summaryrefslogtreecommitdiffstats
path: root/src/3rdparty
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty')
-rw-r--r--src/3rdparty/2geom/2GeomConfig.cmake3
-rw-r--r--src/3rdparty/2geom/2geom.pc.in13
-rw-r--r--src/3rdparty/2geom/AUTHORS.md26
-rw-r--r--src/3rdparty/2geom/CMakeLists.txt156
-rw-r--r--src/3rdparty/2geom/CMakeScripts/Dist.cmake7
-rw-r--r--src/3rdparty/2geom/CMakeScripts/FindCython.cmake37
-rw-r--r--src/3rdparty/2geom/CMakeScripts/FindDoubleConversion.cmake27
-rw-r--r--src/3rdparty/2geom/CMakeScripts/FindPython.cmake14
-rw-r--r--src/3rdparty/2geom/CMakeScripts/UseCython.cmake288
-rw-r--r--src/3rdparty/2geom/COPYING-LGPL-2.1510
-rw-r--r--src/3rdparty/2geom/COPYING-MPL-1.1470
-rw-r--r--src/3rdparty/2geom/Doxyfile2355
-rw-r--r--src/3rdparty/2geom/HACKING.md53
-rw-r--r--src/3rdparty/2geom/LICENSE.md16
-rw-r--r--src/3rdparty/2geom/NEWS.md45
-rw-r--r--src/3rdparty/2geom/README.md123
-rw-r--r--src/3rdparty/2geom/README.win32.md56
-rw-r--r--src/3rdparty/2geom/RELEASING.md21
-rw-r--r--src/3rdparty/2geom/TODO.md85
-rw-r--r--src/3rdparty/2geom/_clang-format53
-rw-r--r--src/3rdparty/2geom/cmake_uninstall.cmake.in23
-rw-r--r--src/3rdparty/2geom/doc/2geom-logo.svg70
-rw-r--r--src/3rdparty/2geom/doc/Makefile6
-rw-r--r--src/3rdparty/2geom/doc/bezier-utils-work.txt34
-rw-r--r--src/3rdparty/2geom/doc/boolops.svg1622
-rw-r--r--src/3rdparty/2geom/doc/degenerate_conic_decomposition.pdfbin0 -> 79341 bytes
-rw-r--r--src/3rdparty/2geom/doc/extradoxygen.css14
-rw-r--r--src/3rdparty/2geom/doc/features.txt28
-rw-r--r--src/3rdparty/2geom/doc/manual.bib55
-rw-r--r--src/3rdparty/2geom/doc/manual.tex734
-rw-r--r--src/3rdparty/2geom/doc/manual2/ack47
-rw-r--r--src/3rdparty/2geom/doc/manual2/concepts128
-rw-r--r--src/3rdparty/2geom/doc/manual2/d2106
-rw-r--r--src/3rdparty/2geom/doc/manual2/geometric primitives65
-rw-r--r--src/3rdparty/2geom/doc/manual2/introduction41
-rw-r--r--src/3rdparty/2geom/doc/manual2/piecewise134
-rw-r--r--src/3rdparty/2geom/doc/manual2/s-basis91
-rw-r--r--src/3rdparty/2geom/doc/media/2geom-logo.pngbin0 -> 15181 bytes
-rw-r--r--src/3rdparty/2geom/doc/media/Rect.svg283
-rw-r--r--src/3rdparty/2geom/doc/media/bezier-curve-evaluation.pngbin0 -> 25116 bytes
-rw-r--r--src/3rdparty/2geom/doc/media/convex.pngbin0 -> 20321 bytes
-rw-r--r--src/3rdparty/2geom/doc/media/convex.svg232
-rw-r--r--src/3rdparty/2geom/doc/media/coords.pngbin0 -> 2365 bytes
-rw-r--r--src/3rdparty/2geom/doc/media/coords.svg142
-rw-r--r--src/3rdparty/2geom/doc/media/ellipse-angular-coordinates.pngbin0 -> 23125 bytes
-rw-r--r--src/3rdparty/2geom/doc/media/ellipse-angular-coordinates.svg249
-rw-r--r--src/3rdparty/2geom/doc/media/elliptical-arc-flags.pngbin0 -> 13944 bytes
-rw-r--r--src/3rdparty/2geom/doc/media/elliptical-arc-flags.svg197
-rw-r--r--src/3rdparty/2geom/doc/media/gear.pngbin0 -> 75841 bytes
-rw-r--r--src/3rdparty/2geom/doc/media/involute.pdfbin0 -> 9087 bytes
-rw-r--r--src/3rdparty/2geom/doc/media/matrix.pngbin0 -> 49751 bytes
-rw-r--r--src/3rdparty/2geom/doc/media/matrix.svg247
-rw-r--r--src/3rdparty/2geom/doc/media/point.pngbin0 -> 6612 bytes
-rw-r--r--src/3rdparty/2geom/doc/media/point.svg156
-rw-r--r--src/3rdparty/2geom/doc/media/rect.pngbin0 -> 19800 bytes
-rw-r--r--src/3rdparty/2geom/doc/media/rotate.pngbin0 -> 40354 bytes
-rw-r--r--src/3rdparty/2geom/doc/media/rotate.svg239
-rw-r--r--src/3rdparty/2geom/doc/media/sbasis.pngbin0 -> 18753 bytes
-rw-r--r--src/3rdparty/2geom/doc/media/sbasis.svg1121
-rw-r--r--src/3rdparty/2geom/doc/media/scale.pngbin0 -> 26639 bytes
-rw-r--r--src/3rdparty/2geom/doc/media/scale.svg243
-rw-r--r--src/3rdparty/2geom/doc/media/translate.pngbin0 -> 45560 bytes
-rw-r--r--src/3rdparty/2geom/doc/media/translate.svg252
-rw-r--r--src/3rdparty/2geom/doc/patchwise.svg131
-rw-r--r--src/3rdparty/2geom/doc/s-pb-thoughts.txt78
-rw-r--r--src/3rdparty/2geom/doc/shapeops.svg653
-rw-r--r--src/3rdparty/2geom/doc/sweep.svg430
-rw-r--r--src/3rdparty/2geom/doc/tutorial.txt291
-rw-r--r--src/3rdparty/2geom/include/2geom/2geom.h75
-rw-r--r--src/3rdparty/2geom/include/2geom/affine.h244
-rw-r--r--src/3rdparty/2geom/include/2geom/angle.h408
-rw-r--r--src/3rdparty/2geom/include/2geom/basic-intersection.h151
-rw-r--r--src/3rdparty/2geom/include/2geom/bezier-curve.h366
-rw-r--r--src/3rdparty/2geom/include/2geom/bezier-to-sbasis.h94
-rw-r--r--src/3rdparty/2geom/include/2geom/bezier-utils.h99
-rw-r--r--src/3rdparty/2geom/include/2geom/bezier.h394
-rw-r--r--src/3rdparty/2geom/include/2geom/cairo-path-sink.h91
-rw-r--r--src/3rdparty/2geom/include/2geom/choose.h147
-rw-r--r--src/3rdparty/2geom/include/2geom/circle.h165
-rw-r--r--src/3rdparty/2geom/include/2geom/concepts.h209
-rw-r--r--src/3rdparty/2geom/include/2geom/conic_section_clipper.h58
-rw-r--r--src/3rdparty/2geom/include/2geom/conic_section_clipper_cr.h64
-rw-r--r--src/3rdparty/2geom/include/2geom/conic_section_clipper_impl.h346
-rw-r--r--src/3rdparty/2geom/include/2geom/conicsec.h537
-rw-r--r--src/3rdparty/2geom/include/2geom/convex-hull.h346
-rw-r--r--src/3rdparty/2geom/include/2geom/coord.h208
-rw-r--r--src/3rdparty/2geom/include/2geom/crossing.h213
-rw-r--r--src/3rdparty/2geom/include/2geom/curve.h375
-rw-r--r--src/3rdparty/2geom/include/2geom/curves.h54
-rw-r--r--src/3rdparty/2geom/include/2geom/d2.h564
-rw-r--r--src/3rdparty/2geom/include/2geom/ellipse.h260
-rw-r--r--src/3rdparty/2geom/include/2geom/elliptical-arc.h344
-rw-r--r--src/3rdparty/2geom/include/2geom/exception.h157
-rw-r--r--src/3rdparty/2geom/include/2geom/forward.h127
-rw-r--r--src/3rdparty/2geom/include/2geom/generic-interval.h374
-rw-r--r--src/3rdparty/2geom/include/2geom/generic-rect.h547
-rw-r--r--src/3rdparty/2geom/include/2geom/geom.h66
-rw-r--r--src/3rdparty/2geom/include/2geom/int-interval.h63
-rw-r--r--src/3rdparty/2geom/include/2geom/int-point.h202
-rw-r--r--src/3rdparty/2geom/include/2geom/int-rect.h75
-rw-r--r--src/3rdparty/2geom/include/2geom/intersection-graph.h259
-rw-r--r--src/3rdparty/2geom/include/2geom/intersection.h147
-rw-r--r--src/3rdparty/2geom/include/2geom/interval.h245
-rw-r--r--src/3rdparty/2geom/include/2geom/intervaltree/interval_tree.h126
-rw-r--r--src/3rdparty/2geom/include/2geom/line.h605
-rw-r--r--src/3rdparty/2geom/include/2geom/linear.h167
-rw-r--r--src/3rdparty/2geom/include/2geom/math-utils.h140
-rw-r--r--src/3rdparty/2geom/include/2geom/nearest-time.h141
-rw-r--r--src/3rdparty/2geom/include/2geom/numeric/fitting-model.h521
-rw-r--r--src/3rdparty/2geom/include/2geom/numeric/fitting-tool.h562
-rw-r--r--src/3rdparty/2geom/include/2geom/numeric/linear_system.h138
-rw-r--r--src/3rdparty/2geom/include/2geom/numeric/matrix.h603
-rw-r--r--src/3rdparty/2geom/include/2geom/numeric/symmetric-matrix-fs-operation.h102
-rw-r--r--src/3rdparty/2geom/include/2geom/numeric/symmetric-matrix-fs-trace.h427
-rw-r--r--src/3rdparty/2geom/include/2geom/numeric/symmetric-matrix-fs.h733
-rw-r--r--src/3rdparty/2geom/include/2geom/numeric/vector.h594
-rw-r--r--src/3rdparty/2geom/include/2geom/ord.h80
-rw-r--r--src/3rdparty/2geom/include/2geom/orphan-code/arc-length.h58
-rw-r--r--src/3rdparty/2geom/include/2geom/orphan-code/chebyshev.h30
-rw-r--r--src/3rdparty/2geom/include/2geom/orphan-code/intersection-by-smashing.h78
-rw-r--r--src/3rdparty/2geom/include/2geom/orphan-code/linear-of.h269
-rw-r--r--src/3rdparty/2geom/include/2geom/orphan-code/linearN.h363
-rw-r--r--src/3rdparty/2geom/include/2geom/orphan-code/redblacktree.h121
-rw-r--r--src/3rdparty/2geom/include/2geom/orphan-code/rtree.h241
-rw-r--r--src/3rdparty/2geom/include/2geom/orphan-code/sbasis-of.h638
-rw-r--r--src/3rdparty/2geom/include/2geom/orphan-code/sbasisN.h1123
-rw-r--r--src/3rdparty/2geom/include/2geom/parallelogram.h83
-rw-r--r--src/3rdparty/2geom/include/2geom/path-intersection.h118
-rw-r--r--src/3rdparty/2geom/include/2geom/path-sink.h253
-rw-r--r--src/3rdparty/2geom/include/2geom/path.h917
-rw-r--r--src/3rdparty/2geom/include/2geom/pathvector.h304
-rw-r--r--src/3rdparty/2geom/include/2geom/piecewise.h945
-rw-r--r--src/3rdparty/2geom/include/2geom/point.h449
-rw-r--r--src/3rdparty/2geom/include/2geom/polynomial.h264
-rw-r--r--src/3rdparty/2geom/include/2geom/ray.h192
-rw-r--r--src/3rdparty/2geom/include/2geom/rect.h263
-rw-r--r--src/3rdparty/2geom/include/2geom/sbasis-2d.h371
-rw-r--r--src/3rdparty/2geom/include/2geom/sbasis-curve.h160
-rw-r--r--src/3rdparty/2geom/include/2geom/sbasis-geometric.h146
-rw-r--r--src/3rdparty/2geom/include/2geom/sbasis-math.h99
-rw-r--r--src/3rdparty/2geom/include/2geom/sbasis-poly.h56
-rw-r--r--src/3rdparty/2geom/include/2geom/sbasis-to-bezier.h87
-rw-r--r--src/3rdparty/2geom/include/2geom/sbasis.h530
-rw-r--r--src/3rdparty/2geom/include/2geom/solver.h88
-rw-r--r--src/3rdparty/2geom/include/2geom/svg-path-parser.h199
-rw-r--r--src/3rdparty/2geom/include/2geom/svg-path-writer.h122
-rw-r--r--src/3rdparty/2geom/include/2geom/sweep-bounds.h62
-rw-r--r--src/3rdparty/2geom/include/2geom/sweeper.h189
-rw-r--r--src/3rdparty/2geom/include/2geom/symbolic/determinant-minor.h175
-rw-r--r--src/3rdparty/2geom/include/2geom/symbolic/implicit.h353
-rw-r--r--src/3rdparty/2geom/include/2geom/symbolic/matrix.h265
-rw-r--r--src/3rdparty/2geom/include/2geom/symbolic/multi-index.h169
-rw-r--r--src/3rdparty/2geom/include/2geom/symbolic/multipoly.h684
-rw-r--r--src/3rdparty/2geom/include/2geom/symbolic/mvpoly-tools.h690
-rw-r--r--src/3rdparty/2geom/include/2geom/symbolic/polynomial.h569
-rw-r--r--src/3rdparty/2geom/include/2geom/symbolic/unity-builder.h102
-rw-r--r--src/3rdparty/2geom/include/2geom/transforms.h370
-rw-r--r--src/3rdparty/2geom/include/2geom/utils.h114
-rw-r--r--src/3rdparty/2geom/include/toys/lpe-framework.h77
-rw-r--r--src/3rdparty/2geom/include/toys/path-cairo.h57
-rw-r--r--src/3rdparty/2geom/include/toys/toy-framework-2.h451
-rw-r--r--src/3rdparty/2geom/makefile.in17
-rw-r--r--src/3rdparty/2geom/mingwenv.bat18
-rwxr-xr-xsrc/3rdparty/2geom/src/2geom/CMakeLists.txt206
-rw-r--r--src/3rdparty/2geom/src/2geom/affine.cpp522
-rw-r--r--src/3rdparty/2geom/src/2geom/basic-intersection.cpp493
-rw-r--r--src/3rdparty/2geom/src/2geom/bezier-clipping.cpp1174
-rw-r--r--src/3rdparty/2geom/src/2geom/bezier-curve.cpp695
-rw-r--r--src/3rdparty/2geom/src/2geom/bezier-utils.cpp997
-rw-r--r--src/3rdparty/2geom/src/2geom/bezier.cpp415
-rw-r--r--src/3rdparty/2geom/src/2geom/cairo-path-sink.cpp127
-rw-r--r--src/3rdparty/2geom/src/2geom/circle.cpp337
-rw-r--r--src/3rdparty/2geom/src/2geom/concepts.cpp69
-rw-r--r--src/3rdparty/2geom/src/2geom/conic_section_clipper_impl.cpp574
-rw-r--r--src/3rdparty/2geom/src/2geom/conicsec.cpp1640
-rw-r--r--src/3rdparty/2geom/src/2geom/convex-hull.cpp746
-rw-r--r--src/3rdparty/2geom/src/2geom/coord.cpp123
-rw-r--r--src/3rdparty/2geom/src/2geom/crossing.cpp233
-rw-r--r--src/3rdparty/2geom/src/2geom/curve.cpp235
-rw-r--r--src/3rdparty/2geom/src/2geom/d2-sbasis.cpp364
-rw-r--r--src/3rdparty/2geom/src/2geom/doxygen.cpp301
-rw-r--r--src/3rdparty/2geom/src/2geom/ellipse.cpp790
-rw-r--r--src/3rdparty/2geom/src/2geom/elliptical-arc-from-sbasis.cpp341
-rw-r--r--src/3rdparty/2geom/src/2geom/elliptical-arc.cpp1045
-rw-r--r--src/3rdparty/2geom/src/2geom/geom.cpp396
-rw-r--r--src/3rdparty/2geom/src/2geom/intersection-graph.cpp535
-rw-r--r--src/3rdparty/2geom/src/2geom/intervaltree/interval_tree.cc799
-rw-r--r--src/3rdparty/2geom/src/2geom/intervaltree/test2.cc74
-rw-r--r--src/3rdparty/2geom/src/2geom/line.cpp610
-rw-r--r--src/3rdparty/2geom/src/2geom/nearest-time.cpp322
-rw-r--r--src/3rdparty/2geom/src/2geom/numeric/matrix.cpp154
-rw-r--r--src/3rdparty/2geom/src/2geom/orphan-code/arc-length.cpp292
-rw-r--r--src/3rdparty/2geom/src/2geom/orphan-code/chebyshev.cpp126
-rw-r--r--src/3rdparty/2geom/src/2geom/orphan-code/intersection-by-bezier-clipping.cpp560
-rw-r--r--src/3rdparty/2geom/src/2geom/orphan-code/intersection-by-smashing.cpp349
-rw-r--r--src/3rdparty/2geom/src/2geom/orphan-code/nearestpoint.cpp405
-rw-r--r--src/3rdparty/2geom/src/2geom/orphan-code/redblack-toy.cpp327
-rw-r--r--src/3rdparty/2geom/src/2geom/orphan-code/redblacktree.cpp575
-rw-r--r--src/3rdparty/2geom/src/2geom/orphan-code/rtree.cpp1350
-rw-r--r--src/3rdparty/2geom/src/2geom/parallelogram.cpp136
-rw-r--r--src/3rdparty/2geom/src/2geom/parting-point.cpp280
-rw-r--r--src/3rdparty/2geom/src/2geom/path-extrema.cpp156
-rw-r--r--src/3rdparty/2geom/src/2geom/path-intersection.cpp728
-rw-r--r--src/3rdparty/2geom/src/2geom/path-sink.cpp104
-rw-r--r--src/3rdparty/2geom/src/2geom/path.cpp1161
-rw-r--r--src/3rdparty/2geom/src/2geom/pathvector.cpp336
-rw-r--r--src/3rdparty/2geom/src/2geom/piecewise.cpp266
-rw-r--r--src/3rdparty/2geom/src/2geom/planar-graph.h1252
-rw-r--r--src/3rdparty/2geom/src/2geom/point.cpp274
-rw-r--r--src/3rdparty/2geom/src/2geom/polynomial.cpp337
-rw-r--r--src/3rdparty/2geom/src/2geom/rect.cpp187
-rw-r--r--src/3rdparty/2geom/src/2geom/recursive-bezier-intersection.cpp476
-rw-r--r--src/3rdparty/2geom/src/2geom/sbasis-2d.cpp202
-rw-r--r--src/3rdparty/2geom/src/2geom/sbasis-geometric.cpp790
-rw-r--r--src/3rdparty/2geom/src/2geom/sbasis-math.cpp379
-rw-r--r--src/3rdparty/2geom/src/2geom/sbasis-poly.cpp59
-rw-r--r--src/3rdparty/2geom/src/2geom/sbasis-roots.cpp656
-rw-r--r--src/3rdparty/2geom/src/2geom/sbasis-to-bezier.cpp584
-rw-r--r--src/3rdparty/2geom/src/2geom/sbasis.cpp681
-rw-r--r--src/3rdparty/2geom/src/2geom/self-intersect.cpp313
-rw-r--r--src/3rdparty/2geom/src/2geom/solve-bezier-one-d.cpp243
-rw-r--r--src/3rdparty/2geom/src/2geom/solve-bezier-parametric.cpp189
-rw-r--r--src/3rdparty/2geom/src/2geom/solve-bezier.cpp304
-rw-r--r--src/3rdparty/2geom/src/2geom/svg-path-parser.cpp1615
-rw-r--r--src/3rdparty/2geom/src/2geom/svg-path-parser.rl487
-rw-r--r--src/3rdparty/2geom/src/2geom/svg-path-writer.cpp296
-rw-r--r--src/3rdparty/2geom/src/2geom/sweep-bounds.cpp154
-rw-r--r--src/3rdparty/2geom/src/2geom/transforms.cpp205
-rw-r--r--src/3rdparty/2geom/src/2geom/utils.cpp86
-rw-r--r--src/3rdparty/2geom/src/CMakeLists.txt10
-rw-r--r--src/3rdparty/2geom/src/cython/CMakeLists.txt131
-rw-r--r--src/3rdparty/2geom/src/cython/README.md29
-rw-r--r--src/3rdparty/2geom/src/cython/_common_decl.pxd14
-rw-r--r--src/3rdparty/2geom/src/cython/_common_decl.pyx12
-rw-r--r--src/3rdparty/2geom/src/cython/_cy_affine.pxd247
-rw-r--r--src/3rdparty/2geom/src/cython/_cy_affine.pyx736
-rw-r--r--src/3rdparty/2geom/src/cython/_cy_conicsection.pxd50
-rw-r--r--src/3rdparty/2geom/src/cython/_cy_conicsection.pyx183
-rw-r--r--src/3rdparty/2geom/src/cython/_cy_curves.pxd421
-rw-r--r--src/3rdparty/2geom/src/cython/_cy_curves.pyx1945
-rw-r--r--src/3rdparty/2geom/src/cython/_cy_path.pxd124
-rw-r--r--src/3rdparty/2geom/src/cython/_cy_path.pyx457
-rw-r--r--src/3rdparty/2geom/src/cython/_cy_primitives.pxd237
-rw-r--r--src/3rdparty/2geom/src/cython/_cy_primitives.pyx846
-rw-r--r--src/3rdparty/2geom/src/cython/_cy_rectangle.pxd442
-rw-r--r--src/3rdparty/2geom/src/cython/_cy_rectangle.pyx2202
-rw-r--r--src/3rdparty/2geom/src/cython/cy2geom.pyx71
-rw-r--r--src/3rdparty/2geom/src/cython/report.md237
-rw-r--r--src/3rdparty/2geom/src/cython/test-affine.py249
-rw-r--r--src/3rdparty/2geom/src/cython/test-conicsection.py137
-rw-r--r--src/3rdparty/2geom/src/cython/test-curves.py458
-rw-r--r--src/3rdparty/2geom/src/cython/test-path.py218
-rw-r--r--src/3rdparty/2geom/src/cython/test-primitives.py288
-rw-r--r--src/3rdparty/2geom/src/cython/test-rectangle.py601
-rw-r--r--src/3rdparty/2geom/src/cython/utils.py52
-rw-r--r--src/3rdparty/2geom/src/cython/wrapped-pyobject.h237
-rw-r--r--src/3rdparty/2geom/src/cython/wrapper.py360
-rw-r--r--src/3rdparty/2geom/src/performance-tests/CMakeLists.txt27
-rw-r--r--src/3rdparty/2geom/src/performance-tests/bendpath-test.cpp128
-rw-r--r--src/3rdparty/2geom/src/performance-tests/bezier-utils-test.cpp133
-rw-r--r--src/3rdparty/2geom/src/performance-tests/boolops-performance-test.cpp101
-rw-r--r--src/3rdparty/2geom/src/performance-tests/example-performance-test.cpp217
-rw-r--r--src/3rdparty/2geom/src/performance-tests/parse-svg-test.cpp88
-rw-r--r--src/3rdparty/2geom/src/performance-tests/path-operations-test.cpp100
-rw-r--r--src/3rdparty/2geom/src/py2geom/CMakeLists.txt118
-rw-r--r--src/3rdparty/2geom/src/py2geom/__init__.py26
-rw-r--r--src/3rdparty/2geom/src/py2geom/bezier.cpp89
-rw-r--r--src/3rdparty/2geom/src/py2geom/cairo-helpers.cpp164
-rw-r--r--src/3rdparty/2geom/src/py2geom/cairo-helpers.h27
-rw-r--r--src/3rdparty/2geom/src/py2geom/circle.cpp72
-rw-r--r--src/3rdparty/2geom/src/py2geom/conic.cpp176
-rw-r--r--src/3rdparty/2geom/src/py2geom/convexcover.cpp93
-rw-r--r--src/3rdparty/2geom/src/py2geom/crossing.cpp69
-rw-r--r--src/3rdparty/2geom/src/py2geom/d2.cpp99
-rw-r--r--src/3rdparty/2geom/src/py2geom/ellipse.cpp88
-rw-r--r--src/3rdparty/2geom/src/py2geom/etc.cpp66
-rw-r--r--src/3rdparty/2geom/src/py2geom/helpers.h59
-rw-r--r--src/3rdparty/2geom/src/py2geom/interval.cpp159
-rw-r--r--src/3rdparty/2geom/src/py2geom/line.cpp96
-rw-r--r--src/3rdparty/2geom/src/py2geom/linear.cpp110
-rw-r--r--src/3rdparty/2geom/src/py2geom/parser.cpp85
-rw-r--r--src/3rdparty/2geom/src/py2geom/path.cpp265
-rw-r--r--src/3rdparty/2geom/src/py2geom/point.cpp146
-rw-r--r--src/3rdparty/2geom/src/py2geom/pw.cpp228
-rw-r--r--src/3rdparty/2geom/src/py2geom/py2geom.cpp85
-rw-r--r--src/3rdparty/2geom/src/py2geom/py2geom.h71
-rw-r--r--src/3rdparty/2geom/src/py2geom/ray.cpp99
-rw-r--r--src/3rdparty/2geom/src/py2geom/rect.cpp125
-rw-r--r--src/3rdparty/2geom/src/py2geom/sbasis.cpp173
-rw-r--r--src/3rdparty/2geom/src/py2geom/transforms.cpp107
-rw-r--r--src/3rdparty/2geom/src/python/cy2geom_example.py10
-rw-r--r--src/3rdparty/2geom/src/python/elip.py155
-rw-r--r--src/3rdparty/2geom/src/python/exact-arc-length-quad-bez.py16
-rw-r--r--src/3rdparty/2geom/src/python/test_py2geom.py41
-rw-r--r--src/3rdparty/2geom/src/toys/2dsb2d.cpp128
-rw-r--r--src/3rdparty/2geom/src/toys/CMakeLists.txt172
-rw-r--r--src/3rdparty/2geom/src/toys/aa.cpp520
-rw-r--r--src/3rdparty/2geom/src/toys/arc-bez.cpp129
-rw-r--r--src/3rdparty/2geom/src/toys/arc-length-param.cpp101
-rw-r--r--src/3rdparty/2geom/src/toys/auto-cross.cpp321
-rw-r--r--src/3rdparty/2geom/src/toys/boolops-toy.cpp242
-rw-r--r--src/3rdparty/2geom/src/toys/bound-path.cpp289
-rw-r--r--src/3rdparty/2geom/src/toys/bounds-test.cpp171
-rw-r--r--src/3rdparty/2geom/src/toys/box3d.cpp153
-rw-r--r--src/3rdparty/2geom/src/toys/center-warp.cpp113
-rw-r--r--src/3rdparty/2geom/src/toys/circle-fitting.cpp164
-rw-r--r--src/3rdparty/2geom/src/toys/circle-intersect.cpp70
-rw-r--r--src/3rdparty/2geom/src/toys/circle-line-intersect.cpp67
-rw-r--r--src/3rdparty/2geom/src/toys/circle-tangent-fitting.cpp224
-rw-r--r--src/3rdparty/2geom/src/toys/collinear-normal.cpp204
-rw-r--r--src/3rdparty/2geom/src/toys/conic-3.cpp96
-rw-r--r--src/3rdparty/2geom/src/toys/conic-4.cpp129
-rw-r--r--src/3rdparty/2geom/src/toys/conic-5.cpp356
-rw-r--r--src/3rdparty/2geom/src/toys/conic-6.cpp304
-rw-r--r--src/3rdparty/2geom/src/toys/conic-section-toy.cpp813
-rw-r--r--src/3rdparty/2geom/src/toys/convole.cpp352
-rw-r--r--src/3rdparty/2geom/src/toys/curvature-curve.cpp142
-rw-r--r--src/3rdparty/2geom/src/toys/curvature-test.cpp110
-rw-r--r--src/3rdparty/2geom/src/toys/curve-curve-distance.cpp1000
-rw-r--r--src/3rdparty/2geom/src/toys/curve-curve-nearest-time.cpp609
-rw-r--r--src/3rdparty/2geom/src/toys/curve-intersection-by-bezier-clipping.cpp127
-rw-r--r--src/3rdparty/2geom/src/toys/curve-intersection-by-implicitization.cpp300
-rw-r--r--src/3rdparty/2geom/src/toys/cylinder3d.cpp253
-rw-r--r--src/3rdparty/2geom/src/toys/d2sbasis-fitting-with-np.cpp147
-rw-r--r--src/3rdparty/2geom/src/toys/d2sbasis-fitting.cpp120
-rw-r--r--src/3rdparty/2geom/src/toys/data/london-locations.csv298
-rw-r--r--src/3rdparty/2geom/src/toys/data/london.txt86
-rw-r--r--src/3rdparty/2geom/src/toys/data/nsw-centre.txt56
-rw-r--r--src/3rdparty/2geom/src/toys/data/nsw-locations.csv805
-rw-r--r--src/3rdparty/2geom/src/toys/data/nsw-london.zipbin0 -> 21209 bytes
-rw-r--r--src/3rdparty/2geom/src/toys/data/nsw.txt86
-rw-r--r--src/3rdparty/2geom/src/toys/data/parser.cpp47
-rw-r--r--src/3rdparty/2geom/src/toys/differential-constraint.cpp132
-rw-r--r--src/3rdparty/2geom/src/toys/draw-toy.cpp116
-rw-r--r--src/3rdparty/2geom/src/toys/ellipse-area-minimizer.cpp352
-rw-r--r--src/3rdparty/2geom/src/toys/ellipse-bezier-intersect-toy.cpp74
-rw-r--r--src/3rdparty/2geom/src/toys/ellipse-fitting.cpp191
-rw-r--r--src/3rdparty/2geom/src/toys/ellipse-intersect-toy.cpp158
-rw-r--r--src/3rdparty/2geom/src/toys/ellipse-line-intersect-toy.cpp67
-rw-r--r--src/3rdparty/2geom/src/toys/elliptiarc-3point-center-fitting.cpp266
-rw-r--r--src/3rdparty/2geom/src/toys/elliptiarc-curve-fitting.cpp127
-rw-r--r--src/3rdparty/2geom/src/toys/elliptical-arc-toy.cpp903
-rw-r--r--src/3rdparty/2geom/src/toys/evolute.cpp93
-rw-r--r--src/3rdparty/2geom/src/toys/filet-minion.cpp159
-rw-r--r--src/3rdparty/2geom/src/toys/find-derivative.cpp500
-rw-r--r--src/3rdparty/2geom/src/toys/gear.cpp317
-rw-r--r--src/3rdparty/2geom/src/toys/hatches.cpp386
-rw-r--r--src/3rdparty/2geom/src/toys/implicit-toy.cpp510
-rw-r--r--src/3rdparty/2geom/src/toys/ineaa.cpp655
-rw-r--r--src/3rdparty/2geom/src/toys/inner-product-clip.cpp174
-rw-r--r--src/3rdparty/2geom/src/toys/intersect-data.cpp436
-rw-r--r--src/3rdparty/2geom/src/toys/inverse-test.cpp174
-rw-r--r--src/3rdparty/2geom/src/toys/kinematic_templates.cpp365
-rw-r--r--src/3rdparty/2geom/src/toys/levelsets-test.cpp155
-rw-r--r--src/3rdparty/2geom/src/toys/line-toy.cpp916
-rw-r--r--src/3rdparty/2geom/src/toys/load-svgd.cpp76
-rw-r--r--src/3rdparty/2geom/src/toys/load-svgd.py68
-rw-r--r--src/3rdparty/2geom/src/toys/lpe-framework.cpp128
-rw-r--r--src/3rdparty/2geom/src/toys/lpe-test.cpp93
-rw-r--r--src/3rdparty/2geom/src/toys/match-curve.cpp162
-rw-r--r--src/3rdparty/2geom/src/toys/mesh-grad.cpp134
-rw-r--r--src/3rdparty/2geom/src/toys/metro.cpp922
-rw-r--r--src/3rdparty/2geom/src/toys/minsb2d-solver.cpp376
-rw-r--r--src/3rdparty/2geom/src/toys/nasty.svg74
-rw-r--r--src/3rdparty/2geom/src/toys/nearest-times.cpp258
-rw-r--r--src/3rdparty/2geom/src/toys/nearest-times2.cpp313
-rw-r--r--src/3rdparty/2geom/src/toys/normal-bundle.cpp230
-rw-r--r--src/3rdparty/2geom/src/toys/offset-toy.cpp156
-rw-r--r--src/3rdparty/2geom/src/toys/pair-intersect.cpp147
-rw-r--r--src/3rdparty/2geom/src/toys/paptest.cpp107
-rw-r--r--src/3rdparty/2geom/src/toys/parametrics.cpp229
-rw-r--r--src/3rdparty/2geom/src/toys/parser.cpp108
-rw-r--r--src/3rdparty/2geom/src/toys/path-along-path.cpp112
-rw-r--r--src/3rdparty/2geom/src/toys/path-cairo.cpp342
-rw-r--r--src/3rdparty/2geom/src/toys/path-effects.cpp140
-rw-r--r--src/3rdparty/2geom/src/toys/path-toy.py41
-rw-r--r--src/3rdparty/2geom/src/toys/pencil-2.cpp1133
-rw-r--r--src/3rdparty/2geom/src/toys/pencil.cpp374
-rw-r--r--src/3rdparty/2geom/src/toys/plane3d.cpp130
-rw-r--r--src/3rdparty/2geom/src/toys/plane3d.py78
-rw-r--r--src/3rdparty/2geom/src/toys/point-curve-nearest-time.cpp397
-rw-r--r--src/3rdparty/2geom/src/toys/portion-test.cpp105
-rw-r--r--src/3rdparty/2geom/src/toys/precise-flat.cpp86
-rw-r--r--src/3rdparty/2geom/src/toys/pw-compose-test.cpp98
-rw-r--r--src/3rdparty/2geom/src/toys/pw-funcs.cpp100
-rw-r--r--src/3rdparty/2geom/src/toys/pw-toy.cpp117
-rw-r--r--src/3rdparty/2geom/src/toys/pw-toy.py180
-rw-r--r--src/3rdparty/2geom/src/toys/pwsbhandle.cpp77
-rw-r--r--src/3rdparty/2geom/src/toys/py2geom_glue.py42
-rw-r--r--src/3rdparty/2geom/src/toys/ray_test.py20
-rw-r--r--src/3rdparty/2geom/src/toys/rdm-area.cpp479
-rw-r--r--src/3rdparty/2geom/src/toys/rect-toy.cpp395
-rw-r--r--src/3rdparty/2geom/src/toys/rect_01.cpp98
-rw-r--r--src/3rdparty/2geom/src/toys/rect_02.cpp81
-rw-r--r--src/3rdparty/2geom/src/toys/rect_03.cpp78
-rw-r--r--src/3rdparty/2geom/src/toys/root-finder-comparer.cpp247
-rw-r--r--src/3rdparty/2geom/src/toys/rtree-toy.cpp573
-rw-r--r--src/3rdparty/2geom/src/toys/sanitize.cpp204
-rw-r--r--src/3rdparty/2geom/src/toys/sb-math-test.cpp164
-rw-r--r--src/3rdparty/2geom/src/toys/sb-of-interval.cpp187
-rw-r--r--src/3rdparty/2geom/src/toys/sb-of-sb.cpp478
-rw-r--r--src/3rdparty/2geom/src/toys/sb-to-bez.cpp404
-rw-r--r--src/3rdparty/2geom/src/toys/sb-zeros.cpp63
-rw-r--r--src/3rdparty/2geom/src/toys/sb1d.cpp125
-rw-r--r--src/3rdparty/2geom/src/toys/sb2d-solver.cpp282
-rw-r--r--src/3rdparty/2geom/src/toys/sb2d.cpp83
-rw-r--r--src/3rdparty/2geom/src/toys/sbasis-fitting.cpp214
-rw-r--r--src/3rdparty/2geom/src/toys/sbasisdim.cpp262
-rw-r--r--src/3rdparty/2geom/src/toys/scribble.cpp366
-rw-r--r--src/3rdparty/2geom/src/toys/self-intersect.cpp67
-rw-r--r--src/3rdparty/2geom/src/toys/sketch-fitter.cpp923
-rw-r--r--src/3rdparty/2geom/src/toys/smash-intersector.cpp583
-rw-r--r--src/3rdparty/2geom/src/toys/squiggles.cpp216
-rw-r--r--src/3rdparty/2geom/src/toys/star-gap.hand1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/2rect.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/4rect.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/ant.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/arcs.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/banana.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/cat.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/circle.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/degenerate-line.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/diederik.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/diederik1.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/double-move.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/ellipses.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/emptyset.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/fan.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/lotsarect.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/monkey.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/nasty.svgd3
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/onlyarcs.svgd10
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/ptitle.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/rect.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/sanitize-examples.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/scribble.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/spiral.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/star.svg60
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/star.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/tadpole.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/touchboxes.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/toy.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/triarrange.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/tricky.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/svgd/winding.svgd1
-rw-r--r--src/3rdparty/2geom/src/toys/sweep.cpp89
-rw-r--r--src/3rdparty/2geom/src/toys/sweeper-toy.cpp170
-rw-r--r--src/3rdparty/2geom/src/toys/sweeper.cpp1135
-rw-r--r--src/3rdparty/2geom/src/toys/topology.cpp668
-rw-r--r--src/3rdparty/2geom/src/toys/toy-framework-2.cpp972
-rw-r--r--src/3rdparty/2geom/src/toys/toy-template.cpp35
-rw-r--r--src/3rdparty/2geom/src/toys/toyframework.py435
-rw-r--r--src/3rdparty/2geom/src/toys/uncross.cpp500
-rw-r--r--src/3rdparty/2geom/src/toys/winding-test.cpp107
-rw-r--r--src/3rdparty/2geom/src/toys/worms.cpp138
-rw-r--r--src/3rdparty/2geom/tests/CMakeLists.txt56
-rw-r--r--src/3rdparty/2geom/tests/WontSnapToSomeCurveSegments.svg129
-rw-r--r--src/3rdparty/2geom/tests/affine-test.cpp429
-rw-r--r--src/3rdparty/2geom/tests/angle-test.cpp209
-rw-r--r--src/3rdparty/2geom/tests/bezier-sbasis-transforms.py72
-rw-r--r--src/3rdparty/2geom/tests/bezier-test.cpp680
-rw-r--r--src/3rdparty/2geom/tests/bezier-utils-test.cpp333
-rw-r--r--src/3rdparty/2geom/tests/choose-test.cpp79
-rw-r--r--src/3rdparty/2geom/tests/circle-test.cpp141
-rw-r--r--src/3rdparty/2geom/tests/convex-hull-test.cpp335
-rw-r--r--src/3rdparty/2geom/tests/coord-test.cpp90
-rw-r--r--src/3rdparty/2geom/tests/dependent-project/CMakeLists.txt27
-rw-r--r--src/3rdparty/2geom/tests/dependent-project/main.cpp12
-rw-r--r--src/3rdparty/2geom/tests/dependent-project/my_lib.cpp6
-rw-r--r--src/3rdparty/2geom/tests/dependent-project/my_lib.h4
-rw-r--r--src/3rdparty/2geom/tests/ellipse-test.cpp410
-rw-r--r--src/3rdparty/2geom/tests/elliptical-arc-test.cpp275
-rw-r--r--src/3rdparty/2geom/tests/implicitization-test.cpp130
-rw-r--r--src/3rdparty/2geom/tests/intersection-graph-test.cpp266
-rw-r--r--src/3rdparty/2geom/tests/interval-test.cpp54
-rw-r--r--src/3rdparty/2geom/tests/linalg-test.cpp502
-rw-r--r--src/3rdparty/2geom/tests/line-test.cpp185
-rw-r--r--src/3rdparty/2geom/tests/mersennetwister.h427
-rw-r--r--src/3rdparty/2geom/tests/nl-vector-test.cpp333
-rw-r--r--src/3rdparty/2geom/tests/parallelogram-test.cpp161
-rw-r--r--src/3rdparty/2geom/tests/parser-test.py94
-rw-r--r--src/3rdparty/2geom/tests/path-test.cpp991
-rw-r--r--src/3rdparty/2geom/tests/pick.h172
-rw-r--r--src/3rdparty/2geom/tests/planar-graph-test.cpp457
-rw-r--r--src/3rdparty/2geom/tests/point-test.cpp119
-rw-r--r--src/3rdparty/2geom/tests/polybez-cases.svg168
-rw-r--r--src/3rdparty/2geom/tests/polynomial-test.cpp126
-rw-r--r--src/3rdparty/2geom/tests/rect-test.cpp368
-rw-r--r--src/3rdparty/2geom/tests/root-find-test.cpp156
-rw-r--r--src/3rdparty/2geom/tests/rtree-performance-test.cpp361
-rw-r--r--src/3rdparty/2geom/tests/rtree-test.cpp158
-rw-r--r--src/3rdparty/2geom/tests/sbasis-test.cpp268
-rw-r--r--src/3rdparty/2geom/tests/sbasis-text-test.cpp225
-rw-r--r--src/3rdparty/2geom/tests/self-intersections-test.cpp219
-rw-r--r--src/3rdparty/2geom/tests/test_pwsb.py67
-rw-r--r--src/3rdparty/2geom/tests/test_py2geom.py75
-rw-r--r--src/3rdparty/2geom/tests/testing.h186
-rw-r--r--src/3rdparty/2geom/tests/timing-test.cpp270
-rw-r--r--src/3rdparty/2geom/tests/utest.h134
-rw-r--r--src/3rdparty/2geom/tools/lib2geom_gdb.py107
-rw-r--r--src/3rdparty/2geom/toy.pc.in13
-rw-r--r--src/3rdparty/CMakeLists.txt34
-rw-r--r--src/3rdparty/adaptagrams/CMakeLists.txt3
-rw-r--r--src/3rdparty/adaptagrams/libavoid/CMakeLists.txt58
-rw-r--r--src/3rdparty/adaptagrams/libavoid/Doxyfile2423
-rw-r--r--src/3rdparty/adaptagrams/libavoid/LICENSE.LGPL460
-rw-r--r--src/3rdparty/adaptagrams/libavoid/Makefile.am91
-rw-r--r--src/3rdparty/adaptagrams/libavoid/README35
-rw-r--r--src/3rdparty/adaptagrams/libavoid/actioninfo.cpp187
-rw-r--r--src/3rdparty/adaptagrams/libavoid/actioninfo.h88
-rw-r--r--src/3rdparty/adaptagrams/libavoid/assertions.h60
-rw-r--r--src/3rdparty/adaptagrams/libavoid/connectionpin.cpp476
-rw-r--r--src/3rdparty/adaptagrams/libavoid/connectionpin.h303
-rw-r--r--src/3rdparty/adaptagrams/libavoid/connector.cpp2487
-rw-r--r--src/3rdparty/adaptagrams/libavoid/connector.h547
-rw-r--r--src/3rdparty/adaptagrams/libavoid/connend.cpp435
-rw-r--r--src/3rdparty/adaptagrams/libavoid/connend.h267
-rw-r--r--src/3rdparty/adaptagrams/libavoid/debug.h100
-rw-r--r--src/3rdparty/adaptagrams/libavoid/debughandler.h138
-rw-r--r--src/3rdparty/adaptagrams/libavoid/dllexport.h39
-rw-r--r--src/3rdparty/adaptagrams/libavoid/doc/description.doc73
-rw-r--r--src/3rdparty/adaptagrams/libavoid/doc/example.doc122
-rw-r--r--src/3rdparty/adaptagrams/libavoid/doc/header.html19
-rw-r--r--src/3rdparty/adaptagrams/libavoid/geometry.cpp641
-rw-r--r--src/3rdparty/adaptagrams/libavoid/geometry.h129
-rw-r--r--src/3rdparty/adaptagrams/libavoid/geomtypes.cpp761
-rw-r--r--src/3rdparty/adaptagrams/libavoid/geomtypes.h381
-rw-r--r--src/3rdparty/adaptagrams/libavoid/graph.cpp785
-rw-r--r--src/3rdparty/adaptagrams/libavoid/graph.h135
-rw-r--r--src/3rdparty/adaptagrams/libavoid/hyperedge.cpp388
-rw-r--r--src/3rdparty/adaptagrams/libavoid/hyperedge.h223
-rw-r--r--src/3rdparty/adaptagrams/libavoid/hyperedgeimprover.cpp1232
-rw-r--r--src/3rdparty/adaptagrams/libavoid/hyperedgeimprover.h159
-rw-r--r--src/3rdparty/adaptagrams/libavoid/hyperedgetree.cpp821
-rw-r--r--src/3rdparty/adaptagrams/libavoid/hyperedgetree.h143
-rw-r--r--src/3rdparty/adaptagrams/libavoid/junction.cpp233
-rw-r--r--src/3rdparty/adaptagrams/libavoid/junction.h197
-rw-r--r--src/3rdparty/adaptagrams/libavoid/libavoid.h55
-rw-r--r--src/3rdparty/adaptagrams/libavoid/libavoid.pc.in12
-rwxr-xr-xsrc/3rdparty/adaptagrams/libavoid/libavoid.sln196
-rwxr-xr-xsrc/3rdparty/adaptagrams/libavoid/libavoid.vcxproj198
-rw-r--r--src/3rdparty/adaptagrams/libavoid/makepath.cpp1554
-rw-r--r--src/3rdparty/adaptagrams/libavoid/makepath.h52
-rw-r--r--src/3rdparty/adaptagrams/libavoid/mtst.cpp1094
-rw-r--r--src/3rdparty/adaptagrams/libavoid/mtst.h134
-rw-r--r--src/3rdparty/adaptagrams/libavoid/obstacle.cpp355
-rw-r--r--src/3rdparty/adaptagrams/libavoid/obstacle.h150
-rw-r--r--src/3rdparty/adaptagrams/libavoid/orthogonal.cpp3259
-rw-r--r--src/3rdparty/adaptagrams/libavoid/orthogonal.h39
-rw-r--r--src/3rdparty/adaptagrams/libavoid/router.cpp3131
-rw-r--r--src/3rdparty/adaptagrams/libavoid/router.h888
-rw-r--r--src/3rdparty/adaptagrams/libavoid/scanline.cpp562
-rw-r--r--src/3rdparty/adaptagrams/libavoid/scanline.h136
-rw-r--r--src/3rdparty/adaptagrams/libavoid/shape.cpp280
-rw-r--r--src/3rdparty/adaptagrams/libavoid/shape.h165
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/2junctions.cpp108
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/Makefile.am217
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/buildOrthogonalChannelInfo1.cpp65
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/checkpointNudging1.cpp2592
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/checkpointNudging2.cpp2606
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/checkpointNudging3.cpp5242
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/checkpoints01.cpp62
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/checkpoints02.cpp105
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/checkpoints03.cpp96
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/complex.cpp107
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/connectionpin01.cpp68
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/connectionpin02.cpp113
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/connectionpin03.cpp328
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/connendmove.cpp85
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/corneroverlap01.cpp154
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/endlessLoop01.cpp142
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/example.cpp81
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/finalSegmentNudging1.cpp5227
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/finalSegmentNudging2.cpp397
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/finalSegmentNudging3.cpp2658
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/forwardFlowingConnectors01.cpp380
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/freeFloatingDirection01.cpp3321
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/hola01.cpp1006
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/hyperedge01.cpp285
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/hyperedge02.cpp99
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/hyperedgeLoop1.cpp87
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/hyperedgeRerouting01.cpp150
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge01.cpp109
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge02.cpp90
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge03.cpp90
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge04.cpp113
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge05.cpp154
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge06.cpp92
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/infinity.cpp26
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/inline.cpp73
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/inlineOverlap09.cpp401
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/inlineOverlap10.cpp93
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/inlineOverlap11.cpp187
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/inlineShapes.cpp97
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap01.cpp25
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap02.cpp62
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap03.cpp55
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap04.cpp62
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap05.cpp69
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap06.cpp62
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap07.cpp75
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap08.cpp120
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/junction01.cpp55
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/junction02.cpp55
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/junction03.cpp55
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/junction04.cpp100
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/latesetup.cpp94
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash1.cpp1884
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash2.cpp1884
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash3.cpp1884
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash4.cpp1884
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash5.cpp1884
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash6.cpp1884
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash7.cpp1884
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash8.cpp1884
-rwxr-xr-xsrc/3rdparty/adaptagrams/libavoid/tests/msctests/2junctions.vcxproj152
-rwxr-xr-xsrc/3rdparty/adaptagrams/libavoid/tests/msctests/buildOrthogonalChannelInfo1.vcxproj152
-rwxr-xr-xsrc/3rdparty/adaptagrams/libavoid/tests/msctests/checkpointNudging1.vcxproj152
-rwxr-xr-xsrc/3rdparty/adaptagrams/libavoid/tests/msctests/checkpointNudging2.vcxproj152
-rwxr-xr-xsrc/3rdparty/adaptagrams/libavoid/tests/msctests/checkpoints01.vcxproj152
-rwxr-xr-xsrc/3rdparty/adaptagrams/libavoid/tests/msctests/connectionpin01.vcxproj152
-rwxr-xr-xsrc/3rdparty/adaptagrams/libavoid/tests/msctests/connectionpin02.vcxproj152
-rwxr-xr-xsrc/3rdparty/adaptagrams/libavoid/tests/msctests/connectionpin03.vcxproj152
-rwxr-xr-xsrc/3rdparty/adaptagrams/libavoid/tests/msctests/connendmove.vcxproj152
-rwxr-xr-xsrc/3rdparty/adaptagrams/libavoid/tests/msctests/corneroverlap01.vcxproj152
-rwxr-xr-xsrc/3rdparty/adaptagrams/libavoid/tests/msctests/example.vcxproj152
-rwxr-xr-xsrc/3rdparty/adaptagrams/libavoid/tests/msctests/finalSegmentNudging1.vcxproj152
-rwxr-xr-xsrc/3rdparty/adaptagrams/libavoid/tests/msctests/finalSegmentNudging2.vcxproj152
-rwxr-xr-xsrc/3rdparty/adaptagrams/libavoid/tests/msctests/finalSegmentNudging3.vcxproj152
-rwxr-xr-xsrc/3rdparty/adaptagrams/libavoid/tests/msctests/freeFloatingDirection01.vcxproj152
-rwxr-xr-xsrc/3rdparty/adaptagrams/libavoid/tests/msctests/junction01.vcxproj152
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/multiconnact.cpp75
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/node1.cpp68
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/nudgeCrossing01.cpp2665
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/nudgeintobug.cpp40
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/nudgeold.cpp80
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/nudgingSkipsCheckpoint01.cpp1507
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/nudgingSkipsCheckpoint02.cpp3054
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/orderassertion.cpp1720
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/orthordering01.cpp92
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/orthordering02.cpp92
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/output/README.txt1
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/overlappingRects.cpp2327
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/penaltyRerouting01.cpp369
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/performance01.cpp7665
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/reallyslowrouting.cpp7099
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/removeJunctions01.cpp103
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/restrictedNudging.cpp68
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/slowrouting.cpp1459
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/tjunct.cpp48
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/treeRootCrash01.cpp140
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/treeRootCrash02.cpp243
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/unsatisfiableRangeAssertion.cpp25789
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/validPaths01.cpp457
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/validPaths02.cpp53
-rw-r--r--src/3rdparty/adaptagrams/libavoid/tests/vertlineassertion.cpp2214
-rw-r--r--src/3rdparty/adaptagrams/libavoid/timer.cpp188
-rw-r--r--src/3rdparty/adaptagrams/libavoid/timer.h104
-rw-r--r--src/3rdparty/adaptagrams/libavoid/vertices.cpp739
-rw-r--r--src/3rdparty/adaptagrams/libavoid/vertices.h226
-rw-r--r--src/3rdparty/adaptagrams/libavoid/viscluster.cpp116
-rw-r--r--src/3rdparty/adaptagrams/libavoid/viscluster.h136
-rw-r--r--src/3rdparty/adaptagrams/libavoid/visibility.cpp676
-rw-r--r--src/3rdparty/adaptagrams/libavoid/visibility.h41
-rw-r--r--src/3rdparty/adaptagrams/libavoid/vpsc.cpp1500
-rw-r--r--src/3rdparty/adaptagrams/libavoid/vpsc.h341
-rw-r--r--src/3rdparty/adaptagrams/libcola/CMakeLists.txt30
-rw-r--r--src/3rdparty/adaptagrams/libcola/Makefile.am60
-rw-r--r--src/3rdparty/adaptagrams/libcola/box.cpp111
-rw-r--r--src/3rdparty/adaptagrams/libcola/box.h82
-rw-r--r--src/3rdparty/adaptagrams/libcola/cc_clustercontainmentconstraints.cpp194
-rw-r--r--src/3rdparty/adaptagrams/libcola/cc_clustercontainmentconstraints.h52
-rw-r--r--src/3rdparty/adaptagrams/libcola/cc_nonoverlapconstraints.cpp590
-rw-r--r--src/3rdparty/adaptagrams/libcola/cc_nonoverlapconstraints.h210
-rw-r--r--src/3rdparty/adaptagrams/libcola/cluster.cpp719
-rw-r--r--src/3rdparty/adaptagrams/libcola/cluster.h371
-rw-r--r--src/3rdparty/adaptagrams/libcola/cola.cpp700
-rw-r--r--src/3rdparty/adaptagrams/libcola/cola.h1002
-rw-r--r--src/3rdparty/adaptagrams/libcola/cola_log.h204
-rw-r--r--src/3rdparty/adaptagrams/libcola/colafd.cpp1681
-rw-r--r--src/3rdparty/adaptagrams/libcola/commondefs.h98
-rw-r--r--src/3rdparty/adaptagrams/libcola/compound_constraints.cpp1671
-rw-r--r--src/3rdparty/adaptagrams/libcola/compound_constraints.h829
-rw-r--r--src/3rdparty/adaptagrams/libcola/conjugate_gradient.cpp137
-rw-r--r--src/3rdparty/adaptagrams/libcola/conjugate_gradient.h36
-rw-r--r--src/3rdparty/adaptagrams/libcola/connected_components.cpp160
-rw-r--r--src/3rdparty/adaptagrams/libcola/connected_components.h54
-rw-r--r--src/3rdparty/adaptagrams/libcola/convex_hull.cpp129
-rw-r--r--src/3rdparty/adaptagrams/libcola/convex_hull.h31
-rw-r--r--src/3rdparty/adaptagrams/libcola/doc/description.doc50
-rw-r--r--src/3rdparty/adaptagrams/libcola/exceptions.h54
-rw-r--r--src/3rdparty/adaptagrams/libcola/gradient_projection.cpp482
-rw-r--r--src/3rdparty/adaptagrams/libcola/gradient_projection.h165
-rw-r--r--src/3rdparty/adaptagrams/libcola/libcola.pc.in11
-rw-r--r--src/3rdparty/adaptagrams/libcola/output_svg.cpp389
-rw-r--r--src/3rdparty/adaptagrams/libcola/output_svg.h80
-rw-r--r--src/3rdparty/adaptagrams/libcola/pseudorandom.cpp48
-rw-r--r--src/3rdparty/adaptagrams/libcola/pseudorandom.h44
-rw-r--r--src/3rdparty/adaptagrams/libcola/shapepair.cpp47
-rw-r--r--src/3rdparty/adaptagrams/libcola/shapepair.h49
-rw-r--r--src/3rdparty/adaptagrams/libcola/shortest_paths.h245
-rw-r--r--src/3rdparty/adaptagrams/libcola/sparse_matrix.h140
-rw-r--r--src/3rdparty/adaptagrams/libcola/straightener.cpp798
-rw-r--r--src/3rdparty/adaptagrams/libcola/straightener.h389
-rwxr-xr-xsrc/3rdparty/adaptagrams/libcola/tests/FixedRelativeConstraint01.cpp51
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/Makefile.am68
-rwxr-xr-xsrc/3rdparty/adaptagrams/libcola/tests/StillOverlap01.cpp221
-rwxr-xr-xsrc/3rdparty/adaptagrams/libcola/tests/StillOverlap02.cpp1863
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/boundary.cpp121
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/connected_components.cpp69
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/constrained.cpp99
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/containment.cpp89
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/containment2.cpp157
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/convex_hull.cpp180
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/cycle_detector.cpp386
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/data/1138_bus.txt1458
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/data/uetzNetworkGSC-all.gml26139
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/gml_graph.cpp257
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/graphlayouttest.h275
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/initialOverlap.cpp168
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/invalid.cpp80
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/large_graph.cpp144
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/makefeasible.cpp368
-rwxr-xr-xsrc/3rdparty/adaptagrams/libcola/tests/makefeasible02.cpp932
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/makemovie.sh10
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/max_acyclic_subgraph.cpp346
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/overlappingClusters01.cpp333
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/overlappingClusters02.cpp100
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/overlappingClusters04.cpp61
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/page_bounds.cpp102
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/planar.cpp287
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/random_graph.cpp113
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/rectangularClusters01.cpp1135
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/rectclustershapecontainment.cpp2173
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/resize.cpp132
-rwxr-xr-xsrc/3rdparty/adaptagrams/libcola/tests/runtest.sh8
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/scale_free.cpp135
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/shortest_paths.cpp140
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/small_graph.cpp111
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/sparse_matrix.cpp88
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/test_cg.cpp164
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/topology.cpp177
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/trees.cpp103
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/unconstrained.cpp71
-rw-r--r--src/3rdparty/adaptagrams/libcola/tests/unsatisfiable.cpp85
-rwxr-xr-xsrc/3rdparty/adaptagrams/libcola/tests/view_cd_output.sh43
-rwxr-xr-xsrc/3rdparty/adaptagrams/libcola/tests/view_mas_output.sh43
-rw-r--r--src/3rdparty/adaptagrams/libcola/unused.h26
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/CMakeLists.txt28
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/COPYING505
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/Makefile.am42
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/assertions.h102
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/block.cpp647
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/block.h113
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/blocks.cpp249
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/blocks.h96
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/cbuffer.cpp95
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/cbuffer.h49
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/constraint.cpp218
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/constraint.h139
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/doc/description.doc36
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/exceptions.h36
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/libvpsc.pc.in12
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/linesegment.h138
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/pairing_heap.h394
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/rectangle.cpp744
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/rectangle.h302
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/solve_VPSC.cpp561
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/solve_VPSC.h130
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/tests/Makefile.am15
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/tests/block.cpp105
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/tests/cycle.cpp106
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/tests/rectangleoverlap.cpp660
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/tests/satisfy_inc.cpp666
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/variable.cpp31
-rw-r--r--src/3rdparty/adaptagrams/libvpsc/variable.h95
-rw-r--r--src/3rdparty/autotrace/CMakeLists.txt48
-rw-r--r--src/3rdparty/autotrace/autotrace.c386
-rw-r--r--src/3rdparty/autotrace/autotrace.h413
-rw-r--r--src/3rdparty/autotrace/bitmap.c8
-rw-r--r--src/3rdparty/autotrace/bitmap.h13
-rw-r--r--src/3rdparty/autotrace/color.c114
-rw-r--r--src/3rdparty/autotrace/color.h53
-rw-r--r--src/3rdparty/autotrace/config.h117
-rw-r--r--src/3rdparty/autotrace/curve.c255
-rw-r--r--src/3rdparty/autotrace/curve.h131
-rw-r--r--src/3rdparty/autotrace/despeckle.c710
-rw-r--r--src/3rdparty/autotrace/despeckle.h54
-rw-r--r--src/3rdparty/autotrace/epsilon-equal.c22
-rw-r--r--src/3rdparty/autotrace/epsilon-equal.h17
-rw-r--r--src/3rdparty/autotrace/exception.c47
-rw-r--r--src/3rdparty/autotrace/exception.h39
-rw-r--r--src/3rdparty/autotrace/filename.c45
-rw-r--r--src/3rdparty/autotrace/filename.h33
-rw-r--r--src/3rdparty/autotrace/fit.c1442
-rw-r--r--src/3rdparty/autotrace/fit.h22
-rw-r--r--src/3rdparty/autotrace/image-header.h18
-rw-r--r--src/3rdparty/autotrace/image-proc.c493
-rw-r--r--src/3rdparty/autotrace/image-proc.h21
-rw-r--r--src/3rdparty/autotrace/input.c231
-rw-r--r--src/3rdparty/autotrace/input.h95
-rw-r--r--src/3rdparty/autotrace/intl.h22
-rw-r--r--src/3rdparty/autotrace/logreport.c9
-rw-r--r--src/3rdparty/autotrace/logreport.h32
-rw-r--r--src/3rdparty/autotrace/median.c863
-rw-r--r--src/3rdparty/autotrace/module.c52
-rw-r--r--src/3rdparty/autotrace/output.c243
-rw-r--r--src/3rdparty/autotrace/output.h89
-rw-r--r--src/3rdparty/autotrace/private.h43
-rw-r--r--src/3rdparty/autotrace/pxl-outline.c889
-rw-r--r--src/3rdparty/autotrace/pxl-outline.h58
-rw-r--r--src/3rdparty/autotrace/quantize.h52
-rw-r--r--src/3rdparty/autotrace/spline.c160
-rw-r--r--src/3rdparty/autotrace/spline.h88
-rw-r--r--src/3rdparty/autotrace/thin-image.c353
-rw-r--r--src/3rdparty/autotrace/thin-image.h36
-rw-r--r--src/3rdparty/autotrace/types.h42
-rw-r--r--src/3rdparty/autotrace/vector.c260
-rw-r--r--src/3rdparty/autotrace/vector.h65
-rw-r--r--src/3rdparty/autotrace/xstd.h85
-rw-r--r--src/3rdparty/libcroco/.clang-format16
-rw-r--r--src/3rdparty/libcroco/ABOUT-NLS226
-rw-r--r--src/3rdparty/libcroco/AUTHORS13
-rw-r--r--src/3rdparty/libcroco/CMakeLists.txt33
-rw-r--r--src/3rdparty/libcroco/CODING-STYLE113
-rw-r--r--src/3rdparty/libcroco/COPYING481
-rw-r--r--src/3rdparty/libcroco/COPYING.LIB481
-rw-r--r--src/3rdparty/libcroco/COPYRIGHTS4
-rw-r--r--src/3rdparty/libcroco/Doxyfile946
-rw-r--r--src/3rdparty/libcroco/Makefile.am72
-rw-r--r--src/3rdparty/libcroco/NEWS178
-rw-r--r--src/3rdparty/libcroco/README.md15
-rw-r--r--src/3rdparty/libcroco/TODO45
-rw-r--r--src/3rdparty/libcroco/acinclude.m4319
-rwxr-xr-xsrc/3rdparty/libcroco/autogen.sh37
-rw-r--r--src/3rdparty/libcroco/config.h.win32.in99
-rw-r--r--src/3rdparty/libcroco/configure.ac191
-rw-r--r--src/3rdparty/libcroco/croco-config.137
-rw-r--r--src/3rdparty/libcroco/croco-config.in82
-rw-r--r--src/3rdparty/libcroco/csslint/CMakeLists.txt16
-rw-r--r--src/3rdparty/libcroco/csslint/ChangeLog29
-rw-r--r--src/3rdparty/libcroco/csslint/Makefile.am18
-rw-r--r--src/3rdparty/libcroco/csslint/csslint.164
-rw-r--r--src/3rdparty/libcroco/csslint/csslint.c1011
-rw-r--r--src/3rdparty/libcroco/docs/Makefile.am3
-rw-r--r--src/3rdparty/libcroco/docs/design/parser-architecture.txt146
-rw-r--r--src/3rdparty/libcroco/docs/design/sel-instr.txt64
-rw-r--r--src/3rdparty/libcroco/docs/examples/Makefile.am1
-rw-r--r--src/3rdparty/libcroco/docs/examples/cssom-example-1.c109
-rw-r--r--src/3rdparty/libcroco/docs/examples/sac-example-1.c198
-rw-r--r--src/3rdparty/libcroco/docs/examples/sac-example-2.c349
-rw-r--r--src/3rdparty/libcroco/docs/examples/selection-example-1.c191
-rw-r--r--src/3rdparty/libcroco/docs/examples/selection-example-1.css41
-rw-r--r--src/3rdparty/libcroco/docs/examples/selection-example-1.xml14
-rw-r--r--src/3rdparty/libcroco/docs/reference/Makefile.am53
-rw-r--r--src/3rdparty/libcroco/docs/reference/libcroco-docs.sgml39
-rw-r--r--src/3rdparty/libcroco/docs/release-notes-template.txt41
-rw-r--r--src/3rdparty/libcroco/docs/usage.txt47
-rw-r--r--src/3rdparty/libcroco/global-test-vars.sh.in12
-rwxr-xr-xsrc/3rdparty/libcroco/libcroco-indent102
-rwxr-xr-xsrc/3rdparty/libcroco/libcroco-zip.in25
-rw-r--r--src/3rdparty/libcroco/libcroco.doap30
-rw-r--r--src/3rdparty/libcroco/libcroco.pc.in11
-rw-r--r--src/3rdparty/libcroco/libcroco.spec.in82
-rw-r--r--src/3rdparty/libcroco/src/CMakeLists.txt85
-rw-r--r--src/3rdparty/libcroco/src/Makefile.am136
-rw-r--r--src/3rdparty/libcroco/src/cr-additional-sel.c456
-rw-r--r--src/3rdparty/libcroco/src/cr-additional-sel.h98
-rw-r--r--src/3rdparty/libcroco/src/cr-attr-sel.c221
-rw-r--r--src/3rdparty/libcroco/src/cr-attr-sel.h74
-rw-r--r--src/3rdparty/libcroco/src/cr-cascade.c214
-rw-r--r--src/3rdparty/libcroco/src/cr-cascade.h74
-rw-r--r--src/3rdparty/libcroco/src/cr-declaration.c794
-rw-r--r--src/3rdparty/libcroco/src/cr-declaration.h136
-rw-r--r--src/3rdparty/libcroco/src/cr-doc-handler.c276
-rw-r--r--src/3rdparty/libcroco/src/cr-doc-handler.h298
-rw-r--r--src/3rdparty/libcroco/src/cr-enc-handler.c184
-rw-r--r--src/3rdparty/libcroco/src/cr-enc-handler.h94
-rw-r--r--src/3rdparty/libcroco/src/cr-fonts.c943
-rw-r--r--src/3rdparty/libcroco/src/cr-fonts.h315
-rw-r--r--src/3rdparty/libcroco/src/cr-input.c1181
-rw-r--r--src/3rdparty/libcroco/src/cr-input.h174
-rw-r--r--src/3rdparty/libcroco/src/cr-libxml-node-iface.c81
-rw-r--r--src/3rdparty/libcroco/src/cr-libxml-node-iface.h14
-rw-r--r--src/3rdparty/libcroco/src/cr-node-iface.h34
-rw-r--r--src/3rdparty/libcroco/src/cr-num.c345
-rw-r--r--src/3rdparty/libcroco/src/cr-num.h127
-rw-r--r--src/3rdparty/libcroco/src/cr-om-parser.c1150
-rw-r--r--src/3rdparty/libcroco/src/cr-om-parser.h98
-rw-r--r--src/3rdparty/libcroco/src/cr-parser.c4568
-rw-r--r--src/3rdparty/libcroco/src/cr-parser.h130
-rw-r--r--src/3rdparty/libcroco/src/cr-parsing-location.c172
-rw-r--r--src/3rdparty/libcroco/src/cr-parsing-location.h70
-rw-r--r--src/3rdparty/libcroco/src/cr-prop-list.c404
-rw-r--r--src/3rdparty/libcroco/src/cr-prop-list.h80
-rw-r--r--src/3rdparty/libcroco/src/cr-pseudo.c166
-rw-r--r--src/3rdparty/libcroco/src/cr-pseudo.h66
-rw-r--r--src/3rdparty/libcroco/src/cr-rgb.c686
-rw-r--r--src/3rdparty/libcroco/src/cr-rgb.h94
-rw-r--r--src/3rdparty/libcroco/src/cr-sel-eng.c2236
-rw-r--r--src/3rdparty/libcroco/src/cr-sel-eng.h118
-rw-r--r--src/3rdparty/libcroco/src/cr-selector.c333
-rw-r--r--src/3rdparty/libcroco/src/cr-selector.h95
-rw-r--r--src/3rdparty/libcroco/src/cr-simple-sel.c322
-rw-r--r--src/3rdparty/libcroco/src/cr-simple-sel.h131
-rw-r--r--src/3rdparty/libcroco/src/cr-statement.c2810
-rw-r--r--src/3rdparty/libcroco/src/cr-statement.h440
-rw-r--r--src/3rdparty/libcroco/src/cr-string.c170
-rw-r--r--src/3rdparty/libcroco/src/cr-string.h76
-rw-r--r--src/3rdparty/libcroco/src/cr-style.c2852
-rw-r--r--src/3rdparty/libcroco/src/cr-style.h339
-rw-r--r--src/3rdparty/libcroco/src/cr-stylesheet.c268
-rw-r--r--src/3rdparty/libcroco/src/cr-stylesheet.h117
-rw-r--r--src/3rdparty/libcroco/src/cr-term.c744
-rw-r--r--src/3rdparty/libcroco/src/cr-term.h195
-rw-r--r--src/3rdparty/libcroco/src/cr-tknzr.c2777
-rw-r--r--src/3rdparty/libcroco/src/cr-tknzr.h115
-rw-r--r--src/3rdparty/libcroco/src/cr-token.c636
-rw-r--r--src/3rdparty/libcroco/src/cr-token.h212
-rw-r--r--src/3rdparty/libcroco/src/cr-utils.c1330
-rw-r--r--src/3rdparty/libcroco/src/cr-utils.h245
-rw-r--r--src/3rdparty/libcroco/src/libcroco-config.h.in17
-rw-r--r--src/3rdparty/libcroco/src/libcroco.h44
-rw-r--r--src/3rdparty/libcroco/src/libcroco.symbols538
-rw-r--r--src/3rdparty/libcroco/tests/CMakeLists.txt69
-rw-r--r--src/3rdparty/libcroco/tests/Makefile.am36
-rw-r--r--src/3rdparty/libcroco/tests/README-description.txt125
-rw-r--r--src/3rdparty/libcroco/tests/cr-test-utils.c59
-rw-r--r--src/3rdparty/libcroco/tests/cr-test-utils.h50
-rw-r--r--src/3rdparty/libcroco/tests/global-vars.sh.in10
-rwxr-xr-xsrc/3rdparty/libcroco/tests/test-functional-notation.sh5
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/Makefile.am16
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/functional-notation.css2
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/lots-of-comments.css198
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/parsing-location.css26
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/prop-vendor-ident.css3
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/sel-child-class.css1
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/sel-child-class.xml10
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/several-media.css10
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test0.1.css258
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test1.css316
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test2.1.css47
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test2.2.css686
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test2.css9
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test3.1.css36
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test3.2.css693
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test3.css9
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test4.1.css682
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test4.2.css24
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/test5.1.css14
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/unknown-at-rule.css3
-rw-r--r--src/3rdparty/libcroco/tests/test-inputs/unknown-at-rule2.css3
-rwxr-xr-xsrc/3rdparty/libcroco/tests/test-lots-of-comments.sh5
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/Makefile.am16
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test-functional-notation.out7
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test-lots-of-comments.out26
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test-parsing-location.out219
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test-prop-ident.out3
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test-sel-child-class.out4
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test-several-media.out17
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test-unknown-at-rule.out1
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test-unknown-at-rule2.out2
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test0.1.css.out1
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test1.css.out316
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test2.1.css.out173
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test2.2.css.out3328
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test2.css.out63
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test3.1.css.out0
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test3.2.css.out0
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test3.css.out0
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test4.1.css.out766
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test4.2.css.out24
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test5.1.css.out105
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test6.out8
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test7.out43
-rw-r--r--src/3rdparty/libcroco/tests/test-output-refs/test8.out15
-rwxr-xr-xsrc/3rdparty/libcroco/tests/test-parsing-location.sh5
-rwxr-xr-xsrc/3rdparty/libcroco/tests/test-prop-ident.sh5
-rwxr-xr-xsrc/3rdparty/libcroco/tests/test-sel-child-class.sh5
-rwxr-xr-xsrc/3rdparty/libcroco/tests/test-several-media.sh5
-rwxr-xr-xsrc/3rdparty/libcroco/tests/test-unknown-at-rule.sh5
-rwxr-xr-xsrc/3rdparty/libcroco/tests/test-unknown-at-rule2.sh5
-rw-r--r--src/3rdparty/libcroco/tests/test0-main.c203
-rw-r--r--src/3rdparty/libcroco/tests/test1-main.c197
-rw-r--r--src/3rdparty/libcroco/tests/test2-main.c564
-rw-r--r--src/3rdparty/libcroco/tests/test3-main.c545
-rw-r--r--src/3rdparty/libcroco/tests/test4-main.c435
-rw-r--r--src/3rdparty/libcroco/tests/test5-main.c255
-rw-r--r--src/3rdparty/libcroco/tests/test6-main.c84
-rw-r--r--src/3rdparty/libcroco/tests/test7-main.c95
-rw-r--r--src/3rdparty/libcroco/tests/test8-main.c44
-rwxr-xr-xsrc/3rdparty/libcroco/tests/testctl462
-rwxr-xr-xsrc/3rdparty/libcroco/tests/valgrind-version.sh48
-rw-r--r--src/3rdparty/libcroco/tests/valgrind.log0
-rwxr-xr-xsrc/3rdparty/libcroco/tests/vg24
-rw-r--r--src/3rdparty/libcroco/tests/vg.supp57
-rw-r--r--src/3rdparty/libcroco/win32/Makefile-newvs.am55
-rw-r--r--src/3rdparty/libcroco/win32/Makefile.am22
-rw-r--r--src/3rdparty/libcroco/win32/Makefile.msvcproj153
-rw-r--r--src/3rdparty/libcroco/win32/crocopc.py33
-rw-r--r--src/3rdparty/libcroco/win32/pc_base.py124
-rw-r--r--src/3rdparty/libcroco/win32/replace.py115
-rw-r--r--src/3rdparty/libcroco/win32/vs10/Makefile.am48
-rw-r--r--src/3rdparty/libcroco/win32/vs10/croco-build-defines.props48
-rw-r--r--src/3rdparty/libcroco/win32/vs10/croco-gen-srcs.props44
-rw-r--r--src/3rdparty/libcroco/win32/vs10/croco-install.propsin62
-rw-r--r--src/3rdparty/libcroco/win32/vs10/croco-install.vcxproj134
-rw-r--r--src/3rdparty/libcroco/win32/vs10/croco-install.vcxproj.filters29
-rw-r--r--src/3rdparty/libcroco/win32/vs10/croco-version-paths.props.in89
-rw-r--r--src/3rdparty/libcroco/win32/vs10/croco.vcxproj.filtersin43
-rw-r--r--src/3rdparty/libcroco/win32/vs10/croco.vcxprojin222
-rw-r--r--src/3rdparty/libcroco/win32/vs10/csslint.vcxproj194
-rw-r--r--src/3rdparty/libcroco/win32/vs10/csslint.vcxproj.filters33
-rw-r--r--src/3rdparty/libcroco/win32/vs10/libcroco.sln46
-rw-r--r--src/3rdparty/libcroco/win32/vs11/Makefile.am39
-rw-r--r--src/3rdparty/libcroco/win32/vs12/Makefile.am39
-rw-r--r--src/3rdparty/libcroco/win32/vs14/Makefile.am39
-rw-r--r--src/3rdparty/libcroco/win32/vs15/Makefile.am40
-rw-r--r--src/3rdparty/libcroco/win32/vs16/Makefile.am40
-rw-r--r--src/3rdparty/libcroco/win32/vs9/Makefile.am39
-rw-r--r--src/3rdparty/libcroco/win32/vs9/croco-build-defines.vsprops41
-rw-r--r--src/3rdparty/libcroco/win32/vs9/croco-gen-srcs.vsprops38
-rw-r--r--src/3rdparty/libcroco/win32/vs9/croco-install.vcproj137
-rw-r--r--src/3rdparty/libcroco/win32/vs9/croco-install.vspropsin51
-rw-r--r--src/3rdparty/libcroco/win32/vs9/croco-version-paths.vsprops.in88
-rw-r--r--src/3rdparty/libcroco/win32/vs9/croco.vcprojin273
-rw-r--r--src/3rdparty/libcroco/win32/vs9/csslint.vcproj189
-rw-r--r--src/3rdparty/libcroco/win32/vs9/libcroco.sln53
-rw-r--r--src/3rdparty/libdepixelize/CMakeLists.txt24
-rw-r--r--src/3rdparty/libdepixelize/README7
-rw-r--r--src/3rdparty/libdepixelize/kopftracer2011.cpp665
-rw-r--r--src/3rdparty/libdepixelize/kopftracer2011.h150
-rw-r--r--src/3rdparty/libdepixelize/priv/branchless.h58
-rw-r--r--src/3rdparty/libdepixelize/priv/colorspace.h111
-rw-r--r--src/3rdparty/libdepixelize/priv/curvature.h115
-rw-r--r--src/3rdparty/libdepixelize/priv/homogeneoussplines.h472
-rw-r--r--src/3rdparty/libdepixelize/priv/integral.h61
-rw-r--r--src/3rdparty/libdepixelize/priv/iterator.h123
-rw-r--r--src/3rdparty/libdepixelize/priv/optimization-kopf2011.h263
-rw-r--r--src/3rdparty/libdepixelize/priv/pixelgraph.h555
-rw-r--r--src/3rdparty/libdepixelize/priv/point.h112
-rw-r--r--src/3rdparty/libdepixelize/priv/simplifiedvoronoi.h1707
-rw-r--r--src/3rdparty/libdepixelize/priv/splines-kopf2011.h167
-rw-r--r--src/3rdparty/libdepixelize/splines.h120
-rw-r--r--src/3rdparty/libuemf/CMakeLists.txt30
-rw-r--r--src/3rdparty/libuemf/README567
-rw-r--r--src/3rdparty/libuemf/symbol_convert.c1008
-rw-r--r--src/3rdparty/libuemf/symbol_convert.h51
-rw-r--r--src/3rdparty/libuemf/uemf.c5606
-rw-r--r--src/3rdparty/libuemf/uemf.h3653
-rw-r--r--src/3rdparty/libuemf/uemf_endian.c2270
-rw-r--r--src/3rdparty/libuemf/uemf_endian.h59
-rw-r--r--src/3rdparty/libuemf/uemf_print.c2704
-rw-r--r--src/3rdparty/libuemf/uemf_print.h177
-rw-r--r--src/3rdparty/libuemf/uemf_safe.c1204
-rw-r--r--src/3rdparty/libuemf/uemf_safe.h32
-rw-r--r--src/3rdparty/libuemf/uemf_utf.c720
-rw-r--r--src/3rdparty/libuemf/uemf_utf.h55
-rw-r--r--src/3rdparty/libuemf/upmf.c8661
-rw-r--r--src/3rdparty/libuemf/upmf.h3178
-rw-r--r--src/3rdparty/libuemf/upmf_print.c3400
-rw-r--r--src/3rdparty/libuemf/upmf_print.h181
-rw-r--r--src/3rdparty/libuemf/uwmf.c7039
-rw-r--r--src/3rdparty/libuemf/uwmf.h2677
-rw-r--r--src/3rdparty/libuemf/uwmf_endian.c1774
-rw-r--r--src/3rdparty/libuemf/uwmf_endian.h34
-rw-r--r--src/3rdparty/libuemf/uwmf_print.c1635
-rw-r--r--src/3rdparty/libuemf/uwmf_print.h52
1068 files changed, 432175 insertions, 0 deletions
diff --git a/src/3rdparty/2geom/2GeomConfig.cmake b/src/3rdparty/2geom/2GeomConfig.cmake
new file mode 100644
index 0000000..926f751
--- /dev/null
+++ b/src/3rdparty/2geom/2GeomConfig.cmake
@@ -0,0 +1,3 @@
+include(CMakeFindDependencyMacro)
+find_dependency(Boost 1.40 REQUIRED)
+include("${CMAKE_CURRENT_LIST_DIR}/2GeomTargets.cmake") \ No newline at end of file
diff --git a/src/3rdparty/2geom/2geom.pc.in b/src/3rdparty/2geom/2geom.pc.in
new file mode 100644
index 0000000..4039851
--- /dev/null
+++ b/src/3rdparty/2geom/2geom.pc.in
@@ -0,0 +1,13 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: 2geom
+Description: A 2D geometry framework
+Version: @2GEOM_VERSION@
+
+Requires:
+Libs: -L${libdir} -l2geom
+Cflags: -I${includedir}/2geom-@2GEOM_VERSION@
+
diff --git a/src/3rdparty/2geom/AUTHORS.md b/src/3rdparty/2geom/AUTHORS.md
new file mode 100644
index 0000000..2a54918
--- /dev/null
+++ b/src/3rdparty/2geom/AUTHORS.md
@@ -0,0 +1,26 @@
+# Authors
+
+ - Maximilian Albert
+ - Joshua Andler
+ - Tavmjong Bah
+ - Jean-François Barraud
+ - Vincent Barrielle
+ - Olaf Bjarnason
+ - Joshua L. Blocher
+ - Marco Cecchetti
+ - Kris De Gussem
+ - Tim G. Dwyer
+ - Markus Engel
+ - Johan B. C. Engelen
+ - Paul F. Harrison
+ - Nathan J. Hurst
+ - Vangelis Katsikaros
+ - Krzysztof Kosiński
+ - Diederik van Lierop
+ - Mentalguy
+ - Jelle R. Moulder
+ - Alvin Penner
+ - Jan Pulmann
+ - Michael G. Sloan
+ - Aaron Spike
+ - Michael Wybrow
diff --git a/src/3rdparty/2geom/CMakeLists.txt b/src/3rdparty/2geom/CMakeLists.txt
new file mode 100644
index 0000000..43fb4cd
--- /dev/null
+++ b/src/3rdparty/2geom/CMakeLists.txt
@@ -0,0 +1,156 @@
+cmake_minimum_required(VERSION 3.12)
+cmake_policy(SET CMP0054 NEW)
+
+
+set(2GEOM_MAJOR_VERSION 1)
+set(2GEOM_MINOR_VERSION 3)
+set(2GEOM_PATCH_VERSION 0)
+set(2GEOM_VERSION ${2GEOM_MAJOR_VERSION}.${2GEOM_MINOR_VERSION}.${2GEOM_PATCH_VERSION} CACHE INTERNAL "" FORCE)
+set(2GEOM_ABI_VERSION ${2GEOM_MAJOR_VERSION}.${2GEOM_MINOR_VERSION}.0)
+
+project(lib2geom
+ VERSION
+ ${2GEOM_VERSION}
+ LANGUAGES
+ CXX
+ C # C is required by CHECK_SYMBOL_EXISTS
+ )
+
+set(2GEOM_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/include" CACHE INTERNAL "")
+include_directories("${CMAKE_CURRENT_LIST_DIR}/src/2geom") # for private headers/template support.
+
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS OFF) # enforces -std=c++17 instead of -std=gnu++17
+set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)
+set(CMAKE_SKIP_RPATH:BOOL OFF)
+set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeScripts)
+set(THREADS_PREFER_PTHREAD_FLAG ON)
+
+include(GNUInstallDirs)
+include(CheckCXXSourceCompiles)
+
+# Find dependencies
+find_package(Boost 1.60 REQUIRED)
+find_package(DoubleConversion REQUIRED)
+find_package(PkgConfig REQUIRED)
+find_package(Cython)
+find_package(Threads)
+pkg_check_modules(GTK3 gtk+-3.0)
+pkg_check_modules(GLIB REQUIRED glib-2.0)
+pkg_check_modules(CAIRO cairo)
+pkg_check_modules(GSL REQUIRED gsl)
+
+if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
+ set(2GEOM_STANDALONE TRUE)
+endif()
+
+option(2GEOM_TESTING "Build tests" "${2GEOM_STANDALONE}")
+
+if (2GEOM_TESTING)
+ enable_testing()
+ add_subdirectory(tests)
+endif()
+
+
+check_cxx_source_compiles("#include <math.h>\nint main() { double a=0.5,b=0.5,c=0.5; sincos(a, &b, &c); return 0; }" HAVE_SINCOS)
+if(HAVE_SINCOS)
+ add_definitions(-DHAVE_SINCOS)
+endif()
+if(GSL_FOUND)
+ add_definitions(-DHAVE_GSL)
+endif()
+if(CAIRO_FOUND)
+ add_definitions(-DHAVE_CAIRO)
+endif()
+if(PYCAIRO_FOUND)
+ add_definitions(-DHAVE_PYCAIRO)
+endif()
+
+
+# SET(NEEDS_GSL
+# differential-constraint
+# root-finder-comparer
+# # contour
+# sb-to-bez
+# )
+
+add_compile_options(-Wall -Wformat-security -Woverloaded-virtual -Wpointer-arith -Werror=return-type)
+add_compile_options(-O2)
+
+# suppress the very annoying "#pragma ms_struct" Clang warning, caused by -mms-bitfield required for GTK
+if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+ if(WIN32)
+ add_compile_options(-Wno-ignored-attributes)
+ endif()
+ add_compile_options(-Wno-unused-local-typedef)
+endif()
+
+option(WITH_PROFILING
+ "Build lib2geom with profiling enabled"
+ OFF)
+
+if(WITH_PROFILING)
+ add_compile_options(-pg)
+ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -pg")
+endif()
+
+option(2GEOM_BUILD_SHARED
+ "Build lib2geom and libtoy as shared libraries."
+ OFF)
+
+if(2GEOM_BUILD_SHARED)
+ set(LIB_TYPE SHARED)
+else()
+ set(LIB_TYPE STATIC)
+endif()
+
+option(2GEOM_USE_GPL_CODE
+ "Build lib2geom with GPL licensed Code."
+ ON)
+
+if(2GEOM_USE_GPL_CODE)
+ add_definitions(-DGPL_TAINT)
+endif()
+
+if(2GEOM_STANDALONE)
+ include(CMakeScripts/Dist.cmake)
+endif()
+
+# make unistall target
+configure_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
+ IMMEDIATE @ONLY)
+
+add_custom_target(uninstall_${PROJECT_NAME}
+ "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
+
+add_subdirectory(src)
+
+install(EXPORT 2geom_targets
+ FILE 2GeomTargets.cmake
+ NAMESPACE 2Geom::
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/2Geom"
+ COMPONENT "lib2geom_dev"
+ )
+
+include(CMakePackageConfigHelpers)
+write_basic_package_version_file("2GeomConfigVersion.cmake"
+ VERSION ${PROJECT_VERSION}
+ COMPATIBILITY SameMajorVersion)
+
+install(FILES "2GeomConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/2GeomConfigVersion.cmake"
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/2Geom"
+ COMPONENT "lib2geom_dev"
+ )
+
+install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/2geom"
+ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/2geom-${2GEOM_VERSION}"
+ COMPONENT "lib2geom_dev")
+
+configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/2geom.pc.in
+ ${CMAKE_CURRENT_BINARY_DIR}/2geom.pc @ONLY IMMEDIATE )
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/2geom.pc"
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
+ COMPONENT "lib2geom_dev")
diff --git a/src/3rdparty/2geom/CMakeScripts/Dist.cmake b/src/3rdparty/2geom/CMakeScripts/Dist.cmake
new file mode 100644
index 0000000..8de9b62
--- /dev/null
+++ b/src/3rdparty/2geom/CMakeScripts/Dist.cmake
@@ -0,0 +1,7 @@
+#make dist target
+SET(2GEOM_DIST_PREFIX "${PROJECT_NAME}-${2GEOM_VERSION}")
+ADD_CUSTOM_TARGET(dist
+ COMMAND git config tar.bz2.command bzip2
+ COMMAND git archive --prefix=${2GEOM_DIST_PREFIX}/ -o ${CMAKE_BINARY_DIR}/${2GEOM_DIST_PREFIX}.tar.bz2 HEAD
+ WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
+ VERBATIM)
diff --git a/src/3rdparty/2geom/CMakeScripts/FindCython.cmake b/src/3rdparty/2geom/CMakeScripts/FindCython.cmake
new file mode 100644
index 0000000..6d06de9
--- /dev/null
+++ b/src/3rdparty/2geom/CMakeScripts/FindCython.cmake
@@ -0,0 +1,37 @@
+# Find the Cython compiler.
+#
+# This code sets the following variables:
+#
+# CYTHON_EXECUTABLE
+#
+# See also UseCython.cmake
+
+#=============================================================================
+# Copyright 2011 Kitware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#=============================================================================
+
+find_program( CYTHON_EXECUTABLE NAMES cython cython.py
+ PATHS $ENV{PYTHON_PATH}\\Lib\\site-packages ${PYTHON_PATH}\\Lib\\site-packages)
+
+include( FindPackageHandleStandardArgs )
+FIND_PACKAGE_HANDLE_STANDARD_ARGS( Cython REQUIRED_VARS CYTHON_EXECUTABLE )
+
+mark_as_advanced( CYTHON_EXECUTABLE )
+
+IF (CYTHON_FOUND)
+ MESSAGE(STATUS "cython: FOUND")
+ELSE(CYTHON_FOUND)
+ MESSAGE(STATUS "cython: NOT FOUND")
+ENDIF (CYTHON_FOUND)
diff --git a/src/3rdparty/2geom/CMakeScripts/FindDoubleConversion.cmake b/src/3rdparty/2geom/CMakeScripts/FindDoubleConversion.cmake
new file mode 100644
index 0000000..bd4c002
--- /dev/null
+++ b/src/3rdparty/2geom/CMakeScripts/FindDoubleConversion.cmake
@@ -0,0 +1,27 @@
+# - Try to find double-conversion
+# Once done, this will define
+#
+# DoubleConversion_FOUND - system has double-conversion
+# DoubleConversion_INCLUDE_DIRS - the double-conversion include directories
+# DoubleConversion_LIBRARIES - link these to use double-conversion
+
+include(FindPackageHandleStandardArgs)
+
+find_library(DoubleConversion_LIBRARY double-conversion
+ PATHS ${DoubleConversion_LIBRARYDIR})
+
+find_path(DoubleConversion_INCLUDE_DIR double-conversion/double-conversion.h
+ PATHS ${DoubleConversion_INCLUDEDIR})
+
+find_package_handle_standard_args(DoubleConversion DEFAULT_MSG
+ DoubleConversion_LIBRARY
+ DoubleConversion_INCLUDE_DIR)
+
+mark_as_advanced(
+ DoubleConversion_LIBRARY
+ DoubleConversion_INCLUDE_DIR)
+
+if(DoubleConversion_FOUND)
+ set(DoubleConversion_LIBRARIES ${DoubleConversion_LIBRARY})
+ set(DoubleConversion_INCLUDE_DIRS ${DoubleConversion_INCLUDE_DIR})
+endif()
diff --git a/src/3rdparty/2geom/CMakeScripts/FindPython.cmake b/src/3rdparty/2geom/CMakeScripts/FindPython.cmake
new file mode 100644
index 0000000..3f05b58
--- /dev/null
+++ b/src/3rdparty/2geom/CMakeScripts/FindPython.cmake
@@ -0,0 +1,14 @@
+# figure out Python flags
+#TODO - rewrite to use ALLCAPS?
+FIND_PACKAGE(PythonInterp)
+IF(PYTHONINTERP_FOUND)
+ EXEC_PROGRAM(${PYTHON_EXECUTABLE}
+ ARGS ${CMAKE_SOURCE_DIR}/makelib/python_config_var.py LIBS
+ OUTPUT_VARIABLE PYTHON_LINK_LIBRARIES )
+ EXEC_PROGRAM(${PYTHON_EXECUTABLE}
+ ARGS ${CMAKE_SOURCE_DIR}/makelib/python_config_var.py LINKFORSTATIC
+ OUTPUT_VARIABLE PYTHON_LINKFORSTATIC )
+ELSE(PYTHONINTERP_FOUND)
+ SET(PYTHON_LINK_LIBRARIES "")
+ SET(PYTHON_LINKFORSTATIC "")
+ENDIF(PYTHONINTERP_FOUND)
diff --git a/src/3rdparty/2geom/CMakeScripts/UseCython.cmake b/src/3rdparty/2geom/CMakeScripts/UseCython.cmake
new file mode 100644
index 0000000..38c3155
--- /dev/null
+++ b/src/3rdparty/2geom/CMakeScripts/UseCython.cmake
@@ -0,0 +1,288 @@
+# Define a function to create Cython modules.
+#
+# For more information on the Cython project, see http://cython.org/.
+# "Cython is a language that makes writing C extensions for the Python language
+# as easy as Python itself."
+#
+# This file defines a CMake function to build a Cython Python module.
+# To use it, first include this file.
+#
+# include( UseCython )
+#
+# Then call cython_add_module to create a module.
+#
+# cython_add_module( <module_name> <src1> <src2> ... <srcN> )
+#
+# To create a standalone executable, the function
+#
+# cython_add_standalone_executable( <executable_name> [MAIN_MODULE src1] <src1> <src2> ... <srcN> )
+#
+# To avoid dependence on Python, set the PYTHON_LIBRARY cache variable to point
+# to a static library. If a MAIN_MODULE source is specified,
+# the "if __name__ == '__main__':" from that module is used as the C main() method
+# for the executable. If MAIN_MODULE, the source with the same basename as
+# <executable_name> is assumed to be the MAIN_MODULE.
+#
+# Where <module_name> is the name of the resulting Python module and
+# <src1> <src2> ... are source files to be compiled into the module, e.g. *.pyx,
+# *.py, *.c, *.cxx, etc. A CMake target is created with name <module_name>. This can
+# be used for target_link_libraries(), etc.
+#
+# The sample paths set with the CMake include_directories() command will be used
+# for include directories to search for *.pxd when running the Cython complire.
+#
+# Cache variables that effect the behavior include:
+#
+# CYTHON_ANNOTATE
+# CYTHON_NO_DOCSTRINGS
+# CYTHON_FLAGS
+#
+# Source file properties that effect the build process are
+#
+# CYTHON_IS_CXX
+#
+# If this is set of a *.pyx file with CMake set_source_files_properties()
+# command, the file will be compiled as a C++ file.
+#
+# See also FindCython.cmake
+
+#=============================================================================
+# Copyright 2011 Kitware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#=============================================================================
+
+# Configuration options.
+
+#TODO - rewrite to use ALLCAPS?
+set( CYTHON_ANNOTATE OFF
+ CACHE BOOL "Create an annotated .html file when compiling *.pyx." )
+set( CYTHON_NO_DOCSTRINGS OFF
+ CACHE BOOL "Strip docstrings from the compiled module." )
+set( CYTHON_FLAGS "" CACHE STRING
+ "Extra flags to the cython compiler." )
+mark_as_advanced( CYTHON_ANNOTATE CYTHON_NO_DOCSTRINGS CYTHON_FLAGS )
+
+find_package( Cython REQUIRED )
+find_package( PythonLibs REQUIRED )
+
+set( CYTHON_CXX_EXTENSION "cxx" )
+set( CYTHON_C_EXTENSION "c" )
+
+# Create a *.c or *.cxx file from a *.pyx file.
+# Input the generated file basename. The generate file will put into the variable
+# placed in the "generated_file" argument. Finally all the *.py and *.pyx files.
+function( compile_pyx _name generated_file )
+ # Default to assuming all files are C.
+ set( cxx_arg "" )
+ set( extension ${CYTHON_C_EXTENSION} )
+ set( pyx_lang "C" )
+ set( comment "Compiling Cython C source for ${_name}..." )
+
+ set( cython_include_directories "" )
+ set( pxd_dependencies "" )
+ set( c_header_dependencies "" )
+ set( pyx_locations "" )
+
+ foreach( pyx_file ${ARGN} )
+ get_filename_component( pyx_file_basename "${pyx_file}" NAME_WE )
+
+ # Determine if it is a C or C++ file.
+ get_source_file_property( property_is_cxx ${pyx_file} CYTHON_IS_CXX )
+ if( ${property_is_cxx} )
+ set( cxx_arg "--cplus" )
+ set( extension ${CYTHON_CXX_EXTENSION} )
+ set( pyx_lang "CXX" )
+ set( comment "Compiling Cython CXX source for ${_name}..." )
+ endif()
+
+ # Get the include directories.
+ get_source_file_property( pyx_location ${pyx_file} LOCATION )
+ get_filename_component( pyx_path ${pyx_location} PATH )
+ get_directory_property( cmake_include_directories DIRECTORY ${pyx_path} INCLUDE_DIRECTORIES )
+ list( APPEND cython_include_directories ${cmake_include_directories} )
+ list( APPEND pyx_locations "${pyx_location}" )
+
+ # Determine dependencies.
+ # Add the pxd file will the same name as the given pyx file.
+ unset( corresponding_pxd_file CACHE )
+ find_file( corresponding_pxd_file ${pyx_file_basename}.pxd
+ PATHS "${pyx_path}" ${cmake_include_directories}
+ NO_DEFAULT_PATH )
+ if( corresponding_pxd_file )
+ list( APPEND pxd_dependencies "${corresponding_pxd_file}" )
+ endif()
+
+ # pxd files to check for additional dependencies.
+ set( pxds_to_check "${pyx_file}" "${pxd_dependencies}" )
+ set( pxds_checked "" )
+ set( number_pxds_to_check 1 )
+ while( ${number_pxds_to_check} GREATER 0 )
+ foreach( pxd ${pxds_to_check} )
+ list( APPEND pxds_checked "${pxd}" )
+ list( REMOVE_ITEM pxds_to_check "${pxd}" )
+
+ # check for C header dependencies
+ file( STRINGS "${pxd}" extern_from_statements
+ REGEX "cdef[ ]+extern[ ]+from.*$" )
+ foreach( statement ${extern_from_statements} )
+ # Had trouble getting the quote in the regex
+ string( REGEX REPLACE "cdef[ ]+extern[ ]+from[ ]+[\"]([^\"]+)[\"].*" "\\1" header "${statement}" )
+ unset( header_location CACHE )
+ find_file( header_location ${header} PATHS ${cmake_include_directories} )
+ if( header_location )
+ list( FIND c_header_dependencies "${header_location}" header_idx )
+ if( ${header_idx} LESS 0 )
+ list( APPEND c_header_dependencies "${header_location}" )
+ endif()
+ endif()
+ endforeach()
+
+ set( module_dependencies "" )
+
+ # Look for cimport and include statements.
+ file( STRINGS "${pxd}" cimport_statements REGEX "(cimport|include)" )
+ foreach( statement ${cimport_statements} )
+ if( ${statement} MATCHES from )
+ string( REGEX REPLACE "from[ ]+([^ ]+).*" "\\1.pxd" module "${statement}" )
+ elseif( ${statement} MATCHES include )
+ string( REGEX REPLACE "include[ ]+[\"]([^\"]+)[\"].*" "\\1" module "${statement}" )
+ else()
+ string( REGEX REPLACE "cimport[ ]+([^ ]+).*" "\\1.pxd" module "${statement}" )
+ endif()
+ list( APPEND module_dependencies ${module} )
+ endforeach()
+ list( REMOVE_DUPLICATES module_dependencies )
+ # Add the module to the files to check, if appropriate.
+ foreach( module ${module_dependencies} )
+ unset( pxd_location CACHE )
+ find_file( pxd_location ${module}
+ PATHS "${pyx_path}" ${cmake_include_directories} NO_DEFAULT_PATH )
+ if( pxd_location )
+ list( FIND pxds_checked ${pxd_location} pxd_idx )
+ if( ${pxd_idx} LESS 0 )
+ list( FIND pxds_to_check ${pxd_location} pxd_idx )
+ if( ${pxd_idx} LESS 0 )
+ list( APPEND pxds_to_check ${pxd_location} )
+ list( APPEND pxd_dependencies ${pxd_location} )
+ endif() # if it is not already going to be checked
+ endif() # if it has not already been checked
+ else()
+ message("${module} ignored")
+ endif() # if pxd file can be found
+ endforeach() # for each module dependency discovered
+ endforeach() # for each pxd file to check
+ list( LENGTH pxds_to_check number_pxds_to_check )
+ endwhile()
+ endforeach() # pyx_file
+
+ # Set additional flags.
+ if( CYTHON_ANNOTATE )
+ set( annotate_arg "--annotate" )
+ endif()
+
+ if( CYTHON_NO_DOCSTRINGS )
+ set( no_docstrings_arg "--no-docstrings" )
+ endif()
+
+ if( "${CMAKE_BUILD_TYPE}" STREQUAL "Debug" OR
+ "${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo" )
+ set( cython_debug_arg "--gdb" )
+ endif()
+
+ # Include directory arguments.
+ list( REMOVE_DUPLICATES cython_include_directories )
+ set( include_directory_arg "" )
+ foreach( _include_dir ${cython_include_directories} )
+ set( include_directory_arg ${include_directory_arg} "-I" "${_include_dir}" )
+ endforeach()
+
+ # Determining generated file name.
+ set( _generated_file "${_name}.${extension}" )
+ set_source_files_properties( ${_generated_file} PROPERTIES GENERATED TRUE )
+ set( ${generated_file} ${_generated_file} PARENT_SCOPE )
+
+ list( REMOVE_DUPLICATES pxd_dependencies )
+ list( REMOVE_DUPLICATES c_header_dependencies )
+
+ # Add the command to run the compiler.
+ add_custom_command( OUTPUT ${_generated_file}
+ COMMAND ${CYTHON_EXECUTABLE}
+ ARGS ${cxx_arg} ${include_directory_arg}
+ ${annotate_arg} ${no_docstrings_arg} ${cython_debug_arg} ${CYTHON_FLAGS}
+ --output-file ${_generated_file} ${pyx_locations}
+ DEPENDS ${pyx_locations} ${pxd_dependencies}
+ IMPLICIT_DEPENDS ${pyx_lang} ${c_header_dependencies}
+ COMMENT ${comment}
+ )
+
+ # Remove their visibility to the user.
+ set( corresponding_pxd_file "" CACHE INTERNAL "" )
+ set( header_location "" CACHE INTERNAL "" )
+ set( pxd_location "" CACHE INTERNAL "" )
+endfunction()
+
+# cython_add_module( <name> src1 src2 ... srcN )
+# Build the Cython Python module.
+function( cython_add_module _name )
+ set( pyx_module_sources "" )
+ set( other_module_sources "" )
+ foreach( _file ${ARGN} )
+ if( ${_file} MATCHES ".*\\.py[x]?$" )
+ list( APPEND pyx_module_sources ${_file} )
+ else()
+ list( APPEND other_module_sources ${_file} )
+ endif()
+ endforeach()
+ compile_pyx( ${_name} generated_file ${pyx_module_sources} )
+ include_directories( ${PYTHON_INCLUDE_DIRS} )
+ python_add_module( ${_name} ${generated_file} ${other_module_sources} )
+ target_link_libraries( ${_name} ${PYTHON_LIBRARIES} )
+endfunction()
+
+include( CMakeParseArguments )
+# cython_add_standalone_executable( _name [MAIN_MODULE src3.py] src1 src2 ... srcN )
+# Creates a standalone executable the given sources.
+function( cython_add_standalone_executable _name )
+ set( pyx_module_sources "" )
+ set( other_module_sources "" )
+ set( main_module "" )
+ cmake_parse_arguments( cython_arguments "" "MAIN_MODULE" "" ${ARGN} )
+ include_directories( ${PYTHON_INCLUDE_DIRS} )
+ foreach( _file ${cython_arguments_UNPARSED_ARGUMENTS} )
+ if( ${_file} MATCHES ".*\\.py[x]?$" )
+ get_filename_component( _file_we ${_file} NAME_WE )
+ if( "${_file_we}" STREQUAL "${_name}" )
+ set( main_module "${_file}" )
+ elseif( NOT "${_file}" STREQUAL "${cython_arguments_MAIN_MODULE}" )
+ set( PYTHON_MODULE_${_file_we}_static_BUILD_SHARED OFF )
+ compile_pyx( "${_file_we}_static" generated_file "${_file}" )
+ list( APPEND pyx_module_sources "${generated_file}" )
+ endif()
+ else()
+ list( APPEND other_module_sources ${_file} )
+ endif()
+ endforeach()
+
+ if( cython_arguments_MAIN_MODULE )
+ set( main_module ${cython_arguments_MAIN_MODULE} )
+ endif()
+ if( NOT main_module )
+ message( FATAL_ERROR "main module not found." )
+ endif()
+ get_filename_component( main_module_we "${main_module}" NAME_WE )
+ set( CYTHON_FLAGS ${CYTHON_FLAGS} --embed )
+ compile_pyx( "${main_module_we}_static" generated_file ${main_module} )
+ add_executable( ${_name} ${generated_file} ${pyx_module_sources} ${other_module_sources} )
+ target_link_libraries( ${_name} ${PYTHON_LIBRARIES} ${pyx_module_libs} )
+endfunction()
diff --git a/src/3rdparty/2geom/COPYING-LGPL-2.1 b/src/3rdparty/2geom/COPYING-LGPL-2.1
new file mode 100644
index 0000000..b124cf5
--- /dev/null
+++ b/src/3rdparty/2geom/COPYING-LGPL-2.1
@@ -0,0 +1,510 @@
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations
+below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes a de-facto standard. To achieve this, non-free programs must
+be allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control
+compilation and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at least
+ three years, to give the same user the materials specified in
+ Subsection 6a, above, for a charge no more than the cost of
+ performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply, and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License
+may add an explicit geographical distribution limitation excluding those
+countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms
+of the ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library.
+It is safest to attach them to the start of each source file to most
+effectively convey the exclusion of warranty; and each file should
+have at least the "copyright" line and a pointer to where the full
+notice is found.
+
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or
+your school, if any, to sign a "copyright disclaimer" for the library,
+if necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James
+ Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/src/3rdparty/2geom/COPYING-MPL-1.1 b/src/3rdparty/2geom/COPYING-MPL-1.1
new file mode 100644
index 0000000..7714141
--- /dev/null
+++ b/src/3rdparty/2geom/COPYING-MPL-1.1
@@ -0,0 +1,470 @@
+ MOZILLA PUBLIC LICENSE
+ Version 1.1
+
+ ---------------
+
+1. Definitions.
+
+ 1.0.1. "Commercial Use" means distribution or otherwise making the
+ Covered Code available to a third party.
+
+ 1.1. "Contributor" means each entity that creates or contributes to
+ the creation of Modifications.
+
+ 1.2. "Contributor Version" means the combination of the Original
+ Code, prior Modifications used by a Contributor, and the Modifications
+ made by that particular Contributor.
+
+ 1.3. "Covered Code" means the Original Code or Modifications or the
+ combination of the Original Code and Modifications, in each case
+ including portions thereof.
+
+ 1.4. "Electronic Distribution Mechanism" means a mechanism generally
+ accepted in the software development community for the electronic
+ transfer of data.
+
+ 1.5. "Executable" means Covered Code in any form other than Source
+ Code.
+
+ 1.6. "Initial Developer" means the individual or entity identified
+ as the Initial Developer in the Source Code notice required by Exhibit
+ A.
+
+ 1.7. "Larger Work" means a work which combines Covered Code or
+ portions thereof with code not governed by the terms of this License.
+
+ 1.8. "License" means this document.
+
+ 1.8.1. "Licensable" means having the right to grant, to the maximum
+ extent possible, whether at the time of the initial grant or
+ subsequently acquired, any and all of the rights conveyed herein.
+
+ 1.9. "Modifications" means any addition to or deletion from the
+ substance or structure of either the Original Code or any previous
+ Modifications. When Covered Code is released as a series of files, a
+ Modification is:
+ A. Any addition to or deletion from the contents of a file
+ containing Original Code or previous Modifications.
+
+ B. Any new file that contains any part of the Original Code or
+ previous Modifications.
+
+ 1.10. "Original Code" means Source Code of computer software code
+ which is described in the Source Code notice required by Exhibit A as
+ Original Code, and which, at the time of its release under this
+ License is not already Covered Code governed by this License.
+
+ 1.10.1. "Patent Claims" means any patent claim(s), now owned or
+ hereafter acquired, including without limitation, method, process,
+ and apparatus claims, in any patent Licensable by grantor.
+
+ 1.11. "Source Code" means the preferred form of the Covered Code for
+ making modifications to it, including all modules it contains, plus
+ any associated interface definition files, scripts used to control
+ compilation and installation of an Executable, or source code
+ differential comparisons against either the Original Code or another
+ well known, available Covered Code of the Contributor's choice. The
+ Source Code can be in a compressed or archival form, provided the
+ appropriate decompression or de-archiving software is widely available
+ for no charge.
+
+ 1.12. "You" (or "Your") means an individual or a legal entity
+ exercising rights under, and complying with all of the terms of, this
+ License or a future version of this License issued under Section 6.1.
+ For legal entities, "You" includes any entity which controls, is
+ controlled by, or is under common control with You. For purposes of
+ this definition, "control" means (a) the power, direct or indirect,
+ to cause the direction or management of such entity, whether by
+ contract or otherwise, or (b) ownership of more than fifty percent
+ (50%) of the outstanding shares or beneficial ownership of such
+ entity.
+
+2. Source Code License.
+
+ 2.1. The Initial Developer Grant.
+ The Initial Developer hereby grants You a world-wide, royalty-free,
+ non-exclusive license, subject to third party intellectual property
+ claims:
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Initial Developer to use, reproduce,
+ modify, display, perform, sublicense and distribute the Original
+ Code (or portions thereof) with or without Modifications, and/or
+ as part of a Larger Work; and
+
+ (b) under Patents Claims infringed by the making, using or
+ selling of Original Code, to make, have made, use, practice,
+ sell, and offer for sale, and/or otherwise dispose of the
+ Original Code (or portions thereof).
+
+ (c) the licenses granted in this Section 2.1(a) and (b) are
+ effective on the date Initial Developer first distributes
+ Original Code under the terms of this License.
+
+ (d) Notwithstanding Section 2.1(b) above, no patent license is
+ granted: 1) for code that You delete from the Original Code; 2)
+ separate from the Original Code; or 3) for infringements caused
+ by: i) the modification of the Original Code or ii) the
+ combination of the Original Code with other software or devices.
+
+ 2.2. Contributor Grant.
+ Subject to third party intellectual property claims, each Contributor
+ hereby grants You a world-wide, royalty-free, non-exclusive license
+
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Contributor, to use, reproduce, modify,
+ display, perform, sublicense and distribute the Modifications
+ created by such Contributor (or portions thereof) either on an
+ unmodified basis, with other Modifications, as Covered Code
+ and/or as part of a Larger Work; and
+
+ (b) under Patent Claims infringed by the making, using, or
+ selling of Modifications made by that Contributor either alone
+ and/or in combination with its Contributor Version (or portions
+ of such combination), to make, use, sell, offer for sale, have
+ made, and/or otherwise dispose of: 1) Modifications made by that
+ Contributor (or portions thereof); and 2) the combination of
+ Modifications made by that Contributor with its Contributor
+ Version (or portions of such combination).
+
+ (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
+ effective on the date Contributor first makes Commercial Use of
+ the Covered Code.
+
+ (d) Notwithstanding Section 2.2(b) above, no patent license is
+ granted: 1) for any code that Contributor has deleted from the
+ Contributor Version; 2) separate from the Contributor Version;
+ 3) for infringements caused by: i) third party modifications of
+ Contributor Version or ii) the combination of Modifications made
+ by that Contributor with other software (except as part of the
+ Contributor Version) or other devices; or 4) under Patent Claims
+ infringed by Covered Code in the absence of Modifications made by
+ that Contributor.
+
+3. Distribution Obligations.
+
+ 3.1. Application of License.
+ The Modifications which You create or to which You contribute are
+ governed by the terms of this License, including without limitation
+ Section 2.2. The Source Code version of Covered Code may be
+ distributed only under the terms of this License or a future version
+ of this License released under Section 6.1, and You must include a
+ copy of this License with every copy of the Source Code You
+ distribute. You may not offer or impose any terms on any Source Code
+ version that alters or restricts the applicable version of this
+ License or the recipients' rights hereunder. However, You may include
+ an additional document offering the additional rights described in
+ Section 3.5.
+
+ 3.2. Availability of Source Code.
+ Any Modification which You create or to which You contribute must be
+ made available in Source Code form under the terms of this License
+ either on the same media as an Executable version or via an accepted
+ Electronic Distribution Mechanism to anyone to whom you made an
+ Executable version available; and if made available via Electronic
+ Distribution Mechanism, must remain available for at least twelve (12)
+ months after the date it initially became available, or at least six
+ (6) months after a subsequent version of that particular Modification
+ has been made available to such recipients. You are responsible for
+ ensuring that the Source Code version remains available even if the
+ Electronic Distribution Mechanism is maintained by a third party.
+
+ 3.3. Description of Modifications.
+ You must cause all Covered Code to which You contribute to contain a
+ file documenting the changes You made to create that Covered Code and
+ the date of any change. You must include a prominent statement that
+ the Modification is derived, directly or indirectly, from Original
+ Code provided by the Initial Developer and including the name of the
+ Initial Developer in (a) the Source Code, and (b) in any notice in an
+ Executable version or related documentation in which You describe the
+ origin or ownership of the Covered Code.
+
+ 3.4. Intellectual Property Matters
+ (a) Third Party Claims.
+ If Contributor has knowledge that a license under a third party's
+ intellectual property rights is required to exercise the rights
+ granted by such Contributor under Sections 2.1 or 2.2,
+ Contributor must include a text file with the Source Code
+ distribution titled "LEGAL" which describes the claim and the
+ party making the claim in sufficient detail that a recipient will
+ know whom to contact. If Contributor obtains such knowledge after
+ the Modification is made available as described in Section 3.2,
+ Contributor shall promptly modify the LEGAL file in all copies
+ Contributor makes available thereafter and shall take other steps
+ (such as notifying appropriate mailing lists or newsgroups)
+ reasonably calculated to inform those who received the Covered
+ Code that new knowledge has been obtained.
+
+ (b) Contributor APIs.
+ If Contributor's Modifications include an application programming
+ interface and Contributor has knowledge of patent licenses which
+ are reasonably necessary to implement that API, Contributor must
+ also include this information in the LEGAL file.
+
+ (c) Representations.
+ Contributor represents that, except as disclosed pursuant to
+ Section 3.4(a) above, Contributor believes that Contributor's
+ Modifications are Contributor's original creation(s) and/or
+ Contributor has sufficient rights to grant the rights conveyed by
+ this License.
+
+ 3.5. Required Notices.
+ You must duplicate the notice in Exhibit A in each file of the Source
+ Code. If it is not possible to put such notice in a particular Source
+ Code file due to its structure, then You must include such notice in a
+ location (such as a relevant directory) where a user would be likely
+ to look for such a notice. If You created one or more Modification(s)
+ You may add your name as a Contributor to the notice described in
+ Exhibit A. You must also duplicate this License in any documentation
+ for the Source Code where You describe recipients' rights or ownership
+ rights relating to Covered Code. You may choose to offer, and to
+ charge a fee for, warranty, support, indemnity or liability
+ obligations to one or more recipients of Covered Code. However, You
+ may do so only on Your own behalf, and not on behalf of the Initial
+ Developer or any Contributor. You must make it absolutely clear than
+ any such warranty, support, indemnity or liability obligation is
+ offered by You alone, and You hereby agree to indemnify the Initial
+ Developer and every Contributor for any liability incurred by the
+ Initial Developer or such Contributor as a result of warranty,
+ support, indemnity or liability terms You offer.
+
+ 3.6. Distribution of Executable Versions.
+ You may distribute Covered Code in Executable form only if the
+ requirements of Section 3.1-3.5 have been met for that Covered Code,
+ and if You include a notice stating that the Source Code version of
+ the Covered Code is available under the terms of this License,
+ including a description of how and where You have fulfilled the
+ obligations of Section 3.2. The notice must be conspicuously included
+ in any notice in an Executable version, related documentation or
+ collateral in which You describe recipients' rights relating to the
+ Covered Code. You may distribute the Executable version of Covered
+ Code or ownership rights under a license of Your choice, which may
+ contain terms different from this License, provided that You are in
+ compliance with the terms of this License and that the license for the
+ Executable version does not attempt to limit or alter the recipient's
+ rights in the Source Code version from the rights set forth in this
+ License. If You distribute the Executable version under a different
+ license You must make it absolutely clear that any terms which differ
+ from this License are offered by You alone, not by the Initial
+ Developer or any Contributor. You hereby agree to indemnify the
+ Initial Developer and every Contributor for any liability incurred by
+ the Initial Developer or such Contributor as a result of any such
+ terms You offer.
+
+ 3.7. Larger Works.
+ You may create a Larger Work by combining Covered Code with other code
+ not governed by the terms of this License and distribute the Larger
+ Work as a single product. In such a case, You must make sure the
+ requirements of this License are fulfilled for the Covered Code.
+
+4. Inability to Comply Due to Statute or Regulation.
+
+ If it is impossible for You to comply with any of the terms of this
+ License with respect to some or all of the Covered Code due to
+ statute, judicial order, or regulation then You must: (a) comply with
+ the terms of this License to the maximum extent possible; and (b)
+ describe the limitations and the code they affect. Such description
+ must be included in the LEGAL file described in Section 3.4 and must
+ be included with all distributions of the Source Code. Except to the
+ extent prohibited by statute or regulation, such description must be
+ sufficiently detailed for a recipient of ordinary skill to be able to
+ understand it.
+
+5. Application of this License.
+
+ This License applies to code to which the Initial Developer has
+ attached the notice in Exhibit A and to related Covered Code.
+
+6. Versions of the License.
+
+ 6.1. New Versions.
+ Netscape Communications Corporation ("Netscape") may publish revised
+ and/or new versions of the License from time to time. Each version
+ will be given a distinguishing version number.
+
+ 6.2. Effect of New Versions.
+ Once Covered Code has been published under a particular version of the
+ License, You may always continue to use it under the terms of that
+ version. You may also choose to use such Covered Code under the terms
+ of any subsequent version of the License published by Netscape. No one
+ other than Netscape has the right to modify the terms applicable to
+ Covered Code created under this License.
+
+ 6.3. Derivative Works.
+ If You create or use a modified version of this License (which you may
+ only do in order to apply it to code which is not already Covered Code
+ governed by this License), You must (a) rename Your license so that
+ the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
+ "MPL", "NPL" or any confusingly similar phrase do not appear in your
+ license (except to note that your license differs from this License)
+ and (b) otherwise make it clear that Your version of the license
+ contains terms which differ from the Mozilla Public License and
+ Netscape Public License. (Filling in the name of the Initial
+ Developer, Original Code or Contributor in the notice described in
+ Exhibit A shall not of themselves be deemed to be modifications of
+ this License.)
+
+7. DISCLAIMER OF WARRANTY.
+
+ COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
+ DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
+ THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
+ IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
+ YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
+ COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
+ OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
+ ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+8. TERMINATION.
+
+ 8.1. This License and the rights granted hereunder will terminate
+ automatically if You fail to comply with terms herein and fail to cure
+ such breach within 30 days of becoming aware of the breach. All
+ sublicenses to the Covered Code which are properly granted shall
+ survive any termination of this License. Provisions which, by their
+ nature, must remain in effect beyond the termination of this License
+ shall survive.
+
+ 8.2. If You initiate litigation by asserting a patent infringement
+ claim (excluding declatory judgment actions) against Initial Developer
+ or a Contributor (the Initial Developer or Contributor against whom
+ You file such action is referred to as "Participant") alleging that:
+
+ (a) such Participant's Contributor Version directly or indirectly
+ infringes any patent, then any and all rights granted by such
+ Participant to You under Sections 2.1 and/or 2.2 of this License
+ shall, upon 60 days notice from Participant terminate prospectively,
+ unless if within 60 days after receipt of notice You either: (i)
+ agree in writing to pay Participant a mutually agreeable reasonable
+ royalty for Your past and future use of Modifications made by such
+ Participant, or (ii) withdraw Your litigation claim with respect to
+ the Contributor Version against such Participant. If within 60 days
+ of notice, a reasonable royalty and payment arrangement are not
+ mutually agreed upon in writing by the parties or the litigation claim
+ is not withdrawn, the rights granted by Participant to You under
+ Sections 2.1 and/or 2.2 automatically terminate at the expiration of
+ the 60 day notice period specified above.
+
+ (b) any software, hardware, or device, other than such Participant's
+ Contributor Version, directly or indirectly infringes any patent, then
+ any rights granted to You by such Participant under Sections 2.1(b)
+ and 2.2(b) are revoked effective as of the date You first made, used,
+ sold, distributed, or had made, Modifications made by that
+ Participant.
+
+ 8.3. If You assert a patent infringement claim against Participant
+ alleging that such Participant's Contributor Version directly or
+ indirectly infringes any patent where such claim is resolved (such as
+ by license or settlement) prior to the initiation of patent
+ infringement litigation, then the reasonable value of the licenses
+ granted by such Participant under Sections 2.1 or 2.2 shall be taken
+ into account in determining the amount or value of any payment or
+ license.
+
+ 8.4. In the event of termination under Sections 8.1 or 8.2 above,
+ all end user license agreements (excluding distributors and resellers)
+ which have been validly granted by You or any distributor hereunder
+ prior to termination shall survive termination.
+
+9. LIMITATION OF LIABILITY.
+
+ UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+ (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
+ DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
+ OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
+ ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+ CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
+ WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+ COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+ INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
+ LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+ RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
+ PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+ EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
+ THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+10. U.S. GOVERNMENT END USERS.
+
+ The Covered Code is a "commercial item," as that term is defined in
+ 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+ software" and "commercial computer software documentation," as such
+ terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
+ C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
+ all U.S. Government End Users acquire Covered Code with only those
+ rights set forth herein.
+
+11. MISCELLANEOUS.
+
+ This License represents the complete agreement concerning subject
+ matter hereof. If any provision of this License is held to be
+ unenforceable, such provision shall be reformed only to the extent
+ necessary to make it enforceable. This License shall be governed by
+ California law provisions (except to the extent applicable law, if
+ any, provides otherwise), excluding its conflict-of-law provisions.
+ With respect to disputes in which at least one party is a citizen of,
+ or an entity chartered or registered to do business in the United
+ States of America, any litigation relating to this License shall be
+ subject to the jurisdiction of the Federal Courts of the Northern
+ District of California, with venue lying in Santa Clara County,
+ California, with the losing party responsible for costs, including
+ without limitation, court costs and reasonable attorneys' fees and
+ expenses. The application of the United Nations Convention on
+ Contracts for the International Sale of Goods is expressly excluded.
+ Any law or regulation which provides that the language of a contract
+ shall be construed against the drafter shall not apply to this
+ License.
+
+12. RESPONSIBILITY FOR CLAIMS.
+
+ As between Initial Developer and the Contributors, each party is
+ responsible for claims and damages arising, directly or indirectly,
+ out of its utilization of rights under this License and You agree to
+ work with Initial Developer and Contributors to distribute such
+ responsibility on an equitable basis. Nothing herein is intended or
+ shall be deemed to constitute any admission of liability.
+
+13. MULTIPLE-LICENSED CODE.
+
+ Initial Developer may designate portions of the Covered Code as
+ "Multiple-Licensed". "Multiple-Licensed" means that the Initial
+ Developer permits you to utilize portions of the Covered Code under
+ Your choice of the NPL or the alternative licenses, if any, specified
+ by the Initial Developer in the file described in Exhibit A.
+
+EXHIBIT A -Mozilla Public License.
+
+ ``The contents of this file are subject to the Mozilla Public License
+ Version 1.1 (the "License"); you may not use this file except in
+ compliance with the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ License for the specific language governing rights and limitations
+ under the License.
+
+ The Original Code is ______________________________________.
+
+ The Initial Developer of the Original Code is ________________________.
+ Portions created by ______________________ are Copyright (C) ______
+ _______________________. All Rights Reserved.
+
+ Contributor(s): ______________________________________.
+
+ Alternatively, the contents of this file may be used under the terms
+ of the _____ license (the "[___] License"), in which case the
+ provisions of [______] License are applicable instead of those
+ above. If you wish to allow use of your version of this file only
+ under the terms of the [____] License and not to allow others to use
+ your version of this file under the MPL, indicate your decision by
+ deleting the provisions above and replace them with the notice and
+ other provisions required by the [___] License. If you do not delete
+ the provisions above, a recipient may use your version of this file
+ under either the MPL or the [___] License."
+
+ [NOTE: The text of this Exhibit A may differ slightly from the text of
+ the notices in the Source Code files of the Original Code. You should
+ use the text of this Exhibit A rather than the text found in the
+ Original Code Source Code for Your Modifications.]
+
diff --git a/src/3rdparty/2geom/Doxyfile b/src/3rdparty/2geom/Doxyfile
new file mode 100644
index 0000000..5fa12d1
--- /dev/null
+++ b/src/3rdparty/2geom/Doxyfile
@@ -0,0 +1,2355 @@
+# Doxyfile 1.8.8
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = lib2geom
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+#ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = NO
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = YES
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = NO
+
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = YES
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = NO
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE = doxygen_warnings.log
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = src/2geom
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS = *.cpp \
+ *.h \
+ *.rl \
+ *.py
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE = src/2geom/toys/* \
+ src/2geom/tests/*
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = YES
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH = src/2geom/toys
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH = doc/media
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = NO
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# compiled with the --with-libclang option.
+# The default value is: NO.
+
+#CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+#CLANG_OPTIONS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra stylesheet files is of importance (e.g. the last
+# stylesheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET = doc/extradoxygen.css
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES = amsmath \
+ amssymb
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty string,
+# for the replacement values of the other commands the user is referred to
+# HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+#MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+#DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED = DOXYGEN_SHOULD_SKIP_THIS
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+# DOT_FONTNAME = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+#PLANTUML_JAR_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
diff --git a/src/3rdparty/2geom/HACKING.md b/src/3rdparty/2geom/HACKING.md
new file mode 100644
index 0000000..198b14a
--- /dev/null
+++ b/src/3rdparty/2geom/HACKING.md
@@ -0,0 +1,53 @@
+# Mailing list
+Communication about this project occurs on the lib2geom
+[mailing list](https://lists.sourceforge.net/lists/listinfo/lib2geom-devel).
+
+
+# Help Wanted
+We greatly appreciate contributions. You don't need to be a `math-whiz` or
+`über-hacker` (though these are definitely appreciated :) ) to help. The tasks
+of code cleanup, consistency, testing, documentation, and toys mostly just
+require perseverance, and benefit the project greatly.
+
+As far as very specialized skill, we are always in need of mathy people, even if
+it is just for their insight on problems and techniques (as opposed to coding).
+
+# Coding Style
+Please refer to the
+[Coding Style Guidelines](http://www.inkscape.org/doc/coding_style.php)
+if you have specific questions on the style to use for code. If reading style
+guidelines doesn't interest you, just follow the general style of the
+surrounding code, so that it is at least internally consistent.
+
+# Compiling
+For Windows instructions, see [README.win32.md](README.win32.md)
+
+For Debian-like platforms, the following packages are required:
+ - cairo v1.1.7 or later (Debian package libcairo2-dev)
+ - cmake
+ - make
+ - libboost-dev
+ - libgsl0-dev (though eventually it will only be required in tests)
+ - refblas3* on dapper
+
+To compile, use
+```bash
+cmake .
+Make
+```
+
+If you have problems, just ask on the mailing list.
+
+# Running tests
+For Debian-like platforms, after compiling lib2geom, issue this command line
+```bash
+make test
+```
+
+# Adding a unit test
+Make sure you write it using GTest syntax - look at e.g.
+[src/tests/affine-test.cpp](src/tests/affine-test.cpp).
+
+To add the test to the build, add the test to
+[src/tests/CMakeLists.txt](src/tests/CMakeLists.txt) in under
+`SET(2GEOM_GTESTS_SRC)`.
diff --git a/src/3rdparty/2geom/LICENSE.md b/src/3rdparty/2geom/LICENSE.md
new file mode 100644
index 0000000..3e725ab
--- /dev/null
+++ b/src/3rdparty/2geom/LICENSE.md
@@ -0,0 +1,16 @@
+lib2geom is free software.
+
+Every source file in the implementation of lib2geom is available to be
+redistributed and/or modified under the terms of either the GNU Lesser
+General Public License (LGPL) version 2.1 or the Mozilla Public
+License (MPL) version 1.1. Some files may be available under more
+liberal terms, but we believe that in all cases, each file may be used
+under either the LGPL or the MPL.
+
+See the following files in this directory for the precise terms and
+conditions of either license:
+ - [COPYING-LGPL-2.1](COPYING-LGPL-2.1)
+ - [COPYING-MPL-1.1](COPYING-MPL-1.1)
+
+Please see each file in the implementation for Copyright and licensing
+information.
diff --git a/src/3rdparty/2geom/NEWS.md b/src/3rdparty/2geom/NEWS.md
new file mode 100644
index 0000000..4d3ccb9
--- /dev/null
+++ b/src/3rdparty/2geom/NEWS.md
@@ -0,0 +1,45 @@
+lib2geom v1.1.0
+===============
+
+2Geom v1.1 is not ABI compatible with v1.0, it switches from
+`boost::optional` to `std::optional`.
+
+Changes:
+
+- Add `Geom::Parallelogram`
+- Add `Geom::PathIteratorSink::inPath()`
+- Add `Geom::are_near_rel()` for `Geom::Point`
+- Move headers to `include` directory
+- Make build system git submodule friendly
+- Fix Python 3 support (py2geom)
+- Remove Python 2 support (py2geom)
+
+
+lib2geom v1.0.0
+===============
+
+2geom is a C++ library of mathematics for paths, curves, and other
+geometric calculations, designed to be well suited for vector graphics:
+Bézier curves, conics, paths, intersections, transformations, and basic
+geometries.
+
+Originally developed to restructure and improve path data structures in
+Inkscape, this library's codebase has been maintained and shipped as
+part of the professional vector graphics software for over a decade.
+
+The major contributors to the 2geom library are Nathan Hurst, Michael
+G. Sloan, Krzysztof Kosiński, Johan B. C. Engelen, MenTaLguY, Aaron
+Spike, Marco Cechetti and JF Barraud.
+
+Work on this release has focused on updating the 2geom source control,
+build, test and packaging systems for both Linux and Windows. The py2geom
+python extension package has been restored and improvements have been
+made to overall code stabilization and quality.
+
+The primary motivation for 2geom's 1.0 release is to support a future
+Inkscape 1.0 launch.
+
+With this evolution to a distinct package, the 2geom team is seeking
+new opportunities to collaborate with individuals and projects
+interested in using this proven tool.
+
diff --git a/src/3rdparty/2geom/README.md b/src/3rdparty/2geom/README.md
new file mode 100644
index 0000000..a4444e6
--- /dev/null
+++ b/src/3rdparty/2geom/README.md
@@ -0,0 +1,123 @@
+# 2Geom: easy 2D graphics library
+
+## What is this?
+
+2Geom is a C++ 2D geometry library geared towards robust processing of
+computational geometry data associated with vector graphics. The primary
+design consideration is ease of use and clarity. It is dual-licensed
+under LGPL 2.1 and MPL 1.1.
+
+The library is descended from a set of geometric routines present in
+Inkscape, a vector graphics editor based around the Scalable Vector
+Graphics format, the most widespread vector graphics interchange format
+on the Web and a W3C Recommendation. Due to this legacy, not all parts
+of the API form a coherent whole (yet).
+
+Rendering is outside the scope of this library, and it is assumed
+something like libcairo or similar is employed for this. 2geom
+concentrates on higher level algorithms and geometric computations.
+
+
+## Features List
+
+* C++ 17
+* Functional programming style.
+* Points
+* Efficient affine transformations
+* Rectangles
+* Convex Hulls
+* Bounded error
+* General purpose paths:
+ + Exact elliptical arcs
+ + Area
+ + Centroid and bending moments
+* Path Locations:
+ + Determination of special spots (e.g. maximum curvature)
+ + Splitting
+ + Point, tangent, curvature at location
+ + Efficient arc length and inverse arc length
+* Path algebra:
+ + Computations such as offset curves can be written with their mathematical definition
+ and still get a bounded error, efficient curve. (preliminary trials indicate offset
+ done this way out performs the method used in Inkscape)
+* Arbitrary distortion (with bounded error):
+ + Mesh distorts
+ + Computational distorts such as the GIMP's 'vortex' plugin
+ + 3d mapping (perspective, flag, sphere)
+* Exact boolean ops (elliptic arcs remain elliptic arcs)
+* Efficient 2d database
+* Implicit function plotting
+* NURBs input and output
+* Tunable path simplification
+* PDoF constraint system for CAD/CAGD
+
+
+## Dependencies
+
+To build 2Geom, you will need:
+
+* C++ 17
+* [Boost](http://www.boost.org/) (headers only)
+* [glib](https://wiki.gnome.org/Projects/GLib)
+* [GNU Scientific Library](http://www.gnu.org/software/gsl/)
+* [double-conversion](https://github.com/google/double-conversion)
+* [cairo](https://www.cairographics.org/)
+* [Ragel](http://www.colm.net/open-source/ragel/) (if you want to modify the SVG path parser)
+* [GTK+ 2](http://www.gtk.org/) (for demo programs)
+
+
+## Building
+
+2Geom uses CMake as the build and configuration system. To build, type:
+
+ mkdir build && cd build
+ cmake ..
+ make
+
+To run tests and performance tests:
+
+ make test
+ make perf
+
+**Note**: Tests are disabled by default. To enable tests pass `-D2GEOM_TESTING=ON` to `cmake` command.
+
+Also check out some of the interactive programs in src/toys.
+
+Documentation is generated from source comments using Doxygen.
+Run `doxygen` in the project root to generate documentation in
+`doc/html`.
+
+
+## API / ABI Stability
+
+Version 1.0 of 2Geom marks its first official release. With this
+release the library's API/ABI is considered stable:
+
+ * All public APIs will not be renamed or have their parameters changed
+ without providing backwards-compatible aliases.
+
+ * New functionality added to these APIs will not change their meaning
+ or fundamental behaviors.
+
+ * If an API needs to be removed or replaced, it will be declared
+ deprecated but will remain in the API until the next major version.
+ Warnings will be issued when the deprecated method is called.
+
+ * We'll only break backwards compatibility of these APIs if a bug or
+ security hole makes it completely unavoidable.
+
+Improvements that would break the API/ABI will be noted in our bug
+tracker, for a future release.
+
+2Geom does not follow Semantic Versioning. Instead, version numbers
+match major Inkscape release versions.
+
+
+## Further information
+
+Communications related to 2Geom development happen on a
+[SourceForge mailing list](https://lists.sourceforge.net/lists/listinfo/lib2geom-devel).
+
+The primary user of 2Geom is [Inkscape](https://inkscape.org/en/).
+API-breaking changes to 2Geom will require corresponding changes to
+Inkscape.
diff --git a/src/3rdparty/2geom/README.win32.md b/src/3rdparty/2geom/README.win32.md
new file mode 100644
index 0000000..fc7a770
--- /dev/null
+++ b/src/3rdparty/2geom/README.win32.md
@@ -0,0 +1,56 @@
+# win32 instructions
+## Installation
+- Download the latest mingw, gsl, and gtk bundles from [http://inkscape.modevia.com/win32libs/?C=M;O=D](http://inkscape.modevia.com/win32libs/?C=M;O=D)
+- Also download Boost from SourceForge and unpack it in a directory of your choice (you specify it's path later on)
+- Obtain, compile and install Inkscape svn following these instructions http://inkscape.org/win32/win32buildnotes.html
+- unpackage the gsl bundle into the directory with the gtk bundle
+- download cmake; install at `C:\cmake`
+- check the directories in mingwenv.bat. Are they set correctly for you? (ignore RAGEL_BIN)
+- make a build directory
+- open cmd.exe
+ ```
+ mingwenv.bat
+ cmake -G "MinGW Makefiles" c:\path\to\2geom # be sure you have a CAPITAL '-G' there!
+ cmake -i # especially mind to set the install dir to where you want it installed (probably the gtk folder, e.g. c:/gtk210))
+ mingw32-make
+ ```
+- copy the resulting `.exe` files into the inkscape install directory
+
+If you want to be able to compile the ragel defined svg-parser as well,
+you must download ragel from [here](http://www.cs.queensu.ca/~thurston/ragel/)
+Unpack the windows binary package into a dir of your own choice.
+Check whether ragel's dir is set correctly in mingwenv.bat (RAGEL_BIN).
+Make sure you have ragel.exe and rlcodegen.exe in the dir you specify.
+If your package does not contain rlcodegen.exe you can copy rlgen-cd.exe
+and rename it to rlcodegen.exe :-)
+
+## PYTHON BINDINGS
+To install python bindings, you need python2 and cython(>=0.16). Get cython from
+[http://www.lfd.uci.edu/~gohlke/pythonlibs/#cython](http://www.lfd.uci.edu/~gohlke/pythonlibs/#cython)
+and install it to `$PYTHON_PATH\Libs\site-packages`
+32-bit version is your safest bet.
+cmake should be able to find cython now. Make sure that `PYTHON_PATH` is set
+correctly to python2 in mingwenv.bat.
+
+Continue with installation as described above. When running "cmake -i",
+remember to choose to build cython bindings and also lib2geom as a
+shared library!
+
+If you get errors about missing DLL file, try copying lib2geom.dll to
+cython-bindings directory.
+
+Note: If you have both python2 and python3 installed, make sure cmake uses
+python2. To ensure this, choose "advanced options" when running "cmake -i",
+scroll and set PYTHON_INCLUDE_DIR and PYTHON_LIBRARY accordingly.
+
+## TROUBLESHOOTING
+If things don't work out, here is a list of things you can try.
+Type `make --version`. It should display:
+```
+E:\inkscapelpe>mingw32-make --version
+GNU Make 3.80
+Copyright (C) 2002 Free Software Foundation, Inc.
+```
+Or something very similar. If it does not, probably windows finds a different
+make (Borland's or another?). Type `set path=`, then start again with
+`mingwenv.bat` etc...
diff --git a/src/3rdparty/2geom/RELEASING.md b/src/3rdparty/2geom/RELEASING.md
new file mode 100644
index 0000000..33a9b24
--- /dev/null
+++ b/src/3rdparty/2geom/RELEASING.md
@@ -0,0 +1,21 @@
+# REALISING
+Add a release note to `NEWS.md`.
+
+Set `2GEOM_MAJOR_VERSION`, `2GEOM_MINOR_VERSION`, and `2GEOM_PATCH_VERSION` in
+*CMakeLists.txt*.
+
+```bash
+cmake .
+make
+make test
+make dist
+```
+
+Next, copy `lib2geom-${VERSION}.tar.bz2` to `/tmp/``, extract it, and verify
+it builds.
+
+```bash
+gpg --armor --detach-sign --output lib2geom-${VERSION}.tar.bz2.sig lib2geom-${VERSION}.tar.bz2
+git tag -s ${MAJOR}.${MINOR}
+git push --tags
+```
diff --git a/src/3rdparty/2geom/TODO.md b/src/3rdparty/2geom/TODO.md
new file mode 100644
index 0000000..697a044
--- /dev/null
+++ b/src/3rdparty/2geom/TODO.md
@@ -0,0 +1,85 @@
+# Code Health:
+ - Rewrite old tests using Google Test Framework.
+ - Add more unit tests. Ideally, every method should be tested.
+ - More Doxygen documentation. Document algorithms used to implement each
+ nontrivial method, preferably with pictures.
+ - Coding style.
+ - Rewrite or remove old junk.
+
+# Primitives:
+ - Add uniform points - Geom::UPoint.
+ - Add projective transformations - Geom::Projective.
+ - Add rational Bezier fragments / curves - Geom::D2U<Bezier>
+
+# Shapes:
+ - Geom::Triangle
+ - Geom::Quad
+ - Geom::Polygon
+ - Function that computes an Affine that maps between triangles.
+ - Function that maps between Rects.
+ - Function that maps between Ellipses (no skew).
+
+# Path / PathVector:
+ - Built in support for arc length parametrization, computed on demand.
+ - Boolean operations accessible via operators: &, |, / (or -), ^
+ - Uncrossing.
+ - Conversion from nonzero winding rule to even-odd winding rule.
+ - Dashing - requires arc length parametrization.
+ - Offset.
+ - Stroke-to-path.
+ - Minkowski sum.
+ - Functions to facilitate node editing without conversion to a node list.
+ - Approximation of arbitrary paths with cubic Beziers, quadratic Beziers
+ or line segments, available as a path sink.
+ - Approximation by lines and circular / elliptical arcs.
+ - Support for per-node and per-segment user data?
+
+# Fragments:
+ - Convert all uses of std::vector<Point> to D2<Bezier> where applicable.
+ - Consider adding push_back() for incremental building of Beziers.
+ - Implement Bezier versions of SBasis methods.
+
+# Toys:
+ - Better Bezier / SBasis handles.
+ - Use GTK 3 to provide widgets such as checkboxes and buttons (?)
+
+# Other:
+ - sweeper.h: add variants of Sweeper that accept void Item
+ and add a version that does sweepline over two lists rather
+ than one.
+ - Rewrite conic section code to match coding style.
+ - Rewrite QuadTree and RTree to make them actually usable.
+ - BSP tree.
+ - Interval tree - Geom::IntervalSet, Geom::IntervalMap<T>
+ - Geom::MultiInterval
+ - Using the above, add regions, as seen in Cairo.
+ - Add some basic 3D functionality, enough to draw a 3D box.
+ - Write GDB pretty printers for all core classes. See the directory "tools"
+ - Clothoid support (clothoids where the curvature is a not-necessarily linear
+ function, perhaps piecewise SBasis, add fitting)
+ - Special geometric shapes (stuff like circles, oriented rectangles, spirals,
+ triangles, regular polygons, inkscape-like polygons, etc)
+ - Constraint system for advanced handle stuff
+ - complete and tidy up intersection apis
+ - complete offset implementation: at this stage only the hard part has been
+ implemented
+ - conic sections: we currently support line and ellipse from xAx form, add
+ parabola and hyperbola; intersection
+ - NURBS (2geom handles division approximation of polynomials, code just needs
+ to be added to convert between standard forms (say x/w, y/w in bernstein and
+ pw<d2<sb>>(t))
+ - T-mesh form for 2D (and higher?) piecewise polynomials
+ - enhance contour tracing algorithm (sb-2d-solver)
+ - transform an svg stroke in an outline (extends offset curve code to handle
+ SVG options)
+ - variable width curve tracing (variant on path along path idea)
+ - collinear tangent (find a line that smoothly connects two curves); extension
+ of bezier clipping idea
+ - transform a path into a single curve (fitting) - improvements required
+ - exploiting modern architecture features (cache coherence, multi-core, packet
+ instruction set, gpgpu)
+ - finish boolops (use faster and more robust sweep-window algorithm, add
+ support for dB @ dB, dB @ B, B @ B where @ is any of the 16 boolean operators
+ that make sense)
+ - bucket fill (variant of bool ops for bucket filling)
+ - path topology and numerical soundness graph
diff --git a/src/3rdparty/2geom/_clang-format b/src/3rdparty/2geom/_clang-format
new file mode 100644
index 0000000..ce33080
--- /dev/null
+++ b/src/3rdparty/2geom/_clang-format
@@ -0,0 +1,53 @@
+---
+# SPDX-License-Identifier: GPL-2.0-or-later
+# BasedOnStyle: LLVM
+AccessModifierOffset: -2
+ConstructorInitializerIndentWidth: 4
+AlignEscapedNewlinesLeft: false
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: true
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: All
+AlwaysBreakTemplateDeclarations: true
+AlwaysBreakBeforeMultilineStrings: false
+BreakBeforeBinaryOperators: false
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: true
+BinPackParameters: true
+ColumnLimit: 120
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+DerivePointerBinding: false
+ExperimentalAutoDetectBinPacking: false
+IndentCaseLabels: true
+MaxEmptyLinesToKeep: 3
+KeepEmptyLinesAtTheStartOfBlocks: true
+NamespaceIndentation: None
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 60
+PenaltyBreakString: 1000
+PenaltyBreakFirstLessLess: 120
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 60
+PointerBindsToType: false
+SpacesBeforeTrailingComments: 1
+Cpp11BracedListStyle: false
+Standard: Cpp11
+IndentWidth: 4
+TabWidth: 4
+UseTab: Never
+BreakBeforeBraces: WebKit
+IndentFunctionDeclarationAfterType: false
+SpacesInParentheses: false
+SpacesInAngles: false
+SpaceInEmptyParentheses: false
+SpacesInCStyleCastParentheses: false
+SpacesInContainerLiterals: true
+SpaceAfterControlStatementKeyword: true
+ContinuationIndentWidth: 4
+SpaceBeforeAssignmentOperators: true
+...
+
diff --git a/src/3rdparty/2geom/cmake_uninstall.cmake.in b/src/3rdparty/2geom/cmake_uninstall.cmake.in
new file mode 100644
index 0000000..cd2001a
--- /dev/null
+++ b/src/3rdparty/2geom/cmake_uninstall.cmake.in
@@ -0,0 +1,23 @@
+IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+ MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
+ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+
+FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
+STRING(REGEX REPLACE "\n" ";" files "${files}")
+FOREACH(file ${files})
+ MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
+ IF(EXISTS "$ENV{DESTDIR}${file}")
+ EXEC_PROGRAM(
+ "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
+ OUTPUT_VARIABLE rm_out
+ RETURN_VALUE rm_retval
+ )
+ IF("${rm_retval}" STREQUAL 0)
+ ELSE("${rm_retval}" STREQUAL 0)
+ MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
+ ENDIF("${rm_retval}" STREQUAL 0)
+ ELSE(EXISTS "$ENV{DESTDIR}${file}")
+ MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
+ ENDIF(EXISTS "$ENV{DESTDIR}${file}")
+ENDFOREACH(file)
+
diff --git a/src/3rdparty/2geom/doc/2geom-logo.svg b/src/3rdparty/2geom/doc/2geom-logo.svg
new file mode 100644
index 0000000..91a6dff
--- /dev/null
+++ b/src/3rdparty/2geom/doc/2geom-logo.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="113.27319mm"
+ height="113.59513mm"
+ viewBox="0 0 113.27319 113.59513"
+ version="1.1"
+ id="svg8"
+ inkscape:version="0.92.1 r15371"
+ sodipodi:docname="2geom-logo.svg"
+ inkscape:export-filename="/home/tweenkpl/2geom-logo.png"
+ inkscape:export-xdpi="111.80057"
+ inkscape:export-ydpi="111.80057">
+ <defs
+ id="defs2" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.4"
+ inkscape:cx="166.69098"
+ inkscape:cy="240.82631"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:object-paths="true"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:window-width="1722"
+ inkscape:window-height="1358"
+ inkscape:window-x="639"
+ inkscape:window-y="321"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-28.785322,-45.762063)">
+ <path
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:12.45454025;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ d="m 107.19276,55.400456 c -15.230149,0 -24.140387,9.013472 -24.140387,24.554437 0,0.621638 2.2e-4,1.45063 0.103836,2.590299 h 13.883015 v -2.383058 c 0,-8.184908 3.833366,-12.950644 10.464176,-12.950644 6.4236,0 10.36078,4.454975 10.36078,11.811032 0,8.081301 -2.58994,11.293214 -18.752545,22.793528 -12.432769,8.49573 -16.266387,15.02298 -16.991633,28.59542 h 37.554848 c -1.05021,4.0163 -4.60797,6.85313 -9.02421,6.85313 H 60.194912 c -5.284123,0 -9.344303,-4.0602 -9.344303,-9.34431 V 77.464994 c 0,-5.284125 4.060178,-9.342587 9.344303,-9.342587 h 22.70085 c 1.164171,-3.007917 2.822357,-5.632208 4.960058,-7.80351 1.913386,-1.943461 4.188188,-3.497369 6.76988,-4.651129 H 60.194912 c -11.968506,0 -21.798514,9.82872 -21.798514,21.797226 v 50.455296 c 0,11.96851 9.830003,21.79851 21.798514,21.79851 h 50.455728 c 11.96851,0 21.79679,-9.83 21.79679,-21.79851 V 117.4604 h -0.38916 -12.06548 -19.01641 c 1.86492,-3.93705 4.14415,-6.00893 14.91922,-13.88301 12.74359,-9.324584 16.47374,-14.919299 16.47374,-24.865515 0,-14.194083 -9.73922,-23.311419 -25.17658,-23.311419 z"
+ id="rect3680"
+ inkscape:connector-curvature="0" />
+ </g>
+</svg>
diff --git a/src/3rdparty/2geom/doc/Makefile b/src/3rdparty/2geom/doc/Makefile
new file mode 100644
index 0000000..c8ab4a1
--- /dev/null
+++ b/src/3rdparty/2geom/doc/Makefile
@@ -0,0 +1,6 @@
+all: manual.pdf
+
+manual.pdf: manual.tex
+ pdflatex manual.tex
+ bibtex manual
+ pdflatex manual.tex
diff --git a/src/3rdparty/2geom/doc/bezier-utils-work.txt b/src/3rdparty/2geom/doc/bezier-utils-work.txt
new file mode 100644
index 0000000..8604c12
--- /dev/null
+++ b/src/3rdparty/2geom/doc/bezier-utils-work.txt
@@ -0,0 +1,34 @@
+min .5 * sum_i lensq(bez_pt(b, u[i]) - d[i])
+
+lensq(d)=dot(d, d) = d.x * d.x + d.y * d.y
+
+sum_i (f(i) + g(i)) = sum_i f(i) + sum_i g(i), so
+we can separate into x,y parts. Since they are the same, we write `z' in the below
+to mean either x or y.
+
+.5 * sum_i (bez_pt(b, u[i]) - d[i]).z^2
+
+= .5 * sum_i (B0(u[i]) * b[0] +
+ B1(u[i]) * b[1] +
+ B2(u[i]) * b[2] +
+ B3(u[i]) * b[3]
+ - d[i] ).z^2
+
+= H.
+
+Suppose that b[0,1,3] are fixed (with b[1] perhaps being calculated
+from a prior call to existing generate_bezier).
+
+d H / d b[2].z = sum_i B2(u[i]) * (bez_pt(b, u[i]) - d[i]).z
+
+Solve for dH/db[2].z==0:
+
+-sum_i B2(u[i]) B2(u[i]) * b[2].z = sum_i B2(u[i]) * (B0(u[i]) * b[0] +
+ B1(u[i]) * b[1] +
+ B3(u[i]) * b[3]
+ - d[i] ).z
+b[2].z = ((sum_i B2(u[i]) * (B0(u[i]) * b[0] +
+ B1(u[i]) * b[1] +
+ B3(u[i]) * b[3]
+ - d[i] ).z)
+ / -sum_i (B2(u[i]))^2)
diff --git a/src/3rdparty/2geom/doc/boolops.svg b/src/3rdparty/2geom/doc/boolops.svg
new file mode 100644
index 0000000..093e03d
--- /dev/null
+++ b/src/3rdparty/2geom/doc/boolops.svg
@@ -0,0 +1,1622 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.45+devel"
+ sodipodi:docname="boolops.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Dot_m"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Dot_m"
+ style="overflow:visible">
+ <path
+ id="path13539"
+ d="M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;marker-end:none"
+ transform="scale(0.4) translate(7.4, 1)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Sstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Sstart"
+ style="overflow:visible">
+ <path
+ id="path5066"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.2) translate(6,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mend"
+ style="overflow:visible;">
+ <path
+ id="path5063"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.4) rotate(180) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Send"
+ style="overflow:visible;">
+ <path
+ id="path5069"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.2) rotate(180) translate(6,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lend"
+ style="overflow:visible;">
+ <path
+ id="path3301"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.8) rotate(180) translate(12.5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path3298"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.8) translate(12.5,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mstart"
+ style="overflow:visible">
+ <path
+ id="path3304"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.4) translate(10,0)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.7071068"
+ inkscape:cx="244.82275"
+ inkscape:cy="325.44392"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:window-width="787"
+ inkscape:window-height="1020"
+ inkscape:window-x="0"
+ inkscape:window-y="0">
+ <sodipodi:guide
+ orientation="vertical"
+ position="0"
+ id="guide2519" />
+ <sodipodi:guide
+ orientation="vertical"
+ position="745.29055"
+ id="guide2576" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ style="opacity:0.5070422;fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M -1144.3715,-909.29614 C -1130.7209,-908.95152 -1113.1883,-906.68446 -1101.5143,-895.01043 C -1092.3992,-885.89531 -1090.0857,-871.31959 -1090.0857,-857.86757 C -1090.0857,-841.37471 -1094.9013,-835.74816 -1098.6572,-820.72472 C -1101.8376,-808.00312 -1109.561,-796.05986 -1115.8,-783.58186 C -1120.9667,-773.24862 -1118.6572,-752.60685 -1118.6572,-737.86757 C -1118.6572,-718.79529 -1107.396,-706.6622 -1098.6572,-695.01043 C -1081.2138,-671.75256 -1051.4077,-665.67141 -1030.0857,-655.01043 C -980.56756,-630.25133 -908.25189,-608.68486 -850.08576,-589.29615 C -816.67987,-578.16085 -794.4911,-580.07024 -761.51433,-563.58186 C -744.30839,-554.97889 -730.76848,-550.8954 -712.9429,-546.439 C -689.48675,-540.57497 -678.27784,-533.29735 -661.51433,-520.72472 C -651.27578,-513.0458 -648.2704,-502.11376 -638.65719,-489.29615 C -628.79688,-476.14908 -639.1503,-457.37446 -647.22862,-449.29615 C -660.19555,-436.32921 -689.09109,-423.58186 -707.22862,-423.58186 C -730.23567,-423.58186 -747.34884,-420.20138 -770.08576,-429.29615 C -817.68916,-448.33751 -860.87437,-478.60664 -910.08576,-495.01043 C -943.48116,-506.14223 -974.84358,-524.21338 -1001.5143,-546.439 C -1037.7259,-576.61531 -1076.5889,-604.37076 -1104.3715,-632.15329 C -1112.8389,-640.62075 -1119.5019,-665.27125 -1124.3715,-675.01043 C -1130.8513,-687.97013 -1134.9167,-697.19129 -1138.6572,-712.15329 C -1142.8203,-728.80565 -1148.2285,-741.8673 -1152.9429,-760.72472 C -1156.5643,-775.21039 -1163.4566,-788.49393 -1167.2286,-803.58186 C -1170.3434,-816.04089 -1167.2286,-833.52054 -1167.2286,-846.439 C -1167.2286,-861.44208 -1175.315,-864.55186 -1167.2286,-880.72471 C -1159.9567,-895.26852 -1160.7884,-896.16257 -1144.3715,-909.29614 z"
+ id="path2987"
+ sodipodi:nodetypes="cssssssssssssssssssssssssc" />
+ <path
+ style="opacity:0.50568183;fill:#0000ff;fill-rule:evenodd;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M -799.91455,-681.43839 C -887.51109,-684.38249 -965.32915,-744.70237 -1012.0466,-814.77852 C -1038.3927,-854.29768 -983.70547,-970.38465 -951.43743,-994.58567 C -855.64892,-1066.4271 -765.09423,-1097.3837 -648.39167,-1039.0324 C -579.60284,-1004.638 -506.18771,-985.96939 -454.44238,-923.875 C -416.40934,-878.23535 -469.68766,-766.16722 -496.86879,-729.92571 C -548.70738,-660.80759 -618.25596,-598.60588 -711.02113,-598.60588 C -737.82948,-598.60588 -838.11897,-599.3314 -828.19883,-639.01198 C -825.17618,-651.10255 -815.62052,-655.63089 -810.01608,-661.23533 C -805.73975,-665.51166 -802.81768,-675.63214 -799.91455,-681.43839 z"
+ id="path2227" />
+ <path
+ style="opacity:0.50568183;fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M -672.63532,-422.83933 C -673.30876,-423.51276 -673.98219,-424.1862 -674.65563,-424.85963 C -678.92567,-429.12967 -708.38695,-517.35852 -711.02112,-527.89519 C -714.39367,-541.3854 -711.02112,-560.32707 -711.02112,-574.36221 C -711.02112,-585.19036 -693.37737,-605.96843 -686.77746,-614.76831 C -677.92264,-626.57474 -670.9646,-640.6827 -662.5338,-649.1135 C -654.50114,-657.14616 -641.38773,-664.50154 -630.20892,-667.29624 C -619.95785,-669.85901 -607.73876,-671.39856 -599.90434,-673.35716 C -590.05857,-675.8186 -579.73699,-673.34823 -571.62007,-675.37747 C -560.52166,-678.15207 -548.66015,-679.41808 -537.27488,-679.41808 C -529.26369,-679.41808 -515.01085,-681.95363 -508.99061,-683.45869 C -502.09255,-685.1832 -494.56272,-692.69294 -488.78756,-695.58052 C -481.41977,-699.26441 -476.18116,-704.63088 -472.62512,-711.74296 C -469.19797,-718.59725 -473.11806,-735.93806 -474.64542,-742.04753 C -477.11091,-751.90948 -484.23165,-759.71498 -488.78756,-764.27089 C -493.69612,-769.17945 -496.96676,-782.84555 -498.88909,-790.53486 C -501.80768,-802.20925 -504.0379,-812.366 -500.90939,-824.88004 C -497.34889,-839.12203 -479.38936,-843.04037 -468.58451,-851.14401 C -458.91681,-858.39478 -446.07286,-858.79222 -436.25963,-861.24553 C -424.5508,-864.17274 -416.44575,-863.46042 -407.97536,-859.22523 C -403.29877,-856.88694 -400.69319,-841.84153 -395.85353,-837.00187 C -391.6837,-832.83205 -385.37678,-817.31825 -383.7317,-810.73791 C -380.57044,-798.09287 -376.38375,-784.0997 -373.63017,-770.3318 C -371.10634,-757.71264 -380.57159,-744.32713 -385.752,-733.96631 C -391.88886,-721.6926 -400.6153,-710.95021 -405.95505,-697.60082 C -407.07357,-694.80453 -408.64879,-692.21334 -409.99566,-689.5196 C -417.6298,-674.25132 -412.39478,-665.23387 -403.93475,-651.1338 C -390.47687,-628.70401 -354.82679,-598.76211 -335.24437,-582.44343 C -325.74155,-574.52441 -323.73745,-560.65938 -321.10224,-550.11855 C -320.57124,-547.99456 -335.58282,-525.19799 -337.26468,-521.83428 C -350.61508,-495.13347 -366.16504,-464.64965 -387.77231,-443.04238 C -422.13187,-408.68282 -470.95732,-366.18266 -519.09214,-354.14891 C -532.84253,-350.71131 -544.7411,-350.10831 -559.49824,-350.10831 C -578.46057,-350.10831 -593.91201,-348.53321 -610.00587,-358.18957 C -620.56665,-364.52603 -625.34158,-376.73916 -630.20892,-386.47384 C -634.24368,-394.54336 -648.94253,-398.73339 -656.47288,-400.61597 C -669.0554,-403.7616 -680.82347,-406.46305 -672.63532,-422.83933 z"
+ id="path2808" />
+ <path
+ id="path2810"
+ d="M -1157.5085,-885.48919 C -1158.182,-886.16262 -1158.8554,-886.83606 -1159.5288,-887.50949 C -1163.7989,-891.77953 -1193.2602,-980.00838 -1195.8943,-990.54505 C -1199.2669,-1004.0353 -1195.8943,-1022.9769 -1195.8943,-1037.0121 C -1195.8943,-1047.8402 -1178.2506,-1068.6183 -1171.6507,-1077.4182 C -1162.7958,-1089.2246 -1155.8378,-1103.3326 -1147.407,-1111.7634 C -1139.3743,-1119.796 -1126.2609,-1127.1514 -1115.0821,-1129.9461 C -1104.8311,-1132.5089 -1092.612,-1134.0484 -1084.7776,-1136.007 C -1074.9318,-1138.4685 -1064.6102,-1135.9981 -1056.4933,-1138.0273 C -1045.3949,-1140.8019 -1033.5334,-1142.0679 -1022.1481,-1142.0679 C -1014.1369,-1142.0679 -999.88407,-1144.6035 -993.86383,-1146.1086 C -986.96577,-1147.8331 -979.43594,-1155.3428 -973.66078,-1158.2304 C -966.29299,-1161.9143 -961.05438,-1167.2807 -957.49834,-1174.3928 C -954.07119,-1181.2471 -957.99128,-1198.5879 -959.51864,-1204.6974 C -961.98413,-1214.5593 -969.10487,-1222.3649 -973.66078,-1226.9208 C -978.56934,-1231.8293 -981.83998,-1245.4954 -983.76231,-1253.1847 C -986.6809,-1264.8591 -988.91112,-1275.0159 -985.78261,-1287.5299 C -982.22211,-1301.7719 -964.26258,-1305.6902 -953.45773,-1313.7939 C -943.79003,-1321.0446 -930.94608,-1321.4421 -921.13285,-1323.8954 C -909.42401,-1326.8226 -901.31896,-1326.1103 -892.84857,-1321.8751 C -888.17198,-1319.5368 -885.5664,-1304.4914 -880.72674,-1299.6517 C -876.55691,-1295.4819 -870.24999,-1279.9681 -868.60491,-1273.3878 C -865.44365,-1260.7427 -861.25696,-1246.7496 -858.50338,-1232.9817 C -855.97955,-1220.3625 -865.4448,-1206.977 -870.62521,-1196.6162 C -876.76207,-1184.3425 -885.48851,-1173.6001 -890.82826,-1160.2507 C -891.94678,-1157.4544 -893.522,-1154.8632 -894.86887,-1152.1695 C -902.50301,-1136.9012 -897.26799,-1127.8837 -888.80796,-1113.7837 C -875.35008,-1091.3539 -839.7,-1061.412 -820.11758,-1045.0933 C -810.61476,-1037.1743 -808.61066,-1023.3092 -805.97545,-1012.7684 C -805.44445,-1010.6444 -820.45603,-987.84785 -822.13789,-984.48414 C -835.48829,-957.78333 -984.37839,-981.84775 -1005.9857,-960.24048 C -1040.3452,-925.88092 -955.83054,-828.83252 -1003.9654,-816.79877 C -1017.7157,-813.36117 -1029.6143,-812.75817 -1044.3715,-812.75817 C -1063.3338,-812.75817 -1078.7852,-811.18307 -1094.8791,-820.83943 C -1105.4399,-827.17589 -1110.2148,-839.38902 -1115.0821,-849.1237 C -1119.1169,-857.19322 -1133.8157,-861.38325 -1141.3461,-863.26583 C -1153.9286,-866.41146 -1165.6967,-869.11291 -1157.5085,-885.48919 z"
+ style="opacity:0.50568183;fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="csssssssssssssssssssssssssssssssssssc" />
+ <g
+ id="g2816"
+ transform="translate(-1113.6536,-1178.6859)">
+ <path
+ id="path2812"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ id="path2814" />
+ </g>
+ <g
+ transform="translate(-1252.4629,-1087.3029)"
+ id="g2820">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ id="path2822" />
+ <path
+ id="path2824"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ id="g2826"
+ transform="translate(-1290.1344,-934.47404)">
+ <path
+ id="path2828"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ id="path2830" />
+ </g>
+ <g
+ transform="translate(-976.86456,-717.58711)"
+ id="g2832">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ id="path2834" />
+ <path
+ id="path2836"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ id="g2838"
+ transform="translate(-817.28148,-798.99105)">
+ <path
+ id="path2840"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ id="path2842" />
+ </g>
+ <g
+ transform="translate(-758.91671,-873.3957)"
+ id="g2844">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ id="path2846" />
+ <path
+ id="path2848"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ transform="translate(-719.93919,-978.7982)"
+ id="g2850">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ id="path2852" />
+ <path
+ id="path2854"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ id="g2981"
+ transform="translate(-1285.32,-1020.1601)">
+ <path
+ id="path2983"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ id="path2985" />
+ </g>
+ <path
+ style="fill:#ff0000;fill-opacity:0.50588229;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M -921.13286,-295.5601 C -921.8063,-296.2335 -922.47973,-296.907 -923.15317,-297.5804 C -984.29068,-358.71794 -1016.0872,-423.42411 -1016.0872,-509.71245 C -1016.0872,-597.3637 -983.4151,-664.39202 -931.23439,-733.96631 C -865.35525,-821.80516 -815.84832,-922.08336 -737.2851,-1000.6466 C -693.29002,-1044.6417 -647.52402,-1120.4273 -628.18862,-1178.4334 C -613.76267,-1221.7113 -573.21021,-1251.8097 -549.39673,-1287.5299 C -536.11145,-1307.4578 -516.82915,-1316.0569 -500.9094,-1331.9766 C -488.49296,-1344.3931 -494.06725,-1302.7767 -496.86879,-1291.5705 C -501.74793,-1272.054 -496.97324,-1248.6219 -500.9094,-1228.9411 C -508.41847,-1191.3957 -530.38151,-1145.7532 -547.37642,-1111.7634 C -561.26485,-1083.9865 -583.92755,-1060.8845 -597.88405,-1032.9715 C -608.19334,-1012.3529 -622.12385,-996.61369 -632.22923,-976.40292 C -639.55197,-961.75745 -642.61989,-946.38567 -648.39168,-931.95621 C -652.90572,-920.6711 -658.98037,-908.75852 -664.55412,-897.61103 C -667.07062,-892.57801 -716.39482,-897.61103 -725.16327,-897.61103 C -734.0549,-897.61103 -748.276,-880.5592 -755.46784,-873.36737 C -764.57241,-864.26279 -767.9049,-857.45805 -775.67089,-847.1034 C -783.07496,-837.23132 -788.25189,-819.9211 -793.85364,-808.7176 C -803.04235,-790.34018 -811.09243,-768.04671 -816.077,-748.10845 C -821.96008,-724.57613 -824.46405,-700.41812 -830.21913,-677.39777 C -833.85459,-662.85593 -836.28005,-649.01243 -836.28005,-632.95106 C -836.28005,-598.82269 -856.2672,-555.02276 -864.56432,-521.83428 C -868.77151,-505.00551 -872.64554,-480.9603 -872.64554,-463.24543 C -872.64554,-452.00743 -874.66584,-438.87968 -874.66584,-426.87994 C -874.66584,-412.06437 -874.66584,-397.2488 -874.66584,-382.43323 C -874.66584,-367.88549 -881.26848,-345.9212 -884.76737,-331.9256 C -889.19493,-314.2153 -902.41425,-300.6724 -909.01103,-287.4789 C -914.1625,-277.1759 -926.05581,-283.2527 -921.13286,-295.5601 z"
+ id="path2989" />
+ <g
+ transform="translate(-988.39466,-665.52836)"
+ id="g2280">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ id="path2282" />
+ <path
+ id="path2284"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ id="g2286"
+ transform="translate(-956.06978,-550.37097)">
+ <path
+ id="path2288"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ id="path2290" />
+ </g>
+ <g
+ transform="translate(-1147.9988,-594.81768)"
+ id="g2292">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ id="path2294" />
+ <path
+ id="path2296"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ id="g2298"
+ transform="translate(-1121.9988,-706.81768)">
+ <path
+ id="path2300"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ id="path2302" />
+ </g>
+ <g
+ transform="translate(-1267.9988,-752.81768)"
+ id="g2304">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ id="path2306" />
+ <path
+ id="path2308"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ id="g2310"
+ transform="translate(-1289.9988,-672.81768)">
+ <path
+ id="path2312"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ id="path2314" />
+ </g>
+ <g
+ transform="translate(-1375.9988,-940.81768)"
+ id="g2316">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ id="path2318" />
+ <path
+ id="path2320"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ id="g2322"
+ transform="translate(-1439.9988,-1012.8177)">
+ <path
+ id="path2324"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ id="path2326" />
+ </g>
+ <g
+ transform="translate(-969.99876,-1174.8177)"
+ id="g2328">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ id="path2330" />
+ <path
+ id="path2332"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ id="g2334"
+ transform="translate(-879.99876,-1140.8177)">
+ <path
+ id="path2336"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ id="path2338" />
+ </g>
+ <g
+ transform="translate(-1105.9988,-804.81768)"
+ id="g2340">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ id="path2342" />
+ <path
+ id="path2344"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ id="g2346"
+ transform="translate(-1211.9988,-846.81768)">
+ <path
+ id="path2348"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ id="path2350" />
+ </g>
+ <path
+ style="opacity:0.50568183;fill:#0000ff;fill-rule:evenodd;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 215.90706,-1069.5786 C 150.58786,-1069.8445 91.365364,-1040.602 30.000864,-994.57855 C -2.2673361,-970.37753 -56.970236,-854.28523 -30.624136,-814.76605 C 16.093264,-744.6899 93.904164,-684.39763 181.50086,-681.45355 C 178.59766,-675.6473 165.68336,-592.66743 161.40706,-588.39105 C 155.80266,-582.78661 -84.509136,-475.38784 144.65706,-463.2973 C 185.50206,-461.14236 245.03616,-540.04733 271.84456,-540.0473 C 364.60966,-540.0473 432.72466,-660.80417 484.56326,-729.9223 C 511.74446,-766.16381 565.03386,-878.22015 527.00086,-923.8598 C 475.25556,-985.95419 408.07096,-1034.3404 339.28206,-1068.7348 C 297.34206,-1089.7048 252.54956,-1069.4294 215.90706,-1069.5786 z M 346.25086,-1022.9223 C 360.30246,-1022.9223 426.37576,-958.11727 426.37576,-947.57855 C 426.37586,-937.03983 360.30246,-984.7348 346.25086,-984.7348 C 332.19916,-984.73481 292.65706,-1030.7898 292.65706,-1041.3286 C 292.65706,-1051.8673 332.19916,-1022.9223 346.25086,-1022.9223 z"
+ id="path2352"
+ sodipodi:nodetypes="csscssssssccsssc" />
+ <path
+ style="fill:#ff0000;fill-opacity:0.50588229;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 484.37586,-1334.2661 C 483.34546,-1334.2376 482.08416,-1333.5369 480.53206,-1331.9848 C 464.61236,-1316.0651 445.31736,-1307.444 432.03206,-1287.5161 C 408.21856,-1251.7958 367.67676,-1221.7002 353.25086,-1178.4223 C 333.91536,-1120.4161 288.15206,-1044.6361 244.15706,-1000.6411 C 165.59386,-922.07783 116.06746,-821.7924 50.188264,-733.95355 C -1.9924361,-664.37926 -34.655436,-597.35479 -34.655436,-509.70355 C -34.655436,-423.41521 -70.087736,-479.73419 58.282064,-297.5785 C 58.830664,-296.8 59.608764,-296.2207 60.282064,-295.5473 C 55.359164,-283.2399 67.255564,-277.1818 72.407064,-287.4848 C 79.003864,-300.6783 92.229464,-314.212 96.657064,-331.9223 C 100.15596,-345.9179 106.75076,-367.87456 106.75086,-382.4223 C 106.75086,-397.23787 106.75076,-412.07548 106.75086,-426.89105 C 106.75086,-438.89079 108.78206,-451.99681 108.78206,-463.2348 C 108.78206,-480.94967 112.66866,-504.99977 116.87586,-521.82855 C 125.17296,-555.01703 145.15706,-598.82519 145.15706,-632.95355 C 145.15706,-649.01492 147.58406,-662.84922 151.21956,-677.39105 C 156.97466,-700.4114 159.46146,-724.57747 165.34456,-748.1098 C 170.32916,-768.04806 178.37466,-790.32614 187.56326,-808.70355 C 193.16506,-819.90705 198.34676,-837.23773 205.75086,-847.1098 C 213.51686,-857.46445 216.86496,-864.25522 225.96956,-873.3598 C 233.16136,-880.55163 247.35926,-897.60981 256.25086,-897.6098 C 265.01936,-897.6098 314.35926,-892.57679 316.87586,-897.6098 C 322.44946,-908.75729 328.51806,-920.66844 333.03206,-931.95355 C 338.80386,-946.38301 341.86546,-961.74558 349.18826,-976.39105 C 359.29366,-996.60182 373.22276,-1012.3662 383.53206,-1032.9848 C 397.48856,-1060.8978 420.17486,-1083.9892 434.06326,-1111.7661 C 451.05826,-1145.7559 473.02296,-1191.4082 480.53206,-1228.9536 C 484.46826,-1248.6344 479.68416,-1272.062 484.56326,-1291.5786 C 487.01466,-1301.384 491.58856,-1334.4653 484.37586,-1334.2661 z M 331.28206,-1066.0473 C 343.77236,-1066.0473 353.90706,-1054.6302 353.90706,-1040.5786 C 353.90706,-1026.5269 343.77236,-1015.1411 331.28206,-1015.1411 C 318.79176,-1015.1411 308.65706,-1026.5269 308.65706,-1040.5786 C 308.65706,-1054.6302 318.79176,-1066.0473 331.28206,-1066.0473 z"
+ id="path2354"
+ sodipodi:nodetypes="cssssssscssssssssssssssssssssccsssc" />
+ <g
+ transform="translate(99.144064,-1138.8177)"
+ id="g2356">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ id="path2358" />
+ <path
+ id="path2360"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ id="g2362"
+ transform="translate(-124.57024,-804.81768)">
+ <path
+ id="path2364"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ id="path2366" />
+ </g>
+ <g
+ transform="translate(-230.57019,-846.81768)"
+ id="g2368">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ id="path2370" />
+ <path
+ id="path2372"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ id="g2374"
+ transform="translate(12.858364,-1176.532)">
+ <path
+ id="path2376"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ id="path2378" />
+ </g>
+ <g
+ id="g2380"
+ transform="translate(-143.42734,-693.96054)">
+ <path
+ id="path2382"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ id="path2384" />
+ </g>
+ <g
+ transform="translate(-169.14163,-583.96054)"
+ id="g2386">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 264.65997,106.8594 L 289.91378,132.11321"
+ id="path2388" />
+ <path
+ id="path2390"
+ d="M 289.91378,106.8594 L 264.65997,132.11321"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <path
+ style="opacity:0.5070422;fill:#ff0000;fill-opacity:0.50588229;stroke:#000000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 1135.7757,-973.9516 C 929.63638,-973.9516 709.30528,-890.79941 709.30528,-712.1047 C 709.30528,-533.40998 839.03848,-428.12946 1045.1777,-428.12946 C 1212.0524,-428.12945 1364.5424,-450.26799 1412.3705,-581.27925 C 1417.5407,-595.44179 1370.7938,-753.65554 1373.69,-768.58369 C 1377.0977,-786.14812 1467.26,-631.83353 1467.26,-650.23286 C 1467.26,-828.92758 1341.9152,-973.9516 1135.7757,-973.9516 z M 1162.3053,-962.886 C 1206.2166,-962.8859 1241.8677,-943.0936 1241.8677,-918.69845 C 1241.8677,-894.30327 1206.2165,-874.51095 1162.3053,-874.51095 C 1118.3939,-874.51096 1082.7427,-894.30327 1082.7427,-918.69845 C 1082.7428,-943.0936 1118.3939,-962.886 1162.3053,-962.886 z M 1216.4303,-772.8547 C 1299.9838,-772.85468 1367.8053,-741.16824 1367.8053,-702.13595 C 1367.8053,-663.10366 1299.9837,-631.44845 1216.4303,-631.44845 C 1132.8767,-631.44847 1065.0865,-663.10366 1065.0865,-702.13595 C 1065.0864,-741.16824 1132.8766,-772.8547 1216.4303,-772.8547 z M 1182.1803,-565.13595 C 1243.1682,-565.13593 1292.6803,-539.89606 1292.6803,-508.7922 C 1292.6803,-477.68834 1243.1682,-452.44845 1182.1803,-452.44845 C 1121.1923,-452.44847 1071.7115,-477.68834 1071.7115,-508.7922 C 1071.7114,-539.89606 1121.1923,-565.13595 1182.1803,-565.13595 z"
+ id="path3727"
+ sodipodi:nodetypes="csssssccsssccsssccsssc" />
+ <path
+ style="opacity:0.5070422;fill:#000080;fill-opacity:0.50588229;stroke:#000000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 1129.1506,-1000.4648 L 1129.1506,-319.87102 L 1732.4006,-319.87102 L 1732.4006,-1000.4648 L 1129.1506,-1000.4648 z M 1187.7131,-783.90227 C 1196.8613,-783.90225 1204.3068,-706.69974 1204.3068,-611.55852 L 1204.2756,-611.55852 C 1204.2757,-516.4173 1196.8613,-439.18352 1187.7131,-439.18352 C 1178.5649,-439.18354 1171.1506,-516.4173 1171.1506,-611.55852 C 1171.1505,-706.69974 1178.5649,-783.90227 1187.7131,-783.90227 z M 1367.8068,-724.24602 C 1447.0912,-724.24603 1511.4318,-688.11098 1511.4318,-643.58977 C 1511.4318,-599.06856 1447.0913,-562.93352 1367.8068,-562.93352 C 1288.5225,-562.93351 1224.1818,-599.06856 1224.1818,-643.58977 C 1224.1819,-688.11098 1288.5226,-724.24602 1367.8068,-724.24602 z"
+ id="rect3729" />
+ <text
+ xml:space="preserve"
+ style="font-size:18px;font-style:normal;font-weight:bold;text-align:end;writing-mode:lr-tb;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="723.4375"
+ y="35.174683"
+ id="text2328"><tspan
+ sodipodi:role="line"
+ id="tspan2330"
+ x="723.4375"
+ y="35.174683">Intersection Project</tspan><tspan
+ sodipodi:role="line"
+ x="723.4375"
+ y="55.681184"
+ id="tspan2332"
+ style="font-size:16px;font-weight:normal;text-align:end;text-anchor:end;font-family:Sans">Michael Sloan</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:24px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Serif"
+ x="15.625"
+ y="84.570549"
+ id="text2334"><tspan
+ sodipodi:role="line"
+ id="tspan2336"
+ x="15.625"
+ y="84.570549">Layer 1: Curve</tspan></text>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999988px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 15.60073,87.695549 L 728.14921,87.695549"
+ id="path2339" />
+ <text
+ xml:space="preserve"
+ style="font-size:14px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="29.6875"
+ y="109.57055"
+ id="text2343"><tspan
+ sodipodi:role="line"
+ x="29.6875"
+ y="109.57055"
+ id="tspan2347"><tspan
+ style="font-weight:bold"
+ id="tspan8521">Curve</tspan>: A continuous 2d function on the interval [0,1], with precise start and end points</tspan></text>
+ <text
+ id="text2351"
+ y="336.49829"
+ x="15.625"
+ style="font-size:24px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Serif"
+ xml:space="preserve"><tspan
+ y="336.49829"
+ x="15.625"
+ id="tspan2353"
+ sodipodi:role="line">Layer 2: Path &amp; Region</tspan></text>
+ <path
+ id="path2355"
+ d="M 15.60073,339.62327 L 728.14921,339.62327"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999988px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 39.0625,142.38305 C 50.953679,82.266289 39.708637,183.98347 140.625,117.38305"
+ id="path2375"
+ sodipodi:nodetypes="cc" />
+ <text
+ xml:space="preserve"
+ style="font-size:14px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Serif"
+ x="33.59375"
+ y="154.10181"
+ id="text2972"><tspan
+ sodipodi:role="line"
+ id="tspan2974"
+ x="33.59375"
+ y="154.10181">0</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:14px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Serif"
+ x="142.1875"
+ y="124.4143"
+ id="text2976"><tspan
+ sodipodi:role="line"
+ id="tspan2978"
+ x="142.1875"
+ y="124.4143">1</tspan></text>
+ <rect
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:1, 47.99999964;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect2994"
+ width="514.0625"
+ height="175.08554"
+ x="201.5625"
+ y="118.94555" />
+ <flowRoot
+ xml:space="preserve"
+ style="font-size:14px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ id="flowRoot3395"><flowRegion
+ id="flowRegion3397"><use
+ x="0"
+ y="0"
+ xlink:href="#rect2994"
+ id="use3399"
+ width="744.09448"
+ height="1052.3622"
+ transform="translate(0,24.041631)" /></flowRegion><flowPara
+ id="flowPara3401"><flowSpan
+ style="font-weight:bold"
+ id="flowSpan8519">Crossing</flowSpan>: A location where two curves cross. This is a subset of the intersections of the curves. Crossings are stored as two time values and a boolean indicating the relationship between the curves.</flowPara><flowPara
+ id="flowPara8507" /><flowPara
+ id="flowPara8511">This relationship is defined by the 'direction' of the curves at the intersection, and is quite useful in the later layers. When the curves are portions of paths with the same winding, this relation boolean indicates whether the first path is exiting (true), or leaving (false).</flowPara><flowPara
+ id="flowPara8515" /><flowPara
+ id="flowPara8517">In curve terms it is the orientation of the derivatives and the origin.</flowPara></flowRoot> <path
+ sodipodi:nodetypes="cc"
+ id="path3802"
+ d="M 39.0625,226.75805 C 50.953679,166.64129 39.708637,268.35847 140.625,201.75805"
+ style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Send);marker-mid:none;marker-end:url(#Arrow1Send);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Send);marker-end:url(#Arrow1Send);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 68.75,265.82055 C 31.50892,217.735 75.40193,186.36624 125,179.88305"
+ id="path3806"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 57.8125,213.4768 L 57.8125,223.63305"
+ id="path4211" />
+ <path
+ id="path4213"
+ d="M 52.73437,218.55493 L 62.89062,218.55493"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Serif"
+ x="81.25"
+ y="245.50806"
+ id="text4215"><tspan
+ sodipodi:role="line"
+ id="tspan4217"
+ x="81.25"
+ y="245.50806">A<tspan
+ style="font-size:8px"
+ id="tspan4219"
+ dy="2.34375">t <tspan
+ style="font-size:12px"
+ id="tspan4221"
+ dy="-1.5625">= 0.4</tspan></tspan></tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Serif"
+ x="85.15625"
+ y="186.13306"
+ id="text4223"><tspan
+ sodipodi:role="line"
+ id="tspan4225"
+ x="85.15625"
+ y="186.13306">A</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Serif"
+ x="117.96875"
+ y="206.44556"
+ id="text4227"><tspan
+ sodipodi:role="line"
+ id="tspan4229"
+ x="117.96875"
+ y="206.44556">B</tspan></text>
+ <text
+ id="text4231"
+ y="260.35181"
+ x="80.46875"
+ style="font-size:12px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Serif"
+ xml:space="preserve"><tspan
+ y="260.35181"
+ x="80.46875"
+ id="tspan4233"
+ sodipodi:role="line"><tspan
+ dy="0 2.34375"
+ id="tspan4235"
+ style="font-size:8px"><tspan
+ style="font-size:12px"
+ id="tspan4247">B</tspan>t <tspan
+ dy="-1.5625"
+ id="tspan4237"
+ style="font-size:12px">= 0.15</tspan></tspan></tspan></text>
+ <rect
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:1.00000001, 48.00000051;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect8527"
+ width="700"
+ height="57.396477"
+ x="27.34375"
+ y="347.43579" />
+ <flowRoot
+ xml:space="preserve"
+ style="font-size:14px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ id="flowRoot8934"
+ transform="translate(0,-42.426407)"><flowRegion
+ id="flowRegion8936"><use
+ x="0"
+ y="0"
+ xlink:href="#rect8527"
+ id="use8938"
+ transform="translate(0,42.426407)"
+ width="744.09448"
+ height="1052.3622" /></flowRegion><flowPara
+ id="flowPara8940"><flowSpan
+ style="font-weight:bold"
+ id="flowSpan8942">Path</flowSpan>: A series of connected Curves, implicitly closed with a final line segment. For some applications, however, this line segment must be treated specially, such that if it is still expressed, it is the last segment of the path. In some cases this is impossible.</flowPara></flowRoot> <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Serif"
+ x="27.125"
+ y="468.62329"
+ id="text8946"><tspan
+ sodipodi:role="line"
+ id="tspan8948"
+ x="27.125"
+ y="468.62329">0</tspan></text>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 36.5,443.80039 C 36.5,443.80039 66.583183,434.01208 81.03125,430.51914 C 152.125,413.33164 150.5625,411.76914 99,432.86289 C 78.75366,441.14548 113.84375,446.14414 117.75,443.80039 C 287.26549,396.25895 87.015116,455.9959 165.40625,450.05039 C 177.90625,448.48789 234.9375,410.98789 234.9375,410.98789 C 251.87833,448.11151 247.88044,478.79245 210.71875,499.26914"
+ id="path8950"
+ sodipodi:nodetypes="csscccc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 37.28125,444.58164 L 210.71875,499.26914"
+ id="path8952"
+ sodipodi:nodetypes="cc" />
+ <text
+ id="text9359"
+ y="427.30042"
+ x="77.875"
+ style="font-size:12px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Serif"
+ xml:space="preserve"><tspan
+ y="427.30042"
+ x="77.875"
+ id="tspan9361"
+ sodipodi:role="line">1</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Serif"
+ x="83.875"
+ y="441.30042"
+ id="text9363"><tspan
+ sodipodi:role="line"
+ id="tspan9365"
+ x="83.875"
+ y="441.30042">2</tspan></text>
+ <text
+ id="text9367"
+ y="455.30042"
+ x="111.875"
+ style="font-size:12px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Serif"
+ xml:space="preserve"><tspan
+ y="455.30042"
+ x="111.875"
+ sodipodi:role="line"
+ id="tspan9371">3</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Serif"
+ x="163.875"
+ y="461.30042"
+ id="text9375"><tspan
+ id="tspan9377"
+ sodipodi:role="line"
+ x="163.875"
+ y="461.30042">4</tspan></text>
+ <text
+ id="text9379"
+ y="427.30042"
+ x="228.875"
+ style="font-size:12px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Serif"
+ xml:space="preserve"><tspan
+ y="427.30042"
+ x="228.875"
+ sodipodi:role="line"
+ id="tspan9381">5</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Serif"
+ x="203.22182"
+ y="511.77289"
+ id="text9383"><tspan
+ sodipodi:role="line"
+ id="tspan9385"
+ x="203.22182"
+ y="511.77289">6</tspan></text>
+ <path
+ id="path9318"
+ d="M 181.00779,605.47923 L 181.00779,756.79173 L 326.69529,756.79173 L 326.69529,605.47923 L 181.00779,605.47923 z M 255.13279,630.91673 C 280.89411,630.91673 301.82029,651.84292 301.82029,677.60423 C 301.82027,703.36552 280.8941,724.26048 255.13279,724.26048 C 229.37148,724.2605 208.47654,703.36554 208.47654,677.60423 C 208.47653,651.84289 229.37148,630.91673 255.13279,630.91673 z"
+ style="opacity:1;fill:#6e5e5e;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <rect
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:1.00000007, 48.0000034;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect9411"
+ width="440"
+ height="44.715744"
+ x="44.483189"
+ y="862.271" />
+ <g
+ id="g2521"
+ transform="translate(0,301.12698)">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 5.2867965,666.45725 C 5.2867965,666.45725 35.369977,656.66894 49.818047,653.176 C 120.9118,635.9885 119.3493,634.426 67.786797,655.51975 C 47.540457,663.80234 82.630547,668.801 86.536797,666.45725 C 256.05229,618.91581 55.801917,678.65276 134.19305,672.70725 C 146.69305,671.14475 203.7243,633.64475 203.7243,633.64475 C 220.66513,670.76837 216.66724,701.44931 179.50555,721.926"
+ id="path9389"
+ sodipodi:nodetypes="csscccc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:4, 2;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 6.0680465,667.2385 L 179.50555,721.926"
+ id="path9391"
+ sodipodi:nodetypes="cc" />
+ <path
+ transform="translate(-30.213203,-10.811184)"
+ d="M 180,671.36218 A 53,53 0 1 1 74,671.36218 A 53,53 0 1 1 180,671.36218 z"
+ sodipodi:ry="53"
+ sodipodi:rx="53"
+ sodipodi:cy="671.36218"
+ sodipodi:cx="127"
+ id="path9834"
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ sodipodi:type="arc" />
+ <g
+ transform="translate(-21.213203,-38.811184)"
+ id="g10655">
+ <path
+ id="path10651"
+ d="M 65.3125,688.01843 L 65.3125,698.17468"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 60.23437,693.09656 L 70.39062,693.09656"
+ id="path10653" />
+ </g>
+ <g
+ transform="translate(-17.713203,-12.311184)"
+ id="g10659">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 65.3125,688.01843 L 65.3125,698.17468"
+ id="path10661" />
+ <path
+ id="path10663"
+ d="M 60.23437,693.09656 L 70.39062,693.09656"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ <g
+ id="g10665"
+ transform="translate(60.286797,12.188816)">
+ <path
+ id="path10667"
+ d="M 65.3125,688.01843 L 65.3125,698.17468"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 60.23437,693.09656 L 70.39062,693.09656"
+ id="path10669" />
+ </g>
+ <g
+ transform="translate(84.286797,-26.311184)"
+ id="g10671">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 65.3125,688.01843 L 65.3125,698.17468"
+ id="path10673" />
+ <path
+ id="path10675"
+ d="M 60.23437,693.09656 L 70.39062,693.09656"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ <g
+ id="g10677"
+ transform="translate(83.786797,-40.811183)">
+ <path
+ id="path10679"
+ d="M 65.3125,688.01843 L 65.3125,698.17468"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 60.23437,693.09656 L 70.39062,693.09656"
+ id="path10681" />
+ </g>
+ <g
+ transform="translate(82.286797,-44.311183)"
+ id="g10683">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 65.3125,688.01843 L 65.3125,698.17468"
+ id="path10685" />
+ <path
+ id="path10687"
+ d="M 60.23437,693.09656 L 70.39062,693.09656"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ </g>
+ <g
+ id="g2554"
+ transform="translate(0,301.12698)">
+ <path
+ id="path11208"
+ d="M 220.05888,649.49465 L 263.83033,649.49465"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ id="text12445"
+ y="638.83783"
+ x="222.01724"
+ style="font-size:12px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Serif"
+ xml:space="preserve"><tspan
+ y="638.83783"
+ x="222.01724"
+ id="tspan12447"
+ sodipodi:role="line">Union</tspan></text>
+ </g>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 414.70605,930.12161 L 517.4494,870.17357"
+ id="path13315" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 416.70608,941.12165 L 526.01012,979.92317"
+ id="path13317" />
+ <g
+ id="g2544"
+ transform="translate(0,301.12698)">
+ <path
+ id="path12896"
+ d="M 415.51098,636.39534 C 415.96828,639.19439 416.20607,642.06692 416.20607,644.99465 L 416.20607,644.99465 C 416.20607,646.96475 416.0984,648.90985 415.88862,650.82438"
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ id="path12892"
+ d="M 310.51289,639.2627 C 313.37363,612.69928 335.88664,591.99465 363.20607,591.99465 C 388.72601,591.99465 410.05186,610.06154 415.0824,634.09412"
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ id="path12888"
+ d="M 392.28508,689.30395 C 383.93485,694.79747 373.94156,697.99465 363.20607,697.99465 C 340.78343,697.99465 321.59861,684.04712 313.85985,664.36028"
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ id="path12460"
+ d="M 415.27762,650.89645 C 436.57244,639.8338 469.64357,618.0884 469.64357,618.0884 C 486.5844,655.21202 482.58651,685.89296 445.42482,706.36965"
+ style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ id="path12456"
+ d="M 416.89529,633.40969 C 426.42762,631.19088 423.32669,632.81532 415.90125,636.06666"
+ style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ id="path12449"
+ d="M 310.81469,638.88458 C 295.40026,643.02872 271.20607,650.9009 271.20607,650.9009 L 313.95542,663.53315"
+ style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path12900"
+ d="M 390.59038,689.68218 L 446.42479,706.36968"
+ style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.99999996, 1.99999998;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ transform="translate(-118.29394,-51.367533)"
+ d="M 540,685.86218 A 5.5,5.5 0 1 1 529,685.86218 A 5.5,5.5 0 1 1 540,685.86218 z"
+ sodipodi:ry="5.5"
+ sodipodi:rx="5.5"
+ sodipodi:cy="685.86218"
+ sodipodi:cx="534.5"
+ id="path12902"
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:0.80000001;stroke-miterlimit:4;stroke-dasharray:0.8, 0.8;stroke-dashoffset:0;stroke-opacity:1"
+ sodipodi:type="arc" />
+ </g>
+ <g
+ id="g2564"
+ transform="translate(0,301.12698)">
+ <path
+ sodipodi:nodetypes="cc"
+ id="path13335"
+ d="M 523.51519,620.60763 C 520.12981,602.83246 515.33803,584.38874 510.2072,573.72907"
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:19.23264885;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:19.23264885;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 540.87055,613.95765 C 632.53653,592.62085 602.717,608.242 531.31153,639.50794"
+ id="path13337" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path13351"
+ d="M 537.05362,641.11822 L 518.0652,644.21465 C 520.08982,656.60699 521.65827,669.15297 522.75281,681.83516 C 534.90606,684.33516 534.16149,677.70481 541.83282,679.90433 C 540.72774,666.83066 539.14076,653.8932 537.05362,641.11822 z"
+ style="opacity:1;fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:39.59658432;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:0.80000001;stroke-miterlimit:4;stroke-dasharray:0.8, 0.8;stroke-dashoffset:0;stroke-opacity:1"
+ id="path13339"
+ sodipodi:cx="534.5"
+ sodipodi:cy="685.86218"
+ sodipodi:rx="5.5"
+ sodipodi:ry="5.5"
+ d="M 540,685.86218 A 5.5,5.5 0 1 1 529,685.86218 A 5.5,5.5 0 1 1 540,685.86218 z"
+ transform="matrix(9.6163242,0,0,9.6163242,-4605.6823,-5971.0816)" />
+ <path
+ transform="matrix(9.6163242,0,0,9.6163242,-4605.6823,-5971.0816)"
+ d="M 540,685.86218 A 5.5,5.5 0 1 1 529,685.86218 A 5.5,5.5 0 1 1 540,685.86218 z"
+ sodipodi:ry="5.5"
+ sodipodi:rx="5.5"
+ sodipodi:cy="685.86218"
+ sodipodi:cx="534.5"
+ id="path13356"
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:0.80000001;stroke-miterlimit:4;stroke-dasharray:0.8, 0.8;stroke-dashoffset:0;stroke-opacity:1"
+ sodipodi:type="arc" />
+ </g>
+ <g
+ id="g2571"
+ transform="translate(-6,301.12698)">
+ <path
+ sodipodi:nodetypes="ccccccsssssssscc"
+ id="path17529"
+ d="M 669.90625,568.88609 L 652.59375,577.22984 C 668.38738,617.91025 658.91917,631.04706 701.75,623.38609 C 661.44527,641.13907 670.89896,635.14549 673.8125,681.13609 C 685.96576,683.63612 685.20367,677.03032 692.875,679.22984 C 692.02305,669.15078 692.20265,658.99187 691.375,649.01109 C 705.86844,642.91912 717.48537,637.56766 726.0625,633.01109 C 731.20833,630.27738 735.25679,627.8742 738.5,625.41734 C 740.12161,624.18891 741.53504,622.95333 742.90625,621.32359 C 744.27746,619.69385 745.99222,617.53449 746.1875,613.57359 C 746.38278,609.61269 743.46312,605.17416 740.9375,603.54234 C 738.41188,601.91052 736.38131,601.53447 734.375,601.22984 C 732.36869,600.92521 730.28822,600.83068 728.03125,600.85484 C 725.77428,600.879 723.34589,601.04254 720.5625,601.29234 C 711.49835,602.10581 699.14713,604.09782 683.09375,607.32359 C 679.47139,592.40484 674.50899,578.44864 669.90625,568.88609 z"
+ style="opacity:1;fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:19.23264885;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ transform="matrix(9.6163242,0,0,9.6163242,-4454.6363,-5971.7659)"
+ d="M 540,685.86218 A 5.5,5.5 0 1 1 529,685.86218 A 5.5,5.5 0 1 1 540,685.86218 z"
+ sodipodi:ry="5.5"
+ sodipodi:rx="5.5"
+ sodipodi:cy="685.86218"
+ sodipodi:cx="534.5"
+ id="path17535"
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:0.80000001;stroke-miterlimit:4;stroke-dasharray:0.8, 0.8;stroke-dashoffset:0;stroke-opacity:1"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:0.80000001;stroke-miterlimit:4;stroke-dasharray:0.8, 0.8;stroke-dashoffset:0;stroke-opacity:1"
+ id="path17537"
+ sodipodi:cx="534.5"
+ sodipodi:cy="685.86218"
+ sodipodi:rx="5.5"
+ sodipodi:ry="5.5"
+ d="M 540,685.86218 A 5.5,5.5 0 1 1 529,685.86218 A 5.5,5.5 0 1 1 540,685.86218 z"
+ transform="matrix(9.6163242,0,0,9.6163242,-4454.6363,-5971.7659)" />
+ </g>
+ <g
+ id="g2559"
+ transform="translate(0,301.12698)">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 584.92598,583.02661 L 628.69743,583.02661"
+ id="path2443" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Serif"
+ x="590.88434"
+ y="576.36975"
+ id="text2445"><tspan
+ sodipodi:role="line"
+ id="tspan2447"
+ x="590.88434"
+ y="576.36975">Fix</tspan></text>
+ </g>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 73.436386,852.85756 L 663.36887,852.85756"
+ id="path2449" />
+ <flowRoot
+ id="flowRoot2451"
+ style="font-size:12px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Serif"
+ xml:space="preserve"
+ transform="translate(-235.46656,388.08684)"><flowRegion
+ id="flowRegion2453"><use
+ id="use2455"
+ xlink:href="#rect9411"
+ y="0"
+ x="0"
+ width="744.09448"
+ height="1052.3622"
+ transform="translate(235.46656,-386.78742)" /></flowRegion><flowPara
+ id="flowPara2457">One problem with storing crossings as a time value is that the locations on the two paths may not perfectly coincide. To maintain continuity, the output portions must be tweaked.</flowPara></flowRoot> <path
+ id="path2477"
+ d="M 73.436386,1034.4627 L 663.36887,1034.4627"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <rect
+ y="415.47995"
+ x="272.02945"
+ height="91.384789"
+ width="440"
+ id="rect2501"
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:1.00000004, 48.00000264;stroke-dashoffset:0;stroke-opacity:1" />
+ <flowRoot
+ xml:space="preserve"
+ style="font-size:14px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ id="flowRoot2503"
+ transform="translate(0,-48.870058)"><flowRegion
+ id="flowRegion2505"><use
+ x="0"
+ y="0"
+ xlink:href="#rect2501"
+ id="use2507"
+ width="744.09448"
+ height="1052.3622"
+ transform="translate(0,48.083262)" /></flowRegion><flowPara
+ id="flowPara2511">The Crossing data type is also valid on Paths, where a particular time value corresponds to the point on curve i at f, where i is the integral part, and f is the fractional part. The crossings function for paths is the basis of the important path_boolean function.</flowPara></flowRoot> <text
+ xml:space="preserve"
+ style="font-size:24px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Serif"
+ x="15.625"
+ y="1081.7888"
+ id="text2513"><tspan
+ sodipodi:role="line"
+ id="tspan2515"
+ x="15.625"
+ y="1081.7888">Layer 3: Shape</tspan></text>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999988px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 15.60073,1084.9138 L 728.14921,1084.9138"
+ id="path2517" />
+ <rect
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:1.00000004, 48.00000245;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect2596"
+ width="690.3158"
+ height="72.698502"
+ x="21.713648"
+ y="520.41602" />
+ <rect
+ y="347.43579"
+ x="27.34375"
+ height="57.396477"
+ width="700"
+ id="rect2602"
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:1.00000001, 48.00000051;stroke-dashoffset:0;stroke-opacity:1" />
+ <flowRoot
+ xml:space="preserve"
+ style="font-size:14;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ id="flowRoot2630"><flowRegion
+ id="flowRegion2632"><use
+ x="0"
+ y="0"
+ xlink:href="#rect2596"
+ id="use2634"
+ width="744.09448"
+ height="1052.3622" /></flowRegion><flowPara
+ id="flowPara2636"><flowSpan
+ style="font-style:normal;font-weight:bold;font-size:14"
+ id="flowSpan2640">Region</flowSpan>: A simple path (a path with no self-intersection), specifying a subset of the plane. Such a path also has a defined winding direction which specifies what the boundary means - a region of 'fill' will have a counter-clockwise wind, whereas a region of 'non-fill' will have a clockwise wind. Reversing the direction of the region's path will give the boolean complement of the region.</flowPara></flowRoot> <path
+ sodipodi:type="arc"
+ style="opacity:1;fill:#6e5e5e;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.45454550000000005;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path6202"
+ sodipodi:cx="91.923882"
+ sodipodi:cy="633.75494"
+ sodipodi:rx="22.627417"
+ sodipodi:ry="22.627417"
+ d="M 114.5513,633.75494 A 22.627417,22.627417 0 1 1 69.296465,633.75494 A 22.627417,22.627417 0 1 1 114.5513,633.75494 z"
+ transform="matrix(2.0625,0,0,2.0625,-91.428942,-630.93823)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.4545455;marker-start:url(#Arrow1Mstart);marker-mid:url(#Arrow1Mstart);marker-end:url(#Arrow1Mstart);stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path2656"
+ sodipodi:cx="91.923882"
+ sodipodi:cy="633.75494"
+ sodipodi:rx="22.627417"
+ sodipodi:ry="22.627417"
+ d="M 114.5513,633.75494 A 22.627417,22.627417 0 1 1 69.296465,633.75494 A 22.627417,22.627417 0 1 1 114.5513,633.75494 z"
+ transform="matrix(2.0625,0,0,2.0625,-92.843157,-629.52402)" />
+ <rect
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect9127"
+ width="145.66399"
+ height="151.32086"
+ x="22.627422"
+ y="605.4707" />
+ <path
+ transform="matrix(2.0625,0,0,2.0625,65.548763,-629.52403)"
+ d="M 114.5513,633.75494 A 22.627417,22.627417 0 1 1 69.296465,633.75494 A 22.627417,22.627417 0 1 1 114.5513,633.75494 z"
+ sodipodi:ry="22.627417"
+ sodipodi:rx="22.627417"
+ sodipodi:cy="633.75494"
+ sodipodi:cx="91.923882"
+ id="path9129"
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.4545455;marker-start:url(#Arrow1Mend);marker-mid:url(#Arrow1Mend);marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ sodipodi:type="arc" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="77.781746"
+ y="769.51947"
+ id="text11070"><tspan
+ sodipodi:role="line"
+ id="tspan11072"
+ x="77.781746"
+ y="769.51947">(Outer box represents the plane)</tspan></text>
+ <rect
+ y="606.68304"
+ x="344.15433"
+ height="143.40918"
+ width="367.87509"
+ id="rect11074"
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999988;stroke-miterlimit:4;stroke-dasharray:1, 48.00000017;stroke-dashoffset:0;stroke-opacity:1" />
+ <flowRoot
+ xml:space="preserve"
+ style="font-size:14px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ id="flowRoot11080"><flowRegion
+ id="flowRegion11082"><use
+ x="0"
+ y="0"
+ xlink:href="#rect11074"
+ id="use11084"
+ width="744.09448"
+ height="1052.3622" /></flowRegion><flowPara
+ id="flowPara11086">This behavior is mainly important for the main region boolean function, which takes two regions and performs an operation. The operation which is performed is specified by a bool which indicates either union (false) or intersection (true).</flowPara><flowPara
+ id="flowPara11777" /><flowPara
+ id="flowPara11779">This operation may be considered from the standpoint of regular path booleans:</flowPara></flowRoot> <text
+ xml:space="preserve"
+ style="font-size:16.31223488px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="390.38602"
+ y="771.6131"
+ id="text11088"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ sodipodi:role="line"
+ id="tspan11090"
+ x="390.38602"
+ y="771.6131">Union</tspan></text>
+ <text
+ id="text11092"
+ y="786.07953"
+ x="455.04291"
+ style="font-size:16.31223488px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ y="786.07953"
+ x="455.04291"
+ id="tspan11094"
+ sodipodi:role="line">A</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:16.31223488px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="340.86606"
+ y="823.54407"
+ id="text11096"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ sodipodi:role="line"
+ id="tspan11098"
+ x="340.86606"
+ y="823.54407">B</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="415.87198"
+ y="798.57526"
+ id="text11100"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ sodipodi:role="line"
+ id="tspan11102"
+ x="415.87198"
+ y="798.57526">Fill</tspan></text>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.00000002, 1.00000002;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 510.65997,802.88125 L 390.54555,802.88125 L 390.54555,837.88488"
+ id="path11104" />
+ <text
+ id="text11106"
+ y="798.57526"
+ x="466.74768"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ y="798.57526"
+ x="466.74768"
+ id="tspan11108"
+ sodipodi:role="line">Hole</tspan></text>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.00000002, 1.00000002;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 460.69754,802.57541 L 460.69754,840.23336"
+ id="path11110" />
+ <text
+ xml:space="preserve"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="395.08356"
+ y="817.79944"
+ id="text11112"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ sodipodi:role="line"
+ id="tspan11114"
+ x="395.08356"
+ y="817.79944">A+B</tspan></text>
+ <text
+ id="text11116"
+ y="817.79944"
+ x="465.38834"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ y="817.79944"
+ x="465.38834"
+ id="tspan11118"
+ sodipodi:role="line">A-B</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="395.08356"
+ y="834.02338"
+ id="text11120"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ sodipodi:role="line"
+ id="tspan11122"
+ x="395.08356"
+ y="834.02338">B-A</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="442.45596"
+ y="833.52515"
+ id="text11124"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ sodipodi:role="line"
+ id="tspan11126"
+ x="442.45596"
+ y="833.52515">H</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="434.12323"
+ y="817.61108"
+ id="text11128"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ sodipodi:role="line"
+ id="tspan11130"
+ x="434.12323"
+ y="817.61108">F</tspan></text>
+ <text
+ id="text11132"
+ y="817.89258"
+ x="442.45596"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ y="817.89258"
+ x="442.45596"
+ id="tspan11134"
+ sodipodi:role="line">H</tspan></text>
+ <text
+ id="text11136"
+ y="817.61108"
+ x="434.12323"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ y="817.61108"
+ x="434.12323"
+ id="tspan11138"
+ sodipodi:role="line">F</tspan></text>
+ <text
+ id="text11188"
+ y="817.89258"
+ x="498.86911"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ y="817.89258"
+ x="498.86911"
+ id="tspan11190"
+ sodipodi:role="line">H</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="465.38834"
+ y="834.11163"
+ id="text11260"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ sodipodi:role="line"
+ id="tspan11262"
+ x="465.38834"
+ y="834.11163">AxB</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="498.86911"
+ y="834.20483"
+ id="text11264"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ sodipodi:role="line"
+ id="tspan11266"
+ x="498.86911"
+ y="834.20483">H</tspan></text>
+ <text
+ id="text11268"
+ y="816.24683"
+ x="368.29462"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ y="816.24683"
+ x="368.29462"
+ id="tspan11270"
+ sodipodi:role="line">Fill</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="352.56204"
+ y="832.55908"
+ id="text11272"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ sodipodi:role="line"
+ id="tspan11274"
+ x="352.56204"
+ y="832.55908">Hole</tspan></text>
+ <text
+ id="text11693"
+ y="771.6131"
+ x="555.71558"
+ style="font-size:16.31223488px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ y="771.6131"
+ x="555.71558"
+ id="tspan11695"
+ sodipodi:role="line">Intersection</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:16.31223488px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="641.52271"
+ y="786.07953"
+ id="text11697"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ sodipodi:role="line"
+ id="tspan11699"
+ x="641.52271"
+ y="786.07953">A</tspan></text>
+ <text
+ id="text11701"
+ y="825.54053"
+ x="539.36707"
+ style="font-size:16.31223488px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ y="825.54053"
+ x="539.36707"
+ id="tspan11703"
+ sodipodi:role="line">B</tspan></text>
+ <text
+ id="text11705"
+ y="798.57526"
+ x="608.36243"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ y="798.57526"
+ x="608.36243"
+ id="tspan11707"
+ sodipodi:role="line">Fill</tspan></text>
+ <path
+ id="path11709"
+ d="M 710.80928,802.88125 L 590.69486,802.88125 L 590.69486,837.88488"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.00000002, 1.00000002;stroke-dashoffset:0;stroke-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="655.01807"
+ y="798.57526"
+ id="text11711"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ sodipodi:role="line"
+ id="tspan11713"
+ x="655.01807"
+ y="798.57526">Hole</tspan></text>
+ <path
+ id="path11715"
+ d="M 647.27741,802.57541 L 647.27741,840.23336"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.00000002, 1.00000002;stroke-dashoffset:0;stroke-opacity:1" />
+ <text
+ id="text11717"
+ y="817.79944"
+ x="595.58807"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ y="817.79944"
+ x="595.58807"
+ id="tspan11719"
+ sodipodi:role="line">AxB</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="653.65869"
+ y="817.79944"
+ id="text11721"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ sodipodi:role="line"
+ id="tspan11723"
+ x="653.65869"
+ y="817.79944">B-A</tspan></text>
+ <text
+ id="text11725"
+ y="836.06238"
+ x="595.58807"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ y="836.06238"
+ x="595.58807"
+ id="tspan11727"
+ sodipodi:role="line">A-B</tspan></text>
+ <text
+ id="text11733"
+ y="817.61108"
+ x="634.62775"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ y="817.61108"
+ x="634.62775"
+ id="tspan11735"
+ sodipodi:role="line">F</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="634.62775"
+ y="817.61108"
+ id="text11741"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ sodipodi:role="line"
+ id="tspan11743"
+ x="634.62775"
+ y="817.61108">F</tspan></text>
+ <text
+ id="text11749"
+ y="835.47101"
+ x="653.65869"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ y="835.47101"
+ x="653.65869"
+ id="tspan11751"
+ sodipodi:role="line">A+B</tspan></text>
+ <text
+ id="text11753"
+ y="835.56415"
+ x="689.17853"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ y="835.56415"
+ x="689.17853"
+ id="tspan11755"
+ sodipodi:role="line">H</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="568.79919"
+ y="816.24683"
+ id="text11757"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ sodipodi:role="line"
+ id="tspan11759"
+ x="568.79919"
+ y="816.24683">Fill</tspan></text>
+ <text
+ id="text11761"
+ y="832.55908"
+ x="553.06659"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#0000ff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ y="832.55908"
+ x="553.06659"
+ id="tspan11763"
+ sodipodi:role="line">Hole</tspan></text>
+ <text
+ id="text11765"
+ y="835.96234"
+ x="634.62775"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ y="835.96234"
+ x="634.62775"
+ id="tspan11767"
+ sodipodi:role="line">F</tspan></text>
+ <text
+ id="text11769"
+ y="817.61108"
+ x="700.5564"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ y="817.61108"
+ x="700.5564"
+ id="tspan11771"
+ sodipodi:role="line">F</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:16.31223488px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="700.5564"
+ y="835.96234"
+ id="text11773"
+ transform="scale(0.9982283,1.0017748)"><tspan
+ sodipodi:role="line"
+ id="tspan11775"
+ x="700.5564"
+ y="835.96234">F</tspan></text>
+ <rect
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999988;stroke-miterlimit:4;stroke-dasharray:0.99999998, 47.99999926;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect11781"
+ width="312.72076"
+ height="59.970577"
+ x="23.127848"
+ y="783.45972" />
+ <flowRoot
+ xml:space="preserve"
+ style="font-size:14px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ id="flowRoot11787"><flowRegion
+ id="flowRegion11789"><use
+ x="0"
+ y="0"
+ xlink:href="#rect11781"
+ id="use11791" /></flowRegion><flowPara
+ id="flowPara11793">Though not on the chart, fill subtraction and hole subtraction may be performed by reversing one of the arguments.</flowPara></flowRoot> <rect
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:1.00000001, 48.00000051;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect12212"
+ width="700"
+ height="57.396477"
+ x="27.34375"
+ y="346.02158" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1;marker-start:url(#Dot_m)"
+ d="M 33.234019,725.63596 L 33.234019,748.26338"
+ id="path12214" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+ d="M 34.062445,725.67885 L 56.689865,725.67885"
+ id="path12218" />
+ </g>
+</svg>
diff --git a/src/3rdparty/2geom/doc/degenerate_conic_decomposition.pdf b/src/3rdparty/2geom/doc/degenerate_conic_decomposition.pdf
new file mode 100644
index 0000000..9d5e1cf
--- /dev/null
+++ b/src/3rdparty/2geom/doc/degenerate_conic_decomposition.pdf
Binary files differ
diff --git a/src/3rdparty/2geom/doc/extradoxygen.css b/src/3rdparty/2geom/doc/extradoxygen.css
new file mode 100644
index 0000000..2e0c486
--- /dev/null
+++ b/src/3rdparty/2geom/doc/extradoxygen.css
@@ -0,0 +1,14 @@
+#top {
+ width: 1000px;
+ margin: 0 auto;
+}
+
+div.contents {
+ width: 1000px;
+ margin: 0 auto;
+}
+
+div.header {
+ width: 1000px;
+ margin: 0 auto;
+} \ No newline at end of file
diff --git a/src/3rdparty/2geom/doc/features.txt b/src/3rdparty/2geom/doc/features.txt
new file mode 100644
index 0000000..2dab29e
--- /dev/null
+++ b/src/3rdparty/2geom/doc/features.txt
@@ -0,0 +1,28 @@
+* C++
+* Functional programming style.
+* Points
+* Efficient affine transformations
+* Rectangles
+* Convex Hulls
+* Bounded error
+* General purpose paths:
+- exact elliptical arcs
+- area
+- centroid and bending moments
+* Path Locations
+- determination of special spots (e.g. maximum curvature)
+- splitting
+- point, tangent, curvature at location
+- efficient arc length and inverse arc length
+* Path algebra
+- computations such as offset curves can be written with their mathematical definition and still get a bounded error, efficient curve. (preliminary trials indicate offset done this way out performs the method used in Inkscape)
+- arbitrary distortion (with bounded error)
+-- mesh distorts
+-- computational distorts such as the GIMP's 'vortex' plugin
+-- 3d mapping (perspective, flag, sphere)
+* exact boolean ops (elliptic arcs remain elliptic arcs)
+* efficient 2d database
+* implicit function plotting
+* NURBs input and output
+* tunable path simplification
+* PDoF constraint system for CAD/ CAGD \ No newline at end of file
diff --git a/src/3rdparty/2geom/doc/manual.bib b/src/3rdparty/2geom/doc/manual.bib
new file mode 100644
index 0000000..af7f0d7
--- /dev/null
+++ b/src/3rdparty/2geom/doc/manual.bib
@@ -0,0 +1,55 @@
+@article{SanchezReyes1997,
+ author = {J. S\'{a}nchez-Reyes},
+ title = {The symmetric analogue of the polynomial power basis},
+ journal = {ACM Trans. Graph.},
+ volume = {16},
+ number = {3},
+ year = {1997},
+ issn = {0730-0301},
+ pages = {319--357},
+ doi = {http://doi.acm.org/10.1145/256157.256162},
+ publisher = {ACM},
+ address = {New York, NY, USA},
+ }
+
+@article{SanchezReyes2001,
+ author = {J. S\'{a}nchez-reyes},
+ title = {Inversion approximations for functions via s-power series},
+ journal = {Comput. Aided Geom. Des.},
+ volume = {18},
+ number = {6},
+ year = {2001},
+ issn = {0167-8396},
+ pages = {587--608},
+ doi = {http://dx.doi.org/10.1016/S0167-8396(01)00054-1},
+ publisher = {Elsevier Science Publishers B. V.},
+ address = {Amsterdam, The Netherlands, The Netherlands},
+ }
+
+@article{SanchezReyes2000,
+ author = {Javier S\'{a}nchez-Reyes},
+ title = {Applications of the polynomial s-power basis in geometry processing},
+ journal = {ACM Trans. Graph.},
+ volume = {19},
+ number = {1},
+ year = {2000},
+ issn = {0730-0301},
+ pages = {27--55},
+ doi = {http://doi.acm.org/10.1145/343002.343018},
+ publisher = {ACM},
+ address = {New York, NY, USA},
+ }
+
+@article{SanchezReyes2005,
+ author = {J. S\'{a}nchez-Reyes and J. M. Chac\'{o}n},
+ title = {s-power series: an alternative to Poisson expansions for representing analytic functions},
+ journal = {Comput. Aided Geom. Des.},
+ volume = {22},
+ number = {2},
+ year = {2005},
+ issn = {0167-8396},
+ pages = {103--119},
+ doi = {http://dx.doi.org/10.1016/j.cagd.2004.09.003},
+ publisher = {Elsevier Science Publishers B. V.},
+ address = {Amsterdam, The Netherlands, The Netherlands},
+ }
diff --git a/src/3rdparty/2geom/doc/manual.tex b/src/3rdparty/2geom/doc/manual.tex
new file mode 100644
index 0000000..196c990
--- /dev/null
+++ b/src/3rdparty/2geom/doc/manual.tex
@@ -0,0 +1,734 @@
+\documentclass[openany]{book}
+\usepackage{tabularx}
+\usepackage{graphicx}
+
+\title{Lib2geom Manual}
+
+\newcommand{\code}[1]{\textsf{#1}}
+
+\begin{document}
+\maketitle{}
+
+\chapter{Overview}
+
+\section{Introduction}
+
+This manual focuses on the lib2geom computational geometry framework.
+The main goal of this framework is the eventual replacement of
+Inkscape's multiple and shoddy geometry frameworks. As with any decent
+module or lib, 2geom is designed to achieve the desired functionality
+while maintaining a generality encouraging usage within other
+applications. The focus on robust, accurate algorithms, as well as
+utilization of newer and better representations makes the lib
+very attractive for many applications.
+
+\section{Design Considerations}
+2Geom is written with a functional programming style in mind.
+Generally data structures are considered immutable and rather than
+assignment we use labeling. However, C++ can become unwieldy if
+this is taken to extreme and so a certain amount of pragmatism is
+used in practice. In particular, usability is not forgotten in the
+mires of functional zeal.
+
+The code relies strongly on the type system and uses some of the more
+'tricky' elements of C++ to make the code more elegant and 'correct'.
+Despite this, the intended use of 2Geom is a serious vector graphics
+application. In such domains, performance is still used as a quality
+metric, and as such we consider inefficiency to be a bug, and have
+traded elegance for efficiency where it matters.
+
+In general the data structures used in 2Geom are relatively 'flat'
+and require little from the memory management. Currently most data
+structures are built on standard STL headers\cite{stl}, and new and
+delete are used sparingly. It is intended for 2Geom to be fully
+compatible with Boehm garbage collector\cite{boehm} though this has
+not yet been tested.
+
+\section{Toy-Based Development}
+We have managed to come up with a method of library development
+that is perfect for geometry: the development of toys exemplifying
+a feature while the feature is perfected. This has somewhat subsumed
+the role of tests, and provides immediate motivation/reward for work.
+
+Every toy uses the same framework, which hides the details of making a
+user interface. You simply request some handles to interact with, and
+write some code to draw the output from the handles.
+
+\begin{figure}
+ \begin{center}
+ \includegraphics[width=90mm]{media/gear.png}
+ \caption{The gear toy demonstrates constructing paths, and computing a path with a known function for the teeth.}
+ \label{fig:gear-toy}
+ \end{center}
+\end{figure}
+
+Every toy can save a screenshot in SVG, PDF or PNG format. You can
+save the current handles to a handle file (.hnd) and load an existing
+handle file. Every toy can be called with \verb|-s filename| to save
+a screenshot to file filename (the type being determined by the
+extension). The toy can be started in a known state from a handle
+file.
+
+If you find some strange or buggy behaviour, save a handle file and a
+screenshot and submit them with your bug report.
+
+\section{Getting started}
+
+Build the library and play with all the toys in src/2geom/toys. Copy one that is similar to the problem you want to solve, and modify it. For example, say you wanted to compute the involute of a curve.
+
+An involute of a curve is defined by
+$$I(t) = B(t) - \frac{dB(t) \int_0^t|dB(\tau)|_2 d\tau}{|dB(\tau)|_2}$$
+
+If we reparameterise this curve to have unit speed (arc length parameterisation) the equation simplifies to:
+
+$$I(t) = B(t) - \frac{dB_x(t) t}{1}$$
+
+so if we can reparameterise a path to have unit speed the involute is almost trivial. Let's start with \verb|arc_length_param.cpp|. We see that the function required is simply:
+\begin{verbatim}
+Piecewise<D2<SBasis> > uniform_B = arc_length_parametrization(B);
+\end{verbatim}
+
+Take the resulting function and apply the calculations. You'll get
+the involute of the curve, as shown in Figure~\ref{fig:involute-toy}.
+We do not include an involute toy, but we would welcome someone to
+work out how to make non-circular gears.
+
+\begin{figure}
+ \begin{center}
+ \includegraphics[width=70mm]{media/involute.pdf}
+ \caption{The output of an involute toy.}
+ \label{fig:involute-toy}
+ \end{center}
+\end{figure}
+
+
+\chapter{Geometric Primitives}
+
+What good is a geometry library without geometric primitives? By this
+I mean the basic stuff that every decent geometry library has:
+Points/Vectors, Matrices, etc.
+
+2geom's primitives are descendant from libNR's geometric primitives.
+They have been modified quite a bit since that initial import, and
+will likely change in the future.
+
+\section{Points}
+
+\includegraphics[height=30mm]{media/point.png}
+
+The mathematical concepts of points and vectors are merged into the
+2geom class called \code{Point}. See Appendix A for a further
+discussion of this decision.
+
+2geom also breaks with the more traditional point \code{struct} with
+\code{.x} and \code{.y} fields. Rather, each 2geom point has a 2
+element array of coordinates.
+
+We found that the availability of \code{.x} and \code{.y} encouraged
+people to attempt to inline geometry operations rather than using the
+operators, perhaps in pursuit of a performance enhancement. By using
+an array, we encourage people to think about \code{Point}s as
+symmetric objects and discourage direct use of the components. We
+still provide direct access for the rare occasion that it is needed.
+Even in these cases, the array method prevents bugs by encouraging
+iteration over the array rather than explicit element reference.
+
+\section{Transformations}
+
+Affine transformations are either represented with a canonical 6
+element matrix, or special forms.
+
+\subsection{Scale}
+
+\includegraphics[height=50mm]{media/scale.png}
+
+A \code{Scale} transformation stores x and y scaling factors.
+
+\subsection{Rotate}
+
+\includegraphics[height=50mm]{media/rotate.png}
+
+A \code{Rotate} transformation uses a vector(\code{Point}) to store
+a rotation about the origin.
+
+In correspondence with mathematical convention (y increasing upwards),
+0 degrees is encoded as a vector pointing along the x axis, and positive
+angles indicate anticlockwise rotation. So, for example, a vector along
+the y axis would encode a 90 degree anticlockwise rotation of 90 degrees.
+
+In the case that the computer convention of y increasing downwards,
+the \verb}Rotate} transformation works essentially the same, except
+that positive angles indicate clockwise rotation.
+
+\subsection{Translate}
+
+\includegraphics[height=70mm]{media/translate.png}
+
+A \code{Translate} transformation is a simple vector(\code{Point})
+which stores an offset.
+
+\subsection{Matrix}
+
+\includegraphics[height=70mm]{media/matrix.png}
+
+A \code{Matrix} is a general affine transform. Code is provided for
+various decompositions, constructions, and manipulations. A
+\code{Matrix} is composed of 6 coordinates, essentially storing the
+x axis, y axis, and offset of the transformation. A detailed
+explanation for matrices is given in Appendix B.
+
+\subsection{D2}
+The \code{D2} class takes two instances of a scalar data type and treats them like a point. All operations which make sense on a point are defined for D2.
+
+A \verb|D2<double>| is a \code{Point}. A \verb|D2<Interval>| is a standard axis aligned rectangle.
+\verb|D2<SBasis>| provides a 2d parametric function which maps $t$ to a point $x(t), y(t)$
+\verb|D2<SBasis2d>| provides a 2d parametric function which maps a point $u,v$ to a point $x(u,v), y(u,v)$ --- a distortion.
+
+\section{Bounding Structures}
+
+2geom currently provides two classes for storing approximate bounding
+regions: \code{Rect} and \code{ConvexHull}. These are mostly intended
+for use in (mathematical) optimization, however provide manipulations suitable for
+other uses.
+
+\subsection{Interval}
+
+An interval is simply a pair of Coords which define a closed interval $[min, max]$.
+
+\subsection{Rect}
+
+\includegraphics[height=50mm]{media/rect.png}
+
+\code{Rect}s are rectangles with all sides parallel to the axes.
+\code{Rect}s are in fact defined as a \verb|D2<Interval>|.
+
+A rectangle can have 0 area and not be empty --- $[0,0] \times [0,0]$ contains exactly 1 point 0,0 and has 0 area. Similarly, $[0,0] \times [0,1]$ defines a 0 area line segment.
+
+\subsection{ConvexHull}
+
+\includegraphics[height=50mm]{media/convex.png}
+
+\verb|convex-cover.h| defines convex hulls with a set of points in clockwise direction. These can bee unioned and tested for intersection.
+
+\subsubsection{Operations}
+\begin{description}
+\item[empty:] contains no points
+\item[singular:] contains exactly one point
+\item[linear:] all points are on a line
+\item[area:] area of the convex hull
+\item[furthest:] furthest point in a direction (log time)
+\item[intersect:] do two convex hulls intersect?
+\item[intersection:] find the convex hull intersection
+\item[merge:] find the convex hull of a set of convex hulls
+\item[hausdorf distance:] the greatest least distance between a point $a$ in convex hull $A$ and a second convex hull $B$.
+\end{description}
+
+\subsection{Piecewise}
+The \code{Piecewise} class manages a sequence of elements of a type as
+segments and the 'cuts' between them. These cuts are time values which
+separate the pieces. This function representation allows for
+more interesting functions, as it provides a viable output for operations
+such as inversion, which may require multiple SBasis to properly invert
+the original.
+
+As for technical details, while the actual SBasis segments begin on the
+first cut and end on the last, the function is defined throughout all
+inputs by extending the first and last segments. The exact switching
+between segments is arbitrarily such that beginnings (t=0) have
+preference over endings (t=1). That is, each segment is $[t_0, t_1)$.
+This only matters if it is discontinuous at the location.
+
+$$
+f(t) \rightarrow \left\{
+\begin{array}{cc}
+s_1,& t <= c_2 \\
+s_2,& c_2 <= t <= c_3\\
+\ldots
+s_n,& c_n <= t
+\end{array}\right.
+$$
+
+\chapter{Paths}
+
+A \code{Path} is an ordered set of \code{Curve}s. Each \code{Path} is $C0$ continuous. To make multiple contours for a region, use \code{PathVector}.
+
+A \code{PathVector} in Inkscape is drawn in a single fill and stroke.
+
+This allows us lots of flexibility with what sort of elements we can
+'understand', while only taking slightly more memory than a sequence
+of points in the poly line or poly bezier case.
+
+The Curves themselves are immutable, which means that they can be shared between Paths.
+
+There is an implicit line segment from the initialPoint to the finalPoint which is used if the path is closed.
+
+An empty (size() == 0) path defines a naked move to.
+
+\section{Curves}
+2Geom has a diversity of curve types and conversions between them.
+
+Curves define a continuous segments which yields points for values of
+t in the range of [0,1]. The start-point is at t=0, and the endpoint
+at t=1.
+
+We require that each \code{Curve} implements virtual functions which
+allow for traversers of a path to perform generic operations. All
+curves must provide functions which give a position and gradient of a
+$t \in [0,1]$, bounds functions, and conversion to s-basis.
+
+\subsection{Bezier Curve}
+We use a \code{Bezier} curve class to store lines and quadratic/cubic
+beziers. This flexibility is attained by templating on order:
+\code{Bezier$<1>$} is a line segment, \code{Bezier$<2>$} is a quadratic
+bezier, and \code{Bezier$<3>$} is a cubic bezier.
+
+Bezier curves have some nice properties:
+\begin{itemize}
+\item Affine transforming the handles also affine transforms the values.
+\item The convex hull of the handles encompasses the curve.
+\end{itemize}
+
+\subsection{SVG Elliptical Arc}
+The \code{SVGEllipticalArc} curve class is implemented for support of
+the SVG elliptical arc. See the svg documentation for details on this
+curve.
+
+\subsection{S-Basis Curve}
+The \code{SBasisCurve} wraps the \code{MultidimSBasis$<2>$} class
+described later.
+
+\subsection{Possible Future Curve Types}
+\begin{itemize}
+\item Clothoids / Raphoids
+\item NURBS
+\end{itemize}
+
+\chapter{S-Power-Basis Form}
+
+2Geom provides a very powerful algebra for modifying paths. Although
+paths are kept in an extended SVG native form where possible, many
+operations require approximation. To do this we can convert a path
+into a sequence of symmetric power basis polynomials, henceforth
+referred to as s-basis, perform the required operations and convert
+back, approximating to a requested tolerance as required.
+
+The precise details of the s-basis form are beyond the scope of this
+manual, the interested reader should consult \cite{SanchezReyes1997,SanchezReyes2000,SanchezReyes2001,SanchezReyes2003,SanchezReyes2005}.
+An elementary, functional description is given in Appendix C.
+
+Geometrically important properties:
+\begin{itemize}
+\item exact representation of bezier segments
+\item low condition number on bezier conversion.
+\item strong convergence guarantees
+\item $C^0$ continuity guarantee
+\end{itemize}
+
+The following operations are implemented and are very efficient:
+\begin{itemize}
+\item fast conversion from all svg elements
+\item basic arithmetic --- $+$, $-$, $\times$, $\div$
+\item algebraic derivative and integral
+\item elementary trigonometric functions: $\sqrt{\cdot}$, $\sin(\cdot)$, $\cos(\cdot)$, $\exp(\cdot)$
+\item efficient degree elevation and reduction
+\item function inversion
+\item exact solutions for many non trivial operations
+\item root finding
+\item composition
+\end{itemize}
+
+All of these operations are fast. For example, multiplication of two
+beziers by converting to s-basis form, multiplying and converting back
+takes roughly the same time as performing the bezier multiplication
+directly, and furthermore, subdivision and degree reduction and
+elevation are straightforward in this form.
+
+\section{Implementation}
+As described in Appendix C, SBasis functions have the form $f(t) \rightarrow y$.
+Just S-Basis functors (in the C++ sense) alone are not enough to perform
+useful geometric operations. There are quite a few 2geom classes to
+address these needs.
+
+\subsection{SBasis}
+The \code{SBasis} class provides the most basic function form,
+$f(t) \rightarrow y$. This is useful in its own right, as well as being an
+element of constructing more complicated forms. \code{SBasis} are made
+up of \code{BezOrd}s, which store from/to values for each polynomial
+coefficient.
+
+\subsection{SBasis2D}
+SBasis2D provides multivariate form --- functions of the form
+$f(u,v) \rightarrow z$. These can be used for arbitrary distortion
+functions (take a path $p(t) \rightarrow (u,v)$ and a pair of surfaces
+$f(u,v),g(u,v)$ and compose: $q(t) = (f(p(t)), g(p(t)))$.
+
+Subdivision for surfaces may be done with either quadtrees or kd-trees.
+
+In general it is recommended to use the \verb|Piecewise<SBasis>| type rather than the SBasis type directly, as it manages the domain arithmetic automatically. It also automatically subdivides when necessary to improve accuracy/convergence.
+
+\chapter{2D databases}
+
+2Geom provides an implementation of a 2D database using quad trees and
+using a list. Quad trees aren't the best data-structure for queries,
+but they usually out perform the linear list. We provide a
+standard interface for object databases with performance guarantees
+and provide a set of useful operations Operations:
+
+\begin{description}
+\item[Insert:] given a bounding box and a 'reference', insert into the db
+\item[Delete:] given a bounding box and a 'reference', delete from the db
+\item[Search:] given a box, find all objects that may interact with this box
+\item[Cast:] given a path (including rays) return a list of objects that interact with the path, roughly sorted by path order
+\item[Shape query:] given a closed path, find all objects whose bounding boxes intersect path. (this and cast are nearly the same)
+\item[Nearest:] given a point (or maybe box) find the nearest objects, perhaps as a generator to get all objects in order. To do this, we walk around the quad tree neighbourhood, pushing all the elements into a priority queue, while the queue is empty, move out a bit. Nearest could be manhattan, max norm or euc?
+\item[Binary:] take two dbs, generate all pairs that have intersecting boxes.
+\item[Sweep:] traverse the tree in say y order, maintaining a y-range of relevant objects. (to implement sweepline algorithms)
+\item[Walk:] traverse the tree in an arbitrary order.
+\end{description}
+
+\chapter{Root like operations}
+
+\section{Roots}
+
+Given a function $x(t)$ we often wish to know where it is 0.
+$roots(x)$ quickly finds all values of $t \in [0,1)$ for which this is
+true. For example, if you wish to find where a path intersects a line you can rotate the path to make the line the x-axis and find the crossings with roots: $B(t) = \langle x(t), y(t)\rangle$, $roots(B \cdot \vec n)$.
+
+\section{Path intersection}
+
+Given a pair of paths, we often wish to know where they intersect. \verb|pair_intersect| finds all points where $A(t) = B(s), t \in [0,1], s \in [0,1]$. This can be performed on paths or \verb|piecewise<d2<sbasis> >|.
+
+\section{Self intersection}
+
+Sometimes we wish to know where a path intersects itself.
+
+\section{Contour finding}
+
+Given a function $f(x, y)$ we wish to construct approximate paths such that $f = 0$. Find two points on the same contour and use \verb|sb2d_cubic_solve|. (still needs code to refine and integration with aa.cpp to find the initial points)
+
+\section{Collinear normals}
+
+Given two paths we wish to find all pairs of points where a line through these points is parallel to the normal at that point.
+
+\section{Bounds: fast and exact}
+
+We provide two classes of bounding for functions, fast and exact.
+Fast is merely guaranteed to contain the function, Exact is the
+smallest bound that completely contains the function.
+
+\chapter{Topological operations: sweepline, boolops, sanitize}
+\section{Layer 1: Path Intersection}
+
+\begin{verbatim}
+src/path-intersection.cpp
+src/path-intersection.h
+src/crossing.h
+src/crossing.h
+src/toys/winding-test.cpp
+\end{verbatim}
+
+\subsection{Winding Number:}
+ the number of times the path goes around a particular point. Since paths are closed, the result is always integral. A counter-clockwise rotation corresponds to a positive wind, whereas a clockwise rotation is represented as a negative wind. Here, and throughout, the terms clockwise and counter-clockwise refer to the standard mathematical coordinate system rather than the computer, inverted y-axis, coordinate system.
+
+\subsection{Crossing:}
+ a location where two paths cross. This is a subset of the intersections of the paths, with the requirement that the winding must change. Crossings are stored as two time values and a boolean indicating the relationship between the curves at the crossing. A particular time value corresponds to the point on curve i at f, where i is the integral part, and f is the fractional part. This boolean is useful for making decisions during a traversal of crossings. It is defined as the sign of the cross product of the derivatives. When the paths are regions with the same winding, this indicates that along B, A crosses 'outside'.
+
+\subsection{Winding functions:}
+
+\verb|int winding(Path, Point);|
+\verb|bool path_direction(Path);| — assumes the path is simple (like a region)
+\verb|bool contains(Path, Point, bool even-odd = true);| — convenience wrapper around winding
+
+There are a few convenience typedefs for the popular crossing collections:
+\verb|typedef std::vector<Crossing> Crossings;|
+\verb|typedef std::vector<Crossings> CrossingSet;|
+
+The intersection system is designed to be modular, so that different algorithms may be used. The current algorithms are generic, and apply to anything that implements Curve. A custom curve type might provide an algorithm with special cases, and default to the generic algorithms. The following crossing functions use the DefaultCrosser, which is currently a simple binary search.
+
+\verb|Crossings crossings(Path, Path);| — finds the crossings between two paths
+\verb|CrossingSet crossings(PathVector, PathVector);| — finds the crossings between two sets of paths.
+
+
+\section{Layer 2: Regions}
+
+\begin{verbatim}
+src/region.cpp
+src/region.h
+\end{verbatim}
+
+\subsection{Region:}
+A limited point-set, defined by a boundary. This boundary is stored as a simple (non-self-crossing) path. Regions with positive winding (counter-clockwise) include points which are inside the boundary (fills), whereas Regions with negative winding include all points outside the boundary (holes). It also caches information such as winding direction and bounding box.
+
+Most of the public api for region simply wraps and caches queries to a Path. It also provides various convenience functions such as \verb|as_fill| and \verb|as_hole|. Region should usually only be used by clients of this library when dealing with paths with the same invariants as regions.
+
+
+\section{Layer 3: Shapes}
+
+\begin{verbatim}
+src/shape.cpp
+src/shape.h
+src/toys/boolops.cpp
+\end{verbatim}
+
+\subsection{Shape:}
+A point-set upon which boolean operations may be performed. Shapes are defined by a list of regions, where the resulting point-set is the cumulative intersection. Though it may be figured out from the regions, shapes also store whether the most outer paths are fill or hole. In other words, it stores the value of all the points completely outside the boundary of all its constituent regions. Shapes have the following invariants:
+
+\begin{itemize}
+\item{ The regions must not cross, or intersect for more than a point.}
+\item{ Filled regions only contain 'hole' regions, and vice-versa.}
+\item{ The 'top level' regions are all the same type (fill or hole).}
+\end{itemize}
+
+The shape files really constitutes the main body of my work, while the other stuff is peripheral support. It contains the algorithms which perform boolean operations and sanitization on shapes.
+
+The most important function looks like this:
+
+\verb|Shape shape_boolean(bool, Shape, Shape, CrossingSet);|
+
+If the initial boolean is false, the function unions the shapes. If it is true, it intersects them. The CrossingSet contains the crossings between the regions of the two shapes (an overload of this function allows omission of this parameter). The functions operation is actually surprisingly simple. It traverses the crossings, keeping track of which it has hit, collecting portions of path as it goes, until it reaches a crossing it has already visited, at which point it stores the path and starts again at an unvisited crossing.
+
+The real magic happens in the traversal. It took me quite a long time to really figure it out, but eventually I realized that quite simple logic would allow for traversing intersecting sets of regions correctly. If the boolean input doesn't equal the direction of the crossing, path A is followed, if they are equal, the path B is followed. I actually figured this particular bit fairly early on, but it was with a pair of regions. At the time I had no idea it could also work for doing boolean operations on sets of regions.
+
+While the previous function contains the main code, the actual public function intended for public use is quite different.
+\verb|Shape boolop(Shape, Shape, unsigned)|
+
+It takes the two shapes, and a flag integer specifying which of 16 boolean operations to perform. These flags use the first 4 bits to represent a boolean truth table. This is the function which is used in the boolops toy. Half of the operations, the complements, deal with cases where the output shape is filled in areas where neither of the input shapes are. The binary complement operation(~) applied to the flags, will yield flags specifying the complementary boolean operation. 6 of the combinations of flags don't even call \verb|shape_boolean| - the various identity, inversion, and none/all operations.
+
+\begin{verbatim}
+src/sweep.cpp
+src/sweep.h
+src/toys/sweep.cpp
+src/tests/intersection-test.cpp
+\end{verbatim}
+
+These are some support algorithms which provide a sweep on bounds, for efficient intersections between sets of bounded objects.
+\section{Current Issues}
+
+The main current deficiency is the sanitizer. I've only recently managed to get a path uncrosser somewhat working. I have a variety of sanitization methods implemented to various degrees, yet have only recently figured out the real reasons I haven't yet gotten it fully functioning. I hope to fix it soon, so that boolops may be used as a live-path-effect within inkscape (the live-path-effects project is a Summer-of-Code project). I think this is a good way to introduce the new boolean operations, and I definitely want my work to be used.
+
+There's also some code which is currently unused:
+
+I have an implementation of intersection routines which splits paths into monotonic portions, and uses the properties of these sections to perform very fast intersection. It works somewhat, but there are bugs I haven't had time to work out, which make the current implementation unstable. This intersection algorithm is especially valuable for self intersections, as monotonic splits are already required.
+
+\section{Possible Future Design Changes}
+
+It may be possible for the boolean operations to return a set of portions. When the actual path data is required, the portion operations would be applied. The actual boolean operations would take no time to execute, as all the computational load would be in the crossing-finder and path synthesizer. This would also work for the sanitization step, saving many spurious portions. The portions found in the boolean operations could be composed onto those produced by the sanitization routine, so that the unnecessary intermediary paths between sanitization and boolean operations are never generated.
+
+The current representation of crossings between sets of paths is fairly awkward. The main core of the data structure, storing times and the direction boolean is fine, the main issue is the storage methods of collections of these crossings. I've come to realize it's actually one of the main reasons that sanitization is as hard as it has been. I've figured out that a better representation would be for each crossing to store pointers to the next and previous crossings along both its participating paths. This would form a connectivity graph, where each vertex has a degree of 4. A dedicated structure such as this would likely be worth it, as algorithms that use it would be more efficient, simpler, and less buggy.
+
+Without too much work, it should also be possible to do boolean operations with non-filled paths. The main change would be to have \verb|shape_boolean| handle coincident crossings, and to derive the resultant region fill from the fill of the contributing regions. This would allow all combinations of boolean operations between filled regions and paths.
+
+\chapter{Acknowledgements and history}
+
+2Geom is a group project, having many authors and contributors. The
+original code was sketched out by Nathan Hurst and Peter Moulder for
+the Inkscape vector graphics program to provide well typed, correct
+and easy to use C++ classes. Since then many people have refined and
+debugged the code. One of the earliest C++ification projects for
+inkscape was replacing NRPoint with NR::Point.
+
+A conspicuous absence was a Path datatype, and indeed Inkscape
+developed at least 3 different internal path datatypes, plus several
+others in related projects. Considering the core importance of path
+operations in vector graphics, this led to much re-implementation of
+algorithms, numerous bugs, and many round trips converting between
+forms.
+
+Many attempts have been made to try and develop a single path data
+structure, but all were fated to sit in random SCMs scattered across
+the web.
+
+Several unrelated projects had copied out various portions of the NR
+code from Inkscape and in 2006 MenTaLguY and Nathan felt that it was
+time to separate out the geometry portions of inkscape into a
+separate library for general use and improvement. The namespace was
+changed from NR to Geom and a prototype for paths sketched out.
+Nathan studied the state of the art for computational geometry whilst
+MenTaLguY focused on the design of Paths.
+
+Before the re-merging of 2Geom with the inkscape svn HEAD it was felt
+that a few smaller projects should be ported to use 2Geom. Michael
+Wybrow's libavoid advanced connector routing system was ported first.
+
+--now.
+
+\pagebreak
+
+\section{People who have contributed to 2Geom}
+\begin{description}
+\item[Aaron C.\ Spike]
+\item[Alex Mac]
+\item[Fred:] livarot
+\item[Javier Sanchez-Reyes]
+\item[Jean-Francois Barraud]
+\item[Johan B.\ C.\ Engelen]
+\item[Jonathon Wright]
+\item[Joshua Blocher]
+\item[Kim Marriott]
+\item[Marco Cecchetti]
+\item[MenTaLguY]
+\item[Michael J.\ Wybrow]
+\item[Michael G.\ Sloan]
+\item[Nathan J.\ Hurst]
+\item[Peter J.\ R.\ Moulder]
+\end{description}
+
+\chapter{Appendix}
+\renewcommand{\thesection}{\Alph{section}}
+
+\section{Geometric Points}
+In standard geometry, points and vectors are quite distinguished: a
+point is a location, whereas a vector is an unbased direction and
+magnitude. Allowed operations on vectors and points also vary:
+
+\begin{tabular}{r l}
+ $P - P$ & $= V$ \\
+
+ $P - P$ & $= V$ \\
+
+ $P + V$ & $= P$ \\
+
+ $P - V$ & $= P$ \\
+
+ $V + V$ & $= V$ \\
+
+ $V - V$ & $= V$ \\
+
+ $V \times S$ & $= V$ \\
+
+ $V \div S$ & $= V$ \\
+\end{tabular}
+
+Here, $P$ represents points, $V$ represents vectors, and $S$ scalars.
+
+Ideally we would render these restrictions in code, as they would
+reinforce algorithm correctness. This is because as far as arithmetic
+operations go, the above are all that you sanely require, unless you
+are prematurely optimizing.
+
+\section{Understanding Matrices}
+
+\section{S-Power-Basis Explanation}
+
+\section{Concepts}
+
+The C++ Standard Template Library\cite{stl} introduces the notion of
+\emph{concepts}\cite{stl_concepts}, which specify families of types related
+by a common interface. In template-based programming with the STL, concepts
+serve a similar purpose to type classes in Haskell. While, unlike Haskell's
+language-level support for type classes, concept-checking is not directly
+supported by the C++ compiler or language, C++ libraries have been written
+which use template techniques to provide compile-time checking and enforcement
+of concepts\cite{boost_concept_check}.
+
+There are several important lib2geom concepts in this sense:
+
+\subsection{ScalarFunction}
+
+\subsubsection{Description}
+
+Scalar functions are C++ function objects which behave like functions
+with type {\tt double (double)}. They take a single time value and return
+a scalar, and are defined over at least the interval $[0, 1]$.
+
+\subsubsection{Refinement of}
+
+\subsubsection{Associated types}
+
+\subsubsection{Notation}
+
+\begin{tabular}{r l}
+ {\tt X} & A type which models ScalarFunction \\
+ {\tt a} & An object of type {\tt X} \\
+ {\tt t} & A time value of type {\tt double} \\
+ {\tt n} & A count of type {\tt unsigned int} \\
+\end{tabular}
+
+\subsubsection{Definitions}
+
+\subsubsection{Valid expressions}
+
+\begin{tabularx}{300pt}{X l X l}
+ Name & Expression & Type requirements & Return type \\
+ Evaluate & {\tt a(t)} & & {\tt double} \\
+ Evaluate & {\tt a.valueAt(t)} & & {\tt double} \\
+ Evaluate with derivatives & {\tt a.valueAndDerivativesAt(t, n, out)} & {\tt out} should be a model of OutputIterator whose {\tt value\_type} is convertible to & {\tt void} \\
+ Range & {\tt a.fastRange()} & & {\tt Range} \\
+ Range & {\tt a.exactRange()} & & {\tt Range} \\
+ SBasis & {\tt a.sbasis()} & & {\tt SBasis} \\
+ Subdivide & {\tt a.subdivide(start, end)} & & {\tt Piecewise<X>} \\
+\end{tabularx}
+
+\subsubsection{Expression semantics}
+
+\begin{tabularx}{300pt}{X l l X l}
+ \bf{Name} & \bf{Expression} & \bf{Precondition} & \bf{Semantics} & \bf{Postcondition} \\
+ Evaluate & {\tt a(t)} & $0\le t\le 1$ & Returns the value of the function at $t$; the function must be exact at $t = 0$ and $t = 1$ and defined over the interval $0\le t\le 1$ & \\
+ Evaluate & {\tt a.valueAt(t)} & $0 \le t \le 1$ & Returns the value of the function at {\tt t}; the function must be exact at $t = 0$ and $t = 1$ and defined over the interval $0 \le t \le 1$ & \\
+ Evaluate with derivatives & {\tt a.valueAndDerivativesAt(t, n, out)} & $0 \le t \le 1$ & Evaluates the function and the first n derivatives at {\tt t}, writing them to {\tt out} & $n + 1$ values have been written to {\tt out} \\
+ Range & {\tt a.fastRange()} & & The result should be a {\tt Range} which includes the function's range & \\
+ Range & {\tt a.exactRange()} & & The result should be a {\tt Range} representing the exact range of the function & \\
+ SBasis conversion & {\tt a.sbasis()} & & The result should be an sbasis approximation of the function & \\
+\end{tabularx}
+
+\subsubsection{Complexity guarantees}
+
+\subsubsection{Invariants}
+
+\subsubsection{Models}
+
+\subsection{Curve}
+
+\section{Location Sequences}
+
+Many algorithms are more efficient on a sorted sequence of locations,
+than calling the function repeatedly for each. So we have algorithms
+that take a sequence of locations, assumed in order, and perform an
+action on those. For example, cutting a path at one location is
+basically linear in the number of path segments, but cutting a path in
+10 locations is still about the same amount of work. Similarly,
+working out the arc length for a location is about the same amount of
+work as working out the arc length for 1000 locations on that path.
+
+Many operations are best described as returning an ordered set of
+locations. For example, we have a function that returns
+intersections between two paths. Rather than return just one
+intersection, we might return all intersections, either in order along
+the path, or in order of distance along other path.
+% I don't understand the distinction between "order along the path" and "order
+% of distance along the path". As for the case of a path that goes back on
+% itself, e.g. a path whose y coordinate is unchanging and whose x coordinate
+% goes from 0 to 10 then back to 5 then to 15, I think most callers (including
+% the dashes case below) want it to behave the same as if the y coordinate did
+% change, i.e. want the same point reported three times if there's an
+% intersection at x=7. Whereas the case of a "stationary path" (bezier whose
+% control points are all coincident) is considered to have just one point and
+% zero length. -- pjrm.
+
+Think about dashes: a dash is a fixed arclength offset. So rather
+than getting the location for a point at arc length 1, at arc length
+2, 3, 4, $\ldots$, up to the length of the curve, instead we just ask for all of
+these, and the algorithm can chug along the curve outputting the
+answer for each. The reason it is faster is because to work out the
+location at arc length say 100, we basically need to work out the
+length for many spots up to 100.
+
+Perhaps we then want to split the curve at each of those points. To
+split a segment at a location first requires finding that segment,
+then splitting it and finally constructing a new path to output a whole
+new path so we can fit the two new segments in. If we started at the
+beginning, and split at the first location, then that would be $n+1$ steps: $n$
+segs in the original, plus an extra one. If we wanted to split at 100
+points, it would be $n+1$ steps for the first, $n+2$ for the
+second, $\ldots$, $n+100$ steps for the last, this would take a total of $100n +
+100*101/2$ steps! Whereas, if we split as we went along, it would take
+just $n+100$ steps.
+
+The downside is that I'll probably not provide a separate split
+routine that takes a single point, to discourage people from making
+exactly that mistake.
+
+\bibliographystyle{plain} % A good style to use with the Harvard package
+\bibliography{manual}\label{chapter:bibliography}
+
+\end{document}
diff --git a/src/3rdparty/2geom/doc/manual2/ack b/src/3rdparty/2geom/doc/manual2/ack
new file mode 100644
index 0000000..c6325fd
--- /dev/null
+++ b/src/3rdparty/2geom/doc/manual2/ack
@@ -0,0 +1,47 @@
+h1. Acknowledgements and History
+2Geom is a group project, having many authors and contributors. The
+original code was sketched out by Nathan Hurst and Peter Moulder for
+the Inkscape vector graphics program to provide well typed, correct
+and easy to use C++ classes. Since then many people have refined and
+debugged the code. One of the earliest C++ification projects for
+inkscape was replacing NRPoint with NR::Point.
+
+A conspicuous absence was a Path datatype, and indeed Inkscape
+developed at least 3 different internal path datatypes, plus several
+others in related projects. Considering the core importance of path
+operations in vector graphics, this led to much re-implementation of
+algorithms, numerous bugs, and many round trips converting between
+forms.
+
+Many attempts have been made to try and develop a single path data
+structure, but all were fated to sit in random SCMs scattered across
+the web.
+
+Several unrelated projects had copied out various portions of the NR
+code from Inkscape and in 2006 MenTaLguY and Nathan felt that it was
+time to separate out the geometry portions of inkscape into a
+separate library for general use and improvement. The namespace was
+changed from NR to Geom and a prototype for paths sketched out.
+Nathan studied the state of the art for computational geometry whilst
+MenTaLguY focused on the design of Paths.
+
+Before the re-merging of 2Geom with the inkscape svn HEAD it was felt
+that a few smaller projects should be ported to use 2Geom. Michael
+Wybrow's libavoid advanced connector routing system was ported first.
+
+(TODO: did this happen? also, add the rest of history..)
+
+h2. People who have contributed to 2Geom
+* Aaron C. Spike
+* Alex Mac
+* Fred: livarot
+* Javier Sanchez-Reyes
+* Jean-Francois Barraud
+* Jonathon Wright
+* Joshua Blocher
+* Kim Marriott
+* MenTaLguY
+* Michael J. Wybrow
+* Michael G. Sloan
+* Nathan J. Hurst
+* Peter J. R. Moulder
diff --git a/src/3rdparty/2geom/doc/manual2/concepts b/src/3rdparty/2geom/doc/manual2/concepts
new file mode 100644
index 0000000..e89bf55
--- /dev/null
+++ b/src/3rdparty/2geom/doc/manual2/concepts
@@ -0,0 +1,128 @@
+h1. Concept Checking
+
+The C++ Standard Template Library introduces the notion of _concepts_,
+which specify families of types related by a common interface. In
+template-based programming with the STL, concepts serve a similar
+purpose to type classes in Haskell. While, unlike Haskell's language-level
+support for type classes, concept-checking is not directly supported by the
+C++ compiler or language, C++ libraries have been written which use template
+techniques to provide compile-time checking and enforcement of concepts.
+We use the Boost Concept Checking library.
+
+h2. Lib2geom's 'Concepts'
+
+There are several important lib2geom 'concepts'.
+
+h3. *FragmentConcept*
+
+This is perhaps the most important concept within lib2geom, as it defines
+the interface for the basic, one-dimensional functions. Fragments are
+defined on the interval [0,1], which is referred to as the _intended domain_
+of the function. Functions may be well defined for all values (many are),
+but the 0-to-1 domain has significant semantic value. When the functions
+are used to represent a *Curve*, 0 is the start and 1 is the end.
+
+h4. @ T::output_type @
+
+Every fragment must typedef an *output_type*. This is usually *Coord*, however,
+in order to support considering @D2<T>@ a fragment, this typedef was added.
+This information is also used by the compiler to infer the proper bounds and
+sbasis types.
+
+h4. Value Query
+
+<pre><code>
+output_type T::valueAt(double);
+output_type T::operator()(double);
+output_type T::at0();
+output_type T::at1();
+</code></pre>
+
+*FragmentConcept* defines several methods for retrieving the value at a point.
+One method is to use the *valueAt* function, which returns output_type given
+a t-value. Fragments are also functors, which in C++ lingo means they look
+like function calls, as they overload the () operator. This is essentially
+the same as calling valueAt. The functions *at0* and *at1* are also
+provided, and should be used whenever the start or end of the function is
+required, as many functions directly store this information.
+
+h4. @ sbasis_type T::toSBasis() @
+
+As *SBasis* will be the main function representation, it is desirable to always
+be able to approximate and deal with other functions in this way. Therefore,
+the *toSBasis* function is required. When *output_type* is @double@,
+@sbasis_type@ is *SBasis*. When *output_type* is *Point*, @sbasis_type@ is
+*SBasisCurve*.
+
+(TODO: in writing this it occurs to me that toSBasis should take a tolerance)
+
+h4. @ T reverse(T) @
+
+As most of the implementors of fragment consider functions in a fairly
+symmetric way, the *reverse* function was included in the *FragmentConcept*.
+*reverse* flips the function's domain on 0.5, such that f'(t) = f(1-t).
+
+h4. Bounds
+
+<code><pre>
+bounds_type bounds_fast(T);
+bounds_type bounds_exact(T);
+bounds_type bounds_local(T, Interval);
+</pre></code>
+
+Finding the bounds of a function is essential for many optimizations and
+algorithms. This is why we provide 3 functions to do it. *bounds_fast*
+provides a quick bounds which contains the actual bounds of the function.
+This form is ideal for optimization, as it hopefully does not require too
+much computation. *bounds_exact*, on the other hand, provides the exact
+bounds of the function. *bounds_local* only returns the bounds of an
+interval on the function - at the moment it is unclear if this is exact.
+When *output_type* is @double@, @bounds_type@ is *Interval*. When
+*output_type* is @Point@, @bounds_type@ is *Rect*.
+
+See the linear.h code for an example of an implementation of *FragmentConcept*.
+
+h3. *OffsetableConcept*
+
+*OffsetableConcept* defines what it means to be offsetable. Like
+*FragmentConcept*, this concept requires an output_type, which is used
+as the offset type. This still makes since when the implementor is
+also a fragment, as in pretty much all cases you would want to offset
+a function using the same type it outputs.
+
+The following operators are defined by *OffsetableConcept*:
+
+@T + output_type, T - output_type, T += output_type, T -= output_type@,
+
+h3. *ScalableConcept*
+
+*ScalableConcept* defines what it means to be scalable. Like
+*OffsetableConcept*, it requires an output_type, which is used as the
+scalar-type. This is an assumption that may not pan out in the future,
+however, for all function types we've used this always applies.
+Technically points should not be multiplicable, however, they provide a
+convenient storage mechanism for non-uniform scaling. If this changes
+in the future, the implementations will remain the same, while the
+concept definitions are loosened.
+
+The following operators are defined by *ScalableConcept*:
+@T * scalar_type, T / scalar_type, T *= scalar_type, T /= scalar_type, -x@,
+
+h3. *AddableConcept*
+
+*AddableConcept* defines a concept for classes which are closed under
+addition (the classes may be added to themselves, and the result is the
+same type). The following operators are included:
+
+@x + y, x - y, x += y, x -= y@
+
+h3. *MultiplicableConcept*
+
+*MultiplicableConcept* defines a concept for classes which are closed under
+multiplication (the classes may be multiplied by themselves, and the result
+is the same type). The following operators are included:
+
+@x * y, x *= y@
+
+At some point a DividableConcept may be implemented, however, at the moment
+it is not very useful.
diff --git a/src/3rdparty/2geom/doc/manual2/d2 b/src/3rdparty/2geom/doc/manual2/d2
new file mode 100644
index 0000000..b4769e0
--- /dev/null
+++ b/src/3rdparty/2geom/doc/manual2/d2
@@ -0,0 +1,106 @@
+h1. Dealing with two Dimensions: *D2*
+
+After writing a few classes for two dimensional objects, we realized
+that there is a lot of boilerplate associated with what is essentially
+lifting one dimensional concepts into two. Instead of frequently
+rewriting this code, we instead created the *D2* template class.
+
+For example, a point in space might be represented by *D2<double>*.
+This may, in fact, become the actual representation for Point.
+We have not yet replaced Point with this, as not all of Points
+operations have been ported (or are applicable), and we are not
+yet sure if there is 0 performance loss.
+
+(TODO remove previous stuff if D2<double> becomes point repr)
+
+h2. Component Access
+
+One might expect such an object to have @.x@ and @.y@ fields, however,
+it instead consists of 2 element array. With LibNR, it was found that
+the availability of @.x@ and @.y@ encouraged people to attempt to
+inline operations rather than using the operators, perhaps in (vain)
+pursuit of a performance enhancement. By using an array, we encourage
+people to think about points as symmetric objects and discourage
+direct use of the components. However, we still provide direct access
+for the rare occasion that it is needed. Even in these cases, the array
+method reduces bugs by encouraging iteration over the array rather than
+explicit element reference.
+
+The components of a *D2* are accessed through the indexing operator, [].
+The input value to the index operator is the @enum@ *Dim2*, which
+defines *X* = 0 and *Y* = 1. This is to encourage using the
+@for(int d=0; i<2; i++)@ idiom when normal operations do not suffice.
+
+h2. Arithmetic Operators
+
+@D2<T>@ implements the *AddableConcept*, *OffsetableConcept*, and
+*ScalableConcept* (if @T@ implements them as well) yielding the
+following operators:
+
+<pre><code>
+AddableConcept: x + y, x - y, x += y, x -= y
+OffsetableConcept: x + p, x - p, x += p, x -= p
+ScalableConcept: x * p, x / p, x *= p, x /= p, -x
+ x * d, x / d, x *= d, x /= d
+</code></pre>
+
+(where @x@ and @y@ are *D2*, d is *Coord*, and @p@ is a *Point* and all
+return @D2<T>@)
+
+These operators all just apply the operation on @T@ to the components.
+So, @a + b@ just returns @D2<T>(a[X] + b[X], a[Y] + b[Y])@, though the
+actual code uses a loop (which is unrolled) in order to avoid
+bugs.
+
+h2. Geometric Operations
+
+<pre><code>
+T dot(D2<T> const &, D2<T> const &);
+T cross(D2<T> const &, D2<T> const &);
+</code></pre>
+
+The *dot*:http://en.wikipedia.org/wiki/Dot@product and
+*cross*:http://en.wikipedia.org/wiki/Cross@product products are defined
+on D2<T> when T implements *AddableConcept* and *MultiplicableConcept.
+The cross function returns the length of the resultant 3d vector
+perpendicular to the 2d plane.
+
+@ D2<T> operator*(D2<T> const &, Matrix const &)@
+
+This operation applies an affine transformation to the 2d object.
+
+h2. Fragment Lifting
+
+*D2<T>* also implements FragmentConcept if T implements it as well,
+allowing *D2* to lift one dimensional functions into two-dimensional
+parametric curves. As a fragment, a *D2* will represent a function
+from a double to a Point.
+
+h3. Fragment Operations
+
+In addition to the normal set of Fragment methods, D2 has the following
+functions:
+
+h4. @ D2<T> compose(D2<T> const &a, T const &b); @
+
+The *compose* function is defined when @T@ is a function representation which
+supports composition. The only forms in 2geom are *SBasis* and *SBasis2d*.
+The *D2* *compose* function composes @b@ on both components of @a@. This
+makes sense, as a D2<SBasis> is double -> D2<double> and the function for
+composition is double -> double. One way to think of composition is that
+the output is equivalent to applying @b@ to the input, and then applying a
+to @b@'s output.
+
+h4. @ D2<T> compose_each(D2<T> const &a, D2<T> &b); @
+
+The *compose_each* function is similar to the *compose* function, except that
+@b@ is also a *D2*, so instead of composing the same function on each component,
+the two functions in @b@ are used.
+
+
+h4. @ Point D2<T>::operator()(double x, double y) const @
+
+*D2* wraps this operator for when @T@ is a function taking a 2 component input.
+The only case of this currently within 2geom is SBasis2d.
+
+(TODO: derivative/integral)
diff --git a/src/3rdparty/2geom/doc/manual2/geometric primitives b/src/3rdparty/2geom/doc/manual2/geometric primitives
new file mode 100644
index 0000000..b78370e
--- /dev/null
+++ b/src/3rdparty/2geom/doc/manual2/geometric primitives
@@ -0,0 +1,65 @@
+h1. Geometric Primitives
+
+What good is a geometry library without geometric primitives? By this
+I mean the very basic stuff, Points/Vectors, Matrices, etc.
+
+2geom's primitives are descendant from libNR's geometric primitives.
+They have been modified quite a bit since that initial import.
+
+h2. Point
+
+!media/point.png!
+
+The mathematical concepts of points and vectors are merged into the
+2geom class called *Point*. See Appendix A for a further
+discussion of this decision.
+
+Point may be interpreted as a D2<double> with some additional operations.
+
+(TODO: document these ops.)
+
+\section{Transformations}
+
+Affine transformations are either represented with a canonical 6
+element matrix, or special forms.
+
+\subsection{Scale}
+
+\includegraphics[height=50mm]{media/scale.png}
+
+A \code{Scale} transformation stores a vector representing a scaling
+transformation.
+
+\subsection{Rotate}
+
+\includegraphics[height=50mm]{media/rotate.png}
+
+A \code{Rotate} transformation uses a vector(\code{Point}) to store
+a rotation about the origin.
+
+In correspondence with mathematical convention (y increasing upwards),
+0 degrees is encoded as a vector pointing along the x axis, and positive
+angles indicate anticlockwise rotation. So, for example, a vector along
+the y axis would encode a 90 degree anticlockwise rotation of 90 degrees.
+
+In the case that the computer convention of y increasing downwards,
+the \verb}Rotate} transformation works essentially the same, except
+that positive angles indicate clockwise rotation.
+
+\subsection{Translate}
+
+\includegraphics[height=70mm]{media/translate.png}
+
+A \code{Translate} transformation is a simple vector(\code{Point})
+which stores an offset.
+
+\subsection{Matrix}
+
+\includegraphics[height=70mm]{media/matrix.png}
+
+A \code{Matrix} is a general affine transform. Code is provided for
+various decompositions, constructions, and manipulations. A
+\code{Matrix} is composed of 6 coordinates, essentially storing the
+x axis, y axis, and offset of the transformation. A detailed
+explanation for matrices is given in Appendix B.
+
diff --git a/src/3rdparty/2geom/doc/manual2/introduction b/src/3rdparty/2geom/doc/manual2/introduction
new file mode 100644
index 0000000..f8c71fc
--- /dev/null
+++ b/src/3rdparty/2geom/doc/manual2/introduction
@@ -0,0 +1,41 @@
+h1. Introduction
+
+This manual focuses on the lib2geom computational geometry framework.
+The main goal of this framework is the eventual replacement of
+Inkscape's multiple and shoddy geometry frameworks. As with any decent
+module or lib, 2geom is designed to achieve the desired functionality
+while maintaining a generality encouraging usage within other
+applications. The focus on robust, accurate algorithms, as well as
+utilization of newer and better representations makes the lib
+very attractive for many applications.
+
+h2. Design Considerations
+
+2Geom is written with a functional programming style in mind.
+Generally data structures are considered immutable and rather than
+assignment we use labeling. However, C++ can become unwieldy if
+this is taken to extreme and so a certain amount of pragmatism is
+used in practice. In particular, usability is not forgotten in the
+mires of functional zeal.
+
+The code relies strongly on the type system and uses some of the more
+'tricky' elements of C++ to make the code more elegant and 'correct'.
+Despite this, the intended use of 2Geom is a serious vector graphics
+application. In such domains, performance is still used as a quality
+metric, and as such we consider inefficiency to be a bug, and have
+traded elegance for efficiency where it matters.
+
+In general the data structures used in 2Geom are relatively 'flat'
+and require little from the memory management. Currently most data
+structures are built on standard STL headers, and new and delete are
+used sparingly. It is intended for 2Geom to be fully compatible with
+Boehm garbage collector though this has not yet been tested.
+
+h2. Toy-Based Development
+
+We have managed to come up with a method of library development
+which is perfect for geometry - the development of toys exemplifying
+a feature while the feature is perfected. This has somewhat subsumed
+the role of tests, and provides immediate motivation/reward for work.
+
+!media/gear.png!
diff --git a/src/3rdparty/2geom/doc/manual2/piecewise b/src/3rdparty/2geom/doc/manual2/piecewise
new file mode 100644
index 0000000..9f1bd98
--- /dev/null
+++ b/src/3rdparty/2geom/doc/manual2/piecewise
@@ -0,0 +1,134 @@
+h1. *Piecewise*
+
+In order to represent functions with a complex shape, it is necessary
+to define functions in a piecewise manner. In the graphics world this
+sort of function, when parametric, is often referred to as a 'spline'.
+Even beyond the representation of paths, it is also often necessary
+for mathematical operations to return piecewise functions, as otherwise
+the single-fragment versions would require an inordinate degree to
+still be accurate. An example of this is the *inverse* function.
+
+In the world of lib2geom, this is implemented as the *Piecewise*
+template class. It manages a sequence of fragment 'segments' and the
+cuts between them. These cuts are the various t-values which separate
+the different segments.
+
+h2. Cuts
+
+The first and last cuts of a piecewise define it's intended range, and
+the intermediary cuts separate the segments. With indices, segment i
+is always bordered on the left with cut i and on the right with cut i+1.
+In general, c = s+1, where c is the number of cuts and s is the number
+of segments. These invariants are checked by the
+@bool Piecewise<T>::invariants();@ method.
+
+The cuts essentially define the position and scale of each segment.
+For example, if the left and right cuts are 0.5 apart, the segment is
+half its regular size; the derivative will be twice as big.
+
+h4. Cut Query Functions
+
+<pre><code>
+unsigned Piecewise<T>::segN(double, int low = 0, int high = -1) const;
+double Piecewise<T>::segT(double, int = -1) const;
+double mapToDomain(double t, unsigned i) const;
+</code></pre>
+
+These functions use the cut information to ascertain which segment a
+t-value lies within ( *segN* ), and what the t-value is for that segment
+at that particular point ( *segT* ). *segN* takes two optional parameters
+which limit the range of the search, and are used internally as it is
+defined as a recursive binary search. These may be used if you are sure
+that the desired segment index lies within the range. *segT* takes an
+optional parameter for the case where you already know the segment number.
+
+mapToDomain is the inverse of segT, as it takes a t-value for a particular
+segment, and returns the global piecewise time for that point.
+
+h4. @ Interval Piecewise<T>::domain() const; @
+
+The *domain* function returns the Interval of the intended domain of the
+function, from the first cut to the last cut.
+
+h4. Cut Modification Functions
+
+<pre><code>
+void Piecewise<T>::offsetDomain(double o)
+void Piecewise<T>::scaleDomain(double s)
+void Piecewise<T>::setDomain(Interval dom)
+</code></pre>
+
+These functions very simply transform the cuts with linear transformations.
+
+h3. Technical Details
+
+As the cuts are simply a public std::vector, they may also be accessed as
+@pw.cuts@.
+
+While the actual segments begin on the first cut and end on the last,
+the function is defined throughout all inputs by extending the first
+and last segments. The exact switching between segments is arbitrarily
+such that beginnings (t=0) have priority over endings (t=1). This only
+really matters if it is discontinuous at that location.
+
+In the context of 2d parametrically defined curves, the usefulness of cuts
+becomes less apparrent, as they make no real difference for the display
+of the curves. Rather, cuts become more of an agreement between various
+functions such that the proper data aligns.
+
+h2. Construction
+
+Most of the time there is no need for raw construction of *Piecewise*
+functions, as they are usually obtained from operations and other sources.
+
+The following constructors defined for *Piecewise*:
+* The blank constructor
+* A constructor which explicitly lifts a fragment to a *Piecewise* on [0,1]
+* A constructor which takes the *output_type*, and creates a constant function
+
+<pre><code>
+void Piecewise<T>::push_seg(T);
+void Piecewise<T>::push_cut(double);
+void Piecewise<T>::push(T, double);
+</code></pre>
+
+The usual method for raw construction is to construct a blank *Piecewise*
+function, and use these push methods to load the content. *push_seg* and
+*push_cut* simply add to the segment and cut lists, although *push_cut*
+also checks that the cut time is larger than the last cut. The current
+recommended method for calling these functions is to have one initial
+*push_cut*, followed by successive calls to *push*, as this will guarantee
+that the cuts and segments properly align.
+
+h2. Operations
+
+h3. Arithmetic
+
+*Piecewise* has many arithmetic operations, and implements
+*OffsetableConcept*, *ScalableConcept*, *AddableConcept*, and
+*MultiplicableConcept*. The operations which operate on two Piecewise
+functions (Addable and Multiplicable) work by interleaving the cuts using
+mutual *partition* calls, and iterating the resulting segments.
+
+h3. Fragment Wrapping
+
+While *Piecewise* is not a fragment (it does not have the [0,1] domain),
+it has many functions reminiscient of *FragmentConcept*, including the
+bounds functions, () and valueAt.
+
+(TODO: reverse function?)
+
+h3. Concatenation
+
+<pre><code>
+void Piecewise<T>::concat(const Piecewise<T> &other);
+void Piecewise<T>::continuousConcat(const Piecewise<T> &other);
+</code></pre>
+
+These functions efficiently append another *Piecewise* to the end of a
+*Piecewise*. They offset the _other_ *Piecewise* in time such that it is
+flush with the end of this *Piecewise*. *continuousConcat* is basically
+the same except that it also offsets in space so the functions also match
+in value.
+
+(TODO: compose/derivative/integral)
diff --git a/src/3rdparty/2geom/doc/manual2/s-basis b/src/3rdparty/2geom/doc/manual2/s-basis
new file mode 100644
index 0000000..5f2ddfb
--- /dev/null
+++ b/src/3rdparty/2geom/doc/manual2/s-basis
@@ -0,0 +1,91 @@
+h1. S-Power-Basis-Forms
+
+2Geom provides a very powerful algebra for modifying paths. Although
+paths are kept in an extended SVG native form where possible, many
+operations require a more mathematical form. Our prefferred form is
+a sequence of s-power basis polynomials, henceforth referred to as
+s-basis. We may convert to this form, perform the required operations
+and convert back, approximating to a requested tolerance as required.
+
+The precise details of the s-basis form are beyond the scope of this
+manual - the interested reader should consult \cite{SanchezReyes1997,SanchezReyes2000,SanchezReyes2001,SanchezReyes2003,SanchezReyes2004}.
+An elementary, functional description is given in Appendix C.
+
+(TODO: work out textile citations, math inclusion)
+
+Geometrically important properties:
+* exact representation of bezier segments
+* low condition number on bezier conversion.
+* strong convergence guarantees
+* $C^0$ continuity guarantee
+
+The following operations are directly implementable and are very efficient:
+* fast conversion from all svg elements
+* basic arithmetic - @+@, @-@, $\times$, $\div$
+* algebraic derivative and integral
+* elementary trigonometric functions: $\sqrt{\cdot}$, $\sin(\cdot)$, $\cos(\cdot)$, $\exp(\cdot)$
+* efficient degree elevation and reduction
+* function inversion
+* exact solutions for many non trivial operations
+* root finding
+* composition
+
+All of these operations are fast. For example, multiplication of two
+beziers by converting to s-basis form, multiplying and converting back
+takes roughly the same time as performing the bezier multiplication
+directly, and furthermore, subdivision and degree reduction are
+straightforward in this form.
+
+h2. Implementation
+
+h3. *Linear*
+
+The *Linear* class represents a linear function, mostly for use as a
+building block for *SBasis*. *Linear* fully implements *AddableConcept*,
+*OffsetableConcept*, and *ScalableConcept* yielding the following operators:
+
+<pre><code>
+ AddableConcept: x + y, x - y, x += y, x -= y
+ OffsetableConcept: x + d, x - d, x += d, x -= d
+ ScalableConcept: x * d, x / d, x *= d, x /= d, -x
+</code></pre>
+
+(where @x@ and @y@ are *Linear*, d is *Coord*, and all return *Linear*)
+
+As *Linear* is a basic function type, it also implements the *FragmentConcept*.
+
+The main *Linear* constructor accepts two *Coord* values, one for the Linear's
+value at 0, and one for its value at 1. These may then later be accessed and
+modified with the indexing operator, @[]@, with a value of 0 or 1.
+
+h3. *SBasis*
+
+The *SBasis* class provides the most basic function form,
+$f(t) \rightarrow y$. *SBasis* are made up of multiple *Linear* elements,
+which store to/from values for each polynomial coefficient.
+
+*SBasis*, like *Linear*, above, fully implements *AddableConcept*,
+*OffsetableConcept*, and *ScalableConcept*.
+
+As *SBasis* is a basic function type, it implements the *FragmentConcept*.
+
+Usually you do not have to directly construct SBasis, as they are obtained
+one way or another, and many of the operations are defined, however, *SBasis*
+may be constructed as an implicit *Linear* cast, as a copy, or as a blank.
+The class is actually an extension of @std::vector<Linear>@. This provides
+the primary method of raw *SBasis* construction -- @push_back(Linear)@, which
+adds another coefficient to the *SBasis*.
+
+*SBasis* also provides the indexing accessor/mutator, and due to its vector
+nature, iteration.
+
+(TODO: wouldn't the indexing be provided by vector any way?)
+
+h3. *SBasis2D*
+
+SBasis2D provides a multivariate form - functions of the form
+$f(u,v) \rightarrow z$. These can be used for arbitrary distortion
+functions (take a path $p(t) \rightarrow (u,v)$ and a pair of surfaces
+$f(u,v),g(u,v)$ and compose: $q(t) = (f(p(t)), g(p(t)))$.
+
+(TODO: flesh out this section)
diff --git a/src/3rdparty/2geom/doc/media/2geom-logo.png b/src/3rdparty/2geom/doc/media/2geom-logo.png
new file mode 100644
index 0000000..af9a33c
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/2geom-logo.png
Binary files differ
diff --git a/src/3rdparty/2geom/doc/media/Rect.svg b/src/3rdparty/2geom/doc/media/Rect.svg
new file mode 100644
index 0000000..dab8ebd
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/Rect.svg
@@ -0,0 +1,283 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="777"
+ height="555"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.44+devel"
+ sodipodi:docbase="/home/michael/2geom/trunk/doc/media"
+ sodipodi:docname="Rect.svg"
+ version="1.0"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/michael/2geom/trunk/doc/media/scale.png"
+ inkscape:export-xdpi="200"
+ inkscape:export-ydpi="200"
+ sodipodi:modified="true">
+ <metadata
+ id="metadata48">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ inkscape:window-height="855"
+ inkscape:window-width="1113"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ inkscape:zoom="8"
+ inkscape:cx="84.25586"
+ inkscape:cy="337.26288"
+ inkscape:window-x="157"
+ inkscape:window-y="140"
+ inkscape:current-layer="g2227"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <sodipodi:guide
+ orientation="vertical"
+ position="111.36932"
+ id="guide4172" />
+ <sodipodi:guide
+ orientation="horizontal"
+ position="411.53615"
+ id="guide4174" />
+ </sodipodi:namedview>
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mend"
+ style="overflow:visible;">
+ <path
+ id="path3249"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.4) rotate(180) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mend"
+ style="overflow:visible;">
+ <path
+ id="path3212"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(0,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mstart"
+ style="overflow:visible">
+ <path
+ id="path3233"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.4) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Sstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Sstart"
+ style="overflow:visible">
+ <path
+ id="path3227"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.2) translate(6,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Send"
+ style="overflow:visible;">
+ <path
+ id="path3224"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.2) rotate(180) translate(6,0)" />
+ </marker>
+ <linearGradient
+ id="linearGradient4094">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1;"
+ offset="0"
+ id="stop4096" />
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:0;"
+ offset="1"
+ id="stop4098" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4062">
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1;"
+ offset="0"
+ id="stop4064" />
+ <stop
+ style="stop-color:#babdb6;stop-opacity:0;"
+ offset="1"
+ id="stop4066" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4040">
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1;"
+ offset="0"
+ id="stop4042" />
+ <stop
+ style="stop-color:#babdb6;stop-opacity:0;"
+ offset="1"
+ id="stop4044" />
+ </linearGradient>
+ <radialGradient
+ xlink:href="#linearGradient4062"
+ id="radialGradient4079"
+ gradientUnits="userSpaceOnUse"
+ cx="8"
+ cy="-16"
+ fx="8"
+ fy="-16"
+ r="108" />
+ <linearGradient
+ xlink:href="#linearGradient4040"
+ id="linearGradient4081"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(80,376)"
+ x1="328.5"
+ y1="-43.664978"
+ x2="328.5"
+ y2="116.68156" />
+ <linearGradient
+ xlink:href="#linearGradient4094"
+ id="linearGradient4116"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.35905,0,0,1.35905,203.6646,-185.2813)"
+ x1="95.105873"
+ y1="363.72418"
+ x2="95.105873"
+ y2="502.67734" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4040"
+ id="linearGradient3175"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-2.121444)"
+ x1="426.27966"
+ y1="483.83633"
+ x2="426.27966"
+ y2="522.72052" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4094"
+ id="linearGradient3177"
+ gradientUnits="userSpaceOnUse"
+ x1="407.09628"
+ y1="374.48508"
+ x2="407.09628"
+ y2="485.16641" />
+ </defs>
+ <g
+ id="g2919"
+ transform="matrix(0.319896,0,0,0.319896,48.45544,81.50285)">
+ <path
+ id="path2921"
+ d="M 163.15,27.83 L 28.81,165.3 C -16.58,221.51 59.7,214.97 92.4,231.16 C 104.13,243.15 47.44,252 59.17,264 C 70.9,275.99 130.1,287.1 141.85,299.09 C 153.58,311.08 117.84,323.8 129.57,335.79 C 141.3,347.78 168.43,336.42 173.51,364.1 C 177.13,383.88 222.4,372.6 244.54,356.4 C 256.27,344.4 222.1,345.53 233.83,333.54 C 263,303.71 290.16,322.7 300.14,292.81 C 305.07,278.04 257.2,270.04 268.95,258.05 C 302.7,238.34 419.35,225.51 364,170.16 L 224.75,27.83 C 207.72,11.48 179.3,11.3 163.15,27.83 z M 130.99,238.57 C 134,238.57 231.54,251.61 193.9,261.92 C 179.72,265.8 113.53,238.57 130.99,238.57 z M 317.46,292.81 C 317.46,299.63 367.71,304.1 367.71,291.2 C 360.55,270.48 323.4,271.88 317.46,292.81 z M 91.1,329.05 C 103,339.34 121.38,326.49 126.89,312.13 C 115.36,296.81 72.2,312.68 91.1,329.05 z M 311.16,306.82 C 295.82,320.58 312.88,334.54 328,325.65 C 331.37,322.23 327.91,310.24 311.16,306.82 z "
+ style="fill:none;stroke:black;stroke-opacity:1" />
+ <path
+ id="path2925"
+ d="M 216.63,37.47 L 269.78,91.45 C 274.82,96.6 275.91315,108.88098 271.93,109.45 C 266.29292,110.2553 260.02293,94.034313 251.80374,94.034313 C 242.7616,94.034313 245.43878,123.58602 238.07227,123.58602 C 230.29748,123.58602 227.72697,107.96 218.30004,107.96 C 210.67739,107.96 205.51399,129.13114 194.80001,129.13114 C 185.2927,129.13114 177.02987,83.24 171.29999,83.24 C 166.28062,83.24 163.47697,123.96 152.33,123.96 C 133.73263,123.96 105.14,123.84 105.14,123.84 C 95.7,123.82 97.27,114.63 106.4,104.78 C 125.16,84.53 161.15,49.43 172.85,37.47 C 184.61,25.45 205.1,25.79 216.63,37.47 z "
+ style="fill:none;stroke:black;stroke-opacity:1"
+ sodipodi:nodetypes="cccsssssscccc" />
+ </g>
+ <g
+ id="g2227"
+ transform="matrix(1.448783,0,0,1.133904,-50.0431,-19.23223)">
+ <rect
+ style="fill:none;fill-opacity:1;stroke:black;stroke-width:0.24958529;stroke-miterlimit:4;stroke-dasharray:1.49751161, 1.49751161;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect2208"
+ width="80.412262"
+ height="101.14787"
+ x="71.123871"
+ y="93.46669" />
+ <path
+ sodipodi:type="arc"
+ style="fill:black;fill-opacity:1;stroke:none;stroke-width:0.31989604;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path2212"
+ sodipodi:cx="160"
+ sodipodi:cy="193"
+ sodipodi:rx="1.25"
+ sodipodi:ry="1.25"
+ d="M 161.25 193 A 1.25 1.25 0 1 1 158.75,193 A 1.25 1.25 0 1 1 161.25 193 z"
+ transform="matrix(0.690234,0,0,0.881909,41.08823,-76.69567)" />
+ <text
+ xml:space="preserve"
+ style="font-size:7.80207539px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Serif"
+ x="172.75986"
+ y="83.146294"
+ id="text3986"
+ transform="scale(0.88468,1.130352)"><tspan
+ sodipodi:role="line"
+ id="tspan3988"
+ x="172.75986"
+ y="83.146294">P<tspan
+ style="font-size:6.24165869px"
+ id="tspan3990"
+ dx="-1.7240311"
+ dy="1.9998763">max</tspan></tspan></text>
+ <path
+ transform="matrix(0.690234,0,0,0.881909,-39.39108,24.30456)"
+ d="M 161.25 193 A 1.25 1.25 0 1 1 158.75,193 A 1.25 1.25 0 1 1 161.25 193 z"
+ sodipodi:ry="1.25"
+ sodipodi:rx="1.25"
+ sodipodi:cy="193"
+ sodipodi:cx="160"
+ id="path3992"
+ style="fill:black;fill-opacity:1;stroke:none;stroke-width:0.31989604;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ sodipodi:type="arc" />
+ <text
+ transform="scale(0.88468,1.130352)"
+ id="text3994"
+ y="176.88782"
+ x="67.843575"
+ style="font-size:7.80207253px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Serif"
+ xml:space="preserve"><tspan
+ y="176.88782"
+ x="67.843575"
+ id="tspan3996"
+ sodipodi:role="line">P<tspan
+ dy="1.9998755"
+ dx="-1.7240307"
+ id="tspan3998"
+ style="font-size:6.24165726px">min</tspan></tspan></text>
+ </g>
+</svg>
diff --git a/src/3rdparty/2geom/doc/media/bezier-curve-evaluation.png b/src/3rdparty/2geom/doc/media/bezier-curve-evaluation.png
new file mode 100644
index 0000000..adb2476
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/bezier-curve-evaluation.png
Binary files differ
diff --git a/src/3rdparty/2geom/doc/media/convex.png b/src/3rdparty/2geom/doc/media/convex.png
new file mode 100644
index 0000000..a5eba70
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/convex.png
Binary files differ
diff --git a/src/3rdparty/2geom/doc/media/convex.svg b/src/3rdparty/2geom/doc/media/convex.svg
new file mode 100644
index 0000000..fea1694
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/convex.svg
@@ -0,0 +1,232 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="777"
+ height="555"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.44+devel"
+ sodipodi:docbase="/home/michael/2geom/trunk/doc/media"
+ sodipodi:docname="convex.svg"
+ version="1.0"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/michael/2geom/trunk/doc/media/scale.png"
+ inkscape:export-xdpi="200"
+ inkscape:export-ydpi="200"
+ sodipodi:modified="true">
+ <metadata
+ id="metadata48">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ inkscape:window-height="855"
+ inkscape:window-width="1113"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ inkscape:zoom="2.8284271"
+ inkscape:cx="93.656296"
+ inkscape:cy="405.77902"
+ inkscape:window-x="157"
+ inkscape:window-y="140"
+ inkscape:current-layer="g2919"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <sodipodi:guide
+ orientation="vertical"
+ position="111.36932"
+ id="guide4172" />
+ <sodipodi:guide
+ orientation="horizontal"
+ position="411.53615"
+ id="guide4174" />
+ </sodipodi:namedview>
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mend"
+ style="overflow:visible;">
+ <path
+ id="path3249"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.4) rotate(180) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mend"
+ style="overflow:visible;">
+ <path
+ id="path3212"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(0,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mstart"
+ style="overflow:visible">
+ <path
+ id="path3233"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.4) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Sstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Sstart"
+ style="overflow:visible">
+ <path
+ id="path3227"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.2) translate(6,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Send"
+ style="overflow:visible;">
+ <path
+ id="path3224"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.2) rotate(180) translate(6,0)" />
+ </marker>
+ <linearGradient
+ id="linearGradient4094">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1;"
+ offset="0"
+ id="stop4096" />
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:0;"
+ offset="1"
+ id="stop4098" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4062">
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1;"
+ offset="0"
+ id="stop4064" />
+ <stop
+ style="stop-color:#babdb6;stop-opacity:0;"
+ offset="1"
+ id="stop4066" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4040">
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1;"
+ offset="0"
+ id="stop4042" />
+ <stop
+ style="stop-color:#babdb6;stop-opacity:0;"
+ offset="1"
+ id="stop4044" />
+ </linearGradient>
+ <radialGradient
+ xlink:href="#linearGradient4062"
+ id="radialGradient4079"
+ gradientUnits="userSpaceOnUse"
+ cx="8"
+ cy="-16"
+ fx="8"
+ fy="-16"
+ r="108" />
+ <linearGradient
+ xlink:href="#linearGradient4040"
+ id="linearGradient4081"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(80,376)"
+ x1="328.5"
+ y1="-43.664978"
+ x2="328.5"
+ y2="116.68156" />
+ <linearGradient
+ xlink:href="#linearGradient4094"
+ id="linearGradient4116"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.35905,0,0,1.35905,203.6646,-185.2813)"
+ x1="95.105873"
+ y1="363.72418"
+ x2="95.105873"
+ y2="502.67734" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4040"
+ id="linearGradient3175"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-2.121444)"
+ x1="426.27966"
+ y1="483.83633"
+ x2="426.27966"
+ y2="522.72052" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4094"
+ id="linearGradient3177"
+ gradientUnits="userSpaceOnUse"
+ x1="407.09628"
+ y1="374.48508"
+ x2="407.09628"
+ y2="485.16641" />
+ </defs>
+ <g
+ id="g2919"
+ transform="matrix(0.319896,0,0,0.319896,48.45544,81.50285)">
+ <path
+ id="path2921"
+ d="M 163.15,27.83 L 28.81,165.3 C -16.58,221.51 59.7,214.97 92.4,231.16 C 104.13,243.15 47.44,252 59.17,264 C 70.9,275.99 130.1,287.1 141.85,299.09 C 153.58,311.08 117.84,323.8 129.57,335.79 C 141.3,347.78 168.43,336.42 173.51,364.1 C 177.13,383.88 222.4,372.6 244.54,356.4 C 256.27,344.4 222.1,345.53 233.83,333.54 C 263,303.71 290.16,322.7 300.14,292.81 C 305.07,278.04 257.2,270.04 268.95,258.05 C 302.7,238.34 419.35,225.51 364,170.16 L 224.75,27.83 C 210.9464,14.577576 189.65976,11.948591 173.48938,20.230605 C 169.70978,22.166415 166.20969,24.698322 163.15,27.83 z M 130.99,238.57 C 134,238.57 231.54,251.61 193.9,261.92 C 179.72,265.8 113.53,238.57 130.99,238.57 z M 317.46,292.81 C 317.46,299.63 367.71,304.1 367.71,291.2 C 360.55,270.48 323.4,271.88 317.46,292.81 z M 91.1,329.05 C 103,339.34 121.38,326.49 126.89,312.13 C 115.36,296.81 72.2,312.68 91.1,329.05 z M 311.16,306.82 C 295.82,320.58 312.88,334.54 328,325.65 C 331.37,322.23 327.91,310.24 311.16,306.82 z "
+ style="fill:none;stroke:black;stroke-opacity:1"
+ sodipodi:nodetypes="cccccscccscccsccccccccccccc" />
+ <path
+ id="path2925"
+ d="M 216.63,37.47 L 269.78,91.45 C 274.82,96.6 275.91315,108.88098 271.93,109.45 C 266.29292,110.2553 260.02293,94.034313 251.80374,94.034313 C 242.7616,94.034313 245.43878,123.58602 238.07227,123.58602 C 230.29748,123.58602 227.72697,107.96 218.30004,107.96 C 210.67739,107.96 205.51399,129.13114 194.80001,129.13114 C 185.2927,129.13114 177.02987,83.24 171.29999,83.24 C 166.28062,83.24 163.47697,123.96 152.33,123.96 C 133.73263,123.96 105.14,123.84 105.14,123.84 C 95.7,123.82 97.27,114.63 106.4,104.78 C 125.16,84.53 161.15,49.43 172.85,37.47 C 184.61,25.45 205.1,25.79 216.63,37.47 z "
+ style="fill:none;stroke:black;stroke-opacity:1"
+ sodipodi:nodetypes="cccsssssscccc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:black;stroke-width:0.99999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 42.801407,152.5919 L 57.629203,134.09469 L 102.53048,88.663078 L 109.248,85.127547 L 116.31907,86.364976 L 164.40234,135.15534 L 182.61033,153.36334 L 166.1701,178.99597 L 153.61895,185.5367 L 148.31566,188.71869 L 119.58944,200.82789 L 105.27053,204.27504 L 81.58245,189.95612 L 71.594568,181.736 L 42.801407,152.5919 z "
+ id="path2213"
+ transform="matrix(3.126016,0,0,3.126016,-151.4725,-254.7792)"
+ sodipodi:nodetypes="ccccccccccccccc" />
+ </g>
+ <g
+ id="g2227"
+ transform="matrix(1.448783,0,0,1.133904,-50.0431,-19.23223)" />
+</svg>
diff --git a/src/3rdparty/2geom/doc/media/coords.png b/src/3rdparty/2geom/doc/media/coords.png
new file mode 100644
index 0000000..343a993
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/coords.png
Binary files differ
diff --git a/src/3rdparty/2geom/doc/media/coords.svg b/src/3rdparty/2geom/doc/media/coords.svg
new file mode 100644
index 0000000..c780df0
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/coords.svg
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="151.71198"
+ height="124.79403"
+ id="svg59"
+ version="1.1"
+ inkscape:version="0.48+devel r10332"
+ sodipodi:docname="coords.svg"
+ inkscape:export-filename="/home/tweenk/src/2geom-bzr/doc/media/coords.png"
+ inkscape:export-xdpi="90.170868"
+ inkscape:export-ydpi="90.170868">
+ <defs
+ id="defs61">
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mend"
+ style="overflow:visible">
+ <path
+ inkscape:connector-curvature="0"
+ id="path802"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="marker51"
+ style="overflow:visible">
+ <path
+ inkscape:connector-curvature="0"
+ id="path53"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.8"
+ inkscape:cx="43.083365"
+ inkscape:cy="80.424336"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:window-width="1105"
+ inkscape:window-height="815"
+ inkscape:window-x="1"
+ inkscape:window-y="31"
+ inkscape:window-maximized="0"
+ inkscape:object-nodes="true"
+ inkscape:object-paths="true"
+ inkscape:snap-intersection-paths="true" />
+ <metadata
+ id="metadata64">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-166.59375,-740.58868)">
+ <path
+ transform="matrix(1,0,0,-1,80.151798,912.09043)"
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;marker-end:url(#marker51);visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 165.71428,146.6479 c 0,-16.18137 -7.27115,-30.66448 -18.72437,-40.36025"
+ id="path12"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;marker-end:url(#Arrow1Mend);visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 193.00893,743.22826 0,119.2857"
+ id="path14"
+ sodipodi:nodetypes="cc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;marker-end:url(#Arrow1Mend);visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 166.58037,765.44253 144.99998,0"
+ id="path16"
+ sodipodi:nodetypes="cc" />
+ <text
+ xml:space="preserve"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+ x="311.07623"
+ y="756.33673"
+ id="text3166"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3168"
+ x="311.07623"
+ y="756.33673">X</tspan></text>
+ <text
+ sodipodi:linespacing="125%"
+ id="text3170"
+ y="862.76532"
+ x="208.93338"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+ xml:space="preserve"><tspan
+ y="862.76532"
+ x="208.93338"
+ id="tspan3172"
+ sodipodi:role="line">Y</tspan></text>
+ <path
+ style="color:#000000;fill:#ff933d;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="M 26.41518,24.85385 69.642857,81.936886"
+ id="path4158"
+ inkscape:connector-curvature="0"
+ transform="translate(166.59375,740.58868)" />
+ </g>
+</svg>
diff --git a/src/3rdparty/2geom/doc/media/ellipse-angular-coordinates.png b/src/3rdparty/2geom/doc/media/ellipse-angular-coordinates.png
new file mode 100644
index 0000000..c79eb47
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/ellipse-angular-coordinates.png
Binary files differ
diff --git a/src/3rdparty/2geom/doc/media/ellipse-angular-coordinates.svg b/src/3rdparty/2geom/doc/media/ellipse-angular-coordinates.svg
new file mode 100644
index 0000000..e9311ec
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/ellipse-angular-coordinates.svg
@@ -0,0 +1,249 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="720"
+ height="320"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46+devel r21383"
+ version="1.0"
+ sodipodi:docname="ellipse-angular-coordinates.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/usr/src/2geom-svn/doc/media/ellipse-angular-coordinates.png"
+ inkscape:export-xdpi="66.050827"
+ inkscape:export-ydpi="66.050827">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Sstart"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Sstart"
+ style="overflow:visible">
+ <path
+ id="path805"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(0.2,0,0,0.2,1.2,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mend"
+ style="overflow:visible">
+ <path
+ id="path802"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Send"
+ style="overflow:visible">
+ <path
+ id="path808"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lend"
+ style="overflow:visible">
+ <path
+ id="path796"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.7"
+ inkscape:cx="408.19305"
+ inkscape:cy="259.59627"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:snap-bbox="false"
+ inkscape:snap-bbox-midpoints="false"
+ inkscape:snap-nodes="true"
+ inkscape:object-paths="true"
+ inkscape:snap-intersection-paths="true"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:snap-global="false"
+ inkscape:window-width="1024"
+ inkscape:window-height="737"
+ inkscape:window-x="0"
+ inkscape:window-y="1" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-732.36214)">
+ <path
+ sodipodi:type="arc"
+ style="color:#000000;fill:none;stroke:#558ada;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path12"
+ sodipodi:cx="112.85714"
+ sodipodi:cy="146.6479"
+ sodipodi:rx="52.857143"
+ sodipodi:ry="52.857143"
+ d="m 165.71428,146.6479 a 52.857143,52.857143 0 1 1 -105.714284,0 52.857143,52.857143 0 1 1 105.714284,0 z"
+ transform="translate(22.612039,728.7384)" />
+ <path
+ style="color:#000000;fill:none;stroke:#ed0000;stroke-width:3;stroke-linecap:square;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 135.46917,875.3863 44.82926,-28.01715"
+ id="path1992" />
+ <path
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;marker-end:url(#Arrow1Mend);visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 135.46917,988.31486 0,-209.99999"
+ id="path14" />
+ <path
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;marker-end:url(#Arrow1Mend);visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 35.469178,875.3863 218.571412,0"
+ id="path16" />
+ <path
+ transform="matrix(1.3986138,1.6285045,-0.49765802,0.42740527,477.84037,634.78699)"
+ d="m 165.71428,146.6479 a 52.857143,52.857143 0 1 1 -105.714284,0 52.857143,52.857143 0 1 1 105.714284,0 z"
+ sodipodi:ry="52.857143"
+ sodipodi:rx="52.857143"
+ sodipodi:cy="146.6479"
+ sodipodi:cx="112.85714"
+ id="path2192"
+ style="color:#000000;fill:none;stroke:#558ada;stroke-width:2.52805805;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ id="path2194"
+ d="m 562.70341,881.25342 76.64178,61.02997"
+ style="color:#000000;fill:none;stroke:#ed0000;stroke-width:3;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:3;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 386.66677,790.99733 0,27.3541 -99.76009,0 0,119.77841 99.76009,0 0,27.3541 51.36989,-87.22345 -51.36989,-87.26316 z"
+ id="rect2196" />
+ <text
+ xml:space="preserve"
+ style="font-size:21.50658035px;text-align:start;text-anchor:start"
+ x="296.32678"
+ y="856.89478"
+ id="text2201"><tspan
+ sodipodi:role="line"
+ id="tspan2203"
+ x="296.32678"
+ y="856.89478">rotation,</tspan><tspan
+ sodipodi:role="line"
+ x="296.32678"
+ y="883.77802"
+ id="tspan2205">scaling,</tspan><tspan
+ sodipodi:role="line"
+ x="296.32678"
+ y="910.66125"
+ id="tspan2231">translation</tspan></text>
+ <text
+ id="text2211"
+ y="1011.1191"
+ x="134.7551"
+ style="font-size:21.50658035px;text-align:center;text-anchor:middle"
+ xml:space="preserve"><tspan
+ id="tspan2215"
+ y="1011.1191"
+ x="134.7551"
+ sodipodi:role="line">mapping angle to point</tspan><tspan
+ y="1038.0023"
+ x="134.7551"
+ sodipodi:role="line"
+ id="tspan2219">on the unit circle</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:21.50658035px;text-align:center;text-anchor:middle"
+ x="571.89789"
+ y="1011.1191"
+ id="text2221"><tspan
+ id="tspan2225"
+ sodipodi:role="line"
+ x="571.89789"
+ y="1011.1191">resulting point</tspan><tspan
+ sodipodi:role="line"
+ x="571.89789"
+ y="1038.0023"
+ id="tspan2229">on the ellipse</tspan></text>
+ <path
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1.50000000000000000;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;marker-end:url(#Arrow1Mend)"
+ d="m 445.21287,881.25343 254.28572,0"
+ id="path2233" />
+ <path
+ sodipodi:type="arc"
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path2235"
+ sodipodi:cx="580.09137"
+ sodipodi:cy="143.9436"
+ sodipodi:rx="19.989418"
+ sodipodi:ry="19.989418"
+ d="M 590.48259,161.01988 A 19.989418,19.989418 0 1 1 600.0786,143.6477"
+ sodipodi:start="1.0241371"
+ sodipodi:end="6.268382"
+ sodipodi:open="true"
+ transform="translate(-17.387962,737.30983)" />
+ <path
+ style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 575.81386,896.51884 -10.70183,1.36745 4.09106,2.2748 -0.34104,4.33235 6.95183,-7.9746 -2e-5,0 z"
+ id="path3214"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ id="path3406"
+ d="m 562.70342,982.92526 0,-211.09183"
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1.50000000000000000;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;marker-end:url(#Arrow1Mend)" />
+ <path
+ style="color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#558ada;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 536.39864,171.48272 589.0082,126.29988"
+ id="path3980"
+ transform="translate(0,732.36214)" />
+ <path
+ style="color:#000000;fill:none;stroke:#558ada;stroke-width:1.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="M 488.77669,62.813201 636.63015,234.96939"
+ id="path3982"
+ transform="translate(0,732.36214)" />
+ </g>
+</svg>
diff --git a/src/3rdparty/2geom/doc/media/elliptical-arc-flags.png b/src/3rdparty/2geom/doc/media/elliptical-arc-flags.png
new file mode 100644
index 0000000..7776fc3
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/elliptical-arc-flags.png
Binary files differ
diff --git a/src/3rdparty/2geom/doc/media/elliptical-arc-flags.svg b/src/3rdparty/2geom/doc/media/elliptical-arc-flags.svg
new file mode 100644
index 0000000..d4116f2
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/elliptical-arc-flags.svg
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="268.49316"
+ height="154.5769"
+ id="svg4007"
+ sodipodi:version="0.32"
+ inkscape:version="0.46+devel r21383"
+ version="1.0"
+ sodipodi:docname="elliptical-arc-flags.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/usr/src/2geom-svn/doc/media/elliptical-arc-flags.png"
+ inkscape:export-xdpi="93.85714"
+ inkscape:export-ydpi="93.85714">
+ <defs
+ id="defs4009">
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mend"
+ style="overflow:visible">
+ <path
+ id="path802"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lend"
+ style="overflow:visible">
+ <path
+ id="path796"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective4015" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.4044"
+ inkscape:cx="111.98708"
+ inkscape:cy="73.679958"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:object-paths="true"
+ inkscape:snap-intersection-paths="true"
+ inkscape:snap-global="false"
+ inkscape:window-width="1024"
+ inkscape:window-height="737"
+ inkscape:window-x="0"
+ inkscape:window-y="1" />
+ <metadata
+ id="metadata4012">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-69.799637,-28.300815)">
+ <path
+ sodipodi:type="arc"
+ style="color:#000000;fill:none;stroke:#558ada;stroke-width:2.05404162;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path4017"
+ sodipodi:cx="166.17009"
+ sodipodi:cy="131.10306"
+ sodipodi:rx="124.75384"
+ sodipodi:ry="74.751289"
+ d="m 290.92393,131.10306 c 0,41.284 -55.8542,74.75129 -124.75384,74.75129 -68.899642,0 -124.753838,-33.46729 -124.753838,-74.75129 0,-41.283999 55.854196,-74.751292 124.753838,-74.751292 68.89964,0 124.75384,33.467293 124.75384,74.751292 z"
+ transform="matrix(0.61918419,0.38818562,-0.38761403,0.61827246,101.94315,-30.37653)" />
+ <path
+ transform="matrix(0.61918419,0.38818562,-0.38761403,0.61827246,170.12845,-49.569428)"
+ d="m 290.92393,131.10306 c 0,41.284 -55.8542,74.75129 -124.75384,74.75129 -68.899642,0 -124.753838,-33.46729 -124.753838,-74.75129 0,-41.283999 55.854196,-74.751292 124.753838,-74.751292 68.89964,0 124.75384,33.467293 124.75384,74.751292 z"
+ sodipodi:ry="74.751289"
+ sodipodi:rx="124.75384"
+ sodipodi:cy="131.10306"
+ sodipodi:cx="166.17009"
+ id="path4021"
+ style="color:#000000;fill:none;stroke:#558ada;stroke-width:2.05404162;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="color:#000000;fill:#ed0000;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path4025"
+ sodipodi:cx="233.37674"
+ sodipodi:cy="159.67299"
+ sodipodi:rx="9.5633268"
+ sodipodi:ry="9.5633268"
+ d="m 242.94007,159.67299 c 0,5.28168 -4.28165,9.56333 -9.56333,9.56333 -5.28168,0 -9.56333,-4.28165 -9.56333,-9.56333 0,-5.28168 4.28165,-9.56333 9.56333,-9.56333 5.28168,0 9.56333,4.28165 9.56333,9.56333 z"
+ transform="matrix(0.55248859,0,0,0.55248859,104.43875,71.455484)" />
+ <path
+ transform="matrix(0.55248859,0,0,0.55248859,14.139401,-36.772691)"
+ d="m 242.94007,159.67299 c 0,5.28168 -4.28165,9.56333 -9.56333,9.56333 -5.28168,0 -9.56333,-4.28165 -9.56333,-9.56333 0,-5.28168 4.28165,-9.56333 9.56333,-9.56333 5.28168,0 9.56333,4.28165 9.56333,9.56333 z"
+ sodipodi:ry="9.5633268"
+ sodipodi:rx="9.5633268"
+ sodipodi:cy="159.67299"
+ sodipodi:cx="233.37674"
+ id="path4537"
+ style="color:#000000;fill:#ed0000;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ style="color:#000000;fill:#ed0000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:6, 6;stroke-dashoffset:0;marker:none;marker-end:url(#Arrow1Mend);visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="M 147.5237,60.982766 226.57224,148.5907"
+ id="path4539" />
+ <text
+ xml:space="preserve"
+ style="text-align:center;text-anchor:middle"
+ x="319.7186"
+ y="88.171432"
+ id="text4915"><tspan
+ sodipodi:role="line"
+ id="tspan4917"
+ x="319.7186"
+ y="88.171432">sweep</tspan><tspan
+ sodipodi:role="line"
+ x="319.7186"
+ y="103.17143"
+ id="tspan4919">large</tspan></text>
+ <text
+ id="text4921"
+ y="88.171432"
+ x="242.18054"
+ style="text-align:center;text-anchor:middle"
+ xml:space="preserve"><tspan
+ y="88.171432"
+ x="242.18054"
+ id="tspan4923"
+ sodipodi:role="line">sweep</tspan><tspan
+ id="tspan4925"
+ y="103.17143"
+ x="242.18054"
+ sodipodi:role="line">!large</tspan></text>
+ <text
+ xml:space="preserve"
+ style="text-align:center;text-anchor:middle"
+ x="123.37082"
+ y="103.70818"
+ id="text4927"><tspan
+ sodipodi:role="line"
+ id="tspan4929"
+ x="123.37082"
+ y="103.70818">!sweep</tspan><tspan
+ sodipodi:role="line"
+ x="123.37082"
+ y="118.70818"
+ id="tspan4931">!large</tspan></text>
+ <text
+ id="text4933"
+ y="163.69551"
+ x="89.621902"
+ style="text-align:center;text-anchor:middle"
+ xml:space="preserve"><tspan
+ y="163.69551"
+ x="89.621902"
+ id="tspan4935"
+ sodipodi:role="line">!sweep</tspan><tspan
+ id="tspan4937"
+ y="178.69551"
+ x="89.621902"
+ sodipodi:role="line">large</tspan></text>
+ </g>
+</svg>
diff --git a/src/3rdparty/2geom/doc/media/gear.png b/src/3rdparty/2geom/doc/media/gear.png
new file mode 100644
index 0000000..3415df2
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/gear.png
Binary files differ
diff --git a/src/3rdparty/2geom/doc/media/involute.pdf b/src/3rdparty/2geom/doc/media/involute.pdf
new file mode 100644
index 0000000..f199a2f
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/involute.pdf
Binary files differ
diff --git a/src/3rdparty/2geom/doc/media/matrix.png b/src/3rdparty/2geom/doc/media/matrix.png
new file mode 100644
index 0000000..343a8e7
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/matrix.png
Binary files differ
diff --git a/src/3rdparty/2geom/doc/media/matrix.svg b/src/3rdparty/2geom/doc/media/matrix.svg
new file mode 100644
index 0000000..f331bb4
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/matrix.svg
@@ -0,0 +1,247 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="777"
+ height="555"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.44+devel"
+ sodipodi:docbase="/home/michael/2geom/trunk/doc/media"
+ sodipodi:docname="matrix.svg"
+ version="1.0"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/michael/2geom/trunk/doc/media/scale.png"
+ inkscape:export-xdpi="200"
+ inkscape:export-ydpi="200"
+ sodipodi:modified="true">
+ <metadata
+ id="metadata48">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ inkscape:window-height="855"
+ inkscape:window-width="1113"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ inkscape:zoom="4"
+ inkscape:cx="97.22678"
+ inkscape:cy="409.27536"
+ inkscape:window-x="157"
+ inkscape:window-y="140"
+ inkscape:current-layer="svg2"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <sodipodi:guide
+ orientation="vertical"
+ position="111.36932"
+ id="guide4172" />
+ <sodipodi:guide
+ orientation="horizontal"
+ position="411.53615"
+ id="guide4174" />
+ </sodipodi:namedview>
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mend"
+ style="overflow:visible;">
+ <path
+ id="path3249"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.4) rotate(180) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mend"
+ style="overflow:visible;">
+ <path
+ id="path3212"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(0,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mstart"
+ style="overflow:visible">
+ <path
+ id="path3233"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.4) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Sstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Sstart"
+ style="overflow:visible">
+ <path
+ id="path3227"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.2) translate(6,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Send"
+ style="overflow:visible;">
+ <path
+ id="path3224"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.2) rotate(180) translate(6,0)" />
+ </marker>
+ <linearGradient
+ id="linearGradient4094">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1;"
+ offset="0"
+ id="stop4096" />
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:0;"
+ offset="1"
+ id="stop4098" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4062">
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1;"
+ offset="0"
+ id="stop4064" />
+ <stop
+ style="stop-color:#babdb6;stop-opacity:0;"
+ offset="1"
+ id="stop4066" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4040">
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1;"
+ offset="0"
+ id="stop4042" />
+ <stop
+ style="stop-color:#babdb6;stop-opacity:0;"
+ offset="1"
+ id="stop4044" />
+ </linearGradient>
+ <radialGradient
+ xlink:href="#linearGradient4062"
+ id="radialGradient4079"
+ gradientUnits="userSpaceOnUse"
+ cx="8"
+ cy="-16"
+ fx="8"
+ fy="-16"
+ r="108" />
+ <linearGradient
+ xlink:href="#linearGradient4040"
+ id="linearGradient4081"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(80,376)"
+ x1="328.5"
+ y1="-43.664978"
+ x2="328.5"
+ y2="116.68156" />
+ <linearGradient
+ xlink:href="#linearGradient4094"
+ id="linearGradient4116"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.35905,0,0,1.35905,203.6646,-185.2813)"
+ x1="95.105873"
+ y1="363.72418"
+ x2="95.105873"
+ y2="502.67734" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4040"
+ id="linearGradient3175"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-2.121444)"
+ x1="426.27966"
+ y1="483.83633"
+ x2="426.27966"
+ y2="522.72052" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4094"
+ id="linearGradient3177"
+ gradientUnits="userSpaceOnUse"
+ x1="407.09628"
+ y1="374.48508"
+ x2="407.09628"
+ y2="485.16641" />
+ </defs>
+ <g
+ id="g2919"
+ transform="matrix(0.319896,0,0,0.319896,48.45544,81.50285)">
+ <path
+ id="path2921"
+ d="M 163.15,27.83 L 28.81,165.3 C -16.58,221.51 59.7,214.97 92.4,231.16 C 104.13,243.15 47.44,252 59.17,264 C 70.9,275.99 130.1,287.1 141.85,299.09 C 153.58,311.08 117.84,323.8 129.57,335.79 C 141.3,347.78 168.43,336.42 173.51,364.1 C 177.13,383.88 222.4,372.6 244.54,356.4 C 256.27,344.4 222.1,345.53 233.83,333.54 C 263,303.71 290.16,322.7 300.14,292.81 C 305.07,278.04 257.2,270.04 268.95,258.05 C 302.7,238.34 419.35,225.51 364,170.16 L 224.75,27.83 C 207.72,11.48 179.3,11.3 163.15,27.83 z M 130.99,238.57 C 134,238.57 231.54,251.61 193.9,261.92 C 179.72,265.8 113.53,238.57 130.99,238.57 z M 317.46,292.81 C 317.46,299.63 367.71,304.1 367.71,291.2 C 360.55,270.48 323.4,271.88 317.46,292.81 z M 91.1,329.05 C 103,339.34 121.38,326.49 126.89,312.13 C 115.36,296.81 72.2,312.68 91.1,329.05 z M 311.16,306.82 C 295.82,320.58 312.88,334.54 328,325.65 C 331.37,322.23 327.91,310.24 311.16,306.82 z "
+ style="fill:none;stroke:black;stroke-opacity:1" />
+ <path
+ id="path2925"
+ d="M 216.63,37.47 L 269.78,91.45 C 274.82,96.6 275.91315,108.88098 271.93,109.45 C 266.29292,110.2553 260.02293,94.034313 251.80374,94.034313 C 242.7616,94.034313 245.43878,123.58602 238.07227,123.58602 C 230.29748,123.58602 227.72697,107.96 218.30004,107.96 C 210.67739,107.96 205.51399,129.13114 194.80001,129.13114 C 185.2927,129.13114 177.02987,83.24 171.29999,83.24 C 166.28062,83.24 163.47697,123.96 152.33,123.96 C 133.73263,123.96 105.14,123.84 105.14,123.84 C 95.7,123.82 97.27,114.63 106.4,104.78 C 125.16,84.53 161.15,49.43 172.85,37.47 C 184.61,25.45 205.1,25.79 216.63,37.47 z "
+ style="fill:none;stroke:black;stroke-opacity:1"
+ sodipodi:nodetypes="cccsssssscccc" />
+ </g>
+ <g
+ id="g2227"
+ transform="matrix(1.448783,-7.650991e-2,-0.400046,1.15503,20.06051,-21.47177)">
+ <path
+ id="path2219"
+ d="M 111.36932,86.249996 L 111.36932,143.46385 L 169.5,143.46385"
+ style="fill:none;fill-rule:evenodd;stroke:black;stroke-width:0.78020775px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);marker-mid:none;marker-end:url(#Arrow1Mend);stroke-opacity:1" />
+ <g
+ id="g2221"
+ transform="matrix(0.319896,0,0,0.319896,48.45544,81.50285)">
+ <path
+ id="path2223"
+ d="M 163.15,27.83 L 28.81,165.3 C -16.58,221.51 59.7,214.97 92.4,231.16 C 104.13,243.15 47.44,252 59.17,264 C 70.9,275.99 130.1,287.1 141.85,299.09 C 153.58,311.08 117.84,323.8 129.57,335.79 C 141.3,347.78 168.43,336.42 173.51,364.1 C 177.13,383.88 222.4,372.6 244.54,356.4 C 256.27,344.4 222.1,345.53 233.83,333.54 C 263,303.71 290.16,322.7 300.14,292.81 C 305.07,278.04 257.2,270.04 268.95,258.05 C 302.7,238.34 419.35,225.51 364,170.16 L 224.75,27.83 C 207.72,11.48 179.3,11.3 163.15,27.83 z M 130.99,238.57 C 134,238.57 231.54,251.61 193.9,261.92 C 179.72,265.8 113.53,238.57 130.99,238.57 z M 317.46,292.81 C 317.46,299.63 367.71,304.1 367.71,291.2 C 360.55,270.48 323.4,271.88 317.46,292.81 z M 91.1,329.05 C 103,339.34 121.38,326.49 126.89,312.13 C 115.36,296.81 72.2,312.68 91.1,329.05 z M 311.16,306.82 C 295.82,320.58 312.88,334.54 328,325.65 C 331.37,322.23 327.91,310.24 311.16,306.82 z "
+ style="fill:none;stroke:black;stroke-width:0.78020769;stroke-miterlimit:4;stroke-dasharray:4.68124631, 4.68124631;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ id="path2225"
+ d="M 216.63,37.47 L 269.78,91.45 C 274.82,96.6 275.91315,108.88098 271.93,109.45 C 266.29292,110.2553 260.02293,94.034313 251.80374,94.034313 C 242.7616,94.034313 245.43878,123.58602 238.07227,123.58602 C 230.29748,123.58602 227.72697,107.96 218.30004,107.96 C 210.67739,107.96 205.51399,129.13114 194.80001,129.13114 C 185.2927,129.13114 177.02987,83.24 171.29999,83.24 C 166.28062,83.24 163.47697,123.96 152.33,123.96 C 133.73263,123.96 105.14,123.84 105.14,123.84 C 95.7,123.82 97.27,114.63 106.4,104.78 C 125.16,84.53 161.15,49.43 172.85,37.47 C 184.61,25.45 205.1,25.79 216.63,37.47 z "
+ style="fill:none;stroke:black;stroke-width:0.78020769;stroke-miterlimit:4;stroke-dasharray:4.68124631, 4.68124631;stroke-dashoffset:0;stroke-opacity:1"
+ sodipodi:nodetypes="cccsssssscccc" />
+ </g>
+ </g>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
+ d="M 111.36932,143.46385 L 123.75,136"
+ id="path2208" />
+</svg>
diff --git a/src/3rdparty/2geom/doc/media/point.png b/src/3rdparty/2geom/doc/media/point.png
new file mode 100644
index 0000000..d0e59b7
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/point.png
Binary files differ
diff --git a/src/3rdparty/2geom/doc/media/point.svg b/src/3rdparty/2geom/doc/media/point.svg
new file mode 100644
index 0000000..5c63137
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/point.svg
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="210mm"
+ height="297mm"
+ id="svg2160"
+ sodipodi:version="0.32"
+ inkscape:version="0.44+devel"
+ sodipodi:docbase="/home/michael/2geom/trunk/doc/media"
+ sodipodi:docname="point.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ sodipodi:modified="true">
+ <defs
+ id="defs3">
+ <marker
+ inkscape:stockid="Arrow1Sstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Sstart"
+ style="overflow:visible">
+ <path
+ id="path4102"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.2) translate(6,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Send"
+ style="overflow:visible;">
+ <path
+ id="path4099"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.2) rotate(180) translate(6,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mend"
+ style="overflow:visible;">
+ <path
+ id="path4105"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.4) rotate(180) translate(10,0)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ inkscape:document-units="mm"
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.8"
+ inkscape:cx="178.41166"
+ inkscape:cy="63.895144"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="1280"
+ inkscape:window-height="949"
+ inkscape:window-x="1280"
+ inkscape:window-y="25"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <sodipodi:guide
+ orientation="vertical"
+ position="107.14286"
+ id="guide3050" />
+ <sodipodi:guide
+ orientation="horizontal"
+ position="56.428571"
+ id="guide3052" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata4">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ sodipodi:type="arc"
+ style="fill:black;fill-opacity:1;stroke:none;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:0.5, 1;stroke-dashoffset:0;stroke-opacity:1"
+ id="path2178"
+ sodipodi:cx="60.104076"
+ sodipodi:cy="962.45862"
+ sodipodi:rx="1.5152289"
+ sodipodi:ry="1.5152289"
+ d="M 61.619305 962.45862 A 1.5152289 1.5152289 0 1 1 58.588848,962.45862 A 1.5152289 1.5152289 0 1 1 61.619305 962.45862 z"
+ transform="matrix(1.199594,0,0,1.199594,34.99081,-158.1218)" />
+ <text
+ xml:space="preserve"
+ style="font-size:10px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Serif"
+ x="110.59128"
+ y="1000.1426"
+ id="text2180"><tspan
+ sodipodi:role="line"
+ id="tspan2182"
+ x="110.59128"
+ y="1000.1426">(60,30)</tspan></text>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:black;stroke-width:1.77165353;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;marker-start:url(#Arrow1Sstart);marker-end:url(#Arrow1Send)"
+ d="M 0,976.6479 L 0,1052.7193 L 167.06354,1052.7193"
+ id="path2160"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:black;stroke-width:1.77165413;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Send);stroke-miterlimit:4;stroke-dasharray:5.31496239,1.77165413;stroke-opacity:1;marker-start:none;stroke-dashoffset:0"
+ d="M -0.35714298,1052.3626 L 103.5899,998.42619"
+ id="path3054" />
+ <text
+ xml:space="preserve"
+ style="font-size:10px;font-style:italic;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Serif"
+ x="3.5714283"
+ y="982.36218"
+ id="text4123"><tspan
+ sodipodi:role="line"
+ id="tspan4125"
+ x="3.5714283"
+ y="982.36218"
+ style="font-style:italic">x</tspan></text>
+ <text
+ id="text4127"
+ y="1048.4336"
+ x="159.64285"
+ style="font-size:10px;font-style:italic;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Serif"
+ xml:space="preserve"><tspan
+ style="font-style:italic"
+ y="1048.4336"
+ x="159.64285"
+ id="tspan4129"
+ sodipodi:role="line">y</tspan></text>
+ </g>
+</svg>
diff --git a/src/3rdparty/2geom/doc/media/rect.png b/src/3rdparty/2geom/doc/media/rect.png
new file mode 100644
index 0000000..adb82f6
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/rect.png
Binary files differ
diff --git a/src/3rdparty/2geom/doc/media/rotate.png b/src/3rdparty/2geom/doc/media/rotate.png
new file mode 100644
index 0000000..8abea74
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/rotate.png
Binary files differ
diff --git a/src/3rdparty/2geom/doc/media/rotate.svg b/src/3rdparty/2geom/doc/media/rotate.svg
new file mode 100644
index 0000000..31a0f7c
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/rotate.svg
@@ -0,0 +1,239 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="777"
+ height="555"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.44+devel"
+ sodipodi:docbase="/home/michael/2geom/trunk/doc/media"
+ sodipodi:docname="rocate.svg"
+ version="1.0"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/michael/2geom/trunk/doc/media/scale.png"
+ inkscape:export-xdpi="200"
+ inkscape:export-ydpi="200">
+ <metadata
+ id="metadata48">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ inkscape:window-height="855"
+ inkscape:window-width="1113"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ inkscape:zoom="2.8284271"
+ inkscape:cx="77.313404"
+ inkscape:cy="436.13958"
+ inkscape:window-x="157"
+ inkscape:window-y="140"
+ inkscape:current-layer="g2190"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <sodipodi:guide
+ orientation="vertical"
+ position="111.36932"
+ id="guide4172" />
+ <sodipodi:guide
+ orientation="horizontal"
+ position="411.53615"
+ id="guide4174" />
+ </sodipodi:namedview>
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mend"
+ style="overflow:visible;">
+ <path
+ id="path3249"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.4) rotate(180) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mend"
+ style="overflow:visible;">
+ <path
+ id="path3212"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(0,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mstart"
+ style="overflow:visible">
+ <path
+ id="path3233"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.4) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Sstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Sstart"
+ style="overflow:visible">
+ <path
+ id="path3227"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.2) translate(6,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Send"
+ style="overflow:visible;">
+ <path
+ id="path3224"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.2) rotate(180) translate(6,0)" />
+ </marker>
+ <linearGradient
+ id="linearGradient4094">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1;"
+ offset="0"
+ id="stop4096" />
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:0;"
+ offset="1"
+ id="stop4098" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4062">
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1;"
+ offset="0"
+ id="stop4064" />
+ <stop
+ style="stop-color:#babdb6;stop-opacity:0;"
+ offset="1"
+ id="stop4066" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4040">
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1;"
+ offset="0"
+ id="stop4042" />
+ <stop
+ style="stop-color:#babdb6;stop-opacity:0;"
+ offset="1"
+ id="stop4044" />
+ </linearGradient>
+ <radialGradient
+ xlink:href="#linearGradient4062"
+ id="radialGradient4079"
+ gradientUnits="userSpaceOnUse"
+ cx="8"
+ cy="-16"
+ fx="8"
+ fy="-16"
+ r="108" />
+ <linearGradient
+ xlink:href="#linearGradient4040"
+ id="linearGradient4081"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(80,376)"
+ x1="328.5"
+ y1="-43.664978"
+ x2="328.5"
+ y2="116.68156" />
+ <linearGradient
+ xlink:href="#linearGradient4094"
+ id="linearGradient4116"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.35905,0,0,1.35905,203.6646,-185.2813)"
+ x1="95.105873"
+ y1="363.72418"
+ x2="95.105873"
+ y2="502.67734" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4040"
+ id="linearGradient3175"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-2.121444)"
+ x1="426.27966"
+ y1="483.83633"
+ x2="426.27966"
+ y2="522.72052" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4094"
+ id="linearGradient3177"
+ gradientUnits="userSpaceOnUse"
+ x1="407.09628"
+ y1="374.48508"
+ x2="407.09628"
+ y2="485.16641" />
+ </defs>
+ <g
+ id="g2919"
+ transform="matrix(0.319896,0,0,0.319896,48.45544,81.50285)">
+ <path
+ id="path2921"
+ d="M 163.15,27.83 L 28.81,165.3 C -16.58,221.51 59.7,214.97 92.4,231.16 C 104.13,243.15 47.44,252 59.17,264 C 70.9,275.99 130.1,287.1 141.85,299.09 C 153.58,311.08 117.84,323.8 129.57,335.79 C 141.3,347.78 168.43,336.42 173.51,364.1 C 177.13,383.88 222.4,372.6 244.54,356.4 C 256.27,344.4 222.1,345.53 233.83,333.54 C 263,303.71 290.16,322.7 300.14,292.81 C 305.07,278.04 257.2,270.04 268.95,258.05 C 302.7,238.34 419.35,225.51 364,170.16 L 224.75,27.83 C 207.72,11.48 179.3,11.3 163.15,27.83 z M 130.99,238.57 C 134,238.57 231.54,251.61 193.9,261.92 C 179.72,265.8 113.53,238.57 130.99,238.57 z M 317.46,292.81 C 317.46,299.63 367.71,304.1 367.71,291.2 C 360.55,270.48 323.4,271.88 317.46,292.81 z M 91.1,329.05 C 103,339.34 121.38,326.49 126.89,312.13 C 115.36,296.81 72.2,312.68 91.1,329.05 z M 311.16,306.82 C 295.82,320.58 312.88,334.54 328,325.65 C 331.37,322.23 327.91,310.24 311.16,306.82 z "
+ style="fill:none;stroke:black;stroke-opacity:1" />
+ <path
+ id="path2925"
+ d="M 216.63,37.47 L 269.78,91.45 C 274.82,96.6 275.91315,108.88098 271.93,109.45 C 266.29292,110.2553 260.02293,94.034313 251.80374,94.034313 C 242.7616,94.034313 245.43878,123.58602 238.07227,123.58602 C 230.29748,123.58602 227.72697,107.96 218.30004,107.96 C 210.67739,107.96 205.51399,129.13114 194.80001,129.13114 C 185.2927,129.13114 177.02987,83.24 171.29999,83.24 C 166.28062,83.24 163.47697,123.96 152.33,123.96 C 133.73263,123.96 105.14,123.84 105.14,123.84 C 95.7,123.82 97.27,114.63 106.4,104.78 C 125.16,84.53 161.15,49.43 172.85,37.47 C 184.61,25.45 205.1,25.79 216.63,37.47 z "
+ style="fill:none;stroke:black;stroke-opacity:1"
+ sodipodi:nodetypes="cccsssssscccc" />
+ </g>
+ <g
+ transform="matrix(0.228764,0.223608,-0.223608,0.228764,109.769,54.85103)"
+ id="g2190">
+ <path
+ style="fill:none;stroke:black;stroke-width:0.99999995;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:5.99999975,5.99999975;stroke-dashoffset:0"
+ d="M 163.15,27.83 L 28.81,165.3 C -16.58,221.51 59.7,214.97 92.4,231.16 C 104.13,243.15 47.44,252 59.17,264 C 70.9,275.99 130.1,287.1 141.85,299.09 C 153.58,311.08 117.84,323.8 129.57,335.79 C 141.3,347.78 168.43,336.42 173.51,364.1 C 177.13,383.88 222.4,372.6 244.54,356.4 C 256.27,344.4 222.1,345.53 233.83,333.54 C 263,303.71 290.16,322.7 300.14,292.81 C 305.07,278.04 257.2,270.04 268.95,258.05 C 302.7,238.34 419.35,225.51 364,170.16 L 224.75,27.83 C 207.72,11.48 179.3,11.3 163.15,27.83 z M 130.99,238.57 C 134,238.57 231.54,251.61 193.9,261.92 C 179.72,265.8 113.53,238.57 130.99,238.57 z M 317.46,292.81 C 317.46,299.63 367.71,304.1 367.71,291.2 C 360.55,270.48 323.4,271.88 317.46,292.81 z M 91.1,329.05 C 103,339.34 121.38,326.49 126.89,312.13 C 115.36,296.81 72.2,312.68 91.1,329.05 z M 311.16,306.82 C 295.82,320.58 312.88,334.54 328,325.65 C 331.37,322.23 327.91,310.24 311.16,306.82 z "
+ id="path2192" />
+ <path
+ sodipodi:nodetypes="cccsssssscccc"
+ style="fill:none;stroke:black;stroke-width:0.99999995;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:5.99999975,5.99999975;stroke-dashoffset:0"
+ d="M 216.63,37.47 L 269.78,91.45 C 274.82,96.6 275.91315,108.88098 271.93,109.45 C 266.29292,110.2553 260.02293,94.034313 251.80374,94.034313 C 242.7616,94.034313 245.43878,123.58602 238.07227,123.58602 C 230.29748,123.58602 227.72697,107.96 218.30004,107.96 C 210.67739,107.96 205.51399,129.13114 194.80001,129.13114 C 185.2927,129.13114 177.02987,83.24 171.29999,83.24 C 166.28062,83.24 163.47697,123.96 152.33,123.96 C 133.73263,123.96 105.14,123.84 105.14,123.84 C 95.7,123.82 97.27,114.63 106.4,104.78 C 125.16,84.53 161.15,49.43 172.85,37.47 C 184.61,25.45 205.1,25.79 216.63,37.47 z "
+ id="path2194" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);marker-end:url(#Arrow1Mend);stroke-opacity:1"
+ d="M 111.36932,86.541753 L 111.36932,143.46385 L 169.35208,143.46385"
+ id="path2196"
+ transform="matrix(3.126016,0,0,3.126016,-151.4725,-254.7792)" />
+ </g>
+</svg>
diff --git a/src/3rdparty/2geom/doc/media/sbasis.png b/src/3rdparty/2geom/doc/media/sbasis.png
new file mode 100644
index 0000000..4e0aad1
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/sbasis.png
Binary files differ
diff --git a/src/3rdparty/2geom/doc/media/sbasis.svg b/src/3rdparty/2geom/doc/media/sbasis.svg
new file mode 100644
index 0000000..c5b4cbe
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/sbasis.svg
@@ -0,0 +1,1121 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="352.37646"
+ height="289.65378"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.48+devel r10201 custom"
+ sodipodi:docname="sbasis.svg"
+ inkscape:export-filename="/home/tweenk/src/2geom-bzr/doc/media/sbasis.png"
+ inkscape:export-xdpi="150.07809"
+ inkscape:export-ydpi="150.07809">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mend"
+ style="overflow:visible">
+ <path
+ id="path796"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mstart"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mstart"
+ style="overflow:visible">
+ <path
+ id="path793"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+ transform="matrix(0.4,0,0,0.4,4,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath1898">
+ <rect
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1.61399996;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect1900"
+ width="22.223356"
+ height="23.991123"
+ x="269.76013"
+ y="174.68845"
+ transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath1910">
+ <rect
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1.61399996;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect1912"
+ width="33.214287"
+ height="22.857143"
+ x="-182.01929"
+ y="290.14496"
+ transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,0,0)" />
+ </clipPath>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.4"
+ inkscape:cx="210.52422"
+ inkscape:cy="131.46418"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:object-nodes="true"
+ inkscape:snap-global="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:window-width="999"
+ inkscape:window-height="828"
+ inkscape:window-x="3"
+ inkscape:window-y="89"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(28.575407,-95.703979)">
+ <path
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1.61399996;stroke-miterlimit:4;stroke-dasharray:none;marker:none;marker-start:url(#Arrow1Mstart);marker-end:url(#Arrow1Mend);visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="m 60,98.790754 0,254.999996 260.71429,0"
+ id="path10"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc" />
+ <text
+ xml:space="preserve"
+ style="font-size:31.43364906px;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:LMMathItalic12;-inkscape-font-specification:LMMathItalic12 Bold Italic"
+ x="7.2479248"
+ y="123.86304"
+ id="text1415-0"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan1417-1"
+ x="7.2479234"
+ y="123.86304"><tspan
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:LMRoman12;-inkscape-font-specification:LMRoman12"
+ id="tspan1440">(1–</tspan>t<tspan
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:LMRoman12;-inkscape-font-specification:LMRoman12"
+ id="tspan2082">)</tspan><tspan
+ id="tspan2088"
+ style="font-size:65.00091553%;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;baseline-shift:super;font-family:LMMathItalic12;-inkscape-font-specification:LMMathItalic12 Bold Italic">n</tspan></tspan></text>
+ <text
+ sodipodi:linespacing="125%"
+ id="text1446"
+ y="385.04343"
+ x="299.8241"
+ style="font-size:31.43364906px;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:LMMathItalic12;-inkscape-font-specification:LMMathItalic12 Bold Italic"
+ xml:space="preserve"><tspan
+ y="385.04343"
+ x="299.8241"
+ id="tspan1448"
+ sodipodi:role="line">t<tspan
+ style="font-size:65.00091553%;baseline-shift:super"
+ id="tspan2084">n</tspan></tspan></text>
+ <rect
+ style="color:#000000;fill:none;stroke:#000000;stroke-width:1.61399996;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect1454"
+ width="28.571428"
+ height="28.571428"
+ x="60"
+ y="325.21933"
+ inkscape:tile-cx="40.040511"
+ inkscape:tile-cy="284.51535"
+ inkscape:tile-w="28.571428"
+ inkscape:tile-h="28.571428"
+ inkscape:tile-x0="25.754797"
+ inkscape:tile-y0="270.22964" />
+ <path
+ sodipodi:type="arc"
+ style="color:#000000;fill:#00ff00;stroke:#000000;stroke-width:2.30571437;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path1840"
+ sodipodi:cx="74.285713"
+ sodipodi:cy="139.50505"
+ sodipodi:rx="14.285713"
+ sodipodi:ry="14.285715"
+ d="m 88.571426,139.50505 c 0,7.88978 -6.395931,14.28572 -14.285713,14.28572 C 66.395932,153.79077 60,147.39483 60,139.50505 c 0,-7.88978 6.395932,-14.28571 14.285713,-14.28571 7.889782,0 14.285713,6.39593 14.285713,14.28571 z"
+ transform="matrix(0.69999998,0,0,0.69999998,22.285716,41.851518)" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path1840"
+ id="use1846"
+ transform="translate(28.571428,28.571423)"
+ width="744.09448"
+ height="1052.3622" />
+ <use
+ height="1052.3622"
+ width="744.09448"
+ transform="translate(57.142857,57.142853)"
+ id="use1848"
+ xlink:href="#path1840"
+ y="0"
+ x="0" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path1840"
+ id="use1850"
+ transform="translate(85.714285,85.714283)"
+ width="744.09448"
+ height="1052.3622" />
+ <use
+ height="1052.3622"
+ width="744.09448"
+ transform="translate(114.28571,114.28571)"
+ id="use1852"
+ xlink:href="#path1840"
+ y="0"
+ x="0" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path1840"
+ id="use1854"
+ transform="translate(142.85714,142.85714)"
+ width="744.09448"
+ height="1052.3622" />
+ <use
+ height="1052.3622"
+ width="744.09448"
+ transform="translate(171.42857,171.42857)"
+ id="use1856"
+ xlink:href="#path1840"
+ y="0"
+ x="0" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path1840"
+ id="use1858"
+ transform="translate(200,199.99999)"
+ width="744.09448"
+ height="1052.3622" />
+ <path
+ transform="matrix(0.69999998,0,0,0.69999998,22.285716,241.85151)"
+ d="m 88.571426,139.50505 c 0,7.88978 -6.395931,14.28572 -14.285713,14.28572 C 66.395932,153.79077 60,147.39483 60,139.50505 c 0,-7.88978 6.395932,-14.28571 14.285713,-14.28571 7.889782,0 14.285713,6.39593 14.285713,14.28571 z"
+ sodipodi:ry="14.285715"
+ sodipodi:rx="14.285713"
+ sodipodi:cy="139.50505"
+ sodipodi:cx="74.285713"
+ id="path1862"
+ style="color:#000000;fill:#ff0000;stroke:#000000;stroke-width:2.30571437;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path1862"
+ id="use1864"
+ transform="translate(57.142857,-1.213469e-8)"
+ width="744.09448"
+ height="1052.3622" />
+ <use
+ height="1052.3622"
+ width="744.09448"
+ transform="translate(85.714285,-1.213469e-8)"
+ id="use1866"
+ xlink:href="#path1862"
+ y="0"
+ x="0" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path1862"
+ id="use1868"
+ transform="translate(114.28571,-1.213469e-8)"
+ width="744.09448"
+ height="1052.3622" />
+ <use
+ height="1052.3622"
+ width="744.09448"
+ transform="translate(142.85714,-1.213469e-8)"
+ id="use1870"
+ xlink:href="#path1862"
+ y="0"
+ x="0" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path1862"
+ id="use1872"
+ transform="translate(171.42857,-1.213469e-8)"
+ width="744.09448"
+ height="1052.3622" />
+ <path
+ sodipodi:type="arc"
+ style="color:#000000;fill:#0000ff;stroke:#000000;stroke-width:2.30571437;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path1874"
+ sodipodi:cx="74.285713"
+ sodipodi:cy="139.50505"
+ sodipodi:rx="14.285713"
+ sodipodi:ry="14.285715"
+ d="m 88.571426,139.50505 c 0,7.88978 -6.395931,14.28572 -14.285713,14.28572 C 66.395932,153.79077 60,147.39483 60,139.50505 c 0,-7.88978 6.395932,-14.28571 14.285713,-14.28571 7.889782,0 14.285713,6.39593 14.285713,14.28571 z"
+ transform="matrix(0.69999998,0,0,0.69999998,50.857144,241.85151)" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path1874"
+ id="use1876"
+ transform="translate(-28.571428,-28.571427)"
+ width="744.09448"
+ height="1052.3622" />
+ <use
+ height="1052.3622"
+ width="744.09448"
+ transform="translate(3.9812881e-7,-57.142856)"
+ id="use1878"
+ xlink:href="#path1874"
+ y="0"
+ x="0" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path1874"
+ id="use1880"
+ transform="translate(28.571429,-85.714284)"
+ width="744.09448"
+ height="1052.3622" />
+ <use
+ height="1052.3622"
+ width="744.09448"
+ transform="translate(28.571429,-28.571427)"
+ id="use1882"
+ xlink:href="#path1874"
+ y="0"
+ x="0" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path1874"
+ id="use1884"
+ transform="translate(57.142857,-57.142856)"
+ width="744.09448"
+ height="1052.3622" />
+ <use
+ height="1052.3622"
+ width="744.09448"
+ transform="translate(28.574438,0.01913589)"
+ id="use1890"
+ xlink:href="#path1862"
+ y="0"
+ x="0"
+ clip-path="url(#clipPath1898)" />
+ <use
+ clip-path="url(#clipPath1898)"
+ x="0"
+ y="0"
+ xlink:href="#path1862"
+ id="use1902"
+ transform="translate(199.91558,-0.10527461)"
+ width="744.09448"
+ height="1052.3622" />
+ <use
+ height="1052.3622"
+ width="744.09448"
+ transform="translate(57.142857,-114.28571)"
+ id="use1906"
+ xlink:href="#path1874"
+ y="0"
+ x="0"
+ clip-path="url(#clipPath1910)" />
+ <use
+ clip-path="url(#clipPath1910)"
+ x="0"
+ y="0"
+ xlink:href="#path1874"
+ id="use1914"
+ transform="translate(85.714282,-85.714285)"
+ width="744.09448"
+ height="1052.3622" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ id="use2126"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(0,-28.571428)"
+ id="use2128"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(0,-57.142857)"
+ id="use2130"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(0,-85.714285)"
+ id="use2132"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(0,-114.28571)"
+ id="use2134"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(0,-142.85714)"
+ id="use2136"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(0,-171.42857)"
+ id="use2138"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(0,-200)"
+ id="use2140"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(28.571428,0)"
+ id="use2142"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(28.571428,-28.571428)"
+ id="use2144"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(28.571428,-57.142857)"
+ id="use2146"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(28.571428,-85.714285)"
+ id="use2148"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(28.571428,-114.28571)"
+ id="use2150"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(28.571428,-142.85714)"
+ id="use2152"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(28.571428,-171.42857)"
+ id="use2154"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(28.571428,-200)"
+ id="use2156"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(57.142857,0)"
+ id="use2158"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(57.142857,-28.571428)"
+ id="use2160"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(57.142857,-57.142857)"
+ id="use2162"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(57.142857,-85.714285)"
+ id="use2164"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(57.142857,-114.28571)"
+ id="use2166"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(57.142857,-142.85714)"
+ id="use2168"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(57.142857,-171.42857)"
+ id="use2170"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(57.142857,-200)"
+ id="use2172"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(85.714285,0)"
+ id="use2174"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(85.714285,-28.571428)"
+ id="use2176"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(85.714285,-57.142857)"
+ id="use2178"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(85.714285,-85.714285)"
+ id="use2180"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(85.714285,-114.28571)"
+ id="use2182"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(85.714285,-142.85714)"
+ id="use2184"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(85.714285,-171.42857)"
+ id="use2186"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(85.714285,-200)"
+ id="use2188"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(114.28571,0)"
+ id="use2190"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(114.28571,-28.571428)"
+ id="use2192"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(114.28571,-57.142857)"
+ id="use2194"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(114.28571,-85.714285)"
+ id="use2196"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(114.28571,-114.28571)"
+ id="use2198"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(114.28571,-142.85714)"
+ id="use2200"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(114.28571,-171.42857)"
+ id="use2202"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(114.28571,-200)"
+ id="use2204"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(142.85714,0)"
+ id="use2206"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(142.85714,-28.571428)"
+ id="use2208"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(142.85714,-57.142857)"
+ id="use2210"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(142.85714,-85.714285)"
+ id="use2212"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(142.85714,-114.28571)"
+ id="use2214"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(142.85714,-142.85714)"
+ id="use2216"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(142.85714,-171.42857)"
+ id="use2218"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(142.85714,-200)"
+ id="use2220"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(171.42857,0)"
+ id="use2222"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(171.42857,-28.571428)"
+ id="use2224"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(171.42857,-57.142857)"
+ id="use2226"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(171.42857,-85.714285)"
+ id="use2228"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(171.42857,-114.28571)"
+ id="use2230"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(171.42857,-142.85714)"
+ id="use2232"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(171.42857,-171.42857)"
+ id="use2234"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(171.42857,-200)"
+ id="use2236"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(200,0)"
+ id="use2238"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(200,-28.571428)"
+ id="use2240"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(200,-57.142857)"
+ id="use2242"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(200,-85.714285)"
+ id="use2244"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(200,-114.28571)"
+ id="use2246"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(200,-142.85714)"
+ id="use2248"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(200,-171.42857)"
+ id="use2250"
+ width="344.55585"
+ height="333.58237" />
+ <use
+ x="0"
+ y="0"
+ inkscape:tiled-clone-of="#rect1454"
+ xlink:href="#rect1454"
+ transform="translate(200,-200)"
+ id="use2252"
+ width="344.55585"
+ height="333.58237" />
+ <text
+ xml:space="preserve"
+ style="font-size:18.89756584px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:LMRoman12;-inkscape-font-specification:LMRoman12"
+ x="47.198875"
+ y="345.9967"
+ id="text113"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan115"
+ x="47.198875"
+ y="345.9967">0</tspan></text>
+ <text
+ sodipodi:linespacing="125%"
+ id="text117"
+ y="317.42383"
+ x="47.198875"
+ style="font-size:18.89756584px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:LMRoman12;-inkscape-font-specification:LMRoman12"
+ xml:space="preserve"><tspan
+ y="317.42383"
+ x="47.198875"
+ id="tspan119"
+ sodipodi:role="line">1</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:18.89756584px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:LMRoman12;-inkscape-font-specification:LMRoman12"
+ x="47.198875"
+ y="288.85092"
+ id="text121"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan123"
+ x="47.198875"
+ y="288.85092">2</tspan></text>
+ <text
+ sodipodi:linespacing="125%"
+ id="text125"
+ y="260.27805"
+ x="47.198875"
+ style="font-size:18.89756584px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:LMRoman12;-inkscape-font-specification:LMRoman12"
+ xml:space="preserve"><tspan
+ y="260.27805"
+ x="47.198875"
+ id="tspan127"
+ sodipodi:role="line">3</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:18.89756584px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:LMRoman12;-inkscape-font-specification:LMRoman12"
+ x="47.198875"
+ y="231.70517"
+ id="text129"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan131"
+ x="47.198875"
+ y="231.70517">4</tspan></text>
+ <text
+ sodipodi:linespacing="125%"
+ id="text133"
+ y="203.13228"
+ x="47.198875"
+ style="font-size:18.89756584px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:LMRoman12;-inkscape-font-specification:LMRoman12"
+ xml:space="preserve"><tspan
+ y="203.13228"
+ x="47.198875"
+ id="tspan135"
+ sodipodi:role="line">5</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:18.89756584px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:LMRoman12;-inkscape-font-specification:LMRoman12"
+ x="47.198875"
+ y="174.5594"
+ id="text137"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan139"
+ x="47.198875"
+ y="174.5594">6</tspan></text>
+ <text
+ sodipodi:linespacing="125%"
+ id="text141"
+ y="145.98651"
+ x="47.198875"
+ style="font-size:18.89756584px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:LMRoman12;-inkscape-font-specification:LMRoman12"
+ xml:space="preserve"><tspan
+ y="145.98651"
+ x="47.198875"
+ id="tspan143"
+ sodipodi:role="line">7</tspan></text>
+ <text
+ sodipodi:linespacing="125%"
+ id="text145"
+ y="372.78241"
+ x="74.341736"
+ style="font-size:18.89756584px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:LMRoman12;-inkscape-font-specification:LMRoman12"
+ xml:space="preserve"><tspan
+ y="372.78241"
+ x="74.341736"
+ id="tspan147"
+ sodipodi:role="line">0</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:18.89756584px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:LMRoman12;-inkscape-font-specification:LMRoman12"
+ x="102.86214"
+ y="372.78241"
+ id="text149"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan151"
+ x="102.86214"
+ y="372.78241">1</tspan></text>
+ <text
+ sodipodi:linespacing="125%"
+ id="text153"
+ y="372.78241"
+ x="131.38255"
+ style="font-size:18.89756584px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:LMRoman12;-inkscape-font-specification:LMRoman12"
+ xml:space="preserve"><tspan
+ y="372.78241"
+ x="131.38255"
+ id="tspan155"
+ sodipodi:role="line">2</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:18.89756584px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:LMRoman12;-inkscape-font-specification:LMRoman12"
+ x="159.90297"
+ y="372.78241"
+ id="text157"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan159"
+ x="159.90297"
+ y="372.78241">3</tspan></text>
+ <text
+ sodipodi:linespacing="125%"
+ id="text161"
+ y="372.78241"
+ x="188.42337"
+ style="font-size:18.89756584px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:LMRoman12;-inkscape-font-specification:LMRoman12"
+ xml:space="preserve"><tspan
+ y="372.78241"
+ x="188.42337"
+ id="tspan163"
+ sodipodi:role="line">4</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:18.89756584px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:LMRoman12;-inkscape-font-specification:LMRoman12"
+ x="216.94377"
+ y="372.78241"
+ id="text165"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan167"
+ x="216.94377"
+ y="372.78241">5</tspan></text>
+ <text
+ sodipodi:linespacing="125%"
+ id="text169"
+ y="372.78241"
+ x="245.46419"
+ style="font-size:18.89756584px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:LMRoman12;-inkscape-font-specification:LMRoman12"
+ xml:space="preserve"><tspan
+ y="372.78241"
+ x="245.46419"
+ id="tspan171"
+ sodipodi:role="line">6</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:18.89756584px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:LMRoman12;-inkscape-font-specification:LMRoman12"
+ x="273.98459"
+ y="372.78241"
+ id="text173"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan175"
+ x="273.98459"
+ y="372.78241">7</tspan></text>
+ </g>
+</svg>
diff --git a/src/3rdparty/2geom/doc/media/scale.png b/src/3rdparty/2geom/doc/media/scale.png
new file mode 100644
index 0000000..3d62b7e
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/scale.png
Binary files differ
diff --git a/src/3rdparty/2geom/doc/media/scale.svg b/src/3rdparty/2geom/doc/media/scale.svg
new file mode 100644
index 0000000..3d37be4
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/scale.svg
@@ -0,0 +1,243 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="777"
+ height="555"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.44+devel"
+ sodipodi:docbase="/home/michael/2geom/trunk/doc/media"
+ sodipodi:docname="scale.svg"
+ version="1.0"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/michael/2geom/trunk/doc/media/scale.png"
+ inkscape:export-xdpi="200"
+ inkscape:export-ydpi="200"
+ sodipodi:modified="true">
+ <metadata
+ id="metadata48">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ inkscape:window-height="855"
+ inkscape:window-width="1113"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ inkscape:zoom="4"
+ inkscape:cx="97.22678"
+ inkscape:cy="404.19505"
+ inkscape:window-x="157"
+ inkscape:window-y="140"
+ inkscape:current-layer="g2227"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <sodipodi:guide
+ orientation="vertical"
+ position="111.36932"
+ id="guide4172" />
+ <sodipodi:guide
+ orientation="horizontal"
+ position="411.53615"
+ id="guide4174" />
+ </sodipodi:namedview>
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mend"
+ style="overflow:visible;">
+ <path
+ id="path3249"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.4) rotate(180) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mend"
+ style="overflow:visible;">
+ <path
+ id="path3212"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(0,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mstart"
+ style="overflow:visible">
+ <path
+ id="path3233"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.4) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Sstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Sstart"
+ style="overflow:visible">
+ <path
+ id="path3227"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.2) translate(6,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Send"
+ style="overflow:visible;">
+ <path
+ id="path3224"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.2) rotate(180) translate(6,0)" />
+ </marker>
+ <linearGradient
+ id="linearGradient4094">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1;"
+ offset="0"
+ id="stop4096" />
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:0;"
+ offset="1"
+ id="stop4098" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4062">
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1;"
+ offset="0"
+ id="stop4064" />
+ <stop
+ style="stop-color:#babdb6;stop-opacity:0;"
+ offset="1"
+ id="stop4066" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4040">
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1;"
+ offset="0"
+ id="stop4042" />
+ <stop
+ style="stop-color:#babdb6;stop-opacity:0;"
+ offset="1"
+ id="stop4044" />
+ </linearGradient>
+ <radialGradient
+ xlink:href="#linearGradient4062"
+ id="radialGradient4079"
+ gradientUnits="userSpaceOnUse"
+ cx="8"
+ cy="-16"
+ fx="8"
+ fy="-16"
+ r="108" />
+ <linearGradient
+ xlink:href="#linearGradient4040"
+ id="linearGradient4081"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(80,376)"
+ x1="328.5"
+ y1="-43.664978"
+ x2="328.5"
+ y2="116.68156" />
+ <linearGradient
+ xlink:href="#linearGradient4094"
+ id="linearGradient4116"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.35905,0,0,1.35905,203.6646,-185.2813)"
+ x1="95.105873"
+ y1="363.72418"
+ x2="95.105873"
+ y2="502.67734" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4040"
+ id="linearGradient3175"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-2.121444)"
+ x1="426.27966"
+ y1="483.83633"
+ x2="426.27966"
+ y2="522.72052" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4094"
+ id="linearGradient3177"
+ gradientUnits="userSpaceOnUse"
+ x1="407.09628"
+ y1="374.48508"
+ x2="407.09628"
+ y2="485.16641" />
+ </defs>
+ <g
+ id="g2919"
+ transform="matrix(0.319896,0,0,0.319896,48.45544,81.50285)">
+ <path
+ id="path2921"
+ d="M 163.15,27.83 L 28.81,165.3 C -16.58,221.51 59.7,214.97 92.4,231.16 C 104.13,243.15 47.44,252 59.17,264 C 70.9,275.99 130.1,287.1 141.85,299.09 C 153.58,311.08 117.84,323.8 129.57,335.79 C 141.3,347.78 168.43,336.42 173.51,364.1 C 177.13,383.88 222.4,372.6 244.54,356.4 C 256.27,344.4 222.1,345.53 233.83,333.54 C 263,303.71 290.16,322.7 300.14,292.81 C 305.07,278.04 257.2,270.04 268.95,258.05 C 302.7,238.34 419.35,225.51 364,170.16 L 224.75,27.83 C 207.72,11.48 179.3,11.3 163.15,27.83 z M 130.99,238.57 C 134,238.57 231.54,251.61 193.9,261.92 C 179.72,265.8 113.53,238.57 130.99,238.57 z M 317.46,292.81 C 317.46,299.63 367.71,304.1 367.71,291.2 C 360.55,270.48 323.4,271.88 317.46,292.81 z M 91.1,329.05 C 103,339.34 121.38,326.49 126.89,312.13 C 115.36,296.81 72.2,312.68 91.1,329.05 z M 311.16,306.82 C 295.82,320.58 312.88,334.54 328,325.65 C 331.37,322.23 327.91,310.24 311.16,306.82 z "
+ style="fill:none;stroke:black;stroke-opacity:1" />
+ <path
+ id="path2925"
+ d="M 216.63,37.47 L 269.78,91.45 C 274.82,96.6 275.91315,108.88098 271.93,109.45 C 266.29292,110.2553 260.02293,94.034313 251.80374,94.034313 C 242.7616,94.034313 245.43878,123.58602 238.07227,123.58602 C 230.29748,123.58602 227.72697,107.96 218.30004,107.96 C 210.67739,107.96 205.51399,129.13114 194.80001,129.13114 C 185.2927,129.13114 177.02987,83.24 171.29999,83.24 C 166.28062,83.24 163.47697,123.96 152.33,123.96 C 133.73263,123.96 105.14,123.84 105.14,123.84 C 95.7,123.82 97.27,114.63 106.4,104.78 C 125.16,84.53 161.15,49.43 172.85,37.47 C 184.61,25.45 205.1,25.79 216.63,37.47 z "
+ style="fill:none;stroke:black;stroke-opacity:1"
+ sodipodi:nodetypes="cccsssssscccc" />
+ </g>
+ <g
+ id="g2227"
+ transform="matrix(1.448783,0,0,1.133904,-50.0431,-19.23223)">
+ <path
+ id="path2219"
+ d="M 111.36932,86.249996 L 111.36932,143.46385 L 169.5,143.46385"
+ style="fill:none;fill-rule:evenodd;stroke:black;stroke-width:0.78020775px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Mstart);marker-mid:none;marker-end:url(#Arrow1Mend)" />
+ <g
+ id="g2221"
+ transform="matrix(0.319896,0,0,0.319896,48.45544,81.50285)">
+ <path
+ id="path2223"
+ d="M 163.15,27.83 L 28.81,165.3 C -16.58,221.51 59.7,214.97 92.4,231.16 C 104.13,243.15 47.44,252 59.17,264 C 70.9,275.99 130.1,287.1 141.85,299.09 C 153.58,311.08 117.84,323.8 129.57,335.79 C 141.3,347.78 168.43,336.42 173.51,364.1 C 177.13,383.88 222.4,372.6 244.54,356.4 C 256.27,344.4 222.1,345.53 233.83,333.54 C 263,303.71 290.16,322.7 300.14,292.81 C 305.07,278.04 257.2,270.04 268.95,258.05 C 302.7,238.34 419.35,225.51 364,170.16 L 224.75,27.83 C 207.72,11.48 179.3,11.3 163.15,27.83 z M 130.99,238.57 C 134,238.57 231.54,251.61 193.9,261.92 C 179.72,265.8 113.53,238.57 130.99,238.57 z M 317.46,292.81 C 317.46,299.63 367.71,304.1 367.71,291.2 C 360.55,270.48 323.4,271.88 317.46,292.81 z M 91.1,329.05 C 103,339.34 121.38,326.49 126.89,312.13 C 115.36,296.81 72.2,312.68 91.1,329.05 z M 311.16,306.82 C 295.82,320.58 312.88,334.54 328,325.65 C 331.37,322.23 327.91,310.24 311.16,306.82 z "
+ style="fill:none;stroke:black;stroke-width:0.78020771;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:4.68124631,4.68124631;stroke-dashoffset:0" />
+ <path
+ id="path2225"
+ d="M 216.63,37.47 L 269.78,91.45 C 274.82,96.6 275.91315,108.88098 271.93,109.45 C 266.29292,110.2553 260.02293,94.034313 251.80374,94.034313 C 242.7616,94.034313 245.43878,123.58602 238.07227,123.58602 C 230.29748,123.58602 227.72697,107.96 218.30004,107.96 C 210.67739,107.96 205.51399,129.13114 194.80001,129.13114 C 185.2927,129.13114 177.02987,83.24 171.29999,83.24 C 166.28062,83.24 163.47697,123.96 152.33,123.96 C 133.73263,123.96 105.14,123.84 105.14,123.84 C 95.7,123.82 97.27,114.63 106.4,104.78 C 125.16,84.53 161.15,49.43 172.85,37.47 C 184.61,25.45 205.1,25.79 216.63,37.47 z "
+ style="fill:none;stroke:black;stroke-width:0.78020771;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:4.68124631,4.68124631;stroke-dashoffset:0"
+ sodipodi:nodetypes="cccsssssscccc" />
+ </g>
+ </g>
+</svg>
diff --git a/src/3rdparty/2geom/doc/media/translate.png b/src/3rdparty/2geom/doc/media/translate.png
new file mode 100644
index 0000000..56de688
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/translate.png
Binary files differ
diff --git a/src/3rdparty/2geom/doc/media/translate.svg b/src/3rdparty/2geom/doc/media/translate.svg
new file mode 100644
index 0000000..33bb817
--- /dev/null
+++ b/src/3rdparty/2geom/doc/media/translate.svg
@@ -0,0 +1,252 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="777"
+ height="555"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.44+devel"
+ sodipodi:docbase="/home/michael/2geom/trunk/doc/media"
+ sodipodi:docname="scale.svg"
+ version="1.0"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/michael/2geom/trunk/doc/media/scale.png"
+ inkscape:export-xdpi="200"
+ inkscape:export-ydpi="200"
+ sodipodi:modified="true">
+ <metadata
+ id="metadata48">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ inkscape:window-height="855"
+ inkscape:window-width="1113"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ inkscape:zoom="2.8284271"
+ inkscape:cx="132.09309"
+ inkscape:cy="435.9628"
+ inkscape:window-x="157"
+ inkscape:window-y="140"
+ inkscape:current-layer="svg2"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <sodipodi:guide
+ orientation="vertical"
+ position="111.36932"
+ id="guide4172" />
+ <sodipodi:guide
+ orientation="horizontal"
+ position="411.53615"
+ id="guide4174" />
+ <sodipodi:guide
+ orientation="vertical"
+ position="170.05918"
+ id="guide3076" />
+ <sodipodi:guide
+ orientation="horizontal"
+ position="460.68007"
+ id="guide3078" />
+ </sodipodi:namedview>
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mend"
+ style="overflow:visible;">
+ <path
+ id="path3249"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.4) rotate(180) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Mend"
+ style="overflow:visible;">
+ <path
+ id="path3212"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(0.6) rotate(180) translate(0,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mstart"
+ style="overflow:visible">
+ <path
+ id="path3233"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.4) translate(10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Sstart"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Sstart"
+ style="overflow:visible">
+ <path
+ id="path3227"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ transform="scale(0.2) translate(6,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Send"
+ style="overflow:visible;">
+ <path
+ id="path3224"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.2) rotate(180) translate(6,0)" />
+ </marker>
+ <linearGradient
+ id="linearGradient4094">
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:1;"
+ offset="0"
+ id="stop4096" />
+ <stop
+ style="stop-color:#eeeeec;stop-opacity:0;"
+ offset="1"
+ id="stop4098" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4062">
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1;"
+ offset="0"
+ id="stop4064" />
+ <stop
+ style="stop-color:#babdb6;stop-opacity:0;"
+ offset="1"
+ id="stop4066" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4040">
+ <stop
+ style="stop-color:#babdb6;stop-opacity:1;"
+ offset="0"
+ id="stop4042" />
+ <stop
+ style="stop-color:#babdb6;stop-opacity:0;"
+ offset="1"
+ id="stop4044" />
+ </linearGradient>
+ <radialGradient
+ xlink:href="#linearGradient4062"
+ id="radialGradient4079"
+ gradientUnits="userSpaceOnUse"
+ cx="8"
+ cy="-16"
+ fx="8"
+ fy="-16"
+ r="108" />
+ <linearGradient
+ xlink:href="#linearGradient4040"
+ id="linearGradient4081"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(80,376)"
+ x1="328.5"
+ y1="-43.664978"
+ x2="328.5"
+ y2="116.68156" />
+ <linearGradient
+ xlink:href="#linearGradient4094"
+ id="linearGradient4116"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.35905,0,0,1.35905,203.6646,-185.2813)"
+ x1="95.105873"
+ y1="363.72418"
+ x2="95.105873"
+ y2="502.67734" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4040"
+ id="linearGradient3175"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-2.121444)"
+ x1="426.27966"
+ y1="483.83633"
+ x2="426.27966"
+ y2="522.72052" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4094"
+ id="linearGradient3177"
+ gradientUnits="userSpaceOnUse"
+ x1="407.09628"
+ y1="374.48508"
+ x2="407.09628"
+ y2="485.16641" />
+ </defs>
+ <g
+ id="g2919"
+ transform="matrix(0.319896,0,0,0.319896,48.45544,81.50285)">
+ <path
+ id="path2921"
+ d="M 163.15,27.83 L 28.81,165.3 C -16.58,221.51 59.7,214.97 92.4,231.16 C 104.13,243.15 47.44,252 59.17,264 C 70.9,275.99 130.1,287.1 141.85,299.09 C 153.58,311.08 117.84,323.8 129.57,335.79 C 141.3,347.78 168.43,336.42 173.51,364.1 C 177.13,383.88 222.4,372.6 244.54,356.4 C 256.27,344.4 222.1,345.53 233.83,333.54 C 263,303.71 290.16,322.7 300.14,292.81 C 305.07,278.04 257.2,270.04 268.95,258.05 C 302.7,238.34 419.35,225.51 364,170.16 L 224.75,27.83 C 207.72,11.48 179.3,11.3 163.15,27.83 z M 130.99,238.57 C 134,238.57 231.54,251.61 193.9,261.92 C 179.72,265.8 113.53,238.57 130.99,238.57 z M 317.46,292.81 C 317.46,299.63 367.71,304.1 367.71,291.2 C 360.55,270.48 323.4,271.88 317.46,292.81 z M 91.1,329.05 C 103,339.34 121.38,326.49 126.89,312.13 C 115.36,296.81 72.2,312.68 91.1,329.05 z M 311.16,306.82 C 295.82,320.58 312.88,334.54 328,325.65 C 331.37,322.23 327.91,310.24 311.16,306.82 z "
+ style="fill:none;stroke:black;stroke-opacity:1" />
+ <path
+ id="path2925"
+ d="M 216.63,37.47 L 269.78,91.45 C 274.82,96.6 275.91315,108.88098 271.93,109.45 C 266.29292,110.2553 260.02293,94.034313 251.80374,94.034313 C 242.7616,94.034313 245.43878,123.58602 238.07227,123.58602 C 230.29748,123.58602 227.72697,107.96 218.30004,107.96 C 210.67739,107.96 205.51399,129.13114 194.80001,129.13114 C 185.2927,129.13114 177.02987,83.24 171.29999,83.24 C 166.28062,83.24 163.47697,123.96 152.33,123.96 C 133.73263,123.96 105.14,123.84 105.14,123.84 C 95.7,123.82 97.27,114.63 106.4,104.78 C 125.16,84.53 161.15,49.43 172.85,37.47 C 184.61,25.45 205.1,25.79 216.63,37.47 z "
+ style="fill:none;stroke:black;stroke-opacity:1"
+ sodipodi:nodetypes="cccsssssscccc" />
+ </g>
+ <g
+ transform="matrix(0.228764,0.223608,-0.223608,0.228764,109.769,54.85103)"
+ id="g2190">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:black;stroke-width:3.12601709px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);marker-end:none;stroke-opacity:1"
+ d="M 220.61954,-37.561022 L 196.6698,193.69109"
+ id="path2196"
+ sodipodi:nodetypes="cc" />
+ </g>
+ <g
+ transform="matrix(0.319896,0,0,0.319896,106.8078,32.71248)"
+ id="g3080">
+ <path
+ style="fill:none;stroke:black;stroke-opacity:1;stroke-width:1.00000003;stroke-miterlimit:4;stroke-dasharray:6.00000025,6.00000025;stroke-dashoffset:0"
+ d="M 163.15,27.83 L 28.81,165.3 C -16.58,221.51 59.7,214.97 92.4,231.16 C 104.13,243.15 47.44,252 59.17,264 C 70.9,275.99 130.1,287.1 141.85,299.09 C 153.58,311.08 117.84,323.8 129.57,335.79 C 141.3,347.78 168.43,336.42 173.51,364.1 C 177.13,383.88 222.4,372.6 244.54,356.4 C 256.27,344.4 222.1,345.53 233.83,333.54 C 263,303.71 290.16,322.7 300.14,292.81 C 305.07,278.04 257.2,270.04 268.95,258.05 C 302.7,238.34 419.35,225.51 364,170.16 L 224.75,27.83 C 207.72,11.48 179.3,11.3 163.15,27.83 z M 130.99,238.57 C 134,238.57 231.54,251.61 193.9,261.92 C 179.72,265.8 113.53,238.57 130.99,238.57 z M 317.46,292.81 C 317.46,299.63 367.71,304.1 367.71,291.2 C 360.55,270.48 323.4,271.88 317.46,292.81 z M 91.1,329.05 C 103,339.34 121.38,326.49 126.89,312.13 C 115.36,296.81 72.2,312.68 91.1,329.05 z M 311.16,306.82 C 295.82,320.58 312.88,334.54 328,325.65 C 331.37,322.23 327.91,310.24 311.16,306.82 z "
+ id="path3082" />
+ <path
+ sodipodi:nodetypes="cccsssssscccc"
+ style="fill:none;stroke:black;stroke-opacity:1;stroke-width:1.00000003;stroke-miterlimit:4;stroke-dasharray:6.00000025,6.00000025;stroke-dashoffset:0"
+ d="M 216.63,37.47 L 269.78,91.45 C 274.82,96.6 275.91315,108.88098 271.93,109.45 C 266.29292,110.2553 260.02293,94.034313 251.80374,94.034313 C 242.7616,94.034313 245.43878,123.58602 238.07227,123.58602 C 230.29748,123.58602 227.72697,107.96 218.30004,107.96 C 210.67739,107.96 205.51399,129.13114 194.80001,129.13114 C 185.2927,129.13114 177.02987,83.24 171.29999,83.24 C 166.28062,83.24 163.47697,123.96 152.33,123.96 C 133.73263,123.96 105.14,123.84 105.14,123.84 C 95.7,123.82 97.27,114.63 106.4,104.78 C 125.16,84.53 161.15,49.43 172.85,37.47 C 184.61,25.45 205.1,25.79 216.63,37.47 z "
+ id="path3084" />
+ </g>
+</svg>
diff --git a/src/3rdparty/2geom/doc/patchwise.svg b/src/3rdparty/2geom/doc/patchwise.svg
new file mode 100644
index 0000000..986c565
--- /dev/null
+++ b/src/3rdparty/2geom/doc/patchwise.svg
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.44+devel"
+ sodipodi:docbase="/home/njh/svn/lib2geom/doc"
+ sodipodi:docname="patchwise.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ sodipodi:modified="true">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="3.3"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.6699525"
+ inkscape:cx="337.14286"
+ inkscape:cy="685.71428"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:object-bbox="true"
+ inkscape:object-points="true"
+ inkscape:object-nodes="true"
+ inkscape:window-width="910"
+ inkscape:window-height="626"
+ inkscape:window-x="0"
+ inkscape:window-y="25" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect2160"
+ width="428.57144"
+ height="428.57144"
+ x="122.85714"
+ y="152.36218" />
+ <g
+ id="g3945">
+ <path
+ id="path3048"
+ d="M 302.91647,152.36218 C 302.91647,580.93359 302.91647,580.93359 302.91647,580.93359"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ id="path3050"
+ d="M 122.85714,323.04064 C 551.42859,323.04064 551.42859,323.04064 551.42859,323.04064"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#580000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 535.16419,323.04064 C 535.16419,580.93359 535.16419,580.93359 535.16419,580.93359"
+ id="path3052" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#580000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 301.86101,479.24844 C 551.42859,479.24844 551.42859,479.24844 551.42859,479.24844"
+ id="path3054" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#dd0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 405.29591,324.0961 L 405.29591,480.3039"
+ id="path3056" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#dd0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 302.91647,390.58996 C 534.06179,390.58996 534.06179,390.58996 534.06179,390.58996"
+ id="path3058" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 122.85714,152.36218 C 120.21593,152.34091 117.57473,152.31964 114.93352,152.29837 C 97.522248,152.15814 80.103265,152.29837 62.691012,152.29837 C 44.201158,152.29837 21.137039,149.25307 2.9852863,153.79101 C -14.749469,158.2247 -35.837039,151.70403 -53.735153,155.28365 C -68.399793,158.21658 -77.097646,171.70273 -94.036518,171.70273 C -113.54478,171.70273 -132.81343,165.14146 -152.2496,161.25423 C -161.04516,159.49511 -169.96413,151.60134 -179.11718,149.31308 C -190.17129,146.54955 -204.84334,149.31308 -216.43326,149.31308 C -217.42835,149.31308 -218.42345,149.31308 -219.41854,149.31308"
+ id="path3973" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 123.88938,580.93359 C 97.091356,580.93359 59.650495,568.7458 26.867577,568.7458 C 10.139914,568.7458 -7.2780498,576.08558 -20.897004,585.16488 C -33.02407,593.24959 -44.192616,596.13321 -58.213083,592.6281 C -75.749282,588.24405 -82.500961,571.73109 -102.99238,571.73109 C -117.70994,571.73109 -138.65753,576.8762 -152.2496,583.67224 C -165.73255,590.41371 -183.38692,593.14188 -197.02889,598.59867 C -209.41442,603.55288 -216.56256,598.1967 -225.38911,591.13545 C -230.5282,587.02419 -236.32857,583.42676 -241.80819,580.68695"
+ id="path3975" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-170.16132"
+ y="359.77576"
+ id="text3977"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3979"
+ x="-170.16132"
+ y="359.77576">Extend to infinity</tspan></text>
+ <rect
+ style="fill:#b5ffb0;fill-opacity:1;stroke:none;stroke-width:1;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3985"
+ width="170.16132"
+ height="158.22017"
+ x="126.87466"
+ y="158.26894" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="140.72752"
+ y="210.51144"
+ id="text3987"
+ sodipodi:linespacing="100%"><tspan
+ sodipodi:role="line"
+ id="tspan3989"
+ x="140.72752"
+ y="210.51144">Defined by four borders</tspan></text>
+ </g>
+</svg>
diff --git a/src/3rdparty/2geom/doc/s-pb-thoughts.txt b/src/3rdparty/2geom/doc/s-pb-thoughts.txt
new file mode 100644
index 0000000..5b11215
--- /dev/null
+++ b/src/3rdparty/2geom/doc/s-pb-thoughts.txt
@@ -0,0 +1,78 @@
+ these s-power bases are exactly what I was trying to invent
+ did you read that paper?
+(13:11:50) mental@gristle.org: I didn't really understand it.
+ oh, well it's precisely what we need for lib2geom
+ it has a nice haskell connection, btw
+ rather than representing things as finite polynomials, we can store them as lazy lists and simply take enough terms at the end of the calculations
+ did you at least look at the examples?
+ namely, conversion of nurbs to beziers and offset curves?
+ the basic idea is that although polynomials (which are really linear combinations of 1, x, x^2, x^3...) are easy to work with
+ they are crap for two main reasons: a) though they are always correct for 0, any rounding or truncation will make the values at 1 fluctuate
+ b) converting between bezier and polynomial is mathematically inprecise
+ b) is subtle and I didn't understand it for quite a while
+ but a) I had already run into
+ anyway, basically s-pbs provide a robust arithmetic for doing paths
+ and there are simple, online algorithms for most operations
+ oh yes, and truncating a s-pb gives an approximation that is basically as good as possible with that number of terms
+ so you might work out the offset curve as a degree 6 pb (corresponding to a degree 11 bezier curve) then truncate to a 2 term (cubic)
+(13:21:05) mental@gristle.org: so, basically an s-pb is an alternate way of approximating functions which has nicer properties than polynomials, at least for our purpose
+ or you might subdivide first
+ an s-pb is an alternate way of approximating functions which has nicer properties than polynomials and nicer properties than beziers, at least for our purpose; at the cost of a little more work
+ for example, multiplying a polynomial is straightforward (poly.cpp has an implementation, e.g.), multiplying a bezier is horid
+ but polynomials don't give a nice control handle interpretation
+ whereas beziers and s-pbs do
+ that article basically shows that anything you can do with polynomials, you can do with s-pbs
+ (with a little extra work)
+ so I'll probably remove poly.h
+ every curve can be written as an infinite s-pb
+ including things like spirals
+ so we could do spiral offset directly
+ basically, if you can write an operation mathematically, you can do it symbolically on an s-pb
+ including differentiation and integration
+ lets say we have a function S(t) which is a lazy list s-pb of a single path elem
+ then we can compute arc length as int(sqrt(diff(S)^2))
+ and we can evaluate that at an arbitrary point on the curve to a require precision simply by lazy list operations
+ similarly, offset means S + d*(transpose(S')/sqrt(diff(S)^2))
+ and we can convert that back to a curve using a routine that takes a lazy list and either degree reduces (truncates) or subdivides until the require tol is achieved
+(13:27:22) mental@gristle.org: man, lazy evaluation without garbage collection, though :/
+ yeah, been pondering that
+ probably easier to string together online algorithms and use a vector cache
+(13:28:09) mental@gristle.org: vector cache?
+ but I thought you might like to think about that as an algorithm
+ std::vector<term>
+(13:28:34) mental@gristle.org: ah, so basically we accumulate stuff in a vector during the computation and discard the vector when complete?
+ we can do a lot simply by providing fixed length versions
+ yeah
+(13:28:44) mental@gristle.org: (using it as a memory pool, essentially)
+ no, not really
+ I was just thinking that for a lazy list we start with something like lazy ->lazy
+ then [1] lazy -> lazy
+ (I think my notation is wrong here)
+ then [1, 5, 3, 87] lazy -> lazy
+ etc
+ many algorithms are linear time online
+ i.e. they do a constant amount of work, looking at a single term or a few terms
+ then output another term
+ you could think of them as a production line
+ every time the caller asks for another term, each element in the chain requests as many terms as it needs
+ any point where we need more than one term, we keep a vector remembering all the bits (as we will need them again)
+ addition, for example, simply takes the two inputs term by term and adds them
+ scalar multiply similar takes a term, multiplies and chugs the answer
+ sqrt ditto (I think)
+ but multiply requires all the terms whose indices add to the required term
+ There are a few algorithms I haven't worked out yet - inverse function (which we could find using the lagrange inversion theorem, perhaps), converting to a beziergon to a specified tolerance, handling singularities correctly (if you get a pole in the complex plane inside a certain distance from your path you need to subdivide to get past it)
+ but what I like is the facts that you can increase precision at the caller's point rather than having to make a guess as to the required precision first
+ and with s-pb we might be able to create a true natural parameterisation accurate to tol
+ http://en.wikipedia.org/wiki/Lagrange_inversion_theorem
+ that would be really cool if it worked with s-pb
+ you could take any s-pb and get an inverse function
+ (think implicit plotter)
+ for inversion we would require that the function in question is monotonic with non-zero derivative
+ I wonder if that condition could be tested easily symbolically
+ we should probably also think about paths of s-pb functions
+ to handle subdivision techniques
+ oh yeah, and I should work out how to find the intersection of two s-pbs
+ I have that nice paper that solves an arbitrary pair of polynomials via eigen decomposition, I may be able to rewrite that in terms of s-pb
+ you can find the intersections of an arbitrary set of polynomials via the resultant (I think I sent you a link)
+ perhaps the result is expressible in s-pb
+ (well of course it is, what I mean is that perhaps you can find it without going via polynomials first) \ No newline at end of file
diff --git a/src/3rdparty/2geom/doc/shapeops.svg b/src/3rdparty/2geom/doc/shapeops.svg
new file mode 100644
index 0000000..19353dc
--- /dev/null
+++ b/src/3rdparty/2geom/doc/shapeops.svg
@@ -0,0 +1,653 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.45+devel"
+ sodipodi:docname="shapeops.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow2Lend"
+ style="overflow:visible;">
+ <path
+ id="path4202"
+ style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+ transform="scale(1.1) rotate(180) translate(1,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="Arrow1Mend"
+ style="overflow:visible;">
+ <path
+ id="path4190"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ transform="scale(0.4) rotate(180) translate(10,0)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.32482718"
+ inkscape:cx="680.14564"
+ inkscape:cy="236.50338"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:window-width="787"
+ inkscape:window-height="1020"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000019, 4.00000019;stroke-dashoffset:0;stroke-opacity:1"
+ d="M -56.434431,402.42818 L 30.462129,402.42818 L 30.462129,556.4676 L -56.434431,556.4676 L -56.434431,402.42818 z"
+ id="rect2799" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:3.99999928;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ d="M -159.93198,363.56119 L 182.92514,363.56119 L 182.92514,542.13261 L -159.93198,542.13261 L -159.93198,363.56119 z"
+ id="rect3182" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000035, 4.00000035;stroke-dashoffset:0;stroke-opacity:1"
+ d="M -145.70904,497.60059 L 130.50958,496.27285 L 130.94124,426.5636 L 4.0769888,427.26388 L 2.9251588,387.60059 L 165.20484,387.60059 L 165.20484,521.85347 L -145.70904,521.85347 L -145.70904,497.60059 z"
+ id="rect3184"
+ sodipodi:nodetypes="ccccccccc" />
+ <text
+ id="text3206"
+ y="346.22397"
+ x="-175.31946"
+ style="font-size:32.92305374px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"><tspan
+ y="346.22397"
+ x="-175.31946"
+ id="tspan3208"
+ sodipodi:role="line">Union</tspan></text>
+ <path
+ id="path3301"
+ d="M -109.376,420.18825 L -76.596301,420.18825 L -76.596301,480.13612 L -109.376,480.13612 L -109.376,420.18825 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000028, 4.00000028;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000028, 4.00000028;stroke-dashoffset:0;stroke-opacity:1"
+ d="M -87.297935,372.34376 L -87.297935,405.12347 L -147.2458,405.12347 L -147.2458,372.34376 L -87.297935,372.34376 z"
+ id="path3303" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000019, 4.00000019;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 109.80135,957.83853 L 109.80135,972.18228 L 196.7076,972.18228 L 196.7076,957.83853 L 109.80135,957.83853 z"
+ id="path3344" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000028, 4.00000028;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 56.866249,835.89549 L 89.645949,835.89549 L 89.645949,895.84336 L 56.866249,895.84336 L 56.866249,835.89549 z"
+ id="path3350" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000028, 4.00000028;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 18.988849,788.05728 L 18.988849,820.83853 L 36.301349,820.83853 L 36.301349,794.99478 L 78.957599,794.99478 L 78.957599,788.05728 L 18.988849,788.05728 z"
+ id="path3352" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000019, 4.00000019;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 170.77092,818.12053 L 171.48967,842.96428 L 197.86467,842.80803 L 197.86467,818.12053 L 170.77092,818.12053 z M 197.86467,912.46428 L 110.95842,912.87053 L 110.95842,937.55803 L 197.86467,937.55803 L 197.86467,912.46428 z"
+ id="path3363" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M -230.83893,1007.8247 L 21.000929,1110.7973"
+ id="path3370" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 169.37394,1003.2069 L 73.161389,1109.4514"
+ id="path3372" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000028, 4.00000028;stroke-dashoffset:0;stroke-opacity:1"
+ d="M -109.376,1197.6263 L -76.596301,1197.6263 L -76.596301,1257.5742 L -109.376,1257.5742 L -109.376,1197.6263 z"
+ id="path3384" />
+ <path
+ id="path3390"
+ d="M -56.440901,1319.5693 L -56.440901,1333.9131 L 30.465349,1333.9131 L 30.465349,1319.5693 L -56.440901,1319.5693 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000019, 4.00000019;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ id="path3394"
+ d="M -147.2534,1149.7881 L -147.2534,1182.5693 L -129.9409,1182.5693 L -129.9409,1156.7256 L -87.284651,1156.7256 L -87.284651,1149.7881 L -147.2534,1149.7881 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000028, 4.00000028;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ id="path3398"
+ d="M 4.9108788,1179.8513 L 5.6296288,1204.6951 L 32.004629,1204.5388 L 32.004629,1179.8513 L 4.9108788,1179.8513 z M 32.004629,1274.1951 L -54.901621,1274.6013 L -54.901621,1299.2888 L 32.004629,1299.2888 L 32.004629,1274.1951 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000019, 4.00000019;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ style="opacity:0.60215053;fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 709.38099,43.724366 L 709.38099,248.00562 L 986.67852,248.00562 L 1029.5566,248.00562 L 1030.0349,153.81897 L 1001.5703,153.97203 L 1001.9499,231.86749 L 987.22644,231.92592 L 987.22644,43.724366 L 709.38099,43.724366 z M 782.88099,66.880616 L 869.78724,66.880616 L 869.78724,220.91187 L 782.88099,220.91187 L 782.88099,66.880616 z M 729.94349,84.630619 L 762.72474,84.630619 L 762.72474,144.56812 L 729.94349,144.56812 L 729.94349,84.630619 z"
+ id="path3400"
+ sodipodi:nodetypes="cccccccccccccccccccc" />
+ <path
+ style="opacity:0.60215053;fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.99999928;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 679.38099,28.005616 L 679.38099,206.56812 L 978.98214,206.56812 L 1022.256,206.56812 L 1022.256,158.04046 L 1022.256,28.005616 L 679.38099,28.005616 z M 692.06849,36.786866 L 752.03724,36.786866 L 752.03724,69.568116 L 692.06849,69.568116 L 692.06849,36.786866 z M 842.25599,52.036866 L 1004.5372,52.036866 L 1004.5372,186.28687 L 980.52142,186.28687 L 693.59974,186.28687 L 693.59974,162.03687 L 969.81849,160.72437 L 970.25599,91.005619 L 843.41224,91.693119 L 842.25599,52.036866 z"
+ id="path3404"
+ sodipodi:nodetypes="cccccccccccccccccccccc" />
+ <path
+ id="path5158"
+ d="M -35.253591,646.56646 L -218.00451,758.75729"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ id="path5160"
+ d="M -8.3903312,649.49025 L 157.576,783.23681"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-size:24px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="-206.51208"
+ y="683.30524"
+ id="text5164"><tspan
+ sodipodi:role="line"
+ id="tspan5166"
+ x="-206.51208"
+ y="683.30524"
+ dy="0 6.5306125 0 -4.3537416 0 0 4.3537416"
+ dx="0 -7.5755764e-08 0 0 0 0 -2.1768708">Ao + Bo</tspan></text>
+ <text
+ id="text5168"
+ y="681.76599"
+ x="46.533127"
+ style="font-size:24px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"><tspan
+ y="681.76599"
+ x="46.533127"
+ id="tspan5170"
+ sodipodi:role="line"
+ dy="0 8.7074833 -6.530612 0 0 0 4.3537416"
+ dx="0 -2.1768708 0 0 0 0 -2.1768708">Ah - Bo</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:24px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="79.49559"
+ y="713.51733"
+ id="text5172"><tspan
+ dx="0 -2.1768708 0 0 0 0 -2.1768708"
+ dy="0 7.6190481 -6.530612 0 0 0 4.3537416"
+ sodipodi:role="line"
+ id="tspan5174"
+ x="79.49559"
+ y="713.51733">Bh - Ao</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:24px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="12.668962"
+ y="652.90643"
+ id="text5176"><tspan
+ dx="0 -2.1768708 0 0 0 0"
+ dy="0 8.7074833 -6.530612 0 0 0"
+ sodipodi:role="line"
+ id="tspan5178"
+ x="12.668962"
+ y="652.90643">Ah x Bh</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:32.92305374px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="798.44019"
+ y="0.67824805"
+ id="text5590"><tspan
+ sodipodi:role="line"
+ id="tspan5592"
+ x="798.44019"
+ y="0.67824805">Input</tspan></text>
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000035, 4.00000035;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 313.34503,803.37606 L 313.34503,937.62606 L 330.65753,937.62606 L 330.65753,803.37606 L 313.34503,803.37606 z M 35.501279,913.31356 L 19.720029,913.37606 L 19.720029,937.62606 L 35.501279,937.62606 L 35.501279,913.31356 z"
+ id="path5604" />
+ <path
+ id="path5611"
+ d="M 145.72598,1166.9135 L 145.72598,1301.1635 L 163.03848,1301.1635 L 163.03848,1166.9135 L 145.72598,1166.9135 z M -132.11777,1276.851 L -147.89902,1276.9135 L -147.89902,1301.1635 L -132.11777,1301.1635 L -132.11777,1276.851 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000035, 4.00000035;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ id="path6029"
+ d="M 624.92611,402.42818 L 711.82267,402.42818 L 711.82267,556.4676 L 624.92611,556.4676 L 624.92611,402.42818 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000019, 4.00000019;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ id="path6031"
+ d="M 521.42857,363.56119 L 864.28569,363.56119 L 864.28569,542.13261 L 521.42857,542.13261 L 521.42857,363.56119 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:3.99999928;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="path6033"
+ d="M 535.6515,497.60059 L 811.87012,496.27285 L 812.30178,426.5636 L 685.43753,427.26388 L 684.2857,387.60059 L 846.56538,387.60059 L 846.56538,521.85347 L 535.6515,521.85347 L 535.6515,497.60059 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000035, 4.00000035;stroke-dashoffset:0;stroke-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-size:32.92305374px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="506.04111"
+ y="346.22397"
+ id="text6035"><tspan
+ sodipodi:role="line"
+ id="tspan6037"
+ x="506.04111"
+ y="346.22397">Intersection</tspan></text>
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000028, 4.00000028;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 571.98454,420.18825 L 604.76424,420.18825 L 604.76424,480.13612 L 571.98454,480.13612 L 571.98454,420.18825 z"
+ id="path6039" />
+ <path
+ id="path6041"
+ d="M 594.06261,372.34376 L 594.06261,405.12347 L 534.11474,405.12347 L 534.11474,372.34376 L 594.06261,372.34376 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000028, 4.00000028;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000019, 4.00000019;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 806.22279,765.03279 L 806.22279,797.81404 L 866.16029,797.81404 L 866.16029,765.03279 L 806.22279,765.03279 z"
+ id="path6973" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000019, 4.00000019;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 956.37904,780.31404 L 956.81664,795.12654 L 897.03534,795.12654 L 897.03534,889.87654 L 807.75404,890.31404 L 807.75404,914.56404 L 897.03534,914.56404 L 897.03534,949.15779 L 983.94164,949.15779 L 983.94164,914.56404 L 1118.6603,914.56404 L 1118.6603,780.31404 L 956.37904,780.31404 z"
+ id="path6971" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000019, 4.00000019;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 844.09779,812.90779 L 844.09779,872.84529 L 876.87899,872.84529 L 876.87899,812.90779 L 844.09779,812.90779 z"
+ id="path6069" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 1084.4116,819.29788 L 1083.9741,888.98538 L 983.94284,889.48538 L 983.94284,819.82913 L 1084.4116,819.29788 z"
+ id="path6052" />
+ <path
+ sodipodi:nodetypes="ccccccccc"
+ id="path6473"
+ d="M -2245.656,497.60059 L -1969.4374,496.27285 L -1969.0057,426.5636 L -2095.87,427.26388 L -2097.0218,387.60059 L -1934.7421,387.60059 L -1934.7421,521.85347 L -2245.656,521.85347 L -2245.656,497.60059 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000035, 4.00000035;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ id="path6469"
+ d="M -2156.3814,402.42818 L -2069.4848,402.42818 L -2069.4848,556.4676 L -2156.3814,556.4676 L -2156.3814,402.42818 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ id="path6471"
+ d="M -2259.8789,363.56119 L -1917.0218,363.56119 L -1917.0218,542.13261 L -2259.8789,542.13261 L -2259.8789,363.56119 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:3.99999928;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-size:32.92305374px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="-2275.2664"
+ y="346.22397"
+ id="text6475"><tspan
+ sodipodi:role="line"
+ id="tspan6477"
+ x="-2275.2664"
+ y="346.22397">Subtraction</tspan></text>
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ d="M -2209.3229,420.18825 L -2176.5432,420.18825 L -2176.5432,480.13612 L -2209.3229,480.13612 L -2209.3229,420.18825 z"
+ id="path6479" />
+ <path
+ id="path6481"
+ d="M -2187.2449,372.34376 L -2187.2449,405.12347 L -2247.1927,405.12347 L -2247.1927,372.34376 L -2187.2449,372.34376 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000028, 4.00000028;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ id="path6467"
+ d="M -2229.8789,379.27547 L -1952.0558,379.27547 L -1952.0558,583.56118 L -2229.8789,583.56118 L -2229.8789,379.27547 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4, 4;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-opacity:1"
+ d="M -2093.8401,646.56645 L -2973.6036,807.88598"
+ id="path6878" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-opacity:1"
+ d="M -2066.9767,649.49025 L -1901.0104,783.23681"
+ id="path6880" />
+ <text
+ id="text6882"
+ y="720.24799"
+ x="-2726.8826"
+ style="font-size:24px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"><tspan
+ dx="0 -7.5755764e-08 0 0 0 0 -2.1768708"
+ dy="0 6.5306125 0 -4.3537416 0 0 4.3537416"
+ y="720.24799"
+ x="-2726.8826"
+ id="tspan6884"
+ sodipodi:role="line">Ao + Bo</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:24px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="-1904.3037"
+ y="740.25861"
+ id="text6886"><tspan
+ dx="0 -2.1768708 0 0 0 0 -2.1768708"
+ dy="0 8.7074833 -6.530612 0 0 0 4.3537416"
+ sodipodi:role="line"
+ id="tspan6888"
+ x="-1904.3037"
+ y="740.25861">Ah - Bo</tspan></text>
+ <text
+ id="text6890"
+ y="765.85284"
+ x="-2471.9321"
+ style="font-size:24px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"><tspan
+ y="765.85284"
+ x="-2471.9321"
+ id="tspan6892"
+ sodipodi:role="line"
+ dy="0 7.6190481 -6.530612 0 0 0 4.3537416"
+ dx="0 -2.1768708 0 0 0 0 -2.1768708">Bh - Ao</tspan></text>
+ <text
+ id="text6894"
+ y="776.04883"
+ x="-2255.2595"
+ style="font-size:24px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"><tspan
+ y="776.04883"
+ x="-2255.2595"
+ id="tspan6896"
+ sodipodi:role="line"
+ dy="0 8.7074833 -6.530612 0 0 0"
+ dx="0 -2.1768708 0 0 0 0">Ah x Bh</tspan></text>
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:3.99999928;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ d="M -3160.7763,814.17474 L -3160.7763,992.73724 L -3130.7763,992.73724 L -3130.7763,829.89349 L -2852.9326,829.89349 L -2852.9326,992.73724 L -2817.9013,992.73724 L -2817.9013,814.17474 L -3160.7763,814.17474 z"
+ id="path6901" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000035, 4.00000035;stroke-dashoffset:0;stroke-opacity:1"
+ d="M -2323.8213,841.56372 L -2323.3838,856.40747 L -2296.2901,856.40747 L -2296.2901,881.06372 L -2195.8213,880.53247 L -2196.2276,950.25122 L -2296.2901,950.71997 L -2296.2901,975.81372 L -2161.5401,975.81372 L -2161.5401,841.56372 L -2323.8213,841.56372 z M -2383.1963,951.12622 L -2472.4463,951.56372 L -2472.4463,975.81372 L -2383.1963,975.81372 L -2383.1963,951.12622 z"
+ id="path6908" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ d="M -2133.7904,820.70536 L -2133.7904,999.26786 L -2030.2904,999.26786 L -2030.2904,1013.6116 L -1943.3842,1013.6116 L -1943.3842,999.26786 L -1790.9154,999.26786 L -1790.9154,820.70536 L -2133.7904,820.70536 z"
+ id="path6910" />
+ <path
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ d="M -2331.1534,1093.5194 L -2331.1534,1119.3631 L -2288.4971,1119.3631 L -2288.4971,1093.5194 L -2331.1534,1093.5194 z M -2198.2784,1101.8319 L -2197.8409,1116.6756 L -2170.7471,1116.6756 L -2170.7471,1141.3319 L -2070.2784,1140.8006 L -2070.7159,1210.5194 L -2170.7471,1210.9881 L -2170.7471,1236.0819 L -2053.3096,1236.0819 L -2053.3096,1101.8319 L -2198.2784,1101.8319 z M -2257.6534,1211.3944 L -2331.1534,1211.7694 L -2331.1534,1236.0819 L -2257.6534,1236.0819 L -2257.6534,1211.3944 z M -2331.1534,1256.3631 L -2331.1534,1297.8007 L -2053.3096,1297.8007 L -2053.3096,1256.3631 L -2170.7471,1256.3631 L -2170.7471,1270.7069 L -2257.6534,1270.7069 L -2257.6534,1256.3631 L -2331.1534,1256.3631 z"
+ id="path6925" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000035, 4.00000035;stroke-dashoffset:0;stroke-opacity:1"
+ d="M -2774.488,821.625 L -2774.488,847.46875 L -2731.8317,847.46875 L -2731.8317,821.625 L -2774.488,821.625 z M -2644.988,830.90625 L -2643.8317,870.5625 L -2516.988,869.875 L -2517.3942,939.59375 L -2777.863,940.84375 L -2777.863,965.15625 L -2500.0192,965.15625 L -2500.0192,830.90625 L -2644.988,830.90625 z"
+ id="path6931" />
+ <path
+ id="path6936"
+ d="M -2093.84,646.56647 L -2542.9316,832.52418"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999988px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-opacity:1" />
+ <path
+ id="path6938"
+ d="M -2067.9768,649.49026 L -2323.4675,795.52171"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-opacity:1" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 694.05575,628.0951 L 511.30483,740.28593"
+ id="path6955" />
+ <text
+ id="text6957"
+ y="664.83386"
+ x="522.79724"
+ style="font-size:24px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"><tspan
+ dx="0 -7.5755764e-08 0 0 0 0 -2.1768708"
+ dy="0 6.5306125 0 0 0 0 4.3537416"
+ y="664.83386"
+ x="522.79724"
+ id="tspan6959"
+ sodipodi:role="line">Ao x Bo</tspan></text>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 730.15469,624.86177 L 896.12104,758.60833"
+ id="path6961" />
+ <text
+ xml:space="preserve"
+ style="font-size:24px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="804.48547"
+ y="664.83386"
+ id="text6963"><tspan
+ sodipodi:role="line"
+ id="tspan6965"
+ x="804.48547"
+ y="664.83386"
+ dy="0 6.1571202 -6.1571202 0 0 0 6.1571202"
+ dx="0 -1.5392801 -1.5392801 0 0 0 -1.5392801">Ah + Bh</tspan></text>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 512.32394,932.29834 L 512.32394,1009.2623 L 801.70859,782.98817"
+ id="path6975" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:3.99999928;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 502.87904,1011.75 L 502.87904,1036.4062 L 457.84779,1036.4062 L 457.84779,1174.5938 L 735.66029,1174.5938 L 735.66029,1011.75 L 502.87904,1011.75 z"
+ id="path6977" />
+ <text
+ xml:space="preserve"
+ style="font-size:28px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="493.85257"
+ y="990.79102"
+ id="text6979"><tspan
+ sodipodi:role="line"
+ id="tspan6981"
+ x="493.85257"
+ y="990.79102">-</tspan></text>
+ <path
+ id="path6986"
+ d="M 512.32397,1188.1621 L 512.32397,1249.39 L 852.50489,919.98413"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:nodetypes="ccc" />
+ <text
+ id="text6988"
+ y="1230.9187"
+ x="493.85257"
+ style="font-size:28px;font-style:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"><tspan
+ y="1230.9187"
+ x="493.85257"
+ id="tspan6990"
+ sodipodi:role="line">-</tspan></text>
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:3.99999928;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 502.87904,1253.417 L 502.87904,1278.0732 L 457.84779,1278.0732 L 457.84779,1372.042 L 532.22279,1371.667 L 532.22279,1276.917 L 592.00404,1276.917 L 591.56654,1262.1045 L 735.66029,1262.1045 L 735.66029,1253.417 L 502.87904,1253.417 z M 457.84779,1396.3545 L 457.84779,1416.2608 L 532.22279,1416.2608 L 532.22279,1396.3545 L 457.84779,1396.3545 z M 619.12904,1396.3545 L 619.12904,1416.2608 L 735.66029,1416.2608 L 735.66029,1396.3545 L 619.12904,1396.3545 z"
+ id="path6999" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 844.80843,852.25577 L 867.89759,1104.6977 L 1032.6006,890.73778"
+ id="path7004" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 867.89769,1103.1584 L 738.59811,1323.2755 L 878.67264,1324.8148"
+ id="path7006"
+ sodipodi:nodetypes="ccc" />
+ <path
+ id="path7794"
+ d="M 940.03464,1253.417 L 940.03464,1278.0732 L 895.00334,1278.0732 L 895.00334,1372.042 L 969.37834,1371.667 L 969.37834,1276.917 L 1029.1596,1276.917 L 1028.7221,1262.1045 L 1172.8158,1262.1045 L 1172.8158,1253.417 L 940.03464,1253.417 z M 895.00334,1396.3545 L 895.00334,1416.2608 L 969.37834,1416.2608 L 969.37834,1396.3545 L 895.00334,1396.3545 z M 1056.2846,1396.3545 L 1056.2846,1416.2608 L 1172.8158,1416.2608 L 1172.8158,1396.3545 L 1056.2846,1396.3545 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:3.99999928;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ id="path7796"
+ d="M 917.98324,1293.1632 L 917.98324,1353.1007 L 950.76444,1353.1007 L 950.76444,1293.1632 L 917.98324,1293.1632 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000019, 4.00000019;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ id="path7798"
+ d="M 1156.7578,1299.5533 L 1156.3203,1369.2408 L 1056.289,1369.7408 L 1056.289,1300.0846 L 1156.7578,1299.5533 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000019, 4.00000019;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 1442.2087,402.42818 L 1529.1052,402.42818 L 1529.1052,556.4676 L 1442.2087,556.4676 L 1442.2087,402.42818 z"
+ id="path7806" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 1352.9341,497.60059 L 1629.1527,496.27285 L 1629.5844,426.5636 L 1502.7201,427.26388 L 1501.5683,387.60059 L 1663.848,387.60059 L 1663.848,521.85347 L 1352.9341,521.85347 L 1352.9341,497.60059 z"
+ id="path7810"
+ sodipodi:nodetypes="ccccccccc" />
+ <text
+ id="text7812"
+ y="346.22397"
+ x="1323.3237"
+ style="font-size:32.92305374px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"><tspan
+ y="346.22397"
+ x="1323.3237"
+ id="tspan7814"
+ sodipodi:role="line">Subtraction</tspan></text>
+ <path
+ id="path7816"
+ d="M 1389.2671,420.18825 L 1422.0468,420.18825 L 1422.0468,480.13612 L 1389.2671,480.13612 L 1389.2671,420.18825 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4.00000028, 4.00000028;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 1411.3452,372.34376 L 1411.3452,405.12347 L 1351.3973,405.12347 L 1351.3973,372.34376 L 1411.3452,372.34376 z"
+ id="path7818" />
+ <path
+ id="path7850"
+ d="M 1534.4275,603.46662 L 1536.9936,715.65745"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.99999976;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-size:24px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="1413.6588"
+ y="631.49792"
+ id="text7852"><tspan
+ sodipodi:role="line"
+ id="tspan7854"
+ x="1413.6588"
+ y="631.49792"
+ dy="0 6.5306125 -6.1571202 0 0 0 4.3537416"
+ dx="0 -7.5755764e-08 0 0 0 0 -2.1768708">Ao - Bo</tspan></text>
+ <path
+ id="path7856"
+ d="M 1530.2556,953.47868 L 1529.7129,1119.6459"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow2Lend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ xml:space="preserve"
+ style="font-size:24px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="1414.9861"
+ y="657.44348"
+ id="text7887"><tspan
+ sodipodi:role="line"
+ id="tspan7889"
+ x="1414.9861"
+ y="657.44348"
+ dy="0 6.5306125 0 -6.1571202 0 0 8.7074833"
+ dx="0 -7.5755764e-08 0 0 0 0 -2.1768708">Ao x Bh</tspan></text>
+ <text
+ id="text7932"
+ y="1036.9882"
+ x="1469.9934"
+ style="font-size:24px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ xml:space="preserve"><tspan
+ dx="0 0"
+ dy="0 0 0 8.7074833"
+ y="1036.9882"
+ x="1469.9934"
+ id="tspan7934"
+ sodipodi:role="line">- Ah</tspan></text>
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ d="M -129.54136,380.68793 L -129.54136,584.96918 L 147.75617,584.96918 L 190.63429,584.96918 L 191.11257,490.78253 L 162.64795,490.93559 L 163.02759,568.83105 L 148.30409,568.88948 L 148.30409,380.68793 L -129.54136,380.68793 z"
+ id="path8337" />
+ <path
+ id="path8339"
+ d="M 552.35971,380.68793 L 552.35971,584.96918 L 829.65724,584.96918 L 872.53536,584.96918 L 873.01364,490.78253 L 844.54902,490.93559 L 844.92866,568.83105 L 830.20516,568.88948 L 830.20516,380.68793 L 552.35971,380.68793 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 1369.7174,380.68793 L 1369.7174,584.96918 L 1647.015,584.96918 L 1689.8931,584.96918 L 1690.3714,490.78253 L 1661.9067,490.93559 L 1662.2864,568.83105 L 1647.5629,568.88948 L 1647.5629,380.68793 L 1369.7174,380.68793 z"
+ id="path8341" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:3.99999928;stroke-miterlimit:4;stroke-dasharray:3.99999928, 3.99999928;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 1338.7111,363.56119 L 1681.5683,363.56119 L 1681.5683,428.95375 L 1681.5683,542.13261 L 1338.7111,542.13261 L 1338.7111,363.56119 z"
+ id="path7808"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:3.99999928;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ d="M -364.66175,776.08956 L -364.66175,954.65206 L -334.2555,954.65206 L -334.2555,997.49581 L -56.974249,997.49581 L -14.099249,997.49581 L -13.599249,903.30831 L -21.786749,903.33956 L -21.786749,776.08956 L -364.66175,776.08956 z"
+ id="path8350" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:4;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;stroke-dasharray:4,4"
+ d="M -56.411749,954.65206 L -41.817999,954.65206 L -41.692999,981.37081 L -56.411749,981.40206 L -56.411749,954.65206 z"
+ id="path8343" />
+ <path
+ id="path8354"
+ d="M -159.9375,1140.8989 L -159.9375,1319.4614 L -129.53125,1319.4614 L -129.53125,1362.3052 L 147.75,1362.3052 L 190.625,1362.3052 L 191.125,1268.1177 L 182.9375,1268.1489 L 182.9375,1140.8989 L -159.9375,1140.8989 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:3.99999928;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ id="path8356"
+ d="M 148.3125,1319.4614 L 162.90625,1319.4614 L 163.03125,1346.1802 L 148.3125,1346.2114 L 148.3125,1319.4614 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:4, 4;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:3.99999928;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 456.93964,767.0468 L 456.93964,928.4843 L 734.78339,928.4843 L 734.78339,767.0468 L 456.93964,767.0468 z"
+ id="path8365" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:3.99999928;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 768.84589,877.20305 L 749.12714,877.2968 L 749.37714,928.4843 L 768.84589,928.4843 L 768.84589,877.20305 z"
+ id="path8358" />
+ <path
+ id="path8367"
+ d="M 768.84589,1123.4878 L 749.12714,1123.5816 L 749.37714,1174.7691 L 768.84589,1174.7691 L 768.84589,1123.4878 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:3.99999928;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:3.99999928;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 768.84375 1365.4375 L 753.84375 1365.5 L 753.84375 1396.3438 L 749.28125 1396.3438 L 749.375 1416.7188 L 768.84375 1416.7188 L 768.84375 1365.4375 z "
+ id="path8369" />
+ <path
+ id="path8376"
+ d="M 1207.5386,1365.4375 L 1192.5386,1365.5 L 1192.5386,1396.3438 L 1187.9761,1396.3438 L 1188.0698,1416.7188 L 1207.5386,1416.7188 L 1207.5386,1365.4375 z"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#0000ff;stroke-width:3.99999928;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 1368.7188 727.3125 L 1368.7188 753.15625 L 1411.375 753.15625 L 1411.375 727.3125 L 1368.7188 727.3125 z M 1502.1562 735.28125 L 1503.3125 774.9375 L 1630.1562 774.25 L 1629.7188 843.96875 L 1369.2812 845.21875 L 1369.2812 869.53125 L 1647.125 869.53125 L 1647.125 735.28125 L 1502.1562 735.28125 z M 1690.375 834.03125 L 1681.5625 834.09375 L 1681.5625 885.375 L 1662.1562 885.375 L 1662.2812 912.09375 L 1647.5625 912.125 L 1647.5625 885.375 L 1369.7188 885.375 L 1369.7188 928.21875 L 1647 928.21875 L 1689.9062 928.21875 L 1690.375 834.03125 z M 1663.4062 838.125 L 1660.4375 838.15625 L 1660.5938 870.46875 L 1663.4062 870.46875 L 1663.4062 838.125 z "
+ id="path7892" />
+ <path
+ style="opacity:1;fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 1368.2454,1469.8261 L 1368.2454,1495.6699 L 1410.9016,1495.6699 L 1410.9016,1469.8261 L 1368.2454,1469.8261 z M 1501.1204,1478.1386 L 1501.5579,1492.9824 L 1528.6516,1492.9824 L 1528.6516,1517.6386 L 1629.1204,1517.1074 L 1628.6829,1586.8261 L 1528.6516,1587.2949 L 1528.6516,1612.3886 L 1639.4016,1612.3886 L 1646.0891,1612.3886 L 1646.0891,1478.1386 L 1501.1204,1478.1386 z M 1688.9016,1579.9199 L 1681.1204,1579.9511 L 1681.1204,1584.1386 L 1681.1204,1632.6699 L 1660.6829,1632.6699 L 1660.8079,1657.9511 L 1646.0891,1658.0136 L 1646.0891,1632.6699 L 1637.8391,1632.6699 L 1528.6516,1632.6699 L 1528.6516,1647.0136 L 1441.7454,1647.0136 L 1441.7454,1632.6699 L 1368.2454,1632.6699 L 1368.2454,1674.1074 L 1645.5579,1674.1074 L 1688.4329,1674.1074 L 1688.9016,1579.9199 z M 1663.4016,1580.0449 L 1660.4329,1580.0761 L 1660.5891,1612.3886 L 1663.4016,1612.3886 L 1663.4016,1580.0449 z M 1441.7454,1587.7011 L 1368.2454,1588.0761 L 1368.2454,1612.3886 L 1441.7454,1612.3886 L 1441.7454,1587.7011 z"
+ id="path8411" />
+ <path
+ style="opacity:1;fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ d="M -161.22241,1457.4046 L -161.22241,1635.9671 L -131.22241,1635.9671 L -131.22241,1677.4046 L 146.09009,1677.4046 L 188.96509,1677.4046 L 189.43379,1583.2171 L 181.65259,1583.2484 L 181.65259,1457.4046 L -161.22241,1457.4046 z M -148.53491,1466.1859 L -88.566206,1466.1859 L -88.566206,1473.1234 L -131.22241,1473.1234 L -131.22241,1498.9671 L -148.53491,1498.9671 L -148.53491,1466.1859 z M 146.62129,1481.4359 L 163.93379,1481.4359 L 163.93379,1583.3421 L 160.96509,1583.3734 L 161.12129,1615.6859 L 146.62129,1615.6859 L 146.62129,1481.4359 z M 2.0900943,1496.2796 L 29.183794,1496.2796 L 29.183794,1520.9359 L 2.8087943,1521.0921 L 2.0900943,1496.2796 z M 29.183794,1590.5921 L 29.183794,1615.6859 L -57.722406,1615.6859 L -57.722406,1590.9984 L 29.183794,1590.5921 z M -131.22241,1591.3734 L -131.22241,1615.6859 L -147.00371,1615.6859 L -147.00371,1591.4359 L -131.22241,1591.3734 z M -57.722406,1635.9671 L 29.183794,1635.9671 L 29.183794,1650.3109 L -57.722406,1650.3109 L -57.722406,1635.9671 z M 146.62129,1635.9671 L 161.21509,1635.9671 L 161.34009,1661.2484 L 146.62129,1661.3109 L 146.62129,1635.9671 z"
+ id="path8416" />
+ <path
+ style="opacity:1;fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 936.10246,1469.7356 L 936.10246,1495.5793 L 893.44616,1495.5793 L 893.44616,1587.9856 L 966.94616,1587.6106 L 966.94616,1492.8918 L 1026.7586,1492.8918 L 1026.3211,1478.0481 L 1171.29,1478.0481 L 1171.29,1469.7356 L 936.10246,1469.7356 z M 914.00866,1510.6418 L 946.78996,1510.6418 L 946.78996,1570.5793 L 914.00866,1570.5793 L 914.00866,1510.6418 z M 1154.3212,1517.0168 L 1053.8524,1517.5481 L 1053.8524,1587.2043 L 1153.8837,1586.7356 L 1154.3212,1517.0168 z M 1206.3212,1579.8606 L 1188.6025,1579.9543 L 1188.6025,1612.2981 L 1185.79,1612.2981 L 1185.8837,1632.5793 L 1206.3212,1632.5793 L 1206.3212,1584.0481 L 1206.3212,1579.8606 z M 893.44616,1612.2981 L 893.44616,1632.5793 L 966.94616,1632.5793 L 966.94616,1612.2981 L 893.44616,1612.2981 z M 1053.8524,1612.2981 L 1053.8524,1632.5793 L 1163.04,1632.5793 L 1171.29,1632.5793 L 1171.29,1612.2981 L 1164.6025,1612.2981 L 1053.8524,1612.2981 z"
+ id="path8421" />
+ <path
+ id="path8406"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:4;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 1368.7188,1164.468 L 1368.7188,1190.3118 L 1411.375,1190.3118 L 1411.375,1164.468 L 1368.7188,1164.468 z M 1502.1562,1172.4368 L 1502.4688,1182.843 L 1529.0938,1182.843 L 1529.0938,1211.968 L 1630.1562,1211.4055 L 1629.7188,1281.1243 L 1529.0938,1281.593 L 1529.0938,1306.6868 L 1647.125,1306.6868 L 1647.125,1172.4368 L 1502.1562,1172.4368 z M 1690.375,1271.1868 L 1681.5625,1271.2493 L 1681.5625,1322.5305 L 1662.1562,1322.5305 L 1662.2812,1349.2493 L 1647.5625,1349.2805 L 1647.5625,1322.5305 L 1529.0938,1322.5305 L 1529.0938,1336.8743 L 1442.2188,1336.8743 L 1442.2188,1322.5305 L 1369.7188,1322.5305 L 1369.7188,1365.3743 L 1647,1365.3743 L 1689.9062,1365.3743 L 1690.375,1271.1868 z M 1442.2188,1282.0305 L 1369.2812,1282.3743 L 1369.2812,1306.6868 L 1442.2188,1306.6868 L 1442.2188,1282.0305 zM 1663.4016,1275.2675 L 1660.4329,1275.2987 L 1660.5891,1307.6112 L 1663.4016,1307.6112 L 1663.4016,1275.2675 z" />
+ <text
+ xml:space="preserve"
+ style="font-size:24px;font-style:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Sans"
+ x="181.63506"
+ y="73.380066"
+ id="text2348"><tspan
+ sodipodi:role="line"
+ id="tspan2350"
+ x="181.63506"
+ y="73.380066">Shape Boolops</tspan><tspan
+ sodipodi:role="line"
+ x="181.63506"
+ y="103.38007"
+ id="tspan2352">Michael Sloan</tspan></text>
+ </g>
+</svg>
diff --git a/src/3rdparty/2geom/doc/sweep.svg b/src/3rdparty/2geom/doc/sweep.svg
new file mode 100644
index 0000000..72920c9
--- /dev/null
+++ b/src/3rdparty/2geom/doc/sweep.svg
@@ -0,0 +1,430 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="1052.3622"
+ height="744.09448"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.46+devel r21616 custom"
+ sodipodi:docname="sweep.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Send"
+ style="overflow:visible">
+ <path
+ id="path936"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ <inkscape:perspective
+ id="perspective859"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.70082296"
+ inkscape:cx="851.52284"
+ inkscape:cy="299.19226"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ inkscape:window-width="1680"
+ inkscape:window-height="977"
+ inkscape:window-x="0"
+ inkscape:window-y="24"
+ inkscape:window-maximized="1">
+ <inkscape:grid
+ type="xygrid"
+ id="grid12"
+ empspacing="4"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true"
+ units="mm"
+ spacingx="1mm"
+ spacingy="1mm" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-308.2677)">
+ <path
+ id="path1413"
+ d="m 226.77166,712.2047 c 99.2126,-28.34646 368.50394,14.17323 481.88976,0"
+ style="fill:none;stroke:#000000;stroke-width:1px"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px"
+ d="m 240.94489,953.14958 127.55905,0"
+ id="path847" />
+ <path
+ id="path849"
+ d="m 637.79528,953.14958 127.55905,0"
+ style="fill:none;stroke:#000000;stroke-width:1px" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px"
+ d="m 226.77166,726.37793 c 85.03937,0 396.85039,0 396.85039,212.59842"
+ id="path843" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px"
+ d="m 432.28348,818.50391 42.51968,-28.34646 0,56.69291 -42.51968,-28.34645"
+ id="path845" />
+ <rect
+ y="471.25983"
+ x="141.73233"
+ height="28.346457"
+ width="42.519684"
+ id="rect793"
+ style="fill:#b3b3b3;stroke:none" />
+ <rect
+ y="471.25983"
+ x="255.11816"
+ height="28.346457"
+ width="42.519684"
+ id="rect797"
+ style="fill:#b3b3b3;stroke:none" />
+ <rect
+ y="471.25983"
+ x="368.504"
+ height="28.346457"
+ width="42.519684"
+ id="rect801"
+ style="fill:#b3b3b3;stroke:none" />
+ <rect
+ style="fill:#b3b3b3;stroke:none"
+ id="rect14"
+ width="42.519684"
+ height="28.346457"
+ x="481.8898"
+ y="471.25983" />
+ <path
+ id="path795"
+ d="m 127.55911,414.56689 0,155.90553"
+ style="fill:none;stroke:#0000ff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:2, 2;stroke-dashoffset:0" />
+ <path
+ id="path799"
+ d="m 240.94494,414.5669 c 0,0 0,30.55294 0,56.69292 0,7.08661 3.54331,10.62992 7.08661,10.62992 8.89859,0 21.25985,0 21.25985,10.62992 0,21.97915 -21.25985,15.37432 -21.25985,7.08661 0,-7.08661 -7.08661,-6.84684 -7.08661,0 0,27.18227 0,70.86615 0,70.86615"
+ style="fill:none;stroke:#0000ff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:2, 2;stroke-dashoffset:0"
+ sodipodi:nodetypes="cssssss" />
+ <path
+ sodipodi:nodetypes="cssssssssss"
+ style="fill:none;stroke:#0000ff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:2, 2;stroke-dashoffset:0"
+ d="m 354.33077,414.56689 c 0,0 0,30.55294 0,56.69292 0,7.08661 3.54331,10.62992 7.08661,10.62992 5.30296,0 10.62992,1e-5 14.17323,1e-5 7.08661,0 4.51157,-14.57853 10.62992,-17.71654 5.14942,-2.64105 21.25984,-3.5433 28.34646,3.54331 7.08661,7.08662 7.08661,28.34646 0,35.43307 -7.08662,7.08661 -38.71107,5.28254 -46.063,3.54331 -3.44813,-0.81572 -7.08661,-3.07644 -7.08661,-7.08662 0,-7.08662 -7.08661,-6.84685 -7.08661,0 0,27.18227 0,70.86615 0,70.86615"
+ id="path805" />
+ <path
+ id="path791"
+ style="fill:none;stroke:#0000ff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:2, 2;stroke-dashoffset:0"
+ d="m 467.71659,570.47242 0,-81.49607 7.08662,0 -10e-6,10.62993 c 0,3.92598 3.16063,7.08661 7.08661,7.08661 l 42.5197,0 c 3.92598,0 7.08661,-3.16063 7.08661,-7.08661 l 0,-28.34646 c 0,-3.92598 -3.16063,-7.08661 -7.08661,-7.08661 l -42.5197,0 c -3.92598,0 -7.08661,3.16063 -7.08661,7.08661 l 10e-6,10.62992 -7.08662,0 0,-67.32284"
+ sodipodi:nodetypes="cccccccccccccc" />
+ <rect
+ y="471.25983"
+ x="595.2757"
+ height="28.346457"
+ width="42.519684"
+ id="rect815"
+ style="fill:#b3b3b3;stroke:none" />
+ <path
+ id="path817"
+ style="fill:none;stroke:#0000ff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:2, 2;stroke-dashoffset:0"
+ d="m 609.44888,513.7795 -14.17326,0 c -7.85197,0 -14.17323,-6.32126 -14.17323,-14.17323 l 3e-5,-10.62992 7.08663,10e-6 -10e-6,10.62992 c 0,3.92598 3.16063,7.08661 7.08661,7.08661 l 42.5197,0 c 3.92598,0 7.08661,-3.16063 7.08661,-7.08661 l 0,-28.34646 c 0,-3.92598 -3.16063,-7.08661 -7.08661,-7.08661 l -42.5197,0 c -3.92598,0 -7.08661,3.16063 -7.08661,7.08661 l 10e-6,10.62992 -7.08663,0 -3e-5,-10.62992 c 0,-7.85197 6.32126,-14.17323 14.17323,-14.17323 l 14.17326,0 m 0,0 0,-42.51969 m 0,155.90552 0,-56.69292"
+ sodipodi:nodetypes="cccccccccccccccccccccc" />
+ <rect
+ style="fill:#b3b3b3;stroke:none"
+ id="rect823"
+ width="42.519684"
+ height="28.346457"
+ x="708.66144"
+ y="471.25983" />
+ <path
+ sodipodi:nodetypes="cccccccccccccccccccccccccc"
+ d="m 772.441,414.5669 0,67.32284 -7.08661,0 -3e-5,-10.62992 c 0,-7.85197 -6.32126,-14.17323 -14.17323,-14.17323 l -42.51971,0 c -7.85197,0 -14.17323,6.32126 -14.17323,14.17323 l 3e-5,10.62992 7.08663,10e-6 -10e-6,-10.62993 c 0,-3.92598 3.16063,-7.08661 7.08661,-7.08661 l 42.5197,0 c 3.92598,0 7.08661,3.16063 7.08661,7.08661 l 0,28.34646 c 0,3.92598 -3.16063,7.08661 -7.08661,7.08661 l -42.5197,0 c -3.92598,0 -7.08661,-3.16063 -7.08661,-7.08661 l 10e-6,-10.62992 -7.08663,0 -3e-5,10.62991 c 0,7.85197 6.32126,14.17323 14.17323,14.17323 l 42.51971,0 c 7.85197,0 14.17323,-6.32126 14.17323,-14.17323 l 3e-5,-10.62992 7.08661,0 0,81.49607"
+ style="fill:none;stroke:#0000ff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:2, 2;stroke-dashoffset:0"
+ id="path825" />
+ <rect
+ style="fill:#b3b3b3;stroke:none"
+ id="rect831"
+ width="42.519684"
+ height="28.346457"
+ x="822.04724"
+ y="471.25983" />
+ <path
+ style="fill:none;stroke:#0000ff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:2, 2;stroke-dashoffset:0"
+ d="m 878.74021,414.5669 0,155.90553"
+ id="path833" />
+ <rect
+ style="fill:#b3b3b3;stroke:none"
+ id="rect835"
+ width="297.63779"
+ height="28.346457"
+ x="354.33069"
+ y="938.97632" />
+ <rect
+ y="783.07086"
+ x="467.71661"
+ height="14.173101"
+ width="14.173126"
+ id="rect841"
+ style="fill:#b3b3b3;stroke:none" />
+ <rect
+ style="fill:#b3b3b3;stroke:none"
+ id="rect837"
+ width="14.173126"
+ height="14.173101"
+ x="467.71652"
+ y="839.76385" />
+ <rect
+ style="fill:#b3b3b3;stroke:none"
+ id="rect839"
+ width="14.173228"
+ height="14.173239"
+ x="425.19684"
+ y="811.4173" />
+ <path
+ sodipodi:nodetypes="cccccccccccccc"
+ d="m 325.98426,1038.189 -1e-5,-92.12603 21.25985,0 0,24.80315 c 0,3.92598 3.16063,7.08661 7.08661,7.08661 l 297.6378,0 c 3.92598,0 10.62992,-3.16063 10.62992,-7.08661 l 0,-35.43308 c 0,-3.92598 -6.70394,-7.08661 -10.62992,-7.08661 l -297.63779,0 c -3.92598,0 -7.08661,3.16063 -7.08661,7.08661 l -10e-6,3.54331 -21.25985,0 1e-5,-255.11811"
+ style="fill:none;stroke:#0000ff;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:2, 2;stroke-dashoffset:0"
+ id="path877" />
+ <path
+ transform="translate(116.92914,503.1496)"
+ d="m 212.59842,226.77164 a 3.5433071,3.5433071 0 1 1 -7.08661,0 3.5433071,3.5433071 0 1 1 7.08661,0 z"
+ sodipodi:ry="3.5433071"
+ sodipodi:rx="3.5433071"
+ sodipodi:cy="226.77164"
+ sodipodi:cx="209.05511"
+ id="use883"
+ style="fill:#00ff00;stroke:none"
+ sodipodi:type="arc" />
+ <path
+ transform="translate(116.92914,726.37794)"
+ d="m 212.59842,226.77164 a 3.5433071,3.5433071 0 1 1 -7.08661,0 3.5433071,3.5433071 0 1 1 7.08661,0 z"
+ sodipodi:ry="3.5433071"
+ sodipodi:rx="3.5433071"
+ sodipodi:cy="226.77164"
+ sodipodi:cx="209.05511"
+ id="use891"
+ style="fill:#00ff00;stroke:none"
+ sodipodi:type="arc" />
+ <path
+ transform="translate(453.54332,726.37794)"
+ d="m 212.59842,226.77164 a 3.5433071,3.5433071 0 1 1 -7.08661,0 3.5433071,3.5433071 0 1 1 7.08661,0 z"
+ sodipodi:ry="3.5433071"
+ sodipodi:rx="3.5433071"
+ sodipodi:cy="226.77164"
+ sodipodi:cx="209.05511"
+ id="use881"
+ style="fill:#00ff00;stroke:none"
+ sodipodi:type="arc" />
+ <path
+ transform="translate(138.18898,726.37794)"
+ d="m 212.59842,226.77164 a 3.5433071,3.5433071 0 1 1 -7.08661,0 3.5433071,3.5433071 0 1 1 7.08661,0 z"
+ sodipodi:ry="3.5433071"
+ sodipodi:rx="3.5433071"
+ sodipodi:cy="226.77164"
+ sodipodi:cx="209.05511"
+ id="path887"
+ style="fill:#ff0000;stroke:none"
+ sodipodi:type="arc" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path887"
+ id="use893"
+ transform="translate(276.37795,-24.803144)"
+ width="744.09448"
+ height="1052.3622" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)"
+ d="m 127.55911,428.74013 28.34645,0"
+ id="path916" />
+ <use
+ height="1052.3622"
+ width="744.09448"
+ transform="translate(340.15748,1.7672246e-6)"
+ id="use1369"
+ xlink:href="#path916"
+ y="0"
+ x="0" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path916"
+ id="use1367"
+ transform="translate(481.88976,1.7672246e-6)"
+ width="744.09448"
+ height="1052.3622" />
+ <path
+ id="path1371"
+ d="m 262.20478,506.69289 c 10.03817,7.0722 19.2398,4.10591 28.34646,0"
+ style="fill:none;stroke:#000000;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)"
+ sodipodi:nodetypes="cc" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#000000;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)"
+ d="m 388.22918,456.94784 c -12.15917,-1.71331 -18.9939,5.12449 -25.22416,12.93305"
+ id="path1373" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#000000;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Send)"
+ d="m 688.46073,501.78863 c 0.007,13.75525 8.4367,18.00622 20.95338,19.09129"
+ id="path1375" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#path1375"
+ id="use1377"
+ transform="matrix(1,0,0,-1,-0.70939357,971.46722)"
+ width="744.09448"
+ height="1052.3622" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ x="623.62207"
+ y="783.07086"
+ id="text1379"><tspan
+ sodipodi:role="line"
+ id="tspan1381"
+ x="623.62207"
+ y="783.07086"
+ style="font-size:12px">this tile has its both ends</tspan><tspan
+ sodipodi:role="line"
+ x="623.62207"
+ y="798.07086"
+ id="tspan1383"
+ style="font-size:12px">in the &quot;known&quot; area, but still</tspan><tspan
+ sodipodi:role="line"
+ x="623.62207"
+ y="813.07086"
+ id="tspan1385"
+ style="font-size:12px">travels through the unknown.</tspan></text>
+ <path
+ id="path1387"
+ d="m 418.11024,818.50391 -85.03937,0"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0;marker-end:url(#Arrow1Send)"
+ sodipodi:nodetypes="cc" />
+ <text
+ id="text1395"
+ y="839.76373"
+ x="340.15747"
+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ style="font-size:12px"
+ y="839.76373"
+ x="340.15747"
+ sodipodi:role="line"
+ id="tspan1407">this piece should </tspan><tspan
+ style="font-size:12px"
+ y="854.76373"
+ x="340.15747"
+ sodipodi:role="line"
+ id="tspan1419">be inserted here</tspan></text>
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker-end:url(#Arrow1Send)"
+ d="m 694.4882,825.59053 c 0,28.34645 -48.419,52.18112 -70.86615,56.69291"
+ id="path1411" />
+ <path
+ sodipodi:nodetypes="cc"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 2;stroke-dashoffset:0;marker-end:url(#Arrow1Send)"
+ d="M 446.46402,797.25871 C 435.54028,749.38028 382.88666,716.7021 332.35416,712.2047"
+ id="path1415" />
+ <use
+ x="0"
+ y="0"
+ xlink:href="#use883"
+ id="use1417"
+ transform="translate(4.0944874e-7,-28.346454)"
+ width="744.09448"
+ height="1052.3622" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ x="396.85037"
+ y="726.37793"
+ id="text1425"><tspan
+ id="tspan1429"
+ sodipodi:role="line"
+ x="396.85037"
+ y="726.37793"
+ style="font-size:12px">not there!</tspan></text>
+ <path
+ style="fill:none;stroke:#ff0000;stroke-width:4"
+ d="m 411.02363,768.89761 42.51968,0 m -14.17322,-14.17323 -14.17323,28.34646"
+ id="path1433"
+ sodipodi:nodetypes="cccc" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ x="212.59842"
+ y="357.87399"
+ id="text1435"><tspan
+ sodipodi:role="line"
+ x="212.59842"
+ y="357.87399"
+ id="tspan1439"
+ style="font-size:20px">Deformations of the sweep line when crossing a vertex box.</tspan></text>
+ <use
+ height="1052.3622"
+ width="744.09448"
+ transform="translate(751.18105,5.1777802e-6)"
+ id="use1457"
+ xlink:href="#path916"
+ y="0"
+ x="0" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ x="170.07874"
+ y="641.33856"
+ id="text1459"><tspan
+ sodipodi:role="line"
+ id="tspan1461"
+ x="170.07874"
+ y="641.33856"
+ style="font-size:20px">Why should tiles be kept in the context until the end of their last box.</tspan></text>
+ </g>
+</svg>
diff --git a/src/3rdparty/2geom/doc/tutorial.txt b/src/3rdparty/2geom/doc/tutorial.txt
new file mode 100644
index 0000000..9d0c81e
--- /dev/null
+++ b/src/3rdparty/2geom/doc/tutorial.txt
@@ -0,0 +1,291 @@
+(09:03:49) ACSpike: I tried to glean drawing a circle from conic-4 (I think) I'm either missing the drawing of the circle in the rest of the code, or it is just so short and simple that I don't get it
+(09:08:03) ACSpike: heh, oh "Define here various primatives, such as line, line segment, circle, bezier path etc."
+(09:18:29) njh: don't look at that
+(09:18:37) njh: that's done in a hacky way
+(09:19:09) njh: ok, lets plan what your program will do
+(09:19:23) njh: I'm thinking an 'on canvas' editor for gears
+(09:20:13) njh: the biggest problem is that you have lumpy parameters (for example number of teeth is a whole number)
+(09:20:54) ACSpike: lets start smaller
+(09:21:00) njh: ok
+(09:21:09) njh: howabout just drawing a circle
+(09:21:11) ACSpike: I need an entry point into the world of 2geom
+(09:21:31) ACSpike: can I get an svg path for a circle?
+(09:21:35) njh: well, what I was going to suggest was just making circles with handles
+(09:21:44) ACSpike: ie, no gtk gui stuff
+(09:21:47) njh: hehe, I still haven't done circles :)
+(09:21:52) njh: but you can use cairo
+(09:21:58) ACSpike: well
+(09:22:02) njh: cairo_arc
+(09:22:03) ACSpike: what can I get?
+(09:22:27) njh: lets make a program that just draws a single circle
+(09:23:00) ACSpike: ok. back in a bit
+(09:31:15) njh: ok
+(09:31:22) njh: I've committed a starting point for you
+(09:31:23) ACSpike: ok, I get it. 2geom doesn't do svg
+(09:31:29) ACSpike: it does beziers
+(09:31:37) ACSpike: and draws them on a cairo surface
+(09:32:27) njh: at this point, yeah
+(09:32:38) njh: actually, it doesn't even draw them :)
+(09:32:54) njh: that's done by path-cairo, which is demidetached :)
+(09:33:22) njh: so gear.cpp is a starting point for you
+(09:33:51) njh: one issue is that I haven't done elliptical arcs in Paths yet
+(09:34:04) njh: so we're going to not even use paths at this point
+(09:34:34) njh: just attempt to make a circle using sbasis rather than calling cairo_arc
+(09:35:03) verbalshadow [verbalshadow@gristle.org/Laptop] entered the room.
+(09:35:17) ACSpike: oy
+(09:35:19) njh: so a circle is parameterised by <cos(t), sin(t)> with t going form 0 to 2*pi
+(09:35:27) ACSpike: right
+(09:35:41) njh: does gear compile and run on your computer?
+(09:36:35) ACSpike: did you commit it?
+(09:39:27) njh: I spose I should add before commiting
+(09:39:37) njh: done
+(09:39:57) njh: ok, your second step will be to add two handles
+(09:48:04) njh: feel free to ask if you are stuck
+(09:48:50) ACSpike: oh, boy
+(09:49:04) ACSpike: so we have a handle for radius
+(09:50:01) Botty: the most elegant way to do this convex stuff would be to have a circular iterator
+(09:50:16) Botty: i suppose modulus works
+(09:51:32) njh: it does
+(09:51:55) njh: ACSpike: the longest journey starts with a single step
+(09:52:11) ACSpike: or a single grep
+(09:52:24) njh: I prefer emacs isearch
+(09:52:35) njh: so, does it compile?
+(09:52:39) ACSpike: ya
+(09:52:41) ACSpike: and runs
+(09:52:48) njh: and have yuo worked out how to add a handle
+(09:52:59) ACSpike: pushback
+(09:53:05) njh: yep
+(09:53:11) njh: just increase the loop
+(09:53:27) njh: generates random handles
+(09:53:51) njh: anyway, have you got two extra handles?
+(09:54:00) ACSpike: no
+(09:54:01) njh: please tell me when you have something working
+(09:54:16) ACSpike: I'm trying to grok the single handle
+(09:54:33) njh: just assume that handles can be moved anyway
+(09:54:40) njh: how they work is a bit fiddly
+(09:54:49) ACSpike: and raise kids :-)
+(09:54:51) njh: but all they are is a Geom::Point
+(09:57:54) njh: no
+(09:58:05) njh: how do I do that?
+(10:01:44) ACSpike: yes
+(10:05:04) ACSpike: norm ~ magnatude ~ distance?
+(10:06:07) njh: norms are like distance, yes
+(10:06:31) njh: but not just 'as the crow flies' distance
+(10:06:51) njh: another norm would be how long it takes you to get between places
+(10:07:17) njh: 2geom provides a few norms: L2 and Linfinity
+(10:07:28) njh: L2 = eucliean, as the crow flies distance
+(10:07:34) ACSpike: L1, L2 and infinity
+(10:07:47) ACSpike: l1 equals as the taxi drives
+(10:07:50) njh: Linfinity = maximum distance in x or y
+(10:07:56) njh: yeah l1 is taxi
+(10:08:07) Botty: (X+Y)
+(10:08:11) ACSpike: linfinity is x or y?
+(10:08:14) njh: no, |X| + |Y|
+(10:08:23) Botty: good point...
+(10:08:25) njh: Linfinity = max(|X|, |Y|)
+(10:08:30) ACSpike: right
+(10:08:34) ACSpike: interesting
+(10:08:40) ACSpike: thanks
+(12:02:59) ACSpike: what should I do with these two random handles?
+(12:03:19) ACSpike: pressure angle and number of teeth is what's needed
+(12:06:18) njh: lets start with a line
+(12:06:49) ACSpike: like constrain the movement of the handles?
+(12:06:52) njh: ok, SBasis functions map [0,1] to a value
+(12:06:57) njh: no, just darwing a line segment
+(12:07:20) ACSpike: each handle makes one endpoint?
+(12:07:21) njh: so we want to construct a function that maps [0,1] onto a line from handle 1 to handle 2
+(12:08:14) njh: do you have two new handles?
+(12:09:35) ACSpike: yes
+(12:09:59) njh: ok, so we're going to make a pair of sbasis functions, one for x, one for y
+(12:10:10) njh: to do this we need a multidim_sbasis<2>
+(12:10:18) njh: (one day I'll work out better names :)
+(12:10:28) ACSpike: which means, a second degree sbasis?
+(12:10:47) njh: multidim_sbasis<2> B;
+(12:10:56) ACSpike: this is global?
+(12:10:57) njh: it means a function which maps [0,1] onto a point
+(12:11:03) njh: no, put it in expose
+(12:11:07) njh: everything goes in expose
+(12:20:09) njh: anyway, so you have a function that maps [0,1] onto a point
+(12:20:08) ACSpike: I'm about to look for the definition of multidim_sbasis
+(12:20:15) njh: don't
+(12:20:23) njh: it's complicated and not necessary
+(12:20:27) ACSpike: ok
+(12:20:36) ACSpike: leaps with faith
+(12:21:21) njh: so we need to define what the functions are for X and Y
+(12:21:36) njh: just like a point, these are B[X] and B[Y]
+(12:21:47) ACSpike: ah
+(12:21:55) ACSpike: X and Y are defined somewhere?
+(12:22:00) njh: yeah, in point I think
+(12:22:06) njh: but I'm lazy and use 0 and 1
+(12:22:12) ACSpike: ah, good
+(12:23:33) njh: Now the simplest function maps [0,1] onto a constant value
+(12:23:53) njh: we could do this with B[0] = handles[1][0];
+(12:23:59) ACSpike: so all values between 0 and 1 are the same
+(12:24:03) njh: and similarly B[1] = handles[1][1];
+(12:24:07) njh: yep
+(12:24:11) njh: that would define a point
+(12:24:32) njh: (I'm not sure that would compile, due to missing code)
+(12:24:48) njh: I usually do everything in parallel like this:
+(12:24:55) njh: for(int im = 0; dim < 2; dim++)
+(12:25:04) njh: B[dim] = handles[1][dim];
+(12:25:25) njh: remember that handles[0] is the point on the gear we did already
+(12:25:51) njh: we're going to draw a line somewhere
+(12:25:57) njh: (you have to draw a line somewhere!)
+(12:26:27) njh: to do this we want to map [0,1] to points between handles[1] and handles[2]
+(12:27:06) njh: for technical(and not very good) reasons this means using BezOrds
+(12:27:11) ACSpike: pause for reflection
+(12:27:11) njh: like this:
+(12:27:30) njh: B[dim] = BezOrd(handles[1][dim], handles[2][dim]);
+(12:27:41) ACSpike: what are BezOrds?
+(12:27:50) njh: so try adding that code into expose
+(12:28:07) njh: BezOrd(a,b) maps 0,1 onto [a,b]
+(12:29:48) njh: the reason for BezOrds is they are the fundamental unit for all the maths
+(12:30:08) ACSpike: what does BezOrd mean though?
+(12:30:10) njh: just like points are the fundamental units for graphics
+(12:30:14) njh: Bezier Ordinal
+(12:30:16) ACSpike: I need to attach the idea to the name
+(12:30:27) njh: you can think of them as linear bezier segments
+(12:30:46) njh: add another poit and you have a quadratic, another, cubic
+(12:31:08) njh: a two point bezier is a line segment
+(12:31:13) Botty: so its like a parametric thing?
+(12:31:19) njh: Botty: correct
+(12:31:30) njh: parametric here means maps from [0,1] to a point
+(12:31:37) njh: <x(t), y(t)>
+(12:31:38) ACSpike: sbasis is all parametric vector squishyness
+(12:31:50) njh: yes, most computer graphics is parametric
+(12:31:59) ACSpike: and squishy
+(12:32:06) njh: sometimes
+(12:32:11) njh: sometimes it is all angular
+(12:39:28) ACSpike: do I need to draw the bezord out?
+(12:39:39) njh: draw it out?
+(12:39:41) njh: to the canvas?
+(12:40:08) njh: no, here is some boilerplate to draw a md_sb to the canvas
+(12:40:25) njh: void draw_cb(cairo_t *cr, multidim_sbasis<2> const &B) {
+ Geom::PathBuilder pb;
+ subpath_from_sbasis(pb, B, 0.1);
+ cairo_path(cr, pb.peek());
+}
+(12:40:37) njh: add that to gear
+(12:41:02) njh: perhaps change the name to draw_md_sb or something
+(12:41:11) njh: then to draw B, just use:
+(12:41:19) njh: draw_md_sb(cr, B);
+(12:41:26) njh: (cr is the cairo canvas)
+(12:41:38) njh: so paste what you have so far
+(12:41:50) njh: (I mean just your lines, not the whole file!)
+(12:46:12) ACSpike: random points are in the same spot on every execution?
+(12:46:31) njh: correct
+(12:46:36) ACSpike: neat
+(12:46:48) njh: that's just rand()
+(12:47:11) ACSpike: wow, the line. it moves.
+(12:47:16) njh: if you want different positions you start the random number generator in a different spot, using say the current time
+(12:47:28) njh: can you commit your changes?
+(12:49:09) ACSpike: yes
+(12:49:11) ACSpike: done
+(12:50:24) njh: ok, so we have a single line :)
+(12:50:35) ACSpike: and a single circle
+(12:50:46) njh: now the nice thing about lines in this form is we can perform arithmetic on them
+(12:50:46) ACSpike: but I don't know why we have a line
+(12:50:54) ACSpike: ok
+(12:52:14) njh: ok, so now you have some experience with lines, we're going to try to make an arc
+(12:52:30) njh: remember that a circle is just <cos, sin>
+(12:52:35) ACSpike: why would I perform arithmetic on a line?
+(12:52:51) njh: because all geometry is arithmetic
+(12:53:31) njh: so we're going to use two built in functions, sin and cos to make an arc from 0 to 1 radian
+(12:53:52) njh: SBasis sin(double a0, double a1, int k);
+SBasis cos(double a0, double a1, int k)
+(12:54:15) njh: these two functions take a range of angles (a0, a1) and a parameter k
+(12:54:23) njh: k is the accuracy
+(12:54:30) njh: for now lets just use k = 2
+(12:55:23) njh: so lets make B[0] = BezOrd(centre[0]) + 100*cos(0,1,2);
+(12:55:29) njh: and similarly Y
+(12:55:44) ***njh has never tried this before, it might not work :)
+(12:56:10) ACSpike: I realize you are taking really small really slow steps
+(12:56:21) ACSpike: but I'm loosing a lot of it
+(12:56:35) njh: that should make an arc centred at the centre with a radius 100
+(12:56:55) njh: perhaps we could convert this conversation into a tutorial when we're finished
+(12:57:01) ACSpike: do I replace the line?
+(12:57:06) njh: yeah
+(12:57:07) ACSpike: make a new arc?
+(12:57:09) ACSpike: ok
+(12:57:19) njh: just comment out the line if you like
+(12:57:25) njh: or you can overwrite it
+(12:58:02) ACSpike: compiling
+(13:00:05) ACSpike: http://rafb.net/paste/results/ZXudDC19.html
+(13:01:26) ACSpike: misplaced parens?
+(13:02:00) njh: no, missing defn
+(13:02:03) njh: try
+(13:02:16) njh: SBasis(BezOrd(centre[0])) + 100*cos(0,1,2);
+(13:02:40) njh: might be due to std::cos actually
+(13:02:48) njh: sin and cos are slightly crap
+(13:03:00) njh: ah, I've got an idea
+(13:05:37) njh: yep, looks like it will work
+(13:07:02) ACSpike: indeed it does
+(13:07:08) ACSpike: now I can draw arcs
+(13:07:29) ACSpike: ok
+(13:07:48) ACSpike: at this point I'm gonna copy the backlogs and go to bed
+(13:08:07) njh: ok!
+(13:08:09) njh: worked it out
+(13:08:21) ACSpike: worked what?
+(13:08:26) njh: I know all this sounds pedestrian
+(13:08:46) ACSpike: you mean this tutorial?
+(13:09:03) njh: but perhaps what you aren't realising is that when you write cos(0,1,2) you aren't just computing cos at a single point
+(13:09:10) ACSpike: right
+(13:09:12) njh: you are computing cos everywhere at the same time
+(13:09:16) ACSpike: it the whole sweep
+(13:09:19) njh: yep
+(13:09:23) ACSpike: I see that
+(13:09:31) ACSpike: but I don't "get" it at all :-)
+(13:09:38) njh: if you run conic-3 you'll see that it converts to beziers automagically
+(13:09:52) njh: well, do you understand how std::cos(t) works?
+(13:10:11) ACSpike: I don't even understand the question
+(13:10:31) njh: well, you wrote cos(x) in your gear program
+(13:10:36) njh: do you understand how it works?
+(13:10:38) ACSpike: my math is really rusty
+(13:10:46) njh: right, yet you managed to draw gears
+(13:11:02) njh: my point is that understanding how something works isn't entirely necessary to use it
+(13:11:05) ACSpike: I don't know the definition of the function, but I know the triangle soh cah toa thing
+(13:11:11) njh: yep
+(13:11:32) njh: I use floating point all the time. I know exactly how it works,because I once implemented my own version
+(13:11:41) njh: but 99.9999% of programmers don't
+(13:11:52) ACSpike: I read the spec once
+(13:11:53) njh: the same should be true of this new stuff
+(13:12:13) ACSpike: but I want to grok it because I want to help
+(13:12:19) njh: you should be able to make an involute without any more than a rough idea of how it works
+(13:12:29) Botty: I just remember that sin is Y (intuitively opposite), cos is X (intuitively adjacent), and tan is Y / X
+(13:12:32) njh: I think you will grok it, once you've got the hang of playing withit
+(13:12:49) njh: we'll get some nice circular arcs going
+(13:13:01) njh: maybe you can try and come up with a nice interface for circulat arcs
+(13:13:04) ACSpike: I think right now I could draw all the arcs from the gear
+(13:13:14) njh: yep, I think so too
+(13:13:26) njh: and you would get bezier curves at the end, rather than line segments
+(13:13:36) njh: and I think it would be a lot faster as well
+(13:13:40) ACSpike: right
+(13:13:44) njh: (actually, in this case, I doubt it metters :)
+(13:14:04) ACSpike: curveto or arcto?
+(13:14:19) njh: curveto, I'm afraid
+(13:14:31) njh: I would like to pick the best choice, but I haven't worked out how yet
+(13:14:56) ACSpike: so if I want to draw the involute I need to map that function in there somehow
+(13:15:04) njh: but you can't represent involutes with arcs anyway
+(13:15:07) njh: yeah
+(13:15:13) ACSpike: ah hah
+(13:15:15) njh: that is basically all there is to it
+(13:15:24) ACSpike: so this is crazy function plotting
+(13:15:38) njh: you should theoretically be able to just change the type of your equation to SBasis and use the old code
+(13:15:57) njh: the only reason you can't do that is because I haven't written all the operator*(,) type functions :)
+(13:16:19) njh: even more cool is you can compute the derivatives in the same way. that is something you simply can't do with point plotting
+(13:16:50) njh: for example, if you want the tangent to a bezier path, B, just write derivative(B)
+(13:17:10) njh: something I played with last night was trying to find the points of maximum and minimum curvature on paths
+(13:17:14) njh: ('corners')
+(13:17:29) njh: so I computed the curvature, took the derivative and found where that = 0
+(13:17:44) njh: SBasis curvature(multidim_sbasis<2> & B) {
+ multidim_sbasis<2> dB = derivative(B);
+ multidim_sbasis<2> ddB = derivative(dB);
+ SBasis n = multiply(dB[0], ddB[1]) - multiply(dB[1], ddB[0]);
+ SBasis den = multiply(dB[0], dB[0]) + multiply(dB[1], dB[1]);
+ den = multiply(den, den);
+ return divide(multiply(n, sqrt(den, 4)), den, 6);
+}
+
+(13:17:54) njh: that is pretty much the definition off wikipedia
+(13:18:16) njh: std::vector<double> r = roots(derivative(curvature(B)));
+(13:18:42) njh: gives r, a list of t values with maximum or minimum curvature
diff --git a/src/3rdparty/2geom/include/2geom/2geom.h b/src/3rdparty/2geom/include/2geom/2geom.h
new file mode 100644
index 0000000..7bf36ae
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/2geom.h
@@ -0,0 +1,75 @@
+/**
+ * \file
+ * \brief Include everything
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2011 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_2GEOM_H
+#define LIB2GEOM_SEEN_2GEOM_H
+
+#include <2geom/forward.h>
+
+// primitives
+#include <2geom/coord.h>
+#include <2geom/point.h>
+#include <2geom/interval.h>
+#include <2geom/rect.h>
+#include <2geom/angle.h>
+#include <2geom/ray.h>
+#include <2geom/line.h>
+#include <2geom/affine.h>
+#include <2geom/transforms.h>
+
+// curves and paths
+#include <2geom/curves.h>
+#include <2geom/path.h>
+#include <2geom/pathvector.h>
+
+// fragments
+#include <2geom/d2.h>
+#include <2geom/linear.h>
+#include <2geom/bezier.h>
+#include <2geom/sbasis.h>
+
+// others
+#include <2geom/math-utils.h>
+#include <2geom/utils.h>
+
+#endif // LIB2GEOM_SEEN_2GEOM_H
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/affine.h b/src/3rdparty/2geom/include/2geom/affine.h
new file mode 100644
index 0000000..470d5fc
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/affine.h
@@ -0,0 +1,244 @@
+/**
+ * \file
+ * \brief 3x3 affine transformation matrix.
+ *//*
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com> (Original NRAffine definition and related macros)
+ * Nathan Hurst <njh@mail.csse.monash.edu.au> (Geom::Affine class version of the above)
+ * Michael G. Sloan <mgsloan@gmail.com> (reorganization and additions)
+ * Krzysztof Kosiński <tweenk.pl@gmail.com> (removal of boilerplate, docs)
+ *
+ * This code is in public domain.
+ */
+
+#ifndef LIB2GEOM_SEEN_AFFINE_H
+#define LIB2GEOM_SEEN_AFFINE_H
+
+#include <boost/operators.hpp>
+#include <2geom/forward.h>
+#include <2geom/point.h>
+#include <2geom/utils.h>
+
+namespace Geom {
+
+/**
+ * @brief 3x3 matrix representing an affine transformation.
+ *
+ * Affine transformations on elements of a vector space are transformations which can be
+ * expressed in terms of matrix multiplication followed by addition
+ * (\f$x \mapsto A x + b\f$). They can be thought of as generalizations of linear functions
+ * (\f$y = a x + b\f$) to vector spaces. Affine transformations of points on a 2D plane preserve
+ * the following properties:
+ *
+ * - Colinearity: if three points lie on the same line, they will still be colinear after
+ * an affine transformation.
+ * - Ratios of distances between points on the same line are preserved
+ * - Parallel lines remain parallel.
+ *
+ * All affine transformations on 2D points can be written as combinations of scaling, rotation,
+ * shearing and translation. They can be represented as a combination of a vector and a 2x2 matrix,
+ * but this form is inconvenient to work with. A better solution is to represent all affine
+ * transformations on the 2D plane as 3x3 matrices, where the last column has fixed values.
+ * \f[ A = \left[ \begin{array}{ccc}
+ c_0 & c_1 & 0 \\
+ c_2 & c_3 & 0 \\
+ c_4 & c_5 & 1 \end{array} \right]\f]
+ *
+ * We then interpret points as row vectors of the form \f$[p_X, p_Y, 1]\f$. Applying a
+ * transformation to a point can be written as right-multiplication by a 3x3 matrix
+ * (\f$p' = pA\f$). This subset of matrices is closed under multiplication - combination
+ * of any two transforms can be expressed as the multiplication of their matrices.
+ * In this representation, the \f$c_4\f$ and \f$c_5\f$ coefficients represent
+ * the translation component of the transformation.
+ *
+ * Matrices can be multiplied by other more specific transformations. When multiplying,
+ * the transformations are applied from left to right, so for example <code>m = a * b</code>
+ * means: @a m first transforms by a, then by b.
+ *
+ * @ingroup Transforms
+ */
+class Affine
+ : boost::equality_comparable< Affine // generates operator!= from operator==
+ , boost::multipliable1< Affine
+ , MultipliableNoncommutative< Affine, Translate
+ , MultipliableNoncommutative< Affine, Scale
+ , MultipliableNoncommutative< Affine, Rotate
+ , MultipliableNoncommutative< Affine, HShear
+ , MultipliableNoncommutative< Affine, VShear
+ , MultipliableNoncommutative< Affine, Zoom
+ > > > > > > > >
+{
+ Coord _c[6];
+public:
+ Affine() {
+ _c[0] = _c[3] = 1;
+ _c[1] = _c[2] = _c[4] = _c[5] = 0;
+ }
+
+ /** @brief Create a matrix from its coefficient values.
+ * It's rather inconvenient to directly create matrices in this way. Use transform classes
+ * if your transformation has a geometric interpretation.
+ * @see Translate
+ * @see Scale
+ * @see Rotate
+ * @see HShear
+ * @see VShear
+ * @see Zoom */
+ Affine(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4, Coord c5) {
+ _c[0] = c0; _c[1] = c1;
+ _c[2] = c2; _c[3] = c3;
+ _c[4] = c4; _c[5] = c5;
+ }
+
+ /** @brief Access a coefficient by its index. */
+ inline Coord operator[](unsigned i) const { return _c[i]; }
+ inline Coord &operator[](unsigned i) { return _c[i]; }
+
+ /// @name Combine with other transformations
+ /// @{
+ Affine &operator*=(Affine const &m);
+ // implemented in transforms.cpp
+ Affine &operator*=(Translate const &t);
+ Affine &operator*=(Scale const &s);
+ Affine &operator*=(Rotate const &r);
+ Affine &operator*=(HShear const &h);
+ Affine &operator*=(VShear const &v);
+ Affine &operator*=(Zoom const &);
+ /// @}
+
+ bool operator==(Affine const &o) const {
+ for(unsigned i = 0; i < 6; ++i) {
+ if ( _c[i] != o._c[i] ) return false;
+ }
+ return true;
+ }
+
+ /// @name Get the parameters of the matrix's transform
+ /// @{
+ Point xAxis() const;
+ Point yAxis() const;
+ Point translation() const;
+ Coord expansionX() const;
+ Coord expansionY() const;
+ Point expansion() const { return Point(expansionX(), expansionY()); }
+ /// @}
+
+ /// @name Modify the matrix
+ /// @{
+ void setXAxis(Point const &vec);
+ void setYAxis(Point const &vec);
+
+ void setTranslation(Point const &loc);
+
+ void setExpansionX(Coord val);
+ void setExpansionY(Coord val);
+ void setIdentity();
+ /// @}
+
+ /// @name Inspect the matrix's transform
+ /// @{
+ bool isIdentity(Coord eps = EPSILON) const;
+
+ bool isTranslation(Coord eps = EPSILON) const;
+ bool isScale(Coord eps = EPSILON) const;
+ bool isUniformScale(Coord eps = EPSILON) const;
+ bool isRotation(Coord eps = EPSILON) const;
+ bool isHShear(Coord eps = EPSILON) const;
+ bool isVShear(Coord eps = EPSILON) const;
+
+ bool isNonzeroTranslation(Coord eps = EPSILON) const;
+ bool isNonzeroScale(Coord eps = EPSILON) const;
+ bool isNonzeroUniformScale(Coord eps = EPSILON) const;
+ bool isNonzeroRotation(Coord eps = EPSILON) const;
+ bool isNonzeroNonpureRotation(Coord eps = EPSILON) const;
+ Point rotationCenter() const;
+ bool isNonzeroHShear(Coord eps = EPSILON) const;
+ bool isNonzeroVShear(Coord eps = EPSILON) const;
+
+ bool isZoom(Coord eps = EPSILON) const;
+ bool preservesArea(Coord eps = EPSILON) const;
+ bool preservesAngles(Coord eps = EPSILON) const;
+ bool preservesDistances(Coord eps = EPSILON) const;
+ bool flips() const;
+
+ bool isSingular(Coord eps = EPSILON) const;
+ /// @}
+
+ /// @name Compute other matrices
+ /// @{
+ Affine withoutTranslation() const {
+ Affine ret(*this);
+ ret.setTranslation(Point(0,0));
+ return ret;
+ }
+ Affine inverse() const;
+ /// @}
+
+ /// @name Compute scalar values
+ /// @{
+ Coord det() const;
+ Coord descrim2() const;
+ Coord descrim() const;
+ /// @}
+ inline static Affine identity();
+};
+
+/** @brief Print out the Affine (for debugging).
+ * @relates Affine */
+inline std::ostream &operator<< (std::ostream &out_file, const Geom::Affine &m) {
+ out_file << "A: " << m[0] << " C: " << m[2] << " E: " << m[4] << "\n";
+ out_file << "B: " << m[1] << " D: " << m[3] << " F: " << m[5] << "\n";
+ return out_file;
+}
+
+// Affine factories
+Affine from_basis(const Point &x_basis, const Point &y_basis, const Point &offset=Point(0,0));
+Affine elliptic_quadratic_form(Affine const &m);
+
+/** Given a matrix (ignoring the translation) this returns the eigen
+ * values and vectors. */
+class Eigen{
+public:
+ Point vectors[2];
+ double values[2];
+ Eigen(Affine const &m);
+ Eigen(double M[2][2]);
+};
+
+/** @brief Create an identity matrix.
+ * This is a convenience function identical to Affine::identity(). */
+inline Affine identity() {
+ Affine ret(Affine::identity());
+ return ret; // allow NRVO
+}
+
+/** @brief Create an identity matrix.
+ * @return The matrix
+ * \f$\left[\begin{array}{ccc}
+ 1 & 0 & 0 \\
+ 0 & 1 & 0 \\
+ 0 & 0 & 1 \end{array}\right]\f$.
+ * @relates Affine */
+inline Affine Affine::identity() {
+ Affine ret(1.0, 0.0,
+ 0.0, 1.0,
+ 0.0, 0.0);
+ return ret; // allow NRVO
+}
+
+bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON);
+
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_AFFINE_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/angle.h b/src/3rdparty/2geom/include/2geom/angle.h
new file mode 100644
index 0000000..f0caaba
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/angle.h
@@ -0,0 +1,408 @@
+/**
+ * \file
+ * \brief Various trigoniometric helper functions
+ *//*
+ * Authors:
+ * Johan Engelen <goejendaagh@zonnet.nl>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2007-2010 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_ANGLE_H
+#define LIB2GEOM_SEEN_ANGLE_H
+
+#include <cmath>
+#include <boost/operators.hpp>
+#include <2geom/exception.h>
+#include <2geom/coord.h>
+#include <2geom/point.h>
+
+namespace Geom {
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+#ifndef M_1_2PI
+# define M_1_2PI 0.159154943091895335768883763373
+#endif
+
+/** @brief Wrapper for angular values.
+ *
+ * This class is a convenience wrapper that implements the behavior generally expected of angles,
+ * like addition modulo \f$2\pi\f$. The value returned from the default conversion
+ * to <tt>double</tt> is in the range \f$[-\pi, \pi)\f$ - the convention used by C's
+ * math library.
+ *
+ * This class holds only a single floating point value, so passing it by value will generally
+ * be faster than passing it by const reference.
+ *
+ * @ingroup Primitives
+ */
+class Angle
+ : boost::additive< Angle
+ , boost::additive< Angle, Coord
+ , boost::equality_comparable< Angle
+ , boost::equality_comparable< Angle, Coord
+ > > > >
+{
+public:
+ Angle() : _angle(0) {}
+ Angle(Coord v) : _angle(v) { _normalize(); } // this can be called implicitly
+ explicit Angle(Point const &p) : _angle(atan2(p)) { _normalize(); }
+ Angle(Point const &a, Point const &b) : _angle(angle_between(a, b)) { _normalize(); }
+ operator Coord() const { return radians(); }
+ Angle &operator+=(Angle o) {
+ _angle += o._angle;
+ _normalize();
+ return *this;
+ }
+ Angle &operator-=(Angle o) {
+ _angle -= o._angle;
+ _normalize();
+ return *this;
+ }
+ Angle &operator+=(Coord a) {
+ *this += Angle(a);
+ return *this;
+ }
+ Angle &operator-=(Coord a) {
+ *this -= Angle(a);
+ return *this;
+ }
+ bool operator==(Angle o) const {
+ return _angle == o._angle;
+ }
+ bool operator==(Coord c) const {
+ return _angle == Angle(c)._angle;
+ }
+
+ /** @brief Get the angle as radians.
+ * @return Number in range \f$[-\pi, \pi)\f$. */
+ Coord radians() const {
+ return _angle >= M_PI ? _angle - 2*M_PI : _angle;
+ }
+ /** @brief Get the angle as positive radians.
+ * @return Number in range \f$[0, 2\pi)\f$. */
+ Coord radians0() const {
+ return _angle;
+ }
+ /** @brief Get the angle as degrees in math convention.
+ * @return Number in range [-180, 180) obtained by scaling the result of radians()
+ * by \f$180/\pi\f$. */
+ Coord degrees() const { return radians() * (180.0 / M_PI); }
+ /** @brief Get the angle as degrees in clock convention.
+ * This method converts the angle to the "clock convention": angles start from the +Y axis
+ * and grow clockwise. This means that 0 corresponds to \f$\pi/2\f$ radians,
+ * 90 to 0 radians, 180 to \f$-\pi/2\f$ radians, and 270 to \f$\pi\f$ radians.
+ * @return A number in the range [0, 360).
+ */
+ Coord degreesClock() const {
+ Coord ret = 90.0 - _angle * (180.0 / M_PI);
+ if (ret < 0) ret += 360;
+ return ret;
+ }
+ /** @brief Create an angle from its measure in radians. */
+ static Angle from_radians(Coord d) {
+ Angle a(d);
+ return a;
+ }
+ /** @brief Create an angle from its measure in degrees. */
+ static Angle from_degrees(Coord d) {
+ Angle a(d * (M_PI / 180.0));
+ return a;
+ }
+ /** @brief Create an angle from its measure in degrees in clock convention.
+ * @see Angle::degreesClock() */
+ static Angle from_degrees_clock(Coord d) {
+ // first make sure d is in [0, 360)
+ d = std::fmod(d, 360.0);
+ if (d < 0) d += 360.0;
+ Coord rad = M_PI/2 - d * (M_PI / 180.0);
+ if (rad < 0) rad += 2*M_PI;
+ Angle a;
+ a._angle = rad;
+ return a;
+ }
+private:
+
+ void _normalize() {
+ _angle = std::fmod(_angle, 2*M_PI);
+ if (_angle < 0) _angle += 2*M_PI;
+ //_angle -= floor(_angle * (1.0/(2*M_PI))) * 2*M_PI;
+ }
+ Coord _angle; // this is always in [0, 2pi)
+ friend class AngleInterval;
+};
+
+inline Angle distance(Angle const &a, Angle const &b) {
+ // the distance cannot be larger than M_PI.
+ Coord ac = a.radians0();
+ Coord bc = b.radians0();
+ Coord d = fabs(ac - bc);
+ return Angle(d > M_PI ? 2*M_PI - d : d);
+}
+
+/** @brief Directed angular interval.
+ *
+ * Wrapper for directed angles with defined start and end values. Useful e.g. for representing
+ * the portion of an ellipse in an elliptical arc. Both extreme angles are contained
+ * in the interval (it is a closed interval). Angular intervals can also be interptered
+ * as functions \f$f: [0, 1] \to [-\pi, \pi)\f$, which return the start angle for 0,
+ * the end angle for 1, and interpolate linearly for other values. Note that such functions
+ * are not continuous if the interval crosses the angle \f$\pi\f$.
+ *
+ * This class can represent all directed angular intervals, including empty ones.
+ * However, not all possible intervals can be created with the constructors.
+ * For full control, use the setInitial(), setFinal() and setAngles() methods.
+ *
+ * @ingroup Primitives
+ */
+class AngleInterval
+ : boost::equality_comparable< AngleInterval >
+{
+public:
+ AngleInterval() {}
+ /** @brief Create an angular interval from two angles and direction.
+ * If the initial and final angle are the same, a degenerate interval
+ * (containing only one angle) will be created.
+ * @param s Starting angle
+ * @param e Ending angle
+ * @param cw Which direction the interval goes. True means that it goes
+ * in the direction of increasing angles, while false means in the direction
+ * of decreasing angles. */
+ AngleInterval(Angle s, Angle e, bool cw = false)
+ : _start_angle(s), _end_angle(e), _sweep(cw), _full(false)
+ {}
+ AngleInterval(double s, double e, bool cw = false)
+ : _start_angle(s), _end_angle(e), _sweep(cw), _full(false)
+ {}
+ /** @brief Create an angular interval from three angles.
+ * If the inner angle is exactly equal to initial or final angle,
+ * the sweep flag will be set to true, i.e. the interval will go
+ * in the direction of increasing angles.
+ *
+ * If the initial and final angle are the same, but the inner angle
+ * is different, a full angle in the direction of increasing angles
+ * will be created.
+ *
+ * @param s Initial angle
+ * @param inner Angle contained in the interval
+ * @param e Final angle */
+ AngleInterval(Angle s, Angle inner, Angle e)
+ : _start_angle(s)
+ , _end_angle(e)
+ , _sweep((inner-s).radians0() <= (e-s).radians0())
+ , _full(s == e && s != inner)
+ {
+ if (_full) {
+ _sweep = true;
+ }
+ }
+
+ /// Get the start angle.
+ Angle initialAngle() const { return _start_angle; }
+ /// Get the end angle.
+ Angle finalAngle() const { return _end_angle; }
+ /// Check whether the interval goes in the direction of increasing angles.
+ bool sweep() const { return _sweep; }
+ /// Check whether the interval contains only a single angle.
+ bool isDegenerate() const {
+ return _start_angle == _end_angle && !_full;
+ }
+ /// Check whether the interval contains all angles.
+ bool isFull() const {
+ return _start_angle == _end_angle && _full;
+ }
+
+ /** @brief Set the initial angle.
+ * @param a Angle to set
+ * @param prefer_full Whether to set a full angular interval when
+ * the initial angle is set to the final angle */
+ void setInitial(Angle a, bool prefer_full = false) {
+ _start_angle = a;
+ _full = prefer_full && a == _end_angle;
+ }
+
+ /** @brief Set the final angle.
+ * @param a Angle to set
+ * @param prefer_full Whether to set a full angular interval when
+ * the initial angle is set to the final angle */
+ void setFinal(Angle a, bool prefer_full = false) {
+ _end_angle = a;
+ _full = prefer_full && a == _start_angle;
+ }
+ /** @brief Set both angles at once.
+ * The direction (sweep flag) is left unchanged.
+ * @param s Initial angle
+ * @param e Final angle
+ * @param prefer_full Whether to set a full interval when the passed
+ * initial and final angle are the same */
+ void setAngles(Angle s, Angle e, bool prefer_full = false) {
+ _start_angle = s;
+ _end_angle = e;
+ _full = prefer_full && s == e;
+ }
+ /// Set whether the interval goes in the direction of increasing angles.
+ void setSweep(bool s) { _sweep = s; }
+
+ /// Reverse the direction of the interval while keeping contained values the same.
+ void reverse() {
+ using std::swap;
+ swap(_start_angle, _end_angle);
+ _sweep = !_sweep;
+ }
+ /// Get a new interval with reversed direction.
+ AngleInterval reversed() const {
+ AngleInterval result(*this);
+ result.reverse();
+ return result;
+ }
+
+ /// Get an angle corresponding to the specified time value.
+ Angle angleAt(Coord t) const {
+ Coord span = extent();
+ Angle ret = _start_angle.radians0() + span * (_sweep ? t : -t);
+ return ret;
+ }
+ Angle operator()(Coord t) const { return angleAt(t); }
+
+ /** @brief Compute a time value that would evaluate to the given angle.
+ * If the start and end angle are exactly the same, NaN will be returned.
+ * Negative values will be returned for angles between the initial angle
+ * and the angle exactly opposite the midpoint of the interval. */
+ Coord timeAtAngle(Angle a) const {
+ if (_full) {
+ Angle ta = _sweep ? a - _start_angle : _start_angle - a;
+ return ta.radians0() / (2*M_PI);
+ }
+ Coord ex = extent();
+ Coord outex = 2*M_PI - ex;
+ if (_sweep) {
+ Angle midout = _start_angle - outex / 2;
+ Angle acmp = a - midout, scmp = _start_angle - midout;
+ if (acmp.radians0() >= scmp.radians0()) {
+ return (a - _start_angle).radians0() / ex;
+ } else {
+ return -(_start_angle - a).radians0() / ex;
+ }
+ } else {
+ Angle midout = _start_angle + outex / 2;
+ Angle acmp = a - midout, scmp = _start_angle - midout;
+ if (acmp.radians0() <= scmp.radians0()) {
+ return (_start_angle - a).radians0() / ex;
+ } else {
+ return -(a - _start_angle).radians0() / ex;
+ }
+ }
+ }
+
+ /// Check whether the interval includes the given angle.
+ bool contains(Angle a) const {
+ if (_full) return true;
+ Coord s = _start_angle.radians0();
+ Coord e = _end_angle.radians0();
+ Coord x = a.radians0();
+ if (_sweep) {
+ if (s < e) return x >= s && x <= e;
+ return x >= s || x <= e;
+ } else {
+ if (s > e) return x <= s && x >= e;
+ return x <= s || x >= e;
+ }
+ }
+ /** @brief Extent of the angle interval.
+ * Equivalent to the absolute value of the sweep angle.
+ * @return Extent in range \f$[0, 2\pi)\f$. */
+ Coord extent() const {
+ if (_full) return 2*M_PI;
+ return _sweep
+ ? (_end_angle - _start_angle).radians0()
+ : (_start_angle - _end_angle).radians0();
+ }
+ /** @brief Get the sweep angle of the interval.
+ * This is the value you need to add to the initial angle to get the final angle.
+ * It is positive when sweep is true. Denoted as \f$\Delta\theta\f$ in the SVG
+ * elliptical arc implementation notes. */
+ Coord sweepAngle() const {
+ if (_full) return _sweep ? 2*M_PI : -2*M_PI;
+ Coord sa = _end_angle.radians0() - _start_angle.radians0();
+ if (_sweep && sa < 0) sa += 2*M_PI;
+ if (!_sweep && sa > 0) sa -= 2*M_PI;
+ return sa;
+ }
+
+ /// Check another interval for equality.
+ bool operator==(AngleInterval const &other) const {
+ if (_start_angle != other._start_angle) return false;
+ if (_end_angle != other._end_angle) return false;
+ if (_sweep != other._sweep) return false;
+ if (_full != other._full) return false;
+ return true;
+ }
+
+ static AngleInterval create_full(Angle start, bool sweep = true) {
+ AngleInterval result;
+ result._start_angle = result._end_angle = start;
+ result._sweep = sweep;
+ result._full = true;
+ return result;
+ }
+
+private:
+ Angle _start_angle;
+ Angle _end_angle;
+ bool _sweep;
+ bool _full;
+};
+
+/** @brief Given an angle in degrees, return radians
+ * @relates Angle */
+inline Coord rad_from_deg(Coord deg) { return deg*M_PI/180.0;}
+/** @brief Given an angle in radians, return degrees
+ * @relates Angle */
+inline Coord deg_from_rad(Coord rad) { return rad*180.0/M_PI;}
+
+} // end namespace Geom
+
+namespace std {
+template <> class iterator_traits<Geom::Angle> {};
+}
+
+#endif // LIB2GEOM_SEEN_ANGLE_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/basic-intersection.h b/src/3rdparty/2geom/include/2geom/basic-intersection.h
new file mode 100644
index 0000000..2d0c00d
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/basic-intersection.h
@@ -0,0 +1,151 @@
+/** @file
+ * @brief Basic intersection routines
+ *//*
+ * Authors:
+ * Nathan Hurst <njh@njhurst.com>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Jean-François Barraud <jf.barraud@gmail.com>
+ *
+ * Copyright 2008-2009 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_BASIC_INTERSECTION_H
+#define LIB2GEOM_SEEN_BASIC_INTERSECTION_H
+
+#include <2geom/point.h>
+#include <2geom/bezier.h>
+#include <2geom/sbasis.h>
+#include <2geom/d2.h>
+
+#include <vector>
+#include <utility>
+
+#define USE_RECURSIVE_INTERSECTOR 0
+
+
+namespace Geom {
+
+void find_intersections(std::vector<std::pair<double, double> > &xs,
+ D2<Bezier> const &A,
+ D2<Bezier> const &B,
+ double precision = EPSILON);
+
+void find_intersections(std::vector<std::pair<double, double> > &xs,
+ D2<SBasis> const &A,
+ D2<SBasis> const &B,
+ double precision = EPSILON);
+
+void find_intersections(std::vector< std::pair<double, double> > &xs,
+ std::vector<Point> const &A,
+ std::vector<Point> const &B,
+ double precision = EPSILON);
+
+void find_self_intersections(std::vector<std::pair<double, double> > &xs,
+ D2<SBasis> const &A,
+ double precision = EPSILON);
+
+void find_self_intersections(std::vector<std::pair<double, double> > &xs,
+ D2<Bezier> const &A,
+ double precision = EPSILON);
+
+/*
+ * find_intersection
+ *
+ * input: A, B - set of control points of two Bezier curve
+ * input: precision - required precision of computation
+ * output: xs - set of pairs of parameter values
+ * at which crossing happens
+ *
+ * This routine is based on the Bezier Clipping Algorithm,
+ * see: Sederberg, Nishita, 1990 - Curve intersection using Bezier clipping
+ */
+void find_intersections_bezier_clipping (std::vector< std::pair<double, double> > & xs,
+ std::vector<Point> const& A,
+ std::vector<Point> const& B,
+ double precision = EPSILON);
+//#endif
+
+void subdivide(D2<Bezier> const &a,
+ D2<Bezier> const &b,
+ std::vector< std::pair<double, double> > const &xs,
+ std::vector< D2<Bezier> > &av,
+ std::vector< D2<Bezier> > &bv);
+
+/*
+ * find_collinear_normal
+ *
+ * input: A, B - set of control points of two Bezier curve
+ * input: precision - required precision of computation
+ * output: xs - set of pairs of parameter values
+ * at which there are collinear normals
+ *
+ * This routine is based on the Bezier Clipping Algorithm,
+ * see: Sederberg, Nishita, 1990 - Curve intersection using Bezier clipping
+ */
+void find_collinear_normal (std::vector< std::pair<double, double> >& xs,
+ std::vector<Point> const& A,
+ std::vector<Point> const& B,
+ double precision = EPSILON);
+
+void polish_intersections(std::vector<std::pair<double, double> > &xs,
+ D2<SBasis> const &A,
+ D2<SBasis> const &B);
+
+
+/**
+ * Compute the Hausdorf distance from A to B only.
+ */
+double hausdorfl(D2<SBasis>& A, D2<SBasis> const &B,
+ double m_precision,
+ double *a_t=NULL, double *b_t=NULL);
+
+/**
+ * Compute the symmetric Hausdorf distance.
+ */
+double hausdorf(D2<SBasis> &A, D2<SBasis> const &B,
+ double m_precision,
+ double *a_t=NULL, double *b_t=NULL);
+
+/**
+ * Check if two line segments intersect. If they are collinear, the result is undefined.
+ * @return True if line segments AB and CD intersect
+ */
+bool non_collinear_segments_intersect(const Point &A, const Point &B, const Point &C, const Point &D);
+}
+
+#endif // !LIB2GEOM_SEEN_BASIC_INTERSECTION_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/bezier-curve.h b/src/3rdparty/2geom/include/2geom/bezier-curve.h
new file mode 100644
index 0000000..754c9cc
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/bezier-curve.h
@@ -0,0 +1,366 @@
+/**
+ * \file
+ * \brief Bezier curve
+ *//*
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2007-2011 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_BEZIER_CURVE_H
+#define LIB2GEOM_SEEN_BEZIER_CURVE_H
+
+#include <2geom/curve.h>
+#include <2geom/sbasis-curve.h> // for non-native winding method
+#include <2geom/bezier.h>
+#include <2geom/transforms.h>
+
+namespace Geom
+{
+
+class BezierCurve : public Curve {
+protected:
+ D2<Bezier> inner;
+ BezierCurve() {}
+ BezierCurve(Bezier const &x, Bezier const &y) : inner(x, y) {}
+ BezierCurve(std::vector<Point> const &pts);
+
+public:
+ explicit BezierCurve(D2<Bezier> const &b) : inner(b) {}
+
+ /// @name Access and modify control points
+ /// @{
+ /** @brief Get the order of the Bezier curve.
+ * A Bezier curve has order() + 1 control points. */
+ unsigned order() const { return inner[X].order(); }
+ /** @brief Get the number of control points. */
+ unsigned size() const { return inner[X].order() + 1; }
+ /** @brief Access control points of the curve.
+ * @param ix The (zero-based) index of the control point. Note that the caller is responsible for checking that this value is <= order().
+ * @return The control point. No-reference return, use setPoint() to modify control points. */
+ Point controlPoint(unsigned ix) const { return Point(inner[X][ix], inner[Y][ix]); }
+ Point operator[](unsigned ix) const { return Point(inner[X][ix], inner[Y][ix]); }
+ /** @brief Get the control points.
+ * @return Vector with order() + 1 control points. */
+ std::vector<Point> controlPoints() const { return bezier_points(inner); }
+ D2<Bezier> const &fragment() const { return inner; }
+
+ /** @brief Modify a control point.
+ * @param ix The zero-based index of the point to modify. Note that the caller is responsible for checking that this value is <= order().
+ * @param v The new value of the point */
+ void setPoint(unsigned ix, Point const &v) {
+ inner[X][ix] = v[X];
+ inner[Y][ix] = v[Y];
+ }
+ /** @brief Set new control points.
+ * @param ps Vector which must contain order() + 1 points.
+ * Note that the caller is responsible for checking the size of this vector.
+ * @throws LogicalError Thrown when the size of the vector does not match the order. */
+ virtual void setPoints(std::vector<Point> const &ps) {
+ // must be virtual, because HLineSegment will need to redefine it
+ if (ps.size() != order() + 1)
+ THROW_LOGICALERROR("BezierCurve::setPoints: incorrect number of points in vector");
+ for(unsigned i = 0; i <= order(); i++) {
+ setPoint(i, ps[i]);
+ }
+ }
+ /// @}
+
+ /// @name Construct a Bezier curve with runtime-determined order.
+ /// @{
+ /** @brief Construct a curve from a vector of control points.
+ * This will construct the appropriate specialization of BezierCurve (i.e. LineSegment,
+ * QuadraticBezier or Cubic Bezier) if the number of control points in the passed vector
+ * does not exceed 4. */
+ static BezierCurve *create(std::vector<Point> const &pts);
+ /// @}
+
+ // implementation of virtual methods goes here
+ Point initialPoint() const override { return inner.at0(); }
+ Point finalPoint() const override { return inner.at1(); }
+ bool isDegenerate() const override;
+ bool isLineSegment() const override;
+ void setInitial(Point const &v) override { setPoint(0, v); }
+ void setFinal(Point const &v) override { setPoint(order(), v); }
+ Rect boundsFast() const override { return *bounds_fast(inner); }
+ Rect boundsExact() const override { return *bounds_exact(inner); }
+ void expandToTransformed(Rect &bbox, Affine const &transform) const override;
+ OptRect boundsLocal(OptInterval const &i, unsigned deg) const override {
+ if (!i) return OptRect();
+ if(i->min() == 0 && i->max() == 1) return boundsFast();
+ if(deg == 0) return bounds_local(inner, i);
+ // TODO: UUUUUUGGGLLY
+ if(deg == 1 && order() > 1) return OptRect(bounds_local(Geom::derivative(inner[X]), i),
+ bounds_local(Geom::derivative(inner[Y]), i));
+ return OptRect();
+ }
+ Curve *duplicate() const override {
+ return new BezierCurve(*this);
+ }
+
+ Curve *portion(Coord f, Coord t) const override;
+
+ Curve *reverse() const override {
+ return new BezierCurve(Geom::reverse(inner));
+ }
+
+ using Curve::operator*=;
+ void operator*=(Translate const &tr) override {
+ for (unsigned i = 0; i < size(); ++i) {
+ inner[X][i] += tr[X];
+ inner[Y][i] += tr[Y];
+ }
+ }
+ void operator*=(Scale const &s) override {
+ for (unsigned i = 0; i < size(); ++i) {
+ inner[X][i] *= s[X];
+ inner[Y][i] *= s[Y];
+ }
+ }
+ void operator*=(Affine const &m) override {
+ for (unsigned i = 0; i < size(); ++i) {
+ setPoint(i, controlPoint(i) * m);
+ }
+ }
+
+ Curve *derivative() const override {
+ return new BezierCurve(Geom::derivative(inner[X]), Geom::derivative(inner[Y]));
+ }
+ int degreesOfFreedom() const override {
+ return 2 * (order() + 1);
+ }
+ std::vector<Coord> roots(Coord v, Dim2 d) const override {
+ return (inner[d] - v).roots();
+ }
+ Coord nearestTime(Point const &p, Coord from = 0, Coord to = 1) const override;
+ Coord length(Coord tolerance) const override;
+ std::vector<CurveIntersection> intersect(Curve const &other, Coord eps = EPSILON) const override;
+ Point pointAt(Coord t) const override { return inner.pointAt(t); }
+ std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const override {
+ return inner.valueAndDerivatives(t, n);
+ }
+ Coord valueAt(Coord t, Dim2 d) const override { return inner[d].valueAt(t); }
+ D2<SBasis> toSBasis() const override {return inner.toSBasis(); }
+ bool isNear(Curve const &c, Coord precision) const override;
+ bool operator==(Curve const &c) const override;
+ void feed(PathSink &sink, bool) const override;
+};
+
+template <unsigned degree>
+class BezierCurveN
+ : public BezierCurve
+{
+ template <unsigned required_degree>
+ static void assert_degree(BezierCurveN<required_degree> const *) {}
+
+public:
+ /// @name Construct Bezier curves
+ /// @{
+ /** @brief Construct a Bezier curve of the specified order with all points zero. */
+ BezierCurveN() {
+ inner = D2<Bezier>(Bezier(Bezier::Order(degree)), Bezier(Bezier::Order(degree)));
+ }
+
+ /** @brief Construct from 2D Bezier polynomial. */
+ explicit BezierCurveN(D2<Bezier > const &x) {
+ inner = x;
+ }
+
+ /** @brief Construct from two 1D Bezier polynomials of the same order. */
+ BezierCurveN(Bezier x, Bezier y) {
+ inner = D2<Bezier > (x,y);
+ }
+
+ /** @brief Construct a Bezier curve from a vector of its control points. */
+ BezierCurveN(std::vector<Point> const &points) {
+ unsigned ord = points.size() - 1;
+ if (ord != degree) THROW_LOGICALERROR("BezierCurve<degree> does not match number of points");
+ for (unsigned d = 0; d < 2; ++d) {
+ inner[d] = Bezier(Bezier::Order(ord));
+ for(unsigned i = 0; i <= ord; i++)
+ inner[d][i] = points[i][d];
+ }
+ }
+
+ /** @brief Construct a linear segment from its endpoints. */
+ BezierCurveN(Point c0, Point c1) {
+ assert_degree<1>(this);
+ for(unsigned d = 0; d < 2; d++)
+ inner[d] = Bezier(c0[d], c1[d]);
+ }
+
+ /** @brief Construct a quadratic Bezier curve from its control points. */
+ BezierCurveN(Point c0, Point c1, Point c2) {
+ assert_degree<2>(this);
+ for(unsigned d = 0; d < 2; d++)
+ inner[d] = Bezier(c0[d], c1[d], c2[d]);
+ }
+
+ /** @brief Construct a cubic Bezier curve from its control points. */
+ BezierCurveN(Point c0, Point c1, Point c2, Point c3) {
+ assert_degree<3>(this);
+ for(unsigned d = 0; d < 2; d++)
+ inner[d] = Bezier(c0[d], c1[d], c2[d], c3[d]);
+ }
+
+ // default copy
+ // default assign
+
+ /// @}
+
+ /** @brief Divide a Bezier curve into two curves
+ * @param t Time value
+ * @return Pair of Bezier curves \f$(\mathbf{D}, \mathbf{E})\f$ such that
+ * \f$\mathbf{D}[ [0,1] ] = \mathbf{C}[ [0,t] ]\f$ and
+ * \f$\mathbf{E}[ [0,1] ] = \mathbf{C}[ [t,1] ]\f$ */
+ std::pair<BezierCurveN, BezierCurveN> subdivide(Coord t) const {
+ std::pair<Bezier, Bezier> sx = inner[X].subdivide(t), sy = inner[Y].subdivide(t);
+ return std::make_pair(
+ BezierCurveN(sx.first, sy.first),
+ BezierCurveN(sx.second, sy.second));
+ }
+
+ bool isDegenerate() const override {
+ return BezierCurve::isDegenerate();
+ }
+
+ bool isLineSegment() const override {
+ if constexpr (degree == 1) {
+ return true;
+ } else {
+ return BezierCurve::isLineSegment();
+ }
+ }
+
+ Curve *duplicate() const override {
+ return new BezierCurveN(*this);
+ }
+ Curve *portion(Coord f, Coord t) const override {
+ if (degree == 1) {
+ return new BezierCurveN<1>(pointAt(f), pointAt(t));
+ } else {
+ return new BezierCurveN(Geom::portion(inner, f, t));
+ }
+ }
+ Curve *reverse() const override {
+ if (degree == 1) {
+ return new BezierCurveN<1>(finalPoint(), initialPoint());
+ } else {
+ return new BezierCurveN(Geom::reverse(inner));
+ }
+ }
+ Curve *derivative() const override;
+
+ Coord nearestTime(Point const &p, Coord from = 0, Coord to = 1) const override {
+ return BezierCurve::nearestTime(p, from, to);
+ }
+ std::vector<CurveIntersection> intersect(Curve const &other, Coord eps = EPSILON) const override {
+ // call super. this is implemented only to allow specializations
+ return BezierCurve::intersect(other, eps);
+ }
+ int winding(Point const &p) const override {
+ return Curve::winding(p);
+ }
+ void feed(PathSink &sink, bool moveto_initial) const override {
+ // call super. this is implemented only to allow specializations
+ BezierCurve::feed(sink, moveto_initial);
+ }
+ void expandToTransformed(Rect &bbox, Affine const &transform) const override {
+ // call super. this is implemented only to allow specializations
+ BezierCurve::expandToTransformed(bbox, transform);
+ }
+};
+
+// BezierCurveN<0> is meaningless; specialize it out
+template<> class BezierCurveN<0> : public BezierCurveN<1> { private: BezierCurveN();};
+
+/** @brief Line segment.
+ * Line segments are Bezier curves of order 1. They have only two control points,
+ * the starting point and the ending point.
+ * @ingroup Curves */
+typedef BezierCurveN<1> LineSegment;
+
+/** @brief Quadratic (order 2) Bezier curve.
+ * @ingroup Curves */
+typedef BezierCurveN<2> QuadraticBezier;
+
+/** @brief Cubic (order 3) Bezier curve.
+ * @ingroup Curves */
+typedef BezierCurveN<3> CubicBezier;
+
+template <unsigned degree>
+inline
+Curve *BezierCurveN<degree>::derivative() const {
+ return new BezierCurveN<degree-1>(Geom::derivative(inner[X]), Geom::derivative(inner[Y]));
+}
+
+// optimized specializations
+template <> inline bool BezierCurveN<1>::isDegenerate() const {
+ return inner[X][0] == inner[X][1] && inner[Y][0] == inner[Y][1];
+}
+template <> inline bool BezierCurveN<1>::isLineSegment() const { return true; }
+template <> Curve *BezierCurveN<1>::derivative() const;
+template <> Coord BezierCurveN<1>::nearestTime(Point const &, Coord, Coord) const;
+template <> std::vector<CurveIntersection> BezierCurveN<1>::intersect(Curve const &, Coord) const;
+template <> std::vector<CurveIntersection> BezierCurveN<2>::intersect(Curve const &, Coord) const;
+template <> std::vector<CurveIntersection> BezierCurveN<3>::intersect(Curve const &, Coord) const;
+template <> int BezierCurveN<1>::winding(Point const &) const;
+template <> void BezierCurveN<1>::feed(PathSink &sink, bool moveto_initial) const;
+template <> void BezierCurveN<2>::feed(PathSink &sink, bool moveto_initial) const;
+template <> void BezierCurveN<3>::feed(PathSink &sink, bool moveto_initial) const;
+template <> void BezierCurveN<1>::expandToTransformed(Rect &bbox, Affine const &transform) const;
+template <> void BezierCurveN<2>::expandToTransformed(Rect &bbox, Affine const &transform) const;
+template <> void BezierCurveN<3>::expandToTransformed(Rect &bbox, Affine const &transform) const;
+
+inline Point middle_point(LineSegment const& _segment) {
+ return ( _segment.initialPoint() + _segment.finalPoint() ) / 2;
+}
+
+inline Coord length(LineSegment const& seg) {
+ return distance(seg.initialPoint(), seg.finalPoint());
+}
+
+Coord bezier_length(std::vector<Point> const &points, Coord tolerance = 0.01);
+Coord bezier_length(Point p0, Point p1, Point p2, Coord tolerance = 0.01);
+Coord bezier_length(Point p0, Point p1, Point p2, Point p3, Coord tolerance = 0.01);
+
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_BEZIER_CURVE_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/bezier-to-sbasis.h b/src/3rdparty/2geom/include/2geom/bezier-to-sbasis.h
new file mode 100644
index 0000000..73c55d9
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/bezier-to-sbasis.h
@@ -0,0 +1,94 @@
+/**
+ * \file
+ * \brief Conversion between Bezier control points and SBasis curves
+ *//*
+ * Copyright 2006 Nathan Hurst <njh@mail.csse.monash.edu.au>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_BEZIER_TO_SBASIS_H
+#define LIB2GEOM_SEEN_BEZIER_TO_SBASIS_H
+
+#include <2geom/coord.h>
+#include <2geom/point.h>
+#include <2geom/d2.h>
+#include <2geom/sbasis-to-bezier.h>
+
+namespace Geom
+{
+
+#if 0
+inline SBasis bezier_to_sbasis(Coord const *handles, unsigned order) {
+ if(order == 0)
+ return Linear(handles[0]);
+ else if(order == 1)
+ return Linear(handles[0], handles[1]);
+ else
+ return multiply(Linear(1, 0), bezier_to_sbasis(handles, order-1)) +
+ multiply(Linear(0, 1), bezier_to_sbasis(handles+1, order-1));
+}
+
+
+template <typename T>
+inline D2<SBasis> handles_to_sbasis(T const &handles, unsigned order)
+{
+ double v[2][order+1];
+ for(unsigned i = 0; i <= order; i++)
+ for(unsigned j = 0; j < 2; j++)
+ v[j][i] = handles[i][j];
+ return D2<SBasis>(bezier_to_sbasis(v[0], order),
+ bezier_to_sbasis(v[1], order));
+}
+#endif
+
+
+template <typename T>
+inline
+D2<SBasis> handles_to_sbasis(T const& handles, unsigned order)
+{
+ D2<SBasis> sbc;
+ size_t sz = order + 1;
+ std::vector<Point> v;
+ v.reserve(sz);
+ for (size_t i = 0; i < sz; ++i)
+ v.push_back(handles[i]);
+ bezier_to_sbasis(sbc, v);
+ return sbc;
+}
+
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_BEZIER_TO_SBASIS_H
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/bezier-utils.h b/src/3rdparty/2geom/include/2geom/bezier-utils.h
new file mode 100644
index 0000000..3e56e6e
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/bezier-utils.h
@@ -0,0 +1,99 @@
+/**
+ * \file
+ * \brief Bezier fitting algorithms
+ *//*
+ * An Algorithm for Automatically Fitting Digitized Curves
+ * by Philip J. Schneider
+ * from "Graphics Gems", Academic Press, 1990
+ *
+ * Authors:
+ * Philip J. Schneider
+ * Lauris Kaplinski <lauris@ximian.com>
+ *
+ * Copyright (C) 1990 Philip J. Schneider
+ * Copyright (C) 2001 Lauris Kaplinski and Ximian, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_BEZIER_UTILS_H
+#define LIB2GEOM_SEEN_BEZIER_UTILS_H
+
+#include <2geom/point.h>
+
+namespace Geom {
+
+Point bezier_pt(unsigned degree, Point const V[], double t);
+
+int bezier_fit_cubic(Point bezier[], Point const data[], int len, double error);
+
+int bezier_fit_cubic_r(Point bezier[], Point const data[], int len, double error,
+ unsigned max_beziers);
+
+int bezier_fit_cubic_full(Point bezier[], int split_points[], Point const data[], int len,
+ Point const &tHat1, Point const &tHat2,
+ double error, unsigned max_beziers);
+
+Point darray_left_tangent(Point const d[], unsigned const len);
+Point darray_left_tangent(Point const d[], unsigned const len, double const tolerance_sq);
+Point darray_right_tangent(Point const d[], unsigned const length, double const tolerance_sq);
+
+template <typename iterator>
+static void
+cubic_bezier_poly_coeff(iterator b, Point *pc) {
+ double c[10] = {1,
+ -3, 3,
+ 3, -6, 3,
+ -1, 3, -3, 1};
+
+ int cp = 0;
+
+ for(int i = 0; i < 4; i++) {
+ pc[i] = Point(0,0);
+ ++b;
+ }
+ for(int i = 0; i < 4; i++) {
+ --b;
+ for(int j = 0; j <= i; j++) {
+ pc[3 - j] += c[cp]*(*b);
+ cp++;
+ }
+ }
+}
+
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_BEZIER_UTILS_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/bezier.h b/src/3rdparty/2geom/include/2geom/bezier.h
new file mode 100644
index 0000000..d65b3bd
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/bezier.h
@@ -0,0 +1,394 @@
+/**
+ * @file
+ * @brief Bernstein-Bezier polynomial
+ *//*
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * Michael Sloan <mgsloan@gmail.com>
+ * Nathan Hurst <njh@njhurst.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2007-2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_BEZIER_H
+#define LIB2GEOM_SEEN_BEZIER_H
+
+#include <algorithm>
+#include <valarray>
+#include <2geom/coord.h>
+#include <2geom/d2.h>
+#include <2geom/math-utils.h>
+
+namespace Geom {
+
+/** @brief Compute the value of a Bernstein-Bezier polynomial.
+ * This method uses a Horner-like fast evaluation scheme.
+ * @param t Time value
+ * @param c_ Pointer to coefficients
+ * @param n Degree of the polynomial (number of coefficients minus one) */
+template <typename T>
+inline T bernstein_value_at(double t, T const *c_, unsigned n) {
+ double u = 1.0 - t;
+ double bc = 1;
+ double tn = 1;
+ T tmp = c_[0]*u;
+ for(unsigned i=1; i<n; i++){
+ tn = tn*t;
+ bc = bc*(n-i+1)/i;
+ tmp = (tmp + tn*bc*c_[i])*u;
+ }
+ return (tmp + tn*t*c_[n]);
+}
+
+/** @brief Perform Casteljau subdivision of a Bezier polynomial.
+ * Given an array of coefficients and a time value, computes two new Bernstein-Bezier basis
+ * polynomials corresponding to the \f$[0, t]\f$ and \f$[t, 1]\f$ intervals of the original one.
+ * @param t Time value
+ * @param v Array of input coordinates
+ * @param left Output polynomial corresponding to \f$[0, t]\f$
+ * @param right Output polynomial corresponding to \f$[t, 1]\f$
+ * @param order Order of the input polynomial, equal to one less the number of coefficients
+ * @return Value of the polynomial at @a t */
+template <typename T>
+inline T casteljau_subdivision(double t, T const *v, T *left, T *right, unsigned order) {
+ // The Horner-like scheme gives very slightly different results, but we need
+ // the result of subdivision to match exactly with Bezier's valueAt function.
+ T val = bernstein_value_at(t, v, order);
+
+ if (!left && !right) {
+ return val;
+ }
+
+ if (!right) {
+ if (left != v) {
+ std::copy(v, v + order + 1, left);
+ }
+ for (std::size_t i = order; i > 0; --i) {
+ for (std::size_t j = i; j <= order; ++j) {
+ left[j] = lerp(t, left[j-1], left[j]);
+ }
+ }
+ left[order] = val;
+ return left[order];
+ }
+
+ if (right != v) {
+ std::copy(v, v + order + 1, right);
+ }
+ for (std::size_t i = 1; i <= order; ++i) {
+ if (left) {
+ left[i-1] = right[0];
+ }
+ for (std::size_t j = i; j > 0; --j) {
+ right[j-1] = lerp(t, right[j-1], right[j]);
+ }
+ }
+ right[0] = val;
+ if (left) {
+ left[order] = right[0];
+ }
+ return right[0];
+}
+
+/**
+ * @brief Polynomial in Bernstein-Bezier basis
+ * @ingroup Fragments
+ */
+class Bezier
+ : boost::arithmetic< Bezier, double
+ , boost::additive< Bezier
+ > >
+{
+private:
+ std::valarray<Coord> c_;
+
+ friend Bezier portion(const Bezier & a, Coord from, Coord to);
+ friend OptInterval bounds_fast(Bezier const & b);
+ friend Bezier derivative(const Bezier & a);
+ friend class Bernstein;
+
+ void
+ find_bezier_roots(std::vector<double> & solutions,
+ double l, double r) const;
+
+protected:
+ Bezier(Coord const c[], unsigned ord)
+ : c_(c, ord+1)
+ {}
+
+public:
+ unsigned order() const { return c_.size()-1;}
+ unsigned degree() const { return order(); }
+ unsigned size() const { return c_.size();}
+
+ Bezier() {}
+ Bezier(const Bezier& b) :c_(b.c_) {}
+ Bezier &operator=(Bezier const &other) {
+ if ( c_.size() != other.c_.size() ) {
+ c_.resize(other.c_.size());
+ }
+ c_ = other.c_;
+ return *this;
+ }
+
+ bool operator==(Bezier const &other) const
+ {
+ if (degree() != other.degree()) {
+ return false;
+ }
+
+ for (size_t i = 0; i < c_.size(); i++) {
+ if (c_[i] != other.c_[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool operator!=(Bezier const &other) const
+ {
+ return !(*this == other);
+ }
+
+ struct Order {
+ unsigned order;
+ explicit Order(Bezier const &b) : order(b.order()) {}
+ explicit Order(unsigned o) : order(o) {}
+ operator unsigned() const { return order; }
+ };
+
+ //Construct an arbitrary order bezier
+ Bezier(Order ord) : c_(0., ord.order+1) {
+ assert(ord.order == order());
+ }
+
+ /// @name Construct Bezier polynomials from their control points
+ /// @{
+ explicit Bezier(Coord c0) : c_(0., 1) {
+ c_[0] = c0;
+ }
+ Bezier(Coord c0, Coord c1) : c_(0., 2) {
+ c_[0] = c0; c_[1] = c1;
+ }
+ Bezier(Coord c0, Coord c1, Coord c2) : c_(0., 3) {
+ c_[0] = c0; c_[1] = c1; c_[2] = c2;
+ }
+ Bezier(Coord c0, Coord c1, Coord c2, Coord c3) : c_(0., 4) {
+ c_[0] = c0; c_[1] = c1; c_[2] = c2; c_[3] = c3;
+ }
+ Bezier(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4) : c_(0., 5) {
+ c_[0] = c0; c_[1] = c1; c_[2] = c2; c_[3] = c3; c_[4] = c4;
+ }
+ Bezier(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4,
+ Coord c5) : c_(0., 6) {
+ c_[0] = c0; c_[1] = c1; c_[2] = c2; c_[3] = c3; c_[4] = c4;
+ c_[5] = c5;
+ }
+ Bezier(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4,
+ Coord c5, Coord c6) : c_(0., 7) {
+ c_[0] = c0; c_[1] = c1; c_[2] = c2; c_[3] = c3; c_[4] = c4;
+ c_[5] = c5; c_[6] = c6;
+ }
+ Bezier(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4,
+ Coord c5, Coord c6, Coord c7) : c_(0., 8) {
+ c_[0] = c0; c_[1] = c1; c_[2] = c2; c_[3] = c3; c_[4] = c4;
+ c_[5] = c5; c_[6] = c6; c_[7] = c7;
+ }
+ Bezier(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4,
+ Coord c5, Coord c6, Coord c7, Coord c8) : c_(0., 9) {
+ c_[0] = c0; c_[1] = c1; c_[2] = c2; c_[3] = c3; c_[4] = c4;
+ c_[5] = c5; c_[6] = c6; c_[7] = c7; c_[8] = c8;
+ }
+ Bezier(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4,
+ Coord c5, Coord c6, Coord c7, Coord c8, Coord c9) : c_(0., 10) {
+ c_[0] = c0; c_[1] = c1; c_[2] = c2; c_[3] = c3; c_[4] = c4;
+ c_[5] = c5; c_[6] = c6; c_[7] = c7; c_[8] = c8; c_[9] = c9;
+ }
+
+ template <typename Iter>
+ Bezier(Iter first, Iter last) {
+ c_.resize(std::distance(first, last));
+ for (std::size_t i = 0; first != last; ++first, ++i) {
+ c_[i] = *first;
+ }
+ }
+ Bezier(std::vector<Coord> const &vec)
+ : c_(&vec[0], vec.size())
+ {}
+ /// @}
+
+ void resize (unsigned int n, Coord v = 0) {
+ c_.resize (n, v);
+ }
+ void clear() {
+ c_.resize(0);
+ }
+
+ //IMPL: FragmentConcept
+ typedef Coord output_type;
+ bool isZero(double eps=EPSILON) const {
+ for(unsigned i = 0; i <= order(); i++) {
+ if( ! are_near(c_[i], 0., eps) ) return false;
+ }
+ return true;
+ }
+ bool isConstant(double eps=EPSILON) const {
+ for(unsigned i = 1; i <= order(); i++) {
+ if( ! are_near(c_[i], c_[0], eps) ) return false;
+ }
+ return true;
+ }
+ bool isFinite() const {
+ for(unsigned i = 0; i <= order(); i++) {
+ if(!std::isfinite(c_[i])) return false;
+ }
+ return true;
+ }
+ Coord at0() const { return c_[0]; }
+ Coord &at0() { return c_[0]; }
+ Coord at1() const { return c_[order()]; }
+ Coord &at1() { return c_[order()]; }
+
+ Coord valueAt(double t) const {
+ return bernstein_value_at(t, &c_[0], order());
+ }
+ Coord operator()(double t) const { return valueAt(t); }
+
+ SBasis toSBasis() const;
+
+ Coord &operator[](unsigned ix) { return c_[ix]; }
+ Coord const &operator[](unsigned ix) const { return const_cast<std::valarray<Coord>&>(c_)[ix]; }
+
+ void setCoeff(unsigned ix, double val) { c_[ix] = val; }
+
+ // The size of the returned vector equals n_derivs+1.
+ std::vector<Coord> valueAndDerivatives(Coord t, unsigned n_derivs) const;
+
+ void subdivide(Coord t, Bezier *left, Bezier *right) const;
+ std::pair<Bezier, Bezier> subdivide(Coord t) const;
+
+ std::vector<Coord> roots() const;
+ std::vector<Coord> roots(Interval const &ivl) const;
+
+ Bezier forward_difference(unsigned k) const;
+ Bezier elevate_degree() const;
+ Bezier reduce_degree() const;
+ Bezier elevate_to_degree(unsigned newDegree) const;
+ Bezier deflate() const;
+
+ // basic arithmetic operators
+ Bezier &operator+=(double v) {
+ c_ += v;
+ return *this;
+ }
+ Bezier &operator-=(double v) {
+ c_ -= v;
+ return *this;
+ }
+ Bezier &operator*=(double v) {
+ c_ *= v;
+ return *this;
+ }
+ Bezier &operator/=(double v) {
+ c_ /= v;
+ return *this;
+ }
+ Bezier &operator+=(Bezier const &other);
+ Bezier &operator-=(Bezier const &other);
+
+ /// Unary minus
+ Bezier operator-() const
+ {
+ Bezier result;
+ result.c_ = -c_;
+ return result;
+ }
+};
+
+
+void bezier_to_sbasis (SBasis &sb, Bezier const &bz);
+
+Bezier operator*(Bezier const &f, Bezier const &g);
+inline Bezier multiply(Bezier const &f, Bezier const &g) {
+ Bezier result = f * g;
+ return result;
+}
+
+inline Bezier reverse(const Bezier & a) {
+ Bezier result = Bezier(Bezier::Order(a));
+ for(unsigned i = 0; i <= a.order(); i++)
+ result[i] = a[a.order() - i];
+ return result;
+}
+
+Bezier portion(const Bezier & a, double from, double to);
+
+// XXX Todo: how to handle differing orders
+inline std::vector<Point> bezier_points(const D2<Bezier > & a) {
+ std::vector<Point> result;
+ for(unsigned i = 0; i <= a[0].order(); i++) {
+ Point p;
+ for(unsigned d = 0; d < 2; d++) p[d] = a[d][i];
+ result.push_back(p);
+ }
+ return result;
+}
+
+Bezier derivative(Bezier const &a);
+Bezier integral(Bezier const &a);
+OptInterval bounds_fast(Bezier const &b);
+OptInterval bounds_exact(Bezier const &b);
+OptInterval bounds_local(Bezier const &b, OptInterval const &i);
+
+/// Expand an interval to the image of a Bézier-Bernstein polynomial, assuming it already contains the initial point x0.
+void bezier_expand_to_image(Interval &range, Coord x0, Coord x1, Coord x2);
+void bezier_expand_to_image(Interval &range, Coord x0, Coord x1, Coord x2, Coord x3);
+
+inline std::ostream &operator<< (std::ostream &os, const Bezier & b) {
+ os << "Bezier(";
+ for(unsigned i = 0; i < b.order(); i++) {
+ os << format_coord_nice(b[i]) << ", ";
+ }
+ os << format_coord_nice(b[b.order()]) << ")";
+ return os;
+}
+
+} // namespace Geom
+
+#endif // LIB2GEOM_SEEN_BEZIER_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/cairo-path-sink.h b/src/3rdparty/2geom/include/2geom/cairo-path-sink.h
new file mode 100644
index 0000000..3f7a044
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/cairo-path-sink.h
@@ -0,0 +1,91 @@
+/**
+ * @file
+ * @brief Path sink for Cairo contexts
+ *//*
+ * Copyright 2014 Krzysztof Kosiński
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_CAIRO_PATH_SINK_H
+#define LIB2GEOM_SEEN_CAIRO_PATH_SINK_H
+
+#ifdef HAVE_CAIRO
+
+#include <2geom/path-sink.h>
+#include <cairo.h>
+
+namespace Geom {
+
+
+/** @brief Output paths to a Cairo drawing context
+ *
+ * This class converts from 2Geom path representation to the Cairo representation.
+ * Use it to simplify visualizing the results of 2Geom operations with the Cairo library,
+ * for example:
+ * @code
+ * CairoPathSink sink(cr);
+ * sink.feed(pv);
+ * cairo_stroke(cr);
+ * @endcode
+ *
+ * Currently the flush method is a no-op, but this is not guaranteed
+ * to hold forever.
+ */
+class CairoPathSink
+ : public PathSink
+{
+public:
+ CairoPathSink(cairo_t *cr);
+
+ void moveTo(Point const &p) override;
+ void lineTo(Point const &p) override;
+ void curveTo(Point const &c0, Point const &c1, Point const &p) override;
+ void quadTo(Point const &c, Point const &p) override;
+ void arcTo(Coord rx, Coord ry, Coord angle,
+ bool large_arc, bool sweep, Point const &p) override;
+ void closePath() override;
+ void flush() override;
+
+private:
+ cairo_t *_cr;
+ Point _current_point;
+};
+
+}
+
+#endif
+
+#endif // !LIB2GEOM_SEEN_CAIRO_PATH_SINK_H
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/choose.h b/src/3rdparty/2geom/include/2geom/choose.h
new file mode 100644
index 0000000..106d04f
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/choose.h
@@ -0,0 +1,147 @@
+/**
+ * \file
+ * \brief Calculation of binomial cefficients
+ *//*
+ * Copyright 2006 Nathan Hurst <njh@mail.csse.monash.edu.au>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_CHOOSE_H
+#define LIB2GEOM_SEEN_CHOOSE_H
+
+#include <vector>
+
+namespace Geom {
+
+/**
+ * @brief Given a multiple of binomial(n, k), modify it to the same multiple of binomial(n + 1, k).
+ */
+template <typename T>
+constexpr void binomial_increment_n(T &b, int n, int k)
+{
+ b = b * (n + 1) / (n + 1 - k);
+}
+
+/**
+ * @brief Given a multiple of binomial(n, k), modify it to the same multiple of binomial(n - 1, k).
+ */
+template <typename T>
+constexpr void binomial_decrement_n(T &b, int n, int k)
+{
+ b = b * (n - k) / n;
+}
+
+/**
+ * @brief Given a multiple of binomial(n, k), modify it to the same multiple of binomial(n, k + 1).
+ */
+template <typename T>
+constexpr void binomial_increment_k(T &b, int n, int k)
+{
+ b = b * (n - k) / (k + 1);
+}
+
+/**
+ * @brief Given a multiple of binomial(n, k), modify it to the same multiple of binomial(n, k - 1).
+ */
+template <typename T>
+constexpr void binomial_decrement_k(T &b, int n, int k)
+{
+ b = b * k / (n + 1 - k);
+}
+
+/**
+ * @brief Calculate the (n, k)th binomial coefficient.
+ */
+template <typename T>
+constexpr T choose(unsigned n, unsigned k)
+{
+ if (k > n) {
+ return 0;
+ }
+ T b = 1;
+ int max = std::min(k, n - k);
+ for (int i = 0; i < max; i++) {
+ binomial_increment_k(b, n, i);
+ }
+ return b;
+}
+
+/**
+ * @brief Class for calculating and accessing a row of Pascal's triangle.
+ */
+template <typename ValueType>
+class BinomialCoefficient
+{
+public:
+ using value_type = ValueType;
+ using container_type = std::vector<value_type>;
+
+ BinomialCoefficient(unsigned int _n)
+ : n(_n)
+ {
+ coefficients.reserve(n / 2 + 1);
+ coefficients.emplace_back(1);
+ value_type b = 1;
+ for (int i = 0; i < n / 2; i++) {
+ binomial_increment_k(b, n, i);
+ coefficients.emplace_back(b);
+ }
+ }
+
+ unsigned int size() const
+ {
+ return degree() + 1;
+ }
+
+ unsigned int degree() const
+ {
+ return n;
+ }
+
+ value_type operator[](unsigned int k) const
+ {
+ return coefficients[std::min(k, n - k)];
+ }
+
+private:
+ int const n;
+ container_type coefficients;
+};
+
+} // namespace Geom
+
+#endif // LIB2GEOM_SEEN_CHOOSE_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/circle.h b/src/3rdparty/2geom/include/2geom/circle.h
new file mode 100644
index 0000000..a4d5f20
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/circle.h
@@ -0,0 +1,165 @@
+/** @file
+ * @brief Circle shape
+ *//*
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2008-2014 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_CIRCLE_H
+#define LIB2GEOM_SEEN_CIRCLE_H
+
+#include <2geom/forward.h>
+#include <2geom/intersection.h>
+#include <2geom/point.h>
+#include <2geom/rect.h>
+#include <2geom/transforms.h>
+
+namespace Geom {
+
+class EllipticalArc;
+
+/** @brief Set of all points at a fixed distance from the center
+ * @ingroup Shapes */
+class Circle
+ : boost::equality_comparable1< Circle
+ , MultipliableNoncommutative< Circle, Translate
+ , MultipliableNoncommutative< Circle, Rotate
+ , MultipliableNoncommutative< Circle, Zoom
+ > > > >
+{
+ Point _center;
+ Coord _radius;
+
+public:
+ Circle() {}
+ Circle(Coord cx, Coord cy, Coord r)
+ : _center(cx, cy), _radius(r)
+ {}
+ Circle(Point const &center, Coord r)
+ : _center(center), _radius(r)
+ {}
+
+ Circle(Coord A, Coord B, Coord C, Coord D) {
+ setCoefficients(A, B, C, D);
+ }
+
+ // Construct the unique circle passing through three points.
+ //Circle(Point const &a, Point const &b, Point const &c);
+
+ Point center() const { return _center; }
+ Coord center(Dim2 d) const { return _center[d]; }
+ Coord radius() const { return _radius; }
+ Coord area() const { return M_PI * _radius * _radius; }
+ bool isDegenerate() const { return _radius == 0; }
+
+ void setCenter(Point const &p) { _center = p; }
+ void setRadius(Coord c) { _radius = c; }
+
+ Rect boundsFast() const;
+ Rect boundsExact() const { return boundsFast(); }
+
+ Point initialPoint() const;
+ Point finalPoint() const { return initialPoint(); }
+ Point pointAt(Coord t) const;
+ Coord valueAt(Coord t, Dim2 d) const;
+ Coord timeAt(Point const &p) const;
+ Coord nearestTime(Point const &p) const;
+
+ bool contains(Point const &p) const { return distance(p, _center) <= _radius; }
+ bool contains(Rect const &other) const;
+ bool contains(Circle const &other) const;
+
+ bool intersects(Line const &l) const;
+ bool intersects(LineSegment const &l) const;
+ bool intersects(Circle const &other) const;
+
+ std::vector<ShapeIntersection> intersect(Line const &other) const;
+ std::vector<ShapeIntersection> intersect(LineSegment const &other) const;
+ std::vector<ShapeIntersection> intersect(Circle const &other) const;
+
+ // build a circle by its implicit equation:
+ // Ax^2 + Ay^2 + Bx + Cy + D = 0
+ void setCoefficients(Coord A, Coord B, Coord C, Coord D);
+ void coefficients(Coord &A, Coord &B, Coord &C, Coord &D) const;
+ std::vector<Coord> coefficients() const;
+
+ Zoom unitCircleTransform() const;
+ Zoom inverseUnitCircleTransform() const;
+
+ EllipticalArc *
+ arc(Point const& initial, Point const& inner, Point const& final) const;
+
+ D2<SBasis> toSBasis() const;
+
+ Circle &operator*=(Translate const &t) {
+ _center *= t;
+ return *this;
+ }
+ Circle &operator*=(Rotate const &) {
+ return *this;
+ }
+ Circle &operator*=(Zoom const &z) {
+ _center *= z;
+ _radius *= z.scale();
+ return *this;
+ }
+
+ bool operator==(Circle const &other) const;
+
+ /** @brief Fit the circle to the passed points using the least squares method.
+ * @param points Samples at the perimeter of the circle */
+ void fit(std::vector<Point> const &points);
+};
+
+bool are_near(Circle const &a, Circle const &b, Coord eps=EPSILON);
+
+std::ostream &operator<<(std::ostream &out, Circle const &c);
+
+template <>
+struct ShapeTraits<Circle> {
+ typedef Coord TimeType;
+ typedef Interval IntervalType;
+ typedef Ellipse AffineClosureType;
+ typedef Intersection<> IntersectionType;
+};
+
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_CIRCLE_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/concepts.h b/src/3rdparty/2geom/include/2geom/concepts.h
new file mode 100644
index 0000000..de76d0f
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/concepts.h
@@ -0,0 +1,209 @@
+/**
+ * \file
+ * \brief Template concepts used by 2Geom
+ *//*
+ * Copyright 2007 Michael Sloan <mgsloan@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, output to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_CONCEPTS_H
+#define LIB2GEOM_SEEN_CONCEPTS_H
+
+#include <2geom/sbasis.h>
+#include <2geom/interval.h>
+#include <2geom/point.h>
+#include <2geom/rect.h>
+#include <2geom/intersection.h>
+#include <vector>
+#include <boost/concept/assert.hpp>
+#include <2geom/forward.h>
+#include <2geom/transforms.h>
+
+namespace Geom {
+
+//forward decls
+template <typename T> struct ResultTraits;
+
+template <> struct ResultTraits<double> {
+ typedef OptInterval bounds_type;
+ typedef SBasis sb_type;
+};
+
+template <> struct ResultTraits<Point> {
+ typedef OptRect bounds_type;
+ typedef D2<SBasis> sb_type;
+};
+
+//A concept for one-dimensional functions defined on [0,1]
+template <typename T>
+struct FragmentConcept {
+ typedef typename T::output_type OutputType;
+ typedef typename ResultTraits<OutputType>::bounds_type BoundsType;
+ typedef typename ResultTraits<OutputType>::sb_type SbType;
+ T t;
+ double d;
+ OutputType o;
+ bool b;
+ BoundsType i;
+ Interval dom;
+ std::vector<OutputType> v;
+ unsigned u;
+ SbType sb;
+ void constraints() {
+ t = T(o);
+ b = t.isZero(d);
+ b = t.isConstant(d);
+ b = t.isFinite();
+ o = t.at0();
+ o = t.at1();
+ t.at0() = o;
+ t.at1() = o;
+ o = t.valueAt(d);
+ o = t(d);
+ v = t.valueAndDerivatives(d, u-1);
+ //Is a pure derivative (ignoring others) accessor ever much faster?
+ //u = number of values returned. first val is value.
+ sb = t.toSBasis();
+ t = reverse(t);
+ i = bounds_fast(t);
+ i = bounds_exact(t);
+ i = bounds_local(t, dom);
+ /*With portion, Interval makes some sense, but instead I'm opting for
+ doubles, for the following reasons:
+ A) This way a reversed portion may be specified
+ B) Performance might be a bit better for piecewise and such
+ C) Interval version provided below
+ */
+ t = portion(t, d, d);
+ }
+};
+
+template <typename T>
+struct ShapeConcept {
+ typedef typename ShapeTraits<T>::TimeType Time;
+ typedef typename ShapeTraits<T>::IntervalType Interval;
+ typedef typename ShapeTraits<T>::AffineClosureType AffineClosure;
+ typedef typename ShapeTraits<T>::IntersectionType Isect;
+
+ T shape, other;
+ Time t;
+ Point p;
+ AffineClosure ac;
+ Affine m;
+ Translate tr;
+ Coord c;
+ bool bool_;
+ std::vector<Isect> ivec;
+
+ void constraints() {
+ p = shape.pointAt(t);
+ c = shape.valueAt(t, X);
+ ivec = shape.intersect(other);
+ t = shape.nearestTime(p);
+ shape *= tr;
+ ac = shape;
+ ac *= m;
+ bool_ = (shape == shape);
+ bool_ = (shape != other);
+ bool_ = shape.isDegenerate();
+ //bool_ = are_near(shape, other, c);
+ }
+};
+
+template <typename T>
+inline T portion(const T& t, const Interval& i) { return portion(t, i.min(), i.max()); }
+
+template <typename T>
+struct EqualityComparableConcept {
+ T a, b;
+ bool bool_;
+ void constraints() {
+ bool_ = (a == b);
+ bool_ = (a != b);
+ }
+};
+
+template <typename T>
+struct NearConcept {
+ T a, b;
+ double tol;
+ bool res;
+ void constraints() {
+ res = are_near(a, b, tol);
+ }
+};
+
+template <typename T>
+struct OffsetableConcept {
+ T t;
+ typename T::output_type d;
+ void constraints() {
+ t = t + d; t += d;
+ t = t - d; t -= d;
+ }
+};
+
+template <typename T>
+struct ScalableConcept {
+ T t;
+ typename T::output_type d;
+ void constraints() {
+ t = -t;
+ t = t * d; t *= d;
+ t = t / d; t /= d;
+ }
+};
+
+template <typename T>
+struct AddableConcept {
+ T i, j;
+ void constraints() {
+ i += j; i = i + j;
+ i -= j; i = i - j;
+ }
+};
+
+template <typename T>
+struct MultiplicableConcept {
+ T i, j;
+ void constraints() {
+ i *= j; i = i * j;
+ }
+};
+
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_CONCEPTS_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/conic_section_clipper.h b/src/3rdparty/2geom/include/2geom/conic_section_clipper.h
new file mode 100644
index 0000000..38bba33
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/conic_section_clipper.h
@@ -0,0 +1,58 @@
+/** @file
+ * @brief Conic section clipping with respect to a rectangle
+ *//*
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail>
+ *
+ * Copyright 2009 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+
+
+#ifndef LIB2GEOM_SEEN_CONIC_SECTION_CLIPPER_H
+#define LIB2GEOM_SEEN_CONIC_SECTION_CLIPPER_H
+
+
+#undef CLIP_WITH_CAIRO_SUPPORT
+#include <2geom/conic_section_clipper_impl.h>
+
+
+#endif // _2GEOM_CONIC_SECTION_CLIPPER_H_
+
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/conic_section_clipper_cr.h b/src/3rdparty/2geom/include/2geom/conic_section_clipper_cr.h
new file mode 100644
index 0000000..6c62494
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/conic_section_clipper_cr.h
@@ -0,0 +1,64 @@
+/** @file
+ * @brief Conic section clipping with respect to a rectangle
+ *//*
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail>
+ *
+ * Copyright 2009 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// This header should be used for graphical debugging purpuse only. //
+////////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef LIB2GEOM_SEEN_CONIC_SECTION_CLIPPER_CR_H
+#define LIB2GEOM_SEEN_CONIC_SECTION_CLIPPER_CR_H
+
+
+#define CLIP_WITH_CAIRO_SUPPORT
+#include "conic_section_clipper_impl.h"
+#include "conic_section_clipper_impl.cpp"
+
+
+#endif // _2GEOM_CONIC_SECTION_CLIPPER_CR_H_
+
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/conic_section_clipper_impl.h b/src/3rdparty/2geom/include/2geom/conic_section_clipper_impl.h
new file mode 100644
index 0000000..ee67df1
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/conic_section_clipper_impl.h
@@ -0,0 +1,346 @@
+/** @file
+ * @brief Conic section clipping with respect to a rectangle
+ *//*
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail>
+ *
+ * Copyright 2009 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_CONIC_SECTION_CLIPPER_IMPL_H
+#define LIB2GEOM_SEEN_CONIC_SECTION_CLIPPER_IMPL_H
+
+
+#include <2geom/conicsec.h>
+#include <2geom/line.h>
+
+#include <list>
+#include <map>
+
+
+
+#ifdef CLIP_WITH_CAIRO_SUPPORT
+ #include <2geom/toys/path-cairo.h>
+ #define CLIPPER_CLASS clipper_cr
+#else
+ #define CLIPPER_CLASS clipper
+#endif
+
+//#define CLIPDBG
+
+#ifdef CLIPDBG
+#include <2geom/toys/path-cairo.h>
+#define DBGINFO(msg) \
+ std::cerr << msg << std::endl;
+#define DBGPRINT(msg, var) \
+ std::cerr << msg << var << std::endl;
+#define DBGPRINTIF(cond, msg, var) \
+ if (cond) \
+ std::cerr << msg << var << std::endl;
+
+#define DBGPRINT2(msg1, var1, msg2, var2) \
+ std::cerr << msg1 << var1 << msg2 << var2 << std::endl;
+
+#define DBGPRINTCOLL(msg, coll) \
+ if (coll.size() != 0) \
+ std::cerr << msg << ":\n"; \
+ for (size_t i = 0; i < coll.size(); ++i) \
+ { \
+ std::cerr << i << ": " << coll[i] << "\n"; \
+ }
+
+#else
+#define DBGINFO(msg)
+#define DBGPRINT(msg, var)
+#define DBGPRINTIF(cond, msg, var)
+#define DBGPRINT2(msg1, var1, msg2, var2)
+#define DBGPRINTCOLL(msg, coll)
+#endif
+
+
+
+
+namespace Geom
+{
+
+class CLIPPER_CLASS
+{
+
+ public:
+
+#ifdef CLIP_WITH_CAIRO_SUPPORT
+ clipper_cr (cairo_t* _cr, const xAx & _cs, const Rect & _R)
+ : cr(_cr), cs(_cs), R(_R)
+ {
+ DBGPRINT ("CLIP: right side: ", R.right())
+ DBGPRINT ("CLIP: top side: ", R.top())
+ DBGPRINT ("CLIP: left side: ", R.left())
+ DBGPRINT ("CLIP: bottom side: ", R.bottom())
+ }
+#else
+ clipper (const xAx & _cs, const Rect & _R)
+ : cs(_cs), R(_R)
+ {
+ }
+#endif
+
+ bool clip (std::vector<RatQuad> & arcs);
+
+ bool found_any_isolated_point() const
+ {
+ return ( !single_points.empty() );
+ }
+
+ const std::vector<Point> & isolated_points() const
+ {
+ return single_points;
+ }
+
+
+ private:
+ bool intersect (std::vector<Point> & crossing_points) const;
+
+ bool are_paired (Point & M, const Point & P1, const Point & P2) const;
+ void pairing (std::vector<Point> & paired_points,
+ std::vector<Point> & inner_points,
+ const std::vector<Point> & crossing_points);
+
+ Point find_inner_point_by_bisector_line (const Point & P,
+ const Point & Q) const;
+ Point find_inner_point (const Point & P, const Point & Q) const;
+
+ std::list<Point>::iterator split (std::list<Point> & points,
+ std::list<Point>::iterator sp,
+ std::list<Point>::iterator fp) const;
+ void rsplit (std::list<Point> & points,
+ std::list<Point>::iterator sp,
+ std::list<Point>::iterator fp,
+ size_t k) const;
+
+ void rsplit (std::list<Point> & points,
+ std::list<Point>::iterator sp,
+ std::list<Point>::iterator fp,
+ double length) const;
+
+ private:
+#ifdef CLIP_WITH_CAIRO_SUPPORT
+ cairo_t* cr;
+#endif
+ const xAx & cs;
+ const Rect & R;
+ std::vector<Point> single_points;
+};
+
+
+
+
+/*
+ * Given two point "P", "Q" on the conic section the method computes
+ * a third point inner to the arc with end-point "P", "Q".
+ * The new point is found by intersecting the conic with the bisector line
+ * of the PQ line segment.
+ */
+inline
+Point CLIPPER_CLASS::find_inner_point_by_bisector_line (const Point & P,
+ const Point & Q) const
+{
+ DBGPRINT ("CLIP: find_inner_point_by_bisector_line: P = ", P)
+ DBGPRINT ("CLIP: find_inner_point_by_bisector_line: Q = ", Q)
+ Line bl = make_bisector_line (LineSegment (P, Q));
+ std::vector<double> rts = cs.roots (bl);
+ //DBGPRINT ("CLIP: find_inner_point: rts.size = ", rts.size())
+ double t;
+ if (rts.size() == 0)
+ {
+ THROW_LOGICALERROR ("clipper::find_inner_point_by_bisector_line: "
+ "no conic-bisector line intersection point");
+ }
+ if (rts.size() == 2)
+ {
+ // we suppose that the searched point is the nearest
+ // to the line segment PQ
+ t = (std::fabs(rts[0]) < std::fabs(rts[1])) ? rts[0] : rts[1];
+ }
+ else
+ {
+ t = rts[0];
+ }
+ return bl.pointAt (t);
+}
+
+
+/*
+ * Given two point "P", "Q" on the conic section the method computes
+ * a third point inner to the arc with end-point "P", "Q".
+ * The new point is found by intersecting the conic with the line
+ * passing through the middle point of the PQ line segment and
+ * the intersection point of the tangent lines at points P and Q.
+ */
+inline
+Point CLIPPER_CLASS::find_inner_point (const Point & P, const Point & Q) const
+{
+
+ Line l1 = cs.tangent (P);
+ Line l2 = cs.tangent (Q);
+ Line l;
+ // in case we fail to find a crossing point we fall back to the bisector
+ // method
+ try
+ {
+ OptCrossing oc = intersection(l1, l2);
+ if (!oc)
+ {
+ return find_inner_point_by_bisector_line (P, Q);
+ }
+ l.setPoints (l1.pointAt (oc->ta), middle_point (P, Q));
+ }
+ catch (Geom::InfiniteSolutions const &e)
+ {
+ return find_inner_point_by_bisector_line (P, Q);
+ }
+
+ std::vector<double> rts = cs.roots (l);
+ double t;
+ if (rts.size() == 0)
+ {
+ return find_inner_point_by_bisector_line (P, Q);
+ }
+ // the line "l" origin is set to the tangent crossing point so in case
+ // we find two intersection points only the nearest belongs to the given arc
+ // pay attention: in case we are dealing with an hyperbola (remember that
+ // end points are on the same branch, because they are paired) the tangent
+ // crossing point belongs to the angle delimited by hyperbola asymptotes
+ // and containing the given hyperbola branch, so the previous statement is
+ // still true
+ if (rts.size() == 2)
+ {
+ t = (std::fabs(rts[0]) < std::fabs(rts[1])) ? rts[0] : rts[1];
+ }
+ else
+ {
+ t = rts[0];
+ }
+ return l.pointAt (t);
+}
+
+
+/*
+ * Given a list of points on the conic section, and given two consecutive
+ * points belonging to the list and passed by two list iterators, the method
+ * finds a new point that is inner to the conic arc which has the two passed
+ * points as initial and final point. This new point is inserted into the list
+ * between the two passed points and an iterator pointing to the new point
+ * is returned.
+ */
+inline
+std::list<Point>::iterator CLIPPER_CLASS::split (std::list<Point> & points,
+ std::list<Point>::iterator sp,
+ std::list<Point>::iterator fp) const
+{
+ Point new_point = find_inner_point (*sp, *fp);
+ std::list<Point>::iterator ip = points.insert (fp, new_point);
+ //std::cerr << "CLIP: split: [" << *sp << ", " << *ip << ", "
+ // << *fp << "]" << std::endl;
+ return ip;
+}
+
+
+/*
+ * Given a list of points on the conic section, and given two consecutive
+ * points belonging to the list and passed by two list iterators, the method
+ * recursively finds new points that are inner to the conic arc which has
+ * the two passed points as initial and final point. The recursion stop after
+ * "k" recursive calls. These new points are inserted into the list between
+ * the two passed points, and in the order we cross them going from
+ * the initial to the final arc point.
+ */
+inline
+void CLIPPER_CLASS::rsplit (std::list<Point> & points,
+ std::list<Point>::iterator sp,
+ std::list<Point>::iterator fp,
+ size_t k) const
+{
+ if (k == 0)
+ {
+ //DBGINFO("CLIP: split: no further split")
+ return;
+ }
+
+ std::list<Point>::iterator ip = split (points, sp, fp);
+ --k;
+ rsplit (points, sp, ip, k);
+ rsplit (points, ip, fp, k);
+}
+
+
+/*
+ * Given a list of points on the conic section, and given two consecutive
+ * points belonging to the list and passed by two list iterators, the method
+ * recursively finds new points that are inner to the conic arc which has
+ * the two passed points as initial and final point. The recursion stop when
+ * the max distance between the new computed inner point and the two passed
+ * arc end-points is less then the value specified by the "length" parameter.
+ * These new points are inserted into the list between the two passed points,
+ * and in the order we cross them going from the initial to the final arc point.
+ */
+inline
+void CLIPPER_CLASS::rsplit (std::list<Point> & points,
+ std::list<Point>::iterator sp,
+ std::list<Point>::iterator fp,
+ double length) const
+{
+ std::list<Point>::iterator ip = split (points, sp, fp);
+ double d1 = distance (*sp, *ip);
+ double d2 = distance (*ip, *fp);
+ double mdist = std::max (d1, d2);
+
+ if (mdist < length)
+ {
+ //DBGINFO("CLIP: split: no further split")
+ return;
+ }
+
+ // they have to be called both to keep the number of points in the list
+ // in the form 2k+1 where k are the sub-arcs the initial arc is split in.
+ rsplit (points, sp, ip, length);
+ rsplit (points, ip, fp, length);
+}
+
+
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_CONIC_SECTION_CLIPPER_IMPL_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/conicsec.h b/src/3rdparty/2geom/include/2geom/conicsec.h
new file mode 100644
index 0000000..bfd5f36
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/conicsec.h
@@ -0,0 +1,537 @@
+/** @file
+ * @brief Conic Section
+ *//*
+ * Authors:
+ * Nathan Hurst <njh@njhurst.com>
+ *
+ * Copyright 2009 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#ifndef LIB2GEOM_SEEN_CONICSEC_H
+#define LIB2GEOM_SEEN_CONICSEC_H
+
+#include <2geom/exception.h>
+#include <2geom/angle.h>
+#include <2geom/rect.h>
+#include <2geom/affine.h>
+#include <2geom/point.h>
+#include <2geom/line.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/numeric/linear_system.h>
+#include <2geom/numeric/symmetric-matrix-fs.h>
+#include <2geom/numeric/symmetric-matrix-fs-operation.h>
+
+#include <optional>
+
+#include <string>
+#include <vector>
+#include <ostream>
+
+
+
+
+namespace Geom
+{
+
+class RatQuad{
+ /**
+ * A curve of the form B02*A + B12*B*w + B22*C/(B02 + B12*w + B22)
+ * These curves can exactly represent a piece conic section less than a certain angle (find out)
+ *
+ **/
+
+public:
+ Point P[3];
+ double w;
+ RatQuad() {}
+ RatQuad(Point a, Point b, Point c, double w) : w(w) {
+ P[0] = a;
+ P[1] = b;
+ P[2] = c;
+ }
+ double lambda() const;
+
+ static RatQuad fromPointsTangents(Point P0, Point dP0,
+ Point P,
+ Point P2, Point dP2);
+ static RatQuad circularArc(Point P0, Point P1, Point P2);
+
+ CubicBezier toCubic() const;
+ CubicBezier toCubic(double lam) const;
+
+ Point pointAt(double t) const;
+ Point at0() const {return P[0];}
+ Point at1() const {return P[2];}
+
+ void split(RatQuad &a, RatQuad &b) const;
+
+ D2<SBasis> hermite() const;
+ std::vector<SBasis> homogeneous() const;
+};
+
+
+
+
+class xAx{
+public:
+ double c[6];
+
+ enum kind_t
+ {
+ PARABOLA,
+ CIRCLE,
+ REAL_ELLIPSE,
+ IMAGINARY_ELLIPSE,
+ RECTANGULAR_HYPERBOLA,
+ HYPERBOLA,
+ DOUBLE_LINE,
+ TWO_REAL_PARALLEL_LINES,
+ TWO_IMAGINARY_PARALLEL_LINES,
+ TWO_REAL_CROSSING_LINES,
+ TWO_IMAGINARY_CROSSING_LINES, // crossing at a real point
+ SINGLE_POINT = TWO_IMAGINARY_CROSSING_LINES,
+ UNKNOWN
+ };
+
+
+ xAx() {}
+
+ /*
+ * Define the conic section by its algebraic equation coefficients
+ *
+ * c0, .., c5: equation coefficients
+ */
+ xAx (double c0, double c1, double c2, double c3, double c4, double c5)
+ {
+ set (c0, c1, c2, c3, c4, c5);
+ }
+
+ /*
+ * Define a conic section by its related symmetric matrix
+ */
+ xAx (const NL::ConstSymmetricMatrixView<3> & C)
+ {
+ set(C);
+ }
+
+ /*
+ * Define a conic section by computing the one that fits better with
+ * N points.
+ *
+ * points: points to fit
+ *
+ * precondition: there must be at least 5 non-overlapping points
+ */
+ xAx (std::vector<Point> const& points)
+ {
+ set (points);
+ }
+
+ /*
+ * Define a section conic by providing the coordinates of one of its
+ * vertex,the major axis inclination angle and the coordinates of its foci
+ * with respect to the unidimensional system defined by the major axis with
+ * origin set at the provided vertex.
+ *
+ * _vertex : section conic vertex V
+ * _angle : section conic major axis angle
+ * _dist1: +/-distance btw V and nearest focus
+ * _dist2: +/-distance btw V and farest focus
+ *
+ * prerequisite: _dist1 <= _dist2
+ */
+ xAx (const Point& _vertex, double _angle, double _dist1, double _dist2)
+ {
+ set (_vertex, _angle, _dist1, _dist2);
+ }
+
+ /*
+ * Define a conic section by providing one of its vertex and its foci.
+ *
+ * _vertex: section conic vertex
+ * _focus1: section conic focus
+ * _focus2: section conic focus
+ */
+ xAx (const Point& _vertex, const Point& _focus1, const Point& _focus2)
+ {
+ set(_vertex, _focus1, _focus2);
+ }
+
+ /*
+ * Define a conic section by passing a focus, the related directrix,
+ * and the eccentricity (e)
+ * (e < 1 -> ellipse; e = 1 -> parabola; e > 1 -> hyperbola)
+ *
+ * _focus: a focus of the conic section
+ * _directrix: the directrix related to the given focus
+ * _eccentricity: the eccentricity parameter of the conic section
+ */
+ xAx (const Point & _focus, const Line & _directrix, double _eccentricity)
+ {
+ set (_focus, _directrix, _eccentricity);
+ }
+
+ /*
+ * Made up a degenerate conic section as a pair of lines
+ *
+ * l1, l2: lines that made up the conic section
+ */
+ xAx (const Line& l1, const Line& l2)
+ {
+ set (l1, l2);
+ }
+
+ /*
+ * Define the conic section by its algebraic equation coefficients
+ * c0, ..., c5: equation coefficients
+ */
+ void set (double c0, double c1, double c2, double c3, double c4, double c5)
+ {
+ c[0] = c0; c[1] = c1; c[2] = c2; // xx, xy, yy
+ c[3] = c3; c[4] = c4; // x, y
+ c[5] = c5; // 1
+ }
+
+ /*
+ * Define a conic section by its related symmetric matrix
+ */
+ void set (const NL::ConstSymmetricMatrixView<3> & C)
+ {
+ set(C(0,0), 2*C(1,0), C(1,1), 2*C(2,0), 2*C(2,1), C(2,2));
+ }
+
+ void set (std::vector<Point> const& points);
+
+ void set (const Point& _vertex, double _angle, double _dist1, double _dist2);
+
+ void set (const Point& _vertex, const Point& _focus1, const Point& _focus2);
+
+ void set (const Point & _focus, const Line & _directrix, double _eccentricity);
+
+ void set (const Line& l1, const Line& l2);
+
+
+ static xAx fromPoint(Point p);
+ static xAx fromDistPoint(Point p, double d);
+ static xAx fromLine(Point n, double d);
+ static xAx fromLine(Line l);
+ static xAx fromPoints(std::vector<Point> const &pts);
+
+
+ template<typename T>
+ T evaluate_at(T x, T y) const {
+ return c[0]*x*x + c[1]*x*y + c[2]*y*y + c[3]*x + c[4]*y + c[5];
+ }
+
+ double valueAt(Point P) const;
+
+ std::vector<double> implicit_form_coefficients() const {
+ return std::vector<double>(c, c+6);
+ }
+
+ template<typename T>
+ T evaluate_at(T x, T y, T w) const {
+ return c[0]*x*x + c[1]*x*y + c[2]*y*y + c[3]*x*w + c[4]*y*w + c[5]*w*w;
+ }
+
+ xAx scale(double sx, double sy) const;
+
+ Point gradient(Point p) const;
+
+ xAx operator-(xAx const &b) const;
+ xAx operator+(xAx const &b) const;
+ xAx operator+(double const &b) const;
+ xAx operator*(double const &b) const;
+
+ std::vector<Point> crossings(Rect r) const;
+ std::optional<RatQuad> toCurve(Rect const & bnd) const;
+ std::vector<double> roots(Point d, Point o) const;
+
+ std::vector<double> roots(Line const &l) const;
+
+ static Interval quad_ex(double a, double b, double c, Interval ivl);
+
+ Geom::Affine hessian() const;
+
+ std::optional<Point> bottom() const;
+
+ Interval extrema(Rect r) const;
+
+
+ /*
+ * Return the symmetric matrix related to the conic section.
+ * Modifying the matrix does not modify the conic section
+ */
+ NL::SymmetricMatrix<3> get_matrix() const
+ {
+ NL::SymmetricMatrix<3> C(c);
+ C(1,0) *= 0.5; C(2,0) *= 0.5; C(2,1) *= 0.5;
+ return C;
+ }
+
+ /*
+ * Return the i-th coefficient of the conic section algebraic equation
+ * Modifying the returned value does not modify the conic section coefficient
+ */
+ double coeff (size_t i) const
+ {
+ return c[i];
+ }
+
+ /*
+ * Return the i-th coefficient of the conic section algebraic equation
+ * Modifying the returned value modifies the conic section coefficient
+ */
+ double& coeff (size_t i)
+ {
+ return c[i];
+ }
+
+ kind_t kind () const;
+
+ std::string categorise() const;
+
+ /*
+ * Return true if the equation:
+ * c0*x^2 + c1*xy + c2*y^2 + c3*x + c4*y +c5 == 0
+ * really defines a conic, false otherwise
+ */
+ bool is_quadratic() const
+ {
+ return (coeff(0) != 0 || coeff(1) != 0 || coeff(2) != 0);
+ }
+
+ /*
+ * Return true if the conic is degenerate, i.e. if the related matrix
+ * determinant is null, false otherwise
+ */
+ bool isDegenerate() const
+ {
+ return (det_sgn (get_matrix()) == 0);
+ }
+
+ /*
+ * Compute the centre of symmetry of the conic section when it exists,
+ * else it return an uninitialized std::optional<Point> instance.
+ */
+ std::optional<Point> centre() const
+ {
+ typedef std::optional<Point> opt_point_t;
+
+ double d = coeff(1) * coeff(1) - 4 * coeff(0) * coeff(2);
+ if (are_near (d, 0)) return opt_point_t();
+ NL::Matrix Q(2, 2);
+ Q(0,0) = coeff(0);
+ Q(1,1) = coeff(2);
+ Q(0,1) = Q(1,0) = coeff(1) * 0.5;
+ NL::Vector T(2);
+ T[0] = - coeff(3) * 0.5;
+ T[1] = - coeff(4) * 0.5;
+
+ NL::LinearSystem ls (Q, T);
+ NL::Vector sol = ls.SV_solve();
+ Point C;
+ C[0] = sol[0];
+ C[1] = sol[1];
+
+ return opt_point_t(C);
+ }
+
+ double axis_angle() const;
+
+ void roots (std::vector<double>& sol, Coord v, Dim2 d) const;
+
+ xAx translate (const Point & _offset) const;
+
+ xAx rotate (double angle) const;
+
+ /*
+ * Rotate the conic section by the given angle wrt the provided point.
+ *
+ * _rot_centre: the rotation centre
+ * _angle: the rotation angle
+ */
+ xAx rotate (const Point & _rot_centre, double _angle) const
+ {
+ xAx result
+ = translate (-_rot_centre).rotate (_angle).translate (_rot_centre);
+ return result;
+ }
+
+ /*
+ * Compute the tangent line of the conic section at the provided point
+ *
+ * _point: the conic section point the tangent line pass through
+ */
+ Line tangent (const Point & _point) const
+ {
+ NL::Vector pp(3);
+ pp[0] = _point[0]; pp[1] = _point[1]; pp[2] = 1;
+ NL::SymmetricMatrix<3> C = get_matrix();
+ NL::Vector line = C * pp;
+ return Line(line[0], line[1], line[2]);
+ }
+
+ /*
+ * For a non degenerate conic compute the dual conic.
+ * TODO: investigate degenerate case
+ */
+ xAx dual () const
+ {
+ //assert (! isDegenerate());
+ NL::SymmetricMatrix<3> C = get_matrix();
+ NL::SymmetricMatrix<3> D = adj(C);
+ xAx dc(D);
+ return dc;
+ }
+
+ bool decompose (Line& l1, Line& l2) const;
+
+ /**
+ * @brief Division-free decomposition of a degenerate conic section, without
+ * degeneration test.
+ *
+ * When the conic is degenerate, it consists of 0, 1 or 2 lines in the xy-plane.
+ * This function returns these lines. But it does not check whether the conic
+ * is really degenerate, so calling it on a non-degenerate conic produces a
+ * meaningless result.
+ *
+ * If the number of lines is less than two, the trailing lines in the returned
+ * array will be degenerate. Use Line::isDegenerate() to test for that.
+ *
+ * This version of the decomposition is division-free, which improves numerical
+ * stability compared to decompose().
+ *
+ * @param epsilon The numerical threshold for floating point comparison of discriminants.
+ */
+ std::array<Line, 2> decompose_df(Coord epsilon = EPSILON) const;
+
+ /*
+ * Generate a RatQuad object from a conic arc.
+ *
+ * p0: the initial point of the arc
+ * p1: the inner point of the arc
+ * p2: the final point of the arc
+ */
+ RatQuad toRatQuad (const Point & p0,
+ const Point & p1,
+ const Point & p2) const
+ {
+ Point dp0 = gradient (p0);
+ Point dp2 = gradient (p2);
+ return
+ RatQuad::fromPointsTangents (p0, rot90 (dp0), p1, p2, rot90 (dp2));
+ }
+
+ /*
+ * Return the angle related to the normal gradient computed at the passed
+ * point.
+ *
+ * _point: the point at which computes the angle
+ *
+ * prerequisite: the passed point must lie on the conic
+ */
+ double angle_at (const Point & _point) const
+ {
+ double angle = atan2 (gradient (_point));
+ if (angle < 0) angle += (2*M_PI);
+ return angle;
+ }
+
+ /*
+ * Return true if the given point is contained in the conic arc determined
+ * by the passed points.
+ *
+ * _point: the point to be tested
+ * _initial: the initial point of the arc
+ * _inner: an inner point of the arc
+ * _final: the final point of the arc
+ *
+ * prerequisite: the passed points must lie on the conic, the inner point
+ * has to be strictly contained in the arc, except when the
+ * initial and final points are equal: in such a case if the
+ * inner point is also equal to them, then they define an arc
+ * made up by a single point.
+ *
+ */
+ bool arc_contains (const Point & _point, const Point & _initial,
+ const Point & _inner, const Point & _final) const
+ {
+ AngleInterval ai(angle_at(_initial), angle_at(_inner), angle_at(_final));
+ return ai.contains(angle_at(_point));
+ }
+
+ Rect arc_bound (const Point & P1, const Point & Q, const Point & P2) const;
+
+ std::vector<Point> allNearestTimes (const Point &P) const;
+
+ /*
+ * Return the point on the conic section nearest to the passed point "P".
+ *
+ * P: the point to compute the nearest one
+ */
+ Point nearestTime (const Point &P) const
+ {
+ std::vector<Point> points = allNearestTimes (P);
+ if ( !points.empty() )
+ {
+ return points.front();
+ }
+ // else
+ THROW_LOGICALERROR ("nearestTime: no nearest point found");
+ return Point();
+ }
+
+};
+
+std::vector<Point> intersect(const xAx & C1, const xAx & C2);
+
+bool clip (std::vector<RatQuad> & rq, const xAx & cs, const Rect & R);
+
+inline std::ostream &operator<< (std::ostream &out_file, const xAx &x) {
+ for(double i : x.c) {
+ out_file << i << ", ";
+ }
+ return out_file;
+}
+
+};
+
+
+#endif // LIB2GEOM_SEEN_CONICSEC_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+
diff --git a/src/3rdparty/2geom/include/2geom/convex-hull.h b/src/3rdparty/2geom/include/2geom/convex-hull.h
new file mode 100644
index 0000000..4dff9c2
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/convex-hull.h
@@ -0,0 +1,346 @@
+/** @file
+ * @brief Convex hull data structures
+ *//*
+ * Copyright 2006 Nathan Hurst <njh@mail.csse.monash.edu.au>
+ * Copyright 2006 Michael G. Sloan <mgsloan@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_CONVEX_HULL_H
+#define LIB2GEOM_SEEN_CONVEX_HULL_H
+
+#include <2geom/point.h>
+#include <2geom/rect.h>
+#include <vector>
+#include <algorithm>
+#include <boost/operators.hpp>
+#include <optional>
+#include <boost/range/iterator_range.hpp>
+
+namespace Geom {
+
+namespace {
+
+/** @brief Iterator for the lower convex hull.
+ * This iterator allows us to avoid duplicating any points in the hull
+ * boundary and still express most algorithms in a concise way. */
+class ConvexHullLowerIterator
+ : public boost::random_access_iterator_helper
+ < ConvexHullLowerIterator
+ , Point
+ , std::ptrdiff_t
+ , Point const *
+ , Point const &
+ >
+{
+public:
+ typedef ConvexHullLowerIterator Self;
+ ConvexHullLowerIterator()
+ : _data(NULL)
+ , _size(0)
+ , _x(0)
+ {}
+ ConvexHullLowerIterator(std::vector<Point> const &pts, std::size_t x)
+ : _data(&pts[0])
+ , _size(pts.size())
+ , _x(x)
+ {}
+
+ Self &operator++() {
+ *this += 1;
+ return *this;
+ }
+ Self &operator--() {
+ *this -= 1;
+ return *this;
+ }
+ Self &operator+=(std::ptrdiff_t d) {
+ _x += d;
+ return *this;
+ }
+ Self &operator-=(std::ptrdiff_t d) {
+ _x -= d;
+ return *this;
+ }
+ std::ptrdiff_t operator-(Self const &other) const {
+ return _x - other._x;
+ }
+ Point const &operator*() const {
+ if (_x < _size) {
+ return _data[_x];
+ } else {
+ return *_data;
+ }
+ }
+ bool operator==(Self const &other) const {
+ return _data == other._data && _x == other._x;
+ }
+ bool operator<(Self const &other) const {
+ return _data == other._data && _x < other._x;
+ }
+
+private:
+ Point const *_data;
+ std::size_t _size;
+ std::size_t _x;
+};
+
+} // end anonymous namespace
+
+/**
+ * @brief Convex hull based on the Andrew's monotone chain algorithm.
+ * @ingroup Shapes
+ */
+class ConvexHull {
+public:
+ typedef std::vector<Point>::const_iterator iterator;
+ typedef std::vector<Point>::const_iterator const_iterator;
+ typedef std::vector<Point>::const_iterator UpperIterator;
+ typedef ConvexHullLowerIterator LowerIterator;
+
+ /// @name Construct a convex hull.
+ /// @{
+
+ /// Create an empty convex hull.
+ ConvexHull() {}
+ /// Construct a singular convex hull.
+ explicit ConvexHull(Point const &a)
+ : _boundary(1, a)
+ , _lower(1)
+ {}
+ /// Construct a convex hull of two points.
+ ConvexHull(Point const &a, Point const &b);
+ /// Construct a convex hull of three points.
+ ConvexHull(Point const &a, Point const &b, Point const &c);
+ /// Construct a convex hull of four points.
+ ConvexHull(Point const &a, Point const &b, Point const &c, Point const &d);
+ /// Create a convex hull of a vector of points.
+ ConvexHull(std::vector<Point> const &pts);
+
+ /// Create a convex hull of a range of points.
+ template <typename Iter>
+ ConvexHull(Iter first, Iter last)
+ : _lower(0)
+ {
+ _prune(first, last, _boundary);
+ _construct();
+ }
+ /// @}
+
+ /// @name Inspect basic properties.
+ /// @{
+
+ /// Check for emptiness.
+ bool empty() const { return _boundary.empty(); }
+ /// Get the number of points in the hull.
+ size_t size() const { return _boundary.size(); }
+ /// Check whether the hull contains only one point.
+ bool isSingular() const { return _boundary.size() == 1; }
+ /// Check whether the hull is a line.
+ bool isLinear() const { return _boundary.size() == 2; }
+ /// Check whether the hull has zero area.
+ bool isDegenerate() const { return _boundary.size() < 3; }
+ /// Calculate the area of the convex hull.
+ double area() const;
+ //Point centroid() const;
+ //double areaAndCentroid(Point &c);
+ //FatLine maxDiameter() const;
+ //FatLine minDiameter() const;
+ /// @}
+
+ /// @name Inspect bounds and extreme points.
+ /// @{
+
+ /// Compute the bounding rectangle of the convex hull.
+ OptRect bounds() const;
+
+ /// Get the leftmost (minimum X) coordinate of the hull.
+ Coord left() const { return _boundary[0][X]; }
+ /// Get the rightmost (maximum X) coordinate of the hull.
+ Coord right() const { return _boundary[_lower-1][X]; }
+ /// Get the topmost (minimum Y) coordinate of the hull.
+ Coord top() const { return topPoint()[Y]; }
+ /// Get the bottommost (maximum Y) coordinate of the hull.
+ Coord bottom() const { return bottomPoint()[Y]; }
+
+ /// Get the leftmost (minimum X) point of the hull.
+ /// If the leftmost edge is vertical, the top point of the edge is returned.
+ Point leftPoint() const { return _boundary[0]; }
+ /// Get the rightmost (maximum X) point of the hull.
+ /// If the rightmost edge is vertical, the bottom point edge is returned.
+ Point rightPoint() const { return _boundary[_lower-1]; }
+ /// Get the topmost (minimum Y) point of the hull.
+ /// If the topmost edge is horizontal, the right point of the edge is returned.
+ Point topPoint() const;
+ /// Get the bottommost (maximum Y) point of the hull.
+ /// If the bottommost edge is horizontal, the left point of the edge is returned.
+ Point bottomPoint() const;
+ ///@}
+
+ /// @name Iterate over points.
+ /// @{
+ /** @brief Get the begin iterator to the points that form the hull.
+ * Points are returned beginning with the leftmost one, going along
+ * the upper (minimum Y) side, and then along the bottom.
+ * Thus the points are always ordered clockwise. No point is
+ * repeated. */
+ iterator begin() const { return _boundary.begin(); }
+ /// Get the end iterator to the points that form the hull.
+ iterator end() const { return _boundary.end(); }
+ /// Get the first, leftmost point in the hull.
+ Point const &front() const { return _boundary.front(); }
+ /// Get the penultimate point of the lower hull.
+ Point const &back() const { return _boundary.back(); }
+ Point const &operator[](std::size_t i) const {
+ return _boundary[i];
+ }
+
+ /** @brief Get an iterator range to the upper part of the hull.
+ * This returns a range that includes the leftmost point,
+ * all points of the upper hull, and the rightmost point. */
+ boost::iterator_range<UpperIterator> upperHull() const {
+ boost::iterator_range<UpperIterator> r(_boundary.begin(), _boundary.begin() + _lower);
+ return r;
+ }
+
+ /** @brief Get an iterator range to the lower part of the hull.
+ * This returns a range that includes the leftmost point,
+ * all points of the lower hull, and the rightmost point. */
+ boost::iterator_range<LowerIterator> lowerHull() const {
+ if (_boundary.empty()) {
+ boost::iterator_range<LowerIterator> r(LowerIterator(_boundary, 0),
+ LowerIterator(_boundary, 0));
+ return r;
+ }
+ if (_boundary.size() == 1) {
+ boost::iterator_range<LowerIterator> r(LowerIterator(_boundary, 0),
+ LowerIterator(_boundary, 1));
+ return r;
+ }
+ boost::iterator_range<LowerIterator> r(LowerIterator(_boundary, _lower - 1),
+ LowerIterator(_boundary, _boundary.size() + 1));
+ return r;
+ }
+ /// @}
+
+ /// @name Check for containment and intersection.
+ /// @{
+ /** @brief Check whether the given point is inside the hull.
+ * This takes logarithmic time. */
+ bool contains(Point const &p) const;
+ /** @brief Check whether the given axis-aligned rectangle is inside the hull.
+ * A rectangle is inside the hull if all of its corners are inside. */
+ bool contains(Rect const &r) const;
+ /// Check whether the given convex hull is completely contained in this one.
+ bool contains(ConvexHull const &other) const;
+ //bool interiorContains(Point const &p) const;
+ //bool interiorContains(Rect const &r) const;
+ //bool interiorContains(ConvexHull const &other) const;
+ //bool intersects(Rect const &r) const;
+ //bool intersects(ConvexHull const &other) const;
+
+ //ConvexHull &operator|=(ConvexHull const &other);
+ //ConvexHull &operator&=(ConvexHull const &other);
+ //ConvexHull &operator*=(Affine const &m);
+
+ //ConvexHull &expand(Point const &p);
+ //void unifyWith(ConvexHull const &other);
+ //void intersectWith(ConvexHull const &other);
+ /// @}
+
+ void swap(ConvexHull &other);
+ void swap(std::vector<Point> &pts);
+
+private:
+ void _construct();
+ static bool _is_clockwise_turn(Point const &a, Point const &b, Point const &c);
+
+ /// Take a vector of points and produce a pruned sorted vector.
+ template <typename Iter>
+ static void _prune(Iter first, Iter last, std::vector<Point> &out) {
+ std::optional<Point> ymin, ymax, xmin, xmax;
+ for (Iter i = first; i != last; ++i) {
+ Point p = *i;
+ if (!ymin || Point::LexLess<Y>()(p, *ymin)) {
+ ymin = p;
+ }
+ if (!xmin || Point::LexLess<X>()(p, *xmin)) {
+ xmin = p;
+ }
+ if (!ymax || Point::LexGreater<Y>()(p, *ymax)) {
+ ymax = p;
+ }
+ if (!xmax || Point::LexGreater<X>()(p, *xmax)) {
+ xmax = p;
+ }
+ }
+ if (!ymin) return;
+
+ ConvexHull qhull(*xmin, *xmax, *ymin, *ymax);
+ for (Iter i = first; i != last; ++i) {
+ if (qhull.contains(*i)) continue;
+ out.push_back(*i);
+ }
+
+ out.push_back(*xmin);
+ out.push_back(*xmax);
+ out.push_back(*ymin);
+ out.push_back(*ymax);
+ std::sort(out.begin(), out.end(), Point::LexLess<X>());
+ out.erase(std::unique(out.begin(), out.end()), out.end());
+ }
+
+ /// Sequence of points forming the convex hull polygon.
+ std::vector<Point> _boundary;
+ /// Index one past the rightmost point, where the lower part of the boundary starts.
+ std::size_t _lower;
+};
+
+/** @brief Output operator for convex hulls.
+ * Prints out all the coordinates. */
+inline std::ostream &operator<< (std::ostream &out_file, const Geom::ConvexHull &in_cvx) {
+ out_file << "ConvexHull(";
+ for(auto i : in_cvx) {
+ out_file << i << ", ";
+ }
+ out_file << ")";
+ return out_file;
+}
+
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_CONVEX_HULL_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/coord.h b/src/3rdparty/2geom/include/2geom/coord.h
new file mode 100644
index 0000000..40db84e
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/coord.h
@@ -0,0 +1,208 @@
+/** @file
+ * @brief Integral and real coordinate types and some basic utilities
+ *//*
+ * Authors:
+ * Nathan Hurst <njh@mail.csse.monash.edu.au>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ * Copyright 2006-2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_COORD_H
+#define LIB2GEOM_SEEN_COORD_H
+
+#include <cmath>
+#include <limits>
+#include <string>
+#include <functional>
+#include <boost/operators.hpp>
+#include <2geom/forward.h>
+
+namespace Geom {
+
+/** @brief 2D axis enumeration (X or Y).
+ * @ingroup Primitives */
+enum Dim2 { X=0, Y=1 };
+
+/** @brief Get the other (perpendicular) dimension.
+ * @ingroup Primitives */
+inline constexpr Dim2 other_dimension(Dim2 d) { return Dim2(int(d) ^ 1); }
+
+// TODO: make a smarter implementation with C++11
+template <typename T>
+struct D2Traits {
+ using D1Value = typename T::D1Value;
+ using D1Reference = typename T::D1Reference;
+ using D1ConstReference = typename T::D1ConstReference;
+};
+
+/** @brief Axis extraction functor.
+ * For use with things such as Boost's transform_iterator.
+ * @ingroup Utilities */
+template <Dim2 D, typename T>
+struct GetAxis {
+ using result_type = typename D2Traits<T>::D1Value;
+ using argument_type = T;
+ typename D2Traits<T>::D1Value operator()(T const &a) const {
+ return a[D];
+ }
+};
+
+/** @brief Floating point type used to store coordinates.
+ * @ingroup Primitives */
+using Coord = double;
+
+/** @brief Type used for integral coordinates.
+ * @ingroup Primitives */
+using IntCoord = int;
+
+/** @brief Default "acceptably small" value.
+ * @ingroup Primitives */
+constexpr Coord EPSILON = 1e-6;
+
+/** @brief Get a value representing infinity.
+ * @ingroup Primitives */
+inline constexpr Coord infinity() { return std::numeric_limits<Coord>::infinity(); }
+
+/** @brief Nearness predicate for values.
+ * @ingroup Primitives */
+inline constexpr bool are_near(Coord a, Coord b, double eps=EPSILON) { return std::abs(a-b) <= eps; }
+inline constexpr bool rel_error_bound(Coord a, Coord b, double eps=EPSILON) { return std::abs(a) <= eps*b; }
+
+/** @brief Numerically stable linear interpolation.
+ * @ingroup Primitives */
+inline constexpr Coord lerp(Coord t, Coord a, Coord b) {
+ return (1 - t) * a + t * b;
+}
+
+/** @brief Traits class used with coordinate types.
+ * Defines point, interval and rectangle types for the given coordinate type.
+ * @ingroup Utilities */
+template <typename C>
+struct CoordTraits {
+ using PointType = D2<C>;
+ using IntervalType = GenericInterval<C>;
+ using OptIntervalType = GenericOptInterval<C>;
+ using RectType = GenericRect<C>;
+ using OptRectType = GenericOptRect<C>;
+
+ using IntervalOps =
+ boost::equality_comparable< IntervalType
+ , boost::orable< IntervalType
+ >>;
+
+ using RectOps =
+ boost::equality_comparable< RectType
+ , boost::orable< RectType
+ , boost::orable< RectType, OptRectType
+ >>>;
+};
+
+// NOTE: operator helpers for Rect and Interval are defined here.
+// This is to avoid increasing their size through multiple inheritance.
+
+template<>
+struct CoordTraits<IntCoord> {
+ using PointType = IntPoint;
+ using IntervalType = IntInterval;
+ using OptIntervalType = OptIntInterval;
+ using RectType = IntRect;
+ using OptRectType = OptIntRect;
+
+ using IntervalOps =
+ boost::equality_comparable< IntInterval
+ , boost::additive< IntInterval
+ , boost::additive< IntInterval, IntCoord
+ , boost::orable< IntInterval
+ >>>>;
+
+ using RectOps =
+ boost::equality_comparable< IntRect
+ , boost::orable< IntRect
+ , boost::orable< IntRect, OptIntRect
+ , boost::additive< IntRect, IntPoint
+ >>>>;
+};
+
+template<>
+struct CoordTraits<Coord> {
+ using PointType = Point;
+ using IntervalType = Interval;
+ using OptIntervalType = OptInterval;
+ using RectType = Rect;
+ using OptRectType = OptRect;
+
+ using IntervalOps =
+ boost::equality_comparable< Interval
+ , boost::equality_comparable< Interval, IntInterval
+ , boost::additive< Interval
+ , boost::multipliable< Interval
+ , boost::orable< Interval
+ , boost::arithmetic< Interval, Coord
+ >>>>>>;
+
+ using RectOps =
+ boost::equality_comparable< Rect
+ , boost::equality_comparable< Rect, IntRect
+ , boost::orable< Rect
+ , boost::orable< Rect, OptRect
+ , boost::additive< Rect, Point
+ , boost::multipliable< Rect, Affine
+ >>>>>>;
+};
+
+/** @brief Convert coordinate to shortest possible string.
+ * @return The shortest string that parses back to the original value.
+ * @relates Coord */
+std::string format_coord_shortest(Coord x);
+
+/** @brief Convert coordinate to human-readable string.
+ * Unlike format_coord_shortest, this function will not omit a leading zero
+ * before a decimal point or use small negative exponents. The output format
+ * is similar to Javascript functions.
+ * @relates Coord */
+std::string format_coord_nice(Coord x);
+
+/** @brief Parse coordinate string.
+ * When using this function in conjunction with format_coord_shortest()
+ * or format_coord_nice(), the value is guaranteed to be preserved exactly.
+ * @relates Coord */
+Coord parse_coord(std::string const &s);
+
+} // namespace Geom
+
+#endif // LIB2GEOM_SEEN_COORD_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/crossing.h b/src/3rdparty/2geom/include/2geom/crossing.h
new file mode 100644
index 0000000..7ca273b
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/crossing.h
@@ -0,0 +1,213 @@
+/**
+ * @file
+ * @brief Structure representing the intersection of two curves
+ *//*
+ * Authors:
+ * Michael Sloan <mgsloan@gmail.com>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2006-2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_CROSSING_H
+#define LIB2GEOM_SEEN_CROSSING_H
+
+#include <vector>
+#include <2geom/rect.h>
+#include <2geom/sweep-bounds.h>
+#include <optional>
+#include <2geom/pathvector.h>
+
+namespace Geom {
+
+//Crossing between one or two paths
+struct Crossing {
+ bool dir; //True: along a, a becomes outside.
+ double ta, tb; //time on a and b of crossing
+ unsigned a, b; //storage of indices
+ Crossing() : dir(false), ta(0), tb(1), a(0), b(1) {}
+ Crossing(double t_a, double t_b, bool direction) : dir(direction), ta(t_a), tb(t_b), a(0), b(1) {}
+ Crossing(double t_a, double t_b, unsigned ai, unsigned bi, bool direction) : dir(direction), ta(t_a), tb(t_b), a(ai), b(bi) {}
+ bool operator==(const Crossing & other) const { return a == other.a && b == other.b && dir == other.dir && ta == other.ta && tb == other.tb; }
+ bool operator!=(const Crossing & other) const { return !(*this == other); }
+
+ unsigned getOther(unsigned cur) const { return a == cur ? b : a; }
+ double getTime(unsigned cur) const { return a == cur ? ta : tb; }
+ double getOtherTime(unsigned cur) const { return a == cur ? tb : ta; }
+ bool onIx(unsigned ix) const { return a == ix || b == ix; }
+};
+
+typedef std::optional<Crossing> OptCrossing;
+
+
+/*
+struct Edge {
+ unsigned node, path;
+ double time;
+ bool reverse;
+ Edge(unsigned p, double t, bool r) : path(p), time(t), reverse(r) {}
+ bool operator==(Edge const &other) const { return other.path == path && other.time == time && other.reverse == reverse; }
+};
+
+struct CrossingNode {
+ std::vector<Edge> edges;
+ CrossingNode() : edges(std::vector<Edge>()) {}
+ explicit CrossingNode(std::vector<Edge> es) : edges(es) {}
+ void add_edge(Edge const &e) {
+ if(std::find(edges.begin(), edges.end(), e) == edges.end())
+ edges.push_back(e);
+ }
+ double time_on(unsigned p) {
+ for(unsigned i = 0; i < edges.size(); i++)
+ if(edges[i].path == p) return edges[i].time;
+ std::cout << "CrossingNode time_on failed\n";
+ return 0;
+ }
+};
+
+
+typedef std::vector<CrossingNode> CrossingGraph;
+
+struct TimeOrder {
+ bool operator()(Edge a, Edge b) {
+ return a.time < b.time;
+ }
+};
+
+class Path;
+CrossingGraph create_crossing_graph(PathVector const &p, Crossings const &crs);
+*/
+
+/*inline bool are_near(Crossing a, Crossing b) {
+ return are_near(a.ta, b.ta) && are_near(a.tb, b.tb);
+}
+
+struct NearF { bool operator()(Crossing a, Crossing b) { return are_near(a, b); } };
+*/
+
+struct CrossingOrder {
+ unsigned ix;
+ bool rev;
+ CrossingOrder(unsigned i, bool r = false) : ix(i), rev(r) {}
+ bool operator()(Crossing a, Crossing b) {
+ if(rev)
+ return (ix == a.a ? a.ta : a.tb) <
+ (ix == b.a ? b.ta : b.tb);
+ else
+ return (ix == a.a ? a.ta : a.tb) >
+ (ix == b.a ? b.ta : b.tb);
+ }
+};
+
+typedef std::vector<Crossing> Crossings;
+
+typedef std::vector<Crossings> CrossingSet;
+
+template<typename C>
+std::vector<Rect> bounds(C const &a) {
+ std::vector<Rect> rs;
+ for (unsigned i = 0; i < a.size(); i++) {
+ OptRect bb = a[i].boundsFast();
+ if (bb) {
+ rs.push_back(*bb);
+ }
+ }
+ return rs;
+}
+// provide specific method for Paths because paths can be closed or open. Path::size() is named somewhat wrong...
+std::vector<Rect> bounds(Path const &a);
+
+inline void sort_crossings(Crossings &cr, unsigned ix) { std::sort(cr.begin(), cr.end(), CrossingOrder(ix)); }
+
+template <typename T>
+struct CrossingTraits {
+ typedef std::vector<T> VectorT;
+ static inline VectorT init(T const &x) { return VectorT(1, x); }
+};
+template <>
+struct CrossingTraits<Path> {
+ typedef PathVector VectorT;
+ static inline VectorT vector_one(Path const &x) { return VectorT(x); }
+};
+
+template<typename T>
+struct Crosser {
+ typedef typename CrossingTraits<T>::VectorT VectorT;
+ virtual ~Crosser() {}
+ virtual Crossings crossings(T const &a, T const &b) {
+ return crossings(CrossingTraits<T>::vector_one(a), CrossingTraits<T>::vector_one(b))[0]; }
+ virtual CrossingSet crossings(VectorT const &a, VectorT const &b) {
+ CrossingSet results(a.size() + b.size(), Crossings());
+
+ std::vector<std::vector<unsigned> > cull = sweep_bounds(bounds(a), bounds(b));
+ for(unsigned i = 0; i < cull.size(); i++) {
+ for(unsigned jx = 0; jx < cull[i].size(); jx++) {
+ unsigned j = cull[i][jx];
+ unsigned jc = j + a.size();
+ Crossings cr = crossings(a[i], b[j]);
+ for(auto & k : cr) { k.a = i; k.b = jc; }
+
+ //Sort & add A-sorted crossings
+ sort_crossings(cr, i);
+ Crossings n(results[i].size() + cr.size());
+ std::merge(results[i].begin(), results[i].end(), cr.begin(), cr.end(), n.begin(), CrossingOrder(i));
+ results[i] = n;
+
+ //Sort & add B-sorted crossings
+ sort_crossings(cr, jc);
+ n.resize(results[jc].size() + cr.size());
+ std::merge(results[jc].begin(), results[jc].end(), cr.begin(), cr.end(), n.begin(), CrossingOrder(jc));
+ results[jc] = n;
+ }
+ }
+ return results;
+ }
+};
+void merge_crossings(Crossings &a, Crossings &b, unsigned i);
+void offset_crossings(Crossings &cr, double a, double b);
+
+Crossings reverse_ta(Crossings const &cr, std::vector<double> max);
+Crossings reverse_tb(Crossings const &cr, unsigned split, std::vector<double> max);
+CrossingSet reverse_ta(CrossingSet const &cr, unsigned split, std::vector<double> max);
+CrossingSet reverse_tb(CrossingSet const &cr, unsigned split, std::vector<double> max);
+
+void clean(Crossings &cr_a, Crossings &cr_b);
+void delete_duplicates(Crossings &crs);
+
+} // end namespace Geom
+
+#endif
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/curve.h b/src/3rdparty/2geom/include/2geom/curve.h
new file mode 100644
index 0000000..9519144
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/curve.h
@@ -0,0 +1,375 @@
+/**
+ * \file
+ * \brief Abstract curve type
+ *
+ *//*
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2007-2009 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#ifndef LIB2GEOM_SEEN_CURVE_H
+#define LIB2GEOM_SEEN_CURVE_H
+
+#include <vector>
+#include <boost/operators.hpp>
+#include <2geom/coord.h>
+#include <2geom/point.h>
+#include <2geom/interval.h>
+#include <2geom/sbasis.h>
+#include <2geom/d2.h>
+#include <2geom/affine.h>
+#include <2geom/intersection.h>
+
+namespace Geom {
+
+class PathSink;
+typedef Intersection<> CurveIntersection;
+
+/**
+ * @brief Abstract continuous curve on a plane defined on [0,1].
+ *
+ * Formally, a curve in 2Geom is defined as a function
+ * \f$\mathbf{C}: [0, 1] \to \mathbb{R}^2\f$
+ * (a function that maps the unit interval to points on a 2D plane). Its image (the set of points
+ * the curve passes through) will be denoted \f$\mathcal{C} = \mathbf{C}[ [0, 1] ]\f$.
+ * All curve types available in 2Geom are continuous and differentiable on their
+ * interior, e.g. \f$(0, 1)\f$. Sometimes the curve's image (value set) is referred to as the curve
+ * itself for simplicity, but keep in mind that it's not strictly correct.
+ *
+ * It is common to think of the parameter as time. The curve can then be interpreted as
+ * describing the position of some moving object from time \f$t=0\f$ to \f$t=1\f$.
+ * Because of this, the parameter is frequently called the time value.
+ *
+ * Some methods return pointers to newly allocated curves. They are expected to be freed
+ * by the caller when no longer used. Default implementations are provided for some methods.
+ *
+ * @ingroup Curves
+ */
+class Curve
+ : boost::equality_comparable<Curve>
+{
+public:
+ virtual ~Curve() {}
+
+ /// @name Evaluate the curve
+ /// @{
+ /** @brief Retrieve the start of the curve.
+ * @return The point corresponding to \f$\mathbf{C}(0)\f$. */
+ virtual Point initialPoint() const = 0;
+
+ /** Retrieve the end of the curve.
+ * @return The point corresponding to \f$\mathbf{C}(1)\f$. */
+ virtual Point finalPoint() const = 0;
+
+ /** @brief Check whether the curve has exactly zero length.
+ * @return True if the curve's initial point is exactly the same as its final point, and it contains
+ * no other points (its value set contains only one element). */
+ virtual bool isDegenerate() const = 0;
+
+ /// Check whether the curve is a line segment.
+ virtual bool isLineSegment() const { return false; }
+
+ /** @brief Get the interval of allowed time values.
+ * @return \f$[0, 1]\f$ */
+ virtual Interval timeRange() const {
+ Interval tr(0, 1);
+ return tr;
+ }
+
+ /** @brief Evaluate the curve at a specified time value.
+ * @param t Time value
+ * @return \f$\mathbf{C}(t)\f$ */
+ virtual Point pointAt(Coord t) const { return pointAndDerivatives(t, 0).front(); }
+
+ /** @brief Evaluate one of the coordinates at the specified time value.
+ * @param t Time value
+ * @param d The dimension to evaluate
+ * @return The specified coordinate of \f$\mathbf{C}(t)\f$ */
+ virtual Coord valueAt(Coord t, Dim2 d) const { return pointAt(t)[d]; }
+
+ /** @brief Evaluate the function at the specified time value. Allows curves to be used
+ * as functors. */
+ virtual Point operator() (Coord t) const { return pointAt(t); }
+
+ /** @brief Evaluate the curve and its derivatives.
+ * This will return a vector that contains the value of the curve and the specified number
+ * of derivatives. However, the returned vector might contain less elements than specified
+ * if some derivatives do not exist.
+ * @param t Time value
+ * @param n The number of derivatives to compute
+ * @return Vector of at most \f$n+1\f$ elements of the form \f$[\mathbf{C}(t),
+ \mathbf{C}'(t), \mathbf{C}''(t), \ldots]\f$ */
+ virtual std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const = 0;
+ /// @}
+
+ /// @name Change the curve's endpoints
+ /// @{
+ /** @brief Change the starting point of the curve.
+ * After calling this method, it is guaranteed that \f$\mathbf{C}(0) = \mathbf{p}\f$,
+ * and the curve is still continuous. The precise new shape of the curve varies with curve
+ * type.
+ * @param p New starting point of the curve */
+ virtual void setInitial(Point const &v) = 0;
+
+ /** @brief Change the ending point of the curve.
+ * After calling this method, it is guaranteed that \f$\mathbf{C}(0) = \mathbf{p}\f$,
+ * and the curve is still continuous. The precise new shape of the curve varies
+ * with curve type.
+ * @param p New ending point of the curve */
+ virtual void setFinal(Point const &v) = 0;
+ /// @}
+
+ /// @name Compute the bounding box
+ /// @{
+ /** @brief Quickly compute the curve's approximate bounding box.
+ * The resulting rectangle is guaranteed to contain all points belonging to the curve,
+ * but it might not be the smallest such rectangle. This method is usually fast.
+ * @return A rectangle that contains all points belonging to the curve. */
+ virtual Rect boundsFast() const = 0;
+
+ /** @brief Compute the curve's exact bounding box.
+ * This method can be dramatically slower than boundsFast() depending on the curve type.
+ * @return The smallest possible rectangle containing all of the curve's points. */
+ virtual Rect boundsExact() const = 0;
+
+ /** @brief Expand the given rectangle to include the transformed curve,
+ * assuming it already contains its initial point.
+ * @param bbox[in,out] bbox The rectangle to expand; it is assumed to already contain (initialPoint() * transform).
+ * @param transform The transform to apply to the curve before taking its bounding box. */
+ virtual void expandToTransformed(Rect &bbox, Affine const &transform) const = 0;
+
+ // I have no idea what the 'deg' parameter is for, so this is undocumented for now.
+ virtual OptRect boundsLocal(OptInterval const &i, unsigned deg) const = 0;
+
+ /** @brief Compute the bounding box of a part of the curve.
+ * Since this method returns the smallest possible bounding rectangle of the specified portion,
+ * it can also be rather slow.
+ * @param a An interval specifying a part of the curve, or nothing.
+ * If \f$[0, 1] \subseteq a\f$, then the bounding box for the entire curve
+ * is calculated.
+ * @return The smallest possible rectangle containing all points in \f$\mathbf{C}[a]\f$,
+ * or nothing if the supplied interval is empty. */
+ OptRect boundsLocal(OptInterval const &a) const { return boundsLocal(a, 0); }
+ /// @}
+
+ /// @name Create new curves based on this one
+ /// @{
+ /** @brief Create an exact copy of this curve.
+ * @return Pointer to a newly allocated curve, identical to the original */
+ virtual Curve *duplicate() const = 0;
+
+ /** @brief Transform this curve by an affine transformation.
+ * Because of this method, all curve types must be closed under affine
+ * transformations.
+ * @param m Affine describing the affine transformation */
+ void transform(Affine const &m) {
+ *this *= m;
+ }
+
+ virtual void operator*=(Translate const &tr) { *this *= Affine(tr); }
+ virtual void operator*=(Scale const &s) { *this *= Affine(s); }
+ virtual void operator*=(Rotate const &r) { *this *= Affine(r); }
+ virtual void operator*=(HShear const &hs) { *this *= Affine(hs); }
+ virtual void operator*=(VShear const &vs) { *this *= Affine(vs); }
+ virtual void operator*=(Zoom const &z) { *this *= Affine(z); }
+ virtual void operator*=(Affine const &m) = 0;
+
+ /** @brief Create a curve transformed by an affine transformation.
+ * This method returns a new curve instead modifying the existing one.
+ * @param m Affine describing the affine transformation
+ * @return Pointer to a new, transformed curve */
+ virtual Curve *transformed(Affine const &m) const {
+ Curve *ret = duplicate();
+ ret->transform(m);
+ return ret;
+ }
+
+ /** @brief Create a curve that corresponds to a part of this curve.
+ * For \f$a > b\f$, the returned portion will be reversed with respect to the original.
+ * The returned curve will always be of the same type.
+ * @param a Beginning of the interval specifying the portion of the curve
+ * @param b End of the interval
+ * @return New curve \f$\mathbf{D}\f$ such that:
+ * - \f$\mathbf{D}(0) = \mathbf{C}(a)\f$
+ * - \f$\mathbf{D}(1) = \mathbf{C}(b)\f$
+ * - \f$\mathbf{D}[ [0, 1] ] = \mathbf{C}[ [a?b] ]\f$,
+ * where \f$[a?b] = [\min(a, b), \max(a, b)]\f$ */
+ virtual Curve *portion(Coord a, Coord b) const = 0;
+
+ /** @brief A version of that accepts an Interval. */
+ Curve *portion(Interval const &i) const { return portion(i.min(), i.max()); }
+
+ /** @brief Create a reversed version of this curve.
+ * The result corresponds to <code>portion(1, 0)</code>, but this method might be faster.
+ * @return Pointer to a new curve \f$\mathbf{D}\f$ such that
+ * \f$\forall_{x \in [0, 1]} \mathbf{D}(x) = \mathbf{C}(1-x)\f$ */
+ virtual Curve *reverse() const { return portion(1, 0); }
+
+ /** @brief Create a derivative of this curve.
+ * It's best to think of the derivative in physical terms: if the curve describes
+ * the position of some object on the plane from time \f$t=0\f$ to \f$t=1\f$ as said in the
+ * introduction, then the curve's derivative describes that object's speed at the same times.
+ * The second derivative refers to its acceleration, the third to jerk, etc.
+ * @return New curve \f$\mathbf{D} = \mathbf{C}'\f$. */
+ virtual Curve *derivative() const = 0;
+ /// @}
+
+ /// @name Advanced operations
+ /// @{
+ /** @brief Compute a time value at which the curve comes closest to a specified point.
+ * The first value with the smallest distance is returned if there are multiple such points.
+ * @param p Query point
+ * @param a Minimum time value to consider
+ * @param b Maximum time value to consider; \f$a < b\f$
+ * @return \f$q \in [a, b]: ||\mathbf{C}(q) - \mathbf{p}|| =
+ \inf(\{r \in \mathbb{R} : ||\mathbf{C}(r) - \mathbf{p}||\})\f$ */
+ virtual Coord nearestTime( Point const& p, Coord a = 0, Coord b = 1 ) const;
+
+ /** @brief A version that takes an Interval. */
+ Coord nearestTime(Point const &p, Interval const &i) const {
+ return nearestTime(p, i.min(), i.max());
+ }
+
+ /** @brief Compute time values at which the curve comes closest to a specified point.
+ * @param p Query point
+ * @param a Minimum time value to consider
+ * @param b Maximum time value to consider; \f$a < b\f$
+ * @return Vector of points closest and equally far away from the query point */
+ virtual std::vector<Coord> allNearestTimes( Point const& p, Coord from = 0,
+ Coord to = 1 ) const;
+
+ /** @brief A version that takes an Interval. */
+ std::vector<Coord> allNearestTimes(Point const &p, Interval const &i) {
+ return allNearestTimes(p, i.min(), i.max());
+ }
+
+ /** @brief Compute the arc length of this curve.
+ * For a curve \f$\mathbf{C}(t) = (C_x(t), C_y(t))\f$, arc length is defined for 2D curves as
+ * \f[ \ell = \int_{0}^{1} \sqrt { [C_x'(t)]^2 + [C_y'(t)]^2 }\, \text{d}t \f]
+ * In other words, we divide the curve into infinitely small linear segments
+ * and add together their lengths. Of course we can't subdivide the curve into
+ * infinitely many segments on a computer, so this method returns an approximation.
+ * Not that there is usually no closed form solution to such integrals, so this
+ * method might be slow.
+ * @param tolerance Maximum allowed error
+ * @return Total distance the curve's value travels on the plane when going from 0 to 1 */
+ virtual Coord length(Coord tolerance=0.01) const;
+
+ /** @brief Computes time values at which the curve intersects an axis-aligned line.
+ * @param v The coordinate of the line
+ * @param d Which axis the coordinate is on. X means a vertical line, Y a horizontal line. */
+ virtual std::vector<Coord> roots(Coord v, Dim2 d) const = 0;
+
+ /** @brief Compute the partial winding number of this curve.
+ * The partial winding number is equal to the difference between the number
+ * of roots at which the curve goes in the +Y direction and the number of roots
+ * at which the curve goes in the -Y direction. This method is mainly useful
+ * for implementing path winding calculation. It will ignore roots which
+ * are local maxima on the Y axis.
+ * @param p Point where the winding number should be determined
+ * @return Winding number contribution at p */
+ virtual int winding(Point const &p) const;
+
+ /// Compute intersections with another curve.
+ virtual std::vector<CurveIntersection> intersect(Curve const &other, Coord eps = EPSILON) const;
+
+ /// Compute intersections of this curve with itself.
+ virtual std::vector<CurveIntersection> intersectSelf(Coord eps = EPSILON) const;
+
+ /** @brief Compute a vector tangent to the curve.
+ * This will return an unit vector (a Point with length() equal to 1) that denotes a vector
+ * tangent to the curve. This vector is defined as
+ * \f$ \mathbf{v}(t) = \frac{\mathbf{C}'(t)}{||\mathbf{C}'(t)||} \f$. It is pointed
+ * in the direction of increasing \f$t\f$, at the specified time value. The method uses
+ * l'Hopital's rule when the derivative is zero. A zero vector is returned if no non-zero
+ * derivative could be found.
+ * @param t Time value
+ * @param n The maximum order of derivative to consider
+ * @return Unit tangent vector \f$\mathbf{v}(t)\f$ */
+ virtual Point unitTangentAt(Coord t, unsigned n = 3) const;
+
+ /** @brief Convert the curve to a symmetric power basis polynomial.
+ * Symmetric power basis polynomials (S-basis for short) are numerical representations
+ * of curves with excellent numerical properties. Most high level operations provided by 2Geom
+ * are implemented in terms of S-basis operations, so every curve has to provide a method
+ * to convert it to an S-basis polynomial on two variables. See SBasis class reference
+ * for more information. */
+ virtual D2<SBasis> toSBasis() const = 0;
+ /// @}
+
+ /// @name Miscellaneous
+ /// @{
+ /** Return the number of independent parameters required to represent all variations
+ * of this curve. For example, for Bezier curves it returns the curve's order
+ * multiplied by 2. */
+ virtual int degreesOfFreedom() const { return 0;}
+
+ /** @brief Test equality of two curves.
+ * Equality means that for any time value, the evaluation of either curve will yield
+ * the same value. This means non-degenerate curves are not equal to their reverses.
+ * Note that this tests for exact equality.
+ * @return True if the curves are identical, false otherwise */
+ virtual bool operator==(Curve const &c) const = 0;
+
+ /** @brief Test whether two curves are approximately the same. */
+ virtual bool isNear(Curve const &c, Coord precision) const = 0;
+
+ /** @brief Feed the curve to a PathSink */
+ virtual void feed(PathSink &sink, bool moveto_initial) const;
+ /// @}
+};
+
+inline
+Coord nearest_time(Point const& p, Curve const& c) {
+ return c.nearestTime(p);
+}
+
+// for make benefit glorious library of Boost Pointer Container
+inline
+Curve *new_clone(Curve const &c) {
+ return c.duplicate();
+}
+
+} // end namespace Geom
+
+
+#endif // _2GEOM_CURVE_H_
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/curves.h b/src/3rdparty/2geom/include/2geom/curves.h
new file mode 100644
index 0000000..46fb6d9
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/curves.h
@@ -0,0 +1,54 @@
+/** @file
+ * @brief Include all curve types
+ *//*
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2007-2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_CURVES_H
+#define LIB2GEOM_SEEN_CURVES_H
+
+#include <2geom/curve.h>
+#include <2geom/sbasis-curve.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/elliptical-arc.h>
+
+#endif // LIB2GEOM_SEEN_CURVES_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+
diff --git a/src/3rdparty/2geom/include/2geom/d2.h b/src/3rdparty/2geom/include/2geom/d2.h
new file mode 100644
index 0000000..45f036b
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/d2.h
@@ -0,0 +1,564 @@
+/**
+ * \file
+ * \brief Lifts one dimensional objects into 2D
+ *//*
+ * Authors:
+ * Michael Sloan <mgsloan@gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2007-2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, output to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_D2_H
+#define LIB2GEOM_SEEN_D2_H
+
+#include <iterator>
+#include <boost/concept/assert.hpp>
+#include <boost/iterator/transform_iterator.hpp>
+#include <2geom/point.h>
+#include <2geom/interval.h>
+#include <2geom/affine.h>
+#include <2geom/rect.h>
+#include <2geom/concepts.h>
+
+namespace Geom {
+/**
+ * @brief Adaptor that creates 2D functions from 1D ones.
+ * @ingroup Fragments
+ */
+template <typename T>
+class D2
+{
+private:
+ T f[2];
+
+public:
+ typedef T D1Value;
+ typedef T &D1Reference;
+ typedef T const &D1ConstReference;
+
+ D2() {f[X] = f[Y] = T();}
+ explicit D2(Point const &a) {
+ f[X] = T(a[X]); f[Y] = T(a[Y]);
+ }
+
+ D2(T const &a, T const &b) {
+ f[X] = a;
+ f[Y] = b;
+ }
+
+ template <typename Iter>
+ D2(Iter first, Iter last) {
+ typedef typename std::iterator_traits<Iter>::value_type V;
+ typedef typename boost::transform_iterator<GetAxis<X,V>, Iter> XIter;
+ typedef typename boost::transform_iterator<GetAxis<Y,V>, Iter> YIter;
+
+ XIter xfirst(first, GetAxis<X,V>()), xlast(last, GetAxis<X,V>());
+ f[X] = T(xfirst, xlast);
+ YIter yfirst(first, GetAxis<Y,V>()), ylast(last, GetAxis<Y,V>());
+ f[Y] = T(yfirst, ylast);
+ }
+
+ D2(std::vector<Point> const &vec) {
+ typedef Point V;
+ typedef std::vector<Point>::const_iterator Iter;
+ typedef boost::transform_iterator<GetAxis<X,V>, Iter> XIter;
+ typedef boost::transform_iterator<GetAxis<Y,V>, Iter> YIter;
+
+ XIter xfirst(vec.begin(), GetAxis<X,V>()), xlast(vec.end(), GetAxis<X,V>());
+ f[X] = T(xfirst, xlast);
+ YIter yfirst(vec.begin(), GetAxis<Y,V>()), ylast(vec.end(), GetAxis<Y,V>());
+ f[Y] = T(yfirst, ylast);
+ }
+
+ //TODO: ask MenTaLguY about operator= as seen in Point
+
+ T& operator[](unsigned i) { return f[i]; }
+ T const & operator[](unsigned i) const { return f[i]; }
+ Point point(unsigned i) const {
+ Point ret(f[X][i], f[Y][i]);
+ return ret;
+ }
+
+ //IMPL: FragmentConcept
+ typedef Point output_type;
+ bool isZero(double eps=EPSILON) const {
+ BOOST_CONCEPT_ASSERT((FragmentConcept<T>));
+ return f[X].isZero(eps) && f[Y].isZero(eps);
+ }
+ bool isConstant(double eps=EPSILON) const {
+ BOOST_CONCEPT_ASSERT((FragmentConcept<T>));
+ return f[X].isConstant(eps) && f[Y].isConstant(eps);
+ }
+ bool isFinite() const {
+ BOOST_CONCEPT_ASSERT((FragmentConcept<T>));
+ return f[X].isFinite() && f[Y].isFinite();
+ }
+ Point at0() const {
+ BOOST_CONCEPT_ASSERT((FragmentConcept<T>));
+ return Point(f[X].at0(), f[Y].at0());
+ }
+ Point at1() const {
+ BOOST_CONCEPT_ASSERT((FragmentConcept<T>));
+ return Point(f[X].at1(), f[Y].at1());
+ }
+ Point pointAt(double t) const {
+ BOOST_CONCEPT_ASSERT((FragmentConcept<T>));
+ return (*this)(t);
+ }
+ Point valueAt(double t) const {
+ // TODO: remove this alias
+ BOOST_CONCEPT_ASSERT((FragmentConcept<T>));
+ return (*this)(t);
+ }
+ std::vector<Point > valueAndDerivatives(double t, unsigned n) const {
+ BOOST_CONCEPT_ASSERT((FragmentConcept<T>));
+ std::vector<Coord> x = f[X].valueAndDerivatives(t, n),
+ y = f[Y].valueAndDerivatives(t, n); // always returns a vector of size n+1
+ std::vector<Point> res(n+1);
+ for(unsigned i = 0; i <= n; i++) {
+ res[i] = Point(x[i], y[i]);
+ }
+ return res;
+ }
+ D2<SBasis> toSBasis() const {
+ BOOST_CONCEPT_ASSERT((FragmentConcept<T>));
+ return D2<SBasis>(f[X].toSBasis(), f[Y].toSBasis());
+ }
+
+ Point operator()(double t) const;
+ Point operator()(double x, double y) const;
+};
+template <typename T>
+inline D2<T> reverse(const D2<T> &a) {
+ BOOST_CONCEPT_ASSERT((FragmentConcept<T>));
+ return D2<T>(reverse(a[X]), reverse(a[Y]));
+}
+
+template <typename T>
+inline D2<T> portion(const D2<T> &a, Coord f, Coord t) {
+ BOOST_CONCEPT_ASSERT((FragmentConcept<T>));
+ return D2<T>(portion(a[X], f, t), portion(a[Y], f, t));
+}
+
+template <typename T>
+inline D2<T> portion(const D2<T> &a, Interval i) {
+ BOOST_CONCEPT_ASSERT((FragmentConcept<T>));
+ return D2<T>(portion(a[X], i), portion(a[Y], i));
+}
+
+//IMPL: EqualityComparableConcept
+template <typename T>
+inline bool
+operator==(D2<T> const &a, D2<T> const &b) {
+ BOOST_CONCEPT_ASSERT((EqualityComparableConcept<T>));
+ return a[0]==b[0] && a[1]==b[1];
+}
+template <typename T>
+inline bool
+operator!=(D2<T> const &a, D2<T> const &b) {
+ BOOST_CONCEPT_ASSERT((EqualityComparableConcept<T>));
+ return a[0]!=b[0] || a[1]!=b[1];
+}
+
+//IMPL: NearConcept
+template <typename T>
+inline bool
+are_near(D2<T> const &a, D2<T> const &b, double tol) {
+ BOOST_CONCEPT_ASSERT((NearConcept<T>));
+ return are_near(a[0], b[0], tol) && are_near(a[1], b[1], tol);
+}
+
+//IMPL: AddableConcept
+template <typename T>
+inline D2<T>
+operator+(D2<T> const &a, D2<T> const &b) {
+ BOOST_CONCEPT_ASSERT((AddableConcept<T>));
+
+ D2<T> r;
+ for(unsigned i = 0; i < 2; i++)
+ r[i] = a[i] + b[i];
+ return r;
+}
+template <typename T>
+inline D2<T>
+operator-(D2<T> const &a, D2<T> const &b) {
+ BOOST_CONCEPT_ASSERT((AddableConcept<T>));
+
+ D2<T> r;
+ for(unsigned i = 0; i < 2; i++)
+ r[i] = a[i] - b[i];
+ return r;
+}
+template <typename T>
+inline D2<T>
+operator+=(D2<T> &a, D2<T> const &b) {
+ BOOST_CONCEPT_ASSERT((AddableConcept<T>));
+
+ for(unsigned i = 0; i < 2; i++)
+ a[i] += b[i];
+ return a;
+}
+template <typename T>
+inline D2<T>
+operator-=(D2<T> &a, D2<T> const & b) {
+ BOOST_CONCEPT_ASSERT((AddableConcept<T>));
+
+ for(unsigned i = 0; i < 2; i++)
+ a[i] -= b[i];
+ return a;
+}
+
+//IMPL: ScalableConcept
+template <typename T>
+inline D2<T>
+operator-(D2<T> const & a) {
+ BOOST_CONCEPT_ASSERT((ScalableConcept<T>));
+ D2<T> r;
+ for(unsigned i = 0; i < 2; i++)
+ r[i] = -a[i];
+ return r;
+}
+template <typename T>
+inline D2<T>
+operator*(D2<T> const & a, Point const & b) {
+ BOOST_CONCEPT_ASSERT((ScalableConcept<T>));
+
+ D2<T> r;
+ for(unsigned i = 0; i < 2; i++)
+ r[i] = a[i] * b[i];
+ return r;
+}
+template <typename T>
+inline D2<T>
+operator/(D2<T> const & a, Point const & b) {
+ BOOST_CONCEPT_ASSERT((ScalableConcept<T>));
+ //TODO: b==0?
+ D2<T> r;
+ for(unsigned i = 0; i < 2; i++)
+ r[i] = a[i] / b[i];
+ return r;
+}
+template <typename T>
+inline D2<T>
+operator*=(D2<T> &a, Point const & b) {
+ BOOST_CONCEPT_ASSERT((ScalableConcept<T>));
+
+ for(unsigned i = 0; i < 2; i++)
+ a[i] *= b[i];
+ return a;
+}
+template <typename T>
+inline D2<T>
+operator/=(D2<T> &a, Point const & b) {
+ BOOST_CONCEPT_ASSERT((ScalableConcept<T>));
+ //TODO: b==0?
+ for(unsigned i = 0; i < 2; i++)
+ a[i] /= b[i];
+ return a;
+}
+
+template <typename T>
+inline D2<T> operator*(D2<T> const & a, double b) { return D2<T>(a[0]*b, a[1]*b); }
+template <typename T>
+inline D2<T> operator*=(D2<T> & a, double b) { a[0] *= b; a[1] *= b; return a; }
+template <typename T>
+inline D2<T> operator/(D2<T> const & a, double b) { return D2<T>(a[0]/b, a[1]/b); }
+template <typename T>
+inline D2<T> operator/=(D2<T> & a, double b) { a[0] /= b; a[1] /= b; return a; }
+
+template<typename T>
+D2<T> operator*(D2<T> const &v, Affine const &m) {
+ BOOST_CONCEPT_ASSERT((AddableConcept<T>));
+ BOOST_CONCEPT_ASSERT((ScalableConcept<T>));
+ D2<T> ret;
+ for(unsigned i = 0; i < 2; i++)
+ ret[i] = v[X] * m[i] + v[Y] * m[i + 2] + m[i + 4];
+ return ret;
+}
+
+//IMPL: MultiplicableConcept
+template <typename T>
+inline D2<T>
+operator*(D2<T> const & a, T const & b) {
+ BOOST_CONCEPT_ASSERT((MultiplicableConcept<T>));
+ D2<T> ret;
+ for(unsigned i = 0; i < 2; i++)
+ ret[i] = a[i] * b;
+ return ret;
+}
+
+//IMPL:
+
+//IMPL: OffsetableConcept
+template <typename T>
+inline D2<T>
+operator+(D2<T> const & a, Point b) {
+ BOOST_CONCEPT_ASSERT((OffsetableConcept<T>));
+ D2<T> r;
+ for(unsigned i = 0; i < 2; i++)
+ r[i] = a[i] + b[i];
+ return r;
+}
+template <typename T>
+inline D2<T>
+operator-(D2<T> const & a, Point b) {
+ BOOST_CONCEPT_ASSERT((OffsetableConcept<T>));
+ D2<T> r;
+ for(unsigned i = 0; i < 2; i++)
+ r[i] = a[i] - b[i];
+ return r;
+}
+template <typename T>
+inline D2<T>
+operator+=(D2<T> & a, Point b) {
+ BOOST_CONCEPT_ASSERT((OffsetableConcept<T>));
+ for(unsigned i = 0; i < 2; i++)
+ a[i] += b[i];
+ return a;
+}
+template <typename T>
+inline D2<T>
+operator-=(D2<T> & a, Point b) {
+ BOOST_CONCEPT_ASSERT((OffsetableConcept<T>));
+ for(unsigned i = 0; i < 2; i++)
+ a[i] -= b[i];
+ return a;
+}
+
+template <typename T>
+inline T
+dot(D2<T> const & a, D2<T> const & b) {
+ BOOST_CONCEPT_ASSERT((AddableConcept<T>));
+ BOOST_CONCEPT_ASSERT((MultiplicableConcept<T>));
+
+ T r;
+ for(unsigned i = 0; i < 2; i++)
+ r += a[i] * b[i];
+ return r;
+}
+
+/** @brief Calculates the 'dot product' or 'inner product' of \c a and \c b
+ * @return \f$a \bullet b = a_X b_X + a_Y b_Y\f$.
+ * @relates D2 */
+template <typename T>
+inline T
+dot(D2<T> const & a, Point const & b) {
+ BOOST_CONCEPT_ASSERT((AddableConcept<T>));
+ BOOST_CONCEPT_ASSERT((ScalableConcept<T>));
+
+ T r;
+ for(unsigned i = 0; i < 2; i++) {
+ r += a[i] * b[i];
+ }
+ return r;
+}
+
+/** @brief Calculates the 'cross product' or 'outer product' of \c a and \c b
+ * @return \f$a \times b = a_Y b_X - a_X b_Y\f$.
+ * @relates D2 */
+template <typename T>
+inline T
+cross(D2<T> const & a, D2<T> const & b) {
+ BOOST_CONCEPT_ASSERT((ScalableConcept<T>));
+ BOOST_CONCEPT_ASSERT((MultiplicableConcept<T>));
+
+ return a[1] * b[0] - a[0] * b[1];
+}
+
+
+//equivalent to cw/ccw, for use in situations where rotation direction doesn't matter.
+template <typename T>
+inline D2<T>
+rot90(D2<T> const & a) {
+ BOOST_CONCEPT_ASSERT((ScalableConcept<T>));
+ return D2<T>(-a[Y], a[X]);
+}
+
+//TODO: concepterize the following functions
+template <typename T>
+inline D2<T>
+compose(D2<T> const & a, T const & b) {
+ D2<T> r;
+ for(unsigned i = 0; i < 2; i++)
+ r[i] = compose(a[i],b);
+ return r;
+}
+
+template <typename T>
+inline D2<T>
+compose_each(D2<T> const & a, D2<T> const & b) {
+ D2<T> r;
+ for(unsigned i = 0; i < 2; i++)
+ r[i] = compose(a[i],b[i]);
+ return r;
+}
+
+template <typename T>
+inline D2<T>
+compose_each(T const & a, D2<T> const & b) {
+ D2<T> r;
+ for(unsigned i = 0; i < 2; i++)
+ r[i] = compose(a,b[i]);
+ return r;
+}
+
+
+template<typename T>
+inline Point
+D2<T>::operator()(double t) const {
+ Point p;
+ for(unsigned i = 0; i < 2; i++)
+ p[i] = (*this)[i](t);
+ return p;
+}
+
+//TODO: we might want to have this take a Point as the parameter.
+template<typename T>
+inline Point
+D2<T>::operator()(double x, double y) const {
+ Point p;
+ for(unsigned i = 0; i < 2; i++)
+ p[i] = (*this)[i](x, y);
+ return p;
+}
+
+
+template<typename T>
+D2<T> derivative(D2<T> const & a) {
+ return D2<T>(derivative(a[X]), derivative(a[Y]));
+}
+template<typename T>
+D2<T> integral(D2<T> const & a) {
+ return D2<T>(integral(a[X]), integral(a[Y]));
+}
+
+/** A function to print out the Point. It just prints out the coords
+ on the given output stream */
+template <typename T>
+inline std::ostream &operator<< (std::ostream &out_file, const Geom::D2<T> &in_d2) {
+ out_file << "X: " << in_d2[X] << " Y: " << in_d2[Y];
+ return out_file;
+}
+
+//Some D2 Fragment implementation which requires rect:
+template <typename T>
+OptRect bounds_fast(const D2<T> &a) {
+ BOOST_CONCEPT_ASSERT((FragmentConcept<T>));
+ return OptRect(bounds_fast(a[X]), bounds_fast(a[Y]));
+}
+template <typename T>
+OptRect bounds_exact(const D2<T> &a) {
+ BOOST_CONCEPT_ASSERT((FragmentConcept<T>));
+ return OptRect(bounds_exact(a[X]), bounds_exact(a[Y]));
+}
+template <typename T>
+OptRect bounds_local(const D2<T> &a, const OptInterval &t) {
+ BOOST_CONCEPT_ASSERT((FragmentConcept<T>));
+ return OptRect(bounds_local(a[X], t), bounds_local(a[Y], t));
+}
+
+
+
+// SBasis-specific declarations
+
+inline D2<SBasis> compose(D2<SBasis> const & a, SBasis const & b) {
+ return D2<SBasis>(compose(a[X], b), compose(a[Y], b));
+}
+
+SBasis L2(D2<SBasis> const & a, unsigned k);
+double L2(D2<double> const & a);
+
+D2<SBasis> multiply(Linear const & a, D2<SBasis> const & b);
+inline D2<SBasis> operator*(Linear const & a, D2<SBasis> const & b) { return multiply(a, b); }
+D2<SBasis> multiply(SBasis const & a, D2<SBasis> const & b);
+inline D2<SBasis> operator*(SBasis const & a, D2<SBasis> const & b) { return multiply(a, b); }
+D2<SBasis> truncate(D2<SBasis> const & a, unsigned terms);
+
+unsigned sbasis_size(D2<SBasis> const & a);
+double tail_error(D2<SBasis> const & a, unsigned tail);
+
+//Piecewise<D2<SBasis> > specific declarations
+
+Piecewise<D2<SBasis> > sectionize(D2<Piecewise<SBasis> > const &a);
+D2<Piecewise<SBasis> > make_cuts_independent(Piecewise<D2<SBasis> > const &a);
+Piecewise<D2<SBasis> > rot90(Piecewise<D2<SBasis> > const &a);
+Piecewise<SBasis> dot(Piecewise<D2<SBasis> > const &a, Piecewise<D2<SBasis> > const &b);
+Piecewise<SBasis> dot(Piecewise<D2<SBasis> > const &a, Point const &b);
+Piecewise<SBasis> cross(Piecewise<D2<SBasis> > const &a, Piecewise<D2<SBasis> > const &b);
+
+Piecewise<D2<SBasis> > operator*(Piecewise<D2<SBasis> > const &a, Affine const &m);
+
+Piecewise<D2<SBasis> > force_continuity(Piecewise<D2<SBasis> > const &f, double tol=0, bool closed=false);
+
+std::vector<Piecewise<D2<SBasis> > > fuse_nearby_ends(std::vector<Piecewise<D2<SBasis> > > const &f, double tol=0);
+
+std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > split_at_discontinuities (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwsbin, double tol = .0001);
+
+Point unitTangentAt(D2<SBasis> const & a, Coord t, unsigned n = 3);
+
+//bounds specializations with order
+inline OptRect bounds_fast(D2<SBasis> const & s, unsigned order=0) {
+ OptRect retval;
+ OptInterval xint = bounds_fast(s[X], order);
+ if (xint) {
+ OptInterval yint = bounds_fast(s[Y], order);
+ if (yint) {
+ retval = Rect(*xint, *yint);
+ }
+ }
+ return retval;
+}
+inline OptRect bounds_local(D2<SBasis> const & s, OptInterval i, unsigned order=0) {
+ OptRect retval;
+ OptInterval xint = bounds_local(s[X], i, order);
+ OptInterval yint = bounds_local(s[Y], i, order);
+ if (xint && yint) {
+ retval = Rect(*xint, *yint);
+ }
+ return retval;
+}
+
+std::vector<Interval> level_set( D2<SBasis> const &f, Rect region);
+std::vector<Interval> level_set( D2<SBasis> const &f, Point p, double tol);
+std::vector<std::vector<Interval> > level_sets( D2<SBasis> const &f, std::vector<Rect> regions);
+std::vector<std::vector<Interval> > level_sets( D2<SBasis> const &f, std::vector<Point> pts, double tol);
+
+
+} // end namespace Geom
+
+#endif
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/ellipse.h b/src/3rdparty/2geom/include/2geom/ellipse.h
new file mode 100644
index 0000000..0d1567a
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/ellipse.h
@@ -0,0 +1,260 @@
+/** @file
+ * @brief Ellipse shape
+ *//*
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#ifndef LIB2GEOM_SEEN_ELLIPSE_H
+#define LIB2GEOM_SEEN_ELLIPSE_H
+
+#include <vector>
+#include <2geom/angle.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/exception.h>
+#include <2geom/forward.h>
+#include <2geom/line.h>
+#include <2geom/transforms.h>
+
+namespace Geom {
+
+class EllipticalArc;
+class Circle;
+
+/** @brief Set of points with a constant sum of distances from two foci.
+ *
+ * An ellipse can be specified in several ways. Internally, 2Geom uses
+ * the SVG style representation: center, rays and angle between the +X ray
+ * and the +X axis. Another popular way is to use an implicit equation,
+ * which is as follows:
+ * \f$Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0\f$
+ *
+ * @ingroup Shapes */
+class Ellipse
+ : boost::multipliable< Ellipse, Translate
+ , boost::multipliable< Ellipse, Scale
+ , boost::multipliable< Ellipse, Rotate
+ , boost::multipliable< Ellipse, Zoom
+ , boost::multipliable< Ellipse, Affine
+ , boost::equality_comparable< Ellipse
+ > > > > > >
+{
+ Point _center;
+ Point _rays;
+ Angle _angle;
+public:
+ Ellipse() {}
+ Ellipse(Point const &c, Point const &r, Coord angle)
+ : _center(c)
+ , _rays(r)
+ , _angle(angle)
+ {}
+ Ellipse(Coord cx, Coord cy, Coord rx, Coord ry, Coord angle)
+ : _center(cx, cy)
+ , _rays(rx, ry)
+ , _angle(angle)
+ {}
+ Ellipse(double A, double B, double C, double D, double E, double F) {
+ setCoefficients(A, B, C, D, E, F);
+ }
+ /// Construct ellipse from a circle.
+ Ellipse(Geom::Circle const &c);
+
+ /// Set center, rays and angle.
+ void set(Point const &c, Point const &r, Coord angle) {
+ _center = c;
+ _rays = r;
+ _angle = angle;
+ }
+ /// Set center, rays and angle as constituent values.
+ void set(Coord cx, Coord cy, Coord rx, Coord ry, Coord a) {
+ _center[X] = cx;
+ _center[Y] = cy;
+ _rays[X] = rx;
+ _rays[Y] = ry;
+ _angle = a;
+ }
+ /// Set an ellipse by solving its implicit equation.
+ void setCoefficients(double A, double B, double C, double D, double E, double F);
+ /// Set the center.
+ void setCenter(Point const &p) { _center = p; }
+ /// Set the center by coordinates.
+ void setCenter(Coord cx, Coord cy) { _center[X] = cx; _center[Y] = cy; }
+ /// Set both rays of the ellipse.
+ void setRays(Point const &p) { _rays = p; }
+ /// Set both rays of the ellipse as coordinates.
+ void setRays(Coord x, Coord y) { _rays[X] = x; _rays[Y] = y; }
+ /// Set one of the rays of the ellipse.
+ void setRay(Coord r, Dim2 d) { _rays[d] = r; }
+ /// Set the angle the X ray makes with the +X axis.
+ void setRotationAngle(Angle a) { _angle = a; }
+
+ Point center() const { return _center; }
+ Coord center(Dim2 d) const { return _center[d]; }
+ /// Get both rays as a point.
+ Point rays() const { return _rays; }
+ /// Get one ray of the ellipse.
+ Coord ray(Dim2 d) const { return _rays[d]; }
+ /// Get the angle the X ray makes with the +X axis.
+ Angle rotationAngle() const { return _angle; }
+ /// Get the point corresponding to the +X ray of the ellipse.
+ Point initialPoint() const;
+ /// Get the point corresponding to the +X ray of the ellipse.
+ Point finalPoint() const { return initialPoint(); }
+
+ /** @brief Create an ellipse passing through the specified points
+ * At least five points have to be specified. */
+ void fit(std::vector<Point> const& points);
+
+ /** @brief Create an elliptical arc from a section of the ellipse.
+ * This is mainly useful to determine the flags of the new arc.
+ * The passed points should lie on the ellipse, otherwise the results
+ * will be undefined.
+ * @param ip Initial point of the arc
+ * @param inner Point in the middle of the arc, used to pick one of two possibilities
+ * @param fp Final point of the arc
+ * @return Newly allocated arc, delete when no longer used */
+ EllipticalArc *arc(Point const &ip, Point const &inner, Point const &fp);
+
+ /** @brief Return an ellipse with less degrees of freedom.
+ * The canonical form always has the angle less than \f$\frac{\pi}{2}\f$,
+ * and zero if the rays are equal (i.e. the ellipse is a circle). */
+ Ellipse canonicalForm() const;
+ void makeCanonical();
+
+ /** @brief Compute the transform that maps the unit circle to this ellipse.
+ * Each ellipse can be interpreted as a translated, scaled and rotate unit circle.
+ * This function returns the transform that maps the unit circle to this ellipse.
+ * @return Transform from unit circle to the ellipse */
+ Affine unitCircleTransform() const;
+ /** @brief Compute the transform that maps this ellipse to the unit circle.
+ * This may be a little more precise and/or faster than simply using
+ * unitCircleTransform().inverse(). An exception will be thrown for
+ * degenerate ellipses. */
+ Affine inverseUnitCircleTransform() const;
+
+ LineSegment majorAxis() const { return ray(X) >= ray(Y) ? axis(X) : axis(Y); }
+ LineSegment minorAxis() const { return ray(X) < ray(Y) ? axis(X) : axis(Y); }
+ LineSegment semimajorAxis(int sign = 1) const {
+ return ray(X) >= ray(Y) ? semiaxis(X, sign) : semiaxis(Y, sign);
+ }
+ LineSegment semiminorAxis(int sign = 1) const {
+ return ray(X) < ray(Y) ? semiaxis(X, sign) : semiaxis(Y, sign);
+ }
+ LineSegment axis(Dim2 d) const;
+ LineSegment semiaxis(Dim2 d, int sign = 1) const;
+
+ /// Get the tight-fitting bounding box of the ellipse.
+ Rect boundsExact() const;
+
+ /** @brief Get a fast to compute bounding box which contains the ellipse.
+ *
+ * The returned rectangle engulfs the ellipse but it may not be the smallest
+ * axis-aligned rectangle with this property.
+ */
+ Rect boundsFast() const;
+
+ /// Get the coefficients of the ellipse's implicit equation.
+ std::vector<double> coefficients() const;
+ void coefficients(Coord &A, Coord &B, Coord &C, Coord &D, Coord &E, Coord &F) const;
+
+ /** @brief Evaluate a point on the ellipse.
+ * The parameter range is \f$[0, 2\pi)\f$; larger and smaller values
+ * wrap around. */
+ Point pointAt(Coord t) const;
+ /// Evaluate a single coordinate of a point on the ellipse.
+ Coord valueAt(Coord t, Dim2 d) const;
+
+ /** @brief Find the time value of a point on an ellipse.
+ * If the point is not on the ellipse, the returned time value will correspond
+ * to an intersection with a ray from the origin passing through the point
+ * with the ellipse. Note that this is NOT the nearest point on the ellipse. */
+ Coord timeAt(Point const &p) const;
+
+ /// Get the value of the derivative at time t normalized to unit length.
+ Point unitTangentAt(Coord t) const;
+
+ /// Check whether the ellipse contains the given point.
+ bool contains(Point const &p) const;
+
+ /// Compute intersections with an infinite line.
+ std::vector<ShapeIntersection> intersect(Line const &line) const;
+ /// Compute intersections with a line segment.
+ std::vector<ShapeIntersection> intersect(LineSegment const &seg) const;
+ /// Compute intersections with another ellipse.
+ std::vector<ShapeIntersection> intersect(Ellipse const &other) const;
+ /// Compute intersections with a 2D Bezier polynomial.
+ std::vector<ShapeIntersection> intersect(D2<Bezier> const &other) const;
+
+ Ellipse &operator*=(Translate const &t) {
+ _center *= t;
+ return *this;
+ }
+ Ellipse &operator*=(Scale const &s) {
+ _center *= s;
+ _rays *= s;
+ return *this;
+ }
+ Ellipse &operator*=(Zoom const &z) {
+ _center *= z;
+ _rays *= z.scale();
+ return *this;
+ }
+ Ellipse &operator*=(Rotate const &r);
+ Ellipse &operator*=(Affine const &m);
+
+ /// Compare ellipses for exact equality.
+ bool operator==(Ellipse const &other) const;
+};
+
+/** @brief Test whether two ellipses are approximately the same.
+ * This will check whether no point on ellipse a is further away from
+ * the corresponding point on ellipse b than precision.
+ * @relates Ellipse */
+bool are_near(Ellipse const &a, Ellipse const &b, Coord precision = EPSILON);
+
+/** @brief Outputs ellipse data, useful for debugging.
+ * @relates Ellipse */
+std::ostream &operator<<(std::ostream &out, Ellipse const &e);
+
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_ELLIPSE_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/elliptical-arc.h b/src/3rdparty/2geom/include/2geom/elliptical-arc.h
new file mode 100644
index 0000000..567e207
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/elliptical-arc.h
@@ -0,0 +1,344 @@
+/**
+ * \file
+ * \brief Elliptical arc curve
+ *
+ *//*
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2007-2009 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_ELLIPTICAL_ARC_H
+#define LIB2GEOM_SEEN_ELLIPTICAL_ARC_H
+
+#include <algorithm>
+#include <2geom/affine.h>
+#include <2geom/angle.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/curve.h>
+#include <2geom/ellipse.h>
+#include <2geom/sbasis-curve.h> // for non-native methods
+#include <2geom/utils.h>
+
+namespace Geom
+{
+
+class EllipticalArc : public Curve
+{
+public:
+ /** @brief Creates an arc with all variables set to zero. */
+ EllipticalArc()
+ : _initial_point(0,0)
+ , _final_point(0,0)
+ , _large_arc(false)
+ {}
+ /** @brief Create a new elliptical arc.
+ * @param ip Initial point of the arc
+ * @param r Rays of the ellipse as a point
+ * @param rot Angle of rotation of the X axis of the ellipse in radians
+ * @param large If true, the large arc is chosen (always >= 180 degrees), otherwise
+ * the smaller arc is chosen
+ * @param sweep If true, the clockwise arc is chosen, otherwise the counter-clockwise
+ * arc is chosen
+ * @param fp Final point of the arc */
+ EllipticalArc( Point const &ip, Point const &r,
+ Coord rot_angle, bool large_arc, bool sweep,
+ Point const &fp
+ )
+ : _initial_point(ip)
+ , _final_point(fp)
+ , _ellipse(0, 0, r[X], r[Y], rot_angle)
+ , _angles(0, 0, sweep)
+ , _large_arc(large_arc)
+ {
+ _updateCenterAndAngles();
+ }
+
+ /// Create a new elliptical arc, giving the ellipse's rays as separate coordinates.
+ EllipticalArc( Point const &ip, Coord rx, Coord ry,
+ Coord rot_angle, bool large_arc, bool sweep,
+ Point const &fp
+ )
+ : _initial_point(ip)
+ , _final_point(fp)
+ , _ellipse(0, 0, rx, ry, rot_angle)
+ , _angles(0, 0, sweep)
+ , _large_arc(large_arc)
+ {
+ _updateCenterAndAngles();
+ }
+
+ /// @name Retrieve basic information
+ /// @{
+
+ /** @brief Get a coordinate of the elliptical arc's center.
+ * @param d The dimension to retrieve
+ * @return The selected coordinate of the center */
+ Coord center(Dim2 d) const { return _ellipse.center(d); }
+
+ /** @brief Get the arc's center
+ * @return The arc's center, situated on the intersection of the ellipse's rays */
+ Point center() const { return _ellipse.center(); }
+
+ /** @brief Get one of the ellipse's rays
+ * @param d Dimension to retrieve
+ * @return The selected ray of the ellipse */
+ Coord ray(Dim2 d) const { return _ellipse.ray(d); }
+
+ /** @brief Get both rays as a point
+ * @return Point with X equal to the X ray and Y to Y ray */
+ Point rays() const { return _ellipse.rays(); }
+
+ /** @brief Get the defining ellipse's rotation
+ * @return Angle between the +X ray of the ellipse and the +X axis */
+ Angle rotationAngle() const {
+ return _ellipse.rotationAngle();
+ }
+
+ /** @brief Whether the arc is larger than half an ellipse.
+ * @return True if the arc is larger than \f$\pi\f$, false otherwise */
+ bool largeArc() const { return _large_arc; }
+
+ /** @brief Whether the arc turns clockwise
+ * @return True if the arc makes a clockwise turn when going from initial to final
+ * point, false otherwise */
+ bool sweep() const { return _angles.sweep(); }
+
+ Angle initialAngle() const { return _angles.initialAngle(); }
+ Angle finalAngle() const { return _angles.finalAngle(); }
+ /// @}
+
+ /// @name Modify parameters
+ /// @{
+
+ /// Change all of the arc's parameters.
+ void set( Point const &ip, double rx, double ry,
+ double rot_angle, bool large_arc, bool sweep,
+ Point const &fp
+ )
+ {
+ _initial_point = ip;
+ _final_point = fp;
+ _ellipse.setRays(rx, ry);
+ _ellipse.setRotationAngle(rot_angle);
+ _angles.setSweep(sweep);
+ _large_arc = large_arc;
+ _updateCenterAndAngles();
+ }
+
+ /// Change all of the arc's parameters.
+ void set( Point const &ip, Point const &r,
+ Angle rot_angle, bool large_arc, bool sweep,
+ Point const &fp
+ )
+ {
+ _initial_point = ip;
+ _final_point = fp;
+ _ellipse.setRays(r);
+ _ellipse.setRotationAngle(rot_angle);
+ _angles.setSweep(sweep);
+ _large_arc = large_arc;
+ _updateCenterAndAngles();
+ }
+
+ /** @brief Change the initial and final point in one operation.
+ * This method exists because modifying any of the endpoints causes rather costly
+ * recalculations of the center and extreme angles.
+ * @param ip New initial point
+ * @param fp New final point */
+ void setEndpoints(Point const &ip, Point const &fp) {
+ _initial_point = ip;
+ _final_point = fp;
+ _updateCenterAndAngles();
+ }
+ /// @}
+
+ /// @name Evaluate the arc as a function
+ /// @{
+ /** Check whether the arc contains the given angle
+ * @param t The angle to check
+ * @return True if the arc contains the angle, false otherwise */
+ bool containsAngle(Angle angle) const { return _angles.contains(angle); }
+
+ /** @brief Evaluate the arc at the specified angular coordinate
+ * @param t Angle
+ * @return Point corresponding to the given angle */
+ Point pointAtAngle(Coord t) const;
+
+ /** @brief Evaluate one of the arc's coordinates at the specified angle
+ * @param t Angle
+ * @param d The dimension to retrieve
+ * @return Selected coordinate of the arc at the specified angle */
+ Coord valueAtAngle(Coord t, Dim2 d) const;
+
+ /// Compute the curve time value corresponding to the given angular value.
+ Coord timeAtAngle(Angle a) const { return _angles.timeAtAngle(a); }
+
+ /// Compute the angular domain value corresponding to the given time value.
+ Angle angleAt(Coord t) const { return _angles.angleAt(t); }
+
+ /** @brief Compute the amount by which the angle parameter changes going from start to end.
+ * This has range \f$(-2\pi, 2\pi)\f$ and thus cannot be represented as instance
+ * of the class Angle. Add this to the initial angle to obtain the final angle. */
+ Coord sweepAngle() const { return _angles.sweepAngle(); }
+
+ /** @brief Get the elliptical angle spanned by the arc.
+ * This is basically the absolute value of sweepAngle(). */
+ Coord angularExtent() const { return _angles.extent(); }
+
+ /// Get the angular interval of the arc.
+ AngleInterval angularInterval() const { return _angles; }
+
+ /// Evaluate the arc in the curve domain, i.e. \f$[0, 1]\f$.
+ Point pointAt(Coord t) const override;
+
+ /// Evaluate a single coordinate on the arc in the curve domain.
+ Coord valueAt(Coord t, Dim2 d) const override;
+
+ /** @brief Compute a transform that maps the unit circle to the arc's ellipse.
+ * Each ellipse can be interpreted as a translated, scaled and rotate unit circle.
+ * This function returns the transform that maps the unit circle to the arc's ellipse.
+ * @return Transform from unit circle to the arc's ellipse */
+ Affine unitCircleTransform() const {
+ Affine result = _ellipse.unitCircleTransform();
+ return result;
+ }
+
+ /** @brief Compute a transform that maps the arc's ellipse to the unit circle. */
+ Affine inverseUnitCircleTransform() const {
+ Affine result = _ellipse.inverseUnitCircleTransform();
+ return result;
+ }
+ /// @}
+
+ /// @name Deal with degenerate ellipses.
+ /// @{
+ /** @brief Check whether both rays are nonzero.
+ * If they are not, the arc is represented as a line segment instead. */
+ bool isChord() const {
+ return ray(X) == 0 || ray(Y) == 0;
+ }
+
+ /** @brief Get the line segment connecting the arc's endpoints.
+ * @return A linear segment with initial and final point corresponding to those of the arc. */
+ LineSegment chord() const { return LineSegment(_initial_point, _final_point); }
+ /// @}
+
+ // implementation of overloads goes here
+ Point initialPoint() const override { return _initial_point; }
+ Point finalPoint() const override { return _final_point; }
+ Curve* duplicate() const override { return new EllipticalArc(*this); }
+ void setInitial(Point const &p) override {
+ _initial_point = p;
+ _updateCenterAndAngles();
+ }
+ void setFinal(Point const &p) override {
+ _final_point = p;
+ _updateCenterAndAngles();
+ }
+ bool isDegenerate() const override {
+ return _initial_point == _final_point;
+ }
+ bool isLineSegment() const override { return isChord(); }
+ Rect boundsFast() const override {
+ return boundsExact();
+ }
+ Rect boundsExact() const override;
+ void expandToTransformed(Rect &bbox, Affine const &transform) const override;
+ // TODO: native implementation of the following methods
+ OptRect boundsLocal(OptInterval const &i, unsigned int deg) const override {
+ return SBasisCurve(toSBasis()).boundsLocal(i, deg);
+ }
+ std::vector<double> roots(double v, Dim2 d) const override;
+#ifdef HAVE_GSL
+ std::vector<double> allNearestTimes( Point const& p, double from = 0, double to = 1 ) const override;
+ double nearestTime( Point const& p, double from = 0, double to = 1 ) const override {
+ if ( are_near(ray(X), ray(Y)) && are_near(center(), p) ) {
+ return from;
+ }
+ return allNearestTimes(p, from, to).front();
+ }
+#endif
+ std::vector<CurveIntersection> intersect(Curve const &other, Coord eps=EPSILON) const override;
+ int degreesOfFreedom() const override { return 7; }
+ Curve *derivative() const override;
+
+ using Curve::operator*=;
+ void operator*=(Translate const &tr) override;
+ void operator*=(Scale const &s) override;
+ void operator*=(Rotate const &r) override;
+ void operator*=(Zoom const &z) override;
+ void operator*=(Affine const &m) override;
+
+ std::vector<Point> pointAndDerivatives(Coord t, unsigned int n) const override;
+ D2<SBasis> toSBasis() const override;
+ Curve *portion(double f, double t) const override;
+ Curve *reverse() const override;
+ bool operator==(Curve const &c) const override;
+ bool isNear(Curve const &other, Coord precision) const override;
+ void feed(PathSink &sink, bool moveto_initial) const override;
+ int winding(Point const &p) const override;
+
+private:
+ void _updateCenterAndAngles();
+ std::vector<ShapeIntersection> _filterIntersections(std::vector<ShapeIntersection> &&xs, bool is_first) const;
+ bool _validateIntersection(ShapeIntersection &xing, bool is_first) const;
+ std::vector<ShapeIntersection> _intersectSameEllipse(EllipticalArc const *other) const;
+
+ Point _initial_point, _final_point;
+ Ellipse _ellipse;
+ AngleInterval _angles;
+ bool _large_arc;
+}; // end class EllipticalArc
+
+
+// implemented in elliptical-arc-from-sbasis.cpp
+/** @brief Fit an elliptical arc to an SBasis fragment.
+ * @relates EllipticalArc */
+bool arc_from_sbasis(EllipticalArc &ea, D2<SBasis> const &in,
+ double tolerance = EPSILON, unsigned num_samples = 20);
+
+/** @brief Debug output for elliptical arcs.
+ * @relates EllipticalArc */
+std::ostream &operator<<(std::ostream &out, EllipticalArc const &ea);
+
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_ELLIPTICAL_ARC_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/exception.h b/src/3rdparty/2geom/include/2geom/exception.h
new file mode 100644
index 0000000..b472aae
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/exception.h
@@ -0,0 +1,157 @@
+/**
+ * \file
+ * \brief Defines the different types of exceptions that 2geom can throw.
+ *
+ * There are two main exception classes: LogicalError and RangeError.
+ * Logical errors are 2geom faults/bugs; RangeErrors are 'user' faults,
+ * e.g. invalid arguments to lib2geom methods.
+ * This way, the 'user' can distinguish between groups of exceptions
+ * ('user' is the coder that uses lib2geom)
+ *
+ * Several macro's are defined for easily throwing exceptions
+ * (e.g. THROW_CONTINUITYERROR).
+ */
+/* Copyright 2007 Johan Engelen <goejendaagh@zonnet.nl>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_EXCEPTION_H
+#define LIB2GEOM_SEEN_EXCEPTION_H
+
+#include <exception>
+#include <sstream>
+#include <string>
+
+namespace Geom {
+
+/**
+ * Base exception class, all 2geom exceptions should be derived from this one.
+ */
+class Exception : public std::exception {
+public:
+ Exception(const char * message, const char *file, const int line) {
+ std::ostringstream os;
+ os << "lib2geom exception: " << message << " (" << file << ":" << line << ")";
+ msgstr = os.str();
+ }
+
+ ~Exception() noexcept override {} // necessary to destroy the string object!!!
+
+ const char* what() const noexcept override {
+ return msgstr.c_str();
+ }
+protected:
+ std::string msgstr;
+};
+#define THROW_EXCEPTION(message) throw(Geom::Exception(message, __FILE__, __LINE__))
+
+//-----------------------------------------------------------------------
+
+class LogicalError : public Exception {
+public:
+ LogicalError(const char * message, const char *file, const int line)
+ : Exception(message, file, line) {}
+};
+#define THROW_LOGICALERROR(message) throw(LogicalError(message, __FILE__, __LINE__))
+
+class RangeError : public Exception {
+public:
+ RangeError(const char * message, const char *file, const int line)
+ : Exception(message, file, line) {}
+};
+#define THROW_RANGEERROR(message) throw(RangeError(message, __FILE__, __LINE__))
+
+//-----------------------------------------------------------------------
+// Special case exceptions. Best used with the defines :)
+
+class NotImplemented : public LogicalError {
+public:
+ NotImplemented(const char *file, const int line)
+ : LogicalError("Method not implemented", file, line) {}
+};
+#define THROW_NOTIMPLEMENTED(i) throw(NotImplemented(__FILE__, __LINE__))
+
+class InvariantsViolation : public LogicalError {
+public:
+ InvariantsViolation(const char *file, const int line)
+ : LogicalError("Invariants violation", file, line) {}
+};
+#define THROW_INVARIANTSVIOLATION(i) throw(InvariantsViolation(__FILE__, __LINE__))
+#define ASSERT_INVARIANTS(e) ((e) ? (void)0 : THROW_INVARIANTSVIOLATION())
+
+class NotInvertible : public RangeError {
+public:
+ NotInvertible(const char *file, const int line)
+ : RangeError("Function does not have a unique inverse", file, line) {}
+};
+#define THROW_NOTINVERTIBLE(i) throw(NotInvertible(__FILE__, __LINE__))
+
+class InfiniteSolutions : public RangeError {
+public:
+ InfiniteSolutions(const char *file, const int line)
+ : RangeError("There are infinite solutions", file, line) {}
+};
+#define THROW_INFINITESOLUTIONS(i) throw(InfiniteSolutions(__FILE__, __LINE__))
+
+class InfinitelyManySolutions : public RangeError {
+private:
+ char const *const _message;
+public:
+ InfinitelyManySolutions(const char *file, const int line, char const *message)
+ : RangeError("There are infinitely many solutions", file, line)
+ , _message{message}
+ {}
+ char const *what() const noexcept override { return _message; }
+};
+#define THROW_INFINITELY_MANY_SOLUTIONS(msg) throw(InfinitelyManySolutions(__FILE__, __LINE__, msg))
+
+class ContinuityError : public RangeError {
+public:
+ ContinuityError(const char *file, const int line)
+ : RangeError("Non-contiguous path", file, line) {}
+};
+#define THROW_CONTINUITYERROR(i) throw(ContinuityError(__FILE__, __LINE__))
+
+struct SVGPathParseError : public std::exception {
+ char const *what() const noexcept override { return "parse error"; }
+};
+
+
+} // namespace Geom
+
+#endif
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/forward.h b/src/3rdparty/2geom/include/2geom/forward.h
new file mode 100644
index 0000000..2790924
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/forward.h
@@ -0,0 +1,127 @@
+/**
+ * \file
+ * \brief Contains forward declarations of 2geom types
+ *//*
+ * Authors:
+ * Johan Engelen <goejendaagh@zonnet.nl>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2008-2010 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_FORWARD_H
+#define LIB2GEOM_SEEN_FORWARD_H
+
+namespace Geom {
+
+// primitives
+typedef double Coord;
+typedef int IntCoord;
+class Point;
+class IntPoint;
+class Line;
+class Ray;
+template <typename> class GenericInterval;
+template <typename> class GenericOptInterval;
+class Interval;
+class OptInterval;
+typedef GenericInterval<IntCoord> IntInterval;
+typedef GenericOptInterval<IntCoord> OptIntInterval;
+template <typename> class GenericRect;
+template <typename> class GenericOptRect;
+class Rect;
+class OptRect;
+typedef GenericRect<IntCoord> IntRect;
+typedef GenericOptRect<IntCoord> OptIntRect;
+
+// fragments
+class Linear;
+class Bezier;
+class SBasis;
+class Poly;
+
+// shapes
+class Circle;
+class Ellipse;
+class ConvexHull;
+
+// curves
+class Curve;
+class SBasisCurve;
+class BezierCurve;
+template <unsigned degree> class BezierCurveN;
+typedef BezierCurveN<1> LineSegment;
+typedef BezierCurveN<2> QuadraticBezier;
+typedef BezierCurveN<3> CubicBezier;
+class EllipticalArc;
+
+// paths and path sequences
+class Path;
+class PathVector;
+struct PathTime;
+class PathInterval;
+struct PathVectorTime;
+
+// errors
+class Exception;
+class LogicalError;
+class RangeError;
+class NotImplemented;
+class InvariantsViolation;
+class NotInvertible;
+class ContinuityError;
+
+// transforms
+class Affine;
+class Translate;
+class Rotate;
+class Scale;
+class HShear;
+class VShear;
+class Zoom;
+
+// templates
+template <typename> class D2;
+template <typename> class Piecewise;
+
+// misc
+class SVGPathSink;
+template <typename> class SVGPathGenerator;
+
+}
+
+#endif // SEEN_GEOM_FORWARD_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/generic-interval.h b/src/3rdparty/2geom/include/2geom/generic-interval.h
new file mode 100644
index 0000000..1d3cfdb
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/generic-interval.h
@@ -0,0 +1,374 @@
+/**
+ * @file
+ * @brief Closed interval of generic values
+ *//*
+ * Copyright 2011 Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_GENERIC_INTERVAL_H
+#define LIB2GEOM_SEEN_GENERIC_INTERVAL_H
+
+#include <cassert>
+#include <iostream>
+#include <optional>
+#include <2geom/coord.h>
+
+namespace Geom {
+
+template <typename C>
+class GenericOptInterval;
+
+/**
+ * @brief A range of numbers which is never empty.
+ * @ingroup Primitives
+ */
+template <typename C>
+class GenericInterval
+ : CoordTraits<C>::IntervalOps
+{
+ typedef typename CoordTraits<C>::IntervalType CInterval;
+ typedef GenericInterval<C> Self;
+protected:
+ C _b[2];
+public:
+ /// @name Create intervals.
+ /// @{
+ /** @brief Create an interval that contains only zero. */
+ GenericInterval() { _b[0] = 0; _b[1] = 0; }
+ /** @brief Create an interval that contains a single point. */
+ explicit GenericInterval(C u) { _b[0] = _b[1] = u; }
+ /** @brief Create an interval that contains all points between @c u and @c v. */
+ GenericInterval(C u, C v) {
+ if (u <= v) {
+ _b[0] = u; _b[1] = v;
+ } else {
+ _b[0] = v; _b[1] = u;
+ }
+ }
+
+ /** @brief Create an interval containing a range of values.
+ * The resulting interval will contain all values from the given range.
+ * The return type of iterators must be convertible to C. The given range
+ * must not be empty. For potentially empty ranges, see GenericOptInterval.
+ * @param start Beginning of the range
+ * @param end End of the range
+ * @return Interval that contains all values from [start, end). */
+ template <typename InputIterator>
+ static CInterval from_range(InputIterator start, InputIterator end) {
+ assert(start != end);
+ CInterval result(*start++);
+ for (; start != end; ++start) result.expandTo(*start);
+ return result;
+ }
+ /** @brief Create an interval from a C-style array of values it should contain. */
+ static CInterval from_array(C const *c, unsigned n) {
+ CInterval result = from_range(c, c+n);
+ return result;
+ }
+ /// @}
+
+ /// @name Inspect contained values.
+ /// @{
+ C min() const { return _b[0]; }
+ C max() const { return _b[1]; }
+ C extent() const { return max() - min(); }
+ C middle() const { return (max() + min()) / 2; }
+ bool isSingular() const { return min() == max(); }
+ C operator[](unsigned i) const { assert(i < 2); return _b[i]; }
+ C clamp(C val) const {
+ if (val < min()) return min();
+ if (val > max()) return max();
+ return val;
+ }
+ /// Return the closer end of the interval.
+ C nearestEnd(C val) const {
+ C dmin = std::abs(val - min()), dmax = std::abs(val - max());
+ return dmin <= dmax ? min() : max();
+ }
+ /// @}
+
+ /// @name Test coordinates and other intervals for inclusion.
+ /// @{
+ /** @brief Check whether the interval includes this number. */
+ bool contains(C val) const {
+ return min() <= val && val <= max();
+ }
+ /** @brief Check whether the interval includes the given interval. */
+ bool contains(CInterval const &val) const {
+ return min() <= val.min() && val.max() <= max();
+ }
+ /** @brief Check whether the intervals have any common elements. */
+ bool intersects(CInterval const &val) const {
+ return contains(val.min()) || contains(val.max()) || val.contains(*this);
+ }
+ /// @}
+
+ /// @name Modify the interval.
+ /// @{
+ //TODO: NaN handleage for the next two?
+ /** @brief Set the lower boundary of the interval.
+ * When the given number is larger than the interval's largest element,
+ * it will be reduced to the single number @c val. */
+ void setMin(C val) {
+ if(val > _b[1]) {
+ _b[0] = _b[1] = val;
+ } else {
+ _b[0] = val;
+ }
+ }
+ /** @brief Set the upper boundary of the interval.
+ * When the given number is smaller than the interval's smallest element,
+ * it will be reduced to the single number @c val. */
+ void setMax(C val) {
+ if(val < _b[0]) {
+ _b[1] = _b[0] = val;
+ } else {
+ _b[1] = val;
+ }
+ }
+ /// Set both ends of the interval simultaneously
+ void setEnds(C a, C b) {
+ if (a <= b) {
+ _b[0] = a;
+ _b[1] = b;
+ } else {
+ _b[0] = b;
+ _b[1] = a;
+ }
+ }
+ /** @brief Extend the interval to include the given number. */
+ void expandTo(C val) {
+ if(val < _b[0]) _b[0] = val;
+ if(val > _b[1]) _b[1] = val; //no else, as we want to handle NaN
+ }
+ /** @brief Expand or shrink the interval in both directions by the given amount.
+ * After this method, the interval's length (extent) will be increased by
+ * <code>amount * 2</code>. Negative values can be given; they will shrink the interval.
+ * Shrinking by a value larger than half the interval's length will create a degenerate
+ * interval containing only the midpoint of the original. */
+ void expandBy(C amount) {
+ _b[0] -= amount;
+ _b[1] += amount;
+ if (_b[0] > _b[1]) {
+ C halfway = (_b[0]+_b[1])/2;
+ _b[0] = _b[1] = halfway;
+ }
+ }
+ /** @brief Union the interval with another one.
+ * The resulting interval will contain all points of both intervals.
+ * It might also contain some points which didn't belong to either - this happens
+ * when the intervals did not have any common elements. */
+ void unionWith(CInterval const &a) {
+ if(a._b[0] < _b[0]) _b[0] = a._b[0];
+ if(a._b[1] > _b[1]) _b[1] = a._b[1];
+ }
+ /// @}
+
+ /// @name Operators
+ /// @{
+ //IMPL: OffsetableConcept
+ //TODO: rename output_type to something else in the concept
+ typedef C output_type;
+ /** @brief Offset the interval by a specified amount */
+ Self &operator+=(C amnt) {
+ _b[0] += amnt; _b[1] += amnt;
+ return *this;
+ }
+ /** @brief Offset the interval by the negation of the specified amount */
+ Self &operator-=(C amnt) {
+ _b[0] -= amnt; _b[1] -= amnt;
+ return *this;
+ }
+
+ /** @brief Return an interval mirrored about 0 */
+ Self operator-() const { Self r(-_b[1], -_b[0]); return r; }
+ // IMPL: AddableConcept
+ /** @brief Add two intervals.
+ * Sum is defined as the set of points that can be obtained by adding any two values
+ * from both operands: \f$S = \{x \in A, y \in B: x + y\}\f$ */
+ Self &operator+=(CInterval const &o) {
+ _b[0] += o._b[0];
+ _b[1] += o._b[1];
+ return *this;
+ }
+ /** @brief Subtract two intervals.
+ * Difference is defined as the set of points that can be obtained by subtracting
+ * any value from the second operand from any value from the first operand:
+ * \f$S = \{x \in A, y \in B: x - y\}\f$ */
+ Self &operator-=(CInterval const &o) {
+ // equal to *this += -o
+ _b[0] -= o._b[1];
+ _b[1] -= o._b[0];
+ return *this;
+ }
+ /** @brief Union two intervals.
+ * Note that the intersection-and-assignment operator is not defined,
+ * because the result of an intersection can be empty, while Interval cannot. */
+ Self &operator|=(CInterval const &o) {
+ unionWith(o);
+ return *this;
+ }
+ /** @brief Test for interval equality. */
+ bool operator==(CInterval const &other) const {
+ return min() == other.min() && max() == other.max();
+ }
+ /// @}
+};
+
+/** @brief Union two intervals
+ * @relates GenericInterval */
+template <typename C>
+inline GenericInterval<C> unify(GenericInterval<C> const &a, GenericInterval<C> const &b) {
+ return a | b;
+}
+
+/**
+ * @brief A range of numbers that can be empty.
+ * @ingroup Primitives
+ */
+template <typename C>
+class GenericOptInterval
+ : public std::optional<typename CoordTraits<C>::IntervalType>
+ , boost::orable< GenericOptInterval<C>
+ , boost::andable< GenericOptInterval<C>
+ > >
+{
+ typedef typename CoordTraits<C>::IntervalType CInterval;
+ typedef typename CoordTraits<C>::OptIntervalType OptCInterval;
+ typedef std::optional<CInterval> Base;
+public:
+ /// @name Create optionally empty intervals.
+ /// @{
+ /** @brief Create an empty interval. */
+ GenericOptInterval() : Base() {}
+ /** @brief Wrap an existing interval. */
+ GenericOptInterval(GenericInterval<C> const &a) : Base(CInterval(a)) {}
+ /** @brief Create an interval containing a single point. */
+ GenericOptInterval(C u) : Base(CInterval(u)) {}
+ /** @brief Create an interval containing a range of numbers. */
+ GenericOptInterval(C u, C v) : Base(CInterval(u,v)) {}
+
+ /** @brief Create a possibly empty interval containing a range of values.
+ * The resulting interval will contain all values from the given range.
+ * The return type of iterators must be convertible to C. The given range
+ * may be empty.
+ * @param start Beginning of the range
+ * @param end End of the range
+ * @return Interval that contains all values from [start, end), or nothing if the range
+ * is empty. */
+ template <typename InputIterator>
+ static GenericOptInterval<C> from_range(InputIterator start, InputIterator end) {
+ if (start == end) {
+ GenericOptInterval<C> ret;
+ return ret;
+ }
+ GenericOptInterval<C> ret(CInterval::from_range(start, end));
+ return ret;
+ }
+ /// @}
+
+ /** @brief Check whether this interval is empty. */
+ bool empty() { return !*this; }
+
+ /** @brief Union with another interval, gracefully handling empty ones. */
+ void unionWith(GenericOptInterval<C> const &a) {
+ if (a) {
+ if (*this) { // check that we are not empty
+ (*this)->unionWith(*a);
+ } else {
+ *this = *a;
+ }
+ }
+ }
+ void intersectWith(GenericOptInterval<C> const &o) {
+ if (o && *this) {
+ if (!*this) return;
+ C u = std::max((*this)->min(), o->min());
+ C v = std::min((*this)->max(), o->max());
+ if (u <= v) {
+ *this = CInterval(u, v);
+ return;
+ }
+ }
+ (*static_cast<Base*>(this)) = std::nullopt;
+ }
+ GenericOptInterval<C> &operator|=(OptCInterval const &o) {
+ unionWith(o);
+ return *this;
+ }
+ GenericOptInterval<C> &operator&=(OptCInterval const &o) {
+ intersectWith(o);
+ return *this;
+ }
+
+ // The equality operators inherited from std::optional don't work with derived types, because
+ // the template overload ignores that the devived type is also an optional. It would result in
+ // `GenericInterval() != GenericInterval()` being true.
+ template <typename U, typename = std::enable_if_t<std::is_base_of_v<Base, U>>>
+ bool operator==(U const &other) const
+ {
+ return static_cast<Base const &>(*this) == static_cast<Base const &>(other);
+ }
+ template <typename U, typename = std::enable_if_t<std::is_base_of_v<Base, U>>>
+ bool operator!=(U const &other) const
+ {
+ return static_cast<Base const &>(*this) != static_cast<Base const &>(other);
+ }
+};
+
+/** @brief Intersect two intervals and return a possibly empty range of numbers
+ * @relates GenericOptInterval */
+template <typename C>
+inline GenericOptInterval<C> intersect(GenericInterval<C> const &a, GenericInterval<C> const &b) {
+ return GenericOptInterval<C>(a) & GenericOptInterval<C>(b);
+}
+/** @brief Intersect two intervals and return a possibly empty range of numbers
+ * @relates GenericOptInterval */
+template <typename C>
+inline GenericOptInterval<C> operator&(GenericInterval<C> const &a, GenericInterval<C> const &b) {
+ return GenericOptInterval<C>(a) & GenericOptInterval<C>(b);
+}
+
+template <typename C>
+inline std::ostream &operator<< (std::ostream &os,
+ Geom::GenericInterval<C> const &I) {
+ os << "Interval("<<I.min() << ", "<<I.max() << ")";
+ return os;
+}
+
+} // namespace Geom
+#endif // !LIB2GEOM_SEEN_GENERIC_INTERVAL_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/generic-rect.h b/src/3rdparty/2geom/include/2geom/generic-rect.h
new file mode 100644
index 0000000..4524d43
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/generic-rect.h
@@ -0,0 +1,547 @@
+/**
+ * \file
+ * \brief Axis-aligned rectangle
+ *//*
+ * Authors:
+ * Michael Sloan <mgsloan@gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ * Copyright 2007-2011 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, output to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * Authors of original rect class:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Nathan Hurst <njh@mail.csse.monash.edu.au>
+ * bulia byak <buliabyak@users.sf.net>
+ * MenTaLguY <mental@rydia.net>
+ */
+
+#ifndef LIB2GEOM_SEEN_GENERIC_RECT_H
+#define LIB2GEOM_SEEN_GENERIC_RECT_H
+
+#include <limits>
+#include <iostream>
+#include <optional>
+#include <2geom/coord.h>
+
+namespace Geom {
+
+template <typename C>
+class GenericOptRect;
+
+/**
+ * @brief Axis aligned, non-empty, generic rectangle.
+ * @ingroup Primitives
+ */
+template <typename C>
+class GenericRect
+ : CoordTraits<C>::RectOps
+{
+ typedef typename CoordTraits<C>::IntervalType CInterval;
+ typedef typename CoordTraits<C>::PointType CPoint;
+ typedef typename CoordTraits<C>::RectType CRect;
+ typedef typename CoordTraits<C>::OptRectType OptCRect;
+protected:
+ CInterval f[2];
+public:
+ typedef CInterval D1Value;
+ typedef CInterval &D1Reference;
+ typedef CInterval const &D1ConstReference;
+
+ /// @name Create rectangles.
+ /// @{
+ /** @brief Create a rectangle that contains only the point at (0,0). */
+ GenericRect() { f[X] = f[Y] = CInterval(); }
+ /** @brief Create a rectangle from X and Y intervals. */
+ GenericRect(CInterval const &a, CInterval const &b) {
+ f[X] = a;
+ f[Y] = b;
+ }
+ /** @brief Create a rectangle from two points. */
+ GenericRect(CPoint const &a, CPoint const &b) {
+ f[X] = CInterval(a[X], b[X]);
+ f[Y] = CInterval(a[Y], b[Y]);
+ }
+ /** @brief Create rectangle from coordinates of two points. */
+ GenericRect(C x0, C y0, C x1, C y1) {
+ f[X] = CInterval(x0, x1);
+ f[Y] = CInterval(y0, y1);
+ }
+ /** @brief Create a rectangle from a range of points.
+ * The resulting rectangle will contain all points from the range.
+ * The return type of iterators must be convertible to Point.
+ * The range must not be empty. For possibly empty ranges, see OptRect.
+ * @param start Beginning of the range
+ * @param end End of the range
+ * @return Rectangle that contains all points from [start, end). */
+ template <typename InputIterator>
+ static CRect from_range(InputIterator start, InputIterator end) {
+ assert(start != end);
+ CPoint p1 = *start++;
+ CRect result(p1, p1);
+ for (; start != end; ++start) {
+ result.expandTo(*start);
+ }
+ return result;
+ }
+ /** @brief Create a rectangle from a C-style array of points it should contain. */
+ static CRect from_array(CPoint const *c, unsigned n) {
+ CRect result = GenericRect<C>::from_range(c, c+n);
+ return result;
+ }
+ /** @brief Create rectangle from origin and dimensions. */
+ static CRect from_xywh(C x, C y, C w, C h) {
+ CPoint xy(x, y);
+ CPoint wh(w, h);
+ CRect result(xy, xy + wh);
+ return result;
+ }
+ /** @brief Create rectangle from origin and dimensions. */
+ static CRect from_xywh(CPoint const &xy, CPoint const &wh) {
+ CRect result(xy, xy + wh);
+ return result;
+ }
+ /// Create infinite rectangle.
+ static CRect infinite() {
+ CPoint p0(std::numeric_limits<C>::min(), std::numeric_limits<C>::min());
+ CPoint p1(std::numeric_limits<C>::max(), std::numeric_limits<C>::max());
+ CRect result(p0, p1);
+ return result;
+ }
+ /// @}
+
+ /// @name Inspect dimensions.
+ /// @{
+ CInterval &operator[](unsigned i) { return f[i]; }
+ CInterval const &operator[](unsigned i) const { return f[i]; }
+ CInterval &operator[](Dim2 d) { return f[d]; }
+ CInterval const &operator[](Dim2 d) const { return f[d]; }
+
+ /** @brief Get the corner of the rectangle with smallest coordinate values.
+ * In 2Geom standard coordinate system, this means upper left. */
+ CPoint min() const { CPoint p(f[X].min(), f[Y].min()); return p; }
+ /** @brief Get the corner of the rectangle with largest coordinate values.
+ * In 2Geom standard coordinate system, this means lower right. */
+ CPoint max() const { CPoint p(f[X].max(), f[Y].max()); return p; }
+ /** @brief Return the n-th corner of the rectangle.
+ * Returns corners in the direction of growing angles, starting from
+ * the one given by min(). For the standard coordinate system used
+ * in 2Geom (+Y downwards), this means clockwise starting from
+ * the upper left. */
+ CPoint corner(unsigned i) const {
+ switch(i % 4) {
+ case 0: return CPoint(f[X].min(), f[Y].min());
+ case 1: return CPoint(f[X].max(), f[Y].min());
+ case 2: return CPoint(f[X].max(), f[Y].max());
+ default: return CPoint(f[X].min(), f[Y].max());
+ }
+ }
+
+ //We should probably remove these - they're coord sys gnostic
+ /** @brief Return top coordinate of the rectangle (+Y is downwards). */
+ C top() const { return f[Y].min(); }
+ /** @brief Return bottom coordinate of the rectangle (+Y is downwards). */
+ C bottom() const { return f[Y].max(); }
+ /** @brief Return leftmost coordinate of the rectangle (+X is to the right). */
+ C left() const { return f[X].min(); }
+ /** @brief Return rightmost coordinate of the rectangle (+X is to the right). */
+ C right() const { return f[X].max(); }
+
+ /** @brief Get the horizontal extent of the rectangle. */
+ C width() const { return f[X].extent(); }
+ /** @brief Get the vertical extent of the rectangle. */
+ C height() const { return f[Y].extent(); }
+ /** @brief Get the ratio of width to height of the rectangle. */
+ Coord aspectRatio() const { return Coord(width()) / Coord(height()); }
+
+ /** @brief Get rectangle's width and height as a point.
+ * @return Point with X coordinate corresponding to the width and the Y coordinate
+ * corresponding to the height of the rectangle. */
+ CPoint dimensions() const { return CPoint(f[X].extent(), f[Y].extent()); }
+ /** @brief Get the point in the geometric center of the rectangle. */
+ CPoint midpoint() const { return CPoint(f[X].middle(), f[Y].middle()); }
+
+ /** @brief Compute rectangle's area. */
+ C area() const { return f[X].extent() * f[Y].extent(); }
+ /** @brief Check whether the rectangle has zero area. */
+ bool hasZeroArea() const { return f[X].isSingular() || f[Y].isSingular(); }
+
+ /** @brief Get the larger extent (width or height) of the rectangle. */
+ C maxExtent() const { return std::max(f[X].extent(), f[Y].extent()); }
+ /** @brief Get the smaller extent (width or height) of the rectangle. */
+ C minExtent() const { return std::min(f[X].extent(), f[Y].extent()); }
+
+ /** @brief Get rectangle's distance SQUARED away from the given point **/
+ C distanceSq(const CPoint pt) const {
+ auto v = clamp(pt) - pt;
+ return v.x() * v.x() + v.y() * v.y();
+ }
+
+ /** @brief Clamp point to the rectangle. */
+ CPoint clamp(CPoint const &p) const {
+ CPoint result(f[X].clamp(p[X]), f[Y].clamp(p[Y]));
+ return result;
+ }
+ /** @brief Get the nearest point on the edge of the rectangle. */
+ CPoint nearestEdgePoint(CPoint const &p) const {
+ CPoint result = p;
+ if (!contains(p)) {
+ result = clamp(p);
+ } else {
+ C cx = f[X].nearestEnd(p[X]);
+ C cy = f[Y].nearestEnd(p[Y]);
+ if (std::abs(cx - p[X]) <= std::abs(cy - p[Y])) {
+ result[X] = cx;
+ } else {
+ result[Y] = cy;
+ }
+ }
+ return result;
+ }
+ /// @}
+
+ /// @name Test other rectangles and points for inclusion.
+ /// @{
+ /** @brief Check whether the rectangles have any common points. */
+ bool intersects(GenericRect<C> const &r) const {
+ return f[X].intersects(r[X]) && f[Y].intersects(r[Y]);
+ }
+ /** @brief Check whether the rectangle includes all points in the given rectangle. */
+ bool contains(GenericRect<C> const &r) const {
+ return f[X].contains(r[X]) && f[Y].contains(r[Y]);
+ }
+
+ /** @brief Check whether the rectangles have any common points.
+ * Empty rectangles will not intersect with any other rectangle. */
+ inline bool intersects(OptCRect const &r) const;
+ /** @brief Check whether the rectangle includes all points in the given rectangle.
+ * Empty rectangles will be contained in any non-empty rectangle. */
+ inline bool contains(OptCRect const &r) const;
+
+ /** @brief Check whether the given point is within the rectangle. */
+ bool contains(CPoint const &p) const {
+ return f[X].contains(p[X]) && f[Y].contains(p[Y]);
+ }
+ /// @}
+
+ /// @name Modify the rectangle.
+ /// @{
+ /** @brief Set the minimum X coordinate of the rectangle. */
+ void setLeft(C val) {
+ f[X].setMin(val);
+ }
+ /** @brief Set the maximum X coordinate of the rectangle. */
+ void setRight(C val) {
+ f[X].setMax(val);
+ }
+ /** @brief Set the minimum Y coordinate of the rectangle. */
+ void setTop(C val) {
+ f[Y].setMin(val);
+ }
+ /** @brief Set the maximum Y coordinate of the rectangle. */
+ void setBottom(C val) {
+ f[Y].setMax(val);
+ }
+ /** @brief Set the upper left point of the rectangle. */
+ void setMin(CPoint const &p) {
+ f[X].setMin(p[X]);
+ f[Y].setMin(p[Y]);
+ }
+ /** @brief Set the lower right point of the rectangle. */
+ void setMax(CPoint const &p) {
+ f[X].setMax(p[X]);
+ f[Y].setMax(p[Y]);
+ }
+ /** @brief Enlarge the rectangle to contain the given point. */
+ void expandTo(CPoint const &p) {
+ f[X].expandTo(p[X]); f[Y].expandTo(p[Y]);
+ }
+ /** @brief Enlarge the rectangle to contain the argument. */
+ void unionWith(CRect const &b) {
+ f[X].unionWith(b[X]); f[Y].unionWith(b[Y]);
+ }
+ /** @brief Enlarge the rectangle to contain the argument.
+ * Unioning with an empty rectangle results in no changes. */
+ void unionWith(OptCRect const &b);
+
+ /** @brief Expand the rectangle in both directions by the specified amount.
+ * Note that this is different from scaling. Negative values will shrink the
+ * rectangle. If <code>-amount</code> is larger than
+ * half of the width, the X interval will contain only the X coordinate
+ * of the midpoint; same for height. */
+ void expandBy(C amount) {
+ expandBy(amount, amount);
+ }
+ /** @brief Expand the rectangle in both directions.
+ * Note that this is different from scaling. Negative values will shrink the
+ * rectangle. If <code>-x</code> is larger than
+ * half of the width, the X interval will contain only the X coordinate
+ * of the midpoint; same for height. */
+ void expandBy(C x, C y) {
+ f[X].expandBy(x); f[Y].expandBy(y);
+ }
+ /** @brief Expand the rectangle by the coordinates of the given point.
+ * This will expand the width by the X coordinate of the point in both directions
+ * and the height by Y coordinate of the point. Negative coordinate values will
+ * shrink the rectangle. If <code>-p[X]</code> is larger than half of the width,
+ * the X interval will contain only the X coordinate of the midpoint;
+ * same for height. */
+ void expandBy(CPoint const &p) {
+ expandBy(p[X], p[Y]);
+ }
+ /// @}
+
+ /// @name Operators
+ /// @{
+ /** @brief Offset the rectangle by a vector. */
+ GenericRect<C> &operator+=(CPoint const &p) {
+ f[X] += p[X];
+ f[Y] += p[Y];
+ return *this;
+ }
+ /** @brief Offset the rectangle by the negation of a vector. */
+ GenericRect<C> &operator-=(CPoint const &p) {
+ f[X] -= p[X];
+ f[Y] -= p[Y];
+ return *this;
+ }
+ /** @brief Union two rectangles. */
+ GenericRect<C> &operator|=(CRect const &o) {
+ unionWith(o);
+ return *this;
+ }
+ GenericRect<C> &operator|=(OptCRect const &o) {
+ unionWith(o);
+ return *this;
+ }
+ /** @brief Test for equality of rectangles. */
+ bool operator==(CRect const &o) const { return f[X] == o[X] && f[Y] == o[Y]; }
+ /// @}
+};
+
+/**
+ * @brief Axis-aligned generic rectangle that can be empty.
+ * @ingroup Primitives
+ */
+template <typename C>
+class GenericOptRect
+ : public std::optional<typename CoordTraits<C>::RectType>
+ , boost::equality_comparable< typename CoordTraits<C>::OptRectType
+ , boost::equality_comparable< typename CoordTraits<C>::OptRectType, typename CoordTraits<C>::RectType
+ , boost::orable< typename CoordTraits<C>::OptRectType
+ , boost::andable< typename CoordTraits<C>::OptRectType
+ , boost::andable< typename CoordTraits<C>::OptRectType, typename CoordTraits<C>::RectType
+ > > > > >
+{
+ typedef typename CoordTraits<C>::IntervalType CInterval;
+ typedef typename CoordTraits<C>::OptIntervalType OptCInterval;
+ typedef typename CoordTraits<C>::PointType CPoint;
+ typedef typename CoordTraits<C>::RectType CRect;
+ typedef typename CoordTraits<C>::OptRectType OptCRect;
+ typedef std::optional<CRect> Base;
+public:
+ typedef CInterval D1Value;
+ typedef CInterval &D1Reference;
+ typedef CInterval const &D1ConstReference;
+
+ /// @name Create potentially empty rectangles.
+ /// @{
+ GenericOptRect() : Base() {}
+ GenericOptRect(GenericRect<C> const &a) : Base(CRect(a)) {}
+ GenericOptRect(CPoint const &a, CPoint const &b) : Base(CRect(a, b)) {}
+ GenericOptRect(C x0, C y0, C x1, C y1) : Base(CRect(x0, y0, x1, y1)) {}
+ /// Creates an empty OptRect when one of the argument intervals is empty.
+ GenericOptRect(OptCInterval const &x_int, OptCInterval const &y_int) {
+ if (x_int && y_int) {
+ *this = CRect(*x_int, *y_int);
+ }
+ // else, stay empty.
+ }
+
+ /** @brief Create a rectangle from a range of points.
+ * The resulting rectangle will contain all points from the range.
+ * If the range contains no points, the result will be an empty rectangle.
+ * The return type of iterators must be convertible to the corresponding
+ * point type (Point or IntPoint).
+ * @param start Beginning of the range
+ * @param end End of the range
+ * @return Rectangle that contains all points from [start, end). */
+ template <typename InputIterator>
+ static OptCRect from_range(InputIterator start, InputIterator end) {
+ OptCRect result;
+ for (; start != end; ++start) {
+ result.expandTo(*start);
+ }
+ return result;
+ }
+ /// @}
+
+ /// @name Check other rectangles and points for inclusion.
+ /// @{
+ /** @brief Check for emptiness. */
+ inline bool empty() const { return !*this; };
+ /** @brief Check whether the rectangles have any common points.
+ * Empty rectangles will not intersect with any other rectangle. */
+ bool intersects(CRect const &r) const { return r.intersects(*this); }
+ /** @brief Check whether the rectangle includes all points in the given rectangle.
+ * Empty rectangles will be contained in any non-empty rectangle. */
+ bool contains(CRect const &r) const { return *this && (*this)->contains(r); }
+
+ /** @brief Check whether the rectangles have any common points.
+ * Empty rectangles will not intersect with any other rectangle.
+ * Two empty rectangles will not intersect each other. */
+ bool intersects(OptCRect const &r) const { return *this && (*this)->intersects(r); }
+ /** @brief Check whether the rectangle includes all points in the given rectangle.
+ * Empty rectangles will be contained in any non-empty rectangle.
+ * An empty rectangle will not contain other empty rectangles. */
+ bool contains(OptCRect const &r) const { return *this && (*this)->contains(r); }
+
+ /** @brief Check whether the given point is within the rectangle.
+ * An empty rectangle will not contain any points. */
+ bool contains(CPoint const &p) const { return *this && (*this)->contains(p); }
+ /// @}
+
+ /** @brief Returns an empty optional (testing false) if the rectangle has zero area. */
+ OptCRect regularized() const {
+ return *this && !(*this)->hasZeroArea() ? *this : OptCRect();
+ }
+
+ /// @name Modify the potentially empty rectangle.
+ /// @{
+ /** @brief Enlarge the rectangle to contain the argument.
+ * If this rectangle is empty, after callng this method it will
+ * be equal to the argument. */
+ void unionWith(CRect const &b) {
+ if (*this) {
+ (*this)->unionWith(b);
+ } else {
+ *this = b;
+ }
+ }
+ /** @brief Enlarge the rectangle to contain the argument.
+ * Unioning with an empty rectangle results in no changes.
+ * If this rectangle is empty, after calling this method it will
+ * be equal to the argument. */
+ void unionWith(OptCRect const &b) {
+ if (b) unionWith(*b);
+ }
+ /** @brief Leave only the area overlapping with the argument.
+ * If the rectangles do not have any points in common, after calling
+ * this method the rectangle will be empty. */
+ void intersectWith(CRect const &b) {
+ if (!*this) return;
+ OptCInterval x = (**this)[X] & b[X], y = (**this)[Y] & b[Y];
+ if (x && y) {
+ *this = CRect(*x, *y);
+ } else {
+ *(static_cast<Base*>(this)) = std::nullopt;
+ }
+ }
+ /** @brief Leave only the area overlapping with the argument.
+ * If the argument is empty or the rectangles do not have any points
+ * in common, after calling this method the rectangle will be empty. */
+ void intersectWith(OptCRect const &b) {
+ if (b) {
+ intersectWith(*b);
+ } else {
+ *(static_cast<Base*>(this)) = std::nullopt;
+ }
+ }
+ /** @brief Create or enlarge the rectangle to contain the given point.
+ * If the rectangle is empty, after calling this method it will be non-empty
+ * and it will contain only the given point. */
+ void expandTo(CPoint const &p) {
+ if (*this) {
+ (*this)->expandTo(p);
+ } else {
+ *this = CRect(p, p);
+ }
+ }
+ /// @}
+
+ /// @name Operators
+ /// @{
+ /** @brief Union with @a b */
+ GenericOptRect<C> &operator|=(OptCRect const &b) {
+ unionWith(b);
+ return *this;
+ }
+ /** @brief Intersect with @a b */
+ GenericOptRect<C> &operator&=(CRect const &b) {
+ intersectWith(b);
+ return *this;
+ }
+ /** @brief Intersect with @a b */
+ GenericOptRect<C> &operator&=(OptCRect const &b) {
+ intersectWith(b);
+ return *this;
+ }
+ /** @brief Test for equality.
+ * All empty rectangles are equal. */
+ bool operator==(OptCRect const &other) const {
+ if (!*this != !other) return false;
+ return *this ? (**this == *other) : true;
+ }
+ bool operator==(CRect const &other) const {
+ if (!*this) return false;
+ return **this == other;
+ }
+ /// @}
+};
+
+template <typename C>
+inline void GenericRect<C>::unionWith(OptCRect const &b) {
+ if (b) {
+ unionWith(*b);
+ }
+}
+template <typename C>
+inline bool GenericRect<C>::intersects(OptCRect const &r) const {
+ return r && intersects(*r);
+}
+template <typename C>
+inline bool GenericRect<C>::contains(OptCRect const &r) const {
+ return !r || contains(*r);
+}
+
+template <typename C>
+inline std::ostream &operator<<(std::ostream &out, GenericRect<C> const &r) {
+ out << "Rect " << r[X] << " x " << r[Y];
+ return out;
+}
+
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_RECT_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/geom.h b/src/3rdparty/2geom/include/2geom/geom.h
new file mode 100644
index 0000000..7393ff4
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/geom.h
@@ -0,0 +1,66 @@
+/**
+ * \file
+ * \brief Various geometrical calculations
+ *
+ * Authors:
+ * Nathan Hurst <njh@mail.csse.monash.edu.au>
+ *
+ * Copyright (C) 1999-2002 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+#ifndef LIB2GEOM_SEEN_GEOM_H
+#define LIB2GEOM_SEEN_GEOM_H
+
+//TODO: move somewhere else
+
+#include <vector>
+#include <2geom/forward.h>
+#include <optional>
+#include <2geom/bezier-curve.h>
+#include <2geom/line.h>
+
+namespace Geom {
+
+std::optional<Geom::LineSegment>
+rect_line_intersect(Geom::Rect &r,
+ Geom::LineSegment ls);
+
+int centroid(std::vector<Geom::Point> const &p, Geom::Point& centroid, double &area);
+
+}
+
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/int-interval.h b/src/3rdparty/2geom/include/2geom/int-interval.h
new file mode 100644
index 0000000..0faf48d
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/int-interval.h
@@ -0,0 +1,63 @@
+/**
+ * \file
+ * \brief Closed interval of integer values
+ *//*
+ * Copyright 2011 Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_INT_INTERVAL_H
+#define LIB2GEOM_SEEN_INT_INTERVAL_H
+
+#include <2geom/coord.h>
+#include <2geom/generic-interval.h>
+
+namespace Geom {
+
+/**
+ * @brief Range of integers that is never empty.
+ * @ingroup Primitives
+ */
+typedef GenericInterval<IntCoord> IntInterval;
+
+/**
+ * @brief Range of integers that can be empty.
+ * @ingroup Primitives
+ */
+typedef GenericOptInterval<IntCoord> OptIntInterval;
+
+} // namespace Geom
+#endif // !LIB2GEOM_SEEN_INT_INTERVAL_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/int-point.h b/src/3rdparty/2geom/include/2geom/int-point.h
new file mode 100644
index 0000000..6dbed11
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/int-point.h
@@ -0,0 +1,202 @@
+/**
+ * \file
+ * \brief Cartesian point / 2D vector with integer coordinates
+ *//*
+ * Copyright 2011 Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_INT_POINT_H
+#define LIB2GEOM_SEEN_INT_POINT_H
+
+#include <stdexcept>
+#include <boost/operators.hpp>
+#include <2geom/coord.h>
+
+namespace Geom {
+
+/**
+ * @brief Two-dimensional point with integer coordinates.
+ *
+ * This class is an exact equivalent of Point, except it stores integer coordinates.
+ * Integer points are useful in contexts related to rasterized graphics, for example
+ * for bounding boxes when rendering SVG.
+ *
+ * @see Point
+ * @ingroup Primitives */
+class IntPoint
+ : boost::additive< IntPoint
+ , boost::totally_ordered< IntPoint
+ , boost::multiplicative< IntPoint, IntCoord
+ , boost::multiplicative< IntPoint
+ > > > >
+{
+ IntCoord _pt[2] = { 0, 0 };
+public:
+ /// @name Create integer points
+ /// @{
+ /** Construct a point at the origin. */
+ IntPoint() = default;
+ /** Construct a point from its coordinates. */
+ IntPoint(IntCoord x, IntCoord y)
+ : _pt{ x, y }
+ {}
+ /// @}
+
+ /// @name Access the coordinates of a point
+ /// @{
+ IntCoord operator[](unsigned i) const {
+ if ( i > Y ) throw std::out_of_range("index out of range");
+ return _pt[i];
+ }
+ IntCoord &operator[](unsigned i) {
+ if ( i > Y ) throw std::out_of_range("index out of range");
+ return _pt[i];
+ }
+ IntCoord operator[](Dim2 d) const { return _pt[d]; }
+ IntCoord &operator[](Dim2 d) { return _pt[d]; }
+
+ IntCoord x() const noexcept { return _pt[X]; }
+ IntCoord &x() noexcept { return _pt[X]; }
+ IntCoord y() const noexcept { return _pt[Y]; }
+ IntCoord &y() noexcept { return _pt[Y]; }
+ /// @}
+
+ /// @name Vector-like arithmetic operations
+ /// @{
+ IntPoint operator-() const {
+ return IntPoint(-_pt[X], -_pt[Y]);
+ }
+ IntPoint &operator+=(IntPoint const &o) {
+ _pt[X] += o._pt[X];
+ _pt[Y] += o._pt[Y];
+ return *this;
+ }
+ IntPoint &operator-=(IntPoint const &o) {
+ _pt[X] -= o._pt[X];
+ _pt[Y] -= o._pt[Y];
+ return *this;
+ }
+ IntPoint &operator*=(IntPoint const &o) {
+ _pt[X] *= o._pt[X];
+ _pt[Y] *= o._pt[Y];
+ return *this;
+ }
+ IntPoint &operator*=(IntCoord o) {
+ _pt[X] *= o;
+ _pt[Y] *= o;
+ return *this;
+ }
+ IntPoint &operator/=(IntPoint const &o) {
+ _pt[X] /= o._pt[X];
+ _pt[Y] /= o._pt[Y];
+ return *this;
+ }
+ IntPoint &operator/=(IntCoord o) {
+ _pt[X] /= o;
+ _pt[Y] /= o;
+ return *this;
+ }
+ /// @}
+
+ /// @name Various utilities
+ /// @{
+ /** @brief Equality operator. */
+ bool operator==(IntPoint const &in_pnt) const {
+ return ((_pt[X] == in_pnt[X]) && (_pt[Y] == in_pnt[Y]));
+ }
+ /** @brief Lexicographical ordering for points.
+ * Y coordinate is regarded as more significant. When sorting according to this
+ * ordering, the points will be sorted according to the Y coordinate, and within
+ * points with the same Y coordinate according to the X coordinate. */
+ bool operator<(IntPoint const &p) const {
+ return ( ( _pt[Y] < p[Y] ) ||
+ (( _pt[Y] == p[Y] ) && ( _pt[X] < p[X] )));
+ }
+ /// @}
+
+ /** @brief Lexicographical ordering functor.
+ * @param d The more significant dimension */
+ template <Dim2 d> struct LexLess;
+ /** @brief Lexicographical ordering functor.
+ * @param d The more significant dimension */
+ template <Dim2 d> struct LexGreater;
+ /** @brief Lexicographical ordering functor with runtime dimension. */
+ struct LexLessRt {
+ LexLessRt(Dim2 d) : dim(d) {}
+ inline bool operator()(IntPoint const &a, IntPoint const &b) const;
+ private:
+ Dim2 dim;
+ };
+ /** @brief Lexicographical ordering functor with runtime dimension. */
+ struct LexGreaterRt {
+ LexGreaterRt(Dim2 d) : dim(d) {}
+ inline bool operator()(IntPoint const &a, IntPoint const &b) const;
+ private:
+ Dim2 dim;
+ };
+};
+
+template<> struct IntPoint::LexLess<X> {
+ bool operator()(IntPoint const &a, IntPoint const &b) const {
+ return a[X] < b[X] || (a[X] == b[X] && a[Y] < b[Y]);
+ }
+};
+template<> struct IntPoint::LexLess<Y> {
+ bool operator()(IntPoint const &a, IntPoint const &b) const {
+ return a[Y] < b[Y] || (a[Y] == b[Y] && a[X] < b[X]);
+ }
+};
+template<> struct IntPoint::LexGreater<X> {
+ bool operator()(IntPoint const &a, IntPoint const &b) const {
+ return a[X] > b[X] || (a[X] == b[X] && a[Y] > b[Y]);
+ }
+};
+template<> struct IntPoint::LexGreater<Y> {
+ bool operator()(IntPoint const &a, IntPoint const &b) const {
+ return a[Y] > b[Y] || (a[Y] == b[Y] && a[X] > b[X]);
+ }
+};
+inline bool IntPoint::LexLessRt::operator()(IntPoint const &a, IntPoint const &b) const {
+ return dim ? IntPoint::LexLess<Y>()(a, b) : IntPoint::LexLess<X>()(a, b);
+}
+inline bool IntPoint::LexGreaterRt::operator()(IntPoint const &a, IntPoint const &b) const {
+ return dim ? IntPoint::LexGreater<Y>()(a, b) : IntPoint::LexGreater<X>()(a, b);
+}
+
+} // namespace Geom
+
+#endif // !SEEN_GEOM_INT_POINT_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/int-rect.h b/src/3rdparty/2geom/include/2geom/int-rect.h
new file mode 100644
index 0000000..567d42d
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/int-rect.h
@@ -0,0 +1,75 @@
+/**
+ * \file
+ * \brief Axis-aligned rectangle with integer coordinates
+ *//*
+ * Copyright 2011 Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_INT_RECT_H
+#define LIB2GEOM_SEEN_INT_RECT_H
+
+#include <2geom/coord.h>
+#include <2geom/int-interval.h>
+#include <2geom/generic-rect.h>
+
+namespace Geom {
+
+typedef GenericRect<IntCoord> IntRect;
+typedef GenericOptRect<IntCoord> OptIntRect;
+
+// the functions below do not work when defined generically
+inline OptIntRect operator&(IntRect const &a, IntRect const &b) {
+ OptIntRect ret(a);
+ ret.intersectWith(b);
+ return ret;
+}
+inline OptIntRect intersect(IntRect const &a, IntRect const &b) {
+ return a & b;
+}
+inline OptIntRect intersect(OptIntRect const &a, OptIntRect const &b) {
+ return a & b;
+}
+inline IntRect unify(IntRect const &a, IntRect const &b) {
+ return a | b;
+}
+inline OptIntRect unify(OptIntRect const &a, OptIntRect const &b) {
+ return a | b;
+}
+
+} // end namespace Geom
+
+#endif // !LIB2GEOM_SEEN_INT_RECT_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/intersection-graph.h b/src/3rdparty/2geom/include/2geom/intersection-graph.h
new file mode 100644
index 0000000..940c43c
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/intersection-graph.h
@@ -0,0 +1,259 @@
+/**
+ * \file
+ * \brief Path intersection graph
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef SEEN_LIB2GEOM_INTERSECTION_GRAPH_H
+#define SEEN_LIB2GEOM_INTERSECTION_GRAPH_H
+
+#include <set>
+#include <vector>
+#include <boost/ptr_container/ptr_vector.hpp>
+#include <boost/intrusive/list.hpp>
+#include <2geom/forward.h>
+#include <2geom/pathvector.h>
+
+namespace Geom {
+
+/** @class PathIntersectionGraph
+ * @brief Intermediate data for computing Boolean operations on paths.
+ *
+ * This class implements the Greiner-Hormann clipping algorithm,
+ * with improvements inspired by Foster and Overfelt as well as some
+ * original contributions.
+ *
+ * For the purposes of boolean operations, a shape is defined as a PathVector
+ * using the "even-odd" rule, i.e., regions with odd winding are considered part
+ * of the shape, whereas regions with even winding are not.
+ *
+ * For this reason, the two path-vectors are sometimes called "shapes" or "operands" of
+ * the boolean operation. Each path-vector may contain several paths, which are called
+ * either "paths" or "components" in the documentation.
+ *
+ * @ingroup Paths
+ */
+class PathIntersectionGraph
+{
+ // this is called PathIntersectionGraph so that we can also have a class for polygons,
+ // e.g. PolygonIntersectionGraph, which is going to be significantly faster
+public:
+ /** @brief Construct a path intersection graph for two shapes described via their boundaries.
+ * The boundaries are passed as path-vectors.
+ *
+ * @param a – the first operand, also referred to as operand A.
+ * @param b – the second operand, also referred to as operand B.
+ * @param precision – precision setting used for intersection calculations.
+ */
+ PathIntersectionGraph(PathVector const &a, PathVector const &b, Coord precision = EPSILON);
+
+ /**
+ * @brief Get the union of the shapes, A ∪ B.
+ *
+ * A point belongs to the union if and only if it belongs to at least one of the operands.
+ *
+ * @return A path-vector describing the union of the operands A and B.
+ */
+ PathVector getUnion();
+
+ /**
+ * @brief Get the intersection of the shapes, A ∩ B.
+ *
+ * A point belongs to the intersection if and only if it belongs to both shapes.
+ *
+ * @return A path-vector describing the intersection of the operands A and B.
+ */
+ PathVector getIntersection();
+
+ /**
+ * @brief Get the difference of the shapes, A ∖ B.
+ *
+ * A point belongs to the difference if and only if it belongs to A but not to B.
+ *
+ * @return A path-vector describing the difference of the operands A and B.
+ */
+ PathVector getAminusB();
+
+ /**
+ * @brief Get the opposite difference of the shapes, B ∖ A.
+ *
+ * A point belongs to the difference if and only if it belongs to B but not to A.
+ *
+ * @return A path-vector describing the difference of the operands B and A.
+ */
+ PathVector getBminusA();
+
+ /**
+ * @brief Get the symmetric difference of the shapes, A ∆ B.
+ *
+ * A point belongs to the symmetric difference if and only if it belongs to one of the two
+ * shapes A or B, but not both. This is equivalent to the logical XOR operation: the elements
+ * of A ∆ B are points which are in A XOR in B.
+ *
+ * @return A path-vector describing the symmetric difference of the operands A and B.
+ */
+ PathVector getXOR();
+
+ /// Returns the number of intersections used when computing Boolean operations.
+ std::size_t size() const;
+
+ /**
+ * @brief Get the geometric points where the two path-vectors intersect.
+ *
+ * Degenerate intersection points, where the shapes merely "kiss", are not retured.
+ *
+ * @param defective – whether to return only the defective crossings or only the true crossings.
+ * @return If defective is true, returns a vector containing all defective intersection points,
+ * i.e., points that are neither true transverse intersections nor degenerate intersections.
+ * If defective is false, returns all true transverse intersections.
+ */
+ std::vector<Point> intersectionPoints(bool defective = false) const;
+
+ /**
+ * @brief Get the geometric points located on path portions between consecutive intersections.
+ *
+ * These points were used for the winding number calculations which determined which path portions
+ * lie inside the other shape and which lie outside.
+ *
+ * @return A vector containing all sample points used for winding calculations.
+ */
+ std::vector<Point> windingPoints() const {
+ return _winding_points;
+ }
+
+ void fragments(PathVector &in, PathVector &out) const;
+
+
+ bool valid() const { return _graph_valid; }
+
+private:
+ enum InOutFlag {
+ INSIDE,
+ OUTSIDE,
+ BOTH
+ };
+
+ struct IntersectionVertex {
+ boost::intrusive::list_member_hook<> _hook;
+ boost::intrusive::list_member_hook<> _proc_hook;
+ PathVectorTime pos; ///< Intersection time.
+ Point p; ///< Geometric position of the intersection point; guarantees that endpoints are exact.
+ IntersectionVertex *neighbor; ///< A pointer to the corresponding vertex on the other shape.
+ /** Tells us whether the edge originating at this intersection lies inside or outside of
+ * the shape given by the other path-vector. The "edge originating" at this intersection is
+ * the portion of the path between this intersection and the next intersection, in the
+ * direction of increasing path time. */
+ InOutFlag next_edge;
+ unsigned which; ///< Index of the operand path-vector that this intersection vertex lies on.
+ /** Whether the intersection is defective, which means that for some reason the paths
+ * neither cross transversally through each other nor "kiss" at a common tangency point.
+ */
+ bool defective;
+ };
+
+ typedef boost::intrusive::list
+ < IntersectionVertex
+ , boost::intrusive::member_hook
+ < IntersectionVertex
+ , boost::intrusive::list_member_hook<>
+ , &IntersectionVertex::_hook
+ >
+ > IntersectionList;
+
+ typedef boost::intrusive::list
+ < IntersectionVertex
+ , boost::intrusive::member_hook
+ < IntersectionVertex
+ , boost::intrusive::list_member_hook<>
+ , &IntersectionVertex::_proc_hook
+ >
+ > UnprocessedList;
+
+ /// Stores processed intersection information for a single path in an operand path-vector.
+ struct PathData {
+ IntersectionList xlist; ///< List of crossings on this particular path.
+ std::size_t path_index; ///< Index of the path in its path-vector.
+ int which; ///< Index of the path-vector (in PathIntersectionGraph::_pv) that the path belongs to.
+ /** Whether this path as a whole is contained INSIDE or OUTSIDE relative to the other path-vector.
+ * The value BOTH means that some portions of the path are inside while others are outside.
+ */
+ InOutFlag status;
+
+ PathData(int w, std::size_t pi)
+ : path_index(pi)
+ , which(w)
+ , status(BOTH)
+ {}
+ };
+
+ struct IntersectionVertexLess;
+ typedef IntersectionList::iterator ILIter;
+ typedef IntersectionList::const_iterator CILIter;
+
+ PathVector _getResult(bool enter_a, bool enter_b);
+ void _handleNonintersectingPaths(PathVector &result, unsigned which, bool inside);
+ void _prepareArguments();
+ bool _prepareIntersectionLists(Coord precision);
+ void _assignEdgeWindingParities(Coord precision);
+ void _assignComponentStatusFromDegenerateIntersections();
+ void _removeDegenerateIntersections();
+ void _verify();
+
+ ILIter _getNeighbor(ILIter iter);
+ PathData &_getPathData(ILIter iter);
+
+ PathVector _pv[2]; ///< Stores the two operand path-vectors, A at _pv[0] and B at _pv[1].
+ boost::ptr_vector<IntersectionVertex> _xs; ///< Stores all crossings between the two shapes.
+ boost::ptr_vector<PathData> _components[2]; ///< Stores the crossing information for the operands.
+ UnprocessedList _ulist; ///< Temporarily holds all unprocessed during a boolean operation.
+ bool _graph_valid; ///< Whether all intersections are regular.
+ /** Stores sample points located on paths of the operand path-vectors,
+ * between consecutive intersections.
+ */
+ std::vector<Point> _winding_points;
+
+ friend std::ostream &operator<<(std::ostream &, PathIntersectionGraph const &);
+};
+
+std::ostream &operator<<(std::ostream &os, PathIntersectionGraph const &pig);
+
+} // namespace Geom
+
+#endif // SEEN_LIB2GEOM_PATH_GRAPH_H
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/intersection.h b/src/3rdparty/2geom/include/2geom/intersection.h
new file mode 100644
index 0000000..8a23811
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/intersection.h
@@ -0,0 +1,147 @@
+/**
+ * \file
+ * \brief Intersection utilities
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef SEEN_LIB2GEOM_INTERSECTION_H
+#define SEEN_LIB2GEOM_INTERSECTION_H
+
+#include <2geom/coord.h>
+#include <2geom/point.h>
+
+namespace Geom {
+
+
+/** @brief Intersection between two shapes.
+ */
+template <typename TimeA = Coord, typename TimeB = TimeA>
+class Intersection
+ : boost::totally_ordered< Intersection<TimeA, TimeB> >
+{
+public:
+ /** @brief Construct from shape references and time values.
+ * By default, the intersection point will be halfway between the evaluated
+ * points on the two shapes. */
+ template <typename TA, typename TB>
+ Intersection(TA const &sa, TB const &sb, TimeA const &ta, TimeB const &tb)
+ : first(ta)
+ , second(tb)
+ , _point(lerp(0.5, sa.pointAt(ta), sb.pointAt(tb)))
+ {}
+
+ /// Additionally report the intersection point.
+ Intersection(TimeA const &ta, TimeB const &tb, Point const &p)
+ : first(ta)
+ , second(tb)
+ , _point(p)
+ {}
+
+ /// Intersection point, as calculated by the intersection algorithm.
+ Point point() const {
+ return _point;
+ }
+ /// Implicit conversion to Point.
+ operator Point() const {
+ return _point;
+ }
+
+ friend inline void swap(Intersection &a, Intersection &b) {
+ using std::swap;
+ swap(a.first, b.first);
+ swap(a.second, b.second);
+ swap(a._point, b._point);
+ }
+
+ bool operator==(Intersection const &other) const {
+ if (first != other.first) return false;
+ if (second != other.second) return false;
+ return true;
+ }
+ bool operator<(Intersection const &other) const {
+ if (first < other.first) return true;
+ if (first == other.first && second < other.second) return true;
+ return false;
+ }
+
+public:
+ /// First shape and time value.
+ TimeA first;
+ /// Second shape and time value.
+ TimeB second;
+private:
+ // Recalculation of the intersection point from the time values is in many cases
+ // less precise than the value obtained directly from the intersection algorithm,
+ // so we need to store it.
+ Point _point;
+};
+
+
+// TODO: move into new header?
+template <typename T>
+struct ShapeTraits {
+ typedef Coord TimeType;
+ typedef Interval IntervalType;
+ typedef T AffineClosureType;
+ typedef Intersection<> IntersectionType;
+};
+
+template <typename A, typename B> inline
+std::vector< Intersection<A, B> > transpose(std::vector< Intersection<B, A> > const &in) {
+ std::vector< Intersection<A, B> > result;
+ for (std::size_t i = 0; i < in.size(); ++i) {
+ result.push_back(Intersection<A, B>(in[i].second, in[i].first, in[i].point()));
+ }
+ return result;
+}
+
+template <typename T> inline
+void transpose_in_place(std::vector< Intersection<T, T> > &xs) {
+ for (std::size_t i = 0; i < xs.size(); ++i) {
+ std::swap(xs[i].first, xs[i].second);
+ }
+}
+
+typedef Intersection<> ShapeIntersection;
+
+
+} // namespace Geom
+
+#endif // SEEN_LIB2GEOM_INTERSECTION_H
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/interval.h b/src/3rdparty/2geom/include/2geom/interval.h
new file mode 100644
index 0000000..11c8f28
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/interval.h
@@ -0,0 +1,245 @@
+/**
+ * \file
+ * \brief Simple closed interval class
+ *//*
+ * Copyright 2007 Michael Sloan <mgsloan@gmail.com>
+ *
+ * Original Rect/Range code by:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Nathan Hurst <njh@mail.csse.monash.edu.au>
+ * bulia byak <buliabyak@users.sf.net>
+ * MenTaLguY <mental@rydia.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, output to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+#ifndef LIB2GEOM_SEEN_INTERVAL_H
+#define LIB2GEOM_SEEN_INTERVAL_H
+
+#include <boost/none.hpp>
+#include <boost/operators.hpp>
+#include <2geom/coord.h>
+#include <2geom/math-utils.h>
+#include <2geom/generic-interval.h>
+#include <2geom/int-interval.h>
+
+namespace Geom {
+
+/**
+ * @brief Range of real numbers that is never empty.
+ *
+ * Intervals are closed ranges \f$[a, b]\f$, which means they include their endpoints.
+ * To use them as open ranges, you can use the interiorContains() methods.
+ *
+ * @ingroup Primitives
+ */
+class Interval
+ : public GenericInterval<Coord>
+{
+ typedef GenericInterval<Coord> Base;
+public:
+ /// @name Create intervals.
+ /// @{
+ /** @brief Create an interval that contains only zero. */
+ Interval() {}
+ /** @brief Create an interval that contains a single point. */
+ explicit Interval(Coord u) : Base(u) {}
+ /** @brief Create an interval that contains all points between @c u and @c v. */
+ Interval(Coord u, Coord v) : Base(u,v) {}
+ /** @brief Convert from integer interval */
+ Interval(IntInterval const &i) : Base(i.min(), i.max()) {}
+ Interval(Base const &b) : Base(b) {}
+
+ /** @brief Create an interval containing a range of values.
+ * The resulting interval will contain all values from the given range.
+ * The return type of iterators must be convertible to Coord. The given range
+ * must not be empty. For potentially empty ranges, see OptInterval.
+ * @param start Beginning of the range
+ * @param end End of the range
+ * @return Interval that contains all values from [start, end). */
+ template <typename InputIterator>
+ static Interval from_range(InputIterator start, InputIterator end) {
+ Interval result = Base::from_range(start, end);
+ return result;
+ }
+ /** @brief Create an interval from a C-style array of values it should contain. */
+ static Interval from_array(Coord const *c, unsigned n) {
+ Interval result = from_range(c, c+n);
+ return result;
+ }
+ /// @}
+
+ /// @name Inspect contained values.
+ /// @{
+ /// Check whether both endpoints are finite.
+ bool isFinite() const {
+ return std::isfinite(min()) && std::isfinite(max());
+ }
+ /** @brief Map the interval [0,1] onto this one.
+ * This method simply performs 1D linear interpolation between endpoints. */
+ Coord valueAt(Coord t) const {
+ return lerp(t, min(), max());
+ }
+ /** @brief Compute a time value that maps to the given value.
+ * The supplied value does not need to be in the interval for this method to work. */
+ Coord timeAt(Coord v) const {
+ return (v - min()) / extent();
+ }
+ /// Find closest time in [0,1] that maps to the given value. */
+ Coord nearestTime(Coord v) const {
+ if (v <= min()) return 0;
+ if (v >= max()) return 1;
+ return timeAt(v);
+ }
+ /// @}
+
+ /// @name Test coordinates and other intervals for inclusion.
+ /// @{
+ /** @brief Check whether the interior of the interval includes this number.
+ * Interior means all numbers in the interval except its ends. */
+ bool interiorContains(Coord val) const { return min() < val && val < max(); }
+ /** @brief Check whether the interior of the interval includes the given interval.
+ * Interior means all numbers in the interval except its ends. */
+ bool interiorContains(Interval const &val) const { return min() < val.min() && val.max() < max(); }
+ /// Check whether the number is contained in the union of the interior and the lower boundary.
+ bool lowerContains(Coord val) const { return min() <= val && val < max(); }
+ /// Check whether the given interval is contained in the union of the interior and the lower boundary.
+ bool lowerContains(Interval const &val) const { return min() <= val.min() && val.max() < max(); }
+ /// Check whether the number is contained in the union of the interior and the upper boundary.
+ bool upperContains(Coord val) { return min() < val && val <= max(); }
+ /// Check whether the given interval is contained in the union of the interior and the upper boundary.
+ bool upperContains(Interval const &val) const { return min() < val.min() && val.max() <= max(); }
+ /** @brief Check whether the interiors of the intervals have any common elements.
+ * A single point in common is not considered an intersection. */
+ bool interiorIntersects(Interval const &val) const {
+ return std::max(min(), val.min()) < std::min(max(), val.max());
+ }
+ /// @}
+
+ /// @name Operators
+ /// @{
+ // IMPL: ScalableConcept
+ /** @brief Scale an interval */
+ Interval &operator*=(Coord s) {
+ using std::swap;
+ _b[0] *= s;
+ _b[1] *= s;
+ if(s < 0) swap(_b[0], _b[1]);
+ return *this;
+ }
+ /** @brief Scale an interval by the inverse of the specified value */
+ Interval &operator/=(Coord s) {
+ using std::swap;
+ _b[0] /= s;
+ _b[1] /= s;
+ if(s < 0) swap(_b[0], _b[1]);
+ return *this;
+ }
+ /** @brief Multiply two intervals.
+ * Product is defined as the set of points that can be obtained by multiplying
+ * any value from the second operand by any value from the first operand:
+ * \f$S = \{x \in A, y \in B: x * y\}\f$ */
+ Interval &operator*=(Interval const &o) {
+ // TODO implement properly
+ Coord mn = min(), mx = max();
+ expandTo(mn * o.min());
+ expandTo(mn * o.max());
+ expandTo(mx * o.min());
+ expandTo(mx * o.max());
+ return *this;
+ }
+ bool operator==(IntInterval const &ii) const {
+ return min() == Coord(ii.min()) && max() == Coord(ii.max());
+ }
+ bool operator==(Interval const &other) const {
+ return Base::operator==(other);
+ }
+ /// @}
+
+ /// @name Rounding to integer values
+ /// @{
+ /** @brief Return the smallest integer interval which contains this one. */
+ IntInterval roundOutwards() const {
+ IntInterval ret(floor(min()), ceil(max()));
+ return ret;
+ }
+ /** @brief Return the largest integer interval which is contained in this one. */
+ OptIntInterval roundInwards() const {
+ IntCoord u = ceil(min()), v = floor(max());
+ if (u > v) { OptIntInterval e; return e; }
+ IntInterval ret(u, v);
+ return ret;
+ }
+ /// @}
+};
+
+/**
+ * @brief Range of real numbers that can be empty.
+ * @ingroup Primitives
+ */
+class OptInterval
+ : public GenericOptInterval<Coord>
+{
+ typedef GenericOptInterval<Coord> Base;
+public:
+ using Base::Base;
+ using Base::operator==;
+ using Base::operator!=;
+
+ OptInterval(Base const &b) : Base(b) {}
+
+ /** @brief Promote from IntInterval. */
+ OptInterval(IntInterval const &i) : Base(Interval(i)) {}
+ /** @brief Promote from OptIntInterval. */
+ OptInterval(OptIntInterval const &i) : Base() {
+ if (i) *this = Interval(*i);
+ }
+};
+
+// functions required for Python bindings
+inline Interval unify(Interval const &a, Interval const &b)
+{
+ Interval r = a | b;
+ return r;
+}
+inline OptInterval intersect(Interval const &a, Interval const &b)
+{
+ OptInterval r = a & b;
+ return r;
+}
+
+} // end namespace Geom
+
+#endif //SEEN_INTERVAL_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/intervaltree/interval_tree.h b/src/3rdparty/2geom/include/2geom/intervaltree/interval_tree.h
new file mode 100644
index 0000000..85f91f9
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/intervaltree/interval_tree.h
@@ -0,0 +1,126 @@
+#ifndef E_INTERVAL_TREE
+#define E_INTERVAL_TREE
+
+// From Emin Martinian, licenced LGPL and MPL with permission
+
+#include <vector>
+#include <math.h>
+#include <limits>
+#include <iostream>
+
+using std::vector;
+
+// The interval_tree.h and interval_tree.cc files contain code for
+// interval trees implemented using red-black-trees as described in
+// the book _Introduction_To_Algorithms_ by Cormen, Leisserson,
+// and Rivest.
+
+// CONVENTIONS:
+// Function names: Each word in a function name begins with
+// a capital letter. An example funcntion name is
+// CreateRedTree(a,b,c). Furthermore, each function name
+// should begin with a capital letter to easily distinguish
+// them from variables.
+//
+// Variable names: Each word in a variable name begins with
+// a capital letter EXCEPT the first letter of the variable
+// name. For example, int newLongInt. Global variables have
+// names beginning with "g". An example of a global
+// variable name is gNewtonsConstant.
+
+
+#ifndef MAX_INT
+#define MAX_INT INT_MAX // some architechturs define INT_MAX not MAX_INT
+#endif
+
+// The Interval class is an Abstract Base Class. This means that no
+// instance of the Interval class can exist. Only classes which
+// inherit from the Interval class can exist. Furthermore any class
+// which inherits from the Interval class must define the member
+// functions GetLowPoint and GetHighPoint.
+//
+// The GetLowPoint should return the lowest point of the interval and
+// the GetHighPoint should return the highest point of the interval.
+
+class Interval {
+public:
+ Interval();
+ virtual ~Interval();
+ virtual int GetLowPoint() const = 0;
+ virtual int GetHighPoint() const = 0;
+ virtual void Print() const;
+};
+
+class IntervalTreeNode {
+ friend class IntervalTree;
+public:
+ void Print(IntervalTreeNode*,
+ IntervalTreeNode*) const;
+ IntervalTreeNode();
+ IntervalTreeNode(Interval *);
+ ~IntervalTreeNode();
+protected:
+ Interval * storedInterval;
+ int key;
+ int high;
+ int maxHigh;
+ bool red; /* if red=0 then the node is black */
+ IntervalTreeNode * left;
+ IntervalTreeNode * right;
+ IntervalTreeNode * parent;
+};
+
+struct it_recursion_node {
+public:
+ /* this structure stores the information needed when we take the */
+ /* right branch in searching for intervals but possibly come back */
+ /* and check the left branch as well. */
+
+ IntervalTreeNode * start_node;
+ unsigned int parentIndex;
+ bool tryRightBranch;
+} ;
+
+
+class IntervalTree {
+public:
+ IntervalTree();
+ ~IntervalTree();
+ void Print() const;
+ Interval * DeleteNode(IntervalTreeNode *);
+ IntervalTreeNode * Insert(Interval *);
+ IntervalTreeNode * GetPredecessorOf(IntervalTreeNode *) const;
+ IntervalTreeNode * GetSuccessorOf(IntervalTreeNode *) const;
+ vector<void *> Enumerate(int low, int high) ;
+ void CheckAssumptions() const;
+protected:
+ /* A sentinel is used for root and for nil. These sentinels are */
+ /* created when ITTreeCreate is caled. root->left should always */
+ /* point to the node which is the root of the tree. nil points to a */
+ /* node which should always be black but has arbitrary children and */
+ /* parent and no key or info. The point of using these sentinels is so */
+ /* that the root and nil nodes do not require special cases in the code */
+ IntervalTreeNode * root;
+ IntervalTreeNode * nil;
+ void LeftRotate(IntervalTreeNode *);
+ void RightRotate(IntervalTreeNode *);
+ void TreeInsertHelp(IntervalTreeNode *);
+ void TreePrintHelper(IntervalTreeNode *) const;
+ void FixUpMaxHigh(IntervalTreeNode *);
+ void DeleteFixUp(IntervalTreeNode *);
+ void CheckMaxHighFields(IntervalTreeNode *) const;
+ int CheckMaxHighFieldsHelper(IntervalTreeNode * y,
+ const int currentHigh,
+ int match) const;
+private:
+ unsigned int recursionNodeStackSize;
+ it_recursion_node * recursionNodeStack;
+ unsigned int currentParent;
+ unsigned int recursionNodeStackTop;
+};
+
+
+#endif
+
+
+
diff --git a/src/3rdparty/2geom/include/2geom/line.h b/src/3rdparty/2geom/include/2geom/line.h
new file mode 100644
index 0000000..9a56602
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/line.h
@@ -0,0 +1,605 @@
+/**
+ * \file
+ * \brief Infinite straight line
+ *//*
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ * Copyright 2008-2011 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_LINE_H
+#define LIB2GEOM_SEEN_LINE_H
+
+#include <cmath>
+#include <optional>
+#include <2geom/bezier-curve.h> // for LineSegment
+#include <2geom/rect.h>
+#include <2geom/crossing.h>
+#include <2geom/exception.h>
+#include <2geom/ray.h>
+#include <2geom/angle.h>
+#include <2geom/intersection.h>
+
+namespace Geom
+{
+
+// class docs in cpp file
+class Line
+ : boost::equality_comparable< Line >
+{
+private:
+ Point _initial;
+ Point _final;
+public:
+ /// @name Creating lines.
+ /// @{
+ /** @brief Create a default horizontal line.
+ * Creates a line with unit speed going in +X direction. */
+ Line()
+ : _initial(0,0), _final(1,0)
+ {}
+ /** @brief Create a line with the specified inclination.
+ * @param origin One of the points on the line
+ * @param angle Angle of the line in mathematical convention */
+ Line(Point const &origin, Coord angle)
+ : _initial(origin)
+ {
+ Point v;
+ sincos(angle, v[Y], v[X]);
+ _final = _initial + v;
+ }
+
+ /** @brief Create a line going through two points.
+ * The first point will be at time 0, while the second one
+ * will be at time 1.
+ * @param a Initial point
+ * @param b First point */
+ Line(Point const &a, Point const &b)
+ : _initial(a)
+ , _final(b)
+ {}
+
+ /** @brief Create a line based on the coefficients of its equation.
+ @see Line::setCoefficients() */
+ Line(double a, double b, double c) {
+ setCoefficients(a, b, c);
+ }
+
+ /// Create a line by extending a line segment.
+ explicit Line(LineSegment const &seg)
+ : _initial(seg.initialPoint())
+ , _final(seg.finalPoint())
+ {}
+
+ /// Create a line by extending a ray.
+ explicit Line(Ray const &r)
+ : _initial(r.origin())
+ , _final(r.origin() + r.vector())
+ {}
+
+ /// Create a line normal to a vector at a specified distance from origin.
+ static Line from_normal_distance(Point const &n, Coord c) {
+ Point start = c * n.normalized();
+ Line l(start, start + rot90(n));
+ return l;
+ }
+ /** @brief Create a line from origin and unit vector.
+ * Note that each line direction has two possible unit vectors.
+ * @param o Point through which the line will pass
+ * @param v Unit vector of the line's direction */
+ static Line from_origin_and_vector(Point const &o, Point const &v) {
+ Line l(o, o + v);
+ return l;
+ }
+
+ Line* duplicate() const {
+ return new Line(*this);
+ }
+ /// @}
+
+ /// @name Retrieve and set the line's parameters.
+ /// @{
+
+ /// Get the line's origin point.
+ Point origin() const { return _initial; }
+ /** @brief Get the line's raw direction vector.
+ * The length of the retrieved vector is equal to the length of a segment parametrized by
+ * a time interval of length 1. */
+ Point vector() const { return _final - _initial; }
+ /** @brief Get the line's normalized direction vector.
+ * The retrieved vector is normalized to unit length. */
+ Point versor() const { return (_final - _initial).normalized(); }
+ /// Angle the line makes with the X axis, in mathematical convention.
+ Coord angle() const {
+ Point d = _final - _initial;
+ double a = std::atan2(d[Y], d[X]);
+ if (a < 0) a += M_PI;
+ if (a == M_PI) a = 0;
+ return a;
+ }
+
+ /** @brief Set the point at zero time.
+ * The orientation remains unchanged, modulo numeric errors during addition. */
+ void setOrigin(Point const &p) {
+ Point d = p - _initial;
+ _initial = p;
+ _final += d;
+ }
+ /** @brief Set the speed of the line.
+ * Origin remains unchanged. */
+ void setVector(Point const &v) {
+ _final = _initial + v;
+ }
+
+ /** @brief Set the angle the line makes with the X axis.
+ * Origin remains unchanged. */
+ void setAngle(Coord angle) {
+ Point v;
+ sincos(angle, v[Y], v[X]);
+ v *= distance(_initial, _final);
+ _final = _initial + v;
+ }
+
+ /// Set a line based on two points it should pass through.
+ void setPoints(Point const &a, Point const &b) {
+ _initial = a;
+ _final = b;
+ }
+
+ /** @brief Set the coefficients of the line equation.
+ * The line equation is: \f$ax + by = c\f$. Points that satisfy the equation
+ * are on the line. */
+ void setCoefficients(double a, double b, double c);
+
+ /** @brief Get the coefficients of the line equation as a vector.
+ * @return STL vector @a v such that @a v[0] contains \f$a\f$, @a v[1] contains \f$b\f$,
+ * and @a v[2] contains \f$c\f$. */
+ std::vector<double> coefficients() const;
+
+ /// Get the coefficients of the line equation by reference.
+ void coefficients(Coord &a, Coord &b, Coord &c) const;
+
+ /** @brief Check if the line has more than one point.
+ * A degenerate line can be created if the line is created from a line equation
+ * that has no solutions.
+ * @return True if the line has no points or exactly one point */
+ bool isDegenerate() const {
+ return _initial == _final;
+ }
+ /// Check if the line is horizontal (y is constant).
+ bool isHorizontal() const {
+ return _initial[Y] == _final[Y];
+ }
+ /// Check if the line is vertical (x is constant).
+ bool isVertical() const {
+ return _initial[X] == _final[X];
+ }
+
+ /** @brief Reparametrize the line so that it has unit speed.
+ * Note that the direction of the line may also change. */
+ void normalize() {
+ // this helps with the nasty case of a line that starts somewhere far
+ // and ends very close to the origin
+ if (L2sq(_final) < L2sq(_initial)) {
+ std::swap(_initial, _final);
+ }
+ Point v = _final - _initial;
+ v.normalize();
+ _final = _initial + v;
+ }
+ /** @brief Return a new line reparametrized for unit speed. */
+ Line normalized() const {
+ Point v = _final - _initial;
+ v.normalize();
+ Line ret(_initial, _initial + v);
+ return ret;
+ }
+ /// @}
+
+ /// @name Evaluate the line as a function.
+ ///@{
+ Point initialPoint() const {
+ return _initial;
+ }
+ Point finalPoint() const {
+ return _final;
+ }
+ Point pointAt(Coord t) const {
+ return lerp(t, _initial, _final);;
+ }
+
+ Coord valueAt(Coord t, Dim2 d) const {
+ return lerp(t, _initial[d], _final[d]);
+ }
+
+ Coord timeAt(Point const &p) const;
+
+ /** @brief Get a time value corresponding to a projection of a point on the line.
+ * @param p Arbitrary point.
+ * @return Time value corresponding to a point closest to @c p. */
+ Coord timeAtProjection(Point const& p) const {
+ if ( isDegenerate() ) return 0;
+ Point v = vector();
+ return dot(p - _initial, v) / dot(v, v);
+ }
+
+ /** @brief Find a point on the line closest to the query point.
+ * This is an alias for timeAtProjection(). */
+ Coord nearestTime(Point const &p) const {
+ return timeAtProjection(p);
+ }
+
+ std::vector<Coord> roots(Coord v, Dim2 d) const;
+ Coord root(Coord v, Dim2 d) const;
+ /// @}
+
+ /// @name Create other objects based on this line.
+ /// @{
+ void reverse() {
+ std::swap(_final, _initial);
+ }
+ /** @brief Create a line containing the same points, but in opposite direction.
+ * @return Line \f$g\f$ such that \f$g(t) = f(1-t)\f$ */
+ Line reversed() const {
+ Line result(_final, _initial);
+ return result;
+ }
+
+ /** @brief Same as segment(), but allocate the line segment dynamically. */
+ // TODO remove this?
+ Curve* portion(Coord f, Coord t) const {
+ LineSegment* seg = new LineSegment(pointAt(f), pointAt(t));
+ return seg;
+ }
+
+ /** @brief Create a segment of this line.
+ * @param f Time value for the initial point of the segment
+ * @param t Time value for the final point of the segment
+ * @return Created line segment */
+ LineSegment segment(Coord f, Coord t) const {
+ return LineSegment(pointAt(f), pointAt(t));
+ }
+
+ /// Return the portion of the line that is inside the given rectangle
+ std::optional<LineSegment> clip(Rect const &r) const;
+
+ /** @brief Create a ray starting at the specified time value.
+ * The created ray will go in the direction of the line's vector (in the direction
+ * of increasing time values).
+ * @param t Time value where the ray should start
+ * @return Ray starting at t and going in the direction of the vector */
+ Ray ray(Coord t) {
+ Ray result;
+ result.setOrigin(pointAt(t));
+ result.setVector(vector());
+ return result;
+ }
+
+ /** @brief Create a derivative of the line.
+ * The new line will always be degenerate. Its origin will be equal to this
+ * line's vector. */
+ Line derivative() const {
+ Point v = vector();
+ Line result(v, v);
+ return result;
+ }
+
+ /// Create a line transformed by an affine transformation.
+ Line transformed(Affine const& m) const {
+ Line l(_initial * m, _final * m);
+ return l;
+ }
+
+ /** @brief Get a unit vector normal to the line.
+ * If Y grows upwards, then this is the left normal. If Y grows downwards,
+ * then this is the right normal. */
+ Point normal() const {
+ return rot90(vector()).normalized();
+ }
+
+ // what does this do?
+ Point normalAndDist(double & dist) const {
+ Point n = normal();
+ dist = -dot(n, _initial);
+ return n;
+ }
+
+ /// Compute an affine matrix representing a reflection about the line.
+ Affine reflection() const {
+ Point v = versor();
+ Coord x2 = v[X]*v[X], y2 = v[Y]*v[Y], xy = v[X]*v[Y];
+ Affine m(x2-y2, 2.*xy,
+ 2.*xy, y2-x2,
+ _initial[X], _initial[Y]);
+ m = Translate(-_initial) * m;
+ return m;
+ }
+
+ /** @brief Compute an affine which transforms all points on the line to zero X or Y coordinate.
+ * This operation is useful in reducing intersection problems to root-finding problems.
+ * There are many affines which do this transformation. This function returns one that
+ * preserves angles, areas and distances - a rotation combined with a translation, and
+ * additionally moves the initial point of the line to (0,0). This way it works without
+ * problems even for lines perpendicular to the target, though may in some cases have
+ * lower precision than e.g. a shear transform.
+ * @param d Which coordinate of points on the line should be zero after the transformation */
+ Affine rotationToZero(Dim2 d) const {
+ Point v = vector();
+ if (d == X) {
+ std::swap(v[X], v[Y]);
+ } else {
+ v[Y] = -v[Y];
+ }
+ Affine m = Translate(-_initial) * Rotate(v);
+ return m;
+ }
+ /** @brief Compute a rotation affine which transforms the line to one of the axes.
+ * @param d Which line should be the axis */
+ Affine rotationToAxis(Dim2 d) const {
+ Affine m = rotationToZero(other_dimension(d));
+ return m;
+ }
+
+ Affine transformTo(Line const &other) const;
+ /// @}
+
+ std::vector<ShapeIntersection> intersect(Line const &other) const;
+ std::vector<ShapeIntersection> intersect(Ray const &r) const;
+ std::vector<ShapeIntersection> intersect(LineSegment const &ls) const;
+
+ template <typename T>
+ Line &operator*=(T const &tr) {
+ BOOST_CONCEPT_ASSERT((TransformConcept<T>));
+ _initial *= tr;
+ _final *= tr;
+ return *this;
+ }
+
+ bool operator==(Line const &other) const {
+ if (distance(pointAt(nearestTime(other._initial)), other._initial) != 0) return false;
+ if (distance(pointAt(nearestTime(other._final)), other._final) != 0) return false;
+ return true;
+ }
+
+ template <typename T>
+ friend Line operator*(Line const &l, T const &tr) {
+ BOOST_CONCEPT_ASSERT((TransformConcept<T>));
+ Line result(l);
+ result *= tr;
+ return result;
+ }
+}; // end class Line
+
+/** @brief Removes intersections outside of the unit interval.
+ * A helper used to implement line segment intersections.
+ * @param xs Line intersections
+ * @param a Whether the first time value has to be in the unit interval
+ * @param b Whether the second time value has to be in the unit interval
+ * @return Appropriately filtered intersections */
+void filter_line_segment_intersections(std::vector<ShapeIntersection> &xs, bool a=false, bool b=true);
+void filter_ray_intersections(std::vector<ShapeIntersection> &xs, bool a=false, bool b=true);
+
+/// @brief Compute distance from point to line.
+/// @relates Line
+inline
+double distance(Point const &p, Line const &line)
+{
+ if (line.isDegenerate()) {
+ return ::Geom::distance(p, line.initialPoint());
+ } else {
+ Coord t = line.nearestTime(p);
+ return ::Geom::distance(line.pointAt(t), p);
+ }
+}
+
+inline
+bool are_near(Point const &p, Line const &line, double eps = EPSILON)
+{
+ return are_near(distance(p, line), 0, eps);
+}
+
+inline
+bool are_parallel(Line const &l1, Line const &l2, double eps = EPSILON)
+{
+ return are_near(cross(l1.vector(), l2.vector()), 0, eps);
+}
+
+/** @brief Test whether two lines are approximately the same.
+ * This tests for being parallel and the origin of one line being close to the other,
+ * so it tests whether the images of the lines are similar, not whether the same time values
+ * correspond to similar points. For example a line from (1,1) to (2,2) and a line from
+ * (-1,-1) to (0,0) will be the same, because their images match, even though there is
+ * no time value for which the lines give similar points.
+ * @relates Line */
+inline
+bool are_same(Line const &l1, Line const &l2, double eps = EPSILON)
+{
+ return are_parallel(l1, l2, eps) && are_near(l1.origin(), l2, eps);
+}
+
+/// Test whether two lines are perpendicular.
+/// @relates Line
+inline
+bool are_orthogonal(Line const &l1, Line const &l2, double eps = EPSILON)
+{
+ return are_near(dot(l1.vector(), l2.vector()), 0, eps);
+}
+
+// evaluate the angle between l1 and l2 rotating l1 in cw direction
+// until it overlaps l2
+// the returned value is an angle in the interval [0, PI[
+inline
+double angle_between(Line const& l1, Line const& l2)
+{
+ double angle = angle_between(l1.vector(), l2.vector());
+ if (angle < 0) angle += M_PI;
+ if (angle == M_PI) angle = 0;
+ return angle;
+}
+
+inline
+double distance(Point const &p, LineSegment const &seg)
+{
+ double t = seg.nearestTime(p);
+ return distance(p, seg.pointAt(t));
+}
+
+inline
+bool are_near(Point const &p, LineSegment const &seg, double eps = EPSILON)
+{
+ return are_near(distance(p, seg), 0, eps);
+}
+
+// build a line passing by _point and orthogonal to _line
+inline
+Line make_orthogonal_line(Point const &p, Line const &line)
+{
+ Point d = line.vector().cw();
+ Line l(p, p + d);
+ return l;
+}
+
+// build a line passing by _point and parallel to _line
+inline
+Line make_parallel_line(Point const &p, Line const &line)
+{
+ Line result(line);
+ result.setOrigin(p);
+ return result;
+}
+
+// build a line passing by the middle point of _segment and orthogonal to it.
+inline
+Line make_bisector_line(LineSegment const& _segment)
+{
+ return make_orthogonal_line( middle_point(_segment), Line(_segment) );
+}
+
+// build the bisector line of the angle between ray(O,A) and ray(O,B)
+inline
+Line make_angle_bisector_line(Point const &A, Point const &O, Point const &B)
+{
+ AngleInterval ival(Angle(A-O), Angle(B-O));
+ Angle bisect = ival.angleAt(0.5);
+ return Line(O, bisect);
+}
+
+// prj(P) = rot(v, Point( rot(-v, P-O)[X], 0 )) + O
+inline
+Point projection(Point const &p, Line const &line)
+{
+ return line.pointAt(line.nearestTime(p));
+}
+
+inline
+LineSegment projection(LineSegment const &seg, Line const &line)
+{
+ return line.segment(line.nearestTime(seg.initialPoint()),
+ line.nearestTime(seg.finalPoint()));
+}
+
+inline
+std::optional<LineSegment> clip(Line const &l, Rect const &r) {
+ return l.clip(r);
+}
+
+
+namespace detail
+{
+
+OptCrossing intersection_impl(Ray const& r1, Line const& l2, unsigned int i);
+OptCrossing intersection_impl( LineSegment const& ls1,
+ Line const& l2,
+ unsigned int i );
+OptCrossing intersection_impl( LineSegment const& ls1,
+ Ray const& r2,
+ unsigned int i );
+}
+
+
+inline
+OptCrossing intersection(Ray const& r1, Line const& l2)
+{
+ return detail::intersection_impl(r1, l2, 0);
+
+}
+
+inline
+OptCrossing intersection(Line const& l1, Ray const& r2)
+{
+ return detail::intersection_impl(r2, l1, 1);
+}
+
+inline
+OptCrossing intersection(LineSegment const& ls1, Line const& l2)
+{
+ return detail::intersection_impl(ls1, l2, 0);
+}
+
+inline
+OptCrossing intersection(Line const& l1, LineSegment const& ls2)
+{
+ return detail::intersection_impl(ls2, l1, 1);
+}
+
+inline
+OptCrossing intersection(LineSegment const& ls1, Ray const& r2)
+{
+ return detail::intersection_impl(ls1, r2, 0);
+
+}
+
+inline
+OptCrossing intersection(Ray const& r1, LineSegment const& ls2)
+{
+ return detail::intersection_impl(ls2, r1, 1);
+}
+
+
+OptCrossing intersection(Line const& l1, Line const& l2);
+
+OptCrossing intersection(Ray const& r1, Ray const& r2);
+
+OptCrossing intersection(LineSegment const& ls1, LineSegment const& ls2);
+
+
+} // end namespace Geom
+
+
+#endif // LIB2GEOM_SEEN_LINE_H
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/linear.h b/src/3rdparty/2geom/include/2geom/linear.h
new file mode 100644
index 0000000..75c6e01
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/linear.h
@@ -0,0 +1,167 @@
+/**
+ * \file
+ * \brief Linear fragment function class
+ *//*
+ * Authors:
+ * Nathan Hurst <njh@mail.csse.monash.edu.au>
+ * Michael Sloan <mgsloan@gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2006-2015 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_LINEAR_H
+#define LIB2GEOM_SEEN_LINEAR_H
+
+#include <2geom/interval.h>
+#include <2geom/math-utils.h>
+
+namespace Geom {
+
+class SBasis;
+
+/**
+ * @brief Function that interpolates linearly between two values.
+ * @ingroup Fragments
+ */
+class Linear
+ : boost::additive< Linear
+ , boost::arithmetic< Linear, Coord
+ , boost::equality_comparable< Linear
+ > > >
+{
+public:
+ Coord a[2];
+ Linear() {a[0]=0; a[1]=0;}
+ Linear(Coord aa, Coord b) {a[0] = aa; a[1] = b;}
+ Linear(Coord aa) {a[0] = aa; a[1] = aa;}
+
+ Coord operator[](unsigned i) const {
+ assert(i < 2);
+ return a[i];
+ }
+ Coord &operator[](unsigned i) {
+ assert(i < 2);
+ return a[i];
+ }
+
+ //IMPL: FragmentConcept
+ typedef Coord output_type;
+ bool isZero(Coord eps=EPSILON) const { return are_near(a[0], 0., eps) && are_near(a[1], 0., eps); }
+ bool isConstant(Coord eps=EPSILON) const { return are_near(a[0], a[1], eps); }
+ bool isFinite() const { return std::isfinite(a[0]) && std::isfinite(a[1]); }
+
+ Coord at0() const { return a[0]; }
+ Coord &at0() { return a[0]; }
+ Coord at1() const { return a[1]; }
+ Coord &at1() { return a[1]; }
+
+ Coord valueAt(Coord t) const { return lerp(t, a[0], a[1]); }
+ Coord operator()(Coord t) const { return valueAt(t); }
+
+ // not very useful, but required for FragmentConcept
+ std::vector<Coord> valueAndDerivatives(Coord t, unsigned n) {
+ std::vector<Coord> result(n+1, 0.0);
+ result[0] = valueAt(t);
+ if (n >= 1) {
+ result[1] = a[1] - a[0];
+ }
+ return result;
+ }
+
+ //defined in sbasis.h
+ inline SBasis toSBasis() const;
+
+ OptInterval bounds_exact() const { return Interval(a[0], a[1]); }
+ OptInterval bounds_fast() const { return bounds_exact(); }
+ OptInterval bounds_local(double u, double v) const { return Interval(valueAt(u), valueAt(v)); }
+
+ double tri() const {
+ return a[1] - a[0];
+ }
+ double hat() const {
+ return (a[1] + a[0])/2;
+ }
+
+ // addition of other Linears
+ Linear &operator+=(Linear const &other) {
+ a[0] += other.a[0];
+ a[1] += other.a[1];
+ return *this;
+ }
+ Linear &operator-=(Linear const &other) {
+ a[0] -= other.a[0];
+ a[1] -= other.a[1];
+ return *this;
+ }
+
+ //
+ Linear &operator+=(Coord x) {
+ a[0] += x; a[1] += x;
+ return *this;
+ }
+ Linear &operator-=(Coord x) {
+ a[0] -= x; a[1] -= x;
+ return *this;
+ }
+ Linear &operator*=(Coord x) {
+ a[0] *= x; a[1] *= x;
+ return *this;
+ }
+ Linear &operator/=(Coord x) {
+ a[0] /= x; a[1] /= x;
+ return *this;
+ }
+ Linear operator-() const {
+ Linear ret(-a[0], -a[1]);
+ return ret;
+ }
+
+ bool operator==(Linear const &other) const {
+ return a[0] == other.a[0] && a[1] == other.a[1];
+ }
+};
+
+inline Linear reverse(Linear const &a) { return Linear(a[1], a[0]); }
+inline Linear portion(Linear const &a, Coord from, Coord to) {
+ Linear result(a.valueAt(from), a.valueAt(to));
+ return result;
+}
+
+} // end namespace Geom
+
+#endif //LIB2GEOM_SEEN_LINEAR_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/math-utils.h b/src/3rdparty/2geom/include/2geom/math-utils.h
new file mode 100644
index 0000000..4c35a80
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/math-utils.h
@@ -0,0 +1,140 @@
+/**
+ * \file
+ * \brief Low level math functions and compatibility wrappers
+ *//*
+ * Authors:
+ * Johan Engelen <goejendaagh@zonnet.nl>
+ * Michael G. Sloan <mgsloan@gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ * Copyright 2006-2009 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_MATH_UTILS_H
+#define LIB2GEOM_SEEN_MATH_UTILS_H
+
+#include <math.h> // sincos is usually only available in math.h
+#include <array>
+#include <cmath>
+#include <utility> // for std::pair
+#include <boost/math/special_functions/fpclassify.hpp>
+
+namespace Geom {
+
+/** @brief Sign function - indicates the sign of a numeric type.
+ * Mathsy people will know this is basically the derivative of abs, except for the fact
+ * that it is defined on 0.
+ * @return -1 when x is negative, 1 when positive, and 0 if equal to 0. */
+template <class T> inline int sgn(const T& x) {
+ return (x < 0 ? -1 : (x > 0 ? 1 : 0) );
+// can we 'optimize' this with:
+// return ( (T(0) < x) - (x < T(0)) );
+}
+
+template <class T> inline T sqr(const T& x) {return x * x;}
+template <class T> inline T cube(const T& x) {return x * x * x;}
+
+/** Between function - returns true if a number x is within a range: (min < x) && (max > x).
+ * The values delimiting the range and the number must have the same type.
+ */
+template <class T> inline const T& between (const T& min, const T& max, const T& x)
+ { return (min < x) && (max > x); }
+
+/** @brief Returns @a x rounded to the nearest multiple of \f$10^{p}\f$.
+
+ Implemented in terms of round, i.e. we make no guarantees as to what happens if x is
+ half way between two rounded numbers.
+
+ Note: places is the number of decimal places without using scientific (e) notation, not the
+ number of significant figures. This function may not be suitable for values of x whose
+ magnitude is so far from 1 that one would want to use scientific (e) notation.
+
+ places may be negative: e.g. places = -2 means rounding to a multiple of .01
+**/
+inline double decimal_round(double x, int p) {
+ //TODO: possibly implement with modulus instead?
+ double const multiplier = ::pow(10.0, p);
+ return ::round( x * multiplier ) / multiplier;
+}
+
+/** @brief Simultaneously compute a sine and a cosine of the same angle.
+ * This function can be up to 2 times faster than separate computation, depending
+ * on the platform. It uses the standard library function sincos() if available.
+ * @param angle Angle
+ * @param sin_ Variable that will store the sine
+ * @param cos_ Variable that will store the cosine */
+inline void sincos(double angle, double &sin_, double &cos_) {
+#ifdef HAVE_SINCOS
+ ::sincos(angle, &sin_, &cos_);
+#else
+ sin_ = ::sin(angle);
+ cos_ = ::cos(angle);
+#endif
+}
+
+/** @brief Scale the doubles in the passed array to make them "reasonably large".
+ *
+ * All doubles in the passed array will get scaled by the same power of 2 (which is
+ * a lossless operation) in such a way that their geometric average gets closer to 1.
+ *
+ * @tparam N The size of the passed array.
+ * @param[in,out] values The doubles to be rescaled in place.
+ * @return The exponent in the power of two by which the doubles got scaled.
+ */
+template <size_t N>
+inline int rescale_homogenous(std::array<double, N> &values)
+{
+ if constexpr (N == 0) {
+ return 0;
+ }
+ std::array<int, N> exponents;
+ std::array<double, N> mantissas;
+ int average = 0;
+ for (size_t i = 0; i < N; i++) {
+ mantissas[i] = std::frexp(values[i], &exponents[i]);
+ average += exponents[i];
+ }
+ average /= (int)N;
+ for (size_t i = 0; i < N; i++) {
+ values[i] = std::ldexp(mantissas[i], exponents[i] - average);
+ }
+ return -average;
+}
+
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_MATH_UTILS_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/nearest-time.h b/src/3rdparty/2geom/include/2geom/nearest-time.h
new file mode 100644
index 0000000..007cd27
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/nearest-time.h
@@ -0,0 +1,141 @@
+/** @file
+ * @brief Nearest time routines for D2<SBasis> and Piecewise<D2<SBasis>>
+ *//*
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2007-2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#ifndef LIB2GEOM_SEEN_NEAREST_TIME_H
+#define LIB2GEOM_SEEN_NEAREST_TIME_H
+
+
+#include <vector>
+
+#include <2geom/d2.h>
+#include <2geom/piecewise.h>
+#include <2geom/exception.h>
+#include <2geom/bezier.h>
+
+
+namespace Geom
+{
+
+/*
+ * Given a line L specified by a point A and direction vector v,
+ * return the point on L nearest to p. Note that the returned value
+ * is with respect to the _normalized_ direction of v!
+ */
+inline double nearest_time(Point const &p, Point const &A, Point const &v)
+{
+ Point d(p - A);
+ return d[0] * v[0] + d[1] * v[1];
+}
+
+Coord nearest_time(Point const &p, D2<Bezier> const &bez, Coord from = 0, Coord to = 1);
+
+////////////////////////////////////////////////////////////////////////////////
+// D2<SBasis> versions
+
+/*
+ * Return the parameter t of a nearest point on the portion of the curve "c",
+ * related to the interval [from, to], to the point "p".
+ * The needed curve derivative "deriv" is passed as parameter.
+ * The function return the first nearest point to "p" that is found.
+ */
+double nearest_time(Point const &p,
+ D2<SBasis> const &c, D2<SBasis> const &deriv,
+ double from = 0, double to = 1);
+
+inline
+double nearest_time(Point const &p,
+ D2<SBasis> const &c,
+ double from = 0, double to = 1 )
+{
+ return nearest_time(p, c, Geom::derivative(c), from, to);
+}
+
+/*
+ * Return the parameters t of all the nearest times on the portion of
+ * the curve "c", related to the interval [from, to], to the point "p".
+ * The needed curve derivative "dc" is passed as parameter.
+ */
+std::vector<double>
+all_nearest_times(Point const& p,
+ D2<SBasis> const& c, D2<SBasis> const& dc,
+ double from = 0, double to = 1 );
+
+inline
+std::vector<double>
+all_nearest_times(Point const &p,
+ D2<SBasis> const &c,
+ double from = 0, double to = 1)
+{
+ return all_nearest_times(p, c, Geom::derivative(c), from, to);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Piecewise< D2<SBasis> > versions
+
+double nearest_time(Point const &p,
+ Piecewise< D2<SBasis> > const &c,
+ double from, double to);
+
+inline
+double nearest_time(Point const& p, Piecewise< D2<SBasis> > const &c)
+{
+ return nearest_time(p, c, c.cuts[0], c.cuts[c.size()]);
+}
+
+
+std::vector<double>
+all_nearest_times(Point const &p,
+ Piecewise< D2<SBasis> > const &c,
+ double from, double to);
+
+inline
+std::vector<double>
+all_nearest_times( Point const& p, Piecewise< D2<SBasis> > const& c )
+{
+ return all_nearest_times(p, c, c.cuts[0], c.cuts[c.size()]);
+}
+
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_NEAREST_TIME_H
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/numeric/fitting-model.h b/src/3rdparty/2geom/include/2geom/numeric/fitting-model.h
new file mode 100644
index 0000000..0316f57
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/numeric/fitting-model.h
@@ -0,0 +1,521 @@
+/*
+ * Fitting Models for Geom Types
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#ifndef _NL_FITTING_MODEL_H_
+#define _NL_FITTING_MODEL_H_
+
+
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/bezier.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/polynomial.h>
+#include <2geom/ellipse.h>
+#include <2geom/circle.h>
+#include <2geom/utils.h>
+#include <2geom/conicsec.h>
+
+
+namespace Geom { namespace NL {
+
+/*
+ * A model is an abstraction for an expression dependent from a parameter where
+ * the coefficients of this expression are the unknowns of the fitting problem.
+ * For a ceratain number of parameter values we know the related values
+ * the expression evaluates to: from each parameter value we get a row of
+ * the matrix of the fitting problem, from each expression value we get
+ * the related constant term.
+ * Example: given the model a*x^2 + b*x + c = 0; from x = 1 we get
+ * the equation a + b + c = 0, in this example the constant term is always
+ * the same for each parameter value.
+ *
+ * A model is required to implement 3 methods:
+ *
+ * - size : returns the number of unknown coefficients that appear in
+ * the expression of the fitting problem;
+ * - feed : its input is a parameter value and the related expression value,
+ * it generates a matrix row and a new entry of the constant vector
+ * of the fitting problem;
+ * - instance : it has an input parameter represented by the raw vector
+ * solution of the fitting problem and an output parameter
+ * of type InstanceType that return a specific object that is
+ * generated using the fitting problem solution, in the example
+ * above the object could be a Poly type.
+ */
+
+/*
+ * completely unknown models must inherit from this template class;
+ * example: the model a*x^2 + b*x + c = 0 to be solved wrt a, b, c;
+ * example: the model A(t) = known_sample_value_at(t) to be solved wrt
+ * the coefficients of the curve A(t) expressed in S-Basis form;
+ * parameter type: the type of x and t variable in the examples above;
+ * value type: the type of the known sample values (in the first example
+ * is constant )
+ * instance type: the type of the objects produced by using
+ * the fitting raw data solution
+ */
+
+
+
+
+template< typename ParameterType, typename ValueType, typename InstanceType >
+class LinearFittingModel
+{
+ public:
+ typedef ParameterType parameter_type;
+ typedef ValueType value_type;
+ typedef InstanceType instance_type;
+
+ static const bool WITH_FIXED_TERMS = false;
+
+ /*
+ * a LinearFittingModel must implement the following methods:
+ *
+ * void feed( VectorView & vector,
+ * parameter_type const& sample_parameter ) const;
+ *
+ * size_t size() const;
+ *
+ * void instance(instance_type &, raw_type const& raw_data) const;
+ *
+ */
+};
+
+
+/*
+ * partially known models must inherit from this template class
+ * example: the model a*x^2 + 2*x + c = 0 to be solved wrt a and c
+ */
+template< typename ParameterType, typename ValueType, typename InstanceType >
+class LinearFittingModelWithFixedTerms
+{
+ public:
+ typedef ParameterType parameter_type;
+ typedef ValueType value_type;
+ typedef InstanceType instance_type;
+
+ static const bool WITH_FIXED_TERMS = true;
+
+ /*
+ * a LinearFittingModelWithFixedTerms must implement the following methods:
+ *
+ * void feed( VectorView & vector,
+ * value_type & fixed_term,
+ * parameter_type const& sample_parameter ) const;
+ *
+ * size_t size() const;
+ *
+ * void instance(instance_type &, raw_type const& raw_data) const;
+ *
+ */
+
+
+};
+
+
+// incomplete model, it can be inherited to make up different kinds of
+// instance type; the raw data is a vector of coefficients of a polynomial
+// represented in standard power basis
+template< typename InstanceType >
+class LFMPowerBasis
+ : public LinearFittingModel<double, double, InstanceType>
+{
+ public:
+ LFMPowerBasis(size_t degree)
+ : m_size(degree + 1)
+ {
+ }
+
+ void feed( VectorView & coeff, double sample_parameter ) const
+ {
+ coeff[0] = 1;
+ double x_i = 1;
+ for (size_t i = 1; i < coeff.size(); ++i)
+ {
+ x_i *= sample_parameter;
+ coeff[i] = x_i;
+ }
+ }
+
+ size_t size() const
+ {
+ return m_size;
+ }
+
+ private:
+ size_t m_size;
+};
+
+
+// this model generates Geom::Poly objects
+class LFMPoly
+ : public LFMPowerBasis<Poly>
+{
+ public:
+ LFMPoly(size_t degree)
+ : LFMPowerBasis<Poly>(degree)
+ {
+ }
+
+ void instance(Poly & poly, ConstVectorView const& raw_data) const
+ {
+ poly.clear();
+ poly.resize(size());
+ for (size_t i = 0; i < raw_data.size(); ++i)
+ {
+ poly[i] = raw_data[i];
+ }
+ }
+};
+
+
+// incomplete model, it can be inherited to make up different kinds of
+// instance type; the raw data is a vector of coefficients of a polynomial
+// represented in standard power basis with leading term coefficient equal to 1
+template< typename InstanceType >
+class LFMNormalizedPowerBasis
+ : public LinearFittingModelWithFixedTerms<double, double, InstanceType>
+{
+ public:
+ LFMNormalizedPowerBasis(size_t _degree)
+ : m_model( _degree - 1)
+ {
+ assert(_degree > 0);
+ }
+
+
+ void feed( VectorView & coeff,
+ double & known_term,
+ double sample_parameter ) const
+ {
+ m_model.feed(coeff, sample_parameter);
+ known_term = coeff[m_model.size()-1] * sample_parameter;
+ }
+
+ size_t size() const
+ {
+ return m_model.size();
+ }
+
+ private:
+ LFMPowerBasis<InstanceType> m_model;
+};
+
+
+// incomplete model, it can be inherited to make up different kinds of
+// instance type; the raw data is a vector of coefficients of the equation
+// of an ellipse curve
+//template< typename InstanceType >
+//class LFMEllipseEquation
+// : public LinearFittingModelWithFixedTerms<Point, double, InstanceType>
+//{
+// public:
+// void feed( VectorView & coeff, double & fixed_term, Point const& p ) const
+// {
+// coeff[0] = p[X] * p[Y];
+// coeff[1] = p[Y] * p[Y];
+// coeff[2] = p[X];
+// coeff[3] = p[Y];
+// coeff[4] = 1;
+// fixed_term = p[X] * p[X];
+// }
+//
+// size_t size() const
+// {
+// return 5;
+// }
+//};
+
+// incomplete model, it can be inherited to make up different kinds of
+// instance type; the raw data is a vector of coefficients of the equation
+// of a conic section
+template< typename InstanceType >
+class LFMConicEquation
+ : public LinearFittingModelWithFixedTerms<Point, double, InstanceType>
+{
+ public:
+ void feed( VectorView & coeff, double & fixed_term, Point const& p ) const
+ {
+ coeff[0] = p[X] * p[Y];
+ coeff[1] = p[Y] * p[Y];
+ coeff[2] = p[X];
+ coeff[3] = p[Y];
+ coeff[4] = 1;
+ fixed_term = p[X] * p[X];
+ }
+
+ size_t size() const
+ {
+ return 5;
+ }
+};
+
+// this model generates Ellipse curves
+class LFMConicSection
+ : public LFMConicEquation<xAx>
+{
+ public:
+ void instance(xAx & c, ConstVectorView const& coeff) const
+ {
+ c.set(1, coeff[0], coeff[1], coeff[2], coeff[3], coeff[4]);
+ }
+};
+
+// this model generates Ellipse curves
+class LFMEllipse
+ : public LFMConicEquation<Ellipse>
+{
+ public:
+ void instance(Ellipse & e, ConstVectorView const& coeff) const
+ {
+ e.setCoefficients(1, coeff[0], coeff[1], coeff[2], coeff[3], coeff[4]);
+ }
+};
+
+
+// incomplete model, it can be inherited to make up different kinds of
+// instance type; the raw data is a vector of coefficients of the equation
+// of a circle curve
+template< typename InstanceType >
+class LFMCircleEquation
+ : public LinearFittingModelWithFixedTerms<Point, double, InstanceType>
+{
+ public:
+ void feed( VectorView & coeff, double & fixed_term, Point const& p ) const
+ {
+ coeff[0] = p[X];
+ coeff[1] = p[Y];
+ coeff[2] = 1;
+ fixed_term = p[X] * p[X] + p[Y] * p[Y];
+ }
+
+ size_t size() const
+ {
+ return 3;
+ }
+};
+
+
+// this model generates Ellipse curves
+class LFMCircle
+ : public LFMCircleEquation<Circle>
+{
+ public:
+ void instance(Circle & c, ConstVectorView const& coeff) const
+ {
+ c.setCoefficients(1, coeff[0], coeff[1], coeff[2]);
+ }
+};
+
+
+// this model generates SBasis objects
+class LFMSBasis
+ : public LinearFittingModel<double, double, SBasis>
+{
+ public:
+ LFMSBasis( size_t _order )
+ : m_size( 2*(_order+1) ),
+ m_order(_order)
+ {
+ }
+
+ void feed( VectorView & coeff, double t ) const
+ {
+ double u0 = 1-t;
+ double u1 = t;
+ double s = u0 * u1;
+ coeff[0] = u0;
+ coeff[1] = u1;
+ for (size_t i = 2; i < size(); i+=2)
+ {
+ u0 *= s;
+ u1 *= s;
+ coeff[i] = u0;
+ coeff[i+1] = u1;
+ }
+ }
+
+ size_t size() const
+ {
+ return m_size;
+ }
+
+ void instance(SBasis & sb, ConstVectorView const& raw_data) const
+ {
+ sb.resize(m_order+1);
+ for (unsigned int i = 0, k = 0; i < raw_data.size(); i+=2, ++k)
+ {
+ sb[k][0] = raw_data[i];
+ sb[k][1] = raw_data[i+1];
+ }
+ }
+
+ private:
+ size_t m_size;
+ size_t m_order;
+};
+
+
+// this model generates D2<SBasis> objects
+class LFMD2SBasis
+ : public LinearFittingModel< double, Point, D2<SBasis> >
+{
+ public:
+ LFMD2SBasis( size_t _order )
+ : mosb(_order)
+ {
+ }
+
+ void feed( VectorView & coeff, double t ) const
+ {
+ mosb.feed(coeff, t);
+ }
+
+ size_t size() const
+ {
+ return mosb.size();
+ }
+
+ void instance(D2<SBasis> & d2sb, ConstMatrixView const& raw_data) const
+ {
+ mosb.instance(d2sb[X], raw_data.column_const_view(X));
+ mosb.instance(d2sb[Y], raw_data.column_const_view(Y));
+ }
+
+ private:
+ LFMSBasis mosb;
+};
+
+
+// this model generates Bezier objects
+class LFMBezier
+ : public LinearFittingModel<double, double, Bezier>
+{
+ public:
+ LFMBezier( size_t _order )
+ : m_size(_order + 1),
+ m_order(_order)
+ {
+ binomial_coefficients(m_bc, m_order);
+ }
+
+ void feed( VectorView & coeff, double t ) const
+ {
+ double s = 1;
+ for (size_t i = 0; i < size(); ++i)
+ {
+ coeff[i] = s * m_bc[i];
+ s *= t;
+ }
+ double u = 1-t;
+ s = 1;
+ for (size_t i = size()-1; i > 0; --i)
+ {
+ coeff[i] *= s;
+ s *= u;
+ }
+ coeff[0] *= s;
+ }
+
+ size_t size() const
+ {
+ return m_size;
+ }
+
+ void instance(Bezier & b, ConstVectorView const& raw_data) const
+ {
+ assert(b.size() == raw_data.size());
+ for (unsigned int i = 0; i < raw_data.size(); ++i)
+ {
+ b[i] = raw_data[i];
+ }
+ }
+
+ private:
+ size_t m_size;
+ size_t m_order;
+ std::vector<size_t> m_bc;
+};
+
+
+// this model generates Bezier curves
+template <unsigned degree>
+class LFMBezierCurveN
+ : public LinearFittingModel< double, Point, BezierCurveN<degree> >
+{
+ public:
+ LFMBezierCurveN()
+ : mob(degree+1)
+ {
+ }
+
+ void feed( VectorView & coeff, double t ) const
+ {
+ mob.feed(coeff, t);
+ }
+
+ size_t size() const
+ {
+ return mob.size();
+ }
+
+ void instance(BezierCurveN<degree> & bc, ConstMatrixView const& raw_data) const
+ {
+ Bezier bx(degree);
+ Bezier by(degree);
+ mob.instance(bx, raw_data.column_const_view(X));
+ mob.instance(by, raw_data.column_const_view(Y));
+ bc = BezierCurveN<degree>(bx, by);
+ }
+
+ private:
+ LFMBezier mob;
+};
+
+} // end namespace NL
+} // end namespace Geom
+
+
+#endif // _NL_FITTING_MODEL_H_
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/numeric/fitting-tool.h b/src/3rdparty/2geom/include/2geom/numeric/fitting-tool.h
new file mode 100644
index 0000000..78d66ca
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/numeric/fitting-tool.h
@@ -0,0 +1,562 @@
+/*
+ * Fitting Tools
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#ifndef _NL_FITTING_TOOL_H_
+#define _NL_FITTING_TOOL_H_
+
+
+#include <2geom/numeric/vector.h>
+#include <2geom/numeric/matrix.h>
+
+#include <2geom/point.h>
+
+#include <vector>
+
+
+/*
+ * The least_square_fitter class represents a tool for solving a fitting
+ * problem with respect to a given model that represents an expression
+ * dependent from a parameter where the coefficients of this expression
+ * are the unknowns of the fitting problem.
+ * The minimizing solution is found by computing the pseudo-inverse
+ * of the problem matrix
+ */
+
+
+namespace Geom { namespace NL {
+
+namespace detail {
+
+template< typename ModelT>
+class lsf_base
+{
+ public:
+ typedef ModelT model_type;
+ typedef typename model_type::parameter_type parameter_type;
+ typedef typename model_type::value_type value_type;
+
+ lsf_base( model_type const& _model, size_t forecasted_samples )
+ : m_model(_model),
+ m_total_samples(0),
+ m_matrix(forecasted_samples, m_model.size()),
+ m_psdinv_matrix(NULL)
+ {
+ }
+
+ // compute pseudo inverse
+ void update()
+ {
+ if (total_samples() == 0) return;
+ if (m_psdinv_matrix != NULL)
+ {
+ delete m_psdinv_matrix;
+ }
+ MatrixView mv(m_matrix, 0, 0, total_samples(), m_matrix.columns());
+ m_psdinv_matrix = new Matrix( pseudo_inverse(mv) );
+ assert(m_psdinv_matrix != NULL);
+ }
+
+ size_t total_samples() const
+ {
+ return m_total_samples;
+ }
+
+ bool is_full() const
+ {
+ return (total_samples() == m_matrix.rows());
+ }
+
+ void clear()
+ {
+ m_total_samples = 0;
+ }
+
+ virtual
+ ~lsf_base()
+ {
+ if (m_psdinv_matrix != NULL)
+ {
+ delete m_psdinv_matrix;
+ }
+ }
+
+ protected:
+ const model_type & m_model;
+ size_t m_total_samples;
+ Matrix m_matrix;
+ Matrix* m_psdinv_matrix;
+
+}; // end class lsf_base
+
+
+
+
+template< typename ModelT, typename ValueType = typename ModelT::value_type>
+class lsf_solution
+{
+};
+
+// a fitting process on samples with value of type double
+// produces a solution of type Vector
+template< typename ModelT>
+class lsf_solution<ModelT, double>
+ : public lsf_base<ModelT>
+{
+public:
+ typedef ModelT model_type;
+ typedef typename model_type::parameter_type parameter_type;
+ typedef typename model_type::value_type value_type;
+ typedef Vector solution_type;
+ typedef lsf_base<model_type> base_type;
+
+ using base_type::m_model;
+ using base_type::m_psdinv_matrix;
+ using base_type::total_samples;
+
+public:
+ lsf_solution<ModelT, double>( model_type const& _model,
+ size_t forecasted_samples )
+ : base_type(_model, forecasted_samples),
+ m_solution(_model.size())
+ {
+ }
+
+ template< typename VectorT >
+ solution_type& result(VectorT const& sample_values)
+ {
+ assert(sample_values.size() == total_samples());
+ ConstVectorView sv(sample_values);
+ m_solution = (*m_psdinv_matrix) * sv;
+ return m_solution;
+ }
+
+ // a comparison between old sample values and the new ones is performed
+ // in order to minimize computation
+ // prerequisite:
+ // old_sample_values.size() == new_sample_values.size()
+ // no update() call can be performed between two result invocations
+ template< typename VectorT >
+ solution_type& result( VectorT const& old_sample_values,
+ VectorT const& new_sample_values )
+ {
+ assert(old_sample_values.size() == total_samples());
+ assert(new_sample_values.size() == total_samples());
+ Vector diff(total_samples());
+ for (size_t i = 0; i < diff.size(); ++i)
+ {
+ diff[i] = new_sample_values[i] - old_sample_values[i];
+ }
+ Vector column(m_model.size());
+ Vector delta(m_model.size(), 0.0);
+ for (size_t i = 0; i < diff.size(); ++i)
+ {
+ if (diff[i] != 0)
+ {
+ column = m_psdinv_matrix->column_view(i);
+ column.scale(diff[i]);
+ delta += column;
+ }
+ }
+ m_solution += delta;
+ return m_solution;
+ }
+
+ solution_type& result()
+ {
+ return m_solution;
+ }
+
+private:
+ solution_type m_solution;
+
+}; // end class lsf_solution<ModelT, double>
+
+
+// a fitting process on samples with value of type Point
+// produces a solution of type Matrix (with 2 columns)
+template< typename ModelT>
+class lsf_solution<ModelT, Point>
+ : public lsf_base<ModelT>
+{
+public:
+ typedef ModelT model_type;
+ typedef typename model_type::parameter_type parameter_type;
+ typedef typename model_type::value_type value_type;
+ typedef Matrix solution_type;
+ typedef lsf_base<model_type> base_type;
+
+ using base_type::m_model;
+ using base_type::m_psdinv_matrix;
+ using base_type::total_samples;
+
+public:
+ lsf_solution<ModelT, Point>( model_type const& _model,
+ size_t forecasted_samples )
+ : base_type(_model, forecasted_samples),
+ m_solution(_model.size(), 2)
+ {
+ }
+
+ solution_type& result(std::vector<Point> const& sample_values)
+ {
+ assert(sample_values.size() == total_samples());
+ Matrix svm(total_samples(), 2);
+ for (size_t i = 0; i < total_samples(); ++i)
+ {
+ svm(i, X) = sample_values[i][X];
+ svm(i, Y) = sample_values[i][Y];
+ }
+ m_solution = (*m_psdinv_matrix) * svm;
+ return m_solution;
+ }
+
+ // a comparison between old sample values and the new ones is performed
+ // in order to minimize computation
+ // prerequisite:
+ // old_sample_values.size() == new_sample_values.size()
+ // no update() call can to be performed between two result invocations
+ solution_type& result( std::vector<Point> const& old_sample_values,
+ std::vector<Point> const& new_sample_values )
+ {
+ assert(old_sample_values.size() == total_samples());
+ assert(new_sample_values.size() == total_samples());
+ Matrix diff(total_samples(), 2);
+ for (size_t i = 0; i < total_samples(); ++i)
+ {
+ diff(i, X) = new_sample_values[i][X] - old_sample_values[i][X];
+ diff(i, Y) = new_sample_values[i][Y] - old_sample_values[i][Y];
+ }
+ Vector column(m_model.size());
+ Matrix delta(m_model.size(), 2, 0.0);
+ VectorView deltax = delta.column_view(X);
+ VectorView deltay = delta.column_view(Y);
+ for (size_t i = 0; i < total_samples(); ++i)
+ {
+ if (diff(i, X) != 0)
+ {
+ column = m_psdinv_matrix->column_view(i);
+ column.scale(diff(i, X));
+ deltax += column;
+ }
+ if (diff(i, Y) != 0)
+ {
+ column = m_psdinv_matrix->column_view(i);
+ column.scale(diff(i, Y));
+ deltay += column;
+ }
+ }
+ m_solution += delta;
+ return m_solution;
+ }
+
+ solution_type& result()
+ {
+ return m_solution;
+ }
+
+private:
+ solution_type m_solution;
+
+}; // end class lsf_solution<ModelT, Point>
+
+
+
+
+template< typename ModelT,
+ bool WITH_FIXED_TERMS = ModelT::WITH_FIXED_TERMS >
+class lsf_with_fixed_terms
+{
+};
+
+
+// fitting tool for completely unknown models
+template< typename ModelT>
+class lsf_with_fixed_terms<ModelT, false>
+ : public lsf_solution<ModelT>
+{
+ public:
+ typedef ModelT model_type;
+ typedef typename model_type::parameter_type parameter_type;
+ typedef typename model_type::value_type value_type;
+ typedef lsf_solution<model_type> base_type;
+ typedef typename base_type::solution_type solution_type;
+
+ using base_type::total_samples;
+ using base_type::is_full;
+ using base_type::m_matrix;
+ using base_type::m_total_samples;
+ using base_type::m_model;
+
+ public:
+ lsf_with_fixed_terms<ModelT, false>( model_type const& _model,
+ size_t forecasted_samples )
+ : base_type(_model, forecasted_samples)
+ {
+ }
+
+ void append(parameter_type const& sample_parameter)
+ {
+ assert(!is_full());
+ VectorView row = m_matrix.row_view(total_samples());
+ m_model.feed(row, sample_parameter);
+ ++m_total_samples;
+ }
+
+ void append_copy(size_t sample_index)
+ {
+ assert(!is_full());
+ assert(sample_index < total_samples());
+ VectorView dest_row = m_matrix.row_view(total_samples());
+ VectorView source_row = m_matrix.row_view(sample_index);
+ dest_row = source_row;
+ ++m_total_samples;
+ }
+
+}; // end class lsf_with_fixed_terms<ModelT, false>
+
+
+// fitting tool for partially known models
+template< typename ModelT>
+class lsf_with_fixed_terms<ModelT, true>
+ : public lsf_solution<ModelT>
+{
+ public:
+ typedef ModelT model_type;
+ typedef typename model_type::parameter_type parameter_type;
+ typedef typename model_type::value_type value_type;
+ typedef lsf_solution<model_type> base_type;
+ typedef typename base_type::solution_type solution_type;
+
+ using base_type::total_samples;
+ using base_type::is_full;
+ using base_type::m_matrix;
+ using base_type::m_total_samples;
+ using base_type::m_model;
+
+ public:
+ lsf_with_fixed_terms<ModelT, true>( model_type const& _model,
+ size_t forecasted_samples )
+ : base_type(_model, forecasted_samples),
+ m_vector(forecasted_samples),
+ m_vector_view(NULL)
+ {
+ }
+ void append(parameter_type const& sample_parameter)
+ {
+ assert(!is_full());
+ VectorView row = m_matrix.row_view(total_samples());
+ m_model.feed(row, m_vector[total_samples()], sample_parameter);
+ ++m_total_samples;
+ }
+
+ void append_copy(size_t sample_index)
+ {
+ assert(!is_full());
+ assert(sample_index < total_samples());
+ VectorView dest_row = m_matrix.row_view(total_samples());
+ VectorView source_row = m_matrix.row_view(sample_index);
+ dest_row = source_row;
+ m_vector[total_samples()] = m_vector[sample_index];
+ ++m_total_samples;
+ }
+
+ void update()
+ {
+ base_type::update();
+ if (total_samples() == 0) return;
+ if (m_vector_view != NULL)
+ {
+ delete m_vector_view;
+ }
+ m_vector_view = new VectorView(m_vector, base_type::total_samples());
+ assert(m_vector_view != NULL);
+ }
+
+
+ ~lsf_with_fixed_terms<model_type, true>() override
+ {
+ if (m_vector_view != NULL)
+ {
+ delete m_vector_view;
+ }
+ }
+
+ protected:
+ Vector m_vector;
+ VectorView* m_vector_view;
+
+}; // end class lsf_with_fixed_terms<ModelT, true>
+
+
+} // end namespace detail
+
+
+
+
+template< typename ModelT,
+ typename ValueType = typename ModelT::value_type,
+ bool WITH_FIXED_TERMS = ModelT::WITH_FIXED_TERMS >
+class least_squeares_fitter
+{
+};
+
+
+template< typename ModelT, typename ValueType >
+class least_squeares_fitter<ModelT, ValueType, false>
+ : public detail::lsf_with_fixed_terms<ModelT>
+{
+ public:
+ typedef ModelT model_type;
+ typedef detail::lsf_with_fixed_terms<model_type> base_type;
+ typedef typename base_type::parameter_type parameter_type;
+ typedef typename base_type::value_type value_type;
+ typedef typename base_type::solution_type solution_type;
+
+ public:
+ least_squeares_fitter<ModelT, ValueType, false>( model_type const& _model,
+ size_t forecasted_samples )
+ : base_type(_model, forecasted_samples)
+ {
+ }
+}; // end class least_squeares_fitter<ModelT, ValueType, true>
+
+
+template< typename ModelT>
+class least_squeares_fitter<ModelT, double, true>
+ : public detail::lsf_with_fixed_terms<ModelT>
+{
+ public:
+ typedef ModelT model_type;
+ typedef detail::lsf_with_fixed_terms<model_type> base_type;
+ typedef typename base_type::parameter_type parameter_type;
+ typedef typename base_type::value_type value_type;
+ typedef typename base_type::solution_type solution_type;
+
+ using base_type::m_vector_view;
+ //using base_type::result; // VSC legacy support
+ solution_type& result( std::vector<Point> const& old_sample_values,
+ std::vector<Point> const& new_sample_values )
+ {
+ return base_type::result(old_sample_values, new_sample_values);
+ }
+
+ solution_type& result()
+ {
+ return base_type::result();
+ }
+
+ public:
+ least_squeares_fitter<ModelT, double, true>( model_type const& _model,
+ size_t forecasted_samples )
+ : base_type(_model, forecasted_samples)
+ {
+ }
+
+ template< typename VectorT >
+ solution_type& result(VectorT const& sample_values)
+ {
+ assert(sample_values.size() == m_vector_view->size());
+ Vector sv(sample_values.size());
+ for (size_t i = 0; i < sv.size(); ++i)
+ sv[i] = sample_values[i] - (*m_vector_view)[i];
+ return base_type::result(sv);
+ }
+
+}; // end class least_squeares_fitter<ModelT, double, true>
+
+
+template< typename ModelT>
+class least_squeares_fitter<ModelT, Point, true>
+ : public detail::lsf_with_fixed_terms<ModelT>
+{
+ public:
+ typedef ModelT model_type;
+ typedef detail::lsf_with_fixed_terms<model_type> base_type;
+ typedef typename base_type::parameter_type parameter_type;
+ typedef typename base_type::value_type value_type;
+ typedef typename base_type::solution_type solution_type;
+
+ using base_type::m_vector_view;
+ //using base_type::result; // VCS legacy support
+ solution_type& result( std::vector<Point> const& old_sample_values,
+ std::vector<Point> const& new_sample_values )
+ {
+ return base_type::result(old_sample_values, new_sample_values);
+ }
+
+ solution_type& result()
+ {
+ return base_type::result();
+ }
+
+
+ public:
+ least_squeares_fitter<ModelT, Point, true>( model_type const& _model,
+ size_t forecasted_samples )
+ : base_type(_model, forecasted_samples)
+ {
+ }
+
+ solution_type& result(std::vector<Point> const& sample_values)
+ {
+ assert(sample_values.size() == m_vector_view->size());
+ NL::Matrix sv(sample_values.size(), 2);
+ for (size_t i = 0; i < sample_values.size(); ++i)
+ {
+ sv(i, X) = sample_values[i][X] - (*m_vector_view)[i];
+ sv(i, Y) = sample_values[i][Y] - (*m_vector_view)[i];
+ }
+ return base_type::result(sv);
+ }
+
+}; // end class least_squeares_fitter<ModelT, Point, true>
+
+
+} // end namespace NL
+} // end namespace Geom
+
+
+
+#endif // _NL_FITTING_TOOL_H_
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/numeric/linear_system.h b/src/3rdparty/2geom/include/2geom/numeric/linear_system.h
new file mode 100644
index 0000000..f793e20
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/numeric/linear_system.h
@@ -0,0 +1,138 @@
+/*
+ * LinearSystem class wraps some gsl routines for solving linear systems
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#ifndef _NL_LINEAR_SYSTEM_H_
+#define _NL_LINEAR_SYSTEM_H_
+
+
+#include <cassert>
+
+#include <gsl/gsl_linalg.h>
+
+#include <2geom/numeric/matrix.h>
+#include <2geom/numeric/vector.h>
+
+
+namespace Geom { namespace NL {
+
+
+class LinearSystem
+{
+public:
+ LinearSystem(MatrixView & _matrix, VectorView & _vector)
+ : m_matrix(_matrix), m_vector(_vector), m_solution(_matrix.columns())
+ {
+ }
+
+ LinearSystem(Matrix & _matrix, Vector & _vector)
+ : m_matrix(_matrix), m_vector(_vector), m_solution(_matrix.columns())
+ {
+ }
+
+ const Vector & LU_solve()
+ {
+ assert( matrix().rows() == matrix().columns()
+ && matrix().rows() == vector().size() );
+ int s;
+ gsl_permutation * p = gsl_permutation_alloc(matrix().rows());
+ gsl_linalg_LU_decomp (matrix().get_gsl_matrix(), p, &s);
+ gsl_linalg_LU_solve( matrix().get_gsl_matrix(),
+ p,
+ vector().get_gsl_vector(),
+ m_solution.get_gsl_vector()
+ );
+ gsl_permutation_free(p);
+ return solution();
+ }
+
+ const Vector & SV_solve()
+ {
+ assert( matrix().rows() >= matrix().columns()
+ && matrix().rows() == vector().size() );
+
+ gsl_matrix* U = matrix().get_gsl_matrix();
+ gsl_matrix* V = gsl_matrix_alloc(matrix().columns(), matrix().columns());
+ gsl_vector* S = gsl_vector_alloc(matrix().columns());
+ gsl_vector* work = gsl_vector_alloc(matrix().columns());
+
+ gsl_linalg_SV_decomp( U, V, S, work );
+
+ gsl_vector* b = vector().get_gsl_vector();
+ gsl_vector* x = m_solution.get_gsl_vector();
+
+ gsl_linalg_SV_solve( U, V, S, b, x);
+
+ gsl_matrix_free(V);
+ gsl_vector_free(S);
+ gsl_vector_free(work);
+
+ return solution();
+ }
+
+ MatrixView & matrix()
+ {
+ return m_matrix;
+ }
+
+ VectorView & vector()
+ {
+ return m_vector;
+ }
+
+ const Vector & solution() const
+ {
+ return m_solution;
+ }
+
+private:
+ MatrixView m_matrix;
+ VectorView m_vector;
+ Vector m_solution;
+};
+
+
+} } // end namespaces
+
+
+#endif /*_NL_LINEAR_SYSTEM_H_*/
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/numeric/matrix.h b/src/3rdparty/2geom/include/2geom/numeric/matrix.h
new file mode 100644
index 0000000..02851b4
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/numeric/matrix.h
@@ -0,0 +1,603 @@
+/*
+ * Matrix, MatrixView, ConstMatrixView classes wrap the gsl matrix routines;
+ * "views" mimic the semantic of C++ references: any operation performed
+ * on a "view" is actually performed on the "viewed object"
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+
+
+#ifndef _NL_MATRIX_H_
+#define _NL_MATRIX_H_
+
+#include <2geom/exception.h>
+#include <2geom/numeric/vector.h>
+
+#include <cassert>
+#include <utility> // for std::pair
+#include <algorithm> // for std::swap
+#include <sstream>
+#include <string>
+#include <gsl/gsl_matrix.h>
+#include <gsl/gsl_linalg.h>
+
+
+namespace Geom { namespace NL {
+
+namespace detail
+{
+
+class BaseMatrixImpl
+{
+ public:
+ virtual ~BaseMatrixImpl()
+ {
+ }
+
+ ConstVectorView row_const_view(size_t i) const
+ {
+ return ConstVectorView(gsl_matrix_const_row(m_matrix, i));
+ }
+
+ ConstVectorView column_const_view(size_t i) const
+ {
+ return ConstVectorView(gsl_matrix_const_column(m_matrix, i));
+ }
+
+ const double & operator() (size_t i, size_t j) const
+ {
+ return *gsl_matrix_const_ptr(m_matrix, i, j);
+ }
+
+ const gsl_matrix* get_gsl_matrix() const
+ {
+ return m_matrix;
+ }
+
+ bool is_zero() const
+ {
+ return gsl_matrix_isnull(m_matrix);
+ }
+
+ bool is_positive() const
+ {
+ for ( unsigned int i = 0; i < rows(); ++i )
+ {
+ for ( unsigned int j = 0; j < columns(); ++j )
+ {
+ if ( (*this)(i,j) <= 0 ) return false;
+ }
+ }
+ return true;
+ }
+
+ bool is_negative() const
+ {
+ for ( unsigned int i = 0; i < rows(); ++i )
+ {
+ for ( unsigned int j = 0; j < columns(); ++j )
+ {
+ if ( (*this)(i,j) >= 0 ) return false;
+ }
+ }
+ return true;
+ }
+
+ bool is_non_negative() const
+ {
+ for ( unsigned int i = 0; i < rows(); ++i )
+ {
+ for ( unsigned int j = 0; j < columns(); ++j )
+ {
+ if ( (*this)(i,j) < 0 ) return false;
+ }
+ }
+ return true;
+ }
+
+ double max() const
+ {
+ return gsl_matrix_max(m_matrix);
+ }
+
+ double min() const
+ {
+ return gsl_matrix_min(m_matrix);
+ }
+
+ std::pair<size_t, size_t>
+ max_index() const
+ {
+ std::pair<size_t, size_t> indices;
+ gsl_matrix_max_index(m_matrix, &(indices.first), &(indices.second));
+ return indices;
+ }
+
+ std::pair<size_t, size_t>
+ min_index() const
+ {
+ std::pair<size_t, size_t> indices;
+ gsl_matrix_min_index(m_matrix, &(indices.first), &(indices.second));
+ return indices;
+ }
+
+ size_t rows() const
+ {
+ return m_rows;
+ }
+
+ size_t columns() const
+ {
+ return m_columns;
+ }
+
+ std::string str() const;
+
+ protected:
+ size_t m_rows, m_columns;
+ gsl_matrix* m_matrix;
+
+}; // end class BaseMatrixImpl
+
+
+inline
+bool operator== (BaseMatrixImpl const& m1, BaseMatrixImpl const& m2)
+{
+ if (m1.rows() != m2.rows() || m1.columns() != m2.columns()) return false;
+
+ for (size_t i = 0; i < m1.rows(); ++i)
+ for (size_t j = 0; j < m1.columns(); ++j)
+ if (m1(i,j) != m2(i,j)) return false;
+
+ return true;
+}
+
+template< class charT >
+inline
+std::basic_ostream<charT> &
+operator<< (std::basic_ostream<charT> & os, const BaseMatrixImpl & _matrix)
+{
+ if (_matrix.rows() == 0 || _matrix.columns() == 0) return os;
+
+ os << "[[" << _matrix(0,0);
+ for (size_t j = 1; j < _matrix.columns(); ++j)
+ {
+ os << ", " << _matrix(0,j);
+ }
+ os << "]";
+
+ for (size_t i = 1; i < _matrix.rows(); ++i)
+ {
+ os << ", [" << _matrix(i,0);
+ for (size_t j = 1; j < _matrix.columns(); ++j)
+ {
+ os << ", " << _matrix(i,j);
+ }
+ os << "]";
+ }
+ os << "]";
+ return os;
+}
+
+inline
+std::string BaseMatrixImpl::str() const
+{
+ std::ostringstream oss;
+ oss << (*this);
+ return oss.str();
+}
+
+
+class MatrixImpl : public BaseMatrixImpl
+{
+ public:
+
+ typedef BaseMatrixImpl base_type;
+
+ void set_all( double x )
+ {
+ gsl_matrix_set_all(m_matrix, x);
+ }
+
+ void set_identity()
+ {
+ gsl_matrix_set_identity(m_matrix);
+ }
+
+ using base_type::operator(); // VSC legacy support
+ const double & operator() (size_t i, size_t j) const
+ {
+ return base_type::operator ()(i, j);
+ }
+
+ double & operator() (size_t i, size_t j)
+ {
+ return *gsl_matrix_ptr(m_matrix, i, j);
+ }
+
+ using base_type::get_gsl_matrix;
+
+ gsl_matrix* get_gsl_matrix()
+ {
+ return m_matrix;
+ }
+
+ VectorView row_view(size_t i)
+ {
+ return VectorView(gsl_matrix_row(m_matrix, i));
+ }
+
+ VectorView column_view(size_t i)
+ {
+ return VectorView(gsl_matrix_column(m_matrix, i));
+ }
+
+ void swap_rows(size_t i, size_t j)
+ {
+ gsl_matrix_swap_rows(m_matrix, i, j);
+ }
+
+ void swap_columns(size_t i, size_t j)
+ {
+ gsl_matrix_swap_columns(m_matrix, i, j);
+ }
+
+ MatrixImpl & transpose()
+ {
+ assert(columns() == rows());
+ gsl_matrix_transpose(m_matrix);
+ return (*this);
+ }
+
+ MatrixImpl & scale(double x)
+ {
+ gsl_matrix_scale(m_matrix, x);
+ return (*this);
+ }
+
+ MatrixImpl & translate(double x)
+ {
+ gsl_matrix_add_constant(m_matrix, x);
+ return (*this);
+ }
+
+ MatrixImpl & operator+=(base_type const& _matrix)
+ {
+ gsl_matrix_add(m_matrix, _matrix.get_gsl_matrix());
+ return (*this);
+ }
+
+ MatrixImpl & operator-=(base_type const& _matrix)
+ {
+ gsl_matrix_sub(m_matrix, _matrix.get_gsl_matrix());
+ return (*this);
+ }
+
+}; // end class MatrixImpl
+
+} // end namespace detail
+
+
+using detail::operator==;
+using detail::operator<<;
+
+
+template <size_t N>
+class ConstBaseSymmetricMatrix;
+
+
+class Matrix: public detail::MatrixImpl
+{
+ public:
+ typedef detail::MatrixImpl base_type;
+
+ public:
+ // the matrix is not initialized
+ Matrix(size_t n1, size_t n2)
+ {
+ m_rows = n1;
+ m_columns = n2;
+ m_matrix = gsl_matrix_alloc(n1, n2);
+ }
+
+ Matrix(size_t n1, size_t n2, double x)
+ {
+ m_rows = n1;
+ m_columns = n2;
+ m_matrix = gsl_matrix_alloc(n1, n2);
+ gsl_matrix_set_all(m_matrix, x);
+ }
+
+ Matrix(Matrix const& _matrix)
+ : base_type()
+ {
+ m_rows = _matrix.rows();
+ m_columns = _matrix.columns();
+ m_matrix = gsl_matrix_alloc(rows(), columns());
+ gsl_matrix_memcpy(m_matrix, _matrix.get_gsl_matrix());
+ }
+
+ explicit
+ Matrix(base_type::base_type const& _matrix)
+ {
+ m_rows = _matrix.rows();
+ m_columns = _matrix.columns();
+ m_matrix = gsl_matrix_alloc(rows(), columns());
+ gsl_matrix_memcpy(m_matrix, _matrix.get_gsl_matrix());
+ }
+
+ template <size_t N>
+ explicit
+ Matrix(ConstBaseSymmetricMatrix<N> const& _smatrix)
+ {
+ m_rows = N;
+ m_columns = N;
+ m_matrix = gsl_matrix_alloc(N, N);
+ for (size_t i = 0; i < N; ++i)
+ for (size_t j = 0; j < N ; ++j)
+ (*gsl_matrix_ptr(m_matrix, i, j)) = _smatrix(i,j);
+ }
+
+ Matrix & operator=(Matrix const& _matrix)
+ {
+ assert( rows() == _matrix.rows() && columns() == _matrix.columns() );
+ gsl_matrix_memcpy(m_matrix, _matrix.get_gsl_matrix());
+ return *this;
+ }
+
+ Matrix & operator=(base_type::base_type const& _matrix)
+ {
+ assert( rows() == _matrix.rows() && columns() == _matrix.columns() );
+ gsl_matrix_memcpy(m_matrix, _matrix.get_gsl_matrix());
+ return *this;
+ }
+
+ template <size_t N>
+ Matrix & operator=(ConstBaseSymmetricMatrix<N> const& _smatrix)
+ {
+ assert (rows() == N && columns() == N);
+ for (size_t i = 0; i < N; ++i)
+ for (size_t j = 0; j < N ; ++j)
+ (*this)(i,j) = _smatrix(i,j);
+ return *this;
+ }
+
+ ~Matrix() override
+ {
+ gsl_matrix_free(m_matrix);
+ }
+
+ Matrix & transpose()
+ {
+ return static_cast<Matrix &>( base_type::transpose() );
+ }
+
+ Matrix & scale(double x)
+ {
+ return static_cast<Matrix &>( base_type::scale(x) );
+ }
+
+ Matrix & translate(double x)
+ {
+ return static_cast<Matrix &>( base_type::translate(x) );
+ }
+
+ Matrix & operator+=(base_type::base_type const& _matrix)
+ {
+ return static_cast<Matrix &>( base_type::operator+=(_matrix) );
+ }
+
+ Matrix & operator-=(base_type::base_type const& _matrix)
+ {
+ return static_cast<Matrix &>( base_type::operator-=(_matrix) );
+ }
+
+ friend
+ void swap(Matrix & m1, Matrix & m2);
+ friend
+ void swap_any(Matrix & m1, Matrix & m2);
+
+}; // end class Matrix
+
+
+// warning! this operation invalidates any view of the passed matrix objects
+inline
+void swap(Matrix & m1, Matrix & m2)
+{
+ assert(m1.rows() == m2.rows() && m1.columns() == m2.columns());
+ using std::swap;
+ swap(m1.m_matrix, m2.m_matrix);
+}
+
+inline void swap_any(Matrix &m1, Matrix &m2)
+{
+ using std::swap;
+ swap(m1.m_matrix, m2.m_matrix);
+ swap(m1.m_rows, m2.m_rows);
+ swap(m1.m_columns, m2.m_columns);
+}
+
+
+
+class ConstMatrixView : public detail::BaseMatrixImpl
+{
+ public:
+ typedef detail::BaseMatrixImpl base_type;
+
+ public:
+ ConstMatrixView(const base_type & _matrix, size_t k1, size_t k2, size_t n1, size_t n2)
+ : m_matrix_view( gsl_matrix_const_submatrix(_matrix.get_gsl_matrix(), k1, k2, n1, n2) )
+ {
+ m_rows = n1;
+ m_columns = n2;
+ m_matrix = const_cast<gsl_matrix*>( &(m_matrix_view.matrix) );
+ }
+
+ ConstMatrixView(const ConstMatrixView & _matrix)
+ : base_type(),
+ m_matrix_view(_matrix.m_matrix_view)
+ {
+ m_rows = _matrix.rows();
+ m_columns = _matrix.columns();
+ m_matrix = const_cast<gsl_matrix*>( &(m_matrix_view.matrix) );
+ }
+
+ ConstMatrixView(const base_type & _matrix)
+ : m_matrix_view(gsl_matrix_const_submatrix(_matrix.get_gsl_matrix(), 0, 0, _matrix.rows(), _matrix.columns()))
+ {
+ m_rows = _matrix.rows();
+ m_columns = _matrix.columns();
+ m_matrix = const_cast<gsl_matrix*>( &(m_matrix_view.matrix) );
+ }
+
+ private:
+ gsl_matrix_const_view m_matrix_view;
+
+}; // end class ConstMatrixView
+
+
+
+
+class MatrixView : public detail::MatrixImpl
+{
+ public:
+ typedef detail::MatrixImpl base_type;
+
+ public:
+ MatrixView(base_type & _matrix, size_t k1, size_t k2, size_t n1, size_t n2)
+ {
+ m_rows = n1;
+ m_columns = n2;
+ m_matrix_view
+ = gsl_matrix_submatrix(_matrix.get_gsl_matrix(), k1, k2, n1, n2);
+ m_matrix = &(m_matrix_view.matrix);
+ }
+
+ MatrixView(const MatrixView & _matrix)
+ : base_type()
+ {
+ m_rows = _matrix.rows();
+ m_columns = _matrix.columns();
+ m_matrix_view = _matrix.m_matrix_view;
+ m_matrix = &(m_matrix_view.matrix);
+ }
+
+ MatrixView(Matrix & _matrix)
+ {
+ m_rows = _matrix.rows();
+ m_columns = _matrix.columns();
+ m_matrix_view
+ = gsl_matrix_submatrix(_matrix.get_gsl_matrix(), 0, 0, rows(), columns());
+ m_matrix = &(m_matrix_view.matrix);
+ }
+
+ MatrixView & operator=(MatrixView const& _matrix)
+ {
+ assert( rows() == _matrix.rows() && columns() == _matrix.columns() );
+ gsl_matrix_memcpy(m_matrix, _matrix.m_matrix);
+ return *this;
+ }
+
+ MatrixView & operator=(base_type::base_type const& _matrix)
+ {
+ assert( rows() == _matrix.rows() && columns() == _matrix.columns() );
+ gsl_matrix_memcpy(m_matrix, _matrix.get_gsl_matrix());
+ return *this;
+ }
+
+ MatrixView & transpose()
+ {
+ return static_cast<MatrixView &>( base_type::transpose() );
+ }
+
+ MatrixView & scale(double x)
+ {
+ return static_cast<MatrixView &>( base_type::scale(x) );
+ }
+
+ MatrixView & translate(double x)
+ {
+ return static_cast<MatrixView &>( base_type::translate(x) );
+ }
+
+ MatrixView & operator+=(base_type::base_type const& _matrix)
+ {
+ return static_cast<MatrixView &>( base_type::operator+=(_matrix) );
+ }
+
+ MatrixView & operator-=(base_type::base_type const& _matrix)
+ {
+ return static_cast<MatrixView &>( base_type::operator-=(_matrix) );
+ }
+
+ friend
+ void swap_view(MatrixView & m1, MatrixView & m2);
+
+ private:
+ gsl_matrix_view m_matrix_view;
+
+}; // end class MatrixView
+
+
+inline
+void swap_view(MatrixView & m1, MatrixView & m2)
+{
+ assert(m1.rows() == m2.rows() && m1.columns() == m2.columns());
+ using std::swap;
+ swap(m1.m_matrix_view, m2.m_matrix_view);
+}
+
+Vector operator*( detail::BaseMatrixImpl const& A,
+ detail::BaseVectorImpl const& v );
+
+Matrix operator*( detail::BaseMatrixImpl const& A,
+ detail::BaseMatrixImpl const& B );
+
+Matrix pseudo_inverse(detail::BaseMatrixImpl const& A);
+
+double trace (detail::BaseMatrixImpl const& A);
+
+double det (detail::BaseMatrixImpl const& A);
+
+} } // end namespaces
+
+#endif /*_NL_MATRIX_H_*/
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/numeric/symmetric-matrix-fs-operation.h b/src/3rdparty/2geom/include/2geom/numeric/symmetric-matrix-fs-operation.h
new file mode 100644
index 0000000..c5aaa72
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/numeric/symmetric-matrix-fs-operation.h
@@ -0,0 +1,102 @@
+/*
+ * SymmetricMatrix basic operation
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2009 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef _NL_SYMMETRIC_MATRIX_FS_OPERATION_H_
+#define _NL_SYMMETRIC_MATRIX_FS_OPERATION_H_
+
+
+#include <2geom/numeric/symmetric-matrix-fs.h>
+#include <2geom/numeric/symmetric-matrix-fs-trace.h>
+
+
+
+
+namespace Geom { namespace NL {
+
+template <size_t N>
+SymmetricMatrix<N> adj(const ConstBaseSymmetricMatrix<N> & S);
+
+template <>
+inline
+SymmetricMatrix<2> adj(const ConstBaseSymmetricMatrix<2> & S)
+{
+ SymmetricMatrix<2> result;
+ result.get<0,0>() = S.get<1,1>();
+ result.get<1,0>() = -S.get<1,0>();
+ result.get<1,1>() = S.get<0,0>();
+ return result;
+}
+
+template <>
+inline
+SymmetricMatrix<3> adj(const ConstBaseSymmetricMatrix<3> & S)
+{
+ SymmetricMatrix<3> result;
+
+ result.get<0,0>() = S.get<1,1>() * S.get<2,2>() - S.get<1,2>() * S.get<2,1>();
+ result.get<1,0>() = S.get<0,2>() * S.get<2,1>() - S.get<0,1>() * S.get<2,2>();
+ result.get<1,1>() = S.get<0,0>() * S.get<2,2>() - S.get<0,2>() * S.get<2,0>();
+ result.get<2,0>() = S.get<0,1>() * S.get<1,2>() - S.get<0,2>() * S.get<1,1>();
+ result.get<2,1>() = S.get<0,2>() * S.get<1,0>() - S.get<0,0>() * S.get<1,2>();
+ result.get<2,2>() = S.get<0,0>() * S.get<1,1>() - S.get<0,1>() * S.get<1,0>();
+ return result;
+}
+
+template <size_t N>
+inline
+SymmetricMatrix<N> inverse(const ConstBaseSymmetricMatrix<N> & S)
+{
+ SymmetricMatrix<N> result = adj(S);
+ double d = det(S);
+ assert (d != 0);
+ result.scale (1/d);
+ return result;
+}
+
+} /* end namespace NL*/ } /* end namespace Geom*/
+
+
+#endif // _NL_SYMMETRIC_MATRIX_FS_OPERATION_H_
+
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/numeric/symmetric-matrix-fs-trace.h b/src/3rdparty/2geom/include/2geom/numeric/symmetric-matrix-fs-trace.h
new file mode 100644
index 0000000..0e7a28c
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/numeric/symmetric-matrix-fs-trace.h
@@ -0,0 +1,427 @@
+/*
+ * SymmetricMatrix trace
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2009 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#ifndef _NL_TRACE_H_
+#define _NL_TRACE_H_
+
+
+#include <2geom/numeric/matrix.h>
+#include <2geom/numeric/symmetric-matrix-fs.h>
+
+
+
+
+
+namespace Geom { namespace NL {
+
+
+namespace detail
+{
+
+/*
+ * helper routines
+ */
+
+inline
+int sgn_prod (int x, int y)
+{
+ if (x == 0 || y == 0) return 0;
+ if (x == y) return 1;
+ return -1;
+}
+
+inline
+bool abs_less (double x, double y)
+{
+ return (std::fabs(x) < std::fabs(y));
+}
+
+
+/*
+ * trace K-th of symmetric matrix S of order N
+ */
+template <size_t K, size_t N>
+struct trace
+{
+ static double evaluate(const ConstBaseSymmetricMatrix<N> &S);
+};
+
+template <size_t N>
+struct trace<1,N>
+{
+ static
+ double evaluate (const ConstBaseSymmetricMatrix<N> & S)
+ {
+ double t = 0;
+ for (size_t i = 0; i < N; ++i)
+ {
+ t += S(i,i);
+ }
+ return t;
+ }
+};
+
+template <size_t N>
+struct trace<N,N>
+{
+ static
+ double evaluate (const ConstBaseSymmetricMatrix<N> & S)
+ {
+ Matrix M(S);
+ return det(M);
+ }
+};
+
+/*
+ * trace for symmetric matrix of order 2
+ */
+template <>
+struct trace<1,2>
+{
+ static
+ double evaluate (const ConstBaseSymmetricMatrix<2> & S)
+ {
+ return (S.get<0,0>() + S.get<1,1>());
+ }
+};
+
+template <>
+struct trace<2,2>
+{
+ static
+ double evaluate (const ConstBaseSymmetricMatrix<2> & S)
+ {
+ return (S.get<0,0>() * S.get<1,1>() - S.get<0,1>() * S.get<1,0>());
+ }
+};
+
+
+/*
+ * trace for symmetric matrix of order 3
+ */
+template <>
+struct trace<1,3>
+{
+ static
+ double evaluate (const ConstBaseSymmetricMatrix<3> & S)
+ {
+ return (S.get<0,0>() + S.get<1,1>() + S.get<2,2>());
+ }
+};
+
+template <>
+struct trace<2,3>
+{
+ static
+ double evaluate (const ConstBaseSymmetricMatrix<3> & S)
+ {
+ double a00 = S.get<1,1>() * S.get<2,2>() - S.get<1,2>() * S.get<2,1>();
+ double a11 = S.get<0,0>() * S.get<2,2>() - S.get<0,2>() * S.get<2,0>();
+ double a22 = S.get<0,0>() * S.get<1,1>() - S.get<0,1>() * S.get<1,0>();
+ return (a00 + a11 + a22);
+ }
+};
+
+template <>
+struct trace<3,3>
+{
+ static
+ double evaluate (const ConstBaseSymmetricMatrix<3> & S)
+ {
+ double d = S.get<0,0>() * S.get<1,1>() * S.get<2,2>();
+ d += (2 * S.get<1,0>() * S.get<2,0>() * S.get<2,1>());
+ d -= (S.get<0,0>() * S.get<2,1>() * S.get<2,1>());
+ d -= (S.get<1,1>() * S.get<2,0>() * S.get<2,0>());
+ d -= (S.get<2,2>() * S.get<1,0>() * S.get<1,0>());
+ return d;
+ }
+};
+
+
+/*
+ * sign of trace K-th
+ */
+template <size_t K, size_t N>
+struct trace_sgn
+{
+ static
+ int evaluate (const ConstBaseSymmetricMatrix<N> & S)
+ {
+ double d = trace<K, N>::evaluate(S);
+ return sgn(d);
+ }
+};
+
+
+/*
+ * sign of trace for symmetric matrix of order 2
+ */
+template <>
+struct trace_sgn<2,2>
+{
+ static
+ int evaluate (const ConstBaseSymmetricMatrix<2> & S)
+ {
+ double m00 = S.get<0,0>();
+ double m10 = S.get<1,0>();
+ double m11 = S.get<1,1>();
+
+ int sm00 = sgn (m00);
+ int sm10 = sgn (m10);
+ int sm11 = sgn (m11);
+
+ if (sm10 == 0)
+ {
+ return sgn_prod (sm00, sm11);
+ }
+ else
+ {
+ int sm00m11 = sgn_prod (sm00, sm11);
+ if (sm00m11 == 1)
+ {
+ int e00, e10, e11;
+ double f00 = std::frexp (m00, &e00);
+ double f10 = std::frexp (m10, &e10);
+ double f11 = std::frexp (m11, &e11);
+
+ int e0011 = e00 + e11;
+ int e1010 = e10 << 1;
+ int ed = e0011 - e1010;
+
+ if (ed > 1)
+ {
+ return 1;
+ }
+ else if (ed < -1)
+ {
+ return -1;
+ }
+ else
+ {
+ double d = std::ldexp (f00 * f11, ed) - f10 * f10;
+ //std::cout << "trace_sgn<2,2>: det = " << d << std::endl;
+ double eps = std::ldexp (1, -50);
+ if (std::fabs(d) < eps) return 0;
+ return sgn (d);
+ }
+ }
+ return -1;
+ }
+ }
+};
+
+
+/*
+ * sign of trace for symmetric matrix of order 3
+ */
+template <>
+struct trace_sgn<2,3>
+{
+ static
+ int evaluate (const ConstBaseSymmetricMatrix<3> & S)
+ {
+ double eps = std::ldexp (1, -50);
+ double t[6];
+
+ t[0] = S.get<1,1>() * S.get<2,2>();
+ t[1] = - S.get<1,2>() * S.get<2,1>();
+ t[2] = S.get<0,0>() * S.get<2,2>();
+ t[3] = - S.get<0,2>() * S.get<2,0>();
+ t[4] = S.get<0,0>() * S.get<1,1>();
+ t[5] = - S.get<0,1>() * S.get<1,0>();
+
+
+ double* maxp = std::max_element (t, t+6, abs_less);
+ int em;
+ std::frexp(*maxp, &em);
+ double d = 0;
+ for (double i : t)
+ {
+ d += i;
+ }
+ double r = std::fabs (std::ldexp (d, -em)); // relative error
+ //std::cout << "trace_sgn<2,3>: d = " << d << std::endl;
+ //std::cout << "trace_sgn<2,3>: r = " << r << std::endl;
+ if (r < eps) return 0;
+ if (d > 0) return 1;
+ return -1;
+ }
+};
+
+template <>
+struct trace_sgn<3,3>
+{
+ static
+ int evaluate (const ConstBaseSymmetricMatrix<3> & S)
+ {
+
+ double eps = std::ldexp (1, -48);
+ double t[5];
+
+ t[0] = S.get<0,0>() * S.get<1,1>() * S.get<2,2>();
+ t[1] = 2 * S.get<1,0>() * S.get<2,0>() * S.get<2,1>();
+ t[2] = -(S.get<0,0>() * S.get<2,1>() * S.get<2,1>());
+ t[3] = -(S.get<1,1>() * S.get<2,0>() * S.get<2,0>());
+ t[4] = -(S.get<2,2>() * S.get<1,0>() * S.get<1,0>());
+
+ double* maxp = std::max_element (t, t+5, abs_less);
+ int em;
+ std::frexp(*maxp, &em);
+ double d = 0;
+ for (double i : t)
+ {
+ d += i;
+ }
+ //std::cout << "trace_sgn<3,3>: d = " << d << std::endl;
+ double r = std::fabs (std::ldexp (d, -em)); // relative error
+ //std::cout << "trace_sgn<3,3>: r = " << r << std::endl;
+
+ if (r < eps) return 0;
+ if (d > 0) return 1;
+ return -1;
+ }
+}; // end struct trace_sgn<3,3>
+
+} // end namespace detail
+
+
+template <size_t K, size_t N>
+inline
+double trace (const ConstBaseSymmetricMatrix<N> & _matrix)
+{
+ return detail::trace<K, N>::evaluate(_matrix);
+}
+
+template <size_t N>
+inline
+double trace (const ConstBaseSymmetricMatrix<N> & _matrix)
+{
+ return detail::trace<1, N>::evaluate(_matrix);
+}
+
+template <size_t N>
+inline
+double det (const ConstBaseSymmetricMatrix<N> & _matrix)
+{
+ return detail::trace<N, N>::evaluate(_matrix);
+}
+
+
+template <size_t K, size_t N>
+inline
+int trace_sgn (const ConstBaseSymmetricMatrix<N> & _matrix)
+{
+ return detail::trace_sgn<K, N>::evaluate(_matrix);
+}
+
+template <size_t N>
+inline
+int trace_sgn (const ConstBaseSymmetricMatrix<N> & _matrix)
+{
+ return detail::trace_sgn<1, N>::evaluate(_matrix);
+}
+
+template <size_t N>
+inline
+int det_sgn (const ConstBaseSymmetricMatrix<N> & _matrix)
+{
+ return detail::trace_sgn<N, N>::evaluate(_matrix);
+}
+
+/*
+template <size_t N>
+inline
+size_t rank (const ConstBaseSymmetricMatrix<N> & S)
+{
+ THROW_NOTIMPLEMENTED();
+ return 0;
+}
+
+template <>
+inline
+size_t rank<2> (const ConstBaseSymmetricMatrix<2> & S)
+{
+ if (S.is_zero()) return 0;
+ double d = S.get<0,0>() * S.get<1,1>() - S.get<0,1>() * S.get<1,0>();
+ if (d != 0) return 2;
+ return 1;
+}
+
+template <>
+inline
+size_t rank<3> (const ConstBaseSymmetricMatrix<3> & S)
+{
+ if (S.is_zero()) return 0;
+
+ double a20 = S.get<0,1>() * S.get<1,2>() - S.get<0,2>() * S.get<1,1>();
+ double a21 = S.get<0,2>() * S.get<1,0>() - S.get<0,0>() * S.get<1,2>();
+ double a22 = S.get<0,0>() * S.get<1,1>() - S.get<0,1>() * S.get<1,0>();
+ double d = a20 * S.get<2,0>() + a21 * S.get<2,1>() + a22 * S.get<2,2>();
+
+ if (d != 0) return 3;
+
+ if (a20 != 0 || a21 != 0 || a22 != 0) return 2;
+
+ double a00 = S.get<1,1>() * S.get<2,2>() - S.get<1,2>() * S.get<2,1>();
+ if (a00 != 0) return 2;
+
+ double a10 = S.get<0,2>() * S.get<2,1>() - S.get<0,1>() * S.get<2,2>();
+ if (a10 != 0) return 2;
+
+ double a11 = S.get<0,0>() * S.get<2,2>() - S.get<0,2>() * S.get<2,0>();
+ if (a11 != 0) return 2;
+
+ return 1;
+}
+*/
+
+} /* end namespace NL*/ } /* end namespace Geom*/
+
+
+
+
+#endif // _NL_TRACE_H_
+
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/numeric/symmetric-matrix-fs.h b/src/3rdparty/2geom/include/2geom/numeric/symmetric-matrix-fs.h
new file mode 100644
index 0000000..2fadd69
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/numeric/symmetric-matrix-fs.h
@@ -0,0 +1,733 @@
+/*
+ * SymmetricMatrix, ConstSymmetricMatrixView, SymmetricMatrixView template
+ * classes implement fixed size symmetric matrix; "views" mimic the semantic
+ * of C++ references: any operation performed on a "view" is actually performed
+ * on the "viewed object"
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2009 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#ifndef _NL_SYMMETRIC_MATRIX_FS_H_
+#define _NL_SYMMETRIC_MATRIX_FS_H_
+
+
+#include <2geom/numeric/vector.h>
+#include <2geom/numeric/matrix.h>
+#include <2geom/utils.h>
+#include <2geom/exception.h>
+
+#include <boost/static_assert.hpp>
+
+#include <cassert>
+#include <utility> // for std::pair
+#include <algorithm> // for std::swap, std::copy
+#include <sstream>
+#include <string>
+
+
+
+namespace Geom { namespace NL {
+
+
+namespace detail
+{
+
+template <size_t I, size_t J, bool B = (I < J)>
+struct index
+{
+ static const size_t K = index<J, I>::K;
+};
+
+template <size_t I, size_t J>
+struct index<I, J, false>
+{
+ static const size_t K = (((I+1) * I) >> 1) + J;
+};
+
+} // end namespace detail
+
+
+
+
+template <size_t N>
+class ConstBaseSymmetricMatrix;
+
+template <size_t N>
+class BaseSymmetricMatrix;
+
+template <size_t N>
+class SymmetricMatrix;
+
+template <size_t N>
+class ConstSymmetricMatrixView;
+
+template <size_t N>
+class SymmetricMatrixView;
+
+
+
+// declaration needed for friend clause
+template <size_t N>
+bool operator== (ConstBaseSymmetricMatrix<N> const& _smatrix1,
+ ConstBaseSymmetricMatrix<N> const& _smatrix2);
+
+
+
+
+template <size_t N>
+class ConstBaseSymmetricMatrix
+{
+ public:
+ const static size_t DIM = N;
+ const static size_t DATA_SIZE = ((DIM+1) * DIM) / 2;
+
+ public:
+
+ ConstBaseSymmetricMatrix (VectorView const& _data)
+ : m_data(_data)
+ {
+ }
+
+ double operator() (size_t i, size_t j) const
+ {
+ return m_data[get_index(i,j)];
+ }
+
+ template <size_t I, size_t J>
+ double get() const
+ {
+ BOOST_STATIC_ASSERT ((I < N && J < N));
+ return m_data[detail::index<I, J>::K];
+ }
+
+
+ size_t rows() const
+ {
+ return DIM;
+ }
+
+ size_t columns() const
+ {
+ return DIM;
+ }
+
+ bool is_zero() const
+ {
+ return m_data.is_zero();
+ }
+
+ bool is_positive() const
+ {
+ return m_data.is_positive();
+ }
+
+ bool is_negative() const
+ {
+ return m_data.is_negative();
+ }
+
+ bool is_non_negative() const
+ {
+ return m_data.is_non_negative();
+ }
+
+ double min() const
+ {
+ return m_data.min();
+ }
+
+ double max() const
+ {
+ return m_data.max();
+ }
+
+ std::pair<size_t, size_t>
+ min_index() const
+ {
+ std::pair<size_t, size_t> indices(0,0);
+ double min_value = m_data[0];
+ for (size_t i = 1; i < DIM; ++i)
+ {
+ for (size_t j = 0; j <= i; ++j)
+ {
+ if (min_value > (*this)(i,j))
+ {
+ min_value = (*this)(i,j);
+ indices.first = i;
+ indices.second = j;
+ }
+ }
+ }
+ return indices;
+ }
+
+ std::pair<size_t, size_t>
+ max_index() const
+ {
+ std::pair<size_t, size_t> indices(0,0);
+ double max_value = m_data[0];
+ for (size_t i = 1; i < DIM; ++i)
+ {
+ for (size_t j = 0; j <= i; ++j)
+ {
+ if (max_value < (*this)(i,j))
+ {
+ max_value = (*this)(i,j);
+ indices.first = i;
+ indices.second = j;
+ }
+ }
+ }
+ return indices;
+ }
+
+ size_t min_on_row_index (size_t i) const
+ {
+ size_t idx = 0;
+ double min_value = (*this)(i,0);
+ for (size_t j = 1; j < DIM; ++j)
+ {
+ if (min_value > (*this)(i,j))
+ {
+ min_value = (*this)(i,j);
+ idx = j;
+ }
+ }
+ return idx;
+ }
+
+ size_t max_on_row_index (size_t i) const
+ {
+ size_t idx = 0;
+ double max_value = (*this)(i,0);
+ for (size_t j = 1; j < DIM; ++j)
+ {
+ if (max_value < (*this)(i,j))
+ {
+ max_value = (*this)(i,j);
+ idx = j;
+ }
+ }
+ return idx;
+ }
+
+ size_t min_on_column_index (size_t j) const
+ {
+ return min_on_row_index(j);
+ }
+
+ size_t max_on_column_index (size_t j) const
+ {
+ return max_on_row_index(j);
+ }
+
+ size_t min_on_diag_index () const
+ {
+ size_t idx = 0;
+ double min_value = (*this)(0,0);
+ for (size_t i = 1; i < DIM; ++i)
+ {
+ if (min_value > (*this)(i,i))
+ {
+ min_value = (*this)(i,i);
+ idx = i;
+ }
+ }
+ return idx;
+ }
+
+ size_t max_on_diag_index () const
+ {
+ size_t idx = 0;
+ double max_value = (*this)(0,0);
+ for (size_t i = 1; i < DIM; ++i)
+ {
+ if (max_value < (*this)(i,i))
+ {
+ max_value = (*this)(i,i);
+ idx = i;
+ }
+ }
+ return idx;
+ }
+
+ std::string str() const;
+
+ ConstSymmetricMatrixView<N-1> main_minor_const_view() const;
+
+ SymmetricMatrix<N> operator- () const;
+
+ Vector operator* (ConstVectorView _vector) const
+ {
+ assert (_vector.size() == DIM);
+ Vector result(DIM, 0.0);
+
+ for (size_t i = 0; i < DIM; ++i)
+ {
+ for (size_t j = 0; j < DIM; ++j)
+ {
+ result[i] += (*this)(i,j) * _vector[j];
+ }
+ }
+ return result;
+ }
+
+ protected:
+ static size_t get_index (size_t i, size_t j)
+ {
+ if (i < j) return get_index (j, i);
+ size_t k = (i+1) * i;
+ k >>= 1;
+ k += j;
+ return k;
+ }
+
+ protected:
+ ConstVectorView get_data() const
+ {
+ return m_data;
+ }
+
+ friend
+ bool operator==<N> (ConstBaseSymmetricMatrix const& _smatrix1,
+ ConstBaseSymmetricMatrix const& _smatrix2);
+
+ protected:
+ VectorView m_data;
+
+}; //end ConstBaseSymmetricMatrix
+
+
+template <size_t N>
+class BaseSymmetricMatrix : public ConstBaseSymmetricMatrix<N>
+{
+ public:
+ typedef ConstBaseSymmetricMatrix<N> base_type;
+
+
+ public:
+
+ BaseSymmetricMatrix (VectorView const& _data)
+ : base_type(_data)
+ {
+ }
+
+ double operator() (size_t i, size_t j) const
+ {
+ return m_data[base_type::get_index(i,j)];
+ }
+
+ double& operator() (size_t i, size_t j)
+ {
+ return m_data[base_type::get_index(i,j)];
+ }
+
+ template <size_t I, size_t J>
+ double& get()
+ {
+ BOOST_STATIC_ASSERT ((I < N && J < N));
+ return m_data[detail::index<I, J>::K];
+ }
+
+ void set_all (double x)
+ {
+ m_data.set_all(x);
+ }
+
+ SymmetricMatrixView<N-1> main_minor_view();
+
+ BaseSymmetricMatrix& transpose() const
+ {
+ return (*this);
+ }
+
+ BaseSymmetricMatrix& translate (double c)
+ {
+ m_data.translate(c);
+ return (*this);
+ }
+
+ BaseSymmetricMatrix& scale (double c)
+ {
+ m_data.scale(c);
+ return (*this);
+ }
+
+ BaseSymmetricMatrix& operator+= (base_type const& _smatrix)
+ {
+ m_data += (static_cast<const BaseSymmetricMatrix &>(_smatrix).m_data);
+ return (*this);
+ }
+
+ BaseSymmetricMatrix& operator-= (base_type const& _smatrix)
+ {
+ m_data -= (static_cast<const BaseSymmetricMatrix &>(_smatrix).m_data);
+ return (*this);
+ }
+
+ using base_type::DIM;
+ using base_type::DATA_SIZE;
+ using base_type::m_data;
+ using base_type::operator-;
+ using base_type::operator*;
+
+}; //end BaseSymmetricMatrix
+
+
+template <size_t N>
+class SymmetricMatrix : public BaseSymmetricMatrix<N>
+{
+ public:
+ typedef BaseSymmetricMatrix<N> base_type;
+ typedef typename base_type::base_type base_base_type;
+
+ using base_type::DIM;
+ using base_type::DATA_SIZE;
+ using base_type::m_data;
+
+ public:
+ SymmetricMatrix ()
+ : base_type (VectorView(m_adata, DATA_SIZE))
+ {
+ }
+
+ explicit
+ SymmetricMatrix (ConstVectorView _data)
+ : base_type (VectorView(m_adata, DATA_SIZE))
+ {
+ assert (_data.size() == DATA_SIZE);
+ m_data = _data;
+ }
+
+ explicit
+ SymmetricMatrix (const double _data[DATA_SIZE])
+ : base_type (VectorView(m_adata, DATA_SIZE))
+ {
+ std::copy (_data, _data + DATA_SIZE, m_adata);
+ }
+
+ SymmetricMatrix (SymmetricMatrix const& _smatrix)
+ : base_type (VectorView(m_adata, DATA_SIZE))
+ {
+ m_data = _smatrix.m_data;
+ }
+
+ explicit
+ SymmetricMatrix (base_base_type const& _smatrix)
+ : base_type (VectorView(m_adata, DATA_SIZE))
+ {
+ m_data = static_cast<const ConstSymmetricMatrixView<DIM> &>(_smatrix).m_data;
+ }
+
+ explicit
+ SymmetricMatrix (ConstMatrixView const& _matrix)
+ : base_type (VectorView(m_adata, DATA_SIZE))
+ {
+ assert (_matrix.rows() == N && _matrix.columns() == N);
+ for (size_t i = 0; i < N; ++i)
+ for (size_t j = 0; j <= i ; ++j)
+ (*this)(i,j) = _matrix(i,j);
+ }
+
+ SymmetricMatrix& operator= (SymmetricMatrix const& _smatrix)
+ {
+ m_data = _smatrix.m_data;
+ return (*this);
+ }
+
+ SymmetricMatrix& operator= (base_base_type const& _smatrix)
+ {
+
+ m_data = static_cast<const ConstSymmetricMatrixView<DIM> &>(_smatrix).m_data;
+ return (*this);
+ }
+
+ SymmetricMatrix& operator= (ConstMatrixView const& _matrix)
+ {
+ assert (_matrix.rows() == N && _matrix.columns() == N);
+ for (size_t i = 0; i < N; ++i)
+ for (size_t j = 0; j <= i ; ++j)
+ (*this)(i,j) = _matrix(i,j);
+
+ return (*this);
+ }
+
+ // needed for accessing m_adata
+ friend class ConstSymmetricMatrixView<DIM>;
+ friend class SymmetricMatrixView<DIM>;
+ private:
+ double m_adata[DATA_SIZE];
+}; //end SymmetricMatrix
+
+
+template <size_t N>
+class ConstSymmetricMatrixView : public ConstBaseSymmetricMatrix<N>
+{
+ public:
+ typedef ConstBaseSymmetricMatrix<N> base_type;
+
+ using base_type::DIM;
+ using base_type::DATA_SIZE;
+ using base_type::m_data;
+
+
+ public:
+
+ explicit
+ ConstSymmetricMatrixView (ConstVectorView _data)
+ : base_type (const_vector_view_cast(_data))
+ {
+ assert (_data.size() == DATA_SIZE);
+ }
+
+ explicit
+ ConstSymmetricMatrixView (const double _data[DATA_SIZE])
+ : base_type (const_vector_view_cast (ConstVectorView (_data, DATA_SIZE)))
+ {
+ }
+
+ ConstSymmetricMatrixView (const ConstSymmetricMatrixView & _smatrix)
+ : base_type (_smatrix.m_data)
+ {
+ }
+
+ ConstSymmetricMatrixView (const base_type & _smatrix)
+ : base_type (static_cast<const ConstSymmetricMatrixView &>(_smatrix).m_data)
+ {
+ }
+
+}; //end SymmetricMatrix
+
+
+// declaration needed for friend clause
+template <size_t N>
+void swap_view(SymmetricMatrixView<N> & m1, SymmetricMatrixView<N> & m2);
+
+
+template <size_t N>
+class SymmetricMatrixView : public BaseSymmetricMatrix<N>
+{
+ public:
+ typedef BaseSymmetricMatrix<N> base_type;
+ typedef typename base_type::base_type base_base_type;
+
+ using base_type::DIM;
+ using base_type::DATA_SIZE;
+ using base_type::m_data;
+
+ public:
+
+ explicit
+ SymmetricMatrixView (VectorView _data)
+ : base_type (_data)
+ {
+ assert (_data.size() == DATA_SIZE);
+ }
+
+ explicit
+ SymmetricMatrixView (double _data[DATA_SIZE])
+ : base_type (VectorView (_data, DATA_SIZE))
+ {
+ }
+
+ SymmetricMatrixView (const SymmetricMatrixView & _smatrix)
+ : base_type (_smatrix.m_data)
+ {
+ }
+
+ SymmetricMatrixView (SymmetricMatrix<DIM> & _smatrix)
+ : base_type (VectorView (_smatrix.m_adata, DATA_SIZE))
+ {
+ }
+
+ SymmetricMatrixView& operator= (const SymmetricMatrixView & _smatrix)
+ {
+ m_data = _smatrix.m_data;
+ return (*this);
+ }
+
+ SymmetricMatrixView& operator= (const base_base_type & _smatrix)
+ {
+ m_data = static_cast<const ConstSymmetricMatrixView<DIM> &>(_smatrix).m_data;
+ return (*this);
+ }
+
+ friend
+ void swap_view<N>(SymmetricMatrixView & m1, SymmetricMatrixView & m2);
+
+}; //end SymmetricMatrix
+
+
+
+
+/*
+ * class ConstBaseSymmetricMatrix methods
+ */
+
+template <size_t N>
+inline
+std::string ConstBaseSymmetricMatrix<N>::str() const
+{
+ std::ostringstream oss;
+ oss << (*this);
+ return oss.str();
+}
+
+template <size_t N>
+inline
+ConstSymmetricMatrixView<N-1>
+ConstBaseSymmetricMatrix<N>::main_minor_const_view() const
+{
+ ConstVectorView data(m_data.get_gsl_vector()->data, DATA_SIZE - DIM);
+ ConstSymmetricMatrixView<N-1> mm(data);
+ return mm;
+}
+
+template <size_t N>
+inline
+SymmetricMatrix<N> ConstBaseSymmetricMatrix<N>::operator- () const
+{
+ SymmetricMatrix<N> result;
+ for (size_t i = 0; i < DATA_SIZE; ++i)
+ {
+ result.m_data[i] = -m_data[i];
+ }
+ return result;
+}
+
+
+/*
+ * class ConstBaseSymmetricMatrix friend free functions
+ */
+
+template <size_t N>
+inline
+bool operator== (ConstBaseSymmetricMatrix<N> const& _smatrix1,
+ ConstBaseSymmetricMatrix<N> const& _smatrix2)
+{
+ return (_smatrix1.m_data == _smatrix2.m_data);
+}
+
+/*
+ * class ConstBaseSymmetricMatrix related free functions
+ */
+
+template< size_t N, class charT >
+inline
+std::basic_ostream<charT> &
+operator<< (std::basic_ostream<charT> & os,
+ const ConstBaseSymmetricMatrix<N> & _matrix)
+{
+ os << "[[" << _matrix(0,0);
+ for (size_t j = 1; j < N; ++j)
+ {
+ os << ", " << _matrix(0,j);
+ }
+ os << "]";
+ for (size_t i = 1; i < N; ++i)
+ {
+ os << "\n [" << _matrix(i,0);
+ for (size_t j = 1; j < N; ++j)
+ {
+ os << ", " << _matrix(i,j);
+ }
+ os << "]";
+ }
+ os << "]";
+ return os;
+}
+
+
+/*
+ * class ConstBaseSymmetricMatrix specialized methods
+ */
+
+template<>
+inline
+size_t ConstBaseSymmetricMatrix<2>::get_index (size_t i, size_t j)
+{
+ return (i+j);
+}
+
+template<>
+inline
+size_t ConstBaseSymmetricMatrix<3>::get_index (size_t i, size_t j)
+{
+ size_t k = i + j;
+ if (i == 2 || j == 2) ++k;
+ return k;
+}
+
+
+/*
+ * class BaseSymmetricMatrix methods
+ */
+
+template <size_t N>
+inline
+SymmetricMatrixView<N-1> BaseSymmetricMatrix<N>::main_minor_view()
+{
+ VectorView data(m_data.get_gsl_vector()->data, DATA_SIZE - DIM);
+ SymmetricMatrixView<N-1> mm(data);
+ return mm;
+}
+
+
+/*
+ * class SymmetricMatrixView friend free functions
+ */
+
+template <size_t N>
+inline
+void swap_view(SymmetricMatrixView<N> & m1, SymmetricMatrixView<N> & m2)
+{
+ swap_view(m1.m_data, m2.m_data);
+}
+
+} /* end namespace NL*/ } /* end namespace Geom*/
+
+
+
+
+#endif // _NL_SYMMETRIC_MATRIX_FS_H_
+
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/numeric/vector.h b/src/3rdparty/2geom/include/2geom/numeric/vector.h
new file mode 100644
index 0000000..b66115b
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/numeric/vector.h
@@ -0,0 +1,594 @@
+/*
+ * Vector, VectorView, ConstVectorView classes wrap the gsl vector routines;
+ * "views" mimic the semantic of C++ references: any operation performed
+ * on a "view" is actually performed on the "viewed object"
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+
+
+#ifndef _NL_VECTOR_H_
+#define _NL_VECTOR_H_
+
+#include <cassert>
+#include <algorithm> // for std::swap
+#include <vector>
+#include <sstream>
+#include <string>
+
+
+#include <gsl/gsl_vector.h>
+#include <gsl/gsl_blas.h>
+
+
+namespace Geom { namespace NL {
+
+namespace detail
+{
+
+class BaseVectorImpl
+{
+ public:
+ double const& operator[](size_t i) const
+ {
+ return *gsl_vector_const_ptr(m_vector, i);
+ }
+
+ const gsl_vector* get_gsl_vector() const
+ {
+ return m_vector;
+ }
+ bool is_zero() const
+ {
+ return gsl_vector_isnull(m_vector);
+ }
+
+ bool is_positive() const
+ {
+ for ( size_t i = 0; i < size(); ++i )
+ {
+ if ( (*this)[i] <= 0 ) return false;
+ }
+ return true;
+ }
+
+ bool is_negative() const
+ {
+ for ( size_t i = 0; i < size(); ++i )
+ {
+ if ( (*this)[i] >= 0 ) return false;
+ }
+ return true;
+ }
+
+ bool is_non_negative() const
+ {
+ for ( size_t i = 0; i < size(); ++i )
+ {
+ if ( (*this)[i] < 0 ) return false;
+ }
+ return true;
+ }
+
+ double max() const
+ {
+ return gsl_vector_max(m_vector);
+ }
+
+ double min() const
+ {
+ return gsl_vector_min(m_vector);
+ }
+
+ size_t max_index() const
+ {
+ return gsl_vector_max_index(m_vector);
+ }
+
+ size_t min_index() const
+ {
+ return gsl_vector_min_index(m_vector);
+ }
+
+ size_t size() const
+ {
+ return m_size;
+ }
+
+ std::string str() const;
+
+ virtual ~BaseVectorImpl()
+ {
+ }
+
+ protected:
+ size_t m_size;
+ gsl_vector* m_vector;
+
+}; // end class BaseVectorImpl
+
+
+inline
+bool operator== (BaseVectorImpl const& v1, BaseVectorImpl const& v2)
+{
+ if (v1.size() != v2.size()) return false;
+
+ for (size_t i = 0; i < v1.size(); ++i)
+ {
+ if (v1[i] != v2[i]) return false;
+ }
+ return true;
+}
+
+template< class charT >
+inline
+std::basic_ostream<charT> &
+operator<< (std::basic_ostream<charT> & os, const BaseVectorImpl & _vector)
+{
+ if (_vector.size() == 0 ) return os;
+ os << "[" << _vector[0];
+ for (unsigned int i = 1; i < _vector.size(); ++i)
+ {
+ os << ", " << _vector[i];
+ }
+ os << "]";
+ return os;
+}
+
+inline
+std::string BaseVectorImpl::str() const
+{
+ std::ostringstream oss;
+ oss << (*this);
+ return oss.str();
+}
+
+inline
+double dot(BaseVectorImpl const& v1, BaseVectorImpl const& v2)
+{
+ double result;
+ gsl_blas_ddot(v1.get_gsl_vector(), v2.get_gsl_vector(), &result);
+ return result;
+}
+
+
+class VectorImpl : public BaseVectorImpl
+{
+ public:
+ typedef BaseVectorImpl base_type;
+
+ public:
+ void set_all(double x)
+ {
+ gsl_vector_set_all(m_vector, x);
+ }
+
+ void set_basis(size_t i)
+ {
+ gsl_vector_set_basis(m_vector, i);
+ }
+
+ using base_type::operator[];
+
+ double & operator[](size_t i)
+ {
+ return *gsl_vector_ptr(m_vector, i);
+ }
+
+ using base_type::get_gsl_vector;
+
+ gsl_vector* get_gsl_vector()
+ {
+ return m_vector;
+ }
+
+ void swap_elements(size_t i, size_t j)
+ {
+ gsl_vector_swap_elements(m_vector, i, j);
+ }
+
+ void reverse()
+ {
+ gsl_vector_reverse(m_vector);
+ }
+
+ VectorImpl & scale(double x)
+ {
+ gsl_vector_scale(m_vector, x);
+ return (*this);
+ }
+
+ VectorImpl & translate(double x)
+ {
+ gsl_vector_add_constant(m_vector, x);
+ return (*this);
+ }
+
+ VectorImpl & operator+=(base_type const& _vector)
+ {
+ gsl_vector_add(m_vector, _vector.get_gsl_vector());
+ return (*this);
+ }
+
+ VectorImpl & operator-=(base_type const& _vector)
+ {
+ gsl_vector_sub(m_vector, _vector.get_gsl_vector());
+ return (*this);
+ }
+
+}; // end class VectorImpl
+
+} // end namespace detail
+
+
+using detail::operator==;
+using detail::operator<<;
+
+class Vector : public detail::VectorImpl
+{
+ public:
+ typedef detail::VectorImpl base_type;
+
+ public:
+ Vector(size_t n)
+ {
+ m_size = n;
+ m_vector = gsl_vector_alloc(n);
+ }
+
+ Vector(size_t n, double x)
+ {
+ m_size = n;
+ m_vector = gsl_vector_alloc(n);
+ gsl_vector_set_all(m_vector, x);
+ }
+
+ // create a vector with n elements all set to zero
+ // but the i-th that is set to 1
+ Vector(size_t n, size_t i)
+ {
+ m_size = n;
+ m_vector = gsl_vector_alloc(n);
+ gsl_vector_set_basis(m_vector, i);
+ }
+
+ Vector(Vector const& _vector)
+ : base_type()
+ {
+ m_size = _vector.size();
+ m_vector = gsl_vector_alloc(size());
+ gsl_vector_memcpy(m_vector, _vector.m_vector);
+ }
+
+ explicit
+ Vector(base_type::base_type const& _vector)
+ {
+ m_size = _vector.size();
+ m_vector = gsl_vector_alloc(size());
+ gsl_vector_memcpy(m_vector, _vector.get_gsl_vector());
+ }
+
+ ~Vector() override
+ {
+ gsl_vector_free(m_vector);
+ }
+
+
+ Vector & operator=(Vector const& _vector)
+ {
+ assert( size() == _vector.size() );
+ gsl_vector_memcpy(m_vector, _vector.m_vector);
+ return (*this);
+ }
+
+ Vector & operator=(base_type::base_type const& _vector)
+ {
+ assert( size() == _vector.size() );
+ gsl_vector_memcpy(m_vector, _vector.get_gsl_vector());
+ return (*this);
+ }
+
+ Vector & scale(double x)
+ {
+ return static_cast<Vector&>( base_type::scale(x) );
+ }
+
+ Vector & translate(double x)
+ {
+ return static_cast<Vector&>( base_type::translate(x) );
+ }
+
+ Vector & operator+=(base_type::base_type const& _vector)
+ {
+ return static_cast<Vector&>( base_type::operator+=(_vector) );
+ }
+
+ Vector & operator-=(base_type::base_type const& _vector)
+ {
+ return static_cast<Vector&>( base_type::operator-=(_vector) );
+ }
+
+ friend
+ void swap(Vector & v1, Vector & v2);
+ friend
+ void swap_any(Vector & v1, Vector & v2);
+
+}; // end class Vector
+
+
+// warning! these operations invalidate any view of the passed vector objects
+inline
+void swap(Vector & v1, Vector & v2)
+{
+ assert(v1.size() == v2.size());
+ using std::swap;
+ swap(v1.m_vector, v2.m_vector);
+}
+
+inline
+void swap_any(Vector & v1, Vector & v2)
+{
+ using std::swap;
+ swap(v1.m_vector, v2.m_vector);
+ swap(v1.m_size, v2.m_size);
+}
+
+
+class ConstVectorView : public detail::BaseVectorImpl
+{
+ public:
+ typedef detail::BaseVectorImpl base_type;
+
+ public:
+ ConstVectorView(const base_type & _vector, size_t n, size_t offset = 0)
+ : m_vector_view( gsl_vector_const_subvector(_vector.get_gsl_vector(), offset, n) )
+ {
+ m_size = n;
+ m_vector = const_cast<gsl_vector*>( &(m_vector_view.vector) );
+ }
+
+ ConstVectorView(const base_type & _vector, size_t n, size_t offset , size_t stride)
+ : m_vector_view( gsl_vector_const_subvector_with_stride(_vector.get_gsl_vector(), offset, stride, n) )
+ {
+ m_size = n;
+ m_vector = const_cast<gsl_vector*>( &(m_vector_view.vector) );
+ }
+
+ ConstVectorView(const double* _vector, size_t n, size_t offset = 0)
+ : m_vector_view( gsl_vector_const_view_array(_vector + offset, n) )
+ {
+ m_size = n;
+ m_vector = const_cast<gsl_vector*>( &(m_vector_view.vector) );
+ }
+
+ ConstVectorView(const double* _vector, size_t n, size_t offset, size_t stride)
+ : m_vector_view( gsl_vector_const_view_array_with_stride(_vector + offset, stride, n) )
+ {
+ m_size = n;
+ m_vector = const_cast<gsl_vector*>( &(m_vector_view.vector) );
+ }
+
+ explicit
+ ConstVectorView(gsl_vector_const_view _gsl_vector_view)
+ : m_vector_view(_gsl_vector_view)
+ {
+ m_vector = const_cast<gsl_vector*>( &(m_vector_view.vector) );
+ m_size = m_vector->size;
+ }
+
+ explicit
+ ConstVectorView(const std::vector<double>& _vector)
+ : m_vector_view( gsl_vector_const_view_array(&(_vector[0]), _vector.size()) )
+ {
+ m_vector = const_cast<gsl_vector*>( &(m_vector_view.vector) );
+ m_size = _vector.size();
+ }
+
+ ConstVectorView(const ConstVectorView & _vector)
+ : base_type(),
+ m_vector_view(_vector.m_vector_view)
+ {
+ m_size = _vector.size();
+ m_vector = const_cast<gsl_vector*>( &(m_vector_view.vector) );
+ }
+
+ ConstVectorView(const base_type & _vector)
+ : m_vector_view(gsl_vector_const_subvector(_vector.get_gsl_vector(), 0, _vector.size()))
+ {
+ m_size = _vector.size();
+ m_vector = const_cast<gsl_vector*>( &(m_vector_view.vector) );
+ }
+
+ private:
+ gsl_vector_const_view m_vector_view;
+
+}; // end class ConstVectorView
+
+
+
+
+class VectorView : public detail::VectorImpl
+{
+ public:
+ typedef detail::VectorImpl base_type;
+
+ public:
+ VectorView(base_type & _vector, size_t n, size_t offset = 0, size_t stride = 1)
+ {
+ m_size = n;
+ if (stride == 1)
+ {
+ m_vector_view
+ = gsl_vector_subvector(_vector.get_gsl_vector(), offset, n);
+ m_vector = &(m_vector_view.vector);
+ }
+ else
+ {
+ m_vector_view
+ = gsl_vector_subvector_with_stride(_vector.get_gsl_vector(), offset, stride, n);
+ m_vector = &(m_vector_view.vector);
+ }
+ }
+
+ VectorView(double* _vector, size_t n, size_t offset = 0, size_t stride = 1)
+ {
+ m_size = n;
+ if (stride == 1)
+ {
+ m_vector_view
+ = gsl_vector_view_array(_vector + offset, n);
+ m_vector = &(m_vector_view.vector);
+ }
+ else
+ {
+ m_vector_view
+ = gsl_vector_view_array_with_stride(_vector + offset, stride, n);
+ m_vector = &(m_vector_view.vector);
+ }
+
+ }
+
+ VectorView(const VectorView & _vector)
+ : base_type()
+ {
+ m_size = _vector.size();
+ m_vector_view = _vector.m_vector_view;
+ m_vector = &(m_vector_view.vector);
+ }
+
+ VectorView(Vector & _vector)
+ {
+ m_size = _vector.size();
+ m_vector_view = gsl_vector_subvector(_vector.get_gsl_vector(), 0, size());
+ m_vector = &(m_vector_view.vector);
+ }
+
+ explicit
+ VectorView(gsl_vector_view _gsl_vector_view)
+ : m_vector_view(_gsl_vector_view)
+ {
+ m_vector = &(m_vector_view.vector);
+ m_size = m_vector->size;
+ }
+
+ explicit
+ VectorView(std::vector<double> & _vector)
+ {
+ m_size = _vector.size();
+ m_vector_view = gsl_vector_view_array(&(_vector[0]), _vector.size());
+ m_vector = &(m_vector_view.vector);
+ }
+
+ VectorView & operator=(VectorView const& _vector)
+ {
+ assert( size() == _vector.size() );
+ gsl_vector_memcpy(m_vector, _vector.get_gsl_vector());
+ return (*this);
+ }
+
+ VectorView & operator=(base_type::base_type const& _vector)
+ {
+ assert( size() == _vector.size() );
+ gsl_vector_memcpy(m_vector, _vector.get_gsl_vector());
+ return (*this);
+ }
+
+ VectorView & scale(double x)
+ {
+ return static_cast<VectorView&>( base_type::scale(x) );
+ }
+
+ VectorView & translate(double x)
+ {
+ return static_cast<VectorView&>( base_type::translate(x) );
+ }
+
+ VectorView & operator+=(base_type::base_type const& _vector)
+ {
+ return static_cast<VectorView&>( base_type::operator+=(_vector) );
+ }
+
+ VectorView & operator-=(base_type::base_type const& _vector)
+ {
+ return static_cast<VectorView&>( base_type::operator-=(_vector) );
+ }
+
+ friend
+ void swap_view(VectorView & v1, VectorView & v2);
+
+ private:
+ gsl_vector_view m_vector_view;
+
+}; // end class VectorView
+
+
+inline
+void swap_view(VectorView & v1, VectorView & v2)
+{
+ assert( v1.size() == v2.size() );
+ using std::swap;
+ swap(v1.m_vector_view, v2.m_vector_view); // not swap m_vector too
+}
+
+inline
+const VectorView & const_vector_view_cast (const ConstVectorView & view)
+{
+ const detail::BaseVectorImpl & bvi
+ = static_cast<const detail::BaseVectorImpl &>(view);
+ const VectorView & vv = reinterpret_cast<const VectorView &>(bvi);
+ return vv;
+}
+
+inline
+VectorView & const_vector_view_cast (ConstVectorView & view)
+{
+ detail::BaseVectorImpl & bvi
+ = static_cast<detail::BaseVectorImpl &>(view);
+ VectorView & vv = reinterpret_cast<VectorView &>(bvi);
+ return vv;
+}
+
+
+} } // end namespaces
+
+
+#endif /*_NL_VECTOR_H_*/
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/ord.h b/src/3rdparty/2geom/include/2geom/ord.h
new file mode 100644
index 0000000..e190a4a
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/ord.h
@@ -0,0 +1,80 @@
+/** @file
+ * @brief Comparator template
+ *//*
+ * Authors:
+ * ? <?@?.?>
+ *
+ * Copyright ?-? authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_ORD_H
+#define LIB2GEOM_SEEN_ORD_H
+
+namespace {
+
+enum Cmp {
+ LESS_THAN=-1,
+ GREATER_THAN=1,
+ EQUAL_TO=0
+};
+
+static inline Cmp operator-(Cmp x) {
+ switch(x) {
+ case LESS_THAN:
+ return GREATER_THAN;
+ case GREATER_THAN:
+ return LESS_THAN;
+ case EQUAL_TO:
+ return EQUAL_TO;
+ }
+}
+
+template <typename T1, typename T2>
+inline Cmp cmp(T1 const &a, T2 const &b) {
+ if ( a < b ) {
+ return LESS_THAN;
+ } else if ( b < a ) {
+ return GREATER_THAN;
+ } else {
+ return EQUAL_TO;
+ }
+}
+
+}
+
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/orphan-code/arc-length.h b/src/3rdparty/2geom/include/2geom/orphan-code/arc-length.h
new file mode 100644
index 0000000..8029f04
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/orphan-code/arc-length.h
@@ -0,0 +1,58 @@
+/**
+ * \file arc-length.h
+ * \brief Arc length computations for paths
+ *//*
+ * Copyright 2006 Nathan Hurst <njh@mail.csse.monash.edu.au>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef __2GEOM_ARC_LENGTH_H
+#define __2GEOM_ARC_LENGTH_H
+
+#include <2geom/path.h>
+
+/* Routines in this group return a path that looks the same, but
+ * include extra knots for certain points of interest. */
+
+/* find_vector_extreme_points
+ * extreme points . dir.
+ */
+
+double arc_length_subdividing(Geom::Path const & p, double tol);
+double arc_length_integrating(Geom::Path const & p, double tol);
+
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/orphan-code/chebyshev.h b/src/3rdparty/2geom/include/2geom/orphan-code/chebyshev.h
new file mode 100644
index 0000000..f729e1f
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/orphan-code/chebyshev.h
@@ -0,0 +1,30 @@
+#ifndef _CHEBYSHEV
+#define _CHEBYSHEV
+
+#include <2geom/sbasis.h>
+#include <2geom/interval.h>
+
+/*** Conversion between Chebyshev approximation and SBasis.
+ *
+ */
+
+namespace Geom{
+
+SBasis chebyshev_approximant (double (*f)(double,void*), int order, Interval in, void* p=0);
+SBasis chebyshev_approximant_interpolating (double (*f)(double,void*), int order, Interval in, void* p=0);
+SBasis chebyshev(unsigned n);
+
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+
+#endif
diff --git a/src/3rdparty/2geom/include/2geom/orphan-code/intersection-by-smashing.h b/src/3rdparty/2geom/include/2geom/orphan-code/intersection-by-smashing.h
new file mode 100644
index 0000000..996ec99
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/orphan-code/intersection-by-smashing.h
@@ -0,0 +1,78 @@
+/*
+ * Diffeomorphism-based intersector: given two curves
+ * M(t)=(x(t),y(t)) and N(u)=(X(u),Y(u))
+ * and supposing M is a graph over the x-axis, we compute y(x) and the
+ * transformation:
+ * X <- X
+ * Y <- Y - y(X)
+ * smashes M on the x axis. The intersections are then given by the roots of:
+ * Y(u) - y(X(u)) = 0
+ *//*
+ * Authors:
+ * J.-F. Barraud <jfbarraud at gmail.com>
+ * Copyright 2010 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef SEEN_LIB2GEOM_INTERSECTION_BY_SMASHING_H
+#define SEEN_LIB2GEOM_INTERSECTION_BY_SMASHING_H
+
+#include <2geom/d2.h>
+#include <2geom/interval.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-geometric.h>
+#include <cstdlib>
+#include <vector>
+#include <algorithm>
+
+
+namespace Geom{
+
+struct SmashIntersection {
+ Rect times;
+ Rect bbox;
+};
+
+std::vector<SmashIntersection> smash_intersect( D2<SBasis> const &a, D2<SBasis> const &b, double tol);
+std::vector<SmashIntersection> monotonic_smash_intersect( D2<SBasis> const &a, D2<SBasis> const &b, double tol);
+//std::vector<Intersection> monotonic_smash_intersect( Curve const &a, double a_from, double a_to,
+// Curve const &b, double b_from, double b_to, double tol);
+
+std::vector<Interval> monotonicSplit(D2<SBasis> const &p);
+
+} // end namespace Geom
+
+#endif // !SEEN_LIB2GEOM_INTERSECTION_BY_SMASHING_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/orphan-code/linear-of.h b/src/3rdparty/2geom/include/2geom/orphan-code/linear-of.h
new file mode 100644
index 0000000..9ba1fb2
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/orphan-code/linear-of.h
@@ -0,0 +1,269 @@
+/**
+ * \file
+ * \brief Linear fragment function class
+ *
+ * Authors:
+ * Nathan Hurst <njh@mail.csse.monash.edu.au>
+ * Michael Sloan <mgsloan@gmail.com>
+ *
+ * Copyright (C) 2006-2007 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef SEEN_LINEAR_OF_H
+#define SEEN_LINEAR_OF_H
+#include <2geom/interval.h>
+#include <2geom/math-utils.h>
+
+namespace Geom{
+
+template <typename T>
+inline T lerp(double t, T a, T b) { return a*(1-t) + b*t; }
+
+template <typename T>
+class SBasisOf;
+
+template <typename T>
+class HatOf{
+public:
+ HatOf () {}
+ HatOf(T d) :d(d) {}
+ operator T() const { return d; }
+ T d;
+};
+
+template <typename T>
+class TriOf{
+public:
+ TriOf () {}
+ TriOf(double d) :d(d) {}
+ operator T() const { return d; }
+ T d;
+};
+
+
+//--------------------------------------------------------------------------
+#ifdef USE_SBASIS_OF
+template <typename T>
+class LinearOf;
+typedef Geom::LinearOf<double> Linear;
+#endif
+//--------------------------------------------------------------------------
+
+template <typename T>
+class LinearOf{
+public:
+ T a[2];
+ LinearOf() {}
+ LinearOf(T aa, T b) {a[0] = aa; a[1] = b;}
+ //LinearOf(double aa, double b) {a[0] = T(aa); a[1] = T(b);}
+ LinearOf(HatOf<T> h, TriOf<T> t) {
+ a[0] = T(h) - T(t)/2;
+ a[1] = T(h) + T(t)/2;
+ }
+
+ LinearOf(HatOf<T> h) {
+ a[0] = T(h);
+ a[1] = T(h);
+ }
+
+ unsigned input_dim(){return T::input_dim() + 1;}
+
+ T operator[](const int i) const {
+ assert(i >= 0);
+ assert(i < 2);
+ return a[i];
+ }
+ T& operator[](const int i) {
+ assert(i >= 0);
+ assert(i < 2);
+ return a[i];
+ }
+
+ //IMPL: FragmentConcept
+ typedef T output_type;
+ inline bool isZero() const { return a[0].isZero() && a[1].isZero(); }
+ inline bool isConstant() const { return a[0] == a[1]; }
+ inline bool isFinite() const { return std::isfinite(a[0]) && std::isfinite(a[1]); }
+
+ inline T at0() const { return a[0]; }
+ inline T at1() const { return a[1]; }
+
+ inline T valueAt(double t) const { return lerp(t, a[0], a[1]); }
+ inline T operator()(double t) const { return valueAt(t); }
+
+ //defined in sbasis.h
+ inline SBasisOf<T> toSBasis() const;
+
+//This is specific for T=double!!
+ inline OptInterval bounds_exact() const { return Interval(a[0], a[1]); }
+ inline OptInterval bounds_fast() const { return bounds_exact(); }
+ inline OptInterval bounds_local(double u, double v) const { return Interval(valueAt(u), valueAt(v)); }
+
+ operator TriOf<T>() const {
+ return a[1] - a[0];
+ }
+ operator HatOf<T>() const {
+ return (a[1] + a[0])/2;
+ }
+};
+
+template <>
+unsigned LinearOf<double>::input_dim(){return 1;}
+template <>
+inline OptInterval LinearOf<double>::bounds_exact() const { return Interval(a[0], a[1]); }
+template <>
+inline OptInterval LinearOf<double>::bounds_fast() const { return bounds_exact(); }
+template <>
+inline OptInterval LinearOf<double>::bounds_local(double u, double v) const { return Interval(valueAt(u), valueAt(v)); }
+template <>
+inline bool LinearOf<double>::isZero() const { return a[0]==0 && a[1]==0; }
+
+template <typename T>
+inline LinearOf<T> reverse(LinearOf<T> const &a) { return LinearOf<T>(a[1], a[0]); }
+
+//IMPL: AddableConcept
+template <typename T>
+inline LinearOf<T> operator+(LinearOf<T> const & a, LinearOf<T> const & b) {
+ return LinearOf<T>(a[0] + b[0], a[1] + b[1]);
+}
+template <typename T>
+inline LinearOf<T> operator-(LinearOf<T> const & a, LinearOf<T> const & b) {
+ return LinearOf<T>(a[0] - b[0], a[1] - b[1]);
+}
+template <typename T>
+inline LinearOf<T>& operator+=(LinearOf<T> & a, LinearOf<T> const & b) {
+ a[0] += b[0]; a[1] += b[1];
+ return a;
+}
+template <typename T>
+inline LinearOf<T>& operator-=(LinearOf<T> & a, LinearOf<T> const & b) {
+ a[0] -= b[0]; a[1] -= b[1];
+ return a;
+}
+//IMPL: OffsetableConcept
+template <typename T>
+inline LinearOf<T> operator+(LinearOf<T> const & a, double b) {
+ return LinearOf<T>(a[0] + b, a[1] + b);
+}
+template <typename T>
+inline LinearOf<T> operator-(LinearOf<T> const & a, double b) {
+ return LinearOf<T>(a[0] - b, a[1] - b);
+}
+template <typename T>
+inline LinearOf<T>& operator+=(LinearOf<T> & a, double b) {
+ a[0] += b; a[1] += b;
+ return a;
+}
+template <typename T>
+inline LinearOf<T>& operator-=(LinearOf<T> & a, double b) {
+ a[0] -= b; a[1] -= b;
+ return a;
+}
+/*
+//We can in fact offset in coeff ring T...
+template <typename T>
+inline LinearOf<T> operator+(LinearOf<T> const & a, T b) {
+ return LinearOf<T>(a[0] + b, a[1] + b);
+}
+template <typename T>
+inline LinearOf<T> operator-(LinearOf<T> const & a, T b) {
+ return LinearOf<T>(a[0] - b, a[1] - b);
+}
+template <typename T>
+inline LinearOf<T>& operator+=(LinearOf<T> & a, T b) {
+ a[0] += b; a[1] += b;
+ return a;
+}
+template <typename T>
+inline LinearOf<T>& operator-=(LinearOf<T> & a, T b) {
+ a[0] -= b; a[1] -= b;
+ return a;
+}
+*/
+
+//IMPL: boost::EqualityComparableConcept
+template <typename T>
+inline bool operator==(LinearOf<T> const & a, LinearOf<T> const & b) {
+ return a[0] == b[0] && a[1] == b[1];
+}
+template <typename T>
+inline bool operator!=(LinearOf<T> const & a, LinearOf<T> const & b) {
+ return a[0] != b[0] || a[1] != b[1];
+}
+//IMPL: ScalableConcept
+template <typename T>
+inline LinearOf<T> operator-(LinearOf<T> const &a) {
+ return LinearOf<T>(-a[0], -a[1]);
+}
+template <typename T>
+inline LinearOf<T> operator*(LinearOf<T> const & a, double b) {
+ return LinearOf<T>(a[0]*b, a[1]*b);
+}
+template <typename T>
+inline LinearOf<T> operator/(LinearOf<T> const & a, double b) {
+ return LinearOf<T>(a[0]/b, a[1]/b);
+}
+template <typename T>
+inline LinearOf<T> operator*=(LinearOf<T> & a, double b) {
+ a[0] *= b; a[1] *= b;
+ return a;
+}
+template <typename T>
+inline LinearOf<T> operator/=(LinearOf<T> & a, double b) {
+ a[0] /= b; a[1] /= b;
+ return a;
+}
+/*
+//We can in fact rescale in coeff ring T... (but not divide!)
+template <typename T>
+inline LinearOf<T> operator*(LinearOf<T> const & a, T b) {
+ return LinearOf<T>(a[0]*b, a[1]*b);
+}
+template <typename T>
+inline LinearOf<T> operator/(LinearOf<T> const & a, T b) {
+ return LinearOf<T>(a[0]/b, a[1]/b);
+}
+template <typename T>
+inline LinearOf<T> operator*=(LinearOf<T> & a, T b) {
+ a[0] *= b; a[1] *= b;
+ return a;
+}
+*/
+
+};
+
+#endif //SEEN_LINEAR_OF_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/orphan-code/linearN.h b/src/3rdparty/2geom/include/2geom/orphan-code/linearN.h
new file mode 100644
index 0000000..bb27c30
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/orphan-code/linearN.h
@@ -0,0 +1,363 @@
+/**
+ * @file
+ * @brief LinearN fragment function class
+ *//*
+ * Authors:
+ * JF Barraud <jf.barraud@gmail.com>
+ * Nathan Hurst <njh@mail.csse.monash.edu.au>
+ * Michael Sloan <mgsloan@gmail.com>
+ *
+ * Copyright (C) 2006-2007 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef SEEN_LINEARN_H
+#define SEEN_LINEARN_H
+#include <2geom/interval.h>
+#include <2geom/math-utils.h>
+#include <2geom/linear.h> //for conversion purpose ( + lerp() )
+
+#include <iostream>
+
+namespace Geom{
+
+//TODO: define this only once!! (see linear.h)
+inline double lerpppp(double t, double a, double b) { return a*(1-t) + b*t; }
+
+template<unsigned n>
+class SBasisN;
+
+template<unsigned n>
+class LinearN{
+public:
+ double a[1<<n];// 1<<n is 2^n
+ LinearN() {
+ for (unsigned i=0; i < (1<<n); i++){
+ a[i] = 0.;
+ }
+ }
+ LinearN(double aa[]) {
+ for (unsigned i=0; i < (1<<n); i++){
+ a[i] = aa[i];
+ }
+ }
+ LinearN(double c) {
+ for (unsigned i=0; i<(1<<n); i++){
+ a[i] = c;
+ }
+ }
+ LinearN(LinearN<n-1> const &aa, LinearN<n-1> const &b, unsigned var=0) {
+// for (unsigned i=0; i<(1<<n-1); i++){
+// a[i] = aa[i];
+// a[i+(1<<(n-1))] = b[i];
+// }
+ unsigned mask = (1<<var)-1;
+ for (unsigned i=0; i < (1<<(n-1)); i++){
+ unsigned low_i = i & mask, high_i = i & ~mask;
+ unsigned idx0 = (high_i<<1)|low_i;
+ unsigned idx1 = (high_i<<1)|(1<<var)|low_i;
+ a[idx0] = aa[i];
+ a[idx1] = b[i];
+ }
+
+ }
+ double operator[](const int i) const {
+ assert( i >= 0 );
+ assert( i < (1<<n) );
+ return a[i];
+ }
+ double& operator[](const int i) {
+ assert(i >= 0);
+ assert(i < (1<<n) );
+ return a[i];
+ }
+
+ //IMPL: FragmentConcept
+ typedef double output_type;
+ unsigned input_dim() const {return n;}
+ inline bool isZero() const {
+ for (unsigned i=0; i < (1<<n); i++){
+ if (a[i] != 0) return false;
+ }
+ return true; }
+ inline bool isConstant() const {
+ for (unsigned i=1; i < (1<<n); i++){
+ if (a[i] != a[0]) return false;
+ }
+ return true; }
+ inline bool isConstant(unsigned var) const {
+ unsigned mask = (1<<var)-1;
+ for (unsigned i=0; i < (1<<(n-1)); i++){
+ unsigned low_i = i & mask, high_i = i & ~mask;
+ unsigned idx0 = (high_i<<1)|low_i;
+ unsigned idx1 = (high_i<<1)|(1<<var)|low_i;
+ if (a[idx0] != a[idx1]) return false;
+ }
+ return true;
+ }
+ inline bool isFinite() const {
+ for (unsigned i=0; i < (1<<n); i++){
+ if ( !std::isfinite(a[i]) ) return false;
+ }
+ return true; }
+ //value if k-th variable is set to 0.
+ inline LinearN<n-1> at0(unsigned k=0) const {
+ LinearN<n-1> res;
+ unsigned mask = (1<<k)-1;
+ for (unsigned i=0; i < (1<<(n-1)); i++){
+ unsigned low_i = i & mask, high_i = i & ~mask;
+ unsigned idx = (high_i<<1)|low_i;
+ res[i] = a[idx];
+ }
+ return res;
+ }
+ //value if k-th variable is set to 1.
+ inline LinearN<n-1> at1(unsigned k=0) const {
+ LinearN<n-1> res;
+ for (unsigned i=0; i < (1<<(n-1)); i++){
+ unsigned mask = (1<<k)-1;
+ unsigned low_i = i & mask, high_i = i & ~mask;
+ unsigned idx = (high_i<<1)|(1<<k)|low_i;
+ res[i] = a[idx];
+ }
+ return res;
+ }
+ inline double atCorner(unsigned k) const {
+ assert( k < (1<<n) );
+ return a[k];
+ }
+ inline double atCorner(double t[]) const {
+ unsigned k=0;
+ for(unsigned i=0; i<n; i++){
+ if (t[i] == 1.) k = k | (1<<i);
+ else assert( t[i] == 0. );
+ }
+ return atCorner(k);
+ }
+ inline LinearN<n-1> partialEval(double t, unsigned var=0 ) const {
+ LinearN<n-1> res;
+ res = at0(var)*(1-t) + at1(var)*t;
+ return res;
+ }
+
+ //fixed and flags are used for recursion.
+ inline double valueAt(double t[], unsigned fixed=0, unsigned flags=0 ) const {
+ if (fixed == n) {
+ return a[flags];
+ }else{
+ double a0 = valueAt(t, fixed+1, flags);
+ double a1 = valueAt(t, fixed+1, flags|(1<<fixed));
+ return lerpppp( t[fixed], a0, a1 );
+ }
+ }
+ inline double operator()(double t[]) const { return valueAt(t); }
+
+ //defined in sbasisN.h
+ inline SBasisN<n> toSBasisN() const;
+
+ inline OptInterval bounds_exact() const {
+ double min=a[0], max=a[0];
+ for (unsigned i=1; i < (1<<n); i++){
+ if (a[i] < min) min = a[i];
+ if (a[i] > max) max = a[i];
+ }
+ return Interval(min, max);
+ }
+ inline OptInterval bounds_fast() const { return bounds_exact(); }
+ //inline OptInterval bounds_local(double u, double v) const { return Interval(valueAt(u), valueAt(v)); }
+};
+
+//LinearN<0> are doubles. Specialize them out.
+template<>
+class LinearN<0>{
+public:
+ double d;
+ LinearN () {}
+ LinearN(double d) :d(d) {}
+ operator double() const { return d; }
+ double operator[](const int i) const {assert (i==0); return d;}
+ double& operator[](const int i) {assert (i==0); return d;}
+ typedef double output_type;
+ unsigned input_dim() const {return 0;}
+ inline bool isZero() const { return d==0; }
+ inline bool isConstant() const { return true; }
+ inline bool isFinite() const { return std::isfinite(d); }
+};
+
+//LinearN<1> are usual Linear. Allow conversion.
+Linear toLinear(LinearN<1> f){
+ return Linear(f[0],f[1]);
+}
+
+
+
+//inline Linear reverse(Linear const &a) { return Linear(a[1], a[0]); }
+
+//IMPL: AddableConcept
+template<unsigned n>
+inline LinearN<n> operator+(LinearN<n> const & a, LinearN<n> const & b) {
+ LinearN<n> res;
+ for (unsigned i=0; i < (1<<n); i++){
+ res[i] = a[i] + b[i];
+ }
+ return res;
+}
+template<unsigned n>
+inline LinearN<n> operator-(LinearN<n> const & a, LinearN<n> const & b) {
+ LinearN<n> res;
+ for (unsigned i=0; i < (1<<n); i++){
+ res[i] = a[i] - b[i];
+ }
+ return res;
+}
+template<unsigned n>
+inline LinearN<n>& operator+=(LinearN<n> & a, LinearN<n> const & b) {
+ for (unsigned i=0; i < (1<<n); i++){
+ a[i] += b[i];
+ }
+ return a;
+}
+template<unsigned n>
+inline LinearN<n>& operator-=(LinearN<n> & a, LinearN<n> const & b) {
+ for (unsigned i=0; i < (1<<n); i++){
+ a[i] -= b[i];
+ }
+ return a;
+}
+//IMPL: OffsetableConcept
+template<unsigned n>
+inline LinearN<n> operator+(LinearN<n> const & a, double b) {
+ LinearN<n> res;
+ for (unsigned i=0; i < (1<<n); i++){
+ res[i] = a[i] + b;
+ }
+ return res;
+}
+template<unsigned n>
+inline LinearN<n> operator-(LinearN<n> const & a, double b) {
+ LinearN<n> res;
+ for (unsigned i=0; i < (1<<n); i++){
+ res[i] = a[i] - b;
+ }
+ return res;
+}
+template<unsigned n>
+inline LinearN<n>& operator+=(LinearN<n> & a, double b) {
+ for (unsigned i=0; i < (1<<n); i++){
+ a[i] += b;
+ }
+ return a;
+}
+template<unsigned n>
+inline LinearN<n>& operator-=(LinearN<n> & a, double b) {
+ for (unsigned i=0; i < (1<<n); i++){
+ a[i] -= b;
+ }
+ return a;
+}
+//IMPL: boost::EqualityComparableConcept
+template<unsigned n>
+inline bool operator==(LinearN<n> const & a, LinearN<n> const & b) {
+ for (unsigned i=0; i < (1<<n); i++){
+ if (a[i] != b[i]) return false;
+ }
+ return true;
+}
+template<unsigned n>
+inline bool operator!=(LinearN<n> const & a, LinearN<n> const & b) {
+ return !(a==b);
+}
+//IMPL: ScalableConcept
+template<unsigned n>
+inline LinearN<n> operator-(LinearN<n> const &a) {
+ LinearN<n> res;
+ for (unsigned i=0; i < (1<<n); i++){
+ res[i] = -a[i];
+ }
+ return res;
+}
+template<unsigned n>
+inline LinearN<n> operator*(LinearN<n> const & a, double b) {
+ LinearN<n> res;
+ for (unsigned i=0; i < (1<<n); i++){
+ res[i] = a[i] * b;
+ }
+ return res;
+}
+template<unsigned n>
+inline LinearN<n> operator/(LinearN<n> const & a, double b) {
+ LinearN<n> res;
+ for (unsigned i=0; i < (1<<n); i++){
+ res[i] = a[i] / b;
+ }
+ return res;
+}
+template<unsigned n>
+inline LinearN<n> operator*=(LinearN<n> & a, double b) {
+ for (unsigned i=0; i < (1<<n); i++){
+ a[i] *= b;
+ }
+ return a;
+}
+template<unsigned n>
+inline LinearN<n> operator/=(LinearN<n> & a, double b) {
+ for (unsigned i=0; i < (1<<n); i++){
+ a[i] /= b;
+ }
+ return a;
+}
+
+template<unsigned n>
+void setToVariable(LinearN<n> &x, unsigned k){;
+ x = LinearN<n>(0.);
+ unsigned mask = 1<<k;
+ for (unsigned i=0; i < (1<<n); i++){
+ if ( i & mask ) x[i] = 1;
+ }
+}
+
+template<unsigned n>
+inline std::ostream &operator<< (std::ostream &out_file, const LinearN<n> &bo) {
+ out_file << "{";
+ for (unsigned i=0; i < (1<<n); i++){
+ out_file << bo[i]<<(i == (1<<n)-1 ? "}" : ",");
+ }
+ return out_file;
+}
+
+
+}
+#endif //SEEN_LINEAR_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/orphan-code/redblacktree.h b/src/3rdparty/2geom/include/2geom/orphan-code/redblacktree.h
new file mode 100644
index 0000000..9d79342
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/orphan-code/redblacktree.h
@@ -0,0 +1,121 @@
+/**
+ * \file
+ * \brief
+ * Implementation of Red-Black Tree as described in
+ * Intorduction to Algorithms. Cormen et al. Mc Grow Hill. 1990. pp 263-280
+ *
+ * The intention is to implement interval trees mentioned in the same book, after the red-black.
+ * Interval are heavily based on red-black trees (most operations are the same). So, we begin first
+ * with implementing red-black!
+ *
+ * Authors:
+ * ? <?@?.?>
+ *
+ * Copyright 2009-2009 Evangelos Katsikaros
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef SEEN_LIB2GEOM_REDBLACKTREE_H
+#define SEEN_LIB2GEOM_REDBLACKTREE_H
+
+#include <vector>
+//#include <cassert>
+#include <limits>
+#include <cfloat>
+
+#include <2geom/d2.h>
+#include <2geom/interval.h>
+
+namespace Geom{
+
+class RedBlack{
+public:
+ Interval interval; // Key of the redblack tree will be the min of the interval
+ RedBlack *left, *right, *parent;
+ bool isRed;
+ Coord subtree_max; // subtree_max = max( x->left->subtree_max, x->right->subtree_max, x->high )
+ int data;
+
+ RedBlack(): left(0), right(0), parent(0), isRed(false), subtree_max(0.0), data(0) {
+ Interval interval(0.0, 0.0);
+ }
+/*
+ RedBlack(Coord min, Coord max): left(0), right(0), parent(0), isRed(false), subtree_max(0.0), data(0) {
+ Interval interval( min, max );
+ }
+*/
+ inline Coord key(){ return interval.min(); };
+ inline Coord high(){ return interval.max(); };
+};
+
+
+class RedBlackTree{
+public:
+ RedBlack* root;
+
+ RedBlackTree(): root(0) {}
+
+ void insert(Rect const &r, int shape, int dimension);
+ void insert(Coord dimension_min, Coord dimension_max, int shape);
+
+ void erase(Rect const &r);
+ void erase(int shape);
+
+ RedBlack* search(Rect const &r, int dimension);
+ RedBlack* search(Interval i);
+ RedBlack* search(Coord a, Coord b);
+
+ void print_tree();
+private:
+ void inorder_tree_walk(RedBlack* x);
+ RedBlack* tree_minimum(RedBlack* x);
+ RedBlack* tree_successor(RedBlack* x);
+
+ void left_rotate(RedBlack* x);
+ void right_rotate(RedBlack* x);
+ void tree_insert(RedBlack* x);
+
+ void update_max(RedBlack* x);
+
+ RedBlack* erase(RedBlack* x); // TODO why rerutn pointer? to collect garbage ???
+ void erase_fixup(RedBlack* x);
+
+};
+
+} // end namespace Geom
+
+#endif // !SEEN_LIB2GEOM_REDBLACKTREE_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/orphan-code/rtree.h b/src/3rdparty/2geom/include/2geom/orphan-code/rtree.h
new file mode 100644
index 0000000..3ffae8e
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/orphan-code/rtree.h
@@ -0,0 +1,241 @@
+/**
+ * \file
+ * \brief
+ * Implementation of Red-Black Tree as described in
+ * Intorduction to Algorithms. Cormen et al. Mc Grow Hill. 1990. pp 263-280
+ *
+ * The intention is to implement interval trees mentioned in the same book, after the red-black.
+ * Interval are heavily based on red-black trees (most operations are the same). So, we begin first
+ * with implementing red-black!
+ *
+ * Authors:
+ * ? <?@?.?>
+ *
+ * Copyright 2009-2009 Evangelos Katsikaros
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef SEEN_LIB2GEOM_RTREE_H
+#define SEEN_LIB2GEOM_RTREE_H
+
+#include <vector>
+#include <utility>
+
+
+#include <2geom/d2.h>
+#include <2geom/interval.h>
+
+namespace Geom{
+
+// used only in pick_next( )
+enum enum_add_to_group {
+ ADD_TO_GROUP_A = 0,
+ ADD_TO_GROUP_B
+};
+
+
+enum enum_split_strategy {
+ QUADRATIC_SPIT = 0,
+ LINEAR_COST,
+ TOTAL_STRATEGIES // this one must be the last item
+};
+
+
+
+template <typename T>
+class pedantic_vector:public std::vector<T> {
+public:
+ pedantic_vector(size_t s=0) : std::vector<T>(s) {}
+ T& operator[](unsigned i) {
+ //assert(i >= 0);
+ assert(i < std::vector<T>::size());
+ return std::vector<T>::operator[](i);
+ }
+ T const& operator[](unsigned i) const {
+ //assert(i >= 0);
+ assert(i < std::vector<T>::size());
+ return std::vector<T>::operator[](i);
+ }
+/*
+ erase( std::vector<T>::iterator it ) {
+ //assert(i >= 0);
+ assert( it < std::vector<T>::size());
+ return std::vector<T>::erase(it);
+ }
+*/
+};
+
+class RTreeNode;
+
+class RTreeRecord_Leaf{
+public:
+ Rect bounding_box;
+ int data;
+
+ RTreeRecord_Leaf(): bounding_box(), data(0)
+ {}
+
+ RTreeRecord_Leaf(Rect bb, int d): bounding_box(bb), data(d)
+ {}
+};
+
+class RTreeRecord_NonLeaf{
+public:
+ Rect bounding_box;
+ RTreeNode* data;
+
+ RTreeRecord_NonLeaf(): bounding_box(), data(0)
+ {}
+
+ RTreeRecord_NonLeaf(Rect bb, RTreeNode* d): bounding_box(bb), data(d)
+ {}
+};
+
+/*
+R-Tree has 2 kinds of nodes
+* Leaves which store:
+ - the actual data
+ - the bounding box of the data
+
+* Non-Leaves which store:
+ - a child node (data)
+ - the bounding box of the child node
+
+This causes some code duplication in rtree.cpp. There are 2 cases:
+- we care whether we touch a leaf/non-leaf node, since we write data in the node, so we want to
+ write the correct thing (int or RTreeNode*)
+- we do NOT care whether we touch a leaf/non-leaf node, because we only read/write the bounding
+ boxes which is the same in both cases.
+
+TODO:
+A better design would eliminate the duplication in the 2nd case, but we can't avoid the 1st probably.
+*/
+class RTreeNode{
+public:
+ // first: bounding box
+ // second: "data" (leaf-node) or node (NON leaf-node)
+ //pedantic_vector< RTreeRecord_Leaf > children_leaves; // if this is empty, then node is leaf-node
+ //pedantic_vector< RTreeRecord_NonLeaf > children_nodes; // if this is empty, then node is NON-leaf node
+
+ std::vector< RTreeRecord_Leaf > children_leaves; // if this is empty, then node is leaf-node
+ std::vector< RTreeRecord_NonLeaf > children_nodes; // if this is empty, then node is NON-leaf node
+
+ RTreeNode(): children_leaves(0), children_nodes(0)
+ {}
+
+};
+
+
+class RTree{
+public:
+ RTreeNode* root;
+
+ // min/max records per node
+ unsigned min_records;
+ unsigned max_records; // allow +1 (used during insert)
+
+ enum_split_strategy split_strategy;
+
+
+ RTree( unsigned n, unsigned m, enum_split_strategy split_s ):
+ root(0), min_records( n ), max_records( m ), split_strategy( split_s ),
+ tree_height(0)
+ {}
+
+ void insert( Rect const &r, unsigned shape);
+ void search( const Rect &search_area, std::vector< int >* result, const RTreeNode* subtree ) const;
+ //int erase( const RTreeRecord_Leaf & search );
+ int erase( const Rect &search_area, const int shape_to_delete );
+
+// update
+
+ void print_tree(RTreeNode* subtree_root, int depth ) const;
+
+private:
+ unsigned tree_height; // 0 is the root level
+
+ void insert( //Rect const &r,
+ //int shape,
+ const RTreeRecord_Leaf &leaf_record,
+ const bool &insert_high = false,
+ const unsigned &stop_height = 0,
+ const RTreeRecord_NonLeaf &nonleaf_record = RTreeRecord_NonLeaf()
+ );
+ // I1
+ RTreeNode* choose_node( const Rect &r, const bool &insert_high = false, const unsigned &stop_height=0 ) const;
+ double find_waste_area( const Rect &a, const Rect &b ) const;
+ double find_enlargement( const Rect &a, const Rect &b ) const;
+
+ // I2
+ std::pair<RTreeNode*, RTreeNode*> split_node( RTreeNode *s );
+ // QUADRATIC_SPIT
+ std::pair<RTreeNode*, RTreeNode*> quadratic_split( RTreeNode* s );
+ std::pair<unsigned, unsigned> pick_seeds( RTreeNode* s ) const;
+ std::pair<unsigned, enum_add_to_group> pick_next( RTreeNode* group_a, RTreeNode* group_b, RTreeNode* s, std::vector<bool> &assigned_v );
+ // others...
+
+ // I3
+ bool adjust_tree( RTreeNode* position,
+ std::pair<RTreeNode*, RTreeNode*> &node_division,
+ bool split_performed
+ );
+ std::pair< RTreeNode*, bool > find_parent( RTreeNode* subtree_root, Rect search_area, RTreeNode* wanted ) const;
+
+ void recalculate_bounding_box( RTreeNode* parent, RTreeNode* child, unsigned &child_in_parent );
+
+ void copy_group_a_to_existing_node( RTreeNode *position, RTreeNode* group_a );
+ RTreeRecord_NonLeaf create_nonleaf_record_from_rtreenode( Rect &new_entry_bounding, RTreeNode *rtreenode );
+ RTreeRecord_Leaf create_leaf_record_from_rtreenode( Rect &new_entry_bounding, RTreeNode *rtreenode );
+
+ // erase
+// RTreeNode* find_leaf( RTreeNode* subtree, const RTreeRecord_Leaf &search ) const;
+ RTreeNode* find_leaf( RTreeNode* subtree, const Rect &search_area, const int shape_to_delete ) const;
+
+ bool condense_tree( RTreeNode* position
+ // std::pair<RTreeNode*, RTreeNode*> &node_division, // modified: it holds the last split group
+ // bool initial_split_performed,
+ // const unsigned min_nodes
+ // const unsigned max_nodes
+ );
+ int remove_record_from_parent( RTreeNode* parent, RTreeNode* child );
+ void sanity_check(RTreeNode* subtree_root, int depth, bool used_during_insert = false ) const;
+
+};
+
+} // end namespace Geom
+
+#endif // !SEEN_LIB2GEOM_RTREE_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/orphan-code/sbasis-of.h b/src/3rdparty/2geom/include/2geom/orphan-code/sbasis-of.h
new file mode 100644
index 0000000..e5b76d6
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/orphan-code/sbasis-of.h
@@ -0,0 +1,638 @@
+/**
+ * \file
+ * \brief Defines S-power basis function class
+ * with coefficient in arbitrary ring
+ *
+ * Authors:
+ * Nathan Hurst <njh@mail.csse.monash.edu.au>
+ * Michael Sloan <mgsloan@gmail.com>
+ *
+ * Copyright (C) 2006-2007 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef SEEN_SBASIS_OF_H
+#define SEEN_SBASIS_OF_H
+#include <vector>
+#include <cassert>
+#include <iostream>
+
+#include <2geom/interval.h>
+#include <2geom/utils.h>
+#include <2geom/exception.h>
+
+#include <2geom/orphan-code/linear-of.h>
+
+namespace Geom {
+
+template<typename T>
+class SBasisOf;
+
+#ifdef USE_SBASIS_OF
+typedef Geom::SBasisOf<double> SBasis;
+#endif
+
+/*** An empty SBasisOf<T> is identically 0. */
+template<typename T>
+class SBasisOf : public std::vector<LinearOf<T> >{
+public:
+ SBasisOf() {}
+ explicit SBasisOf(T a) {
+ this->push_back(LinearOf<T>(a,a));
+ }
+ SBasisOf(SBasisOf<T> const & a) :
+ std::vector<LinearOf<T> >(a)
+ {}
+ SBasisOf(LinearOf<T> const & bo) {
+ this->push_back(bo);
+ }
+ SBasisOf(LinearOf<T>* bo) {
+ this->push_back(*bo);
+ }
+ //static unsigned input_dim(){return T::input_dim()+1;}
+
+ //IMPL: FragmentConcept
+ typedef T output_type;
+ inline bool isZero() const {
+ if(this->empty()) return true;
+ for(unsigned i = 0; i < this->size(); i++) {
+ if(!(*this)[i].isZero()) return false;
+ }
+ return true;
+ }
+ inline bool isConstant() const {
+ if (this->empty()) return true;
+ for (unsigned i = 0; i < this->size(); i++) {
+ if(!(*this)[i].isConstant()) return false;
+ }
+ return true;
+ }
+
+ //TODO: code this...
+ bool isFinite() const;
+
+ inline T at0() const {
+ if(this->empty()) return T(0); else return (*this)[0][0];
+ }
+ inline T at1() const{
+ if(this->empty()) return T(0); else return (*this)[0][1];
+ }
+
+ T valueAt(double t) const {
+ double s = t*(1-t);
+ T p0 = T(0.), p1 = T(0.);
+ for(unsigned k = this->size(); k > 0; k--) {
+ const LinearOf<T> &lin = (*this)[k-1];
+ p0 = p0*s + lin[0];
+ p1 = p1*s + lin[1];
+ }
+ return p0*(1-t) + p1*t;
+ }
+
+ T operator()(double t) const {
+ return valueAt(t);
+ }
+
+ /**
+ * The size of the returned vector equals n+1.
+ */
+ std::vector<T> valueAndDerivatives(double t, unsigned n) const{
+ std::vector<T> ret(n+1);
+ ret[0] = valueAt(t);
+ SBasisOf<T> tmp = *this;
+ for(unsigned i = 0; i < n; i++) {
+ tmp.derive();
+ ret[i+1] = tmp.valueAt(t);
+ }
+ return ret;
+ }
+
+ //The following lines only makes sens if T=double!
+ SBasisOf<T> toSBasis() const { return SBasisOf<T>(*this); }
+ double tailError(unsigned tail) const{
+ Interval bs = *bounds_fast(*this, tail);
+ return std::max(fabs(bs.min()),fabs(bs.max()));
+ }
+
+// compute f(g)
+ SBasisOf<T> operator()(SBasisOf<T> const & g) const;
+
+ LinearOf<T> operator[](unsigned i) const {
+ assert(i < this->size());
+ return std::vector<LinearOf<T> >::operator[](i);
+ }
+
+//MUTATOR PRISON
+ LinearOf<T>& operator[](unsigned i) { return this->at(i); }
+
+ //remove extra zeros
+ void normalize() {
+ while(!this->empty() && this->back().isZero())
+ this->pop_back();
+ }
+
+ void truncate(unsigned k) { if(k < this->size()) this->resize(k); }
+private:
+ void derive(); // in place version
+ unsigned dim;
+};
+
+//template<>
+//inline unsigned SBasisOf<double>::input_dim() { return 1; }
+
+//--------------------------------------------------------------------------
+#ifdef USE_SBASIS_OF
+
+//implemented in sbasis-roots.cpp
+OptInterval bounds_exact(SBasis const &a);
+OptInterval bounds_fast(SBasis const &a, int order = 0);
+OptInterval bounds_local(SBasis const &a, const OptInterval &t, int order = 0);
+
+std::vector<double> roots(SBasis const & s);
+std::vector<std::vector<double> > multi_roots(SBasis const &f,
+ std::vector<double> const &levels,
+ double htol=1e-7,
+ double vtol=1e-7,
+ double a=0,
+ double b=1);
+#endif
+//--------------------------------------------------------------------------
+
+
+//TODO: figure out how to stick this in linear, while not adding an sbasis dep
+template<typename T>
+inline SBasisOf<T> LinearOf<T>::toSBasis() const { return SBasisOf<T>(*this); }
+
+template<typename T>
+inline SBasisOf<T> reverse(SBasisOf<T> const &a) {
+ SBasisOf<T> result;
+ result.reserve(a.size());
+ for(unsigned k = 0; k < a.size(); k++)
+ result.push_back(reverse(a[k]));
+ return result;
+}
+
+//IMPL: ScalableConcept
+template<typename T>
+inline SBasisOf<T> operator-(const SBasisOf<T>& p) {
+ if(p.isZero()) return SBasisOf<T>();
+ SBasisOf<T> result;
+ result.reserve(p.size());
+
+ for(unsigned i = 0; i < p.size(); i++) {
+ result.push_back(-p[i]);
+ }
+ return result;
+}
+
+template<typename T>
+SBasisOf<T> operator*(SBasisOf<T> const &a, double k){
+ SBasisOf<T> c;
+ //TODO: what does this mean for vectors of vectors??
+ //c.reserve(a.size());
+ for(unsigned i = 0; i < a.size(); i++)
+ c.push_back(a[i] * k);
+ return c;
+}
+
+template<typename T>
+inline SBasisOf<T> operator*(double k, SBasisOf<T> const &a) { return a*k; }
+template<typename T>
+inline SBasisOf<T> operator/(SBasisOf<T> const &a, double k) { return a*(1./k); }
+template<typename T>
+SBasisOf<T>& operator*=(SBasisOf<T>& a, double b){
+ if (a.isZero()) return a;
+ if (b == 0)
+ a.clear();
+ else
+ for(unsigned i = 0; i < a.size(); i++)
+ a[i] *= b;
+ return a;
+}
+
+template<typename T>
+inline SBasisOf<T>& operator/=(SBasisOf<T>& a, double b) { return (a*=(1./b)); }
+
+/*
+//We can also multiply by element of ring coeff T:
+template<typename T>
+SBasisOf<T> operator*(SBasisOf<T> const &a, T k){
+ SBasisOf<T> c;
+ //TODO: what does this mean for vectors of vectors??
+ //c.reserve(a.size());
+ for(unsigned i = 0; i < a.size(); i++)
+ c.push_back(a[i] * k);
+ return c;
+}
+
+template<typename T>
+inline SBasisOf<T> operator*(T k, SBasisOf<T> const &a) { return a*k; }
+template<typename T>
+SBasisOf<T>& operator*=(SBasisOf<T>& a, T b){
+ if (a.isZero()) return a;
+ if (b == 0)
+ a.clear();
+ else
+ for(unsigned i = 0; i < a.size(); i++)
+ a[i] *= b;
+ return a;
+}
+*/
+
+//IMPL: AddableConcept
+template<typename T>
+inline SBasisOf<T> operator+(const SBasisOf<T>& a, const SBasisOf<T>& b){
+ SBasisOf<T> result;
+ const unsigned out_size = std::max(a.size(), b.size());
+ const unsigned min_size = std::min(a.size(), b.size());
+ //TODO: what does this mean for vector<vector>;
+ //result.reserve(out_size);
+
+ for(unsigned i = 0; i < min_size; i++) {
+ result.push_back(a[i] + b[i]);
+ }
+ for(unsigned i = min_size; i < a.size(); i++)
+ result.push_back(a[i]);
+ for(unsigned i = min_size; i < b.size(); i++)
+ result.push_back(b[i]);
+
+ assert(result.size() == out_size);
+ return result;
+}
+
+template<typename T>
+SBasisOf<T> operator-(const SBasisOf<T>& a, const SBasisOf<T>& b){
+ SBasisOf<T> result;
+ const unsigned out_size = std::max(a.size(), b.size());
+ const unsigned min_size = std::min(a.size(), b.size());
+ //TODO: what does this mean for vector<vector>;
+ //result.reserve(out_size);
+
+ for(unsigned i = 0; i < min_size; i++) {
+ result.push_back(a[i] - b[i]);
+ }
+ for(unsigned i = min_size; i < a.size(); i++)
+ result.push_back(a[i]);
+ for(unsigned i = min_size; i < b.size(); i++)
+ result.push_back(-b[i]);
+
+ assert(result.size() == out_size);
+ return result;
+}
+
+template<typename T>
+SBasisOf<T>& operator+=(SBasisOf<T>& a, const SBasisOf<T>& b){
+ const unsigned out_size = std::max(a.size(), b.size());
+ const unsigned min_size = std::min(a.size(), b.size());
+ //TODO: what does this mean for vectors of vectors
+ //a.reserve(out_size);
+ for(unsigned i = 0; i < min_size; i++)
+ a[i] += b[i];
+ for(unsigned i = min_size; i < b.size(); i++)
+ a.push_back(b[i]);
+
+ assert(a.size() == out_size);
+ return a;
+}
+
+template<typename T>
+SBasisOf<T>& operator-=(SBasisOf<T>& a, const SBasisOf<T>& b){
+ const unsigned out_size = std::max(a.size(), b.size());
+ const unsigned min_size = std::min(a.size(), b.size());
+ //TODO: what does this mean for vectors of vectors
+ //a.reserve(out_size);
+ for(unsigned i = 0; i < min_size; i++)
+ a[i] -= b[i];
+ for(unsigned i = min_size; i < b.size(); i++)
+ a.push_back(-b[i]);
+
+ assert(a.size() == out_size);
+ return a;
+}
+
+//TODO: remove?
+template<typename T>
+inline SBasisOf<T> operator+(const SBasisOf<T> & a, LinearOf<T> const & b) {
+ if(b.isZero()) return a;
+ if(a.isZero()) return b;
+ SBasisOf<T> result(a);
+ result[0] += b;
+ return result;
+}
+template<typename T>
+inline SBasisOf<T> operator-(const SBasisOf<T> & a, LinearOf<T> const & b) {
+ if(b.isZero()) return a;
+ SBasisOf<T> result(a);
+ result[0] -= b;
+ return result;
+}
+template<typename T>
+inline SBasisOf<T>& operator+=(SBasisOf<T>& a, const LinearOf<T>& b) {
+ if(a.isZero())
+ a.push_back(b);
+ else
+ a[0] += b;
+ return a;
+}
+template<typename T>
+inline SBasisOf<T>& operator-=(SBasisOf<T>& a, const LinearOf<T>& b) {
+ if(a.isZero())
+ a.push_back(-b);
+ else
+ a[0] -= b;
+ return a;
+}
+
+//IMPL: OffsetableConcept
+/*
+template<typename T>
+inline SBasisOf<T> operator+(const SBasisOf<T> & a, double b) {
+ if(a.isZero()) return LinearOf<T>(b, b);
+ SBasisOf<T> result(a);
+ result[0] += b;
+ return result;
+}
+template<typename T>
+inline SBasisOf<T> operator-(const SBasisOf<T> & a, double b) {
+ if(a.isZero()) return LinearOf<T>(-b, -b);
+ SBasisOf<T> result(a);
+ result[0] -= b;
+ return result;
+}
+template<typename T>
+inline SBasisOf<T>& operator+=(SBasisOf<T>& a, double b) {
+ if(a.isZero())
+ a.push_back(LinearOf<T>(b,b));
+ else
+ a[0] += b;
+ return a;
+}
+template<typename T>
+inline SBasisOf<T>& operator-=(SBasisOf<T>& a, double b) {
+ if(a.isZero())
+ a.push_back(LinearOf<T>(-b,-b));
+ else
+ a[0] -= b;
+ return a;
+}
+*/
+//We can also offset by elements of coeff ring T
+template<typename T>
+inline SBasisOf<T> operator+(const SBasisOf<T> & a, T b) {
+ if(a.isZero()) return LinearOf<T>(b, b);
+ SBasisOf<T> result(a);
+ result[0] += b;
+ return result;
+}
+template<typename T>
+inline SBasisOf<T> operator-(const SBasisOf<T> & a, T b) {
+ if(a.isZero()) return LinearOf<T>(-b, -b);
+ SBasisOf<T> result(a);
+ result[0] -= b;
+ return result;
+}
+template<typename T>
+inline SBasisOf<T>& operator+=(SBasisOf<T>& a, T b) {
+ if(a.isZero())
+ a.push_back(LinearOf<T>(b,b));
+ else
+ a[0] += b;
+ return a;
+}
+template<typename T>
+inline SBasisOf<T>& operator-=(SBasisOf<T>& a, T b) {
+ if(a.isZero())
+ a.push_back(LinearOf<T>(-b,-b));
+ else
+ a[0] -= b;
+ return a;
+}
+
+
+template<typename T>
+SBasisOf<T> shift(SBasisOf<T> const &a, int sh){
+ SBasisOf<T> c = a;
+ if(sh > 0) {
+ c.insert(c.begin(), sh, LinearOf<T>(0,0));
+ } else {
+ //TODO: truncate
+ }
+ return c;
+}
+
+template<typename T>
+SBasisOf<T> shift(LinearOf<T> const &a, int sh) {
+ SBasisOf<T> c;
+ if(sh > 0) {
+ c.insert(c.begin(), sh, LinearOf<T>(0,0));
+ c.push_back(a);
+ }
+ return c;
+}
+
+template<typename T>
+inline SBasisOf<T> truncate(SBasisOf<T> const &a, unsigned terms) {
+ SBasisOf<T> c;
+ c.insert(c.begin(), a.begin(), a.begin() + std::min(terms, (unsigned)a.size()));
+ return c;
+}
+
+template<typename T>
+SBasisOf<T> multiply_add(SBasisOf<T> const &a, SBasisOf<T> const &b, SBasisOf<T> c) {
+ if(a.isZero() || b.isZero())
+ return c;
+ c.resize(a.size() + b.size(), LinearOf<T>(T(0.),T(0.)));
+ for(unsigned j = 0; j < b.size(); j++) {
+ for(unsigned i = j; i < a.size()+j; i++) {
+ T tri = (b[j][1]-b[j][0])*(a[i-j][1]-a[i-j][0]);
+ c[i+1/*shift*/] += LinearOf<T>(-tri);
+ }
+ }
+ for(unsigned j = 0; j < b.size(); j++) {
+ for(unsigned i = j; i < a.size()+j; i++) {
+ for(unsigned dim = 0; dim < 2; dim++)
+ c[i][dim] += b[j][dim]*a[i-j][dim];
+ }
+ }
+ c.normalize();
+ //assert(!(0 == c.back()[0] && 0 == c.back()[1]));
+ return c;
+}
+
+template<typename T>
+SBasisOf<T> multiply(SBasisOf<T> const &a, SBasisOf<T> const &b) {
+ SBasisOf<T> c;
+ if(a.isZero() || b.isZero())
+ return c;
+ return multiply_add(a, b, c);
+}
+
+template<typename T>
+SBasisOf<T> integral(SBasisOf<T> const &c){
+ SBasisOf<T> a;
+ T aTri = T(0.);
+ for(int k = c.size()-1; k >= 0; k--) {
+ aTri = (HatOf<T>(c[k]).d + (k+1)*aTri/2)/(2*k+1);
+ a[k][0] -= aTri/2;
+ a[k][1] += aTri/2;
+ }
+ a.normalize();
+ return a;
+}
+
+template<typename T>
+SBasisOf<T> derivative(SBasisOf<T> const &a){
+ SBasisOf<T> c;
+ c.resize(a.size(), LinearOf<T>());
+ if(a.isZero())
+ return c;
+
+ for(unsigned k = 0; k < a.size()-1; k++) {
+ T d = (2*k+1)*(a[k][1] - a[k][0]);
+
+ c[k][0] = d + (k+1)*a[k+1][0];
+ c[k][1] = d - (k+1)*a[k+1][1];
+ }
+ int k = a.size()-1;
+ T d = (2*k+1)*(a[k][1] - a[k][0]);
+ //TODO: do a real test to know if d==0!
+ if(d == T(0.0))
+ c.pop_back();
+ else {
+ c[k][0] = d;
+ c[k][1] = d;
+ }
+
+ return c;
+}
+
+template<typename T>
+void SBasisOf<T>::derive() { // in place version
+ if(isZero()) return;
+ for(unsigned k = 0; k < this->size()-1; k++) {
+ T d = (2*k+1)*((*this)[k][1] - (*this)[k][0]);
+
+ (*this)[k][0] = d + (k+1)*(*this)[k+1][0];
+ (*this)[k][1] = d - (k+1)*(*this)[k+1][1];
+ }
+ int k = this->size()-1;
+ T d = (2*k+1)*((*this)[k][1] - (*this)[k][0]);
+ if(d == 0)//TODO: give this a meaning for general coeff ring.
+ this->pop_back();
+ else {
+ (*this)[k][0] = d;
+ (*this)[k][1] = d;
+ }
+}
+
+
+template<typename T>
+inline SBasisOf<T> operator*(SBasisOf<T> const & a, SBasisOf<T> const & b) {
+ return multiply(a, b);
+}
+
+template<typename T>
+inline SBasisOf<T>& operator*=(SBasisOf<T>& a, SBasisOf<T> const & b) {
+ a = multiply(a, b);
+ return a;
+}
+
+// a(b(t))
+//TODO: compose all compatibles types!
+template<typename T>
+SBasisOf<T> compose(SBasisOf<T> const &a, SBasisOf<T> const &b){
+ SBasisOf<double> s = multiply((SBasisOf<T>(LinearOf<T>(1,1))-b), b);
+ SBasisOf<T> r;
+
+ for(int i = a.size()-1; i >= 0; i--) {
+ r = multiply_add(r, s, SBasisOf<T>(LinearOf<T>(HatOf<T>(a[i][0]))) - b*a[i][0] + b*a[i][1]);
+ }
+ return r;
+}
+
+template<typename T>
+SBasisOf<T> compose(SBasisOf<T> const &a, SBasisOf<T> const &b, unsigned k){
+ SBasisOf<T> s = multiply((SBasisOf<T>(LinearOf<T>(1,1))-b), b);
+ SBasisOf<T> r;
+
+ for(int i = a.size()-1; i >= 0; i--) {
+ r = multiply_add(r, s, SBasisOf<T>(LinearOf<T>(HatOf<T>(a[i][0]))) - b*a[i][0] + b*a[i][1]);
+ }
+ r.truncate(k);
+ return r;
+}
+template<typename T>
+SBasisOf<T> compose(LinearOf<T> const &a, SBasisOf<T> const &b){
+ return compose(SBasisOf<T>(a),b);
+}
+template<typename T>
+SBasisOf<T> compose(SBasisOf<T> const &a, LinearOf<T> const &b){
+ return compose(a,SBasisOf<T>(b));
+}
+template<typename T>//TODO: don't be so lazy!!
+SBasisOf<T> compose(LinearOf<T> const &a, LinearOf<T> const &b){
+ return compose(SBasisOf<T>(a),SBasisOf<T>(b));
+}
+
+
+
+template<typename T>
+inline SBasisOf<T> portion(const SBasisOf<T> &t, double from, double to) { return compose(t, LinearOf<T>(from, to)); }
+
+// compute f(g)
+template<typename T>
+inline SBasisOf<T>
+SBasisOf<T>::operator()(SBasisOf<T> const & g) const {
+ return compose(*this, g);
+}
+
+template<typename T>
+inline std::ostream &operator<< (std::ostream &out_file, const LinearOf<T> &bo) {
+ out_file << "{" << bo[0] << ", " << bo[1] << "}";
+ return out_file;
+}
+
+template<typename T>
+inline std::ostream &operator<< (std::ostream &out_file, const SBasisOf<T> & p) {
+ for(unsigned i = 0; i < p.size(); i++) {
+ out_file << p[i] << "s^" << i << " + ";
+ }
+ return out_file;
+}
+
+};
+#endif
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/orphan-code/sbasisN.h b/src/3rdparty/2geom/include/2geom/orphan-code/sbasisN.h
new file mode 100644
index 0000000..0b5a48f
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/orphan-code/sbasisN.h
@@ -0,0 +1,1123 @@
+/**
+ * \file
+ * \brief Multi-dimensional symmetric power basis function.
+ * A SBasisN<n> is a polynomial f of n variables (t0,...,tn-1),
+ * written in a particular form. Let si = ti(1-t_i). f is written as
+ *
+ * f = sum_p s^p a_{p}(t0,...,t_{n-1})
+ *
+ * where p=(p0,...,p_{n-1}) is a multi index (called MultiDegree<n> in the code)
+ * s^p = prod_i si^pi, and a_p is a LinearN<n>.
+ * Recall a LinearN<n> is sum over all choices xi = ti or (1-ti) of terms of form
+ * a * x0*...*x_{n-1}
+ *
+ * Caution: degrees are expressed as degrees of s=t*(1-t). The real degree
+ * (with respect to t) of the polynomial is twice that + 0 or 1 depending
+ * whether the relevant LinearN<n> coeff is constant or not.
+ *//*
+ *
+ * Authors:
+ * JF Barraud <jf.barraud@gmail.com>
+ * Nathan Hurst <njh@mail.csse.monash.edu.au>
+ * Michael Sloan <mgsloan@gmail.com>
+ *
+ * Copyright (C) 2006-2007 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef SEEN_SBASISN_H
+#define SEEN_SBASISN_H
+#include <vector>
+#include <cassert>
+#include <iostream>
+
+#include <2geom/orphan-code/linearN.h>
+#include <2geom/linear.h>//for conversion purpose
+#include <2geom/sbasis.h>//for conversion purpose
+#include <2geom/interval.h>
+#include <2geom/utils.h>
+#include <2geom/exception.h>
+
+
+namespace Geom{
+
+/** MultiDegree:
+ * \brief multi-degree (p0,...,p^{n-1}) of a s0^p0...s_{n-1}p^{n-1} monomial.
+ *
+ * a "Multi_deg" is a sequence p={p0,...,p_n-1} representing the monomial
+ * s^p = s_0^{p_0}*...*s_{n-1}^{p_{n-1}}.
+ * Caution: the degrees are expressed with respect to si! ( in SBasis code
+ * below, si = ti*(1-ti) ).
+ */
+
+template<unsigned n>
+class MultiDegree{
+public:
+ unsigned p[n];
+ MultiDegree(){
+ for (unsigned i = 0; i <n; i++) {
+ p[i]=0;
+ }
+ }
+ MultiDegree( unsigned const other_p[] ){
+ p = other_p;
+ }
+ MultiDegree(unsigned const idx, unsigned const sizes[]){
+ unsigned q = idx;
+ for (unsigned i = n-1; i >0; i--) {
+ div_t d = std::div(int(q), int(sizes[i]));
+ p[i] = d.rem;
+ q = d.quot;
+ }
+ p[0] = q;
+ }
+ unsigned operator[](const unsigned i) const {
+ assert(i < n); return p[i];
+ }
+ unsigned& operator[](const unsigned i) {
+ assert(i < n); return p[i];
+ }
+
+ unsigned asIdx(unsigned const sizes[]) const{
+ unsigned ret = p[0];
+ bool in_range = (p[0]<sizes[0]);
+ for (unsigned i = 1; i < n; i++) {
+ in_range = in_range && (p[i]<sizes[i]);
+ ret = ret*sizes[i] + p[i];
+ }
+ if (in_range) return ret;
+ //TODO: find a better warning than returning out of range idx!
+ ret =1;
+ for (unsigned i = 0; i < n; i++) {
+ ret *= sizes[i];
+ }
+ return ret;
+ }
+ bool stepUp(unsigned const sizes[], unsigned frozen_mask = 0){
+ unsigned i = 0;
+ while ( i < n && ( (1<<i) & frozen_mask ) ) i++;
+ while ( i <n && p[i] == sizes[i]-1 ) {
+ i++;
+ while (i<n && ( (1<<i) & frozen_mask ) ) i++;
+ }
+ if (i<n){
+ p[i]+=1;
+ for (unsigned j = 0; j < i; j++) {
+ if ( !( (1<<j) & frozen_mask ) ) p[j] = 0;
+ }
+ return true;
+ }else{
+ return false;
+ }
+ }
+ bool stepDown(unsigned const sizes[], unsigned frozen_mask = 0){
+ int i = n-1;
+ while (i>=0 && ( (1<<i) & frozen_mask ) ) i--;
+ while ( i >= 0 && p[i] == 0 ) {
+ i--;
+ while (i>=0 && ( (1<<i) & frozen_mask ) ) i--;
+ }
+ if ( i >= 0 ){
+ p[i]-=1;
+ for (unsigned j = i+1; j < n; j++) {
+ if ( !( (1<<j) & frozen_mask ) ) p[j] = sizes[j]-1;
+ }
+ return true;
+ }else{
+ return false;
+ }
+ }
+};
+
+/**
+ * Returns the maximal degree appearing in the two arguments for each variables.
+ */
+template <unsigned n>
+MultiDegree<n> max(MultiDegree<n> const &p, MultiDegree<n> const &q){
+ MultiDegree<n> ret;
+ for (unsigned i = 0; i <n; i++) {
+ ret.p[i] = (p[i]>q[i] ? p[i] : q[i]);
+ }
+ return ret;
+}
+
+template <unsigned n>
+MultiDegree<n> operator + (MultiDegree<n> const &p, MultiDegree<n> const &q){
+ MultiDegree<n> ret;
+ for (unsigned i = 0; i <n; i++) {
+ ret.p[i] = p[i] + q[i];
+ }
+ return ret;
+}
+template <unsigned n>
+MultiDegree<n> operator += (MultiDegree<n> const &p, MultiDegree<n> const &q){
+ for (unsigned i = 0; i <n; i++) {
+ p[i] += q[i];
+ }
+ return p;
+}
+
+/**
+ * \brief MultiDegree comparison.
+ * A MultiDegree \param p is smaller than another \param q
+ * if all it's smaller for all variables.
+ *
+ * In particular, p<=q and q<=p can both be false!
+ */
+template<unsigned n>
+bool operator<=(MultiDegree<n> const &p, MultiDegree<n> const &q){
+ for (unsigned i = 0; i <n; i++) {
+ if (p[i]>q[i]) return false;
+ }
+ return true;
+}
+
+
+/**
+ * \brief Polynomials of n variables, written in SBasis form.
+ * An SBasisN<n> f is internaly represented as a vector of LinearN<n>.
+ * It should be thought of as an n-dimensional vector: the coef of s0^p0...s_{n-1}p^{n-1}
+ * is soterd in f[p0,...,p_{n-1}]. The sizes of each dimension is stored in "sizes".
+ * Note: an empty SBasis is identically 0.
+ */
+template<unsigned n>
+class SBasisN : public std::vector<LinearN<n> >{
+public:
+ unsigned sizes[n];
+ SBasisN() {
+ for (unsigned i = 0; i < n; i++) {
+ sizes[i] = 0;
+ }
+ }
+ explicit SBasisN(double a) {
+ for (unsigned i = 0; i < n; i++) {
+ sizes[i] = 1;
+ }
+ this->push_back(LinearN<n>(a));
+ }
+ SBasisN(SBasisN<n> const & a) : std::vector<LinearN<n> >(a){
+ //TODO: efficient array copy??
+ for (unsigned i = 0; i < n; i++) {
+ sizes[i] = a.sizes[i];
+ }
+ }
+ SBasisN(LinearN<n> const & bo) {
+ for (unsigned i = 0; i < n; i++) {
+ sizes[i] = 1;
+ }
+ this->push_back(bo);
+ }
+ SBasisN(LinearN<n>* bo) {
+ for (unsigned i = 0; i < n; i++) {
+ sizes[i] = 1;
+ }
+ this->push_back(*bo);
+ }
+
+//----------------------------------------------
+//-- Degree/Sizing facilities ------------------
+//----------------------------------------------
+/**
+ * Internal recursive function used to compute partial degrees.
+ */
+ bool find_non_empty_level(unsigned var, MultiDegree<n> &fixed_degrees)const{
+ if (this->size()==0){
+ for (unsigned i = 0; i < n; i++) {
+ fixed_degrees[i] = 0;//FIXME this should be -infty!!
+ }
+ return false;
+ }
+ if ( !((*this)[fixed_degrees.asIdx(sizes)].isZero()) ) return true;
+
+ unsigned frozen = (1<<var);
+ if ( fixed_degrees.stepDown(sizes, frozen) ){
+ if ( find_non_empty_level(var, fixed_degrees) ) return true;
+ }
+ if ( fixed_degrees[var] > 0 ){
+ fixed_degrees[var] -= 1;
+ for (unsigned i = 0; i < n; i++) {
+ if (i!=var) fixed_degrees[i] = sizes[i]-1;
+ }
+ if (find_non_empty_level(var, fixed_degrees)) return true;
+ }
+ return false;//FIXME: this should return -infty in all variables!
+ }
+
+/**
+ * Returns the degree of an SBasisN<n> with respect to a given variable form its sizes.
+ * All terms are taken into account, even eventual trailing zeros.
+ * Note: degree is expressed with respect to s = t*(1-t), not t itself.
+ */
+ unsigned quick_degree(unsigned var) const{
+ return ( sizes[var] > 0 ? sizes[var]-1 : 0 );//this should be -infty.
+ }
+/**
+ * Computes the multi degree of the SBasis from it's sizes.
+ * All terms are taken into account, even eventual trailing zeros.
+ * Note: degrees are expressed with respect to s = t*(1-t), not t itself.
+ */
+ MultiDegree<n> quick_multi_degree() const{
+ MultiDegree<n> ret;
+ if (this->size()==0) return ret;//should be -infty for all vars.
+ for (unsigned i = 0; i < n; i++) {
+ assert( sizes[i]>0 );
+ ret.p[i] = sizes[i]-1;
+ }
+ return ret;
+ }
+/**
+ * Returns the degree of an SBasisN<n> with respect to a given variable.
+ * Trailing zeros are not taken into account.
+ * Note: degree is expressed with respect to s = t*(1-t), not t itself.
+ */
+ unsigned degree(unsigned var)const{
+ MultiDegree<n> degrees;
+ for(unsigned i = 0; i < n; i++) {
+ degrees[i] = sizes[i]-1;
+ }
+ if ( find_non_empty_level(var, degrees) ) return degrees[var];
+ else return 0;//should be -infty.
+ }
+/**
+ * Returns the *real* degree of an SBasisN<n> with respect to a given variable.
+ * Trailing zeros are not taken into account.
+ * Note: degree is expressed with respect to t itself, not s = t*(1-t).
+ * In particular: real_t_degree() = 2*degree() + 0 or 1.
+ */
+ unsigned real_t_degree(unsigned var)const{
+ unsigned deg = 0;
+ bool even = true;
+ bool notfound = true;
+ unsigned frozen = (1<<var);
+ MultiDegree<n> degrees;
+ for(unsigned i = 0; i < n; i++) {
+ degrees[i] = sizes[i]-1;
+ }
+ while( notfound ){
+ if ( find_non_empty_level(var, degrees) && degrees[var]>= deg ){
+ deg = degrees[var];
+ even = (*this)[degrees.asIdx(sizes)].isConstant(var);
+ }
+ notfound = even && degrees.stepDown(sizes, frozen);
+ }
+ return 2*deg + ( even ? 0 : 1 );
+ }
+/**
+ * Returns the *real* degrees of an SBasisN<n>.
+ * Trailing zeros are not taken into account.
+ * Note: degree is expressed with respect to t itself, not s = t*(1-t).
+ * In particular: real_t_degree() = 2*degree() + 0 or 1.
+ */
+ MultiDegree<n> real_t_degrees()const{
+ MultiDegree<n>res;
+ for(unsigned i = 0; i < n; i++) {
+ res[i] = real_t_degree(i);
+ }
+ return res;
+ }
+/**
+ * Computes the multi degree of the SBasis.
+ * Trailing zeros are not taken into account.
+ * Note: degree is expressed with respect to s = t*(1-t), not t itself.
+ */
+ MultiDegree<n> multi_degree() const{
+ MultiDegree<n> ret;
+ if (this->size()==0) return ret;//should be -infty for all vars.
+ for (unsigned i = 0; i < n; i++) {
+ ret[i] = this->degree(i);
+ }
+ return ret;
+ }
+/**
+ * Returns the highest degree over all variables.
+ * Note: degree is expressed with respect to s = t*(1-t), not t itself.
+ */
+ unsigned max_degree() const {
+ if (this->size()==0) return 0;//should be -infty!
+ unsigned d=0;
+ for (unsigned i = 0; i < n; i++) {
+ assert( sizes[i]>0 );
+ if (d < sizes[i]-1) d = sizes[i]-1;
+ }
+ return d;
+ }
+
+/**
+ * Resize an SBasisN<n> to match new sizes.
+ *
+ * Caution: if a new size is smaller, the corresponding coefficients are discarded.
+ */
+ void multi_resize(unsigned new_sizes[], LinearN<n> def_value = LinearN<n>(0.)){
+ SBasisN<n> result;
+ bool nothing_todo = true;
+ unsigned tot_size = 1;
+ for(unsigned i = 0; i < n; i++) {
+ nothing_todo = nothing_todo && (sizes[i] == new_sizes[i]);
+ result.sizes[i] = new_sizes[i];
+ tot_size *= new_sizes[i];
+ }
+ if (nothing_todo) return;
+ result.resize(tot_size, def_value);
+ for(unsigned i = 0; i < tot_size; i++) {
+ MultiDegree<n> d( i, result.sizes );
+ unsigned j = d.asIdx(sizes);
+ if ( j < this->size() ){
+ result[i] = (*this)[j];
+ }
+ }
+ *this = result;
+ }
+
+ //remove extra zeros
+ void normalize() {
+ MultiDegree<n> max_p = multi_degree();
+ unsigned new_sizes[n];
+ for (unsigned i=0; i<n; i++){
+ new_sizes[i] = max_p[i]+1;
+ }
+ multi_resize(new_sizes);
+ }
+
+//-----------------------------
+//-- Misc. --------------------
+//-----------------------------
+
+/**
+ * Returns the number of variables this function takes as input: n.
+ */
+ unsigned input_dim(){return n;};
+
+ //IMPL: FragmentConcept
+ typedef double output_type;
+
+ inline bool isZero() const {
+ if(this->size()==0) return true;
+ for(unsigned i = 0; i < this->size(); i++) {
+ if(!(*this)[i].isZero()) return false;
+ }
+ return true;
+ }
+ inline bool isConstant() const {
+ if (this->size()==0) return true;
+ if(!(*this)[0].isConstant()) return false;
+ for (unsigned i = 1; i < this->size(); i++) {
+ if(!(*this)[i].isZero()) return false;
+ }
+ return true;
+ }
+
+ bool isFinite() const{
+ for (unsigned i = 0; i < this->size(); i++) {
+ if(!(*this)[i].isFinite()) return false;
+ }
+ return true;
+ }
+
+
+//------------------------------------------
+//-- Evaluation methods --------------------
+//------------------------------------------
+/**
+ * Returns the value of the SBasis at a given corner of [0,1]^n.
+ * \param k describes the corner: if i-th bit is 0, ti=0, otherwise ti=1.
+ */
+ inline double atCorner(unsigned k) const {
+ if(this->size()==0) return 0.;
+ return (*this)[0].atCorner(k);
+ }
+/**
+ * Returns the value of the SBasis at a given corner of [0,1]^n.
+ * \param t[n] describes the corner: the values should be 0's and 1's.
+ */
+ inline double atCorner(double t[]) const {
+ if(this->size()==0) return 0.;
+ return (*this)[0].atCorner(t);
+ }
+/**
+ * Returns a "slice" of the array.
+ * Returns an SBasis containing all the coeff of (s-)degree \param deg in variable \param var
+ */
+ //TODO: move by bigger blocks (?) but they are broken into pieces in general...
+ SBasisN<n> slice(unsigned const var, unsigned const deg) const{
+ if (deg >= sizes[var] ) return SBasisN<n>();
+ SBasisN<n> res;
+ unsigned tot_size = 1;
+ for (unsigned i = 0; i < n; i++) {
+ res.sizes[i] = (i==var ? 1 : sizes[i]);
+ tot_size *= res.sizes[i];
+ }
+ res.resize( tot_size, LinearN<n>(0.));
+ for (unsigned i = 0; i < tot_size; i++) {
+ MultiDegree<n> d(i,res.sizes);
+ d.p[var] = deg;
+ res[i] = (*this)[d.asIdx(sizes)];
+ }
+ return res;
+ }
+/**
+ * Returns a the SBasisN<n-1> obtained by setting variable \param var to 0.
+ */
+ inline SBasisN<n-1> at0(unsigned var=0, unsigned deg=0) const {
+ SBasisN<n> sl = slice(var,deg);
+ SBasisN<n-1> res;
+ res.reserve(sl.size());
+ for (unsigned i = 0; i < n-1; i++) {
+ res.sizes[i] = sizes[ ( i<var ? i : i+1 ) ];
+ }
+ for (unsigned i = 0; i < sl.size(); i++) {
+ res.push_back( sl[i].at0(var) );
+ }
+ return res;
+ }
+/**
+ * Returns a the SBasisN<n-1> obtained by setting variable \param var to 1.
+ */
+ inline SBasisN<n-1> at1(unsigned var=0, unsigned deg=0) const {
+ SBasisN<n> sl = slice(var,deg);
+ SBasisN<n-1> res;
+ res.reserve(sl.size());
+ for (unsigned i = 0; i < n-1; i++) {
+ res.sizes[i] = sizes[ ( i<var ? i : i+1 ) ];
+ }
+ for (unsigned i = 0; i < sl.size(); i++) {
+ res.push_back( sl[i].at1(var) );
+ }
+ return res;
+ }
+/**
+ * Returns a the SBasisN<n-1> obtained by setting variable \param var to \param t.
+ */
+ inline SBasisN<n-1> partialEval(double t, unsigned var=0 ) const {
+ SBasisN<n> sl;
+ double s = t*(1-t);
+ double si = 1;
+ for (unsigned i = 0; i <sizes[var]; i++) {
+ sl = sl + slice(var, i)*si;
+ si *= s;
+ }
+ SBasisN<n-1> res;
+ res.resize(sl.size(), LinearN<n-1>(0.));
+ for (unsigned i = 0; i < n-1; i++) {
+ res.sizes[i] = sizes[ ( i<var ? i : i+1 ) ];
+ }
+ for (unsigned i = 0; i < sl.size(); i++) {
+ res[i] = sl[i].partialEval(t,var);
+ }
+ return res;
+ }
+
+/**
+ * \brief Internal recursive function.
+ * Replace each variable by it's value in the 's=t*(1-t)' factor
+ * but not in the LinearN<n> coeffs. Then sum up all coefficients.
+ * \param t[n]: values of the variables.
+ */
+ LinearN<n> sumCoefs( double t[], unsigned const k, unsigned const idx) const{
+ LinearN<n> a;
+ if (k == n){
+ a = (*this)[idx];
+ return (*this)[idx];
+ }
+ double s = t[k]*(1-t[k]);
+ double si=1;
+ for (unsigned i=0; i<sizes[k]; i++){
+ a += sumCoefs(t,k+1,idx*sizes[k]+i)*si;;
+ si *= s;
+ }
+ return a;
+ }
+/**
+ * Evaluate at given n-dimensional point.
+ * \param t[n]: values of the variables.
+ */
+ double valueAt(double t[]) const {
+ LinearN<n> a = sumCoefs(t,0,0);
+ return a.valueAt(t);
+ }
+
+ double operator()(double t[]) const {
+ return valueAt(t);
+ }
+
+ //double valueAndDerivative(double t, double &der) const;
+ //std::vector<double> valueAndDerivatives(double t, unsigned n) const;
+ //SBasisN toSBasisN() const { return SBasisN(*this); }
+ //double tailError(unsigned tail) const;
+
+
+//--------------------------------------------------
+//-- Coeff. manipulation ---------------------------
+//--------------------------------------------------
+
+/**
+ * Accessing the SBasisN<n> coefficients.
+ */
+ LinearN<n> operator[](unsigned i) const {
+ assert(i < this->size());
+ return std::vector<LinearN<n> >::operator[](i);
+ }
+ LinearN<n> operator[](MultiDegree<n> const &p) const {
+ unsigned i = p.asIdx(sizes);
+ assert(i < this->size());
+ return std::vector<LinearN<n> >::operator[](i);
+ }
+
+//MUTATOR PRISON
+ LinearN<n>& operator[](unsigned i) { return this->at(i); }
+// LinearN<n>& operator[](MultiDegree const &p) {
+// unsigned i = p.asIdx(sizes);
+// return this->at(i);
+// }
+
+ void appendCoef(const SBasisN<n-1> &a, const SBasisN<n-1> &b, unsigned var=0){
+ unsigned new_sizes[n];
+ MultiDegree<n-1> deg_a = a.multi_degree(), deg_b = b.multi_degree();
+ MultiDegree<n-1> dcoef = max( deg_a, deg_b );
+ for (unsigned i=0; i<n; i++){
+ if ( i == var ){
+ new_sizes[var] = sizes[var] + 1;
+ }else{
+ unsigned coef_size = dcoef[(i<var?i:i-1)] + 1;
+ new_sizes[i] = ( sizes[i]>coef_size ? sizes[i] : coef_size );
+ }
+ }
+ multi_resize(new_sizes);
+
+ MultiDegree<n> d;
+ d[var] = sizes[var]-1;
+ unsigned frozen_mask = (1<<var);
+ do{
+ for (unsigned i=0; i<n-1; i++){
+ dcoef.p[i] = d.p[ ( i<var ? i : i+1) ];
+ }
+ LinearN<n-1> a_d,b_d;
+ unsigned ia = dcoef.asIdx(a.sizes);
+ if ( ia < a.size() ) a_d = a[ia];
+ unsigned ib = dcoef.asIdx(b.sizes);
+ if ( ib < b.size() ) b_d = b[ib];
+ (*this)[d.asIdx(sizes)] = LinearN<n>(a_d,b_d);
+ }while (d.stepUp(sizes,frozen_mask));
+ }
+
+//private:
+ //void derive(); // in place version
+};
+
+//SBasisN<0> is a double. Specialize it out.
+template<>
+class SBasisN<0>{
+public:
+ double d;
+ SBasisN () {}
+ SBasisN(double d) :d(d) {}
+ operator double() const { return d; }
+};
+
+
+//SBasisN<1> are usual SBasis. Allow conversion.
+SBasis toSBasis(SBasisN<1> f){
+ SBasis res(f.size(), Linear());
+ for (unsigned i = 0; i < f.size(); i++) {
+ res[i] = toLinear(f[i]);
+ }
+ return res;
+}
+
+//TODO: figure out how to stick this in linear, while not adding an sbasis dep
+template<unsigned n>
+inline SBasisN<n> LinearN<n>::toSBasisN() const { return SBasisN<n>(*this); }
+
+
+
+
+//implemented in sbasis-roots.cpp
+//OptInterval bounds_exact(SBasisN const &a);
+//OptInterval bounds_fast(SBasisN const &a, int order = 0);
+//OptInterval bounds_local(SBasisN const &a, const OptInterval &t, int order = 0);
+
+/** Returns a function which reverses the domain of a.
+ \param a sbasis function
+
+useful for reversing a parameteric curve.
+*/
+//template<unsigned n>
+//inline SBasisN<n> reverse(SBasisN<n> const &a);
+
+//IMPL: ScalableConcept
+template<unsigned n>
+inline SBasisN<n> operator-(const SBasisN<n>& p) {
+ if(p.isZero()) return SBasisN<n>();
+ SBasisN<n> result;
+ for(unsigned i = 0; i < n; i++) {
+ result.sizes[i] = p.sizes[i];
+ }
+ result.reserve(p.size());
+ for(unsigned i = 0; i < p.size(); i++) {
+ result.push_back(-p[i]);
+ }
+ return result;
+}
+template<unsigned n>
+SBasisN<n> operator*(SBasisN<n> const &a, double c){
+ if(a.isZero()) return SBasisN<n>();
+ SBasisN<n> result;
+ for(unsigned i = 0; i < n; i++) {
+ result.sizes[i] = a.sizes[i];
+ }
+ result.reserve(a.size());
+ for(unsigned i = 0; i < a.size(); i++) {
+ result.push_back(a[i] * c);
+ }
+ return result;
+}
+template<unsigned n>
+inline SBasisN<n> operator*(double k, SBasisN<n> const &a) { return a*k; }
+template<unsigned n>
+inline SBasisN<n> operator/(SBasisN<n> const &a, double k) { return a*(1./k); }
+template<unsigned n>
+SBasisN<n>& operator*=(SBasisN<n>& a, double c){
+ for(unsigned i = 0; i < a.size(); i++) a[i] *= c;
+ return a;
+}
+template<unsigned n>
+inline SBasisN<n>& operator/=(SBasisN<n>& a, double b) { return (a*=(1./b)); }
+
+//IMPL: AddableConcept
+template<unsigned n>
+SBasisN<n> operator + (const SBasisN<n>& a, const SBasisN<n>& b){
+ if( a.isZero() ) return b;
+ if( b.isZero() ) return a;
+ SBasisN<n> result;
+ MultiDegree<n> deg = max(a.quick_multi_degree(),b.quick_multi_degree());
+ unsigned max_size = 1;
+ for(unsigned i = 0; i < n; i++) {
+ result.sizes[i] = deg[i]+1;
+ max_size *= result.sizes[i];
+ }
+ result.resize( max_size, LinearN<n>(0.) );
+ for(unsigned i = 0; i < result.size(); i++) {
+ MultiDegree<n> p(i,result.sizes);
+ unsigned ia = p.asIdx(a.sizes);
+ unsigned ib = p.asIdx(b.sizes);
+ if (ia<a.size()) {
+ result[i] += a[ia];
+ }
+ if (ib<b.size()) {
+ result[i] += b[ib];
+ }
+ }
+ return result;
+}
+template<unsigned n>
+SBasisN<n> operator-(const SBasisN<n>& a, const SBasisN<n>& b){return a+(-b);}
+template<unsigned n>
+SBasisN<n>& operator+=(SBasisN<n>& a, const SBasisN<n>& b){
+ if(b.isZero()) return a;
+ a = a + b;
+ return a;
+}
+template<unsigned n>
+SBasisN<n>& operator-=(SBasisN<n>& a, const SBasisN<n>& b){
+ a += -b;
+ return a;
+}
+
+//TODO: remove?
+template<unsigned n>
+inline SBasisN<n> operator+(const SBasisN<n> & a, LinearN<n> const & b) {
+ if(b.isZero()) return a;
+ if(a.isZero()) return b;
+ SBasisN<n> result(a);
+ result[0] += b;
+ return result;
+}
+template<unsigned n>
+
+inline SBasisN<n> operator-(const SBasisN<n> & a, LinearN<n> const & b) {
+ if(b.isZero()) return a;
+ if(a.isZero()) return -b;
+ SBasisN<n> result(a);
+ result[0] -= b;
+ return result;
+}
+template<unsigned n>
+inline SBasisN<n>& operator+=(SBasisN<n>& a, const LinearN<n>& b) {
+ if(a.size()==0)
+ a.push_back(b);
+ else
+ a[0] += b;
+ return a;
+}
+template<unsigned n>
+inline SBasisN<n>& operator-=(SBasisN<n>& a, const LinearN<n>& b) {
+ if(a.size()==0)
+ a.push_back(-b);
+ else
+ a[0] -= b;
+ return a;
+}
+
+//IMPL: OffsetableConcept
+template<unsigned n>
+inline SBasisN<n> operator+(const SBasisN<n> & a, double b) {
+ if(a.isZero()) return LinearN<n>(b);
+ SBasisN<n> result(a);
+ result[0] += b;
+ return result;
+}
+template<unsigned n>
+inline SBasisN<n> operator-(const SBasisN<n> & a, double b) {
+ if(a.isZero()) return LinearN<n>(-b);
+ SBasisN<n> result(a);
+ result[0] -= b;
+ return result;
+}
+template<unsigned n>
+inline SBasisN<n>& operator+=(SBasisN<n>& a, double b) {
+ if(a.size()==0)
+ a.push_back(LinearN<n>(b));
+ else
+ a[0] += b;
+ return a;
+}
+template<unsigned n>
+inline SBasisN<n>& operator-=(SBasisN<n>& a, double b) {
+ if(a.size()==0)
+ a.push_back(LinearN<n>(-b));
+ else
+ a[0] -= b;
+ return a;
+}
+
+template<unsigned n>
+SBasisN<n> shift(SBasisN<n> const &a, MultiDegree<n> sh){
+ SBasisN<n> result;
+ MultiDegree<n> deg = a.quick_multi_degree() + sh;
+ for(unsigned i = 0; i < n; i++) {
+ result.sizes[i] = deg[i]+1;
+ }
+ unsigned max_size = deg.asIdx(result.sizes);
+ result.resize( max_size, LinearN<n>(0.) );
+ for(unsigned i = 0; i < a.size(); i++) {
+ MultiDegree<n> p(i,a.sizes);
+ p+=sh;
+ result[p.asIdx(result.sizes)]=a[i];
+ }
+ return result;
+}
+template<unsigned n>
+SBasisN<n> shift(LinearN<n> const &a, MultiDegree<n> sh){
+ SBasisN<n> result;
+ for(unsigned i = 0; i < n; i++) {
+ result.sizes[i] = sh[i]+1;
+ }
+ unsigned max_size = sh.asIdx(result.sizes);
+ result.resize( max_size, LinearN<n>(0.) );
+ result[max_size-1]=a;
+ return result;
+}
+//shift only in one variable
+template<unsigned n>
+SBasisN<n> shift(LinearN<n> const &a, unsigned sh, unsigned var){
+ assert( var < n );
+ SBasisN<n> result;
+ for(unsigned i = 0; i < n; i++) {
+ result.sizes[i] = 1;
+ }
+ result.sizes[var] = sh+1;
+ result.resize( sh+1, LinearN<n>(0.) );
+ result[sh]=a;
+ return result;
+}
+
+//truncate only in first variable
+template<unsigned n>
+inline SBasisN<n> truncate(SBasisN<n> const &a, unsigned first_size) {
+ if ( first_size <= a.sizes[0] ) return a;
+ SBasisN<n> c;
+ for (unsigned i = 0; i < n; i++) {
+ c.sizes[i] = a.sizes[i];
+ }
+ c.sizes[0] = first_size;
+ unsigned tot_size = 1;
+ for(unsigned i = 0; i < n; i++) {
+ tot_size*=c.sizes[i];
+ }
+ c.insert(c.begin(), a.begin(), a.begin() + tot_size);
+ return c;
+}
+
+template<unsigned n>
+SBasisN<n> multiply(SBasisN<n> const &a, SBasisN<n> const &b){
+ SBasisN<n> c;
+ MultiDegree<n> d;
+ MultiDegree<n> t_deg = a.real_t_degrees() + b.real_t_degrees();
+ for(unsigned i = 0; i < n; i++) {
+ d[i] = ( t_deg[i]%2 == 0 ? t_deg[i]/2 : (t_deg[i]-1)/2 ) ;
+ }
+ unsigned new_sizes[n], tot_size = 1;
+ for(unsigned i = 0; i < n; i++) {
+ //c.sizes[i] = d[i] + 1+1;//product of linears might give 1 more s in each dir!!
+ new_sizes[i] = d[i] + 1;
+ tot_size*=new_sizes[i];
+ }
+ c.resize( tot_size, LinearN<n>(0.) );
+ for(unsigned i = 0; i < n; i++) {
+ c.sizes[i] = new_sizes[i];
+ }
+
+ for(unsigned ai = 0; ai < a.size(); ai++) {
+ for(unsigned bj = 0; bj < b.size(); bj++) {
+ MultiDegree<n> di( ai, a.sizes );
+ MultiDegree<n> dj( bj, b.sizes );
+ //compute a[ai]*b[bj]:
+ for(unsigned p = 0; p < (1<<n); p++) {
+ for(unsigned q = 0; q < (1<<n); q++) {
+
+ //compute a[ai][p]*b[bj][q]:
+ unsigned m = p^q;//m has ones for factors s, 0 for (t-s) or ((1-t)-s).
+ for(unsigned r = 0; r < (1<<n); r++) {
+ if (!(r&m)) {// a 1 in r means take t (or (1-t)), otherwise take -s.
+ int sign = 1;
+ MultiDegree<n> dr;
+ unsigned t0 = 0, t1 = 0;
+ for (unsigned var = 0; var < n; var++) {
+ //if var is in mask m, no choice, take s
+ if ( m & (1<<var) ){
+ dr.p[var] = 1;
+ }//if var is in mask r, take t or (1-t)
+ else if ( r & (1<<var) ){
+ dr.p[var] = 0;
+ if ( p&(1<<var) ) {
+ t0 = t0 | (1<<var);
+ }else{
+ t1 = t1 | (1<<var);
+ }
+ }//ohterwise take -s
+ else{
+ dr.p[var] = 1;
+ sign *= -1;
+ }
+ }
+ unsigned idx = (di+dj+dr).asIdx(c.sizes);
+ if (idx < c.size()){
+ for(unsigned s = 0; s < (1<<n); s++) {
+ if ( (t0 & ~s) || (t1 & s) ){
+ c[idx][s] += 0;
+ }else{
+ c[idx][s] += sign * a[ai][p] * b[bj][q];
+ }
+ }
+ }
+ }
+ }//r loop: all choices have been expanded in the product a[ai][p]*b[bj][q]
+ }//q loop
+ }//p loop: all products a[ai][p]*b[bj][q] have been computed.
+ }//bj loop
+ }//ai loop: all a[ai]b[bj] have been computed.
+
+ //TODO: normalize c, or even better, compute with the right size from scratch
+ return c;
+}
+
+
+template<unsigned n>
+inline SBasisN<n> operator*(SBasisN<n> const & a, SBasisN<n> const & b) {
+ return multiply(a, b);
+}
+
+template<unsigned n>
+inline SBasisN<n>& operator*=(SBasisN<n>& a, SBasisN<n> const & b) {
+ a = multiply(a, b);
+ return a;
+}
+
+template<unsigned m,unsigned n>
+SBasisN<m> compose(LinearN<n> const &f, std::vector<SBasisN<m> > const &t, unsigned fixed=0, unsigned flags=0 ){
+ assert (t.size() == n );
+ if (fixed == n) {
+ return SBasisN<m>(1.) * f[flags];
+ }else{
+ SBasisN<m> a0 = compose(f, t, fixed+1, flags);
+ SBasisN<m> a1 = compose(f, t, fixed+1, flags|(1<<fixed));
+ return (-t[fixed]+1) * a0 + t[fixed] * a1;
+ }
+}
+
+template<unsigned m,unsigned n>
+SBasisN<m> compose(SBasisN<n> const &f, std::vector<SBasisN<m> > const &t, unsigned const k=0, unsigned const idx = 0){
+ assert (t.size() == n );
+ if (k == n){
+ return compose( f[idx], t);
+ }
+ SBasisN<m> a;
+ SBasisN<m> s = multiply( t[k], (-t[k]+1.) );
+ SBasisN<m> si= SBasisN<m>(1.);
+ for (unsigned i=0; i<f.sizes[k]; i++){
+ a += compose(f, t,k+1,idx*f.sizes[k]+i)*si;;
+ si *= s;
+ }
+ return a;
+}
+
+template <unsigned n>
+inline std::ostream &operator<< (std::ostream &out_file, const MultiDegree<n> & d) {
+ out_file << "s^{";
+ for(unsigned i = 0; i < n; i++) {
+ out_file << d[i] << (i == n-1 ? "}" : ",");
+ }
+ return out_file;
+}
+template <unsigned n>
+inline std::ostream &operator<< (std::ostream &out_file, const SBasisN<n> & p) {
+ for(unsigned i = 0; i < p.size(); i++) {
+ MultiDegree<n> d(i, p.sizes);
+ out_file << d << " " << p[i] << " + ";
+ }
+ return out_file;
+}
+
+
+//--------------------------------------------------
+//--------------------------------------------------
+//--------------------------------------------------
+//--------------------------------------------------
+//--------------------------------------------------
+
+#if 0
+
+
+// This performs a multiply and accumulate operation in about the same time as multiply. return a*b + c
+template<unsigned n>
+SBasisN<n> multiply_add(SBasisN<n> const &a, SBasisN<n> const &b, SBasisN<n> c);
+
+template<unsigned n>
+SBasisN<n> integral(SBasisN<n> const &c);
+template<unsigned n>
+SBasisN<n> derivative(SBasisN<n> const &a);
+
+template<unsigned n>
+SBasisN<n> sqrt(SBasisN<n> const &a, int k);
+
+// return a kth order approx to 1/a)
+template<unsigned n>
+SBasisN<n> reciprocal(LinearN<n> const &a, int k);
+template<unsigned n>
+SBasisN<n> divide(SBasisN<n> const &a, SBasisN<n> const &b, int k);
+
+
+/** Returns the degree of the first non zero coefficient.
+ \param a sbasis function
+ \param tol largest abs val considered 0
+ \returns first non zero coefficient
+*/
+template<unsigned n>
+inline unsigned
+valuation(SBasisN<n> const &a, double tol=0){
+ unsigned val=0;
+ while( val<a.size() &&
+ fabs(a[val][0])<tol &&
+ fabs(a[val][1])<tol )
+ val++;
+ return val;
+}
+
+// a(b(t))
+template<unsigned n>
+SBasisN<n> compose(SBasisN<n> const &a, SBasisN<n> const &b);
+template<unsigned n>
+SBasisN<n> compose(SBasisN<n> const &a, SBasisN<n> const &b, unsigned k);
+template<unsigned n>
+SBasisN<n> inverse(SBasisN<n> a, int k);
+//compose_inverse(f,g)=compose(f,inverse(g)), but is numerically more stable in some good cases...
+//TODO: requires g(0)=0 & g(1)=1 atm. generalization should be obvious.
+template<unsigned n>
+SBasisN<n> compose_inverse(SBasisN<n> const &f, SBasisN<n> const &g, unsigned order=2, double tol=1e-3);
+
+/** Returns the sbasis on domain [0,1] that was t on [from, to]
+ \param a sbasis function
+ \param from,to interval
+ \returns sbasis
+
+*/
+template<unsigned n>
+inline SBasisN<n> portion(const SBasisN<n> &t, double from, double to) { return compose(t, LinearN<n>(from, to)); }
+
+// compute f(g)
+template<unsigned n>
+inline SBasisN<n>
+SBasisN<n>::operator()(SBasisN<n> const & g) const {
+ return compose(*this, g);
+}
+
+template<unsigned n>
+inline std::ostream &operator<< (std::ostream &out_file, const LinearN<n> &bo) {
+ out_file << "{" << bo[0] << ", " << bo[1] << "}";
+ return out_file;
+}
+
+template<unsigned n>
+inline std::ostream &operator<< (std::ostream &out_file, const SBasisN<n> & p) {
+ for(unsigned i = 0; i < p.size(); i++) {
+ out_file << p[i] << "s^" << i << " + ";
+ }
+ return out_file;
+}
+
+// These are deprecated, use sbasis-math.h versions if possible
+template<unsigned n>
+SBasisN<n> sin(LinearN<n> bo, int k);
+template<unsigned n>
+SBasisN<n> cos(LinearN<n> bo, int k);
+
+template<unsigned n>
+std::vector<double> roots(SBasisN<n> const & s);
+template<unsigned n>
+std::vector<std::vector<double> > multi_roots(SBasisN<n> const &f,
+ std::vector<double> const &levels,
+ double htol=1e-7,
+ double vtol=1e-7,
+ double a=0,
+ double b=1);
+
+#endif
+//--------------------------------------------------
+//--------------------------------------------------
+//--------------------------------------------------
+//--------------------------------------------------
+//--------------------------------------------------
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+#endif
diff --git a/src/3rdparty/2geom/include/2geom/parallelogram.h b/src/3rdparty/2geom/include/2geom/parallelogram.h
new file mode 100644
index 0000000..0c7134f
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/parallelogram.h
@@ -0,0 +1,83 @@
+/*
+ * Authors:
+ * Thomas Holder
+ * Sergei Izmailov
+ *
+ * Copyright 2020 Authors
+ *
+ * SPDX-License-Identifier: LGPL-2.1 or MPL-1.1
+ */
+
+#ifndef LIB2GEOM_SEEN_PARALLELOGRAM_H
+#define LIB2GEOM_SEEN_PARALLELOGRAM_H
+
+#include <2geom/affine.h>
+#include <2geom/rect.h>
+
+namespace Geom {
+
+/**
+ * Paralellogram, representing a linear transformation of a rectangle.
+ *
+ * Implements efficient "contains" and "intersects" operations.
+ */
+class Parallelogram {
+ Affine m_affine;
+
+ /// Transformed unit rectangle
+ Parallelogram(Affine const &affine)
+ : m_affine(affine)
+ {
+ }
+
+ public:
+ explicit Parallelogram(Rect const &rect)
+ : m_affine(rect.width(), 0, 0, rect.height(), rect.left(), rect.top())
+ {
+ }
+
+ Point corner(unsigned i) const;
+
+ Point midpoint() const { return Point(0.5, 0.5) * m_affine; }
+
+ /// Area (non-negative)
+ Coord area() const { return m_affine.descrim2(); }
+
+ /// Axis-aligned bounding box
+ Rect bounds() const;
+
+ bool intersects(Parallelogram const &) const;
+ bool intersects(Rect const &rect) const { return intersects(Parallelogram(rect)); }
+
+ bool contains(Point const &) const;
+ bool contains(Parallelogram const &) const;
+ bool contains(Rect const &rect) const { return contains(Parallelogram(rect)); }
+
+ /// Returns shorter side length
+ Coord minExtent() const;
+
+ /// Returns longer side length
+ Coord maxExtent() const;
+
+ /// Return a new transformed parallelogram
+ Parallelogram operator*(Affine const &affine) const { return m_affine * affine; }
+ Parallelogram &operator*=(Affine const &affine) { m_affine *= affine; return *this; }
+
+ /// True if this parallelogram does not have right angles
+ bool isSheared(Coord eps = EPSILON) const;
+};
+
+} // namespace Geom
+
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/path-intersection.h b/src/3rdparty/2geom/include/2geom/path-intersection.h
new file mode 100644
index 0000000..7d7cec9
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/path-intersection.h
@@ -0,0 +1,118 @@
+/**
+ * \file
+ * \brief Path intersection
+ *//*
+ * Authors:
+ * ? <?@?.?>
+ *
+ * Copyright ?-? authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_PATH_INTERSECTION_H
+#define LIB2GEOM_SEEN_PATH_INTERSECTION_H
+
+#include <2geom/crossing.h>
+#include <2geom/path.h>
+#include <2geom/sweep-bounds.h>
+
+namespace Geom {
+
+int winding(Path const &path, Point const &p);
+bool path_direction(Path const &p);
+
+inline bool contains(Path const & p, Point const &i, bool evenodd = true) {
+ return (evenodd ? winding(p, i) % 2 : winding(p, i)) != 0;
+}
+
+template<typename T>
+Crossings curve_sweep(Path const &a, Path const &b) {
+ T t;
+ Crossings ret;
+ std::vector<Rect> bounds_a = bounds(a), bounds_b = bounds(b);
+ std::vector<std::vector<unsigned> > ixs = sweep_bounds(bounds_a, bounds_b);
+ for(unsigned i = 0; i < a.size(); i++) {
+ for(std::vector<unsigned>::iterator jp = ixs[i].begin(); jp != ixs[i].end(); ++jp) {
+ Crossings cc = t.crossings(a[i], b[*jp]);
+ offset_crossings(cc, i, *jp);
+ ret.insert(ret.end(), cc.begin(), cc.end());
+ }
+ }
+ return ret;
+}
+
+Crossings pair_intersect(Curve const & A, Interval const &Ad,
+ Curve const & B, Interval const &Bd);
+Crossings mono_intersect(Curve const & A, Interval const &Ad,
+ Curve const & B, Interval const &Bd);
+
+struct SimpleCrosser : public Crosser<Path> {
+ Crossings crossings(Curve const &a, Curve const &b);
+ Crossings crossings(Path const &a, Path const &b) override { return curve_sweep<SimpleCrosser>(a, b); }
+ CrossingSet crossings(PathVector const &a, PathVector const &b) override { return Crosser<Path>::crossings(a, b); }
+};
+
+struct MonoCrosser : public Crosser<Path> {
+ Crossings crossings(Path const &a, Path const &b) override { return crossings(PathVector(a), PathVector(b))[0]; }
+ CrossingSet crossings(PathVector const &a, PathVector const &b) override;
+};
+
+typedef SimpleCrosser DefaultCrosser;
+
+std::vector<double> path_mono_splits(Path const &p);
+
+CrossingSet crossings_among(PathVector const & p);
+Crossings self_crossings(Path const & a);
+
+inline Crossings crossings(Curve const & a, Curve const & b) {
+ DefaultCrosser c = DefaultCrosser();
+ return c.crossings(a, b);
+}
+
+inline Crossings crossings(Path const & a, Path const & b) {
+ DefaultCrosser c = DefaultCrosser();
+ return c.crossings(a, b);
+}
+
+inline CrossingSet crossings(PathVector const & a, PathVector const & b) {
+ DefaultCrosser c = DefaultCrosser();
+ return c.crossings(a, b);
+}
+
+}
+
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/path-sink.h b/src/3rdparty/2geom/include/2geom/path-sink.h
new file mode 100644
index 0000000..35bd1cd
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/path-sink.h
@@ -0,0 +1,253 @@
+/**
+ * \file
+ * \brief callback interface for SVG path data
+ *//*
+ * Copyright 2007 MenTaLguY <mental@rydia.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_PATH_SINK_H
+#define LIB2GEOM_SEEN_PATH_SINK_H
+
+#include <2geom/forward.h>
+#include <2geom/pathvector.h>
+#include <2geom/curves.h>
+#include <iterator>
+
+namespace Geom {
+
+
+/** @brief Callback interface for processing path data.
+ *
+ * PathSink provides an interface that allows one to easily write
+ * code which processes path data, for instance when converting
+ * between path formats used by different graphics libraries.
+ * It is also useful for writing algorithms which must do something
+ * for each curve in the path.
+ *
+ * To store a path in a new format, implement the virtual methods
+ * for segments in a derived class and call feed().
+ *
+ * @ingroup Paths
+ */
+class PathSink {
+public:
+ /** @brief Move to a different point without creating a segment.
+ * Usually starts a new subpath. */
+ virtual void moveTo(Point const &p) = 0;
+ /// Output a line segment.
+ virtual void lineTo(Point const &p) = 0;
+ /// Output a quadratic Bezier segment.
+ virtual void curveTo(Point const &c0, Point const &c1, Point const &p) = 0;
+ /// Output a cubic Bezier segment.
+ virtual void quadTo(Point const &c, Point const &p) = 0;
+ /** @brief Output an elliptical arc segment.
+ * See the EllipticalArc class for the documentation of parameters. */
+ virtual void arcTo(Coord rx, Coord ry, Coord angle,
+ bool large_arc, bool sweep, Point const &p) = 0;
+
+ /// Close the current path with a line segment.
+ virtual void closePath() = 0;
+ /** @brief Flush any internal state of the generator.
+ * This call should implicitly finish the current subpath.
+ * Calling this method should be idempotent, because the default
+ * implementations of path() and pathvector() will call it
+ * multiple times in a row. */
+ virtual void flush() = 0;
+ // Get the current point, e.g. where the initial point of the next segment will be.
+ //virtual Point currentPoint() const = 0;
+
+ /** @brief Undo the last segment.
+ * This method is optional.
+ * @return true true if a segment was erased, false otherwise. */
+ virtual bool backspace() { return false; }
+
+ // these have a default implementation
+ virtual void feed(Curve const &c, bool moveto_initial = true);
+ /** @brief Output a subpath.
+ * Calls the appropriate segment methods according to the contents
+ * of the passed subpath. You can override this function.
+ * NOTE: if you override only some of the feed() functions,
+ * always write this in the derived class:
+ * @code
+ using PathSink::feed;
+ @endcode
+ * Otherwise the remaining methods will be hidden. */
+ virtual void feed(Path const &p);
+ /** @brief Output a path.
+ * Calls feed() on each path in the vector. You can override this function. */
+ virtual void feed(PathVector const &v);
+ /// Output an axis-aligned rectangle, using moveTo, lineTo and closePath.
+ virtual void feed(Rect const &);
+ /// Output a circle as two elliptical arcs.
+ virtual void feed(Circle const &e);
+ /// Output an ellipse as two elliptical arcs.
+ virtual void feed(Ellipse const &e);
+
+ virtual ~PathSink() {}
+};
+
+/** @brief Store paths to an output iterator
+ * @ingroup Paths */
+template <typename OutputIterator>
+class PathIteratorSink : public PathSink {
+public:
+ explicit PathIteratorSink(OutputIterator out)
+ : _in_path(false), _out(out) {}
+
+ void moveTo(Point const &p) override {
+ flush();
+ _path.start(p);
+ _start_p = p;
+ _in_path = true;
+ }
+//TODO: what if _in_path = false?
+
+ /** @brief Detect if the builder is in a path and thus will NOT
+ create a new moveTo command when given the next line
+ @return true if the builder is inside a subpath.
+ */
+ bool inPath() const {
+ return _in_path;
+ }
+
+ void lineTo(Point const &p) override {
+ // check for implicit moveto, like in: "M 1,1 L 2,2 z l 2,2 z"
+ if (!_in_path) {
+ moveTo(_start_p);
+ }
+ _path.template appendNew<LineSegment>(p);
+ }
+
+ void quadTo(Point const &c, Point const &p) override {
+ // check for implicit moveto, like in: "M 1,1 L 2,2 z l 2,2 z"
+ if (!_in_path) {
+ moveTo(_start_p);
+ }
+ _path.template appendNew<QuadraticBezier>(c, p);
+ }
+
+ void curveTo(Point const &c0, Point const &c1, Point const &p) override {
+ // check for implicit moveto, like in: "M 1,1 L 2,2 z l 2,2 z"
+ if (!_in_path) {
+ moveTo(_start_p);
+ }
+ _path.template appendNew<CubicBezier>(c0, c1, p);
+ }
+
+ void arcTo(Coord rx, Coord ry, Coord angle,
+ bool large_arc, bool sweep, Point const &p) override
+ {
+ // check for implicit moveto, like in: "M 1,1 L 2,2 z l 2,2 z"
+ if (!_in_path) {
+ moveTo(_start_p);
+ }
+ _path.template appendNew<EllipticalArc>(rx, ry, angle,
+ large_arc, sweep, p);
+ }
+
+ bool backspace() override
+ {
+ if (_in_path && _path.size() > 0) {
+ _path.erase_last();
+ return true;
+ }
+ return false;
+ }
+
+ void append(Path const &other)
+ {
+ if (!_in_path) {
+ moveTo(other.initialPoint());
+ }
+ _path.append(other);
+ }
+
+ void closePath() override {
+ if (_in_path) {
+ _path.close();
+ flush();
+ }
+ }
+
+ void flush() override {
+ if (_in_path) {
+ _in_path = false;
+ *_out++ = _path;
+ _path.clear();
+ }
+ }
+
+ void setStitching(bool s) {
+ _path.setStitching(s);
+ }
+
+ using PathSink::feed;
+ void feed(Path const &other) override
+ {
+ flush();
+ *_out++ = other;
+ }
+
+protected:
+ bool _in_path;
+ OutputIterator _out;
+ Path _path;
+ Point _start_p;
+};
+
+typedef std::back_insert_iterator<PathVector> SubpathInserter;
+
+/** @brief Store paths to a PathVector
+ * @ingroup Paths */
+class PathBuilder : public PathIteratorSink<SubpathInserter> {
+private:
+ PathVector _pathset;
+public:
+ /// Create a builder that outputs to an internal pathvector.
+ PathBuilder() : PathIteratorSink<SubpathInserter>(SubpathInserter(_pathset)) {}
+ /// Create a builder that outputs to pathvector given by reference.
+ PathBuilder(PathVector &pv) : PathIteratorSink<SubpathInserter>(SubpathInserter(pv)) {}
+
+ /// Retrieve the path
+ PathVector const &peek() const {return _pathset;}
+ /// Clear the stored path vector
+ void clear() { _pathset.clear(); }
+};
+
+}
+
+#endif
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/path.h b/src/3rdparty/2geom/include/2geom/path.h
new file mode 100644
index 0000000..f3042d7
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/path.h
@@ -0,0 +1,917 @@
+/** @file
+ * @brief Path - a sequence of contiguous curves
+ *//*
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2007-2014 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_PATH_H
+#define LIB2GEOM_SEEN_PATH_H
+
+#include <cstddef>
+#include <iterator>
+#include <algorithm>
+#include <iostream>
+#include <memory>
+#include <optional>
+#include <utility>
+#include <vector>
+
+#include <boost/operators.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
+
+#include <2geom/intersection.h>
+#include <2geom/curve.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/transforms.h>
+
+namespace Geom {
+
+class Path;
+class ConvexHull;
+
+namespace PathInternal {
+
+typedef boost::ptr_vector<Curve> Sequence;
+
+struct PathData {
+ Sequence curves;
+ OptRect fast_bounds;
+};
+
+template <typename P>
+class BaseIterator
+ : public boost::random_access_iterator_helper
+ < BaseIterator<P>
+ , Curve const
+ , std::ptrdiff_t
+ , Curve const *
+ , Curve const &
+ >
+{
+ protected:
+ BaseIterator(P &p, unsigned i) : path(&p), index(i) {}
+ // default copy, default assign
+ typedef BaseIterator<P> Self;
+
+ public:
+ BaseIterator() : path(NULL), index(0) {}
+
+ bool operator<(BaseIterator const &other) const {
+ return path == other.path && index < other.index;
+ }
+ bool operator==(BaseIterator const &other) const {
+ return path == other.path && index == other.index;
+ }
+ Curve const &operator*() const {
+ return (*path)[index];
+ }
+
+ Self &operator++() {
+ ++index;
+ return *this;
+ }
+ Self &operator--() {
+ --index;
+ return *this;
+ }
+ Self &operator+=(std::ptrdiff_t d) {
+ index += d;
+ return *this;
+ }
+ Self &operator-=(std::ptrdiff_t d) {
+ index -= d;
+ return *this;
+ }
+ std::ptrdiff_t operator-(Self const &other) const {
+ assert(path == other.path);
+ return (std::ptrdiff_t)index - (std::ptrdiff_t)other.index;
+ }
+
+ private:
+ P *path;
+ unsigned index;
+
+ friend class ::Geom::Path;
+};
+
+}
+
+/** @brief Generalized time value in the path.
+ *
+ * This class exists because when mapping the range of multiple curves onto the same interval
+ * as the curve index, we lose some precision. For instance, a path with 16 curves will
+ * have 4 bits less precision than a path with 1 curve. If you need high precision results
+ * in long paths, either use this class and related methods instead of the standard methods
+ * pointAt(), nearestTime() and so on, or use curveAt() to first obtain the curve, then
+ * call the method again to obtain a high precision result.
+ *
+ * @ingroup Paths */
+struct PathTime
+ : boost::totally_ordered<PathTime>
+{
+ typedef PathInternal::Sequence::size_type size_type;
+
+ Coord t; ///< Time value in the curve
+ size_type curve_index; ///< Index of the curve in the path
+
+ PathTime() : t(0), curve_index(0) {}
+ PathTime(size_type idx, Coord tval) : t(tval), curve_index(idx) {}
+
+ bool operator<(PathTime const &other) const {
+ if (curve_index < other.curve_index) return true;
+ if (curve_index == other.curve_index) {
+ return t < other.t;
+ }
+ return false;
+ }
+ bool operator==(PathTime const &other) const {
+ return curve_index == other.curve_index && t == other.t;
+ }
+ /// Convert times at or beyond 1 to 0 on the next curve.
+ void normalizeForward(size_type path_size) {
+ if (t >= 1) {
+ curve_index = (curve_index + 1) % path_size;
+ t = 0;
+ }
+ }
+ /// Convert times at or before 0 to 1 on the previous curve.
+ void normalizeBackward(size_type path_size) {
+ if (t <= 0) {
+ curve_index = (curve_index - 1) % path_size;
+ t = 1;
+ }
+ }
+
+ Coord asFlatTime() const { return curve_index + t; }
+};
+
+inline std::ostream &operator<<(std::ostream &os, PathTime const &pos) {
+ os << pos.curve_index << ": " << format_coord_nice(pos.t);
+ return os;
+}
+
+
+/** @brief Contiguous subset of the path's parameter domain.
+ * This is a directed interval, which allows one to specify any contiguous subset
+ * of the path's domain, including subsets that wrap around the initial point
+ * of the path.
+ * @ingroup Paths */
+class PathInterval {
+public:
+ typedef PathInternal::Sequence::size_type size_type;
+
+ /** @brief Default interval.
+ * Default-constructed PathInterval includes only the initial point of the initial segment. */
+ PathInterval();
+
+ /** @brief Construct an interval in the path's parameter domain.
+ * @param from Initial time
+ * @param to Final time
+ * @param cross_start If true, the interval will proceed from the initial to final
+ * time through the initial point of the path, wrapping around the closing segment;
+ * otherwise it will not wrap around the closing segment.
+ * @param path_size Size of the path to which this interval applies, required
+ * to clean up degenerate cases */
+ PathInterval(PathTime const &from, PathTime const &to, bool cross_start, size_type path_size);
+
+ /// Get the time value of the initial point.
+ PathTime const &initialTime() const { return _from; }
+ /// Get the time value of the final point.
+ PathTime const &finalTime() const { return _to; }
+
+ PathTime const &from() const { return _from; }
+ PathTime const &to() const { return _to; }
+
+ /// Check whether the interval has only one point.
+ bool isDegenerate() const { return _from == _to; }
+ /// True if the interval goes in the direction of decreasing time values.
+ bool reverse() const { return _reverse; }
+ /// True if the interior of the interval contains the initial point of the path.
+ bool crossesStart() const { return _cross_start; }
+
+ /// Test a path time for inclusion.
+ bool contains(PathTime const &pos) const;
+
+ /// Get a time at least @a min_dist away in parameter space from the ends.
+ /// If no such time exists, the middle point is returned.
+ PathTime inside(Coord min_dist = EPSILON) const;
+
+ /// Select one of two intervals with given endpoints by parameter direction.
+ static PathInterval from_direction(PathTime const &from, PathTime const &to,
+ bool reversed, size_type path_size);
+
+ /// Select one of two intervals with given endpoints by whether it includes the initial point.
+ static PathInterval from_start_crossing(PathTime const &from, PathTime const &to,
+ bool cross_start, size_type path_size) {
+ PathInterval result(from, to, cross_start, path_size);
+ return result;
+ }
+
+ size_type pathSize() const { return _path_size; }
+ size_type curveCount() const;
+
+private:
+ PathTime _from, _to;
+ size_type _path_size;
+ bool _cross_start, _reverse;
+};
+
+/// Create an interval in the direction of increasing time value.
+/// @relates PathInterval
+inline PathInterval forward_interval(PathTime const &from, PathTime const &to,
+ PathInterval::size_type path_size)
+{
+ PathInterval result = PathInterval::from_direction(from, to, false, path_size);
+ return result;
+}
+
+/// Create an interval in the direction of decreasing time value.
+/// @relates PathInterval
+inline PathInterval backward_interval(PathTime const &from, PathTime const &to,
+ PathInterval::size_type path_size)
+{
+ PathInterval result = PathInterval::from_direction(from, to, true, path_size);
+ return result;
+}
+
+/// Output an interval in the path's domain.
+/// @relates PathInterval
+inline std::ostream &operator<<(std::ostream &os, PathInterval const &ival) {
+ os << "PathInterval[";
+ if (ival.crossesStart()) {
+ os << ival.from() << " -> 0: 0.0 -> " << ival.to();
+ } else {
+ os << ival.from() << " -> " << ival.to();
+ }
+ os << "]";
+ return os;
+}
+
+typedef Intersection<PathTime> PathIntersection;
+
+template <>
+struct ShapeTraits<Path> {
+ typedef PathTime TimeType;
+ typedef PathInterval IntervalType;
+ typedef Path AffineClosureType;
+ typedef PathIntersection IntersectionType;
+};
+
+/** @brief Stores information about the extremum points on a path, with respect
+ * to one of the coordinate axes.
+ * @relates Path::extrema()
+ */
+struct PathExtrema {
+ /** Points with the minimum and maximum value of a coordinate. */
+ Point min_point, max_point;
+
+ /** Directions in which the OTHER coordinates change at the extremum points.
+ *
+ * - equals +1.0 if the other coordinate increases,
+ * - equals 0.0 if the other coordinate is constant (e.g., for an axis-aligned segment),
+ * - equals -1.0 if the other coordinate decreases.
+ */
+ float glance_direction_at_min, glance_direction_at_max;
+
+ /** Path times corresponding to minimum and maximum points. */
+ PathTime min_time, max_time;
+};
+
+/** @brief Sequence of contiguous curves, aka spline.
+ *
+ * Path represents a sequence of contiguous curves, also known as a spline.
+ * It corresponds to a "subpath" in SVG terminology. It can represent both
+ * open and closed subpaths. The final point of each curve is exactly
+ * equal to the initial point of the next curve.
+ *
+ * The path always contains a linear closing segment that connects
+ * the final point of the last "real" curve to the initial point of the
+ * first curve. This way the curves form a closed loop even for open paths.
+ * If the closing segment has nonzero length and the path is closed, it is
+ * considered a normal part of the path data. There are three distinct sets
+ * of end iterators one can use to iterate over the segments:
+ *
+ * - Iterating between @a begin() and @a end() will iterate over segments
+ * which are part of the path.
+ * - Iterating between @a begin() and @a end_closed()
+ * will always iterate over a closed loop of segments.
+ * - Iterating between @a begin() and @a end_open() will always skip
+ * the final linear closing segment.
+ *
+ * If the final point of the last "real" segment coincides exactly with the initial
+ * point of the first segment, the closing segment will be absent from both
+ * [begin(), end_open()) and [begin(), end_closed()).
+ *
+ * Normally, an exception will be thrown when you try to insert a curve
+ * that makes the path non-continuous. If you are working with unsanitized
+ * curve data, you can call setStitching(true), which will insert line segments
+ * to make the path continuous.
+ *
+ * Internally, Path uses copy-on-write data. This is done for two reasons: first,
+ * copying a Curve requires calling a virtual function, so it's a little more expensive
+ * that normal copying; and second, it reduces the memory cost of copying the path.
+ * Therefore you can return Path and PathVector from functions without worrying
+ * about temporary copies.
+ *
+ * Note that this class cannot represent arbitrary shapes, which may contain holes.
+ * To do that, use PathVector, which is more generic.
+ *
+ * It's not very convenient to create a Path directly. To construct paths more easily,
+ * use PathBuilder.
+ *
+ * @ingroup Paths */
+class Path
+ : boost::equality_comparable< Path >
+{
+public:
+ typedef PathInternal::PathData PathData;
+ typedef PathInternal::Sequence Sequence;
+ typedef PathInternal::BaseIterator<Path> iterator;
+ typedef PathInternal::BaseIterator<Path const> const_iterator;
+ typedef Sequence::size_type size_type;
+ typedef Sequence::difference_type difference_type;
+
+ class ClosingSegment : public LineSegment {
+ public:
+ ClosingSegment() : LineSegment() {}
+ ClosingSegment(Point const &p1, Point const &p2) : LineSegment(p1, p2) {}
+ Curve *duplicate() const override { return new ClosingSegment(*this); }
+ Curve *reverse() const override { return new ClosingSegment((*this)[1], (*this)[0]); }
+ };
+
+ class StitchSegment : public LineSegment {
+ public:
+ StitchSegment() : LineSegment() {}
+ StitchSegment(Point const &p1, Point const &p2) : LineSegment(p1, p2) {}
+ Curve *duplicate() const override { return new StitchSegment(*this); }
+ Curve *reverse() const override { return new StitchSegment((*this)[1], (*this)[0]); }
+ };
+
+ // Path(Path const &other) - use default copy constructor
+
+ /// Construct an empty path starting at the specified point.
+ explicit Path(Point const &p = Point())
+ : _data(new PathData())
+ , _closing_seg(new ClosingSegment(p, p))
+ , _closed(false)
+ , _exception_on_stitch(true)
+ {
+ _data->curves.push_back(_closing_seg);
+ }
+
+ /// Construct a path containing a range of curves.
+ template <typename Iter>
+ Path(Iter first, Iter last, bool closed = false, bool stitch = false)
+ : _data(new PathData())
+ , _closed(closed)
+ , _exception_on_stitch(!stitch)
+ {
+ for (Iter i = first; i != last; ++i) {
+ _data->curves.push_back(i->duplicate());
+ }
+ if (!_data->curves.empty()) {
+ _closing_seg = new ClosingSegment(_data->curves.back().finalPoint(),
+ _data->curves.front().initialPoint());
+ } else {
+ _closing_seg = new ClosingSegment();
+ }
+ _data->curves.push_back(_closing_seg);
+ }
+
+ /// Create a path from a rectangle.
+ explicit Path(Rect const &r);
+ /// Create a path from a convex hull.
+ explicit Path(ConvexHull const &);
+ /// Create a path from a circle, using two elliptical arcs.
+ explicit Path(Circle const &c);
+ /// Create a path from an ellipse, using two elliptical arcs.
+ explicit Path(Ellipse const &e);
+
+ virtual ~Path() {}
+
+ // Path &operator=(Path const &other) - use default assignment operator
+
+ /** @brief Swap contents with another path
+ * @todo Add noexcept specifiers for C++11 */
+ void swap(Path &other) noexcept {
+ using std::swap;
+ swap(other._data, _data);
+ swap(other._closing_seg, _closing_seg);
+ swap(other._closed, _closed);
+ swap(other._exception_on_stitch, _exception_on_stitch);
+ }
+ /** @brief Swap contents of two paths.
+ * @relates Path */
+ friend inline void swap(Path &a, Path &b) noexcept { a.swap(b); }
+
+ /** @brief Access a curve by index */
+ Curve const &operator[](size_type i) const { return _data->curves[i]; }
+ /** @brief Access a curve by index */
+ Curve const &at(size_type i) const { return _data->curves.at(i); }
+
+ /** @brief Access the first curve in the path.
+ * Since the curve always contains at least a degenerate closing segment,
+ * it is always safe to use this method. */
+ Curve const &front() const { return _data->curves.front(); }
+ /// Alias for front().
+ Curve const &initialCurve() const { return _data->curves.front(); }
+ /** @brief Access the last curve in the path. */
+ Curve const &back() const { return back_default(); }
+ Curve const &back_open() const {
+ if (empty()) return _data->curves.back();
+ return _data->curves[_data->curves.size() - 2];
+ }
+ Curve const &back_closed() const {
+ return _closing_seg->isDegenerate()
+ ? _data->curves[_data->curves.size() - 2]
+ : _data->curves[_data->curves.size() - 1];
+ }
+ Curve const &back_default() const {
+ return _includesClosingSegment()
+ ? back_closed()
+ : back_open();
+ }
+ Curve const &finalCurve() const { return back_default(); }
+
+ const_iterator begin() const { return const_iterator(*this, 0); }
+ const_iterator end() const { return end_default(); }
+ const_iterator end_default() const { return const_iterator(*this, size_default()); }
+ const_iterator end_open() const { return const_iterator(*this, size_open()); }
+ const_iterator end_closed() const { return const_iterator(*this, size_closed()); }
+ iterator begin() { return iterator(*this, 0); }
+ iterator end() { return end_default(); }
+ iterator end_default() { return iterator(*this, size_default()); }
+ iterator end_open() { return iterator(*this, size_open()); }
+ iterator end_closed() { return iterator(*this, size_closed()); }
+
+ /// Size without the closing segment, even if the path is closed.
+ size_type size_open() const { return _data->curves.size() - 1; }
+
+ /** @brief Size with the closing segment, if it makes a difference.
+ * If the closing segment is degenerate, i.e. its initial and final points
+ * are exactly equal, then it is not included in this size. */
+ size_type size_closed() const {
+ return _closing_seg->isDegenerate() ? _data->curves.size() - 1 : _data->curves.size();
+ }
+
+ /// Natural size of the path.
+ size_type size_default() const {
+ return _includesClosingSegment() ? size_closed() : size_open();
+ }
+ /// Natural size of the path.
+ size_type size() const { return size_default(); }
+
+ size_type max_size() const { return _data->curves.max_size() - 1; }
+
+ /** @brief Check whether path is empty.
+ * The path is empty if it contains only the closing segment, which according
+ * to the continuity invariant must be degenerate. Note that unlike standard
+ * containers, two empty paths are not necessarily identical, because the
+ * degenerate closing segment may be at a different point, affecting the operation
+ * of methods such as appendNew(). */
+ bool empty() const { return (_data->curves.size() == 1); }
+
+ /// Check whether the path is closed.
+ bool closed() const { return _closed; }
+
+ /** @brief Set whether the path is closed.
+ * When closing a path where the last segment can be represented as a closing
+ * segment, the last segment will be removed. When opening a path, the closing
+ * segment will be erased. This means that closing and then opening a path
+ * will not always give back the original path. */
+ void close(bool closed = true);
+
+ /** @brief Remove all curves from the path.
+ * The initial and final points of the closing segment are set to (0,0).
+ * The stitching flag remains unchanged. */
+ void clear();
+
+ /** @brief Get the approximate bounding box.
+ * The rectangle returned by this method will contain all the curves, but it's not
+ * guaranteed to be the smallest possible one */
+ OptRect boundsFast() const;
+
+ /** @brief Get a tight-fitting bounding box.
+ * This will return the smallest possible axis-aligned rectangle containing
+ * all the curves in the path. */
+ OptRect boundsExact() const;
+
+ Piecewise<D2<SBasis> > toPwSb() const;
+
+ /// Test paths for exact equality.
+ bool operator==(Path const &other) const;
+
+ /// Apply a transform to each curve.
+ template <typename T>
+ Path &operator*=(T const &tr) {
+ BOOST_CONCEPT_ASSERT((TransformConcept<T>));
+ _unshare();
+ for (std::size_t i = 0; i < _data->curves.size(); ++i) {
+ _data->curves[i] *= tr;
+ }
+ return *this;
+ }
+
+ template <typename T>
+ friend Path operator*(Path const &path, T const &tr) {
+ BOOST_CONCEPT_ASSERT((TransformConcept<T>));
+ Path result(path);
+ result *= tr;
+ return result;
+ }
+
+ /** @brief Get the allowed range of time values.
+ * @return Values for which pointAt() and valueAt() yield valid results. */
+ Interval timeRange() const;
+
+ /** Get the curve at the specified time value.
+ * @param t Time value
+ * @param rest Optional storage for the corresponding time value in the curve */
+ Curve const &curveAt(Coord t, Coord *rest = NULL) const;
+
+ /// Get the closing segment of the path.
+ LineSegment const &closingSegment() const { return *_closing_seg; }
+
+ /** @brief Get the point at the specified time value.
+ * Note that this method has reduced precision with respect to calling pointAt()
+ * directly on the curve. If you want high precision results, use the version
+ * that takes a PathTime parameter.
+ *
+ * Allowed time values range from zero to the number of curves; you can retrieve
+ * the allowed range of values with timeRange(). */
+ Point pointAt(Coord t) const;
+
+ /// Get one coordinate (X or Y) at the specified time value.
+ Coord valueAt(Coord t, Dim2 d) const;
+
+ /// Get the curve at the specified path time.
+ Curve const &curveAt(PathTime const &pos) const;
+ /// Get the point at the specified path time.
+ Point pointAt(PathTime const &pos) const;
+ /// Get one coordinate at the specified path time.
+ Coord valueAt(PathTime const &pos, Dim2 d) const;
+
+ Point operator()(Coord t) const { return pointAt(t); }
+
+ /** @brief Find the extrema of the specified coordinate.
+ *
+ * Returns a PathExtrema struct describing "witness" points on the path
+ * where the specified coordinate attains its minimum and maximum values.
+ */
+ PathExtrema extrema(Dim2 d) const;
+
+ /// Compute intersections with axis-aligned line.
+ std::vector<PathTime> roots(Coord v, Dim2 d) const;
+
+ /// Compute intersections with another path.
+ std::vector<PathIntersection> intersect(Path const &other, Coord precision = EPSILON) const;
+
+ /// Compute intersections of the path with itself.
+ std::vector<PathIntersection> intersectSelf(Coord precision = EPSILON) const;
+
+ /** @brief Determine the winding number at the specified point.
+ *
+ * The winding number is the number of full turns made by a ray that connects the passed
+ * point and the path's value (i.e. the result of the pointAt() method) as the time increases
+ * from 0 to the maximum valid value. Positive numbers indicate turns in the direction
+ * of increasing angles.
+ *
+ * Winding numbers are often used as the definition of what is considered "inside"
+ * the shape. Typically points with either nonzero winding or odd winding are
+ * considered to be inside the path. */
+ int winding(Point const &p) const;
+
+ std::vector<Coord> allNearestTimes(Point const &p, Coord from, Coord to) const;
+ std::vector<Coord> allNearestTimes(Point const &p) const {
+ return allNearestTimes(p, 0, size_default());
+ }
+
+ PathTime nearestTime(Point const &p, Coord *dist = NULL) const;
+ std::vector<Coord> nearestTimePerCurve(Point const &p) const;
+
+ std::vector<Point> nodes() const;
+
+ void appendPortionTo(Path &p, Coord f, Coord t) const;
+
+ /** @brief Append a subset of this path to another path.
+ * An extra stitching segment will be inserted if the start point of the portion
+ * and the final point of the target path do not match exactly.
+ * The closing segment of the target path will be modified. */
+ void appendPortionTo(Path &p, PathTime const &from, PathTime const &to, bool cross_start = false) const {
+ PathInterval ival(from, to, cross_start, size_closed());
+ appendPortionTo(p, ival, std::nullopt, std::nullopt);
+ }
+
+ /** @brief Append a subset of this path to another path.
+ * This version allows you to explicitly pass a PathInterval. */
+ void appendPortionTo(Path &p, PathInterval const &ival) const {
+ appendPortionTo(p, ival, std::nullopt, std::nullopt);
+ }
+
+ /** @brief Append a subset of this path to another path, specifying endpoints.
+ * This method is for use in situations where endpoints of the portion segments
+ * have to be set exactly, for instance when computing Boolean operations. */
+ void appendPortionTo(Path &p, PathInterval const &ival,
+ std::optional<Point> const &p_from, std::optional<Point> const &p_to) const;
+
+ Path portion(Coord f, Coord t) const {
+ Path ret;
+ ret.close(false);
+ appendPortionTo(ret, f, t);
+ return ret;
+ }
+
+ Path portion(Interval const &i) const { return portion(i.min(), i.max()); }
+
+ /** @brief Get a subset of the current path with full precision.
+ * When @a from is larger (later in the path) than @a to, the returned portion
+ * will be reversed. If @a cross_start is true, the portion will be reversed
+ * and will cross the initial point of the path. Therefore, when @a from is larger
+ * than @a to and @a cross_start is true, the returned portion will not be reversed,
+ * but will "wrap around" the end of the path. */
+ Path portion(PathTime const &from, PathTime const &to, bool cross_start = false) const {
+ Path ret;
+ ret.close(false);
+ appendPortionTo(ret, from, to, cross_start);
+ return ret;
+ }
+
+ /** @brief Get a subset of the current path with full precision.
+ * This version allows you to explicitly pass a PathInterval. */
+ Path portion(PathInterval const &ival) const {
+ Path ret;
+ ret.close(false);
+ appendPortionTo(ret, ival);
+ return ret;
+ }
+
+ /** @brief Obtain a reversed version of the current path.
+ * The final point of the current path will become the initial point
+ * of the reversed path, unless it is closed and has a non-degenerate
+ * closing segment. In that case, the new initial point will be the final point
+ * of the last "real" segment. */
+ Path reversed() const;
+
+ void insert(iterator pos, Curve const &curve);
+
+ template <typename Iter>
+ void insert(iterator pos, Iter first, Iter last) {
+ _unshare();
+ Sequence::iterator seq_pos(seq_iter(pos));
+ Sequence source;
+ for (; first != last; ++first) {
+ source.push_back(first->duplicate());
+ }
+ do_update(seq_pos, seq_pos, source);
+ }
+
+ void erase(iterator pos);
+ void erase(iterator first, iterator last);
+
+ // erase last segment of path
+ void erase_last() { erase(iterator(*this, size() - 1)); }
+
+ void start(Point const &p);
+
+ /** @brief Get the first point in the path. */
+ Point initialPoint() const { return (*_closing_seg)[1]; }
+
+ /** @brief Get the last point in the path.
+ * If the path is closed, this is always the same as the initial point. */
+ Point finalPoint() const { return (*_closing_seg)[_closed ? 1 : 0]; }
+
+ /** @brief Get the unit tangent vector at the start of the path,
+ * or the zero vector if undefined. */
+ Point initialUnitTangent() const {
+ for (auto const &curve : *this) {
+ if (!curve.isDegenerate()) {
+ return curve.unitTangentAt(0.0);
+ }
+ }
+ return Point();
+ }
+
+ /** @brief Get the unit tangent vector at the end of the path,
+ * or the zero vector if undefined. */
+ Point finalUnitTangent() const {
+ for (auto it = end(); it != begin();) {
+ --it;
+ if (!it->isDegenerate()) {
+ return it->unitTangentAt(1.0);
+ }
+ }
+ return Point();
+ }
+
+ void setInitial(Point const &p) {
+ _unshare();
+ _closed = false;
+ _data->curves.front().setInitial(p);
+ _closing_seg->setFinal(p);
+ }
+ void setFinal(Point const &p) {
+ _unshare();
+ _closed = false;
+ _data->curves[size_open() - 1].setFinal(p);
+ _closing_seg->setInitial(p);
+ }
+
+ /** @brief Add a new curve to the end of the path.
+ * This inserts the new curve right before the closing segment.
+ * The path takes ownership of the passed pointer, which should not be freed. */
+ void append(Curve *curve) {
+ _unshare();
+ stitchTo(curve->initialPoint());
+ do_append(curve);
+ }
+
+ void append(Curve const &curve) {
+ _unshare();
+ stitchTo(curve.initialPoint());
+ do_append(curve.duplicate());
+ }
+ void append(D2<SBasis> const &curve) {
+ _unshare();
+ stitchTo(Point(curve[X][0][0], curve[Y][0][0]));
+ do_append(new SBasisCurve(curve));
+ }
+ void append(Path const &other) {
+ replace(end_open(), other.begin(), other.end());
+ }
+
+ void replace(iterator replaced, Curve const &curve);
+ void replace(iterator first, iterator last, Curve const &curve);
+ void replace(iterator replaced, Path const &path);
+ void replace(iterator first, iterator last, Path const &path);
+
+ template <typename Iter>
+ void replace(iterator replaced, Iter first, Iter last) {
+ replace(replaced, replaced + 1, first, last);
+ }
+
+ template <typename Iter>
+ void replace(iterator first_replaced, iterator last_replaced, Iter first, Iter last) {
+ _unshare();
+ Sequence::iterator seq_first_replaced(seq_iter(first_replaced));
+ Sequence::iterator seq_last_replaced(seq_iter(last_replaced));
+ Sequence source;
+ for (; first != last; ++first) {
+ source.push_back(first->duplicate());
+ }
+ do_update(seq_first_replaced, seq_last_replaced, source);
+ }
+
+ /** @brief Append a new curve to the path.
+ *
+ * This family of methods will automatically use the current final point of the path
+ * as the first argument of the new curve's constructor. To call this method,
+ * you'll need to write e.g.:
+ * @code
+ path.template appendNew<CubicBezier>(control1, control2, end_point);
+ @endcode
+ * It is important to note that the coordinates passed to appendNew should be finite!
+ * If one of the coordinates is infinite, 2geom will throw a ContinuityError exception.
+ */
+ template <typename CurveType, typename... Args>
+ void appendNew(Args&&... args) {
+ _unshare();
+ do_append(new CurveType(finalPoint(), std::forward<Args>(args)...));
+ }
+
+ /** @brief Reduce the closing segment to a point if it's shorter than precision.
+ * Do this by moving the final point. */
+ void snapEnds(Coord precision = EPSILON);
+
+ /// Append a stitching segment ending at the specified point.
+ void stitchTo(Point const &p);
+
+ /** @brief Return a copy of the path without degenerate curves, except possibly for a
+ * degenerate closing segment. */
+ Path withoutDegenerateCurves() const;
+
+ /** @brief Verify the continuity invariant.
+ * If the path is not contiguous, this will throw a CountinuityError. */
+ void checkContinuity() const;
+
+ /** @brief Enable or disable the throwing of exceptions when stitching discontinuities.
+ * Normally stitching will cause exceptions, but when you are working with unsanitized
+ * curve data, you can disable these exceptions. */
+ void setStitching(bool x) {
+ _exception_on_stitch = !x;
+ }
+
+private:
+ static Sequence::iterator seq_iter(iterator const &iter) {
+ return iter.path->_data->curves.begin() + iter.index;
+ }
+ static Sequence::const_iterator seq_iter(const_iterator const &iter) {
+ return iter.path->_data->curves.begin() + iter.index;
+ }
+
+ // whether the closing segment is part of the path
+ bool _includesClosingSegment() const {
+ return _closed && !_closing_seg->isDegenerate();
+ }
+ void _unshare() {
+ // Called before every mutation.
+ // Ensure we have our own copy of curve data and reset cached values
+ if (!_data.unique()) {
+ _data.reset(new PathData(*_data));
+ _closing_seg = static_cast<ClosingSegment*>(&_data->curves.back());
+ }
+ _data->fast_bounds = OptRect();
+ }
+ PathTime _factorTime(Coord t) const;
+
+ void stitch(Sequence::iterator first_replaced, Sequence::iterator last_replaced, Sequence &sequence);
+ void do_update(Sequence::iterator first, Sequence::iterator last, Sequence &source);
+
+ // n.b. takes ownership of curve object
+ void do_append(Curve *curve);
+
+ std::shared_ptr<PathData> _data;
+ ClosingSegment *_closing_seg;
+ bool _closed;
+ bool _exception_on_stitch;
+}; // end class Path
+
+Piecewise<D2<SBasis> > paths_to_pw(PathVector const &paths);
+
+inline Coord nearest_time(Point const &p, Path const &c) {
+ PathTime pt = c.nearestTime(p);
+ return pt.curve_index + pt.t;
+}
+
+bool are_near(Path const &a, Path const &b, Coord precision = EPSILON);
+
+/**
+ * @brief Find the first point where two paths diverge away from one another.
+ *
+ * If the two paths have a common starting point, the algorithm follows them for as long as the
+ * images of the paths coincide and finds the first point where they stop coinciding. Note that
+ * only the images of paths in the plane are compared, and not their parametrizations, so this
+ * is not a functional (parametric) coincidence. If you want to test parametric coincidence, use
+ * bool are_near(Path const&, Path const&, Coord) instead.
+ *
+ * The function returns the point where the traces of the two paths finally diverge up to the
+ * specified precision. If the traces (images) of the paths are nearly identical until the end,
+ * the returned point is their (almost) common endpoint. If however the image of one of the paths
+ * is completely contained in the image of the other path, the returned point is the endpoint of
+ * the shorter path.
+ *
+ * If the paths have different starting points, then the returned intersection has the special
+ * time values of -1.0 on both paths and the returned intersection point is the midpoint of the
+ * line segment connecting the two starting points.
+ *
+ * @param first The first path to follow; corresponds to .first in the return value.
+ * @param second The second path to follow; corresponds to .second in the return value.
+ * @param precision How close the paths' images need to be in order to be considered as overlapping.
+ * @return A path intersection specifying the point and path times where the two paths part ways.
+ */
+PathIntersection parting_point(Path const &first, Path const &second, Coord precision = EPSILON);
+
+std::ostream &operator<<(std::ostream &out, Path const &path);
+
+} // end namespace Geom
+
+
+#endif // LIB2GEOM_SEEN_PATH_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/pathvector.h b/src/3rdparty/2geom/include/2geom/pathvector.h
new file mode 100644
index 0000000..3fd7d36
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/pathvector.h
@@ -0,0 +1,304 @@
+/** @file
+ * @brief PathVector - a sequence of subpaths
+ *//*
+ * Authors:
+ * Johan Engelen <j.b.c.engelen@alumnus.utwente.nl>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2008-2014 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_PATHVECTOR_H
+#define LIB2GEOM_SEEN_PATHVECTOR_H
+
+#include <optional>
+#include <boost/concept/requires.hpp>
+#include <boost/range/algorithm/equal.hpp>
+#include <2geom/forward.h>
+#include <2geom/path.h>
+#include <2geom/transforms.h>
+
+namespace Geom {
+
+/** @brief Generalized time value in the path vector.
+ *
+ * This class exists because mapping the range of multiple curves onto the same interval
+ * as the curve index, we lose some precision. For instance, a path with 16 curves will
+ * have 4 bits less precision than a path with 1 curve. If you need high precision results
+ * in long paths, use this class and related methods instead of the standard methods
+ * pointAt(), nearestTime() and so on.
+ *
+ * @ingroup Paths */
+struct PathVectorTime
+ : public PathTime
+ , boost::totally_ordered<PathVectorTime>
+{
+ size_type path_index; ///< Index of the path in the vector
+
+ PathVectorTime() : PathTime(0, 0), path_index(0) {}
+ PathVectorTime(size_type _i, size_type _c, Coord _t)
+ : PathTime(_c, _t), path_index(_i) {}
+ PathVectorTime(size_type _i, PathTime const &pos)
+ : PathTime(pos), path_index(_i) {}
+
+ bool operator<(PathVectorTime const &other) const {
+ if (path_index < other.path_index) return true;
+ if (path_index == other.path_index) {
+ return static_cast<PathTime const &>(*this) < static_cast<PathTime const &>(other);
+ }
+ return false;
+ }
+ bool operator==(PathVectorTime const &other) const {
+ return path_index == other.path_index
+ && static_cast<PathTime const &>(*this) == static_cast<PathTime const &>(other);
+ }
+
+ PathTime const &asPathTime() const {
+ return *static_cast<PathTime const *>(this);
+ }
+};
+
+inline std::ostream &operator<<(std::ostream &os, PathVectorTime const &pvt) {
+ os << pvt.path_index << ": " << pvt.asPathTime();
+ return os;
+}
+
+typedef Intersection<PathVectorTime> PathVectorIntersection;
+typedef PathVectorIntersection PVIntersection; ///< Alias to save typing
+
+template <>
+struct ShapeTraits<PathVector> {
+ typedef PathVectorTime TimeType;
+ //typedef PathVectorInterval IntervalType;
+ typedef PathVector AffineClosureType;
+ typedef PathVectorIntersection IntersectionType;
+};
+
+/** @brief Sequence of subpaths.
+ *
+ * This class corresponds to the SVG notion of a path:
+ * a sequence of any number of open or closed contiguous subpaths.
+ * Unlike Path, this class is closed under boolean operations.
+ *
+ * If you want to represent an arbitrary shape, this is the best class to use.
+ * Shapes with a boundary that is composed of only a single contiguous
+ * component can be represented with Path instead.
+ *
+ * @ingroup Paths
+ */
+class PathVector
+ : MultipliableNoncommutative< PathVector, Affine
+ , MultipliableNoncommutative< PathVector, Translate
+ , MultipliableNoncommutative< PathVector, Scale
+ , MultipliableNoncommutative< PathVector, Rotate
+ , MultipliableNoncommutative< PathVector, HShear
+ , MultipliableNoncommutative< PathVector, VShear
+ , MultipliableNoncommutative< PathVector, Zoom
+ , boost::equality_comparable< PathVector
+ > > > > > > > >
+{
+ typedef std::vector<Path> Sequence;
+public:
+ typedef PathVectorTime Position;
+ typedef Sequence::iterator iterator;
+ typedef Sequence::const_iterator const_iterator;
+ typedef Sequence::size_type size_type;
+ typedef Path value_type;
+ typedef Path &reference;
+ typedef Path const &const_reference;
+ typedef Path *pointer;
+ typedef std::ptrdiff_t difference_type;
+
+ PathVector() {}
+ PathVector(Path const &p)
+ : _data(1, p)
+ {}
+ template <typename InputIter>
+ PathVector(InputIter first, InputIter last)
+ : _data(first, last)
+ {}
+
+ /// Check whether the vector contains any paths.
+ bool empty() const { return _data.empty(); }
+ /// Get the number of paths in the vector.
+ size_type size() const { return _data.size(); }
+ /// Get the total number of curves in the vector.
+ size_type curveCount() const;
+
+ iterator begin() { return _data.begin(); }
+ iterator end() { return _data.end(); }
+ const_iterator begin() const { return _data.begin(); }
+ const_iterator end() const { return _data.end(); }
+ Path &operator[](size_type index) {
+ return _data[index];
+ }
+ Path const &operator[](size_type index) const {
+ return _data[index];
+ }
+ Path &at(size_type index) {
+ return _data.at(index);
+ }
+ Path const &at(size_type index) const {
+ return _data.at(index);
+ }
+ Path &front() { return _data.front(); }
+ Path const &front() const { return _data.front(); }
+ Path &back() { return _data.back(); }
+ Path const &back() const { return _data.back(); }
+ /// Append a path at the end.
+ void push_back(Path const &path) {
+ _data.push_back(path);
+ }
+ /// Remove the last path.
+ void pop_back() {
+ _data.pop_back();
+ }
+ iterator insert(iterator pos, Path const &p) {
+ return _data.insert(pos, p);
+ }
+ template <typename InputIter>
+ void insert(iterator out, InputIter first, InputIter last) {
+ _data.insert(out, first, last);
+ }
+ /// Remove a path from the vector.
+ iterator erase(iterator i) {
+ return _data.erase(i);
+ }
+ /// Remove a range of paths from the vector.
+ iterator erase(iterator first, iterator last) {
+ return _data.erase(first, last);
+ }
+ /// Remove all paths from the vector.
+ void clear() { _data.clear(); }
+ /** @brief Change the number of paths.
+ * If the vector size increases, it is passed with paths that contain only
+ * a degenerate closing segment at (0,0). */
+ void resize(size_type n) { _data.resize(n); }
+ /** @brief Reverse the direction of paths in the vector.
+ * @param reverse_paths If this is true, the order of paths is reversed as well;
+ * otherwise each path is reversed, but their order in the
+ * PathVector stays the same */
+ void reverse(bool reverse_paths = true);
+ /** @brief Get a new vector with reversed direction of paths.
+ * @param reverse_paths If this is true, the order of paths is reversed as well;
+ * otherwise each path is reversed, but their order in the
+ * PathVector stays the same */
+ PathVector reversed(bool reverse_paths = true) const;
+
+ /// Get the range of allowed time values.
+ Interval timeRange() const {
+ Interval ret(0, curveCount()); return ret;
+ }
+ /** @brief Get the first point in the first path of the vector.
+ * This method will throw an exception if the vector doesn't contain any paths. */
+ Point initialPoint() const {
+ return _data.front().initialPoint();
+ }
+ /** @brief Get the last point in the last path of the vector.
+ * This method will throw an exception if the vector doesn't contain any paths. */
+ Point finalPoint() const {
+ return _data.back().finalPoint();
+ }
+ /** @brief Get all intersections of the path-vector with itself. This includes both
+ * self-intersections of constituent paths and intersections between different paths. */
+ std::vector<PathVectorIntersection> intersectSelf(Coord precision = EPSILON) const;
+ Path &pathAt(Coord t, Coord *rest = NULL);
+ Path const &pathAt(Coord t, Coord *rest = NULL) const;
+ Curve const &curveAt(Coord t, Coord *rest = NULL) const;
+ Coord valueAt(Coord t, Dim2 d) const;
+ Point pointAt(Coord t) const;
+
+ Path &pathAt(PathVectorTime const &pos) {
+ return const_cast<Path &>(static_cast<PathVector const*>(this)->pathAt(pos));
+ }
+ Path const &pathAt(PathVectorTime const &pos) const {
+ return at(pos.path_index);
+ }
+ Curve const &curveAt(PathVectorTime const &pos) const {
+ return at(pos.path_index).at(pos.curve_index);
+ }
+ Point pointAt(PathVectorTime const &pos) const {
+ return at(pos.path_index).at(pos.curve_index).pointAt(pos.t);
+ }
+ Coord valueAt(PathVectorTime const &pos, Dim2 d) const {
+ return at(pos.path_index).at(pos.curve_index).valueAt(pos.t, d);
+ }
+
+ OptRect boundsFast() const;
+ OptRect boundsExact() const;
+
+ template <typename T>
+ BOOST_CONCEPT_REQUIRES(((TransformConcept<T>)), (PathVector &))
+ operator*=(T const &t) {
+ if (empty()) return *this;
+ for (auto & i : *this) {
+ i *= t;
+ }
+ return *this;
+ }
+
+ bool operator==(PathVector const &other) const {
+ return boost::range::equal(_data, other._data);
+ }
+
+ void snapEnds(Coord precision = EPSILON);
+
+ std::vector<PVIntersection> intersect(PathVector const &other, Coord precision = EPSILON) const;
+
+ /** @brief Determine the winding number at the specified point.
+ * This is simply the sum of winding numbers for constituent paths. */
+ int winding(Point const &p) const;
+
+ std::optional<PathVectorTime> nearestTime(Point const &p, Coord *dist = NULL) const;
+ std::vector<PathVectorTime> allNearestTimes(Point const &p, Coord *dist = NULL) const;
+
+ std::vector<Point> nodes() const;
+
+private:
+ PathVectorTime _factorTime(Coord t) const;
+
+ Sequence _data;
+};
+
+inline OptRect bounds_fast(PathVector const &pv) { return pv.boundsFast(); }
+inline OptRect bounds_exact(PathVector const &pv) { return pv.boundsExact(); }
+
+std::ostream &operator<<(std::ostream &out, PathVector const &pv);
+
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_PATHVECTOR_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/piecewise.h b/src/3rdparty/2geom/include/2geom/piecewise.h
new file mode 100644
index 0000000..e34df15
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/piecewise.h
@@ -0,0 +1,945 @@
+/** @file
+ * @brief Piecewise function class
+ *//*
+ * Copyright 2007 Michael Sloan <mgsloan@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, output to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_PIECEWISE_H
+#define LIB2GEOM_SEEN_PIECEWISE_H
+
+#include <vector>
+#include <map>
+#include <utility>
+#include <boost/concept_check.hpp>
+#include <2geom/concepts.h>
+#include <2geom/math-utils.h>
+#include <2geom/sbasis.h>
+
+
+namespace Geom {
+/**
+ * @brief Function defined as discrete pieces.
+ *
+ * The Piecewise class manages a sequence of elements of a type as segments and
+ * the ’cuts’ between them. These cuts are time values which separate the pieces.
+ * This function representation allows for more interesting functions, as it provides
+ * a viable output for operations such as inversion, which may require multiple
+ * SBasis to properly invert the original.
+ *
+ * As for technical details, while the actual SBasis segments begin on the ï¬rst
+ * cut and end on the last, the function is deï¬ned throughout all inputs by ex-
+ * tending the ï¬rst and last segments. The exact switching between segments is
+ * arbitrarily such that beginnings (t=0) have preference over endings (t=1). This
+ * only matters if it is discontinuous at the location.
+ * \f[
+ * f(t) \rightarrow \left\{
+ * \begin{array}{cc}
+ * s_1,& t <= c_2 \\
+ * s_2,& c_2 <= t <= c_3\\
+ * \ldots \\
+ * s_n,& c_n <= t
+ * \end{array}\right.
+ * \f]
+ *
+ * @ingroup Fragments
+ */
+template <typename T>
+class Piecewise {
+ BOOST_CLASS_REQUIRE(T, Geom, FragmentConcept);
+
+ public:
+ std::vector<double> cuts;
+ std::vector<T> segs;
+ //segs[i] stretches from cuts[i] to cuts[i+1].
+
+ Piecewise() {}
+
+ explicit Piecewise(const T &s) {
+ push_cut(0.);
+ push_seg(s);
+ push_cut(1.);
+ }
+
+ unsigned input_dim(){return 1;}
+
+ typedef typename T::output_type output_type;
+
+ explicit Piecewise(const output_type & v) {
+ push_cut(0.);
+ push_seg(T(v));
+ push_cut(1.);
+ }
+
+ inline void reserve(unsigned i) { segs.reserve(i); cuts.reserve(i + 1); }
+
+ inline T const& operator[](unsigned i) const { return segs[i]; }
+ inline T& operator[](unsigned i) { return segs[i]; }
+ inline output_type operator()(double t) const { return valueAt(t); }
+ inline output_type valueAt(double t) const {
+ unsigned n = segN(t);
+ return segs[n](segT(t, n));
+ }
+ inline output_type firstValue() const {
+ return valueAt(cuts.front());
+ }
+ inline output_type lastValue() const {
+ return valueAt(cuts.back());
+ }
+
+ /**
+ * The size of the returned vector equals n_derivs+1.
+ */
+ std::vector<output_type> valueAndDerivatives(double t, unsigned n_derivs) const {
+ unsigned n = segN(t);
+ std::vector<output_type> ret, val = segs[n].valueAndDerivatives(segT(t, n), n_derivs);
+ double mult = 1;
+ for(unsigned i = 0; i < val.size(); i++) {
+ ret.push_back(val[i] * mult);
+ mult /= cuts[n+1] - cuts[n];
+ }
+ return ret;
+ }
+
+ //TODO: maybe it is not a good idea to have this?
+ Piecewise<T> operator()(SBasis f);
+ Piecewise<T> operator()(Piecewise<SBasis>f);
+
+ inline unsigned size() const { return segs.size(); }
+ inline bool empty() const { return segs.empty(); }
+ inline void clear() {
+ segs.clear();
+ cuts.clear();
+ }
+
+ /**Convenience/implementation hiding function to add segment/cut pairs.
+ * Asserts that basic size and order invariants are correct
+ */
+ inline void push(const T &s, double to) {
+ assert(cuts.size() - segs.size() == 1);
+ push_seg(s);
+ push_cut(to);
+ }
+ inline void push(T &&s, double to) {
+ assert(cuts.size() - segs.size() == 1);
+ push_seg(s);
+ push_cut(to);
+ }
+ //Convenience/implementation hiding function to add cuts.
+ inline void push_cut(double c) {
+ ASSERT_INVARIANTS(cuts.empty() || c > cuts.back());
+ cuts.push_back(c);
+ }
+ //Convenience/implementation hiding function to add segments.
+ inline void push_seg(const T &s) { segs.push_back(s); }
+ inline void push_seg(T &&s) { segs.emplace_back(s); }
+
+ /**Returns the segment index which corresponds to a 'global' piecewise time.
+ * Also takes optional low/high parameters to expedite the search for the segment.
+ */
+ inline unsigned segN(double t, int low = 0, int high = -1) const {
+ high = (high == -1) ? size() : high;
+ if(t < cuts[0]) return 0;
+ if(t >= cuts[size()]) return size() - 1;
+ while(low < high) {
+ int mid = (high + low) / 2; //Lets not plan on having huge (> INT_MAX / 2) cut sequences
+ double mv = cuts[mid];
+ if(mv < t) {
+ if(t < cuts[mid + 1]) return mid; else low = mid + 1;
+ } else if(t < mv) {
+ if(cuts[mid - 1] < t) return mid - 1; else high = mid - 1;
+ } else {
+ return mid;
+ }
+ }
+ return low;
+ }
+
+ /**Returns the time within a segment, given the 'global' piecewise time.
+ * Also takes an optional index parameter which may be used for efficiency or to find the time on a
+ * segment outside its range. If it is left to its default, -1, it will call segN to find the index.
+ */
+ inline double segT(double t, int i = -1) const {
+ if(i == -1) i = segN(t);
+ assert(i >= 0);
+ return (t - cuts[i]) / (cuts[i+1] - cuts[i]);
+ }
+
+ inline double mapToDomain(double t, unsigned i) const {
+ return (1-t)*cuts[i] + t*cuts[i+1]; //same as: t * (cuts[i+1] - cuts[i]) + cuts[i]
+ }
+
+ //Offsets the piecewise domain
+ inline void offsetDomain(double o) {
+ assert(std::isfinite(o));
+ if(o != 0)
+ for(unsigned i = 0; i <= size(); i++)
+ cuts[i] += o;
+ }
+
+ //Scales the domain of the function by a value. 0 will result in an empty Piecewise.
+ inline void scaleDomain(double s) {
+ assert(s > 0);
+ if(s == 0) {
+ cuts.clear(); segs.clear();
+ return;
+ }
+ for(unsigned i = 0; i <= size(); i++)
+ cuts[i] *= s;
+ }
+
+ //Retrieves the domain in interval form
+ inline Interval domain() const { return Interval(cuts.front(), cuts.back()); }
+
+ //Transforms the domain into another interval
+ inline void setDomain(Interval dom) {
+ if(empty()) return;
+ /* dom can not be empty
+ if(dom.empty()) {
+ cuts.clear(); segs.clear();
+ return;
+ }*/
+ double cf = cuts.front();
+ double o = dom.min() - cf, s = dom.extent() / (cuts.back() - cf);
+ for(unsigned i = 0; i <= size(); i++)
+ cuts[i] = (cuts[i] - cf) * s + o;
+ //fix floating point precision errors.
+ cuts[0] = dom.min();
+ cuts[size()] = dom.max();
+ }
+
+ //Concatenates this Piecewise function with another, offsetting time of the other to match the end.
+ inline void concat(const Piecewise<T> &other) {
+ if(other.empty()) return;
+
+ if(empty()) {
+ cuts = other.cuts; segs = other.segs;
+ return;
+ }
+
+ segs.insert(segs.end(), other.segs.begin(), other.segs.end());
+ double t = cuts.back() - other.cuts.front();
+ cuts.reserve(cuts.size() + other.size());
+ for(unsigned i = 0; i < other.size(); i++)
+ push_cut(other.cuts[i + 1] + t);
+ }
+
+ //Like concat, but ensures continuity.
+ inline void continuousConcat(const Piecewise<T> &other) {
+ boost::function_requires<AddableConcept<typename T::output_type> >();
+ if(other.empty()) return;
+
+ if(empty()) { segs = other.segs; cuts = other.cuts; return; }
+
+ typename T::output_type y = segs.back().at1() - other.segs.front().at0();
+ double t = cuts.back() - other.cuts.front();
+ reserve(size() + other.size());
+ for(unsigned i = 0; i < other.size(); i++)
+ push(other[i] + y, other.cuts[i + 1] + t);
+ }
+
+ //returns true if the Piecewise<T> meets some basic invariants.
+ inline bool invariants() const {
+ // segs between cuts
+ if(!(segs.size() + 1 == cuts.size() || (segs.empty() && cuts.empty())))
+ return false;
+ // cuts in order
+ for(unsigned i = 0; i < segs.size(); i++)
+ if(cuts[i] >= cuts[i+1])
+ return false;
+ return true;
+ }
+
+};
+
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
+template<typename T>
+inline typename FragmentConcept<T>::BoundsType bounds_fast(const Piecewise<T> &f) {
+ boost::function_requires<FragmentConcept<T> >();
+
+ if(f.empty()) return typename FragmentConcept<T>::BoundsType();
+ typename FragmentConcept<T>::BoundsType ret(bounds_fast(f[0]));
+ for(unsigned i = 1; i < f.size(); i++)
+ ret.unionWith(bounds_fast(f[i]));
+ return ret;
+}
+
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
+template<typename T>
+inline typename FragmentConcept<T>::BoundsType bounds_exact(const Piecewise<T> &f) {
+ boost::function_requires<FragmentConcept<T> >();
+
+ if(f.empty()) return typename FragmentConcept<T>::BoundsType();
+ typename FragmentConcept<T>::BoundsType ret(bounds_exact(f[0]));
+ for(unsigned i = 1; i < f.size(); i++)
+ ret.unionWith(bounds_exact(f[i]));
+ return ret;
+}
+
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
+template<typename T>
+inline typename FragmentConcept<T>::BoundsType bounds_local(const Piecewise<T> &f, const OptInterval &_m) {
+ boost::function_requires<FragmentConcept<T> >();
+
+ if(f.empty() || !_m) return typename FragmentConcept<T>::BoundsType();
+ Interval const &m = *_m;
+ if(m.isSingular()) return typename FragmentConcept<T>::BoundsType(f(m.min()));
+
+ unsigned fi = f.segN(m.min()), ti = f.segN(m.max());
+ double ft = f.segT(m.min(), fi), tt = f.segT(m.max(), ti);
+
+ if(fi == ti) return bounds_local(f[fi], Interval(ft, tt));
+
+ typename FragmentConcept<T>::BoundsType ret(bounds_local(f[fi], Interval(ft, 1.)));
+ for(unsigned i = fi + 1; i < ti; i++)
+ ret.unionWith(bounds_exact(f[i]));
+ if(tt != 0.) ret.unionWith(bounds_local(f[ti], Interval(0., tt)));
+
+ return ret;
+}
+
+/**
+ * Returns a portion of a piece of a Piecewise<T>, given the piece's index and a to/from time.
+ * \relates Piecewise
+ */
+template<typename T>
+T elem_portion(const Piecewise<T> &a, unsigned i, double from, double to) {
+ assert(i < a.size());
+ double rwidth = 1 / (a.cuts[i+1] - a.cuts[i]);
+ return portion( a[i], (from - a.cuts[i]) * rwidth, (to - a.cuts[i]) * rwidth );
+}
+
+/**Piecewise<T> partition(const Piecewise<T> &pw, std::vector<double> const &c);
+ * Further subdivides the Piecewise<T> such that there is a cut at every value in c.
+ * Precondition: c sorted lower to higher.
+ *
+ * //Given Piecewise<T> a and b:
+ * Piecewise<T> ac = a.partition(b.cuts);
+ * Piecewise<T> bc = b.partition(a.cuts);
+ * //ac.cuts should be equivalent to bc.cuts
+ *
+ * \relates Piecewise
+ */
+template<typename T>
+Piecewise<T> partition(const Piecewise<T> &pw, std::vector<double> const &c) {
+ assert(pw.invariants());
+ if(c.empty()) return Piecewise<T>(pw);
+
+ Piecewise<T> ret = Piecewise<T>();
+ ret.reserve(c.size() + pw.cuts.size() - 1);
+
+ if(pw.empty()) {
+ ret.cuts = c;
+ for(unsigned i = 0; i < c.size() - 1; i++)
+ ret.push_seg(T());
+ return ret;
+ }
+
+ unsigned si = 0, ci = 0; //Segment index, Cut index
+
+ //if the cuts have something earlier than the Piecewise<T>, add portions of the first segment
+ while(ci < c.size() && c[ci] < pw.cuts.front()) {
+ bool isLast = (ci == c.size()-1 || c[ci + 1] >= pw.cuts.front());
+ ret.push_cut(c[ci]);
+ ret.push_seg( elem_portion(pw, 0, c[ci], isLast ? pw.cuts.front() : c[ci + 1]) );
+ ci++;
+ }
+
+ ret.push_cut(pw.cuts[0]);
+ double prev = pw.cuts[0]; //previous cut
+ //Loop which handles cuts within the Piecewise<T> domain
+ //Should have the cuts = segs + 1 invariant
+ while(si < pw.size() && ci <= c.size()) {
+ if(ci == c.size() && prev <= pw.cuts[si]) { //cuts exhausted, straight copy the rest
+ ret.segs.insert(ret.segs.end(), pw.segs.begin() + si, pw.segs.end());
+ ret.cuts.insert(ret.cuts.end(), pw.cuts.begin() + si + 1, pw.cuts.end());
+ return ret;
+ }else if(ci == c.size() || c[ci] >= pw.cuts[si + 1]) { //no more cuts within this segment, finalize
+ if(prev > pw.cuts[si]) { //segment already has cuts, so portion is required
+ ret.push_seg(portion(pw[si], pw.segT(prev, si), 1.0));
+ } else { //plain copy is fine
+ ret.push_seg(pw[si]);
+ }
+ ret.push_cut(pw.cuts[si + 1]);
+ prev = pw.cuts[si + 1];
+ si++;
+ } else if(c[ci] == pw.cuts[si]){ //coincident
+ //Already finalized the seg with the code immediately above
+ ci++;
+ } else { //plain old subdivision
+ ret.push(elem_portion(pw, si, prev, c[ci]), c[ci]);
+ prev = c[ci];
+ ci++;
+ }
+ }
+
+ //input cuts extend further than this Piecewise<T>, extend the last segment.
+ while(ci < c.size()) {
+ if(c[ci] > prev) {
+ ret.push(elem_portion(pw, pw.size() - 1, prev, c[ci]), c[ci]);
+ prev = c[ci];
+ }
+ ci++;
+ }
+ return ret;
+}
+
+/**
+ * Returns a Piecewise<T> with a defined domain of [min(from, to), max(from, to)].
+ * \relates Piecewise
+ */
+template<typename T>
+Piecewise<T> portion(const Piecewise<T> &pw, double from, double to) {
+ if(pw.empty() || from == to) return Piecewise<T>();
+
+ Piecewise<T> ret;
+
+ double temp = from;
+ from = std::min(from, to);
+ to = std::max(temp, to);
+
+ unsigned i = pw.segN(from);
+ ret.push_cut(from);
+ if(i == pw.size() - 1 || to <= pw.cuts[i + 1]) { //to/from inhabit the same segment
+ ret.push(elem_portion(pw, i, from, to), to);
+ return ret;
+ }
+ ret.push_seg(portion( pw[i], pw.segT(from, i), 1.0 ));
+ i++;
+ unsigned fi = pw.segN(to, i);
+ ret.reserve(fi - i + 1);
+ if (to == pw.cuts[fi]) fi-=1;
+
+ ret.segs.insert(ret.segs.end(), pw.segs.begin() + i, pw.segs.begin() + fi); //copy segs
+ ret.cuts.insert(ret.cuts.end(), pw.cuts.begin() + i, pw.cuts.begin() + fi + 1); //and their cuts
+
+ ret.push_seg( portion(pw[fi], 0.0, pw.segT(to, fi)));
+ if(to != ret.cuts.back()) ret.push_cut(to);
+ ret.invariants();
+ return ret;
+}
+
+//TODO: seems like these should be mutating
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
+template<typename T>
+Piecewise<T> remove_short_cuts(Piecewise<T> const &f, double tol) {
+ if(f.empty()) return f;
+ Piecewise<T> ret;
+ ret.reserve(f.size());
+ ret.push_cut(f.cuts[0]);
+ for(unsigned i=0; i<f.size(); i++){
+ if (f.cuts[i+1]-f.cuts[i] >= tol || i==f.size()-1) {
+ ret.push(f[i], f.cuts[i+1]);
+ }
+ }
+ return ret;
+}
+
+//TODO: seems like these should be mutating
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
+template<typename T>
+Piecewise<T> remove_short_cuts_extending(Piecewise<T> const &f, double tol) {
+ if(f.empty()) return f;
+ Piecewise<T> ret;
+ ret.reserve(f.size());
+ ret.push_cut(f.cuts[0]);
+ double last = f.cuts[0]; // last cut included
+ for(unsigned i=0; i<f.size(); i++){
+ if (f.cuts[i+1]-f.cuts[i] >= tol) {
+ ret.push(elem_portion(f, i, last, f.cuts[i+1]), f.cuts[i+1]);
+ last = f.cuts[i+1];
+ }
+ }
+ return ret;
+}
+
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
+template<typename T>
+std::vector<double> roots(const Piecewise<T> &pw) {
+ std::vector<double> ret;
+ for(unsigned i = 0; i < pw.size(); i++) {
+ std::vector<double> sr = roots(pw[i]);
+ for (double & j : sr) ret.push_back(j * (pw.cuts[i + 1] - pw.cuts[i]) + pw.cuts[i]);
+
+ }
+ return ret;
+}
+
+//IMPL: OffsetableConcept
+/**
+ * ...
+ * \return \f$ a + b = \f$
+ * \relates Piecewise
+ */
+template<typename T>
+Piecewise<T> operator+(Piecewise<T> const &a, typename T::output_type b) {
+ boost::function_requires<OffsetableConcept<T> >();
+//TODO:empty
+ Piecewise<T> ret;
+ ret.segs.reserve(a.size());
+ ret.cuts = a.cuts;
+ for(unsigned i = 0; i < a.size();i++)
+ ret.push_seg(a[i] + b);
+ return ret;
+}
+template<typename T>
+Piecewise<T> operator-(Piecewise<T> const &a, typename T::output_type b) {
+ boost::function_requires<OffsetableConcept<T> >();
+//TODO: empty
+ Piecewise<T> ret;
+ ret.segs.reserve(a.size());
+ ret.cuts = a.cuts;
+ for(unsigned i = 0; i < a.size();i++)
+ ret.push_seg(a[i] - b);
+ return ret;
+}
+template<typename T>
+Piecewise<T>& operator+=(Piecewise<T>& a, typename T::output_type b) {
+ boost::function_requires<OffsetableConcept<T> >();
+
+ if(a.empty()) { a.push_cut(0.); a.push(T(b), 1.); return a; }
+
+ for(unsigned i = 0; i < a.size();i++)
+ a[i] += b;
+ return a;
+}
+template<typename T>
+Piecewise<T>& operator-=(Piecewise<T>& a, typename T::output_type b) {
+ boost::function_requires<OffsetableConcept<T> >();
+
+ if(a.empty()) { a.push_cut(0.); a.push(T(-b), 1.); return a; }
+
+ for(unsigned i = 0;i < a.size();i++)
+ a[i] -= b;
+ return a;
+}
+
+//IMPL: ScalableConcept
+/**
+ * ...
+ * \return \f$ -a = \f$
+ * \relates Piecewise
+ */
+template<typename T>
+Piecewise<T> operator-(Piecewise<T> const &a) {
+ boost::function_requires<ScalableConcept<T> >();
+
+ Piecewise<T> ret;
+ ret.segs.reserve(a.size());
+ ret.cuts = a.cuts;
+ for(unsigned i = 0; i < a.size();i++)
+ ret.push_seg(- a[i]);
+ return ret;
+}
+/**
+ * ...
+ * \return \f$ a * b = \f$
+ * \relates Piecewise
+ */
+template<typename T>
+Piecewise<T> operator*(Piecewise<T> const &a, double b) {
+ boost::function_requires<ScalableConcept<T> >();
+
+ if(a.empty()) return Piecewise<T>();
+
+ Piecewise<T> ret;
+ ret.segs.reserve(a.size());
+ ret.cuts = a.cuts;
+ for(unsigned i = 0; i < a.size();i++)
+ ret.push_seg(a[i] * b);
+ return ret;
+}
+/**
+ * ...
+ * \return \f$ a * b = \f$
+ * \relates Piecewise
+ */
+template<typename T>
+Piecewise<T> operator*(Piecewise<T> const &a, T b) {
+ boost::function_requires<ScalableConcept<T> >();
+
+ if(a.empty()) return Piecewise<T>();
+
+ Piecewise<T> ret;
+ ret.segs.reserve(a.size());
+ ret.cuts = a.cuts;
+ for(unsigned i = 0; i < a.size();i++)
+ ret.push_seg(a[i] * b);
+ return ret;
+}
+/**
+ * ...
+ * \return \f$ a / b = \f$
+ * \relates Piecewise
+ */
+template<typename T>
+Piecewise<T> operator/(Piecewise<T> const &a, double b) {
+ boost::function_requires<ScalableConcept<T> >();
+
+ //FIXME: b == 0?
+ if(a.empty()) return Piecewise<T>();
+
+ Piecewise<T> ret;
+ ret.segs.reserve(a.size());
+ ret.cuts = a.cuts;
+ for(unsigned i = 0; i < a.size();i++)
+ ret.push_seg(a[i] / b);
+ return ret;
+}
+template<typename T>
+Piecewise<T>& operator*=(Piecewise<T>& a, double b) {
+ boost::function_requires<ScalableConcept<T> >();
+
+ for(unsigned i = 0; i < a.size();i++)
+ a[i] *= b;
+ return a;
+}
+template<typename T>
+Piecewise<T>& operator/=(Piecewise<T>& a, double b) {
+ boost::function_requires<ScalableConcept<T> >();
+
+ //FIXME: b == 0?
+
+ for(unsigned i = 0; i < a.size();i++)
+ a[i] /= b;
+ return a;
+}
+
+//IMPL: AddableConcept
+/**
+ * ...
+ * \return \f$ a + b = \f$
+ * \relates Piecewise
+ */
+template<typename T>
+Piecewise<T> operator+(Piecewise<T> const &a, Piecewise<T> const &b) {
+ boost::function_requires<AddableConcept<T> >();
+
+ Piecewise<T> pa = partition(a, b.cuts), pb = partition(b, a.cuts);
+ Piecewise<T> ret;
+ assert(pa.size() == pb.size());
+ ret.segs.reserve(pa.size());
+ ret.cuts = pa.cuts;
+ for (unsigned i = 0; i < pa.size(); i++)
+ ret.push_seg(pa[i] + pb[i]);
+ return ret;
+}
+/**
+ * ...
+ * \return \f$ a - b = \f$
+ * \relates Piecewise
+ */
+template<typename T>
+Piecewise<T> operator-(Piecewise<T> const &a, Piecewise<T> const &b) {
+ boost::function_requires<AddableConcept<T> >();
+
+ Piecewise<T> pa = partition(a, b.cuts), pb = partition(b, a.cuts);
+ Piecewise<T> ret = Piecewise<T>();
+ assert(pa.size() == pb.size());
+ ret.segs.reserve(pa.size());
+ ret.cuts = pa.cuts;
+ for (unsigned i = 0; i < pa.size(); i++)
+ ret.push_seg(pa[i] - pb[i]);
+ return ret;
+}
+template<typename T>
+inline Piecewise<T>& operator+=(Piecewise<T> &a, Piecewise<T> const &b) {
+ a = a+b;
+ return a;
+}
+template<typename T>
+inline Piecewise<T>& operator-=(Piecewise<T> &a, Piecewise<T> const &b) {
+ a = a-b;
+ return a;
+}
+
+/**
+ * ...
+ * \return \f$ a \cdot b = \f$
+ * \relates Piecewise
+ */
+template<typename T1,typename T2>
+Piecewise<T2> operator*(Piecewise<T1> const &a, Piecewise<T2> const &b) {
+ //function_requires<MultiplicableConcept<T1> >();
+ //function_requires<MultiplicableConcept<T2> >();
+
+ Piecewise<T1> pa = partition(a, b.cuts);
+ Piecewise<T2> pb = partition(b, a.cuts);
+ Piecewise<T2> ret = Piecewise<T2>();
+ assert(pa.size() == pb.size());
+ ret.segs.reserve(pa.size());
+ ret.cuts = pa.cuts;
+ for (unsigned i = 0; i < pa.size(); i++)
+ ret.push_seg(pa[i] * pb[i]);
+ return ret;
+}
+
+/**
+ * ...
+ * \return \f$ a \cdot b \f$
+ * \relates Piecewise
+ */
+template<typename T>
+inline Piecewise<T>& operator*=(Piecewise<T> &a, Piecewise<T> const &b) {
+ a = a * b;
+ return a;
+}
+
+Piecewise<SBasis> divide(Piecewise<SBasis> const &a, Piecewise<SBasis> const &b, unsigned k);
+//TODO: replace divide(a,b,k) by divide(a,b,tol,k)?
+//TODO: atm, relative error is ~(tol/a)%. Find a way to make it independent of a.
+//Nota: the result is 'truncated' where b is smaller than 'zero': ~ a/max(b,zero).
+Piecewise<SBasis>
+divide(Piecewise<SBasis> const &a, Piecewise<SBasis> const &b, double tol, unsigned k, double zero=1.e-3);
+Piecewise<SBasis>
+divide(SBasis const &a, Piecewise<SBasis> const &b, double tol, unsigned k, double zero=1.e-3);
+Piecewise<SBasis>
+divide(Piecewise<SBasis> const &a, SBasis const &b, double tol, unsigned k, double zero=1.e-3);
+Piecewise<SBasis>
+divide(SBasis const &a, SBasis const &b, double tol, unsigned k, double zero=1.e-3);
+
+//Composition: functions called compose_* are pieces of compose that are factored out in pw.cpp.
+std::map<double,unsigned> compose_pullback(std::vector<double> const &cuts, SBasis const &g);
+int compose_findSegIdx(std::map<double,unsigned>::iterator const &cut,
+ std::map<double,unsigned>::iterator const &next,
+ std::vector<double> const &levels,
+ SBasis const &g);
+
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
+template<typename T>
+Piecewise<T> compose(Piecewise<T> const &f, SBasis const &g){
+ /// \todo add concept check
+ Piecewise<T> result;
+ if (f.empty()) return result;
+ if (g.isZero()) return Piecewise<T>(f(0));
+ if (f.size()==1){
+ double t0 = f.cuts[0], width = f.cuts[1] - t0;
+ return (Piecewise<T>) compose(f.segs[0],compose(Linear(-t0 / width, (1-t0) / width), g));
+ }
+
+ //first check bounds...
+ Interval bs = *bounds_fast(g);
+ if (f.cuts.front() > bs.max() || bs.min() > f.cuts.back()){
+ int idx = (bs.max() < f.cuts[1]) ? 0 : f.cuts.size()-2;
+ double t0 = f.cuts[idx], width = f.cuts[idx+1] - t0;
+ return (Piecewise<T>) compose(f.segs[idx],compose(Linear(-t0 / width, (1-t0) / width), g));
+ }
+
+ std::vector<double> levels;//we can forget first and last cuts...
+ levels.insert(levels.begin(),f.cuts.begin()+1,f.cuts.end()-1);
+ //TODO: use a std::vector<pairs<double,unsigned> > instead of a map<double,unsigned>.
+ std::map<double,unsigned> cuts_pb = compose_pullback(levels,g);
+
+ //-- Compose each piece of g with the relevant seg of f.
+ result.cuts.push_back(0.);
+ std::map<double,unsigned>::iterator cut=cuts_pb.begin();
+ std::map<double,unsigned>::iterator next=cut; next++;
+ while(next!=cuts_pb.end()){
+ //assert(std::abs(int((*cut).second-(*next).second))<1);
+ //TODO: find a way to recover from this error? the root finder missed some root;
+ // the levels/variations of f might be too close/fast...
+ int idx = compose_findSegIdx(cut,next,levels,g);
+ double t0=(*cut).first;
+ double t1=(*next).first;
+
+ if (!are_near(t0,t1,EPSILON*EPSILON)) { // prevent adding cuts that are extremely close together and that may cause trouble with rounding e.g. when reversing the path
+ SBasis sub_g=compose(g, Linear(t0,t1));
+ sub_g=compose(Linear(-f.cuts[idx]/(f.cuts[idx+1]-f.cuts[idx]),
+ (1-f.cuts[idx])/(f.cuts[idx+1]-f.cuts[idx])),sub_g);
+ result.push(compose(f[idx],sub_g),t1);
+ }
+
+ cut++;
+ next++;
+ }
+ return(result);
+}
+
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
+template<typename T>
+Piecewise<T> compose(Piecewise<T> const &f, Piecewise<SBasis> const &g){
+/// \todo add concept check
+ Piecewise<T> result;
+ for(unsigned i = 0; i < g.segs.size(); i++){
+ Piecewise<T> fgi=compose(f, g.segs[i]);
+ fgi.setDomain(Interval(g.cuts[i], g.cuts[i+1]));
+ result.concat(fgi);
+ }
+ return result;
+}
+
+/*
+Piecewise<D2<SBasis> > compose(D2<SBasis2d> const &sb2d, Piecewise<D2<SBasis> > const &pwd2sb){
+/// \todo add concept check
+ Piecewise<D2<SBasis> > result;
+ result.push_cut(0.);
+ for(unsigned i = 0; i < pwd2sb.size(); i++){
+ result.push(compose_each(sb2d,pwd2sb[i]),i+1);
+ }
+ return result;
+}*/
+
+/** Compose an SBasis with the inverse of another.
+ * WARNING: It's up to the user to check that the second SBasis is indeed
+ * invertible (i.e. strictly increasing or decreasing).
+ * \return \f$ f \cdot g^{-1} \f$
+ * \relates Piecewise
+ */
+Piecewise<SBasis> pw_compose_inverse(SBasis const &f, SBasis const &g, unsigned order, double zero);
+
+
+
+template <typename T>
+Piecewise<T> Piecewise<T>::operator()(SBasis f){return compose((*this),f);}
+template <typename T>
+Piecewise<T> Piecewise<T>::operator()(Piecewise<SBasis>f){return compose((*this),f);}
+
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
+template<typename T>
+Piecewise<T> integral(Piecewise<T> const &a) {
+ Piecewise<T> result;
+ result.segs.resize(a.segs.size());
+ result.cuts = a.cuts;
+ typename T::output_type c = a.segs[0].at0();
+ for(unsigned i = 0; i < a.segs.size(); i++){
+ result.segs[i] = integral(a.segs[i])*(a.cuts[i+1]-a.cuts[i]);
+ result.segs[i]+= c-result.segs[i].at0();
+ c = result.segs[i].at1();
+ }
+ return result;
+}
+
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
+template<typename T>
+Piecewise<T> derivative(Piecewise<T> const &a) {
+ Piecewise<T> result;
+ result.segs.resize(a.segs.size());
+ result.cuts = a.cuts;
+ for(unsigned i = 0; i < a.segs.size(); i++){
+ result.segs[i] = derivative(a.segs[i])/(a.cuts[i+1]-a.cuts[i]);
+ }
+ return result;
+}
+
+std::vector<double> roots(Piecewise<SBasis> const &f);
+
+std::vector<std::vector<double> >multi_roots(Piecewise<SBasis> const &f, std::vector<double> const &values);
+
+//TODO: implement level_sets directly for pwsb instead of sb (and derive it fo sb).
+//It should be faster than the reverse as the algorithm may jump over full cut intervals.
+std::vector<Interval> level_set(Piecewise<SBasis> const &f, Interval const &level, double tol=1e-5);
+std::vector<Interval> level_set(Piecewise<SBasis> const &f, double v, double vtol, double tol=1e-5);
+//std::vector<Interval> level_sets(Piecewise<SBasis> const &f, std::vector<Interval> const &levels, double tol=1e-5);
+//std::vector<Interval> level_sets(Piecewise<SBasis> const &f, std::vector<double> &v, double vtol, double tol=1e-5);
+
+
+/**
+ * ...
+ * \return ...
+ * \relates Piecewise
+ */
+template<typename T>
+Piecewise<T> reverse(Piecewise<T> const &f) {
+ Piecewise<T> ret = Piecewise<T>();
+ ret.reserve(f.size());
+ double start = f.cuts[0];
+ double end = f.cuts.back();
+ for (unsigned i = 0; i < f.cuts.size(); i++) {
+ double x = f.cuts[f.cuts.size() - 1 - i];
+ ret.push_cut(end - (x - start));
+ }
+ for (unsigned i = 0; i < f.segs.size(); i++)
+ ret.push_seg(reverse(f[f.segs.size() - i - 1]));
+ return ret;
+}
+
+/**
+ * Interpolates between a and b.
+ * \return a if t = 0, b if t = 1, or an interpolation between a and b for t in [0,1]
+ * \relates Piecewise
+ */
+template<typename T>
+Piecewise<T> lerp(double t, Piecewise<T> const &a, Piecewise<T> b) {
+ // Make sure both paths have the same number of segments and cuts at the same locations
+ b.setDomain(a.domain());
+ Piecewise<T> pA = partition(a, b.cuts);
+ Piecewise<T> pB = partition(b, a.cuts);
+
+ return (pA*(1-t) + pB*t);
+}
+
+}
+#endif //LIB2GEOM_SEEN_PIECEWISE_H
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/point.h b/src/3rdparty/2geom/include/2geom/point.h
new file mode 100644
index 0000000..3a29066
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/point.h
@@ -0,0 +1,449 @@
+/** @file
+ * @brief Cartesian point / 2D vector and related operations
+ *//*
+ * Authors:
+ * Michael G. Sloan <mgsloan@gmail.com>
+ * Nathan Hurst <njh@njhurst.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2006-2009 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_POINT_H
+#define LIB2GEOM_SEEN_POINT_H
+
+#include <iostream>
+#include <iterator>
+#include <boost/operators.hpp>
+#include <2geom/forward.h>
+#include <2geom/coord.h>
+#include <2geom/int-point.h>
+#include <2geom/math-utils.h>
+#include <2geom/utils.h>
+
+namespace Geom {
+
+class Point
+ : boost::additive< Point
+ , boost::totally_ordered< Point
+ , boost::multiplicative< Point, Coord
+ , boost::multiplicative< Point
+ , boost::multiplicative< Point, IntPoint
+ , MultipliableNoncommutative< Point, Affine
+ , MultipliableNoncommutative< Point, Translate
+ , MultipliableNoncommutative< Point, Rotate
+ , MultipliableNoncommutative< Point, Scale
+ , MultipliableNoncommutative< Point, HShear
+ , MultipliableNoncommutative< Point, VShear
+ , MultipliableNoncommutative< Point, Zoom
+ > > > > > > > > > > > > // base class chaining, see documentation for Boost.Operator
+{
+ Coord _pt[2] = { 0, 0 };
+public:
+ using D1Value = Coord;
+ using D1Reference = Coord &;
+ using D1ConstReference = Coord const &;
+
+ /// @name Create points
+ /// @{
+ /** Construct a point at the origin. */
+ Point() = default;
+ /** Construct a point from its coordinates. */
+ Point(Coord x, Coord y)
+ : _pt{ x, y }
+ {}
+ /** Construct from integer point. */
+ Point(IntPoint const &p)
+ : Point(p[X], p[Y])
+ {}
+ /** @brief Construct a point from its polar coordinates.
+ * The angle is specified in radians, in the mathematical convention (increasing
+ * counter-clockwise from +X). */
+ static Point polar(Coord angle, Coord radius) {
+ Point ret(polar(angle));
+ ret *= radius;
+ return ret;
+ }
+ /** @brief Construct an unit vector from its angle.
+ * The angle is specified in radians, in the mathematical convention (increasing
+ * counter-clockwise from +X). */
+ static Point polar(Coord angle);
+ /// @}
+
+ /// @name Access the coordinates of a point
+ /// @{
+ Coord operator[](unsigned i) const { return _pt[i]; }
+ Coord &operator[](unsigned i) { return _pt[i]; }
+
+ Coord operator[](Dim2 d) const noexcept { return _pt[d]; }
+ Coord &operator[](Dim2 d) noexcept { return _pt[d]; }
+
+ Coord x() const noexcept { return _pt[X]; }
+ Coord &x() noexcept { return _pt[X]; }
+ Coord y() const noexcept { return _pt[Y]; }
+ Coord &y() noexcept { return _pt[Y]; }
+ /// @}
+
+ /// @name Vector operations
+ /// @{
+ /** @brief Compute the distance from origin.
+ * @return Length of the vector from origin to this point */
+ Coord length() const { return std::hypot(_pt[0], _pt[1]); }
+ void normalize();
+ Point normalized() const {
+ Point ret(*this);
+ ret.normalize();
+ return ret;
+ }
+
+ /** @brief Return a point like this point but rotated -90 degrees.
+ * If the y axis grows downwards and the x axis grows to the
+ * right, then this is 90 degrees counter-clockwise. */
+ Point ccw() const {
+ return Point(_pt[Y], -_pt[X]);
+ }
+
+ /** @brief Return a point like this point but rotated +90 degrees.
+ * If the y axis grows downwards and the x axis grows to the
+ * right, then this is 90 degrees clockwise. */
+ Point cw() const {
+ return Point(-_pt[Y], _pt[X]);
+ }
+ /// @}
+
+ /// @name Vector-like arithmetic operations
+ /// @{
+ Point operator-() const {
+ return Point(-_pt[X], -_pt[Y]);
+ }
+ Point &operator+=(Point const &o) {
+ _pt[X] += o._pt[X];
+ _pt[Y] += o._pt[Y];
+ return *this;
+ }
+ Point &operator-=(Point const &o) {
+ _pt[X] -= o._pt[X];
+ _pt[Y] -= o._pt[Y];
+ return *this;
+ }
+ Point &operator*=(Coord s) {
+ for (double & i : _pt) i *= s;
+ return *this;
+ }
+ Point &operator*=(Point const &o) {
+ _pt[X] *= o._pt[X];
+ _pt[Y] *= o._pt[Y];
+ return *this;
+ }
+ Point &operator*=(IntPoint const &o) {
+ _pt[X] *= o.x();
+ _pt[Y] *= o.y();
+ return *this;
+ }
+ Point &operator/=(Coord s) {
+ //TODO: s == 0?
+ for (double & i : _pt) i /= s;
+ return *this;
+ }
+ Point &operator/=(Point const &o) {
+ _pt[X] /= o._pt[X];
+ _pt[Y] /= o._pt[Y];
+ return *this;
+ }
+ Point &operator/=(IntPoint const &o) {
+ _pt[X] /= o.x();
+ _pt[Y] /= o.y();
+ return *this;
+ }
+ /// @}
+
+ /// @name Affine transformations
+ /// @{
+ Point &operator*=(Affine const &m);
+ // implemented in transforms.cpp
+ Point &operator*=(Translate const &t);
+ Point &operator*=(Scale const &s);
+ Point &operator*=(Rotate const &r);
+ Point &operator*=(HShear const &s);
+ Point &operator*=(VShear const &s);
+ Point &operator*=(Zoom const &z);
+ /// @}
+
+ /// @name Conversion to integer points
+ /// @{
+ /** @brief Round to nearest integer coordinates. */
+ IntPoint round() const {
+ IntPoint ret(::round(_pt[X]), ::round(_pt[Y]));
+ return ret;
+ }
+ /** @brief Round coordinates downwards. */
+ IntPoint floor() const {
+ IntPoint ret(::floor(_pt[X]), ::floor(_pt[Y]));
+ return ret;
+ }
+ /** @brief Round coordinates upwards. */
+ IntPoint ceil() const {
+ IntPoint ret(::ceil(_pt[X]), ::ceil(_pt[Y]));
+ return ret;
+ }
+ /// @}
+
+ /// @name Various utilities
+ /// @{
+ /** @brief Check whether both coordinates are finite. */
+ bool isFinite() const {
+ for (double i : _pt) {
+ if(!std::isfinite(i)) return false;
+ }
+ return true;
+ }
+ /** @brief Check whether both coordinates are zero. */
+ bool isZero() const {
+ return _pt[X] == 0 && _pt[Y] == 0;
+ }
+ /** @brief Check whether the length of the vector is close to 1. */
+ bool isNormalized(Coord eps=EPSILON) const {
+ return are_near(length(), 1.0, eps);
+ }
+ /** @brief Equality operator.
+ * This tests for exact identity (as opposed to are_near()). Note that due to numerical
+ * errors, this test might return false even if the points should be identical. */
+ bool operator==(const Point &in_pnt) const {
+ return (_pt[X] == in_pnt[X]) && (_pt[Y] == in_pnt[Y]);
+ }
+ /** @brief Lexicographical ordering for points.
+ * Y coordinate is regarded as more significant. When sorting according to this
+ * ordering, the points will be sorted according to the Y coordinate, and within
+ * points with the same Y coordinate according to the X coordinate. */
+ bool operator<(const Point &p) const {
+ return _pt[Y] < p[Y] || (_pt[Y] == p[Y] && _pt[X] < p[X]);
+ }
+ /// @}
+
+ /** @brief Lexicographical ordering functor.
+ * @param d The dimension with higher significance */
+ template <Dim2 DIM> struct LexLess;
+ template <Dim2 DIM> struct LexGreater;
+ //template <Dim2 DIM, typename First = std::less<Coord>, typename Second = std::less<Coord> > LexOrder;
+ /** @brief Lexicographical ordering functor with runtime dimension. */
+ struct LexLessRt {
+ LexLessRt(Dim2 d) : dim(d) {}
+ inline bool operator()(Point const &a, Point const &b) const;
+ private:
+ Dim2 dim;
+ };
+ struct LexGreaterRt {
+ LexGreaterRt(Dim2 d) : dim(d) {}
+ inline bool operator()(Point const &a, Point const &b) const;
+ private:
+ Dim2 dim;
+ };
+ //template <typename First = std::less<Coord>, typename Second = std::less<Coord> > LexOrder
+};
+
+/** @brief Output operator for points.
+ * Prints out the coordinates.
+ * @relates Point */
+std::ostream &operator<<(std::ostream &out, const Geom::Point &p);
+
+template<> struct Point::LexLess<X> {
+ typedef std::less<Coord> Primary;
+ typedef std::less<Coord> Secondary;
+ typedef std::less<Coord> XOrder;
+ typedef std::less<Coord> YOrder;
+ bool operator()(Point const &a, Point const &b) const {
+ return a[X] < b[X] || (a[X] == b[X] && a[Y] < b[Y]);
+ }
+};
+template<> struct Point::LexLess<Y> {
+ typedef std::less<Coord> Primary;
+ typedef std::less<Coord> Secondary;
+ typedef std::less<Coord> XOrder;
+ typedef std::less<Coord> YOrder;
+ bool operator()(Point const &a, Point const &b) const {
+ return a[Y] < b[Y] || (a[Y] == b[Y] && a[X] < b[X]);
+ }
+};
+template<> struct Point::LexGreater<X> {
+ typedef std::greater<Coord> Primary;
+ typedef std::greater<Coord> Secondary;
+ typedef std::greater<Coord> XOrder;
+ typedef std::greater<Coord> YOrder;
+ bool operator()(Point const &a, Point const &b) const {
+ return a[X] > b[X] || (a[X] == b[X] && a[Y] > b[Y]);
+ }
+};
+template<> struct Point::LexGreater<Y> {
+ typedef std::greater<Coord> Primary;
+ typedef std::greater<Coord> Secondary;
+ typedef std::greater<Coord> XOrder;
+ typedef std::greater<Coord> YOrder;
+ bool operator()(Point const &a, Point const &b) const {
+ return a[Y] > b[Y] || (a[Y] == b[Y] && a[X] > b[X]);
+ }
+};
+inline bool Point::LexLessRt::operator()(Point const &a, Point const &b) const {
+ return dim ? Point::LexLess<Y>()(a, b) : Point::LexLess<X>()(a, b);
+}
+inline bool Point::LexGreaterRt::operator()(Point const &a, Point const &b) const {
+ return dim ? Point::LexGreater<Y>()(a, b) : Point::LexGreater<X>()(a, b);
+}
+
+/** @brief Compute the second (Euclidean) norm of @a p.
+ * This corresponds to the length of @a p. The result will not overflow even if
+ * \f$p_X^2 + p_Y^2\f$ is larger that the maximum value that can be stored
+ * in a <code>double</code>.
+ * @return \f$\sqrt{p_X^2 + p_Y^2}\f$
+ * @relates Point */
+inline Coord L2(Point const &p) {
+ return p.length();
+}
+
+/** @brief Compute the square of the Euclidean norm of @a p.
+ * Warning: this can overflow where L2 won't.
+ * @return \f$p_X^2 + p_Y^2\f$
+ * @relates Point */
+inline Coord L2sq(Point const &p) {
+ return p[0]*p[0] + p[1]*p[1];
+}
+
+/** @brief Returns p * Geom::rotate_degrees(90), but more efficient.
+ *
+ * Angle direction in 2Geom: If you use the traditional mathematics convention that y
+ * increases upwards, then positive angles are anticlockwise as per the mathematics convention. If
+ * you take the common non-mathematical convention that y increases downwards, then positive angles
+ * are clockwise, as is common outside of mathematics.
+ *
+ * There is no function to rotate by -90 degrees: use -rot90(p) instead.
+ * @relates Point */
+inline Point rot90(Point const &p) {
+ return Point(-p[Y], p[X]);
+}
+
+/** @brief Linear interpolation between two points.
+ * @param t Time value
+ * @param a First point
+ * @param b Second point
+ * @return Point on a line between a and b. The ratio of its distance from a
+ * and the distance between a and b will be equal to t.
+ * @relates Point */
+inline Point lerp(Coord t, Point const &a, Point const &b) {
+ return (1 - t) * a + t * b;
+}
+
+/** @brief Return a point halfway between the specified ones.
+ * @relates Point */
+inline Point middle_point(Point const &p1, Point const &p2) {
+ return lerp(0.5, p1, p2);
+}
+
+/** @brief Compute the dot product of a and b.
+ * Dot product can be interpreted as a measure of how parallel the vectors are.
+ * For perpendicular vectors, it is zero. For parallel ones, its absolute value is highest,
+ * and the sign depends on whether they point in the same direction (+) or opposite ones (-).
+ * @return \f$a \cdot b = a_X b_X + a_Y b_Y\f$.
+ * @relates Point */
+inline Coord dot(Point const &a, Point const &b) {
+ return a[X] * b[X] + a[Y] * b[Y];
+}
+
+/** @brief Compute the 2D cross product.
+ * This is also known as "perp dot product". It will be zero for parallel vectors,
+ * and the absolute value will be highest for perpendicular vectors.
+ * @return \f$a \times b = a_X b_Y - a_Y b_X\f$.
+ * @relates Point*/
+inline Coord cross(Point const &a, Point const &b)
+{
+ // equivalent implementation:
+ // return dot(a, b.ccw());
+ return a[X] * b[Y] - a[Y] * b[X];
+}
+
+/// Compute the (Euclidean) distance between points.
+/// @relates Point
+inline Coord distance (Point const &a, Point const &b) {
+ return (a - b).length();
+}
+
+/// Compute the square of the distance between points.
+/// @relates Point
+inline Coord distanceSq (Point const &a, Point const &b) {
+ return L2sq(a - b);
+}
+
+//IMPL: NearConcept
+/// Test whether two points are no further apart than some threshold.
+/// @relates Point
+inline bool are_near(Point const &a, Point const &b, double eps = EPSILON) {
+ // do not use an unqualified calls to distance before the empty
+ // specialization of iterator_traits is defined - see end of file
+ return are_near((a - b).length(), 0, eps);
+}
+
+/// Test whether the relative distance between two points is less than some threshold.
+inline bool are_near_rel(Point const &a, Point const &b, double eps = EPSILON) {
+ return (a - b).length() <= eps * (a.length() + b.length()) / 2;
+}
+
+/// Test whether three points lie approximately on the same line.
+/// @relates Point
+inline bool are_collinear(Point const& p1, Point const& p2, Point const& p3,
+ double eps = EPSILON)
+{
+ return are_near( cross(p3, p2) - cross(p3, p1) + cross(p2, p1), 0, eps);
+}
+
+Point unit_vector(Point const &a);
+Coord L1(Point const &p);
+Coord LInfty(Point const &p);
+bool is_zero(Point const &p);
+bool is_unit_vector(Point const &p, Coord eps = EPSILON);
+double atan2(Point const &p);
+double angle_between(Point const &a, Point const &b);
+Point abs(Point const &b);
+Point constrain_angle(Point const &A, Point const &B, unsigned int n = 4, Geom::Point const &dir = Geom::Point(1,0));
+
+} // end namespace Geom
+
+// This is required to fix a bug in GCC 4.3.3 (and probably others) that causes the compiler
+// to try to instantiate the iterator_traits template and fail. Probably it thinks that Point
+// is an iterator and tries to use std::distance instead of Geom::distance.
+namespace std {
+template <> class iterator_traits<Geom::Point> {};
+}
+
+#endif // LIB2GEOM_SEEN_POINT_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/polynomial.h b/src/3rdparty/2geom/include/2geom/polynomial.h
new file mode 100644
index 0000000..640cab6
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/polynomial.h
@@ -0,0 +1,264 @@
+/**
+ * \file
+ * \brief Polynomial in canonical (monomial) basis
+ *//*
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2007-2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_POLY_H
+#define LIB2GEOM_SEEN_POLY_H
+#include <assert.h>
+#include <vector>
+#include <iostream>
+#include <algorithm>
+#include <complex>
+#include <2geom/coord.h>
+#include <2geom/utils.h>
+
+namespace Geom {
+
+/** @brief Polynomial in canonical (monomial) basis.
+ * @ingroup Fragments */
+class Poly : public std::vector<double>{
+public:
+ // coeff; // sum x^i*coeff[i]
+
+ //unsigned size() const { return coeff.size();}
+ unsigned degree() const { return size()-1;}
+
+ //double operator[](const int i) const { return (*this)[i];}
+ //double& operator[](const int i) { return (*this)[i];}
+
+ Poly operator+(const Poly& p) const {
+ Poly result;
+ const unsigned out_size = std::max(size(), p.size());
+ const unsigned min_size = std::min(size(), p.size());
+ result.reserve(out_size);
+
+ for(unsigned i = 0; i < min_size; i++) {
+ result.push_back((*this)[i] + p[i]);
+ }
+ for(unsigned i = min_size; i < size(); i++)
+ result.push_back((*this)[i]);
+ for(unsigned i = min_size; i < p.size(); i++)
+ result.push_back(p[i]);
+ assert(result.size() == out_size);
+ return result;
+ }
+ Poly operator-(const Poly& p) const {
+ Poly result;
+ const unsigned out_size = std::max(size(), p.size());
+ const unsigned min_size = std::min(size(), p.size());
+ result.reserve(out_size);
+
+ for(unsigned i = 0; i < min_size; i++) {
+ result.push_back((*this)[i] - p[i]);
+ }
+ for(unsigned i = min_size; i < size(); i++)
+ result.push_back((*this)[i]);
+ for(unsigned i = min_size; i < p.size(); i++)
+ result.push_back(-p[i]);
+ assert(result.size() == out_size);
+ return result;
+ }
+ Poly operator-=(const Poly& p) {
+ const unsigned out_size = std::max(size(), p.size());
+ const unsigned min_size = std::min(size(), p.size());
+ resize(out_size);
+
+ for(unsigned i = 0; i < min_size; i++) {
+ (*this)[i] -= p[i];
+ }
+ for(unsigned i = min_size; i < out_size; i++)
+ (*this)[i] = -p[i];
+ return *this;
+ }
+ Poly operator-(const double k) const {
+ Poly result;
+ const unsigned out_size = size();
+ result.reserve(out_size);
+
+ for(unsigned i = 0; i < out_size; i++) {
+ result.push_back((*this)[i]);
+ }
+ result[0] -= k;
+ return result;
+ }
+ Poly operator-() const {
+ Poly result;
+ result.resize(size());
+
+ for(unsigned i = 0; i < size(); i++) {
+ result[i] = -(*this)[i];
+ }
+ return result;
+ }
+ Poly operator*(const double p) const {
+ Poly result;
+ const unsigned out_size = size();
+ result.reserve(out_size);
+
+ for(unsigned i = 0; i < out_size; i++) {
+ result.push_back((*this)[i]*p);
+ }
+ assert(result.size() == out_size);
+ return result;
+ }
+ // equivalent to multiply by x^terms, negative terms are disallowed
+ Poly shifted(unsigned const terms) const {
+ Poly result;
+ size_type const out_size = size() + terms;
+ result.reserve(out_size);
+
+ result.resize(terms, 0.0);
+ result.insert(result.end(), this->begin(), this->end());
+
+ assert(result.size() == out_size);
+ return result;
+ }
+ Poly operator*(const Poly& p) const;
+
+ template <typename T>
+ T eval(T x) const {
+ T r = 0;
+ for(int k = size()-1; k >= 0; k--) {
+ r = r*x + T((*this)[k]);
+ }
+ return r;
+ }
+
+ template <typename T>
+ T operator()(T t) const { return (T)eval(t);}
+
+ void normalize();
+
+ void monicify();
+ Poly() {}
+ Poly(const Poly& p) : std::vector<double>(p) {}
+ Poly(const double a) {push_back(a);}
+
+public:
+ template <class T, class U>
+ void val_and_deriv(T x, U &pd) const {
+ pd[0] = back();
+ int nc = size() - 1;
+ int nd = pd.size() - 1;
+ for(unsigned j = 1; j < pd.size(); j++)
+ pd[j] = 0.0;
+ for(int i = nc -1; i >= 0; i--) {
+ int nnd = std::min(nd, nc-i);
+ for(int j = nnd; j >= 1; j--)
+ pd[j] = pd[j]*x + operator[](i);
+ pd[0] = pd[0]*x + operator[](i);
+ }
+ double cnst = 1;
+ for(int i = 2; i <= nd; i++) {
+ cnst *= i;
+ pd[i] *= cnst;
+ }
+ }
+
+ static Poly linear(double ax, double b) {
+ Poly p;
+ p.push_back(b);
+ p.push_back(ax);
+ return p;
+ }
+};
+
+inline Poly operator*(double a, Poly const & b) { return b * a;}
+
+Poly integral(Poly const & p);
+Poly derivative(Poly const & p);
+Poly divide_out_root(Poly const & p, double x);
+Poly compose(Poly const & a, Poly const & b);
+Poly divide(Poly const &a, Poly const &b, Poly &r);
+Poly gcd(Poly const &a, Poly const &b, const double tol=1e-10);
+
+/*** solve(Poly p)
+ * find all p.degree() roots of p.
+ * This function can take a long time with suitably crafted polynomials, but in practice it should be fast. Should we provide special forms for degree() <= 4?
+ */
+std::vector<std::complex<double> > solve(const Poly & p);
+
+#ifdef HAVE_GSL
+/*** solve_reals(Poly p)
+ * find all real solutions to Poly p.
+ * currently we just use solve and pick out the suitably real looking values, there may be a better algorithm.
+ */
+std::vector<double> solve_reals(const Poly & p);
+#endif
+double polish_root(Poly const & p, double guess, double tol);
+
+
+/** @brief Analytically solve quadratic equation.
+ * The equation is given in the standard form: ax^2 + bx + c = 0.
+ * Only real roots are returned. */
+std::vector<Coord> solve_quadratic(Coord a, Coord b, Coord c);
+
+/** @brief Analytically solve cubic equation.
+ * The equation is given in the standard form: ax^3 + bx^2 + cx + d = 0.
+ * Only real roots are returned. */
+std::vector<Coord> solve_cubic(Coord a, Coord b, Coord c, Coord d);
+
+
+inline std::ostream &operator<< (std::ostream &out_file, const Poly &in_poly) {
+ if(in_poly.size() == 0)
+ out_file << "0";
+ else {
+ for(int i = (int)in_poly.size()-1; i >= 0; --i) {
+ if(i == 1) {
+ out_file << "" << in_poly[i] << "*x";
+ out_file << " + ";
+ } else if(i) {
+ out_file << "" << in_poly[i] << "*x^" << i;
+ out_file << " + ";
+ } else
+ out_file << in_poly[i];
+
+ }
+ }
+ return out_file;
+}
+
+} // namespace Geom
+
+#endif //LIB2GEOM_SEEN_POLY_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/ray.h b/src/3rdparty/2geom/include/2geom/ray.h
new file mode 100644
index 0000000..4e60fd8
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/ray.h
@@ -0,0 +1,192 @@
+/**
+ * \file
+ * \brief Infinite straight ray
+ *//*
+ * Copyright 2008 Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_RAY_H
+#define LIB2GEOM_SEEN_RAY_H
+
+#include <vector>
+#include <2geom/point.h>
+#include <2geom/bezier-curve.h> // for LineSegment
+#include <2geom/exception.h>
+#include <2geom/math-utils.h>
+#include <2geom/transforms.h>
+#include <2geom/angle.h>
+
+namespace Geom
+{
+
+/**
+ * @brief Straight ray from a specific point to infinity.
+ *
+ * Rays are "half-lines" - they begin at some specific point and extend in a straight line
+ * to infinity.
+ *
+ * @ingroup Primitives
+ */
+class Ray {
+private:
+ Point _origin;
+ Point _vector;
+
+public:
+ Ray() : _origin(0,0), _vector(1,0) {}
+ Ray(Point const& origin, Coord angle)
+ : _origin(origin)
+ {
+ sincos(angle, _vector[Y], _vector[X]);
+ }
+ Ray(Point const& A, Point const& B) {
+ setPoints(A, B);
+ }
+ Point origin() const { return _origin; }
+ Point vector() const { return _vector; }
+ Point versor() const { return _vector.normalized(); }
+ void setOrigin(Point const &o) { _origin = o; }
+ void setVector(Point const& v) { _vector = v; }
+ Coord angle() const { return std::atan2(_vector[Y], _vector[X]); }
+ void setAngle(Coord a) { sincos(a, _vector[Y], _vector[X]); }
+ void setPoints(Point const &a, Point const &b) {
+ _origin = a;
+ _vector = b - a;
+ if (are_near(_vector, Point(0,0)) )
+ _vector = Point(0,0);
+ else
+ _vector.normalize();
+ }
+ bool isDegenerate() const {
+ return ( _vector[X] == 0 && _vector[Y] == 0 );
+ }
+ Point pointAt(Coord t) const {
+ return _origin + _vector * t;
+ }
+ Coord valueAt(Coord t, Dim2 d) const {
+ return _origin[d] + _vector[d] * t;
+ }
+ std::vector<Coord> roots(Coord v, Dim2 d) const {
+ std::vector<Coord> result;
+ if ( _vector[d] != 0 ) {
+ double t = (v - _origin[d]) / _vector[d];
+ if (t >= 0) result.push_back(t);
+ } else if (_vector[(d+1)%2] == v) {
+ THROW_INFINITESOLUTIONS();
+ }
+ return result;
+ }
+ Coord nearestTime(Point const& point) const {
+ if ( isDegenerate() ) return 0;
+ double t = dot(point - _origin, _vector);
+ if (t < 0) t = 0;
+ return t;
+ }
+ Ray reverse() const {
+ Ray result;
+ result.setOrigin(_origin);
+ result.setVector(-_vector);
+ return result;
+ }
+ Curve *portion(Coord f, Coord t) const {
+ return new LineSegment(pointAt(f), pointAt(t));
+ }
+ LineSegment segment(Coord f, Coord t) const {
+ return LineSegment(pointAt(f), pointAt(t));
+ }
+ Ray transformed(Affine const& m) const {
+ return Ray(_origin * m, (_origin + _vector) * m);
+ }
+}; // end class Ray
+
+inline
+double distance(Point const& _point, Ray const& _ray) {
+ double t = _ray.nearestTime(_point);
+ return ::Geom::distance(_point, _ray.pointAt(t));
+}
+
+inline
+bool are_near(Point const& _point, Ray const& _ray, double eps = EPSILON) {
+ return are_near(distance(_point, _ray), 0, eps);
+}
+
+inline
+bool are_same(Ray const& r1, Ray const& r2, double eps = EPSILON) {
+ return are_near(r1.vector(), r2.vector(), eps)
+ && are_near(r1.origin(), r2.origin(), eps);
+}
+
+// evaluate the angle between r1 and r2 rotating r1 in cw or ccw direction on r2
+// the returned value is an angle in the interval [0, 2PI[
+inline
+double angle_between(Ray const& r1, Ray const& r2, bool cw = true) {
+ double angle = angle_between(r1.vector(), r2.vector());
+ if (angle < 0) angle += 2*M_PI;
+ if (!cw) angle = 2*M_PI - angle;
+ return angle;
+}
+
+/**
+ * @brief Returns the angle bisector for the two given rays.
+ *
+ * @a r1 is rotated half the way to @a r2 in either clockwise or counter-clockwise direction.
+ *
+ * @pre Both passed rays must have the same origin.
+ *
+ * @remarks If the versors of both given rays point in the same direction, the direction of the
+ * angle bisector ray depends on the third parameter:
+ * - If @a cw is set to @c true, the returned ray will equal the passed rays @a r1 and @a r2.
+ * - If @a cw is set to @c false, the returned ray will go in the opposite direction.
+ *
+ * @throws RangeError if the given rays do not have the same origins
+ */
+inline
+Ray make_angle_bisector_ray(Ray const& r1, Ray const& r2, bool cw = true)
+{
+ if ( !are_near(r1.origin(), r2.origin()) )
+ {
+ THROW_RANGEERROR("passed rays do not have the same origin");
+ }
+
+ Ray bisector(r1.origin(), r1.origin() + r1.vector() * Rotate(angle_between(r1, r2) / 2.0));
+
+ return (cw ? bisector : bisector.reverse());
+}
+
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_RAY_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/rect.h b/src/3rdparty/2geom/include/2geom/rect.h
new file mode 100644
index 0000000..5edfc95
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/rect.h
@@ -0,0 +1,263 @@
+/**
+ * \file
+ * \brief Axis-aligned rectangle
+ *//*
+ * Authors:
+ * Michael Sloan <mgsloan@gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ * Copyright 2007-2011 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, output to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * Authors of original rect class:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Nathan Hurst <njh@mail.csse.monash.edu.au>
+ * bulia byak <buliabyak@users.sf.net>
+ * MenTaLguY <mental@rydia.net>
+ */
+
+#ifndef LIB2GEOM_SEEN_RECT_H
+#define LIB2GEOM_SEEN_RECT_H
+
+#include <2geom/affine.h>
+#include <2geom/interval.h>
+#include <2geom/int-rect.h>
+
+namespace Geom {
+
+/** Values for the <align> parameter of preserveAspectRatio.
+ * See: http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute */
+enum Align {
+ ALIGN_NONE,
+ ALIGN_XMIN_YMIN,
+ ALIGN_XMID_YMIN,
+ ALIGN_XMAX_YMIN,
+ ALIGN_XMIN_YMID,
+ ALIGN_XMID_YMID,
+ ALIGN_XMAX_YMID,
+ ALIGN_XMIN_YMAX,
+ ALIGN_XMID_YMAX,
+ ALIGN_XMAX_YMAX
+};
+
+/** Values for the <meetOrSlice> parameter of preserveAspectRatio.
+ * See: http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute */
+enum Expansion {
+ EXPANSION_MEET,
+ EXPANSION_SLICE
+};
+
+/// Convert an align specification to coordinate fractions.
+Point align_factors(Align align);
+
+/** @brief Structure that specifies placement of within a viewport.
+ * Use this to create transformations that preserve aspect. */
+struct Aspect {
+ Align align;
+ Expansion expansion;
+ bool deferred; ///< for SVG compatibility
+
+ Aspect(Align a = ALIGN_NONE, Expansion ex = EXPANSION_MEET)
+ : align(a), expansion(ex), deferred(false)
+ {}
+};
+
+/**
+ * @brief Axis aligned, non-empty rectangle.
+ * @ingroup Primitives
+ */
+class Rect
+ : public GenericRect<Coord>
+{
+ typedef GenericRect<Coord> Base;
+public:
+ /// @name Create rectangles.
+ /// @{
+ /** @brief Create a rectangle that contains only the point at (0,0). */
+ Rect() {}
+ /** @brief Create a rectangle from X and Y intervals. */
+ Rect(Interval const &a, Interval const &b) : Base(a,b) {}
+ /** @brief Create a rectangle from two points. */
+ Rect(Point const &a, Point const &b) : Base(a,b) {}
+ Rect(Coord x0, Coord y0, Coord x1, Coord y1) : Base(x0, y0, x1, y1) {}
+ Rect(Base const &b) : Base(b) {}
+ Rect(IntRect const &ir) : Base(ir.min(), ir.max()) {}
+ /// @}
+
+ /// @name Inspect dimensions.
+ /// @{
+ /** @brief Check whether the rectangle has zero area up to specified tolerance.
+ * @param eps Maximum value of the area to consider empty
+ * @return True if rectangle has an area smaller than tolerance, false otherwise */
+ bool hasZeroArea(Coord eps = EPSILON) const { return (area() <= eps); }
+ /// Check whether the rectangle has finite area
+ bool isFinite() const { return (*this)[X].isFinite() && (*this)[Y].isFinite(); }
+ /// Calculate the diameter of the smallest circle that would contain the rectangle.
+ Coord diameter() const { return distance(corner(0), corner(2)); }
+ /// @}
+
+ /// @name Test other rectangles and points for inclusion.
+ /// @{
+ /** @brief Check whether the interiors of the rectangles have any common points. */
+ bool interiorIntersects(Rect const &r) const {
+ return f[X].interiorIntersects(r[X]) && f[Y].interiorIntersects(r[Y]);
+ }
+ /** @brief Check whether the interior includes the given point. */
+ bool interiorContains(Point const &p) const {
+ return f[X].interiorContains(p[X]) && f[Y].interiorContains(p[Y]);
+ }
+ /** @brief Check whether the interior includes all points in the given rectangle.
+ * Interior of the rectangle is the entire rectangle without its borders. */
+ bool interiorContains(Rect const &r) const {
+ return f[X].interiorContains(r[X]) && f[Y].interiorContains(r[Y]);
+ }
+ inline bool interiorContains(OptRect const &r) const;
+ /// @}
+
+ /// @name Rounding to integer coordinates
+ /// @{
+ /** @brief Return the smallest integer rectangle which contains this one. */
+ IntRect roundOutwards() const {
+ IntRect ir(f[X].roundOutwards(), f[Y].roundOutwards());
+ return ir;
+ }
+ /** @brief Return the largest integer rectangle which is contained in this one. */
+ OptIntRect roundInwards() const {
+ OptIntRect oir(f[X].roundInwards(), f[Y].roundInwards());
+ return oir;
+ }
+ /// @}
+
+ /// @name SVG viewbox functionality.
+ /// @{
+ /** @brief Transform contents to viewport.
+ * Computes an affine that transforms the contents of this rectangle
+ * to the specified viewport. The aspect parameter specifies how to
+ * to the transformation (whether the aspect ratio of content
+ * should be kept and where it should be placed in the viewport). */
+ Affine transformTo(Rect const &viewport, Aspect const &aspect = Aspect()) const;
+ /// @}
+
+ /// @name Operators
+ /// @{
+ Rect &operator*=(Affine const &m);
+ bool operator==(IntRect const &ir) const {
+ return f[X] == ir[X] && f[Y] == ir[Y];
+ }
+ bool operator==(Rect const &other) const {
+ return Base::operator==(other);
+ }
+ /// @}
+};
+
+/**
+ * @brief Axis-aligned rectangle that can be empty.
+ * @ingroup Primitives
+ */
+class OptRect
+ : public GenericOptRect<Coord>
+{
+ typedef GenericOptRect<Coord> Base;
+public:
+ OptRect() : Base() {}
+ OptRect(Rect const &a) : Base(a) {}
+ OptRect(Point const &a, Point const &b) : Base(a, b) {}
+ OptRect(Coord x0, Coord y0, Coord x1, Coord y1) : Base(x0, y0, x1, y1) {}
+ OptRect(OptInterval const &x_int, OptInterval const &y_int) : Base(x_int, y_int) {}
+ OptRect(Base const &b) : Base(b) {}
+
+ OptRect(IntRect const &r) : Base(Rect(r)) {}
+ OptRect(OptIntRect const &r) : Base() {
+ if (r) *this = Rect(*r);
+ }
+
+ Affine transformTo(Rect const &viewport, Aspect const &aspect = Aspect()) {
+ Affine ret = Affine::identity();
+ if (empty()) return ret;
+ ret = (*this)->transformTo(viewport, aspect);
+ return ret;
+ }
+
+ bool operator==(OptRect const &other) const {
+ return Base::operator==(other);
+ }
+ bool operator==(Rect const &other) const {
+ return Base::operator==(other);
+ }
+};
+
+Coord distanceSq(Point const &p, Rect const &rect);
+Coord distance(Point const &p, Rect const &rect);
+/// Minimum square of distance to rectangle, or infinity if empty.
+Coord distanceSq(Point const &p, OptRect const &rect);
+/// Minimum distance to rectangle, or infinity if empty.
+Coord distance(Point const &p, OptRect const &rect);
+
+inline bool Rect::interiorContains(OptRect const &r) const {
+ return !r || interiorContains(static_cast<Rect const &>(*r));
+}
+
+// the functions below do not work when defined generically
+inline OptRect operator&(Rect const &a, Rect const &b) {
+ OptRect ret(a);
+ ret.intersectWith(b);
+ return ret;
+}
+inline OptRect intersect(Rect const &a, Rect const &b) {
+ return a & b;
+}
+inline OptRect intersect(OptRect const &a, OptRect const &b) {
+ return a & b;
+}
+inline Rect unify(Rect const &a, Rect const &b) {
+ return a | b;
+}
+inline OptRect unify(OptRect const &a, OptRect const &b) {
+ return a | b;
+}
+
+/** @brief Union a list of rectangles
+ * @deprecated Use OptRect::from_range instead */
+inline Rect union_list(std::vector<Rect> const &r) {
+ if(r.empty()) return Rect(Interval(0,0), Interval(0,0));
+ Rect ret = r[0];
+ for(unsigned i = 1; i < r.size(); i++)
+ ret.unionWith(r[i]);
+ return ret;
+}
+
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_RECT_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/sbasis-2d.h b/src/3rdparty/2geom/include/2geom/sbasis-2d.h
new file mode 100644
index 0000000..98dec67
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/sbasis-2d.h
@@ -0,0 +1,371 @@
+/**
+ * \file
+ * \brief Obsolete 2D SBasis function class
+ *//*
+ * Authors:
+ * Nathan Hurst <?@?.?>
+ * JFBarraud <?@?.?>
+ *
+ * Copyright 2006-2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_SBASIS_2D_H
+#define LIB2GEOM_SEEN_SBASIS_2D_H
+#include <vector>
+#include <cassert>
+#include <algorithm>
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <iostream>
+
+namespace Geom{
+
+class Linear2d{
+public:
+ /*
+ u 0,1
+ v 0,2
+ */
+ double a[4];
+ Linear2d() {
+ a[0] = 0;
+ a[1] = 0;
+ a[2] = 0;
+ a[3] = 0;
+ }
+ Linear2d(double aa) {
+ for(double & i : a)
+ i = aa;
+ }
+ Linear2d(double a00, double a01, double a10, double a11)
+ {
+ a[0] = a00;
+ a[1] = a01;
+ a[2] = a10;
+ a[3] = a11;
+ }
+
+ double operator[](const int i) const {
+ assert(i >= 0);
+ assert(i < 4);
+ return a[i];
+ }
+ double& operator[](const int i) {
+ assert(i >= 0);
+ assert(i < 4);
+ return a[i];
+ }
+ double apply(double u, double v) {
+ return (a[0]*(1-u)*(1-v) +
+ a[1]*u*(1-v) +
+ a[2]*(1-u)*v +
+ a[3]*u*v);
+ }
+};
+
+inline Linear extract_u(Linear2d const &a, double u) {
+ return Linear(a[0]*(1-u) +
+ a[1]*u,
+ a[2]*(1-u) +
+ a[3]*u);
+}
+inline Linear extract_v(Linear2d const &a, double v) {
+ return Linear(a[0]*(1-v) +
+ a[2]*v,
+ a[1]*(1-v) +
+ a[3]*v);
+}
+inline Linear2d operator-(Linear2d const &a) {
+ return Linear2d(-a.a[0], -a.a[1],
+ -a.a[2], -a.a[3]);
+}
+inline Linear2d operator+(Linear2d const & a, Linear2d const & b) {
+ return Linear2d(a[0] + b[0],
+ a[1] + b[1],
+ a[2] + b[2],
+ a[3] + b[3]);
+}
+inline Linear2d operator-(Linear2d const & a, Linear2d const & b) {
+ return Linear2d(a[0] - b[0],
+ a[1] - b[1],
+ a[2] - b[2],
+ a[3] - b[3]);
+}
+inline Linear2d& operator+=(Linear2d & a, Linear2d const & b) {
+ for(unsigned i = 0; i < 4; i++)
+ a[i] += b[i];
+ return a;
+}
+inline Linear2d& operator-=(Linear2d & a, Linear2d const & b) {
+ for(unsigned i = 0; i < 4; i++)
+ a[i] -= b[i];
+ return a;
+}
+inline Linear2d& operator*=(Linear2d & a, double b) {
+ for(unsigned i = 0; i < 4; i++)
+ a[i] *= b;
+ return a;
+}
+
+inline bool operator==(Linear2d const & a, Linear2d const & b) {
+ for(unsigned i = 0; i < 4; i++)
+ if(a[i] != b[i])
+ return false;
+ return true;
+}
+inline bool operator!=(Linear2d const & a, Linear2d const & b) {
+ for(unsigned i = 0; i < 4; i++)
+ if(a[i] == b[i])
+ return false;
+ return true;
+}
+inline Linear2d operator*(double const a, Linear2d const & b) {
+ return Linear2d(a*b[0], a*b[1],
+ a*b[2], a*b[3]);
+}
+
+class SBasis2d : public std::vector<Linear2d>{
+public:
+ // vector in u,v
+ unsigned us, vs; // number of u terms, v terms
+ SBasis2d() {}
+ SBasis2d(Linear2d const & bo)
+ : us(1), vs(1) {
+ push_back(bo);
+ }
+ SBasis2d(SBasis2d const & a)
+ : std::vector<Linear2d>(a), us(a.us), vs(a.vs) {}
+
+ Linear2d& index(unsigned ui, unsigned vi) {
+ assert(ui < us);
+ assert(vi < vs);
+ return (*this)[ui + vi*us];
+ }
+
+ Linear2d index(unsigned ui, unsigned vi) const {
+ if(ui >= us)
+ return Linear2d(0);
+ if(vi >= vs)
+ return Linear2d(0);
+ return (*this)[ui + vi*us];
+ }
+
+ double apply(double u, double v) const {
+ double s = u*(1-u);
+ double t = v*(1-v);
+ Linear2d p;
+ double tk = 1;
+// XXX rewrite as horner
+ for(unsigned vi = 0; vi < vs; vi++) {
+ double sk = 1;
+ for(unsigned ui = 0; ui < us; ui++) {
+ p += (sk*tk)*index(ui, vi);
+ sk *= s;
+ }
+ tk *= t;
+ }
+ return p.apply(u,v);
+ }
+
+ void clear() {
+ fill(begin(), end(), Linear2d(0));
+ }
+
+ void normalize(); // remove extra zeros
+
+ double tail_error(unsigned tail) const;
+
+ void truncate(unsigned k);
+};
+
+inline SBasis2d operator-(const SBasis2d& p) {
+ SBasis2d result;
+ result.reserve(p.size());
+
+ for(unsigned i = 0; i < p.size(); i++) {
+ result.push_back(-p[i]);
+ }
+ return result;
+}
+
+inline SBasis2d operator+(const SBasis2d& a, const SBasis2d& b) {
+ SBasis2d result;
+ result.us = std::max(a.us, b.us);
+ result.vs = std::max(a.vs, b.vs);
+ const unsigned out_size = result.us*result.vs;
+ result.resize(out_size);
+
+ for(unsigned vi = 0; vi < result.vs; vi++) {
+ for(unsigned ui = 0; ui < result.us; ui++) {
+ Linear2d bo;
+ if(ui < a.us && vi < a.vs)
+ bo += a.index(ui, vi);
+ if(ui < b.us && vi < b.vs)
+ bo += b.index(ui, vi);
+ result.index(ui, vi) = bo;
+ }
+ }
+ return result;
+}
+
+inline SBasis2d operator-(const SBasis2d& a, const SBasis2d& b) {
+ SBasis2d result;
+ result.us = std::max(a.us, b.us);
+ result.vs = std::max(a.vs, b.vs);
+ const unsigned out_size = result.us*result.vs;
+ result.resize(out_size);
+
+ for(unsigned vi = 0; vi < result.vs; vi++) {
+ for(unsigned ui = 0; ui < result.us; ui++) {
+ Linear2d bo;
+ if(ui < a.us && vi < a.vs)
+ bo += a.index(ui, vi);
+ if(ui < b.us && vi < b.vs)
+ bo -= b.index(ui, vi);
+ result.index(ui, vi) = bo;
+ }
+ }
+ return result;
+}
+
+
+inline SBasis2d& operator+=(SBasis2d& a, const Linear2d& b) {
+ if(a.size() < 1)
+ a.push_back(b);
+ else
+ a[0] += b;
+ return a;
+}
+
+inline SBasis2d& operator-=(SBasis2d& a, const Linear2d& b) {
+ if(a.size() < 1)
+ a.push_back(-b);
+ else
+ a[0] -= b;
+ return a;
+}
+
+inline SBasis2d& operator+=(SBasis2d& a, double b) {
+ if(a.size() < 1)
+ a.push_back(Linear2d(b));
+ else {
+ for(unsigned i = 0; i < 4; i++)
+ a[0] += double(b);
+ }
+ return a;
+}
+
+inline SBasis2d& operator-=(SBasis2d& a, double b) {
+ if(a.size() < 1)
+ a.push_back(Linear2d(-b));
+ else {
+ a[0] -= b;
+ }
+ return a;
+}
+
+inline SBasis2d& operator*=(SBasis2d& a, double b) {
+ for(unsigned i = 0; i < a.size(); i++)
+ a[i] *= b;
+ return a;
+}
+
+inline SBasis2d& operator/=(SBasis2d& a, double b) {
+ for(unsigned i = 0; i < a.size(); i++)
+ a[i] *= (1./b);
+ return a;
+}
+
+SBasis2d operator*(double k, SBasis2d const &a);
+SBasis2d operator*(SBasis2d const &a, SBasis2d const &b);
+
+SBasis2d shift(SBasis2d const &a, int sh);
+
+SBasis2d shift(Linear2d const &a, int sh);
+
+SBasis2d truncate(SBasis2d const &a, unsigned terms);
+
+SBasis2d multiply(SBasis2d const &a, SBasis2d const &b);
+
+SBasis2d integral(SBasis2d const &c);
+
+SBasis2d partial_derivative(SBasis2d const &a, int dim);
+
+SBasis2d sqrt(SBasis2d const &a, int k);
+
+// return a kth order approx to 1/a)
+SBasis2d reciprocal(Linear2d const &a, int k);
+
+SBasis2d divide(SBasis2d const &a, SBasis2d const &b, int k);
+
+// a(b(t))
+SBasis2d compose(SBasis2d const &a, SBasis2d const &b);
+SBasis2d compose(SBasis2d const &a, SBasis2d const &b, unsigned k);
+SBasis2d inverse(SBasis2d const &a, int k);
+
+// these two should probably be replaced with compose
+SBasis extract_u(SBasis2d const &a, double u);
+SBasis extract_v(SBasis2d const &a, double v);
+
+SBasis compose(Linear2d const &a, D2<SBasis> const &p);
+
+SBasis compose(SBasis2d const &fg, D2<SBasis> const &p);
+
+D2<SBasis> compose_each(D2<SBasis2d> const &fg, D2<SBasis> const &p);
+
+inline std::ostream &operator<< (std::ostream &out_file, const Linear2d &bo) {
+ out_file << "{" << bo[0] << ", " << bo[1] << "}, ";
+ out_file << "{" << bo[2] << ", " << bo[3] << "}";
+ return out_file;
+}
+
+inline std::ostream &operator<< (std::ostream &out_file, const SBasis2d & p) {
+ for(unsigned i = 0; i < p.size(); i++) {
+ out_file << p[i] << "s^" << i << " + ";
+ }
+ return out_file;
+}
+
+D2<SBasis>
+sb2dsolve(SBasis2d const &f, Geom::Point const &A, Geom::Point const &B, unsigned degmax=2);
+
+D2<SBasis>
+sb2d_cubic_solve(SBasis2d const &f, Geom::Point const &A, Geom::Point const &B);
+
+} // end namespace Geom
+
+#endif
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/sbasis-curve.h b/src/3rdparty/2geom/include/2geom/sbasis-curve.h
new file mode 100644
index 0000000..93d6772
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/sbasis-curve.h
@@ -0,0 +1,160 @@
+/**
+ * \file
+ * \brief Symmetric power basis curve
+ *//*
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2007-2009 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_SBASIS_CURVE_H
+#define LIB2GEOM_SEEN_SBASIS_CURVE_H
+
+#include <2geom/curve.h>
+#include <2geom/exception.h>
+#include <2geom/nearest-time.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/transforms.h>
+
+namespace Geom
+{
+
+/** @brief Symmetric power basis curve.
+ *
+ * Symmetric power basis (S-basis for short) polynomials are a versatile numeric
+ * representation of arbitrary continuous curves. They are the main representation of curves
+ * in 2Geom.
+ *
+ * S-basis is defined for odd degrees and composed of the following polynomials:
+ * \f{align*}{
+ P_k^0(t) &= t^k (1-t)^{k+1} \\
+ P_k^1(t) &= t^{k+1} (1-t)^k \f}
+ * This can be understood more easily with the help of the chart below. Each square
+ * represents a product of a specific number of \f$t\f$ and \f$(1-t)\f$ terms. Red dots
+ * are the canonical (monomial) basis, the green dots are the Bezier basis, and the blue
+ * dots are the S-basis, all of them of degree 7.
+ *
+ * @image html sbasis.png "Illustration of the monomial, Bezier and symmetric power bases"
+ *
+ * The S-Basis has several important properties:
+ * - S-basis polynomials are closed under multiplication.
+ * - Evaluation is fast, using a modified Horner scheme.
+ * - Degree change is as trivial as in the monomial basis. To elevate, just add extra
+ * zero coefficients. To reduce the degree, truncate the terms in the highest powers.
+ * Compare this with Bezier curves, where degree change is complicated.
+ * - Conversion between S-basis and Bezier basis is numerically stable.
+ *
+ * More in-depth information can be found in the following paper:
+ * J Sanchez-Reyes, "The symmetric analogue of the polynomial power basis".
+ * ACM Transactions on Graphics, Vol. 16, No. 3, July 1997, pages 319--357.
+ * http://portal.acm.org/citation.cfm?id=256162
+ *
+ * @ingroup Curves
+ */
+class SBasisCurve : public Curve {
+private:
+ D2<SBasis> inner;
+
+public:
+ explicit SBasisCurve(D2<SBasis> const &sb) : inner(sb) {}
+ explicit SBasisCurve(Curve const &other) : inner(other.toSBasis()) {}
+
+ Curve *duplicate() const override { return new SBasisCurve(*this); }
+ Point initialPoint() const override { return inner.at0(); }
+ Point finalPoint() const override { return inner.at1(); }
+ bool isDegenerate() const override { return inner.isConstant(0); }
+ bool isLineSegment() const override { return inner[X].size() == 1; }
+ Point pointAt(Coord t) const override { return inner.valueAt(t); }
+ std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const override {
+ return inner.valueAndDerivatives(t, n);
+ }
+ Coord valueAt(Coord t, Dim2 d) const override { return inner[d].valueAt(t); }
+ void setInitial(Point const &v) override {
+ for (unsigned d = 0; d < 2; d++) { inner[d][0][0] = v[d]; }
+ }
+ void setFinal(Point const &v) override {
+ for (unsigned d = 0; d < 2; d++) { inner[d][0][1] = v[d]; }
+ }
+ Rect boundsFast() const override { return *bounds_fast(inner); }
+ Rect boundsExact() const override { return *bounds_exact(inner); }
+ void expandToTransformed(Rect &bbox, Affine const &transform) const override {
+ bbox |= bounds_exact(inner * transform);
+ }
+ OptRect boundsLocal(OptInterval const &i, unsigned deg) const override {
+ return bounds_local(inner, i, deg);
+ }
+ std::vector<Coord> roots(Coord v, Dim2 d) const override { return Geom::roots(inner[d] - v); }
+ Coord nearestTime( Point const& p, Coord from = 0, Coord to = 1 ) const override {
+ return nearest_time(p, inner, from, to);
+ }
+ std::vector<Coord> allNearestTimes( Point const& p, Coord from = 0,
+ Coord to = 1 ) const override
+ {
+ return all_nearest_times(p, inner, from, to);
+ }
+ Coord length(Coord tolerance) const override { return ::Geom::length(inner, tolerance); }
+ Curve *portion(Coord f, Coord t) const override {
+ return new SBasisCurve(Geom::portion(inner, f, t));
+ }
+
+ using Curve::operator*=;
+ void operator*=(Affine const &m) override { inner = inner * m; }
+
+ Curve *derivative() const override {
+ return new SBasisCurve(Geom::derivative(inner));
+ }
+ D2<SBasis> toSBasis() const override { return inner; }
+ bool operator==(Curve const &c) const override {
+ SBasisCurve const *other = dynamic_cast<SBasisCurve const *>(&c);
+ if (!other) return false;
+ return inner == other->inner;
+ }
+ bool isNear(Curve const &/*c*/, Coord /*eps*/) const override {
+ THROW_NOTIMPLEMENTED();
+ return false;
+ }
+ int degreesOfFreedom() const override {
+ return inner[0].degreesOfFreedom() + inner[1].degreesOfFreedom();
+ }
+};
+
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_SBASIS_CURVE_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/sbasis-geometric.h b/src/3rdparty/2geom/include/2geom/sbasis-geometric.h
new file mode 100644
index 0000000..7f1e8aa
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/sbasis-geometric.h
@@ -0,0 +1,146 @@
+/**
+ * \file
+ * \brief two-dimensional geometric operators.
+ *
+ * These operators are built on a more 'polynomially robust'
+ * transformation to map a function that takes a [0,1] parameter to a
+ * 2d vector into a function that takes the same [0,1] parameter to a
+ * unit vector with the same direction.
+ *
+ * Rather that using (X/sqrt(X))(t) which involves two unstable
+ * operations, sqrt and divide, this approach forms a curve directly
+ * from the various tangent directions at each end (angular jet). As
+ * a result, the final path has a convergence behaviour derived from
+ * that of the sin and cos series. -- njh
+ *//*
+ * Copyright 2007, JFBarraud
+ * Copyright 2007, njh
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_SBASIS_GEOMETRIC_H
+#define LIB2GEOM_SEEN_SBASIS_GEOMETRIC_H
+
+#include <2geom/d2.h>
+#include <2geom/piecewise.h>
+#include <vector>
+
+namespace Geom {
+
+Piecewise<D2<SBasis> >
+cutAtRoots(Piecewise<D2<SBasis> > const &M, double tol=1e-4);
+
+Piecewise<SBasis>
+atan2(D2<SBasis> const &vect,
+ double tol=.01, unsigned order=3);
+
+Piecewise<SBasis>
+atan2(Piecewise<D2<SBasis> >const &vect,
+ double tol=.01, unsigned order=3);
+
+D2<Piecewise<SBasis> >
+tan2(SBasis const &angle,
+ double tol=.01, unsigned order=3);
+
+D2<Piecewise<SBasis> >
+tan2(Piecewise<SBasis> const &angle,
+ double tol=.01, unsigned order=3);
+
+Piecewise<D2<SBasis> >
+unitVector(D2<SBasis> const &vect,
+ double tol=.01, unsigned order=3);
+Piecewise<D2<SBasis> >
+unitVector(Piecewise<D2<SBasis> > const &vect,
+ double tol=.01, unsigned order=3);
+
+// Piecewise<D2<SBasis> >
+// uniform_speed(D2<SBasis> const M,
+// double tol=.1);
+
+Piecewise<SBasis> curvature( D2<SBasis> const &M, double tol=.01);
+Piecewise<SBasis> curvature(Piecewise<D2<SBasis> > const &M, double tol=.01);
+
+Piecewise<SBasis> arcLengthSb( D2<SBasis> const &M, double tol=.01);
+Piecewise<SBasis> arcLengthSb(Piecewise<D2<SBasis> > const &M, double tol=.01);
+
+double length( D2<SBasis> const &M, double tol=.01);
+double length(Piecewise<D2<SBasis> > const &M, double tol=.01);
+
+void length_integrating(D2<SBasis> const &B, double &result, double &abs_error, double tol);
+
+Piecewise<D2<SBasis> >
+arc_length_parametrization(D2<SBasis> const &M,
+ unsigned order=3,
+ double tol=.01);
+Piecewise<D2<SBasis> >
+arc_length_parametrization(Piecewise<D2<SBasis> > const &M,
+ unsigned order=3,
+ double tol=.01);
+
+
+unsigned centroid(Piecewise<D2<SBasis> > const &p, Point& centroid, double &area);
+
+std::vector<D2<SBasis> >
+cubics_fitting_curvature(Point const &M0, Point const &M1,
+ Point const &dM0, Point const &dM1,
+ double d2M0xdM0, double d2M1xdM1,
+ int insist_on_speed_signs = 1,
+ double epsilon = 1e-5);
+
+std::vector<D2<SBasis> >
+cubics_fitting_curvature(Point const &M0, Point const &M1,
+ Point const &dM0, Point const &dM1,
+ Point const &d2M0, Point const &d2M1,
+ int insist_on_speed_signs = 1,
+ double epsilon = 1e-5);
+
+std::vector<D2<SBasis> >
+cubics_with_prescribed_curvature(Point const &M0, Point const &M1,
+ Point const &dM0, Point const &dM1,
+ double k0, double k1,
+ int insist_on_speed_signs = 1,
+ double error = 1e-5);
+
+
+std::vector<double> find_tangents(Point P, D2<SBasis> const &A);
+std::vector<double> find_tangents_by_vector(Point V, D2<SBasis> const &A);
+std::vector<double> find_normals(Point P, D2<SBasis> const &A);
+std::vector<double> find_normals_by_vector(Point V, D2<SBasis> const &A);
+
+};
+
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+
diff --git a/src/3rdparty/2geom/include/2geom/sbasis-math.h b/src/3rdparty/2geom/include/2geom/sbasis-math.h
new file mode 100644
index 0000000..e191dae
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/sbasis-math.h
@@ -0,0 +1,99 @@
+/** @file
+ * @brief some std functions to work with (pw)s-basis
+ *//*
+ * Authors:
+ * Jean-Francois Barraud
+ *
+ * Copyright (C) 2006-2007 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+//this a first try to define sqrt, cos, sin, etc...
+//TODO: define a truncated compose(sb,sb, order) and extend it to pw<sb>.
+//TODO: in all these functions, compute 'order' according to 'tol'.
+//TODO: use template to define the pw version automatically from the sb version?
+
+#ifndef LIB2GEOM_SEEN_SBASIS_MATH_H
+#define LIB2GEOM_SEEN_SBASIS_MATH_H
+
+
+#include <2geom/sbasis.h>
+#include <2geom/piecewise.h>
+#include <2geom/d2.h>
+
+namespace Geom{
+//-|x|---------------------------------------------------------------
+Piecewise<SBasis> abs( SBasis const &f);
+Piecewise<SBasis> abs(Piecewise<SBasis>const &f);
+
+//- max(f,g), min(f,g) ----------------------------------------------
+Piecewise<SBasis> max( SBasis const &f, SBasis const &g);
+Piecewise<SBasis> max(Piecewise<SBasis> const &f, SBasis const &g);
+Piecewise<SBasis> max( SBasis const &f, Piecewise<SBasis> const &g);
+Piecewise<SBasis> max(Piecewise<SBasis> const &f, Piecewise<SBasis> const &g);
+Piecewise<SBasis> min( SBasis const &f, SBasis const &g);
+Piecewise<SBasis> min(Piecewise<SBasis> const &f, SBasis const &g);
+Piecewise<SBasis> min( SBasis const &f, Piecewise<SBasis> const &g);
+Piecewise<SBasis> min(Piecewise<SBasis> const &f, Piecewise<SBasis> const &g);
+
+//-sign(x)---------------------------------------------------------------
+Piecewise<SBasis> signSb( SBasis const &f);
+Piecewise<SBasis> signSb(Piecewise<SBasis>const &f);
+
+//-Sqrt---------------------------------------------------------------
+Piecewise<SBasis> sqrt( SBasis const &f, double tol=1e-3, int order=3);
+Piecewise<SBasis> sqrt(Piecewise<SBasis>const &f, double tol=1e-3, int order=3);
+
+//-sin/cos--------------------------------------------------------------
+Piecewise<SBasis> cos( SBasis const &f, double tol=1e-3, int order=3);
+Piecewise<SBasis> cos(Piecewise<SBasis> const &f, double tol=1e-3, int order=3);
+Piecewise<SBasis> sin( SBasis const &f, double tol=1e-3, int order=3);
+Piecewise<SBasis> sin(Piecewise<SBasis> const &f, double tol=1e-3, int order=3);
+//-Log---------------------------------------------------------------
+Piecewise<SBasis> log( SBasis const &f, double tol=1e-3, int order=3);
+Piecewise<SBasis> log(Piecewise<SBasis>const &f, double tol=1e-3, int order=3);
+
+//--1/x------------------------------------------------------------
+//TODO: change this...
+Piecewise<SBasis> reciprocalOnDomain(Interval range, double tol=1e-3);
+Piecewise<SBasis> reciprocal( SBasis const &f, double tol=1e-3, int order=3);
+Piecewise<SBasis> reciprocal(Piecewise<SBasis>const &f, double tol=1e-3, int order=3);
+
+//--interpolate------------------------------------------------------------
+Piecewise<SBasis> interpolate( std::vector<double> times, std::vector<double> values, unsigned smoothness = 1);
+}
+
+#endif //SEEN_GEOM_PW_SB_CALCULUS_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/sbasis-poly.h b/src/3rdparty/2geom/include/2geom/sbasis-poly.h
new file mode 100644
index 0000000..d18bc36
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/sbasis-poly.h
@@ -0,0 +1,56 @@
+/** @file
+ * @brief Conversion between SBasis and Poly. Not recommended for general use due to instability.
+ *//*
+ * Authors:
+ * ? <?@?.?>
+ *
+ * Copyright ?-? authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_SBASIS_POLY_H
+#define LIB2GEOM_SEEN_SBASIS_POLY_H
+
+#include <2geom/polynomial.h>
+#include <2geom/sbasis.h>
+
+namespace Geom{
+
+SBasis poly_to_sbasis(Poly const & p);
+Poly sbasis_to_poly(SBasis const & s);
+
+};
+
+#endif
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/sbasis-to-bezier.h b/src/3rdparty/2geom/include/2geom/sbasis-to-bezier.h
new file mode 100644
index 0000000..eadb47b
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/sbasis-to-bezier.h
@@ -0,0 +1,87 @@
+/**
+ * \file
+ * \brief Conversion between SBasis and Bezier basis polynomials
+ *//*
+ * Authors:
+ * ? <?@?.?>
+ *
+ * Copyright ?-? authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_SBASIS_TO_BEZIER_H
+#define LIB2GEOM_SEEN_SBASIS_TO_BEZIER_H
+
+#include <2geom/d2.h>
+#include <2geom/pathvector.h>
+
+#include <vector>
+
+namespace Geom {
+
+class PathBuilder;
+
+void sbasis_to_bezier (Bezier &bz, SBasis const &sb, size_t sz = 0);
+void sbasis_to_bezier (D2<Bezier> &bz, D2<SBasis> const &sb, size_t sz = 0);
+void sbasis_to_bezier (std::vector<Point> & bz, D2<SBasis> const& sb, size_t sz = 0);
+void sbasis_to_cubic_bezier (std::vector<Point> & bz, D2<SBasis> const& sb);
+void bezier_to_sbasis (SBasis & sb, Bezier const& bz);
+void bezier_to_sbasis (D2<SBasis> & sb, std::vector<Point> const& bz);
+void build_from_sbasis(PathBuilder &pb, D2<SBasis> const &B, double tol, bool only_cubicbeziers);
+
+#if 0
+// this produces a degree k bezier from a degree k sbasis
+Bezier
+sbasis_to_bezier(SBasis const &B, unsigned q = 0);
+
+// inverse
+SBasis bezier_to_sbasis(Bezier const &B);
+
+
+std::vector<Geom::Point>
+sbasis_to_bezier(D2<SBasis> const &B, unsigned q = 0);
+#endif
+
+
+PathVector path_from_piecewise(Piecewise<D2<SBasis> > const &B, double tol, bool only_cubicbeziers = false);
+
+Path path_from_sbasis(D2<SBasis> const &B, double tol, bool only_cubicbeziers = false);
+inline Path cubicbezierpath_from_sbasis(D2<SBasis> const &B, double tol)
+ { return path_from_sbasis(B, tol, true); }
+
+} // end namespace Geom
+
+#endif
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/sbasis.h b/src/3rdparty/2geom/include/2geom/sbasis.h
new file mode 100644
index 0000000..5cb0e93
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/sbasis.h
@@ -0,0 +1,530 @@
+/** @file
+ * @brief Polynomial in symmetric power basis (S-basis)
+ *//*
+ * Authors:
+ * Nathan Hurst <njh@mail.csse.monash.edu.au>
+ * Michael Sloan <mgsloan@gmail.com>
+ *
+ * Copyright (C) 2006-2007 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_SBASIS_H
+#define LIB2GEOM_SEEN_SBASIS_H
+#include <cassert>
+#include <iostream>
+#include <utility>
+#include <vector>
+
+#include <2geom/linear.h>
+#include <2geom/interval.h>
+#include <2geom/utils.h>
+#include <2geom/exception.h>
+
+//#define USE_SBASISN 1
+
+
+#if defined(USE_SBASIS_OF)
+
+#include "sbasis-of.h"
+
+#elif defined(USE_SBASISN)
+
+#include "sbasisN.h"
+namespace Geom{
+
+/*** An empty SBasis is identically 0. */
+class SBasis : public SBasisN<1>;
+
+};
+#else
+
+namespace Geom {
+
+/**
+ * @brief Polynomial in symmetric power basis
+ * @ingroup Fragments
+ */
+class SBasis {
+ std::vector<Linear> d;
+ void push_back(Linear const&l) { d.push_back(l); }
+
+public:
+ // As part of our migration away from SBasis isa vector we provide this minimal set of vector interface methods.
+ size_t size() const {return d.size();}
+ typedef std::vector<Linear>::iterator iterator;
+ typedef std::vector<Linear>::const_iterator const_iterator;
+ Linear operator[](unsigned i) const {
+ return d[i];
+ }
+ Linear& operator[](unsigned i) { return d.at(i); }
+ const_iterator begin() const { return d.begin();}
+ const_iterator end() const { return d.end();}
+ iterator begin() { return d.begin();}
+ iterator end() { return d.end();}
+ bool empty() const { return d.size() == 1 && d[0][0] == 0 && d[0][1] == 0; }
+ Linear &back() {return d.back();}
+ Linear const &back() const {return d.back();}
+ void pop_back() {
+ if (d.size() > 1) {
+ d.pop_back();
+ } else {
+ d[0][0] = 0;
+ d[0][1] = 0;
+ }
+ }
+ void resize(unsigned n) { d.resize(std::max<unsigned>(n, 1));}
+ void resize(unsigned n, Linear const& l) { d.resize(std::max<unsigned>(n, 1), l);}
+ void reserve(unsigned n) { d.reserve(n);}
+ void clear() {
+ d.resize(1);
+ d[0][0] = 0;
+ d[0][1] = 0;
+ }
+ void insert(iterator before, const_iterator src_begin, const_iterator src_end) { d.insert(before, src_begin, src_end);}
+ Linear& at(unsigned i) { return d.at(i);}
+ //void insert(Linear* before, int& n, Linear const &l) { d.insert(std::vector<Linear>::iterator(before), n, l);}
+ bool operator==(SBasis const&B) const { return d == B.d;}
+ bool operator!=(SBasis const&B) const { return d != B.d;}
+
+ SBasis()
+ : d(1, Linear(0, 0))
+ {}
+ explicit SBasis(double a)
+ : d(1, Linear(a, a))
+ {}
+ explicit SBasis(double a, double b)
+ : d(1, Linear(a, b))
+ {}
+ SBasis(SBasis const &a)
+ : d(a.d)
+ {}
+ SBasis(std::vector<Linear> ls)
+ : d(std::move(ls))
+ {}
+ SBasis(Linear const &bo)
+ : d(1, bo)
+ {}
+ SBasis(Linear* bo)
+ : d(1, bo ? *bo : Linear(0, 0))
+ {}
+ explicit SBasis(size_t n, Linear const&l) : d(n, l) {}
+
+ SBasis(Coord c0, Coord c1, Coord c2, Coord c3)
+ : d(2)
+ {
+ d[0][0] = c0;
+ d[1][0] = c1;
+ d[1][1] = c2;
+ d[0][1] = c3;
+ }
+ SBasis(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4, Coord c5)
+ : d(3)
+ {
+ d[0][0] = c0;
+ d[1][0] = c1;
+ d[2][0] = c2;
+ d[2][1] = c3;
+ d[1][1] = c4;
+ d[0][1] = c5;
+ }
+ SBasis(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4, Coord c5,
+ Coord c6, Coord c7)
+ : d(4)
+ {
+ d[0][0] = c0;
+ d[1][0] = c1;
+ d[2][0] = c2;
+ d[3][0] = c3;
+ d[3][1] = c4;
+ d[2][1] = c5;
+ d[1][1] = c6;
+ d[0][1] = c7;
+ }
+ SBasis(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4, Coord c5,
+ Coord c6, Coord c7, Coord c8, Coord c9)
+ : d(5)
+ {
+ d[0][0] = c0;
+ d[1][0] = c1;
+ d[2][0] = c2;
+ d[3][0] = c3;
+ d[4][0] = c4;
+ d[4][1] = c5;
+ d[3][1] = c6;
+ d[2][1] = c7;
+ d[1][1] = c8;
+ d[0][1] = c9;
+ }
+
+ // construct from a sequence of coefficients
+ template <typename Iter>
+ SBasis(Iter first, Iter last) {
+ assert(std::distance(first, last) % 2 == 0);
+ assert(std::distance(first, last) >= 2);
+ for (; first != last; ++first) {
+ --last;
+ push_back(Linear(*first, *last));
+ }
+ }
+
+ //IMPL: FragmentConcept
+ typedef double output_type;
+ inline bool isZero(double eps=EPSILON) const {
+ assert(size() > 0);
+ for(unsigned i = 0; i < size(); i++) {
+ if(!(*this)[i].isZero(eps)) return false;
+ }
+ return true;
+ }
+ inline bool isConstant(double eps=EPSILON) const {
+ assert(size() > 0);
+ if(!(*this)[0].isConstant(eps)) return false;
+ for (unsigned i = 1; i < size(); i++) {
+ if(!(*this)[i].isZero(eps)) return false;
+ }
+ return true;
+ }
+
+ bool isFinite() const;
+ inline Coord at0() const { return (*this)[0][0]; }
+ inline Coord &at0() { return (*this)[0][0]; }
+ inline Coord at1() const { return (*this)[0][1]; }
+ inline Coord &at1() { return (*this)[0][1]; }
+
+ int degreesOfFreedom() const { return size()*2;}
+
+ double valueAt(double t) const {
+ assert(size() > 0);
+ double s = t*(1-t);
+ double p0 = 0, p1 = 0;
+ for(unsigned k = size(); k > 0; k--) {
+ const Linear &lin = (*this)[k-1];
+ p0 = p0*s + lin[0];
+ p1 = p1*s + lin[1];
+ }
+ return (1-t)*p0 + t*p1;
+ }
+ //double valueAndDerivative(double t, double &der) const {
+ //}
+ double operator()(double t) const {
+ return valueAt(t);
+ }
+
+ std::vector<double> valueAndDerivatives(double t, unsigned n) const;
+
+ SBasis toSBasis() const { return SBasis(*this); }
+
+ double tailError(unsigned tail) const;
+
+// compute f(g)
+ SBasis operator()(SBasis const & g) const;
+
+//MUTATOR PRISON
+ //remove extra zeros
+ void normalize() {
+ while(size() > 1 && back().isZero(0))
+ pop_back();
+ }
+
+ void truncate(unsigned k) { if(k < size()) resize(std::max<size_t>(k, 1)); }
+private:
+ void derive(); // in place version
+};
+
+//TODO: figure out how to stick this in linear, while not adding an sbasis dep
+inline SBasis Linear::toSBasis() const { return SBasis(*this); }
+
+//implemented in sbasis-roots.cpp
+OptInterval bounds_exact(SBasis const &a);
+OptInterval bounds_fast(SBasis const &a, int order = 0);
+OptInterval bounds_local(SBasis const &a, const OptInterval &t, int order = 0);
+
+/** Returns a function which reverses the domain of a.
+ \param a sbasis function
+ \relates SBasis
+
+useful for reversing a parameteric curve.
+*/
+inline SBasis reverse(SBasis const &a) {
+ SBasis result(a.size(), Linear());
+
+ for(unsigned k = 0; k < a.size(); k++)
+ result[k] = reverse(a[k]);
+ return result;
+}
+
+//IMPL: ScalableConcept
+inline SBasis operator-(const SBasis& p) {
+ if(p.isZero()) return SBasis();
+ SBasis result(p.size(), Linear());
+
+ for(unsigned i = 0; i < p.size(); i++) {
+ result[i] = -p[i];
+ }
+ return result;
+}
+SBasis operator*(SBasis const &a, double k);
+inline SBasis operator*(double k, SBasis const &a) { return a*k; }
+inline SBasis operator/(SBasis const &a, double k) { return a*(1./k); }
+SBasis& operator*=(SBasis& a, double b);
+inline SBasis& operator/=(SBasis& a, double b) { return (a*=(1./b)); }
+
+//IMPL: AddableConcept
+SBasis operator+(const SBasis& a, const SBasis& b);
+SBasis operator-(const SBasis& a, const SBasis& b);
+SBasis& operator+=(SBasis& a, const SBasis& b);
+SBasis& operator-=(SBasis& a, const SBasis& b);
+
+//TODO: remove?
+/*inline SBasis operator+(const SBasis & a, Linear const & b) {
+ if(b.isZero()) return a;
+ if(a.isZero()) return b;
+ SBasis result(a);
+ result[0] += b;
+ return result;
+}
+inline SBasis operator-(const SBasis & a, Linear const & b) {
+ if(b.isZero()) return a;
+ SBasis result(a);
+ result[0] -= b;
+ return result;
+}
+inline SBasis& operator+=(SBasis& a, const Linear& b) {
+ if(a.isZero())
+ a.push_back(b);
+ else
+ a[0] += b;
+ return a;
+}
+inline SBasis& operator-=(SBasis& a, const Linear& b) {
+ if(a.isZero())
+ a.push_back(-b);
+ else
+ a[0] -= b;
+ return a;
+ }*/
+
+//IMPL: OffsetableConcept
+inline SBasis operator+(const SBasis & a, double b) {
+ if(a.isZero()) return Linear(b, b);
+ SBasis result(a);
+ result[0] += b;
+ return result;
+}
+inline SBasis operator-(const SBasis & a, double b) {
+ if(a.isZero()) return Linear(-b, -b);
+ SBasis result(a);
+ result[0] -= b;
+ return result;
+}
+inline SBasis& operator+=(SBasis& a, double b) {
+ if(a.isZero())
+ a = SBasis(Linear(b,b));
+ else
+ a[0] += b;
+ return a;
+}
+inline SBasis& operator-=(SBasis& a, double b) {
+ if(a.isZero())
+ a = SBasis(Linear(-b,-b));
+ else
+ a[0] -= b;
+ return a;
+}
+
+SBasis shift(SBasis const &a, int sh);
+SBasis shift(Linear const &a, int sh);
+
+inline SBasis truncate(SBasis const &a, unsigned terms) {
+ SBasis c;
+ c.insert(c.begin(), a.begin(), a.begin() + std::min(terms, (unsigned)a.size()));
+ return c;
+}
+
+SBasis multiply(SBasis const &a, SBasis const &b);
+// This performs a multiply and accumulate operation in about the same time as multiply. return a*b + c
+SBasis multiply_add(SBasis const &a, SBasis const &b, SBasis c);
+
+SBasis integral(SBasis const &c);
+SBasis derivative(SBasis const &a);
+
+SBasis sqrt(SBasis const &a, int k);
+
+// return a kth order approx to 1/a)
+SBasis reciprocal(Linear const &a, int k);
+SBasis divide(SBasis const &a, SBasis const &b, int k);
+
+inline SBasis operator*(SBasis const & a, SBasis const & b) {
+ return multiply(a, b);
+}
+
+inline SBasis& operator*=(SBasis& a, SBasis const & b) {
+ a = multiply(a, b);
+ return a;
+}
+
+/** Returns the degree of the first non zero coefficient.
+ \param a sbasis function
+ \param tol largest abs val considered 0
+ \return first non zero coefficient
+ \relates SBasis
+*/
+inline unsigned
+valuation(SBasis const &a, double tol=0){
+ unsigned val=0;
+ while( val<a.size() &&
+ fabs(a[val][0])<tol &&
+ fabs(a[val][1])<tol )
+ val++;
+ return val;
+}
+
+// a(b(t))
+SBasis compose(SBasis const &a, SBasis const &b);
+SBasis compose(SBasis const &a, SBasis const &b, unsigned k);
+SBasis inverse(SBasis a, int k);
+//compose_inverse(f,g)=compose(f,inverse(g)), but is numerically more stable in some good cases...
+//TODO: requires g(0)=0 & g(1)=1 atm. generalization should be obvious.
+SBasis compose_inverse(SBasis const &f, SBasis const &g, unsigned order=2, double tol=1e-3);
+
+/** Returns the sbasis on domain [0,1] that was t on [from, to]
+ \param t sbasis function
+ \param from,to interval
+ \return sbasis
+ \relates SBasis
+*/
+SBasis portion(const SBasis &t, double from, double to);
+inline SBasis portion(const SBasis &t, Interval const &ivl) { return portion(t, ivl.min(), ivl.max()); }
+
+// compute f(g)
+inline SBasis
+SBasis::operator()(SBasis const & g) const {
+ return compose(*this, g);
+}
+
+inline std::ostream &operator<< (std::ostream &out_file, const Linear &bo) {
+ out_file << "{" << bo[0] << ", " << bo[1] << "}";
+ return out_file;
+}
+
+inline std::ostream &operator<< (std::ostream &out_file, const SBasis & p) {
+ for(unsigned i = 0; i < p.size(); i++) {
+ if (i != 0) {
+ out_file << " + ";
+ }
+ out_file << p[i] << "s^" << i;
+ }
+ return out_file;
+}
+
+// These are deprecated, use sbasis-math.h versions if possible
+SBasis sin(Linear bo, int k);
+SBasis cos(Linear bo, int k);
+
+std::vector<double> roots(SBasis const & s);
+std::vector<double> roots(SBasis const & s, Interval const inside);
+std::vector<std::vector<double> > multi_roots(SBasis const &f,
+ std::vector<double> const &levels,
+ double htol=1e-7,
+ double vtol=1e-7,
+ double a=0,
+ double b=1);
+
+//--------- Levelset like functions -----------------------------------------------------
+
+/** Solve f(t) = v +/- tolerance. The collection of intervals where
+ * v - vtol <= f(t) <= v+vtol
+ * is returned (with a precision tol on the boundaries).
+ \param f sbasis function
+ \param level the value of v.
+ \param vtol: error tolerance on v.
+ \param a, b limit search on domain [a,b]
+ \param tol: tolerance on the result bounds.
+ \returns a vector of intervals.
+*/
+std::vector<Interval> level_set (SBasis const &f,
+ double level,
+ double vtol = 1e-5,
+ double a=0.,
+ double b=1.,
+ double tol = 1e-5);
+
+/** Solve f(t)\in I=[u,v], which defines a collection of intervals (J_k). More precisely,
+ * a collection (J'_k) is returned with J'_k = J_k up to a given tolerance.
+ \param f sbasis function
+ \param level: the given interval of deisred values for f.
+ \param a, b limit search on domain [a,b]
+ \param tol: tolerance on the bounds of the result.
+ \returns a vector of intervals.
+*/
+std::vector<Interval> level_set (SBasis const &f,
+ Interval const &level,
+ double a=0.,
+ double b=1.,
+ double tol = 1e-5);
+
+/** 'Solve' f(t) = v +/- tolerance for several values of v at once.
+ \param f sbasis function
+ \param levels vector of values, that should be sorted.
+ \param vtol: error tolerance on v.
+ \param a, b limit search on domain [a,b]
+ \param tol: the bounds of the returned intervals are exact up to that tolerance.
+ \returns a vector of vectors of intervals.
+*/
+std::vector<std::vector<Interval> > level_sets (SBasis const &f,
+ std::vector<double> const &levels,
+ double a=0.,
+ double b=1.,
+ double vtol = 1e-5,
+ double tol = 1e-5);
+
+/** 'Solve' f(t)\in I=[u,v] for several intervals I at once.
+ \param f sbasis function
+ \param levels vector of 'y' intervals, that should be disjoints and sorted.
+ \param a, b limit search on domain [a,b]
+ \param tol: the bounds of the returned intervals are exact up to that tolerance.
+ \returns a vector of vectors of intervals.
+*/
+std::vector<std::vector<Interval> > level_sets (SBasis const &f,
+ std::vector<Interval> const &levels,
+ double a=0.,
+ double b=1.,
+ double tol = 1e-5);
+
+}
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+#endif
diff --git a/src/3rdparty/2geom/include/2geom/solver.h b/src/3rdparty/2geom/include/2geom/solver.h
new file mode 100644
index 0000000..5b082cb
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/solver.h
@@ -0,0 +1,88 @@
+/**
+ * \file
+ * \brief Finding roots of Bernstein-Bezier polynomials
+ *//*
+ * Authors:
+ * ? <?@?.?>
+ *
+ * Copyright ?-? authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_SOLVER_H
+#define LIB2GEOM_SEEN_SOLVER_H
+
+#include <2geom/point.h>
+#include <2geom/sbasis.h>
+#include <vector>
+
+namespace Geom {
+
+ class Point;
+ class Bezier;
+
+unsigned
+crossing_count(Geom::Point const *V, /* Control pts of Bezier curve */
+ unsigned degree); /* Degree of Bezier curve */
+void
+find_parametric_bezier_roots(
+ Geom::Point const *w, /* The control points */
+ unsigned degree, /* The degree of the polynomial */
+ std::vector<double> & solutions, /* RETURN candidate t-values */
+ unsigned depth); /* The depth of the recursion */
+
+unsigned
+crossing_count(double const *V, /* Control pts of Bezier curve */
+ unsigned degree, /* Degree of Bezier curve */
+ double left_t, double right_t);
+
+
+void
+find_bernstein_roots(
+ double const *w, /* The control points */
+ unsigned degree, /* The degree of the polynomial */
+ std::vector<double> & solutions, /* RETURN candidate t-values */
+ unsigned depth, /* The depth of the recursion */
+ double left_t=0, double right_t=1, bool use_secant=true);
+
+};
+
+void
+find_bernstein_roots(std::vector<double> &solutions, /* RETURN candidate t-values */
+ Geom::Bezier const& bz,
+ double left_t, double right_t);
+
+#endif
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/svg-path-parser.h b/src/3rdparty/2geom/include/2geom/svg-path-parser.h
new file mode 100644
index 0000000..e25316c
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/svg-path-parser.h
@@ -0,0 +1,199 @@
+/**
+ * \file
+ * \brief parse SVG path specifications
+ *
+ * Copyright 2007 MenTaLguY <mental@rydia.net>
+ * Copyright 2007 Aaron Spike <aaron@ekips.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_SVG_PATH_PARSER_H
+#define LIB2GEOM_SEEN_SVG_PATH_PARSER_H
+
+#include <iostream>
+#include <iterator>
+#include <stdexcept>
+#include <vector>
+#include <cstdio>
+#include <2geom/exception.h>
+#include <2geom/point.h>
+#include <2geom/path-sink.h>
+#include <2geom/forward.h>
+
+namespace Geom {
+
+/** @brief Read SVG path data and feed it to a PathSink
+ *
+ * This class provides an interface to an SVG path data parser written in Ragel.
+ * It supports parsing the path data either at once or block-by-block.
+ * Use the parse() functions to parse complete data and the feed() and finish()
+ * functions to parse partial data.
+ *
+ * The parser will call the appropriate methods on the PathSink supplied
+ * at construction. To store the path in memory as a PathVector, pass
+ * a PathBuilder. You can also use one of the freestanding helper functions
+ * if you don't need to parse data block-by-block.
+ *
+ * @ingroup Paths
+ */
+class SVGPathParser {
+public:
+ SVGPathParser(PathSink &sink);
+ ~SVGPathParser();
+
+ /** @brief Reset internal state.
+ * Discards the internal state associated with partially parsed data,
+ * letting you start from scratch. Note that any partial data written
+ * to the path sink is not affected - you need to clear it yourself. */
+ void reset();
+
+ /** @brief Parse a C-style string.
+ * The path sink is flushed and the internal state is reset after this call.
+ * Note that the state is not reset before this method, so you can use it to
+ * process the last block of partial data.
+ * @param str String to parse
+ * @param len Length of string or -1 if null-terminated */
+ void parse(char const *str, int len = -1);
+ /** @brief Parse an STL string. */
+ void parse(std::string const &s);
+
+ /** @brief Parse a part of path data stored in a C-style string.
+ * This method does not reset internal state, so it can be called multiple
+ * times to parse successive blocks of a longer SVG path data string.
+ * To finish parsing, call finish() after the final block or call parse()
+ * with the last block of data.
+ * @param str String to parse
+ * @param len Length of string or -1 if null-terminated */
+ void feed(char const *str, int len = -1);
+ /** @brief Parse a part of path data stored in an STL string. */
+ void feed(std::string const &s);
+
+ /** @brief Finalize parsing.
+ * After the last block of data was submitted with feed(), call this method
+ * to finalize parsing, flush the path sink and reset internal state.
+ * You should not call this after parse(). */
+ void finish();
+
+ /** @brief Set the threshold for considering the closing segment degenerate.
+ * When the current point was reached by a relative command, is closer
+ * to the initial point of the path than the specified threshold
+ * and a 'z' is encountered, the last segment will be adjusted instead so that
+ * the closing segment has exactly zero length. This is useful when reading
+ * SVG 1.1 paths that have non-linear final segments written in relative
+ * coordinates, which always suffer from some loss of precision. SVG 2
+ * allows alternate placement of 'z' which does not have this problem. */
+ void setZSnapThreshold(Coord threshold) { _z_snap_threshold = threshold; }
+ Coord zSnapThreshold() const { return _z_snap_threshold; }
+
+private:
+ bool _absolute;
+ bool _moveto_was_absolute;
+ Point _current;
+ Point _initial;
+ Point _cubic_tangent;
+ Point _quad_tangent;
+ std::vector<Coord> _params;
+ PathSink &_sink;
+ Coord _z_snap_threshold;
+ Curve *_curve;
+
+ int cs;
+ std::string _number_part;
+
+ void _push(Coord value);
+ Coord _pop();
+ bool _pop_flag();
+ Coord _pop_coord(Geom::Dim2 axis);
+ Point _pop_point();
+ void _moveTo(Point const &p);
+ void _lineTo(Point const &p);
+ void _curveTo(Point const &c0, Point const &c1, Point const &p);
+ void _quadTo(Point const &c, Point const &p);
+ void _arcTo(double rx, double ry, double angle,
+ bool large_arc, bool sweep, Point const &p);
+ void _closePath();
+ void _pushCurve(Curve *c);
+
+ void _parse(char const *str, char const *strend, bool finish);
+};
+
+/** @brief Feed SVG path data to the specified sink
+ * @ingroup Paths */
+void parse_svg_path(char const *str, PathSink &sink);
+/** @brief Feed SVG path data to the specified sink
+ * @ingroup Paths */
+inline void parse_svg_path(std::string const &str, PathSink &sink) {
+ parse_svg_path(str.c_str(), sink);
+}
+/** Feed SVG path data from a C stream to the specified sink
+ * @ingroup Paths */
+void parse_svg_path_file(FILE *fi, PathSink &sink);
+
+/** @brief Create path vector from SVG path data stored in a C string
+ * @ingroup Paths */
+inline PathVector parse_svg_path(char const *str) {
+ PathVector ret;
+ SubpathInserter iter(ret);
+ PathIteratorSink<SubpathInserter> generator(iter);
+
+ parse_svg_path(str, generator);
+ return ret;
+}
+
+/** @brief Create path vector from a C stream with SVG path data
+ * @ingroup Paths */
+inline PathVector read_svgd_f(FILE * fi) {
+ PathVector ret;
+ SubpathInserter iter(ret);
+ PathIteratorSink<SubpathInserter> generator(iter);
+
+ parse_svg_path_file(fi, generator);
+ return ret;
+}
+
+/** @brief Create path vector from SVG path data stored in a file
+ * @ingroup Paths */
+inline PathVector read_svgd(char const *filename) {
+ FILE* fi = fopen(filename, "r");
+ if(fi == NULL) throw(std::runtime_error("Error opening file"));
+ PathVector out = read_svgd_f(fi);
+ fclose(fi);
+ return out;
+}
+
+} // end namespace Geom
+
+#endif
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/svg-path-writer.h b/src/3rdparty/2geom/include/2geom/svg-path-writer.h
new file mode 100644
index 0000000..92a80ec
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/svg-path-writer.h
@@ -0,0 +1,122 @@
+/** @file
+ * @brief Path sink which writes an SVG-compatible command string
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2014 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_SVG_PATH_WRITER_H
+#define LIB2GEOM_SEEN_SVG_PATH_WRITER_H
+
+#include <2geom/path-sink.h>
+#include <sstream>
+
+namespace Geom {
+
+/** @brief Serialize paths to SVG path data strings.
+ * You can access the generated string by calling the str() method.
+ * @ingroup Paths
+ */
+class SVGPathWriter
+ : public PathSink
+{
+public:
+ SVGPathWriter();
+ ~SVGPathWriter() override {}
+
+ void moveTo(Point const &p) override;
+ void lineTo(Point const &p) override;
+ void quadTo(Point const &c, Point const &p) override;
+ void curveTo(Point const &c0, Point const &c1, Point const &p) override;
+ void arcTo(double rx, double ry, double angle,
+ bool large_arc, bool sweep, Point const &p) override;
+ void closePath() override;
+ void flush() override;
+
+ /// Clear any path data written so far.
+ void clear();
+
+ /** @brief Set output precision.
+ * When the parameter is negative, the path writer enters a verbatim mode
+ * which preserves all values exactly. */
+ void setPrecision(int prec);
+
+ /** @brief Enable or disable length optimization.
+ *
+ * When set to true, the path writer will optimize the generated path data
+ * for minimum length. However, this will make the data less readable,
+ * because spaces between commands and coordinates will be omitted where
+ * unnecessary for correct parsing.
+ *
+ * When set to false, the string will be a straightforward, partially redundant
+ * representation of the passed commands, optimized for readability.
+ * Commands and coordinates will always be separated by spaces and the command
+ * symbol will not be omitted for multiple consecutive commands of the same type.
+ *
+ * Length optimization is turned off by default. */
+ void setOptimize(bool opt) { _optimize = opt; }
+
+ /** @brief Enable or disable the use of V, H, T and S commands where possible.
+ * Shorthands are turned on by default. */
+ void setUseShorthands(bool use) { _use_shorthands = use; }
+
+ /// Retrieve the generated path data string.
+ std::string str() const { return _s.str(); }
+
+private:
+ void _setCommand(char cmd);
+ std::string _formatCoord(Coord par);
+
+ std::ostringstream _s, _ns;
+ std::vector<Coord> _current_pars;
+ Point _subpath_start;
+ Point _current;
+ Point _quad_tangent;
+ Point _cubic_tangent;
+ Coord _epsilon;
+ int _precision;
+ bool _optimize;
+ bool _use_shorthands;
+ char _command;
+};
+
+std::string write_svg_path(PathVector const &pv, int prec = -1, bool optimize = false, bool shorthands = true);
+
+} // namespace Geom
+
+#endif // LIB2GEOM_SEEN_SVG_PATH_WRITER_H
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/sweep-bounds.h b/src/3rdparty/2geom/include/2geom/sweep-bounds.h
new file mode 100644
index 0000000..e0ebf29
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/sweep-bounds.h
@@ -0,0 +1,62 @@
+/**
+ * \file
+ * \brief Sweepline intersection of groups of rectangles
+ *//*
+ * Authors:
+ * ? <?@?.?>
+ *
+ * Copyright ?-? authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_SWEEP_H
+#define LIB2GEOM_SEEN_SWEEP_H
+
+#include <vector>
+#include <2geom/d2.h>
+
+namespace Geom {
+
+std::vector<std::vector<unsigned> >
+sweep_bounds(std::vector<Rect>, Dim2 dim = X);
+
+std::vector<std::vector<unsigned> >
+sweep_bounds(std::vector<Rect>, std::vector<Rect>, Dim2 dim = X);
+
+}
+
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/sweeper.h b/src/3rdparty/2geom/include/2geom/sweeper.h
new file mode 100644
index 0000000..233d181
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/sweeper.h
@@ -0,0 +1,189 @@
+/** @file
+ * @brief Class for implementing sweepline algorithms
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_SWEEPER_H
+#define LIB2GEOM_SEEN_SWEEPER_H
+
+#include <2geom/coord.h>
+#include <algorithm>
+#include <vector>
+#include <boost/intrusive/list.hpp>
+
+namespace Geom {
+
+// exposition only
+template <typename Item>
+class SweepVector {
+public:
+ typedef typename std::vector<Item>::const_iterator ItemIterator;
+
+ SweepVector(std::vector<Item> const &v)
+ : _items(v)
+ {}
+
+ std::vector<Item> const &items() { return _items; }
+ Interval itemBounds(ItemIterator /*ii*/) { return Interval(); }
+
+ void addActiveItem(ItemIterator /*ii*/) {}
+ void removeActiveItem(ItemIterator /*ii*/) {}
+
+private:
+ std::vector<Item> const &_items;
+};
+
+/** @brief Generic sweepline algorithm.
+ *
+ * This class encapsulates an algorithm that sorts the objects according
+ * to their bounds, then moves an imaginary line (sweepline) over those
+ * bounds from left to right. Objects are added to the active list when
+ * the line starts intersecting their bounds, and removed when it completely
+ * passes over them.
+ *
+ * To use this, create a class that exposes the following methods:
+ * - Range items() - returns a forward iterable range of items that will be swept.
+ * - Interval itemBounds(iterator i) - given an iterator from the above range,
+ * compute the bounding interval of the referenced item in the direction of sweep.
+ * - void addActiveItem(iterator i) - add an item to the active list.
+ * - void removeActiveItem(iterator i) - remove an item from the active list.
+ *
+ * Create the object, then instantiate this template with the above class
+ * as the template parameter, pass it the constructed object of the class,
+ * and call the process() method.
+ *
+ * A good choice for the active list is a Boost intrusive list, which allows
+ * you to get an iterator from a value in constant time.
+ *
+ * Look in path.cpp for example usage.
+ *
+ * @tparam Item The type of items to sweep
+ * @tparam SweepTraits Traits class that defines the items' bounds,
+ * how to interpret them and how to sort the events
+ * @ingroup Utilities
+ */
+template <typename SweepSet>
+class Sweeper {
+public:
+ typedef typename SweepSet::ItemIterator Iter;
+
+ explicit Sweeper(SweepSet &set)
+ : _set(set)
+ {
+ std::size_t sz = std::distance(set.items().begin(), set.items().end());
+ _entry_events.reserve(sz);
+ _exit_events.reserve(sz);
+ }
+
+ /** @brief Process entry and exit events.
+ * This will iterate over all inserted items, calling the methods
+ * addActiveItem and removeActiveItem on the SweepSet passed at construction
+ * according to the order of the boundaries of each item. */
+ void process() {
+ if (_set.items().empty()) return;
+
+ Iter last = _set.items().end();
+ for (Iter i = _set.items().begin(); i != last; ++i) {
+ Interval b = _set.itemBounds(i);
+ // guard against NANs
+ assert(b.min() == b.min() && b.max() == b.max());
+ _entry_events.push_back(Event(b.max(), i));
+ _exit_events.push_back(Event(b.min(), i));
+ }
+
+ std::make_heap(_entry_events.begin(), _entry_events.end());
+ std::make_heap(_exit_events.begin(), _exit_events.end());
+
+ Event next_entry = _get_next(_entry_events);
+ Event next_exit = _get_next(_exit_events);
+
+ while (next_entry || next_exit) {
+ assert(next_exit);
+
+ if (!next_entry || next_exit > next_entry) {
+ // exit event - remove record from active list
+ _set.removeActiveItem(next_exit.item);
+ next_exit = _get_next(_exit_events);
+ } else {
+ // entry event - add record to active list
+ _set.addActiveItem(next_entry.item);
+ next_entry = _get_next(_entry_events);
+ }
+ }
+ }
+
+private:
+ struct Event
+ : boost::totally_ordered<Event>
+ {
+ Coord coord;
+ Iter item;
+
+ Event(Coord c, Iter const &i)
+ : coord(c), item(i)
+ {}
+ Event()
+ : coord(nan("")), item()
+ {}
+ bool operator<(Event const &other) const { return coord < other.coord; }
+ bool operator==(Event const &other) const { return coord == other.coord; }
+ operator bool() const { return !std::isnan(coord); }
+ };
+
+ static Event _get_next(std::vector<Event> &heap) {
+ if (heap.empty()) {
+ Event e;
+ return e;
+ }
+ std::pop_heap(heap.begin(), heap.end());
+ Event ret = heap.back();
+ heap.pop_back();
+ return ret;
+ }
+
+ SweepSet &_set;
+ std::vector<Event> _entry_events;
+ std::vector<Event> _exit_events;
+};
+
+} // namespace Geom
+
+#endif // !LIB2GEOM_SEEN_SWEEPER_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/symbolic/determinant-minor.h b/src/3rdparty/2geom/include/2geom/symbolic/determinant-minor.h
new file mode 100644
index 0000000..d70c397
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/symbolic/determinant-minor.h
@@ -0,0 +1,175 @@
+/*
+ * GiNaC Copyright (C) 1999-2008 Johannes Gutenberg University Mainz, Germany
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _GEOM_SL_DETERMINANT_MINOR_H_
+#define _GEOM_SL_DETERMINANT_MINOR_H_
+
+#include <map>
+
+
+namespace Geom { namespace SL {
+
+/*
+ * determinant_minor
+ * This routine has been taken from the ginac project
+ * and adapted as needed; comments are the original ones.
+ */
+
+/** Recursive determinant for small matrices having at least one symbolic
+ * entry. The basic algorithm, known as Laplace-expansion, is enhanced by
+ * some bookkeeping to avoid calculation of the same submatrices ("minors")
+ * more than once. According to W.M.Gentleman and S.C.Johnson this algorithm
+ * is better than elimination schemes for matrices of sparse multivariate
+ * polynomials and also for matrices of dense univariate polynomials if the
+ * matrix' dimesion is larger than 7.
+ *
+ * @return the determinant as a new expression (in expanded form)
+ * @see matrix::determinant() */
+
+template< typename Coeff >
+Coeff determinant_minor(Matrix<Coeff> const& M)
+{
+ assert(M.rows() == M.columns());
+ // for small matrices the algorithm does not make any sense:
+ const unsigned int n = M.columns();
+ if (n == 1)
+ return M(0,0);
+ if (n == 2)
+ return (M(0,0) * M(1,1) - M(0,1) * M(1,0));
+ if (n == 3)
+ return ( M(0,0)*M(1,1)*M(2,2) + M(0,2)*M(1,0)*M(2,1)
+ + M(0,1)*M(1,2)*M(2,0) - M(0,2)*M(1,1)*M(2,0)
+ - M(0,0)*M(1,2)*M(2,1) - M(0,1)*M(1,0)*M(2,2) );
+
+ // This algorithm can best be understood by looking at a naive
+ // implementation of Laplace-expansion, like this one:
+ // ex det;
+ // matrix minorM(this->rows()-1,this->cols()-1);
+ // for (unsigned r1=0; r1<this->rows(); ++r1) {
+ // // shortcut if element(r1,0) vanishes
+ // if (m[r1*col].is_zero())
+ // continue;
+ // // assemble the minor matrix
+ // for (unsigned r=0; r<minorM.rows(); ++r) {
+ // for (unsigned c=0; c<minorM.cols(); ++c) {
+ // if (r<r1)
+ // minorM(r,c) = m[r*col+c+1];
+ // else
+ // minorM(r,c) = m[(r+1)*col+c+1];
+ // }
+ // }
+ // // recurse down and care for sign:
+ // if (r1%2)
+ // det -= m[r1*col] * minorM.determinant_minor();
+ // else
+ // det += m[r1*col] * minorM.determinant_minor();
+ // }
+ // return det.expand();
+ // What happens is that while proceeding down many of the minors are
+ // computed more than once. In particular, there are binomial(n,k)
+ // kxk minors and each one is computed factorial(n-k) times. Therefore
+ // it is reasonable to store the results of the minors. We proceed from
+ // right to left. At each column c we only need to retrieve the minors
+ // calculated in step c-1. We therefore only have to store at most
+ // 2*binomial(n,n/2) minors.
+
+ // Unique flipper counter for partitioning into minors
+ std::vector<unsigned int> Pkey;
+ Pkey.reserve(n);
+ // key for minor determinant (a subpartition of Pkey)
+ std::vector<unsigned int> Mkey;
+ Mkey.reserve(n-1);
+ // we store our subminors in maps, keys being the rows they arise from
+ typedef typename std::map<std::vector<unsigned>, Coeff> Rmap;
+ typedef typename std::map<std::vector<unsigned>, Coeff>::value_type Rmap_value;
+ Rmap A;
+ Rmap B;
+ Coeff det;
+ // initialize A with last column:
+ for (unsigned int r = 0; r < n; ++r)
+ {
+ Pkey.erase(Pkey.begin(),Pkey.end());
+ Pkey.push_back(r);
+ A.insert(Rmap_value(Pkey,M(r,n-1)));
+ }
+ // proceed from right to left through matrix
+ for (int c = n-2; c >= 0; --c)
+ {
+ Pkey.erase(Pkey.begin(),Pkey.end()); // don't change capacity
+ Mkey.erase(Mkey.begin(),Mkey.end());
+ for (unsigned int i = 0; i < n-c; ++i)
+ Pkey.push_back(i);
+ unsigned int fc = 0; // controls logic for our strange flipper counter
+ do
+ {
+ det = Geom::SL::zero<Coeff>()();
+ for (unsigned int r = 0; r < n-c; ++r)
+ {
+ // maybe there is nothing to do?
+ if (M(Pkey[r], c).is_zero())
+ continue;
+ // create the sorted key for all possible minors
+ Mkey.erase(Mkey.begin(),Mkey.end());
+ for (unsigned int i = 0; i < n-c; ++i)
+ if (i != r)
+ Mkey.push_back(Pkey[i]);
+ // Fetch the minors and compute the new determinant
+ if (r % 2)
+ det -= M(Pkey[r],c)*A[Mkey];
+ else
+ det += M(Pkey[r],c)*A[Mkey];
+ }
+ // store the new determinant at its place in B:
+ if (!det.is_zero())
+ B.insert(Rmap_value(Pkey,det));
+ // increment our strange flipper counter
+ for (fc = n-c; fc > 0; --fc)
+ {
+ ++Pkey[fc-1];
+ if (Pkey[fc-1]<fc+c)
+ break;
+ }
+ if (fc < n-c && fc > 0)
+ for (unsigned int j = fc; j < n-c; ++j)
+ Pkey[j] = Pkey[j-1]+1;
+ } while(fc);
+ // next column, so change the role of A and B:
+ A.swap(B);
+ B.clear();
+ }
+
+ return det;
+}
+
+
+
+} /*end namespace Geom*/ } /*end namespace SL*/
+
+#endif // _GEOM_SL_DETERMINANT_MINOR_H_
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/symbolic/implicit.h b/src/3rdparty/2geom/include/2geom/symbolic/implicit.h
new file mode 100644
index 0000000..82d77cd
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/symbolic/implicit.h
@@ -0,0 +1,353 @@
+/*
+ * Routines to compute the implicit equation of a parametric polynomial curve
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#ifndef _GEOM_SL_IMPLICIT_H_
+#define _GEOM_SL_IMPLICIT_H_
+
+
+
+#include <2geom/symbolic/multipoly.h>
+#include <2geom/symbolic/matrix.h>
+
+
+#include <2geom/exception.h>
+
+#include <array>
+
+
+namespace Geom { namespace SL {
+
+typedef MultiPoly<1, double> MVPoly1;
+typedef MultiPoly<2, double> MVPoly2;
+typedef MultiPoly<3, double> MVPoly3;
+typedef std::array<MVPoly1, 3> poly_vector_type;
+typedef std::array<poly_vector_type, 2> basis_type;
+typedef std::array<double, 3> coeff_vector_type;
+
+namespace detail {
+
+/*
+ * transform a univariate polynomial f(t) in a 3-variate polynomial
+ * p(t, x, y) = f(t) * x^i * y^j
+ */
+inline
+void poly1_to_poly3(MVPoly3 & p3, MVPoly1 const& p1, size_t i, size_t j)
+{
+ multi_index_type I = make_multi_index(0, i, j);
+ for (; I[0] < p1.get_poly().size(); ++I[0])
+ {
+ p3.coefficient(I, p1[I[0]]);
+ }
+}
+
+/*
+ * evaluates the degree of a poly_vector_type, such a degree is defined as:
+ * deg({p[0](t), p[1](t), p[2](t)}) := {max(deg(p[i](t)), i = 0, 1, 2), k}
+ * here k is the index where the max is achieved,
+ * if deg(p[i](t)) == deg(p[j](t)) and i < j then k = i
+ */
+inline
+std::pair<size_t, size_t> deg(poly_vector_type const& p)
+{
+ std::pair<size_t, size_t> d;
+ d.first = p[0].get_poly().real_degree();
+ d.second = 0;
+ size_t k = p[1].get_poly().real_degree();
+ if (d.first < k)
+ {
+ d.first = k;
+ d.second = 1;
+ }
+ k = p[2].get_poly().real_degree();
+ if (d.first < k)
+ {
+ d.first = k;
+ d.second = 2;
+ }
+ return d;
+}
+
+} // end namespace detail
+
+
+/*
+ * A polynomial parametrization could be seen as 1-variety V in R^3,
+ * intersection of two surfaces x = f(t), y = g(t), this variety V has
+ * attached an ideal I in the ring of polynomials in t, x, y with coefficients
+ * on reals; a basis of generators for I is given by p(t, x, y) = x - f(t),
+ * q(t, x, y) = y - g(t); such a basis has the nice property that could be
+ * written as a couple of vectors of dim 3 with entries in R[t]; the original
+ * polinomials p and q can be obtained by doing a dot product between each
+ * vector and the vector {x, y, 1}
+ * As reference you can read the text book:
+ * Ideals, Varieties and Algorithms by Cox, Little, O'Shea
+ */
+inline
+void make_initial_basis(basis_type& b, MVPoly1 const& p, MVPoly1 const& q)
+{
+ // first basis vector
+ b[0][0] = 1;
+ b[0][1] = 0;
+ b[0][2] = -p;
+
+ // second basis vector
+ b[1][0] = 0;
+ b[1][1] = 1;
+ b[1][2] = -q;
+}
+
+/*
+ * Starting from the initial basis for the ideal I is possible to make up
+ * a new basis, still showing off the nice property that each generator is
+ * a moving line that is a linear combination of x, y, 1 where the coefficients
+ * are polynomials in R[t], and moreover each generator is of minimal degree.
+ * Can be proved that given a polynomial parametrization f(t), g(t)
+ * we are able to make up a "micro" basis of generators p(t, x, y), q(t, x, y)
+ * for the ideal I such that the deg(p, t) = m <= n/2 and deg(q, t) = n - m,
+ * where n = max(deg(f(t)), deg(g(t))); this let us halve the order of
+ * the Bezout matrix.
+ * Reference:
+ * Zheng, Sederberg - A Direct Approach to Computing the micro-basis
+ * of a Planar Rational Curves
+ * Deng, Chen, Shen - Computing micro-Basis of Rational Curves and Surfaces
+ * Using Polynomial Matrix Factorization
+ */
+inline
+void microbasis(basis_type& b, MVPoly1 const& p, MVPoly1 const& q)
+{
+ typedef std::pair<size_t, size_t> degree_pair_t;
+
+ size_t n = std::max(p.get_poly().real_degree(), q.get_poly().real_degree());
+ make_initial_basis(b, p, q);
+ degree_pair_t n0 = detail::deg(b[0]);
+ degree_pair_t n1 = detail::deg(b[1]);
+ size_t d;
+ double r0, r1;
+ //size_t iter = 0;
+ while ((n0.first + n1.first) > n)// && iter < 30)
+ {
+// ++iter;
+// std::cout << "iter = " << iter << std::endl;
+// for (size_t i= 0; i < 2; ++i)
+// for (size_t j= 0; j < 3; ++j)
+// std::cout << b[i][j] << std::endl;
+// std::cout << n0.first << ", " << n0.second << std::endl;
+// std::cout << n1.first << ", " << n1.second << std::endl;
+// std::cout << "-----" << std::endl;
+// if (n0.first < n1.first)
+// {
+// d = n1.first - n0.first;
+// r = b[1][n1.second][n1.first] / b[0][n1.second][n0.first];
+// for (size_t i = 0; i < b[0].size(); ++i)
+// b[1][i] -= ((r * b[0][i]).get_poly() << d);
+// b[1][n1.second][n1.first] = 0;
+// n1 = detail::deg(b[1]);
+// }
+// else
+// {
+// d = n0.first - n1.first;
+// r = b[0][n0.second][n0.first] / b[1][n0.second][n1.first];
+// for (size_t i = 0; i < b[0].size(); ++i)
+// b[0][i] -= ((r * b[1][i]).get_poly() << d);
+// b[0][n0.second][n0.first] = 0;
+// n0 = detail::deg(b[0]);
+// }
+
+ // this version shouldn't suffer of ill-conditioning due to
+ // cancellation issue
+ if (n0.first < n1.first)
+ {
+ d = n1.first - n0.first;
+ r0 = b[0][n1.second][n0.first];
+ r1 = b[1][n1.second][n1.first];
+ for (size_t i = 0; i < b[0].size(); ++i)
+ {
+ b[1][i] *= r0;
+ b[1][i] -= ((r1 * b[0][i]).get_poly() << d);
+ // without the following division the modulus grows
+ // beyond the limit of the double type
+ b[1][i] /= r0;
+ }
+ n1 = detail::deg(b[1]);
+ }
+ else
+ {
+ d = n0.first - n1.first;
+ r0 = b[0][n1.second][n0.first];
+ r1 = b[1][n1.second][n1.first];
+
+ for (size_t i = 0; i < b[0].size(); ++i)
+ {
+ b[0][i] *= r1;
+ b[0][i] -= ((r0 * b[1][i]).get_poly() << d);
+ b[0][i] /= r1;
+ }
+ n0 = detail::deg(b[0]);
+ }
+
+ }
+}
+
+/*
+ * computes the dot product:
+ * p(t, x, y) = {p0(t), p1(t), p2(t)} . {x, y, 1}
+ */
+inline
+void basis_to_poly(MVPoly3 & p0, poly_vector_type const& v)
+{
+ MVPoly3 p1, p2;
+ detail::poly1_to_poly3(p0, v[0], 1,0);
+ detail::poly1_to_poly3(p1, v[1], 0,1);
+ detail::poly1_to_poly3(p2, v[2], 0,0);
+ p0 += p1;
+ p0 += p2;
+}
+
+
+/*
+ * Make up a Bezout matrix with two basis genarators as input.
+ *
+ * A Bezout matrix is the matrix related to the symmetric bilinear form
+ * (f,g) -> B[f,g] where B[f,g](s,t) = (f(t)*g(s) - f(s)*g(t))/(s-t)
+ * where f, g are polynomials, this function is called a bezoutian.
+ * Given a basis of generators {p(t, x, y), q(t, x, y)} for the ideal I
+ * related to our parametrization x = f(t), y = g(t), we are able to prove
+ * that the implicit equation of such polynomial parametrization can be
+ * evaluated computing the determinant of the Bezout matrix made up using
+ * the polinomial p and q as univariate polynomials in t with coefficients
+ * in R[x,y], so the resulting Bezout matrix will be a matrix with bivariate
+ * polynomials as entries. A Bezout matrix is always symmetric.
+ * Reference:
+ * Sederberg, Zheng - Algebraic Methods for Computer Aided Geometric Design
+ */
+Matrix<MVPoly2>
+make_bezout_matrix (MVPoly3 const& p, MVPoly3 const& q)
+{
+ size_t pdeg = p.get_poly().real_degree();
+ size_t qdeg = q.get_poly().real_degree();
+ size_t n = std::max(pdeg, qdeg);
+
+ Matrix<MVPoly2> BM(n, n);
+ //std::cerr << "rows, columns " << BM.rows() << " , " << BM.columns() << std::endl;
+ for (size_t i = n; i >= 1; --i)
+ {
+ for (size_t j = n; j >= i; --j)
+ {
+ size_t m = std::min(i, n + 1 - j);
+ //std::cerr << "m = " << m << std::endl;
+ for (size_t k = 1; k <= m; ++k)
+ {
+ //BM(i-1,j-1) += (p[j-1+k] * q[i-k] - p[i-k] * q[j-1+k]);
+ BM(n-i,n-j) += (p.coefficient(j-1+k) * q.coefficient(i-k)
+ - p.coefficient(i-k) * q.coefficient(j-1+k));
+ }
+ }
+ }
+
+ for (size_t i = 0; i < n; ++i)
+ {
+ for (size_t j = 0; j < i; ++j)
+ BM(j,i) = BM(i,j);
+ }
+ return BM;
+}
+
+/*
+ * Make a matrix that represents a main minor (i.e. with the diagonal
+ * on the diagonal of the matrix to which it owns) of the Bezout matrix
+ * with order n-1 where n is the order of the Bezout matrix.
+ * The minor is obtained by removing the "h"-th row and the "h"-th column,
+ * and as the Bezout matrix is symmetric.
+ */
+Matrix<MVPoly2>
+make_bezout_main_minor (MVPoly3 const& p, MVPoly3 const& q, size_t h)
+{
+ size_t pdeg = p.get_poly().real_degree();
+ size_t qdeg = q.get_poly().real_degree();
+ size_t n = std::max(pdeg, qdeg);
+
+ Matrix<MVPoly2> BM(n-1, n-1);
+ size_t u = 0, v;
+ for (size_t i = 1; i <= n; ++i)
+ {
+ v = 0;
+ if (i == h)
+ {
+ u = 1;
+ continue;
+ }
+ for (size_t j = 1; j <= i; ++j)
+ {
+ if (j == h)
+ {
+ v = 1;
+ continue;
+ }
+ size_t m = std::min(i, n + 1 - j);
+ for (size_t k = 1; k <= m; ++k)
+ {
+ //BM(i-u-1,j-v-1) += (p[j-1+k] * q[i-k] - p[i-k] * q[j-1+k]);
+ BM(i-u-1,j-v-1) += (p.coefficient(j-1+k) * q.coefficient(i-k)
+ - p.coefficient(i-k) * q.coefficient(j-1+k));
+ }
+ }
+ }
+
+ --n;
+ for (size_t i = 0; i < n; ++i)
+ {
+ for (size_t j = 0; j < i; ++j)
+ BM(j,i) = BM(i,j);
+ }
+ return BM;
+}
+
+
+} /*end namespace Geom*/ } /*end namespace SL*/
+
+
+
+
+#endif // _GEOM_SL_IMPLICIT_H_
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/symbolic/matrix.h b/src/3rdparty/2geom/include/2geom/symbolic/matrix.h
new file mode 100644
index 0000000..d9dc690
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/symbolic/matrix.h
@@ -0,0 +1,265 @@
+/*
+ * Matrix<CoeffT> class template
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+
+#ifndef _GEOM_SL_MATRIX_H_
+#define _GEOM_SL_MATRIX_H_
+
+
+#include <array>
+#include <vector>
+#include <map>
+
+#include <2geom/point.h>
+#include <2geom/numeric/matrix.h>
+#include <2geom/symbolic/multipoly.h>
+
+
+
+
+namespace Geom { namespace SL {
+
+/*
+ * generic Matrix class template
+ * needed for building up a matrix with polynomial entries
+ */
+template< typename Coeff>
+class Matrix
+{
+ public:
+ typedef Coeff coeff_type;
+ typedef std::vector<coeff_type> container_type;
+
+ Matrix()
+ {}
+
+ Matrix(size_t m, size_t n)
+ : m_data(m*n), m_rows(m), m_columns(n)
+ {
+ }
+
+ void resize(size_t m, size_t n)
+ {
+ m_data.resize(m,n);
+ m_rows = m;
+ m_columns = n;
+ }
+
+ size_t rows() const
+ {
+ return m_rows;
+ }
+
+ size_t columns() const
+ {
+ return m_columns;
+ }
+
+ coeff_type const& operator() (size_t i, size_t j) const
+ {
+ return m_data[i * columns() + j];
+ }
+
+ coeff_type & operator() (size_t i, size_t j)
+ {
+ return m_data[i * columns() + j];
+ }
+
+
+ private:
+ container_type m_data;
+ size_t m_rows;
+ size_t m_columns;
+};
+
+
+template< typename Coeff, typename charT >
+inline
+std::basic_ostream<charT> &
+operator<< ( std::basic_ostream<charT> & os,
+ const Matrix<Coeff> & _matrix )
+{
+ if (_matrix.rows() == 0 || _matrix.columns() == 0) return os;
+
+ os << "{{" << _matrix(0,0);
+ for (size_t j = 1; j < _matrix.columns(); ++j)
+ {
+ os << ", " << _matrix(0,j);
+ }
+ os << "}";
+
+ for (size_t i = 1; i < _matrix.rows(); ++i)
+ {
+ os << ", {" << _matrix(i,0);
+ for (size_t j = 1; j < _matrix.columns(); ++j)
+ {
+ os << ", " << _matrix(i,j);
+ }
+ os << "}";
+ }
+ os << "}";
+ return os;
+}
+
+template <size_t N, typename CoeffT, typename T>
+void polynomial_matrix_evaluate (Matrix<T> & A,
+ Matrix< MultiPoly<N, CoeffT> > const& M,
+ std::array<T, N> const& X)
+{
+ A.resize(M.rows(), M.columns());
+ for (size_t i = 0; i < M.rows(); ++i)
+ {
+ for (size_t j = 0; j < M.columns(); ++j)
+ {
+ A(i,j) = M(i,j)(X);
+ }
+ }
+}
+
+
+inline
+void polynomial_matrix_evaluate (NL::Matrix & A,
+ Matrix< MultiPoly<2, double> > const& M,
+ Point const& P)
+{
+ for (size_t i = 0; i < M.rows(); ++i)
+ {
+ for (size_t j = 0; j < M.columns(); ++j)
+ {
+ A(i,j) = M(i,j)(P[X], P[Y]);
+ }
+ }
+}
+
+
+/*
+template< typename Coeff>
+class SymmetricSquareMatrix
+{
+ public:
+ typedef Coeff coeff_type;
+ typedef std::vector<coeff_type> container_type;
+
+ SymmetricSquareMatrix(size_t n)
+ : m_data((n*n)/2 + n), m_size(n)
+ {
+
+ }
+
+ size_t rows() const
+ {
+ return m_size;
+ }
+
+ size_t columns() const
+ {
+ return m_size;
+ }
+
+ coeff_type const& operator() (size_t i, size_t j) const
+ {
+ return m_data[i * columns() + j];
+ }
+
+ coeff_type & operator() (size_t i, size_t j)
+ {
+ return m_data[i * columns() + j];
+ }
+
+ coeff_type det()
+ {
+
+ }
+
+ private:
+ container_type m_data;
+ size_t m_size;
+};
+*/
+
+/*
+ * This is an adaptation of the LU algorithm used in the numerical case.
+ * This algorithm is based on the article due to Bareiss:
+ * "Sylvester's identity and multistep integer-preserving Gaussian elimination"
+ */
+
+/*
+template< typename CoeffT >
+CoeffT det(Matrix<CoeffT> const& M)
+{
+ assert(M.rows() == M.columns());
+
+ Matrix<CoeffT> A(M);
+ CoeffT n;
+ CoeffT d = one<CoeffT>()();
+ for (size_t k = 1; k < A.rows(); ++k)
+ {
+ for (size_t i = k; i < A.rows(); ++i)
+ {
+ for (size_t j = k; j < A.columns(); ++j)
+ {
+ n = A(i,j) * A(k-1,k-1) - A(k-1,j) * A(i,k-1);
+// std::cout << "k, i, j: "
+// << k << ", " << i << ", " << j << std::endl;
+// std::cout << "n = " << n << std::endl;
+// std::cout << "d = " << d << std::endl;
+ A(i,j) = factor(n, d);
+ }
+ }
+ d = A(k-1,k-1);
+ }
+ return A(A.rows()-1, A.columns()-1);
+}
+*/
+
+
+
+} /*end namespace Geom*/ } /*end namespace SL*/
+
+
+#include <2geom/symbolic/determinant-minor.h>
+
+
+#endif // _GEOM_SL_MATRIX_H_
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/symbolic/multi-index.h b/src/3rdparty/2geom/include/2geom/symbolic/multi-index.h
new file mode 100644
index 0000000..311fae8
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/symbolic/multi-index.h
@@ -0,0 +1,169 @@
+/*
+ * A multi-index is an ordered sequence of unsigned int
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef _GEOM_SL_MULTI_INDEX_H_
+#define _GEOM_SL_MULTI_INDEX_H_
+
+
+#include <2geom/exception.h>
+
+#include <valarray>
+
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+#include <boost/preprocessor/repetition/repeat_from_to.hpp>
+
+
+
+
+/*
+ * an helper macro for generating function with declaration:
+ * multi_index_type make_multi_index (size_t i0, ..., size_t iN)
+ * that is a facility to make up a multi-index from a list of values
+ */
+
+#define GEOM_SL_MAX_RANK 10
+
+#define GEOM_SL_ASSIGN_INDEX(z, k, unused) I[k] = BOOST_PP_CAT(i, k);
+
+#define GEOM_SL_MAKE_MULTI_INDEX(z, N, unused) \
+inline \
+multi_index_type make_multi_index (BOOST_PP_ENUM_PARAMS(N, size_t i)) \
+{ \
+ multi_index_type I(N); \
+ BOOST_PP_REPEAT(N, GEOM_SL_ASSIGN_INDEX, unused) \
+ return I; \
+}
+// end macro GEOM_SL_MAKE_MULTI_INDEX
+
+
+
+
+namespace Geom { namespace SL {
+
+/*
+ * A multi-index is an ordered sequence of unsigned int;
+ * it's useful for representing exponent, degree and coefficient index
+ * of a multi-variate polynomial;
+ * example: given a monomial x_(0)^i_(0)*x_(1)^i_(1)*...*x_(N-1)^i_(N-1)
+ * we can write it in the simpler form X^I where X=(x_(0), .., x_(N-1))
+ * and I=(i_(0), .., i_(N-1)) is a multi-index
+ * A multi-index is represented as a valarray this let us make simple
+ * arithmetic operations on a multi-index
+ */
+
+typedef std::valarray<size_t> multi_index_type;
+
+
+// make up a multi-index of size N and fill it with zeroes
+inline
+multi_index_type multi_index_zero(size_t N)
+{
+ return multi_index_type(N);
+}
+
+// helper functions for generating a multi-index from a list of values
+// we create an amount of GEOM_SL_MAX_RANK of suzh functions
+BOOST_PP_REPEAT_FROM_TO(0, GEOM_SL_MAX_RANK, GEOM_SL_MAKE_MULTI_INDEX, unused)
+
+
+// helper function for generating a multi-index of size N
+// from a single index v that is placed at position i with i in [0,N[
+template <size_t N>
+inline
+multi_index_type make_multi_index(size_t i, size_t v)
+{
+ if (!(i < N))
+ THROW_RANGEERROR ("make_multi_index<N> from a single index: "
+ "out of range position");
+ multi_index_type I(N);
+ I[i] = v;
+ return I;
+}
+
+// transform a N size multi-index in (N-1)-size multi-index
+// by removing the first index: (i1, i2,...,iN) -> (i2,..,iN)
+inline
+multi_index_type shift(multi_index_type const& I, size_t i = 1)
+{
+ size_t N = I.size() - i;
+ multi_index_type J = I[std::slice(i, N, 1)];
+ return J;
+}
+
+// valarray operator== returns a valarray of bool
+inline
+bool is_equal(multi_index_type const& I, multi_index_type const& J)
+{
+ if (I.size() != J.size()) return false;
+ for (size_t i = 0; i < I.size(); ++i)
+ if (I[i] != J[i]) return false;
+ return true;
+}
+
+// extended operator<< for printing a multi-index
+template <typename charT>
+inline
+std::basic_ostream<charT> &
+operator<< (std::basic_ostream<charT> & os,
+ const Geom::SL::multi_index_type & I)
+{
+ if (I.size() == 0 ) return os;
+ os << "[" << I[0];
+ for (unsigned int i = 1; i < I.size(); ++i)
+ {
+ os << ", " << I[i];
+ }
+ os << "]";
+ return os;
+}
+
+} /*end namespace Geom*/ } /*end namespace SL*/
+
+// argument dependent name lookup doesn't work with typedef
+using Geom::SL::operator<<;
+
+
+#endif // _GEOM_SL_MULTI_INDEX_
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/symbolic/multipoly.h b/src/3rdparty/2geom/include/2geom/symbolic/multipoly.h
new file mode 100644
index 0000000..ab3a5f4
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/symbolic/multipoly.h
@@ -0,0 +1,684 @@
+/*
+ * MultiPoly<N, CoeffT> class template
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef _GEOM_SL_MULTIPOLY_H_
+#define _GEOM_SL_MULTIPOLY_H_
+
+#include <utility>
+
+#include <array>
+#include <functional>
+#include <type_traits>
+
+#include <2geom/symbolic/unity-builder.h>
+#include <2geom/symbolic/mvpoly-tools.h>
+
+
+namespace Geom { namespace SL {
+
+/*
+ * MultiPoly<N, CoeffT> class template
+ *
+ * It represents a multi-variate polynomial with N indeterminates
+ * and coefficients of type CoeffT, but it doesn't support explicit
+ * symbol attaching; the indeterminates should be thought as implicitly
+ * defined in an automatic enumerative style: x_(0),...,x_(N-1) .
+ *
+ */
+
+template <size_t N, typename CoeffT>
+class MultiPoly
+{
+public:
+ typedef typename mvpoly<N, CoeffT>::type poly_type;
+ typedef CoeffT coeff_type;
+ static const size_t rank = N;
+
+public:
+ MultiPoly()
+ {
+ }
+
+ MultiPoly(poly_type p)
+ : m_poly(std::move(p))
+ {
+ }
+
+ // create a mv polynomial of type c*X^I
+ MultiPoly(coeff_type c, multi_index_type const& I = multi_index_zero(N))
+ : m_poly(monomial<N, coeff_type>::make(I, c))
+ {
+ }
+
+ // create a mv polynomial p(x_(N-M),...,x_(N-1))*X'^I
+ // where I.size() == N-M and X'=(x_(0),...,x_(N-M-1))
+ template <size_t M>
+ MultiPoly (MultiPoly<M, CoeffT> const& p,
+ multi_index_type const& I = multi_index_zero(N-M),
+ typename std::enable_if_t<(M > 0) && (M < N)>* = 0)
+ {
+ Geom::SL::coefficient<N-M-1, poly_type>::set_safe(m_poly, I, p.m_poly);
+ }
+
+ /*
+ * assignment operators
+ */
+ MultiPoly& operator=(poly_type const& p)
+ {
+ m_poly = p;
+ return (*this);
+ }
+
+ MultiPoly& operator=(coeff_type const& c)
+ {
+ multi_index_type I = multi_index_zero(N);
+ (*this) = MultiPoly(c);
+ return (*this);
+ }
+
+ // return the degree of the mv polynomial wrt the ordering OrderT
+ template <typename OrderT>
+ multi_index_type degree() const
+ {
+ return Geom::SL::mvdegree<N, CoeffT, OrderT>::value(m_poly);
+ }
+
+ // return the coefficient of the term with the highest degree
+ // wrt the ordering OrderT
+ template <typename OrderT>
+ coeff_type const& leading_coefficient() const
+ {
+ return (*this)(degree<OrderT>());
+ }
+
+ template <typename OrderT>
+ coeff_type & leading_coefficient()
+ {
+ return (*this)(degree<OrderT>());
+ }
+
+ // return the coefficient of the term of degree 0 (wrt all indeterminates)
+ coeff_type const& trailing_coefficient() const
+ {
+ return (*this)(multi_index_zero(N));
+ }
+
+ coeff_type & trailing_coefficient()
+ {
+ return (*this)(multi_index_zero(N));
+ }
+
+ // access coefficient methods with no out-of-range checking
+ coeff_type const& operator() (multi_index_type const& I) const
+ {
+ return Geom::SL::coefficient<N-1, poly_type>::get(m_poly, I);
+ }
+
+ coeff_type & operator() (multi_index_type const& I)
+ {
+ return Geom::SL::coefficient<N-1, poly_type>::get(m_poly, I);
+ }
+
+ // safe coefficient get method
+ coeff_type const& coefficient(multi_index_type const& I) const
+ {
+ return Geom::SL::coefficient<N-1, poly_type>::get_safe(m_poly, I);
+ }
+
+ // safe coefficient set method
+ void coefficient(multi_index_type const& I, coeff_type const& c)
+ {
+ Geom::SL::coefficient<N-1, poly_type>::set_safe(m_poly, I, c);
+ }
+
+ // access the mv poly of rank N-1 with no out-of-range checking
+ typename poly_type::coeff_type const&
+ operator[] (size_t const& i) const
+ {
+ return m_poly[i];
+ }
+
+ typename poly_type::coeff_type &
+ operator[] (size_t const& i)
+ {
+ return m_poly[i];
+ }
+
+ // safe access to the mv poly of rank N-1
+ typename poly_type::coeff_type const&
+ coefficient(size_t const& i) const
+ {
+ return m_poly.coefficient(i);
+ }
+
+ void coefficient (size_t const& i,
+ typename poly_type::coeff_type const& c)
+ {
+ m_poly.coefficient(i, c);
+ }
+
+ /*
+ * polynomail evaluation:
+ * T can be any type that is able to be + and * with the coefficient type
+ */
+ template <typename T>
+ T operator() (std::array<T, N> const& X) const
+ {
+ return Geom::SL::mvpoly<N, CoeffT>::evaluate(m_poly, X);
+ }
+
+ template <typename T>
+ typename std::enable_if_t<(N == 1), T>
+ operator() (T const& x0) const
+ {
+ std::array<T, N> X = {{x0}};
+ return Geom::SL::mvpoly<N, CoeffT>::evaluate(m_poly, X);
+ }
+
+ template <typename T>
+ typename std::enable_if_t<(N == 2), T>
+ operator() (T const& x0, T const& x1) const
+ {
+ std::array<T, N> X = {{x0, x1}};
+ return Geom::SL::mvpoly<N, CoeffT>::evaluate(m_poly, X);
+ }
+
+ template <typename T>
+ typename std::enable_if_t<(N == 3), T>
+ operator() (T const& x0, T const& x1, T const& x2) const
+ {
+ std::array<T, N> X = {{x0, x1, x2}};
+ return Geom::SL::mvpoly<N, CoeffT>::evaluate(m_poly, X);
+ }
+
+ /*
+ * trim leading zero coefficients
+ */
+ void normalize()
+ {
+ Geom::SL::mvpoly<N, CoeffT>::normalize(m_poly);
+ }
+
+ /*
+ * select the sub multi-variate polynomial with rank M
+ * which is unambiguously characterized by the multi-index I
+ * requirements:
+ * - M > 0 && M < N;
+ * - multi-index size == N-M
+ */
+ template <size_t M>
+ typename mvpoly<M, CoeffT>::type const&
+ select (multi_index_type const& I= multi_index_zero(N-M),
+ typename std::enable_if_t<(M > 0) && (M < N)>* = 0) const
+ {
+ return Geom::SL::coefficient<N-M-1, poly_type>::get_safe(m_poly, I);
+ }
+
+ poly_type const& get_poly() const
+ {
+ return m_poly;
+ }
+
+ bool is_zero() const
+ {
+ return ((*this) == zero);
+ }
+
+ // return the opposite mv poly
+ MultiPoly operator-() const
+ {
+ MultiPoly r(-m_poly);
+ return r;
+ }
+
+ /*
+ * multipoly-multipoly mutating operators
+ */
+ MultiPoly& operator+=(MultiPoly const& p)
+ {
+ m_poly += p.m_poly;
+ return (*this);
+ }
+
+ MultiPoly& operator-=(MultiPoly const& p)
+ {
+ m_poly -= p.m_poly;
+ return (*this);
+ }
+
+ MultiPoly& operator*=(MultiPoly const& p)
+ {
+ m_poly *= p.m_poly;
+ return (*this);
+ }
+
+ MultiPoly& operator<<=(multi_index_type const& I)
+ {
+ Geom::SL::mvpoly<N, CoeffT>::shift(m_poly, I);
+ return (*this);
+ }
+
+ bool operator==(MultiPoly const& q) const
+ {
+ return (m_poly == q.m_poly);
+ }
+
+ bool operator!=(MultiPoly const& q) const
+ {
+ return !((*this) == q);
+ }
+
+ /*
+ * multipoly-coefficient mutating operators
+ */
+ MultiPoly& operator+=(CoeffT const& c)
+ {
+ trailing_coefficient() += c;
+ return (*this);
+ }
+
+ MultiPoly& operator-=(CoeffT const& c)
+ {
+ trailing_coefficient() -= c;
+ return (*this);
+ }
+
+ MultiPoly& operator*=(CoeffT const& c)
+ {
+ mvpoly<N, CoeffT>::template
+ for_each<0>(m_poly, std::bind(mvpoly<0, CoeffT>::multiply_to, std::placeholders::_1, c));
+ return (*this);
+ }
+
+ MultiPoly& operator/=(CoeffT const& c)
+ {
+ mvpoly<N, CoeffT>::template
+ for_each<0>(m_poly, std::bind(mvpoly<0, CoeffT>::divide_to, std::placeholders::_1, c));
+ return (*this);
+ }
+
+ /*
+ * multipoly-polynomial mutating operators
+ */
+ MultiPoly& operator+=(poly_type const& p)
+ {
+ m_poly += p;
+ return (*this);
+ }
+
+ MultiPoly& operator-=(poly_type const& p)
+ {
+ m_poly -= p;
+ return (*this);
+ }
+
+ MultiPoly& operator*=(poly_type const& p)
+ {
+ m_poly *= p;
+ return (*this);
+ }
+
+ /*
+ * multipoly<N>-multipoly<M> mutating operators
+ * requirements:
+ * - M > 0 && M < N;
+ * - they must have the same coefficient type.
+ */
+
+ template <size_t M>
+ typename std::enable_if_t<(M > 0) && (M < N), MultiPoly> &
+ operator+= (MultiPoly<M, CoeffT> const& p)
+ {
+ multi_index_type I = multi_index_zero(N-M);
+ Geom::SL::coefficient<N-M-1, poly_type>::get(m_poly, I) += p.m_poly;
+ return (*this);
+ }
+
+ template <size_t M>
+ typename std::enable_if_t<(M > 0) && (M < N), MultiPoly> &
+ operator-= (MultiPoly<M, CoeffT> const& p)
+ {
+ multi_index_type I = multi_index_zero(N-M);
+ Geom::SL::coefficient<N-M-1, poly_type>::get(m_poly, I) -= p.m_poly;
+ return (*this);
+ }
+
+ template <size_t M>
+ typename std::enable_if_t<(M > 0) && (M < N), MultiPoly> &
+ operator*= (MultiPoly<M, CoeffT> const& p)
+ {
+ mvpoly<N, CoeffT>::template
+ for_each<M>(m_poly, std::bind(mvpoly<M, CoeffT>::multiply_to, std::placeholders::_1, p.m_poly));
+ return (*this);
+ }
+
+ /*
+ * we need MultiPoly instantiations to be each other friend
+ * in order to be able of implementing operations between
+ * MultiPoly instantiations with a different ranks
+ */
+ template<size_t M, typename C>
+ friend class MultiPoly;
+
+ template< typename charT, size_t M, typename C>
+ friend
+ std::basic_ostream<charT> &
+ operator<< (std::basic_ostream<charT> & os, const MultiPoly<M, C> & p);
+
+ static const MultiPoly zero;
+ static const MultiPoly one;
+ static const coeff_type zero_coeff;
+ static const coeff_type one_coeff;
+
+private:
+ poly_type m_poly;
+
+}; // end class MultiPoly
+
+
+/*
+ * zero and one element spezcialization for MultiPoly
+ */
+template <size_t N, typename CoeffT>
+struct zero<MultiPoly<N, CoeffT>, false>
+{
+ MultiPoly<N, CoeffT> operator() ()
+ {
+ CoeffT _0c = zero<CoeffT>()();
+ MultiPoly<N, CoeffT> _0(_0c);
+ return _0;
+ }
+};
+
+
+template <size_t N, typename CoeffT>
+struct one<MultiPoly<N, CoeffT>, false>
+{
+ MultiPoly<N, CoeffT> operator() ()
+ {
+ CoeffT _1c = one<CoeffT>()();
+ MultiPoly<N, CoeffT> _1(_1c);
+ return _1;
+ }
+};
+
+
+/*
+ * initialization of MultiPoly static data members
+ */
+template <size_t N, typename CoeffT>
+const MultiPoly<N, CoeffT> MultiPoly<N, CoeffT>::one
+ = Geom::SL::one< MultiPoly<N, CoeffT> >()();
+
+template <size_t N, typename CoeffT>
+const MultiPoly<N, CoeffT> MultiPoly<N, CoeffT>::zero
+ = Geom::SL::zero< MultiPoly<N, CoeffT> >()();
+
+template <size_t N, typename CoeffT>
+const typename MultiPoly<N, CoeffT>::coeff_type MultiPoly<N, CoeffT>::zero_coeff
+ = Geom::SL::zero<typename MultiPoly<N, CoeffT>::coeff_type>()();
+
+template <size_t N, typename CoeffT>
+const typename MultiPoly<N, CoeffT>::coeff_type MultiPoly<N, CoeffT>::one_coeff
+ = Geom::SL::one<typename MultiPoly<N, CoeffT>::coeff_type>()();
+
+
+/*
+ * operator<< extended to print out a mv poly type
+ */
+template <typename charT, size_t N, typename CoeffT>
+inline
+std::basic_ostream<charT> &
+operator<< (std::basic_ostream<charT> & os, const MultiPoly<N, CoeffT> & p)
+{
+ return operator<<(os, p.m_poly);
+}
+
+/*
+ * equivalent to multiply by X^I
+ */
+template <size_t N, typename CoeffT>
+inline
+MultiPoly<N, CoeffT>
+operator<< (MultiPoly<N, CoeffT> const& p, multi_index_type const& I)
+{
+ MultiPoly<N, CoeffT> r(p);
+ r <<= I;
+ return r;
+}
+
+/*
+ * MultiPoly<M, CoeffT> - MultiPoly<N, CoeffT> binary mathematical operators
+ */
+
+template <size_t M, size_t N, typename CoeffT>
+inline
+typename std::enable_if_t<(M > 0) && (M <= N), MultiPoly<N, CoeffT> >
+operator+ (MultiPoly<N, CoeffT> const& p,
+ MultiPoly<M, CoeffT> const& q )
+{
+ MultiPoly<N, CoeffT> r(p);
+ r += q;
+ return r;
+}
+
+template <size_t M, size_t N, typename CoeffT>
+inline
+typename std::enable_if_t<(N > 0) && (M > N), MultiPoly<M, CoeffT> >
+operator+ (MultiPoly<N, CoeffT> const& p,
+ MultiPoly<M, CoeffT> const& q )
+{
+ MultiPoly<M, CoeffT> r(q);
+ r += p;
+ return r;
+}
+
+template <size_t M, size_t N, typename CoeffT>
+inline
+typename std::enable_if_t<(M > 0) && (M <= N), MultiPoly<N, CoeffT> >
+operator- (MultiPoly<N, CoeffT> const& p,
+ MultiPoly<M, CoeffT> const& q )
+{
+ MultiPoly<N, CoeffT> r(p);
+ r -= q;
+ return r;
+}
+
+template <size_t M, size_t N, typename CoeffT>
+inline
+typename std::enable_if_t<(N > 0) && (M > N), MultiPoly<M, CoeffT> >
+operator- (MultiPoly<N, CoeffT> const& p,
+ MultiPoly<M, CoeffT> const& q )
+{
+ MultiPoly<M, CoeffT> r(-q);
+ r += p;
+ return r;
+}
+
+
+template <size_t M, size_t N, typename CoeffT>
+inline
+typename std::enable_if_t<(M > 0) && (M <= N), MultiPoly<N, CoeffT> >
+operator* (MultiPoly<N, CoeffT> const& p,
+ MultiPoly<M, CoeffT> const& q )
+{
+ MultiPoly<N, CoeffT> r(p);
+ r *= q;
+ return r;
+}
+
+template <size_t M, size_t N, typename CoeffT>
+inline
+typename std::enable_if_t<(N > 0) && (M > N), MultiPoly<M, CoeffT> >
+operator* (MultiPoly<N, CoeffT> const& p,
+ MultiPoly<M, CoeffT> const& q )
+{
+ MultiPoly<M, CoeffT> r(q);
+ r *= p;
+ return r;
+}
+
+/*
+ * MultiPoly-coefficient and coefficient-MultiPoly binary mathematical operators
+ */
+
+template <size_t N, typename CoeffT>
+inline
+MultiPoly<N, CoeffT> operator+(MultiPoly<N, CoeffT> const& p, CoeffT const& c)
+{
+ MultiPoly<N, CoeffT> r(p);
+ r += c;
+ return r;
+}
+
+template <size_t N, typename CoeffT>
+inline
+MultiPoly<N, CoeffT> operator+(CoeffT const& c, MultiPoly<N, CoeffT> const& p)
+{
+ MultiPoly<N, CoeffT> r(p);
+ r += c;
+ return r;
+}
+
+template <size_t N, typename CoeffT>
+inline
+MultiPoly<N, CoeffT> operator-(MultiPoly<N, CoeffT> const& p, CoeffT const& c)
+{
+ MultiPoly<N, CoeffT> r(p);
+ r -= c;
+ return r;
+}
+
+template <size_t N, typename CoeffT>
+inline
+MultiPoly<N, CoeffT> operator-(CoeffT const& c, MultiPoly<N, CoeffT> const& p)
+{
+ MultiPoly<N, CoeffT> r(-p);
+ r += c;
+ return r;
+}
+
+template <size_t N, typename CoeffT>
+inline
+MultiPoly<N, CoeffT> operator*(MultiPoly<N, CoeffT> const& p, CoeffT const& c)
+{
+ MultiPoly<N, CoeffT> r(p);
+ r *= c;
+ return r;
+}
+
+template <size_t N, typename CoeffT>
+inline
+MultiPoly<N, CoeffT> operator*(CoeffT const& c, MultiPoly<N, CoeffT> const& p)
+{
+ MultiPoly<N, CoeffT> r(p);
+ r *= c;
+ return r;
+}
+
+
+template <size_t N, typename CoeffT>
+inline
+MultiPoly<N, CoeffT> operator/(MultiPoly<N, CoeffT> const& p, CoeffT const& c)
+{
+ MultiPoly<N, CoeffT> r(p);
+ r /= c;
+ return r;
+}
+
+
+
+
+/*
+template< size_t N, typename CoeffT >
+MultiPoly<N, CoeffT>
+factor( MultiPoly<N, CoeffT> const& f,
+ MultiPoly<N, CoeffT> const& g )
+{
+ typedef MultiPoly<N, CoeffT> poly_type;
+
+ if (g == poly_type::one) return f;
+ poly_type h(g), q, r(f);
+ multi_index_type deg_r = r.template degree<ordering::lex>();
+ multi_index_type deg_g = g.template degree<ordering::lex>();
+ multi_index_type deg0 = multi_index_zero(deg_g.size());
+ CoeffT ltg = g(deg_g);
+ if (is_equal(deg_g, deg0)) return (f / ltg);
+ //h(deg_g) = 0;
+// std::cout << "deg_g = " << deg_g << std::endl;
+// std::cout << "ltg = " << ltg << std::endl;
+ CoeffT lt, ltr;
+ multi_index_type deg(1, deg_g.size());
+ size_t iter = 0;
+ while (!is_equal(deg, deg0) && iter < 10000)
+ {
+ ++iter;
+ deg = deg_r - deg_g;
+ ltr = r(deg_r);
+ lt = ltr / ltg;
+ q.coefficient(deg, lt);
+ //r(deg_r) = 0;
+ r -= ((lt * g) << deg);
+ deg_r = r.template degree<ordering::lex>();
+// std::cout << "deg_r = " << deg_r << std::endl;
+// std::cout << "ltr = " << ltr << std::endl;
+// std::cout << "deg = " << deg << std::endl;
+// std::cout << "lt = " << lt << std::endl;
+// std::cout << "q = " << q << std::endl;
+// std::cout << "r = " << r << std::endl;
+
+// break;
+ }
+ //std::cout << "iter = " << iter << std::endl;
+ return q;
+}
+*/
+
+
+} /*end namespace Geom*/ } /*end namespace SL*/
+
+
+
+
+#endif /* _MULTIPOLY_H_ */
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/symbolic/mvpoly-tools.h b/src/3rdparty/2geom/include/2geom/symbolic/mvpoly-tools.h
new file mode 100644
index 0000000..34dece7
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/symbolic/mvpoly-tools.h
@@ -0,0 +1,690 @@
+/*
+ * Routines that extend univariate polynomial functions
+ * to multi-variate polynomial exploiting recursion at compile time
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef _GEOM_SL_MVPOLY_TOOLS_H_
+#define _GEOM_SL_MVPOLY_TOOLS_H_
+
+
+#include <2geom/exception.h>
+
+#include <2geom/symbolic/multi-index.h>
+#include <2geom/symbolic/unity-builder.h>
+#include <2geom/symbolic/polynomial.h>
+
+#include <array>
+#include <functional>
+#include <iostream>
+#include <type_traits>
+
+
+namespace Geom { namespace SL {
+
+/*
+ * rank<PolyT>::value == total amount of indeterminates
+ * x_(0),x_(1),...,x_(rank-1) that belong to type PolyT
+ */
+
+template <typename T>
+struct rank
+{
+ static const size_t value = 0;
+};
+
+template <typename CoeffT>
+struct rank< Polynomial<CoeffT> >
+{
+ static const size_t value = rank<CoeffT>::value + 1;
+};
+
+
+/*
+ * mvpoly<N, CoeffT> creates a multi-variate polynomial type
+ * by nesting N-1 Polynomial class template and setting
+ * the coefficient type of the most nested Polynomial to CoeffT
+ * example: mvpoly<3, double>::type is the same than
+ * Polynomial< Polynomial< Polynomial<double> > >
+ */
+
+template <size_t N, typename CoeffT>
+struct mvpoly
+{
+ typedef Polynomial<typename mvpoly<N-1, CoeffT>::type> type;
+ typedef CoeffT coeff_type;
+ static const size_t rank = N;
+
+ /*
+ * computes the lexicographic degree of the mv polynomial p
+ */
+ static
+ multi_index_type lex_degree (type const& p)
+ {
+ multi_index_type D(N);
+ lex_degree_impl<0>(p, D);
+ return D;
+ }
+
+ /*
+ * Returns in the out-parameter D an N-sequence where each entry value
+ * represents the max degree of the polynomial related to the passed
+ * index I, if one index value in I is greater than the related max degree
+ * the routine returns false otherwise it returns true.
+ * This routine can be used to test if a given multi-index I is related
+ * to an actual initialized coefficient.
+ */
+ static
+ bool max_degree (type const& p,
+ multi_index_type& D,
+ multi_index_type const& I)
+ {
+ if (I.size() != N)
+ THROW_RANGEERROR ("multi-index with wrong length");
+ D.resize(N);
+ return max_degree_impl<0>(p, D, I);
+ }
+
+ /*
+ * Returns in the out-parameter D an N-sequence where each entry value
+ * represents the real degree of the polynomial related to the passed
+ * index I, if one index value in I is greater than the related real degree
+ * the routine returns false otherwise it returns true.
+ * This routine can be used to test if a given multi-index I is related
+ * to an actual initialized and non-zero coefficient.
+ */
+
+ static
+ bool real_degree (type const& p,
+ multi_index_type& D,
+ multi_index_type const& I)
+ {
+ if (I.size() != N)
+ THROW_RANGEERROR ("multi-index with wrong length");
+ D.resize(N);
+ return real_degree_impl<0>(p, D, I);
+ }
+
+ /*
+ * Multiplies p by X^I
+ */
+ static
+ void shift(type & p, multi_index_type const& I)
+ {
+ if (I.size() != N)
+ THROW_RANGEERROR ("multi-index with wrong length");
+ shift_impl<0>(p, I);
+ }
+
+ /*
+ * mv poly evaluation:
+ * T can be any type that is able to be += with the coefficient type
+ * and that can be *= with the same type T moreover a specialization
+ * of zero struct for the type T is needed
+ */
+ template <typename T>
+ static
+ T evaluate(type const& p, std::array<T, N> const& X)
+ {
+ return evaluate_impl<T, 0>(p, X);
+ }
+
+ /*
+ * trim leading zero coefficients
+ */
+ static
+ void normalize(type & p)
+ {
+ p.normalize();
+ for (size_t k = 0; k < p.size(); ++k)
+ mvpoly<N-1, CoeffT>::normalize(p[k]);
+ }
+
+ /*
+ * Applies the unary operator "op" to each coefficient of p with rank M.
+ * For instance when M = 0 op is applied to each coefficient
+ * of the multi-variate polynomial p.
+ * When M < N the function call recursively the for_each routine
+ * for p.real_degree() times, when M == N the operator "op" is invoked on p;
+ */
+ template <size_t M>
+ static
+ void for_each
+ (type & p,
+ std::function<void (typename mvpoly<M, CoeffT>::type &)> const& op,
+ typename std::enable_if_t<(M < N)>* = 0)
+ {
+ for (size_t k = 0; k <= p.real_degree(); ++k)
+ {
+ mvpoly<N-1, CoeffT>::template for_each<M>(p[k], op);
+ }
+ }
+
+ template <size_t M>
+ static
+ void for_each
+ (type & p,
+ std::function<void (typename mvpoly<M, CoeffT>::type &)> const& op,
+ typename std::enable_if_t<(M == N)>* = 0)
+ {
+ op(p);
+ }
+
+ // this is only an helper function to be passed to the for_each routine
+ static
+ void multiply_to (type& p, type const& q)
+ {
+ p *= q;
+ }
+
+ private:
+ template <size_t i>
+ static
+ void lex_degree_impl (type const& p, multi_index_type& D)
+ {
+ D[i] = p.real_degree();
+ mvpoly<N-1, CoeffT>::template lex_degree_impl<i+1>(p[D[i]], D);
+ }
+
+ template <size_t i>
+ static
+ bool max_degree_impl (type const& p,
+ multi_index_type& D,
+ multi_index_type const& I)
+ {
+ D[i] = p.max_degree();
+ if (I[i] > D[i]) return false;
+ return
+ mvpoly<N-1, CoeffT>::template max_degree_impl<i+1>(p[I[i]], D, I);
+ }
+
+ template <size_t i>
+ static
+ bool real_degree_impl (type const& p,
+ multi_index_type& D,
+ multi_index_type const& I)
+ {
+ D[i] = p.real_degree();
+ if (I[i] > D[i]) return false;
+ return
+ mvpoly<N-1, CoeffT>::template real_degree_impl<i+1>(p[I[i]], D, I);
+ }
+
+ template <size_t i>
+ static
+ void shift_impl(type & p, multi_index_type const& I)
+ {
+ p <<= I[i];
+ for (size_t k = 0; k < p.size(); ++k)
+ {
+ mvpoly<N-1, CoeffT>::template shift_impl<i+1>(p[k], I);
+ }
+ }
+
+ template <typename T, size_t i>
+ static
+ T evaluate_impl(type const& p, std::array<T, N+i> const& X)
+ {
+// T r = zero<T>()();
+// for (size_t k = p.max_degree(); k > 0; --k)
+// {
+// r += mvpoly<N-1, CoeffT>::template evaluate_impl<T, i+1>(p[k], X);
+// r *= X[i];
+// }
+// r += mvpoly<N-1, CoeffT>::template evaluate_impl<T, i+1>(p[0], X);
+
+ int n = p.max_degree();
+ T r = mvpoly<N-1, CoeffT>::template evaluate_impl<T, i+1>(p[n], X);
+ for (int k = n - 1; k >= 0; --k)
+ {
+ r *= X[i];
+ r += mvpoly<N-1, CoeffT>::template evaluate_impl<T, i+1>(p[k], X);
+ }
+ return r;
+ }
+
+ template <size_t M, typename C>
+ friend struct mvpoly;
+};
+
+/*
+ * rank 0 mv poly, that is a scalar value (usually a numeric value),
+ * the routines implemented here are used only to stop recursion
+ * (but for_each)
+ */
+template< typename CoeffT >
+struct mvpoly<0, CoeffT>
+{
+ typedef CoeffT type;
+ typedef CoeffT coeff_type;
+ static const size_t rank = 0;
+
+ template <size_t M>
+ static
+ void for_each
+ (type & p,
+ std::function<void (typename mvpoly<M, CoeffT>::type &)> const& op,
+ typename std::enable_if_t<(M == 0)>* = 0)
+ {
+ op(p);
+ }
+
+ // multiply_to and divide_to are only helper functions
+ // to be passed to the for_each routine
+ static
+ void multiply_to (type& p, type const& q)
+ {
+ p *= q;
+ }
+
+ static
+ void divide_to (type& p, type const& c)
+ {
+ p /= c;
+ }
+
+ private:
+ template <size_t i>
+ static
+ void lex_degree_impl (type const &/*p*/, multi_index_type&/*D*/)
+ {
+ return;
+ }
+
+ template <size_t i>
+ static
+ bool max_degree_impl (type const &/*p*/,
+ multi_index_type &/*D*/,
+ multi_index_type const &/*I*/)
+ {
+ return true;
+ }
+
+ template <size_t i>
+ static
+ bool real_degree_impl (type const &/*p*/,
+ multi_index_type &/*D*/,
+ multi_index_type const &/*I*/)
+ {
+ return true;
+ }
+
+ template <size_t i>
+ static
+ void shift_impl(type &/*p*/, multi_index_type const &/*I*/)
+ {}
+
+ template <typename T, size_t i>
+ static
+ T evaluate_impl(type const &p, std::array<T, i> const &/*X*/)
+ {
+ return p;
+ }
+
+ static
+ void normalize(type &/*p*/)
+ {}
+
+
+ template <size_t M, typename C>
+ friend struct mvpoly;
+};
+
+
+/*
+ * monomial::make generate a mv-poly made up by a single term:
+ * monomial::make<N>(I,c) == c*X^I, where X=(x_(0), .., x_(N-1))
+ */
+
+template <size_t N, typename CoeffT>
+struct monomial
+{
+ typedef typename mvpoly<N, CoeffT>::type poly_type;
+
+ static inline
+ poly_type make(multi_index_type const& I, CoeffT c)
+ {
+ if (I.size() != N) // an exponent for each indeterminate
+ THROW_RANGEERROR ("multi-index with wrong length");
+
+ return make_impl<0>(I, c);
+ }
+
+ private:
+ // at i-th level of recursion I need to pick up the i-th exponent in "I"
+ // so I pass i as a template parameter, this trick is needed to avoid
+ // to create a new multi-index at each recursion level:
+ // (J = I[std::slice[1, I.size()-1, 1)]) that will be more expensive
+ template <size_t i>
+ static
+ poly_type make_impl(multi_index_type const& I, CoeffT c)
+ {
+ poly_type p(monomial<N-1,CoeffT>::template make_impl<i+1>(I, c), I[i]);
+ return p;
+ }
+
+ // make_impl private require that monomial classes to be each other friend
+ template <size_t M, typename C>
+ friend struct monomial;
+};
+
+
+// case N = 0 for stopping recursion
+template <typename CoeffT>
+struct monomial<0, CoeffT>
+{
+ private:
+ template <size_t i>
+ static
+ CoeffT make_impl(multi_index_type const &/*I*/, CoeffT c)
+ {
+ return c;
+ }
+
+ template<size_t N, typename C>
+ friend struct monomial;
+};
+
+
+/*
+ * coefficient<N, PolyT>
+ *
+ * N should be in the range [0, rank<PolyT>-1]
+ *
+ * "type" == the type of the coefficient of the polynomial with
+ * rank = rank<PolyT> - N - 1, that is it is the type of the object returned
+ * by applying the operator[] of a Polynomial object N+1 times;
+ *
+ * "zero" represents the zero element (in the group theory meaning)
+ * for the coefficient type "type"; having it as a static class member
+ * allows to return always a (const) reference by the "get_safe" method
+ *
+ * get(p, I) returns the coefficient of the monomial X^I
+ * this method doesn't check if such a coefficient really exists,
+ * so it's up to the user checking that the passed multi-index I is
+ * not out of range
+ *
+ * get_safe(p, I) returns the coefficient of the monomial X^I
+ * in case such a coefficient doesn't really exist "zero" is returned
+ *
+ * set_safe(p, I, c) set the coefficient of the monomial X^I to "c"
+ * in case such a coefficient doesn't really exist this method creates it
+ * and creates all monomials X^J with J < I that don't exist yet, setting
+ * their coefficients to "zero";
+ * (with J < I we mean "<" wrt the lexicographic order)
+ *
+ */
+
+template <size_t N, typename T>
+struct coefficient
+{
+};
+
+
+template <size_t N, typename CoeffT>
+struct coefficient< N, Polynomial<CoeffT> >
+{
+ typedef typename coefficient<N-1, CoeffT>::type type;
+ typedef Polynomial<CoeffT> poly_type;
+
+ static const type zero;
+
+ static
+ type const& get(poly_type const& p, multi_index_type const& I)
+ {
+ if (I.size() != N+1)
+ THROW_RANGEERROR ("multi-index with wrong length");
+
+ return get_impl<0>(p, I);
+ }
+
+ static
+ type & get(poly_type & p, multi_index_type const& I)
+ {
+ if (I.size() != N+1)
+ THROW_RANGEERROR ("multi-index with wrong length");
+
+ return get_impl<0>(p, I);
+ }
+
+ static
+ type const& get_safe(poly_type const& p, multi_index_type const& I)
+ {
+ if (I.size() != N+1)
+ THROW_RANGEERROR ("multi-index with wrong length");
+
+ return get_safe_impl<0>(p, I);
+ }
+
+ static
+ void set_safe(poly_type & p, multi_index_type const& I, type const& c)
+ {
+ if (I.size() != N+1)
+ THROW_RANGEERROR ("multi-index with wrong length");
+
+ return set_safe_impl<0>(p, I, c);
+ }
+
+ private:
+ template <size_t i>
+ static
+ type const& get_impl(poly_type const& p, multi_index_type const& I)
+ {
+ return coefficient<N-1, CoeffT>::template get_impl<i+1>(p[I[i]], I);
+ }
+
+ template <size_t i>
+ static
+ type & get_impl(poly_type & p, multi_index_type const& I)
+ {
+ return coefficient<N-1, CoeffT>::template get_impl<i+1>(p[I[i]], I);
+ }
+
+ template <size_t i>
+ static
+ type const& get_safe_impl(poly_type const& p, multi_index_type const& I)
+ {
+ if (I[i] > p.max_degree())
+ {
+ return zero;
+ }
+ else
+ {
+ return
+ coefficient<N-1, CoeffT>::template get_safe_impl<i+1>(p[I[i]], I);
+ }
+ }
+
+ template <size_t i>
+ static
+ void set_safe_impl(poly_type & p, multi_index_type const& I, type const& c)
+ {
+ if (I[i] > p.max_degree())
+ {
+ multi_index_type J = shift(I, i+1);
+ CoeffT m = monomial<N, type>::make(J, c);
+ p.coefficient(I[i], m);
+ }
+ else
+ {
+ coefficient<N-1, CoeffT>::template set_safe_impl<i+1>(p[I[i]], I, c);
+ }
+ }
+
+ template<size_t M, typename T>
+ friend struct coefficient;
+
+};
+
+// initialization of static member zero
+template <size_t N, typename CoeffT>
+const typename coefficient< N, Polynomial<CoeffT> >::type
+coefficient< N, Polynomial<CoeffT> >::zero
+ = Geom::SL::zero<typename coefficient< N, Polynomial<CoeffT> >::type >()();
+
+
+// case N = 0 for stopping recursion
+template <typename CoeffT>
+struct coefficient< 0, Polynomial<CoeffT> >
+{
+ typedef CoeffT type;
+ typedef Polynomial<CoeffT> poly_type;
+
+ static const type zero;
+
+ static
+ type const& get(poly_type const& p, multi_index_type const& I)
+ {
+ if (I.size() != 1)
+ THROW_RANGEERROR ("multi-index with wrong length");
+
+ return p[I[0]];
+ }
+
+ static
+ type & get(poly_type & p, multi_index_type const& I)
+ {
+ if (I.size() != 1)
+ THROW_RANGEERROR ("multi-index with wrong length");
+
+ return p[I[0]];
+ }
+
+ static
+ type const& get_safe(poly_type const& p, multi_index_type const& I)
+ {
+ if (I.size() != 1)
+ THROW_RANGEERROR ("multi-index with wrong length");
+
+ return p.coefficient(I[0]);
+ }
+
+ static
+ void set_safe(poly_type & p, multi_index_type const& I, type const& c)
+ {
+ if (I.size() != 1)
+ THROW_RANGEERROR ("multi-index with wrong length");
+
+ p.coefficient(I[0], c);
+ }
+
+ private:
+ template <size_t i>
+ static
+ type const& get_impl(poly_type const& p, multi_index_type const& I)
+ {
+ return p[I[i]];
+ }
+
+ template <size_t i>
+ static
+ type & get_impl(poly_type & p, multi_index_type const& I)
+ {
+ return p[I[i]];
+ }
+
+ template <size_t i>
+ static
+ type const& get_safe_impl(poly_type const& p, multi_index_type const& I)
+ {
+ return p.coefficient(I[i]);
+ }
+
+ template <size_t i>
+ static
+ void set_safe_impl(poly_type & p, multi_index_type const& I, type const& c)
+ {
+ p.coefficient(I[i], c);
+ }
+
+ template<size_t M, typename T>
+ friend struct coefficient;
+};
+
+// initialization of static member zero
+template <typename CoeffT>
+const typename coefficient< 0, Polynomial<CoeffT> >::type
+coefficient< 0, Polynomial<CoeffT> >::zero
+ = Geom::SL::zero<typename coefficient< 0, Polynomial<CoeffT> >::type >()();
+
+
+/*
+ * ordering types:
+ * lex : lexicographic ordering
+ * ilex : inverse lexicographic ordering
+ * max_lex : max degree + lexicographic ordering for disambiguation
+ *
+ */
+
+namespace ordering
+{
+ struct lex; // WARNING: at present only lex ordering is supported
+ struct ilex;
+ struct max_lex;
+}
+
+
+/*
+ * degree of a mv poly wrt a given ordering
+ */
+
+template <size_t N, typename CoeffT, typename OrderT = ordering::lex>
+struct mvdegree
+{};
+
+template <size_t N, typename CoeffT>
+struct mvdegree<N, CoeffT, ordering::lex>
+{
+ typedef typename mvpoly<N, CoeffT>::type poly_type;
+ typedef ordering::lex ordering;
+
+ static
+ multi_index_type value(poly_type const& p)
+ {
+ return Geom::SL::mvpoly<N, CoeffT>::lex_degree(p);
+ }
+};
+
+} /*end namespace Geom*/ } /*end namespace SL*/
+
+
+#endif // _GEOM_SL_MVPOLY_TOOLS_H_
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/symbolic/polynomial.h b/src/3rdparty/2geom/include/2geom/symbolic/polynomial.h
new file mode 100644
index 0000000..fea7e6c
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/symbolic/polynomial.h
@@ -0,0 +1,569 @@
+/*
+ * Polynomial<CoeffT> class template
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef _GEOM_SL_POLYNOMIAL_H_
+#define _GEOM_SL_POLYNOMIAL_H_
+
+
+#include <2geom/symbolic/unity-builder.h>
+
+#include <vector>
+#include <string>
+
+#include <2geom/exception.h>
+
+
+
+
+namespace Geom { namespace SL {
+
+/*
+ * Polynomial<CoeffT> class template
+ *
+ * It represents a generic univariate polynomial with coefficients
+ * of type CoeffT. One way to get a multi-variate polynomial is
+ * to utilize a Polynomial instantiation as coefficient type
+ * in a recursive style.
+ *
+ */
+
+template< typename CoeffT >
+class Polynomial
+{
+ public:
+ typedef CoeffT coeff_type;
+ typedef std::vector<coeff_type> coeff_container_t;
+ typedef typename coeff_container_t::iterator iterator;
+ typedef typename coeff_container_t::const_iterator const_iterator;
+
+ /*
+ * a Polynomial should be never empty
+ */
+ Polynomial()
+ {
+ m_coeff.push_back(zero_coeff);
+ }
+
+ explicit
+ Polynomial(CoeffT const& c, size_t i = 0)
+ {
+ m_coeff.resize(i, zero_coeff);
+ m_coeff.push_back(c);
+ }
+
+ /*
+ * forwarding of some std::vector methods
+ */
+
+ size_t size() const
+ {
+ return m_coeff.size();
+ }
+
+ const_iterator begin() const
+ {
+ return m_coeff.begin();
+ }
+
+ const_iterator end() const
+ {
+ return m_coeff.end();
+ }
+
+ iterator begin()
+ {
+ return m_coeff.begin();
+ }
+
+ iterator end()
+ {
+ return m_coeff.end();
+ }
+
+ void reserve(size_t n)
+ {
+ m_coeff.reserve(n);
+ }
+
+ size_t capacity() const
+ {
+ return m_coeff.capacity();
+ }
+
+ /*
+ * degree of the term with the highest degree
+ * and an initialized coefficient (even if zero)
+ */
+ size_t max_degree() const
+ {
+ if (size() == 0)
+ THROW_INVARIANTSVIOLATION (0);
+
+ return (size() - 1);
+ }
+
+ void max_degree(size_t n)
+ {
+ m_coeff.resize(n+1, zero_coeff);
+ }
+
+ /*
+ * degree of the term with the highest degree
+ * and an initialized coefficient that is not null
+ */
+ size_t real_degree() const
+ {
+ if (size() == 0)
+ THROW_INVARIANTSVIOLATION (0);
+
+ const_iterator it = end() - 1;
+ for (; it != begin(); --it)
+ {
+ if (*it != zero_coeff) break;
+ }
+ size_t i = static_cast<size_t>(it - begin());
+ return i;
+ }
+
+ bool is_zero() const
+ {
+ if (size() == 0)
+ THROW_INVARIANTSVIOLATION (0);
+
+ if (real_degree() != 0) return false;
+ if (m_coeff[0] != zero_coeff) return false;
+ return true;
+ }
+
+ /*
+ * trim leading zero coefficients
+ * after calling normalize max_degree == real_degree
+ */
+ void normalize()
+ {
+ size_t rd = real_degree();
+ if (rd != max_degree())
+ {
+ m_coeff.erase(begin() + rd + 1, end());
+ }
+ }
+
+ coeff_type const& operator[] (size_t i) const
+ {
+ return m_coeff[i];
+ }
+
+ coeff_type & operator[] (size_t i)
+ {
+ return m_coeff[i];
+ }
+
+ // safe coefficient getter routine
+ coeff_type const& coefficient(size_t i) const
+ {
+ if (i > max_degree())
+ {
+ return zero_coeff;
+ }
+ else
+ {
+ return m_coeff[i];
+ }
+ }
+
+ // safe coefficient setter routine
+ void coefficient(size_t i, coeff_type const& c)
+ {
+ //std::cerr << "i: " << i << " c: " << c << std::endl;
+ if (i > max_degree())
+ {
+ if (c == zero_coeff) return;
+ reserve(i+1);
+ m_coeff.resize(i, zero_coeff);
+ m_coeff.push_back(c);
+ }
+ else
+ {
+ m_coeff[i] = c;
+ }
+ }
+
+ coeff_type const& leading_coefficient() const
+ {
+ return m_coeff[real_degree()];
+ }
+
+ coeff_type & leading_coefficient()
+ {
+ return m_coeff[real_degree()];
+ }
+
+ /*
+ * polynomail evaluation:
+ * T can be any type that is able to be + and * with the coefficient type
+ */
+ template <typename T>
+ T operator() (T const& x) const
+ {
+ T r = zero<T>()();
+ for(size_t i = max_degree(); i > 0; --i)
+ {
+ r += (*this)[i];
+ r *= x;
+ }
+ r += (*this)[0];
+ return r;
+ }
+
+ // opposite polynomial
+ Polynomial operator-() const
+ {
+ Polynomial r;
+ // we need r.m_coeff to be empty so we can utilize push_back
+ r.m_coeff.pop_back();
+ r.reserve(size());
+ for(size_t i = 0; i < size(); ++i)
+ {
+ r.m_coeff.push_back( -(*this)[i] );
+ }
+ return r;
+ }
+
+ /*
+ * polynomial-polynomial mutating operators
+ */
+
+ Polynomial& operator+=(Polynomial const& p)
+ {
+ size_t sz = std::min(size(), p.size());
+ for (size_t i = 0; i < sz; ++i)
+ {
+ (*this)[i] += p[i];
+ }
+ if (size() < p.size())
+ {
+ m_coeff.insert(end(), p.begin() + size(), p.end());
+ }
+ return (*this);
+ }
+
+ Polynomial& operator-=(Polynomial const& p)
+ {
+ size_t sz = std::min(size(), p.size());
+ for (size_t i = 0; i < sz; ++i)
+ {
+ (*this)[i] -= p[i];
+ }
+ reserve(p.size());
+ for(size_t i = sz; i < p.size(); ++i)
+ {
+ m_coeff.push_back( -p[i] );
+ }
+ return (*this);
+ }
+
+ Polynomial& operator*=(Polynomial const& p)
+ {
+ Polynomial r;
+ r.m_coeff.resize(size() + p.size() - 1, zero_coeff);
+
+ for (size_t i = 0; i < size(); ++i)
+ {
+ for (size_t j = 0; j < p.size(); ++j)
+ {
+ r[i+j] += (*this)[i] * p[j];
+ }
+ }
+ (*this) = r;
+ return (*this);
+ }
+
+ /*
+ * equivalent to multiply by x^n
+ */
+ Polynomial& operator<<=(size_t n)
+ {
+ m_coeff.insert(begin(), n, zero_coeff);
+ return (*this);
+ }
+
+ /*
+ * polynomial-coefficient mutating operators
+ */
+
+ Polynomial& operator=(coeff_type const& c)
+ {
+ m_coeff[0] = c;
+ return (*this);
+ }
+
+ Polynomial& operator+=(coeff_type const& c)
+ {
+ (*this)[0] += c;
+ return (*this);
+ }
+
+ Polynomial& operator-=(coeff_type const& c)
+ {
+ (*this)[0] -= c;
+ return (*this);
+ }
+
+ Polynomial& operator*=(coeff_type const& c)
+ {
+ for (size_t i = 0; i < size(); ++i)
+ {
+ (*this)[i] *= c;
+ }
+ return (*this);
+ }
+
+ // return the poly in a string form
+ std::string str() const;
+
+ private:
+ // with zero_coeff defined as a static data member
+ // coefficient(size_t i) safe get method can always
+ // return a (const) reference
+ static const coeff_type zero_coeff;
+ coeff_container_t m_coeff;
+
+}; // end class Polynomial
+
+
+/*
+ * zero and one element spezcialization for Polynomial
+ */
+
+template< typename CoeffT >
+struct zero<Polynomial<CoeffT>, false>
+{
+ Polynomial<CoeffT> operator() () const
+ {
+ CoeffT zc = zero<CoeffT>()();
+ Polynomial<CoeffT> z(zc);
+ return z;
+ }
+};
+
+template< typename CoeffT >
+struct one<Polynomial<CoeffT>, false>
+{
+ Polynomial<CoeffT> operator() ()
+ {
+ CoeffT _1c = one<CoeffT>()();
+ Polynomial<CoeffT> _1(_1c);
+ return _1;
+ }
+};
+
+
+/*
+ * initialization of Polynomial static data members
+ */
+
+template< typename CoeffT >
+const typename Polynomial<CoeffT>::coeff_type Polynomial<CoeffT>::zero_coeff
+ = zero<typename Polynomial<CoeffT>::coeff_type>()();
+
+/*
+ * Polynomial - Polynomial binary mathematical operators
+ */
+
+template< typename CoeffT >
+inline
+bool operator==(Polynomial<CoeffT> const& p, Polynomial<CoeffT> const& q)
+{
+ size_t d = p.real_degree();
+ if (d != q.real_degree()) return false;
+ for (size_t i = 0; i <= d; ++i)
+ {
+ if (p[i] != q[i]) return false;
+ }
+ return true;
+}
+
+template< typename CoeffT >
+inline
+bool operator!=(Polynomial<CoeffT> const& p, Polynomial<CoeffT> const& q)
+{
+ return !(p == q);
+}
+
+template< typename CoeffT >
+inline
+Polynomial<CoeffT>
+operator+( Polynomial<CoeffT> const& p, Polynomial<CoeffT> const& q )
+{
+ Polynomial<CoeffT> r(p);
+ r += q;
+ return r;
+}
+
+template< typename CoeffT >
+inline
+Polynomial<CoeffT>
+operator-( Polynomial<CoeffT> const& p, Polynomial<CoeffT> const& q )
+{
+ Polynomial<CoeffT> r(p);
+ r -= q;
+ return r;
+}
+
+template< typename CoeffT >
+inline
+Polynomial<CoeffT>
+operator*( Polynomial<CoeffT> const& p, Polynomial<CoeffT> const& q )
+{
+ Polynomial<CoeffT> r(p);
+ r *= q;
+ return r;
+}
+
+template< typename CoeffT >
+inline
+Polynomial<CoeffT> operator<<(Polynomial<CoeffT> const& p, size_t n)
+{
+ Polynomial<CoeffT> r(p);
+ r <<= n;
+ return r;
+}
+
+
+/*
+ * polynomial-coefficient and coefficient-polynomial mathematical operators
+ */
+
+template< typename CoeffT >
+inline
+Polynomial<CoeffT>
+operator+( Polynomial<CoeffT> const& p, CoeffT const& c )
+{
+ Polynomial<CoeffT> r(p);
+ r += c;
+ return r;
+}
+
+template< typename CoeffT >
+inline
+Polynomial<CoeffT>
+operator+( CoeffT const& c, Polynomial<CoeffT> const& p)
+{
+ return (p + c);
+}
+
+template< typename CoeffT >
+inline
+Polynomial<CoeffT>
+operator-( Polynomial<CoeffT> const& p, CoeffT const& c )
+{
+ Polynomial<CoeffT> r(p);
+ r -= c;
+ return r;
+}
+
+template< typename CoeffT >
+inline
+Polynomial<CoeffT>
+operator-( CoeffT const& c, Polynomial<CoeffT> const& p)
+{
+ return (p - c);
+}
+
+template< typename CoeffT >
+inline
+Polynomial<CoeffT>
+operator*( Polynomial<CoeffT> const& p, CoeffT const& c )
+{
+ Polynomial<CoeffT> r(p);
+ r *= c;
+ return r;
+}
+
+template< typename CoeffT >
+inline
+Polynomial<CoeffT>
+operator*( CoeffT const& c, Polynomial<CoeffT> const& p)
+{
+ return (p * c);
+}
+
+
+/*
+ * operator<< extension for printing Polynomial
+ * and str() method for transforming a Polynomial into a string
+ */
+
+template< typename charT, typename CoeffT >
+inline
+std::basic_ostream<charT> &
+operator<< (std::basic_ostream<charT> & os, const Polynomial<CoeffT> & p)
+{
+ if (p.size() == 0) return os;
+ os << "{" << p[0];
+ for (size_t i = 1; i < p.size(); ++i)
+ {
+ os << ", " << p[i];
+ }
+ os << "}";
+ return os;
+}
+
+
+template< typename CoeffT >
+inline
+std::string Polynomial<CoeffT>::str() const
+{
+ std::ostringstream oss;
+ oss << (*this);
+ return oss.str();
+}
+
+
+} /*end namespace Geom*/ } /*end namespace SL*/
+
+
+
+
+#endif // _GEOM_SL_POLYNOMIAL_H_
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/symbolic/unity-builder.h b/src/3rdparty/2geom/include/2geom/symbolic/unity-builder.h
new file mode 100644
index 0000000..cb8046f
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/symbolic/unity-builder.h
@@ -0,0 +1,102 @@
+/*
+ * Routines to make up "zero" and "one" elements of a ring
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef _GEOM_SL_UNITY_BUILDER_H_
+#define _GEOM_SL_UNITY_BUILDER_H_
+
+
+#include <type_traits>
+
+
+
+namespace Geom { namespace SL {
+
+
+/*
+ * zero builder function class type
+ *
+ * made up a zero element, in the algebraic ring theory meaning,
+ * for the type T
+ */
+
+template< typename T, bool numeric = std::is_arithmetic<T>::value >
+struct zero
+{};
+
+// specialization for basic numeric type
+template< typename T >
+struct zero<T, true>
+{
+ T operator() () const
+ {
+ return 0;
+ }
+};
+
+
+/*
+ * one builder function class type
+ *
+ * made up a one element, in the algebraic ring theory meaning,
+ * for the type T
+ */
+
+template< typename T, bool numeric = std::is_arithmetic<T>::value >
+struct one
+{};
+
+// specialization for basic numeric type
+template< typename T >
+struct one<T, true>
+{
+ T operator() ()
+ {
+ return 1;
+ }
+};
+
+} /*end namespace Geom*/ } /*end namespace SL*/
+
+
+#endif // _GEOM_SL_UNITY_BUILDER_H_
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/transforms.h b/src/3rdparty/2geom/include/2geom/transforms.h
new file mode 100644
index 0000000..cc55e29
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/transforms.h
@@ -0,0 +1,370 @@
+/**
+ * @file
+ * @brief Affine transformation classes
+ *//*
+ * Authors:
+ * ? <?@?.?>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ * Johan Engelen
+ *
+ * Copyright ?-2012 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_TRANSFORMS_H
+#define LIB2GEOM_SEEN_TRANSFORMS_H
+
+#include <cmath>
+#include <2geom/forward.h>
+#include <2geom/affine.h>
+#include <2geom/angle.h>
+#include <boost/concept/assert.hpp>
+
+namespace Geom {
+
+/** @brief Type requirements for transforms.
+ * @ingroup Concepts */
+template <typename T>
+struct TransformConcept {
+ T t, t2;
+ Affine m;
+ Point p;
+ bool bool_;
+ Coord epsilon;
+ void constraints() {
+ m = t; //implicit conversion
+ m *= t;
+ m = m * t;
+ m = t * m;
+ p *= t;
+ p = p * t;
+ t *= t;
+ t = t * t;
+ t = pow(t, 3);
+ bool_ = (t == t);
+ bool_ = (t != t);
+ t = T::identity();
+ t = t.inverse();
+ bool_ = are_near(t, t2);
+ bool_ = are_near(t, t2, epsilon);
+ }
+};
+
+/** @brief Base template for transforms.
+ * This class is an implementation detail and should not be used directly. */
+template <typename T>
+class TransformOperations
+ : boost::equality_comparable< T
+ , boost::multipliable< T
+ > >
+{
+public:
+ template <typename T2>
+ Affine operator*(T2 const &t) const {
+ Affine ret(*static_cast<T const*>(this)); ret *= t; return ret;
+ }
+};
+
+/** @brief Integer exponentiation for transforms.
+ * Negative exponents will yield the corresponding power of the inverse. This function
+ * can also be applied to matrices.
+ * @param t Affine or transform to exponantiate
+ * @param n Exponent
+ * @return \f$A^n\f$ if @a n is positive, \f$(A^{-1})^n\f$ if negative, identity if zero.
+ * @ingroup Transforms */
+template <typename T>
+T pow(T const &t, int n) {
+ BOOST_CONCEPT_ASSERT((TransformConcept<T>));
+ if (n == 0) return T::identity();
+ T result(T::identity());
+ T x(n < 0 ? t.inverse() : t);
+ if (n < 0) n = -n;
+ while ( n ) { // binary exponentiation - fast
+ if ( n & 1 ) { result *= x; --n; }
+ x *= x; n /= 2;
+ }
+ return result;
+}
+
+/** @brief Translation by a vector.
+ * @ingroup Transforms */
+class Translate
+ : public TransformOperations< Translate >
+{
+ Point vec;
+public:
+ /// Create a translation that doesn't do anything.
+ Translate() : vec(0, 0) {}
+ /// Construct a translation from its vector.
+ Translate(Point const &p) : vec(p) {}
+ /// Construct a translation from its coordinates.
+ Translate(Coord x, Coord y) : vec(x, y) {}
+
+ operator Affine() const { Affine ret(1, 0, 0, 1, vec[X], vec[Y]); return ret; }
+ Coord operator[](Dim2 dim) const { return vec[dim]; }
+ Coord operator[](unsigned dim) const { return vec[dim]; }
+ Translate &operator*=(Translate const &o) { vec += o.vec; return *this; }
+ bool operator==(Translate const &o) const { return vec == o.vec; }
+
+ Point vector() const { return vec; }
+ /// Get the inverse translation.
+ Translate inverse() const { return Translate(-vec); }
+ /// Get a translation that doesn't do anything.
+ static Translate identity() { Translate ret; return ret; }
+
+ friend class Point;
+};
+
+inline bool are_near(Translate const &a, Translate const &b, Coord eps=EPSILON) {
+ return are_near(a[X], b[X], eps) && are_near(a[Y], b[Y], eps);
+}
+
+/** @brief Scaling from the origin.
+ * During scaling, the point (0,0) will not move. To obtain a scale with a different
+ * invariant point, combine with translation to the origin and back.
+ * @ingroup Transforms */
+class Scale
+ : public TransformOperations< Scale >
+{
+ Point vec;
+public:
+ /// Create a scaling that doesn't do anything.
+ Scale() : vec(1, 1) {}
+ /// Create a scaling from two scaling factors given as coordinates of a point.
+ explicit Scale(Point const &p) : vec(p) {}
+ /// Create a scaling from two scaling factors.
+ Scale(Coord x, Coord y) : vec(x, y) {}
+ /// Create an uniform scaling from a single scaling factor.
+ explicit Scale(Coord s) : vec(s, s) {}
+ inline operator Affine() const { Affine ret(vec[X], 0, 0, vec[Y], 0, 0); return ret; }
+
+ Coord operator[](Dim2 d) const { return vec[d]; }
+ Coord operator[](unsigned d) const { return vec[d]; }
+ //TODO: should we keep these mutators? add them to the other transforms?
+ Coord &operator[](Dim2 d) { return vec[d]; }
+ Coord &operator[](unsigned d) { return vec[d]; }
+ Scale &operator*=(Scale const &b) { vec[X] *= b[X]; vec[Y] *= b[Y]; return *this; }
+ bool operator==(Scale const &o) const { return vec == o.vec; }
+
+ Point vector() const { return vec; }
+ Scale inverse() const { return Scale(1./vec[0], 1./vec[1]); }
+ static Scale identity() { Scale ret; return ret; }
+
+ friend class Point;
+};
+
+inline bool are_near(Scale const &a, Scale const &b, Coord eps=EPSILON) {
+ return are_near(a[X], b[X], eps) && are_near(a[Y], b[Y], eps);
+}
+
+/** @brief Rotation around the origin.
+ * Combine with translations to the origin and back to get a rotation around a different point.
+ * @ingroup Transforms */
+class Rotate
+ : public TransformOperations< Rotate >
+{
+ Point vec; ///< @todo Convert to storing the angle, as it's more space-efficient.
+public:
+ /// Construct a zero-degree rotation.
+ Rotate() : vec(1, 0) {}
+ /** @brief Construct a rotation from its angle in radians.
+ * Positive arguments correspond to counter-clockwise rotations (if Y grows upwards). */
+ explicit Rotate(Coord theta) : vec(Point::polar(theta)) {}
+ /// Construct a rotation from its characteristic vector.
+ explicit Rotate(Point const &p) : vec(unit_vector(p)) {}
+ /// Construct a rotation from the coordinates of its characteristic vector.
+ explicit Rotate(Coord x, Coord y) { Rotate(Point(x, y)); }
+ operator Affine() const { Affine ret(vec[X], vec[Y], -vec[Y], vec[X], 0, 0); return ret; }
+
+ /** @brief Get the characteristic vector of the rotation.
+ * @return A vector that would be obtained by applying this transform to the X versor. */
+ Point vector() const { return vec; }
+ Coord angle() const { return atan2(vec); }
+ Coord operator[](Dim2 dim) const { return vec[dim]; }
+ Coord operator[](unsigned dim) const { return vec[dim]; }
+ Rotate &operator*=(Rotate const &o) { vec *= o; return *this; }
+ bool operator==(Rotate const &o) const { return vec == o.vec; }
+ Rotate inverse() const {
+ Rotate r;
+ r.vec = Point(vec[X], -vec[Y]);
+ return r;
+ }
+ /// @brief Get a zero-degree rotation.
+ static Rotate identity() { Rotate ret; return ret; }
+ /** @brief Construct a rotation from its angle in degrees.
+ * Positive arguments correspond to clockwise rotations if Y grows downwards. */
+ static Rotate from_degrees(Coord deg) {
+ Coord rad = (deg / 180.0) * M_PI;
+ return Rotate(rad);
+ }
+ static Affine around(Point const &p, Coord angle);
+
+ friend class Point;
+};
+
+inline bool are_near(Rotate const &a, Rotate const &b, Coord eps=EPSILON) {
+ return are_near(a[X], b[X], eps) && are_near(a[Y], b[Y], eps);
+}
+
+/** @brief Common base for shearing transforms.
+ * This class is an implementation detail and should not be used directly.
+ * @ingroup Transforms */
+template <typename S>
+class ShearBase
+ : public TransformOperations< S >
+{
+protected:
+ Coord f;
+ ShearBase(Coord _f) : f(_f) {}
+public:
+ Coord factor() const { return f; }
+ void setFactor(Coord nf) { f = nf; }
+ S &operator*=(S const &s) { f += s.f; return static_cast<S &>(*this); }
+ bool operator==(S const &s) const { return f == s.f; }
+ S inverse() const { S ret(-f); return ret; }
+ static S identity() { S ret(0); return ret; }
+
+ friend class Point;
+ friend class Affine;
+};
+
+/** @brief Horizontal shearing.
+ * Points on the X axis will not move. Combine with translations to get a shear
+ * with a different invariant line.
+ * @ingroup Transforms */
+class HShear
+ : public ShearBase<HShear>
+{
+public:
+ explicit HShear(Coord h) : ShearBase<HShear>(h) {}
+ operator Affine() const { Affine ret(1, 0, f, 1, 0, 0); return ret; }
+};
+
+inline bool are_near(HShear const &a, HShear const &b, Coord eps=EPSILON) {
+ return are_near(a.factor(), b.factor(), eps);
+}
+
+/** @brief Vertical shearing.
+ * Points on the Y axis will not move. Combine with translations to get a shear
+ * with a different invariant line.
+ * @ingroup Transforms */
+class VShear
+ : public ShearBase<VShear>
+{
+public:
+ explicit VShear(Coord h) : ShearBase<VShear>(h) {}
+ operator Affine() const { Affine ret(1, f, 0, 1, 0, 0); return ret; }
+};
+
+inline bool are_near(VShear const &a, VShear const &b, Coord eps=EPSILON) {
+ return are_near(a.factor(), b.factor(), eps);
+}
+
+/** @brief Combination of a translation and uniform scale.
+ * The translation part is applied first, then the result is scaled from the new origin.
+ * This way when the class is used to accumulate a zoom transform, trans always points
+ * to the new origin in original coordinates.
+ * @ingroup Transforms */
+class Zoom
+ : public TransformOperations< Zoom >
+{
+ Coord _scale;
+ Point _trans;
+ Zoom() : _scale(1), _trans() {}
+public:
+ /// Construct a zoom from a scaling factor.
+ explicit Zoom(Coord s) : _scale(s), _trans() {}
+ /// Construct a zoom from a translation.
+ explicit Zoom(Translate const &t) : _scale(1), _trans(t.vector()) {}
+ /// Construct a zoom from a scaling factor and a translation.
+ Zoom(Coord s, Translate const &t) : _scale(s), _trans(t.vector()) {}
+
+ operator Affine() const {
+ Affine ret(_scale, 0, 0, _scale, _trans[X] * _scale, _trans[Y] * _scale);
+ return ret;
+ }
+ Zoom &operator*=(Zoom const &z) {
+ _trans += z._trans / _scale;
+ _scale *= z._scale;
+ return *this;
+ }
+ bool operator==(Zoom const &z) const { return _scale == z._scale && _trans == z._trans; }
+
+ Coord scale() const { return _scale; }
+ void setScale(Coord s) { _scale = s; }
+ Point translation() const { return _trans; }
+ void setTranslation(Point const &p) { _trans = p; }
+ Zoom inverse() const { Zoom ret(1/_scale, Translate(-_trans*_scale)); return ret; }
+ static Zoom identity() { Zoom ret(1.0); return ret; }
+ static Zoom map_rect(Rect const &old_r, Rect const &new_r);
+
+ friend class Point;
+ friend class Affine;
+};
+
+inline bool are_near(Zoom const &a, Zoom const &b, Coord eps=EPSILON) {
+ return are_near(a.scale(), b.scale(), eps) &&
+ are_near(a.translation(), b.translation(), eps);
+}
+
+/** @brief Specialization of exponentiation for Scale.
+ * @relates Scale */
+template<>
+inline Scale pow(Scale const &s, int n) {
+ Scale ret(::pow(s[X], n), ::pow(s[Y], n));
+ return ret;
+}
+/** @brief Specialization of exponentiation for Translate.
+ * @relates Translate */
+template<>
+inline Translate pow(Translate const &t, int n) {
+ Translate ret(t[X] * n, t[Y] * n);
+ return ret;
+}
+
+
+/** @brief Reflects objects about line.
+ * The line, defined by a vector along the line and a point on it, acts as a mirror.
+ * @ingroup Transforms
+ * @see Line::reflection()
+ */
+Affine reflection(Point const & vector, Point const & origin);
+
+//TODO: decomposition of Affine into some finite combination of the above classes
+
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_TRANSFORMS_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/2geom/utils.h b/src/3rdparty/2geom/include/2geom/utils.h
new file mode 100644
index 0000000..87f49bb
--- /dev/null
+++ b/src/3rdparty/2geom/include/2geom/utils.h
@@ -0,0 +1,114 @@
+/**
+ * \file
+ * \brief Various utility functions.
+ *//*
+ * Copyright 2007 Johan Engelen <goejendaagh@zonnet.nl>
+ * Copyright 2006 Michael G. Sloan <mgsloan@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef LIB2GEOM_SEEN_UTILS_H
+#define LIB2GEOM_SEEN_UTILS_H
+
+#include <cstddef>
+#include <vector>
+#include <boost/operators.hpp>
+
+namespace Geom {
+
+// Throw these errors instead of aserting so code can handle them if needed.
+using ErrorCode = int;
+enum Errors : ErrorCode {
+ GEOM_ERR_INTERSECGRAPH,
+};
+
+void binomial_coefficients(std::vector<size_t>& bc, std::size_t n);
+
+struct EmptyClass {};
+
+/**
+ * @brief Noncommutative multiplication helper.
+ * Generates operator*(T, U) from operator*=(T, U). Does not generate operator*(U, T)
+ * like boost::multipliable does. This makes it suitable for noncommutative cases,
+ * such as transforms.
+ */
+template <class T, class U, class B = EmptyClass>
+struct MultipliableNoncommutative : B
+{
+ friend T operator*(T const &lhs, U const &rhs) {
+ T nrv(lhs); nrv *= rhs; return nrv;
+ }
+};
+
+/** @brief Null output iterator
+ * Use this if you want to discard a result returned through an output iterator. */
+struct NullIterator
+ : public boost::output_iterator_helper<NullIterator>
+{
+ NullIterator() {}
+
+ template <typename T>
+ void operator=(T const &) {}
+};
+
+/** @brief Get the next iterator in the container with wrap-around.
+ * If the iterator would become the end iterator after incrementing,
+ * return the begin iterator instead. */
+template <typename Iter, typename Container>
+Iter cyclic_next(Iter i, Container &c) {
+ ++i;
+ if (i == c.end()) {
+ i = c.begin();
+ }
+ return i;
+}
+
+/** @brief Get the previous iterator in the container with wrap-around.
+ * If the passed iterator is the begin iterator, return the iterator
+ * just before the end iterator instead. */
+template <typename Iter, typename Container>
+Iter cyclic_prior(Iter i, Container &c) {
+ if (i == c.begin()) {
+ i = c.end();
+ }
+ --i;
+ return i;
+}
+
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_UTILS_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/toys/lpe-framework.h b/src/3rdparty/2geom/include/toys/lpe-framework.h
new file mode 100644
index 0000000..9de5aa0
--- /dev/null
+++ b/src/3rdparty/2geom/include/toys/lpe-framework.h
@@ -0,0 +1,77 @@
+/**
+ * \file lpe-framework.h
+ * \brief A framework for writing an Inkscape Live Path Effect toy.
+ *
+ * Instead of using the standard toy framework, one can use this LPE
+ * framework when creating an LPE for Inkscape. When new 2geom functions
+ * are required for the LPE, adding this functionality directly in Inkscape
+ * greatly increases compile times. Using this framework, one only has to
+ * rebuild 2geom, which speeds up development considerably. (Think about
+ * how much of Inkscape will have to be rebuild if you change/add something
+ * in point.h ...)
+ * An example of how to use this framework is lpe.test.cpp.
+ *//*
+ * Copyright 2009 Johan Engelen <goejendaagh@zonnet.nl>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef _2GEOM_LPE_TOY_FRAMEWORK_H_
+#define _2GEOM_LPE_TOY_FRAMEWORK_H_
+
+/**
+ * This should greatly simplify creating toy code for a Live Path Effect (LPE) for Inkscape
+ */
+
+
+#include <toys/toy-framework-2.h>
+#include <2geom/pathvector.h>
+
+class LPEToy: public Toy {
+public:
+ LPEToy();
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override;
+ virtual Geom::PathVector
+ doEffect_path (Geom::PathVector const & path_in);
+ virtual Geom::Piecewise<Geom::D2<Geom::SBasis> >
+ doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in);
+
+ /** this boolean defaults to false, it concatenates the input path to one pwd2,
+ * instead of normally 'splitting' the path into continuous pwd2 paths. */
+ bool concatenate_before_pwd2;
+ PointSetHandle curve_handle;
+};
+
+#endif // _2GEOM_LPE_TOY_FRAMEWORK_H_
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+ */
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/include/toys/path-cairo.h b/src/3rdparty/2geom/include/toys/path-cairo.h
new file mode 100644
index 0000000..4c0403f
--- /dev/null
+++ b/src/3rdparty/2geom/include/toys/path-cairo.h
@@ -0,0 +1,57 @@
+#ifndef PATH_CAIRO
+#define PATH_CAIRO
+
+
+#include <cairo.h>
+#include <2geom/line.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/d2.h>
+#include <2geom/piecewise.h>
+#include <2geom/path.h>
+#include <2geom/convex-hull.h>
+#include <vector>
+#include <string>
+
+typedef struct _cairo cairo_t;
+
+void cairo_curve(cairo_t *cr, Geom::Curve const &c);
+void cairo_rectangle(cairo_t *cr, Geom::Rect const &r);
+void cairo_convex_hull(cairo_t *cr, Geom::ConvexHull const &r);
+void cairo_path(cairo_t *cr, Geom::Path const &p);
+void cairo_path(cairo_t *cr, Geom::PathVector const &p);
+void cairo_path_stitches(cairo_t *cr, Geom::Path const &p);
+void cairo_path_stitches(cairo_t *cr, Geom::PathVector const &p);
+
+void cairo_d2_sb(cairo_t *cr, Geom::D2<Geom::SBasis> const &p);
+void cairo_d2_sb_handles(cairo_t *cr, Geom::D2<Geom::SBasis> const &p);
+void cairo_d2_sb2d(cairo_t* cr, Geom::D2<Geom::SBasis2d> const &sb2, Geom::Point dir, double width);
+void cairo_sb2d(cairo_t* cr, Geom::SBasis2d const &sb2, Geom::Point dir, double width);
+
+void cairo_d2_pw_sb(cairo_t *cr, Geom::D2<Geom::Piecewise<Geom::SBasis> > const &p);
+void cairo_pw_d2_sb(cairo_t *cr, Geom::Piecewise<Geom::D2<Geom::SBasis> > const &p);
+
+
+void draw_line(cairo_t *cr, const Geom::Line& l, const Geom::Rect& r);
+void draw_line(cairo_t *cr, Geom::Point n, double d, Geom::Rect r);
+void draw_line(cairo_t *cr, Geom::Point a, Geom::Point b, Geom::Rect r);
+
+void draw_line_seg(cairo_t *cr, Geom::Point a, Geom::Point b);
+void draw_line_seg_with_arrow(cairo_t *cr, Geom::Point a, Geom::Point b, double dangle = 15*M_PI/180, double radius = 20);
+void draw_spot(cairo_t *cr, Geom::Point h);
+void draw_handle(cairo_t *cr, Geom::Point h);
+void draw_cross(cairo_t *cr, Geom::Point h);
+void draw_circ(cairo_t *cr, Geom::Point h);
+void draw_ray(cairo_t *cr, Geom::Point h, Geom::Point dir);
+void draw_ray(cairo_t *cr, const Geom::Ray& ray, const Geom::Rect& r);
+void draw_line_segment(cairo_t *cr, const Geom::LineSegment& ls, const Geom::Rect& r);
+
+void cairo_move_to(cairo_t *cr, Geom::Point p1);
+void cairo_line_to(cairo_t *cr, Geom::Point p1);
+void cairo_curve_to(cairo_t *cr, Geom::Point p1, Geom::Point p2, Geom::Point p3);
+
+// H in [0,360)
+// S, V, R, G, B in [0,1]
+void convertHSVtoRGB(const double H, const double S, const double V,
+ double& R, double& G, double& B);
+#endif
diff --git a/src/3rdparty/2geom/include/toys/toy-framework-2.h b/src/3rdparty/2geom/include/toys/toy-framework-2.h
new file mode 100644
index 0000000..5504dfd
--- /dev/null
+++ b/src/3rdparty/2geom/include/toys/toy-framework-2.h
@@ -0,0 +1,451 @@
+
+#ifndef _2GEOM_TOY_FRAMEWORK2_H_
+#define _2GEOM_TOY_FRAMEWORK2_H_
+
+
+
+#include <cairo.h>
+#include <gtk/gtk.h>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <assert.h>
+#include <2geom/exception.h>
+#include <2geom/point.h>
+#include <2geom/geom.h>
+#include <2geom/sbasis.h>
+#include <2geom/d2.h>
+#include <sched.h>
+#include <toys/path-cairo.h>
+
+using std::vector;
+
+//Utility functions
+double uniform();
+
+void draw_text(cairo_t *cr, Geom::Point pos, const char* txt, bool bottom = false, const char* fontdesc = "Sans");
+void draw_text(cairo_t *cr, Geom::Point pos, const std::string& txt, bool bottom = false, const std::string& fontdesc = "Sans");
+void draw_number(cairo_t *cr, Geom::Point pos, int num, std::string name=std::string(), bool bottom = true);
+void draw_number(cairo_t *cr, Geom::Point pos, unsigned num, std::string name=std::string(), bool bottom = true);
+void draw_number(cairo_t *cr, Geom::Point pos, double num, std::string name=std::string(), bool bottom = true);
+
+struct colour{
+ double r,g,b,a;
+ colour(double r, double g, double b, double a) : r(r), g(g), b(b), a(a) {}
+ static colour from_hsv( float H, // hue shift (radians)
+ float S, // saturation shift (scalar)
+ float V, // value multiplier (scalar)
+ float A
+ );
+ static colour from_hsl( float H, // hue shift (radians)
+ float S, // saturation shift (scalar)
+ float L, // value multiplier (scalar)
+ float A
+ );
+};
+void cairo_set_source_rgba(cairo_t* cr, colour c);
+
+class Handle{
+public:
+ std::string name;
+ float rgb[3];
+ Handle() {rgb[0] = rgb[1] = rgb[2] = 0;}
+ virtual ~Handle() {}
+ virtual void draw(cairo_t *cr, bool annotes=false) = 0;
+
+ virtual void* hit(Geom::Point pos) = 0;
+ virtual void move_to(void* hit, Geom::Point om, Geom::Point m) = 0;
+ virtual void load(FILE* f)=0;
+ virtual void save(FILE* f)=0;
+};
+
+class Toggle : public Handle{
+public:
+ Geom::Rect bounds;
+ const char* text;
+ bool on;
+ Toggle() : bounds(Geom::Point(0,0), Geom::Point(0,0)), text(""), on(false) {}
+ Toggle(const char* txt, bool v) : bounds(Geom::Point(0,0), Geom::Point(0,0)), text(txt), on(v) {}
+ Toggle(Geom::Rect bnds, const char* txt, bool v) : bounds(bnds), text(txt), on(v) {}
+ void draw(cairo_t *cr, bool annotes = false) override;
+ void toggle();
+ void set(bool state);
+ void handle_click(GdkEventButton* e);
+ void* hit(Geom::Point pos) override;
+ void move_to(void* /*hit*/, Geom::Point /*om*/, Geom::Point /*m*/) override { /* not implemented */ }
+ void load(FILE* /*f*/) override { /* not implemented */ }
+ void save(FILE* /*f*/) override { /* not implemented */ }
+};
+
+
+template< typename T>
+class VectorHandle : public Handle
+{
+ public:
+ VectorHandle()
+ : m_handles()
+ {
+ }
+ void draw(cairo_t *cr, bool annotes=false) override
+ {
+ for (iterator it = m_handles.begin(); it != m_handles.end(); ++it)
+ it->draw(cr, annotes);
+ }
+
+ void* hit(Geom::Point pos) override
+ {
+ void* result = NULL;
+ for (iterator it = m_handles.begin(); it != m_handles.end(); ++it)
+ {
+ result = it->hit(pos);
+ if (result != NULL) break;
+ }
+ return result;
+ }
+
+ void move_to(void* hit, Geom::Point om, Geom::Point m) override
+ {
+ if (hit != NULL)
+ {
+ static_cast<T*>(hit)->move_to(hit, om, m);
+ }
+ }
+
+ void load(FILE* f) override
+ {
+ for (iterator it = m_handles.begin(); it != m_handles.end(); ++it)
+ it->load(f);
+ }
+
+ void save(FILE* f) override
+ {
+ for (iterator it = m_handles.begin(); it != m_handles.end(); ++it)
+ it->save(f);
+ }
+
+ void clear()
+ {
+ m_handles.clear();
+ }
+
+ void reserve(size_t sz)
+ {
+ m_handles.reserve(sz);
+ }
+
+ size_t size() const
+ {
+ return m_handles.size();
+ }
+
+ void push_back (const T& _handle)
+ {
+ m_handles.push_back(_handle);
+ }
+
+ const T& operator[] (size_t i) const
+ {
+ return m_handles.at(i);
+ }
+
+ T& operator[] (size_t i)
+ {
+ return m_handles.at(i);
+ }
+
+ private:
+ typedef typename std::vector<T>::iterator iterator;
+ std::vector<T> m_handles;
+}; // end class VectorHandle
+
+
+class PointHandle : public Handle{
+public:
+ PointHandle(double x, double y) : pos(x,y) {}
+ PointHandle(Geom::Point pt) : pos(pt) {}
+ PointHandle() {}
+ Geom::Point pos;
+ void draw(cairo_t *cr, bool annotes = false) override;
+
+ void* hit(Geom::Point mouse) override;
+ void move_to(void* hit, Geom::Point om, Geom::Point m) override;
+ void load(FILE* f) override;
+ void save(FILE* f) override;
+};
+
+class PointSetHandle : public Handle{
+public:
+ PointSetHandle() {}
+ std::vector<Geom::Point> pts;
+ void draw(cairo_t *cr, bool annotes = false) override;
+
+ void* hit(Geom::Point mouse) override;
+ void move_to(void* hit, Geom::Point om, Geom::Point m) override;
+ void push_back(double x, double y) {pts.emplace_back(x,y);}
+ void push_back(Geom::Point pt) {pts.push_back(pt);}
+ unsigned size() {return pts.size();}
+ Geom::D2<Geom::SBasis> asBezier();
+ void load(FILE* f) override;
+ void save(FILE* f) override;
+};
+
+class RectHandle : public Handle{
+public:
+ RectHandle() {}
+ RectHandle(Geom::Rect pos, bool show_center_handle) : pos(pos), show_center_handle(show_center_handle) {}
+ Geom::Rect pos;
+ bool show_center_handle;
+ void draw(cairo_t *cr, bool annotes = false) override;
+
+ void* hit(Geom::Point mouse) override;
+ void move_to(void* hit, Geom::Point om, Geom::Point m) override;
+ void load(FILE* f) override;
+ void save(FILE* f) override;
+};
+
+
+// used by Slider
+inline std::string default_formatter(double x)
+{
+ std::ostringstream os;
+ os << x;
+ return os.str();
+}
+
+class Slider : public Handle
+{
+ public:
+
+ typedef std::string (*formatter_t) (double );
+ typedef double value_type;
+
+ Slider()
+ : m_handle(), m_pos(Geom::Point(0,0)), m_length(1),
+ m_min(0), m_max(1), m_step(0), m_dir(Geom::X),
+ m_label(""), m_formatter(&default_formatter)
+ {
+ value(0);
+ }
+
+ // pass step = 0 for having a continuos value variation
+ Slider( value_type _min, value_type _max, value_type _step,
+ value_type _value, std::string _label = "" )
+ : m_handle(),m_pos(Geom::Point(0,0)), m_length(1),
+ m_min(_min), m_max(_max), m_step(_step), m_dir(Geom::X),
+ m_label(std::move(_label)), m_formatter(&default_formatter)
+ {
+ value(_value);
+ }
+
+ void set( value_type _min, value_type _max, value_type _step,
+ value_type _value, const std::string& _label = "" )
+ {
+ m_min = _min;
+ m_max = _max;
+ m_step = _step;
+ m_label = _label;
+ value(_value);
+ }
+
+ value_type value() const;
+
+ void value(value_type _value);
+
+ value_type max_value() const
+ {
+ return m_max;
+ }
+
+ void max_value(value_type _value);
+
+ value_type min_value() const
+ {
+ return m_min;
+ }
+
+ void min_value(value_type _value);
+
+ // dir = X horizontal slider dir = Y vertical slider
+ void geometry(Geom::Point _pos, value_type _length, Geom::Dim2 _dir = Geom::X);
+
+ void draw(cairo_t* cr, bool annotate = false) override;
+
+ void formatter( formatter_t _formatter )
+ {
+ m_formatter = _formatter;
+ }
+
+ void* hit(Geom::Point pos) override
+ {
+ if (m_handle.hit(pos) != NULL)
+ return this;
+ return NULL;
+ }
+
+ void move_to(void* hit, Geom::Point om, Geom::Point m) override;
+
+ void load(FILE* f) override
+ {
+ m_handle.load(f);
+ }
+
+ void save(FILE* f) override
+ {
+ m_handle.save(f);
+ }
+
+ private:
+ PointHandle m_handle;
+ Geom::Point m_pos;
+ value_type m_length;
+ value_type m_min, m_max, m_step;
+ int m_dir;
+ std::string m_label;
+ formatter_t m_formatter;
+};
+
+
+
+
+
+class Toy {
+public:
+ vector<Handle*> handles;
+ bool mouse_down = false;
+ Geom::Point old_mouse_point;
+ Handle* selected = nullptr;
+ void* hit_data = nullptr;
+ int canvas_click_button = 0;
+ double notify_offset = 0.0;
+ std::string name;
+ bool show_timings = false;
+ FILE* spool_file = nullptr; // if non-NULL we record all interactions to this file
+
+ Toy() {}
+
+ virtual ~Toy() {}
+
+ virtual void draw(cairo_t *cr, std::ostringstream *notify, int w, int h, bool save, std::ostringstream *timing_stream);
+
+ virtual void mouse_moved(GdkEventMotion* e);
+ virtual void mouse_pressed(GdkEventButton* e);
+ virtual void mouse_released(GdkEventButton* e);
+ virtual void canvas_click(Geom::Point at, int button);
+ virtual void scroll(GdkEventScroll* e);
+
+ virtual void key_hit(GdkEventKey */*e*/) {}
+
+ //Cheapo way of informing the framework what the toy would like drawn for it.
+ virtual bool should_draw_numbers() { return true; }
+ virtual int should_draw_bounds() { return 0; }
+
+ virtual void first_time(int /*argc*/, char** /*argv*/) {}
+
+ virtual void resize_canvas(Geom::Rect const & /*s*/) {}
+ virtual void load(FILE* f);
+ virtual void save(FILE* f);
+};
+
+//Framework Accesors
+void redraw();
+void take_screenshot(const char* file);
+void init(int argc, char **argv, Toy *t, int width=600, int height=600);
+
+void toggle_events(std::vector<Toggle> &ts, GdkEventButton* e);
+void draw_toggles(cairo_t *cr, std::vector<Toggle> &ts);
+Geom::Point read_point(FILE* f);
+
+
+
+
+
+const long long NS_PER_SECOND = 1000000000LL;
+const long long NS_PER_NS = 1;
+
+
+class Timer{
+public:
+ Timer() {}
+ // note that CPU time is tracked per-thread, so the timer is only useful
+ // in the thread it was start()ed from.
+
+ class Time{
+ public:
+ double value;
+ Time(long long /*s*/, long long l) : value(l) {}
+ Time(double v) : value(v) {}
+ Time operator/(double iters) const {
+ return Time(value / iters);
+ }
+ };
+
+ void start() {
+ nsec(start_time);
+ }
+ void lap(long long &ns) {
+ nsec(ns);
+ ns -= start_time;
+ }
+ Time lap() {
+ long long ns;
+ nsec(ns);
+ return Time(start_time, ns - start_time);
+ }
+ void nsec(long long &ns) {
+#if ! (defined(_WIN32) || defined(__APPLE__))
+ clock_gettime(clock, &ts);
+ ns = ts.tv_sec * NS_PER_SECOND + ts.tv_nsec / NS_PER_NS;
+#else
+ ns = 0;
+#endif
+ }
+ /** Ask the OS nicely for a big time slice */
+ void ask_for_timeslice() {
+#ifndef _WIN32
+ sched_yield();
+#endif
+ }
+private:
+ long long start_time;
+#if ! (defined(_WIN32) || defined(__APPLE__))
+ struct timespec ts;
+# ifdef _POSIX_THREAD_CPUTIME
+ static const clockid_t clock = CLOCK_THREAD_CPUTIME_ID;
+# else
+# ifdef CLOCK_MONOTONIC
+ static const clockid_t clock = CLOCK_MONOTONIC;
+# else
+ static const clockid_t clock = CLOCK_REALTIME;
+# endif
+# endif
+#endif
+};
+
+inline std::ostream& operator<<(std::ostream& o, Timer::Time const &t) {
+ double tm = t.value;
+ unsigned prefix = 0;
+ char prefixes[] = "num kMGT";
+ while(prefix < sizeof(prefixes) and tm > 1000) {
+ tm /= 1000.0;
+ prefix += 1;
+ }
+ o << tm << prefixes[prefix] << "s";
+ return o;
+}
+
+
+
+#endif // _2GEOM_TOY_FRAMEWORK2_H_
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+ */
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/makefile.in b/src/3rdparty/2geom/makefile.in
new file mode 100644
index 0000000..8c80244
--- /dev/null
+++ b/src/3rdparty/2geom/makefile.in
@@ -0,0 +1,17 @@
+# Convenience stub makefile to call the real Makefile.
+
+@SET_MAKE@
+
+# Explicit so that it's the default rule.
+all:
+ cd .. && $(MAKE) libnr/all
+
+clean %.a %.o:
+ cd .. && $(MAKE) libnr/$@
+
+.PHONY: all clean
+
+OBJEXT = @OBJEXT@
+
+.SUFFIXES:
+.SUFFIXES: .a .$(OBJEXT)
diff --git a/src/3rdparty/2geom/mingwenv.bat b/src/3rdparty/2geom/mingwenv.bat
new file mode 100644
index 0000000..6ef6d2a
--- /dev/null
+++ b/src/3rdparty/2geom/mingwenv.bat
@@ -0,0 +1,18 @@
+@echo Setting environment variables for MinGW build of lib2geom
+IF "%DEVLIBS_PATH%"=="" set DEVLIBS_PATH=c:\devlibs
+IF "%MINGW_PATH%"=="" set MINGW_PATH=C:\mingw
+
+
+set RAGEL_BIN=c:\ragel
+set GS_BIN=C:\latex\gs\gs9.15\bin
+set PYTHON_PATH=C:\Python27
+set GRAPHVIZ_BIN="C:\Program Files (x86)\Graphviz2.38\bin"
+set GS_BIN=C:\latex\gs\gs8.61\bin
+
+set MINGW_BIN=%MINGW_PATH%\bin
+set PKG_CONFIG_PATH=%DEVLIBS_PATH%\lib\pkgconfig
+set CMAKE_PREFIX_PATH=%DEVLIBS_PATH%
+set GTKMM_BASEPATH=%DEVLIBS_PATH%
+set PKG_CONFIG_PATH=%DEVLIBS_PATH%\lib\pkgconfig
+set PATH=%MINGW_BIN%;%RAGEL_BIN%;%PATH%;%GS_BIN%;%GRAPHVIZ_BIN%;%PYTHON_PATH%;%DEVLIBS_PATH%\bin
+set BOOST_DIR=%DEVLIBS_PATH%\include
diff --git a/src/3rdparty/2geom/src/2geom/CMakeLists.txt b/src/3rdparty/2geom/src/2geom/CMakeLists.txt
new file mode 100755
index 0000000..80b9e8e
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/CMakeLists.txt
@@ -0,0 +1,206 @@
+# (re-)generate parser file with ragel if it's available
+SET(SVG_PARSER_CPP "svg-path-parser.cpp")
+SET(SVG_PARSER_RL "svg-path-parser.rl")
+find_program(RAGEL_PROGRAM
+ NAMES ragel
+ HINTS /usr/bin
+ /usr/local/bin
+)
+if(RAGEL_PROGRAM)
+ message(STATUS "Found Ragel in ${RAGEL_PROGRAM}. ${SVG_PARSER_CPP} will be recreated from ${SVG_PARSER_RL}.")
+ add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/${SVG_PARSER_CPP}"
+ COMMAND ${RAGEL_PROGRAM} -o "${SVG_PARSER_CPP}" "${SVG_PARSER_RL}"
+ DEPENDS "${SVG_PARSER_RL}"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ COMMENT "Generating ${SVG_PARSER_CPP} with ragel")
+else()
+ message(STATUS "Ragel NOT found. Using stale ${SVG_PARSER_CPP}.")
+endif()
+
+
+add_library(2geom ${LIB_TYPE}
+ # sources
+ affine.cpp
+
+ basic-intersection.cpp
+ bezier.cpp
+ bezier-clipping.cpp
+ bezier-curve.cpp
+ bezier-utils.cpp
+
+ cairo-path-sink.cpp
+ circle.cpp
+ concepts.cpp
+ conicsec.cpp
+ conic_section_clipper_impl.cpp
+ convex-hull.cpp
+ coord.cpp
+ crossing.cpp
+ curve.cpp
+
+ d2-sbasis.cpp
+
+ ellipse.cpp
+ elliptical-arc.cpp
+ elliptical-arc-from-sbasis.cpp
+
+ geom.cpp
+
+ intersection-graph.cpp
+
+ line.cpp
+
+ nearest-time.cpp
+
+ numeric/matrix.cpp
+
+ parallelogram.cpp
+ parting-point.cpp
+ path-extrema.cpp
+ path-intersection.cpp
+ path-sink.cpp
+ path.cpp
+ pathvector.cpp
+ piecewise.cpp
+ point.cpp
+ polynomial.cpp
+
+ rect.cpp
+ recursive-bezier-intersection.cpp
+
+ sbasis-2d.cpp
+ sbasis-geometric.cpp
+ sbasis-math.cpp
+ sbasis-poly.cpp
+ sbasis-roots.cpp
+ sbasis-to-bezier.cpp
+ sbasis.cpp
+ self-intersect.cpp
+ solve-bezier.cpp
+ solve-bezier-one-d.cpp
+ solve-bezier-parametric.cpp
+ svg-path-parser.cpp
+ svg-path-writer.cpp
+ sweep-bounds.cpp
+
+ transforms.cpp
+
+ utils.cpp
+
+ # headers (for IDE support only)
+ # private:
+ planar-graph.h
+
+ # public:
+ ${2GEOM_INCLUDE_DIR}/2geom/affine.h
+ ${2GEOM_INCLUDE_DIR}/2geom/angle.h
+
+ ${2GEOM_INCLUDE_DIR}/2geom/basic-intersection.h
+ ${2GEOM_INCLUDE_DIR}/2geom/bezier.h
+ ${2GEOM_INCLUDE_DIR}/2geom/bezier-curve.h
+ ${2GEOM_INCLUDE_DIR}/2geom/bezier-to-sbasis.h
+ ${2GEOM_INCLUDE_DIR}/2geom/bezier-utils.h
+
+ ${2GEOM_INCLUDE_DIR}/2geom/cairo-path-sink.h
+ ${2GEOM_INCLUDE_DIR}/2geom/choose.h
+ ${2GEOM_INCLUDE_DIR}/2geom/circle.h
+ ${2GEOM_INCLUDE_DIR}/2geom/concepts.h
+ ${2GEOM_INCLUDE_DIR}/2geom/conicsec.h
+ ${2GEOM_INCLUDE_DIR}/2geom/conic_section_clipper.h
+ ${2GEOM_INCLUDE_DIR}/2geom/conic_section_clipper_cr.h
+ ${2GEOM_INCLUDE_DIR}/2geom/conic_section_clipper_impl.h
+ ${2GEOM_INCLUDE_DIR}/2geom/convex-hull.h
+ ${2GEOM_INCLUDE_DIR}/2geom/coord.h
+ ${2GEOM_INCLUDE_DIR}/2geom/crossing.h
+ ${2GEOM_INCLUDE_DIR}/2geom/curve.h
+ ${2GEOM_INCLUDE_DIR}/2geom/curves.h
+
+ ${2GEOM_INCLUDE_DIR}/2geom/d2.h
+
+ ${2GEOM_INCLUDE_DIR}/2geom/ellipse.h
+ ${2GEOM_INCLUDE_DIR}/2geom/elliptical-arc.h
+ ${2GEOM_INCLUDE_DIR}/2geom/exception.h
+
+ ${2GEOM_INCLUDE_DIR}/2geom/forward.h
+
+ ${2GEOM_INCLUDE_DIR}/2geom/geom.h
+
+ ${2GEOM_INCLUDE_DIR}/2geom/intersection.h
+ ${2GEOM_INCLUDE_DIR}/2geom/intersection-graph.h
+
+ ${2GEOM_INCLUDE_DIR}/2geom/line.h
+ ${2GEOM_INCLUDE_DIR}/2geom/linear.h
+
+ ${2GEOM_INCLUDE_DIR}/2geom/math-utils.h
+
+ ${2GEOM_INCLUDE_DIR}/2geom/nearest-time.h
+
+ ${2GEOM_INCLUDE_DIR}/2geom/ord.h
+
+ ${2GEOM_INCLUDE_DIR}/2geom/parallelogram.h
+ ${2GEOM_INCLUDE_DIR}/2geom/path-intersection.h
+ ${2GEOM_INCLUDE_DIR}/2geom/path-sink.h
+ ${2GEOM_INCLUDE_DIR}/2geom/path.h
+ ${2GEOM_INCLUDE_DIR}/2geom/pathvector.h
+ ${2GEOM_INCLUDE_DIR}/2geom/piecewise.h
+ ${2GEOM_INCLUDE_DIR}/2geom/point.h
+ ${2GEOM_INCLUDE_DIR}/2geom/polynomial.h
+
+ ${2GEOM_INCLUDE_DIR}/2geom/ray.h
+ ${2GEOM_INCLUDE_DIR}/2geom/rect.h
+
+ ${2GEOM_INCLUDE_DIR}/2geom/sbasis-2d.h
+ ${2GEOM_INCLUDE_DIR}/2geom/sbasis-curve.h
+ ${2GEOM_INCLUDE_DIR}/2geom/sbasis-geometric.h
+ ${2GEOM_INCLUDE_DIR}/2geom/sbasis-math.h
+ ${2GEOM_INCLUDE_DIR}/2geom/sbasis-poly.h
+ ${2GEOM_INCLUDE_DIR}/2geom/sbasis-to-bezier.h
+ ${2GEOM_INCLUDE_DIR}/2geom/sbasis.h
+ ${2GEOM_INCLUDE_DIR}/2geom/solver.h
+ ${2GEOM_INCLUDE_DIR}/2geom/svg-path-parser.h
+ ${2GEOM_INCLUDE_DIR}/2geom/svg-path-writer.h
+ ${2GEOM_INCLUDE_DIR}/2geom/sweeper.h
+ ${2GEOM_INCLUDE_DIR}/2geom/sweep-bounds.h
+
+ ${2GEOM_INCLUDE_DIR}/2geom/transforms.h
+
+ ${2GEOM_INCLUDE_DIR}/2geom/utils.h
+)
+
+# make lib for 2geom
+target_include_directories(2geom
+ PUBLIC
+ ${GLIB_INCLUDE_DIRS}
+ ${GSL_INCLUDE_DIRS}
+ ${CAIRO_INCLUDE_DIRS}
+ ${DoubleConversion_INCLUDE_DIRS}
+ $<BUILD_INTERFACE:${2GEOM_INCLUDE_DIR}>
+ $<BUILD_INTERFACE:${2GEOM_INCLUDE_DIR}/2geom>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/2geom-${2GEOM_VERSION}>
+ )
+
+target_link_libraries(2geom
+ PUBLIC
+ ${GLIB_LIBRARIES}
+ ${GSL_LIBRARIES}
+ ${CAIRO_LIBRARIES}
+ ${DoubleConversion_LIBRARIES}
+ )
+
+set_target_properties(2geom PROPERTIES SOVERSION "${2GEOM_ABI_VERSION}")
+
+install(TARGETS 2geom
+ EXPORT 2geom_targets
+ RUNTIME
+ DESTINATION ${CMAKE_INSTALL_BINDIR}
+ COMPONENT "lib2geom${2GEOM_VERSION}"
+ LIBRARY
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ COMPONENT "lib2geom${2GEOM_VERSION}"
+ NAMELINK_COMPONENT "lib2geom_dev"
+ ARCHIVE
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ COMPONENT "lib2geom${2GEOM_VERSION}"
+)
+
+add_library(2Geom::2geom ALIAS 2geom)
diff --git a/src/3rdparty/2geom/src/2geom/affine.cpp b/src/3rdparty/2geom/src/2geom/affine.cpp
new file mode 100644
index 0000000..48179e8
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/affine.cpp
@@ -0,0 +1,522 @@
+/*
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Michael G. Sloan <mgsloan@gmail.com>
+ *
+ * This code is in public domain
+ */
+
+#include <2geom/affine.h>
+#include <2geom/point.h>
+#include <2geom/polynomial.h>
+#include <2geom/utils.h>
+
+namespace Geom {
+
+/** Creates a Affine given an axis and origin point.
+ * The axis is represented as two vectors, which represent skew, rotation, and scaling in two dimensions.
+ * from_basis(Point(1, 0), Point(0, 1), Point(0, 0)) would return the identity matrix.
+
+ \param x_basis the vector for the x-axis.
+ \param y_basis the vector for the y-axis.
+ \param offset the translation applied by the matrix.
+ \return The new Affine.
+ */
+//NOTE: Inkscape's version is broken, so when including this version, you'll have to search for code with this func
+Affine from_basis(Point const &x_basis, Point const &y_basis, Point const &offset) {
+ return Affine(x_basis[X], x_basis[Y],
+ y_basis[X], y_basis[Y],
+ offset [X], offset [Y]);
+}
+
+Point Affine::xAxis() const {
+ return Point(_c[0], _c[1]);
+}
+
+Point Affine::yAxis() const {
+ return Point(_c[2], _c[3]);
+}
+
+/// Gets the translation imparted by the Affine.
+Point Affine::translation() const {
+ return Point(_c[4], _c[5]);
+}
+
+void Affine::setXAxis(Point const &vec) {
+ for(int i = 0; i < 2; i++)
+ _c[i] = vec[i];
+}
+
+void Affine::setYAxis(Point const &vec) {
+ for(int i = 0; i < 2; i++)
+ _c[i + 2] = vec[i];
+}
+
+/// Sets the translation imparted by the Affine.
+void Affine::setTranslation(Point const &loc) {
+ for(int i = 0; i < 2; i++)
+ _c[i + 4] = loc[i];
+}
+
+/** Calculates the amount of x-scaling imparted by the Affine. This is the scaling applied to
+ * the original x-axis region. It is \emph{not} the overall x-scaling of the transformation.
+ * Equivalent to L2(m.xAxis()). */
+double Affine::expansionX() const {
+ return sqrt(_c[0] * _c[0] + _c[1] * _c[1]);
+}
+
+/** Calculates the amount of y-scaling imparted by the Affine. This is the scaling applied before
+ * the other transformations. It is \emph{not} the overall y-scaling of the transformation.
+ * Equivalent to L2(m.yAxis()). */
+double Affine::expansionY() const {
+ return sqrt(_c[2] * _c[2] + _c[3] * _c[3]);
+}
+
+void Affine::setExpansionX(double val) {
+ double exp_x = expansionX();
+ if (exp_x != 0.0) { //TODO: best way to deal with it is to skip op?
+ double coef = val / expansionX();
+ for (unsigned i = 0; i < 2; ++i) {
+ _c[i] *= coef;
+ }
+ }
+}
+
+void Affine::setExpansionY(double val) {
+ double exp_y = expansionY();
+ if (exp_y != 0.0) { //TODO: best way to deal with it is to skip op?
+ double coef = val / expansionY();
+ for (unsigned i = 2; i < 4; ++i) {
+ _c[i] *= coef;
+ }
+ }
+}
+
+/** Sets this matrix to be the Identity Affine. */
+void Affine::setIdentity() {
+ _c[0] = 1.0; _c[1] = 0.0;
+ _c[2] = 0.0; _c[3] = 1.0;
+ _c[4] = 0.0; _c[5] = 0.0;
+}
+
+/** @brief Check whether this matrix is an identity matrix.
+ * @param eps Numerical tolerance
+ * @return True iff the matrix is of the form
+ * \f$\left[\begin{array}{ccc}
+ 1 & 0 & 0 \\
+ 0 & 1 & 0 \\
+ 0 & 0 & 1 \end{array}\right]\f$ */
+bool Affine::isIdentity(Coord eps) const {
+ return are_near(_c[0], 1.0, eps) && are_near(_c[1], 0.0, eps) &&
+ are_near(_c[2], 0.0, eps) && are_near(_c[3], 1.0, eps) &&
+ are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps);
+}
+
+/** @brief Check whether this matrix represents a pure translation.
+ * Will return true for the identity matrix, which represents a zero translation.
+ * @param eps Numerical tolerance
+ * @return True iff the matrix is of the form
+ * \f$\left[\begin{array}{ccc}
+ 1 & 0 & 0 \\
+ 0 & 1 & 0 \\
+ a & b & 1 \end{array}\right]\f$ */
+bool Affine::isTranslation(Coord eps) const {
+ return are_near(_c[0], 1.0, eps) && are_near(_c[1], 0.0, eps) &&
+ are_near(_c[2], 0.0, eps) && are_near(_c[3], 1.0, eps);
+}
+/** @brief Check whether this matrix represents a pure nonzero translation.
+ * @param eps Numerical tolerance
+ * @return True iff the matrix is of the form
+ * \f$\left[\begin{array}{ccc}
+ 1 & 0 & 0 \\
+ 0 & 1 & 0 \\
+ a & b & 1 \end{array}\right]\f$ and \f$a, b \neq 0\f$ */
+bool Affine::isNonzeroTranslation(Coord eps) const {
+ return are_near(_c[0], 1.0, eps) && are_near(_c[1], 0.0, eps) &&
+ are_near(_c[2], 0.0, eps) && are_near(_c[3], 1.0, eps) &&
+ (!are_near(_c[4], 0.0, eps) || !are_near(_c[5], 0.0, eps));
+}
+
+/** @brief Check whether this matrix represents pure scaling.
+ * @param eps Numerical tolerance
+ * @return True iff the matrix is of the form
+ * \f$\left[\begin{array}{ccc}
+ a & 0 & 0 \\
+ 0 & b & 0 \\
+ 0 & 0 & 1 \end{array}\right]\f$. */
+bool Affine::isScale(Coord eps) const {
+ if (isSingular(eps)) return false;
+ return are_near(_c[1], 0.0, eps) && are_near(_c[2], 0.0, eps) &&
+ are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps);
+}
+
+/** @brief Check whether this matrix represents pure, nonzero scaling.
+ * @param eps Numerical tolerance
+ * @return True iff the matrix is of the form
+ * \f$\left[\begin{array}{ccc}
+ a & 0 & 0 \\
+ 0 & b & 0 \\
+ 0 & 0 & 1 \end{array}\right]\f$ and \f$a, b \neq 1\f$. */
+bool Affine::isNonzeroScale(Coord eps) const {
+ if (isSingular(eps)) return false;
+ return (!are_near(_c[0], 1.0, eps) || !are_near(_c[3], 1.0, eps)) && //NOTE: these are the diags, and the next line opposite diags
+ are_near(_c[1], 0.0, eps) && are_near(_c[2], 0.0, eps) &&
+ are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps);
+}
+
+/** @brief Check whether this matrix represents pure uniform scaling.
+ * @param eps Numerical tolerance
+ * @return True iff the matrix is of the form
+ * \f$\left[\begin{array}{ccc}
+ a_1 & 0 & 0 \\
+ 0 & a_2 & 0 \\
+ 0 & 0 & 1 \end{array}\right]\f$ where \f$|a_1| = |a_2|\f$. */
+bool Affine::isUniformScale(Coord eps) const {
+ if (isSingular(eps)) return false;
+ return are_near(fabs(_c[0]), fabs(_c[3]), eps) &&
+ are_near(_c[1], 0.0, eps) && are_near(_c[2], 0.0, eps) &&
+ are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps);
+}
+
+/** @brief Check whether this matrix represents pure, nonzero uniform scaling.
+ * @param eps Numerical tolerance
+ * @return True iff the matrix is of the form
+ * \f$\left[\begin{array}{ccc}
+ a_1 & 0 & 0 \\
+ 0 & a_2 & 0 \\
+ 0 & 0 & 1 \end{array}\right]\f$ where \f$|a_1| = |a_2|\f$
+ * and \f$a_1, a_2 \neq 1\f$. */
+bool Affine::isNonzeroUniformScale(Coord eps) const {
+ if (isSingular(eps)) return false;
+ // we need to test both c0 and c3 to handle the case of flips,
+ // which should be treated as nonzero uniform scales
+ return !(are_near(_c[0], 1.0, eps) && are_near(_c[3], 1.0, eps)) &&
+ are_near(fabs(_c[0]), fabs(_c[3]), eps) &&
+ are_near(_c[1], 0.0, eps) && are_near(_c[2], 0.0, eps) &&
+ are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps);
+}
+
+/** @brief Check whether this matrix represents a pure rotation.
+ * @param eps Numerical tolerance
+ * @return True iff the matrix is of the form
+ * \f$\left[\begin{array}{ccc}
+ a & b & 0 \\
+ -b & a & 0 \\
+ 0 & 0 & 1 \end{array}\right]\f$ and \f$a^2 + b^2 = 1\f$. */
+bool Affine::isRotation(Coord eps) const {
+ return are_near(_c[0], _c[3], eps) && are_near(_c[1], -_c[2], eps) &&
+ are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps) &&
+ are_near(_c[0]*_c[0] + _c[1]*_c[1], 1.0, eps);
+}
+
+/** @brief Check whether this matrix represents a pure, nonzero rotation.
+ * @param eps Numerical tolerance
+ * @return True iff the matrix is of the form
+ * \f$\left[\begin{array}{ccc}
+ a & b & 0 \\
+ -b & a & 0 \\
+ 0 & 0 & 1 \end{array}\right]\f$, \f$a^2 + b^2 = 1\f$ and \f$a \neq 1\f$. */
+bool Affine::isNonzeroRotation(Coord eps) const {
+ return !are_near(_c[0], 1.0, eps) &&
+ are_near(_c[0], _c[3], eps) && are_near(_c[1], -_c[2], eps) &&
+ are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps) &&
+ are_near(_c[0]*_c[0] + _c[1]*_c[1], 1.0, eps);
+}
+
+/** @brief Check whether this matrix represents a non-zero rotation about any point.
+ * @param eps Numerical tolerance
+ * @return True iff the matrix is of the form
+ * \f$\left[\begin{array}{ccc}
+ a & b & 0 \\
+ -b & a & 0 \\
+ c & d & 1 \end{array}\right]\f$, \f$a^2 + b^2 = 1\f$ and \f$a \neq 1\f$. */
+bool Affine::isNonzeroNonpureRotation(Coord eps) const {
+ return !are_near(_c[0], 1.0, eps) &&
+ are_near(_c[0], _c[3], eps) && are_near(_c[1], -_c[2], eps) &&
+ are_near(_c[0]*_c[0] + _c[1]*_c[1], 1.0, eps);
+}
+
+/** @brief For a (possibly non-pure) non-zero-rotation matrix, calculate the rotation center.
+ * @pre The matrix must be a non-zero-rotation matrix to prevent division by zero, see isNonzeroNonpureRotation().
+ * @return The rotation center x, the solution to the equation
+ * \f$A x = x\f$. */
+Point Affine::rotationCenter() const {
+ Coord x = (_c[2]*_c[5]+_c[4]-_c[4]*_c[3]) / (1-_c[3]-_c[0]+_c[0]*_c[3]-_c[2]*_c[1]);
+ Coord y = (_c[1]*x + _c[5]) / (1 - _c[3]);
+ return Point(x,y);
+};
+
+/** @brief Check whether this matrix represents pure horizontal shearing.
+ * @param eps Numerical tolerance
+ * @return True iff the matrix is of the form
+ * \f$\left[\begin{array}{ccc}
+ 1 & 0 & 0 \\
+ k & 1 & 0 \\
+ 0 & 0 & 1 \end{array}\right]\f$. */
+bool Affine::isHShear(Coord eps) const {
+ return are_near(_c[0], 1.0, eps) && are_near(_c[1], 0.0, eps) &&
+ are_near(_c[3], 1.0, eps) && are_near(_c[4], 0.0, eps) &&
+ are_near(_c[5], 0.0, eps);
+}
+/** @brief Check whether this matrix represents pure, nonzero horizontal shearing.
+ * @param eps Numerical tolerance
+ * @return True iff the matrix is of the form
+ * \f$\left[\begin{array}{ccc}
+ 1 & 0 & 0 \\
+ k & 1 & 0 \\
+ 0 & 0 & 1 \end{array}\right]\f$ and \f$k \neq 0\f$. */
+bool Affine::isNonzeroHShear(Coord eps) const {
+ return are_near(_c[0], 1.0, eps) && are_near(_c[1], 0.0, eps) &&
+ !are_near(_c[2], 0.0, eps) && are_near(_c[3], 1.0, eps) &&
+ are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps);
+}
+
+/** @brief Check whether this matrix represents pure vertical shearing.
+ * @param eps Numerical tolerance
+ * @return True iff the matrix is of the form
+ * \f$\left[\begin{array}{ccc}
+ 1 & k & 0 \\
+ 0 & 1 & 0 \\
+ 0 & 0 & 1 \end{array}\right]\f$. */
+bool Affine::isVShear(Coord eps) const {
+ return are_near(_c[0], 1.0, eps) && are_near(_c[2], 0.0, eps) &&
+ are_near(_c[3], 1.0, eps) && are_near(_c[4], 0.0, eps) &&
+ are_near(_c[5], 0.0, eps);
+}
+
+/** @brief Check whether this matrix represents pure, nonzero vertical shearing.
+ * @param eps Numerical tolerance
+ * @return True iff the matrix is of the form
+ * \f$\left[\begin{array}{ccc}
+ 1 & k & 0 \\
+ 0 & 1 & 0 \\
+ 0 & 0 & 1 \end{array}\right]\f$ and \f$k \neq 0\f$. */
+bool Affine::isNonzeroVShear(Coord eps) const {
+ return are_near(_c[0], 1.0, eps) && !are_near(_c[1], 0.0, eps) &&
+ are_near(_c[2], 0.0, eps) && are_near(_c[3], 1.0, eps) &&
+ are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps);
+}
+
+/** @brief Check whether this matrix represents zooming.
+ * Zooming is any combination of translation and uniform non-flipping scaling.
+ * It preserves angles, ratios of distances between arbitrary points
+ * and unit vectors of line segments.
+ * @param eps Numerical tolerance
+ * @return True iff the matrix is invertible and of the form
+ * \f$\left[\begin{array}{ccc}
+ a & 0 & 0 \\
+ 0 & a & 0 \\
+ b & c & 1 \end{array}\right]\f$. */
+bool Affine::isZoom(Coord eps) const {
+ if (isSingular(eps)) return false;
+ return are_near(_c[0], _c[3], eps) && are_near(_c[1], 0, eps) && are_near(_c[2], 0, eps);
+}
+
+/** @brief Check whether the transformation preserves areas of polygons.
+ * This means that the transformation can be any combination of translation, rotation,
+ * shearing and squeezing (non-uniform scaling such that the absolute value of the product
+ * of Y-scale and X-scale is 1).
+ * @param eps Numerical tolerance
+ * @return True iff \f$|\det A| = 1\f$. */
+bool Affine::preservesArea(Coord eps) const
+{
+ return are_near(descrim2(), 1.0, eps);
+}
+
+/** @brief Check whether the transformation preserves angles between lines.
+ * This means that the transformation can be any combination of translation, uniform scaling,
+ * rotation and flipping.
+ * @param eps Numerical tolerance
+ * @return True iff the matrix is of the form
+ * \f$\left[\begin{array}{ccc}
+ a & b & 0 \\
+ -b & a & 0 \\
+ c & d & 1 \end{array}\right]\f$ or
+ \f$\left[\begin{array}{ccc}
+ -a & b & 0 \\
+ b & a & 0 \\
+ c & d & 1 \end{array}\right]\f$. */
+bool Affine::preservesAngles(Coord eps) const
+{
+ if (isSingular(eps)) return false;
+ return (are_near(_c[0], _c[3], eps) && are_near(_c[1], -_c[2], eps)) ||
+ (are_near(_c[0], -_c[3], eps) && are_near(_c[1], _c[2], eps));
+}
+
+/** @brief Check whether the transformation preserves distances between points.
+ * This means that the transformation can be any combination of translation,
+ * rotation and flipping.
+ * @param eps Numerical tolerance
+ * @return True iff the matrix is of the form
+ * \f$\left[\begin{array}{ccc}
+ a & b & 0 \\
+ -b & a & 0 \\
+ c & d & 1 \end{array}\right]\f$ or
+ \f$\left[\begin{array}{ccc}
+ -a & b & 0 \\
+ b & a & 0 \\
+ c & d & 1 \end{array}\right]\f$ and \f$a^2 + b^2 = 1\f$. */
+bool Affine::preservesDistances(Coord eps) const
+{
+ return ((are_near(_c[0], _c[3], eps) && are_near(_c[1], -_c[2], eps)) ||
+ (are_near(_c[0], -_c[3], eps) && are_near(_c[1], _c[2], eps))) &&
+ are_near(_c[0] * _c[0] + _c[1] * _c[1], 1.0, eps);
+}
+
+/** @brief Check whether this transformation flips objects.
+ * A transformation flips objects if it has a negative scaling component. */
+bool Affine::flips() const {
+ return det() < 0;
+}
+
+/** @brief Check whether this matrix is singular.
+ * Singular matrices have no inverse, which means that applying them to a set of points
+ * results in a loss of information.
+ * @param eps Numerical tolerance
+ * @return True iff the determinant is near zero. */
+bool Affine::isSingular(Coord eps) const {
+ return are_near(det(), 0.0, eps);
+}
+
+/** @brief Compute the inverse matrix.
+ * Inverse is a matrix (denoted \f$A^{-1}\f$) such that \f$AA^{-1} = A^{-1}A = I\f$.
+ * Singular matrices have no inverse (for example a matrix that has two of its columns equal).
+ * For such matrices, the identity matrix will be returned instead.
+ * @param eps Numerical tolerance
+ * @return Inverse of the matrix, or the identity matrix if the inverse is undefined.
+ * @post (m * m.inverse()).isIdentity() == true */
+Affine Affine::inverse() const {
+ Affine d;
+
+ double mx = std::max(fabs(_c[0]) + fabs(_c[1]),
+ fabs(_c[2]) + fabs(_c[3])); // a random matrix norm (either l1 or linfty
+ if(mx > 0) {
+ Geom::Coord const determ = det();
+ if (!rel_error_bound(std::sqrt(fabs(determ)), mx)) {
+ Geom::Coord const ideterm = 1.0 / (determ);
+
+ d._c[0] = _c[3] * ideterm;
+ d._c[1] = -_c[1] * ideterm;
+ d._c[2] = -_c[2] * ideterm;
+ d._c[3] = _c[0] * ideterm;
+ d._c[4] = (-_c[4] * d._c[0] - _c[5] * d._c[2]);
+ d._c[5] = (-_c[4] * d._c[1] - _c[5] * d._c[3]);
+ } else {
+ d.setIdentity();
+ }
+ } else {
+ d.setIdentity();
+ }
+
+ return d;
+}
+
+/** @brief Calculate the determinant.
+ * @return \f$\det A\f$. */
+Coord Affine::det() const {
+ // TODO this can overflow
+ return _c[0] * _c[3] - _c[1] * _c[2];
+}
+
+/** @brief Calculate the square of the descriminant.
+ * This is simply the absolute value of the determinant.
+ * @return \f$|\det A|\f$. */
+Coord Affine::descrim2() const {
+ return fabs(det());
+}
+
+/** @brief Calculate the descriminant.
+ * If the matrix doesn't contain a shearing or non-uniform scaling component, this value says
+ * how will the length of any line segment change after applying this transformation
+ * to arbitrary objects on a plane. The new length will be
+ * @code line_seg.length() * m.descrim()) @endcode
+ * @return \f$\sqrt{|\det A|}\f$. */
+Coord Affine::descrim() const {
+ return sqrt(descrim2());
+}
+
+/** @brief Combine this transformation with another one.
+ * After this operation, the matrix will correspond to the transformation
+ * obtained by first applying the original version of this matrix, and then
+ * applying @a m. */
+Affine &Affine::operator*=(Affine const &o) {
+ Coord nc[6];
+ for(int a = 0; a < 5; a += 2) {
+ for(int b = 0; b < 2; b++) {
+ nc[a + b] = _c[a] * o._c[b] + _c[a + 1] * o._c[b + 2];
+ }
+ }
+ for(int a = 0; a < 6; ++a) {
+ _c[a] = nc[a];
+ }
+ _c[4] += o._c[4];
+ _c[5] += o._c[5];
+ return *this;
+}
+
+//TODO: What's this!?!
+/** Given a matrix m such that unit_circle = m*x, this returns the
+ * quadratic form x*A*x = 1.
+ * @relates Affine */
+Affine elliptic_quadratic_form(Affine const &m) {
+ double od = m[0] * m[1] + m[2] * m[3];
+ Affine ret (m[0]*m[0] + m[1]*m[1], od,
+ od, m[2]*m[2] + m[3]*m[3],
+ 0, 0);
+ return ret; // allow NRVO
+}
+
+Eigen::Eigen(Affine const &m) {
+ double const B = -m[0] - m[3];
+ double const C = m[0]*m[3] - m[1]*m[2];
+
+ std::vector<double> v = solve_quadratic(1, B, C);
+
+ for (unsigned i = 0; i < v.size(); ++i) {
+ values[i] = v[i];
+ vectors[i] = unit_vector(rot90(Point(m[0] - values[i], m[1])));
+ }
+ for (unsigned i = v.size(); i < 2; ++i) {
+ values[i] = 0;
+ vectors[i] = Point(0,0);
+ }
+}
+
+Eigen::Eigen(double m[2][2]) {
+ double const B = -m[0][0] - m[1][1];
+ double const C = m[0][0]*m[1][1] - m[1][0]*m[0][1];
+
+ std::vector<double> v = solve_quadratic(1, B, C);
+
+ for (unsigned i = 0; i < v.size(); ++i) {
+ values[i] = v[i];
+ vectors[i] = unit_vector(rot90(Point(m[0][0] - values[i], m[0][1])));
+ }
+ for (unsigned i = v.size(); i < 2; ++i) {
+ values[i] = 0;
+ vectors[i] = Point(0,0);
+ }
+}
+
+/** @brief Nearness predicate for affine transforms.
+ * @returns True if all entries of matrices are within eps of each other.
+ * @relates Affine */
+bool are_near(Affine const &a, Affine const &b, Coord eps)
+{
+ return are_near(a[0], b[0], eps) && are_near(a[1], b[1], eps) &&
+ are_near(a[2], b[2], eps) && are_near(a[3], b[3], eps) &&
+ are_near(a[4], b[4], eps) && are_near(a[5], b[5], eps);
+}
+
+} //namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/basic-intersection.cpp b/src/3rdparty/2geom/src/2geom/basic-intersection.cpp
new file mode 100644
index 0000000..61d7a6d
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/basic-intersection.cpp
@@ -0,0 +1,493 @@
+/** @file
+ * @brief Basic intersection routines
+ *//*
+ * Authors:
+ * Nathan Hurst <njh@njhurst.com>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Jean-François Barraud <jf.barraud@gmail.com>
+ *
+ * Copyright 2008-2009 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <2geom/basic-intersection.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/exception.h>
+
+#ifdef HAVE_GSL
+#include <gsl/gsl_vector.h>
+#include <gsl/gsl_multiroots.h>
+#endif
+
+using std::vector;
+namespace Geom {
+
+//#ifdef USE_RECURSIVE_INTERSECTOR
+
+// void find_intersections(std::vector<std::pair<double, double> > &xs,
+// D2<SBasis> const & A,
+// D2<SBasis> const & B) {
+// vector<Point> BezA, BezB;
+// sbasis_to_bezier(BezA, A);
+// sbasis_to_bezier(BezB, B);
+
+// xs.clear();
+
+// find_intersections_bezier_recursive(xs, BezA, BezB);
+// }
+// void find_intersections(std::vector< std::pair<double, double> > & xs,
+// std::vector<Point> const& A,
+// std::vector<Point> const& B,
+// double precision){
+// find_intersections_bezier_recursive(xs, A, B, precision);
+// }
+
+//#else
+
+namespace detail{ namespace bezier_clipping {
+void portion(std::vector<Point> &B, Interval const &I);
+void derivative(std::vector<Point> &D, std::vector<Point> const &B);
+}; };
+
+void find_intersections(std::vector<std::pair<double, double> > &xs,
+ D2<Bezier> const & A,
+ D2<Bezier> const & B,
+ double precision)
+{
+ find_intersections_bezier_clipping(xs, bezier_points(A), bezier_points(B), precision);
+}
+
+void find_intersections(std::vector<std::pair<double, double> > &xs,
+ D2<SBasis> const & A,
+ D2<SBasis> const & B,
+ double precision)
+{
+ vector<Point> BezA, BezB;
+ sbasis_to_bezier(BezA, A);
+ sbasis_to_bezier(BezB, B);
+
+ find_intersections_bezier_clipping(xs, BezA, BezB, precision);
+}
+
+void find_intersections(std::vector< std::pair<double, double> > & xs,
+ std::vector<Point> const& A,
+ std::vector<Point> const& B,
+ double precision)
+{
+ find_intersections_bezier_clipping(xs, A, B, precision);
+}
+
+//#endif
+
+/*
+ * split the curve at the midpoint, returning an array with the two parts
+ * Temporary storage is minimized by using part of the storage for the result
+ * to hold an intermediate value until it is no longer needed.
+ */
+// TODO replace with Bezier method
+void split(vector<Point> const &p, double t,
+ vector<Point> &left, vector<Point> &right) {
+ const unsigned sz = p.size();
+ //Geom::Point Vtemp[sz][sz];
+ vector<vector<Point> > Vtemp(sz);
+ for ( size_t i = 0; i < sz; ++i )
+ Vtemp[i].reserve(sz);
+
+ /* Copy control points */
+ std::copy(p.begin(), p.end(), Vtemp[0].begin());
+
+ /* Triangle computation */
+ for (unsigned i = 1; i < sz; i++) {
+ for (unsigned j = 0; j < sz - i; j++) {
+ Vtemp[i][j] = lerp(t, Vtemp[i-1][j], Vtemp[i-1][j+1]);
+ }
+ }
+
+ left.resize(sz);
+ right.resize(sz);
+ for (unsigned j = 0; j < sz; j++)
+ left[j] = Vtemp[j][0];
+ for (unsigned j = 0; j < sz; j++)
+ right[j] = Vtemp[sz-1-j][j];
+}
+
+
+
+void find_self_intersections(std::vector<std::pair<double, double> > &xs,
+ D2<Bezier> const &A,
+ double precision)
+{
+ std::vector<double> dr = derivative(A[X]).roots();
+ {
+ std::vector<double> dyr = derivative(A[Y]).roots();
+ dr.insert(dr.begin(), dyr.begin(), dyr.end());
+ }
+ dr.push_back(0);
+ dr.push_back(1);
+ // We want to be sure that we have no empty segments
+ std::sort(dr.begin(), dr.end());
+ std::vector<double>::iterator new_end = std::unique(dr.begin(), dr.end());
+ dr.resize( new_end - dr.begin() );
+
+ std::vector< D2<Bezier> > pieces;
+ for (unsigned i = 0; i < dr.size() - 1; ++i) {
+ pieces.push_back(portion(A, dr[i], dr[i+1]));
+ }
+ /*{
+ vector<Point> l, r, in = A;
+ for(unsigned i = 0; i < dr.size()-1; i++) {
+ split(in, (dr[i+1]-dr[i]) / (1 - dr[i]), l, r);
+ pieces.push_back(l);
+ in = r;
+ }
+ }*/
+
+ for(unsigned i = 0; i < dr.size()-1; i++) {
+ for(unsigned j = i+1; j < dr.size()-1; j++) {
+ std::vector<std::pair<double, double> > section;
+
+ find_intersections(section, pieces[i], pieces[j], precision);
+ for(auto & k : section) {
+ double l = k.first;
+ double r = k.second;
+// XXX: This condition will prune out false positives, but it might create some false negatives. Todo: Confirm it is correct.
+ if(j == i+1)
+ //if((l == 1) && (r == 0))
+ if( ( l > precision ) && (r < precision) )//FIXME: what precision should be used here???
+ continue;
+ xs.emplace_back((1-l)*dr[i] + l*dr[i+1],
+ (1-r)*dr[j] + r*dr[j+1]);
+ }
+ }
+ }
+
+ // Because i is in order, xs should be roughly already in order?
+ //sort(xs.begin(), xs.end());
+ //unique(xs.begin(), xs.end());
+}
+
+void find_self_intersections(std::vector<std::pair<double, double> > &xs,
+ D2<SBasis> const &A,
+ double precision)
+{
+ D2<Bezier> in;
+ sbasis_to_bezier(in, A);
+ find_self_intersections(xs, in, precision);
+}
+
+
+void subdivide(D2<Bezier> const &a,
+ D2<Bezier> const &b,
+ std::vector< std::pair<double, double> > const &xs,
+ std::vector< D2<Bezier> > &av,
+ std::vector< D2<Bezier> > &bv)
+{
+ if (xs.empty()) {
+ av.push_back(a);
+ bv.push_back(b);
+ return;
+ }
+
+ std::pair<double, double> prev = std::make_pair(0., 0.);
+ for (const auto & x : xs) {
+ av.push_back(portion(a, prev.first, x.first));
+ bv.push_back(portion(b, prev.second, x.second));
+ av.back()[X].at0() = bv.back()[X].at0() = lerp(0.5, av.back()[X].at0(), bv.back()[X].at0());
+ av.back()[X].at1() = bv.back()[X].at1() = lerp(0.5, av.back()[X].at1(), bv.back()[X].at1());
+ av.back()[Y].at0() = bv.back()[Y].at0() = lerp(0.5, av.back()[Y].at0(), bv.back()[Y].at0());
+ av.back()[Y].at1() = bv.back()[Y].at1() = lerp(0.5, av.back()[Y].at1(), bv.back()[Y].at1());
+ prev = x;
+ }
+ av.push_back(portion(a, prev.first, 1));
+ bv.push_back(portion(b, prev.second, 1));
+ av.back()[X].at0() = bv.back()[X].at0() = lerp(0.5, av.back()[X].at0(), bv.back()[X].at0());
+ av.back()[X].at1() = bv.back()[X].at1() = lerp(0.5, av.back()[X].at1(), bv.back()[X].at1());
+ av.back()[Y].at0() = bv.back()[Y].at0() = lerp(0.5, av.back()[Y].at0(), bv.back()[Y].at0());
+ av.back()[Y].at1() = bv.back()[Y].at1() = lerp(0.5, av.back()[Y].at1(), bv.back()[Y].at1());
+}
+
+#ifdef HAVE_GSL
+#include <gsl/gsl_multiroots.h>
+
+struct rparams
+{
+ D2<SBasis> const &A;
+ D2<SBasis> const &B;
+};
+
+static int
+intersect_polish_f (const gsl_vector * x, void *params,
+ gsl_vector * f)
+{
+ const double x0 = gsl_vector_get (x, 0);
+ const double x1 = gsl_vector_get (x, 1);
+
+ Geom::Point dx = ((struct rparams *) params)->A(x0) -
+ ((struct rparams *) params)->B(x1);
+
+ gsl_vector_set (f, 0, dx[0]);
+ gsl_vector_set (f, 1, dx[1]);
+
+ return GSL_SUCCESS;
+}
+#endif
+
+union dbl_64{
+ long long i64;
+ double d64;
+};
+
+static double EpsilonBy(double value, int eps)
+{
+ dbl_64 s;
+ s.d64 = value;
+ s.i64 += eps;
+ return s.d64;
+}
+
+
+static void intersect_polish_root (D2<SBasis> const &A, double &s,
+ D2<SBasis> const &B, double &t) {
+#ifdef HAVE_GSL
+ const gsl_multiroot_fsolver_type *T;
+ gsl_multiroot_fsolver *sol;
+
+ int status;
+ size_t iter = 0;
+#endif
+ std::vector<Point> as, bs;
+ as = A.valueAndDerivatives(s, 2);
+ bs = B.valueAndDerivatives(t, 2);
+ Point F = as[0] - bs[0];
+ double best = dot(F, F);
+
+ for(int i = 0; i < 4; i++) {
+
+ /**
+ we want to solve
+ J*(x1 - x0) = f(x0)
+
+ |dA(s)[0] -dB(t)[0]| (X1 - X0) = A(s) - B(t)
+ |dA(s)[1] -dB(t)[1]|
+ **/
+
+ // We're using the standard transformation matricies, which is numerically rather poor. Much better to solve the equation using elimination.
+
+ Affine jack(as[1][0], as[1][1],
+ -bs[1][0], -bs[1][1],
+ 0, 0);
+ Point soln = (F)*jack.inverse();
+ double ns = s - soln[0];
+ double nt = t - soln[1];
+
+ as = A.valueAndDerivatives(ns, 2);
+ bs = B.valueAndDerivatives(nt, 2);
+ F = as[0] - bs[0];
+ double trial = dot(F, F);
+ if (trial > best*0.1) {// we have standards, you know
+ // At this point we could do a line search
+ break;
+ }
+ best = trial;
+ s = ns;
+ t = nt;
+ }
+
+#ifdef HAVE_GSL
+ const size_t n = 2;
+ struct rparams p = {A, B};
+ gsl_multiroot_function f = {&intersect_polish_f, n, &p};
+
+ double x_init[2] = {s, t};
+ gsl_vector *x = gsl_vector_alloc (n);
+
+ gsl_vector_set (x, 0, x_init[0]);
+ gsl_vector_set (x, 1, x_init[1]);
+
+ T = gsl_multiroot_fsolver_hybrids;
+ sol = gsl_multiroot_fsolver_alloc (T, 2);
+ gsl_multiroot_fsolver_set (sol, &f, x);
+
+ do
+ {
+ iter++;
+ status = gsl_multiroot_fsolver_iterate (sol);
+
+ if (status) /* check if solver is stuck */
+ break;
+
+ status =
+ gsl_multiroot_test_residual (sol->f, 1e-12);
+ }
+ while (status == GSL_CONTINUE && iter < 1000);
+
+ s = gsl_vector_get (sol->x, 0);
+ t = gsl_vector_get (sol->x, 1);
+
+ gsl_multiroot_fsolver_free (sol);
+ gsl_vector_free (x);
+#endif
+
+ {
+ // This code does a neighbourhood search for minor improvements.
+ double best_v = L1(A(s) - B(t));
+ //std::cout << "------\n" << best_v << std::endl;
+ Point best(s,t);
+ while (true) {
+ Point trial = best;
+ double trial_v = best_v;
+ for(int nsi = -1; nsi < 2; nsi++) {
+ for(int nti = -1; nti < 2; nti++) {
+ Point n(EpsilonBy(best[0], nsi),
+ EpsilonBy(best[1], nti));
+ double c = L1(A(n[0]) - B(n[1]));
+ //std::cout << c << "; ";
+ if (c < trial_v) {
+ trial = n;
+ trial_v = c;
+ }
+ }
+ }
+ if(trial == best) {
+ //std::cout << "\n" << s << " -> " << s - best[0] << std::endl;
+ //std::cout << t << " -> " << t - best[1] << std::endl;
+ //std::cout << best_v << std::endl;
+ s = best[0];
+ t = best[1];
+ return;
+ } else {
+ best = trial;
+ best_v = trial_v;
+ }
+ }
+ }
+}
+
+
+void polish_intersections(std::vector<std::pair<double, double> > &xs,
+ D2<SBasis> const &A, D2<SBasis> const &B)
+{
+ for(auto & x : xs)
+ intersect_polish_root(A, x.first,
+ B, x.second);
+}
+
+/**
+ * Compute the Hausdorf distance from A to B only.
+ */
+double hausdorfl(D2<SBasis>& A, D2<SBasis> const& B,
+ double m_precision,
+ double *a_t, double* b_t) {
+ std::vector< std::pair<double, double> > xs;
+ std::vector<Point> Az, Bz;
+ sbasis_to_bezier (Az, A);
+ sbasis_to_bezier (Bz, B);
+ find_collinear_normal(xs, Az, Bz, m_precision);
+ double h_dist = 0, h_a_t = 0, h_b_t = 0;
+ double dist = 0;
+ Point Ax = A.at0();
+ double t = Geom::nearest_time(Ax, B);
+ dist = Geom::distance(Ax, B(t));
+ if (dist > h_dist) {
+ h_a_t = 0;
+ h_b_t = t;
+ h_dist = dist;
+ }
+ Ax = A.at1();
+ t = Geom::nearest_time(Ax, B);
+ dist = Geom::distance(Ax, B(t));
+ if (dist > h_dist) {
+ h_a_t = 1;
+ h_b_t = t;
+ h_dist = dist;
+ }
+ for (auto & x : xs)
+ {
+ Point At = A(x.first);
+ Point Bu = B(x.second);
+ double distAtBu = Geom::distance(At, Bu);
+ t = Geom::nearest_time(At, B);
+ dist = Geom::distance(At, B(t));
+ //FIXME: we might miss it due to floating point precision...
+ if (dist >= distAtBu-.1 && distAtBu > h_dist) {
+ h_a_t = x.first;
+ h_b_t = x.second;
+ h_dist = distAtBu;
+ }
+
+ }
+ if(a_t) *a_t = h_a_t;
+ if(b_t) *b_t = h_b_t;
+
+ return h_dist;
+}
+
+/**
+ * Compute the symmetric Hausdorf distance.
+ */
+double hausdorf(D2<SBasis>& A, D2<SBasis> const& B,
+ double m_precision,
+ double *a_t, double* b_t) {
+ double h_dist = hausdorfl(A, B, m_precision, a_t, b_t);
+
+ double dist = 0;
+ Point Bx = B.at0();
+ double t = Geom::nearest_time(Bx, A);
+ dist = Geom::distance(Bx, A(t));
+ if (dist > h_dist) {
+ if(a_t) *a_t = t;
+ if(b_t) *b_t = 0;
+ h_dist = dist;
+ }
+ Bx = B.at1();
+ t = Geom::nearest_time(Bx, A);
+ dist = Geom::distance(Bx, A(t));
+ if (dist > h_dist) {
+ if(a_t) *a_t = t;
+ if(b_t) *b_t = 1;
+ h_dist = dist;
+ }
+
+ return h_dist;
+}
+
+bool non_collinear_segments_intersect(const Point &A, const Point &B, const Point &C, const Point &D)
+{
+ return cross(D - C, A - C) * cross(D - C, B - C) < 0 && //
+ cross(B - A, C - A) * cross(B - A, D - A) < 0;
+}
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/bezier-clipping.cpp b/src/3rdparty/2geom/src/2geom/bezier-clipping.cpp
new file mode 100644
index 0000000..27da3d2
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/bezier-clipping.cpp
@@ -0,0 +1,1174 @@
+/*
+ * Implement the Bezier clipping algorithm for finding
+ * Bezier curve intersection points and collinear normals
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+
+
+#include <2geom/basic-intersection.h>
+#include <2geom/choose.h>
+#include <2geom/point.h>
+#include <2geom/interval.h>
+#include <2geom/bezier.h>
+#include <2geom/numeric/matrix.h>
+#include <2geom/convex-hull.h>
+#include <2geom/line.h>
+
+#include <cassert>
+#include <vector>
+#include <algorithm>
+#include <utility>
+//#include <iomanip>
+
+using std::swap;
+
+
+#define VERBOSE 0
+#define CHECK 0
+
+namespace Geom {
+
+namespace detail { namespace bezier_clipping {
+
+////////////////////////////////////////////////////////////////////////////////
+// for debugging
+//
+
+void print(std::vector<Point> const& cp, const char* msg = "")
+{
+ std::cerr << msg << std::endl;
+ for (size_t i = 0; i < cp.size(); ++i)
+ std::cerr << i << " : " << cp[i] << std::endl;
+}
+
+template< class charT >
+std::basic_ostream<charT> &
+operator<< (std::basic_ostream<charT> & os, const Interval & I)
+{
+ os << "[" << I.min() << ", " << I.max() << "]";
+ return os;
+}
+
+double angle (std::vector<Point> const& A)
+{
+ size_t n = A.size() -1;
+ double a = std::atan2(A[n][Y] - A[0][Y], A[n][X] - A[0][X]);
+ return (180 * a / M_PI);
+}
+
+size_t get_precision(Interval const& I)
+{
+ double d = I.extent();
+ double e = 0.1, p = 10;
+ int n = 0;
+ while (n < 16 && d < e)
+ {
+ p *= 10;
+ e = 1/p;
+ ++n;
+ }
+ return n;
+}
+
+void range_assertion(int k, int m, int n, const char* msg)
+{
+ if ( k < m || k > n)
+ {
+ std::cerr << "range assertion failed: \n"
+ << msg << std::endl
+ << "value: " << k
+ << " range: " << m << ", " << n << std::endl;
+ assert (k >= m && k <= n);
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// numerical routines
+
+/*
+ * Compute the determinant of the 2x2 matrix with column the point P1, P2
+ */
+double det(Point const& P1, Point const& P2)
+{
+ return P1[X]*P2[Y] - P1[Y]*P2[X];
+}
+
+/*
+ * Solve the linear system [P1,P2] * P = Q
+ * in case there isn't exactly one solution the routine returns false
+ */
+bool solve(Point & P, Point const& P1, Point const& P2, Point const& Q)
+{
+ double d = det(P1, P2);
+ if (d == 0) return false;
+ d = 1 / d;
+ P[X] = det(Q, P2) * d;
+ P[Y] = det(P1, Q) * d;
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// interval routines
+
+/*
+ * Map the sub-interval I in [0,1] into the interval J and assign it to J
+ */
+void map_to(Interval & J, Interval const& I)
+{
+ J.setEnds(J.valueAt(I.min()), J.valueAt(I.max()));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// bezier curve routines
+
+/*
+ * Return true if all the Bezier curve control points are near,
+ * false otherwise
+ */
+// Bezier.isConstant(precision)
+bool is_constant(std::vector<Point> const& A, double precision)
+{
+ for (unsigned int i = 1; i < A.size(); ++i)
+ {
+ if(!are_near(A[i], A[0], precision))
+ return false;
+ }
+ return true;
+}
+
+/*
+ * Compute the hodograph of the bezier curve B and return it in D
+ */
+// derivative(Bezier)
+void derivative(std::vector<Point> & D, std::vector<Point> const& B)
+{
+ D.clear();
+ size_t sz = B.size();
+ if (sz == 0) return;
+ if (sz == 1)
+ {
+ D.resize(1, Point(0,0));
+ return;
+ }
+ size_t n = sz-1;
+ D.reserve(n);
+ for (size_t i = 0; i < n; ++i)
+ {
+ D.push_back(n*(B[i+1] - B[i]));
+ }
+}
+
+/*
+ * Compute the hodograph of the Bezier curve B rotated of 90 degree
+ * and return it in D; we have N(t) orthogonal to B(t) for any t
+ */
+// rot90(derivative(Bezier))
+void normal(std::vector<Point> & N, std::vector<Point> const& B)
+{
+ derivative(N,B);
+ for (auto & i : N)
+ {
+ i = rot90(i);
+ }
+}
+
+/*
+ * Compute the portion of the Bezier curve "B" wrt the interval [0,t]
+ */
+// portion(Bezier, 0, t)
+void left_portion(Coord t, std::vector<Point> & B)
+{
+ size_t n = B.size();
+ for (size_t i = 1; i < n; ++i)
+ {
+ for (size_t j = n-1; j > i-1 ; --j)
+ {
+ B[j] = lerp(t, B[j-1], B[j]);
+ }
+ }
+}
+
+/*
+ * Compute the portion of the Bezier curve "B" wrt the interval [t,1]
+ */
+// portion(Bezier, t, 1)
+void right_portion(Coord t, std::vector<Point> & B)
+{
+ size_t n = B.size();
+ for (size_t i = 1; i < n; ++i)
+ {
+ for (size_t j = 0; j < n-i; ++j)
+ {
+ B[j] = lerp(t, B[j], B[j+1]);
+ }
+ }
+}
+
+/*
+ * Compute the portion of the Bezier curve "B" wrt the interval "I"
+ */
+// portion(Bezier, I)
+void portion (std::vector<Point> & B , Interval const& I)
+{
+ if (I.min() == 0)
+ {
+ if (I.max() == 1) return;
+ left_portion(I.max(), B);
+ return;
+ }
+ right_portion(I.min(), B);
+ if (I.max() == 1) return;
+ double t = I.extent() / (1 - I.min());
+ left_portion(t, B);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// tags
+
+struct intersection_point_tag;
+struct collinear_normal_tag;
+template <typename Tag>
+OptInterval clip(std::vector<Point> const& A,
+ std::vector<Point> const& B,
+ double precision);
+template <typename Tag>
+void iterate(std::vector<Interval>& domsA,
+ std::vector<Interval>& domsB,
+ std::vector<Point> const& A,
+ std::vector<Point> const& B,
+ Interval const& domA,
+ Interval const& domB,
+ double precision );
+
+
+////////////////////////////////////////////////////////////////////////////////
+// intersection
+
+/*
+ * Make up an orientation line using the control points c[i] and c[j]
+ * the line is returned in the output parameter "l" in the form of a 3 element
+ * vector : l[0] * x + l[1] * y + l[2] == 0; the line is normalized.
+ */
+// Line(c[i], c[j])
+void orientation_line (std::vector<double> & l,
+ std::vector<Point> const& c,
+ size_t i, size_t j)
+{
+ l[0] = c[j][Y] - c[i][Y];
+ l[1] = c[i][X] - c[j][X];
+ l[2] = cross(c[j], c[i]);
+ double length = std::sqrt(l[0] * l[0] + l[1] * l[1]);
+ assert (length != 0);
+ l[0] /= length;
+ l[1] /= length;
+ l[2] /= length;
+}
+
+/*
+ * Pick up an orientation line for the Bezier curve "c" and return it in
+ * the output parameter "l"
+ */
+Line pick_orientation_line (std::vector<Point> const &c, double precision)
+{
+ size_t i = c.size();
+ while (--i > 0 && are_near(c[0], c[i], precision))
+ {}
+
+ // this should never happen because when a new curve portion is created
+ // we check that it is not constant;
+ // however this requires that the precision used in the is_constant
+ // routine has to be the same used here in the are_near test
+ assert(i != 0);
+
+ Line line(c[0], c[i]);
+ return line;
+ //std::cerr << "i = " << i << std::endl;
+}
+
+/*
+ * Make up an orientation line for constant bezier curve;
+ * the orientation line is made up orthogonal to the other curve base line;
+ * the line is returned in the output parameter "l" in the form of a 3 element
+ * vector : l[0] * x + l[1] * y + l[2] == 0; the line is normalized.
+ */
+Line orthogonal_orientation_line (std::vector<Point> const &c,
+ Point const &p,
+ double precision)
+{
+ // this should never happen
+ assert(!is_constant(c, precision));
+
+ Line line(p, (c.back() - c.front()).cw() + p);
+ return line;
+}
+
+/*
+ * Compute the signed distance of the point "P" from the normalized line l
+ */
+double signed_distance(Point const &p, Line const &l)
+{
+ Coord a, b, c;
+ l.coefficients(a, b, c);
+ return a * p[X] + b * p[Y] + c;
+}
+
+/*
+ * Compute the min and max distance of the control points of the Bezier
+ * curve "c" from the normalized orientation line "l".
+ * This bounds are returned through the output Interval parameter"bound".
+ */
+Interval fat_line_bounds (std::vector<Point> const &c,
+ Line const &l)
+{
+ Interval bound(0, 0);
+ for (auto i : c) {
+ bound.expandTo(signed_distance(i, l));
+ }
+ return bound;
+}
+
+/*
+ * return the x component of the intersection point between the line
+ * passing through points p1, p2 and the line Y = "y"
+ */
+double intersect (Point const& p1, Point const& p2, double y)
+{
+ // we are sure that p2[Y] != p1[Y] because this routine is called
+ // only when the lower or the upper bound is crossed
+ double dy = (p2[Y] - p1[Y]);
+ double s = (y - p1[Y]) / dy;
+ return (p2[X]-p1[X])*s + p1[X];
+}
+
+/*
+ * Clip the Bezier curve "B" wrt the fat line defined by the orientation
+ * line "l" and the interval range "bound", the new parameter interval for
+ * the clipped curve is returned through the output parameter "dom"
+ */
+OptInterval clip_interval (std::vector<Point> const& B,
+ Line const &l,
+ Interval const &bound)
+{
+ double n = B.size() - 1; // number of sub-intervals
+ std::vector<Point> D; // distance curve control points
+ D.reserve (B.size());
+ for (size_t i = 0; i < B.size(); ++i)
+ {
+ const double d = signed_distance(B[i], l);
+ D.emplace_back(i/n, d);
+ }
+ //print(D);
+
+ ConvexHull p;
+ p.swap(D);
+ //print(p);
+
+ bool plower, phigher;
+ bool clower, chigher;
+ double t, tmin = 1, tmax = 0;
+// std::cerr << "bound : " << bound << std::endl;
+
+ plower = (p[0][Y] < bound.min());
+ phigher = (p[0][Y] > bound.max());
+ if (!(plower || phigher)) // inside the fat line
+ {
+ if (tmin > p[0][X]) tmin = p[0][X];
+ if (tmax < p[0][X]) tmax = p[0][X];
+// std::cerr << "0 : inside " << p[0]
+// << " : tmin = " << tmin << ", tmax = " << tmax << std::endl;
+ }
+
+ for (size_t i = 1; i < p.size(); ++i)
+ {
+ clower = (p[i][Y] < bound.min());
+ chigher = (p[i][Y] > bound.max());
+ if (!(clower || chigher)) // inside the fat line
+ {
+ if (tmin > p[i][X]) tmin = p[i][X];
+ if (tmax < p[i][X]) tmax = p[i][X];
+// std::cerr << i << " : inside " << p[i]
+// << " : tmin = " << tmin << ", tmax = " << tmax
+// << std::endl;
+ }
+ if (clower != plower) // cross the lower bound
+ {
+ t = intersect(p[i-1], p[i], bound.min());
+ if (tmin > t) tmin = t;
+ if (tmax < t) tmax = t;
+ plower = clower;
+// std::cerr << i << " : lower " << p[i]
+// << " : tmin = " << tmin << ", tmax = " << tmax
+// << std::endl;
+ }
+ if (chigher != phigher) // cross the upper bound
+ {
+ t = intersect(p[i-1], p[i], bound.max());
+ if (tmin > t) tmin = t;
+ if (tmax < t) tmax = t;
+ phigher = chigher;
+// std::cerr << i << " : higher " << p[i]
+// << " : tmin = " << tmin << ", tmax = " << tmax
+// << std::endl;
+ }
+ }
+
+ // we have to test the closing segment for intersection
+ size_t last = p.size() - 1;
+ clower = (p[0][Y] < bound.min());
+ chigher = (p[0][Y] > bound.max());
+ if (clower != plower) // cross the lower bound
+ {
+ t = intersect(p[last], p[0], bound.min());
+ if (tmin > t) tmin = t;
+ if (tmax < t) tmax = t;
+// std::cerr << "0 : lower " << p[0]
+// << " : tmin = " << tmin << ", tmax = " << tmax << std::endl;
+ }
+ if (chigher != phigher) // cross the upper bound
+ {
+ t = intersect(p[last], p[0], bound.max());
+ if (tmin > t) tmin = t;
+ if (tmax < t) tmax = t;
+// std::cerr << "0 : higher " << p[0]
+// << " : tmin = " << tmin << ", tmax = " << tmax << std::endl;
+ }
+
+ if (tmin == 1 && tmax == 0) {
+ return OptInterval();
+ } else {
+ return Interval(tmin, tmax);
+ }
+}
+
+/*
+ * Clip the Bezier curve "B" wrt the Bezier curve "A" for individuating
+ * intersection points the new parameter interval for the clipped curve
+ * is returned through the output parameter "dom"
+ */
+template <>
+OptInterval clip<intersection_point_tag> (std::vector<Point> const& A,
+ std::vector<Point> const& B,
+ double precision)
+{
+ Line bl;
+ if (is_constant(A, precision)) {
+ Point M = middle_point(A.front(), A.back());
+ bl = orthogonal_orientation_line(B, M, precision);
+ } else {
+ bl = pick_orientation_line(A, precision);
+ }
+ bl.normalize();
+ Interval bound = fat_line_bounds(A, bl);
+ return clip_interval(B, bl, bound);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// collinear normal
+
+/*
+ * Compute a closed focus for the Bezier curve B and return it in F
+ * A focus is any curve through which all lines perpendicular to B(t) pass.
+ */
+void make_focus (std::vector<Point> & F, std::vector<Point> const& B)
+{
+ assert (B.size() > 2);
+ size_t n = B.size() - 1;
+ normal(F, B);
+ Point c(1, 1);
+#if VERBOSE
+ if (!solve(c, F[0], -F[n-1], B[n]-B[0]))
+ {
+ std::cerr << "make_focus: unable to make up a closed focus" << std::endl;
+ }
+#else
+ solve(c, F[0], -F[n-1], B[n]-B[0]);
+#endif
+// std::cerr << "c = " << c << std::endl;
+
+
+ // B(t) + c(t) * N(t)
+ double n_inv = 1 / (double)(n);
+ Point c0ni;
+ F.push_back(c[1] * F[n-1]);
+ F[n] += B[n];
+ for (size_t i = n-1; i > 0; --i)
+ {
+ F[i] *= -c[0];
+ c0ni = F[i];
+ F[i] += (c[1] * F[i-1]);
+ F[i] *= (i * n_inv);
+ F[i] -= c0ni;
+ F[i] += B[i];
+ }
+ F[0] *= c[0];
+ F[0] += B[0];
+}
+
+/*
+ * Compute the projection on the plane (t, d) of the control points
+ * (t, u, D(t,u)) where D(t,u) = <(B(t) - F(u)), B'(t)> with 0 <= t, u <= 1
+ * B is a Bezier curve and F is a focus of another Bezier curve.
+ * See Sederberg, Nishita, 1990 - Curve intersection using Bezier clipping.
+ */
+void distance_control_points (std::vector<Point> & D,
+ std::vector<Point> const& B,
+ std::vector<Point> const& F)
+{
+ assert (B.size() > 1);
+ assert (!F.empty());
+ const size_t n = B.size() - 1;
+ const size_t m = F.size() - 1;
+ const size_t r = 2 * n - 1;
+ const double r_inv = 1 / (double)(r);
+ D.clear();
+ D.reserve (B.size() * F.size());
+
+ std::vector<Point> dB;
+ dB.reserve(n);
+ for (size_t k = 0; k < n; ++k)
+ {
+ dB.push_back (B[k+1] - B[k]);
+ }
+ NL::Matrix dBB(n,B.size());
+ for (size_t i = 0; i < n; ++i)
+ for (size_t j = 0; j < B.size(); ++j)
+ dBB(i,j) = dot (dB[i], B[j]);
+ NL::Matrix dBF(n, F.size());
+ for (size_t i = 0; i < n; ++i)
+ for (size_t j = 0; j < F.size(); ++j)
+ dBF(i,j) = dot (dB[i], F[j]);
+
+ size_t l;
+ double bc;
+ Point dij;
+ std::vector<double> d(F.size());
+ int rci = 1;
+ int b1 = 1;
+ for (size_t i = 0; i <= r; ++i)
+ {
+ for (size_t j = 0; j <= m; ++j)
+ {
+ d[j] = 0;
+ }
+ const size_t k0 = std::max(i, n) - n;
+ const size_t kn = std::min(i, n-1);
+ const double bri = (double)n / rci;
+
+ // assert(rci == binomial(r, i));
+ binomial_increment_k(rci, r, i);
+
+ int b2 = b1;
+ for (size_t k = k0; k <= kn; ++k)
+ {
+ //if (k > i || (i-k) > n) continue;
+ l = i - k;
+#if CHECK
+ assert (l <= n);
+#endif
+ bc = bri * b2;
+
+ // assert(b2 == binomial(n, l) * binomial(n - 1, k));
+ binomial_decrement_k(b2, n, l);
+ binomial_increment_k(b2, n - 1, k);
+
+ for (size_t j = 0; j <= m; ++j)
+ {
+ //d[j] += bc * dot(dB[k], B[l] - F[j]);
+ d[j] += bc * (dBB(k,l) - dBF(k,j));
+ }
+ }
+
+ // assert(b1 == binomial(n, i - k0) * binomial(n - 1, k0));
+ if (i < n) {
+ binomial_increment_k(b1, n, i);
+ } else {
+ binomial_increment_k(b1, n - 1, k0);
+ }
+
+ double dmin, dmax;
+ dmin = dmax = d[m];
+ for (size_t j = 0; j < m; ++j)
+ {
+ if (dmin > d[j]) dmin = d[j];
+ if (dmax < d[j]) dmax = d[j];
+ }
+ dij[0] = i * r_inv;
+ dij[1] = dmin;
+ D.push_back (dij);
+ dij[1] = dmax;
+ D.push_back (dij);
+ }
+}
+
+/*
+ * Clip the Bezier curve "B" wrt the focus "F"; the new parameter interval for
+ * the clipped curve is returned through the output parameter "dom"
+ */
+OptInterval clip_interval (std::vector<Point> const& B,
+ std::vector<Point> const& F)
+{
+ std::vector<Point> D; // distance curve control points
+ distance_control_points(D, B, F);
+ //print(D, "D");
+// ConvexHull chD(D);
+// std::vector<Point>& p = chD.boundary; // convex hull vertices
+
+ ConvexHull p;
+ p.swap(D);
+ //print(p, "CH(D)");
+
+ bool plower, clower;
+ double t, tmin = 1, tmax = 0;
+
+ plower = (p[0][Y] < 0);
+ if (p[0][Y] == 0) // on the x axis
+ {
+ if (tmin > p[0][X]) tmin = p[0][X];
+ if (tmax < p[0][X]) tmax = p[0][X];
+// std::cerr << "0 : on x axis " << p[0]
+// << " : tmin = " << tmin << ", tmax = " << tmax << std::endl;
+ }
+
+ for (size_t i = 1; i < p.size(); ++i)
+ {
+ clower = (p[i][Y] < 0);
+ if (p[i][Y] == 0) // on x axis
+ {
+ if (tmin > p[i][X]) tmin = p[i][X];
+ if (tmax < p[i][X]) tmax = p[i][X];
+// std::cerr << i << " : on x axis " << p[i]
+// << " : tmin = " << tmin << ", tmax = " << tmax
+// << std::endl;
+ }
+ else if (clower != plower) // cross the x axis
+ {
+ t = intersect(p[i-1], p[i], 0);
+ if (tmin > t) tmin = t;
+ if (tmax < t) tmax = t;
+ plower = clower;
+// std::cerr << i << " : lower " << p[i]
+// << " : tmin = " << tmin << ", tmax = " << tmax
+// << std::endl;
+ }
+ }
+
+ // we have to test the closing segment for intersection
+ size_t last = p.size() - 1;
+ clower = (p[0][Y] < 0);
+ if (clower != plower) // cross the x axis
+ {
+ t = intersect(p[last], p[0], 0);
+ if (tmin > t) tmin = t;
+ if (tmax < t) tmax = t;
+// std::cerr << "0 : lower " << p[0]
+// << " : tmin = " << tmin << ", tmax = " << tmax << std::endl;
+ }
+ if (tmin == 1 && tmax == 0) {
+ return OptInterval();
+ } else {
+ return Interval(tmin, tmax);
+ }
+}
+
+/*
+ * Clip the Bezier curve "B" wrt the Bezier curve "A" for individuating
+ * points which have collinear normals; the new parameter interval
+ * for the clipped curve is returned through the output parameter "dom"
+ */
+template <>
+OptInterval clip<collinear_normal_tag> (std::vector<Point> const& A,
+ std::vector<Point> const& B,
+ double /*precision*/)
+{
+ std::vector<Point> F;
+ make_focus(F, A);
+ return clip_interval(B, F);
+}
+
+
+
+const double MAX_PRECISION = 1e-8;
+const double MIN_CLIPPED_SIZE_THRESHOLD = 0.8;
+const Interval UNIT_INTERVAL(0,1);
+const OptInterval EMPTY_INTERVAL;
+const Interval H1_INTERVAL(0, 0.5);
+const Interval H2_INTERVAL(nextafter(0.5, 1.0), 1.0);
+
+/*
+ * iterate
+ *
+ * input:
+ * A, B: control point sets of two bezier curves
+ * domA, domB: real parameter intervals of the two curves
+ * precision: required computational precision of the returned parameter ranges
+ * output:
+ * domsA, domsB: sets of parameter intervals
+ *
+ * The parameter intervals are computed by using a Bezier clipping algorithm,
+ * in case the clipping doesn't shrink the initial interval more than 20%,
+ * a subdivision step is performed.
+ * If during the computation both curves collapse to a single point
+ * the routine exits independently by the precision reached in the computation
+ * of the curve intervals.
+ */
+template <>
+void iterate<intersection_point_tag> (std::vector<Interval>& domsA,
+ std::vector<Interval>& domsB,
+ std::vector<Point> const& A,
+ std::vector<Point> const& B,
+ Interval const& domA,
+ Interval const& domB,
+ double precision )
+{
+ // in order to limit recursion
+ static size_t counter = 0;
+ if (domA.extent() == 1 && domB.extent() == 1) counter = 0;
+ if (++counter > 100) return;
+#if VERBOSE
+ std::cerr << std::fixed << std::setprecision(16);
+ std::cerr << ">> curve subdision performed <<" << std::endl;
+ std::cerr << "dom(A) : " << domA << std::endl;
+ std::cerr << "dom(B) : " << domB << std::endl;
+// std::cerr << "angle(A) : " << angle(A) << std::endl;
+// std::cerr << "angle(B) : " << angle(B) << std::endl;
+#endif
+
+ if (precision < MAX_PRECISION)
+ precision = MAX_PRECISION;
+
+ std::vector<Point> pA = A;
+ std::vector<Point> pB = B;
+ std::vector<Point>* C1 = &pA;
+ std::vector<Point>* C2 = &pB;
+
+ Interval dompA = domA;
+ Interval dompB = domB;
+ Interval* dom1 = &dompA;
+ Interval* dom2 = &dompB;
+
+ OptInterval dom;
+
+ if ( is_constant(A, precision) && is_constant(B, precision) ){
+ Point M1 = middle_point(C1->front(), C1->back());
+ Point M2 = middle_point(C2->front(), C2->back());
+ if (are_near(M1,M2)){
+ domsA.push_back(domA);
+ domsB.push_back(domB);
+ }
+ return;
+ }
+
+ size_t iter = 0;
+ while (++iter < 100
+ && (dompA.extent() >= precision || dompB.extent() >= precision))
+ {
+#if VERBOSE
+ std::cerr << "iter: " << iter << std::endl;
+#endif
+ dom = clip<intersection_point_tag>(*C1, *C2, precision);
+
+ if (dom.empty())
+ {
+#if VERBOSE
+ std::cerr << "dom: empty" << std::endl;
+#endif
+ return;
+ }
+#if VERBOSE
+ std::cerr << "dom : " << dom << std::endl;
+#endif
+ // all other cases where dom[0] > dom[1] are invalid
+ assert(dom->min() <= dom->max());
+
+ map_to(*dom2, *dom);
+
+ portion(*C2, *dom);
+ if (is_constant(*C2, precision) && is_constant(*C1, precision))
+ {
+ Point M1 = middle_point(C1->front(), C1->back());
+ Point M2 = middle_point(C2->front(), C2->back());
+#if VERBOSE
+ std::cerr << "both curves are constant: \n"
+ << "M1: " << M1 << "\n"
+ << "M2: " << M2 << std::endl;
+ print(*C2, "C2");
+ print(*C1, "C1");
+#endif
+ if (are_near(M1,M2))
+ break; // append the new interval
+ else
+ return; // exit without appending any new interval
+ }
+
+
+ // if we have clipped less than 20% than we need to subdive the curve
+ // with the largest domain into two sub-curves
+ if (dom->extent() > MIN_CLIPPED_SIZE_THRESHOLD)
+ {
+#if VERBOSE
+ std::cerr << "clipped less than 20% : " << dom->extent() << std::endl;
+ std::cerr << "angle(pA) : " << angle(pA) << std::endl;
+ std::cerr << "angle(pB) : " << angle(pB) << std::endl;
+#endif
+ std::vector<Point> pC1, pC2;
+ Interval dompC1, dompC2;
+ if (dompA.extent() > dompB.extent())
+ {
+ pC1 = pC2 = pA;
+ portion(pC1, H1_INTERVAL);
+ portion(pC2, H2_INTERVAL);
+ dompC1 = dompC2 = dompA;
+ map_to(dompC1, H1_INTERVAL);
+ map_to(dompC2, H2_INTERVAL);
+ iterate<intersection_point_tag>(domsA, domsB, pC1, pB,
+ dompC1, dompB, precision);
+ iterate<intersection_point_tag>(domsA, domsB, pC2, pB,
+ dompC2, dompB, precision);
+ }
+ else
+ {
+ pC1 = pC2 = pB;
+ portion(pC1, H1_INTERVAL);
+ portion(pC2, H2_INTERVAL);
+ dompC1 = dompC2 = dompB;
+ map_to(dompC1, H1_INTERVAL);
+ map_to(dompC2, H2_INTERVAL);
+ iterate<intersection_point_tag>(domsB, domsA, pC1, pA,
+ dompC1, dompA, precision);
+ iterate<intersection_point_tag>(domsB, domsA, pC2, pA,
+ dompC2, dompA, precision);
+ }
+ return;
+ }
+
+ swap(C1, C2);
+ swap(dom1, dom2);
+#if VERBOSE
+ std::cerr << "dom(pA) : " << dompA << std::endl;
+ std::cerr << "dom(pB) : " << dompB << std::endl;
+#endif
+ }
+ domsA.push_back(dompA);
+ domsB.push_back(dompB);
+}
+
+
+/*
+ * iterate
+ *
+ * input:
+ * A, B: control point sets of two bezier curves
+ * domA, domB: real parameter intervals of the two curves
+ * precision: required computational precision of the returned parameter ranges
+ * output:
+ * domsA, domsB: sets of parameter intervals
+ *
+ * The parameter intervals are computed by using a Bezier clipping algorithm,
+ * in case the clipping doesn't shrink the initial interval more than 20%,
+ * a subdivision step is performed.
+ * If during the computation one of the two curve interval length becomes less
+ * than MAX_PRECISION the routine exits independently by the precision reached
+ * in the computation of the other curve interval.
+ */
+template <>
+void iterate<collinear_normal_tag> (std::vector<Interval>& domsA,
+ std::vector<Interval>& domsB,
+ std::vector<Point> const& A,
+ std::vector<Point> const& B,
+ Interval const& domA,
+ Interval const& domB,
+ double precision)
+{
+ // in order to limit recursion
+ static size_t counter = 0;
+ if (domA.extent() == 1 && domB.extent() == 1) counter = 0;
+ if (++counter > 100) return;
+#if VERBOSE
+ std::cerr << std::fixed << std::setprecision(16);
+ std::cerr << ">> curve subdision performed <<" << std::endl;
+ std::cerr << "dom(A) : " << domA << std::endl;
+ std::cerr << "dom(B) : " << domB << std::endl;
+// std::cerr << "angle(A) : " << angle(A) << std::endl;
+// std::cerr << "angle(B) : " << angle(B) << std::endl;
+#endif
+
+ if (precision < MAX_PRECISION)
+ precision = MAX_PRECISION;
+
+ std::vector<Point> pA = A;
+ std::vector<Point> pB = B;
+ std::vector<Point>* C1 = &pA;
+ std::vector<Point>* C2 = &pB;
+
+ Interval dompA = domA;
+ Interval dompB = domB;
+ Interval* dom1 = &dompA;
+ Interval* dom2 = &dompB;
+
+ OptInterval dom;
+
+ size_t iter = 0;
+ while (++iter < 100
+ && (dompA.extent() >= precision || dompB.extent() >= precision))
+ {
+#if VERBOSE
+ std::cerr << "iter: " << iter << std::endl;
+#endif
+ dom = clip<collinear_normal_tag>(*C1, *C2, precision);
+
+ if (dom.empty()) {
+#if VERBOSE
+ std::cerr << "dom: empty" << std::endl;
+#endif
+ return;
+ }
+#if VERBOSE
+ std::cerr << "dom : " << dom << std::endl;
+#endif
+ assert(dom->min() <= dom->max());
+
+ map_to(*dom2, *dom);
+
+ // it's better to stop before losing computational precision
+ if (iter > 1 && (dom2->extent() <= MAX_PRECISION))
+ {
+#if VERBOSE
+ std::cerr << "beyond max precision limit" << std::endl;
+#endif
+ break;
+ }
+
+ portion(*C2, *dom);
+ if (iter > 1 && is_constant(*C2, precision))
+ {
+#if VERBOSE
+ std::cerr << "new curve portion pC1 is constant" << std::endl;
+#endif
+ break;
+ }
+
+
+ // if we have clipped less than 20% than we need to subdive the curve
+ // with the largest domain into two sub-curves
+ if ( dom->extent() > MIN_CLIPPED_SIZE_THRESHOLD)
+ {
+#if VERBOSE
+ std::cerr << "clipped less than 20% : " << dom->extent() << std::endl;
+ std::cerr << "angle(pA) : " << angle(pA) << std::endl;
+ std::cerr << "angle(pB) : " << angle(pB) << std::endl;
+#endif
+ std::vector<Point> pC1, pC2;
+ Interval dompC1, dompC2;
+ if (dompA.extent() > dompB.extent())
+ {
+ if ((dompA.extent() / 2) < MAX_PRECISION)
+ {
+ break;
+ }
+ pC1 = pC2 = pA;
+ portion(pC1, H1_INTERVAL);
+ if (false && is_constant(pC1, precision))
+ {
+#if VERBOSE
+ std::cerr << "new curve portion pC1 is constant" << std::endl;
+#endif
+ break;
+ }
+ portion(pC2, H2_INTERVAL);
+ if (is_constant(pC2, precision))
+ {
+#if VERBOSE
+ std::cerr << "new curve portion pC2 is constant" << std::endl;
+#endif
+ break;
+ }
+ dompC1 = dompC2 = dompA;
+ map_to(dompC1, H1_INTERVAL);
+ map_to(dompC2, H2_INTERVAL);
+ iterate<collinear_normal_tag>(domsA, domsB, pC1, pB,
+ dompC1, dompB, precision);
+ iterate<collinear_normal_tag>(domsA, domsB, pC2, pB,
+ dompC2, dompB, precision);
+ }
+ else
+ {
+ if ((dompB.extent() / 2) < MAX_PRECISION)
+ {
+ break;
+ }
+ pC1 = pC2 = pB;
+ portion(pC1, H1_INTERVAL);
+ if (is_constant(pC1, precision))
+ {
+#if VERBOSE
+ std::cerr << "new curve portion pC1 is constant" << std::endl;
+#endif
+ break;
+ }
+ portion(pC2, H2_INTERVAL);
+ if (is_constant(pC2, precision))
+ {
+#if VERBOSE
+ std::cerr << "new curve portion pC2 is constant" << std::endl;
+#endif
+ break;
+ }
+ dompC1 = dompC2 = dompB;
+ map_to(dompC1, H1_INTERVAL);
+ map_to(dompC2, H2_INTERVAL);
+ iterate<collinear_normal_tag>(domsB, domsA, pC1, pA,
+ dompC1, dompA, precision);
+ iterate<collinear_normal_tag>(domsB, domsA, pC2, pA,
+ dompC2, dompA, precision);
+ }
+ return;
+ }
+
+ swap(C1, C2);
+ swap(dom1, dom2);
+#if VERBOSE
+ std::cerr << "dom(pA) : " << dompA << std::endl;
+ std::cerr << "dom(pB) : " << dompB << std::endl;
+#endif
+ }
+ domsA.push_back(dompA);
+ domsB.push_back(dompB);
+}
+
+
+/*
+ * get_solutions
+ *
+ * input: A, B - set of control points of two Bezier curve
+ * input: precision - required precision of computation
+ * input: clip - the routine used for clipping
+ * output: xs - set of pairs of parameter values
+ * at which the clipping algorithm converges
+ *
+ * This routine is based on the Bezier Clipping Algorithm,
+ * see: Sederberg - Computer Aided Geometric Design
+ */
+template <typename Tag>
+void get_solutions (std::vector< std::pair<double, double> >& xs,
+ std::vector<Point> const& A,
+ std::vector<Point> const& B,
+ double precision)
+{
+ std::pair<double, double> ci;
+ std::vector<Interval> domsA, domsB;
+ iterate<Tag> (domsA, domsB, A, B, UNIT_INTERVAL, UNIT_INTERVAL, precision);
+ if (domsA.size() != domsB.size())
+ {
+ assert (domsA.size() == domsB.size());
+ }
+ xs.clear();
+ xs.reserve(domsA.size());
+ for (size_t i = 0; i < domsA.size(); ++i)
+ {
+#if VERBOSE
+ std::cerr << i << " : domA : " << domsA[i] << std::endl;
+ std::cerr << "extent A: " << domsA[i].extent() << " ";
+ std::cerr << "precision A: " << get_precision(domsA[i]) << std::endl;
+ std::cerr << i << " : domB : " << domsB[i] << std::endl;
+ std::cerr << "extent B: " << domsB[i].extent() << " ";
+ std::cerr << "precision B: " << get_precision(domsB[i]) << std::endl;
+#endif
+ ci.first = domsA[i].middle();
+ ci.second = domsB[i].middle();
+ xs.push_back(ci);
+ }
+}
+
+} /* end namespace bezier_clipping */ } /* end namespace detail */
+
+
+/*
+ * find_collinear_normal
+ *
+ * input: A, B - set of control points of two Bezier curve
+ * input: precision - required precision of computation
+ * output: xs - set of pairs of parameter values
+ * at which there are collinear normals
+ *
+ * This routine is based on the Bezier Clipping Algorithm,
+ * see: Sederberg, Nishita, 1990 - Curve intersection using Bezier clipping
+ */
+void find_collinear_normal (std::vector< std::pair<double, double> >& xs,
+ std::vector<Point> const& A,
+ std::vector<Point> const& B,
+ double precision)
+{
+ using detail::bezier_clipping::get_solutions;
+ using detail::bezier_clipping::collinear_normal_tag;
+ get_solutions<collinear_normal_tag>(xs, A, B, precision);
+}
+
+
+/*
+ * find_intersections_bezier_clipping
+ *
+ * input: A, B - set of control points of two Bezier curve
+ * input: precision - required precision of computation
+ * output: xs - set of pairs of parameter values
+ * at which crossing happens
+ *
+ * This routine is based on the Bezier Clipping Algorithm,
+ * see: Sederberg, Nishita, 1990 - Curve intersection using Bezier clipping
+ */
+void find_intersections_bezier_clipping (std::vector< std::pair<double, double> >& xs,
+ std::vector<Point> const& A,
+ std::vector<Point> const& B,
+ double precision)
+{
+ using detail::bezier_clipping::get_solutions;
+ using detail::bezier_clipping::intersection_point_tag;
+ get_solutions<intersection_point_tag>(xs, A, B, precision);
+}
+
+} // end namespace Geom
+
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/bezier-curve.cpp b/src/3rdparty/2geom/src/2geom/bezier-curve.cpp
new file mode 100644
index 0000000..ca0f787
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/bezier-curve.cpp
@@ -0,0 +1,695 @@
+/* Bezier curve implementation
+ *
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2007-2009 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/bezier-curve.h>
+#include <2geom/path-sink.h>
+#include <2geom/basic-intersection.h>
+#include <2geom/nearest-time.h>
+#include <2geom/polynomial.h>
+
+namespace Geom
+{
+
+/**
+ * @class BezierCurve
+ * @brief Two-dimensional Bezier curve of arbitrary order.
+ *
+ * Bezier curves are an expansion of the concept of linear interpolation to n points.
+ * Linear segments in 2Geom are in fact Bezier curves of order 1.
+ *
+ * Let \f$\mathbf{B}_{\mathbf{p}_0\mathbf{p}_1\ldots\mathbf{p}_n}\f$ denote a Bezier curve
+ * of order \f$n\f$ defined by the points \f$\mathbf{p}_0, \mathbf{p}_1, \ldots, \mathbf{p}_n\f$.
+ * Bezier curve of order 1 is a linear interpolation curve between two points, defined as
+ * \f[ \mathbf{B}_{\mathbf{p}_0\mathbf{p}_1}(t) = (1-t)\mathbf{p}_0 + t\mathbf{p}_1 \f]
+ * If we now substitute points \f$\mathbf{p_0}\f$ and \f$\mathbf{p_1}\f$ in this definition
+ * by linear interpolations, we get the definition of a Bezier curve of order 2, also called
+ * a quadratic Bezier curve.
+ * \f{align*}{ \mathbf{B}_{\mathbf{p}_0\mathbf{p}_1\mathbf{p}_2}(t)
+ &= (1-t) \mathbf{B}_{\mathbf{p}_0\mathbf{p}_1}(t) + t \mathbf{B}_{\mathbf{p}_1\mathbf{p}_2}(t) \\
+ \mathbf{B}_{\mathbf{p}_0\mathbf{p}_1\mathbf{p}_2}(t)
+ &= (1-t)^2\mathbf{p}_0 + 2(1-t)t\mathbf{p}_1 + t^2\mathbf{p}_2 \f}
+ * By substituting points for quadratic Bezier curves in the original definition,
+ * we get a Bezier curve of order 3, called a cubic Bezier curve.
+ * \f{align*}{ \mathbf{B}_{\mathbf{p}_0\mathbf{p}_1\mathbf{p}_2\mathbf{p}_3}(t)
+ &= (1-t) \mathbf{B}_{\mathbf{p}_0\mathbf{p}_1\mathbf{p}_2}(t)
+ + t \mathbf{B}_{\mathbf{p}_1\mathbf{p}_2\mathbf{p}_3}(t) \\
+ \mathbf{B}_{\mathbf{p}_0\mathbf{p}_1\mathbf{p}_2\mathbf{p}_3}(t)
+ &= (1-t)^3\mathbf{p}_0+3(1-t)^2t\mathbf{p}_1+3(1-t)t^2\mathbf{p}_2+t^3\mathbf{p}_3 \f}
+ * In general, a Bezier curve or order \f$n\f$ can be recursively defined as
+ * \f[ \mathbf{B}_{\mathbf{p}_0\mathbf{p}_1\ldots\mathbf{p}_n}(t)
+ = (1-t) \mathbf{B}_{\mathbf{p}_0\mathbf{p}_1\ldots\mathbf{p}_{n-1}}(t)
+ + t \mathbf{B}_{\mathbf{p}_1\mathbf{p}_2\ldots\mathbf{p}_n}(t) \f]
+ *
+ * This substitution can be repeated an arbitrary number of times. To picture this, imagine
+ * the evaluation of a point on the curve as follows: first, all control points are joined with
+ * straight lines, and a point corresponding to the selected time value is marked on them.
+ * Then, the marked points are joined with straight lines and the point corresponding to
+ * the time value is marked. This is repeated until only one marked point remains, which is the
+ * point at the selected time value.
+ *
+ * @image html bezier-curve-evaluation.png "Evaluation of the Bezier curve"
+ *
+ * An important property of the Bezier curves is that their parameters (control points)
+ * have an intuitive geometric interpretation. Because of this, they are frequently used
+ * in vector graphics editors.
+ *
+ * Every Bezier curve is contained in its control polygon (the convex polygon composed
+ * of its control points). This fact is useful for sweepline algorithms and intersection.
+ *
+ * @par Implementation notes
+ * The order of a Bezier curve is immuable once it has been created. Normally, you should
+ * know the order at compile time and use the BezierCurveN template. If you need to determine
+ * the order at runtime, use the BezierCurve::create() function. It will create a BezierCurveN
+ * for orders 1, 2 and 3 (up to cubic Beziers), so you can later <tt>dynamic_cast</tt>
+ * to those types, and for higher orders it will create an instance of BezierCurve.
+ *
+ * @relates BezierCurveN
+ * @ingroup Curves
+ */
+
+/**
+ * @class BezierCurveN
+ * @brief Bezier curve with compile-time specified order.
+ *
+ * @tparam degree unsigned value indicating the order of the Bezier curve
+ *
+ * @relates BezierCurve
+ * @ingroup Curves
+ */
+
+
+BezierCurve::BezierCurve(std::vector<Point> const &pts)
+ : inner(pts)
+{
+ if (pts.size() < 2) {
+ THROW_RANGEERROR("Bezier curve must have at least 2 control points");
+ }
+}
+
+bool BezierCurve::isDegenerate() const
+{
+ for (unsigned d = 0; d < 2; ++d) {
+ Coord ic = inner[d][0];
+ for (unsigned i = 1; i < size(); ++i) {
+ if (inner[d][i] != ic) return false;
+ }
+ }
+ return true;
+}
+
+/** Return false if there are at least 3 distinct control points, true otherwise. */
+bool BezierCurve::isLineSegment() const
+{
+ auto const last_idx = size() - 1;
+ if (last_idx == 1) {
+ return true;
+ }
+ auto const start = controlPoint(0);
+ auto const end = controlPoint(last_idx);
+ for (unsigned i = 1; i < last_idx; ++i) {
+ auto const pi = controlPoint(i);
+ if (pi != start && pi != end) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void BezierCurve::expandToTransformed(Rect &bbox, Affine const &transform) const
+{
+ bbox |= bounds_exact(inner * transform);
+}
+
+Coord BezierCurve::length(Coord tolerance) const
+{
+ switch (order())
+ {
+ case 0:
+ return 0.0;
+ case 1:
+ return distance(initialPoint(), finalPoint());
+ case 2:
+ {
+ std::vector<Point> pts = controlPoints();
+ return bezier_length(pts[0], pts[1], pts[2], tolerance);
+ }
+ case 3:
+ {
+ std::vector<Point> pts = controlPoints();
+ return bezier_length(pts[0], pts[1], pts[2], pts[3], tolerance);
+ }
+ default:
+ return bezier_length(controlPoints(), tolerance);
+ }
+}
+
+std::vector<CurveIntersection>
+BezierCurve::intersect(Curve const &other, Coord eps) const
+{
+ std::vector<CurveIntersection> result;
+
+ // in case we encounter an order-1 curve created from a vector
+ // or a degenerate elliptical arc
+ if (isLineSegment()) {
+ LineSegment ls(initialPoint(), finalPoint());
+ result = ls.intersect(other);
+ return result;
+ }
+
+ // here we are sure that this curve is at least a quadratic Bezier
+ BezierCurve const *bez = dynamic_cast<BezierCurve const *>(&other);
+ if (bez) {
+ std::vector<std::pair<double, double> > xs;
+ find_intersections(xs, inner, bez->inner, eps);
+ for (auto & i : xs) {
+ CurveIntersection x(*this, other, i.first, i.second);
+ result.push_back(x);
+ }
+ return result;
+ }
+
+ // pass other intersection types to the other curve
+ result = other.intersect(*this, eps);
+ transpose_in_place(result);
+ return result;
+}
+
+bool BezierCurve::isNear(Curve const &c, Coord precision) const
+{
+ if (this == &c) return true;
+
+ BezierCurve const *other = dynamic_cast<BezierCurve const *>(&c);
+ if (!other) return false;
+
+ if (!are_near(inner.at0(), other->inner.at0(), precision)) return false;
+ if (!are_near(inner.at1(), other->inner.at1(), precision)) return false;
+
+ if (size() == other->size()) {
+ for (unsigned i = 1; i < order(); ++i) {
+ if (!are_near(inner.point(i), other->inner.point(i), precision)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ // Must equalize the degrees before comparing
+ BezierCurve elevated_this, elevated_other;
+ for (size_t dim = 0; dim < 2; dim++) {
+ unsigned const our_degree = inner[dim].degree();
+ unsigned const other_degree = other->inner[dim].degree();
+
+ if (our_degree < other_degree) {
+ // Elevate our degree
+ elevated_this.inner[dim] = inner[dim].elevate_to_degree(other_degree);
+ elevated_other.inner[dim] = other->inner[dim];
+ } else if (our_degree > other_degree) {
+ // Elevate the other's degree
+ elevated_this.inner[dim] = inner[dim];
+ elevated_other.inner[dim] = other->inner[dim].elevate_to_degree(our_degree);
+ } else {
+ // Equal degrees: just copy
+ elevated_this.inner[dim] = inner[dim];
+ elevated_other.inner[dim] = other->inner[dim];
+ }
+ }
+ assert(elevated_other.size() == elevated_this.size());
+ return elevated_this.isNear(elevated_other, precision);
+ }
+}
+
+Curve *BezierCurve::portion(Coord f, Coord t) const
+{
+ if (f == 0.0 && t == 1.0) {
+ return duplicate();
+ }
+ if (f == 1.0 && t == 0.0) {
+ return reverse();
+ }
+ return new BezierCurve(Geom::portion(inner, f, t));
+}
+
+bool BezierCurve::operator==(Curve const &c) const
+{
+ if (this == &c) return true;
+
+ BezierCurve const *other = dynamic_cast<BezierCurve const *>(&c);
+ if (!other) return false;
+ if (size() != other->size()) return false;
+
+ for (unsigned i = 0; i < size(); ++i) {
+ if (controlPoint(i) != other->controlPoint(i)) return false;
+ }
+ return true;
+}
+
+Coord BezierCurve::nearestTime(Point const &p, Coord from, Coord to) const
+{
+ return nearest_time(p, inner, from, to);
+}
+
+void BezierCurve::feed(PathSink &sink, bool moveto_initial) const
+{
+ if (size() > 4) {
+ Curve::feed(sink, moveto_initial);
+ return;
+ }
+
+ Point ip = controlPoint(0);
+ if (moveto_initial) {
+ sink.moveTo(ip);
+ }
+ switch (size()) {
+ case 2:
+ sink.lineTo(controlPoint(1));
+ break;
+ case 3:
+ sink.quadTo(controlPoint(1), controlPoint(2));
+ break;
+ case 4:
+ sink.curveTo(controlPoint(1), controlPoint(2), controlPoint(3));
+ break;
+ default:
+ // TODO: add a path sink method that accepts a vector of control points
+ // and converts to cubic spline by default
+ assert(false);
+ break;
+ }
+}
+
+BezierCurve *BezierCurve::create(std::vector<Point> const &pts)
+{
+ switch (pts.size()) {
+ case 0:
+ case 1:
+ THROW_LOGICALERROR("BezierCurve::create: too few points in vector");
+ return NULL;
+ case 2:
+ return new LineSegment(pts[0], pts[1]);
+ case 3:
+ return new QuadraticBezier(pts[0], pts[1], pts[2]);
+ case 4:
+ return new CubicBezier(pts[0], pts[1], pts[2], pts[3]);
+ default:
+ return new BezierCurve(pts);
+ }
+}
+
+// optimized specializations for LineSegment
+
+template <>
+Curve *BezierCurveN<1>::derivative() const {
+ double dx = inner[X][1] - inner[X][0], dy = inner[Y][1] - inner[Y][0];
+ return new BezierCurveN<1>(Point(dx,dy),Point(dx,dy));
+}
+
+template<>
+Coord BezierCurveN<1>::nearestTime(Point const& p, Coord from, Coord to) const
+{
+ using std::swap;
+
+ if ( from > to ) swap(from, to);
+ Point ip = pointAt(from);
+ Point fp = pointAt(to);
+ Point v = fp - ip;
+ Coord l2v = L2sq(v);
+ if (l2v == 0) return 0;
+ Coord t = dot( p - ip, v ) / l2v;
+ if ( t <= 0 ) return from;
+ else if ( t >= 1 ) return to;
+ else return from + t*(to-from);
+}
+
+/* Specialized intersection routine for line segments. */
+template <>
+std::vector<CurveIntersection> BezierCurveN<1>::intersect(Curve const &other, Coord eps) const
+{
+ std::vector<CurveIntersection> result;
+
+ // only handle intersections with other LineSegments here
+ if (other.isLineSegment()) {
+ Line this_line(initialPoint(), finalPoint());
+ Line other_line(other.initialPoint(), other.finalPoint());
+ result = this_line.intersect(other_line);
+ filter_line_segment_intersections(result, true, true);
+ return result;
+ }
+
+ // pass all other types to the other curve
+ result = other.intersect(*this, eps);
+ transpose_in_place(result);
+ return result;
+}
+
+/** @brief Find intersections of a low-degree Bézier curve with a line segment.
+ *
+ * Uses algebraic solutions to low-degree polynomial equations which may be faster
+ * and more precise than iterative methods.
+ *
+ * @tparam degree The degree of the Bézier curve; must be 2 or 3.
+ * @param curve A Bézier curve of the given degree.
+ * @param line A line (but really a segment).
+ * @return Intersections between the passed curve and the fundamental segment of the line
+ * (the segment where the time parameter lies in the unit interval).
+ */
+template <unsigned degree>
+static std::vector<CurveIntersection> bezier_line_intersections(BezierCurveN<degree> const &curve, Line const &line)
+{
+ static_assert(degree == 2 || degree == 3, "bezier_line_intersections<degree>() error: degree must be 2 or 3.");
+
+ auto const length = distance(line.initialPoint(), line.finalPoint());
+ if (length == 0) {
+ return {};
+ }
+ std::vector<CurveIntersection> result;
+
+ // Find the isometry mapping the line to the x-axis, taking the initial point to the origin
+ // and the final point to (length, 0). Apply this transformation to the Bézier curve and
+ // extract the y-coordinate polynomial.
+ auto const transform = line.rotationToZero(Y);
+ Bezier const y = (curve.fragment() * transform)[Y];
+ std::vector<double> roots;
+
+ // Find roots of the polynomial y.
+ {
+ double const c2 = y[0] + y[2] - 2.0 * y[1];
+ double const c1 = y[1] - y[0];
+ double const c0 = y[0];
+
+ if constexpr (degree == 2) {
+ roots = solve_quadratic(c2, 2.0 * c1, c0);
+ } else if constexpr (degree == 3) {
+ double const c3 = y[3] - y[0] + 3.0 * (y[1] - y[2]);
+ roots = solve_cubic(c3, 3.0 * c2, 3.0 * c1 , c0);
+ }
+ }
+
+ // Filter the roots and assemble intersections.
+ for (double root : roots) {
+ if (root < 0.0 || root > 1.0) {
+ continue;
+ }
+ Coord x = (curve.pointAt(root) * transform)[X];
+ if (x < 0.0 || x > length) {
+ continue;
+ }
+ result.emplace_back(curve, line, root, x / length);
+ }
+ return result;
+}
+
+/* Specialized intersection routine for quadratic Bézier curves. */
+template <>
+std::vector<CurveIntersection> BezierCurveN<2>::intersect(Curve const &other, Coord eps) const
+{
+ if (auto other_bezier = dynamic_cast<BezierCurve const *>(&other)) {
+ auto const other_degree = other_bezier->order();
+ if (other_degree == 1) {
+ // Use the exact method to intersect a quadratic Bézier with a line segment.
+ auto line = Line(other_bezier->initialPoint(), other_bezier->finalPoint());
+ return bezier_line_intersections<2>(*this, line);
+ }
+ // TODO: implement exact intersection of two quadratic Béziers using the method of resultants.
+ }
+ return BezierCurve::intersect(other, eps);
+}
+
+/* Specialized intersection routine for cubic Bézier curves. */
+template <>
+std::vector<CurveIntersection> BezierCurveN<3>::intersect(Curve const &other, Coord eps) const
+{
+ if (auto other_bezier = dynamic_cast<BezierCurve const *>(&other)) {
+ if (other_bezier->order() == 1) {
+ // Use the exact method to intersect a cubic Bézier with a line segment.
+ auto line = Line(other_bezier->initialPoint(), other_bezier->finalPoint());
+ return bezier_line_intersections<3>(*this, line);
+ }
+ }
+ return BezierCurve::intersect(other, eps);
+}
+
+template <>
+int BezierCurveN<1>::winding(Point const &p) const
+{
+ Point ip = inner.at0(), fp = inner.at1();
+ if (p[Y] == std::max(ip[Y], fp[Y])) return 0;
+
+ Point v = fp - ip;
+ assert(v[Y] != 0);
+ Coord t = (p[Y] - ip[Y]) / v[Y];
+ assert(t >= 0 && t <= 1);
+ Coord xcross = lerp(t, ip[X], fp[X]);
+ if (xcross > p[X]) {
+ return v[Y] > 0 ? 1 : -1;
+ }
+ return 0;
+}
+
+template <>
+void BezierCurveN<1>::feed(PathSink &sink, bool moveto_initial) const
+{
+ if (moveto_initial) {
+ sink.moveTo(controlPoint(0));
+ }
+ sink.lineTo(controlPoint(1));
+}
+
+template <>
+void BezierCurveN<2>::feed(PathSink &sink, bool moveto_initial) const
+{
+ if (moveto_initial) {
+ sink.moveTo(controlPoint(0));
+ }
+ sink.quadTo(controlPoint(1), controlPoint(2));
+}
+
+template <>
+void BezierCurveN<3>::feed(PathSink &sink, bool moveto_initial) const
+{
+ if (moveto_initial) {
+ sink.moveTo(controlPoint(0));
+ }
+ sink.curveTo(controlPoint(1), controlPoint(2), controlPoint(3));
+}
+
+static void bezier_expand_to_image(Rect &range, Point const &x0, Point const &x1, Point const &x2)
+{
+ for (auto i : { X, Y }) {
+ bezier_expand_to_image(range[i], x0[i], x1[i], x2[i]);
+ }
+}
+
+static void bezier_expand_to_image(Rect &range, Point const &x0, Point const &x1, Point const &x2, Point const &x3)
+{
+ for (auto i : { X, Y }) {
+ bezier_expand_to_image(range[i], x0[i], x1[i], x2[i], x3[i]);
+ }
+}
+
+template <>
+void BezierCurveN<1>::expandToTransformed(Rect &bbox, Affine const &transform) const
+{
+ bbox.expandTo(finalPoint() * transform);
+}
+
+template <>
+void BezierCurveN<2>::expandToTransformed(Rect &bbox, Affine const &transform) const
+{
+ bezier_expand_to_image(bbox, controlPoint(0) * transform,
+ controlPoint(1) * transform,
+ controlPoint(2) * transform);
+}
+
+template <>
+void BezierCurveN<3>::expandToTransformed(Rect &bbox, Affine const &transform) const
+{
+ bezier_expand_to_image(bbox, controlPoint(0) * transform,
+ controlPoint(1) * transform,
+ controlPoint(2) * transform,
+ controlPoint(3) * transform);
+}
+
+static Coord bezier_length_internal(std::vector<Point> &v1, Coord tolerance, int level)
+{
+ /* The Bezier length algorithm used in 2Geom utilizes a simple fact:
+ * the Bezier curve is longer than the distance between its endpoints
+ * but shorter than the length of the polyline formed by its control
+ * points. When the difference between the two values is smaller than the
+ * error tolerance, we can be sure that the true value is no further than
+ * 0.5 * tolerance from their arithmetic mean. When it's larger, we recursively
+ * subdivide the Bezier curve into two parts and add their lengths.
+ *
+ * We cap the maximum number of subdivisions at 256, which corresponds to 8 levels.
+ */
+ Coord lower = distance(v1.front(), v1.back());
+ Coord upper = 0.0;
+ for (size_t i = 0; i < v1.size() - 1; ++i) {
+ upper += distance(v1[i], v1[i+1]);
+ }
+ if (upper - lower <= 2*tolerance || level >= 8) {
+ return (lower + upper) / 2;
+ }
+
+
+ std::vector<Point> v2 = v1;
+
+ /* Compute the right subdivision directly in v1 and the left one in v2.
+ * Explanation of the algorithm used:
+ * We have to compute the left and right edges of this triangle in which
+ * the top row are the control points of the Bezier curve, and each cell
+ * is equal to the arithmetic mean of the cells directly above it
+ * to the right and left. This corresponds to subdividing the Bezier curve
+ * at time value 0.5: the left edge has the control points of the first
+ * portion of the Bezier curve and the right edge - the second one.
+ * In the example we subdivide a curve with 5 control points (order 4).
+ *
+ * Start:
+ * 0 1 2 3 4
+ * ? ? ? ?
+ * ? ? ?
+ * ? ?
+ * ?
+ * # means we have overwritten the value, ? means we don't know
+ * the value yet. Numbers mean the value is at i-th position in the vector.
+ *
+ * After loop with i==1
+ * # 1 2 3 4
+ * 0 ? ? ? -> write 0 to v2[1]
+ * ? ? ?
+ * ? ?
+ * ?
+ *
+ * After loop with i==2
+ * # # 2 3 4
+ * # 1 ? ?
+ * 0 ? ? -> write 0 to v2[2]
+ * ? ?
+ * ?
+ *
+ * After loop with i==3
+ * # # # 3 4
+ * # # 2 ?
+ * # 1 ?
+ * 0 ? -> write 0 to v2[3]
+ * ?
+ *
+ * After loop with i==4, we have the right edge of the triangle in v1,
+ * and we write the last value needed for the left edge in v2[4].
+ */
+
+ for (size_t i = 1; i < v1.size(); ++i) {
+ for (size_t j = i; j > 0; --j) {
+ v1[j-1] = 0.5 * (v1[j-1] + v1[j]);
+ }
+ v2[i] = v1[0];
+ }
+
+ return bezier_length_internal(v1, 0.5 * tolerance, level + 1) +
+ bezier_length_internal(v2, 0.5 * tolerance, level + 1);
+}
+
+/** @brief Compute the length of a bezier curve given by a vector of its control points
+ * @relatesalso BezierCurve */
+Coord bezier_length(std::vector<Point> const &points, Coord tolerance)
+{
+ if (points.size() < 2) return 0.0;
+ std::vector<Point> v1 = points;
+ return bezier_length_internal(v1, tolerance, 0);
+}
+
+static Coord bezier_length_internal(Point a0, Point a1, Point a2, Coord tolerance, int level)
+{
+ Coord lower = distance(a0, a2);
+ Coord upper = distance(a0, a1) + distance(a1, a2);
+
+ if (upper - lower <= 2*tolerance || level >= 8) {
+ return (lower + upper) / 2;
+ }
+
+ Point // Casteljau subdivision
+ // b0 = a0,
+ // c0 = a2,
+ b1 = 0.5*(a0 + a1),
+ c1 = 0.5*(a1 + a2),
+ b2 = 0.5*(b1 + c1); // == c2
+ return bezier_length_internal(a0, b1, b2, 0.5 * tolerance, level + 1) +
+ bezier_length_internal(b2, c1, a2, 0.5 * tolerance, level + 1);
+}
+
+/** @brief Compute the length of a quadratic bezier curve given by its control points
+ * @relatesalso QuadraticBezier */
+Coord bezier_length(Point a0, Point a1, Point a2, Coord tolerance)
+{
+ return bezier_length_internal(a0, a1, a2, tolerance, 0);
+}
+
+static Coord bezier_length_internal(Point a0, Point a1, Point a2, Point a3, Coord tolerance, int level)
+{
+ Coord lower = distance(a0, a3);
+ Coord upper = distance(a0, a1) + distance(a1, a2) + distance(a2, a3);
+
+ if (upper - lower <= 2*tolerance || level >= 8) {
+ return (lower + upper) / 2;
+ }
+
+ Point // Casteljau subdivision
+ // b0 = a0,
+ // c0 = a3,
+ b1 = 0.5*(a0 + a1),
+ t0 = 0.5*(a1 + a2),
+ c1 = 0.5*(a2 + a3),
+ b2 = 0.5*(b1 + t0),
+ c2 = 0.5*(t0 + c1),
+ b3 = 0.5*(b2 + c2); // == c3
+ return bezier_length_internal(a0, b1, b2, b3, 0.5 * tolerance, level + 1) +
+ bezier_length_internal(b3, c2, c1, a3, 0.5 * tolerance, level + 1);
+}
+
+/** @brief Compute the length of a cubic bezier curve given by its control points
+ * @relatesalso CubicBezier */
+Coord bezier_length(Point a0, Point a1, Point a2, Point a3, Coord tolerance)
+{
+ return bezier_length_internal(a0, a1, a2, a3, tolerance, 0);
+}
+
+} // end namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/bezier-utils.cpp b/src/3rdparty/2geom/src/2geom/bezier-utils.cpp
new file mode 100644
index 0000000..181b5b3
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/bezier-utils.cpp
@@ -0,0 +1,997 @@
+/* Bezier interpolation for inkscape drawing code.
+ *
+ * Original code published in:
+ * An Algorithm for Automatically Fitting Digitized Curves
+ * by Philip J. Schneider
+ * "Graphics Gems", Academic Press, 1990
+ *
+ * Authors:
+ * Philip J. Schneider
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Peter Moulder <pmoulder@mail.csse.monash.edu.au>
+ *
+ * Copyright (C) 1990 Philip J. Schneider
+ * Copyright (C) 2001 Lauris Kaplinski
+ * Copyright (C) 2001 Ximian, Inc.
+ * Copyright (C) 2003,2004 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#define SP_HUGE 1e5
+#define noBEZIER_DEBUG
+
+#ifdef HAVE_IEEEFP_H
+# include <ieeefp.h>
+#endif
+
+#include <2geom/bezier-utils.h>
+#include <2geom/math-utils.h>
+#include <assert.h>
+
+namespace Geom {
+
+/* Forward declarations */
+static void generate_bezier(Point b[], Point const d[], double const u[], unsigned len,
+ Point const &tHat1, Point const &tHat2, double tolerance_sq);
+static void estimate_lengths(Point bezier[],
+ Point const data[], double const u[], unsigned len,
+ Point const &tHat1, Point const &tHat2);
+static void estimate_bi(Point b[4], unsigned ei,
+ Point const data[], double const u[], unsigned len);
+static void reparameterize(Point const d[], unsigned len, double u[], Point const bezCurve[]);
+static double NewtonRaphsonRootFind(Point const Q[], Point const &P, double u);
+static Point darray_center_tangent(Point const d[], unsigned center, unsigned length);
+static Point darray_right_tangent(Point const d[], unsigned const len);
+static unsigned copy_without_nans_or_adjacent_duplicates(Point const src[], unsigned src_len, Point dest[]);
+static void chord_length_parameterize(Point const d[], double u[], unsigned len);
+static double compute_max_error_ratio(Point const d[], double const u[], unsigned len,
+ Point const bezCurve[], double tolerance,
+ unsigned *splitPoint);
+static double compute_hook(Point const &a, Point const &b, double const u, Point const bezCurve[],
+ double const tolerance);
+
+
+static Point const unconstrained_tangent(0, 0);
+
+
+/*
+ * B0, B1, B2, B3 : Bezier multipliers
+ */
+
+#define B0(u) ( ( 1.0 - u ) * ( 1.0 - u ) * ( 1.0 - u ) )
+#define B1(u) ( 3 * u * ( 1.0 - u ) * ( 1.0 - u ) )
+#define B2(u) ( 3 * u * u * ( 1.0 - u ) )
+#define B3(u) ( u * u * u )
+
+#ifdef BEZIER_DEBUG
+# define DOUBLE_ASSERT(x) assert( ( (x) > -SP_HUGE ) && ( (x) < SP_HUGE ) )
+# define BEZIER_ASSERT(b) do { \
+ DOUBLE_ASSERT((b)[0][X]); DOUBLE_ASSERT((b)[0][Y]); \
+ DOUBLE_ASSERT((b)[1][X]); DOUBLE_ASSERT((b)[1][Y]); \
+ DOUBLE_ASSERT((b)[2][X]); DOUBLE_ASSERT((b)[2][Y]); \
+ DOUBLE_ASSERT((b)[3][X]); DOUBLE_ASSERT((b)[3][Y]); \
+ } while(0)
+#else
+# define DOUBLE_ASSERT(x) do { } while(0)
+# define BEZIER_ASSERT(b) do { } while(0)
+#endif
+
+
+/**
+ * Fit a single-segment Bezier curve to a set of digitized points.
+ *
+ * \return Number of segments generated, or -1 on error.
+ */
+int
+bezier_fit_cubic(Point *bezier, Point const *data, int len, double error)
+{
+ return bezier_fit_cubic_r(bezier, data, len, error, 1);
+}
+
+/**
+ * Fit a multi-segment Bezier curve to a set of digitized points, with
+ * possible weedout of identical points and NaNs.
+ *
+ * \param max_beziers Maximum number of generated segments
+ * \param Result array, must be large enough for n. segments * 4 elements.
+ *
+ * \return Number of segments generated, or -1 on error.
+ */
+int
+bezier_fit_cubic_r(Point bezier[], Point const data[], int const len, double const error, unsigned const max_beziers)
+{
+ if(bezier == NULL ||
+ data == NULL ||
+ len <= 0 ||
+ max_beziers >= (1ul << (31 - 2 - 1 - 3)))
+ return -1;
+
+ Point *uniqued_data = new Point[len];
+ unsigned uniqued_len = copy_without_nans_or_adjacent_duplicates(data, len, uniqued_data);
+
+ if ( uniqued_len < 2 ) {
+ delete[] uniqued_data;
+ return 0;
+ }
+
+ /* Call fit-cubic function with recursion. */
+ int const ret = bezier_fit_cubic_full(bezier, NULL, uniqued_data, uniqued_len,
+ unconstrained_tangent, unconstrained_tangent,
+ error, max_beziers);
+ delete[] uniqued_data;
+ return ret;
+}
+
+/**
+ * Copy points from src to dest, filter out points containing NaN and
+ * adjacent points with equal x and y.
+ * \return length of dest
+ */
+static unsigned
+copy_without_nans_or_adjacent_duplicates(Point const src[], unsigned src_len, Point dest[])
+{
+ unsigned si = 0;
+ for (;;) {
+ if ( si == src_len ) {
+ return 0;
+ }
+ if (!std::isnan(src[si][X]) &&
+ !std::isnan(src[si][Y])) {
+ dest[0] = Point(src[si]);
+ ++si;
+ break;
+ }
+ si++;
+ }
+ unsigned di = 0;
+ for (; si < src_len; ++si) {
+ Point const src_pt = Point(src[si]);
+ if ( src_pt != dest[di]
+ && !std::isnan(src_pt[X])
+ && !std::isnan(src_pt[Y])) {
+ dest[++di] = src_pt;
+ }
+ }
+ unsigned dest_len = di + 1;
+ assert( dest_len <= src_len );
+ return dest_len;
+}
+
+/**
+ * Fit a multi-segment Bezier curve to a set of digitized points, without
+ * possible weedout of identical points and NaNs.
+ *
+ * \pre data is uniqued, i.e. not exist i: data[i] == data[i + 1].
+ * \param max_beziers Maximum number of generated segments
+ * \param Result array, must be large enough for n. segments * 4 elements.
+ */
+int
+bezier_fit_cubic_full(Point bezier[], int split_points[],
+ Point const data[], int const len,
+ Point const &tHat1, Point const &tHat2,
+ double const error, unsigned const max_beziers)
+{
+ if(!(bezier != NULL) ||
+ !(data != NULL) ||
+ !(len > 0) ||
+ !(max_beziers >= 1) ||
+ !(error >= 0.0))
+ return -1;
+
+ if ( len < 2 ) return 0;
+
+ if ( len == 2 ) {
+ /* We have 2 points, which can be fitted trivially. */
+ bezier[0] = data[0];
+ bezier[3] = data[len - 1];
+ double const dist = distance(bezier[0], bezier[3]) / 3.0;
+ if (std::isnan(dist)) {
+ /* Numerical problem, fall back to straight line segment. */
+ bezier[1] = bezier[0];
+ bezier[2] = bezier[3];
+ } else {
+ bezier[1] = ( is_zero(tHat1)
+ ? ( 2 * bezier[0] + bezier[3] ) / 3.
+ : bezier[0] + dist * tHat1 );
+ bezier[2] = ( is_zero(tHat2)
+ ? ( bezier[0] + 2 * bezier[3] ) / 3.
+ : bezier[3] + dist * tHat2 );
+ }
+ BEZIER_ASSERT(bezier);
+ return 1;
+ }
+
+ /* Parameterize points, and attempt to fit curve */
+ unsigned splitPoint; /* Point to split point set at. */
+ bool is_corner;
+ {
+ double *u = new double[len];
+ chord_length_parameterize(data, u, len);
+ if ( u[len - 1] == 0.0 ) {
+ /* Zero-length path: every point in data[] is the same.
+ *
+ * (Clients aren't allowed to pass such data; handling the case is defensive
+ * programming.)
+ */
+ delete[] u;
+ return 0;
+ }
+
+ generate_bezier(bezier, data, u, len, tHat1, tHat2, error);
+ reparameterize(data, len, u, bezier);
+
+ /* Find max deviation of points to fitted curve. */
+ double const tolerance = sqrt(error + 1e-9);
+ double maxErrorRatio = compute_max_error_ratio(data, u, len, bezier, tolerance, &splitPoint);
+
+ if ( fabs(maxErrorRatio) <= 1.0 ) {
+ BEZIER_ASSERT(bezier);
+ delete[] u;
+ return 1;
+ }
+
+ /* If error not too large, then try some reparameterization and iteration. */
+ if ( 0.0 <= maxErrorRatio && maxErrorRatio <= 3.0 ) {
+ int const maxIterations = 4; /* std::max times to try iterating */
+ for (int i = 0; i < maxIterations; i++) {
+ generate_bezier(bezier, data, u, len, tHat1, tHat2, error);
+ reparameterize(data, len, u, bezier);
+ maxErrorRatio = compute_max_error_ratio(data, u, len, bezier, tolerance, &splitPoint);
+ if ( fabs(maxErrorRatio) <= 1.0 ) {
+ BEZIER_ASSERT(bezier);
+ delete[] u;
+ return 1;
+ }
+ }
+ }
+ delete[] u;
+ is_corner = (maxErrorRatio < 0);
+ }
+
+ if (is_corner) {
+ assert(splitPoint < unsigned(len));
+ if (splitPoint == 0) {
+ if (is_zero(tHat1)) {
+ /* Got spike even with unconstrained initial tangent. */
+ ++splitPoint;
+ } else {
+ return bezier_fit_cubic_full(bezier, split_points, data, len, unconstrained_tangent, tHat2,
+ error, max_beziers);
+ }
+ } else if (splitPoint == unsigned(len - 1)) {
+ if (is_zero(tHat2)) {
+ /* Got spike even with unconstrained final tangent. */
+ --splitPoint;
+ } else {
+ return bezier_fit_cubic_full(bezier, split_points, data, len, tHat1, unconstrained_tangent,
+ error, max_beziers);
+ }
+ }
+ }
+
+ if ( 1 < max_beziers ) {
+ /*
+ * Fitting failed -- split at max error point and fit recursively
+ */
+ unsigned const rec_max_beziers1 = max_beziers - 1;
+
+ Point recTHat2, recTHat1;
+ if (is_corner) {
+ if(!(0 < splitPoint && splitPoint < unsigned(len - 1)))
+ return -1;
+ recTHat1 = recTHat2 = unconstrained_tangent;
+ } else {
+ /* Unit tangent vector at splitPoint. */
+ recTHat2 = darray_center_tangent(data, splitPoint, len);
+ recTHat1 = -recTHat2;
+ }
+ int const nsegs1 = bezier_fit_cubic_full(bezier, split_points, data, splitPoint + 1,
+ tHat1, recTHat2, error, rec_max_beziers1);
+ if ( nsegs1 < 0 ) {
+#ifdef BEZIER_DEBUG
+ g_print("fit_cubic[1]: recursive call failed\n");
+#endif
+ return -1;
+ }
+ assert( nsegs1 != 0 );
+ if (split_points != NULL) {
+ split_points[nsegs1 - 1] = splitPoint;
+ }
+ unsigned const rec_max_beziers2 = max_beziers - nsegs1;
+ int const nsegs2 = bezier_fit_cubic_full(bezier + nsegs1*4,
+ ( split_points == NULL
+ ? NULL
+ : split_points + nsegs1 ),
+ data + splitPoint, len - splitPoint,
+ recTHat1, tHat2, error, rec_max_beziers2);
+ if ( nsegs2 < 0 ) {
+#ifdef BEZIER_DEBUG
+ g_print("fit_cubic[2]: recursive call failed\n");
+#endif
+ return -1;
+ }
+
+#ifdef BEZIER_DEBUG
+ g_print("fit_cubic: success[nsegs: %d+%d=%d] on max_beziers:%u\n",
+ nsegs1, nsegs2, nsegs1 + nsegs2, max_beziers);
+#endif
+ return nsegs1 + nsegs2;
+ } else {
+ return -1;
+ }
+}
+
+
+/**
+ * Fill in \a bezier[] based on the given data and tangent requirements, using
+ * a least-squares fit.
+ *
+ * Each of tHat1 and tHat2 should be either a zero vector or a unit vector.
+ * If it is zero, then bezier[1 or 2] is estimated without constraint; otherwise,
+ * it bezier[1 or 2] is placed in the specified direction from bezier[0 or 3].
+ *
+ * \param tolerance_sq Used only for an initial guess as to tangent directions
+ * when \a tHat1 or \a tHat2 is zero.
+ */
+static void
+generate_bezier(Point bezier[],
+ Point const data[], double const u[], unsigned const len,
+ Point const &tHat1, Point const &tHat2,
+ double const tolerance_sq)
+{
+ bool const est1 = is_zero(tHat1);
+ bool const est2 = is_zero(tHat2);
+ Point est_tHat1( est1
+ ? darray_left_tangent(data, len, tolerance_sq)
+ : tHat1 );
+ Point est_tHat2( est2
+ ? darray_right_tangent(data, len, tolerance_sq)
+ : tHat2 );
+ estimate_lengths(bezier, data, u, len, est_tHat1, est_tHat2);
+ /* We find that darray_right_tangent tends to produce better results
+ for our current freehand tool than full estimation. */
+ if (est1) {
+ estimate_bi(bezier, 1, data, u, len);
+ if (bezier[1] != bezier[0]) {
+ est_tHat1 = unit_vector(bezier[1] - bezier[0]);
+ }
+ estimate_lengths(bezier, data, u, len, est_tHat1, est_tHat2);
+ }
+}
+
+
+static void
+estimate_lengths(Point bezier[],
+ Point const data[], double const uPrime[], unsigned const len,
+ Point const &tHat1, Point const &tHat2)
+{
+ double C[2][2]; /* Matrix C. */
+ double X[2]; /* Matrix X. */
+
+ /* Create the C and X matrices. */
+ C[0][0] = 0.0;
+ C[0][1] = 0.0;
+ C[1][0] = 0.0;
+ C[1][1] = 0.0;
+ X[0] = 0.0;
+ X[1] = 0.0;
+
+ /* First and last control points of the Bezier curve are positioned exactly at the first and
+ last data points. */
+ bezier[0] = data[0];
+ bezier[3] = data[len - 1];
+
+ for (unsigned i = 0; i < len; i++) {
+ /* Bezier control point coefficients. */
+ double const b0 = B0(uPrime[i]);
+ double const b1 = B1(uPrime[i]);
+ double const b2 = B2(uPrime[i]);
+ double const b3 = B3(uPrime[i]);
+
+ /* rhs for eqn */
+ Point const a1 = b1 * tHat1;
+ Point const a2 = b2 * tHat2;
+
+ C[0][0] += dot(a1, a1);
+ C[0][1] += dot(a1, a2);
+ C[1][0] = C[0][1];
+ C[1][1] += dot(a2, a2);
+
+ /* Additional offset to the data point from the predicted point if we were to set bezier[1]
+ to bezier[0] and bezier[2] to bezier[3]. */
+ Point const shortfall
+ = ( data[i]
+ - ( ( b0 + b1 ) * bezier[0] )
+ - ( ( b2 + b3 ) * bezier[3] ) );
+ X[0] += dot(a1, shortfall);
+ X[1] += dot(a2, shortfall);
+ }
+
+ /* We've constructed a pair of equations in the form of a matrix product C * alpha = X.
+ Now solve for alpha. */
+ double alpha_l, alpha_r;
+
+ /* Compute the determinants of C and X. */
+ double const det_C0_C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1];
+ if ( det_C0_C1 != 0 ) {
+ /* Apparently Kramer's rule. */
+ double const det_C0_X = C[0][0] * X[1] - C[0][1] * X[0];
+ double const det_X_C1 = X[0] * C[1][1] - X[1] * C[0][1];
+ alpha_l = det_X_C1 / det_C0_C1;
+ alpha_r = det_C0_X / det_C0_C1;
+ } else {
+ /* The matrix is under-determined. Try requiring alpha_l == alpha_r.
+ *
+ * One way of implementing the constraint alpha_l == alpha_r is to treat them as the same
+ * variable in the equations. We can do this by adding the columns of C to form a single
+ * column, to be multiplied by alpha to give the column vector X.
+ *
+ * We try each row in turn.
+ */
+ double const c0 = C[0][0] + C[0][1];
+ if (c0 != 0) {
+ alpha_l = alpha_r = X[0] / c0;
+ } else {
+ double const c1 = C[1][0] + C[1][1];
+ if (c1 != 0) {
+ alpha_l = alpha_r = X[1] / c1;
+ } else {
+ /* Let the below code handle this. */
+ alpha_l = alpha_r = 0.;
+ }
+ }
+ }
+
+ /* If alpha negative, use the Wu/Barsky heuristic (see text). (If alpha is 0, you get
+ coincident control points that lead to divide by zero in any subsequent
+ NewtonRaphsonRootFind() call.) */
+ /// \todo Check whether this special-casing is necessary now that
+ /// NewtonRaphsonRootFind handles non-positive denominator.
+ if ( alpha_l < 1.0e-6 ||
+ alpha_r < 1.0e-6 )
+ {
+ alpha_l = alpha_r = distance(data[0], data[len-1]) / 3.0;
+ }
+
+ /* Control points 1 and 2 are positioned an alpha distance out on the tangent vectors, left and
+ right, respectively. */
+ bezier[1] = alpha_l * tHat1 + bezier[0];
+ bezier[2] = alpha_r * tHat2 + bezier[3];
+
+ return;
+}
+
+static double lensq(Point const p) {
+ return dot(p, p);
+}
+
+static void
+estimate_bi(Point bezier[4], unsigned const ei,
+ Point const data[], double const u[], unsigned const len)
+{
+ if(!(1 <= ei && ei <= 2))
+ return;
+ unsigned const oi = 3 - ei;
+ double num[2] = {0., 0.};
+ double den = 0.;
+ for (unsigned i = 0; i < len; ++i) {
+ double const ui = u[i];
+ double const b[4] = {
+ B0(ui),
+ B1(ui),
+ B2(ui),
+ B3(ui)
+ };
+
+ for (unsigned d = 0; d < 2; ++d) {
+ num[d] += b[ei] * (b[0] * bezier[0][d] +
+ b[oi] * bezier[oi][d] +
+ b[3] * bezier[3][d] +
+ - data[i][d]);
+ }
+ den -= b[ei] * b[ei];
+ }
+
+ if (den != 0.) {
+ for (unsigned d = 0; d < 2; ++d) {
+ bezier[ei][d] = num[d] / den;
+ }
+ } else {
+ bezier[ei] = ( oi * bezier[0] + ei * bezier[3] ) / 3.;
+ }
+}
+
+/**
+ * Given set of points and their parameterization, try to find a better assignment of parameter
+ * values for the points.
+ *
+ * \param d Array of digitized points.
+ * \param u Current parameter values.
+ * \param bezCurve Current fitted curve.
+ * \param len Number of values in both d and u arrays.
+ * Also the size of the array that is allocated for return.
+ */
+static void
+reparameterize(Point const d[],
+ unsigned const len,
+ double u[],
+ Point const bezCurve[])
+{
+ assert( 2 <= len );
+
+ unsigned const last = len - 1;
+ assert( bezCurve[0] == d[0] );
+ assert( bezCurve[3] == d[last] );
+ assert( u[0] == 0.0 );
+ assert( u[last] == 1.0 );
+ /* Otherwise, consider including 0 and last in the below loop. */
+
+ for (unsigned i = 1; i < last; i++) {
+ u[i] = NewtonRaphsonRootFind(bezCurve, d[i], u[i]);
+ }
+}
+
+/**
+ * Use Newton-Raphson iteration to find better root.
+ *
+ * \param Q Current fitted curve
+ * \param P Digitized point
+ * \param u Parameter value for "P"
+ *
+ * \return Improved u
+ */
+static double
+NewtonRaphsonRootFind(Point const Q[], Point const &P, double const u)
+{
+ assert( 0.0 <= u );
+ assert( u <= 1.0 );
+
+ /* Generate control vertices for Q'. */
+ Point Q1[3];
+ for (unsigned i = 0; i < 3; i++) {
+ Q1[i] = 3.0 * ( Q[i+1] - Q[i] );
+ }
+
+ /* Generate control vertices for Q''. */
+ Point Q2[2];
+ for (unsigned i = 0; i < 2; i++) {
+ Q2[i] = 2.0 * ( Q1[i+1] - Q1[i] );
+ }
+
+ /* Compute Q(u), Q'(u) and Q''(u). */
+ Point const Q_u = bezier_pt(3, Q, u);
+ Point const Q1_u = bezier_pt(2, Q1, u);
+ Point const Q2_u = bezier_pt(1, Q2, u);
+
+ /* Compute f(u)/f'(u), where f is the derivative wrt u of distsq(u) = 0.5 * the square of the
+ distance from P to Q(u). Here we're using Newton-Raphson to find a stationary point in the
+ distsq(u), hopefully corresponding to a local minimum in distsq (and hence a local minimum
+ distance from P to Q(u)). */
+ Point const diff = Q_u - P;
+ double numerator = dot(diff, Q1_u);
+ double denominator = dot(Q1_u, Q1_u) + dot(diff, Q2_u);
+
+ double improved_u;
+ if ( denominator > 0. ) {
+ /* One iteration of Newton-Raphson:
+ improved_u = u - f(u)/f'(u) */
+ improved_u = u - ( numerator / denominator );
+ } else {
+ /* Using Newton-Raphson would move in the wrong direction (towards a local maximum rather
+ than local minimum), so we move an arbitrary amount in the right direction. */
+ if ( numerator > 0. ) {
+ improved_u = u * .98 - .01;
+ } else if ( numerator < 0. ) {
+ /* Deliberately asymmetrical, to reduce the chance of cycling. */
+ improved_u = .031 + u * .98;
+ } else {
+ improved_u = u;
+ }
+ }
+
+ if (!std::isfinite(improved_u)) {
+ improved_u = u;
+ } else if ( improved_u < 0.0 ) {
+ improved_u = 0.0;
+ } else if ( improved_u > 1.0 ) {
+ improved_u = 1.0;
+ }
+
+ /* Ensure that improved_u isn't actually worse. */
+ {
+ double const diff_lensq = lensq(diff);
+ for (double proportion = .125; ; proportion += .125) {
+ if ( lensq( bezier_pt(3, Q, improved_u) - P ) > diff_lensq ) {
+ if ( proportion > 1.0 ) {
+ //g_warning("found proportion %g", proportion);
+ improved_u = u;
+ break;
+ }
+ improved_u = ( ( 1 - proportion ) * improved_u +
+ proportion * u );
+ } else {
+ break;
+ }
+ }
+ }
+
+ DOUBLE_ASSERT(improved_u);
+ return improved_u;
+}
+
+/**
+ * Evaluate a Bezier curve at parameter value \a t.
+ *
+ * \param degree The degree of the Bezier curve: 3 for cubic, 2 for quadratic etc. Must be less
+ * than 4.
+ * \param V The control points for the Bezier curve. Must have (\a degree+1)
+ * elements.
+ * \param t The "parameter" value, specifying whereabouts along the curve to
+ * evaluate. Typically in the range [0.0, 1.0].
+ *
+ * Let s = 1 - t.
+ * BezierII(1, V) gives (s, t) * V, i.e. t of the way
+ * from V[0] to V[1].
+ * BezierII(2, V) gives (s**2, 2*s*t, t**2) * V.
+ * BezierII(3, V) gives (s**3, 3 s**2 t, 3s t**2, t**3) * V.
+ *
+ * The derivative of BezierII(i, V) with respect to t
+ * is i * BezierII(i-1, V'), where for all j, V'[j] =
+ * V[j + 1] - V[j].
+ */
+Point
+bezier_pt(unsigned const degree, Point const V[], double const t)
+{
+ /** Pascal's triangle. */
+ static int const pascal[4][4] = {{1, 0, 0, 0},
+ {1, 1, 0, 0},
+ {1, 2, 1, 0},
+ {1, 3, 3, 1}};
+ assert( degree < 4);
+ double const s = 1.0 - t;
+
+ /* Calculate powers of t and s. */
+ double spow[4];
+ double tpow[4];
+ spow[0] = 1.0; spow[1] = s;
+ tpow[0] = 1.0; tpow[1] = t;
+ for (unsigned i = 1; i < degree; ++i) {
+ spow[i + 1] = spow[i] * s;
+ tpow[i + 1] = tpow[i] * t;
+ }
+
+ Point ret = spow[degree] * V[0];
+ for (unsigned i = 1; i <= degree; ++i) {
+ ret += pascal[degree][i] * spow[degree - i] * tpow[i] * V[i];
+ }
+ return ret;
+}
+
+/*
+ * ComputeLeftTangent, ComputeRightTangent, ComputeCenterTangent :
+ * Approximate unit tangents at endpoints and "center" of digitized curve
+ */
+
+/**
+ * Estimate the (forward) tangent at point d[first + 0.5].
+ *
+ * Unlike the center and right versions, this calculates the tangent in
+ * the way one might expect, i.e., wrt increasing index into d.
+ * \pre (2 \<= len) and (d[0] != d[1]).
+ **/
+Point
+darray_left_tangent(Point const d[], unsigned const len)
+{
+ assert( len >= 2 );
+ assert( d[0] != d[1] );
+ return unit_vector( d[1] - d[0] );
+}
+
+/**
+ * Estimates the (backward) tangent at d[last - 0.5].
+ *
+ * \note The tangent is "backwards", i.e. it is with respect to
+ * decreasing index rather than increasing index.
+ *
+ * \pre 2 \<= len.
+ * \pre d[len - 1] != d[len - 2].
+ * \pre all[p in d] in_svg_plane(p).
+ */
+static Point
+darray_right_tangent(Point const d[], unsigned const len)
+{
+ assert( 2 <= len );
+ unsigned const last = len - 1;
+ unsigned const prev = last - 1;
+ assert( d[last] != d[prev] );
+ return unit_vector( d[prev] - d[last] );
+}
+
+/**
+ * Estimate the (forward) tangent at point d[0].
+ *
+ * Unlike the center and right versions, this calculates the tangent in
+ * the way one might expect, i.e., wrt increasing index into d.
+ *
+ * \pre 2 \<= len.
+ * \pre d[0] != d[1].
+ * \pre all[p in d] in_svg_plane(p).
+ * \post is_unit_vector(ret).
+ **/
+Point
+darray_left_tangent(Point const d[], unsigned const len, double const tolerance_sq)
+{
+ assert( 2 <= len );
+ assert( 0 <= tolerance_sq );
+ for (unsigned i = 1;;) {
+ Point const pi(d[i]);
+ Point const t(pi - d[0]);
+ double const distsq = dot(t, t);
+ if ( tolerance_sq < distsq ) {
+ return unit_vector(t);
+ }
+ ++i;
+ if (i == len) {
+ return ( distsq == 0
+ ? darray_left_tangent(d, len)
+ : unit_vector(t) );
+ }
+ }
+}
+
+/**
+ * Estimates the (backward) tangent at d[last].
+ *
+ * \note The tangent is "backwards", i.e. it is with respect to
+ * decreasing index rather than increasing index.
+ *
+ * \pre 2 \<= len.
+ * \pre d[len - 1] != d[len - 2].
+ * \pre all[p in d] in_svg_plane(p).
+ */
+Point
+darray_right_tangent(Point const d[], unsigned const len, double const tolerance_sq)
+{
+ assert( 2 <= len );
+ assert( 0 <= tolerance_sq );
+ unsigned const last = len - 1;
+ for (unsigned i = last - 1;; i--) {
+ Point const pi(d[i]);
+ Point const t(pi - d[last]);
+ double const distsq = dot(t, t);
+ if ( tolerance_sq < distsq ) {
+ return unit_vector(t);
+ }
+ if (i == 0) {
+ return ( distsq == 0
+ ? darray_right_tangent(d, len)
+ : unit_vector(t) );
+ }
+ }
+}
+
+/**
+ * Estimates the (backward) tangent at d[center], by averaging the two
+ * segments connected to d[center] (and then normalizing the result).
+ *
+ * \note The tangent is "backwards", i.e. it is with respect to
+ * decreasing index rather than increasing index.
+ *
+ * \pre (0 \< center \< len - 1) and d is uniqued (at least in
+ * the immediate vicinity of \a center).
+ */
+static Point
+darray_center_tangent(Point const d[],
+ unsigned const center,
+ unsigned const len)
+{
+ assert( center != 0 );
+ assert( center < len - 1 );
+
+ Point ret;
+ if ( d[center + 1] == d[center - 1] ) {
+ /* Rotate 90 degrees in an arbitrary direction. */
+ Point const diff = d[center] - d[center - 1];
+ ret = rot90(diff);
+ } else {
+ ret = d[center - 1] - d[center + 1];
+ }
+ ret.normalize();
+ return ret;
+}
+
+
+/**
+ * Assign parameter values to digitized points using relative distances between points.
+ *
+ * \pre Parameter array u must have space for \a len items.
+ */
+static void
+chord_length_parameterize(Point const d[], double u[], unsigned const len)
+{
+ if(!( 2 <= len ))
+ return;
+
+ /* First let u[i] equal the distance travelled along the path from d[0] to d[i]. */
+ u[0] = 0.0;
+ for (unsigned i = 1; i < len; i++) {
+ double const dist = distance(d[i], d[i-1]);
+ u[i] = u[i-1] + dist;
+ }
+
+ /* Then scale to [0.0 .. 1.0]. */
+ double tot_len = u[len - 1];
+ if(!( tot_len != 0 ))
+ return;
+ if (std::isfinite(tot_len)) {
+ for (unsigned i = 1; i < len; ++i) {
+ u[i] /= tot_len;
+ }
+ } else {
+ /* We could do better, but this probably never happens anyway. */
+ for (unsigned i = 1; i < len; ++i) {
+ u[i] = i / (double) ( len - 1 );
+ }
+ }
+
+ /** \todo
+ * It's been reported that u[len - 1] can differ from 1.0 on some
+ * systems (amd64), despite it having been calculated as x / x where x
+ * is isFinite and non-zero.
+ */
+ if (u[len - 1] != 1) {
+ double const diff = u[len - 1] - 1;
+ if (fabs(diff) > 1e-13) {
+ assert(0); // No warnings in 2geom
+ //g_warning("u[len - 1] = %19g (= 1 + %19g), expecting exactly 1",
+ // u[len - 1], diff);
+ }
+ u[len - 1] = 1;
+ }
+
+#ifdef BEZIER_DEBUG
+ assert( u[0] == 0.0 && u[len - 1] == 1.0 );
+ for (unsigned i = 1; i < len; i++) {
+ assert( u[i] >= u[i-1] );
+ }
+#endif
+}
+
+
+
+
+/**
+ * Find the maximum squared distance of digitized points to fitted curve, and (if this maximum
+ * error is non-zero) set \a *splitPoint to the corresponding index.
+ *
+ * \pre 2 \<= len.
+ * \pre u[0] == 0.
+ * \pre u[len - 1] == 1.0.
+ * \post ((ret == 0.0)
+ * || ((*splitPoint \< len - 1)
+ * \&\& (*splitPoint != 0 || ret \< 0.0))).
+ */
+static double
+compute_max_error_ratio(Point const d[], double const u[], unsigned const len,
+ Point const bezCurve[], double const tolerance,
+ unsigned *const splitPoint)
+{
+ assert( 2 <= len );
+ unsigned const last = len - 1;
+ assert( bezCurve[0] == d[0] );
+ assert( bezCurve[3] == d[last] );
+ assert( u[0] == 0.0 );
+ assert( u[last] == 1.0 );
+ /* I.e. assert that the error for the first & last points is zero.
+ * Otherwise we should include those points in the below loop.
+ * The assertion is also necessary to ensure 0 < splitPoint < last.
+ */
+
+ double maxDistsq = 0.0; /* Maximum error */
+ double max_hook_ratio = 0.0;
+ unsigned snap_end = 0;
+ Point prev = bezCurve[0];
+ for (unsigned i = 1; i <= last; i++) {
+ Point const curr = bezier_pt(3, bezCurve, u[i]);
+ double const distsq = lensq( curr - d[i] );
+ if ( distsq > maxDistsq ) {
+ maxDistsq = distsq;
+ *splitPoint = i;
+ }
+ double const hook_ratio = compute_hook(prev, curr, .5 * (u[i - 1] + u[i]), bezCurve, tolerance);
+ if (max_hook_ratio < hook_ratio) {
+ max_hook_ratio = hook_ratio;
+ snap_end = i;
+ }
+ prev = curr;
+ }
+
+ double const dist_ratio = sqrt(maxDistsq) / tolerance;
+ double ret;
+ if (max_hook_ratio <= dist_ratio) {
+ ret = dist_ratio;
+ } else {
+ assert(0 < snap_end);
+ ret = -max_hook_ratio;
+ *splitPoint = snap_end - 1;
+ }
+ assert( ret == 0.0
+ || ( ( *splitPoint < last )
+ && ( *splitPoint != 0 || ret < 0. ) ) );
+ return ret;
+}
+
+/**
+ * Whereas compute_max_error_ratio() checks for itself that each data point
+ * is near some point on the curve, this function checks that each point on
+ * the curve is near some data point (or near some point on the polyline
+ * defined by the data points, or something like that: we allow for a
+ * "reasonable curviness" from such a polyline). "Reasonable curviness"
+ * means we draw a circle centred at the midpoint of a..b, of radius
+ * proportional to the length |a - b|, and require that each point on the
+ * segment of bezCurve between the parameters of a and b be within that circle.
+ * If any point P on the bezCurve segment is outside of that allowable
+ * region (circle), then we return some metric that increases with the
+ * distance from P to the circle.
+ *
+ * Given that this is a fairly arbitrary criterion for finding appropriate
+ * places for sharp corners, we test only one point on bezCurve, namely
+ * the point on bezCurve with parameter halfway between our estimated
+ * parameters for a and b. (Alternatives are taking the farthest of a
+ * few parameters between those of a and b, or even using a variant of
+ * NewtonRaphsonFindRoot() for finding the maximum rather than minimum
+ * distance.)
+ */
+static double
+compute_hook(Point const &a, Point const &b, double const u, Point const bezCurve[],
+ double const tolerance)
+{
+ Point const P = bezier_pt(3, bezCurve, u);
+ double const dist = distance((a+b)*.5, P);
+ if (dist < tolerance) {
+ return 0;
+ }
+ double const allowed = distance(a, b) + tolerance;
+ return dist / allowed;
+ /** \todo
+ * effic: Hooks are very rare. We could start by comparing
+ * distsq, only resorting to the more expensive L2 in cases of
+ * uncertainty.
+ */
+}
+
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/bezier.cpp b/src/3rdparty/2geom/src/2geom/bezier.cpp
new file mode 100644
index 0000000..264b3c2
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/bezier.cpp
@@ -0,0 +1,415 @@
+/**
+ * @file
+ * @brief Bernstein-Bezier polynomial
+ *//*
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * Michael Sloan <mgsloan@gmail.com>
+ * Nathan Hurst <njh@njhurst.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2007-2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <2geom/bezier.h>
+#include <2geom/solver.h>
+#include <2geom/concepts.h>
+#include <2geom/choose.h>
+
+namespace Geom {
+
+std::vector<Coord> Bezier::valueAndDerivatives(Coord t, unsigned n_derivs) const {
+ /* This is inelegant, as it uses several extra stores. I think there might be a way to
+ * evaluate roughly in situ. */
+
+ // initialize return vector with zeroes, such that we only need to replace the non-zero derivs
+ std::vector<Coord> val_n_der(n_derivs + 1, Coord(0.0));
+
+ // initialize temp storage variables
+ std::valarray<Coord> d_(order()+1);
+ for(unsigned i = 0; i < size(); i++) {
+ d_[i] = c_[i];
+ }
+
+ unsigned nn = n_derivs + 1;
+ if(n_derivs > order()) {
+ nn = order()+1; // only calculate the non zero derivs
+ }
+ for(unsigned di = 0; di < nn; di++) {
+ //val_n_der[di] = (casteljau_subdivision(t, &d_[0], NULL, NULL, order() - di));
+ val_n_der[di] = bernstein_value_at(t, &d_[0], order() - di);
+ for(unsigned i = 0; i < order() - di; i++) {
+ d_[i] = (order()-di)*(d_[i+1] - d_[i]);
+ }
+ }
+
+ return val_n_der;
+}
+
+void Bezier::subdivide(Coord t, Bezier *left, Bezier *right) const
+{
+ if (left) {
+ left->c_.resize(size());
+ if (right) {
+ right->c_.resize(size());
+ casteljau_subdivision<double>(t, &const_cast<std::valarray<Coord>&>(c_)[0],
+ &left->c_[0], &right->c_[0], order());
+ } else {
+ casteljau_subdivision<double>(t, &const_cast<std::valarray<Coord>&>(c_)[0],
+ &left->c_[0], NULL, order());
+ }
+ } else if (right) {
+ right->c_.resize(size());
+ casteljau_subdivision<double>(t, &const_cast<std::valarray<Coord>&>(c_)[0],
+ NULL, &right->c_[0], order());
+ }
+}
+
+std::pair<Bezier, Bezier> Bezier::subdivide(Coord t) const
+{
+ std::pair<Bezier, Bezier> ret;
+ subdivide(t, &ret.first, &ret.second);
+ return ret;
+}
+
+std::vector<Coord> Bezier::roots() const
+{
+ std::vector<Coord> solutions;
+ find_bezier_roots(solutions, 0, 1);
+ std::sort(solutions.begin(), solutions.end());
+ return solutions;
+}
+
+std::vector<Coord> Bezier::roots(Interval const &ivl) const
+{
+ std::vector<Coord> solutions;
+ find_bernstein_roots(&const_cast<std::valarray<Coord>&>(c_)[0], order(), solutions, 0, ivl.min(), ivl.max());
+ std::sort(solutions.begin(), solutions.end());
+ return solutions;
+}
+
+Bezier Bezier::forward_difference(unsigned k) const
+{
+ Bezier fd(Order(order() - k));
+ int n = fd.size();
+
+ for (int i = 0; i < n; i++) {
+ fd[i] = 0;
+ int b = (i & 1) ? -1 : 1; // b = (-1)^j binomial(n, j - i)
+ for (int j = i; j < n; j++) {
+ fd[i] += c_[j] * b;
+ binomial_increment_k(b, n, j - i);
+ b = -b;
+ }
+ }
+ return fd;
+}
+
+Bezier Bezier::elevate_degree() const
+{
+ Bezier ed(Order(order()+1));
+ unsigned n = size();
+ ed[0] = c_[0];
+ ed[n] = c_[n-1];
+ for(unsigned i = 1; i < n; i++) {
+ ed[i] = (i*c_[i-1] + (n - i)*c_[i])/(n);
+ }
+ return ed;
+}
+
+Bezier Bezier::reduce_degree() const
+{
+ if(order() == 0) return *this;
+ Bezier ed(Order(order()-1));
+ unsigned n = size();
+ ed[0] = c_[0];
+ ed[n-1] = c_[n]; // ensure exact endpoints
+ unsigned middle = n/2;
+ for(unsigned i = 1; i < middle; i++) {
+ ed[i] = (n*c_[i] - i*ed[i-1])/(n-i);
+ }
+ for(unsigned i = n-1; i >= middle; i--) {
+ ed[i] = (n*c_[i] - i*ed[n-i])/(i);
+ }
+ return ed;
+}
+
+Bezier Bezier::elevate_to_degree(unsigned newDegree) const
+{
+ Bezier ed = *this;
+ for(unsigned i = degree(); i < newDegree; i++) {
+ ed = ed.elevate_degree();
+ }
+ return ed;
+}
+
+Bezier Bezier::deflate() const
+{
+ if(order() == 0) return *this;
+ unsigned n = order();
+ Bezier b(Order(n-1));
+ for(unsigned i = 0; i < n; i++) {
+ b[i] = (n*c_[i+1])/(i+1);
+ }
+ return b;
+}
+
+SBasis Bezier::toSBasis() const
+{
+ SBasis sb;
+ bezier_to_sbasis(sb, (*this));
+ return sb;
+ //return bezier_to_sbasis(&c_[0], order());
+}
+
+Bezier &Bezier::operator+=(Bezier const &other)
+{
+ if (c_.size() > other.size()) {
+ c_ += other.elevate_to_degree(degree()).c_;
+ } else if (c_.size() < other.size()) {
+ *this = elevate_to_degree(other.degree());
+ c_ += other.c_;
+ } else {
+ c_ += other.c_;
+ }
+ return *this;
+}
+
+Bezier &Bezier::operator-=(Bezier const &other)
+{
+ if (c_.size() > other.size()) {
+ c_ -= other.elevate_to_degree(degree()).c_;
+ } else if (c_.size() < other.size()) {
+ *this = elevate_to_degree(other.degree());
+ c_ -= other.c_;
+ } else {
+ c_ -= other.c_;
+ }
+ return *this;
+}
+
+Bezier operator*(Bezier const &f, Bezier const &g)
+{
+ int m = f.order();
+ int n = g.order();
+ Bezier h(Bezier::Order(m+n));
+ // h_k = sum_(i+j=k) (m i)f_i (n j)g_j / (m+n k)
+
+ int mci = 1;
+ for (int i = 0; i <= m; i++) {
+ double const fi = mci * f[i];
+
+ int ncj = 1;
+ for (int j = 0; j <= n; j++) {
+ h[i + j] += fi * ncj * g[j];
+ binomial_increment_k(ncj, n, j);
+ }
+
+ binomial_increment_k(mci, m, i);
+ }
+
+ int mnck = 1;
+ for (int k = 0; k <= m + n; k++) {
+ h[k] /= mnck;
+ binomial_increment_k(mnck, m + n, k);
+ }
+
+ return h;
+}
+
+Bezier portion(Bezier const &a, double from, double to)
+{
+ Bezier ret(a);
+
+ bool reverse_result = false;
+ if (from > to) {
+ std::swap(from, to);
+ reverse_result = true;
+ }
+
+ do {
+ if (from == 0) {
+ if (to == 1) {
+ break;
+ }
+ casteljau_subdivision<double>(to, &ret.c_[0], &ret.c_[0], NULL, ret.order());
+ break;
+ }
+ casteljau_subdivision<double>(from, &ret.c_[0], NULL, &ret.c_[0], ret.order());
+ if (to == 1) break;
+ casteljau_subdivision<double>((to - from) / (1 - from), &ret.c_[0], &ret.c_[0], NULL, ret.order());
+ // to protect against numerical inaccuracy in the above expression, we manually set
+ // the last coefficient to a value evaluated directly from the original polynomial
+ ret.c_[ret.order()] = a.valueAt(to);
+ } while(0);
+
+ if (reverse_result) {
+ std::reverse(&ret.c_[0], &ret.c_[0] + ret.c_.size());
+ }
+ return ret;
+}
+
+Bezier derivative(Bezier const &a)
+{
+ //if(a.order() == 1) return Bezier(0.0);
+ if(a.order() == 1) return Bezier(a.c_[1]-a.c_[0]);
+ Bezier der(Bezier::Order(a.order()-1));
+
+ for(unsigned i = 0; i < a.order(); i++) {
+ der.c_[i] = a.order()*(a.c_[i+1] - a.c_[i]);
+ }
+ return der;
+}
+
+Bezier integral(Bezier const &a)
+{
+ Bezier inte(Bezier::Order(a.order()+1));
+
+ inte[0] = 0;
+ for(unsigned i = 0; i < inte.order(); i++) {
+ inte[i+1] = inte[i] + a[i]/(inte.order());
+ }
+ return inte;
+}
+
+OptInterval bounds_fast(Bezier const &b)
+{
+ OptInterval ret = Interval::from_array(&const_cast<Bezier&>(b).c_[0], b.size());
+ return ret;
+}
+
+OptInterval bounds_exact(Bezier const &b)
+{
+ OptInterval ret(b.at0(), b.at1());
+ std::vector<Coord> r = derivative(b).roots();
+ for (double i : r) {
+ ret->expandTo(b.valueAt(i));
+ }
+ return ret;
+}
+
+OptInterval bounds_local(Bezier const &b, OptInterval const &i)
+{
+ //return bounds_local(b.toSBasis(), i);
+ if (i) {
+ return bounds_fast(portion(b, i->min(), i->max()));
+ } else {
+ return OptInterval();
+ }
+}
+
+/*
+ * The general bézier of degree n is
+ *
+ * p(t) = sum_{i = 0...n} binomial(n, i) t^i (1 - t)^(n - i) x[i]
+ *
+ * It can be written explicitly as a polynomial in t as
+ *
+ * p(t) = sum_{i = 0...n} binomial(n, i) t^i [ sum_{j = 0...i} binomial(i, j) (-1)^(i - j) x[j] ]
+ *
+ * Its derivative is
+ *
+ * p'(t) = n sum_{i = 1...n} binomial(n - 1, i - 1) t^(i - 1) [ sum_{j = 0...i} binomial(i, j) (-1)^(i - j) x[j] ]
+ *
+ * This is used by the various specialisations below as an optimisation for low degree n <= 3.
+ * In the remaining cases, the generic implementation is used which resorts to iteration.
+ */
+
+void bezier_expand_to_image(Interval &range, Coord x0, Coord x1, Coord x2)
+{
+ range.expandTo(x2);
+
+ if (range.contains(x1)) {
+ // The interval contains all control points, and therefore the entire curve.
+ return;
+ }
+
+ // p'(t) / 2 = at + b
+ auto a = (x2 - x1) - (x1 - x0);
+ auto b = x1 - x0;
+
+ // t = -b / a
+ if (std::abs(a) > EPSILON) {
+ auto t = -b / a;
+ if (t > 0.0 && t < 1.0) {
+ auto s = 1.0 - t;
+ auto x = s * s * x0 + 2 * s * t * x1 + t * t * x2;
+ range.expandTo(x);
+ }
+ }
+}
+
+void bezier_expand_to_image(Interval &range, Coord x0, Coord x1, Coord x2, Coord x3)
+{
+ range.expandTo(x3);
+
+ if (range.contains(x1) && range.contains(x2)) {
+ // The interval contains all control points, and therefore the entire curve.
+ return;
+ }
+
+ // p'(t) / 3 = at^2 + 2bt + c
+ auto a = (x3 - x0) - 3 * (x2 - x1);
+ auto b = (x2 - x1) - (x1 - x0);
+ auto c = x1 - x0;
+
+ auto expand = [&] (Coord t) {
+ if (t > 0.0 && t < 1.0) {
+ auto s = 1.0 - t;
+ auto x = s * s * s * x0 + 3 * s * s * t * x1 + 3 * t * t * s * x2 + t * t * t * x3;
+ range.expandTo(x);
+ }
+ };
+
+ // t = (-b ± sqrt(b^2 - ac)) / a
+ if (std::abs(a) < EPSILON) {
+ if (std::abs(b) > EPSILON) {
+ expand(-c / (2 * b));
+ }
+ } else {
+ auto d2 = b * b - a * c;
+ if (d2 >= 0.0) {
+ auto bsign = b >= 0.0 ? 1 : -1;
+ auto tmp = -(b + bsign * std::sqrt(d2));
+ expand(tmp / a);
+ expand(c / tmp); // Using Vieta's formula: product of roots == c/a
+ }
+ }
+}
+
+} // namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/cairo-path-sink.cpp b/src/3rdparty/2geom/src/2geom/cairo-path-sink.cpp
new file mode 100644
index 0000000..a04f715
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/cairo-path-sink.cpp
@@ -0,0 +1,127 @@
+/**
+ * @file
+ * @brief Path sink for Cairo contexts
+ *//*
+ * Copyright 2014 Krzysztof Kosiński
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, output to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifdef HAVE_CAIRO
+
+#include <cairo.h>
+#include <2geom/cairo-path-sink.h>
+#include <2geom/elliptical-arc.h>
+
+namespace Geom {
+
+CairoPathSink::CairoPathSink(cairo_t *cr)
+ : _cr(cr)
+{}
+
+void CairoPathSink::moveTo(Point const &p)
+{
+ cairo_move_to(_cr, p[X], p[Y]);
+ _current_point = p;
+}
+
+void CairoPathSink::lineTo(Point const &p)
+{
+ cairo_line_to(_cr, p[X], p[Y]);
+ _current_point = p;
+}
+
+void CairoPathSink::curveTo(Point const &p1, Point const &p2, Point const &p3)
+{
+ cairo_curve_to(_cr, p1[X], p1[Y], p2[X], p2[Y], p3[X], p3[Y]);
+ _current_point = p3;
+}
+
+void CairoPathSink::quadTo(Point const &p1, Point const &p2)
+{
+ // degree-elevate to cubic Bezier, since Cairo doesn't do quad Beziers
+ // google "Bezier degree elevation" for more info
+ Point q1 = (1./3.) * _current_point + (2./3.) * p1;
+ Point q2 = (2./3.) * p1 + (1./3.) * p2;
+ // q3 = p2
+ cairo_curve_to(_cr, q1[X], q1[Y], q2[X], q2[Y], p2[X], p2[Y]);
+ _current_point = p2;
+}
+
+void CairoPathSink::arcTo(double rx, double ry, double angle,
+ bool large_arc, bool sweep, Point const &p)
+{
+ EllipticalArc arc(_current_point, rx, ry, angle, large_arc, sweep, p);
+ // Cairo only does circular arcs.
+ // To do elliptical arcs, we must use a temporary transform.
+ Affine uct = arc.unitCircleTransform();
+
+ // TODO move Cairo-2Geom matrix conversion into a common location
+ cairo_matrix_t cm;
+ cm.xx = uct[0];
+ cm.xy = uct[2];
+ cm.x0 = uct[4];
+ cm.yx = uct[1];
+ cm.yy = uct[3];
+ cm.y0 = uct[5];
+
+ cairo_save(_cr);
+ cairo_transform(_cr, &cm);
+ if (sweep) {
+ cairo_arc(_cr, 0, 0, 1, arc.initialAngle(), arc.finalAngle());
+ } else {
+ cairo_arc_negative(_cr, 0, 0, 1, arc.initialAngle(), arc.finalAngle());
+ }
+ _current_point = p;
+ cairo_restore(_cr);
+
+ /* Note that an extra linear segment will be inserted before the arc
+ * if Cairo considers the current point distinct from the initial point
+ * of the arc; we could partially alleviate this by not emitting
+ * linear segments that are followed by arc segments, but this would require
+ * buffering the input curves. */
+}
+
+void CairoPathSink::closePath()
+{
+ cairo_close_path(_cr);
+}
+
+void CairoPathSink::flush() {}
+
+} // namespace Geom
+
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/circle.cpp b/src/3rdparty/2geom/src/2geom/circle.cpp
new file mode 100644
index 0000000..d97487a
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/circle.cpp
@@ -0,0 +1,337 @@
+/** @file
+ * @brief Circle shape
+ *//*
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2008-2014 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/circle.h>
+#include <2geom/ellipse.h>
+#include <2geom/elliptical-arc.h>
+#include <2geom/numeric/fitting-tool.h>
+#include <2geom/numeric/fitting-model.h>
+
+namespace Geom {
+
+Rect Circle::boundsFast() const
+{
+ Point rr(_radius, _radius);
+ Rect bbox(_center - rr, _center + rr);
+ return bbox;
+}
+
+void Circle::setCoefficients(Coord A, Coord B, Coord C, Coord D)
+{
+ if (A == 0) {
+ THROW_RANGEERROR("square term coefficient == 0");
+ }
+
+ //std::cerr << "B = " << B << " C = " << C << " D = " << D << std::endl;
+
+ Coord b = B / A;
+ Coord c = C / A;
+ Coord d = D / A;
+
+ _center[X] = -b/2;
+ _center[Y] = -c/2;
+ Coord r2 = _center[X] * _center[X] + _center[Y] * _center[Y] - d;
+
+ if (r2 < 0) {
+ THROW_RANGEERROR("ray^2 < 0");
+ }
+
+ _radius = std::sqrt(r2);
+}
+
+void Circle::coefficients(Coord &A, Coord &B, Coord &C, Coord &D) const
+{
+ A = 1;
+ B = -2 * _center[X];
+ C = -2 * _center[Y];
+ D = _center[X] * _center[X] + _center[Y] * _center[Y] - _radius * _radius;
+}
+
+std::vector<Coord> Circle::coefficients() const
+{
+ std::vector<Coord> c(4);
+ coefficients(c[0], c[1], c[2], c[3]);
+ return c;
+}
+
+
+Zoom Circle::unitCircleTransform() const
+{
+ Zoom ret(_radius, _center / _radius);
+ return ret;
+}
+
+Zoom Circle::inverseUnitCircleTransform() const
+{
+ if (_radius == 0) {
+ THROW_RANGEERROR("degenerate circle does not have an inverse unit circle transform");
+ }
+
+ Zoom ret(1/_radius, Translate(-_center));
+ return ret;
+}
+
+Point Circle::initialPoint() const
+{
+ Point p(_center);
+ p[X] += _radius;
+ return p;
+}
+
+Point Circle::pointAt(Coord t) const {
+ return _center + Point::polar(t) * _radius;
+}
+
+Coord Circle::valueAt(Coord t, Dim2 d) const {
+ Coord delta = (d == X ? std::cos(t) : std::sin(t));
+ return _center[d] + delta * _radius;
+}
+
+Coord Circle::timeAt(Point const &p) const {
+ if (_center == p) return 0;
+ return atan2(p - _center);
+}
+
+Coord Circle::nearestTime(Point const &p) const {
+ return timeAt(p);
+}
+
+bool Circle::contains(Rect const &r) const
+{
+ for (unsigned i = 0; i < 4; ++i) {
+ if (!contains(r.corner(i))) return false;
+ }
+ return true;
+}
+
+bool Circle::contains(Circle const &other) const
+{
+ Coord cdist = distance(_center, other._center);
+ Coord rdist = fabs(_radius - other._radius);
+ return cdist <= rdist;
+}
+
+bool Circle::intersects(Line const &l) const
+{
+ // http://mathworld.wolfram.com/Circle-LineIntersection.html
+ Coord dr = l.vector().length();
+ Coord r = _radius;
+ Coord D = cross(l.initialPoint(), l.finalPoint());
+ Coord delta = r*r * dr*dr - D*D;
+ if (delta >= 0) return true;
+ return false;
+}
+
+bool Circle::intersects(Circle const &other) const
+{
+ Coord cdist = distance(_center, other._center);
+ Coord rsum = _radius + other._radius;
+ return cdist <= rsum;
+}
+
+
+std::vector<ShapeIntersection> Circle::intersect(Line const &l) const
+{
+ // http://mathworld.wolfram.com/Circle-LineIntersection.html
+ Coord dr = l.vector().length();
+ Coord dx = l.vector().x();
+ Coord dy = l.vector().y();
+ Coord D = cross(l.initialPoint() - _center, l.finalPoint() - _center);
+ Coord delta = _radius*_radius * dr*dr - D*D;
+
+ std::vector<ShapeIntersection> result;
+ if (delta < 0) return result;
+ if (delta == 0) {
+ Coord ix = (D*dy) / (dr*dr);
+ Coord iy = (-D*dx) / (dr*dr);
+ Point ip(ix, iy); ip += _center;
+ result.emplace_back(timeAt(ip), l.timeAt(ip), ip);
+ return result;
+ }
+
+ Coord sqrt_delta = std::sqrt(delta);
+ Coord signmod = dy < 0 ? -1 : 1;
+
+ Coord i1x = (D*dy + signmod * dx * sqrt_delta) / (dr*dr);
+ Coord i1y = (-D*dx + fabs(dy) * sqrt_delta) / (dr*dr);
+ Point i1p(i1x, i1y); i1p += _center;
+
+ Coord i2x = (D*dy - signmod * dx * sqrt_delta) / (dr*dr);
+ Coord i2y = (-D*dx - fabs(dy) * sqrt_delta) / (dr*dr);
+ Point i2p(i2x, i2y); i2p += _center;
+
+ result.emplace_back(timeAt(i1p), l.timeAt(i1p), i1p);
+ result.emplace_back(timeAt(i2p), l.timeAt(i2p), i2p);
+ return result;
+}
+
+std::vector<ShapeIntersection> Circle::intersect(LineSegment const &l) const
+{
+ std::vector<ShapeIntersection> result = intersect(Line(l));
+ filter_line_segment_intersections(result);
+ return result;
+}
+
+std::vector<ShapeIntersection> Circle::intersect(Circle const &other) const
+{
+ std::vector<ShapeIntersection> result;
+
+ if (*this == other) {
+ THROW_INFINITESOLUTIONS();
+ }
+ if (contains(other)) return result;
+ if (!intersects(other)) return result;
+
+ // See e.g. http://mathworld.wolfram.com/Circle-CircleIntersection.html
+ // Basically, we figure out where is the third point of a triangle
+ // with two points in the centers and with edge lengths equal to radii
+ Point cv = other._center - _center;
+ Coord d = cv.length();
+ Coord R = radius(), r = other.radius();
+
+ if (d == R + r) {
+ Point px = lerp(R / d, _center, other._center);
+ Coord T = timeAt(px), t = other.timeAt(px);
+ result.emplace_back(T, t, px);
+ return result;
+ }
+
+ // q is the distance along the line between centers to the perpendicular line
+ // that goes through both intersections.
+ Coord q = (d*d - r*r + R*R) / (2*d);
+ Point qp = lerp(q/d, _center, other._center);
+
+ // The triangle given by the points:
+ // _center, qp, intersection
+ // is a right triangle. Determine the distance between qp and intersection
+ // using the Pythagorean theorem.
+ Coord h = std::sqrt(R*R - q*q);
+ Point qd = (h/d) * cv.cw();
+
+ // now compute the intersection points
+ Point x1 = qp + qd;
+ Point x2 = qp - qd;
+
+ result.emplace_back(timeAt(x1), other.timeAt(x1), x1);
+ result.emplace_back(timeAt(x2), other.timeAt(x2), x2);
+ return result;
+}
+
+/**
+ @param inner a point whose angle with the circle center is inside the angle that the arc spans
+ */
+EllipticalArc *
+Circle::arc(Point const& initial, Point const& inner, Point const& final) const
+{
+ // TODO native implementation!
+ Ellipse e(_center[X], _center[Y], _radius, _radius, 0);
+ return e.arc(initial, inner, final);
+}
+
+bool Circle::operator==(Circle const &other) const
+{
+ if (_center != other._center) return false;
+ if (_radius != other._radius) return false;
+ return true;
+}
+
+D2<SBasis> Circle::toSBasis() const
+{
+ D2<SBasis> B;
+ Linear bo = Linear(0, 2 * M_PI);
+
+ B[0] = cos(bo,4);
+ B[1] = sin(bo,4);
+
+ B = B * _radius + _center;
+
+ return B;
+}
+
+
+void Circle::fit(std::vector<Point> const& points)
+{
+ size_t sz = points.size();
+ if (sz < 2) {
+ THROW_RANGEERROR("fitting error: too few points passed");
+ }
+ if (sz == 2) {
+ _center = points[0] * 0.5 + points[1] * 0.5;
+ _radius = distance(points[0], points[1]) / 2;
+ return;
+ }
+
+ NL::LFMCircle model;
+ NL::least_squeares_fitter<NL::LFMCircle> fitter(model, sz);
+
+ for (size_t i = 0; i < sz; ++i) {
+ fitter.append(points[i]);
+ }
+ fitter.update();
+
+ NL::Vector z(sz, 0.0);
+ model.instance(*this, fitter.result(z));
+}
+
+
+bool are_near(Circle const &a, Circle const &b, Coord eps)
+{
+ // to check whether no point on a is further than eps from b,
+ // we check two things:
+ // 1. if radii differ by more than eps, there is definitely a point that fails
+ // 2. if they differ by less, we check the centers. They have to be closer
+ // together if the radius differs, since the maximum distance will be
+ // equal to sum of radius difference and distance between centers.
+ if (!are_near(a.radius(), b.radius(), eps)) return false;
+ Coord adjusted_eps = eps - fabs(a.radius() - b.radius());
+ return are_near(a.center(), b.center(), adjusted_eps);
+}
+
+std::ostream &operator<<(std::ostream &out, Circle const &c)
+{
+ out << "Circle(" << c.center() << ", " << format_coord_nice(c.radius()) << ")";
+ return out;
+}
+
+} // end namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/concepts.cpp b/src/3rdparty/2geom/src/2geom/concepts.cpp
new file mode 100644
index 0000000..e8c8e5c
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/concepts.cpp
@@ -0,0 +1,69 @@
+/**
+ * \file
+ * \brief Concept checking
+ *//*
+ * Copyright 2015 Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, output to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <boost/concept/assert.hpp>
+#include <2geom/concepts.h>
+
+#include <2geom/line.h>
+#include <2geom/circle.h>
+#include <2geom/ellipse.h>
+#include <2geom/curves.h>
+#include <2geom/convex-hull.h>
+#include <2geom/path.h>
+#include <2geom/pathvector.h>
+
+#include <2geom/bezier.h>
+#include <2geom/sbasis.h>
+#include <2geom/linear.h>
+#include <2geom/d2.h>
+
+namespace Geom {
+
+void concept_checks()
+{
+ BOOST_CONCEPT_ASSERT((ShapeConcept<Line>));
+ //BOOST_CONCEPT_ASSERT((ShapeConcept<Circle>));
+ //BOOST_CONCEPT_ASSERT((ShapeConcept<Ellipse>));
+ BOOST_CONCEPT_ASSERT((ShapeConcept<BezierCurve>));
+ BOOST_CONCEPT_ASSERT((ShapeConcept<EllipticalArc>));
+ //BOOST_CONCEPT_ASSERT((ShapeConcept<SBasisCurve>));
+ //BOOST_CONCEPT_ASSERT((ShapeConcept<ConvexHull>));
+ //BOOST_CONCEPT_ASSERT((ShapeConcept<Path>));
+ //BOOST_CONCEPT_ASSERT((ShapeConcept<PathVector>));
+
+ BOOST_CONCEPT_ASSERT((NearConcept<Coord>));
+ BOOST_CONCEPT_ASSERT((NearConcept<Point>));
+
+ BOOST_CONCEPT_ASSERT((FragmentConcept<Bezier>));
+ BOOST_CONCEPT_ASSERT((FragmentConcept<Linear>));
+ BOOST_CONCEPT_ASSERT((FragmentConcept<SBasis>));
+}
+
+} // end namespace Geom
diff --git a/src/3rdparty/2geom/src/2geom/conic_section_clipper_impl.cpp b/src/3rdparty/2geom/src/2geom/conic_section_clipper_impl.cpp
new file mode 100644
index 0000000..8b0445e
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/conic_section_clipper_impl.cpp
@@ -0,0 +1,574 @@
+/* Conic section clipping with respect to a rectangle
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail>
+ *
+ * Copyright 2009 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <optional>
+
+#ifndef CLIP_WITH_CAIRO_SUPPORT
+ #include <2geom/conic_section_clipper.h>
+#endif
+
+namespace Geom
+{
+
+/*
+ * Find rectangle-conic crossing points. They are returned in the
+ * "crossing_points" parameter.
+ * The method returns true if the conic section intersects at least one
+ * of the four lines passing through rectangle edges, else it returns false.
+ */
+bool CLIPPER_CLASS::intersect (std::vector<Point> & crossing_points) const
+{
+ crossing_points.clear();
+
+ std::vector<double> rts;
+ std::vector<Point> cpts;
+ // rectangle corners
+ enum {TOP_LEFT, TOP_RIGHT, BOTTOM_RIGHT, BOTTOM_LEFT};
+
+ bool no_crossing = true;
+
+ // right edge
+ cs.roots (rts, R.right(), X);
+ if (!rts.empty())
+ {
+ no_crossing = false;
+ DBGPRINT ("CLIP: right: rts[0] = ", rts[0])
+ DBGPRINTIF ((rts.size() == 2), "CLIP: right: rts[1] = ", rts[1])
+
+ Point corner1 = R.corner(TOP_RIGHT);
+ Point corner2 = R.corner(BOTTOM_RIGHT);
+
+ for (double rt : rts)
+ {
+ if (rt < R.top() || rt > R.bottom()) continue;
+ Point P (R.right(), rt);
+ if (are_near (P, corner1))
+ P = corner1;
+ else if (are_near (P, corner2))
+ P = corner2;
+
+ cpts.push_back (P);
+ }
+ if (cpts.size() == 2 && are_near (cpts[0], cpts[1]))
+ {
+ cpts[0] = middle_point (cpts[0], cpts[1]);
+ cpts.pop_back();
+ }
+ }
+
+ // top edge
+ cs.roots (rts, R.top(), Y);
+ if (!rts.empty())
+ {
+ no_crossing = false;
+ DBGPRINT ("CLIP: top: rts[0] = ", rts[0])
+ DBGPRINTIF ((rts.size() == 2), "CLIP: top: rts[1] = ", rts[1])
+
+ Point corner1 = R.corner(TOP_RIGHT);
+ Point corner2 = R.corner(TOP_LEFT);
+
+ for (double rt : rts)
+ {
+ if (rt < R.left() || rt > R.right()) continue;
+ Point P (rt, R.top());
+ if (are_near (P, corner1))
+ P = corner1;
+ else if (are_near (P, corner2))
+ P = corner2;
+
+ cpts.push_back (P);
+ }
+ if (cpts.size() == 2 && are_near (cpts[0], cpts[1]))
+ {
+ cpts[0] = middle_point (cpts[0], cpts[1]);
+ cpts.pop_back();
+ }
+ }
+
+ // left edge
+ cs.roots (rts, R.left(), X);
+ if (!rts.empty())
+ {
+ no_crossing = false;
+ DBGPRINT ("CLIP: left: rts[0] = ", rts[0])
+ DBGPRINTIF ((rts.size() == 2), "CLIP: left: rts[1] = ", rts[1])
+
+ Point corner1 = R.corner(TOP_LEFT);
+ Point corner2 = R.corner(BOTTOM_LEFT);
+
+ for (double rt : rts)
+ {
+ if (rt < R.top() || rt > R.bottom()) continue;
+ Point P (R.left(), rt);
+ if (are_near (P, corner1))
+ P = corner1;
+ else if (are_near (P, corner2))
+ P = corner2;
+
+ cpts.push_back (P);
+ }
+ if (cpts.size() == 2 && are_near (cpts[0], cpts[1]))
+ {
+ cpts[0] = middle_point (cpts[0], cpts[1]);
+ cpts.pop_back();
+ }
+ }
+
+ // bottom edge
+ cs.roots (rts, R.bottom(), Y);
+ if (!rts.empty())
+ {
+ no_crossing = false;
+ DBGPRINT ("CLIP: bottom: rts[0] = ", rts[0])
+ DBGPRINTIF ((rts.size() == 2), "CLIP: bottom: rts[1] = ", rts[1])
+
+ Point corner1 = R.corner(BOTTOM_RIGHT);
+ Point corner2 = R.corner(BOTTOM_LEFT);
+
+ for (double rt : rts)
+ {
+ if (rt < R.left() || rt > R.right()) continue;
+ Point P (rt, R.bottom());
+ if (are_near (P, corner1))
+ P = corner1;
+ else if (are_near (P, corner2))
+ P = corner2;
+
+ cpts.push_back (P);
+ }
+ if (cpts.size() == 2 && are_near (cpts[0], cpts[1]))
+ {
+ cpts[0] = middle_point (cpts[0], cpts[1]);
+ cpts.pop_back();
+ }
+ }
+
+ DBGPRINT ("CLIP: intersect: crossing_points.size (with duplicates) = ",
+ cpts.size())
+
+ // remove duplicates
+ std::sort (cpts.begin(), cpts.end(), Point::LexLess<X>());
+ cpts.erase (std::unique (cpts.begin(), cpts.end()), cpts.end());
+
+
+ // Order crossing points on the rectangle edge clockwise, so two consecutive
+ // crossing points would be the end points of a conic arc all inside or all
+ // outside the rectangle.
+ std::map<double, size_t> cp_angles;
+ for (size_t i = 0; i < cpts.size(); ++i)
+ {
+ cp_angles.insert (std::make_pair (cs.angle_at (cpts[i]), i));
+ }
+
+ std::map<double, size_t>::const_iterator pos;
+ for (pos = cp_angles.begin(); pos != cp_angles.end(); ++pos)
+ {
+ crossing_points.push_back (cpts[pos->second]);
+ }
+
+ DBGPRINT ("CLIP: intersect: crossing_points.size = ", crossing_points.size())
+ DBGPRINTCOLL ("CLIP: intersect: crossing_points:", crossing_points)
+
+ return no_crossing;
+} // end function intersect
+
+
+
+inline
+double signed_triangle_area (Point const& p1, Point const& p2, Point const& p3)
+{
+ return (cross(p2, p3) - cross(p1, p3) + cross(p1, p2));
+}
+
+
+/*
+ * Test if two crossing points are the end points of a conic arc inner to the
+ * rectangle. In such a case the method returns true, else it returns false.
+ * Moreover by the parameter "M" it returns a point inner to the conic arc
+ * with the given end-points.
+ *
+ */
+bool CLIPPER_CLASS::are_paired (Point& M, const Point & P1, const Point & P2) const
+{
+ using std::swap;
+
+ /*
+ * we looks for the points on the conic whose tangent is parallel to the
+ * arc chord P1P2, they will be extrema of the conic arc P1P2 wrt the
+ * direction orthogonal to the chord
+ */
+ Point dir = P2 - P1;
+ DBGPRINT ("CLIP: are_paired: first point: ", P1)
+ DBGPRINT ("CLIP: are_paired: second point: ", P2)
+
+ double grad0 = 2 * cs.coeff(0) * dir[0] + cs.coeff(1) * dir[1];
+ double grad1 = cs.coeff(1) * dir[0] + 2 * cs.coeff(2) * dir[1];
+ double grad2 = cs.coeff(3) * dir[0] + cs.coeff(4) * dir[1];
+
+
+ /*
+ * such points are found intersecating the conic section with the line
+ * orthogonal to "grad": the derivative wrt the "dir" direction
+ */
+ Line gl (grad0, grad1, grad2);
+ std::vector<double> rts;
+ rts = cs.roots (gl);
+ DBGPRINT ("CLIP: are_paired: extrema: rts.size() = ", rts.size())
+
+
+
+ std::vector<Point> extrema;
+ for (double rt : rts)
+ {
+ extrema.push_back (gl.pointAt (rt));
+ }
+
+ if (extrema.size() == 2)
+ {
+ // in case we are dealing with an hyperbola we could have two extrema
+ // on the same side wrt the line passing through P1 and P2, but
+ // only the nearer extremum is on the arc P1P2
+ double side0 = signed_triangle_area (P1, extrema[0], P2);
+ double side1 = signed_triangle_area (P1, extrema[1], P2);
+
+ if (sgn(side0) == sgn(side1))
+ {
+ if (std::fabs(side0) > std::fabs(side1)) {
+ swap(extrema[0], extrema[1]);
+ }
+ extrema.pop_back();
+ }
+ }
+
+ std::vector<Point> inner_points;
+ for (auto & i : extrema)
+ {
+ if (!R.contains (i)) continue;
+ // in case we are dealing with an ellipse tangent to two orthogonal
+ // rectangle edges we could have two extrema on opposite sides wrt the
+ // line passing through P1P2 and both inner the rectangle; anyway, since
+ // we order the crossing points clockwise we have only one extremum
+ // that follows such an ordering wrt P1 and P2;
+ // remark: the other arc will be selected when we test for the arc P2P1.
+ double P1angle = cs.angle_at (P1);
+ double P2angle = cs.angle_at (P2);
+ double Qangle = cs.angle_at (i);
+ if (P1angle < P2angle && !(P1angle <= Qangle && Qangle <= P2angle))
+ continue;
+ if (P1angle > P2angle && !(P1angle <= Qangle || Qangle <= P2angle))
+ continue;
+
+ inner_points.push_back (i);
+ }
+
+ if (inner_points.size() > 1)
+ {
+ THROW_LOGICALERROR ("conic section clipper: "
+ "more than one extremum found");
+ }
+ else if (inner_points.size() == 1)
+ {
+ M = inner_points.front();
+ return true;
+ }
+
+ return false;
+}
+
+
+/*
+ * Pair the points contained in the "crossing_points" vector; the paired points
+ * are put in the paired_points vector so that given a point with an even index
+ * and the next one they are the end points of a conic arc that is inner to the
+ * rectangle. In the "inner_points" are returned points that are inner to the
+ * arc, where the inner point with index k is related to the arc with end
+ * points with indexes 2k, 2k+1. In case there are unpaired points the are put
+ * in to the "single_points" vector.
+ */
+void CLIPPER_CLASS::pairing (std::vector<Point> & paired_points,
+ std::vector<Point> & inner_points,
+ const std::vector<Point> & crossing_points)
+{
+ paired_points.clear();
+ paired_points.reserve (crossing_points.size());
+
+ inner_points.clear();
+ inner_points.reserve (crossing_points.size() / 2);
+
+ single_points.clear();
+
+ // to keep trace of which crossing points have been paired
+ std::vector<bool> paired (crossing_points.size(), false);
+
+ Point M;
+
+ // by the way we have ordered crossing points we need to test one point wrt
+ // the next point only, for pairing; moreover the last point need to be
+ // tested wrt the first point; pay attention: one point can be paired both
+ // with the previous and the next one: this is not an error, think of
+ // crossing points that are tangent to the rectangle edge (and inner);
+ for (size_t i = 0; i < crossing_points.size(); ++i)
+ {
+ // we need to test the last point wrt the first one
+ size_t j = (i == 0) ? (crossing_points.size() - 1) : (i-1);
+ if (are_paired (M, crossing_points[j], crossing_points[i]))
+ {
+#ifdef CLIP_WITH_CAIRO_SUPPORT
+ cairo_set_source_rgba(cr, 0.1, 0.1, 0.8, 1.0);
+ draw_line_seg (cr, crossing_points[j], crossing_points[i]);
+ draw_handle (cr, crossing_points[j]);
+ draw_handle (cr, crossing_points[i]);
+ draw_handle (cr, M);
+ cairo_stroke (cr);
+#endif
+ paired[j] = paired[i] = true;
+ paired_points.push_back (crossing_points[j]);
+ paired_points.push_back (crossing_points[i]);
+ inner_points.push_back (M);
+ }
+ }
+
+ // some point are not paired with any point, e.g. a crossing point tangent
+ // to a rectangle edge but with the conic arc outside the rectangle
+ for (size_t i = 0; i < paired.size(); ++i)
+ {
+ if (!paired[i])
+ single_points.push_back (crossing_points[i]);
+ }
+ DBGPRINTCOLL ("single_points", single_points)
+
+}
+
+
+/*
+ * This method clip the section conic wrt the rectangle and returns the inner
+ * conic arcs as a vector of RatQuad objects by the "arcs" parameter.
+ */
+bool CLIPPER_CLASS::clip (std::vector<RatQuad> & arcs)
+{
+ using std::swap;
+
+ arcs.clear();
+ std::vector<Point> crossing_points;
+ std::vector<Point> paired_points;
+ std::vector<Point> inner_points;
+
+ Line l1, l2;
+ if (cs.decompose (l1, l2))
+ {
+ bool inner_empty = true;
+
+ DBGINFO ("CLIP: degenerate section conic")
+
+ std::optional<LineSegment> ls1 = Geom::clip (l1, R);
+ if (ls1)
+ {
+ if (ls1->isDegenerate())
+ {
+ single_points.push_back (ls1->initialPoint());
+ }
+ else
+ {
+ Point M = middle_point (*ls1);
+ arcs.emplace_back(ls1->initialPoint(), M, ls1->finalPoint(), 1);
+ inner_empty = false;
+ }
+ }
+
+ std::optional<LineSegment> ls2 = Geom::clip (l2, R);
+ if (ls2)
+ {
+ if (ls2->isDegenerate())
+ {
+ single_points.push_back (ls2->initialPoint());
+ }
+ else
+ {
+ Point M = middle_point (*ls2);
+ arcs.emplace_back(ls2->initialPoint(), M, ls2->finalPoint(), 1);
+ inner_empty = false;
+ }
+ }
+
+ return !inner_empty;
+ }
+
+
+ bool no_crossing = intersect (crossing_points);
+
+ // if the only crossing point is a rectangle corner than the section conic
+ // is all outside the rectangle
+ if (crossing_points.size() == 1)
+ {
+ for (size_t i = 0; i < 4; ++i)
+ {
+ if (crossing_points[0] == R.corner(i))
+ {
+ single_points.push_back (R.corner(i));
+ return false;
+ }
+ }
+ }
+
+ // if the conic does not cross any line passing through a rectangle edge or
+ // it is tangent to only one edge then it is an ellipse
+ if (no_crossing
+ || (crossing_points.size() == 1 && single_points.empty()))
+ {
+ // if the ellipse centre is inside the rectangle
+ // then so it is the ellipse
+ std::optional<Point> c = cs.centre();
+ if (c && R.contains (*c))
+ {
+ DBGPRINT ("CLIP: ellipse with centre", *c)
+ // we set paired and inner points by finding the ellipse
+ // intersection with its axes; this choice let us having a more
+ // accurate RatQuad parametric arc
+ paired_points.resize(4);
+ std::vector<double> rts;
+ double angle = cs.axis_angle();
+ Line axis1 (*c, angle);
+ rts = cs.roots (axis1);
+ if (rts[0] > rts[1]) swap (rts[0], rts[1]);
+ paired_points[0] = axis1.pointAt (rts[0]);
+ paired_points[1] = axis1.pointAt (rts[1]);
+ paired_points[2] = paired_points[1];
+ paired_points[3] = paired_points[0];
+ Line axis2 (*c, angle + M_PI/2);
+ rts = cs.roots (axis2);
+ if (rts[0] > rts[1]) swap (rts[0], rts[1]);
+ inner_points.push_back (axis2.pointAt (rts[0]));
+ inner_points.push_back (axis2.pointAt (rts[1]));
+ }
+ else if (crossing_points.size() == 1)
+ {
+ // so we have a tangent crossing point but the ellipse is outside
+ // the rectangle
+ single_points.push_back (crossing_points[0]);
+ }
+ }
+ else
+ {
+ // in case the conic section intersects any of the four lines passing
+ // through the rectangle edges but it does not cross any rectangle edge
+ // then the conic is all outer of the rectangle
+ if (crossing_points.empty()) return false;
+ // else we need to pair crossing points, and to find an arc inner point
+ // in order to generate a RatQuad object
+ pairing (paired_points, inner_points, crossing_points);
+ }
+
+
+ // we split arcs until the end-point distance is less than a given value,
+ // in this way the RatQuad parametrization is enough accurate
+ std::list<Point> points;
+ std::list<Point>::iterator sp, ip, fp;
+ for (size_t i = 0, j = 0; i < paired_points.size(); i += 2, ++j)
+ {
+ //DBGPRINT ("CLIP: clip: P = ", paired_points[i])
+ //DBGPRINT ("CLIP: clip: M = ", inner_points[j])
+ //DBGPRINT ("CLIP: clip: Q = ", paired_points[i+1])
+
+ // in case inner point and end points are near is better not split
+ // the conic arc further or we could get a degenerate RatQuad object
+ if (are_near (paired_points[i], inner_points[j], 1e-4)
+ && are_near (paired_points[i+1], inner_points[j], 1e-4))
+ {
+ arcs.push_back (cs.toRatQuad (paired_points[i],
+ inner_points[j],
+ paired_points[i+1]));
+ continue;
+ }
+
+ // populate the list
+ points.push_back(paired_points[i]);
+ points.push_back(inner_points[j]);
+ points.push_back(paired_points[i+1]);
+
+ // an initial unconditioned splitting
+ sp = points.begin();
+ ip = sp; ++ip;
+ fp = ip; ++fp;
+ rsplit (points, sp, ip, size_t(1u));
+ rsplit (points, ip, fp, size_t(1u));
+
+ // length conditioned split
+ sp = points.begin();
+ fp = sp; ++fp;
+ while (fp != points.end())
+ {
+ rsplit (points, sp, fp, 100.0);
+ sp = fp;
+ ++fp;
+ }
+
+ sp = points.begin();
+ ip = sp; ++ip;
+ fp = ip; ++fp;
+ //DBGPRINT ("CLIP: points ", j)
+ //DBGPRINT ("CLIP: points.size = ", points.size())
+ while (ip != points.end())
+ {
+#ifdef CLIP_WITH_CAIRO_SUPPORT
+ cairo_set_source_rgba(cr, 0.1, 0.1, 0.8, 1.0);
+ draw_handle (cr, *sp);
+ draw_handle (cr, *ip);
+ cairo_stroke (cr);
+#endif
+ //std::cerr << "CLIP: arc: [" << *sp << ", " << *ip << ", "
+ // << *fp << "]" << std::endl;
+ arcs.push_back (cs.toRatQuad (*sp, *ip, *fp));
+ sp = fp;
+ ip = sp; ++ip;
+ fp = ip; ++fp;
+ }
+ points.clear();
+ }
+ DBGPRINT ("CLIP: arcs.size() = ", arcs.size())
+ return (arcs.size() != 0);
+} // end method clip
+
+
+} // end namespace geom
+
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/conicsec.cpp b/src/3rdparty/2geom/src/2geom/conicsec.cpp
new file mode 100644
index 0000000..0865c0e
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/conicsec.cpp
@@ -0,0 +1,1640 @@
+/*
+ * Authors:
+ * Nathan Hurst <njh@njhurst.com
+ *
+ * Copyright 2009 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#include <2geom/conicsec.h>
+#include <2geom/conic_section_clipper.h>
+#include <2geom/numeric/fitting-tool.h>
+#include <2geom/numeric/fitting-model.h>
+
+
+// File: convert.h
+#include <utility>
+#include <sstream>
+#include <stdexcept>
+#include <optional>
+
+namespace Geom
+{
+
+LineSegment intersection(Line l, Rect r) {
+ std::optional<LineSegment> seg = l.clip(r);
+ if (seg) {
+ return *seg;
+ } else {
+ return LineSegment(Point(0,0), Point(0,0));
+ }
+}
+
+static double det(Point a, Point b) {
+ return a[0]*b[1] - a[1]*b[0];
+}
+
+template <typename T>
+static T det(T a, T b, T c, T d) {
+ return a*d - b*c;
+}
+
+template <typename T>
+static T det(T M[2][2]) {
+ return M[0][0]*M[1][1] - M[1][0]*M[0][1];
+}
+
+template <typename T>
+static T det3(T M[3][3]) {
+ return ( M[0][0] * det(M[1][1], M[1][2],
+ M[2][1], M[2][2])
+ -M[1][0] * det(M[0][1], M[0][2],
+ M[2][1], M[2][2])
+ +M[2][0] * det(M[0][1], M[0][2],
+ M[1][1], M[1][2]));
+}
+
+static double boxprod(Point a, Point b, Point c) {
+ return det(a,b) - det(a,c) + det(b,c);
+}
+
+class BadConversion : public std::runtime_error {
+public:
+ BadConversion(const std::string& s)
+ : std::runtime_error(s)
+ { }
+};
+
+template <typename T>
+inline std::string stringify(T x)
+{
+ std::ostringstream o;
+ if (!(o << x))
+ throw BadConversion("stringify(T)");
+ return o.str();
+}
+
+ /* A G4 continuous cubic parametric approximation for rational quadratics.
+ See
+ An analysis of cubic approximation schemes for conic sections
+ Michael Floater
+ SINTEF
+
+ This is less accurate overall than some of his other schemes, but
+ produces very smooth joins and is still optimally h^-6
+ convergent.
+ */
+
+double RatQuad::lambda() const {
+ return 2*(6*w*w +1 -std::sqrt(3*w*w+1))/(12*w*w+3);
+}
+
+RatQuad RatQuad::fromPointsTangents(Point P0, Point dP0,
+ Point P,
+ Point P2, Point dP2) {
+ Line Line0 = Line::from_origin_and_vector(P0, dP0);
+ Line Line2 = Line::from_origin_and_vector(P2, dP2);
+ try {
+ OptCrossing oc = intersection(Line0, Line2);
+ if(!oc) // what to do?
+ return RatQuad(Point(), Point(), Point(), 0); // need opt really
+ //assert(0);
+ Point P1 = Line0.pointAt((*oc).ta);
+ double triarea = boxprod(P0, P1, P2);
+// std::cout << "RatQuad::fromPointsTangents: triarea = " << triarea << std::endl;
+ if (triarea == 0)
+ {
+ return RatQuad(P0, 0.5*(P0+P2), P2, 1);
+ }
+ double tau0 = boxprod(P, P1, P2)/triarea;
+ double tau1 = boxprod(P0, P, P2)/triarea;
+ double tau2 = boxprod(P0, P1, P)/triarea;
+ if (tau0 == 0 || tau1 == 0 || tau2 == 0)
+ {
+ return RatQuad(P0, 0.5*(P0+P2), P2, 1);
+ }
+ double w = tau1/(2*std::sqrt(tau0*tau2));
+// std::cout << "RatQuad::fromPointsTangents: tau0 = " << tau0 << std::endl;
+// std::cout << "RatQuad::fromPointsTangents: tau1 = " << tau1 << std::endl;
+// std::cout << "RatQuad::fromPointsTangents: tau2 = " << tau2 << std::endl;
+// std::cout << "RatQuad::fromPointsTangents: w = " << w << std::endl;
+ return RatQuad(P0, P1, P2, w);
+ } catch(Geom::InfiniteSolutions const&) {
+ return RatQuad(P0, 0.5*(P0+P2), P2, 1);
+ }
+ return RatQuad(Point(), Point(), Point(), 0); // need opt really
+}
+
+RatQuad RatQuad::circularArc(Point P0, Point P1, Point P2) {
+ return RatQuad(P0, P1, P2, dot(unit_vector(P0 - P1), unit_vector(P0 - P2)));
+}
+
+
+CubicBezier RatQuad::toCubic() const {
+ return toCubic(lambda());
+}
+
+CubicBezier RatQuad::toCubic(double lamb) const {
+ return CubicBezier(P[0],
+ (1-lamb)*P[0] + lamb*P[1],
+ (1-lamb)*P[2] + lamb*P[1],
+ P[2]);
+}
+
+Point RatQuad::pointAt(double t) const {
+ Bezier xt(P[0][0], P[1][0]*w, P[2][0]);
+ Bezier yt(P[0][1], P[1][1]*w, P[2][1]);
+ double wt = Bezier(1, w, 1).valueAt(t);
+ return Point(xt.valueAt(t)/wt,
+ yt.valueAt(t)/wt);
+}
+
+void RatQuad::split(RatQuad &a, RatQuad &b) const {
+ a.P[0] = P[0];
+ b.P[2] = P[2];
+ a.P[1] = (P[0]+w*P[1])/(1+w);
+ b.P[1] = (w*P[1]+P[2])/(1+w);
+ a.w = b.w = std::sqrt((1+w)/2);
+ a.P[2] = b.P[0] = (0.5*a.P[1]+0.5*b.P[1]);
+}
+
+
+D2<SBasis> RatQuad::hermite() const {
+ SBasis t = Linear(0, 1);
+ SBasis omt = Linear(1, 0);
+
+ D2<SBasis> out(omt*omt*P[0][0]+2*omt*t*P[1][0]*w+t*t*P[2][0],
+ omt*omt*P[0][1]+2*omt*t*P[1][1]*w+t*t*P[2][1]);
+ for(int dim = 0; dim < 2; dim++) {
+ out[dim] = divide(out[dim], (omt*omt+2*omt*t*w+t*t), 2);
+ }
+ return out;
+}
+
+ std::vector<SBasis> RatQuad::homogeneous() const {
+ std::vector<SBasis> res(3, SBasis());
+ Bezier xt(P[0][0], P[1][0]*w, P[2][0]);
+ bezier_to_sbasis(res[0],xt);
+ Bezier yt(P[0][1], P[1][1]*w, P[2][1]);
+ bezier_to_sbasis(res[1],yt);
+ Bezier wt(1, w, 1);
+ bezier_to_sbasis(res[2],wt);
+ return res;
+}
+
+#if 0
+ std::string xAx::categorise() const {
+ double M[3][3] = {{c[0], c[1], c[3]},
+ {c[1], c[2], c[4]},
+ {c[3], c[4], c[5]}};
+ double D = det3(M);
+ if (c[0] == 0 && c[1] == 0 && c[2] == 0)
+ return "line";
+ std::string res = stringify(D);
+ double descr = c[1]*c[1] - c[0]*c[2];
+ if (descr < 0) {
+ if (c[0] == c[2] && c[1] == 0)
+ return res + "circle";
+ return res + "ellipse";
+ } else if (descr == 0) {
+ return res + "parabola";
+ } else if (descr > 0) {
+ if (c[0] + c[2] == 0) {
+ if (D == 0)
+ return res + "two lines";
+ return res + "rectangular hyperbola";
+ }
+ return res + "hyperbola";
+
+ }
+ return "no idea!";
+}
+#endif
+
+
+std::vector<Point> decompose_degenerate(xAx const & C1, xAx const & C2, xAx const & xC0) {
+ std::vector<Point> res;
+ double A[2][2] = {{2*xC0.c[0], xC0.c[1]},
+ {xC0.c[1], 2*xC0.c[2]}};
+//Point B0 = xC0.bottom();
+ double const determ = det(A);
+ //std::cout << determ << "\n";
+ if (fabs(determ) >= 1e-20) { // hopeful, I know
+ Geom::Coord const ideterm = 1.0 / determ;
+
+ double b[2] = {-xC0.c[3], -xC0.c[4]};
+ Point B0((A[1][1]*b[0] -A[0][1]*b[1]),
+ (-A[1][0]*b[0] + A[0][0]*b[1]));
+ B0 *= ideterm;
+ Point n0, n1;
+ // Are these just the eigenvectors of A11?
+ if(xC0.c[0] == xC0.c[2]) {
+ double b = 0.5*xC0.c[1]/xC0.c[0];
+ double c = xC0.c[2]/xC0.c[0];
+ //assert(fabs(b*b-c) > 1e-10);
+ double d = std::sqrt(b*b-c);
+ //assert(fabs(b-d) > 1e-10);
+ n0 = Point(1, b+d);
+ n1 = Point(1, b-d);
+ } else if(fabs(xC0.c[0]) > fabs(xC0.c[2])) {
+ double b = 0.5*xC0.c[1]/xC0.c[0];
+ double c = xC0.c[2]/xC0.c[0];
+ //assert(fabs(b*b-c) > 1e-10);
+ double d = std::sqrt(b*b-c);
+ //assert(fabs(b-d) > 1e-10);
+ n0 = Point(1, b+d);
+ n1 = Point(1, b-d);
+ } else {
+ double b = 0.5*xC0.c[1]/xC0.c[2];
+ double c = xC0.c[0]/xC0.c[2];
+ //assert(fabs(b*b-c) > 1e-10);
+ double d = std::sqrt(b*b-c);
+ //assert(fabs(b-d) > 1e-10);
+ n0 = Point(b+d, 1);
+ n1 = Point(b-d, 1);
+ }
+
+ Line L0 = Line::from_origin_and_vector(B0, rot90(n0));
+ Line L1 = Line::from_origin_and_vector(B0, rot90(n1));
+
+ std::vector<double> rts = C1.roots(L0);
+ for(double rt : rts) {
+ Point P = L0.pointAt(rt);
+ res.push_back(P);
+ }
+ rts = C1.roots(L1);
+ for(double rt : rts) {
+ Point P = L1.pointAt(rt);
+ res.push_back(P);
+ }
+ } else {
+ // single or double line
+ // check for completely zero case (what to do?)
+ assert(xC0.c[0] || xC0.c[1] ||
+ xC0.c[2] || xC0.c[3] ||
+ xC0.c[4] || xC0.c[5]);
+ Point trial_pt(0,0);
+ Point g = xC0.gradient(trial_pt);
+ if(L2sq(g) == 0) {
+ trial_pt[0] += 1;
+ g = xC0.gradient(trial_pt);
+ if(L2sq(g) == 0) {
+ trial_pt[1] += 1;
+ g = xC0.gradient(trial_pt);
+ if(L2sq(g) == 0) {
+ trial_pt[0] += 1;
+ g = xC0.gradient(trial_pt);
+ if(L2sq(g) == 0) {
+ trial_pt = Point(1.5,0.5);
+ g = xC0.gradient(trial_pt);
+ }
+ }
+ }
+ }
+ //std::cout << trial_pt << ", " << g << "\n";
+ /**
+ * At this point we have tried up to 4 points: 0,0, 1,0, 1,1, 2,1, 1.5,1.5
+ *
+ * No degenerate conic can pass through these points, so we can assume
+ * that we've found a perpendicular to the double line.
+ * Proof:
+ * any degenerate must consist of at most 2 lines. 1.5,0.5 is not on any pair of lines
+ * passing through the previous 4 trials.
+ *
+ * alternatively, there may be a way to determine this directly from xC0
+ */
+ assert(L2sq(g) != 0);
+
+ Line Lx = Line::from_origin_and_vector(trial_pt, g); // a line along the gradient
+ std::vector<double> rts = xC0.roots(Lx);
+ for(double rt : rts) {
+ Point P0 = Lx.pointAt(rt);
+ //std::cout << P0 << "\n";
+ Line L = Line::from_origin_and_vector(P0, rot90(g));
+ std::vector<double> cnrts;
+ // It's very likely that at least one of the conics is degenerate, this will hopefully pick the more generate of the two.
+ if(fabs(C1.hessian().det()) > fabs(C2.hessian().det()))
+ cnrts = C1.roots(L);
+ else
+ cnrts = C2.roots(L);
+ for(double cnrt : cnrts) {
+ Point P = L.pointAt(cnrt);
+ res.push_back(P);
+ }
+ }
+ }
+ return res;
+}
+
+double xAx_descr(xAx const & C) {
+ double mC[3][3] = {{C.c[0], (C.c[1])/2, (C.c[3])/2},
+ {(C.c[1])/2, C.c[2], (C.c[4])/2},
+ {(C.c[3])/2, (C.c[4])/2, C.c[5]}};
+
+ return det3(mC);
+}
+
+
+std::vector<Point> intersect(xAx const & C1, xAx const & C2) {
+ // You know, if either of the inputs are degenerate we should use them first!
+ if(xAx_descr(C1) == 0) {
+ return decompose_degenerate(C1, C2, C1);
+ }
+ if(xAx_descr(C2) == 0) {
+ return decompose_degenerate(C1, C2, C2);
+ }
+ std::vector<Point> res;
+ SBasis T(Linear(-1,1));
+ SBasis S(Linear(1,1));
+ SBasis C[3][3] = {{T*C1.c[0]+S*C2.c[0], (T*C1.c[1]+S*C2.c[1])/2, (T*C1.c[3]+S*C2.c[3])/2},
+ {(T*C1.c[1]+S*C2.c[1])/2, T*C1.c[2]+S*C2.c[2], (T*C1.c[4]+S*C2.c[4])/2},
+ {(T*C1.c[3]+S*C2.c[3])/2, (T*C1.c[4]+S*C2.c[4])/2, T*C1.c[5]+S*C2.c[5]}};
+
+ SBasis D = det3(C);
+ std::vector<double> rts = Geom::roots(D);
+ if(rts.empty()) {
+ T = Linear(1,1);
+ S = Linear(-1,1);
+ SBasis C[3][3] = {{T*C1.c[0]+S*C2.c[0], (T*C1.c[1]+S*C2.c[1])/2, (T*C1.c[3]+S*C2.c[3])/2},
+ {(T*C1.c[1]+S*C2.c[1])/2, T*C1.c[2]+S*C2.c[2], (T*C1.c[4]+S*C2.c[4])/2},
+ {(T*C1.c[3]+S*C2.c[3])/2, (T*C1.c[4]+S*C2.c[4])/2, T*C1.c[5]+S*C2.c[5]}};
+
+ D = det3(C);
+ rts = Geom::roots(D);
+ }
+ // at this point we have a T and S and perhaps some roots that represent our degenerate conic
+ // Let's just pick one randomly (can we do better?)
+ //for(unsigned i = 0; i < rts.size(); i++) {
+ if(!rts.empty()) {
+ unsigned i = 0;
+ double t = T.valueAt(rts[i]);
+ double s = S.valueAt(rts[i]);
+ xAx xC0 = C1*t + C2*s;
+ //::draw(cr, xC0, screen_rect); // degen
+
+ return decompose_degenerate(C1, C2, xC0);
+
+
+ } else {
+ std::cout << "What?" << std::endl;
+ ;//std::cout << D << "\n";
+ }
+ return res;
+}
+
+
+xAx xAx::fromPoint(Point p) {
+ return xAx(1., 0, 1., -2*p[0], -2*p[1], dot(p,p));
+}
+
+xAx xAx::fromDistPoint(Point /*p*/, double /*d*/) {
+ return xAx();//1., 0, 1., -2*(1+d)*p[0], -2*(1+d)*p[1], dot(p,p)+d*d);
+}
+
+xAx xAx::fromLine(Point n, double d) {
+ return xAx(n[0]*n[0], 2*n[0]*n[1], n[1]*n[1], 2*d*n[0], 2*d*n[1], d*d);
+}
+
+xAx xAx::fromLine(Line l) {
+ double dist;
+ Point norm = l.normalAndDist(dist);
+
+ return fromLine(norm, dist);
+}
+
+xAx xAx::fromPoints(std::vector<Geom::Point> const &pt) {
+ Geom::NL::Vector V(pt.size(), -1.0);
+ Geom::NL::Matrix M(pt.size(), 5);
+ for(unsigned i = 0; i < pt.size(); i++) {
+ Geom::Point P = pt[i];
+ Geom::NL::VectorView vv = M.row_view(i);
+ vv[0] = P[0]*P[0];
+ vv[1] = P[0]*P[1];
+ vv[2] = P[1]*P[1];
+ vv[3] = P[0];
+ vv[4] = P[1];
+ }
+
+ Geom::NL::LinearSystem ls(M, V);
+
+ Geom::NL::Vector x = ls.SV_solve();
+ return Geom::xAx(x[0], x[1], x[2], x[3], x[4], 1);
+
+}
+
+
+
+double xAx::valueAt(Point P) const {
+ return evaluate_at(P[0], P[1]);
+}
+
+xAx xAx::scale(double sx, double sy) const {
+ return xAx(c[0]*sx*sx, c[1]*sx*sy, c[2]*sy*sy,
+ c[3]*sx, c[4]*sy, c[5]);
+}
+
+Point xAx::gradient(Point p) const{
+ double x = p[0];
+ double y = p[1];
+ return Point(2*c[0]*x + c[1]*y + c[3],
+ c[1]*x + 2*c[2]*y + c[4]);
+}
+
+xAx xAx::operator-(xAx const &b) const {
+ xAx res;
+ for(int i = 0; i < 6; i++) {
+ res.c[i] = c[i] - b.c[i];
+ }
+ return res;
+}
+xAx xAx::operator+(xAx const &b) const {
+ xAx res;
+ for(int i = 0; i < 6; i++) {
+ res.c[i] = c[i] + b.c[i];
+ }
+ return res;
+}
+xAx xAx::operator+(double const &b) const {
+ xAx res;
+ for(int i = 0; i < 5; i++) {
+ res.c[i] = c[i];
+ }
+ res.c[5] = c[5] + b;
+ return res;
+}
+
+xAx xAx::operator*(double const &b) const {
+ xAx res;
+ for(int i = 0; i < 6; i++) {
+ res.c[i] = c[i] * b;
+ }
+ return res;
+}
+
+ std::vector<Point> xAx::crossings(Rect r) const {
+ std::vector<Point> res;
+ for(int ei = 0; ei < 4; ei++) {
+ Geom::LineSegment ls(r.corner(ei), r.corner(ei+1));
+ D2<SBasis> lssb = ls.toSBasis();
+ SBasis edge_curve = evaluate_at(lssb[0], lssb[1]);
+ std::vector<double> rts = Geom::roots(edge_curve);
+ for(double rt : rts) {
+ res.push_back(lssb.valueAt(rt));
+ }
+ }
+ return res;
+}
+
+ std::optional<RatQuad> xAx::toCurve(Rect const & bnd) const {
+ std::vector<Point> crs = crossings(bnd);
+ if(crs.size() == 1) {
+ Point A = crs[0];
+ Point dA = rot90(gradient(A));
+ if(L2sq(dA) <= 1e-10) { // perhaps a single point?
+ return std::optional<RatQuad> ();
+ }
+ LineSegment ls = intersection(Line::from_origin_and_vector(A, dA), bnd);
+ return RatQuad::fromPointsTangents(A, dA, ls.pointAt(0.5), ls[1], dA);
+ }
+ else if(crs.size() >= 2 && crs.size() < 4) {
+ Point A = crs[0];
+ Point C = crs[1];
+ if(crs.size() == 3) {
+ if(distance(A, crs[2]) > distance(A, C))
+ C = crs[2];
+ else if(distance(C, crs[2]) > distance(A, C))
+ A = crs[2];
+ }
+ Line bisector = make_bisector_line(LineSegment(A, C));
+ std::vector<double> bisect_rts = this->roots(bisector);
+ if(!bisect_rts.empty()) {
+ int besti = -1;
+ for(unsigned i =0; i < bisect_rts.size(); i++) {
+ Point p = bisector.pointAt(bisect_rts[i]);
+ if(bnd.contains(p)) {
+ besti = i;
+ }
+ }
+ if(besti >= 0) {
+ Point B = bisector.pointAt(bisect_rts[besti]);
+
+ Point dA = gradient(A);
+ Point dC = gradient(C);
+ if(L2sq(dA) <= 1e-10 || L2sq(dC) <= 1e-10) {
+ return RatQuad::fromPointsTangents(A, C-A, B, C, A-C);
+ }
+
+ RatQuad rq = RatQuad::fromPointsTangents(A, rot90(dA),
+ B, C, rot90(dC));
+ return rq;
+ //std::vector<SBasis> hrq = rq.homogeneous();
+ /*SBasis vertex_poly = evaluate_at(hrq[0], hrq[1], hrq[2]);
+ std::vector<double> rts = roots(vertex_poly);
+ for(unsigned i = 0; i < rts.size(); i++) {
+ //draw_circ(cr, Point(rq.pointAt(rts[i])));
+ }*/
+ }
+ }
+ }
+ return std::optional<RatQuad>();
+}
+
+ std::vector<double> xAx::roots(Point d, Point o) const {
+ // Find the roots on line l
+ // form the quadratic Q(t) = 0 by composing l with xAx
+ double q2 = c[0]*d[0]*d[0] + c[1]*d[0]*d[1] + c[2]*d[1]*d[1];
+ double q1 = (2*c[0]*d[0]*o[0] +
+ c[1]*(d[0]*o[1]+d[1]*o[0]) +
+ 2*c[2]*d[1]*o[1] +
+ c[3]*d[0] + c[4]*d[1]);
+ double q0 = c[0]*o[0]*o[0] + c[1]*o[0]*o[1] + c[2]*o[1]*o[1] + c[3]*o[0] + c[4]*o[1] + c[5];
+ std::vector<double> r;
+ if(q2 == 0) {
+ if(q1 == 0) {
+ return r;
+ }
+ r.push_back(-q0/q1);
+ } else {
+ double desc = q1*q1 - 4*q2*q0;
+ /*std::cout << q2 << ", "
+ << q1 << ", "
+ << q0 << "; "
+ << desc << "\n";*/
+ if (desc < 0)
+ return r;
+ else if (desc == 0)
+ r.push_back(-q1/(2*q2));
+ else {
+ desc = std::sqrt(desc);
+ double t;
+ if (q1 == 0)
+ {
+ t = -0.5 * desc;
+ }
+ else
+ {
+ t = -0.5 * (q1 + sgn(q1) * desc);
+ }
+ r.push_back(t/q2);
+ r.push_back(q0/t);
+ }
+ }
+ return r;
+}
+
+std::vector<double> xAx::roots(Line const &l) const {
+ return roots(l.versor(), l.origin());
+}
+
+Interval xAx::quad_ex(double a, double b, double c, Interval ivl) {
+ double cx = -b*0.5/a;
+ Interval bnds((a*ivl.min()+b)*ivl.min()+c, (a*ivl.max()+b)*ivl.max()+c);
+ if(ivl.contains(cx))
+ bnds.expandTo((a*cx+b)*cx+c);
+ return bnds;
+}
+
+Geom::Affine xAx::hessian() const {
+ Geom::Affine m(2*c[0], c[1],
+ c[1], 2*c[2],
+ 0, 0);
+ return m;
+}
+
+
+std::optional<Point> solve(double A[2][2], double b[2]) {
+ double const determ = det(A);
+ if (determ != 0.0) { // hopeful, I know
+ Geom::Coord const ideterm = 1.0 / determ;
+
+ return Point ((A[1][1]*b[0] -A[0][1]*b[1]),
+ (-A[1][0]*b[0] + A[0][0]*b[1]))* ideterm;
+ } else {
+ return std::optional<Point>();
+ }
+}
+
+std::optional<Point> xAx::bottom() const {
+ double A[2][2] = {{2*c[0], c[1]},
+ {c[1], 2*c[2]}};
+ double b[2] = {-c[3], -c[4]};
+ return solve(A, b);
+ //return Point(-c[3], -c[4])*hessian().inverse();
+}
+
+Interval xAx::extrema(Rect r) const {
+ if (c[0] == 0 && c[1] == 0 && c[2] == 0) {
+ Interval ext(valueAt(r.corner(0)));
+ for(int i = 1; i < 4; i++)
+ ext |= Interval(valueAt(r.corner(i)));
+ return ext;
+ }
+ double k = r[X].min();
+ Interval ext = quad_ex(c[2], c[1]*k+c[4], (c[0]*k + c[3])*k + c[5], r[Y]);
+ k = r[X].max();
+ ext |= quad_ex(c[2], c[1]*k+c[4], (c[0]*k + c[3])*k + c[5], r[Y]);
+ k = r[Y].min();
+ ext |= quad_ex(c[0], c[1]*k+c[3], (c[2]*k + c[4])*k + c[5], r[X]);
+ k = r[Y].max();
+ ext |= quad_ex(c[0], c[1]*k+c[3], (c[2]*k + c[4])*k + c[5], r[X]);
+ std::optional<Point> B0 = bottom();
+ if (B0 && r.contains(*B0))
+ ext.expandTo(0);
+ return ext;
+}
+
+
+
+
+
+
+
+
+
+/*
+ * helper functions
+ */
+
+bool at_infinity (Point const& p)
+{
+ if (p[X] == infinity() || p[X] == -infinity()
+ || p[Y] == infinity() || p[Y] == -infinity())
+ {
+ return true;
+ }
+ return false;
+}
+
+inline
+double signed_triangle_area (Point const& p1, Point const& p2, Point const& p3)
+{
+ return (cross(p2, p3) - cross(p1, p3) + cross(p1, p2));
+}
+
+
+
+/*
+ * Define a conic section by computing the one that fits better with
+ * N points.
+ *
+ * points: points to fit
+ *
+ * precondition: there must be at least 5 non-overlapping points
+ */
+void xAx::set(std::vector<Point> const& points)
+{
+ size_t sz = points.size();
+ if (sz < 5)
+ {
+ THROW_RANGEERROR("fitting error: too few points passed");
+ }
+ NL::LFMConicSection model;
+ NL::least_squeares_fitter<NL::LFMConicSection> fitter(model, sz);
+
+ for (size_t i = 0; i < sz; ++i)
+ {
+ fitter.append(points[i]);
+ }
+ fitter.update();
+
+ NL::Vector z(sz, 0.0);
+ model.instance(*this, fitter.result(z));
+}
+
+/*
+ * Define a section conic by providing the coordinates of one of its vertex,
+ * the major axis inclination angle and the coordinates of its foci
+ * with respect to the unidimensional system defined by the major axis with
+ * origin set at the provided vertex.
+ *
+ * _vertex : section conic vertex V
+ * _angle : section conic major axis angle
+ * _dist1: +/-distance btw V and nearest focus
+ * _dist2: +/-distance btw V and farest focus
+ *
+ * prerequisite: _dist1 <= _dist2
+ */
+void xAx::set (const Point& _vertex, double _angle, double _dist1, double _dist2)
+{
+ using std::swap;
+
+ if (_dist2 == infinity() || _dist2 == -infinity()) // parabola
+ {
+ if (_dist1 == infinity()) // degenerate to a line
+ {
+ Line l(_vertex, _angle);
+ std::vector<double> lcoeff = l.coefficients();
+ coeff(3) = lcoeff[0];
+ coeff(4) = lcoeff[1];
+ coeff(5) = lcoeff[2];
+ return;
+ }
+
+ // y^2 - 4px == 0
+ double cD = -4 * _dist1;
+
+ double cosa = std::cos (_angle);
+ double sina = std::sin (_angle);
+ double cca = cosa * cosa;
+ double ssa = sina * sina;
+ double csa = cosa * sina;
+
+ coeff(0) = ssa;
+ coeff(1) = -2 * csa;
+ coeff(2) = cca;
+ coeff(3) = cD * cosa;
+ coeff(4) = cD * sina;
+
+ double VxVx = _vertex[X] * _vertex[X];
+ double VxVy = _vertex[X] * _vertex[Y];
+ double VyVy = _vertex[Y] * _vertex[Y];
+
+ coeff(5) = coeff(0) * VxVx + coeff(1) * VxVy + coeff(2) * VyVy
+ - coeff(3) * _vertex[X] - coeff(4) * _vertex[Y];
+ coeff(3) -= (2 * coeff(0) * _vertex[X] + coeff(1) * _vertex[Y]);
+ coeff(4) -= (2 * coeff(2) * _vertex[Y] + coeff(1) * _vertex[X]);
+
+ return;
+ }
+
+ if (std::fabs(_dist1) > std::fabs(_dist2))
+ {
+ swap (_dist1, _dist2);
+ }
+ if (_dist1 < 0)
+ {
+ _angle -= M_PI;
+ _dist1 = -_dist1;
+ _dist2 = -_dist2;
+ }
+
+ // ellipse and hyperbola
+ double lin_ecc = (_dist2 - _dist1) / 2;
+ double rx = (_dist2 + _dist1) / 2;
+
+ double cA = rx * rx - lin_ecc * lin_ecc;
+ double cC = rx * rx;
+ double cF = - cA * cC;
+// std::cout << "cA: " << cA << std::endl;
+// std::cout << "cC: " << cC << std::endl;
+// std::cout << "cF: " << cF << std::endl;
+
+ double cosa = std::cos (_angle);
+ double sina = std::sin (_angle);
+ double cca = cosa * cosa;
+ double ssa = sina * sina;
+ double csa = cosa * sina;
+
+ coeff(0) = cca * cA + ssa * cC;
+ coeff(2) = ssa * cA + cca * cC;
+ coeff(1) = 2 * csa * (cA - cC);
+
+ Point C (rx * cosa + _vertex[X], rx * sina + _vertex[Y]);
+ double CxCx = C[X] * C[X];
+ double CxCy = C[X] * C[Y];
+ double CyCy = C[Y] * C[Y];
+
+ coeff(3) = -2 * coeff(0) * C[X] - coeff(1) * C[Y];
+ coeff(4) = -2 * coeff(2) * C[Y] - coeff(1) * C[X];
+ coeff(5) = cF + coeff(0) * CxCx + coeff(1) * CxCy + coeff(2) * CyCy;
+}
+
+/*
+ * Define a conic section by providing one of its vertex and its foci.
+ *
+ * _vertex: section conic vertex
+ * _focus1: section conic focus
+ * _focus2: section conic focus
+ */
+void xAx::set (const Point& _vertex, const Point& _focus1, const Point& _focus2)
+{
+ if (at_infinity(_vertex))
+ {
+ THROW_RANGEERROR("case not handled: vertex at infinity");
+ }
+ if (at_infinity(_focus2))
+ {
+ if (at_infinity(_focus1))
+ {
+ THROW_RANGEERROR("case not handled: both focus at infinity");
+ }
+ Point VF = _focus1 - _vertex;
+ double dist1 = L2(VF);
+ double angle = atan2(VF);
+ set(_vertex, angle, dist1, infinity());
+ return;
+ }
+ else if (at_infinity(_focus1))
+ {
+ Point VF = _focus2 - _vertex;
+ double dist1 = L2(VF);
+ double angle = atan2(VF);
+ set(_vertex, angle, dist1, infinity());
+ return;
+ }
+ assert (are_collinear (_vertex, _focus1, _focus2));
+ if (!are_near(_vertex, _focus1))
+ {
+ Point VF = _focus1 - _vertex;
+ Line axis(_vertex, _focus1);
+ double angle = atan2(VF);
+ double dist1 = L2(VF);
+ double dist2 = distance (_vertex, _focus2);
+ double t = axis.timeAt(_focus2);
+ if (t < 0) dist2 = -dist2;
+// std::cout << "t = " << t << std::endl;
+// std::cout << "dist2 = " << dist2 << std::endl;
+ set (_vertex, angle, dist1, dist2);
+ }
+ else if (!are_near(_vertex, _focus2))
+ {
+ Point VF = _focus2 - _vertex;
+ double angle = atan2(VF);
+ double dist1 = 0;
+ double dist2 = L2(VF);
+ set (_vertex, angle, dist1, dist2);
+ }
+ else
+ {
+ coeff(0) = coeff(2) = 1;
+ coeff(1) = coeff(3) = coeff(4) = coeff(5) = 0;
+ }
+}
+
+/*
+ * Define a conic section by passing a focus, the related directrix,
+ * and the eccentricity (e)
+ * (e < 1 -> ellipse; e = 1 -> parabola; e > 1 -> hyperbola)
+ *
+ * _focus: a focus of the conic section
+ * _directrix: the directrix related to the given focus
+ * _eccentricity: the eccentricity parameter of the conic section
+ */
+void xAx::set (const Point & _focus, const Line & _directrix, double _eccentricity)
+{
+ Point O = _directrix.pointAt (_directrix.timeAtProjection (_focus));
+ //std::cout << "O = " << O << std::endl;
+ Point OF = _focus - O;
+ double p = L2(OF);
+
+ coeff(0) = 1 - _eccentricity * _eccentricity;
+ coeff(1) = 0;
+ coeff(2) = 1;
+ coeff(3) = -2 * p;
+ coeff(4) = 0;
+ coeff(5) = p * p;
+
+ double angle = atan2 (OF);
+
+ (*this) = rotate (angle);
+ //std::cout << "O = " << O << std::endl;
+ (*this) = translate (O);
+}
+
+/*
+ * Made up a degenerate conic section as a pair of lines
+ *
+ * l1, l2: lines that made up the conic section
+ */
+void xAx::set (const Line& l1, const Line& l2)
+{
+ std::vector<double> cl1 = l1.coefficients();
+ std::vector<double> cl2 = l2.coefficients();
+
+ coeff(0) = cl1[0] * cl2[0];
+ coeff(2) = cl1[1] * cl2[1];
+ coeff(5) = cl1[2] * cl2[2];
+ coeff(1) = cl1[0] * cl2[1] + cl1[1] * cl2[0];
+ coeff(3) = cl1[0] * cl2[2] + cl1[2] * cl2[0];
+ coeff(4) = cl1[1] * cl2[2] + cl1[2] * cl2[1];
+}
+
+
+
+/*
+ * Return the section conic kind
+ */
+xAx::kind_t xAx::kind () const
+{
+
+ xAx conic(*this);
+ NL::SymmetricMatrix<3> C = conic.get_matrix();
+ NL::ConstSymmetricMatrixView<2> A = C.main_minor_const_view();
+
+ double t1 = trace(A);
+ double t2 = det(A);
+ //double T3 = det(C);
+ int st1 = trace_sgn(A);
+ int st2 = det_sgn(A);
+ int sT3 = det_sgn(C);
+
+ //std::cout << "T3 = " << T3 << std::endl;
+ //std::cout << "sT3 = " << sT3 << std::endl;
+ //std::cout << "t2 = " << t2 << std::endl;
+ //std::cout << "t1 = " << t1 << std::endl;
+ //std::cout << "st2 = " << st2 << std::endl;
+
+ if (sT3 != 0)
+ {
+ if (st2 == 0)
+ {
+ return PARABOLA;
+ }
+ else if (st2 == 1)
+ {
+
+ if (sT3 * st1 < 0)
+ {
+ NL::SymmetricMatrix<2> discr;
+ discr(0,0) = 4; discr(1,1) = t2; discr(1,0) = t1;
+ int discr_sgn = - det_sgn (discr);
+ //std::cout << "t1 * t1 - 4 * t2 = "
+ // << (t1 * t1 - 4 * t2) << std::endl;
+ //std::cout << "discr_sgn = " << discr_sgn << std::endl;
+ if (discr_sgn == 0)
+ {
+ return CIRCLE;
+ }
+ else
+ {
+ return REAL_ELLIPSE;
+ }
+ }
+ else // sT3 * st1 > 0
+ {
+ return IMAGINARY_ELLIPSE;
+ }
+ }
+ else // t2 < 0
+ {
+ if (st1 == 0)
+ {
+ return RECTANGULAR_HYPERBOLA;
+ }
+ else
+ {
+ return HYPERBOLA;
+ }
+ }
+ }
+ else // T3 == 0
+ {
+ if (st2 == 0)
+ {
+ //double T2 = NL::trace<2>(C);
+ int sT2 = NL::trace_sgn<2>(C);
+ //std::cout << "T2 = " << T2 << std::endl;
+ //std::cout << "sT2 = " << sT2 << std::endl;
+
+ if (sT2 == 0)
+ {
+ return DOUBLE_LINE;
+ }
+ if (sT2 == -1)
+ {
+ return TWO_REAL_PARALLEL_LINES;
+ }
+ else // T2 > 0
+ {
+ return TWO_IMAGINARY_PARALLEL_LINES;
+ }
+ }
+ else if (st2 == -1)
+ {
+ return TWO_REAL_CROSSING_LINES;
+ }
+ else // t2 > 0
+ {
+ return TWO_IMAGINARY_CROSSING_LINES;
+ }
+ }
+ return UNKNOWN;
+}
+
+/*
+ * Return a string representing the conic section kind
+ */
+std::string xAx::categorise() const
+{
+ kind_t KIND = kind();
+
+ switch (KIND)
+ {
+ case PARABOLA :
+ return "parabola";
+ case CIRCLE :
+ return "circle";
+ case REAL_ELLIPSE :
+ return "real ellispe";
+ case IMAGINARY_ELLIPSE :
+ return "imaginary ellispe";
+ case RECTANGULAR_HYPERBOLA :
+ return "rectangular hyperbola";
+ case HYPERBOLA :
+ return "hyperbola";
+ case DOUBLE_LINE :
+ return "double line";
+ case TWO_REAL_PARALLEL_LINES :
+ return "two real parallel lines";
+ case TWO_IMAGINARY_PARALLEL_LINES :
+ return "two imaginary parallel lines";
+ case TWO_REAL_CROSSING_LINES :
+ return "two real crossing lines";
+ case TWO_IMAGINARY_CROSSING_LINES :
+ return "two imaginary crossing lines";
+ default :
+ return "unknown";
+ }
+}
+
+/*
+ * Compute the solutions of the conic section algebraic equation with respect to
+ * one coordinate after substituting to the other coordinate the passed value
+ *
+ * sol: the computed solutions
+ * v: the provided value
+ * d: the index of the coordinate the passed value have to be substituted to
+ */
+void xAx::roots (std::vector<double>& sol, Coord v, Dim2 d) const
+{
+ sol.clear();
+ if (d < 0 || d > Y)
+ {
+ THROW_RANGEERROR("dimension parameter out of range");
+ }
+
+ // p*t^2 + q*t + r = 0;
+ double p, q, r;
+
+ if (d == X)
+ {
+ p = coeff(2);
+ q = coeff(4) + coeff(1) * v;
+ r = coeff(5) + (coeff(0) * v + coeff(3)) * v;
+ }
+ else
+ {
+ p = coeff(0);
+ q = coeff(3) + coeff(1) * v;
+ r = coeff(5) + (coeff(2) * v + coeff(4)) * v;
+ }
+
+ if (p == 0)
+ {
+ if (q == 0) return;
+ double t = -r/q;
+ sol.push_back(t);
+ return;
+ }
+
+ if (q == 0)
+ {
+ if ((p > 0 && r > 0) || (p < 0 && r < 0)) return;
+ double t = -r / p;
+ t = std::sqrt (t);
+ sol.push_back(-t);
+ sol.push_back(t);
+ return;
+ }
+
+ if (r == 0)
+ {
+ double t = -q/p;
+ sol.push_back(0);
+ sol.push_back(t);
+ return;
+ }
+
+
+ //std::cout << "p = " << p << ", q = " << q << ", r = " << r << std::endl;
+ double delta = q * q - 4 * p * r;
+ if (delta < 0) return;
+ if (delta == 0)
+ {
+ double t = -q / (2 * p);
+ sol.push_back(t);
+ return;
+ }
+ // else
+ double srd = std::sqrt(delta);
+ double t = - (q + sgn(q) * srd) / 2;
+ sol.push_back (t/p);
+ sol.push_back (r/t);
+
+}
+
+/*
+ * Return the inclination angle of the major axis of the conic section
+ */
+double xAx::axis_angle() const
+{
+ if (coeff(0) == 0 && coeff(1) == 0 && coeff(2) == 0)
+ {
+ Line l (coeff(3), coeff(4), coeff(5));
+ return l.angle();
+ }
+ if (coeff(1) == 0 && (coeff(0) == coeff(2))) return 0;
+
+ double angle;
+
+ int sgn_discr = det_sgn (get_matrix().main_minor_const_view());
+ if (sgn_discr == 0)
+ {
+ //std::cout << "rotation_angle: sgn_discr = "
+ // << sgn_discr << std::endl;
+ angle = std::atan2 (-coeff(1), 2 * coeff(2));
+ if (angle < 0) angle += 2*M_PI;
+ if (angle >= M_PI) angle -= M_PI;
+
+ }
+ else
+ {
+ angle = std::atan2 (coeff(1), coeff(0) - coeff(2));
+ if (angle < 0) angle += 2*M_PI;
+ angle -= M_PI;
+ if (angle < 0) angle += 2*M_PI;
+ angle /= 2;
+ if (angle >= M_PI) angle -= M_PI;
+ }
+ //std::cout << "rotation_angle : angle = " << angle << std::endl;
+ return angle;
+}
+
+/*
+ * Translate the conic section by the given vector offset
+ *
+ * _offset: represent the vector offset
+ */
+xAx xAx::translate (const Point & _offset) const
+{
+ double B = coeff(1) / 2;
+ double D = coeff(3) / 2;
+ double E = coeff(4) / 2;
+
+ Point T = - _offset;
+
+ xAx cs;
+ cs.coeff(0) = coeff(0);
+ cs.coeff(1) = coeff(1);
+ cs.coeff(2) = coeff(2);
+
+ Point DE;
+ DE[0] = coeff(0) * T[0] + B * T[1];
+ DE[1] = B * T[0] + coeff(2) * T[1];
+
+ cs.coeff(3) = (DE[0] + D) * 2;
+ cs.coeff(4) = (DE[1] + E) * 2;
+
+ cs.coeff(5) = dot (T, DE) + 2 * (T[0] * D + T[1] * E) + coeff(5);
+
+ return cs;
+}
+
+
+/*
+ * Rotate the conic section by the given angle wrt the point (0,0)
+ *
+ * angle: represent the rotation angle
+ */
+xAx xAx::rotate (double angle) const
+{
+ double c = std::cos(-angle);
+ double s = std::sin(-angle);
+ double cc = c * c;
+ double ss = s * s;
+ double cs = c * s;
+
+ xAx result;
+ result.coeff(5) = coeff(5);
+
+ // quadratic terms
+ double Bcs = coeff(1) * cs;
+
+ result.coeff(0) = coeff(0) * cc + Bcs + coeff(2) * ss;
+ result.coeff(2) = coeff(0) * ss - Bcs + coeff(2) * cc;
+ result.coeff(1) = coeff(1) * (cc - ss) + 2 * (coeff(2) - coeff(0)) * cs;
+
+ // linear terms
+ result.coeff(3) = coeff(3) * c + coeff(4) * s;
+ result.coeff(4) = coeff(4) * c - coeff(3) * s;
+
+ return result;
+}
+
+
+/*
+ * Decompose a degenerate conic in two lines the conic section is made by.
+ * Return true if the decomposition is successful, else if it fails.
+ *
+ * l1, l2: out parameters where the decomposed conic section is returned
+ */
+bool xAx::decompose (Line& l1, Line& l2) const
+{
+ NL::SymmetricMatrix<3> C = get_matrix();
+ if (!is_quadratic() || !isDegenerate())
+ {
+ return false;
+ }
+ NL::Matrix M(C);
+ NL::SymmetricMatrix<3> D = -adj(C);
+
+ if (!D.is_zero()) // D == 0 <=> rank(C) < 2
+ {
+
+ //if (D.get<0,0>() < 0 || D.get<1,1>() < 0 || D.get<2,2>() < 0)
+ //{
+ //std::cout << "C: \n" << C << std::endl;
+ //std::cout << "D: \n" << D << std::endl;
+
+ /*
+ * This case should be impossible because any diagonal element
+ * of D is a square, but due to non exact aritmethic computation
+ * it can actually happen; however the algorithm seems to work
+ * correctly even if some diagonal term is negative, the only
+ * difference is that we should compute the absolute value of
+ * diagonal elements. So until we elaborate a better degenerate
+ * test it's better not rising exception when we have a negative
+ * diagonal element.
+ */
+ //}
+
+ NL::Vector d(3);
+ d[0] = std::fabs (D.get<0,0>());
+ d[1] = std::fabs (D.get<1,1>());
+ d[2] = std::fabs (D.get<2,2>());
+
+ size_t idx = d.max_index();
+ if (d[idx] == 0)
+ {
+ THROW_LOGICALERROR ("xAx::decompose: "
+ "rank 2 but adjoint with null diagonal");
+ }
+ d[0] = D(idx,0); d[1] = D(idx,1); d[2] = D(idx,2);
+ d.scale (1 / std::sqrt (std::fabs (D(idx,idx))));
+ M(1,2) += d[0]; M(2,1) -= d[0];
+ M(0,2) -= d[1]; M(2,0) += d[1];
+ M(0,1) += d[2]; M(1,0) -= d[2];
+
+ //std::cout << "C: \n" << C << std::endl;
+ //std::cout << "D: \n" << D << std::endl;
+ //std::cout << "d = " << d << std::endl;
+ //std::cout << "M = " << M << std::endl;
+ }
+
+ std::pair<size_t, size_t> max_ij = M.max_index();
+ std::pair<size_t, size_t> min_ij = M.min_index();
+ double abs_max = std::fabs (M(max_ij.first, max_ij.second));
+ double abs_min = std::fabs (M(min_ij.first, min_ij.second));
+ size_t i_max, j_max;
+ if (abs_max > abs_min)
+ {
+ i_max = max_ij.first;
+ j_max = max_ij.second;
+ }
+ else
+ {
+ i_max = min_ij.first;
+ j_max = min_ij.second;
+ }
+ l1.setCoefficients (M(i_max,0), M(i_max,1), M(i_max,2));
+ l2.setCoefficients (M(0, j_max), M(1,j_max), M(2,j_max));
+
+ return true;
+}
+
+std::array<Line, 2> xAx::decompose_df(Coord epsilon) const
+{
+ // For the classification of degenerate conics, see https://mathworld.wolfram.com/QuadraticCurve.html
+ using std::sqrt, std::abs;
+
+ // Create 2 degenerate lines
+ auto const origin = Point(0, 0);
+ std::array<Line, 2> result = {Line(origin, origin), Line(origin, origin)};
+
+ double A = c[0];
+ double B = c[1];
+ double C = c[2];
+ double D = c[3];
+ double E = c[4];
+ double F = c[5];
+ Coord discriminant = sqr(B) - 4 * A * C;
+ if (discriminant < -epsilon) {
+ return result;
+ }
+
+ bool single_line = false; // In the generic case, there will be 2 lines.
+ bool parallel_lines = false;
+ if (discriminant < epsilon) {
+ discriminant = 0;
+ parallel_lines = true;
+ // Check the secondary discriminant
+ Coord const secondary = sqr(D) + sqr(E) - 4 * F * (A + C);
+ if (secondary < -epsilon) {
+ return result;
+ }
+ single_line = (secondary < epsilon);
+ }
+
+ if (abs(A) > epsilon || abs(C) > epsilon) {
+ // This is the typical case: either x² or y² come with a nonzero coefficient.
+ // To guard against numerical errors, we check which of the coefficients A, C has larger absolute value.
+
+ bool const swap_xy = abs(C) > abs(A);
+ if (swap_xy) {
+ std::swap(A, C);
+ std::swap(D, E);
+ }
+
+ // From now on, we may assume that A is "reasonably large".
+ if (parallel_lines) {
+ if (single_line) {
+ // Special case: a single line.
+ std::array<double, 3> coeffs = {sqrt(abs(A)), sqrt(abs(C)), sqrt(abs(F))};
+ if (swap_xy) {
+ std::swap(coeffs[0], coeffs[1]);
+ }
+ rescale_homogenous(coeffs);
+ result[0].setCoefficients(coeffs[0], coeffs[1], coeffs[2]);
+ return result;
+ }
+
+ // Two parallel lines.
+ Coord const quotient_discriminant = sqr(D) - 4 * A * F;
+ if (quotient_discriminant < 0) {
+ return result;
+ }
+ Coord const sqrt_disc = sqrt(quotient_discriminant);
+ double const c1 = 0.5 * (D - sqrt_disc);
+ double const c2 = c1 + sqrt_disc;
+ std::array<double, 3> coeffs = {A, 0.5 * B, c1};
+ if (swap_xy) {
+ std::swap(coeffs[0], coeffs[1]);
+ }
+ rescale_homogenous(coeffs);
+ result[0].setCoefficients(coeffs[0], coeffs[1], coeffs[2]);
+
+ coeffs = {A, 0.5 * B, c2};
+ if (swap_xy) {
+ std::swap(coeffs[0], coeffs[1]);
+ }
+ rescale_homogenous(coeffs);
+ result[1].setCoefficients(coeffs[0], coeffs[1], coeffs[2]);
+ return result;
+ }
+
+ // Now for the typical case of 2 non-parallel lines.
+
+ // We know that A is further away from 0 than C is.
+ // The mathematical derivation of the solution is as follows:
+ // let Δ = B² - 4AC (the discriminant); we know Δ > 0.
+ // Write δ = sqrt(Δ); we know that this is also positive.
+ // Then the product AΔ is nonzero, so the equation
+ // Ax² + Bxy + Cy² + Dx + Ey + F = 0
+ // is equivalent to
+ // AΔ (Ax² + Bxy + Cy² + Dx + Ey + F) = 0.
+ // Consider the two factors
+ // L_1 = Aδx + 0.5 (Bδ-Δ)y + EA - 0.5 D(B-δ)
+ // L_2 = Aδx + 0.5 (Bδ+Δ)y - EA + 0.5 D(B+δ)
+ // With a bit of algebra, you can show that L_1 * L_2 expands
+ // to AΔ (Ax² + Bxy + Cy² + Dx + Ey + F) (in order to get the
+ // correct value of F, you have to use the fact that the conic
+ // is degenerate). Therefore, the factors L_1 and L_2 are in
+ // fact equations of the two lines to be found.
+ Coord const delta = sqrt(discriminant);
+ std::array<double, 3> coeffs1 = {A * delta, 0.5 * (B * delta - discriminant), E * A - 0.5 * D * (B - delta)};
+ std::array<double, 3> coeffs2 = {coeffs1[0], coeffs1[1] + discriminant, D * delta - coeffs1[2]};
+ if (swap_xy) { // We must unswap the coefficients of x and y
+ std::swap(coeffs1[0], coeffs1[1]);
+ std::swap(coeffs2[0], coeffs2[1]);
+ }
+
+ unsigned index = 0;
+ if (coeffs1[0] != 0 || coeffs1[1] != 0) {
+ rescale_homogenous(coeffs1);
+ result[index++].setCoefficients(coeffs1[0], coeffs1[1], coeffs1[2]);
+ }
+ if (coeffs2[0] != 0 || coeffs2[1] != 0) {
+ rescale_homogenous(coeffs2);
+ result[index].setCoefficients(coeffs2[0], coeffs2[1], coeffs2[2]);
+ }
+ return result;
+ }
+
+ // If we're here, then A==0 and C==0.
+ if (abs(B) < epsilon) { // A == B == C == 0, so the conic reduces to Dx + Ey + F.
+ if (D == 0 && E == 0) {
+ return result;
+ }
+ std::array<double, 3> coeffs = {D, E, F};
+ rescale_homogenous(coeffs);
+ result[0].setCoefficients(coeffs[0], coeffs[1], coeffs[2]);
+ return result;
+ }
+
+ // OK, so A == C == 0 but B != 0. In other words, the conic has the form
+ // Bxy + Dx + Ey + F. Since B != 0, the zero set stays the same if we multiply the
+ // equation by B, which gives us this equation:
+ // B²xy + BDx + BEy + BF = 0.
+ // The above factors as (Bx + E)(By + D) = 0.
+ std::array<double, 2> nonzero_coeffs = {B, E};
+ rescale_homogenous(nonzero_coeffs);
+ result[0].setCoefficients(nonzero_coeffs[0], 0, nonzero_coeffs[1]);
+
+ nonzero_coeffs = {B, D};
+ rescale_homogenous(nonzero_coeffs);
+ result[1].setCoefficients(0, nonzero_coeffs[0], nonzero_coeffs[1]);
+ return result;
+}
+
+/*
+ * Return the rectangle that bound the conic section arc characterized by
+ * the passed points.
+ *
+ * P1: the initial point of the arc
+ * Q: the inner point of the arc
+ * P2: the final point of the arc
+ *
+ * prerequisite: the passed points must lie on the conic
+ */
+Rect xAx::arc_bound (const Point & P1, const Point & Q, const Point & P2) const
+{
+ using std::swap;
+ //std::cout << "BOUND: P1 = " << P1 << std::endl;
+ //std::cout << "BOUND: Q = " << Q << std::endl;
+ //std::cout << "BOUND: P2 = " << P2 << std::endl;
+
+ Rect B(P1, P2);
+ double Qside = signed_triangle_area (P1, Q, P2);
+ //std::cout << "BOUND: Qside = " << Qside << std::endl;
+
+ Line gl[2];
+ bool empty[2] = {false, false};
+
+ try // if the passed coefficients lead to an equation 0x + 0y + c == 0,
+ { // with c != 0 the setCoefficients rise an exception
+ gl[0].setCoefficients (coeff(1), 2 * coeff(2), coeff(4));
+ }
+ catch(Geom::LogicalError const &e)
+ {
+ empty[0] = true;
+ }
+
+ try
+ {
+ gl[1].setCoefficients (2 * coeff(0), coeff(1), coeff(3));
+ }
+ catch(Geom::LogicalError const &e)
+ {
+ empty[1] = true;
+ }
+
+ std::vector<double> rts;
+ std::vector<Point> M;
+ for (size_t dim = 0; dim < 2; ++dim)
+ {
+ if (empty[dim]) continue;
+ rts = roots (gl[dim]);
+ M.clear();
+ for (double rt : rts)
+ M.push_back (gl[dim].pointAt (rt));
+ if (M.size() == 1)
+ {
+ double Mside = signed_triangle_area (P1, M[0], P2);
+ if (sgn(Mside) == sgn(Qside))
+ {
+ //std::cout << "BOUND: M.size() == 1" << std::endl;
+ B[dim].expandTo(M[0][dim]);
+ }
+ }
+ else if (M.size() == 2)
+ {
+ //std::cout << "BOUND: M.size() == 2" << std::endl;
+ if (M[0][dim] > M[1][dim])
+ swap (M[0], M[1]);
+
+ if (M[0][dim] > B[dim].max())
+ {
+ double Mside = signed_triangle_area (P1, M[0], P2);
+ if (sgn(Mside) == sgn(Qside))
+ B[dim].setMax(M[0][dim]);
+ }
+ else if (M[1][dim] < B[dim].min())
+ {
+ double Mside = signed_triangle_area (P1, M[1], P2);
+ if (sgn(Mside) == sgn(Qside))
+ B[dim].setMin(M[1][dim]);
+ }
+ else
+ {
+ double Mside = signed_triangle_area (P1, M[0], P2);
+ if (sgn(Mside) == sgn(Qside))
+ B[dim].setMin(M[0][dim]);
+ Mside = signed_triangle_area (P1, M[1], P2);
+ if (sgn(Mside) == sgn(Qside))
+ B[dim].setMax(M[1][dim]);
+ }
+ }
+ }
+
+ return B;
+}
+
+/*
+ * Return all points on the conic section nearest to the passed point "P".
+ *
+ * P: the point to compute the nearest one
+ */
+std::vector<Point> xAx::allNearestTimes (const Point &P) const
+{
+ // TODO: manage the circle - centre case
+ std::vector<Point> points;
+
+ // named C the conic we look for points (x,y) on C such that
+ // dot (grad (C(x,y)), rot90 (P -(x,y))) == 0; the set of points satisfying
+ // this equation is still a conic G, so the wanted points can be found by
+ // intersecting C with G
+ xAx G (-coeff(1),
+ 2 * (coeff(0) - coeff(2)),
+ coeff(1),
+ -coeff(4) + coeff(1) * P[X] - 2 * coeff(0) * P[Y],
+ coeff(3) - coeff(1) * P[Y] + 2 * coeff(2) * P[X],
+ -coeff(3) * P[Y] + coeff(4) * P[X]);
+
+ std::vector<Point> crs = intersect (*this, G);
+
+ //std::cout << "NEAREST POINT: crs.size = " << crs.size() << std::endl;
+ if (crs.empty()) return points;
+
+ size_t idx = 0;
+ double mindist = distanceSq (crs[0], P);
+ std::vector<double> dist;
+ dist.push_back (mindist);
+
+ for (size_t i = 1; i < crs.size(); ++i)
+ {
+ dist.push_back (distanceSq (crs[i], P));
+ if (mindist > dist.back())
+ {
+ idx = i;
+ mindist = dist.back();
+ }
+ }
+
+ points.push_back (crs[idx]);
+ for (size_t i = 0; i < crs.size(); ++i)
+ {
+ if (i == idx) continue;
+ if (dist[i] == mindist)
+ points.push_back (crs[i]);
+ }
+
+ return points;
+}
+
+
+
+bool clip (std::vector<RatQuad> & rq, const xAx & cs, const Rect & R)
+{
+ clipper aclipper (cs, R);
+ return aclipper.clip (rq);
+}
+
+
+} // end namespace Geom
+
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/convex-hull.cpp b/src/3rdparty/2geom/src/2geom/convex-hull.cpp
new file mode 100644
index 0000000..f801fcc
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/convex-hull.cpp
@@ -0,0 +1,746 @@
+/** @file
+ * @brief Convex hull of a set of points
+ *//*
+ * Authors:
+ * Nathan Hurst <njh@mail.csse.monash.edu.au>
+ * Michael G. Sloan <mgsloan@gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ * Copyright 2006-2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <2geom/convex-hull.h>
+#include <2geom/exception.h>
+#include <algorithm>
+#include <map>
+#include <iostream>
+#include <cassert>
+#include <boost/array.hpp>
+
+/** Todo:
+ + modify graham scan to work top to bottom, rather than around angles
+ + intersection
+ + minimum distance between convex hulls
+ + maximum distance between convex hulls
+ + hausdorf metric?
+ + check all degenerate cases carefully
+ + check all algorithms meet all invariants
+ + generalise rotating caliper algorithm (iterator/circulator?)
+*/
+
+using std::vector;
+using std::map;
+using std::pair;
+using std::make_pair;
+using std::swap;
+
+namespace Geom {
+
+ConvexHull::ConvexHull(Point const &a, Point const &b)
+ : _boundary(2)
+ , _lower(0)
+{
+ _boundary[0] = a;
+ _boundary[1] = b;
+ std::sort(_boundary.begin(), _boundary.end(), Point::LexLess<X>());
+ _construct();
+}
+
+ConvexHull::ConvexHull(Point const &a, Point const &b, Point const &c)
+ : _boundary(3)
+ , _lower(0)
+{
+ _boundary[0] = a;
+ _boundary[1] = b;
+ _boundary[2] = c;
+ std::sort(_boundary.begin(), _boundary.end(), Point::LexLess<X>());
+ _construct();
+}
+
+ConvexHull::ConvexHull(Point const &a, Point const &b, Point const &c, Point const &d)
+ : _boundary(4)
+ , _lower(0)
+{
+ _boundary[0] = a;
+ _boundary[1] = b;
+ _boundary[2] = c;
+ _boundary[3] = d;
+ std::sort(_boundary.begin(), _boundary.end(), Point::LexLess<X>());
+ _construct();
+}
+
+ConvexHull::ConvexHull(std::vector<Point> const &pts)
+ : _lower(0)
+{
+ //if (pts.size() > 16) { // arbitrary threshold
+ // _prune(pts.begin(), pts.end(), _boundary);
+ //} else {
+ _boundary = pts;
+ std::sort(_boundary.begin(), _boundary.end(), Point::LexLess<X>());
+ //}
+ _construct();
+}
+
+bool ConvexHull::_is_clockwise_turn(Point const &a, Point const &b, Point const &c)
+{
+ if (b == c) return false;
+ return cross(b-a, c-a) > 0;
+}
+
+void ConvexHull::_construct()
+{
+ // _boundary must already be sorted in LexLess<X> order
+ if (_boundary.empty()) {
+ _lower = 0;
+ return;
+ }
+ if (_boundary.size() == 1 || (_boundary.size() == 2 && _boundary[0] == _boundary[1])) {
+ _boundary.resize(1);
+ _lower = 1;
+ return;
+ }
+ if (_boundary.size() == 2) {
+ _lower = 2;
+ return;
+ }
+
+ std::size_t k = 2;
+ for (std::size_t i = 2; i < _boundary.size(); ++i) {
+ while (k >= 2 && !_is_clockwise_turn(_boundary[k-2], _boundary[k-1], _boundary[i])) {
+ --k;
+ }
+ std::swap(_boundary[k++], _boundary[i]);
+ }
+
+ _lower = k;
+ std::sort(_boundary.begin() + k, _boundary.end(), Point::LexGreater<X>());
+ _boundary.push_back(_boundary.front());
+ for (std::size_t i = _lower; i < _boundary.size(); ++i) {
+ while (k > _lower && !_is_clockwise_turn(_boundary[k-2], _boundary[k-1], _boundary[i])) {
+ --k;
+ }
+ std::swap(_boundary[k++], _boundary[i]);
+ }
+
+ _boundary.resize(k-1);
+}
+
+double ConvexHull::area() const
+{
+ if (size() <= 2) return 0;
+
+ double a = 0;
+ for (std::size_t i = 0; i < size()-1; ++i) {
+ a += cross(_boundary[i], _boundary[i+1]);
+ }
+ a += cross(_boundary.back(), _boundary.front());
+ return fabs(a * 0.5);
+}
+
+OptRect ConvexHull::bounds() const
+{
+ OptRect ret;
+ if (empty()) return ret;
+ ret = Rect(left(), top(), right(), bottom());
+ return ret;
+}
+
+Point ConvexHull::topPoint() const
+{
+ Point ret;
+ ret[Y] = std::numeric_limits<Coord>::infinity();
+
+ for (auto i : upperHull()) {
+ if (ret[Y] >= i.y()) {
+ ret = i;
+ } else {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+Point ConvexHull::bottomPoint() const
+{
+ Point ret;
+ ret[Y] = -std::numeric_limits<Coord>::infinity();
+
+ for (auto j : lowerHull()) {
+ if (ret[Y] <= j.y()) {
+ ret = j;
+ } else {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+template <typename Iter, typename Lex>
+bool below_x_monotonic_polyline(Point const &p, Iter first, Iter last, Lex lex)
+{
+ typename Lex::Secondary above;
+ Iter f = std::lower_bound(first, last, p, lex);
+ if (f == last) return false;
+ if (f == first) {
+ if (p == *f) return true;
+ return false;
+ }
+
+ Point a = *(f-1), b = *f;
+ if (a[X] == b[X]) {
+ if (above(p[Y], a[Y]) || above(b[Y], p[Y])) return false;
+ } else {
+ // TODO: maybe there is a more numerically stable method
+ Coord y = lerp((p[X] - a[X]) / (b[X] - a[X]), a[Y], b[Y]);
+ if (above(p[Y], y)) return false;
+ }
+ return true;
+}
+
+bool ConvexHull::contains(Point const &p) const
+{
+ if (_boundary.empty()) return false;
+ if (_boundary.size() == 1) {
+ if (_boundary[0] == p) return true;
+ return false;
+ }
+
+ // 1. verify that the point is in the relevant X range
+ if (p[X] < _boundary[0][X] || p[X] > _boundary[_lower-1][X]) return false;
+
+ // 2. check whether it is below the upper hull
+ UpperIterator ub = upperHull().begin(), ue = upperHull().end();
+ if (!below_x_monotonic_polyline(p, ub, ue, Point::LexLess<X>())) return false;
+
+ // 3. check whether it is above the lower hull
+ LowerIterator lb = lowerHull().begin(), le = lowerHull().end();
+ if (!below_x_monotonic_polyline(p, lb, le, Point::LexGreater<X>())) return false;
+
+ return true;
+}
+
+bool ConvexHull::contains(Rect const &r) const
+{
+ for (unsigned i = 0; i < 4; ++i) {
+ if (!contains(r.corner(i))) return false;
+ }
+ return true;
+}
+
+bool ConvexHull::contains(ConvexHull const &ch) const
+{
+ // TODO: requires interiorContains.
+ // We have to check all points of ch, and each point takes logarithmic time.
+ // If there are more points in ch that here, it is faster to make the check
+ // the other way around.
+ /*if (ch.size() > size()) {
+ for (iterator i = begin(); i != end(); ++i) {
+ if (ch.interiorContains(*i)) return false;
+ }
+ return true;
+ }*/
+
+ for (auto i : ch) {
+ if (!contains(i)) return false;
+ }
+ return true;
+}
+
+void ConvexHull::swap(ConvexHull &other)
+{
+ _boundary.swap(other._boundary);
+ std::swap(_lower, other._lower);
+}
+
+void ConvexHull::swap(std::vector<Point> &pts)
+{
+ _boundary.swap(pts);
+ _lower = 0;
+ std::sort(_boundary.begin(), _boundary.end(), Point::LexLess<X>());
+ _construct();
+}
+
+#if 0
+/*** SignedTriangleArea
+ * returns the area of the triangle defined by p0, p1, p2. A clockwise triangle has positive area.
+ */
+double
+SignedTriangleArea(Point p0, Point p1, Point p2) {
+ return cross((p1 - p0), (p2 - p0));
+}
+
+class angle_cmp{
+public:
+ Point o;
+ angle_cmp(Point o) : o(o) {}
+
+#if 0
+ bool
+ operator()(Point a, Point b) {
+ // not remove this check or std::sort could crash
+ if (a == b) return false;
+ Point da = a - o;
+ Point db = b - o;
+ if (da == -db) return false;
+
+#if 1
+ double aa = da[0];
+ double ab = db[0];
+ if((da[1] == 0) && (db[1] == 0))
+ return da[0] < db[0];
+ if(da[1] == 0)
+ return true; // infinite tangent
+ if(db[1] == 0)
+ return false; // infinite tangent
+ aa = da[0] / da[1];
+ ab = db[0] / db[1];
+ if(aa > ab)
+ return true;
+#else
+ //assert((ata > atb) == (aa < ab));
+ double aa = atan2(da);
+ double ab = atan2(db);
+ if(aa < ab)
+ return true;
+#endif
+ if(aa == ab)
+ return L2sq(da) < L2sq(db);
+ return false;
+ }
+#else
+ bool operator() (Point const& a, Point const& b)
+ {
+ // not remove this check or std::sort could generate
+ // a segmentation fault because it needs a strict '<'
+ // but due to round errors a == b doesn't mean dxy == dyx
+ if (a == b) return false;
+ Point da = a - o;
+ Point db = b - o;
+ if (da == -db) return false;
+ double dxy = da[X] * db[Y];
+ double dyx = da[Y] * db[X];
+ if (dxy > dyx) return true;
+ else if (dxy < dyx) return false;
+ return L2sq(da) < L2sq(db);
+ }
+#endif
+};
+
+//Mathematically incorrect mod, but more useful.
+int mod(int i, int l) {
+ return i >= 0 ?
+ i % l : (i % l) + l;
+}
+//OPT: usages can often be replaced by conditions
+
+/*** ConvexHull::add_point
+ * to add a point we need to find whether the new point extends the boundary, and if so, what it
+ * obscures. Tarjan? Jarvis?*/
+void
+ConvexHull::merge(Point p) {
+ std::vector<Point> out;
+
+ int len = boundary.size();
+
+ if(len < 2) {
+ if(boundary.empty() || boundary[0] != p)
+ boundary.push_back(p);
+ return;
+ }
+
+ bool pushed = false;
+
+ bool pre = is_left(p, -1);
+ for(int i = 0; i < len; i++) {
+ bool cur = is_left(p, i);
+ if(pre) {
+ if(cur) {
+ if(!pushed) {
+ out.push_back(p);
+ pushed = true;
+ }
+ continue;
+ }
+ else if(!pushed) {
+ out.push_back(p);
+ pushed = true;
+ }
+ }
+ out.push_back(boundary[i]);
+ pre = cur;
+ }
+
+ boundary = out;
+}
+//OPT: quickly find an obscured point and find the bounds by extending from there. then push all points not within the bounds in order.
+ //OPT: use binary searches to find the actual starts/ends, use known rights as boundaries. may require cooperation of find_left algo.
+
+/*** ConvexHull::is_clockwise
+ * We require that successive pairs of edges always turn right.
+ * We return false on collinear points
+ * proposed algorithm: walk successive edges and require triangle area is positive.
+ */
+bool
+ConvexHull::is_clockwise() const {
+ if(is_degenerate())
+ return true;
+ Point first = boundary[0];
+ Point second = boundary[1];
+ for(std::vector<Point>::const_iterator it(boundary.begin()+2), e(boundary.end());
+ it != e;) {
+ if(SignedTriangleArea(first, second, *it) > 0)
+ return false;
+ first = second;
+ second = *it;
+ ++it;
+ }
+ return true;
+}
+
+/*** ConvexHull::top_point_first
+ * We require that the first point in the convex hull has the least y coord, and that off all such points on the hull, it has the least x coord.
+ * proposed algorithm: track lexicographic minimum while walking the list.
+ */
+bool
+ConvexHull::top_point_first() const {
+ if(size() <= 1) return true;
+ std::vector<Point>::const_iterator pivot = boundary.begin();
+ for(std::vector<Point>::const_iterator it(boundary.begin()+1),
+ e(boundary.end());
+ it != e; it++) {
+ if((*it)[1] < (*pivot)[1])
+ pivot = it;
+ else if(((*it)[1] == (*pivot)[1]) &&
+ ((*it)[0] < (*pivot)[0]))
+ pivot = it;
+ }
+ return pivot == boundary.begin();
+}
+//OPT: since the Y values are orderly there should be something like a binary search to do this.
+
+bool
+ConvexHull::meets_invariants() const {
+ return is_clockwise() && top_point_first();
+}
+
+/*** ConvexHull::is_degenerate
+ * We allow three degenerate cases: empty, 1 point and 2 points. In many cases these should be handled explicitly.
+ */
+bool
+ConvexHull::is_degenerate() const {
+ return boundary.size() < 3;
+}
+
+
+int sgn(double x) {
+ if(x == 0) return 0;
+ return (x<0)?-1:1;
+}
+
+bool same_side(Point L[2], Point xs[4]) {
+ int side = 0;
+ for(int i = 0; i < 4; i++) {
+ int sn = sgn(SignedTriangleArea(L[0], L[1], xs[i]));
+ if(sn && !side)
+ side = sn;
+ else if(sn != side) return false;
+ }
+ return true;
+}
+
+/** find bridging pairs between two convex hulls.
+ * this code is based on Hormoz Pirzadeh's masters thesis. There is room for optimisation:
+ * 1. reduce recomputation
+ * 2. use more efficient angle code
+ * 3. write as iterator
+ */
+std::vector<pair<int, int> > bridges(ConvexHull a, ConvexHull b) {
+ vector<pair<int, int> > ret;
+
+ // 1. find maximal points on a and b
+ int ai = 0, bi = 0;
+ // 2. find first copodal pair
+ double ap_angle = atan2(a[ai+1] - a[ai]);
+ double bp_angle = atan2(b[bi+1] - b[bi]);
+ Point L[2] = {a[ai], b[bi]};
+ while(ai < int(a.size()) || bi < int(b.size())) {
+ if(ap_angle == bp_angle) {
+ // In the case of parallel support lines, we must consider all four pairs of copodal points
+ {
+ assert(0); // untested
+ Point xs[4] = {a[ai-1], a[ai+1], b[bi-1], b[bi+1]};
+ if(same_side(L, xs)) ret.push_back(make_pair(ai, bi));
+ xs[2] = b[bi];
+ xs[3] = b[bi+2];
+ if(same_side(L, xs)) ret.push_back(make_pair(ai, bi));
+ xs[0] = a[ai];
+ xs[1] = a[ai+2];
+ if(same_side(L, xs)) ret.push_back(make_pair(ai, bi));
+ xs[2] = b[bi-1];
+ xs[3] = b[bi+1];
+ if(same_side(L, xs)) ret.push_back(make_pair(ai, bi));
+ }
+ ai++;
+ ap_angle += angle_between(a[ai] - a[ai-1], a[ai+1] - a[ai]);
+ L[0] = a[ai];
+ bi++;
+ bp_angle += angle_between(b[bi] - b[bi-1], b[bi+1] - b[bi]);
+ L[1] = b[bi];
+ std::cout << "parallel\n";
+ } else if(ap_angle < bp_angle) {
+ ai++;
+ ap_angle += angle_between(a[ai] - a[ai-1], a[ai+1] - a[ai]);
+ L[0] = a[ai];
+ Point xs[4] = {a[ai-1], a[ai+1], b[bi-1], b[bi+1]};
+ if(same_side(L, xs)) ret.push_back(make_pair(ai, bi));
+ } else {
+ bi++;
+ bp_angle += angle_between(b[bi] - b[bi-1], b[bi+1] - b[bi]);
+ L[1] = b[bi];
+ Point xs[4] = {a[ai-1], a[ai+1], b[bi-1], b[bi+1]};
+ if(same_side(L, xs)) ret.push_back(make_pair(ai, bi));
+ }
+ }
+ return ret;
+}
+
+unsigned find_bottom_right(ConvexHull const &a) {
+ unsigned it = 1;
+ while(it < a.boundary.size() &&
+ a.boundary[it][Y] > a.boundary[it-1][Y])
+ it++;
+ return it-1;
+}
+
+/*** ConvexHull sweepline_intersection(ConvexHull a, ConvexHull b);
+ * find the intersection between two convex hulls. The intersection is also a convex hull.
+ * (Proof: take any two points both in a and in b. Any point between them is in a by convexity,
+ * and in b by convexity, thus in both. Need to prove still finite bounds.)
+ * This algorithm works by sweeping a line down both convex hulls in parallel, working out the left and right edges of the new hull.
+ */
+ConvexHull sweepline_intersection(ConvexHull const &a, ConvexHull const &b) {
+ ConvexHull ret;
+
+ unsigned al = 0;
+ unsigned bl = 0;
+
+ while(al+1 < a.boundary.size() &&
+ (a.boundary[al+1][Y] > b.boundary[bl][Y])) {
+ al++;
+ }
+ while(bl+1 < b.boundary.size() &&
+ (b.boundary[bl+1][Y] > a.boundary[al][Y])) {
+ bl++;
+ }
+ // al and bl now point to the top of the first pair of edges that overlap in y value
+ //double sweep_y = std::min(a.boundary[al][Y],
+ // b.boundary[bl][Y]);
+ return ret;
+}
+
+/*** ConvexHull intersection(ConvexHull a, ConvexHull b);
+ * find the intersection between two convex hulls. The intersection is also a convex hull.
+ * (Proof: take any two points both in a and in b. Any point between them is in a by convexity,
+ * and in b by convexity, thus in both. Need to prove still finite bounds.)
+ */
+ConvexHull intersection(ConvexHull /*a*/, ConvexHull /*b*/) {
+ ConvexHull ret;
+ /*
+ int ai = 0, bi = 0;
+ int aj = a.boundary.size() - 1;
+ int bj = b.boundary.size() - 1;
+ */
+ /*while (true) {
+ if(a[ai]
+ }*/
+ return ret;
+}
+
+template <typename T>
+T idx_to_pair(pair<T, T> p, int idx) {
+ return idx?p.second:p.first;
+}
+
+/*** ConvexHull merge(ConvexHull a, ConvexHull b);
+ * find the smallest convex hull that surrounds a and b.
+ */
+ConvexHull merge(ConvexHull a, ConvexHull b) {
+ ConvexHull ret;
+
+ std::cout << "---\n";
+ std::vector<pair<int, int> > bpair = bridges(a, b);
+
+ // Given our list of bridges {(pb1, qb1), ..., (pbk, qbk)}
+ // we start with the highest point in p0, q0, say it is p0.
+ // then the merged hull is p0, ..., pb1, qb1, ..., qb2, pb2, ...
+ // In other words, either of the two polygons vertices are added in order until the vertex coincides with a bridge point, at which point we swap.
+
+ unsigned state = (a[0][Y] < b[0][Y])?0:1;
+ ret.boundary.reserve(a.size() + b.size());
+ ConvexHull chs[2] = {a, b};
+ unsigned idx = 0;
+
+ for(unsigned k = 0; k < bpair.size(); k++) {
+ unsigned limit = idx_to_pair(bpair[k], state);
+ std::cout << bpair[k].first << " , " << bpair[k].second << "; "
+ << idx << ", " << limit << ", s: "
+ << state
+ << " \n";
+ while(idx <= limit) {
+ ret.boundary.push_back(chs[state][idx++]);
+ }
+ state = 1-state;
+ idx = idx_to_pair(bpair[k], state);
+ }
+ while(idx < chs[state].size()) {
+ ret.boundary.push_back(chs[state][idx++]);
+ }
+ return ret;
+}
+
+ConvexHull graham_merge(ConvexHull a, ConvexHull b) {
+ ConvexHull result;
+
+ // we can avoid the find pivot step because of top_point_first
+ if(b.boundary[0] <= a.boundary[0])
+ swap(a, b);
+
+ result.boundary = a.boundary;
+ result.boundary.insert(result.boundary.end(),
+ b.boundary.begin(), b.boundary.end());
+
+/** if we modified graham scan to work top to bottom as proposed in lect754.pdf we could replace the
+ angle sort with a simple merge sort type algorithm. furthermore, we could do the graham scan
+ online, avoiding a bunch of memory copies. That would probably be linear. -- njh*/
+ result.angle_sort();
+ result.graham_scan();
+
+ return result;
+}
+
+ConvexHull andrew_merge(ConvexHull a, ConvexHull b) {
+ ConvexHull result;
+
+ // we can avoid the find pivot step because of top_point_first
+ if(b.boundary[0] <= a.boundary[0])
+ swap(a, b);
+
+ result.boundary = a.boundary;
+ result.boundary.insert(result.boundary.end(),
+ b.boundary.begin(), b.boundary.end());
+
+/** if we modified graham scan to work top to bottom as proposed in lect754.pdf we could replace the
+ angle sort with a simple merge sort type algorithm. furthermore, we could do the graham scan
+ online, avoiding a bunch of memory copies. That would probably be linear. -- njh*/
+ result.andrew_scan();
+
+ return result;
+}
+
+//TODO: reinstate
+/*ConvexCover::ConvexCover(Path const &sp) : path(&sp) {
+ cc.reserve(sp.size());
+ for(Geom::Path::const_iterator it(sp.begin()), end(sp.end()); it != end; ++it) {
+ cc.push_back(ConvexHull((*it).begin(), (*it).end()));
+ }
+}*/
+
+double ConvexHull::centroid_and_area(Geom::Point& centroid) const {
+ const unsigned n = boundary.size();
+ if (n < 2)
+ return 0;
+ if(n < 3) {
+ centroid = (boundary[0] + boundary[1])/2;
+ return 0;
+ }
+ Geom::Point centroid_tmp(0,0);
+ double atmp = 0;
+ for (unsigned i = n-1, j = 0; j < n; i = j, j++) {
+ const double ai = cross(boundary[j], boundary[i]);
+ atmp += ai;
+ centroid_tmp += (boundary[j] + boundary[i])*ai; // first moment.
+ }
+ if (atmp != 0) {
+ centroid = centroid_tmp / (3 * atmp);
+ }
+ return atmp / 2;
+}
+
+// TODO: This can be made lg(n) using golden section/fibonacci search three starting points, say 0,
+// n/2, n-1 construct a new point, say (n/2 + n)/2 throw away the furthest boundary point iterate
+// until interval is a single value
+Point const * ConvexHull::furthest(Point direction) const {
+ Point const * p = &boundary[0];
+ double d = dot(*p, direction);
+ for(unsigned i = 1; i < boundary.size(); i++) {
+ double dd = dot(boundary[i], direction);
+ if(d < dd) {
+ p = &boundary[i];
+ d = dd;
+ }
+ }
+ return p;
+}
+
+
+// returns (a, (b,c)), three points which define the narrowest diameter of the hull as the pair of
+// lines going through b,c, and through a, parallel to b,c TODO: This can be made linear time by
+// moving point tc incrementally from the previous value (it can only move in one direction). It
+// is currently n*O(furthest)
+double ConvexHull::narrowest_diameter(Point &a, Point &b, Point &c) {
+ Point tb = boundary.back();
+ double d = std::numeric_limits<double>::max();
+ for(unsigned i = 0; i < boundary.size(); i++) {
+ Point tc = boundary[i];
+ Point n = -rot90(tb-tc);
+ Point ta = *furthest(n);
+ double td = dot(n, ta-tb)/dot(n,n);
+ if(td < d) {
+ a = ta;
+ b = tb;
+ c = tc;
+ d = td;
+ }
+ tb = tc;
+ }
+ return d;
+}
+#endif
+
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/coord.cpp b/src/3rdparty/2geom/src/2geom/coord.cpp
new file mode 100644
index 0000000..205a82f
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/coord.cpp
@@ -0,0 +1,123 @@
+/** @file
+ * @brief Conversion between Coord and strings
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2014 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+// Most of the code in this file is derived from:
+// https://code.google.com/p/double-conversion/
+// The copyright notice for that code is attached below.
+//
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <2geom/coord.h>
+#include <cstdint>
+#include <cstdlib>
+#include <cassert>
+#include <cstring>
+#include <climits>
+#include <cstdarg>
+#include <cmath>
+
+#include <double-conversion/double-conversion.h>
+
+namespace Geom {
+
+std::string format_coord_shortest(Coord x)
+{
+ static const double_conversion::DoubleToStringConverter conv(
+ double_conversion::DoubleToStringConverter::UNIQUE_ZERO,
+ "inf", "NaN", 'e', -3, 6, 0, 0);
+ std::string ret(' ', 32);
+ double_conversion::StringBuilder builder(&ret[0], 32);
+ conv.ToShortest(x, &builder);
+ ret.resize(builder.position());
+ return ret;
+}
+
+std::string format_coord_nice(Coord x)
+{
+ static const double_conversion::DoubleToStringConverter conv(
+ double_conversion::DoubleToStringConverter::UNIQUE_ZERO,
+ "inf", "NaN", 'e', -6, 21, 0, 0);
+ std::string ret(' ', 32);
+ double_conversion::StringBuilder builder(&ret[0], 32);
+ conv.ToShortest(x, &builder);
+ ret.resize(builder.position());
+ return ret;
+}
+
+Coord parse_coord(std::string const &s)
+{
+ static const double_conversion::StringToDoubleConverter conv(
+ double_conversion::StringToDoubleConverter::ALLOW_LEADING_SPACES |
+ double_conversion::StringToDoubleConverter::ALLOW_TRAILING_SPACES |
+ double_conversion::StringToDoubleConverter::ALLOW_SPACES_AFTER_SIGN,
+ 0.0, nan(""), "inf", "NaN");
+ int dummy;
+ return conv.StringToDouble(s.c_str(), s.length(), &dummy);
+}
+
+} // namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/crossing.cpp b/src/3rdparty/2geom/src/2geom/crossing.cpp
new file mode 100644
index 0000000..1159fb0
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/crossing.cpp
@@ -0,0 +1,233 @@
+#include <2geom/crossing.h>
+#include <2geom/path.h>
+
+namespace Geom {
+
+//bool edge_involved_in(Edge const &e, Crossing const &c) {
+// if(e.path == c.a) {
+// if(e.time == c.ta) return true;
+// } else if(e.path == c.b) {
+// if(e.time == c.tb) return true;
+// }
+// return false;
+//}
+
+double wrap_dist(double from, double to, double size, bool rev) {
+ if(rev) {
+ if(to > from) {
+ return from + (size - to);
+ } else {
+ return from - to;
+ }
+ } else {
+ if(to < from) {
+ return to + (size - from);
+ } else {
+ return to - from;
+ }
+ }
+}
+/*
+CrossingGraph create_crossing_graph(PathVector const &p, Crossings const &crs) {
+ std::vector<Point> locs;
+ CrossingGraph ret;
+ for(unsigned i = 0; i < crs.size(); i++) {
+ Point pnt = p[crs[i].a].pointAt(crs[i].ta);
+ unsigned j = 0;
+ for(; j < locs.size(); j++) {
+ if(are_near(pnt, locs[j])) break;
+ }
+ if(j == locs.size()) {
+ ret.push_back(CrossingNode());
+ locs.push_back(pnt);
+ }
+ ret[j].add_edge(Edge(crs[i].a, crs[i].ta, false));
+ ret[j].add_edge(Edge(crs[i].a, crs[i].ta, true));
+ ret[j].add_edge(Edge(crs[i].b, crs[i].tb, false));
+ ret[j].add_edge(Edge(crs[i].b, crs[i].tb, true));
+ }
+
+ for(unsigned i = 0; i < ret.size(); i++) {
+ for(unsigned j = 0; j < ret[i].edges.size(); j++) {
+ unsigned pth = ret[i].edges[j].path;
+ double t = ret[i].edges[j].time;
+ bool rev = ret[i].edges[j].reverse;
+ double size = p[pth].size()+1;
+ double best = size;
+ unsigned bix = ret.size();
+ for(unsigned k = 0; k < ret.size(); k++) {
+ for(unsigned l = 0; l < ret[k].edges.size(); l++) {
+ if(ret[i].edges[j].path == ret[k].edges[l].path && (k != i || l != j)) {
+ double d = wrap_dist(t, ret[i].edges[j].time, size, rev);
+ if(d < best) {
+ best = d;
+ bix = k;
+ }
+ }
+ }
+ }
+ if(bix == ret.size()) {
+ std::cout << "couldn't find an adequate next-crossing node";
+ bix = i;
+ }
+ ret[i].edges[j].node = bix;
+ }
+ }
+
+ return ret;
+ */
+ /* Various incoherent code bits
+ // list of sets of edges, each set corresponding to those emanating from the path
+ CrossingGraph ret;
+ std::vector<Edge> edges(crs.size());
+
+ std::vector<std::vector<bool> > used;
+ unsigned i, j;
+ do {
+ first_false(used, i, j);
+ CrossingNode cn;
+ do {
+ unsigned di = i, dj = j;
+ crossing_dual(di, dj);
+ if(!used[di,dj]) {
+
+ }
+ }
+
+ } while(!used[i,j])
+
+
+ for(unsigned j = 0; j < crs[i].size(); j++) {
+
+ edges.push_back(Edge(i, crs[i][j].getOtherTime(i), false));
+ edges.push_back(Edge(i, crs[i][j].getOtherTime(i), true));
+ }
+ std::sort(edges.begin(), edges.end(), TimeOrder());
+ for(unsigned j = 0; j < edges.size(); ) {
+ CrossingNode cn;
+ double t = edges[j].time;
+ while(j < edges.size() && are_near(edges[j].time, t)) {
+ cn.edges.push_back(edges[j]);
+ }
+ }
+*/
+//}
+
+// provide specific method for Paths because paths can be closed or open. Path::size() is named somewhat wrong...
+std::vector<Rect> bounds(Path const &a) {
+ std::vector<Rect> rs;
+ for (unsigned i = 0; i < a.size_default(); i++) {
+ OptRect bb = a[i].boundsFast();
+ if (bb) {
+ rs.push_back(*bb);
+ }
+ }
+ return rs;
+}
+
+void merge_crossings(Crossings &a, Crossings &b, unsigned i) {
+ Crossings n;
+ sort_crossings(b, i);
+ n.resize(a.size() + b.size());
+ std::merge(a.begin(), a.end(), b.begin(), b.end(), n.begin(), CrossingOrder(i));
+ a = n;
+}
+
+void offset_crossings(Crossings &cr, double a, double b) {
+ for(auto & i : cr) {
+ i.ta += a;
+ i.tb += b;
+ }
+}
+
+Crossings reverse_ta(Crossings const &cr, std::vector<double> max) {
+ Crossings ret;
+ for(const auto & i : cr) {
+ double mx = max[i.a];
+ ret.push_back(Crossing(i.ta > mx+0.01 ? (1 - (i.ta - mx) + mx) : mx - i.ta,
+ i.tb, !i.dir));
+ }
+ return ret;
+}
+
+Crossings reverse_tb(Crossings const &cr, unsigned split, std::vector<double> max) {
+ Crossings ret;
+ for(const auto & i : cr) {
+ double mx = max[i.b - split];
+ ret.push_back(Crossing(i.ta, i.tb > mx+0.01 ? (1 - (i.tb - mx) + mx) : mx - i.tb,
+ !i.dir));
+ }
+ return ret;
+}
+
+CrossingSet reverse_ta(CrossingSet const &cr, unsigned split, std::vector<double> max) {
+ CrossingSet ret;
+ for(unsigned i = 0; i < cr.size(); i++) {
+ Crossings res = reverse_ta(cr[i], max);
+ if(i < split) std::reverse(res.begin(), res.end());
+ ret.push_back(res);
+ }
+ return ret;
+}
+
+CrossingSet reverse_tb(CrossingSet const &cr, unsigned split, std::vector<double> max) {
+ CrossingSet ret;
+ for(unsigned i = 0; i < cr.size(); i++) {
+ Crossings res = reverse_tb(cr[i], split, max);
+ if(i >= split) std::reverse(res.begin(), res.end());
+ ret.push_back(res);
+ }
+ return ret;
+}
+
+// Delete any duplicates in a vector of crossings
+// A crossing is considered to be a duplicate when it has both t_a and t_b near to another crossing's t_a and t_b
+// For example, duplicates will be found when calculating the intersections of a linesegment with a polygon, if the
+// endpoint of that line coincides with a cusp node of the polygon. In that case, an intersection will be found of
+// the linesegment with each of the polygon's linesegments extending from the cusp node (i.e. two intersections)
+void delete_duplicates(Crossings &crs) {
+ Crossings::reverse_iterator rit = crs.rbegin();
+
+ for (rit = crs.rbegin(); rit!= crs.rend(); ++rit) {
+ Crossings::reverse_iterator rit2 = rit;
+ while (++rit2 != crs.rend()) {
+ if (Geom::are_near((*rit).ta, (*rit2).ta) && Geom::are_near((*rit).tb, (*rit2).tb)) {
+ crs.erase((rit + 1).base()); // This +1 and .base() construction is needed to convert to a regular iterator
+ break; // out of while loop, and continue with next iteration of for loop
+ }
+ }
+ }
+}
+
+void clean(Crossings &/*cr_a*/, Crossings &/*cr_b*/) {
+/* if(cr_a.empty()) return;
+
+ //Remove anything with dupes
+
+ for(Eraser<Crossings> i(&cr_a); !i.ended(); i++) {
+ const Crossing cur = *i;
+ Eraser<Crossings> next(i);
+ next++;
+ if(are_near(cur, *next)) {
+ cr_b.erase(std::find(cr_b.begin(), cr_b.end(), cur));
+ for(i = next; near(*i, cur); i++) {
+ cr_b.erase(std::find(cr_b.begin(), cr_b.end(), *i));
+ }
+ continue;
+ }
+ }
+*/
+}
+
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/curve.cpp b/src/3rdparty/2geom/src/2geom/curve.cpp
new file mode 100644
index 0000000..f79edb3
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/curve.cpp
@@ -0,0 +1,235 @@
+/* Abstract curve type - implementation of default methods
+ *
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ * Rafał Siejakowski <rs@rs-math.net>
+ *
+ * Copyright 2007-2009 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/curve.h>
+#include <2geom/exception.h>
+#include <2geom/nearest-time.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/ord.h>
+#include <2geom/path-sink.h>
+
+namespace Geom
+{
+
+Coord Curve::nearestTime(Point const& p, Coord a, Coord b) const
+{
+ return nearest_time(p, toSBasis(), a, b);
+}
+
+std::vector<Coord> Curve::allNearestTimes(Point const& p, Coord from, Coord to) const
+{
+ return all_nearest_times(p, toSBasis(), from, to);
+}
+
+Coord Curve::length(Coord tolerance) const
+{
+ return ::Geom::length(toSBasis(), tolerance);
+}
+
+int Curve::winding(Point const &p) const
+{
+ try {
+ std::vector<Coord> ts = roots(p[Y], Y);
+ if(ts.empty()) return 0;
+ std::sort(ts.begin(), ts.end());
+
+ // skip endpoint roots when they are local maxima on the Y axis
+ // this follows the convention used in other winding routines,
+ // i.e. that the bottommost coordinate is not part of the shape
+ bool ignore_0 = unitTangentAt(0)[Y] <= 0;
+ bool ignore_1 = unitTangentAt(1)[Y] >= 0;
+
+ int wind = 0;
+ for (double t : ts) {
+ //std::cout << t << std::endl;
+ if ((t == 0 && ignore_0) || (t == 1 && ignore_1)) continue;
+ if (valueAt(t, X) > p[X]) { // root is ray intersection
+ Point tangent = unitTangentAt(t);
+ if (tangent[Y] > 0) {
+ // at the point of intersection, curve goes in +Y direction,
+ // so it winds in the direction of positive angles
+ ++wind;
+ } else if (tangent[Y] < 0) {
+ --wind;
+ }
+ }
+ }
+ return wind;
+ } catch (InfiniteSolutions const &e) {
+ // this means we encountered a line segment exactly coincident with the point
+ // skip, since this will be taken care of by endpoint roots in other segments
+ return 0;
+ }
+}
+
+std::vector<CurveIntersection> Curve::intersect(Curve const &/*other*/, Coord /*eps*/) const
+{
+ // TODO: approximate as Bezier
+ THROW_NOTIMPLEMENTED();
+}
+
+std::vector<CurveIntersection> Curve::intersectSelf(Coord eps) const
+{
+ /// Represents a sub-arc of the curve.
+ struct Subcurve
+ {
+ std::unique_ptr<Curve> curve;
+ Interval parameter_range;
+
+ Subcurve(Curve *piece, Coord from, Coord to)
+ : curve{piece}
+ , parameter_range{from, to}
+ {}
+ };
+
+ /// A closure to split the curve into portions at the prescribed split points.
+ auto const split_into_subcurves = [=](std::vector<Coord> const &splits) {
+ std::vector<Subcurve> result;
+ result.reserve(splits.size() + 1);
+ Coord previous = 0;
+ for (Coord split : splits) {
+ // Use global EPSILON since we're operating on normalized curve times.
+ if (split < EPSILON || split > 1.0 - EPSILON) {
+ continue;
+ }
+ result.emplace_back(portion(previous, split), previous, split);
+ previous = split;
+ }
+ result.emplace_back(portion(previous, 1.0), previous, 1.0);
+ return result;
+ };
+
+ /// A closure to find pairwise intersections between the passed subcurves.
+ auto const pairwise_intersect = [=](std::vector<Subcurve> const &subcurves) {
+ std::vector<CurveIntersection> result;
+ for (unsigned i = 0; i < subcurves.size(); i++) {
+ for (unsigned j = i + 1; j < subcurves.size(); j++) {
+ auto const xings = subcurves[i].curve->intersect(*subcurves[j].curve, eps);
+ for (auto const &xing : xings) {
+ // To avoid duplicate intersections, skip values at exactly 1.
+ if (xing.first == 1. || xing.second == 1.) {
+ continue;
+ }
+ Coord const ti = subcurves[i].parameter_range.valueAt(xing.first);
+ Coord const tj = subcurves[j].parameter_range.valueAt(xing.second);
+ result.emplace_back(ti, tj, xing.point());
+ }
+ }
+ }
+ std::sort(result.begin(), result.end());
+ return result;
+ };
+
+ // Monotonic segments cannot have self-intersections. Thus, we can split
+ // the curve at critical points of the X or Y coordinate and intersect
+ // the portions. However, there's the risk that a juncture between two
+ // adjacent portions is mistaken for an intersection due to numerical errors.
+ // Hence, we run the algorithm for both the X and Y coordinates and only
+ // keep the intersections that show up in both intersection lists.
+
+ // Find the critical points of both coordinates.
+ std::unique_ptr<Curve> deriv{derivative()};
+ auto const crits_x = deriv->roots(0, X);
+ auto const crits_y = deriv->roots(0, Y);
+ if (crits_x.empty() || crits_y.empty()) {
+ return {};
+ }
+
+ // Split into pieces in two ways and find self-intersections.
+ auto const pieces_x = split_into_subcurves(crits_x);
+ auto const pieces_y = split_into_subcurves(crits_y);
+ auto const crossings_from_x = pairwise_intersect(pieces_x);
+ auto const crossings_from_y = pairwise_intersect(pieces_y);
+ if (crossings_from_x.empty() || crossings_from_y.empty()) {
+ return {};
+ }
+
+ // Filter the results, only keeping self-intersections found by both approaches.
+ std::vector<CurveIntersection> result;
+ unsigned index_y = 0;
+ for (auto &&candidate_x : crossings_from_x) {
+ // Find a crossing corresponding to this one in the y-method collection.
+ while (index_y != crossings_from_y.size()) {
+ auto const gap = crossings_from_y[index_y].first - candidate_x.first;
+ if (std::abs(gap) < EPSILON) {
+ // We found the matching intersection!
+ result.emplace_back(candidate_x);
+ index_y++;
+ break;
+ } else if (gap < 0.0) {
+ index_y++;
+ } else {
+ break;
+ }
+ }
+ }
+ return result;
+}
+
+Point Curve::unitTangentAt(Coord t, unsigned n) const
+{
+ std::vector<Point> derivs = pointAndDerivatives(t, n);
+ for (unsigned deriv_n = 1; deriv_n < derivs.size(); deriv_n++) {
+ Coord length = derivs[deriv_n].length();
+ if ( ! are_near(length, 0) ) {
+ // length of derivative is non-zero, so return unit vector
+ return derivs[deriv_n] / length;
+ }
+ }
+ return Point (0,0);
+};
+
+void Curve::feed(PathSink &sink, bool moveto_initial) const
+{
+ std::vector<Point> pts;
+ sbasis_to_bezier(pts, toSBasis(), 2); //TODO: use something better!
+ if (moveto_initial) {
+ sink.moveTo(initialPoint());
+ }
+ sink.curveTo(pts[0], pts[1], pts[2]);
+}
+
+} // namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/d2-sbasis.cpp b/src/3rdparty/2geom/src/2geom/d2-sbasis.cpp
new file mode 100644
index 0000000..4e95f6f
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/d2-sbasis.cpp
@@ -0,0 +1,364 @@
+/**
+ * \file
+ * \brief Some two-dimensional SBasis operations
+ *//*
+ * Authors:
+ * MenTaLguy <mental@rydia.net>
+ * Jean-François Barraud <jf.barraud@gmail.com>
+ * Johan Engelen <j.b.c.engelen@alumnus.utwente.nl>
+ *
+ * Copyright 2007-2012 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, output to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <2geom/d2.h>
+#include <2geom/piecewise.h>
+
+namespace Geom {
+
+SBasis L2(D2<SBasis> const & a, unsigned k) { return sqrt(dot(a, a), k); }
+
+D2<SBasis> multiply(Linear const & a, D2<SBasis> const & b) {
+ return D2<SBasis>(multiply(a, b[X]), multiply(a, b[Y]));
+}
+
+D2<SBasis> multiply(SBasis const & a, D2<SBasis> const & b) {
+ return D2<SBasis>(multiply(a, b[X]), multiply(a, b[Y]));
+}
+
+D2<SBasis> truncate(D2<SBasis> const & a, unsigned terms) {
+ return D2<SBasis>(truncate(a[X], terms), truncate(a[Y], terms));
+}
+
+unsigned sbasis_size(D2<SBasis> const & a) {
+ return std::max((unsigned) a[0].size(), (unsigned) a[1].size());
+}
+
+//TODO: Is this sensical? shouldn't it be like pythagorean or something?
+double tail_error(D2<SBasis> const & a, unsigned tail) {
+ return std::max(a[0].tailError(tail), a[1].tailError(tail));
+}
+
+Piecewise<D2<SBasis> > sectionize(D2<Piecewise<SBasis> > const &a) {
+ Piecewise<SBasis> x = partition(a[0], a[1].cuts), y = partition(a[1], a[0].cuts);
+ assert(x.size() == y.size());
+ Piecewise<D2<SBasis> > ret;
+ for(unsigned i = 0; i < x.size(); i++)
+ ret.push_seg(D2<SBasis>(x[i], y[i]));
+ ret.cuts.insert(ret.cuts.end(), x.cuts.begin(), x.cuts.end());
+ return ret;
+}
+
+D2<Piecewise<SBasis> > make_cuts_independent(Piecewise<D2<SBasis> > const &a) {
+ D2<Piecewise<SBasis> > ret;
+ for(unsigned d = 0; d < 2; d++) {
+ for(unsigned i = 0; i < a.size(); i++)
+ ret[d].push_seg(a[i][d]);
+ ret[d].cuts.insert(ret[d].cuts.end(), a.cuts.begin(), a.cuts.end());
+ }
+ return ret;
+}
+
+Piecewise<D2<SBasis> > rot90(Piecewise<D2<SBasis> > const &M){
+ Piecewise<D2<SBasis> > result;
+ if (M.empty()) return M;
+ result.push_cut(M.cuts[0]);
+ for (unsigned i=0; i<M.size(); i++){
+ result.push(rot90(M[i]),M.cuts[i+1]);
+ }
+ return result;
+}
+
+/** @brief Calculates the 'dot product' or 'inner product' of \c a and \c b
+ * @return \f[
+ * f(t) \rightarrow \left\{
+ * \begin{array}{c}
+ * a_1 \bullet b_1 \\
+ * a_2 \bullet b_2 \\
+ * \ldots \\
+ * a_n \bullet b_n \\
+ * \end{array}\right.
+ * \f]
+ * @relates Piecewise */
+Piecewise<SBasis> dot(Piecewise<D2<SBasis> > const &a, Piecewise<D2<SBasis> > const &b)
+{
+ Piecewise<SBasis > result;
+ if (a.empty() || b.empty()) return result;
+ Piecewise<D2<SBasis> > aa = partition(a,b.cuts);
+ Piecewise<D2<SBasis> > bb = partition(b,a.cuts);
+
+ result.push_cut(aa.cuts.front());
+ for (unsigned i=0; i<aa.size(); i++){
+ result.push(dot(aa.segs[i],bb.segs[i]),aa.cuts[i+1]);
+ }
+ return result;
+}
+
+/** @brief Calculates the 'dot product' or 'inner product' of \c a and \c b
+ * @return \f[
+ * f(t) \rightarrow \left\{
+ * \begin{array}{c}
+ * a_1 \bullet b \\
+ * a_2 \bullet b \\
+ * \ldots \\
+ * a_n \bullet b \\
+ * \end{array}\right.
+ * \f]
+ * @relates Piecewise */
+Piecewise<SBasis> dot(Piecewise<D2<SBasis> > const &a, Point const &b)
+{
+ Piecewise<SBasis > result;
+ if (a.empty()) return result;
+
+ result.push_cut(a.cuts.front());
+ for (unsigned i = 0; i < a.size(); ++i){
+ result.push(dot(a.segs[i],b), a.cuts[i+1]);
+ }
+ return result;
+}
+
+
+Piecewise<SBasis> cross(Piecewise<D2<SBasis> > const &a,
+ Piecewise<D2<SBasis> > const &b){
+ Piecewise<SBasis > result;
+ if (a.empty() || b.empty()) return result;
+ Piecewise<D2<SBasis> > aa = partition(a,b.cuts);
+ Piecewise<D2<SBasis> > bb = partition(b,a.cuts);
+
+ result.push_cut(aa.cuts.front());
+ for (unsigned i=0; i<a.size(); i++){
+ result.push(cross(aa.segs[i],bb.segs[i]),aa.cuts[i+1]);
+ }
+ return result;
+}
+
+Piecewise<D2<SBasis> > operator*(Piecewise<D2<SBasis> > const &a, Affine const &m) {
+ Piecewise<D2<SBasis> > result;
+ if(a.empty()) return result;
+ result.push_cut(a.cuts[0]);
+ for (unsigned i = 0; i < a.size(); i++) {
+ result.push(a[i] * m, a.cuts[i+1]);
+ }
+ return result;
+}
+
+//if tol>0, only force continuity where the jump is smaller than tol.
+Piecewise<D2<SBasis> > force_continuity(Piecewise<D2<SBasis> > const &f, double tol, bool closed)
+{
+ if (f.size()==0) return f;
+ Piecewise<D2<SBasis> > result=f;
+ unsigned cur = (closed)? 0:1;
+ unsigned prev = (closed)? f.size()-1:0;
+ while(cur<f.size()){
+ Point pt0 = f.segs[prev].at1();
+ Point pt1 = f.segs[cur ].at0();
+ if (tol<=0 || L2sq(pt0-pt1)<tol*tol){
+ pt0 = (pt0+pt1)/2;
+ for (unsigned dim=0; dim<2; dim++){
+ SBasis &prev_sb=result.segs[prev][dim];
+ SBasis &cur_sb =result.segs[cur][dim];
+ Coord const c=pt0[dim];
+ if (prev_sb.isZero(0)) {
+ prev_sb = SBasis(Linear(0.0, c));
+ } else {
+ prev_sb[0][1] = c;
+ }
+ if (cur_sb.isZero(0)) {
+ cur_sb = SBasis(Linear(c, 0.0));
+ } else {
+ cur_sb[0][0] = c;
+ }
+ }
+ }
+ prev = cur++;
+ }
+ return result;
+}
+
+std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > >
+split_at_discontinuities (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwsbin, double tol)
+{
+ using namespace Geom;
+ std::vector<Piecewise<D2<SBasis> > > ret;
+ unsigned piece_start = 0;
+ for (unsigned i=0; i<pwsbin.segs.size(); i++){
+ if (i==(pwsbin.segs.size()-1) || L2(pwsbin.segs[i].at1()- pwsbin.segs[i+1].at0()) > tol){
+ Piecewise<D2<SBasis> > piece;
+ piece.cuts.push_back(pwsbin.cuts[piece_start]);
+ for (unsigned j = piece_start; j<i+1; j++){
+ piece.segs.push_back(pwsbin.segs[j]);
+ piece.cuts.push_back(pwsbin.cuts[j+1]);
+ }
+ ret.push_back(piece);
+ piece_start = i+1;
+ }
+ }
+ return ret;
+}
+
+Point unitTangentAt(D2<SBasis> const & a, Coord t, unsigned n)
+{
+ std::vector<Point> derivs = a.valueAndDerivatives(t, n);
+ for (unsigned deriv_n = 1; deriv_n < derivs.size(); deriv_n++) {
+ Coord length = derivs[deriv_n].length();
+ if ( ! are_near(length, 0) ) {
+ // length of derivative is non-zero, so return unit vector
+ return derivs[deriv_n] / length;
+ }
+ }
+ return Point (0,0);
+}
+
+static void set_first_point(Piecewise<D2<SBasis> > &f, Point const &a){
+ if ( f.empty() ){
+ f.concat(Piecewise<D2<SBasis> >(D2<SBasis>(SBasis(Linear(a[X])), SBasis(Linear(a[Y])))));
+ return;
+ }
+ for (unsigned dim=0; dim<2; dim++){
+ f.segs.front()[dim][0][0] = a[dim];
+ }
+}
+static void set_last_point(Piecewise<D2<SBasis> > &f, Point const &a){
+ if ( f.empty() ){
+ f.concat(Piecewise<D2<SBasis> >(D2<SBasis>(SBasis(Linear(a[X])), SBasis(Linear(a[Y])))));
+ return;
+ }
+ for (unsigned dim=0; dim<2; dim++){
+ f.segs.back()[dim][0][1] = a[dim];
+ }
+}
+
+std::vector<Piecewise<D2<SBasis> > > fuse_nearby_ends(std::vector<Piecewise<D2<SBasis> > > const &f, double tol){
+
+ if ( f.empty()) return f;
+ std::vector<Piecewise<D2<SBasis> > > result;
+ std::vector<std::vector<unsigned> > pre_result;
+ for (unsigned i=0; i<f.size(); i++){
+ bool inserted = false;
+ Point a = f[i].firstValue();
+ Point b = f[i].lastValue();
+ for (auto & j : pre_result){
+ Point aj = f.at(j.back()).lastValue();
+ Point bj = f.at(j.front()).firstValue();
+ if ( L2(a-aj) < tol ) {
+ j.push_back(i);
+ inserted = true;
+ break;
+ }
+ if ( L2(b-bj) < tol ) {
+ j.insert(j.begin(),i);
+ inserted = true;
+ break;
+ }
+ }
+ if (!inserted) {
+ pre_result.emplace_back();
+ pre_result.back().push_back(i);
+ }
+ }
+ for (auto & i : pre_result){
+ Piecewise<D2<SBasis> > comp;
+ for (unsigned j=0; j<i.size(); j++){
+ Piecewise<D2<SBasis> > new_comp = f.at(i[j]);
+ if ( j>0 ){
+ set_first_point( new_comp, comp.segs.back().at1() );
+ }
+ comp.concat(new_comp);
+ }
+ if ( L2(comp.firstValue()-comp.lastValue()) < tol ){
+ //TODO: check sizes!!!
+ set_last_point( comp, comp.segs.front().at0() );
+ }
+ result.push_back(comp);
+ }
+ return result;
+}
+
+/*
+ * Computes the intersection of two sets given as (ordered) union of intervals.
+ */
+static std::vector<Interval> intersect( std::vector<Interval> const &a, std::vector<Interval> const &b){
+ std::vector<Interval> result;
+ //TODO: use order!
+ for (auto i : a){
+ for (auto j : b){
+ OptInterval c( i );
+ c &= j;
+ if ( c ) {
+ result.push_back( *c );
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<Interval> level_set( D2<SBasis> const &f, Rect region){
+ std::vector<Rect> regions( 1, region );
+ return level_sets( f, regions ).front();
+}
+std::vector<Interval> level_set( D2<SBasis> const &f, Point p, double tol){
+ Rect region(p, p);
+ region.expandBy( tol );
+ return level_set( f, region );
+}
+std::vector<std::vector<Interval> > level_sets( D2<SBasis> const &f, std::vector<Rect> regions){
+ std::vector<Interval> regsX (regions.size(), Interval() );
+ std::vector<Interval> regsY (regions.size(), Interval() );
+ for ( unsigned i=0; i < regions.size(); i++ ){
+ regsX[i] = regions[i][X];
+ regsY[i] = regions[i][Y];
+ }
+ std::vector<std::vector<Interval> > x_in_regs = level_sets( f[X], regsX );
+ std::vector<std::vector<Interval> > y_in_regs = level_sets( f[Y], regsY );
+ std::vector<std::vector<Interval> >result(regions.size(), std::vector<Interval>() );
+ for (unsigned i=0; i<regions.size(); i++){
+ result[i] = intersect ( x_in_regs[i], y_in_regs[i] );
+ }
+ return result;
+}
+std::vector<std::vector<Interval> > level_sets( D2<SBasis> const &f, std::vector<Point> pts, double tol){
+ std::vector<Rect> regions( pts.size(), Rect() );
+ for (unsigned i=0; i<pts.size(); i++){
+ regions[i] = Rect( pts[i], pts[i] );
+ regions[i].expandBy( tol );
+ }
+ return level_sets( f, regions );
+}
+
+
+} // namespace Geom
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/doxygen.cpp b/src/3rdparty/2geom/src/2geom/doxygen.cpp
new file mode 100644
index 0000000..3c64eec
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/doxygen.cpp
@@ -0,0 +1,301 @@
+/*
+ * Doxygen documentation for the lib2geom library
+ *
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2009-2011 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+// Main page of the documentation - contains logo and introductory text
+/**
+ * @mainpage
+ *
+ * @image html 2geom-logo.png
+ *
+ * @section Introduction
+ *
+ * 2Geom is a computational geometry library intended for use with 2D vector graphics.
+ * It concentrates on high-level algorithms, such as computing the length of a curve
+ * or Boolean operations on paths. It evolved from the geometry code used
+ * in Inkscape, a free software, cross-platform vector graphics editor.
+ *
+ * @section UserGuide User guide
+ *
+ * - @subpage Overview "Overview of 2Geom"
+ * - @ref Primitives "Primitives" - points, angles, lines, axis-aligned rectangles...
+ * - @ref Transforms "Transformations" - mathematical representation for operations
+ * like translation, scaling and rotation.
+ * - @ref Fragments "Fragments" - one-dimensional functions and related utilities.
+ * - @ref Curves "Curves" - functions mapping the unit interval to points on a plane.
+ * - @ref Shapes "Shapes" - circles, ellipses, polygons and the like.
+ * - @ref Paths "Paths" - sequences of contiguous curves, aka splines, and their processing.
+ * - @ref ShapeOps "Shape operations" - boolean algebra, offsets and other advanced operations.
+ * - @ref Containers "Geometric containers" - efficient ways to store and retrieve
+ * geometric information.
+ * - @ref Utilities "Utilities" - other useful code that does not fit under the above categories.
+ * - @subpage ReleaseNotes "Release notes" - what's new in 2Geom
+ *
+ * @section DeveloperInfo Developer information
+ *
+ * - @subpage CodingStandards "Coding standards used in 2Geom"
+ */
+
+// Overview subpage
+/**
+ * @page Overview Overview of 2Geom
+ *
+ * 2Geom has two APIs: a high level one, which uses virtual functions to allow handling
+ * objects of in a generic way without knowing their actual type at compile time,
+ * and a lower-level one based on templates, which is designed with performance in mind.
+ * For performance-critical tasks it may be necessary to use the lower level API.
+ *
+ * @section CoordSys Standard coordinate system
+ *
+ * 2Geom's standard coordinate system is common for computer graphics: the X axis grows
+ * to the right and the Y axis grows downwards. Angles start from the +X axis
+ * and grow towards the +Y axis (clockwise).
+ *
+ * @image html coords.png Standard coordinate system in 2Geom
+ *
+ * Most functions can be used without taking the coordinate system into account,
+ * as their interpretation is the same regardless of the coordinate system. However,
+ * a few of them depend on this definition, for example Rect's top() and bottom() methods.
+ *
+ * @section OpNote Operator note
+ *
+ * Most operators are provided by Boost operator helpers. This means that not all operators
+ * are defined in the class. For example, Rect only implements the operators
+ * +=, -= for points and *= for affines. The corresponding +, - and * operators
+ * are generated automatically by Boost.
+ */
+
+// RELEASE NOTES
+// Update this to describe the most important API changes.
+/**
+ * @page ReleaseNotes 2Geom release notes
+ *
+ * @section Ver04 Version 0.4
+ * - API additions:
+ * - Integer versions of Point, Interval and OptInterval, called
+ * IntPoint, IntInterval and OptIntInterval.
+ * - New geometric primitives: Angle and AngleInterval.
+ * - Major changes:
+ * - Matrix has been renamed to Affine.
+ * - Classification methods of Affine, for example Affine::isRotation(), will now
+ * return true for transforms that are close to identity. This is to reflect the
+ * fact that an identity transform can be interpreted as a rotation by zero
+ * degrees. To get the old behavior of returning false for identity, use
+ * methods prefixed with "Nonzero", e.g. Affine::isNonzeroRotation().
+ * - EllipticalArc and SVGEllipticalArc have been merged. Now there is only the former.
+ * All arcs are SVG-compliant.
+ * - Minor changes:
+ * - Affine::without_translation() is now called Affine::withoutTranslation().
+ * - Interval::strict_contains() is now called Interval::interiorContains().
+ * The same change has been made for Rect.
+ * - Some unclear and unused operators of D2 were removed, for instance D2 * Point.
+ * - Interval is now a derived class of a GenericInterval template.
+ * - Rect is no longer a D2 specialization.
+ * - isnan.h merged with math-utils.h.
+ * @section Ver03 Version 0.3
+ * - release notes were started after this version.
+ */
+
+/**
+ * @page CodingStandards Coding standards and conventions used in 2Geom
+ *
+ * @section Filenames
+ *
+ * Files and directories should be all lowercase. Words should be separated with hyphens (-).
+ * Underscores, capital letters and non-ASCII characters should not be used.
+ *
+ * @section Indenting
+ *
+ * All files should use 4 spaces as indentation.
+ *
+ * @section Namespaces
+ *
+ * All classes intended for direct use by the end users should be in the Geom namespace.
+ * Contents of namespaces should not be indented. Closing brace of a namespace
+ * should have a comment indicating which namespace it is closing.
+ * @code
+ namespace Geom {
+ namespace FooInternal {
+
+ unsigned some_function()
+ {
+ // ...code...
+ }
+
+ } // namespace FooInternal
+ } // namespace Geom
+ @endcode
+ *
+ * @section Classes
+ *
+ * @code
+ // superclass list should use Boost notation,
+ // especially if there is more than one.
+ class Foo
+ : public Bar
+ , public Baz
+ {
+ // constructors should use Boost notation if the class has superclasses.
+ Foo(int a)
+ : Bar(a)
+ , Baz(b)
+ {
+ // constructor body
+ }
+ Foo(int a) {
+ // constructor with default initialization of superclasses
+ }
+
+ // methods use camelCaseNames.
+ // one-line methods can be collapsed.
+ bool isActive() { return _blurp; }
+ // multi-line methods have the opening brace on the same line.
+ void invert() {
+ // ... code ...
+ }
+
+ // static functions use lowercase_with_underscores.
+ // static factory functions should be called from_something.
+ static Foo from_point(Point const &p) {
+ // ...
+ }
+ }; // end of class Foo
+
+ // Closing brace of a class should have the above comment, unless it's very short.
+ @endcode
+ *
+ * @section FreeFuns Free functions
+ *
+ * Functions should use lowercase_with_underscores names. The opening brace of
+ * the definition should be on a separate line.
+ *
+ * @section InlineInClasses When to use inline
+ *
+ * The "inline" keyword is not required when the body of the function is given
+ * in the definition of the class. Do not mark such functions inline, because
+ * they are automatically marked as inline by the compiler. It is only
+ * necessary to use the inline keyword when the body of the function is given
+ * after the class definition.
+ */
+
+// Documentation for groups
+/**
+ * @defgroup Transforms Affine transformations
+ * @brief Transformations of the plane such as rotation and scaling
+ *
+ * Each transformation class represent a set of affine transforms that is closed
+ * under multiplication. Those are translation, scaling, rotation, horizontal shearing
+ * and vertical shearing. Any affine transform can be obtained by combining those
+ * basic operations.
+ *
+ * Each of the transforms can be applied to points and matrices (using multiplication).
+ * Each can also be converted into a matrix (which can represent any composition
+ * of transforms generically). All (except translation) use the origin (0,0) as the invariant
+ * point (e.g. one that stays in the same place after applying the transform to the plane).
+ * To obtain transforms with different invariant points, combine them with translation to
+ * and back from the origin. For example, to get a 60 degree rotation around the point @a p:
+ * @code Affine rot_around_p = Translate(-p) * Rotate::from_degrees(60) * Translate(p); @endcode
+ *
+ * Multiplication of transforms is associative: the result of an expression involving
+ * points and matrices is the same regardless of the order of evaluating multiplications.
+ *
+ * If you need to transform a complicated object
+ * by A, then B, and then C, you should first compute the total transform and apply it to the
+ * object in one go. This way instead of performing 3 expensive operations, you will only do
+ * two very fast matrix multiplications and one complex transformation. Here is an example:
+ * @code
+ transformed_path = long_path * A * B * C; // wrong! long_path will be transformed 3 times.
+ transformed_path = long_path * (A * B * C); // good! long_path will be transformed only once.
+ Affine total = A * B * C; // you can store the transform to apply it to several objects.
+ transformed_path = long_path * total; // good!
+ @endcode
+ * Ordering note: if you compose transformations via multiplication, they are applied
+ * from left to right. If you write <code> ptrans = p * A * B * C * D;</code>, then it means
+ * that @a ptrans is obtained from @a p by first transforming it by A, then by B, then by C,
+ * and finally by D. This is a consequence of interpreting points as row vectors, instead
+ * of the more common column vector interpretation; 2Geom's choice leads to more intuitive
+ * notation.
+ */
+
+/**
+ * @defgroup Primitives Primitives
+ * @brief Basic mathematical objects such as intervals and points
+ *
+ * 2Geom has several basic geometrical objects: points, lines, intervals, angles,
+ * and others. Most of those objects can be treated as sets of points or numbers
+ * satisfying some equation or as functions.
+ */
+
+/**
+ * @defgroup Fragments Fragments and related classes
+ * @brief 1D functions on the unit interval
+ *
+ * Each type of fragments represents one of the various ways in which a function from
+ * the unit interval to the real line may be given. These are the most important mathematical
+ * primitives in 2Geom.
+ */
+
+/**
+ * @defgroup Curves Curves
+ * @brief Functions mapping the unit interval to a plane
+ *
+ * Curves are functions \f$\mathbf{C}: [0, 1] \to \mathbb{R}^2\f$. For details, see
+ * the documentation for the Curve class. All curves can be included in paths and path sequences.
+ */
+
+/**
+ * @defgroup Shapes Basic shapes
+ * @brief Circles, ellipes, polygons...
+ *
+ * Among the shapes supported by 2Geom are circles, ellipses and polygons.
+ * Polygons can also be represented by paths containing only linear segments.
+ */
+
+/**
+ * @defgroup Paths Paths and path sequences
+ * @brief Sequences of contiguous curves, aka splines, and their processing
+ */
+
+/**
+ * @defgroup Utilities Miscellaneous utilities
+ * @brief Useful code that does not fit under other categories.
+ */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/ellipse.cpp b/src/3rdparty/2geom/src/2geom/ellipse.cpp
new file mode 100644
index 0000000..42cb36d
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/ellipse.cpp
@@ -0,0 +1,790 @@
+/** @file
+ * @brief Ellipse shape
+ *//*
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2008-2014 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/conicsec.h>
+#include <2geom/ellipse.h>
+#include <2geom/elliptical-arc.h>
+#include <2geom/numeric/fitting-tool.h>
+#include <2geom/numeric/fitting-model.h>
+
+namespace Geom {
+
+Ellipse::Ellipse(Geom::Circle const &c)
+ : _center(c.center())
+ , _rays(c.radius(), c.radius())
+ , _angle(0)
+{}
+
+void Ellipse::setCoefficients(double A, double B, double C, double D, double E, double F)
+{
+ double den = 4*A*C - B*B;
+ if (den == 0) {
+ THROW_RANGEERROR("den == 0, while computing ellipse centre");
+ }
+ _center[X] = (B*E - 2*C*D) / den;
+ _center[Y] = (B*D - 2*A*E) / den;
+
+ // evaluate the a coefficient of the ellipse equation in normal form
+ // E(x,y) = a*(x-cx)^2 + b*(x-cx)*(y-cy) + c*(y-cy)^2 = 1
+ // where b = a*B , c = a*C, (cx,cy) == centre
+ double num = A * sqr(_center[X])
+ + B * _center[X] * _center[Y]
+ + C * sqr(_center[Y])
+ - F;
+
+
+ //evaluate ellipse rotation angle
+ _angle = std::atan2( -B, -(A - C) )/2;
+
+ // evaluate the length of the ellipse rays
+ double sinrot, cosrot;
+ sincos(_angle, sinrot, cosrot);
+ double cos2 = cosrot * cosrot;
+ double sin2 = sinrot * sinrot;
+ double cossin = cosrot * sinrot;
+
+ den = A * cos2 + B * cossin + C * sin2;
+ if (den == 0) {
+ THROW_RANGEERROR("den == 0, while computing 'rx' coefficient");
+ }
+ double rx2 = num / den;
+ if (rx2 < 0) {
+ THROW_RANGEERROR("rx2 < 0, while computing 'rx' coefficient");
+ }
+ _rays[X] = std::sqrt(rx2);
+
+ den = C * cos2 - B * cossin + A * sin2;
+ if (den == 0) {
+ THROW_RANGEERROR("den == 0, while computing 'ry' coefficient");
+ }
+ double ry2 = num / den;
+ if (ry2 < 0) {
+ THROW_RANGEERROR("ry2 < 0, while computing 'rx' coefficient");
+ }
+ _rays[Y] = std::sqrt(ry2);
+
+ // the solution is not unique so we choose always the ellipse
+ // with a rotation angle between 0 and PI/2
+ makeCanonical();
+}
+
+Point Ellipse::initialPoint() const
+{
+ Coord sinrot, cosrot;
+ sincos(_angle, sinrot, cosrot);
+ Point p(ray(X) * cosrot + center(X), ray(X) * sinrot + center(Y));
+ return p;
+}
+
+
+Affine Ellipse::unitCircleTransform() const
+{
+ Affine ret = Scale(ray(X), ray(Y)) * Rotate(_angle);
+ ret.setTranslation(center());
+ return ret;
+}
+
+Affine Ellipse::inverseUnitCircleTransform() const
+{
+ if (ray(X) == 0 || ray(Y) == 0) {
+ THROW_RANGEERROR("a degenerate ellipse doesn't have an inverse unit circle transform");
+ }
+ Affine ret = Translate(-center()) * Rotate(-_angle) * Scale(1/ray(X), 1/ray(Y));
+ return ret;
+}
+
+
+LineSegment Ellipse::axis(Dim2 d) const
+{
+ Point a(0, 0), b(0, 0);
+ a[d] = -1;
+ b[d] = 1;
+ LineSegment ls(a, b);
+ ls.transform(unitCircleTransform());
+ return ls;
+}
+
+LineSegment Ellipse::semiaxis(Dim2 d, int sign) const
+{
+ Point a(0, 0), b(0, 0);
+ b[d] = sgn(sign);
+ LineSegment ls(a, b);
+ ls.transform(unitCircleTransform());
+ return ls;
+}
+
+Rect Ellipse::boundsExact() const
+{
+ auto const trans = unitCircleTransform();
+
+ auto proj_bounds = [&] (Dim2 d) {
+ // The dth coordinate function pulls back to trans[d] * x + trans[d + 2] * y + trans[d + 4]
+ // in the coordinate system where the ellipse is a unit circle. We compute its range of
+ // values on the unit circle.
+ auto const r = std::hypot(trans[d], trans[d + 2]);
+ auto const mid = trans[d + 4];
+ return Interval(mid - r, mid + r);
+ };
+
+ return { proj_bounds(X), proj_bounds(Y) };
+}
+
+Rect Ellipse::boundsFast() const
+{
+ // Every ellipse is contained in the circle with the same center and radius
+ // equal to the larger of the two rays. We return the bounding square
+ // of this circle (this is really fast but only exact for circles).
+ auto const larger_ray = (ray(X) > ray(Y) ? ray(X) : ray(Y));
+ assert(larger_ray >= 0.0);
+ auto const rr = Point(larger_ray, larger_ray);
+ return Rect(_center - rr, _center + rr);
+}
+
+std::vector<double> Ellipse::coefficients() const
+{
+ std::vector<double> c(6);
+ coefficients(c[0], c[1], c[2], c[3], c[4], c[5]);
+ return c;
+}
+
+void Ellipse::coefficients(Coord &A, Coord &B, Coord &C, Coord &D, Coord &E, Coord &F) const
+{
+ if (ray(X) == 0 || ray(Y) == 0) {
+ THROW_RANGEERROR("a degenerate ellipse doesn't have an implicit form");
+ }
+
+ double cosrot, sinrot;
+ sincos(_angle, sinrot, cosrot);
+ double cos2 = cosrot * cosrot;
+ double sin2 = sinrot * sinrot;
+ double cossin = cosrot * sinrot;
+ double invrx2 = 1 / (ray(X) * ray(X));
+ double invry2 = 1 / (ray(Y) * ray(Y));
+
+ A = invrx2 * cos2 + invry2 * sin2;
+ B = 2 * (invrx2 - invry2) * cossin;
+ C = invrx2 * sin2 + invry2 * cos2;
+ D = -2 * A * center(X) - B * center(Y);
+ E = -2 * C * center(Y) - B * center(X);
+ F = A * center(X) * center(X)
+ + B * center(X) * center(Y)
+ + C * center(Y) * center(Y)
+ - 1;
+}
+
+
+void Ellipse::fit(std::vector<Point> const &points)
+{
+ size_t sz = points.size();
+ if (sz < 5) {
+ THROW_RANGEERROR("fitting error: too few points passed");
+ }
+ NL::LFMEllipse model;
+ NL::least_squeares_fitter<NL::LFMEllipse> fitter(model, sz);
+
+ for (size_t i = 0; i < sz; ++i) {
+ fitter.append(points[i]);
+ }
+ fitter.update();
+
+ NL::Vector z(sz, 0.0);
+ model.instance(*this, fitter.result(z));
+}
+
+
+EllipticalArc *
+Ellipse::arc(Point const &ip, Point const &inner, Point const &fp)
+{
+ // This is resistant to degenerate ellipses:
+ // both flags evaluate to false in that case.
+
+ bool large_arc_flag = false;
+ bool sweep_flag = false;
+
+ // Determination of large arc flag:
+ // large_arc is false when the inner point is on the same side
+ // of the center---initial point line as the final point, AND
+ // is on the same side of the center---final point line as the
+ // initial point.
+ // Additionally, large_arc is always false when we have exactly
+ // 1/2 of an arc, i.e. the cross product of the center -> initial point
+ // and center -> final point vectors is zero.
+ // Negating the above leads to the condition for large_arc being true.
+ Point fv = fp - _center;
+ Point iv = ip - _center;
+ Point innerv = inner - _center;
+ double ifcp = cross(fv, iv);
+
+ if (ifcp != 0 && (sgn(cross(fv, innerv)) != sgn(ifcp) ||
+ sgn(cross(iv, innerv)) != sgn(-ifcp)))
+ {
+ large_arc_flag = true;
+ }
+
+ // Determination of sweep flag:
+ // For clarity, let's assume that Y grows up. Then the cross product
+ // is positive for points on the left side of a vector and negative
+ // on the right side of a vector.
+ //
+ // cross(?, v) > 0
+ // o------------------->
+ // cross(?, v) < 0
+ //
+ // If the arc is small (large_arc_flag is false) and the final point
+ // is on the right side of the vector initial point -> center,
+ // we have to go in the direction of increasing angles
+ // (counter-clockwise) and the sweep flag is true.
+ // If the arc is large, the opposite is true, since we have to reach
+ // the final point going the long way - in the other direction.
+ // We can express this observation as:
+ // cross(_center - ip, fp - _center) < 0 xor large_arc flag
+ // This is equal to:
+ // cross(-iv, fv) < 0 xor large_arc flag
+ // But cross(-iv, fv) is equal to cross(fv, iv) due to antisymmetry
+ // of the cross product, so we end up with the condition below.
+ if ((ifcp < 0) ^ large_arc_flag) {
+ sweep_flag = true;
+ }
+
+ EllipticalArc *ret_arc = new EllipticalArc(ip, ray(X), ray(Y), rotationAngle(),
+ large_arc_flag, sweep_flag, fp);
+ return ret_arc;
+}
+
+Ellipse &Ellipse::operator*=(Rotate const &r)
+{
+ _angle += r.angle();
+ _center *= r;
+ return *this;
+}
+
+Ellipse &Ellipse::operator*=(Affine const& m)
+{
+ Affine a = Scale(ray(X), ray(Y)) * Rotate(_angle);
+ Affine mwot = m.withoutTranslation();
+ Affine am = a * mwot;
+ Point new_center = _center * m;
+
+ if (are_near(am.descrim(), 0)) {
+ double angle;
+ if (am[0] != 0) {
+ angle = std::atan2(am[2], am[0]);
+ } else if (am[1] != 0) {
+ angle = std::atan2(am[3], am[1]);
+ } else {
+ angle = M_PI/2;
+ }
+ Point v = Point::polar(angle) * am;
+ _center = new_center;
+ _rays[X] = L2(v);
+ _rays[Y] = 0;
+ _angle = atan2(v);
+ return *this;
+ } else if (mwot.isScale(0) && _angle.radians() == 0) {
+ _rays[X] *= std::abs(mwot[0]);
+ _rays[Y] *= std::abs(mwot[3]);
+ _center = new_center;
+ return *this;
+ }
+
+ std::vector<double> coeff = coefficients();
+ Affine q( coeff[0], coeff[1]/2,
+ coeff[1]/2, coeff[2],
+ 0, 0 );
+
+ Affine invm = mwot.inverse();
+ q = invm * q ;
+ std::swap(invm[1], invm[2]);
+ q *= invm;
+ setCoefficients(q[0], 2*q[1], q[3], 0, 0, -1);
+ _center = new_center;
+
+ return *this;
+}
+
+Ellipse Ellipse::canonicalForm() const
+{
+ Ellipse result(*this);
+ result.makeCanonical();
+ return result;
+}
+
+void Ellipse::makeCanonical()
+{
+ if (_rays[X] == _rays[Y]) {
+ _angle = 0;
+ return;
+ }
+
+ if (_angle < 0) {
+ _angle += M_PI;
+ }
+ if (_angle >= M_PI/2) {
+ std::swap(_rays[X], _rays[Y]);
+ _angle -= M_PI/2;
+ }
+}
+
+Point Ellipse::pointAt(Coord t) const
+{
+ Point p = Point::polar(t);
+ p *= unitCircleTransform();
+ return p;
+}
+
+Coord Ellipse::valueAt(Coord t, Dim2 d) const
+{
+ Coord sinrot, cosrot, cost, sint;
+ sincos(rotationAngle(), sinrot, cosrot);
+ sincos(t, sint, cost);
+
+ if ( d == X ) {
+ return ray(X) * cosrot * cost
+ - ray(Y) * sinrot * sint
+ + center(X);
+ } else {
+ return ray(X) * sinrot * cost
+ + ray(Y) * cosrot * sint
+ + center(Y);
+ }
+}
+
+Coord Ellipse::timeAt(Point const &p) const
+{
+ // degenerate ellipse is basically a reparametrized line segment
+ if (ray(X) == 0 || ray(Y) == 0) {
+ if (ray(X) != 0) {
+ return asin(Line(axis(X)).timeAt(p));
+ } else if (ray(Y) != 0) {
+ return acos(Line(axis(Y)).timeAt(p));
+ } else {
+ return 0;
+ }
+ }
+ Affine iuct = inverseUnitCircleTransform();
+ return Angle(atan2(p * iuct)).radians0(); // return a value in [0, 2pi)
+}
+
+Point Ellipse::unitTangentAt(Coord t) const
+{
+ Point p = Point::polar(t + M_PI/2);
+ p *= unitCircleTransform().withoutTranslation();
+ p.normalize();
+ return p;
+}
+
+bool Ellipse::contains(Point const &p) const
+{
+ Point tp = p * inverseUnitCircleTransform();
+ return tp.length() <= 1;
+}
+
+/** @brief Convert curve time on the major axis to the corresponding angle
+ * parameters on a degenerate ellipse collapsed onto that axis.
+ * @param t The curve time on the major axis of an ellipse.
+ * @param vertical If true, the major axis goes from angle -Ï€/2 to +Ï€/2;
+ * otherwise, the major axis connects angles π and 0.
+ * @return The two angles at which the collapsed ellipse passes through the
+ * major axis point corresponding to the given time \f$t \in [0, 1]\f$.
+ */
+static std::array<Coord, 2> axis_time_to_angles(Coord t, bool vertical)
+{
+ Coord const to_unit = std::clamp(2.0 * t - 1.0, -1.0, 1.0);
+ if (vertical) {
+ double const arcsin = std::asin(to_unit);
+ return {arcsin, M_PI - arcsin};
+ } else {
+ double const arccos = std::acos(to_unit);
+ return {arccos, -arccos};
+ }
+}
+
+/** @brief For each intersection of some shape with the major axis of an ellipse, produce one or two
+ * intersections of a degenerate ellipse (collapsed onto that axis) with the same shape.
+ *
+ * @param axis_intersections The intersections of some shape with the major axis.
+ * @param vertical Whether this is the vertical major axis (in the ellipse's natural coordinates).
+ * @return A vector with doubled intersections (corresponding to the two passages of the squashed
+ * ellipse through that point) and swapped order of the intersected shapes.
+*/
+static std::vector<ShapeIntersection> double_axis_intersections(std::vector<ShapeIntersection> &&axis_intersections,
+ bool vertical)
+{
+ if (axis_intersections.empty()) {
+ return {};
+ }
+ std::vector<ShapeIntersection> result;
+ result.reserve(2 * axis_intersections.size());
+
+ for (auto const &x : axis_intersections) {
+ for (auto a : axis_time_to_angles(x.second, vertical)) {
+ result.emplace_back(a, x.first, x.point()); // Swap first <-> converted second.
+ if (x.second == 0.0 || x.second == 1.0) {
+ break; // Do not double up endpoint intersections.
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<ShapeIntersection> Ellipse::intersect(Line const &line) const
+{
+ std::vector<ShapeIntersection> result;
+
+ if (line.isDegenerate()) {
+ return result;
+ }
+ if (ray(X) == 0 || ray(Y) == 0) {
+ return double_axis_intersections(line.intersect(majorAxis()), ray(X) == 0);
+ }
+
+ // Ax^2 + Bxy + Cy^2 + Dx + Ey + F
+ std::array<Coord, 6> coeffs;
+ coefficients(coeffs[0], coeffs[1], coeffs[2], coeffs[3], coeffs[4], coeffs[5]);
+ rescale_homogenous(coeffs);
+ auto [A, B, C, D, E, F] = coeffs;
+ Affine iuct = inverseUnitCircleTransform();
+
+ // generic case
+ std::array<Coord, 3> line_coeffs;
+ line.coefficients(line_coeffs[0], line_coeffs[1], line_coeffs[2]);
+ rescale_homogenous(line_coeffs);
+ auto [a, b, c] = line_coeffs;
+ Point lv = line.vector();
+
+ if (fabs(lv[X]) > fabs(lv[Y])) {
+ // y = -a/b x - c/b
+ Coord q = -a/b;
+ Coord r = -c/b;
+
+ // substitute that into the ellipse equation, making it quadratic in x
+ Coord I = A + B*q + C*q*q; // x^2 terms
+ Coord J = B*r + C*2*q*r + D + E*q; // x^1 terms
+ Coord K = C*r*r + E*r + F; // x^0 terms
+ std::vector<Coord> xs = solve_quadratic(I, J, K);
+
+ for (double x : xs) {
+ Point p(x, q*x + r);
+ result.emplace_back(atan2(p * iuct), line.timeAt(p), p);
+ }
+ } else {
+ Coord q = -b/a;
+ Coord r = -c/a;
+
+ Coord I = A*q*q + B*q + C;
+ Coord J = A*2*q*r + B*r + D*q + E;
+ Coord K = A*r*r + D*r + F;
+ std::vector<Coord> xs = solve_quadratic(I, J, K);
+
+ for (double x : xs) {
+ Point p(q*x + r, x);
+ result.emplace_back(atan2(p * iuct), line.timeAt(p), p);
+ }
+ }
+ return result;
+}
+
+std::vector<ShapeIntersection> Ellipse::intersect(LineSegment const &seg) const
+{
+ if (!boundsFast().intersects(seg.boundsFast())) {
+ return {};
+ }
+
+ // We simply reuse the procedure for lines and filter out
+ // results where the line time value is outside of the unit interval,
+ // but we apply a small tolerance to account for numerical errors.
+ double const param_prec = EPSILON / seg.length(0.0);
+ // TODO: accept a precision setting instead of always using EPSILON
+ // (requires an ABI break).
+
+ auto xings = intersect(Line(seg));
+ if (xings.empty()) {
+ return xings;
+ }
+ decltype(xings) result;
+ result.reserve(xings.size());
+
+ for (auto const &x : xings) {
+ if (x.second < -param_prec || x.second > 1.0 + param_prec) {
+ continue;
+ }
+ result.emplace_back(x.first, std::clamp(x.second, 0.0, 1.0), x.point());
+ }
+ return result;
+}
+
+std::vector<ShapeIntersection> Ellipse::intersect(Ellipse const &other) const
+{
+ // Handle degenerate cases first.
+ if (ray(X) == 0 || ray(Y) == 0) { // Degenerate ellipse, collapsed to the major axis.
+ return double_axis_intersections(other.intersect(majorAxis()), ray(X) == 0);
+ }
+ if (*this == other) { // Two identical ellipses.
+ THROW_INFINITELY_MANY_SOLUTIONS("The two ellipses are identical.");
+ }
+ if (!boundsFast().intersects(other.boundsFast())) {
+ return {};
+ }
+
+ // Find coefficients of the implicit equations of the two ellipses and rescale
+ // them (losslessly) for better numerical conditioning.
+ std::array<double, 6> coeffs;
+ coefficients(coeffs[0], coeffs[1], coeffs[2], coeffs[3], coeffs[4], coeffs[5]);
+ rescale_homogenous(coeffs);
+ auto [A, B, C, D, E, F] = coeffs;
+
+ std::array<double, 6> otheffs;
+ other.coefficients(otheffs[0], otheffs[1], otheffs[2], otheffs[3], otheffs[4], otheffs[5]);
+ rescale_homogenous(otheffs);
+ auto [a, b, c, d, e, f] = otheffs;
+
+ // Assume that Q(x, y) = 0 is the ellipse equation given by uppercase letters
+ // and R(x, y) = 0 is the equation given by lowercase ones.
+ // In other words, Q is the quadratic function describing this ellipse and
+ // R is the quadratic function for the other ellipse.
+ //
+ // A point (x, y) is common to both ellipses if and only if it solves the system
+ // { Q(x, y) = 0,
+ // { R(x, y) = 0.
+ //
+ // If µ is any real number, we can multiply the first equation by µ and add that
+ // to the first equation, obtaining the new system of equations:
+ // { Q(x, y) = 0,
+ // { µQ(x, y) + R(x, y) = 0.
+ //
+ // The first equation still says that (x, y) is a point on this ellipse, but the
+ // second equation uses the new expression (µQ + R) instead of the original R.
+ //
+ // Why do we do this? The reason is that the set of functions {µQ + R : µ real}
+ // is a "real system of conics" and there's a theorem which guarantees that such a system
+ // always contains a "degenerate conic" [proof below].
+ // In practice, the degenerate conic will describe a line or a pair of lines, and intersecting
+ // a line with an ellipse is much easier than intersecting two ellipses directly.
+ //
+ // But in order to be able to do this, we must find a value of µ for which µQ + R is degenerate.
+ // We can write the expression (µQ + R)(x, y) in the following way:
+ //
+ // | aa bb/2 dd/2 | |x|
+ // (µQ + R)(x, y) = [x y 1] | bb/2 cc ee/2 | |y|
+ // | dd/2 ee/2 ff | |1|
+ //
+ // where aa = µA + a and so on. The determinant can be explicitly written out,
+ // giving an equation which is cubic in µ and can be solved analytically.
+ // The conic µQ + R is degenerate if and only if this determinant is 0.
+ //
+ // Proof that there's always a degenerate conic: a cubic real polynomial always has a root,
+ // and if the polynomial in µ isn't cubic (coefficient of µ^3 is zero), then the starting
+ // conic is already degenerate.
+
+ Coord I, J, K, L; // Coefficients of µ in the expression for the determinant.
+ I = (-B*B*F + 4*A*C*F + D*E*B - A*E*E - C*D*D) / 4;
+ J = -((B*B - 4*A*C) * f + (2*B*F - D*E) * b + (2*A*E - D*B) * e +
+ (2*C*D - E*B) * d + (D*D - 4*A*F) * c + (E*E - 4*C*F) * a) / 4;
+ K = -((b*b - 4*a*c) * F + (2*b*f - d*e) * B + (2*a*e - d*b) * E +
+ (2*c*d - e*b) * D + (d*d - 4*a*f) * C + (e*e - 4*c*f) * A) / 4;
+ L = (-b*b*f + 4*a*c*f + d*e*b - a*e*e - c*d*d) / 4;
+
+ std::vector<Coord> mus = solve_cubic(I, J, K, L);
+ Coord mu = infinity();
+
+ // Now that we have solved for µ, we need to check whether the conic
+ // determined by µQ + R is reducible to a product of two lines. If it's not,
+ // it means that there are no intersections. If it is, the intersections of these
+ // lines with the original ellipses (if there are any) give the coordinates
+ // of intersections.
+
+ // Prefer middle root if there are three.
+ // Out of three possible pairs of lines that go through four points of intersection
+ // of two ellipses, this corresponds to cross-lines. These intersect the ellipses
+ // at less shallow angles than the other two options.
+ if (mus.size() == 3) {
+ std::swap(mus[1], mus[0]);
+ }
+ /// Discriminant within this radius of 0 will be considered zero.
+ static Coord const discriminant_precision = 1e-10;
+
+ for (Coord candidate_mu : mus) {
+ Coord const aa = std::fma(candidate_mu, A, a);
+ Coord const bb = std::fma(candidate_mu, B, b);
+ Coord const cc = std::fma(candidate_mu, C, c);
+ Coord const delta = sqr(bb) - 4*aa*cc;
+ if (delta < -discriminant_precision) {
+ continue;
+ }
+ mu = candidate_mu;
+ break;
+ }
+
+ // if no suitable mu was found, there are no intersections
+ if (mu == infinity()) {
+ return {};
+ }
+
+ // Create the degenerate conic and decompose it into lines.
+ std::array<double, 6> degen = {std::fma(mu, A, a), std::fma(mu, B, b), std::fma(mu, C, c),
+ std::fma(mu, D, d), std::fma(mu, E, e), std::fma(mu, F, f)};
+ rescale_homogenous(degen);
+ auto const lines = xAx(degen[0], degen[1], degen[2],
+ degen[3], degen[4], degen[5]).decompose_df(discriminant_precision);
+
+ // intersect with the obtained lines and report intersections
+ std::vector<ShapeIntersection> result;
+ for (auto const &line : lines) {
+ if (line.isDegenerate()) {
+ continue;
+ }
+ auto as = intersect(line);
+ // NOTE: If we only cared about the intersection points, we could simply
+ // intersect this ellipse with the lines and ignore the other ellipse.
+ // But we need the time coordinates on the other ellipse as well.
+ auto bs = other.intersect(line);
+ if (as.empty() || bs.empty()) {
+ continue;
+ }
+ // Due to numerical errors, a tangency may sometimes be found as 1 intersection
+ // on one ellipse and 2 intersections on the other. If this happens, we average
+ // the points of the two intersections.
+ auto const intersection_average = [](ShapeIntersection const &i,
+ ShapeIntersection const &j) -> ShapeIntersection
+ {
+ return ShapeIntersection(i.first, j.first, middle_point(i.point(), j.point()));
+ };
+ auto const synthesize_intersection = [&](ShapeIntersection const &i,
+ ShapeIntersection const &j) -> void
+ {
+ result.emplace_back(i.first, j.first, middle_point(i.point(), j.point()));
+ };
+ if (as.size() == 2) {
+ if (bs.size() == 2) {
+ synthesize_intersection(as[0], bs[0]);
+ synthesize_intersection(as[1], bs[1]);
+ } else if (bs.size() == 1) {
+ synthesize_intersection(intersection_average(as[0], as[1]), bs[0]);
+ }
+ } else if (as.size() == 1) {
+ if (bs.size() == 2) {
+ synthesize_intersection(as[0], intersection_average(bs[0], bs[1]));
+ } else if (bs.size() == 1) {
+ synthesize_intersection(as[0], bs[0]);
+ }
+ }
+ }
+ return result;
+}
+
+std::vector<ShapeIntersection> Ellipse::intersect(D2<Bezier> const &b) const
+{
+ Coord A, B, C, D, E, F;
+ coefficients(A, B, C, D, E, F);
+
+ // We plug the X and Y curves into the implicit equation and solve for t.
+ Bezier x = A*b[X]*b[X] + B*b[X]*b[Y] + C*b[Y]*b[Y] + D*b[X] + E*b[Y] + F;
+ std::vector<Coord> r = x.roots();
+
+ std::vector<ShapeIntersection> result;
+ for (double & i : r) {
+ Point p = b.valueAt(i);
+ result.emplace_back(timeAt(p), i, p);
+ }
+ return result;
+}
+
+bool Ellipse::operator==(Ellipse const &other) const
+{
+ if (_center != other._center) return false;
+
+ Ellipse a = this->canonicalForm();
+ Ellipse b = other.canonicalForm();
+
+ if (a._rays != b._rays) return false;
+ if (a._angle != b._angle) return false;
+
+ return true;
+}
+
+
+bool are_near(Ellipse const &a, Ellipse const &b, Coord precision)
+{
+ // We want to know whether no point on ellipse a is further than precision
+ // from the corresponding point on ellipse b. To check this, we compute
+ // the four extreme points at the end of each ray for each ellipse
+ // and check whether they are sufficiently close.
+
+ // First, we need to correct the angles on the ellipses, so that they are
+ // no further than M_PI/4 apart. This can always be done by rotating
+ // and exchanging axes.
+ Ellipse ac = a, bc = b;
+ if (distance(ac.rotationAngle(), bc.rotationAngle()).radians0() >= M_PI/2) {
+ ac.setRotationAngle(ac.rotationAngle() + M_PI);
+ }
+ if (distance(ac.rotationAngle(), bc.rotationAngle()) >= M_PI/4) {
+ Angle d1 = distance(ac.rotationAngle() + M_PI/2, bc.rotationAngle());
+ Angle d2 = distance(ac.rotationAngle() - M_PI/2, bc.rotationAngle());
+ Coord adj = d1.radians0() < d2.radians0() ? M_PI/2 : -M_PI/2;
+ ac.setRotationAngle(ac.rotationAngle() + adj);
+ ac.setRays(ac.ray(Y), ac.ray(X));
+ }
+
+ // Do the actual comparison by computing four points on each ellipse.
+ Point tps[] = {Point(1,0), Point(0,1), Point(-1,0), Point(0,-1)};
+ for (auto & tp : tps) {
+ if (!are_near(tp * ac.unitCircleTransform(),
+ tp * bc.unitCircleTransform(),
+ precision))
+ return false;
+ }
+ return true;
+}
+
+std::ostream &operator<<(std::ostream &out, Ellipse const &e)
+{
+ out << "Ellipse(" << e.center() << ", " << e.rays()
+ << ", " << format_coord_nice(e.rotationAngle()) << ")";
+ return out;
+}
+
+} // end namespace Geom
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+
+
diff --git a/src/3rdparty/2geom/src/2geom/elliptical-arc-from-sbasis.cpp b/src/3rdparty/2geom/src/2geom/elliptical-arc-from-sbasis.cpp
new file mode 100644
index 0000000..c536d89
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/elliptical-arc-from-sbasis.cpp
@@ -0,0 +1,341 @@
+/** @file
+ * @brief Fitting elliptical arc to SBasis
+ *
+ * This file contains the implementation of the function arc_from_sbasis.
+ *//*
+ * Copyright 2008 Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/curve.h>
+#include <2geom/angle.h>
+#include <2geom/utils.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/elliptical-arc.h>
+#include <2geom/sbasis-curve.h> // for non-native methods
+#include <2geom/numeric/vector.h>
+#include <2geom/numeric/fitting-tool.h>
+#include <2geom/numeric/fitting-model.h>
+#include <algorithm>
+
+namespace Geom {
+
+// forward declaration
+namespace detail
+{
+ struct ellipse_equation;
+}
+
+/*
+ * make_elliptical_arc
+ *
+ * convert a parametric polynomial curve given in symmetric power basis form
+ * into an EllipticalArc type; in order to be successful the input curve
+ * has to look like an actual elliptical arc even if a certain tolerance
+ * is allowed through an ad-hoc parameter.
+ * The conversion is performed through an interpolation on a certain amount of
+ * sample points computed on the input curve;
+ * the interpolation computes the coefficients of the general implicit equation
+ * of an ellipse (A*X^2 + B*XY + C*Y^2 + D*X + E*Y + F = 0), then from the
+ * implicit equation we compute the parametric form.
+ *
+ */
+class make_elliptical_arc
+{
+ public:
+ typedef D2<SBasis> curve_type;
+
+ /*
+ * constructor
+ *
+ * it doesn't execute the conversion but set the input and output parameters
+ *
+ * _ea: the output EllipticalArc that will be generated;
+ * _curve: the input curve to be converted;
+ * _total_samples: the amount of sample points to be taken
+ * on the input curve for performing the conversion
+ * _tolerance: how much likelihood is required between the input curve
+ * and the generated elliptical arc; the smaller it is the
+ * the tolerance the higher it is the likelihood.
+ */
+ make_elliptical_arc( EllipticalArc& _ea,
+ curve_type const& _curve,
+ unsigned int _total_samples,
+ double _tolerance );
+
+ private:
+ bool bound_exceeded( unsigned int k, detail::ellipse_equation const & ee,
+ double e1x, double e1y, double e2 );
+
+ bool check_bound(double A, double B, double C, double D, double E, double F);
+
+ void fit();
+
+ bool make_elliptiarc();
+
+ void print_bound_error(unsigned int k)
+ {
+ std::cerr
+ << "tolerance error" << std::endl
+ << "at point: " << k << std::endl
+ << "error value: "<< dist_err << std::endl
+ << "bound: " << dist_bound << std::endl
+ << "angle error: " << angle_err
+ << " (" << angle_tol << ")" << std::endl;
+ }
+
+ public:
+ /*
+ * perform the actual conversion
+ * return true if the conversion is successful, false on the contrary
+ */
+ bool operator()()
+ {
+ // initialize the reference
+ const NL::Vector & coeff = fitter.result();
+ fit();
+ if ( !check_bound(1, coeff[0], coeff[1], coeff[2], coeff[3], coeff[4]) )
+ return false;
+ if ( !(make_elliptiarc()) ) return false;
+ return true;
+ }
+
+ private:
+ EllipticalArc& ea; // output elliptical arc
+ const curve_type & curve; // input curve
+ Piecewise<D2<SBasis> > dcurve; // derivative of the input curve
+ NL::LFMEllipse model; // model used for fitting
+ // perform the actual fitting task
+ NL::least_squeares_fitter<NL::LFMEllipse> fitter;
+ // tolerance: the user-defined tolerance parameter;
+ // tol_at_extr: the tolerance at end-points automatically computed
+ // on the value of "tolerance", and usually more strict;
+ // tol_at_center: tolerance at the center of the ellipse
+ // angle_tol: tolerance for the angle btw the input curve tangent
+ // versor and the ellipse normal versor at the sample points
+ double tolerance, tol_at_extr, tol_at_center, angle_tol;
+ Point initial_point, final_point; // initial and final end-points
+ unsigned int N; // total samples
+ unsigned int last; // N-1
+ double partitions; // N-1
+ std::vector<Point> p; // sample points
+ double dist_err, dist_bound, angle_err;
+};
+
+namespace detail
+{
+/*
+ * ellipse_equation
+ *
+ * this is an helper struct, it provides two routines:
+ * the first one evaluates the implicit form of an ellipse on a given point
+ * the second one computes the normal versor at a given point of an ellipse
+ * in implicit form
+ */
+struct ellipse_equation
+{
+ ellipse_equation(double a, double b, double c, double d, double e, double f)
+ : A(a), B(b), C(c), D(d), E(e), F(f)
+ {
+ }
+
+ double operator()(double x, double y) const
+ {
+ // A * x * x + B * x * y + C * y * y + D * x + E * y + F;
+ return (A * x + B * y + D) * x + (C * y + E) * y + F;
+ }
+
+ double operator()(Point const& p) const
+ {
+ return (*this)(p[X], p[Y]);
+ }
+
+ Point normal(double x, double y) const
+ {
+ Point n( 2 * A * x + B * y + D, 2 * C * y + B * x + E );
+ return unit_vector(n);
+ }
+
+ Point normal(Point const& p) const
+ {
+ return normal(p[X], p[Y]);
+ }
+
+ double A, B, C, D, E, F;
+};
+
+} // end namespace detail
+
+make_elliptical_arc::
+make_elliptical_arc( EllipticalArc& _ea,
+ curve_type const& _curve,
+ unsigned int _total_samples,
+ double _tolerance )
+ : ea(_ea), curve(_curve),
+ dcurve( unitVector(derivative(curve)) ),
+ model(), fitter(model, _total_samples),
+ tolerance(_tolerance), tol_at_extr(tolerance/2),
+ tol_at_center(0.1), angle_tol(0.1),
+ initial_point(curve.at0()), final_point(curve.at1()),
+ N(_total_samples), last(N-1), partitions(N-1), p(N)
+{
+}
+
+/*
+ * check that the coefficients computed by the fit method satisfy
+ * the tolerance parameters at the k-th sample point
+ */
+bool
+make_elliptical_arc::
+bound_exceeded( unsigned int k, detail::ellipse_equation const & ee,
+ double e1x, double e1y, double e2 )
+{
+ dist_err = std::fabs( ee(p[k]) );
+ dist_bound = std::fabs( e1x * p[k][X] + e1y * p[k][Y] + e2 );
+ // check that the angle btw the tangent versor to the input curve
+ // and the normal versor of the elliptical arc, both evaluate
+ // at the k-th sample point, are really othogonal
+ angle_err = std::fabs( dot( dcurve(k/partitions), ee.normal(p[k]) ) );
+ //angle_err *= angle_err;
+ return ( dist_err > dist_bound || angle_err > angle_tol );
+}
+
+/*
+ * check that the coefficients computed by the fit method satisfy
+ * the tolerance parameters at each sample point
+ */
+bool
+make_elliptical_arc::
+check_bound(double A, double B, double C, double D, double E, double F)
+{
+ detail::ellipse_equation ee(A, B, C, D, E, F);
+
+ // check error magnitude at the end-points
+ double e1x = (2*A + B) * tol_at_extr;
+ double e1y = (B + 2*C) * tol_at_extr;
+ double e2 = ((D + E) + (A + B + C) * tol_at_extr) * tol_at_extr;
+ if (bound_exceeded(0, ee, e1x, e1y, e2))
+ {
+ print_bound_error(0);
+ return false;
+ }
+ if (bound_exceeded(0, ee, e1x, e1y, e2))
+ {
+ print_bound_error(last);
+ return false;
+ }
+
+ // e1x = derivative((ee(x,y), x) | x->tolerance, y->tolerance
+ e1x = (2*A + B) * tolerance;
+ // e1y = derivative((ee(x,y), y) | x->tolerance, y->tolerance
+ e1y = (B + 2*C) * tolerance;
+ // e2 = ee(tolerance, tolerance) - F;
+ e2 = ((D + E) + (A + B + C) * tolerance) * tolerance;
+// std::cerr << "e1x = " << e1x << std::endl;
+// std::cerr << "e1y = " << e1y << std::endl;
+// std::cerr << "e2 = " << e2 << std::endl;
+
+ // check error magnitude at sample points
+ for ( unsigned int k = 1; k < last; ++k )
+ {
+ if ( bound_exceeded(k, ee, e1x, e1y, e2) )
+ {
+ print_bound_error(k);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*
+ * fit
+ *
+ * supply the samples to the fitter and compute
+ * the ellipse implicit equation coefficients
+ */
+void make_elliptical_arc::fit()
+{
+ for (unsigned int k = 0; k < N; ++k)
+ {
+ p[k] = curve( k / partitions );
+ fitter.append(p[k]);
+ }
+ fitter.update();
+
+ NL::Vector z(N, 0.0);
+ fitter.result(z);
+}
+
+bool make_elliptical_arc::make_elliptiarc()
+{
+ const NL::Vector & coeff = fitter.result();
+ Ellipse e;
+ try
+ {
+ e.setCoefficients(1, coeff[0], coeff[1], coeff[2], coeff[3], coeff[4]);
+ }
+ catch(LogicalError const &exc)
+ {
+ return false;
+ }
+
+ Point inner_point = curve(0.5);
+
+ std::unique_ptr<EllipticalArc> arc( e.arc(initial_point, inner_point, final_point) );
+ ea = *arc;
+
+ if ( !are_near( e.center(),
+ ea.center(),
+ tol_at_center * std::min(e.ray(X),e.ray(Y))
+ )
+ )
+ {
+ return false;
+ }
+ return true;
+}
+
+
+
+bool arc_from_sbasis(EllipticalArc &ea, D2<SBasis> const &in,
+ double tolerance, unsigned num_samples)
+{
+ make_elliptical_arc convert(ea, in, num_samples, tolerance);
+ return convert();
+}
+
+} // end namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/elliptical-arc.cpp b/src/3rdparty/2geom/src/2geom/elliptical-arc.cpp
new file mode 100644
index 0000000..63e534c
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/elliptical-arc.cpp
@@ -0,0 +1,1045 @@
+/*
+ * SVG Elliptical Arc Class
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ * Copyright 2008-2009 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <cfloat>
+#include <limits>
+#include <memory>
+
+#include <2geom/bezier-curve.h>
+#include <2geom/ellipse.h>
+#include <2geom/elliptical-arc.h>
+#include <2geom/path-sink.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/transforms.h>
+#include <2geom/utils.h>
+
+#include <2geom/numeric/vector.h>
+#include <2geom/numeric/fitting-tool.h>
+#include <2geom/numeric/fitting-model.h>
+
+namespace Geom
+{
+
+/**
+ * @class EllipticalArc
+ * @brief Elliptical arc curve
+ *
+ * Elliptical arc is a curve taking the shape of a section of an ellipse.
+ *
+ * The arc function has two forms: the regular one, mapping the unit interval to points
+ * on 2D plane (the linear domain), and a second form that maps some interval
+ * \f$A \subseteq [0,2\pi)\f$ to the same points (the angular domain). The interval \f$A\f$
+ * determines which part of the ellipse forms the arc. The arc is said to contain an angle
+ * if its angular domain includes that angle (and therefore it is defined for that angle).
+ *
+ * The angular domain considers each ellipse to be
+ * a rotated, scaled and translated unit circle: 0 corresponds to \f$(1,0)\f$ on the unit circle,
+ * \f$\pi/2\f$ corresponds to \f$(0,1)\f$, \f$\pi\f$ to \f$(-1,0)\f$ and \f$3\pi/2\f$
+ * to \f$(0,-1)\f$. After the angle is mapped to a point from a unit circle, the point is
+ * transformed using a matrix of this form
+ * \f[ M = \left[ \begin{array}{ccc}
+ r_X \cos(\theta) & -r_Y \sin(\theta) & 0 \\
+ r_X \sin(\theta) & r_Y \cos(\theta) & 0 \\
+ c_X & c_Y & 1 \end{array} \right] \f]
+ * where \f$r_X, r_Y\f$ are the X and Y rays of the ellipse, \f$\theta\f$ is its angle of rotation,
+ * and \f$c_X, c_Y\f$ the coordinates of the ellipse's center - thus mapping the angle
+ * to some point on the ellipse. Note that for example the point at angluar coordinate 0,
+ * the center and the point at angular coordinate \f$\pi/4\f$ do not necessarily
+ * create an angle of \f$\pi/4\f$ radians; it is only the case if both axes of the ellipse
+ * are of the same length (i.e. it is a circle).
+ *
+ * @image html ellipse-angular-coordinates.png "An illustration of the angular domain"
+ *
+ * Each arc is defined by five variables: The initial and final point, the ellipse's rays,
+ * and the ellipse's rotation. Each set of those parameters corresponds to four different arcs,
+ * with two of them larger than half an ellipse and two of them turning clockwise while traveling
+ * from initial to final point. The two flags disambiguate between them: "large arc flag" selects
+ * the bigger arc, while the "sweep flag" selects the arc going in the direction of positive
+ * angles. Angles always increase when going from the +X axis in the direction of the +Y axis,
+ * so if Y grows downwards, this means clockwise.
+ *
+ * @image html elliptical-arc-flags.png "Meaning of arc flags (Y grows downwards)"
+ *
+ * @ingroup Curves
+ */
+
+
+/** @brief Compute bounds of an elliptical arc.
+ * The bounds computation works as follows. The extreme X and Y points
+ * are either the endpoints or local minima / maxima of the ellipse.
+ * We already have endpoints, and we compute the local extremes.
+ * The local extremes correspond to two angles separated by \f$\pi\f$.
+ * Once we compute these angles, we check whether they belong to the arc,
+ * and if they do, we evaluate the ellipse at these angles.
+ * The bounding box of the arc is equal to the bounding box of the endpoints
+ * and the local extrema that belong to the arc.
+ */
+Rect EllipticalArc::boundsExact() const
+{
+ if (isChord()) {
+ return { _initial_point, _final_point };
+ }
+
+ if (_angles.isFull()) {
+ return _ellipse.boundsExact();
+ }
+
+ auto const trans = unitCircleTransform();
+
+ auto proj_bounds = [&] (Dim2 d) {
+ // The dth coordinate function pulls back to trans[d] * x + trans[d + 2] * y + trans[d + 4]
+ // in the coordinate system where the ellipse is a unit circle. We compute its range of
+ // values on the unit circle arc.
+ auto result = Interval(_initial_point[d], _final_point[d]);
+
+ auto const v = Point(trans[d], trans[d + 2]);
+ auto const r = v.length();
+ auto const mid = trans[d + 4];
+ auto const angle = Angle(v);
+
+ if (_angles.contains(angle)) {
+ result.expandTo(mid + r);
+ }
+ if (_angles.contains(angle + M_PI)) {
+ result.expandTo(mid - r);
+ }
+
+ return result;
+ };
+
+ return { proj_bounds(X), proj_bounds(Y) };
+}
+
+void EllipticalArc::expandToTransformed(Rect &bbox, Affine const &transform) const
+{
+ bbox.expandTo(_final_point * transform);
+
+ if (isChord() || bbox.contains(_ellipse.boundsFast())) {
+ return;
+ }
+
+ auto const trans = unitCircleTransform() * transform;
+
+ for (auto d : { X, Y }) {
+ // See boundsExact() for explanation.
+ auto const v = Point(trans[d], trans[d + 2]);
+ auto const r = v.length();
+ auto const mid = trans[d + 4];
+
+ if (_angles.isFull()) {
+ bbox[d].unionWith(Interval(mid - r, mid + r));
+ } else {
+ auto const angle = Angle(v);
+ if (_angles.contains(angle)) {
+ bbox[d].expandTo(mid + r);
+ }
+ if (_angles.contains(angle + M_PI)) {
+ bbox[d].expandTo(mid - r);
+ }
+ }
+ }
+}
+
+Point EllipticalArc::pointAtAngle(Coord t) const
+{
+ Point ret = _ellipse.pointAt(t);
+ return ret;
+}
+
+Coord EllipticalArc::valueAtAngle(Coord t, Dim2 d) const
+{
+ return _ellipse.valueAt(t, d);
+}
+
+std::vector<Coord> EllipticalArc::roots(Coord v, Dim2 d) const
+{
+ std::vector<Coord> sol;
+
+ if (isChord()) {
+ sol = chord().roots(v, d);
+ return sol;
+ }
+
+ Interval unit_interval(0, 1);
+
+ double rotx, roty;
+ if (d == X) {
+ sincos(rotationAngle(), roty, rotx);
+ roty = -roty;
+ } else {
+ sincos(rotationAngle(), rotx, roty);
+ }
+
+ double rxrotx = ray(X) * rotx;
+ double c_v = center(d) - v;
+
+ double a = -rxrotx + c_v;
+ double b = ray(Y) * roty;
+ double c = rxrotx + c_v;
+ //std::cerr << "a = " << a << std::endl;
+ //std::cerr << "b = " << b << std::endl;
+ //std::cerr << "c = " << c << std::endl;
+
+ if (a == 0)
+ {
+ sol.push_back(M_PI);
+ if (b != 0)
+ {
+ double s = 2 * std::atan(-c/(2*b));
+ if ( s < 0 ) s += 2*M_PI;
+ sol.push_back(s);
+ }
+ }
+ else
+ {
+ double delta = b * b - a * c;
+ //std::cerr << "delta = " << delta << std::endl;
+ if (delta == 0) {
+ double s = 2 * std::atan(-b/a);
+ if ( s < 0 ) s += 2*M_PI;
+ sol.push_back(s);
+ }
+ else if ( delta > 0 )
+ {
+ double sq = std::sqrt(delta);
+ double s = 2 * std::atan( (-b - sq) / a );
+ if ( s < 0 ) s += 2*M_PI;
+ sol.push_back(s);
+ s = 2 * std::atan( (-b + sq) / a );
+ if ( s < 0 ) s += 2*M_PI;
+ sol.push_back(s);
+ }
+ }
+
+ std::vector<double> arc_sol;
+ for (double & i : sol) {
+ //std::cerr << "s = " << deg_from_rad(sol[i]);
+ i = timeAtAngle(i);
+ //std::cerr << " -> t: " << sol[i] << std::endl;
+ if (unit_interval.contains(i)) {
+ arc_sol.push_back(i);
+ }
+ }
+ return arc_sol;
+}
+
+
+// D(E(t,C),t) = E(t+PI/2,O), where C is the ellipse center
+// the derivative doesn't rotate the ellipse but there is a translation
+// of the parameter t by an angle of PI/2 so the ellipse points are shifted
+// of such an angle in the cw direction
+Curve *EllipticalArc::derivative() const
+{
+ if (isChord()) {
+ return chord().derivative();
+ }
+
+ EllipticalArc *result = static_cast<EllipticalArc*>(duplicate());
+ result->_ellipse.setCenter(0, 0);
+ result->_angles.setInitial(result->_angles.initialAngle() + M_PI/2);
+ result->_angles.setFinal(result->_angles.finalAngle() + M_PI/2);
+ result->_initial_point = result->pointAtAngle( result->initialAngle() );
+ result->_final_point = result->pointAtAngle( result->finalAngle() );
+ return result;
+}
+
+
+std::vector<Point>
+EllipticalArc::pointAndDerivatives(Coord t, unsigned int n) const
+{
+ if (isChord()) {
+ return chord().pointAndDerivatives(t, n);
+ }
+
+ unsigned int nn = n+1; // nn represents the size of the result vector.
+ std::vector<Point> result;
+ result.reserve(nn);
+ double angle = angleAt(t);
+ std::unique_ptr<EllipticalArc> ea( static_cast<EllipticalArc*>(duplicate()) );
+ ea->_ellipse.setCenter(0, 0);
+ unsigned int m = std::min(nn, 4u);
+ for ( unsigned int i = 0; i < m; ++i )
+ {
+ result.push_back( ea->pointAtAngle(angle) );
+ angle += (sweep() ? M_PI/2 : -M_PI/2);
+ if ( !(angle < 2*M_PI) ) angle -= 2*M_PI;
+ }
+ m = nn / 4;
+ for ( unsigned int i = 1; i < m; ++i )
+ {
+ for ( unsigned int j = 0; j < 4; ++j )
+ result.push_back( result[j] );
+ }
+ m = nn - 4 * m;
+ for ( unsigned int i = 0; i < m; ++i )
+ {
+ result.push_back( result[i] );
+ }
+ if ( !result.empty() ) // nn != 0
+ result[0] = pointAtAngle(angle);
+ return result;
+}
+
+Point EllipticalArc::pointAt(Coord t) const
+{
+ if (t == 0.0) {
+ return initialPoint();
+ }
+ if (t == 1.0) {
+ return finalPoint();
+ }
+ if (isChord()) {
+ return chord().pointAt(t);
+ }
+ return _ellipse.pointAt(angleAt(t));
+}
+
+Coord EllipticalArc::valueAt(Coord t, Dim2 d) const
+{
+ if (isChord()) return chord().valueAt(t, d);
+ return valueAtAngle(angleAt(t), d);
+}
+
+Curve* EllipticalArc::portion(double f, double t) const
+{
+ // fix input arguments
+ f = std::clamp(f, 0.0, 1.0);
+ t = std::clamp(t, 0.0, 1.0);
+
+ if (f == t) {
+ EllipticalArc *arc = new EllipticalArc();
+ arc->_initial_point = arc->_final_point = pointAt(f);
+ return arc;
+ }
+ if (f == 0.0 && t == 1.0) {
+ return duplicate();
+ }
+ if (f == 1.0 && t == 0.0) {
+ return reverse();
+ }
+
+ EllipticalArc *arc = static_cast<EllipticalArc*>(duplicate());
+ arc->_initial_point = pointAt(f);
+ arc->_final_point = pointAt(t);
+ arc->_angles.setAngles(angleAt(f), angleAt(t));
+ if (f > t) arc->_angles.setSweep(!sweep());
+ if ( _large_arc && fabs(angularExtent() * (t-f)) <= M_PI) {
+ arc->_large_arc = false;
+ }
+ return arc;
+}
+
+// the arc is the same but traversed in the opposite direction
+Curve *EllipticalArc::reverse() const
+{
+ using std::swap;
+ EllipticalArc *rarc = static_cast<EllipticalArc*>(duplicate());
+ rarc->_angles.reverse();
+ swap(rarc->_initial_point, rarc->_final_point);
+ return rarc;
+}
+
+#ifdef HAVE_GSL // GSL is required for function "solve_reals"
+std::vector<double> EllipticalArc::allNearestTimes( Point const& p, double from, double to ) const
+{
+ std::vector<double> result;
+
+ if ( from > to ) std::swap(from, to);
+ if ( from < 0 || to > 1 )
+ {
+ THROW_RANGEERROR("[from,to] interval out of range");
+ }
+
+ if ( ( are_near(ray(X), 0) && are_near(ray(Y), 0) ) || are_near(from, to) )
+ {
+ result.push_back(from);
+ return result;
+ }
+ else if ( are_near(ray(X), 0) || are_near(ray(Y), 0) )
+ {
+ LineSegment seg(pointAt(from), pointAt(to));
+ Point np = seg.pointAt( seg.nearestTime(p) );
+ if ( are_near(ray(Y), 0) )
+ {
+ if ( are_near(rotationAngle(), M_PI/2)
+ || are_near(rotationAngle(), 3*M_PI/2) )
+ {
+ result = roots(np[Y], Y);
+ }
+ else
+ {
+ result = roots(np[X], X);
+ }
+ }
+ else
+ {
+ if ( are_near(rotationAngle(), M_PI/2)
+ || are_near(rotationAngle(), 3*M_PI/2) )
+ {
+ result = roots(np[X], X);
+ }
+ else
+ {
+ result = roots(np[Y], Y);
+ }
+ }
+ return result;
+ }
+ else if ( are_near(ray(X), ray(Y)) )
+ {
+ Point r = p - center();
+ if ( are_near(r, Point(0,0)) )
+ {
+ THROW_INFINITESOLUTIONS(0);
+ }
+ // TODO: implement case r != 0
+// Point np = ray(X) * unit_vector(r);
+// std::vector<double> solX = roots(np[X],X);
+// std::vector<double> solY = roots(np[Y],Y);
+// double t;
+// if ( are_near(solX[0], solY[0]) || are_near(solX[0], solY[1]))
+// {
+// t = solX[0];
+// }
+// else
+// {
+// t = solX[1];
+// }
+// if ( !(t < from || t > to) )
+// {
+// result.push_back(t);
+// }
+// else
+// {
+//
+// }
+ }
+
+ // solve the equation <D(E(t),t)|E(t)-p> == 0
+ // that provides min and max distance points
+ // on the ellipse E wrt the point p
+ // after the substitutions:
+ // cos(t) = (1 - s^2) / (1 + s^2)
+ // sin(t) = 2t / (1 + s^2)
+ // where s = tan(t/2)
+ // we get a 4th degree equation in s
+ /*
+ * ry s^4 ((-cy + py) Cos[Phi] + (cx - px) Sin[Phi]) +
+ * ry ((cy - py) Cos[Phi] + (-cx + px) Sin[Phi]) +
+ * 2 s^3 (rx^2 - ry^2 + (-cx + px) rx Cos[Phi] + (-cy + py) rx Sin[Phi]) +
+ * 2 s (-rx^2 + ry^2 + (-cx + px) rx Cos[Phi] + (-cy + py) rx Sin[Phi])
+ */
+
+ Point p_c = p - center();
+ double rx2_ry2 = (ray(X) - ray(Y)) * (ray(X) + ray(Y));
+ double sinrot, cosrot;
+ sincos(rotationAngle(), sinrot, cosrot);
+ double expr1 = ray(X) * (p_c[X] * cosrot + p_c[Y] * sinrot);
+ Poly coeff;
+ coeff.resize(5);
+ coeff[4] = ray(Y) * ( p_c[Y] * cosrot - p_c[X] * sinrot );
+ coeff[3] = 2 * ( rx2_ry2 + expr1 );
+ coeff[2] = 0;
+ coeff[1] = 2 * ( -rx2_ry2 + expr1 );
+ coeff[0] = -coeff[4];
+
+// for ( unsigned int i = 0; i < 5; ++i )
+// std::cerr << "c[" << i << "] = " << coeff[i] << std::endl;
+
+ std::vector<double> real_sol;
+ // gsl_poly_complex_solve raises an error
+ // if the leading coefficient is zero
+ if ( are_near(coeff[4], 0) )
+ {
+ real_sol.push_back(0);
+ if ( !are_near(coeff[3], 0) )
+ {
+ double sq = -coeff[1] / coeff[3];
+ if ( sq > 0 )
+ {
+ double s = std::sqrt(sq);
+ real_sol.push_back(s);
+ real_sol.push_back(-s);
+ }
+ }
+ }
+ else
+ {
+ real_sol = solve_reals(coeff);
+ }
+
+ for (double & i : real_sol)
+ {
+ i = 2 * std::atan(i);
+ if ( i < 0 ) i += 2*M_PI;
+ }
+ // when s -> Infinity then <D(E)|E-p> -> 0 iff coeff[4] == 0
+ // so we add M_PI to the solutions being lim arctan(s) = PI when s->Infinity
+ if ( (real_sol.size() % 2) != 0 )
+ {
+ real_sol.push_back(M_PI);
+ }
+
+ double mindistsq1 = std::numeric_limits<double>::max();
+ double mindistsq2 = std::numeric_limits<double>::max();
+ double dsq = 0;
+ unsigned int mi1 = 0, mi2 = 0;
+ for ( unsigned int i = 0; i < real_sol.size(); ++i )
+ {
+ dsq = distanceSq(p, pointAtAngle(real_sol[i]));
+ if ( mindistsq1 > dsq )
+ {
+ mindistsq2 = mindistsq1;
+ mi2 = mi1;
+ mindistsq1 = dsq;
+ mi1 = i;
+ }
+ else if ( mindistsq2 > dsq )
+ {
+ mindistsq2 = dsq;
+ mi2 = i;
+ }
+ }
+
+ double t = timeAtAngle(real_sol[mi1]);
+ if ( !(t < from || t > to) )
+ {
+ result.push_back(t);
+ }
+
+ bool second_sol = false;
+ t = timeAtAngle(real_sol[mi2]);
+ if ( real_sol.size() == 4 && !(t < from || t > to) )
+ {
+ if ( result.empty() || are_near(mindistsq1, mindistsq2) )
+ {
+ result.push_back(t);
+ second_sol = true;
+ }
+ }
+
+ // we need to test extreme points too
+ double dsq1 = distanceSq(p, pointAt(from));
+ double dsq2 = distanceSq(p, pointAt(to));
+ if ( second_sol )
+ {
+ if ( mindistsq2 > dsq1 )
+ {
+ result.clear();
+ result.push_back(from);
+ mindistsq2 = dsq1;
+ }
+ else if ( are_near(mindistsq2, dsq) )
+ {
+ result.push_back(from);
+ }
+ if ( mindistsq2 > dsq2 )
+ {
+ result.clear();
+ result.push_back(to);
+ }
+ else if ( are_near(mindistsq2, dsq2) )
+ {
+ result.push_back(to);
+ }
+
+ }
+ else
+ {
+ if ( result.empty() )
+ {
+ if ( are_near(dsq1, dsq2) )
+ {
+ result.push_back(from);
+ result.push_back(to);
+ }
+ else if ( dsq2 > dsq1 )
+ {
+ result.push_back(from);
+ }
+ else
+ {
+ result.push_back(to);
+ }
+ }
+ }
+
+ return result;
+}
+#endif
+
+/** @brief Convert the passed intersections to curve time parametrization
+ * and filter out any invalid intersections.
+ */
+std::vector<ShapeIntersection> EllipticalArc::_filterIntersections(std::vector<ShapeIntersection> &&xs,
+ bool is_first) const
+{
+ std::vector<ShapeIntersection> result;
+ result.reserve(xs.size());
+ for (auto &xing : xs) {
+ if (_validateIntersection(xing, is_first)) {
+ result.emplace_back(std::move(xing));
+ }
+ }
+ return result;
+}
+
+/** @brief Convert the passed intersection to curve time and check whether the intersection
+ * is numerically sane.
+ *
+ * @param xing The intersection to convert to curve time and to validate.
+ * @param is_first If true, this arc is the first of the intersected curves; if false, it's second.
+ * @return Whether the intersection is valid.
+ *
+ * Note that the intersection is guaranteed to be converted only if the return value is true.
+ */
+bool EllipticalArc::_validateIntersection(ShapeIntersection &xing, bool is_first) const
+{
+ static auto const UNIT_INTERVAL = Interval(0, 1);
+ constexpr auto EPS = 1e-4;
+
+ Coord &t = is_first ? xing.first : xing.second;
+ if (!are_near_rel(_ellipse.pointAt(t), xing.point(), EPS)) {
+ return false;
+ }
+
+ t = timeAtAngle(t);
+ if (!UNIT_INTERVAL.contains(t)) {
+ return false;
+ }
+ if (!are_near_rel(pointAt(t), xing.point(), EPS)) {
+ return false;
+ }
+ return true;
+}
+
+std::vector<CurveIntersection> EllipticalArc::intersect(Curve const &other, Coord eps) const
+{
+ if (isLineSegment()) {
+ LineSegment ls(_initial_point, _final_point);
+ return ls.intersect(other, eps);
+ }
+
+ if (other.isLineSegment()) {
+ LineSegment ls(other.initialPoint(), other.finalPoint());
+ return _filterIntersections(_ellipse.intersect(ls), true);
+ }
+
+ if (auto bez = dynamic_cast<BezierCurve const *>(&other)) {
+ return _filterIntersections(_ellipse.intersect(bez->fragment()), true);
+ }
+
+ if (auto arc = dynamic_cast<EllipticalArc const *>(&other)) {
+ std::vector<CurveIntersection> crossings;
+ try {
+ crossings = _ellipse.intersect(arc->_ellipse);
+ } catch (InfinitelyManySolutions &) {
+ // This could happen if the two arcs come from the same ellipse.
+ return _intersectSameEllipse(arc);
+ }
+ return arc->_filterIntersections(_filterIntersections(std::move(crossings), true), false);
+ }
+
+ // in case someone wants to make a custom curve type
+ auto result = other.intersect(*this, eps);
+ transpose_in_place(result);
+ return result;
+}
+
+/** @brief Check if two arcs on the same ellipse intersect/overlap.
+ *
+ * @param other Another elliptical arc on the same ellipse as this one.
+ * @return If the arcs overlap, the returned vector contains synthesized intersections
+ * at the start and end of the overlap.
+ * If the arcs do not overlap, an empty vector is returned.
+ */
+std::vector<ShapeIntersection> EllipticalArc::_intersectSameEllipse(EllipticalArc const *other) const
+{
+ assert(_ellipse == other->_ellipse);
+ auto const &other_angles = other->angularInterval();
+ std::vector<ShapeIntersection> result;
+
+ /// A closure to create an "intersection" at the prescribed angle.
+ auto const synthesize_intersection = [&](Angle angle) {
+ auto const time = timeAtAngle(angle);
+ if (result.end() == std::find_if(result.begin(), result.end(),
+ [=](ShapeIntersection const &xing) -> bool {
+ return xing.first == time;
+ }))
+ {
+ result.emplace_back(time, other->timeAtAngle(angle), _ellipse.pointAt(angle));
+ }
+ };
+
+ for (auto a : {_angles.initialAngle(), _angles.finalAngle()}) {
+ if (other_angles.contains(a)) {
+ synthesize_intersection(a);
+ }
+ }
+ for (auto a : {other_angles.initialAngle(), other_angles.finalAngle()}) {
+ if (_angles.contains(a)) {
+ synthesize_intersection(a);
+ }
+ }
+ return result;
+}
+
+void EllipticalArc::_updateCenterAndAngles()
+{
+ // See: http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
+ Point d = initialPoint() - finalPoint();
+ Point mid = middle_point(initialPoint(), finalPoint());
+
+ auto degenerate_ellipse = [&] {
+ _ellipse = Ellipse();
+ _ellipse.setCenter(initialPoint());
+ _angles = AngleInterval();
+ _large_arc = false;
+ };
+
+ // if ip = fp, the arc contains no other points
+ if (initialPoint() == finalPoint()) {
+ degenerate_ellipse();
+ return;
+ }
+
+ // rays should be positive
+ _ellipse.setRays(std::fabs(ray(X)), std::fabs(ray(Y)));
+
+ if (isChord()) {
+ _ellipse.setRays(L2(d) / 2, 0);
+ _ellipse.setRotationAngle(atan2(d));
+ _ellipse.setCenter(mid);
+ _angles.setAngles(0, M_PI);
+ _angles.setSweep(false);
+ _large_arc = false;
+ return;
+ }
+
+ Rotate rot(rotationAngle()); // the matrix in F.6.5.3
+ Rotate invrot = rot.inverse(); // the matrix in F.6.5.1
+
+ Point r = rays();
+ Point p = d / 2 * invrot; // x', y' in F.6.5.1
+ Point c(0,0); // cx', cy' in F.6.5.2
+
+ // Correct out-of-range radii
+ Coord lambda = hypot(p[X]/r[X], p[Y]/r[Y]);
+ if (lambda > 1) {
+ r *= lambda;
+ _ellipse.setRays(r);
+ _ellipse.setCenter(mid);
+ } else {
+ // evaluate F.6.5.2
+ Coord rxry = r[X]*r[X] * r[Y]*r[Y];
+ Coord pxry = p[X]*p[X] * r[Y]*r[Y];
+ Coord rxpy = r[X]*r[X] * p[Y]*p[Y];
+ Coord const denominator = rxpy + pxry;
+ if (denominator == 0.0) {
+ degenerate_ellipse();
+ return;
+ }
+ Coord rad = (rxry - pxry - rxpy) / denominator;
+ // normally rad should never be negative, but numerical inaccuracy may cause this
+ if (rad > 0) {
+ rad = std::sqrt(rad);
+ if (sweep() == _large_arc) {
+ rad = -rad;
+ }
+ c = rad * Point(r[X]*p[Y]/r[Y], -r[Y]*p[X]/r[X]);
+ _ellipse.setCenter(c * rot + mid);
+ } else {
+ _ellipse.setCenter(mid);
+ }
+ }
+
+ // Compute start and end angles.
+ // If the ellipse was enlarged, c will be zero - this is correct.
+ Point sp((p[X] - c[X]) / r[X], (p[Y] - c[Y]) / r[Y]);
+ Point ep((-p[X] - c[X]) / r[X], (-p[Y] - c[Y]) / r[Y]);
+ Point v(1, 0);
+
+ _angles.setInitial(angle_between(v, sp));
+ _angles.setFinal(angle_between(v, ep));
+
+ /*double sweep_angle = angle_between(sp, ep);
+ if (!sweep() && sweep_angle > 0) sweep_angle -= 2*M_PI;
+ if (sweep() && sweep_angle < 0) sweep_angle += 2*M_PI;*/
+}
+
+D2<SBasis> EllipticalArc::toSBasis() const
+{
+ if (isChord()) {
+ return chord().toSBasis();
+ }
+
+ D2<SBasis> arc;
+ // the interval of parametrization has to be [0,1]
+ Coord et = initialAngle().radians() + sweepAngle();
+ Linear param(initialAngle().radians(), et);
+ Coord cosrot, sinrot;
+ sincos(rotationAngle(), sinrot, cosrot);
+
+ // order = 4 seems to be enough to get a perfect looking elliptical arc
+ SBasis arc_x = ray(X) * cos(param,4);
+ SBasis arc_y = ray(Y) * sin(param,4);
+ arc[0] = arc_x * cosrot - arc_y * sinrot + Linear(center(X), center(X));
+ arc[1] = arc_x * sinrot + arc_y * cosrot + Linear(center(Y), center(Y));
+
+ // ensure that endpoints remain exact
+ for ( int d = 0 ; d < 2 ; d++ ) {
+ arc[d][0][0] = initialPoint()[d];
+ arc[d][0][1] = finalPoint()[d];
+ }
+
+ return arc;
+}
+
+// All operations that do not contain skew can be evaluated
+// without passing through the implicit form of the ellipse,
+// which preserves precision.
+
+void EllipticalArc::operator*=(Translate const &tr)
+{
+ _initial_point *= tr;
+ _final_point *= tr;
+ _ellipse *= tr;
+}
+
+void EllipticalArc::operator*=(Scale const &s)
+{
+ _initial_point *= s;
+ _final_point *= s;
+ _ellipse *= s;
+}
+
+void EllipticalArc::operator*=(Rotate const &r)
+{
+ _initial_point *= r;
+ _final_point *= r;
+ _ellipse *= r;
+}
+
+void EllipticalArc::operator*=(Zoom const &z)
+{
+ _initial_point *= z;
+ _final_point *= z;
+ _ellipse *= z;
+}
+
+void EllipticalArc::operator*=(Affine const& m)
+{
+ if (isChord()) {
+ _initial_point *= m;
+ _final_point *= m;
+ _ellipse.setCenter(middle_point(_initial_point, _final_point));
+ _ellipse.setRays(0, 0);
+ _ellipse.setRotationAngle(0);
+ return;
+ }
+
+ _initial_point *= m;
+ _final_point *= m;
+ _ellipse *= m;
+ if (m.det() < 0) {
+ _angles.setSweep(!sweep());
+ }
+
+ // ellipse transformation does not preserve its functional form,
+ // i.e. e.pointAt(0.5)*m and (e*m).pointAt(0.5) can be different.
+ // We need to recompute start / end angles.
+ _angles.setInitial(_ellipse.timeAt(_initial_point));
+ _angles.setFinal(_ellipse.timeAt(_final_point));
+}
+
+bool EllipticalArc::operator==(Curve const &c) const
+{
+ EllipticalArc const *other = dynamic_cast<EllipticalArc const *>(&c);
+ if (!other) return false;
+ if (_initial_point != other->_initial_point) return false;
+ if (_final_point != other->_final_point) return false;
+ // TODO: all arcs with ellipse rays which are too small
+ // and fall back to a line should probably be equal
+ if (rays() != other->rays()) return false;
+ if (rotationAngle() != other->rotationAngle()) return false;
+ if (_large_arc != other->_large_arc) return false;
+ if (sweep() != other->sweep()) return false;
+ return true;
+}
+
+bool EllipticalArc::isNear(Curve const &c, Coord precision) const
+{
+ EllipticalArc const *other = dynamic_cast<EllipticalArc const *>(&c);
+ if (!other) {
+ if (isChord()) {
+ return c.isNear(chord(), precision);
+ }
+ return false;
+ }
+
+ if (!are_near(_initial_point, other->_initial_point, precision)) return false;
+ if (!are_near(_final_point, other->_final_point, precision)) return false;
+ if (isChord() && other->isChord()) return true;
+
+ if (sweep() != other->sweep()) return false;
+ if (!are_near(_ellipse, other->_ellipse, precision)) return false;
+ return true;
+}
+
+void EllipticalArc::feed(PathSink &sink, bool moveto_initial) const
+{
+ if (moveto_initial) {
+ sink.moveTo(_initial_point);
+ }
+ sink.arcTo(ray(X), ray(Y), rotationAngle(), _large_arc, sweep(), _final_point);
+}
+
+int EllipticalArc::winding(Point const &p) const
+{
+ using std::swap;
+
+ double sinrot, cosrot;
+ sincos(rotationAngle(), sinrot, cosrot);
+
+ Angle ymin_a = std::atan2( ray(Y) * cosrot, ray(X) * sinrot );
+ Angle ymax_a = ymin_a + M_PI;
+
+ Point ymin = pointAtAngle(ymin_a);
+ Point ymax = pointAtAngle(ymax_a);
+ if (ymin[Y] > ymax[Y]) {
+ swap(ymin, ymax);
+ swap(ymin_a, ymax_a);
+ }
+
+ if (!Interval(ymin[Y], ymax[Y]).lowerContains(p[Y])) {
+ return 0;
+ }
+
+ bool const left = cross(ymax - ymin, p - ymin) > 0;
+ bool const inside = _ellipse.contains(p);
+ if (_angles.isFull()) {
+ if (inside) {
+ return sweep() ? 1 : -1;
+ }
+ return 0;
+ }
+ bool const includes_ymin = _angles.contains(ymin_a);
+ bool const includes_ymax = _angles.contains(ymax_a);
+
+ AngleInterval rarc(ymin_a, ymax_a, true),
+ larc(ymax_a, ymin_a, true);
+
+ // we'll compute the result for an arc in the direction of increasing angles
+ // and then negate if necessary
+ Angle ia = initialAngle(), fa = finalAngle();
+ Point ip = _initial_point, fp = _final_point;
+ if (!sweep()) {
+ swap(ia, fa);
+ swap(ip, fp);
+ }
+
+ bool const initial_left = larc.contains(ia);
+ bool const final_left = larc.contains(fa);
+
+ bool intersects_left = false, intersects_right = false;
+ if (inside || left) {
+ // The point is inside the ellipse or to the left of it, so the rightwards horizontal ray
+ // may intersect the part of the arc contained in the right half of the ellipse.
+ // There are four ways in which this can happen.
+
+ intersects_right =
+ // Possiblity 1: the arc extends into the right half through the min-Y point
+ // and the ray intersects this extension:
+ (includes_ymin && !final_left && Interval(ymin[Y], fp[Y]).lowerContains(p[Y]))
+ ||
+ // Possibility 2: the arc starts and ends within the right half (hence, it cannot be the
+ // "large arc") and the ray's Y-coordinate is within the Y-coordinate range of the arc:
+ (!initial_left && !final_left && !largeArc() && Interval(ip[Y], fp[Y]).lowerContains(p[Y]))
+ ||
+ // Possibility 3: the arc starts in the right half and continues through the max-Y
+ // point into the left half:
+ (!initial_left && includes_ymax && Interval(ip[Y], ymax[Y]).lowerContains(p[Y]))
+ ||
+ // Possibility 4: the entire right half of the ellipse is contained in the arc.
+ (initial_left && final_left && includes_ymin && includes_ymax);
+ }
+ if (left && !inside) {
+ // The point is to the left of the ellipse, so the rightwards horizontal ray
+ // may intersect the part of the arc contained in the left half of the ellipse.
+ // There are four ways in which this can happen.
+
+ intersects_left =
+ // Possibility 1: the arc starts in the left half and continues through the min-Y
+ // point into the right half:
+ (includes_ymin && initial_left && Interval(ymin[Y], ip[Y]).lowerContains(p[Y]))
+ ||
+ // Possibility 2: the arc starts and ends within the left half (hence, it cannot be the
+ // "large arc") and the ray's Y-coordinate is within the Y-coordinate range of the arc:
+ (initial_left && final_left && !largeArc() && Interval(ip[Y], fp[Y]).lowerContains(p[Y]))
+ ||
+ // Possibility 3: the arc extends into the left half through the max-Y point
+ // and the ray intersects this extension:
+ (final_left && includes_ymax && Interval(fp[Y], ymax[Y]).lowerContains(p[Y]))
+ ||
+ // Possibility 4: the entire left half of the ellipse is contained in the arc.
+ (!initial_left && !final_left && includes_ymin && includes_ymax);
+
+ }
+ int const winding_assuming_increasing_angles = (int)intersects_right - (int)intersects_left;
+ return sweep() ? winding_assuming_increasing_angles : -winding_assuming_increasing_angles;
+}
+
+std::ostream &operator<<(std::ostream &out, EllipticalArc const &ea)
+{
+ out << "EllipticalArc("
+ << ea.initialPoint() << ", "
+ << format_coord_nice(ea.ray(X)) << ", " << format_coord_nice(ea.ray(Y)) << ", "
+ << format_coord_nice(ea.rotationAngle()) << ", "
+ << "large_arc=" << (ea.largeArc() ? "true" : "false") << ", "
+ << "sweep=" << (ea.sweep() ? "true" : "false") << ", "
+ << ea.finalPoint() << ")";
+ return out;
+}
+
+} // end namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+
diff --git a/src/3rdparty/2geom/src/2geom/geom.cpp b/src/3rdparty/2geom/src/2geom/geom.cpp
new file mode 100644
index 0000000..791e3a6
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/geom.cpp
@@ -0,0 +1,396 @@
+/**
+ * \brief Various geometrical calculations.
+ */
+
+#include <2geom/geom.h>
+#include <2geom/point.h>
+#include <algorithm>
+#include <optional>
+#include <2geom/rect.h>
+
+using std::swap;
+
+namespace Geom {
+
+enum IntersectorKind {
+ intersects = 0,
+ parallel,
+ coincident,
+ no_intersection
+};
+
+/**
+ * Finds the intersection of the two (infinite) lines
+ * defined by the points p such that dot(n0, p) == d0 and dot(n1, p) == d1.
+ *
+ * If the two lines intersect, then \a result becomes their point of
+ * intersection; otherwise, \a result remains unchanged.
+ *
+ * This function finds the intersection of the two lines (infinite)
+ * defined by n0.X = d0 and x1.X = d1. The algorithm is as follows:
+ * To compute the intersection point use kramer's rule:
+ * \verbatim
+ * convert lines to form
+ * ax + by = c
+ * dx + ey = f
+ *
+ * (
+ * e.g. a = (x2 - x1), b = (y2 - y1), c = (x2 - x1)*x1 + (y2 - y1)*y1
+ * )
+ *
+ * In our case we use:
+ * a = n0.x d = n1.x
+ * b = n0.y e = n1.y
+ * c = d0 f = d1
+ *
+ * so:
+ *
+ * adx + bdy = cd
+ * adx + aey = af
+ *
+ * bdy - aey = cd - af
+ * (bd - ae)y = cd - af
+ *
+ * y = (cd - af)/(bd - ae)
+ *
+ * repeat for x and you get:
+ *
+ * x = (fb - ce)/(bd - ae) \endverbatim
+ *
+ * If the denominator (bd-ae) is 0 then the lines are parallel, if the
+ * numerators are 0 then the lines coincide.
+ *
+ * \todo Why not use existing but outcommented code below
+ * (HAVE_NEW_INTERSECTOR_CODE)?
+ */
+IntersectorKind
+line_intersection(Geom::Point const &n0, double const d0,
+ Geom::Point const &n1, double const d1,
+ Geom::Point &result)
+{
+ double denominator = dot(Geom::rot90(n0), n1);
+ double X = n1[Geom::Y] * d0 -
+ n0[Geom::Y] * d1;
+ /* X = (-d1, d0) dot (n0[Y], n1[Y]) */
+
+ if (denominator == 0) {
+ if ( X == 0 ) {
+ return coincident;
+ } else {
+ return parallel;
+ }
+ }
+
+ double Y = n0[Geom::X] * d1 -
+ n1[Geom::X] * d0;
+
+ result = Geom::Point(X, Y) / denominator;
+
+ return intersects;
+}
+
+
+
+/* ccw exists as a building block */
+int
+intersector_ccw(const Geom::Point& p0, const Geom::Point& p1,
+ const Geom::Point& p2)
+/* Determine which way a set of three points winds. */
+{
+ Geom::Point d1 = p1 - p0;
+ Geom::Point d2 = p2 - p0;
+ /* compare slopes but avoid division operation */
+ double c = dot(Geom::rot90(d1), d2);
+ if(c > 0)
+ return +1; // ccw - do these match def'n in header?
+ if(c < 0)
+ return -1; // cw
+
+ /* Colinear [or NaN]. Decide the order. */
+ if ( ( d1[0] * d2[0] < 0 ) ||
+ ( d1[1] * d2[1] < 0 ) ) {
+ return -1; // p2 < p0 < p1
+ } else if ( dot(d1,d1) < dot(d2,d2) ) {
+ return +1; // p0 <= p1 < p2
+ } else {
+ return 0; // p0 <= p2 <= p1
+ }
+}
+
+/** Determine whether the line segment from p00 to p01 intersects the
+ infinite line passing through p10 and p11. This doesn't find the
+ point of intersection, use the line_intersect function above,
+ or the segment_intersection interface below.
+
+ \pre neither segment is zero-length; i.e. p00 != p01 and p10 != p11.
+*/
+bool
+line_segment_intersectp(Geom::Point const &p00, Geom::Point const &p01,
+ Geom::Point const &p10, Geom::Point const &p11)
+{
+ if(p00 == p01) return false;
+ if(p10 == p11) return false;
+
+ return ((intersector_ccw(p00, p01, p10) * intersector_ccw(p00, p01, p11)) <= 0 );
+}
+
+
+/** Determine whether two line segments intersect. This doesn't find
+ the point of intersection, use the line_intersect function above,
+ or the segment_intersection interface below.
+
+ \pre neither segment is zero-length; i.e. p00 != p01 and p10 != p11.
+*/
+bool
+segment_intersectp(Geom::Point const &p00, Geom::Point const &p01,
+ Geom::Point const &p10, Geom::Point const &p11)
+{
+ if(p00 == p01) return false;
+ if(p10 == p11) return false;
+
+ /* true iff ( (the p1 segment straddles the p0 infinite line)
+ * and (the p0 segment straddles the p1 infinite line) ). */
+ return (line_segment_intersectp(p00, p01, p10, p11) &&
+ line_segment_intersectp(p10, p11, p00, p01));
+}
+
+/** Determine whether \& where a line segments intersects an (infinite) line.
+
+If there is no intersection, then \a result remains unchanged.
+
+\pre neither segment is zero-length; i.e. p00 != p01 and p10 != p11.
+**/
+IntersectorKind
+line_segment_intersect(Geom::Point const &p00, Geom::Point const &p01,
+ Geom::Point const &p10, Geom::Point const &p11,
+ Geom::Point &result)
+{
+ if(line_segment_intersectp(p00, p01, p10, p11)) {
+ Geom::Point n0 = (p01 - p00).ccw();
+ double d0 = dot(n0,p00);
+
+ Geom::Point n1 = (p11 - p10).ccw();
+ double d1 = dot(n1,p10);
+ return line_intersection(n0, d0, n1, d1, result);
+ } else {
+ return no_intersection;
+ }
+}
+
+
+/** Determine whether \& where two line segments intersect.
+
+If the two segments don't intersect, then \a result remains unchanged.
+
+\pre neither segment is zero-length; i.e. p00 != p01 and p10 != p11.
+**/
+IntersectorKind
+segment_intersect(Geom::Point const &p00, Geom::Point const &p01,
+ Geom::Point const &p10, Geom::Point const &p11,
+ Geom::Point &result)
+{
+ if(segment_intersectp(p00, p01, p10, p11)) {
+ Geom::Point n0 = (p01 - p00).ccw();
+ double d0 = dot(n0,p00);
+
+ Geom::Point n1 = (p11 - p10).ccw();
+ double d1 = dot(n1,p10);
+ return line_intersection(n0, d0, n1, d1, result);
+ } else {
+ return no_intersection;
+ }
+}
+
+/** Determine whether \& where two line segments intersect.
+
+If the two segments don't intersect, then \a result remains unchanged.
+
+\pre neither segment is zero-length; i.e. p00 != p01 and p10 != p11.
+**/
+IntersectorKind
+line_twopoint_intersect(Geom::Point const &p00, Geom::Point const &p01,
+ Geom::Point const &p10, Geom::Point const &p11,
+ Geom::Point &result)
+{
+ Geom::Point n0 = (p01 - p00).ccw();
+ double d0 = dot(n0,p00);
+
+ Geom::Point n1 = (p11 - p10).ccw();
+ double d1 = dot(n1,p10);
+ return line_intersection(n0, d0, n1, d1, result);
+}
+
+// this is used to compare points for std::sort below
+static bool
+is_less(Point const &A, Point const &B)
+{
+ if (A[X] < B[X]) {
+ return true;
+ } else if (A[X] == B[X] && A[Y] < B[Y]) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+// TODO: this can doubtlessly be improved
+static void
+eliminate_duplicates_p(std::vector<Point> &pts)
+{
+ unsigned int size = pts.size();
+
+ if (size < 2)
+ return;
+
+ if (size == 2) {
+ if (pts[0] == pts[1]) {
+ pts.pop_back();
+ }
+ } else {
+ std::sort(pts.begin(), pts.end(), &is_less);
+ if (size == 3) {
+ if (pts[0] == pts[1]) {
+ pts.erase(pts.begin());
+ } else if (pts[1] == pts[2]) {
+ pts.pop_back();
+ }
+ } else {
+ // we have size == 4
+ if (pts[2] == pts[3]) {
+ pts.pop_back();
+ }
+ if (pts[0] == pts[1]) {
+ pts.erase(pts.begin());
+ }
+ }
+ }
+}
+
+/** Determine whether \& where an (infinite) line intersects a rectangle.
+ *
+ * \a c0, \a c1 are diagonal corners of the rectangle and
+ * \a p1, \a p1 are distinct points on the line
+ *
+ * \return A list (possibly empty) of points of intersection. If two such points (say \a r0 and \a
+ * r1) then it is guaranteed that the order of \a r0, \a r1 along the line is the same as the that
+ * of \a c0, \a c1 (i.e., the vectors \a r1 - \a r0 and \a p1 - \a p0 point into the same
+ * direction).
+ */
+std::vector<Geom::Point>
+rect_line_intersect(Geom::Point const &c0, Geom::Point const &c1,
+ Geom::Point const &p0, Geom::Point const &p1)
+{
+ using namespace Geom;
+
+ std::vector<Point> results;
+
+ Point A(c0);
+ Point C(c1);
+
+ Point B(A[X], C[Y]);
+ Point D(C[X], A[Y]);
+
+ Point res;
+
+ if (line_segment_intersect(p0, p1, A, B, res) == intersects) {
+ results.push_back(res);
+ }
+ if (line_segment_intersect(p0, p1, B, C, res) == intersects) {
+ results.push_back(res);
+ }
+ if (line_segment_intersect(p0, p1, C, D, res) == intersects) {
+ results.push_back(res);
+ }
+ if (line_segment_intersect(p0, p1, D, A, res) == intersects) {
+ results.push_back(res);
+ }
+
+ eliminate_duplicates_p(results);
+
+ if (results.size() == 2) {
+ // sort the results so that the order is the same as that of p0 and p1
+ Point dir1 (results[1] - results[0]);
+ Point dir2 (p1 - p0);
+ if (dot(dir1, dir2) < 0) {
+ swap(results[0], results[1]);
+ }
+ }
+
+ return results;
+}
+
+/** Determine whether \& where an (infinite) line intersects a rectangle.
+ *
+ * \a c0, \a c1 are diagonal corners of the rectangle and
+ * \a p1, \a p1 are distinct points on the line
+ *
+ * \return A list (possibly empty) of points of intersection. If two such points (say \a r0 and \a
+ * r1) then it is guaranteed that the order of \a r0, \a r1 along the line is the same as the that
+ * of \a c0, \a c1 (i.e., the vectors \a r1 - \a r0 and \a p1 - \a p0 point into the same
+ * direction).
+ */
+std::optional<LineSegment>
+rect_line_intersect(Geom::Rect &r,
+ Geom::LineSegment ls)
+{
+ std::vector<Point> results;
+
+ results = rect_line_intersect(r.min(), r.max(), ls[0], ls[1]);
+ if(results.size() == 2) {
+ return LineSegment(results[0], results[1]);
+ }
+ return std::optional<LineSegment>();
+}
+
+std::optional<LineSegment>
+rect_line_intersect(Geom::Rect &r,
+ Geom::Line l)
+{
+ return rect_line_intersect(r, l.segment(0, 1));
+}
+
+/**
+ * polyCentroid: Calculates the centroid (xCentroid, yCentroid) and area of a polygon, given its
+ * vertices (x[0], y[0]) ... (x[n-1], y[n-1]). It is assumed that the contour is closed, i.e., that
+ * the vertex following (x[n-1], y[n-1]) is (x[0], y[0]). The algebraic sign of the area is
+ * positive for counterclockwise ordering of vertices in x-y plane; otherwise negative.
+
+ * Returned values:
+ 0 for normal execution;
+ 1 if the polygon is degenerate (number of vertices < 3);
+ 2 if area = 0 (and the centroid is undefined).
+
+ * for now we require the path to be a polyline and assume it is closed.
+**/
+
+int centroid(std::vector<Geom::Point> const &p, Geom::Point& centroid, double &area) {
+ const unsigned n = p.size();
+ if (n < 3)
+ return 1;
+ Geom::Point centroid_tmp(0,0);
+ double atmp = 0;
+ for (unsigned i = n-1, j = 0; j < n; i = j, j++) {
+ const double ai = cross(p[j], p[i]);
+ atmp += ai;
+ centroid_tmp += (p[j] + p[i])*ai; // first moment.
+ }
+ area = atmp / 2;
+ if (atmp != 0) {
+ centroid = centroid_tmp / (3 * atmp);
+ return 0;
+ }
+ return 2;
+}
+
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/intersection-graph.cpp b/src/3rdparty/2geom/src/2geom/intersection-graph.cpp
new file mode 100644
index 0000000..524267e
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/intersection-graph.cpp
@@ -0,0 +1,535 @@
+/**
+ * \file
+ * \brief Intersection graph for Boolean operations
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/intersection-graph.h>
+#include <2geom/path.h>
+#include <2geom/pathvector.h>
+#include <2geom/utils.h>
+#include <iostream>
+#include <iterator>
+
+namespace Geom {
+
+/// Function object for comparing intersection vertices based on the intersection time.
+struct PathIntersectionGraph::IntersectionVertexLess {
+ bool operator()(IntersectionVertex const &a, IntersectionVertex const &b) const {
+ return a.pos < b.pos;
+ }
+};
+
+PathIntersectionGraph::PathIntersectionGraph(PathVector const &a, PathVector const &b, Coord precision)
+ : _graph_valid(true)
+{
+ _pv[0] = a;
+ _pv[1] = b;
+
+ if (a.empty() || b.empty()) return;
+
+ _prepareArguments();
+ bool has_intersections = _prepareIntersectionLists(precision);
+ if (!has_intersections) return;
+
+ _assignEdgeWindingParities(precision);
+
+ // If a path has only degenerate intersections, assign its status now.
+ // This protects against later accidentally picking a point for winding
+ // determination that is exactly at a removed intersection.
+ _assignComponentStatusFromDegenerateIntersections();
+ _removeDegenerateIntersections();
+ if (_graph_valid) {
+ _verify();
+ }
+}
+
+/** Prepare the operands stored in PathIntersectionGraph::_pv by closing all of their constituent
+ * paths and removing degenerate segments from them.
+ */
+void PathIntersectionGraph::_prepareArguments()
+{
+ // all paths must be closed, otherwise we will miss some intersections
+ for (auto & w : _pv) {
+ for (auto & i : w) {
+ i.close();
+ }
+ }
+ // remove degenerate segments
+ for (auto & w : _pv) {
+ for (std::size_t i = w.size(); i > 0; --i) {
+ if (w[i-1].empty()) {
+ w.erase(w.begin() + (i-1));
+ continue;
+ }
+ for (std::size_t j = w[i-1].size(); j > 0; --j) {
+ if (w[i-1][j-1].isDegenerate()) {
+ w[i-1].erase(w[i-1].begin() + (j-1));
+ }
+ }
+ }
+ }
+}
+
+/** @brief Compute the lists of intersections between the constituent paths of both operands.
+ * @param precision – the precision setting for the sweepline algorithm.
+ * @return Whether any intersections were found.
+ */
+bool PathIntersectionGraph::_prepareIntersectionLists(Coord precision)
+{
+ std::vector<PVIntersection> pxs = _pv[0].intersect(_pv[1], precision);
+ // NOTE: this early return means that the path data structures will not be created
+ // if there are no intersections at all!
+ if (pxs.empty()) return false;
+
+ // prepare intersection lists for each path component
+ for (unsigned w = 0; w < 2; ++w) {
+ for (std::size_t i = 0; i < _pv[w].size(); ++i) {
+ _components[w].push_back(new PathData(w, i));
+ }
+ }
+
+ // create intersection vertices
+ for (auto & px : pxs) {
+ IntersectionVertex *xa, *xb;
+ xa = new IntersectionVertex();
+ xb = new IntersectionVertex();
+ //xa->processed = xb->processed = false;
+ xa->which = 0; xb->which = 1;
+ xa->pos = px.first;
+ xb->pos = px.second;
+ xa->p = xb->p = px.point();
+ xa->neighbor = xb;
+ xb->neighbor = xa;
+ xa->next_edge = xb->next_edge = OUTSIDE;
+ xa->defective = xb->defective = false;
+ _xs.push_back(xa);
+ _xs.push_back(xb);
+ _components[0][xa->pos.path_index].xlist.push_back(*xa);
+ _components[1][xb->pos.path_index].xlist.push_back(*xb);
+ }
+
+ // sort intersections in each component according to time value
+ for (auto & _component : _components) {
+ for (std::size_t i = 0; i < _component.size(); ++i) {
+ _component[i].xlist.sort(IntersectionVertexLess());
+ }
+ }
+
+ return true;
+}
+
+/** Determine whether path portions between consecutive intersections lie inside or outside
+ * of the other path-vector.
+ */
+void PathIntersectionGraph::_assignEdgeWindingParities(Coord precision)
+{
+ for (unsigned w = 0; w < 2; ++w) {
+ unsigned ow = (w+1) % 2; ///< The index of the other operand
+
+ for (unsigned li = 0; li < _components[w].size(); ++li) { // Traverse all paths in the component
+ IntersectionList &xl = _components[w][li].xlist;
+ for (ILIter i = xl.begin(); i != xl.end(); ++i) { // Traverse all intersections in the path
+ ILIter n = cyclic_next(i, xl);
+ std::size_t pi = i->pos.path_index;
+
+ /// Path time interval from the current crossing to the next one
+ PathInterval ival = forward_interval(i->pos, n->pos, _pv[w][pi].size());
+ PathTime mid = ival.inside(precision);
+
+ Point wpoint = _pv[w][pi].pointAt(mid);
+ _winding_points.push_back(wpoint);
+ int wdg = _pv[ow].winding(wpoint);
+ if (wdg % 2) {
+ i->next_edge = INSIDE;
+ } else {
+ i->next_edge = OUTSIDE;
+ }
+ }
+ }
+ }
+}
+
+/** Detect the situation where a path is either entirely inside or entirely outside of the other
+ * path-vector and set the status flag accordingly.
+ */
+void PathIntersectionGraph::_assignComponentStatusFromDegenerateIntersections()
+{
+ for (auto & _component : _components) {
+ for (unsigned li = 0; li < _component.size(); ++li) {
+ IntersectionList &xl = _component[li].xlist;
+ bool has_in = false;
+ bool has_out = false;
+ for (auto & i : xl) {
+ has_in |= (i.next_edge == INSIDE);
+ has_out |= (i.next_edge == OUTSIDE);
+ }
+ if (has_in && !has_out) {
+ _component[li].status = INSIDE;
+ }
+ if (!has_in && has_out) {
+ _component[li].status = OUTSIDE;
+ }
+ }
+ }
+}
+
+/** Remove intersections that don't change between in/out.
+ *
+ * In general, a degenerate intersection can happen at a point where
+ * two shapes "kiss" (are tangent) but do not cross into each other.
+ */
+void PathIntersectionGraph::_removeDegenerateIntersections()
+{
+ for (auto & _component : _components) {
+ for (unsigned li = 0; li < _component.size(); ++li) {
+ IntersectionList &xl = _component[li].xlist;
+ for (ILIter i = xl.begin(); i != xl.end();) {
+ ILIter n = cyclic_next(i, xl);
+ if (i->next_edge == n->next_edge) { // Both edges inside or both outside
+ bool last_node = (i == n); ///< Whether this is the last remaining crossing.
+ ILIter nn = _getNeighbor(n);
+ IntersectionList &oxl = _getPathData(nn).xlist;
+
+ // When exactly 3 out of 4 edges adjacent to an intersection
+ // have the same winding, we have a defective intersection,
+ // which is neither degenerate nor normal. Those can occur in paths
+ // that contain overlapping segments.
+ if (cyclic_prior(nn, oxl)->next_edge != nn->next_edge) {
+ // Not a backtrack - set the defective flag.
+ _graph_valid = false;
+ n->defective = true;
+ nn->defective = true;
+ ++i;
+ continue;
+ }
+ // Erase the degenerate or defective crossings
+ oxl.erase(nn);
+ xl.erase(n);
+ if (last_node) break;
+ } else {
+ ++i;
+ }
+ }
+ }
+ }
+}
+
+/** Verify that all paths contain an even number of intersections and that
+ * the intersection graph does not contain leaves (degree one vertices).
+ */
+void PathIntersectionGraph::_verify()
+{
+#ifndef NDEBUG
+ for (auto & _component : _components) {
+ for (unsigned li = 0; li < _component.size(); ++li) {
+ IntersectionList &xl = _component[li].xlist;
+ assert(xl.size() % 2 == 0);
+ for (ILIter i = xl.begin(); i != xl.end(); ++i) {
+ ILIter j = cyclic_next(i, xl);
+ assert(i->next_edge != j->next_edge);
+ }
+ }
+ }
+#endif
+}
+
+PathVector PathIntersectionGraph::getUnion()
+{
+ PathVector result = _getResult(false, false);
+ _handleNonintersectingPaths(result, 0, false);
+ _handleNonintersectingPaths(result, 1, false);
+ return result;
+}
+
+PathVector PathIntersectionGraph::getIntersection()
+{
+ PathVector result = _getResult(true, true);
+ _handleNonintersectingPaths(result, 0, true);
+ _handleNonintersectingPaths(result, 1, true);
+ return result;
+}
+
+PathVector PathIntersectionGraph::getAminusB()
+{
+ PathVector result = _getResult(false, true);
+ _handleNonintersectingPaths(result, 0, false);
+ _handleNonintersectingPaths(result, 1, true);
+ return result;
+}
+
+PathVector PathIntersectionGraph::getBminusA()
+{
+ PathVector result = _getResult(true, false);
+ _handleNonintersectingPaths(result, 1, false);
+ _handleNonintersectingPaths(result, 0, true);
+ return result;
+}
+
+PathVector PathIntersectionGraph::getXOR()
+{
+ PathVector r1, r2;
+ r1 = getAminusB();
+ r2 = getBminusA();
+ std::copy(r2.begin(), r2.end(), std::back_inserter(r1));
+ return r1;
+}
+
+std::size_t PathIntersectionGraph::size() const
+{
+ std::size_t result = 0;
+ for (std::size_t i = 0; i < _components[0].size(); ++i) {
+ result += _components[0][i].xlist.size();
+ }
+ return result;
+}
+
+std::vector<Point> PathIntersectionGraph::intersectionPoints(bool defective) const
+{
+ std::vector<Point> result;
+
+ for (std::size_t i = 0; i < _components[0].size(); ++i) {
+ for (const auto & j : _components[0][i].xlist) {
+ if (j.defective == defective) {
+ result.push_back(j.p);
+ }
+ }
+ }
+ return result;
+}
+
+void PathIntersectionGraph::fragments(PathVector &in, PathVector &out) const
+{
+ typedef boost::ptr_vector<PathData>::const_iterator PIter;
+ for (unsigned w = 0; w < 2; ++w) {
+ for (PIter li = _components[w].begin(); li != _components[w].end(); ++li) {
+ for (CILIter k = li->xlist.begin(); k != li->xlist.end(); ++k) {
+ CILIter n = cyclic_next(k, li->xlist);
+ // TODO: investigate why non-contiguous paths are sometimes generated here
+ Path frag(k->p);
+ frag.setStitching(true);
+ PathInterval ival = forward_interval(k->pos, n->pos, _pv[w][k->pos.path_index].size());
+ _pv[w][k->pos.path_index].appendPortionTo(frag, ival, k->p, n->p);
+ if (k->next_edge == INSIDE) {
+ in.push_back(frag);
+ } else {
+ out.push_back(frag);
+ }
+ }
+ }
+ }
+}
+
+/** @brief Compute the partial result of a boolean operation by looking at components containing
+ * intersections and stitching the correct path portions between them, depending on the truth
+ * table of the operation.
+ *
+ * @param enter_a – whether the path portions contained inside operand A should be part of the boundary
+ * of the boolean operation's result.
+ * @param enter_b – whether the path portions contained inside operand B should be part of the boundary
+ * of the boolean operation's result.
+ *
+ * These two flags completely determine how to resolve the crossings when building the result
+ * and therefore encode which boolean operation we are performing. For example, the boolean intersection
+ * corresponds to enter_a == true and enter_b == true, as can be seen by looking at a Venn diagram.
+ */
+PathVector PathIntersectionGraph::_getResult(bool enter_a, bool enter_b)
+{
+ PathVector result;
+ if (_xs.empty()) return result;
+
+ // Create the list of intersections to process
+ _ulist.clear();
+ for (auto & _component : _components) {
+ for (auto & li : _component) {
+ for (auto & k : li.xlist) {
+ _ulist.push_back(k);
+ }
+ }
+ }
+
+ unsigned n_processed = 0;
+
+ while (true) {
+ // get unprocessed intersection
+ if (_ulist.empty()) break;
+ IntersectionVertex &iv = _ulist.front();
+ unsigned w = iv.which;
+ ILIter i = _components[w][iv.pos.path_index].xlist.iterator_to(iv);
+
+ result.push_back(Path(i->p));
+ result.back().setStitching(true);
+ bool reverse = false; ///< Whether to traverse the current component in the backwards direction.
+ while (i->_proc_hook.is_linked()) {
+ ILIter prev = i;
+ std::size_t pi = i->pos.path_index; ///< Index of the path in its PathVector
+ // determine which direction to go
+ // union: always go outside
+ // intersection: always go inside
+ // a minus b: go inside in b, outside in a
+ // b minus a: go inside in a, outside in b
+ if (w == 0) { // The path we're on is a part of A
+ reverse = (i->next_edge == INSIDE) ^ enter_a;
+ } else { // The path we're on is a part of B
+ reverse = (i->next_edge == INSIDE) ^ enter_b;
+ }
+
+ // get next intersection
+ if (reverse) {
+ i = cyclic_prior(i, _components[w][pi].xlist);
+ } else {
+ i = cyclic_next(i, _components[w][pi].xlist);
+ }
+
+ // append portion of path to the result
+ PathInterval ival = PathInterval::from_direction(
+ prev->pos.asPathTime(), i->pos.asPathTime(),
+ reverse, _pv[i->which][pi].size());
+
+ _pv[i->which][pi].appendPortionTo(result.back(), ival, prev->p, i->p);
+
+ // count both vertices as processed
+ n_processed += 2;
+ if (prev->_proc_hook.is_linked()) {
+ _ulist.erase(_ulist.iterator_to(*prev));
+ }
+ if (i->_proc_hook.is_linked()) {
+ _ulist.erase(_ulist.iterator_to(*i));
+ }
+
+ // switch to the other path
+ i = _getNeighbor(i);
+ w = i->which;
+ }
+ result.back().close(true);
+ if (reverse){
+ result.back() = result.back().reversed();
+ }
+ if (result.back().empty()) {
+ // std::cerr << "Path is empty" << std::endl;
+ throw GEOM_ERR_INTERSECGRAPH;
+ }
+ }
+
+ if (n_processed != size() * 2) {
+ // std::cerr << "Processed " << n_processed << " intersections, expected " << (size() * 2) << std::endl;
+ throw GEOM_ERR_INTERSECGRAPH;
+ }
+
+ return result;
+}
+
+/** @brief Select intersection-free path components ahead of a boolean operation based on whether
+ * they should be a part of that operation's result.
+ *
+ * Every component that has intersections will be processed by _getResult().
+ * Here we take care of paths that don't have any intersections. They are either
+ * completely inside or completely outside the other path-vector.
+ *
+ * @param result – output parameter to store the selected components.
+ * @param which – which of the two operands to search for intersection-free paths.
+ * @param inside – If set to true, add paths entirely contained inside the other path-vector to
+ * the result. If set to false, add paths entirely outside of the other path-vector instead.
+ */
+void PathIntersectionGraph::_handleNonintersectingPaths(PathVector &result, unsigned which, bool inside)
+{
+ unsigned w = which;
+ unsigned ow = (w+1) % 2;
+
+ for (std::size_t i = 0; i < _pv[w].size(); ++i) {
+ // the path data vector might have been left empty if there were no intersections at all
+ bool has_path_data = !_components[w].empty();
+ // Skip if the path has intersections
+ if (has_path_data && !_components[w][i].xlist.empty()) continue;
+ bool path_inside = false;
+
+ // Use the status flag set in the constructor if available.
+ if (has_path_data && _components[w][i].status == INSIDE) {
+ path_inside = true;
+ } else if (has_path_data && _components[w][i].status == OUTSIDE) {
+ path_inside = false;
+ } else {
+ // The status flag is ambiguous: we evaluate the winding number of the initial point.
+ int wdg = _pv[ow].winding(_pv[w][i].initialPoint());
+ path_inside = wdg % 2 != 0;
+ }
+
+ if (path_inside == inside) {
+ result.push_back(_pv[w][i]);
+ }
+ }
+}
+
+/** @brief Get an iterator to the corresponding crossing on the other path-vector.
+ *
+ * @param ILIter – an iterator to a list of intersections in one of the path-vectors.
+ * @return An iterator to the corresponding intersection in the other path-vector.
+ */
+PathIntersectionGraph::ILIter PathIntersectionGraph::_getNeighbor(ILIter iter)
+{
+ unsigned ow = (iter->which + 1) % 2;
+ return _components[ow][iter->neighbor->pos.path_index].xlist.iterator_to(*iter->neighbor);
+}
+
+/** Get the path data for the path containing the intersection given an iterator to the intersection */
+PathIntersectionGraph::PathData &
+PathIntersectionGraph::_getPathData(ILIter iter)
+{
+ return _components[iter->which][iter->pos.path_index];
+}
+
+/** Format the PathIntersectionGraph for output. */
+std::ostream &operator<<(std::ostream &os, PathIntersectionGraph const &pig)
+{
+ os << "Intersection graph:\n"
+ << pig._xs.size()/2 << " total intersections\n"
+ << pig.size() << " considered intersections\n";
+ for (std::size_t i = 0; i < pig._components[0].size(); ++i) {
+ PathIntersectionGraph::IntersectionList const &xl = pig._components[0][i].xlist;
+ for (const auto & j : xl) {
+ os << j.pos << " - " << j.neighbor->pos << " @ " << j.p << "\n";
+ }
+ }
+ return os;
+}
+
+} // namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+
diff --git a/src/3rdparty/2geom/src/2geom/intervaltree/interval_tree.cc b/src/3rdparty/2geom/src/2geom/intervaltree/interval_tree.cc
new file mode 100644
index 0000000..01a222a
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/intervaltree/interval_tree.cc
@@ -0,0 +1,799 @@
+#include "interval_tree.h"
+#include <stdio.h>
+#include <math.h>
+#include <assert.h>
+
+// From Emin Martinian, licenced LGPL and MPL with permission
+
+
+using namespace std;
+
+// If the symbol CHECK_INTERVAL_TREE_ASSUMPTIONS is defined then the
+// code does a lot of extra checking to make sure certain assumptions
+// are satisfied. This only needs to be done if you suspect bugs are
+// present or if you make significant changes and want to make sure
+// your changes didn't mess anything up.
+//#define CHECK_INTERVAL_TREE_ASSUMPTIONS 1
+
+
+const int MIN_INT=-MAX_INT;
+
+IntervalTreeNode::IntervalTreeNode(){}
+
+IntervalTreeNode::IntervalTreeNode(Interval * newInterval)
+ : storedInterval (newInterval) ,
+ key(newInterval->GetLowPoint()),
+ high(newInterval->GetHighPoint()) ,
+ maxHigh(high) {
+}
+IntervalTreeNode::~IntervalTreeNode(){}
+Interval::Interval(){}
+Interval::~Interval(){}
+void Interval::Print() const {
+ cout << "No Print Method defined for instance of Interval" << endl;
+}
+
+IntervalTree::IntervalTree()
+{
+ nil = new IntervalTreeNode;
+ nil->left = nil->right = nil->parent = nil;
+ nil->red = 0;
+ nil->key = nil->high = nil->maxHigh = MIN_INT;
+ nil->storedInterval = NULL;
+
+ root = new IntervalTreeNode;
+ root->parent = root->left = root->right = nil;
+ root->key = root->high = root->maxHigh = MAX_INT;
+ root->red=0;
+ root->storedInterval = NULL;
+
+ /* the following are used for the Enumerate function */
+ recursionNodeStackSize = 8; // the tree depth is approximately lg(n), this is a 256 element tree. The code will adapt to deeper trees, but this saves considerable space for small trees.
+ recursionNodeStack = new it_recursion_node[recursionNodeStackSize];
+ recursionNodeStackTop = 1;
+ recursionNodeStack[0].start_node = NULL;
+
+}
+
+/***********************************************************************/
+/* FUNCTION: LeftRotate */
+/**/
+/* INPUTS: the node to rotate on */
+/**/
+/* OUTPUT: None */
+/**/
+/* Modifies Input: this, x */
+/**/
+/* EFFECTS: Rotates as described in _Introduction_To_Algorithms by */
+/* Cormen, Leiserson, Rivest (Chapter 14). Basically this */
+/* makes the parent of x be to the left of x, x the parent of */
+/* its parent before the rotation and fixes other pointers */
+/* accordingly. Also updates the maxHigh fields of x and y */
+/* after rotation. */
+/***********************************************************************/
+
+void IntervalTree::LeftRotate(IntervalTreeNode* x) {
+ IntervalTreeNode* y;
+
+ /* I originally wrote this function to use the sentinel for */
+ /* nil to avoid checking for nil. However this introduces a */
+ /* very subtle bug because sometimes this function modifies */
+ /* the parent pointer of nil. This can be a problem if a */
+ /* function which calls LeftRotate also uses the nil sentinel */
+ /* and expects the nil sentinel's parent pointer to be unchanged */
+ /* after calling this function. For example, when DeleteFixUP */
+ /* calls LeftRotate it expects the parent pointer of nil to be */
+ /* unchanged. */
+
+ y=x->right;
+ x->right=y->left;
+
+ if (y->left != nil) y->left->parent=x; /* used to use sentinel here */
+ /* and do an unconditional assignment instead of testing for nil */
+
+ y->parent=x->parent;
+
+ /* instead of checking if x->parent is the root as in the book, we */
+ /* count on the root sentinel to implicitly take care of this case */
+ if( x == x->parent->left) {
+ x->parent->left=y;
+ } else {
+ x->parent->right=y;
+ }
+ y->left=x;
+ x->parent=y;
+
+ x->maxHigh=std::max(x->left->maxHigh,std::max(x->right->maxHigh,x->high));
+ y->maxHigh=std::max(x->maxHigh,std::max(y->right->maxHigh,y->high));
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+ CheckAssumptions();
+#elif defined(DEBUG_ASSERT)
+ assert(!nil->red,"nil not red in ITLeftRotate");
+ assert((nil->maxHigh=MIN_INT),
+ "nil->maxHigh != MIN_INT in ITLeftRotate");
+#endif
+}
+
+
+/***********************************************************************/
+/* FUNCTION: RighttRotate */
+/**/
+/* INPUTS: node to rotate on */
+/**/
+/* OUTPUT: None */
+/**/
+/* Modifies Input?: this, y */
+/**/
+/* EFFECTS: Rotates as described in _Introduction_To_Algorithms by */
+/* Cormen, Leiserson, Rivest (Chapter 14). Basically this */
+/* makes the parent of x be to the left of x, x the parent of */
+/* its parent before the rotation and fixes other pointers */
+/* accordingly. Also updates the maxHigh fields of x and y */
+/* after rotation. */
+/***********************************************************************/
+
+
+void IntervalTree::RightRotate(IntervalTreeNode* y) {
+ IntervalTreeNode* x;
+
+ /* I originally wrote this function to use the sentinel for */
+ /* nil to avoid checking for nil. However this introduces a */
+ /* very subtle bug because sometimes this function modifies */
+ /* the parent pointer of nil. This can be a problem if a */
+ /* function which calls LeftRotate also uses the nil sentinel */
+ /* and expects the nil sentinel's parent pointer to be unchanged */
+ /* after calling this function. For example, when DeleteFixUP */
+ /* calls LeftRotate it expects the parent pointer of nil to be */
+ /* unchanged. */
+
+ x=y->left;
+ y->left=x->right;
+
+ if (nil != x->right) x->right->parent=y; /*used to use sentinel here */
+ /* and do an unconditional assignment instead of testing for nil */
+
+ /* instead of checking if x->parent is the root as in the book, we */
+ /* count on the root sentinel to implicitly take care of this case */
+ x->parent=y->parent;
+ if( y == y->parent->left) {
+ y->parent->left=x;
+ } else {
+ y->parent->right=x;
+ }
+ x->right=y;
+ y->parent=x;
+
+ y->maxHigh=std::max(y->left->maxHigh,std::max(y->right->maxHigh,y->high));
+ x->maxHigh=std::max(x->left->maxHigh,std::max(y->maxHigh,x->high));
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+ CheckAssumptions();
+#elif defined(DEBUG_ASSERT)
+ assert(!nil->red,"nil not red in ITRightRotate");
+ assert((nil->maxHigh=MIN_INT),
+ "nil->maxHigh != MIN_INT in ITRightRotate");
+#endif
+}
+
+/***********************************************************************/
+/* FUNCTION: TreeInsertHelp */
+/**/
+/* INPUTS: z is the node to insert */
+/**/
+/* OUTPUT: none */
+/**/
+/* Modifies Input: this, z */
+/**/
+/* EFFECTS: Inserts z into the tree as if it were a regular binary tree */
+/* using the algorithm described in _Introduction_To_Algorithms_ */
+/* by Cormen et al. This function is only intended to be called */
+/* by the InsertTree function and not by the user */
+/***********************************************************************/
+
+void IntervalTree::TreeInsertHelp(IntervalTreeNode* z) {
+ /* This function should only be called by InsertITTree (see above) */
+ IntervalTreeNode* x;
+ IntervalTreeNode* y;
+
+ z->left=z->right=nil;
+ y=root;
+ x=root->left;
+ while( x != nil) {
+ y=x;
+ if ( x->key > z->key) {
+ x=x->left;
+ } else { /* x->key <= z->key */
+ x=x->right;
+ }
+ }
+ z->parent=y;
+ if ( (y == root) ||
+ (y->key > z->key) ) {
+ y->left=z;
+ } else {
+ y->right=z;
+ }
+
+
+#if defined(DEBUG_ASSERT)
+ assert(!nil->red,"nil not red in ITTreeInsertHelp");
+ assert((nil->maxHigh=MIN_INT),
+ "nil->maxHigh != MIN_INT in ITTreeInsertHelp");
+#endif
+}
+
+
+/***********************************************************************/
+/* FUNCTION: FixUpMaxHigh */
+/**/
+/* INPUTS: x is the node to start from*/
+/**/
+/* OUTPUT: none */
+/**/
+/* Modifies Input: this */
+/**/
+/* EFFECTS: Travels up to the root fixing the maxHigh fields after */
+/* an insertion or deletion */
+/***********************************************************************/
+
+void IntervalTree::FixUpMaxHigh(IntervalTreeNode * x) {
+ while(x != root) {
+ x->maxHigh=std::max(x->high,std::max(x->left->maxHigh,x->right->maxHigh));
+ x=x->parent;
+ }
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+ CheckAssumptions();
+#endif
+}
+
+/* Before calling InsertNode the node x should have its key set */
+
+/***********************************************************************/
+/* FUNCTION: InsertNode */
+/**/
+/* INPUTS: newInterval is the interval to insert*/
+/**/
+/* OUTPUT: This function returns a pointer to the newly inserted node */
+/* which is guaranteed to be valid until this node is deleted. */
+/* What this means is if another data structure stores this */
+/* pointer then the tree does not need to be searched when this */
+/* is to be deleted. */
+/**/
+/* Modifies Input: tree */
+/**/
+/* EFFECTS: Creates a node node which contains the appropriate key and */
+/* info pointers and inserts it into the tree. */
+/***********************************************************************/
+
+IntervalTreeNode * IntervalTree::Insert(Interval * newInterval)
+{
+ IntervalTreeNode * y;
+ IntervalTreeNode * x;
+ IntervalTreeNode * newNode;
+
+ x = new IntervalTreeNode(newInterval);
+ TreeInsertHelp(x);
+ FixUpMaxHigh(x->parent);
+ newNode = x;
+ x->red=1;
+ while(x->parent->red) { /* use sentinel instead of checking for root */
+ if (x->parent == x->parent->parent->left) {
+ y=x->parent->parent->right;
+ if (y->red) {
+ x->parent->red=0;
+ y->red=0;
+ x->parent->parent->red=1;
+ x=x->parent->parent;
+ } else {
+ if (x == x->parent->right) {
+ x=x->parent;
+ LeftRotate(x);
+ }
+ x->parent->red=0;
+ x->parent->parent->red=1;
+ RightRotate(x->parent->parent);
+ }
+ } else { /* case for x->parent == x->parent->parent->right */
+ /* this part is just like the section above with */
+ /* left and right interchanged */
+ y=x->parent->parent->left;
+ if (y->red) {
+ x->parent->red=0;
+ y->red=0;
+ x->parent->parent->red=1;
+ x=x->parent->parent;
+ } else {
+ if (x == x->parent->left) {
+ x=x->parent;
+ RightRotate(x);
+ }
+ x->parent->red=0;
+ x->parent->parent->red=1;
+ LeftRotate(x->parent->parent);
+ }
+ }
+ }
+ root->left->red=0;
+ return(newNode);
+
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+ CheckAssumptions();
+#elif defined(DEBUG_ASSERT)
+ assert(!nil->red,"nil not red in ITTreeInsert");
+ assert(!root->red,"root not red in ITTreeInsert");
+ assert((nil->maxHigh=MIN_INT),
+ "nil->maxHigh != MIN_INT in ITTreeInsert");
+#endif
+}
+
+/***********************************************************************/
+/* FUNCTION: GetSuccessorOf */
+/**/
+/* INPUTS: x is the node we want the successor of */
+/**/
+/* OUTPUT: This function returns the successor of x or NULL if no */
+/* successor exists. */
+/**/
+/* Modifies Input: none */
+/**/
+/* Note: uses the algorithm in _Introduction_To_Algorithms_ */
+/***********************************************************************/
+
+IntervalTreeNode * IntervalTree::GetSuccessorOf(IntervalTreeNode * x) const
+{
+ IntervalTreeNode* y;
+
+ if (nil != (y = x->right)) { /* assignment to y is intentional */
+ while(y->left != nil) { /* returns the minimum of the right subtree of x */
+ y=y->left;
+ }
+ return(y);
+ } else {
+ y=x->parent;
+ while(x == y->right) { /* sentinel used instead of checking for nil */
+ x=y;
+ y=y->parent;
+ }
+ if (y == root) return(nil);
+ return(y);
+ }
+}
+
+/***********************************************************************/
+/* FUNCTION: GetPredecessorOf */
+/**/
+/* INPUTS: x is the node to get predecessor of */
+/**/
+/* OUTPUT: This function returns the predecessor of x or NULL if no */
+/* predecessor exists. */
+/**/
+/* Modifies Input: none */
+/**/
+/* Note: uses the algorithm in _Introduction_To_Algorithms_ */
+/***********************************************************************/
+
+IntervalTreeNode * IntervalTree::GetPredecessorOf(IntervalTreeNode * x) const {
+ IntervalTreeNode* y;
+
+ if (nil != (y = x->left)) { /* assignment to y is intentional */
+ while(y->right != nil) { /* returns the maximum of the left subtree of x */
+ y=y->right;
+ }
+ return(y);
+ } else {
+ y=x->parent;
+ while(x == y->left) {
+ if (y == root) return(nil);
+ x=y;
+ y=y->parent;
+ }
+ return(y);
+ }
+}
+
+/***********************************************************************/
+/* FUNCTION: Print */
+/**/
+/* INPUTS: none */
+/**/
+/* OUTPUT: none */
+/**/
+/* EFFECTS: This function recursively prints the nodes of the tree */
+/* inorder. */
+/**/
+/* Modifies Input: none */
+/**/
+/* Note: This function should only be called from ITTreePrint */
+/***********************************************************************/
+
+void IntervalTreeNode::Print(IntervalTreeNode * nil,
+ IntervalTreeNode * root) const {
+ storedInterval->Print();
+ printf(", k=%i, h=%i, mH=%i",key,high,maxHigh);
+ printf(" l->key=");
+ if( left == nil) printf("NULL"); else printf("%i",left->key);
+ printf(" r->key=");
+ if( right == nil) printf("NULL"); else printf("%i",right->key);
+ printf(" p->key=");
+ if( parent == root) printf("NULL"); else printf("%i",parent->key);
+ printf(" red=%i\n",red);
+}
+
+void IntervalTree::TreePrintHelper( IntervalTreeNode* x) const {
+
+ if (x != nil) {
+ TreePrintHelper(x->left);
+ x->Print(nil,root);
+ TreePrintHelper(x->right);
+ }
+}
+
+IntervalTree::~IntervalTree() {
+ IntervalTreeNode * x = root->left;
+ vector<IntervalTreeNode *> stuffToFree;
+
+ if (x != nil) {
+ if (x->left != nil) {
+ stuffToFree.push_back(x->left);
+ }
+ if (x->right != nil) {
+ stuffToFree.push_back(x->right);
+ }
+ // delete x->storedInterval;
+ delete x;
+ while(! stuffToFree.empty() ) {
+ x = stuffToFree.back();
+ stuffToFree.pop_back();
+ if (x->left != nil) {
+ stuffToFree.push_back(x->left);
+ }
+ if (x->right != nil) {
+ stuffToFree.push_back(x->right);
+ }
+ // delete x->storedInterval;
+ delete x;
+ }
+ }
+ delete nil;
+ delete root;
+ delete[] recursionNodeStack;
+}
+
+
+/***********************************************************************/
+/* FUNCTION: Print */
+/**/
+/* INPUTS: none */
+/**/
+/* OUTPUT: none */
+/**/
+/* EFFECT: This function recursively prints the nodes of the tree */
+/* inorder. */
+/**/
+/* Modifies Input: none */
+/**/
+/***********************************************************************/
+
+void IntervalTree::Print() const {
+ TreePrintHelper(root->left);
+}
+
+/***********************************************************************/
+/* FUNCTION: DeleteFixUp */
+/**/
+/* INPUTS: x is the child of the spliced */
+/* out node in DeleteNode. */
+/**/
+/* OUTPUT: none */
+/**/
+/* EFFECT: Performs rotations and changes colors to restore red-black */
+/* properties after a node is deleted */
+/**/
+/* Modifies Input: this, x */
+/**/
+/* The algorithm from this function is from _Introduction_To_Algorithms_ */
+/***********************************************************************/
+
+void IntervalTree::DeleteFixUp(IntervalTreeNode* x) {
+ IntervalTreeNode * w;
+ IntervalTreeNode * rootLeft = root->left;
+
+ while( (!x->red) && (rootLeft != x)) {
+ if (x == x->parent->left) {
+ w=x->parent->right;
+ if (w->red) {
+ w->red=0;
+ x->parent->red=1;
+ LeftRotate(x->parent);
+ w=x->parent->right;
+ }
+ if ( (!w->right->red) && (!w->left->red) ) {
+ w->red=1;
+ x=x->parent;
+ } else {
+ if (!w->right->red) {
+ w->left->red=0;
+ w->red=1;
+ RightRotate(w);
+ w=x->parent->right;
+ }
+ w->red=x->parent->red;
+ x->parent->red=0;
+ w->right->red=0;
+ LeftRotate(x->parent);
+ x=rootLeft; /* this is to exit while loop */
+ }
+ } else { /* the code below is has left and right switched from above */
+ w=x->parent->left;
+ if (w->red) {
+ w->red=0;
+ x->parent->red=1;
+ RightRotate(x->parent);
+ w=x->parent->left;
+ }
+ if ( (!w->right->red) && (!w->left->red) ) {
+ w->red=1;
+ x=x->parent;
+ } else {
+ if (!w->left->red) {
+ w->right->red=0;
+ w->red=1;
+ LeftRotate(w);
+ w=x->parent->left;
+ }
+ w->red=x->parent->red;
+ x->parent->red=0;
+ w->left->red=0;
+ RightRotate(x->parent);
+ x=rootLeft; /* this is to exit while loop */
+ }
+ }
+ }
+ x->red=0;
+
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+ CheckAssumptions();
+#elif defined(DEBUG_ASSERT)
+ assert(!nil->red,"nil not black in ITDeleteFixUp");
+ assert((nil->maxHigh=MIN_INT),
+ "nil->maxHigh != MIN_INT in ITDeleteFixUp");
+#endif
+}
+
+
+/***********************************************************************/
+/* FUNCTION: DeleteNode */
+/**/
+/* INPUTS: tree is the tree to delete node z from */
+/**/
+/* OUTPUT: returns the Interval stored at deleted node */
+/**/
+/* EFFECT: Deletes z from tree and but don't call destructor */
+/* Then calls FixUpMaxHigh to fix maxHigh fields then calls */
+/* ITDeleteFixUp to restore red-black properties */
+/**/
+/* Modifies Input: z */
+/**/
+/* The algorithm from this function is from _Introduction_To_Algorithms_ */
+/***********************************************************************/
+
+Interval * IntervalTree::DeleteNode(IntervalTreeNode * z){
+ IntervalTreeNode* y;
+ IntervalTreeNode* x;
+ Interval * returnValue = z->storedInterval;
+
+ y= ((z->left == nil) || (z->right == nil)) ? z : GetSuccessorOf(z);
+ x= (y->left == nil) ? y->right : y->left;
+ if (root == (x->parent = y->parent)) { /* assignment of y->p to x->p is intentional */
+ root->left=x;
+ } else {
+ if (y == y->parent->left) {
+ y->parent->left=x;
+ } else {
+ y->parent->right=x;
+ }
+ }
+ if (y != z) { /* y should not be nil in this case */
+
+#ifdef DEBUG_ASSERT
+ assert( (y!=nil),"y is nil in DeleteNode \n");
+#endif
+ /* y is the node to splice out and x is its child */
+
+ y->maxHigh = MIN_INT;
+ y->left=z->left;
+ y->right=z->right;
+ y->parent=z->parent;
+ z->left->parent=z->right->parent=y;
+ if (z == z->parent->left) {
+ z->parent->left=y;
+ } else {
+ z->parent->right=y;
+ }
+ FixUpMaxHigh(x->parent);
+ if (!(y->red)) {
+ y->red = z->red;
+ DeleteFixUp(x);
+ } else
+ y->red = z->red;
+ delete z;
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+ CheckAssumptions();
+#elif defined(DEBUG_ASSERT)
+ assert(!nil->red,"nil not black in ITDelete");
+ assert((nil->maxHigh=MIN_INT),"nil->maxHigh != MIN_INT in ITDelete");
+#endif
+ } else {
+ FixUpMaxHigh(x->parent);
+ if (!(y->red)) DeleteFixUp(x);
+ delete y;
+#ifdef CHECK_INTERVAL_TREE_ASSUMPTIONS
+ CheckAssumptions();
+#elif defined(DEBUG_ASSERT)
+ assert(!nil->red,"nil not black in ITDelete");
+ assert((nil->maxHigh=MIN_INT),"nil->maxHigh != MIN_INT in ITDelete");
+#endif
+ }
+ return returnValue;
+}
+
+
+/***********************************************************************/
+/* FUNCTION: Overlap */
+/**/
+/* INPUTS: [a1,a2] and [b1,b2] are the low and high endpoints of two */
+/* closed intervals. */
+/**/
+/* OUTPUT: stack containing pointers to the nodes between [low,high] */
+/**/
+/* Modifies Input: none */
+/**/
+/* EFFECT: returns 1 if the intervals overlap, and 0 otherwise */
+/***********************************************************************/
+
+int Overlap(int a1, int a2, int b1, int b2) {
+ if (a1 <= b1) {
+ return( (b1 <= a2) );
+ } else {
+ return( (a1 <= b2) );
+ }
+}
+
+
+/***********************************************************************/
+/* FUNCTION: Enumerate */
+/**/
+/* INPUTS: tree is the tree to look for intervals overlapping the */
+/* closed interval [low,high] */
+/**/
+/* OUTPUT: stack containing pointers to the nodes overlapping */
+/* [low,high] */
+/**/
+/* Modifies Input: none */
+/**/
+/* EFFECT: Returns a stack containing pointers to nodes containing */
+/* intervals which overlap [low,high] in O(max(N,k*log(N))) */
+/* where N is the number of intervals in the tree and k is */
+/* the number of overlapping intervals */
+/**/
+/* Note: This basic idea for this function comes from the */
+/* _Introduction_To_Algorithms_ book by Cormen et al, but */
+/* modifications were made to return all overlapping intervals */
+/* instead of just the first overlapping interval as in the */
+/* book. The natural way to do this would require recursive */
+/* calls of a basic search function. I translated the */
+/* recursive version into an interative version with a stack */
+/* as described below. */
+/***********************************************************************/
+
+
+
+/* The basic idea for the function below is to take the IntervalSearch */
+/* function from the book and modify to find all overlapping intervals */
+/* instead of just one. This means that any time we take the left */
+/* branch down the tree we must also check the right branch if and only if */
+/* we find an overlapping interval in that left branch. Note this is a */
+/* recursive condition because if we go left at the root then go left */
+/* again at the first left child and find an overlap in the left subtree */
+/* of the left child of root we must recursively check the right subtree */
+/* of the left child of root as well as the right child of root. */
+
+vector<void *> IntervalTree::Enumerate(int low, int high) {
+ vector<void *> enumResultStack;
+ IntervalTreeNode* x=root->left;
+ int stuffToDo = (x != nil);
+
+ // Possible speed up: add min field to prune right searches //
+
+#ifdef DEBUG_ASSERT
+ assert((recursionNodeStackTop == 1),
+ "recursionStack not empty when entering IntervalTree::Enumerate");
+#endif
+ currentParent = 0;
+
+ while(stuffToDo) {
+ if (Overlap(low,high,x->key,x->high) ) {
+ enumResultStack.push_back(x->storedInterval);
+ recursionNodeStack[currentParent].tryRightBranch=true;
+ }
+ if(x->left->maxHigh >= low) { // implies x != nil
+ if ( recursionNodeStackTop == recursionNodeStackSize ) {
+ recursionNodeStackSize *= 2;
+ recursionNodeStack = (it_recursion_node *)
+ realloc(recursionNodeStack,
+ recursionNodeStackSize * sizeof(it_recursion_node));
+ if (recursionNodeStack == NULL)
+ assert("realloc failed in IntervalTree::Enumerate\n");
+ }
+ recursionNodeStack[recursionNodeStackTop].start_node = x;
+ recursionNodeStack[recursionNodeStackTop].tryRightBranch = 0;
+ recursionNodeStack[recursionNodeStackTop].parentIndex = currentParent;
+ currentParent = recursionNodeStackTop++;
+ x = x->left;
+ } else {
+ x = x->right;
+ }
+ stuffToDo = (x != nil);
+ while( (!stuffToDo) && (recursionNodeStackTop > 1) ) {
+ if(recursionNodeStack[--recursionNodeStackTop].tryRightBranch) {
+ x=recursionNodeStack[recursionNodeStackTop].start_node->right;
+ currentParent=recursionNodeStack[recursionNodeStackTop].parentIndex;
+ recursionNodeStack[currentParent].tryRightBranch=true;
+ stuffToDo = ( x != nil);
+ }
+ }
+ }
+#ifdef DEBUG_ASSERT
+ assert((recursionNodeStackTop == 1),
+ "recursionStack not empty when exiting IntervalTree::Enumerate");
+#endif
+ return enumResultStack;
+}
+
+
+
+int IntervalTree::CheckMaxHighFieldsHelper(IntervalTreeNode * y,
+ const int currentHigh,
+ int match) const
+{
+ if (y != nil) {
+ match = CheckMaxHighFieldsHelper(y->left,currentHigh,match) ?
+ 1 : match;
+ assert(y->high <= currentHigh);
+ if (y->high == currentHigh)
+ match = 1;
+ match = CheckMaxHighFieldsHelper(y->right,currentHigh,match) ?
+ 1 : match;
+ }
+ return match;
+}
+
+
+
+/* Make sure the maxHigh fields for everything makes sense. *
+ * If something is wrong, print a warning and exit */
+void IntervalTree::CheckMaxHighFields(IntervalTreeNode * x) const {
+ if (x != nil) {
+ CheckMaxHighFields(x->left);
+ if(!(CheckMaxHighFieldsHelper(x,x->maxHigh,0) > 0)) {
+ assert("error found in CheckMaxHighFields.\n");
+ }
+ CheckMaxHighFields(x->right);
+ }
+}
+
+void IntervalTree::CheckAssumptions() const {
+ assert(nil->key == MIN_INT);
+ assert(nil->high == MIN_INT);
+ assert(nil->maxHigh == MIN_INT);
+ assert(root->key == MAX_INT);
+ assert(root->high == MAX_INT);
+ assert(root->maxHigh == MAX_INT);
+ assert(nil->storedInterval == NULL);
+ assert(root->storedInterval == NULL);
+ assert(nil->red == 0);
+ assert(root->red == 0);
+ CheckMaxHighFields(root->left);
+}
+
+
+
diff --git a/src/3rdparty/2geom/src/2geom/intervaltree/test2.cc b/src/3rdparty/2geom/src/2geom/intervaltree/test2.cc
new file mode 100644
index 0000000..bce448e
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/intervaltree/test2.cc
@@ -0,0 +1,74 @@
+#include <iostream>
+
+// Nathan Hurst and Emin Martinian, licenced LGPL and MPL with permission
+
+
+#include "interval_tree.h"
+
+class SimpleInterval : public Interval {
+public:
+ SimpleInterval() :
+ _low(0),
+ _high(0),
+ _node(NULL)
+ {}
+ SimpleInterval(const int low,const int high)
+ :_low(low),
+ _high(high),
+ _node(NULL)
+ { }
+
+ int GetLowPoint() const { return _low;}
+ int GetHighPoint() const { return _high;}
+ IntervalTreeNode * GetNode() { return _node;}
+ void SetNode(IntervalTreeNode * node) {_node = node;}
+ virtual void Print() const {
+ printf("(%d, %d)", _low, _high);
+ }
+protected:
+ int _low;
+ int _high;
+ IntervalTreeNode * _node;
+
+};
+
+using namespace std;
+
+#include <stdlib.h>
+#include <time.h>
+
+int main() {
+ const int N = 1L<<24;
+ SimpleInterval *x = new SimpleInterval[N];
+ for(int i = 0; i < N; i++) {
+ x[i] = SimpleInterval(random(), random());
+ }
+
+ cout << "sizeof(SimpleInterval)" << sizeof(SimpleInterval) << endl;
+ cout << "sizeof(IntervalTreeNode)" << sizeof(IntervalTreeNode) << endl;
+ cout << "sizeof(it_recursion_node)" << sizeof(it_recursion_node) << endl;
+ cout << "sizeof(IntervalTree)" << sizeof(IntervalTree) << endl;
+
+ IntervalTree itree;
+ int onn = 0;
+ for(int nn = 1; nn < N; nn*=2) {
+ for(int i = onn; i < nn; i++) {
+ itree.Insert(&x[i]);
+ }
+ onn = nn;
+ clock_t s = clock();
+
+ int iters = 0;
+ int outputs = 0;
+ while(clock() - s < CLOCKS_PER_SEC/4) {
+ vector<void *> n = itree.Enumerate(random(), random()) ;
+ outputs += n.size();
+ //cout << n.size() << endl;
+ iters++;
+ }
+ clock_t e = clock();
+ double total = double(e - s)/(CLOCKS_PER_SEC);
+ cout << total << " " << outputs << " " << total/outputs << " " << nn << endl;
+ }
+ //itree.Print();
+}
diff --git a/src/3rdparty/2geom/src/2geom/line.cpp b/src/3rdparty/2geom/src/2geom/line.cpp
new file mode 100644
index 0000000..3db3039
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/line.cpp
@@ -0,0 +1,610 @@
+/*
+ * Infinite Straight Line
+ *
+ * Copyright 2008 Marco Cecchetti <mrcekets at gmail.com>
+ * Nathan Hurst
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <algorithm>
+#include <optional>
+#include <2geom/line.h>
+#include <2geom/math-utils.h>
+
+namespace Geom
+{
+
+/**
+ * @class Line
+ * @brief Infinite line on a plane.
+ *
+ * A line is specified as two points through which it passes. Lines can be interpreted as functions
+ * \f$ f: (-\infty, \infty) \to \mathbb{R}^2\f$. Zero corresponds to the first (origin) point,
+ * one corresponds to the second (final) point. All other points are computed as a linear
+ * interpolation between those two: \f$p = (1-t) a + t b\f$. Many such functions have the same
+ * image and therefore represent the same lines; for example, adding \f$b-a\f$ to both points
+ * yields the same line.
+ *
+ * 2Geom can represent the same line in many ways by design: using a different representation
+ * would lead to precision loss. For example, a line from (1e30, 1e30) to (10,0) would actually
+ * evaluate to (0,0) at time 1 if it was stored as origin and normalized versor,
+ * or origin and angle.
+ *
+ * @ingroup Primitives
+ */
+
+/** @brief Set the line by solving the line equation.
+ * A line is a set of points that satisfies the line equation
+ * \f$Ax + By + C = 0\f$. This function changes the line so that its points
+ * satisfy the line equation with the given coefficients. */
+void Line::setCoefficients (Coord a, Coord b, Coord c)
+{
+ // degenerate case
+ if (a == 0 && b == 0) {
+ if (c != 0) {
+ THROW_LOGICALERROR("the passed coefficients give the empty set");
+ }
+ _initial = Point(0,0);
+ _final = Point(0,0);
+ return;
+ }
+
+ // The way final / initial points are set based on coefficients is somewhat unusual.
+ // This is done to make sure that calling coefficients() will give back
+ // (almost) the same values.
+
+ // vertical case
+ if (a == 0) {
+ // b must be nonzero
+ _initial = Point(-b/2, -c / b);
+ _final = _initial;
+ _final[X] = b/2;
+ return;
+ }
+
+ // horizontal case
+ if (b == 0) {
+ _initial = Point(-c / a, a/2);
+ _final = _initial;
+ _final[Y] = -a/2;
+ return;
+ }
+
+ // This gives reasonable results regardless of the magnitudes of a, b and c.
+ _initial = Point(-b/2,a/2);
+ _final = Point(b/2,-a/2);
+
+ Point offset(-c/(2*a), -c/(2*b));
+
+ _initial += offset;
+ _final += offset;
+}
+
+void Line::coefficients(Coord &a, Coord &b, Coord &c) const
+{
+ Point v = vector().cw();
+ a = v[X];
+ b = v[Y];
+ c = cross(_initial, _final);
+}
+
+/** @brief Get the implicit line equation coefficients.
+ * Note that conversion to implicit form always causes loss of
+ * precision when dealing with lines that start far from the origin
+ * and end very close to it. It is recommended to normalize the line
+ * before converting it to implicit form.
+ * @return Vector with three values corresponding to the A, B and C
+ * coefficients of the line equation for this line. */
+std::vector<Coord> Line::coefficients() const
+{
+ std::vector<Coord> c(3);
+ coefficients(c[0], c[1], c[2]);
+ return c;
+}
+
+/** @brief Find intersection with an axis-aligned line.
+ * @param v Coordinate of the axis-aligned line
+ * @param d Which axis the coordinate is on. X means a vertical line, Y means a horizontal line.
+ * @return Time values at which this line intersects the query line. */
+std::vector<Coord> Line::roots(Coord v, Dim2 d) const {
+ std::vector<Coord> result;
+ Coord r = root(v, d);
+ if (std::isfinite(r)) {
+ result.push_back(r);
+ }
+ return result;
+}
+
+Coord Line::root(Coord v, Dim2 d) const
+{
+ assert(d == X || d == Y);
+ Point vs = vector();
+ if (vs[d] != 0) {
+ return (v - _initial[d]) / vs[d];
+ } else {
+ return nan("");
+ }
+}
+
+std::optional<LineSegment> Line::clip(Rect const &r) const
+{
+ Point v = vector();
+ // handle horizontal and vertical lines first,
+ // since the root-based code below will break for them
+ for (unsigned i = 0; i < 2; ++i) {
+ Dim2 d = (Dim2) i;
+ Dim2 o = other_dimension(d);
+ if (v[d] != 0) continue;
+ if (r[d].contains(_initial[d])) {
+ Point a, b;
+ a[o] = r[o].min();
+ b[o] = r[o].max();
+ a[d] = b[d] = _initial[d];
+ if (v[o] > 0) {
+ return LineSegment(a, b);
+ } else {
+ return LineSegment(b, a);
+ }
+ } else {
+ return std::nullopt;
+ }
+ }
+
+ Interval xpart(root(r[X].min(), X), root(r[X].max(), X));
+ Interval ypart(root(r[Y].min(), Y), root(r[Y].max(), Y));
+ if (!xpart.isFinite() || !ypart.isFinite()) {
+ return std::nullopt;
+ }
+
+ OptInterval common = xpart & ypart;
+ if (common) {
+ Point p1 = pointAt(common->min()), p2 = pointAt(common->max());
+ LineSegment result(r.clamp(p1), r.clamp(p2));
+ return result;
+ } else {
+ return std::nullopt;
+ }
+
+ /* old implementation using coefficients:
+
+ if (fabs(b) > fabs(a)) {
+ p0 = Point(r[X].min(), (-c - a*r[X].min())/b);
+ if (p0[Y] < r[Y].min())
+ p0 = Point((-c - b*r[Y].min())/a, r[Y].min());
+ if (p0[Y] > r[Y].max())
+ p0 = Point((-c - b*r[Y].max())/a, r[Y].max());
+ p1 = Point(r[X].max(), (-c - a*r[X].max())/b);
+ if (p1[Y] < r[Y].min())
+ p1 = Point((-c - b*r[Y].min())/a, r[Y].min());
+ if (p1[Y] > r[Y].max())
+ p1 = Point((-c - b*r[Y].max())/a, r[Y].max());
+ } else {
+ p0 = Point((-c - b*r[Y].min())/a, r[Y].min());
+ if (p0[X] < r[X].min())
+ p0 = Point(r[X].min(), (-c - a*r[X].min())/b);
+ if (p0[X] > r[X].max())
+ p0 = Point(r[X].max(), (-c - a*r[X].max())/b);
+ p1 = Point((-c - b*r[Y].max())/a, r[Y].max());
+ if (p1[X] < r[X].min())
+ p1 = Point(r[X].min(), (-c - a*r[X].min())/b);
+ if (p1[X] > r[X].max())
+ p1 = Point(r[X].max(), (-c - a*r[X].max())/b);
+ }
+ return LineSegment(p0, p1); */
+}
+
+/** @brief Get a time value corresponding to a point.
+ * @param p Point on the line. If the point is not on the line,
+ * the returned value will be meaningless.
+ * @return Time value t such that \f$f(t) = p\f$.
+ * @see timeAtProjection */
+Coord Line::timeAt(Point const &p) const
+{
+ Point v = vector();
+ // degenerate case
+ if (v[X] == 0 && v[Y] == 0) {
+ return 0;
+ }
+
+ // use the coordinate that will give better precision
+ if (fabs(v[X]) > fabs(v[Y])) {
+ return (p[X] - _initial[X]) / v[X];
+ } else {
+ return (p[Y] - _initial[Y]) / v[Y];
+ }
+}
+
+/** @brief Create a transformation that maps one line to another.
+ * This will return a transformation \f$A\f$ such that
+ * \f$L_1(t) \cdot A = L_2(t)\f$, where \f$L_1\f$ is this line
+ * and \f$L_2\f$ is the line passed as the parameter. The returned
+ * transformation will preserve angles. */
+Affine Line::transformTo(Line const &other) const
+{
+ Affine result = Translate(-_initial);
+ result *= Rotate(angle_between(vector(), other.vector()));
+ result *= Scale(other.vector().length() / vector().length());
+ result *= Translate(other._initial);
+ return result;
+}
+
+std::vector<ShapeIntersection> Line::intersect(Line const &other) const
+{
+ std::vector<ShapeIntersection> result;
+
+ Point v1 = vector();
+ Point v2 = other.vector();
+ Coord cp = cross(v1, v2);
+ if (cp == 0) return result;
+
+ Point odiff = other.initialPoint() - initialPoint();
+ Coord t1 = cross(odiff, v2) / cp;
+ Coord t2 = cross(odiff, v1) / cp;
+ result.emplace_back(*this, other, t1, t2);
+ return result;
+}
+
+std::vector<ShapeIntersection> Line::intersect(Ray const &r) const
+{
+ Line other(r);
+ std::vector<ShapeIntersection> result = intersect(other);
+ filter_ray_intersections(result, false, true);
+ return result;
+}
+
+std::vector<ShapeIntersection> Line::intersect(LineSegment const &ls) const
+{
+ Line other(ls);
+ std::vector<ShapeIntersection> result = intersect(other);
+ filter_line_segment_intersections(result, false, true);
+ return result;
+}
+
+
+
+void filter_line_segment_intersections(std::vector<ShapeIntersection> &xs, bool a, bool b)
+{
+ Interval unit(0, 1);
+ std::vector<ShapeIntersection>::reverse_iterator i = xs.rbegin(), last = xs.rend();
+ while (i != last) {
+ if ((a && !unit.contains(i->first)) || (b && !unit.contains(i->second))) {
+ xs.erase((++i).base());
+ } else {
+ ++i;
+ }
+ }
+}
+
+void filter_ray_intersections(std::vector<ShapeIntersection> &xs, bool a, bool b)
+{
+ Interval unit(0, 1);
+ std::vector<ShapeIntersection>::reverse_iterator i = xs.rbegin(), last = xs.rend();
+ while (i != last) {
+ if ((a && i->first < 0) || (b && i->second < 0)) {
+ xs.erase((++i).base());
+ } else {
+ ++i;
+ }
+ }
+}
+
+namespace detail
+{
+
+inline
+OptCrossing intersection_impl(Point const &v1, Point const &o1,
+ Point const &v2, Point const &o2)
+{
+ Coord cp = cross(v1, v2);
+ if (cp == 0) return OptCrossing();
+
+ Point odiff = o2 - o1;
+
+ Crossing c;
+ c.ta = cross(odiff, v2) / cp;
+ c.tb = cross(odiff, v1) / cp;
+ return c;
+}
+
+
+OptCrossing intersection_impl(Ray const& r1, Line const& l2, unsigned int i)
+{
+ using std::swap;
+
+ OptCrossing crossing =
+ intersection_impl(r1.vector(), r1.origin(),
+ l2.vector(), l2.origin() );
+
+ if (crossing) {
+ if (crossing->ta < 0) {
+ return OptCrossing();
+ } else {
+ if (i != 0) {
+ swap(crossing->ta, crossing->tb);
+ }
+ return crossing;
+ }
+ }
+ if (are_near(r1.origin(), l2)) {
+ THROW_INFINITESOLUTIONS();
+ } else {
+ return OptCrossing();
+ }
+}
+
+
+OptCrossing intersection_impl( LineSegment const& ls1,
+ Line const& l2,
+ unsigned int i )
+{
+ using std::swap;
+
+ OptCrossing crossing =
+ intersection_impl(ls1.finalPoint() - ls1.initialPoint(),
+ ls1.initialPoint(),
+ l2.vector(),
+ l2.origin() );
+
+ if (crossing) {
+ if ( crossing->getTime(0) < 0
+ || crossing->getTime(0) > 1 )
+ {
+ return OptCrossing();
+ } else {
+ if (i != 0) {
+ swap((*crossing).ta, (*crossing).tb);
+ }
+ return crossing;
+ }
+ }
+ if (are_near(ls1.initialPoint(), l2)) {
+ THROW_INFINITESOLUTIONS();
+ } else {
+ return OptCrossing();
+ }
+}
+
+
+OptCrossing intersection_impl( LineSegment const& ls1,
+ Ray const& r2,
+ unsigned int i )
+{
+ using std::swap;
+
+ Point direction = ls1.finalPoint() - ls1.initialPoint();
+ OptCrossing crossing =
+ intersection_impl( direction,
+ ls1.initialPoint(),
+ r2.vector(),
+ r2.origin() );
+
+ if (crossing) {
+ if ( (crossing->getTime(0) < 0)
+ || (crossing->getTime(0) > 1)
+ || (crossing->getTime(1) < 0) )
+ {
+ return OptCrossing();
+ } else {
+ if (i != 0) {
+ swap(crossing->ta, crossing->tb);
+ }
+ return crossing;
+ }
+ }
+
+ if ( are_near(r2.origin(), ls1) ) {
+ bool eqvs = (dot(direction, r2.vector()) > 0);
+ if ( are_near(ls1.initialPoint(), r2.origin()) && !eqvs) {
+ crossing->ta = crossing->tb = 0;
+ return crossing;
+ } else if ( are_near(ls1.finalPoint(), r2.origin()) && eqvs) {
+ if (i == 0) {
+ crossing->ta = 1;
+ crossing->tb = 0;
+ } else {
+ crossing->ta = 0;
+ crossing->tb = 1;
+ }
+ return crossing;
+ } else {
+ THROW_INFINITESOLUTIONS();
+ }
+ } else if ( are_near(ls1.initialPoint(), r2) ) {
+ THROW_INFINITESOLUTIONS();
+ } else {
+ OptCrossing no_crossing;
+ return no_crossing;
+ }
+}
+
+} // end namespace detail
+
+
+
+OptCrossing intersection(Line const& l1, Line const& l2)
+{
+ OptCrossing c = detail::intersection_impl(
+ l1.vector(), l1.origin(),
+ l2.vector(), l2.origin());
+
+ if (!c && distance(l1.origin(), l2) == 0) {
+ THROW_INFINITESOLUTIONS();
+ }
+ return c;
+}
+
+OptCrossing intersection(Ray const& r1, Ray const& r2)
+{
+ OptCrossing crossing =
+ detail::intersection_impl( r1.vector(), r1.origin(),
+ r2.vector(), r2.origin() );
+
+ if (crossing)
+ {
+ if ( crossing->ta < 0
+ || crossing->tb < 0 )
+ {
+ OptCrossing no_crossing;
+ return no_crossing;
+ }
+ else
+ {
+ return crossing;
+ }
+ }
+
+ if ( are_near(r1.origin(), r2) || are_near(r2.origin(), r1) )
+ {
+ if ( are_near(r1.origin(), r2.origin())
+ && !are_near(r1.vector(), r2.vector()) )
+ {
+ crossing->ta = crossing->tb = 0;
+ return crossing;
+ }
+ else
+ {
+ THROW_INFINITESOLUTIONS();
+ }
+ }
+ else
+ {
+ OptCrossing no_crossing;
+ return no_crossing;
+ }
+}
+
+
+OptCrossing intersection( LineSegment const& ls1, LineSegment const& ls2 )
+{
+ Point direction1 = ls1.finalPoint() - ls1.initialPoint();
+ Point direction2 = ls2.finalPoint() - ls2.initialPoint();
+ OptCrossing crossing =
+ detail::intersection_impl( direction1,
+ ls1.initialPoint(),
+ direction2,
+ ls2.initialPoint() );
+
+ if (crossing)
+ {
+ if ( crossing->getTime(0) < 0
+ || crossing->getTime(0) > 1
+ || crossing->getTime(1) < 0
+ || crossing->getTime(1) > 1 )
+ {
+ OptCrossing no_crossing;
+ return no_crossing;
+ }
+ else
+ {
+ return crossing;
+ }
+ }
+
+ bool eqvs = (dot(direction1, direction2) > 0);
+ if ( are_near(ls2.initialPoint(), ls1) )
+ {
+ if ( are_near(ls1.initialPoint(), ls2.initialPoint()) && !eqvs )
+ {
+ crossing->ta = crossing->tb = 0;
+ return crossing;
+ }
+ else if ( are_near(ls1.finalPoint(), ls2.initialPoint()) && eqvs )
+ {
+ crossing->ta = 1;
+ crossing->tb = 0;
+ return crossing;
+ }
+ else
+ {
+ THROW_INFINITESOLUTIONS();
+ }
+ }
+ else if ( are_near(ls2.finalPoint(), ls1) )
+ {
+ if ( are_near(ls1.finalPoint(), ls2.finalPoint()) && !eqvs )
+ {
+ crossing->ta = crossing->tb = 1;
+ return crossing;
+ }
+ else if ( are_near(ls1.initialPoint(), ls2.finalPoint()) && eqvs )
+ {
+ crossing->ta = 0;
+ crossing->tb = 1;
+ return crossing;
+ }
+ else
+ {
+ THROW_INFINITESOLUTIONS();
+ }
+ }
+ else
+ {
+ OptCrossing no_crossing;
+ return no_crossing;
+ }
+}
+
+Line make_angle_bisector_line(Line const& l1, Line const& l2)
+{
+ OptCrossing crossing;
+ try
+ {
+ crossing = intersection(l1, l2);
+ }
+ catch(InfiniteSolutions const &e)
+ {
+ return l1;
+ }
+ if (!crossing)
+ {
+ THROW_RANGEERROR("passed lines are parallel");
+ }
+ Point O = l1.pointAt(crossing->ta);
+ Point A = l1.pointAt(crossing->ta + 1);
+ double angle = angle_between(l1.vector(), l2.vector());
+ Point B = (angle > 0) ? l2.pointAt(crossing->tb + 1)
+ : l2.pointAt(crossing->tb - 1);
+
+ return make_angle_bisector_line(A, O, B);
+}
+
+
+
+
+} // end namespace Geom
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(substatement-open . 0))
+ indent-tabs-mode:nil
+ c-brace-offset:0
+ fill-column:99
+ End:
+ vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+*/
diff --git a/src/3rdparty/2geom/src/2geom/nearest-time.cpp b/src/3rdparty/2geom/src/2geom/nearest-time.cpp
new file mode 100644
index 0000000..e52251c
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/nearest-time.cpp
@@ -0,0 +1,322 @@
+/** @file
+ * @brief Nearest time routines for D2<SBasis> and Piecewise<D2<SBasis>>
+ *//*
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2007-2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#include <2geom/nearest-time.h>
+#include <algorithm>
+
+namespace Geom
+{
+
+Coord nearest_time(Point const &p, D2<Bezier> const &input, Coord from, Coord to)
+{
+ Interval domain(from, to);
+ bool partial = false;
+
+ if (domain.min() < 0 || domain.max() > 1) {
+ THROW_RANGEERROR("[from,to] interval out of bounds");
+ }
+
+ if (input.isConstant(0)) return from;
+
+ D2<Bezier> bez;
+ if (domain.min() != 0 || domain.max() != 1) {
+ bez = portion(input, domain) - p;
+ partial = true;
+ } else {
+ bez = input - p;
+ }
+
+ // find extrema of the function x(t)^2 + y(t)^2
+ // use the fact that (f^2)' = 2 f f'
+ // this reduces the order of the distance function by 1
+ D2<Bezier> deriv = derivative(bez);
+ std::vector<Coord> ts = (multiply(bez[X], deriv[X]) + multiply(bez[Y], deriv[Y])).roots();
+
+ Coord t = -1, mind = infinity();
+ for (double i : ts) {
+ Coord droot = L2sq(bez.valueAt(i));
+ if (droot < mind) {
+ mind = droot;
+ t = i;
+ }
+ }
+
+ // also check endpoints
+ Coord dinitial = L2sq(bez.at0());
+ Coord dfinal = L2sq(bez.at1());
+
+ if (dinitial < mind) {
+ mind = dinitial;
+ t = 0;
+ }
+ if (dfinal < mind) {
+ //mind = dfinal;
+ t = 1;
+ }
+
+ if (partial) {
+ t = domain.valueAt(t);
+ }
+ return t;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// D2<SBasis> versions
+
+/*
+ * Return the parameter t of the nearest time value on the portion of the curve "c",
+ * related to the interval [from, to], to the point "p".
+ * The needed curve derivative "dc" is passed as parameter.
+ * The function return the first nearest time value to "p" that is found.
+ */
+
+double nearest_time(Point const& p,
+ D2<SBasis> const& c,
+ D2<SBasis> const& dc,
+ double from, double to )
+{
+ if ( from > to ) std::swap(from, to);
+ if ( from < 0 || to > 1 )
+ {
+ THROW_RANGEERROR("[from,to] interval out of bounds");
+ }
+ if (c.isConstant()) return from;
+ SBasis dd = dot(c - p, dc);
+ //std::cout << dd << std::endl;
+ std::vector<double> zeros = Geom::roots(dd);
+
+ double closest = from;
+ double min_dist_sq = L2sq(c(from) - p);
+ for (double zero : zeros)
+ {
+ double distsq = L2sq(c(zero) - p);
+ if ( min_dist_sq > L2sq(c(zero) - p) )
+ {
+ closest = zero;
+ min_dist_sq = distsq;
+ }
+ }
+ if ( min_dist_sq > L2sq( c(to) - p ) )
+ closest = to;
+ return closest;
+
+}
+
+/*
+ * Return the parameters t of all the nearest points on the portion of
+ * the curve "c", related to the interval [from, to], to the point "p".
+ * The needed curve derivative "dc" is passed as parameter.
+ */
+
+std::vector<double>
+all_nearest_times(Point const &p,
+ D2<SBasis> const &c,
+ D2<SBasis> const &dc,
+ double from, double to)
+{
+ if (from > to) {
+ std::swap(from, to);
+ }
+ if (from < 0 || to > 1) {
+ THROW_RANGEERROR("[from,to] interval out of bounds");
+ }
+
+ std::vector<double> result;
+ if (c.isConstant()) {
+ result.push_back(from);
+ return result;
+ }
+ SBasis dd = dot(c - p, dc);
+
+ std::vector<double> zeros = Geom::roots(dd);
+ std::vector<double> candidates;
+ candidates.push_back(from);
+ candidates.insert(candidates.end(), zeros.begin(), zeros.end());
+ candidates.push_back(to);
+ std::vector<double> distsq;
+ distsq.reserve(candidates.size());
+ for (double candidate : candidates) {
+ distsq.push_back(L2sq(c(candidate) - p));
+ }
+ unsigned closest = 0;
+ double dsq = distsq[0];
+ for (unsigned i = 1; i < candidates.size(); ++i) {
+ if (dsq > distsq[i]) {
+ closest = i;
+ dsq = distsq[i];
+ }
+ }
+ for (unsigned i = 0; i < candidates.size(); ++i) {
+ if (distsq[closest] == distsq[i]) {
+ result.push_back(candidates[i]);
+ }
+ }
+ return result;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Piecewise< D2<SBasis> > versions
+
+
+double nearest_time(Point const &p,
+ Piecewise< D2<SBasis> > const &c,
+ double from, double to)
+{
+ if (from > to) std::swap(from, to);
+ if (from < c.cuts[0] || to > c.cuts[c.size()]) {
+ THROW_RANGEERROR("[from,to] interval out of bounds");
+ }
+
+ unsigned si = c.segN(from);
+ unsigned ei = c.segN(to);
+ if (si == ei) {
+ double nearest =
+ nearest_time(p, c[si], c.segT(from, si), c.segT(to, si));
+ return c.mapToDomain(nearest, si);
+ }
+
+ double t;
+ double nearest = nearest_time(p, c[si], c.segT(from, si));
+ unsigned int ni = si;
+ double dsq;
+ double mindistsq = distanceSq(p, c[si](nearest));
+ Rect bb;
+ for (unsigned i = si + 1; i < ei; ++i) {
+ bb = *bounds_fast(c[i]);
+ dsq = distanceSq(p, bb);
+ if ( mindistsq <= dsq ) continue;
+
+ t = nearest_time(p, c[i]);
+ dsq = distanceSq(p, c[i](t));
+ if (mindistsq > dsq) {
+ nearest = t;
+ ni = i;
+ mindistsq = dsq;
+ }
+ }
+ bb = *bounds_fast(c[ei]);
+ dsq = distanceSq(p, bb);
+ if (mindistsq > dsq) {
+ t = nearest_time(p, c[ei], 0, c.segT(to, ei));
+ dsq = distanceSq(p, c[ei](t));
+ if (mindistsq > dsq) {
+ nearest = t;
+ ni = ei;
+ }
+ }
+ return c.mapToDomain(nearest, ni);
+}
+
+std::vector<double>
+all_nearest_times(Point const &p,
+ Piecewise< D2<SBasis> > const &c,
+ double from, double to)
+{
+ if (from > to) {
+ std::swap(from, to);
+ }
+ if (from < c.cuts[0] || to > c.cuts[c.size()]) {
+ THROW_RANGEERROR("[from,to] interval out of bounds");
+ }
+
+ unsigned si = c.segN(from);
+ unsigned ei = c.segN(to);
+ if ( si == ei )
+ {
+ std::vector<double> all_nearest =
+ all_nearest_times(p, c[si], c.segT(from, si), c.segT(to, si));
+ for (double & i : all_nearest)
+ {
+ i = c.mapToDomain(i, si);
+ }
+ return all_nearest;
+ }
+ std::vector<double> all_t;
+ std::vector< std::vector<double> > all_np;
+ all_np.push_back( all_nearest_times(p, c[si], c.segT(from, si)) );
+ std::vector<unsigned> ni;
+ ni.push_back(si);
+ double dsq;
+ double mindistsq = distanceSq( p, c[si](all_np.front().front()) );
+ Rect bb;
+
+ for (unsigned i = si + 1; i < ei; ++i) {
+ bb = *bounds_fast(c[i]);
+ dsq = distanceSq(p, bb);
+ if ( mindistsq < dsq ) continue;
+ all_t = all_nearest_times(p, c[i]);
+ dsq = distanceSq( p, c[i](all_t.front()) );
+ if ( mindistsq > dsq )
+ {
+ all_np.clear();
+ all_np.push_back(all_t);
+ ni.clear();
+ ni.push_back(i);
+ mindistsq = dsq;
+ }
+ else if ( mindistsq == dsq )
+ {
+ all_np.push_back(all_t);
+ ni.push_back(i);
+ }
+ }
+ bb = *bounds_fast(c[ei]);
+ dsq = distanceSq(p, bb);
+ if (mindistsq >= dsq) {
+ all_t = all_nearest_times(p, c[ei], 0, c.segT(to, ei));
+ dsq = distanceSq( p, c[ei](all_t.front()) );
+ if (mindistsq > dsq) {
+ for (double & i : all_t) {
+ i = c.mapToDomain(i, ei);
+ }
+ return all_t;
+ } else if (mindistsq == dsq) {
+ all_np.push_back(all_t);
+ ni.push_back(ei);
+ }
+ }
+ std::vector<double> all_nearest;
+ for (unsigned i = 0; i < all_np.size(); ++i) {
+ for (unsigned int j = 0; j < all_np[i].size(); ++j) {
+ all_nearest.push_back( c.mapToDomain(all_np[i][j], ni[i]) );
+ }
+ }
+ all_nearest.erase(std::unique(all_nearest.begin(), all_nearest.end()),
+ all_nearest.end());
+ return all_nearest;
+}
+
+} // end namespace Geom
+
+
diff --git a/src/3rdparty/2geom/src/2geom/numeric/matrix.cpp b/src/3rdparty/2geom/src/2geom/numeric/matrix.cpp
new file mode 100644
index 0000000..98ff3b6
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/numeric/matrix.cpp
@@ -0,0 +1,154 @@
+/*
+ * Matrix, MatrixView, ConstMatrixView classes wrap the gsl matrix routines;
+ * "views" mimic the semantic of C++ references: any operation performed
+ * on a "view" is actually performed on the "viewed object"
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#include <2geom/numeric/matrix.h>
+#include <2geom/numeric/vector.h>
+
+
+namespace Geom { namespace NL {
+
+Vector operator*( detail::BaseMatrixImpl const& A,
+ detail::BaseVectorImpl const& v )
+{
+ assert(A.columns() == v.size());
+
+ Vector result(A.rows(), 0.0);
+ for (size_t i = 0; i < A.rows(); ++i)
+ for (size_t j = 0; j < A.columns(); ++j)
+ result[i] += A(i,j) * v[j];
+
+ return result;
+}
+
+Matrix operator*( detail::BaseMatrixImpl const& A,
+ detail::BaseMatrixImpl const& B )
+{
+ assert(A.columns() == B.rows());
+
+ Matrix C(A.rows(), B.columns(), 0.0);
+ for (size_t i = 0; i < C.rows(); ++i)
+ for (size_t j = 0; j < C.columns(); ++j)
+ for (size_t k = 0; k < A.columns(); ++k)
+ C(i,j) += A(i,k) * B(k, j);
+
+ return C;
+}
+
+Matrix pseudo_inverse(detail::BaseMatrixImpl const& A)
+{
+
+ Matrix U(A);
+ Matrix V(A.columns(), A.columns());
+ Vector s(A.columns());
+ gsl_vector* work = gsl_vector_alloc(A.columns());
+
+ gsl_linalg_SV_decomp( U.get_gsl_matrix(),
+ V.get_gsl_matrix(),
+ s.get_gsl_vector(),
+ work );
+
+ Matrix P(A.columns(), A.rows(), 0.0);
+
+ int sz = s.size();
+ while ( sz-- > 0 && s[sz] == 0 ) {}
+ ++sz;
+ if (sz == 0) return P;
+ VectorView sv(s, sz);
+
+ for (size_t i = 0; i < sv.size(); ++i)
+ {
+ VectorView v = V.column_view(i);
+ v.scale(1/sv[i]);
+ for (size_t h = 0; h < P.rows(); ++h)
+ for (size_t k = 0; k < P.columns(); ++k)
+ P(h,k) += V(h,i) * U(k,i);
+ }
+
+ return P;
+}
+
+
+double trace (detail::BaseMatrixImpl const& A)
+{
+ if (A.rows() != A.columns())
+ {
+ THROW_RANGEERROR ("NL::Matrix: computing trace: "
+ "rows() != columns()");
+ }
+ double t = 0;
+ for (size_t i = 0; i < A.rows(); ++i)
+ {
+ t += A(i,i);
+ }
+ return t;
+}
+
+
+double det (detail::BaseMatrixImpl const& A)
+{
+ if (A.rows() != A.columns())
+ {
+ THROW_RANGEERROR ("NL::Matrix: computing determinant: "
+ "rows() != columns()");
+ }
+
+ Matrix LU(A);
+ int s;
+ gsl_permutation * p = gsl_permutation_alloc(LU.rows());
+ gsl_linalg_LU_decomp (LU.get_gsl_matrix(), p, &s);
+
+ double t = 1;
+ for (size_t i = 0; i < LU.rows(); ++i)
+ {
+ t *= LU(i,i);
+ }
+
+ gsl_permutation_free(p);
+ return t;
+}
+
+
+} } // end namespaces
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/orphan-code/arc-length.cpp b/src/3rdparty/2geom/src/2geom/orphan-code/arc-length.cpp
new file mode 100644
index 0000000..3f72862
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/orphan-code/arc-length.cpp
@@ -0,0 +1,292 @@
+/*
+ * arc-length.cpp
+ *
+ * Copyright 2006 Nathan Hurst <njh@mail.csse.monash.edu.au>
+ * Copyright 2006 Michael G. Sloan <mgsloan@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <2geom/arc-length.h>
+#include <2geom/bezier-utils.h>
+#include <2geom/polynomial.h>
+using namespace Geom;
+
+/** Calculates the length of a cubic element through subdivision.
+ * The 'tol' parameter is the maximum error allowed. This is used to subdivide the curve where necessary.
+ */
+double cubic_length_subdividing(Path::Elem const & e, double tol) {
+ Point v[3];
+ for(int i = 0; i < 3; i++)
+ v[i] = e[i+1] - e[0];
+ Point orth = v[2]; // unit normal to path line
+ rot90(orth);
+ orth.normalize();
+ double err = fabs(dot(orth, v[1])) + fabs(dot(orth, v[0]));
+ if(err < tol) {
+ return distance(e.first(), e.last()); // approximately a line
+ } else {
+ Point mid[3];
+ double result;
+ for(int i = 0; i < 3; i++)
+ mid[i] = lerp(0.5, e[i], e[i+1]);
+ Point midmid[2];
+ for(int i = 0; i < 2; i++)
+ midmid[i] = lerp(0.5, mid[i], mid[i+1]);
+ Point midmidmid = lerp(0.5, midmid[0], midmid[1]);
+ {
+ Point curve[4] = {e[0], mid[0], midmid[0], midmidmid};
+ Path::Elem e0(cubicto, std::vector<Point>::const_iterator(curve), std::vector<Point>::const_iterator(curve) + 4);
+ result = cubic_length_subdividing(e0, tol);
+ } {
+ Point curve[4] = {midmidmid, midmid[1], mid[2], e[3]};
+ Path::Elem e1(cubicto, std::vector<Point>::const_iterator(curve), std::vector<Point>::const_iterator(curve) + 4);
+ return result + cubic_length_subdividing(e1, tol);
+ }
+ }
+}
+
+/** Calculates the length of a path through iteration and subsequent subdivision.
+ * Currently handles cubic curves and lines.
+ * The 'tol' parameter is the maximum error allowed. This is used to subdivide the curve where necessary.
+ */
+double arc_length_subdividing(Path const & p, double tol) {
+ double result = 0;
+
+ for(Path::const_iterator iter(p.begin()), end(p.end()); iter != end; ++iter) {
+ if(dynamic_cast<LineTo *>(iter.cmd()))
+ result += distance((*iter).first(), (*iter).last());
+ else if(dynamic_cast<CubicTo *>(iter.cmd()))
+ result += cubic_length_subdividing(*iter, tol);
+ else
+ ;
+ }
+
+ return result;
+}
+
+
+#ifdef HAVE_GSL
+#include <gsl/gsl_integration.h>
+static double poly_length_integrating(double t, void* param) {
+ Poly* pc = (Poly*)param;
+ return hypot(pc[0].eval(t), pc[1].eval(t));
+}
+
+/** Calculates the length of a path Element through gsl integration.
+ \param pe the Element.
+ \param t the parametric input 0 to 1 which specifies the amount of the curve to use.
+ \param tol the maximum error allowed.
+ \param result variable to be incremented with the length of the path
+ \param abs_error variable to be incremented with the estimated error
+*/
+void arc_length_integrating(Path::Elem pe, double t, double tol, double &result, double &abs_error) {
+ if(dynamic_cast<LineTo *>(iter.cmd()))
+ result += distance(pe.first(), pe.last()) * t;
+ else if(dynamic_cast<QuadTo *>(iter.cmd()) ||
+ dynamic_cast<CubicTo *>(iter.cmd())) {
+ Poly B[2] = {get_parametric_poly(pe, X), get_parametric_poly(pe, Y)};
+ for(int i = 0; i < 2; i++)
+ B[i] = derivative(B[i]);
+
+ gsl_function F;
+ gsl_integration_workspace * w
+ = gsl_integration_workspace_alloc (20);
+ F.function = &poly_length_integrating;
+ F.params = (void*)B;
+ double quad_result, err;
+ /* We could probably use the non adaptive code here if we removed any cusps first. */
+ int returncode =
+ gsl_integration_qag (&F, 0, t, 0, tol, 20,
+ GSL_INTEG_GAUSS21, w, &quad_result, &err);
+
+ abs_error += err;
+ result += quad_result;
+ } else
+ return;
+}
+
+/** Calculates the length of a Path through gsl integration. The parameter 'tol' is the maximum error allowed. */
+double arc_length_integrating(Path const & p, double tol) {
+ double result = 0, abserr = 0;
+
+ for(Path::const_iterator iter(p.begin()), end(p.end()); iter != end; ++iter) {
+ arc_length_integrating(*iter, 1.0, tol, result, abserr);
+ }
+ //printf("got %g with err %g\n", result, abserr);
+
+ return result;
+}
+
+/** Calculates the arc length to a specific location on the path. The parameter 'tol' is the maximum error allowed. */
+double arc_length_integrating(Path const & p, Path::Location const & pl, double tol) {
+ double result = 0, abserr = 0;
+ ptrdiff_t offset = pl.it - p.begin();
+
+ assert(offset >= 0);
+ assert(offset < p.size());
+
+ for(Path::const_iterator iter(p.begin()), end(p.end());
+ (iter != pl.it); ++iter) {
+ arc_length_integrating(*iter, 1.0, tol, result, abserr);
+ }
+ arc_length_integrating(*pl.it, pl.t, tol, result, abserr);
+
+ return result;
+}
+
+/* We use a somewhat surprising result for this that s'(t) = |p'(t)|
+ Thus, we can use a derivative based root finder.
+*/
+
+#include <stdio.h>
+#include <gsl/gsl_errno.h>
+#include <gsl/gsl_math.h>
+#include <gsl/gsl_roots.h>
+
+struct arc_length_params
+{
+ Path::Elem pe;
+ double s,tol, result, abs_error;
+ double left, right;
+};
+
+double
+arc_length (double t, void *params)
+{
+ struct arc_length_params *p
+ = (struct arc_length_params *) params;
+
+ double result = 0, abs_error = 0;
+ if(t < 0) t = 0;
+ if(t > 1) t = 1;
+ if(!((t >= 0) && (t <= 1))) {
+ printf("t = %g\n", t);
+ }
+ assert((t >= 0) && (t <= 1));
+ arc_length_integrating(p->pe, t, p->tol, result, abs_error);
+ return result - p->s ;
+}
+
+double
+arc_length_deriv (double t, void *params)
+{
+ struct arc_length_params *p
+ = (struct arc_length_params *) params;
+
+ Point pos, tgt, acc;
+ p->pe.point_tangent_acc_at(t, pos, tgt, acc);
+ return L2(tgt);
+}
+
+void
+arc_length_fdf (double t, void *params,
+ double *y, double *dy)
+{
+ *y = arc_length(t, params);
+ *dy = arc_length_deriv(t, params);
+}
+
+double polish_brent(double t, arc_length_params &alp) {
+ int status;
+ int iter = 0, max_iter = 10;
+ const gsl_root_fsolver_type *T;
+ gsl_root_fsolver *solver;
+ double x_lo = 0.0, x_hi = 1.0;
+ gsl_function F;
+
+ F.function = &arc_length;
+ F.params = &alp;
+
+ T = gsl_root_fsolver_brent;
+ solver = gsl_root_fsolver_alloc (T);
+ gsl_root_fsolver_set (solver, &F, x_lo, x_hi);
+
+ do
+ {
+ iter++;
+ status = gsl_root_fsolver_iterate (solver);
+ t = gsl_root_fsolver_root (solver);
+ x_lo = gsl_root_fsolver_x_lower (solver);
+ x_hi = gsl_root_fsolver_x_upper (solver);
+ status = gsl_root_test_interval (x_lo, x_hi,
+ 0, alp.tol);
+
+ //if (status == GSL_SUCCESS)
+ // printf ("Converged:\n");
+
+ }
+ while (status == GSL_CONTINUE && iter < max_iter);
+ return t;
+}
+
+double polish (double t, arc_length_params &alp) {
+ int status;
+ int iter = 0, max_iter = 5;
+ const gsl_root_fdfsolver_type *T;
+ gsl_root_fdfsolver *solver;
+ double t0;
+ gsl_function_fdf FDF;
+
+ FDF.f = &arc_length;
+ FDF.df = &arc_length_deriv;
+ FDF.fdf = &arc_length_fdf;
+ FDF.params = &alp;
+
+ T = gsl_root_fdfsolver_newton;
+ solver = gsl_root_fdfsolver_alloc (T);
+ gsl_root_fdfsolver_set (solver, &FDF, t);
+
+ do
+ {
+ iter++;
+ status = gsl_root_fdfsolver_iterate (solver);
+ t0 = t;
+ t = gsl_root_fdfsolver_root (solver);
+ status = gsl_root_test_delta (t, t0, 0, alp.tol);
+
+ if (status == GSL_SUCCESS)
+ ;//printf ("Converged:\n");
+
+ printf ("%5d %10.7f %+10.7f\n",
+ iter, t, t - t0);
+ }
+ while (status == GSL_CONTINUE && iter < max_iter);
+ return t;
+}
+
+
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/orphan-code/chebyshev.cpp b/src/3rdparty/2geom/src/2geom/orphan-code/chebyshev.cpp
new file mode 100644
index 0000000..c886daf
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/orphan-code/chebyshev.cpp
@@ -0,0 +1,126 @@
+#include <2geom/chebyshev.h>
+
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-poly.h>
+
+#include <vector>
+using std::vector;
+
+#include <gsl/gsl_math.h>
+#include <gsl/gsl_chebyshev.h>
+
+namespace Geom{
+
+SBasis cheb(unsigned n) {
+ static std::vector<SBasis> basis;
+ if(basis.empty()) {
+ basis.push_back(Linear(1,1));
+ basis.push_back(Linear(0,1));
+ }
+ for(unsigned i = basis.size(); i <= n; i++) {
+ basis.push_back(Linear(0,2)*basis[i-1] - basis[i-2]);
+ }
+
+ return basis[n];
+}
+
+SBasis cheb_series(unsigned n, double* cheb_coeff) {
+ SBasis r;
+ for(unsigned i = 0; i < n; i++) {
+ double cof = cheb_coeff[i];
+ //if(i == 0)
+ //cof /= 2;
+ r += cheb(i)*cof;
+ }
+
+ return r;
+}
+
+SBasis clenshaw_series(unsigned m, double* cheb_coeff) {
+ /** b_n = a_n
+ b_n-1 = 2*x*b_n + a_n-1
+ b_n-k = 2*x*b_{n-k+1} + a_{n-k} - b_{n - k + 2}
+ b_0 = x*b_1 + a_0 - b_2
+ */
+
+ double a = -1, b = 1;
+ SBasis d, dd;
+ SBasis y = (Linear(0, 2) - (a+b)) / (b-a);
+ SBasis y2 = 2*y;
+ for(int j = m - 1; j >= 1; j--) {
+ SBasis sv = d;
+ d = y2*d - dd + cheb_coeff[j];
+ dd = sv;
+ }
+
+ return y*d - dd + 0.5*cheb_coeff[0];
+}
+
+SBasis chebyshev_approximant (double (*f)(double,void*), int order, Interval in, void* p) {
+ gsl_cheb_series *cs = gsl_cheb_alloc (order+2);
+
+ gsl_function F;
+
+ F.function = f;
+ F.params = p;
+
+ gsl_cheb_init (cs, &F, in[0], in[1]);
+
+ SBasis r = compose(clenshaw_series(order, cs->c), Linear(-1,1));
+
+ gsl_cheb_free (cs);
+ return r;
+}
+
+struct wrap {
+ double (*f)(double,void*);
+ void* pp;
+ double fa, fb;
+ Interval in;
+};
+
+double f_interp(double x, void* p) {
+ struct wrap *wr = (struct wrap *)p;
+ double z = (x - wr->in[0]) / (wr->in[1] - wr->in[0]);
+ return (wr->f)(x, wr->pp) - ((1 - z)*wr->fa + z*wr->fb);
+}
+
+SBasis chebyshev_approximant_interpolating (double (*f)(double,void*),
+ int order, Interval in, void* p) {
+ double fa = f(in[0], p);
+ double fb = f(in[1], p);
+ struct wrap wr;
+ wr.fa = fa;
+ wr.fb = fb;
+ wr.in = in;
+ printf("%f %f\n", fa, fb);
+ wr.f = f;
+ wr.pp = p;
+ return compose(Linear(in[0], in[1]), Linear(fa, fb)) + chebyshev_approximant(f_interp, order, in, &wr) + Linear(fa, fb);
+}
+
+SBasis chebyshev(unsigned n) {
+ static std::vector<SBasis> basis;
+ if(basis.empty()) {
+ basis.push_back(Linear(1,1));
+ basis.push_back(Linear(0,1));
+ }
+ for(unsigned i = basis.size(); i <= n; i++) {
+ basis.push_back(Linear(0,2)*basis[i-1] - basis[i-2]);
+ }
+
+ return basis[n];
+}
+
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/orphan-code/intersection-by-bezier-clipping.cpp b/src/3rdparty/2geom/src/2geom/orphan-code/intersection-by-bezier-clipping.cpp
new file mode 100644
index 0000000..c55f623
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/orphan-code/intersection-by-bezier-clipping.cpp
@@ -0,0 +1,560 @@
+
+/*
+ * Find intersecions between two Bezier curves.
+ * The intersection points are found by using Bezier clipping.
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+
+
+
+#include <2geom/basic-intersection.h>
+#include <2geom/bezier.h>
+#include <2geom/interval.h>
+#include <2geom/convex-hull.h>
+
+
+#include <vector>
+#include <utility>
+#include <iomanip>
+
+
+namespace Geom {
+
+namespace detail { namespace bezier_clipping {
+
+
+////////////////////////////////////////////////////////////////////////////////
+// for debugging
+//
+
+inline
+void print(std::vector<Point> const& cp)
+{
+ for (size_t i = 0; i < cp.size(); ++i)
+ std::cerr << i << " : " << cp[i] << std::endl;
+}
+
+template< class charT >
+inline
+std::basic_ostream<charT> &
+operator<< (std::basic_ostream<charT> & os, const Interval & I)
+{
+ os << "[" << I.min() << ", " << I.max() << "]";
+ return os;
+}
+
+inline
+double angle (std::vector<Point> const& A)
+{
+ size_t n = A.size() -1;
+ double a = std::atan2(A[n][Y] - A[0][Y], A[n][X] - A[0][X]);
+ return (180 * a / M_PI);
+}
+
+inline
+size_t get_precision(Interval const& I)
+{
+ double d = I.extent();
+ double e = 1, p = 1;
+ size_t n = 0;
+ while (n < 16 && (are_near(d, 0, e)))
+ {
+ p *= 10;
+ e = 1 /p;
+ ++n;
+ }
+ return n;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+/*
+ * return true if all the Bezier curve control points are near,
+ * false otherwise
+ */
+inline
+bool is_constant(std::vector<Point> const& A, double precision = EPSILON)
+{
+ for (unsigned int i = 1; i < A.size(); ++i)
+ {
+ if(!are_near(A[i], A[0], precision))
+ return false;
+ }
+ return true;
+}
+
+/*
+ * Make up an orientation line using the control points c[i] and c[j]
+ * the line is returned in the output parameter "l" in the form of a 3 element
+ * vector : l[0] * x + l[1] * y + l[2] == 0; the line is normalized.
+ */
+inline
+void orientation_line (std::vector<double> & l,
+ std::vector<Point> const& c,
+ size_t i, size_t j)
+{
+ l[0] = c[j][Y] - c[i][Y];
+ l[1] = c[i][X] - c[j][X];
+ l[2] = cross(c[i], c[j]);
+ double length = std::sqrt(l[0] * l[0] + l[1] * l[1]);
+ assert (length != 0);
+ l[0] /= length;
+ l[1] /= length;
+ l[2] /= length;
+}
+
+/*
+ * Pick up an orientation line for the Bezier curve "c" and return it in
+ * the output parameter "l"
+ */
+inline
+void pick_orientation_line (std::vector<double> & l,
+ std::vector<Point> const& c)
+{
+ size_t i = c.size();
+ while (--i > 0 && are_near(c[0], c[i]))
+ {}
+ if (i == 0)
+ {
+ // this should never happen because when a new curve portion is created
+ // we check that it is not constant;
+ // however this requires that the precision used in the is_constant
+ // routine has to be the same used here in the are_near test
+ assert(i != 0);
+ }
+ orientation_line(l, c, 0, i);
+ //std::cerr << "i = " << i << std::endl;
+}
+
+/*
+ * Compute the signed distance of the point "P" from the normalized line l
+ */
+inline
+double distance (Point const& P, std::vector<double> const& l)
+{
+ return l[X] * P[X] + l[Y] * P[Y] + l[2];
+}
+
+/*
+ * Compute the min and max distance of the control points of the Bezier
+ * curve "c" from the normalized orientation line "l".
+ * This bounds are returned through the output Interval parameter"bound".
+ */
+inline
+void fat_line_bounds (Interval& bound,
+ std::vector<Point> const& c,
+ std::vector<double> const& l)
+{
+ bound[0] = 0;
+ bound[1] = 0;
+ double d;
+ for (size_t i = 0; i < c.size(); ++i)
+ {
+ d = distance(c[i], l);
+ if (bound[0] > d) bound[0] = d;
+ if (bound[1] < d) bound[1] = d;
+ }
+}
+
+/*
+ * return the x component of the intersection point between the line
+ * passing through points p1, p2 and the line Y = "y"
+ */
+inline
+double intersect (Point const& p1, Point const& p2, double y)
+{
+ // we are sure that p2[Y] != p1[Y] because this routine is called
+ // only when the lower or the upper bound is crossed
+ double dy = (p2[Y] - p1[Y]);
+ double s = (y - p1[Y]) / dy;
+ return (p2[X]-p1[X])*s + p1[X];
+}
+
+/*
+ * Clip the Bezier curve "B" wrt the fat line defined by the orientation
+ * line "l" and the interval range "bound", the new parameter interval for
+ * the clipped curve is returned through the output parameter "dom"
+ */
+void clip (Interval& dom,
+ std::vector<Point> const& B,
+ std::vector<double> const& l,
+ Interval const& bound)
+{
+ double n = B.size() - 1; // number of sub-intervals
+ std::vector<Point> D; // distance curve control points
+ D.reserve (B.size());
+ double d;
+ for (size_t i = 0; i < B.size(); ++i)
+ {
+ d = distance (B[i], l);
+ D.push_back (Point(i/n, d));
+ }
+ //print(D);
+ ConvexHull chD(D);
+ std::vector<Point> & p = chD.boundary; // convex hull vertices
+
+ //print(p);
+
+ bool plower, phigher;
+ bool clower, chigher;
+ double t, tmin = 1, tmax = 0;
+ //std::cerr << "bound : " << bound << std::endl;
+
+ plower = (p[0][Y] < bound.min());
+ phigher = (p[0][Y] > bound.max());
+ if (!(plower || phigher)) // inside the fat line
+ {
+ if (tmin > p[0][X]) tmin = p[0][X];
+ if (tmax < p[0][X]) tmax = p[0][X];
+ //std::cerr << "0 : inside " << p[0]
+ // << " : tmin = " << tmin << ", tmax = " << tmax << std::endl;
+ }
+
+ for (size_t i = 1; i < p.size(); ++i)
+ {
+ clower = (p[i][Y] < bound.min());
+ chigher = (p[i][Y] > bound.max());
+ if (!(clower || chigher)) // inside the fat line
+ {
+ if (tmin > p[i][X]) tmin = p[i][X];
+ if (tmax < p[i][X]) tmax = p[i][X];
+ //std::cerr << i << " : inside " << p[i]
+ // << " : tmin = " << tmin << ", tmax = " << tmax
+ // << std::endl;
+ }
+ if (clower != plower) // cross the lower bound
+ {
+ t = intersect(p[i-1], p[i], bound.min());
+ if (tmin > t) tmin = t;
+ if (tmax < t) tmax = t;
+ plower = clower;
+ //std::cerr << i << " : lower " << p[i]
+ // << " : tmin = " << tmin << ", tmax = " << tmax
+ // << std::endl;
+ }
+ if (chigher != phigher) // cross the upper bound
+ {
+ t = intersect(p[i-1], p[i], bound.max());
+ if (tmin > t) tmin = t;
+ if (tmax < t) tmax = t;
+ phigher = chigher;
+ //std::cerr << i << " : higher " << p[i]
+ // << " : tmin = " << tmin << ", tmax = " << tmax
+ // << std::endl;
+ }
+ }
+
+ // we have to test the closing segment for intersection
+ size_t last = p.size() - 1;
+ clower = (p[0][Y] < bound.min());
+ chigher = (p[0][Y] > bound.max());
+ if (clower != plower) // cross the lower bound
+ {
+ t = intersect(p[last], p[0], bound.min());
+ if (tmin > t) tmin = t;
+ if (tmax < t) tmax = t;
+ //std::cerr << "0 : lower " << p[0]
+ // << " : tmin = " << tmin << ", tmax = " << tmax << std::endl;
+ }
+ if (chigher != phigher) // cross the upper bound
+ {
+ t = intersect(p[last], p[0], bound.max());
+ if (tmin > t) tmin = t;
+ if (tmax < t) tmax = t;
+ //std::cerr << "0 : higher " << p[0]
+ // << " : tmin = " << tmin << ", tmax = " << tmax << std::endl;
+ }
+
+ dom[0] = tmin;
+ dom[1] = tmax;
+}
+
+/*
+ * Compute the portion of the Bezier curve "B" wrt the interval "I"
+ */
+void portion (std::vector<Point> & B, Interval const& I)
+{
+ Bezier::Order bo(B.size()-1);
+ Bezier Bx(bo), By(bo);
+ for (size_t i = 0; i < B.size(); ++i)
+ {
+ Bx[i] = B[i][X];
+ By[i] = B[i][Y];
+ }
+ Bx = portion(Bx, I.min(), I.max());
+ By = portion(By, I.min(), I.max());
+ assert (Bx.size() == By.size());
+ B.resize(Bx.size());
+ for (size_t i = 0; i < Bx.size(); ++i)
+ {
+ B[i][X] = Bx[i];
+ B[i][Y] = By[i];
+ }
+}
+
+/*
+ * Map the sub-interval I in [0,1] into the interval J and assign it to J
+ */
+inline
+void map_to(Interval & J, Interval const& I)
+{
+ double length = J.extent();
+ J[1] = I.max() * length + J[0];
+ J[0] = I.min() * length + J[0];
+}
+
+/*
+ * The interval [1,0] is used to represent the empty interval, this routine
+ * is just an helper function for creating such an interval
+ */
+inline
+Interval make_empty_interval()
+{
+ Interval I(0);
+ I[0] = 1;
+ return I;
+}
+
+
+
+
+const double MAX_PRECISION = 1e-8;
+const double MIN_CLIPPED_SIZE_THRESHOLD = 0.8;
+const Interval UNIT_INTERVAL(0,1);
+const Interval EMPTY_INTERVAL = make_empty_interval();
+const Interval H1_INTERVAL(0, 0.5);
+const Interval H2_INTERVAL(0.5 + MAX_PRECISION, 1.0);
+
+/*
+ * intersection
+ *
+ * input:
+ * A, B: control point sets of two bezier curves
+ * domA, domB: real parameter intervals of the two curves
+ * precision: required computational precision of the returned parameter ranges
+ * output:
+ * domsA, domsB: sets of parameter intervals describing an intersection point
+ *
+ * The parameter intervals are computed by using a Bezier clipping algorithm,
+ * in case the clipping doesn't shrink the initial interval more than 20%,
+ * a subdivision step is performed.
+ * If during the computation one of the two curve interval length becomes less
+ * than MAX_PRECISION the routine exits independently by the precision reached
+ * in the computation of the other curve interval.
+ */
+void intersection (std::vector<Interval>& domsA,
+ std::vector<Interval>& domsB,
+ std::vector<Point> const& A,
+ std::vector<Point> const& B,
+ Interval const& domA,
+ Interval const& domB,
+ double precision)
+{
+// std::cerr << ">> curve subdision performed <<" << std::endl;
+// std::cerr << "dom(A) : " << domA << std::endl;
+// std::cerr << "dom(B) : " << domB << std::endl;
+// std::cerr << "angle(A) : " << angle(A) << std::endl;
+// std::cerr << "angle(B) : " << angle(B) << std::endl;
+
+
+ if (precision < MAX_PRECISION)
+ precision = MAX_PRECISION;
+
+ std::vector<Point> pA = A;
+ std::vector<Point> pB = B;
+ std::vector<Point>* C1 = &pA;
+ std::vector<Point>* C2 = &pB;
+
+ Interval dompA = domA;
+ Interval dompB = domB;
+ Interval* dom1 = &dompA;
+ Interval* dom2 = &dompB;
+
+ std::vector<double> bl(3);
+ Interval bound, dom;
+
+
+ size_t iter = 0;
+ while (++iter < 100
+ && (dompA.extent() >= precision || dompB.extent() >= precision))
+ {
+// std::cerr << "iter: " << iter << std::endl;
+
+ pick_orientation_line(bl, *C1);
+ fat_line_bounds(bound, *C1, bl);
+ clip(dom, *C2, bl, bound);
+
+ // [1,0] is utilized to represent an empty interval
+ if (dom == EMPTY_INTERVAL)
+ {
+// std::cerr << "dom: empty" << std::endl;
+ return;
+ }
+// std::cerr << "dom : " << dom << std::endl;
+
+ // all other cases where dom[0] > dom[1] are invalid
+ if (dom.min() > dom.max())
+ {
+ assert(dom.min() < dom.max());
+ }
+
+ map_to(*dom2, dom);
+
+ // it's better to stop before losing computational precision
+ if (dom2->extent() <= MAX_PRECISION)
+ {
+// std::cerr << "beyond max precision limit" << std::endl;
+ break;
+ }
+
+ portion(*C2, dom);
+ if (is_constant(*C2))
+ {
+// std::cerr << "new curve portion is constant" << std::endl;
+ break;
+ }
+ // if we have clipped less than 20% than we need to subdive the curve
+ // with the largest domain into two sub-curves
+ if (dom.extent() > MIN_CLIPPED_SIZE_THRESHOLD)
+ {
+// std::cerr << "clipped less than 20% : " << dom.extent() << std::endl;
+// std::cerr << "angle(pA) : " << angle(pA) << std::endl;
+// std::cerr << "angle(pB) : " << angle(pB) << std::endl;
+
+ std::vector<Point> pC1, pC2;
+ Interval dompC1, dompC2;
+ if (dompA.extent() > dompB.extent())
+ {
+ if ((dompA.extent() / 2) < MAX_PRECISION)
+ {
+ break;
+ }
+ pC1 = pC2 = pA;
+ portion(pC1, H1_INTERVAL);
+ portion(pC2, H2_INTERVAL);
+ dompC1 = dompC2 = dompA;
+ map_to(dompC1, H1_INTERVAL);
+ map_to(dompC2, H2_INTERVAL);
+ intersection(domsA, domsB, pC1, pB, dompC1, dompB, precision);
+ intersection(domsA, domsB, pC2, pB, dompC2, dompB, precision);
+ }
+ else
+ {
+ if ((dompB.extent() / 2) < MAX_PRECISION)
+ {
+ break;
+ }
+ pC1 = pC2 = pB;
+ portion(pC1, H1_INTERVAL);
+ portion(pC2, H2_INTERVAL);
+ dompC1 = dompC2 = dompB;
+ map_to(dompC1, H1_INTERVAL);
+ map_to(dompC2, H2_INTERVAL);
+ intersection(domsB, domsA, pC1, pA, dompC1, dompA, precision);
+ intersection(domsB, domsA, pC2, pA, dompC2, dompA, precision);
+ }
+ return;
+ }
+
+ using std::swap;
+ swap(C1, C2);
+ swap(dom1, dom2);
+// std::cerr << "dom(pA) : " << dompA << std::endl;
+// std::cerr << "dom(pB) : " << dompB << std::endl;
+ }
+ domsA.push_back(dompA);
+ domsB.push_back(dompB);
+}
+
+} /* end namespace bezier_clipping */ } /* end namespace detail */
+
+
+/*
+ * find_intersection
+ *
+ * input: A, B - set of control points of two Bezier curve
+ * input: precision - required precision of computation
+ * output: xs - set of pairs of parameter values
+ * at which crossing happens
+ *
+ * This routine is based on the Bezier Clipping Algorithm,
+ * see: Sederberg - Computer Aided Geometric Design
+ */
+void find_intersections (std::vector< std::pair<double, double> > & xs,
+ std::vector<Point> const& A,
+ std::vector<Point> const& B,
+ double precision)
+{
+ std::cout << "find_intersections: intersection-by-clipping.cpp version\n";
+// std::cerr << std::fixed << std::setprecision(16);
+
+ using detail::bezier_clipping::get_precision;
+ using detail::bezier_clipping::operator<<;
+ using detail::bezier_clipping::intersection;
+ using detail::bezier_clipping::UNIT_INTERVAL;
+
+ std::pair<double, double> ci;
+ std::vector<Interval> domsA, domsB;
+ intersection (domsA, domsB, A, B, UNIT_INTERVAL, UNIT_INTERVAL, precision);
+ if (domsA.size() != domsB.size())
+ {
+ assert (domsA.size() == domsB.size());
+ }
+ xs.clear();
+ xs.reserve(domsA.size());
+ for (size_t i = 0; i < domsA.size(); ++i)
+ {
+// std::cerr << i << " : domA : " << domsA[i] << std::endl;
+// std::cerr << "precision A: " << get_precision(domsA[i]) << std::endl;
+// std::cerr << i << " : domB : " << domsB[i] << std::endl;
+// std::cerr << "precision B: " << get_precision(domsB[i]) << std::endl;
+
+ ci.first = domsA[i].middle();
+ ci.second = domsB[i].middle();
+ xs.push_back(ci);
+ }
+}
+
+} // end namespace Geom
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/orphan-code/intersection-by-smashing.cpp b/src/3rdparty/2geom/src/2geom/orphan-code/intersection-by-smashing.cpp
new file mode 100644
index 0000000..02e44b1
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/orphan-code/intersection-by-smashing.cpp
@@ -0,0 +1,349 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/orphan-code/intersection-by-smashing.h>
+
+#include <cstdlib>
+#include <cstdio>
+#include <vector>
+#include <algorithm>
+
+namespace Geom {
+using namespace Geom;
+
+/*
+ * Computes the top and bottom boundaries of the L_\infty neighborhood
+ * of a curve. The curve is supposed to be a graph over the x-axis.
+ */
+static
+void computeLinfinityNeighborhood( D2<SBasis > const &f, double tol, D2<Piecewise<SBasis> > &topside, D2<Piecewise<SBasis> > &botside ){
+ double signx = ( f[X].at0() > f[X].at1() )? -1 : 1;
+ double signy = ( f[Y].at0() > f[Y].at1() )? -1 : 1;
+
+ Piecewise<D2<SBasis> > top, bot;
+ top = Piecewise<D2<SBasis> > (f);
+ top.cuts.insert( top.cuts.end(), 2);
+ top.segs.insert( top.segs.end(), D2<SBasis>(SBasis(Linear( f[X].at1(), f[X].at1()+2*tol*signx)),
+ SBasis(Linear( f[Y].at1() )) ));
+ bot = Piecewise<D2<SBasis> >(f);
+ bot.cuts.insert( bot.cuts.begin(), - 1 );
+ bot.segs.insert( bot.segs.begin(), D2<SBasis>(SBasis(Linear( f[X].at0()-2*tol*signx, f[X].at0())),
+ SBasis(Linear( f[Y].at0() )) ));
+ top += Point(-tol*signx, tol);
+ bot += Point( tol*signx, -tol);
+
+ if ( signy < 0 ){
+ std::swap( top, bot );
+ top += Point( 0, 2*tol);
+ bot += Point( 0, -2*tol);
+ }
+ topside = make_cuts_independent(top);
+ botside = make_cuts_independent(bot);
+}
+
+
+/*
+ * Compute top and bottom boundaries of the L^infty nbhd of the graph of a *monotonic* function f.
+ * if f is increasing, it is given by [f(t-tol)-tol, f(t+tol)+tol].
+ * if not, it is [f(t+tol)-tol, f(t-tol)+tol].
+ */
+static
+void computeLinfinityNeighborhood( Piecewise<SBasis> const &f, double tol, Piecewise<SBasis> &top, Piecewise<SBasis> &bot){
+ top = f + tol;
+ top.offsetDomain( - tol );
+ top.cuts.insert( top.cuts.end(), f.domain().max() + tol);
+ top.segs.insert( top.segs.end(), SBasis(Linear( f.lastValue() + tol )) );
+
+ bot = f - tol;
+ bot.offsetDomain( tol );
+ bot.cuts.insert( bot.cuts.begin(), f.domain().min() - tol);
+ bot.segs.insert( bot.segs.begin(), SBasis(Linear( f.firstValue() - tol )) );
+
+ if (f.firstValue() > f.lastValue()) {
+ std::swap(top, bot);
+ top += 2 * tol;
+ bot -= 2 * tol;
+ }
+}
+
+/*
+ * Returns the intervals over which the curve keeps its slope
+ * in one of the 8 sectors delimited by x=0, y=0, y=x, y=-x.
+ */
+std::vector<Interval> monotonicSplit(D2<SBasis> const &p){
+ std::vector<Interval> result;
+
+ D2<SBasis> v = derivative(p);
+
+ std::vector<double> someroots;
+ std::vector<double> cuts (2,0.);
+ cuts[1] = 1.;
+
+ someroots = roots(v[X]);
+ cuts.insert( cuts.end(), someroots.begin(), someroots.end() );
+
+ someroots = roots(v[Y]);
+ cuts.insert( cuts.end(), someroots.begin(), someroots.end() );
+
+ //we could split in the middle to avoid computing roots again...
+ someroots = roots(v[X]-v[Y]);
+ cuts.insert( cuts.end(), someroots.begin(), someroots.end() );
+
+ someroots = roots(v[X]+v[Y]);
+ cuts.insert( cuts.end(), someroots.begin(), someroots.end() );
+
+ sort(cuts.begin(),cuts.end());
+ unique(cuts.begin(), cuts.end() );
+
+ for (unsigned i=1; i<cuts.size(); i++){
+ result.push_back( Interval( cuts[i-1], cuts[i] ) );
+ }
+ return result;
+}
+
+//std::vector<Interval> level_set( D2<SBasis> const &f, Rect region){
+// std::vector<Interval> x_in_reg = level_set( f[X], region[X] );
+// std::vector<Interval> y_in_reg = level_set( f[Y], region[Y] );
+// std::vector<Interval> result = intersect ( x_in_reg, y_in_reg );
+// return result;
+//}
+
+/*TODO: remove this!!!
+ * the minimum would be to move it to piecewise.h but this would be stupid.
+ * The best would be to let 'compose' be aware of extension modes (constant, linear, polynomial..)
+ * (I think the extension modes (at start and end) should be properties of the pwsb).
+ */
+static
+void prolongateByConstants( Piecewise<SBasis> &f, double paddle_width ){
+ if ( f.size() == 0 ) return; //do we have a covention about the domain of empty pwsb?
+ f.cuts.insert( f.cuts.begin(), f.cuts.front() - paddle_width );
+ f.segs.insert( f.segs.begin(), SBasis( f.segs.front().at0() ) );
+ f.cuts.insert( f.cuts.end(), f.cuts.back() + paddle_width );
+ f.segs.insert( f.segs.end(), SBasis( f.segs.back().at1() ) );
+}
+
+static
+bool compareIntersectionsTimesX( SmashIntersection const &inter1, SmashIntersection const &inter2 ){
+ return inter1.times[X].min() < inter2.times[Y].min();
+}
+/*Fuse contiguous intersection domains
+ *
+ */
+static
+void cleanup_and_fuse( std::vector<SmashIntersection> &inters ){
+ std::sort( inters.begin(), inters.end(), compareIntersectionsTimesX);
+ for (unsigned i=0; i < inters.size(); i++ ){
+ for (unsigned j=i+1; j < inters.size() && inters[i].times[X].intersects( inters[j].times[X]) ; j++ ){
+ if (inters[i].times[Y].intersects( inters[j].times[Y] ) ){
+ inters[i].times.unionWith(inters[j].times);
+ inters[i].bbox.unionWith(inters[j].bbox);
+ inters.erase( inters.begin() + j );
+ }
+ }
+ }
+}
+
+/* Computes the intersection of two sets given as (ordered) union intervals.
+ */
+static
+std::vector<Interval> intersect( std::vector<Interval> const &a, std::vector<Interval> const &b){
+ std::vector<Interval> result;
+ //TODO: use order to optimize this!
+ for (auto i : a){
+ for (auto j : b){
+ OptInterval c( i );
+ c &= j;
+ if ( c ) {
+ result.push_back( *c );
+ }
+ }
+ }
+ return result;
+}
+
+/* Returns the intervals over which the curves are in the
+ * tol-neighborhood one of the other for the L_\infty metric.
+ * WARNING: each curve is supposed to be a graph over x or y axis
+ * (but not necessarily the same axis for both) and the smaller
+ * the slope the better (typically <=45°).
+ */
+std::vector<SmashIntersection> monotonic_smash_intersect( D2<SBasis> const &a, D2<SBasis> const &b, double tol){
+ using std::swap;
+
+ // a and b or X and Y may have to be exchanged, so make local copies.
+ D2<SBasis> aa = a;
+ D2<SBasis> bb = b;
+ bool swapresult = false;
+ bool swapcoord = false;//debug only!
+
+ //if the (enlarged) bounding boxes don't intersect, stop.
+ OptRect abounds = bounds_fast( a );
+ OptRect bbounds = bounds_fast( b );
+ if ( !abounds || !bbounds ) return std::vector<SmashIntersection>();
+ abounds->expandBy(tol);
+ if ( !(abounds->intersects(*bbounds))){
+ return std::vector<SmashIntersection>();
+ }
+
+ //Choose the best curve to be re-parametrized by x or y values.
+ OptRect dabounds = bounds_exact(derivative(a));
+ OptRect dbbounds = bounds_exact(derivative(b));
+ if ( dbbounds->min().length() > dabounds->min().length() ){
+ aa=b;
+ bb=a;
+ swap( dabounds, dbbounds );
+ swapresult = true;
+ }
+
+ //Choose the best coordinate to use as new parameter
+ double dxmin = std::min( std::abs((*dabounds)[X].max()), std::abs((*dabounds)[X].min()) );
+ double dymin = std::min( std::abs((*dabounds)[Y].max()), std::abs((*dabounds)[Y].min()) );
+ if ( (*dabounds)[X].max()*(*dabounds)[X].min() < 0 ) dxmin=0;
+ if ( (*dabounds)[Y].max()*(*dabounds)[Y].min() < 0 ) dymin=0;
+ assert (dxmin>=0 && dymin>=0);
+
+ if (dxmin < dymin) {
+ aa = D2<SBasis>( aa[Y], aa[X] );
+ bb = D2<SBasis>( bb[Y], bb[X] );
+ swapcoord = true;
+ }
+
+ //re-parametrize aa by the value of x.
+ Interval x_range_strict( aa[X].at0(), aa[X].at1() );
+ Piecewise<SBasis> y_of_x = pw_compose_inverse(aa[Y],aa[X], 2, 1e-5);
+
+ //Compute top and bottom boundaries of the L^infty nbhd of aa.
+ Piecewise<SBasis> top_ay, bot_ay;
+ computeLinfinityNeighborhood( y_of_x, tol, top_ay, bot_ay);
+
+ Interval ax_range = top_ay.domain();//i.e. aa[X] domain ewpanded by tol.
+ std::vector<Interval> bx_in_ax_range = level_set(bb[X], ax_range );
+
+ // find times when bb is in the neighborhood of aa.
+ std::vector<Interval> tbs;
+ for (auto & i : bx_in_ax_range){
+ D2<Piecewise<SBasis> > bb_in;
+ bb_in[X] = Piecewise<SBasis> ( portion( bb[X], i ) );
+ bb_in[Y] = Piecewise<SBasis> ( portion( bb[Y], i) );
+ bb_in[X].setDomain( i );
+ bb_in[Y].setDomain( i );
+
+ Piecewise<SBasis> h;
+ Interval level;
+ h = bb_in[Y] - compose( top_ay, bb_in[X] );
+ level = Interval( -infinity(), 0 );
+ std::vector<Interval> rts_lo = level_set( h, level);
+ h = bb_in[Y] - compose( bot_ay, bb_in[X] );
+ level = Interval( 0, infinity());
+ std::vector<Interval> rts_hi = level_set( h, level);
+
+ std::vector<Interval> rts = intersect( rts_lo, rts_hi );
+ tbs.insert(tbs.end(), rts.begin(), rts.end() );
+ }
+
+ std::vector<SmashIntersection> result(tbs.size(), SmashIntersection());
+
+ /* for each solution I, find times when aa is in the neighborhood of bb(I).
+ * (Note: the preimage of bb[X](I) by aa[X], enlarged by tol, is a good approximation of this:
+ * it would give points in the 2*tol neighborhood of bb (if the slope of aa is never more than 1).
+ * + faster computation.
+ * - implies little jumps depending on the subdivision of the input curve into monotonic pieces
+ * and on the choice of preferred axis. If noticeable, these jumps would feel random to the user :-(
+ */
+ for (unsigned j=0; j<tbs.size(); j++){
+ result[j].times[Y] = tbs[j];
+ std::vector<Interval> tas;
+ //TODO: replace this by some option in the "compose(pw,pw)" method!
+ Piecewise<SBasis> fat_y_of_x = y_of_x;
+ prolongateByConstants( fat_y_of_x, 100*(1+tol) );
+
+ D2<Piecewise<SBasis> > top_b, bot_b;
+ D2<SBasis> bbj = portion( bb, tbs[j] );
+ computeLinfinityNeighborhood( bbj, tol, top_b, bot_b );
+
+ Piecewise<SBasis> h;
+ Interval level;
+ h = top_b[Y] - compose( fat_y_of_x, top_b[X] );
+ level = Interval( +infinity(), 0 );
+ std::vector<Interval> rts_top = level_set( h, level);
+ for (auto & idx : rts_top){
+ idx = Interval( top_b[X].valueAt( idx.min() ),
+ top_b[X].valueAt( idx.max() ) );
+ }
+ assert( rts_top.size() == 1 );
+
+ h = bot_b[Y] - compose( fat_y_of_x, bot_b[X] );
+ level = Interval( 0, -infinity());
+ std::vector<Interval> rts_bot = level_set( h, level);
+ for (auto & idx : rts_bot){
+ idx = Interval( bot_b[X].valueAt( idx.min() ),
+ bot_b[X].valueAt( idx.max() ) );
+ }
+ assert( rts_bot.size() == 1 );
+ rts_top = intersect( rts_top, rts_bot );
+ assert (rts_top.size() == 1);
+ Interval x_dom = rts_top[0];
+
+ if ( x_dom.max() <= x_range_strict.min() ){
+ tas.push_back( Interval ( ( aa[X].at0() < aa[X].at1() ) ? 0 : 1 ) );
+ }else if ( x_dom.min() >= x_range_strict.max() ){
+ tas.push_back( Interval ( ( aa[X].at0() < aa[X].at1() ) ? 1 : 0 ) );
+ }else{
+ tas = level_set(aa[X], x_dom );
+ }
+ assert( tas.size()==1 );
+ result[j].times[X] = tas.front();
+
+ result[j].bbox = Rect( bbj.at0(), bbj.at1() );
+ Interval y_dom( aa[Y](result[j].times[X].min()), aa[Y](result[j].times[X].max()) );
+ result[j].bbox.unionWith( Rect( x_dom, y_dom ) );
+ }
+
+ if (swapresult) {
+ for (auto & i : result){
+ swap( i.times[X], i.times[Y]);
+ }
+ }
+ if (swapcoord) {
+ for (auto & i : result){
+ swap( i.bbox[X], i.bbox[Y] );
+ }
+ }
+
+ //TODO: cleanup result? fuse contiguous intersections?
+ return result;
+}
+
+std::vector<SmashIntersection> smash_intersect( D2<SBasis> const &a, D2<SBasis> const &b, double tol){
+ std::vector<SmashIntersection> result;
+
+ std::vector<Interval> acuts = monotonicSplit(a);
+ std::vector<Interval> bcuts = monotonicSplit(b);
+ for (auto & acut : acuts){
+ D2<SBasis> ai = portion( a, acut);
+ for (auto & bcut : bcuts){
+ D2<SBasis> bj = portion( b, bcut);
+ std::vector<SmashIntersection> ai_cap_bj = monotonic_smash_intersect( ai, bj, tol );
+ for (auto & k : ai_cap_bj){
+ k.times[X] = k.times[X] * acut.extent() + acut.min();
+ k.times[Y] = k.times[Y] * bcut.extent() + bcut.min();
+ }
+ result.insert( result.end(), ai_cap_bj.begin(), ai_cap_bj.end() );
+ }
+ }
+ cleanup_and_fuse( result );
+ return result;
+}
+
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/orphan-code/nearestpoint.cpp b/src/3rdparty/2geom/src/2geom/orphan-code/nearestpoint.cpp
new file mode 100644
index 0000000..870ed09
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/orphan-code/nearestpoint.cpp
@@ -0,0 +1,405 @@
+/*
+** vim: ts=4 sw=4 et tw=0 wm=0
+**
+** RCS Information:
+** $Author: mjw $
+** $Revision: 1 $
+** $Date: 2006-03-28 15:59:38 +1100 (Tue, 28 Mar 2006) $
+**
+** Solving the Nearest Point-on-Curve Problem and
+** A Bezier Curve-Based Root-Finder
+** by Philip J. Schneider
+** from "Graphics Gems", Academic Press, 1990
+** modified by mwybrow, njh
+*/
+
+/* point_on_curve.c */
+
+static double SquaredLength(const Geom::Point a)
+{
+ return dot(a, a);
+}
+
+
+/*
+ * Forward declarations
+ */
+static int FindRoots(Geom::Point *w, int degree, double *t, int depth);
+static Geom::Point *ConvertToBezierForm( Geom::Point P, Geom::Point *V);
+static double ComputeXIntercept( Geom::Point *V, int degree);
+static int ControlPolygonFlatEnough( Geom::Point *V, int degree);
+static int CrossingCount(Geom::Point *V, int degree);
+static Geom::Point Bez(Geom::Point *V, int degree, double t, Geom::Point *Left,
+ Geom::Point *Right);
+
+int MAXDEPTH = 64; /* Maximum depth for recursion */
+
+#define EPSILON (ldexp(1.0,-MAXDEPTH-1)) /*Flatness control value */
+#define DEGREE 3 /* Cubic Bezier curve */
+#define W_DEGREE 5 /* Degree of eqn to find roots of */
+
+
+/*
+ * NearestPointOnCurve :
+ * Compute the parameter value of the point on a Bezier
+ * curve segment closest to some arbtitrary, user-input point.
+ * Return the point on the curve at that parameter value.
+ *
+ Geom::Point P; The user-supplied point
+ Geom::Point *V; Control points of cubic Bezier
+*/
+double NearestPointOnCurve(Geom::Point P, Geom::Point *V)
+{
+ double t_candidate[W_DEGREE]; /* Possible roots */
+
+ /* Convert problem to 5th-degree Bezier form */
+ Geom::Point *w = ConvertToBezierForm(P, V);
+
+ /* Find all possible roots of 5th-degree equation */
+ int n_solutions = FindRoots(w, W_DEGREE, t_candidate, 0);
+ std::free((char *)w);
+
+ /* Check distance to end of the curve, where t = 1 */
+ double dist = SquaredLength(P - V[DEGREE]);
+ double t = 1.0;
+
+ /* Find distances for candidate points */
+ for (int i = 0; i < n_solutions; i++) {
+ Geom::Point p = Bez(V, DEGREE, t_candidate[i], NULL, NULL);
+ double new_dist = SquaredLength(P - p);
+ if (new_dist < dist) {
+ dist = new_dist;
+ t = t_candidate[i];
+ }
+ }
+
+ /* Return the parameter value t */
+ return t;
+}
+
+
+/*
+ * ConvertToBezierForm :
+ * Given a point and a Bezier curve, generate a 5th-degree
+ * Bezier-format equation whose solution finds the point on the
+ * curve nearest the user-defined point.
+ */
+static Geom::Point *ConvertToBezierForm(
+ Geom::Point P, /* The point to find t for */
+ Geom::Point *V) /* The control points */
+{
+ Geom::Point c[DEGREE+1]; /* V(i)'s - P */
+ Geom::Point d[DEGREE]; /* V(i+1) - V(i) */
+ Geom::Point *w; /* Ctl pts of 5th-degree curve */
+ double cdTable[3][4]; /* Dot product of c, d */
+ static double z[3][4] = { /* Precomputed "z" for cubics */
+ {1.0, 0.6, 0.3, 0.1},
+ {0.4, 0.6, 0.6, 0.4},
+ {0.1, 0.3, 0.6, 1.0},
+ };
+
+
+ /*Determine the c's -- these are vectors created by subtracting*/
+ /* point P from each of the control points */
+ for (int i = 0; i <= DEGREE; i++) {
+ c[i] = V[i] - P;
+ }
+ /* Determine the d's -- these are vectors created by subtracting*/
+ /* each control point from the next */
+ for (int i = 0; i <= DEGREE - 1; i++) {
+ d[i] = 3.0*(V[i+1] - V[i]);
+ }
+
+ /* Create the c,d table -- this is a table of dot products of the */
+ /* c's and d's */
+ for (int row = 0; row <= DEGREE - 1; row++) {
+ for (int column = 0; column <= DEGREE; column++) {
+ cdTable[row][column] = dot(d[row], c[column]);
+ }
+ }
+
+ /* Now, apply the z's to the dot products, on the skew diagonal*/
+ /* Also, set up the x-values, making these "points" */
+ w = (Geom::Point *)malloc((unsigned)(W_DEGREE+1) * sizeof(Geom::Point));
+ for (int i = 0; i <= W_DEGREE; i++) {
+ w[i][Geom::Y] = 0.0;
+ w[i][Geom::X] = (double)(i) / W_DEGREE;
+ }
+
+ const int n = DEGREE;
+ const int m = DEGREE-1;
+ for (int k = 0; k <= n + m; k++) {
+ const int lb = std::max(0, k - m);
+ const int ub = std::min(k, n);
+ for (int i = lb; i <= ub; i++) {
+ int j = k - i;
+ w[i+j][Geom::Y] += cdTable[j][i] * z[j][i];
+ }
+ }
+
+ return w;
+}
+
+
+/*
+ * FindRoots :
+ * Given a 5th-degree equation in Bernstein-Bezier form, find
+ * all of the roots in the interval [0, 1]. Return the number
+ * of roots found.
+ */
+static int FindRoots(
+ Geom::Point *w, /* The control points */
+ int degree, /* The degree of the polynomial */
+ double *t, /* RETURN candidate t-values */
+ int depth) /* The depth of the recursion */
+{
+ int i;
+ Geom::Point Left[W_DEGREE+1], /* New left and right */
+ Right[W_DEGREE+1]; /* control polygons */
+ int left_count, /* Solution count from */
+ right_count; /* children */
+ double left_t[W_DEGREE+1], /* Solutions from kids */
+ right_t[W_DEGREE+1];
+
+ switch (CrossingCount(w, degree)) {
+ case 0 : { /* No solutions here */
+ return 0;
+ break;
+ }
+ case 1 : { /* Unique solution */
+ /* Stop recursion when the tree is deep enough */
+ /* if deep enough, return 1 solution at midpoint */
+ if (depth >= MAXDEPTH) {
+ t[0] = (w[0][Geom::X] + w[W_DEGREE][Geom::X]) / 2.0;
+ return 1;
+ }
+ if (ControlPolygonFlatEnough(w, degree)) {
+ t[0] = ComputeXIntercept(w, degree);
+ return 1;
+ }
+ break;
+ }
+ }
+
+ /* Otherwise, solve recursively after */
+ /* subdividing control polygon */
+ Bez(w, degree, 0.5, Left, Right);
+ left_count = FindRoots(Left, degree, left_t, depth+1);
+ right_count = FindRoots(Right, degree, right_t, depth+1);
+
+
+ /* Gather solutions together */
+ for (i = 0; i < left_count; i++) {
+ t[i] = left_t[i];
+ }
+ for (i = 0; i < right_count; i++) {
+ t[i+left_count] = right_t[i];
+ }
+
+ /* Send back total number of solutions */
+ return (left_count+right_count);
+}
+
+
+/*
+ * CrossingCount :
+ * Count the number of times a Bezier control polygon
+ * crosses the 0-axis. This number is >= the number of roots.
+ *
+ */
+static int CrossingCount(
+ Geom::Point *V, /* Control pts of Bezier curve */
+ int degree) /* Degree of Bezier curve */
+{
+ int n_crossings = 0; /* Number of zero-crossings */
+ int old_sign; /* Sign of coefficients */
+
+ old_sign = Geom::sgn(V[0][Geom::Y]);
+ for (int i = 1; i <= degree; i++) {
+ int sign = Geom::sgn(V[i][Geom::Y]);
+ if (sign != old_sign)
+ n_crossings++;
+ old_sign = sign;
+ }
+ return n_crossings;
+}
+
+
+
+/*
+ * ControlPolygonFlatEnough :
+ * Check if the control polygon of a Bezier curve is flat enough
+ * for recursive subdivision to bottom out.
+ *
+ */
+static int ControlPolygonFlatEnough(
+ Geom::Point *V, /* Control points */
+ int degree) /* Degree of polynomial */
+{
+ int i; /* Index variable */
+ double *distance; /* Distances from pts to line */
+ double max_distance_above; /* maximum of these */
+ double max_distance_below;
+ double error; /* Precision of root */
+ //Geom::Point t; /* Vector from V[0] to V[degree]*/
+ double intercept_1,
+ intercept_2,
+ left_intercept,
+ right_intercept;
+ double a, b, c; /* Coefficients of implicit */
+ /* eqn for line from V[0]-V[deg]*/
+
+ /* Find the perpendicular distance */
+ /* from each interior control point to */
+ /* line connecting V[0] and V[degree] */
+ distance = (double *)malloc((unsigned)(degree + 1) * sizeof(double));
+ {
+ double abSquared;
+
+ /* Derive the implicit equation for line connecting first */
+ /* and last control points */
+ a = V[0][Geom::Y] - V[degree][Geom::Y];
+ b = V[degree][Geom::X] - V[0][Geom::X];
+ c = V[0][Geom::X] * V[degree][Geom::Y] - V[degree][Geom::X] * V[0][Geom::Y];
+
+ abSquared = (a * a) + (b * b);
+
+ for (i = 1; i < degree; i++) {
+ /* Compute distance from each of the points to that line */
+ distance[i] = a * V[i][Geom::X] + b * V[i][Geom::Y] + c;
+ if (distance[i] > 0.0) {
+ distance[i] = (distance[i] * distance[i]) / abSquared;
+ }
+ if (distance[i] < 0.0) {
+ distance[i] = -((distance[i] * distance[i]) / abSquared);
+ }
+ }
+ }
+
+
+ /* Find the largest distance */
+ max_distance_above = 0.0;
+ max_distance_below = 0.0;
+ for (i = 1; i < degree; i++) {
+ if (distance[i] < 0.0) {
+ max_distance_below = std::min(max_distance_below, distance[i]);
+ };
+ if (distance[i] > 0.0) {
+ max_distance_above = std::max(max_distance_above, distance[i]);
+ }
+ }
+ free((char *)distance);
+
+ {
+ double det;
+ double a1, b1, c1, a2, b2, c2;
+
+ /* Implicit equation for zero line */
+ a1 = 0.0;
+ b1 = 1.0;
+ c1 = 0.0;
+
+ /* Implicit equation for "above" line */
+ a2 = a;
+ b2 = b;
+ c2 = c + max_distance_above;
+
+ det = a1 * b2 - a2 * b1;
+
+ intercept_1 = (b1 * c2 - b2 * c1) / det;
+
+ /* Implicit equation for "below" line */
+ a2 = a;
+ b2 = b;
+ c2 = c + max_distance_below;
+
+ det = a1 * b2 - a2 * b1;
+
+ intercept_2 = (b1 * c2 - b2 * c1) / det;
+ }
+
+ /* Compute intercepts of bounding box */
+ left_intercept = std::min(intercept_1, intercept_2);
+ right_intercept = std::max(intercept_1, intercept_2);
+
+ error = 0.5 * (right_intercept-left_intercept);
+ if (error < EPSILON) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+
+/*
+ * ComputeXIntercept :
+ * Compute intersection of chord from first control point to last
+ * with 0-axis.
+ *
+ */
+static double ComputeXIntercept(
+ Geom::Point *V, /* Control points */
+ int degree) /* Degree of curve */
+{
+ const Geom::Point A = V[degree] - V[0];
+
+ return (A[Geom::X]*V[0][Geom::Y] - A[Geom::Y]*V[0][Geom::X]) / -A[Geom::Y];
+}
+
+
+/*
+ * Bez :
+ * Evaluate a Bezier curve at a particular parameter value
+ * Fill in control points for resulting sub-curves if "Left" and
+ * "Right" are non-null.
+ *
+ */
+static Geom::Point Bez(
+ Geom::Point *V, /* Control pts */
+ int degree, /* Degree of bezier curve */
+ double t, /* Parameter value */
+ Geom::Point *Left, /* RETURN left half ctl pts */
+ Geom::Point *Right) /* RETURN right half ctl pts */
+{
+ Geom::Point Vtemp[W_DEGREE+1][W_DEGREE+1];
+
+
+ /* Copy control points */
+ for (int j =0; j <= degree; j++) {
+ Vtemp[0][j] = V[j];
+ }
+
+ /* Triangle computation */
+ for (int i = 1; i <= degree; i++) {
+ for (int j =0 ; j <= degree - i; j++) {
+ Vtemp[i][j] =
+ (1.0 - t) * Vtemp[i-1][j] + t * Vtemp[i-1][j+1];
+ }
+ }
+
+ if (Left != NULL) {
+ for (int j = 0; j <= degree; j++) {
+ Left[j] = Vtemp[j][0];
+ }
+ }
+ if (Right != NULL) {
+ for (int j = 0; j <= degree; j++) {
+ Right[j] = Vtemp[degree-j][j];
+ }
+ }
+
+ return (Vtemp[degree][0]);
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/orphan-code/redblack-toy.cpp b/src/3rdparty/2geom/src/2geom/orphan-code/redblack-toy.cpp
new file mode 100644
index 0000000..01ffa7d
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/orphan-code/redblack-toy.cpp
@@ -0,0 +1,327 @@
+/*
+ * Copyright 2009 Evangelos Katsikaros <vkatsikaros at yahoo dot gr>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+/*
+ initial toy for redblack trees
+*/
+
+#include <2geom/toys/path-cairo.h>
+#include <2geom/toys/toy-framework-2.h>
+
+#include <2geom/orphan-code/redblacktree.h>
+#include <2geom/orphan-code/redblacktree.cpp>
+
+#include <time.h>
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+
+class RedBlackToy: public Toy
+{
+ PointSetHandle handle_set;
+ Geom::Point starting_point; // during click and drag: start point of click
+ Geom::Point ending_point; // during click and drag: end point of click (release)
+ Geom::Point highlight_point; // not used
+
+ Geom::RedBlackTree rbtree_x;
+ RedBlack* search_result;
+ RedBlack temp_deleted_node;
+
+ // colors we are going to use for different purposes
+ colour color_rect, color_rect_guide; // black(a=0.6), black
+ colour color_select_area, color_select_area_guide; // red(a=0.6), red
+
+ int alter_existing_rect;
+ int add_new_rect;
+
+ Rect rect_chosen; // the rectangle of the search area
+ Rect dummy_draw; // the "helper" rectangle that is shown during the click and drag (before the mouse release)
+ int mode; // insert/alter, search, delete modes
+
+ // printing of the tree
+ int help_counter; // the "x" of the label of each node
+ static const int label_size = 15 ; // size the label of each node
+
+ // used for the keys that switch between modes
+ enum menu_item_t
+ {
+ INSERT = 0,
+ DELETE,
+ SEARCH,
+ TOTAL_ITEMS // this one must be the last item
+ };
+ static const char* menu_items[TOTAL_ITEMS];
+ static const char keys[TOTAL_ITEMS];
+
+
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) {
+ cairo_set_line_width( cr, 1 );
+
+ // draw the rects that we have in the handles
+ for( unsigned i=0; i<handle_set.pts.size(); i=i+2 ){
+ Rect r1( handle_set.pts[i], handle_set.pts[i+1] );
+ cairo_rectangle( cr, r1 );
+ }
+ cairo_set_source_rgba( cr, color_rect);
+ cairo_stroke( cr );
+
+ // draw a rect if we click & drag (so that we know what we are going to create)
+ if(add_new_rect){
+ dummy_draw = Rect( starting_point, ending_point );
+ cairo_rectangle( cr, dummy_draw );
+ if( mode == 0){
+ cairo_set_source_rgba( cr, color_rect_guide);
+ }
+ else if( mode == 1){
+ cairo_set_source_rgba( cr, color_select_area_guide );
+ }
+ cairo_stroke( cr );
+ }
+
+ // draw a rect for the search area
+ cairo_rectangle( cr, rect_chosen );
+ cairo_set_source_rgba( cr, color_select_area);
+ cairo_stroke( cr );
+
+ Toy::draw( cr, notify, width, height, save,timer_stream );
+ draw_tree_in_toy( cr ,rbtree_x.root, 0);
+ help_counter=0;
+ }
+
+ void mouse_moved(GdkEventMotion* e){
+ if( !( alter_existing_rect && mode == 1 ) ){
+ Toy::mouse_moved(e);
+ }
+
+ if(add_new_rect){
+ ending_point = Point(e->x, e->y);
+ }
+ }
+
+ void mouse_pressed(GdkEventButton* e) {
+ Toy::mouse_pressed(e);
+ if(e->button == 1){ // left mouse button
+ if( mode == 0 ){ // mode: insert / alter
+ if(!selected) {
+ starting_point = Point(e->x, e->y);
+ ending_point = starting_point;
+ add_new_rect = 1;
+ }
+ else
+ {
+ // TODO find the selected rect
+ // ideas : from Handle *selected ???
+ //std::cout <<find_selected_rect(selected) << std::endl ;
+ alter_existing_rect = 1;
+ }
+ }
+ else if( mode == 1 ){ // mode: search
+ if(!selected) {
+ starting_point = Point(e->x, e->y);
+ ending_point = starting_point;
+ add_new_rect = 1;
+ }
+ else{
+ alter_existing_rect = 1;
+ }
+ }
+ else if( mode == 2) { // mode: delete
+ }
+ }
+ else if(e->button == 2){ //middle button
+ }
+ else if(e->button == 3){ //right button
+ }
+ }
+
+ virtual void mouse_released(GdkEventButton* e) {
+ Toy::mouse_released(e);
+ if( e->button == 1 ) { //left mouse button
+ if( mode == 0) { // mode: insert / alter
+ if( add_new_rect ){
+ ending_point = Point(e->x, e->y);
+ handle_set.push_back(starting_point);
+ handle_set.push_back(ending_point);
+ insert_in_tree_the_last_rect();
+ add_new_rect = 0;
+ }
+ else if( alter_existing_rect ){
+ //TODO update rect (and tree)
+ // delete selected rect
+ // insert altered
+ alter_existing_rect = 0;
+ }
+ }
+ else if( mode == 1 ){ // mode: search
+ if( add_new_rect ){
+ ending_point = Point(e->x, e->y);
+ rect_chosen = Rect(starting_point, ending_point);
+
+ // search in the X axis
+ Coord a = rect_chosen[0].min();
+ Coord b = rect_chosen[0].max();
+ search_result = rbtree_x.search( Interval( a, b ) );
+ if(search_result){
+ std::cout << "Found: (" << search_result->data << ": " << search_result->key()
+ << ", " << search_result->high() << " : " << search_result->subtree_max << ") "
+ << std::endl;
+ }
+ else{
+ std::cout << "Nothing found..."<< std::endl;
+ }
+ add_new_rect = 0;
+ }
+ else if(alter_existing_rect){
+ // do nothing
+ alter_existing_rect = 0;
+ }
+ }
+ else if( mode == 2) { // mode: delete
+
+ }
+ }
+ else if(e->button == 2){ //middle button
+ }
+ else if(e->button == 3){ //right button
+
+ }
+ }
+
+
+ void key_hit(GdkEventKey *e)
+ {
+ char choice = std::toupper(e->keyval);
+ switch ( choice )
+ {
+ case 'A':
+ mode = 0;
+ break;
+ case 'B':
+ mode = 1;
+ break;
+ case 'C':
+ mode = 2;
+ break;
+ }
+ //redraw();
+ }
+
+ void insert_in_tree_the_last_rect(){
+ unsigned i = handle_set.pts.size() - 2;
+ Rect r1(handle_set.pts[i], handle_set.pts[i+1]);
+ // insert in X axis tree
+ rbtree_x.insert(r1, i, 0);
+ rbtree_x.print_tree();
+ };
+
+ void draw_tree_in_toy(cairo_t* cr, Geom::RedBlack* n, int depth = 0) {
+ if(n){
+ if(n->left){
+ draw_tree_in_toy(cr, n->left, depth+1);
+ }
+ help_counter += 1;
+ //drawthisnode(cr, x*10, depth*10);
+ if(n->isRed){
+ cairo_set_source_rgba (cr, color_select_area_guide);
+ }
+ else{
+ cairo_set_source_rgba (cr, color_rect_guide);
+ }
+
+ cairo_stroke(cr);
+
+ Geom::Point text_point = Point( help_counter*15, depth*15 );
+ char label[4];
+ sprintf( label,"%d",n->data ); // instead of std::itoa(depth, label, 10);
+
+ draw_text(cr, text_point, label);
+ ////////////////////////////////////////////////////////////////
+ if(n->right){
+ draw_tree_in_toy(cr, n->right, depth+1);
+ }
+ }
+ };
+
+/*
+ int find_selected_rect(PointHandle * selected){
+
+ for( unsigned i=0; i<handle_set.pts.size(); i=i+2 ){
+ if( handle_set.pts[i] == selected || handle_set.pts[i+1] == selected ){
+ return i;
+ }
+ }
+
+ return -1;
+ };
+*/
+
+
+public:
+ RedBlackToy(): color_rect(0, 0, 0, 0.6), color_rect_guide(0, 0, 0, 1),
+ color_select_area(1, 0, 0, 0.6 ), color_select_area_guide(1, 0, 0, 1 ),
+ alter_existing_rect(0), add_new_rect(0), mode(0), help_counter(0)
+ {
+ if(handles.empty()) {
+ handles.push_back(&handle_set);
+ }
+ Rect rect_chosen();
+ Rect dummy_draw();
+ }
+
+
+};
+
+
+
+int main(int argc, char **argv) {
+ std::cout << "---------------------------------------------------------"<< std::endl;
+ std::cout << "Let's play with the Red Black Tree! ONLY Insert works now!!!"<< std::endl;
+ std::cout << " Key A: insert/alter mode "<< std::endl;
+ std::cout << " * Left click and drag on white area: create a rectangle"<< std::endl;
+ std::cout << " *NOT READY: Left click and drag on handler: alter a rectangle"<< std::endl;
+ std::cout << " Key B: search mode "<< std::endl;
+ std::cout << " * Left click and drag on white area: \"search\" for nodes that intersect red area"<< std::endl;
+ std::cout << " NOT READY: Key C: delete mode "<< std::endl;
+ std::cout << " * Left click on handler: delete for a rectangle"<< std::endl;
+ std::cout << "---------------------------------------------------------"<< std::endl;
+ init(argc, argv, new RedBlackToy);
+ return 0;
+}
+
+const char* RedBlackToy::menu_items[] =
+{
+ "Insert / Alter Rectangle",
+ "Search Rectangle",
+ "Delete Reactangle"
+};
+
+const char RedBlackToy::keys[] =
+{
+ 'A', 'B', 'C'
+};
diff --git a/src/3rdparty/2geom/src/2geom/orphan-code/redblacktree.cpp b/src/3rdparty/2geom/src/2geom/orphan-code/redblacktree.cpp
new file mode 100644
index 0000000..bf9a728
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/orphan-code/redblacktree.cpp
@@ -0,0 +1,575 @@
+#include <2geom/orphan-code/redblacktree.h>
+//#include <algorithm>
+
+
+#define _REDBLACK_PRINT(x) std::cout << x << std::endl;
+//comment the following if you want output during RedBlack Tree operations
+//#define _REDBLACK_PRINT(x) ;
+
+
+namespace Geom{
+
+
+
+RedBlack* RedBlackTree::search(Rect const &r, int dimension){
+ return search( Interval( r[dimension].min(), r[dimension].max() ) );
+ // TODO get rid of dimension
+ // TODO put 2 trees (X, Y axis in one lump)
+}
+
+/*
+INTERVAL-SEARCH(T, i)
+1 x <- root[T]
+2 while x != nil[T] and i does not overlap int[x]
+3 do if left[x] != nil[T] and max[left[x]] >= low[i]
+4 then x <- left[x]
+5 else x <- right[x]
+6 return x
+
+Two intervals i,x overlap in the 4 following cases:
+ 1) |--------| i
+ |---| x
+
+ 2) |-----| i
+ |----------| x
+
+ 3) |------| i
+ |------| x
+
+ 4) |----| i
+ |----| x
+
+And do not overlap when (the one os left or right of the other)
+ 1) |--------| i
+ |---| x
+
+ 2) |-----| i
+ |----------| x
+
+
+*/
+RedBlack* RedBlackTree::search(Interval i){
+ _REDBLACK_PRINT( "==============================================================" << std::endl << "ENTER: search(Interval i) : (" << i.min() << ", " << i.max() << ")" )
+ RedBlack *x;
+ x = root;
+
+ while( x!=0 &&
+ ( i.max() < x->interval.min() ||
+ i.min() > x->interval.max() )
+ ){
+ _REDBLACK_PRINT( "(" << x->data << ": " << x->key() << ", " << x->high() << " : " << x->subtree_max << ") "
+ << " i do not overlap with x")
+
+ if(x->left != 0 && (x->left)->subtree_max >= i.min() ){
+ x = x->left;
+ }
+ else{
+ x = x->right;
+ }
+ }
+ _REDBLACK_PRINT( "RETURN: search" << std::endl )
+ return x;
+}
+
+
+
+void RedBlackTree::insert(Rect const &r, int shape, int dimension) {
+ _REDBLACK_PRINT( "==============================================================" << std::endl << "ENTER: insert(Rect, int, dimension): " << " dimension:" << dimension << " shape:" << shape )
+ insert(r[dimension].min(), r[dimension].max(), shape);
+ _REDBLACK_PRINT( "RETURN: insert(Rect, int, dimension)")
+}
+
+// source: book pp 251
+void RedBlackTree::insert(Coord dimension_min, Coord dimension_max, int shape) {
+ _REDBLACK_PRINT( std::endl << "ENTER: insert(Coord, Coord, int): " << dimension_min << ", " << dimension_max << " , shape: " << shape )
+ // x is the new node we insert
+ RedBlack *x = new RedBlack();
+ x->interval = Interval( dimension_min, dimension_max );
+ x->data = shape;
+ x->isRed = true;
+
+ _REDBLACK_PRINT( " x: " << x << " KEY: " << x->key() << " high: " << x->high() )
+
+ tree_insert(x);
+
+ print_tree();
+
+ _REDBLACK_PRINT( " Begin coloring" )
+ // we now do the coloring of the tree.
+ _REDBLACK_PRINT( " while( x!= root && (x->parent)->isRed )" )
+ while( x!= root && (x->parent)->isRed ){
+ _REDBLACK_PRINT( " ((x->parent)->parent)->left:" << ((x->parent)->parent)->left << " ((x->parent)->parent)->right:" << ((x->parent)->parent)->right )
+
+ if( x->parent == ((x->parent)->parent)->left ){
+ _REDBLACK_PRINT( " Left:" )
+ RedBlack *y = new RedBlack;
+ y = ((x->parent)->parent)->right;
+ if( y == 0 ){
+ /*
+ This 1st brach is not in the book, but is needed. We must check y->isRed but it is
+ undefined, so we get segfault. But 0 (undefined) means that y is a leaf, so it is
+ black by definition. So, do the same as in the else part.
+ */
+ _REDBLACK_PRINT( " y==0" )
+ if( x == (x->parent)->right ){
+ x = x->parent;
+ left_rotate(x);
+ }
+ (x->parent)->isRed = false;
+ ((x->parent)->parent)->isRed = true;
+ right_rotate((x->parent)->parent);
+ }
+ else if( y->isRed ){
+ _REDBLACK_PRINT( " y->isRed" )
+ (x->parent)->isRed = false;
+ y->isRed = false;
+ ((x->parent)->parent)->isRed = true;
+ x = (x->parent)->parent;
+ }
+ else{
+ _REDBLACK_PRINT( " !( y->isRed)" )
+ if( x == (x->parent)->right ){
+ x = x->parent;
+ left_rotate(x);
+ }
+ (x->parent)->isRed = false;
+ ((x->parent)->parent)->isRed = true;
+ right_rotate((x->parent)->parent);
+ }
+ }
+ else{ // this branch is the same with the above if clause with "right", "left" exchanged
+ _REDBLACK_PRINT( " Right:" )
+ RedBlack *y = new RedBlack;
+ y = ((x->parent)->parent)->left;
+ if( y == 0 ){
+ /*
+ This 1st brach is not in the book, but is needed. We must check y->isRed but it is
+ undefined, so we get segfault. But 0 (undefined) means that y is a leaf, so it is
+ black by definition. So, do the same as in the else part.
+ */
+ _REDBLACK_PRINT( " y==0" )
+ if( x == (x->parent)->left ){
+ x = x->parent;
+ right_rotate(x);
+ }
+ (x->parent)->isRed = false;
+ ((x->parent)->parent)->isRed = true;
+ left_rotate((x->parent)->parent);
+ }
+ else if( y->isRed ){
+ _REDBLACK_PRINT( " y->isRed" )
+ (x->parent)->isRed = false;
+ y->isRed = false;
+ ((x->parent)->parent)->isRed = true;
+ x = (x->parent)->parent;
+ }
+ else{
+ _REDBLACK_PRINT( " !( y->isRed)" )
+ if( x == (x->parent)->left ){
+ x = x->parent;
+ right_rotate(x);
+ }
+ (x->parent)->isRed = false;
+ ((x->parent)->parent)->isRed = true;
+ left_rotate((x->parent)->parent);
+ }
+ }
+ }
+ root->isRed = false;
+
+ // update the max value with a slow/stupid yet certain way, walking all the tree :P
+ // TODO find better way
+ _REDBLACK_PRINT( " Update max" )
+
+ update_max(root);
+
+ _REDBLACK_PRINT( "RETURN: insert(Coord, Coord, int)" << std::endl)
+}
+
+// from book p. 266)
+void RedBlackTree::left_rotate(RedBlack* x){
+ // x->right != 0 (assumption book page 266)
+ // ??? hm problem ???
+ _REDBLACK_PRINT( "ENTER: left_rotate" )
+ RedBlack* y = new RedBlack;
+ y = x->right;
+ x->right = y->left;
+
+ if( y->left != 0){
+ (y->left)->parent = x;
+ }
+
+ y->parent = x->parent;
+
+ if( x->parent == 0){
+ root = y;
+ }
+ else{
+ if( x == (x->parent)->left ){
+ (x->parent)->left = y;
+ }
+ else{
+ (x->parent)->right = y;
+ }
+ }
+ y->left = x;
+ x->parent = y;
+ _REDBLACK_PRINT( "RETURN: left_rotate" << std::endl )
+}
+
+// from book p. 266: right_rotate is inverse of left_rotate
+// same to left_rotate with "right", "left" exchanged
+void RedBlackTree::right_rotate(RedBlack* x){
+ // x->right != 0 (assumption book page 266)
+ // ??? hm problem ??
+ _REDBLACK_PRINT( "ENTER: right_rotate" )
+ RedBlack* y = new RedBlack;
+
+ _REDBLACK_PRINT( "x->left: " << x->left )
+ y = x->left;
+ x->left = y->right;
+
+ if( y->right != 0){
+ (y->right)->parent = x;
+ }
+
+ y->parent = x->parent;
+
+ if( x->parent == 0){
+ root = y;
+ }
+ else{
+ if( x == (x->parent)->left ){
+ (x->parent)->left = y;
+ }
+ else{
+ (x->parent)->right = y;
+ }
+ }
+ y->right = x;
+ x->parent = y;
+ _REDBLACK_PRINT( "RETURN: right_rotate" << std::endl )
+}
+
+// insertion in binary search tree: book page 251
+// then the redblack insert performs the coloring
+void RedBlackTree::tree_insert(RedBlack* z){
+ _REDBLACK_PRINT( "ENTER: tree_insert(RedBlack* z)" )
+ RedBlack* y = 0; // y <- nil
+
+ RedBlack* x = root;
+
+ _REDBLACK_PRINT( " while x!=0 " )
+ while( x != 0 ){
+ y = x;
+// _REDBLACK_PRINT( " x:" << x << " y:" << y << " z:" << z )
+ _REDBLACK_PRINT( " z->key: " << z->key() << " y->key: " << y->key() << " compare")
+ if( z->key() < x->key() ){
+ _REDBLACK_PRINT( " z smaller: go left" )
+ x = x->left;
+ }
+ else{
+ _REDBLACK_PRINT( " z bigger: go right" )
+ x = x->right;
+ }
+ }
+
+ _REDBLACK_PRINT( " z->parent = y" )
+ z->parent = y;
+
+ if( y == 0 ){
+ _REDBLACK_PRINT( " set z root (empty tree)" )
+ root = z;
+ }
+ else{
+ _REDBLACK_PRINT( " z->key: " << z->key() << " y->key: " << y->key() << " compare")
+ if( z->key() < y->key() ){
+ _REDBLACK_PRINT( " z->key() smaller: y->left = z; " )
+ y->left = z;
+ }
+ else{
+ _REDBLACK_PRINT( " z->key() bigger: y->right = z " )
+ y->right = z;
+ }
+ }
+ _REDBLACK_PRINT( "RETURN: tree_insert(RedBlack* z)" << std::endl )
+}
+
+
+/*
+RB-DELETE(T, z)
+ 1 if left[z] = nil[T] or right[z] = nil[T]
+ 2 then y <- z
+ 3 else y <- TREE-SUCCESSOR(z)
+ 4 if left[y] != nil[T]
+ 5 then x <- left[y]
+ 6 else x <- right[y]
+ 7 p[x] <- p[y]
+ 8 if p[y] = nil[T]
+ 9 then root[T] <- x
+10 else if y = left[p[y]]
+11 then left[p[y]] <- x
+12 else right[p[y]] <- x
+13 if y != z
+14 then key[z] <- key[y]
+15 copy y's satellite data into z
+16 if color[y] = BLACK
+17 then RB-DELETE-FIXUP(T, x)
+18 return y
+*/
+RedBlack* RedBlackTree::erase(RedBlack* z){
+ _REDBLACK_PRINT( "==============================================================" << std::endl << "ENTER: earse(z)" )
+ RedBlack* x = new RedBlack();
+ RedBlack* y = new RedBlack();
+ if( z->left == 0 || z->right == 0 ){
+ y = z;
+ }
+ else{
+ y = tree_successor(z);
+ }
+
+ if( y->left != 0 ){
+ x = y->left;
+ }
+ else{
+ x = y->right;
+ }
+
+ x->parent = y->parent;
+
+ if( y->parent == 0){
+ root = x;
+ }
+ else {
+ if( y == (y->parent)->left ){
+ (y->parent)->left = x;
+ }
+ else{
+ (y->parent)->right = x;
+ }
+ }
+
+ if( y != z){
+ z->interval = y->interval ; // key[z] <- key[y] TODO check this
+ //copy y's satellite data into z
+ z->data = y->data;
+ z->isRed = y->isRed;
+
+ z->left = y->left;
+ z->right = y->right;
+ z->parent = y->parent;
+ }
+
+ if( y->isRed == false){
+ erase_fixup(x);
+ }
+
+ _REDBLACK_PRINT( "Update max" )
+ update_max(root);
+
+ _REDBLACK_PRINT( "RETURN: erase" )
+ return y;
+}
+
+/*
+RB-DELETE-FIXUP(T, x)
+ 1 while x != root[T] and color[x] = BLACK
+ 2 do if x = left[p[x]]
+ 3 then w <- right[p[x]]
+ 4 if color[w] = RED
+ 5 then color[w] <- BLACK Case 1
+ 6 color[p[x]] <- RED Case 1
+ 7 LEFT-ROTATE(T, p[x]) Case 1
+ 8 w <- right[p[x]]
+ 9 if color[left[w]] = BLACK and color[right[w]] = BLACK
+10 then color[w] <- RED Case 2
+11 x p[x] Case 2
+12 else if color[right[w]] = BLACK
+13 then color[left[w]] <- BLACK Case 3
+14 color[w] <- RED Case 3
+15 RIGHT-ROTATE(T, w) Case 3
+16 w <- right[p[x]] Case 3
+17 color[w] <- color[p[x]] Case 4
+18 color[p[x]] <- BLACK Case 4
+19 color[right[w]] <- BLACK Case 4
+20 LEFT-ROTATE(T, p[x]) Case 4
+21 x <- root[T] Case 4
+22 else (same as then clause with "right" and "left" exchanged)
+23 color[x] <- BLACK
+*/
+void RedBlackTree::erase_fixup(RedBlack* x){
+ RedBlack* w = 0;
+ while( x != root && x->isRed == false ){
+ if( x == (x->parent)->left ){
+ w = (x->parent)->right;
+ if(w->isRed == true){
+ w->isRed = false;
+ (w->parent)->isRed = true;
+ left_rotate(x->parent);
+ w = (x->parent)->right;
+ }
+ if( (w->left)->isRed == false && (w->right)->isRed == false ){
+ w->isRed = true;
+ x = x->parent; // TODO understand why this happens ???
+ }
+ else{
+ if( (w->right)->isRed == false ){
+ (w->left)->isRed = false;
+ right_rotate(w);
+ w = (x->parent)->right;
+ }
+ else{ // TODO ??? is this correct ???
+ w->isRed = (x->parent)->isRed;
+ (x->parent)->isRed = false;
+ (w->right)->isRed = false;
+ left_rotate(x->parent);
+ x = root; // TODO ??? is this correct ???
+ }
+ }
+ }
+ else{ // same as then clause with "right" and "left" exchanged
+ w = (x->parent)->left;
+ if(w->isRed == true){
+ w->isRed = false;
+ (w->parent)->isRed = true;
+ right_rotate(x->parent);
+ w = (x->parent)->left;
+ }
+ if( (w->right)->isRed == false && (w->left)->isRed == false ){
+ w->isRed = true;
+ x = x->parent; // ??? is this correct ???
+ }
+ else{
+ if( (w->left)->isRed == false ){
+ (w->right)->isRed = false;
+ left_rotate(w);
+ w = (x->parent)->left;
+ }
+ else{ // TODO ??? is this correct ???
+ w->isRed = (x->parent)->isRed;
+ (x->parent)->isRed = false;
+ (w->left)->isRed = false;
+ right_rotate(x->parent);
+ x = root; // TODO ??? is this correct ???
+ }
+ }
+ }
+ }
+ x->isRed = false;
+}
+
+
+void RedBlackTree::print_tree(){
+ std::cout << "Print RedBlackTree status:" << std::endl;
+ inorder_tree_walk(root);
+}
+
+
+void RedBlackTree::inorder_tree_walk(RedBlack* x){
+ int oops =0;
+ if( x != 0 ){
+ inorder_tree_walk(x->left);
+ std::cout<< "(" << x->data << ": " << x->key() << ", " << x->high() << " : " << x->subtree_max << ") " ;
+
+ if( x->left != 0 ){
+ std::cout<< "L:(" << (x->left)->data << ", " << (x->left)->key() << ") " ;
+ if( x->key() < (x->left)->key()){
+ std::cout<<" !!! ";
+ oops = 1;
+ }
+ }
+ else{
+ std::cout<< "L:0 " ;
+ }
+
+ if( x->right != 0 ){
+ std::cout<< "R:(" << (x->right)->data << ", "<< (x->right)->key() << ") " ;
+ if( x->key() > (x->right)->key() ){
+ std::cout<<" !!! ";
+ oops = 1;
+ }
+ }
+ else{
+ std::cout<< "R:0 " ;
+ }
+
+ if(oops){
+ std::cout<<" ....... !!! Problem " << oops ;
+ }
+ std::cout << std::endl;
+ inorder_tree_walk(x->right);
+ }
+}
+
+// not an norder walk of the tree
+void RedBlackTree::update_max(RedBlack* x){
+ Coord max_left, max_right;
+ if( x != 0 ){
+ update_max(x->left);
+ update_max(x->right);
+
+ // check for child
+ // if child is Nil then max = DBL_MIN
+ // could there be problems when comparing for max between two DBL_MIN ???
+ if( x->left == 0 ){
+ max_left = DBL_MIN ;
+ }
+ else{
+ max_left = (x->left)->subtree_max;
+ }
+
+ if( x->right == 0 ){
+ max_right = DBL_MIN ;
+ }
+ else{
+ max_right = (x->right)->subtree_max;
+ }
+
+ //find max of: x->high(), max_left, max_right
+ Coord temp_max;
+ temp_max = std::max( x->high(), max_left );
+ temp_max = std::max( temp_max, max_right );
+ x->subtree_max = temp_max;
+
+ }
+}
+
+
+RedBlack* RedBlackTree::tree_minimum(RedBlack* x){
+ _REDBLACK_PRINT( "==============================================================" << std::endl << "ENTER: tree_minimum" )
+ while( x->left <- 0 ) {
+ x->left = x;
+ }
+ _REDBLACK_PRINT( "RETURN: tree_minimum" << std::endl )
+ return x;
+}
+
+RedBlack* RedBlackTree::tree_successor(RedBlack* x){
+ _REDBLACK_PRINT( "==============================================================" << std::endl << "ENTER: tree_successor" )
+ if( x->right <- 0 ){
+ _REDBLACK_PRINT( "RETURN: tree_successor" << std::endl )
+ return tree_minimum(x);
+ }
+ RedBlack* y = x->parent;
+ _REDBLACK_PRINT( "y->parent: y->parent" )
+ while( y <- 0 && x == y->right ){
+ x = y;
+ y = y->parent;
+ }
+ _REDBLACK_PRINT( "RETURN: tree_successor" << std::endl )
+ return y;
+}
+
+
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/orphan-code/rtree.cpp b/src/3rdparty/2geom/src/2geom/orphan-code/rtree.cpp
new file mode 100644
index 0000000..4264292
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/orphan-code/rtree.cpp
@@ -0,0 +1,1350 @@
+#include <2geom/orphan-code/rtree.h>
+#include <limits>
+
+/*
+Based on source (BibTex):
+@inproceedings{DBLP:conf/sigmod/Guttman84,
+ author = {Antonin Guttman},
+ title = {R-Trees: A Dynamic Index Structure for Spatial Searching},
+ booktitle = {SIGMOD Conference},
+ year = {1984},
+ pages = {47-57},
+ ee = {http://doi.acm.org/10.1145/602259.602266, db/conf/sigmod/Guttman84.html},
+}
+*/
+
+/*
+#define _RTREE_PRINT(x) std::cout << x << std::endl;
+#define _RTREE_PRINT_TREE( x, y ) print_tree( x, y );
+#define _RTREE_PRINT_TREE_INS( x, y, z ) print_tree( x, y, z );
+*/
+//comment the following if you want output during RTree operations
+
+
+#define _RTREE_PRINT(x) ;
+#define _RTREE_PRINT_TREE( x, y ) ;
+#define _RTREE_PRINT_TREE_INS( x, y, z ) ;
+
+
+
+/*
+TODO 1
+some if(non_leaf)
+ else // leaf
+could be eliminated when function starts from a leaf
+do leaf action
+then repeat function for non-leafs only
+candidates:
+- adjust_tree
+- condense_tree
+
+TODO 2
+generalize in a different way the splitting techniques
+
+*/
+
+
+namespace Geom{
+
+/*=============================================================================
+ insert
+===============================================================================
+insert a new index entry E into the R-tree:
+
+I1) find position of new record:
+ choose_node will find a leaf node L (position) in which to place r
+I2) add record to leaf node:
+ if L has room for another entry install E
+ else split_node will obtain L and LL containing E and all the old entries of L
+ from the available splitting strategies we chose quadtratic-cost algorithm (just to begin
+ with sth)
+ // TODO implement more of them
+I3) propagate changes upward:
+ Invoke adjust_tree on L, also passing LL if a split was performed.
+I4) grow tree taller:
+ if a node spilt propagation, cuased the root to split
+ create new root whose children are the 2 resulting nodes
+*/
+
+void RTree::insert( Rect const &r, unsigned shape ){
+ _RTREE_PRINT("\n=====================================");
+ _RTREE_PRINT("insert");
+ RTreeRecord_Leaf* leaf_record= new RTreeRecord_Leaf( r, shape );
+ insert( *leaf_record );
+}
+
+
+
+void RTree::insert( const RTreeRecord_Leaf &leaf_record,
+ const bool &insert_high /* false */,
+ const unsigned &stop_height /* 0 */,
+ const RTreeRecord_NonLeaf &nonleaf_record /* 0 */
+ )
+{
+ _RTREE_PRINT("\n--------------");
+ _RTREE_PRINT("insert private. element:" << leaf_record.data << " insert high:" << insert_high << " stop height:" << stop_height );
+ RTreeNode *position = 0;
+
+ // if tree is unused create the root Node, not described in source, stupid me :P
+ if(root == 0){
+ root = new RTreeNode();
+ }
+
+ _RTREE_PRINT("I1"); // I1
+ if( insert_high == false ){ // choose leaf node
+ position = choose_node( leaf_record.bounding_box );
+ }
+ else { // choose nonleaf node
+ position = choose_node( nonleaf_record.bounding_box, insert_high, stop_height );
+ }
+ _RTREE_PRINT("leaf node chosen: " );
+ _RTREE_PRINT_TREE( position , 0 );
+ std::pair< RTreeNode*, RTreeNode* > node_division;
+
+ bool split_performed = false;
+
+ if( position->children_nodes.size() > 0 ){ // non-leaf node: position
+ // we must reach here only to insert high non leaf node, not insert leaf node
+ assert( insert_high == true );
+
+ // put new element in node temporarily. Later on, if we need to, we will split the node.
+ position->children_nodes.push_back( nonleaf_record );
+ if( position->children_nodes.size() <= max_records ){
+ _RTREE_PRINT("I2 nonleaf: no split: " << position->children_nodes.size() ); // I2
+ }
+ else{
+ _RTREE_PRINT("I2 nonleaf: split: " << position->children_nodes.size() ); // I2
+ node_division = split_node( position );
+ split_performed = true;
+ }
+
+ }
+ else { // leaf node: position:
+ // we must reach here only to insert leaf node, not insert high non leaf node
+ assert( insert_high == false );
+
+
+ // put new element in node temporarily. Later on, if we need to, we will split the node.
+ position->children_leaves.push_back( leaf_record );
+ if( position->children_leaves.size() <= max_records ){
+ _RTREE_PRINT("I2 leaf: no split: " << position->children_leaves.size() ); // I2
+ }
+ else{
+ _RTREE_PRINT("I2 leaf: split: " << position->children_leaves.size() << " max_records:" << max_records); // I2
+ node_division = split_node( position );
+ split_performed = true;
+
+ _RTREE_PRINT(" group A");
+ _RTREE_PRINT_TREE( node_division.first , 3 );
+ _RTREE_PRINT(" group B");
+ _RTREE_PRINT_TREE( node_division.second , 3 );
+
+ }
+
+ }
+
+ _RTREE_PRINT("I3"); // I3
+ bool root_split_performed = adjust_tree( position, node_division, split_performed );
+ _RTREE_PRINT("root split: " << root_split_performed);
+
+
+// _RTREE_PRINT("TREE:");
+// print_tree( root , 2 );
+
+ _RTREE_PRINT("I4"); // I4
+ if( root_split_performed ){
+ std::pair<RTreeNode*, RTreeNode*> root_division;
+ root_division = quadratic_split( root ); // AT5
+
+ Rect first_record_bounding_box;
+ Rect second_record_bounding_box;
+
+ RTreeRecord_NonLeaf first_new_record = create_nonleaf_record_from_rtreenode( first_record_bounding_box, root_division.first );
+ RTreeRecord_NonLeaf second_new_record = create_nonleaf_record_from_rtreenode( second_record_bounding_box, root_division.second );
+ _RTREE_PRINT(" 1st:");
+ _RTREE_PRINT_TREE( first_new_record.data, 5 );
+ _RTREE_PRINT(" 2nd:");
+ _RTREE_PRINT_TREE( second_new_record.data, 5 );
+
+ // *new* root is by definition non-leaf. Install the new records there
+ RTreeNode* new_root = new RTreeNode();
+ new_root->children_nodes.push_back( first_new_record );
+ new_root->children_nodes.push_back( second_new_record );
+
+ delete root;
+
+ root = new_root;
+ tree_height++; // increse tree height
+
+ _RTREE_PRINT_TREE( root, 5 );
+ sanity_check( root, 0 );
+ }
+ _RTREE_PRINT("done");
+
+ /*
+ the node_division.second is saved on the tree
+ the node_division.first was copied in existing tree in node
+ so we don't need this anymore
+ */
+ delete node_division.first;
+}
+
+/* I1 =========================================================================
+
+original: choose_node will find a leaf node L in which to place r
+changed to choose_node will find a node L in which to place r
+the node L is:
+non-leaf: if flag is set. the height of the node is insert_at_height
+leaf: if flag is NOT set
+
+1) Initialize: set N to be the root node
+2) Leaf Check:
+ insert_height = false
+ if N is leaf return N
+ insert_height = true
+3) Choose subtree: If N not leaf OR not we are not in the proper height then
+ let F be an entry in N whose rect Fi needs least enlargement to include r
+ ties resolved with rect of smallest area
+4) descend until a leaf is reached OR proper height is reached: set N to the child node pointed to by F and goto 2.
+*/
+
+// TODO keep stack with visited nodes
+
+RTreeNode* RTree::choose_node( const Rect &r, const bool &insert_high /* false */, const unsigned &stop_height /* 0 */) const {
+
+ _RTREE_PRINT(" CL1");// CL1
+ RTreeNode *pos = root;
+
+ double min_enlargement;
+ double current_enlargement;
+ int node_min_enlargement;
+ unsigned current_height = 0; // zero is the root
+
+ _RTREE_PRINT(" CL2 current_height:" << current_height << " stop_height:" << stop_height << " insert_high:" << insert_high);
+ // CL2 Leaf check && Height check
+ while( ( insert_high ? true : pos->children_nodes.size() != 0 )
+ && ( insert_high ? current_height < stop_height : true ) )
+ /* Leaf check, during insert leaf */
+ /* node height check, during insert non-leaf */
+ {
+ _RTREE_PRINT(" CL3 current_height:" << current_height << " stop_height:" << stop_height ); // CL3
+ min_enlargement = std::numeric_limits<double>::max();
+ current_enlargement = 0;
+ node_min_enlargement = 0;
+
+ for(unsigned i=0; i< pos->children_nodes.size(); i++){
+ current_enlargement = find_enlargement( pos->children_nodes[i].bounding_box, r );
+
+ // TODO tie not solved!
+ if( current_enlargement < min_enlargement ){
+ node_min_enlargement = i;
+ min_enlargement = current_enlargement;
+ }
+ }
+ _RTREE_PRINT(" CL4"); // CL4
+ // descend to the node with the min_enlargement
+ pos = pos->children_nodes[node_min_enlargement].data;
+ current_height++; // increase current visiting height
+ }
+
+ return pos;
+}
+
+
+/*
+find_enlargement:
+
+enlargement that "a" needs in order to include "b"
+b is the new rect we want to insert.
+a is the rect of the node we try to see if b should go in.
+*/
+double RTree::find_enlargement( const Rect &a, const Rect &b ) const{
+
+
+ Rect union_rect(a);
+ union_rect.unionWith(b);
+
+ OptRect a_intersection_b = intersect( a, b );
+
+ // a, b do not intersect
+ if( a_intersection_b.empty() ){
+ _RTREE_PRINT(" find_enlargement (no intersect): " << union_rect.area() - a.area() - b.area() );
+ return union_rect.area() - a.area() - b.area();
+ }
+
+ // a, b intersect
+
+ // a contains b
+ if( a.contains( b ) ){
+ _RTREE_PRINT(" find_enlargement (intersect: a cont b): " << a.area() - b.area() );
+ //return a.area() - b.area();
+ return b.area() - a.area(); // enlargement is negative in this case.
+ }
+
+ // b contains a
+ if( b.contains( a ) ){
+ _RTREE_PRINT(" find_enlargement (intersect: b cont a): " << a.area() - b.area() );
+ return b.area() - a.area();
+ }
+
+ // a partially cover b
+ _RTREE_PRINT(" find_enlargement (intersect: a partial cover b): " << union_rect.area() - a.area() - b.area() - a_intersection_b->area() );
+ return union_rect.area()
+ - ( a.area() - a_intersection_b->area() )
+ - ( b.area() - a_intersection_b->area() );
+}
+
+
+/* I2 =========================================================================
+use one split strategy
+*/
+
+std::pair<RTreeNode*, RTreeNode*> RTree::split_node( RTreeNode *s ){
+/*
+ if( split_strategy == LINEAR_COST ){
+ linear_cost_split( ............. );
+ }
+*/
+ return quadratic_split( s ); // else QUADRATIC_SPIT
+}
+
+
+/*-----------------------------------------------------------------------------
+ Quadratic Split
+
+QS1) Pick first entry for each group:
+ Appy pick_seeds to choose 2 entries to be the first elements of the groups. Assign each one of
+ them to one group
+QS2) check if done:
+ a) if all entries have been assinged stop
+ b) if one group has so few entries that all the rest must be assignmed to it, in order for it to
+ have the min number , assign them and stop
+QS3) select entry and assign:
+ Inkvoke pick_next() to choose the next entry to assign.
+ *[in pick_next] Add it to the group whose covering rectangle will have to be enlrarged least to
+ accommodate it. Resolve ties by adding the entry to the group with the smaller are, then to the
+ one with fewer entries, then to either of the two.
+ goto 2.
+*/
+std::pair<RTreeNode*, RTreeNode*> RTree::quadratic_split( RTreeNode *s ) {
+
+ // s is the original leaf node or non-leaf node
+ RTreeNode* group_a = new RTreeNode(); // a is the 1st group
+ RTreeNode* group_b = new RTreeNode(); // b is the 2nd group
+
+
+ _RTREE_PRINT(" QS1"); // QS1
+ std::pair<unsigned, unsigned> initial_seeds;
+ initial_seeds = pick_seeds(s);
+
+ // if non-leaf node: s
+ if( s->children_nodes.size() > 0 ){
+ _RTREE_PRINT(" non-leaf node");
+ // each element is true if the node has been assinged to either "a" or "b"
+ std::vector<bool> assigned_v( s->children_nodes.size() );
+ std::fill( assigned_v.begin(), assigned_v.end(), false );
+
+ group_a->children_nodes.push_back( s->children_nodes[initial_seeds.first] );
+ assert(initial_seeds.first < assigned_v.size());
+ assigned_v[ initial_seeds.first ] = true;
+
+ group_b->children_nodes.push_back( s->children_nodes[initial_seeds.second] );
+ assert(initial_seeds.second < assigned_v.size());
+ assigned_v[ initial_seeds.second ] = true;
+
+ _RTREE_PRINT(" QS2"); // QS2
+ unsigned num_of_not_assigned = s->children_nodes.size() - 2;
+ // so far we have assinged 2 out of all
+
+ while( num_of_not_assigned ){// QS2 a
+ _RTREE_PRINT(" QS2 b, num_of_not_assigned:" << num_of_not_assigned); // QS2 b
+ /*
+ we are on NON leaf node so children of split groups must be nodes
+
+ Check each group to see if one group has so few entries that all the rest must
+ be assignmed to it, in order for it to have the min number.
+ */
+ if( group_a->children_nodes.size() + num_of_not_assigned <= min_records ){
+ // add the non-assigned to group_a
+ for(unsigned i = 0; i < assigned_v.size(); i++){
+ if(assigned_v[i] == false){
+ group_a->children_nodes.push_back( s->children_nodes[i] );
+ assigned_v[i] = true;
+ }
+ }
+ break;
+ }
+
+ if( group_b->children_nodes.size() + num_of_not_assigned <= min_records ){
+ // add the non-assigned to group_b
+ for( unsigned i = 0; i < assigned_v.size(); i++ ){
+ if( assigned_v[i] == false ){
+ group_b->children_nodes.push_back( s->children_nodes[i] );
+ assigned_v[i] = true;
+ }
+ }
+ break;
+ }
+
+ _RTREE_PRINT(" QS3"); // QS3
+ std::pair<unsigned, enum_add_to_group> next_element;
+ next_element = pick_next( group_a, group_b, s, assigned_v );
+ if( next_element.second == ADD_TO_GROUP_A ){
+ group_a->children_nodes.push_back( s->children_nodes[ next_element.first ] );
+ }
+ else{
+ group_b->children_nodes.push_back( s->children_nodes[ next_element.first ] );
+ }
+
+ num_of_not_assigned--;
+ }
+ }
+ // else leaf node: s
+ else{
+ _RTREE_PRINT(" leaf node");
+ // each element is true if the node has been assinged to either "a" or "b"
+ std::vector<bool> assigned_v( s->children_leaves.size() );
+ std::fill( assigned_v.begin(), assigned_v.end(), false );
+
+ // assign 1st seed to group a
+ group_a->children_leaves.push_back( s->children_leaves[initial_seeds.first] );
+ assert(initial_seeds.first < assigned_v.size());
+ assigned_v[ initial_seeds.first ] = true;
+
+ // assign 2nd seed to group b
+ group_b->children_leaves.push_back( s->children_leaves[initial_seeds.second] );
+ assert(initial_seeds.second < assigned_v.size());
+ assigned_v[ initial_seeds.second ] = true;
+
+ _RTREE_PRINT(" QS2"); // QS2
+ unsigned num_of_not_assigned = s->children_leaves.size() - 2;
+ // so far we have assinged 2 out of all
+
+ while( num_of_not_assigned ){// QS2 a
+ _RTREE_PRINT(" QS2 b, num_of_not_assigned:" << num_of_not_assigned); // QS2 b
+ /*
+ we are on leaf node so children of split groups must be leaves
+
+ Check each group to see if one group has so few entries that all the rest must
+ be assignmed to it, in order for it to have the min number.
+ */
+ if( group_a->children_leaves.size() + num_of_not_assigned <= min_records ){
+ _RTREE_PRINT(" add the non-assigned to group_a");
+ // add the non-assigned to group_a
+ for( unsigned i = 0; i < assigned_v.size(); i++ ){
+ if( assigned_v[i] == false ){
+ group_a->children_leaves.push_back( s->children_leaves[i] );
+ assigned_v[i] = true;
+ }
+ }
+ break;
+ }
+
+ if( group_b->children_leaves.size() + num_of_not_assigned <= min_records ){
+ _RTREE_PRINT(" add the non-assigned to group_b");
+ // add the non-assigned to group_b
+ for( unsigned i = 0; i < assigned_v.size(); i++ ){
+ if( assigned_v[i] == false ){
+ group_b->children_leaves.push_back( s->children_leaves[i] );
+ assigned_v[i] = true;
+ }
+ }
+ break;
+ }
+
+ _RTREE_PRINT(" QS3"); // QS3
+ std::pair<unsigned, enum_add_to_group> next_element;
+ next_element = pick_next(group_a, group_b, s, assigned_v);
+ if( next_element.second == ADD_TO_GROUP_A ){
+ group_a->children_leaves.push_back( s->children_leaves[ next_element.first ] );
+ }
+ else{
+ group_b->children_leaves.push_back( s->children_leaves[ next_element.first ] );
+ }
+
+ num_of_not_assigned--;
+ }
+ }
+ assert( initial_seeds.first != initial_seeds.second );
+ return std::make_pair( group_a, group_b );
+}
+
+/*
+PS1) caclulate ineffeciency of grouping entries together:
+ Foreach pair of entries E1 (i), E2 (j) compose rectangle J (i_union_j) including E1, E2.
+ Calculate d = area(i_union_j) - area(i) - area(j)
+PS2) choose the most wastefull pair:
+ Choose pair with largest d
+*/
+
+std::pair<unsigned, unsigned> RTree::pick_seeds( RTreeNode *s ) const{
+ double current_d = 0;
+ double max_d = std::numeric_limits<double>::min();
+ unsigned seed_a = 0;
+ unsigned seed_b = 1;
+ _RTREE_PRINT(" pick_seeds");
+
+ // if non leaf node: s
+ if( s->children_nodes.size() > 0 ){
+ _RTREE_PRINT(" non leaf");
+ _RTREE_PRINT(" PS1"); // PS1
+ for( unsigned a = 0; a < s->children_nodes.size(); a++ ){
+ // with j=i we check only the upper (diagonal) half
+ // with j=i+1 we also avoid checking for b==a (we don't need it)
+ for( unsigned b = a+1; b < s->children_nodes.size(); b++ ){
+ _RTREE_PRINT(" PS2 " << a << " - " << b ); // PS2
+ current_d = find_waste_area( s->children_nodes[a].bounding_box, s->children_nodes[b].bounding_box );
+
+ if( current_d > max_d ){
+ max_d = current_d;
+ seed_a = a;
+ seed_b = b;
+ }
+ }
+ }
+ }
+ // else leaf node: s
+ else{
+ _RTREE_PRINT(" leaf node");
+ _RTREE_PRINT(" PS1"); // PS1
+ for( unsigned a = 0; a < s->children_leaves.size(); a++ ){
+ // with j=i we check only the upper (diagonal) half
+ // with j=i+1 we also avoid checking for j==i (we don't need this one)
+ for( unsigned b = a+1; b < s->children_leaves.size(); b++ ){
+ _RTREE_PRINT(" PS2 " << s->children_leaves[a].data << ":" << s->children_leaves[a].bounding_box.area()
+ << " - " << s->children_leaves[b].data << ":" << s->children_leaves[b].bounding_box.area() ); // PS2
+ current_d = find_waste_area( s->children_leaves[a].bounding_box, s->children_leaves[b].bounding_box );
+
+ if( current_d > max_d ){
+ max_d = current_d;
+ seed_a = a;
+ seed_b = b;
+ }
+ }
+ }
+ }
+ _RTREE_PRINT(" seed_a: " << seed_a << " seed_b: " << seed_b );
+ return std::make_pair( seed_a, seed_b );
+}
+
+/*
+find_waste_area (used in pick_seeds step 1)
+
+for a pair A, B compose a rect union_rect that includes a and b
+calculate area of union_rect - area of a - area b
+*/
+double RTree::find_waste_area( const Rect &a, const Rect &b ) const{
+ Rect union_rect(a);
+ union_rect.unionWith(b);
+
+ return union_rect.area() - a.area() - b.area();
+}
+
+/*
+pick_next:
+select one remaining entry for classification in a group
+
+PN1) Determine cost of putting each entry in each group:
+ Foreach entry E not yet in a group, calculate
+ d1= area increase required in the cover rect of Group 1 to include E
+ d2= area increase required in the cover rect of Group 2 to include E
+PN2) Find entry with greatest preference for each group:
+ Choose any entry with the maximum difference between d1 and d2
+
+*/
+
+std::pair<unsigned, enum_add_to_group> RTree::pick_next( RTreeNode* group_a,
+ RTreeNode* group_b,
+ RTreeNode* s,
+ std::vector<bool> &assigned_v )
+{
+ double max_increase_difference = std::numeric_limits<double>::min();
+ unsigned max_increase_difference_node = 0;
+ double current_increase_difference = 0;
+
+ enum_add_to_group group_to_add = ADD_TO_GROUP_A;
+
+ /*
+ bounding boxes of the 2 new groups. This info isn't available, since they
+ have no parent nodes (so that the parent node knows the bounding box).
+ */
+ Rect bounding_box_a;
+ Rect bounding_box_b;
+
+ double increase_area_a = 0;
+ double increase_area_b = 0;
+
+ _RTREE_PRINT(" pick_next, assigned_v.size:" << assigned_v.size() );
+
+ // if non leaf node: one of the 2 groups (both groups are the same, either leaf/nonleaf)
+ if( group_a->children_nodes.size() > 0 ){
+ _RTREE_PRINT(" non leaf");
+
+ // calculate the bounding boxes of the 2 new groups.
+ bounding_box_a = Rect( group_a->children_nodes[0].bounding_box );
+ for( unsigned i = 1; i < group_a->children_nodes.size(); i++ ){
+ bounding_box_a.unionWith( group_a->children_nodes[i].bounding_box );
+ }
+
+ bounding_box_b = Rect( group_b->children_nodes[0].bounding_box );
+ for( unsigned i = 1; i < group_b->children_nodes.size(); i++ ){
+ bounding_box_b.unionWith( group_b->children_nodes[i].bounding_box );
+ }
+
+
+ _RTREE_PRINT(" PN1"); // PN1
+ for( unsigned i = 0; i < assigned_v.size(); i++ ){
+ _RTREE_PRINT(" i:" << i << " assigned:" << assigned_v[i]);
+ if( assigned_v[i] == false ){
+
+ increase_area_a = find_enlargement( bounding_box_a, s->children_nodes[i].bounding_box );
+ increase_area_b = find_enlargement( bounding_box_b, s->children_nodes[i].bounding_box );
+
+ current_increase_difference = std::abs( increase_area_a - increase_area_b );
+ _RTREE_PRINT(" PN2 " << i << ": " << current_increase_difference ); // PN2
+ if( current_increase_difference > max_increase_difference ){
+ max_increase_difference = current_increase_difference;
+ max_increase_difference_node = i;
+
+ // TODO tie not solved!
+ if( increase_area_a < increase_area_b ){
+ group_to_add = ADD_TO_GROUP_A;
+ }
+ else{
+ group_to_add = ADD_TO_GROUP_B;
+ }
+ }
+ }
+ }
+ //assert(max_increase_difference_node >= 0);
+ assert(max_increase_difference_node < assigned_v.size());
+ assigned_v[max_increase_difference_node] = true;
+ _RTREE_PRINT(" ... i:" << max_increase_difference_node << " assigned:" << assigned_v[max_increase_difference_node] );
+ }
+ else{ // else leaf node
+ _RTREE_PRINT(" leaf");
+
+ // calculate the bounding boxes of the 2 new groups
+ bounding_box_a = Rect( group_a->children_leaves[0].bounding_box );
+ for( unsigned i = 1; i < group_a->children_leaves.size(); i++ ){
+ std::cout<< " lala";
+ bounding_box_a.unionWith( group_a->children_leaves[i].bounding_box );
+ }
+
+ bounding_box_b = Rect( group_b->children_leaves[0].bounding_box );
+ for( unsigned i = 1; i < group_b->children_leaves.size(); i++ ){
+ std::cout<< " lala";
+ bounding_box_b.unionWith( group_b->children_leaves[i].bounding_box );
+ }
+ std::cout<< "" << std::endl;
+
+ _RTREE_PRINT(" PN1"); // PN1
+ for( unsigned i = 0; i < assigned_v.size(); i++ ){
+ _RTREE_PRINT(" i:" << i << " assigned:" << assigned_v[i]);
+ if( assigned_v[i] == false ){
+ increase_area_a = find_enlargement( bounding_box_a, s->children_leaves[i].bounding_box );
+ increase_area_b = find_enlargement( bounding_box_b, s->children_leaves[i].bounding_box );
+
+ current_increase_difference = std::abs( increase_area_a - increase_area_b );
+ _RTREE_PRINT(" PN2 " << i << ": " << current_increase_difference ); // PN2
+
+ if( current_increase_difference > max_increase_difference ){
+ max_increase_difference = current_increase_difference;
+ max_increase_difference_node = i;
+
+ // TODO tie not solved!
+ if( increase_area_a < increase_area_b ){
+ group_to_add = ADD_TO_GROUP_A;
+ }
+ else{
+ group_to_add = ADD_TO_GROUP_B;
+ }
+ }
+ }
+ }
+ assert(max_increase_difference_node < assigned_v.size());
+ assigned_v[max_increase_difference_node] = true;
+ _RTREE_PRINT(" ... i:" << max_increase_difference_node << " assigned:" << assigned_v[max_increase_difference_node] );
+ }
+
+ _RTREE_PRINT(" node:" << max_increase_difference_node << " added:" << group_to_add );
+ return std::make_pair( max_increase_difference_node, group_to_add );
+}
+
+/* I3 =========================================================================
+
+adjust_tree:
+Ascend from a leaf node L to root, adjusting covering rectangles and propagating node splits as
+necessary
+
+We modified this one from the source in the step AT1 and AT5
+
+AT1) Initialize:
+ Set N=L
+ IF L was spilt previously, set NN to be the resulting second node AND
+ (not mentioned in the original source but that's what it should mean)
+ Assign all entries of first node to L
+AT2) check if done:
+ IF N is root stop
+AT3) adjust covering rectangle in parent entry
+ 1) Let P be the parent of N
+ 2) Let EN be the N's entry in P
+ 3) Adjust EN bounding box so that it tightly enclosses all entry rectangles in N
+AT4) Propagate node split upward
+ IF N has a partner NN resulting from an earlier split
+ create a new entry ENN with ENN "p" pointing to NN and ENN bounding box enclosing all
+ rectangles in NN
+
+ IF there is room in P add ENN
+ ELSE invoke split_node to produce P an PP containing ENN and all P's old entries.
+AT5) Move up to next level
+ Set N=P,
+ IF a split occurred, set NN=PP
+ goto AT1 (was goto AT2)
+*/
+
+bool RTree::adjust_tree( RTreeNode* position,
+ // modified: it holds the last split group
+ std::pair<RTreeNode*, RTreeNode*> &node_division,
+ bool initial_split_performed)
+{
+ RTreeNode* parent;
+ unsigned child_in_parent; // the element in parent node that points to current posistion
+ std::pair< RTreeNode*, bool > find_result;
+ bool split_performed = initial_split_performed;
+ bool root_split_performed = false;
+
+ _RTREE_PRINT(" adjust_tree");
+ _RTREE_PRINT(" AT1");
+
+ while( true ){
+ _RTREE_PRINT(" ------- current tree status:");
+ _RTREE_PRINT_TREE_INS(root, 2, true);
+
+ // check for loop BREAK
+ if( position == root ){
+ _RTREE_PRINT(" AT2: found root");
+ if( split_performed ){
+ root_split_performed = true;
+ }
+ break;
+ }
+
+ if( split_performed ){
+ copy_group_a_to_existing_node( position, node_division.first );
+ }
+
+ /*
+ pick randomly, let's say the 1st entry of the current node.
+ Search for this spatial area in the tree, and stop to the parent node.
+ Then find position of current node pointer, in the parent node.
+ */
+ _RTREE_PRINT(" AT3.1"); // AT3.1 Let P be the parent of N
+ if( position->children_nodes.size() > 0 ){
+ find_result = find_parent( root, position->children_nodes[0].bounding_box, position);
+ }
+ else{
+ find_result = find_parent( root, position->children_leaves[0].bounding_box, position);
+ }
+ parent = find_result.first;
+
+ // parent is a non-leaf, by definition
+ _RTREE_PRINT(" AT3.2"); // AT3.2 Let EN be the N's entry in P
+ for( child_in_parent = 0; child_in_parent < parent->children_nodes.size(); child_in_parent++ ){
+ if( parent->children_nodes[ child_in_parent ].data == position){
+ _RTREE_PRINT(" child_in_parent: " << child_in_parent);
+ break;
+ }
+ }
+
+ _RTREE_PRINT(" AT3.3");
+ // AT3.2 Adjust EN bounding box so that it tightly enclosses all entry rectangles in N
+ recalculate_bounding_box( parent, position, child_in_parent );
+
+
+ _RTREE_PRINT(" AT4"); // AT4
+ if( split_performed ){
+ // create new record (from group_b)
+ //RTreeNode* new_node = new RTreeNode();
+ Rect new_record_bounding;
+
+ RTreeRecord_NonLeaf new_record = create_nonleaf_record_from_rtreenode( new_record_bounding, node_division.second );
+
+ // install new entry (group_b)
+ if( parent->children_nodes.size() < max_records ){
+ parent->children_nodes.push_back( new_record );
+ split_performed = false;
+ }
+ else{
+ parent->children_nodes.push_back( new_record );
+ node_division = quadratic_split( parent ); // AT5
+ split_performed = true;
+ }
+
+ }
+ _RTREE_PRINT(" AT5"); // AT5
+ position = parent;
+ }
+
+ return root_split_performed;
+}
+
+/*
+find_parent:
+The source only mentions that we should "find" the parent. But it doesn't seay how. So we made a
+modification of search.
+
+Initially we take the root, a rect of the node, of which the parent we look for and the node we seek
+
+We do a spatial search for this rect. If we find get an intersecttion with the rect we check if the
+child is the one we look for.
+If not we call find_parent again recursively
+*/
+
+std::pair< RTreeNode*, bool > RTree::find_parent( RTreeNode* subtree_root,
+ Rect search_area,
+ RTreeNode* wanted) const
+{
+ _RTREE_PRINT("find_parent");
+
+ std::pair< RTreeNode*, bool > result;
+ if( subtree_root->children_nodes.size() > 0 ){
+
+ for( unsigned i=0; i < subtree_root->children_nodes.size(); i++ ){
+ if( subtree_root->children_nodes[i].data == wanted){
+ _RTREE_PRINT("FOUND!!"); // non leaf node
+ return std::make_pair( subtree_root, true );
+ }
+
+ if( subtree_root->children_nodes[i].bounding_box.intersects( search_area ) ){
+ result = find_parent( subtree_root->children_nodes[i].data, search_area, wanted);
+ if ( result.second ){
+ break;
+ }
+ }
+ }
+ }
+ return result;
+}
+
+
+void RTree::copy_group_a_to_existing_node( RTreeNode *position, RTreeNode* group_a ){
+ // clear position (the one that was split) and put there all the nodes of group_a
+ if( position->children_nodes.size() > 0 ){
+ _RTREE_PRINT(" copy_group...(): install group A to existing non-leaf node");
+ // non leaf-node: position
+ position->children_nodes.clear();
+ for(auto & children_node : group_a->children_nodes){
+ position->children_nodes.push_back( children_node );
+ }
+ }
+ else{
+ _RTREE_PRINT(" copy_group...(): install group A to existing leaf node");
+ // leaf-node: positions
+ position->children_leaves.clear();
+ for(auto & children_leave : group_a->children_leaves){
+ position->children_leaves.push_back( children_leave );
+ }
+ }
+}
+
+
+
+RTreeRecord_NonLeaf RTree::create_nonleaf_record_from_rtreenode( Rect &new_entry_bounding, RTreeNode* rtreenode ){
+
+ if( rtreenode->children_nodes.size() > 0 ){
+ // found bounding box of new entry
+ new_entry_bounding = Rect( rtreenode->children_nodes[0].bounding_box );
+ for(unsigned i = 1; i < rtreenode->children_nodes.size(); i++ ){
+ new_entry_bounding.unionWith( rtreenode->children_nodes[ i ].bounding_box );
+ }
+ }
+ else{ // non leaf: rtreenode
+ // found bounding box of new entry
+ new_entry_bounding = Rect( rtreenode->children_leaves[0].bounding_box );
+ for(unsigned i = 1; i < rtreenode->children_leaves.size(); i++ ){
+ new_entry_bounding.unionWith( rtreenode->children_leaves[ i ].bounding_box );
+ }
+ }
+ return RTreeRecord_NonLeaf( new_entry_bounding, rtreenode );
+}
+
+
+
+/*
+ print the elements of the tree
+ based on ordered tree walking
+*/
+void RTree::print_tree(RTreeNode* subtree_root, int depth ) const{
+
+ if( subtree_root->children_nodes.size() > 0 ){
+
+ // descend in each one of the elements and call print_tree
+ for( unsigned i=0; i < subtree_root->children_nodes.size(); i++ ){
+ //print spaces for indentation
+ for(int j=0; j < depth; j++){
+ std::cout << " " ;
+ }
+
+ std::cout << subtree_root->children_nodes[i].bounding_box << ", " << subtree_root->children_nodes.size() << std::endl ;
+ _RTREE_PRINT_TREE_INS( subtree_root->children_nodes[i].data, depth+1, used_during_insert);
+ }
+
+ }
+ else{
+ for(int j=0; j < depth; j++){
+ std::cout << " " ;
+ }
+ std::cout << subtree_root->children_leaves.size() << ": " ;
+
+ // print all the elements of the leaf node
+ for(auto & children_leave : subtree_root->children_leaves){
+ std::cout << children_leave.data << ", " ;
+ }
+ std::cout << std::endl ;
+
+ }
+}
+
+
+void RTree::sanity_check(RTreeNode* subtree_root, int depth, bool used_during_insert ) const{
+
+ if( subtree_root->children_nodes.size() > 0 ){
+ // descend in each one of the elements and call sanity_check
+ for(auto & children_node : subtree_root->children_nodes){
+ sanity_check( children_node.data, depth+1, used_during_insert);
+ }
+
+
+ // sanity check
+ if( subtree_root != root ){
+ assert( subtree_root->children_nodes.size() >= min_records);
+ }
+/*
+ else{
+ assert( subtree_root->children_nodes.size() >= 1);
+ }
+*/
+
+ if( used_during_insert ){
+ // allow one more during for insert
+ assert( subtree_root->children_nodes.size() <= max_records + 1 );
+ }
+ else{
+ assert( subtree_root->children_nodes.size() <= max_records );
+ }
+
+ }
+ else{
+ // sanity check
+ if( subtree_root != root ){
+ assert( subtree_root->children_leaves.size() >= min_records);
+ }
+/*
+ else{
+ assert( subtree_root->children_leaves.size() >= 1);
+ }
+*/
+
+ if( used_during_insert ){
+ // allow one more during for insert
+ assert( subtree_root->children_leaves.size() <= max_records + 1 );
+ }
+ else{
+ assert( subtree_root->children_nodes.size() <= max_records );
+ }
+ }
+}
+
+
+
+/*=============================================================================
+ search
+===============================================================================
+Given an RTree whose root node is T find all index records whose rects overlap search rect S
+S1) Search subtrees:
+ IF T isn't a leaf, check every entry E to determine whether E I overlaps S
+ FOR all overlapping entries invoke Search on the tree whose root node is pointed by E P
+S2) ELSE T is leaf
+ check all entries E to determine whether E I overlaps S
+ IF so E is a qualifying record
+*/
+
+
+void RTree::search( const Rect &search_area, std::vector< int >* result, const RTreeNode* subtree ) const {
+ // S1
+ if( subtree->children_nodes.size() > 0 ){ // non-leaf: subtree
+ for(const auto & children_node : subtree->children_nodes){
+ if( children_node.bounding_box.intersects( search_area ) ){
+ search( search_area, result, children_node.data );
+ }
+ }
+ }
+ // S2
+ else{ // leaf: subtree
+ for(const auto & children_leave : subtree->children_leaves){
+ if( children_leave.bounding_box.intersects( search_area ) ){
+ result->push_back( children_leave.data );
+ }
+ }
+ }
+}
+
+
+/*=============================================================================
+ erase
+===============================================================================
+we changed steps D2)
+D1) Find node containing record
+ Invoke find_leaf() to locate the leaf node L containing E
+ IF record is found stop
+D2) Delete record
+ Remove E from L (it happened in find_leaf step FL2)
+D3) Propagate changes
+ Invoke condense_tree, passing L
+D4) Shorten tree
+ If root node has only one child, after the tree was adjusted, make the child new root
+
+return
+0 on success
+1 in case no entry was found
+
+*/
+//int RTree::erase( const RTreeRecord_Leaf & record_to_erase ){
+int RTree::erase( const Rect &search_area, const int shape_to_delete ){
+ _RTREE_PRINT("\n=====================================");
+ _RTREE_PRINT("erase element: " << shape_to_delete);
+ // D1 + D2: entry is deleted in find_leaf
+ _RTREE_PRINT("D1 & D2 : find and delete the leaf");
+ RTreeNode* contains_record = find_leaf( root, search_area, shape_to_delete );
+ if( !contains_record ){ // no entry returned from find_leaf
+ return 1; // no entry found
+ }
+
+ // D3
+ //bool root_elimination_performed = condense_tree( contains_record );
+
+ // D4
+
+ //if( root_elimination_performed ){
+ if( root->children_nodes.size() > 0 ){ // non leaf: root
+ // D4
+ if( root->children_nodes.size() == 1 ){
+ _RTREE_PRINT("D4 : non leaf: ");
+ tree_height--;
+ RTreeNode* t = root;
+ root = root->children_nodes[0].data;
+ delete t;
+ }
+
+ }
+ else { // leaf: root
+ // D4
+ // do nothing
+ }
+ sanity_check( root, 0 );
+ return 0; // success
+}
+
+
+/*
+ find_leaf()
+Given an RTree whose root node is T find the leaf node containing index entry E
+
+FL1) Search subtrees
+ IF T is non leaf, check each entry F in T to determine if F I overlaps E I
+ foreach such entry invoke find_leaf on the tree whose root is pointed to by F P until E is
+ found or all entries have been checked
+FL2) search leaf node for record
+ IF T is leaf, check each entry to see if it matches E
+ IF E is found return T
+ AND delete element E (step D2)
+*/
+
+RTreeNode* RTree::find_leaf( RTreeNode* subtree, const Rect &search_area, const int shape_to_delete ) const {
+ // FL1
+ if( subtree->children_nodes.size() > 0 ){ // non-leaf: subtree
+ for(auto & children_node : subtree->children_nodes){
+ if( children_node.bounding_box.intersects( search_area ) ){
+ RTreeNode* t = find_leaf( children_node.data, search_area, shape_to_delete );
+ if( t ){ // if search was successful terminate
+ return t;
+ }
+ }
+ }
+ }
+ // FL2
+ else{ // leaf: subtree
+ for( std::vector< RTreeRecord_Leaf >::iterator it = subtree->children_leaves.begin(); it!=subtree->children_leaves.end(); ++it ){
+ if( it->data == shape_to_delete ){
+ // delete element: implement step D2)
+ subtree->children_leaves.erase( it );
+ return subtree;
+ }
+ }
+ }
+ return 0;
+}
+
+
+/*
+ condense_tree()
+Given a Leaf node L from which an entry has been deleted eliminate the node if it has too few entries and reallocate its entries
+Propagate node elimination upwards as necessary
+Adjust all covering recsts n the path to the root making them smaller if possible
+
+CT1) Initialize
+ Set N=L
+ Set Q the set of eliminated nodes to be empty
+CT2) // Find parent entry (was there but doesn't make sense)
+ IF N is the root
+ goto CT6
+ ELSE
+ 1) Find parent entry
+ 2) let P be the parent of N
+ 3) and let EN be N's entry in P
+CT3) IF N has fewer than m entries
+ Eliminate underfull node
+ 1) delete EN from P
+ 2) and add N to set Q
+CT4) ELSE
+ adjust EN I to tightly contain all entries in N
+CT5) move up one level in tree
+ set N=P and repeat from CT2
+
+CT6) Re insert orphaned entries
+ Re-inser all entreis of nodes in set Q
+ Entries from eliminated leaf nodes are re-inserted in tree leaves (like in insert)
+ BUT non-leaf nodes must be placed higher in the tree so that leaves of their dependent subtrees
+ will be on the same level as leaves of the main tree. (on the same height they originally were)
+ (not mentioned in the source description: the criteria for placing the node should be
+ again TODO ??? least enlargement)
+
+*/
+// TODO this can be merged with adjust_tree or refactor to reutilize some parts. less readable
+bool RTree::condense_tree( RTreeNode* position )
+{
+ RTreeNode* parent;
+ unsigned child_in_parent = 0; // the element in parent node that points to current posistion
+
+ std::pair< RTreeNode*, bool > find_result;
+ bool elimination_performed = false;
+ bool root_elimination_performed = false;
+ unsigned current_height = tree_height+1;
+ Rect special_case_bounding_box;
+ _RTREE_PRINT(" condense_tree");
+ _RTREE_PRINT(" CT1");
+ // leaf records that were eliminated due to under-full node
+ std::vector< RTreeRecord_Leaf > Q_leaf_records( 0 );
+
+ // < non-leaf records, their height > that were eliminated due to under-full node
+ std::vector< std::pair< RTreeRecord_NonLeaf, unsigned > > Q_nonleaf_records( 0 );
+
+
+ while( true ){
+
+ // check for loop BREAK
+ if( position == root ){
+ _RTREE_PRINT(" CT2 position is root");
+ if( elimination_performed ){
+ root_elimination_performed = true;
+ }
+ break;
+ }
+
+ /*
+ pick randomly, let's say the 1st entry of the current node.
+ Search for this spatial area in the tree, and stop to the parent node.
+ Then find position of current node pointer, in the parent node.
+ */
+ /*
+ special case. if elimination due to children being underfull was performed AND
+ AND parent had only 1 record ,then this one record was removed.
+ */
+ if( position->children_nodes.size() > 0 ){
+ _RTREE_PRINT(" CT2.1 - 2 non leaf: find parent, P is parent");
+ // CT2.1 find parent. By definition it's nonleaf
+ find_result = find_parent( root, position->children_nodes[0].bounding_box, position);
+ }
+ else if( position->children_nodes.size() == 0
+ && position->children_leaves.size() == 0
+ && elimination_performed )
+ { // special case
+ _RTREE_PRINT(" CT2.1 - 2 special case: find parent, P is parent");
+ // CT2.1 find parent. By definition it's nonleaf
+ find_result = find_parent( root, special_case_bounding_box, position);
+ }
+ else{
+ _RTREE_PRINT(" CT2.1 - 2 leaf: find parent, P is parent");
+ // CT2.1 find parent. By definition it's nonleaf
+ find_result = find_parent( root, position->children_leaves[0].bounding_box, position);
+ }
+ // CT2.2 Let P be the parent of N
+ parent = find_result.first;
+
+
+ // parent is a non-leaf, by definition. Calculate "child_in_parent"
+ _RTREE_PRINT(" CT2.3 find in parent, position's record EN");
+ // CT2.3 Let EN be the N's entry in P
+ for( child_in_parent = 0; child_in_parent < parent->children_nodes.size(); child_in_parent++ ){
+ if( parent->children_nodes[ child_in_parent ].data == position){
+ _RTREE_PRINT(" child_in_parent: " << child_in_parent << " out of " << parent->children_nodes.size() << " (size)" );
+ break;
+ }
+ }
+
+ if( position->children_nodes.size() > 0 ){ // non leaf node: position
+ _RTREE_PRINT(" CT3 nonleaf: eliminate underfull node");
+ // CT3 Eliminate underfull node
+ if( position->children_nodes.size() < min_records ){
+ _RTREE_PRINT(" CT3.2 add N to Q");
+ // CT3.2 add N to set Q ( EN the record that points to N )
+ for(auto & children_node : position->children_nodes){
+ _RTREE_PRINT(" i " << i );
+ std::pair< RTreeRecord_NonLeaf, unsigned > t = std::make_pair( children_node, current_height-1);
+ Q_nonleaf_records.push_back( t );
+
+ }
+ special_case_bounding_box = parent->children_nodes[ child_in_parent ].bounding_box;
+
+ _RTREE_PRINT(" CT3.1 delete in parent, position's record EN");
+ // CT3.1 delete EN from P ( parent is by definition nonleaf )
+ if( remove_record_from_parent( parent, position ) ){ // TODO does erase, delete to the pointer ???
+ _RTREE_PRINT(" remove_record_from_parent error ");
+ }
+ elimination_performed = true;
+ }
+ else{
+ _RTREE_PRINT(" CT4 "); /// CT4) if not underfull
+ recalculate_bounding_box( parent, position, child_in_parent );
+ elimination_performed = false;
+ }
+
+ }
+ else{ // leaf node: position
+ _RTREE_PRINT(" CT3 leaf: eliminate underfull node");
+ // CT3 Eliminate underfull node
+ if( position->children_leaves.size() < min_records ){
+ _RTREE_PRINT(" CT3.2 add N to Q " << position->children_leaves.size() );
+ // CT3.2 add N to set Q
+ for(auto & children_leave : position->children_leaves){
+ _RTREE_PRINT(" i " << i );
+ Q_leaf_records.push_back( children_leave ); // TODO problem here
+ special_case_bounding_box = children_leave.bounding_box;
+ }
+
+ _RTREE_PRINT(" CT3.1 delete in parent, position's record EN");
+ // CT3.1 delete EN from P ( parent is by definition nonleaf )
+ if( remove_record_from_parent( parent, position ) ){
+ _RTREE_PRINT(" remove_record_from_parent error ");
+ }
+ elimination_performed = true;
+ }
+ else{
+ _RTREE_PRINT(" CT4 "); /// CT4) if not underfull
+ recalculate_bounding_box( parent, position, child_in_parent );
+ elimination_performed = false;
+ }
+ }
+ _RTREE_PRINT(" CT5 ");// CT5) move up one level in tree
+ position = parent;
+
+ current_height--;
+ }
+ // CT6: reinsert
+ _RTREE_PRINT(" ------ Q_leaf");
+ for( std::vector< RTreeRecord_Leaf >::iterator it = Q_leaf_records.begin(); it != Q_leaf_records.end(); ++it ){
+ _RTREE_PRINT(" leaf:" << (*it).data);
+ }
+ _RTREE_PRINT(" ------ Q_nonleaf");
+ for( std::vector< std::pair< RTreeRecord_NonLeaf, unsigned > >::iterator it = Q_nonleaf_records.begin(); it != Q_nonleaf_records.end(); ++it ){
+ _RTREE_PRINT(" ------- " << it->second );
+ _RTREE_PRINT_TREE( it->first.data, 0);
+ }
+
+ _RTREE_PRINT(" CT6 ");
+ for(auto & Q_leaf_record : Q_leaf_records){
+ insert( Q_leaf_record );
+ _RTREE_PRINT(" inserted leaf:" << (*it).data << " ------------");
+ _RTREE_PRINT_TREE( root, 0);
+ }
+
+
+ for(auto & Q_nonleaf_record : Q_nonleaf_records){
+ insert( RTreeRecord_Leaf() , true, Q_nonleaf_record.second, Q_nonleaf_record.first );
+ _RTREE_PRINT(" inserted nonleaf------------");
+ _RTREE_PRINT_TREE( root, 0);
+ // TODO this fake RTreeRecord_Leaf() looks stupid. find better way to do this ???
+ }
+
+ return root_elimination_performed;
+}
+
+
+/*
+given:
+- a parent
+- a child node
+- and the position of the child node in the parent
+recalculate the parent record's bounding box of the child, in order to ightly contain all entries of child
+
+NOTE! child must be indeed child of the parent, otherwise it screws up things. So find parent and child
+before calling this function
+*/
+void RTree::recalculate_bounding_box( RTreeNode* parent, RTreeNode* child, unsigned &child_in_parent ) {
+ if( child->children_nodes.size() > 0 ){
+ _RTREE_PRINT(" non-leaf: recalculate bounding box of parent "); // non leaf-node: child
+ parent->children_nodes[ child_in_parent ].bounding_box = Rect( child->children_nodes[0].bounding_box );
+ for( unsigned i=1; i < child->children_nodes.size(); i++ ){
+ parent->children_nodes[ child_in_parent ].bounding_box.unionWith( child->children_nodes[i].bounding_box );
+ }
+ }
+ else{
+ _RTREE_PRINT(" leaf: recalculate bounding box of parent "); // leaf-node: child
+ parent->children_nodes[ child_in_parent ].bounding_box = Rect( child->children_leaves[0].bounding_box );
+
+ for( unsigned i=1; i < child->children_leaves.size(); i++ ){
+ parent->children_nodes[ child_in_parent ].bounding_box.unionWith( child->children_leaves[i].bounding_box );
+ }
+ }
+}
+
+/*
+given:
+- a parent
+- a child node
+it removes the child record from the parent
+
+NOTE! child must be indeed child of the parent, otherwise it screws up things.
+So find parent and child before calling this function
+*/
+int RTree::remove_record_from_parent( RTreeNode* parent, RTreeNode* child ) {
+ _RTREE_PRINT( "remove_record_from_parent)" );
+ for( std::vector< RTreeRecord_NonLeaf >::iterator it = parent->children_nodes.begin(); it!=parent->children_nodes.end(); ++it ){
+ if( it->data == child ){
+ // delete element: implement step D2)
+ parent->children_nodes.erase( it );
+ return 0; // success
+ }
+ }
+ return 1; // failure
+}
+
+/*=============================================================================
+TODO update
+===============================================================================
+*/
+
+
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/parallelogram.cpp b/src/3rdparty/2geom/src/2geom/parallelogram.cpp
new file mode 100644
index 0000000..b477a01
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/parallelogram.cpp
@@ -0,0 +1,136 @@
+/*
+ * Authors:
+ * Thomas Holder
+ * Sergei Izmailov
+ *
+ * Copyright 2020 Authors
+ *
+ * SPDX-License-Identifier: LGPL-2.1 or MPL-1.1
+ */
+
+#include <2geom/basic-intersection.h>
+#include <2geom/parallelogram.h>
+
+#include <cassert>
+
+namespace Geom {
+
+namespace {
+/// Return true if `p` is inside a unit rectangle
+inline bool unit_rect_contains(Point const &p)
+{
+ return 0 <= p.x() && p.x() <= 1 && //
+ 0 <= p.y() && p.y() <= 1;
+}
+
+/// N'th corner of a unit rectangle
+inline Point unit_rect_corner(unsigned i)
+{
+ assert(i < 4);
+ unsigned const y = i >> 1;
+ unsigned const x = (i & 1) ^ y;
+ return Point(x, y);
+}
+} // namespace
+
+Point Parallelogram::corner(unsigned i) const
+{
+ assert(i < 4);
+ return unit_rect_corner(i) * m_affine;
+}
+
+Rect Parallelogram::bounds() const
+{
+ Rect rect(corner(0), corner(2));
+ rect.expandTo(corner(1));
+ rect.expandTo(corner(3));
+ return rect;
+}
+
+bool Parallelogram::intersects(Parallelogram const &other) const
+{
+ if (m_affine.isSingular() || other.m_affine.isSingular()) {
+ return false;
+ }
+
+ auto const affine1 = other.m_affine * m_affine.inverse();
+ auto const affine2 = affine1.inverse();
+
+ // case 1: any corner inside the other rectangle
+ for (unsigned i = 0; i != 4; ++i) {
+ auto const p = unit_rect_corner(i);
+ if (unit_rect_contains(p * affine1) || //
+ unit_rect_contains(p * affine2)) {
+ return true;
+ }
+ }
+
+ // case 2: any sides intersect (check diagonals)
+ for (unsigned i = 0; i != 2; ++i) {
+ auto const A = corner(i);
+ auto const B = corner((i + 2) % 4);
+ for (unsigned j = 0; j != 2; ++j) {
+ auto const C = other.corner(j);
+ auto const D = other.corner((j + 2) % 4);
+ if (non_collinear_segments_intersect(A, B, C, D)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool Parallelogram::contains(Point const &p) const
+{
+ return !m_affine.isSingular() && //
+ unit_rect_contains(p * m_affine.inverse());
+}
+
+bool Parallelogram::contains(Parallelogram const &other) const
+{
+ if (m_affine.isSingular()) {
+ return false;
+ }
+
+ auto const inv = m_affine.inverse();
+
+ for (unsigned i = 0; i != 4; ++i) {
+ if (!unit_rect_contains(other.corner(i) * inv)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+Coord Parallelogram::minExtent() const
+{
+ return std::min(m_affine.expansionX(), //
+ m_affine.expansionY());
+}
+
+Coord Parallelogram::maxExtent() const
+{
+ return std::max(m_affine.expansionX(), //
+ m_affine.expansionY());
+}
+
+bool Parallelogram::isSheared(Coord eps) const
+{
+ return !are_near(dot(m_affine.xAxis(), m_affine.yAxis()), //
+ 0.0, eps);
+}
+
+} // namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/parting-point.cpp b/src/3rdparty/2geom/src/2geom/parting-point.cpp
new file mode 100644
index 0000000..3e3e803
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/parting-point.cpp
@@ -0,0 +1,280 @@
+/** @file Implementation of parting_point(Path const&, Path const&, Coord)
+ */
+/* An algorithm to find the first parting point of two paths.
+ *
+ * Authors:
+ * Rafał Siejakowski <rs@rs-math.net>
+ *
+ * Copyright 2022 the Authors.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/path.h>
+#include <2geom/point.h>
+
+namespace Geom
+{
+
+PathIntersection parting_point(Path const &first, Path const &second, Coord precision)
+{
+ Path const *paths[2] = { &first, &second };
+ Point const starts[2] = { first.initialPoint(), second.initialPoint() };
+
+ if (!are_near(starts[0], starts[1], precision)) {
+ auto const invalid = PathTime(0, -1.0);
+ return PathIntersection(invalid, invalid, middle_point(starts[0], starts[1]));
+ }
+
+ if (first.empty() || second.empty()) {
+ auto const start_time = PathTime(0, 0.0);
+ return PathIntersection(start_time, start_time, middle_point(starts[0], starts[1]));
+ }
+
+ size_t const curve_count[2] = { first.size(), second.size() };
+ Coord const max_time[2] = { first.timeRange().max(), second.timeRange().max() };
+
+ /// Curve indices up until which the paths are known to overlap
+ unsigned pos[2] = { 0, 0 };
+ /// Curve times on the curves with indices pos[] up until which the
+ /// curves are known to overlap ahead of the nodes.
+ Coord curve_times[2] = { 0.0, 0.0 };
+
+ bool leg = 0; ///< Flag indicating which leg is stepping on the ladder
+ bool just_changed_legs = false;
+
+ /* The ladder algorithm takes steps along the two paths, as if they the stiles of
+ * an imaginary ladder. Note that the nodes (X) on boths paths may not coincide:
+ *
+ * paths[0] START--------X-----------X-----------------------X---------X----> ...
+ * paths[1] START--------------X-----------------X-----------X--------------> ...
+ *
+ * The variables pos[0], pos[1] are the indices of the nodes we've cleared so far;
+ * i.e., we know that the portions before pos[] overlap.
+ *
+ * In each iteration of the loop, we move to the next node along one of the paths;
+ * the variable `leg` tells us which path. We find the point nearest to that node
+ * on the first unprocessed curve of the other path and check the curve time.
+ *
+ * Suppose the current node positions are denoted by P; one possible location of
+ * the nearest point (N) to the next node is:
+ *
+ * ----P------------------N--X---- paths[!leg]
+ * --------P--------------X------- paths[leg] (we've stepped forward from P to X)
+ *
+ * We detect this situation when we find that the curve time of N is < 1.0.
+ * We then create a trimmed version of the top curve so that it corresponds to
+ * the current bottom curve:
+ *
+ * ----P----------------------N--X---------- paths[!leg]
+ * [------------------] trimmed curve
+ * --------P------------------X------------- paths[leg]
+ *
+ * Using isNear(), we can compare the trimmed curve to the front curve (P--X) on
+ * paths[leg]; if they are indeed near, then pos[leg] can be incremented.
+ *
+ * Another possibility is that we overstep the end of the other curve:
+ *
+ * ----P-----------------X------------------ paths[!leg]
+ * N
+ * --------P------------------X------------- paths[leg]
+ *
+ * so the nearest point N now coincides with a node on the top path. We detect
+ * this situation by observing that the curve time of N is close to 1. In case
+ * of such overstep, we change legs by flipping the `leg` variable:
+ *
+ * ----P-----------------X------------------ paths[leg]
+ * --------P------------------X------------- paths[!leg]
+ *
+ * We can now continue the stepping procedure, but the next step will be taken on
+ * the path `paths[leg]`, so it should be a shorter step (if it isn't, the paths
+ * must have diverged and we're done):
+ *
+ * ----P-----------------X------------------ paths[leg]
+ * --------P-------------N----X------------- paths[!leg]
+ *
+ * Another piece of data we hold on to are the curve times on the current curves
+ * up until which the paths have been found to coincide. In other words, at every
+ * step of the algorithm we know that the curves agree up to the path-times
+ * PathTime(pos[i], curve_times[i]).
+ *
+ * In the situation mentioned just above, the times (T) will be as follows:
+ *
+ * ----P---T-------------X------------------ paths[leg]
+ *
+ * --------P-------------N----X------------- paths[!leg]
+ * T
+ *
+ * In this example, the time on top path is > 0.0, since the T mark is further
+ * ahead than P on that path. This value of the curve time is needed to correctly
+ * crop the top curve for the purpose of the isNear() comparison:
+ *
+ * ----P---T-------------X---------- paths[leg]
+ * [-------------] comparison curve (cropped from paths[leg])
+ * [-------------] comparison curve (cropped from paths[!leg])
+ * --------P-------------N----X----- paths[!leg]
+ * T
+ *
+ * In fact, the lower end of the curve time range for cropping is always
+ * given by curve_times[i].
+ *
+ * The iteration ends when we find that the two paths have diverged or when we
+ * reach the end. When that happens, the positions and curve times will be
+ * the PathTime components of the actual point of divergence on both paths.
+ */
+
+ /// A closure to crop and compare the curve pieces ([----] in the diagrams above).
+ auto const pieces_agree = [&](Coord time_on_other) -> bool {
+ Curve *pieces[2];
+ // The leg-side curve is always cropped to the end:
+ pieces[ leg] = paths[ leg]->at(pos[ leg]).portion(curve_times[ leg], 1.0);
+ // The other one is cropped to a variable curve time:
+ pieces[!leg] = paths[!leg]->at(pos[!leg]).portion(curve_times[!leg], time_on_other);
+ bool ret = pieces[0]->isNear(*pieces[1], precision);
+ delete pieces[0];
+ delete pieces[1];
+ return ret;
+ };
+
+ /// A closure to skip degenerate curves; returns true if we reached the end.
+ auto const skip_degenerates = [&](size_t which) -> bool {
+ while (paths[which]->at(pos[which]).isDegenerate()) {
+ ++pos[which];
+ curve_times[which] = 0.0;
+ if (pos[which] == curve_count[which]) {
+ return true; // We've reached the end
+ }
+ }
+ return false;
+ };
+
+ // Main loop of the ladder algorithm.
+ while (pos[0] < curve_count[0] && pos[1] < curve_count[1]) {
+ // Skip degenerate curves if any.
+ if (skip_degenerates(0)) {
+ break;
+ }
+ if (skip_degenerates(1)) {
+ break;
+ }
+
+ // Try to step to the next node with the current leg and see what happens.
+ Coord forward_coord = (Coord)(pos[leg] + 1);
+ if (forward_coord > max_time[leg]) {
+ forward_coord = max_time[leg];
+ }
+ auto const step_point = paths[leg]->pointAt(forward_coord);
+ auto const time_on_other = paths[!leg]->at(pos[!leg]).nearestTime(step_point);
+
+ if (are_near(time_on_other, 1.0, precision) &&
+ are_near(step_point, paths[!leg]->pointAt(pos[!leg] + 1), precision))
+ { // The step took us very near to the first uncertified node on the other path.
+ just_changed_legs = false;
+ //
+ // -------PT-----------------X---------- paths[!leg]
+ // --P-----T-----------------X---------- paths[leg]
+ // ^
+ // endpoints (almost) coincide
+ //
+ // We should compare the curves cropped to the end:
+ //
+ // --------T-----------------X---------- paths[!leg]
+ // [-----------------]
+ // [-----------------]
+ // --------T-----------------X---------- paths[leg]
+ if (pieces_agree(1.0)) {
+ // The curves are nearly identical, so we advance both positions
+ // and zero out the forward curve times.
+ for (size_t i = 0; i < 2; i++) {
+ pos[i]++;
+ curve_times[i] = 0.0;
+ }
+ } else { // We've diverged.
+ break;
+ }
+ } else if (time_on_other < 1.0 - precision) {
+ just_changed_legs = false;
+
+ // The other curve is longer than our step! We trim the other curve to the point
+ // nearest to the step point and compare the resulting pieces.
+ //
+ // --------T-----------------N--------X---- paths[!leg]
+ // [-----------------]
+ // [-----------------]
+ // --------T-----------------X------------- paths[leg]
+ //
+ if (pieces_agree(time_on_other)) { // The curve pieces are near to one another!
+ // We can advance our position and zero out the curve time:
+ pos[leg]++;
+ curve_times[leg] = 0.0;
+ // But on the other path, we can only advance the time, not the curve index:
+ curve_times[!leg] = time_on_other;
+ } else { // We've diverged.
+ break;
+ }
+ } else {
+ // The other curve is shorter than ours, which means that we've overstepped.
+ // We change legs and try to take a shorter step in the next iteration.
+ if (just_changed_legs) {
+ // We already changed legs before and it didn't help, i.e., we've diverged.
+ break;
+ } else {
+ leg = !leg;
+ just_changed_legs = true;
+ }
+ }
+ }
+
+ // Compute the parting time on both paths
+ PathTime path_times[2];
+ for (size_t i = 0; i < 2; i++) {
+ path_times[i] = (pos[i] == curve_count[i]) ? PathTime(curve_count[i] - 1, 1.0)
+ : PathTime(pos[i], curve_times[i]);
+ }
+
+ // Get the parting point from the numerically nicest source
+ Point parting_pt;
+ if (curve_times[0] == 0.0) {
+ parting_pt = paths[0]->pointAt(path_times[0]);
+ } else if (curve_times[1] == 0.0) {
+ parting_pt = paths[1]->pointAt(path_times[1]);
+ } else {
+ parting_pt = middle_point(first.pointAt(path_times[0]), second.pointAt(path_times[1]));
+ }
+
+ return PathIntersection(path_times[0], path_times[1], std::move(parting_pt));
+}
+
+} // namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/path-extrema.cpp b/src/3rdparty/2geom/src/2geom/path-extrema.cpp
new file mode 100644
index 0000000..319ccec
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/path-extrema.cpp
@@ -0,0 +1,156 @@
+/** @file Implementation of Path::extrema()
+ */
+/* An algorithm to find the points on a path where a given coordinate
+ * attains its minimum and maximum values.
+ *
+ * Authors:
+ * Rafał Siejakowski <rs@rs-math.net>
+ *
+ * Copyright 2022 the Authors.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/curve.h>
+#include <2geom/path.h>
+#include <2geom/point.h>
+
+namespace Geom {
+
+/** Returns +1 for positive numbers, -1 for negative numbers, and 0 otherwise. */
+inline static float sign(double number)
+{
+ if (number > 0.0) {
+ return 1.0;
+ } else if (number < 0.0) {
+ return -1.0;
+ }
+ return 0.0;
+}
+
+/** @brief Determine whether the d-coordinate increases or decreases at the given path time.
+ *
+ * @param path A path.
+ * @param time A forward-normalized time on the given path.
+ * @param d The coordinate about which we want to know whether it increases.
+ * @return +1.0 if the coordinate increases, -1.0 if it decreases, 0.0 if it remains constant.
+*/
+static float find_direction_of_travel(Path const &path, PathTime const &time, Dim2 d)
+{
+ if (time.t == 0.0) { // We're at a node point
+ if (time.curve_index == 0) { // Starting point of the path.
+ if (path.closed()) {
+ return sign(path.initialUnitTangent()[d] + path.finalUnitTangent()[d]);
+ } else {
+ return sign(path.initialUnitTangent()[d]);
+ }
+ } else if (time.curve_index == path.size()) { // End point of the path.
+ if (path.closed()) {
+ return sign(path.initialUnitTangent()[d] + path.finalUnitTangent()[d]);
+ } else {
+ return sign(path.finalUnitTangent()[d]);
+ }
+ }
+
+ // Otherwise, check the average of the two unit tangent vectors.
+ auto const outgoing_tangent = path.curveAt(time.curve_index).unitTangentAt(0.0);
+ auto const incoming_tangent = path.curveAt(time.curve_index - 1).unitTangentAt(1.0);
+ return sign(outgoing_tangent[d] + incoming_tangent[d]);
+ }
+ // We're in the middle of a curve
+ return sign(path.curveAt(time.curve_index).unitTangentAt(time.t)[d]);
+}
+
+/* Find information about the points on the path where the specified
+ * coordinate attains its minimum and maximum values.
+ */
+PathExtrema Path::extrema(Dim2 d) const
+{
+ auto const ZERO_TIME = PathTime(0, 0);
+
+ // Handle the trivial case of an empty path.
+ if (empty()) {
+ auto const origin = initialPoint();
+ return PathExtrema{
+ .min_point = origin,
+ .max_point = origin,
+ .glance_direction_at_min = 0.0,
+ .glance_direction_at_max = 0.0,
+ .min_time = ZERO_TIME,
+ .max_time = ZERO_TIME
+ };
+ }
+
+ // Set up the simultaneous min-max search
+ Point min_point = initialPoint(), max_point = min_point;
+ auto min_time = ZERO_TIME, max_time = ZERO_TIME;
+ unsigned curve_counter = 0;
+
+ /// A closure to update the current minimum and maximum values.
+ auto const update_minmax = [&](Point const &new_point, Coord t) {
+ if (new_point[d] < min_point[d]) {
+ min_point = new_point;
+ min_time = PathTime(curve_counter, t);
+ } else if (new_point[d] > max_point[d]) {
+ max_point = new_point;
+ max_time = PathTime(curve_counter, t);
+ }
+ };
+
+ // Iterate through the curves, searching for min and max.
+ for (auto const &curve : _data->curves) {
+ // Check the starting node first
+ update_minmax(curve.initialPoint(), 0.0);
+
+ // Check the critical points (zeroes of the derivative).
+ std::unique_ptr<Curve> const derivative{curve.derivative()};
+ for (auto root : derivative->roots(0.0, d)) {
+ update_minmax(curve.pointAt(root), root);
+ }
+ curve_counter++;
+ }
+
+ auto const other = other_dimension(d);
+ return PathExtrema{
+ .min_point = min_point,
+ .max_point = max_point,
+ .glance_direction_at_min = find_direction_of_travel(*this, min_time, other),
+ .glance_direction_at_max = find_direction_of_travel(*this, max_time, other),
+ .min_time = min_time,
+ .max_time = max_time
+ };
+}
+
+} // namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/path-intersection.cpp b/src/3rdparty/2geom/src/2geom/path-intersection.cpp
new file mode 100644
index 0000000..280d7ba
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/path-intersection.cpp
@@ -0,0 +1,728 @@
+#include <2geom/path-intersection.h>
+
+#include <2geom/ord.h>
+
+//for path_direction:
+#include <2geom/sbasis-geometric.h>
+#include <2geom/line.h>
+#ifdef HAVE_GSL
+#include <gsl/gsl_vector.h>
+#include <gsl/gsl_multiroots.h>
+#endif
+
+namespace Geom {
+
+/// Compute winding number of the path at the specified point
+int winding(Path const &path, Point const &p) {
+ return path.winding(p);
+}
+
+/**
+ * This function should only be applied to simple paths (regions), as otherwise
+ * a boolean winding direction is undefined. It returns true for fill, false for
+ * hole. Defaults to using the sign of area when it reaches funny cases.
+ */
+bool path_direction(Path const &p) {
+ if(p.empty()) return false;
+
+ /*goto doh;
+ //could probably be more efficient, but this is a quick job
+ double y = p.initialPoint()[Y];
+ double x = p.initialPoint()[X];
+ Cmp res = cmp(p[0].finalPoint()[Y], y);
+ for(unsigned i = 1; i < p.size(); i++) {
+ Cmp final_to_ray = cmp(p[i].finalPoint()[Y], y);
+ Cmp initial_to_ray = cmp(p[i].initialPoint()[Y], y);
+ // if y is included, these will have opposite values, giving order.
+ Cmp c = cmp(final_to_ray, initial_to_ray);
+ if(c != EQUAL_TO) {
+ std::vector<double> rs = p[i].roots(y, Y);
+ for(unsigned j = 0; j < rs.size(); j++) {
+ double nx = p[i].valueAt(rs[j], X);
+ if(nx > x) {
+ x = nx;
+ res = c;
+ }
+ }
+ } else if(final_to_ray == EQUAL_TO) goto doh;
+ }
+ return res < 0;
+
+ doh:*/
+ //Otherwise fallback on area
+
+ Piecewise<D2<SBasis> > pw = p.toPwSb();
+ double area;
+ Point centre;
+ Geom::centroid(pw, centre, area);
+ return area > 0;
+}
+
+//pair intersect code based on njh's pair-intersect
+
+/** A little sugar for appending a list to another */
+template<typename T>
+void append(T &a, T const &b) {
+ a.insert(a.end(), b.begin(), b.end());
+}
+
+/**
+ * Finds the intersection between the lines defined by A0 & A1, and B0 & B1.
+ * Returns through the last 3 parameters, returning the t-values on the lines
+ * and the cross-product of the deltas (a useful byproduct). The return value
+ * indicates if the time values are within their proper range on the line segments.
+ */
+bool
+linear_intersect(Point const &A0, Point const &A1, Point const &B0, Point const &B1,
+ double &tA, double &tB, double &det) {
+ bool both_lines_non_zero = (!are_near(A0, A1)) && (!are_near(B0, B1));
+
+ // Cramer's rule as cross products
+ Point Ad = A1 - A0,
+ Bd = B1 - B0,
+ d = B0 - A0;
+ det = cross(Ad, Bd);
+
+ double det_rel = det; // Calculate the determinant of the normalized vectors
+ if (both_lines_non_zero) {
+ det_rel /= Ad.length();
+ det_rel /= Bd.length();
+ }
+
+ if( fabs(det_rel) < 1e-12 ) { // If the cross product is NEARLY zero,
+ // Then one of the linesegments might have length zero
+ if (both_lines_non_zero) {
+ // If that's not the case, then we must have either:
+ // - parallel lines, with no intersections, or
+ // - coincident lines, with an infinite number of intersections
+ // Either is quite useless, so we'll just bail out
+ return false;
+ } // Else, one of the linesegments is zero, and we might still be able to calculate a single intersection point
+ } // Else we haven't bailed out, and we'll try to calculate the intersections
+
+ double detinv = 1.0 / det;
+ tA = cross(d, Bd) * detinv;
+ tB = cross(d, Ad) * detinv;
+ return (tA >= 0.) && (tA <= 1.) && (tB >= 0.) && (tB <= 1.);
+}
+
+
+#if 0
+typedef union dbl_64{
+ long long i64;
+ double d64;
+};
+
+static double EpsilonOf(double value)
+{
+ dbl_64 s;
+ s.d64 = value;
+ if(s.i64 == 0)
+ {
+ s.i64++;
+ return s.d64 - value;
+ }
+ else if(s.i64-- < 0)
+ return s.d64 - value;
+ else
+ return value - s.d64;
+}
+#endif
+
+#ifdef HAVE_GSL
+struct rparams {
+ Curve const &A;
+ Curve const &B;
+};
+
+static int
+intersect_polish_f (const gsl_vector * x, void *params,
+ gsl_vector * f)
+{
+ const double x0 = gsl_vector_get (x, 0);
+ const double x1 = gsl_vector_get (x, 1);
+
+ Geom::Point dx = ((struct rparams *) params)->A(x0) -
+ ((struct rparams *) params)->B(x1);
+
+ gsl_vector_set (f, 0, dx[0]);
+ gsl_vector_set (f, 1, dx[1]);
+
+ return GSL_SUCCESS;
+}
+#endif
+
+static void
+intersect_polish_root (Curve const &A, double &s, Curve const &B, double &t)
+{
+ std::vector<Point> as, bs;
+ as = A.pointAndDerivatives(s, 2);
+ bs = B.pointAndDerivatives(t, 2);
+ Point F = as[0] - bs[0];
+ double best = dot(F, F);
+
+ for(int i = 0; i < 4; i++) {
+
+ /**
+ we want to solve
+ J*(x1 - x0) = f(x0)
+
+ |dA(s)[0] -dB(t)[0]| (X1 - X0) = A(s) - B(t)
+ |dA(s)[1] -dB(t)[1]|
+ **/
+
+ // We're using the standard transformation matricies, which is numerically rather poor. Much better to solve the equation using elimination.
+
+ Affine jack(as[1][0], as[1][1],
+ -bs[1][0], -bs[1][1],
+ 0, 0);
+ Point soln = (F)*jack.inverse();
+ double ns = s - soln[0];
+ double nt = t - soln[1];
+
+ if (ns<0) ns=0;
+ else if (ns>1) ns=1;
+ if (nt<0) nt=0;
+ else if (nt>1) nt=1;
+
+ as = A.pointAndDerivatives(ns, 2);
+ bs = B.pointAndDerivatives(nt, 2);
+ F = as[0] - bs[0];
+ double trial = dot(F, F);
+ if (trial > best*0.1) // we have standards, you know
+ // At this point we could do a line search
+ break;
+ best = trial;
+ s = ns;
+ t = nt;
+ }
+
+#ifdef HAVE_GSL
+ if(0) { // the GSL version is more accurate, but taints this with GPL
+ int status;
+ size_t iter = 0;
+ const size_t n = 2;
+ struct rparams p = {A, B};
+ gsl_multiroot_function f = {&intersect_polish_f, n, &p};
+
+ double x_init[2] = {s, t};
+ gsl_vector *x = gsl_vector_alloc (n);
+
+ gsl_vector_set (x, 0, x_init[0]);
+ gsl_vector_set (x, 1, x_init[1]);
+
+ const gsl_multiroot_fsolver_type *T = gsl_multiroot_fsolver_hybrids;
+ gsl_multiroot_fsolver *sol = gsl_multiroot_fsolver_alloc (T, 2);
+ gsl_multiroot_fsolver_set (sol, &f, x);
+
+ do
+ {
+ iter++;
+ status = gsl_multiroot_fsolver_iterate (sol);
+
+ if (status) /* check if solver is stuck */
+ break;
+
+ status =
+ gsl_multiroot_test_residual (sol->f, 1e-12);
+ }
+ while (status == GSL_CONTINUE && iter < 1000);
+
+ s = gsl_vector_get (sol->x, 0);
+ t = gsl_vector_get (sol->x, 1);
+
+ gsl_multiroot_fsolver_free (sol);
+ gsl_vector_free (x);
+ }
+#endif
+}
+
+/**
+ * This uses the local bounds functions of curves to generically intersect two.
+ * It passes in the curves, time intervals, and keeps track of depth, while
+ * returning the results through the Crossings parameter.
+ */
+void pair_intersect(Curve const & A, double Al, double Ah,
+ Curve const & B, double Bl, double Bh,
+ Crossings &ret, unsigned depth = 0) {
+ // std::cout << depth << "(" << Al << ", " << Ah << ")\n";
+ OptRect Ar = A.boundsLocal(Interval(Al, Ah));
+ if (!Ar) return;
+
+ OptRect Br = B.boundsLocal(Interval(Bl, Bh));
+ if (!Br) return;
+
+ if(! Ar->intersects(*Br)) return;
+
+ //Checks the general linearity of the function
+ if((depth > 12)) { // || (A.boundsLocal(Interval(Al, Ah), 1).maxExtent() < 0.1
+ //&& B.boundsLocal(Interval(Bl, Bh), 1).maxExtent() < 0.1)) {
+ double tA, tB, c;
+ if(linear_intersect(A.pointAt(Al), A.pointAt(Ah),
+ B.pointAt(Bl), B.pointAt(Bh),
+ tA, tB, c)) {
+ tA = tA * (Ah - Al) + Al;
+ tB = tB * (Bh - Bl) + Bl;
+ intersect_polish_root(A, tA,
+ B, tB);
+ if(depth % 2)
+ ret.push_back(Crossing(tB, tA, c < 0));
+ else
+ ret.push_back(Crossing(tA, tB, c > 0));
+ return;
+ }
+ }
+ if(depth > 12) return;
+ double mid = (Bl + Bh)/2;
+ pair_intersect(B, Bl, mid,
+ A, Al, Ah,
+ ret, depth+1);
+ pair_intersect(B, mid, Bh,
+ A, Al, Ah,
+ ret, depth+1);
+}
+
+Crossings pair_intersect(Curve const & A, Interval const &Ad,
+ Curve const & B, Interval const &Bd) {
+ Crossings ret;
+ pair_intersect(A, Ad.min(), Ad.max(), B, Bd.min(), Bd.max(), ret);
+ return ret;
+}
+
+/** A simple wrapper around pair_intersect */
+Crossings SimpleCrosser::crossings(Curve const &a, Curve const &b) {
+ Crossings ret;
+ pair_intersect(a, 0, 1, b, 0, 1, ret);
+ return ret;
+}
+
+
+//same as below but curves not paths
+void mono_intersect(Curve const &A, double Al, double Ah,
+ Curve const &B, double Bl, double Bh,
+ Crossings &ret, double tol = 0.1, unsigned depth = 0) {
+ if( Al >= Ah || Bl >= Bh) return;
+ //std::cout << " " << depth << "[" << Al << ", " << Ah << "]" << "[" << Bl << ", " << Bh << "]";
+
+ Point A0 = A.pointAt(Al), A1 = A.pointAt(Ah),
+ B0 = B.pointAt(Bl), B1 = B.pointAt(Bh);
+ //inline code that this implies? (without rect/interval construction)
+ Rect Ar = Rect(A0, A1), Br = Rect(B0, B1);
+ if(!Ar.intersects(Br) || A0 == A1 || B0 == B1) return;
+
+ if(depth > 12 || (Ar.maxExtent() < tol && Ar.maxExtent() < tol)) {
+ double tA, tB, c;
+ if(linear_intersect(A.pointAt(Al), A.pointAt(Ah),
+ B.pointAt(Bl), B.pointAt(Bh),
+ tA, tB, c)) {
+ tA = tA * (Ah - Al) + Al;
+ tB = tB * (Bh - Bl) + Bl;
+ intersect_polish_root(A, tA,
+ B, tB);
+ if(depth % 2)
+ ret.push_back(Crossing(tB, tA, c < 0));
+ else
+ ret.push_back(Crossing(tA, tB, c > 0));
+ return;
+ }
+ }
+ if(depth > 12) return;
+ double mid = (Bl + Bh)/2;
+ mono_intersect(B, Bl, mid,
+ A, Al, Ah,
+ ret, tol, depth+1);
+ mono_intersect(B, mid, Bh,
+ A, Al, Ah,
+ ret, tol, depth+1);
+}
+
+Crossings mono_intersect(Curve const & A, Interval const &Ad,
+ Curve const & B, Interval const &Bd) {
+ Crossings ret;
+ mono_intersect(A, Ad.min(), Ad.max(), B, Bd.min(), Bd.max(), ret);
+ return ret;
+}
+
+/**
+ * Takes two paths and time ranges on them, with the invariant that the
+ * paths are monotonic on the range. Splits A when the linear intersection
+ * doesn't exist or is inaccurate. Uses the fact that it is monotonic to
+ * do very fast local bounds.
+ */
+void mono_pair(Path const &A, double Al, double Ah,
+ Path const &B, double Bl, double Bh,
+ Crossings &ret, double /*tol*/, unsigned depth = 0) {
+ if( Al >= Ah || Bl >= Bh) return;
+ std::cout << " " << depth << "[" << Al << ", " << Ah << "]" << "[" << Bl << ", " << Bh << "]";
+
+ Point A0 = A.pointAt(Al), A1 = A.pointAt(Ah),
+ B0 = B.pointAt(Bl), B1 = B.pointAt(Bh);
+ //inline code that this implies? (without rect/interval construction)
+ Rect Ar = Rect(A0, A1), Br = Rect(B0, B1);
+ if(!Ar.intersects(Br) || A0 == A1 || B0 == B1) return;
+
+ if(depth > 12 || (Ar.maxExtent() < 0.1 && Ar.maxExtent() < 0.1)) {
+ double tA, tB, c;
+ if(linear_intersect(A0, A1, B0, B1,
+ tA, tB, c)) {
+ tA = tA * (Ah - Al) + Al;
+ tB = tB * (Bh - Bl) + Bl;
+ if(depth % 2)
+ ret.push_back(Crossing(tB, tA, c < 0));
+ else
+ ret.push_back(Crossing(tA, tB, c > 0));
+ return;
+ }
+ }
+ if(depth > 12) return;
+ double mid = (Bl + Bh)/2;
+ mono_pair(B, Bl, mid,
+ A, Al, Ah,
+ ret, depth+1);
+ mono_pair(B, mid, Bh,
+ A, Al, Ah,
+ ret, depth+1);
+}
+
+/** This returns the times when the x or y derivative is 0 in the curve. */
+std::vector<double> curve_mono_splits(Curve const &d) {
+ Curve* deriv = d.derivative();
+ std::vector<double> rs = deriv->roots(0, X);
+ append(rs, deriv->roots(0, Y));
+ delete deriv;
+ std::sort(rs.begin(), rs.end());
+ return rs;
+}
+
+/** Convenience function to add a value to each entry in a vector of doubles. */
+std::vector<double> offset_doubles(std::vector<double> const &x, double offs) {
+ std::vector<double> ret;
+ for(double i : x) {
+ ret.push_back(i + offs);
+ }
+ return ret;
+}
+
+/**
+ * Finds all the monotonic splits for a path. Only includes the split between
+ * curves if they switch derivative directions at that point.
+ */
+std::vector<double> path_mono_splits(Path const &p) {
+ std::vector<double> ret;
+ if(p.empty()) return ret;
+
+ int pdx = 2, pdy = 2; // Previous derivative direction
+ for(unsigned i = 0; i < p.size(); i++) {
+ std::vector<double> spl = offset_doubles(curve_mono_splits(p[i]), i);
+ int dx = p[i].initialPoint()[X] > (spl.empty() ? p[i].finalPoint()[X] : p.valueAt(spl.front(), X)) ? 1 : 0;
+ int dy = p[i].initialPoint()[Y] > (spl.empty() ? p[i].finalPoint()[Y] : p.valueAt(spl.front(), Y)) ? 1 : 0;
+ //The direction changed, include the split time
+ if(dx != pdx || dy != pdy) {
+ ret.push_back(i);
+ pdx = dx; pdy = dy;
+ }
+ append(ret, spl);
+ }
+ return ret;
+}
+
+/**
+ * Applies path_mono_splits to multiple paths, and returns the results such that
+ * time-set i corresponds to Path i.
+ */
+std::vector<std::vector<double> > paths_mono_splits(PathVector const &ps) {
+ std::vector<std::vector<double> > ret;
+ for(const auto & p : ps)
+ ret.push_back(path_mono_splits(p));
+ return ret;
+}
+
+/**
+ * Processes the bounds for a list of paths and a list of splits on them, yielding a list of rects for each.
+ * Each entry i corresponds to path i of the input. The number of rects in each entry is guaranteed to be the
+ * number of splits for that path, subtracted by one.
+ */
+std::vector<std::vector<Rect> > split_bounds(PathVector const &p, std::vector<std::vector<double> > splits) {
+ std::vector<std::vector<Rect> > ret;
+ for(unsigned i = 0; i < p.size(); i++) {
+ std::vector<Rect> res;
+ for(unsigned j = 1; j < splits[i].size(); j++)
+ res.emplace_back(p[i].pointAt(splits[i][j-1]), p[i].pointAt(splits[i][j]));
+ ret.push_back(res);
+ }
+ return ret;
+}
+
+/**
+ * This is the main routine of "MonoCrosser", and implements a monotonic strategy on multiple curves.
+ * Finds crossings between two sets of paths, yielding a CrossingSet. [0, a.size()) of the return correspond
+ * to the sorted crossings of a with paths of b. The rest of the return, [a.size(), a.size() + b.size()],
+ * corresponds to the sorted crossings of b with paths of a.
+ *
+ * This function does two sweeps, one on the bounds of each path, and after that cull, one on the curves within.
+ * This leads to a certain amount of code complexity, however, most of that is factored into the above functions
+ */
+CrossingSet MonoCrosser::crossings(PathVector const &a, PathVector const &b) {
+ if(b.empty()) return CrossingSet(a.size(), Crossings());
+ CrossingSet results(a.size() + b.size(), Crossings());
+ if(a.empty()) return results;
+
+ std::vector<std::vector<double> > splits_a = paths_mono_splits(a), splits_b = paths_mono_splits(b);
+ std::vector<std::vector<Rect> > bounds_a = split_bounds(a, splits_a), bounds_b = split_bounds(b, splits_b);
+
+ std::vector<Rect> bounds_a_union, bounds_b_union;
+ for(auto & i : bounds_a) bounds_a_union.push_back(union_list(i));
+ for(auto & i : bounds_b) bounds_b_union.push_back(union_list(i));
+
+ std::vector<std::vector<unsigned> > cull = sweep_bounds(bounds_a_union, bounds_b_union);
+ Crossings n;
+ for(unsigned i = 0; i < cull.size(); i++) {
+ for(unsigned jx = 0; jx < cull[i].size(); jx++) {
+ unsigned j = cull[i][jx];
+ unsigned jc = j + a.size();
+ Crossings res;
+
+ //Sweep of the monotonic portions
+ std::vector<std::vector<unsigned> > cull2 = sweep_bounds(bounds_a[i], bounds_b[j]);
+ for(unsigned k = 0; k < cull2.size(); k++) {
+ for(unsigned lx = 0; lx < cull2[k].size(); lx++) {
+ unsigned l = cull2[k][lx];
+ mono_pair(a[i], splits_a[i][k-1], splits_a[i][k],
+ b[j], splits_b[j][l-1], splits_b[j][l],
+ res, .1);
+ }
+ }
+
+ for(auto & re : res) { re.a = i; re.b = jc; }
+
+ merge_crossings(results[i], res, i);
+ merge_crossings(results[i], res, jc);
+ }
+ }
+
+ return results;
+}
+
+/* This function is similar codewise to the MonoCrosser, the main difference is that it deals with
+ * only one set of paths and includes self intersection
+CrossingSet crossings_among(PathVector const &p) {
+ CrossingSet results(p.size(), Crossings());
+ if(p.empty()) return results;
+
+ std::vector<std::vector<double> > splits = paths_mono_splits(p);
+ std::vector<std::vector<Rect> > prs = split_bounds(p, splits);
+ std::vector<Rect> rs;
+ for(unsigned i = 0; i < prs.size(); i++) rs.push_back(union_list(prs[i]));
+
+ std::vector<std::vector<unsigned> > cull = sweep_bounds(rs);
+
+ //we actually want to do the self-intersections, so add em in:
+ for(unsigned i = 0; i < cull.size(); i++) cull[i].push_back(i);
+
+ for(unsigned i = 0; i < cull.size(); i++) {
+ for(unsigned jx = 0; jx < cull[i].size(); jx++) {
+ unsigned j = cull[i][jx];
+ Crossings res;
+
+ //Sweep of the monotonic portions
+ std::vector<std::vector<unsigned> > cull2 = sweep_bounds(prs[i], prs[j]);
+ for(unsigned k = 0; k < cull2.size(); k++) {
+ for(unsigned lx = 0; lx < cull2[k].size(); lx++) {
+ unsigned l = cull2[k][lx];
+ mono_pair(p[i], splits[i][k-1], splits[i][k],
+ p[j], splits[j][l-1], splits[j][l],
+ res, .1);
+ }
+ }
+
+ for(unsigned k = 0; k < res.size(); k++) { res[k].a = i; res[k].b = j; }
+
+ merge_crossings(results[i], res, i);
+ merge_crossings(results[j], res, j);
+ }
+ }
+
+ return results;
+}
+*/
+
+
+Crossings curve_self_crossings(Curve const &a) {
+ Crossings res;
+ std::vector<double> spl;
+ spl.push_back(0);
+ append(spl, curve_mono_splits(a));
+ spl.push_back(1);
+ for(unsigned i = 1; i < spl.size(); i++)
+ for(unsigned j = i+1; j < spl.size(); j++)
+ pair_intersect(a, spl[i-1], spl[i], a, spl[j-1], spl[j], res);
+ return res;
+}
+
+/*
+void mono_curve_intersect(Curve const & A, double Al, double Ah,
+ Curve const & B, double Bl, double Bh,
+ Crossings &ret, unsigned depth=0) {
+ // std::cout << depth << "(" << Al << ", " << Ah << ")\n";
+ Point A0 = A.pointAt(Al), A1 = A.pointAt(Ah),
+ B0 = B.pointAt(Bl), B1 = B.pointAt(Bh);
+ //inline code that this implies? (without rect/interval construction)
+ if(!Rect(A0, A1).intersects(Rect(B0, B1)) || A0 == A1 || B0 == B1) return;
+
+ //Checks the general linearity of the function
+ if((depth > 12) || (A.boundsLocal(Interval(Al, Ah), 1).maxExtent() < 0.1
+ && B.boundsLocal(Interval(Bl, Bh), 1).maxExtent() < 0.1)) {
+ double tA, tB, c;
+ if(linear_intersect(A0, A1, B0, B1, tA, tB, c)) {
+ tA = tA * (Ah - Al) + Al;
+ tB = tB * (Bh - Bl) + Bl;
+ if(depth % 2)
+ ret.push_back(Crossing(tB, tA, c < 0));
+ else
+ ret.push_back(Crossing(tA, tB, c > 0));
+ return;
+ }
+ }
+ if(depth > 12) return;
+ double mid = (Bl + Bh)/2;
+ mono_curve_intersect(B, Bl, mid,
+ A, Al, Ah,
+ ret, depth+1);
+ mono_curve_intersect(B, mid, Bh,
+ A, Al, Ah,
+ ret, depth+1);
+}
+
+std::vector<std::vector<double> > curves_mono_splits(Path const &p) {
+ std::vector<std::vector<double> > ret;
+ for(unsigned i = 0; i <= p.size(); i++) {
+ std::vector<double> spl;
+ spl.push_back(0);
+ append(spl, curve_mono_splits(p[i]));
+ spl.push_back(1);
+ ret.push_back(spl);
+ }
+}
+
+std::vector<std::vector<Rect> > curves_split_bounds(Path const &p, std::vector<std::vector<double> > splits) {
+ std::vector<std::vector<Rect> > ret;
+ for(unsigned i = 0; i < splits.size(); i++) {
+ std::vector<Rect> res;
+ for(unsigned j = 1; j < splits[i].size(); j++)
+ res.push_back(Rect(p.pointAt(splits[i][j-1]+i), p.pointAt(splits[i][j]+i)));
+ ret.push_back(res);
+ }
+ return ret;
+}
+
+Crossings path_self_crossings(Path const &p) {
+ Crossings ret;
+ std::vector<std::vector<unsigned> > cull = sweep_bounds(bounds(p));
+ std::vector<std::vector<double> > spl = curves_mono_splits(p);
+ std::vector<std::vector<Rect> > bnds = curves_split_bounds(p, spl);
+ for(unsigned i = 0; i < cull.size(); i++) {
+ Crossings res;
+ for(unsigned k = 1; k < spl[i].size(); k++)
+ for(unsigned l = k+1; l < spl[i].size(); l++)
+ mono_curve_intersect(p[i], spl[i][k-1], spl[i][k], p[i], spl[i][l-1], spl[i][l], res);
+ offset_crossings(res, i, i);
+ append(ret, res);
+ for(unsigned jx = 0; jx < cull[i].size(); jx++) {
+ unsigned j = cull[i][jx];
+ res.clear();
+
+ std::vector<std::vector<unsigned> > cull2 = sweep_bounds(bnds[i], bnds[j]);
+ for(unsigned k = 0; k < cull2.size(); k++) {
+ for(unsigned lx = 0; lx < cull2[k].size(); lx++) {
+ unsigned l = cull2[k][lx];
+ mono_curve_intersect(p[i], spl[i][k-1], spl[i][k], p[j], spl[j][l-1], spl[j][l], res);
+ }
+ }
+
+ //if(fabs(int(i)-j) == 1 || fabs(int(i)-j) == p.size()-1) {
+ Crossings res2;
+ for(unsigned k = 0; k < res.size(); k++) {
+ if(res[k].ta != 0 && res[k].ta != 1 && res[k].tb != 0 && res[k].tb != 1) {
+ res.push_back(res[k]);
+ }
+ }
+ res = res2;
+ //}
+ offset_crossings(res, i, j);
+ append(ret, res);
+ }
+ }
+ return ret;
+}
+*/
+
+Crossings self_crossings(Path const &p) {
+ Crossings ret;
+ std::vector<std::vector<unsigned> > cull = sweep_bounds(bounds(p));
+ for(unsigned i = 0; i < cull.size(); i++) {
+ Crossings res = curve_self_crossings(p[i]);
+ offset_crossings(res, i, i);
+ append(ret, res);
+ for(unsigned jx = 0; jx < cull[i].size(); jx++) {
+ unsigned j = cull[i][jx];
+ res.clear();
+ pair_intersect(p[i], 0, 1, p[j], 0, 1, res);
+
+ //if(fabs(int(i)-j) == 1 || fabs(int(i)-j) == p.size()-1) {
+ Crossings res2;
+ for(auto & re : res) {
+ if(re.ta != 0 && re.ta != 1 && re.tb != 0 && re.tb != 1) {
+ res2.push_back(re);
+ }
+ }
+ res = res2;
+ //}
+ offset_crossings(res, i, j);
+ append(ret, res);
+ }
+ }
+ return ret;
+}
+
+void flip_crossings(Crossings &crs) {
+ for(auto & cr : crs)
+ cr = Crossing(cr.tb, cr.ta, cr.b, cr.a, !cr.dir);
+}
+
+CrossingSet crossings_among(PathVector const &p) {
+ CrossingSet results(p.size(), Crossings());
+ if(p.empty()) return results;
+
+ SimpleCrosser cc;
+
+ std::vector<std::vector<unsigned> > cull = sweep_bounds(bounds(p));
+ for(unsigned i = 0; i < cull.size(); i++) {
+ Crossings res = self_crossings(p[i]);
+ for(auto & re : res) { re.a = re.b = i; }
+ merge_crossings(results[i], res, i);
+ flip_crossings(res);
+ merge_crossings(results[i], res, i);
+ for(unsigned jx = 0; jx < cull[i].size(); jx++) {
+ unsigned j = cull[i][jx];
+
+ Crossings res = cc.crossings(p[i], p[j]);
+ for(auto & re : res) { re.a = i; re.b = j; }
+ merge_crossings(results[i], res, i);
+ merge_crossings(results[j], res, j);
+ }
+ }
+ return results;
+}
+
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/path-sink.cpp b/src/3rdparty/2geom/src/2geom/path-sink.cpp
new file mode 100644
index 0000000..1a22c81
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/path-sink.cpp
@@ -0,0 +1,104 @@
+/*
+ * callback interface for SVG path data
+ *
+ * Copyright 2007 MenTaLguY <mental@rydia.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, output to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/path-sink.h>
+#include <2geom/exception.h>
+#include <2geom/circle.h>
+#include <2geom/ellipse.h>
+
+namespace Geom {
+
+void PathSink::feed(Curve const &c, bool moveto_initial)
+{
+ c.feed(*this, moveto_initial);
+}
+
+void PathSink::feed(Path const &path) {
+ flush();
+ moveTo(path.front().initialPoint());
+
+ // never output the closing segment to the sink
+ Path::const_iterator iter = path.begin(), last = path.end_open();
+ for (; iter != last; ++iter) {
+ iter->feed(*this, false);
+ }
+ if (path.closed()) {
+ closePath();
+ }
+ flush();
+}
+
+void PathSink::feed(PathVector const &pv) {
+ for (const auto & i : pv) {
+ feed(i);
+ }
+}
+
+void PathSink::feed(Rect const &r) {
+ moveTo(r.corner(0));
+ lineTo(r.corner(1));
+ lineTo(r.corner(2));
+ lineTo(r.corner(3));
+ closePath();
+}
+
+void PathSink::feed(Circle const &e) {
+ Coord r = e.radius();
+ Point c = e.center();
+ Point a = c + Point(0, +r);
+ Point b = c + Point(0, -r);
+
+ moveTo(a);
+ arcTo(r, r, 0, false, false, b);
+ arcTo(r, r, 0, false, false, a);
+ closePath();
+}
+
+void PathSink::feed(Ellipse const &e) {
+ Point s = e.pointAt(0);
+ moveTo(s);
+ arcTo(e.ray(X), e.ray(Y), e.rotationAngle(), false, false, e.pointAt(M_PI));
+ arcTo(e.ray(X), e.ray(Y), e.rotationAngle(), false, false, s);
+ closePath();
+}
+
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/path.cpp b/src/3rdparty/2geom/src/2geom/path.cpp
new file mode 100644
index 0000000..aeff503
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/path.cpp
@@ -0,0 +1,1161 @@
+/** @file
+ * @brief Path - a sequence of contiguous curves (implementation file)
+ *//*
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2007-2014 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/path.h>
+#include <2geom/pathvector.h>
+#include <2geom/transforms.h>
+#include <2geom/circle.h>
+#include <2geom/ellipse.h>
+#include <2geom/convex-hull.h>
+#include <2geom/svg-path-writer.h>
+#include <2geom/sweeper.h>
+#include <algorithm>
+#include <limits>
+#include <optional>
+
+using std::swap;
+using namespace Geom::PathInternal;
+
+namespace Geom {
+
+// this represents an empty interval
+PathInterval::PathInterval()
+ : _from(0, 0.0)
+ , _to(0, 0.0)
+ , _path_size(1)
+ , _cross_start(false)
+ , _reverse(false)
+{}
+
+PathInterval::PathInterval(PathTime const &from, PathTime const &to, bool cross_start, size_type path_size)
+ : _from(from)
+ , _to(to)
+ , _path_size(path_size)
+ , _cross_start(cross_start)
+ , _reverse((to < from) ^ cross_start)
+{
+ if (_reverse) {
+ _to.normalizeForward(_path_size);
+ if (cross_start && _to < to) {
+ // Normalization made us cross start (closed path),
+ // so we don't need to cross the start anymore.
+ _cross_start = false;
+ }
+ if (_from != _to) {
+ _from.normalizeBackward(_path_size);
+ if (cross_start && _from > from) {
+ // Normalization backwards made us logically cross
+ // the start – we shouldn't cross the start again.
+ _cross_start = false;
+ }
+ }
+ } else {
+ _from.normalizeForward(_path_size);
+ if (cross_start && _from < from) {
+ _cross_start = false;
+ }
+ if (_from != _to) {
+ _to.normalizeBackward(_path_size);
+ if (cross_start && _to > to) {
+ _cross_start = false;
+ }
+ }
+ }
+
+ if (_from == _to) {
+ _reverse = false;
+ _cross_start = false;
+ }
+}
+
+bool PathInterval::contains(PathTime const &pos) const {
+ if (_cross_start) {
+ if (_reverse) {
+ return pos >= _to || _from >= pos;
+ } else {
+ return pos >= _from || _to >= pos;
+ }
+ } else {
+ if (_reverse) {
+ return _to <= pos && pos <= _from;
+ } else {
+ return _from <= pos && pos <= _to;
+ }
+ }
+}
+
+PathInterval::size_type PathInterval::curveCount() const
+{
+ if (isDegenerate()) return 0;
+ if (_cross_start) {
+ if (_reverse) {
+ return _path_size - _to.curve_index + _from.curve_index + 1;
+ } else {
+ return _path_size - _from.curve_index + _to.curve_index + 1;
+ }
+ } else {
+ if (_reverse) {
+ return _from.curve_index - _to.curve_index + 1;
+ } else {
+ return _to.curve_index - _from.curve_index + 1;
+ }
+ }
+}
+
+PathTime PathInterval::inside(Coord min_dist) const
+{
+ // If there is some node further than min_dist (in time coord) from the ends,
+ // return that node. Otherwise, return the middle.
+ PathTime result(0, 0.0);
+
+ if (!_cross_start && _from.curve_index == _to.curve_index) {
+ PathTime result(_from.curve_index, lerp(0.5, _from.t, _to.t));
+ return result;
+ }
+ // If _cross_start, then we can be sure that at least one node is in the domain.
+ // If dcurve == 0, it actually means that all curves are included in the domain
+
+ if (_reverse) {
+ size_type dcurve = (_path_size + _from.curve_index - _to.curve_index) % _path_size;
+ bool from_close = _from.t < min_dist;
+ bool to_close = _to.t > 1 - min_dist;
+
+ if (dcurve == 0) {
+ dcurve = _path_size;
+ }
+
+ if (dcurve == 1) {
+ if (from_close || to_close) {
+ result.curve_index = _from.curve_index;
+ Coord tmid = _from.t - ((1 - _to.t) + _from.t) * 0.5;
+ if (tmid < 0) {
+ result.curve_index = (_path_size + result.curve_index - 1) % _path_size;
+ tmid += 1;
+ }
+ result.t = tmid;
+ return result;
+ }
+
+ result.curve_index = _from.curve_index;
+ return result;
+ }
+
+ result.curve_index = (_to.curve_index + 1) % _path_size;
+ if (to_close) {
+ if (dcurve == 2) {
+ result.t = 0.5;
+ } else {
+ result.curve_index = (result.curve_index + 1) % _path_size;
+ }
+ }
+ return result;
+ } else {
+ size_type dcurve = (_path_size + _to.curve_index - _from.curve_index) % _path_size;
+ bool from_close = _from.t > 1 - min_dist;
+ bool to_close = _to.t < min_dist;
+
+ if (dcurve == 0) {
+ dcurve = _path_size;
+ }
+
+ if (dcurve == 1) {
+ if (from_close || to_close) {
+ result.curve_index = _from.curve_index;
+ Coord tmid = ((1 - _from.t) + _to.t) * 0.5 + _from.t;
+ if (tmid >= 1) {
+ result.curve_index = (result.curve_index + 1) % _path_size;
+ tmid -= 1;
+ }
+ result.t = tmid;
+ return result;
+ }
+
+ result.curve_index = _to.curve_index;
+ return result;
+ }
+
+ result.curve_index = (_from.curve_index + 1) % _path_size;
+ if (from_close) {
+ if (dcurve == 2) {
+ result.t = 0.5;
+ } else {
+ result.curve_index = (result.curve_index + 1) % _path_size;
+ }
+ }
+ return result;
+ }
+
+ result.curve_index = _reverse ? _from.curve_index : _to.curve_index;
+ return result;
+}
+
+PathInterval PathInterval::from_direction(PathTime const &from, PathTime const &to, bool reversed, size_type path_size)
+{
+ PathInterval result;
+ result._from = from;
+ result._to = to;
+ result._path_size = path_size;
+
+ if (reversed) {
+ result._to.normalizeForward(path_size);
+ if (result._from != result._to) {
+ result._from.normalizeBackward(path_size);
+ }
+ } else {
+ result._from.normalizeForward(path_size);
+ if (result._from != result._to) {
+ result._to.normalizeBackward(path_size);
+ }
+ }
+
+ if (result._from == result._to) {
+ result._reverse = false;
+ result._cross_start = false;
+ } else {
+ result._reverse = reversed;
+ if (reversed) {
+ result._cross_start = from < to;
+ } else {
+ result._cross_start = to < from;
+ }
+ }
+ return result;
+}
+
+
+Path::Path(Rect const &r)
+ : _data(new PathData())
+ , _closing_seg(new ClosingSegment(r.corner(3), r.corner(0)))
+ , _closed(true)
+ , _exception_on_stitch(true)
+{
+ for (unsigned i = 0; i < 3; ++i) {
+ _data->curves.push_back(new LineSegment(r.corner(i), r.corner(i+1)));
+ }
+ _data->curves.push_back(_closing_seg);
+}
+
+Path::Path(ConvexHull const &ch)
+ : _data(new PathData())
+ , _closing_seg(new ClosingSegment(Point(), Point()))
+ , _closed(true)
+ , _exception_on_stitch(true)
+{
+ if (ch.empty()) {
+ _data->curves.push_back(_closing_seg);
+ return;
+ }
+
+ _closing_seg->setInitial(ch.back());
+ _closing_seg->setFinal(ch.front());
+
+ Point last = ch.front();
+
+ for (std::size_t i = 1; i < ch.size(); ++i) {
+ _data->curves.push_back(new LineSegment(last, ch[i]));
+ last = ch[i];
+ }
+
+ _data->curves.push_back(_closing_seg);
+ _closed = true;
+}
+
+Path::Path(Circle const &c)
+ : _data(new PathData())
+ , _closing_seg(NULL)
+ , _closed(true)
+ , _exception_on_stitch(true)
+{
+ Point p1 = c.pointAt(0);
+ Point p2 = c.pointAt(M_PI);
+ _data->curves.push_back(new EllipticalArc(p1, c.radius(), c.radius(), 0, false, true, p2));
+ _data->curves.push_back(new EllipticalArc(p2, c.radius(), c.radius(), 0, false, true, p1));
+ _closing_seg = new ClosingSegment(p1, p1);
+ _data->curves.push_back(_closing_seg);
+}
+
+Path::Path(Ellipse const &e)
+ : _data(new PathData())
+ , _closing_seg(NULL)
+ , _closed(true)
+ , _exception_on_stitch(true)
+{
+ Point p1 = e.pointAt(0);
+ Point p2 = e.pointAt(M_PI);
+ _data->curves.push_back(new EllipticalArc(p1, e.rays(), e.rotationAngle(), false, true, p2));
+ _data->curves.push_back(new EllipticalArc(p2, e.rays(), e.rotationAngle(), false, true, p1));
+ _closing_seg = new ClosingSegment(p1, p1);
+ _data->curves.push_back(_closing_seg);
+}
+
+void Path::close(bool c)
+{
+ if (c == _closed) return;
+ if (c && _data->curves.size() >= 2) {
+ // when closing, if last segment is linear and ends at initial point,
+ // replace it with the closing segment
+ Sequence::iterator last = _data->curves.end() - 2;
+ if (last->isLineSegment() && last->finalPoint() == initialPoint()) {
+ _closing_seg->setInitial(last->initialPoint());
+ _data->curves.erase(last);
+ }
+ }
+ _closed = c;
+}
+
+void Path::clear()
+{
+ _unshare();
+ _data->curves.pop_back().release();
+ _data->curves.clear();
+ _closing_seg->setInitial(Point(0, 0));
+ _closing_seg->setFinal(Point(0, 0));
+ _data->curves.push_back(_closing_seg);
+ _closed = false;
+}
+
+OptRect Path::boundsFast() const
+{
+ OptRect bounds;
+ if (empty()) {
+ return bounds;
+ }
+ // if the path is not empty, we look for cached bounds
+ if (_data->fast_bounds) {
+ return _data->fast_bounds;
+ }
+
+ bounds = front().boundsFast();
+ const_iterator iter = begin();
+ // the closing path segment can be ignored, because it will always
+ // lie within the bbox of the rest of the path
+ if (iter != end()) {
+ for (++iter; iter != end(); ++iter) {
+ bounds.unionWith(iter->boundsFast());
+ }
+ }
+ _data->fast_bounds = bounds;
+ return bounds;
+}
+
+OptRect Path::boundsExact() const
+{
+ OptRect bounds;
+ if (empty())
+ return bounds;
+ bounds = front().boundsExact();
+ const_iterator iter = begin();
+ // the closing path segment can be ignored, because it will always lie within the bbox of the rest of the path
+ if (iter != end()) {
+ for (++iter; iter != end(); ++iter) {
+ bounds.unionWith(iter->boundsExact());
+ }
+ }
+ return bounds;
+}
+
+Piecewise<D2<SBasis> > Path::toPwSb() const
+{
+ Piecewise<D2<SBasis> > ret;
+ ret.push_cut(0);
+ unsigned i = 1;
+ bool degenerate = true;
+ // pw<d2<>> is always open. so if path is closed, add closing segment as well to pwd2.
+ for (const_iterator it = begin(); it != end_default(); ++it) {
+ if (!it->isDegenerate()) {
+ ret.push(it->toSBasis(), i++);
+ degenerate = false;
+ }
+ }
+ if (degenerate) {
+ // if path only contains degenerate curves, no second cut is added
+ // so we need to create at least one segment manually
+ ret = Piecewise<D2<SBasis> >(initialPoint());
+ }
+ return ret;
+}
+
+template <typename iter>
+iter inc(iter const &x, unsigned n) {
+ iter ret = x;
+ for (unsigned i = 0; i < n; i++)
+ ret++;
+ return ret;
+}
+
+bool Path::operator==(Path const &other) const
+{
+ if (this == &other)
+ return true;
+ if (_closed != other._closed)
+ return false;
+ return _data->curves == other._data->curves;
+}
+
+void Path::start(Point const &p) {
+ if (_data->curves.size() > 1) {
+ clear();
+ }
+ _closing_seg->setInitial(p);
+ _closing_seg->setFinal(p);
+}
+
+Interval Path::timeRange() const
+{
+ Interval ret(0, size_default());
+ return ret;
+}
+
+Curve const &Path::curveAt(Coord t, Coord *rest) const
+{
+ PathTime pos = _factorTime(t);
+ if (rest) {
+ *rest = pos.t;
+ }
+ return at(pos.curve_index);
+}
+
+Point Path::pointAt(Coord t) const
+{
+ return pointAt(_factorTime(t));
+}
+
+Coord Path::valueAt(Coord t, Dim2 d) const
+{
+ return valueAt(_factorTime(t), d);
+}
+
+Curve const &Path::curveAt(PathTime const &pos) const
+{
+ return at(pos.curve_index);
+}
+Point Path::pointAt(PathTime const &pos) const
+{
+ return at(pos.curve_index).pointAt(pos.t);
+}
+Coord Path::valueAt(PathTime const &pos, Dim2 d) const
+{
+ return at(pos.curve_index).valueAt(pos.t, d);
+}
+
+std::vector<PathTime> Path::roots(Coord v, Dim2 d) const
+{
+ std::vector<PathTime> res;
+ for (unsigned i = 0; i < size(); i++) {
+ std::vector<Coord> temp = (*this)[i].roots(v, d);
+ for (double j : temp)
+ res.emplace_back(i, j);
+ }
+ return res;
+}
+
+
+// The class below implements sweepline optimization for curve intersection in paths.
+// Instead of O(N^2), this takes O(N + X), where X is the number of overlaps
+// between the bounding boxes of curves.
+
+struct CurveIntersectionSweepSet
+{
+public:
+ struct CurveRecord {
+ boost::intrusive::list_member_hook<> _hook;
+ Curve const *curve;
+ Rect bounds;
+ std::size_t index;
+ unsigned which;
+
+ CurveRecord(Curve const *pc, std::size_t idx, unsigned w)
+ : curve(pc)
+ , bounds(curve->boundsFast())
+ , index(idx)
+ , which(w)
+ {}
+ };
+
+ typedef std::vector<CurveRecord>::const_iterator ItemIterator;
+
+ CurveIntersectionSweepSet(std::vector<PathIntersection> &result,
+ Path const &a, Path const &b, Coord precision)
+ : _result(result)
+ , _precision(precision)
+ , _sweep_dir(X)
+ {
+ std::size_t asz = a.size(), bsz = b.size();
+ _records.reserve(asz + bsz);
+
+ for (std::size_t i = 0; i < asz; ++i) {
+ _records.emplace_back(&a[i], i, 0);
+ }
+ for (std::size_t i = 0; i < bsz; ++i) {
+ _records.emplace_back(&b[i], i, 1);
+ }
+
+ OptRect abb = a.boundsFast() | b.boundsFast();
+ if (abb && abb->height() > abb->width()) {
+ _sweep_dir = Y;
+ }
+ }
+
+ std::vector<CurveRecord> const &items() { return _records; }
+ Interval itemBounds(ItemIterator ii) {
+ return ii->bounds[_sweep_dir];
+ }
+
+ void addActiveItem(ItemIterator ii) {
+ unsigned w = ii->which;
+ unsigned ow = (w+1) % 2;
+
+ _active[w].push_back(const_cast<CurveRecord&>(*ii));
+
+ for (auto & i : _active[ow]) {
+ if (!ii->bounds.intersects(i.bounds)) continue;
+ std::vector<CurveIntersection> cx = ii->curve->intersect(*i.curve, _precision);
+ for (auto & k : cx) {
+ PathTime tw(ii->index, k.first), tow(i.index, k.second);
+ _result.emplace_back(
+ w == 0 ? tw : tow,
+ w == 0 ? tow : tw,
+ k.point());
+ }
+ }
+ }
+ void removeActiveItem(ItemIterator ii) {
+ ActiveCurveList &acl = _active[ii->which];
+ acl.erase(acl.iterator_to(*ii));
+ }
+
+private:
+ typedef boost::intrusive::list
+ < CurveRecord
+ , boost::intrusive::member_hook
+ < CurveRecord
+ , boost::intrusive::list_member_hook<>
+ , &CurveRecord::_hook
+ >
+ > ActiveCurveList;
+
+ std::vector<CurveRecord> _records;
+ std::vector<PathIntersection> &_result;
+ ActiveCurveList _active[2];
+ Coord _precision;
+ Dim2 _sweep_dir;
+};
+
+std::vector<PathIntersection> Path::intersect(Path const &other, Coord precision) const
+{
+ std::vector<PathIntersection> result;
+
+ CurveIntersectionSweepSet cisset(result, *this, other, precision);
+ Sweeper<CurveIntersectionSweepSet> sweeper(cisset);
+ sweeper.process();
+
+ // preprocessing to remove duplicate intersections at endpoints
+ std::size_t asz = size(), bsz = other.size();
+ for (auto & i : result) {
+ i.first.normalizeForward(asz);
+ i.second.normalizeForward(bsz);
+ }
+ std::sort(result.begin(), result.end());
+ result.erase(std::unique(result.begin(), result.end()), result.end());
+
+ return result;
+}
+
+int Path::winding(Point const &p) const {
+ int wind = 0;
+
+ /* To handle all the edge cases, we consider the maximum Y edge of the bounding box
+ * as not included in box. This way paths that contain linear horizontal
+ * segments will be treated correctly. */
+ for (const_iterator i = begin(); i != end_closed(); ++i) {
+ Rect bounds = i->boundsFast();
+
+ if (bounds.height() == 0) continue;
+ if (p[X] > bounds.right() || !bounds[Y].lowerContains(p[Y])) {
+ // Ray doesn't intersect bbox, so we ignore this segment
+ continue;
+ }
+
+ if (p[X] < bounds.left()) {
+ /* Ray intersects the curve's bbox, but the point is outside it.
+ * The winding contribution is exactly the same as that
+ * of a linear segment with the same initial and final points. */
+ Point ip = i->initialPoint();
+ Point fp = i->finalPoint();
+ Rect eqbox(ip, fp);
+
+ if (eqbox[Y].lowerContains(p[Y])) {
+ /* The ray intersects the equivalent linear segment.
+ * Determine winding contribution based on its derivative. */
+ if (ip[Y] < fp[Y]) {
+ wind += 1;
+ } else if (ip[Y] > fp[Y]) {
+ wind -= 1;
+ } else {
+ // should never happen, because bounds.height() was not zero
+ assert(false);
+ }
+ }
+ } else {
+ // point is inside bbox
+ wind += i->winding(p);
+ }
+ }
+ return wind;
+}
+
+std::vector<double> Path::allNearestTimes(Point const &_point, double from, double to) const
+{
+ // TODO from and to are not used anywhere.
+ // rewrite this to simplify.
+ using std::swap;
+
+ if (from > to)
+ swap(from, to);
+ const Path &_path = *this;
+ unsigned int sz = _path.size();
+ if (_path.closed())
+ ++sz;
+ if (from < 0 || to > sz) {
+ THROW_RANGEERROR("[from,to] interval out of bounds");
+ }
+ double sif, st = modf(from, &sif);
+ double eif, et = modf(to, &eif);
+ unsigned int si = static_cast<unsigned int>(sif);
+ unsigned int ei = static_cast<unsigned int>(eif);
+ if (si == sz) {
+ --si;
+ st = 1;
+ }
+ if (ei == sz) {
+ --ei;
+ et = 1;
+ }
+ if (si == ei) {
+ std::vector<double> all_nearest = _path[si].allNearestTimes(_point, st, et);
+ for (double & i : all_nearest) {
+ i = si + i;
+ }
+ return all_nearest;
+ }
+ std::vector<double> all_t;
+ std::vector<std::vector<double> > all_np;
+ all_np.push_back(_path[si].allNearestTimes(_point, st));
+ std::vector<unsigned int> ni;
+ ni.push_back(si);
+ double dsq;
+ double mindistsq = distanceSq(_point, _path[si].pointAt(all_np.front().front()));
+ Rect bb(Geom::Point(0, 0), Geom::Point(0, 0));
+ for (unsigned int i = si + 1; i < ei; ++i) {
+ bb = (_path[i].boundsFast());
+ dsq = distanceSq(_point, bb);
+ if (mindistsq < dsq)
+ continue;
+ all_t = _path[i].allNearestTimes(_point);
+ dsq = distanceSq(_point, _path[i].pointAt(all_t.front()));
+ if (mindistsq > dsq) {
+ all_np.clear();
+ all_np.push_back(all_t);
+ ni.clear();
+ ni.push_back(i);
+ mindistsq = dsq;
+ } else if (mindistsq == dsq) {
+ all_np.push_back(all_t);
+ ni.push_back(i);
+ }
+ }
+ bb = (_path[ei].boundsFast());
+ dsq = distanceSq(_point, bb);
+ if (mindistsq >= dsq) {
+ all_t = _path[ei].allNearestTimes(_point, 0, et);
+ dsq = distanceSq(_point, _path[ei].pointAt(all_t.front()));
+ if (mindistsq > dsq) {
+ for (double & i : all_t) {
+ i = ei + i;
+ }
+ return all_t;
+ } else if (mindistsq == dsq) {
+ all_np.push_back(all_t);
+ ni.push_back(ei);
+ }
+ }
+ std::vector<double> all_nearest;
+ for (unsigned int i = 0; i < all_np.size(); ++i) {
+ for (unsigned int j = 0; j < all_np[i].size(); ++j) {
+ all_nearest.push_back(ni[i] + all_np[i][j]);
+ }
+ }
+ all_nearest.erase(std::unique(all_nearest.begin(), all_nearest.end()), all_nearest.end());
+ return all_nearest;
+}
+
+std::vector<Coord> Path::nearestTimePerCurve(Point const &p) const
+{
+ // return a single nearest time for each curve in this path
+ std::vector<Coord> np;
+ for (const_iterator it = begin(); it != end_default(); ++it) {
+ np.push_back(it->nearestTime(p));
+ }
+ return np;
+}
+
+PathTime Path::nearestTime(Point const &p, Coord *dist) const
+{
+ Coord mindist = std::numeric_limits<Coord>::max();
+ PathTime ret;
+
+ if (_data->curves.size() == 1) {
+ // naked moveto
+ ret.curve_index = 0;
+ ret.t = 0;
+ if (dist) {
+ *dist = distance(_closing_seg->initialPoint(), p);
+ }
+ return ret;
+ }
+
+ for (size_type i = 0; i < size_default(); ++i) {
+ Curve const &c = at(i);
+ if (distance(p, c.boundsFast()) >= mindist) continue;
+
+ Coord t = c.nearestTime(p);
+ Coord d = distance(c.pointAt(t), p);
+ if (d < mindist) {
+ mindist = d;
+ ret.curve_index = i;
+ ret.t = t;
+ }
+ }
+ if (dist) {
+ *dist = mindist;
+ }
+
+ return ret;
+}
+
+std::vector<Point> Path::nodes() const
+{
+ std::vector<Point> result;
+ size_type path_size = size_closed();
+ for (size_type i = 0; i < path_size; ++i) {
+ result.push_back(_data->curves[i].initialPoint());
+ }
+ return result;
+}
+
+void Path::appendPortionTo(Path &ret, double from, double to) const
+{
+ if (!(from >= 0 && to >= 0)) {
+ THROW_RANGEERROR("from and to must be >=0 in Path::appendPortionTo");
+ }
+ if (to == 0)
+ to = size() + 0.999999;
+ if (from == to) {
+ return;
+ }
+ double fi, ti;
+ double ff = modf(from, &fi), tf = modf(to, &ti);
+ if (tf == 0) {
+ ti--;
+ tf = 1;
+ }
+ const_iterator fromi = inc(begin(), (unsigned)fi);
+ if (fi == ti && from < to) {
+ ret.append(fromi->portion(ff, tf));
+ return;
+ }
+ const_iterator toi = inc(begin(), (unsigned)ti);
+ if (ff != 1.) {
+ // fromv->setInitial(ret.finalPoint());
+ ret.append(fromi->portion(ff, 1.));
+ }
+ if (from >= to) {
+ const_iterator ender = end();
+ if (ender->initialPoint() == ender->finalPoint())
+ ++ender;
+ ret.insert(ret.end(), ++fromi, ender);
+ ret.insert(ret.end(), begin(), toi);
+ } else {
+ ret.insert(ret.end(), ++fromi, toi);
+ }
+ ret.append(toi->portion(0., tf));
+}
+
+void Path::appendPortionTo(Path &target, PathInterval const &ival,
+ std::optional<Point> const &p_from, std::optional<Point> const &p_to) const
+{
+ assert(ival.pathSize() == size_closed());
+
+ if (ival.isDegenerate()) {
+ Point stitch_to = p_from ? *p_from : pointAt(ival.from());
+ target.stitchTo(stitch_to);
+ return;
+ }
+
+ PathTime const &from = ival.from(), &to = ival.to();
+
+ bool reverse = ival.reverse();
+ int di = reverse ? -1 : 1;
+ size_type s = size_closed();
+
+ if (!ival.crossesStart() && from.curve_index == to.curve_index) {
+ Curve *c = (*this)[from.curve_index].portion(from.t, to.t);
+ if (p_from) {
+ c->setInitial(*p_from);
+ }
+ if (p_to) {
+ c->setFinal(*p_to);
+ }
+ target.append(c);
+ } else {
+ Curve *c_first = (*this)[from.curve_index].portion(from.t, reverse ? 0 : 1);
+ if (p_from) {
+ c_first->setInitial(*p_from);
+ }
+ target.append(c_first);
+
+ for (size_type i = (from.curve_index + s + di) % s; i != to.curve_index;
+ i = (i + s + di) % s)
+ {
+ if (reverse) {
+ target.append((*this)[i].reverse());
+ } else {
+ target.append((*this)[i].duplicate());
+ }
+ }
+
+ Curve *c_last = (*this)[to.curve_index].portion(reverse ? 1 : 0, to.t);
+ if (p_to) {
+ c_last->setFinal(*p_to);
+ }
+ target.append(c_last);
+ }
+}
+
+Path Path::reversed() const
+{
+ typedef std::reverse_iterator<Sequence::const_iterator> RIter;
+
+ Path ret(finalPoint());
+ if (empty()) return ret;
+
+ ret._data->curves.pop_back(); // this also deletes the closing segment from ret
+
+ RIter iter(_includesClosingSegment() ? _data->curves.end() : _data->curves.end() - 1);
+ RIter rend(_data->curves.begin());
+
+ if (_closed) {
+ // when the path is closed, there are two cases:
+ if (front().isLineSegment()) {
+ // 1. initial segment is linear: it becomes the new closing segment.
+ rend = RIter(_data->curves.begin() + 1);
+ ret._closing_seg = new ClosingSegment(front().finalPoint(), front().initialPoint());
+ } else {
+ // 2. initial segment is not linear: the closing segment becomes degenerate.
+ // However, skip it if it's already degenerate.
+ Point fp = finalPoint();
+ ret._closing_seg = new ClosingSegment(fp, fp);
+ }
+ } else {
+ // when the path is open, we reverse all real curves, and add a reversed closing segment.
+ ret._closing_seg = static_cast<ClosingSegment *>(_closing_seg->reverse());
+ }
+
+ for (; iter != rend; ++iter) {
+ ret._data->curves.push_back(iter->reverse());
+ }
+ ret._data->curves.push_back(ret._closing_seg);
+ ret._closed = _closed;
+ return ret;
+}
+
+
+void Path::insert(iterator pos, Curve const &curve)
+{
+ _unshare();
+ Sequence::iterator seq_pos(seq_iter(pos));
+ Sequence source;
+ source.push_back(curve.duplicate());
+ do_update(seq_pos, seq_pos, source);
+}
+
+void Path::erase(iterator pos)
+{
+ _unshare();
+ Sequence::iterator seq_pos(seq_iter(pos));
+
+ Sequence stitched;
+ do_update(seq_pos, seq_pos + 1, stitched);
+}
+
+void Path::erase(iterator first, iterator last)
+{
+ _unshare();
+ Sequence::iterator seq_first = seq_iter(first);
+ Sequence::iterator seq_last = seq_iter(last);
+
+ Sequence stitched;
+ do_update(seq_first, seq_last, stitched);
+}
+
+void Path::stitchTo(Point const &p)
+{
+ if (!empty() && _closing_seg->initialPoint() != p) {
+ if (_exception_on_stitch) {
+ THROW_CONTINUITYERROR();
+ }
+ _unshare();
+ do_append(new StitchSegment(_closing_seg->initialPoint(), p));
+ }
+}
+
+void Path::replace(iterator replaced, Curve const &curve)
+{
+ replace(replaced, replaced + 1, curve);
+}
+
+void Path::replace(iterator first_replaced, iterator last_replaced, Curve const &curve)
+{
+ _unshare();
+ Sequence::iterator seq_first_replaced(seq_iter(first_replaced));
+ Sequence::iterator seq_last_replaced(seq_iter(last_replaced));
+ Sequence source(1);
+ source.push_back(curve.duplicate());
+
+ do_update(seq_first_replaced, seq_last_replaced, source);
+}
+
+void Path::replace(iterator replaced, Path const &path)
+{
+ replace(replaced, path.begin(), path.end());
+}
+
+void Path::replace(iterator first, iterator last, Path const &path)
+{
+ replace(first, last, path.begin(), path.end());
+}
+
+void Path::snapEnds(Coord precision)
+{
+ if (!_closed) return;
+ if (_data->curves.size() > 1 && are_near(_closing_seg->length(precision), 0, precision)) {
+ _unshare();
+ _closing_seg->setInitial(_closing_seg->finalPoint());
+ (_data->curves.end() - 1)->setFinal(_closing_seg->finalPoint());
+ }
+}
+
+Path Path::withoutDegenerateCurves() const
+{
+ Sequence cleaned;
+ cleaned.reserve(size());
+
+ for (auto it = begin(); it != end_open(); ++it) {
+ if (!it->isDegenerate()) {
+ cleaned.push_back(it->duplicate());
+ }
+ }
+
+ Path result;
+ result._closed = _closed;
+ result.do_update(result._data->curves.begin(), result._data->curves.end(), cleaned);
+ return result;
+}
+
+// Replace curves between first and last with the contents of source.
+void Path::do_update(Sequence::iterator first, Sequence::iterator last, Sequence &source)
+{
+ // TODO: handle cases where first > last in closed paths?
+ bool last_beyond_closing_segment = (last == _data->curves.end());
+
+ // special case:
+ // if do_update replaces the closing segment, we have to regenerate it
+ if (source.empty()) {
+ if (first == last) return; // nothing to do
+
+ // only removing some segments
+ if ((!_closed && first == _data->curves.begin()) || (!_closed && last == _data->curves.end() - 1) || last_beyond_closing_segment) {
+ // just adjust the closing segment
+ // do nothing
+ } else if (first->initialPoint() != (last - 1)->finalPoint()) {
+ if (_exception_on_stitch) {
+ THROW_CONTINUITYERROR();
+ }
+ source.push_back(new StitchSegment(first->initialPoint(), (last - 1)->finalPoint()));
+ }
+ } else {
+ // replacing
+ if (first == _data->curves.begin() && last == _data->curves.end()) {
+ // special case: replacing everything should work the same in open and closed curves
+ _data->curves.erase(_data->curves.begin(), _data->curves.end() - 1);
+ _closing_seg->setFinal(source.front().initialPoint());
+ _closing_seg->setInitial(source.back().finalPoint());
+ _data->curves.transfer(_data->curves.begin(), source.begin(), source.end(), source);
+ return;
+ }
+
+ // stitch in front
+ if (!_closed && first == _data->curves.begin()) {
+ // not necessary to stitch in front
+ } else if (first->initialPoint() != source.front().initialPoint()) {
+ if (_exception_on_stitch) {
+ THROW_CONTINUITYERROR();
+ }
+ source.insert(source.begin(), new StitchSegment(first->initialPoint(), source.front().initialPoint()));
+ }
+
+ // stitch at the end
+ if ((!_closed && last == _data->curves.end() - 1) || last_beyond_closing_segment) {
+ // repurpose the closing segment as the stitch segment
+ // do nothing
+ } else if (source.back().finalPoint() != (last - 1)->finalPoint()) {
+ if (_exception_on_stitch) {
+ THROW_CONTINUITYERROR();
+ }
+ source.push_back(new StitchSegment(source.back().finalPoint(), (last - 1)->finalPoint()));
+ }
+ }
+
+ // do not erase the closing segment, adjust it instead
+ if (last_beyond_closing_segment) {
+ --last;
+ }
+ _data->curves.erase(first, last);
+ _data->curves.transfer(first, source.begin(), source.end(), source);
+
+ // adjust closing segment
+ if (size_open() == 0) {
+ _closing_seg->setFinal(_closing_seg->initialPoint());
+ } else {
+ _closing_seg->setInitial(back_open().finalPoint());
+ _closing_seg->setFinal(front().initialPoint());
+ }
+
+ checkContinuity();
+}
+
+void Path::do_append(Curve *c)
+{
+ if (&_data->curves.front() == _closing_seg) {
+ _closing_seg->setFinal(c->initialPoint());
+ } else {
+ // if we can't freely move the closing segment, we check whether
+ // the new curve connects with the last non-closing curve
+ if (c->initialPoint() != _closing_seg->initialPoint()) {
+ THROW_CONTINUITYERROR();
+ }
+ if (_closed && c->isLineSegment() &&
+ c->finalPoint() == _closing_seg->finalPoint())
+ {
+ // appending a curve that matches the closing segment has no effect
+ delete c;
+ return;
+ }
+ }
+ _data->curves.insert(_data->curves.end() - 1, c);
+ _closing_seg->setInitial(c->finalPoint());
+}
+
+void Path::checkContinuity() const
+{
+ Sequence::const_iterator i = _data->curves.begin(), j = _data->curves.begin();
+ ++j;
+ for (; j != _data->curves.end(); ++i, ++j) {
+ if (i->finalPoint() != j->initialPoint()) {
+ THROW_CONTINUITYERROR();
+ }
+ }
+ if (_data->curves.front().initialPoint() != _data->curves.back().finalPoint()) {
+ THROW_CONTINUITYERROR();
+ }
+}
+
+// breaks time value into integral and fractional part
+PathTime Path::_factorTime(Coord t) const
+{
+ size_type sz = size_default();
+ if (t < 0 || t > sz) {
+ THROW_RANGEERROR("parameter t out of bounds");
+ }
+
+ PathTime ret;
+ Coord k;
+ ret.t = modf(t, &k);
+ ret.curve_index = k;
+ if (ret.curve_index == sz) {
+ --ret.curve_index;
+ ret.t = 1;
+ }
+ return ret;
+}
+
+Piecewise<D2<SBasis> > paths_to_pw(PathVector const &paths)
+{
+ Piecewise<D2<SBasis> > ret = paths[0].toPwSb();
+ for (unsigned i = 1; i < paths.size(); i++) {
+ ret.concat(paths[i].toPwSb());
+ }
+ return ret;
+}
+
+bool are_near(Path const &a, Path const &b, Coord precision)
+{
+ if (a.size() != b.size()) return false;
+
+ for (unsigned i = 0; i < a.size(); ++i) {
+ if (!a[i].isNear(b[i], precision)) return false;
+ }
+ return true;
+}
+
+std::ostream &operator<<(std::ostream &out, Path const &path)
+{
+ SVGPathWriter pw;
+ pw.feed(path);
+ out << pw.str();
+ return out;
+}
+
+} // end namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/pathvector.cpp b/src/3rdparty/2geom/src/2geom/pathvector.cpp
new file mode 100644
index 0000000..0683c31
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/pathvector.cpp
@@ -0,0 +1,336 @@
+/** @file
+ * @brief PathVector - a sequence of subpaths
+ *//*
+ * Authors:
+ * Johan Engelen <goejendaagh@zonnet.nl>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2008-2014 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/affine.h>
+#include <2geom/path.h>
+#include <2geom/pathvector.h>
+#include <2geom/svg-path-writer.h>
+#include <2geom/sweeper.h>
+#include <optional>
+
+namespace Geom {
+
+//PathVector &PathVector::operator+=(PathVector const &other);
+
+PathVector::size_type PathVector::curveCount() const
+{
+ size_type n = 0;
+ for (const auto & it : *this) {
+ n += it.size_default();
+ }
+ return n;
+}
+
+void PathVector::reverse(bool reverse_paths)
+{
+ if (reverse_paths) {
+ std::reverse(begin(), end());
+ }
+ for (auto & i : *this) {
+ i = i.reversed();
+ }
+}
+
+PathVector PathVector::reversed(bool reverse_paths) const
+{
+ PathVector ret;
+ for (const auto & i : *this) {
+ ret.push_back(i.reversed());
+ }
+ if (reverse_paths) {
+ std::reverse(ret.begin(), ret.end());
+ }
+ return ret;
+}
+
+Path &PathVector::pathAt(Coord t, Coord *rest)
+{
+ return const_cast<Path &>(static_cast<PathVector const*>(this)->pathAt(t, rest));
+}
+Path const &PathVector::pathAt(Coord t, Coord *rest) const
+{
+ PathVectorTime pos = _factorTime(t);
+ if (rest) {
+ *rest = Coord(pos.curve_index) + pos.t;
+ }
+ return at(pos.path_index);
+}
+Curve const &PathVector::curveAt(Coord t, Coord *rest) const
+{
+ PathVectorTime pos = _factorTime(t);
+ if (rest) {
+ *rest = pos.t;
+ }
+ return at(pos.path_index).at(pos.curve_index);
+}
+Coord PathVector::valueAt(Coord t, Dim2 d) const
+{
+ PathVectorTime pos = _factorTime(t);
+ return at(pos.path_index).at(pos.curve_index).valueAt(pos.t, d);
+}
+Point PathVector::pointAt(Coord t) const
+{
+ PathVectorTime pos = _factorTime(t);
+ return at(pos.path_index).at(pos.curve_index).pointAt(pos.t);
+}
+
+OptRect PathVector::boundsFast() const
+{
+ OptRect bound;
+ if (empty()) return bound;
+
+ bound = front().boundsFast();
+ for (const_iterator it = ++begin(); it != end(); ++it) {
+ bound.unionWith(it->boundsFast());
+ }
+ return bound;
+}
+
+OptRect PathVector::boundsExact() const
+{
+ OptRect bound;
+ if (empty()) return bound;
+
+ bound = front().boundsExact();
+ for (const_iterator it = ++begin(); it != end(); ++it) {
+ bound.unionWith(it->boundsExact());
+ }
+ return bound;
+}
+
+void PathVector::snapEnds(Coord precision)
+{
+ for (std::size_t i = 0; i < size(); ++i) {
+ (*this)[i].snapEnds(precision);
+ }
+}
+
+// sweepline optimization
+// this is very similar to CurveIntersectionSweepSet in path.cpp
+// should probably be merged
+class PathIntersectionSweepSet {
+public:
+ struct PathRecord {
+ boost::intrusive::list_member_hook<> _hook;
+ Path const *path;
+ std::size_t index;
+ unsigned which;
+
+ PathRecord(Path const &p, std::size_t i, unsigned w)
+ : path(&p)
+ , index(i)
+ , which(w)
+ {}
+ };
+
+ typedef std::vector<PathRecord>::iterator ItemIterator;
+
+ PathIntersectionSweepSet(std::vector<PVIntersection> &result,
+ PathVector const &a, PathVector const &b, Coord precision)
+ : _result(result)
+ , _precision(precision)
+ {
+ _records.reserve(a.size() + b.size());
+ for (std::size_t i = 0; i < a.size(); ++i) {
+ _records.emplace_back(a[i], i, 0);
+ }
+ for (std::size_t i = 0; i < b.size(); ++i) {
+ _records.emplace_back(b[i], i, 1);
+ }
+ }
+
+ std::vector<PathRecord> &items() { return _records; }
+
+ Interval itemBounds(ItemIterator ii) {
+ OptRect r = ii->path->boundsFast();
+ if (!r) return Interval();
+ return (*r)[X];
+ }
+
+ void addActiveItem(ItemIterator ii) {
+ unsigned w = ii->which;
+ unsigned ow = (ii->which + 1) % 2;
+
+ for (auto & i : _active[ow]) {
+ if (!ii->path->boundsFast().intersects(i.path->boundsFast())) continue;
+ std::vector<PathIntersection> px = ii->path->intersect(*i.path, _precision);
+ for (auto & k : px) {
+ PathVectorTime tw(ii->index, k.first), tow(i.index, k.second);
+ _result.emplace_back(
+ w == 0 ? tw : tow,
+ w == 0 ? tow : tw,
+ k.point());
+ }
+ }
+ _active[w].push_back(*ii);
+ }
+
+ void removeActiveItem(ItemIterator ii) {
+ ActivePathList &apl = _active[ii->which];
+ apl.erase(apl.iterator_to(*ii));
+ }
+
+private:
+ typedef boost::intrusive::list
+ < PathRecord
+ , boost::intrusive::member_hook
+ < PathRecord
+ , boost::intrusive::list_member_hook<>
+ , &PathRecord::_hook
+ >
+ > ActivePathList;
+
+ std::vector<PVIntersection> &_result;
+ std::vector<PathRecord> _records;
+ ActivePathList _active[2];
+ Coord _precision;
+};
+
+std::vector<PVIntersection> PathVector::intersect(PathVector const &other, Coord precision) const
+{
+ std::vector<PVIntersection> result;
+
+ PathIntersectionSweepSet pisset(result, *this, other, precision);
+ Sweeper<PathIntersectionSweepSet> sweeper(pisset);
+ sweeper.process();
+
+ std::sort(result.begin(), result.end());
+
+ return result;
+}
+
+int PathVector::winding(Point const &p) const
+{
+ int wind = 0;
+ for (const auto & i : *this) {
+ if (!i.boundsFast().contains(p)) continue;
+ wind += i.winding(p);
+ }
+ return wind;
+}
+
+std::optional<PathVectorTime> PathVector::nearestTime(Point const &p, Coord *dist) const
+{
+ std::optional<PathVectorTime> retval;
+
+ Coord mindist = infinity();
+ for (size_type i = 0; i < size(); ++i) {
+ Coord d;
+ PathTime pos = (*this)[i].nearestTime(p, &d);
+ if (d < mindist) {
+ mindist = d;
+ retval = PathVectorTime(i, pos.curve_index, pos.t);
+ }
+ }
+
+ if (dist) {
+ *dist = mindist;
+ }
+ return retval;
+}
+
+std::vector<PathVectorTime> PathVector::allNearestTimes(Point const &p, Coord *dist) const
+{
+ std::vector<PathVectorTime> retval;
+
+ Coord mindist = infinity();
+ for (size_type i = 0; i < size(); ++i) {
+ Coord d;
+ PathTime pos = (*this)[i].nearestTime(p, &d);
+ if (d < mindist) {
+ mindist = d;
+ retval.clear();
+ }
+ if (d <= mindist) {
+ retval.emplace_back(i, pos.curve_index, pos.t);
+ }
+ }
+
+ if (dist) {
+ *dist = mindist;
+ }
+ return retval;
+}
+
+std::vector<Point> PathVector::nodes() const
+{
+ std::vector<Point> result;
+ for (size_type i = 0; i < size(); ++i) {
+ size_type path_size = (*this)[i].size_closed();
+ for (size_type j = 0; j < path_size; ++j) {
+ result.push_back((*this)[i][j].initialPoint());
+ }
+ }
+ return result;
+}
+
+PathVectorTime PathVector::_factorTime(Coord t) const
+{
+ PathVectorTime ret;
+ Coord rest = 0;
+ ret.t = modf(t, &rest);
+ ret.curve_index = rest;
+ for (; ret.path_index < size(); ++ret.path_index) {
+ unsigned s = _data.at(ret.path_index).size_default();
+ if (s > ret.curve_index) break;
+ // special case for the last point
+ if (s == ret.curve_index && ret.path_index + 1 == size()) {
+ --ret.curve_index;
+ ret.t = 1;
+ break;
+ }
+ ret.curve_index -= s;
+ }
+ return ret;
+}
+
+std::ostream &operator<<(std::ostream &out, PathVector const &pv)
+{
+ SVGPathWriter wr;
+ wr.feed(pv);
+ out << wr.str();
+ return out;
+}
+
+} // namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/piecewise.cpp b/src/3rdparty/2geom/src/2geom/piecewise.cpp
new file mode 100644
index 0000000..8714bd6
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/piecewise.cpp
@@ -0,0 +1,266 @@
+/*
+ * piecewise.cpp - Piecewise function class
+ *
+ * Copyright 2007 Michael Sloan <mgsloan@gmail.com>
+ * Copyright 2007 JF Barraud
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, output to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <2geom/piecewise.h>
+#include <iterator>
+#include <map>
+
+namespace Geom {
+
+Piecewise<SBasis> divide(Piecewise<SBasis> const &a, Piecewise<SBasis> const &b, unsigned k) {
+ Piecewise<SBasis> pa = partition(a, b.cuts), pb = partition(b, a.cuts);
+ Piecewise<SBasis> ret = Piecewise<SBasis>();
+ assert(pa.size() == pb.size());
+ ret.cuts = pa.cuts;
+ for (unsigned i = 0; i < pa.size(); i++)
+ ret.push_seg(divide(pa[i], pb[i], k));
+ return ret;
+}
+
+Piecewise<SBasis>
+divide(Piecewise<SBasis> const &a, Piecewise<SBasis> const &b, double tol, unsigned k, double zero) {
+ Piecewise<SBasis> pa = partition(a, b.cuts), pb = partition(b, a.cuts);
+ Piecewise<SBasis> ret = Piecewise<SBasis>();
+ assert(pa.size() == pb.size());
+ for (unsigned i = 0; i < pa.size(); i++){
+ Piecewise<SBasis> divi = divide(pa[i], pb[i], tol, k, zero);
+ divi.setDomain(Interval(pa.cuts[i],pa.cuts[i+1]));
+ ret.concat(divi);
+ }
+ return ret;
+}
+Piecewise<SBasis> divide(Piecewise<SBasis> const &a, SBasis const &b, double tol, unsigned k, double zero){
+ return divide(a,Piecewise<SBasis>(b),tol,k,zero);
+}
+Piecewise<SBasis> divide(SBasis const &a, Piecewise<SBasis> const &b, double tol, unsigned k, double zero){
+ return divide(Piecewise<SBasis>(a),b,tol,k,zero);
+}
+Piecewise<SBasis> divide(SBasis const &a, SBasis const &b, double tol, unsigned k, double zero) {
+ if (b.tailError(0)<2*zero){
+ //TODO: have a better look at sgn(b).
+ double sgn= (b(.5)<0.)?-1.:1;
+ return Piecewise<SBasis>(Linear(sgn/zero)*a);
+ }
+
+ if (fabs(b.at0())>zero && fabs(b.at1())>zero ){
+ SBasis c,r=a;
+ //TODO: what is a good relative tol? atm, c=a/b +/- (tol/a)%...
+
+ k+=1;
+ r.resize(k, Linear(0,0));
+ c.resize(k, Linear(0,0));
+
+ //assert(b.at0()!=0 && b.at1()!=0);
+ for (unsigned i=0; i<k; i++){
+ Linear ci = Linear(r[i][0]/b[0][0],r[i][1]/b[0][1]);
+ c[i]=ci;
+ r-=shift(ci*b,i);
+ }
+
+ if (r.tailError(k)<tol) return Piecewise<SBasis>(c);
+ }
+
+ Piecewise<SBasis> c0,c1;
+ c0 = divide(compose(a,Linear(0.,.5)),compose(b,Linear(0.,.5)),tol,k);
+ c1 = divide(compose(a,Linear(.5,1.)),compose(b,Linear(.5,1.)),tol,k);
+ c0.setDomain(Interval(0.,.5));
+ c1.setDomain(Interval(.5,1.));
+ c0.concat(c1);
+ return c0;
+}
+
+
+//-- compose(pw<T>,SBasis) ---------------
+/*
+ the purpose of the following functions is only to reduce the code in piecewise.h
+ TODO: use a vector<pairs<double,unsigned> > instead of a map<double,unsigned>.
+ */
+
+std::map<double,unsigned> compose_pullback(std::vector<double> const &values, SBasis const &g){
+ std::map<double,unsigned> result;
+
+ std::vector<std::vector<double> > roots = multi_roots(g, values);
+ for(unsigned i=0; i<roots.size(); i++){
+ for(unsigned j=0; j<roots[i].size();j++){
+ result[roots[i][j]]=i;
+ }
+ }
+ // Also map 0 and 1 to the first value above(or =) g(0) and g(1).
+ if(result.count(0.)==0){
+ unsigned i=0;
+ while (i<values.size()&&(g.at0()>values[i])) i++;
+ result[0.]=i;
+ }
+ if(result.count(1.)==0){
+ unsigned i=0;
+ while (i<values.size()&&(g.at1()>values[i])) i++;
+ result[1.]=i;
+ }
+ return(result);
+}
+
+int compose_findSegIdx(std::map<double,unsigned>::iterator const &cut,
+ std::map<double,unsigned>::iterator const &next,
+ std::vector<double> const &levels,
+ SBasis const &g){
+ double t0=(*cut).first;
+ unsigned idx0=(*cut).second;
+ double t1=(*next).first;
+ unsigned idx1=(*next).second;
+ assert(t0<t1);
+ int idx; //idx of the relevant f.segs
+ if (std::max(idx0,idx1)==levels.size()){ //g([t0,t1]) is above the top level,
+ idx=levels.size()-1;
+ } else if (idx0 != idx1){ //g([t0,t1]) crosses from level idx0 to idx1,
+ idx=std::min(idx0,idx1);
+ } else if(g((t0+t1)/2) < levels[idx0]) { //g([t0,t1]) is a 'U' under level idx0,
+ idx=idx0-1;
+ } else if(g((t0+t1)/2) > levels[idx0]) { //g([t0,t1]) is a 'bump' over level idx0,
+ idx=idx0;
+ } else { //g([t0,t1]) is contained in level idx0!...
+ idx = (idx0==levels.size())? idx0-1:idx0;
+ }
+
+ //move idx back from levels f.cuts
+ idx+=1;
+ return idx;
+}
+
+
+Piecewise<SBasis> pw_compose_inverse(SBasis const &f, SBasis const &g, unsigned order, double zero){
+ Piecewise<SBasis> result;
+
+ assert( f.size()>0 && g.size()>0);
+ SBasis g01 = g;
+ bool flip = ( g01.at0() > g01.at1() );
+
+ //OptInterval g_range = bounds_exact(g);
+ OptInterval g_range( Interval( g.at0(), g.at1() ));
+
+ g01 -= g_range->min();
+ g01 /= g_range->extent();
+ if ( flip ){
+ g01 *= -1.;
+ g01 += 1.;
+ }
+#if 1
+ assert( std::abs( g01.at0() - 0. ) < zero );
+ assert( std::abs( g01.at1() - 1. ) < zero );
+ //g[0][0] = 0.;
+ //g[0][1] = 1.;
+#endif
+
+ SBasis foginv = compose_inverse( f, g01, order, zero );
+ SBasis err = compose( foginv, g01) - f;
+
+ if ( err.tailError(0) < zero ){
+ result = Piecewise<SBasis> (foginv);
+ }else{
+ SBasis g_portion = portion( g01, Interval(0.,.5) );
+ SBasis f_portion = portion( f, Interval(0.,.5) );
+ result = pw_compose_inverse(f_portion, g_portion, order, zero);
+
+ g_portion = portion( g01, Interval(.5, 1.) );
+ f_portion = portion( f, Interval(.5, 1.) );
+ Piecewise<SBasis> result_next;
+ result_next = pw_compose_inverse(f_portion, g_portion, order, zero);
+ result.concat( result_next );
+ }
+ if (flip) {
+ result = reverse(result);
+ }
+ result.setDomain(*g_range);
+ return result;
+}
+
+
+std::vector<double> roots(Piecewise<SBasis> const &f){
+ std::vector<double> result;
+ for (unsigned i=0; i<f.size(); i++){
+ std::vector<double> rts=roots(f.segs[i]);
+
+ for (double rt : rts){
+ result.push_back(f.mapToDomain(rt, i));
+ }
+ }
+ return result;
+}
+
+std::vector<std::vector<double> > multi_roots(Piecewise<SBasis> const &f, std::vector<double> const &values) {
+ std::vector<std::vector<double> > result(values.size());
+ for (unsigned i=0; i<f.size(); i++) {
+ std::vector<std::vector<double> > rts = multi_roots(f.segs[i], values);
+ for(unsigned j=0; j<rts.size(); j++) {
+ for(unsigned r=0; r<rts[j].size(); r++){
+ result[j].push_back(f.mapToDomain(rts[j][r], i));
+ }
+ }
+ }
+ return result;
+}
+
+
+std::vector<Interval> level_set(Piecewise<SBasis> const &f, Interval const &level, double tol){
+ std::vector<Interval> result;
+ for (unsigned i=0; i<f.size(); i++){
+ std::vector<Interval> resulti = level_set( f[i], level, 0., 1., tol);
+ for (unsigned j=0; j<resulti.size(); j++){
+ double a = f.cuts[i] + resulti[j].min() * ( f.cuts[i+1] - f.cuts[i] );
+ double b = f.cuts[i] + resulti[j].max() * ( f.cuts[i+1] - f.cuts[i] );
+ Interval domj( a, b );
+ //Interval domj( f.mapToDomain(resulti[j].min(), i ), f.mapToDomain(resulti[j].max(), i ) );
+
+ if ( j==0 && !result.empty() && result.back().intersects(domj) ){
+ result.back().unionWith(domj);
+ }else{
+ result.push_back(domj);
+ }
+ }
+ }
+ return result;
+}
+std::vector<Interval> level_set(Piecewise<SBasis> const &f, double v, double vtol, double tol){
+ Interval level ( v-vtol, v+vtol );
+ return level_set( f, level, tol);
+}
+
+
+}
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/planar-graph.h b/src/3rdparty/2geom/src/2geom/planar-graph.h
new file mode 100644
index 0000000..fb5f1ac
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/planar-graph.h
@@ -0,0 +1,1252 @@
+/** @file PlanarGraph – a graph geometrically embedded in the plane.
+ */
+/*
+ * Authors:
+ * Rafał Siejakowski <rs@rs-math.net>
+ *
+ * Copyright 2022 the Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+// WARNING: This is a private header. Do not include it directly.
+
+#ifndef LIB2GEOM_SEEN_PLANAR_GRAPH_H
+#define LIB2GEOM_SEEN_PLANAR_GRAPH_H
+
+#include <algorithm>
+#include <iterator>
+#include <list>
+
+#include <2geom/angle.h>
+#include <2geom/coord.h>
+#include <2geom/line.h>
+#include <2geom/point.h>
+#include <2geom/path.h>
+#include <2geom/path-intersection.h>
+#include <2geom/utils.h>
+
+namespace Geom {
+
+/**
+ * \class PlanarGraph
+ * \brief Planar graph - a graph geometrically embedded in the plane.
+ *
+ * A planar graph is composed of vertices with assigned locations (as points in the plane)
+ * and of edges (arcs), which are imagined as non-intersecting paths in the plane connecting
+ * the vertices. The edges can hold user-supplied labels (e.g., weights) which support event
+ * callbacks for when the graph is reconfigured, allowing the labels to be updated accordingly.
+ *
+ * \tparam EdgeLabel A user-supplied type; an object of this type will be attached to each
+ * edge of the planar graph (e.g., a "weight" of the edge). The type must
+ * satisfy requirements described further below.
+ *
+ * In order to construct a planar graph, you should specify the clumping precision (passed as
+ * a constructor argument) and then use the method insertEdge() to add edges to the graph, as
+ * many times as necessary. The graph will automatically figure out the locations of the
+ * vertices based on the endpoints of the inserted edges. Vertices will be combined into one
+ * when they are positioned within the distance specified as the clumping threshold, and the
+ * inserted edges will be attached to them accordingly. It is also possible to insert paths
+ * (typically, closed) not attached to any vertices, using the method insertDetached().
+ *
+ * After the edges are inserted, the graph is in a potentially degenerate state, where several
+ * edges may exactly coincide in part or in full. If this is not desired, you can regularize
+ * the graph by calling regularize(). During the regularization process, any overlapping edges
+ * are combined into one. Partially overlapping edges are first split into overlapping and
+ * non-overlapping portions, after which the overlapping portions are combined. If the edges
+ * or their parts overlap but run in opposite directions, one of them will be reversed before
+ * being merged with the other one. The overlaps are detected using the precision setting passed
+ * as the clumping precision in the constructor argument.
+ *
+ * Note however that the regularization procedure does NOT detect transverse intersections
+ * between the edge paths: if such intersections are not desired, the user must pass non-\
+ * intersecting paths to the insertEdge() method (the paths may still have common endpoints,
+ * which is fine: that's how common vertices are created).
+ *
+ * The insertion of new edges invalidates the regularized status, which you can check at any
+ * time by calling isRegularized().
+ *
+ * The vertices stored by the graph are sorted by increasing X-coordinate, and if they have
+ * equal X-coordinates, by increasing Y-coordinate. Even before regularization, incidences of
+ * edges to each vertex are sorted by increasing azimuth of the outgoing tangent (departure
+ * heading, but in radians, in the interval \f$(-\pi, \pi]\f$). After regularization, the edges
+ * around each vertex are guaranteed to be sorted counterclockwise (when the Y-axis points up)
+ * by where they end up going eventually, even if they're tangent at the vertex and therefore
+ * have equal or nearly equal departure azimuths.
+ *
+ * \note
+ * Requirements on the \c EdgeLabel template parameter type.
+ * In order for the template to instantiate correctly, the following must be satisfied:
+ * \li The \c EdgeLabel type provides a method \c onReverse() which gets called whenever
+ * the orientation of the labeled edge is reversed. This is useful when implementing
+ * a directed graph, since the label can keep track of the logical direction.
+ * \li The \c EdgeLabel type provides a method \c onMergeWith(EdgeLabel const&) which gets
+ * called when the labeled edge is combined with a geometrically identical (coinciding)
+ * edge (both combined edges having the same orientations). The label of the edge merged
+ * with the current one is provided as an argument to the method. This is useful when
+ * implementing a graph with weights: for example, when two edges are merged, you may
+ * want to combine their weights in some way.
+ * \li There is a method \c onDetach() called when the edge is removed from the graph. The
+ * edge objects are never destroyed but may be disconnected from the graph when they're no
+ * longer needed; this allows the user to put the labels of such edges in a "dead" state.
+ * \li The \c EdgeLabel objects must be copy-constructible and copy-assignable. This is
+ * because when an edge is subdivided into two, the new edges replacing it get decorated
+ * with copies of the original edge's label.
+ */
+template<typename EdgeLabel>
+#if __cplusplus >= 202002L
+requires requires(EdgeLabel el, EdgeLabel const &other) {
+ el.onReverse();
+ el.onMergeWith(other);
+ el.onDetach();
+ el = other;
+}
+#endif
+class PlanarGraph
+{
+public:
+
+ /** Represents the joint between an edge and a vertex. */
+ struct Incidence
+ {
+ using Sign = bool;
+ inline static Sign const START = false;
+ inline static Sign const END = true;
+
+ double azimuth; ///< Angle of the edge's departure.
+ unsigned index; ///< Index of the edge in the parent graph.
+ Sign sign; ///< Whether this is the start or end of the edge.
+ bool invalid = false; ///< Whether this incidence has been marked for deletion.
+
+ Incidence(unsigned edge_index, double departure_azimuth, Sign which_end)
+ : azimuth{departure_azimuth}
+ , index{edge_index}
+ , sign{which_end}
+ {
+ }
+ ~Incidence() = default;
+
+ /// Compare incidences based on their azimuths in radians.
+ inline bool operator<(Incidence const &other) const { return azimuth < other.azimuth; }
+
+ /// Compare the azimuth of an incidence with the given angle.
+ inline bool operator<(double angle) const { return azimuth < angle; }
+
+ /// Check equality (only tests edges and their ends).
+ inline bool operator==(Incidence const &other) const
+ {
+ return index == other.index && sign == other.sign;
+ }
+ };
+ using IncIt = typename std::list<Incidence>::iterator;
+ using IncConstIt = typename std::list<Incidence>::const_iterator;
+
+ /** Represents the vertex of a planar graph. */
+ class Vertex
+ {
+ private:
+ Point const _position; ///< Geometric position of the vertex.
+ std::list<Incidence> _incidences; ///< List of incidences of edges to this vertex.
+ unsigned mutable _flags = 0; ///< User-settable flags.
+
+ inline static Point::LexLess<X> const _cmp; ///< Point sorting function object.
+
+ public:
+ Vertex(Point const &pos)
+ : _position{pos}
+ {
+ }
+
+ /** Get the geometric position of the vertex. */
+ Point const &point() const { return _position; }
+
+ /** Get the list of incidences to the vertex. */
+ auto const &getIncidences() const { return _incidences; }
+
+ /** Compare vertices based on their coordinates (lexicographically). */
+ bool operator<(Vertex const &other) const { return _cmp(_position, other._position); }
+
+ unsigned flags() const { return _flags; } ///< Get the user flags.
+ void setFlags(unsigned flags) const { _flags = flags; } ///< Set the user flags.
+
+ /** Get the cyclic-next incidence after the passed one, in the CCW direction. */
+ IncConstIt cyclicNextIncidence(IncConstIt it) const { return cyclic_next(it, _incidences); }
+
+ /** Get the cyclic-next incidence after the passed one, in the CW direction. */
+ IncConstIt cyclicPrevIncidence(IncConstIt it) const { return cyclic_prior(it, _incidences); }
+
+ /** The same but with pointers. */
+ Incidence *cyclicNextIncidence(Incidence *from)
+ {
+ return &(*cyclicNextIncidence(_incidencePtr2It(from)));
+ }
+ Incidence *cyclicPrevIncidence(Incidence *from)
+ {
+ return &(*cyclicPrevIncidence(_incidencePtr2It(from)));
+ }
+
+ private:
+ /** Same as above, but not const (so only for private use). */
+ IncIt cyclicNextIncidence(IncIt it) { return cyclic_next(it, _incidences); }
+ IncIt cyclicPrevIncidence(IncIt it) { return cyclic_prior(it, _incidences); }
+
+ /** Insert an incidence; for internal use by the PlanarGraph class. */
+ Incidence &_addIncidence(unsigned edge_index, double azimuth, typename Incidence::Sign sign)
+ {
+ auto where = std::find_if(_incidences.begin(), _incidences.end(), [=](auto &inc) -> bool {
+ return inc.azimuth >= azimuth;
+ });
+ return *(_incidences.emplace(where, edge_index, azimuth, sign));
+ }
+
+ /** Return a valid iterator to an incidence passed by pointer;
+ * if the pointer is invalid, return a start iterator. */
+ IncIt _incidencePtr2It(Incidence *pointer)
+ {
+ auto it = std::find_if(_incidences.begin(), _incidences.end(),
+ [=](Incidence const &i) -> bool { return &i == pointer; });
+ return (it == _incidences.end()) ? _incidences.begin() : it;
+ }
+
+ friend class PlanarGraph<EdgeLabel>;
+ };
+ using VertexIterator = typename std::list<Vertex>::iterator;
+
+ /** Represents an edge of the planar graph. */
+ struct Edge
+ {
+ Vertex *start = nullptr, *end = nullptr; ///< Start and end vertices.
+ Path path; ///< The path associated to the edge.
+ bool detached = false; ///< Whether the edge is detached from the graph.
+ bool inserted_as_detached = false; ///< Whether the edge was inserted as detached.
+ EdgeLabel mutable label; ///< The user-supplied label of the edge.
+
+ /** Construct an edge with a given label. */
+ Edge(Path &&movein_path, EdgeLabel &&movein_label)
+ : path{movein_path}
+ , label{movein_label}
+ {
+ }
+
+ /** Detach the edge from the graph. */
+ void detach()
+ {
+ detached = true;
+ label.onDetach();
+ }
+ };
+ using EdgeIterator = typename std::vector<Edge>::iterator;
+ using EdgeConstIterator = typename std::vector<Edge>::const_iterator;
+
+private:
+ double const _precision; ///< Numerical epsilon for vertex clumping.
+ std::list<Vertex> _vertices; ///< Vertices of the graph.
+ std::vector<Edge> _edges; ///< Edges of the graph.
+ std::vector< std::pair<Vertex *, Incidence *> > _junk; ///< Incidences that should be purged.
+ bool _regularized = true; // An empty graph is (trivially) regularized.
+
+public:
+ PlanarGraph(Coord precision = EPSILON)
+ : _precision{precision}
+ {
+ }
+
+ std::list<Vertex> const &getVertices() const { return _vertices; }
+ std::vector<Edge> const &getEdges() const { return _edges; }
+ Edge const &getEdge(size_t index) const { return _edges.at(index); }
+ size_t getEdgeIndex(Edge const &edge) const { return &edge - _edges.data(); }
+ double getPrecision() const { return _precision; }
+ size_t numVertices() const { return _vertices.size(); }
+ size_t numEdges(bool include_detached = true) const
+ {
+ if (include_detached) {
+ return _edges.size();
+ }
+ return std::count_if(_edges.begin(), _edges.end(),
+ [](Edge const &e) -> bool { return !e.detached; });
+ }
+
+ /** Check if the graph has been regularized. */
+ bool isRegularized() const { return _regularized; }
+
+ // 0x1p-50 is about twice the distance between M_PI and the next representable double.
+ void regularize(double angle_precision = 0x1p-50, bool remove_collapsed_loops = true);
+
+ /** Allocate memory to store the specified number of edges. */
+ void reserveEdgeCapacity(size_t capacity) { _edges.reserve(capacity); }
+
+ unsigned insertEdge(Path &&path, EdgeLabel &&edge = EdgeLabel());
+ unsigned insertDetached(Path &&path, EdgeLabel &&edge = EdgeLabel());
+
+ /** Edge insertion with a copy of the path. */
+ unsigned insertEdge(Path const &path, EdgeLabel &&edge = EdgeLabel())
+ {
+ return insertEdge(Path(path), std::forward<EdgeLabel>(edge));
+ }
+ unsigned insertDetached(Path const &path, EdgeLabel &&edge = EdgeLabel())
+ {
+ return insertDetached(Path(path), std::forward<EdgeLabel>(edge));
+ }
+
+ /** \brief Find the incidence at the specified endpoint of the edge.
+ *
+ * \param edge_index The index of the edge whose incidence we wish to query.
+ * \param sign Which end of the edge do we want an incidence of.
+ * \return A pair consisting of pointers to the vertex and the incidence.
+ * If not found, both pointers will be null.
+ */
+ std::pair<Vertex *, Incidence *>
+ getIncidence(unsigned edge_index, typename Incidence::Sign sign) const
+ {
+ if (edge_index >= _edges.size() || _edges[edge_index].detached) {
+ return {nullptr, nullptr};
+ }
+ Vertex *vertex = (sign == Incidence::START) ? _edges[edge_index].start
+ : _edges[edge_index].end;
+ if (!vertex) {
+ return {nullptr, nullptr};
+ }
+ auto it = std::find(vertex->_incidences.begin(), vertex->_incidences.end(),
+ Incidence(edge_index, 42, sign)); // azimuth doesn't matter.
+ if (it == vertex->_incidences.end()) {
+ return {nullptr, nullptr};
+ }
+ return {vertex, &(*it)};
+ }
+
+ /**
+ * \brief Go clockwise or counterclockwise around the vertex and find the next incidence.
+ * The notions of "clockwise"/"counterclockwise" correspond to the y-axis pointing up.
+ *
+ * \param vertex The vertex around which to orbit.
+ * \param incidence The incidence from which to start traversal.
+ * \param clockwise Whether to go clockwise instead of (default) counterclockwise.
+ * \return The next incidence encountered going in the specified direction.
+ */
+ inline Incidence const &nextIncidence(VertexIterator const &vertex, IncConstIt const &incidence,
+ bool clockwise = false) const
+ {
+ return clockwise ? *(vertex->_cyclicPrevIncidence(incidence))
+ : *(vertex->_cyclicNextIncidence(incidence));
+ }
+
+ /** As above, but taking references instead of iterators. */
+ inline Incidence const &nextIncidence(Vertex const &vertex, Incidence const &incidence,
+ bool clockwise = false) const
+ {
+ IncConstIt it = std::find(vertex._incidences.begin(), vertex._incidences.end(), incidence);
+ if (it == vertex._incidences.end()) {
+ return incidence;
+ }
+ return clockwise ? *(vertex.cyclicPrevIncidence(it))
+ : *(vertex.cyclicNextIncidence(it));
+ }
+
+ /** As above, but return an iterator to a const incidence. */
+ inline IncConstIt nextIncidenceIt(Vertex const &vertex, Incidence const &incidence,
+ bool clockwise = false) const
+ {
+ IncConstIt it = std::find(vertex._incidences.begin(), vertex._incidences.end(), incidence);
+ if (it == vertex._incidences.end()) {
+ return vertex._incidences.begin();
+ }
+ return clockwise ? vertex.cyclicPrevIncidence(it)
+ : vertex.cyclicNextIncidence(it);
+ }
+ inline IncConstIt nextIncidenceIt(Vertex const &vertex, IncConstIt const &incidence,
+ bool clockwise = false) const
+ {
+ return clockwise ? vertex.cyclicPrevIncidence(incidence)
+ : vertex.cyclicNextIncidence(incidence);
+ }
+
+ /** As above, but start at the prescribed departure azimuth (in radians).
+ *
+ * \return A pointer to the incidence emanating from the vertex at or immediately after
+ * the specified azimuth, when going around the vertex in the specified direction.
+ * If the vertex has no incidences, return value is nullptr.
+ */
+ Incidence *nextIncidence(VertexIterator const &vertex, double azimuth,
+ bool clockwise = false) const;
+
+ /** Get the incident path, always oriented away from the vertex. */
+ Path getOutgoingPath(Incidence const *incidence) const
+ {
+ return incidence ? _getPathImpl(incidence, Incidence::START) : Path();
+ }
+
+ /** Get the incident path, always oriented towards the vertex. */
+ Path getIncomingPath(Incidence const *incidence) const
+ {
+ return incidence ? _getPathImpl(incidence, Incidence::END) : Path();
+ }
+
+private:
+ inline Path _getPathImpl(Incidence const *incidence, typename Incidence::Sign origin) const
+ {
+ return (incidence->sign == origin) ? _edges[incidence->index].path
+ : _edges[incidence->index].path.reversed();
+ }
+
+ /** Earmark an incidence for future deletion. */
+ inline void _throwAway(Vertex *vertex, Incidence *incidence)
+ {
+ if (!vertex || !incidence) {
+ return;
+ }
+ incidence->invalid = true;
+ _junk.emplace_back(vertex, incidence);
+ }
+
+ // Topological reconfiguration functions; see their definitions for documentation.
+ bool _compareAndReglue(Vertex &vertex, Incidence *first, Incidence *second, bool deloop);
+ Vertex *_ensureVertexAt(Point const &position);
+ void _mergeCoincidingEdges(Incidence *first, Incidence *second);
+ void _mergeShorterLonger(Vertex &vertex, Incidence *shorter, Incidence *longer,
+ PathTime const &time_on_longer);
+ void _mergeWyeConfiguration(Vertex &vertex, Incidence *first, Incidence *second,
+ PathIntersection const &split);
+ void _purgeJunkIncidences();
+ void _reglueLasso(Vertex &vertex, Incidence *first, Incidence *second,
+ PathIntersection const &split);
+ bool _reglueTeardrop(Vertex &vertex, Incidence *first, Incidence *second, bool deloop);
+ void _reglueTangentFan(Vertex &vertex, IncIt const &first, IncIt const &last, bool deloop);
+ void _regularizeVertex(Vertex &vertex, double angle_precision, bool deloop);
+
+ // === Static stuff ===
+
+ /** Return the angle between the vector and the positive X axis or 0 if undefined. */
+ inline static double _getAzimuth(Point const &vec) { return vec.isZero() ? 0.0 : atan2(vec); }
+
+ /** Return path time corresponding to the same point on the reversed path. */
+ inline static PathTime _reversePathTime(PathTime const &time, Path const &path)
+ {
+ int new_index = path.size() - time.curve_index - 1;
+ Coord new_time = 1.0 - time.t;
+ if (new_index < 0) {
+ new_index = 0;
+ new_time = 0;
+ }
+ return PathTime(new_index, new_time);
+ }
+
+ /** Return path time at the end of the path. */
+ inline static PathTime _pathEnd(Path const &path) { return PathTime(path.size() - 1, 1.0); }
+ inline static auto const PATH_START = PathTime(0, 0);
+
+public:
+ static double closedPathArea(Path const &path);
+ static bool deviatesLeft(Path const &first, Path const &second);
+};
+
+/**
+ * \brief Insert a new vertex or reuse an existing one.
+ *
+ * Ensures that there is a vertex at or near the specified position
+ * (within the distance of _precision).
+ *
+ * \param pos The desired geometric position of the new vertex.
+ * \return A pointer to the inserted vertex or a pre-existing vertex near the
+ * desired position.
+ */
+template<typename EL>
+typename PlanarGraph<EL>::Vertex *PlanarGraph<EL>::_ensureVertexAt(Point const &pos)
+{
+ auto const insert_at_front = [&, this]() -> Vertex* {
+ _vertices.emplace_front(pos);
+ return &(_vertices.front());
+ };
+
+ if (_vertices.empty()) {
+ return insert_at_front();
+ }
+
+ // TODO: Use a heap?
+ auto it = std::find_if(_vertices.begin(), _vertices.end(), [&](Vertex const &v) -> bool {
+ return Vertex::_cmp(pos, v._position); // existing vertex position > pos.
+ });
+
+ if (it != _vertices.end()) {
+ if (are_near(pos, it->_position, _precision)) {
+ return &(*it); // Reuse existing vertex.
+ }
+ if (it == _vertices.begin()) {
+ return insert_at_front();
+ }
+ }
+ // Look at the previous element, reuse if near, insert before `it` otherwise.
+ return &(*(are_near(pos, std::prev(it)->_position, _precision) ? std::prev(it)
+ : _vertices.emplace(it, pos)));
+}
+
+/**
+ * \brief Move-insert a new labeled edge into the planar graph.
+ *
+ * \param path The geometric path of the edge.
+ * \param label Optionally, the label (extra user data) associated to this edge.
+ * If absent, a default-constructed label will be used.
+ * \return The index of the inserted edge.
+ */
+template<typename EdgeLabel>
+unsigned PlanarGraph<EdgeLabel>::insertEdge(Path &&path, EdgeLabel &&label)
+{
+ unsigned edge_index = _edges.size();
+ auto &inserted = _edges.emplace_back(std::forward<Path>(path),
+ std::forward<EdgeLabel>(label));
+
+ // Calculate the outgoing azimuths at both endpoints.
+ double const start_azimuth = _getAzimuth(inserted.path.initialUnitTangent());
+ double const end_azimuth = _getAzimuth(-inserted.path.finalUnitTangent());
+
+ // Get the endpoints into the graph.
+ auto start = _ensureVertexAt(inserted.path.initialPoint());
+ auto end = _ensureVertexAt(inserted.path.finalPoint());
+
+ // Inform the edge about its endpoints.
+ inserted.start = start;
+ inserted.end = end;
+
+ // Add incidences at the endpoints.
+ start->_addIncidence(edge_index, start_azimuth, Incidence::START);
+ end->_addIncidence(edge_index, end_azimuth, Incidence::END);
+
+ _regularized = false;
+ return edge_index;
+}
+
+/**
+ * \brief Move-insert a new labeled edge but do not connect it to the graph.
+ *
+ * Although the graph will hold the path data of an edge inserted in this way, the edge
+ * will not be connected to any vertex. This can be used to store information about closed
+ * paths (loops) in the instance, without having to specify starting points for them.
+ *
+ * \param path The geometric path of the edge.
+ * \param label Optionally, the label (extra user data) associated to this edge; if absent,
+ * the label will be default-constructed.
+ * \return The index of the inserted edge.
+ */
+template<typename EdgeLabel>
+unsigned PlanarGraph<EdgeLabel>::insertDetached(Path &&path, EdgeLabel &&label)
+{
+ unsigned edge_index = _edges.size();
+ auto &inserted = _edges.emplace_back(std::forward<Path>(path),
+ std::forward<EdgeLabel>(label));
+ inserted.detached = true;
+ inserted.inserted_as_detached = true;
+ return edge_index;
+}
+
+/** Remove incidences previously marked as junk. */
+template<typename EdgeLabel>
+void PlanarGraph<EdgeLabel>::_purgeJunkIncidences()
+{
+ for (auto &[vertex, incidence] : _junk) {
+ Incidence *to_remove = incidence;
+ auto it = std::find_if(vertex->_incidences.begin(), vertex->_incidences.end(),
+ [=](Incidence const &inc) -> bool { return &inc == to_remove; });
+ if (it != vertex->_incidences.end()) {
+ vertex->_incidences.erase(it);
+ }
+ }
+ _junk.clear();
+}
+
+/**
+ * \brief Merge overlapping edges or their portions, adding vertices if necessary.
+ *
+ * \param angle_precision The numerical epsilon for radian angle comparisons.
+ * \param remove_collapsed_loops Whether to detach edges with both ends incident to the same
+ * vertex (loops) when these loops don't enclose any area.
+ *
+ * This function performs the following operations:
+ * \li Edges that are tangent at a vertex but don't otherwise overlap are sorted correctly
+ * in the counterclockwise cyclic order around the vertex.
+ * \li Degenerate loops which don't enclose any area are removed if the argument is true.
+ * \li Edges that coincide completely are reversed if needed and merged into one.
+ * \li Edges that coincide partially are split into overlapping and non-overlapping portions.
+ * Any overlapping portions are oriented consistently and then merged.
+ * \li As a sub-case of the above, any non-degenerate loop with an initial self-everlap
+ * (a "lasso") is replaced with a shorter non-overlapping loop and a simple path leading
+ * to it.
+ */
+template<typename EdgeLabel>
+void PlanarGraph<EdgeLabel>::regularize(double angle_precision, bool remove_collapsed_loops)
+{
+ for (auto it = _vertices.begin(); it != _vertices.end(); ++it) {
+ // Note: the list of vertices may grow during the execution of this loop,
+ // so don't replace it with a range-for (which stores the end iterator).
+ // We want the loop to carry on going over the elements it inserted.
+ if (it->_incidences.size() < 2) {
+ continue;
+ }
+ _regularizeVertex(*it, angle_precision, remove_collapsed_loops);
+ }
+ _purgeJunkIncidences();
+ _regularized = true;
+}
+
+/**
+ * \brief Analyze and regularize all edges emanating from a given vertex.
+ *
+ * This function goes through the list of incidences at the vertex (roughly sorted by
+ * azimuth, i.e., departure heading in radians), picking out runs of mutually tangent
+ * edges and calling _reglueTangentFan() on each run. The algorithm is quite complicated
+ * because the incidences have to be treated as a cyclic container and a run of mutually
+ * tangent edges may straddle the "end" of the list, including the possibility that the
+ * entire list is a single such run.
+ *
+ * \param vertex The vertex whose incidences should be analyzed.
+ * \param angle_precision The numerical epsilon for radian angle comparisons.
+ * \param deloop Whether loops that don't enclose any area should be detached.
+ */
+template<typename EdgeLabel>
+void PlanarGraph<EdgeLabel>::_regularizeVertex(typename PlanarGraph<EdgeLabel>::Vertex &vertex,
+ double angle_precision, bool deloop)
+{
+ auto &incidences = vertex._incidences;
+
+ /// Compare two polar angles in the interval [-π, π] modulo 2π to within angle_precision:
+ auto const angles_equal = [=](double az1, double az2) -> bool {
+ static double const twopi = 2.0 * M_PI;
+ return are_near(std::fmod(az1 + twopi, twopi), std::fmod(az2 + twopi, twopi),
+ angle_precision);
+ };
+
+ IncIt run_begin; // First element in the last discovered run of equal azimuths.
+
+ /// Find and reglue runs of nearly identical azimuths in the specified range.
+ auto const process_runs = [&](IncIt begin, IncIt end) -> bool
+ {
+ double current_azimuth = 42; // Invalid radian angle.
+ bool in_a_run = false;
+
+ for (auto it = begin; it != end; ++it) {
+ bool const equal = angles_equal(it->azimuth, current_azimuth);
+ if (equal && !in_a_run) {
+ run_begin = std::prev(it); // Save to enclosing scope.
+ in_a_run = true;
+ } else if (!equal && in_a_run) {
+ _reglueTangentFan(vertex, run_begin, std::prev(it), deloop);
+ in_a_run = false;
+ }
+ current_azimuth = it->azimuth;
+ }
+ return in_a_run;
+ };
+
+ double const last_azimuth = incidences.back().azimuth;
+
+ if (angles_equal(incidences.front().azimuth, last_azimuth)) {
+ // The cyclic list contains a run of equal azimuths which straddles the "end".
+ // This means that we must skip the part of this run on the "begin" side on the
+ // first pass and handle it once we've traversed the remainder of the list.
+
+ bool processed = false; ///< Whether we've cleared the straddling run.
+ double previous_azimuth = last_azimuth;
+ IncIt straddling_run_last;
+
+ for (auto it = incidences.begin(); it != incidences.end(); ++it) {
+ if (!angles_equal(it->azimuth, previous_azimuth)) {
+ straddling_run_last = std::prev(it);
+ process_runs(it, incidences.end());
+ processed = true;
+ break;
+ }
+ previous_azimuth = it->azimuth;
+ }
+ if (processed) {
+ // Find the first element of the straddling run.
+ auto it = std::prev(incidences.end());
+ while (angles_equal(it->azimuth, last_azimuth)) {
+ --it;
+ }
+ ++it; // Now we're at the start of the straddling run.
+ _reglueTangentFan(vertex, it, straddling_run_last, deloop);
+ } else {
+ // We never encountered anything outside of the straddling run: reglue everything.
+ _reglueTangentFan(vertex, incidences.begin(), std::prev(incidences.end()), deloop);
+ }
+ } else if (process_runs(incidences.begin(), incidences.end())) {
+ // Our run got rudely interrupted by the end of the container; reglue till the end.
+ _reglueTangentFan(vertex, run_begin, std::prev(incidences.end()), deloop);
+ }
+}
+
+/**
+ * \brief Regularize a fan of mutually tangent edges emanating from a vertex.
+ *
+ * This function compares the tangent edges pairwise and ensures that the sequence of their
+ * incidences to the vertex ends up being sorted by the ultimate direction in which the
+ * emanating edges fan out, in the counterclockwise order.
+ *
+ * If a partial or complete overlap between edges is detected, these edges are reglued.
+ *
+ * \param vertex The vertex from which the fan emanates.
+ * \param first An iterator pointing to the first incidence in the fan.
+ * \param last An iterator pointing to the last incidence in the fan.
+ * NOTE: This iterator must point to the actual last incidence, not "past" it.
+ * The reason is that we're iterating over a cyclic collection, so there
+ * isn't really a meaningful end.
+ * \param deloop Whether loops that don't enclose any area should be detached.
+ */
+template<typename EL>
+void PlanarGraph<EL>::_reglueTangentFan(typename PlanarGraph<EL>::Vertex &vertex,
+ typename PlanarGraph<EL>::IncIt const &first,
+ typename PlanarGraph<EL>::IncIt const &last, bool deloop)
+{
+ // Search all pairs (triangular pattern), skipping invalid incidences.
+ for (auto it = first; it != last; it = vertex.cyclicNextIncidence(it)) {
+ if (it->invalid) {
+ continue;
+ }
+ for (auto is = vertex.cyclicNextIncidence(it); true; is = vertex.cyclicNextIncidence(is)) {
+ if (!is->invalid && _compareAndReglue(vertex, &(*it), &(*is), deloop)) {
+ // Swap the incidences, effectively implementing "bubble sort".
+ std::swap(*it, *is);
+ }
+ if (is == last) {
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * \brief Compare a pair of edges emanating from the same vertex in the same direction.
+ *
+ * If the edges overlap in part or in full, they get reglued, which means that the topology
+ * of the graph may get modified. Otherwise, if the detailed comparison shows that the edges
+ * aren't correctly ordered around the vertex (because the second edge deviates to the right
+ * instead of to the left of the first, when looking away from the vertex), then the function
+ * will return true, signalling that the incidences should be swapped.
+ *
+ * \param vertex The vertex where the mutually tangent paths meet.
+ * \param first The incidence appearing as the first one in the provisional cyclic order.
+ * \param second The incidence appearing as the second one in the provisional cyclic order.
+ * \param deloop Whether to detach collapsed loops (backtracks) which don't enclose any area.
+ * \return Whether the incidences should be swapped.
+ */
+template<typename EL>
+bool PlanarGraph<EL>::_compareAndReglue(typename PlanarGraph<EL>::Vertex &vertex,
+ typename PlanarGraph<EL>::Incidence *first,
+ typename PlanarGraph<EL>::Incidence *second, bool deloop)
+{
+ if (first->index == second->index) {
+ return _reglueTeardrop(vertex, first, second, deloop);
+ }
+
+ // Get paths corresponding to the edges but travelling away from the vertex.
+ auto first_path_out = getOutgoingPath(first);
+ auto second_path_out = getOutgoingPath(second);
+ auto split = parting_point(first_path_out, second_path_out, _precision);
+
+ if (are_near(split.point(), vertex.point(), _precision)) {
+ // Paths deviate immediately, so no gluing is needed. The incidences should
+ // be swapped if the first edge path departs to the left of the second one.
+ return deviatesLeft(first_path_out, second_path_out);
+ }
+
+ // Determine the nature of the initial overlap between the paths.
+ bool const till_end_of_1st = are_near(split.point(), first_path_out.finalPoint(), _precision);
+ bool const till_end_of_2nd = are_near(split.point(), second_path_out.finalPoint(), _precision);
+
+ if (till_end_of_1st && till_end_of_2nd) { // Paths coincide completely.
+ _mergeCoincidingEdges(first, second);
+ } else if (till_end_of_1st) {
+ // Paths coincide until the end of the 1st one, which however isn't the end of the
+ // 2nd one; for example, the first one could be the vertical riser of the letter L
+ // whereas the second one – the entire letter stroke.
+ _mergeShorterLonger(vertex, first, second, split.second);
+ } else if (till_end_of_2nd) {
+ // The same but with with the second edge shorter than the first one.
+ _mergeShorterLonger(vertex, second, first, split.first);
+ } else { // A Y-shaped split.
+ _mergeWyeConfiguration(vertex, first, second, split);
+ }
+ return false; // We've glued so no need to swap anything.
+}
+
+/**
+ * \brief Analyze a loop path a with self-tangency at the attachment point (a teardrop).
+ *
+ * The following steps are taken:
+ * \li If the loop encloses zero area and \c deloop is true, the loop is detached.
+ * \li If the two arms of the loop split out immediately, the loop is left alone and we
+ * only check whether the incidences should be swapped.
+ * \li If the loop overlaps itself near the vertex, resembling a lasso, we split it into
+ * a shorter simple path and a smaller loop attached to the end of the shorter path.
+ *
+ * \param vertex The vertex at which the teardrop originates.
+ * \param first The first incidence of the loop to the vertex.
+ * \param second The second incidence of the loop to the vertex.
+ * \param deloop Whether the loop should be removed if it doesn't enclose any area
+ * (i.e., the path exactly backtracks on itself).
+ * \return Whether the two incidences of the loop to the vertex should be swapped.
+ */
+template<typename EL>
+bool PlanarGraph<EL>::_reglueTeardrop(typename PlanarGraph<EL>::Vertex &vertex,
+ typename PlanarGraph<EL>::Incidence *first,
+ typename PlanarGraph<EL>::Incidence *second, bool deloop)
+{
+ // Calculate the area enclosed by the teardrop.
+ // The convention is that the unit circle (cos(t), sint(t)), t from 0 to 2pi,
+ // encloses an area of +pi.
+ auto &edge = _edges[first->index];
+ Path loop = edge.path; loop.close();
+ double signed_area = closedPathArea(loop);
+
+ if (deloop && are_near(signed_area, 0.0, _precision)) {
+ edge.detach();
+ _throwAway(&vertex, first);
+ _throwAway(&vertex, second);
+ return false;
+ }
+
+ auto split = parting_point(loop, loop.reversed(), _precision);
+ if (are_near(split.point(), vertex.point(), _precision)) {
+ // The loop spreads out immediately. We simply check if the incidences should be swapped.
+ // We want them to be ordered such that the signed area encircled by the path going out
+ // at the first incidence and coming back at the second (with this orientation) is > 0.
+ return (first->sign == Incidence::START) ^ (signed_area > 0.0);
+ }
+
+ // The loop encloses a nonzero area, but the two branches don't separate at the starting
+ // point. Instead, they travel together for a while before they split like a lasso.
+ _reglueLasso(vertex, first, second, split);
+ return false;
+}
+
+/**
+ * \brief Reglue a lasso-shaped loop, separating it into the "free rope" and the "hoop".
+ *
+ * The lasso is an edge looping back to the same vertex, where the closed path encloses
+ * a non-zero area, but its two branches don't separate at the starting point. Instead,
+ * they travel together for a while (forming the doubled-up "free rope") before they
+ * split like a lasso. This function cuts the lasso at the split point:
+ * \code{.unparsed}
+ * ____ ____
+ * / \ / \
+ * VERTEX =====< | ==> VERTEX ------ NEW + NEW < |
+ * \____/ (lasso) (rope) \____/ (hoop)
+ *
+ * \endcode
+ *
+ * \param vertex A reference to the vertex where the lasso is attached.
+ * \param first The first incidence of the lasso to the vertex.
+ * \param second The second incidence of the lasso to the vertex.
+ * \param split The point where the free rope of the lasso ends and the hoop begins.
+ */
+template<typename EL>
+void PlanarGraph<EL>::_reglueLasso(typename PlanarGraph<EL>::Vertex &vertex,
+ typename PlanarGraph<EL>::Incidence *first,
+ typename PlanarGraph<EL>::Incidence *second,
+ PathIntersection const &split)
+{
+ unsigned lasso = first->index;
+
+ // Create the "free rope" path.
+ auto rope = _edges[lasso].path.portion(PATH_START, split.first);
+ rope.setInitial(vertex.point());
+ rope.setFinal(split.point());
+ double const rope_final_backward_azimuth = _getAzimuth(-rope.finalUnitTangent());
+
+ // Compute the new label of the rope edge.
+ auto oriented_as_loop = _edges[lasso].label;
+ auto reversed = oriented_as_loop; reversed.onReverse();
+ oriented_as_loop.onMergeWith(reversed);
+
+ // Insert the rope and its endpoint.
+ unsigned const rope_index = _edges.size();
+ auto &rope_edge = _edges.emplace_back(std::move(rope), std::move(oriented_as_loop));
+ auto const new_split_vertex = _ensureVertexAt(split.point());
+
+ // Reuse lasso's first incidence as the incidence to the rope (azimuth can stay).
+ first->index = rope_index;
+ first->sign = Incidence::START;
+
+ // Connect the rope to the newly created split vertex.
+ new_split_vertex->_addIncidence(rope_index, rope_final_backward_azimuth, Incidence::END);
+ rope_edge.start = &vertex;
+ rope_edge.end = new_split_vertex;
+
+ // Insert the hoop
+ auto hoop = _edges[lasso].path.portion(split.first,
+ _reversePathTime(split.second, _edges[lasso].path));
+ hoop.setInitial(split.point());
+ hoop.setFinal(split.point());
+ insertEdge(std::move(hoop), EL(_edges[lasso].label));
+
+ // Detach the original lasso edge and mark the second incidence for cleanup.
+ _edges[lasso].detach();
+ _throwAway(&vertex, second);
+}
+
+/**
+ * \brief Completely coallesce two fully overlapping edges.
+ *
+ * In practice, the first edge stays and the second one gets detached from the graph.
+ *
+ * \param first An iterator to the first edge's incidence to a common vertex.
+ * \param second An iterator to the second edge's incidence to a common vertex.
+ */
+template<typename EL>
+void PlanarGraph<EL>::_mergeCoincidingEdges(typename PlanarGraph<EL>::Incidence *first,
+ typename PlanarGraph<EL>::Incidence *second)
+{
+ auto &surviver = _edges[first->index];
+ auto &casualty = _edges[second->index];
+
+ auto other_label = casualty.label;
+ if (first->sign != second->sign) { // Logically reverse the label before merging.
+ other_label.onReverse();
+ }
+ surviver.label.onMergeWith(other_label);
+
+ // Mark both incidences of the second edge as junk and detach it.
+ auto [start_vertex, start_inc] = getIncidence(second->index, Incidence::START);
+ _throwAway(start_vertex, start_inc);
+ auto [end_vertex, end_inc] = getIncidence(second->index, Incidence::END);
+ _throwAway(end_vertex, end_inc);
+ casualty.detach();
+}
+
+/**
+ * \brief Merge a longer edge with a shorter edge that overlaps it.
+ *
+ * In practice, the shorter edge remains unchanged and the longer one is trimmed to
+ * become just the part extending past the shorter one.
+ *
+ * \param vertex The vertex where the overlap starts.
+ * \param shorter The incidence of the shorter edge to the common vertex.
+ * \param longer The incidence of the longer edge to the common vertex.
+ * \param time_on_longer The PathTime on the longer edge at which it passes through
+ * the endpoint of the shorter edge.
+ */
+template<typename EL>
+void PlanarGraph<EL>::_mergeShorterLonger(typename PlanarGraph<EL>::Vertex &vertex,
+ typename PlanarGraph<EL>::Incidence *shorter,
+ typename PlanarGraph<EL>::Incidence *longer,
+ PathTime const &time_on_longer)
+{
+ auto &shorter_edge = _edges[shorter->index];
+ auto &longer_edge = _edges[longer->index];
+
+ // Get the vertices at the far ends of both edges.
+ auto shorter_far_end = (shorter->sign == Incidence::START) ? shorter_edge.end
+ : shorter_edge.start;
+ /// Whether the longer edge heads out of the vertex.
+ bool const longer_out = (longer->sign == Incidence::START);
+ auto longer_far_end = longer_out ? longer_edge.end : longer_edge.start;
+
+ // Copy the longer edge's label and merge with that of the shorter.
+ auto longer_label = longer_edge.label;
+ if (shorter->sign != longer->sign) {
+ longer_label.onReverse();
+ }
+ shorter_edge.label.onMergeWith(longer_label);
+
+ // Create the trimmed path (longer minus shorter).
+ Path trimmed;
+ double trimmed_departure_azimuth;
+ if (longer_out) {
+ trimmed = longer_edge.path.portion(time_on_longer, _pathEnd(longer_edge.path));
+ longer_edge.start = shorter_far_end;
+ trimmed.setInitial(shorter_far_end->point());
+ trimmed.setFinal(longer_far_end->point());
+ trimmed_departure_azimuth = _getAzimuth(trimmed.initialUnitTangent());
+ } else {
+ trimmed = longer_edge.path.portion(PATH_START, _reversePathTime(time_on_longer,
+ longer_edge.path));
+ longer_edge.end = shorter_far_end;
+ trimmed.setInitial(longer_far_end->point());
+ trimmed.setFinal(shorter_far_end->point());
+ trimmed_departure_azimuth = _getAzimuth(-trimmed.finalUnitTangent());
+ }
+
+ // Set the trimmed path as the new path of the longer edge and set up the incidences:
+ longer_edge.path = std::move(trimmed);
+ shorter_far_end->_addIncidence(longer->index, trimmed_departure_azimuth, longer->sign);
+
+ // Throw away the old start incidence of the longer edge.
+ _throwAway(&vertex, longer);
+}
+
+/**
+ * \brief Merge a pair of partially overlapping edges, producing a Y-split at a new vertex.
+ *
+ * This topological modification is performed by inserting a new vertex at the three-way
+ * point (where the two paths separate) and clipping the original edges to that point.
+ * In this way, the original edges become the "arms" of the Y-shape. In addition, a new
+ * edge is inserted, forming the "stem" of the Y.
+ *
+ * \param vertex The vertex from which the partially overlapping edges originate (bottom of Y).
+ * \param first The incidence to the first edge (whose path is the stem and one arm of the Y).
+ * \param second The incidence to the second edge (stem and the other arm of the Y).
+ * \param fork The splitting point of the two paths.
+ */
+template<typename EL>
+void PlanarGraph<EL>::_mergeWyeConfiguration(typename PlanarGraph<EL>::Vertex &vertex,
+ typename PlanarGraph<EL>::Incidence *first,
+ typename PlanarGraph<EL>::Incidence *second,
+ PathIntersection const &fork)
+{
+ bool const first_is_out = (first->sign == Incidence::START);
+ bool const second_is_out = (second->sign == Incidence::START);
+
+ auto &first_edge = _edges[first->index];
+ auto &second_edge = _edges[second->index];
+
+ // Calculate the path forming the stem of the Y:
+ auto stem_path = getOutgoingPath(first).portion(PATH_START, fork.first);
+ stem_path.setInitial(vertex.point());
+ stem_path.setFinal(fork.point());
+
+ /// A closure to clip the path of an original edge to the fork point.
+ auto const clip_to_fork = [&](PathTime const &t, Edge &e, bool out) {
+ if (out) { // Trim from time to end
+ e.path = e.path.portion(t, _pathEnd(e.path));
+ e.path.setInitial(fork.point());
+ } else { // Trim from reverse-end to reverse-time
+ e.path = e.path.portion(PATH_START, _reversePathTime(t, e.path));
+ e.path.setFinal(fork.point());
+ }
+ };
+
+ /// A closure to find the departing azimuth of an edge at the fork point.
+ auto const departing_azimuth = [&](Edge const &e, bool out) -> double {
+ return _getAzimuth((out) ? e.path.initialUnitTangent()
+ : -e.path.finalUnitTangent());
+ };
+
+ // Clip the paths obtaining the arms of the Y.
+ clip_to_fork(fork.first, first_edge, first_is_out);
+ clip_to_fork(fork.second, second_edge, second_is_out);
+
+ // Create the fork vertex and set up its incidences.
+ auto const fork_vertex = _ensureVertexAt(fork.point());
+ fork_vertex->_addIncidence(first->index, departing_azimuth(first_edge, first_is_out),
+ first->sign);
+ fork_vertex->_addIncidence(second->index, departing_azimuth(second_edge, second_is_out),
+ second->sign);
+
+ // Repoint the ends of the edges that were clipped
+ (first_is_out ? first_edge.start : first_edge.end) = fork_vertex;
+ (second_is_out ? second_edge.start : second_edge.end) = fork_vertex;
+
+ /// A closure to get a consistently oriented label of an edge.
+ auto upwards_oriented_label = [&](Edge const &e, bool out) -> EL {
+ auto label = e.label;
+ if (!out) {
+ label.onReverse();
+ }
+ return label;
+ };
+
+ auto stem_label = upwards_oriented_label(first_edge, first_is_out);
+ stem_label.onMergeWith(upwards_oriented_label(second_edge, second_is_out));
+ auto stem_departure_from_fork = _getAzimuth(-stem_path.finalUnitTangent());
+
+ // Insert the stem of the Y-configuration.
+ unsigned const stem_index = _edges.size();
+ auto &stem_edge = _edges.emplace_back(std::move(stem_path), std::move(stem_label));
+ stem_edge.start = &vertex;
+ stem_edge.end = fork_vertex;
+
+ // Set up the incidences.
+ fork_vertex->_addIncidence(stem_index, stem_departure_from_fork, Incidence::END);
+ first->index = stem_index;
+ first->sign = Incidence::START;
+ _throwAway(&vertex, second);
+}
+
+template<typename EL>
+typename PlanarGraph<EL>::Incidence*
+PlanarGraph<EL>::nextIncidence(typename PlanarGraph<EL>::VertexIterator const &vertex,
+ double azimuth, bool clockwise) const
+{
+ auto &incidences = vertex._incidences;
+ Incidence *result = nullptr;
+
+ if (incidences.empty()) {
+ return result;
+ }
+ // Normalize azimuth to the interval [-pi; pi].
+ auto angle = Angle(azimuth);
+
+ if (clockwise) { // Go backwards and find a lower bound
+ auto it = std::find_if(incidences.rbegin(), incidences.rend(), [=](auto inc) -> bool {
+ return inc.azimuth <= angle;
+ });
+ if (it == incidences.rend()) {
+ // azimuth is lower than the azimuths of all incidences;
+ // going clockwise we wrap back to the highest azimuth (last incidence).
+ return &incidences.back();
+ }
+ result = &(*it);
+ } else {
+ auto it = std::find_if(incidences.begin(), incidences.end, [=](auto inc) -> bool {
+ return inc.azimuth >= angle;
+ });
+ if (it == incidences.end()) {
+ // azimuth is higher than the azimuths of all incidences;
+ // going counterclockwise we wrap back to the lowest azimuth.
+ return &incidences.front();
+ }
+ result = &(*it);
+ }
+ return result;
+}
+
+/** Return the signed area enclosed by a closed path. */
+template<typename EL>
+double PlanarGraph<EL>::closedPathArea(Path const &path)
+{
+ double area;
+ Point _;
+ centroid(path.toPwSb(), _, area);
+ return -area; // Our convention is that the Y-axis points up
+}
+
+/** \brief Determine whether the first path deviates to the left of the second.
+ *
+ * The two paths are assumed to have identical or nearly identical starting points
+ * but not an overlapping initial portion. The concept of "left" is based on the
+ * y-axis pointing up.
+ *
+ * \param first The first path.
+ * \param second The second path.
+ *
+ * \return True if the first path deviates towards the left of the second;
+ * False if the first path deviates towards the right of the second.
+ */
+template<typename EL>
+bool PlanarGraph<EL>::deviatesLeft(Path const &first, Path const &second)
+{
+ auto start = middle_point(first.initialPoint(), second.initialPoint());
+ auto tangent_between = middle_point(first.initialUnitTangent(), second.initialUnitTangent());
+ if (tangent_between.isZero()) {
+ return false;
+ }
+ auto tangent_line = Line::from_origin_and_vector(start, tangent_between);
+
+ // Find the first non-degenerate curves on both paths
+ std::unique_ptr<Curve> c[2];
+ auto const find_first_nondegen = [](std::unique_ptr<Curve> &pointer, Path const &path) {
+ for (auto const &c : path) {
+ if (!c.isDegenerate()) {
+ pointer.reset(c.duplicate());
+ return;
+ }
+ }
+ };
+
+ find_first_nondegen(c[0], first);
+ find_first_nondegen(c[1], second);
+ if (!c[0] || !c[1]) {
+ return false;
+ }
+
+ // Find the bounding boxes
+ Rect const bounding_boxes[] {
+ c[0]->boundsExact(),
+ c[1]->boundsExact()
+ };
+
+ // For a bounding box, find the corner that goes the furthest in the direction of the
+ // tangent vector.
+ auto const furthest_corner = [&](Rect const &r) -> unsigned {
+ Coord max_dot = dot(r.corner(0) - start, tangent_between);
+ unsigned result = 0;
+ for (unsigned i = 1; i < 4; i++) {
+ auto current_dot = dot(r.corner(i), tangent_between);
+ if (current_dot > max_dot) {
+ max_dot = current_dot;
+ result = i;
+ } else if (current_dot == max_dot) {
+ // Disambiguate based on proximity to the tangent line.
+ auto const offset = start + tangent_between;
+ if (distance(offset, r.corner(i)) < distance(offset, r.corner(result))) {
+ result = i;
+ }
+ }
+ }
+ return result;
+ };
+
+ // Calculate the corner points overlooking the "rift" between the paths.
+ Point corner_points[2];
+ for (size_t i : {0, 1}) {
+ corner_points[i] = bounding_boxes[i].corner(furthest_corner(bounding_boxes[i]));
+ }
+
+ // Find a vantage point from which we can best observe the splitting paths.
+ Point vantage_point;
+ bool found = false;
+ if (corner_points[0] != corner_points[1]) {
+ auto line_connecting_corners = Line(corner_points[0], corner_points[1]);
+ auto xing = line_connecting_corners.intersect(tangent_line);
+ if (!xing.empty()) {
+ vantage_point = xing[0].point();
+ found = true;
+ }
+ }
+ if (!found) {
+ vantage_point = tangent_line.pointAt(tangent_line.timeAtProjection(corner_points[0]));
+ }
+
+ // Move to twice as far in the direction of the vantage point.
+ vantage_point += vantage_point - start;
+
+ // Find the points on both curves that are nearest to the vantage point.
+ Coord nearest[2];
+ for (size_t i : {0, 1}) {
+ nearest[i] = c[i]->nearestTime(vantage_point);
+ }
+
+ // Clip to the nearest points and examine the closed contour.
+ Path closed_contour(start);
+ closed_contour.setStitching(true);
+ closed_contour.append(c[0]->portion(0, nearest[0]));
+ closed_contour = closed_contour.reversed();
+ closed_contour.setStitching(true);
+ closed_contour.append(c[1]->portion(0, nearest[1]));
+ closed_contour.close();
+ return !path_direction(closed_contour); // Reverse to match the convention that y-axis is up.
+}
+
+} // namespace Geom
+
+#endif // LIB2GEOM_SEEN_PLANAR_GRAPH_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/point.cpp b/src/3rdparty/2geom/src/2geom/point.cpp
new file mode 100644
index 0000000..cbe53c4
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/point.cpp
@@ -0,0 +1,274 @@
+/**
+ * \file
+ * \brief Cartesian point / 2D vector and related operations
+ *//*
+ * Authors:
+ * Michael G. Sloan <mgsloan@gmail.com>
+ * Nathan Hurst <njh@njhurst.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2006-2009 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <assert.h>
+#include <math.h>
+#include <2geom/angle.h>
+#include <2geom/coord.h>
+#include <2geom/point.h>
+#include <2geom/transforms.h>
+
+namespace Geom {
+
+/**
+ * @class Point
+ * @brief Two-dimensional point that doubles as a vector.
+ *
+ * Points in 2Geom are represented in Cartesian coordinates, e.g. as a pair of numbers
+ * that store the X and Y coordinates. Each point is also a vector in \f$\mathbb{R}^2\f$
+ * from the origin (point at 0,0) to the stored coordinates,
+ * and has methods implementing several vector operations (like length()).
+ *
+ * @section OpNotePoint Operator note
+ *
+ * Most operators are provided by Boost operator helpers, so they are not visible in this class.
+ * If @a p, @a q, @a r denote points, @a s a floating-point scalar, and @a m a transformation matrix,
+ * then the following operations are available:
+ * @code
+ p += q; p -= q; r = p + q; r = p - q;
+ p *= s; p /= s; q = p * s; q = s * p; q = p / s;
+ p *= m; q = p * m; q = m * p;
+ @endcode
+ * It is possible to left-multiply a point by a matrix, even though mathematically speaking
+ * this is undefined. The result is a point identical to that obtained by right-multiplying.
+ *
+ * @ingroup Primitives */
+
+Point Point::polar(Coord angle) {
+ Point ret;
+ Coord remainder = Angle(angle).radians0();
+ if (are_near(remainder, 0) || are_near(remainder, 2*M_PI)) {
+ ret[X] = 1;
+ ret[Y] = 0;
+ } else if (are_near(remainder, M_PI/2)) {
+ ret[X] = 0;
+ ret[Y] = 1;
+ } else if (are_near(remainder, M_PI)) {
+ ret[X] = -1;
+ ret[Y] = 0;
+ } else if (are_near(remainder, 3*M_PI/2)) {
+ ret[X] = 0;
+ ret[Y] = -1;
+ } else {
+ sincos(angle, ret[Y], ret[X]);
+ }
+ return ret;
+}
+
+/** @brief Normalize the vector representing the point.
+ * After this method returns, the length of the vector will be 1 (unless both coordinates are
+ * zero - the zero point will be returned then). The function tries to handle infinite
+ * coordinates gracefully. If any of the coordinates are NaN, the function will do nothing.
+ * @post \f$-\epsilon < \left|this\right| - 1 < \epsilon\f$
+ * @see unit_vector(Geom::Point const &) */
+void Point::normalize() {
+ double len = hypot(_pt[0], _pt[1]);
+ if(len == 0) return;
+ if(std::isnan(len)) return;
+ static double const inf = HUGE_VAL;
+ if(len != inf) {
+ *this /= len;
+ } else {
+ unsigned n_inf_coords = 0;
+ /* Delay updating pt in case neither coord is infinite. */
+ Point tmp;
+ for ( unsigned i = 0 ; i < 2 ; ++i ) {
+ if ( _pt[i] == inf ) {
+ ++n_inf_coords;
+ tmp[i] = 1.0;
+ } else if ( _pt[i] == -inf ) {
+ ++n_inf_coords;
+ tmp[i] = -1.0;
+ } else {
+ tmp[i] = 0.0;
+ }
+ }
+ switch (n_inf_coords) {
+ case 0: {
+ /* Can happen if both coords are near +/-DBL_MAX. */
+ *this /= 4.0;
+ len = hypot(_pt[0], _pt[1]);
+ assert(len != inf);
+ *this /= len;
+ break;
+ }
+ case 1: {
+ *this = tmp;
+ break;
+ }
+ case 2: {
+ *this = tmp * sqrt(0.5);
+ break;
+ }
+ }
+ }
+}
+
+/** @brief Compute the first norm (Manhattan distance) of @a p.
+ * This is equal to the sum of absolutes values of the coordinates.
+ * @return \f$|p_X| + |p_Y|\f$
+ * @relates Point */
+Coord L1(Point const &p) {
+ Coord d = 0;
+ for ( int i = 0 ; i < 2 ; i++ ) {
+ d += fabs(p[i]);
+ }
+ return d;
+}
+
+/** @brief Compute the infinity norm (maximum norm) of @a p.
+ * @return \f$\max(|p_X|, |p_Y|)\f$
+ * @relates Point */
+Coord LInfty(Point const &p) {
+ Coord const a(fabs(p[0]));
+ Coord const b(fabs(p[1]));
+ return ( a < b || std::isnan(b)
+ ? b
+ : a );
+}
+
+/** @brief True if the point has both coordinates zero.
+ * NaNs are treated as not equal to zero.
+ * @relates Point */
+bool is_zero(Point const &p) {
+ return ( p[0] == 0 &&
+ p[1] == 0 );
+}
+
+/** @brief True if the point has a length near 1. The are_near() function is used.
+ * @relates Point */
+bool is_unit_vector(Point const &p, Coord eps) {
+ return are_near(L2(p), 1.0, eps);
+}
+/** @brief Return the angle between the point and the +X axis.
+ * @return Angle in \f$(-\pi, \pi]\f$.
+ * @relates Point */
+Coord atan2(Point const &p) {
+ return std::atan2(p[Y], p[X]);
+}
+
+/** @brief Compute the angle between a and b relative to the origin.
+ * The computation is done by projecting b onto the basis defined by a, rot90(a).
+ * @return Angle in \f$(-\pi, \pi]\f$.
+ * @relates Point */
+Coord angle_between(Point const &a, Point const &b) {
+ return std::atan2(cross(a,b), dot(a,b));
+}
+
+/** @brief Create a normalized version of a point.
+ * This is equivalent to copying the point and calling its normalize() method.
+ * The returned point will be (0,0) if the argument has both coordinates equal to zero.
+ * If any coordinate is NaN, this function will do nothing.
+ * @param a Input point
+ * @return Point on the unit circle in the same direction from origin as a, or the origin
+ * if a has both coordinates equal to zero
+ * @relates Point */
+Point unit_vector(Point const &a)
+{
+ Point ret(a);
+ ret.normalize();
+ return ret;
+}
+/** @brief Return the "absolute value" of the point's vector.
+ * This is defined in terms of the default lexicographical ordering. If the point is "larger"
+ * that the origin (0, 0), its negation is returned. You can check whether
+ * the points' vectors have the same direction (e.g. lie
+ * on the same line passing through the origin) using
+ * @code abs(a).normalize() == abs(b).normalize() @endcode
+ * To check with some margin of error, use
+ * @code are_near(abs(a).normalize(), abs(b).normalize()) @endcode
+ * Although naively this should take the absolute value of each coordinate, such an operation
+ * is not very useful.
+ * @relates Point */
+Point abs(Point const &b)
+{
+ Point ret;
+ if (b[Y] < 0.0) {
+ ret = -b;
+ } else if (b[Y] == 0.0) {
+ ret = b[X] < 0.0 ? -b : b;
+ } else {
+ ret = b;
+ }
+ return ret;
+}
+
+/** @brief Transform the point by the specified matrix. */
+Point &Point::operator*=(Affine const &m) {
+ double x = _pt[X], y = _pt[Y];
+ for(int i = 0; i < 2; i++) {
+ _pt[i] = x * m[i] + y * m[i + 2] + m[i + 4];
+ }
+ return *this;
+}
+
+/** @brief Snap the angle B - A - dir to multiples of \f$2\pi/n\f$.
+ * The 'dir' argument must be normalized (have unit length), otherwise the result
+ * is undefined.
+ * @return Point with the same distance from A as B, with a snapped angle.
+ * @post distance(A, B) == distance(A, result)
+ * @post angle_between(result - A, dir) == \f$2k\pi/n, k \in \mathbb{N}\f$
+ * @relates Point */
+Point constrain_angle(Point const &A, Point const &B, unsigned int n, Point const &dir)
+{
+ // for special cases we could perhaps use explicit testing (which might be faster)
+ if (n == 0.0) {
+ return B;
+ }
+ Point diff(B - A);
+ double angle = -angle_between(diff, dir);
+ double k = round(angle * (double)n / (2.0*M_PI));
+ return A + dir * Rotate(k * 2.0 * M_PI / (double)n) * L2(diff);
+}
+
+std::ostream &operator<<(std::ostream &out, const Geom::Point &p)
+{
+ out << "(" << format_coord_nice(p[X]) << ", "
+ << format_coord_nice(p[Y]) << ")";
+ return out;
+}
+
+} // end namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/polynomial.cpp b/src/3rdparty/2geom/src/2geom/polynomial.cpp
new file mode 100644
index 0000000..9737bd0
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/polynomial.cpp
@@ -0,0 +1,337 @@
+/**
+ * \file
+ * \brief Polynomial in canonical (monomial) basis
+ *//*
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2007-2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <algorithm>
+#include <2geom/polynomial.h>
+#include <2geom/math-utils.h>
+#include <math.h>
+
+#ifdef HAVE_GSL
+#include <gsl/gsl_poly.h>
+#endif
+
+namespace Geom {
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
+Poly Poly::operator*(const Poly& p) const {
+ Poly result;
+ result.resize(degree() + p.degree()+1);
+
+ for(unsigned i = 0; i < size(); i++) {
+ for(unsigned j = 0; j < p.size(); j++) {
+ result[i+j] += (*this)[i] * p[j];
+ }
+ }
+ return result;
+}
+
+/*double Poly::eval(double x) const {
+ return gsl_poly_eval(&coeff[0], size(), x);
+ }*/
+
+void Poly::normalize() {
+ while(back() == 0)
+ pop_back();
+}
+
+void Poly::monicify() {
+ normalize();
+
+ double scale = 1./back(); // unitize
+
+ for(unsigned i = 0; i < size(); i++) {
+ (*this)[i] *= scale;
+ }
+}
+
+
+#ifdef HAVE_GSL
+std::vector<std::complex<double> > solve(Poly const & pp) {
+ Poly p(pp);
+ p.normalize();
+ gsl_poly_complex_workspace * w
+ = gsl_poly_complex_workspace_alloc (p.size());
+
+ gsl_complex_packed_ptr z = new double[p.degree()*2];
+ double* a = new double[p.size()];
+ for(unsigned int i = 0; i < p.size(); i++)
+ a[i] = p[i];
+ std::vector<std::complex<double> > roots;
+ //roots.resize(p.degree());
+
+ gsl_poly_complex_solve (a, p.size(), w, z);
+ delete[]a;
+
+ gsl_poly_complex_workspace_free (w);
+
+ for (unsigned int i = 0; i < p.degree(); i++) {
+ roots.emplace_back(z[2*i] ,z[2*i+1]);
+ //printf ("z%d = %+.18f %+.18f\n", i, z[2*i], z[2*i+1]);
+ }
+ delete[] z;
+ return roots;
+}
+
+std::vector<double > solve_reals(Poly const & p) {
+ std::vector<std::complex<double> > roots = solve(p);
+ std::vector<double> real_roots;
+
+ for(auto & root : roots) {
+ if(root.imag() == 0) // should be more lenient perhaps
+ real_roots.push_back(root.real());
+ }
+ return real_roots;
+}
+#endif
+
+double polish_root(Poly const & p, double guess, double tol) {
+ Poly dp = derivative(p);
+
+ double fn = p(guess);
+ while(fabs(fn) > tol) {
+ guess -= fn/dp(guess);
+ fn = p(guess);
+ }
+ return guess;
+}
+
+Poly integral(Poly const & p) {
+ Poly result;
+
+ result.reserve(p.size()+1);
+ result.push_back(0); // arbitrary const
+ for(unsigned i = 0; i < p.size(); i++) {
+ result.push_back(p[i]/(i+1));
+ }
+ return result;
+
+}
+
+Poly derivative(Poly const & p) {
+ Poly result;
+
+ if(p.size() <= 1)
+ return Poly(0);
+ result.reserve(p.size()-1);
+ for(unsigned i = 1; i < p.size(); i++) {
+ result.push_back(i*p[i]);
+ }
+ return result;
+}
+
+Poly compose(Poly const & a, Poly const & b) {
+ Poly result;
+
+ for(unsigned i = a.size(); i > 0; i--) {
+ result = Poly(a[i-1]) + result * b;
+ }
+ return result;
+
+}
+
+/* This version is backwards - dividing taylor terms
+Poly divide(Poly const &a, Poly const &b, Poly &r) {
+ Poly c;
+ r = a; // remainder
+
+ const unsigned k = a.size();
+ r.resize(k, 0);
+ c.resize(k, 0);
+
+ for(unsigned i = 0; i < k; i++) {
+ double ci = r[i]/b[0];
+ c[i] += ci;
+ Poly bb = ci*b;
+ std::cout << ci <<"*" << b << ", r= " << r << std::endl;
+ r -= bb.shifted(i);
+ }
+
+ return c;
+}
+*/
+
+Poly divide(Poly const &a, Poly const &b, Poly &r) {
+ Poly c;
+ r = a; // remainder
+ assert(b.size() > 0);
+
+ const unsigned k = a.degree();
+ const unsigned l = b.degree();
+ c.resize(k, 0.);
+
+ for(unsigned i = k; i >= l; i--) {
+ //assert(i >= 0);
+ double ci = r.back()/b.back();
+ c[i-l] += ci;
+ Poly bb = ci*b;
+ //std::cout << ci <<"*(" << b.shifted(i-l) << ") = "
+ // << bb.shifted(i-l) << " r= " << r << std::endl;
+ r -= bb.shifted(i-l);
+ r.pop_back();
+ }
+ //std::cout << "r= " << r << std::endl;
+ r.normalize();
+ c.normalize();
+
+ return c;
+}
+
+Poly gcd(Poly const &a, Poly const &b, const double /*tol*/) {
+ if(a.size() < b.size())
+ return gcd(b, a);
+ if(b.size() <= 0)
+ return a;
+ if(b.size() == 1)
+ return a;
+ Poly r;
+ divide(a, b, r);
+ return gcd(b, r);
+}
+
+
+
+
+std::vector<Coord> solve_quadratic(Coord a, Coord b, Coord c)
+{
+ std::vector<Coord> result;
+
+ if (a == 0) {
+ // linear equation
+ if (b == 0) return result;
+ result.push_back(-c/b);
+ return result;
+ }
+
+ Coord delta = b*b - 4*a*c;
+
+ if (delta == 0) {
+ // one root
+ result.push_back(-b / (2*a));
+ } else if (delta > 0) {
+ // two roots
+ Coord delta_sqrt = sqrt(delta);
+
+ // Use different formulas depending on sign of b to preserve
+ // numerical stability. See e.g.:
+ // http://people.csail.mit.edu/bkph/articles/Quadratics.pdf
+ int sign = b >= 0 ? 1 : -1;
+ Coord t = -0.5 * (b + sign * delta_sqrt);
+ result.push_back(t / a);
+ result.push_back(c / t);
+ }
+ // no roots otherwise
+
+ std::sort(result.begin(), result.end());
+ return result;
+}
+
+
+std::vector<Coord> solve_cubic(Coord a, Coord b, Coord c, Coord d)
+{
+ // based on:
+ // http://mathworld.wolfram.com/CubicFormula.html
+
+ if (a == 0) {
+ return solve_quadratic(b, c, d);
+ }
+ if (d == 0) {
+ // divide by x
+ std::vector<Coord> result = solve_quadratic(a, b, c);
+ result.push_back(0);
+ std::sort(result.begin(), result.end());
+ return result;
+ }
+
+ std::vector<Coord> result;
+
+ // 1. divide everything by a to bring to canonical form
+ b /= a;
+ c /= a;
+ d /= a;
+
+ // 2. eliminate x^2 term: x^3 + 3Qx - 2R = 0
+ Coord Q = (3*c - b*b) / 9;
+ Coord R = (-27 * d + b * (9*c - 2*b*b)) / 54;
+
+ // 3. compute polynomial discriminant
+ Coord D = Q*Q*Q + R*R;
+ Coord term1 = b/3;
+
+ if (D > 0) {
+ // only one real root
+ Coord S = cbrt(R + sqrt(D));
+ Coord T = cbrt(R - sqrt(D));
+ result.push_back(-b/3 + S + T);
+ } else if (D == 0) {
+ // 3 real roots, 2 of which are equal
+ Coord rroot = cbrt(R);
+ result.reserve(3);
+ result.push_back(-term1 + 2*rroot);
+ result.push_back(-term1 - rroot);
+ result.push_back(-term1 - rroot);
+ } else {
+ // 3 distinct real roots
+ assert(Q < 0);
+ Coord theta = acos(R / sqrt(-Q*Q*Q));
+ Coord rroot = 2 * sqrt(-Q);
+ result.reserve(3);
+ result.push_back(-term1 + rroot * cos(theta / 3));
+ result.push_back(-term1 + rroot * cos((theta + 2*M_PI) / 3));
+ result.push_back(-term1 + rroot * cos((theta + 4*M_PI) / 3));
+ }
+
+ std::sort(result.begin(), result.end());
+ return result;
+}
+
+
+/*Poly divide_out_root(Poly const & p, double x) {
+ assert(1);
+ }*/
+
+} //namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/rect.cpp b/src/3rdparty/2geom/src/2geom/rect.cpp
new file mode 100644
index 0000000..60dcc87
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/rect.cpp
@@ -0,0 +1,187 @@
+/* Axis-aligned rectangle
+ *
+ * Authors:
+ * Michael Sloan <mgsloan@gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ * Copyright 2007-2011 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/rect.h>
+#include <2geom/transforms.h>
+
+namespace Geom {
+
+Point align_factors(Align g) {
+ Point p;
+ switch (g) {
+ case ALIGN_XMIN_YMIN:
+ p[X] = 0.0;
+ p[Y] = 0.0;
+ break;
+ case ALIGN_XMID_YMIN:
+ p[X] = 0.5;
+ p[Y] = 0.0;
+ break;
+ case ALIGN_XMAX_YMIN:
+ p[X] = 1.0;
+ p[Y] = 0.0;
+ break;
+ case ALIGN_XMIN_YMID:
+ p[X] = 0.0;
+ p[Y] = 0.5;
+ break;
+ case ALIGN_XMID_YMID:
+ p[X] = 0.5;
+ p[Y] = 0.5;
+ break;
+ case ALIGN_XMAX_YMID:
+ p[X] = 1.0;
+ p[Y] = 0.5;
+ break;
+ case ALIGN_XMIN_YMAX:
+ p[X] = 0.0;
+ p[Y] = 1.0;
+ break;
+ case ALIGN_XMID_YMAX:
+ p[X] = 0.5;
+ p[Y] = 1.0;
+ break;
+ case ALIGN_XMAX_YMAX:
+ p[X] = 1.0;
+ p[Y] = 1.0;
+ break;
+ default:
+ break;
+ }
+ return p;
+}
+
+
+/** @brief Transform the rectangle by an affine.
+ * The result of the transformation might not be axis-aligned. The return value
+ * of this operation will be the smallest axis-aligned rectangle containing
+ * all points of the true result. */
+Rect &Rect::operator*=(Affine const &m) {
+ Point pts[4];
+ for (unsigned i=0; i<4; ++i) pts[i] = corner(i) * m;
+ Coord minx = std::min(std::min(pts[0][X], pts[1][X]), std::min(pts[2][X], pts[3][X]));
+ Coord miny = std::min(std::min(pts[0][Y], pts[1][Y]), std::min(pts[2][Y], pts[3][Y]));
+ Coord maxx = std::max(std::max(pts[0][X], pts[1][X]), std::max(pts[2][X], pts[3][X]));
+ Coord maxy = std::max(std::max(pts[0][Y], pts[1][Y]), std::max(pts[2][Y], pts[3][Y]));
+ f[X].setMin(minx); f[X].setMax(maxx);
+ f[Y].setMin(miny); f[Y].setMax(maxy);
+ return *this;
+}
+
+Affine Rect::transformTo(Rect const &viewport, Aspect const &aspect) const
+{
+ // 1. translate viewbox to origin
+ Geom::Affine total = Translate(-min());
+
+ // 2. compute scale
+ Geom::Point vdims = viewport.dimensions();
+ Geom::Point dims = dimensions();
+ Geom::Scale scale(vdims[X] / dims[X], vdims[Y] / dims[Y]);
+
+ if (aspect.align == ALIGN_NONE) {
+ // apply non-uniform scale
+ total *= scale * Translate(viewport.min());
+ } else {
+ double uscale = 0;
+ if (aspect.expansion == EXPANSION_MEET) {
+ uscale = std::min(scale[X], scale[Y]);
+ } else {
+ uscale = std::max(scale[X], scale[Y]);
+ }
+ scale = Scale(uscale);
+
+ // compute offset for align
+ Geom::Point offset = vdims - dims * scale;
+ offset *= Scale(align_factors(aspect.align));
+ total *= scale * Translate(viewport.min() + offset);
+ }
+
+ return total;
+}
+
+Coord distanceSq(Point const &p, Rect const &rect)
+{
+ double dx = 0, dy = 0;
+ if ( p[X] < rect.left() ) {
+ dx = p[X] - rect.left();
+ } else if ( p[X] > rect.right() ) {
+ dx = rect.right() - p[X];
+ }
+ if (p[Y] < rect.top() ) {
+ dy = rect.top() - p[Y];
+ } else if ( p[Y] > rect.bottom() ) {
+ dy = p[Y] - rect.bottom();
+ }
+ return dx*dx+dy*dy;
+}
+
+/** @brief Returns the smallest distance between p and rect.
+ * @relates Rect */
+Coord distance(Point const &p, Rect const &rect)
+{
+ // copy of distanceSq, because we need to use hypot()
+ double dx = 0, dy = 0;
+ if ( p[X] < rect.left() ) {
+ dx = p[X] - rect.left();
+ } else if ( p[X] > rect.right() ) {
+ dx = rect.right() - p[X];
+ }
+ if (p[Y] < rect.top() ) {
+ dy = rect.top() - p[Y];
+ } else if ( p[Y] > rect.bottom() ) {
+ dy = p[Y] - rect.bottom();
+ }
+ return hypot(dx, dy);
+}
+
+Coord distanceSq(Point const &p, OptRect const &rect)
+{
+ if (!rect) return std::numeric_limits<Coord>::max();
+ return distanceSq(p, *rect);
+}
+Coord distance(Point const &p, OptRect const &rect)
+{
+ if (!rect) return std::numeric_limits<Coord>::max();
+ return distance(p, *rect);
+}
+
+} // namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/recursive-bezier-intersection.cpp b/src/3rdparty/2geom/src/2geom/recursive-bezier-intersection.cpp
new file mode 100644
index 0000000..20b07d9
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/recursive-bezier-intersection.cpp
@@ -0,0 +1,476 @@
+
+
+
+#include <2geom/basic-intersection.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/exception.h>
+
+
+#include <gsl/gsl_vector.h>
+#include <gsl/gsl_multiroots.h>
+
+
+unsigned intersect_steps = 0;
+
+using std::vector;
+
+namespace Geom {
+
+class OldBezier {
+public:
+ std::vector<Geom::Point> p;
+ OldBezier() {
+ }
+ void split(double t, OldBezier &a, OldBezier &b) const;
+ Point operator()(double t) const;
+
+ ~OldBezier() {}
+
+ void bounds(double &minax, double &maxax,
+ double &minay, double &maxay) {
+ // Compute bounding box for a
+ minax = p[0][X]; // These are the most likely to be extremal
+ maxax = p.back()[X];
+ if( minax > maxax )
+ std::swap(minax, maxax);
+ for(unsigned i = 1; i < p.size()-1; i++) {
+ if( p[i][X] < minax )
+ minax = p[i][X];
+ else if( p[i][X] > maxax )
+ maxax = p[i][X];
+ }
+
+ minay = p[0][Y]; // These are the most likely to be extremal
+ maxay = p.back()[Y];
+ if( minay > maxay )
+ std::swap(minay, maxay);
+ for(unsigned i = 1; i < p.size()-1; i++) {
+ if( p[i][Y] < minay )
+ minay = p[i][Y];
+ else if( p[i][Y] > maxay )
+ maxay = p[i][Y];
+ }
+
+ }
+
+};
+
+static void
+find_intersections_bezier_recursive(std::vector<std::pair<double, double> > & xs,
+ OldBezier a,
+ OldBezier b);
+
+void
+find_intersections_bezier_recursive( std::vector<std::pair<double, double> > &xs,
+ vector<Geom::Point> const & A,
+ vector<Geom::Point> const & B,
+ double /*precision*/) {
+ OldBezier a, b;
+ a.p = A;
+ b.p = B;
+ return find_intersections_bezier_recursive(xs, a,b);
+}
+
+
+/*
+ * split the curve at the midpoint, returning an array with the two parts
+ * Temporary storage is minimized by using part of the storage for the result
+ * to hold an intermediate value until it is no longer needed.
+ */
+void OldBezier::split(double t, OldBezier &left, OldBezier &right) const {
+ const unsigned sz = p.size();
+ //Geom::Point Vtemp[sz][sz];
+ std::vector< std::vector< Geom::Point > > Vtemp;
+ for (size_t i = 0; i < sz; ++i )
+ Vtemp[i].reserve(sz);
+
+ /* Copy control points */
+ std::copy(p.begin(), p.end(), Vtemp[0].begin());
+
+ /* Triangle computation */
+ for (unsigned i = 1; i < sz; i++) {
+ for (unsigned j = 0; j < sz - i; j++) {
+ Vtemp[i][j] = lerp(t, Vtemp[i-1][j], Vtemp[i-1][j+1]);
+ }
+ }
+
+ left.p.resize(sz);
+ right.p.resize(sz);
+ for (unsigned j = 0; j < sz; j++)
+ left.p[j] = Vtemp[j][0];
+ for (unsigned j = 0; j < sz; j++)
+ right.p[j] = Vtemp[sz-1-j][j];
+}
+
+#if 0
+/*
+ * split the curve at the midpoint, returning an array with the two parts
+ * Temporary storage is minimized by using part of the storage for the result
+ * to hold an intermediate value until it is no longer needed.
+ */
+Point OldBezier::operator()(double t) const {
+ const unsigned sz = p.size();
+ Geom::Point Vtemp[sz][sz];
+
+ /* Copy control points */
+ std::copy(p.begin(), p.end(), Vtemp[0]);
+
+ /* Triangle computation */
+ for (unsigned i = 1; i < sz; i++) {
+ for (unsigned j = 0; j < sz - i; j++) {
+ Vtemp[i][j] = lerp(t, Vtemp[i-1][j], Vtemp[i-1][j+1]);
+ }
+ }
+ return Vtemp[sz-1][0];
+}
+#endif
+
+// suggested by Sederberg.
+Point OldBezier::operator()(double const t) const {
+ size_t const n = p.size()-1;
+ Point r;
+ for(int dim = 0; dim < 2; dim++) {
+ double const u = 1.0 - t;
+ double bc = 1;
+ double tn = 1;
+ double tmp = p[0][dim]*u;
+ for(size_t i=1; i<n; i++){
+ tn = tn*t;
+ bc = bc*(n-i+1)/i;
+ tmp = (tmp + tn*bc*p[i][dim])*u;
+ }
+ r[dim] = (tmp + tn*t*p[n][dim]);
+ }
+ return r;
+}
+
+
+/*
+ * Test the bounding boxes of two OldBezier curves for interference.
+ * Several observations:
+ * First, it is cheaper to compute the bounding box of the second curve
+ * and test its bounding box for interference than to use a more direct
+ * approach of comparing all control points of the second curve with
+ * the various edges of the bounding box of the first curve to test
+ * for interference.
+ * Second, after a few subdivisions it is highly probable that two corners
+ * of the bounding box of a given Bezier curve are the first and last
+ * control point. Once this happens once, it happens for all subsequent
+ * subcurves. It might be worth putting in a test and then short-circuit
+ * code for further subdivision levels.
+ * Third, in the final comparison (the interference test) the comparisons
+ * should both permit equality. We want to find intersections even if they
+ * occur at the ends of segments.
+ * Finally, there are tighter bounding boxes that can be derived. It isn't
+ * clear whether the higher probability of rejection (and hence fewer
+ * subdivisions and tests) is worth the extra work.
+ */
+
+bool intersect_BB( OldBezier a, OldBezier b ) {
+ double minax, maxax, minay, maxay;
+ a.bounds(minax, maxax, minay, maxay);
+ double minbx, maxbx, minby, maxby;
+ b.bounds(minbx, maxbx, minby, maxby);
+ // Test bounding box of b against bounding box of a
+ // Not >= : need boundary case
+ return !( ( minax > maxbx ) || ( minay > maxby )
+ || ( minbx > maxax ) || ( minby > maxay ) );
+}
+
+/*
+ * Recursively intersect two curves keeping track of their real parameters
+ * and depths of intersection.
+ * The results are returned in a 2-D array of doubles indicating the parameters
+ * for which intersections are found. The parameters are in the order the
+ * intersections were found, which is probably not in sorted order.
+ * When an intersection is found, the parameter value for each of the two
+ * is stored in the index elements array, and the index is incremented.
+ *
+ * If either of the curves has subdivisions left before it is straight
+ * (depth > 0)
+ * that curve (possibly both) is (are) subdivided at its (their) midpoint(s).
+ * the depth(s) is (are) decremented, and the parameter value(s) corresponding
+ * to the midpoints(s) is (are) computed.
+ * Then each of the subcurves of one curve is intersected with each of the
+ * subcurves of the other curve, first by testing the bounding boxes for
+ * interference. If there is any bounding box interference, the corresponding
+ * subcurves are recursively intersected.
+ *
+ * If neither curve has subdivisions left, the line segments from the first
+ * to last control point of each segment are intersected. (Actually the
+ * only the parameter value corresponding to the intersection point is found).
+ *
+ * The apriori flatness test is probably more efficient than testing at each
+ * level of recursion, although a test after three or four levels would
+ * probably be worthwhile, since many curves become flat faster than their
+ * asymptotic rate for the first few levels of recursion.
+ *
+ * The bounding box test fails much more frequently than it succeeds, providing
+ * substantial pruning of the search space.
+ *
+ * Each (sub)curve is subdivided only once, hence it is not possible that for
+ * one final line intersection test the subdivision was at one level, while
+ * for another final line intersection test the subdivision (of the same curve)
+ * was at another. Since the line segments share endpoints, the intersection
+ * is robust: a near-tangential intersection will yield zero or two
+ * intersections.
+ */
+void recursively_intersect( OldBezier a, double t0, double t1, int deptha,
+ OldBezier b, double u0, double u1, int depthb,
+ std::vector<std::pair<double, double> > &parameters)
+{
+ intersect_steps ++;
+ //std::cout << deptha << std::endl;
+ if( deptha > 0 )
+ {
+ OldBezier A[2];
+ a.split(0.5, A[0], A[1]);
+ double tmid = (t0+t1)*0.5;
+ deptha--;
+ if( depthb > 0 )
+ {
+ OldBezier B[2];
+ b.split(0.5, B[0], B[1]);
+ double umid = (u0+u1)*0.5;
+ depthb--;
+ if( intersect_BB( A[0], B[0] ) )
+ recursively_intersect( A[0], t0, tmid, deptha,
+ B[0], u0, umid, depthb,
+ parameters );
+ if( intersect_BB( A[1], B[0] ) )
+ recursively_intersect( A[1], tmid, t1, deptha,
+ B[0], u0, umid, depthb,
+ parameters );
+ if( intersect_BB( A[0], B[1] ) )
+ recursively_intersect( A[0], t0, tmid, deptha,
+ B[1], umid, u1, depthb,
+ parameters );
+ if( intersect_BB( A[1], B[1] ) )
+ recursively_intersect( A[1], tmid, t1, deptha,
+ B[1], umid, u1, depthb,
+ parameters );
+ }
+ else
+ {
+ if( intersect_BB( A[0], b ) )
+ recursively_intersect( A[0], t0, tmid, deptha,
+ b, u0, u1, depthb,
+ parameters );
+ if( intersect_BB( A[1], b ) )
+ recursively_intersect( A[1], tmid, t1, deptha,
+ b, u0, u1, depthb,
+ parameters );
+ }
+ }
+ else
+ if( depthb > 0 )
+ {
+ OldBezier B[2];
+ b.split(0.5, B[0], B[1]);
+ double umid = (u0 + u1)*0.5;
+ depthb--;
+ if( intersect_BB( a, B[0] ) )
+ recursively_intersect( a, t0, t1, deptha,
+ B[0], u0, umid, depthb,
+ parameters );
+ if( intersect_BB( a, B[1] ) )
+ recursively_intersect( a, t0, t1, deptha,
+ B[0], umid, u1, depthb,
+ parameters );
+ }
+ else // Both segments are fully subdivided; now do line segments
+ {
+ double xlk = a.p.back()[X] - a.p[0][X];
+ double ylk = a.p.back()[Y] - a.p[0][Y];
+ double xnm = b.p.back()[X] - b.p[0][X];
+ double ynm = b.p.back()[Y] - b.p[0][Y];
+ double xmk = b.p[0][X] - a.p[0][X];
+ double ymk = b.p[0][Y] - a.p[0][Y];
+ double det = xnm * ylk - ynm * xlk;
+ if( 1.0 + det == 1.0 )
+ return;
+ else
+ {
+ double detinv = 1.0 / det;
+ double s = ( xnm * ymk - ynm *xmk ) * detinv;
+ double t = ( xlk * ymk - ylk * xmk ) * detinv;
+ if( ( s < 0.0 ) || ( s > 1.0 ) || ( t < 0.0 ) || ( t > 1.0 ) )
+ return;
+ parameters.emplace_back(t0 + s * ( t1 - t0 ),
+ u0 + t * ( u1 - u0 ));
+ }
+ }
+}
+
+inline double log4( double x ) { return log(x)/log(4.); }
+
+/*
+ * Wang's theorem is used to estimate the level of subdivision required,
+ * but only if the bounding boxes interfere at the top level.
+ * Assuming there is a possible intersection, recursively_intersect is
+ * used to find all the parameters corresponding to intersection points.
+ * these are then sorted and returned in an array.
+ */
+
+double Lmax(Point p) {
+ return std::max(fabs(p[X]), fabs(p[Y]));
+}
+
+
+unsigned wangs_theorem(OldBezier /*a*/) {
+ return 6; // seems a good approximation!
+
+ /*
+ const double INV_EPS = (1L<<14); // The value of 1.0 / (1L<<14) is enough for most applications
+
+ double la1 = Lmax( ( a.p[2] - a.p[1] ) - (a.p[1] - a.p[0]) );
+ double la2 = Lmax( ( a.p[3] - a.p[2] ) - (a.p[2] - a.p[1]) );
+ double l0 = std::max(la1, la2);
+ unsigned ra;
+ if( l0 * 0.75 * M_SQRT2 + 1.0 == 1.0 )
+ ra = 0;
+ else
+ ra = (unsigned)ceil( log4( M_SQRT2 * 6.0 / 8.0 * INV_EPS * l0 ) );
+ //std::cout << ra << std::endl;
+ return ra;*/
+}
+
+struct rparams
+{
+ OldBezier &A;
+ OldBezier &B;
+};
+
+/*static int
+intersect_polish_f (const gsl_vector * x, void *params,
+ gsl_vector * f)
+{
+ const double x0 = gsl_vector_get (x, 0);
+ const double x1 = gsl_vector_get (x, 1);
+
+ Geom::Point dx = ((struct rparams *) params)->A(x0) -
+ ((struct rparams *) params)->B(x1);
+
+ gsl_vector_set (f, 0, dx[0]);
+ gsl_vector_set (f, 1, dx[1]);
+
+ return GSL_SUCCESS;
+}*/
+
+/*union dbl_64{
+ long long i64;
+ double d64;
+};*/
+
+/*static double EpsilonBy(double value, int eps)
+{
+ dbl_64 s;
+ s.d64 = value;
+ s.i64 += eps;
+ return s.d64;
+}*/
+
+/*
+static void intersect_polish_root (OldBezier &A, double &s,
+ OldBezier &B, double &t) {
+ const gsl_multiroot_fsolver_type *T;
+ gsl_multiroot_fsolver *sol;
+
+ int status;
+ size_t iter = 0;
+
+ const size_t n = 2;
+ struct rparams p = {A, B};
+ gsl_multiroot_function f = {&intersect_polish_f, n, &p};
+
+ double x_init[2] = {s, t};
+ gsl_vector *x = gsl_vector_alloc (n);
+
+ gsl_vector_set (x, 0, x_init[0]);
+ gsl_vector_set (x, 1, x_init[1]);
+
+ T = gsl_multiroot_fsolver_hybrids;
+ sol = gsl_multiroot_fsolver_alloc (T, 2);
+ gsl_multiroot_fsolver_set (sol, &f, x);
+
+ do
+ {
+ iter++;
+ status = gsl_multiroot_fsolver_iterate (sol);
+
+ if (status) // check if solver is stuck
+ break;
+
+ status =
+ gsl_multiroot_test_residual (sol->f, 1e-12);
+ }
+ while (status == GSL_CONTINUE && iter < 1000);
+
+ s = gsl_vector_get (sol->x, 0);
+ t = gsl_vector_get (sol->x, 1);
+
+ gsl_multiroot_fsolver_free (sol);
+ gsl_vector_free (x);
+
+ // This code does a neighbourhood search for minor improvements.
+ double best_v = L1(A(s) - B(t));
+ //std::cout << "------\n" << best_v << std::endl;
+ Point best(s,t);
+ while (true) {
+ Point trial = best;
+ double trial_v = best_v;
+ for(int nsi = -1; nsi < 2; nsi++) {
+ for(int nti = -1; nti < 2; nti++) {
+ Point n(EpsilonBy(best[0], nsi),
+ EpsilonBy(best[1], nti));
+ double c = L1(A(n[0]) - B(n[1]));
+ //std::cout << c << "; ";
+ if (c < trial_v) {
+ trial = n;
+ trial_v = c;
+ }
+ }
+ }
+ if(trial == best) {
+ //std::cout << "\n" << s << " -> " << s - best[0] << std::endl;
+ //std::cout << t << " -> " << t - best[1] << std::endl;
+ //std::cout << best_v << std::endl;
+ s = best[0];
+ t = best[1];
+ return;
+ } else {
+ best = trial;
+ best_v = trial_v;
+ }
+ }
+}*/
+
+
+void find_intersections_bezier_recursive( std::vector<std::pair<double, double> > &xs,
+ OldBezier a, OldBezier b)
+{
+ if( intersect_BB( a, b ) )
+ {
+ recursively_intersect( a, 0., 1., wangs_theorem(a),
+ b, 0., 1., wangs_theorem(b),
+ xs);
+ }
+ /*for(unsigned i = 0; i < xs.size(); i++)
+ intersect_polish_root(a, xs[i].first,
+ b, xs[i].second);*/
+ std::sort(xs.begin(), xs.end());
+}
+
+
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/sbasis-2d.cpp b/src/3rdparty/2geom/src/2geom/sbasis-2d.cpp
new file mode 100644
index 0000000..53b09cd
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/sbasis-2d.cpp
@@ -0,0 +1,202 @@
+#include <2geom/sbasis-2d.h>
+#include <2geom/sbasis-geometric.h>
+
+namespace Geom{
+
+SBasis extract_u(SBasis2d const &a, double u) {
+ SBasis sb(a.vs, Linear());
+ double s = u*(1-u);
+
+ for(unsigned vi = 0; vi < a.vs; vi++) {
+ double sk = 1;
+ Linear bo(0,0);
+ for(unsigned ui = 0; ui < a.us; ui++) {
+ bo += (extract_u(a.index(ui, vi), u))*sk;
+ sk *= s;
+ }
+ sb[vi] = bo;
+ }
+
+ return sb;
+}
+
+SBasis extract_v(SBasis2d const &a, double v) {
+ SBasis sb(a.us, Linear());
+ double s = v*(1-v);
+
+ for(unsigned ui = 0; ui < a.us; ui++) {
+ double sk = 1;
+ Linear bo(0,0);
+ for(unsigned vi = 0; vi < a.vs; vi++) {
+ bo += (extract_v(a.index(ui, vi), v))*sk;
+ sk *= s;
+ }
+ sb[ui] = bo;
+ }
+
+ return sb;
+}
+
+SBasis compose(Linear2d const &a, D2<SBasis> const &p) {
+ D2<SBasis> omp(-p[X] + 1, -p[Y] + 1);
+ return multiply(omp[0], omp[1])*a[0] +
+ multiply(p[0], omp[1])*a[1] +
+ multiply(omp[0], p[1])*a[2] +
+ multiply(p[0], p[1])*a[3];
+}
+
+SBasis
+compose(SBasis2d const &fg, D2<SBasis> const &p) {
+ SBasis B;
+ SBasis s[2];
+ SBasis ss[2];
+ for(unsigned dim = 0; dim < 2; dim++)
+ s[dim] = p[dim]*(Linear(1) - p[dim]);
+ ss[1] = Linear(1);
+ for(unsigned vi = 0; vi < fg.vs; vi++) {
+ ss[0] = ss[1];
+ for(unsigned ui = 0; ui < fg.us; ui++) {
+ unsigned i = ui + vi*fg.us;
+ B += ss[0]*compose(fg[i], p);
+ ss[0] *= s[0];
+ }
+ ss[1] *= s[1];
+ }
+ return B;
+}
+
+D2<SBasis>
+compose_each(D2<SBasis2d> const &fg, D2<SBasis> const &p) {
+ return D2<SBasis>(compose(fg[X], p), compose(fg[Y], p));
+}
+
+SBasis2d partial_derivative(SBasis2d const &f, int dim) {
+ SBasis2d result;
+ for(unsigned i = 0; i < f.size(); i++) {
+ result.push_back(Linear2d(0,0,0,0));
+ }
+ result.us = f.us;
+ result.vs = f.vs;
+
+ for(unsigned i = 0; i < f.us; i++) {
+ for(unsigned j = 0; j < f.vs; j++) {
+ Linear2d lin = f.index(i,j);
+ Linear2d dlin(lin[1+dim]-lin[0], lin[1+2*dim]-lin[dim], lin[3-dim]-lin[2*(1-dim)], lin[3]-lin[2-dim]);
+ result[i+j*result.us] += dlin;
+ unsigned di = dim?j:i;
+ if (di>=1){
+ float motpi = dim?-1:1;
+ Linear2d ds_lin_low( lin[0], -motpi*lin[1], motpi*lin[2], -lin[3] );
+ result[(i+dim-1)+(j-dim)*result.us] += di*ds_lin_low;
+
+ Linear2d ds_lin_hi( lin[1+dim]-lin[0], lin[1+2*dim]-lin[dim], lin[3]-lin[2-dim], lin[3-dim]-lin[2-dim] );
+ result[i+j*result.us] += di*ds_lin_hi;
+ }
+ }
+ }
+ return result;
+}
+
+/**
+ * Finds a path which traces the 0 contour of f, traversing from A to B as a single d2<sbasis>.
+ * degmax specifies the degree (degree = 2*degmax-1, so a degmax of 2 generates a cubic fit).
+ * The algorithm is based on dividing out derivatives at each end point and does not use the curvature for fitting.
+ * It is less accurate than sb2d_cubic_solve, although this may be fixed in the future.
+ */
+D2<SBasis>
+sb2dsolve(SBasis2d const &f, Geom::Point const &A, Geom::Point const &B, unsigned degmax){
+ //g_warning("check f(A)= %f = f(B) = %f =0!", f.apply(A[X],A[Y]), f.apply(B[X],B[Y]));
+
+ SBasis2d dfdu = partial_derivative(f, 0);
+ SBasis2d dfdv = partial_derivative(f, 1);
+ Geom::Point dfA(dfdu.apply(A[X],A[Y]),dfdv.apply(A[X],A[Y]));
+ Geom::Point dfB(dfdu.apply(B[X],B[Y]),dfdv.apply(B[X],B[Y]));
+ Geom::Point nA = dfA/(dfA[X]*dfA[X]+dfA[Y]*dfA[Y]);
+ Geom::Point nB = dfB/(dfB[X]*dfB[X]+dfB[Y]*dfB[Y]);
+
+ D2<SBasis>result(SBasis(degmax, Linear()), SBasis(degmax, Linear()));
+ double fact_k=1;
+ double sign = 1.;
+ for(int dim = 0; dim < 2; dim++)
+ result[dim][0] = Linear(A[dim],B[dim]);
+ for(unsigned k=1; k<degmax; k++){
+ // these two lines make the solutions worse!
+ //fact_k *= k;
+ //sign = -sign;
+ SBasis f_on_curve = compose(f,result);
+ Linear reste = f_on_curve[k];
+ double ax = -reste[0]/fact_k*nA[X];
+ double ay = -reste[0]/fact_k*nA[Y];
+ double bx = -sign*reste[1]/fact_k*nB[X];
+ double by = -sign*reste[1]/fact_k*nB[Y];
+
+ result[X][k] = Linear(ax,bx);
+ result[Y][k] = Linear(ay,by);
+ //sign *= 3;
+ }
+ return result;
+}
+
+/**
+ * Finds a path which traces the 0 contour of f, traversing from A to B as a single cubic d2<sbasis>.
+ * The algorithm is based on matching direction and curvature at each end point.
+ */
+//TODO: handle the case when B is "behind" A for the natural orientation of the level set.
+//TODO: more generally, there might be up to 4 solutions. Choose the best one!
+D2<SBasis>
+sb2d_cubic_solve(SBasis2d const &f, Geom::Point const &A, Geom::Point const &B){
+ D2<SBasis>result;//(Linear(A[X],B[X]),Linear(A[Y],B[Y]));
+ //g_warning("check 0 = %f = %f!", f.apply(A[X],A[Y]), f.apply(B[X],B[Y]));
+
+ SBasis2d f_u = partial_derivative(f , 0);
+ SBasis2d f_v = partial_derivative(f , 1);
+ SBasis2d f_uu = partial_derivative(f_u, 0);
+ SBasis2d f_uv = partial_derivative(f_v, 0);
+ SBasis2d f_vv = partial_derivative(f_v, 1);
+
+ Geom::Point dfA(f_u.apply(A[X],A[Y]),f_v.apply(A[X],A[Y]));
+ Geom::Point dfB(f_u.apply(B[X],B[Y]),f_v.apply(B[X],B[Y]));
+
+ Geom::Point V0 = rot90(dfA);
+ Geom::Point V1 = rot90(dfB);
+
+ double D2fVV0 = f_uu.apply(A[X],A[Y])*V0[X]*V0[X]+
+ 2*f_uv.apply(A[X],A[Y])*V0[X]*V0[Y]+
+ f_vv.apply(A[X],A[Y])*V0[Y]*V0[Y];
+ double D2fVV1 = f_uu.apply(B[X],B[Y])*V1[X]*V1[X]+
+ 2*f_uv.apply(B[X],B[Y])*V1[X]*V1[Y]+
+ f_vv.apply(B[X],B[Y])*V1[Y]*V1[Y];
+
+ std::vector<D2<SBasis> > candidates = cubics_fitting_curvature(A,B,V0,V1,D2fVV0,D2fVV1);
+ if (candidates.empty()) {
+ return D2<SBasis>(SBasis(Linear(A[X],B[X])), SBasis(Linear(A[Y],B[Y])));
+ }
+ //TODO: I'm sure std algorithm could do that for me...
+ double error = -1;
+ unsigned best = 0;
+ for (unsigned i=0; i<candidates.size(); i++){
+ Interval bounds = *bounds_fast(compose(f,candidates[i]));
+ double new_error = (fabs(bounds.max())>fabs(bounds.min()) ? fabs(bounds.max()) : fabs(bounds.min()) );
+ if ( new_error < error || error < 0 ){
+ error = new_error;
+ best = i;
+ }
+ }
+ return candidates[best];
+}
+
+
+
+
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/sbasis-geometric.cpp b/src/3rdparty/2geom/src/2geom/sbasis-geometric.cpp
new file mode 100644
index 0000000..7039c6d
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/sbasis-geometric.cpp
@@ -0,0 +1,790 @@
+/** Geometric operators on D2<SBasis> (1D->2D).
+ * Copyright 2012 JBC Engelen
+ * Copyright 2007 JF Barraud
+ * Copyright 2007 N Hurst
+ *
+ * The functions defined in this header related to 2d geometric operations such as arc length,
+ * unit_vector, curvature, and centroid. Most are built on top of unit_vector, which takes an
+ * arbitrary D2 and returns a D2 with unit length with the same direction.
+ *
+ * Todo/think about:
+ * arclength D2 -> sbasis (giving arclength function)
+ * does uniform_speed return natural parameterisation?
+ * integrate sb2d code from normal-bundle
+ * angle(md<2>) -> sbasis (gives angle from vector - discontinuous?)
+ * osculating circle center?
+ *
+ **/
+
+#include <2geom/sbasis-geometric.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-math.h>
+#include <2geom/sbasis-geometric.h>
+
+//namespace Geom{
+using namespace Geom;
+using namespace std;
+
+//Some utils first.
+//TODO: remove this!!
+/**
+ * Return a list of doubles that appear in both a and b to within error tol
+ * a, b, vector of double
+ * tol tolerance
+ */
+static vector<double>
+vect_intersect(vector<double> const &a, vector<double> const &b, double tol=0.){
+ vector<double> inter;
+ unsigned i=0,j=0;
+ while ( i<a.size() && j<b.size() ){
+ if (fabs(a[i]-b[j])<tol){
+ inter.push_back(a[i]);
+ i+=1;
+ j+=1;
+ }else if (a[i]<b[j]){
+ i+=1;
+ }else if (a[i]>b[j]){
+ j+=1;
+ }
+ }
+ return inter;
+}
+
+//------------------------------------------------------------------------------
+static SBasis divide_by_sk(SBasis const &a, int k) {
+ if ( k>=(int)a.size()){
+ //make sure a is 0?
+ return SBasis();
+ }
+ if(k < 0) return shift(a,-k);
+ SBasis c;
+ c.insert(c.begin(), a.begin()+k, a.end());
+ return c;
+}
+
+static SBasis divide_by_t0k(SBasis const &a, int k) {
+ if(k < 0) {
+ SBasis c = Linear(0,1);
+ for (int i=2; i<=-k; i++){
+ c*=c;
+ }
+ c*=a;
+ return(c);
+ }else{
+ SBasis c = Linear(1,0);
+ for (int i=2; i<=k; i++){
+ c*=c;
+ }
+ c*=a;
+ return(divide_by_sk(c,k));
+ }
+}
+
+static SBasis divide_by_t1k(SBasis const &a, int k) {
+ if(k < 0) {
+ SBasis c = Linear(1,0);
+ for (int i=2; i<=-k; i++){
+ c*=c;
+ }
+ c*=a;
+ return(c);
+ }else{
+ SBasis c = Linear(0,1);
+ for (int i=2; i<=k; i++){
+ c*=c;
+ }
+ c*=a;
+ return(divide_by_sk(c,k));
+ }
+}
+
+static D2<SBasis> RescaleForNonVanishingEnds(D2<SBasis> const &MM, double ZERO=1.e-4){
+ D2<SBasis> M = MM;
+ //TODO: divide by all the s at once!!!
+ while ((M[0].size()>1||M[1].size()>1) &&
+ fabs(M[0].at0())<ZERO &&
+ fabs(M[1].at0())<ZERO &&
+ fabs(M[0].at1())<ZERO &&
+ fabs(M[1].at1())<ZERO){
+ M[0] = divide_by_sk(M[0],1);
+ M[1] = divide_by_sk(M[1],1);
+ }
+ while ((M[0].size()>1||M[1].size()>1) &&
+ fabs(M[0].at0())<ZERO && fabs(M[1].at0())<ZERO){
+ M[0] = divide_by_t0k(M[0],1);
+ M[1] = divide_by_t0k(M[1],1);
+ }
+ while ((M[0].size()>1||M[1].size()>1) &&
+ fabs(M[0].at1())<ZERO && fabs(M[1].at1())<ZERO){
+ M[0] = divide_by_t1k(M[0],1);
+ M[1] = divide_by_t1k(M[1],1);
+ }
+ return M;
+}
+
+/*static D2<SBasis> RescaleForNonVanishing(D2<SBasis> const &MM, double ZERO=1.e-4){
+ std::vector<double> levels;
+ levels.push_back(-ZERO);
+ levels.push_back(ZERO);
+ //std::vector<std::vector<double> > mr = multi_roots(MM, levels);
+ }*/
+
+
+//=================================================================
+//TODO: what's this for?!?!
+Piecewise<D2<SBasis> >
+Geom::cutAtRoots(Piecewise<D2<SBasis> > const &M, double ZERO){
+ vector<double> rts;
+ for (unsigned i=0; i<M.size(); i++){
+ vector<double> seg_rts = roots((M.segs[i])[0]);
+ seg_rts = vect_intersect(seg_rts, roots((M.segs[i])[1]), ZERO);
+ Linear mapToDom = Linear(M.cuts[i],M.cuts[i+1]);
+ for (double & seg_rt : seg_rts){
+ seg_rt= mapToDom(seg_rt);
+ }
+ rts.insert(rts.end(),seg_rts.begin(),seg_rts.end());
+ }
+ return partition(M,rts);
+}
+
+/** Return a function which gives the angle of vect at each point.
+ \param vect a piecewise parameteric curve.
+ \param tol the maximum error allowed.
+ \param order the maximum degree to use for approximation
+ \relates Piecewise
+*/
+Piecewise<SBasis>
+Geom::atan2(Piecewise<D2<SBasis> > const &vect, double tol, unsigned order){
+ Piecewise<SBasis> result;
+ Piecewise<D2<SBasis> > v = cutAtRoots(vect,tol);
+ result.cuts.push_back(v.cuts.front());
+ for (unsigned i=0; i<v.size(); i++){
+
+ D2<SBasis> vi = RescaleForNonVanishingEnds(v.segs[i]);
+ SBasis x=vi[0], y=vi[1];
+ Piecewise<SBasis> angle;
+ angle = divide (x*derivative(y)-y*derivative(x), x*x+y*y, tol, order);
+
+ //TODO: I don't understand this - sign.
+ angle = integral(-angle);
+ Point vi0 = vi.at0();
+ angle += -std::atan2(vi0[1],vi0[0]) - angle[0].at0();
+ //TODO: deal with 2*pi jumps form one seg to the other...
+ //TODO: not exact at t=1 because of the integral.
+ //TODO: force continuity?
+
+ angle.setDomain(Interval(v.cuts[i],v.cuts[i+1]));
+ result.concat(angle);
+ }
+ return result;
+}
+/** Return a function which gives the angle of vect at each point.
+ \param vect a piecewise parameteric curve.
+ \param tol the maximum error allowed.
+ \param order the maximum degree to use for approximation
+ \relates Piecewise, D2
+*/
+Piecewise<SBasis>
+Geom::atan2(D2<SBasis> const &vect, double tol, unsigned order){
+ return atan2(Piecewise<D2<SBasis> >(vect),tol,order);
+}
+
+/** tan2 is the pseudo-inverse of atan2. It takes an angle and returns a unit_vector that points in the direction of angle.
+ \param angle a piecewise function of angle wrt t.
+ \param tol the maximum error allowed.
+ \param order the maximum degree to use for approximation
+ \relates D2, SBasis
+*/
+D2<Piecewise<SBasis> >
+Geom::tan2(SBasis const &angle, double tol, unsigned order){
+ return tan2(Piecewise<SBasis>(angle), tol, order);
+}
+
+/** tan2 is the pseudo-inverse of atan2. It takes an angle and returns a unit_vector that points in the direction of angle.
+ \param angle a piecewise function of angle wrt t.
+ \param tol the maximum error allowed.
+ \param order the maximum degree to use for approximation
+ \relates Piecewise, D2
+*/
+D2<Piecewise<SBasis> >
+Geom::tan2(Piecewise<SBasis> const &angle, double tol, unsigned order){
+ return D2<Piecewise<SBasis> >(cos(angle, tol, order), sin(angle, tol, order));
+}
+
+/** Return a Piecewise<D2<SBasis> > which points in the same direction as V_in, but has unit_length.
+ \param V_in the original path.
+ \param tol the maximum error allowed.
+ \param order the maximum degree to use for approximation
+
+unitVector(x,y) is computed as (b,-a) where a and b are solutions of:
+ ax+by=0 (eqn1) and a^2+b^2=1 (eqn2)
+
+ \relates Piecewise, D2
+*/
+Piecewise<D2<SBasis> >
+Geom::unitVector(D2<SBasis> const &V_in, double tol, unsigned order){
+ //TODO: Handle vanishing vectors...
+ // -This approach is numerically bad. Find a stable way to rescale V_in to have non vanishing ends.
+ // -This done, unitVector will have jumps at zeros: fill the gaps with arcs of circles.
+ D2<SBasis> V = RescaleForNonVanishingEnds(V_in);
+
+ if (V[0].isZero(tol) && V[1].isZero(tol))
+ return Piecewise<D2<SBasis> >(D2<SBasis>(Linear(1),SBasis()));
+ SBasis x = V[0], y = V[1];
+ SBasis r_eqn1, r_eqn2;
+
+ Point v0 = unit_vector(V.at0());
+ Point v1 = unit_vector(V.at1());
+ SBasis a = SBasis(order+1, Linear(0.));
+ a[0] = Linear(-v0[1],-v1[1]);
+ SBasis b = SBasis(order+1, Linear(0.));
+ b[0] = Linear( v0[0], v1[0]);
+
+ r_eqn1 = -(a*x+b*y);
+ r_eqn2 = Linear(1.)-(a*a+b*b);
+
+ for (unsigned k=1; k<=order; k++){
+ double r0 = (k<r_eqn1.size())? r_eqn1.at(k).at0() : 0;
+ double r1 = (k<r_eqn1.size())? r_eqn1.at(k).at1() : 0;
+ double rr0 = (k<r_eqn2.size())? r_eqn2.at(k).at0() : 0;
+ double rr1 = (k<r_eqn2.size())? r_eqn2.at(k).at1() : 0;
+ double a0,a1,b0,b1;// coeffs in a[k] and b[k]
+
+ //the equations to solve at this point are:
+ // a0*x(0)+b0*y(0)=r0 & 2*a0*a(0)+2*b0*b(0)=rr0
+ //and
+ // a1*x(1)+b1*y(1)=r1 & 2*a1*a(1)+2*b1*b(1)=rr1
+ a0 = r0/dot(v0,V.at0())*v0[0]-rr0/2*v0[1];
+ b0 = r0/dot(v0,V.at0())*v0[1]+rr0/2*v0[0];
+ a1 = r1/dot(v1,V.at1())*v1[0]-rr1/2*v1[1];
+ b1 = r1/dot(v1,V.at1())*v1[1]+rr1/2*v1[0];
+
+ a[k] = Linear(a0,a1);
+ b[k] = Linear(b0,b1);
+
+ //TODO: use "incremental" rather than explicit formulas.
+ r_eqn1 = -(a*x+b*y);
+ r_eqn2 = Linear(1)-(a*a+b*b);
+ }
+
+ //our candidate is:
+ D2<SBasis> unitV;
+ unitV[0] = b;
+ unitV[1] = -a;
+
+ //is it good?
+ double rel_tol = std::max(1.,std::max(V_in[0].tailError(0),V_in[1].tailError(0)))*tol;
+ if (r_eqn1.tailError(order)>rel_tol || r_eqn2.tailError(order)>tol){
+ //if not: subdivide and concat results.
+ Piecewise<D2<SBasis> > unitV0, unitV1;
+ unitV0 = unitVector(compose(V,Linear(0,.5)),tol,order);
+ unitV1 = unitVector(compose(V,Linear(.5,1)),tol,order);
+ unitV0.setDomain(Interval(0.,.5));
+ unitV1.setDomain(Interval(.5,1.));
+ unitV0.concat(unitV1);
+ return(unitV0);
+ }else{
+ //if yes: return it as pw.
+ Piecewise<D2<SBasis> > result;
+ result=(Piecewise<D2<SBasis> >)unitV;
+ return result;
+ }
+}
+
+/** Return a Piecewise<D2<SBasis> > which points in the same direction as V_in, but has unit_length.
+ \param V_in the original path.
+ \param tol the maximum error allowed.
+ \param order the maximum degree to use for approximation
+
+unitVector(x,y) is computed as (b,-a) where a and b are solutions of:
+ ax+by=0 (eqn1) and a^2+b^2=1 (eqn2)
+
+ \relates Piecewise
+*/
+Piecewise<D2<SBasis> >
+Geom::unitVector(Piecewise<D2<SBasis> > const &V, double tol, unsigned order){
+ Piecewise<D2<SBasis> > result;
+ Piecewise<D2<SBasis> > VV = cutAtRoots(V);
+ result.cuts.push_back(VV.cuts.front());
+ for (unsigned i=0; i<VV.size(); i++){
+ Piecewise<D2<SBasis> > unit_seg;
+ unit_seg = unitVector(VV.segs[i],tol, order);
+ unit_seg.setDomain(Interval(VV.cuts[i],VV.cuts[i+1]));
+ result.concat(unit_seg);
+ }
+ return result;
+}
+
+/** returns a function giving the arclength at each point in M.
+ \param M the Element.
+ \param tol the maximum error allowed.
+ \relates Piecewise
+*/
+Piecewise<SBasis>
+Geom::arcLengthSb(Piecewise<D2<SBasis> > const &M, double tol){
+ Piecewise<D2<SBasis> > dM = derivative(M);
+ Piecewise<SBasis> dMlength = sqrt(dot(dM,dM),tol,3);
+ Piecewise<SBasis> length = integral(dMlength);
+ length-=length.segs.front().at0();
+ return length;
+}
+
+/** returns a function giving the arclength at each point in M.
+ \param M the Element.
+ \param tol the maximum error allowed.
+ \relates Piecewise, D2
+*/
+Piecewise<SBasis>
+Geom::arcLengthSb(D2<SBasis> const &M, double tol){
+ return arcLengthSb(Piecewise<D2<SBasis> >(M), tol);
+}
+
+#if 0
+double
+Geom::length(D2<SBasis> const &M,
+ double tol){
+ Piecewise<SBasis> length = arcLengthSb(M, tol);
+ return length.segs.back().at1();
+}
+double
+Geom::length(Piecewise<D2<SBasis> > const &M,
+ double tol){
+ Piecewise<SBasis> length = arcLengthSb(M, tol);
+ return length.segs.back().at1();
+}
+#endif
+
+/** returns a function giving the curvature at each point in M.
+ \param M the Element.
+ \param tol the maximum error allowed.
+ \relates Piecewise, D2
+ \todo claimed incomplete. Check.
+*/
+Piecewise<SBasis>
+Geom::curvature(D2<SBasis> const &M, double tol) {
+ D2<SBasis> dM=derivative(M);
+ Piecewise<D2<SBasis> > unitv = unitVector(dM,tol);
+ Piecewise<SBasis> dMlength = dot(Piecewise<D2<SBasis> >(dM),unitv);
+ Piecewise<SBasis> k = cross(derivative(unitv),unitv);
+ k = divide(k,dMlength,tol,3);
+ return(k);
+}
+
+/** returns a function giving the curvature at each point in M.
+ \param M the Element.
+ \param tol the maximum error allowed.
+ \relates Piecewise
+ \todo claimed incomplete. Check.
+*/
+Piecewise<SBasis>
+Geom::curvature(Piecewise<D2<SBasis> > const &V, double tol){
+ Piecewise<SBasis> result;
+ Piecewise<D2<SBasis> > VV = cutAtRoots(V);
+ result.cuts.push_back(VV.cuts.front());
+ for (unsigned i=0; i<VV.size(); i++){
+ Piecewise<SBasis> curv_seg;
+ curv_seg = curvature(VV.segs[i],tol);
+ curv_seg.setDomain(Interval(VV.cuts[i],VV.cuts[i+1]));
+ result.concat(curv_seg);
+ }
+ return result;
+}
+
+//=================================================================
+
+/** Reparameterise M to have unit speed.
+ \param M the Element.
+ \param tol the maximum error allowed.
+ \param order the maximum degree to use for approximation
+ \relates Piecewise, D2
+*/
+Piecewise<D2<SBasis> >
+Geom::arc_length_parametrization(D2<SBasis> const &M,
+ unsigned order,
+ double tol){
+ Piecewise<D2<SBasis> > u;
+ u.push_cut(0);
+
+ Piecewise<SBasis> s = arcLengthSb(Piecewise<D2<SBasis> >(M),tol);
+ for (unsigned i=0; i < s.size();i++){
+ double t0=s.cuts[i],t1=s.cuts[i+1];
+ if ( are_near(s(t0),s(t1)) ) {
+ continue;
+ }
+ D2<SBasis> sub_M = compose(M,Linear(t0,t1));
+ D2<SBasis> sub_u;
+ for (unsigned dim=0;dim<2;dim++){
+ SBasis sub_s = s.segs[i];
+ sub_s-=sub_s.at0();
+ sub_s/=sub_s.at1();
+ sub_u[dim]=compose_inverse(sub_M[dim],sub_s, order, tol);
+ }
+ u.push(sub_u,s(t1));
+ }
+ return u;
+}
+
+/** Reparameterise M to have unit speed.
+ \param M the Element.
+ \param tol the maximum error allowed.
+ \param order the maximum degree to use for approximation
+ \relates Piecewise
+*/
+Piecewise<D2<SBasis> >
+Geom::arc_length_parametrization(Piecewise<D2<SBasis> > const &M,
+ unsigned order,
+ double tol){
+ Piecewise<D2<SBasis> > result;
+ for (unsigned i=0; i<M.size(); i++) {
+ result.concat( arc_length_parametrization(M[i],order,tol) );
+ }
+ return result;
+}
+
+#include <gsl/gsl_integration.h>
+static double sb_length_integrating(double t, void* param) {
+ SBasis* pc = (SBasis*)param;
+ return sqrt((*pc)(t));
+}
+
+/** Calculates the length of a D2<SBasis> through gsl integration.
+ \param B the Element.
+ \param tol the maximum error allowed.
+ \param result variable to be incremented with the length of the path
+ \param abs_error variable to be incremented with the estimated error
+ \relates D2
+If you only want the length, this routine may be faster/more accurate.
+*/
+void Geom::length_integrating(D2<SBasis> const &B, double &result, double &abs_error, double tol) {
+ D2<SBasis> dB = derivative(B);
+ SBasis dB2 = dot(dB, dB);
+
+ gsl_function F;
+ gsl_integration_workspace * w
+ = gsl_integration_workspace_alloc (20);
+ F.function = &sb_length_integrating;
+ F.params = (void*)&dB2;
+ double quad_result, err;
+ /* We could probably use the non adaptive code here if we removed any cusps first. */
+
+ gsl_integration_qag (&F, 0, 1, 0, tol, 20,
+ GSL_INTEG_GAUSS21, w, &quad_result, &err);
+
+ abs_error += err;
+ result += quad_result;
+}
+
+/** Calculates the length of a D2<SBasis> through gsl integration.
+ \param s the Element.
+ \param tol the maximum error allowed.
+ \relates D2
+If you only want the total length, this routine faster and more accurate than constructing an arcLengthSb.
+*/
+double
+Geom::length(D2<SBasis> const &s,
+ double tol){
+ double result = 0;
+ double abs_error = 0;
+ length_integrating(s, result, abs_error, tol);
+ return result;
+}
+/** Calculates the length of a Piecewise<D2<SBasis> > through gsl integration.
+ \param s the Element.
+ \param tol the maximum error allowed.
+ \relates Piecewise
+If you only want the total length, this routine faster and more accurate than constructing an arcLengthSb.
+*/
+double
+Geom::length(Piecewise<D2<SBasis> > const &s,
+ double tol){
+ double result = 0;
+ double abs_error = 0;
+ for (unsigned i=0; i < s.size();i++){
+ length_integrating(s[i], result, abs_error, tol);
+ }
+ return result;
+}
+
+/**
+ * Centroid using sbasis integration.
+ \param p the Element.
+ \param centroid on return contains the centroid of the shape
+ \param area on return contains the signed area of the shape.
+ \relates Piecewise
+This approach uses green's theorem to compute the area and centroid using integrals. For curved shapes this is much faster than converting to polyline. Note that without an uncross operation the output is not the absolute area.
+
+ * Returned values:
+ 0 for normal execution;
+ 2 if area is zero, meaning centroid is meaningless.
+
+ */
+unsigned Geom::centroid(Piecewise<D2<SBasis> > const &p, Point& centroid, double &area) {
+ Point centroid_tmp(0,0);
+ double atmp = 0;
+ for(unsigned i = 0; i < p.size(); i++) {
+ SBasis curl = dot(p[i], rot90(derivative(p[i])));
+ SBasis A = integral(curl);
+ D2<SBasis> C = integral(multiply(curl, p[i]));
+ atmp += A.at1() - A.at0();
+ centroid_tmp += C.at1()- C.at0(); // first moment.
+ }
+// join ends
+ centroid_tmp *= 2;
+ Point final = p[p.size()-1].at1(), initial = p[0].at0();
+ const double ai = cross(final, initial);
+ atmp += ai;
+ centroid_tmp += (final + initial)*ai; // first moment.
+
+ area = atmp / 2;
+ if (atmp != 0) {
+ centroid = centroid_tmp / (3 * atmp);
+ return 0;
+ }
+ return 2;
+}
+
+/**
+ * Find cubics with prescribed curvatures at both ends.
+ *
+ * this requires to solve a system of the form
+ *
+ * \f[
+ * \lambda_1 = a_0 \lambda_0^2 + c_0
+ * \lambda_0 = a_1 \lambda_1^2 + c_1
+ * \f]
+ *
+ * which is a deg 4 equation in lambda 0.
+ * Below are basic functions dedicated to solving this assuming a0 and a1 !=0.
+ */
+
+static OptInterval
+find_bounds_for_lambda0(double aa0,double aa1,double cc0,double cc1,
+ int insist_on_speeds_signs){
+
+ double a0=aa0,a1=aa1,c0=cc0,c1=cc1;
+ Interval result;
+ bool flip = a1<0;
+ if (a1<0){a1=-a1; c1=-c1;}
+ if (a0<0){a0=-a0; c0=-c0;}
+ double a = (a0<a1 ? a0 : a1);
+ double c = (c0<c1 ? c0 : c1);
+ double delta = 1-4*a*c;
+ if ( delta < 0 )
+ return OptInterval();//return empty interval
+ double lambda_max = (1+std::sqrt(delta))/2/a;
+
+ result = Interval(c,lambda_max);
+ if (flip)
+ result *= -1;
+ if (insist_on_speeds_signs == 1){
+ if (result.max() < 0)//Caution: setMin with max<new min...
+ return OptInterval();//return empty interval
+ result.setMin(0);
+ }
+ result = Interval(result.min()-.1,result.max()+.1);//just in case all our approx. were exact...
+ return result;
+}
+
+static
+std::vector<double>
+solve_lambda0(double a0,double a1,double c0,double c1,
+ int insist_on_speeds_signs){
+
+ SBasis p(3, Linear());
+ p[0] = Linear( a1*c0*c0+c1, a1*a0*(a0+ 2*c0) +a1*c0*c0 +c1 -1 );
+ p[1] = Linear( -a1*a0*(a0+2*c0), -a1*a0*(3*a0+2*c0) );
+ p[2] = Linear( a1*a0*a0 );
+
+ OptInterval domain = find_bounds_for_lambda0(a0,a1,c0,c1,insist_on_speeds_signs);
+ if ( !domain )
+ return std::vector<double>();
+ p = compose(p,Linear(domain->min(),domain->max()));
+ std::vector<double>rts = roots(p);
+ for (double & rt : rts){
+ rt = domain->min() + rt * domain->extent();
+ }
+ return rts;
+}
+
+/**
+* \brief returns the cubics fitting direction and curvature of a given
+* input curve at two points.
+*
+* The input can be the
+* value, speed, and acceleration
+* or
+* value, speed, and cross(acceleration,speed)
+* of the original curve at the both ends.
+* (the second is often technically useful, as it avoids unnecessary division by |v|^2)
+* Recall that K=1/R=cross(acceleration,speed)/|speed|^3.
+*
+* Moreover, a 7-th argument 'insist_on_speed_signs' can be supplied to select solutions:
+* If insist_on_speed_signs == 1, only consider solutions where speeds at both ends are positively
+* proportional to the given ones.
+* If insist_on_speed_signs == 0, allow speeds to point in the opposite direction (both at the same time)
+* If insist_on_speed_signs == -1, allow speeds to point in both direction independently.
+*
+* \relates D2
+*/
+std::vector<D2<SBasis> >
+Geom::cubics_fitting_curvature(Point const &M0, Point const &M1,
+ Point const &dM0, Point const &dM1,
+ double d2M0xdM0, double d2M1xdM1,
+ int insist_on_speed_signs,
+ double epsilon){
+ std::vector<D2<SBasis> > result;
+
+ //speed of cubic bezier will be lambda0*dM0 and lambda1*dM1,
+ //with lambda0 and lambda1 s.t. curvature at both ends is the same
+ //as the curvature of the given curve.
+ std::vector<double> lambda0,lambda1;
+ double dM1xdM0=cross(dM1,dM0);
+ if (fabs(dM1xdM0)<epsilon){
+ if (fabs(d2M0xdM0)<epsilon || fabs(d2M1xdM1)<epsilon){
+ return result;
+ }
+ double lbda02 = 6.*cross(M1-M0,dM0)/d2M0xdM0;
+ double lbda12 =-6.*cross(M1-M0,dM1)/d2M1xdM1;
+ if (lbda02<0 || lbda12<0){
+ return result;
+ }
+ lambda0.push_back(std::sqrt(lbda02) );
+ lambda1.push_back(std::sqrt(lbda12) );
+ }else{
+ //solve: lambda1 = a0 lambda0^2 + c0
+ // lambda0 = a1 lambda1^2 + c1
+ double a0,c0,a1,c1;
+ a0 = -d2M0xdM0/2/dM1xdM0;
+ c0 = 3*cross(M1-M0,dM0)/dM1xdM0;
+ a1 = -d2M1xdM1/2/dM1xdM0;
+ c1 = -3*cross(M1-M0,dM1)/dM1xdM0;
+
+ if (fabs(a0)<epsilon){
+ lambda1.push_back( c0 );
+ lambda0.push_back( a1*c0*c0 + c1 );
+ }else if (fabs(a1)<epsilon){
+ lambda0.push_back( c1 );
+ lambda1.push_back( a0*c1*c1 + c0 );
+ }else{
+ //find lamda0 by solving a deg 4 equation d0+d1*X+...+d4*X^4=0
+ vector<double> solns=solve_lambda0(a0,a1,c0,c1,insist_on_speed_signs);
+ for (double lbda0 : solns){
+ double lbda1=c0+a0*lbda0*lbda0;
+ //is this solution pointing in the + direction at both ends?
+ if (lbda0>=0. && lbda1>=0.){
+ lambda0.push_back( lbda0);
+ lambda1.push_back( lbda1);
+ }
+ //is this solution pointing in the - direction at both ends?
+ else if (lbda0<=0. && lbda1<=0. && insist_on_speed_signs<=0){
+ lambda0.push_back( lbda0);
+ lambda1.push_back( lbda1);
+ }
+ //ok,this solution is pointing in the + and - directions.
+ else if (insist_on_speed_signs<0){
+ lambda0.push_back( lbda0);
+ lambda1.push_back( lbda1);
+ }
+ }
+ }
+ }
+
+ for (unsigned i=0; i<lambda0.size(); i++){
+ Point V0 = lambda0[i]*dM0;
+ Point V1 = lambda1[i]*dM1;
+ D2<SBasis> cubic;
+ for(unsigned dim=0;dim<2;dim++){
+ SBasis c(2, Linear());
+ c[0] = Linear(M0[dim],M1[dim]);
+ c[1] = Linear( M0[dim]-M1[dim]+V0[dim],
+ -M0[dim]+M1[dim]-V1[dim]);
+ cubic[dim] = c;
+ }
+#if 0
+ Piecewise<SBasis> k = curvature(result);
+ double dM0_l = dM0.length();
+ double dM1_l = dM1.length();
+ g_warning("Target radii: %f, %f", dM0_l*dM0_l*dM0_l/d2M0xdM0,dM1_l*dM1_l*dM1_l/d2M1xdM1);
+ g_warning("Obtained radii: %f, %f",1/k.valueAt(0),1/k.valueAt(1));
+#endif
+ result.push_back(cubic);
+ }
+ return(result);
+}
+
+std::vector<D2<SBasis> >
+Geom::cubics_fitting_curvature(Point const &M0, Point const &M1,
+ Point const &dM0, Point const &dM1,
+ Point const &d2M0, Point const &d2M1,
+ int insist_on_speed_signs,
+ double epsilon){
+ double d2M0xdM0 = cross(d2M0,dM0);
+ double d2M1xdM1 = cross(d2M1,dM1);
+ return cubics_fitting_curvature(M0,M1,dM0,dM1,d2M0xdM0,d2M1xdM1,insist_on_speed_signs,epsilon);
+}
+
+std::vector<D2<SBasis> >
+Geom::cubics_with_prescribed_curvature(Point const &M0, Point const &M1,
+ Point const &dM0, Point const &dM1,
+ double k0, double k1,
+ int insist_on_speed_signs,
+ double epsilon){
+ double length;
+ length = dM0.length();
+ double d2M0xdM0 = k0*length*length*length;
+ length = dM1.length();
+ double d2M1xdM1 = k1*length*length*length;
+ return cubics_fitting_curvature(M0,M1,dM0,dM1,d2M0xdM0,d2M1xdM1,insist_on_speed_signs,epsilon);
+}
+
+
+namespace Geom {
+/**
+* \brief returns all the parameter values of A whose tangent passes through P.
+* \relates D2
+*/
+std::vector<double> find_tangents(Point P, D2<SBasis> const &A) {
+ SBasis crs (cross(A - P, derivative(A)));
+ return roots(crs);
+}
+
+/**
+* \brief returns all the parameter values of A whose normal passes through P.
+* \relates D2
+*/
+std::vector<double> find_normals(Point P, D2<SBasis> const &A) {
+ SBasis crs (dot(A - P, derivative(A)));
+ return roots(crs);
+}
+
+/**
+* \brief returns all the parameter values of A whose normal is parallel to vector V.
+* \relates D2
+*/
+std::vector<double> find_normals_by_vector(Point V, D2<SBasis> const &A) {
+ SBasis crs = dot(derivative(A), V);
+ return roots(crs);
+}
+/**
+* \brief returns all the parameter values of A whose tangent is parallel to vector V.
+* \relates D2
+*/
+std::vector<double> find_tangents_by_vector(Point V, D2<SBasis> const &A) {
+ SBasis crs = dot(derivative(A), rot90(V));
+ return roots(crs);
+}
+
+}
+//}; // namespace
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/sbasis-math.cpp b/src/3rdparty/2geom/src/2geom/sbasis-math.cpp
new file mode 100644
index 0000000..547f9af
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/sbasis-math.cpp
@@ -0,0 +1,379 @@
+/*
+ * sbasis-math.cpp - some std functions to work with (pw)s-basis
+ *
+ * Authors:
+ * Jean-Francois Barraud
+ *
+ * Copyright (C) 2006-2007 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+//this a first try to define sqrt, cos, sin, etc...
+//TODO: define a truncated compose(sb,sb, order) and extend it to pw<sb>.
+//TODO: in all these functions, compute 'order' according to 'tol'.
+
+#include <2geom/d2.h>
+#include <2geom/sbasis-math.h>
+#include <stdio.h>
+#include <math.h>
+//#define ZERO 1e-3
+
+
+namespace Geom {
+
+
+//-|x|-----------------------------------------------------------------------
+/** Return the absolute value of a function pointwise.
+ \param f function
+*/
+Piecewise<SBasis> abs(SBasis const &f){
+ return abs(Piecewise<SBasis>(f));
+}
+/** Return the absolute value of a function pointwise.
+ \param f function
+*/
+Piecewise<SBasis> abs(Piecewise<SBasis> const &f){
+ Piecewise<SBasis> absf=partition(f,roots(f));
+ for (unsigned i=0; i<absf.size(); i++){
+ if (absf.segs[i](.5)<0) absf.segs[i]*=-1;
+ }
+ return absf;
+}
+
+//-max(x,y), min(x,y)--------------------------------------------------------
+/** Return the greater of the two functions pointwise.
+ \param f, g two functions
+*/
+Piecewise<SBasis> max( SBasis const &f, SBasis const &g){
+ return max(Piecewise<SBasis>(f),Piecewise<SBasis>(g));
+}
+/** Return the greater of the two functions pointwise.
+ \param f, g two functions
+*/
+Piecewise<SBasis> max(Piecewise<SBasis> const &f, SBasis const &g){
+ return max(f,Piecewise<SBasis>(g));
+}
+/** Return the greater of the two functions pointwise.
+ \param f, g two functions
+*/
+Piecewise<SBasis> max( SBasis const &f, Piecewise<SBasis> const &g){
+ return max(Piecewise<SBasis>(f),g);
+}
+/** Return the greater of the two functions pointwise.
+ \param f, g two functions
+*/
+Piecewise<SBasis> max(Piecewise<SBasis> const &f, Piecewise<SBasis> const &g){
+ Piecewise<SBasis> max=partition(f,roots(f-g));
+ Piecewise<SBasis> gg =partition(g,max.cuts);
+ max = partition(max,gg.cuts);
+ for (unsigned i=0; i<max.size(); i++){
+ if (max.segs[i](.5)<gg.segs[i](.5)) max.segs[i]=gg.segs[i];
+ }
+ return max;
+}
+
+/** Return the more negative of the two functions pointwise.
+ \param f, g two functions
+*/
+Piecewise<SBasis>
+min( SBasis const &f, SBasis const &g){ return -max(-f,-g); }
+/** Return the more negative of the two functions pointwise.
+ \param f, g two functions
+*/
+Piecewise<SBasis>
+min(Piecewise<SBasis> const &f, SBasis const &g){ return -max(-f,-g); }
+/** Return the more negative of the two functions pointwise.
+ \param f, g two functions
+*/
+Piecewise<SBasis>
+min( SBasis const &f, Piecewise<SBasis> const &g){ return -max(-f,-g); }
+/** Return the more negative of the two functions pointwise.
+ \param f, g two functions
+*/
+Piecewise<SBasis>
+min(Piecewise<SBasis> const &f, Piecewise<SBasis> const &g){ return -max(-f,-g); }
+
+
+//-sign(x)---------------------------------------------------------------
+/** Return the sign of the two functions pointwise.
+ \param f function
+*/
+Piecewise<SBasis> signSb(SBasis const &f){
+ return signSb(Piecewise<SBasis>(f));
+}
+/** Return the sign of the two functions pointwise.
+ \param f function
+*/
+Piecewise<SBasis> signSb(Piecewise<SBasis> const &f){
+ Piecewise<SBasis> sign=partition(f,roots(f));
+ for (unsigned i=0; i<sign.size(); i++){
+ sign.segs[i] = (sign.segs[i](.5)<0)? Linear(-1.):Linear(1.);
+ }
+ return sign;
+}
+
+//-Sqrt----------------------------------------------------------
+static Piecewise<SBasis> sqrt_internal(SBasis const &f,
+ double tol,
+ int order){
+ SBasis sqrtf;
+ if(f.isZero() || order == 0){
+ return Piecewise<SBasis>(sqrtf);
+ }
+ if (f.at0()<-tol*tol && f.at1()<-tol*tol){
+ return sqrt_internal(-f,tol,order);
+ }else if (f.at0()>tol*tol && f.at1()>tol*tol){
+ sqrtf.resize(order+1, Linear(0,0));
+ sqrtf[0] = Linear(std::sqrt(f[0][0]), std::sqrt(f[0][1]));
+ SBasis r = f - multiply(sqrtf, sqrtf); // remainder
+ for(unsigned i = 1; int(i) <= order && i<r.size(); i++) {
+ Linear ci(r[i][0]/(2*sqrtf[0][0]), r[i][1]/(2*sqrtf[0][1]));
+ SBasis cisi = shift(ci, i);
+ r -= multiply(shift((sqrtf*2 + cisi), i), SBasis(ci));
+ r.truncate(order+1);
+ sqrtf[i] = ci;
+ if(r.tailError(i) == 0) // if exact
+ break;
+ }
+ }else{
+ sqrtf = Linear(std::sqrt(fabs(f.at0())), std::sqrt(fabs(f.at1())));
+ }
+
+ double err = (f - multiply(sqrtf, sqrtf)).tailError(0);
+ if (err<tol){
+ return Piecewise<SBasis>(sqrtf);
+ }
+
+ Piecewise<SBasis> sqrtf0,sqrtf1;
+ sqrtf0 = sqrt_internal(compose(f,Linear(0.,.5)),tol,order);
+ sqrtf1 = sqrt_internal(compose(f,Linear(.5,1.)),tol,order);
+ sqrtf0.setDomain(Interval(0.,.5));
+ sqrtf1.setDomain(Interval(.5,1.));
+ sqrtf0.concat(sqrtf1);
+ return sqrtf0;
+}
+
+/** Compute the sqrt of a function.
+ \param f function
+*/
+Piecewise<SBasis> sqrt(SBasis const &f, double tol, int order){
+ return sqrt(max(f,Linear(tol*tol)),tol,order);
+}
+
+/** Compute the sqrt of a function.
+ \param f function
+*/
+Piecewise<SBasis> sqrt(Piecewise<SBasis> const &f, double tol, int order){
+ Piecewise<SBasis> result;
+ Piecewise<SBasis> zero = Piecewise<SBasis>(Linear(tol*tol));
+ zero.setDomain(f.domain());
+ Piecewise<SBasis> ff=max(f,zero);
+
+ for (unsigned i=0; i<ff.size(); i++){
+ Piecewise<SBasis> sqrtfi = sqrt_internal(ff.segs[i],tol,order);
+ sqrtfi.setDomain(Interval(ff.cuts[i],ff.cuts[i+1]));
+ result.concat(sqrtfi);
+ }
+ return result;
+}
+
+//-Yet another sin/cos--------------------------------------------------------------
+
+/** Compute the sine of a function.
+ \param f function
+ \param tol maximum error
+ \param order maximum degree polynomial to use
+*/
+Piecewise<SBasis> sin( SBasis const &f, double tol, int order){return(cos(-f+M_PI/2,tol,order));}
+/** Compute the sine of a function.
+ \param f function
+ \param tol maximum error
+ \param order maximum degree polynomial to use
+*/
+Piecewise<SBasis> sin(Piecewise<SBasis> const &f, double tol, int order){return(cos(-f+M_PI/2,tol,order));}
+
+/** Compute the cosine of a function.
+ \param f function
+ \param tol maximum error
+ \param order maximum degree polynomial to use
+*/
+Piecewise<SBasis> cos(Piecewise<SBasis> const &f, double tol, int order){
+ Piecewise<SBasis> result;
+ for (unsigned i=0; i<f.size(); i++){
+ Piecewise<SBasis> cosfi = cos(f.segs[i],tol,order);
+ cosfi.setDomain(Interval(f.cuts[i],f.cuts[i+1]));
+ result.concat(cosfi);
+ }
+ return result;
+}
+
+/** Compute the cosine of a function.
+ \param f function
+ \param tol maximum error
+ \param order maximum degree polynomial to use
+*/
+Piecewise<SBasis> cos( SBasis const &f, double tol, int order){
+ double alpha = (f.at0()+f.at1())/2.;
+ SBasis x = f-alpha;
+ double d = x.tailError(0),err=1;
+ //estimate cos(x)-sum_0^order (-1)^k x^2k/2k! by the first neglicted term
+ for (int i=1; i<=2*order; i++) err*=d/i;
+
+ if (err<tol){
+ SBasis xk=Linear(1), c=Linear(1), s=Linear(0);
+ for (int k=1; k<=2*order; k+=2){
+ xk*=x/k;
+ //take also truncature errors into account...
+ err+=xk.tailError(order);
+ xk.truncate(order);
+ s+=xk;
+ xk*=-x/(k+1);
+ //take also truncature errors into account...
+ err+=xk.tailError(order);
+ xk.truncate(order);
+ c+=xk;
+ }
+ if (err<tol){
+ return Piecewise<SBasis>(std::cos(alpha)*c-std::sin(alpha)*s);
+ }
+ }
+ Piecewise<SBasis> c0,c1;
+ c0 = cos(compose(f,Linear(0.,.5)),tol,order);
+ c1 = cos(compose(f,Linear(.5,1.)),tol,order);
+ c0.setDomain(Interval(0.,.5));
+ c1.setDomain(Interval(.5,1.));
+ c0.concat(c1);
+ return c0;
+}
+
+//--1/x------------------------------------------------------------
+//TODO: this implementation is just wrong. Remove or redo!
+
+void truncateResult(Piecewise<SBasis> &f, int order){
+ if (order>=0){
+ for (auto & seg : f.segs){
+ seg.truncate(order);
+ }
+ }
+}
+
+Piecewise<SBasis> reciprocalOnDomain(Interval range, double tol){
+ Piecewise<SBasis> reciprocal_fn;
+ //TODO: deduce R from tol...
+ double R=2.;
+ SBasis reciprocal1_R=reciprocal(Linear(1,R),3);
+ double a=range.min(), b=range.max();
+ if (a*b<0){
+ b=std::max(fabs(a),fabs(b));
+ a=0;
+ }else if (b<0){
+ a=-range.max();
+ b=-range.min();
+ }
+
+ if (a<=tol){
+ reciprocal_fn.push_cut(0);
+ int i0=(int) floor(std::log(tol)/std::log(R));
+ a = std::pow(R,i0);
+ reciprocal_fn.push(Linear(1/a),a);
+ }else{
+ int i0=(int) floor(std::log(a)/std::log(R));
+ a = std::pow(R,i0);
+ reciprocal_fn.cuts.push_back(a);
+ }
+
+ while (a<b){
+ reciprocal_fn.push(reciprocal1_R/a,R*a);
+ a*=R;
+ }
+ if (range.min()<0 || range.max()<0){
+ Piecewise<SBasis>reciprocal_fn_neg;
+ //TODO: define reverse(pw<sb>);
+ reciprocal_fn_neg.cuts.push_back(-reciprocal_fn.cuts.back());
+ for (unsigned i=0; i<reciprocal_fn.size(); i++){
+ int idx=reciprocal_fn.segs.size()-1-i;
+ reciprocal_fn_neg.push_seg(-reverse(reciprocal_fn.segs.at(idx)));
+ reciprocal_fn_neg.push_cut(-reciprocal_fn.cuts.at(idx));
+ }
+ if (range.max()>0){
+ reciprocal_fn_neg.concat(reciprocal_fn);
+ }
+ reciprocal_fn=reciprocal_fn_neg;
+ }
+
+ return(reciprocal_fn);
+}
+
+Piecewise<SBasis> reciprocal(SBasis const &f, double tol, int order){
+ Piecewise<SBasis> reciprocal_fn=reciprocalOnDomain(*bounds_fast(f), tol);
+ Piecewise<SBasis> result=compose(reciprocal_fn,f);
+ truncateResult(result,order);
+ return(result);
+}
+Piecewise<SBasis> reciprocal(Piecewise<SBasis> const &f, double tol, int order){
+ Piecewise<SBasis> reciprocal_fn=reciprocalOnDomain(*bounds_fast(f), tol);
+ Piecewise<SBasis> result=compose(reciprocal_fn,f);
+ truncateResult(result,order);
+ return(result);
+}
+
+/**
+ * \brief Returns a Piecewise SBasis with prescribed values at prescribed times.
+ *
+ * \param times: vector of times at which the values are given. Should be sorted in increasing order.
+ * \param values: vector of prescribed values. Should have the same size as times and be sorted accordingly.
+ * \param smoothness: (defaults to 1) regularity class of the result: 0=piecewise linear, 1=continuous derivative, etc...
+ */
+Piecewise<SBasis> interpolate(std::vector<double> times, std::vector<double> values, unsigned smoothness){
+ assert ( values.size() == times.size() );
+ if ( values.empty() ) return Piecewise<SBasis>();
+ if ( values.size() == 1 ) return Piecewise<SBasis>(values[0]);//what about time??
+
+ SBasis sk = shift(Linear(1.),smoothness);
+ SBasis bump_in = integral(sk);
+ bump_in -= bump_in.at0();
+ bump_in /= bump_in.at1();
+ SBasis bump_out = reverse( bump_in );
+
+ Piecewise<SBasis> result;
+ result.cuts.push_back(times[0]);
+ for (unsigned i = 0; i<values.size()-1; i++){
+ result.push(bump_out*values[i]+bump_in*values[i+1],times[i+1]);
+ }
+ return result;
+}
+
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/sbasis-poly.cpp b/src/3rdparty/2geom/src/2geom/sbasis-poly.cpp
new file mode 100644
index 0000000..ffee43f
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/sbasis-poly.cpp
@@ -0,0 +1,59 @@
+#include <2geom/sbasis-poly.h>
+
+namespace Geom{
+
+/** Changes the basis of p to be sbasis.
+ \param p the Monomial basis polynomial
+ \returns the Symmetric basis polynomial
+
+This algorithm is horribly slow and numerically terrible. Only for testing.
+*/
+SBasis poly_to_sbasis(Poly const & p) {
+ SBasis x = Linear(0, 1);
+ SBasis r;
+
+ for(int i = p.size()-1; i >= 0; i--) {
+ r = SBasis(Linear(p[i], p[i])) + multiply(x, r);
+ }
+ r.normalize();
+ return r;
+
+}
+
+/** Changes the basis of p to be monomial.
+ \param p the Symmetric basis polynomial
+ \returns the Monomial basis polynomial
+
+This algorithm is horribly slow and numerically terrible. Only for testing.
+*/
+Poly sbasis_to_poly(SBasis const & sb) {
+ if(sb.isZero())
+ return Poly();
+ Poly S; // (1-x)x = -1*x^2 + 1*x + 0
+ Poly A, B;
+ B.push_back(0);
+ B.push_back(1);
+ A.push_back(1);
+ A.push_back(-1);
+ S = A*B;
+ Poly r;
+
+ for(int i = sb.size()-1; i >= 0; i--) {
+ r = S*r + sb[i][0]*A + sb[i][1]*B;
+ }
+ r.normalize();
+ return r;
+}
+
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/sbasis-roots.cpp b/src/3rdparty/2geom/src/2geom/sbasis-roots.cpp
new file mode 100644
index 0000000..ee006d2
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/sbasis-roots.cpp
@@ -0,0 +1,656 @@
+/**
+ * @file
+ * @brief Root finding for sbasis functions.
+ *//*
+ * Authors:
+ * Nathan Hurst <njh@njhurst.com>
+ * JF Barraud
+ * Copyright 2006-2007 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+ /*
+ * It is more efficient to find roots of f(t) = c_0, c_1, ... all at once, rather than iterating.
+ *
+ * Todo/think about:
+ * multi-roots using bernstein method, one approach would be:
+ sort c
+ take median and find roots of that
+ whenever a segment lies entirely on one side of the median,
+ find the median of the half and recurse.
+
+ in essence we are implementing quicksort on a continuous function
+
+ * the gsl poly roots finder is faster than bernstein too, but we don't use it for 3 reasons:
+
+ a) it requires conversion to poly, which is numerically unstable
+
+ b) it requires gsl (which is currently not a dependency, and would bring in a whole slew of unrelated stuff)
+
+ c) it finds all roots, even complex ones. We don't want to accidentally treat a nearly real root as a real root
+
+From memory gsl poly roots was about 10 times faster than bernstein in the case where all the roots
+are in [0,1] for polys of order 5. I spent some time working out whether eigenvalue root finding
+could be done directly in sbasis space, but the maths was too hard for me. -- njh
+
+jfbarraud: eigenvalue root finding could be done directly in sbasis space ?
+
+njh: I don't know, I think it should. You would make a matrix whose characteristic polynomial was
+correct, but do it by putting the sbasis terms in the right spots in the matrix. normal eigenvalue
+root finding makes a matrix that is a diagonal + a row along the top. This matrix has the property
+that its characteristic poly is just the poly whose coefficients are along the top row.
+
+Now an sbasis function is a linear combination of the poly coeffs. So it seems to me that you
+should be able to put the sbasis coeffs directly into a matrix in the right spots so that the
+characteristic poly is the sbasis. You'll still have problems b) and c).
+
+We might be able to lift an eigenvalue solver and include that directly into 2geom. Eigenvalues
+also allow you to find intersections of multiple curves but require solving n*m x n*m matrices.
+
+ **/
+
+#include <cmath>
+#include <map>
+
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/solver.h>
+
+using namespace std;
+
+namespace Geom{
+
+/** Find the smallest interval that bounds a
+ \param a sbasis function
+ \returns interval
+
+*/
+
+#ifdef USE_SBASIS_OF
+OptInterval bounds_exact(SBasisOf<double> const &a) {
+ Interval result = Interval(a.at0(), a.at1());
+ SBasisOf<double> df = derivative(a);
+ vector<double>extrema = roots(df);
+ for (unsigned i=0; i<extrema.size(); i++){
+ result.extendTo(a(extrema[i]));
+ }
+ return result;
+}
+#else
+OptInterval bounds_exact(SBasis const &a) {
+ Interval result = Interval(a.at0(), a.at1());
+ SBasis df = derivative(a);
+ vector<double>extrema = roots(df);
+ for (double i : extrema){
+ result.expandTo(a(i));
+ }
+ return result;
+}
+#endif
+
+/** Find a small interval that bounds a
+ \param a sbasis function
+ \returns interval
+
+*/
+// I have no idea how this works, some clever bounding argument by jfb.
+#ifdef USE_SBASIS_OF
+OptInterval bounds_fast(const SBasisOf<double> &sb, int order) {
+#else
+OptInterval bounds_fast(const SBasis &sb, int order) {
+#endif
+ Interval res(0,0); // an empty sbasis is 0.
+
+ for(int j = sb.size()-1; j>=order; j--) {
+ double a=sb[j][0];
+ double b=sb[j][1];
+
+ double v, t = 0;
+ v = res.min();
+ if (v<0) t = ((b-a)/v+1)*0.5;
+ if (v>=0 || t<0 || t>1) {
+ res.setMin(std::min(a,b));
+ } else {
+ res.setMin(lerp(t, a+v*t, b));
+ }
+
+ v = res.max();
+ if (v>0) t = ((b-a)/v+1)*0.5;
+ if (v<=0 || t<0 || t>1) {
+ res.setMax(std::max(a,b));
+ }else{
+ res.setMax(lerp(t, a+v*t, b));
+ }
+ }
+ if (order>0) res*=std::pow(.25,order);
+ return res;
+}
+
+/** Find a small interval that bounds a(t) for t in i to order order
+ \param sb sbasis function
+ \param i domain interval
+ \param order number of terms
+ \return interval
+
+*/
+#ifdef USE_SBASIS_OF
+OptInterval bounds_local(const SBasisOf<double> &sb, const OptInterval &i, int order) {
+#else
+OptInterval bounds_local(const SBasis &sb, const OptInterval &i, int order) {
+#endif
+ double t0=i->min(), t1=i->max(), lo=0., hi=0.;
+ for(int j = sb.size()-1; j>=order; j--) {
+ double a=sb[j][0];
+ double b=sb[j][1];
+
+ double t = 0;
+ if (lo<0) t = ((b-a)/lo+1)*0.5;
+ if (lo>=0 || t<t0 || t>t1) {
+ lo = std::min(a*(1-t0)+b*t0+lo*t0*(1-t0),a*(1-t1)+b*t1+lo*t1*(1-t1));
+ }else{
+ lo = lerp(t, a+lo*t, b);
+ }
+
+ if (hi>0) t = ((b-a)/hi+1)*0.5;
+ if (hi<=0 || t<t0 || t>t1) {
+ hi = std::max(a*(1-t0)+b*t0+hi*t0*(1-t0),a*(1-t1)+b*t1+hi*t1*(1-t1));
+ }else{
+ hi = lerp(t, a+hi*t, b);
+ }
+ }
+ Interval res = Interval(lo,hi);
+ if (order>0) res*=std::pow(.25,order);
+ return res;
+}
+
+//-- multi_roots ------------------------------------
+// goal: solve f(t)=c for several c at once.
+/* algo: -compute f at both ends of the given segment [a,b].
+ -compute bounds m<df(t)<M for df on the segment.
+ let c and C be the levels below and above f(a):
+ going from f(a) down to c with slope m takes at least time (f(a)-c)/m
+ going from f(a) up to C with slope M takes at least time (C-f(a))/M
+ From this we conclude there are no roots before a'=a+min((f(a)-c)/m,(C-f(a))/M).
+ Do the same for b: compute some b' such that there are no roots in (b',b].
+ -if [a',b'] is not empty, repeat the process with [a',(a'+b')/2] and [(a'+b')/2,b'].
+ unfortunately, extra care is needed about rounding errors, and also to avoid the repetition of roots,
+ making things tricky and unpleasant...
+*/
+//TODO: Make sure the code is "rounding-errors proof" and take care about repetition of roots!
+
+
+static int upper_level(vector<double> const &levels,double x,double tol=0.){
+ return(upper_bound(levels.begin(),levels.end(),x-tol)-levels.begin());
+}
+
+#ifdef USE_SBASIS_OF
+static void multi_roots_internal(SBasis const &f,
+ SBasis const &df,
+#else
+static void multi_roots_internal(SBasis const &f,
+ SBasis const &df,
+#endif
+ std::vector<double> const &levels,
+ std::vector<std::vector<double> > &roots,
+ double htol,
+ double vtol,
+ double a,
+ double fa,
+ double b,
+ double fb){
+
+ if (f.isZero(0)){
+ int idx;
+ idx=upper_level(levels,0,vtol);
+ if (idx<(int)levels.size()&&fabs(levels.at(idx))<=vtol){
+ roots[idx].push_back(a);
+ roots[idx].push_back(b);
+ }
+ return;
+ }
+////useful?
+// if (f.size()==1){
+// int idxa=upper_level(levels,fa);
+// int idxb=upper_level(levels,fb);
+// if (fa==fb){
+// if (fa==levels[idxa]){
+// roots[a]=idxa;
+// roots[b]=idxa;
+// }
+// return;
+// }
+// int idx_min=std::min(idxa,idxb);
+// int idx_max=std::max(idxa,idxb);
+// if (idx_max==levels.size()) idx_max-=1;
+// for(int i=idx_min;i<=idx_max; i++){
+// double t=a+(b-a)*(levels[i]-fa)/(fb-fa);
+// if(a<t&&t<b) roots[t]=i;
+// }
+// return;
+// }
+ if ((b-a)<htol){
+ //TODO: use different tol for t and f ?
+ //TODO: unsigned idx ? (remove int casts when fixed)
+ int idx=std::min(upper_level(levels,fa,vtol),upper_level(levels,fb,vtol));
+ if (idx==(int)levels.size()) idx-=1;
+ double c=levels.at(idx);
+ if((fa-c)*(fb-c)<=0||fabs(fa-c)<vtol||fabs(fb-c)<vtol){
+ roots[idx].push_back((a+b)/2);
+ }
+ return;
+ }
+
+ int idxa=upper_level(levels,fa,vtol);
+ int idxb=upper_level(levels,fb,vtol);
+
+ Interval bs = *bounds_local(df,Interval(a,b));
+
+ //first times when a level (higher or lower) can be reached from a or b.
+ double ta_hi,tb_hi,ta_lo,tb_lo;
+ ta_hi=ta_lo=b+1;//default values => no root there.
+ tb_hi=tb_lo=a-1;//default values => no root there.
+
+ if (idxa<(int)levels.size() && fabs(fa-levels.at(idxa))<vtol){//a can be considered a root.
+ //ta_hi=ta_lo=a;
+ roots[idxa].push_back(a);
+ ta_hi=ta_lo=a+htol;
+ }else{
+ if (bs.max()>0 && idxa<(int)levels.size())
+ ta_hi=a+(levels.at(idxa )-fa)/bs.max();
+ if (bs.min()<0 && idxa>0)
+ ta_lo=a+(levels.at(idxa-1)-fa)/bs.min();
+ }
+ if (idxb<(int)levels.size() && fabs(fb-levels.at(idxb))<vtol){//b can be considered a root.
+ //tb_hi=tb_lo=b;
+ roots[idxb].push_back(b);
+ tb_hi=tb_lo=b-htol;
+ }else{
+ if (bs.min()<0 && idxb<(int)levels.size())
+ tb_hi=b+(levels.at(idxb )-fb)/bs.min();
+ if (bs.max()>0 && idxb>0)
+ tb_lo=b+(levels.at(idxb-1)-fb)/bs.max();
+ }
+
+ double t0,t1;
+ t0=std::min(ta_hi,ta_lo);
+ t1=std::max(tb_hi,tb_lo);
+ //hum, rounding errors frighten me! so I add this +tol...
+ if (t0>t1+htol) return;//no root here.
+
+ if (fabs(t1-t0)<htol){
+ multi_roots_internal(f,df,levels,roots,htol,vtol,t0,f(t0),t1,f(t1));
+ }else{
+ double t,t_left,t_right,ft,ft_left,ft_right;
+ t_left =t_right =t =(t0+t1)/2;
+ ft_left=ft_right=ft=f(t);
+ int idx=upper_level(levels,ft,vtol);
+ if (idx<(int)levels.size() && fabs(ft-levels.at(idx))<vtol){//t can be considered a root.
+ roots[idx].push_back(t);
+ //we do not want to count it twice (from the left and from the right)
+ t_left =t-htol/2;
+ t_right=t+htol/2;
+ ft_left =f(t_left);
+ ft_right=f(t_right);
+ }
+ multi_roots_internal(f,df,levels,roots,htol,vtol,t0 ,f(t0) ,t_left,ft_left);
+ multi_roots_internal(f,df,levels,roots,htol,vtol,t_right,ft_right,t1 ,f(t1) );
+ }
+}
+
+/** Solve f(t)=c for several c at once.
+ \param f sbasis function
+ \param levels vector of 'y' values
+ \param htol, vtol
+ \param a, b left and right bounds
+ \returns a vector of vectors, one for each y giving roots
+
+Effectively computes:
+results = roots(f(y_i)) for all y_i
+
+* algo: -compute f at both ends of the given segment [a,b].
+ -compute bounds m<df(t)<M for df on the segment.
+ let c and C be the levels below and above f(a):
+ going from f(a) down to c with slope m takes at least time (f(a)-c)/m
+ going from f(a) up to C with slope M takes at least time (C-f(a))/M
+ From this we conclude there are no roots before a'=a+min((f(a)-c)/m,(C-f(a))/M).
+ Do the same for b: compute some b' such that there are no roots in (b',b].
+ -if [a',b'] is not empty, repeat the process with [a',(a'+b')/2] and [(a'+b')/2,b'].
+ unfortunately, extra care is needed about rounding errors, and also to avoid the repetition of roots,
+ making things tricky and unpleasant...
+
+TODO: Make sure the code is "rounding-errors proof" and take care about repetition of roots!
+*/
+std::vector<std::vector<double> > multi_roots(SBasis const &f,
+ std::vector<double> const &levels,
+ double htol,
+ double vtol,
+ double a,
+ double b){
+
+ std::vector<std::vector<double> > roots(levels.size(), std::vector<double>());
+
+ SBasis df=derivative(f);
+ multi_roots_internal(f,df,levels,roots,htol,vtol,a,f(a),b,f(b));
+
+ return(roots);
+}
+
+
+static bool compareIntervalMin( Interval I, Interval J ){
+ return I.min()<J.min();
+}
+static bool compareIntervalMax( Interval I, Interval J ){
+ return I.max()<J.max();
+}
+
+//find the first interval whose max is >= x
+static unsigned upper_level(vector<Interval> const &levels, double x ){
+ return( lower_bound( levels.begin(), levels.end(), Interval(x,x), compareIntervalMax) - levels.begin() );
+}
+
+static std::vector<Interval> fuseContiguous(std::vector<Interval> const &sets, double tol=0.){
+ std::vector<Interval> result;
+ if (sets.empty() ) return result;
+ result.push_back( sets.front() );
+ for (unsigned i=1; i < sets.size(); i++ ){
+ if ( result.back().max() + tol >= sets[i].min() ){
+ result.back().unionWith( sets[i] );
+ }else{
+ result.push_back( sets[i] );
+ }
+ }
+ return result;
+}
+
+/** level_sets internal method.
+* algorithm: (~adaptation of Newton method versus 'accroissements finis')
+ -compute f at both ends of the given segment [a,b].
+ -compute bounds m<df(t)<M for df on the segment.
+ Suppose f(a) is between two 'levels' c and C. Then
+ f won't enter c before a + (f(a)-c.max())/m
+ f won't enter C before a + (C.min()-f(a))/M
+ From this we conclude nothing happens before a'=a+min((f(a)-c.max())/m,(C.min()-f(a))/M).
+ We do the same for b: compute some b' such that nothing happens in (b',b].
+ -if [a',b'] is not empty, repeat the process with [a',(a'+b')/2] and [(a'+b')/2,b'].
+
+ If f(a) or f(b) belongs to some 'level' C, then use the same argument to find a' or b' such
+ that f remains in C on [a,a'] or [b',b]. In case f is monotonic, we also know f won't enter another
+ level before or after some time, allowing us to restrict the search a little more.
+
+ unfortunately, extra care is needed about rounding errors, and also to avoid the repetition of roots,
+ making things tricky and unpleasant...
+*/
+
+static void level_sets_internal(SBasis const &f,
+ SBasis const &df,
+ std::vector<Interval> const &levels,
+ std::vector<std::vector<Interval> > &solsets,
+ double a,
+ double fa,
+ double b,
+ double fb,
+ double tol=1e-5){
+
+ if (f.isZero(0)){
+ unsigned idx;
+ idx=upper_level( levels, 0. );
+ if (idx<levels.size() && levels[idx].contains(0.)){
+ solsets[idx].push_back( Interval(a,b) ) ;
+ }
+ return;
+ }
+
+ unsigned idxa=upper_level(levels,fa);
+ unsigned idxb=upper_level(levels,fb);
+
+ Interval bs = *bounds_local(df,Interval(a,b));
+
+ //first times when a level (higher or lower) can be reached from a or b.
+ double ta_hi; // f remains below next level for t<ta_hi
+ double ta_lo; // f remains above prev level for t<ta_lo
+ double tb_hi; // f remains below next level for t>tb_hi
+ double tb_lo; // f remains above next level for t>tb_lo
+
+ ta_hi=ta_lo=b+1;//default values => no root there.
+ tb_hi=tb_lo=a-1;//default values => no root there.
+
+ //--- if f(a) belongs to a level.-------
+ if ( idxa < levels.size() && levels[idxa].contains( fa ) ){
+ //find the first time when we may exit this level.
+ ta_lo = a + ( levels[idxa].min() - fa)/bs.min();
+ ta_hi = a + ( levels[idxa].max() - fa)/bs.max();
+ if ( ta_lo < a || ta_lo > b ) ta_lo = b;
+ if ( ta_hi < a || ta_hi > b ) ta_hi = b;
+ //move to that time for the next iteration.
+ solsets[idxa].push_back( Interval( a, std::min( ta_lo, ta_hi ) ) );
+ }else{
+ //--- if f(b) does not belong to a level.-------
+ if ( idxa == 0 ){
+ ta_lo = b;
+ }else{
+ ta_lo = a + ( levels[idxa-1].max() - fa)/bs.min();
+ if ( ta_lo < a ) ta_lo = b;
+ }
+ if ( idxa == levels.size() ){
+ ta_hi = b;
+ }else{
+ ta_hi = a + ( levels[idxa].min() - fa)/bs.max();
+ if ( ta_hi < a ) ta_hi = b;
+ }
+ }
+
+ //--- if f(b) belongs to a level.-------
+ if (idxb<levels.size() && levels.at(idxb).contains(fb)){
+ //find the first time from b when we may exit this level.
+ tb_lo = b + ( levels[idxb].min() - fb ) / bs.max();
+ tb_hi = b + ( levels[idxb].max() - fb ) / bs.min();
+ if ( tb_lo > b || tb_lo < a ) tb_lo = a;
+ if ( tb_hi > b || tb_hi < a ) tb_hi = a;
+ //move to that time for the next iteration.
+ solsets[idxb].push_back( Interval( std::max( tb_lo, tb_hi ), b) );
+ }else{
+ //--- if f(b) does not belong to a level.-------
+ if ( idxb == 0 ){
+ tb_lo = a;
+ }else{
+ tb_lo = b + ( levels[idxb-1].max() - fb)/bs.max();
+ if ( tb_lo > b ) tb_lo = a;
+ }
+ if ( idxb == levels.size() ){
+ tb_hi = a;
+ }else{
+ tb_hi = b + ( levels[idxb].min() - fb)/bs.min();
+ if ( tb_hi > b ) tb_hi = a;
+ }
+
+
+ if ( bs.min() < 0 && idxb < levels.size() )
+ tb_hi = b + ( levels[idxb ].min() - fb ) / bs.min();
+ if ( bs.max() > 0 && idxb > 0 )
+ tb_lo = b + ( levels[idxb-1].max() - fb ) / bs.max();
+ }
+
+ //let [t0,t1] be the next interval where to search.
+ double t0=std::min(ta_hi,ta_lo);
+ double t1=std::max(tb_hi,tb_lo);
+
+ if (t0>=t1) return;//no root here.
+
+ //if the interval is smaller than our resolution:
+ //pretend f simultaneously meets all the levels between f(t0) and f(t1)...
+ if ( t1 - t0 <= tol ){
+ Interval f_t0t1 ( f(t0), f(t1) );
+ unsigned idxmin = std::min(idxa, idxb);
+ unsigned idxmax = std::max(idxa, idxb);
+ //push [t0,t1] into all crossed level. Cheat to avoid overlapping intervals on different levels?
+ if ( idxmax > idxmin ){
+ for (unsigned idx = idxmin; idx < idxmax; idx++){
+ solsets[idx].push_back( Interval( t0, t1 ) );
+ }
+ }
+ if ( idxmax < levels.size() && f_t0t1.intersects( levels[idxmax] ) ){
+ solsets[idxmax].push_back( Interval( t0, t1 ) );
+ }
+ return;
+ }
+
+ //To make sure we finally exit the level jump at least by tol:
+ t0 = std::min( std::max( t0, a + tol ), b );
+ t1 = std::max( std::min( t1, b - tol ), a );
+
+ double t =(t0+t1)/2;
+ double ft=f(t);
+ level_sets_internal( f, df, levels, solsets, t0, f(t0), t, ft );
+ level_sets_internal( f, df, levels, solsets, t, ft, t1, f(t1) );
+}
+
+std::vector<std::vector<Interval> > level_sets(SBasis const &f,
+ std::vector<Interval> const &levels,
+ double a, double b, double tol){
+
+ std::vector<std::vector<Interval> > solsets(levels.size(), std::vector<Interval>());
+
+ SBasis df=derivative(f);
+ level_sets_internal(f,df,levels,solsets,a,f(a),b,f(b),tol);
+ // Fuse overlapping intervals...
+ for (auto & solset : solsets){
+ if ( solset.size() == 0 ) continue;
+ std::sort( solset.begin(), solset.end(), compareIntervalMin );
+ solset = fuseContiguous( solset, tol );
+ }
+ return solsets;
+}
+
+std::vector<Interval> level_set (SBasis const &f, double level, double vtol, double a, double b, double tol){
+ Interval fat_level( level - vtol, level + vtol );
+ return level_set(f, fat_level, a, b, tol);
+}
+std::vector<Interval> level_set (SBasis const &f, Interval const &level, double a, double b, double tol){
+ std::vector<Interval> levels(1,level);
+ return level_sets(f,levels, a, b, tol).front() ;
+}
+std::vector<std::vector<Interval> > level_sets (SBasis const &f, std::vector<double> const &levels, double vtol, double a, double b, double tol){
+ std::vector<Interval> fat_levels( levels.size(), Interval());
+ for (unsigned i = 0; i < levels.size(); i++){
+ fat_levels[i] = Interval( levels[i]-vtol, levels[i]+vtol);
+ }
+ return level_sets(f, fat_levels, a, b, tol);
+}
+
+
+//-------------------------------------
+//-------------------------------------
+
+
+void subdiv_sbasis(SBasis const & s,
+ std::vector<double> & roots,
+ double left, double right) {
+ OptInterval bs = bounds_fast(s);
+ if(!bs || bs->min() > 0 || bs->max() < 0)
+ return; // no roots here
+ if(s.tailError(1) < 1e-7) {
+ double t = s[0][0] / (s[0][0] - s[0][1]);
+ roots.push_back(left*(1-t) + t*right);
+ return;
+ }
+ double middle = (left + right)/2;
+ subdiv_sbasis(compose(s, Linear(0, 0.5)), roots, left, middle);
+ subdiv_sbasis(compose(s, Linear(0.5, 1.)), roots, middle, right);
+}
+
+// It is faster to use the bernstein root finder for small degree polynomials (<100?.
+
+std::vector<double> roots1(SBasis const & s) {
+ std::vector<double> res;
+ double d = s[0][0] - s[0][1];
+ if(d != 0) {
+ double r = s[0][0] / d;
+ if(0 <= r && r <= 1)
+ res.push_back(r);
+ }
+ return res;
+}
+
+std::vector<double> roots1(SBasis const & s, Interval const ivl) {
+ std::vector<double> res;
+ double d = s[0][0] - s[0][1];
+ if(d != 0) {
+ double r = s[0][0] / d;
+ if(ivl.contains(r))
+ res.push_back(r);
+ }
+ return res;
+}
+
+/** Find all t s.t s(t) = 0
+ \param a sbasis function
+ \see Bezier::roots
+ \returns vector of zeros (roots)
+
+*/
+std::vector<double> roots(SBasis const & s) {
+ switch(s.size()) {
+ case 0:
+ assert(false);
+ return std::vector<double>();
+ case 1:
+ return roots1(s);
+ default:
+ {
+ Bezier bz;
+ sbasis_to_bezier(bz, s);
+ return bz.roots();
+ }
+ }
+}
+std::vector<double> roots(SBasis const & s, Interval const ivl) {
+ switch(s.size()) {
+ case 0:
+ assert(false);
+ return std::vector<double>();
+ case 1:
+ return roots1(s, ivl);
+ default:
+ {
+ Bezier bz;
+ sbasis_to_bezier(bz, s);
+ return bz.roots(ivl);
+ }
+ }
+}
+
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/sbasis-to-bezier.cpp b/src/3rdparty/2geom/src/2geom/sbasis-to-bezier.cpp
new file mode 100644
index 0000000..5580956
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/sbasis-to-bezier.cpp
@@ -0,0 +1,584 @@
+/*
+ * Symmetric Power Basis - Bernstein Basis conversion routines
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Nathan Hurst <njh@mail.csse.monash.edu.au>
+ *
+ * Copyright 2007-2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/d2.h>
+#include <2geom/choose.h>
+#include <2geom/path-sink.h>
+#include <2geom/exception.h>
+#include <2geom/convex-hull.h>
+
+#include <iostream>
+
+
+
+
+namespace Geom
+{
+
+/*
+ * Symmetric Power Basis - Bernstein Basis conversion routines
+ *
+ * some remark about precision:
+ * interval [0,1], subdivisions: 10^3
+ * - bezier_to_sbasis : up to degree ~72 precision is at least 10^-5
+ * up to degree ~87 precision is at least 10^-3
+ * - sbasis_to_bezier : up to order ~63 precision is at least 10^-15
+ * precision is at least 10^-14 even beyond order 200
+ *
+ * interval [-1,1], subdivisions: 10^3
+ * - bezier_to_sbasis : up to degree ~21 precision is at least 10^-5
+ * up to degree ~24 precision is at least 10^-3
+ * - sbasis_to_bezier : up to order ~11 precision is at least 10^-5
+ * up to order ~13 precision is at least 10^-3
+ *
+ * interval [-10,10], subdivisions: 10^3
+ * - bezier_to_sbasis : up to degree ~7 precision is at least 10^-5
+ * up to degree ~8 precision is at least 10^-3
+ * - sbasis_to_bezier : up to order ~3 precision is at least 10^-5
+ * up to order ~4 precision is at least 10^-3
+ *
+ * references:
+ * this implementation is based on the following article:
+ * J.Sanchez-Reyes - The Symmetric Analogue of the Polynomial Power Basis
+ */
+
+/** Changes the basis of p to be bernstein.
+ \param p the Symmetric basis polynomial
+ \returns the Bernstein basis polynomial
+
+ if the degree is even q is the order in the symmetrical power basis,
+ if the degree is odd q is the order + 1
+ n is always the polynomial degree, i. e. the Bezier order
+ sz is the number of bezier handles.
+*/
+void sbasis_to_bezier (Bezier & bz, SBasis const& sb, size_t sz)
+{
+ assert(sb.size() > 0);
+
+ size_t q, n;
+ bool even;
+ if (sz == 0)
+ {
+ q = sb.size();
+ if (sb[q-1][0] == sb[q-1][1])
+ {
+ even = true;
+ --q;
+ n = 2*q;
+ }
+ else
+ {
+ even = false;
+ n = 2*q-1;
+ }
+ }
+ else
+ {
+ q = (sz > 2*sb.size()-1) ? sb.size() : (sz+1)/2;
+ n = sz-1;
+ even = false;
+ }
+ bz.clear();
+ bz.resize(n+1);
+ for (size_t k = 0; k < q; ++k)
+ {
+ int Tjk = 1;
+ for (size_t j = k; j < n-k; ++j) // j <= n-k-1
+ {
+ bz[j] += (Tjk * sb[k][0]);
+ bz[n-j] += (Tjk * sb[k][1]); // n-k <-> [k][1]
+ // assert(Tjk == binomial(n-2*k-1, j-k));
+ binomial_increment_k(Tjk, n-2*k-1, j-k);
+ }
+ }
+ if (even)
+ {
+ bz[q] += sb[q][0];
+ }
+ // the resulting coefficients are with respect to the scaled Bernstein
+ // basis so we need to divide them by (n, j) binomial coefficient
+ int bcj = n;
+ for (size_t j = 1; j < n; ++j)
+ {
+ bz[j] /= bcj;
+ // assert(bcj == binomial(n, j));
+ binomial_increment_k(bcj, n, j);
+ }
+ bz[0] = sb[0][0];
+ bz[n] = sb[0][1];
+}
+
+void sbasis_to_bezier(D2<Bezier> &bz, D2<SBasis> const &sb, size_t sz)
+{
+ if (sz == 0) {
+ sz = std::max(sb[X].size(), sb[Y].size())*2;
+ }
+ sbasis_to_bezier(bz[X], sb[X], sz);
+ sbasis_to_bezier(bz[Y], sb[Y], sz);
+}
+
+/** Changes the basis of p to be Bernstein.
+ \param p the D2 Symmetric basis polynomial
+ \returns the D2 Bernstein basis polynomial
+
+ sz is always the polynomial degree, i. e. the Bezier order
+*/
+void sbasis_to_bezier (std::vector<Point> & bz, D2<SBasis> const& sb, size_t sz)
+{
+ D2<Bezier> bez;
+ sbasis_to_bezier(bez, sb, sz);
+ bz = bezier_points(bez);
+}
+
+/** Changes the basis of p to be Bernstein.
+ \param p the D2 Symmetric basis polynomial
+ \returns the D2 Bernstein basis cubic polynomial
+
+Bezier is always cubic.
+For general asymmetric case, fit the SBasis function value at midpoint
+For parallel, symmetric case, find the point of closest approach to the midpoint
+For parallel, anti-symmetric case, fit the SBasis slope at midpoint
+*/
+void sbasis_to_cubic_bezier (std::vector<Point> & bz, D2<SBasis> const& sb)
+{
+ double delx[2], dely[2];
+ double xprime[2], yprime[2];
+ double midx = 0;
+ double midy = 0;
+ double midx_0, midy_0;
+ double numer[2], numer_0[2];
+ double denom;
+ double div;
+
+ if ((sb[X].size() == 0) || (sb[Y].size() == 0)) {
+ THROW_RANGEERROR("size of sb is too small");
+ }
+
+ sbasis_to_bezier(bz, sb, 4); // zeroth-order estimate
+ if ((sb[X].size() < 3) && (sb[Y].size() < 3))
+ return; // cubic bezier estimate is exact
+ Geom::ConvexHull bezhull(bz);
+
+// calculate first derivatives of x and y wrt t
+
+ for (int i = 0; i < 2; ++i) {
+ xprime[i] = sb[X][0][1] - sb[X][0][0];
+ yprime[i] = sb[Y][0][1] - sb[Y][0][0];
+ }
+ if (sb[X].size() > 1) {
+ xprime[0] += sb[X][1][0];
+ xprime[1] -= sb[X][1][1];
+ }
+ if (sb[Y].size() > 1) {
+ yprime[0] += sb[Y][1][0];
+ yprime[1] -= sb[Y][1][1];
+ }
+
+// calculate midpoint at t = 0.5
+
+ div = 2;
+ for (auto i : sb[X]) {
+ midx += (i[0] + i[1])/div;
+ div *= 4;
+ }
+
+ div = 2;
+ for (auto i : sb[Y]) {
+ midy += (i[0] + i[1])/div;
+ div *= 4;
+ }
+
+// is midpoint in hull: if not, the solution will be ill-conditioned, LP Bug 1428683
+
+ if (!bezhull.contains(Geom::Point(midx, midy)))
+ return;
+
+// calculate Bezier control arms
+
+ midx = 8*midx - 4*bz[0][X] - 4*bz[3][X]; // re-define relative to center
+ midy = 8*midy - 4*bz[0][Y] - 4*bz[3][Y];
+ midx_0 = sb[X].size() > 1 ? sb[X][1][0] + sb[X][1][1] : 0; // zeroth order estimate
+ midy_0 = sb[Y].size() > 1 ? sb[Y][1][0] + sb[Y][1][1] : 0;
+
+ if ((std::abs(xprime[0]) < EPSILON) && (std::abs(yprime[0]) < EPSILON)
+ && ((std::abs(xprime[1]) > EPSILON) || (std::abs(yprime[1]) > EPSILON))) { // degenerate handle at 0 : use distance of closest approach
+ numer[0] = midx*xprime[1] + midy*yprime[1];
+ denom = 3.0*(xprime[1]*xprime[1] + yprime[1]*yprime[1]);
+ delx[0] = 0;
+ dely[0] = 0;
+ delx[1] = -xprime[1]*numer[0]/denom;
+ dely[1] = -yprime[1]*numer[0]/denom;
+ } else if ((std::abs(xprime[1]) < EPSILON) && (std::abs(yprime[1]) < EPSILON)
+ && ((std::abs(xprime[0]) > EPSILON) || (std::abs(yprime[0]) > EPSILON))) { // degenerate handle at 1 : ditto
+ numer[1] = midx*xprime[0] + midy*yprime[0];
+ denom = 3.0*(xprime[0]*xprime[0] + yprime[0]*yprime[0]);
+ delx[0] = xprime[0]*numer[1]/denom;
+ dely[0] = yprime[0]*numer[1]/denom;
+ delx[1] = 0;
+ dely[1] = 0;
+ } else if (std::abs(xprime[1]*yprime[0] - yprime[1]*xprime[0]) > // general case : fit mid fxn value
+ 0.002 * std::abs(xprime[1]*xprime[0] + yprime[1]*yprime[0])) { // approx. 0.1 degree of angle
+ double test1 = (bz[1][Y] - bz[0][Y])*(bz[3][X] - bz[0][X]) - (bz[1][X] - bz[0][X])*(bz[3][Y] - bz[0][Y]);
+ double test2 = (bz[2][Y] - bz[0][Y])*(bz[3][X] - bz[0][X]) - (bz[2][X] - bz[0][X])*(bz[3][Y] - bz[0][Y]);
+ if (test1*test2 < 0) // reject anti-symmetric case, LP Bug 1428267 & Bug 1428683
+ return;
+ denom = 3.0*(xprime[1]*yprime[0] - yprime[1]*xprime[0]);
+ for (int i = 0; i < 2; ++i) {
+ numer_0[i] = xprime[1 - i]*midy_0 - yprime[1 - i]*midx_0;
+ numer[i] = xprime[1 - i]*midy - yprime[1 - i]*midx;
+ delx[i] = xprime[i]*numer[i]/denom;
+ dely[i] = yprime[i]*numer[i]/denom;
+ if (numer_0[i]*numer[i] < 0) // check for reversal of direction, LP Bug 1544680
+ return;
+ }
+ if (std::abs((numer[0] - numer_0[0])*numer_0[1]) > 10.0*std::abs((numer[1] - numer_0[1])*numer_0[0]) // check for asymmetry
+ || std::abs((numer[1] - numer_0[1])*numer_0[0]) > 10.0*std::abs((numer[0] - numer_0[0])*numer_0[1]))
+ return;
+ } else if ((xprime[0]*xprime[1] < 0) || (yprime[0]*yprime[1] < 0)) { // symmetric case : use distance of closest approach
+ numer[0] = midx*xprime[0] + midy*yprime[0];
+ denom = 6.0*(xprime[0]*xprime[0] + yprime[0]*yprime[0]);
+ delx[0] = xprime[0]*numer[0]/denom;
+ dely[0] = yprime[0]*numer[0]/denom;
+ delx[1] = -delx[0];
+ dely[1] = -dely[0];
+ } else { // anti-symmetric case : fit mid slope
+ // calculate slope at t = 0.5
+ midx = 0;
+ div = 1;
+ for (auto i : sb[X]) {
+ midx += (i[1] - i[0])/div;
+ div *= 4;
+ }
+ midy = 0;
+ div = 1;
+ for (auto i : sb[Y]) {
+ midy += (i[1] - i[0])/div;
+ div *= 4;
+ }
+ if (midx*yprime[0] != midy*xprime[0]) {
+ denom = midx*yprime[0] - midy*xprime[0];
+ numer[0] = midx*(bz[3][Y] - bz[0][Y]) - midy*(bz[3][X] - bz[0][X]);
+ for (int i = 0; i < 2; ++i) {
+ delx[i] = xprime[0]*numer[0]/denom;
+ dely[i] = yprime[0]*numer[0]/denom;
+ }
+ } else { // linear case
+ for (int i = 0; i < 2; ++i) {
+ delx[i] = (bz[3][X] - bz[0][X])/3;
+ dely[i] = (bz[3][Y] - bz[0][Y])/3;
+ }
+ }
+ }
+ bz[1][X] = bz[0][X] + delx[0];
+ bz[1][Y] = bz[0][Y] + dely[0];
+ bz[2][X] = bz[3][X] - delx[1];
+ bz[2][Y] = bz[3][Y] - dely[1];
+}
+
+/** Changes the basis of p to be sbasis.
+ \param p the Bernstein basis polynomial
+ \returns the Symmetric basis polynomial
+
+ if the degree is even q is the order in the symmetrical power basis,
+ if the degree is odd q is the order + 1
+ n is always the polynomial degree, i. e. the Bezier order
+*/
+void bezier_to_sbasis (SBasis & sb, Bezier const& bz)
+{
+ size_t n = bz.order();
+ size_t q = (n+1) / 2;
+ size_t even = (n & 1u) ? 0 : 1;
+ sb.clear();
+ sb.resize(q + even, Linear(0, 0));
+ int nck = 1;
+ for (size_t k = 0; k < q; ++k)
+ {
+ int Tjk = nck;
+ for (size_t j = k; j < q; ++j)
+ {
+ sb[j][0] += (Tjk * bz[k]);
+ sb[j][1] += (Tjk * bz[n-k]); // n-j <-> [j][1]
+ // assert(Tjk == sgn(j, k) * binomial(n-j-k, j-k) * binomial(n, k));
+ binomial_increment_k(Tjk, n-j-k, j-k);
+ binomial_decrement_n(Tjk, n-j-k, j-k+1);
+ Tjk = -Tjk;
+ }
+ Tjk = -nck;
+ for (size_t j = k+1; j < q; ++j)
+ {
+ sb[j][0] += (Tjk * bz[n-k]);
+ sb[j][1] += (Tjk * bz[k]); // n-j <-> [j][1]
+ // assert(Tjk == sgn(j, k) * binomial(n-j-k-1, j-k-1) * binomial(n, k));
+ binomial_increment_k(Tjk, n-j-k-1, j-k-1);
+ binomial_decrement_n(Tjk, n-j-k-1, j-k);
+ Tjk = -Tjk;
+ }
+ // assert(nck == binomial(n, k));
+ binomial_increment_k(nck, n, k);
+ }
+ if (even)
+ {
+ int Tjk = q & 1 ? -1 : 1;
+ for (size_t k = 0; k < q; ++k)
+ {
+ sb[q][0] += (Tjk * (bz[k] + bz[n-k]));
+ // assert(Tjk == sgn(q,k) * binomial(n, k));
+ binomial_increment_k(Tjk, n, k);
+ Tjk = -Tjk;
+ }
+ // assert(Tjk == binomial(n, q));
+ sb[q][0] += Tjk * bz[q];
+ sb[q][1] = sb[q][0];
+ }
+ sb[0][0] = bz[0];
+ sb[0][1] = bz[n];
+}
+
+/** Changes the basis of d2 p to be sbasis.
+ \param p the d2 Bernstein basis polynomial
+ \returns the d2 Symmetric basis polynomial
+
+ if the degree is even q is the order in the symmetrical power basis,
+ if the degree is odd q is the order + 1
+ n is always the polynomial degree, i. e. the Bezier order
+*/
+void bezier_to_sbasis (D2<SBasis> & sb, std::vector<Point> const& bz)
+{
+ size_t n = bz.size() - 1;
+ size_t q = (n+1) / 2;
+ size_t even = (n & 1u) ? 0 : 1;
+ sb[X].clear();
+ sb[Y].clear();
+ sb[X].resize(q + even, Linear(0, 0));
+ sb[Y].resize(q + even, Linear(0, 0));
+ int nck = 1;
+ for (size_t k = 0; k < q; ++k)
+ {
+ int Tjk = nck;
+ for (size_t j = k; j < q; ++j)
+ {
+ sb[X][j][0] += (Tjk * bz[k][X]);
+ sb[X][j][1] += (Tjk * bz[n-k][X]);
+ sb[Y][j][0] += (Tjk * bz[k][Y]);
+ sb[Y][j][1] += (Tjk * bz[n-k][Y]);
+ // assert(Tjk == sgn(j, k) * binomial(n-j-k, j-k) * binomial(n, k));
+ binomial_increment_k(Tjk, n-j-k, j-k);
+ binomial_decrement_n(Tjk, n-j-k, j-k+1);
+ Tjk = -Tjk;
+ }
+ Tjk = -nck;
+ for (size_t j = k+1; j < q; ++j)
+ {
+ sb[X][j][0] += (Tjk * bz[n-k][X]);
+ sb[X][j][1] += (Tjk * bz[k][X]);
+ sb[Y][j][0] += (Tjk * bz[n-k][Y]);
+ sb[Y][j][1] += (Tjk * bz[k][Y]);
+ // assert(Tjk == sgn(j, k) * binomial(n-j-k-1, j-k-1) * binomial(n, k));
+ binomial_increment_k(Tjk, n-j-k-1, j-k-1);
+ binomial_decrement_n(Tjk, n-j-k-1, j-k);
+ Tjk = -Tjk;
+ }
+ // assert(nck == binomial(n, k));
+ binomial_increment_k(nck, n, k);
+ }
+ if (even)
+ {
+ int Tjk = q & 1 ? -1 : 1;
+ for (size_t k = 0; k < q; ++k)
+ {
+ sb[X][q][0] += (Tjk * (bz[k][X] + bz[n-k][X]));
+ sb[Y][q][0] += (Tjk * (bz[k][Y] + bz[n-k][Y]));
+ // assert(Tjk == sgn(q,k) * binomial(n, k));
+ binomial_increment_k(Tjk, n, k);
+ Tjk = -Tjk;
+ }
+ // assert(Tjk == binomial(n, q));
+ sb[X][q][0] += Tjk * bz[q][X];
+ sb[X][q][1] = sb[X][q][0];
+ sb[Y][q][0] += Tjk * bz[q][Y];
+ sb[Y][q][1] = sb[Y][q][0];
+ }
+ sb[X][0][0] = bz[0][X];
+ sb[X][0][1] = bz[n][X];
+ sb[Y][0][0] = bz[0][Y];
+ sb[Y][0][1] = bz[n][Y];
+}
+
+} // namespace Geom
+
+#if 0
+/*
+* This version works by inverting a reasonable upper bound on the error term after subdividing the
+* curve at $a$. We keep biting off pieces until there is no more curve left.
+*
+* Derivation: The tail of the power series is $a_ks^k + a_{k+1}s^{k+1} + \ldots = e$. A
+* subdivision at $a$ results in a tail error of $e*A^k, A = (1-a)a$. Let this be the desired
+* tolerance tol $= e*A^k$ and invert getting $A = e^{1/k}$ and $a = 1/2 - \sqrt{1/4 - A}$
+*/
+void
+subpath_from_sbasis_incremental(Geom::OldPathSetBuilder &pb, D2<SBasis> B, double tol, bool initial) {
+ const unsigned k = 2; // cubic bezier
+ double te = B.tail_error(k);
+ assert(B[0].std::isfinite());
+ assert(B[1].std::isfinite());
+
+ //std::cout << "tol = " << tol << std::endl;
+ while(1) {
+ double A = std::sqrt(tol/te); // pow(te, 1./k)
+ double a = A;
+ if(A < 1) {
+ A = std::min(A, 0.25);
+ a = 0.5 - std::sqrt(0.25 - A); // quadratic formula
+ if(a > 1) a = 1; // clamp to the end of the segment
+ } else
+ a = 1;
+ assert(a > 0);
+ //std::cout << "te = " << te << std::endl;
+ //std::cout << "A = " << A << "; a=" << a << std::endl;
+ D2<SBasis> Bs = compose(B, Linear(0, a));
+ assert(Bs.tail_error(k));
+ std::vector<Geom::Point> bez = sbasis_to_bezier(Bs, 2);
+ reverse(bez.begin(), bez.end());
+ if (initial) {
+ pb.start_subpath(bez[0]);
+ initial = false;
+ }
+ pb.push_cubic(bez[1], bez[2], bez[3]);
+
+// move to next piece of curve
+ if(a >= 1) break;
+ B = compose(B, Linear(a, 1));
+ te = B.tail_error(k);
+ }
+}
+
+#endif
+
+namespace Geom{
+
+/** Make a path from a d2 sbasis.
+ \param p the d2 Symmetric basis polynomial
+ \returns a Path
+
+ If only_cubicbeziers is true, the resulting path may only contain CubicBezier curves.
+*/
+void build_from_sbasis(Geom::PathBuilder &pb, D2<SBasis> const &B, double tol, bool only_cubicbeziers) {
+ if (!B.isFinite()) {
+ THROW_EXCEPTION("assertion failed: B.isFinite()");
+ }
+ if(tail_error(B, 3) < tol || sbasis_size(B) == 2) { // nearly cubic enough
+ if( !only_cubicbeziers && (sbasis_size(B) <= 1) ) {
+ pb.lineTo(B.at1());
+ } else {
+ std::vector<Geom::Point> bez;
+// sbasis_to_bezier(bez, B, 4);
+ sbasis_to_cubic_bezier(bez, B);
+ pb.curveTo(bez[1], bez[2], bez[3]);
+ }
+ } else {
+ build_from_sbasis(pb, compose(B, Linear(0, 0.5)), tol, only_cubicbeziers);
+ build_from_sbasis(pb, compose(B, Linear(0.5, 1)), tol, only_cubicbeziers);
+ }
+}
+
+/** Make a path from a d2 sbasis.
+ \param p the d2 Symmetric basis polynomial
+ \returns a Path
+
+ If only_cubicbeziers is true, the resulting path may only contain CubicBezier curves.
+*/
+Path
+path_from_sbasis(D2<SBasis> const &B, double tol, bool only_cubicbeziers) {
+ PathBuilder pb;
+ pb.moveTo(B.at0());
+ build_from_sbasis(pb, B, tol, only_cubicbeziers);
+ pb.flush();
+ return pb.peek().front();
+}
+
+/** Make a path from a d2 sbasis.
+ \param p the d2 Symmetric basis polynomial
+ \returns a Path
+
+ If only_cubicbeziers is true, the resulting path may only contain CubicBezier curves.
+ TODO: some of this logic should be lifted into svg-path
+*/
+PathVector
+path_from_piecewise(Geom::Piecewise<Geom::D2<Geom::SBasis> > const &B, double tol, bool only_cubicbeziers) {
+ Geom::PathBuilder pb;
+ if(B.size() == 0) return pb.peek();
+ Geom::Point start = B[0].at0();
+ pb.moveTo(start);
+ for(unsigned i = 0; ; i++) {
+ if ( (i+1 == B.size())
+ || !are_near(B[i+1].at0(), B[i].at1(), tol) )
+ {
+ //start of a new path
+ if (are_near(start, B[i].at1()) && sbasis_size(B[i]) <= 1) {
+ pb.closePath();
+ //last line seg already there (because of .closePath())
+ goto no_add;
+ }
+ build_from_sbasis(pb, B[i], tol, only_cubicbeziers);
+ if (are_near(start, B[i].at1())) {
+ //it's closed, the last closing segment was not a straight line so it needed to be added, but still make it closed here with degenerate straight line.
+ pb.closePath();
+ }
+ no_add:
+ if (i+1 >= B.size()) {
+ break;
+ }
+ start = B[i+1].at0();
+ pb.moveTo(start);
+ } else {
+ build_from_sbasis(pb, B[i], tol, only_cubicbeziers);
+ }
+ }
+ pb.flush();
+ return pb.peek();
+}
+
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/sbasis.cpp b/src/3rdparty/2geom/src/2geom/sbasis.cpp
new file mode 100644
index 0000000..ceaae3f
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/sbasis.cpp
@@ -0,0 +1,681 @@
+/*
+ * sbasis.cpp - S-power basis function class + supporting classes
+ *
+ * Authors:
+ * Nathan Hurst <njh@mail.csse.monash.edu.au>
+ * Michael Sloan <mgsloan@gmail.com>
+ *
+ * Copyright (C) 2006-2007 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <cmath>
+
+#include <2geom/sbasis.h>
+#include <2geom/math-utils.h>
+
+namespace Geom {
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
+/** bound the error from term truncation
+ \param tail first term to chop
+ \returns the largest possible error this truncation could give
+*/
+double SBasis::tailError(unsigned tail) const {
+ Interval bs = *bounds_fast(*this, tail);
+ return std::max(fabs(bs.min()),fabs(bs.max()));
+}
+
+/** test all coefficients are finite
+*/
+bool SBasis::isFinite() const {
+ for(unsigned i = 0; i < size(); i++) {
+ if(!(*this)[i].isFinite())
+ return false;
+ }
+ return true;
+}
+
+/** Compute the value and the first n derivatives
+ \param t position to evaluate
+ \param n number of derivatives (not counting value)
+ \returns a vector with the value and the n derivative evaluations
+
+There is an elegant way to compute the value and n derivatives for a polynomial using a variant of horner's rule. Someone will someday work out how for sbasis.
+*/
+std::vector<double> SBasis::valueAndDerivatives(double t, unsigned n) const {
+ std::vector<double> ret(n+1);
+ ret[0] = valueAt(t);
+ SBasis tmp = *this;
+ for(unsigned i = 1; i < n+1; i++) {
+ tmp.derive();
+ ret[i] = tmp.valueAt(t);
+ }
+ return ret;
+}
+
+
+/** Compute the pointwise sum of a and b (Exact)
+ \param a,b sbasis functions
+ \returns sbasis equal to a+b
+
+*/
+SBasis operator+(const SBasis& a, const SBasis& b) {
+ const unsigned out_size = std::max(a.size(), b.size());
+ const unsigned min_size = std::min(a.size(), b.size());
+ SBasis result(out_size, Linear());
+
+ for(unsigned i = 0; i < min_size; i++) {
+ result[i] = a[i] + b[i];
+ }
+ for(unsigned i = min_size; i < a.size(); i++)
+ result[i] = a[i];
+ for(unsigned i = min_size; i < b.size(); i++)
+ result[i] = b[i];
+
+ assert(result.size() == out_size);
+ return result;
+}
+
+/** Compute the pointwise difference of a and b (Exact)
+ \param a,b sbasis functions
+ \returns sbasis equal to a-b
+
+*/
+SBasis operator-(const SBasis& a, const SBasis& b) {
+ const unsigned out_size = std::max(a.size(), b.size());
+ const unsigned min_size = std::min(a.size(), b.size());
+ SBasis result(out_size, Linear());
+
+ for(unsigned i = 0; i < min_size; i++) {
+ result[i] = a[i] - b[i];
+ }
+ for(unsigned i = min_size; i < a.size(); i++)
+ result[i] = a[i];
+ for(unsigned i = min_size; i < b.size(); i++)
+ result[i] = -b[i];
+
+ assert(result.size() == out_size);
+ return result;
+}
+
+/** Compute the pointwise sum of a and b and store in a (Exact)
+ \param a,b sbasis functions
+ \returns sbasis equal to a+b
+
+*/
+SBasis& operator+=(SBasis& a, const SBasis& b) {
+ const unsigned out_size = std::max(a.size(), b.size());
+ const unsigned min_size = std::min(a.size(), b.size());
+ a.resize(out_size);
+
+ for(unsigned i = 0; i < min_size; i++)
+ a[i] += b[i];
+ for(unsigned i = min_size; i < b.size(); i++)
+ a[i] = b[i];
+
+ assert(a.size() == out_size);
+ return a;
+}
+
+/** Compute the pointwise difference of a and b and store in a (Exact)
+ \param a,b sbasis functions
+ \returns sbasis equal to a-b
+
+*/
+SBasis& operator-=(SBasis& a, const SBasis& b) {
+ const unsigned out_size = std::max(a.size(), b.size());
+ const unsigned min_size = std::min(a.size(), b.size());
+ a.resize(out_size);
+
+ for(unsigned i = 0; i < min_size; i++)
+ a[i] -= b[i];
+ for(unsigned i = min_size; i < b.size(); i++)
+ a[i] = -b[i];
+
+ assert(a.size() == out_size);
+ return a;
+}
+
+/** Compute the pointwise product of a and b (Exact)
+ \param a,b sbasis functions
+ \returns sbasis equal to a*b
+
+*/
+SBasis operator*(SBasis const &a, double k) {
+ SBasis c(a.size(), Linear());
+ for(unsigned i = 0; i < a.size(); i++)
+ c[i] = a[i] * k;
+ return c;
+}
+
+/** Compute the pointwise product of a and b and store the value in a (Exact)
+ \param a,b sbasis functions
+ \returns sbasis equal to a*b
+
+*/
+SBasis& operator*=(SBasis& a, double b) {
+ if (a.isZero()) return a;
+ if (b == 0)
+ a.clear();
+ else
+ for(auto & i : a)
+ i *= b;
+ return a;
+}
+
+/** multiply a by x^sh in place (Exact)
+ \param a sbasis function
+ \param sh power
+ \returns a
+
+*/
+SBasis shift(SBasis const &a, int sh) {
+ size_t n = a.size()+sh;
+ SBasis c(n, Linear());
+ size_t m = std::max(0, sh);
+
+ for(int i = 0; i < sh; i++)
+ c[i] = Linear(0,0);
+ for(size_t i = m, j = std::max(0,-sh); i < n; i++, j++)
+ c[i] = a[j];
+ return c;
+}
+
+/** multiply a by x^sh (Exact)
+ \param a linear function
+ \param sh power
+ \returns a* x^sh
+
+*/
+SBasis shift(Linear const &a, int sh) {
+ size_t n = 1+sh;
+ SBasis c(n, Linear());
+
+ for(int i = 0; i < sh; i++)
+ c[i] = Linear(0,0);
+ if(sh >= 0)
+ c[sh] = a;
+ return c;
+}
+
+#if 0
+SBasis multiply(SBasis const &a, SBasis const &b) {
+ // c = {a0*b0 - shift(1, a.Tri*b.Tri), a1*b1 - shift(1, a.Tri*b.Tri)}
+
+ // shift(1, a.Tri*b.Tri)
+ SBasis c(a.size() + b.size(), Linear(0,0));
+ if(a.isZero() || b.isZero())
+ return c;
+ for(unsigned j = 0; j < b.size(); j++) {
+ for(unsigned i = j; i < a.size()+j; i++) {
+ double tri = b[j].tri()*a[i-j].tri();
+ c[i+1/*shift*/] += Linear(-tri);
+ }
+ }
+ for(unsigned j = 0; j < b.size(); j++) {
+ for(unsigned i = j; i < a.size()+j; i++) {
+ for(unsigned dim = 0; dim < 2; dim++)
+ c[i][dim] += b[j][dim]*a[i-j][dim];
+ }
+ }
+ c.normalize();
+ //assert(!(0 == c.back()[0] && 0 == c.back()[1]));
+ return c;
+}
+#else
+
+/** Compute the pointwise product of a and b adding c (Exact)
+ \param a,b,c sbasis functions
+ \returns sbasis equal to a*b+c
+
+The added term is almost free
+*/
+SBasis multiply_add(SBasis const &a, SBasis const &b, SBasis c) {
+ if(a.isZero() || b.isZero())
+ return c;
+ c.resize(a.size() + b.size(), Linear(0,0));
+ for(unsigned j = 0; j < b.size(); j++) {
+ for(unsigned i = j; i < a.size()+j; i++) {
+ double tri = b[j].tri()*a[i-j].tri();
+ c[i+1/*shift*/] += Linear(-tri);
+ }
+ }
+ for(unsigned j = 0; j < b.size(); j++) {
+ for(unsigned i = j; i < a.size()+j; i++) {
+ for(unsigned dim = 0; dim < 2; dim++)
+ c[i][dim] += b[j][dim]*a[i-j][dim];
+ }
+ }
+ c.normalize();
+ //assert(!(0 == c.back()[0] && 0 == c.back()[1]));
+ return c;
+}
+
+/** Compute the pointwise product of a and b (Exact)
+ \param a,b sbasis functions
+ \returns sbasis equal to a*b
+
+*/
+SBasis multiply(SBasis const &a, SBasis const &b) {
+ if(a.isZero() || b.isZero()) {
+ SBasis c(1, Linear(0,0));
+ return c;
+ }
+ SBasis c(a.size() + b.size(), Linear(0,0));
+ return multiply_add(a, b, c);
+}
+#endif
+/** Compute the integral of a (Exact)
+ \param a sbasis functions
+ \returns sbasis integral(a)
+
+*/
+SBasis integral(SBasis const &c) {
+ SBasis a;
+ a.resize(c.size() + 1, Linear(0,0));
+ a[0] = Linear(0,0);
+
+ for(unsigned k = 1; k < c.size() + 1; k++) {
+ double ahat = -c[k-1].tri()/(2*k);
+ a[k][0] = a[k][1] = ahat;
+ }
+ double aTri = 0;
+ for(int k = c.size()-1; k >= 0; k--) {
+ aTri = (c[k].hat() + (k+1)*aTri/2)/(2*k+1);
+ a[k][0] -= aTri/2;
+ a[k][1] += aTri/2;
+ }
+ a.normalize();
+ return a;
+}
+
+/** Compute the derivative of a (Exact)
+ \param a sbasis functions
+ \returns sbasis da/dt
+
+*/
+SBasis derivative(SBasis const &a) {
+ SBasis c;
+ c.resize(a.size(), Linear(0,0));
+ if(a.isZero())
+ return c;
+
+ for(unsigned k = 0; k < a.size()-1; k++) {
+ double d = (2*k+1)*(a[k][1] - a[k][0]);
+
+ c[k][0] = d + (k+1)*a[k+1][0];
+ c[k][1] = d - (k+1)*a[k+1][1];
+ }
+ int k = a.size()-1;
+ double d = (2*k+1)*(a[k][1] - a[k][0]);
+ if (d == 0 && k > 0) {
+ c.pop_back();
+ } else {
+ c[k][0] = d;
+ c[k][1] = d;
+ }
+
+ return c;
+}
+
+/** Compute the derivative of this inplace (Exact)
+
+*/
+void SBasis::derive() { // in place version
+ if(isZero()) return;
+ for(unsigned k = 0; k < size()-1; k++) {
+ double d = (2*k+1)*((*this)[k][1] - (*this)[k][0]);
+
+ (*this)[k][0] = d + (k+1)*(*this)[k+1][0];
+ (*this)[k][1] = d - (k+1)*(*this)[k+1][1];
+ }
+ int k = size()-1;
+ double d = (2*k+1)*((*this)[k][1] - (*this)[k][0]);
+ if (d == 0 && k > 0) {
+ pop_back();
+ } else {
+ (*this)[k][0] = d;
+ (*this)[k][1] = d;
+ }
+}
+
+/** Compute the sqrt of a
+ \param a sbasis functions
+ \returns sbasis \f[ \sqrt{a} \f]
+
+It is recommended to use the piecewise version unless you have good reason.
+TODO: convert int k to unsigned k, and remove cast
+*/
+SBasis sqrt(SBasis const &a, int k) {
+ SBasis c;
+ if(a.isZero() || k == 0)
+ return c;
+ c.resize(k, Linear(0,0));
+ c[0] = Linear(std::sqrt(a[0][0]), std::sqrt(a[0][1]));
+ SBasis r = a - multiply(c, c); // remainder
+
+ for(unsigned i = 1; i <= (unsigned)k && i<r.size(); i++) {
+ Linear ci(r[i][0]/(2*c[0][0]), r[i][1]/(2*c[0][1]));
+ SBasis cisi = shift(ci, i);
+ r -= multiply(shift((c*2 + cisi), i), SBasis(ci));
+ r.truncate(k+1);
+ c += cisi;
+ if(r.tailError(i) == 0) // if exact
+ break;
+ }
+
+ return c;
+}
+
+/** Compute the recpirocal of a
+ \param a sbasis functions
+ \returns sbasis 1/a
+
+It is recommended to use the piecewise version unless you have good reason.
+*/
+SBasis reciprocal(Linear const &a, int k) {
+ SBasis c;
+ assert(!a.isZero());
+ c.resize(k, Linear(0,0));
+ double r_s0 = (a.tri()*a.tri())/(-a[0]*a[1]);
+ double r_s0k = 1;
+ for(unsigned i = 0; i < (unsigned)k; i++) {
+ c[i] = Linear(r_s0k/a[0], r_s0k/a[1]);
+ r_s0k *= r_s0;
+ }
+ return c;
+}
+
+/** Compute a / b to k terms
+ \param a,b sbasis functions
+ \returns sbasis a/b
+
+It is recommended to use the piecewise version unless you have good reason.
+*/
+SBasis divide(SBasis const &a, SBasis const &b, int k) {
+ SBasis c;
+ assert(!a.isZero());
+ SBasis r = a; // remainder
+
+ k++;
+ r.resize(k, Linear(0,0));
+ c.resize(k, Linear(0,0));
+
+ for(unsigned i = 0; i < (unsigned)k; i++) {
+ Linear ci(r[i][0]/b[0][0], r[i][1]/b[0][1]); //H0
+ c[i] += ci;
+ r -= shift(multiply(ci,b), i);
+ r.truncate(k+1);
+ if(r.tailError(i) == 0) // if exact
+ break;
+ }
+
+ return c;
+}
+
+/** Compute a composed with b
+ \param a,b sbasis functions
+ \returns sbasis a(b(t))
+
+ return a0 + s(a1 + s(a2 +... where s = (1-u)u; ak =(1 - u)a^0_k + ua^1_k
+*/
+SBasis compose(SBasis const &a, SBasis const &b) {
+ SBasis s = multiply((SBasis(Linear(1,1))-b), b);
+ SBasis r;
+
+ for(int i = a.size()-1; i >= 0; i--) {
+ r = multiply_add(r, s, SBasis(Linear(a[i][0])) - b*a[i][0] + b*a[i][1]);
+ }
+ return r;
+}
+
+/** Compute a composed with b to k terms
+ \param a,b sbasis functions
+ \returns sbasis a(b(t))
+
+ return a0 + s(a1 + s(a2 +... where s = (1-u)u; ak =(1 - u)a^0_k + ua^1_k
+*/
+SBasis compose(SBasis const &a, SBasis const &b, unsigned k) {
+ SBasis s = multiply((SBasis(Linear(1,1))-b), b);
+ SBasis r;
+
+ for(int i = a.size()-1; i >= 0; i--) {
+ r = multiply_add(r, s, SBasis(Linear(a[i][0])) - b*a[i][0] + b*a[i][1]);
+ }
+ r.truncate(k);
+ return r;
+}
+
+SBasis portion(const SBasis &t, double from, double to) {
+ double fv = t.valueAt(from);
+ double tv = t.valueAt(to);
+ SBasis ret = compose(t, Linear(from, to));
+ ret.at0() = fv;
+ ret.at1() = tv;
+ return ret;
+}
+
+/*
+Inversion algorithm. The notation is certainly very misleading. The
+pseudocode should say:
+
+c(v) := 0
+r(u) := r_0(u) := u
+for i:=0 to k do
+ c_i(v) := H_0(r_i(u)/(t_1)^i; u)
+ c(v) := c(v) + c_i(v)*t^i
+ r(u) := r(u) ? c_i(u)*(t(u))^i
+endfor
+*/
+
+//#define DEBUG_INVERSION 1
+
+/** find the function a^-1 such that a^-1 composed with a to k terms is the identity function
+ \param a sbasis function
+ \returns sbasis a^-1 s.t. a^-1(a(t)) = 1
+
+ The function must have 'unit range'("a00 = 0 and a01 = 1") and be monotonic.
+*/
+SBasis inverse(SBasis a, int k) {
+ assert(a.size() > 0);
+ double a0 = a[0][0];
+ if(a0 != 0) {
+ a -= a0;
+ }
+ double a1 = a[0][1];
+ assert(a1 != 0); // not invertable.
+
+ if(a1 != 1) {
+ a /= a1;
+ }
+ SBasis c(k, Linear()); // c(v) := 0
+ if(a.size() >= 2 && k == 2) {
+ c[0] = Linear(0,1);
+ Linear t1(1+a[1][0], 1-a[1][1]); // t_1
+ c[1] = Linear(-a[1][0]/t1[0], -a[1][1]/t1[1]);
+ } else if(a.size() >= 2) { // non linear
+ SBasis r = Linear(0,1); // r(u) := r_0(u) := u
+ Linear t1(1./(1+a[1][0]), 1./(1-a[1][1])); // 1./t_1
+ Linear one(1,1);
+ Linear t1i = one; // t_1^0
+ SBasis one_minus_a = SBasis(one) - a;
+ SBasis t = multiply(one_minus_a, a); // t(u)
+ SBasis ti(one); // t(u)^0
+#ifdef DEBUG_INVERSION
+ std::cout << "a=" << a << std::endl;
+ std::cout << "1-a=" << one_minus_a << std::endl;
+ std::cout << "t1=" << t1 << std::endl;
+ //assert(t1 == t[1]);
+#endif
+
+ //c.resize(k+1, Linear(0,0));
+ for(unsigned i = 0; i < (unsigned)k; i++) { // for i:=0 to k do
+#ifdef DEBUG_INVERSION
+ std::cout << "-------" << i << ": ---------" <<std::endl;
+ std::cout << "r=" << r << std::endl
+ << "c=" << c << std::endl
+ << "ti=" << ti << std::endl
+ << std::endl;
+#endif
+ if(r.size() <= i) // ensure enough space in the remainder, probably not needed
+ r.resize(i+1, Linear(0,0));
+ Linear ci(r[i][0]*t1i[0], r[i][1]*t1i[1]); // c_i(v) := H_0(r_i(u)/(t_1)^i; u)
+#ifdef DEBUG_INVERSION
+ std::cout << "t1i=" << t1i << std::endl;
+ std::cout << "ci=" << ci << std::endl;
+#endif
+ for(int dim = 0; dim < 2; dim++) // t1^-i *= 1./t1
+ t1i[dim] *= t1[dim];
+ c[i] = ci; // c(v) := c(v) + c_i(v)*t^i
+ // change from v to u parameterisation
+ SBasis civ = one_minus_a*ci[0] + a*ci[1];
+ // r(u) := r(u) - c_i(u)*(t(u))^i
+ // We can truncate this to the number of final terms, as no following terms can
+ // contribute to the result.
+ r -= multiply(civ,ti);
+ r.truncate(k);
+ if(r.tailError(i) == 0)
+ break; // yay!
+ ti = multiply(ti,t);
+ }
+#ifdef DEBUG_INVERSION
+ std::cout << "##########################" << std::endl;
+#endif
+ } else
+ c = Linear(0,1); // linear
+ c -= a0; // invert the offset
+ c /= a1; // invert the slope
+ return c;
+}
+
+/** Compute the sine of a to k terms
+ \param b linear function
+ \returns sbasis sin(a)
+
+It is recommended to use the piecewise version unless you have good reason.
+*/
+SBasis sin(Linear b, int k) {
+ SBasis s(k+2, Linear());
+ s[0] = Linear(std::sin(b[0]), std::sin(b[1]));
+ double tr = s[0].tri();
+ double t2 = b.tri();
+ s[1] = Linear(std::cos(b[0])*t2 - tr, -std::cos(b[1])*t2 + tr);
+
+ t2 *= t2;
+ for(int i = 0; i < k; i++) {
+ Linear bo(4*(i+1)*s[i+1][0] - 2*s[i+1][1],
+ -2*s[i+1][0] + 4*(i+1)*s[i+1][1]);
+ bo -= s[i]*(t2/(i+1));
+
+
+ s[i+2] = bo/double(i+2);
+ }
+
+ return s;
+}
+
+/** Compute the cosine of a
+ \param b linear function
+ \returns sbasis cos(a)
+
+It is recommended to use the piecewise version unless you have good reason.
+*/
+SBasis cos(Linear bo, int k) {
+ return sin(Linear(bo[0] + M_PI/2,
+ bo[1] + M_PI/2),
+ k);
+}
+
+/** compute fog^-1.
+ \param f,g sbasis functions
+ \returns sbasis f(g^-1(t)).
+
+("zero" = double comparison threshold. *!*we might divide by "zero"*!*)
+TODO: compute order according to tol?
+TODO: requires g(0)=0 & g(1)=1 atm... adaptation to other cases should be obvious!
+*/
+SBasis compose_inverse(SBasis const &f, SBasis const &g, unsigned order, double zero){
+ SBasis result(order, Linear(0.)); //result
+ SBasis r=f; //remainder
+ SBasis Pk=Linear(1)-g,Qk=g,sg=Pk*Qk;
+ Pk.truncate(order);
+ Qk.truncate(order);
+ Pk.resize(order,Linear(0.));
+ Qk.resize(order,Linear(0.));
+ r.resize(order,Linear(0.));
+
+ int vs = valuation(sg,zero);
+ if (vs == 0) { // to prevent infinite loop
+ return result;
+ }
+
+ for (unsigned k=0; k<order; k+=vs){
+ double p10 = Pk.at(k)[0];// we have to solve the linear system:
+ double p01 = Pk.at(k)[1];//
+ double q10 = Qk.at(k)[0];// p10*a + q10*b = r10
+ double q01 = Qk.at(k)[1];// &
+ double r10 = r.at(k)[0];// p01*a + q01*b = r01
+ double r01 = r.at(k)[1];//
+ double a,b;
+ double det = p10*q01-p01*q10;
+
+ //TODO: handle det~0!!
+ if (fabs(det)<zero){
+ a=b=0;
+ }else{
+ a=( q01*r10-q10*r01)/det;
+ b=(-p01*r10+p10*r01)/det;
+ }
+ result[k] = Linear(a,b);
+ r=r-Pk*a-Qk*b;
+
+ Pk=Pk*sg;
+ Qk=Qk*sg;
+
+ Pk.resize(order,Linear(0.)); // truncates if too high order, expands with zeros if too low
+ Qk.resize(order,Linear(0.));
+ r.resize(order,Linear(0.));
+
+ }
+ result.normalize();
+ return result;
+}
+
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/self-intersect.cpp b/src/3rdparty/2geom/src/2geom/self-intersect.cpp
new file mode 100644
index 0000000..4fe4d9e
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/self-intersect.cpp
@@ -0,0 +1,313 @@
+/**
+ * @file Implementation of Path::intersectSelf() and PathVector::intersectSelf().
+ */
+/* An algorithm for finding self-intersections of paths and path-vectors.
+ *
+ * Authors:
+ * Rafał Siejakowski <rs@rs-math.net>
+ *
+ * (C) Copyright 2022 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <list>
+
+#include <2geom/coord.h>
+#include <2geom/curve.h>
+#include <2geom/path.h>
+#include <2geom/pathvector.h>
+#include <2geom/point.h>
+#include <2geom/sweeper.h>
+
+namespace Geom {
+
+/** @brief The PathSelfIntersector class is a sweepset class used for intersecting curves in the
+ * same path with one another. It is intended to be used as the template parameter of Sweeper.
+ */
+class PathSelfIntersector
+{
+public:
+ using ItemIterator = Path::iterator;
+
+private:
+ Path _path; ///< The path searched for self-crossings, cleaned of degenerate curves.
+ std::list<ItemIterator> _active; ///< List of active curves during the sweepline passage.
+ std::vector<PathIntersection> _crossings; ///< Stores the crossings found.
+ std::vector<size_t> _original_indices; ///< Curve indices before removal of degenerate curves.
+ double const _precision; ///< Numerical epsilon.
+
+public:
+ PathSelfIntersector(Path const &path, double precision)
+ : _path{path.initialPoint()}
+ , _precision{precision}
+ {
+ _original_indices.reserve(path.size());
+ for (size_t i = 0; i < path.size(); i++) {
+ if (!path[i].isDegenerate()) {
+ _path.append(path[i]);
+ _original_indices.push_back(i);
+ }
+ }
+ _path.close(path.closed());
+ }
+
+ // === SweepSet API ===
+ auto &items() { return _path; }
+ Interval itemBounds(ItemIterator curve) const { return curve->boundsFast()[X]; }
+ /// Callback for when the sweepline starts intersecting a new item.
+ void addActiveItem(ItemIterator incoming)
+ {
+ _intersectWithActive(incoming);
+ _intersectWithSelf(incoming);
+ _active.push_back(incoming);
+ }
+ /// Callback for when the sweepline stops intersecting an item.
+ void removeActiveItem(ItemIterator to_remove)
+ {
+ auto it = std::find(_active.begin(), _active.end(), to_remove);
+ _active.erase(it);
+ }
+ // ===
+
+ std::vector<PathIntersection> &&moveOutCrossings() { return std::move(_crossings); }
+
+private:
+ /** Find and store all intersections of a curve with itself. */
+ void _intersectWithSelf(ItemIterator curve)
+ {
+ size_t const index = std::distance(_path.begin(), curve);
+ for (auto &&self_x : curve->intersectSelf(_precision)) {
+ _appendCurveCrossing(std::move(self_x), index, index);
+ }
+ }
+
+ /** Find and store all intersections of a curve with the active curves. */
+ void _intersectWithActive(ItemIterator curve)
+ {
+ size_t const index = std::distance(_path.begin(), curve);
+ for (auto const &other : _active) {
+ if (!curve->boundsFast().intersects(other->boundsFast())) {
+ continue;
+ }
+
+ size_t const other_index = std::distance(_path.begin(), other);
+ auto const &[smaller, larger] = std::minmax(index, other_index);
+ /// Whether the curves meet at a common node in the path.
+ bool consecutive = smaller + 1 == larger;
+ /// Whether the curves meet at the closure point of the path.
+ bool wraparound = _path.closed() && smaller == 0 && larger + 1 == _path.size();
+ for (auto &&xing : curve->intersect(*other, _precision)) {
+ _appendCurveCrossing(std::move(xing), index, other_index, consecutive, wraparound);
+ }
+ }
+ }
+
+ /** Append a curve crossing to the store as long as it satisfies nondegeneracy criteria. */
+ void _appendCurveCrossing(CurveIntersection &&xing, size_t first_index, size_t second_index,
+ bool consecutive = false, bool wraparound = false)
+ {
+ // Filter out crossings that aren't real but rather represent the agreement of final
+ // and initial points of consecutive curves – a consequence of the path's continuity.
+ auto const should_exclude = [&](bool flipped) -> bool {
+ // Filter out spurious self-intersections by using squared geometric average.
+ bool const first_is_first = (first_index < second_index) ^ flipped;
+ double const geom2 = first_is_first ? (1.0 - xing.first) * xing.second
+ : (1.0 - xing.second) * xing.first;
+ return geom2 < EPSILON;
+ };
+
+ if ((consecutive && should_exclude(false)) || (wraparound && should_exclude(true))) {
+ return;
+ }
+
+ // Convert curve indices to the original ones (before the removal of degenerate curves).
+ _crossings.emplace_back(PathTime(_original_indices[first_index], xing.first),
+ PathTime(_original_indices[second_index], xing.second),
+ xing.point());
+ }
+};
+
+// Compute all crossings of a path with itself.
+std::vector<PathIntersection> Path::intersectSelf(Coord precision) const
+{
+ auto intersector = PathSelfIntersector(*this, precision);
+ Sweeper(intersector).process();
+ auto result = intersector.moveOutCrossings();
+ std::sort(result.begin(), result.end());
+ return result;
+}
+
+/**
+ * @brief The PathVectorSelfIntersector class is an implementation of a SweepSet whose intended
+ * use is the search for self-intersections in a single PathVector. It's designed to be used as
+ * the template parameter for the Sweeper class template.
+ */
+class PathVectorSelfIntersector
+{
+public:
+ using ItemIterator = PathVector::const_iterator;
+
+private:
+ PathVector const &_pathvector; ///< A reference to the path-vector searched for self-crossings.
+ std::list<ItemIterator> _active; ///< A list of active paths during sweepline passage.
+ std::vector<PathVectorIntersection> _crossings; ///< Stores the crossings found.
+ double const _precision; ///< Numerical epsilon.
+
+public:
+ PathVectorSelfIntersector(PathVector const &subject, double precision)
+ : _pathvector{subject}
+ , _precision{precision}
+ {
+ }
+
+ // == SweepSet API ===
+ auto const &items() { return _pathvector; }
+ Interval itemBounds(ItemIterator path)
+ {
+ auto const r = path->boundsFast();
+ return r ? (*r)[X] : Interval(); // Sweeplines are vertical
+ }
+
+ /// Callback for when the sweepline starts intersecting a new item.
+ void addActiveItem(ItemIterator incoming)
+ {
+ _intersectWithActive(incoming);
+ _intersectWithSelf(incoming);
+ _active.push_back(incoming);
+ }
+
+ /// Callback for when the sweepline stops intersecting an item.
+ void removeActiveItem(ItemIterator to_remove)
+ {
+ auto it = std::find(_active.begin(), _active.end(), to_remove);
+ _active.erase(it);
+ }
+ // ===
+
+ std::vector<PathVectorIntersection> &&moveOutCrossings() { return std::move(_crossings); }
+
+private:
+ /**
+ * @brief Find all intersections of the path pointed to by the given
+ * iterator with all currently active paths and store results
+ * in the instance of the class.
+ *
+ * @param it An iterator to a path to be intersected with the active ones.
+ */
+ void _intersectWithActive(ItemIterator &it);
+
+ /**
+ * @brief Find all intersections of the path pointed to by the given
+ * iterator with itself and store the results in the class instance.
+ *
+ * @param it An iterator to a path which will be intersected with itself.
+ */
+ void _intersectWithSelf(ItemIterator &it);
+
+ /// Append a path crossing to the store.
+ void _appendPathCrossing(PathIntersection const &xing, size_t first_index, size_t second_index)
+ {
+ auto const first_time = PathVectorTime(first_index, xing.first);
+ auto const second_time = PathVectorTime(second_index, xing.second);
+ _crossings.emplace_back(first_time, second_time, xing.point());
+ }
+
+public:
+
+ std::vector<PathVectorIntersection>
+ filterDeduplicate(std::vector<PathVectorIntersection> &&xings) const;
+};
+
+/** Remove duplicate intersections (artifacts of the path/curve crossing algorithms). */
+std::vector<PathVectorIntersection>
+PathVectorSelfIntersector::filterDeduplicate(std::vector<PathVectorIntersection> &&xings) const
+{
+ std::vector<PathVectorIntersection> result;
+ result.reserve(xings.size());
+
+ auto const are_same_times = [&](Coord a1, Coord a2, Coord b1, Coord b2) -> bool {
+ return (are_near(a1, b1) && are_near(a2, b2)) ||
+ (are_near(a1, b2) && are_near(a2, b1));
+ };
+
+ Coord last_time_1 = -1.0, last_time_2 = -1.0; // Invalid path times
+ for (auto &&x : xings) {
+ auto const current_1 = x.first.asFlatTime(), current_2 = x.second.asFlatTime();
+ if (!are_same_times(current_1, current_2, last_time_1, last_time_2)) {
+ result.push_back(std::move(x));
+ }
+ last_time_1 = current_1;
+ last_time_2 = current_2;
+ }
+
+ return result;
+}
+
+/** Compute and store intersections of a path with all active paths. */
+void PathVectorSelfIntersector::_intersectWithActive(ItemIterator &it)
+{
+ auto const start = _pathvector.begin();
+ for (auto &path : _active) {
+ if (!path->boundsFast().intersects(it->boundsFast())) {
+ continue;
+ }
+ for (auto &&xing : path->intersect(*it, _precision)) {
+ _appendPathCrossing(std::move(xing), std::distance(start, path),
+ std::distance(start, it));
+ }
+ }
+}
+
+/** Compute and store intersections of a constituent path with itself. */
+void PathVectorSelfIntersector::_intersectWithSelf(ItemIterator &it)
+{
+ size_t const path_index = std::distance(_pathvector.begin(), it);
+ for (auto &&xing : it->intersectSelf(_precision)) {
+ _appendPathCrossing(std::move(xing), path_index, path_index);
+ }
+}
+
+// Compute self-intersections in a path-vector.
+std::vector<PathVectorIntersection> PathVector::intersectSelf(Coord precision) const
+{
+ auto intersector = PathVectorSelfIntersector(*this, precision);
+ Sweeper(intersector).process();
+ auto result = intersector.moveOutCrossings();
+ std::sort(result.begin(), result.end());
+ return (result.size() > 1) ? intersector.filterDeduplicate(std::move(result)) : result;
+}
+
+} // namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/solve-bezier-one-d.cpp b/src/3rdparty/2geom/src/2geom/solve-bezier-one-d.cpp
new file mode 100644
index 0000000..b82d20b
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/solve-bezier-one-d.cpp
@@ -0,0 +1,243 @@
+
+#include <2geom/solver.h>
+#include <2geom/choose.h>
+#include <2geom/bezier.h>
+#include <2geom/point.h>
+
+#include <cmath>
+#include <algorithm>
+//#include <valarray>
+
+/*** Find the zeros of the bernstein function. The code subdivides until it is happy with the
+ * linearity of the function. This requires an O(degree^2) subdivision for each step, even when
+ * there is only one solution.
+ */
+
+namespace Geom {
+
+template<class t>
+static int SGN(t x) { return (x > 0 ? 1 : (x < 0 ? -1 : 0)); }
+
+//const unsigned MAXDEPTH = 23; // Maximum depth for recursion. Using floats means 23 bits precision max
+
+//const double BEPSILON = ldexp(1.0,(-MAXDEPTH-1)); /*Flatness control value */
+//const double SECANT_EPSILON = 1e-13; // secant method converges much faster, get a bit more precision
+/**
+ * This function is called _a lot_. We have included various manual memory management stuff to reduce the amount of mallocing that goes on. In the future it is possible that this will hurt performance.
+ **/
+class Bernsteins
+{
+public:
+ static constexpr size_t MAX_DEPTH = 53;
+ size_t degree, N;
+ std::vector<double> &solutions;
+
+ Bernsteins(size_t _degree, std::vector<double> &sol)
+ : degree(_degree), N(degree+1), solutions(sol)
+ {
+ }
+
+ unsigned
+ control_poly_flat_enough(double const *V);
+
+ void
+ find_bernstein_roots(double const *w, /* The control points */
+ unsigned depth, /* The depth of the recursion */
+ double left_t, double right_t);
+};
+/*
+ * find_bernstein_roots : Given an equation in Bernstein-Bernstein form, find all
+ * of the roots in the open interval (0, 1). Return the number of roots found.
+ */
+void
+find_bernstein_roots(double const *w, /* The control points */
+ unsigned degree, /* The degree of the polynomial */
+ std::vector<double> &solutions, /* RETURN candidate t-values */
+ unsigned depth, /* The depth of the recursion */
+ double left_t, double right_t, bool /*use_secant*/)
+{
+ Bernsteins B(degree, solutions);
+ B.find_bernstein_roots(w, depth, left_t, right_t);
+}
+
+void
+find_bernstein_roots(std::vector<double> &solutions, /* RETURN candidate t-values */
+ Geom::Bezier const &bz, /* The control points */
+ double left_t, double right_t)
+{
+ Bernsteins B(bz.degree(), solutions);
+ Geom::Bezier& bzl = const_cast<Geom::Bezier&>(bz);
+ double* w = &(bzl[0]);
+ B.find_bernstein_roots(w, 0, left_t, right_t);
+}
+
+
+
+void Bernsteins::find_bernstein_roots(double const *w, /* The control points */
+ unsigned depth, /* The depth of the recursion */
+ double left_t,
+ double right_t)
+{
+
+ size_t n_crossings = 0;
+
+ int old_sign = SGN(w[0]);
+ //std::cout << "w[0] = " << w[0] << std::endl;
+ for (size_t i = 1; i < N; i++)
+ {
+ //std::cout << "w[" << i << "] = " << w[i] << std::endl;
+ int sign = SGN(w[i]);
+ if (sign != 0)
+ {
+ if (sign != old_sign && old_sign != 0)
+ {
+ ++n_crossings;
+ }
+ old_sign = sign;
+ }
+ }
+ //std::cout << "n_crossings = " << n_crossings << std::endl;
+ if (n_crossings == 0) return; // no solutions here
+
+ if (n_crossings == 1) /* Unique solution */
+ {
+ //std::cout << "depth = " << depth << std::endl;
+ /* Stop recursion when the tree is deep enough */
+ /* if deep enough, return 1 solution at midpoint */
+ if (depth > MAX_DEPTH)
+ {
+ //printf("bottom out %d\n", depth);
+ const double Ax = right_t - left_t;
+ const double Ay = w[degree] - w[0];
+
+ solutions.push_back(left_t - Ax*w[0] / Ay);
+ return;
+ }
+
+
+ double s = 0, t = 1;
+ double e = 1e-10;
+ int side = 0;
+ double r, fs = w[0], ft = w[degree];
+
+ for (size_t n = 0; n < 100; ++n)
+ {
+ r = (fs*t - ft*s) / (fs - ft);
+ if (fabs(t-s) < e * fabs(t+s)) break;
+
+ double fr = bernstein_value_at(r, w, degree);
+
+ if (fr * ft > 0)
+ {
+ t = r; ft = fr;
+ if (side == -1) fs /= 2;
+ side = -1;
+ }
+ else if (fs * fr > 0)
+ {
+ s = r; fs = fr;
+ if (side == +1) ft /= 2;
+ side = +1;
+ }
+ else break;
+ }
+ solutions.push_back(r*right_t + (1-r)*left_t);
+ return;
+
+ }
+
+ /* Otherwise, solve recursively after subdividing control polygon */
+// double Left[N], /* New left and right */
+// Right[N]; /* control polygons */
+ //const double t = 0.5;
+ double* LR = new double[2*N];
+ double* Left = LR;
+ double* Right = LR + N;
+
+ std::copy(w, w + N, Right);
+
+ Left[0] = Right[0];
+ for (size_t i = 1; i < N; ++i)
+ {
+ for (size_t j = 0; j < N-i; ++j)
+ {
+ Right[j] = (Right[j] + Right[j+1]) * 0.5;
+ }
+ Left[i] = Right[0];
+ }
+
+ double mid_t = (left_t + right_t) * 0.5;
+
+
+ find_bernstein_roots(Left, depth+1, left_t, mid_t);
+
+
+ /* Solution is exactly on the subdivision point. */
+ if (Right[0] == 0)
+ {
+ solutions.push_back(mid_t);
+ }
+
+ find_bernstein_roots(Right, depth+1, mid_t, right_t);
+ delete[] LR;
+}
+
+#if 0
+/*
+ * control_poly_flat_enough :
+ * Check if the control polygon of a Bernstein curve is flat enough
+ * for recursive subdivision to bottom out.
+ *
+ */
+unsigned
+Bernsteins::control_poly_flat_enough(double const *V)
+{
+ /* Find the perpendicular distance from each interior control point to line connecting V[0] and
+ * V[degree] */
+
+ /* Derive the implicit equation for line connecting first */
+ /* and last control points */
+ const double a = V[0] - V[degree];
+
+ double max_distance_above = 0.0;
+ double max_distance_below = 0.0;
+ double ii = 0, dii = 1./degree;
+ for (unsigned i = 1; i < degree; i++) {
+ ii += dii;
+ /* Compute distance from each of the points to that line */
+ const double d = (a + V[i]) * ii - a;
+ double dist = d*d;
+ // Find the largest distance
+ if (d < 0.0)
+ max_distance_below = std::min(max_distance_below, -dist);
+ else
+ max_distance_above = std::max(max_distance_above, dist);
+ }
+
+ const double abSquared = 1./((a * a) + 1);
+
+ const double intercept_1 = (a - max_distance_above * abSquared);
+ const double intercept_2 = (a - max_distance_below * abSquared);
+
+ /* Compute bounding interval*/
+ const double left_intercept = std::min(intercept_1, intercept_2);
+ const double right_intercept = std::max(intercept_1, intercept_2);
+
+ const double error = 0.5 * (right_intercept - left_intercept);
+ //printf("error %g %g %g\n", error, a, BEPSILON * a);
+ return error < BEPSILON * a;
+}
+#endif
+
+} // namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/solve-bezier-parametric.cpp b/src/3rdparty/2geom/src/2geom/solve-bezier-parametric.cpp
new file mode 100644
index 0000000..2fb3f41
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/solve-bezier-parametric.cpp
@@ -0,0 +1,189 @@
+#include <2geom/bezier.h>
+#include <2geom/point.h>
+#include <2geom/solver.h>
+#include <algorithm>
+
+namespace Geom {
+
+/*** Find the zeros of the parametric function in 2d defined by two beziers X(t), Y(t). The code subdivides until it happy with the linearity of the bezier. This requires an n^2 subdivision for each step, even when there is only one solution.
+ *
+ * Perhaps it would be better to subdivide particularly around nodes with changing sign, rather than simply cutting in half.
+ */
+
+#define SGN(a) (((a)<0) ? -1 : 1)
+
+/*
+ * Forward declarations
+ */
+unsigned
+crossing_count(Geom::Point const *V, unsigned degree);
+static unsigned
+control_poly_flat_enough(Geom::Point const *V, unsigned degree);
+static double
+compute_x_intercept(Geom::Point const *V, unsigned degree);
+
+const unsigned MAXDEPTH = 64; /* Maximum depth for recursion */
+
+const double BEPSILON = ldexp(1.0,-MAXDEPTH-1); /*Flatness control value */
+
+unsigned total_steps, total_subs;
+
+/*
+ * find_bezier_roots : Given an equation in Bernstein-Bezier form, find all
+ * of the roots in the interval [0, 1]. Return the number of roots found.
+ */
+void
+find_parametric_bezier_roots(Geom::Point const *w, /* The control points */
+ unsigned degree, /* The degree of the polynomial */
+ std::vector<double> &solutions, /* RETURN candidate t-values */
+ unsigned depth) /* The depth of the recursion */
+{
+ total_steps++;
+ const unsigned max_crossings = crossing_count(w, degree);
+ switch (max_crossings) {
+ case 0: /* No solutions here */
+ return;
+
+ case 1:
+ /* Unique solution */
+ /* Stop recursion when the tree is deep enough */
+ /* if deep enough, return 1 solution at midpoint */
+ if (depth >= MAXDEPTH) {
+ solutions.push_back((w[0][Geom::X] + w[degree][Geom::X]) / 2.0);
+ return;
+ }
+
+ // I thought secant method would be faster here, but it'aint. -- njh
+
+ if (control_poly_flat_enough(w, degree)) {
+ solutions.push_back(compute_x_intercept(w, degree));
+ return;
+ }
+ break;
+ }
+
+ /* Otherwise, solve recursively after subdividing control polygon */
+
+ //Geom::Point Left[degree+1], /* New left and right */
+ // Right[degree+1]; /* control polygons */
+ std::vector<Geom::Point> Left( degree+1 ), Right(degree+1);
+
+ casteljau_subdivision(0.5, w, Left.data(), Right.data(), degree);
+ total_subs ++;
+ find_parametric_bezier_roots(Left.data(), degree, solutions, depth+1);
+ find_parametric_bezier_roots(Right.data(), degree, solutions, depth+1);
+}
+
+
+/*
+ * crossing_count:
+ * Count the number of times a Bezier control polygon
+ * crosses the 0-axis. This number is >= the number of roots.
+ *
+ */
+unsigned
+crossing_count(Geom::Point const *V, /* Control pts of Bezier curve */
+ unsigned degree) /* Degree of Bezier curve */
+{
+ unsigned n_crossings = 0; /* Number of zero-crossings */
+
+ int old_sign = SGN(V[0][Geom::Y]);
+ for (unsigned i = 1; i <= degree; i++) {
+ int sign = SGN(V[i][Geom::Y]);
+ if (sign != old_sign)
+ n_crossings++;
+ old_sign = sign;
+ }
+ return n_crossings;
+}
+
+
+
+/*
+ * control_poly_flat_enough :
+ * Check if the control polygon of a Bezier curve is flat enough
+ * for recursive subdivision to bottom out.
+ *
+ */
+static unsigned
+control_poly_flat_enough(Geom::Point const *V, /* Control points */
+ unsigned degree) /* Degree of polynomial */
+{
+ /* Find the perpendicular distance from each interior control point to line connecting V[0] and
+ * V[degree] */
+
+ /* Derive the implicit equation for line connecting first */
+ /* and last control points */
+ const double a = V[0][Geom::Y] - V[degree][Geom::Y];
+ const double b = V[degree][Geom::X] - V[0][Geom::X];
+ const double c = V[0][Geom::X] * V[degree][Geom::Y] - V[degree][Geom::X] * V[0][Geom::Y];
+
+ const double abSquared = (a * a) + (b * b);
+
+ //double distance[degree]; /* Distances from pts to line */
+ std::vector<double> distance(degree); /* Distances from pts to line */
+ for (unsigned i = 1; i < degree; i++) {
+ /* Compute distance from each of the points to that line */
+ double & dist(distance[i-1]);
+ const double d = a * V[i][Geom::X] + b * V[i][Geom::Y] + c;
+ dist = d*d / abSquared;
+ if (d < 0.0)
+ dist = -dist;
+ }
+
+
+ // Find the largest distance
+ double max_distance_above = 0.0;
+ double max_distance_below = 0.0;
+ for (unsigned i = 0; i < degree-1; i++) {
+ const double d = distance[i];
+ if (d < 0.0)
+ max_distance_below = std::min(max_distance_below, d);
+ if (d > 0.0)
+ max_distance_above = std::max(max_distance_above, d);
+ }
+
+ const double intercept_1 = (c + max_distance_above) / -a;
+ const double intercept_2 = (c + max_distance_below) / -a;
+
+ /* Compute bounding interval*/
+ const double left_intercept = std::min(intercept_1, intercept_2);
+ const double right_intercept = std::max(intercept_1, intercept_2);
+
+ const double error = 0.5 * (right_intercept - left_intercept);
+
+ if (error < BEPSILON)
+ return 1;
+
+ return 0;
+}
+
+
+
+/*
+ * compute_x_intercept :
+ * Compute intersection of chord from first control point to last
+ * with 0-axis.
+ *
+ */
+static double
+compute_x_intercept(Geom::Point const *V, /* Control points */
+ unsigned degree) /* Degree of curve */
+{
+ const Geom::Point A = V[degree] - V[0];
+
+ return (A[Geom::X]*V[0][Geom::Y] - A[Geom::Y]*V[0][Geom::X]) / -A[Geom::Y];
+}
+
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/solve-bezier.cpp b/src/3rdparty/2geom/src/2geom/solve-bezier.cpp
new file mode 100644
index 0000000..4ff42bb
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/solve-bezier.cpp
@@ -0,0 +1,304 @@
+
+#include <2geom/solver.h>
+#include <2geom/choose.h>
+#include <2geom/bezier.h>
+#include <2geom/point.h>
+
+#include <cmath>
+#include <algorithm>
+
+/*** Find the zeros of a Bezier. The code subdivides until it is happy with the linearity of the
+ * function. This requires an O(degree^2) subdivision for each step, even when there is only one
+ * solution.
+ *
+ * We try fairly hard to correctly handle multiple roots.
+ */
+
+//#define debug(x) do{x;}while(0)
+#define debug(x)
+
+namespace Geom{
+
+template<class t>
+static int SGN(t x) { return (x > 0 ? 1 : (x < 0 ? -1 : 0)); }
+
+class Bernsteins{
+public:
+ static const size_t MAX_DEPTH = 22;
+ std::vector<double> &solutions;
+ //std::vector<double> dsolutions;
+
+ Bernsteins(std::vector<double> & sol)
+ : solutions(sol)
+ {}
+
+ void subdivide(double const *V,
+ double t,
+ double *Left,
+ double *Right);
+
+ double secant(Bezier const &bz);
+
+
+ void find_bernstein_roots(Bezier const &bz, unsigned depth,
+ double left_t, double right_t);
+};
+
+template <typename T>
+inline std::ostream &operator<< (std::ostream &out_file, const std::vector<T> & b) {
+ out_file << "[";
+ for(unsigned i = 0; i < b.size(); i++) {
+ out_file << b[i] << ", ";
+ }
+ return out_file << "]";
+}
+
+void convex_hull_marching(Bezier const &src_bz, Bezier bz,
+ std::vector<double> &solutions,
+ double left_t,
+ double right_t)
+{
+ while(bz.order() > 0 && bz[0] == 0) {
+ std::cout << "deflate\n";
+ bz = bz.deflate();
+ solutions.push_back(left_t);
+ }
+ std::cout << std::endl;
+ if (bz.order() > 0) {
+
+ int old_sign = SGN(bz[0]);
+
+ double left_bound = 0;
+ double dt = 0;
+ for (size_t i = 1; i < bz.size(); i++)
+ {
+ int sign = SGN(bz[i]);
+ if (sign != old_sign)
+ {
+ dt = double(i) / bz.order();
+ left_bound = dt * bz[0] / (bz[0] - bz[i]);
+ break;
+ }
+ old_sign = sign;
+ }
+ if (dt == 0) return;
+ std::cout << bz << std::endl;
+ std::cout << "dt = " << dt << std::endl;
+ std::cout << "left_t = " << left_t << std::endl;
+ std::cout << "right_t = " << right_t << std::endl;
+ std::cout << "left bound = " << left_bound
+ << " = " << bz(left_bound) << std::endl;
+ double new_left_t = left_bound * (right_t - left_t) + left_t;
+ std::cout << "new_left_t = " << new_left_t << std::endl;
+ Bezier bzr = portion(src_bz, new_left_t, 1);
+ while(bzr.order() > 0 && bzr[0] == 0) {
+ std::cout << "deflate\n";
+ bzr = bzr.deflate();
+ solutions.push_back(new_left_t);
+ }
+ if (left_t < new_left_t) {
+ convex_hull_marching(src_bz, bzr,
+ solutions,
+ new_left_t, right_t);
+ } else {
+ std::cout << "epsilon reached\n";
+ while(bzr.order() > 0 && fabs(bzr[0]) <= 1e-10) {
+ std::cout << "deflate\n";
+ bzr = bzr.deflate();
+ std::cout << bzr << std::endl;
+ solutions.push_back(new_left_t);
+ }
+
+ }
+ }
+}
+
+void
+Bezier::find_bezier_roots(std::vector<double> &solutions,
+ double left_t, double right_t) const {
+ Bezier bz = *this;
+ //convex_hull_marching(bz, bz, solutions, left_t, right_t);
+ //return;
+
+ // a constant bezier, even if identically zero, has no roots
+ if (bz.isConstant()) {
+ return;
+ }
+
+ while(bz[0] == 0) {
+ debug(std::cout << "deflate\n");
+ bz = bz.deflate();
+ solutions.push_back(0);
+ }
+ if (bz.degree() == 1) {
+ debug(std::cout << "linear\n");
+
+ if (SGN(bz[0]) != SGN(bz[1])) {
+ double d = bz[0] - bz[1];
+ if(d != 0) {
+ double r = bz[0] / d;
+ if(0 <= r && r <= 1)
+ solutions.push_back(r);
+ }
+ }
+ return;
+ }
+
+ //std::cout << "initial = " << bz << std::endl;
+ Bernsteins B(solutions);
+ B.find_bernstein_roots(bz, 0, left_t, right_t);
+ //std::cout << solutions << std::endl;
+}
+
+void Bernsteins::find_bernstein_roots(Bezier const &bz,
+ unsigned depth,
+ double left_t,
+ double right_t)
+{
+ debug(std::cout << left_t << ", " << right_t << std::endl);
+ size_t n_crossings = 0;
+
+ int old_sign = SGN(bz[0]);
+ //std::cout << "w[0] = " << bz[0] << std::endl;
+ for (size_t i = 1; i < bz.size(); i++)
+ {
+ //std::cout << "w[" << i << "] = " << w[i] << std::endl;
+ int sign = SGN(bz[i]);
+ if (sign != 0)
+ {
+ if (sign != old_sign && old_sign != 0)
+ {
+ ++n_crossings;
+ }
+ old_sign = sign;
+ }
+ }
+ // if last control point is zero, that counts as crossing too
+ if (SGN(bz[bz.size()-1]) == 0) {
+ ++n_crossings;
+ }
+
+ //std::cout << "n_crossings = " << n_crossings << std::endl;
+ if (n_crossings == 0) return; // no solutions here
+
+ if (n_crossings == 1) /* Unique solution */
+ {
+ //std::cout << "depth = " << depth << std::endl;
+ /* Stop recursion when the tree is deep enough */
+ /* if deep enough, return 1 solution at midpoint */
+ if (depth > MAX_DEPTH)
+ {
+ //printf("bottom out %d\n", depth);
+ const double Ax = right_t - left_t;
+ const double Ay = bz.at1() - bz.at0();
+
+ solutions.push_back(left_t - Ax*bz.at0() / Ay);
+ return;
+ }
+
+ double r = secant(bz);
+ solutions.push_back(r*right_t + (1-r)*left_t);
+ return;
+ }
+ /* Otherwise, solve recursively after subdividing control polygon */
+ Bezier::Order o(bz);
+ Bezier Left(o), Right = bz;
+ double split_t = (left_t + right_t) * 0.5;
+
+ // If subdivision is working poorly, split around the leftmost root of the derivative
+ if (depth > 2) {
+ debug(std::cout << "derivative mode\n");
+ Bezier dbz = derivative(bz);
+
+ debug(std::cout << "initial = " << dbz << std::endl);
+ std::vector<double> dsolutions = dbz.roots(Interval(left_t, right_t));
+ debug(std::cout << "dsolutions = " << dsolutions << std::endl);
+
+ double dsplit_t = 0.5;
+ if(!dsolutions.empty()) {
+ dsplit_t = dsolutions[0];
+ split_t = left_t + (right_t - left_t)*dsplit_t;
+ debug(std::cout << "split_value = " << bz(split_t) << std::endl);
+ debug(std::cout << "splitting around " << dsplit_t << " = "
+ << split_t << "\n");
+
+ }
+ std::pair<Bezier, Bezier> LR = bz.subdivide(dsplit_t);
+ Left = LR.first;
+ Right = LR.second;
+ } else {
+ // split at midpoint, because it is cheap
+ Left[0] = Right[0];
+ for (size_t i = 1; i < bz.size(); ++i)
+ {
+ for (size_t j = 0; j < bz.size()-i; ++j)
+ {
+ Right[j] = (Right[j] + Right[j+1]) * 0.5;
+ }
+ Left[i] = Right[0];
+ }
+ }
+ debug(std::cout << "Solution is exactly on the subdivision point.\n");
+ debug(std::cout << Left << " , " << Right << std::endl);
+ Left = reverse(Left);
+ while(Right.order() > 0 && fabs(Right[0]) <= 1e-10) {
+ debug(std::cout << "deflate\n");
+ Right = Right.deflate();
+ Left = Left.deflate();
+ solutions.push_back(split_t);
+ }
+ Left = reverse(Left);
+ if (Right.order() > 0) {
+ debug(std::cout << Left << " , " << Right << std::endl);
+ find_bernstein_roots(Left, depth+1, left_t, split_t);
+ find_bernstein_roots(Right, depth+1, split_t, right_t);
+ }
+}
+
+double Bernsteins::secant(Bezier const &bz) {
+ double s = 0, t = 1;
+ double e = 1e-14;
+ int side = 0;
+ double r, fs = bz.at0(), ft = bz.at1();
+
+ for (size_t n = 0; n < 100; ++n)
+ {
+ r = (fs*t - ft*s) / (fs - ft);
+ if (fabs(t-s) < e * fabs(t+s)) {
+ debug(std::cout << "error small " << fabs(t-s)
+ << ", accepting solution " << r
+ << "after " << n << "iterations\n");
+ return r;
+ }
+
+ double fr = bz.valueAt(r);
+
+ if (fr * ft > 0)
+ {
+ t = r; ft = fr;
+ if (side == -1) fs /= 2;
+ side = -1;
+ }
+ else if (fs * fr > 0)
+ {
+ s = r; fs = fr;
+ if (side == +1) ft /= 2;
+ side = +1;
+ }
+ else break;
+ }
+ return r;
+}
+
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/svg-path-parser.cpp b/src/3rdparty/2geom/src/2geom/svg-path-parser.cpp
new file mode 100644
index 0000000..6a1cb15
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/svg-path-parser.cpp
@@ -0,0 +1,1615 @@
+
+#line 1 "svg-path-parser.rl"
+/**
+ * \file
+ * \brief parse SVG path specifications
+ *
+ * Copyright 2007 MenTaLguY <mental@rydia.net>
+ * Copyright 2007 Aaron Spike <aaron@ekips.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <cstdio>
+#include <cmath>
+#include <vector>
+#include <glib.h>
+
+#include <2geom/point.h>
+#include <2geom/svg-path-parser.h>
+#include <2geom/angle.h>
+
+namespace Geom {
+
+
+#line 48 "svg-path-parser.cpp"
+static const char _svg_path_actions[] = {
+ 0, 1, 0, 1, 1, 1, 2, 1,
+ 3, 1, 4, 1, 5, 1, 15, 2,
+ 1, 0, 2, 1, 6, 2, 1, 7,
+ 2, 1, 8, 2, 1, 9, 2, 1,
+ 10, 2, 1, 11, 2, 1, 12, 2,
+ 1, 13, 2, 1, 14, 2, 2, 0,
+ 2, 3, 0, 2, 4, 0, 2, 5,
+ 0, 3, 1, 6, 0, 3, 1, 7,
+ 0, 3, 1, 8, 0, 3, 1, 9,
+ 0, 3, 1, 10, 0, 3, 1, 11,
+ 0, 3, 1, 12, 0, 3, 1, 13,
+ 0, 3, 1, 14, 0
+};
+
+static const short _svg_path_key_offsets[] = {
+ 0, 0, 9, 18, 21, 23, 35, 45,
+ 48, 50, 53, 55, 67, 77, 80, 82,
+ 91, 103, 112, 121, 130, 133, 135, 147,
+ 157, 160, 162, 174, 184, 187, 189, 198,
+ 205, 211, 218, 225, 231, 241, 251, 254,
+ 256, 268, 278, 281, 283, 295, 304, 316,
+ 325, 335, 339, 341, 348, 352, 354, 364,
+ 368, 370, 380, 389, 398, 401, 403, 415,
+ 425, 428, 430, 442, 452, 455, 457, 469,
+ 479, 482, 484, 496, 506, 509, 511, 523,
+ 533, 536, 538, 550, 559, 571, 580, 592,
+ 601, 613, 622, 634, 643, 647, 649, 658,
+ 667, 670, 672, 676, 678, 687, 696, 705,
+ 708, 710, 722, 732, 735, 737, 749, 759,
+ 762, 764, 776, 786, 789, 791, 803, 812,
+ 824, 833, 845, 854, 858, 860, 869, 878,
+ 881, 883, 895, 905, 908, 910, 922, 932,
+ 935, 937, 949, 959, 962, 964, 976, 985,
+ 997, 1006, 1018, 1027, 1031, 1033, 1042, 1051,
+ 1054, 1056, 1068, 1078, 1081, 1083, 1095, 1104,
+ 1108, 1110, 1119, 1128, 1131, 1133, 1137, 1139,
+ 1148, 1157, 1166, 1175, 1184, 1196, 1205, 1209,
+ 1211, 1220, 1229, 1238, 1247, 1251, 1253, 1263,
+ 1267, 1269, 1279, 1283, 1285, 1295, 1299, 1301,
+ 1311, 1315, 1317, 1327, 1331, 1333, 1343, 1347,
+ 1349, 1359, 1363, 1365, 1375, 1379, 1381, 1391,
+ 1395, 1397, 1407, 1411, 1413, 1423, 1427, 1429,
+ 1439, 1443, 1445, 1455, 1459, 1461, 1470, 1474,
+ 1476, 1486, 1498, 1507, 1517, 1524, 1528, 1530,
+ 1534, 1536, 1546, 1552, 1584, 1614, 1646, 1678,
+ 1710, 1740, 1772, 1802, 1834, 1864, 1896, 1926,
+ 1958, 1988, 2020, 2050, 2082, 2112, 2144, 2174,
+ 2206, 2236, 2268, 2298, 2330, 2360, 2392, 2422,
+ 2454, 2484, 2508, 2532, 2564, 2594, 2624, 2656
+};
+
+static const char _svg_path_trans_keys[] = {
+ 13, 32, 43, 45, 46, 9, 10, 48,
+ 57, 13, 32, 43, 45, 46, 9, 10,
+ 48, 57, 46, 48, 57, 48, 57, 13,
+ 32, 44, 46, 69, 101, 9, 10, 43,
+ 45, 48, 57, 13, 32, 44, 46, 9,
+ 10, 43, 45, 48, 57, 46, 48, 57,
+ 48, 57, 46, 48, 57, 48, 57, 13,
+ 32, 44, 46, 69, 101, 9, 10, 43,
+ 45, 48, 57, 13, 32, 44, 46, 9,
+ 10, 43, 45, 48, 57, 46, 48, 57,
+ 48, 57, 13, 32, 43, 45, 46, 9,
+ 10, 48, 57, 13, 32, 44, 46, 69,
+ 101, 9, 10, 43, 45, 48, 57, 13,
+ 32, 43, 45, 46, 9, 10, 48, 57,
+ 13, 32, 43, 45, 46, 9, 10, 48,
+ 57, 13, 32, 43, 45, 46, 9, 10,
+ 48, 57, 46, 48, 57, 48, 57, 13,
+ 32, 44, 46, 69, 101, 9, 10, 43,
+ 45, 48, 57, 13, 32, 44, 46, 9,
+ 10, 43, 45, 48, 57, 46, 48, 57,
+ 48, 57, 13, 32, 44, 46, 69, 101,
+ 9, 10, 43, 45, 48, 57, 13, 32,
+ 44, 46, 9, 10, 43, 45, 48, 57,
+ 46, 48, 57, 48, 57, 13, 32, 44,
+ 69, 101, 9, 10, 48, 57, 13, 32,
+ 44, 48, 49, 9, 10, 13, 32, 48,
+ 49, 9, 10, 13, 32, 44, 48, 49,
+ 9, 10, 13, 32, 44, 48, 49, 9,
+ 10, 13, 32, 48, 49, 9, 10, 13,
+ 32, 44, 46, 9, 10, 43, 45, 48,
+ 57, 13, 32, 44, 46, 9, 10, 43,
+ 45, 48, 57, 46, 48, 57, 48, 57,
+ 13, 32, 44, 46, 69, 101, 9, 10,
+ 43, 45, 48, 57, 13, 32, 44, 46,
+ 9, 10, 43, 45, 48, 57, 46, 48,
+ 57, 48, 57, 13, 32, 44, 46, 69,
+ 101, 9, 10, 43, 45, 48, 57, 13,
+ 32, 43, 45, 46, 9, 10, 48, 57,
+ 13, 32, 44, 46, 69, 101, 9, 10,
+ 43, 45, 48, 57, 13, 32, 43, 45,
+ 46, 9, 10, 48, 57, 13, 32, 44,
+ 46, 69, 101, 9, 10, 48, 57, 43,
+ 45, 48, 57, 48, 57, 13, 32, 44,
+ 9, 10, 48, 57, 43, 45, 48, 57,
+ 48, 57, 13, 32, 44, 46, 9, 10,
+ 43, 45, 48, 57, 43, 45, 48, 57,
+ 48, 57, 13, 32, 44, 46, 9, 10,
+ 43, 45, 48, 57, 13, 32, 43, 45,
+ 46, 9, 10, 48, 57, 13, 32, 43,
+ 45, 46, 9, 10, 48, 57, 46, 48,
+ 57, 48, 57, 13, 32, 44, 46, 69,
+ 101, 9, 10, 43, 45, 48, 57, 13,
+ 32, 44, 46, 9, 10, 43, 45, 48,
+ 57, 46, 48, 57, 48, 57, 13, 32,
+ 44, 46, 69, 101, 9, 10, 43, 45,
+ 48, 57, 13, 32, 44, 46, 9, 10,
+ 43, 45, 48, 57, 46, 48, 57, 48,
+ 57, 13, 32, 44, 46, 69, 101, 9,
+ 10, 43, 45, 48, 57, 13, 32, 44,
+ 46, 9, 10, 43, 45, 48, 57, 46,
+ 48, 57, 48, 57, 13, 32, 44, 46,
+ 69, 101, 9, 10, 43, 45, 48, 57,
+ 13, 32, 44, 46, 9, 10, 43, 45,
+ 48, 57, 46, 48, 57, 48, 57, 13,
+ 32, 44, 46, 69, 101, 9, 10, 43,
+ 45, 48, 57, 13, 32, 44, 46, 9,
+ 10, 43, 45, 48, 57, 46, 48, 57,
+ 48, 57, 13, 32, 44, 46, 69, 101,
+ 9, 10, 43, 45, 48, 57, 13, 32,
+ 43, 45, 46, 9, 10, 48, 57, 13,
+ 32, 44, 46, 69, 101, 9, 10, 43,
+ 45, 48, 57, 13, 32, 43, 45, 46,
+ 9, 10, 48, 57, 13, 32, 44, 46,
+ 69, 101, 9, 10, 43, 45, 48, 57,
+ 13, 32, 43, 45, 46, 9, 10, 48,
+ 57, 13, 32, 44, 46, 69, 101, 9,
+ 10, 43, 45, 48, 57, 13, 32, 43,
+ 45, 46, 9, 10, 48, 57, 13, 32,
+ 44, 46, 69, 101, 9, 10, 43, 45,
+ 48, 57, 13, 32, 43, 45, 46, 9,
+ 10, 48, 57, 43, 45, 48, 57, 48,
+ 57, 13, 32, 43, 45, 46, 9, 10,
+ 48, 57, 13, 32, 43, 45, 46, 9,
+ 10, 48, 57, 46, 48, 57, 48, 57,
+ 43, 45, 48, 57, 48, 57, 13, 32,
+ 43, 45, 46, 9, 10, 48, 57, 13,
+ 32, 43, 45, 46, 9, 10, 48, 57,
+ 13, 32, 43, 45, 46, 9, 10, 48,
+ 57, 46, 48, 57, 48, 57, 13, 32,
+ 44, 46, 69, 101, 9, 10, 43, 45,
+ 48, 57, 13, 32, 44, 46, 9, 10,
+ 43, 45, 48, 57, 46, 48, 57, 48,
+ 57, 13, 32, 44, 46, 69, 101, 9,
+ 10, 43, 45, 48, 57, 13, 32, 44,
+ 46, 9, 10, 43, 45, 48, 57, 46,
+ 48, 57, 48, 57, 13, 32, 44, 46,
+ 69, 101, 9, 10, 43, 45, 48, 57,
+ 13, 32, 44, 46, 9, 10, 43, 45,
+ 48, 57, 46, 48, 57, 48, 57, 13,
+ 32, 44, 46, 69, 101, 9, 10, 43,
+ 45, 48, 57, 13, 32, 43, 45, 46,
+ 9, 10, 48, 57, 13, 32, 44, 46,
+ 69, 101, 9, 10, 43, 45, 48, 57,
+ 13, 32, 43, 45, 46, 9, 10, 48,
+ 57, 13, 32, 44, 46, 69, 101, 9,
+ 10, 43, 45, 48, 57, 13, 32, 43,
+ 45, 46, 9, 10, 48, 57, 43, 45,
+ 48, 57, 48, 57, 13, 32, 43, 45,
+ 46, 9, 10, 48, 57, 13, 32, 43,
+ 45, 46, 9, 10, 48, 57, 46, 48,
+ 57, 48, 57, 13, 32, 44, 46, 69,
+ 101, 9, 10, 43, 45, 48, 57, 13,
+ 32, 44, 46, 9, 10, 43, 45, 48,
+ 57, 46, 48, 57, 48, 57, 13, 32,
+ 44, 46, 69, 101, 9, 10, 43, 45,
+ 48, 57, 13, 32, 44, 46, 9, 10,
+ 43, 45, 48, 57, 46, 48, 57, 48,
+ 57, 13, 32, 44, 46, 69, 101, 9,
+ 10, 43, 45, 48, 57, 13, 32, 44,
+ 46, 9, 10, 43, 45, 48, 57, 46,
+ 48, 57, 48, 57, 13, 32, 44, 46,
+ 69, 101, 9, 10, 43, 45, 48, 57,
+ 13, 32, 43, 45, 46, 9, 10, 48,
+ 57, 13, 32, 44, 46, 69, 101, 9,
+ 10, 43, 45, 48, 57, 13, 32, 43,
+ 45, 46, 9, 10, 48, 57, 13, 32,
+ 44, 46, 69, 101, 9, 10, 43, 45,
+ 48, 57, 13, 32, 43, 45, 46, 9,
+ 10, 48, 57, 43, 45, 48, 57, 48,
+ 57, 13, 32, 43, 45, 46, 9, 10,
+ 48, 57, 13, 32, 43, 45, 46, 9,
+ 10, 48, 57, 46, 48, 57, 48, 57,
+ 13, 32, 44, 46, 69, 101, 9, 10,
+ 43, 45, 48, 57, 13, 32, 44, 46,
+ 9, 10, 43, 45, 48, 57, 46, 48,
+ 57, 48, 57, 13, 32, 44, 46, 69,
+ 101, 9, 10, 43, 45, 48, 57, 13,
+ 32, 43, 45, 46, 9, 10, 48, 57,
+ 43, 45, 48, 57, 48, 57, 13, 32,
+ 43, 45, 46, 9, 10, 48, 57, 13,
+ 32, 43, 45, 46, 9, 10, 48, 57,
+ 46, 48, 57, 48, 57, 43, 45, 48,
+ 57, 48, 57, 13, 32, 43, 45, 46,
+ 9, 10, 48, 57, 13, 32, 43, 45,
+ 46, 9, 10, 48, 57, 13, 32, 43,
+ 45, 46, 9, 10, 48, 57, 13, 32,
+ 43, 45, 46, 9, 10, 48, 57, 13,
+ 32, 43, 45, 46, 9, 10, 48, 57,
+ 13, 32, 44, 46, 69, 101, 9, 10,
+ 43, 45, 48, 57, 13, 32, 43, 45,
+ 46, 9, 10, 48, 57, 43, 45, 48,
+ 57, 48, 57, 13, 32, 43, 45, 46,
+ 9, 10, 48, 57, 13, 32, 43, 45,
+ 46, 9, 10, 48, 57, 13, 32, 43,
+ 45, 46, 9, 10, 48, 57, 13, 32,
+ 43, 45, 46, 9, 10, 48, 57, 43,
+ 45, 48, 57, 48, 57, 13, 32, 44,
+ 46, 9, 10, 43, 45, 48, 57, 43,
+ 45, 48, 57, 48, 57, 13, 32, 44,
+ 46, 9, 10, 43, 45, 48, 57, 43,
+ 45, 48, 57, 48, 57, 13, 32, 44,
+ 46, 9, 10, 43, 45, 48, 57, 43,
+ 45, 48, 57, 48, 57, 13, 32, 44,
+ 46, 9, 10, 43, 45, 48, 57, 43,
+ 45, 48, 57, 48, 57, 13, 32, 44,
+ 46, 9, 10, 43, 45, 48, 57, 43,
+ 45, 48, 57, 48, 57, 13, 32, 44,
+ 46, 9, 10, 43, 45, 48, 57, 43,
+ 45, 48, 57, 48, 57, 13, 32, 44,
+ 46, 9, 10, 43, 45, 48, 57, 43,
+ 45, 48, 57, 48, 57, 13, 32, 44,
+ 46, 9, 10, 43, 45, 48, 57, 43,
+ 45, 48, 57, 48, 57, 13, 32, 44,
+ 46, 9, 10, 43, 45, 48, 57, 43,
+ 45, 48, 57, 48, 57, 13, 32, 44,
+ 46, 9, 10, 43, 45, 48, 57, 43,
+ 45, 48, 57, 48, 57, 13, 32, 44,
+ 46, 9, 10, 43, 45, 48, 57, 43,
+ 45, 48, 57, 48, 57, 13, 32, 44,
+ 46, 9, 10, 43, 45, 48, 57, 43,
+ 45, 48, 57, 48, 57, 13, 32, 44,
+ 46, 9, 10, 43, 45, 48, 57, 43,
+ 45, 48, 57, 48, 57, 13, 32, 43,
+ 45, 46, 9, 10, 48, 57, 43, 45,
+ 48, 57, 48, 57, 13, 32, 44, 46,
+ 9, 10, 43, 45, 48, 57, 13, 32,
+ 44, 46, 69, 101, 9, 10, 43, 45,
+ 48, 57, 13, 32, 43, 45, 46, 9,
+ 10, 48, 57, 13, 32, 44, 46, 9,
+ 10, 43, 45, 48, 57, 13, 32, 44,
+ 48, 49, 9, 10, 43, 45, 48, 57,
+ 48, 57, 43, 45, 48, 57, 48, 57,
+ 13, 32, 44, 46, 9, 10, 43, 45,
+ 48, 57, 13, 32, 77, 109, 9, 10,
+ 13, 32, 44, 46, 65, 67, 69, 72,
+ 76, 77, 81, 83, 84, 86, 90, 97,
+ 99, 101, 104, 108, 109, 113, 115, 116,
+ 118, 122, 9, 10, 43, 45, 48, 57,
+ 13, 32, 44, 46, 65, 67, 72, 76,
+ 77, 81, 83, 84, 86, 90, 97, 99,
+ 104, 108, 109, 113, 115, 116, 118, 122,
+ 9, 10, 43, 45, 48, 57, 13, 32,
+ 44, 46, 65, 67, 69, 72, 76, 77,
+ 81, 83, 84, 86, 90, 97, 99, 101,
+ 104, 108, 109, 113, 115, 116, 118, 122,
+ 9, 10, 43, 45, 48, 57, 13, 32,
+ 44, 46, 65, 67, 69, 72, 76, 77,
+ 81, 83, 84, 86, 90, 97, 99, 101,
+ 104, 108, 109, 113, 115, 116, 118, 122,
+ 9, 10, 43, 45, 48, 57, 13, 32,
+ 44, 46, 65, 67, 69, 72, 76, 77,
+ 81, 83, 84, 86, 90, 97, 99, 101,
+ 104, 108, 109, 113, 115, 116, 118, 122,
+ 9, 10, 43, 45, 48, 57, 13, 32,
+ 44, 46, 65, 67, 72, 76, 77, 81,
+ 83, 84, 86, 90, 97, 99, 104, 108,
+ 109, 113, 115, 116, 118, 122, 9, 10,
+ 43, 45, 48, 57, 13, 32, 44, 46,
+ 65, 67, 69, 72, 76, 77, 81, 83,
+ 84, 86, 90, 97, 99, 101, 104, 108,
+ 109, 113, 115, 116, 118, 122, 9, 10,
+ 43, 45, 48, 57, 13, 32, 44, 46,
+ 65, 67, 72, 76, 77, 81, 83, 84,
+ 86, 90, 97, 99, 104, 108, 109, 113,
+ 115, 116, 118, 122, 9, 10, 43, 45,
+ 48, 57, 13, 32, 44, 46, 65, 67,
+ 69, 72, 76, 77, 81, 83, 84, 86,
+ 90, 97, 99, 101, 104, 108, 109, 113,
+ 115, 116, 118, 122, 9, 10, 43, 45,
+ 48, 57, 13, 32, 44, 46, 65, 67,
+ 72, 76, 77, 81, 83, 84, 86, 90,
+ 97, 99, 104, 108, 109, 113, 115, 116,
+ 118, 122, 9, 10, 43, 45, 48, 57,
+ 13, 32, 44, 46, 65, 67, 69, 72,
+ 76, 77, 81, 83, 84, 86, 90, 97,
+ 99, 101, 104, 108, 109, 113, 115, 116,
+ 118, 122, 9, 10, 43, 45, 48, 57,
+ 13, 32, 44, 46, 65, 67, 72, 76,
+ 77, 81, 83, 84, 86, 90, 97, 99,
+ 104, 108, 109, 113, 115, 116, 118, 122,
+ 9, 10, 43, 45, 48, 57, 13, 32,
+ 44, 46, 65, 67, 69, 72, 76, 77,
+ 81, 83, 84, 86, 90, 97, 99, 101,
+ 104, 108, 109, 113, 115, 116, 118, 122,
+ 9, 10, 43, 45, 48, 57, 13, 32,
+ 44, 46, 65, 67, 72, 76, 77, 81,
+ 83, 84, 86, 90, 97, 99, 104, 108,
+ 109, 113, 115, 116, 118, 122, 9, 10,
+ 43, 45, 48, 57, 13, 32, 44, 46,
+ 65, 67, 69, 72, 76, 77, 81, 83,
+ 84, 86, 90, 97, 99, 101, 104, 108,
+ 109, 113, 115, 116, 118, 122, 9, 10,
+ 43, 45, 48, 57, 13, 32, 44, 46,
+ 65, 67, 72, 76, 77, 81, 83, 84,
+ 86, 90, 97, 99, 104, 108, 109, 113,
+ 115, 116, 118, 122, 9, 10, 43, 45,
+ 48, 57, 13, 32, 44, 46, 65, 67,
+ 69, 72, 76, 77, 81, 83, 84, 86,
+ 90, 97, 99, 101, 104, 108, 109, 113,
+ 115, 116, 118, 122, 9, 10, 43, 45,
+ 48, 57, 13, 32, 44, 46, 65, 67,
+ 72, 76, 77, 81, 83, 84, 86, 90,
+ 97, 99, 104, 108, 109, 113, 115, 116,
+ 118, 122, 9, 10, 43, 45, 48, 57,
+ 13, 32, 44, 46, 65, 67, 69, 72,
+ 76, 77, 81, 83, 84, 86, 90, 97,
+ 99, 101, 104, 108, 109, 113, 115, 116,
+ 118, 122, 9, 10, 43, 45, 48, 57,
+ 13, 32, 44, 46, 65, 67, 72, 76,
+ 77, 81, 83, 84, 86, 90, 97, 99,
+ 104, 108, 109, 113, 115, 116, 118, 122,
+ 9, 10, 43, 45, 48, 57, 13, 32,
+ 44, 46, 65, 67, 69, 72, 76, 77,
+ 81, 83, 84, 86, 90, 97, 99, 101,
+ 104, 108, 109, 113, 115, 116, 118, 122,
+ 9, 10, 43, 45, 48, 57, 13, 32,
+ 44, 46, 65, 67, 72, 76, 77, 81,
+ 83, 84, 86, 90, 97, 99, 104, 108,
+ 109, 113, 115, 116, 118, 122, 9, 10,
+ 43, 45, 48, 57, 13, 32, 44, 46,
+ 65, 67, 69, 72, 76, 77, 81, 83,
+ 84, 86, 90, 97, 99, 101, 104, 108,
+ 109, 113, 115, 116, 118, 122, 9, 10,
+ 43, 45, 48, 57, 13, 32, 44, 46,
+ 65, 67, 72, 76, 77, 81, 83, 84,
+ 86, 90, 97, 99, 104, 108, 109, 113,
+ 115, 116, 118, 122, 9, 10, 43, 45,
+ 48, 57, 13, 32, 44, 46, 65, 67,
+ 69, 72, 76, 77, 81, 83, 84, 86,
+ 90, 97, 99, 101, 104, 108, 109, 113,
+ 115, 116, 118, 122, 9, 10, 43, 45,
+ 48, 57, 13, 32, 44, 46, 65, 67,
+ 72, 76, 77, 81, 83, 84, 86, 90,
+ 97, 99, 104, 108, 109, 113, 115, 116,
+ 118, 122, 9, 10, 43, 45, 48, 57,
+ 13, 32, 44, 46, 65, 67, 69, 72,
+ 76, 77, 81, 83, 84, 86, 90, 97,
+ 99, 101, 104, 108, 109, 113, 115, 116,
+ 118, 122, 9, 10, 43, 45, 48, 57,
+ 13, 32, 44, 46, 65, 67, 72, 76,
+ 77, 81, 83, 84, 86, 90, 97, 99,
+ 104, 108, 109, 113, 115, 116, 118, 122,
+ 9, 10, 43, 45, 48, 57, 13, 32,
+ 44, 46, 65, 67, 69, 72, 76, 77,
+ 81, 83, 84, 86, 90, 97, 99, 101,
+ 104, 108, 109, 113, 115, 116, 118, 122,
+ 9, 10, 43, 45, 48, 57, 13, 32,
+ 44, 46, 65, 67, 72, 76, 77, 81,
+ 83, 84, 86, 90, 97, 99, 104, 108,
+ 109, 113, 115, 116, 118, 122, 9, 10,
+ 43, 45, 48, 57, 13, 32, 65, 67,
+ 72, 76, 77, 81, 83, 84, 86, 90,
+ 97, 99, 104, 108, 109, 113, 115, 116,
+ 118, 122, 9, 10, 13, 32, 65, 67,
+ 72, 76, 77, 81, 83, 84, 86, 90,
+ 97, 99, 104, 108, 109, 113, 115, 116,
+ 118, 122, 9, 10, 13, 32, 44, 46,
+ 65, 67, 69, 72, 76, 77, 81, 83,
+ 84, 86, 90, 97, 99, 101, 104, 108,
+ 109, 113, 115, 116, 118, 122, 9, 10,
+ 43, 45, 48, 57, 13, 32, 44, 46,
+ 65, 67, 72, 76, 77, 81, 83, 84,
+ 86, 90, 97, 99, 104, 108, 109, 113,
+ 115, 116, 118, 122, 9, 10, 43, 45,
+ 48, 57, 13, 32, 44, 46, 65, 67,
+ 72, 76, 77, 81, 83, 84, 86, 90,
+ 97, 99, 104, 108, 109, 113, 115, 116,
+ 118, 122, 9, 10, 43, 45, 48, 57,
+ 13, 32, 44, 46, 65, 67, 69, 72,
+ 76, 77, 81, 83, 84, 86, 90, 97,
+ 99, 101, 104, 108, 109, 113, 115, 116,
+ 118, 122, 9, 10, 43, 45, 48, 57,
+ 13, 32, 44, 46, 65, 67, 72, 76,
+ 77, 81, 83, 84, 86, 90, 97, 99,
+ 104, 108, 109, 113, 115, 116, 118, 122,
+ 9, 10, 43, 45, 48, 57, 0
+};
+
+static const char _svg_path_single_lengths[] = {
+ 0, 5, 5, 1, 0, 6, 4, 1,
+ 0, 1, 0, 6, 4, 1, 0, 5,
+ 6, 5, 5, 5, 1, 0, 6, 4,
+ 1, 0, 6, 4, 1, 0, 5, 5,
+ 4, 5, 5, 4, 4, 4, 1, 0,
+ 6, 4, 1, 0, 6, 5, 6, 5,
+ 6, 2, 0, 3, 2, 0, 4, 2,
+ 0, 4, 5, 5, 1, 0, 6, 4,
+ 1, 0, 6, 4, 1, 0, 6, 4,
+ 1, 0, 6, 4, 1, 0, 6, 4,
+ 1, 0, 6, 5, 6, 5, 6, 5,
+ 6, 5, 6, 5, 2, 0, 5, 5,
+ 1, 0, 2, 0, 5, 5, 5, 1,
+ 0, 6, 4, 1, 0, 6, 4, 1,
+ 0, 6, 4, 1, 0, 6, 5, 6,
+ 5, 6, 5, 2, 0, 5, 5, 1,
+ 0, 6, 4, 1, 0, 6, 4, 1,
+ 0, 6, 4, 1, 0, 6, 5, 6,
+ 5, 6, 5, 2, 0, 5, 5, 1,
+ 0, 6, 4, 1, 0, 6, 5, 2,
+ 0, 5, 5, 1, 0, 2, 0, 5,
+ 5, 5, 5, 5, 6, 5, 2, 0,
+ 5, 5, 5, 5, 2, 0, 4, 2,
+ 0, 4, 2, 0, 4, 2, 0, 4,
+ 2, 0, 4, 2, 0, 4, 2, 0,
+ 4, 2, 0, 4, 2, 0, 4, 2,
+ 0, 4, 2, 0, 4, 2, 0, 4,
+ 2, 0, 4, 2, 0, 5, 2, 0,
+ 4, 6, 5, 4, 5, 2, 0, 2,
+ 0, 4, 4, 26, 24, 26, 26, 26,
+ 24, 26, 24, 26, 24, 26, 24, 26,
+ 24, 26, 24, 26, 24, 26, 24, 26,
+ 24, 26, 24, 26, 24, 26, 24, 26,
+ 24, 22, 22, 26, 24, 24, 26, 24
+};
+
+static const char _svg_path_range_lengths[] = {
+ 0, 2, 2, 1, 1, 3, 3, 1,
+ 1, 1, 1, 3, 3, 1, 1, 2,
+ 3, 2, 2, 2, 1, 1, 3, 3,
+ 1, 1, 3, 3, 1, 1, 2, 1,
+ 1, 1, 1, 1, 3, 3, 1, 1,
+ 3, 3, 1, 1, 3, 2, 3, 2,
+ 2, 1, 1, 2, 1, 1, 3, 1,
+ 1, 3, 2, 2, 1, 1, 3, 3,
+ 1, 1, 3, 3, 1, 1, 3, 3,
+ 1, 1, 3, 3, 1, 1, 3, 3,
+ 1, 1, 3, 2, 3, 2, 3, 2,
+ 3, 2, 3, 2, 1, 1, 2, 2,
+ 1, 1, 1, 1, 2, 2, 2, 1,
+ 1, 3, 3, 1, 1, 3, 3, 1,
+ 1, 3, 3, 1, 1, 3, 2, 3,
+ 2, 3, 2, 1, 1, 2, 2, 1,
+ 1, 3, 3, 1, 1, 3, 3, 1,
+ 1, 3, 3, 1, 1, 3, 2, 3,
+ 2, 3, 2, 1, 1, 2, 2, 1,
+ 1, 3, 3, 1, 1, 3, 2, 1,
+ 1, 2, 2, 1, 1, 1, 1, 2,
+ 2, 2, 2, 2, 3, 2, 1, 1,
+ 2, 2, 2, 2, 1, 1, 3, 1,
+ 1, 3, 1, 1, 3, 1, 1, 3,
+ 1, 1, 3, 1, 1, 3, 1, 1,
+ 3, 1, 1, 3, 1, 1, 3, 1,
+ 1, 3, 1, 1, 3, 1, 1, 3,
+ 1, 1, 3, 1, 1, 2, 1, 1,
+ 3, 3, 2, 3, 1, 1, 1, 1,
+ 1, 3, 1, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 1, 1, 3, 3, 3, 3, 3
+};
+
+static const short _svg_path_index_offsets[] = {
+ 0, 0, 8, 16, 19, 21, 31, 39,
+ 42, 44, 47, 49, 59, 67, 70, 72,
+ 80, 90, 98, 106, 114, 117, 119, 129,
+ 137, 140, 142, 152, 160, 163, 165, 173,
+ 180, 186, 193, 200, 206, 214, 222, 225,
+ 227, 237, 245, 248, 250, 260, 268, 278,
+ 286, 295, 299, 301, 307, 311, 313, 321,
+ 325, 327, 335, 343, 351, 354, 356, 366,
+ 374, 377, 379, 389, 397, 400, 402, 412,
+ 420, 423, 425, 435, 443, 446, 448, 458,
+ 466, 469, 471, 481, 489, 499, 507, 517,
+ 525, 535, 543, 553, 561, 565, 567, 575,
+ 583, 586, 588, 592, 594, 602, 610, 618,
+ 621, 623, 633, 641, 644, 646, 656, 664,
+ 667, 669, 679, 687, 690, 692, 702, 710,
+ 720, 728, 738, 746, 750, 752, 760, 768,
+ 771, 773, 783, 791, 794, 796, 806, 814,
+ 817, 819, 829, 837, 840, 842, 852, 860,
+ 870, 878, 888, 896, 900, 902, 910, 918,
+ 921, 923, 933, 941, 944, 946, 956, 964,
+ 968, 970, 978, 986, 989, 991, 995, 997,
+ 1005, 1013, 1021, 1029, 1037, 1047, 1055, 1059,
+ 1061, 1069, 1077, 1085, 1093, 1097, 1099, 1107,
+ 1111, 1113, 1121, 1125, 1127, 1135, 1139, 1141,
+ 1149, 1153, 1155, 1163, 1167, 1169, 1177, 1181,
+ 1183, 1191, 1195, 1197, 1205, 1209, 1211, 1219,
+ 1223, 1225, 1233, 1237, 1239, 1247, 1251, 1253,
+ 1261, 1265, 1267, 1275, 1279, 1281, 1289, 1293,
+ 1295, 1303, 1313, 1321, 1329, 1336, 1340, 1342,
+ 1346, 1348, 1356, 1362, 1392, 1420, 1450, 1480,
+ 1510, 1538, 1568, 1596, 1626, 1654, 1684, 1712,
+ 1742, 1770, 1800, 1828, 1858, 1886, 1916, 1944,
+ 1974, 2002, 2032, 2060, 2090, 2118, 2148, 2176,
+ 2206, 2234, 2258, 2282, 2312, 2340, 2368, 2398
+};
+
+static const short _svg_path_indicies[] = {
+ 0, 0, 2, 2, 3, 0, 4, 1,
+ 5, 5, 6, 6, 7, 5, 8, 1,
+ 9, 10, 1, 11, 1, 12, 12, 14,
+ 15, 16, 16, 12, 13, 11, 1, 17,
+ 17, 19, 20, 17, 18, 21, 1, 22,
+ 23, 1, 24, 1, 25, 26, 1, 27,
+ 1, 28, 28, 30, 31, 32, 32, 28,
+ 29, 27, 1, 33, 33, 35, 36, 33,
+ 34, 37, 1, 38, 39, 1, 40, 1,
+ 41, 41, 42, 42, 43, 41, 44, 1,
+ 28, 28, 30, 27, 32, 32, 28, 29,
+ 26, 1, 35, 35, 34, 34, 36, 35,
+ 37, 1, 45, 45, 46, 46, 47, 45,
+ 48, 1, 49, 49, 50, 50, 51, 49,
+ 52, 1, 53, 54, 1, 55, 1, 56,
+ 56, 58, 59, 60, 60, 56, 57, 55,
+ 1, 61, 61, 63, 64, 61, 62, 65,
+ 1, 66, 67, 1, 68, 1, 69, 69,
+ 71, 72, 73, 73, 69, 70, 68, 1,
+ 74, 74, 76, 77, 74, 75, 78, 1,
+ 79, 80, 1, 81, 1, 82, 82, 83,
+ 84, 84, 82, 81, 1, 85, 85, 86,
+ 87, 88, 85, 1, 86, 86, 87, 88,
+ 86, 1, 89, 89, 90, 91, 92, 89,
+ 1, 93, 93, 94, 95, 96, 93, 1,
+ 94, 94, 95, 96, 94, 1, 97, 97,
+ 99, 100, 97, 98, 101, 1, 102, 102,
+ 104, 105, 102, 103, 106, 1, 107, 108,
+ 1, 109, 1, 110, 110, 112, 113, 114,
+ 114, 110, 111, 109, 1, 115, 115, 117,
+ 118, 115, 116, 119, 1, 120, 121, 1,
+ 122, 1, 56, 56, 58, 55, 60, 60,
+ 56, 57, 54, 1, 63, 63, 62, 62,
+ 64, 63, 65, 1, 69, 69, 71, 68,
+ 73, 73, 69, 70, 67, 1, 76, 76,
+ 75, 75, 77, 76, 78, 1, 82, 82,
+ 83, 81, 84, 84, 82, 80, 1, 123,
+ 123, 124, 1, 124, 1, 82, 82, 83,
+ 82, 124, 1, 125, 125, 126, 1, 126,
+ 1, 69, 69, 71, 72, 69, 70, 126,
+ 1, 127, 127, 128, 1, 128, 1, 56,
+ 56, 58, 59, 56, 57, 128, 1, 129,
+ 129, 130, 130, 131, 129, 132, 1, 133,
+ 133, 134, 134, 135, 133, 136, 1, 137,
+ 138, 1, 139, 1, 140, 140, 142, 143,
+ 144, 144, 140, 141, 139, 1, 145, 145,
+ 147, 148, 145, 146, 149, 1, 150, 151,
+ 1, 152, 1, 153, 153, 155, 156, 157,
+ 157, 153, 154, 152, 1, 158, 158, 160,
+ 161, 158, 159, 162, 1, 163, 164, 1,
+ 165, 1, 166, 166, 168, 169, 170, 170,
+ 166, 167, 165, 1, 171, 171, 173, 174,
+ 171, 172, 175, 1, 176, 177, 1, 178,
+ 1, 179, 179, 181, 182, 183, 183, 179,
+ 180, 178, 1, 184, 184, 186, 187, 184,
+ 185, 188, 1, 189, 190, 1, 191, 1,
+ 192, 192, 194, 195, 196, 196, 192, 193,
+ 191, 1, 197, 197, 199, 200, 197, 198,
+ 201, 1, 202, 203, 1, 204, 1, 140,
+ 140, 142, 139, 144, 144, 140, 141, 138,
+ 1, 147, 147, 146, 146, 148, 147, 149,
+ 1, 153, 153, 155, 152, 157, 157, 153,
+ 154, 151, 1, 160, 160, 159, 159, 161,
+ 160, 162, 1, 166, 166, 168, 165, 170,
+ 170, 166, 167, 164, 1, 173, 173, 172,
+ 172, 174, 173, 175, 1, 179, 179, 181,
+ 178, 183, 183, 179, 180, 177, 1, 186,
+ 186, 185, 185, 187, 186, 188, 1, 192,
+ 192, 194, 191, 196, 196, 192, 193, 190,
+ 1, 199, 199, 198, 198, 200, 199, 201,
+ 1, 205, 205, 206, 1, 206, 1, 207,
+ 207, 208, 208, 209, 207, 210, 1, 211,
+ 211, 212, 212, 213, 211, 214, 1, 215,
+ 216, 1, 217, 1, 218, 218, 219, 1,
+ 219, 1, 220, 220, 221, 221, 222, 220,
+ 223, 1, 224, 224, 225, 225, 226, 224,
+ 227, 1, 228, 228, 229, 229, 230, 228,
+ 231, 1, 232, 233, 1, 234, 1, 235,
+ 235, 237, 238, 239, 239, 235, 236, 234,
+ 1, 240, 240, 242, 243, 240, 241, 244,
+ 1, 245, 246, 1, 247, 1, 248, 248,
+ 250, 251, 252, 252, 248, 249, 247, 1,
+ 253, 253, 255, 256, 253, 254, 257, 1,
+ 258, 259, 1, 260, 1, 261, 261, 263,
+ 264, 265, 265, 261, 262, 260, 1, 266,
+ 266, 268, 269, 266, 267, 270, 1, 271,
+ 272, 1, 273, 1, 235, 235, 237, 234,
+ 239, 239, 235, 236, 233, 1, 242, 242,
+ 241, 241, 243, 242, 244, 1, 248, 248,
+ 250, 247, 252, 252, 248, 249, 246, 1,
+ 255, 255, 254, 254, 256, 255, 257, 1,
+ 261, 261, 263, 260, 265, 265, 261, 262,
+ 259, 1, 268, 268, 267, 267, 269, 268,
+ 270, 1, 274, 274, 275, 1, 275, 1,
+ 276, 276, 277, 277, 278, 276, 279, 1,
+ 280, 280, 281, 281, 282, 280, 283, 1,
+ 284, 285, 1, 286, 1, 287, 287, 289,
+ 290, 291, 291, 287, 288, 286, 1, 292,
+ 292, 294, 295, 292, 293, 296, 1, 297,
+ 298, 1, 299, 1, 300, 300, 302, 303,
+ 304, 304, 300, 301, 299, 1, 305, 305,
+ 307, 308, 305, 306, 309, 1, 310, 311,
+ 1, 312, 1, 313, 313, 315, 316, 317,
+ 317, 313, 314, 312, 1, 318, 318, 320,
+ 321, 318, 319, 322, 1, 323, 324, 1,
+ 325, 1, 287, 287, 289, 286, 291, 291,
+ 287, 288, 285, 1, 294, 294, 293, 293,
+ 295, 294, 296, 1, 300, 300, 302, 299,
+ 304, 304, 300, 301, 298, 1, 307, 307,
+ 306, 306, 308, 307, 309, 1, 313, 313,
+ 315, 312, 317, 317, 313, 314, 311, 1,
+ 320, 320, 319, 319, 321, 320, 322, 1,
+ 326, 326, 327, 1, 327, 1, 328, 328,
+ 329, 329, 330, 328, 331, 1, 332, 332,
+ 333, 333, 334, 332, 335, 1, 336, 337,
+ 1, 338, 1, 339, 339, 341, 342, 343,
+ 343, 339, 340, 338, 1, 344, 344, 346,
+ 347, 344, 345, 348, 1, 349, 350, 1,
+ 351, 1, 339, 339, 341, 338, 343, 343,
+ 339, 340, 337, 1, 346, 346, 345, 345,
+ 347, 346, 348, 1, 352, 352, 353, 1,
+ 353, 1, 354, 354, 355, 355, 356, 354,
+ 357, 1, 358, 358, 359, 359, 360, 358,
+ 361, 1, 362, 363, 1, 364, 1, 365,
+ 365, 366, 1, 366, 1, 367, 367, 368,
+ 368, 369, 367, 370, 1, 371, 371, 372,
+ 372, 373, 371, 374, 1, 375, 375, 376,
+ 376, 377, 375, 378, 1, 379, 379, 380,
+ 380, 381, 379, 382, 1, 383, 383, 384,
+ 384, 385, 383, 386, 1, 12, 12, 14,
+ 11, 16, 16, 12, 13, 10, 1, 19,
+ 19, 18, 18, 20, 19, 21, 1, 387,
+ 387, 388, 1, 388, 1, 389, 389, 390,
+ 390, 391, 389, 392, 1, 393, 393, 394,
+ 394, 395, 393, 396, 1, 397, 397, 398,
+ 398, 399, 397, 400, 1, 401, 401, 402,
+ 402, 403, 401, 404, 1, 405, 405, 406,
+ 1, 406, 1, 12, 12, 14, 15, 12,
+ 13, 406, 1, 407, 407, 408, 1, 408,
+ 1, 339, 339, 341, 342, 339, 340, 408,
+ 1, 409, 409, 410, 1, 410, 1, 313,
+ 313, 315, 316, 313, 314, 410, 1, 411,
+ 411, 412, 1, 412, 1, 300, 300, 302,
+ 303, 300, 301, 412, 1, 413, 413, 414,
+ 1, 414, 1, 287, 287, 289, 290, 287,
+ 288, 414, 1, 415, 415, 416, 1, 416,
+ 1, 261, 261, 263, 264, 261, 262, 416,
+ 1, 417, 417, 418, 1, 418, 1, 248,
+ 248, 250, 251, 248, 249, 418, 1, 419,
+ 419, 420, 1, 420, 1, 235, 235, 237,
+ 238, 235, 236, 420, 1, 421, 421, 422,
+ 1, 422, 1, 192, 192, 194, 195, 192,
+ 193, 422, 1, 423, 423, 424, 1, 424,
+ 1, 179, 179, 181, 182, 179, 180, 424,
+ 1, 425, 425, 426, 1, 426, 1, 166,
+ 166, 168, 169, 166, 167, 426, 1, 427,
+ 427, 428, 1, 428, 1, 153, 153, 155,
+ 156, 153, 154, 428, 1, 429, 429, 430,
+ 1, 430, 1, 140, 140, 142, 143, 140,
+ 141, 430, 1, 431, 431, 432, 1, 432,
+ 1, 117, 117, 116, 116, 118, 117, 119,
+ 1, 433, 433, 434, 1, 434, 1, 110,
+ 110, 112, 113, 110, 111, 434, 1, 110,
+ 110, 112, 109, 114, 114, 110, 111, 108,
+ 1, 104, 104, 103, 103, 105, 104, 106,
+ 1, 435, 435, 437, 438, 435, 436, 439,
+ 1, 440, 440, 441, 442, 443, 440, 1,
+ 444, 444, 445, 1, 445, 1, 446, 446,
+ 447, 1, 447, 1, 28, 28, 30, 31,
+ 28, 29, 447, 1, 448, 448, 449, 450,
+ 448, 1, 451, 451, 453, 454, 455, 456,
+ 457, 458, 459, 460, 461, 462, 463, 464,
+ 465, 466, 467, 457, 468, 469, 470, 471,
+ 472, 473, 474, 465, 451, 452, 24, 1,
+ 475, 475, 41, 43, 476, 477, 478, 479,
+ 449, 480, 481, 482, 483, 484, 485, 486,
+ 487, 488, 450, 489, 490, 491, 492, 484,
+ 475, 42, 44, 1, 493, 493, 495, 496,
+ 497, 498, 499, 500, 501, 502, 503, 504,
+ 505, 506, 507, 508, 509, 499, 510, 511,
+ 512, 513, 514, 515, 516, 507, 493, 494,
+ 40, 1, 493, 493, 495, 40, 497, 498,
+ 499, 500, 501, 502, 503, 504, 505, 506,
+ 507, 508, 509, 499, 510, 511, 512, 513,
+ 514, 515, 516, 507, 493, 494, 39, 1,
+ 517, 517, 519, 520, 521, 522, 523, 524,
+ 525, 526, 527, 528, 529, 530, 531, 532,
+ 533, 523, 534, 535, 536, 537, 538, 539,
+ 540, 531, 517, 518, 122, 1, 541, 541,
+ 49, 51, 476, 477, 478, 479, 449, 480,
+ 481, 482, 483, 484, 485, 486, 487, 488,
+ 450, 489, 490, 491, 492, 484, 541, 50,
+ 52, 1, 542, 542, 544, 545, 546, 547,
+ 548, 549, 550, 551, 552, 553, 554, 555,
+ 556, 557, 558, 548, 559, 560, 561, 562,
+ 563, 564, 565, 556, 542, 543, 204, 1,
+ 566, 566, 133, 135, 476, 477, 478, 479,
+ 449, 480, 481, 482, 483, 484, 485, 486,
+ 487, 488, 450, 489, 490, 491, 492, 484,
+ 566, 134, 136, 1, 542, 542, 544, 204,
+ 546, 547, 548, 549, 550, 551, 552, 553,
+ 554, 555, 556, 557, 558, 548, 559, 560,
+ 561, 562, 563, 564, 565, 556, 542, 543,
+ 203, 1, 542, 542, 544, 545, 546, 547,
+ 549, 550, 551, 552, 553, 554, 555, 556,
+ 557, 558, 559, 560, 561, 562, 563, 564,
+ 565, 556, 542, 543, 206, 1, 567, 567,
+ 569, 570, 571, 572, 573, 574, 575, 576,
+ 577, 578, 579, 580, 581, 582, 583, 573,
+ 584, 585, 586, 587, 588, 589, 590, 581,
+ 567, 568, 217, 1, 591, 591, 211, 213,
+ 476, 477, 478, 479, 449, 480, 481, 482,
+ 483, 484, 485, 486, 487, 488, 450, 489,
+ 490, 491, 492, 484, 591, 212, 214, 1,
+ 567, 567, 569, 217, 571, 572, 573, 574,
+ 575, 576, 577, 578, 579, 580, 581, 582,
+ 583, 573, 584, 585, 586, 587, 588, 589,
+ 590, 581, 567, 568, 216, 1, 567, 567,
+ 569, 570, 571, 572, 574, 575, 576, 577,
+ 578, 579, 580, 581, 582, 583, 584, 585,
+ 586, 587, 588, 589, 590, 581, 567, 568,
+ 219, 1, 592, 592, 594, 595, 596, 597,
+ 598, 599, 600, 601, 602, 603, 604, 605,
+ 606, 607, 608, 598, 609, 610, 611, 612,
+ 613, 614, 615, 606, 592, 593, 273, 1,
+ 616, 616, 228, 230, 476, 477, 478, 479,
+ 449, 480, 481, 482, 483, 484, 485, 486,
+ 487, 488, 450, 489, 490, 491, 492, 484,
+ 616, 229, 231, 1, 592, 592, 594, 273,
+ 596, 597, 598, 599, 600, 601, 602, 603,
+ 604, 605, 606, 607, 608, 598, 609, 610,
+ 611, 612, 613, 614, 615, 606, 592, 593,
+ 272, 1, 592, 592, 594, 595, 596, 597,
+ 599, 600, 601, 602, 603, 604, 605, 606,
+ 607, 608, 609, 610, 611, 612, 613, 614,
+ 615, 606, 592, 593, 275, 1, 617, 617,
+ 619, 620, 621, 622, 623, 624, 625, 626,
+ 627, 628, 629, 630, 631, 632, 633, 623,
+ 634, 635, 636, 637, 638, 639, 640, 631,
+ 617, 618, 325, 1, 641, 641, 280, 282,
+ 476, 477, 478, 479, 449, 480, 481, 482,
+ 483, 484, 485, 486, 487, 488, 450, 489,
+ 490, 491, 492, 484, 641, 281, 283, 1,
+ 617, 617, 619, 325, 621, 622, 623, 624,
+ 625, 626, 627, 628, 629, 630, 631, 632,
+ 633, 623, 634, 635, 636, 637, 638, 639,
+ 640, 631, 617, 618, 324, 1, 617, 617,
+ 619, 620, 621, 622, 624, 625, 626, 627,
+ 628, 629, 630, 631, 632, 633, 634, 635,
+ 636, 637, 638, 639, 640, 631, 617, 618,
+ 327, 1, 642, 642, 644, 645, 646, 647,
+ 648, 649, 650, 651, 652, 653, 654, 655,
+ 656, 657, 658, 648, 659, 660, 661, 662,
+ 663, 664, 665, 656, 642, 643, 351, 1,
+ 666, 666, 332, 334, 476, 477, 478, 479,
+ 449, 480, 481, 482, 483, 484, 485, 486,
+ 487, 488, 450, 489, 490, 491, 492, 484,
+ 666, 333, 335, 1, 642, 642, 644, 351,
+ 646, 647, 648, 649, 650, 651, 652, 653,
+ 654, 655, 656, 657, 658, 648, 659, 660,
+ 661, 662, 663, 664, 665, 656, 642, 643,
+ 350, 1, 642, 642, 644, 645, 646, 647,
+ 649, 650, 651, 652, 653, 654, 655, 656,
+ 657, 658, 659, 660, 661, 662, 663, 664,
+ 665, 656, 642, 643, 353, 1, 667, 667,
+ 669, 670, 671, 672, 673, 674, 675, 676,
+ 677, 678, 679, 680, 681, 682, 683, 673,
+ 684, 685, 686, 687, 688, 689, 690, 681,
+ 667, 668, 364, 1, 691, 691, 358, 360,
+ 476, 477, 478, 479, 449, 480, 481, 482,
+ 483, 484, 485, 486, 487, 488, 450, 489,
+ 490, 491, 492, 484, 691, 359, 361, 1,
+ 667, 667, 669, 364, 671, 672, 673, 674,
+ 675, 676, 677, 678, 679, 680, 681, 682,
+ 683, 673, 684, 685, 686, 687, 688, 689,
+ 690, 681, 667, 668, 363, 1, 667, 667,
+ 669, 670, 671, 672, 674, 675, 676, 677,
+ 678, 679, 680, 681, 682, 683, 684, 685,
+ 686, 687, 688, 689, 690, 681, 667, 668,
+ 366, 1, 692, 692, 693, 694, 695, 696,
+ 697, 698, 699, 700, 701, 702, 703, 704,
+ 705, 706, 707, 708, 709, 710, 711, 702,
+ 692, 1, 712, 712, 476, 477, 478, 479,
+ 449, 480, 481, 482, 483, 484, 485, 486,
+ 487, 488, 450, 489, 490, 491, 492, 484,
+ 712, 1, 451, 451, 453, 24, 455, 456,
+ 457, 458, 459, 460, 461, 462, 463, 464,
+ 465, 466, 467, 457, 468, 469, 470, 471,
+ 472, 473, 474, 465, 451, 452, 23, 1,
+ 451, 451, 453, 454, 455, 456, 458, 459,
+ 460, 461, 462, 463, 464, 465, 466, 467,
+ 468, 469, 470, 471, 472, 473, 474, 465,
+ 451, 452, 388, 1, 517, 517, 519, 520,
+ 521, 522, 524, 525, 526, 527, 528, 529,
+ 530, 531, 532, 533, 534, 535, 536, 537,
+ 538, 539, 540, 531, 517, 518, 432, 1,
+ 517, 517, 519, 122, 521, 522, 523, 524,
+ 525, 526, 527, 528, 529, 530, 531, 532,
+ 533, 523, 534, 535, 536, 537, 538, 539,
+ 540, 531, 517, 518, 121, 1, 493, 493,
+ 495, 496, 497, 498, 500, 501, 502, 503,
+ 504, 505, 506, 507, 508, 509, 510, 511,
+ 512, 513, 514, 515, 516, 507, 493, 494,
+ 445, 1, 0
+};
+
+static const short _svg_path_trans_targs[] = {
+ 2, 0, 3, 4, 172, 2, 3, 4,
+ 172, 4, 172, 5, 6, 7, 173, 8,
+ 180, 6, 7, 173, 8, 267, 8, 267,
+ 235, 10, 16, 11, 12, 13, 17, 14,
+ 231, 12, 13, 17, 14, 238, 14, 238,
+ 237, 15, 9, 10, 16, 19, 20, 21,
+ 44, 19, 20, 21, 44, 21, 44, 22,
+ 23, 24, 45, 25, 55, 23, 24, 45,
+ 25, 46, 25, 46, 26, 27, 28, 47,
+ 29, 52, 27, 28, 47, 29, 48, 29,
+ 48, 30, 31, 32, 49, 31, 32, 33,
+ 228, 34, 35, 36, 227, 34, 35, 36,
+ 227, 37, 38, 226, 39, 225, 37, 38,
+ 226, 39, 225, 39, 225, 40, 41, 42,
+ 221, 43, 222, 41, 42, 221, 43, 270,
+ 43, 270, 239, 50, 51, 53, 54, 56,
+ 57, 59, 60, 61, 82, 59, 60, 61,
+ 82, 61, 82, 62, 63, 64, 83, 65,
+ 216, 63, 64, 83, 65, 84, 65, 84,
+ 66, 67, 68, 85, 69, 213, 67, 68,
+ 85, 69, 86, 69, 86, 70, 71, 72,
+ 87, 73, 210, 71, 72, 87, 73, 88,
+ 73, 88, 74, 75, 76, 89, 77, 207,
+ 75, 76, 89, 77, 90, 77, 90, 78,
+ 79, 80, 91, 81, 204, 79, 80, 91,
+ 81, 243, 81, 243, 241, 93, 244, 95,
+ 96, 97, 247, 95, 96, 97, 247, 97,
+ 247, 245, 99, 248, 15, 9, 10, 16,
+ 102, 103, 104, 117, 102, 103, 104, 117,
+ 104, 117, 105, 106, 107, 118, 108, 201,
+ 106, 107, 118, 108, 119, 108, 119, 109,
+ 110, 111, 120, 112, 198, 110, 111, 120,
+ 112, 121, 112, 121, 113, 114, 115, 122,
+ 116, 195, 114, 115, 122, 116, 251, 116,
+ 251, 249, 124, 252, 126, 127, 128, 141,
+ 126, 127, 128, 141, 128, 141, 129, 130,
+ 131, 142, 132, 192, 130, 131, 142, 132,
+ 143, 132, 143, 133, 134, 135, 144, 136,
+ 189, 134, 135, 144, 136, 145, 136, 145,
+ 137, 138, 139, 146, 140, 186, 138, 139,
+ 146, 140, 255, 140, 255, 253, 148, 256,
+ 150, 151, 152, 157, 150, 151, 152, 157,
+ 152, 157, 153, 154, 155, 158, 156, 183,
+ 154, 155, 158, 156, 259, 156, 259, 257,
+ 160, 260, 162, 163, 164, 263, 162, 163,
+ 164, 263, 164, 263, 261, 166, 264, 19,
+ 20, 21, 44, 59, 60, 61, 82, 95,
+ 96, 97, 247, 15, 9, 10, 16, 2,
+ 3, 4, 172, 175, 268, 102, 103, 104,
+ 117, 126, 127, 128, 141, 150, 151, 152,
+ 157, 162, 163, 164, 263, 181, 182, 184,
+ 185, 187, 188, 190, 191, 193, 194, 196,
+ 197, 199, 200, 202, 203, 205, 206, 208,
+ 209, 211, 212, 214, 215, 217, 218, 220,
+ 269, 223, 224, 37, 38, 226, 39, 225,
+ 34, 35, 36, 227, 230, 271, 232, 233,
+ 234, 1, 171, 236, 9, 15, 10, 18,
+ 58, 174, 94, 100, 1, 101, 125, 149,
+ 161, 265, 167, 168, 169, 170, 171, 176,
+ 177, 178, 179, 236, 18, 58, 94, 100,
+ 101, 125, 149, 161, 265, 167, 168, 169,
+ 170, 176, 177, 178, 179, 236, 9, 15,
+ 10, 18, 58, 229, 94, 100, 1, 101,
+ 125, 149, 161, 265, 167, 168, 169, 170,
+ 171, 176, 177, 178, 179, 240, 20, 19,
+ 21, 18, 58, 219, 94, 100, 1, 101,
+ 125, 149, 161, 265, 167, 168, 169, 170,
+ 171, 176, 177, 178, 179, 240, 242, 60,
+ 59, 61, 18, 58, 92, 94, 100, 1,
+ 101, 125, 149, 161, 265, 167, 168, 169,
+ 170, 171, 176, 177, 178, 179, 242, 246,
+ 96, 95, 97, 18, 58, 98, 94, 100,
+ 1, 101, 125, 149, 161, 265, 167, 168,
+ 169, 170, 171, 176, 177, 178, 179, 246,
+ 250, 103, 102, 104, 18, 58, 123, 94,
+ 100, 1, 101, 125, 149, 161, 265, 167,
+ 168, 169, 170, 171, 176, 177, 178, 179,
+ 250, 254, 127, 126, 128, 18, 58, 147,
+ 94, 100, 1, 101, 125, 149, 161, 265,
+ 167, 168, 169, 170, 171, 176, 177, 178,
+ 179, 254, 258, 151, 150, 152, 18, 58,
+ 159, 94, 100, 1, 101, 125, 149, 161,
+ 265, 167, 168, 169, 170, 171, 176, 177,
+ 178, 179, 258, 262, 163, 162, 164, 18,
+ 58, 165, 94, 100, 1, 101, 125, 149,
+ 161, 265, 167, 168, 169, 170, 171, 176,
+ 177, 178, 179, 262, 266, 18, 58, 94,
+ 100, 1, 101, 125, 149, 161, 265, 167,
+ 168, 169, 170, 171, 176, 177, 178, 179,
+ 266
+};
+
+static const char _svg_path_trans_actions[] = {
+ 9, 0, 51, 51, 51, 0, 1, 1,
+ 1, 0, 0, 0, 3, 15, 3, 15,
+ 0, 0, 1, 0, 1, 1, 0, 0,
+ 0, 0, 0, 0, 3, 15, 3, 15,
+ 0, 0, 1, 0, 1, 1, 0, 0,
+ 0, 0, 1, 1, 1, 9, 51, 51,
+ 51, 0, 1, 1, 1, 0, 0, 0,
+ 3, 15, 3, 15, 0, 0, 1, 0,
+ 1, 1, 0, 0, 0, 3, 15, 3,
+ 15, 0, 0, 1, 0, 1, 1, 0,
+ 0, 0, 3, 3, 0, 0, 0, 0,
+ 0, 7, 7, 7, 7, 0, 0, 0,
+ 0, 7, 48, 7, 48, 48, 0, 1,
+ 0, 1, 1, 0, 0, 0, 3, 15,
+ 3, 15, 0, 0, 1, 0, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 9, 51, 51, 51, 0, 1, 1,
+ 1, 0, 0, 0, 3, 15, 3, 15,
+ 0, 0, 1, 0, 1, 1, 0, 0,
+ 0, 3, 15, 3, 15, 0, 0, 1,
+ 0, 1, 1, 0, 0, 0, 3, 15,
+ 3, 15, 0, 0, 1, 0, 1, 1,
+ 0, 0, 0, 3, 15, 3, 15, 0,
+ 0, 1, 0, 1, 1, 0, 0, 0,
+ 3, 15, 3, 15, 0, 0, 1, 0,
+ 1, 1, 0, 0, 0, 0, 0, 9,
+ 51, 51, 51, 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 9, 51, 51, 51,
+ 9, 51, 51, 51, 0, 1, 1, 1,
+ 0, 0, 0, 3, 15, 3, 15, 0,
+ 0, 1, 0, 1, 1, 0, 0, 0,
+ 3, 15, 3, 15, 0, 0, 1, 0,
+ 1, 1, 0, 0, 0, 3, 15, 3,
+ 15, 0, 0, 1, 0, 1, 1, 0,
+ 0, 0, 0, 0, 9, 51, 51, 51,
+ 0, 1, 1, 1, 0, 0, 0, 3,
+ 15, 3, 15, 0, 0, 1, 0, 1,
+ 1, 0, 0, 0, 3, 15, 3, 15,
+ 0, 0, 1, 0, 1, 1, 0, 0,
+ 0, 3, 15, 3, 15, 0, 0, 1,
+ 0, 1, 1, 0, 0, 0, 0, 0,
+ 9, 51, 51, 51, 0, 1, 1, 1,
+ 0, 0, 0, 3, 15, 3, 15, 0,
+ 0, 1, 0, 1, 1, 0, 0, 0,
+ 0, 0, 9, 51, 51, 51, 0, 1,
+ 1, 1, 0, 0, 0, 0, 0, 11,
+ 54, 54, 54, 11, 54, 54, 54, 11,
+ 54, 54, 54, 11, 54, 54, 54, 11,
+ 54, 54, 54, 0, 0, 11, 54, 54,
+ 54, 11, 54, 54, 54, 11, 54, 54,
+ 54, 11, 54, 54, 54, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 5, 45, 5, 45, 45,
+ 5, 5, 5, 5, 0, 0, 0, 0,
+ 0, 0, 0, 18, 57, 18, 57, 18,
+ 18, 0, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 21, 61, 21,
+ 61, 21, 21, 0, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 42, 89, 42,
+ 89, 42, 42, 0, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 0, 30, 73,
+ 30, 73, 30, 30, 0, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 0, 24,
+ 65, 24, 65, 24, 24, 0, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 0,
+ 36, 81, 36, 81, 36, 36, 0, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 0, 33, 77, 33, 77, 33, 33, 0,
+ 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 0, 39, 85, 39, 85, 39, 39,
+ 0, 39, 39, 39, 39, 39, 39, 39,
+ 39, 39, 39, 39, 39, 39, 39, 39,
+ 39, 39, 0, 27, 69, 27, 69, 27,
+ 27, 0, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 0, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13,
+ 0
+};
+
+static const char _svg_path_eof_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 18, 0, 21, 21, 42,
+ 0, 30, 0, 30, 30, 24, 0, 24,
+ 24, 36, 0, 36, 36, 33, 0, 33,
+ 33, 39, 0, 39, 39, 27, 0, 27,
+ 27, 13, 0, 18, 18, 42, 42, 21
+};
+
+static const int svg_path_start = 234;
+static const int svg_path_first_final = 234;
+
+static const int svg_path_en_main = 234;
+
+
+#line 47 "svg-path-parser.rl"
+
+
+SVGPathParser::SVGPathParser(PathSink &sink)
+ : _absolute(false)
+ , _sink(sink)
+ , _z_snap_threshold(0)
+ , _curve(NULL)
+{
+ reset();
+}
+
+SVGPathParser::~SVGPathParser()
+{
+ delete _curve;
+}
+
+void SVGPathParser::reset() {
+ _absolute = false;
+ _current = _initial = Point(0, 0);
+ _quad_tangent = _cubic_tangent = Point(0, 0);
+ _params.clear();
+ delete _curve;
+ _curve = NULL;
+
+
+#line 1113 "svg-path-parser.cpp"
+ {
+ cs = svg_path_start;
+ }
+
+#line 73 "svg-path-parser.rl"
+
+}
+
+void SVGPathParser::parse(char const *str, int len)
+{
+ if (len < 0) {
+ len = std::strlen(str);
+ }
+ _parse(str, str + len, true);
+}
+
+void SVGPathParser::parse(std::string const &s)
+{
+ _parse(s.c_str(), s.c_str() + s.size(), true);
+}
+
+void SVGPathParser::feed(char const *str, int len)
+{
+ if (len < 0) {
+ len = std::strlen(str);
+ }
+ _parse(str, str + len, false);
+}
+
+void SVGPathParser::feed(std::string const &s)
+{
+ _parse(s.c_str(), s.c_str() + s.size(), false);
+}
+
+void SVGPathParser::finish()
+{
+ char const *empty = "";
+ _parse(empty, empty, true);
+}
+
+void SVGPathParser::_push(Coord value)
+{
+ _params.push_back(value);
+}
+
+Coord SVGPathParser::_pop()
+{
+ Coord value = _params.back();
+ _params.pop_back();
+ return value;
+}
+
+bool SVGPathParser::_pop_flag()
+{
+ return _pop() != 0.0;
+}
+
+Coord SVGPathParser::_pop_coord(Dim2 axis)
+{
+ if (_absolute) {
+ return _pop();
+ } else {
+ return _pop() + _current[axis];
+ }
+}
+
+Point SVGPathParser::_pop_point()
+{
+ Coord y = _pop_coord(Y);
+ Coord x = _pop_coord(X);
+ return Point(x, y);
+}
+
+void SVGPathParser::_moveTo(Point const &p)
+{
+ _pushCurve(NULL); // flush
+ _sink.moveTo(p);
+ _quad_tangent = _cubic_tangent = _current = _initial = p;
+}
+
+void SVGPathParser::_lineTo(Point const &p)
+{
+ _pushCurve(new LineSegment(_current, p));
+ _quad_tangent = _cubic_tangent = _current = p;
+}
+
+void SVGPathParser::_curveTo(Point const &c0, Point const &c1, Point const &p)
+{
+ _pushCurve(new CubicBezier(_current, c0, c1, p));
+ _quad_tangent = _current = p;
+ _cubic_tangent = p + ( p - c1 );
+}
+
+void SVGPathParser::_quadTo(Point const &c, Point const &p)
+{
+ _pushCurve(new QuadraticBezier(_current, c, p));
+ _cubic_tangent = _current = p;
+ _quad_tangent = p + ( p - c );
+}
+
+void SVGPathParser::_arcTo(Coord rx, Coord ry, Coord angle,
+ bool large_arc, bool sweep, Point const &p)
+{
+ if (_current == p) {
+ return; // ignore invalid (ambiguous) arc segments where start and end point are the same (per SVG spec)
+ }
+
+ _pushCurve(new EllipticalArc(_current, fabs(rx), fabs(ry), angle, large_arc, sweep, p));
+ _quad_tangent = _cubic_tangent = _current = p;
+}
+
+void SVGPathParser::_closePath()
+{
+ if (_curve && (!_absolute || !_moveto_was_absolute) &&
+ are_near(_initial, _current, _z_snap_threshold))
+ {
+ _curve->setFinal(_initial);
+ }
+
+ _pushCurve(NULL); // flush
+ _sink.closePath();
+ _quad_tangent = _cubic_tangent = _current = _initial;
+}
+
+void SVGPathParser::_pushCurve(Curve *c)
+{
+ if (_curve) {
+ _sink.feed(*_curve, false);
+ delete _curve;
+ }
+ _curve = c;
+}
+
+void SVGPathParser::_parse(char const *str, char const *strend, bool finish)
+{
+ char const *p = str;
+ char const *pe = strend;
+ char const *eof = finish ? pe : NULL;
+ char const *start = NULL;
+
+
+#line 1255 "svg-path-parser.cpp"
+ {
+ int _klen;
+ unsigned int _trans;
+ const char *_acts;
+ unsigned int _nacts;
+ const char *_keys;
+
+ if ( p == pe )
+ goto _test_eof;
+ if ( cs == 0 )
+ goto _out;
+_resume:
+ _keys = _svg_path_trans_keys + _svg_path_key_offsets[cs];
+ _trans = _svg_path_index_offsets[cs];
+
+ _klen = _svg_path_single_lengths[cs];
+ if ( _klen > 0 ) {
+ const char *_lower = _keys;
+ const char *_mid;
+ const char *_upper = _keys + _klen - 1;
+ while (1) {
+ if ( _upper < _lower )
+ break;
+
+ _mid = _lower + ((_upper-_lower) >> 1);
+ if ( (*p) < *_mid )
+ _upper = _mid - 1;
+ else if ( (*p) > *_mid )
+ _lower = _mid + 1;
+ else {
+ _trans += (unsigned int)(_mid - _keys);
+ goto _match;
+ }
+ }
+ _keys += _klen;
+ _trans += _klen;
+ }
+
+ _klen = _svg_path_range_lengths[cs];
+ if ( _klen > 0 ) {
+ const char *_lower = _keys;
+ const char *_mid;
+ const char *_upper = _keys + (_klen<<1) - 2;
+ while (1) {
+ if ( _upper < _lower )
+ break;
+
+ _mid = _lower + (((_upper-_lower) >> 1) & ~1);
+ if ( (*p) < _mid[0] )
+ _upper = _mid - 2;
+ else if ( (*p) > _mid[1] )
+ _lower = _mid + 2;
+ else {
+ _trans += (unsigned int)((_mid - _keys)>>1);
+ goto _match;
+ }
+ }
+ _trans += _klen;
+ }
+
+_match:
+ _trans = _svg_path_indicies[_trans];
+ cs = _svg_path_trans_targs[_trans];
+
+ if ( _svg_path_trans_actions[_trans] == 0 )
+ goto _again;
+
+ _acts = _svg_path_actions + _svg_path_trans_actions[_trans];
+ _nacts = (unsigned int) *_acts++;
+ while ( _nacts-- > 0 )
+ {
+ switch ( *_acts++ )
+ {
+ case 0:
+#line 209 "svg-path-parser.rl"
+ {
+ start = p;
+ }
+ break;
+ case 1:
+#line 213 "svg-path-parser.rl"
+ {
+ if (start) {
+ std::string buf(start, p);
+ _push(g_ascii_strtod(buf.c_str(), NULL));
+ start = NULL;
+ } else {
+ std::string buf(str, p);
+ _push(g_ascii_strtod((_number_part + buf).c_str(), NULL));
+ _number_part.clear();
+ }
+ }
+ break;
+ case 2:
+#line 225 "svg-path-parser.rl"
+ {
+ _push(1.0);
+ }
+ break;
+ case 3:
+#line 229 "svg-path-parser.rl"
+ {
+ _push(0.0);
+ }
+ break;
+ case 4:
+#line 233 "svg-path-parser.rl"
+ {
+ _absolute = true;
+ }
+ break;
+ case 5:
+#line 237 "svg-path-parser.rl"
+ {
+ _absolute = false;
+ }
+ break;
+ case 6:
+#line 241 "svg-path-parser.rl"
+ {
+ _moveto_was_absolute = _absolute;
+ _moveTo(_pop_point());
+ }
+ break;
+ case 7:
+#line 246 "svg-path-parser.rl"
+ {
+ _lineTo(_pop_point());
+ }
+ break;
+ case 8:
+#line 250 "svg-path-parser.rl"
+ {
+ _lineTo(Point(_pop_coord(X), _current[Y]));
+ }
+ break;
+ case 9:
+#line 254 "svg-path-parser.rl"
+ {
+ _lineTo(Point(_current[X], _pop_coord(Y)));
+ }
+ break;
+ case 10:
+#line 258 "svg-path-parser.rl"
+ {
+ Point p = _pop_point();
+ Point c1 = _pop_point();
+ Point c0 = _pop_point();
+ _curveTo(c0, c1, p);
+ }
+ break;
+ case 11:
+#line 265 "svg-path-parser.rl"
+ {
+ Point p = _pop_point();
+ Point c1 = _pop_point();
+ _curveTo(_cubic_tangent, c1, p);
+ }
+ break;
+ case 12:
+#line 271 "svg-path-parser.rl"
+ {
+ Point p = _pop_point();
+ Point c = _pop_point();
+ _quadTo(c, p);
+ }
+ break;
+ case 13:
+#line 277 "svg-path-parser.rl"
+ {
+ Point p = _pop_point();
+ _quadTo(_quad_tangent, p);
+ }
+ break;
+ case 14:
+#line 282 "svg-path-parser.rl"
+ {
+ Point point = _pop_point();
+ bool sweep = _pop_flag();
+ bool large_arc = _pop_flag();
+ double angle = rad_from_deg(_pop());
+ double ry = _pop();
+ double rx = _pop();
+
+ _arcTo(rx, ry, angle, large_arc, sweep, point);
+ }
+ break;
+ case 15:
+#line 293 "svg-path-parser.rl"
+ {
+ _closePath();
+ }
+ break;
+#line 1449 "svg-path-parser.cpp"
+ }
+ }
+
+_again:
+ if ( cs == 0 )
+ goto _out;
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ if ( p == eof )
+ {
+ const char *__acts = _svg_path_actions + _svg_path_eof_actions[cs];
+ unsigned int __nacts = (unsigned int) *__acts++;
+ while ( __nacts-- > 0 ) {
+ switch ( *__acts++ ) {
+ case 1:
+#line 213 "svg-path-parser.rl"
+ {
+ if (start) {
+ std::string buf(start, p);
+ _push(g_ascii_strtod(buf.c_str(), NULL));
+ start = NULL;
+ } else {
+ std::string buf(str, p);
+ _push(g_ascii_strtod((_number_part + buf).c_str(), NULL));
+ _number_part.clear();
+ }
+ }
+ break;
+ case 6:
+#line 241 "svg-path-parser.rl"
+ {
+ _moveto_was_absolute = _absolute;
+ _moveTo(_pop_point());
+ }
+ break;
+ case 7:
+#line 246 "svg-path-parser.rl"
+ {
+ _lineTo(_pop_point());
+ }
+ break;
+ case 8:
+#line 250 "svg-path-parser.rl"
+ {
+ _lineTo(Point(_pop_coord(X), _current[Y]));
+ }
+ break;
+ case 9:
+#line 254 "svg-path-parser.rl"
+ {
+ _lineTo(Point(_current[X], _pop_coord(Y)));
+ }
+ break;
+ case 10:
+#line 258 "svg-path-parser.rl"
+ {
+ Point p = _pop_point();
+ Point c1 = _pop_point();
+ Point c0 = _pop_point();
+ _curveTo(c0, c1, p);
+ }
+ break;
+ case 11:
+#line 265 "svg-path-parser.rl"
+ {
+ Point p = _pop_point();
+ Point c1 = _pop_point();
+ _curveTo(_cubic_tangent, c1, p);
+ }
+ break;
+ case 12:
+#line 271 "svg-path-parser.rl"
+ {
+ Point p = _pop_point();
+ Point c = _pop_point();
+ _quadTo(c, p);
+ }
+ break;
+ case 13:
+#line 277 "svg-path-parser.rl"
+ {
+ Point p = _pop_point();
+ _quadTo(_quad_tangent, p);
+ }
+ break;
+ case 14:
+#line 282 "svg-path-parser.rl"
+ {
+ Point point = _pop_point();
+ bool sweep = _pop_flag();
+ bool large_arc = _pop_flag();
+ double angle = rad_from_deg(_pop());
+ double ry = _pop();
+ double rx = _pop();
+
+ _arcTo(rx, ry, angle, large_arc, sweep, point);
+ }
+ break;
+ case 15:
+#line 293 "svg-path-parser.rl"
+ {
+ _closePath();
+ }
+ break;
+#line 1555 "svg-path-parser.cpp"
+ }
+ }
+ }
+
+ _out: {}
+ }
+
+#line 435 "svg-path-parser.rl"
+
+
+ if (finish) {
+ if (cs < svg_path_first_final) {
+ throw SVGPathParseError();
+ }
+ } else if (start != NULL) {
+ _number_part = std::string(start, pe);
+ }
+
+ if (finish) {
+ _pushCurve(NULL);
+ _sink.flush();
+ reset();
+ }
+}
+
+void parse_svg_path(char const *str, PathSink &sink)
+{
+ SVGPathParser parser(sink);
+ parser.parse(str);
+}
+
+void parse_svg_path_file(FILE *fi, PathSink &sink)
+{
+ static const size_t BUFFER_SIZE = 4096;
+ char buffer[BUFFER_SIZE];
+ size_t bytes_read;
+ SVGPathParser parser(sink);
+
+ while (true) {
+ bytes_read = fread(buffer, 1, BUFFER_SIZE, fi);
+ if (bytes_read < BUFFER_SIZE) {
+ parser.parse(buffer, bytes_read);
+ break;
+ } else {
+ parser.feed(buffer, bytes_read);
+ }
+ }
+}
+
+} // namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=ragel:cindent:expandtab:shiftwidth=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/svg-path-parser.rl b/src/3rdparty/2geom/src/2geom/svg-path-parser.rl
new file mode 100644
index 0000000..7b3eb5a
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/svg-path-parser.rl
@@ -0,0 +1,487 @@
+/**
+ * \file
+ * \brief parse SVG path specifications
+ *
+ * Copyright 2007 MenTaLguY <mental@rydia.net>
+ * Copyright 2007 Aaron Spike <aaron@ekips.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <cstdio>
+#include <cmath>
+#include <vector>
+#include <glib.h>
+
+#include <2geom/point.h>
+#include <2geom/svg-path-parser.h>
+#include <2geom/angle.h>
+
+namespace Geom {
+
+%%{
+ machine svg_path;
+ write data noerror;
+}%%
+
+SVGPathParser::SVGPathParser(PathSink &sink)
+ : _absolute(false)
+ , _sink(sink)
+ , _z_snap_threshold(0)
+ , _curve(NULL)
+{
+ reset();
+}
+
+SVGPathParser::~SVGPathParser()
+{
+ delete _curve;
+}
+
+void SVGPathParser::reset() {
+ _absolute = false;
+ _current = _initial = Point(0, 0);
+ _quad_tangent = _cubic_tangent = Point(0, 0);
+ _params.clear();
+ delete _curve;
+ _curve = NULL;
+
+ %%{
+ write init;
+ }%%
+}
+
+void SVGPathParser::parse(char const *str, int len)
+{
+ if (len < 0) {
+ len = std::strlen(str);
+ }
+ _parse(str, str + len, true);
+}
+
+void SVGPathParser::parse(std::string const &s)
+{
+ _parse(s.c_str(), s.c_str() + s.size(), true);
+}
+
+void SVGPathParser::feed(char const *str, int len)
+{
+ if (len < 0) {
+ len = std::strlen(str);
+ }
+ _parse(str, str + len, false);
+}
+
+void SVGPathParser::feed(std::string const &s)
+{
+ _parse(s.c_str(), s.c_str() + s.size(), false);
+}
+
+void SVGPathParser::finish()
+{
+ char const *empty = "";
+ _parse(empty, empty, true);
+}
+
+void SVGPathParser::_push(Coord value)
+{
+ _params.push_back(value);
+}
+
+Coord SVGPathParser::_pop()
+{
+ Coord value = _params.back();
+ _params.pop_back();
+ return value;
+}
+
+bool SVGPathParser::_pop_flag()
+{
+ return _pop() != 0.0;
+}
+
+Coord SVGPathParser::_pop_coord(Dim2 axis)
+{
+ if (_absolute) {
+ return _pop();
+ } else {
+ return _pop() + _current[axis];
+ }
+}
+
+Point SVGPathParser::_pop_point()
+{
+ Coord y = _pop_coord(Y);
+ Coord x = _pop_coord(X);
+ return Point(x, y);
+}
+
+void SVGPathParser::_moveTo(Point const &p)
+{
+ _pushCurve(NULL); // flush
+ _sink.moveTo(p);
+ _quad_tangent = _cubic_tangent = _current = _initial = p;
+}
+
+void SVGPathParser::_lineTo(Point const &p)
+{
+ _pushCurve(new LineSegment(_current, p));
+ _quad_tangent = _cubic_tangent = _current = p;
+}
+
+void SVGPathParser::_curveTo(Point const &c0, Point const &c1, Point const &p)
+{
+ _pushCurve(new CubicBezier(_current, c0, c1, p));
+ _quad_tangent = _current = p;
+ _cubic_tangent = p + ( p - c1 );
+}
+
+void SVGPathParser::_quadTo(Point const &c, Point const &p)
+{
+ _pushCurve(new QuadraticBezier(_current, c, p));
+ _cubic_tangent = _current = p;
+ _quad_tangent = p + ( p - c );
+}
+
+void SVGPathParser::_arcTo(Coord rx, Coord ry, Coord angle,
+ bool large_arc, bool sweep, Point const &p)
+{
+ if (_current == p) {
+ return; // ignore invalid (ambiguous) arc segments where start and end point are the same (per SVG spec)
+ }
+
+ _pushCurve(new EllipticalArc(_current, fabs(rx), fabs(ry), angle, large_arc, sweep, p));
+ _quad_tangent = _cubic_tangent = _current = p;
+}
+
+void SVGPathParser::_closePath()
+{
+ if (_curve && (!_absolute || !_moveto_was_absolute) &&
+ are_near(_initial, _current, _z_snap_threshold))
+ {
+ _curve->setFinal(_initial);
+ }
+
+ _pushCurve(NULL); // flush
+ _sink.closePath();
+ _quad_tangent = _cubic_tangent = _current = _initial;
+}
+
+void SVGPathParser::_pushCurve(Curve *c)
+{
+ if (_curve) {
+ _sink.feed(*_curve, false);
+ delete _curve;
+ }
+ _curve = c;
+}
+
+void SVGPathParser::_parse(char const *str, char const *strend, bool finish)
+{
+ char const *p = str;
+ char const *pe = strend;
+ char const *eof = finish ? pe : NULL;
+ char const *start = NULL;
+
+ %%{
+ action start_number {
+ start = p;
+ }
+
+ action push_number {
+ if (start) {
+ std::string buf(start, p);
+ _push(g_ascii_strtod(buf.c_str(), NULL));
+ start = NULL;
+ } else {
+ std::string buf(str, p);
+ _push(g_ascii_strtod((_number_part + buf).c_str(), NULL));
+ _number_part.clear();
+ }
+ }
+
+ action push_true {
+ _push(1.0);
+ }
+
+ action push_false {
+ _push(0.0);
+ }
+
+ action mode_abs {
+ _absolute = true;
+ }
+
+ action mode_rel {
+ _absolute = false;
+ }
+
+ action moveto {
+ _moveto_was_absolute = _absolute;
+ _moveTo(_pop_point());
+ }
+
+ action lineto {
+ _lineTo(_pop_point());
+ }
+
+ action horizontal_lineto {
+ _lineTo(Point(_pop_coord(X), _current[Y]));
+ }
+
+ action vertical_lineto {
+ _lineTo(Point(_current[X], _pop_coord(Y)));
+ }
+
+ action curveto {
+ Point p = _pop_point();
+ Point c1 = _pop_point();
+ Point c0 = _pop_point();
+ _curveTo(c0, c1, p);
+ }
+
+ action smooth_curveto {
+ Point p = _pop_point();
+ Point c1 = _pop_point();
+ _curveTo(_cubic_tangent, c1, p);
+ }
+
+ action quadratic_bezier_curveto {
+ Point p = _pop_point();
+ Point c = _pop_point();
+ _quadTo(c, p);
+ }
+
+ action smooth_quadratic_bezier_curveto {
+ Point p = _pop_point();
+ _quadTo(_quad_tangent, p);
+ }
+
+ action elliptical_arc {
+ Point point = _pop_point();
+ bool sweep = _pop_flag();
+ bool large_arc = _pop_flag();
+ double angle = rad_from_deg(_pop());
+ double ry = _pop();
+ double rx = _pop();
+
+ _arcTo(rx, ry, angle, large_arc, sweep, point);
+ }
+
+ action closepath {
+ _closePath();
+ }
+
+ wsp = (' ' | 9 | 10 | 13);
+ sign = ('+' | '-');
+ digit_sequence = digit+;
+ exponent = ('e' | 'E') sign? digit_sequence;
+ fractional_constant =
+ digit_sequence? '.' digit_sequence
+ | digit_sequence '.';
+ floating_point_constant =
+ fractional_constant exponent?
+ | digit_sequence exponent;
+ integer_constant = digit_sequence;
+ comma = ',';
+ comma_wsp = (wsp+ comma? wsp*) | (comma wsp*);
+
+ flag = ('0' %push_false | '1' %push_true);
+
+ number =
+ ( sign? integer_constant
+ | sign? floating_point_constant )
+ >start_number %push_number;
+
+ nonnegative_number =
+ ( integer_constant
+ | floating_point_constant)
+ >start_number %push_number;
+
+ coordinate = number $(number,1) %(number,0);
+ coordinate_pair = (coordinate $(coordinate_pair_a,1) %(coordinate_pair_a,0) comma_wsp? coordinate $(coordinate_pair_b,1) %(coordinate_pair_b,0)) $(coordinate_pair,1) %(coordinate_pair,0);
+ elliptical_arc_argument =
+ (number $(elliptical_arg_a,1) %(elliptical_arg_a,0) comma_wsp?
+ number $(elliptical_arg_b,1) %(elliptical_arg_b,0) comma_wsp?
+ number comma_wsp
+ flag comma_wsp? flag comma_wsp?
+ coordinate_pair)
+ %elliptical_arc;
+ elliptical_arc_argument_sequence =
+ elliptical_arc_argument $1 %0
+ (comma_wsp? elliptical_arc_argument $1 %0)*;
+ elliptical_arc =
+ ('A' %mode_abs| 'a' %mode_rel) wsp*
+ elliptical_arc_argument_sequence;
+
+ smooth_quadratic_bezier_curveto_argument =
+ coordinate_pair %smooth_quadratic_bezier_curveto;
+ smooth_quadratic_bezier_curveto_argument_sequence =
+ smooth_quadratic_bezier_curveto_argument $1 %0
+ (comma_wsp?
+ smooth_quadratic_bezier_curveto_argument $1 %0)*;
+ smooth_quadratic_bezier_curveto =
+ ('T' %mode_abs| 't' %mode_rel) wsp*
+ smooth_quadratic_bezier_curveto_argument_sequence;
+
+ quadratic_bezier_curveto_argument =
+ (coordinate_pair $1 %0 comma_wsp? coordinate_pair)
+ %quadratic_bezier_curveto;
+ quadratic_bezier_curveto_argument_sequence =
+ quadratic_bezier_curveto_argument $1 %0
+ (comma_wsp? quadratic_bezier_curveto_argument $1 %0)*;
+ quadratic_bezier_curveto =
+ ('Q' %mode_abs| 'q' %mode_rel) wsp*
+ quadratic_bezier_curveto_argument_sequence;
+
+ smooth_curveto_argument =
+ (coordinate_pair $1 %0 comma_wsp? coordinate_pair)
+ %smooth_curveto;
+ smooth_curveto_argument_sequence =
+ smooth_curveto_argument $1 %0
+ (comma_wsp? smooth_curveto_argument $1 %0)*;
+ smooth_curveto =
+ ('S' %mode_abs| 's' %mode_rel)
+ wsp* smooth_curveto_argument_sequence;
+
+ curveto_argument =
+ (coordinate_pair $1 %0 comma_wsp?
+ coordinate_pair $1 %0 comma_wsp?
+ coordinate_pair)
+ %curveto;
+ curveto_argument_sequence =
+ curveto_argument $1 %0
+ (comma_wsp? curveto_argument $1 %0)*;
+ curveto =
+ ('C' %mode_abs| 'c' %mode_rel)
+ wsp* curveto_argument_sequence;
+
+ vertical_lineto_argument = coordinate %vertical_lineto;
+ vertical_lineto_argument_sequence =
+ vertical_lineto_argument $(vertical_lineto_argument_a,1) %(vertical_lineto_argument_a,0)
+ (comma_wsp? vertical_lineto_argument $(vertical_lineto_argument_b,1) %(vertical_lineto_argument_b,0))*;
+ vertical_lineto =
+ ('V' %mode_abs| 'v' %mode_rel)
+ wsp* vertical_lineto_argument_sequence;
+
+ horizontal_lineto_argument = coordinate %horizontal_lineto;
+ horizontal_lineto_argument_sequence =
+ horizontal_lineto_argument $(horizontal_lineto_argument_a,1) %(horizontal_lineto_argument_a,0)
+ (comma_wsp? horizontal_lineto_argument $(horizontal_lineto_argument_b,1) %(horizontal_lineto_argument_b,0))*;
+ horizontal_lineto =
+ ('H' %mode_abs| 'h' %mode_rel)
+ wsp* horizontal_lineto_argument_sequence;
+
+ lineto_argument = coordinate_pair %lineto;
+ lineto_argument_sequence =
+ lineto_argument $1 %0
+ (comma_wsp? lineto_argument $1 %0)*;
+ lineto =
+ ('L' %mode_abs| 'l' %mode_rel) wsp*
+ lineto_argument_sequence;
+
+ closepath = ('Z' | 'z') %closepath;
+
+ moveto_argument = coordinate_pair %moveto;
+ moveto_argument_sequence =
+ moveto_argument $1 %0
+ (comma_wsp? lineto_argument $1 %0)*;
+ moveto =
+ ('M' %mode_abs | 'm' %mode_rel)
+ wsp* moveto_argument_sequence;
+
+ drawto_command =
+ closepath | lineto |
+ horizontal_lineto | vertical_lineto |
+ curveto | smooth_curveto |
+ quadratic_bezier_curveto |
+ smooth_quadratic_bezier_curveto |
+ elliptical_arc;
+
+ drawto_commands = drawto_command (wsp* drawto_command)*;
+ moveto_drawto_command_group = moveto wsp* drawto_commands?;
+ moveto_drawto_command_groups =
+ moveto_drawto_command_group
+ (wsp* moveto_drawto_command_group)*;
+
+ svg_path = wsp* moveto_drawto_command_groups? wsp*;
+
+
+ main := svg_path;
+
+ write exec;
+ }%%
+
+ if (finish) {
+ if (cs < svg_path_first_final) {
+ throw SVGPathParseError();
+ }
+ } else if (start != NULL) {
+ _number_part = std::string(start, pe);
+ }
+
+ if (finish) {
+ _pushCurve(NULL);
+ _sink.flush();
+ reset();
+ }
+}
+
+void parse_svg_path(char const *str, PathSink &sink)
+{
+ SVGPathParser parser(sink);
+ parser.parse(str);
+}
+
+void parse_svg_path_file(FILE *fi, PathSink &sink)
+{
+ static const size_t BUFFER_SIZE = 4096;
+ char buffer[BUFFER_SIZE];
+ size_t bytes_read;
+ SVGPathParser parser(sink);
+
+ while (true) {
+ bytes_read = fread(buffer, 1, BUFFER_SIZE, fi);
+ if (bytes_read < BUFFER_SIZE) {
+ parser.parse(buffer, bytes_read);
+ break;
+ } else {
+ parser.feed(buffer, bytes_read);
+ }
+ }
+}
+
+} // namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=ragel:cindent:expandtab:shiftwidth=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/svg-path-writer.cpp b/src/3rdparty/2geom/src/2geom/svg-path-writer.cpp
new file mode 100644
index 0000000..1b8cabe
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/svg-path-writer.cpp
@@ -0,0 +1,296 @@
+/** @file
+ * @brief Path sink which writes an SVG-compatible command string
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2014 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <cmath>
+#include <iomanip>
+#include <2geom/coord.h>
+#include <2geom/svg-path-writer.h>
+#include <glib.h>
+
+namespace Geom {
+
+static inline bool is_digit(char c) {
+ return c >= '0' && c <= '9';
+}
+
+SVGPathWriter::SVGPathWriter()
+ : _epsilon(0)
+ , _precision(-1)
+ , _optimize(false)
+ , _use_shorthands(true)
+ , _command(0)
+{
+ // always use C locale for number formatting
+ _ns.imbue(std::locale::classic());
+ _ns.unsetf(std::ios::floatfield);
+}
+
+void SVGPathWriter::moveTo(Point const &p)
+{
+ _setCommand('M');
+ _current_pars.push_back(p[X]);
+ _current_pars.push_back(p[Y]);
+
+ _current = _subpath_start = _quad_tangent = _cubic_tangent = p;
+ if (!_optimize) {
+ flush();
+ }
+}
+
+void SVGPathWriter::lineTo(Point const &p)
+{
+ // The weird setting of _current is to avoid drift with many almost-aligned segments
+ // The additional conditions ensure that the smaller dimension is rounded to zero
+ bool written = false;
+ if (_use_shorthands) {
+ Point r = _current - p;
+ if (are_near(p[X], _current[X], _epsilon) && std::abs(r[X]) < std::abs(r[Y])) {
+ // emit vlineto
+ _setCommand('V');
+ _current_pars.push_back(p[Y]);
+ _current[Y] = p[Y];
+ written = true;
+ } else if (are_near(p[Y], _current[Y], _epsilon) && std::abs(r[Y]) < std::abs(r[X])) {
+ // emit hlineto
+ _setCommand('H');
+ _current_pars.push_back(p[X]);
+ _current[X] = p[X];
+ written = true;
+ }
+ }
+
+ if (!written) {
+ // emit normal lineto
+ if (_command != 'M' && _command != 'L') {
+ _setCommand('L');
+ }
+ _current_pars.push_back(p[X]);
+ _current_pars.push_back(p[Y]);
+ _current = p;
+ }
+
+ _cubic_tangent = _quad_tangent = _current;
+ if (!_optimize) {
+ flush();
+ }
+}
+
+void SVGPathWriter::quadTo(Point const &c, Point const &p)
+{
+ bool shorthand = _use_shorthands && are_near(c, _quad_tangent, _epsilon);
+
+ _setCommand(shorthand ? 'T' : 'Q');
+ if (!shorthand) {
+ _current_pars.push_back(c[X]);
+ _current_pars.push_back(c[Y]);
+ }
+ _current_pars.push_back(p[X]);
+ _current_pars.push_back(p[Y]);
+
+ _current = _cubic_tangent = p;
+ _quad_tangent = p + (p - c);
+ if (!_optimize) {
+ flush();
+ }
+}
+
+void SVGPathWriter::curveTo(Point const &p1, Point const &p2, Point const &p3)
+{
+ bool shorthand = _use_shorthands && are_near(p1, _cubic_tangent, _epsilon);
+
+ _setCommand(shorthand ? 'S' : 'C');
+ if (!shorthand) {
+ _current_pars.push_back(p1[X]);
+ _current_pars.push_back(p1[Y]);
+ }
+ _current_pars.push_back(p2[X]);
+ _current_pars.push_back(p2[Y]);
+ _current_pars.push_back(p3[X]);
+ _current_pars.push_back(p3[Y]);
+
+ _current = _quad_tangent = p3;
+ _cubic_tangent = p3 + (p3 - p2);
+ if (!_optimize) {
+ flush();
+ }
+}
+
+void SVGPathWriter::arcTo(double rx, double ry, double angle,
+ bool large_arc, bool sweep, Point const &p)
+{
+ _setCommand('A');
+ _current_pars.push_back(rx);
+ _current_pars.push_back(ry);
+ _current_pars.push_back(deg_from_rad(angle));
+ _current_pars.push_back(large_arc ? 1. : 0.);
+ _current_pars.push_back(sweep ? 1. : 0.);
+ _current_pars.push_back(p[X]);
+ _current_pars.push_back(p[Y]);
+
+ _current = _quad_tangent = _cubic_tangent = p;
+ if (!_optimize) {
+ flush();
+ }
+}
+
+void SVGPathWriter::closePath()
+{
+ flush();
+ if (_optimize) {
+ _s << "z";
+ } else {
+ _s << " z";
+ }
+ _current = _quad_tangent = _cubic_tangent = _subpath_start;
+}
+
+void SVGPathWriter::flush()
+{
+ if (_command == 0 || _current_pars.empty()) return;
+
+ if (_optimize) {
+ _s << _command;
+ } else {
+ if (_s.tellp() != 0) {
+ _s << ' ';
+ }
+ _s << _command;
+ }
+
+ char lastchar = _command;
+ bool contained_dot = false;
+
+ for (double _current_par : _current_pars) {
+ // TODO: optimize the use of absolute / relative coords
+ std::string cs = _formatCoord(_current_par);
+
+ // Separator handling logic.
+ // Floating point values can end with a digit or dot
+ // and start with a digit, a plus or minus sign, or a dot.
+ // The following cases require a separator:
+ // * digit-digit
+ // * digit-dot (only if the previous number didn't contain a dot)
+ // * dot-digit
+ if (_optimize) {
+ // C++11: change to front()
+ char firstchar = cs[0];
+ if (is_digit(lastchar)) {
+ if (is_digit(firstchar)) {
+ _s << " ";
+ } else if (firstchar == '.' && !contained_dot) {
+ _s << " ";
+ }
+ } else if (lastchar == '.' && is_digit(firstchar)) {
+ _s << " ";
+ }
+ _s << cs;
+
+ // C++11: change to back()
+ lastchar = cs[cs.length()-1];
+ contained_dot = cs.find('.') != std::string::npos;
+ } else {
+ _s << " " << cs;
+ }
+ }
+ _current_pars.clear();
+ _command = 0;
+}
+
+void SVGPathWriter::clear()
+{
+ _s.clear();
+ _s.str("");
+ _ns.clear();
+ _ns.str("");
+ _command = 0;
+ _current_pars.clear();
+ _current = Point(0,0);
+ _subpath_start = Point(0,0);
+}
+
+void SVGPathWriter::setPrecision(int prec)
+{
+ _precision = prec;
+ if (prec < 0) {
+ _epsilon = 0;
+ } else {
+ _epsilon = std::pow(10., -prec);
+ _ns << std::setprecision(_precision);
+ }
+}
+
+void SVGPathWriter::_setCommand(char cmd)
+{
+ if (_command != 0 && _command != cmd) {
+ flush();
+ }
+ _command = cmd;
+}
+
+std::string SVGPathWriter::_formatCoord(Coord par)
+{
+ std::string ret;
+ if (_precision < 0) {
+ ret = format_coord_shortest(par);
+ } else {
+ _ns << par;
+ ret = _ns.str();
+ _ns.clear();
+ _ns.str("");
+ }
+ return ret;
+}
+
+
+std::string write_svg_path(PathVector const &pv, int prec, bool optimize, bool shorthands)
+{
+ SVGPathWriter writer;
+ writer.setPrecision(prec);
+ writer.setOptimize(optimize);
+ writer.setUseShorthands(shorthands);
+
+ writer.feed(pv);
+ return writer.str();
+}
+
+} // namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/sweep-bounds.cpp b/src/3rdparty/2geom/src/2geom/sweep-bounds.cpp
new file mode 100644
index 0000000..2f31b67
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/sweep-bounds.cpp
@@ -0,0 +1,154 @@
+#include <2geom/sweep-bounds.h>
+
+#include <algorithm>
+
+namespace Geom {
+
+struct Event {
+ double x;
+ unsigned ix;
+ bool closing;
+ Event(double pos, unsigned i, bool c) : x(pos), ix(i), closing(c) {}
+// Lexicographic ordering by x then closing
+ bool operator<(Event const &other) const {
+ if(x < other.x) return true;
+ if(x > other.x) return false;
+ return closing < other.closing;
+ }
+ bool operator==(Event const &other) const {
+ return other.x == x && other.ix == ix && other.closing == closing;
+ }
+};
+
+std::vector<std::vector<unsigned> > fake_cull(unsigned a, unsigned b);
+
+/**
+ * \brief Make a list of pairs of self intersections in a list of Rects.
+ *
+ * \param rs: vector of Rect.
+ * \param d: dimension to sweep along
+ *
+ * [(A = rs[i], B = rs[j]) for i,J in enumerate(pairs) for j in J]
+ * then A.left <= B.left
+ */
+
+std::vector<std::vector<unsigned> > sweep_bounds(std::vector<Rect> rs, Dim2 d) {
+ std::vector<Event> events; events.reserve(rs.size()*2);
+ std::vector<std::vector<unsigned> > pairs(rs.size());
+
+ for(unsigned i = 0; i < rs.size(); i++) {
+ events.emplace_back(rs[i][d].min(), i, false);
+ events.emplace_back(rs[i][d].max(), i, true);
+ }
+ std::sort(events.begin(), events.end());
+
+ std::vector<unsigned> open;
+ for(auto & event : events) {
+ unsigned ix = event.ix;
+ if(event.closing) {
+ std::vector<unsigned>::iterator iter = std::find(open.begin(), open.end(), ix);
+ //if(iter != open.end())
+ open.erase(iter);
+ } else {
+ for(unsigned int jx : open) {
+ if(rs[jx][1-d].intersects(rs[ix][1-d])) {
+ pairs[jx].push_back(ix);
+ }
+ }
+ open.push_back(ix);
+ }
+ }
+ return pairs;
+}
+
+/**
+ * \brief Make a list of pairs of red-blue intersections between two lists of Rects.
+ *
+ * \param a: vector of Rect.
+ * \param b: vector of Rect.
+ * \param d: dimension to scan along
+ *
+ * [(A = rs[i], B = rs[j]) for i,J in enumerate(pairs) for j in J]
+ * then A.left <= B.left, A in a, B in b
+ */
+std::vector<std::vector<unsigned> > sweep_bounds(std::vector<Rect> a, std::vector<Rect> b, Dim2 d) {
+ std::vector<std::vector<unsigned> > pairs(a.size());
+ if(a.empty() || b.empty()) return pairs;
+ std::vector<Event> events[2];
+ events[0].reserve(a.size()*2);
+ events[1].reserve(b.size()*2);
+
+ for(unsigned n = 0; n < 2; n++) {
+ unsigned sz = n ? b.size() : a.size();
+ events[n].reserve(sz*2);
+ for(unsigned i = 0; i < sz; i++) {
+ Rect r = n ? b[i] : a[i];
+ events[n].emplace_back(r[d].min(), i, false);
+ events[n].emplace_back(r[d].max(), i, true);
+ }
+ std::sort(events[n].begin(), events[n].end());
+ }
+
+ std::vector<unsigned> open[2];
+ bool n = events[1].front() < events[0].front();
+ {// As elegant as putting the initialiser in the for was, it upsets some legacy compilers (MS VS C++)
+ unsigned i[] = {0,0};
+ for(; i[n] < events[n].size();) {
+ unsigned ix = events[n][i[n]].ix;
+ bool closing = events[n][i[n]].closing;
+ //std::cout << n << "[" << ix << "] - " << (closing ? "closer" : "opener") << "\n";
+ if(closing) {
+ open[n].erase(std::find(open[n].begin(), open[n].end(), ix));
+ } else {
+ if(n) {
+ //n = 1
+ //opening a B, add to all open a
+ for(unsigned int jx : open[0]) {
+ if(a[jx][1-d].intersects(b[ix][1-d])) {
+ pairs[jx].push_back(ix);
+ }
+ }
+ } else {
+ //n = 0
+ //opening an A, add all open b
+ for(unsigned int jx : open[1]) {
+ if(b[jx][1-d].intersects(a[ix][1-d])) {
+ pairs[ix].push_back(jx);
+ }
+ }
+ }
+ open[n].push_back(ix);
+ }
+ i[n]++;
+ if(i[n]>=events[n].size()) {break;}
+ n = (events[!n][i[!n]] < events[n][i[n]]) ? !n : n;
+ }}
+ return pairs;
+}
+
+//Fake cull, until the switch to the real sweep is made.
+std::vector<std::vector<unsigned> > fake_cull(unsigned a, unsigned b) {
+ std::vector<std::vector<unsigned> > ret;
+
+ std::vector<unsigned> all;
+ for(unsigned j = 0; j < b; j++)
+ all.push_back(j);
+
+ for(unsigned i = 0; i < a; i++)
+ ret.push_back(all);
+
+ return ret;
+}
+
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/transforms.cpp b/src/3rdparty/2geom/src/2geom/transforms.cpp
new file mode 100644
index 0000000..41d3952
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/transforms.cpp
@@ -0,0 +1,205 @@
+/**
+ * @file
+ * @brief Affine transformation classes
+ *//*
+ * Authors:
+ * ? <?@?.?>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ * Johan Engelen
+ *
+ * Copyright ?-2012 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <boost/concept_check.hpp>
+#include <2geom/point.h>
+#include <2geom/transforms.h>
+#include <2geom/rect.h>
+
+namespace Geom {
+
+/** @brief Zoom between rectangles.
+ * Given two rectangles, compute a zoom that maps one to the other.
+ * Rectangles are assumed to have the same aspect ratio. */
+Zoom Zoom::map_rect(Rect const &old_r, Rect const &new_r)
+{
+ Zoom ret;
+ ret._scale = new_r.width() / old_r.width();
+ ret._trans = new_r.min() - old_r.min();
+ return ret;
+}
+
+// Point transformation methods.
+Point &Point::operator*=(Translate const &t)
+{
+ _pt[X] += t.vec[X];
+ _pt[Y] += t.vec[Y];
+ return *this;
+}
+Point &Point::operator*=(Scale const &s)
+{
+ _pt[X] *= s.vec[X];
+ _pt[Y] *= s.vec[Y];
+ return *this;
+}
+Point &Point::operator*=(Rotate const &r)
+{
+ double x = _pt[X], y = _pt[Y];
+ _pt[X] = x * r.vec[X] - y * r.vec[Y];
+ _pt[Y] = y * r.vec[X] + x * r.vec[Y];
+ return *this;
+}
+Point &Point::operator*=(HShear const &h)
+{
+ _pt[X] += h.f * _pt[X];
+ return *this;
+}
+Point &Point::operator*=(VShear const &v)
+{
+ _pt[Y] += v.f * _pt[Y];
+ return *this;
+}
+Point &Point::operator*=(Zoom const &z)
+{
+ _pt[X] += z._trans[X];
+ _pt[Y] += z._trans[Y];
+ _pt[X] *= z._scale;
+ _pt[Y] *= z._scale;
+ return *this;
+}
+
+// Affine multiplication methods.
+
+/** @brief Combine this transformation with a translation. */
+Affine &Affine::operator*=(Translate const &t) {
+ _c[4] += t[X];
+ _c[5] += t[Y];
+ return *this;
+}
+
+/** @brief Combine this transformation with scaling. */
+Affine &Affine::operator*=(Scale const &s) {
+ _c[0] *= s[X]; _c[1] *= s[Y];
+ _c[2] *= s[X]; _c[3] *= s[Y];
+ _c[4] *= s[X]; _c[5] *= s[Y];
+ return *this;
+}
+
+/** @brief Combine this transformation a rotation. */
+Affine &Affine::operator*=(Rotate const &r) {
+ // TODO: we just convert the Rotate to an Affine and use the existing operator*=()
+ // is there a better way?
+ *this *= (Affine) r;
+ return *this;
+}
+
+/** @brief Combine this transformation with horizontal shearing (skew). */
+Affine &Affine::operator*=(HShear const &h) {
+ _c[0] += h.f * _c[1];
+ _c[2] += h.f * _c[3];
+ _c[4] += h.f * _c[5];
+ return *this;
+}
+
+/** @brief Combine this transformation with vertical shearing (skew). */
+Affine &Affine::operator*=(VShear const &v) {
+ _c[1] += v.f * _c[0];
+ _c[3] += v.f * _c[2];
+ _c[5] += v.f * _c[4];
+ return *this;
+}
+
+Affine &Affine::operator*=(Zoom const &z) {
+ _c[0] *= z._scale; _c[1] *= z._scale;
+ _c[2] *= z._scale; _c[3] *= z._scale;
+ _c[4] += z._trans[X]; _c[5] += z._trans[Y];
+ _c[4] *= z._scale; _c[5] *= z._scale;
+ return *this;
+}
+
+Affine Rotate::around(Point const &p, Coord angle)
+{
+ Affine result = Translate(-p) * Rotate(angle) * Translate(p);
+ return result;
+}
+
+Affine reflection(Point const & vector, Point const & origin)
+{
+ Geom::Point vn = unit_vector(vector);
+ Coord cx2 = vn[X] * vn[X];
+ Coord cy2 = vn[Y] * vn[Y];
+ Coord c2xy = 2 * vn[X] * vn[Y];
+ Affine mirror ( cx2 - cy2, c2xy,
+ c2xy, cy2 - cx2,
+ 0, 0 );
+ return Translate(-origin) * mirror * Translate(origin);
+}
+
+// this checks whether the requirements of TransformConcept are satisfied for all transforms.
+// if you add a new transform type, include it here!
+void check_transforms()
+{
+#ifdef BOOST_CONCEPT_ASSERT
+ BOOST_CONCEPT_ASSERT((TransformConcept<Translate>));
+ BOOST_CONCEPT_ASSERT((TransformConcept<Scale>));
+ BOOST_CONCEPT_ASSERT((TransformConcept<Rotate>));
+ BOOST_CONCEPT_ASSERT((TransformConcept<HShear>));
+ BOOST_CONCEPT_ASSERT((TransformConcept<VShear>));
+ BOOST_CONCEPT_ASSERT((TransformConcept<Zoom>));
+ BOOST_CONCEPT_ASSERT((TransformConcept<Affine>)); // Affine is also a transform
+#endif
+
+ // check inter-transform multiplication
+ Affine m;
+ Translate t(Translate::identity());
+ Scale s(Scale::identity());
+ Rotate r(Rotate::identity());
+ HShear h(HShear::identity());
+ VShear v(VShear::identity());
+ Zoom z(Zoom::identity());
+
+ // notice that the first column is always the same and enumerates all transform types,
+ // while the second one changes to each transform type in turn.
+ // cppcheck-suppress redundantAssignment
+ m = t * t; m = t * s; m = t * r; m = t * h; m = t * v; m = t * z;
+ m = s * t; m = s * s; m = s * r; m = s * h; m = s * v; m = s * z;
+ m = r * t; m = r * s; m = r * r; m = r * h; m = r * v; m = r * z;
+ m = h * t; m = h * s; m = h * r; m = h * h; m = h * v; m = h * z;
+ m = v * t; m = v * s; m = v * r; m = v * h; m = v * v; m = v * z;
+ m = z * t; m = z * s; m = z * r; m = z * h; m = z * v; m = z * z;
+}
+
+} // namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/2geom/utils.cpp b/src/3rdparty/2geom/src/2geom/utils.cpp
new file mode 100644
index 0000000..83d93cc
--- /dev/null
+++ b/src/3rdparty/2geom/src/2geom/utils.cpp
@@ -0,0 +1,86 @@
+/** Various utility functions.
+ *
+ * Copyright 2008 Marco Cecchetti <mrcekets at gmail.com>
+ * Copyright 2007 Johan Engelen <goejendaagh@zonnet.nl>
+ * Copyright 2006 Michael G. Sloan <mgsloan@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+
+#include <2geom/utils.h>
+
+
+namespace Geom
+{
+
+// return a vector that contains all the binomial coefficients of degree n
+void binomial_coefficients(std::vector<size_t>& bc, std::size_t n)
+{
+ size_t s = n+1;
+ bc.clear();
+ bc.resize(s);
+ bc[0] = 1;
+ for (size_t i = 1; i < n; ++i)
+ {
+ size_t k = i >> 1;
+ if (i & 1u)
+ {
+ bc[k+1] = bc[k] << 1;
+ }
+ for (size_t j = k; j > 0; --j)
+ {
+ bc[j] += bc[j-1];
+ }
+ }
+ s >>= 1;
+ for (size_t i = 0; i < s; ++i)
+ {
+ bc[n-i] = bc[i];
+ }
+}
+
+} // end namespace Geom
+
+
+
+
+
+
+
+
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/CMakeLists.txt b/src/3rdparty/2geom/src/CMakeLists.txt
new file mode 100644
index 0000000..268d4df
--- /dev/null
+++ b/src/3rdparty/2geom/src/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_subdirectory(2geom)
+add_subdirectory(performance-tests EXCLUDE_FROM_ALL)
+if(GTK3_FOUND)
+ add_subdirectory(toys EXCLUDE_FROM_ALL)
+else()
+ message("Not building toys as they require GTK3.")
+endif()
+
+add_subdirectory(cython EXCLUDE_FROM_ALL)
+add_subdirectory(py2geom EXCLUDE_FROM_ALL)
diff --git a/src/3rdparty/2geom/src/cython/CMakeLists.txt b/src/3rdparty/2geom/src/cython/CMakeLists.txt
new file mode 100644
index 0000000..9187d35
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/CMakeLists.txt
@@ -0,0 +1,131 @@
+#TODO - rewrite to use ALLCAPS?
+
+OPTION(2GEOM_CYTHON_BINDINGS
+ "Build a python binding with Cython."
+ OFF)
+OPTION(2GEOM_CYTHON_BUILD_SHARED
+ "Build cython shared libraries."
+ ON)
+IF(2GEOM_CYTHON_BUILD_SHARED)
+ SET(LIB_TYPE SHARED)
+ SET (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -shared")
+ELSE(2GEOM_CYTHON_BUILD_SHARED)
+ SET(LIB_TYPE STATIC)
+ENDIF(2GEOM_CYTHON_BUILD_SHARED)
+
+
+IF(2GEOM_CYTHON_BINDINGS)
+
+ include( UseCython )
+
+ # With CMake, a clean separation can be made between the source tree and the
+ # build tree. When all source is compiled, as with pure C/C++, the source is
+ # no-longer needed in the build tree. However, with pure *.py source, the
+ # source is processed directly. To handle this, we reproduce the availability
+ # of the source files in the build tree.
+ #add_custom_target( ReplicatePythonSourceTree ALL ${CMAKE_COMMAND} -P
+ # ${CMAKE_CURRENT_SOURCE_DIR}/CMakeScripts/ReplicatePythonSourceTree.cmake
+ # ${CMAKE_CURRENT_BINARY_DIR}
+ # WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
+
+ #include_directories( ${CYTHON_CMAKE_EXAMPLE_SOURCE_DIR}/include )
+
+ # Process the CMakeLists.txt in the 'src' and 'bin' directory.
+
+ set_source_files_properties(
+ _common_decl.pxd
+ _common_decl.pyx
+
+ _cy_primitives.pxd
+ _cy_primitives.pyx
+
+ _cy_rectangle.pxd
+ _cy_rectangle.pyx
+
+ _cy_affine.pxd
+ _cy_affine.pyx
+
+ _cy_curves.pxd
+ _cy_curves.pyx
+
+ _cy_path.pxd
+ _cy_path.pyx
+
+ _cy_conicsection.pxd
+ _cy_conicsection.pyx
+
+ cy2geom.pyx
+
+ PROPERTIES CYTHON_IS_CXX 1)
+
+ # Multi-file cython modules do not appear to be working at the moment.
+ cython_add_module( _common_decl _common_decl.pyx)
+
+
+ cython_add_module( _cy_primitives _cy_primitives.pyx)
+
+ cython_add_module( _cy_rectangle _cy_rectangle.pyx)
+
+ cython_add_module( _cy_affine _cy_affine.pyx)
+
+ cython_add_module( _cy_curves _cy_curves.pyx)
+
+ cython_add_module( _cy_path _cy_path.pyx)
+
+ #not finished for now
+ #~ cython_add_module( _cy_shape _cy_shape.pyx)
+
+ cython_add_module( _cy_conicsection _cy_conicsection.pyx)
+
+ target_link_libraries(_cy_primitives
+ #TODO! linking to static lib2geom.a gives -fPIC error, to compile
+ #you have to enable building dynamic library in cmake . -i
+ gsl gslcblas 2geom
+ )
+ target_link_libraries(_cy_rectangle
+ gsl gslcblas 2geom
+ )
+
+ target_link_libraries(_cy_affine
+ gsl gslcblas 2geom
+ )
+
+ target_link_libraries(_cy_curves
+ gsl gslcblas 2geom
+ )
+
+ target_link_libraries(_cy_path
+ gsl gslcblas 2geom
+ )
+
+ #~ target_link_libraries(_cy_shape
+ #~ gsl gslcblas 2geom
+ #~ )
+
+ target_link_libraries(_cy_conicsection
+ gsl gslcblas 2geom
+ )
+
+ cython_add_module( cy2geom cy2geom.pyx)
+
+ add_test(cython-primitives python2 test-primitives.py)
+ add_test(cython-rectangle python2 test-rectangle.py)
+ add_test(cython-affine python2 test-affine.py)
+ add_test(cython-curves python2 test-curves.py)
+ add_test(cython-path python2 test-path.py)
+ add_test(cython-conicsection python2 test-conicsection.py)
+
+ # stuff to install the cy2geom package in the Python site-packages directory
+ FIND_PACKAGE(PythonLibs)
+ IF (WIN32)
+ GET_FILENAME_COMPONENT(PYTHON_LIB_INSTALL "${PYTHON_LIBRARY}" PATH)
+ GET_FILENAME_COMPONENT(SITEPACKAGE "${PYTHON_LIB_INSTALL}/../Lib/site-packages" ABSOLUTE)
+ ELSE (WIN32)
+ SET(PYTHON_LIB_INSTALL "/usr/local/lib/python2.7/dist-packages" CACHE STRING "Where to install the cy2geom module?")
+ SET(SITEPACKAGE ${PYTHON_LIB_INSTALL})
+ ENDIF(WIN32)
+
+ INSTALL(TARGETS _common_decl _cy_primitives _cy_rectangle _cy_affine _cy_curves _cy_path _cy_conicsection cy2geom
+ DESTINATION "${SITEPACKAGE}/cy2geom")
+
+ENDIF(2GEOM_CYTHON_BINDINGS)
diff --git a/src/3rdparty/2geom/src/cython/README.md b/src/3rdparty/2geom/src/cython/README.md
new file mode 100644
index 0000000..a4a0847
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/README.md
@@ -0,0 +1,29 @@
+# Installing:
+
+In addition to 2geom dependencies, cython bindings need `cython >= 0.16`.
+
+You can turn them on using cmake. Please note that you need to enable
+shared library option as well.
+
+Building on Windows is not tested yet, should be done shortly. Extrapolating
+from other projects using cython, this should not be major problem.
+
+# Usage:
+
+Bindings are almost 1-1 to 2geom, so using them is pretty straightforward.
+Classes and methods are documented shortly. It's generally good idea to
+look at 2geom docs and, if problems persist, at their source.
+
+To look at simple use cases, I suggest looking at tests and utils.py, located
+in cython-bindings directory.
+
+# Hacking:
+
+cython is pretty straightforward to pick up, but its docs usually cover only
+the simplest example. Looking at source of other project can be helpful
+(cython bindings for SFML 2 are good example).
+
+Don't hesitate to contact me or 2geom mailinglist with any requests concerning
+design of bindings and bug reports.
+
+Jan Pulmann - jan.pulmann@gmail.com
diff --git a/src/3rdparty/2geom/src/cython/_common_decl.pxd b/src/3rdparty/2geom/src/cython/_common_decl.pxd
new file mode 100644
index 0000000..8877048
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/_common_decl.pxd
@@ -0,0 +1,14 @@
+from libcpp.vector cimport vector
+from libcpp.pair cimport pair
+
+ctypedef double Coord
+ctypedef int IntCoord
+
+cdef extern from "2geom/coord.h" namespace "Geom":
+ cdef Coord EPSILON
+ cdef enum Dim2:
+ X = 0
+ Y = 1
+
+cdef object wrap_vector_double(vector[double] v)
+cdef vector[double] make_vector_double(object l)
diff --git a/src/3rdparty/2geom/src/cython/_common_decl.pyx b/src/3rdparty/2geom/src/cython/_common_decl.pyx
new file mode 100644
index 0000000..1f1544e
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/_common_decl.pyx
@@ -0,0 +1,12 @@
+cdef object wrap_vector_double(vector[double] v):
+ r = []
+ cdef unsigned int i
+ for i in range(v.size()):
+ r.append(v[i])
+ return r
+
+cdef vector[double] make_vector_double(object l):
+ cdef vector[double] ret
+ for i in l:
+ ret.push_back( float(i) )
+ return ret
diff --git a/src/3rdparty/2geom/src/cython/_cy_affine.pxd b/src/3rdparty/2geom/src/cython/_cy_affine.pxd
new file mode 100644
index 0000000..91eb662
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/_cy_affine.pxd
@@ -0,0 +1,247 @@
+from _common_decl cimport *
+
+from _cy_rectangle cimport Rect, cy_Rect, wrap_Rect
+from _cy_primitives cimport Point, cy_Point, wrap_Point
+
+
+cdef extern from "2geom/affine.h" namespace "Geom":
+ cdef cppclass Affine:
+
+ Affine(Affine &)
+ Affine()
+ Affine(Coord, Coord, Coord, Coord, Coord, Coord)
+
+ Coord operator[](unsigned int)
+
+ Affine & operator*(Affine &)
+ Affine & operator*(Translate &)
+ Affine & operator*(Scale &)
+ Affine & operator*(Rotate &)
+ Affine & operator*(HShear &)
+ Affine & operator*(VShear &)
+ Affine & operator*(Zoom &)
+
+ bint operator==(Affine &)
+ bint operator!=(Affine &)
+
+ Point xAxis()
+ Point yAxis()
+ Point translation()
+ Coord expansionX()
+ Coord expansionY()
+ Point expansion()
+
+ void setXAxis(Point &)
+ void setYAxis(Point &)
+ void setTranslation(Point &)
+ void setExpansionX(Coord)
+ void setExpansionY(Coord)
+ void setIdentity()
+
+ bint isIdentity(Coord)
+ bint isTranslation(Coord)
+ bint isScale(Coord)
+ bint isUniformScale(Coord)
+ bint isRotation(Coord)
+ bint isHShear(Coord)
+ bint isVShear(Coord)
+ bint isNonzeroTranslation(Coord)
+ bint isNonzeroScale(Coord)
+ bint isNonzeroUniformScale(Coord)
+ bint isNonzeroRotation(Coord)
+ bint isNonzeroHShear(Coord)
+ bint isNonzeroVShear(Coord)
+ bint isZoom(Coord)
+ bint preservesArea(Coord)
+ bint preservesAngles(Coord)
+ bint preservesDistances(Coord)
+ bint flips()
+ bint isSingular(Coord)
+
+ Affine withoutTranslation()
+ Affine inverse()
+
+ Coord det()
+ Coord descrim2()
+ Coord descrim()
+
+ bint are_near(Affine &, Affine &, Coord)
+ Affine a_identity "Geom::Affine::identity" ()
+
+cdef extern from "2geom/transforms.h" namespace "Geom":
+ Affine reflection(Point &, Point &)
+ #TODO find out how cython __pow__ works
+ Affine pow(Affine &, int)
+ Translate pow(Translate &, int)
+ Scale pow(Scale &, int)
+ Rotate pow(Rotate &, int)
+ HShear pow(HShear &, int)
+ VShear pow(VShear &, int)
+ Zoom pow(Zoom &, int)
+
+cdef class cy_Affine:
+ cdef Affine* thisptr
+
+cdef cy_Affine wrap_Affine(Affine)
+
+#helper functions
+cdef Affine get_Affine(t)
+cdef bint is_transform(t)
+
+
+cdef extern from "2geom/transforms.h" namespace "Geom":
+ cdef cppclass Translate:
+ Translate(Translate &)
+ Translate()
+ Translate(Point &)
+ Translate(Coord, Coord)
+ Coord operator[](Dim2)
+ Coord operator[](unsigned int)
+ Translate & operator*(Translate &)
+ Affine & operator*(Affine &)
+ bint operator==(Translate &)
+ bint operator!=(Translate &)
+
+ Affine operator()
+
+ Point vector()
+ Translate inverse()
+
+ Translate t_identity "Geom::Translate::identity" ()
+
+cdef class cy_Translate:
+ cdef Translate* thisptr
+
+
+cdef extern from "2geom/transforms.h" namespace "Geom":
+ cdef cppclass Scale:
+ Scale(Scale &)
+ Scale()
+ Scale(Point &)
+ Scale(Coord, Coord)
+ Scale(Coord)
+ Coord operator[](Dim2)
+ Scale & operator*(Scale &)
+ Affine & operator*(Affine &)
+ bint operator==(Scale &)
+ bint operator!=(Scale &)
+
+ Affine operator()
+
+ Point vector()
+ Scale inverse()
+ Scale identity()
+
+ Scale s_identity "Geom::Scale::identity" ()
+
+cdef class cy_Scale:
+ cdef Scale* thisptr
+
+
+cdef extern from "2geom/transforms.h" namespace "Geom":
+ cdef cppclass Rotate:
+ Rotate(Rotate &)
+ Rotate()
+ Rotate(Coord)
+ Rotate(Point &)
+ Rotate(Coord, Coord)
+ Point vector()
+
+ Coord operator[](Dim2)
+ Coord operator[](unsigned int)
+ Rotate & operator*(Rotate &)
+ Affine & operator*(Affine &)
+ bint operator==(Rotate &)
+ bint operator!=(Rotate &)
+
+ Affine operator()
+ Rotate inverse()
+
+ Rotate r_identity "Geom::Rotate::identity" ()
+
+cdef extern from "2geom/transforms.h" namespace "Geom::Rotate":
+ Rotate from_degrees(Coord)
+
+
+cdef class cy_Rotate:
+ cdef Rotate* thisptr
+
+cdef extern from "2geom/transforms.h" namespace "Geom":
+ cdef cppclass VShear:
+ VShear(VShear &)
+ VShear(Coord)
+ Coord factor()
+ void setFactor(Coord)
+
+ VShear &operator*(VShear)
+ Affine & operator*(Affine &)
+ bint operator==(VShear &)
+ bint operator!=(VShear &)
+ Affine operator()
+
+ VShear inverse()
+
+ VShear vs_identity "Geom::VShear::identity"()
+
+cdef class cy_VShear:
+ cdef VShear* thisptr
+
+
+cdef extern from "2geom/transforms.h" namespace "Geom":
+ cdef cppclass HShear:
+ HShear(HShear &)
+ HShear(Coord)
+ Coord factor()
+ void setFactor(Coord)
+ HShear &operator*(HShear)
+ Affine & operator*(Affine &)
+ bint operator==(HShear &)
+ bint operator!=(HShear &)
+ Affine operator()
+
+ HShear inverse()
+
+ HShear hs_identity "Geom::HShear::identity"()
+
+cdef class cy_HShear:
+ cdef HShear* thisptr
+
+
+cdef extern from "2geom/transforms.h" namespace "Geom":
+ cdef cppclass Zoom:
+ Zoom(Zoom &)
+ Zoom(Coord)
+ Zoom(Translate &)
+ Zoom(Coord, Translate &)
+
+ Zoom & operator*(Zoom &)
+ Affine & operator*(Affine &)
+ bint operator==(Zoom &)
+ bint operator!=(Zoom &)
+
+ Affine operator()
+
+ Coord scale()
+ void setScale(Coord)
+ Point translation()
+ void setTranslation(Point &)
+
+ Zoom inverse()
+
+ Zoom()
+
+ Zoom z_identity "Geom::Zoom::identity" ()
+
+cdef extern from "2geom/transforms.h" namespace "Geom::Zoom":
+ Zoom map_rect(Rect &, Rect &)
+
+cdef class cy_Zoom:
+ cdef Zoom* thisptr
+
+
+cdef extern from "2geom/affine.h" namespace "Geom":
+ cdef cppclass Eigen:
+ Point *vectors
+ double *values
+ Eigen(Affine &)
+ Eigen(double[2][2])
diff --git a/src/3rdparty/2geom/src/cython/_cy_affine.pyx b/src/3rdparty/2geom/src/cython/_cy_affine.pyx
new file mode 100644
index 0000000..19aa9ef
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/_cy_affine.pyx
@@ -0,0 +1,736 @@
+from cython.operator cimport dereference as deref
+
+from numbers import Number
+
+
+cdef class cy_Affine:
+
+ """Class representing affine transform in 2D plane.
+
+ Corresponds to Affine class in 2geom.
+ """
+
+ def __cinit__(self, c0=None,
+ Coord c1=0,
+ Coord c2=0,
+ Coord c3=1,
+ Coord c4=0,
+ Coord c5=0):
+ """Create Affine instance from either transform or from coefficients."""
+ if c0 is None:
+ self.thisptr = new Affine()
+ elif is_transform(c0):
+ self.thisptr = new Affine( get_Affine(c0) )
+ else:
+ self.thisptr = new Affine(<Coord> float(c0) ,c1 ,c2 ,c3 ,c4 ,c5)
+
+ def __str__(self):
+ """str(self)"""
+ return "Affine({}, {}, {}, {}, {}, {})".format( self[0],
+ self[1],
+ self[2],
+ self[3],
+ self[4],
+ self[5],
+ )
+ def __repr__(self):
+ """repr(self)"""
+ return str(self)
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ def __getitem__(self, int i):
+ """Get coefficients."""
+ if i >= 6:
+ raise IndexError("Affine has only 6 coefficients.")
+ return deref(self.thisptr) [i]
+
+ def __mul__(cy_Affine self, other):
+ """Compose with another transformation."""
+ if isinstance(other, cy_Affine):
+ return wrap_Affine( deref(self.thisptr) * deref( (<cy_Affine> other).thisptr ) )
+ elif isinstance(other, cy_Translate):
+ return wrap_Affine( deref(self.thisptr) * deref( (<cy_Translate> other).thisptr ) )
+ elif isinstance(other, cy_Scale):
+ return wrap_Affine( deref(self.thisptr) * deref( (<cy_Scale> other).thisptr ) )
+ elif isinstance(other, cy_Rotate):
+ return wrap_Affine( deref(self.thisptr) * deref( (<cy_Rotate> other).thisptr ) )
+ elif isinstance(other, cy_HShear):
+ return wrap_Affine( deref(self.thisptr) * deref( (<cy_HShear> other).thisptr ) )
+ elif isinstance(other, cy_VShear):
+ return wrap_Affine( deref(self.thisptr) * deref( (<cy_VShear> other).thisptr ) )
+ elif isinstance(other, cy_Zoom):
+ return wrap_Affine( deref(self.thisptr) * deref( (<cy_Zoom> other).thisptr ) )
+
+ def __pow__(cy_Affine self, int n, z):
+ """Compose with self n times."""
+ return wrap_Affine(pow( deref(self.thisptr), n ))
+
+ def __richcmp__(cy_Affine self, cy_Affine other, int op):
+ if op == 2:
+ return deref(self.thisptr) == deref(other.thisptr)
+ elif op == 3:
+ return deref(self.thisptr) != deref(other.thisptr)
+
+ def x_axis(self):
+ """Transformation of unit x vector without translation."""
+ return wrap_Point(self.thisptr.xAxis())
+
+ def y_axis(self):
+ """Transformation of unit y vector without translation."""
+ return wrap_Point(self.thisptr.yAxis())
+
+ def translation(self):
+ """Translation of transformation."""
+ return wrap_Point(self.thisptr.translation())
+
+ def expansion_X(self):
+ """Expansion of unit x vector."""
+ return self.thisptr.expansionX()
+
+ def expansion_Y(self):
+ """Expansion of unit y vector."""
+ return self.thisptr.expansionY()
+
+ def expansion(self):
+ """Point( self.expansion_X(), self.expansion_Y() )"""
+ return wrap_Point(self.thisptr.expansion())
+
+ def set_X_axis(self, cy_Point vec):
+ """Set transformation of x unit vector without translation."""
+ self.thisptr.setXAxis(deref( vec.thisptr ))
+
+ def set_Y_axis(self, cy_Point vec):
+ """Set transformation of y unit vector without translation."""
+ self.thisptr.setYAxis(deref( vec.thisptr ))
+
+ def set_translation(self, cy_Point loc):
+ """Set translation of origin."""
+ self.thisptr.setTranslation(deref( loc.thisptr ))
+
+ def set_expansion_X(self, Coord val):
+ """Set expansion of x unit vector."""
+ self.thisptr.setExpansionX(val)
+
+ def set_expansion_Y(self, Coord val):
+ """Set expansion of y unit vector."""
+ self.thisptr.setExpansionY(val)
+
+ def set_identity(self):
+ """Set self to identity transformation."""
+ self.thisptr.setIdentity()
+
+ def is_identity(self, Coord eps=EPSILON):
+ """Return true if self is close to identity transform.
+
+ Use second argument eps to specify tolerance.
+ """
+ return self.thisptr.isIdentity(eps)
+
+ def is_translation(self, Coord eps=EPSILON):
+ """Return true if self is close to transformation.
+
+ Use second argument eps to specify tolerance.
+ """
+ return self.thisptr.isTranslation(eps)
+
+ def is_scale(self, Coord eps=EPSILON):
+ """Return true if self is close to scale.
+
+ Use second argument eps to specify tolerance.
+ """
+ return self.thisptr.isScale(eps)
+
+ def is_uniform_scale(self, Coord eps=EPSILON):
+ """Return true if self is close to uniform scale.
+
+ Use second argument eps to specify tolerance.
+ """
+ return self.thisptr.isUniformScale(eps)
+
+ def is_rotation(self, Coord eps=EPSILON):
+ """Return true if self is close to rotation.
+
+ Use second argument eps to specify tolerance.
+ """
+ return self.thisptr.isRotation(eps)
+
+ def is_HShear(self, Coord eps=EPSILON):
+ """Return true if self is close to horizontal shear.
+
+ Use second argument eps to specify tolerance.
+ """
+ return self.thisptr.isHShear(eps)
+
+ def is_VShear(self, Coord eps=EPSILON):
+ """Return true if self is close to vertical shear.
+
+ Use second argument eps to specify tolerance.
+ """
+ return self.thisptr.isVShear(eps)
+
+ def is_nonzero_translation(self, Coord eps=EPSILON):
+ """Return true if self is close to translation and is identity.
+
+ Use second argument eps to specify tolerance.
+ """
+ return self.thisptr.isNonzeroTranslation(eps)
+
+ def is_nonzero_scale(self, Coord eps=EPSILON):
+ """Return true if self is close to scale and is identity.
+
+ Use second argument eps to specify tolerance.
+ """
+ return self.thisptr.isNonzeroScale(eps)
+
+ def is_nonzero_uniform_scale(self, Coord eps=EPSILON):
+ """Return true if self is close to scale and is identity.
+
+ Use second argument eps to specify tolerance.
+ """
+ return self.thisptr.isNonzeroUniformScale(eps)
+
+ def is_nonzero_rotation(self, Coord eps=EPSILON):
+ """Return true if self is close to rotation and is identity.
+
+ Use second argument eps to specify tolerance.
+ """
+ return self.thisptr.isNonzeroRotation(eps)
+
+ def is_nonzero_HShear(self, Coord eps=EPSILON):
+ """Return true if self is close to horizontal shear and is not identity.
+
+ Use second argument eps to specify tolerance.
+ """
+ return self.thisptr.isNonzeroHShear(eps)
+
+ def is_nonzero_VShear(self, Coord eps=EPSILON):
+ """Return true if self is close to vertical shear and is not identity.
+
+ Use second argument eps to specify tolerance.
+ """
+ return self.thisptr.isNonzeroVShear(eps)
+
+ def is_zoom(self, Coord eps=EPSILON):
+ """Return true if self is close to zoom.
+
+ Use second argument eps to specify tolerance.
+ """
+ return self.thisptr.isZoom(eps)
+
+ def preserves_area(self, Coord eps=EPSILON):
+ """Return true if areas are preserved after transformation
+
+ Use second argument eps to specify tolerance.
+ """
+ return self.thisptr.preservesArea(eps)
+
+ def preserves_angles(self, Coord eps=EPSILON):
+ """Return true if angles are preserved after transformation
+
+ Use second argument eps to specify tolerance.
+ """
+ return self.thisptr.preservesAngles(eps)
+
+ def preserves_distances(self, Coord eps=EPSILON):
+ """Return true if distances are preserved after transformation
+
+ Use second argument eps to specify tolerance.
+ """
+ return self.thisptr.preservesDistances(eps)
+
+ def flips(self):
+ """Return true if transformation flips - it has negative scaling."""
+ return self.thisptr.flips()
+
+ def is_singular(self, Coord eps=EPSILON):
+ """Check whether transformation matrix is singular."""
+ return self.thisptr.isSingular(eps)
+
+ def without_translation(self):
+ """Return transformation without translation part."""
+ return wrap_Affine(self.thisptr.withoutTranslation())
+
+ def inverse(self):
+ """Return inverse transformation."""
+ return wrap_Affine(self.thisptr.inverse())
+
+ def det(self):
+ """Return determinant of transformation matrix."""
+ return self.thisptr.det()
+
+ def descrim2(self):
+ """Return absolute value of self.det()"""
+ return self.thisptr.descrim2()
+
+ def descrim(self):
+ """Return square root of self.descrim2()"""
+ return self.thisptr.descrim()
+
+ @classmethod
+ def identity(self):
+ """Create identity transformation."""
+ return wrap_Affine(a_identity())
+
+ @classmethod
+ def are_near(cls, A, B, Coord eps=EPSILON):
+ """Test if two transforms are near."""
+ if is_transform(A) & is_transform(B):
+ return are_near(get_Affine(A), get_Affine(B), eps)
+
+ @classmethod
+ def reflection(cls, cy_Point vector, cy_Point origin):
+ """Create transformation reflecting along line specified by vector and origin."""
+ return wrap_Affine( reflection( deref(vector.thisptr), deref(origin.thisptr) ) )
+
+cdef cy_Affine wrap_Affine(Affine p):
+ cdef Affine * retp = new Affine()
+ retp[0] = p
+ cdef cy_Affine r = cy_Affine.__new__(cy_Affine)
+ r.thisptr = retp
+ return r
+
+cdef Affine get_Affine(t):
+ if isinstance(t, cy_Affine ):
+ return deref( (<cy_Affine> t).thisptr )
+ elif isinstance(t, cy_Translate):
+ return <Affine> deref( (<cy_Translate> t).thisptr )
+ elif isinstance(t, cy_Scale):
+ return <Affine> deref( (<cy_Scale> t).thisptr )
+ elif isinstance(t, cy_Rotate):
+ return <Affine> deref( (<cy_Rotate> t).thisptr )
+ elif isinstance(t, cy_HShear):
+ return <Affine> deref( (<cy_HShear> t).thisptr )
+ elif isinstance(t, cy_VShear):
+ return <Affine> deref( (<cy_VShear> t).thisptr )
+ elif isinstance(t, cy_Zoom):
+ return <Affine> deref( (<cy_Zoom> t).thisptr )
+
+cdef bint is_transform(t):
+ return any([isinstance(t, cy_Affine),
+ isinstance(t, cy_Translate),
+ isinstance(t, cy_Scale),
+ isinstance(t, cy_Rotate),
+ isinstance(t, cy_HShear),
+ isinstance(t, cy_VShear),
+ isinstance(t, cy_Zoom)
+ ])
+
+
+cdef class cy_Translate:
+
+ """Translation in 2D plane
+
+ Corresponds to Translate class in 2geom.
+ """
+
+ def __cinit__(self, *args):
+ """Create Translate instance form point or it's two coordinates."""
+ if len(args) == 0:
+ self.thisptr = new Translate()
+ elif len(args) == 1:
+ self.thisptr = new Translate( deref( (<cy_Point> args[0]).thisptr ) )
+ elif len(args) == 2:
+ self.thisptr = new Translate(float(args[0]), float(args[1]))
+
+ def __dealloc__(self):
+ del self.thisptr
+
+
+ def __getitem__(self, Dim2 dim):
+ """Get components of displacement vector."""
+ return deref( self.thisptr ) [dim]
+
+ def __mul__(cy_Translate self, o):
+ """Compose with another transformation."""
+ if isinstance(o, cy_Translate):
+ return wrap_Translate(deref( self.thisptr ) * deref( (<cy_Translate>o).thisptr ))
+ elif is_transform(o):
+ return wrap_Affine(deref(self.thisptr) * get_Affine(o))
+
+ def __pow__(cy_Translate self, int n, z):
+ """Compose with self n times."""
+ return wrap_Translate(pow( deref(self.thisptr), n ))
+
+ def vector(self):
+ """Get displacement vector."""
+ return wrap_Point(self.thisptr.vector())
+
+ def inverse(self):
+ """Return inverse transformation."""
+ return wrap_Translate(self.thisptr.inverse())
+
+ @classmethod
+ def identity(self):
+ """Create identity translation."""
+ return wrap_Translate(t_identity())
+
+ def __richcmp__(cy_Translate self, cy_Translate t, op):
+ if op == 2:
+ return deref(self.thisptr) == deref(t.thisptr)
+ elif op == 3:
+ return deref(self.thisptr) != deref(t.thisptr)
+
+cdef cy_Translate wrap_Translate(Translate p):
+ cdef Translate * retp = new Translate()
+ retp[0] = p
+ cdef cy_Translate r = cy_Translate.__new__(cy_Translate)
+ r.thisptr = retp
+ return r
+
+
+cdef class cy_Scale:
+
+ """Scale in 2D plane.
+
+ Corresponds to Scale in 2geom.
+ """
+
+ def __cinit__(self, *args):
+ """Create scale from number, point or it's two coordinates.
+
+ One number creates uniform scale, point or two numbers create
+ scale with different x and y scale factor.
+ """
+ if len(args) == 0:
+ self.thisptr = new Scale()
+ elif len(args) == 1:
+ if isinstance(args[0], Number):
+ self.thisptr = new Scale(<Coord> float(args[0]))
+ elif isinstance(args[0], cy_Point):
+ self.thisptr = new Scale( deref( (<cy_Point> args[0]).thisptr ) )
+ elif len(args) == 2:
+ self.thisptr = new Scale(float(args[0]), float(args[1]))
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ def __getitem__(self, Dim2 d):
+ """Get scale factors for each axis."""
+ return deref( self.thisptr ) [d]
+
+ def __mul__(cy_Scale self, o):
+ """Compose with another transformation."""
+ if isinstance(o, cy_Scale):
+ return wrap_Scale(deref( self.thisptr ) * deref( (<cy_Scale>o).thisptr ))
+ elif is_transform(o):
+ return wrap_Affine(deref(self.thisptr) * get_Affine(o))
+
+ def __pow__(cy_Scale self, int n, z):
+ """Compose with self n times."""
+ return wrap_Scale(pow( deref(self.thisptr), n ))
+
+ def vector(self):
+ """Get both scale factors as a point."""
+ return wrap_Point(self.thisptr.vector())
+
+ def inverse(self):
+ """Return inverse transformation."""
+ return wrap_Scale(self.thisptr.inverse())
+
+ @classmethod
+ def identity(self):
+ """Create identity scale."""
+ return wrap_Scale(s_identity())
+
+ def __richcmp__(cy_Scale self, cy_Scale s, op):
+ if op == 2:
+ return deref(self.thisptr) == deref(s.thisptr)
+ elif op == 3:
+ return deref(self.thisptr) != deref(s.thisptr)
+
+cdef cy_Scale wrap_Scale(Scale p):
+ cdef Scale * retp = new Scale()
+ retp[0] = p
+ cdef cy_Scale r = cy_Scale.__new__(cy_Scale)
+ r.thisptr = retp
+ return r
+
+
+cdef class cy_Rotate:
+
+ """Rotation in 2D plane.
+
+ Corresponds to Rotate in 2geom.
+ """
+
+ def __cinit__(self, *args):
+ """Create new Rotate instance, specifying angle.
+
+ Use one number to set the angle, or point/its two coordinates,
+ using point's angle with x-axis as a rotation angle.
+ """
+ if len(args) == 0:
+ self.thisptr = new Rotate()
+ elif len(args) == 1:
+ if isinstance(args[0], Number):
+ self.thisptr = new Rotate(<Coord> float(args[0]))
+ elif isinstance(args[0], cy_Point):
+ self.thisptr = new Rotate( deref( (<cy_Point> args[0]).thisptr ) )
+ elif len(args) == 2:
+ self.thisptr = new Rotate(float(args[0]), float(args[1]))
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ def vector(self):
+ """Return Point(1, 0)*self."""
+ return wrap_Point(self.thisptr.vector())
+
+ def __getitem__(self, Dim2 dim):
+ """Get components of self.vector()"""
+ return deref( self.thisptr ) [dim]
+
+ def __mul__(cy_Rotate self, o):
+ """Compose with another transformation."""
+ if isinstance(o, cy_Rotate):
+ return wrap_Rotate(deref( self.thisptr ) * deref( (<cy_Rotate>o).thisptr ))
+ elif is_transform(o):
+ return wrap_Affine(deref(self.thisptr) * get_Affine(o))
+
+ def __pow__(cy_Rotate self, int n, z):
+ """Compose with self n times."""
+ return wrap_Rotate(pow( deref(self.thisptr), n ))
+
+ def inverse(self):
+ """Return inverse transformation."""
+ return wrap_Rotate(self.thisptr.inverse())
+
+ @classmethod
+ def identity(cls):
+ """Create identity rotation."""
+ return wrap_Rotate(r_identity())
+
+ @classmethod
+ def from_degrees(cls, Coord deg):
+ """Create rotation from angle in degrees."""
+ return wrap_Rotate(from_degrees(deg))
+
+ def __richcmp__(cy_Rotate self, cy_Rotate r, op):
+ if op == 2:
+ return deref(self.thisptr) == deref(r.thisptr)
+ elif op == 3:
+ return deref(self.thisptr) != deref(r.thisptr)
+
+cdef cy_Rotate wrap_Rotate(Rotate p):
+ cdef Rotate * retp = new Rotate()
+ retp[0] = p
+ cdef cy_Rotate r = cy_Rotate.__new__(cy_Rotate)
+ r.thisptr = retp
+ return r
+
+
+cdef class cy_VShear:
+
+ """Vertical shear in 2D plane
+
+ Corresponds to VShear in 2geom.
+ """
+
+ def __cinit__(self, Coord h):
+ """Create VShear instance form shearing factor."""
+ self.thisptr = new VShear(h)
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ def factor(self):
+ """Get shearing factor."""
+ return self.thisptr.factor()
+
+ def set_factor(self, Coord nf):
+ """Set shearing factor."""
+ self.thisptr.setFactor(nf)
+
+ def __mul__(cy_VShear self, o):
+ """Compose with another transformation."""
+ if isinstance(o, cy_VShear):
+ return wrap_VShear(deref( self.thisptr ) * deref( (<cy_VShear>o).thisptr ))
+ elif is_transform(o):
+ return wrap_Affine(deref(self.thisptr) * get_Affine(o))
+
+ def __pow__(cy_VShear self, int n, z):
+ """Compose with self n times."""
+ return wrap_VShear(pow( deref(self.thisptr), n ))
+
+ def inverse(self):
+ """Return inverse transformation."""
+ return wrap_VShear(self.thisptr.inverse())
+
+ @classmethod
+ def identity(cls):
+ """Create identity VShear."""
+ return wrap_VShear( vs_identity() )
+
+ def __richcmp__(cy_VShear self, cy_VShear hs, op):
+ if op == 2:
+ return deref(self.thisptr) == deref(hs.thisptr)
+ elif op == 3:
+ return deref(self.thisptr) != deref(hs.thisptr)
+
+
+
+cdef cy_VShear wrap_VShear(VShear p):
+ cdef VShear * retp = new VShear(0)
+ retp[0] = p
+ cdef cy_VShear r = cy_VShear.__new__(cy_VShear, 0)
+ r.thisptr = retp
+ return r
+
+cdef class cy_HShear:
+
+ """Horizontal shear in 2D plane
+
+ Corresponds to HShear in 2geom.
+ """
+
+ def __cinit__(self, Coord h):
+ """Create HShear instance form shearing factor."""
+ self.thisptr = new HShear(h)
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ def factor(self):
+ """Get shearing factor."""
+ return self.thisptr.factor()
+
+ def set_factor(self, Coord nf):
+ """Set shearing factor."""
+ self.thisptr.setFactor(nf)
+
+ def __mul__(cy_HShear self, o):
+ """Compose with another transformation."""
+ if isinstance(o, cy_HShear):
+ return wrap_HShear(deref( self.thisptr ) * deref( (<cy_HShear>o).thisptr ))
+ elif is_transform(o):
+ return wrap_Affine(deref(self.thisptr) * get_Affine(o))
+
+ def __pow__(cy_HShear self, int n, z):
+ """Compose with self n times."""
+ return wrap_HShear(pow( deref(self.thisptr), n ))
+
+ def inverse(self):
+ """Return inverse transformation."""
+ return wrap_HShear(self.thisptr.inverse())
+
+ @classmethod
+ def identity(cls):
+ """Create identity HShear."""
+ return wrap_HShear( hs_identity() )
+
+ def __richcmp__(cy_HShear self, cy_HShear hs, op):
+ if op == 2:
+ return deref(self.thisptr) == deref(hs.thisptr)
+ elif op == 3:
+ return deref(self.thisptr) != deref(hs.thisptr)
+
+cdef cy_HShear wrap_HShear(HShear p):
+ cdef HShear * retp = new HShear(0)
+ retp[0] = p
+ cdef cy_HShear r = cy_HShear.__new__(cy_HShear, 0)
+ r.thisptr = retp
+ return r
+
+
+cdef class cy_Zoom:
+
+ """Zoom in 2D plane, consisting of uniform scale and translation.
+
+ Corresponds to Zoom in 2geom.
+ """
+
+ def __cinit__(self, Coord scale=1, cy_Translate translate=cy_Translate()):
+ """Create Zoom from scale factor and translation"""
+ self.thisptr = new Zoom( scale, deref( translate.thisptr ) )
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ def __mul__(cy_Zoom self, cy_Zoom z):
+ """Compose with another transformation."""
+ return wrap_Zoom( deref(self.thisptr) * deref( z.thisptr ))
+
+ def __pow__(cy_Zoom self, int n, z):
+ """Compose with self n times."""
+ return wrap_Zoom(pow( deref(self.thisptr), n ))
+
+ def __richcmp__(cy_Zoom self, cy_Zoom z, op):
+ if op == 2:
+ return deref(self.thisptr) == deref(z.thisptr)
+ elif op == 3:
+ return deref(self.thisptr) != deref(z.thisptr)
+
+ def scale(self):
+ """Get scale factor."""
+ return self.thisptr.scale()
+
+ def set_scale(self, Coord s):
+ """Set scale factor."""
+ self.thisptr.setScale(s)
+
+ def translation(self):
+ """Get translation as a point."""
+ return wrap_Point(self.thisptr.translation())
+
+ def set_translation(self, cy_Point p):
+ """Set translation."""
+ self.thisptr.setTranslation(deref( p.thisptr ))
+
+ def inverse(self):
+ """Return inverse transformation."""
+ return wrap_Zoom(self.thisptr.inverse())
+
+ @classmethod
+ def identity(cls):
+ """Create identity zoom."""
+ return wrap_Zoom(z_identity())
+
+ @classmethod
+ def map_rect(self, cy_Rect old_r, cy_Rect new_r):
+ """Create zooming used to go from old rectangle to new."""
+ return wrap_Zoom(map_rect(deref( old_r.thisptr ) ,deref( new_r.thisptr )))
+
+cdef cy_Zoom wrap_Zoom(Zoom p):
+ cdef Zoom * retp = new Zoom(0)
+ retp[0] = p
+ cdef cy_Zoom r = cy_Zoom.__new__(cy_Zoom, 0)
+ r.thisptr = retp
+ return r
+
+
+cdef class cy_Eigen:
+
+ """Class computing eigenvalues and eigenvectors of 2x2 matrix.
+
+ Corresponds to Eigen class in 2geom.
+ """
+
+ cdef Eigen* thisptr
+
+ def __cinit__(self, a):
+ """Create Eigen form 2D transform or 2x2 list - matrix."""
+ cdef Affine at
+ cdef double m[2][2]
+ if is_transform(a):
+ at = get_Affine(a)
+ self.thisptr = new Eigen(at)
+ else:
+ for i in range(2):
+ for j in range(2):
+ m[i][j] = a[i][j]
+ self.thisptr = new Eigen(m)
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ @property
+ def vectors(self):
+ """Eigenvectors of matrix."""
+ return (wrap_Point(self.thisptr.vectors[0]), wrap_Point(self.thisptr.vectors[1]))
+
+ @property
+ def values(self):
+ """Eigenvalues of matrix."""
+ return (self.thisptr.values[0], self.thisptr.values[1])
diff --git a/src/3rdparty/2geom/src/cython/_cy_conicsection.pxd b/src/3rdparty/2geom/src/cython/_cy_conicsection.pxd
new file mode 100644
index 0000000..f330cd3
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/_cy_conicsection.pxd
@@ -0,0 +1,50 @@
+from _common_decl cimport *
+
+from libcpp.vector cimport vector
+from libcpp.pair cimport pair
+
+from _cy_rectangle cimport Interval, OptInterval, Rect, OptRect
+from _cy_rectangle cimport cy_OptRect
+from _cy_affine cimport is_transform, get_Affine, Affine
+from _cy_curves cimport Curve, cy_Curve, wrap_Curve_p
+from _cy_curves cimport SBasis, cy_SBasis
+from _cy_curves cimport EllipticalArc, cy_EllipticalArc, wrap_EllipticalArc
+
+from _cy_path cimport Path, cy_Path
+
+from _cy_primitives cimport Point, cy_Point, wrap_Point, wrap_vector_point, make_vector_point
+
+
+cdef extern from "2geom/circle.h" namespace "Geom":
+ cdef cppclass Circle:
+ Circle()
+ Circle(double, double, double)
+ Circle(Point, double)
+ Circle(double, double, double, double)
+ Circle(vector[Point] &)
+ void setCenter(Point &)
+ void setRadius(double)
+ void set(double, double, double, double)
+ void fit(vector[Point] &)
+ EllipticalArc * arc(Point &, Point &, Point &, bint)
+ Point center()
+ Coord center(Dim2)
+ Coord radius()
+
+cdef extern from "2geom/ellipse.h" namespace "Geom":
+ cdef cppclass Ellipse:
+ Ellipse()
+ Ellipse(double, double, double, double, double)
+ Ellipse(double, double, double, double, double, double)
+ Ellipse(vector[Point] &)
+ Ellipse(Circle &)
+ void set(double, double, double, double, double)
+ void set(double, double, double, double, double, double)
+ void set(vector[Point] &)
+ EllipticalArc * arc(Point &, Point &, Point &, bint)
+ Point center()
+ Coord center(Dim2)
+ Coord ray(Dim2)
+ Coord rot_angle()
+ vector[double] implicit_form_coefficients()
+ Ellipse transformed(Affine &)
diff --git a/src/3rdparty/2geom/src/cython/_cy_conicsection.pyx b/src/3rdparty/2geom/src/cython/_cy_conicsection.pyx
new file mode 100644
index 0000000..91bbd73
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/_cy_conicsection.pyx
@@ -0,0 +1,183 @@
+from cython.operator cimport dereference as deref
+from numbers import Number
+from _cy_rectangle cimport cy_OptInterval, wrap_OptInterval, wrap_Rect, OptRect, wrap_OptRect
+from _cy_rectangle cimport cy_Interval, wrap_Interval
+
+from _cy_affine cimport cy_Affine, wrap_Affine, get_Affine, is_transform
+
+from _cy_curves cimport is_Curve, get_Curve_p
+from _cy_path cimport wrap_Path
+
+
+cdef class cy_Circle:
+
+ """Circle in 2D plane.
+
+ Corresponds to Circle class in 2geom.
+ """
+
+ cdef Circle* thisptr
+
+ def __cinit__(self, cy_Point center=None, double r=0):
+ """Create circle from center and radius."""
+ if center is None:
+ self.thisptr = new Circle()
+ else:
+ self.thisptr = new Circle(deref( center.thisptr ), r)
+
+ @classmethod
+ def from_coefficients(self, double A, double B, double C, double D):
+ """Create circle form implicit equation coefficients:
+
+ Implicit equation is Ax**2 + Ay**2 + Bx + Cy + D = 0
+ """
+ return wrap_Circle( Circle(A, B, C, D) )
+
+ @classmethod
+ def from_points(self, points):
+ """Create best fitting circle from at least three points."""
+ return wrap_Circle( Circle( make_vector_point(points) ) )
+
+ def set_center(self, cy_Point c):
+ """Set coordinates of center."""
+ self.thisptr.setCenter(deref(c.thisptr))
+
+ def set_radius(self, double r):
+ """Set the circle's radius."""
+ self.thisptr.setRadius(r)
+
+ def set_coefficients(self, double A, double B, double C, double D):
+ """Set implicit equation coefficients:
+
+ Implicit equation is Ax**2 + Ay**2 + Bx + Cy + D = 0
+ """
+ self.thisptr.set(A, B, C, D)
+
+ def fit(self, points):
+ """Set circle to the best fit of at least three points."""
+ self.thisptr.fit( make_vector_point(points) )
+
+ def arc(self, cy_Point initial, cy_Point inner, cy_Point final, bint _svg_compliant=True):
+ """Get (SVG)EllipticalArc.
+
+ Args:
+ initial: Initial point of arc
+ inner: Inner point of arc.
+ final: Final point of arc.
+ """
+ return wrap_EllipticalArc( deref(self.thisptr.arc(deref( initial.thisptr ), deref( inner.thisptr ), deref( final.thisptr ))) )
+
+ def center(self):
+ """Get center of circle in point."""
+ return wrap_Point(self.thisptr.center())
+
+ def radius(self):
+ """Get radius of circle."""
+ return self.thisptr.radius()
+
+cdef cy_Circle wrap_Circle(Circle p):
+ cdef Circle * retp = new Circle()
+ retp[0] = p
+ cdef cy_Circle r = cy_Circle.__new__(cy_Circle)
+ r.thisptr = retp
+ return r
+
+cdef class cy_Ellipse:
+ """Ellipse in 2D plane.
+
+ Corresponds to Ellipse class in 2geom.
+ """
+
+ cdef Ellipse* thisptr
+
+ def __cinit__(self, cy_Point center=None, rx=0, ry=0, double a=0):
+ """Create new ellipse:
+
+ Args:
+ center: Center of ellipse (between foci)
+ rx, ry: major and minor semi-axis.
+ a: angle of major axis.
+ """
+ if center is None:
+ self.thisptr = new Ellipse()
+ else:
+ self.thisptr = new Ellipse(center.x, center.y, rx, ry, a)
+
+ @classmethod
+ def from_coefficients(cls, double A, double B, double C, double D, double E, double F):
+ """Create ellipse from coefficients of implicit equation.
+
+ Implicit equation has form Ax**2 + Bxy + Cy**2 + Dx + Ey + F = 0
+ """
+ return wrap_Ellipse(Ellipse(A, B, C, D, E, F))
+
+ @classmethod
+ def from_circle(cls, cy_Circle c):
+ """Create ellipse identical to circle."""
+ return wrap_Ellipse(Ellipse(deref( c.thisptr )))
+
+ @classmethod
+ def from_points(cls, points):
+ """Create ellipse fitting at least 5 points."""
+ return wrap_Ellipse( Ellipse( make_vector_point(points) ) )
+
+ def set(self, cy_Point center, double rx, double ry, double a):
+ """Set center, rays and angle of ellipse.
+
+ Args:
+ center: Center of ellipse.
+ rx, ry: Major and minor semi-axis.
+ a: angle of major axis.
+ self.thisptr.set(center.x, center.y, rx, ry, a)
+ """
+
+ def set_coefficients(self, double A, double B, double C, double D, double E, double F):
+ """Set coefficients of implicit equation.
+
+ Implicit equation has form Ax**2 + Bxy + Cy**2 + Dx + Ey + F = 0
+ """
+ self.thisptr.set(A, B, C, D, E, F)
+
+ def set_points(self, points):
+ """Set ellipse to the best fit of at least five points."""
+ self.thisptr.set( make_vector_point(points) )
+
+ def arc(self, cy_Point initial, cy_Point inner, cy_Point final, bint svg_compliant=True):
+ """Get (SVG)EllipticalArc.
+
+ Args:
+ initial: Initial point of arc
+ inner: Inner point of arc.
+ final: Final point of arc.
+ """
+ return wrap_EllipticalArc( deref(self.thisptr.arc(deref( initial.thisptr ), deref( inner.thisptr ), deref( final.thisptr ))) )
+
+ def center(self):
+ """Get center of ellipse."""
+ return wrap_Point(self.thisptr.center())
+
+ def ray(self, Dim2 d):
+ """Get major/minor semi-axis."""
+ return self.thisptr.ray(d)
+
+ def rot_angle(self):
+ """Get angle of major axis."""
+ return self.thisptr.rot_angle()
+
+ def implicit_form_coefficients(self):
+ """Get coefficients of implicit equation in list."""
+ return wrap_vector_double(self.thisptr.implicit_form_coefficients())
+
+ def transformed(self, m):
+ """Return transformed ellipse."""
+ cdef Affine at
+ if is_transform(m):
+ at = get_Affine(m)
+ return wrap_Ellipse(self.thisptr.transformed(at))
+
+cdef cy_Ellipse wrap_Ellipse(Ellipse p):
+ cdef Ellipse * retp = new Ellipse()
+ retp[0] = p
+ cdef cy_Ellipse r = cy_Ellipse.__new__(cy_Ellipse)
+ r.thisptr = retp
+ return r
diff --git a/src/3rdparty/2geom/src/cython/_cy_curves.pxd b/src/3rdparty/2geom/src/cython/_cy_curves.pxd
new file mode 100644
index 0000000..dd13c06
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/_cy_curves.pxd
@@ -0,0 +1,421 @@
+from _common_decl cimport *
+
+from libcpp.vector cimport vector
+from libcpp.pair cimport pair
+
+from _cy_rectangle cimport Interval, OptInterval, Rect, OptRect
+from _cy_affine cimport Affine
+from _cy_primitives cimport Point, cy_Point, wrap_Point, wrap_vector_point, make_vector_point
+from _cy_primitives cimport Angle, cy_Angle, wrap_Angle
+from _cy_primitives cimport AngleInterval
+
+
+cdef extern from "2geom/d2.h" namespace "Geom":
+ cdef cppclass D2[T]:
+ D2()
+ D2(T &, T &)
+ T& operator[](unsigned i)
+
+cdef extern from "2geom/curve.h" namespace "Geom":
+ cdef cppclass Curve:
+ Curve()
+ Point initialPoint()
+ Point finalPoint()
+ bint isDegenerate()
+ Point pointAt(Coord)
+ Coord valueAt(Coord, Dim2)
+ Point operator()(Coord)
+ vector[Point] pointAndDerivatives(Coord, unsigned int)
+ void setInitial(Point &)
+ void setFinal(Point &)
+ Rect boundsFast()
+ Rect boundsExact()
+ OptRect boundsLocal(OptInterval &, unsigned int)
+ OptRect boundsLocal(OptInterval &)
+ Curve * duplicate()
+ Curve * transformed(Affine &)
+ Curve * portion(Coord, Coord)
+ Curve * portion(Interval &)
+ Curve * reverse()
+ Curve * derivative()
+ Coord nearestTime(Point &, Coord, Coord)
+ Coord nearestTime(Point &, Interval &)
+ vector[double] allNearestTimes(Point &, Coord, Coord)
+ vector[double] allNearestTimes(Point &, Interval &)
+ Coord length(Coord)
+ vector[double] roots(Coord, Dim2)
+ int winding(Point &)
+ Point unitTangentAt(Coord, unsigned int)
+ D2[SBasis] toSBasis()
+ int degreesOfFreedom()
+ bint operator==(Curve &)
+
+cdef class cy_Curve:
+ cdef Curve* thisptr
+
+#~ cdef cy_Curve wrap_Curve(Curve & p)
+cdef cy_Curve wrap_Curve_p(Curve * p)
+
+
+cdef extern from "2geom/linear.h" namespace "Geom":
+ cdef cppclass Linear:
+#~ Linear(Linear &)
+ Linear()
+ Linear(double, double)
+ Linear(double)
+ double operator[](int const)
+ bint isZero(double)
+ bint isConstant(double)
+ bint isFinite()
+ double at0()
+ double at1()
+ double valueAt(double)
+ double operator()(double)
+ SBasis toSBasis()
+ OptInterval bounds_exact()
+ OptInterval bounds_fast()
+ OptInterval bounds_local(double, double)
+ double tri()
+ double hat()
+
+ bint operator==(Linear &, Linear &)
+ bint operator!=(Linear &, Linear &)
+ Linear operator*(Linear &, double)
+ Linear operator+(Linear &, double)
+ Linear operator+(Linear &, Linear &)
+ #cython has trouble resolving these
+ Linear L_neg "operator-" (Linear &)
+ Linear L_sub_Ld "operator-"(Linear &, double)
+ Linear L_sub_LL "operator-"(Linear &, Linear &)
+ Linear operator/(Linear &, double)
+
+ double lerp(double, double, double)
+ Linear reverse(Linear &)
+
+
+cdef extern from "2geom/sbasis.h" namespace "Geom":
+ cdef cppclass SBasis:
+
+ SBasis()
+ SBasis(double)
+ SBasis(double, double)
+ SBasis(SBasis &)
+ SBasis(vector[Linear] &)
+ SBasis(Linear &)
+
+ size_t size()
+ Linear operator[](unsigned int)
+ bint empty()
+ Linear & back()
+ void pop_back()
+ void resize(unsigned int)
+ void resize(unsigned int, Linear &)
+ void reserve(unsigned int)
+ void clear()
+#~ void insert(::__gnu_cxx::__normal_iterator<Geom::Linear*, std::vector<Geom::Linear, std::allocator<Geom::Linear> > >, ::__gnu_cxx::__normal_iterator<Geom::Linear const*, std::vector<Geom::Linear, std::allocator<Geom::Linear> > >, ::__gnu_cxx::__normal_iterator<Geom::Linear const*, std::vector<Geom::Linear, std::allocator<Geom::Linear> > >)
+ Linear & at(unsigned int)
+ bint operator==(SBasis &)
+ bint operator!=(SBasis &)
+
+ bint isZero(double)
+ bint isConstant(double)
+ bint isFinite()
+ double at0()
+ double at1()
+ int degreesOfFreedom()
+ double valueAt(double)
+ double operator()(double)
+ vector[double] valueAndDerivatives(double, unsigned int)
+ SBasis toSBasis()
+ double tailError(unsigned int)
+ SBasis operator()(SBasis &)
+ void normalize()
+ void truncate(unsigned int)
+
+ SBasis operator*(SBasis &, SBasis &)
+ SBasis operator*(double, SBasis &)
+ SBasis operator*(SBasis &, double)
+ SBasis operator+(SBasis &, double)
+ SBasis operator+(SBasis &, SBasis &)
+ SBasis SB_sub_Sd "operator-" (SBasis &, double)
+ SBasis SB_sub_SS "operator-" (SBasis &, SBasis &)
+ SBasis SB_neg "operator-" (SBasis &)
+ SBasis operator/(SBasis &, double)
+
+ SBasis sin(Linear, int)
+ SBasis cos(Linear, int)
+ SBasis sqrt(SBasis &, int)
+ SBasis reciprocal(Linear &, int)
+ SBasis shift(Linear &, int)
+ SBasis shift(SBasis &, int)
+ SBasis inverse(SBasis, int)
+
+ SBasis portion(SBasis &, Interval)
+ SBasis portion(SBasis &, double, double)
+ SBasis compose(SBasis &, SBasis &, unsigned int)
+ SBasis compose(SBasis &, SBasis &)
+ SBasis truncate(SBasis &, unsigned int)
+
+ unsigned int valuation(SBasis &, double)
+
+ vector[ vector[double] ] multi_roots(SBasis &, vector[double] &, double, double, double, double) #TODO
+ vector[Interval] level_set(SBasis &, Interval &, double, double, double)
+ vector[Interval] level_set(SBasis &, double, double, double, double, double)
+ vector[double] roots(SBasis &, Interval const)
+ vector[double] roots(SBasis &)
+ vector[ vector[Interval] ] level_sets(SBasis &, vector[Interval] &, double, double, double) #TODO
+ vector[ vector[Interval] ] level_sets(SBasis &, vector[double] &, double, double, double, double) #TODO
+
+ SBasis reverse(SBasis &)
+ SBasis derivative(SBasis &)
+ SBasis integral(SBasis &)
+ SBasis divide(SBasis &, SBasis &, int)
+ SBasis compose_inverse(SBasis &, SBasis &, unsigned int, double)
+ SBasis multiply(SBasis &, SBasis &)
+ SBasis multiply_add(SBasis &, SBasis &, SBasis)
+
+ OptInterval bounds_exact(SBasis &)
+ OptInterval bounds_local(SBasis &, OptInterval &, int)
+ OptInterval bounds_fast(SBasis &, int)
+
+cdef class cy_SBasis:
+ cdef SBasis* thisptr
+
+cdef extern from "2geom/sbasis-curve.h" namespace "Geom":
+ cdef cppclass SBasisCurve:
+ SBasisCurve(D2[SBasis] &)
+ SBasisCurve(Curve &)
+ Curve * duplicate()
+ Point initialPoint()
+ Point finalPoint()
+ bint isDegenerate()
+ Point pointAt(Coord)
+ Point operator()(double)
+ vector[Point] pointAndDerivatives(Coord, unsigned int)
+ Coord valueAt(Coord, Dim2)
+ void setInitial(Point &)
+ void setFinal(Point &)
+ Rect boundsFast()
+ Rect boundsExact()
+ OptRect boundsLocal(OptInterval &, unsigned int)
+ vector[double] roots(Coord, Dim2)
+ Coord nearestTime(Point &, Coord, Coord)
+ vector[double] allNearestTimes(Point &, Coord, Coord)
+ Coord length(Coord)
+ Curve * portion(Coord, Coord)
+ Curve * transformed(Affine &)
+ Curve * derivative()
+ D2[SBasis] toSBasis()
+ int degreesOfFreedom()
+
+
+cdef extern from "2geom/bezier.h" namespace "Geom":
+ cdef cppclass Bezier:
+#~ struct Order
+#~ pass
+ unsigned int order()
+ unsigned int size()
+ Bezier()
+#~ Bezier(Bezier.Order)
+ Bezier(Coord)
+ Bezier(Coord, Coord)
+ Bezier(Coord, Coord, Coord)
+ Bezier(Coord, Coord, Coord, Coord)
+ void resize(unsigned int, Coord)
+ void clear()
+ unsigned int degree()
+ bint isZero(double)
+ bint isConstant(double)
+ bint isFinite()
+ Coord at0()
+ Coord at1()
+ Coord valueAt(double)
+ Coord operator()(double)
+ SBasis toSBasis()
+ Coord & operator[](unsigned int)
+ void setPoint(unsigned int, double)
+ vector[double] valueAndDerivatives(Coord, unsigned int)
+ pair[Bezier, Bezier] subdivide(Coord)
+ vector[double] roots()
+ vector[double] roots(Interval const)
+ Bezier forward_difference(unsigned int)
+ Bezier elevate_degree()
+ Bezier reduce_degree()
+ Bezier elevate_to_degree(unsigned int)
+ Bezier deflate()
+ Bezier(Coord *, unsigned int)
+
+ Bezier operator*(Bezier &, double)
+ Bezier operator+(Bezier &, double)
+ Bezier operator-(Bezier &, double)
+ Bezier operator/(Bezier &, double)
+
+ Bezier portion(Bezier &, double, double)
+ OptInterval bounds_local(Bezier &, OptInterval)
+ Coord casteljau_subidivision(Coord, Coord *, Coord *, Coord *, unsigned int)
+ void bezier_to_sbasis(SBasis &, Bezier &)
+ Bezier integral(Bezier &)
+ Bezier derivative(Bezier &)
+ OptInterval bounds_exact(Bezier &)
+ double bernsteinValueAt(double, double *, unsigned int)
+ vector[Point] bezier_points(D2[Bezier] &)
+ OptInterval bounds_fast(Bezier &)
+ Bezier multiply(Bezier &, Bezier &)
+ Bezier reverse(Bezier &)
+
+#This is ugly workaround around cython's lack of support for integer template parameters
+cdef extern from *:
+ ctypedef int n_0 "0"
+ ctypedef int n_1 "1"
+
+cdef extern from "2geom/bezier-curve.h" namespace "Geom":
+ cdef cppclass BezierCurve:
+ unsigned int order()
+ vector[Point] controlPoints()
+ void setPoint(unsigned int, Point)
+ void setPoints(vector[Point] &)
+ Point operator[](unsigned int)
+ Point initialPoint()
+ Point finalPoint()
+ bint isDegenerate()
+ void setInitial(Point &)
+ void setFinal(Point &)
+ Rect boundsFast()
+ Rect boundsExact()
+ OptRect boundsLocal(OptInterval &, unsigned int)
+ Curve * duplicate()
+ Curve * portion(Coord, Coord)
+ Curve * reverse()
+ Curve * transformed(Affine &)
+ Curve * derivative()
+ int degreesOfFreedom()
+ vector[double] roots(Coord, Dim2)
+ Coord length(Coord)
+ Point pointAt(Coord)
+ vector[Point] pointAndDerivatives(Coord, unsigned int)
+ Coord valueAt(Coord, Dim2)
+ D2[SBasis] toSBasis()
+ #protected:
+#~ BezierCurve()
+#~ BezierCurve(D2[Bezier] &)
+#~ BezierCurve(Bezier &, Bezier &)
+#~ BezierCurve(vector[Point] &)
+ #~ Point middle_point(LineSegment &)
+ #~ Coord length(LineSegment &)
+ Coord bezier_length(Point, Point, Point, Point, Coord)
+ Coord bezier_length(Point, Point, Point, Coord)
+ Coord bezier_length(vector[Point] &, Coord)
+
+ cdef cppclass LineSegment:
+ LineSegment()
+ LineSegment(D2[Bezier] &)
+ LineSegment(Bezier, Bezier)
+ LineSegment(vector[Point] &)
+ LineSegment(Point, Point)
+ pair[LineSegment, LineSegment] subdivide(Coord)
+
+ Curve * duplicate()
+ Curve * reverse()
+ Curve * transformed(Affine &)
+ Curve * derivative()
+
+ cdef cppclass QuadraticBezier:
+ QuadraticBezier()
+ QuadraticBezier(D2[Bezier] &)
+ QuadraticBezier(Bezier, Bezier)
+ QuadraticBezier(vector[Point] &)
+ QuadraticBezier(Point, Point, Point)
+ pair[QuadraticBezier, QuadraticBezier] subdivide(Coord)
+
+ Curve * duplicate()
+ Curve * reverse()
+ Curve * transformed(Affine &)
+ Curve * derivative()
+
+
+ cdef cppclass CubicBezier:
+ CubicBezier()
+ CubicBezier(D2[Bezier] &)
+ CubicBezier(Bezier, Bezier)
+ CubicBezier(vector[Point] &)
+ CubicBezier(Point, Point, Point, Point)
+ pair[CubicBezier, CubicBezier] subdivide(Coord)
+
+ Curve * duplicate()
+ Curve * reverse()
+ Curve * transformed(Affine &)
+ Curve * derivative()
+
+#~ cdef cppclass BezierCurveN[n_1]:
+#~ BezierCurveN ()
+#~ BezierCurveN(Bezier &, Bezier &)
+#~ #BezierCurveN(Point &, Point &)
+#~ BezierCurveN(vector[Point] &)
+#~ pair[BezierCurveN, BezierCurveN] subdivide(Coord)
+#~
+#~ Curve * duplicate()
+#~ Curve * reverse()
+#~ Curve * transformed(Affine &)
+#~ Curve * derivative()
+
+cdef class cy_BezierCurve:
+ cdef BezierCurve* thisptr
+
+cdef class cy_LineSegment(cy_BezierCurve):
+ pass
+
+cdef cy_LineSegment wrap_LineSegment(LineSegment p)
+
+cdef extern from "2geom/bezier-curve.h" namespace "Geom::BezierCurve":
+ BezierCurve * create(vector[Point] &)
+
+cdef extern from "2geom/elliptical-arc.h" namespace "Geom":
+ cdef cppclass EllipticalArc:
+ EllipticalArc(EllipticalArc &)
+ EllipticalArc()
+ EllipticalArc(Point, Coord, Coord, Coord, bint, bint, Point)
+ Interval angleInterval()
+ Angle rotationAngle()
+ Coord ray(Dim2)
+ Point rays()
+ bint largeArc()
+ bint sweep()
+ LineSegment chord()
+ void set(Point &, double, double, double, bint, bint, Point &)
+ void setExtremes(Point &, Point &)
+ Coord center(Dim2)
+ Point center()
+ Coord sweepAngle()
+ bint containsAngle(Coord)
+ Point pointAtAngle(Coord)
+ Coord valueAtAngle(Coord, Dim2)
+ Affine unitCircleTransform()
+ bint isSVGCompliant()
+ pair[EllipticalArc, EllipticalArc] subdivide(Coord)
+ Point initialPoint()
+ Point finalPoint()
+ Curve * duplicate()
+ void setInitial(Point &)
+ void setFinal(Point &)
+ bint isDegenerate()
+ Rect boundsFast()
+ Rect boundsExact()
+ OptRect boundsLocal(OptInterval &, unsigned int)
+ vector[double] roots(double, Dim2)
+ double nearestTime(Point &, double, double)
+ int degreesOfFreedom()
+ Curve * derivative()
+ Curve * transformed(Affine &)
+ vector[Point] pointAndDerivatives(Coord, unsigned int)
+ D2[SBasis] toSBasis()
+ double valueAt(Coord, Dim2)
+ Point pointAt(Coord)
+ Curve * portion(double, double)
+ Curve * reverse()
+
+cdef class cy_EllipticalArc:
+ cdef EllipticalArc* thisptr
+cdef cy_EllipticalArc wrap_EllipticalArc(EllipticalArc p)
+
+cdef Curve * get_Curve_p(object c)
+cdef bint is_Curve(object c)
diff --git a/src/3rdparty/2geom/src/cython/_cy_curves.pyx b/src/3rdparty/2geom/src/cython/_cy_curves.pyx
new file mode 100644
index 0000000..3584a87
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/_cy_curves.pyx
@@ -0,0 +1,1945 @@
+from numbers import Number
+
+from cython.operator cimport dereference as deref
+
+from _cy_rectangle cimport cy_OptInterval, wrap_OptInterval, wrap_Rect, OptRect, wrap_OptRect
+from _cy_rectangle cimport cy_Interval, wrap_Interval
+
+from _cy_affine cimport cy_Translate, cy_Rotate, cy_Scale
+from _cy_affine cimport cy_VShear, cy_HShear, cy_Zoom
+from _cy_affine cimport cy_Affine, wrap_Affine, get_Affine, is_transform
+
+
+cdef class cy_Curve:
+
+ """Class representing generic curve.
+
+ Curve maps unit interval to real plane. All curves should implement
+ these methods.
+
+ This class corresponds to Curve class in 2geom. It's children in cython
+ aren't actually derived from it, it would make code more unreadable.
+ """
+
+ def __cinit__(self):
+ """Create new Curve.
+
+ You shouldn't create Curve this way, it usually wraps existing
+ curves (f. e. in Path).
+ """
+ self.thisptr = <Curve *> new SBasisCurve(D2[SBasis]( SBasis(0), SBasis(0) ))
+
+ def __call__(self, Coord t):
+ """Get point at time value t."""
+ return wrap_Point( deref(self.thisptr)(t) )
+
+ def initial_point(self):
+ """Get self(0)."""
+ return wrap_Point(self.thisptr.initialPoint())
+
+ def final_point(self):
+ """Get self(1)."""
+ return wrap_Point(self.thisptr.finalPoint())
+ def is_degenerate(self):
+ """Curve is degenerate if it's length is zero."""
+ return self.thisptr.isDegenerate()
+
+ def point_at(self, Coord t):
+ """Equivalent to self(t)."""
+ return wrap_Point(self.thisptr.pointAt(t))
+
+ def value_at(self, Coord t, Dim2 d):
+ """Equivalent to self(t)[d]."""
+ return self.thisptr.valueAt(t, d)
+
+ def point_and_derivatives(self, Coord t, unsigned int n):
+ """Return point and at least first n derivatives at point t in list."""
+ return wrap_vector_point(self.thisptr.pointAndDerivatives(t, n))
+
+ def set_initial(self, cy_Point v):
+ """Set initial point of curve."""
+ self.thisptr.setInitial(deref( v.thisptr ))
+
+ def set_final(self, cy_Point v):
+ """Set final point of curve."""
+ self.thisptr.setFinal(deref( v.thisptr ))
+
+ def bounds_fast(self):
+ """Return bounding rectangle for curve.
+
+ This method is fast, but does not guarantee to give smallest
+ rectangle.
+ """
+ return wrap_Rect(self.thisptr.boundsFast())
+
+ def bounds_exact(self):
+ """Return exact bounding rectangle for curve.
+
+ This may take a while.
+ """
+ return wrap_Rect(self.thisptr.boundsExact())
+
+ def bounds_local(self, cy_OptInterval i, unsigned int deg=0):
+ """Return bounding rectangle to portion of curve."""
+ return wrap_OptRect(self.thisptr.boundsLocal(deref( i.thisptr ), deg))
+
+ #TODO rewrite all duplicates to copy."""
+ def duplicate(self):
+ """Duplicate the curve."""
+ return wrap_Curve_p( self.thisptr.duplicate() )
+
+ def transformed(self, m):
+ """Transform curve by affine transform."""
+ cdef Affine at
+ if is_transform(m):
+ at = get_Affine(m)
+ return wrap_Curve_p( self.thisptr.transformed(at) )
+
+ def portion(self, Coord fr=0, Coord to=1, cy_Interval interval=None):
+ """Return portion of curve, specified by endpoints or interval."""
+ if interval is None:
+ return wrap_Curve_p( self.thisptr.portion(deref( interval.thisptr )) )
+ else:
+ return wrap_Curve_p( self.thisptr.portion(fr, to) )
+
+ def reverse(self):
+ """Return curve with reversed time."""
+ return wrap_Curve_p( self.thisptr.reverse() )
+
+ def derivative(self):
+ """Return curve's derivative."""
+ return wrap_Curve_p( self.thisptr.derivative() )
+
+ def nearest_time(self, cy_Point p, Coord fr=0, Coord to=1, cy_Interval interval=None):
+ """Return such t that |self(t) - point| is minimized."""
+ if interval is None:
+ return self.thisptr.nearestTime(deref( p.thisptr ), fr, to)
+ else:
+ return self.thisptr.nearestTime(deref( p.thisptr ), deref( interval.thisptr ))
+
+ def all_nearest_times(self, cy_Point p, Coord fr=0, Coord to=1, cy_Interval interval=None):
+ """Return all values of t that |self(t) - point| is minimized."""
+ if interval is None:
+ return wrap_vector_double(self.thisptr.allNearestTimes(deref( p.thisptr ), fr, to))
+ else:
+ return wrap_vector_double(self.thisptr.allNearestTimes(deref( p.thisptr ),
+ deref( interval.thisptr )))
+
+ def length(self, Coord tolerance):
+ """Return length of curve, within give tolerance."""
+ return self.thisptr.length(tolerance)
+
+ def roots(self, Coord v, Dim2 d):
+ """Find time values where self(t)[d] == v."""
+ return wrap_vector_double(self.thisptr.roots(v, d))
+
+ def winding(self, cy_Point p):
+ """Return winding number around specified point."""
+ return self.thisptr.winding(deref( p.thisptr ))
+
+ def unit_tangent_at(self, Coord t, unsigned int n):
+ """Return tangent at self(t).
+
+ Parameter n specifies how many derivatives to take into account."""
+ return wrap_Point(self.thisptr.unitTangentAt(t, n))
+
+ def to_SBasis(self):
+ """Return tuple of SBasis functions."""
+ cdef D2[SBasis] ret = self.thisptr.toSBasis()
+ return ( wrap_SBasis(ret[0]), wrap_SBasis(ret[1]) )
+
+ def degrees_of_freedom(self):
+ """Return number of independent parameters needed to specify the curve."""
+ return self.thisptr.degreesOfFreedom()
+#~ def operator==(self, cy_Curve c):
+#~ return deref( self.thisptr ) == deref( c.thisptr )
+
+#~ cdef cy_Curve wrap_Curve(Curve & p):
+#~ cdef Curve * retp = <Curve *> new SBasisCurve(D2[SBasis]( SBasis(), SBasis() ))
+#~ retp[0] = p
+#~ cdef cy_Curve r = cy_Curve.__new__(cy_Curve)
+#~ r.thisptr = retp
+#~ return r
+
+cdef cy_Curve wrap_Curve_p(Curve * p):
+ cdef cy_Curve r = cy_Curve.__new__(cy_Curve)
+ r.thisptr = p
+ return r
+
+cdef class cy_Linear:
+ """Function mapping linearly between two values.
+
+ Corresponds to Linear class in 2geom.
+ """
+
+ cdef Linear* thisptr
+
+ def __cinit__(self, aa = None, b = None):
+ """Create new Linear from two end values.
+
+ No arguments create zero constant, one value creates constant.
+ """
+ if aa is None:
+ self.thisptr = new Linear()
+ elif b is None:
+ self.thisptr = new Linear(float(aa))
+ else:
+ self.thisptr = new Linear(float(aa), float(b))
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ def __call__(self, Coord t):
+ """Get value at time value t."""
+ return deref(self.thisptr)(t)
+
+ def __getitem__(self, i):
+ """Get end values."""
+ return deref( self.thisptr ) [i]
+
+ def __richcmp__(cy_Linear self, cy_Linear other, int op):
+ if op == 2:
+ return deref(self.thisptr) == deref(other.thisptr)
+ elif op == 3:
+ return deref(self.thisptr) != deref(other.thisptr)
+
+
+ def __neg__(cy_Linear self):
+ """Negate all values of self."""
+ return wrap_Linear( L_neg(deref(self.thisptr)) )
+
+
+ def __add__(cy_Linear self, other):
+ """Add number or other linear."""
+ if isinstance(other, Number):
+ return wrap_Linear( deref(self.thisptr) + float(other) )
+ elif isinstance(other, cy_Linear):
+ return wrap_Linear( deref(self.thisptr) + deref( (<cy_Linear> other).thisptr ) )
+
+ def __sub__(cy_Linear self, other):
+ """Substract number or other linear."""
+ if isinstance(other, Number):
+ return wrap_Linear( L_sub_Ld(deref(self.thisptr), float(other)) )
+ elif isinstance(other, cy_Linear):
+ return wrap_Linear( L_sub_LL(deref(self.thisptr), deref( (<cy_Linear> other).thisptr )) )
+
+
+ def __mul__(cy_Linear self, double b):
+ """Multiply linear by number."""
+ return wrap_Linear(deref( self.thisptr ) * b)
+
+ def __div__(cy_Linear self, double b):
+ """Divide linear by value."""
+ return wrap_Linear(deref( self.thisptr ) / b)
+
+ def is_zero(self, double eps = EPSILON):
+ """Test whether linear is zero within given tolerance."""
+ return self.thisptr.isZero(eps)
+
+ def is_constant(self, double eps = EPSILON):
+ """Test whether linear is constant within given tolerance."""
+ return self.thisptr.isConstant(eps)
+
+ def is_finite(self):
+ """Test whether linear is finite."""
+ return self.thisptr.isFinite()
+
+ def at0(self):
+ """Equivalent to self(0)."""
+ return self.thisptr.at0()
+
+ def at1(self):
+ """Equivalent to self(1)."""
+ return self.thisptr.at1()
+
+ def value_at(self, double t):
+ """Equivalent to self(t)."""
+ return self.thisptr.valueAt(t)
+
+ def to_SBasis(self):
+ """Convert to SBasis."""
+ return wrap_SBasis(self.thisptr.toSBasis())
+
+ def bounds_exact(self):
+ """Return exact bounding interval
+
+ This may take a while.
+ """
+ return wrap_OptInterval(self.thisptr.bounds_exact())
+
+ def bounds_fast(self):
+ """Return bounding interval
+
+ This method is fast, but does not guarantee to give smallest
+ interval.
+ """
+ return wrap_OptInterval(self.thisptr.bounds_fast())
+
+ def bounds_local(self, double u, double v):
+ """Return bounding interval to the portion of Linear."""
+ return wrap_OptInterval(self.thisptr.bounds_local(u, v))
+
+ def tri(self):
+ """Return difference between end values."""
+ return self.thisptr.tri()
+
+ def hat(self):
+ """Return value at (0.5)."""
+ return self.thisptr.hat()
+
+ @classmethod
+ def sin(cls, cy_Linear bo, int k):
+ """Return sine of linear."""
+ return wrap_SBasis(sin(deref( bo.thisptr ), k))
+
+ @classmethod
+ def cos(cls, cy_Linear bo, int k):
+ """Return cosine of linear."""
+ return wrap_SBasis(cos(deref( bo.thisptr ), k))
+
+ @classmethod
+ def reciprocal(cls, cy_Linear a, int k):
+ """Return reciprocical of linear."""
+ return wrap_SBasis(reciprocal(deref( a.thisptr ), k))
+
+ @classmethod
+ def shift(cls, cy_Linear a, int sh):
+ """Multiply by x**sh."""
+ return wrap_SBasis(shift(deref( a.thisptr ), sh))
+
+#leave these in cy2geom napespace?
+def cy_lerp(double t, double a, double b):
+ return lerp(t, a, b)
+
+cdef cy_Linear wrap_Linear(Linear p):
+ cdef Linear * retp = new Linear()
+ retp[0] = p
+ cdef cy_Linear r = cy_Linear.__new__(cy_Linear)
+ r.thisptr = retp
+ return r
+
+cdef vector[Linear] make_vector_linear(object l):
+ cdef vector[Linear] ret
+ for i in l:
+ ret.push_back( deref( (<cy_Linear> i).thisptr ) )
+ return ret
+
+
+cdef class cy_SBasis:
+
+ """Class representing SBasis polynomial.
+
+ Corresponds to SBasis class in 2geom."""
+
+ def __cinit__(self, a=None, b=None):
+ """Create new SBasis.
+
+ This constructor only creates linear SBasis, specifying endpoints.
+ """
+ if a is None:
+ self.thisptr = new SBasis()
+ elif b is None:
+ self.thisptr = new SBasis( float(a) )
+ else:
+ self.thisptr = new SBasis( float(a), float(b) )
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ @classmethod
+ def from_linear(cls, cy_Linear l):
+ """Create SBasis from Linear."""
+ return wrap_SBasis( SBasis(deref( l.thisptr )) )
+
+ @classmethod
+ def from_linears(cls, lst):
+ """Create SBasis from list of Linears."""
+ return wrap_SBasis( SBasis( make_vector_linear(lst) ) )
+
+ def size(self):
+ """Return number of linears SBasis consists of."""
+ return self.thisptr.size()
+
+ def __call__(self, o):
+ """Get point at time value t."""
+ if isinstance(o, Number):
+ return deref(self.thisptr)(float(o))
+ elif isinstance(self, cy_SBasis):
+ return wrap_SBasis(deref(self.thisptr)( deref( (<cy_SBasis> o).thisptr ) ))
+
+ def __getitem__(self, unsigned int i):
+ """Get Linear at i th position."""
+ if i>=self.size():
+ raise IndexError
+ else:
+ return wrap_Linear(deref( self.thisptr ) [i])
+
+ def __neg__(self):
+ """Return SBasis with negated values."""
+ return wrap_SBasis( SB_neg(deref(self.thisptr)) )
+
+ #cython doesn't use __rmul__, it switches the arguments instead
+ def __add__(cy_SBasis self, other):
+ """Add number or other SBasis to SBasis."""
+ if isinstance(other, Number):
+ return wrap_SBasis( deref(self.thisptr) + float(other) )
+ elif isinstance(other, cy_SBasis):
+ return wrap_SBasis( deref(self.thisptr) + deref( (<cy_SBasis> other).thisptr ) )
+
+ def __sub__(cy_SBasis self, other):
+ """Substract number or other SBasis from SBasis."""
+ if isinstance(other, Number):
+ return wrap_SBasis( SB_sub_Sd(deref(self.thisptr), float(other) ) )
+ elif isinstance(other, cy_SBasis):
+ return wrap_SBasis( SB_sub_SS(deref(self.thisptr), deref( (<cy_SBasis> other).thisptr ) ) )
+
+ def __mul__(self, other):
+ """Multiply SBasis by number or other SBasis."""
+ if isinstance(other, Number):
+ return wrap_SBasis( deref( (<cy_SBasis> self).thisptr ) * float(other) )
+ elif isinstance(other, cy_SBasis):
+ if isinstance(self, cy_SBasis):
+ return wrap_SBasis( deref( (<cy_SBasis> self).thisptr ) * deref( (<cy_SBasis> other).thisptr ) )
+ elif isinstance(self, Number):
+ return wrap_SBasis( float(self) * deref( (<cy_SBasis> other).thisptr ) )
+
+ def __div__(cy_SBasis self, double other):
+ """Divide SBasis by number."""
+ return wrap_SBasis( deref(self.thisptr)/other )
+
+
+ def empty(self):
+ """Test whether SBasis has no linears."""
+ return self.thisptr.empty()
+
+ def back(self):
+ """Return last linear in SBasis."""
+ return wrap_Linear(self.thisptr.back())
+
+ def pop_back(self):
+ """Remove last linear in SBasis."""
+ self.thisptr.pop_back()
+
+ def resize(self, unsigned int n, cy_Linear l = None):
+ """Resize SBasis, optionally filling created slots with linear."""
+ if l is None:
+ self.thisptr.resize(n)
+ else:
+ self.thisptr.resize(n, deref( l.thisptr ))
+
+#~ def reserve(self, unsigned int n):
+#~ self.thisptr.reserve(n)
+
+ def clear(self):
+ """Make SBasis empty."""
+ self.thisptr.clear()
+#~ def insert(self, cy_::__gnu_cxx::__normal_iterator<Geom::Linear*, std::vector<Geom::Linear, std::allocator<Geom::Linear> > > before, cy_::__gnu_cxx::__normal_iterator<Geom::Linear const*, std::vector<Geom::Linear, std::allocator<Geom::Linear> > > src_begin, cy_::__gnu_cxx::__normal_iterator<Geom::Linear const*, std::vector<Geom::Linear, std::allocator<Geom::Linear> > > src_end):
+#~ self.thisptr.insert(deref( before.thisptr ), deref( src_begin.thisptr ), deref( src_end.thisptr ))
+
+ def at(self, unsigned int i):
+ """Equivalent to self[i]."""
+ return wrap_Linear(self.thisptr.at(i))
+
+ def __richcmp__(cy_SBasis self, cy_SBasis B, int op):
+ if op == 2:
+ return deref( self.thisptr ) == deref( B.thisptr )
+ elif op == 3:
+ return deref( self.thisptr ) != deref( B.thisptr )
+
+ def is_zero(self, double eps = EPSILON):
+ """Test whether linear is zero within given tolerance."""
+ return self.thisptr.isZero(eps)
+
+ def is_constant(self, double eps = EPSILON):
+ """Test whether linear is constant within given tolerance."""
+ return self.thisptr.isConstant(eps)
+
+ def is_finite(self):
+ """Test whether linear is finite."""
+ return self.thisptr.isFinite()
+
+ def at0(self):
+ """Equivalent to self(0)."""
+ return self.thisptr.at0()
+
+ def at1(self):
+ """Equivalent to self(1)."""
+ return self.thisptr.at1()
+
+ def degrees_of_freedom(self):
+ """Return number of independent parameters needed to specify the curve."""
+ return self.thisptr.degreesOfFreedom()
+
+ def value_at(self, double t):
+ """Equivalent to self(t)[d]."""
+ return self.thisptr.valueAt(t)
+
+ def value_and_derivatives(self, double t, unsigned int n):
+ """Return value and at least n derivatives at time t."""
+ return wrap_vector_double (self.thisptr.valueAndDerivatives(t, n))
+
+ def to_SBasis(self):
+ """Just return self."""
+ return wrap_SBasis(self.thisptr.toSBasis())
+
+ def tail_error(self, unsigned int tail):
+ """Return largest error after truncating linears from tail."""
+ return self.thisptr.tailError(tail)
+
+ def normalize(self):
+ """Remove zero linears at the end."""
+ self.thisptr.normalize()
+
+ def truncate(self, unsigned int k):
+ """Truncate SBasis to have k elements."""
+ self.thisptr.truncate(k)
+
+ @classmethod
+ def sqrt(cls, cy_SBasis a, int k):
+ """Return square root of SBasis.
+
+ Use k to specify degree of resulting SBasis.
+ """
+ return wrap_SBasis(sqrt(deref( a.thisptr ), k))
+
+ @classmethod
+ def inverse(cls, cy_SBasis a, int k):
+ """Return inverse function to SBasis.
+
+ Passed SBasis must be function [1-1] -> [1-1] bijection.
+ """
+ return wrap_SBasis(inverse(deref( a.thisptr ), k))
+
+ @classmethod
+ def valuation(cls, cy_SBasis a, double tol = 0):
+ """Return the degree of the first non zero coefficient."""
+ return valuation(deref( a.thisptr ), tol)
+
+ #call with level_set(SBasis(1, 5), 2, a = 0.2, b = 0.4, tol = 0.02)
+ @classmethod
+ def level_set(cls, cy_SBasis f, level, a = 0, b = 1, tol = 1e-5, vtol = 1e-5):
+ """Return intervals where SBasis is in specified level.
+
+ Specify range and tolerance in other arguments.
+ """
+ if isinstance(level, cy_Interval):
+ return wrap_vector_interval(level_set(deref( f.thisptr ), deref( (<cy_Interval> level).thisptr ), a, b, tol)) #a, b, tol
+ else:
+ return wrap_vector_interval(level_set(deref( f.thisptr ), float(level), vtol, a, b, tol)) #vtol, a, b, tol
+
+ @classmethod
+ def shift(cls, cy_SBasis a, int sh):
+ """Multiply by x**sh."""
+ return wrap_SBasis(shift(deref( a.thisptr ), sh))
+
+ @classmethod
+ def compose(cls, cy_SBasis a, cy_SBasis b, k = None):
+ """Compose two SBasis.
+
+ Specify order of resulting SBasis by parameter k.
+ """
+ if k is None:
+ return wrap_SBasis(compose(deref( a.thisptr ), deref( b.thisptr )))
+ else:
+ return wrap_SBasis(compose(deref( a.thisptr ), deref( b.thisptr ), int(k)))
+
+ @classmethod
+ def roots(cls, cy_SBasis s, cy_Interval inside = None):
+ """Return time values where self equals 0.
+
+ inside intervals specifies subset of domain.
+ """
+ if inside is None:
+ return wrap_vector_double(roots(deref( s.thisptr )))
+ else:
+ return wrap_vector_double(roots(deref( s.thisptr ), deref( inside.thisptr )))
+
+ @classmethod
+ def multi_roots(cls, cy_SBasis f, levels, double htol = 1e-7, double vtol = 1e-7, double a = 0, double b = 1):
+ """Return lists of roots for different levels."""
+ cdef vector[double] l = make_vector_double(levels)
+ cdef vector[ vector[double] ] r = multi_roots(deref( f.thisptr ), l, htol, vtol, a, b)
+ lst = []
+ for i in range(r.size()):
+ lst.append( wrap_vector_double(r[i]) )
+ return lst
+
+ @classmethod
+ def multiply_add(cls, cy_SBasis a, cy_SBasis b, cy_SBasis c):
+ """Return a*b+c."""
+ return wrap_SBasis(multiply_add(deref( a.thisptr ), deref( b.thisptr ), deref( c.thisptr )))
+
+ @classmethod
+ def divide(cls, cy_SBasis a, cy_SBasis b, int k):
+ """Divide two SBasis functions.
+
+ Use k to specify degree of resulting SBasis.
+ """
+ return wrap_SBasis(divide(deref( a.thisptr ), deref( b.thisptr ), k))
+
+ @classmethod
+ def compose_inverse(cls, cy_SBasis f, cy_SBasis g, unsigned int order, double tol):
+ """Compose f with g's inverse.
+
+ Requires g to be bijection g: [0, 1] -> [0, 1]
+ """
+ return wrap_SBasis(compose_inverse(deref( f.thisptr ), deref( g.thisptr ), order, tol))
+
+ @classmethod
+ def multiply(cls, cy_SBasis a, cy_SBasis b):
+ """Multiply two SBasis functions."""
+ return wrap_SBasis(multiply(deref( (<cy_SBasis> a).thisptr ), deref( (<cy_SBasis> b).thisptr )))
+
+ @classmethod
+ def derivative(cls, cy_SBasis a):
+ """Return derivative os SBasis."""
+ return wrap_SBasis(derivative(deref( (<cy_SBasis> a).thisptr )))
+
+ @classmethod
+ def integral(cls, a):
+ """Return integral of SBasis."""
+ return wrap_SBasis(integral(deref( (<cy_SBasis> a).thisptr )))
+
+ @classmethod
+ def portion(cls, cy_SBasis a, Coord fr=0, Coord to=1, cy_Interval interval=None):
+ """Return portion of SBasis, specified by endpoints or interval."""
+ if interval is None:
+ return wrap_SBasis( portion( deref( a.thisptr ), fr, to ) )
+ else:
+ return wrap_SBasis( portion( deref( a.thisptr ), deref( interval.thisptr ) ) )
+
+ @classmethod
+ def bounds_fast(cls, cy_SBasis a, int order = 0):
+ """Return bounding interval
+
+ This method is fast, but does not guarantee to give smallest
+ interval.
+ """
+ return wrap_OptInterval(bounds_fast(deref( a.thisptr ), order))
+
+ @classmethod
+ def bounds_exact(cls, cy_SBasis a):
+ """Return exact bounding interval
+
+ This may take a while.
+ """
+ return wrap_OptInterval(bounds_exact(deref( a.thisptr )))
+
+ @classmethod
+ def bounds_local(cls, cy_SBasis a, cy_OptInterval t, int order = 0):
+ """Return bounding interval to the portion of SBasis."""
+ return wrap_OptInterval(bounds_local(deref( a.thisptr ), deref( t.thisptr ), order))
+
+#~ def cy_level_sets(cy_SBasis f, vector[Interval] levels, double a, double b, double tol):
+#~ return wrap_::std::vector<std::vector<Geom::Interval, std::allocator<Geom::Interval> >,std::allocator<std::vector<Geom::Interval, std::allocator<Geom::Interval> > > >(level_sets(deref( f.thisptr ), deref( levels.thisptr ), a, b, tol))
+#~ def cy_level_sets(cy_SBasis f, vector[vector] levels, double a, double b, double vtol, double tol):
+#~ return wrap_::std::vector<std::vector<Geom::Interval, std::allocator<Geom::Interval> >,std::allocator<std::vector<Geom::Interval, std::allocator<Geom::Interval> > > >(level_sets(deref( f.thisptr ), deref( levels.thisptr ), a, b, vtol, tol))
+
+def cy_reverse(a):
+ if isinstance(a, cy_Linear):
+ return wrap_Linear( reverse(deref( (<cy_Linear> a).thisptr )))
+ elif isinstance(a, cy_SBasis):
+ return wrap_SBasis( reverse(deref( (<cy_SBasis> a).thisptr )))
+ elif isinstance(a, cy_Bezier):
+ return wrap_Bezier( reverse(deref( (<cy_Bezier> a).thisptr )))
+
+#already implemented
+#~ def cy_truncate(cy_SBasis a, unsigned int terms):
+#~ return wrap_SBasis(truncate(deref( a.thisptr ), terms))
+
+cdef cy_SBasis wrap_SBasis(SBasis p):
+ cdef SBasis * retp = new SBasis()
+ retp[0] = p
+ cdef cy_SBasis r = cy_SBasis.__new__(cy_SBasis, 0, 0)
+ r.thisptr = retp
+ return r
+
+
+cdef class cy_SBasisCurve:
+
+ """Curve mapping two SBasis functions to point (s1(t), s2(t)).
+
+ Corresponds to SBasisCurve in 2geom.
+ """
+
+ cdef SBasisCurve* thisptr
+
+#~ def __init__(self, cy_Curve other):
+#~ self.thisptr = self.thisptr.SBasisCurve(deref( other.thisptr ))
+
+ def __cinit__(self, cy_SBasis s1, cy_SBasis s2):
+ """Create new SBasisCurve from two SBasis functions."""
+ self.thisptr = new SBasisCurve( D2[SBasis](
+ deref( s1.thisptr ),
+ deref( s2.thisptr ) ) )
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ def __call__(self, double t):
+ """Get point at time value t."""
+ return wrap_Point(deref(self.thisptr)(t))
+
+ def duplicate(self):
+ """Duplicate the curve."""
+ return wrap_SBasisCurve( <SBasisCurve> deref(self.thisptr.duplicate()) )
+
+ def initial_point(self):
+ """Get self(0)."""
+ return wrap_Point(self.thisptr.initialPoint())
+
+ def final_point(self):
+ """Get self(1)."""
+ return wrap_Point(self.thisptr.finalPoint())
+
+ def is_degenerate(self):
+ """Curve is degenerate if it's length is zero."""
+ return self.thisptr.isDegenerate()
+
+ def point_at(self, Coord t):
+ """Equivalent to self(t)."""
+ return wrap_Point(self.thisptr.pointAt(t))
+
+ def point_and_derivatives(self, Coord t, unsigned int n):
+ """Return point and at least first n derivatives at point t in list."""
+ return wrap_vector_point(self.thisptr.pointAndDerivatives(t, n))
+
+ def value_at(self, Coord t, Dim2 d):
+ """Equivalent to self(t)[d]."""
+ return self.thisptr.valueAt(t, d)
+
+ def set_initial(self, cy_Point v):
+ """Set initial point of curve."""
+ self.thisptr.setInitial(deref( v.thisptr ))
+
+ def set_final(self, cy_Point v):
+ """Set final point of curve."""
+ self.thisptr.setFinal(deref( v.thisptr ))
+
+ def bounds_fast(self):
+ """Return bounding rectangle for curve.
+
+ This method is fast, but does not guarantee to give smallest
+ rectangle.
+ """
+ return wrap_Rect(self.thisptr.boundsFast())
+
+ def bounds_exact(self):
+ """Return exact bounding rectangle for curve.
+
+ This may take a while.
+ """
+ return wrap_Rect(self.thisptr.boundsExact())
+
+ def bounds_local(self, cy_OptInterval i, unsigned int deg):
+ """Return bounding rectangle to portion of curve."""
+ return wrap_OptRect(self.thisptr.boundsLocal(deref( i.thisptr ), deg))
+
+ def roots(self, Coord v, Dim2 d):
+ """Find time values where self(t)[d] == v."""
+ return wrap_vector_double( self.thisptr.roots(v, d) )
+
+ def nearest_time(self, cy_Point p, Coord fr=0, Coord to=1, cy_Interval interval=None):
+ """Return such t that |self(t) - point| is minimized."""
+ if interval is None:
+ return self.thisptr.nearestTime(deref( p.thisptr ), fr, to)
+ else:
+ return (<Curve *> self.thisptr).nearestTime(deref( p.thisptr ), deref( interval.thisptr ) )
+
+ def all_nearest_times(self, cy_Point p, Coord fr=0, Coord to=1, cy_Interval interval=None):
+ """Return all values of t that |self(t) - point| is minimized."""
+ if interval is None:
+ return wrap_vector_double(self.thisptr.allNearestTimes(deref( p.thisptr ), fr, to))
+ else:
+ return wrap_vector_double((<Curve *> self.thisptr).allNearestTimes(deref( p.thisptr ),
+ deref( interval.thisptr ) ))
+
+ def length(self, Coord tolerance = 0.01):
+ """Return length of curve, within give tolerance."""
+ return self.thisptr.length(tolerance)
+
+
+ def portion(self, Coord fr=0, Coord to=1, cy_Interval interval=None):
+ """Return portion of curve, specified by endpoints or interval."""
+ if interval is None:
+ return wrap_SBasisCurve( <SBasisCurve> deref(self.thisptr.portion( fr, to ) ) )
+ else:
+ return wrap_SBasisCurve( <SBasisCurve>
+ deref( (<Curve *> self.thisptr).portion( deref( interval.thisptr ))) )
+
+ def transformed(self, t):
+ """Transform curve by affine transform."""
+ cdef Affine at
+ if is_transform(t):
+ at = get_Affine(t)
+ return wrap_SBasisCurve( <SBasisCurve> deref(self.thisptr.transformed( at )))
+
+ def reverse(self):
+ """Return curve with reversed time."""
+ return wrap_SBasisCurve( <SBasisCurve> deref( (<Curve *> self.thisptr).reverse() ) )
+
+ def derivative(self):
+ """Return curve's derivative."""
+ return wrap_SBasisCurve( <SBasisCurve> deref(self.thisptr.derivative()) )
+
+
+ def winding(self, cy_Point p):
+ """Return winding number around specified point."""
+ return (<Curve *> self.thisptr).winding(deref(p.thisptr))
+
+ def unit_tangent_at(self, Coord t, int n = 3):
+ """Return tangent at self(t).
+
+ Parameter n specifies how many derivatives to take into account."""
+ return wrap_Point((<Curve *> self.thisptr).unitTangentAt(t, n))
+
+ def to_SBasis(self):
+ """Return tuple containing it's SBasis functions."""
+ return wrap_D2_SBasis(self.thisptr.toSBasis())
+
+ def degrees_of_freedom(self):
+ """Return number of independent parameters needed to specify the curve."""
+ return self.thisptr.degreesOfFreedom()
+
+cdef object wrap_D2_SBasis(D2[SBasis] p):
+ return ( wrap_SBasis(p[0]), wrap_SBasis(p[1]) )
+
+cdef cy_SBasisCurve wrap_SBasisCurve(SBasisCurve p):
+ cdef SBasisCurve * retp = new SBasisCurve(D2[SBasis]( SBasis(), SBasis() ))
+ retp[0] = p
+ cdef cy_SBasisCurve r = cy_SBasisCurve.__new__(cy_SBasisCurve, cy_SBasis(), cy_SBasis())
+ r.thisptr = retp
+ return r
+
+
+cdef class cy_Bezier:
+
+ """Bezier polynomial.
+
+ Corresponds to Bezier class in 2geom.
+ """
+
+ cdef Bezier* thisptr
+
+ def __cinit__(self, *args):
+ """Create Bezier polynomial specifying it's coeffincients
+
+ This constructor takes up to four coefficients.
+ """
+ if len(args) == 0:
+ #new Bezier() causes segfault
+ self.thisptr = new Bezier(0)
+ elif len(args) == 1:
+ self.thisptr = new Bezier( float(args[0]) )
+ elif len(args) == 2:
+ self.thisptr = new Bezier( float(args[0]), float(args[1]) )
+ elif len(args) == 3:
+ self.thisptr = new Bezier( float(args[0]), float(args[1]), float(args[2]) )
+ elif len(args) == 4:
+ self.thisptr = new Bezier( float(args[0]), float(args[1]), float(args[2]), float(args[3]) )
+ else:
+ raise ValueError("Passed list has too many points")
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ def __call__(self, double t):
+ """Get point at time value t."""
+ return deref( self.thisptr ) (t)
+
+
+ def __getitem__(self, unsigned int ix):
+ """Get coefficient by accessing list."""
+ if ix >= self.size():
+ raise IndexError
+ return deref( self.thisptr ) [ix]
+
+ def order(self):
+ """Return order of Bezier."""
+ return self.thisptr.order()
+
+ def size(self):
+ """Return number of coefficients."""
+ return self.thisptr.size()
+
+ def __mul__( cy_Bezier self, double v):
+ """Multiply Bezier by number."""
+ return wrap_Bezier(deref( self.thisptr ) * v)
+
+ def __add__( cy_Bezier self, double v):
+ """Add number to Bezier."""
+ return wrap_Bezier(deref( self.thisptr ) + v)
+
+ def __sub__( cy_Bezier self, double v):
+ """Substract number from Bezier."""
+ return wrap_Bezier(deref( self.thisptr ) - v)
+
+ def __div__( cy_Bezier self, double v):
+ """Divide Bezier number."""
+ return wrap_Bezier(deref( self.thisptr ) / v)
+
+
+ def resize(self, unsigned int n, Coord v):
+ """Change order of Bezier."""
+ self.thisptr.resize(n, v)
+
+ def clear(self):
+ """Create empty Bezier."""
+ self.thisptr.clear()
+
+ def degree(self):
+ """Return degree of Bezier polynomial."""
+ return self.thisptr.degree()
+
+ def is_zero(self, double eps = EPSILON):
+ """Test whether linear is zero within given tolerance."""
+ return self.thisptr.isZero(eps)
+
+ def is_constant(self, double eps = EPSILON):
+ """Test whether linear is constant within given tolerance."""
+ return self.thisptr.isConstant(eps)
+
+ def is_finite(self):
+ """Test whether linear is finite."""
+ return self.thisptr.isFinite()
+
+ def at0(self):
+ """Equivalent to self(0)."""
+ return self.thisptr.at0()
+
+ def at1(self):
+ """Equivalent to self(1)."""
+ return self.thisptr.at1()
+
+ def value_at(self, double t):
+ """Equivalent to self(t)."""
+ return self.thisptr.valueAt(t)
+
+ def to_SBasis(self):
+ """Convert to SBasis."""
+ return wrap_SBasis(self.thisptr.toSBasis())
+
+ def set_point(self, unsigned int ix, double val):
+ """Set self[ix] to val."""
+ self.thisptr.setPoint(ix, val)
+
+ def value_and_derivatives(self, Coord t, unsigned int n_derivs):
+ """Return value and at least n derivatives at time t."""
+ return wrap_vector_double(self.thisptr.valueAndDerivatives(t, n_derivs))
+
+ def subdivide(self, Coord t):
+ """Get two beziers, from 0 to t and from t to 1."""
+ cdef pair[Bezier, Bezier] p = self.thisptr.subdivide(t)
+ return ( wrap_Bezier(p.first), wrap_Bezier(p.second) )
+
+ def roots(self, cy_Interval ivl = None):
+ """Find time values where self(t)[d] == v."""
+ if ivl is None:
+ return wrap_vector_double(self.thisptr.roots())
+ else:
+ return wrap_vector_double(self.thisptr.roots(deref( ivl.thisptr )))
+
+ def forward_difference(self, unsigned int k):
+#TODO: ask someone what this function does.
+#~ """Compute forward difference of degree k.
+#~
+#~ First forward difference of B is roughly function B'(t) = B(t+h)-B(t)
+#~ for fixed step h"""
+ return wrap_Bezier(self.thisptr.forward_difference(k))
+
+ def elevate_degree(self):
+ """Increase degree of Bezier by 1."""
+ return wrap_Bezier(self.thisptr.elevate_degree())
+
+ def reduce_degree(self):
+ """Decrease degree of Bezier by 1."""
+ return wrap_Bezier(self.thisptr.reduce_degree())
+
+ def elevate_to_degree(self, unsigned int new_degree):
+ """Increase degree of Bezier to new_degree."""
+ return wrap_Bezier(self.thisptr.elevate_to_degree(new_degree))
+
+ def deflate(self):
+#TODO: ask someone what this function does.
+ #It looks like integral(self)*self.size()
+ return wrap_Bezier(self.thisptr.deflate())
+
+ @classmethod
+ def bezier_points(cls, cy_Bezier a, cy_Bezier b):
+ """Return control points of BezierCurve consisting of two beziers.
+
+ Passed bezier must have same degree."""
+ return wrap_vector_point(bezier_points( D2[Bezier]( deref(a.thisptr), deref(b.thisptr) ) ))
+
+ @classmethod
+ def multiply(cls, cy_Bezier a, cy_Bezier b):
+ """Multiply two Bezier functions."""
+ return wrap_Bezier(multiply(deref( (<cy_Bezier> a).thisptr ),
+ deref( (<cy_Bezier> b).thisptr )))
+
+ @classmethod
+ def portion(cls, cy_Bezier a, Coord fr=0, Coord to=1, interval=None):
+ """Return portion of bezier, specified by endpoints or interval."""
+ if interval is None:
+ return wrap_Bezier(portion(deref( a.thisptr ), fr, to))
+ else:
+ return wrap_Bezier(portion(deref( a.thisptr ), float(interval.min()),
+ float(interval.max()) ))
+
+ @classmethod
+ def derivative(cls, cy_Bezier a):
+ """Return derivative of a bezier."""
+ return wrap_Bezier(derivative(deref( a.thisptr )))
+
+ @classmethod
+ def integral(cls, cy_Bezier a):
+ """Return derivative of a bezier."""
+ return wrap_Bezier(integral(deref( a.thisptr )))
+
+ @classmethod
+ def bounds_fast(cls, cy_Bezier a):
+ """Return bounding interval
+
+ This method is fast, but does not guarantee to give smallest
+ interval.
+ """
+ return wrap_OptInterval(bounds_fast(deref( a.thisptr )))
+
+ @classmethod
+ def bounds_exact(cls, cy_Bezier a):
+ """Return exact bounding interval
+
+ This may take a while.
+ """
+ return wrap_OptInterval(bounds_exact(deref( a.thisptr )))
+
+ @classmethod
+ def bounds_local(cls, cy_Bezier a, cy_OptInterval t):
+ """Return bounding interval to the portion of bezier."""
+ return wrap_OptInterval(bounds_local(deref( a.thisptr ), deref( t.thisptr )))
+
+#This is the same as bz.to_SBasis()
+#~ def cy_bezier_to_sbasis(cy_SBasis sb, cy_Bezier bz):
+#~ bezier_to_sbasis(deref( sb.thisptr ), deref( bz.thisptr ))
+
+#These are look like internal functions.
+#~ def cy_casteljau_subdivision(Coord t, cy_Coord * v, cy_Coord * left, cy_Coord * right, unsigned int order):
+#~ return subdivideArr(t, v.thisptr, left.thisptr, right.thisptr, order)
+#~ def cy_bernsteinValueAt(double t, cy_double * c_, unsigned int n):
+#~ return bernsteinValueAt(t, c_.thisptr, n)
+
+cdef cy_Bezier wrap_Bezier(Bezier p):
+ cdef Bezier * retp = new Bezier()
+ retp[0] = p
+ cdef cy_Bezier r = cy_Bezier.__new__(cy_Bezier)
+ r.thisptr = retp
+ return r
+
+
+cdef class cy_BezierCurve:
+
+ """Bezier curve, consisting of two Bezier functions.
+
+ Corresponds to BezierCurve class in 2geom.
+ """
+
+ #This flag is due to this class children
+ def __cinit__(self, *args, **kwargs):
+ """Don't use this constructor, use create instead."""
+ pass
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ def __call__(self, Coord t):
+ """Get point at time value t."""
+ return wrap_Point(deref( <Curve *> self.thisptr )(t))
+
+ def __getitem__(self, unsigned int ix):
+ """Get control point by list access."""
+ return wrap_Point(deref( self.thisptr ) [ix])
+
+ @classmethod
+ def create(cls, pts):
+ """Create new BezierCurve from control points."""
+ return wrap_BezierCurve( deref( create( make_vector_point(pts) ) ) )
+
+ def order(self):
+ """Get order of curve."""
+ return self.thisptr.order()
+
+ def control_points(self):
+ """Get control points."""
+ return wrap_vector_point(self.thisptr.controlPoints())
+
+ def set_point(self, unsigned int ix, cy_Point v):
+ """Set control point."""
+ self.thisptr.setPoint(ix, deref( v.thisptr ))
+
+ def set_points(self, ps):
+ """Set control points"""
+ self.thisptr.setPoints( make_vector_point(ps) )
+
+ def initial_point(self):
+ """Get self(0)."""
+ return wrap_Point(self.thisptr.initialPoint())
+
+ def final_point(self):
+ """Get self(1)."""
+ return wrap_Point(self.thisptr.finalPoint())
+
+ def is_degenerate(self):
+ """Curve is degenerate if it's length is zero."""
+ return self.thisptr.isDegenerate()
+
+ def set_initial(self, cy_Point v):
+ """Set initial point of curve."""
+ self.thisptr.setInitial(deref( v.thisptr ))
+
+ def set_final(self, cy_Point v):
+ """Set final point of curve."""
+ self.thisptr.setFinal(deref( v.thisptr ))
+
+ def bounds_fast(self):
+ """Return bounding rectangle for curve.
+
+ This method is fast, but does not guarantee to give smallest
+ rectangle.
+ """
+ return wrap_Rect(self.thisptr.boundsFast())
+
+ def bounds_exact(self):
+ """Return exact bounding rectangle for curve.
+
+ This may take a while.
+ """
+ return wrap_Rect(self.thisptr.boundsExact())
+
+ def bounds_local(cy_BezierCurve self, cy_OptInterval i, unsigned int deg):
+ """Return bounding rectangle to portion of curve."""
+ return wrap_OptRect(self.thisptr.boundsLocal(deref( i.thisptr ), deg))
+
+ def nearest_time(self, cy_Point p, Coord fr=0, Coord to=1, cy_Interval interval=None):
+ """Return such t that |self(t) - point| is minimized."""
+ if interval is None:
+ return (<Curve *> self.thisptr).nearestTime(deref( p.thisptr ), fr, to)
+ else:
+ return (<Curve *> self.thisptr).nearestTime(deref( p.thisptr ), deref( interval.thisptr ) )
+
+ def all_nearest_times(self, cy_Point p, Coord fr=0, Coord to=1, cy_Interval interval=None):
+ """Return all values of t that |self(t) - point| is minimized."""
+ if interval is None:
+ return wrap_vector_double((<Curve *> self.thisptr).allNearestTimes(deref( p.thisptr ), fr, to))
+ else:
+ return wrap_vector_double((<Curve *> self.thisptr).allNearestTimes(deref( p.thisptr ),
+ deref( interval.thisptr ) ))
+
+ def portion(self, Coord fr=0, Coord to=1, cy_Interval interval=None):
+ """Return portion of curve, specified by endpoints or interval."""
+ if interval is None:
+ return wrap_BezierCurve( <BezierCurve> deref(<BezierCurve *>
+ (<Curve *> self.thisptr).portion( fr, to )
+ ) )
+ else:
+ return wrap_BezierCurve( <BezierCurve> deref(<BezierCurve *>
+ (<Curve *> self.thisptr).portion(deref( interval.thisptr ))
+ ) )
+
+ def duplicate(self):
+ """Duplicate the curve."""
+ return wrap_BezierCurve( deref( <BezierCurve *> self.thisptr.duplicate()))
+
+ def reverse(self):
+ """Return curve with reversed time."""
+ return wrap_BezierCurve( deref( <BezierCurve *> self.thisptr.reverse()))
+
+ def transformed(self, t):
+ """Transform curve by affine transform."""
+ cdef Affine at
+ if is_transform(t):
+ at = get_Affine(t)
+ return wrap_BezierCurve( deref( <BezierCurve *> self.thisptr.transformed( at )))
+
+ def derivative(self):
+ """Return curve's derivative."""
+ return wrap_BezierCurve( deref( <BezierCurve *> self.thisptr.derivative()))
+
+ def degrees_of_freedom(self):
+ """Return number of independent parameters needed to specify the curve."""
+ return self.thisptr.degreesOfFreedom()
+
+ def roots(self, Coord v, Dim2 d):
+ """Find time values where self(t)[d] == v."""
+ return wrap_vector_double(self.thisptr.roots(v, d))
+
+ def length(self, Coord tolerance = 0.01):
+ """Return length of curve, within give tolerance."""
+ return self.thisptr.length(tolerance)
+
+ def point_at(self, Coord t):
+ """Equivalent to self(t)."""
+ return wrap_Point(self.thisptr.pointAt(t))
+
+ def point_and_derivatives(self, Coord t, unsigned int n):
+ """Return point and at least first n derivatives at point t in list."""
+ return wrap_vector_point(self.thisptr.pointAndDerivatives(t, n))
+
+ def value_at(self, Coord t, Dim2 d):
+ """Equivalent to self(t)[d]."""
+ return self.thisptr.valueAt(t, d)
+
+ def to_SBasis(self):
+ """Convert self to pair of SBasis functions."""
+ return wrap_D2_SBasis(self.thisptr.toSBasis())
+
+ def winding(self, cy_Point p):
+ """Return winding number around specified point."""
+ return (<Curve *> self.thisptr).winding(deref(p.thisptr))
+
+ def unit_tangent_at(self, Coord t, int n = 3):
+ """Return tangent at self(t).
+
+ Parameter n specifies how many derivatives to take into account."""
+ return wrap_Point((<Curve *> self.thisptr).unitTangentAt(t, n))
+
+cdef cy_BezierCurve wrap_BezierCurve(BezierCurve p):
+ cdef vector[Point] points = make_vector_point([cy_Point(), cy_Point()])
+ cdef BezierCurve * retp = create(p.controlPoints())
+ cdef cy_BezierCurve r = cy_BezierCurve.__new__(cy_BezierCurve, [cy_Point(), cy_Point()])
+ r.thisptr = retp
+ return r
+
+
+cdef class cy_LineSegment(cy_BezierCurve):
+
+ """Bezier curve with fixed order 1.
+
+ This class inherits from BezierCurve.
+
+ Corresponds to LineSegment in 2geom. BezierCurveN is not wrapped.
+ """
+
+ def __cinit__(self, cy_Point p0=None,
+ cy_Point p1=cy_Point()):
+ """Create new LineSegment from it's endpoints."""
+ if p0 is None:
+ self.thisptr = <BezierCurve *> new LineSegment()
+ else:
+ self.thisptr = <BezierCurve *> new LineSegment( deref(p0.thisptr),
+ deref(p1.thisptr))
+
+ @classmethod
+ def from_beziers(cls, cy_Bezier b0, cy_Bezier b1):
+ """Create LineSegment from two linear beziers."""
+ return wrap_LineSegment( LineSegment(deref(b0.thisptr), deref(b1.thisptr)) )
+
+ def subdivide(self, Coord t):
+ """Get two LineSegments, from 0 to t and from t to 1."""
+ cdef pair[LineSegment, LineSegment] p = (<LineSegment *> self.thisptr).subdivide(t)
+ return ( wrap_LineSegment(p.first), wrap_LineSegment(p.second) )
+
+ def duplicate(self):
+ """Duplicate the curve."""
+ return wrap_LineSegment( deref( <LineSegment *> self.thisptr.duplicate()))
+
+ def portion(self, double fr=0, double to=1, cy_Interval interval=None):
+ """Return portion of curve, specified by endpoints or interval."""
+ if interval is None:
+ return wrap_LineSegment( deref( <LineSegment *> self.thisptr.portion( fr, to ) ) )
+ else:
+ return wrap_LineSegment( deref( <LineSegment *>
+ (<Curve *> self.thisptr).portion( deref( interval.thisptr ))
+ ) )
+
+ def reverse(self):
+ """Return curve with reversed time."""
+ return wrap_LineSegment( deref( <LineSegment *> self.thisptr.reverse()))
+
+ def transformed(self, t):
+ """Transform curve by affine transform."""
+ cdef Affine at
+ if is_transform(t):
+ at = get_Affine(t)
+ return wrap_LineSegment( deref( <LineSegment *> self.thisptr.transformed( at )))
+
+ def derivative(self):
+ """Return curve's derivative."""
+ return wrap_LineSegment( deref( <LineSegment *> self.thisptr.derivative()))
+
+cdef cy_LineSegment wrap_LineSegment(LineSegment p):
+ cdef LineSegment * retp = new LineSegment()
+ retp[0] = p
+ cdef cy_LineSegment r = cy_LineSegment.__new__(cy_LineSegment)
+ r.thisptr = <BezierCurve* > retp
+ return r
+
+
+cdef class cy_QuadraticBezier(cy_BezierCurve):
+
+ """Bezier curve with fixed order 2.
+
+ This class inherits from BezierCurve.
+
+ Corresponds to QuadraticBezier in 2geom. BezierCurveN is not wrapped.
+ """
+
+ def __cinit__(self, cy_Point p0=None,
+ cy_Point p1=cy_Point(),
+ cy_Point p2=cy_Point()):
+ """Create new QuadraticBezier from three control points."""
+ if p0 is None:
+ self.thisptr = <BezierCurve *> new QuadraticBezier()
+ else:
+ self.thisptr = <BezierCurve *> new QuadraticBezier( deref( p0.thisptr ),
+ deref( p1.thisptr ),
+ deref( p2.thisptr ) )
+
+ @classmethod
+ def from_beziers(cls, cy_Bezier b0, cy_Bezier b1):
+ """Create QuadraticBezier from two quadratic bezier functions."""
+ return wrap_QuadraticBezier( QuadraticBezier(deref(b0.thisptr), deref(b1.thisptr)) )
+
+ def subdivide(self, Coord t):
+ """Get two QuadraticBeziers, from 0 to t and from t to 1."""
+ cdef pair[QuadraticBezier, QuadraticBezier] p = (<QuadraticBezier *> self.thisptr).subdivide(t)
+ return ( wrap_QuadraticBezier(p.first), wrap_QuadraticBezier(p.second) )
+
+ def duplicate(self):
+ """Duplicate the curve."""
+ return wrap_QuadraticBezier( deref( <QuadraticBezier *> self.thisptr.duplicate()))
+
+ def portion(self, double fr=0, double to=1, cy_Interval interval=None):
+ """Return portion of curve, specified by endpoints or interval."""
+ if interval is None:
+ return wrap_QuadraticBezier( deref( <QuadraticBezier *> self.thisptr.portion( fr, to ) ) )
+ else:
+ return wrap_QuadraticBezier( deref( <QuadraticBezier *>
+ (<Curve *> self.thisptr).portion( deref( interval.thisptr ))
+ ) )
+
+ def reverse(self):
+ """Return curve with reversed time."""
+ return wrap_QuadraticBezier( deref( <QuadraticBezier *> self.thisptr.reverse()))
+
+ def transformed(self, t):
+ """Transform curve by affine transform."""
+ cdef Affine at
+ if is_transform(t):
+ at = get_Affine(t)
+ return wrap_QuadraticBezier( deref( <QuadraticBezier *> self.thisptr.transformed( at )))
+
+ def derivative(self):
+ """Return curve's derivative."""
+ return wrap_LineSegment( deref( <LineSegment *> self.thisptr.derivative()))
+
+cdef cy_QuadraticBezier wrap_QuadraticBezier(QuadraticBezier p):
+ cdef QuadraticBezier * retp = new QuadraticBezier()
+ retp[0] = p
+ cdef cy_QuadraticBezier r = cy_QuadraticBezier.__new__(cy_QuadraticBezier)
+ r.thisptr = <BezierCurve* > retp
+ return r
+
+cdef class cy_CubicBezier(cy_BezierCurve):
+
+ """Bezier curve with fixed order 2.
+
+ This class inherits from BezierCurve.
+
+ Corresponds to QuadraticBezier in 2geom. BezierCurveN is not wrapped.
+ """
+
+ def __cinit__(self, cy_Point p0=None,
+ cy_Point p1=cy_Point(),
+ cy_Point p2=cy_Point(),
+ cy_Point p3=cy_Point()):
+ """Create new CubicBezier from four control points."""
+ if p0 is None:
+ self.thisptr = <BezierCurve *> new CubicBezier()
+ else:
+ self.thisptr = <BezierCurve *> new CubicBezier( deref( p0.thisptr ),
+ deref( p1.thisptr ),
+ deref( p2.thisptr ),
+ deref( p3.thisptr ) )
+
+ @classmethod
+ def from_beziers(cls, cy_Bezier b0, cy_Bezier b1):
+ """Create CubicBezier from two cubic bezier functions."""
+ return wrap_CubicBezier( CubicBezier(deref(b0.thisptr), deref(b1.thisptr)) )
+
+ def subdivide(self, Coord t):
+ """Get two CubicBeziers, from 0 to t and from t to 1."""
+ cdef pair[CubicBezier, CubicBezier] p = (<CubicBezier *> self.thisptr).subdivide(t)
+ return ( wrap_CubicBezier(p.first), wrap_CubicBezier(p.second) )
+
+ def duplicate(self):
+ """Duplicate the curve."""
+ return wrap_CubicBezier( deref( <CubicBezier *> self.thisptr.duplicate()))
+
+ def portion(self, double fr=0, double to=1, cy_Interval interval=None):
+ """Return portion of curve, specified by endpoints or interval."""
+ if interval is None:
+ return wrap_CubicBezier( deref( <CubicBezier *> self.thisptr.portion( fr, to ) ) )
+ else:
+ return wrap_CubicBezier( deref( <CubicBezier *>
+ (<Curve *> self.thisptr).portion( deref( interval.thisptr ))
+ ) )
+
+ def reverse(self):
+ """Return curve with reversed time."""
+ return wrap_CubicBezier( deref( <CubicBezier *> self.thisptr.reverse()))
+
+ def transformed(self, t):
+ """Transform curve by affine transform."""
+ cdef Affine at
+ if is_transform(t):
+ at = get_Affine(t)
+ return wrap_CubicBezier( deref( <CubicBezier *> self.thisptr.transformed( at )))
+
+ def derivative(self):
+ """Return curve's derivative."""
+ return wrap_QuadraticBezier( deref( <QuadraticBezier *> self.thisptr.derivative()))
+
+cdef cy_CubicBezier wrap_CubicBezier(CubicBezier p):
+ cdef CubicBezier * retp = new CubicBezier()
+ retp[0] = p
+ cdef cy_CubicBezier r = cy_CubicBezier.__new__(cy_CubicBezier)
+ r.thisptr = <BezierCurve* > retp
+ return r
+
+#~ cdef class cy_BezierCurveN(cy_BezierCurve):
+
+
+cdef class cy_HLineSegment(cy_LineSegment):
+
+ """Horizontal line segment.
+
+ This class corresponds to HLineSegment in 2geom.
+ """
+
+ def __cinit__(self, cy_Point p0=None, cy_Point p1=cy_Point()):
+ """Create HLineSegment from it's endpoints."""
+ if p0 is None:
+ self.thisptr = <BezierCurve *> new HLineSegment()
+ else:
+ self.thisptr = <BezierCurve *> new HLineSegment( deref( p0.thisptr ), deref( p1.thisptr ) )
+
+ @classmethod
+ def from_points(cls, cy_Point p0, cy_Point p1):
+ """Create HLineSegment from it's endpoints."""
+ return wrap_HLineSegment( HLineSegment( deref(p0.thisptr),
+ deref(p1.thisptr)) )
+
+ @classmethod
+ def from_point_length(cls, cy_Point p, Coord length):
+ return wrap_HLineSegment( HLineSegment( deref( p.thisptr ), length ) )
+
+ def set_initial(self, cy_Point p):
+ """Set initial point of curve."""
+ (<AxisLineSegment_X *> self.thisptr).setInitial( deref(p.thisptr) )
+
+ def set_final(self, cy_Point p):
+ """Set final point of curve."""
+ (<AxisLineSegment_X *> self.thisptr).setFinal( deref(p.thisptr) )
+
+ def bounds_fast(self):
+ """Return bounding rectangle for curve.
+
+ This method is fast, but does not guarantee to give smallest
+ rectangle.
+ """
+ return wrap_Rect( (<AxisLineSegment_X *> self.thisptr).boundsFast() )
+
+ def bounds_exact(self):
+ """Return exact bounding rectangle for curve.
+
+ This may take a while.
+ """
+ return wrap_Rect( (<AxisLineSegment_X *> self.thisptr).boundsExact() )
+
+ def degrees_of_freedom(self):
+ """Return number of independent parameters needed to specify the curve."""
+ return (<AxisLineSegment_X *> self.thisptr).degreesOfFreedom()
+
+ def roots(self, Coord v, Dim2 d):
+ """Find time values where self(t)[d] == v."""
+ return wrap_vector_double( (<AxisLineSegment_X *> self.thisptr).roots(v, d) )
+
+ def nearest_time(self, cy_Point p, Coord fr=0, Coord to=1, cy_Interval interval=None):
+ """Return such t that |self(t) - point| is minimized."""
+ if interval is None:
+ return (<AxisLineSegment_X *> self.thisptr).nearestTime(deref( p.thisptr ), fr, to)
+ else:
+ return (<Curve *> self.thisptr).nearestTime(deref( p.thisptr ),
+ deref( ( interval.thisptr ) ) )
+
+ def point_at(self, Coord t):
+ """Equivalent to self(t)."""
+ return wrap_Point((<AxisLineSegment_X *> self.thisptr).pointAt(t))
+
+ def value_at(self, Coord t, Dim2 d):
+ """Equivalent to self(t)[d]."""
+ return (<AxisLineSegment_X *> self.thisptr).valueAt(t, d)
+
+ def point_and_derivatives(self, Coord t, unsigned n):
+ """Return point and at least first n derivatives at point t in list."""
+ return wrap_vector_point( (<AxisLineSegment_X *> self.thisptr).pointAndDerivatives(t, n) )
+
+ def get_Y(self):
+ """Get distance of self from y-axis."""
+ return (<HLineSegment *> self.thisptr).getY()
+
+ def set_initial_X(self, Coord x):
+ """Set initial point's X coordinate."""
+ (<HLineSegment *> self.thisptr).setInitialX(x)
+
+ def set_final_X(self, Coord x):
+ """Set final point's X coordinate."""
+ (<HLineSegment *> self.thisptr).setFinalX(x)
+
+ def set_Y(self, Coord y):
+ """Set Y coordinate of points."""
+ (<HLineSegment *> self.thisptr).setY(y)
+
+ def subdivide(self, Coord t):
+ """Return two HLineSegments subdivided at t."""
+ cdef pair[HLineSegment, HLineSegment] p = (<HLineSegment *> self.thisptr).subdivide(t)
+ return (wrap_HLineSegment(p.first), wrap_HLineSegment(p.second))
+
+ def duplicate(self):
+ """Duplicate the curve."""
+ return wrap_HLineSegment( deref(<HLineSegment *> self.thisptr.duplicate()) )
+
+ def portion(self, Coord fr=0, Coord to=1, cy_Interval interval=None):
+ """Return portion of curve, specified by endpoints or interval."""
+ if interval is None:
+ return wrap_HLineSegment( deref( <HLineSegment *> self.thisptr.portion( fr, to ) ) )
+ else:
+ return wrap_HLineSegment( deref( <HLineSegment *>
+ (<Curve *> self.thisptr).portion( deref( interval.thisptr ) )
+ ) )
+
+ def reverse(self):
+ """Return curve with reversed time."""
+ return wrap_HLineSegment( deref(<HLineSegment *> self.thisptr.reverse()) )
+
+ def transformed(self, t):
+ """Transform curve by affine transform."""
+ cdef Affine at
+ if is_transform(t):
+ at = get_Affine(t)
+ return wrap_LineSegment( deref(<LineSegment *> self.thisptr.transformed( at )) )
+
+ def derivative(self):
+ """Return curve's derivative."""
+ return wrap_HLineSegment( deref(<HLineSegment *> self.thisptr.derivative()) )
+
+cdef cy_HLineSegment wrap_HLineSegment(HLineSegment p):
+ cdef HLineSegment * retp = new HLineSegment()
+ retp[0] = p
+ cdef cy_HLineSegment r = cy_HLineSegment.__new__(cy_HLineSegment)
+ r.thisptr = <BezierCurve *> retp
+ return r
+
+cdef class cy_VLineSegment(cy_LineSegment):
+
+ """Vertical line segment.
+
+ This class corresponds to HLineSegment in 2geom.
+ """
+
+ def __cinit__(self, cy_Point p0=None, cy_Point p1=cy_Point()):
+ """Create VLineSegment from it's endpoints."""
+ if p0 is None:
+ self.thisptr = <BezierCurve *> new VLineSegment()
+ else:
+ self.thisptr = <BezierCurve *> new VLineSegment( deref( p0.thisptr ), deref( p1.thisptr ) )
+
+ @classmethod
+ def from_points(cls, cy_Point p0, cy_Point p1):
+ """Create VLineSegment from it's endpoints."""
+ return wrap_VLineSegment( VLineSegment( deref(p0.thisptr),
+ deref(p1.thisptr)) )
+
+ @classmethod
+ def from_point_length(cls, cy_Point p, Coord length):
+ return wrap_VLineSegment( VLineSegment( deref( p.thisptr ), length ) )
+
+ def set_initial(self, cy_Point p):
+ """Set initial point of curve."""
+ (<AxisLineSegment_Y *> self.thisptr).setInitial( deref(p.thisptr) )
+
+ def set_final(self, cy_Point p):
+ """Set final point of curve."""
+ (<AxisLineSegment_Y *> self.thisptr).setFinal( deref(p.thisptr) )
+
+ def bounds_fast(self):
+ """Return bounding rectangle for curve.
+
+ This method is fast, but does not guarantee to give smallest
+ rectangle.
+ """
+ return wrap_Rect( (<AxisLineSegment_Y *> self.thisptr).boundsFast() )
+
+ def bounds_exact(self):
+ """Return exact bounding rectangle for curve.
+
+ This may take a while.
+ """
+ return wrap_Rect( (<AxisLineSegment_Y *> self.thisptr).boundsExact() )
+
+ def degrees_of_freedom(self):
+ """Return number of independent parameters needed to specify the curve."""
+ return (<AxisLineSegment_Y *> self.thisptr).degreesOfFreedom()
+
+ def roots(self, Coord v, Dim2 d):
+ """Find time values where self(t)[d] == v."""
+ return wrap_vector_double( (<AxisLineSegment_Y *> self.thisptr).roots(v, d) )
+
+ def nearest_time(self, cy_Point p, Coord fr=0, Coord to=1, cy_Interval interval=None):
+ """Return such t that |self(t) - point| is minimized."""
+ if interval is None:
+ return (<AxisLineSegment_Y *> self.thisptr).nearestTime(deref( p.thisptr ), fr, to)
+ else:
+ return (<Curve *> self.thisptr).nearestTime(deref( p.thisptr ),
+ deref( ( interval.thisptr ) ) )
+
+ def point_at(self, Coord t):
+ """Equivalent to self(t)."""
+ return wrap_Point((<AxisLineSegment_Y *> self.thisptr).pointAt(t))
+
+ def value_at(self, Coord t, Dim2 d):
+ """Equivalent to self(t)[d]."""
+ return (<AxisLineSegment_Y *> self.thisptr).valueAt(t, d)
+
+ def point_and_derivatives(self, Coord t, unsigned n):
+ """Return point and at least first n derivatives at point t in list."""
+ return wrap_vector_point( (<AxisLineSegment_Y *> self.thisptr).pointAndDerivatives(t, n) )
+
+ def get_X(self):
+ return (<VLineSegment *> self.thisptr).getX()
+
+ def set_initial_Y(self, Coord y):
+ (<VLineSegment *> self.thisptr).setInitialY(y)
+
+ def set_final_Y(self, Coord y):
+ (<VLineSegment *> self.thisptr).setFinalY(y)
+
+ def set_X(self, Coord x):
+ (<VLineSegment *> self.thisptr).setX(x)
+
+ def subdivide(self, Coord t):
+ """Return two HLineSegments subdivided at t."""
+ cdef pair[VLineSegment, VLineSegment] p = (<VLineSegment *> self.thisptr).subdivide(t)
+ return (wrap_VLineSegment(p.first), wrap_VLineSegment(p.second))
+
+ def duplicate(self):
+ """Duplicate the curve."""
+ return wrap_VLineSegment( deref(<VLineSegment *> self.thisptr.duplicate()) )
+
+ def portion(self, Coord fr=0, Coord to=1, cy_Interval interval=None):
+ """Return portion of curve, specified by endpoints or interval."""
+ if interval is None:
+ return wrap_VLineSegment( deref( <VLineSegment *> self.thisptr.portion( fr, to ) ) )
+ else:
+ return wrap_VLineSegment( deref( <VLineSegment *>
+ (<Curve *> self.thisptr).portion( deref( interval.thisptr ) )
+ ) )
+
+ def reverse(self):
+ """Return curve with reversed time."""
+ return wrap_VLineSegment( deref(<VLineSegment *> self.thisptr.reverse()) )
+
+ def transformed(self, t):
+ """Transform curve by affine transform."""
+ cdef Affine at
+ if is_transform(t):
+ at = get_Affine(t)
+ return wrap_LineSegment( deref(<LineSegment *> self.thisptr.transformed( at )) )
+
+ def derivative(self):
+ """Return curve's derivative."""
+ return wrap_VLineSegment( deref(<VLineSegment *> self.thisptr.derivative()) )
+
+cdef cy_VLineSegment wrap_VLineSegment(VLineSegment p):
+ cdef VLineSegment * retp = new VLineSegment()
+ retp[0] = p
+ cdef cy_VLineSegment r = cy_VLineSegment.__new__(cy_VLineSegment)
+ r.thisptr = <BezierCurve *> retp
+ return r
+
+cdef class cy_EllipticalArc:
+
+ """Elliptical arc.
+
+ Corresponds to EllipticalArc class in 2geom.
+ """
+
+ def __cinit__(self, cy_Point ip = cy_Point(0, 0),
+ Coord rx = 0,
+ Coord ry = 0,
+ Coord rot_angle = 0,
+ bint large_arc = True,
+ bint sweep = True,
+ cy_Point fp = cy_Point(0, 0)):
+ """Create Elliptical arc from it's major axis and rays."""
+ self.thisptr = new EllipticalArc(deref( ip.thisptr ), rx, ry, rot_angle, large_arc, sweep, deref( fp.thisptr ))
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ def __call__(self, Coord t):
+ """Get point at time value t."""
+ return wrap_Point( deref(<Curve *> self.thisptr)(t) )
+ #Curve methods
+
+ def length(self, Coord tolerance = 0.01):
+ """Return length of curve, within give tolerance."""
+ return (<Curve *> self.thisptr).length(tolerance)
+
+ #AngleInterval methods
+
+ def initial_angle(self):
+ """Get initial Angle of arc."""
+ return wrap_Angle((<AngleInterval *> self.thisptr).initialAngle())
+
+ def final_angle(self):
+ """Get final Angle of arc."""
+ return wrap_Angle((<AngleInterval *> self.thisptr).finalAngle())
+
+ def angle_at(self, Coord t):
+ """Get Angle from time value."""
+ return wrap_Angle((<AngleInterval *> self.thisptr).angleAt(t))
+
+ def contains(self, cy_Angle a):
+ """Test whether arc contains angle."""
+ return (<AngleInterval *> self.thisptr).contains(deref( a.thisptr ))
+
+ def extent(self):
+ """Get extent of angle interval."""
+ return (<AngleInterval *> self.thisptr).extent()
+
+ def angle_interval(self):
+ """Get underlying angle Interval."""
+ return wrap_Interval(self.thisptr.angleInterval())
+
+ def rotation_angle(self):
+ """Return rotation angle of major axis."""
+ return wrap_Angle(self.thisptr.rotationAngle())
+
+ def ray(self, Dim2 d):
+ """Access rays with X or Y."""
+ return self.thisptr.ray(d)
+
+ def rays(self):
+ """Get rays as a point."""
+ return wrap_Point(self.thisptr.rays())
+
+ def large_arc(self):
+ """Check if large arc flag is set."""
+ return self.thisptr.largeArc()
+
+ def sweep(self):
+ """Check if sweep flag is set."""
+ return self.thisptr.sweep()
+
+ def chord(self):
+ """Return chord of arc."""
+ return wrap_LineSegment(self.thisptr.chord())
+
+ def set(self, cy_Point ip, double rx, double ry, double rot_angle, bint large_arc, bint sweep, cy_Point fp):
+ """Set arc's properties."""
+ self.thisptr.set(deref( ip.thisptr ), rx, ry, rot_angle, large_arc, sweep, deref( fp.thisptr ))
+
+ def set_extremes(self, cy_Point ip, cy_Point fp):
+ """Set endpoints of arc."""
+ self.thisptr.setExtremes(deref( ip.thisptr ), deref( fp.thisptr ))
+
+ def center(self, coordinate=None):
+ """Return center of ellipse, or it's coordinate."""
+ if coordinate is None:
+ return wrap_Point(self.thisptr.center())
+ else:
+ return self.thisptr.center(int(coordinate))
+
+ def sweep_angle(self):
+ """Equivalent to self.extent()"""
+ return self.thisptr.sweepAngle()
+
+ def contains_angle(self, Coord angle):
+ """Test whether arc contains angle.
+
+ Equivalent to self.contains(Angle(a))
+ """
+ return self.thisptr.containsAngle(angle)
+
+ def point_at_angle(self, Coord a):
+ """Get point of arc at specified angle."""
+ return wrap_Point(self.thisptr.pointAtAngle(a))
+
+ def value_at_angle(self, Coord a, Dim2 d):
+ """Equivalent to self.point_at_angle(a)[d]"""
+ return self.thisptr.valueAtAngle(a, d)
+
+ def unit_circle_transform(self):
+ """Get Affine transform needed to transform unit circle to ellipse."""
+ return wrap_Affine(self.thisptr.unitCircleTransform())
+
+ def is_SVG_compliant(self):
+ """Check whether arc is SVG compliant
+
+ SVG has special specification for degenerated ellipse."""
+ return self.thisptr.isSVGCompliant()
+
+ def subdivide(self, Coord t):
+ """Return two arcs, subdivided at time t."""
+ cdef pair[EllipticalArc, EllipticalArc] r = self.thisptr.subdivide(t)
+ return (wrap_EllipticalArc(r.first), wrap_EllipticalArc(r.second))
+
+ def initial_point(self):
+ """Get self(0)."""
+ return wrap_Point(self.thisptr.initialPoint())
+
+ def final_point(self):
+ """Get self(1)."""
+ return wrap_Point(self.thisptr.finalPoint())
+
+ def duplicate(self):
+ """Duplicate the curve."""
+ return wrap_EllipticalArc( deref(<EllipticalArc *> self.thisptr.duplicate()) )
+
+ def set_initial(self, cy_Point p):
+ """Set initial point of curve."""
+ self.thisptr.setInitial(deref( p.thisptr ))
+
+ def set_final(self, cy_Point p):
+ """Set final point of curve."""
+ self.thisptr.setFinal(deref( p.thisptr ))
+
+ def is_degenerate(self):
+ """Curve is degenerate if its length is zero."""
+ return self.thisptr.isDegenerate()
+
+ def bounds_fast(self):
+ """Return bounding rectangle for curve.
+
+ This method is fast, but does not guarantee to give smallest
+ rectangle.
+ """
+ return wrap_Rect(self.thisptr.boundsFast())
+
+ def bounds_exact(self):
+ """Return exact bounding rectangle for curve.
+
+ This may take a while.
+ """
+ return wrap_Rect(self.thisptr.boundsExact())
+
+ def bounds_local(self, cy_OptInterval i, unsigned int deg):
+ """Return bounding rectangle to portion of curve."""
+ return wrap_OptRect(self.thisptr.boundsLocal(deref( i.thisptr ), deg))
+
+ def roots(self, double v, Dim2 d):
+ """Find time values where self(t)[d] == v."""
+ return wrap_vector_double(self.thisptr.roots(v, d))
+
+ def nearest_time(self, cy_Point p, Coord fr=0, Coord to=1, cy_Interval interval=None):
+ """Return such t that |self(t) - point| is minimized."""
+ if interval is None:
+ return self.thisptr.nearestTime(deref( p.thisptr ), fr, to)
+ else:
+ return (<Curve *> self.thisptr).nearestTime(deref( p.thisptr ),
+ deref( interval.thisptr ) )
+
+ def all_nearest_times(self, cy_Point p, Coord fr=0, Coord to=1, cy_Interval interval=None):
+ """Return all values of t that |self(t) - point| is minimized."""
+ if interval is None:
+ return wrap_vector_double( (<Curve *> self.thisptr).allNearestTimes(deref( p.thisptr ), fr, to))
+ else:
+ return wrap_vector_double( (<Curve *> self.thisptr).allNearestTimes(deref( p.thisptr ), deref( interval.thisptr ) ))
+
+ def degrees_of_freedom(self):
+ """Return number of independent parameters needed to specify the curve."""
+ return self.thisptr.degreesOfFreedom()
+
+ def derivative(self):
+ """Return curve's derivative."""
+ return wrap_EllipticalArc( deref(<EllipticalArc *> self.thisptr.derivative()) )
+
+ def transformed(self, cy_Affine m):
+ """Transform curve by affine transform."""
+ return wrap_EllipticalArc( deref(<EllipticalArc *> self.thisptr.transformed(deref( m.thisptr ))) )
+
+ def point_and_derivatives(self, Coord t, unsigned int n):
+ """Return point and at least first n derivatives at point t in list."""
+ return wrap_vector_point(self.thisptr.pointAndDerivatives(t, n))
+
+ def to_SBasis(self):
+ """Convert to pair of SBasis polynomials."""
+ cdef D2[SBasis] r = self.thisptr.toSBasis()
+ return ( wrap_SBasis(r[0]), wrap_SBasis(r[1]) )
+
+ def value_at(self, Coord t, Dim2 d):
+ """Equivalent to self(t)[d]."""
+ return self.thisptr.valueAt(t, d)
+
+ def point_at(self, Coord t):
+ """Equivalent to self(t)."""
+ return wrap_Point(self.thisptr.pointAt(t))
+
+
+ def portion(self, Coord fr=0, Coord to=1, cy_Interval interval=None):
+ """Return portion of curve, specified by endpoints or interval."""
+ if interval is None:
+ return wrap_EllipticalArc( deref( <EllipticalArc *> self.thisptr.portion( fr, to ) ) )
+ else:
+ return wrap_EllipticalArc( deref( <EllipticalArc *> (<Curve *> self.thisptr).portion( deref( interval.thisptr ) ) ) )
+
+ def reverse(self):
+ """Return curve with reversed time."""
+ return wrap_EllipticalArc( deref(<EllipticalArc *> self.thisptr.reverse()) )
+
+ def winding(self, cy_Point p):
+ """Return winding number around specified point."""
+ return (<Curve *> self.thisptr).winding(deref(p.thisptr))
+
+ def unit_tangent_at(self, Coord t, int n = 3):
+ """Return tangent at self(t).
+
+ Parameter n specifies how many derivatives to take into account."""
+ return wrap_Point((<Curve *> self.thisptr).unitTangentAt(t, n))
+
+cdef cy_EllipticalArc wrap_EllipticalArc(EllipticalArc p):
+ cdef EllipticalArc * retp = new EllipticalArc()
+ retp[0] = p
+ cdef cy_EllipticalArc r = cy_EllipticalArc.__new__(cy_EllipticalArc)
+ r.thisptr = retp
+ return r
+
+#TODO move somewhere else
+
+cdef object wrap_vector_interval(vector[Interval] v):
+ r = []
+ cdef unsigned int i
+ for i in range(v.size()):
+ r.append( wrap_Interval(v[i]))
+ return r
+
+
+cdef bint is_Curve(object c):
+ return any([
+ isinstance(c, cy_Curve),
+ isinstance(c, cy_SBasisCurve),
+ isinstance(c, cy_BezierCurve),
+ isinstance(c, cy_EllipticalArc)])
+
+cdef Curve * get_Curve_p(object c):
+ if isinstance(c, cy_Curve):
+ return (<cy_Curve> c).thisptr
+ elif isinstance(c, cy_SBasisCurve):
+ return <Curve *> (<cy_SBasisCurve> c).thisptr
+ elif isinstance(c, cy_BezierCurve):
+ return <Curve *> (<cy_BezierCurve> c).thisptr
+ elif isinstance(c, cy_EllipticalArc):
+ return <Curve *> (<cy_EllipticalArc> c).thisptr
+ return NULL
+
diff --git a/src/3rdparty/2geom/src/cython/_cy_path.pxd b/src/3rdparty/2geom/src/cython/_cy_path.pxd
new file mode 100644
index 0000000..2d41581
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/_cy_path.pxd
@@ -0,0 +1,124 @@
+from _common_decl cimport *
+
+from libcpp.vector cimport vector
+from libcpp.pair cimport pair
+
+from _cy_rectangle cimport Interval, OptInterval, Rect, OptRect
+from _cy_affine cimport Affine
+from _cy_curves cimport Curve, cy_Curve, wrap_Curve_p
+from _cy_curves cimport SBasis, cy_SBasis
+
+from _cy_primitives cimport Point, cy_Point, wrap_Point
+
+
+cdef extern from "2geom/d2.h" namespace "Geom":
+ cdef cppclass D2[T]:
+ D2()
+ D2(T &, T &)
+ T& operator[](unsigned i)
+
+#~ ctypedef int BaseIteratorConst "BaseIterator<ConstIterator, Path const>"
+
+cdef extern from "2geom/path.h" namespace "Geom::PathInternal":
+ cdef cppclass BaseIterator[C, P]:
+ Curve & c_item "operator*" ()
+ C & c_next "operator++" ()
+ C & c_next "operator++" (int)
+ bint operator==(BaseIterator[C, P])
+
+
+ cdef cppclass ConstIterator:
+ ConstIterator()
+ cdef cppclass Iterator:
+ Iterator()
+ ConstIterator & operator()
+
+ cdef cppclass BaseIteratorConst "Geom::PathInternal::BaseIterator<Geom::PathInternal::ConstIterator, Path const>":
+#~ Curve & c_item "operator*" ()
+ ConstIterator & c_next "operator++" ()
+ ConstIterator & c_next "operator++" (int)
+#~ bint operator==(BaseIterator[C, P])
+
+
+cdef extern from "2geom/path.h" namespace "Geom::Path":
+ cdef enum Stitching:
+ c_NO_STITCHING "Path::NO_STITCHING" = 0,
+ c_STITCH_DISCONTINUOUS "Path::STITCH_DISCONTINUOUS"
+
+cdef extern from "2geom/path.h" namespace "Geom":
+ cdef cppclass Path:
+ Path(Path &)
+ Path(Point)
+ Path(ConstIterator &, ConstIterator &, bint)
+ void swap(Path &)
+ Curve & operator[](unsigned int)
+#~ Curve & at_index(unsigned int)
+#~ ::boost::shared_ptr<Geom::Curve const> get_ref_at_index(unsigned int)
+ Curve & front()
+ Curve & back()
+ Curve & back_open()
+ Curve & back_closed()
+ Curve & back_default()
+ ConstIterator begin_const "begin" ()
+ ConstIterator end()
+ Iterator begin()
+#~ Iterator end()
+ ConstIterator end_open()
+ ConstIterator end_closed()
+ ConstIterator end_default()
+ size_t size_open()
+ size_t size_closed()
+ size_t size_default()
+ size_t size()
+ size_t max_size()
+ bint empty()
+ bint closed()
+ void close(bint)
+ OptRect boundsFast()
+ OptRect boundsExact()
+#~ Piecewise<Geom::D2<Geom::SBasis> > toPwSb()
+ bint operator==(Path &)
+ bint operator!=(Path &)
+ Path operator*(Affine &)
+#~ Path & operator*=(Affine &)
+ Point pointAt(double)
+ double valueAt(double, Dim2)
+ Point operator()(double) except +
+ vector[double] roots(double, Dim2)
+ vector[double] allNearestTimes(Point &, double, double)
+ vector[double] allNearestTimes(Point &)
+ vector[double] nearestTimePerCurve(Point &)
+ double nearestTime(Point &, double, double, double *)
+ double nearestTime(Point &, double *)
+ void appendPortionTo(Path &, double, double)
+ Path portion(double, double)
+ Path portion(Interval)
+ Path reversed()
+ void insert(Iterator &, Curve &, Stitching) except +
+ void insert(Iterator &, ConstIterator &, ConstIterator &, Stitching)
+ void clear()
+ void erase(Iterator &, Stitching)
+ void erase(Iterator &, Iterator &, Stitching)
+ void erase_last()
+ void replace(Iterator &, Curve &, Stitching)
+ void replace(Iterator &, Iterator &, Curve &, Stitching)
+ void replace(Iterator &, ConstIterator &, ConstIterator &, Stitching)
+ void replace(Iterator &, Iterator &, ConstIterator &, ConstIterator &, Stitching)
+ void start(Point)
+ Point initialPoint()
+ Point finalPoint()
+ void setInitial(Point &)
+ void setFinal(Point &)
+ void append(Curve &, Stitching)
+ void append(D2[SBasis] &, Stitching)
+ void append(Path &, Stitching)
+ void stitchTo(Point &)
+
+cdef class cy_Path:
+#~ NO_STITCHING = c_NO_STITCHING
+#~ STITCH_DISCONTINUOUS = c_STITCH_DISCONTINUOUS
+ cdef Path* thisptr
+ cdef ConstIterator _const_iterator_at_index(self, int i)
+ cdef Iterator _iterator_at_index(self, int i)
+
+cdef cy_Path wrap_Path(Path p)
diff --git a/src/3rdparty/2geom/src/cython/_cy_path.pyx b/src/3rdparty/2geom/src/cython/_cy_path.pyx
new file mode 100644
index 0000000..9f3f88e
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/_cy_path.pyx
@@ -0,0 +1,457 @@
+from cython.operator cimport dereference as deref
+from numbers import Number
+from _cy_rectangle cimport cy_OptInterval, wrap_OptInterval, wrap_Rect, OptRect, wrap_OptRect
+from _cy_rectangle cimport cy_Interval, wrap_Interval
+
+from _cy_affine cimport cy_Affine, wrap_Affine, get_Affine, is_transform
+
+from _cy_curves cimport is_Curve, get_Curve_p
+
+
+cdef class cy_Iterator:
+ cdef Iterator* thisptr
+ cdef ConstIterator* startptr
+ cdef ConstIterator* endptr
+
+ def __cinit__(self):
+ self.thisptr = new Iterator()
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ if deref(<BaseIterator[ConstIterator, Path] *> self.endptr) == deref(<BaseIterator[ConstIterator, Path] *> self.thisptr):
+ raise StopIteration
+ cdef Curve * r = <Curve *> &(<BaseIterator[Iterator, Path] * > self.thisptr).c_item()
+ (<BaseIterator[Iterator, Path] *> self.thisptr).c_next()
+ return wrap_Curve_p ( r )
+
+
+
+
+cdef cy_Iterator wrap_Iterator(Iterator i, ConstIterator starti, ConstIterator endi):
+ cdef Iterator * retp = new Iterator()
+ retp[0] = i
+ cdef cy_Iterator r = cy_Iterator.__new__(cy_Iterator)
+ r.thisptr = retp
+
+ cdef ConstIterator * endp = new ConstIterator()
+ endp[0] = endi
+ r.endptr = endp
+
+ cdef ConstIterator * startp = new ConstIterator()
+ startp[0] = starti
+ r.startptr = startp
+
+ return r
+
+cdef class cy_Path:
+
+ """Path is a ordered sequence of curves.
+
+ You can iterate this class, accessing curves one at time, or access
+ them using indices.
+
+ Two constants, NO_STITCHING and STITCH_DISCONTINUOUS are members of
+ Path namespace, and are used to specify type of stitching, if
+ necessary.
+
+ Path is either open or closed, but in both cases carries closing
+ segment, connecting last and first point.
+
+ Corresponds to Path class in 2geom.
+ """
+
+ NO_STITCHING = c_NO_STITCHING
+ STITCH_DISCONTINUOUS = c_STITCH_DISCONTINUOUS
+
+ def __cinit__(self, cy_Point p=cy_Point()):
+ """Create Path containing only one point."""
+ self.thisptr = new Path(deref( p.thisptr ))
+
+ @classmethod
+ def fromList(cls, l, Stitching stitching=NO_STITCHING, closed=False):
+ """Create path from list of curves.
+
+ Specify stithing and closed flag in additional arguments.
+ """
+ p = cy_Path()
+ for curve in l:
+ p.append_curve(curve, stitching)
+ p.close(closed)
+ return p
+
+ @classmethod
+ def fromPath(cls, cy_Path p, fr=-1, to = 1, bint closed=False):
+ """Create path copying another's path curves.
+
+ Either copy all curves, or ones from
+ fr - index of first curve copied
+ to
+ to - index of first curve not copied.
+
+ Also takes closed flag.
+ """
+ if fr == -1:
+ return wrap_Path( Path(p.thisptr.begin_const(), p.thisptr.end_default(), closed) )
+ else:
+ return wrap_Path( Path(p._const_iterator_at_index(fr), p._const_iterator_at_index(to), closed) )
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ def __getitem__(self, unsigned int i):
+ """Get curve with index i."""
+ cdef Curve * r = <Curve *> & deref(self.thisptr)[i]
+ return wrap_Curve_p(r)
+
+ def __call__(self, double t):
+ """Evaluate path at time t.
+
+ Note: t can be greater than 1 here, it can go to self.size()
+ """
+ return wrap_Point(deref( self.thisptr ) (t) )
+
+ def __richcmp__(cy_Path self, cy_Path other, int op):
+ if op == 2:
+ return deref( self.thisptr ) == deref( other.thisptr )
+ elif op == 3:
+ return deref( self.thisptr ) != deref( other.thisptr )
+
+ def __mul__(cy_Path self, m):
+ """Transform path with a transform."""
+ cdef Affine at
+ if is_transform(m):
+ at = get_Affine(m)
+ return wrap_Path( deref(self.thisptr) * at )
+
+ #This is not the fastest way, but it's pretty nice from python's perspective
+ #Anyway, I would expect that performance hit is minimal, since i is generally really small
+ cdef ConstIterator _const_iterator_at_index(self, int i):
+ cdef ConstIterator ci = self.thisptr.begin_const()
+ cdef ConstIterator * cip = &ci
+ for ii in range(i):
+ (<BaseIteratorConst *> cip).c_next()
+ return ci
+
+ cdef Iterator _iterator_at_index(self, int i):
+ cdef Iterator ci = self.thisptr.begin()
+ cdef Iterator * cip = &ci
+ for ii in range(i):
+ (<BaseIterator[Iterator, Path] *> cip).c_next()
+ return ci
+
+ def swap(self, cy_Path other):
+ """Swap curves with another path."""
+ self.thisptr.swap(deref( other.thisptr ))
+
+#This is the same as __getitem__
+#~ def at_index(self, unsigned int i):
+#~ return wrap_Curve(self.thisptr.at_index(i))
+
+ def front(self):
+ """Get first curve."""
+ #this is AFAIK the shortest way to do this
+ cdef Curve * r = <Curve *> &self.thisptr.front()
+ return wrap_Curve_p(r)
+
+ def back(self):
+ """Same as back_open."""
+ cdef Curve * r = <Curve *> &self.thisptr.back()
+ return wrap_Curve_p(r)
+
+ def back_open(self):
+ """Get last curve, treating self as open."""
+ cdef Curve * r = <Curve *> &self.thisptr.back_open()
+ return wrap_Curve_p(r)
+
+ def back_closed(self):
+ """Get last curve, treating self as closed."""
+ cdef Curve * r = <Curve *> &self.thisptr.back_closed()
+ return wrap_Curve_p(r)
+
+ def back_default(self):
+ """Get last curve."""
+ cdef Curve * r = <Curve *> &self.thisptr.back_default()
+ return wrap_Curve_p(r)
+
+ def curves(self):
+ """Same as curves_open"""
+ return wrap_Iterator(self.thisptr.begin(), self.thisptr.begin_const(), self.thisptr.end())
+
+ def curves_open(self):
+ """Return all curves as iterable, treating self as open."""
+ return wrap_Iterator(self.thisptr.begin(), self.thisptr.begin_const(), self.thisptr.end_open())
+
+ def curves_closed(self):
+ """Return all curves as iterable, treating self as closed."""
+ return wrap_Iterator(self.thisptr.begin(), self.thisptr.begin_const(), self.thisptr.end_closed())
+
+ def curves_default(self):
+ """Return all curves as iterable."""
+ return wrap_Iterator(self.thisptr.begin(), self.thisptr.begin_const(), self.thisptr.end_default())
+
+ def __iter__(self):
+ return self.curves_default()
+
+ def size_open(self):
+ """Get number of curves, treating self as open."""
+ return self.thisptr.size_open()
+
+ def size_closed(self):
+ """Get number of curves, treating self as closed."""
+ return self.thisptr.size_closed()
+
+ def size_default(self):
+ """Get number of curves."""
+ return self.thisptr.size_default()
+
+ def size(self):
+ """Same as size_open."""
+ return self.thisptr.size()
+
+#Does the same as size_open, which doesn't correspond with name.
+#~ def max_size(self):
+#~ return self.thisptr.max_size()
+
+ def empty(self):
+ """Test whether path contains no curves."""
+ return self.thisptr.empty()
+
+ def closed(self):
+ """Return state of closed flag."""
+ return self.thisptr.closed()
+
+ def close(self, bint closed):
+ """Set closed flag."""
+ self.thisptr.close(closed)
+
+ def bounds_fast(self):
+ """Return fast bounding rectangle for path.
+
+ It's not guaranteed to give the tighest bound.
+ """
+ return wrap_OptRect(self.thisptr.boundsFast())
+
+ def bounds_exact(self):
+ """Give the tighest bounding rectangle for path."""
+ return wrap_OptRect(self.thisptr.boundsExact())
+
+#~ def toPwSb(self):
+#~ return wrap_Piecewise<Geom::D2<Geom::SBasis> >(self.thisptr.toPwSb())
+
+ def point_at(self, double t):
+ """Same as self(t)."""
+ return wrap_Point(self.thisptr.pointAt(t))
+
+ def value_at(self, double t, Dim2 d):
+ """Same as self(t)[d]."""
+ return self.thisptr.valueAt(t, d)
+
+ def __call__(self, double t):
+ """Evaluate path at time t.
+
+ Equivalent to self[floor(t)](t-floor(t))
+ """
+ return wrap_Point(deref( self.thisptr ) (t) )
+
+ def roots(self, double v, Dim2 d):
+ """Find time values where self(t)[d] == v"""
+ return wrap_vector_double(self.thisptr.roots(v, d))
+
+ def all_nearest_times(self, cy_Point _point, double fr=-1, double to=1):
+ """Return all values of t that |self(t) - point| is minimized."""
+ if fr == -1:
+ return wrap_vector_double(self.thisptr.allNearestTimes(deref( _point.thisptr )))
+ return wrap_vector_double(self.thisptr.allNearestTimes(deref( _point.thisptr ), fr, to))
+
+
+ def nearest_time_per_curve(self, cy_Point _point):
+ """Find nearest points, return one time value per each curve."""
+ return wrap_vector_double(self.thisptr.nearestTimePerCurve(deref( _point.thisptr )))
+
+ def nearest_time(self, cy_Point _point, double fr=-1, double to=1):#, cy_double * distance_squared):
+ """Return such t that |self(t) - point| is minimized."""
+ if fr == -1:
+ return self.thisptr.nearestTime(deref( _point.thisptr ), NULL)
+ return self.thisptr.nearestTime(deref( _point.thisptr ), fr, to, NULL)
+
+ def nearest_time_and_dist_sq(self, cy_Point _point, double fr=-1, double to=1):
+ """Return such t that |self(t) - point| is minimized and square of that distance."""
+ cdef double t, dist
+ if fr == -1:
+ t = self.thisptr.nearestTime(deref( _point.thisptr ), &dist )
+ else:
+ t = self.thisptr.nearestTime(deref( _point.thisptr ), fr, to, &dist)
+ return (t, dist)
+
+ def append_portion_to(self, cy_Path p, double f, double t):
+ """Append portion of path to self."""
+ self.thisptr.appendPortionTo(deref( p.thisptr ), f, t)
+
+ def portion(self, Coord fr=0, Coord to=1, cy_Interval interval=None):
+ """Return portion of curve between two time values.
+
+ Alternatively use argument interval.
+ """
+ if interval is None:
+ return wrap_Path(self.thisptr.portion(fr, to))
+ else:
+ return wrap_Path(self.thisptr.portion(deref( interval.thisptr )))
+
+ def reversed(self):
+ """Return reversed curve."""
+ return wrap_Path(self.thisptr.reversed())
+
+ def insert(self, int pos, curve, Stitching stitching=NO_STITCHING):
+ """Insert curve into position pos.
+
+ Args:
+ pos: Position of inserted curve.
+ curve: Curve to insert.
+ stitching=NO_STITCHING
+ """
+ cdef Curve * cptr = get_Curve_p(curve)
+ if cptr:
+ self.thisptr.insert( self._iterator_at_index(pos), deref( cptr ), stitching )
+ else:
+ raise TypeError("passed curve is not C++ Curve")
+
+ def insert_slice(self, int pos, cy_Path p, int first, int last, Stitching stitching=NO_STITCHING):
+ """Insert curves to position pos.
+
+ Args:
+ pos: Position of inserted slice.
+ p: Path from which slice is inserted.
+ first: First inserted curve position (in p).
+ last: Fist not inserted curve position (in p).
+ stiching=NO_STITCHING
+ """
+ self.thisptr.insert(self._iterator_at_index(pos), p._const_iterator_at_index(first), p._const_iterator_at_index(last), stitching)
+
+ def clear(self):
+ """Clear all curves."""
+ self.thisptr.clear()
+
+ def erase(self, int pos, Stitching stitching=NO_STITCHING):
+ """Erase curve at position pos.
+
+ Args:
+ pos: Position of erased curve.
+ stitching=NO_STITCHING
+ """
+ self.thisptr.erase(self._iterator_at_index(pos), stitching)
+
+ def erase_slice(self, int start, int end, Stitching stitching=NO_STITCHING):
+ """Erase curves with indices [start, end).
+
+ Args:
+ start, end: Curves with indices start...end-1 are erased
+ stitching=NO_STITCHING
+ """
+ self.thisptr.erase(self._iterator_at_index(start), self._iterator_at_index(end), stitching)
+
+ def erase_last(self):
+ """Erase last curve."""
+ self.thisptr.erase_last()
+
+ def replace(self, int replaced, curve, Stitching stitching=NO_STITCHING):
+ """Replace curve at position replaced with another curve.
+
+ Args:
+ replaced: Position of replaced curve.
+ curve: New curve.
+ stitching=NO_STITCHING
+ """
+ cdef Curve * cptr = get_Curve_p(curve)
+ if cptr:
+ self.thisptr.replace(self._iterator_at_index(replaced), deref( cptr ), stitching)
+ else:
+ raise TypeError("passed curve is not C++ Curve")
+
+ def replace_slice(self, int first_replaced, int last_replaced, curve, Stitching stitching=NO_STITCHING):
+ """Replace slice of curves by new curve.
+
+ Args:
+ first_replaced, last_replace: Curves with indices
+ first_replaced ... last_replaced
+ curve: New curve.
+ stitching=NO_STITCHING
+ """
+ cdef Curve * cptr = get_Curve_p(curve)
+ if cptr:
+ self.thisptr.replace(self._iterator_at_index(first_replaced), self._iterator_at_index(last_replaced), deref( cptr ), stitching)
+ else:
+ raise TypeError("passed curve is not C++ Curve")
+
+#How to implement this nicely?
+#~ def replaceByList(self, int replaced, cy_ConstIterator first, cy_ConstIterator last, Stitching stitching):
+#~ self.thisptr.replace(deref( replaced.thisptr ), deref( first.thisptr ), deref( last.thisptr ), stitching)
+#~ def replace(self, cy_Iterator first_replaced, cy_Iterator last_replaced, cy_ConstIterator first, cy_ConstIterator last, Stitching stitching):
+#~ self.thisptr.replace(deref( first_replaced.thisptr ), deref( last_replaced.thisptr ), deref( first.thisptr ), deref( last.thisptr ), stitching)
+
+ def start(self, cy_Point p):
+ """Erase all curves and set first point."""
+ self.thisptr.start(deref( p.thisptr ))
+
+ def initial_point(self):
+ """Get initial point."""
+ return wrap_Point(self.thisptr.initialPoint())
+
+ def final_point(self):
+ """Get final point."""
+ return wrap_Point(self.thisptr.finalPoint())
+
+ def set_initial(self, cy_Point p):
+ """Set initial point."""
+ self.thisptr.setInitial(deref( p.thisptr ))
+
+ def set_final(self, cy_Point p):
+ """Set final point."""
+ self.thisptr.setFinal(deref( p.thisptr ))
+
+ def append_curve(self, curve, Stitching stitching=NO_STITCHING):
+ """Append curve to path.
+
+ Args:
+ curve: Curve to append.
+ stitching=NO_STITCHING
+ """
+ cdef Curve * cptr = get_Curve_p(curve)
+ if cptr:
+ self.thisptr.append( deref( cptr ), stitching)
+ else:
+ raise TypeError("passed curve is not C++ Curve")
+
+ def append_SBasis(self, cy_SBasis x, cy_SBasis y, Stitching stitching=NO_STITCHING):
+ """Append two SBasis functions to path.
+
+ Args:
+ x, y: SBasis functions to append.
+ stitching=NO_STITCHING
+ """
+ cdef D2[SBasis] sb = D2[SBasis]( deref(x.thisptr), deref(y.thisptr) )
+ self.thisptr.append(sb, stitching)
+
+ def append_path(self, cy_Path other, Stitching stitching=NO_STITCHING):
+ """Append another path to path.
+
+ Args:
+ other: Path to append.
+ stitching=NO_STITCHING
+ """
+ self.thisptr.append(deref( other.thisptr ), stitching)
+
+ def stitch_to(self, cy_Point p):
+ """Set last point to p, creating stitching segment to it."""
+ self.thisptr.stitchTo(deref( p.thisptr ))
+
+cdef cy_Path wrap_Path(Path p):
+ cdef Path * retp = new Path(Point())
+ retp[0] = p
+ cdef cy_Path r = cy_Path.__new__(cy_Path)
+ r.thisptr = retp
+ return r
diff --git a/src/3rdparty/2geom/src/cython/_cy_primitives.pxd b/src/3rdparty/2geom/src/cython/_cy_primitives.pxd
new file mode 100644
index 0000000..87df1c6
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/_cy_primitives.pxd
@@ -0,0 +1,237 @@
+from _common_decl cimport *
+
+
+cdef extern from "2geom/affine.h" namespace "Geom":
+ cdef cppclass Affine:
+ pass
+ cdef cppclass Translate
+ cdef cppclass Scale
+ cdef cppclass Rotate
+ cdef cppclass VShear
+ cdef cppclass HShear
+ cdef cppclass Zoom
+
+
+cdef extern from "2geom/angle.h" namespace "Geom":
+ cdef cppclass Angle:
+ Angle()
+ Angle(Coord)
+ Angle(Point)
+ Coord radians()
+ Coord radians0()
+ Coord degrees()
+ Coord degreesClock()
+
+ Coord operator()
+ Angle &operator+(Angle &)
+ Angle &operator-(Angle &)
+ bint operator==(Angle &)
+ bint operator!=(Angle &)
+
+ Coord rad_from_deg(Coord)
+ Coord deg_from_rad(Coord)
+
+cdef extern from "2geom/angle.h" namespace "Geom::Angle":
+ Angle from_radians(Coord d)
+ Angle from_degrees(Coord d)
+ Angle from_degrees_clock(Coord d)
+
+cdef class cy_Angle:
+ cdef Angle* thisptr
+
+cdef cy_Angle wrap_Angle(Angle)
+
+
+cdef extern from "2geom/angle.h" namespace "Geom":
+ cdef cppclass AngleInterval:
+ AngleInterval(AngleInterval &)
+ AngleInterval(Angle &, Angle &, bint)
+ AngleInterval(double, double, bint)
+ Angle & initialAngle()
+ Angle & finalAngle()
+ bint isDegenerate()
+ Angle angleAt(Coord)
+ Angle operator()(Coord)
+ bint contains(Angle &)
+ Coord extent()
+
+
+cdef extern from "2geom/point.h" namespace "Geom":
+ cdef cppclass Point:
+ Point()
+ Point(Coord, Coord)
+ Coord length()
+ Point ccw()
+ Point cw()
+ Coord x()
+ Coord y()
+ IntPoint round()
+ IntPoint floor()
+ IntPoint ceil()
+
+ bint isFinite()
+ bint isZero()
+ bint isNormalized(Coord)
+
+ bint operator==(Point &)
+ bint operator!=(Point &)
+ bint operator<(Point &)
+ bint operator>(Point &)
+ bint operator<=(Point &)
+ bint operator>=(Point &)
+
+ Coord &operator[](int)
+ Point operator-()
+ Point &operator+(Point &)
+ Point &operator-(Point &)
+ Point &operator*(Coord)
+ Point &operator/(Coord)
+
+ Point &operator*(Affine &)
+ Point &operator*(Translate &)
+ Point &operator*(Scale &)
+ Point &operator*(Rotate &)
+ Point &operator*(HShear &)
+ Point &operator*(VShear &)
+ Point &operator*(Zoom &)
+
+ Coord L2(Point &)
+ Coord L2sq(Point &)
+
+ bint are_near(Point &, Point &, double)
+
+ Point middle_point(Point &, Point &)
+ Point rot90(Point &)
+ Point lerp(double, Point &, Point &)
+
+ Coord dot(Point &, Point &)
+ Coord cross(Point &, Point &)
+ Coord distance (Point &, Point &)
+ Coord distanceSq (Point &, Point &)
+
+ Point unit_vector(Point &)
+ Coord L1(Point &)
+ Coord LInfty(Point &)
+ bint is_zero(Point &)
+ bint is_unit_vector(Point &)
+ double atan2(Point &)
+ double angle_between(Point &, Point &)
+ Point abs(Point &)
+ Point constrain_angle(Point &, Point &, unsigned int, Point &)
+
+cdef extern from "2geom/point.h" namespace "Geom::Point":
+ Point polar(Coord angle, Coord radius)
+
+cdef class cy_Point:
+ cdef Point* thisptr
+
+cdef cy_Point wrap_Point(Point p)
+cdef object wrap_vector_point(vector[Point] v)
+cdef vector[Point] make_vector_point(object l)
+
+
+cdef extern from "2geom/int-point.h" namespace "Geom":
+ cdef cppclass IntPoint:
+ IntPoint()
+ IntPoint(IntCoord, IntCoord)
+ IntPoint(IntPoint &)
+ IntCoord operator[](unsigned int)
+ IntCoord x()
+ IntCoord y()
+ #why doesn't IntPoint have unary -?
+ IntPoint & operator+(IntPoint &)
+ IntPoint & operator-(IntPoint &)
+ bint operator==(IntPoint &)
+ bint operator!=(IntPoint &)
+ bint operator<=(IntPoint &)
+ bint operator>=(IntPoint &)
+ bint operator>(IntPoint &)
+ bint operator<(IntPoint &)
+
+cdef class cy_IntPoint:
+ cdef IntPoint* thisptr
+
+cdef cy_IntPoint wrap_IntPoint(IntPoint p)
+
+
+cdef extern from "2geom/curve.h" namespace "Geom":
+ cdef cppclass Curve
+
+cdef extern from "2geom/bezier.h" namespace "Geom":
+ cdef cppclass LineSegment
+
+cdef extern from "2geom/line.h" namespace "Geom":
+ cdef cppclass Line:
+ Line()
+ Line(Point &, Coord)
+ Line(Point &, Point &)
+
+ Line(LineSegment &)
+ Line(Ray &)
+ Line* duplicate()
+
+ Point origin()
+ Point versor()
+ Coord angle()
+ void setOrigin(Point &)
+ void setVersor(Point &)
+ void setAngle(Coord)
+ void setPoints(Point &, Point &)
+ void setCoefficients(double, double, double)
+ bint isDegenerate()
+ Point pointAt(Coord)
+ Coord valueAt(Coord, Dim2)
+ Coord timeAt(Point &)
+ Coord timeAtProjection(Point &)
+ Coord nearestTime(Point &)
+ vector[Coord] roots(Coord, Dim2)
+ Line reverse()
+ Curve* portion(Coord, Coord)
+ LineSegment segment(Coord, Coord)
+ Ray ray(Coord)
+ Line derivative()
+ Line transformed(Affine &)
+ Point normal()
+ Point normalAndDist(double &)
+
+ double distance(Point &, Line &)
+ bint are_near(Point &, Line &, double)
+ bint are_parallel(Line &, Line &, double)
+ bint are_same(Line &, Line &, double)
+ bint are_orthogonal(Line &, Line &, double)
+ bint are_collinear(Point &, Point &, Point &, double)
+
+ double angle_between(Line &, Line &)
+ double distance(Point &, LineSegment &)
+
+cdef extern from "2geom/line.h" namespace "Geom::Line":
+ Line from_origin_and_versor(Point, Point)
+ Line from_normal_distance(Point, double)
+
+
+cdef extern from "2geom/ray.h" namespace "Geom":
+ cdef cppclass Ray:
+ Ray()
+ Ray(Point &, Coord)
+ Ray(Point&, Point &)
+ Point origin()
+ Point versor()
+ void setOrigin(Point &)
+ void setVersor(Point &)
+ void setAngle(Coord)
+ Coord angle()
+ void setPoints(Point &, Point &)
+ bint isDegenerate()
+ Point pointAt(Coord)
+ Coord valueAt(Coord, Dim2)
+ vector[Coord] roots(Coord, Dim2)
+ Coord nearestTime(Point &)
+ Ray reverse()
+ Curve *portion(Coord, Coord)
+ LineSegment segment(Coord, Coord)
+ Ray transformed(Affine &)
+ double distance(Point &, Ray &)
+ bint are_near(Point &, Ray &, double)
+ bint are_same(Ray&, Ray &, double)
+ double angle_between(Ray &, Ray &, bint)
+ Ray make_angle_bisector_ray(Ray &, Ray&)
diff --git a/src/3rdparty/2geom/src/cython/_cy_primitives.pyx b/src/3rdparty/2geom/src/cython/_cy_primitives.pyx
new file mode 100644
index 0000000..62f7f41
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/_cy_primitives.pyx
@@ -0,0 +1,846 @@
+from numbers import Number
+
+from _common_decl cimport *
+from cython.operator cimport dereference as deref
+
+from _cy_affine cimport cy_Translate, cy_Rotate, cy_Scale
+from _cy_affine cimport cy_VShear, cy_HShear, cy_Zoom
+from _cy_affine cimport cy_Affine, get_Affine, is_transform
+
+from _cy_curves cimport cy_Curve, wrap_Curve_p
+from _cy_curves cimport cy_LineSegment, wrap_LineSegment
+
+cdef class cy_Angle:
+
+ """Class representig angle.
+
+ Angles can be tested for equality, but they are not ordered.
+
+ Corresponds to Angle class in 2geom. Most members are direct
+ calls to Angle methods, otherwise C++ call is specified.
+ """
+
+ def __cinit__(self, double x):
+ """Create new angle from value in radians."""
+ self.thisptr = new Angle(x)
+
+ def __repr__(self):
+ """repr(self)"""
+ return "Angle({0:2.f})".format(self.radians())
+
+ def __str__(self):
+ """str(self)"""
+ return "{0:.2f} radians".format(self.radians())
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ @classmethod
+ def from_radians(cls, rad):
+ """Construnct angle from radians."""
+ return wrap_Angle(from_radians(rad))
+
+ @classmethod
+ def from_degrees(cls, d):
+ """Construnct angle from degrees."""
+ return wrap_Angle(from_degrees(d))
+
+ @classmethod
+ def from_degrees_clock(cls, d):
+ """Construnct angle from degrees in clock convention."""
+ return wrap_Angle(from_degrees_clock(d))
+
+ @classmethod
+ def from_Point(cls, cy_Point p):
+ """Construct angle from Point. Calls Angle(Point) in 2geom."""
+ cdef Point * pp = p.thisptr
+ return wrap_Angle( Angle( deref(p.thisptr) ))
+
+ def __float__(self):
+ """float(self)"""
+ return <Coord> deref(self.thisptr)
+
+ def __add__(cy_Angle self, cy_Angle other):
+ """alpha + beta"""
+ return wrap_Angle(deref(other.thisptr) + deref(self.thisptr))
+
+ def __sub__(cy_Angle self, cy_Angle other):
+ """alpha - beta"""
+ return wrap_Angle(deref(other.thisptr) - deref(self.thisptr))
+
+ def __richcmp__(cy_Angle self, cy_Angle other, int op):
+ """Test equality of angles. Note: angles are not ordered."""
+ if op == 2:
+ return deref(other.thisptr) == deref(self.thisptr)
+ elif op == 3:
+ return deref(other.thisptr) != deref(self.thisptr)
+ return NotImplemented
+
+ def radians(self):
+ """Return the angle in radians."""
+ return self.thisptr.radians()
+
+ def radians0(self):
+ """Return the angle in positive radians."""
+ return self.thisptr.radians0()
+
+ def degrees(self):
+ """Return the angle in degrees."""
+ return self.thisptr.degrees()
+
+ def degrees_clock(self):
+ """Return the angle in clock convention. Calls degreesClock() in 2geom."""
+ return self.thisptr.degreesClock()
+
+ @classmethod
+ def rad_from_deg(cls, deg):
+ """Convert degrees to radians."""
+ return rad_from_deg(deg)
+
+ @classmethod
+ def deg_from_rad(cls, rad):
+ """Convert radians to degrees."""
+ return deg_from_rad(rad)
+
+cdef cy_Angle wrap_Angle(Angle p):
+ cdef Angle * retp = new Angle()
+ retp[0] = p
+ cdef cy_Angle r = cy_Angle.__new__(cy_Angle, 0)
+ r.thisptr = retp
+ return r
+
+
+cdef class cy_AngleInterval:
+
+ """ Class representing interval of angles.
+
+ Corresponds to AngleInterval class in 2geom. Most members are direct
+ calls to AngleInterval methods, otherwise C++ call is specified.
+ """
+
+ cdef AngleInterval* thisptr
+
+ def __cinit__(self, start, end, bint cw=False):
+ """Create AngleInterval from starting and ending value.
+
+ Optional argument cw specifies direction - counter-clockwise
+ is default.
+ """
+ self.thisptr = new AngleInterval(float(start), float(end), cw)
+
+ def __call__(self, Coord t):
+ """A(t), maps unit interval to Angle."""
+ return wrap_Angle(deref( self.thisptr ) (t))
+
+ def initial_angle(self):
+ """Return initial angle as Angle instance."""
+ return wrap_Angle(self.thisptr.initialAngle())
+
+ def final_angle(self):
+ """Return final angle as Angle instance."""
+ return wrap_Angle(self.thisptr.finalAngle())
+
+ def is_degenerate(self):
+ """Test for empty interval."""
+ return self.thisptr.isDegenerate()
+
+ def angle_at(self, Coord t):
+ """A.angle_at(t) <==> A(t)"""
+ return wrap_Angle(self.thisptr.angleAt(t))
+
+ def contains(self, cy_Angle a):
+ """Test whether interval contains Angle."""
+ return self.thisptr.contains(deref( a.thisptr ))
+
+ def extent(self):
+ """Calculate interval's extent."""
+ return self.thisptr.extent()
+
+cdef cy_AngleInterval wrap_AngleInterval(AngleInterval p):
+ cdef AngleInterval * retp = new AngleInterval(0, 0, 0)
+ retp[0] = p
+ cdef cy_AngleInterval r = cy_AngleInterval.__new__(cy_AngleInterval)
+ r.thisptr = retp
+ return r
+
+
+cdef class cy_Point:
+
+ """Represents point or vector in 2D plane.
+
+ Points are ordered lexicographically, with y coordinate being
+ more significant.
+
+ Corresponds to Point class in 2geom. Most members are direct
+ calls to Point methods, otherwise C++ call is specified.
+ """
+
+ def __cinit__(self, double x=0.0, double y=0.0):
+ """Create Point from it's cartesian coordinates."""
+ self.thisptr = new Point(x, y)
+
+ def __repr__(self):
+ """repr(self)"""
+ return "Point ({0:.3f}, {1:.3f})".format(self[0], self[1])
+
+ def __str__(self):
+ """str(self)"""
+ return "[{0:.3f}, {1:.3f}]".format(self[0], self[1])
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ @classmethod
+ def polar(cls, Coord angle, Coord radius = 1.0):
+ """Create Point from polar coordinates."""
+ return wrap_Point(polar(angle, radius))
+
+ def length(self):
+ """Return distance from origin or length of vector."""
+ return self.thisptr.length()
+
+ def ccw(self):
+ """Return point rotated counter-clockwise."""
+ return wrap_Point(self.thisptr.ccw())
+
+ def cw(self):
+ """Return point rotated clockwise."""
+ return wrap_Point(self.thisptr.cw())
+
+ def __getitem__(self, key):
+ """Access coordinates of point."""
+ return deref(self.thisptr)[key]
+
+ @property
+ def x(self):
+ """First coordinate of point."""
+ return self.thisptr.x()
+
+ @property
+ def y(self):
+ """Second coordinate of point."""
+ return self.thisptr.y()
+
+ def round(self):
+ """Create IntPoint rounding coordinates."""
+ return wrap_IntPoint(self.thisptr.round())
+
+ def floor(self):
+ """Create IntPoint flooring coordinates."""
+ return wrap_IntPoint(self.thisptr.floor())
+
+ def ceil(self):
+ """Create IntPoint ceiling coordinates."""
+ return wrap_IntPoint(self.thisptr.ceil())
+
+ def __neg__(self):
+ """-P"""
+ return(wrap_Point(-deref(self.thisptr)))
+
+ def __abs__(self):
+ """abs(P)"""
+ return self.length()
+
+ def __add__(cy_Point self, cy_Point other):
+ """P + Q"""
+ return wrap_Point(deref(self.thisptr) + deref(other.thisptr))
+
+ def __sub__(cy_Point self, cy_Point other):
+ """P - Q"""
+ return wrap_Point(deref(self.thisptr) - deref(other.thisptr))
+
+ #TODO exceptions
+ def __mul__(cy_Point self, s):
+ """Multiply point by number or Affine transform."""
+ if isinstance(s, Number):
+ return wrap_Point(deref(self.thisptr)* (<Coord> float(s)))
+ elif isinstance(s, cy_Affine):
+ return wrap_Point( deref(self.thisptr) * <Affine &> deref( (<cy_Affine> s).thisptr ) )
+ elif isinstance(s, cy_Translate):
+ return wrap_Point( deref(self.thisptr) * <Translate &> deref( (<cy_Translate> s).thisptr ) )
+ elif isinstance(s, cy_Scale):
+ return wrap_Point( deref(self.thisptr) * <Scale &> deref( (<cy_Scale> s).thisptr ) )
+ elif isinstance(s, cy_Rotate):
+ return wrap_Point( deref(self.thisptr) * <Rotate &> deref( (<cy_Rotate> s).thisptr ) )
+ elif isinstance(s, cy_HShear):
+ return wrap_Point( deref(self.thisptr) * <HShear &> deref( (<cy_HShear> s).thisptr ) )
+ elif isinstance(s, cy_VShear):
+ return wrap_Point( deref(self.thisptr) * <VShear &> deref( (<cy_VShear> s).thisptr ) )
+ elif isinstance(s, cy_Zoom):
+ return wrap_Point( deref(self.thisptr) * <Zoom &> deref( (<cy_Zoom> s).thisptr ) )
+ return NotImplemented
+
+ def __div__(cy_Point self, Coord s):
+ """P / s"""
+ return wrap_Point(deref(self.thisptr)/s)
+
+ def __richcmp__(cy_Point self, cy_Point other, int op):
+ if op == 0:
+ return deref(self.thisptr) < deref(other.thisptr)
+ if op == 1:
+ return deref(self.thisptr) <= deref(other.thisptr)
+ if op == 2:
+ return deref(self.thisptr) == deref(other.thisptr)
+ if op == 3:
+ return deref(self.thisptr) != deref(other.thisptr)
+ if op == 4:
+ return deref(self.thisptr) > deref(other.thisptr)
+ if op == 5:
+ return deref(self.thisptr) >= deref(other.thisptr)
+
+ def isFinite(self):
+ """Test whether point is finite."""
+ return self.thisptr.isFinite()
+
+ def isZero(self):
+ """Test whether point is origin"""
+ return self.thisptr.isZero()
+
+ def isNormalized(self, eps=EPSILON):
+ """Test whether point's norm is close to 1."""
+ return self.thisptr.isNormalized(eps)
+
+ @classmethod
+ def L2(cls, cy_Point p):
+ """Compute L2 (Euclidean) norm of point.
+
+ L2(P) = sqrt( P.x**2 + P.y**2 )
+ """
+ return L2(deref(p.thisptr))
+
+ @classmethod
+ def L2sq(cls, cy_Point p):
+ """Compute square of L2 (Euclidean) norm."""
+ return L2sq(deref(p.thisptr))
+
+ @classmethod
+ def are_near(cls, cy_Point a, cy_Point b, double eps=EPSILON):
+ """Test if two points are close."""
+ return are_near(deref(a.thisptr), deref(b.thisptr), eps)
+
+ @classmethod
+ def middle_point(cls, cy_Point a, cy_Point b):
+ """Return point between two points."""
+ return wrap_Point(middle_point(deref(a.thisptr), deref(b.thisptr)))
+
+ @classmethod
+ def rot90(cls, cy_Point a):
+ """Rotate point by 90 degrees."""
+ return wrap_Point(rot90(deref(a.thisptr)))
+
+ @classmethod
+ def lerp(cls, double t, cy_Point a, cy_Point b):
+ """Linearly interpolate between too points."""
+ return wrap_Point(lerp(t, deref(a.thisptr), deref(b.thisptr)))
+
+ @classmethod
+ def dot(cls, cy_Point a, cy_Point b):
+ """Calculate dot product of two points."""
+ return dot(deref(a.thisptr), deref(b.thisptr))
+
+ @classmethod
+ def cross(cls, cy_Point a, cy_Point b):
+ """Calculate (z-coordinate of) cross product of two points."""
+ return cross(deref(a.thisptr), deref(b.thisptr))
+
+ @classmethod
+ def distance(cls, cy_Point a, cy_Point b):
+ """Compute distance between two points."""
+ return distance(deref(a.thisptr), deref(b.thisptr))
+
+ @classmethod
+ def distanceSq(cls, cy_Point a, cy_Point b):
+ """Compute square of distance between two points."""
+ return distanceSq(deref(a.thisptr), deref(b.thisptr))
+
+ @classmethod
+ def unit_vector(cls, cy_Point p):
+ """Normalise point."""
+ return wrap_Point(unit_vector(deref(p.thisptr)))
+
+ @classmethod
+ def L1(cls, cy_Point p):
+ """Compute L1 (Manhattan) norm of a point.
+
+ L1(P) = |P.x| + |P.y|
+ """
+ return L1(deref(p.thisptr))
+
+ @classmethod
+ def LInfty(cls, cy_Point p):
+ """Compute Infinity norm of a point.
+
+ LInfty(P) = max(|P.x|, |P.y|)
+ """
+ return LInfty(deref(p.thisptr))
+
+ @classmethod
+ def is_zero(cls, cy_Point p):
+ """Test whether point is origin."""
+ return is_zero(deref(p.thisptr))
+
+ @classmethod
+ def is_unit_vector(cls, cy_Point p):
+ """Test whether point's length equal 1."""
+ return is_unit_vector(deref(p.thisptr))
+
+ @classmethod
+ def atan2(cls, cy_Point p):
+ """Return angle between point and x-axis."""
+ return atan2(deref(p.thisptr))
+
+ @classmethod
+ def angle_between(cls, cy_Point a, cy_Point b):
+ """Return angle between two point."""
+ return angle_between(deref(a.thisptr), deref(b.thisptr))
+
+ @classmethod
+ def abs(cls, cy_Point p):
+ """Return length of a point."""
+ return wrap_Point(abs(deref(p.thisptr)))
+
+ @classmethod
+ def constrain_angle(cls, cy_Point a, cy_Point b, unsigned int n, cy_Point direction):
+ """Rotate B around A to have specified angle wrt. direction."""
+ return wrap_Point(constrain_angle(deref(a.thisptr), deref(b.thisptr), n, deref(direction.thisptr)))
+
+cdef cy_Point wrap_Point(Point p):
+ cdef Point * retp = new Point()
+ retp[0] = p
+ cdef cy_Point r = cy_Point.__new__(cy_Point)
+ r.thisptr = retp
+ return r
+
+cdef object wrap_vector_point(vector[Point] v):
+ r = []
+ cdef unsigned int i
+ for i in range(v.size()):
+ r.append( wrap_Point(v[i]) )
+ return r
+
+cdef vector[Point] make_vector_point(object l):
+ cdef vector[Point] ret
+ for i in l:
+ ret.push_back( deref( (<cy_Point> i).thisptr ) )
+ return ret
+
+
+cdef class cy_IntPoint:
+
+ """Represents point with integer coordinates
+
+ IntPoints are ordered lexicographically, with y coordinate being
+ more significant.
+
+ Corresponds to IntPoint class in 2geom. Most members are direct
+ calls to IntPoint methods, otherwise C++ call is specified.
+ """
+
+ def __init__(self, IntCoord x = 0, IntCoord y = 0):
+ """Create new IntPoint from it's cartesian coordinates."""
+ self.thisptr = new IntPoint(x ,y)
+
+ def __getitem__(self, key):
+ """Get coordinates of IntPoint."""
+ return deref(self.thisptr)[key]
+
+ def __repr__(self):
+ """repr(self)"""
+ return "IntPoint ({0}, {1})".format(self[0], self[1])
+
+ def __str__(self):
+ """str(self)"""
+ return "[{0}, {1}]".format(self[0], self[1])
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ @property
+ def x(self):
+ """First coordinate of IntPoint."""
+ return self.thisptr.x()
+
+ @property
+ def y(self):
+ """Second coordinate of IntPoint."""
+ return self.thisptr.y()
+
+ def __add__(cy_IntPoint self, cy_IntPoint o):
+ """P + Q"""
+ return wrap_IntPoint(deref(self.thisptr)+deref( o.thisptr ))
+
+ def __sub__(cy_IntPoint self, cy_IntPoint o):
+ """P - Q"""
+ return wrap_IntPoint(deref(self.thisptr)-deref( o.thisptr ))
+
+ def __richcmp__(cy_IntPoint self, cy_IntPoint other, int op):
+ if op == 0:
+ return deref(self.thisptr) < deref(other.thisptr)
+ if op == 1:
+ return deref(self.thisptr) <= deref(other.thisptr)
+ if op == 2:
+ return deref(self.thisptr) == deref(other.thisptr)
+ if op == 3:
+ return deref(self.thisptr) != deref(other.thisptr)
+ if op == 4:
+ return deref(self.thisptr) > deref(other.thisptr)
+ if op == 5:
+ return deref(self.thisptr) >= deref(other.thisptr)
+
+cdef cy_IntPoint wrap_IntPoint(IntPoint p):
+ cdef IntPoint * retp = new IntPoint()
+ retp[0] = p
+ cdef cy_IntPoint r = cy_IntPoint.__new__(cy_IntPoint)
+ r.thisptr = retp
+ return r
+
+
+cdef class cy_Line:
+
+ """Class representing line in plane.
+
+ Corresponds to Line class in 2geom. Most members are direct
+ calls to Line methods, otherwise C++ call is specified.
+ """
+
+ cdef Line* thisptr
+
+ def __cinit__(self, cy_Point cp = None, double x = 0):
+ """Create Line from point and angle to x-axis.
+
+ Constructor with no arguments calls Line() in 2geom, otherwise
+ Line(Point &, double) is called.
+ """
+ if cp is None:
+ self.thisptr = new Line()
+ else:
+ self.thisptr = new Line( deref(cp.thisptr), x)
+
+ def __repr__(self):
+ """repr(self)."""
+ return "Line({0}, {1:3f})".format(repr(self.origin()), self.angle())
+
+ def __str__(self):
+ """str(self)"""
+ return repr(self)
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ @classmethod
+ def from_points(cls, cy_Point cp, cy_Point cq):
+ """Create Line passing through two points.
+
+ Calls Line(Point &, Point &) in 2geom.
+ """
+ return wrap_Line( Line( deref(cp.thisptr), deref(cq.thisptr) ) )
+
+ @classmethod
+ def from_origin_and_versor(cls, cy_Point o, cy_Point v):
+ """Create Line passing through point with specified versor."""
+ return wrap_Line( from_origin_and_versor(deref(o.thisptr), deref(v.thisptr)) )
+
+ @classmethod
+ def from_normal_distance(cls, cy_Point normal, double dist):
+ """Create Line from it's normal and distance from origin."""
+ return wrap_Line( from_normal_distance( deref(normal.thisptr), dist ) )
+
+ @classmethod
+ def from_LineSegment(cls, cy_LineSegment LS):
+ """Create Line from LineSegment.
+
+ Calls Line(LineSegment &) in 2geom.
+ """
+ return wrap_Line( Line( deref(<LineSegment *> LS.thisptr) ) )
+
+ @classmethod
+ def from_Ray(cls, cy_Ray R):
+ """Create Line from Ray.
+
+ Calls Line(Ray &) in 2geom.
+ """
+ return wrap_Line( Line( deref(R.thisptr) ) )
+
+ #maybe implement as properties.
+
+ def origin(self):
+ """Return origin of line."""
+ return wrap_Point(self.thisptr.origin())
+
+ def versor(self):
+ """Return versor of line."""
+ return wrap_Point(self.thisptr.versor())
+
+ def angle(self):
+ """Return angle between line and x-axis."""
+ return self.thisptr.angle()
+
+ def set_origin(self, cy_Point origin):
+ """Set origin."""
+ self.thisptr.setOrigin( deref(origin.thisptr) )
+
+ def set_versor(self, cy_Point versor):
+ """Set versor."""
+ self.thisptr.setVersor( deref(versor.thisptr) )
+
+ def set_angle(self, Coord a):
+ """Set angle."""
+ self.thisptr.setAngle(a)
+
+ def set_points(self, cy_Point cp, cy_Point cq):
+ """Set two points line passes through."""
+ self.thisptr.setPoints( deref(cp.thisptr), deref(cq.thisptr) )
+
+ def set_coefficients(self, a, b, c):
+ """Set coefficients in parametric equation of line."""
+ self.thisptr.setCoefficients(a, b, c)
+
+ def is_degenerate(self):
+ """Test whether line's versor is zero vector."""
+ return self.thisptr.isDegenerate()
+
+ def point_at(self, t):
+ """origin + t*versor"""
+ return wrap_Point(self.thisptr.pointAt(t))
+
+ def value_at(self, t, Dim2 d):
+ """Coordinates of point_at(t)."""
+ return self.thisptr.valueAt(t, d)
+
+ def time_at(self, cy_Point cp):
+ """Find time value corresponding to point on line."""
+ return self.thisptr.timeAt( deref(cp.thisptr) )
+
+ def time_at_projection(self, cy_Point cp):
+ """Find time value corresponding to orthogonal projection of point."""
+ return self.thisptr.timeAtProjection( deref(cp.thisptr) )
+
+ def nearest_time(self, cy_Point cp):
+ """Alias for time_at_projection."""
+ return self.thisptr.nearestTime( deref(cp.thisptr) )
+
+ def roots(self, Coord v, Dim2 d):
+ """Return time values where self.value_at(t, dim) == v."""
+ return wrap_vector_double( self.thisptr.roots(v, d) )
+
+ def reverse(self):
+ """Reverse line."""
+ return wrap_Line( self.thisptr.reverse() )
+
+ def derivative(self):
+ """Take line's derivative."""
+ return wrap_Line( self.thisptr.derivative() )
+
+ def normal(self):
+ """Return line's normal."""
+ return wrap_Point( self.thisptr.normal() )
+
+ def normal_and_dist(self):
+ """return tuple containing normal vector and distance from origin.
+
+ Calls normal_and_dist(x) and return it's result and x as a tuple.
+ """
+ cdef double x = 0
+ cdef Point p = self.thisptr.normalAndDist(x)
+ return (wrap_Point(p), x)
+
+ def portion(self, Coord f, Coord t):
+ """Return Curve corresponding to portion of line."""
+ return wrap_Curve_p( self.thisptr.portion(f, t) )
+
+ def ray(self, Coord t):
+ """Return Ray continuing from time value t."""
+ return wrap_Ray( self.thisptr.ray(t) )
+
+ def segment(self, Coord f, Coord t):
+ """Return LineSegment corresponding to portion of line."""
+ return wrap_LineSegment( self.thisptr.segment(f, t) )
+
+ def transformed(self, t):
+ """Return line transformed by transform."""
+ #doing this because transformed(t) takes reference
+ cdef Affine at
+ if is_transform(t):
+ at = get_Affine(t)
+ return wrap_Line(self.thisptr.transformed( at ))
+
+ @classmethod
+ def distance(cls, cy_Point cp, cy_Line cl):
+ """Calculate distance between point and line."""
+ return distance( deref(cp.thisptr), deref(cl.thisptr))
+
+ @classmethod
+ def are_near(cls, cy_Point cp, cy_Line cl, double eps=EPSILON):
+ """Test if point is near line."""
+ return are_near( deref(cp.thisptr), deref(cl.thisptr), eps)
+
+ @classmethod
+ def are_parallel(cls, cy_Line cl, cy_Line ck, eps=EPSILON):
+ """Test if lines are almost parallel."""
+ return are_parallel( deref(cl.thisptr), deref(ck.thisptr), eps)
+
+ @classmethod
+ def are_same(cls, cy_Line cl, cy_Line ck, double eps=EPSILON):
+ """Test if lines represent the same line."""
+ return are_same( deref(cl.thisptr), deref(ck.thisptr), eps)
+
+ @classmethod
+ def are_orthogonal(cls, cy_Line cl, cy_Line ck, eps=EPSILON):
+ """Test two lines for orthogonality."""
+ return are_orthogonal( deref(cl.thisptr), deref(ck.thisptr), eps)
+
+ @classmethod
+ def are_collinear(cls, cy_Point cp, cy_Point cq, cy_Point cr, eps=EPSILON):
+ """Test for collinearity of vectors (cq-cp) and (cr-cp)"""
+ return are_collinear( deref(cp.thisptr), deref(cq.thisptr), deref(cr.thisptr), eps)
+
+ @classmethod
+ def angle_between(cls, cy_Line cl, cy_Line ck):
+ """Calculate angle between two lines"""
+ return angle_between( deref(cl.thisptr), deref(ck.thisptr) )
+
+cdef cy_Line wrap_Line(Line p):
+ cdef Line * retp = new Line()
+ retp[0] = p
+ cdef cy_Line r = cy_Line.__new__(cy_Line)
+ r.thisptr = retp
+ return r
+
+#-- Ray --
+
+cdef class cy_Ray:
+
+ """Ray represents half of line, starting at origin and going to
+ infinity.
+
+ Corresponds to Ray class in 2geom. Most members are direct
+ calls to Ray methods, otherwise C++ call is specified.
+ """
+
+ cdef Ray* thisptr
+
+ def __cinit__(self, cy_Point cp = None, double x = 0):
+ """Create Ray from origin and angle with x-axis.
+
+ Empty constructor calls Ray() in 2geom.
+ """
+ if cp is None:
+ self.thisptr = new Ray()
+ else:
+ self.thisptr = new Ray( deref(cp.thisptr), x)
+
+ def __repr__(self):
+ """repr(self)."""
+ return "Ray({0}, {1:3f})".format(repr(self.origin()), self.angle())
+
+ def __str__(self):
+ """str(self)"""
+ return repr(self)
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ @classmethod
+ def from_points(cls, cy_Point cp, cy_Point cq):
+ """Create ray passing through two points, starting at first one."""
+ return wrap_Ray( (Ray( deref(cp.thisptr), deref(cq.thisptr) )) )
+
+ def origin(self):
+ """Return origin."""
+ return wrap_Point(self.thisptr.origin())
+
+ def versor(self):
+ """Return versor."""
+ return wrap_Point(self.thisptr.versor())
+
+ def angle(self):
+ """Return angle between ray and x-axis."""
+ return self.thisptr.angle()
+
+ def set_origin(self, cy_Point cp):
+ """Set origin."""
+ self.thisptr.setOrigin( deref(cp.thisptr) )
+
+ def set_versor(self, cy_Point cp):
+ """Set versor."""
+ self.thisptr.setVersor( deref(cp.thisptr) )
+
+ def set_angle(self, Coord a):
+ """Set angle."""
+ self.thisptr.setAngle(a)
+
+ def set_points(self, cy_Point cp, cy_Point cq):
+ """Set origin and second point of ray."""
+ self.thisptr.setPoints( deref(cp.thisptr), deref(cq.thisptr) )
+
+ def is_degenerate(self):
+ """Check for zero versor."""
+ return self.thisptr.isDegenerate()
+
+ def point_at(self, t):
+ """origin + t * versor"""
+ return wrap_Point(self.thisptr.pointAt(t))
+ def value_at(self, t, Dim2 d):
+ """Access coordinates of point_at(t)."""
+ return self.thisptr.valueAt(t, d)
+
+ def nearest_time(self, cy_Point cp):
+ """Get time value of nearest point of ray."""
+ return self.thisptr.nearestTime( deref(cp.thisptr) )
+ def reverse(self):
+ """Reverse the ray."""
+ return wrap_Ray( self.thisptr.reverse() )
+
+ def roots(self, Coord v, Dim2 d):
+ """Return time values for which self.value_at(t, d) == v."""
+ return wrap_vector_double( self.thisptr.roots(v, d) )
+
+ def transformed(self, t):
+ """Return ray transformed by affine transform."""
+ cdef Affine at
+ if is_transform(t):
+ at = get_Affine(t)
+ return wrap_Ray(self.thisptr.transformed( at ))
+
+ def portion(self, Coord f, Coord t):
+ """Return Curve corresponding to portion of ray."""
+ return wrap_Curve_p( self.thisptr.portion(f, t) )
+
+ def segment(self, Coord f, Coord t):
+ """Return LineSegment corresponding to portion of ray."""
+ return wrap_LineSegment( self.thisptr.segment(f, t) )
+
+ @classmethod
+ def distance(cls, cy_Point cp, cy_Ray cl):
+ """Compute distance between point and ray."""
+ return distance( deref(cp.thisptr), deref(cl.thisptr))
+
+ @classmethod
+ def are_near(cls, cy_Point cp, cy_Ray cl, double eps=EPSILON):
+ """Check if distance between point and ray is small."""
+ return are_near( deref(cp.thisptr), deref(cl.thisptr), eps)
+
+ @classmethod
+ def are_same(cls, cy_Ray cl, cy_Ray ck, double eps=EPSILON):
+ """Check if two ray are same."""
+ return are_same( deref(cl.thisptr), deref(ck.thisptr), eps)
+
+ @classmethod
+ def angle_between(cls, cy_Ray cl, cy_Ray ck, bint cw=True):
+ """Compute angle between two rays.
+
+ Can specify direction using parameter cw.
+ """
+ return angle_between( deref(cl.thisptr), deref(ck.thisptr), cw)
+
+ @classmethod
+ def make_angle_bisector_ray(cls, cy_Ray cl, cy_Ray ck):
+ """Make ray bisecting smaller angle formed by two rays."""
+ return wrap_Ray( make_angle_bisector_ray(deref(cl.thisptr), deref(ck.thisptr) ))
+
+cdef cy_Ray wrap_Ray(Ray p):
+ cdef Ray * retp = new Ray()
+ retp[0] = p
+ cdef cy_Ray r = cy_Ray.__new__(cy_Ray)
+ r.thisptr = retp
+ return r
diff --git a/src/3rdparty/2geom/src/cython/_cy_rectangle.pxd b/src/3rdparty/2geom/src/cython/_cy_rectangle.pxd
new file mode 100644
index 0000000..ac18169
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/_cy_rectangle.pxd
@@ -0,0 +1,442 @@
+from _common_decl cimport *
+from cpython.ref cimport PyObject
+
+from _cy_primitives cimport Point, cy_Point, wrap_Point
+from _cy_primitives cimport IntPoint, cy_IntPoint, wrap_IntPoint
+
+cdef extern from "2geom/affine.h" namespace "Geom":
+ cdef cppclass Affine:
+ pass
+
+cdef extern from "2geom/cython-bindings/wrapped-pyobject.h" namespace "Geom":
+
+ cdef cppclass WrappedPyObject:
+ WrappedPyObject()
+ WrappedPyObject(object)
+ object getObj()
+
+ cdef cppclass PyPoint:
+ PyPoint()
+ PyPoint(WrappedPyObject, WrappedPyObject)
+ WrappedPyObject operator[](int)
+
+
+cdef extern from "2geom/generic-interval.h" namespace "Geom":
+
+ cdef cppclass GenericInterval[C]:
+
+ GenericInterval()
+ GenericInterval(C)
+ GenericInterval(C, C)
+
+ C min()
+ C max()
+ C extent()
+ C middle()
+
+ bint isSingular()
+ bint contains(C)
+ bint contains(GenericInterval[C] &)
+ bint intersects(GenericInterval[C] &)
+
+ void setMin(C)
+ void setMax(C)
+ void expandTo(C)
+ void expandBy(C)
+ void unionWith(GenericInterval[C] &)
+
+ GenericInterval[C] &operator+(C)
+ GenericInterval[C] &operator-(C)
+ GenericInterval[C] &operator-()
+ GenericInterval[C] &operator+(GenericInterval[C] &)
+ GenericInterval[C] &operator-(GenericInterval[C] &)
+ GenericInterval[C] &operator|(GenericInterval[C] &)
+ bint operator==(GenericInterval[C] &)
+ bint operator!=(GenericInterval[C] &)
+
+
+ cdef cppclass GenericOptInterval[C]:
+
+ GenericOptInterval()
+ GenericOptInterval(C)
+ GenericOptInterval(C, C)
+
+ GenericInterval get()
+
+ C min()
+ C max()
+ C extent()
+ C middle()
+
+ bint isEmpty()
+ bint isSingular()
+ bint contains(C)
+ bint contains(GenericOptInterval[C] &)
+ bint intersects(GenericOptInterval[C] &)
+
+ void setMin(C)
+ void setMax(C)
+ void expandTo(C)
+ void expandBy(C)
+ void unionWith(GenericOptInterval[C] &)
+ void intersectWith(GenericOptInterval &)
+
+
+ GenericOptInterval[C] &operator+(C)
+ GenericOptInterval[C] &operator-(C)
+ GenericOptInterval[C] &operator-()
+ GenericOptInterval[C] &operator+(GenericOptInterval[C] &)
+ GenericOptInterval[C] &operator-(GenericOptInterval[C] &)
+ GenericOptInterval[C] &operator|(GenericOptInterval[C] &)
+ GenericOptInterval[C] &operator&(GenericOptInterval[C] &)
+ bint operator==(GenericOptInterval[C] &)
+ bint operator!=(GenericOptInterval[C] &)
+
+
+cdef extern from "2geom/int-interval.h" namespace "Geom":
+ ctypedef GenericInterval[IntCoord] IntInterval
+ ctypedef GenericOptInterval[IntCoord] OptIntInterval
+
+
+#redeclaring inherited methods, other option is to cast all
+#pointers from Interval to GenericInterval[Coord] in extension class
+cdef extern from "2geom/interval.h" namespace "Geom":
+
+ cdef cppclass Interval:
+
+ Interval()
+ Interval(Coord)
+ Interval(Coord, Coord)
+
+ Coord min()
+ Coord max()
+ Coord extent()
+ Coord middle()
+
+ bint isSingular()
+ bint contains(Coord)
+ bint contains(Interval &)
+ bint intersects(Interval &)
+
+ void setMin(Coord)
+ void setMax(Coord)
+ void expandTo(Coord)
+ void expandBy(Coord)
+ void unionWith(Interval &)
+
+ bint isFinite()
+ bint interiorContains(Coord)
+ bint interiorContains(Interval &)
+ bint interiorIntersects(Interval &)
+
+ Interval & operator*(Coord)
+ Interval & operator/(Coord)
+ Interval & operator*(Interval &)
+ bint operator==(IntInterval &)
+ bint operator==(Interval &)
+ bint operator!=(Interval &)
+ bint operator!=(IntInterval &)
+ Interval &operator+(Coord)
+ Interval &operator-(Coord)
+ Interval &operator-()
+ Interval &operator+(Interval &)
+ Interval &operator-(Interval &)
+ Interval &operator|(Interval &)
+
+ IntInterval roundOutwards()
+ OptIntInterval roundInwards()
+
+
+ cdef cppclass OptInterval:
+
+ OptInterval(OptInterval &)
+ OptInterval()
+ OptInterval(Interval &)
+ OptInterval(Coord)
+ OptInterval(Coord, Coord)
+ OptInterval(GenericOptInterval[double] &)
+ OptInterval(IntInterval &)
+ OptInterval(OptIntInterval &)
+
+ Interval get()
+ bint isEmpty()
+ void unionWith(OptInterval &)
+ void intersectWith(OptInterval &)
+
+ OptInterval &operator|(OptInterval &)
+ OptInterval &operator&(OptInterval &)
+
+cdef class cy_Interval:
+ cdef Interval* thisptr
+
+cdef cy_Interval wrap_Interval(Interval p)
+
+cdef class cy_OptInterval:
+ cdef OptInterval* thisptr
+
+cdef cy_OptInterval wrap_OptInterval(OptInterval p)
+
+
+cdef extern from "2geom/generic-rect.h" namespace "Geom":
+ cdef cppclass GenericRect[C]:
+ GenericRect()
+ GenericRect(GenericInterval[C] &, GenericInterval[C] &)
+ GenericRect(Point &, Point &)
+ GenericRect(PyPoint &, PyPoint &)
+ GenericRect(IntPoint &, IntPoint &)
+ GenericRect(C, C, C, C)
+
+ GenericInterval[C] & operator[](Dim2)
+
+ PyPoint min()
+ PyPoint max()
+ PyPoint corner(unsigned int)
+
+ IntPoint i_min "min" ()
+ IntPoint i_max "max" ()
+ IntPoint i_corner "corner" (unsigned int)
+
+ C top()
+ C bottom()
+ C left()
+ C right()
+ C width()
+ C height()
+ Coord aspectRatio()
+
+ PyPoint dimensions()
+ PyPoint midpoint()
+
+ IntPoint i_dimensions "dimensions" ()
+ IntPoint i_midpoint "midpoint" ()
+
+ C area()
+ bint hasZeroArea()
+ C maxExtent()
+ C minExtent()
+ bint intersects(GenericRect[C] &)
+ bint contains(GenericRect[C] &)
+
+ bint contains(PyPoint &)
+ bint contains(IntPoint &)
+
+ void setLeft(C)
+ void setRight(C)
+ void setTop(C)
+ void setBottom(C)
+
+ void setMin(PyPoint &)
+ void setMax(PyPoint &)
+ void expandTo(PyPoint &)
+ void setMin(IntPoint &)
+ void setMax(IntPoint &)
+ void expandTo(IntPoint &)
+
+ void unionWith(GenericRect[C] &)
+ void expandBy(C)
+ void expandBy(C, C)
+
+ void expandBy(PyPoint &)
+ void expandBy(IntPoint &)
+
+ GenericRect[C] & operator+(PyPoint &)
+ GenericRect[C] & operator+(IntPoint &)
+
+ GenericRect[C] & operator-(PyPoint &)
+ GenericRect[C] & operator-(IntPoint &)
+
+ GenericRect[C] & operator|(GenericRect[C] &)
+ bint operator==(GenericRect[C] &)
+ bint operator!=(GenericRect[C] &)
+
+
+ cdef cppclass GenericOptRect[C]:
+ GenericOptRect()
+ GenericOptRect(GenericRect[C] &)
+ GenericOptRect(C, C, C, C)
+ GenericOptRect(Point &, Point &)
+ GenericOptRect(GenericOptInterval[C] &, GenericOptInterval[C] &)
+
+ GenericRect[C] get()
+
+ bint isEmpty()
+ bint intersects(GenericRect[C] &)
+ bint contains(GenericRect[C] &)
+ bint intersects(GenericOptRect[C] &)
+ bint contains(GenericOptRect[C] &)
+
+ bint contains(Point &)
+ bint contains(IntPoint &)
+
+ void unionWith(GenericRect[C] &)
+ void unionWith(GenericOptRect[C] &)
+ void intersectWith(GenericRect[C] &)
+ void intersectWith(GenericOptRect[C] &)
+
+ void expandTo(Point &)
+
+ GenericOptRect[C] &operator|(GenericOptRect[C] &)
+ GenericOptRect[C] &operator&(GenericRect[C] &)
+ GenericOptRect[C] &operator&(GenericOptRect[C] &)
+
+ bint operator==(GenericOptRect[C] &)
+ bint operator==(GenericRect[C] &)
+
+ bint operator!=(GenericOptRect[C] &)
+ bint operator!=(GenericRect[C] &)
+
+cdef extern from "2geom/generic-rect.h" namespace "Geom::GenericRect<Geom::WrappedPyObject>":
+ GenericRect[WrappedPyObject] from_xywh(WrappedPyObject, WrappedPyObject, WrappedPyObject, WrappedPyObject)
+ GenericRect[WrappedPyObject] from_xywh(PyPoint &, PyPoint &)
+
+cdef extern from "2geom/int-rect.h" namespace "Geom":
+ ctypedef GenericRect[IntCoord] IntRect
+
+cdef extern from "2geom/rect.h" namespace "Geom":
+ cdef cppclass Rect:
+ Rect()
+ Rect(Interval &, Interval &)
+ Rect(Point &, Point &)
+ Rect(Coord, Coord, Coord, Coord)
+
+ Interval & operator[](Dim2)
+ Point min()
+ Point max()
+ Point corner(unsigned int)
+ Coord top()
+ Coord bottom()
+ Coord left()
+ Coord right()
+ Coord width()
+ Coord height()
+ Coord aspectRatio()
+ Point dimensions()
+ Point midpoint()
+ Coord area()
+ bint hasZeroArea()
+ Coord maxExtent()
+ Coord minExtent()
+
+ bint intersects(Rect &)
+ bint contains(Rect &)
+ bint contains(Point &)
+
+ void setLeft(Coord)
+ void setRight(Coord)
+ void setTop(Coord)
+ void setBottom(Coord)
+ void setMin(Point &)
+ void setMax(Point &)
+ void expandTo(Point &)
+ void unionWith(Rect &)
+ void expandBy(Coord)
+ void expandBy(Coord, Coord)
+ void expandBy(Point &)
+
+ Rect & operator+(Point &)
+ Rect & operator-(Point &)
+ Rect & operator|(Rect &)
+ bint operator==(Rect &)
+ bint operator!=(Rect &)
+ bint operator==(IntRect &)
+ bint operator!=(IntRect &)
+
+ bint hasZeroArea(Coord)
+ bint interiorIntersects(Rect &)
+ bint interiorContains(Point &)
+ bint interiorContains(Rect &)
+ bint interiorContains(OptRect &)
+
+ IntRect roundOutwards()
+ OptIntRect roundInwards()
+ Rect &operator*(Affine &)
+
+ Coord distanceSq(Point &, Rect &)
+ Coord distance(Point &, Rect &)
+
+
+ cdef cppclass OptRect:
+ OptRect()
+ OptRect(Rect &)
+ OptRect(Coord, Coord, Coord, Coord)
+ OptRect(Point &, Point &)
+ OptRect(OptInterval &, OptInterval &)
+
+ Rect get()
+
+ bint isEmpty()
+ bint intersects(Rect &)
+ bint contains(Rect &)
+ bint intersects(OptRect &)
+ bint contains(OptRect &)
+ bint contains(Point &)
+
+ void unionWith(Rect &)
+ void unionWith(OptRect &)
+ void intersectWith(Rect &)
+ void intersectWith(OptRect &)
+ void expandTo(Point &)
+
+ OptRect &operator|(OptRect &)
+ OptRect &operator&(Rect &)
+ OptRect &operator&(OptRect &)
+
+ bint operator==(OptRect &)
+ bint operator==(Rect &)
+
+ bint operator!=(OptRect &)
+ bint operator!=(Rect &)
+
+cdef extern from "2geom/rect.h" namespace "Geom::Rect":
+ Rect from_xywh(Coord, Coord, Coord, Coord)
+ Rect from_xywh(Point &, Point &)
+ Rect infinite()
+
+cdef class cy_Rect:
+ cdef Rect* thisptr
+
+cdef cy_Rect wrap_Rect(Rect p)
+
+cdef class cy_OptRect:
+ cdef OptRect* thisptr
+
+cdef cy_OptRect wrap_OptRect(OptRect p)
+
+
+cdef extern from "2geom/int-rect.h" namespace "Geom":
+ #redeclaring because cython complains about ambiguous overloading otherwise
+ cdef cppclass OptIntRect:
+ OptIntRect()
+ OptIntRect(IntRect &)
+ OptIntRect(IntCoord, IntCoord, IntCoord, IntCoord)
+ OptIntRect(IntPoint &, IntPoint &)
+ OptIntRect(OptIntInterval &, OptIntInterval &)
+
+ IntRect get()
+
+ bint isEmpty()
+ bint intersects(IntRect &)
+ bint contains(IntRect &)
+ bint intersects(OptIntRect &)
+ bint contains(OptIntRect &)
+
+ bint contains(Point &)
+ bint contains(IntPoint &)
+
+ void unionWith(IntRect &)
+ void unionWith(OptIntRect &)
+ void intersectWith(IntRect &)
+ void intersectWith(OptIntRect &)
+
+ void expandTo(IntPoint &)
+
+ OptIntRect &operator|(OptIntRect &)
+ OptIntRect &operator&(IntRect &)
+ OptIntRect &operator&(OptIntRect &)
+
+ bint operator==(OptIntRect &)
+ bint operator==(IntRect &)
+
+ bint operator!=(OptIntRect &)
+ bint operator!=(IntRect &)
+
diff --git a/src/3rdparty/2geom/src/cython/_cy_rectangle.pyx b/src/3rdparty/2geom/src/cython/_cy_rectangle.pyx
new file mode 100644
index 0000000..1d1b687
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/_cy_rectangle.pyx
@@ -0,0 +1,2202 @@
+from numbers import Number
+
+from _common_decl cimport *
+from cython.operator cimport dereference as deref
+
+from _cy_affine cimport cy_Affine, get_Affine, is_transform
+
+
+cdef class cy_GenericInterval:
+ """
+ Represents all numbers between min and max.
+
+ Corresponds to GenericInterval in 2geom. min and max can be arbitrary
+ python object, they just have to implement arithmetic operations and
+ comparison - fractions.Fraction works. This is a bit experimental,
+ it leak memory right now.
+ """
+
+ cdef GenericInterval[WrappedPyObject]* thisptr
+
+ def __cinit__(self, u = 0, v = None):
+ """Create GenericInterval from either one or two values."""
+ if v is None:
+ self.thisptr = new GenericInterval[WrappedPyObject]( WrappedPyObject(u) )
+ else:
+ self.thisptr = new GenericInterval[WrappedPyObject]( WrappedPyObject(u), WrappedPyObject(v) )
+
+ def __str__(self):
+ """str(self)"""
+ return "[{}, {}]".format(self.min(), self.max())
+
+ def __repr__(self):
+ """repr(self)"""
+ if self.is_singular():
+ return "GenericInterval({})".format( str(self.min()) )
+ return "GenericInterval({}, {})".format( str(self.min()) , str(self.max()) )
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ @classmethod
+ def from_Interval(self, i):
+ """Create GenericInterval with same minimum and maximum as argument."""
+ return cy_GenericInterval( i.min(), i.max() )
+
+ @classmethod
+ def from_list(self, lst):
+ """Create GenericInterval containing all values in list."""
+ if len(lst) == 0:
+ return cy_GenericInterval()
+ ret = cy_GenericInterval(lst[0])
+ for i in lst[1:]:
+ ret.expand_to(i)
+ return ret
+
+ def min(self):
+ """Return minimal value of interval."""
+ return self.thisptr.min().getObj()
+
+ def max(self):
+ """Return maximal value of interval."""
+ return self.thisptr.max().getObj()
+ def extent(self):
+ """Return difference between maximal and minimal value."""
+ return self.thisptr.extent().getObj()
+
+ def middle(self):
+ """Return midpoint of interval."""
+ return self.thisptr.middle().getObj()
+
+ def is_singular(self):
+ """Test for one-valued interval."""
+ return self.thisptr.isSingular()
+
+ def set_min(self, val):
+ """Set minimal value."""
+ self.thisptr.setMin( WrappedPyObject(val) )
+
+ def set_max(self, val):
+ """Set maximal value."""
+ self.thisptr.setMax( WrappedPyObject(val) )
+
+ def expand_to(self, val):
+ """Create smallest superset of self containing value."""
+ self.thisptr.expandTo( WrappedPyObject(val) )
+
+ def expand_by(self, val):
+ """Push both boundaries by value."""
+ self.thisptr.expandBy( WrappedPyObject(val) )
+ def union_with(self, cy_GenericInterval interval):
+ """self = self | other"""
+ self.thisptr.unionWith( deref(interval.thisptr) )
+
+ def contains(self, other):
+ """Check if interval contains value."""
+ return self.thisptr.contains( WrappedPyObject(other) )
+
+ def contains_interval(self, cy_GenericInterval other):
+ """Check if interval contains every point of interval."""
+ return self.thisptr.contains( deref(other.thisptr) )
+
+ def intersects(self, cy_GenericInterval other):
+ """Check for intersecting intervals."""
+ return self.thisptr.intersects(deref( other.thisptr ))
+
+ def __neg__(self):
+ """Return interval with negated boundaries."""
+ return wrap_GenericInterval(-deref(self.thisptr))
+
+ def _add_pyobj(self, X):
+ return wrap_GenericInterval(deref(self.thisptr) + WrappedPyObject(X) )
+ def _sub_pyobj(self, X):
+ return wrap_GenericInterval(deref(self.thisptr) - WrappedPyObject(X) )
+
+ def _add_interval(self, cy_GenericInterval I):
+ return wrap_GenericInterval(deref(self.thisptr)+deref(I.thisptr))
+ def _sub_interval(self, cy_GenericInterval I):
+ return wrap_GenericInterval(deref(self.thisptr)-deref(I.thisptr))
+
+ def __add__(cy_GenericInterval self, other):
+ """Add interval or value to self.
+
+ Interval I+J consists of all values i+j such that i is in I and
+ j is in J
+
+ Interval I+x consists of all values i+x such that i is in I.
+ """
+ if isinstance(other, cy_GenericInterval):
+ return self._add_interval(other)
+ else:
+ return self._add_pyobj(other)
+
+ def __sub__(cy_GenericInterval self, other):
+ """Substract interval or value.
+
+ Interval I-J consists of all values i-j such that i is in I and
+ j is in J
+
+ Interval I-x consists of all values i-x such that i is in I.
+ """
+ if isinstance(other, cy_GenericInterval):
+ return self._sub_interval(other)
+ else:
+ return self._sub_pyobj(other)
+
+ def __or__(cy_GenericInterval self, cy_GenericInterval I):
+ """Return a union of two intervals"""
+ return wrap_GenericInterval(deref(self.thisptr)|deref(I.thisptr))
+
+ def _eq(self, cy_GenericInterval other):
+ return deref(self.thisptr)==deref(other.thisptr)
+
+ def _neq(self, cy_GenericInterval other):
+ return deref(self.thisptr)!=deref(other.thisptr)
+
+ def __richcmp__(cy_GenericInterval self, other, op):
+ """Intervals are not ordered."""
+ if op == 2:
+ return self._eq(other)
+ elif op == 3:
+ return self._neq(other)
+
+cdef cy_GenericInterval wrap_GenericInterval(GenericInterval[WrappedPyObject] p):
+ cdef GenericInterval[WrappedPyObject] * retp = new GenericInterval[WrappedPyObject](WrappedPyObject(0))
+ retp[0] = p
+ cdef cy_GenericInterval r = cy_GenericInterval.__new__(
+ cy_GenericInterval, 0, 0)
+ r.thisptr = retp
+ return r
+
+
+cdef class cy_GenericOptInterval:
+
+ """Class representing optionally empty interval.
+
+ Empty interval has False bool value, and using methods that require
+ non-empty interval will result in ValueError. This is supposed to be
+ used this way:
+
+ >>> C = A & B
+ >>> if C:
+ >>> print C.min()
+
+ This class represents GenericOptInterval with python object boundaries.
+ It tries to model behaviour of std::optional.
+ """
+
+ cdef GenericOptInterval[WrappedPyObject]* thisptr
+
+ def __cinit__(self, u = None, v = None):
+ """Create interval from boundaries.
+
+ Using no arguments, you will end up with empty interval."""
+ if u is None:
+ self.thisptr = new GenericOptInterval[WrappedPyObject]()
+ elif v is None:
+ self.thisptr = new GenericOptInterval[WrappedPyObject](WrappedPyObject(u))
+ else:
+ self.thisptr = new GenericOptInterval[WrappedPyObject](WrappedPyObject(u), WrappedPyObject(v) )
+
+ def __bool__(self):
+ """Logical value of interval, False only for empty interval."""
+ return not self.thisptr.isEmpty()
+
+ def __str__(self):
+ """str(self)"""
+ if not self:
+ return "[]"
+ return "[{}, {}]".format(self.Interval.min(), self.Interval.max())
+
+ def __repr__(self):
+ """repr(self)"""
+ if not self:
+ return "GenericOptInterval()"
+ if self.Interval.isSingular():
+ return "GenericOptInterval({})".format( str(self.Interval.min()) )
+ return "GenericOptInterval({}, {})".format( str(self.Interval.min()) , str(self.Interval.max()) )
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ @classmethod
+ def from_Interval(self, i):
+ """Create interval from existing interval."""
+ if hasattr(i, "isEmpty"):
+ if i.isEmpty():
+ return cy_GenericOptInterval()
+ else:
+ return cy_GenericOptInterval.from_Interval(i.Interval)
+ return cy_GenericOptInterval( i.min(), i.max() )
+
+ @classmethod
+ def from_list(self, lst):
+ """Create interval containing all values in list.
+
+ Empty list will result in empty interval."""
+ if len(lst) == 0:
+ return cy_GenericOptInterval()
+ ret = cy_GenericOptInterval(lst[0])
+ for i in lst[1:]:
+ ret.Interval.expandTo(i)
+ return ret
+
+ property Interval:
+ """Get underlying GenericInterval."""
+ def __get__(self):
+ if self.is_empty():
+ raise ValueError("Interval is empty.")
+ else:
+ return wrap_GenericInterval(self.thisptr.get())
+
+ def is_empty(self):
+ """Check whether interval is empty set."""
+ return self.thisptr.isEmpty()
+
+ def union_with(self, cy_GenericOptInterval o):
+ """self = self | other"""
+ self.thisptr.unionWith( deref(o.thisptr) )
+
+ def intersect_with(cy_GenericOptInterval self, cy_GenericOptInterval o):
+ """self = self & other"""
+ self.thisptr.intersectWith( deref(o.thisptr) )
+
+ def __or__(cy_GenericOptInterval self, cy_GenericOptInterval o):
+ """Return a union of two intervals."""
+ return wrap_GenericOptInterval(deref(self.thisptr) | deref(o.thisptr))
+
+ def __and__(cy_GenericOptInterval self, cy_GenericOptInterval o):
+ """Return an intersection of two intervals."""
+ return wrap_GenericOptInterval(deref(self.thisptr) & deref(o.thisptr))
+
+ def __richcmp__(cy_GenericOptInterval self, cy_GenericOptInterval o, int op):
+ """Intervals are not ordered."""
+ if op == 2:
+ return deref(self.thisptr) == deref(o.thisptr)
+ elif op == 3:
+ return deref(self.thisptr) != deref(o.thisptr)
+ return NotImplemented
+
+
+ def _get_Interval_method(self, name):
+ def f(*args, **kwargs):
+ if self.is_empty():
+ raise ValueError("GenericOptInterval is empty.")
+ else:
+ return self.Interval.__getattribute__(name)(*args, **kwargs)
+ return f
+
+ def __getattr__(self, name):
+
+ Interval_methods = set(['contains', 'contains_interval',
+ 'expand_by', 'expand_to', 'extent', 'from_Interval', 'from_list',
+ 'intersects', 'is_singular', 'max', 'middle', 'min', 'set_max',
+ 'set_min', 'union_with'])
+
+ if name in Interval_methods:
+ return self._get_Interval_method(name)
+ else:
+ raise AttributeError("GenericOptInterval instance has no attribute \"{}\"".format(name))
+
+ def _wrap_Interval_method(self, name, *args, **kwargs):
+ if self.isEmpty():
+ raise ValueError("GenericOptInterval is empty.")
+ else:
+ return self.Interval.__getattr__(name)(*args, **kwargs)
+
+ #declaring these by hand, because they take fixed number of arguments,
+ #which is enforced by cython
+
+ def __neg__(self):
+ """Return interval with negated boundaries."""
+ return self._wrap_Interval_method("__sub__")
+
+ def __add__(cy_Interval self, other):
+ """Add interval or value to self.
+
+ Interval I+J consists of all values i+j such that i is in I and
+ j is in J
+
+ Interval I+x consists of all values i+x such that i is in I.
+ """
+ return self._wrap_Interval_method("__add__", other)
+
+ def __sub__(cy_Interval self, other):
+ """Substract interval or value.
+
+ Interval I-J consists of all values i-j such that i is in I and
+ j is in J
+
+ Interval I-x consists of all values i-x such that i is in I.
+ """
+ return self._wrap_Interval_method("__sub__", other)
+
+cdef cy_GenericOptInterval wrap_GenericOptInterval(GenericOptInterval[WrappedPyObject] p):
+ cdef GenericOptInterval[WrappedPyObject] * retp = new GenericOptInterval[WrappedPyObject]()
+ retp[0] = p
+ cdef cy_GenericOptInterval r = cy_GenericOptInterval.__new__(cy_GenericOptInterval)
+ r.thisptr = retp
+ return r
+
+
+cdef class cy_Interval:
+
+ """Class representing interval on real line.
+
+ Corresponds to Interval class in 2geom.
+ """
+
+ def __cinit__(self, u = None, v = None):
+ """Create interval from it's boundaries.
+
+ One argument will create interval consisting that value, no
+ arguments create Interval(0).
+ """
+ if u is None:
+ self.thisptr = new Interval()
+ elif v is None:
+ self.thisptr = new Interval(<Coord>float(u))
+ else:
+ self.thisptr = new Interval(<Coord>float(u), <Coord>float(v))
+
+ def __str__(self):
+ """str(self)"""
+ return "[{}, {}]".format(self.min(), self.max())
+
+ def __repr__(self):
+ """repr(self)"""
+ if self.is_singular():
+ return "Interval({})".format( str(self.min()) )
+ return "Interval({}, {})".format( str(self.min()) , str(self.max()) )
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ @classmethod
+ def from_Interval(c, i):
+ """Create Interval with same boundaries as argument."""
+ return cy_Interval( i.min(), i.max() )
+
+ @classmethod
+ def from_list(cls, lst):
+ """Create interval containing all values in a list."""
+ if len(lst) == 0:
+ return cy_Interval()
+ ret = cy_Interval(lst[0])
+ for i in lst[1:]:
+ ret.expand_to(i)
+ return ret
+
+ def min(self):
+ """Return minimal boundary."""
+ return self.thisptr.min()
+
+ def max(self):
+ """Return maximal boundary."""
+ return self.thisptr.max()
+
+ def extent(self):
+ """Return length of interval."""
+ return self.thisptr.extent()
+
+ def middle(self):
+ """Return middle value."""
+ return self.thisptr.middle()
+
+ def set_min(self, Coord val):
+ """Set minimal value."""
+ self.thisptr.setMin(val)
+
+ def set_max(self, Coord val):
+ """Set maximal value."""
+ self.thisptr.setMax(val)
+
+ def expand_to(self, Coord val):
+ """Set self to smallest superset of set containing value."""
+ self.thisptr.expandTo(val)
+
+ def expand_by(self, Coord amount):
+ """Move both boundaries by amount."""
+ self.thisptr.expandBy(amount)
+
+ def union_with(self, cy_Interval a):
+ """self = self | other"""
+ self.thisptr.unionWith(deref( a.thisptr ))
+
+# Not exposing this - deprecated
+# def __getitem__(self, unsigned int i):
+# return deref(self.thisptr)[i]
+
+ def is_singular(self):
+ """Test if interval contains only one value."""
+ return self.thisptr.isSingular()
+
+ def isFinite(self):
+ """Test for finiteness of interval's extent."""
+ return self.thisptr.isFinite()
+
+ def contains(cy_Interval self, other):
+ """Test if interval contains number."""
+ return self.thisptr.contains(float(other))
+
+ def contains_interval(cy_Interval self, cy_Interval other):
+ """Test if interval contains another interval."""
+ return self.thisptr.contains( deref(other.thisptr) )
+
+ def intersects(self, cy_Interval val):
+ """Test for intersection of intervals."""
+ return self.thisptr.intersects(deref( val.thisptr ))
+
+ def interior_contains(cy_Interval self, other):
+ """Test if interior of iterval contains number."""
+ return self.thisptr.interiorContains(float(other))
+
+ def interior_contains_interval(cy_Interval self, cy_Interval other):
+ """Test if interior of interval contains another interval."""
+ return self.thisptr.interiorContains( <Interval &> deref(other.thisptr) )
+
+
+ def interior_intersects(self, cy_Interval val):
+ """Test for intersection of interiors of two points."""
+ return self.thisptr.interiorIntersects(deref( val.thisptr ))
+
+ def _cmp_Interval(cy_Interval self, cy_Interval other, op):
+ if op == 2:
+ return deref(self.thisptr) == deref(other.thisptr)
+ elif op == 3:
+ return deref(self.thisptr) != deref(other.thisptr)
+ def _cmp_IntInterval(cy_Interval self, cy_IntInterval other, op):
+ if op == 2:
+ return deref(self.thisptr) == deref(other.thisptr)
+ elif op == 3:
+ return deref(self.thisptr) != deref(other.thisptr)
+
+ def __richcmp__(cy_Interval self, other, op):
+ """Intervals are not ordered."""
+ if isinstance(other, cy_Interval):
+ return self._cmp_Interval(other, op)
+ elif isinstance(other, cy_IntInterval):
+ return self._cmp_IntInterval(other, op)
+
+ def __neg__(self):
+ """Return interval with negated boundaries."""
+ return wrap_Interval(-deref(self.thisptr))
+
+ def _add_number(self, Coord X):
+ return wrap_Interval(deref(self.thisptr)+X)
+ def _sub_number(self, Coord X):
+ return wrap_Interval(deref(self.thisptr)-X)
+ def _mul_number(self, Coord X):
+ return wrap_Interval(deref(self.thisptr)*X)
+
+ def _add_interval(self, cy_Interval I):
+ return wrap_Interval(deref(self.thisptr)+deref(I.thisptr))
+ def _sub_interval(self, cy_Interval I):
+ return wrap_Interval(deref(self.thisptr)-deref(I.thisptr))
+ def _mul_interval(self, cy_Interval I):
+ return wrap_Interval(deref(self.thisptr)*deref(I.thisptr))
+
+ def __mul__(cy_Interval self, other):
+ """Multiply interval by interval or number.
+
+ Multiplying by number simply multiplies boundaries,
+ multiplying intervals creates all values that can be written as
+ product i*j of i in I and j in J.
+ """
+ if isinstance(other, Number):
+ return self._mul_number(float(other))
+ else:
+ return self._mul_interval(other)
+
+ def __add__(cy_Interval self, other):
+ """Add interval or value to self.
+
+ Interval I+J consists of all values i+j such that i is in I and
+ j is in J
+
+ Interval I+x consists of all values i+x such that i is in I.
+ """
+ if isinstance(other, Number):
+ return self._add_number(float(other))
+ else:
+ return self._add_interval(other)
+
+ def __sub__(cy_Interval self, other):
+ """Substract interval or value.
+
+ Interval I-J consists of all values i-j such that i is in I and
+ j is in J
+
+ Interval I-x consists of all values i-x such that i is in I.
+ """
+ if isinstance(other, Number):
+ return self._sub_number(float(other))
+ else:
+ return self._sub_interval(other)
+
+ def __div__(cy_Interval self, Coord s):
+ """Divide boundaries by number."""
+ return wrap_Interval(deref(self.thisptr)/s)
+
+ def __or__(cy_Interval self, cy_Interval I):
+ """Return union of two intervals."""
+ return wrap_Interval(deref(self.thisptr)|deref(I.thisptr))
+
+ def round_outwards(self):
+ """Create the smallest IntIterval that is superset."""
+ return wrap_IntInterval(self.thisptr.roundOutwards())
+
+ def round_inwards(self):
+ """Create the largest IntInterval that is subset."""
+ return wrap_OptIntInterval(self.thisptr.roundInwards())
+
+cdef cy_Interval wrap_Interval(Interval p):
+ cdef Interval * retp = new Interval()
+ retp[0] = p
+ cdef cy_Interval r = cy_Interval.__new__(cy_Interval)
+ r.thisptr = retp
+ return r
+
+
+cdef class cy_OptInterval:
+
+ """Class representing optionally empty interval on real line.
+
+ Empty interval has False bool value, and using methods that require
+ non-empty interval will result in ValueError. This is supposed to be
+ used this way:
+
+ >>> C = A & B
+ >>> if C:
+ >>> print C.min()
+
+ This class represents OptInterval. It tries to model behaviour of
+ std::optional.
+ """
+
+ def __cinit__(self, u = None, v = None):
+ """Create optionally empty interval form it's endpoints.
+
+ No arguments will result in empty interval.
+ """
+ if u is None:
+ self.thisptr = new OptInterval()
+ elif v is None:
+ self.thisptr = new OptInterval(<Coord>float(u))
+ else:
+ self.thisptr = new OptInterval(<Coord>float(u), <Coord>float(v))
+
+ def __bool__(self):
+ """Only empty interval is False."""
+ return not self.thisptr.isEmpty()
+
+ def __str__(self):
+ """str(self)"""
+ if not self:
+ return "[]"
+ return "[{}, {}]".format(self.Interval.min(), self.Interval.max())
+
+ def __repr__(self):
+ """repr(self)"""
+ if not self:
+ return "OptInterval()"
+ if self.Interval.isSingular():
+ return "OptInterval({})".format( str(self.Interval.min()) )
+ return "OptInterval({}, {})".format( str(self.Interval.min()) , str(self.Interval.max()) )
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ @classmethod
+ def from_Interval(cls, i):
+ """Create interval from other (possibly empty) interval."""
+ if hasattr(i, "isEmpty"):
+ if i.isEmpty():
+ return cy_OptInterval()
+ else:
+ return cy_OptInterval.from_Interval(i.Interval)
+ return cy_OptInterval( i.min(), i.max() )
+
+ @classmethod
+ def from_list(self, lst):
+ """Create interval containing all values in list.
+
+ Empty list will result in empty interval."""
+ if len(lst) == 0:
+ return cy_OptInterval()
+ ret = cy_OptInterval(lst[0])
+ for i in lst[1:]:
+ ret.Interval.expandTo(i)
+ return ret
+
+ property Interval:
+ """Get underlying Interval."""
+ def __get__(self):
+ if self.is_empty():
+ raise ValueError("Interval is empty.")
+ else:
+ return wrap_Interval(self.thisptr.get())
+
+ def is_empty(self):
+ """Test for empty interval."""
+ return self.thisptr.isEmpty()
+
+ def union_with(self, cy_OptInterval o):
+ """self = self | other"""
+ self.thisptr.unionWith( deref(o.thisptr) )
+
+ def intersect_with(cy_OptInterval self, cy_OptInterval o):
+ """self = self & other"""
+ self.thisptr.intersectWith( deref(o.thisptr) )
+
+ def __or__(cy_OptInterval self, cy_OptInterval o):
+ """Return union of intervals."""
+ return wrap_OptInterval(deref(self.thisptr) | deref(o.thisptr))
+
+ def __and__(cy_OptInterval self, cy_OptInterval o):
+ """Return intersection of intervals."""
+ return wrap_OptInterval(deref(self.thisptr) & deref(o.thisptr))
+
+ def _get_Interval_method(self, name):
+ def f(*args, **kwargs):
+ if self.is_empty():
+ raise ValueError("OptInterval is empty.")
+ else:
+ return self.Interval.__getattribute__(name)(*args, **kwargs)
+ return f
+
+ def __getattr__(self, name):
+
+ Interval_methods = set(['contains', 'contains_interval', 'expand_by',
+ 'expand_to', 'extent', 'from_Interval', 'from_list',
+ 'interior_contains', 'interior_contains_interval',
+ 'interior_intersects', 'intersects', 'isFinite', 'is_singular',
+ 'max', 'middle', 'min', 'round_inwards', 'round_outwards',
+ 'set_max', 'set_min', 'union_with'])
+
+ if name in Interval_methods:
+ return self._get_Interval_method(name)
+ else:
+ raise AttributeError("OptInterval instance has no attribute \"{}\"".format(name))
+
+ def _wrap_Interval_method(self, name, *args, **kwargs):
+ if self.isEmpty():
+ raise ValueError("OptInterval is empty.")
+ else:
+ return self.Interval.__getattr__(name)(*args, **kwargs)
+
+ #declaring these by hand, because they take fixed number of arguments,
+ #which is enforced by cython
+
+ def __neg__(self):
+ """Return interval with negated boundaries."""
+ return self._wrap_Interval_method("__sub__")
+
+ def __mul__(cy_Interval self, other):
+ """Multiply interval by interval or number.
+
+ Multiplying by number simply multiplies boundaries,
+ multiplying intervals creates all values that can be written as
+ product i*j of i in I and j in J.
+ """
+ return self._wrap_Interval_method("__mul__", other)
+
+ def __add__(cy_Interval self, other):
+ """Add interval or value to self.
+
+ Interval I+J consists of all values i+j such that i is in I and
+ j is in J
+
+ Interval I+x consists of all values i+x such that i is in I.
+ """
+ return self._wrap_Interval_method("__add__", other)
+
+ def __sub__(cy_Interval self, other):
+ """Substract interval or value.
+
+ Interval I-J consists of all values i-j such that i is in I and
+ j is in J
+
+ Interval I-x consists of all values i-x such that i is in I.
+ """
+ return self._wrap_Interval_method("__sub__", other)
+
+ def __div__(cy_Interval self, other):
+ """Divide boundaries by number."""
+ return self._wrap_Interval_method("__div__", other)
+
+cdef cy_OptInterval wrap_OptInterval(OptInterval p):
+ cdef OptInterval * retp = new OptInterval()
+ retp[0] = p
+ cdef cy_OptInterval r = cy_OptInterval.__new__(cy_OptInterval)
+ r.thisptr = retp
+ return r
+
+
+cdef class cy_IntInterval:
+
+ """Class representing interval of integers.
+
+ Corresponds to IntInterval class in 2geom.
+ """
+
+ cdef IntInterval* thisptr
+
+ def __cinit__(self, u = None, v = None):
+ """Create interval from it's boundaries.
+
+ One argument will create interval consisting that value, no
+ arguments create IntInterval(0).
+ """
+ if u is None:
+ self.thisptr = new IntInterval()
+ elif v is None:
+ self.thisptr = new IntInterval(<IntCoord>int(u))
+ else:
+ self.thisptr = new IntInterval(<IntCoord>int(u), <IntCoord>int(v))
+
+ def __str__(self):
+ """str(self)"""
+ return "[{}, {}]".format(self.min(), self.max())
+
+ def __repr__(self):
+ """repr(self)"""
+ if self.is_singular():
+ return "IntInterval({})".format( str(self.min()) )
+ return "IntInterval({}, {})".format( str(self.min()) , str(self.max()) )
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ @classmethod
+ def from_Interval(cls, i):
+ return cy_IntInterval( int(i.min()), int(i.max()) )
+
+ @classmethod
+ def from_list(cls, lst):
+ if len(lst) == 0:
+ return cy_IntInterval()
+ ret = cy_IntInterval(lst[0])
+ for i in lst[1:]:
+ ret.expand_to(i)
+ return ret
+
+ def min(self):
+ """Return minimal boundary."""
+ return self.thisptr.min()
+
+ def max(self):
+ """Return maximal boundary."""
+ return self.thisptr.max()
+
+ def extent(self):
+ """Return length of interval."""
+ return self.thisptr.extent()
+
+ def middle(self):
+ """Return middle value."""
+ return self.thisptr.middle()
+
+ def set_min(self, IntCoord val):
+ """Set minimal value."""
+ self.thisptr.setMin(val)
+
+ def set_max(self, IntCoord val):
+ """Set maximal value."""
+ self.thisptr.setMax(val)
+
+ def expand_to(self, IntCoord val):
+ """Set self to smallest superset of set containing value."""
+ self.thisptr.expandTo(val)
+
+ def expand_by(self, IntCoord amount):
+ """Move both boundaries by amount."""
+ self.thisptr.expandBy(amount)
+
+ def union_with(self, cy_IntInterval a):
+ """self = self | other"""
+ self.thisptr.unionWith(deref( a.thisptr ))
+
+# Not exposing this - deprecated
+# def __getitem__(self, unsigned int i):
+# return deref(self.thisptr)[i]
+
+ def is_singular(self):
+ """Test if interval contains only one value."""
+ return self.thisptr.isSingular()
+
+ def contains(cy_IntInterval self, other):
+ """Test if interval contains number."""
+ return self.thisptr.contains(<IntCoord> int(other))
+
+ def contains_interval(cy_IntInterval self, cy_IntInterval other):
+ """Test if interval contains another interval."""
+ return self.thisptr.contains( deref(other.thisptr) )
+
+ def intersects(self, cy_IntInterval val):
+ """Test for intersection with other interval."""
+ return self.thisptr.intersects(deref( val.thisptr ))
+
+ def __richcmp__(cy_IntInterval self, cy_IntInterval other, op):
+ """Intervals are not ordered."""
+ if op == 2:
+ return deref(self.thisptr) == deref(other.thisptr)
+ elif op == 3:
+ return deref(self.thisptr) != deref(other.thisptr)
+
+ def __neg__(self):
+ """Negate interval's endpoints."""
+ return wrap_IntInterval(-deref(self.thisptr))
+
+ def _add_number(self, IntCoord X):
+ return wrap_IntInterval(deref(self.thisptr)+X)
+ def _sub_number(self, IntCoord X):
+ return wrap_IntInterval(deref(self.thisptr)-X)
+
+ def _add_interval(self, cy_IntInterval I):
+ return wrap_IntInterval(deref(self.thisptr)+deref(I.thisptr))
+ def _sub_interval(self, cy_IntInterval I):
+ return wrap_IntInterval(deref(self.thisptr)-deref(I.thisptr))
+
+ def __add__(cy_IntInterval self, other):
+ """Add interval or value to self.
+
+ Interval I+J consists of all values i+j such that i is in I and
+ j is in J
+
+ Interval I+x consists of all values i+x such that i is in I.
+ """
+ if isinstance(other, Number):
+ return self._add_number(int(other))
+ else:
+ return self._add_interval(other)
+
+ def __sub__(cy_IntInterval self, other):
+ """Substract interval or value.
+
+ Interval I-J consists of all values i-j such that i is in I and
+ j is in J
+
+ Interval I-x consists of all values i-x such that i is in I.
+ """
+ if isinstance(other, Number):
+ return self._sub_number(int(other))
+ else:
+ return self._sub_interval(other)
+
+ def __or__(cy_IntInterval self, cy_IntInterval I):
+ """Return union of two intervals."""
+ return wrap_IntInterval(deref(self.thisptr)|deref(I.thisptr))
+
+cdef cy_IntInterval wrap_IntInterval(IntInterval p):
+ cdef IntInterval * retp = new IntInterval()
+ retp[0] = p
+ cdef cy_IntInterval r = cy_IntInterval.__new__(cy_IntInterval)
+ r.thisptr = retp
+ return r
+
+cdef class cy_OptIntInterval:
+
+ """Class representing optionally empty interval of integers.
+
+ Empty interval has False bool value, and using methods that require
+ non-empty interval will result in ValueError. This is supposed to be
+ used this way:
+
+ >>> C = A & B
+ >>> if C:
+ >>> print C.min()
+
+ This class represents OptIntInterval. It tries to model behaviour of
+ std::optional.
+ """
+
+ cdef OptIntInterval* thisptr
+
+ def __cinit__(self, u = None, v = None):
+ """Create optionally empty interval form it's endpoints.
+
+ No arguments will result in empty interval.
+ """
+ if u is None:
+ self.thisptr = new OptIntInterval()
+ elif v is None:
+ self.thisptr = new OptIntInterval(<IntCoord>int(u))
+ else:
+ self.thisptr = new OptIntInterval(<IntCoord>int(u), <IntCoord>int(v))
+
+ def __bool__(self):
+ """Only empty interval is False."""
+ return not self.thisptr.isEmpty()
+
+ def __str__(self):
+ """str(self)"""
+ if not self:
+ return "[]"
+ return "[{}, {}]".format(self.Interval.min(), self.Interval.max())
+
+ def __repr__(self):
+ """repr(self)"""
+ if not self:
+ return "OptIntInterval()"
+ if self.Interval.isSingular():
+ return "OptIntInterval({})".format( str(self.Interval.min()) )
+ return "OptIntInterval({}, {})".format( str(self.Interval.min()) , str(self.Interval.max()) )
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ @classmethod
+ def from_Interval(self, i):
+ """Create interval from other (possibly empty) interval."""
+ if hasattr(i, "isEmpty"):
+ if i.isEmpty():
+ return cy_OptIntInterval()
+ else:
+ return cy_OptIntInterval.from_Interval(i.Interval)
+ return cy_OptIntInterval( i.min(), i.max() )
+
+ @classmethod
+ def from_list(self, lst):
+ """Create interval containing all values in list.
+
+ Empty list will result in empty interval."""
+ if len(lst) == 0:
+ return cy_OptIntInterval()
+ ret = cy_OptIntInterval(lst[0])
+ for i in lst[1:]:
+ ret.Interval.expandTo(i)
+ return ret
+
+ property Interval:
+ """Get underlying interval."""
+ def __get__(self):
+ return wrap_IntInterval(self.thisptr.get())
+
+ def is_empty(self):
+ """Test for empty interval."""
+ return self.thisptr.isEmpty()
+
+ def union_with(self, cy_OptIntInterval o):
+ """self = self | other"""
+ self.thisptr.unionWith( deref(o.thisptr) )
+
+ def intersect_with(cy_OptIntInterval self, cy_OptIntInterval o):
+ """self = self & other"""
+ self.thisptr.intersectWith( deref(o.thisptr) )
+
+ def __or__(cy_OptIntInterval self, cy_OptIntInterval o):
+ """Return a union of two intervals."""
+ return wrap_OptIntInterval(deref(self.thisptr) | deref(o.thisptr))
+
+ def __and__(cy_OptIntInterval self, cy_OptIntInterval o):
+ """Return an intersection of two intervals."""
+ return wrap_OptIntInterval(deref(self.thisptr) & deref(o.thisptr))
+
+ #TODO decide how to implement various combinations of comparisons!
+
+ def _get_Interval_method(self, name):
+ def f(*args, **kwargs):
+ if self.is_empty():
+ raise ValueError("OptInterval is empty.")
+ else:
+ return self.Interval.__getattribute__(name)(*args, **kwargs)
+ return f
+
+ def __getattr__(self, name):
+
+ Interval_methods = set(['contains', 'contains_interval',
+ 'expand_by', 'expand_to', 'extent', 'from_Interval', 'from_list',
+ 'intersects', 'is_singular', 'max', 'middle', 'min', 'set_max',
+ 'set_min', 'union_with'])
+
+ if name in Interval_methods:
+ return self._get_Interval_method(name)
+ else:
+ raise AttributeError("OptIntInterval instance has no attribute \"{}\"".format(name))
+
+ def _wrap_Interval_method(self, name, *args, **kwargs):
+ if self.isEmpty():
+ raise ValueError("OptIntInterval is empty.")
+ else:
+ return self.Interval.__getattr__(name)(*args, **kwargs)
+
+ #declaring these by hand, because they take fixed number of arguments,
+ #which is enforced by cython
+
+ def __neg__(self):
+ """Negate interval's endpoints."""
+ return self._wrap_Interval_method("__sub__")
+
+
+ def __add__(cy_Interval self, other):
+ """Add interval or value to self.
+
+ Interval I+J consists of all values i+j such that i is in I and
+ j is in J
+
+ Interval I+x consists of all values i+x such that i is in I.
+ """
+ return self._wrap_Interval_method("__add__", other)
+
+ def __sub__(cy_Interval self, other):
+ """Substract interval or value.
+
+ Interval I-J consists of all values i-j such that i is in I and
+ j is in J
+
+ Interval I-x consists of all values i-x such that i is in I.
+ """
+ return self._wrap_Interval_method("__sub__", other)
+
+cdef cy_OptIntInterval wrap_OptIntInterval(OptIntInterval p):
+ cdef OptIntInterval * retp = new OptIntInterval()
+ retp[0] = p
+ cdef cy_OptIntInterval r = cy_OptIntInterval.__new__(cy_OptIntInterval)
+ r.thisptr = retp
+ return r
+
+
+cdef class cy_GenericRect:
+
+ """Class representing axis aligned rectangle, with arbitrary corners.
+
+ Plane in which the rectangle lies can have any object as a coordinates,
+ as long as they implement arithmetic operations and comparison.
+
+ This is a bit experimental, corresponds to GenericRect[C] templated
+ with (wrapped) python object.
+ """
+
+ cdef GenericRect[WrappedPyObject]* thisptr
+
+ def __cinit__(self, x0=0, y0=0, x1=0, y1=0):
+ """Create rectangle from it's top-left and bottom-right corners."""
+ self.thisptr = new GenericRect[WrappedPyObject](WrappedPyObject(x0),
+ WrappedPyObject(y0),
+ WrappedPyObject(x1),
+ WrappedPyObject(y1))
+
+ def __str__(self):
+ """str(self)"""
+ return "Rectangle with dimensions {}, topleft point {}".format(
+ str(self.dimensions()),
+ str(self.min()))
+
+ def __repr__(self):
+ """repr(self)"""
+ return "Rect({}, {}, {}, {})".format( str(self.left()),
+ str(self.top()),
+ str(self.right()),
+ str(self.bottom()) )
+
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ @classmethod
+ def from_intervals(self, I, J):
+ """Create rectangle from two intervals.
+
+ First interval corresponds to side parallel with x-axis,
+ second one with side parallel with y-axis."""
+ return cy_GenericRect(I.min(), I.max(), J.min(), J.max())
+
+ @classmethod
+ def from_list(cls, lst):
+ """Create rectangle containing all points in list.
+
+ These points are represented simply by 2-tuples.
+ """
+ ret = cy_GenericRect()
+ for a in lst:
+ ret.expand_to(a)
+ return ret
+
+ @classmethod
+ def from_xywh(cls, x, y, w, h):
+ """Create rectangle from topleft point and dimensions."""
+ return wrap_GenericRect( from_xywh(WrappedPyObject(x),
+ WrappedPyObject(y),
+ WrappedPyObject(w),
+ WrappedPyObject(h)))
+
+ def __getitem__(self, Dim2 d):
+ """self[i]"""
+ return wrap_GenericInterval( deref(self.thisptr)[d] )
+
+ def min(self):
+ """Get top-left point."""
+ return wrap_PyPoint( self.thisptr.min() )
+
+ def max(self):
+ """Get bottom-right point."""
+ return wrap_PyPoint( self.thisptr.max() )
+
+ def corner(self, unsigned int i):
+ """Get corners (modulo) indexed from 0 to 3."""
+ return wrap_PyPoint( self.thisptr.corner(i) )
+
+ def top(self):
+ """Get top coordinate."""
+ return self.thisptr.top().getObj()
+
+ def bottom(self):
+ """Get bottom coordinate."""
+ return self.thisptr.bottom().getObj()
+
+ def left(self):
+ """Get left coordinate."""
+ return self.thisptr.left().getObj()
+
+ def right(self):
+ """Get right coordinate."""
+ return self.thisptr.right().getObj()
+
+ def width(self):
+ """Get width."""
+ return self.thisptr.width().getObj()
+
+ def height(self):
+ """Get height."""
+ return self.thisptr.height().getObj()
+
+ #For some reason, Cpp aspectRatio returns Coord.
+ def aspectRatio(self):
+ """Get ratio between width and height."""
+ return float(self.width())/float(self.height())
+
+ def dimensions(self):
+ """Get dimensions as tuple."""
+ return wrap_PyPoint( self.thisptr.dimensions() )
+
+ def midpoint(self):
+ """Get midpoint as tuple."""
+ return wrap_PyPoint( self.thisptr.midpoint() )
+
+ def area(self):
+ """Get area."""
+ return self.thisptr.area().getObj()
+
+ def has_zero_area(self):
+ """Test for area being zero."""
+ return self.thisptr.hasZeroArea()
+
+ def max_extent(self):
+ """Get bigger value from width, height."""
+ return self.thisptr.maxExtent().getObj()
+
+ def min_extent(self):
+ """Get smaller value from width, height."""
+ return self.thisptr.minExtent().getObj()
+
+ def intersects(self, cy_GenericRect r):
+ """Check if rectangle intersects another rectangle."""
+ return self.thisptr.intersects(deref( r.thisptr ))
+
+ def contains(self, r):
+ """Check if rectangle contains point represented as tuple."""
+ if not isinstance(r, tuple):
+ raise TypeError("Tuple required to create point.")
+ return self.thisptr.contains( make_PyPoint(r) )
+
+ def contains_rect(self, cy_GenericRect r):
+ """Check if rectangle contains another rect."""
+ return self.thisptr.contains( deref(r.thisptr) )
+
+ def set_left(self, val):
+ """Set left coordinate."""
+ self.thisptr.setLeft( WrappedPyObject(val) )
+
+ def set_right(self, val):
+ """Set right coordinate."""
+ self.thisptr.setRight( WrappedPyObject(val) )
+
+ def set_top(self, val):
+ """Set top coordinate."""
+ self.thisptr.setTop( WrappedPyObject(val) )
+
+ def set_bottom(self, val):
+ """Set bottom coordinate."""
+ self.thisptr.setBottom( WrappedPyObject(val) )
+
+ def set_min(self, p):
+ """Set top-left point."""
+ self.thisptr.setMin(make_PyPoint(p))
+
+ def set_max(self, p):
+ """Set bottom-right point."""
+ self.thisptr.setMax(make_PyPoint(p))
+
+ def expand_to(self, p):
+ """Expand rectangle to contain point represented as tuple."""
+ self.thisptr.expandTo(make_PyPoint(p))
+
+ def union_with(self, cy_GenericRect b):
+ """self = self | other."""
+ self.thisptr.unionWith(deref( b.thisptr ))
+
+ def expand_by(self, x, y = None):
+ """Expand both intervals.
+
+ Either expand them both by one value, or each by different value.
+ """
+ if y is None:
+ self.thisptr.expandBy(WrappedPyObject(x))
+ else:
+ self.thisptr.expandBy(WrappedPyObject(x),
+ WrappedPyObject(y))
+
+
+ def __add__(cy_GenericRect self, p):
+ """Offset rectangle by point."""
+ return wrap_GenericRect( deref(self.thisptr) + make_PyPoint(p) )
+
+ def __sub__(cy_GenericRect self, p):
+ """Offset rectangle by -point."""
+ return wrap_GenericRect( deref(self.thisptr) - make_PyPoint(p) )
+
+ def __or__(cy_GenericRect self, cy_GenericRect o):
+ """Return union of two rects - it's actually bounding rect of union."""
+ return wrap_GenericRect( deref(self.thisptr) | deref( o.thisptr ))
+
+ def __richcmp__(cy_GenericRect self, cy_GenericRect o, int op):
+ """Rectangles are not ordered."""
+ if op == 2:
+ return deref(self.thisptr) == deref(o.thisptr)
+ if op == 3:
+ return deref(self.thisptr) != deref(o.thisptr)
+
+cdef PyPoint make_PyPoint(p):
+ return PyPoint( WrappedPyObject(p[0]), WrappedPyObject(p[1]) )
+
+#D2[WrappedPyObject] is converted to tuple
+cdef wrap_PyPoint(PyPoint p):
+ return (p[0].getObj(), p[1].getObj())
+
+cdef cy_GenericRect wrap_GenericRect(GenericRect[WrappedPyObject] p):
+ cdef WrappedPyObject zero = WrappedPyObject(0)
+ cdef GenericRect[WrappedPyObject] * retp = new GenericRect[WrappedPyObject](zero, zero, zero, zero)
+ retp[0] = p
+ cdef cy_GenericRect r = cy_GenericRect.__new__(cy_GenericRect)
+ r.thisptr = retp
+ return r
+
+
+cdef class cy_Rect:
+
+ """Class representing axis-aligned rectangle in 2D real plane.
+
+ Corresponds to Rect class in 2geom."""
+
+ def __cinit__(self, Coord x0=0, Coord y0=0, Coord x1=0, Coord y1=0):
+ """Create Rect from coordinates of its top-left and bottom-right corners."""
+ self.thisptr = new Rect(x0, y0, x1, y1)
+
+ def __str__(self):
+ """str(self)"""
+ return "Rectangle with dimensions {}, topleft point {}".format(str(self.dimensions()), str(self.min()))
+
+ def __repr__(self):
+ """repr(self)"""
+ return "Rect({}, {}, {}, {})".format( str(self.left()),
+ str(self.top()),
+ str(self.right()),
+ str(self.bottom()))
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ @classmethod
+ def from_points(cls, cy_Point p0, cy_Point p1):
+ """Create rectangle from it's top-left and bottom-right corners."""
+ return wrap_Rect( Rect(deref(p0.thisptr), deref(p1.thisptr)) )
+
+ @classmethod
+ def from_intervals(cls, I, J):
+ """Create rectangle from two intervals representing its sides."""
+ return wrap_Rect( Rect( float(I.min()),
+ float(J.min()),
+ float(I.max()),
+ float(J.max()) ) )
+
+ @classmethod
+ def from_list(cls, lst):
+ """Create rectangle containing all points in list."""
+ if lst == []:
+ return cy_Rect()
+ if len(lst) == 1:
+ return cy_Rect.from_points(lst[0], lst[0])
+ ret = cy_Rect.from_points(lst[0], lst[1])
+ for a in lst:
+ ret.expand_to(a)
+ return ret
+
+ @classmethod
+ def from_xywh(cls, x, y, w, h):
+ """Create rectangle from it's topleft point and dimensions."""
+ return wrap_Rect( from_xywh(<Coord> x,
+ <Coord> y,
+ <Coord> w,
+ <Coord> h) )
+
+ @classmethod
+ def infinite(self):
+ """Create infinite rectangle."""
+ return wrap_Rect(infinite())
+
+ def __getitem__(self, Dim2 d):
+ """self[d]"""
+ return wrap_Interval( deref(self.thisptr)[d] )
+
+ def min(self):
+ """Get top-left point."""
+ return wrap_Point( self.thisptr.min() )
+
+ def max(self):
+ """Get bottom-right point."""
+ return wrap_Point( self.thisptr.max() )
+
+ def corner(self, unsigned int i):
+ """Get corners (modulo) indexed from 0 to 3."""
+ return wrap_Point( self.thisptr.corner(i) )
+
+ def top(self):
+ """Get top coordinate."""
+ return self.thisptr.top()
+
+ def bottom(self):
+ """Get bottom coordinate."""
+ return self.thisptr.bottom()
+
+ def left(self):
+ """Get left coordinate."""
+ return self.thisptr.left()
+
+ def right(self):
+ """Get right coordinate."""
+ return self.thisptr.right()
+
+ def width(self):
+ """Get width."""
+ return self.thisptr.width()
+
+ def height(self):
+ """Get height."""
+ return self.thisptr.height()
+
+ def aspect_ratio(self):
+ """Get ratio between width and height."""
+ return self.thisptr.aspectRatio()
+
+ def dimensions(self):
+ """Get dimensions as point."""
+ return wrap_Point( self.thisptr.dimensions() )
+
+ def midpoint(self):
+ """Get midpoint."""
+ return wrap_Point( self.thisptr.midpoint() )
+
+ def area(self):
+ """Get area."""
+ return self.thisptr.area()
+
+ def has_zero_area(self, Coord eps = EPSILON):
+ """Test for area being zero."""
+ return self.thisptr.hasZeroArea(eps)
+
+ def max_extent(self):
+ """Get bigger value from width, height."""
+ return self.thisptr.maxExtent()
+
+ def min_extent(self):
+ """Get smaller value from width, height."""
+ return self.thisptr.minExtent()
+
+ def intersects(self, cy_Rect r):
+ """Check if rectangle intersects another rectangle."""
+ return self.thisptr.intersects(deref( r.thisptr ))
+
+ def contains(self, cy_Point r):
+ """Check if rectangle contains point."""
+ return self.thisptr.contains( deref(r.thisptr) )
+
+ def contains_rect(self, cy_Rect r):
+ """Check if rectangle contains another rect."""
+ return self.thisptr.contains( deref(r.thisptr) )
+
+ def interior_intersects(self, cy_Rect r):
+ """Check if interior of self intersects another rectangle."""
+ return self.thisptr.interiorIntersects(deref( r.thisptr ))
+
+ def interior_contains(self, cy_Point other):
+ """Check if interior of self contains point."""
+ return self.thisptr.interiorContains( deref( (<cy_Point> other).thisptr ) )
+
+ def interior_contains_rect(self, other):
+ """Check if interior of self contains another rectangle."""
+ if isinstance(other, cy_Rect):
+ return self.thisptr.interiorContains( deref( (<cy_Rect> other).thisptr ) )
+ elif isinstance(other, cy_OptRect):
+ return self.thisptr.interiorContains( deref( (<cy_OptRect> other).thisptr ) )
+
+ def set_left(self, Coord val):
+ """Set left coordinate."""
+ self.thisptr.setLeft(val)
+
+ def set_right(self, Coord val):
+ """Set right coordinate."""
+ self.thisptr.setRight(val)
+
+ def set_top(self, Coord val):
+ """Set top coordinate."""
+ self.thisptr.setTop(val)
+
+ def set_bottom(self, Coord val):
+ """Set bottom coordinate."""
+ self.thisptr.setBottom(val)
+
+ def set_min(self, cy_Point p):
+ """Set top-left point."""
+ self.thisptr.setMin( deref( p.thisptr ) )
+
+ def set_max(self, cy_Point p):
+ """Set bottom-right point."""
+ self.thisptr.setMax( deref( p.thisptr ))
+
+ def expand_to(self, cy_Point p):
+ """Expand rectangle to contain point represented as tuple."""
+ self.thisptr.expandTo( deref( p.thisptr ) )
+
+ def union_with(self, cy_Rect b):
+ """self = self | other."""
+ self.thisptr.unionWith(deref( b.thisptr ))
+
+ def expand_by(cy_Rect self, x, y = None):
+ """Expand both intervals.
+
+ Either expand them both by one value, or each by different value.
+ """
+ if y is None:
+ if isinstance(x, cy_Point):
+ self.thisptr.expandBy( deref( (<cy_Point> x).thisptr ) )
+ else:
+ self.thisptr.expandBy( <Coord> x)
+ else:
+ self.thisptr.expandBy( <Coord> x,
+ <Coord> y)
+
+ def __add__(cy_Rect self, cy_Point p):
+ """Offset rectangle by point."""
+ return wrap_Rect( deref(self.thisptr) + deref( p.thisptr ) )
+
+ def __sub__(cy_Rect self, cy_Point p):
+ """Offset rectangle by -point."""
+ return wrap_Rect( deref(self.thisptr) - deref( p.thisptr ) )
+
+ def __mul__(cy_Rect self, t):
+ """Apply transform to rectangle."""
+ cdef Affine at
+ if is_transform(t):
+ at = get_Affine(t)
+ return wrap_Rect( deref(self.thisptr) * at )
+
+ def __or__(cy_Rect self, cy_Rect o):
+ """Return union of two rects - it's actually bounding rect of union."""
+ return wrap_Rect( deref(self.thisptr) | deref( o.thisptr ))
+
+ def __richcmp__(cy_Rect self, o, int op):
+ """Rectangles are not ordered."""
+ if op == 2:
+ if isinstance(o, cy_Rect):
+ return deref(self.thisptr) == deref( (<cy_Rect> o).thisptr)
+ elif isinstance(o, cy_IntRect):
+ return deref(self.thisptr) == deref( (<cy_IntRect> o).thisptr)
+ if op == 3:
+ if isinstance(o, cy_Rect):
+ return deref(self.thisptr) != deref( (<cy_Rect> o).thisptr)
+ elif isinstance(o, cy_IntRect):
+ return deref(self.thisptr) != deref( (<cy_IntRect> o).thisptr)
+
+ def round_inwards(self):
+ """Create OptIntRect rounding inwards."""
+ return wrap_OptIntRect(self.thisptr.roundInwards())
+
+ def round_outwards(self):
+ """Create IntRect rounding outwards."""
+ return wrap_IntRect(self.thisptr.roundOutwards())
+
+ @classmethod
+ def distanceSq(cls, cy_Point p, cy_Rect rect):
+ """Compute square of distance between point and rectangle."""
+ return distanceSq( deref(p.thisptr), deref(rect.thisptr) )
+
+ @classmethod
+ def distance(cls, cy_Point p, cy_Rect rect):
+ """Compute distance between point and rectangle."""
+ return distance( deref(p.thisptr), deref(rect.thisptr) )
+
+cdef cy_Rect wrap_Rect(Rect p):
+ cdef Rect* retp = new Rect()
+ retp[0] = p
+ cdef cy_Rect r = cy_Rect.__new__(cy_Rect)
+ r.thisptr = retp
+ return r
+
+
+cdef class cy_OptRect:
+
+ """Class representing optionally empty rect in real plane.
+
+ This class corresponds to OptRect in 2geom, and it tries to mimic
+ the behaviour of std::optional. In addition to OptRect methods,
+ this class passes calls for Rect methods to underlying Rect class,
+ or throws ValueError when it's empty.
+ """
+
+ def __cinit__(self, x0=None, y0=None, x1=None, y1=None):
+ """Create OptRect from coordinates of top-left and bottom-right corners.
+
+ No arguments will result in empty rectangle.
+ """
+ if x0 is None:
+ self.thisptr = new OptRect()
+ else:
+ self.thisptr = new OptRect( float(x0),
+ float(y0),
+ float(x1),
+ float(y1) )
+
+ def __str__(self):
+ """str(self)"""
+ if self.is_empty():
+ return "Empty OptRect."
+ return "OptRect with dimensions {}, topleft point {}".format(str(self.dimensions()), str(self.min()))
+
+ def __repr__(self):
+ """repr(self)"""
+ if self.is_empty():
+ return "OptRect()"
+ return "OptRect({}, {}, {}, {})".format( str(self.left()),
+ str(self.top()),
+ str(self.right()),
+ str(self.bottom()))
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ @classmethod
+ def from_points(cls, cy_Point p0, cy_Point p1):
+ """Create rectangle from it's top-left and bottom-right corners."""
+ return wrap_OptRect( OptRect(deref(p0.thisptr), deref(p1.thisptr)) )
+
+ @classmethod
+ def from_intervals(cls, I, J):
+ """Create rectangle from two intervals representing its sides."""
+ if hasattr(I, "isEmpty"):
+ if I.isEmpty():
+ return cy_OptRect()
+
+ if hasattr(J, "isEmpty"):
+ if J.isEmpty():
+ return cy_OptRect()
+
+ return wrap_OptRect( OptRect( float(I.min()),
+ float(J.min()),
+ float(I.max()),
+ float(J.max()) ) )
+
+ @classmethod
+ def from_rect(cls, r):
+ """Create OptRect from other, possibly empty, rectangle."""
+ if hasattr(r, "isEmpty"):
+ if r.isEmpty():
+ return cy_OptRect()
+
+ return cy_OptRect( r.min().x,
+ r.min().y,
+ r.max().x,
+ r.max().y )
+
+ @classmethod
+ def from_list(cls, lst):
+ """Create OptRect containing all points in the list.
+
+ Empty list will result in empty OptRect.
+ """
+ if lst == []:
+ return cy_OptRect()
+ if len(lst) == 1:
+ return cy_OptRect.from_points(lst[0], lst[0])
+ ret = cy_OptRect.from_points(lst[0], lst[1])
+ for a in lst:
+ ret.expand_to(a)
+ return ret
+
+ property Rect:
+ """Get underlying Rect."""
+ def __get__(self):
+ if self.is_empty():
+ raise ValueError("Rect is empty.")
+ else:
+ return wrap_Rect(self.thisptr.get())
+
+ def __bool__(self):
+ """OptRect is False only when it's empty."""
+ return not self.thisptr.isEmpty()
+
+ def is_empty(self):
+ """Check for OptRect containing no points."""
+ return self.thisptr.isEmpty()
+
+ def intersects(self, other):
+ """Check if rectangle intersects another rectangle."""
+ if isinstance(other, cy_Rect):
+ return self.thisptr.intersects( deref( (<cy_Rect> other).thisptr ) )
+ elif isinstance(other, cy_OptRect):
+ return self.thisptr.intersects( deref( (<cy_OptRect> other).thisptr ) )
+
+ def contains(self, cy_Point r):
+ """Check if rectangle contains point."""
+ return self.thisptr.contains( deref(r.thisptr) )
+
+ def contains_rect(self, other):
+ """Check if rectangle contains another rect."""
+ if isinstance(other, cy_Rect):
+ return self.thisptr.contains( deref( (<cy_Rect> other).thisptr ) )
+ elif isinstance(other, cy_OptRect):
+ return self.thisptr.contains( deref( (<cy_OptRect> other).thisptr ) )
+
+ def union_with(self, other):
+ """self = self | other."""
+ if isinstance(other, cy_Rect):
+ self.thisptr.unionWith( deref( (<cy_Rect> other).thisptr ) )
+ elif isinstance(other, cy_OptRect):
+ self.thisptr.unionWith( deref( (<cy_OptRect> other).thisptr ) )
+
+ def intersect_with(self, other):
+ """self = self & other."""
+ if isinstance(other, cy_Rect):
+ self.thisptr.intersectWith( deref( (<cy_Rect> other).thisptr ) )
+ elif isinstance(other, cy_OptRect):
+ self.thisptr.intersectWith( deref( (<cy_OptRect> other).thisptr ) )
+
+ def expand_to(self, cy_Point p):
+ """Expand rectangle to contain point represented as tuple."""
+ self.thisptr.expandTo( deref(p.thisptr) )
+
+ def __or__(cy_OptRect self, cy_OptRect other):
+ """Return union of two rects - it's actually bounding rect of union."""
+ return wrap_OptRect( deref(self.thisptr) | deref(other.thisptr) )
+
+ def __and__(cy_OptRect self, other):
+ """Return intersection of two rectangles."""
+ if isinstance(other, cy_Rect):
+ return wrap_OptRect( deref(self.thisptr) & deref( (<cy_Rect> other).thisptr) )
+ elif isinstance(other, cy_OptRect):
+ return wrap_OptRect( deref(self.thisptr) & deref( (<cy_OptRect> other).thisptr) )
+
+ def __richcmp__(cy_OptRect self, other, op):
+ """Rectangles are not ordered."""
+ if op == 2:
+ if isinstance(other, cy_Rect):
+ return deref(self.thisptr) == deref( (<cy_Rect> other).thisptr )
+ elif isinstance(other, cy_OptRect):
+ return deref(self.thisptr) == deref( (<cy_OptRect> other).thisptr )
+ elif op == 3:
+ if isinstance(other, cy_Rect):
+ return deref(self.thisptr) != deref( (<cy_Rect> other).thisptr )
+ elif isinstance(other, cy_OptRect):
+ return deref(self.thisptr) != deref( (<cy_OptRect> other).thisptr )
+ return NotImplemented
+
+ def _get_Rect_method(self, name):
+ def f(*args, **kwargs):
+ if self.is_empty():
+ raise ValueError("OptRect is empty.")
+ else:
+ return self.Rect.__getattribute__(name)(*args, **kwargs)
+ return f
+
+ def __getattr__(self, name):
+ Rect_methods = set(['area', 'aspectRatio', 'bottom', 'contains',
+ 'contains_rect', 'corner', 'dimensions', 'distance', 'distanceSq',
+ 'expand_by', 'expand_to', 'has_zero_area', 'height', 'infinite',
+ 'interior_contains', 'interior_contains_rect',
+ 'interior_intersects', 'intersects', 'left', 'max', 'max_extent',
+ 'midpoint', 'min', 'min_extent', 'right', 'round_inwards',
+ 'round_outwards', 'set_bottom', 'set_left', 'set_max', 'set_min',
+ 'set_right', 'set_top', 'top', 'union_with', 'width'])
+
+ if name in Rect_methods:
+ return self._get_Rect_method(name)
+ else:
+ raise AttributeError("OptRect instance has no attribute \"{}\"".format(name))
+
+ def _wrap_Rect_method(self, name, *args, **kwargs):
+ if self.isEmpty():
+ raise ValueError("OptRect is empty.")
+ else:
+ return self.Rect.__getattr__(name)(*args, **kwargs)
+
+ #declaring these by hand, because they take fixed number of arguments,
+ #which is enforced by cython
+
+ def __getitem__(self, i):
+ """self[d]"""
+ return self._wrap_Rect_method("__getitem__", i)
+
+ def __add__(self, other):
+ """Offset rectangle by point."""
+ return self._wrap_Rect_method("__add__", other)
+
+ def __mul__(self, other):
+ """Apply transform to rectangle."""
+ return self._wrap_Rect_method("__mul__", other)
+
+ def __sub__(self, other):
+ """Offset rectangle by -point."""
+ return self._wrap_Rect_method("__sub__", other)
+
+
+cdef cy_OptRect wrap_OptRect(OptRect p):
+ cdef OptRect* retp = new OptRect()
+ retp[0] = p
+ cdef cy_OptRect r = cy_OptRect.__new__(cy_OptRect)
+ r.thisptr = retp
+ return r
+
+
+
+cdef class cy_IntRect:
+
+ """Class representing axis-aligned rectangle in 2D with integer coordinates.
+
+ Corresponds to IntRect class (typedef) in 2geom."""
+
+ cdef IntRect* thisptr
+
+ def __cinit__(self, IntCoord x0=0, IntCoord y0=0, IntCoord x1=0, IntCoord y1=0):
+ """Create IntRect from coordinates of its top-left and bottom-right corners."""
+ self.thisptr = new IntRect(x0, y0, x1, y1)
+
+ def __str__(self):
+ """str(self)"""
+ return "IntRect with dimensions {}, topleft point {}".format(
+ str(self.dimensions()),
+ str(self.min()))
+
+ def __repr__(self):
+ """repr(self)"""
+ return "IntRect({}, {}, {}, {})".format( str(self.left()),
+ str(self.top()),
+ str(self.right()),
+ str(self.bottom()))
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ @classmethod
+ def from_points(cls, cy_IntPoint p0, cy_IntPoint p1):
+ """Create rectangle from it's top-left and bottom-right corners."""
+ return wrap_IntRect( IntRect(deref(p0.thisptr), deref(p1.thisptr)) )
+
+ @classmethod
+ def from_intervals(cls, I, J):
+ """Create rectangle from two intervals representing its sides."""
+ return cy_IntRect( int(I.min()),
+ int(J.min()),
+ int(I.max()),
+ int(J.max()) )
+
+ @classmethod
+ def from_list(cls, lst):
+ """Create rectangle containing all points in list."""
+ if lst == []:
+ return cy_IntRect()
+ if len(lst) == 1:
+ return cy_IntRect(lst[0], lst[0])
+ ret = cy_IntRect(lst[0], lst[1])
+ for a in lst:
+ ret.expand_to(a)
+ return ret
+
+ #didn't manage to declare from_xywh for IntRect
+ @classmethod
+ def from_xywh(cls, x, y, w, h):
+ """Create rectangle from it's topleft point and dimensions."""
+ return cy_IntRect(int(x),
+ int(y),
+ int(x) + int(w),
+ int(y) + int(h) )
+
+ def __getitem__(self, Dim2 d):
+ """self[d]"""
+ return wrap_IntInterval( deref(self.thisptr)[d] )
+
+ def min(self):
+ """Get top-left point."""
+ return wrap_IntPoint( self.thisptr.i_min() )
+
+ def max(self):
+ """Get bottom-right point."""
+ return wrap_IntPoint( self.thisptr.i_max() )
+
+ def corner(self, unsigned int i):
+ """Get corners (modulo) indexed from 0 to 3."""
+ return wrap_IntPoint( self.thisptr.i_corner(i) )
+
+ def top(self):
+ """Get top coordinate."""
+ return self.thisptr.top()
+
+ def bottom(self):
+ """Get bottom coordinate."""
+ return self.thisptr.bottom()
+
+ def left(self):
+ """Get left coordinate."""
+ return self.thisptr.left()
+
+ def right(self):
+ """Get right coordinate."""
+ return self.thisptr.right()
+
+ def width(self):
+ """Get width."""
+ return self.thisptr.width()
+
+ def height(self):
+ """Get height."""
+ return self.thisptr.height()
+
+ def aspect_ratio(self):
+ """Get ratio between width and height."""
+ return self.thisptr.aspectRatio()
+
+ def dimensions(self):
+ """Get dimensions as IntPoint."""
+ return wrap_IntPoint( self.thisptr.i_dimensions() )
+
+ def midpoint(self):
+ """Get midpoint."""
+ return wrap_IntPoint( self.thisptr.i_midpoint() )
+
+ def area(self):
+ """Get area."""
+ return self.thisptr.area()
+
+ def has_zero_area(self):
+ """Test for area being zero."""
+ return self.thisptr.hasZeroArea()
+
+ def max_extent(self):
+ """Get bigger value from width, height."""
+ return self.thisptr.maxExtent()
+
+ def min_extent(self):
+ """Get smaller value from width, height."""
+ return self.thisptr.minExtent()
+
+ def intersects(self, cy_IntRect r):
+ """Check if rectangle intersects another rectangle."""
+ return self.thisptr.intersects(deref( r.thisptr ))
+
+ def contains(self, cy_IntPoint r):
+ """Check if rectangle contains point."""
+ return self.thisptr.contains( deref(r.thisptr) )
+
+ def contains_rect(self, cy_IntRect r):
+ """Check if rectangle contains another rect."""
+ return self.thisptr.contains( deref(r.thisptr) )
+
+ def set_left(self, IntCoord val):
+ """Set left coordinate."""
+ self.thisptr.setLeft(val)
+
+ def set_right(self, IntCoord val):
+ """Set right coordinate."""
+ self.thisptr.setRight(val)
+
+ def set_top(self, IntCoord val):
+ """Set top coordinate."""
+ self.thisptr.setTop(val)
+
+ def set_bottom(self, IntCoord val):
+ """Set bottom coordinate."""
+ self.thisptr.setBottom(val)
+
+ def set_min(self, cy_IntPoint p):
+ """Set top-left point."""
+ self.thisptr.setMin( deref( p.thisptr ) )
+
+ def set_max(self, cy_IntPoint p):
+ """Set bottom-right point."""
+ self.thisptr.setMax( deref( p.thisptr ))
+
+ def expand_to(self, cy_IntPoint p):
+ """Expand rectangle to contain point represented as tuple."""
+ self.thisptr.expandTo( deref( p.thisptr ) )
+
+ def union_with(self, cy_IntRect b):
+ """self = self | other."""
+ self.thisptr.unionWith(deref( b.thisptr ))
+
+ def expand_by(cy_IntRect self, x, y = None):
+ """Expand both intervals.
+
+ Either expand them both by one value, or each by different value.
+ """
+ if y is None:
+ if isinstance(x, cy_IntPoint):
+ self.thisptr.expandBy( deref( (<cy_IntPoint> x).thisptr ) )
+ else:
+ self.thisptr.expandBy( <IntCoord> x)
+ else:
+ self.thisptr.expandBy( <IntCoord> x,
+ <IntCoord> y)
+
+ def __add__(cy_IntRect self, cy_IntPoint p):
+ """Offset rectangle by point."""
+ return wrap_IntRect( deref(self.thisptr) + deref( p.thisptr ) )
+
+ def __sub__(cy_IntRect self, cy_IntPoint p):
+ """Offset rectangle by -point."""
+ return wrap_IntRect( deref(self.thisptr) - deref( p.thisptr ) )
+
+ def __or__(cy_IntRect self, cy_IntRect o):
+ """Return union of two rects - it's actually bounding rect of union."""
+ return wrap_IntRect( deref(self.thisptr) | deref( o.thisptr ))
+
+ def __richcmp__(cy_IntRect self, cy_IntRect o, int op):
+ """Rectangles are not ordered."""
+ if op == 2:
+ return deref(self.thisptr) == deref(o.thisptr)
+ if op == 3:
+ return deref(self.thisptr) != deref(o.thisptr)
+
+cdef cy_IntRect wrap_IntRect(IntRect p):
+ cdef IntRect* retp = new IntRect()
+ retp[0] = p
+ cdef cy_IntRect r = cy_IntRect.__new__(cy_IntRect)
+ r.thisptr = retp
+ return r
+
+
+
+cdef class cy_OptIntRect:
+
+ """Class representing optionally empty rect in with integer coordinates.
+
+ This class corresponds to OptIntRect in 2geom, and it tries to mimic
+ the behaviour of std::optional. In addition to OptIntRect methods,
+ this class passes calls for IntRect methods to underlying IntRect class,
+ or throws ValueError when it's empty.
+ """
+
+ cdef OptIntRect* thisptr
+
+ def __cinit__(self, x0=None, y0=None, x1=None, y1=None):
+ """Create OptIntRect from coordinates of top-left and bottom-right corners.
+
+ No arguments will result in empty rectangle.
+ """
+ if x0 is None:
+ self.thisptr = new OptIntRect()
+ else:
+ self.thisptr = new OptIntRect( int(x0),
+ int(y0),
+ int(x1),
+ int(y1) )
+
+ def __str__(self):
+ """str(self)"""
+ if self.isEmpty():
+ return "Empty OptIntRect"
+ return "OptIntRect with dimensions {}, topleft point {}".format(
+ str(self.Rect.dimensions()),
+ str(self.Rect.min()))
+
+ def __repr__(self):
+ """repr(self)"""
+ if self.isEmpty():
+ return "OptIntRect()"
+ return "OptIntRect({}, {}, {}, {})".format( str(self.Rect.left()),
+ str(self.Rect.top()),
+ str(self.Rect.right()),
+ str(self.Rect.bottom()))
+
+ def __dealloc__(self):
+ del self.thisptr
+
+ @classmethod
+ def from_points(cls, cy_IntPoint p0, cy_IntPoint p1):
+ """Create rectangle from it's top-left and bottom-right corners."""
+ return wrap_OptIntRect( OptIntRect(deref(p0.thisptr), deref(p1.thisptr)) )
+
+ @classmethod
+ def from_intervals(cls, I, J):
+ """Create rectangle from two intervals representing its sides."""
+ if hasattr(I, "isEmpty"):
+ if I.isEmpty():
+ return cy_OptIntRect()
+
+ if hasattr(J, "isEmpty"):
+ if J.isEmpty():
+ return cy_OptIntRect()
+
+ return wrap_OptIntRect( OptIntRect( int(I.min()),
+ int(J.min()),
+ int(I.max()),
+ int(J.max()) ) )
+
+ @classmethod
+ def from_rect(cls, r):
+ """Create OptIntRect from other, possibly empty, rectangle."""
+ if hasattr(r, "isEmpty"):
+ if r.isEmpty():
+ return cy_OptIntRect()
+ return cy_OptIntRect( r.min().x,
+ r.min().y,
+ r.max().x,
+ r.max().y )
+
+ @classmethod
+ def from_list(cls, lst):
+ """Create OptIntRect containing all points in the list.
+
+ Empty list will result in empty OptIntRect.
+ """
+ if lst == []:
+ return cy_OptIntRect()
+ if len(lst) == 1:
+ return cy_OptIntRect.from_points(lst[0], lst[0])
+ ret = cy_OptIntRect.from_points(lst[0], lst[1])
+ for a in lst:
+ ret.expand_to(a)
+ return ret
+
+ property Rect:
+ """Get underlying IntRect."""
+ def __get__(self):
+ return wrap_IntRect(self.thisptr.get())
+
+ def __bool__(self):
+ """OptIntRect is False only when it's empty."""
+ return not self.thisptr.isEmpty()
+
+ def is_empty(self):
+ """Check for OptIntRect containing no points."""
+ return self.thisptr.isEmpty()
+
+ def intersects(cy_OptIntRect self, other):
+ """Check if rectangle intersects another rectangle."""
+ if isinstance(other, cy_IntRect):
+ return self.thisptr.intersects( deref( (<cy_IntRect> other).thisptr ) )
+ elif isinstance(other, cy_OptIntRect):
+ return self.thisptr.intersects( deref( (<cy_OptIntRect> other).thisptr ) )
+
+ def contains(self, cy_IntPoint other):
+ """Check if rectangle contains point."""
+ return self.thisptr.contains( deref(other.thisptr) )
+
+ def contains_rect(cy_OptIntRect self, other):
+ """Check if rectangle contains another rectangle."""
+ if isinstance(other, cy_IntRect):
+ return self.thisptr.contains( deref( (<cy_IntRect> other).thisptr ) )
+ elif isinstance(other, cy_OptIntRect):
+ return self.thisptr.contains( deref( (<cy_OptIntRect> other).thisptr ) )
+
+
+ def union_with(cy_OptIntRect self, other):
+ """self = self | other."""
+ if isinstance(other, cy_IntRect):
+ self.thisptr.unionWith( deref( (<cy_IntRect> other).thisptr ) )
+ elif isinstance(other, cy_OptIntRect):
+ self.thisptr.unionWith( deref( (<cy_OptIntRect> other).thisptr ) )
+
+ def intersect_with(cy_OptIntRect self, other):
+ """self = self & other."""
+ if isinstance(other, cy_IntRect):
+ self.thisptr.intersectWith( deref( (<cy_IntRect> other).thisptr ) )
+ elif isinstance(other, cy_OptIntRect):
+ self.thisptr.intersectWith( deref( (<cy_OptIntRect> other).thisptr ) )
+
+ def expand_to(self, cy_IntPoint p):
+ """Expand rectangle to contain point."""
+ self.thisptr.expandTo( deref(p.thisptr) )
+
+ def __or__(cy_OptIntRect self, cy_OptIntRect other):
+ """Return union of two rects - it's actually bounding rect of union."""
+ return wrap_OptIntRect( deref(self.thisptr) | deref(other.thisptr) )
+
+ def __and__(cy_OptIntRect self, other):
+ """Return intersection of two rectangles."""
+ if isinstance(other, cy_IntRect):
+ return wrap_OptIntRect( deref(self.thisptr) & deref( (<cy_IntRect> other).thisptr) )
+ elif isinstance(other, cy_OptIntRect):
+ return wrap_OptIntRect( deref(self.thisptr) & deref( (<cy_OptIntRect> other).thisptr) )
+
+ def __richcmp__(cy_OptIntRect self, other, op):
+ """Rectangles are not ordered."""
+ if op == 2:
+ if isinstance(other, cy_IntRect):
+ return deref(self.thisptr) == deref( (<cy_IntRect> other).thisptr )
+ elif isinstance(other, cy_OptIntRect):
+ return deref(self.thisptr) == deref( (<cy_OptIntRect> other).thisptr )
+ elif op == 3:
+ if isinstance(other, cy_IntRect):
+ return deref(self.thisptr) != deref( (<cy_IntRect> other).thisptr )
+ elif isinstance(other, cy_OptIntRect):
+ return deref(self.thisptr) != deref( (<cy_OptIntRect> other).thisptr )
+
+ def _get_Rect_method(self, name):
+ def f(*args, **kwargs):
+ if self.is_empty():
+ raise ValueError("OptIntRect is empty.")
+ else:
+ return self.Rect.__getattribute__(name)(*args, **kwargs)
+ return f
+
+ def __getattr__(self, name):
+
+ Rect_methods = set(['area', 'aspect_ratio', 'bottom', 'contains',
+ 'contains_rect', 'corner', 'dimensions', 'expand_by', 'expand_to',
+ 'from_intervals', 'from_list', 'from_points', 'from_xywh',
+ 'has_zero_area', 'height', 'intersects', 'left', 'max',
+ 'max_extent', 'midpoint', 'min', 'min_extent', 'right',
+ 'set_bottom', 'set_left', 'set_max', 'set_min', 'set_right',
+ 'set_top', 'top', 'union_with', 'width'])
+
+ if name in Rect_methods:
+ return self._get_Rect_method(name)
+ else:
+ raise AttributeError("OptIntRect instance has no attribute \"{}\"".format(name))
+
+ def _wrap_Rect_method(self, name, *args, **kwargs):
+ if self.isEmpty():
+ raise ValueError("OptIntRect is empty.")
+ else:
+ return self.Rect.__getattr__(name)(*args, **kwargs)
+
+ #declaring these by hand, because they take fixed number of arguments,
+ #which is enforced by cython
+
+ def __getitem__(self, i):
+ """self[d]"""
+ return self._wrap_Rect_method("__getitem__", i)
+
+ def __add__(self, other):
+ """Offset rectangle by point."""
+ return self._wrap_Rect_method("__add__", other)
+
+ def __sub__(self, other):
+ """Offset rectangle by -point."""
+ return self._wrap_Rect_method("__sub__", other)
+
+cdef cy_OptIntRect wrap_OptIntRect(OptIntRect p):
+ cdef OptIntRect* retp = new OptIntRect()
+ retp[0] = p
+ cdef cy_OptIntRect r = cy_OptIntRect.__new__(cy_OptIntRect)
+ r.thisptr = retp
+ return r
diff --git a/src/3rdparty/2geom/src/cython/cy2geom.pyx b/src/3rdparty/2geom/src/cython/cy2geom.pyx
new file mode 100644
index 0000000..f1ba7a6
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/cy2geom.pyx
@@ -0,0 +1,71 @@
+#Axis specifiers for Dim2
+X = 0
+Y = 1
+
+from _cy_primitives import cy_Angle as Angle
+from _cy_primitives import cy_AngleInterval as AngleInterval
+from _cy_primitives import cy_Point as Point
+from _cy_primitives import cy_Line as Line
+from _cy_primitives import cy_Ray as Ray
+from _cy_primitives import cy_IntPoint as IntPoint
+
+
+from _cy_rectangle import cy_Interval as Interval
+from _cy_rectangle import cy_OptInterval as OptInterval
+from _cy_rectangle import cy_IntInterval as IntInterval
+from _cy_rectangle import cy_OptIntInterval as OptIntInterval
+
+from _cy_rectangle import cy_GenericInterval as GenericInterval
+from _cy_rectangle import cy_GenericOptInterval as GenericOptInterval
+
+from _cy_rectangle import cy_GenericRect as GenericRect
+
+from _cy_rectangle import cy_Rect as Rect
+from _cy_rectangle import cy_OptRect as OptRect
+from _cy_rectangle import cy_IntRect as IntRect
+from _cy_rectangle import cy_OptIntRect as OptIntRect
+
+
+from _cy_affine import cy_Affine as Affine
+from _cy_affine import cy_Translate as Translate
+from _cy_affine import cy_Rotate as Rotate
+from _cy_affine import cy_VShear as VShear
+from _cy_affine import cy_HShear as HShear
+from _cy_affine import cy_Scale as Scale
+from _cy_affine import cy_Zoom as Zoom
+
+from _cy_affine import cy_Eigen as Eigen
+
+from _cy_curves import cy_Curve as Curve
+
+from _cy_curves import cy_Linear as Linear
+from _cy_curves import cy_SBasis as SBasis
+from _cy_curves import cy_SBasisCurve as SBasisCurve
+
+from _cy_curves import cy_Bezier as Bezier
+from _cy_curves import cy_BezierCurve as BezierCurve
+from _cy_curves import cy_LineSegment as LineSegment
+from _cy_curves import cy_QuadraticBezier as QuadraticBezier
+from _cy_curves import cy_CubicBezier as CubicBezier
+
+from _cy_curves import cy_HLineSegment as HLineSegment
+from _cy_curves import cy_VLineSegment as VLineSegment
+
+from _cy_curves import cy_EllipticalArc as EllipticalArc
+#Wrap this? It doesn't fit into python's dynamic nature and
+#BezierCurve covers most of it's functionality
+#Maybe implement constructors for BezierCurve similar to those
+#seen in BezierCurveN
+#TODO
+#from _cy_curves import cy_BezierCurveN as BezierCurveN
+
+from _cy_curves import cy_lerp as lerp
+from _cy_curves import cy_reverse as reverse
+#~ from _cy_curves import cy_level_sets as level_sets
+
+
+from _cy_path import cy_Path as Path
+
+
+from _cy_conicsection import cy_Circle as Circle
+from _cy_conicsection import cy_Ellipse as Ellipse
diff --git a/src/3rdparty/2geom/src/cython/report.md b/src/3rdparty/2geom/src/cython/report.md
new file mode 100644
index 0000000..e1f8353
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/report.md
@@ -0,0 +1,237 @@
+# State of cython Bindings
+
+This report summarizes work done on [lib2geom][2g] cython bindings during
+GSoC 2012 mostly from technical standpoint. It should serve for anyone
+doing any further work on these bindings, and for me to help my memory.
+
+Prior to the project, there were bindings using boost.python. These
+bindigs, however, uncovered only part of the lib2geom functionality and
+were not actively developed. I decided to go for a fresh start using
+[cython][cy]. Cython is programming language capable of calling C and C++
+methods and making so-called "extension types", which act as python
+classes. Reasons for choosing python include bit of experience I had with
+it, its cleanliness and activity in development.
+
+## Overview of Bindings
+
+All work was done in [trunk][tr], since it mostly added new functionality
+without altering existing code. Whole bindings are located in directory
+
+ 2geom_dir/src/2geom/cython-bindings
+
+Code is located in files ending with `.pxd` and `.pyx`, roughly cython's
+equivalent of header and implementation files. Classes in cython are
+divided into logical groups, which are wrapped in corresponding classes.
+cy2geom.pyx imports all classes and methods, and it's what one sees after
+
+ >>> import cy2geom
+
+In addition to this, there are some C++ files, necessary to wrap some of
+the code for cython, unit-tests covering most of the functionality and
+wrapper.py script, used to skip tedious part of creating extension types.
+
+Building of bindings was integrated with cmake, which is used to build
+the bindings, using [thewext's code][cm].
+
+I will now describe files/logical groups of them, their significance and
+state. I will try to write down most of the technical non-trivialities that
+I encountered.
+
+Pattern used for wrapping all classes is taken from cython docs and various
+other cython bindings. In .pxd file C++ classes, methods and functions are
+declared. In corresponding .pyx file there is an extension type which holds
+pointer (called `thisptr`) to it's underlying C++ class. Instance of this
+class is created with cython's `__cinit__`, and deleted with `__dealloc__`.
+Methods of class are called with `self.thisptr.methodname`, which cython
+translates to `thisptr->methodname`. Argument are stripped of their python
+wrapping using `deref(arg.thisptr)`, or they are translated automatically
+(these are basic numerical types).
+
+There is a function for each class, named `wrap_classname()`, which takes
+C++ instance and creates new python object around it.
+
+## `_common_decl`
+These files (.pxd/.pyx) include basic declarations, common to all files.
+Functions for creating and wrapping `vector[double]` should become redundant
+in next cython release (0.17), since it should do this conversion
+automatically.
+
+All extension types (cdef classes) have prefix `_cy_`, to avoid clash with
+C++ classes. This is removed when importing to `_common_decl.pyx`, but is still
+somewhat visible to the user of bindings, for example in traces. Other
+option would be renaming the C++ classes.
+
+## `_cy_primitives`
+Geometric primitives are wrapped here. These are relatively simple, few
+things that are worth mentioning are:
+
+* Some of the methods for Line and Ray could be rewritten using properties.
+* General points about exceptions, docstrings and classmethod apply here.
+
+## `_cy_rectangle`
+These files include intervals and rectangles, which all inherit from
+`GenericInterval[C]` or `GenericRect[C]`, respectively.
+
+For intervals, classes Interval and IntInterval are wrapped, with added
+methods for interval too. Opt variants are supported by rewriting
+`__getattr__` method. When calling the method that Interval provides,
+OptInterval checks whether it's not empty and passes arguments to Interval's
+method. If it is empty, it will raise ValueError. Due to this, Interval's
+method do not appear in OptInterval's namespace, which might be not ideal.
+
+GenericInterval is supported by setting the template type to WrappedPyObject,
+defined in `wrapped-pyobject.h`. This thin wrapper of `PyObject *` overloads
+operators to support arithmetic operations, comparisons and similar. When
+adding two WrappedPyObjects, these objects call corresponding addition using
+Python's C-API. This is a bit unstable feature, because it still leaks these
+python objects, and propagating error from Python, through C-API to cython
+back to Python is not done yet correctly. However, constraints on
+parameter of GenericInterval's type are pretty tight - it has to support
+arithmetic operations within itself, multiplication by reals and has to be
+ordered (ordered linear space with multiplication and division between its
+elements), so having GenericInterval only with reals and integers covers most
+cases.
+
+For rectangles, situations is almost identical as for intervals. GenericRect,
+return 2-tuples as a points, which is a bit of disadvantage, because adding
+tuples doesn't add element-wise, but append them one after another. It might
+be convenient to implement PyPoint overloading this functionality.
+
+A bit problematic region is in comparing all the intervals and rectangles.
+Should every interval be comparable to every other type, Interval with
+OptIntInterval? This would probably require writing the logic in cython.
+
+GenericOptRect is not there yet, because I got GenericRect only working
+only recently. It should be, however, quick to add.
+
+## `_cy_affine`
+Affine and specialised transforms. This is in pretty good state. Eigenvalues
+seem to be a bit off sometimes.
+
+## `_cy_curves`
+All of the curves are wrapped here, together with functions like Linear,
+SBasis and Bezier.
+
+Curve implements method every curve should implement, but other curve
+classes do not inherit from Curve. This is mainly because of technical
+details, this inheritance would only add complexity to code. However, I
+might consider rewriting curves, so they would actually inherit from
+Curve, if this appears to be needed.
+
+State of functions and classmethods is a bit strange. I tried to copy
+2geom's methods, but there are differences for Beziers and SBasis
+polynomials - to name a few, SBasis implements multiplication with SBasis
+as a operator, but Bezier only as a function, or bounds are implemented
+as instance methods for Linear, but as a module level functions for Bezier
+and SBasis. In case I wasn't sure what to do with a method, I put it, as
+a classmethod, to corresponding class.
+
+BezierCurveN is not implemented. It would be major hurdle, as cython has
+problems with templated classes - one would have to declare each type
+separately. First three orders are wrapped, and BezierCurve, with variable
+degree, is also wrapped.
+
+`hacks.h` is used to go around cython's problems with integer template
+parameters.
+
+## `_cy_path`
+Path is wrapped here. Biggest problem with path was it's heavy use of
+iterators, which are not the same as python's iterators. In most of the
+cases, I replaced them with integers marking the position of iterator,
+and go to the position step-by-step. This makes potentially O(1) operations
+actually O(n) where n is size of Path. Best way to deal with this would be
+to allow iterators to be shifted by arbitrary number.
+
+Not everything is provided, but there should be enough functionality to
+have total control over Path's curves.
+
+## `_cy_conicsection`
+Circle and ellipse classes. ratQuad and xAx from conic-section should also
+go there.
+
+## `utils.py`
+Only a simple function to draw curve/path to Tk windows and regular
+N-agon creating function reside there, useful mainly for debugging
+
+## `wrapper.py`
+Script used to cut the most trivial part of creating bindings, writing
+.pxd declarations, extension type and other functions. It's pretty tailored
+into 2geom, but I guess after some work one could make it more generic.
+
+
+## General Issues
+Exceptions coming from C++ code are not handled yet, they actually crash
+the program. Simplest solution is adding `except +` after every method that
+possibly raises exceptions, but traces won't look that nice.
+
+cython has some kind of problem with docstrings, it doesn't write function's
+argument to them, just ellipsis. This can be addressed by specifying all
+arguments in the docstring.
+
+Design decision has been made to put most of function not belonging to any
+class to extension type's namespace using classmethods. Most apt extension
+type is chosen, distance(Point, Point) goes to Point class. Other options
+are making them check for all possible types (this is ugly and error-prone)
+or differentiating using different names, which is more or less the same as
+classmethods, just not that systematic
+
+## What's missing
+Piecewise missing and all of crossings/boolops stuff are biggest things
+that didn't make. Concerning Piecewise, I think best option is to
+implement only `Piecewise<SBasis>` and `Piecewise<D2<SBasis>>` as those are
+only ones actually useful (SBasis, Bezier and their D2 versions are AFAIK
+only classes implementing required concepts).
+
+Crossings are working, boolops not so much. Work on Shape and Region has
+been started.
+
+# Personal Notes
+I am also summarizing a bit on my personal experience with GSoC.
+
+## What Did I Learn
+I learned a lot, not only new technology, but also gained new perspective
+on long-time work.
+
+Speaking of technology, I am much more confident with cython, and I am not
+really scared of python C-API. I got a grasp of bazaar, CMake, python's
+unittest module and various (mainly template) C++ features, heavily used
+in 2geom.
+
+I got a grasp of what a polished product looks like, and I realize how
+hard is to get your product to that state. I can now appreciate testing,
+at first seemingly just a boring and not trivial chore, turned out to be
+very helpful both for my understanding of code and for making changes more
+quickly. I also read a lot about design of python API, what's idiomatic
+and what does various norms (PEPs) say about python.
+
+I think I never did something of this size before (not that monolithic),
+so I learned lot about my work habits and importance of both work ethic
+and taking a rest.
+
+## What I Liked & Disliked
+I liked mainly the process of learning new things. I disliked the really
+technical scope of this project - I can imagine more exciting things to
+work on than doing bindings, but I guess it doesn't hurt to have this kind
+of experience. I certainly won't spend my whole life doing only exciting
+things :)
+
+## What Would I Do Differently
+I would have planned a bit more. I like to write it on account of my
+inexperience, I felt many times that knowing how should final product
+look like would save me tons of work - this way, I approached state
+with which I was more-or-less content at the end of doing most of the tasks.
+Luckily, I got time to go through the code at the end, so I ended up
+correcting the largest mistakes.
+
+I would also discuss design of API bit more, since mapping the C++ sometimes
+turned out to be cumbersome from python's perspective. Often, I would spend
+lots of time thinking through some detail (Iterator for Path, std::optional,
+most of the templated classes), only doing ad-hoc solution at the end in
+order to I to keep progressing.
+
+Jan Pulmann - jan.pulmann@gmail.com
+
+[2g]: http://lib2geom.sourceforge.net/
+[cy]: http://www.cython.org/
+[cm]: https://github.com/thewtex/cython-cmake-example
+[tr]: https://code.launchpad.net/~lib2geom-hackers/lib2geom/trunk
diff --git a/src/3rdparty/2geom/src/cython/test-affine.py b/src/3rdparty/2geom/src/cython/test-affine.py
new file mode 100644
index 0000000..a020d73
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/test-affine.py
@@ -0,0 +1,249 @@
+import unittest
+from math import pi, sqrt, sin, cos
+from random import randint, uniform
+
+import cy2geom
+
+from cy2geom import Point, IntPoint
+from cy2geom import Line, Ray, Rect
+
+from cy2geom import Rect
+
+from cy2geom import Affine
+from cy2geom import Translate, Scale, Rotate, VShear, HShear, Zoom
+from cy2geom import Eigen
+
+class TestPrimitives(unittest.TestCase):
+ def affine(self, A, B):
+ c0, c1, c2, c3, c4, c5 = A[0], A[1], A[2], A[3], A[4], A[5]
+ C = Affine(c0, c1, c2, c3, c4, c5)
+ self.assertEqual(C, A)
+ E = Affine.identity()
+ self.assertEqual(C, C*E)
+ self.assertEqual(E*B, B)
+ self.assertEqual(E.det(), 1)
+
+ self.assertAlmostEqual(A.det(), c0*c3-c1*c2)
+ self.assertAlmostEqual(abs(A.det()), A.descrim2())
+ self.assertAlmostEqual(abs(A.det())**0.5, A.descrim())
+ #xor
+ self.assertFalse( A.flips() ^ (A.det() < 0) )
+
+ if A.is_singular():
+ self.assertAlmostEqual(A.det(), 0)
+ else:
+ self.assertTrue( Affine.are_near (A*A.inverse(), E) )
+ self.assertAlmostEqual(A.det(), 1/A.inverse().det())
+ self.assertEqual( A.x_axis(), Point(c0, c1) )
+ self.assertEqual( A.y_axis(), Point(c2, c3) )
+ self.assertEqual( A.translation(), Point(c4, c5) )
+
+ self.assertAlmostEqual(A.expansion_X(), A.x_axis().length())
+ self.assertAlmostEqual(A.expansion_Y(), A.y_axis().length())
+
+ if abs(A.expansion_X()) > 1e-7 and abs(A.expansion_Y()) > 1e-7:
+ A.set_expansion_X(2)
+ A.set_expansion_Y(3)
+ self.assertAlmostEqual(A.expansion_X(), 2)
+ self.assertAlmostEqual(A.expansion_Y(), 3)
+
+ A.set_identity()
+
+ self.assertTrue(A.is_identity())
+ self.assertTrue(A.is_translation())
+ self.assertFalse(A.is_nonzero_translation())
+ self.assertTrue(A.is_scale())
+ self.assertTrue(A.is_uniform_scale())
+ self.assertFalse(A.is_nonzero_scale())
+ self.assertFalse(A.is_nonzero_uniform_scale())
+ self.assertTrue(A.is_rotation())
+ self.assertFalse(A.is_nonzero_rotation())
+ self.assertTrue(A.is_HShear())
+ self.assertTrue(A.is_VShear())
+ self.assertFalse(A.is_nonzero_HShear())
+ self.assertFalse(A.is_nonzero_VShear())
+ self.assertTrue(A.is_zoom())
+
+ self.assertTrue(A.preserves_area() and A.preserves_angles() and A.preserves_distances())
+
+ self.assertFalse( A.flips() )
+ self.assertFalse( A.is_singular() )
+
+ A.set_X_axis(Point(c0, c1))
+ A.set_Y_axis(Point(c2, c3))
+
+ self.assertEqual(A.without_translation(), A)
+
+ A.set_translation(Point(c4, c5))
+ self.assertEqual(C, A)
+
+ self.assertAlmostEqual( (A*B).det(), A.det()*B.det() )
+
+ self.assertEqual( A.translation(), Point()*A )
+ self.assertEqual( Point(1, 1)*A, Point( c0+c2+c4, c1+c3+c5 ))
+
+ l = Line(Point(1, 1), 2)
+ self.assertEqual( (l.transformed(A)).origin(), l.origin()*A )
+ self.assertTrue( Line.are_near( l.point_at(3)*A, l.transformed(A) ) )
+
+ r = Ray(Point(2, 3), 4)
+ self.assertEqual( (r.transformed(A)).origin(), r.origin()*A )
+ self.assertTrue( Ray.are_near( r.point_at(3)*A, r.transformed(A) ) )
+
+
+
+ def test_affine(self):
+ al = []
+ for i in range(10):
+ al.append(Affine( uniform(-10, 10),
+ uniform(-10, 10),
+ uniform(-10, 10),
+ uniform(-10, 10),
+ uniform(-10, 10),
+ uniform(-10, 10)))
+ for A in al:
+ for B in al:
+ self.affine(A, B)
+
+ o = Point(2, 4)
+ v = Point(-1, 1)/sqrt(2)
+ l = Line.from_origin_and_versor(o, v)
+
+ R = Affine.reflection(v, o)
+ for i in range(100):
+ p = Point(randint(0, 100), randint(0, 100))
+ self.assertAlmostEqual(Line.distance(p, l), Line.distance(p*R, l))
+ self.assertTrue( Affine.are_near( R, R.inverse() ) )
+
+ self.affine(R, R.inverse())
+
+ def test_translate(self):
+ T = Translate()
+ U = Translate(Point(2, 4))
+ V = Translate(1, -9)
+
+ self.assertTrue(Affine(T).is_translation())
+ self.assertTrue(Affine(U).is_nonzero_translation())
+
+ self.assertEqual( (U*V).vector(), U.vector()+V.vector() )
+ self.assertEqual( U.inverse().vector(), -U.vector() )
+ self.assertEqual(T, Translate.identity())
+ self.assertEqual( U.vector(), Point(U[0], U[1]) )
+
+ self.affine(Affine(V), Affine(U))
+ self.affine(Affine(U), Affine(V))
+
+ r = Rect.from_points( Point(0, 2), Point(4, 8) )
+
+ self.assertEqual( ( r*(U*V) ).min(), r.min()+U.vector()+V.vector())
+
+ def test_scale(self):
+ S = Scale()
+ T = Scale( Point (3, 8) )
+ U = Scale( -3, 1)
+ V = Scale(sqrt(2))
+
+ self.assertTrue( Affine(T).is_scale() )
+ self.assertTrue( Affine(T).is_nonzero_scale() )
+ self.assertTrue( Affine(V).is_nonzero_uniform_scale())
+
+ self.assertEqual( (T*V).vector(), T.vector()*sqrt(2) )
+ self.assertEqual( (T*U)[0], T[0]*U[0] )
+ self.assertAlmostEqual( 1/U.inverse()[1], U[1] )
+
+ r = Rect.from_points( Point(0, 2), Point(4, 8) )
+ self.assertAlmostEqual((r*V).area(), 2*r.area())
+ self.assertFalse(Affine(U).preserves_area())
+ self.assertTrue(Affine(V).preserves_angles())
+
+ self.affine(Affine(T), Affine(U))
+ self.affine(Affine(U), Affine(V))
+ self.affine(Affine(V), Affine(T))
+
+ def test_rotate(self):
+ R = Rotate()
+ S = Rotate(pi/3)
+ T = Rotate(Point( 1, 1 ))
+ U = Rotate( -1, 1 )
+
+ self.assertTrue(S.vector(), Point(cos(pi/3), sin(pi/3)) )
+ self.assertEqual( Point(T[0], T[1]), T.vector() )
+ self.assertTrue( Affine.are_near( Rotate.from_degrees(60), S ) )
+ self.assertEqual(R, Rotate.identity())
+ self.assertTrue( Point.are_near( ( S * T ).vector(),
+ Point( cos( pi/3 + pi/4 ), sin( pi/3 + pi/4 ) ) ) )
+
+ self.affine( Affine(R), Affine(S))
+ self.affine( Affine(S), Affine(T))
+ self.affine( Affine(T), Affine(U))
+ self.affine( Affine(U), Affine(R))
+
+ def test_shear(self):
+ H = HShear(2.98)
+ V = VShear(-sqrt(2))
+
+ self.assertAlmostEqual(H.factor(), 2.98)
+ self.assertAlmostEqual(V.inverse().factor(), sqrt(2))
+
+ G = HShear.identity()
+ H.set_factor(0)
+ self.assertEqual(G, H)
+
+ G.set_factor(2)
+ H.set_factor(4)
+ self.assertAlmostEqual((G*H).factor(), G.factor()+H.factor())
+
+ W = VShear.identity()
+ V.set_factor(0)
+ self.assertEqual(W, V)
+
+ W.set_factor(-2)
+ V.set_factor(3)
+ self.assertAlmostEqual((W*V).factor(), W.factor()+V.factor())
+
+ def test_zoom(self):
+ Z = Zoom(3)
+ Y = Zoom(translate=Translate(3,2))
+ X = Zoom(sqrt(3), Translate(-1, 3))
+
+ self.assertEqual(
+ Zoom(Z.scale(), Translate(Y.translation())),
+ Y*Z )
+
+ Z.set_translation(Y.translation())
+ Y.set_scale(Z.scale())
+ self.assertEqual(Z, Y)
+
+ self.assertEqual(Y.inverse().scale(), 1/Y.scale())
+
+ r = Rect.from_xywh( 1, 1, 3, 6)
+ q = Rect.from_xywh( 0, -1, 1, 2)
+ W = Zoom.map_rect(r, q)
+
+ self.assertAlmostEqual(W.scale()*r.width(), q.width())
+ self.assertTrue(Point.are_near(
+ r.min()+W.translation(),
+ q.min()))
+ def test_eigen(self):
+ #TODO looks like bug in eigen - (1, 0) should be eigenvector too
+ #~ S = Scale(1, 2)
+ #~ E_S = Eigen(S)
+ #~ print E_S.vectors, E_S.values
+ #~ print Affine(S)
+ #~ for i in E_S.vectors:
+ #~ print i, i*S, Point(1, 0) * S
+
+ B = Affine(-2, 2, 2, 1, 0, 0)
+ G1 = Eigen(B)
+ G2 = Eigen( [[-2, 2], [2, 1]] )
+
+ self.assertAlmostEqual(min(G1.values), min(G2.values))
+ self.assertAlmostEqual(max(G1.values), max(G2.values))
+
+ if Point.are_near( G1.vectors[0]*G1.values[0], G1.vectors[0]*B ):
+ self.assertTrue( Point.are_near( G1.vectors[1]*G1.values[1], G1.vectors[1]*B ) )
+ else:
+ self.assertTrue( Point.are_near( G1.vectors[1]*G1.values[0], G1.vectors[1]*B ) )
+ self.assertTrue( Point.are_near( G1.vectors[0]*G1.values[1], G1.vectors[0]*B ) )
+
+unittest.main()
diff --git a/src/3rdparty/2geom/src/cython/test-conicsection.py b/src/3rdparty/2geom/src/cython/test-conicsection.py
new file mode 100644
index 0000000..9fc1c20
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/test-conicsection.py
@@ -0,0 +1,137 @@
+import unittest
+import math
+from random import randint, uniform
+
+import cy2geom
+
+from cy2geom import Point, IntPoint
+from cy2geom import Interval, IntInterval, OptInterval, OptIntInterval
+
+from cy2geom import Affine
+from cy2geom import Translate, Scale, Rotate, VShear, HShear, Zoom
+from cy2geom import Eigen
+
+from cy2geom import Curve
+from cy2geom import Linear
+from cy2geom import SBasis, SBasisCurve
+from cy2geom import Bezier, BezierCurve
+
+from cy2geom import LineSegment, QuadraticBezier, CubicBezier
+from cy2geom import HLineSegment, VLineSegment
+
+from cy2geom import EllipticalArc
+
+from cy2geom import Path
+
+from cy2geom import Circle, Ellipse
+
+
+class TestPrimitives(unittest.TestCase):
+ def test_circle(self):
+ C = Circle()
+ self.assertEqual(C.center(), Point())
+
+ D = Circle(Point(2, 4), 2)
+ Dp = D.getPath()
+ self.assertEqual(D.center(), Point(2, 4))
+ self.assertEqual(D.ray(), 2)
+
+ for i in range(11):
+ t = i/10.0
+ #Circle approximated by SBasis is not perfect
+ self.assertAlmostEqual( abs(D.center()-Dp(t)), D.ray(), delta=0.1 )
+
+ half_circle = D.arc(Dp(0), Dp(0.3), Dp(0.5))
+
+ self.assertTrue(half_circle.is_SVG_compliant())
+
+ self.assertAlmostEqual(Dp(0.25), half_circle(0.5), delta=0.1)
+
+ points = [Point(2, 5), Point(1, 4), Point(9, 0)]
+ D.set_points(points)
+ for p in points:
+ self.assertAlmostEqual( abs(p-D.center()), D.ray() )
+ Dc = Circle.from_points(points)
+ self.assertAlmostEqual(Dc.center(), D.center())
+ self.assertAlmostEqual(Dc.ray(), D.ray())
+
+ coeffs = (2, 4, 1, -4)
+ E = Circle.from_coefficients(*coeffs)
+ def param(x, y):
+ A, B, C, D = coeffs
+ return A*x**2 + A*y**2 + B*x + C*y + D
+ Ec = E.arc(E.center()+Point(E.ray(), 0), E.center()-Point(E.ray(), 0), E.center()+Point(E.ray(), 0) )
+ for i in range(11):
+ t = i/10.0
+ self.assertAlmostEqual(param(Ec.value_at(t, 0), Ec.value_at(t, 1)), 0)
+
+ E.set(3, 5, 9)
+ self.assertAlmostEqual(E.center(), Point(3, 5))
+ self.assertAlmostEqual(E.ray(), 9)
+
+ E.set_coefficients(*coeffs)
+ #radius and center from parametric equation
+ ca = float(coeffs[1])/coeffs[0]
+ cb = float(coeffs[2])/coeffs[0]
+ cc = float(coeffs[3])/coeffs[0]
+ self.assertAlmostEqual( 4*E.ray()**2 , ca**2 + cb**2 -4*cc )
+ self.assertAlmostEqual( E.center(), -Point(ca, cb)/2)
+
+ def test_ellipse(self):
+ #TODO: maybe a bug in arc? get_curve(F) returns different ellipse than F
+ def get_curve(ellipse):
+ p = Point(ellipse.ray(0), 0)*Rotate(ellipse.rot_angle())
+ return ellipse.arc(ellipse.center()+p, ellipse.center()-p, ellipse.center()+p*(1-1e-7))
+ E = Ellipse()
+ self.assertAlmostEqual(E.center(), Point())
+ self.assertAlmostEqual(E.ray(0), 0)
+ self.assertAlmostEqual(E.ray(1), 0)
+
+ F = Ellipse(Point(), 3, 2, 0)
+ self.assertAlmostEqual(F.center(), Point())
+ self.assertAlmostEqual(F.ray(0), 3)
+ self.assertAlmostEqual(F.ray(1), 2)
+ self.assertAlmostEqual(F.rot_angle(), 0)
+ # x**2/9 + y**2/4 = 1
+ self.assertAlmostEqual(F.implicit_form_coefficients()[0], 1/9.0)
+ self.assertAlmostEqual(F.implicit_form_coefficients()[2], 1/4.0)
+ self.assertAlmostEqual(F.implicit_form_coefficients()[5], -1)
+
+ coeffs = (1/3.0, 0, 1/16.0, 1, 0, -1/4.0)
+ G = Ellipse.from_coefficients(*coeffs)
+ self.assertAlmostEqual(G.center(), Point(-3/2.0, 0))
+ self.assertAlmostEqual(G.ray(0), math.sqrt(3))
+ self.assertAlmostEqual(G.ray(1), 4)
+ self.assertAlmostEqual(G.rot_angle(), 0)
+
+ points = [Point(1, 2), Point(2 ,9), Point(0, 3), Point(-3, 8), Point(5, 8)]
+ G.set_points(points)
+ coeffs_G = tuple(G.implicit_form_coefficients())
+ def paramG(x, y):
+ A, B, C, D, E, F = coeffs_G
+ return A*x**2 + B*x*y + C*y**2 + D*x + E*y + F
+ for p in points:
+ self.assertAlmostEqual(paramG(p.x, p.y), 0)
+
+ G2 = Ellipse.from_points(points)
+ coeffs_G2 = tuple(G.implicit_form_coefficients())
+ def paramG2(x, y):
+ A, B, C, D, E, F = coeffs_G2
+ return A*x**2 + B*x*y + C*y**2 + D*x + E*y + F
+ for p in points:
+ self.assertAlmostEqual(paramG2(p.x, p.y), 0)
+
+ E.set_coefficients(*coeffs_G2)
+ for a1, a2 in zip(E.implicit_form_coefficients(), G2.implicit_form_coefficients()):
+ self.assertAlmostEqual(a1, a2)
+
+ H = Ellipse.from_circle(Circle(Point(2, 8), 5))
+ self.assertAlmostEqual(H.center(), Point(2, 8))
+ self.assertAlmostEqual(H.ray(0), 5)
+ self.assertAlmostEqual(H.ray(1), 5)
+
+ Ft = F.transformed( Rotate(math.pi/2) )
+ self.assertAlmostEqual(F.ray(0), Ft.ray(1))
+ self.assertAlmostEqual(F.ray(1), Ft.ray(0))
+
+unittest.main()
diff --git a/src/3rdparty/2geom/src/cython/test-curves.py b/src/3rdparty/2geom/src/cython/test-curves.py
new file mode 100644
index 0000000..8f9b870
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/test-curves.py
@@ -0,0 +1,458 @@
+import unittest
+import math
+from random import randint, uniform
+
+import cy2geom
+
+from cy2geom import Angle
+from cy2geom import Point, IntPoint
+from cy2geom import Line, Ray, Rect
+from cy2geom import Interval, IntInterval, OptInterval, OptIntInterval
+
+
+from cy2geom import Affine
+from cy2geom import Translate, Scale, Rotate, VShear, HShear, Zoom
+from cy2geom import Eigen
+
+from cy2geom import Linear
+from cy2geom import SBasis, SBasisCurve
+from cy2geom import Bezier, BezierCurve
+from cy2geom import lerp
+
+from cy2geom import LineSegment, QuadraticBezier, CubicBezier
+from cy2geom import HLineSegment, VLineSegment
+
+from cy2geom import EllipticalArc
+
+class TestPrimitives(unittest.TestCase):
+ def test_linear(self):
+ L = Linear(0, 1)
+ M = Linear(2)
+ N = Linear()
+ self.assertEqual( (L+M), L+2 )
+ self.assertEqual( (L-M), L-2 )
+ self.assertAlmostEqual(L(0.5), lerp(.5, 0, 1))
+ #~ self.assertTrue(N.is_zero())
+ self.assertTrue(M.is_constant())
+ self.assertTrue(L.is_finite())
+ self.assertAlmostEqual(L(0), L.at0())
+ self.assertAlmostEqual(L(1), L.at1())
+ self.assertAlmostEqual(L.value_at(0.3), L(0.3))
+ self.assertTrue( isinstance(M.to_SBasis(), SBasis ))
+
+ self.assertAlmostEqual(L.tri(), L(1) - L(0))
+ self.assertAlmostEqual(L.hat(), (L(1) + L(0))/2)
+
+ for i in range(11):
+ t = i/10.0
+ self.assertTrue(L.bounds_exact().Interval.contains(L(t)))
+ self.assertTrue(L.bounds_fast().Interval.contains(L(t)))
+ self.assertTrue(L.bounds_local(t-0.05, t+0.05).Interval.contains(L(t)))
+ self.assertAlmostEqual(lerp(t, 0, 4), t*4)
+ self.assertAlmostEqual(L(t), cy2geom.reverse(L)(1-t))
+ self.assertAlmostEqual( L(t)*t, (L*t)(t) )
+ self.assertAlmostEqual( L(t)+t, (L+t)(t) )
+ self.assertAlmostEqual( L(t)-t, (L-t)(t) )
+ self.assertAlmostEqual( -( L(t) ), (-L)(t) )
+ self.assertAlmostEqual( (L/2)(t), L(t)/2 )
+
+ def test_sBasis(self):
+ S = SBasis()
+ T = SBasis(2)
+ U = SBasis(1, 7)
+ V = SBasis.from_linear( Linear(2, 8) )
+
+ self.assertEqual(V[0], Linear(2, 8))
+ self.assertEqual(V.back(), Linear(2, 8))
+
+ #~ self.assertTrue(S.empty())
+ self.assertFalse(T.empty())
+
+ T.pop_back()
+ self.assertTrue(T.empty())
+
+ self.assertEqual(S.size(), 0)
+ self.assertEqual(U.size(), 1)
+ self.assertEqual((U*V).size(), 2)
+
+ T.resize(1, Linear(2, 3))
+ self.assertEqual(T[0], Linear(2, 3))
+ T.clear()
+ self.assertTrue(T.empty())
+ #TODO
+ #~ T.reserve(5)
+ #~ print T.size()
+ self.assertEqual(V.at(0), V[0])
+ self.assertEqual(V, U+1)
+ self.assertNotEqual(V, U)
+ self.assertTrue(T.is_zero())
+ self.assertTrue(SBasis(1).is_constant())
+ def f(A, B):
+ return (-A)*(A+B*2.2)*(A*B-B*B/3)
+ W = f(U, V)
+ self.assertAlmostEqual(W(0), W.at0())
+ self.assertAlmostEqual(W(1), W.at1())
+
+ for i in range(11):
+ t = i/10.0
+ self.assertAlmostEqual(W(t), W.value_at(t))
+ self.assertAlmostEqual(W(t), f(U(t), V(t)))
+
+ vd_UV = (U*V).value_and_derivatives(t, 1)
+ vd_U = U.value_and_derivatives(t, 1)
+ vd_V = V.value_and_derivatives(t, 1)
+ self.assertAlmostEqual( vd_UV[1], vd_U[1]*V(t)+U(t)*vd_V[1] )
+
+ self.assertAlmostEqual( U(V)(t), U(V(t)) )
+ self.assertEqual(T.degrees_of_freedom(), 0)
+ self.assertEqual(U.degrees_of_freedom(), 2)
+
+ self.assertEqual(T, T.to_SBasis())
+
+ U2 = SBasis(U(0), U(1))
+ U2.resize(10)
+ self.assertNotEqual(U2, U)
+ U2.truncate(U.size())
+ self.assertEqual(U2, U)
+ #TODO: normalize()
+ sL = Linear.sin(Linear(0, 1), 3)
+ cL = Linear.cos(Linear(0, 1), 3)
+ sqrtU = SBasis.sqrt( U, 3 )
+ rL = Linear.reciprocal(Linear(1,2), 3)
+ # cy2geom.inverse seems to return nans for degrees > 1
+ #~ asin = cy2geom.inverse( cy2geom.sqrt( SBasis(Linear(0, 1)), 3 ), 1)
+ for i in range(11):
+ t = i/10.0
+ self.assertAlmostEqual(sL(t), math.sin(t))
+ self.assertAlmostEqual(cL(t), math.cos(t))
+ #cy2geom.sqrt is not that precise
+ self.assertAlmostEqual(sqrtU(t), math.sqrt(U(t)), places = 1)
+ self.assertAlmostEqual(rL(t), 1/(1+t), places = 1 )
+ #~ self.assertAlmostEqual( asin(t), math.asin(t) )
+ self.assertAlmostEqual( SBasis.compose(U, V)(t), U(V)(t) )
+ self.assertAlmostEqual( SBasis.divide(U, V, 3)(t), U(t)/V(t), places = 1)
+
+ self.assertAlmostEqual( SBasis.derivative(SBasis.integral(W))(t), W(t))
+ self.assertAlmostEqual( cy2geom.reverse(W)(t), W(1-t) )
+ self.assertAlmostEqual( SBasis.multiply(U, V)(t), (U*V)(t))
+ #TODO looks like bug in 2geom
+ #~ print cy2geom.multiply_add(U, V, W)(t), (U*V+W)(t)
+ self.assertAlmostEqual( SBasis.multiply_add(U, W, V)(t), (U*W+V)(t))
+
+ self.assertTrue( SBasis.bounds_exact(U).Interval.contains(U(t)) )
+ self.assertTrue( SBasis.bounds_fast(U).Interval.contains(U(t)) )
+ self.assertTrue( SBasis.bounds_local(U, OptInterval(t-0.05, t+0.05)).Interval.contains(U(t)) )
+
+
+ for r in SBasis.roots(W):
+ self.assertAlmostEqual(W(r), 0)
+ for r in SBasis.roots(W, Interval(0, 0.7)):
+ self.assertAlmostEqual(W(r), 0)
+ self.assertTrue(Interval(0, 0.7).contains(r))
+
+ levels = [0, 3, 22, -21]
+ for i, roots in enumerate( SBasis.multi_roots(W, levels) ):
+ level = levels[i]
+ for r in roots:
+ self.assertAlmostEqual(W(r), level)
+
+ self.assertEqual(SBasis.valuation(W), 0)
+ #TODO: why is this still 0?
+ #~ print cy2geom.valuation(cy2geom.shift(W, 6))
+ self.assertEqual( U[0], SBasis.shift(U, 2)[2] )
+
+ for I in SBasis.level_set(W, 2, tol = 1e-7):
+ self.assertAlmostEqual( W(I.mid()), 2 )
+ for I in SBasis.level_set(W, Interval(0, 1), tol = 1e-7, vtol = 1e-7):
+ self.assertTrue( 0 <= W(I.begin()) <= 1 )
+ self.assertTrue( 0 <= W(I.mid()) <= 1 )
+ self.assertTrue( 0 <= W(I.end()) <= 1 )
+
+ def test_bezier(self):
+ B = Bezier()
+ C = Bezier(2)
+ D = Bezier(2, 4)
+ E = Bezier(1, 3, 9)
+ F = Bezier(-2, 5, -1, 2)
+ self.assertTrue( B.is_zero() )
+ self.assertTrue( C.is_constant() )
+ self.assertTrue( D.is_finite() )
+ C.clear()
+ self.assertEqual(D.degree(), 1)
+ self.assertEqual(E.at0(), 1)
+ self.assertEqual(E.at1(), 9)
+ self.assertEqual(E[2], 9)
+ for i in range(11):
+ t = i/10.0
+ self.assertAlmostEqual( D(t), lerp(t, 2, 4) )
+ self.assertAlmostEqual( D(t), D.value_at(t))
+ self.assertAlmostEqual( D.value_and_derivatives(t, 0)[0], D(t) )
+ self.assertAlmostEqual( D.value_and_derivatives(t, 1)[1], Bezier.derivative(D)(t) )
+ self.assertAlmostEqual( Bezier.integral(D).value_and_derivatives(t, 1)[1], D(t) )
+ #~ self.assertAlmostEqual( D.elevate_degree().reduce_degree()(t), D(t) )
+ self.assertAlmostEqual( (D+2)(t), D(t)+2 )
+ self.assertAlmostEqual( (D-1)(t), D(t)-1 )
+ self.assertAlmostEqual( (D*2)(t), D(t)*2 )
+ self.assertAlmostEqual( (D/4)(t), D(t)/4 )
+ self.assertTrue( Bezier.bounds_fast(F).Interval.contains(F(t)) )
+ self.assertTrue( Bezier.bounds_exact(F).Interval.contains(F(t)) )
+ self.assertTrue( Bezier.bounds_local(F, OptInterval(t-0.05, t+0.05)).Interval.contains(F(t)) )
+ for r in F.roots():
+ self.assertAlmostEqual(F(r), 0)
+ #TODO: bug in 2geom?
+ #~ for r in F.roots(Interval(0.1, 0.8)):
+ #~ self.assertAlmostEqual(F(r), 0)
+ #~ self.assertTrue( 0.1 <= r <= 0.8 )
+ self.assertIsInstance(F.forward_difference(1), Bezier)
+ self.assertIsInstance(F.elevate_degree(), Bezier)
+ self.assertIsInstance(E.reduce_degree(), Bezier)
+ #F.reduce_degree() fails with
+ # *** glibc detected *** python2: malloc(): memory corruption:
+ self.assertIsInstance(F.elevate_to_degree(4), Bezier)
+ self.assertIsInstance(F.deflate(), Bezier)
+ S = F.to_SBasis()
+ self.assertIsInstance(S, SBasis)
+ for i in range(11):
+ t = i/10.0
+ self.assertAlmostEqual(S(t), F(t))
+
+ def curve(self, C):
+ self.assertAlmostEqual(C.initial_point(), C(0))
+ self.assertAlmostEqual(C.final_point(), C.point_at(1))
+ #Doesn't have to be true
+ #~ if C.length() > 0.01:
+ #~ self.assertFalse(C.is_degenerate())
+
+ if C.is_degenerate():
+ #trivial special case
+ return
+
+ for i in range(11):
+ t = i/10.0
+ self.assertAlmostEqual(C(t).x, C.point_at(t).x)
+ self.assertAlmostEqual(C(t).y, C.value_at(t, 1))
+ self.assertEqual( C(t), C.point_and_derivatives(t, 1)[0] )
+ self.assertTrue( C.bounds_exact().contains(C(t)) )
+ self.assertTrue( C.bounds_fast().contains(C(t)) )
+ #TODO why this works only with degree = 0?
+ if C.bounds_local(OptInterval(t-0.05, t+0.05), 0
+ ) and (
+ C.bounds_local(OptInterval(t-0.05, t+0.05), 0).Rect.area() > 1e-10):
+ #ruling out too small rectangles, they have problems with precision
+ self.assertTrue( C.bounds_local( OptInterval(t-0.05, t+0.05), 0 ).Rect.contains(C(t)))
+ D = C.duplicate()
+
+ D.set_initial(Point())
+ self.assertAlmostEqual(D.initial_point(), Point())
+
+ D.set_final(Point(1, 1))
+ self.assertAlmostEqual(D.final_point(), Point(1, 1))
+
+ A = Affine( uniform(-10, 10),
+ uniform(-10, 10),
+ uniform(-10, 10),
+ uniform(-10, 10),
+ uniform(-10, 10),
+ uniform(-10, 10))
+ E = C.transformed(A)
+ for i in range(11):
+ t = i/10.0
+ # self.assertAlmostEqual( E(t), C(t)*A )
+ G1 = C.portion(0.2, 0.8)
+ G2 = C.portion( interval=Interval(2, 8)/10 )
+ self.assertAlmostEqual( G1(0), C(0.2) )
+ self.assertAlmostEqual( G2(0.5), C( lerp(0.5, 0.2, 0.8) ))
+ self.assertAlmostEqual( G1(1), G2(1) )
+
+ for i in range(11):
+ t = i/10.0
+ self.assertAlmostEqual( C.reverse()(t), C(1-t) )
+ self.assertAlmostEqual( C.point_and_derivatives(0.3, 1)[1], C.derivative()(0.3) )
+
+ self.assertAlmostEqual( C.nearest_time(C(0)), 0 )
+ self.assertAlmostEqual( C( C.nearest_time(C(0.5), interval=Interval(0.2, 0.5)) ), C(0.5) )
+ self.assertAlmostEqual( C( C.nearest_time(C(0.5), 0.2, 0.5) ), C(0.5) )
+ for p in C.all_nearest_times( C(0), 0, 1):
+ self.assertEqual(C(p), C(0))
+ for p in C.all_nearest_times( C(1), interval=Interval(0, 1)):
+ self.assertEqual(C(p), C(1))
+ for r in C.roots(0, 0):
+ self.assertAlmostEqual(C.value_at(r, 0), 0)
+
+ self.assertGreaterEqual(C.length(), abs(C(1) - C(0)))
+ self.assertEqual(C.winding(Point()), int(C.winding(Point())) )
+ self.assertAlmostEqual( C.unit_tangent_at(0.5),
+ Point.unit_vector(C.derivative()(0.5)) )
+ self.assertTrue(isinstance(C.to_SBasis()[0], SBasis))
+
+ def test_sBasisCurve(self):
+ S = SBasisCurve(SBasis(0, 2), SBasis(3, 7)*SBasis(1, 8))
+ a = SBasis(3, 9)*SBasis(4, 6)
+ b = SBasis(2, 0)
+ c = a(b)
+ self.curve(S)
+ self.curve(S.derivative())
+ self.curve(S.reverse())
+ self.curve(S.transformed( Scale(4) ))
+ self.curve(S.transformed( Zoom(9, Translate(3, 6)) ))
+ self.curve(SBasisCurve(a*b*c, a+b+c))
+ self.curve(S.derivative().derivative())
+
+ def test_bezierCurve(self):
+ B = BezierCurve.create( [ Point(0, 5), Point(3, 65), Point(-3, 2), Point(1, 9) ] )
+ C = BezierCurve.create( [ Point(0,1), Point(1, 0) ] )
+ self.curve(B)
+ self.curve(C)
+ self.curve(C.reverse())
+ self.curve(B.portion(0, 2))
+ self.curve(B.transformed(Zoom(9, Translate(3, 6))))
+ self.curve(B.derivative())
+
+ def ntest_lineSegment(self):
+ L = LineSegment(Point(2, 8), Point(1, 9))
+ K = LineSegment.from_beziers(Bezier(2, 8), Bezier(-1, 9))
+ self.curve(L)
+ self.curve(K)
+ self.curve(L.reverse())
+ self.curve(L.portion(Interval(0.2, 0.4)))
+ self.curve(L.subdivide(0.3)[0])
+ self.curve(L.subdivide(0.3)[1])
+ self.curve(L.derivative())
+ self.curve(L.transformed(Scale(30)*Translate(3, 9)))
+
+ self.curve(LineSegment())
+
+ def test_quadraticBezier(self):
+ Q = QuadraticBezier(Point(2, 8), Point(1, 9), Point(-2, 3))
+ R = QuadraticBezier.from_beziers(Bezier(2, 8, 4), Bezier(-1, 9, 9))
+ self.curve(Q)
+ self.curve(R)
+ self.curve(Q.reverse())
+ self.curve(Q.portion(interval=Interval(0.1, 0.9)))
+ self.curve(Q.subdivide(0.8)[0])
+ self.curve(Q.subdivide(0.8)[1])
+ self.curve(Q.derivative())
+ self.curve(Q.transformed(Scale(-3)*Translate(4, 8)))
+
+ self.curve(QuadraticBezier())
+
+ def test_cubicBezier(self):
+ C = CubicBezier(Point(2, 0), Point(-1, 2.9), Point(-2, 3), Point(3, 1))
+ D = CubicBezier.from_beziers(Bezier(2, 8, 4, 7), Bezier(-1, 9, 9, 8))
+ print 343
+ self.curve(C)
+ self.curve(D)
+ self.curve(C.reverse())
+ #Some kind of numerical instability imo
+ #~ self.curve(C.portion(Interval(0.1, 0.9)))
+ self.curve(C.subdivide(0.8)[0])
+ self.curve(C.subdivide(0.8)[1])
+ self.curve(C.derivative())
+ self.curve(C.transformed(Scale(-3)*Translate(4, 8)))
+
+ self.curve(CubicBezier())
+
+ def test_hLineSegment(self):
+ H = HLineSegment(Point(3, 9), Point(9, 9))
+ I = HLineSegment(Point(1, 3), Point(92, 3))
+ J = HLineSegment.from_point_length( Point(2, 4), 1)
+ self.curve( H )
+ self.curve( I )
+ self.curve( J )
+ self.curve( H.portion(0, .25) )
+ self.curve( H.derivative() )
+ self.curve( H.transformed(Rotate(20)) )
+ self.curve( HLineSegment() )
+ self.curve( I.reverse() )
+ map(self.curve, I.subdivide(0.8))
+
+ self.assertAlmostEqual(I.get_Y(), 3)
+ J.set_Y(2)
+ J.set_initial_X(0)
+ J.set_final_X(1)
+ self.assertAlmostEqual( J(0), Point(0, 2) )
+ self.assertAlmostEqual( J(1), Point(1, 2) )
+
+ def test_vLineSegment(self):
+ V = VLineSegment(Point(2, 9), Point(2, 6))
+ W = VLineSegment(Point(1, 2), Point(1, 8))
+ X = VLineSegment.from_point_length( Point(2, 4), 1)
+ #~ self.curve( V )
+ #~ self.curve( W )
+ #~ self.curve( X )
+ #~ self.curve( V.portion(0, .25) )
+ #~ self.curve( V.derivative() )
+ #~ self.curve( V.transformed(Rotate(20)) )
+ #~ self.curve( VLineSegment() )
+ #~ self.curve( W.reverse() )
+ #~ map(self.curve, W.subdivide(0.8))
+ #~
+ #~ self.assertAlmostEqual(I.get_Y(), 3)
+ #~ X.set_Y(2)
+ #~ X.set_initialX(0)
+ #~ X.set_finalX(1)
+ #~ self.assertAlmostEqual( X(0), Point(0, 2) )
+ #~ self.assertAlmostEqual( X(1), Point(1, 2) )
+ #~ print V(0.5)
+ #~ print V.nearest_time(V(0.5), 0.1, 0.4 )
+ #~ print V.nearest_time(V(0.5), Interval(0.2, 0.5))
+ #~ print V(0.5), V(0.2)
+ #TODO:
+ #this is likely a bug in 2geom, following code
+
+ #~ VLineSegment V(Point(0, 0), 2);
+ #~ printf("%f\n", V.nearest_time(V(0.5), 0.2, 0.5));
+
+ #prints
+ #0.2
+
+ def test_ellipticalArc(self):
+ E = EllipticalArc()
+ self.curve(E)
+ F = EllipticalArc(Point(), 1, 2, math.pi/6, True, True, Point(1, 1))
+
+ self.assertTrue(F.sweep())
+ self.assertTrue(F.large_arc())
+ self.assertAlmostEqual(F.chord()(0), Point())
+ self.assertAlmostEqual(F.chord()(1), Point(1, 1))
+
+ F.set_extremes(Point(1, 1), Point(-1, 1))
+ self.assertAlmostEqual(F.initial_point(), Point(1, 1))
+ self.assertAlmostEqual(F.final_point(), Point(-1, 1))
+ self.assertEqual(F.initial_angle(), F.angle_at(0))
+ self.assertEqual(F.final_angle(), F.angle_at(1))
+ self.assertTrue(F.contains(F.angle_at(0.5)))
+
+ G = EllipticalArc(Point(), 1, 1, 0, True, True, Point(2, 0))
+ for i in range(11):
+ t = i/10.0
+ print G(t)
+ self.assertAlmostEqual(G.extent(), math.pi)
+ self.assertAlmostEqual(G.extent(), G.sweep_angle())
+ self.assertAlmostEqual(float(G.angle_at(0.5)), -math.pi/2)
+
+ self.assertAlmostEqual(Point(1, 1), G.rays())
+ self.assertAlmostEqual(1, G.ray(1))
+ self.assertAlmostEqual(0, float(G.rotation_angle()))
+
+ self.assertAlmostEqual(G.extent(), G.angle_interval().extent())
+
+ self.assertAlmostEqual(G.center(), Point(1, 0))
+ #unit half-circle
+ U = EllipticalArc(Point(1, 0), 1, 1, 0, True, True, Point(-1, 0))
+
+ G.set(Point(), 1, 1, 0, True, False, Point(1, 0))
+
+ A = G.unit_circle_transform()
+
+ self.assertAlmostEqual( G(0.5), U.transformed(A)(0.5) )
+ self.assertAlmostEqual( G.value_at_angle(G.angle_at(0.32), 0), G.value_at(0.32, 0) )
+
+ self.assertTrue(G.contains_angle(Angle(math.pi/4)))
+ self.assertFalse(G.is_SVG_compliant())
+ #~ self.curve(F)
+ #TODO:
+ #F.point_and_derivatives(t, 1)[0] differs from F(0) and F.bounds_exact,
+ #F.bounds_fast doesn't contain F(1)
+
+unittest.main()
diff --git a/src/3rdparty/2geom/src/cython/test-path.py b/src/3rdparty/2geom/src/cython/test-path.py
new file mode 100644
index 0000000..6ad6af4
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/test-path.py
@@ -0,0 +1,218 @@
+import unittest
+import math
+from random import randint, uniform
+
+import cy2geom
+
+from cy2geom import Point, IntPoint
+from cy2geom import Interval, IntInterval, OptInterval, OptIntInterval
+
+from cy2geom import Affine
+from cy2geom import Translate, Scale, Rotate, VShear, HShear, Zoom
+from cy2geom import Eigen
+
+from cy2geom import Curve
+from cy2geom import Linear
+from cy2geom import SBasis, SBasisCurve
+from cy2geom import Bezier, BezierCurve
+
+from cy2geom import LineSegment, QuadraticBezier, CubicBezier
+from cy2geom import HLineSegment, VLineSegment
+
+from cy2geom import EllipticalArc
+
+from cy2geom import Path
+
+#TODO! move drawing elsewhere, it nice to see paths, but is not very suitable for automatic testing
+draw = False
+
+try:
+ import utils
+except ImportError:
+ print "No drawing with Tk"
+ draw = False
+
+class TestPrimitives(unittest.TestCase):
+ def curves_equal(self, C1, C2):
+ for i in range(101):
+ t = i/100.0
+ self.assertAlmostEqual(C1(t), C2(t))
+ def path(self, P):
+ for curve in P:
+ self.assertIsInstance(curve, Curve)
+
+ self.assertAlmostEqual(P(0), P.front()(0))
+ self.curves_equal(P.front(), P[0])
+
+ self.curves_equal(P.back_default(), P[P.size_default()-1])
+ self.curves_equal(P.back_open(), P.back())
+ self.assertEqual(P.size_open(), P.size())
+
+ self.assertFalse(P.empty() ^ (P.size()==0))
+
+ exact = P.bounds_exact().Rect
+ exact.expand_by(1e-5)
+
+ fast = P.bounds_fast().Rect
+ fast.expand_by(1e-5)
+ A1 = Affine(3, 1, 8, 3, 9, 9)
+ A2 = Rotate(0.231)
+
+ for i in range(100 * P.size_open() + 1):
+ t = i/100.0
+ self.assertTrue(exact.contains(P(t)))
+ self.assertTrue(fast.contains(P(t)))
+ self.assertAlmostEqual( (P*A1)(t) , P(t)*A1 )
+ self.assertAlmostEqual( (P*A2)(t) , P(t)*A2 )
+
+ self.assertAlmostEqual(P(t), P.point_at(t))
+ self.assertAlmostEqual(P(t).x, P.value_at(t, 0))
+ self.assertAlmostEqual(P(t).y, P.value_at(t, 1))
+
+ if P.closed():
+ self.curves_equal(P.back_default(), P.back_closed())
+ self.assertEqual(P.size_default(), P.size_closed())
+ else:
+ self.curves_equal(P.back_default(), P.back_open())
+ self.assertEqual(P.size_default(), P.size_open())
+
+ for i in range(10):
+ for root in P.roots(i, 0):
+ if root < P.size_default():
+ self.assertAlmostEqual(P.value_at(root, 0), i)
+ for root in P.roots(i, 1):
+ if root < P.size_default():
+ self.assertAlmostEqual(P.value_at(root, 1), i)
+
+ for t in P.all_nearest_times(P(0)):
+ self.assertAlmostEqual(P(t), P(0))
+ self.assertAlmostEqual(min(P.all_nearest_times( P(0) )), 0)
+ self.assertAlmostEqual(P.nearest_time(P(0), 0, 0.2), 0)
+ self.assertEqual( len(P.nearest_time_per_curve(Point())), P.size_default() )
+
+ t, distSq = P.nearest_time_and_dist_sq(Point(-1, -1), 0, P.size())
+ self.assertAlmostEqual(distSq**0.5, abs(P(t)-Point(-1, -1)) )
+
+ self.assertAlmostEqual(P.portion(0.3, 0.4)(0), P(0.3))
+ self.assertAlmostEqual( P.portion( interval=Interval(P.size(), P.size() * 2) / 3 )(0),
+ P(P.size()/3.0))
+
+ self.assertAlmostEqual(P(0.23), P.reverse()(P.size()-0.23))
+
+ self.assertAlmostEqual(P.initial_point(), P(0))
+ self.assertAlmostEqual(P.final_point(), P(P.size()))
+ def test_path(self):
+ a = Path()
+ a.append_curve( CubicBezier( Point(-7, -3), Point(2, 8), Point(2, 1), Point(-2, 0) ) )
+
+ self.assertEqual(a.size(), 1)
+ self.assertFalse(a.closed())
+ self.path(a)
+
+ a.close(True)
+ self.assertTrue(a.closed())
+ self.path(a)
+
+ a.close(False)
+ a.append_curve( LineSegment(a.final_point(), Point(3, 5)) )
+ self.assertEqual(a.size(), 2)
+ self.path(a)
+
+ a.append_SBasis( SBasis(3, 6)*SBasis(1, 0), SBasis(5, 2))
+ self.path(a)
+
+ a.append_curve(EllipticalArc(Point(), 1, 2, math.pi/6, True, True, Point(1, 1)), Path.STITCH_DISCONTINUOUS)
+ #Stitching adds new segment
+ self.assertEqual(a.size(), 5)
+
+ b = Path()
+ for c in a:
+ b.append_curve(c)
+
+ #TODO: This fails with STITCH_DISCONTINUOUS, but also does so in C++, so
+ #it's either correct behaviour or bug in 2geom
+ #~ self.path(b)
+
+ b.insert(2, LineSegment(b[2-1](1), b[2](0))) #, Path.STITCH_DISCONTINUOUS)
+ self.curves_equal(LineSegment(b[2-1](1), b[2](0)), b[2])
+ #TODO! fails on root finding
+ #self.path(b)
+
+ b.set_initial(a[2](1))
+ b.set_final(a[3](0))
+
+ a.insert_slice(3, b, 0, b.size())
+ self.assertEqual(a.size(), b.size()*2-1)
+
+ for i in range(b.size()):
+ self.curves_equal(a[3+i], b[i])
+
+ #Looks like bug:
+# A = Path()
+# A.append_curve( CubicBezier( Point(-7, -3), Point(2, 8), Point(2, 1), Point(-2, 0) ) )
+# A.append_curve(EllipticalArc(Point(), 1, 2, math.pi/6, True, True, Point(1, 1)), Path.STITCH_DISCONTINUOUS)
+# print A.roots(0, 1)
+
+ #Roots are [1.0, 2.768305708350847, 3.25], Point at second root is
+ #Point (2.32, -0.48)
+ #and third root is > 3 - it corresponds to root on closing segment, but A is open,
+ #and computing A(3.25) results in RangeError - this might be bug or feature.
+
+ self.path(a.portion(0.232, 3.12))
+ self.path(a.portion( interval=Interval(0.1, 4.7) ))
+ self.path(a.portion(0.232, 3.12).reverse())
+
+ b.clear()
+ self.assertTrue(b.empty())
+
+ aa = Path()
+ for c in a:
+ aa.append_curve(c)
+
+ a.erase(0)
+ self.assertEqual(a.size(), aa.size() - 1)
+ self.assertAlmostEqual(a(0), aa(1))
+
+ a.erase_last()
+ self.assertEqual(a.size(), aa.size() - 2)
+ self.assertAlmostEqual(a.final_point(), aa[aa.size()-2](1))
+
+ a.replace(3, QuadraticBezier(a(3), Point(), a(4)))
+ self.assertEqual(a.size(), aa.size() - 2)
+
+ cs = [LineSegment(Point(-0.5, 0), Point(0.5, 0)).transformed( Rotate(-math.pi/3 * i)*Translate(Point(0, math.sqrt(3)/2)*Rotate(-math.pi/3 * i)) ) for i in range(6)]
+
+ hexagon = Path.fromList(cs, stitching = Path.STITCH_DISCONTINUOUS, closed = True)
+
+ if draw:
+ utils.draw(hexagon, scale = 100)
+
+ #to = 5 because each corner contains one stitching segment
+ half_hexagon = Path.fromPath(hexagon, fr = 0, to = 5)
+ if draw:
+ utils.draw(half_hexagon, scale = 100)
+
+ half_hexagon.replace_slice(1, 5, LineSegment(half_hexagon(1), half_hexagon(5)))
+ self.assertEqual(half_hexagon.size(), 2)
+ self.assertAlmostEqual(half_hexagon(1.5), Point(0.5, 0))
+
+ half_hexagon.stitch_to(half_hexagon(0))
+ self.assertAlmostEqual(half_hexagon(2.5), Point())
+
+ a.start(Point(2, 2))
+ a.append_SBasis( SBasis(2, 6), SBasis(1, 5)*SBasis(2, 9) )
+ self.assertAlmostEqual(a(1), Point(6, 5*9))
+
+ l = Path.fromList([QuadraticBezier(Point(6, 5*9), Point(1, 2), Point(-2, .21))])
+ a.append_path(l)
+ self.assertAlmostEqual(a.final_point(), l.final_point())
+
+ k = Path.fromList([QuadraticBezier(Point(), Point(2, 1), Point(-2, .21)).reverse()])
+ k.append_portion_to(l, 0, 0.3)
+ self.assertAlmostEqual(l.final_point(), k(0.3))
+
+ def test_read_svgd(self):
+ p = Path.read_svgd("../toys/spiral.svgd")
+ if draw:
+ utils.draw(p[0], scale=0.4)
+unittest.main()
diff --git a/src/3rdparty/2geom/src/cython/test-primitives.py b/src/3rdparty/2geom/src/cython/test-primitives.py
new file mode 100644
index 0000000..0edf218
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/test-primitives.py
@@ -0,0 +1,288 @@
+import unittest
+from math import pi, sqrt
+
+import cy2geom
+from cy2geom import Angle, AngleInterval, Point, IntPoint, Line, Ray
+from cy2geom import LineSegment, Curve
+
+class TestPrimitives(unittest.TestCase):
+
+ def test_angle(self):
+ self.assertAlmostEqual(Angle.rad_from_deg(45), pi/4)
+ self.assertAlmostEqual(Angle.deg_from_rad(pi/6), 30)
+
+ p = Point(1, sqrt(3))
+ alpha = Angle.from_Point(p)
+ self.assertAlmostEqual(alpha.degrees(), 60)
+
+ beta = Angle.from_radians(pi/5)
+ gamma = Angle.from_degrees(36)
+ self.assertAlmostEqual(beta.radians0(), gamma.radians0())
+ self.assertTrue(beta==gamma)
+ omega = Angle.from_degrees_clock(0)
+ self.assertAlmostEqual(omega.radians(), pi/2)
+
+ delta = Angle(-pi * 0.5)
+ self.assertAlmostEqual(delta.degrees(), -90)
+ self.assertAlmostEqual(delta.radians0(), 1.5*pi)
+ #degreesClock roughly means [ 90 - Angle.degrees() ] mod 360
+ self.assertAlmostEqual(delta.degrees_clock(), 180)
+
+ self.assertAlmostEqual(
+ (beta + gamma).radians(),
+ beta.radians()+gamma.radians() )
+ self.assertAlmostEqual( (beta - gamma).degrees(), 0)
+
+ def test_angleInterval(self):
+ A = AngleInterval(Angle(pi/6), Angle(pi/4))
+ B = AngleInterval( 0, pi/4, cw = True )
+ self.assertEqual(A(0), Angle(pi/6))
+ self.assertEqual(A(0.5), A.angle_at(0.5))
+ self.assertEqual(A(0), A.initial_angle())
+ self.assertEqual(B(1), B.final_angle())
+ self.assertFalse(B.is_degenerate())
+ self.assertTrue(B.contains(Angle(pi/6)))
+ self.assertTrue(A.contains(Angle(pi)))
+
+ self.assertAlmostEqual( B.extent(), pi/4 )
+ def test_point(self):
+ p = Point(3, 4)
+ q = Point(8, 16)
+ p_inf = Point(float('inf'), 1)
+ #y axis points downwards
+ p_ccw = Point(4, -3)
+
+ self.assertAlmostEqual(p.length(), 5)
+ self.assertAlmostEqual(p.ccw(), p_ccw)
+ self.assertAlmostEqual(p_ccw.cw(), p)
+ self.assertAlmostEqual(p[0], 3)
+ self.assertAlmostEqual(p[1], 4)
+
+ self.assertFalse(p_inf.isFinite())
+ self.assertTrue(p.isFinite())
+ self.assertFalse(p.isNormalized())
+ self.assertTrue((p/p.length()).isNormalized())
+ self.assertFalse(p.isZero())
+ self.assertTrue((p*0).isZero())
+
+ self.assertTrue( (p + p.ccw().ccw()).isZero)
+ self.assertAlmostEqual( (q-p).length(), 13)
+
+ self.assertGreater(q, p)
+ self.assertGreaterEqual(q, p)
+ self.assertEqual(p, p)
+ self.assertNotEqual(p, q)
+ self.assertLess( Point(1, 1), Point(1, 2) )
+ self.assertLessEqual(p, p)
+
+ self.assertTrue( Point.are_near(
+ Point.polar(pi/4, sqrt(2)),
+ Point(1, 1) ))
+ self.assertAlmostEqual(sqrt(2), Point.L2(Point(1, 1)))
+ self.assertAlmostEqual(2, Point.L2sq(Point(1, 1)))
+ self.assertAlmostEqual( Point.middle_point(Point(), q), q/2 )
+ self.assertAlmostEqual( Point.rot90(p), p.cw() )
+ self.assertAlmostEqual(
+ Point.lerp(0.2, Point(), Point(3,4)).length(),
+ 1)
+ self.assertAlmostEqual(Point.dot(p, p_ccw), 0)
+ self.assertAlmostEqual(Point.dot(p, p_inf), float('inf'))
+ self.assertAlmostEqual(Point.dot(p, q), 88)
+ #TODO this might be implemented incorrectly in lib2geom!
+ self.assertAlmostEqual(Point.cross(p, q), -16)
+
+ self.assertAlmostEqual(Point.distance(p, q), 13)
+ self.assertAlmostEqual(Point.distanceSq(p, p_ccw), 50)
+ self.assertAlmostEqual(Point.unit_vector(p), p/5)
+
+ self.assertAlmostEqual(Point.L1(p), 7)
+ self.assertAlmostEqual(Point.L1(p_inf), float('inf'))
+ self.assertAlmostEqual(Point.LInfty(q), 16)
+ self.assertAlmostEqual(Point.LInfty(p_inf), float('inf'))
+
+ self.assertTrue(Point.is_zero(Point()))
+ self.assertFalse(Point.is_zero(p))
+ self.assertTrue(Point.is_unit_vector(p/5))
+ self.assertFalse(Point.is_unit_vector(q))
+
+ self.assertAlmostEqual(Point.atan2(Point(1, 1)), pi/4)
+ self.assertAlmostEqual(Point.angle_between(p, p_ccw), -pi/2)
+ self.assertAlmostEqual(Point.abs(-p), p)
+ #TODO I have no idea what should this function do
+ # self.assertAlmostEqual(
+ # Point.constrain_angle(Point(1, 0), Point(0, 1), 1, Point(sqrt(2)/2, sqrt(2)/2)),
+ #
+ # ))
+
+ def test_intPoint(self):
+ p = Point(4.89, 3.21)
+ self.assertEqual(p.round(), IntPoint(5, 3))
+ self.assertEqual(p.floor(), IntPoint(4, 3))
+ self.assertEqual(p.ceil(), IntPoint(5, 4))
+
+ self.assertEqual(p.ceil().x, 5)
+ self.assertEqual(p.floor().y, 3)
+ self.assertEqual(IntPoint(), p.floor()-p.floor())
+
+ a = IntPoint(2, -5)
+ b = IntPoint(5, 3)
+ self.assertEqual(IntPoint(7, -2), a+b)
+ self.assertEqual(IntPoint(3, 8), b-a)
+ self.assertGreater(b, a)
+ self.assertGreaterEqual(b, b)
+ self.assertNotEqual(a, b)
+
+ def test_line(self):
+
+ l = Line(Point(), pi/4)
+ self.assertAlmostEqual( l.origin(), Point() )
+ self.assertAlmostEqual( l.versor(), Point(1, 1)/sqrt(2) )
+ self.assertAlmostEqual( l.angle(), pi/4 )
+
+ k = Line.from_points(Point(), Point(2, 1))
+ self.assertFalse(k.is_degenerate())
+ self.assertFalse(Line().is_degenerate())
+ self.assertAlmostEqual( l.point_at(sqrt(2)), Point(1,1) )
+ self.assertAlmostEqual(
+ k.point_at(43),
+ Point(k.value_at(43, 0), k.value_at(43, 1)))
+ self.assertAlmostEqual(k.time_at(Point(4, 2)), sqrt(20))
+ self.assertAlmostEqual(
+ k.time_at_projection(Point(4, 2) + Point(2, -4)),
+ sqrt(20))
+ self.assertAlmostEqual(
+ k.point_at(k.nearest_time(Point(4, 2) + Point(2, -4))),
+ Point(4,2))
+ self.assertAlmostEqual(
+ k.time_at_projection(Point(3, 3)),
+ -k.reverse().time_at_projection(Point(3, 3)))
+ self.assertAlmostEqual( k.derivative().origin(), k.versor())
+ self.assertAlmostEqual(k.normal(), k.versor().cw())
+
+ roots = k.roots( 3, 0 )
+ for root in roots:
+ self.assertAlmostEqual( k.value_at(root, 0), 3)
+
+ self.assertAlmostEqual(l.normal(), l.normal_and_dist()[0])
+ self.assertAlmostEqual(Line.distance(Point(), l), l.normal_and_dist()[1])
+
+ self.assertAlmostEqual(Line.distance(Point(-1, 1), l), sqrt(2))
+ self.assertTrue(Line.are_near(Point(0), l))
+ self.assertFalse(Line.are_near(Point(1, 1), k))
+ self.assertTrue(Line.are_near(Point(1, 1), k, 2))
+
+ p = Line(Point(1, 1))
+ p_orto = Line(Point(2, 3), pi/2)
+ p_para = Line(Point(2, 3))
+ p_same = Line.from_points(Point(1, 1), Point(5, 1))
+
+ self.assertTrue(Line.are_orthogonal(p, p_orto))
+ self.assertFalse(Line.are_orthogonal(p, p_para))
+ self.assertTrue(Line.are_parallel(p, p_para))
+ self.assertFalse(Line.are_parallel(p, p_orto))
+ self.assertTrue(Line.are_same(p, p_same))
+ self.assertFalse(Line.are_same(p, p_para))
+
+ self.assertTrue(Line.are_collinear(
+ Point(1,1),
+ Point(2, 3),
+ Point(4, 7)))
+ self.assertAlmostEqual(Line.angle_between(p, p_orto), pi/2)
+
+ m = Line.from_normal_distance(Point(1, -1), 1)
+ self.assertAlmostEqual(m.angle(), pi/4)
+
+ m = Line.from_LineSegment( LineSegment( Point(2, 2), Point(4, 4) ) )
+ self.assertAlmostEqual(m.angle(), pi/4)
+
+ m = Line.from_Ray( Ray(Point(2, 3), 0.2) )
+ self.assertAlmostEqual(m.angle(), 0.2)
+ self.assertAlmostEqual(m.origin(), Point(2, 3))
+
+ self.assertIsInstance(m.portion(2, 4), Curve)
+ self.assertAlmostEqual(m.portion(2, 4)(0), m.point_at(2))
+
+ self.assertIsInstance(m.segment(1, 5), LineSegment)
+ self.assertAlmostEqual(m.segment(1, 5)(1), m.point_at(5))
+
+ self.assertAlmostEqual(m.ray(4).origin(), m.point_at(4))
+
+ m.set_origin(Point())
+ self.assertAlmostEqual(m.origin(), Point())
+
+ m.set_angle(0.2)
+ self.assertAlmostEqual(m.angle(), 0.2)
+
+ m.set_versor(Point())
+ self.assertTrue(m.is_degenerate())
+
+ m.set_points(Point(2, 9), Point(1, 8))
+ self.assertAlmostEqual(m.versor(), Point.unit_vector(Point(1, 8) - Point(2, 9)))
+
+ def test_ray(self):
+ r = Ray(Point(1,1), pi/4)
+ self.assertAlmostEqual(r.origin(), Point(1, 1))
+ self.assertAlmostEqual(r.versor(), Point(1, 1)/sqrt(2))
+ self.assertAlmostEqual(r.angle(), pi/4)
+
+ r.set_origin(Point(4, 3))
+ #TODO this should maybe normalize the versor!
+ r.set_versor(Point(1, -1)/sqrt(2))
+ self.assertAlmostEqual(r.origin(), Point(4, 3))
+ self.assertAlmostEqual(r.versor(), Point(1, -1)/sqrt(2))
+ self.assertAlmostEqual(r.angle(), -pi/4)
+
+ r.set_points(Point(1, 1), Point(1, 3))
+ self.assertFalse(r.is_degenerate())
+ self.assertFalse(Ray().is_degenerate())
+ self.assertAlmostEqual(r.point_at(4), Point(1, 5))
+
+ #TODO I think this should be expected behaviour
+# self.assertAlmostEqual(
+# r.pointAt(-3),
+# Point(1, 1)))
+ self.assertAlmostEqual(r.value_at(4, 0), 1)
+ self.assertAlmostEqual(r.value_at(4, 1), 5)
+
+ roots = r.roots( 3, 1 )
+ for root in roots:
+ self.assertAlmostEqual( r.value_at(root, 1), 3)
+
+ self.assertAlmostEqual(
+ r.point_at(3) - r.origin(),
+ r.origin()-r.reverse().point_at(3))
+
+ self.assertAlmostEqual(Ray.distance(Point(), r), sqrt(2))
+ self.assertAlmostEqual(Ray.distance(Point()+r.versor(), r), 1)
+
+ self.assertTrue(Ray.are_near(Point(), r, 2))
+ self.assertFalse(Ray.are_near(Point(), r))
+ self.assertTrue(Ray.are_same(r, r))
+
+ q = Ray(r.origin(), r.angle())
+ self.assertTrue(Ray.are_same(r, q))
+
+ q.set_origin(r.origin()+Point(0, 1))
+ self.assertFalse(Ray.are_same(r, q))
+ #TODO shouldn't this really be 0?
+ self.assertAlmostEqual(Ray.angle_between(r, q), 2*pi)
+
+ q.set_versor(Point(1, 0))
+ q.set_origin(r.origin())
+ self.assertAlmostEqual(
+ Point(1, 1)/sqrt(2),
+ Ray.make_angle_bisector_ray(q, r).versor())
+
+ q.set_angle(pi/7)
+ self.assertAlmostEqual(q.angle(), pi/7)
+
+ self.assertIsInstance(q.portion(2, 4), Curve)
+ self.assertAlmostEqual(q.portion(2, 4)(0), q.point_at(2))
+
+ self.assertIsInstance(q.segment(1, 5), LineSegment)
+
+ self.assertAlmostEqual(q.segment(1, 5)(1), q.point_at(5))
+
+
+unittest.main()
+
diff --git a/src/3rdparty/2geom/src/cython/test-rectangle.py b/src/3rdparty/2geom/src/cython/test-rectangle.py
new file mode 100644
index 0000000..51f3c50
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/test-rectangle.py
@@ -0,0 +1,601 @@
+import unittest
+from math import pi, sqrt
+from random import randint
+
+import cy2geom
+
+from cy2geom import Point, IntPoint
+
+from cy2geom import Interval, IntInterval, OptInterval, OptIntInterval
+from cy2geom import GenericInterval, GenericOptInterval
+
+from cy2geom import Rect, OptRect, IntRect, OptIntRect
+from cy2geom import GenericRect
+
+from fractions import Fraction
+
+
+class TestPrimitives(unittest.TestCase):
+ def interval_basic(self, I, J):
+ #for simplicity
+ self.assertTrue(I.min() >= 0)
+ self.assertTrue(J.min() >= 0)
+ a = I.min()
+ b = I.max();
+ self.assertAlmostEqual(I.middle(), (a+b)/2);
+ self.assertAlmostEqual(I.extent(), (b-a));
+ if a != b:
+ self.assertFalse(I.is_singular())
+ else:
+ self.assertTrue(I.is_singular())
+
+ I.expand_by(a)
+ self.assertAlmostEqual(I.min(), 0);
+ self.assertAlmostEqual(I.max(), a+b)
+ I.set_min(a)
+ I.set_max(b)
+
+ self.assertTrue(I.contains(a+ (b-a)/3 ))
+ self.assertTrue(I.contains(a))
+ self.assertTrue(I.contains_interval(I))
+
+ if (not I.is_singular()) or I.min() != 0 :
+ pass
+ self.assertFalse(I.contains_interval(I+I))
+ self.assertFalse(I.contains(a-1))
+
+ c = J.min()
+ d = J.max()
+ self.assertAlmostEqual( (I+J).min(), a+c )
+ self.assertAlmostEqual((I|J).min(), min(a, c))
+ J.set_min(a+2)
+ J.set_max(b+2)
+ self.assertEqual(I+2, J)
+ I.expand_to(2*b)
+ self.assertAlmostEqual(I.max(), 2*b)
+
+ def test_interval(self):
+ I = Interval(1.2, 5)
+ J = Interval(0, 0.3)
+ self.interval_basic(I, J)
+
+ self.assertTrue(I.interior_contains(I.middle()))
+ self.assertFalse(I.interior_contains(I.min()))
+ self.assertFalse(I.interior_contains_interval(I))
+ self.assertTrue(I.interior_contains_interval(Interval(I.min()+1, I.max()-1)))
+
+ self.assertTrue(I.interior_intersects(I))
+ self.assertFalse(I.interior_intersects(-I))
+ p = [1, 2, 3.442, 3]
+ K = Interval.from_list(p)
+ self.assertAlmostEqual(K.max(), max(p))
+ self.assertAlmostEqual((K+Interval(1.0)).min(), min(p)+1)
+ L = Interval(10/3.0)
+ for i in range(3):
+ K+=L
+ self.assertAlmostEqual(K.max(), max(p)+10)
+
+ #TODO This 2geom behaviour is a bit strange
+ self.assertEqual(Interval(3.0)|Interval(5.0),
+ Interval(3.0, 5.0))
+ self.assertAlmostEqual((K-L).max(), (K-10/3.0).max())
+
+ self.assertAlmostEqual((K*3.4).max(), 3.4*K.max())
+ self.assertAlmostEqual((K/3).extent(), K.extent()/3)
+
+ def test_optInterval(self):
+ I = OptInterval(2.2, 9.3)
+ J = Interval(3, 13)
+ K = OptInterval.from_Interval(J)
+ self.assertEqual(K.Interval, J)
+ self.interval_basic(K.Interval, I.Interval)
+
+ L = OptInterval()
+
+ self.assertFalse(L)
+ self.assertTrue( (L&I).is_empty() )
+ L.intersect_with(I)
+ self.assertFalse(L)
+
+ L |= I
+
+ self.assertEqual(L.Interval, I.Interval)
+
+ self.assertEqual((I & K).Interval, Interval(3, 9.3))
+
+ def test_intInterval(self):
+ I = IntInterval(2, 6)
+ J = IntInterval(0, 1)
+ self.interval_basic(I, J)
+ p = [3, 2.3, 65.3, 43]
+ K = IntInterval.from_list(p)
+ self.assertAlmostEqual(K.max(), int(max(p)))
+ self.assertAlmostEqual(int((K+IntInterval(1.0)).min()), int(min(p)+1))
+ L = IntInterval(3)
+ for i in range(3):
+ K+=L
+ self.assertAlmostEqual(K.max(), int(max(p))+9)
+
+ self.assertEqual(Interval(3)|Interval(5),
+ Interval(3, 5))
+ self.assertAlmostEqual((K-L).max(), (K-3).max())
+
+ def test_optIntInterval(self):
+ I = OptIntInterval(2, 9)
+ J = IntInterval(3, 13)
+ K = OptIntInterval.from_Interval(J)
+ self.assertEqual(K.Interval, J)
+ self.interval_basic(K.Interval, I.Interval)
+
+ L = OptIntInterval()
+
+ self.assertFalse(L)
+ self.assertTrue( (L&I).is_empty() )
+ L.intersect_with(I)
+ self.assertFalse(L)
+
+ L |= I
+
+ self.assertEqual(L.Interval, I.Interval)
+
+ self.assertEqual((I & K).Interval, IntInterval(3, 9))
+
+ def test_genericInterval(self):
+ maxv = 100000
+ test_vars = [
+ ( (randint(0, maxv), randint(0, maxv)), (randint(0, maxv), randint(0, maxv)) ),
+ ( (3,), (2, 0) ),
+ ( (0.0, 9), (4, 1.3)),
+ ((2.98, sqrt(2)), (sqrt(7),)),
+ ( (Fraction(1,2), Fraction(3, 7)), ( Fraction(2, 1), ) )
+ ]
+ for a,b in test_vars:
+ self.interval_basic( GenericInterval(*a), GenericInterval(*b) )
+
+ def test_genericOptInterval(self):
+ test_vars = [
+ ( (3,), (2, 0) ),
+ ( (0.0, 9), (4, 1.3)),
+ ((2.98, sqrt(2)), (sqrt(7),)),
+ ( (Fraction(1,2), Fraction(3, 7)), ( Fraction(2, 1), ) )
+ ]
+
+ for a, b in test_vars:
+ I = GenericOptInterval(*a)
+ J = GenericInterval(*b)
+ K = GenericOptInterval.from_Interval(J)
+
+ self.assertEqual(I, GenericOptInterval.from_Interval(I))
+
+ self.assertEqual(K.Interval, J)
+ self.interval_basic(K.Interval, I.Interval)
+
+ L = GenericOptInterval()
+
+ self.assertFalse(L)
+ self.assertTrue( (L&I).is_empty() )
+ L.intersect_with(I)
+ self.assertFalse(L)
+
+ L |= I
+
+ self.assertEqual(L.Interval, I.Interval)
+
+ if I.intersect_with(K):
+ if I.Interval.min() <= K.Interval.min():
+ if I.Interval.max() >= K.Interval.max():
+ self.assertEqual( I & K, K)
+ else:
+ self.assertEqual( I & K, GenericInterval(K.min(), I.max()))
+ else:
+ if I.Interval.max() >= K.Interval.max():
+ self.assertEqual( I & K, GenericInterval(I.min(), K.max()))
+ else:
+ self.assertEqual( I & K, I)
+
+ def test_genericRect(self):
+ A = GenericRect(1, 1, 4, 4)
+ self.assertEqual( A.min(), (1, 1) )
+ B = GenericRect(Fraction(1,4), Fraction(9, 94), Fraction(2, 3), Fraction(23, 37))
+
+ amin = A.min()
+ amax = A.max()
+
+ self.assertAlmostEqual(amin[0], A[0].min())
+ self.assertAlmostEqual(amax[1], A[1].max())
+ self.assertEqual(amin, A.corner(0))
+
+ self.assertEqual(amin, (A.left(), A.top()))
+ self.assertEqual(amax, (A.right(), A.bottom()))
+
+ self.assertAlmostEqual( A.width(), A[0].extent() )
+ self.assertAlmostEqual( A.height(), A[1].extent() )
+
+ self.assertEqual( A.dimensions(), ( A.width(), A.height() ) )
+ #~ self.assertEqual( A.midpoint(), (A.min() + A.max())/2 )
+ self.assertAlmostEqual(A.area(), A.width()*A.height())
+ #TODO export EPSILON from 2geom
+ if A.area() > 0:
+ self.assertFalse(A.has_zero_area())
+ else:
+ self.assertTrue(A.has_zero_area())
+ self.assertAlmostEqual(A.max_extent(), max(A.width(), A.height()))
+ self.assertGreaterEqual(A.max_extent(), A.min_extent())
+
+ bmin = B.min()
+ bmax = B.max()
+
+ pdiag = sqrt((amax[0]-amin[0])**2+(amax[1]-amin[1])**2)
+
+ B.set_min(A.midpoint())
+ B.set_max(A.midpoint())
+
+ self.assertTrue(B.has_zero_area())
+
+ B.expand_by(A.min_extent()/3.0)
+
+ self.assertTrue(A.contains_rect(B))
+ self.assertTrue(A.intersects(B))
+ self.assertTrue(B.intersects(A))
+ self.assertFalse(B.contains_rect(A))
+
+ self.assertTrue(A.contains(A.midpoint()))
+ self.assertFalse(A.contains( (A.midpoint()[0]*3, A.midpoint()[1]*3) ))
+
+ A.union_with(B)
+
+ self.assertEqual( A.min(), amin )
+
+ B.set_left(bmin[0])
+ B.set_top(bmin[1])
+ B.set_right(bmax[0])
+ B.set_bottom(bmax[1])
+
+ self.assertEqual(B.min(), bmin)
+ self.assertEqual(B.max(), bmax)
+
+ B.expand_to( (0, 0) )
+ self.assertEqual((0, 0), B.min())
+
+ B.expand_by(*bmax)
+ self.assertEqual(bmax, (- (B.min()[0]), - (B.min()[1])) )
+
+ B.expand_by(-bmax[0], -bmax[1])
+ self.assertEqual(B.max(), bmax)
+
+ self.assertEqual( (A+B.min()).max()[0], A.max()[0] + B.min()[0] )
+
+ #~ self.assertEqual( (A-B.max()).min(), A.min() - B.max() )
+
+ self.assertEqual( A|A, A )
+
+ self.assertFalse( A != A )
+
+ B.set_left(bmin[0])
+ B.set_top(bmin[1])
+ B.set_right(bmax[0])
+ B.set_bottom(bmax[1])
+
+ #~ self.assertAlmostEqual(Rect.distance(Point(), A), A.min().length())
+ #~ self.assertAlmostEqual(Rect.distanceSq(B.min(), A), Rect.distance(B.min(), A)**2 )
+
+
+
+ def rect_basic(self, P, Q):
+ pmin = P.min()
+ pmax = P.max()
+ #for simplicity
+ self.assertTrue(pmin.x > 0)
+ self.assertTrue(pmin.y > 0)
+
+ self.assertAlmostEqual(pmin.x, P[0].min())
+ self.assertAlmostEqual(pmax.y, P[1].max())
+ self.assertEqual(pmin, P.corner(0))
+
+ self.assertEqual(pmin, Point(P.left(), P.top()))
+ self.assertEqual(pmax, Point(P.right(), P.bottom()))
+
+ self.assertAlmostEqual( P.width(), P[0].extent() )
+ self.assertAlmostEqual( P.height(), P[1].extent() )
+
+ self.assertAlmostEqual( P.aspect_ratio(), P.width()/P.height() )
+ self.assertEqual( P.dimensions(), Point( P.width(), P.height() ) )
+ self.assertEqual( P.midpoint(), (P.min() + P.max())/2 )
+ self.assertAlmostEqual(P.area(), P.width()*P.height())
+ #TODO export EPSILON from 2geom
+ if P.area() > 1e-7:
+ self.assertFalse(P.has_zero_area())
+ self.assertTrue(P.has_zero_area(P.area()))
+ else:
+ self.assertTrue(P.has_zero_area())
+ self.assertAlmostEqual(P.max_extent(), max(P.width(), P.height()))
+ self.assertGreaterEqual(P.max_extent(), P.min_extent())
+
+ qmin = Q.min()
+ qmax = Q.max()
+
+ pdiag = (pmax-pmin).length()
+
+ Q.set_min(P.midpoint())
+ Q.set_max(P.midpoint())
+ self.assertTrue(Q.has_zero_area())
+
+ #print P,Q
+ Q.expand_by(P.min_extent()/3.0)
+
+ #print P, Q
+
+ self.assertTrue(P.contains_rect(Q))
+ self.assertTrue(P.intersects(Q))
+ self.assertTrue(Q.intersects(P))
+ self.assertFalse(Q.contains_rect(P))
+
+ self.assertTrue(P.interior_contains_rect(Q))
+ self.assertFalse(P.interior_contains_rect(P))
+ self.assertTrue(P.interior_intersects(Q))
+ self.assertTrue(P.interior_intersects(P))
+
+ self.assertTrue(P.contains(P.midpoint()))
+ self.assertFalse(P.contains(P.midpoint()*3))
+
+ P.union_with(Q)
+
+ self.assertEqual( P.min(), pmin )
+
+ Q.set_left(qmin.x)
+ Q.set_top(qmin.y)
+ Q.set_right(qmax.x)
+ Q.set_bottom(qmax.y)
+
+ self.assertEqual(Q.min(), qmin)
+ self.assertEqual(Q.max(), qmax)
+
+ Q.expand_to( Point() )
+ self.assertEqual(Point(), Q.min())
+ Q.expand_by(qmax)
+ self.assertEqual(qmax, -Q.min())
+
+ Q.expand_by(-qmax.x, -qmax.y)
+ self.assertEqual(Q.max(), qmax)
+
+ self.assertEqual( (P+Q.min()).max(), P.max() + Q.min() )
+
+ self.assertEqual( (P-Q.max()).min(), P.min() - Q.max() )
+
+ self.assertEqual( P|P, P )
+
+ self.assertFalse( P != P )
+
+ Q.set_left(qmin.x)
+ Q.set_top(qmin.y)
+ Q.set_right(qmax.x)
+ Q.set_bottom(qmax.y)
+
+ self.assertAlmostEqual(Rect.distance(Point(), P), P.min().length())
+ self.assertAlmostEqual(Rect.distanceSq(Q.min(), P), Rect.distance(Q.min(), P)**2 )
+
+ self.assertEqual(P.round_outwards()[0], P[0].round_outwards())
+ if P.round_inwards():
+ self.assertEqual(P.round_inwards().Rect[1], P[1].round_inwards().Interval)
+
+
+ def intrect_basic(self, P, Q):
+ pmin = P.min()
+ pmax = P.max()
+ #for simplicity
+ self.assertTrue(pmin.x > 0)
+ self.assertTrue(pmin.y > 0)
+
+ self.assertAlmostEqual(pmin.x, P[0].min())
+ self.assertAlmostEqual(pmax.y, P[1].max())
+ self.assertEqual(pmin, P.corner(0))
+
+ self.assertEqual(pmin, IntPoint(P.left(), P.top()))
+ self.assertEqual(pmax, IntPoint(P.right(), P.bottom()))
+
+ self.assertAlmostEqual( P.width(), P[0].extent() )
+ self.assertAlmostEqual( P.height(), P[1].extent() )
+
+ self.assertAlmostEqual( P.aspect_ratio(), float(P.width())/float(P.height()) )
+ self.assertEqual( P.dimensions(), IntPoint( P.width(), P.height() ) )
+ self.assertEqual( P.midpoint().x, (P.min() + P.max()).x/2 )
+ self.assertAlmostEqual(P.area(), P.width()*P.height())
+
+ if P.area() > 0:
+ self.assertFalse(P.has_zero_area())
+ else:
+ self.assertTrue(P.has_zero_area())
+ self.assertAlmostEqual(P.max_extent(), max(P.width(), P.height()))
+ self.assertGreaterEqual(P.max_extent(), P.min_extent())
+
+ qmin = Q.min()
+ qmax = Q.max()
+
+ Q.set_min(P.midpoint())
+ Q.set_max(P.midpoint())
+ self.assertTrue(Q.has_zero_area())
+
+ Q.expand_by(P.min_extent()/3.0)
+
+ self.assertTrue(P.contains_rect(Q))
+ self.assertTrue(P.intersects(Q))
+ self.assertTrue(Q.intersects(P))
+ self.assertFalse(Q.contains_rect(P))
+
+ self.assertTrue(P.contains(P.midpoint()))
+ self.assertFalse(P.contains(P.midpoint()+P.midpoint()+P.midpoint()))
+
+ P.union_with(Q)
+
+ self.assertEqual( P.min(), pmin )
+
+ Q.set_left(qmin.x)
+ Q.set_top(qmin.y)
+ Q.set_right(qmax.x)
+ Q.set_bottom(qmax.y)
+
+ self.assertEqual(Q.min(), qmin)
+ self.assertEqual(Q.max(), qmax)
+
+ Q.expand_to( IntPoint() )
+ self.assertEqual(IntPoint(), Q.min())
+ Q.expand_by(qmax)
+ self.assertEqual(qmax, IntPoint()-Q.min())
+
+ Q.expand_by(-qmax.x, -qmax.y)
+ self.assertEqual(Q.max(), qmax)
+
+ self.assertEqual( (P+Q.min()).max(), P.max() + Q.min() )
+
+ self.assertEqual( (P-Q.max()).min(), P.min() - Q.max() )
+
+ self.assertEqual( P|P, P )
+
+ self.assertFalse( P != P )
+
+ Q.set_left(qmin.x)
+ Q.set_top(qmin.y)
+ Q.set_right(qmax.x)
+ Q.set_bottom(qmax.y)
+
+
+
+ def test_rect(self):
+
+ P = Rect(0.298, 2, 4, 5)
+
+ self.interval_basic(P[0], P[1])
+ G = Rect(sqrt(2), sqrt(2), sqrt(3), sqrt(3))
+ H = Rect.from_xywh(3.43232, 9.23214, 21.523, -0.31232)
+
+ self.rect_basic(P, G)
+ self.rect_basic(G, H)
+
+ lst = [Point(randint(-100, 100), randint(-100, 100)) for i in range(10)]
+
+ R = Rect.from_list(lst)
+
+ for p in lst:
+ self.assertTrue(R.contains(p))
+
+ self.assertAlmostEqual(min(lst).y, R.min().y)
+ self.assertAlmostEqual(max(lst).y, R.max().y)
+
+
+
+ def test_optRect(self):
+
+ P = OptRect(0.298, 2, 4, 5)
+ self.interval_basic(P.Rect[0], P.Rect[1])
+
+
+ G = Rect(sqrt(2), sqrt(2), sqrt(3), sqrt(3))
+ H = OptRect.from_rect(G)
+
+ self.rect_basic(P.Rect, G)
+
+ lst = [Point(randint(-100, 100), randint(-100, 100)) for i in range(10)]
+
+ R = OptRect.from_list(lst)
+
+ for p in lst:
+ self.assertTrue(R.Rect.contains(p))
+
+ self.assertAlmostEqual(min(lst).y, R.Rect.min().y)
+ self.assertAlmostEqual(max(lst).y, R.Rect.max().y)
+
+ Q = OptRect()
+ self.assertFalse(Q)
+ self.assertTrue(P)
+
+ self.assertTrue(Q.is_empty())
+ self.assertFalse(P.is_empty())
+
+ self.assertTrue(P.contains_rect( P ))
+ self.assertTrue(P.contains_rect(Q))
+ self.assertFalse(Q.contains_rect(P))
+ self.assertFalse(P.intersects(Q))
+ self.assertTrue(P.contains_rect(P.Rect))
+ self.assertTrue(P.contains(P.Rect.midpoint()))
+
+ self.assertEqual(P, OptRect.from_rect(P))
+
+ P.union_with(G)
+ P.union_with(H)
+ self.assertTrue(P.contains_rect(H))
+
+ P.intersect_with(G)
+ self.assertEqual(P, G)
+
+ self.assertEqual( P|H, G )
+ self.assertEqual( (P|R).Rect.min().x , min( P.Rect.min().x, R.Rect.min().x ))
+
+ self.assertFalse(P & Q)
+ self.assertEqual(P, P&P)
+
+ self.assertEqual( P & (R | H), (P & R) | (P & H) )
+
+ def test_intRect(self):
+ A = IntRect(2, 6, 9, 23)
+ B = IntRect.from_intervals(IntInterval(1, 5), IntInterval(8, 9))
+ C = IntRect.from_points(IntPoint(1, 8), IntPoint(5, 9))
+
+ self.assertEqual(B, C)
+
+ self.intrect_basic(A, B)
+ self.intrect_basic(B, C)
+ self.intrect_basic(C, A)
+
+ def test_optIntRect(self):
+ P = OptIntRect(1, 2, 4, 5)
+ self.interval_basic(P.Rect[0], P.Rect[1])
+
+
+ G = IntRect(2, 2, 3, 3)
+ H = OptIntRect.from_rect(G)
+
+ self.intrect_basic(P.Rect, G)
+
+ lst = [IntPoint(randint(-100, 100), randint(-100, 100)) for i in range(10)]
+
+ R = OptIntRect.from_list(lst)
+
+ for p in lst:
+ self.assertTrue(R.Rect.contains(p))
+
+ self.assertAlmostEqual(min(lst).y, R.Rect.min().y)
+ self.assertAlmostEqual(max(lst).y, R.Rect.max().y)
+
+ Q = OptIntRect()
+ self.assertFalse(Q)
+ self.assertTrue(P)
+
+ self.assertTrue(Q.is_empty())
+ self.assertFalse(P.is_empty())
+
+ self.assertTrue(P.contains_rect( P ))
+ self.assertTrue(P.contains_rect( P.Rect ))
+ self.assertTrue(P.contains_rect(Q))
+ self.assertFalse(Q.contains_rect(P))
+ self.assertFalse(P.intersects(Q))
+ self.assertTrue(P.contains_rect(P.Rect))
+ self.assertTrue(P.contains(P.Rect.midpoint()))
+
+ self.assertEqual(P, OptIntRect.from_rect(P))
+
+ P.union_with(G)
+ P.union_with(H)
+ self.assertTrue(P.contains_rect(H))
+
+ P.intersect_with(G)
+ self.assertEqual(P, G)
+
+ self.assertEqual( P|H, G )
+ self.assertEqual( (P|R).Rect.min().x , min( P.Rect.min().x, R.Rect.min().x ))
+
+ self.assertFalse(P & Q)
+ self.assertEqual(P, P&P)
+
+ self.assertEqual( P & (R | H), (P & R) | (P & H) )
+
+unittest.main()
diff --git a/src/3rdparty/2geom/src/cython/utils.py b/src/3rdparty/2geom/src/cython/utils.py
new file mode 100644
index 0000000..1115d32
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/utils.py
@@ -0,0 +1,52 @@
+from Tkinter import *
+
+import math
+
+import cy2geom
+from cy2geom import Point, Path
+
+
+def Nagon(N):
+ """Return N-agon with side of length 1."""
+ side = cy2geom.LineSegment(Point(-0.5, 0), Point(0.5, 0))
+ angle = 2*math.pi/N
+ distance_to_center = 0.5 / math.tan(math.pi/N)
+ return Path.fromList(
+ [ side.transformed(
+ cy2geom.Translate(Point(0, -distance_to_center))*
+ cy2geom.Rotate(angle*i))
+ for i in range(N)
+ ],
+ stitching = Path.STITCH_DISCONTINUOUS,
+ closed = True )
+
+def draw(c, dt=0.001, batch=10, scale=20, x_offset = 400, y_offset = 300):
+ """Draw curve or path."""
+ master = Tk()
+ w = Canvas(master, width=800, height=600)
+ w.pack()
+ n = 0
+ t = 0
+ points = []
+
+ if isinstance(c, Path):
+ maxt = c.size_default()
+ else:
+ maxt = 1
+
+ while (t < maxt):
+ t = n*dt
+ n+=1
+ p = c(t)
+ points.extend( [ p.x * scale + x_offset, p.y * scale + y_offset] )
+
+ while points:
+ draw_points = tuple(points[:batch*2])
+ if len(points) == 2:
+ break
+ del points[:batch*2]
+
+ l = w.create_line(*draw_points)
+ w.grid()
+
+ master.mainloop()
diff --git a/src/3rdparty/2geom/src/cython/wrapped-pyobject.h b/src/3rdparty/2geom/src/cython/wrapped-pyobject.h
new file mode 100644
index 0000000..bd316fb
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/wrapped-pyobject.h
@@ -0,0 +1,237 @@
+#include "Python.h"
+#include "2geom/generic-interval.h"
+#include "2geom/generic-rect.h"
+#include "2geom/d2.h"
+
+
+namespace Geom{
+
+//TODO! looks like memory leak
+class WrappedPyObject{
+private:
+ PyObject* self;
+public:
+ //~ int code;
+
+ WrappedPyObject(){
+ //~ printf("Created empty WPO at address %p\n", this);
+ self = NULL;
+ //~ code = 0;
+ }
+
+ WrappedPyObject(WrappedPyObject const &other){
+ self = other.getObj();
+ //~ code = other.code;
+ //~ printf("COPY-CONSTRUCTOR %p, this WPO %p, other WPO %p\n", self, this, &other);
+ Py_XINCREF(self);
+ }
+
+ WrappedPyObject(PyObject* arg){
+ if (arg == NULL){
+ //PyErr_Print();
+ //~ code = c;
+ }
+ else{
+ //~ printf("CONSTRUCTOR %p\n", arg);
+ Py_INCREF(arg);
+ self = arg;
+ //~ code = c;
+ }
+ }
+
+ WrappedPyObject(int c){
+ self = Py_BuildValue("i", c);
+ //~ printf("INT-OPERATOR= %p, this WPO %p, other WPO %p\n", self, this, &other);
+ Py_INCREF(self);
+ }
+
+
+ ~WrappedPyObject(){
+ //TODO Leaking memory
+ //~ printf("DECREF %p\n", self);
+ //Py_DECREF(self);
+ }
+
+ PyObject* getObj() const {
+ return self;
+ }
+
+ WrappedPyObject operator=(WrappedPyObject other){
+ if (this != &other){
+ self = other.getObj();
+ //~ printf("OPERATOR= %p, this WPO %p, other WPO %p\n", self, this, &other);
+ Py_XINCREF(self);
+ }
+ return *this;
+ }
+
+ WrappedPyObject operator=(int other){
+
+ self = Py_BuildValue("i", other);
+ //~ printf("INT-OPERATOR= %p, this WPO %p, other WPO %p\n", self, this, &other);
+ Py_INCREF(self);
+
+ return *this;
+ }
+
+ WrappedPyObject operator-() const {
+ PyObject * ret;
+ ret = PyObject_CallMethodObjArgs(self, Py_BuildValue("s", "__neg__"), NULL);
+ if (ret == NULL){
+ Py_INCREF(Py_None);
+ return WrappedPyObject(Py_None);
+ }
+ //Py_INCREF(ret);
+ WrappedPyObject * retw = new WrappedPyObject(ret);
+ //Py_DECREF(ret);
+ return *retw;
+ }
+
+ WrappedPyObject arithmetic(PyObject* const other, std::string method, std::string rmethod) const {
+ PyObject * ret;
+ //printf("%p %p\n", self, other);
+ ret = PyObject_CallMethodObjArgs(self, Py_BuildValue("s", method.c_str()), other, NULL);
+ if (ret == NULL){
+ Py_INCREF(Py_None);
+ return WrappedPyObject(Py_None);
+ }
+ PyObject * isNI = PyObject_RichCompare(ret, Py_NotImplemented, Py_EQ);
+ if ( PyInt_AsLong(isNI) ){
+ ret = PyObject_CallMethodObjArgs(other, Py_BuildValue("s", rmethod.c_str()), self, NULL);
+ }
+ if (ret == NULL){
+ Py_INCREF(Py_None);
+ return WrappedPyObject(Py_None);
+ }
+ WrappedPyObject * retw = new WrappedPyObject(ret);
+ return *retw;
+
+ }
+
+ WrappedPyObject operator+(WrappedPyObject const other) const {
+ return arithmetic(other.getObj(), "__add__", "__radd__");
+ }
+
+ WrappedPyObject operator-(WrappedPyObject const other){
+ return arithmetic(other.getObj(), "__sub__", "__rsub__");
+ }
+
+ WrappedPyObject operator*(WrappedPyObject const other){
+ return arithmetic(other.getObj(), "__mul__", "__rmul__");
+ }
+
+ WrappedPyObject operator*(int other){
+ PyObject* other_obj = Py_BuildValue("i", other);
+ //Py_INCREF(other_obj);
+ WrappedPyObject ret = arithmetic(other_obj, "__mul__", "__rmul__");
+ //Py_DECREF(other_obj);
+ return ret;
+ }
+
+ WrappedPyObject operator/(int other){
+ PyObject* other_obj = Py_BuildValue("i", other);
+ Py_INCREF(other_obj);
+ WrappedPyObject ret = arithmetic(other_obj, "__div__", "__rdiv__");
+ Py_DECREF(other_obj);
+ return ret;
+ }
+
+ bool richcmp(WrappedPyObject const &other, int op) const {
+ PyObject * ret;
+ long retv;
+ ret = PyObject_RichCompare(self, other.getObj(), op);
+ retv = PyInt_AsLong(ret);
+ return retv;
+ }
+
+ bool operator<(WrappedPyObject const &other) const {
+ return richcmp(other, Py_LT);
+ }
+
+ bool operator<=(WrappedPyObject const &other) const {
+ return richcmp(other, Py_LE);
+ }
+
+ bool operator>=(WrappedPyObject const &other) const{
+ return richcmp(other, Py_GE);
+ }
+
+ bool operator>(WrappedPyObject const &other) const {
+ return richcmp(other, Py_GT);
+ }
+
+ bool operator==(WrappedPyObject const &other) const {
+ return richcmp(other, Py_EQ);
+ }
+
+
+ bool operator<(int const c) const {
+ return richcmp(WrappedPyObject(c), Py_LT);
+ }
+
+ bool operator<=(int const c) const {
+ return richcmp(WrappedPyObject(c), Py_LE);
+ }
+
+ bool operator>=(int const c) const{
+ return richcmp(WrappedPyObject(c), Py_GE);
+ }
+
+ bool operator>(int const c) const {
+ return richcmp(WrappedPyObject(c), Py_GT);
+ }
+
+ bool operator==(int const c) const {
+ return richcmp(WrappedPyObject(c), Py_EQ);
+ }
+
+
+ WrappedPyObject operator+=(WrappedPyObject other){
+ *this = *this + other;
+ return *this;
+
+ }
+
+ WrappedPyObject operator-=(WrappedPyObject other){
+ *this = *this - other;
+ return *this;
+ }
+};
+
+typedef GenericInterval<WrappedPyObject> PyInterval;
+typedef GenericOptInterval<WrappedPyObject> PyOptInterval;
+
+typedef GenericRect<WrappedPyObject> PyRect;
+typedef GenericOptRect<WrappedPyObject> PyOptRect;
+
+typedef D2<WrappedPyObject> PyPoint;
+
+template<>
+struct CoordTraits<WrappedPyObject> {
+ typedef PyPoint PointType;
+ typedef PyInterval IntervalType;
+ typedef PyOptInterval OptIntervalType;
+ typedef PyRect RectType;
+ typedef PyOptRect OptRectType;
+
+ typedef
+ boost::equality_comparable< PyInterval
+ , boost::additive< PyInterval
+ , boost::multipliable< PyInterval
+ , boost::orable< PyInterval
+ , boost::arithmetic< PyInterval, WrappedPyObject
+ > > > > >
+ IntervalOps;
+
+ typedef
+ boost::equality_comparable< PyRect
+ //, boost::equality_comparable< PyRect, IntRect
+ , boost::orable< PyRect
+ , boost::orable< PyRect, PyOptRect
+ , boost::additive< PyRect, PyPoint
+ //, boost::multipliable< Rect, Affine
+ > > > > //> >
+ RectOps;
+};
+
+}
diff --git a/src/3rdparty/2geom/src/cython/wrapper.py b/src/3rdparty/2geom/src/cython/wrapper.py
new file mode 100644
index 0000000..241782a
--- /dev/null
+++ b/src/3rdparty/2geom/src/cython/wrapper.py
@@ -0,0 +1,360 @@
+import os
+import sys
+import argparse
+
+from pygccxml import parser, declarations
+
+class wType:
+ def __init__(self, c_str):
+ self.c_str = c_str
+ self.wrapped_types = ["bint", "double", "int", "unsigned int",
+ "Coord", "IntCoord", "Dim2", "size_t"]
+
+ def get_C(self):
+ """returns plain c string"""
+ return self.c_str
+
+ def get_Cython_type(self):
+ """Returns corresponding Cython type string"""
+ typestr= self.get_C()
+ typestr= typestr.replace(" const ", " ")
+ if typestr.find("::Geom::")==0:
+ typestr = typestr[len("::Geom::"):]
+ if typestr == "bool":
+ typestr = "bint"
+ return typestr
+
+ def get_Python_function_argument(self):
+ """Returns argument type to Python function call"""
+
+ typestr = self.get_Cython_type()
+ if typestr[-1]=="&":
+ typestr = typestr[:-2]
+ if typestr in self.wrapped_types:
+ return typestr+" "
+ return "cy_"+typestr+" "
+ def get_Python_return(self):
+ """ Returns a string used to wrap a function returning this type
+ returns a string to be called with format( 'function call to c function ')
+ """
+ typestr = self.get_Cython_type()
+
+ if typestr[-1] == "&":
+ typestr = typestr[:-2]
+ if typestr in self.wrapped_types:
+ return "return {}"
+ if typestr == "void":
+ return "{}"
+ if typestr[-1] == "*":
+ typestr = typestr[:-2]+"_p"
+ return "return wrap_"+typestr+"({})"
+
+ def get_wrap_method(self, delim):
+ """Returns wrap method in a form of a list of lines"""
+ ret = []
+ typestr = self.get_Cython_type()
+
+ if typestr[-1] == "&":
+ typestr = typestr[:-2]
+ if typestr in self.wrapped_types:
+ return []
+ if typestr == "void":
+ return []
+ if typestr[-1] == "*":
+ typestr = typestr[:-2]+"_p"
+ ret.append("cdef cy_{} wrap_{}({} p):".format(typestr, typestr, typestr))
+ ret.append(delim+"cdef {} * retp = new {}()".format(typestr, typestr))
+ ret.append(delim+"retp[0] = p")
+ ret.append(delim+"cdef cy_{} r = cy_{}.__new__(cy_{})".format(typestr, typestr, typestr))
+ ret.append(delim+"r.thisptr = retp")
+ ret.append(delim+"return r")
+ return ret
+
+ def get_Python_pass_argument(self):
+ """ Returns argument to be passed to C function, to be called with .format(arg_name)"""
+ typestr = self.get_Cython_type()
+ if typestr[-1]=="&":
+ typestr = typestr[:-2]
+ if typestr in self.wrapped_types:
+ return "{}"
+ if typestr[-1] == "*":
+ return "{}.thisptr"
+ return "deref( {}.thisptr )"
+
+class CythonWrapper:
+ def __init__(self, gn):
+ self.global_namespace = gn
+ self.delim = ' '
+
+ def wrap_constructor(self, constructor, types_dict):
+ pxd_lines = []
+ pyx_lines = []
+
+ pxd_arguments = []
+ for argument_type in constructor.argument_types:
+ pxd_arguments.append( types_dict[argument_type.decl_string].get_Cython_type() )
+ pxd_argument_str = "({})".format(", ".join(pxd_arguments))
+
+ pxd_function_str = constructor.name+pxd_argument_str
+ pxd_lines.append(self.delim*2+pxd_function_str)
+
+ #python function
+ arguments_python = ["self"]
+ for argument in constructor.arguments:
+ arguments_python.append(types_dict[argument.type.decl_string].get_Python_function_argument()+argument.name)
+ declaration = "def {}".format("__init__")+"({}):".format(", ".join(arguments_python))
+
+ arguments_cython = []
+ for argument in constructor.arguments:
+ arguments_cython.append(types_dict[argument.type.decl_string].get_Python_pass_argument().format(argument.name))
+ function_call = "new "+constructor.name+"({})".format(", ".join(arguments_cython))
+
+ return_statement = "self.thisptr = {}".format(function_call)
+ pyx_lines.append(self.delim+declaration)
+ pyx_lines.append(self.delim*2 + return_statement)
+
+ return (pxd_lines, pyx_lines)
+
+ def wrap_operator(self, operator, types_dict):
+ pxd_lines = []
+ pyx_lines = []
+
+ pxd_arguments = []
+ for argument_type in operator.argument_types:
+ pxd_arguments.append( types_dict[argument_type.decl_string].get_Cython_type() )
+ pxd_argument_str = "({})".format(", ".join(pxd_arguments))
+ boost_wrapped = ["operator{}=".format(i) for i in ["+", "-", "*", "/", "|", "&"]]
+ pxd_function_str = types_dict[operator.return_type.decl_string].get_Cython_type()+\
+ " "+operator.name+pxd_argument_str
+
+ if not (operator.name in boost_wrapped):
+ pxd_lines.append(self.delim*2+pxd_function_str)
+
+ else:
+ pxd_lines.append(self.delim*2+"#"+pxd_function_str)
+
+ pxd_function_str = types_dict[operator.return_type.decl_string].get_Cython_type()+\
+ " "+operator.name[:-1]+pxd_argument_str
+ pxd_lines.append(self.delim*2+pxd_function_str)
+
+
+ special_methods = {
+ "+" : "__add__",
+ "-" : "__sub__",
+ "*" : "__mul__",
+ "/" : "__div__",
+ "|" : "__or__",
+ "&" : "__and__",
+ "[]": "__getitem__",
+ "()": "__call__",
+ "==": "__richcmp__",
+ "!=": "__richcmp__"
+ }
+
+ if operator.name in boost_wrapped:
+ operation = operator.name[-2]
+ else:
+ operation = operator.name[ len("operator"): ]
+
+ if operation in special_methods:
+ python_name = special_methods[operation]
+ else:
+ python_name = operator.name
+
+ arguments_python = ["self"]
+ for argument in operator.arguments:
+ arguments_python.append(types_dict[argument.type.decl_string].get_Python_function_argument()+argument.name)
+ declaration = "def {}".format(python_name)+"({}):".format(", ".join(arguments_python))
+
+ arguments_cython = []
+ for argument in operator.arguments:
+ arguments_cython.append(types_dict[argument.type.decl_string].get_Python_pass_argument().format(argument.name))
+ function_call = "deref( self.thisptr ) "+operation+" {}".format(", ".join(arguments_cython))
+
+ return_statement = types_dict[operator.return_type.decl_string].get_Python_return().format(function_call)
+
+ if (operator.arguments == []) and (operation == '-'):
+ declaration = "def __neg__(self):"
+ pyx_lines.append(self.delim+declaration)
+ pyx_lines.append(self.delim*2 + return_statement)
+
+ return (pxd_lines, pyx_lines)
+
+ def wrap_method(self, method, types_dict):
+ pxd_lines = []
+ pyx_lines = []
+
+ pxd_arguments = []
+ for argument_type in method.argument_types:
+ pxd_arguments.append( types_dict[argument_type.decl_string].get_Cython_type() )
+ pxd_argument_str = "({})".format(", ".join(pxd_arguments))
+
+
+ pxd_function_str = types_dict[method.return_type.decl_string].get_Cython_type()+\
+ " "+method.name+pxd_argument_str
+ pxd_lines.append(self.delim*2+pxd_function_str)
+
+ #python function
+ arguments_python = ["self"]
+ for argument in method.arguments:
+ arguments_python.append(types_dict[argument.type.decl_string].get_Python_function_argument()+argument.name)
+ declaration = "def {}".format(method.name)+"({}):".format(", ".join(arguments_python))
+
+ arguments_cython = []
+ for argument in method.arguments:
+ arguments_cython.append(types_dict[argument.type.decl_string].get_Python_pass_argument().format(argument.name))
+ function_call = "self.thisptr."+method.name+"({})".format(", ".join(arguments_cython))
+
+ return_statement = types_dict[method.return_type.decl_string].get_Python_return().format(function_call)
+ pyx_lines.append(self.delim+declaration)
+ pyx_lines.append(self.delim*2 + return_statement)
+
+ return (pxd_lines, pyx_lines)
+
+ def wrap_free_function(self, function, types_dict):
+ pxd_lines = []
+ pyx_lines = []
+ decl_lines = []
+
+ pxd_arguments = []
+ for argument_type in function.argument_types:
+ pxd_arguments.append( types_dict[argument_type.decl_string].get_Cython_type() )
+ pxd_argument_str = "({})".format(", ".join(pxd_arguments))
+
+
+ pxd_function_str = types_dict[function.return_type.decl_string].get_Cython_type()+\
+ " "+function.name+pxd_argument_str
+ pxd_lines.append(self.delim+pxd_function_str)
+
+ #python function
+ arguments_python = []
+ for argument in function.arguments:
+ arguments_python.append(types_dict[argument.type.decl_string].get_Python_function_argument()+argument.name)
+ declaration = "def cy_{}".format(function.name)+"({}):".format(", ".join(arguments_python))
+
+ decl_lines.append("from _cy_??? import cy_{0} as {0}".format(function.name))
+
+ arguments_cython = []
+ for argument in function.arguments:
+
+ arguments_cython.append(types_dict[argument.type.decl_string].get_Python_pass_argument().format(argument.name))
+ function_call = function.name+"({})".format(", ".join(arguments_cython))
+
+ return_statement = types_dict[function.return_type.decl_string].get_Python_return().format(function_call)
+ pyx_lines.append(declaration)
+ pyx_lines.append(self.delim + return_statement)
+
+ return (pxd_lines, pyx_lines, decl_lines)
+
+
+ def wrap_class(self, class_name, class_file):
+ pxd_lines = []
+ pyx_lines = []
+ decl_lines = []
+ other_lines = []
+
+ pxd_lines.append("cdef extern from \"2geom/{}\" namespace \"Geom\":".format(class_file))
+ pxd_lines.append(self.delim+"cdef cppclass {}:".format(class_name))
+ pyx_lines.append("cdef class cy_{}:".format(class_name))
+ pyx_lines.append(self.delim+"cdef {}* thisptr".format(class_name))
+ #get_types
+ types_dict = self.collect_types(class_name)
+ #parse
+ c_class = self.global_namespace.namespace(name = "Geom").class_(name=class_name)
+
+ for member in c_class.get_members():
+ if isinstance(member, declarations.calldef.constructor_t):
+ pxd, pyx = self.wrap_constructor(member, types_dict)
+ pxd_lines += pxd
+ pyx_lines += pyx
+ elif isinstance(member, declarations.calldef.member_operator_t):
+ pxd, pyx = self.wrap_operator(member, types_dict)
+ pxd_lines += pxd
+ pyx_lines += pyx
+ elif isinstance(member, declarations.calldef.member_function_t):
+ pxd, pyx = self.wrap_method(member, types_dict)
+ pxd_lines += pxd
+ pyx_lines += pyx
+
+ pyx_lines.append("#free functions:")
+ for ff in self.global_namespace.namespace(name = "Geom").free_funs():
+ if os.path.basename(ff.location.file_name) == class_file:
+ pxd, pyx, decl = self.wrap_free_function(ff, types_dict)
+ pxd_lines += map(lambda x: x[4:], pxd)
+ pyx_lines += pyx
+ decl_lines += decl
+
+ for ff in self.global_namespace.namespace(name = "Geom").free_operators():
+ if os.path.basename(ff.location.file_name) == class_file:
+ pxd, pyx = self.wrap_operator(ff, types_dict)
+ pxd_lines += map(lambda x: x[4:], pxd)
+ pyx_lines += pyx
+
+ pyx_lines.append("")
+ for ctype in types_dict:
+ wtype = types_dict[ctype]
+ for line in wtype.get_wrap_method(self.delim):
+ pyx_lines.append(line)
+ print "------"
+ for i in pxd_lines:
+ print i
+ print "------"
+ for i in pyx_lines:
+ print i
+ print "------"
+ for i in decl_lines:
+ print i
+
+
+ def collect_types(self, class_name):
+ types_set = set()
+ c_class = self.global_namespace.namespace(name = "Geom").class_(name=class_name)
+ for member in c_class.get_members():
+ if any([isinstance(member, declarations.calldef.constructor_t),
+ isinstance(member, declarations.calldef.member_operator_t),
+ isinstance(member, declarations.calldef.member_function_t)]):
+ for a_type in member.argument_types:
+ types_set.add(a_type.decl_string)
+ if isinstance(member, declarations.calldef.member_operator_t) or isinstance(member, declarations.calldef.member_function_t):
+ types_set.add(member.return_type.decl_string)
+ for ff in list(self.global_namespace.namespace(name = "Geom").free_funs()) + list(self.global_namespace.namespace(name = "Geom").free_operators()):
+ for a_type in ff.argument_types:
+ types_set.add(a_type.decl_string)
+ types_set.add(ff.return_type.decl_string)
+ types_dict = dict()
+
+ for f_type in types_set:
+
+ types_dict[f_type] = wType(f_type)
+ return types_dict
+
+def main():
+
+ #set up argument parser
+ cmd_parser = argparse.ArgumentParser()
+ cmd_parser.add_argument('--lib2geom_dir', action = 'store')
+ cmd_parser.add_argument('--file_name', action = 'store')
+ cmd_parser.add_argument('--class_name', action = 'store')
+ cmd_args = cmd_parser.parse_args()
+
+ #set up pygccxml
+ includes = [cmd_args.lib2geom_dir,
+ os.path.join(cmd_args.lib2geom_dir, 'src'),
+ "/usr/include/boost"]
+
+ config = parser.config_t(compiler='gcc',
+ include_paths=includes,
+ cflags="")
+
+ file_to_parse = [os.path.join(cmd_args.lib2geom_dir, "src", "2geom", cmd_args.file_name)]
+
+ decls = parser.parse( file_to_parse, config )
+ global_namespace = declarations.get_global_namespace( decls )
+ wrapper = CythonWrapper(global_namespace)
+ wrapper.wrap_class(cmd_args.class_name, cmd_args.file_name)
+
+main()
+
+#run with
+#python2 wrapper.py --lib2geom_dir ../../.. --file_name int-point.h --class_name IntPoint
+#from cython-bindings directory
diff --git a/src/3rdparty/2geom/src/performance-tests/CMakeLists.txt b/src/3rdparty/2geom/src/performance-tests/CMakeLists.txt
new file mode 100644
index 0000000..60ceaa3
--- /dev/null
+++ b/src/3rdparty/2geom/src/performance-tests/CMakeLists.txt
@@ -0,0 +1,27 @@
+SET(2GEOM_PERFORMANCE_TESTS_SRC
+example-performance-test
+boolops-performance-test
+bendpath-test
+bezier-utils-test
+parse-svg-test
+path-operations-test
+)
+
+add_custom_target(perf)
+
+OPTION(2GEOM_PERFORMANCE_TESTS
+ "Build the performance tests"
+ ON)
+IF(2GEOM_PERFORMANCE_TESTS)
+ FOREACH(source ${2GEOM_PERFORMANCE_TESTS_SRC})
+ ADD_EXECUTABLE(${source} ${source}.cpp)
+ target_link_libraries(${source} 2Geom::2geom)
+ add_dependencies(perf ${source})
+ add_custom_command(TARGET perf COMMAND ${source})
+ ENDFOREACH(source)
+ENDIF()
+
+IF(WIN32 AND 2GEOM_BUILD_SHARED)
+ ADD_CUSTOM_TARGET(copy-perf ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_BINARY_DIR}/src/2geom/lib2geom.dll ${CMAKE_BINARY_DIR}/src/performance-tests/lib2geom.dll)
+ ADD_DEPENDENCIES(copy-perf 2geom)
+ENDIF()
diff --git a/src/3rdparty/2geom/src/performance-tests/bendpath-test.cpp b/src/3rdparty/2geom/src/performance-tests/bendpath-test.cpp
new file mode 100644
index 0000000..30fc500
--- /dev/null
+++ b/src/3rdparty/2geom/src/performance-tests/bendpath-test.cpp
@@ -0,0 +1,128 @@
+/*
+ * Test performance of
+ *
+ * Copyright (C) Authors 2007-2013
+ * Authors:
+ * Johan Engelen <j.b.c.engelen@alumnus.utwente.nl>
+ * Steren Giannini <steren.giannini@gmail.com>
+ *
+ * the test part was taken from Inkscape's Bend Path LPE (and simplified a bit)
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+
+#include <iostream>
+#include <ctime>
+
+#include "2geom/svg-path-parser.h"
+#include "2geom/pathvector.h"
+#include "2geom/path.h"
+#include "2geom/d2.h"
+#include "2geom/piecewise.h"
+#include "2geom/sbasis.h"
+using namespace Geom;
+
+static char const *path_str =
+ "M -460,523.79076 C -460.65718,514.47985 -460.79228,505.75495 -460.43635,497.52584 -460.08041,489.29674 "
+ "-459.23345,481.56342 -457.92649,474.23566 -456.61954,466.9079 -454.85259,459.9857 -452.65671,453.37885 "
+ "-450.46083,446.77199 -447.836,440.48046 -444.81328,434.41405 -441.79056,428.34764 -438.36994,422.50633 "
+ "-434.58247,416.79991 -430.79501,411.0935 -426.64069,405.52196 -422.15057,399.99508 -417.66045,394.4682 "
+ "-412.83452,388.98598 -407.70384,383.4582 -402.57316,377.93041 -397.13772,372.35705 -391.42857,366.6479 "
+ "-378.14065,353.35999 -362.09447,346.86737 -344.03764,345.52929 -325.98081,344.19121 -305.91333,348.00766 "
+ "-284.58283,355.33787 -263.25234,362.66809 -240.65882,373.51207 -217.5499,386.22904 -194.44098,398.94602 "
+ "-170.81666,413.53598 -147.42457,428.35818 -124.03248,443.18037 -100.87262,458.2348 -78.692608,471.88067 "
+ "-56.512594,485.52655 -35.312431,497.76389 -15.839741,506.95191 3.632948,516.13994 21.378163,522.27865 "
+ "36.648281,523.72729 51.918398,525.17592 64.713417,521.93448 74.285714,512.36218 76.124134,510.52376 "
+ "78.521676,506.73937 81.393111,501.43833 84.264546,496.13729 87.609874,489.31958 91.343869,481.41453 "
+ "95.077864,473.50947 99.200524,464.51706 103.62662,454.86661 108.05272,445.21615 112.78226,434.90765 "
+ "117.73001,424.37041 122.67776,413.83317 127.84371,403.0672 133.14266,392.50178 138.4416,381.93637 "
+ "143.87352,371.57153 149.3532,361.83656 154.83288,352.10159 160.36031,342.99649 165.85028,334.95058 "
+ "171.34024,326.90466 176.79273,319.91793 182.12252,314.41968 189.27211,307.04412 196.34366,301.16926 "
+ "203.28385,296.57404 210.22405,291.97882 217.03288,288.66325 223.65704,286.40628 230.2812,284.1493 "
+ "236.72068,282.95093 242.92215,282.59009 249.12362,282.22926 255.08709,282.70597 260.75924,283.79918 "
+ "266.43138,284.89239 271.8122,286.60209 276.84836,288.70724 281.88453,290.81239 286.57604,293.31298 "
+ "290.86959,295.98796 295.16313,298.66294 299.0587,301.51232 302.50297,304.31504 305.94724,307.11776 "
+ "308.94022,309.87382 311.42857,312.36218 317.70879,318.6424 325.20531,326.50894 333.6587,335.29576 "
+ "342.11209,344.08258 351.52235,353.78967 361.63006,363.75101 371.73777,373.71235 382.54293,383.92792 "
+ "393.78611,393.7317 405.02929,403.53547 416.71049,412.92744 428.57029,421.24156 440.43008,429.55569 "
+ "452.46847,436.79197 464.42603,442.28436 476.38359,447.77676 488.26032,451.52527 499.7968,452.86385 "
+ "511.33327,454.20243 522.52948,453.13109 533.12602,448.98378 543.72255,444.83647 553.7194,437.61319 "
+ "562.85714,426.6479";
+
+static char const *bend_str =
+ "M -489.19983,473.24818 C -478.58599,460.43092 -465.31914,447.40133 -450.91614,434.95746 -436.51315,422.51359 "
+ "-420.97403,410.65543 -405.81565,400.18102 -390.65727,389.70661 -375.87963,380.61595 -362.99962,373.70708 "
+ "-350.11961,366.79821 -339.13723,362.07112 -331.56936,360.32386 -323.49864,358.4605 -311.32246,357.96153 "
+ "-296.07049,358.53595 -280.81852,359.11038 -262.49077,360.7582 -242.11692,363.18844 -221.74308,365.61867 "
+ "-199.32313,368.83132 -175.88677,372.53539 -152.45042,376.23947 -127.99765,380.43497 -103.55815,384.83091 "
+ "-90.798706,387.12596 -78.042879,389.47564 -65.437198,391.83855 -52.831517,394.20146 -40.375984,396.57759 "
+ "-28.217127,398.92554 -16.058269,401.27349 -4.1960885,403.59326 7.2228872,405.84343 18.641863,408.09361 "
+ "29.617633,410.27419 40.00367,412.34378 50.09967,414.35557 59.638414,416.26247 68.485308,418.02645 "
+ "77.332201,419.79043 85.487246,421.41149 92.815847,422.85159 100.14445,424.29169 106.64661,425.55083 "
+ "112.18773,426.59098 117.72885,427.63113 122.30894,428.45228 125.7934,429.01641 134.20502,430.37823 "
+ "142.47705,429.25391 150.64115,426.35391 158.80525,423.45391 166.86142,418.77822 174.84134,413.03729 "
+ "182.82125,407.29637 190.72491,400.49022 198.58398,393.32929 206.44305,386.16836 214.25752,378.65265 "
+ "222.05908,371.49262 227.06421,366.89906 232.06402,362.4519 237.06688,358.33874 242.06974,354.22557 "
+ "247.07564,350.44641 252.09294,347.18884 257.11025,343.93127 262.13896,341.1953 267.18744,339.16853 "
+ "272.23593,337.14176 277.30418,335.82419 282.40056,335.40342 293.00641,334.52778 302.22965,341.02775 "
+ "310.80162,351.57579 319.37358,362.12384 327.29427,376.71996 335.29503,392.03663 343.29579,407.3533 "
+ "351.37662,423.39051 360.26886,436.82075 369.1611,450.25099 378.86474,461.07425 390.11114,465.96301 "
+ "401.98566,471.1248 423.45174,470.72496 449.88663,467.14319 476.32151,463.56143 507.72518,456.79775 "
+ "539.47487,449.23188 571.22455,441.66601 603.32025,433.29795 631.13918,426.50743 658.9581,419.7169 "
+ "688.21455,391.64677 702.85715,390.39104";
+
+
+// adapted from Inkscape's BendPath LPE
+Geom::Piecewise<Geom::D2<Geom::SBasis> > doEffect_pwd2(Geom::Piecewise<Geom::D2<Geom::SBasis> > const &pwd2_in,
+ Piecewise<D2<SBasis> > const &bend_path)
+{
+ Piecewise<D2<SBasis> > uskeleton = arc_length_parametrization(bend_path, 2, .1);
+ uskeleton = remove_short_cuts(uskeleton, .01);
+ Piecewise<D2<SBasis> > n = rot90(derivative(uskeleton));
+ n = force_continuity(remove_short_cuts(n, .1));
+
+ D2<Piecewise<SBasis> > patternd2 = make_cuts_independent(pwd2_in);
+ Piecewise<SBasis> x = Piecewise<SBasis>(patternd2[1]);
+ Piecewise<SBasis> y = Piecewise<SBasis>(patternd2[0]);
+
+ Geom::OptRect bbox = bounds_exact(pwd2_in);
+ Interval bboxHorizontal = (*bbox)[Geom::X];
+ Interval bboxVertical = (*bbox)[Geom::Y];
+
+ x -= bboxHorizontal.min();
+ y -= bboxVertical.middle();
+
+ double scaling = uskeleton.cuts.back() / bboxHorizontal.extent();
+
+ if (scaling != 1.0) {
+ x *= scaling;
+ y *= scaling;
+ }
+
+ Piecewise<D2<SBasis> > output = compose(uskeleton, x) + y * compose(n, x);
+ return output;
+}
+
+
+int main()
+{
+ for (int rep = 0; rep < 3; rep++) {
+ const int num_repeats = 100;
+ PathVector path1 = parse_svg_path(path_str);
+ PathVector path2 = parse_svg_path(bend_str);
+ Piecewise<D2<SBasis> > pwd2_path = path1[0].toPwSb();
+ Piecewise<D2<SBasis> > pwd2_bend = path2[0].toPwSb();
+ std::clock_t start = std::clock();
+ for (int i = 0; i < num_repeats; i++) {
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > result = doEffect_pwd2(pwd2_path, pwd2_bend);
+ }
+ std::clock_t stop = std::clock();
+ std::cout << "Bend paths (" << num_repeats << "x): " << (stop - start) * (1000. / CLOCKS_PER_SEC) << " ms "
+ << std::endl;
+ }
+}
+
+
+
+// \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/performance-tests/bezier-utils-test.cpp b/src/3rdparty/2geom/src/performance-tests/bezier-utils-test.cpp
new file mode 100644
index 0000000..111d939
--- /dev/null
+++ b/src/3rdparty/2geom/src/performance-tests/bezier-utils-test.cpp
@@ -0,0 +1,133 @@
+/*
+ * Test performance of bezier-util fitting code
+ *
+ * Copyright (C) authors 2013
+ * Authors:
+ * Johan Engelen <j.b.c.engelen@alumnus.utwente.nl>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+
+#include <iostream>
+#include <ctime>
+
+#include "2geom/bezier-utils.h"
+#include "2geom/path.h"
+using namespace Geom;
+
+//static const Point data[] = { Point(0, 0), Point(1, 0), Point( 2, 0 ), Point( 1, 1 )};
+static const Point data[] = { Point( 0, 0 ), Point( 1, 0 ), Point( 2, 0 ), Point( 1, 1 ),
+ Point( 1, 2 ), Point( 1, 3 ), Point( 3, 0 ), Point( 4, 0 ),
+ Point( 2, 0 ), Point( 1, 1 ), Point( 1, 2 ), Point( 2, 0 ),
+ Point( 1, 0 ), Point( 2, 0 ), Point( 1, 3 ), Point( 1, 4 ),
+ Point( 1, 2 ), Point( 1, 1 ), Point( 0, 0 ), Point( 1, 0 ),
+ Point( 2, 0 ), Point( 1, 1 ), Point( 1, 2 ), Point( 1, 3 ),
+ Point( 4, 0 ), Point( 2, 0 ), Point( 1, 1 ), Point( 1, 2 ),
+ Point( 2, 0 ), Point( 1, 0 ), Point( 2, 0 ), Point( 1, 3 ),
+ Point( 1, 4 ), Point( 1, 2 ), Point( 1, 1 ), Point( 2, 1 ) };
+
+static const unsigned int data_len = sizeof(data)/sizeof(Point);
+
+
+
+// code test with 2geom types
+Path interpolateToPath(std::vector<Point> const &points, double tolerance_sq, unsigned max_beziers)
+{
+ Geom::Point *b = new Geom::Point[max_beziers*4];
+ Geom::Point *points_array = new Geom::Point[4 * points.size()]; // for safety, do a copy into a vector. I think it
+ // is possible to simply pass &points[0] as a
+ // Point[], but I am not sure
+ for (size_t i = 0; i < points.size(); ++i) {
+ points_array[i] = points.at(i);
+ }
+
+ int const n_segs = Geom::bezier_fit_cubic_r(b, points_array, points.size(), tolerance_sq, max_beziers);
+
+ Geom::Path fit;
+ if (n_segs > 0) {
+ fit.start(b[0]);
+ for (int c = 0; c < n_segs; c++) {
+ fit.appendNew<Geom::CubicBezier>(b[4 * c + 1], b[4 * c + 2], b[4 * c + 3]);
+ }
+ }
+
+ delete[] b;
+ delete[] points_array;
+
+ return fit;
+};
+
+
+Path interpolateToPath2(std::vector<Point> const &points, double tolerance_sq, unsigned max_beziers)
+{
+ std::vector<Point> b(max_beziers * 4);
+
+ int const n_segs = Geom::bezier_fit_cubic_r(b.data(), points.data(), points.size(), tolerance_sq, max_beziers);
+
+ Geom::Path fit;
+ if (n_segs > 0) {
+ fit.start(b[0]);
+ for (int c = 0; c < n_segs; c++) {
+ fit.appendNew<Geom::CubicBezier>(b[4 * c + 1], b[4 * c + 2], b[4 * c + 3]);
+ }
+ }
+
+ return fit;
+};
+
+
+int main()
+{
+ std::vector<Point> data_vector;
+ for (auto i : data) {
+ data_vector.push_back(i);
+ }
+
+ const int num_repeats = 2000;
+
+ unsigned max_beziers = data_len*2;
+ double tolerance_sq = 0.01;
+
+ for (int rep = 0; rep < 3; rep++) {
+ std::clock_t start = std::clock();
+ for (int i = 0; i < num_repeats; i++) {
+ Point *bezier = new Point[max_beziers*4]; // large array on stack = not good, so allocate on heap
+ int n_segs = bezier_fit_cubic_r(bezier, data, data_len, tolerance_sq, max_beziers);
+ (void) n_segs;
+ delete[] bezier;
+ }
+ std::clock_t stop = std::clock();
+ std::cout << "bezier_fit_cubic_r C-array (" << num_repeats << "x): " << (stop - start) * (1000. / CLOCKS_PER_SEC) << " ms "
+ << std::endl;
+ }
+
+ for (int rep = 0; rep < 3; rep++) {
+ std::clock_t start = std::clock();
+ for (int i = 0; i < num_repeats; i++) {
+ Path path = interpolateToPath(data_vector, tolerance_sq, max_beziers);
+ int n_segs = path.size();
+ (void) n_segs;
+ }
+ std::clock_t stop = std::clock();
+ std::cout << "bezier_fit_cubic_r 2Geom interoperability (" << num_repeats << "x): " << (stop - start) * (1000. / CLOCKS_PER_SEC) << " ms "
+ << std::endl;
+ }
+
+ for (int rep = 0; rep < 3; rep++) {
+ std::clock_t start = std::clock();
+ for (int i = 0; i < num_repeats; i++) {
+ Path path = interpolateToPath2(data_vector, tolerance_sq, max_beziers);
+ int n_segs = path.size();
+ (void) n_segs;
+ }
+ std::clock_t stop = std::clock();
+ std::cout << "bezier_fit_cubic_r 2Geom interoperability 2nd version (" << num_repeats
+ << "x): " << (stop - start) * (1000. / CLOCKS_PER_SEC) << " ms " << std::endl;
+ }
+
+}
+
+
+
+// \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/performance-tests/boolops-performance-test.cpp b/src/3rdparty/2geom/src/performance-tests/boolops-performance-test.cpp
new file mode 100644
index 0000000..49d87aa
--- /dev/null
+++ b/src/3rdparty/2geom/src/performance-tests/boolops-performance-test.cpp
@@ -0,0 +1,101 @@
+/**
+ * \file
+ * \brief Performance test for Boolops
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/intersection-graph.h>
+#include <2geom/svg-path-parser.h>
+#include <iostream>
+#include <glib.h>
+
+using namespace Geom;
+
+int main(int argc, char **argv)
+{
+ if (argc != 4) {
+ std::cout << "boolops: wrong number of arguments; no tests run!" << std::endl;
+ exit(0); // TODO: add suitable arguments in CMake target / actually do some tests here
+ }
+
+ PathVector a = read_svgd(argv[2]);
+ PathVector b = read_svgd(argv[3]);
+ unsigned const ops = atoi(argv[1]);
+
+ OptRect abox = a.boundsExact();
+ OptRect bbox = a.boundsExact();
+ if (!abox) {
+ std::cout << argv[1] << " contains an empty path" << std::endl;
+ std::exit(1);
+ }
+ if (!bbox) {
+ std::cout << argv[2] << " contains an empty path" << std::endl;
+ std::exit(1);
+ }
+
+ a *= Translate(-abox->corner(0));
+ b *= Translate(-bbox->corner(0));
+
+ long num_intersections = 0;
+ long num_outcv = 0;
+
+ // for reproducibility.
+ g_random_set_seed(1234);
+
+ for (unsigned i = 0; i < ops; ++i) {
+ Point delta;
+ delta[X] = g_random_double_range(-bbox->width(), abox->width());
+ delta[Y] = g_random_double_range(-bbox->height(), abox->height());
+
+ PathVector bt = b * Translate(delta);
+
+ PathIntersectionGraph pig(a, bt);
+ PathVector x = pig.getIntersection();
+ num_intersections += pig.intersectionPoints().size();
+ num_outcv += x.curveCount();
+ }
+
+ std::cout << "Completed " << ops << " operations.\n"
+ << "Total intersections: " << num_intersections << "\n"
+ << "Total output curves: " << num_outcv << std::endl;
+
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/performance-tests/example-performance-test.cpp b/src/3rdparty/2geom/src/performance-tests/example-performance-test.cpp
new file mode 100644
index 0000000..0ca706d
--- /dev/null
+++ b/src/3rdparty/2geom/src/performance-tests/example-performance-test.cpp
@@ -0,0 +1,217 @@
+#include <iostream>
+#include <ctime>
+
+#include "2geom/svg-path-parser.h"
+#include "2geom/pathvector.h"
+#include "2geom/path.h"
+#include "2geom/d2.h"
+#include "2geom/piecewise.h"
+#include "2geom/sbasis.h"
+using namespace Geom;
+
+static char const *many_subpaths =
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 "
+ "M 240,495.21933 648.57143,400.93361 C 190.6809,177.20365 122.07669,234.71591 104.6,312.5 ";
+
+
+
+
+int main()
+{
+ for (int rep = 0; rep < 3; rep++) {
+ const int num_repeats = 100;
+ PathVector path = parse_svg_path(many_subpaths);
+ std::clock_t start = std::clock();
+ for (int i = 0; i < num_repeats; i++) {
+ PathVector path2 = path.reversed();
+ PathVector path3 = path2.reversed().reversed();
+ }
+ std::clock_t stop = std::clock();
+ std::cout << "Reverse paths (" << num_repeats << "x): " << (stop - start) * (1000. / CLOCKS_PER_SEC) << " ms " << std::endl;
+ }
+}
+
+
+
+//
diff --git a/src/3rdparty/2geom/src/performance-tests/parse-svg-test.cpp b/src/3rdparty/2geom/src/performance-tests/parse-svg-test.cpp
new file mode 100644
index 0000000..5147d75
--- /dev/null
+++ b/src/3rdparty/2geom/src/performance-tests/parse-svg-test.cpp
@@ -0,0 +1,88 @@
+/*
+ * Test performance of
+ *
+ * Copyright (C) Authors 2007-2013
+ * Authors:
+ * Johan Engelen <j.b.c.engelen@alumnus.utwente.nl>
+ * Steren Giannini <steren.giannini@gmail.com>
+ *
+ * the test part was taken from Inkscape's Bend Path LPE (and simplified a bit)
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+
+#include <iostream>
+#include <ctime>
+
+#include "2geom/svg-path-parser.h"
+#include "2geom/pathvector.h"
+#include "2geom/path.h"
+#include "2geom/d2.h"
+#include "2geom/piecewise.h"
+#include "2geom/sbasis.h"
+using namespace Geom;
+
+static char const *path_str =
+ "M -460,523.79076 C -460.65718,514.47985 -460.79228,505.75495 -460.43635,497.52584 -460.08041,489.29674 "
+ "-459.23345,481.56342 -457.92649,474.23566 -456.61954,466.9079 -454.85259,459.9857 -452.65671,453.37885 "
+ "-450.46083,446.77199 -447.836,440.48046 -444.81328,434.41405 -441.79056,428.34764 -438.36994,422.50633 "
+ "-434.58247,416.79991 -430.79501,411.0935 -426.64069,405.52196 -422.15057,399.99508 -417.66045,394.4682 "
+ "-412.83452,388.98598 -407.70384,383.4582 -402.57316,377.93041 -397.13772,372.35705 -391.42857,366.6479 "
+ "-378.14065,353.35999 -362.09447,346.86737 -344.03764,345.52929 -325.98081,344.19121 -305.91333,348.00766 "
+ "-284.58283,355.33787 -263.25234,362.66809 -240.65882,373.51207 -217.5499,386.22904 -194.44098,398.94602 "
+ "-170.81666,413.53598 -147.42457,428.35818 -124.03248,443.18037 -100.87262,458.2348 -78.692608,471.88067 "
+ "-56.512594,485.52655 -35.312431,497.76389 -15.839741,506.95191 3.632948,516.13994 21.378163,522.27865 "
+ "36.648281,523.72729 51.918398,525.17592 64.713417,521.93448 74.285714,512.36218 76.124134,510.52376 "
+ "78.521676,506.73937 81.393111,501.43833 84.264546,496.13729 87.609874,489.31958 91.343869,481.41453 "
+ "95.077864,473.50947 99.200524,464.51706 103.62662,454.86661 108.05272,445.21615 112.78226,434.90765 "
+ "117.73001,424.37041 122.67776,413.83317 127.84371,403.0672 133.14266,392.50178 138.4416,381.93637 "
+ "143.87352,371.57153 149.3532,361.83656 154.83288,352.10159 160.36031,342.99649 165.85028,334.95058 "
+ "171.34024,326.90466 176.79273,319.91793 182.12252,314.41968 189.27211,307.04412 196.34366,301.16926 "
+ "203.28385,296.57404 210.22405,291.97882 217.03288,288.66325 223.65704,286.40628 230.2812,284.1493 "
+ "236.72068,282.95093 242.92215,282.59009 249.12362,282.22926 255.08709,282.70597 260.75924,283.79918 "
+ "266.43138,284.89239 271.8122,286.60209 276.84836,288.70724 281.88453,290.81239 286.57604,293.31298 "
+ "290.86959,295.98796 295.16313,298.66294 299.0587,301.51232 302.50297,304.31504 305.94724,307.11776 "
+ "308.94022,309.87382 311.42857,312.36218 317.70879,318.6424 325.20531,326.50894 333.6587,335.29576 "
+ "342.11209,344.08258 351.52235,353.78967 361.63006,363.75101 371.73777,373.71235 382.54293,383.92792 "
+ "393.78611,393.7317 405.02929,403.53547 416.71049,412.92744 428.57029,421.24156 440.43008,429.55569 "
+ "452.46847,436.79197 464.42603,442.28436 476.38359,447.77676 488.26032,451.52527 499.7968,452.86385 "
+ "511.33327,454.20243 522.52948,453.13109 533.12602,448.98378 543.72255,444.83647 553.7194,437.61319 "
+ "562.85714,426.6479 C -478.58599,460.43092 -465.31914,447.40133 -450.91614,434.95746 -436.51315,422.51359 "
+ "-420.97403,410.65543 -405.81565,400.18102 -390.65727,389.70661 -375.87963,380.61595 -362.99962,373.70708 "
+ "-350.11961,366.79821 -339.13723,362.07112 -331.56936,360.32386 -323.49864,358.4605 -311.32246,357.96153 "
+ "-296.07049,358.53595 -280.81852,359.11038 -262.49077,360.7582 -242.11692,363.18844 -221.74308,365.61867 "
+ "-199.32313,368.83132 -175.88677,372.53539 -152.45042,376.23947 -127.99765,380.43497 -103.55815,384.83091 "
+ "-90.798706,387.12596 -78.042879,389.47564 -65.437198,391.83855 -52.831517,394.20146 -40.375984,396.57759 "
+ "-28.217127,398.92554 -16.058269,401.27349 -4.1960885,403.59326 7.2228872,405.84343 18.641863,408.09361 "
+ "29.617633,410.27419 40.00367,412.34378 50.09967,414.35557 59.638414,416.26247 68.485308,418.02645 "
+ "77.332201,419.79043 85.487246,421.41149 92.815847,422.85159 100.14445,424.29169 106.64661,425.55083 "
+ "112.18773,426.59098 117.72885,427.63113 122.30894,428.45228 125.7934,429.01641 134.20502,430.37823 "
+ "142.47705,429.25391 150.64115,426.35391 158.80525,423.45391 166.86142,418.77822 174.84134,413.03729 "
+ "182.82125,407.29637 190.72491,400.49022 198.58398,393.32929 206.44305,386.16836 214.25752,378.65265 "
+ "222.05908,371.49262 227.06421,366.89906 232.06402,362.4519 237.06688,358.33874 242.06974,354.22557 "
+ "247.07564,350.44641 252.09294,347.18884 257.11025,343.93127 262.13896,341.1953 267.18744,339.16853 "
+ "272.23593,337.14176 277.30418,335.82419 282.40056,335.40342 293.00641,334.52778 302.22965,341.02775 "
+ "310.80162,351.57579 319.37358,362.12384 327.29427,376.71996 335.29503,392.03663 343.29579,407.3533 "
+ "351.37662,423.39051 360.26886,436.82075 369.1611,450.25099 378.86474,461.07425 390.11114,465.96301 "
+ "401.98566,471.1248 423.45174,470.72496 449.88663,467.14319 476.32151,463.56143 507.72518,456.79775 "
+ "539.47487,449.23188 571.22455,441.66601 603.32025,433.29795 631.13918,426.50743 658.9581,419.7169 "
+ "688.21455,391.64677 702.85715,390.39104";
+
+int main()
+{
+ for (int rep = 0; rep < 3; rep++) {
+ const int num_repeats = 100;
+ std::clock_t start = std::clock();
+ for (int i = 0; i < num_repeats; i++) {
+ PathVector path = parse_svg_path(path_str);
+ }
+ std::clock_t stop = std::clock();
+ std::cout << "Parse SVG-d (" << num_repeats << "x): " << (stop - start) * (1000. / CLOCKS_PER_SEC) << " ms "
+ << std::endl;
+ }
+}
+
+
+
+// \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/performance-tests/path-operations-test.cpp b/src/3rdparty/2geom/src/performance-tests/path-operations-test.cpp
new file mode 100644
index 0000000..c55ddda
--- /dev/null
+++ b/src/3rdparty/2geom/src/performance-tests/path-operations-test.cpp
@@ -0,0 +1,100 @@
+/*
+ * Test performance of
+ *
+ * Copyright (C) Authors 2007-2013
+ * Authors:
+ * Johan Engelen <j.b.c.engelen@alumnus.utwente.nl>
+ * Steren Giannini <steren.giannini@gmail.com>
+ *
+ * the test part was taken from Inkscape's Bend Path LPE (and simplified a bit)
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+
+#include <iostream>
+#include <ctime>
+
+#include "2geom/svg-path-parser.h"
+#include "2geom/pathvector.h"
+#include "2geom/path.h"
+#include "2geom/d2.h"
+#include "2geom/piecewise.h"
+#include "2geom/sbasis.h"
+#include "2geom/transforms.h"
+using namespace Geom;
+
+static char const *path_str =
+ "M -460,523.79076 C -460.65718,514.47985 -460.79228,505.75495 -460.43635,497.52584 -460.08041,489.29674 "
+ "-459.23345,481.56342 -457.92649,474.23566 -456.61954,466.9079 -454.85259,459.9857 -452.65671,453.37885 "
+ "-450.46083,446.77199 -447.836,440.48046 -444.81328,434.41405 -441.79056,428.34764 -438.36994,422.50633 "
+ "-434.58247,416.79991 -430.79501,411.0935 -426.64069,405.52196 -422.15057,399.99508 -417.66045,394.4682 "
+ "-412.83452,388.98598 -407.70384,383.4582 -402.57316,377.93041 -397.13772,372.35705 -391.42857,366.6479 "
+ "-378.14065,353.35999 -362.09447,346.86737 -344.03764,345.52929 -325.98081,344.19121 -305.91333,348.00766 "
+ "-284.58283,355.33787 -263.25234,362.66809 -240.65882,373.51207 -217.5499,386.22904 -194.44098,398.94602 "
+ "-170.81666,413.53598 -147.42457,428.35818 -124.03248,443.18037 -100.87262,458.2348 -78.692608,471.88067 "
+ "-56.512594,485.52655 -35.312431,497.76389 -15.839741,506.95191 3.632948,516.13994 21.378163,522.27865 "
+ "36.648281,523.72729 51.918398,525.17592 64.713417,521.93448 74.285714,512.36218 76.124134,510.52376 "
+ "78.521676,506.73937 81.393111,501.43833 84.264546,496.13729 87.609874,489.31958 91.343869,481.41453 "
+ "95.077864,473.50947 99.200524,464.51706 103.62662,454.86661 108.05272,445.21615 112.78226,434.90765 "
+ "117.73001,424.37041 122.67776,413.83317 127.84371,403.0672 133.14266,392.50178 138.4416,381.93637 "
+ "143.87352,371.57153 149.3532,361.83656 154.83288,352.10159 160.36031,342.99649 165.85028,334.95058 "
+ "171.34024,326.90466 176.79273,319.91793 182.12252,314.41968 189.27211,307.04412 196.34366,301.16926 "
+ "203.28385,296.57404 210.22405,291.97882 217.03288,288.66325 223.65704,286.40628 230.2812,284.1493 "
+ "236.72068,282.95093 242.92215,282.59009 249.12362,282.22926 255.08709,282.70597 260.75924,283.79918 "
+ "266.43138,284.89239 271.8122,286.60209 276.84836,288.70724 281.88453,290.81239 286.57604,293.31298 "
+ "290.86959,295.98796 295.16313,298.66294 299.0587,301.51232 302.50297,304.31504 305.94724,307.11776 "
+ "308.94022,309.87382 311.42857,312.36218 317.70879,318.6424 325.20531,326.50894 333.6587,335.29576 "
+ "342.11209,344.08258 351.52235,353.78967 361.63006,363.75101 371.73777,373.71235 382.54293,383.92792 "
+ "95.077864,473.50947 99.200524,464.51706 103.62662,454.86661 108.05272,445.21615 112.78226,434.90765 "
+ "117.73001,424.37041 122.67776,413.83317 127.84371,403.0672 133.14266,392.50178 138.4416,381.93637 "
+ "143.87352,371.57153 149.3532,361.83656 154.83288,352.10159 160.36031,342.99649 165.85028,334.95058 "
+ "171.34024,326.90466 176.79273,319.91793 182.12252,314.41968 189.27211,307.04412 196.34366,301.16926 "
+ "203.28385,296.57404 210.22405,291.97882 217.03288,288.66325 223.65704,286.40628 230.2812,284.1493 "
+ "236.72068,282.95093 242.92215,282.59009 249.12362,282.22926 255.08709,282.70597 260.75924,283.79918 "
+ "266.43138,284.89239 271.8122,286.60209 276.84836,288.70724 281.88453,290.81239 286.57604,293.31298 "
+ "290.86959,295.98796 295.16313,298.66294 299.0587,301.51232 302.50297,304.31504 305.94724,307.11776 "
+ "308.94022,309.87382 311.42857,312.36218 317.70879,318.6424 325.20531,326.50894 333.6587,335.29576 "
+ "342.11209,344.08258 351.52235,353.78967 361.63006,363.75101 371.73777,373.71235 382.54293,383.92792 "
+ "393.78611,393.7317 405.02929,403.53547 416.71049,412.92744 428.57029,421.24156 440.43008,429.55569 "
+ "452.46847,436.79197 464.42603,442.28436 476.38359,447.77676 488.26032,451.52527 499.7968,452.86385 "
+ "511.33327,454.20243 522.52948,453.13109 533.12602,448.98378 543.72255,444.83647 553.7194,437.61319 "
+ "511.33327,454.20243 522.52948,453.13109 533.12602,448.98378 543.72255,444.83647 553.7194,437.61319 "
+ "511.33327,454.20243 522.52948,453.13109 533.12602,448.98378 543.72255,444.83647 553.7194,437.61319 "
+ "562.85714,426.6479";
+
+
+int main()
+{
+ for (int rep = 0; rep < 3; rep++) {
+ PathVector path1 = parse_svg_path(path_str);
+ const int num_repeats = 1000;
+ std::clock_t start = std::clock();
+ for (int i = 0; i < num_repeats; i++) {
+ path1 *= Translate(Point(3.,1.));
+ path1 *= Translate(Point(4.,1.));
+ path1 *= Translate(Point(5.,1.));
+ }
+ std::clock_t stop = std::clock();
+ std::cout << "PathVector *= Translate (" << num_repeats << "x): " << (stop - start) * (1000. / CLOCKS_PER_SEC) << " ms "
+ << std::endl;
+ }
+
+ for (int rep = 0; rep < 3; rep++) {
+ PathVector path1 = parse_svg_path(path_str);
+ const int num_repeats = 1000;
+ std::clock_t start = std::clock();
+ for (int i = 0; i < num_repeats; i++) {
+ path1 *= Affine(Translate(Point(3.,1.)));
+ path1 *= Affine(Translate(Point(4.,1.)));
+ path1 *= Affine(Translate(Point(5.,1.)));
+ }
+ std::clock_t stop = std::clock();
+ std::cout << "PathVector *= Affine (" << num_repeats << "x): " << (stop - start) * (1000. / CLOCKS_PER_SEC) << " ms "
+ << std::endl;
+ }
+}
+
+
+
+// \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/py2geom/CMakeLists.txt b/src/3rdparty/2geom/src/py2geom/CMakeLists.txt
new file mode 100644
index 0000000..8e21e74
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/CMakeLists.txt
@@ -0,0 +1,118 @@
+SET(2GEOM_BOOST_PYTHON_SRC
+etc.cpp
+point.cpp
+interval.cpp
+transforms.cpp
+rect.cpp
+line.cpp
+circle.cpp
+ellipse.cpp
+conic.cpp
+crossing.cpp
+sbasis.cpp
+bezier.cpp
+linear.cpp
+pw.cpp
+d2.cpp
+parser.cpp
+path.cpp
+ray.cpp
+#convexcover.cpp
+py2geom.cpp
+# curves
+#curve.cpp
+#bezier-curve.cpp
+)
+
+IF (WIN32)
+ SET(BUILD_BOOST_PYTHON_STATIC FALSE)
+ELSE (WIN32)
+ SET(BUILD_BOOST_PYTHON_STATIC FALSE)
+ENDIF (WIN32)
+IF (BUILD_BOOST_PYTHON_STATIC)
+ SET(BOOST_PYTHON_SRC "C:/boost_1_42_0/libs/python/src")
+ #define BOOST_PYTHON_STATIC_LIB
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBOOST_PYTHON_STATIC_LIB")
+ SET(2GEOM_BOOST_PYTHON_SRC
+ ${2GEOM_BOOST_PYTHON_SRC}
+ ${BOOST_PYTHON_SRC}/dict.cpp
+ ${BOOST_PYTHON_SRC}/errors.cpp
+ ${BOOST_PYTHON_SRC}/exec.cpp
+ ${BOOST_PYTHON_SRC}/import.cpp
+ ${BOOST_PYTHON_SRC}/list.cpp
+ ${BOOST_PYTHON_SRC}/long.cpp
+ ${BOOST_PYTHON_SRC}/module.cpp
+ ${BOOST_PYTHON_SRC}/numeric.cpp
+ ${BOOST_PYTHON_SRC}/object_operators.cpp
+ ${BOOST_PYTHON_SRC}/object_protocol.cpp
+ ${BOOST_PYTHON_SRC}/slice.cpp
+ ${BOOST_PYTHON_SRC}/str.cpp
+ ${BOOST_PYTHON_SRC}/tuple.cpp
+ ${BOOST_PYTHON_SRC}/wrapper.cpp
+
+ ${BOOST_PYTHON_SRC}/converter/arg_to_python_base.cpp
+ ${BOOST_PYTHON_SRC}/converter/builtin_converters.cpp
+ ${BOOST_PYTHON_SRC}/converter/from_python.cpp
+ ${BOOST_PYTHON_SRC}/converter/registry.cpp
+ ${BOOST_PYTHON_SRC}/converter/type_id.cpp
+
+ ${BOOST_PYTHON_SRC}/object/class.cpp
+ ${BOOST_PYTHON_SRC}/object/enum.cpp
+ ${BOOST_PYTHON_SRC}/object/function.cpp
+ ${BOOST_PYTHON_SRC}/object/function_doc_signature.cpp
+ ${BOOST_PYTHON_SRC}/object/inheritance.cpp
+ ${BOOST_PYTHON_SRC}/object/iterator.cpp
+ ${BOOST_PYTHON_SRC}/object/life_support.cpp
+ ${BOOST_PYTHON_SRC}/object/pickle_support.cpp
+ ${BOOST_PYTHON_SRC}/object/stl_iterator.cpp
+ )
+ENDIF (BUILD_BOOST_PYTHON_STATIC)
+
+IF(PYCAIRO_FOUND)
+ SET(2GEOM_BOOST_PYTHON_SRC
+ ${2GEOM_BOOST_PYTHON_SRC}
+ cairo-helpers.cpp
+ )
+ENDIF(PYCAIRO_FOUND)
+
+
+OPTION(2GEOM_BOOST_PYTHON
+ "Build a python binding with Boost.Python"
+ OFF)
+IF(2GEOM_BOOST_PYTHON)
+ FIND_PACKAGE(Python3 COMPONENTS Development Interpreter REQUIRED)
+
+ SET(Boost_DEBUG TRUE)
+ SET(Boost_REALPATH FALSE)
+ FIND_PACKAGE(Boost 1.42.0 REQUIRED)
+ FIND_PACKAGE(Boost REQUIRED COMPONENTS python${Python3_VERSION_MAJOR}${Python3_VERSION_MINOR})
+
+ IF (WIN32)
+ SET_TARGET_PROPERTIES(py2geom PROPERTIES SUFFIX ".pyd")
+ ELSEIF (APPLE)
+ SET(CMAKE_MACOSX_RPATH FALSE)
+ SET(CMAKE_SHARED_LIBRARY_SUFFIX ".so")
+ ENDIF(WIN32)
+
+ INCLUDE_DIRECTORIES( src/ ${Python3_INCLUDE_DIRS} ${Boost_INCLUDE_DIR} )
+ ADD_LIBRARY(py2geom SHARED ${2GEOM_BOOST_PYTHON_SRC})
+ SET_TARGET_PROPERTIES(py2geom PROPERTIES PREFIX "_")
+
+ IF (BUILD_BOOST_PYTHON_STATIC)
+ TARGET_LINK_LIBRARIES(py2geom 2geom ${Python3_LIBRARIES})
+ ELSE (BUILD_BOOST_PYTHON_STATIC)
+ TARGET_LINK_LIBRARIES(py2geom 2geom ${Boost_LIBRARIES} ${Python3_LIBRARIES})
+ ENDIF (BUILD_BOOST_PYTHON_STATIC)
+
+ set_property(TARGET 2geom PROPERTY POSITION_INDEPENDENT_CODE ON) # we need -fPIC to link py2geom against 2geom
+
+ IF(PYCAIRO_FOUND)
+ TARGET_LINK_LIBRARIES(py2geom ${Cairo_LIBRARIES})
+ ENDIF(PYCAIRO_FOUND)
+
+ INSTALL(TARGETS py2geom DESTINATION "${Python3_SITEARCH}/py2geom")
+ INSTALL(FILES "${CMAKE_CURRENT_SOURCE_DIR}/__init__.py" DESTINATION "${Python3_SITEARCH}/py2geom")
+ENDIF(2GEOM_BOOST_PYTHON)
+
+
+
diff --git a/src/3rdparty/2geom/src/py2geom/__init__.py b/src/3rdparty/2geom/src/py2geom/__init__.py
new file mode 100644
index 0000000..06faf3c
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/__init__.py
@@ -0,0 +1,26 @@
+# Copyright 2006, 2007 Aaron Spike <aaron@ekips.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it either under the terms of the GNU Lesser General Public
+# License version 2.1 as published by the Free Software Foundation
+# (the "LGPL") or, at your option, under the terms of the Mozilla
+# Public License Version 1.1 (the "MPL"). If you do not alter this
+# notice, a recipient may use your version of this file under either
+# the MPL or the LGPL.
+#
+# You should have received a copy of the LGPL along with this library
+# in the file COPYING-LGPL-2.1; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+# You should have received a copy of the MPL along with this library
+# in the file COPYING-MPL-1.1
+#
+# The contents of this file are subject to the Mozilla Public License
+# Version 1.1 (the "License"); you may not use this file except in
+# compliance with the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+# OF ANY KIND, either express or implied. See the LGPL or the MPL for
+# the specific language governing rights and limitations.
+
+from py2geom._py2geom import *
diff --git a/src/3rdparty/2geom/src/py2geom/bezier.cpp b/src/3rdparty/2geom/src/py2geom/bezier.cpp
new file mode 100644
index 0000000..f0664c1
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/bezier.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2006, 2007 Aaron Spike <aaron@ekips.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <boost/python.hpp>
+#include <boost/python/implicit.hpp>
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+
+#include "py2geom.h"
+#include "helpers.h"
+
+#include "2geom/bezier.h"
+#include "2geom/point.h"
+
+using namespace boost::python;
+
+double bezier_getitem(Geom::Bezier const& p, int index)
+{
+ int D = p.size();
+ if (index < 0)
+ {
+ index = D + index;
+ }
+ if ((index < 0) || (index > (D - 1))) {
+ PyErr_SetString(PyExc_IndexError, "index out of range");
+ boost::python::throw_error_already_set();
+ }
+ return p[index];
+}
+
+void wrap_bezier() {
+ //bezier.h
+
+ class_<Geom::Bezier>("Bezier", init<double>())
+ .def(init<double, double>())
+ .def(init<double, double, double>())
+ .def(init<double, double, double, double>())
+ .def(self_ns::str(self))
+ //TODO: add important vector funcs
+ .def("__getitem__", &bezier_getitem)
+
+ .def("isZero", &Geom::Bezier::isZero)
+ .def("isFinite", &Geom::Bezier::isFinite)
+ .def("at0", (double (Geom::Bezier::*)() const) &Geom::Bezier::at0)
+ .def("at1", (double (Geom::Bezier::*)() const) &Geom::Bezier::at1)
+ .def("valueAt", &Geom::Bezier::valueAt)
+ .def("toSBasis", &Geom::Bezier::toSBasis)
+
+ .def(self + float())
+ .def(self - float())
+
+ .def(self * float())
+ ;
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/py2geom/cairo-helpers.cpp b/src/3rdparty/2geom/src/py2geom/cairo-helpers.cpp
new file mode 100644
index 0000000..c341439
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/cairo-helpers.cpp
@@ -0,0 +1,164 @@
+#include <boost/python.hpp>
+#include <cairo.h>
+#include <toys/path-cairo.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/utils.h>
+#include <sstream>
+#include <pycairo/pycairo.h>
+#include "cairo-helpers.h"
+
+using namespace Geom;
+
+
+void
+cairo_move_to (cairo_t *cr, Geom::Point p1) {
+ cairo_move_to(cr, p1[0], p1[1]);
+}
+
+void
+cairo_line_to (cairo_t *cr, Geom::Point p1) {
+ cairo_line_to(cr, p1[0], p1[1]);
+}
+
+void
+cairo_curve_to (cairo_t *cr, Geom::Point p1,
+ Geom::Point p2, Geom::Point p3) {
+ cairo_curve_to(cr, p1[0], p1[1],
+ p2[0], p2[1],
+ p3[0], p3[1]);
+}
+
+void cairo_rectangle(cairo_t *cr, Rect const& r) {
+ cairo_rectangle(cr, r.left(), r.top(), r.width(), r.height());
+}
+
+void cairo_convex_hull(cairo_t *cr, ConvexHull const& ch) {
+ if(ch.empty()) return;
+ cairo_move_to(cr, ch.back());
+ for(unsigned i = 0; i < ch.size(); i++) {
+ cairo_line_to(cr, ch[i]);
+ }
+}
+
+void cairo_curve(cairo_t *cr, Curve const& c) {
+ if(LineSegment const* line_segment = dynamic_cast<LineSegment const*>(&c)) {
+ cairo_line_to(cr, (*line_segment)[1][0], (*line_segment)[1][1]);
+ }
+ else if(QuadraticBezier const *quadratic_bezier = dynamic_cast<QuadraticBezier const*>(&c)) {
+ std::vector<Point> points = quadratic_bezier->controlPoints();
+ Point b1 = points[0] + (2./3) * (points[1] - points[0]);
+ Point b2 = b1 + (1./3) * (points[2] - points[0]);
+ cairo_curve_to(cr, b1[0], b1[1],
+ b2[0], b2[1],
+ points[2][0], points[2][1]);
+ }
+ else if(CubicBezier const *cubic_bezier = dynamic_cast<CubicBezier const*>(&c)) {
+ std::vector<Point> points = cubic_bezier->controlPoints();
+ cairo_curve_to(cr, points[1][0], points[1][1], points[2][0], points[2][1], points[3][0], points[3][1]);
+ }
+// else if(EllipticalArc const *svg_elliptical_arc = dynamic_cast<EllipticalArc *>(c)) {
+// //TODO: get at the innards and spit them out to cairo
+// }
+ else {
+ //this case handles sbasis as well as all other curve types
+ Path sbasis_path = cubicbezierpath_from_sbasis(c.toSBasis(), 0.1);
+
+ //recurse to convert the new path resulting from the sbasis to svgd
+ for(Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter) {
+ cairo_curve(cr, *iter);
+ }
+ }
+}
+
+void cairo_path(cairo_t *cr, Path const &p) {
+ cairo_move_to(cr, p.initialPoint()[0], p.initialPoint()[1]);
+ if(p.size() == 0) { // naked moveto
+ cairo_move_to(cr, p.finalPoint()+Point(8,0));
+ cairo_line_to(cr, p.finalPoint()+Point(-8,0));
+ cairo_move_to(cr, p.finalPoint()+Point(0,8));
+ cairo_line_to(cr, p.finalPoint()+Point(0,-8));
+ return;
+ }
+
+ for(Path::const_iterator iter(p.begin()), end(p.end()); iter != end; ++iter) {
+ cairo_curve(cr, *iter);
+ }
+ if(p.closed())
+ cairo_close_path(cr);
+}
+
+void cairo_path_stitches(cairo_t *cr, Path const &p) {
+ Path::const_iterator iter;
+ for ( iter = p.begin() ; iter != p.end() ; ++iter ) {
+ Curve const &c=*iter;
+ if (dynamic_cast<Path::StitchSegment const *>(&c)) {
+ cairo_move_to(cr, c.initialPoint()[X], c.initialPoint()[Y]);
+ cairo_line_to(cr, c.finalPoint()[X], c.finalPoint()[Y]);
+
+ //std::stringstream s;
+ //s << L1(c.finalPoint() - c.initialPoint());
+ //std::string ss = s.str();
+ //draw_text(cr, c.initialPoint()+Point(5,5), ss.c_str(), false, "Serif 6");
+
+ //std::cout << c.finalPoint() - c.initialPoint() << std::endl;
+ }
+ }
+}
+
+void cairo_path(cairo_t *cr, PathVector const &p) {
+ PathVector::const_iterator it;
+ for(it = p.begin(); it != p.end(); ++it) {
+ cairo_path(cr, *it);
+ }
+}
+
+void cairo_path_stitches(cairo_t *cr, PathVector const &p) {
+ PathVector::const_iterator it;
+ for ( it = p.begin() ; it != p.end() ; ++it ) {
+ cairo_path_stitches(cr, *it);
+ }
+}
+
+
+void cairo_d2_sb(cairo_t *cr, D2<SBasis> const &B) {
+ cairo_path(cr, path_from_sbasis(B, 0.1));
+}
+
+void cairo_d2_pw_sb(cairo_t *cr, D2<Piecewise<SBasis> > const &p) {
+ cairo_pw_d2_sb(cr, sectionize(p));
+}
+
+void cairo_pw_d2_sb(cairo_t *cr, Piecewise<D2<SBasis> > const &p) {
+ for(unsigned i = 0; i < p.size(); i++)
+ cairo_d2_sb(cr, p[i]);
+}
+
+#if PY_MAJOR_VERSION < 3
+static Pycairo_CAPI_t *Pycairo_CAPI = 0;
+#endif
+
+cairo_t* cairo_t_from_object(boost::python::object cr) {
+#if PY_MAJOR_VERSION < 3
+ if(!Pycairo_CAPI)
+ Pycairo_IMPORT;
+#else
+ import_cairo();
+#endif
+ PycairoContext* pcc = (PycairoContext*)cr.ptr();
+ assert(PyObject_TypeCheck(pcc, &PycairoContext_Type));
+ return PycairoContext_GET(pcc);
+}
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(substatement-open . 0))
+ indent-tabs-mode:nil
+ c-brace-offset:0
+ fill-column:99
+ End:
+ vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+*/
diff --git a/src/3rdparty/2geom/src/py2geom/cairo-helpers.h b/src/3rdparty/2geom/src/py2geom/cairo-helpers.h
new file mode 100644
index 0000000..daa2960
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/cairo-helpers.h
@@ -0,0 +1,27 @@
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/d2.h>
+#include <2geom/piecewise.h>
+#include <2geom/path.h>
+#include <2geom/convex-hull.h>
+#include <vector>
+
+typedef struct _cairo cairo_t;
+
+void cairo_move_to(cairo_t *cr, Geom::Point p1);
+void cairo_line_to(cairo_t *cr, Geom::Point p1);
+void cairo_curve_to(cairo_t *cr, Geom::Point p1, Geom::Point p2, Geom::Point p3);
+
+void cairo_curve(cairo_t *cr, Geom::Curve const &c);
+void cairo_rectangle(cairo_t *cr, Geom::Rect const &r);
+void cairo_convex_hull(cairo_t *cr, Geom::ConvexHull const &r);
+void cairo_path(cairo_t *cr, Geom::Path const &p);
+void cairo_path(cairo_t *cr, Geom::PathVector const &p);
+void cairo_path_stitches(cairo_t *cr, Geom::Path const &p);
+void cairo_path_stitches(cairo_t *cr, Geom::PathVector const &p);
+
+void cairo_d2_sb(cairo_t *cr, Geom::D2<Geom::SBasis> const &p);
+void cairo_d2_pw_sb(cairo_t *cr, Geom::D2<Geom::Piecewise<Geom::SBasis> > const &p);
+void cairo_pw_d2_sb(cairo_t *cr, Geom::Piecewise<Geom::D2<Geom::SBasis> > const &p);
+
+cairo_t* cairo_t_from_object(boost::python::object cr);
diff --git a/src/3rdparty/2geom/src/py2geom/circle.cpp b/src/3rdparty/2geom/src/py2geom/circle.cpp
new file mode 100644
index 0000000..55e683b
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/circle.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2009 Ricardo Lafuente <r@sollec.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <boost/python.hpp>
+#include <boost/python/implicit.hpp>
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+
+#include "py2geom.h"
+#include "helpers.h"
+
+#include "2geom/point.h"
+#include "2geom/circle.h"
+#include "2geom/exception.h"
+
+// i can't get these to work
+//Geom::Point (Geom::Circle::*center_point)() = (Geom::Point (*)() const)&Geom::Circle::center;
+//Geom::Coord (Geom::Circle::*center_coord)(Geom::Dim2 const& d) = &Geom::Circle::center;
+
+using namespace boost::python;
+
+void wrap_circle() {
+
+ class_<Geom::Circle>("Circle", init<double, double, double>())
+ .def(init<double, double, double, double>())
+
+ .def("setCoefficients", &Geom::Circle::setCoefficients)
+ .def("fit", &Geom::Circle::fit)
+ .add_property("radius", &Geom::Circle::radius)
+
+ .add_property("center", (Geom::Point (Geom::Circle::*)() const )&Geom::Circle::center)
+ //.def("center", center)
+ // requires EllipticalArc
+ //.def("arc", &Geom::Circle::arc)
+ ;
+
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/py2geom/conic.cpp b/src/3rdparty/2geom/src/py2geom/conic.cpp
new file mode 100644
index 0000000..8e5360e
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/conic.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2009 Nathan Hurst <njh@njhurst.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <boost/python.hpp>
+#include <boost/python/implicit.hpp>
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+#include <optional>
+
+#include "py2geom.h"
+#include "helpers.h"
+
+#include "2geom/point.h"
+#include "2geom/line.h"
+#include "2geom/conicsec.h"
+
+using namespace boost::python;
+
+// helpers for point
+static tuple xAx_to_tuple(Geom::xAx const& a)
+{
+ return make_tuple(a.c[0], a.c[1], a.c[2], a.c[3], a.c[4], a.c[5]);
+}
+
+static Geom::xAx tuple_to_xAx(boost::python::tuple const& t)
+{
+ return Geom::xAx(extract<double>(t[0]),
+ extract<double>(t[1]),
+ extract<double>(t[2]),
+ extract<double>(t[3]),
+ extract<double>(t[4]),
+ extract<double>(t[5])
+ );
+}
+
+static std::vector<double> xax_roots1(Geom::xAx const & xax, Geom::Point const &a, Geom::Point const &b) { return xax.roots(a,b); }
+static std::vector<double> xax_roots2(Geom::xAx const & xax, Geom::Line const &l) { return xax.roots(l); }
+static Geom::SBasis homo_eval_at(Geom::xAx const & xax,
+ Geom::SBasis const & x,
+ Geom::SBasis const & y,
+ Geom::SBasis const & w
+ ) {
+ return xax.evaluate_at(x, y, w);
+}
+
+static Geom::SBasis xy_eval_at(Geom::xAx const & xax,
+ Geom::SBasis const & x,
+ Geom::SBasis const & y
+ ) {
+ return xax.evaluate_at(x, y);
+}
+
+static Geom::D2<Geom::SBasis> wrap_rq_to_cubic_sb(Geom::RatQuad const & rq) {
+ return rq.toCubic().toSBasis();
+}
+
+static Geom::D2<Geom::SBasis> wrap_rq_to_cubic_sb_l(Geom::RatQuad const & rq, double l) {
+ return rq.toCubic(l).toSBasis();
+}
+
+static std::vector<Geom::Point> wrap_rq_to_cubic_l(Geom::RatQuad const & rq, double l) {
+ return rq.toCubic(l).controlPoints();
+}
+
+static std::vector<Geom::Point> wrap_rq_to_cubic(Geom::RatQuad const & rq) {
+ return wrap_rq_to_cubic_l(rq, rq.lambda());
+}
+
+static tuple wrap_rq_split(Geom::RatQuad const & rq) {
+ Geom::RatQuad a, b;
+ rq.split(a, b);
+ return make_tuple(a, b);
+}
+
+static object wrap_xax_to_curve(Geom::xAx const & xax, Geom::Rect const & r) {
+ std::optional<Geom::RatQuad> oc = xax.toCurve(r);
+ return oc?object(*oc):object();
+}
+
+
+
+void wrap_conic() {
+ //conicsec.h
+ def("intersect", (std::vector<Geom::Point> (*)(Geom::xAx const &, Geom::xAx const &))Geom::intersect);
+
+ class_<Geom::xAx>("xAx", init<>())
+ .def(init<double, double, double, double, double, double>())
+ .def(init<Geom::xAx const&>())
+ .def_readonly("c", &Geom::xAx::c)
+ .def("tuple", xAx_to_tuple)
+
+ .def("from_tuple", tuple_to_xAx)
+ .staticmethod("from_tuple")
+ .def("fromPoint", Geom::xAx::fromPoint)
+ .staticmethod("fromPoint")
+ .def("fromPoints", Geom::xAx::fromPoints)
+ .staticmethod("fromPoints")
+ .def("fromLine", (Geom::xAx (*)(Geom::Line l))Geom::xAx::fromLine)
+ .staticmethod("fromLine")
+ .def(self_ns::str(self))
+ .def("valueAt", &Geom::xAx::valueAt)
+
+ .def("implicit_form_coefficients", &Geom::xAx::implicit_form_coefficients)
+
+ .def("isDegenerate", &Geom::xAx::isDegenerate)
+ .def("roots", &xax_roots1)
+ .def("roots", &xax_roots2)
+ .def("extrema", &Geom::xAx::extrema)
+ .def("gradient", &Geom::xAx::gradient)
+ .def("crossings", &Geom::xAx::crossings)
+ .def("evaluate_at", &xy_eval_at)
+ .def("evaluate_at", &homo_eval_at)
+ .def("toCurve", &wrap_xax_to_curve)
+ .def(self - self)
+ .def(self + float())
+ .def(self * float())
+ ;
+
+ class_<Geom::RatQuad>("RatQuad", init<>())
+ .def(init<Geom::Point, Geom::Point, Geom::Point, double>())
+ .def_readonly("P", &Geom::RatQuad::P)
+ .def_readonly("w", &Geom::RatQuad::w)
+ .def_readonly("lam", &Geom::RatQuad::lambda)
+ //.def(self_ns::str(self))
+ .def("at0", &Geom::RatQuad::at0)
+ .def("at1", &Geom::RatQuad::at1)
+ .def("pointAt", &Geom::RatQuad::pointAt)
+
+ .def("toCubic", &wrap_rq_to_cubic)
+ .def("toCubic", &wrap_rq_to_cubic_l)
+ .def("toCubicSBasis", &wrap_rq_to_cubic_sb)
+ .def("toCubicSBasis", &wrap_rq_to_cubic_sb_l)
+
+ .def("split", &wrap_rq_split)
+ .def("hermite", &Geom::RatQuad::hermite)
+ .def("homogeneous", &Geom::RatQuad::homogeneous)
+ .def("fromPointsTangents", &Geom::RatQuad::fromPointsTangents)
+ .staticmethod("fromPointsTangents")
+ ;
+ implicitly_convertible<Geom::Point,tuple>();
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/py2geom/convexcover.cpp b/src/3rdparty/2geom/src/py2geom/convexcover.cpp
new file mode 100644
index 0000000..3f0b270
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/convexcover.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2009 Nathan Hurst <njh@njhurst.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <boost/python.hpp>
+#include <boost/python/implicit.hpp>
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+
+#include "py2geom.h"
+#include "helpers.h"
+
+#include "2geom/point.h"
+#include "2geom/exception.h"
+#include "2geom/convex-cover.h"
+
+
+
+using namespace boost::python;
+
+PointVec ch_boundary(Geom::ConvexHull const &ch) {
+ return ch.boundary;
+}
+
+int furthest_index(Geom::ConvexHull const &ch, Geom::Point const &p) {
+ return (int)(ch.furthest(p) - &ch.boundary[0]);
+}
+
+void wrap_convex_cover() {
+ class_<Geom::ConvexHull>("ConvexHull", init<>())
+ .def(init<PointVec>())
+
+ .def("merge", &Geom::ConvexHull::merge)
+ .def("contains_point", &Geom::ConvexHull::contains_point)
+ .def("strict_contains_point", &Geom::ConvexHull::strict_contains_point)
+
+ .add_property("boundary", &ch_boundary)
+ .add_property("is_clockwise", &Geom::ConvexHull::is_clockwise)
+ .add_property("top_point_first", &Geom::ConvexHull::top_point_first)
+ .add_property("meets_invariants", &Geom::ConvexHull::meets_invariants)
+ .add_property("empty", &Geom::ConvexHull::empty)
+
+ .add_property("singular", &Geom::ConvexHull::singular)
+
+ .add_property("linear", &Geom::ConvexHull::linear)
+ .add_property("is_degenerate", &Geom::ConvexHull::is_degenerate)
+
+ .def("centroid_and_area", &Geom::ConvexHull::centroid_and_area)
+ .def("area", &Geom::ConvexHull::area)
+ .def("furthest", &furthest_index)
+
+ .def("is_left", &Geom::ConvexHull::is_left)
+ .def("is_strict_left", &Geom::ConvexHull::is_strict_left)
+ .def("find_left", &Geom::ConvexHull::find_left)
+ .def("find_strict_left", &Geom::ConvexHull::find_strict_left)
+ .def("narrowest_diameter", &Geom::ConvexHull::narrowest_diameter)
+ ;
+
+ };
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/py2geom/crossing.cpp b/src/3rdparty/2geom/src/py2geom/crossing.cpp
new file mode 100644
index 0000000..6b4f050
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/crossing.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2009 Nathan Hurst <njh@njhurst.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <boost/python.hpp>
+#include <boost/python/implicit.hpp>
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+
+#include "py2geom.h"
+#include "helpers.h"
+
+#include "2geom/crossing.h"
+#include "2geom/point.h"
+
+using namespace boost::python;
+
+void wrap_crossing() {
+ //line.h
+
+ class_<Geom::Crossing>("Crossing", init<>())
+ .def(init<double, double, bool>())
+ .def(init<double, double, unsigned, unsigned, bool>())
+ .def_readonly("ta", &Geom::Crossing::ta)
+ .def_readonly("tb", &Geom::Crossing::tb)
+ .def_readonly("a", &Geom::Crossing::a)
+ .def_readonly("b", &Geom::Crossing::b)
+ .def_readonly("dir", &Geom::Crossing::dir)
+ //.def(self_ns::str(self))
+ .def("getOther", &Geom::Crossing::getOther)
+ .def("getTime", &Geom::Crossing::getTime)
+ .def("getOtherTime", &Geom::Crossing::getOtherTime)
+ .def("onIx", &Geom::Crossing::onIx)
+ ;
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/py2geom/d2.cpp b/src/3rdparty/2geom/src/py2geom/d2.cpp
new file mode 100644
index 0000000..d646ea5
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/d2.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2006, 2007 Aaron Spike <aaron@ekips.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <boost/python.hpp>
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+
+#include "py2geom.h"
+#include "helpers.h"
+#include <2geom/point.h>
+#include <2geom/sbasis.h>
+#include <2geom/d2.h>
+#include <2geom/piecewise.h>
+
+using namespace boost::python;
+
+void wrap_d2() {
+ class_<Geom::D2<Geom::SBasis> >("D2SBasis", init<>())
+ .def(init<Geom::SBasis,Geom::SBasis>())
+ .def("__getitem__", python_getitem<Geom::D2<Geom::SBasis>,Geom::SBasis,2>)
+
+ .def("isZero", &Geom::D2<Geom::SBasis>::isZero)
+ .def("isFinite", &Geom::D2<Geom::SBasis>::isFinite)
+ .def("at0", &Geom::D2<Geom::SBasis>::at0)
+ .def("at1", &Geom::D2<Geom::SBasis>::at1)
+ .def("pointAt", &Geom::D2<Geom::SBasis>::valueAt)
+ .def("valueAndDerivatives", &Geom::D2<Geom::SBasis>::valueAndDerivatives)
+ .def("toSBasis", &Geom::D2<Geom::SBasis>::toSBasis)
+
+ .def(-self)
+ .def(self + self)
+ .def(self - self)
+ .def(self += self)
+ .def(self -= self)
+ .def(self + Geom::Point())
+ .def(self - Geom::Point())
+ .def(self += Geom::Point())
+ .def(self -= Geom::Point())
+ .def(self * Geom::Point())
+ .def(self / Geom::Point())
+ .def(self *= Geom::Point())
+ .def(self /= Geom::Point())
+ .def(self * float())
+ .def(self / float())
+ .def(self *= float())
+ .def(self /= float())
+ ;
+ def("reverse", ((Geom::D2<Geom::SBasis> (*)(Geom::D2<Geom::SBasis> const &b))&Geom::reverse));
+ def("portion", ((Geom::D2<Geom::SBasis> (*)(Geom::D2<Geom::SBasis> const &a, Geom::Coord f, Geom::Coord t))&Geom::portion));
+ //TODO: dot, rot90, cross, compose, composeEach, eval ops, derivative, integral, L2, portion, multiply ops,
+
+ class_<Geom::D2<Geom::Piecewise<Geom::SBasis> > >("D2PiecewiseSBasis")
+ .def("__getitem__", python_getitem<Geom::D2<Geom::Piecewise<Geom::SBasis> >,Geom::Piecewise<Geom::SBasis>,2>)
+
+ //.def("isZero", &Geom::D2<Geom::Piecewise<Geom::SBasis> >::isZero)
+ //.def("isFinite", &Geom::D2<Geom::Piecewise<Geom::SBasis> >::isFinite)
+ //.def("at0", &Geom::D2<Geom::Piecewise<Geom::SBasis> >::at0)
+ //.def("at1", &Geom::D2<Geom::Piecewise<Geom::SBasis> >::at1)
+ //.def("pointAt", &Geom::D2<Geom::Piecewise<Geom::SBasis> >::valueAt)
+ //.def("valueAndDerivatives", &Geom::D2<Geom::Piecewise<Geom::SBasis> >::valueAndDerivatives)
+ //.def("toSBasis", &Geom::D2<Geom::Piecewise<Geom::SBasis> >::toSBasis)
+
+ ;
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/py2geom/ellipse.cpp b/src/3rdparty/2geom/src/py2geom/ellipse.cpp
new file mode 100644
index 0000000..7592bd4
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/ellipse.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2009 Ricardo Lafuente <r@sollec.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <boost/python.hpp>
+#include <boost/python/implicit.hpp>
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+
+#include "py2geom.h"
+#include "helpers.h"
+
+#include "2geom/point.h"
+#include "2geom/ellipse.h"
+#include "2geom/circle.h"
+#include "2geom/exception.h"
+#include "2geom/d2.h"
+
+
+void (Geom::Ellipse::*ellipse_set1)(Geom::Point const &, Geom::Point const &, double) = &Geom::Ellipse::set;
+void (Geom::Ellipse::*ellipse_set2)(double, double, double, double, double) = &Geom::Ellipse::set;
+std::vector<Geom::Coord> (Geom::Ellipse::*ellipse_coefficients)() const = &Geom::Ellipse::coefficients;
+
+// i can't get these to work
+//Geom::Point (Geom::Ellipse::*center_point)() = (Geom::Point (*)() const)&Geom::Ellipse::center;
+// Geom::Coord (Geom::Ellipse::*center_coord)(Geom::Dim2 const& d) = &Geom::Ellipse::center;
+
+using namespace boost::python;
+
+void wrap_ellipse() {
+ class_<Geom::Ellipse>("Ellipse", init<double, double, double, double, double>())
+ .def(init<double, double, double, double, double, double>())
+ // needs to be mapped to PointVec, but i can't figure out how
+ .def(init<Geom::Circle>())
+
+ .def("set", ellipse_set1)
+ .def("set", ellipse_set2)
+ .def("setCoefficients", &Geom::Ellipse::setCoefficients)
+ .def("fit", &Geom::Ellipse::fit)
+
+ .def("center", (Geom::Point (Geom::Ellipse::*)() const) &Geom::Ellipse::center)
+ // .def("center", center_coord)
+
+ .def("ray", &Geom::Ellipse::ray)
+ .def("rotationAngle", &Geom::Ellipse::rotationAngle)
+ .def("coefficients", ellipse_coefficients)
+ .def(self * Geom::Affine())
+ .def(self *= Geom::Affine())
+ // requires EllipticalArc
+ //.def("arc", &Geom::Ellipse::arc)
+
+ ;
+
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/py2geom/etc.cpp b/src/3rdparty/2geom/src/py2geom/etc.cpp
new file mode 100644
index 0000000..57fdf4c
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/etc.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2009 Ricardo Lafuente <r@sollec.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <boost/python.hpp>
+#include <boost/python/implicit.hpp>
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+
+#include "py2geom.h"
+#include "helpers.h"
+
+#include "2geom/point.h"
+#include "2geom/sbasis.h"
+#include "2geom/exception.h"
+
+using namespace boost::python;
+
+void wrap_etc() {
+ // needed for roots
+ class_<DoubleVec >("DoubleVec")
+ .def(vector_indexing_suite<std::vector<double> >())
+ ;
+ class_<PointVec>("PointVec")
+ .def(vector_indexing_suite<std::vector<Geom::Point> >())
+ ;
+ // sbasis is a subclass of
+ class_<LinearVec >("LinearVec")
+ .def(vector_indexing_suite<std::vector<Geom::Linear> >())
+ ;
+
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/py2geom/helpers.h b/src/3rdparty/2geom/src/py2geom/helpers.h
new file mode 100644
index 0000000..4502fba
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/helpers.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2006, 2007 Aaron Spike <aaron@ekips.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef SEEN_PY2GEOM_HELPERS_H
+#define SEEN_PY2GEOM_HELPERS_H
+
+#include <boost/python.hpp>
+
+template <typename T, typename R, unsigned D>
+R python_getitem(T const& p, int index)
+{
+ unsigned i = index;
+ if (index < 0)
+ {
+ i = index = D + index;
+ }
+ if ((index < 0) || (i > (D - 1))) {
+ PyErr_SetString(PyExc_IndexError, "index out of range");
+ boost::python::throw_error_already_set();
+ }
+ return p[i];
+}
+
+#endif
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/py2geom/interval.cpp b/src/3rdparty/2geom/src/py2geom/interval.cpp
new file mode 100644
index 0000000..1ac2d60
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/interval.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2008 Aaron Spike <aaron@ekips.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <boost/python.hpp>
+#include <boost/python/implicit.hpp>
+
+#include "py2geom.h"
+#include "helpers.h"
+
+#include "2geom/interval.h"
+
+using namespace boost::python;
+
+
+// helpers for interval
+static tuple interval_to_tuple(Geom::Interval const& p)
+{
+ return make_tuple(p.min(), p.max());
+}
+
+static Geom::Interval tuple_to_interval(boost::python::tuple const& t)
+{
+ return Geom::Interval(extract<double>(t[0]), extract<double>(t[1]));
+}
+
+static str interval_repr(Geom::Interval const& p)
+{
+ return str("(" + str(p.min()) + ", " + str(p.max()) + ")");
+}
+
+static Geom::Interval from_optinterval(Geom::OptInterval const & ivl)
+{
+ return *ivl;
+}
+
+
+static bool wrap_contains_coord(Geom::Interval const &x, Geom::Coord val) {
+ return x.contains(val);
+}
+
+static bool wrap_contains_ivl(Geom::Interval const &x, Geom::Interval val) {
+ return x.contains(val);
+}
+
+static bool wrap_interiorContains_coord(Geom::Interval const &x, Geom::Coord val) {
+ return x.interiorContains(val);
+}
+
+static bool wrap_interiorContains_ivl(Geom::Interval const &x, Geom::Interval val) {
+ return x.interiorContains(val);
+}
+
+void wrap_interval() {
+ def("interval_to_tuple", interval_to_tuple);
+ def("tuple_to_interval", tuple_to_interval);
+
+ //def("unify", Geom::unify(Geom::Interval const &, Geom::Interval const &));
+ //def("intersect", Geom::intersect(Geom::Interval const &, Geom::Interval const &));
+
+ //TODO: add overloaded constructors
+ class_<Geom::Interval>("Interval", init<double, double>())
+ .def("__str__", interval_repr)
+ .def("__repr__", interval_repr)
+ .def("tuple", interval_to_tuple)
+
+ .def("from_tuple", tuple_to_interval)
+ .staticmethod("from_tuple")
+
+ .def("min", &Geom::Interval::min)
+ .def("max", &Geom::Interval::max)
+ .def("middle", &Geom::Interval::middle)
+ .def("extent", &Geom::Interval::extent)
+ .def("isSingular", &Geom::Interval::isSingular)
+ //TODO: fix for overloading
+ .def("contains", wrap_contains_coord)
+ .def("contains", wrap_contains_ivl)
+ .def("interiorContains", wrap_interiorContains_coord)
+ .def("interiorContains", wrap_interiorContains_ivl)
+ .def("intersects", &Geom::Interval::intersects)
+
+ .def("setMin", &Geom::Interval::setMin)
+ .def("setMax", &Geom::Interval::setMax)
+ .def("expandTo", &Geom::Interval::expandTo)
+ .def("from_array", &Geom::Interval::from_array)
+ .def("expandBy", &Geom::Interval::expandBy)
+ .def("unionWith", &Geom::Interval::unionWith)
+
+ .def(self == self)
+ .def(self != self)
+
+ .def(self + float())
+ .def(self - float())
+ .def(self += float())
+ .def(self -= float())
+
+ .def(-self)
+
+ .def(self * float())
+ .def(self / float())
+ .def(self *= float())
+ .def(self /= float())
+
+ .def(self + self)
+ .def(self - self)
+ .def(self += self)
+ .def(self -= self)
+ .def(self * self)
+ .def(self *= self)
+ ;
+ class_<Geom::OptInterval>("OptInterval", init<double, double>())
+ .def(init<Geom::Interval>())
+ .def("unionWith", &Geom::OptInterval::unionWith)
+ .def("empty", &Geom::OptInterval::empty)
+ .def("toInterval", from_optinterval)
+
+ .def(self == self)
+ .def(self != self)
+ ;
+ implicitly_convertible<Geom::Interval,tuple>();
+// TODO: is this possible?
+// implicitly_convertible<tuple,Geom::Interval>();
+
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/py2geom/line.cpp b/src/3rdparty/2geom/src/py2geom/line.cpp
new file mode 100644
index 0000000..0df4360
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/line.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2009 Nathan Hurst <njh@njhurst.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <boost/python.hpp>
+#include <boost/python/implicit.hpp>
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+
+#include "py2geom.h"
+#include "helpers.h"
+
+#include "2geom/line.h"
+//#include "2geom/bezier-curve.h"
+#include "2geom/point.h"
+
+using namespace boost::python;
+
+template <typename S, typename T>
+object wrap_intersection(S const& a, T const& b) {
+ Geom::OptCrossing oc = intersection(a, b);
+ return oc?object(*oc):object();
+}
+
+std::vector<Geom::Coord> (Geom::Line::*coefficients_vec)() const = &Geom::Line::coefficients;
+
+void wrap_line() {
+ //line.h
+
+ def("intersection", wrap_intersection<Geom::Line, Geom::Line>);
+ def("intersection", wrap_intersection<Geom::Line, Geom::Ray>);
+ //def("intersection", wrap_intersection<Geom::Line, Geom::LineSegment>);
+ def("intersection", wrap_intersection<Geom::Ray, Geom::Line>);
+ def("intersection", wrap_intersection<Geom::Ray, Geom::Ray>);
+ //def("intersection", wrap_intersection<Geom::Ray, Geom::LineSegment>);
+ //def("intersection", wrap_intersection<Geom::LineSegement, Geom::Line>);
+ //def("intersection", wrap_intersection<Geom::LineSegement, Geom::Ray>);
+ //def("intersection", wrap_intersection<Geom::LineSegement, Geom::LineSegment>);
+ class_<Geom::Line>("Line", init<>())
+ .def(init<Geom::Point const&, Geom::Coord>())
+ .def(init<Geom::Point const&, Geom::Point const&>())
+ .def(init<double, double, double>())
+ //.def(self_ns::str(self))
+ .def("valueAt", &Geom::Line::valueAt)
+
+ .def("coefficients", coefficients_vec)
+ .def("isDegenerate", &Geom::Line::isDegenerate)
+ .def("pointAt", &Geom::Line::pointAt)
+ .def("roots", &Geom::Line::roots)
+ .def("nearestTime", &Geom::Line::nearestTime)
+ .def("reverse", &Geom::Line::reverse)
+ //.def("portion", &Geom::Line::portion)
+ //.def("segment", &Geom::Line::segment)
+ .def("derivative", &Geom::Line::derivative)
+ .def("transformed", &Geom::Line::transformed)
+ .def("normal", &Geom::Line::normal)
+ .def("normalAndDist", &Geom::Line::normalAndDist)
+ .def("setPoints", &Geom::Line::setPoints)
+ .def("setCoefficients", &Geom::Line::setCoefficients)
+ ;
+
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/py2geom/linear.cpp b/src/3rdparty/2geom/src/py2geom/linear.cpp
new file mode 100644
index 0000000..419af64
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/linear.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2006, 2007 Aaron Spike <aaron@ekips.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <boost/python.hpp>
+#include <boost/python/implicit.hpp>
+
+#include "py2geom.h"
+#include "helpers.h"
+
+#include "2geom/linear.h"
+#include "2geom/point.h"
+#include "2geom/sbasis.h"
+
+using namespace boost::python;
+
+// helpers for bezord
+tuple bezord_to_tuple(Geom::Linear const& b)
+{
+ return make_tuple(b[0], b[1]);
+}
+
+Geom::Linear tuple_to_bezord(boost::python::tuple const& t)
+{
+ return Geom::Linear(extract<double>(t[0]), extract<double>(t[1]));
+}
+
+str bezord_repr(Geom::Linear const& b)
+{
+ return str("<" + str(b[0]) + ", " + str(b[1]) + ">");
+}
+
+void wrap_linear() {
+ def("lerp", (double (*)(double, double, double))&Geom::lerp);
+ def("reverse", (Geom::Linear (*)(Geom::Linear const &))&Geom::reverse);
+ def("bounds_fast", (Geom::OptInterval (*)(Geom::Linear const &))&Geom::bounds_fast);
+ def("bounds_exact", (Geom::OptInterval (*)(Geom::Linear const &))&Geom::bounds_exact);
+ def("bounds_local", (Geom::OptInterval (*)(Geom::Linear const &))&Geom::bounds_local);
+
+ class_<Geom::Linear>("Linear", init<double, double>())
+ .def("__str__", bezord_repr)
+ .def("__repr__", bezord_repr)
+ .def("__getitem__", python_getitem<Geom::Linear,double,2>)
+ .def("tuple", bezord_to_tuple)
+
+ .def("from_tuple", tuple_to_bezord)
+ .staticmethod("from_tuple")
+
+ .def("isZero", &Geom::Linear::isZero)
+ .def("isFinite", &Geom::Linear::isFinite)
+ .def("at0", (double (Geom::Linear::*)() const) &Geom::Linear::at0)
+ .def("at1", (double (Geom::Linear::*)() const) &Geom::Linear::at1)
+ .def("valueAt", &Geom::Linear::valueAt)
+ .def("toSBasis", &Geom::Linear::toSBasis)
+
+ .def(-self)
+ .def(self + self)
+ .def(self - self)
+ .def(self += self)
+ .def(self -= self)
+ .def(self + float())
+ .def(self - float())
+ .def(self += float())
+ .def(self -= float())
+ .def(self == self)
+ .def(self != self)
+ .def(self * float())
+ .def(self / float())
+ .def(self *= float())
+ .def(self /= float())
+ ;
+ def("reverse", ((Geom::Linear (*)(Geom::Linear const &b))&Geom::reverse));
+ //TODO: reinstate
+ //implicitly_convertible<Geom::Linear,tuple>();
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/py2geom/parser.cpp b/src/3rdparty/2geom/src/py2geom/parser.cpp
new file mode 100644
index 0000000..8f729a1
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/parser.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2008 Aaron Spike <aaron@ekips.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <boost/python.hpp>
+
+#include "py2geom.h"
+#include "helpers.h"
+
+#include "2geom/path-sink.h"
+#include "2geom/svg-path-parser.h"
+
+
+using namespace boost::python;
+
+void (*parse_svg_path_str_sink) (char const *, Geom::PathSink &) = &Geom::parse_svg_path;
+Geom::PathVector (*parse_svg_path_str) (char const *) = &Geom::parse_svg_path;
+
+void (Geom::PathSink::*feed_path)(Geom::Path const &) = &Geom::PathSink::feed;
+void (Geom::PathSink::*feed_pathvector)(Geom::PathVector const &) = &Geom::PathSink::feed;
+
+class PathSinkWrap: public Geom::PathSink, public wrapper<Geom::PathSink> {
+ void moveTo(Geom::Point const &p) {this->get_override("moveTo")(p);}
+ void lineTo(Geom::Point const &p) {this->get_override("lineTo")(p);}
+ void curveTo(Geom::Point const &c0, Geom::Point const &c1, Geom::Point const &p) {this->get_override("curveTo")(c0, c1, p);}
+ void quadTo(Geom::Point const &c, Geom::Point const &p) {this->get_override("quadTo")(c, p);}
+ void arcTo(double rx, double ry, double angle, bool large_arc, bool sweep, Geom::Point const &p) {this->get_override("arcTo")(rx, ry, angle, large_arc, sweep, p);}
+ bool backspace() {return this->get_override("backspace")();}
+ void closePath() {this->get_override("closePath")();}
+ void flush() {this->get_override("flush")();}
+};
+
+void wrap_parser() {
+ def("parse_svg_path", parse_svg_path_str_sink);
+ def("parse_svg_path", parse_svg_path_str);
+ def("read_svgd", Geom::read_svgd);
+
+ class_<PathSinkWrap, boost::noncopyable>("PathSink")
+ .def("moveTo", pure_virtual(&Geom::PathSink::moveTo))
+ .def("lineTo", pure_virtual(&Geom::PathSink::lineTo))
+ .def("curveTo", pure_virtual(&Geom::PathSink::curveTo))
+ .def("quadTo", pure_virtual(&Geom::PathSink::quadTo))
+ .def("arcTo", pure_virtual(&Geom::PathSink::arcTo))
+ .def("backspace", pure_virtual(&Geom::PathSink::backspace))
+ .def("closePath", pure_virtual(&Geom::PathSink::closePath))
+ .def("flush", pure_virtual(&Geom::PathSink::flush))
+ .def("feed", feed_path)
+ .def("feed", feed_pathvector)
+ ;
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/py2geom/path.cpp b/src/3rdparty/2geom/src/py2geom/path.cpp
new file mode 100644
index 0000000..68757a6
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/path.cpp
@@ -0,0 +1,265 @@
+/*
+ * Python bindings for lib2geom
+ *
+ * Copyright 2007 Aaron Spike <aaron@ekips.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <boost/python.hpp>
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+
+#include "2geom/curve.h"
+#include "2geom/bezier-curve.h"
+#include "2geom/path.h"
+#include "2geom/pathvector.h"
+#include "2geom/sbasis-to-bezier.h"
+#include "helpers.h"
+
+#include "2geom/point.h"
+#include "2geom/rect.h"
+#include "2geom/d2.h"
+
+using namespace boost::python;
+
+Geom::Curve const &path_getitem(Geom::Path const& p, int index)
+{
+ unsigned size = p.size_default();
+ unsigned i = index;
+ if (index < 0)
+ {
+ i = index = size + index;
+ }
+ if ((index < 0) || (i > (size - 1))) {
+ PyErr_SetString(PyExc_IndexError, "index out of range");
+ boost::python::throw_error_already_set();
+ }
+ return p[i];
+}
+
+struct CurveWrap : Geom::Curve, wrapper<Geom::Curve>
+{
+ Geom::Point initialPoint() const {return this->get_override("initialPoint")();}
+ Geom::Point finalPoint() const {return this->get_override("finalPoint")();}
+ bool isDegenerate() const {return this->get_override("isDegenerate")();}
+ CurveWrap *duplicate() const {return this->get_override("duplicate")();}
+ Geom::Rect boundsFast() const {return this->get_override("boundsFast")();}
+ Geom::Rect boundsExact() const {return this->get_override("boundsExact")();}
+ virtual Geom::OptRect boundsLocal(Geom::OptInterval const &i, unsigned deg) const {return this->get_override("boundsLocal")(i,deg);}
+ std::vector<double> roots(double v, Geom::Dim2 d) const {return this->get_override("roots")(v,d);}
+
+ int winding(Geom::Point const &p) const {
+ if (override f = this->get_override("winding")) {
+ return f(p);
+ }
+ return Geom::Curve::winding(p);
+ }
+ int default_winding(Geom::Point p) const { return this->Geom::Curve::winding(p); }
+
+ Geom::Curve *portion(double f, double t) const { return this->get_override("portion")(f,t); }
+ Geom::Curve *reverse() const {
+ if (override f = this->get_override("reverse")) {
+ return f();
+ }
+ return Geom::Curve::reverse();
+ }
+ Geom::Curve *default_reverse() const { return this->Geom::Curve::reverse(); }
+
+ Geom::Curve *derivative() const { return this->get_override("derivative")(); }
+
+
+ Geom::Curve *transformed(Geom::Affine const &m) const { return this->get_override("transformed")(m); }
+
+ Geom::Point pointAt(Geom::Coord t) const {
+ if (override f = this->get_override("pointAt")) {
+ return f(t);
+ }
+ return Geom::Curve::pointAt(t);
+ }
+ Geom::Point default_pointAt(Geom::Coord t) { return this->Geom::Curve::pointAt(t); }
+ std::vector<Geom::Point> pointAndDerivatives(Geom::Coord t, unsigned n) const {
+ return this->get_override("pointAndDerivatives")(t, n);
+ }
+
+ Geom::D2<Geom::SBasis> toSBasis() const {return this->get_override("sbasis")();}
+};
+
+
+/* pycairo stuff: */
+#ifdef HAVE_PYCAIRO
+
+#include "cairo-helpers.h"
+
+void py_cairo_curve(object cr, Geom::Curve const &c) {
+ cairo_curve(cairo_t_from_object(cr), c);
+}
+void py_cairo_rectangle(object cr, Geom::Rect const &r) {
+ cairo_rectangle(cairo_t_from_object(cr), r);
+}
+
+void py_cairo_convex_hull(object cr, Geom::ConvexHull const &r) {
+ cairo_convex_hull(cairo_t_from_object(cr), r);
+}
+/*void py_cairo_path(object cr, Geom::Path const &p) {
+ cairo_path(cairo_t_from_object(cr), p);
+ }*/
+
+void py_cairo_path(object cr, Geom::Path const &p) {
+ cairo_path(cairo_t_from_object(cr), p);
+}
+
+void py_cairo_path(object cr, Geom::PathVector const &p) {
+ cairo_path(cairo_t_from_object(cr), p);
+}
+void py_cairo_path_stitches(object cr, Geom::Path const &p) {
+ cairo_path_stitches(cairo_t_from_object(cr), p);
+}
+void py_cairo_path_stitches(object cr, Geom::PathVector const &p) {
+ cairo_path_stitches(cairo_t_from_object(cr), p);
+}
+void (*cp_1)(object, Geom::Path const &) = &py_cairo_path;
+void (*cp_2)(object, Geom::PathVector const &) = &py_cairo_path;
+
+void (*cps_1)(object, Geom::Path const &) = &py_cairo_path_stitches;
+void (*cps_2)(object, Geom::PathVector const &) = &py_cairo_path_stitches;
+
+
+void py_cairo_d2_sb(object cr, Geom::D2<Geom::SBasis> const &p) {
+ cairo_d2_sb(cairo_t_from_object(cr), p);
+}
+
+void py_cairo_d2_pw_sb(object cr, Geom::D2<Geom::Piecewise<Geom::SBasis> > const &p) {
+ cairo_d2_pw_sb(cairo_t_from_object(cr), p);
+}
+
+void py_cairo_pw_d2_sb(object cr, Geom::Piecewise<Geom::D2<Geom::SBasis> > const &p) {
+ cairo_pw_d2_sb(cairo_t_from_object(cr), p);
+}
+
+#endif // HAVE_PYCAIRO
+
+Geom::Point (Geom::Path::*path_pointAt_time)(Geom::Coord) const = &Geom::Path::pointAt;
+Geom::Coord (Geom::Path::*path_valueAt_time)(Geom::Coord, Geom::Dim2) const = &Geom::Path::valueAt;
+void (Geom::Path::*appendPortionTo_time)(Geom::Path &, Geom::Coord, Geom::Coord) const = &Geom::Path::appendPortionTo;
+//void (Geom::Path::*appendPortionTo_pos)(Geom::Path &, Geom::PathPosition const &, Geom::PathPosition const &, bool) const = &Geom::Path::appendPortionTo;
+
+void wrap_path()
+{
+/* class_<CurveWrap, boost::noncopyable>("Curve")
+ .def("initalPoint", pure_virtual(&Geom::Curve::initialPoint))
+ .def("finalPoint", pure_virtual(&Geom::Curve::finalPoint))
+ .def("duplicate", pure_virtual(&Geom::Curve::duplicate), return_value_policy<manage_new_object>())
+ .def("boundsFast", pure_virtual(&Geom::Curve::boundsFast))
+ .def("boundsExact", pure_virtual(&Geom::Curve::boundsExact))
+ //.def("pointAt", &Geom::Curve::pointAt, &CurveWrap::default_pointAt)
+ //.def("winding", &Geom::Curve::winding, &CurveWrap::default_winding)
+ .def("pointAndDerivatives", pure_virtual(&Geom::Curve::pointAndDerivatives))
+ .def("toSBasis", pure_virtual(&Geom::Curve::toSBasis))
+ ;*/
+/* class_<Geom::LineSegment, bases<CurveWrap> >("LineSegment")
+ .def("points", &Geom::LineSegment::points)
+ ;
+ class_<Geom::QuadraticBezier, bases<CurveWrap> >("QuadraticBezier")
+ .def("points", &Geom::QuadraticBezier::points)
+ ;
+ class_<Geom::CubicBezier, bases<CurveWrap> >("CubicBezier")
+ .def("points", &Geom::CubicBezier::points)
+ ;*/
+ class_<Geom::Path>("Path")
+ .def("__getitem__", path_getitem, return_value_policy<copy_const_reference>()) //or return_internal_reference see http://www.boost.org/doc/libs/1_36_0/libs/python/doc/v2/faq.html#question1
+ .def("empty", &Geom::Path::empty)
+ .def("closed", &Geom::Path::closed)
+ .def("close", &Geom::Path::close)
+ .def("boundsFast", &Geom::Path::boundsFast)
+ .def("boundsExact", &Geom::Path::boundsExact)
+ .def("toPwSb", &Geom::Path::toPwSb)
+ .def(self * Geom::Affine())
+ .def(self *= Geom::Affine())
+ .def("pointAt", path_pointAt_time)
+ .def("valueAt", path_valueAt_time)
+ .def("__call__", path_pointAt_time)
+ .def("roots", &Geom::Path::roots)
+ //.def("allNearestTimes", &Geom::Path::allNearestTimes)
+ //.def("nearestTime", &Geom::Path::nearestTime)
+ .def("appendPortionTo", appendPortionTo_time)
+ //.def("portion", &Geom::Path::portion)
+ .def("reversed", &Geom::Path::reversed)
+ //.def("insert", &Geom::Path::insert)
+ .def("clear", &Geom::Path::clear)
+ //.def("erase", &Geom::Path::erase)
+ .def("erase_last", &Geom::Path::erase_last)
+ //.def("replace", &Geom::Path::replace)
+ .def("start", &Geom::Path::start)
+ .def("initialPoint", &Geom::Path::initialPoint)
+ .def("finalPoint", &Geom::Path::finalPoint)
+ //.def("append", &Geom::Path::append)
+ //.def("appendNew", &Geom::Path::appendNew)
+ ;
+ def("paths_to_pw",Geom::paths_to_pw);
+ class_<Geom::PathVector >("PathVector")
+ .def(vector_indexing_suite<Geom::PathVector >())
+ .def(self * Geom::Affine())
+ .def(self *= Geom::Affine())
+ .def("reversed", &Geom::PathVector::reversed)
+ .def("reverse", &Geom::PathVector::reverse)
+ .def("boundsFast", &Geom::PathVector::boundsFast)
+ .def("boundsExact", &Geom::PathVector::boundsExact)
+ ;
+ def("path_from_piecewise", Geom::path_from_piecewise);
+ def("path_from_sbasis", Geom::path_from_sbasis);
+ def("cubicbezierpath_from_sbasis", Geom::cubicbezierpath_from_sbasis);
+
+#ifdef HAVE_PYCAIRO
+void cairo_move_to(cairo_t *cr, Geom::Point p1);
+ def("cubicbezierpath_from_sbasis", Geom::cubicbezierpath_from_sbasis);
+void cairo_line_to(cairo_t *cr, Geom::Point p1);
+ def("cubicbezierpath_from_sbasis", Geom::cubicbezierpath_from_sbasis);
+void cairo_curve_to(cairo_t *cr, Geom::Point p1, Geom::Point p2, Geom::Point p3);
+ def("cubicbezierpath_from_sbasis", Geom::cubicbezierpath_from_sbasis);
+
+ //def("cairo_curve", cairo_curve);
+ def("cairo_convex_hull", py_cairo_convex_hull);
+ def("cairo_path", cp_1);
+ def("cairo_path", cp_2);
+ def("cairo_path_stitches", cps_1);
+ def("cairo_path_stitches", cps_2);
+
+ def("cairo_d2_sb", py_cairo_d2_sb);
+ def("cairo_d2_pw_sb", py_cairo_d2_pw_sb);
+ def("cairo_pw_d2_sb", py_cairo_pw_d2_sb);
+#endif // HAVE_PYCAIRO
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(substatement-open . 0))
+ indent-tabs-mode:nil
+ c-brace-offset:0
+ fill-column:99
+ End:
+ vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+*/
diff --git a/src/3rdparty/2geom/src/py2geom/point.cpp b/src/3rdparty/2geom/src/py2geom/point.cpp
new file mode 100644
index 0000000..869240d
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/point.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2006, 2007 Aaron Spike <aaron@ekips.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <boost/python.hpp>
+#include <boost/python/implicit.hpp>
+
+#include "py2geom.h"
+#include "helpers.h"
+
+#include "2geom/point.h"
+
+using namespace boost::python;
+
+
+// helpers for point
+tuple point_to_tuple(Geom::Point const& p)
+{
+ return make_tuple(p[0], p[1]);
+}
+
+Geom::Point tuple_to_point(boost::python::tuple const& t)
+{
+ return Geom::Point(extract<double>(t[0]), extract<double>(t[1]));
+}
+
+str point_repr(Geom::Point const& p)
+{
+ return str("(" + str(p[0]) + ", " + str(p[1]) + ")");
+}
+
+//Specifications of overloads
+Geom::Coord (*L2_point) (Geom::Point const &) = &Geom::L2;
+Geom::Point (*rot90_point)(Geom::Point const &) = &Geom::rot90;
+Geom::Coord (*dot_point) (Geom::Point const &, Geom::Point const &) = &Geom::dot;
+Geom::Coord (*cross_point)(Geom::Point const &, Geom::Point const &) = &Geom::cross;
+Geom::Point (*lerp_point)(Geom::Coord, Geom::Point const &, Geom::Point const &) = &Geom::lerp;
+
+bool near_point1(Geom::Point const &a, Geom::Point const &b) { return are_near(a,b); }
+bool near_point2(Geom::Point const &a, Geom::Point const &b, double eps) { return are_near(a,b,eps); }
+
+void wrap_point() {
+ def("point_to_tuple", point_to_tuple);
+ def("tuple_to_point", tuple_to_point);
+
+ def("L1", Geom::L1);
+ def("L2", L2_point);
+ def("L2sq", Geom::L2sq);
+ def("LInfty", Geom::LInfty);
+
+ def("unit_vector", Geom::unit_vector);
+ def("is_zero", Geom::is_zero);
+ def("is_unit_vector", Geom::is_unit_vector);
+
+ def("dot", dot_point);
+ def("cross", cross_point);
+ def("distance", Geom::distance);
+ def("distanceSq", Geom::distanceSq);
+ def("lerp", lerp_point);
+
+ def("atan2", Geom::atan2);
+ def("angle_between", Geom::angle_between);
+
+ def("near", near_point1);
+ def("near", near_point2);
+
+ def("rot90", rot90_point);
+ def("abs", (Geom::Point (*)(Geom::Point const&))&Geom::abs);
+
+ class_<Geom::Point>("Point", init<double, double>())
+ .def(init<>())
+
+ .def("__str__", point_repr)
+ .def("__repr__", point_repr)
+ .def("__getitem__", python_getitem<Geom::Point,double,2>)
+ .def("tuple", point_to_tuple)
+
+ .def("from_tuple", tuple_to_point)
+ .staticmethod("from_tuple")
+
+ //point.h
+ //.def("polar", &Geom::Point::polar)
+ //.staticmethod("polar")
+
+ .def("ccw", &Geom::Point::ccw)
+ .def("cw", &Geom::Point::cw)
+ .def("round", &Geom::Point::round)
+ .def("normalize", &Geom::Point::normalize)
+
+ .def("length", &Geom::Point::length)
+
+ .def(self + self)
+ .def(self - self)
+ .def(self += self)
+ .def(self -= self)
+
+ .def(-self)
+ .def(self * float()).def(float() * self)
+ .def(self / float())
+ .def(self *= float())
+
+ .def(self == self)
+ .def(self != self)
+
+ .def(self <= self)
+ ;
+ implicitly_convertible<Geom::Point,tuple>();
+// TODO: explain why this gives a compile time error
+// implicitly_convertible<tuple,Geom::Point>();
+
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/py2geom/pw.cpp b/src/3rdparty/2geom/src/py2geom/pw.cpp
new file mode 100644
index 0000000..bbd8f2c
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/pw.cpp
@@ -0,0 +1,228 @@
+/*
+ * Copyright 2006, 2007 Aaron Spike <aaron@ekips.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+#include <boost/python.hpp>
+#include <boost/python/implicit.hpp>
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+
+#include "2geom/sbasis.h"
+#include "2geom/piecewise.h"
+#include "2geom/d2.h"
+#include "2geom/sbasis-math.h"
+#include "2geom/sbasis-geometric.h"
+
+#include "py2geom.h"
+#include "helpers.h"
+
+using namespace boost::python;
+
+// helpers for point
+tuple pwd2sb_centroid(Geom::Piecewise<Geom::D2<Geom::SBasis> > const &pw)
+{
+ Geom::Point p;
+ double a;
+ Geom::centroid(pw, p, a);
+ return boost::python::make_tuple(p, a);
+}
+
+
+void (Geom::Piecewise<Geom::SBasis>::*push_pwsb)(Geom::SBasis const &, double) = &Geom::Piecewise<Geom::SBasis>::push;
+void (Geom::Piecewise<Geom::SBasis>::*push_seg_pwsb)(Geom::SBasis const &) = &Geom::Piecewise<Geom::SBasis>::push_seg;
+Geom::Piecewise<Geom::SBasis> (*portion_pwsb)(const Geom::Piecewise<Geom::SBasis> &, double, double) = &Geom::portion;
+void (Geom::Piecewise<Geom::D2<Geom::SBasis>>::*push_pwd2sb)(Geom::D2<Geom::SBasis> const &, double) = &Geom::Piecewise<Geom::D2<Geom::SBasis>>::push;
+void (Geom::Piecewise<Geom::D2<Geom::SBasis>>::*push_seg_pwd2sb)(Geom::D2<Geom::SBasis> const &) = &Geom::Piecewise<Geom::D2<Geom::SBasis>>::push_seg;
+Geom::Piecewise<Geom::D2<Geom::SBasis>> (*portion_pwd2sb)(const Geom::Piecewise<Geom::D2<Geom::SBasis> > &, double, double) = &Geom::portion;
+std::vector<double> (*roots_pwsb)(const Geom::Piecewise<Geom::SBasis> &) = &Geom::roots;
+//Geom::Piecewise<Geom::SBasis> (*multiply_pwsb)(Geom::Piecewise<Geom::SBasis> const &, Geom::Piecewise<Geom::SBasis> const &) = &Geom::multiply;
+Geom::Piecewise<Geom::SBasis> (*divide_pwsb)(Geom::Piecewise<Geom::SBasis> const &, Geom::Piecewise<Geom::SBasis> const &, unsigned) = &Geom::divide;
+Geom::Piecewise<Geom::SBasis> (*compose_pwsb_sb)(Geom::Piecewise<Geom::SBasis> const &, Geom::SBasis const &) = &Geom::compose;
+Geom::Piecewise<Geom::SBasis> (*compose_pwsb)(Geom::Piecewise<Geom::SBasis> const &, Geom::Piecewise<Geom::SBasis> const &) = &Geom::compose;
+
+Geom::Piecewise<Geom::SBasis> (*abs_pwsb)(Geom::Piecewise<Geom::SBasis> const &) = &Geom::abs;
+
+Geom::Piecewise<Geom::SBasis> (*min_pwsb)(Geom::Piecewise<Geom::SBasis> const &, Geom::Piecewise<Geom::SBasis> const &) = &Geom::min;
+Geom::Piecewise<Geom::SBasis> (*max_pwsb)(Geom::Piecewise<Geom::SBasis> const &, Geom::Piecewise<Geom::SBasis> const &) = &Geom::max;
+Geom::Piecewise<Geom::SBasis> (*signSb_pwsb)(Geom::Piecewise<Geom::SBasis> const &) = &Geom::signSb;
+
+Geom::Piecewise<Geom::SBasis> (*sqrt_pwsb)(Geom::Piecewise<Geom::SBasis> const &, double, int) = &Geom::sqrt;
+
+Geom::Piecewise<Geom::SBasis> (*sin_pwsb)(Geom::Piecewise<Geom::SBasis> const &, double, int) = &Geom::sin;
+Geom::Piecewise<Geom::SBasis> (*cos_pwsb)(Geom::Piecewise<Geom::SBasis> const &, double, int) = &Geom::cos;
+
+//Geom::Piecewise<Geom::SBasis> (*log_pwsb)(Geom::Piecewise<Geom::SBasis> const &, double, int) = &Geom::log;
+Geom::Piecewise<Geom::SBasis> (*reciprocal_pwsb)(Geom::Piecewise<Geom::SBasis> const &, double, int) = &Geom::reciprocal;
+
+Geom::FragmentConcept<Geom::SBasis>::BoundsType (*bounds_fast_pwsb)(Geom::Piecewise<Geom::SBasis> const &) = &Geom::bounds_fast;
+Geom::FragmentConcept<Geom::SBasis>::BoundsType (*bounds_exact_pwsb)(Geom::Piecewise<Geom::SBasis> const &) = &Geom::bounds_exact;
+Geom::FragmentConcept<Geom::SBasis>::BoundsType (*bounds_local_pwsb)(Geom::Piecewise<Geom::SBasis> const &, const Geom::OptInterval &) = &Geom::bounds_local;
+
+Geom::SBasis getitem_pwsb(Geom::Piecewise<Geom::SBasis> const &p, int index) {
+ unsigned D = p.size();
+ unsigned i = index;
+ if (index < 0)
+ {
+ i = index = D + index;
+ }
+ if (index < 0 || i > (D - 1)) {
+ PyErr_SetString(PyExc_IndexError, "index out of range");
+ boost::python::throw_error_already_set();
+ }
+ return p[i];
+}
+
+Geom::Piecewise<Geom::D2<Geom::SBasis> > (*unitVector_pwd2sb)(Geom::Piecewise<Geom::D2<Geom::SBasis> > const &, double, unsigned int) = &Geom::unitVector;
+
+Geom::Piecewise<Geom::SBasis> (*arcLengthSb_pwd2sb)(Geom::Piecewise<Geom::D2<Geom::SBasis> > const &, double) = &Geom::arcLengthSb;
+
+Geom::Piecewise<Geom::D2<Geom::SBasis> > (*rot90_pwd2sb)(Geom::Piecewise<Geom::D2<Geom::SBasis> > const &) = &Geom::rot90;
+
+void wrap_pw() {
+ class_<std::vector<Geom::SBasis> >("SBasisVec")
+ .def(vector_indexing_suite<std::vector<Geom::SBasis> >())
+ ;
+ class_<std::vector<Geom::D2<Geom::SBasis> > >("D2SBasisVec")
+ .def(vector_indexing_suite<std::vector<Geom::D2<Geom::SBasis> > >())
+ ;
+
+ def("portion", portion_pwsb);
+ def("portion", portion_pwd2sb);
+ //def("partition", &partition);
+ def("roots", roots_pwsb);
+ //def("multiply", multiply_pwsb);
+ def("divide", divide_pwsb);
+ def("compose", compose_pwsb_sb);
+ def("compose", compose_pwsb);
+ def("abs", abs_pwsb);
+ def("min", min_pwsb);
+ def("max", max_pwsb);
+ def("signSb", signSb_pwsb);
+ def("sqrt", sqrt_pwsb);
+ def("cos", cos_pwsb);
+ def("sin", sin_pwsb);
+ //def("log", log_pwsb);
+ def("reciprocal", reciprocal_pwsb);
+ def("bounds_fast", bounds_fast_pwsb);
+ def("bounds_exact", bounds_exact_pwsb);
+ def("bounds_local", bounds_local_pwsb);
+
+ def("derivative", (Geom::Piecewise<Geom::SBasis> (*)(Geom::Piecewise<Geom::SBasis> const & ))&Geom::derivative);
+ def("integral", (Geom::Piecewise<Geom::SBasis> (*)(Geom::Piecewise<Geom::SBasis> const & ))&Geom::integral);
+ def("derivative", (Geom::Piecewise<Geom::D2<Geom::SBasis> > (*)(Geom::Piecewise<Geom::D2<Geom::SBasis> > const &)) &Geom::derivative);
+ def("rot90", rot90_pwd2sb);
+ def("unit_vector", unitVector_pwd2sb);
+ def("arcLengthSb", arcLengthSb_pwd2sb);
+
+ class_<Geom::Piecewise<Geom::SBasis> >("PiecewiseSBasis", init<>())
+ .def(init<double>())
+ .def(init<Geom::SBasis>())
+ .def("__getitem__", getitem_pwsb)
+ .def("__call__", &Geom::Piecewise<Geom::SBasis>::valueAt)
+ .def_readonly("cuts", &Geom::Piecewise<Geom::SBasis>::cuts)
+ .def_readonly("segs", &Geom::Piecewise<Geom::SBasis>::segs)
+ .def("at0", &Geom::Piecewise<Geom::SBasis>::firstValue)
+ .def("at1", &Geom::Piecewise<Geom::SBasis>::lastValue)
+ .def("valueAt", &Geom::Piecewise<Geom::SBasis>::valueAt)
+ .def("size", &Geom::Piecewise<Geom::SBasis>::size)
+ .def("empty", &Geom::Piecewise<Geom::SBasis>::empty)
+ .def("push", push_pwsb)
+ .def("push_cut", &Geom::Piecewise<Geom::SBasis>::push_cut)
+ .def("push_seg", push_seg_pwsb)
+
+ .def("segN", &Geom::Piecewise<Geom::SBasis>::segN)
+ .def("segT", &Geom::Piecewise<Geom::SBasis>::segT)
+ .def("offsetDomain", &Geom::Piecewise<Geom::SBasis>::offsetDomain)
+ .def("scaleDomain", &Geom::Piecewise<Geom::SBasis>::scaleDomain)
+ .def("setDomain", &Geom::Piecewise<Geom::SBasis>::setDomain)
+ .def("concat", &Geom::Piecewise<Geom::SBasis>::concat)
+ .def("continuousConcat", &Geom::Piecewise<Geom::SBasis>::continuousConcat)
+ .def("invariants", &Geom::Piecewise<Geom::SBasis>::invariants)
+
+ .def(self + double())
+ .def(-self)
+ .def(self += double())
+ .def(self -= double())
+ .def(self /= double())
+ .def(self * double())
+ .def(self *= double())
+ .def(self + self)
+ .def(self - self)
+ .def(self * self)
+ .def(self *= self)
+
+ ;
+
+ class_<Geom::Piecewise<Geom::D2<Geom::SBasis> > >("PiecewiseD2SBasis", init<>())
+ .def(init<Geom::D2<Geom::SBasis> >())
+ .def("__getitem__", getitem_pwsb)
+ .def("__call__", &Geom::Piecewise<Geom::D2<Geom::SBasis> >::valueAt)
+ .def_readonly("cuts", &Geom::Piecewise<Geom::D2<Geom::SBasis> >::cuts)
+ .def_readonly("segs", &Geom::Piecewise<Geom::D2<Geom::SBasis> >::segs)
+ .def("valueAt", &Geom::Piecewise<Geom::D2<Geom::SBasis> >::valueAt)
+ .def("size", &Geom::Piecewise<Geom::D2<Geom::SBasis> >::size)
+ .def("empty", &Geom::Piecewise<Geom::D2<Geom::SBasis> >::empty)
+ .def("push", push_pwd2sb)
+ .def("push_cut", &Geom::Piecewise<Geom::D2<Geom::SBasis> >::push_cut)
+ .def("push_seg", push_seg_pwd2sb)
+
+ .def("segN", &Geom::Piecewise<Geom::D2<Geom::SBasis> >::segN)
+ .def("segT", &Geom::Piecewise<Geom::D2<Geom::SBasis> >::segT)
+ .def("offsetDomain", &Geom::Piecewise<Geom::D2<Geom::SBasis> >::offsetDomain)
+ .def("scaleDomain", &Geom::Piecewise<Geom::D2<Geom::SBasis> >::scaleDomain)
+ .def("setDomain", &Geom::Piecewise<Geom::D2<Geom::SBasis> >::setDomain)
+ .def("concat", &Geom::Piecewise<Geom::D2<Geom::SBasis> >::concat)
+ .def("continuousConcat", &Geom::Piecewise<Geom::D2<Geom::SBasis> >::continuousConcat)
+ .def("invariants", &Geom::Piecewise<Geom::D2<Geom::SBasis> >::invariants)
+
+ //.def(self + double())
+ .def(-self)
+ //.def(self += double())
+ //.def(self -= double())
+ //.def(self /= double())
+ .def(self * double())
+ .def(Geom::Piecewise<Geom::SBasis>() * self)
+ .def(self *= double())
+ .def(self + self)
+ .def(self - self)
+ //.def(self * self)
+ //.def(self *= self)
+
+ ;
+ def("centroid", pwd2sb_centroid);
+ def("make_cuts_independent", Geom::make_cuts_independent);
+
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/py2geom/py2geom.cpp b/src/3rdparty/2geom/src/py2geom/py2geom.cpp
new file mode 100644
index 0000000..b1ef493
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/py2geom.cpp
@@ -0,0 +1,85 @@
+/*
+ * Python bindings for lib2geom
+ *
+ * Copyright 2006, 2007 Aaron Spike <aaron@ekips.org>
+ * Copyright 2007 Alex Mac <ajm@cs.nott.ac.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+#include <boost/python.hpp>
+#include <boost/python/implicit.hpp>
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+
+#include <2geom/geom.h>
+
+#include "py2geom.h"
+
+using namespace boost::python;
+
+BOOST_PYTHON_MODULE(_py2geom)
+{
+
+ /*enum_<IntersectorKind>("IntersectorKind")
+ .value("intersects", intersects)
+ .value("parallel", parallel)
+ .value("coincident", coincident)
+ .value("no_intersection", no_intersection)
+ ;
+ def("segment_intersect", segment_intersect);*/
+
+ wrap_point();
+ wrap_etc();
+ wrap_interval();
+ wrap_transforms();
+ wrap_rect();
+ wrap_circle();
+ wrap_ellipse();
+ wrap_sbasis();
+ wrap_bezier();
+ wrap_linear();
+ wrap_line();
+ wrap_conic();
+ wrap_pw();
+ wrap_d2();
+ wrap_parser();
+ wrap_path();
+ wrap_ray();
+ // wrap_shape();
+ wrap_crossing();
+ // wrap_convex_cover();
+
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(substatement-open . 0))
+ indent-tabs-mode:nil
+ c-brace-offset:0
+ fill-column:99
+ End:
+ vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+*/
diff --git a/src/3rdparty/2geom/src/py2geom/py2geom.h b/src/3rdparty/2geom/src/py2geom/py2geom.h
new file mode 100644
index 0000000..ba9fb13
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/py2geom.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2006, 2007 Aaron Spike <aaron@ekips.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#ifndef SEEN_PY2GEOM_H
+#define SEEN_PY2GEOM_H
+
+void wrap_point();
+void wrap_etc();
+void wrap_interval();
+void wrap_transforms();
+void wrap_rect();
+void wrap_circle();
+void wrap_ellipse();
+void wrap_sbasis();
+void wrap_bezier();
+void wrap_linear();
+void wrap_pw();
+void wrap_d2();
+void wrap_path();
+void wrap_parser();
+void wrap_ray();
+// void wrap_shape();
+void wrap_line();
+void wrap_conic();
+void wrap_crossing();
+// void wrap_convex_cover();
+namespace Geom{
+class Point;
+class Linear;
+};
+#include <vector>
+typedef std::vector<Geom::Point > PointVec;
+typedef std::vector<double > DoubleVec;
+typedef std::vector<Geom::Linear> LinearVec;
+
+#endif
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/py2geom/ray.cpp b/src/3rdparty/2geom/src/py2geom/ray.cpp
new file mode 100644
index 0000000..9fda595
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/ray.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2009 Ricardo Lafuente <r@sollec.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <boost/python.hpp>
+#include <boost/python/implicit.hpp>
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+
+#include "py2geom.h"
+#include "helpers.h"
+
+#include "2geom/point.h"
+#include "2geom/ray.h"
+// #include "2geom/bezier_curve.h"
+#include "2geom/exception.h"
+
+
+using namespace boost::python;
+
+bool (*are_near_ray)(Geom::Point const& _point, Geom::Ray const& _ray, double eps) = &Geom::are_near;
+double (*angle_between_ray)(Geom::Ray const& r1, Geom::Ray const& r2, bool cw) = &Geom::angle_between;
+
+
+double angle_between_ray_def(Geom::Ray const& r1, Geom::Ray const& r2) {
+ return Geom::angle_between(r1, r2);
+}
+double (*distance_ray)(Geom::Point const& _point, Geom::Ray const& _ray) = &Geom::distance;
+
+// why don't these compile?
+//Geom::Point (*get_ray_origin)(Geom::Ray const) = &Geom::Ray::origin;
+//void (*set_ray_origin)(Geom::Ray const, Geom::Point const& _point) = &Geom::Ray::origin;
+
+void wrap_ray() {
+ def("distance", distance_ray);
+ def("are_near", are_near_ray);
+ def("are_same", Geom::are_same);
+ def("angle_between", angle_between_ray);
+ def("angle_between", angle_between_ray_def);
+ def("make_angle_bisector_ray", Geom::make_angle_bisector_ray);
+
+ class_<Geom::Ray>("Ray", init<Geom::Point, Geom::Coord>())
+ .def(init<Geom::Point,Geom::Point>())
+ .def(init<>())
+
+ // TODO: overloaded
+ //.add_property("origin", get_ray_origin, set_ray_origin)
+ // .add_property("versor", &Geom::Ray::versor, &Geom::Ray::versor)
+ // .add_property("angle", &Geom::Ray::angle, &Geom::Ray::angle)
+
+ .def("isDegenerate", &Geom::Ray::isDegenerate)
+ .def("nearestTime", &Geom::Ray::nearestTime)
+ .def("setBy2Points", &Geom::Ray::setPoints)
+ .def("valueAt", &Geom::Ray::valueAt)
+ .def("pointAt", &Geom::Ray::pointAt)
+ .def("nearestTime", &Geom::Ray::nearestTime)
+ .def("reverse", &Geom::Ray::reverse)
+ .def("roots", &Geom::Ray::roots)
+ .def("transformed", &Geom::Ray::transformed)
+ // requires Curve
+ // .def("portion", &Geom::Ray::portion)
+ .def("segment", &Geom::Ray::segment)
+ ;
+
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/py2geom/rect.cpp b/src/3rdparty/2geom/src/py2geom/rect.cpp
new file mode 100644
index 0000000..3b75625
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/rect.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2008 Aaron Spike <aaron@ekips.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <boost/python.hpp>
+#include <boost/python/implicit.hpp>
+
+#include "py2geom.h"
+#include "helpers.h"
+
+#include "2geom/affine.h"
+#include "2geom/d2.h"
+#include "2geom/interval.h"
+
+using namespace boost::python;
+
+static bool wrap_contains_coord(Geom::Rect const &x, Geom::Point val) {
+ return x.contains(val);
+}
+
+static bool wrap_contains_ivl(Geom::Rect const &x, Geom::Rect val) {
+ return x.contains(val);
+}
+
+static bool wrap_interiorContains_coord(Geom::Rect const &x, Geom::Point val) {
+ return x.interiorContains(val);
+}
+
+static bool wrap_interiorContains_ivl(Geom::Rect const &x, Geom::Rect val) {
+ return x.interiorContains(val);
+}
+
+static void wrap_expandBy_pt(Geom::Rect &x, Geom::Point val) {
+ x.expandBy(val);
+}
+
+static void wrap_expandBy(Geom::Rect &x, double val) {
+ x.expandBy(val);
+}
+
+static void wrap_unionWith(Geom::Rect &x, Geom::Rect const &y) {
+ x.unionWith(y);
+}
+static bool wrap_intersects(Geom::Rect const &x, Geom::Rect const &y) {
+ return x.intersects(y);
+}
+
+void wrap_rect() {
+ //TODO: fix overloads
+ //def("unify", Geom::unify);
+ def("union_list", Geom::union_list);
+ //def("intersect", Geom::intersect);
+ def("distanceSq", (double (*)( Geom::Point const&, Geom::Rect const& ))Geom::distanceSq);
+ def("distance", (double (*)( Geom::Point const&, Geom::Rect const& ))Geom::distance);
+
+ class_<Geom::Rect>("Rect", init<Geom::Interval, Geom::Interval>())
+ .def(init<Geom::Point,Geom::Point>())
+ .def(init<>())
+ .def(init<Geom::Rect const &>())
+
+ .def("__getitem__", python_getitem<Geom::Rect,Geom::Interval,2>)
+
+ .def("min", &Geom::Rect::min)
+ .def("max", &Geom::Rect::max)
+ .def("corner", &Geom::Rect::corner)
+ .def("top", &Geom::Rect::top)
+ .def("bottom", &Geom::Rect::bottom)
+ .def("left", &Geom::Rect::left)
+ .def("right", &Geom::Rect::right)
+ .def("width", &Geom::Rect::width)
+ .def("height", &Geom::Rect::height)
+ .def("dimensions", &Geom::Rect::dimensions)
+ .def("midpoint", &Geom::Rect::midpoint)
+ .def("area", &Geom::Rect::area)
+ .def("maxExtent", &Geom::Rect::maxExtent)
+ .def("contains", wrap_contains_coord)
+ .def("contains", wrap_contains_ivl)
+ .def("interiorContains", wrap_interiorContains_coord)
+ .def("interiorContains", wrap_interiorContains_ivl)
+ .def("intersects", wrap_intersects)
+ .def("expandTo", &Geom::Rect::expandTo)
+ .def("unionWith", &wrap_unionWith)
+ // TODO: overloaded
+ .def("expandBy", wrap_expandBy)
+ .def("expandBy", wrap_expandBy_pt)
+
+ .def(self * Geom::Affine())
+ ;
+
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/py2geom/sbasis.cpp b/src/3rdparty/2geom/src/py2geom/sbasis.cpp
new file mode 100644
index 0000000..be547ca
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/sbasis.cpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2006, 2007 Aaron Spike <aaron@ekips.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <boost/python.hpp>
+#include <boost/python/implicit.hpp>
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+
+#include "py2geom.h"
+#include "helpers.h"
+
+#include "2geom/sbasis.h"
+#include "2geom/sbasis-math.h"
+#include "2geom/point.h"
+
+using namespace boost::python;
+
+Geom::SBasis (*truncate_sbasis)(Geom::SBasis const &, unsigned) = &Geom::truncate;
+Geom::SBasis (*multiply_sbasis)(Geom::SBasis const &, Geom::SBasis const &) = &Geom::multiply;
+Geom::SBasis (*integral_sbasis)(Geom::SBasis const &) = &Geom::integral;
+Geom::SBasis (*derivative_sbasis)(Geom::SBasis const &) = &Geom::derivative;
+
+Geom::Linear sbasis_getitem(Geom::SBasis const& p, int index)
+{
+ int D = p.size();
+ if (index < 0)
+ {
+ index = D + index;
+ }
+ if ((index < 0) || (index > (D - 1))) {
+ PyErr_SetString(PyExc_IndexError, "index out of range");
+ boost::python::throw_error_already_set();
+ }
+ return p[index];
+}
+
+int sbasis_len(Geom::SBasis const& p)
+{
+ return p.size();
+}
+
+#include "2geom/sbasis-to-bezier.h"
+#include "2geom/bezier.h"
+
+Geom::Bezier sbasis_to_returned_bezier (Geom::SBasis const& sb, size_t sz = 0) {
+ Geom::Bezier res;
+ Geom::sbasis_to_bezier(res, sb, sz);
+ return res;
+}
+
+/*object wrap_bounds_fast(Geom::SBasis const& sb) {
+ Geom::OptInterval oi = bounds_fast(sb);
+ return oi?object(*oi):object();
+ }*/
+
+template <typename T, typename target_type>
+object wrap_bounds_fast(T const& sb) {
+ target_type oi = bounds_fast(sb);
+ return oi?object(*oi):object();
+}
+
+
+object wrap_bounds_exact(Geom::SBasis const& sb) {
+ Geom::OptInterval oi = bounds_exact(sb);
+ return oi?object(*oi):object();
+}
+
+object wrap_bounds_local(Geom::SBasis const& sb, Geom::Interval const & iv) {
+ Geom::OptInterval oi = bounds_local(sb, iv);
+ return oi?object(*oi):object();
+}
+void wrap_sbasis() {
+ //sbasis.h
+
+ def("shift", (Geom::SBasis (*)(Geom::SBasis const &a, int sh))&Geom::shift);
+ def("truncate", truncate_sbasis);
+ def("multiply", multiply_sbasis);
+ def("compose", (Geom::SBasis (*) (Geom::SBasis const &, Geom::SBasis const &))&Geom::compose);
+ def("integral", integral_sbasis);
+ def("derivative", derivative_sbasis);
+ def("min", (Geom::Piecewise<Geom::SBasis> (*)(Geom::SBasis const &, Geom::SBasis const & ))&Geom::min);
+ def("sqrt", (Geom::SBasis (*)(Geom::SBasis const &, int ))&Geom::sqrt);
+ def("reciprocal", (Geom::SBasis (*)(Geom::Linear const &, int ))&Geom::reciprocal);
+ def("divide",(Geom::SBasis (*)(Geom::SBasis const &, Geom::SBasis const &, int )) &Geom::divide);
+ def("inverse", (Geom::SBasis (*)(Geom::SBasis, int ))&Geom::inverse);
+ //def("sin", (Geom::SBasis (*)(Geom::SBasis const &, int ))&Geom::sin);
+ //def("cos", (Geom::SBasis (*)(Geom::SBasis const &, int ))&Geom::cos);
+ def("reverse", (Geom::SBasis (*)(Geom::SBasis const &))&Geom::reverse);
+ def("roots", (std::vector<double> (*)(Geom::SBasis const &))&Geom::roots);
+ def("bounds_fast", &wrap_bounds_fast<Geom::SBasis, Geom::OptInterval>);
+ def("bounds_exact", &wrap_bounds_exact);
+ def("bounds_local", &wrap_bounds_local);
+ def("sbasis_to_bezier", &::sbasis_to_returned_bezier);
+
+ class_<Geom::SBasis>("SBasis", init<double>())
+ .def(init<double, double>())
+ .def(init<Geom::Linear>())
+ .def(self_ns::str(self))
+ //TODO: add important vector funcs
+ .def("__getitem__", &sbasis_getitem)
+ .def("__len__", &sbasis_len)
+
+ .def("isZero", &Geom::SBasis::isZero)
+ .def("isFinite", &Geom::SBasis::isFinite)
+ .def("at0", (double (Geom::SBasis::*)() const) &Geom::SBasis::at0)
+ .def("at1", (double (Geom::SBasis::*)() const) &Geom::SBasis::at1)
+ .def("valueAt", &Geom::SBasis::valueAt)
+ .def("toSBasis", &Geom::SBasis::toSBasis)
+
+ .def("normalize", &Geom::SBasis::normalize)
+ .def("tailError", &Geom::SBasis::tailError)
+ .def("truncate", &Geom::SBasis::truncate)
+
+ .def(self + self)
+ .def(self - self)
+ .def(self += self)
+ .def(self -= self)
+
+ .def(self + Geom::Linear())
+ .def(self - Geom::Linear())
+ .def(self += Geom::Linear())
+ .def(self -= Geom::Linear())
+
+ .def(self + float())
+ .def(self - float())
+ .def(self += float())
+ .def(self -= float())
+
+ .def(-self)
+ .def(self * self)
+ .def(self *= self)
+ .def(self * float())
+ .def(float() * self)
+ .def(self / float())
+ .def(self *= float())
+ .def(self /= float())
+ ;
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/py2geom/transforms.cpp b/src/3rdparty/2geom/src/py2geom/transforms.cpp
new file mode 100644
index 0000000..ea050da
--- /dev/null
+++ b/src/3rdparty/2geom/src/py2geom/transforms.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2006, 2007 Aaron Spike <aaron@ekips.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <boost/python.hpp>
+
+#include "py2geom.h"
+
+#include "2geom/transforms.h"
+
+using namespace boost::python;
+
+//TODO: properly wrap other transforms
+
+void wrap_transforms() {
+ class_<Geom::Affine>("Affine", init<double, double, double, double, double, double>())
+ .def(init<>())
+ .def(init<Geom::Rotate>())
+ .def(init<Geom::Scale>())
+ .def(init<Geom::Translate>())
+ .def(self_ns::str(self))
+ .add_property("xAxis",&Geom::Affine::xAxis,&Geom::Affine::setXAxis)
+ .add_property("yAxis",&Geom::Affine::yAxis,&Geom::Affine::setYAxis)
+ .add_property("translation",&Geom::Affine::translation,&Geom::Affine::setTranslation)
+ .def("isTranslation", &Geom::Affine::isTranslation)
+ .def("isRotation", &Geom::Affine::isRotation)
+ .def("isScale", &Geom::Affine::isScale)
+ .def("isUniformScale", &Geom::Affine::isUniformScale)
+ .def("setIdentity", &Geom::Affine::setIdentity)
+ .def("inverse", &Geom::Affine::inverse)
+ .def("det", &Geom::Affine::det)
+ .def("descrim2", &Geom::Affine::descrim2)
+ .def("descrim", &Geom::Affine::descrim)
+ .def("expansionX", &Geom::Affine::expansionX)
+ .def("expansionY", &Geom::Affine::expansionY)
+ .def(self * self)
+ .def(self * other<Geom::Translate>())
+ .def(self * other<Geom::Scale>())
+ .def(self * other<Geom::Rotate>())
+ ;
+
+ class_<Geom::Scale>("Scale", init<double, double>())
+ .def(self == self)
+ .def(self != self)
+ .def("inverse", &Geom::Scale::inverse)
+ .def(Geom::Point() * self)
+ .def(self * self)
+ .def(self * Geom::Affine())
+ ;
+
+ class_<Geom::Translate>("Translate", init<double, double>())
+ .def(init<Geom::Point>())
+ .def(self == self)
+ .def(self != self)
+ .def("inverse", &Geom::Translate::inverse)
+ .def(Geom::Point() * self)
+ .def(self * self)
+ .def(self * other<Geom::Rotate>())
+ .def(self * other<Geom::Scale>())
+ ;
+
+ class_<Geom::Rotate>("Rotate", init<double>())
+ .def(self == self)
+ .def(self != self)
+ .def("inverse", &Geom::Rotate::inverse)
+ .def("from_degrees", &Geom::Rotate::from_degrees)
+ .staticmethod("from_degrees")
+ .def(Geom::Point() * self)
+ .def(self * self)
+ .def(Geom::Affine() * self)
+ ;
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/python/cy2geom_example.py b/src/3rdparty/2geom/src/python/cy2geom_example.py
new file mode 100644
index 0000000..aca7dca
--- /dev/null
+++ b/src/3rdparty/2geom/src/python/cy2geom_example.py
@@ -0,0 +1,10 @@
+#!/usr/bin/python
+
+import cy2geom
+from cy2geom import *
+
+a = Point(1,2)
+b = Point(31,2)
+print a, b
+print Point.dot(a,b)
+print Point.unit_vector(a)
diff --git a/src/3rdparty/2geom/src/python/elip.py b/src/3rdparty/2geom/src/python/elip.py
new file mode 100644
index 0000000..9809db8
--- /dev/null
+++ b/src/3rdparty/2geom/src/python/elip.py
@@ -0,0 +1,155 @@
+#!/usr/bin/python
+
+import gtk,gtk.gdk,math,pango #Numeric,
+
+templayout = None
+
+def draw_spot(w, h):
+ x,y = h.x, h.y
+ g = gtk.gdk.GC(w)
+ w.draw_line(g, int(x), int(y), int(x), int(y))
+
+def draw_handle(w, h, name = ""):
+ x,y = h.x, h.y
+ g = gtk.gdk.GC(w)
+ w.draw_line(g, int(x-3), int(y), int(x+3), int(y))
+ w.draw_line(g, int(x), int(y-3), int(x), int(y+3))
+ templayout.set_text(name)
+ w.draw_layout(g, x, y, templayout)
+
+def draw_ray(w, h, d):
+ x,y = h.x, h.y
+ g = gtk.gdk.GC(w)
+ w.draw_line(g, int(h.x), int(h.y), int(3*d.x-2*h.x), int(3*d.y-2*h.y))
+
+def intersect(n0, d0, n1, d1):
+ denominator = n0.x*n1.y - n0.y*n1.x
+ X = n1.y * d0 - n0.y * d1
+ if denominator == 0:
+ return None;
+
+ Y = n0.x * d1 - n1.x * d0
+
+ return handle(X / denominator, Y / denominator)
+
+def seg(a0, a1, b0, b1):
+ n0 = handle(a1.y - a0.y, -a1.x + a0.x)
+ d0 = n0.x*a0.x + n0.y *a0.y
+ n1 = handle(b1.y - b0.y, -b1.x + b0.x)
+ d1 = n1.x*b0.x + n1.y *b0.y
+
+ return intersect(n0, d0, n1, d1)
+
+def draw_elip(w, h):
+ g = gtk.gdk.GC(w)
+ w.draw_line(g, h[0].x, h[0].y, h[1].x, h[1].y)
+ w.draw_line(g, h[3].x, h[3].y, h[4].x, h[4].y)
+ w.draw_line(g, h[3].x, h[3].y, h[2].x, h[2].y)
+ w.draw_line(g, h[2].x, h[2].y, h[1].x, h[1].y)
+
+ c = seg(h[0], h[1], h[3], h[4])
+ draw_handle(w, c)
+
+ if 0:
+ for i in range(6):
+ w.draw_line(g, h[i].x, h[i].y, h[(i+1)%6].x, h[(i+1)%6].y)
+
+
+ cx,cy = c.x, c.y
+
+ ox, oy = None, None
+ for i in range(0, 101):
+ t = i/100.0
+
+
+ nx = (1-t)*h[0].x + t*h[3].x
+ ny = (1-t)*h[0].y + t*h[3].y
+ #w.draw_line(g, 2*cx-nx, 2*cy-ny, nx, ny)
+ c1 = seg(handle(2*cx-nx, 2*cy-ny), handle(nx, ny), h[0], h[2])
+ #draw_handle(w, c1)
+ c2 = seg(handle(2*cx-nx, 2*cy-ny), handle(nx, ny), h[4], h[2])
+ #draw_handle(w, c2)
+ #draw_ray(w, h[3], c1)
+ #draw_ray(w, h[1], c2)
+ six = seg(c1, h[3], c2, h[1])
+ #draw_spot(w, six)
+ if ox:
+ w.draw_line(g, ox, oy, six.x, six.y)
+ ox, oy = six.x, six.y
+ return
+
+ r = math.hypot(h[0].x - cx, h[0].y - cy)
+ s = math.atan2(h[0].y - h[3].y, h[0].x - h[3].x)
+ e = math.atan2(h[1].y - h[4].y, h[1].x - h[4].x)
+ for i in range(0, 101):
+ t = (e-s)*i/100.0 + s
+ nx, ny = r*math.cos(t)+cx, r*math.sin(t)+cy
+ sx, sy = r*math.cos(t+math.pi)+cx, r*math.sin(t+math.pi)+cy
+ w.draw_line(g, sx, sy, nx, ny)
+
+
+class handle:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+ def __repr__(self):
+ return "handle(%f, %f)" % (self.x, self.y)
+
+handles = [handle(145.000000, 50.000000), handle(43.000000, 69.000000), handle(26.000000, 135.000000), handle(48.000000, 189.000000), handle(248.000000, 188.000000)]
+
+selected_handle = None
+
+def display(da, ev):
+ g = gtk.gdk.GC(da.window)
+ i = 0
+
+
+
+ for h in handles:
+ draw_handle(da.window, h, str(i))
+ i += 1
+ draw_elip(da.window, handles)
+
+def mouse_event(w, e):
+ global selected_handle
+ if e.button == 1:
+ for h in handles:
+ if math.hypot(e.x-h.x, e.y - h.y) < 5:
+ selected_handle = (h, (e.x-h.x, e.y-h.y))
+
+def mouse_release_event(w, e):
+ global selected_handle
+ selected_handle = None
+
+def mouse_motion_event(w, e):
+ global selected_handle
+ if selected_handle:
+ h, (ox, oy) = selected_handle
+ if(e.state & gtk.gdk.BUTTON1_MASK):
+ h.x = e.x - ox
+ h.y = e.y - oy
+ w.queue_draw()
+
+
+win = gtk.Window()
+win.set_default_size(400,400)
+vb = gtk.VBox(False)
+
+da = gtk.DrawingArea()
+templayout = da.create_pango_layout("")
+da.connect("expose_event", display)
+da.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.KEY_PRESS_MASK | gtk.gdk.POINTER_MOTION_MASK)
+da.connect("button-press-event", mouse_event)
+da.connect("button-release-event", mouse_release_event)
+da.connect("motion-notify-event", mouse_motion_event)
+#da.connect("key_press_event", key_event)
+win.add(vb)
+vb.pack_start(da)
+win.connect("destroy", gtk.main_quit)
+
+
+win.show_all()
+
+gtk.main()
+
+print handles
diff --git a/src/3rdparty/2geom/src/python/exact-arc-length-quad-bez.py b/src/3rdparty/2geom/src/python/exact-arc-length-quad-bez.py
new file mode 100644
index 0000000..fd2f4b3
--- /dev/null
+++ b/src/3rdparty/2geom/src/python/exact-arc-length-quad-bez.py
@@ -0,0 +1,16 @@
+import math
+
+def q(x, a, b, c):
+ sa = math.sqrt(a)
+ y = math.sqrt(a*x*x+b*x+c)
+ dp = 2*a*x + b
+ r = dp*y/(4*a)
+ t = abs(dp + 2*y*sa)
+ s = (4*a*c-b*b)/(a*sa*8)
+ return r+s*math.log(t)
+
+a = 1160390
+b = -922658
+c = 249477
+print q(1, a,b,c) - q(0,a,b,c)
+
diff --git a/src/3rdparty/2geom/src/python/test_py2geom.py b/src/3rdparty/2geom/src/python/test_py2geom.py
new file mode 100644
index 0000000..2ad6e66
--- /dev/null
+++ b/src/3rdparty/2geom/src/python/test_py2geom.py
@@ -0,0 +1,41 @@
+#!/usr/bin/python
+
+import py2geom as g
+
+a = g.Point(1,2)
+b = g.Point(31,2)
+print a, b
+
+point_fns_1 = ["L1", "L2", "L2sq", "LInfty", "is_zero", "is_unit_vector",
+ "atan2", "rot90",
+ "unit_vector", "abs"]
+point_fns_2 = ["dot", "angle_between", "distance", "distanceSq", "cross"]
+
+for i in point_fns_1:
+ print "%s:" % i, g.__dict__[i](a)
+for i in point_fns_2:
+ print "%s:" % i, g.__dict__[i](a,b)
+print "a == b", a == b
+print "Lerp:", g.lerp(0.3, a,b)
+
+bo = g.BezOrd(2,3)
+print bo
+print bo.point_at(0.3)
+
+print bo.reverse()
+
+sn = g.sin(g.BezOrd(0.0,8.0),5)
+print sn
+print g.inverse(sn,10)
+print list(sn)
+
+r_sn = g.roots(sn)
+print len(r_sn)
+print list(r_sn)
+
+bo = g.BezOrd(-1,1)
+sb = g.SBasis()
+print sb
+print list(g.roots(sb))
+sb.append(bo)
+print list(g.roots(sb))
diff --git a/src/3rdparty/2geom/src/toys/2dsb2d.cpp b/src/3rdparty/2geom/src/toys/2dsb2d.cpp
new file mode 100644
index 0000000..3effd1f
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/2dsb2d.cpp
@@ -0,0 +1,128 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/transforms.h>
+#include <2geom/pathvector.h>
+#include <2geom/svg-path-parser.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <vector>
+using std::vector;
+using namespace Geom;
+
+unsigned total_pieces_sub;
+unsigned total_pieces_inc;
+
+class Sb2d2: public Toy {
+ Path path_a;
+ D2<SBasis2d> sb2;
+ Piecewise<D2<SBasis> > path_a_pw;
+ PointSetHandle hand;
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ Geom::Point dir(1,-2);
+ for(unsigned dim = 0; dim < 2; dim++) {
+ Geom::Point dir(0,0);
+ dir[dim] = 1;
+ for(unsigned vi = 0; vi < sb2[dim].vs; vi++)
+ for(unsigned ui = 0; ui < sb2[dim].us; ui++)
+ for(unsigned iv = 0; iv < 2; iv++)
+ for(unsigned iu = 0; iu < 2; iu++) {
+ unsigned corner = iu + 2*iv;
+ unsigned i = ui + vi*sb2[dim].us;
+ Geom::Point base((2*(iu+ui)/(2.*ui+1)+1)*width/4.,
+ (2*(iv+vi)/(2.*vi+1)+1)*width/4.);
+ if(vi == 0 && ui == 0) {
+ base = Geom::Point(width/4., width/4.);
+ }
+ double dl = dot((hand.pts[corner+4*i] - base), dir)/dot(dir,dir);
+ sb2[dim][i][corner] = dl/(width/2)*pow(4.0,(double)ui+vi);
+ }
+ }
+ cairo_d2_sb2d(cr, sb2, dir*0.1, width);
+ cairo_set_source_rgba (cr, 0., 0., 0, 0.5);
+ cairo_stroke(cr);
+ for(unsigned i = 0; i < path_a_pw.size(); i++) {
+ D2<SBasis> B = path_a_pw[i];
+ //const int depth = sb2[0].us*sb2[0].vs;
+ //const int surface_hand.pts = 4*depth;
+ //D2<SBasis> B = hand.pts_to_sbasis<3>(hand.pts.begin() + surface_hand.pts);
+ cairo_d2_sb(cr, B);
+ for(unsigned dim = 0; dim < 2; dim++) {
+ std::vector<double> r = roots(B[dim]);
+ for(double i : r)
+ draw_cross(cr, B(i));
+ r = roots(Linear(width/4) - B[dim]);
+ for(double i : r)
+ draw_cross(cr, B(i));
+ }
+ cairo_set_source_rgba (cr, 0., 0.125, 0, 1);
+ cairo_stroke(cr);
+ B *= (4./width);
+ D2<SBasis> tB = compose_each(sb2, B);
+ B = B*(width/2) + Geom::Point(width/4, width/4);
+ tB = tB*(width/2) + Geom::Point(width/4, width/4);
+
+ cairo_d2_sb(cr, tB);
+ }
+
+ //*notify << "bo = " << sb2.index(0,0);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+ void first_time(int argc, char** argv) override {
+ const char *path_a_name="star.svgd";
+ if(argc > 1)
+ path_a_name = argv[1];
+ PathVector paths_a = read_svgd(path_a_name);
+ assert(!paths_a.empty());
+ path_a = paths_a[0];
+ Rect bounds = path_a[0].boundsFast();
+ std::cout << bounds.min() <<std::endl;
+ path_a = path_a * Affine(Translate(-bounds.min()));
+ double extreme = std::max(bounds.width(), bounds.height());
+ path_a = path_a * Scale(40./extreme);
+
+ path_a_pw = path_a.toPwSb();
+ for(unsigned dim = 0; dim < 2; dim++) {
+ sb2[dim].us = 2;
+ sb2[dim].vs = 2;
+ const int depth = sb2[dim].us*sb2[dim].vs;
+ sb2[dim].resize(depth, Linear2d(0));
+ }
+
+ hand.pts.resize(sb2[0].vs*sb2[0].us*4);
+ handles.push_back(&hand);
+
+ }
+ void resize_canvas(Geom::Rect const & s) override {
+ double width = s[0].extent();
+ unsigned ii = 0;
+ for(unsigned vi = 0; vi < sb2[0].vs; vi++)
+ for(unsigned ui = 0; ui < sb2[0].us; ui++)
+ for(unsigned iv = 0; iv < 2; iv++)
+ for(unsigned iu = 0; iu < 2; iu++)
+ hand.pts[ii++] = Geom::Point((2*(iu+ui)/(2.*ui+1)+1)*width/4.,
+ (2*(iv+vi)/(2.*vi+1)+1)*width/4.);
+
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new Sb2d2);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/CMakeLists.txt b/src/3rdparty/2geom/src/toys/CMakeLists.txt
new file mode 100644
index 0000000..c4929b7
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/CMakeLists.txt
@@ -0,0 +1,172 @@
+SET(2GEOM_TOY-FRAMEWORK-2_SRC
+toy-framework-2.cpp
+${2GEOM_INCLUDE_DIR}/toys/toy-framework-2.h
+path-cairo.cpp
+${2GEOM_INCLUDE_DIR}/toys/path-cairo.h
+)
+SET(2GEOM_LPE_TOY_FRAMEWORK_SRC
+${2GEOM_TOY-FRAMEWORK-2_SRC}
+lpe-framework.cpp
+${2GEOM_INCLUDE_DIR}/toys/lpe-framework.h
+)
+
+SET(2GEOM_TOYS-2_SRC
+2dsb2d
+aa
+arc-bez
+arc-length-param
+auto-cross
+boolops-toy
+bound-path
+bounds-test
+box3d
+center-warp
+circle-fitting
+circle-intersect
+circle-line-intersect
+circle-tangent-fitting
+collinear-normal
+conic-3
+conic-4
+conic-5
+conic-6
+conic-section-toy
+convole
+curvature-curve
+curvature-test
+curve-curve-distance
+curve-curve-nearest-time
+curve-intersection-by-bezier-clipping
+curve-intersection-by-implicitization
+cylinder3d
+d2sbasis-fitting
+d2sbasis-fitting-with-np
+draw-toy
+ellipse-area-minimizer
+ellipse-bezier-intersect-toy
+ellipse-fitting
+ellipse-intersect-toy
+ellipse-line-intersect-toy
+elliptiarc-3point-center-fitting
+elliptiarc-curve-fitting
+elliptical-arc-toy
+evolute
+filet-minion
+find-derivative
+gear
+#hatches
+implicit-toy
+ineaa
+inner-product-clip
+intersect-data
+inverse-test
+kinematic_templates
+levelsets-test
+line-toy
+load-svgd
+match-curve
+mesh-grad
+metro
+minsb2d-solver
+#normal-bundle
+offset-toy
+pair-intersect
+paptest
+parametrics
+parser
+path-along-path
+path-effects
+pencil
+pencil-2
+plane3d
+point-curve-nearest-time
+portion-test
+precise-flat
+pw-compose-test
+pw-funcs
+pw-toy
+rdm-area
+rect_01
+rect_02
+rect_03
+rect-toy
+root-finder-comparer
+#rtree-toy
+sanitize
+#sb1d
+sb2d
+sb2d-solver
+sbasisdim
+sbasis-fitting
+sb-math-test
+sb-of-interval
+sb-of-sb
+sb-to-bez
+sb-zeros
+scribble
+self-intersect
+sketch-fitter
+smash-intersector
+squiggles
+sweep
+sweeper-toy
+# these ones have only had a trivial rewrite to toy-2
+#uncross
+winding-test
+worms
+)
+
+SET(2GEOM_LPE_TOYS_SRC
+lpe-test
+)
+
+OPTION(2GEOM_TOYS_LPE
+ "Build Inkscape Live Path Effect (LPE) Toy files"
+ ON)
+IF(2GEOM_TOYS_LPE)
+ # make lib for lpetoy
+ add_library(lpetoy ${LIB_TYPE} ${2GEOM_LPE_TOY_FRAMEWORK_SRC})
+ target_include_directories(lpetoy PUBLIC ${GTK3_INCLUDE_DIRS})
+ target_link_libraries(lpetoy 2Geom::2geom ${GTK3_LIBRARIES})
+ if(NOT WIN32 AND NOT APPLE)
+ target_link_libraries(lpetoy -lrt)
+ endif()
+
+ FOREACH(source ${2GEOM_LPE_TOYS_SRC})
+ add_executable(${source} ${source}.cpp)
+ target_link_libraries(${source} lpetoy 2Geom::2geom)
+ ENDFOREACH(source)
+
+ENDIF(2GEOM_TOYS_LPE)
+
+OPTION(2GEOM_TOYS
+ "Build the projects Toy files"
+ ON)
+IF(2GEOM_TOYS)
+ # make lib for toy
+ ADD_LIBRARY(toy-2 ${LIB_TYPE} ${2GEOM_TOY-FRAMEWORK-2_SRC})
+ target_include_directories(toy-2 PUBLIC ${GTK3_INCLUDE_DIRS})
+ TARGET_LINK_LIBRARIES(toy-2 2Geom::2geom ${GTK3_LIBRARIES})
+ if(NOT WIN32 AND NOT APPLE)
+ target_link_libraries(toy-2 -lrt)
+ endif()
+
+ FOREACH(source ${2GEOM_TOYS-2_SRC})
+ IF(${source} STREQUAL aa)
+ ADD_EXECUTABLE(${source} EXCLUDE_FROM_ALL ${source}.cpp)
+ TARGET_LINK_LIBRARIES(${source} affa)
+ ELSEIF(${source} STREQUAL ineaa)
+ ADD_EXECUTABLE(${source} EXCLUDE_FROM_ALL ${source}.cpp)
+ TARGET_LINK_LIBRARIES(${source} affa)
+ ELSEIF(${source} STREQUAL implicit-toy)
+ ADD_EXECUTABLE(${source} EXCLUDE_FROM_ALL ${source}.cpp)
+ TARGET_LINK_LIBRARIES(${source} affa)
+ ELSEIF(${source} STREQUAL boolops-cgal)
+
+ ELSE(${source} STREQUAL aa)
+ ADD_EXECUTABLE(${source} ${source}.cpp)
+ ENDIF(${source} STREQUAL aa)
+ TARGET_LINK_LIBRARIES(${source} toy-2 2Geom::2geom ${GTK3_LIBRARIES} )
+ ENDFOREACH(source)
+ENDIF(2GEOM_TOYS)
+
diff --git a/src/3rdparty/2geom/src/toys/aa.cpp b/src/3rdparty/2geom/src/toys/aa.cpp
new file mode 100644
index 0000000..8b852a2
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/aa.cpp
@@ -0,0 +1,520 @@
+#include <2geom/convex-hull.h>
+#include <2geom/d2.h>
+#include <2geom/geom.h>
+#include <2geom/numeric/linear_system.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <aa.h>
+#include <complex>
+#include <algorithm>
+#include <optional>
+
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+//Geom::Rect zoom(Geom::Rect r, Geom::Point p, double s) {
+// return p + (r - p)*s;
+//}
+
+typedef std::complex<AAF> CAAF;
+
+struct PtLexCmp{
+ bool operator()(const Point &a, const Point &b) {
+ return (a[0] < b[0]) || ((a[0] == b[0]) and (a[1] < b[1]));
+ }
+};
+
+void draw_line_in_rect(cairo_t*cr, Rect &r, Point n, double c) {
+ std::optional<Geom::LineSegment> ls =
+ rect_line_intersect(r, Line::fromNormalDistance(n, c));
+
+ if(ls) {
+ cairo_move_to(cr, (*ls)[0]);
+ cairo_line_to(cr, (*ls)[1]);
+ cairo_stroke(cr);
+
+ }
+}
+
+OptRect tighten(Rect &r, Point n, Interval lu) {
+ vector<Geom::Point> result;
+ Point resultp;
+ for(int i = 0; i < 4; i++) {
+ Point cnr = r.corner(i);
+ double z = dot(cnr, n);
+ if((z > lu[0]) and (z < lu[1]))
+ result.push_back(cnr);
+ }
+ for(int i = 0; i < 2; i++) {
+ double c = lu[i];
+
+ std::optional<Geom::LineSegment> ls =
+ rect_line_intersect(r, Line::fromNormalDistance(n, c));
+
+ if(ls) {
+ result.push_back((*ls)[0]);
+ result.push_back((*ls)[1]);
+ }
+ }
+ if(result.size() < 2)
+ return OptRect();
+ Rect nr(result[0], result[1]);
+ for(size_t i = 2; i < result.size(); i++) {
+ nr.expandTo(result[i]);
+ }
+ return intersect(nr, r);
+}
+
+AAF ls_sample_based(AAF x, vector<Point> pts) {
+ NL::Matrix m(pts.size(), 2);
+ NL::Vector v(pts.size());
+ NL::LinearSystem ls(m, v);
+
+ m.set_all(0);
+ v.set_all(0);
+ for (unsigned int k = 0; k < pts.size(); ++k)
+ {
+ m(k,0) += pts[k][0];
+ m(k,1) += 1;
+ //std::cout << pts[k] << " ";
+
+ v[k] += pts[k][1];
+ //v[1] += pts[k][1];
+ //v[2] += y2;
+ }
+
+ ls.SV_solve();
+
+ double A = ls.solution()[0];
+ double B = ls.solution()[1];
+ // Ax + B = y
+ Interval bnd(0,0);
+ for (unsigned int k = 0; k < pts.size(); ++k)
+ {
+ bnd.extendTo(A*pts[k][0]+B - pts[k][1]);
+ }
+ //std::cout << A << "," << B << std::endl;
+ return AAF(x, A, B, bnd.extent(),
+ x.special);
+}
+
+AAF md_sample_based(AAF x, vector<Point> pts) {
+ Geom::ConvexHull ch1(pts);
+ Point a, b, c;
+ double dia = ch1.narrowest_diameter(a, b, c);
+ Point db = c-b;
+ double A = db[1]/db[0];
+ Point aa = db*(dot(db, a-b)/dot(db,db))+b;
+ Point mid = (a+aa)/2;
+ double B = mid[1] - A*mid[0];
+ double dB = (a[1] - A*a[0]) - B;
+ // Ax + B = y
+ std::cout << A << "," << B << std::endl;
+ return AAF(x, A, B, dB,
+ x.special);
+}
+
+AAF atan_sample_based(AAF x) {
+ interval ab(x);
+ const double a = ab.min(); // [a,b] is our interval
+ const double b = ab.max();
+
+ const double ea = atan(a);
+ const double eb = atan(b);
+ vector<Point> pts;
+ pts.push_back(Point(a,ea));
+ pts.push_back(Point(b,eb));
+ const double alpha = (eb-ea)/(b-a);
+ double xs = sqrt(1/alpha-1);
+ if((a < xs) and (xs < b))
+ pts.push_back(Point(xs,atan(xs)));
+ xs = -xs;
+ if((a < xs) and (xs < b))
+ pts.push_back(Point(xs,atan(xs)));
+
+ return md_sample_based(x, pts);
+}
+
+AAF log_sample_based(AAF x) {
+ interval ab(x);
+ const double a = ab.min(); // [a,b] is our interval
+ const double b = ab.max();
+ AAF_TYPE type;
+ if(a > 0)
+ type = AAF_TYPE_AFFINE;
+ else if(b < 0) { // no point in continuing
+ type = AAF_TYPE_NAN;
+ return AAF(type);
+ }
+ else if(a <= 0) { // undefined, can we do better?
+ type = (AAF_TYPE)(AAF_TYPE_AFFINE | AAF_TYPE_NAN);
+ return AAF(type);
+ // perhaps we should make a = 0+eps and try to continue?
+ }
+
+ const double ea = log(a);
+ const double eb = log(b);
+ vector<Point> pts;
+ pts.push_back(Point(a,ea));
+ pts.push_back(Point(b,eb));
+ const double alpha = (eb-ea)/(b-a);
+ // dlog(xs) = alpha
+ double xs = 1/(alpha);
+ if((a < xs) and (xs < b))
+ pts.push_back(Point(xs,log(xs)));
+
+ return md_sample_based(x, pts);
+}
+
+AAF exp_sample_based(AAF x) {
+ interval ab(x);
+ const double a = ab.min(); // [a,b] is our interval
+ const double b = ab.max();
+
+ const double ea = exp(a);
+ const double eb = exp(b);
+ vector<Point> pts;
+ pts.push_back(Point(a,ea));
+ pts.push_back(Point(b,eb));
+ const double alpha = (eb-ea)/(b-a);
+ // dexp(xs) = alpha
+ double xs = log(alpha);
+ if((a < xs) and (xs < b))
+ pts.push_back(Point(xs,exp(xs)));
+
+ return md_sample_based(x, pts);
+}
+
+AAF pow_sample_based(AAF x, double p) {
+ interval ab(x);
+ const double a = ab.min(); // [a,b] is our interval
+ const double b = ab.max();
+ AAF_TYPE type;
+ if(a >= 0)
+ type = AAF_TYPE_AFFINE;
+ else if(b < 0) { // no point in continuing
+ type = AAF_TYPE_NAN;
+ return AAF(type);
+ }
+ else if(a <= 0) { // undefined, can we do better?
+ type = (AAF_TYPE)(AAF_TYPE_AFFINE | AAF_TYPE_NAN);
+ return AAF(type);
+ // perhaps we should make a = 0+eps and try to continue?
+ }
+
+ const double ea = pow(a, p);
+ const double eb = pow(b, p);
+ vector<Point> pts;
+ pts.push_back(Point(a,ea));
+ pts.push_back(Point(b,eb));
+ const double alpha = (eb-ea)/(b-a);
+ // d(xs^p) = alpha
+ // p xs^(p-1) = alpha
+ // xs = (alpha/p)^(1-p)
+ double xs = pow(alpha/p, 1./(p-1));
+ if((a < xs) and (xs < b))
+ pts.push_back(Point(xs,pow(xs, p)));
+ xs = -xs;
+ if((a < xs) and (xs < b))
+ pts.push_back(Point(xs,pow(xs, p)));
+
+ return md_sample_based(x, pts);
+}
+
+Point origin;
+double scale=100;
+
+AAF trial_eval(AAF x, AAF y) {
+ x = x-origin[0];
+ y = y-origin[1];
+
+ x = x/scale;
+ y = y/scale;
+
+ return x*x -y*y + -6*x +10*y-16;
+ return -y + log(sqrt(x))/log(x);
+ return y*y - x*(x-1)*(x+1);
+
+ //return x*x - 1;
+ //return y - pow(x,3);
+ //return y - pow_sample_based(x,2.5);
+ //return y - log_sample_based(x);
+ //return y - log(x);
+ //return y - exp_sample_based(x*log(x));
+ //return y - sqrt(sin(x));
+ //return sqrt(y)*x - sqrt(x) - y - 1;
+ //return y-1/x;
+ //return exp(x)-y;
+ //return sin(x)-y;
+ //return exp_sample_based(x)-y;
+ //return atan(x)-y;
+ //return atan_sample_based(x)-y;
+ //return atanh(x)-y;
+ //return x*y;
+ //return 4*x+3*y-1;
+ //return x*x + y*y - 1;
+ //return sin(x*y) + cos(pow(x, 3)) - atan(x);
+ //return pow((x*x + y*y), 2) - (x*x-y*y);
+ return 4*(2*y-4*x)*(2*y+4*x-16)-16*y*y;
+ return pow((x*x + y*y), 2) - (x*x-y*y);
+ //return pow(x,3) - 3*x*x - 3*y*y;
+ return (x*x + y*y-1)*((x-1)*(x-1)+y*y-1);
+ //return x*x-y;
+ //return (x*x*x-y*x)*sin(x) + (x-y*y)*cos(y)-0.5;
+}
+
+AAF xaxis(AAF x, AAF y) {
+ y = y-origin[1];
+ y = y/scale;
+ return y;
+}
+
+AAF xaxis2(AAF x, AAF y) {
+ y = y-origin[1];
+ y = y/scale;
+ return y-4;
+}
+
+AAF yaxis(AAF x, AAF y) {
+ x = x-origin[0];
+ x = x/scale;
+ return x;
+}
+
+class ConvexTest: public Toy {
+public:
+ PointSetHandle test_window;
+ PointSetHandle samples;
+ PointHandle orig_handle;
+ ConvexTest () {
+ toggles.push_back(Toggle("Show trials", false));
+ handles.push_back(&test_window);
+ handles.push_back(&samples);
+ handles.push_back(&orig_handle);
+ orig_handle.pos = Point(300,300);
+ test_window.push_back(Point(100,100));
+ test_window.push_back(Point(200,200));
+ for(int i = 0; i < 0; i++) {
+ samples.push_back(Point(i*100, i*100+25));
+ }
+ }
+ int iters;
+ int splits[4];
+ bool show_splits;
+ std::vector<Toggle> toggles;
+ AAF (*eval)(AAF, AAF);
+ Geom::Rect view;
+ void recursive_implicit(Rect r, cairo_t*cr, double w) {
+ if(show_splits) {
+ cairo_save(cr);
+ cairo_set_line_width(cr, 0.3);
+ /*if(f.is_partial())
+ cairo_set_source_rgba(cr, 1, 0, 1, 0.25);
+ else*/
+ cairo_set_source_rgba(cr, 0, 1, 0, 0.25);
+ cairo_rectangle(cr, r);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ }
+ iters++;
+ AAF x(interval(r.left(), r.right()));
+ AAF y(interval(r.top(), r.bottom()));
+ //assert(x.rad() > 0);
+ //assert(y.rad() > 0);
+ AAF f = (*eval)(x, y);
+ // pivot
+ double a = f.index_coeff(x.get_index(0))/x.index_coeff(x.get_index(0));
+ double b = f.index_coeff(y.get_index(0))/y.index_coeff(y.get_index(0));
+ AAF d = a*x + b*y - f;
+ interval ivl(d);
+ Point n(a,b);
+ OptRect out = tighten(r, n, Interval(ivl.min(), ivl.max()));
+ if(ivl.extent() < 0.5*L2(n)) {
+ draw_line_in_rect(cr, r, n, ivl.middle());
+ return;
+ }
+ if(!f.is_partial() and f.is_indeterminate()) {
+ cairo_save(cr);
+ cairo_set_line_width(cr, 0.3);
+ if(f.is_infinite()) {
+ cairo_set_source_rgb(cr, 1, 0.5, 0.5);
+ } else if(f.is_nan()) {
+ cairo_set_source_rgb(cr, 1, 1, 0);
+ } else {
+ cairo_set_source_rgb(cr, 1, 0, 0);
+ }
+ cairo_rectangle(cr, r);
+ if(show_splits) {
+ cairo_stroke(cr);
+ } else {
+ cairo_fill(cr);
+ }
+ cairo_restore(cr);
+ return;
+ }
+
+ if((r.width() > w) or (r.height()>w)) {
+ if(f.straddles_zero()) {
+ // Three possibilities:
+ // 1) the trim operation buys us enough that we should just iterate
+ Point c = r.midpoint();
+ Rect oldr = r;
+ if(out)
+ r = *out;
+ if(1 && out && (r.area() < oldr.area()*0.25)) {
+ splits[0] ++;
+ recursive_implicit(r, cr, w);
+ // 2) one dimension is significantly smaller
+ } else if(1 && (r[1].extent() < oldr[1].extent()*0.5)) {
+ splits[1]++;
+ recursive_implicit(Rect(Interval(r.left(), r.right()),
+ Interval(r.top(), c[1])), cr,w);
+ recursive_implicit(Rect(Interval(r.left(), r.right()),
+ Interval(c[1], r.bottom())), cr,w);
+ } else if(1 && (r[0].extent() < oldr[0].extent()*0.5)) {
+ splits[2]++;
+ recursive_implicit(Rect(Interval(r.left(), c[0]),
+ Interval(r.top(), r.bottom())), cr,w);
+ recursive_implicit(Rect(Interval(c[0], r.right()),
+ Interval(r.top(), r.bottom())), cr,w);
+ // 3) to ensure progress we must do a four way split
+ } else {
+ splits[3]++;
+ recursive_implicit(Rect(Interval(r.left(), c[0]),
+ Interval(r.top(), c[1])), cr,w);
+ recursive_implicit(Rect(Interval(c[0], r.right()),
+ Interval(r.top(), c[1])), cr,w);
+ recursive_implicit(Rect(Interval(r.left(), c[0]),
+ Interval(c[1], r.bottom())), cr,w);
+ recursive_implicit(Rect(Interval(c[0], r.right()),
+ Interval(c[1], r.bottom())), cr,w);
+ }
+ }
+ } else {
+ }
+ }
+
+ void key_hit(GdkEventKey *e) override {
+ if(e->keyval == 'w') toggles[0].toggle(); else
+ if(e->keyval == 'a') toggles[1].toggle(); else
+ if(e->keyval == 'q') toggles[2].toggle(); else
+ if(e->keyval == 's') toggles[3].toggle();
+ redraw();
+ }
+ void mouse_pressed(GdkEventButton* e) override {
+ toggle_events(toggles, e);
+ Toy::mouse_pressed(e);
+ }
+ void scroll(GdkEventScroll* e) override {
+ if (e->direction == GDK_SCROLL_UP) {
+ scale /= 1.2;
+ } else if (e->direction == GDK_SCROLL_DOWN) {
+ scale *= 1.2;
+ }
+ redraw();
+ }
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_source_rgba (cr, 0., 0., 0, 1);
+ cairo_set_line_width (cr, 1);
+ origin = orig_handle.pos;
+ if(1) {
+ cairo_save(cr);
+ cairo_set_line_width(cr, 0.3);
+ cairo_set_source_rgb(cr, 0.5, 0.5, 1);
+ eval = xaxis;
+ recursive_implicit(Rect(Interval(0,width), Interval(0, height)), cr, 3);
+ eval = xaxis2;
+ recursive_implicit(Rect(Interval(0,width), Interval(0, height)), cr, 3);
+ eval = yaxis;
+ recursive_implicit(Rect(Interval(0,width), Interval(0, height)), cr, 3);
+ cairo_restore(cr);
+ iters = 0;
+ for(int & split : splits)
+ split = 0;
+ show_splits = toggles[0].on;
+ eval = trial_eval;
+ recursive_implicit(Rect(Interval(0,width), Interval(0, height)), cr, 3);
+ for(int split : splits)
+ *notify << split << " + ";
+ *notify << " = " << iters;
+ }
+ if(1) {
+ Rect r(test_window.pts[0], test_window.pts[1]);
+ AAF x(interval(r.left(), r.right()));
+ AAF y(interval(r.top(), r.bottom()));
+ //AAF f = md_sample_based(x, samples.pts)-y;
+ if(0) {
+ x = x-500;
+ y = y-300;
+ x = x/200;
+ y = y/200;
+ AAF f = atan_sample_based(x)-y;
+ cout << f << endl;
+ }
+ AAF f = (*eval)(x, y);
+ double a = f.index_coeff(x.get_index(0))/x.index_coeff(x.get_index(0));
+ double b = f.index_coeff(y.get_index(0))/y.index_coeff(y.get_index(0));
+ AAF d = a*x + b*y - f;
+ //cout << d << endl;
+ interval ivl(d);
+ Point n(a,b);
+ OptRect out = tighten(r, n, Interval(ivl.min(), ivl.max()));
+ if(out)
+ cairo_rectangle(cr, *out);
+ cairo_rectangle(cr, r);
+ draw_line_in_rect(cr, r, n, ivl.min());
+ cairo_stroke(cr);
+ cairo_save(cr);
+ cairo_set_line_width(cr, 0.3);
+ cairo_set_source_rgb(cr, 0.5, 0.5, 0);
+ draw_line_in_rect(cr, r, n, ivl.middle());
+ cairo_restore(cr);
+ draw_line_in_rect(cr, r, n, ivl.max());
+ cairo_stroke(cr);
+ }
+ if(0) {
+ Geom::ConvexHull gm(samples.pts);
+ cairo_convex_hull(cr, gm);
+ cairo_stroke(cr);
+ Point a, b, c;
+ double dia = gm.narrowest_diameter(a, b, c);
+ cairo_save(cr);
+ cairo_set_line_width(cr, 2);
+ cairo_set_source_rgba(cr, 1, 0, 0, 0.5);
+ cairo_move_to(cr, b);
+ cairo_line_to(cr, c);
+ cairo_move_to(cr, a);
+ cairo_line_to(cr, (c-b)*dot(a-b, c-b)/dot(c-b,c-b)+b);
+ cairo_stroke(cr);
+ //std::cout << a << ", " << b << ", " << c << ": " << dia << "\n";
+ cairo_restore(cr);
+ }
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ Point d(25,25);
+ toggles[0].bounds = Rect(Point(10, height-80)+d,
+ Point(10+120, height-80+d[1])+d);
+
+ draw_toggles(cr, toggles);
+ }
+
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new ConvexTest());
+
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/arc-bez.cpp b/src/3rdparty/2geom/src/toys/arc-bez.cpp
new file mode 100644
index 0000000..4e9dace
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/arc-bez.cpp
@@ -0,0 +1,129 @@
+#include <2geom/d2.h>
+
+#include <2geom/sbasis.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-math.h>
+#include <2geom/sbasis-geometric.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <vector>
+using std::vector;
+using namespace Geom;
+
+Piecewise<SBasis>
+arcLengthSb2(Piecewise<D2<SBasis> > const &M, double /*tol*/){
+ Piecewise<D2<SBasis> > dM = derivative(M);
+ Piecewise<SBasis> length = integral(dot(dM, unitVector(dM)));
+ length-=length.segs.front().at0();
+ return length;
+}
+
+
+
+class ArcBez: public Toy {
+ PointSetHandle bez_handle;
+public:
+ ArcBez() {
+ for(int i = 0; i < 6; i++)
+ bez_handle.push_back(uniform()*400, uniform()*400);
+ handles.push_back(&bez_handle);
+ }
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timing_stream) override {
+ cairo_set_source_rgba (cr, 0., 0., 0, 1);
+ cairo_set_line_width (cr, 1);
+
+ D2<SBasis> B = bez_handle.asBezier();
+ cairo_d2_sb(cr, B);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba (cr, 0.25, 0.5, 0, 0.8);
+
+ double tol = 0.01;
+ bool time_operations = true;
+ if(time_operations) {
+ std::string units_string("us");
+ Timer tm;
+ tm.ask_for_timeslice();
+ tm.start();
+ Piecewise<SBasis> als = arcLengthSb(B, tol);
+ Timer::Time als_time = tm.lap();
+ *timing_stream << "arcLengthSb based "
+ << ", time = " << als_time
+ << units_string << std::endl;
+
+ tm.start();
+ Piecewise<SBasis> als2 = arcLengthSb2(Piecewise<D2<SBasis> >(B), 0.01);
+ Timer::Time als2_time = tm.lap();
+
+ *timing_stream << "arcLengthSb2 based "
+ << ", time = " << als2_time
+ << units_string << std::endl;
+ double abs_error = 0;
+ double integrating_arc_length = 0;
+ tm.start();
+ length_integrating(B, integrating_arc_length, abs_error, 1e-10);
+ Timer::Time li_time = tm.lap();
+
+ *timing_stream << "gsl integrating "
+ << ", time = " << li_time
+ << units_string << std::endl;
+ }
+ Piecewise<SBasis> als = arcLengthSb(B, tol);
+ Piecewise<SBasis> als2 = arcLengthSb2(Piecewise<D2<SBasis> >(B), 0.01);
+
+ cairo_d2_pw_sb(cr, D2<Piecewise<SBasis> >(Piecewise<SBasis>(SBasis(Linear(0, width))) , Piecewise<SBasis>(Linear(height-5)) - Piecewise<SBasis>(als)) );
+
+ double abs_error = 0;
+ double integrating_arc_length = 0;
+ length_integrating(B, integrating_arc_length, abs_error, 1e-10);
+ *notify << "arc length = " << integrating_arc_length << "; abs error = " << abs_error << std::endl;
+ double als_arc_length = als.segs.back().at1();
+ *notify << "arc length = " << als_arc_length << "; error = " << als_arc_length - integrating_arc_length << std::endl;
+ double als_arc_length2 = als2.segs.back().at1();
+ *notify << "arc length2 = " << als_arc_length2 << "; error = " << als_arc_length2 - integrating_arc_length << std::endl;
+
+ {
+ double err = fabs(als_arc_length - integrating_arc_length);
+ double scale = 10./err;
+ Piecewise<D2<SBasis> > dM = derivative(Piecewise<D2<SBasis> >(B));
+ Piecewise<SBasis> ddM = dot(dM,dM);
+ Piecewise<SBasis> dMlength = sqrt(ddM,tol,3);
+ double plot_width = (width - 200);
+
+ Point org(100,height - 200);
+ cairo_move_to(cr, org);
+ for(double t = 0; t < 1; t += 0.01) {
+ cairo_line_to(cr, org + Point(t*plot_width, scale*(sqrt(ddM.valueAt(t)) - dMlength.valueAt(t))));
+ }
+ cairo_move_to(cr, org);
+ cairo_line_to(cr, org+Point(plot_width, 0));
+ cairo_stroke(cr);
+
+ draw_number(cr, org, scale);
+
+ }
+
+
+ Toy::draw(cr, notify, width, height, save,timing_stream);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new ArcBez());
+
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/arc-length-param.cpp b/src/3rdparty/2geom/src/toys/arc-length-param.cpp
new file mode 100644
index 0000000..2c7f3c9
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/arc-length-param.cpp
@@ -0,0 +1,101 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-geometric.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <vector>
+using std::vector;
+using namespace Geom;
+
+static void dot_plot(cairo_t *cr, Piecewise<D2<SBasis> > const &M, double space=10){
+ //double dt=(M[0].cuts.back()-M[0].cuts.front())/space;
+ Piecewise<D2<SBasis> > Mperp = rot90(derivative(M)) * 2;
+ for( double t = M.cuts.front(); t < M.cuts.back(); t += space) {
+ Point pos = M(t), perp = Mperp(t);
+ draw_line_seg(cr, pos + perp, pos - perp);
+ }
+ cairo_pw_d2_sb(cr, M);
+ cairo_stroke(cr);
+}
+
+#define SIZE 4
+
+class LengthTester: public Toy {
+public:
+ PointSetHandle b1_handle;
+ PointSetHandle b2_handle;
+ void draw(cairo_t *cr,
+ std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override {
+
+ D2<SBasis> B1 = b1_handle.asBezier();
+ D2<SBasis> B2 = b2_handle.asBezier();
+ Piecewise<D2<SBasis> >B;
+ B.concat(Piecewise<D2<SBasis> >(B1));
+ B.concat(Piecewise<D2<SBasis> >(B2));
+
+// testing fuse_nearby_ends
+ std::vector< Piecewise<D2<SBasis> > > pieces;
+ pieces = fuse_nearby_ends(split_at_discontinuities(B),9);
+ Piecewise<D2<SBasis> > C;
+ for (auto & piece : pieces){
+ C.concat(piece);
+ }
+// testing fuse_nearby_ends
+
+ cairo_set_line_width (cr, .5);
+ cairo_set_source_rgba (cr, 0., 0.5, 0., 1);
+ //cairo_d2_sb(cr, B1);
+ cairo_pw_d2_sb(cr, C);
+ //cairo_pw_d2_sb(cr, B);
+ cairo_stroke(cr);
+
+ Timer tm;
+ tm.ask_for_timeslice();
+ tm.start();
+
+ Piecewise<D2<SBasis> > uniform_B = arc_length_parametrization(B);
+ Timer::Time als_time = tm.lap();
+ *timer_stream << "arc_length_parametrization, time = " << als_time << std::endl;
+
+ cairo_set_source_rgba (cr, 0., 0., 0.9, 1);
+ dot_plot(cr,uniform_B);
+ cairo_stroke(cr);
+ *notify << "pieces = " << uniform_B.size() << ";\n";
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+public:
+ LengthTester(){
+ for(int i = 0; i < SIZE; i++) {
+ b1_handle.push_back(150+uniform()*300,150+uniform()*300);
+ b2_handle.push_back(150+uniform()*300,150+uniform()*300);
+ }
+ b1_handle.pts[0] = Geom::Point(150,150);
+ b1_handle.pts[1] = Geom::Point(150,150);
+ b1_handle.pts[2] = Geom::Point(150,450);
+ b1_handle.pts[3] = Geom::Point(450,150);
+ handles.push_back(&b1_handle);
+ handles.push_back(&b2_handle);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new LengthTester);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+//vim:filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99:
diff --git a/src/3rdparty/2geom/src/toys/auto-cross.cpp b/src/3rdparty/2geom/src/toys/auto-cross.cpp
new file mode 100644
index 0000000..00b5b25
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/auto-cross.cpp
@@ -0,0 +1,321 @@
+/* @brief
+ * A toy for playing around with Path::intersectSelf().
+ *
+ * Authors:
+ * Rafał Siejakowski <rs@rs-math.net>
+ *
+ * Copyright 2022 the Authors.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <toys/toy-framework-2.h>
+#include <2geom/path.h>
+#include <2geom/elliptical-arc.h>
+#include <2geom/svg-path-parser.h>
+
+using namespace Geom;
+using Color = uint32_t;
+
+Color const RED = 0x80000000;
+Color const GREEN = 0x00800000;
+Color const BROWN = 0x90500000;
+Color const BLUE = 0x0000ff00;
+Color const BLACK = 0x00000000;
+
+static void set_cairo_rgb(cairo_t *c, Color rgb)
+{
+ cairo_set_source_rgba(c, (double)((rgb & 0xFF000000) >> 24) / 255.0,
+ (double)((rgb & 0x00FF0000) >> 16) / 255.0,
+ (double)((rgb & 0x0000FF00) >> 8) / 255.0,
+ 1.0);
+}
+
+static void write_text(cairo_t *c, const char *text, Point const &position, Color color)
+{
+ cairo_move_to(c, position);
+ cairo_set_font_size(c, 12);
+ set_cairo_rgb(c, color);
+ cairo_show_text(c, text);
+}
+
+static std::string format_point(Point const &pt)
+{
+ std::ostringstream ss;
+ ss.precision(4);
+ ss << pt;
+ return ss.str();
+}
+
+static EllipticalArc random_arc(Point from, Point to)
+{
+ double const dist = distance(from, to);
+ auto angle = atan2(to - from);
+ bool sweep = std::abs(angle) > M_PI_2;
+ angle *= 2;
+ angle = std::fmod(angle, 2.0 * M_PI);
+ return EllipticalArc(from, Point(0.5 * dist, 2.0 * dist), angle, false, sweep, to);
+}
+
+class Item
+{
+private:
+ Path _path;
+ Color _color;
+ std::string _d;
+
+public:
+ Item(Color color)
+ : _color{color}
+ {}
+
+ void setPath(Path &&new_path)
+ {
+ _path = std::forward<Path>(new_path);
+ std::ostringstream oss;
+ oss << _path;
+ _d = oss.str();
+ }
+
+ void draw(cairo_t *cr) const
+ {
+ cairo_set_line_width(cr, 2);
+ set_cairo_rgb(cr, _color);
+ cairo_path(cr, _path);
+ cairo_stroke(cr);
+ _drawBezierTangents(cr);
+ _drawSelfIntersections(cr);
+ }
+
+ void write(cairo_t *cr, Point const &pos) const
+ {
+ write_text(cr, _d.c_str(), pos, _color);
+ }
+
+ std::string const& getSVGD() const { return _d; }
+
+private:
+ void _drawBezierTangents(cairo_t *c) const
+ {
+ cairo_set_line_width(c, 1);
+ set_cairo_rgb(c, 0x0000b000);
+ // Draw tangents for Beziers:
+ for (auto const &curve : _path) {
+ if (auto const *bezier = dynamic_cast<BezierCurve const *>(&curve)) {
+ if (bezier->order() > 1) {
+ auto points = bezier->controlPoints();
+ cairo_move_to(c, points[0]);
+ cairo_line_to(c, points[1]);
+ cairo_stroke(c);
+ cairo_move_to(c, points.back());
+ cairo_line_to(c, points[points.size() - 2]);
+ cairo_stroke(c);
+ }
+ }
+ }
+ }
+
+ void _drawSelfIntersections(cairo_t *cr) const
+ {
+ set_cairo_rgb(cr, BLACK);
+ for (auto const &xing : _path.intersectSelf()) {
+ draw_cross(cr, xing.point());
+ auto const coords = format_point(xing.point());
+ write_text(cr, coords.c_str(), xing.point() + Point(8, -8), BLACK);
+ }
+ }
+};
+
+class AutoCross : public Toy
+{
+public:
+ AutoCross()
+ : items{Item(RED), Item(GREEN), Item(BROWN)}
+ {
+ bezier_handles.pts = { {200, 400}, {100, 300}, {300, 400}, {300, 300}, {450, 300}, {500, 500}, {400, 400} };
+ elliptical_handles.pts = { {500, 200}, {700, 400}, {600, 500} };
+ mixed_handles.pts = { {100, 600}, {120, 690}, {300, 650}, {330, 600}, {500, 800} };
+ handles.push_back(&bezier_handles);
+ handles.push_back(&elliptical_handles);
+ handles.push_back(&mixed_handles);
+ }
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save,
+ std::ostringstream *timer_stream) override
+ {
+ if (crashed) {
+ draw_error(cr, width, height);
+ } else {
+ try {
+ draw_impl(cr, width, height);
+ } catch (Exception &e) {
+ error = e.what();
+ handles.clear();
+ crashed = true;
+ }
+ }
+ Toy::draw(cr, notify, width, height, save, timer_stream);
+ }
+
+ void key_hit(GdkEventKey *ev) override
+ {
+ if (ev->keyval == GDK_KEY_space) {
+ print_path_d();
+ } else if ((ev->keyval == GDK_KEY_V || ev->keyval == GDK_KEY_v) && (ev->state & GDK_CONTROL_MASK)) {
+ paste_d();
+ }
+
+ }
+
+private:
+ std::string error;
+ std::vector<Item> items;
+ PointSetHandle bezier_handles, elliptical_handles, mixed_handles;
+ bool crashed = false;
+
+ void paste_d()
+ {
+ auto *clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
+ auto *text = gtk_clipboard_wait_for_text(clipboard);
+ if (!text) {
+ return;
+ }
+ PathVector pv;
+ try {
+ pv = parse_svg_path(text);
+ } catch (SVGPathParseError &error) {
+ std::cerr << "Error pasting path d: " << error.what() << std::endl;
+ return;
+ }
+ if (pv.empty()) {
+ return;
+ }
+ Item paste_item{RED}; // TODO: cycle through a color palette.
+ paste_item.setPath(std::move(pv[0]));
+ items.push_back(paste_item);
+ redraw();
+ }
+
+ void print_path_d()
+ {
+ std::cout << "Path snapshots:\n";
+ for (auto it = items.rbegin(); it != items.rend(); ++it) {
+ std::cout << it->getSVGD() << '\n';
+ }
+ }
+
+ void refresh_geometry()
+ {
+ // Construct the 2-segment Bézier path
+ auto const &cp = bezier_handles.pts;
+ Path bezier;
+ bezier.append(BezierCurveN<3>(cp[0].round(), cp[1].round(), cp[2].round(), cp[3].round()));
+ bezier.append(BezierCurveN<3>(cp[3].round(), cp[4].round(), cp[5].round(), cp[6].round()));
+ items[0].setPath(std::move(bezier));
+
+ // Construct the elliptical arcs
+ auto const &ae = elliptical_handles.pts;
+ Path elliptical;
+ elliptical.append(random_arc(ae[0], ae[1]));
+ elliptical.append(random_arc(ae[1], ae[2]));
+ items[1].setPath(std::move(elliptical));
+
+ // Construct a mixed path
+ auto const &mh = mixed_handles.pts;
+ Path mixed;
+ mixed.append(BezierCurveN<3>(mh[0], mh[1], mh[2], mh[3]));
+ mixed.append(random_arc(mh[3], mh[4]));
+ mixed.close();
+ items[2].setPath(std::move(mixed));
+ }
+
+ void draw_impl(cairo_t *cr, int width, int height)
+ {
+ refresh_geometry();
+ write_title(cr);
+
+ auto text_pos = Point(20, height - 20);
+ for (auto const &item : items) {
+ item.draw(cr);
+ item.write(cr, text_pos);
+ text_pos -= Point(0, 20);
+ }
+ }
+
+ void write_title(cairo_t *c)
+ {
+ cairo_move_to(c, 10, 40);
+ cairo_set_font_size(c, 30);
+ set_cairo_rgb(c, 0x0);
+ cairo_show_text(c, "Self-intersection of paths in lib2geom!");
+ cairo_set_font_size(c, 14);
+ cairo_move_to(c, 10, 60);
+ cairo_show_text(c, "[Space]: Print SVG 'd' attributes to stdout");
+ cairo_move_to(c, 10, 80);
+ cairo_show_text(c, "[Ctrl-V]: Paste a 'd' attribute from clipboard");
+ }
+
+ void draw_error(cairo_t *cr, int width, int height)
+ {
+ auto center = Point(0.5 * (double)width, 0.5 * (double)height);
+ cairo_move_to(cr, center + Point(-90, -100));
+ cairo_line_to(cr, center + Point(100, 90));
+ cairo_line_to(cr, center + Point(90, 100));
+ cairo_line_to(cr, center + Point(-100, -90));
+ cairo_close_path(cr);
+ cairo_set_source_rgb(cr, 1, 0, 0);
+ cairo_fill(cr);
+
+ cairo_move_to(cr, center + Point(90, -100));
+ cairo_line_to(cr, center + Point(100, -90));
+ cairo_line_to(cr, center + Point(-90, 100));
+ cairo_line_to(cr, center + Point(-100, 90));
+ cairo_close_path(cr);
+ cairo_set_source_rgb(cr, 1, 0, 0);
+ cairo_fill(cr);
+
+ cairo_move_to(cr, center + Point(-90, 120));
+ cairo_show_text(cr, "Sorry, your toy has just broken :-/");
+ cairo_move_to(cr, Point(10, center[Y] + 150));
+ cairo_show_text(cr, error.c_str());
+ }
+};
+
+int main(int argc, char **argv)
+{
+ auto toy = AutoCross();
+ init(argc, argv, &toy, 800, 800);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+ */
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/toys/boolops-toy.cpp b/src/3rdparty/2geom/src/toys/boolops-toy.cpp
new file mode 100644
index 0000000..389fdc3
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/boolops-toy.cpp
@@ -0,0 +1,242 @@
+#include <2geom/d2.h>
+#include <2geom/intersection-graph.h>
+#include <2geom/path.h>
+#include <2geom/sbasis.h>
+#include <2geom/svg-path-parser.h>
+#include <2geom/transforms.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <algorithm>
+#include <cstdlib>
+
+using namespace Geom;
+
+class BoolOps : public Toy {
+ PathVector as, bs;
+ Line ah, bh;
+ PointHandle path_handles[4];
+ std::vector<Toggle> togs;
+ bool path_handles_inited;
+
+public:
+ BoolOps()
+ : path_handles_inited(false)
+ {}
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ if (!path_handles_inited) {
+ Rect vp(Point(10,10), Point(width-10, height-10));
+ setup_path_handles(vp);
+ }
+
+ Line aht(path_handles[0].pos, path_handles[1].pos);
+ Line bht(path_handles[2].pos, path_handles[3].pos);
+
+ PathVector ast = as * ah.transformTo(aht);
+ PathVector bst = bs * bh.transformTo(bht);
+
+ Timer tm;
+ tm.start();
+
+ PathIntersectionGraph pig(ast, bst);
+ std::vector<Point> dix, ix, wpoints;
+ ix = pig.intersectionPoints();
+ dix = pig.intersectionPoints(true);
+ wpoints = pig.windingPoints();
+ PathVector result, f_in, f_out;
+
+ if (pig.valid()) {
+ if (togs[0].on && !togs[1].on && !togs[2].on) {
+ result = pig.getAminusB();
+ }
+ if (!togs[0].on && togs[1].on && !togs[2].on) {
+ result = pig.getIntersection();
+ }
+ if (!togs[0].on && !togs[1].on && togs[2].on) {
+ result = pig.getBminusA();
+ }
+ if (togs[0].on && togs[1].on && !togs[2].on) {
+ result = ast;
+ }
+ if (togs[0].on && !togs[1].on && togs[2].on) {
+ result = pig.getXOR();
+ }
+ if (!togs[0].on && togs[1].on && togs[2].on) {
+ result = bst;
+ }
+ if (togs[0].on && togs[1].on && togs[2].on) {
+ result = pig.getUnion();
+ }
+ }
+
+ if (togs[5].on || togs[6].on) {
+ pig.fragments(f_in, f_out);
+ }
+ Timer::Time boolop_time = tm.lap();
+
+ cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
+ cairo_set_line_join(cr, CAIRO_LINE_JOIN_BEVEL);
+ cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
+
+ cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
+ cairo_path(cr, result);
+ cairo_fill(cr);
+
+ cairo_set_line_width(cr, 1);
+ cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
+ cairo_path(cr, ast);
+
+ cairo_stroke(cr);
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ cairo_path(cr, bst);
+ cairo_stroke(cr);
+
+ if (togs[5].on) {
+ cairo_set_source_rgb(cr, 1, 0, 0);
+ cairo_path(cr, f_in);
+ cairo_stroke(cr);
+ }
+ if (togs[6].on) {
+ cairo_set_source_rgb(cr, 0, 0, 1);
+ cairo_path(cr, f_out);
+ cairo_stroke(cr);
+ }
+
+ //cairo_set_line_width(cr, 1);
+
+ if (togs[7].on) {
+ cairo_set_source_rgb(cr, 0, 1, 1);
+ for (auto & wpoint : wpoints) {
+ draw_handle(cr, wpoint);
+ }
+ cairo_stroke(cr);
+ }
+
+ if (togs[3].on) {
+ cairo_set_source_rgb(cr, 0, 1, 0);
+ for (auto & i : ix) {
+ draw_handle(cr, i);
+ }
+ cairo_stroke(cr);
+ }
+
+ if (togs[4].on) {
+ cairo_set_source_rgb(cr, 1, 0, 0);
+ for (auto & i : dix) {
+ draw_handle(cr, i);
+ }
+ cairo_stroke(cr);
+ }
+
+
+ double x = width - 90, y = height - 40, y2 = height - 80;
+ Point p(x, y), p2(x, y2), dpoint(25,25), xo(25,0);
+ togs[0].bounds = Rect(p, p + dpoint);
+ togs[1].bounds = Rect(p + xo, p + xo + dpoint);
+ togs[2].bounds = Rect(p + 2*xo, p + 2*xo + dpoint);
+
+ togs[3].bounds = Rect(p2 - 2*xo, p2 - 2*xo + dpoint);
+ togs[4].bounds = Rect(p2 - xo, p2 - xo + dpoint);
+ togs[5].bounds = Rect(p2, p2 + dpoint);
+ togs[6].bounds = Rect(p2 + xo, p2 + xo + dpoint);
+ togs[7].bounds = Rect(p2 + 2*xo, p2 + 2*xo + dpoint);
+ draw_toggles(cr, togs);
+
+ *notify << ix.size() << " intersections";
+ if (dix.size() != 0) {
+ *notify << " + " << dix.size() << " defective";
+ }
+ if (pig.valid()) {
+ *notify << "\nboolop time: " << boolop_time << std::endl;
+ } else {
+ *notify << "\nboolop failed, time: " << boolop_time << std::endl;
+ }
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ void mouse_pressed(GdkEventButton* e) override {
+ toggle_events(togs, e);
+ Toy::mouse_pressed(e);
+ }
+
+ void first_time(int argc, char** argv) override {
+ const char *path_a_name="svgd/winding.svgd";
+ const char *path_b_name="svgd/star.svgd";
+ if(argc > 1)
+ path_a_name = argv[1];
+ if(argc > 2)
+ path_b_name = argv[2];
+
+ as = read_svgd(path_a_name);
+ bs = read_svgd(path_b_name);
+
+ OptRect abox = as.boundsExact();
+ OptRect bbox = bs.boundsExact();
+
+ if (!abox) {
+ std::clog << "Error: path A is empty" << std::endl;
+ }
+ if (!bbox) {
+ std::clog << "Error: path B is empty" << std::endl;
+ }
+ if (!abox || !bbox) {
+ std::exit(1);
+ }
+
+ std::vector<Point> anodes = as.nodes();
+ std::vector<Point> bnodes = bs.nodes();
+
+ typedef std::vector<Point>::iterator Iter;
+ std::pair<Iter, Iter> apts =
+ std::minmax_element(anodes.begin(), anodes.end(), Point::LexLess<Y>());
+ std::pair<Iter, Iter> bpts =
+ std::minmax_element(bnodes.begin(), bnodes.end(), Point::LexLess<Y>());
+
+ ah = Line(*apts.first, *apts.second);
+ bh = Line(*bpts.first, *bpts.second);
+
+ togs.emplace_back("R", true);
+ togs.emplace_back("&", false);
+ togs.emplace_back("B", false);
+
+ togs.emplace_back("X", true);
+ togs.emplace_back("D", true);
+ togs.emplace_back("I", false);
+ togs.emplace_back("O", false);
+ togs.emplace_back("W", false);
+ }
+
+ void setup_path_handles(Rect const &viewport) {
+ Line aht = ah * as.boundsExact()->transformTo(viewport, Aspect(ALIGN_XMID_YMID));
+ Line bht = bh * bs.boundsExact()->transformTo(viewport, Aspect(ALIGN_XMID_YMID));
+
+ path_handles[0] = PointHandle(aht.initialPoint());
+ path_handles[1] = PointHandle(aht.finalPoint());
+ path_handles[2] = PointHandle(bht.initialPoint());
+ path_handles[3] = PointHandle(bht.finalPoint());
+
+ for (auto & path_handle : path_handles) {
+ handles.push_back(&path_handle);
+ }
+ path_handles_inited = true;
+ }
+ //virtual bool should_draw_numbers() {return false;}
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new BoolOps());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/bound-path.cpp b/src/3rdparty/2geom/src/toys/bound-path.cpp
new file mode 100644
index 0000000..39ce2a1
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/bound-path.cpp
@@ -0,0 +1,289 @@
+/*
+ * Bounds Path and PathVector
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/path.h>
+#include <2geom/pathvector.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+using namespace Geom;
+
+std::string option_formatter(double x)
+{
+ if (x == 0.0)
+ return std::string("CURVE");
+ if (x == 1.0)
+ return std::string("PATH");
+ if (x == 2.0)
+ return std::string("PATHVECTOR");
+
+ return std::string("");
+}
+
+class BoundsPath : public Toy
+{
+ enum { CURVE = 0, PATH, PATHVECTOR };
+ enum { FAST = 0, EXACT = 1 };
+
+ private:
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ cairo_set_line_width (cr, 0.3);
+ m_selection_kind = (unsigned int) (sliders[0].value());
+
+ for (unsigned int i = 0; i < m_pathvector_coll.size(); ++i)
+ {
+ cairo_set_source_rgba(cr, 0.0, 0.4*(i+1), 0.8/(i+1), 1.0);
+ for (unsigned int j = 0; j < m_pathvector_coll[i].size(); ++j)
+ {
+ m_pathvector_coll[i][j].clear();
+ for (unsigned int k = 0; k < m_curves_per_path; ++k)
+ {
+ PointSetHandle psh;
+ psh.pts.resize(m_handles_per_curve);
+ for (unsigned int h = 0; h < m_handles_per_curve; ++h)
+ {
+ unsigned int kk = k * (m_handles_per_curve-1) + h;
+ psh.pts[h] = m_pathvector_coll_handles[i][j].pts[kk];
+ }
+ m_pathvector_coll[i][j].append(psh.asBezier());
+ }
+ cairo_path(cr, m_pathvector_coll[i][j]);
+ }
+ cairo_stroke(cr);
+ }
+
+
+ Rect bound;
+ if ( (m_selection_kind == CURVE) && (m_selected_curve != -1) )
+ {
+ const Curve & curve = m_pathvector_coll[m_selected_pathvector][m_selected_path][m_selected_curve];
+ bound = toggles[0].on ? curve.boundsExact()
+ : curve.boundsFast();
+ }
+ else if ( (m_selection_kind == PATH) && (m_selected_path != -1) )
+ {
+ const Path & path = m_pathvector_coll[m_selected_pathvector][m_selected_path];
+ bound = toggles[0].on ? *path.boundsExact()
+ : *path.boundsFast();
+ }
+ else if ( (m_selection_kind == PATHVECTOR) && (m_selected_pathvector != -1) )
+ {
+ const PathVector & pathvector = m_pathvector_coll[m_selected_pathvector];
+ bound = toggles[0].on ? *bounds_exact(pathvector)
+ : *bounds_fast(pathvector);
+ }
+
+ cairo_set_source_rgba(cr, 0.5, 0.0, 0.0, 1.0);
+ cairo_set_line_width (cr, 0.4);
+ cairo_rectangle(cr, bound.left(), bound.top(), bound.width(), bound.height());
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+
+ void mouse_pressed(GdkEventButton* e) override
+ {
+ Point pos(e->x, e->y);
+ double d, t;
+ double dist = 1e10;
+ Rect bound;
+ m_selected_pathvector = -1;
+ m_selected_path = -1;
+ m_selected_curve = -1;
+ if (m_selection_kind == CURVE)
+ {
+ for (unsigned int i = 0; i < m_pathvector_coll.size(); ++i)
+ {
+ for (unsigned int j = 0; j < m_pathvector_coll[i].size(); ++j)
+ {
+ for ( unsigned int k = 0; k < m_pathvector_coll[i][j].size(); ++k)
+ {
+ const Curve & curve = m_pathvector_coll[i][j][k];
+ bound = toggles[0].on ? curve.boundsExact()
+ : curve.boundsFast();
+ d = distanceSq(pos, bound);
+ if ( are_near(d, 0) )
+ {
+ t = curve.nearestTime(pos);
+ d = distanceSq(pos, curve.pointAt(t));
+ if (d < dist)
+ {
+ dist = d;
+ m_selected_pathvector = i;
+ m_selected_path = j;
+ m_selected_curve = k;
+ }
+ }
+ }
+ }
+ }
+ //std::cerr << "m_selected_path = " << m_selected_path << std::endl;
+ //std::cerr << "m_selected_curve = " << m_selected_curve << std::endl;
+ }
+ else if (m_selection_kind == PATH)
+ {
+ for (unsigned int i = 0; i < m_pathvector_coll.size(); ++i)
+ {
+ for (unsigned int j = 0; j < m_pathvector_coll[i].size(); ++j)
+ {
+ const Path & path = m_pathvector_coll[i][j];
+ bound = toggles[0].on ? *path.boundsExact()
+ : *path.boundsFast();
+ d = distanceSq(pos, bound);
+ if ( are_near(d, 0) )
+ {
+ t = path.nearestTime(pos).asFlatTime();
+ d = distanceSq(pos, path.pointAt(t));
+ if (d < dist)
+ {
+ dist = d;
+ m_selected_pathvector = i;
+ m_selected_path = j;
+ }
+ }
+ }
+ }
+ }
+ else if (m_selection_kind == PATHVECTOR)
+ {
+ for (unsigned int i = 0; i < m_pathvector_coll.size(); ++i)
+ {
+ const PathVector & pathvector = m_pathvector_coll[i];
+ bound = toggles[0].on ? *bounds_exact(pathvector)
+ : *bounds_fast(pathvector);
+ d = distanceSq(pos, bound);
+ if ( are_near(d, 0) )
+ {
+ for (unsigned int j = 0; j < m_pathvector_coll[i].size(); ++j)
+ {
+ const Path & path = m_pathvector_coll[i][j];
+ t = path.nearestTime(pos).asFlatTime();
+ d = distanceSq(pos, path.pointAt(t));
+ if (d < dist)
+ {
+ dist = d;
+ m_selected_pathvector = i;
+ }
+ }
+ }
+ }
+ }
+
+ Toy::mouse_pressed(e);
+ }
+
+ public:
+ BoundsPath()
+ {
+ m_total_pathvectors = 2;
+ m_paths_per_vector = 2;
+ m_curves_per_path = 3;
+ m_handles_per_curve = 4;
+
+ m_selection_kind = CURVE;
+ m_selected_pathvector = -1;
+ m_selected_path = -1;
+ m_selected_curve = -1;
+ m_handles_per_path = m_curves_per_path * (m_handles_per_curve-1) + 1;
+
+ m_pathvector_coll_handles.resize(m_total_pathvectors);
+ m_pathvector_coll.resize(m_total_pathvectors);
+ for (unsigned int k = 0; k < m_total_pathvectors; ++k)
+ {
+ m_pathvector_coll_handles[k].resize(m_paths_per_vector);
+ m_pathvector_coll[k].resize(m_paths_per_vector);
+ for (unsigned int j = 0; j < m_paths_per_vector; ++j)
+ {
+ m_pathvector_coll_handles[k][j].pts.resize(m_handles_per_path);
+ handles.push_back(&(m_pathvector_coll_handles[k][j]));
+ for (unsigned int i = 0; i < m_handles_per_path; ++i)
+ {
+ m_pathvector_coll_handles[k][j].pts[i]
+ = Point(500*uniform() + 300*k, 300*uniform() + 80 + 200*j);
+ }
+ }
+ }
+
+ sliders.emplace_back(0, 2, 1, 0, "selection type");
+ sliders[0].geometry(Point(10, 20), 50, X);
+ sliders[0].formatter(&option_formatter);
+
+ Rect toggle_bound(Point(300,20), Point(390, 45));
+ toggles.emplace_back(toggle_bound, "fast/exact", EXACT);
+
+ handles.push_back(&(sliders[0]));
+ handles.push_back(&(toggles[0]));
+ }
+
+
+ private:
+ unsigned int m_total_pathvectors;
+ unsigned int m_paths_per_vector;
+ unsigned int m_curves_per_path;
+ unsigned int m_handles_per_curve;
+ unsigned int m_handles_per_path;
+ std::vector<PathVector> m_pathvector_coll;
+ std::vector< std::vector<PointSetHandle> > m_pathvector_coll_handles;
+// PathVector m_pathvector;
+// std::vector<PointSetHandle> m_pathvector_handles;
+ int m_selected_curve;
+ int m_selected_path;
+ int m_selected_pathvector;
+ unsigned int m_selection_kind;
+ std::vector<Slider> sliders;
+ std::vector<Toggle> toggles;
+};
+
+
+int main(int argc, char **argv)
+{
+ init( argc, argv, new BoundsPath(), 800, 600 );
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/bounds-test.cpp b/src/3rdparty/2geom/src/toys/bounds-test.cpp
new file mode 100644
index 0000000..f600162
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/bounds-test.cpp
@@ -0,0 +1,171 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/bezier-to-sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <time.h>
+#include <vector>
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+static void plot(cairo_t* cr, SBasis const &B,double vscale=1,double a=0,double b=1){
+ D2<SBasis> plot;
+ plot[0]=SBasis(Linear(150+a*300,150+b*300));
+ plot[1]=B*(-vscale);
+ plot[1]+=300;
+ cairo_d2_sb(cr, plot);
+ cairo_stroke(cr);
+}
+static void plot_bar(cairo_t* cr, double height, double vscale=1,double a=0,double b=1){
+ cairo_move_to(cr, Geom::Point(150+300*a,-height*vscale+300));
+ cairo_line_to(cr, Geom::Point(150+300*b,-height*vscale+300));
+ cairo_stroke(cr);
+}
+
+class BoundsTester: public Toy {
+ unsigned size;
+ PointSetHandle hand;
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+
+ for (unsigned i=0;i<size;i++){
+ hand.pts[i ][0]=150+15*(i-size);
+ hand.pts[i+size][0]=450+15*(i+1);
+ cairo_move_to(cr, Geom::Point(hand.pts[i ][0],150));
+ cairo_line_to(cr, Geom::Point(hand.pts[i ][0],450));
+ cairo_move_to(cr, Geom::Point(hand.pts[i+size][0],150));
+ cairo_line_to(cr, Geom::Point(hand.pts[i+size][0],450));
+ }
+ cairo_move_to(cr, Geom::Point(0,300));
+ cairo_line_to(cr, Geom::Point(600,300));
+
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0.2, 0.2, 0.2, 1);
+ cairo_stroke(cr);
+
+ SBasis B(size, Linear());
+ for (unsigned i=0;i<size;i++){
+ B[i] = Linear(-(hand.pts[i ][1]-300)*std::pow(4.,(int)i),
+ -(hand.pts[i+size][1]-300)*std::pow(4.,(int)i) );
+ }
+ B.normalize();
+ plot(cr,B,1);
+ cairo_set_source_rgba (cr, 0., 0., 0.8, 1);
+ cairo_stroke(cr);
+
+ Interval bnds = *bounds_local(B,Interval(0.,.5));
+ plot_bar(cr,bnds.min(),1,.0,.5);
+ plot_bar(cr,bnds.max(),1,.0,.5);
+ cairo_set_source_rgba (cr, 0.4, 0., 0., 1);
+ cairo_stroke(cr);
+ bnds = *bounds_exact(B);
+ plot_bar(cr,bnds.min());
+ plot_bar(cr,bnds.max());
+ cairo_set_source_rgba (cr, 0.9, 0., 0., 1);
+ cairo_stroke(cr);
+
+/*
+This is a multi-root test...
+*/
+ hand.pts[2*size ][0]=150;
+ hand.pts[2*size+1][0]=150;
+ hand.pts[2*size+2][0]=150;
+ hand.pts[2*size ][1]=std::max(hand.pts[2*size ][1],hand.pts[2*size+1][1]);
+ hand.pts[2*size+1][1]=std::max(hand.pts[2*size+1][1],hand.pts[2*size+2][1]);
+ vector<double> levels;
+ levels.push_back((300-hand.pts[2*size ][1]));
+ levels.push_back((300-hand.pts[2*size+1][1]));
+ levels.push_back((300-hand.pts[2*size+2][1]));
+ for (double level : levels) plot_bar(cr,level);
+
+ cairo_set_source_rgba (cr, 0., 0.5, 0., 1);
+
+ *notify<<"Use hand.pts to set the coefficients of the s-basis."<<std::endl;
+
+ vector<double>my_roots;
+
+// cairo_set_source_rgba (cr, 0.9, 0., 0.8, 1);
+// for (unsigned i=0;i<levels.size();i++){
+// my_roots.clear();
+// my_roots=roots(B-Linear(levels[i]));
+// for(unsigned j=0;j<my_roots.size();j++){
+// draw_cross(cr,Point(150+300*my_roots[j],300-levels[i]));
+// }
+// }
+
+// cairo_set_source_rgba (cr, 0.9, 0., 0.8, 1);
+
+ vector<vector<double> > sols=multi_roots(B,levels,.001,.001);
+ //map<double,unsigned> sols=multi_roots(B,levels);
+ //for(map<double,unsigned>::iterator sol=sols.begin();sol!=sols.end();sol++){
+ // draw_handle(cr,Point(150+300*(*sol).first,300-levels[(*sol).second]));
+ //}
+
+ for (unsigned i=0;i<sols.size();i++){
+ for (unsigned j=0;j<sols[i].size();j++){
+ draw_handle(cr,Point(150+300*sols[i][j],300-levels[i]));
+ }
+ }
+ cairo_set_source_rgba (cr, 0.9, 0., 0.8, 1);
+
+/*
+
+ clock_t end_t;
+ unsigned iterations = 0;
+
+ my_roots.clear();
+ end_t = clock()+clock_t(0.1*CLOCKS_PER_SEC);
+ iterations = 0;
+ while(end_t > clock()) {
+ my_roots.clear();
+ for (unsigned i=0;i<levels.size();i++){
+ my_roots=roots(B-Linear(levels[i]));
+ }
+ iterations++;
+ }
+ *notify << 1000*0.1/iterations <<" ms = roots time"<< std::endl;
+
+ sols.clear();
+ end_t = clock()+clock_t(0.1*CLOCKS_PER_SEC);
+ iterations = 0;
+ while(end_t > clock()) {
+ sols.clear();
+ sols=multi_roots(B,levels);
+ iterations++;
+ }
+ *notify << 1000*0.1/iterations <<" ms = multi roots time"<< std::endl;
+*/
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+public:
+ BoundsTester(){
+ size=5;
+ if(hand.pts.empty()) {
+ for(unsigned i = 0; i < 2*size; i++)
+ hand.pts.emplace_back(0,150+150+uniform()*300*0);
+ }
+ hand.pts.emplace_back(150,300+ 50+uniform()*100);
+ hand.pts.emplace_back(150,300- 50+uniform()*100);
+ hand.pts.emplace_back(150,300-150+uniform()*100);
+ handles.push_back(&hand);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new BoundsTester);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype = cpp:expandtab:shiftwidth = 4:tabstop = 8:softtabstop = 4:encoding = utf-8:textwidth = 99 :
diff --git a/src/3rdparty/2geom/src/toys/box3d.cpp b/src/3rdparty/2geom/src/toys/box3d.cpp
new file mode 100644
index 0000000..06d2e6a
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/box3d.cpp
@@ -0,0 +1,153 @@
+#include <toys/toy-framework-2.h>
+
+#include <vector>
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+class Box3d: public Toy {
+ Point orig;
+
+ double tmat[3][4];
+ double c[8][4];
+ Point corners[8];
+
+ PointHandle origin_handle;
+ PointSetHandle vanishing_points_handles, axes_handles;
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ Geom::Point dir(1,-2);
+
+ cairo_set_source_rgba (cr, 0., 0.125, 0, 1);
+
+ // draw vertical lines for the VP sliders and keep the sliders at their horizontal positions
+ draw_slider_lines (cr);
+ axes_handles.pts[0][0] = 30;
+ axes_handles.pts[1][0] = 45;
+ axes_handles.pts[2][0] = 60;
+
+ /* create the transformation matrix for the map P^3 --> P^2 that has the following effect:
+ (1 : 0 : 0 : 0) --> vanishing point in x direction (= handle #0)
+ (0 : 1 : 0 : 0) --> vanishing point in y direction (= handle #1)
+ (0 : 0 : 1 : 0) --> vanishing point in z direction (= handle #2)
+ (0 : 0 : 0 : 1) --> origin (= handle #3)
+ */
+ for (int j = 0; j < 4; ++j) {
+ tmat[0][j] = vanishing_points_handles.pts[j][0];
+ tmat[1][j] = vanishing_points_handles.pts[j][1];
+ tmat[2][j] = 1;
+ }
+
+ *notify << "Projection matrix:" << endl;
+ for (auto & i : tmat) {
+ for (double j : i) {
+ *notify << j << " ";
+ }
+ *notify << endl;
+ }
+
+ // draw the projective images of the box's corners
+ for (int i = 0; i < 8; ++i) {
+ corners[i] = proj_image (cr, c[i]);
+ }
+ draw_box(cr, corners);
+ cairo_set_line_width (cr, 2);
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+ void first_time(int /*argc*/, char** /*argv*/) override {
+ // Finite images of the three vanishing points and the origin
+ handles.push_back(&origin_handle);
+ handles.push_back(&vanishing_points_handles);
+ handles.push_back(&axes_handles);
+ vanishing_points_handles.push_back(550,350);
+ vanishing_points_handles.push_back(150,300);
+ vanishing_points_handles.push_back(380,40);
+ vanishing_points_handles.push_back(340,450);
+ // plane origin
+ origin_handle.pos = Point(180,65);
+
+ // Handles for moving in axes directions
+ axes_handles.push_back(30,300);
+ axes_handles.push_back(45,300);
+ axes_handles.push_back(60,300);
+
+ // Box corners
+ for (int i = 0; i < 8; ++i) {
+ c[i][0] = ((i & 1) ? 1 : 0);
+ c[i][1] = ((i & 2) ? 1 : 0);
+ c[i][2] = ((i & 4) ? 1 : 0);
+ c[i][3] = 1;
+ }
+
+ orig = origin_handle.pos;
+ }
+ Geom::Point proj_image (cairo_t *cr, const double pt[4]) {
+ double res[3];
+ for (int j = 0; j < 3; ++j) {
+ res[j] =
+ tmat[j][0] * (pt[0] - (axes_handles.pts[0][1]-300)/100)
+ + tmat[j][1] * (pt[1] - (axes_handles.pts[1][1]-300)/100)
+ + tmat[j][2] * (pt[2] - (axes_handles.pts[2][1]-300)/100)
+ + tmat[j][3] * pt[3];
+ }
+ if (fabs (res[2]) > 0.000001) {
+ Geom::Point result = Geom::Point (res[0]/res[2], res[1]/res[2]);
+ draw_handle(cr, result);
+ return result;
+ }
+ assert(0); // unclipped point
+ return Geom::Point(0,0);
+ }
+
+ void draw_box (cairo_t *cr, Geom::Point corners[8]) {
+ cairo_move_to(cr,corners[0]);
+ cairo_line_to(cr,corners[1]);
+ cairo_line_to(cr,corners[3]);
+ cairo_line_to(cr,corners[2]);
+ cairo_close_path(cr);
+
+ cairo_move_to(cr,corners[4]);
+ cairo_line_to(cr,corners[5]);
+ cairo_line_to(cr,corners[7]);
+ cairo_line_to(cr,corners[6]);
+ cairo_close_path(cr);
+
+ for(int i = 0 ; i < 4; i++) {
+ cairo_move_to(cr,corners[i]);
+ cairo_line_to(cr,corners[i+4]);
+ }
+ }
+
+ void draw_slider_lines (cairo_t *cr) {
+ cairo_move_to(cr, Geom::Point(20,300));
+ cairo_line_to(cr, Geom::Point(70,300));
+
+ for(int i = 0; i < 3; i++) {
+ cairo_move_to(cr, Geom::Point(30 + 15*i,00));
+ cairo_line_to(cr, Geom::Point(30 + 15*i,450));
+ }
+
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0.2, 0.2, 0.2, 1);
+ cairo_stroke(cr);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new Box3d);
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/center-warp.cpp b/src/3rdparty/2geom/src/toys/center-warp.cpp
new file mode 100644
index 0000000..4c0f750
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/center-warp.cpp
@@ -0,0 +1,113 @@
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/d2.h>
+#include <2geom/path.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-math.h>
+#include <2geom/svg-path-parser.h>
+#include <2geom/transforms.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <vector>
+using std::vector;
+using namespace Geom;
+
+unsigned total_pieces_sub;
+unsigned total_pieces_inc;
+
+void cairo_pw(cairo_t *cr, Piecewise<SBasis> p) {
+ for(unsigned i = 0; i < p.size(); i++) {
+ D2<SBasis> B;
+ B[0] = Linear(p.cuts[i], p.cuts[i+1]);
+ B[1] = p[i];
+ cairo_d2_sb(cr, B);
+ }
+}
+
+class CentreWarp: public Toy {
+ Path path_a;
+ D2<SBasis2d> sb2;
+ Piecewise<D2<SBasis> > path_a_pw;
+ PointHandle brush_handle;
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ Geom::Point dir(1,-2);
+
+ D2<Piecewise<SBasis> > B = make_cuts_independent(path_a_pw);
+
+ cairo_set_source_rgba (cr, 0., 0.125, 0, 1);
+
+ if(0) {
+ D2<Piecewise<SBasis> > tB(cos(B[0]*0.1)*(brush_handle.pos[0]/100) + B[0],
+ cos(B[1]*0.1)*(brush_handle.pos[1]/100) + B[1]);
+
+ cairo_d2_pw_sb(cr, tB);
+ } else {
+ Piecewise<SBasis> r2 = (dot(path_a_pw - brush_handle.pos, path_a_pw - brush_handle.pos));
+ Piecewise<SBasis> rc;
+ rc.push_cut(0);
+ rc.push(SBasis(Linear(1, 1)), 2);
+ rc.push(SBasis(Linear(1, 0)), 4);
+ rc.push(SBasis(Linear(0, 0)), 30);
+ rc *= 10;
+ rc.scaleDomain(1000);
+ Piecewise<SBasis> swr;
+ swr.push_cut(0);
+ swr.push(SBasis(Linear(0, 1)), 2);
+ swr.push(SBasis(Linear(1, 0)), 4);
+ swr.push(SBasis(Linear(0, 0)), 30);
+ swr *= 10;
+ swr.scaleDomain(1000);
+ cairo_pw(cr, swr);// + (height - 100));
+ D2<Piecewise<SBasis> > uB = make_cuts_independent(unitVector(path_a_pw - brush_handle.pos));
+
+ D2<Piecewise<SBasis> > tB(compose(rc, (r2))*uB[0] + B[0],
+ compose(rc, (r2))*uB[1] + B[1]);
+ cairo_d2_pw_sb(cr, tB);
+ //path_a_pw = sectionize(tB);
+ }
+ cairo_stroke(cr);
+
+ *notify << path_a_pw.size();
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+ void first_time(int argc, char** argv) override {
+ const char *path_a_name="star.svgd";
+ if(argc > 1)
+ path_a_name = argv[1];
+ PathVector paths_a = read_svgd(path_a_name);
+ assert(!paths_a.empty());
+ path_a = paths_a[0];
+
+ path_a.close(true);
+ path_a_pw = path_a.toPwSb();
+ for(unsigned dim = 0; dim < 2; dim++) {
+ sb2[dim].us = 2;
+ sb2[dim].vs = 2;
+ const int depth = sb2[dim].us*sb2[dim].vs;
+ sb2[dim].resize(depth, Linear2d(0));
+ }
+
+ handles.push_back(&brush_handle);
+ brush_handle.pos = Point(100,100);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new CentreWarp);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/circle-fitting.cpp b/src/3rdparty/2geom/src/toys/circle-fitting.cpp
new file mode 100644
index 0000000..d51b1cf
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/circle-fitting.cpp
@@ -0,0 +1,164 @@
+/*
+ * Circle and Elliptical Arc Fitting Example
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <memory>
+#include <2geom/circle.h>
+#include <2geom/elliptical-arc.h>
+#include <2geom/numeric/fitting-tool.h>
+#include <2geom/numeric/fitting-model.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+
+using namespace Geom;
+
+
+class CircleFitting : public Toy
+{
+ private:
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ if (first_time)
+ {
+ first_time = false;
+ Point toggle_sp( 300, height - 50);
+ toggles[0].bounds = Rect( toggle_sp, toggle_sp + Point(120,25) );
+ sliders[0].geometry(Point(50, height - 50), 100);
+ }
+
+ size_t n = (size_t)(sliders[0].value()) + 3;
+ if (n < psh.pts.size())
+ {
+ psh.pts.resize(n);
+ }
+ else if (n > psh.pts.size())
+ {
+ psh.push_back(400*uniform()+50, 300*uniform()+50);
+ }
+
+ try
+ {
+ c.fit(psh.pts);
+ }
+ catch(RangeError exc)
+ {
+ std::cerr << exc.what() << std::endl;
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ return;
+ }
+
+ if (toggles[0].on)
+ {
+ try
+ {
+ std::unique_ptr<EllipticalArc> eap( c.arc(psh.pts[0], psh.pts[1], psh.pts[2]) );
+ ea = *eap;
+ }
+ catch(RangeError exc)
+ {
+ std::cerr << exc.what() << std::endl;
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ return;
+ }
+ }
+
+ std::cerr << "center = " << c.center() << " ray = " << c.radius() << std::endl;
+
+ cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, 1.0);
+ cairo_set_line_width (cr, 0.3);
+ if (!toggles[0].on)
+ {
+ cairo_arc(cr, c.center(X), c.center(Y), c.radius(), 0, 2*M_PI);
+ }
+ else
+ {
+ draw_text(cr, psh.pts[0], "initial");
+ draw_text(cr, psh.pts[1], "inner");
+ draw_text(cr, psh.pts[2], "final");
+
+ D2<SBasis> easb = ea.toSBasis();
+ cairo_d2_sb(cr, easb);
+ }
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ CircleFitting()
+ {
+ first_time = true;
+
+ psh.pts.resize(3);
+ psh.pts[0] = Point(450, 250);
+ psh.pts[1] = Point(250, 100);
+ psh.pts[2] = Point(250, 400);
+
+
+ toggles.emplace_back(" arc / circle ", false);
+ sliders.emplace_back(0, 5, 1, 0, "more handles");
+
+ handles.push_back(&psh);
+ handles.push_back(&(toggles[0]));
+ handles.push_back(&(sliders[0]));
+ }
+
+ private:
+ Circle c;
+ EllipticalArc ea;
+ bool first_time;
+ PointSetHandle psh;
+ std::vector<Toggle> toggles;
+ std::vector<Slider> sliders;
+};
+
+
+
+int main(int argc, char **argv)
+{
+ init( argc, argv, new CircleFitting(), 600, 600 );
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/circle-intersect.cpp b/src/3rdparty/2geom/src/toys/circle-intersect.cpp
new file mode 100644
index 0000000..d327a24
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/circle-intersect.cpp
@@ -0,0 +1,70 @@
+#include <toys/toy-framework-2.h>
+#include <2geom/circle.h>
+
+using namespace Geom;
+
+class CircleIntersect : public Toy {
+ PointSetHandle psh[2];
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ double r1 = Geom::distance(psh[0].pts[0], psh[0].pts[1]);
+ double r2 = Geom::distance(psh[1].pts[0], psh[1].pts[1]);
+
+ Circle c1(psh[0].pts[0], r1);
+ Circle c2(psh[1].pts[0], r2);
+
+ std::vector<ShapeIntersection> result = c1.intersect(c2);
+
+ cairo_set_line_width(cr, 1.0);
+
+ // draw the circles
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ cairo_arc(cr, c1.center(X), c1.center(Y), c1.radius(), 0, 2*M_PI);
+ cairo_stroke(cr);
+ cairo_arc(cr, c2.center(X), c2.center(Y), c2.radius(), 0, 2*M_PI);
+ cairo_stroke(cr);
+
+ // draw intersection points
+ cairo_set_source_rgb(cr, 1, 0, 0);
+ for (auto & i : result) {
+ draw_handle(cr, i.point());
+ }
+ cairo_stroke(cr);
+
+ // show message
+ if (c1.contains(c2)) {
+ *notify << "Containment";
+ } else if (!result.empty()) {
+ for (auto & i : result) {
+ *notify << i.point() << " ";
+ }
+ } else {
+ *notify << "No intersection";
+ }
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ CircleIntersect(){
+ psh[0].push_back(200,200); psh[0].push_back(250,200);
+ psh[1].push_back(150,150); psh[1].push_back(250,150);
+ handles.push_back(&psh[0]);
+ handles.push_back(&psh[1]);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new CircleIntersect());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/circle-line-intersect.cpp b/src/3rdparty/2geom/src/toys/circle-line-intersect.cpp
new file mode 100644
index 0000000..3946ca1
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/circle-line-intersect.cpp
@@ -0,0 +1,67 @@
+#include <2geom/circle.h>
+#include <toys/toy-framework-2.h>
+
+using namespace Geom;
+
+class CircleIntersect : public Toy {
+ PointSetHandle psh[2];
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ Rect all(Point(0, 0), Point(width, height));
+ double r = Geom::distance(psh[0].pts[0], psh[0].pts[1]);
+
+ Circle circ(psh[0].pts[0], r);
+ Line line(psh[1].pts[0], psh[1].pts[1]);
+
+ std::vector<ShapeIntersection> result = circ.intersect(line);
+
+ cairo_set_line_width(cr, 1.0);
+
+ // draw the shapes
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ cairo_arc(cr, circ.center(X), circ.center(Y), circ.radius(), 0, 2*M_PI);
+ draw_line(cr, line, all);
+ cairo_stroke(cr);
+
+ // draw intersection points
+ cairo_set_source_rgb(cr, 1, 0, 0);
+ for (auto & i : result) {
+ draw_handle(cr, i.point());
+ }
+ cairo_stroke(cr);
+
+ // show message
+ if (!result.empty()) {
+ for (auto & i : result) {
+ *notify << i.point() << ", ";
+ }
+ } else {
+ *notify << "No intersection";
+ }
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ CircleIntersect(){
+ psh[0].push_back(200,200); psh[0].push_back(250,200);
+ psh[1].push_back(150,150); psh[1].push_back(250,150);
+ handles.push_back(&psh[0]);
+ handles.push_back(&psh[1]);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new CircleIntersect());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/circle-tangent-fitting.cpp b/src/3rdparty/2geom/src/toys/circle-tangent-fitting.cpp
new file mode 100644
index 0000000..f0d74ee
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/circle-tangent-fitting.cpp
@@ -0,0 +1,224 @@
+/*
+ * Circle and Elliptical Arc Fitting Example
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <memory>
+#include <2geom/numeric/fitting-tool.h>
+#include <2geom/numeric/fitting-model.h>
+
+#include <2geom/circle.h>
+#include <2geom/elliptical-arc.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+
+using namespace Geom;
+
+
+
+class LFMCircleTangentEquation
+ : public NL::LinearFittingModelWithFixedTerms<Point, double, Circle>
+{
+ public:
+ mutable unsigned count; // sigh
+ mutable Point pb;
+ vector<Point> bases;
+ void feed( NL::VectorView & coeff, double & fixed_term, Point const& p ) const
+ {
+ if (count >= bases.size()) {
+ coeff[0] = p[X];
+ coeff[1] = p[Y];
+ coeff[2] = 1;
+ fixed_term = p[X] * p[X] + p[Y] * p[Y];
+ pb = p;
+ } else {
+ Point pb = bases[count];
+ coeff[0] = p[X];
+ coeff[1] = p[Y];
+ coeff[2] = 0;
+ fixed_term = 2*p[X]*pb[X] + 2*p[Y]*pb[Y];
+ count ++;
+ }
+ }
+
+ size_t size() const
+ {
+ return 3;
+ }
+ void instance(Circle & c, NL::Vector const& coeff) const
+ {
+ c.setCoefficients(1, coeff[0], coeff[1], coeff[2]);
+ }
+};
+
+
+class CircleFitting : public Toy
+{
+ private:
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ if (first_time)
+ {
+ first_time = false;
+ Point toggle_sp( 300, height - 50);
+ toggles[0].bounds = Rect( toggle_sp, toggle_sp + Point(120,25) );
+ sliders[0].geometry(Point(50, height - 50), 100);
+ }
+
+ try
+ {
+ vector<Point> points;
+ points.push_back(psh.pts[1]-psh.pts[0]); // tangents
+ //points.push_back(psh.pts[2]-psh.pts[3]);
+ points.push_back(psh.pts[3]);
+ points.push_back(psh.pts[0]);
+ size_t sz = points.size();
+ if (sz < 3)
+ {
+ THROW_RANGEERROR("fitting error: too few points passed");
+ }
+ LFMCircleTangentEquation model;
+ model.count = 0;
+ model.bases.push_back(psh.pts[0]);
+ //model.bases.push_back(psh.pts[3]);
+ NL::least_squeares_fitter<LFMCircleTangentEquation> fitter(model, sz);
+
+ for (size_t i = 0; i < sz; ++i)
+ {
+ fitter.append(points[i]);
+ }
+ fitter.update();
+
+ NL::Vector z(sz, 0.0);
+ model.instance(c, fitter.result(z));
+ //c.set(psh.pts);
+ }
+ catch(RangeError exc)
+ {
+ std::cerr << exc.what() << std::endl;
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ return;
+ }
+
+ if (toggles[0].on)
+ {
+ try
+ {
+ std::unique_ptr<EllipticalArc> eap( c.arc(psh.pts[0], psh.pts[1], psh.pts[3]) );
+ ea = *eap;
+ }
+ catch(RangeError exc)
+ {
+ std::cerr << exc.what() << std::endl;
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ return;
+ }
+ }
+ cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, 1.0);
+ cairo_set_line_width (cr, 0.3);
+ cairo_move_to(cr, psh.pts[1]);
+ cairo_line_to(cr, 2*psh.pts[0] - psh.pts[1]);
+ cairo_move_to(cr, psh.pts[2]);
+ cairo_line_to(cr, 2*psh.pts[3] - psh.pts[2]);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, 1.0);
+ cairo_set_line_width (cr, 0.3);
+ if (!toggles[0].on)
+ {
+ cairo_arc(cr, c.center(X), c.center(Y), c.radius(), 0, 2*M_PI);
+ }
+ else
+ {
+ draw_text(cr, psh.pts[0], "initial");
+ draw_text(cr, psh.pts[1], "inner");
+ draw_text(cr, psh.pts[2], "inner");
+ draw_text(cr, psh.pts[3], "final");
+
+ D2<SBasis> easb = ea.toSBasis();
+ cairo_d2_sb(cr, easb);
+ }
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ CircleFitting()
+ {
+ first_time = true;
+
+ psh.pts.resize(4);
+ psh.pts[0] = Point(450, 250);
+ psh.pts[1] = Point(450+100, 250+100);
+ psh.pts[2] = Point(250+100, 400+100);
+ psh.pts[3] = Point(250, 400);
+
+
+
+ toggles.emplace_back(" arc / circle ", false);
+ sliders.emplace_back(0, 5, 1, 0, "more handles");
+
+ handles.push_back(&psh);
+ handles.push_back(&(toggles[0]));
+ handles.push_back(&(sliders[0]));
+ }
+
+ private:
+ Circle c;
+ EllipticalArc ea;
+ bool first_time;
+ PointSetHandle psh;
+ std::vector<Toggle> toggles;
+ std::vector<Slider> sliders;
+};
+
+
+
+int main(int argc, char **argv)
+{
+ init( argc, argv, new CircleFitting(), 600, 600 );
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/collinear-normal.cpp b/src/3rdparty/2geom/src/toys/collinear-normal.cpp
new file mode 100644
index 0000000..a5e1af5
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/collinear-normal.cpp
@@ -0,0 +1,204 @@
+/*
+ * Show off collinear normals between two Bezier curves.
+ * The intersection points are found by using Bezier clipping.
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/d2.h>
+#include <2geom/basic-intersection.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/ray.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+using namespace Geom;
+
+
+
+class CurveIntersect : public Toy
+{
+
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ m_width = width;
+ m_height = height;
+ m_length = (m_width > m_height) ? m_width : m_height;
+ m_length *= 2;
+
+ cairo_set_line_width (cr, 0.3);
+ cairo_set_source_rgba (cr, 0.8, 0., 0, 1);
+ D2<SBasis> A = pshA.asBezier();
+ cairo_d2_sb(cr, A);
+ cairo_stroke(cr);
+ cairo_set_source_rgba (cr, 0.0, 0., 0, 1);
+ D2<SBasis> B = pshB.asBezier();
+ cairo_d2_sb(cr, B);
+ cairo_stroke(cr);
+ draw_text(cr, A.at0(), "A");
+ draw_text(cr, B.at0(), "B");
+
+ Timer tm;
+ tm.ask_for_timeslice();
+ tm.start();
+
+ find_collinear_normal(xs, pshA.pts, pshB.pts, m_precision);
+ Timer::Time als_time = tm.lap();
+ *timer_stream << "find_collinear_normal " << als_time << std::endl;
+ cairo_set_line_width (cr, 0.3);
+ cairo_set_source_rgba (cr, 0.0, 0.0, 0.7, 1);
+ for (auto & x : xs)
+ {
+ Point At = A(x.first);
+ Point Bu = B(x.second);
+ draw_axis(cr, At, Bu);
+ draw_handle(cr, At);
+ draw_handle(cr, Bu);
+
+ }
+ cairo_stroke(cr);
+
+ double h_a_t = 0, h_b_t = 0;
+
+ double h_dist = hausdorfl( A, B, m_precision, &h_a_t, &h_b_t);
+ {
+ Point At = A(h_a_t);
+ Point Bu = B(h_b_t);
+ cairo_move_to(cr, At);
+ cairo_line_to(cr, Bu);
+ draw_handle(cr, At);
+ draw_handle(cr, Bu);
+ cairo_save(cr);
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0.7, 0.0, 0.0, 1);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ }
+ /*h_dist = hausdorf( A, B, m_precision, &h_a_t, &h_b_t);
+ {
+ Point At = A(h_a_t);
+ Point Bu = B(h_b_t);
+ draw_axis(cr, At, Bu);
+ draw_handle(cr, At);
+ draw_handle(cr, Bu);
+ cairo_save(cr);
+ cairo_set_line_width (cr, 0.3);
+ cairo_set_source_rgba (cr, 0.0, 0.7, 0.0, 1);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ }*/
+ *notify << "Hausdorf distance = " << h_dist
+ << " occurring at " << h_a_t
+ << " B=" << h_b_t << std::endl;
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ void draw_segment(cairo_t* cr, Point const& p1, Point const& p2)
+ {
+ cairo_move_to(cr, p1);
+ cairo_line_to(cr, p2);
+ }
+
+ void draw_segment(cairo_t* cr, Point const& p1, double angle, double length)
+ {
+ Point p2;
+ p2[X] = length * std::cos(angle);
+ p2[Y] = length * std::sin(angle);
+ p2 += p1;
+ draw_segment(cr, p1, p2);
+ }
+
+ void draw_ray(cairo_t* cr, Ray const& r)
+ {
+ double angle = r.angle();
+ draw_segment(cr, r.origin(), angle, m_length);
+ }
+
+ void draw_axis(cairo_t* cr, Point const& p1, Point const& p2)
+ {
+ double d = Geom::distance(p1, p2);
+ d = d + d/4;
+ Point q1 = Ray(p1, p2).pointAt(d);
+ Point q2 = Ray(p2, p1).pointAt(d);
+ draw_segment(cr, q1, q2);
+ }
+
+public:
+ CurveIntersect(unsigned int _A_bez_ord, unsigned int _B_bez_ord)
+ : A_bez_ord(_A_bez_ord), B_bez_ord(_B_bez_ord)
+ {
+ handles.push_back(&pshA);
+ for (unsigned int i = 0; i <= A_bez_ord; ++i)
+ pshA.push_back(Geom::Point(uniform()*400, uniform()*400)+Point(200,200));
+ handles.push_back(&pshB);
+ for (unsigned int i = 0; i <= B_bez_ord; ++i)
+ pshB.push_back(Geom::Point(uniform()*400, uniform()*400)+Point(200,200));
+
+ m_precision = 1e-6;
+ }
+
+private:
+ unsigned int A_bez_ord, B_bez_ord;
+ PointSetHandle pshA, pshB, pshC;
+ std::vector< std::pair<double, double> > xs;
+ double m_precision;
+ double m_width, m_height, m_length;
+};
+
+
+int main(int argc, char **argv)
+{
+ unsigned int A_bez_ord = 4;
+ unsigned int B_bez_ord = 6;
+ if(argc > 1)
+ sscanf(argv[1], "%d", &A_bez_ord);
+ if(argc > 2)
+ sscanf(argv[2], "%d", &B_bez_ord);
+
+
+ init( argc, argv, new CurveIntersect(A_bez_ord, B_bez_ord), 800, 800);
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+ */
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+
+
diff --git a/src/3rdparty/2geom/src/toys/conic-3.cpp b/src/3rdparty/2geom/src/toys/conic-3.cpp
new file mode 100644
index 0000000..64b2c27
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/conic-3.cpp
@@ -0,0 +1,96 @@
+/**
+ * elliptics via C-curves. (njh)
+ * Limited to 180 degrees (by end point and tangent matching criteria)
+ * Also represents cycloids
+ */
+
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/sbasis-math.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+using std::vector;
+using namespace Geom;
+
+Linear z0(0.5,1.);
+
+unsigned total_pieces;
+
+double sinC(double t) { return t - sin(t);}
+double cosC(double t) { return 1 - cos(t);}
+double tanC(double t) { return sinC(t) / cosC(t);}
+
+class Conic3: public Toy {
+ PointSetHandle psh;
+ public:
+ Conic3 () {
+ psh.push_back(100, 500);
+ psh.push_back(100, 500 - 200*M_PI/2);
+ psh.push_back(500, 500 - 200*M_PI/2);
+ psh.push_back(500, 500);
+ handles.push_back(&psh);
+ }
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_source_rgba (cr, 0., 0., 0, 0.8);
+ cairo_set_line_width (cr, 0.5);
+ cairo_stroke(cr);
+
+ Geom::Point a[2] = {psh.pts[0] - psh.pts[1],
+ psh.pts[2] - psh.pts[1]};
+ double angle = Geom::angle_between(a[0], a[1]);
+ double len = std::max(Geom::L2(a[0]),
+ Geom::L2(a[1]));
+ for(auto & i : a)
+ i = len*unit_vector(i);
+ *notify << "angle = " << angle;
+ *notify << " sinC = " << sinC(angle);
+ *notify << " cosC = " << cosC(angle);
+ *notify << " tanC = " << tanC(angle);
+ vector<Geom::Point> e_a_h = psh.pts;
+
+ double alpha = M_PI;
+ Piecewise<SBasis> pw(Linear(0, alpha));
+ Piecewise<SBasis> C = cos(pw);
+ Piecewise<SBasis> S = sin(pw);
+ Piecewise<SBasis> sinC = pw - S;
+ Piecewise<SBasis> cosC = Piecewise<SBasis>(1) - C;
+ Piecewise<SBasis> Z3 = sinC/sinC(1);
+ Piecewise<SBasis> Z0 = reverse(Z3);
+ Piecewise<SBasis> Z2 = cosC/cosC(1) - Z3;
+ Piecewise<SBasis> Z1 = reverse(Z2);
+
+ Piecewise<SBasis> Z[4] = {Z0, Z1, Z2, Z3};
+
+ D2<Piecewise<SBasis> > B;
+ for(unsigned dim = 0; dim < 2; dim++) {
+ B[dim] = Piecewise<SBasis>(0);
+ for(unsigned i = 0; i < 4; i++) {
+ B[dim] += Z[i]*e_a_h[i][dim];
+ }
+ }
+ cairo_d2_pw_sb(cr, B);
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new Conic3());
+
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/conic-4.cpp b/src/3rdparty/2geom/src/toys/conic-4.cpp
new file mode 100644
index 0000000..0dbecd6
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/conic-4.cpp
@@ -0,0 +1,129 @@
+/**
+ * elliptics via 5 point w-pi basis. (njh)
+ * Affine, endpoint, tangent, exact circle
+ * full circle. Convex containment implies small circle.
+ * Also represents lumpy polar type curves
+ */
+
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-math.h>
+#include <2geom/bezier-to-sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+using std::vector;
+using namespace Geom;
+
+const double w = 1./3;
+const double cwp = cos(w*M_PI);
+const double swp = sin(w*M_PI);
+/*double phi(double t, double w) { return sin(w*t) - w*sin(t); }
+double phih(double t, double w) { return sin(w*t) + w*sin(t); }
+double b4(double t, double w) {return phi(t/2,w)*phih(t/2,w)/(swp*swp);}
+double b3(double t, double w) {return cwp*phi(t,w)/(2*swp) - cwp*cwp*b4(t,w); }
+double b2(double t, double w) {return 2*w*w*sin(t/2)*sin(t/2);}
+double b1(double t, double w) {return b3(2*M_PI - t, w);}
+double b0(double t, double w) {return b4(2*M_PI - t, w);}*/
+
+class arc_basis{
+public:
+ Piecewise<SBasis> basis[5];
+ double w;
+
+ Piecewise<SBasis> phi(Piecewise<SBasis> const &d, double w) {
+ return sin(d*w) - sin(d)*w;
+ }
+ Piecewise<SBasis> phih(Piecewise<SBasis> const &d, double w) {
+ return sin(d*w) + sin(d)*w;
+ }
+ Piecewise<SBasis> b4(Piecewise<SBasis> const &d, double w) {
+ return phi(d*.5,w)/(swp*swp)*phih(d*.5,w);
+ }
+ Piecewise<SBasis> b3(Piecewise<SBasis> const &d, double w) {
+ return phi(d,w)*(cwp/(2*swp)) - b4(d,w)*(cwp*cwp);
+ }
+
+ Piecewise<SBasis> b2(Piecewise<SBasis> const &d, double w) {
+ return sin(d*.5)*(2*w*w)*sin(d*.5);
+ }
+ Piecewise<SBasis> b1(Piecewise<SBasis> const &d, double w) {
+ return b3(reverse(d), w);
+ }
+ Piecewise<SBasis> b0(Piecewise<SBasis> const &d, double w) {
+ return b4(reverse(d), w);
+ }
+
+
+ arc_basis(double w) {
+ Piecewise<SBasis> dom(Linear(0, 2*M_PI));
+ basis[0] = b4(dom, w);
+ basis[1] = b3(dom, w);
+ basis[2] = b2(dom, w);
+ basis[3] = b1(dom, w);
+ basis[4] = b0(dom, w);
+ }
+
+};
+
+class Conic4: public Toy {
+ PointSetHandle psh;
+ public:
+ Conic4 () {
+ double sc = 30;
+ Geom::Point c(6*sc, 6*sc);
+ psh.push_back(sc*Geom::Point(0,0)+c);
+ psh.push_back(sc*Geom::Point(tan(w*M_PI)/w, 0)+c);
+ psh.push_back(sc*Geom::Point(0, 1/(w*w))+c);
+ psh.push_back(sc*Geom::Point(-tan(w*M_PI)/w, 0)+c);
+ psh.push_back(sc*Geom::Point(0,0)+c);
+ handles.push_back(&psh);
+ }
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ std::vector<Geom::Point> e_h = psh.pts;
+ for(int i = 0; i < 5; i++) {
+ Geom::Point p = e_h[i];
+
+ if(i)
+ cairo_line_to(cr, p);
+ else
+ cairo_move_to(cr, p);
+ }
+ cairo_set_source_rgba (cr, 0., 0., 0, 1);
+ cairo_set_line_width (cr, 1);
+ cairo_stroke(cr);
+
+ arc_basis ab(1./3);
+ D2<Piecewise<SBasis> > B;
+
+ for(unsigned dim = 0; dim < 2; dim++)
+ for(unsigned i = 0; i < 5; i++)
+ B[dim] += ab.basis[i]*e_h[i][dim];
+
+ cairo_d2_pw_sb(cr, B);
+ cairo_set_source_rgba (cr, 1., 0.5, 0, 1);
+ cairo_set_line_width (cr, 1);
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new Conic4());
+
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/conic-5.cpp b/src/3rdparty/2geom/src/toys/conic-5.cpp
new file mode 100644
index 0000000..51140c1
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/conic-5.cpp
@@ -0,0 +1,356 @@
+#include <iostream>
+#include <2geom/path.h>
+#include <2geom/svg-path-parser.h>
+#include <2geom/path-intersection.h>
+#include <2geom/basic-intersection.h>
+#include <2geom/pathvector.h>
+#include <2geom/exception.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/path-intersection.h>
+#include <2geom/nearest-time.h>
+#include <2geom/line.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-to-bezier.h>
+
+#include <cstdlib>
+#include <map>
+#include <vector>
+#include <algorithm>
+#include <optional>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/ord.h>
+
+
+
+#include <2geom/conicsec.h>
+
+using namespace Geom;
+using namespace std;
+
+
+// File: convert.h
+#include <sstream>
+#include <stdexcept>
+
+class BadConversion : public std::runtime_error {
+public:
+ BadConversion(const std::string& s)
+ : std::runtime_error(s)
+ { }
+};
+
+template <typename T>
+inline std::string stringify(T x)
+{
+ std::ostringstream o;
+ if (!(o << x))
+ throw BadConversion("stringify(T)");
+ return o.str();
+}
+
+void draw_hull(cairo_t*cr, RatQuad rq) {
+ cairo_move_to(cr, rq.P[0]);
+ cairo_line_to(cr, rq.P[1]);
+ cairo_line_to(cr, rq.P[2]);
+ cairo_stroke(cr);
+}
+
+
+
+void draw(cairo_t* cr, xAx C, Rect bnd) {
+ if(bnd[1].extent() < 5) return;
+ vector<double> prev_rts;
+ double py = bnd[Y].min();
+ for(int i = 0; i < 100; i++) {
+ double t = i/100.;
+ double y = bnd[Y].valueAt(t);
+ vector<double> rts = C.roots(Point(1, 0), Point(0, y));
+ int top = 0;
+ for(unsigned j = 0; j < rts.size(); j++) {
+ if(bnd[0].contains(rts[j])) {
+ rts[top] = rts[j];
+ top++;
+ }
+ }
+ rts.erase(rts.begin()+top, rts.end());
+
+ if(rts.size() == prev_rts.size()) {
+ for(unsigned j = 0; j < rts.size(); j++) {
+ cairo_move_to(cr, prev_rts[j], py);
+ cairo_line_to(cr, rts[j], y);
+ cairo_stroke(cr);
+ }
+ } else {
+ draw(cr, C, Rect(bnd[X], Interval(py, y)));
+ }
+ prev_rts = rts;
+ py = y;
+ }
+}
+
+template <typename T>
+static T det(T a, T b, T c, T d) {
+ return a*d - b*c;
+}
+
+template <typename T>
+static T det(T M[2][2]) {
+ return M[0][0]*M[1][1] - M[1][0]*M[0][1];
+}
+
+template <typename T>
+static T det3(T M[3][3]) {
+ return ( M[0][0] * det(M[1][1], M[1][2],
+ M[2][1], M[2][2])
+ -M[1][0] * det(M[0][1], M[0][2],
+ M[2][1], M[2][2])
+ +M[2][0] * det(M[0][1], M[0][2],
+ M[1][1], M[1][2]));
+}
+
+double xAx_descr(xAx const & C) {
+ double mC[3][3] = {{C.c[0], (C.c[1])/2, (C.c[3])/2},
+ {(C.c[1])/2, C.c[2], (C.c[4])/2},
+ {(C.c[3])/2, (C.c[4])/2, C.c[5]}};
+
+ return det3(mC);
+}
+
+void draw_ratquad(cairo_t*cr, RatQuad rq, double tol=1e-1) {
+ CubicBezier cb = rq.toCubic();
+ // I tried using the nearest point to 0.5 for the error, but the improvement was negligible
+ if(L2(cb.pointAt(0.5) - rq.pointAt(0.5)) > tol) {
+ RatQuad a, b;
+ rq.split(a, b);
+ draw_ratquad(cr, a, tol);
+ draw_ratquad(cr, b, tol);
+ } else {
+ cairo_curve(cr, cb);
+ //draw_cross(cr, cb.pointAt(0));
+ //draw_cross(cr, cb.pointAt(1));
+ }
+}
+
+
+class Conic5: public Toy {
+ PointSetHandle path_handles;
+ PointHandle oncurve;
+ PointSetHandle cutting_plane;
+ std::vector<Slider> sliders;
+ RectHandle rh;
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_source_rgba (cr, 0., 0., 0, 1);
+ cairo_set_line_width (cr, 1);
+
+ if(0) {
+ Path path;
+ path = Path(path_handles.pts[0]);
+ D2<SBasis> c = handles_to_sbasis(path_handles.pts.begin(), 2);
+ path.append(c);
+
+ cairo_save(cr);
+ cairo_path(cr, path);
+ cairo_set_source_rgba (cr, 0., 1., 0, 0.3);
+ cairo_set_line_width (cr, 3);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+
+ //double w = exp(sliders[0].value());
+ }
+ Point A = path_handles.pts[0];
+ Point B = path_handles.pts[1];
+ Point C = path_handles.pts[2];
+
+ if(1) {
+ QuadraticBezier qb(A, B, C);
+ //double abt = qb.nearestTime(oncurve.pos);
+ //oncurve.pos = qb.pointAt(abt);
+
+ RatQuad rq = RatQuad::fromPointsTangents(A, B-A, oncurve.pos, C, B -C); //( A, B, C, w);
+
+ cairo_save(cr);
+ cairo_set_source_rgba (cr, 0., 0., 0, 1);
+ cairo_set_line_width (cr, 1);
+ draw_ratquad(cr, rq);
+ //cairo_d2_sb(cr, rq.hermite());
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ }
+
+ if(0) {
+ RatQuad rq = RatQuad::circularArc(A, B, C);
+
+ cairo_save(cr);
+ cairo_set_source_rgba (cr, 0., 0., 0, 1);
+ cairo_set_line_width (cr, 1);
+ RatQuad a, b;
+ rq.split(a,b);
+ cairo_curve(cr, a.toCubic());
+ cairo_curve(cr, b.toCubic());
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ }
+
+ Rect screen_rect(Interval(10, width-10), Interval(10, height-10));
+ Line cutLine(cutting_plane.pts[0], cutting_plane.pts[1]);
+ //double dist;
+ //Point norm = cutLine.normalAndDist(dist);
+
+ const unsigned N = 3;
+ xAx sources[N] = {
+ xAx::fromPoint(A)*(exp(-sliders[0].value())),
+ xAx::fromPoint(B)*(exp(-sliders[1].value())),
+ xAx::fromPoint(C)*(exp(-sliders[2].value()))
+ //xAx::fromLine(Line(A, oncurve.pos))
+ };
+ for(unsigned i = 0; i < N; i++) {
+ //*notify << sources[i] << "\n";
+ }
+ for(unsigned i = 0; i < N; i++) {
+ for(unsigned j = i+1; j < N; j++) {
+ xAx Q = sources[i]-sources[j];
+ *notify << Q << " is a " << Q.categorise() << "\n";
+ }
+ }
+ {
+ cairo_save(cr);
+ cairo_set_source_rgba(cr, 0, 0, 1, 0.5);
+
+ ::draw(cr, (sources[0]-sources[1]), screen_rect);
+ ::draw(cr, (sources[0]-sources[2]), screen_rect);
+ ::draw(cr, (sources[1]-sources[2]), screen_rect);
+ cairo_restore(cr);
+ }
+ {
+ string os;
+ for(unsigned i = 0; i < N; i++) {
+ for(unsigned j = i+1; j < N; j++) {
+ xAx Q = sources[i]-sources[j];
+ Interval iQ = Q.extrema(rh.pos);
+ if(iQ.contains(0)) {
+ os += stringify(iQ) + "\n";
+
+ Q.toCurve(rh.pos);
+ vector<Point> crs = Q.crossings(rh.pos);
+ for(auto & ei : crs) {
+ draw_cross(cr, ei);
+ }
+
+ }
+ }
+ }
+
+ draw_text(cr, rh.pos.midpoint(),
+ os);
+ }
+ if(1) {
+ xAx oxo=sources[0] - sources[2];
+ Timer tm;
+
+ tm.ask_for_timeslice();
+ tm.start();
+
+ std::vector<Point> intrs = intersect(oxo, sources[0] - sources[1]);
+ Timer::Time als_time = tm.lap();
+ *notify << "intersect time = " << als_time << std::endl;
+ for(auto & intr : intrs) {
+ cairo_save(cr);
+ cairo_set_source_rgb(cr, 1, 0,0);
+ draw_cross(cr, intr);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ }
+
+ std::optional<RatQuad> orq = oxo.toCurve(rh.pos);
+ if(orq) {
+ RatQuad rq = *orq;
+ draw_hull(cr, rq);
+ vector<SBasis> hrq = rq.homogeneous();
+ SBasis vertex_poly = (sources[0] - sources[1]).evaluate_at(hrq[0], hrq[1], hrq[2]);
+ //*notify << "\n0: " << hrq[0];
+ //*notify << "\n1: " << hrq[1];
+ //*notify << "\n2: " << hrq[2];
+ vector<double> rts = roots(vertex_poly);
+ //*notify << "\nvertex poly:" << vertex_poly << '\n';
+ for(unsigned i = 0; i < rts.size(); i++) {
+ draw_circ(cr, Point(rq.pointAt(rts[i])));
+ *notify << "\nrq" << i << ":" << rts[i];
+ }
+
+ cairo_save(cr);
+ cairo_set_source_rgb(cr, 1, 0, 0);
+ RatQuad a, b;
+ rq.split(a,b);
+ cairo_curve(cr, a.toCubic());
+ cairo_curve(cr, b.toCubic());
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ }
+ }
+ if(0) {
+ RatQuad a, b;
+ //rq.split(a,b);
+ //cairo_move_to(cr, rq.toCubic().pointAt(0.5));
+ cairo_line_to(cr, a.P[2]);
+ cairo_stroke(cr);
+
+ cairo_curve(cr, a.toCubic());
+ cairo_curve(cr, b.toCubic());
+
+ }
+ cairo_stroke(cr);
+
+ //*notify << "w = " << w << "; lambda = " << rq.lambda() << "\n";
+ Toy::draw(cr, notify, width, height, save, timer_stream);
+ }
+
+public:
+ Conic5() {
+ handles.push_back(&path_handles);
+ handles.push_back(&rh);
+ rh.pos = Rect(Point(100,100), Point(200,200));
+ rh.show_center_handle = true;
+ handles.push_back(&oncurve);
+ for(int j = 0; j < 3; j++){
+ path_handles.push_back(uniform()*400, 100+ uniform()*300);
+ }
+ oncurve.pos = ((path_handles.pts[0]+path_handles.pts[1]+path_handles.pts[2])/3);
+ handles.push_back(&cutting_plane);
+ for(int j = 0; j < 2; j++){
+ cutting_plane.push_back(uniform()*400, 100+ uniform()*300);
+ }
+ sliders.emplace_back(0.0, 5.0, 0, 0.0, "a");
+ sliders.emplace_back(0.0, 5.0, 0, 0.0, "b");
+ sliders.emplace_back(0.0, 5.0, 0, 0.0, "c");
+ handles.push_back(&(sliders[0]));
+ handles.push_back(&(sliders[1]));
+ handles.push_back(&(sliders[2]));
+ sliders[0].geometry(Point(50, 20), 250);
+ sliders[1].geometry(Point(50, 50), 250);
+ sliders[2].geometry(Point(50, 80), 250);
+ }
+
+ void first_time(int /*argc*/, char**/* argv*/) override {
+
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new Conic5());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/conic-6.cpp b/src/3rdparty/2geom/src/toys/conic-6.cpp
new file mode 100644
index 0000000..90da671
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/conic-6.cpp
@@ -0,0 +1,304 @@
+#include <iostream>
+#include <2geom/path.h>
+#include <2geom/svg-path-parser.h>
+#include <2geom/path-intersection.h>
+#include <2geom/basic-intersection.h>
+#include <2geom/pathvector.h>
+#include <2geom/exception.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/path-intersection.h>
+#include <2geom/nearest-time.h>
+#include <2geom/line.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-to-bezier.h>
+
+#include <cstdlib>
+#include <map>
+#include <vector>
+#include <algorithm>
+#include <optional>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/ord.h>
+
+#include <2geom/conicsec.h>
+
+std::vector<Geom::RatQuad> xAx_to_RatQuads(Geom::xAx const &/*C*/, Geom::Rect const &/*bnd*/) {
+ // find points on boundary
+ // if there are exactly 0 points return
+ // if there are exactly 2 points fit ratquad and return
+ // if there are an odd number, split bnd on the point with the smallest dot(unit_vector(grad), rect_edge)
+ // sort into clockwise order ABCD
+ // compute corresponding tangents
+ // test boundary points against the line through A
+ // if all on one side
+ //
+ // if A,X and Y,Z
+ // ratquad from A,X and Y,Z
+ return std::vector<Geom::RatQuad>();
+}
+
+
+
+using namespace Geom;
+using namespace std;
+
+
+// File: convert.h
+#include <sstream>
+#include <stdexcept>
+
+class BadConversion : public std::runtime_error {
+public:
+ BadConversion(const std::string& s)
+ : std::runtime_error(s)
+ { }
+};
+
+template <typename T>
+inline std::string stringify(T x)
+{
+ std::ostringstream o;
+ if (!(o << x))
+ throw BadConversion("stringify(T)");
+ return o.str();
+}
+
+namespace Geom{
+xAx degen;
+};
+
+void draw_hull(cairo_t*cr, RatQuad rq) {
+ cairo_move_to(cr, rq.P[0]);
+ cairo_line_to(cr, rq.P[1]);
+ cairo_line_to(cr, rq.P[2]);
+ cairo_stroke(cr);
+}
+
+
+
+void draw(cairo_t* cr, xAx C, Rect bnd) {
+ if(bnd[1].extent() < 5) return;
+ vector<double> prev_rts;
+ double py = bnd[Y].min();
+ for(int i = 0; i < 100; i++) {
+ double t = i/100.;
+ double y = bnd[Y].valueAt(t);
+ vector<double> rts = C.roots(Point(1, 0), Point(0, y));
+ int top = 0;
+ for(unsigned j = 0; j < rts.size(); j++) {
+ if(bnd[0].contains(rts[j])) {
+ rts[top] = rts[j];
+ top++;
+ }
+ }
+ rts.erase(rts.begin()+top, rts.end());
+
+ if(rts.size() == prev_rts.size()) {
+ for(unsigned j = 0; j < rts.size(); j++) {
+ cairo_move_to(cr, prev_rts[j], py);
+ cairo_line_to(cr, rts[j], y);
+ cairo_stroke(cr);
+ }
+/* } else if(prev_rts.size() == 1) {
+ for(unsigned j = 0; j < rts.size(); j++) {
+ cairo_move_to(cr, prev_rts[0], py);
+ cairo_line_to(cr, rts[j], y);
+ cairo_stroke(cr);
+ }
+ } else if(rts.size() == 1) {
+ for(unsigned j = 0; j < prev_rts.size(); j++) {
+ cairo_move_to(cr, prev_rts[j], py);
+ cairo_line_to(cr, rts[0], y);
+ cairo_stroke(cr);
+ }*/
+ } else {
+ draw(cr, C, Rect(bnd[0], Interval(py, y)));
+ /*for(unsigned j = 0; j < rts.size(); j++) {
+ cairo_move_to(cr, rts[j], y);
+ cairo_rel_line_to(cr, 1,1);
+ }*/
+ }
+ prev_rts = rts;
+ py = y;
+ }
+}
+
+template <typename T>
+static T det(T a, T b, T c, T d) {
+ return a*d - b*c;
+}
+
+template <typename T>
+static T det(T M[2][2]) {
+ return M[0][0]*M[1][1] - M[1][0]*M[0][1];
+}
+
+template <typename T>
+static T det3(T M[3][3]) {
+ return ( M[0][0] * det(M[1][1], M[1][2],
+ M[2][1], M[2][2])
+ -M[1][0] * det(M[0][1], M[0][2],
+ M[2][1], M[2][2])
+ +M[2][0] * det(M[0][1], M[0][2],
+ M[1][1], M[1][2]));
+}
+
+class Conic6: public Toy {
+ PointSetHandle C1H, C2H;
+ std::vector<Slider> sliders;
+ Point mouse_sampler;
+
+ void mouse_moved(GdkEventMotion* e) override {
+ mouse_sampler = Point(e->x, e->y);
+ Toy::mouse_moved(e);
+ }
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_source_rgba (cr, 0., 0., 0, 1);
+ cairo_set_line_width (cr, 1);
+ Rect screen_rect(Interval(10, width-10), Interval(10, height-10));
+
+ Geom::xAx C1 = xAx::fromPoints(C1H.pts);
+ ::draw(cr, C1, screen_rect);
+ *notify << C1;
+
+ Geom::xAx C2 = xAx::fromPoints(C2H.pts);
+ ::draw(cr, C2, screen_rect);
+ *notify << C2;
+
+
+ SBasis T(Linear(-1,1));
+ SBasis S(Linear(1,1));
+ SBasis C[3][3] = {{T*C1.c[0]+S*C2.c[0], (T*C1.c[1]+S*C2.c[1])/2, (T*C1.c[3]+S*C2.c[3])/2},
+ {(T*C1.c[1]+S*C2.c[1])/2, T*C1.c[2]+S*C2.c[2], (T*C1.c[4]+S*C2.c[4])/2},
+ {(T*C1.c[3]+S*C2.c[3])/2, (T*C1.c[4]+S*C2.c[4])/2, T*C1.c[5]+S*C2.c[5]}};
+
+ SBasis D = det3(C);
+ std::vector<double> rts = Geom::roots(D);
+ if(rts.empty()) {
+ T = Linear(1,1);
+ S = Linear(-1,1);
+ SBasis C[3][3] = {{T*C1.c[0]+S*C2.c[0], (T*C1.c[1]+S*C2.c[1])/2, (T*C1.c[3]+S*C2.c[3])/2},
+ {(T*C1.c[1]+S*C2.c[1])/2, T*C1.c[2]+S*C2.c[2], (T*C1.c[4]+S*C2.c[4])/2},
+ {(T*C1.c[3]+S*C2.c[3])/2, (T*C1.c[4]+S*C2.c[4])/2, T*C1.c[5]+S*C2.c[5]}};
+
+ D = det3(C);
+ rts = Geom::roots(D);
+ }
+ // at this point we have a T and S and perhaps some roots that represent our degenerate conic
+ // Let's just pick one randomly (can we do better?)
+ //for(unsigned i = 0; i < rts.size(); i++) {
+ if(!rts.empty()) {
+ cairo_save(cr);
+
+ unsigned i = 0;
+ double t = T.valueAt(rts[i]);
+ double s = S.valueAt(rts[i]);
+ *notify << t << "; " << s << std::endl;
+ /*double C0[3][3] = {{t*C1.c[0]+s*C2.c[0], (t*C1.c[1]+s*C2.c[1])/2, (t*C1.c[3]+s*C2.c[3])/2},
+ {(t*C1.c[1]+s*C2.c[1])/2, t*C1.c[2]+s*C2.c[2], (t*C1.c[4]+s*C2.c[4])/2},
+ {(t*C1.c[3]+s*C2.c[3])/2, (t*C1.c[4]+s*C2.c[4])/2, t*C1.c[5]+s*C2.c[5]}};*/
+ xAx xC0 = C1*t + C2*s;
+ //::draw(cr, xC0, screen_rect); // degen
+
+ std::optional<Point> oB0 = xC0.bottom();
+
+ Point B0 = *oB0;
+ //*notify << B0 << " = " << C1.gradient(B0);
+ draw_circ(cr, B0);
+
+ Point n0, n1;
+ // Are these just the eigenvectors of A11?
+ if(fabs(xC0.c[0]) > fabs(xC0.c[2])) {
+ double b = 0.5*xC0.c[1]/xC0.c[0];
+ double c = xC0.c[2]/xC0.c[0];
+ double d = std::sqrt(b*b-c);
+ n0 = Point(1, b+d);
+ n1 = Point(1, b-d);
+ } else {
+
+ double b = 0.5*xC0.c[1]/xC0.c[2];
+ double c = xC0.c[0]/xC0.c[2];
+ double d = std::sqrt(b*b-c);
+ n0 = Point(b+d, 1);
+ n1 = Point(b-d, 1);
+ }
+ cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
+
+ Line L0 = Line::from_origin_and_vector(B0, rot90(n0));
+ draw_line(cr, L0, screen_rect);
+ Line L1 = Line::from_origin_and_vector(B0, rot90(n1));
+ draw_line(cr, L1, screen_rect);
+
+ cairo_set_source_rgb(cr, 1, 0., 0.);
+ rts = C1.roots(L0);
+ for(double rt : rts) {
+ Point P = L0.pointAt(rt);
+ draw_cross(cr, P);
+ *notify << C1.valueAt(P) << "; " << C2.valueAt(P) << "\n";
+ }
+ rts = C1.roots(L1);
+ for(double rt : rts) {
+ Point P = L1.pointAt(rt);
+ draw_cross(cr, P);
+ *notify << C1.valueAt(P) << "; "<< C2.valueAt(P) << "\n";
+ }
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ }
+
+ ::draw(cr, C1*sliders[0].value() + C2*sliders[1].value(), screen_rect);
+
+ std::vector<Point> res = intersect(C1, C2);
+ for(auto & re : res) {
+ draw_circ(cr, re);
+ }
+
+ cairo_stroke(cr);
+
+ //*notify << "w = " << w << "; lambda = " << rq.lambda() << "\n";
+ Toy::draw(cr, notify, width, height, save, timer_stream);
+ }
+
+public:
+ Conic6() {
+ for(int j = 0; j < 5; j++){
+ C1H.push_back(uniform()*400, 100+ uniform()*300);
+ C2H.push_back(uniform()*400, 100+ uniform()*300);
+ }
+ handles.push_back(&C1H);
+ handles.push_back(&C2H);
+ sliders.emplace_back(-1.0, 1.0, 0, 0.0, "a");
+ sliders.emplace_back(-1.0, 1.0, 0, 0.0, "b");
+ sliders.emplace_back(0.0, 5.0, 0, 0.0, "c");
+ handles.push_back(&(sliders[0]));
+ handles.push_back(&(sliders[1]));
+ handles.push_back(&(sliders[2]));
+ sliders[0].geometry(Point(50, 20), 250);
+ sliders[1].geometry(Point(50, 50), 250);
+ sliders[2].geometry(Point(50, 80), 250);
+ }
+
+ void first_time(int /*argc*/, char**/* argv*/) override {
+
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new Conic6());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/conic-section-toy.cpp b/src/3rdparty/2geom/src/toys/conic-section-toy.cpp
new file mode 100644
index 0000000..31695be
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/conic-section-toy.cpp
@@ -0,0 +1,813 @@
+/*
+ * Conic Section Toy
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2009 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+//#define CLIP_WITH_CAIRO_SUPPORT
+#ifdef CLIP_WITH_CAIRO_SUPPORT
+ #include <2geom/conic_section_clipper_cr.h>
+#endif
+
+
+#include <2geom/conicsec.h>
+#include <2geom/line.h>
+
+//#include <iomanip>
+#include <optional>
+
+
+using namespace Geom;
+
+
+class ConicSectionToy : public Toy
+{
+ enum menu_item_t
+ {
+ SHOW_MENU = 0,
+ TEST_VERTEX_FOCI,
+ TEST_FITTING,
+ TEST_ECCENTRICITY,
+ TEST_DEGENERATE,
+ TEST_ROOTS,
+ TEST_NEAREST_POINT,
+ TEST_BOUND,
+ TEST_CLIP,
+ TEST_TANGENT,
+ TEST_DUAL,
+ TOTAL_ITEMS // this one must be the last item
+ };
+
+ static const char* menu_items[TOTAL_ITEMS];
+ static const char keys[TOTAL_ITEMS];
+
+ void first_time(int /*argc*/, char** /*argv*/) override
+ {
+ draw_f = &ConicSectionToy::draw_menu;
+ }
+
+
+ void init_common()
+ {
+ init_vertex_foci();
+ set_control_geometry = true;
+ }
+
+ void draw_common (cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save,
+ std::ostringstream * timer_stream)
+ {
+ draw_vertex_foci(cr, notify, width, height, save, timer_stream);
+ }
+
+
+/*
+ * TEST VERTEX FOCI
+ */
+ void init_vertex_foci()
+ {
+ set_common_control_geometry = true;
+ handles.clear();
+
+ focus1.pos = Point(300, 300);
+ focus2.pos = Point(500, 300);
+ vertex.pos = Point(200, 300);
+
+ parabola_toggle = Toggle("set/unset F2 to infinity", false);
+
+ handles.push_back (&vertex);
+ handles.push_back (&focus1);
+ handles.push_back (&focus2);
+ handles.push_back (&parabola_toggle);
+ }
+
+ void draw_vertex_foci (cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool /*save*/,
+ std::ostringstream * /*timer_stream*/)
+ {
+ init_vertex_foci_ctrl_geom(cr, notify, width, height);
+
+
+ if (!parabola_toggle.on )
+ {
+ if (focus2.pos == Point(infinity(),infinity()))
+ focus2.pos = Point(m_width/2, m_height/2);
+ double df1f2 = distance (focus1.pos, focus2.pos);
+ if (df1f2 > 20 )
+ {
+ Line axis(focus1.pos,focus2.pos);
+ vertex.pos = projection (vertex.pos, axis);
+ }
+ else if (df1f2 > 1)
+ {
+ Line axis(focus1.pos,vertex.pos);
+ focus2.pos = projection (focus2.pos, axis);
+ }
+ else
+ {
+ Line axis(focus1.pos,vertex.pos);
+ focus2.pos = focus1.pos;
+ }
+ }
+ else
+ {
+ focus2.pos = Point(infinity(),infinity());
+ }
+
+ cs.set (vertex.pos, focus1.pos, focus2.pos);
+ cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, 1.0);
+ cairo_set_line_width (cr, 0.5);
+ draw (cr, cs, m_window);
+ cairo_stroke(cr);
+
+ draw_label(cr, focus1, "F1");
+ if (!parabola_toggle.on) draw_label(cr, focus2, "F2");
+ draw_label(cr, vertex, "V");
+ cairo_stroke(cr);
+
+ *notify << cs.categorise() << ": " << cs << std::endl;
+ }
+
+ void init_vertex_foci_ctrl_geom (cairo_t* /*cr*/,
+ std::ostringstream* /*notify*/,
+ int width, int /*height*/)
+ {
+ if ( set_common_control_geometry )
+ {
+ set_common_control_geometry = false;
+
+ Point toggle_sp( width - 200, 10);
+ parabola_toggle.bounds = Rect (toggle_sp, toggle_sp + Point(190,30));
+ }
+ }
+
+
+/*
+ * TEST FITTING
+ */
+ void init_fitting()
+ {
+ set_common_control_geometry = true;
+ handles.clear();
+
+ psh.pts.resize(5);
+ psh.pts[0] = Point(450, 250);
+ psh.pts[1] = Point(250, 100);
+ psh.pts[2] = Point(250, 400);
+ psh.pts[3] = Point(400, 320);
+ psh.pts[4] = Point(50, 250);
+
+ fitting_slider.set (0, 5, 1, 0, "more handles");
+
+ handles.push_back(&psh);
+ handles.push_back(&fitting_slider);
+ }
+
+ void draw_fitting (cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool /*save*/,
+ std::ostringstream * /*timer_stream*/)
+ {
+ init_fitting_ctrl_geom(cr, notify, width, height);
+
+ size_t n = (size_t)(fitting_slider.value()) + 5;
+ if (n < psh.pts.size())
+ {
+ psh.pts.resize(n);
+ }
+ else if (n > psh.pts.size())
+ {
+ psh.push_back (std::fabs (width - 100) * uniform() + 50,
+ std::fabs (height - 100) * uniform() + 50);
+ }
+
+ cs.set (psh.pts);
+
+ cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, 1.0);
+ cairo_set_line_width (cr, 0.5);
+ draw (cr, cs, m_window);
+ cairo_stroke(cr);
+ *notify << cs.categorise() << ": " << cs << std::endl;
+ }
+
+ void init_fitting_ctrl_geom (cairo_t* /*cr*/,
+ std::ostringstream* /*notify*/,
+ int /*width*/, int height)
+ {
+ if ( set_common_control_geometry )
+ {
+ set_common_control_geometry = false;
+ fitting_slider.geometry (Point(50, height - 50), 100);
+ }
+ }
+
+
+/*
+ * TEST ECCENTRICITY
+ */
+ void init_eccentricity()
+ {
+ set_common_control_geometry = true;
+ handles.clear();
+
+ p1 = Point (100, 100);
+ p2 = Point (100, 400);
+ focus1 = Point (300, 250);
+
+ eccentricity_slider.set (0, 3, 0, 1, "eccentricity");
+
+ handles.push_back (&p1);
+ handles.push_back (&p2);
+ handles.push_back (&focus1);
+ handles.push_back (&eccentricity_slider);
+ }
+
+ void draw_eccentricity (cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool /*save*/,
+ std::ostringstream * /*timer_stream*/)
+ {
+ init_eccentricity_ctrl_geom(cr, notify, width, height);
+
+ Line directrix (p1.pos, p2.pos);
+
+ cs.set (focus1.pos, directrix, eccentricity_slider.value());
+
+ cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, 1.0);
+ cairo_set_line_width (cr, 0.5);
+ draw (cr, cs, m_window);
+ cairo_stroke(cr);
+
+ draw_label (cr, focus1, "F");
+ draw_line (cr, directrix, m_window);
+ draw_label(cr, p1, "directrix");
+ cairo_stroke(cr);
+
+ *notify << cs.categorise() << ": " << cs << std::endl;
+ }
+
+ void init_eccentricity_ctrl_geom (cairo_t* /*cr*/,
+ std::ostringstream* /*notify*/,
+ int /*width*/, int height)
+ {
+ if ( set_common_control_geometry )
+ {
+ set_common_control_geometry = false;
+ eccentricity_slider.geometry (Point (10, height - 50), 300);
+ }
+ }
+
+
+
+/*
+ * TEST DEGENERATE
+ */
+ void init_degenerate()
+ {
+ set_common_control_geometry = true;
+ handles.clear();
+
+ psh.pts.resize(4);
+ psh.pts[0] = Point(450, 250);
+ psh.pts[1] = Point(250, 100);
+ psh.pts[2] = Point(250, 400);
+ psh.pts[3] = Point(400, 320);
+
+
+
+ handles.push_back(&psh);
+ }
+
+ void draw_degenerate (cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool /*save*/,
+ std::ostringstream * /*timer_stream*/)
+ {
+ init_degenerate_ctrl_geom(cr, notify, width, height);
+
+ Line l1 (psh.pts[0], psh.pts[1]);
+ Line l2 (psh.pts[2], psh.pts[3]);
+ cs.set (l1, l2);
+ cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, 1.0);
+ cairo_set_line_width (cr, 0.5);
+ draw (cr, cs, m_window);
+ cairo_stroke(cr);
+
+ *notify << cs.categorise() << ": " << cs << std::endl;
+ }
+
+ void init_degenerate_ctrl_geom (cairo_t* /*cr*/,
+ std::ostringstream* /*notify*/,
+ int /*width*/, int /*height*/)
+ {
+ if ( set_common_control_geometry )
+ {
+ set_common_control_geometry = false;
+ }
+ }
+
+
+/*
+ * TEST ROOTS
+ */
+ void init_roots()
+ {
+ init_common();
+
+ p1.pos = Point(180, 50);
+
+ x_y_toggle = Toggle("X/Y roots", true);
+
+ handles.push_back(&p1);
+ handles.push_back(&x_y_toggle);
+ }
+
+ void draw_roots (cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save,
+ std::ostringstream * timer_stream)
+ {
+ draw_common(cr, notify, width, height, save, timer_stream);
+ init_roots_ctrl_geom(cr, notify, width, height);
+
+
+ Dim2 DIM = x_y_toggle.on ? X : Y;
+ Line l(p1.pos, DIM * (-M_PI/2) + M_PI/2);
+
+ cairo_set_line_width(cr, 0.2);
+ cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, 1.0);
+ draw_line(cr, l, m_window);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba(cr, 0.8, 0.0, 0.0, 1.0);
+ std::vector<double> values;
+ try
+ {
+ cs.roots(values, p1.pos[DIM], DIM);
+ }
+ catch(Geom::Exception e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+ for (double value : values)
+ {
+ Point p(value, value);
+ p[DIM] = p1.pos[DIM];
+ draw_handle(cr, p);
+ }
+ cairo_stroke(cr);
+
+ *notify << " ";
+ for ( unsigned int i = 0; i < values.size(); ++i )
+ {
+ *notify << "v" << i << " = " << values[i] << " ";
+ }
+ }
+
+ void init_roots_ctrl_geom (cairo_t* /*cr*/, std::ostringstream* /*notify*/,
+ int width, int height)
+ {
+ if ( set_control_geometry )
+ {
+ set_control_geometry = false;
+
+ Point T(width - 120, height - 60);
+ x_y_toggle.bounds = Rect( T, T + Point(100,25) );
+ }
+ }
+
+/*
+ * TEST NEAREST POINT
+ */
+
+ void init_nearest_time()
+ {
+ init_common();
+ p1.pos = Point(180, 50);
+ handles.push_back(&p1);
+ }
+
+ void draw_nearest_time (cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save,
+ std::ostringstream * timer_stream)
+ {
+ draw_common(cr, notify, width, height, save, timer_stream);
+
+ Point P;
+ try
+ {
+ P = cs.nearestTime (p1.pos);
+ }
+ catch (LogicalError e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+
+
+ cairo_set_source_rgba(cr, 0.8, 0.1, 0.1, 1.0);
+ draw_line_seg(cr, p1.pos, P);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba(cr, 0.1, 0.1, 0.9, 1.0);
+ draw_handle(cr, P);
+ cairo_stroke(cr);
+ cairo_set_source_rgba(cr, 0.1, 0.1, 0.1, 1.0);
+ draw_label(cr, p1, "Q");
+ draw_text(cr, P + Point(5, 5), "P");
+ cairo_stroke(cr);
+ }
+
+/*
+ * TEST BOUND
+ */
+ void init_bound()
+ {
+ init_common();
+ p1.pos = Point(50, 200);
+ p2.pos = Point(50, 400);
+ p3.pos = Point(50, 500);
+ handles.push_back(&p1);
+ handles.push_back(&p2);
+ handles.push_back(&p3);
+ }
+
+ void draw_bound (cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save,
+ std::ostringstream * timer_stream)
+ {
+ draw_common(cr, notify, width, height, save, timer_stream);
+
+ try
+ {
+ p1.pos = cs.nearestTime (p1.pos);
+ p2.pos = cs.nearestTime (p2.pos);
+ p3.pos = cs.nearestTime (p3.pos);
+ }
+ catch (LogicalError e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+
+ Rect bound = cs.arc_bound (p1.pos, p2.pos, p3.pos);
+ cairo_set_source_rgba(cr, 0.8, 0.1, 0.1, 1.0);
+ cairo_set_line_width (cr, 0.5);
+ cairo_rectangle (cr, bound);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba(cr, 0.1, 0.1, 0.1, 1.0);
+ draw_label (cr, p1, "initial");
+ draw_label (cr, p2, "inner");
+ draw_label (cr, p3, "final");
+ cairo_stroke(cr);
+
+ }
+
+/*
+ * TEST CLIP
+ */
+ void init_clip()
+ {
+ init_common();
+ }
+
+ void draw_clip (cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save,
+ std::ostringstream * timer_stream)
+ {
+ draw_common(cr, notify, width, height, save, timer_stream);
+ //init_clip_ctrl_geom(cr, notify, width, height);
+
+
+ Rect R(Point (100, 100),Point (width-100, height-100));
+ std::vector<RatQuad> rq;
+#ifdef CLIP_WITH_CAIRO_SUPPORT
+ clipper_cr aclipper(cr, cs, R);
+ aclipper.clip (rq);
+#else
+ clip (rq, cs, R);
+#endif
+ cairo_set_source_rgba(cr, 0.8, 0.1, 0.1, 1.0);
+ cairo_set_line_width (cr, 0.5);
+ cairo_rectangle (cr, Rect (Point (100, 100),Point (width-100, height-100)));
+ for (auto & i : rq)
+ {
+ cairo_d2_sb (cr, i.toCubic().toSBasis());
+ }
+ cairo_stroke(cr);
+ }
+
+/*
+ * TEST TANGENT
+ */
+ void init_tangent()
+ {
+ init_common();
+
+ p1.pos = Point(180, 50);
+
+ handles.push_back(&p1);
+ }
+
+ void draw_tangent (cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save,
+ std::ostringstream * timer_stream)
+ {
+ draw_common(cr, notify, width, height, save, timer_stream);
+
+ p1.pos = cs.nearestTime (p1.pos);
+ Line l = cs.tangent(p1.pos);
+
+ draw_label (cr, p1, "P");
+ cairo_set_source_rgba(cr, 0.8, 0.0, 0.0, 1.0);
+ draw_line(cr, l, m_window);
+ cairo_stroke(cr);
+ }
+
+/*
+ * TEST DUAL
+ */
+ void init_dual()
+ {
+ init_common();
+ }
+
+ void draw_dual (cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save,
+ std::ostringstream * timer_stream)
+ {
+ draw_common(cr, notify, width, height, save, timer_stream);
+
+ cairo_set_source_rgba(cr, 0.8, 0.0, 0.0, 1.0);
+ xAx dc = cs.dual();
+ // we need some trick to make the dual visible in the window
+ std::string dckind = dc.categorise();
+ std::optional<Point> T = dc.centre();
+ if (T) dc = dc.translate (-*T);
+ dc = dc.scale (1e-5, 1e-5);
+ dc = dc.translate (Point(width/2, height/2));
+ draw (cr, dc, m_window);
+ cairo_stroke(cr);
+ *notify << "\n dual: " << dckind << ": " << dc;
+ }
+
+
+ void draw_segment (cairo_t* cr, Point const& p1, Point const& p2)
+ {
+ cairo_move_to(cr, p1);
+ cairo_line_to(cr, p2);
+ }
+
+ void draw (cairo_t* cr, xAx const& cs, const Rect& _window)
+ {
+
+ // offset
+ //Point O(400, 300);
+ Point O(0, 0);
+ std::vector<double> r1, r2;
+
+ size_t N = (size_t)(2 *_window.width());
+ double dx = 0.5;//width / N;
+ //std::cout << "dx = " << dx << std::endl;
+ double x = _window.left() - O[X];
+ for (size_t i = 0; i < N; ++i, x += dx)
+ {
+ if (r1.empty())
+ {
+ cs.roots(r1, x, X);
+ if (r1.size() == 1)
+ {
+ r1.push_back(r1.front());
+ }
+ if (i != 0 && r1.size() == 2)
+ {
+ Point p1(x-dx, r1[0]);
+ Point p2(x-dx, r1[1]);
+ p1 += O; p2 += O;
+ if (_window.contains(p1) && _window.contains(p2))
+ draw_segment(cr, p1, p2);
+ }
+ continue;
+ }
+ cs.roots(r2, x, X);
+ if (r2.empty())
+ {
+ Point p1(x-dx, r1[0]);
+ Point p2(x-dx, r1[1]);
+ p1 += O; p2 += O;
+ if (_window.contains(p1) && _window.contains(p2))
+ draw_segment(cr, p1, p2);
+ r1.clear();
+ continue;
+ }
+ if (r2.size() == 1)
+ {
+ r2.push_back(r2.front());
+ }
+
+ Point p1(x-dx, r1[0]);
+ Point p2(x, r2[0]);
+ p1 += O; p2 += O;
+ if (_window.contains(p1) && _window.contains(p2))
+ draw_segment(cr, p1, p2);
+
+ p1 = Point(x-dx, r1[1]) + O;
+ p2 = Point(x, r2[1]) + O;
+ if (_window.contains(p1) && _window.contains(p2))
+ draw_segment(cr, p1, p2);
+
+ using std::swap;
+ swap(r1, r2);
+ }
+ }
+
+ void draw_label(cairo_t* cr, PointHandle const& ph, const char* label)
+ {
+ draw_text(cr, ph.pos+op, label);
+ }
+
+// void draw_label(cairo_t* cr, Line const& l, const char* label)
+// {
+// draw_text(cr, projection(Point(m_width/2-30, m_height/2-30), l)+op, label);
+// }
+
+ void init_menu()
+ {
+ handles.clear();
+ }
+
+ void draw_menu( cairo_t * /*cr*/, std::ostringstream *notify,
+ int /*width*/, int /*height*/, bool /*save*/,
+ std::ostringstream */*timer_stream*/ )
+ {
+ *notify << std::endl;
+ for (int i = SHOW_MENU; i < TOTAL_ITEMS; ++i)
+ {
+ *notify << " " << keys[i] << " - " << menu_items[i] << std::endl;
+ }
+ }
+
+
+ void key_hit(GdkEventKey *e) override
+ {
+ char choice = std::toupper(e->keyval);
+ switch ( choice )
+ {
+ case 'A':
+ init_menu();
+ draw_f = &ConicSectionToy::draw_menu;
+ break;
+ case 'B':
+ init_common();
+ draw_f = &ConicSectionToy::draw_vertex_foci;
+ break;
+ case 'C':
+ init_fitting();
+ draw_f = &ConicSectionToy::draw_fitting;
+ break;
+ case 'D':
+ init_eccentricity();
+ draw_f = &ConicSectionToy::draw_eccentricity;
+ break;
+ case 'E':
+ init_degenerate();
+ draw_f = &ConicSectionToy::draw_degenerate;
+ break;
+ case 'F':
+ init_roots();
+ draw_f = &ConicSectionToy::draw_roots;
+ break;
+ case 'G':
+ init_nearest_time();
+ draw_f = &ConicSectionToy::draw_nearest_time;
+ break;
+ case 'H':
+ init_bound();
+ draw_f = &ConicSectionToy::draw_bound;
+ break;
+ case 'K':
+ init_clip();
+ draw_f = &ConicSectionToy::draw_clip;
+ break;
+ case 'J':
+ init_tangent();
+ draw_f = &ConicSectionToy::draw_tangent;
+ break;
+ case 'I':
+ init_dual();
+ draw_f = &ConicSectionToy::draw_dual;
+ break;
+
+ }
+ redraw();
+ }
+
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save,
+ std::ostringstream *timer_stream ) override
+ {
+ if (timer_stream == 0) timer_stream = notify;
+ m_width = width;
+ m_height = height;
+ m_length = (m_width > m_height) ? m_width : m_height;
+ m_length *= 2;
+ m_window = Rect (Point (0, 0), Point (m_width, m_height));
+ (this->*draw_f)(cr, notify, width, height, save, timer_stream);
+ Toy::draw(cr, notify, width, height, save, timer_stream);
+ }
+
+public:
+ ConicSectionToy()
+ {
+ op = Point(5,5);
+ }
+
+private:
+ typedef void (ConicSectionToy::* draw_func_t) (cairo_t*, std::ostringstream*, int, int, bool, std::ostringstream*);
+ draw_func_t draw_f;
+ bool set_common_control_geometry;
+ bool set_control_geometry;
+ Point op;
+ double m_width, m_height, m_length;
+ Rect m_window;
+
+ xAx cs;
+ PointHandle vertex, focus1, focus2;
+ Toggle parabola_toggle;
+
+ PointSetHandle psh;
+ Slider fitting_slider;
+
+ PointHandle p1, p2, p3;
+ Toggle x_y_toggle;
+
+ Slider eccentricity_slider;
+};
+
+
+const char* ConicSectionToy::menu_items[] =
+{
+ "show this menu",
+ "vertex and foci",
+ "fitting",
+ "eccentricity",
+ "degenerate",
+ "roots",
+ "nearest point",
+ "bound",
+ "clip",
+ "tangent",
+ "dual"
+};
+
+const char ConicSectionToy::keys[] =
+{
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'K', 'J', 'I'
+};
+
+
+int main(int argc, char **argv)
+{
+ //std::cout.precision(20);
+ init( argc, argv, new ConicSectionToy(), 800, 600 );
+ return 0;
+}
+
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/convole.cpp b/src/3rdparty/2geom/src/toys/convole.cpp
new file mode 100644
index 0000000..5f76cbc
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/convole.cpp
@@ -0,0 +1,352 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-geometric.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <2geom/orphan-code/sbasis-of.h>
+
+#include <vector>
+using std::vector;
+using namespace Geom;
+
+SBasis toSBasis(SBasisOf<double> const &f){
+ SBasis result(f.size(), Linear());
+ for (unsigned i=0; i<f.size(); i++){
+ result[i] = Linear(f[i][0],f[i][1]);
+ }
+ return result;
+}
+SBasisOf<double> toSBasisOfDouble(SBasis const &f){
+ SBasisOf<double> result;
+ for (auto i : f){
+ result.push_back(LinearOf<double>(i[0],i[1]));
+ }
+ return result;
+}
+
+
+
+SBasis integral(SBasis const &c) {
+ SBasis a;
+ a.resize(c.size() + 1, Linear(0,0));
+ a[0] = Linear(0,0);
+
+ for(unsigned k = 1; k < c.size() + 1; k++) {
+ double ahat = -c[k-1].tri()/(2*k);
+ a[k][0] = a[k][1] = ahat;
+ }
+ double aTri = 0;
+ for(int k = c.size()-1; k >= 0; k--) {
+ aTri = (c[k].hat() + (k+1)*aTri/2)/(2*k+1);
+ a[k][0] -= aTri/2;
+ a[k][1] += aTri/2;
+ }
+ a.normalize();
+ return a;
+}
+template<typename T>
+SBasisOf<T> integraaal(SBasisOf<T> const &c){
+ SBasisOf<T> a;
+ a.resize(c.size() + 1, LinearOf<T>(T(0.),T(0.)));
+
+ for(unsigned k = 1; k < c.size() + 1; k++) {
+ T ahat = (c[k-1][0]-c[k-1][1])/(2*k);
+ a[k] = LinearOf<T>(ahat);
+ }
+
+ T aTri = T(0.);
+ for(int k = c.size()-1; k >= 0; k--) {
+ aTri = (HatOf<T>(c[k]).d + (k+1)*aTri/2)/(2*k+1);
+ a[k][0] -= aTri/2;
+ a[k][1] += aTri/2;
+ }
+ //a.normalize();
+ return a;
+}
+
+SBasisOf<SBasisOf<double> > integral(SBasisOf<SBasisOf<double> > const &f, unsigned var){
+ //variable of f = 1, variable of f's coefficients = 0.
+ if (var == 1) return integraaal(f);
+ SBasisOf<SBasisOf<double> > result;
+ for(unsigned i = 0; i< f.size(); i++) {
+ //result.push_back(LinearOf<SBasisOf<double> >( integral(f[i][0]),integral(f[i][1])));
+ result.push_back(LinearOf<SBasisOf<double> >( integraaal(f[i][0]),integraaal(f[i][1])));
+ }
+ return result;
+}
+
+template <typename T>
+SBasisOf<T> multi_compose(SBasisOf<double> const &f, SBasisOf<T> const &g ){
+
+ //assert( f.input_dim() <= g.size() );
+
+ SBasisOf<T> u1 = g;
+ SBasisOf<T> u0 = -g + LinearOf<SBasisOf<double> >(SBasisOf<double>(LinearOf<double>(1,1)));
+ SBasisOf<T> s = multiply(u0,u1);
+ SBasisOf<T> r;
+
+ for(int i = f.size()-1; i >= 0; i--) {
+ r = s*r + f[i][0]*u0 + f[i][1]*u1;
+ }
+ return r;
+}
+
+SBasisOf<double> compose(SBasisOf<SBasisOf<double> > const &f,
+ SBasisOf<double> const &x,
+ SBasisOf<double> const &y){
+ SBasisOf<double> y0 = -y + LinearOf<double>(1,1);
+ SBasisOf<double> s = multiply(y0,y);
+ SBasisOf<double> r;
+
+ for(int i = f.size()-1; i >= 0; i--) {
+ r = s*r + compose(f[i][0],x)*y0 + compose(f[i][1],x)*y;
+ }
+ return r;
+}
+
+Piecewise<SBasis> convole(SBasisOf<double> const &f, Interval dom_f,
+ SBasisOf<double> const &g, Interval dom_g,
+ bool f_cst_ends = false){
+
+ if ( dom_f.extent() < dom_g.extent() ) return convole(g, dom_g, f, dom_f);
+
+ Piecewise<SBasis> result;
+
+ SBasisOf<SBasisOf<double> > u,v;
+ u.push_back(LinearOf<SBasisOf<double> >(SBasisOf<double>(LinearOf<double>(0,1))));
+ v.push_back(LinearOf<SBasisOf<double> >(SBasisOf<double>(LinearOf<double>(0,0)),
+ SBasisOf<double>(LinearOf<double>(1,1))));
+ SBasisOf<SBasisOf<double> > v_u = (v - u)*(dom_f.extent()/dom_g.extent());
+ v_u += SBasisOf<SBasisOf<double> >(SBasisOf<double>(-dom_g.min()/dom_g.extent()));
+ SBasisOf<SBasisOf<double> > gg = multi_compose(g,v_u);
+ SBasisOf<SBasisOf<double> > ff = SBasisOf<SBasisOf<double> >(f);
+ SBasisOf<SBasisOf<double> > hh = integral(ff*gg,0);
+
+ result.cuts.push_back(dom_f.min()+dom_g.min());
+ //Note: we know dom_f.extent() >= dom_g.extent()!!
+ //double rho = dom_f.extent()/dom_g.extent();
+ double t0 = dom_g.min()/dom_f.extent();
+ double t1 = dom_g.max()/dom_f.extent();
+ double t2 = t0+1;
+ double t3 = t1+1;
+ SBasisOf<double> a,b,t;
+ SBasis seg;
+ a = SBasisOf<double>(LinearOf<double>(0,0));
+ b = SBasisOf<double>(LinearOf<double>(0,t1-t0));
+ t = SBasisOf<double>(LinearOf<double>(t0,t1));
+ seg = toSBasis(compose(hh,b,t)-compose(hh,a,t));
+ result.push(seg,dom_f.min() + dom_g.max());
+ if (dom_f.extent() > dom_g.extent()){
+ a = SBasisOf<double>(LinearOf<double>(0,t2-t1));
+ b = SBasisOf<double>(LinearOf<double>(t1-t0,1));
+ t = SBasisOf<double>(LinearOf<double>(t1,t2));
+ seg = toSBasis(compose(hh,b,t)-compose(hh,a,t));
+ result.push(seg,dom_f.max() + dom_g.min());
+ }
+ a = SBasisOf<double>(LinearOf<double>(t2-t1,1.));
+ b = SBasisOf<double>(LinearOf<double>(1.,1.));
+ t = SBasisOf<double>(LinearOf<double>(t2,t3));
+ seg = toSBasis(compose(hh,b,t)-compose(hh,a,t));
+ result.push(seg,dom_f.max() + dom_g.max());
+ result*=dom_f.extent();
+
+ //--constant ends correction--------------
+ if (f_cst_ends){
+ SBasis ig = toSBasis(integraaal(g))*dom_g.extent();
+ ig -= ig.at0();
+ Piecewise<SBasis> cor;
+ cor.cuts.push_back(dom_f.min()+dom_g.min());
+ cor.push(reverse(ig)*f.at0(),dom_f.min()+dom_g.max());
+ cor.push(Linear(0),dom_f.max()+dom_g.min());
+ cor.push(ig*f.at1(),dom_f.max()+dom_g.max());
+ result+=cor;
+ }
+ //----------------------------------------
+ return result;
+}
+
+/*static void dot_plot(cairo_t *cr, Piecewise<D2<SBasis> > const &M, double space=10){
+ //double dt=(M[0].cuts.back()-M[0].cuts.front())/space;
+ Piecewise<D2<SBasis> > Mperp = rot90(derivative(M)) * 2;
+ for( double t = M.cuts.front(); t < M.cuts.back(); t += space) {
+ Point pos = M(t), perp = Mperp(t);
+ draw_line_seg(cr, pos + perp, pos - perp);
+ }
+ cairo_pw_d2_sb(cr, M);
+ cairo_stroke(cr);
+ }*/
+
+static void plot_graph(cairo_t *cr, Piecewise<SBasis> const &f,
+ double x_scale=300,
+ double y_scale=100){
+ //double dt=(M[0].cuts.back()-M[0].cuts.front())/space;
+ D2<Piecewise<SBasis> > g;
+ g[X] = Piecewise<SBasis>( SBasis(Linear(100+f.cuts.front()*x_scale,
+ 100+f.cuts.back()*x_scale)));
+ g[X].setDomain(f.domain());
+ g[Y] = -f*y_scale+400;
+ cairo_d2_pw_sb(cr, g);
+}
+
+struct Frame
+{
+ Geom::Point O;
+ Geom::Point x;
+ Geom::Point y;
+ Geom::Point z;
+};
+
+void
+plot3d(cairo_t *cr, SBasis const &x, SBasis const &y, SBasis const &z, Frame frame){
+ D2<SBasis> curve;
+ for (unsigned dim=0; dim<2; dim++){
+ curve[dim] = x*frame.x[dim] + y*frame.y[dim] + z*frame.z[dim];
+ curve[dim] += frame.O[dim];
+ }
+ cairo_d2_sb(cr, curve);
+}
+void
+plot3d(cairo_t *cr, SBasisOf<SBasisOf<double> > const &f, Frame frame, int NbRays=5){
+ for (int i=0; i<=NbRays; i++){
+ SBasisOf<double> var = LinearOf<double>(0,1);
+ SBasisOf<double> cst = LinearOf<double>(i*1./NbRays,i*1./NbRays);
+ SBasis f_on_seg = toSBasis(compose(f,var,cst));
+ plot3d(cr,Linear(0,1),Linear(i*1./NbRays),f_on_seg,frame);
+ f_on_seg = toSBasis(compose(f,cst,var));
+ plot3d(cr,Linear(i*1./NbRays),Linear(0,1),f_on_seg,frame);
+ }
+}
+
+
+#define SIZE 2
+
+class ConvolutionToy: public Toy {
+
+ PointHandle adjuster, adjuster2, adjuster3;
+
+public:
+ PointSetHandle b1_handle;
+ PointSetHandle b2_handle;
+ void draw(cairo_t *cr,
+ std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override {
+
+ D2<SBasis> B1 = b1_handle.asBezier();
+ D2<SBasis> B2 = b2_handle.asBezier();
+ D2<Piecewise<SBasis> >B;
+ B[X].concat(Piecewise<SBasis>(B1[X]));
+ B[X].concat(Piecewise<SBasis>(B2[X]));
+ B[Y].concat(Piecewise<SBasis>(B1[Y]));
+ B[Y].concat(Piecewise<SBasis>(B2[Y]));
+
+//-----------------------------------------------------
+#if 0
+ Frame frame;
+ frame.O = Point(50,400);
+ frame.x = Point(300,0);
+ frame.y = Point(120,-75);
+ frame.z = Point(0,-300);
+ SBasisOf<SBasisOf<double> > u,v,cst;
+ cst.push_back(LinearOf<SBasisOf<double> >(SBasisOf<double>(LinearOf<double>(1,1))));
+ u.push_back(LinearOf<SBasisOf<double> >(SBasisOf<double>(LinearOf<double>(0,1))));
+ v.push_back(LinearOf<SBasisOf<double> >(SBasisOf<double>(LinearOf<double>(0,0)),
+ SBasisOf<double>(LinearOf<double>(1,1))));
+ plot3d(cr, integral(v,1) ,frame);
+ plot3d(cr, v ,frame);
+ cairo_set_source_rgba (cr, 0., 0.5, 0., 1);
+ cairo_stroke(cr);
+ plot3d(cr, Linear(0,1), Linear(0), Linear(0), frame);
+ plot3d(cr, Linear(0), Linear(0,1), Linear(0), frame);
+ plot3d(cr, Linear(0), Linear(0), Linear(0,1), frame);
+ plot3d(cr, Linear(0,1), Linear(1), Linear(0), frame);
+ plot3d(cr, Linear(1), Linear(0,1), Linear(0), frame);
+ cairo_set_source_rgba (cr, 0., 0.0, 0.9, 1);
+ cairo_stroke(cr);
+#endif
+//-----------------------------------------------------
+
+ SBasisOf<double> smoother;
+ smoother.push_back(LinearOf<double>(0.));
+ smoother.push_back(LinearOf<double>(0.));
+ smoother.push_back(LinearOf<double>(30.));//could be less degree hungry!
+
+ adjuster.pos[X] = 400;
+ if(adjuster.pos[Y]>400) adjuster.pos[Y] = 400;
+ if(adjuster.pos[Y]<100) adjuster.pos[Y] = 100;
+ double scale=(400.-adjuster.pos[Y])/300+.01;
+ D2<Piecewise<SBasis> > smoothB1,smoothB2;
+ smoothB1[X] = convole(toSBasisOfDouble(B1[X]),Interval(0,4),smoother/scale,Interval(-scale/2,scale/2));
+ smoothB1[Y] = convole(toSBasisOfDouble(B1[Y]),Interval(0,4),smoother/scale,Interval(-scale/2,scale/2));
+ smoothB1[X].push(Linear(0.), 8+scale/2);
+ smoothB1[Y].push(Linear(0.), 8+scale/2);
+ smoothB2[X] = Piecewise<SBasis>(Linear(0));
+ smoothB2[X].setDomain(Interval(-scale/2,4-scale/2));
+ smoothB2[Y] = smoothB2[X];
+ smoothB2[X].concat(convole(toSBasisOfDouble(B2[X]),Interval(4,8),smoother/scale,Interval(-scale/2,scale/2)));
+ smoothB2[Y].concat(convole(toSBasisOfDouble(B2[Y]),Interval(4,8),smoother/scale,Interval(-scale/2,scale/2)));
+
+ Piecewise<D2<SBasis> > smoothB;
+ smoothB = sectionize(smoothB1)+sectionize(smoothB2);
+ //cairo_d2_sb(cr, B1);
+ //cairo_d2_sb(cr, B2);
+ cairo_pw_d2_sb(cr, smoothB);
+
+ cairo_move_to(cr,100,400);
+ cairo_line_to(cr,500,400);
+ cairo_set_line_width (cr, .5);
+ cairo_set_source_rgba (cr, 0., 0., 0., 1);
+ cairo_stroke(cr);
+
+ Piecewise<SBasis>bx = Piecewise<SBasis>(B1[X]);
+ bx.setDomain(Interval(0,4));
+ Piecewise<SBasis>smth = Piecewise<SBasis>(toSBasis(smoother));
+ smth.setDomain(Interval(-scale/2,scale/2));
+ cairo_d2_sb(cr, B1);
+ plot_graph(cr, bx, 100, 1);
+ plot_graph(cr, smth/scale, 100, 100);
+ plot_graph(cr, smoothB1[X],100,1);
+
+ //cairo_pw_d2_sb(cr, Piecewise<D2<SBasis> >(B1) );
+ //cairo_pw_d2_sb(cr, sectionize(smoothB1));
+
+ cairo_set_line_width (cr, .5);
+ cairo_set_source_rgba (cr, 0.7, 0.2, 0., 1);
+ cairo_stroke(cr);
+
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+public:
+ ConvolutionToy(){
+ for(int i = 0; i < SIZE; i++) {
+ b1_handle.push_back(150+uniform()*300,150+uniform()*300);
+ b2_handle.push_back(150+uniform()*300,150+uniform()*300);
+ }
+ handles.push_back(&b1_handle);
+ handles.push_back(&b2_handle);
+
+ adjuster.pos = Geom::Point(400,100+300*uniform());
+ handles.push_back(&adjuster);
+
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new ConvolutionToy);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+//vim:filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99:
diff --git a/src/3rdparty/2geom/src/toys/curvature-curve.cpp b/src/3rdparty/2geom/src/toys/curvature-curve.cpp
new file mode 100644
index 0000000..8f8f7bc
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/curvature-curve.cpp
@@ -0,0 +1,142 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-geometric.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <time.h>
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+//-----------------------------------------------
+
+class CurvatureTester: public Toy {
+ PointSetHandle curve_handle;
+ Path current_curve;
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_line_width (cr, 1);
+ current_curve = Path();
+
+ for(int base_i = 0; base_i < int(curve_handle.pts.size()/2) - 1; base_i++) {
+ for(int i = 0; i < 2; i++) {
+ Geom::Point center=curve_handle.pts[1+2*i+base_i*2];
+ Geom::Point normal=center- curve_handle.pts[2*i+base_i*2];
+ double radius = Geom::L2(normal);
+ *notify<<"K="<<radius<<std::endl;
+ if (fabs(radius)>1e-4){
+
+ double ang = atan2(-normal);
+ cairo_arc(cr, center[0], center[1],fabs(radius), ang-0.3, ang+0.3);
+ cairo_set_source_rgba (cr, 0.75, 0.89, 1., 1);
+ cairo_stroke(cr);
+
+
+ //draw_handle(cr, center);
+ }else{
+ }
+ {
+ cairo_save(cr);
+ double dashes[2] = {10, 10};
+ cairo_set_dash(cr, dashes, 2, 0);
+ cairo_move_to(cr, center);
+ cairo_line_to(cr, center-normal);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ }
+ }
+ cairo_set_source_rgba (cr, 0., 0, 0., 1);
+ Geom::Point A = curve_handle.pts[0+base_i*2];
+ Geom::Point B = curve_handle.pts[2+base_i*2];
+ D2<SBasis> best_c = D2<SBasis>(SBasis(Linear(A[X],B[X])),SBasis(Linear(A[Y],B[Y])));
+ double error = -1;
+ for(int i = 0; i < 16; i++) {
+ Geom::Point dA = curve_handle.pts[1+base_i*2]-A;
+ Geom::Point dB = curve_handle.pts[3+base_i*2]-B;
+ std::vector<D2<SBasis> > candidates =
+ cubics_fitting_curvature(curve_handle.pts[0+base_i*2],curve_handle.pts[2+base_i*2],
+ (i&2)?rot90(dA):-rot90(dA),
+ (i&1)?rot90(dB):-rot90(dB),
+ ((i&4)?-1:1)*L2sq(dA), ((i&8)?-1:1)*L2sq(dB));
+
+ if (candidates.empty()) {
+ } else {
+ //TODO: I'm sure std algorithm could do that for me...
+ unsigned best = 0;
+ for (unsigned i=0; i<candidates.size(); i++){
+ Piecewise<SBasis> K = arcLengthSb(candidates[i]);
+
+ double l = Geom::length(candidates[i]);
+ //double l = K.segs.back().at1();//Geom::length(candidates[i]);
+ //printf("l = %g\n", l);
+ if ( l < error || error < 0 ){
+ error = l;
+ best = i;
+ best_c = candidates[best];
+ }
+ }
+ }
+ }
+ if(error >= 0) {
+ //cairo_d2_sb(cr, best_c);
+ current_curve.append(best_c);
+ }
+ }
+
+ cairo_path(cr, current_curve);
+ cairo_stroke(cr);
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ void canvas_click(Geom::Point at, int button) override {
+ std::cout << "clicked at:" << at << " with button " << button << std::endl;
+ if(button == 1) {
+ double dist;
+ double t = current_curve.nearestTime(at, &dist).asFlatTime();
+ if(dist > 5) {
+ curve_handle.push_back(at);
+ curve_handle.push_back(at+Point(100,100));
+ } else {
+ // split around t
+ Piecewise<D2<SBasis> > pw = current_curve.toPwSb();
+ std::vector<Point > vnd = pw.valueAndDerivatives(t, 2);
+ Point on_curve = current_curve(t);
+ Point normal = rot90(vnd[1]);
+ Piecewise<SBasis > K = curvature(pw);
+ Point ps[2] = {on_curve, on_curve+unit_vector(normal)/K(t)};
+ curve_handle.pts.insert(curve_handle.pts.begin()+2*(int(t)+1), ps, ps+2);
+ }
+ }
+ }
+
+public:
+ CurvatureTester(){
+ if(handles.empty()) {
+ handles.push_back(&curve_handle);
+ for(unsigned i = 0; i < 4; i++)
+ curve_handle.push_back(150+uniform()*300,150+uniform()*300);
+ }
+ }
+};
+
+int main(int argc, char **argv) {
+ std::cout << "testing unit_normal(multidim_sbasis) based offset." << std::endl;
+ init(argc, argv, new CurvatureTester);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+//vim:expandtab:shiftwidth = 4:tabstop = 8:softtabstop = 4:encoding = utf-8:textwidth = 99 :
+
+
diff --git a/src/3rdparty/2geom/src/toys/curvature-test.cpp b/src/3rdparty/2geom/src/toys/curvature-test.cpp
new file mode 100644
index 0000000..c209fe3
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/curvature-test.cpp
@@ -0,0 +1,110 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-geometric.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <time.h>
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+// TODO:
+// use path2
+// replace Ray stuff with path2 line segments.
+
+//-----------------------------------------------
+
+class CurvatureTester: public Toy {
+ PointSetHandle curve_handle;
+ PointHandle sample_point;
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+
+ D2<SBasis> B = curve_handle.asBezier();
+
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0., 0.5, 0., 1);
+ cairo_d2_sb(cr, B);
+ cairo_stroke(cr);
+
+ sample_point.pos[1]=400;
+ sample_point.pos[0]=std::max(150.,sample_point.pos[0]);
+ sample_point.pos[0]=std::min(450.,sample_point.pos[0]);
+ cairo_move_to(cr, Geom::Point(150,400));
+ cairo_line_to(cr, Geom::Point(450,400));
+ cairo_set_source_rgba (cr, 0., 0., 0.5, 0.8);
+ cairo_stroke(cr);
+
+ double t=std::max(0.,std::min(1.,(sample_point.pos[0]-150)/300.));
+ Timer tm;
+ tm.ask_for_timeslice();
+ tm.start();
+
+ Piecewise<SBasis> K = curvature(B);
+ Timer::Time als_time = tm.lap();
+ *timer_stream << "curvature " << als_time << std::endl;
+
+ for(unsigned ix = 0; ix < K.segs.size(); ix++) {
+ D2<SBasis> Kxy;
+ Kxy[1] = Linear(400) - K.segs[ix]*300;
+ Kxy[0] = Linear(300*K.cuts[ix] + 150, 300*K.cuts[ix+1] + 150);
+ cairo_d2_sb(cr, Kxy);
+ cairo_stroke(cr);
+ }
+
+ double radius = K(t);
+ *notify<<"K="<<radius<<std::endl;
+ if (fabs(radius)>1e-4){
+ radius=1./radius;
+ Geom::Point normal=unit_vector(derivative(B)(t));
+ normal=rot90(normal);
+ Geom::Point center=B(t)-radius*normal;
+
+ cairo_arc(cr, center[0], center[1],fabs(radius), 0, M_PI*2);
+ draw_handle(cr, center);
+ draw_handle(cr, B(t));
+ }else{
+ Geom::Point p=B(t);
+ Geom::Point v=derivative(B)(t);
+ draw_handle(cr, p);
+ cairo_move_to(cr, p-100*v);
+ cairo_line_to(cr, p+100*v);
+ }
+ cairo_set_source_rgba (cr, 0.5, 0.2, 0., 0.8);
+ cairo_stroke(cr);
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+public:
+ CurvatureTester(){
+ if(handles.empty()) {
+ handles.push_back(&curve_handle);
+ handles.push_back(&sample_point);
+ for(unsigned i = 0; i < 4; i++)
+ curve_handle.push_back(150+uniform()*300,150+uniform()*300);
+ sample_point.pos = Geom::Point(250,300);
+ }
+ }
+};
+
+int main(int argc, char **argv) {
+ std::cout << "testing unit_normal(multidim_sbasis) based offset." << std::endl;
+ init(argc, argv, new CurvatureTester);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+//vim:expandtab:shiftwidth = 4:tabstop = 8:softtabstop = 4:encoding = utf-8:textwidth = 99 :
+
+
diff --git a/src/3rdparty/2geom/src/toys/curve-curve-distance.cpp b/src/3rdparty/2geom/src/toys/curve-curve-distance.cpp
new file mode 100644
index 0000000..bca0f27
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/curve-curve-distance.cpp
@@ -0,0 +1,1000 @@
+/*
+ * curve-curve distance
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/path.h>
+#include <2geom/angle.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/piecewise.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <2geom/nearest-time.h>
+#include <2geom/numeric/linear_system.h>
+
+#include <algorithm>
+
+
+
+namespace Geom
+{
+
+namespace detail
+{
+
+// this wrapper class is an helper to make up a curve portion and access it
+// in an homogeneous way
+template< typename Curve01T >
+class CurvePortion
+{
+ public:
+ CurvePortion(const Curve & curve, double from, double to)
+ : m_curve_ptr(curve.portion(from, to))
+ {
+ }
+
+ Curve01T & get_curve()
+ {
+ return *( static_cast<Curve01T*>(m_curve_ptr) );
+ }
+
+ ~CurvePortion()
+ {
+ if (m_curve_ptr != NULL)
+ delete m_curve_ptr;
+ }
+
+ private:
+ Curve* m_curve_ptr;
+};
+
+template<>
+class CurvePortion< D2<SBasis> >
+{
+ public:
+ CurvePortion< D2<SBasis> >(const D2<SBasis> & curve, double from, double to)
+ : m_curve(portion(curve, from, to))
+ {
+ }
+
+ D2<SBasis> & get_curve()
+ {
+ return m_curve;
+ }
+
+ private:
+ D2<SBasis> m_curve;
+};
+
+
+template< typename Curve01T, typename CurveT >
+class distance_impl
+{
+ typedef Curve01T curveA_type;
+ typedef CurveT curveB_type;
+ // determine how near a distance sample and the value computed through
+ // the interpolated function have to be
+ double accuracy;
+ // determine the recursion limit
+ double adaptive_limit;
+ // pieces of the initial subdivision
+ unsigned int piecees;
+ // degree of the polynomial used to interpolate a piece
+ unsigned int piece_degree;
+ // number of coefficients = piece_degree + 1
+ unsigned int piece_size;
+ unsigned int samples_per_piece;
+ // total initial samples
+ unsigned int N;
+ // a junction is a part of the previous or of the next piece
+ unsigned int samples_per_junction;
+ unsigned int samples_per_2junctions;
+ // number of distance samples used in the interpolation (in the general case)
+ unsigned int samples_per_interpolation;
+
+ // distance between two consecutive parameters at which samples are evaluated
+ double step;
+ double half_step;
+ // length of the initial domain interval of a piece
+ double piece_step;
+ // length of the interval related to a junction
+ double junction_step;
+ // index of the first sample related to a piece
+ unsigned int interval_si;
+ // index of the last sample related to a piece
+ unsigned int interval_ei;
+ // index of the first sample to be evaluated for the current piece
+ unsigned int evaluation_si;
+ // index of the last sample to be evaluated for the current piece
+ unsigned int evaluation_ei;
+ // index of the first sample to be used for interpolating the current piece
+ unsigned int interpolation_si;
+ // index of the last sample to be used for interpolating the current piece
+ unsigned int interpolation_ei;
+ // number of total samples to be used for interpolating the current piece
+ // this is equal to samples_per_interpolation except for the first and last
+ // piece
+ unsigned int interpolation_samples;
+ // parameter value for the first sample related to the current piece
+ double interval_st;
+ // interval_st + piece_step
+ double interval_et;
+ // curve piece start t
+ double portion_st;
+ // curve piece end t
+ double portion_et;
+
+ unsigned int rec_pieces;
+ unsigned int rec_N;
+ unsigned int shared_si;
+ unsigned int shared_ei;
+ double rec_step;
+ double rec_half_step;
+ double rec_piece_step;
+ double rec_piece_2steps;
+ unsigned int rec_total_samples;
+
+
+ void init()
+ {
+ piece_degree = 3;
+ piece_size = piece_degree + 1;
+ samples_per_piece = 4;
+ N = piecees * samples_per_piece;
+ samples_per_junction = 2;
+ samples_per_2junctions = 2*samples_per_junction;
+ samples_per_interpolation
+ = samples_per_piece + samples_per_2junctions;
+ step = 1.0 / N;
+ half_step = step / 2;
+ piece_step = samples_per_piece * step;
+ junction_step = samples_per_junction * step;
+ interval_si = samples_per_junction;
+ interval_ei = interval_si + samples_per_piece;
+ portion_st = (double)(samples_per_junction) / samples_per_interpolation;
+ portion_et = portion_st
+ + (double)(samples_per_piece) / samples_per_interpolation;
+
+ // recursive routine parameters
+ rec_pieces = 2;
+ rec_N = rec_pieces * samples_per_piece;
+ rec_total_samples = 2 * samples_per_piece + 1;
+ shared_si = samples_per_piece - samples_per_junction;
+ shared_ei = samples_per_piece + samples_per_junction;
+ rec_step = 1.0 / rec_N;
+ rec_half_step = rec_step / 2;
+ rec_piece_step = samples_per_piece * rec_step;
+ rec_piece_2steps = 2 * rec_piece_step;
+ }
+
+ bool check_accuracy( SBasis const& piece,
+ NL::Vector const& sample_distances,
+ double step )
+ {
+ double t = 0;
+ for (unsigned int i = 0; i < sample_distances.size(); ++i)
+ {
+ if ( !are_near(piece(t), sample_distances[i], accuracy) )
+ {
+ return false;
+ }
+ t += step;
+ }
+ return true;
+ }
+
+
+ void append( Piecewise<SBasis> & pwc,
+ Piecewise<SBasis> const& spwc,
+ double interval_st,
+ double interval_length )
+ {
+ double cut;
+ for (unsigned int i = 0; i < spwc.size(); ++i)
+ {
+ cut = interval_st + spwc.cuts[i+1] * interval_length;
+ pwc.push(spwc.segs[i], cut);
+ }
+ }
+
+ void init_power_matrix(NL::Matrix & power_matrix)
+ {
+ double t = 0;
+ double u0, u1, s;
+ unsigned int half_rows = power_matrix.rows() / 2;
+ unsigned int n = power_matrix.rows() - 1;
+ for (unsigned int i0 = 0, i1 = n; i0 < half_rows; ++i0, --i1)
+ {
+ u0 = 1-t;
+ u1 = t;
+ s = u0 * u1;
+ for (unsigned int j = 0; j < piece_size; j+=2)
+ {
+ power_matrix(i0, j) = u0;
+ power_matrix(i0, j+1) = u1;
+ power_matrix(i1, j) = u1;
+ power_matrix(i1, j+1) = u0;
+ u0 *= s;
+ u1 *= s;
+ }
+ t += rec_step;
+ }
+ // t = 1/2
+ assert( are_near(t, 0.5) );
+ u1 = 1/2.0;
+ s = 1/4.0;
+ for (unsigned int j = 0; j < piece_size; j+=2)
+ {
+ power_matrix(half_rows, j) = u1;
+ power_matrix(half_rows, j+1) = u1;
+ u1 *= s;
+ }
+ }
+
+ void interpolate( SBasis & piece,
+ NL::Matrix & psdinv_matrix,
+ NL::Vector & sample_distances,
+ double interpolation_si, double interpolation_samples,
+ double _portion_st, double _portion_et )
+ {
+ piece.resize(2);
+
+ NL::VectorView v( sample_distances,
+ interpolation_samples,
+ interpolation_si );
+ NL::Vector coeff = psdinv_matrix * v;
+ for (unsigned int i = 0, k = 0; i < piece_size; i+=2, ++k)
+ {
+ piece[k][0] = coeff[i];
+ piece[k][1] = coeff[i+1];
+ }
+ piece = portion(piece, _portion_st, _portion_et);
+ }
+
+ void evaluate_samples( curveA_type const& A,
+ curveB_type const& B,
+ NL::Vector & sample_distances,
+ double& t )
+ {
+ Point At;
+ double nptime;
+ for (unsigned int i = evaluation_si; i < evaluation_ei; ++i)
+ {
+ At = A(t);
+ nptime = nearest_time(At, B);
+ sample_distances[i] = distance(At, B(nptime));
+ t += step;
+ }
+ }
+
+ void evaluate_piece_rec( Piecewise<SBasis> & pwc,
+ curveA_type const& A,
+ curveB_type const& B,
+ NL::Matrix & psdinv_matrix,
+ NL::Matrix & fpi_matrix,
+ NL::Matrix & lpi_matrix,
+ NL::Vector & curr_vector,
+ NL::Vector & sample_distances,
+ bool adaptive,
+ double _interpolation_si,
+ double _interpolation_ei,
+ double _interval_st,
+ double _interval_et,
+ double half_real_step )
+ {
+ SBasis piece;
+ double _interpolation_samples = _interpolation_ei - _interpolation_si;
+ interpolate( piece, psdinv_matrix, curr_vector,
+ _interpolation_si, _interpolation_samples,
+ _interval_st, _interval_et );
+ if (adaptive)
+ {
+ bool good
+ = check_accuracy( piece, sample_distances, rec_step );
+ if (!good)
+ {
+ Piecewise<SBasis> spwc;
+ CurvePortion<curveA_type> cp(A, _interval_st, _interval_et);
+ evaluate_rec( spwc,
+ cp.get_curve(),
+ B,
+ fpi_matrix,
+ lpi_matrix,
+ sample_distances,
+ half_real_step );
+ append(pwc, spwc, _interval_st, rec_piece_step);
+ }
+ else
+ {
+ pwc.push(piece, _interval_et);
+ }
+ }
+ else
+ {
+ pwc.push(piece, _interval_et);
+ }
+ }
+
+
+ // recursive routine: if the interpolated piece is accurate enough
+ // it's returned in the out-parameter pwc, otherwise the computation of
+ // two new piecees is performed using half of the current step so the
+ // number of samples per piece is always the same, while the interpolation
+ // of one piece is split into the computation of two new piecees when
+ // needed.
+ void evaluate_rec( Piecewise<SBasis> & pwc,
+ curveA_type const& A,
+ curveB_type const& B,
+ NL::Matrix & fpi_matrix,
+ NL::Matrix & lpi_matrix,
+ NL::Vector & sample_distances,
+ double real_step )
+ {
+ const double half_real_step = real_step / 2;
+ const bool adaptive = !(real_step < adaptive_limit);
+ static const unsigned int middle_sample_index = samples_per_piece + 1;
+
+ pwc.clear();
+ pwc.push_cut(0);
+ // sample_distances used to check accuracy and for the interpolation
+ // of the two sub-pieces when needed
+ NL::Vector sample_distances_1(rec_total_samples);
+ NL::Vector sample_distances_2(rec_total_samples);
+
+ // view of even indexes of sample_distances_1
+ NL::VectorView
+ sd1_view_0(sample_distances_1, middle_sample_index, 0, 2);
+ // view of even indexes of sample_distances_2
+ NL::VectorView
+ sd2_view_0(sample_distances_2, middle_sample_index, 0, 2);
+ // view of first half (+ 1) of sample_distances
+ NL::VectorView
+ sd_view_1(sample_distances, middle_sample_index, 0);
+ // view of second half of sample_distances
+ NL::VectorView
+ sd_view_2(sample_distances, middle_sample_index, samples_per_piece);
+
+ sd1_view_0 = sd_view_1;
+ sd2_view_0 = sd_view_2;
+
+ // if we have to check accuracy and go on with recursion
+ // we need to compute the distance samples of middle points
+ // of all current samples, because the new step is half of
+ // the current one
+ if (adaptive)
+ {
+ Point At;
+ double nptime;
+ double t = rec_half_step;
+ for (unsigned int i = 1; i < sample_distances.size(); i+=2)
+ {
+ At = A(t);
+ nptime = nearest_time(At, B);
+ sample_distances_1[i] = distance(At, B(nptime));
+ At = A(t + rec_piece_step);
+ nptime = nearest_time(At, B);
+ sample_distances_2[i] = distance(At, B(nptime));
+ t += rec_step;
+ }
+ }
+
+ // first piece
+ evaluate_piece_rec( pwc, A, B,
+ fpi_matrix,
+ fpi_matrix,
+ lpi_matrix,
+ sample_distances,
+ sample_distances_1,
+ adaptive,
+ 0, // interpolation_si
+ shared_ei, // interpolation_ei
+ 0, // portion_st
+ rec_piece_step, // portion_et
+ half_real_step );
+
+ // copy back junction parts because
+ // the interpolate routine modifies them
+ for ( unsigned int i = 0, j = samples_per_piece - 1;
+ i < samples_per_junction;
+ ++i, --j )
+ {
+ sd_view_1[j] = sd1_view_0[j];
+ sd_view_2[i] = sd2_view_0[i];
+ }
+
+
+ // last piece
+ evaluate_piece_rec( pwc, A, B,
+ lpi_matrix,
+ fpi_matrix,
+ lpi_matrix,
+ sample_distances,
+ sample_distances_2,
+ adaptive,
+ shared_si, // interpolation_si
+ rec_total_samples, // interpolation_ei
+ rec_piece_step, // portion_st
+ rec_piece_2steps, // portion_et
+ half_real_step );
+ }
+
+
+ void evaluate_piece( Piecewise<SBasis> & pwc,
+ curveA_type const& A,
+ curveB_type const& B,
+ NL::Matrix & psdinv_matrix,
+ NL::Matrix & fpi_matrix,
+ NL::Matrix & lpi_matrix,
+ NL::Vector & curr_vector,
+ NL::Vector & sample_distances,
+ NL::Vector & end_junction,
+ NL::VectorView & start_junction_view,
+ NL::VectorView & end_junction_view,
+ double & t )
+ {
+ //static size_t index = 0;
+ //std::cerr << "index = " << index++ << std::endl;
+ bool good;
+ SBasis piece;
+ Piecewise<SBasis> spwc;
+ interval_et += piece_step;
+ //std::cerr << "interval: " << interval_st << ", " << interval_et << std::endl;
+ //std::cerr << "interpolation range: " << interpolation_si << ", " << interpolation_ei << std::endl;
+ //std::cerr << "interpolation samples = " << interpolation_samples << std::endl;
+ evaluate_samples( A, B, curr_vector, t );
+ //std::cerr << "current vector: " << curr_vector << std::endl;
+ for ( unsigned int i = 0, k = interval_si;
+ i < sample_distances.size();
+ i+=2, ++k )
+ {
+ sample_distances[i] = curr_vector[k];
+ }
+ Point At;
+ double nptime;
+ double tt = interval_st + half_step;
+ for (unsigned int i = 1; i < sample_distances.size(); i+=2)
+ {
+ At = A(tt);
+ nptime = nearest_time(At, B);
+ sample_distances[i] = distance(At, B(nptime));
+ tt += step;
+ }
+ //std::cerr << "sample_distances: " << sample_distances << std::endl;
+ end_junction = end_junction_view;
+ interpolate( piece, psdinv_matrix, curr_vector,
+ interpolation_si, interpolation_samples,
+ portion_st, portion_et );
+ good = check_accuracy( piece, sample_distances, rec_step );
+ //std::cerr << "good: " << good << std::endl;
+ //good = true;
+ if (!good)
+ {
+ CurvePortion<curveA_type> cp(A, interval_st, interval_et);
+ evaluate_rec( spwc,
+ cp.get_curve(),
+ B,
+ fpi_matrix,
+ lpi_matrix,
+ sample_distances,
+ half_step );
+ append(pwc, spwc, interval_st, piece_step);
+ }
+ else
+ {
+ pwc.push(piece, interval_et);
+ }
+ interval_st = interval_et;
+ for (unsigned int i = 0; i < samples_per_junction; ++i)
+ {
+ curr_vector[i] = start_junction_view[i];
+ curr_vector[samples_per_junction + i] = end_junction[i];
+ }
+ }
+
+ public:
+ void evaluate( Piecewise<SBasis> & pwc,
+ curveA_type const& A,
+ curveB_type const& B,
+ unsigned int _piecees )
+ {
+ piecees = _piecees;
+ init();
+ assert( !(piecees & 1) );
+ assert( !(piece_size & 1) );
+ assert( rec_total_samples & 1);
+ pwc.clear();
+ pwc.push_cut(0);
+ NL::Matrix power_matrix(rec_total_samples, piece_size);
+ init_power_matrix(power_matrix);
+
+ NL::MatrixView rec_fmv( power_matrix,
+ 0, 0,
+ shared_ei, piece_size );
+ NL::Matrix rec_fpim = NL::pseudo_inverse(rec_fmv);
+ NL::MatrixView rec_lmv( power_matrix,
+ shared_si, 0,
+ rec_total_samples - shared_si, piece_size );
+ NL::Matrix rec_lpim = NL::pseudo_inverse(rec_lmv);
+
+
+
+ NL::Vector curr_vector(samples_per_interpolation);
+ NL::Vector sample_distances(rec_total_samples);
+ NL::Vector end_junction(samples_per_junction);
+ NL::VectorView start_junction_view(
+ sample_distances,
+ samples_per_junction,
+ rec_total_samples - 1 - samples_per_2junctions,
+ 2 );
+ NL::VectorView end_junction_view(
+ curr_vector,
+ samples_per_junction,
+ samples_per_junction + samples_per_piece );
+
+ double t = 0;
+
+ // first piece
+ evaluation_si = interval_si;
+ evaluation_ei = samples_per_interpolation;
+ interpolation_si = evaluation_si;
+ interpolation_ei = evaluation_ei;
+ interpolation_samples = interpolation_ei - interpolation_si;
+ interval_st = 0;
+ interval_et = 0;
+ NL::MatrixView fmv( power_matrix,
+ interpolation_si, 0,
+ interpolation_samples, piece_size );
+ NL::Matrix fpim = NL::pseudo_inverse(fmv);
+
+ evaluate_piece( pwc, A, B, fpim,
+ rec_fpim, rec_lpim,
+ curr_vector, sample_distances, end_junction,
+ start_junction_view, end_junction_view,
+ t );
+
+ // general case
+ evaluation_si = interval_si + samples_per_junction;
+ evaluation_ei = samples_per_interpolation;
+ interpolation_si = 0;
+ interpolation_ei = evaluation_ei;
+ interpolation_samples = interpolation_ei - interpolation_si;
+ NL::MatrixView gmv( power_matrix,
+ interpolation_si, 0,
+ interpolation_samples, piece_size );
+ NL::Matrix gpim = NL::pseudo_inverse(gmv);
+
+ for ( unsigned int piece_index = 1;
+ piece_index < piecees - 1;
+ ++piece_index )
+ {
+ evaluate_piece( pwc, A, B, gpim,
+ rec_fpim, rec_lpim,
+ curr_vector, sample_distances, end_junction,
+ start_junction_view, end_junction_view,
+ t );
+ }
+
+ // last piece
+ evaluation_si = interval_si + samples_per_junction;
+ evaluation_ei = interval_ei + 1;
+ interpolation_si = 0;
+ interpolation_ei = evaluation_ei;
+ interpolation_samples = interpolation_ei -interpolation_si;
+ NL::MatrixView lmv( power_matrix,
+ interpolation_si, 0,
+ interpolation_samples, piece_size );
+ NL::Matrix lpim = NL::pseudo_inverse(lmv);
+
+ evaluate_piece( pwc, A, B, lpim,
+ rec_fpim, rec_lpim,
+ curr_vector, sample_distances, end_junction,
+ start_junction_view, end_junction_view,
+ t );
+ }
+
+ distance_impl()
+ : accuracy(1e-3),
+ adaptive_limit(1e-5)
+ {}
+
+ void set_accuracy(double _accuracy)
+ {
+ accuracy = _accuracy;
+ }
+
+ void set_adaptive_limit(double _adaptive_limit)
+ {
+ adaptive_limit = _adaptive_limit;
+ }
+
+}; // end class distance_impl
+
+} // end namespace detail
+
+template < typename Curve01T, typename CurveT >
+inline
+Piecewise<SBasis>
+distance( Curve01T const& A,
+ CurveT const& B,
+ unsigned int pieces = 40,
+ double adaptive_limit = 1e-5,
+ double accuracy = 1e-3 )
+{
+
+ detail::distance_impl<Curve01T, CurveT> dist;
+ dist.set_accuracy(accuracy);
+ dist.set_adaptive_limit(adaptive_limit);
+ Piecewise<SBasis> pwc;
+ dist.evaluate(pwc, A, B, pieces);
+ return pwc;
+}
+
+template < typename CurveT >
+inline
+Piecewise<SBasis>
+distance( Piecewise< D2<SBasis> > const& A,
+ CurveT const& B,
+ unsigned int pieces = 40,
+ double adaptive_limit = 1e-5,
+ double accuracy = 1e-3 )
+{
+ Piecewise<SBasis> result;
+ Piecewise<SBasis> pwc;
+ for (unsigned int i = 0; i < A.size(); ++i)
+ {
+ pwc = distance(A[i], B, pieces, adaptive_limit, accuracy);
+ pwc.scaleDomain(A.cuts[i+1] - A.cuts[i]);
+ pwc.offsetDomain(A.cuts[i]);
+ result.concat(pwc);
+ }
+ return result;
+}
+
+template < typename CurveT >
+inline
+Piecewise<SBasis>
+distance( Path const& A,
+ CurveT const& B,
+ unsigned int pieces = 40,
+ double adaptive_limit = 1e-5,
+ double accuracy = 1e-3 )
+{
+ Piecewise<SBasis> result;
+ Piecewise<SBasis> pwc;
+ unsigned int sz = A.size();
+ if (A.closed()) ++sz;
+ for (unsigned int i = 0; i < sz; ++i)
+ {
+ pwc = distance(A[i], B, pieces, adaptive_limit, accuracy);
+ pwc.offsetDomain(i);
+ result.concat(pwc);
+ }
+ return result;
+}
+
+
+template < typename Curve01T, typename CurveT >
+unsigned int dist_test( Piecewise<SBasis> const& pwc,
+ Curve01T const& A,
+ CurveT const& B,
+ double step )
+{
+ std::cerr << "======= inside dist test =======" << std::endl;
+ unsigned int total_checked_values = 0;
+ unsigned int total_error = 0;
+ double nptime, sample_distance;
+ Point At;
+ for (double t = 0; t <= 1; t += step)
+ {
+ At = A(t);
+ nptime = nearest_time(At, B);
+ sample_distance = distance(At, B(nptime));
+ if ( !are_near(pwc(t), sample_distance, 0.001) )
+ {
+ ++total_error;
+ std::cerr << "error at t: " << t << std::endl;
+ }
+ ++total_checked_values;
+ }
+ std::cerr << " total checked values : " << total_checked_values << std::endl;
+ std::cerr << " total error : " << total_error << std::endl;
+ return total_error;
+}
+
+} // end namespace Geom
+
+
+using namespace Geom;
+
+class DCCToy : public Toy
+{
+ private:
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ Point ulc(width - 300, height - 60 );
+ toggles[0].bounds = Rect(ulc, ulc + Point(160,25) );
+ toggles[1].bounds = Rect(ulc + Point(0,30), ulc + Point(160,55) );
+ sliders[0].geometry(ulc - Point(450,0), 400);
+ if (toggle0_status != toggles[0].on)
+ {
+ toggle0_status = toggles[0].on;
+ using std::swap;
+ swap(sliders[0], sliders[1]);
+ }
+
+ cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, 1.0);
+ cairo_set_line_width (cr, 0.3);
+
+ if (choice == 0)
+ {
+ A = single_curve_psh.asBezier();
+ cairo_d2_sb(cr, A);
+ }
+ else if (choice == 1)
+ {
+ pA.clear();
+ for (unsigned int k = 0; k < path_curves; ++k)
+ {
+ PointSetHandle psh;
+ psh.pts.resize(path_handles_per_curve);
+ for (unsigned int h = 0; h < path_handles_per_curve; ++h)
+ {
+ unsigned int kk = k * (path_handles_per_curve-1) + h;
+ psh.pts[h] = path_psh.pts[kk];
+ }
+ pA.append(psh.asBezier());
+ }
+ cairo_path(cr, pA);
+ }
+ else if (choice == 2)
+ {
+ for (unsigned int i = 0; i < pwc_curves; ++i)
+ {
+ pwA.segs[i] = pwc_psh[i].asBezier();
+ }
+ cairo_pw_d2_sb(cr, pwA);
+ }
+
+ D2<SBasis> B = B_psh.asBezier();
+ cairo_d2_sb(cr, B);
+
+ double t = sliders[0].value();
+ Piecewise<SBasis> d;
+ unsigned int total_error = 0;
+ Point cursor;
+
+ if (!toggles[0].on)
+ {
+ if (choice == 0)
+ {
+ cursor = A(t);
+ d = distance(A, B, 40);
+ // uncomment following lines to view errors in computing the distance
+ //total_error = dist_test(d, A, B, 0.0004);
+ }
+ else if (choice == 1)
+ {
+ cursor = pA(t);
+ d = distance(pA, B, 40);
+ // uncomment following lines to view errors in computing the distance
+ //total_error = dist_test(d, pA, B, 0.0004);
+ }
+ else if (choice == 2)
+ {
+ cursor = pwA(t);
+ d = distance(pwA, B, 40);
+ // uncomment following lines to view errors in computing the distance
+ //total_error = dist_test(d, pwA, B, 0.0004);
+ }
+
+ double nptB = nearest_time(cursor, B);
+ draw_circ(cr, cursor);
+ cairo_move_to(cr, cursor);
+ cairo_line_to(cr, B(nptB));
+ cairo_stroke(cr);
+ }
+ else
+ {
+ Point np(0,0);
+ cursor = B(t);
+ if (choice == 0)
+ {
+ double nptA = nearest_time(cursor, A);
+ np = A(nptA);
+ d = distance(B, A, 40);
+ // uncomment following lines to view errors in computing the distance
+ //total_error = dist_test(d, B, A, 0.0004);
+ }
+ else if (choice == 1)
+ {
+ double nptA = nearest_time(cursor, pA);
+ np = pA(nptA);
+ d = distance(B, pA, 40);
+ // uncomment following lines to view errors in computing the distance
+ //total_error = dist_test(d, B, pA, 0.0004);
+ }
+ draw_circ(cr, cursor);
+ cairo_move_to(cr, cursor);
+ cairo_line_to(cr, np);
+ cairo_stroke(cr);
+ }
+
+ if (total_error != 0)
+ *notify << "total error: " << total_error << " ";
+
+
+ // draw distance function
+ Piecewise< D2<SBasis> > pwc;
+ pwc.cuts = d.cuts;
+ pwc.segs.resize(d.size());
+ D2<SBasis> piece;
+ double domain_length = 800 / d.domain().extent();
+ for ( unsigned int i = 0; i < d.size(); ++i )
+ {
+ piece[X] = SBasis(Linear(20,20)
+ + domain_length * Linear(d.cuts[i], d.cuts[i+1]));
+ piece[Y] = 3 * d.segs[i];
+ pwc.segs[i] = piece;
+ }
+ cairo_set_source_rgb(cr, 0.7,0,0);
+ cairo_pw_d2_sb(cr, pwc);
+ *notify << "total cuts: " << pwc.cuts.size();
+ if (toggles[1].on)
+ {
+ for (unsigned int i = 0; i < pwc.cuts.size(); ++i)
+ {
+ draw_handle(cr, pwc(pwc.cuts[i]));
+ }
+ }
+ else
+ {
+ draw_handle(cr, pwc(0.0));
+ draw_handle(cr, pwc(0.25));
+ draw_handle(cr, pwc(0.5));
+ draw_handle(cr, pwc(0.75));
+ draw_handle(cr, pwc(1));
+ }
+ draw_circ(cr, pwc(t));
+ cairo_stroke(cr);
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+
+ public:
+ DCCToy()
+ {
+ toggle0_status = false;
+ choice = 0;
+
+ single_curve_handles = 6;
+ path_curves = 3;
+ path_handles_per_curve = 4;
+ path_total_handles = path_curves * (path_handles_per_curve - 1) + 1;
+ pwc_curves = 3;
+ pwc_handles_per_curve = 4;
+ pwc_total_handles = pwc_curves * pwc_handles_per_curve;
+ B_handles = 4;
+
+ if (choice == 0)
+ {
+ for (unsigned int i = 0; i < single_curve_handles; ++i)
+ {
+ single_curve_psh.push_back(700*uniform(), 500*uniform());
+ }
+ handles.push_back(&single_curve_psh);
+ sliders.emplace_back(0.0, 1.0, 0.0, 0.0, "t");
+ }
+ else if (choice == 1)
+ {
+ for (unsigned int i = 0; i < path_total_handles; ++i)
+ {
+ path_psh.push_back(700*uniform(), 500*uniform());
+ }
+ handles.push_back(&path_psh);
+ sliders.emplace_back(0.0, path_curves, 0.0, 0.0, "t");
+ }
+ else if (choice == 2)
+ {
+ pwc_psh.resize(pwc_curves);
+ pwA.segs.resize(pwc_curves);
+ pwA.cuts.resize(pwc_curves+1);
+ pwA.cuts[0] = 0;
+ double length = 1.0 / pwc_curves;
+ for (unsigned int i = 0; i < pwc_curves; ++i)
+ {
+ for (unsigned int j = 0; j < pwc_handles_per_curve; ++j)
+ {
+ pwc_psh[i].push_back(700*uniform(), 500*uniform());
+ }
+ handles.push_back(&(pwc_psh[i]));
+ pwA.cuts[i+1] = pwA.cuts[i] + length;
+ }
+ sliders.emplace_back(0.0, 1.0, 0.0, 0.0, "t");
+ }
+
+ for (unsigned int i = 0; i < B_handles; ++i)
+ {
+ B_psh.push_back(700*uniform(), 500*uniform());
+ }
+ handles.push_back(&B_psh);
+ sliders.emplace_back(0.0, 1.0, 0.0, 0.0, "t");
+
+ toggles.emplace_back("d(A,B) <-> d(B,A)", false);
+ toggles.emplace_back("Show/Hide cuts", false);
+
+ handles.push_back(&(toggles[0]));
+ handles.push_back(&(toggles[1]));
+ handles.push_back(&(sliders[0]));
+
+ }
+
+ private:
+ bool toggle0_status;
+ unsigned int choice;
+ unsigned int single_curve_handles, B_handles;
+ unsigned int path_curves, path_handles_per_curve, path_total_handles;
+ unsigned int pwc_curves, pwc_handles_per_curve, pwc_total_handles;
+ PointSetHandle single_curve_psh;
+ PointSetHandle path_psh;
+ std::vector<PointSetHandle> pwc_psh;
+ PointSetHandle B_psh;
+ std::vector<Toggle> toggles;
+ std::vector<Slider> sliders;
+ D2<SBasis> A;
+ Path pA;
+ Piecewise< D2<SBasis> > pwA;
+};
+
+
+
+
+int main(int argc, char **argv)
+{
+ init( argc, argv, new DCCToy(), 840, 600 );
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/curve-curve-nearest-time.cpp b/src/3rdparty/2geom/src/toys/curve-curve-nearest-time.cpp
new file mode 100644
index 0000000..30fb327
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/curve-curve-nearest-time.cpp
@@ -0,0 +1,609 @@
+/*
+ * Nearest Points Toy 3
+ *
+ * Authors:
+ * Nathan Hurst <njh at njhurst.com>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/path.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/piecewise.h>
+#include <2geom/path-intersection.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <algorithm>
+
+
+using namespace Geom;
+
+
+class np_finder
+{
+public:
+ np_finder(cairo_t* _cr, D2<SBasis> const& _c1, D2<SBasis> const& _c2)
+ : cr(_cr), cc1(_c1), cc2(_c2), c1(_c1), c2(_c2)
+ {
+
+ dc1 = derivative(_c1);
+ dc2 = derivative(_c2);
+ cd1 = dot(_c1,dc1);
+ cd2 = dot(_c2,dc2);
+ dsq = 10e30;
+
+ Piecewise< D2<SBasis> > uv1 = unitVector(dc1, EPSILON);
+ Piecewise< D2<SBasis> > uv2 = unitVector(dc2, EPSILON);
+
+ dcn1 = dot(Piecewise< D2<SBasis> >(dc1), uv1);
+ dcn2 = dot(Piecewise< D2<SBasis> >(dc2), uv2);
+
+ r_dcn1 = cross(derivative(uv1), uv1);
+ r_dcn2 = cross(derivative(uv2), uv2);
+
+ k1 = Geom::divide(r_dcn1, dcn1, EPSILON, 3);
+ k2 = Geom::divide(r_dcn2, dcn2, EPSILON, 3);
+
+
+ n1 = divide(rot90(uv1), k1, EPSILON, 3);
+ n2 = divide(rot90(uv2), k2, EPSILON, 3);
+
+ std::vector<double> cuts1, cuts2;
+
+ // add cuts at points where the curvature is discontinuos
+ for ( unsigned int i = 1; i < k1.size(); ++i )
+ {
+ if( !are_near(k1[i-1].at1(), k1[i].at0()) )
+ {
+ cuts1.push_back(k1.cuts[i]);
+ }
+ }
+ for ( unsigned int i = 1; i < k2.size(); ++i )
+ {
+ if( !are_near(k2[i-1].at1(), k2[i].at0()) )
+ {
+ cuts2.push_back(k2.cuts[i]);
+ }
+ }
+
+ c1 = partition(c1, cuts1);
+ c2 = partition(c2, cuts2);
+
+// std::cerr << "# k1 discontinuitis" << std::endl;
+// for( unsigned int i = 0; i < cuts1.size(); ++i )
+// {
+// std::cerr << "[" << i << "]= " << cuts1[i] << std::endl;
+// }
+// std::cerr << "# k2 discontinuitis" << std::endl;
+// for( unsigned int i = 0; i < cuts2.size(); ++i )
+// {
+// std::cerr << "[" << i << "]= " << cuts2[i] << std::endl;
+// }
+
+ // add cuts at points were the curvature is zero
+ std::vector<double> k1_roots = roots(k1);
+ std::vector<double> k2_roots = roots(k2);
+ std::sort(k1_roots.begin(), k1_roots.end());
+ std::sort(k2_roots.begin(), k2_roots.end());
+ c1 = partition(c1, k1_roots);
+ c2 = partition(c2, k2_roots);
+
+// std::cerr << "# k1 zeros" << std::endl;
+// for( unsigned int i = 0; i < k1_roots.size(); ++i )
+// {
+// std::cerr << "[" << i << "]= " << k1_roots[i] << std::endl;
+// }
+// std::cerr << "# k2 zeros" << std::endl;
+// for( unsigned int i = 0; i < k2_roots.size(); ++i )
+// {
+// std::cerr << "[" << i << "]= " << k2_roots[i] << std::endl;
+// }
+
+
+ cairo_set_line_width(cr, 0.2);
+// cairo_set_source_rgba(cr, 0.0, 0.5, 0.0, 1.0);
+// for( unsigned int i = 1; i < c1.size(); ++i )
+// {
+// draw_circ(cr, c1[i].at0() );
+// }
+// for( unsigned int i = 1; i < c2.size(); ++i )
+// {
+// draw_circ(cr, c2[i].at0() );
+// }
+
+
+ // add cuts at nearest points to the other curve cuts points
+ cuts1.clear();
+ cuts1.reserve(c1.size()+1);
+ for ( unsigned int i = 0; i < c1.size(); ++i )
+ {
+ cuts1.push_back( nearest_time(c1[i].at0(), _c2, dc2, cd2) );
+ }
+ cuts1.push_back( nearest_time(c1[c1.size()-1].at1(), _c2, dc2, cd2) );
+
+// for ( unsigned int i = 0; i < c1.size(); ++i )
+// {
+// cairo_move_to( cr, c1[i].at0() );
+// cairo_line_to(cr, c2(cuts1[i]) );
+// }
+// cairo_move_to( cr, c1[c1.size()-1].at1() );
+// cairo_line_to(cr, c2(cuts1[c1.size()]));
+
+ std::sort(cuts1.begin(), cuts1.end());
+
+ cuts2.clear();
+ cuts2.reserve(c2.size()+1);
+ for ( unsigned int i = 0; i < c2.size(); ++i )
+ {
+ cuts2.push_back( nearest_time(c2[i].at0(), _c1, dc1, cd1) );
+ }
+ cuts2.push_back( nearest_time(c2[c2.size()-1].at1(), _c1, dc1, cd1) );
+
+// for ( unsigned int i = 0; i < c2.size(); ++i )
+// {
+// cairo_move_to( cr, c2[i].at0() );
+// cairo_line_to(cr, c1(cuts2[i]) );
+// }
+// cairo_move_to( cr, c2[c2.size()-1].at1() );
+// cairo_line_to(cr, c1(cuts2[c2.size()]));
+// cairo_stroke(cr);
+
+ std::sort(cuts2.begin(), cuts2.end());
+
+ c1 = partition(c1, cuts2);
+ c2 = partition(c2, cuts1);
+
+
+ // copy curve to preserve cuts status
+ Piecewise< D2<SBasis> > pwc1 = c1;
+ n1 = partition(n1, pwc1.cuts);
+ pwc1 = partition(pwc1, n1.cuts);
+ r_dcn1 = partition(r_dcn1, n1.cuts);
+ Piecewise< D2<SBasis> > pwc2 = c2;
+ n2 = partition(n2, pwc2.cuts);
+ pwc2 = partition(pwc2, n2.cuts);
+
+ assert( pwc1.size() == n1.size() );
+ assert( pwc2.size() == n2.size() );
+ assert( r_dcn1.size() == n1.size() );
+
+ // add cuts at curvature max and min points
+ Piecewise<SBasis> dk1 = derivative(k1);
+ Piecewise<SBasis> dk2 = derivative(k2);
+ std::vector<double> dk1_roots = roots(dk1);
+ std::vector<double> dk2_roots = roots(dk2);
+ std::sort(dk1_roots.begin(), dk1_roots.end());
+ std::sort(dk2_roots.begin(), dk2_roots.end());
+
+ c1 = partition(c1, dk1_roots);
+ c2 = partition(c2, dk2_roots);
+
+// std::cerr << "# k1 min/max" << std::endl;
+// for( unsigned int i = 0; i < dk1_roots.size(); ++i )
+// {
+// std::cerr << "[" << i << "]= " << dk1_roots[i] << std::endl;
+// }
+// std::cerr << "# k2 min/max" << std::endl;
+// for( unsigned int i = 0; i < dk2_roots.size(); ++i )
+// {
+// std::cerr << "[" << i << "]= " << dk2_roots[i] << std::endl;
+// }
+
+// cairo_set_source_rgba(cr, 0.0, 0.0, 0.6, 1.0);
+// for( unsigned int i = 0; i < dk1_roots.size(); ++i )
+// {
+// draw_handle(cr, c1(dk1_roots[i]));
+// }
+// for( unsigned int i = 0; i < dk2_roots.size(); ++i )
+// {
+// draw_handle(cr, c2(dk2_roots[i]));
+// }
+
+
+ // add cuts at nearest points to max and min curvature points
+ // of the other curve
+ cuts1.clear();
+ cuts1.reserve(dk2_roots.size());
+ for (double dk2_root : dk2_roots)
+ {
+ cuts1.push_back(nearest_time(_c2(dk2_root), _c1, dc1, cd1));
+ }
+
+// for( unsigned int i = 0; i < dk2_roots.size(); ++i )
+// {
+// cairo_move_to(cr, c2(dk2_roots[i]));
+// cairo_line_to(cr, c1(cuts1[i]));
+// }
+// cairo_stroke(cr);
+
+ std::sort(cuts1.begin(), cuts1.end());
+ c1 = partition(c1, cuts1);
+
+
+ // swap normal vector direction and fill the skip list
+ skip_list.clear();
+ skip_list.resize(c1.size(), false);
+ double npt;
+ Point p, nv;
+ unsigned int si;
+ for ( unsigned int i = 0; i < pwc1.size(); ++i )
+ {
+ p = pwc1[i](0.5);
+ nv = n1[i](0.5);
+ npt = nearest_time(p, _c2, dc2, cd2);
+ if( dot( _c2(npt) - p, nv ) > 0 )
+ {
+ if ( dot( nv, n2(npt) ) > 0 )
+ {
+ n1[i] = -n1[i];
+ r_dcn1[i] = -r_dcn1[i];
+ }
+ else
+ {
+ si = c1.segN( n1.mapToDomain(0.5, i) );
+ skip_list[si] = true;
+ }
+ }
+ }
+
+
+ for ( unsigned int i = 0; i < pwc2.size(); ++i )
+ {
+ p = pwc2[i](0.5);
+ nv = n2[i](0.5);
+ npt = nearest_time(p, _c1, dc1, cd1);
+ if( dot( _c1(npt) - p, nv ) > 0 )
+ {
+ if ( dot( nv, n1(npt) ) > 0 )
+ {
+ n2[i] = -n2[i];
+ }
+ }
+ }
+
+
+ evl1 = c1 + n1;
+ evl2 = c2 + n2;
+
+// cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, 1.0);
+// for ( unsigned int i = 0; i < c1.size(); ++i )
+// {
+// double t = c1.mapToDomain(0.5, i);
+// cairo_move_to(cr, c1(t));
+// cairo_line_to(cr, c1(t) + 30*unit_vector(n1(t)));
+// }
+//
+// for ( unsigned int i = 0; i < c2.size(); ++i )
+// {
+// double t = c2.mapToDomain(0.5, i);
+// cairo_move_to(cr, c2(t));
+// cairo_line_to(cr, c2(t) + 30*unit_vector(n2(t)));
+// }
+// cairo_stroke(cr);
+
+ std::cerr << "# skip list: ";
+ for( unsigned int i = 0; i < c1.cuts.size(); ++i )
+ {
+ if ( skip_list[i] )
+ std::cerr << i << " ";
+ }
+ std::cerr << std::endl;
+
+ cairo_set_line_width(cr, 0.4);
+ cairo_set_source_rgba(cr, 0.6, 0.0, 0.0, 1.0);
+ for( unsigned int i = 0; i < c1.size(); ++i )
+ {
+ if ( skip_list[i] )
+ {
+ cairo_move_to(cr, c1[i].at0());
+ cairo_line_to(cr, c1[i].at1());
+ }
+ }
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba(cr, 0.2, 0.2, 0.2, 1.0);
+ for( unsigned int i = 1; i < c1.size(); ++i )
+ {
+ draw_circ(cr, c1[i].at0() );
+ }
+ cairo_stroke(cr);
+
+ std::cerr << "# c1 cuts: " << std::endl;
+ for( unsigned int i = 0; i < c1.cuts.size(); ++i )
+ {
+ std::cerr << "c1.cuts[" << i << "]= " << c1.cuts[i] << std::endl;
+ }
+
+ }
+
+ void operator() ()
+ {
+ nearest_times_impl();
+ d = sqrt(dsq);
+ }
+
+ Point firstPoint() const
+ {
+ return p1;
+ }
+
+ Point secondPoint() const
+ {
+ return p2;
+ }
+
+ double firstValue() const
+ {
+ return t1;
+ }
+
+ double secondValue() const
+ {
+ return t2;
+ }
+
+ double distance() const
+ {
+ return d;
+ }
+
+private:
+ void nearest_times_impl()
+ {
+ double t;
+ for ( unsigned int i = 0; i < c1.size(); ++i )
+ {
+ if ( skip_list[i] ) continue;
+ std::cerr << i << " ";
+ t = c1.mapToDomain(0.5, i);
+ std::pair<double, double> npc = loc_nearest_times(t, c1.cuts[i], c1.cuts[i+1]);
+ if ( npc.second != -1 && dsq > L2sq(c1(npc.first) - c2(npc.second)) )
+ {
+ t1 = npc.first;
+ t2 = npc.second;
+ p1 = c1(t1);
+ p2 = c2(t2);
+ dsq = L2sq(p1 - p2);
+ }
+ }
+ }
+
+ std::pair<double, double>
+ loc_nearest_times( double t, double from = 0, double to = 1 )
+ {
+ std::cerr << "[" << from << "," << to << "] t: " << t << std::endl;
+ unsigned int iter = 0, iter1 = 0, iter2 = 0;
+ std::pair<double, double> np(-1,-1);
+ std::pair<double, double> npf(from, -1);
+ std::pair<double, double> npt(to, -1);
+ double ct = t;
+ double pt = -1;
+ double s = nearest_time(c1(t), cc2, dc2, cd2);
+ cairo_set_source_rgba(cr, 1/(t+1), t*t, t, 1.0);
+ cairo_move_to(cr, c1(t));
+ while( !are_near(ct, pt) && iter < 1000 )
+ {
+ pt = ct;
+ double angle = angle_between( n1(ct), evl2(s) - evl1(ct) );
+ assert( !std::isnan(angle) );
+ angle = (angle > 0) ? angle - M_PI : angle + M_PI;
+ if ( std::fabs(angle) < M_PI/12 )
+ {
+ ++iter2;
+// cairo_move_to(cr, c1(ct));
+// cairo_line_to(cr, evl1(ct));
+// cairo_line_to(cr, evl2(s));
+ //std::cerr << "s: " << s << std::endl;
+ //std::cerr << "t: " << ct << std::endl;
+
+ ct = ct + angle / r_dcn1(ct);
+ s = nearest_time(c1(ct), cc2, dc2, cd2);
+// angle = angle_between( n2(s), evl1(ct) - evl2(s) );
+// assert( !std::isnan(angle) );
+// angle = (angle > 0) ? angle - M_PI : angle + M_PI;
+// s = s + angle / (dcn2(s) * k2(s));
+ }
+ else
+ {
+ ++iter1;
+ ct = nearest_time(c2(s), cc1, dc1, cd1, from, to);
+ s = nearest_time(c1(ct), cc2, dc2, cd2);
+ }
+ iter = iter1 + iter2;
+ //std::cerr << "s: " << s << std::endl;
+ //std::cerr << "t: " << ct << std::endl;
+ //cairo_line_to(cr, c2(s));
+ //cairo_line_to(cr, c1(ct));
+ //std::cerr << "d(pt, ct) = " << std::fabs(ct - pt) << std::endl;
+ if ( ct < from )
+ {
+ std::cerr << "break left" << std::endl;
+ np = npf;
+ break;
+ }
+ if ( ct > to )
+ {
+ std::cerr << "break right" << std::endl;
+ np =npt;
+ break;
+ }
+ }
+ //std::cerr << "\n \n";
+ std::cerr << "iterations: " << iter1 << " + " << iter2 << " = "<< iter << std::endl;
+ assert(iter < 3000);
+ //cairo_move_to(cr, c1(ct));
+ //cairo_line_to(cr, c2(s));
+ cairo_stroke(cr);
+ np.first = ct;
+ np.second = s;
+ return np;
+ }
+
+ double nearest_time( Point const& p, D2<SBasis> const&c, D2<SBasis> const& dc, SBasis const& cd, double from = 0, double to = 1 )
+ {
+ D2<SBasis> sbc = c - p;
+ SBasis dd = cd - dotp(p, dc);
+ std::vector<double> zeros = roots(dd);
+ double closest = from;
+ double distsq = L2sq(sbc(from));
+ for (double zero : zeros)
+ {
+ if ( distsq > L2sq(sbc(zero)) )
+ {
+ closest = zero;
+ distsq = L2sq(sbc(closest));
+ }
+ }
+ if ( distsq > L2sq(sbc(to)) )
+ closest = to;
+ return closest;
+ }
+
+ SBasis dotp(Point const& p, D2<SBasis> const& c)
+ {
+ SBasis d;
+ d.resize(c[X].size());
+ for ( unsigned int i = 0; i < c[0].size(); ++i )
+ {
+ for( unsigned int j = 0; j < 2; ++j )
+ d[i][j] = p[X] * c[X][i][j] + p[Y] * c[Y][i][j];
+ }
+ return d;
+ }
+
+ Piecewise< D2<SBasis> >
+ divide( Piecewise< D2<SBasis> > const& a, Piecewise<SBasis> const& b, double tol, unsigned int k, double zero=1.e-3)
+ {
+ D2< Piecewise<SBasis> > aa = make_cuts_independent(a);
+ D2< Piecewise<SBasis> > q(Geom::divide(aa[0], b, tol, k, zero), Geom::divide(aa[1], b, tol, k, zero));
+ return sectionize(q);
+ }
+
+ struct are_near_
+ {
+ bool operator() (double x, double y, double eps = Geom::EPSILON )
+ {
+ return are_near(x, y, eps);
+ }
+ };
+
+private:
+ cairo_t* cr;
+ D2<SBasis> const& cc1, cc2;
+ Piecewise< D2<SBasis> > c1, c2;
+ D2<SBasis> dc1, dc2;
+ SBasis cd1, cd2;
+ Piecewise< D2<SBasis> > n1, n2, evl1, evl2;
+ Piecewise<SBasis> k1, k2, dcn1, dcn2, r_dcn1, r_dcn2;
+ double t1, t2, d, dsq;
+ Point p1, p2;
+ std::vector<bool> skip_list;
+};
+
+
+
+
+class NearestPoints : public Toy
+{
+ private:
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ cairo_set_line_width (cr, 0.3);
+ D2<SBasis> A = pshA.asBezier();
+ cairo_d2_sb(cr, A);
+ D2<SBasis> B = pshB.asBezier();
+ cairo_d2_sb(cr, B);
+ cairo_stroke(cr);
+
+ np_finder np(cr, A, B);
+ Path AP, BP;
+ AP.append(A); BP.append(B);
+ Crossings ip_list = curve_sweep<SimpleCrosser>(AP, BP);
+ if( ip_list.empty() )
+ {
+ np();
+ cairo_set_line_width (cr, 0.4);
+ cairo_set_source_rgba(cr, 0.7, 0.0, 0.7, 1.0);
+ cairo_move_to(cr, np.firstPoint());
+ cairo_line_to(cr, np.secondPoint());
+ cairo_stroke(cr);
+ //std::cerr << "np: (" << np.firstValue() << "," << np.secondValue() << ")" << std::endl;
+ }
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ NearestPoints(unsigned int _A_bez_ord, unsigned int _B_bez_ord)
+ : A_bez_ord(_A_bez_ord), B_bez_ord(_B_bez_ord)
+ {
+ handles.push_back(&pshA);
+ handles.push_back(&pshB);
+ for ( unsigned int i = 0; i < A_bez_ord; ++i )
+ pshA.push_back(Geom::Point(uniform()*400, uniform()*400));
+ for ( unsigned int i = 0; i < B_bez_ord; ++i )
+ pshB.push_back(Geom::Point(uniform()*400, uniform()*400));
+
+ }
+
+ private:
+ PointSetHandle pshA, pshB;
+ unsigned int A_bez_ord;
+ unsigned int B_bez_ord;
+};
+
+
+int main(int argc, char **argv)
+{
+ unsigned int A_bez_ord=8;
+ unsigned int B_bez_ord=5;
+ if(argc > 2)
+ sscanf(argv[2], "%d", &B_bez_ord);
+ if(argc > 1)
+ sscanf(argv[1], "%d", &A_bez_ord);
+
+ init( argc, argv, new NearestPoints(A_bez_ord, B_bez_ord));
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/curve-intersection-by-bezier-clipping.cpp b/src/3rdparty/2geom/src/toys/curve-intersection-by-bezier-clipping.cpp
new file mode 100644
index 0000000..dfd0a56
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/curve-intersection-by-bezier-clipping.cpp
@@ -0,0 +1,127 @@
+/*
+ * Show off crossings between two Bezier curves.
+ * The intersection points are found by using Bezier clipping.
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <2geom/d2.h>
+#include <2geom/basic-intersection.h>
+#include <2geom/sbasis-to-bezier.h>
+
+
+
+
+using namespace Geom;
+
+
+class CurveIntersect : public Toy
+{
+
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ cairo_set_line_width (cr, 0.3);
+ cairo_set_source_rgba (cr, 0.8, 0., 0, 1);
+ //pshA.pts.back() = pshB.pts[0];
+ D2<SBasis> A = pshA.asBezier();
+ cairo_d2_sb(cr, A);
+ cairo_stroke(cr);
+ cairo_set_source_rgba (cr, 0.0, 0., 0, 1);
+ D2<SBasis> B = pshB.asBezier();
+ cairo_d2_sb(cr, B);
+ cairo_stroke(cr);
+
+ find_intersections_bezier_clipping(xs, pshA.pts, pshB.pts, m_precision);
+ cairo_set_line_width (cr, 0.3);
+ cairo_set_source_rgba (cr, 0.0, 0.0, 0.7, 1);
+ for (auto & x : xs)
+ {
+ draw_handle(cr, A(x.first));
+ draw_handle(cr, B(x.second));
+ }
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+
+public:
+ CurveIntersect(unsigned int _A_bez_ord, unsigned int _B_bez_ord)
+ : A_bez_ord(_A_bez_ord), B_bez_ord(_B_bez_ord)
+ {
+ handles.push_back(&pshA);
+ for (unsigned int i = 0; i <= A_bez_ord; ++i)
+ pshA.push_back(Geom::Point(uniform()*400, uniform()*400)+Point(200,200));
+ handles.push_back(&pshB);
+ for (unsigned int i = 0; i <= B_bez_ord; ++i)
+ pshB.push_back(Geom::Point(uniform()*400, uniform()*400)+Point(200,200));
+
+ m_precision = 1e-6;
+ }
+
+private:
+ unsigned int A_bez_ord, B_bez_ord;
+ PointSetHandle pshA, pshB, pshC;
+ std::vector< std::pair<double, double> > xs;
+ double m_precision;
+};
+
+
+int main(int argc, char **argv)
+{
+ unsigned int A_bez_ord = 6;
+ unsigned int B_bez_ord = 8;
+ if(argc > 1)
+ sscanf(argv[1], "%d", &A_bez_ord);
+ if(argc > 2)
+ sscanf(argv[2], "%d", &B_bez_ord);
+
+
+ init( argc, argv, new CurveIntersect(A_bez_ord, B_bez_ord), 800, 800);
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+ */
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+
+
diff --git a/src/3rdparty/2geom/src/toys/curve-intersection-by-implicitization.cpp b/src/3rdparty/2geom/src/toys/curve-intersection-by-implicitization.cpp
new file mode 100644
index 0000000..e071911
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/curve-intersection-by-implicitization.cpp
@@ -0,0 +1,300 @@
+/*
+ * Show off crossings between two D2<SBasis> curves.
+ * The intersection points are found by using implicitization tecnique.
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <2geom/d2.h>
+#include <2geom/sbasis-poly.h>
+#include <2geom/numeric/linear_system.h>
+#include <2geom/symbolic/implicit.h>
+
+
+using namespace Geom;
+
+/*
+ * helper routines
+ */
+void poly_to_mvpoly1(SL::MVPoly1 & p, Geom::Poly const& q)
+{
+ for (size_t i = 0; i < q.size(); ++i)
+ {
+ p.coefficient(i, q[i]);
+ }
+ p.normalize();
+}
+
+void mvpoly1_to_poly(Geom::Poly & p, SL::MVPoly1 const& q)
+{
+ p.resize(q.get_poly().size());
+ for (size_t i = 0; i < q.get_poly().size(); ++i)
+ {
+ p[i] = q[i];
+ }
+}
+
+
+/*
+ * intersection_info
+ * structure utilized to store intersection info
+ *
+ * p - the intersection point
+ * t0 - the parameter t value at which the first curve pass through p
+ * t1 - the parameter t value at which the first curve pass through p
+ */
+struct intersection_info
+{
+ intersection_info()
+ {}
+
+ intersection_info(Point const& _p, Coord _t0, Coord _t1)
+ : p(_p), t0(_t0), t1(_t1)
+ {}
+
+ Point p;
+ Coord t0, t1;
+};
+
+typedef std::vector<intersection_info> intersections_info;
+
+
+
+/*
+ * intersection algorithm
+ */
+void intersect(intersections_info& xs, D2<SBasis> const& A, D2<SBasis> const& B)
+{
+ using std::swap;
+
+ // supposing implicitization the most expensive step
+ // we perform a call to intersect with curve arguments swapped
+ if (A[0].size() > B[0].size())
+ {
+ intersect(xs, B, A);
+ for (auto & x : xs)
+ swap(x.t0, x.t1);
+
+ return;
+ }
+
+ // convert A from symmetric power basis to power basis
+ Geom::Poly A0 = sbasis_to_poly(A[0]);
+ Geom::Poly A1 = sbasis_to_poly(A[1]);
+
+ // convert to MultiPoly type
+ SL::MVPoly1 Af, Ag;
+ poly_to_mvpoly1(Af, A0);
+ poly_to_mvpoly1(Ag, A1);
+
+ // compute a basis of the ideal related to the curve A
+ // in vector form
+ Geom::SL::basis_type b;
+ // if we compute the micro-basis the bezout matrix is made up
+ // by one only entry so we can't do the inversion step.
+ if (A0.size() == 3)
+ {
+ make_initial_basis(b, Af, Ag);
+ }
+ else
+ {
+ microbasis(b, Af, Ag);
+ }
+
+ // we put the basis in of the form of two independent moving line
+ Geom::SL::MVPoly3 p, q;
+ basis_to_poly(p, b[0]);
+ basis_to_poly(q, b[1]);
+
+ // compute the Bezout matrix and the implicit equation of the curve A
+ Geom::SL::Matrix<Geom::SL::MVPoly2> BZ = make_bezout_matrix(p, q);
+ SL::MVPoly2 ic = determinant_minor(BZ);
+ ic.normalize();
+
+
+ // convert B from symmetric power basis to power basis
+ Geom::Poly B0 = sbasis_to_poly(B[0]);
+ Geom::Poly B1 = sbasis_to_poly(B[1]);
+
+ // convert to MultiPoly type
+ SL::MVPoly1 Bf, Bg;
+ poly_to_mvpoly1(Bf, B0);
+ poly_to_mvpoly1(Bg, B1);
+
+ // evaluate the implicit equation of A on B
+ // so we get an s(t) polynomial that give us
+ // the t values for B at which intersection happens
+ SL::MVPoly1 s = ic(Bf, Bg);
+
+ // convert s(t) to Poly type, in order to use the real_solve function
+ Geom::Poly z;
+ mvpoly1_to_poly(z, s);
+
+ // compute t values for the curve B at which intersection happens
+ std::vector<double> sol = solve_reals(z);
+
+ // filter the found solutions wrt the domain interval [0,1] of B
+ // and compute the related point coordinates
+ std::vector<double> pt;
+ pt.reserve(sol.size());
+ std::vector<Point> points;
+ points.reserve(sol.size());
+ for (double & i : sol)
+ {
+ if (i >= 0 && i <= 1)
+ {
+ pt.push_back(i);
+ points.push_back(B(pt.back()));
+ }
+ }
+
+ // case: A is parametrized by polynomial of degree 1
+ // we compute the t values of A at the intersection points
+ // and filter the results wrt the domain interval [0,1]
+ double t;
+ xs.clear();
+ xs.reserve(pt.size());
+ if (A0.size() == 2)
+ {
+ for (size_t i = 0; i < points.size(); ++i)
+ {
+ t = (points[i][X] - A0[0]) / A0[1];
+ if (t >= 0 && t <= 1)
+ {
+ xs.push_back(intersection_info(points[i], t, pt[i]));
+ }
+ }
+ return;
+ }
+
+ // general case
+ // we compute the value of the parameter t of A at each intersection point
+ // and we filter the final result wrt the domain interval [0,1]
+ // the computation is performed by using the inversion formula for each point
+ // As reference see:
+ // Sederberger - Computer Aided Geometric Design
+ // par 16.5 - Implicitization and Inversion
+ size_t n = BZ.rows();
+ Geom::NL::Matrix BZN(n, n);
+ Geom::NL::MatrixView BZV(BZN, 0, 0, n-1, n-1);
+ Geom::NL::VectorView cv = BZN.column_view(n-1);
+ Geom::NL::VectorView bv(cv, n-1);
+ Geom::NL::LinearSystem ls(BZV, bv);
+ for (size_t i = 0; i < points.size(); ++i)
+ {
+ // evaluate the first main minor of order n-1 at each intersection point
+ polynomial_matrix_evaluate(BZN, BZ, points[i]);
+ // solve the linear system with the powers of t as unknowns
+ ls.SV_solve();
+ // the last element contains the t value
+ t = -ls.solution()[n-2];
+ // filter with respect to the domain of A
+ if (t >= 0 && t <= 1)
+ {
+ xs.push_back(intersection_info(points[i], t, pt[i]));
+ }
+ }
+}
+
+
+
+class IntersectImplicit : public Toy
+{
+
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ cairo_set_line_width (cr, 0.3);
+ cairo_set_source_rgba (cr, 0.8, 0., 0, 1);
+ D2<SBasis> A = pshA.asBezier();
+ cairo_d2_sb(cr, A);
+ cairo_stroke(cr);
+ cairo_set_source_rgba (cr, 0.0, 0., 0, 1);
+ D2<SBasis> B = pshB.asBezier();
+ cairo_d2_sb(cr, B);
+ cairo_stroke(cr);
+
+ intersect(xs, A, B);
+ for (auto & x : xs)
+ {
+ draw_handle(cr, x.p);
+ }
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+
+public:
+ IntersectImplicit(unsigned int _A_bez_ord, unsigned int _B_bez_ord)
+ : A_bez_ord(_A_bez_ord), B_bez_ord(_B_bez_ord)
+ {
+ handles.push_back(&pshA);
+ for (unsigned int i = 0; i <= A_bez_ord; ++i)
+ pshA.push_back(Geom::Point(uniform()*400, uniform()*400));
+ handles.push_back(&pshB);
+ for (unsigned int i = 0; i <= B_bez_ord; ++i)
+ pshB.push_back(Geom::Point(uniform()*400, uniform()*400));
+
+ }
+
+private:
+ unsigned int A_bez_ord, B_bez_ord;
+ PointSetHandle pshA, pshB;
+ intersections_info xs;
+};
+
+
+int main(int argc, char **argv)
+{
+ unsigned int A_bez_ord = 4;
+ unsigned int B_bez_ord = 6;
+ if(argc > 1)
+ sscanf(argv[1], "%d", &A_bez_ord);
+ if(argc > 2)
+ sscanf(argv[2], "%d", &B_bez_ord);
+
+
+ init( argc, argv, new IntersectImplicit(A_bez_ord, B_bez_ord));
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+ */
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/cylinder3d.cpp b/src/3rdparty/2geom/src/toys/cylinder3d.cpp
new file mode 100644
index 0000000..19f3440
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/cylinder3d.cpp
@@ -0,0 +1,253 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/transforms.h>
+#include <2geom/sbasis-math.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <2geom/path.h>
+#include <2geom/svg-path-parser.h>
+
+#include <gsl/gsl_matrix.h>
+
+#include <vector>
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+unsigned total_pieces_sub;
+unsigned total_pieces_inc;
+
+void cairo_pw(cairo_t *cr, Piecewise<SBasis> p) {
+ for(unsigned i = 0; i < p.size(); i++) {
+ D2<SBasis> B;
+ B[0] = Linear(p.cuts[i], p.cuts[i+1]);
+ B[1] = p[i];
+ cairo_d2_sb(cr, B);
+ }
+}
+
+Geom::Point orig;
+
+static void draw_box (cairo_t *cr, Geom::Point corners[8]);
+static void draw_slider_lines (cairo_t *cr);
+static Geom::Point proj_image (cairo_t *cr, const double pt[4], const vector<Geom::Point> &handles);
+
+double tmat[3][4];
+double c[8][4];
+Geom::Point corners[8];
+
+class Box3d: public Toy {
+ std::vector<Toggle> togs;
+ Path path_a;
+ Piecewise<D2<SBasis> > path_a_pw;
+ PointSetHandle hand;
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ orig = hand.pts[7];
+
+ Geom::Point dir(1,-2);
+
+ cairo_set_source_rgba (cr, 0., 0.125, 0, 1);
+
+ // draw vertical lines for the VP sliders and keep the sliders at their horizontal positions
+ draw_slider_lines (cr);
+ hand.pts[4][0] = 30;
+ hand.pts[5][0] = 45;
+ hand.pts[6][0] = 60;
+
+ // draw the curve that is supposed to be projected on the box's front face
+ vector<Geom::Point>::iterator it = hand.pts.begin();
+ for (int j = 0; j < 7; ++j) ++it;
+
+ /* create the transformation matrix for the map P^3 --> P^2 that has the following effect:
+ (1 : 0 : 0 : 0) --> vanishing point in x direction (= handle #0)
+ (0 : 1 : 0 : 0) --> vanishing point in y direction (= handle #1)
+ (0 : 0 : 1 : 0) --> vanishing point in z direction (= handle #2)
+ (0 : 0 : 0 : 1) --> origin (= handle #3)
+ */
+ for (int j = 0; j < 4; ++j) {
+ tmat[0][j] = hand.pts[j][0];
+ tmat[1][j] = hand.pts[j][1];
+ tmat[2][j] = 1;
+ }
+
+ *notify << "Projection matrix:" << endl;
+ for (auto & i : tmat) {
+ for (double j : i) {
+ *notify << j << " ";
+ }
+ *notify << endl;
+ }
+
+ // draw the projective images of the box's corners
+ for (int i = 0; i < 8; ++i) {
+ corners[i] = proj_image (cr, c[i], hand.pts);
+ }
+ draw_box(cr, corners);
+ cairo_set_line_width (cr, 2);
+ cairo_stroke(cr);
+
+ {
+ D2<Piecewise<SBasis> > B = make_cuts_independent(path_a_pw);
+ Piecewise<SBasis> preimage[4];
+
+ if(togs[0].on) {
+ preimage[0] = sin((B[0] - orig[0]) / 100);
+ preimage[1] = -(B[1] - orig[1]) / 100;
+ preimage[2] = cos((B[0] - orig[0]) / 100);
+ } else { //if(togs[1].state) {
+ Piecewise<SBasis> sphi = sin((B[0] - orig[0]) / 200);
+ Piecewise<SBasis> cphi = cos((B[0] - orig[0]) / 200);
+
+ preimage[0] = -sphi*sin((B[1] - orig[1]) / 200);
+ preimage[1] = -sphi*cos((B[1] - orig[1]) / 200);
+ preimage[2] = -cphi;
+ }
+ Piecewise<SBasis> res[3];
+ for (int j = 0; j < 3; ++j) {
+ res[j] =
+ (preimage[0]) * tmat[j][0]
+ + (preimage[1] - ((hand.pts[5][1]-300)/100)) * tmat[j][1]
+ + (preimage[2] - ((hand.pts[6][1]-00)/100)) * tmat[j][2]
+ +( - (hand.pts[4][1]-300)/100) * tmat[j][0] + tmat[j][3];
+ }
+ //if (fabs (res[2]) > 0.000001) {
+ D2<Piecewise<SBasis> > result(divide(res[0],res[2], 4),
+ divide(res[1],res[2], 4));
+
+ cairo_d2_pw_sb(cr, result);
+ cairo_set_source_rgba (cr, 0., 0.125, 0, 1);
+ cairo_stroke(cr);
+ }
+ draw_toggles(cr, togs);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+ void first_time(int argc, char** argv) override {
+ const char *path_a_name="star.svgd";
+ if(argc > 1)
+ path_a_name = argv[1];
+ PathVector paths_a = read_svgd(path_a_name);
+ assert(!paths_a.empty());
+ path_a = paths_a[0];
+
+ path_a.close(true);
+ path_a_pw = path_a.toPwSb();
+
+ // Finite images of the three vanishing points and the origin
+ hand.pts.emplace_back(150,300);
+ hand.pts.emplace_back(380,40);
+ hand.pts.emplace_back(550,350);
+ hand.pts.emplace_back(340,450);
+
+ // Hand.Pts for moving in axes directions
+ hand.pts.emplace_back(30,300);
+ hand.pts.emplace_back(45,300);
+ hand.pts.emplace_back(60,300);
+
+ // Box corners
+ for (int i = 0; i < 8; ++i) {
+ c[i][0] = ((i & 1) ? 1 : 0);
+ c[i][1] = ((i & 2) ? 1 : 0);
+ c[i][2] = ((i & 4) ? 1 : 0);
+ c[i][3] = 1;
+ }
+
+ // Origin handle
+ hand.pts.emplace_back(180,70);
+ togs.emplace_back("S", true);
+ handles.push_back(&hand);
+ }
+ void key_hit(GdkEventKey *e) override {
+ if(e->keyval == 'c') togs[0].set(1); else
+ if(e->keyval == 's') togs[0].set(0);
+ redraw();
+ }
+ void mouse_pressed(GdkEventButton* e) override {
+ toggle_events(togs, e);
+ Toy::mouse_pressed(e);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new Box3d);
+ return 0;
+}
+
+void draw_box (cairo_t *cr, Geom::Point corners[8]) {
+ cairo_move_to(cr,corners[0]);
+ cairo_line_to(cr,corners[1]);
+ cairo_line_to(cr,corners[3]);
+ cairo_line_to(cr,corners[2]);
+ cairo_close_path(cr);
+
+ cairo_move_to(cr,corners[4]);
+ cairo_line_to(cr,corners[5]);
+ cairo_line_to(cr,corners[7]);
+ cairo_line_to(cr,corners[6]);
+ cairo_close_path(cr);
+
+ cairo_move_to(cr,corners[0]);
+ cairo_line_to(cr,corners[4]);
+
+ cairo_move_to(cr,corners[1]);
+ cairo_line_to(cr,corners[5]);
+
+ cairo_move_to(cr,corners[2]);
+ cairo_line_to(cr,corners[6]);
+
+ cairo_move_to(cr,corners[3]);
+ cairo_line_to(cr,corners[7]);
+}
+
+void draw_slider_lines (cairo_t *cr) {
+ cairo_move_to(cr, Geom::Point(20,300));
+ cairo_line_to(cr, Geom::Point(70,300));
+
+ cairo_move_to(cr, Geom::Point(30,00));
+ cairo_line_to(cr, Geom::Point(30,450));
+
+ cairo_move_to(cr, Geom::Point(45,00));
+ cairo_line_to(cr, Geom::Point(45,450));
+
+ cairo_move_to(cr, Geom::Point(60,00));
+ cairo_line_to(cr, Geom::Point(60,450));
+
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0.2, 0.2, 0.2, 1);
+ cairo_stroke(cr);
+}
+
+static Geom::Point proj_image (cairo_t *cr, const double pt[4], const vector<Geom::Point> &handles)
+{
+ double res[3];
+ for (int j = 0; j < 3; ++j) {
+ res[j] =
+ tmat[j][0] * (pt[0] - (handles[4][1]-300)/100)
+ + tmat[j][1] * (pt[1] - (handles[5][1]-300)/100)
+ + tmat[j][2] * (pt[2] - (handles[6][1]-300)/100)
+ + tmat[j][3] * pt[3];
+ }
+ if (fabs (res[2]) > 0.000001) {
+ Geom::Point result = Geom::Point (res[0]/res[2], res[1]/res[2]);
+ draw_handle(cr, result);
+ return result;
+ }
+ assert(0); // unclipped point
+ return Geom::Point(0,0);
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/d2sbasis-fitting-with-np.cpp b/src/3rdparty/2geom/src/toys/d2sbasis-fitting-with-np.cpp
new file mode 100644
index 0000000..05bcc6c
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/d2sbasis-fitting-with-np.cpp
@@ -0,0 +1,147 @@
+/*
+ * D2<SBasis> Fitting Example
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#include <2geom/numeric/fitting-tool.h>
+#include <2geom/numeric/fitting-model.h>
+
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+
+using namespace Geom;
+
+
+class D2SBasisFitting : public Toy
+{
+ private:
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ bool changed = false;
+ for (size_t i = 0; i < total_handles; ++i)
+ {
+ if (psh.pts[i] != prev_pts[i])
+ {
+ changed = true;
+ break;
+ }
+ }
+ if (changed)
+ {
+ for (size_t k = 0; k < 200; ++k)
+ {
+ lsf_2dsb.clear();
+ lsf_2dsb.append(0);
+ lsf_2dsb.append(0.33);
+ double t = 0;
+ for (size_t i = 2; i < total_handles-2; ++i)
+ {
+ t = nearest_time(psh.pts[i], sb_curve);
+ lsf_2dsb.append(t);
+ }
+ lsf_2dsb.append(0.66);
+ lsf_2dsb.append(1);
+ lsf_2dsb.update();
+ fmd2sb.instance(sb_curve, lsf_2dsb.result(psh.pts));
+ }
+ prev_pts = psh.pts;
+ }
+
+ cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, 1.0);
+ cairo_set_line_width (cr, 0.3);
+ cairo_d2_sb(cr, sb_curve);
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ D2SBasisFitting()
+ : sb_curve(),
+ total_handles(8),
+ order(total_handles / 2 - 1),
+ fmd2sb(order),
+ lsf_2dsb(fmd2sb, total_handles),
+ prev_pts()
+ {
+ step = 1.0 / (total_handles - 1);
+ for (size_t i = 0; i < total_handles; ++i)
+ {
+ psh.push_back(400*uniform() + 50, 300*uniform() + 50);
+ }
+ handles.push_back(&psh);
+
+ double t = 0;
+ for (size_t i = 0; i < total_handles; ++i)
+ {
+ lsf_2dsb.append(t);
+ t += step;
+ }
+ prev_pts = psh.pts;
+ lsf_2dsb.update();
+ fmd2sb.instance(sb_curve, lsf_2dsb.result(prev_pts));
+ }
+
+ private:
+ D2<SBasis> sb_curve;
+ unsigned int total_handles;
+ unsigned int order;
+ NL::LFMD2SBasis fmd2sb;
+ NL::least_squeares_fitter<NL::LFMD2SBasis> lsf_2dsb;
+ std::vector<Point> prev_pts;
+ double step;
+ PointSetHandle psh;
+};
+
+
+
+int main(int argc, char **argv)
+{
+ init( argc, argv, new D2SBasisFitting(), 600, 600 );
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/d2sbasis-fitting.cpp b/src/3rdparty/2geom/src/toys/d2sbasis-fitting.cpp
new file mode 100644
index 0000000..7e9b233
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/d2sbasis-fitting.cpp
@@ -0,0 +1,120 @@
+/*
+ * D2<SBasis> Fitting Example
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#include <2geom/numeric/fitting-tool.h>
+#include <2geom/numeric/fitting-model.h>
+
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+
+using namespace Geom;
+
+
+class D2SBasisFitting : public Toy
+{
+ private:
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ fmd2sb.instance(sb_curve, lsf_2dsb.result(prev_pts, psh.pts));
+ prev_pts = psh.pts;
+
+ cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, 1.0);
+ cairo_set_line_width (cr, 0.3);
+ cairo_d2_sb(cr, sb_curve);
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ D2SBasisFitting()
+ : sb_curve(),
+ total_handles(6),
+ order(total_handles / 2 - 1),
+ fmd2sb(order),
+ lsf_2dsb(fmd2sb, total_handles),
+ prev_pts()
+ {
+ step = 1.0 / (total_handles - 1);
+ for (size_t i = 0; i < total_handles; ++i)
+ {
+ psh.push_back(400*uniform() + 50, 300*uniform() + 50);
+ }
+ handles.push_back(&psh);
+
+ double t = 0;
+ for (size_t i = 0; i < total_handles; ++i)
+ {
+ lsf_2dsb.append(t);
+ t += step;
+ }
+ prev_pts = psh.pts;
+ lsf_2dsb.update();
+ fmd2sb.instance(sb_curve, lsf_2dsb.result(prev_pts));
+ }
+
+ private:
+ D2<SBasis> sb_curve;
+ unsigned int total_handles;
+ unsigned int order;
+ NL::LFMD2SBasis fmd2sb;
+ NL::least_squeares_fitter<NL::LFMD2SBasis> lsf_2dsb;
+ std::vector<Point> prev_pts;
+ double step;
+ PointSetHandle psh;
+};
+
+
+
+int main(int argc, char **argv)
+{
+ init( argc, argv, new D2SBasisFitting(), 600, 600 );
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/data/london-locations.csv b/src/3rdparty/2geom/src/toys/data/london-locations.csv
new file mode 100644
index 0000000..e7299c9
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/data/london-locations.csv
@@ -0,0 +1,298 @@
+Harrow & Wealdstone,75.2,163.5
+Kenton,86.1,153.6
+South Kenton,91,143.5
+North Wembley,94.2,136.8
+Wembley Central,99.1,128
+Stonebridge Park,110.7,122.8
+Harlesden,120.1,116.7
+Willesden Junction,128.3,112.4
+Kensal Green,137.7,111.6
+Queen's Park,148.6,113.5
+Kilburn Park,155.2,115.1
+Maida Vale,158.7,110
+Warwick Avenue,161.1,104.9
+Paddington,164.1,98.5
+Edgware Road,168.2,103.7
+Marylebone,171,105.1
+Baker Street,175.3,105.1
+Regent's Park,181.7,103.9
+Oxford Circus,184.3,97.5
+Piccadilly Circus,188.3,92.5
+Charing Cross,192.9,91.3
+Embankment,195.2,91
+Waterloo,199.6,87.6
+Lambeth North,201.3,84.9
+Elephant & Castle,208.3,81.1
+West Ruislip,20.7,139.9
+Ruislip Gardens,35.6,133.5
+South Ruislip,42.8,130.5
+Northolt,58.8,123.9
+Greenford,72.4,119.4
+Perivale,84.3,115.6
+Hanger Lane,103,109.7
+North Acton,121.2,104.4
+Ealing Broadway,98.3,93.7
+West Acton,108.6,98.8
+East Acton,127.1,99
+White City,138.5,95.1
+Shepherd's Bush,141.7,87.7
+Holland Park,148,90.3
+Notting Hill Gate,152.6,91.8
+Queensway,158.4,92.9
+Lancaster Gate,165,94
+Marble Arch,174.8,96
+Bond Street,179.8,96.8
+Tottenham Court Road,189.9,98.4
+Holborn,195.7,99.3
+Chancery Lane,199.9,100.1
+St Paul's,207.8,97.8
+Bank,213,96.1
+Liverpool Street,216.9,101
+Bethnal Green,234.3,109.1
+Mile End,243.4,107.7
+Stratford,259.5,121.2
+Leyton,259.1,136.9
+Leytonstone,266.9,145.2
+Snaresbrook,272.5,153.7
+South Woodford,276,164.6
+Woodford,279.7,180.2
+Wanstead,277.9,150.9
+Redbridge,286.9,152.9
+Gants Hill,296.3,152.4
+Newbury Park,310.1,152
+Barkingside,309.3,160.9
+Fairlop,310.4,170.7
+Hainault,311.4,175.2
+Grange Hill,310.4,185.8
+Chigwell,299.8,190.2
+Roding Valley,285.7,190.8
+Buckhurst Hill,285.6,195.5
+Loughton,290.1,213.7
+Debden,306.5,214.6
+Theydon Bois,315.1,241.9
+Epping,320.3,264.7
+Tower Hill,220.7,94.3
+Aldgate,220.4,98.8
+Moorgate,212.5,102.2
+Barbican,208.1,102.9
+Farringdon,203.2,105
+King's Cross St Pancras,193.1,112.1
+Euston Square,188.1,107.1
+Great Portland Street,183.3,105.4
+Edgware Road,169.6,102.2
+Bayswater,158,95.3
+High Street Kensington,155.2,84.6
+Gloucester Road,161.2,78.8
+South Kensington,166.5,78.5
+Sloane Square,176.5,77.4
+Victoria,183,79.3
+St James's Park,187.9,83.1
+Westminster,193.7,85.4
+Temple,199.2,94.2
+Blackfriars,205.3,94.7
+Mansion House,210.3,94.3
+Cannon Street,213,93.8
+Monument,215.5,93.1
+Ealing Common,105.3,91.1
+Acton Town,109.2,85.1
+Chiswick Park,114.9,80.3
+Turnham Green,123.5,79.5
+Richmond,99.7,49.4
+Kew Gardens,107.8,61.9
+Gunnersbury,111.3,75.6
+Stamford Brook,128.1,79.3
+Ravenscourt Park,133.3,79.2
+Hammersmith,139.1,77.3
+Barons Court,144.1,75.1
+West Kensington,148.9,75.7
+Earl's Court,154.8,76.8
+Kensington (Olympia),146.3,82
+Wimbledon,152,15.1
+Wimbledon Park,155.2,25.7
+Southfields,150.2,36.6
+East Putney,147.5,46.4
+Putney Bridge,149.1,54.9
+Parsons Green,152.3,62.1
+Fulham Broadway,155.2,67.3
+West Brompton,154.4,72.7
+Aldgate East,222.9,99.8
+Whitechapel,228.6,102.8
+Stepney Green,236.3,105.3
+Bow Road,249.5,107.1
+Bromley-by-Bow,256.1,106.2
+West Ham,264.2,110.7
+Plaistow,271.2,113.4
+Upton Park,280.7,116
+East Ham,291.9,120.2
+Barking,305.8,121.1
+Upney,316.3,118.7
+Becontree,330.3,121.8
+Dagenham Heathway,340.3,122.7
+Dagenham East,350.3,125.4
+Elm Park,369.8,130.4
+Hornchurch,378.4,133.8
+Upminster Bridge,386.5,137.2
+Upminster,397.5,138.6
+Shoreditch,223,103.3
+Shadwell,231.3,96
+Wapping,231.8,89.2
+Rotherhithe,233.1,85.5
+Canada Water,234.3,83.5
+Surrey Quays,237.1,78
+New Cross Gate,241.3,63.5
+New Cross,245,64.3
+Hammersmith,137.7,80.1
+Goldhawk Road,136.8,85.7
+Shepherd's Bush,137,89.2
+Latimer Road,142.5,95.9
+Ladbroke Grove,145.5,99.1
+Westbourne Park,150,101.9
+Royal Oak,158.1,100.2
+Stanmore,93.9,186.2
+Canons Park,97.2,177.9
+Queensbury,101.1,165.5
+Kingsbury,106.7,156.6
+Wembley Park,106.4,139.6
+Neasden,123.8,131.6
+Dollis Hill,129.7,129.9
+Willesden Green,139.1,128.9
+Kilburn,147.4,128.2
+West Hampstead,157.2,127.2
+Finchley Road,162.4,126.9
+Swiss Cottage,164.7,123.3
+St John's Wood,164.8,115.1
+Green Park,184.1,89.6
+Southwark,204.4,88.5
+London Bridge,214.4,89.7
+Bermondsey,225,84.5
+Canary Wharf,254,88.1
+North Greenwich,269.3,88
+Canning Town,267.7,96.2
+Watford,29.9,219.2
+Croxley,15.2,210.9
+Moor Park,22,194.9
+Northwood,27.7,177.9
+Northwood Hills,35.4,169.1
+Pinner,51.6,163.4
+North Harrow,60.4,157.3
+Harrow-on-the-Hill,76,149.6
+Uxbridge,2,121.7
+Hillingdon,14,126.4
+Ickenham,17.6,133.5
+Ruislip,28.9,142.2
+Ruislip Manor,34.2,144.6
+Eastcote,43.2,147.3
+Rayners Lane,56.3,146.9
+West Harrow,66.4,150
+Northwick Park,84.8,149.9
+Preston Road,97.8,146.4
+Edgware,107.3,182.3
+Burnt Oak,113.7,173.6
+Colindale,122.1,167.5
+Hendon Central,135.2,157.6
+Bent Cross,141.9,151.7
+Golders Green,154.3,146.9
+Hampstead,164.8,135.3
+Belsize Park,171.2,129.1
+Chalk Farm,176.2,124.3
+Camden Town,182,121.2
+High Barnet,150.8,219.3
+Totteridge & Whetstone,159.7,200.8
+Woodside Park,156.8,188.9
+West Finchley,154.5,181.9
+Finchley Central,154.5,172.7
+Mill Hill East,142.9,180.2
+East Finchley,168.9,161.8
+Highgate,180.5,152.8
+Archway,186.2,144.1
+Tufnell Park,186,136.6
+Kentish Town,184.4,129.9
+Mornington Crescent,184.6,114.9
+Euston,187.9,110.1
+Angel,203.9,113.6
+Old Street,212.2,108.4
+Borough,210.5,85.8
+Kennington,204.3,74.8
+Warren Street,185.4,104.9
+Goodge Street,187.9,101.9
+Leicester Square,191.4,94.2
+Oval,200,69.1
+Stockwell,195.3,60.4
+Clapham North,191.2,52.6
+Clapham Common,186,49.2
+Clapham South,181.6,41.9
+Balham,178.6,34.2
+Tooting Bec,176.2,28.2
+Tooting Broadway,171.2,17.6
+Colliers Wood,166.8,11.2
+South Wimbledon,159.4,7.9
+Morden,155.1,1.5
+Heathrow Terminals 1-2-3,20.5,53.7
+Heathrow Terminal 4,24.4,46.8
+Hatton Cross,35,51.4
+Hounslow West,57,57
+Hounslow Central,65.2,55.4
+Hounslow East,70.8,57.8
+Osterley,74,65
+Boston Manor,87.1,76.2
+Northfields,91.8,80.2
+South Ealing,95.6,81.7
+South Harrow,67.8,137.1
+Sudbury Hill,75.6,131.2
+Sudbury Town,88.1,127
+Alperton,97.1,119
+Park Royal,107,106
+North Ealing,105.2,98.1
+Knightsbridge,173.7,85.1
+Hyde Park Corner,178.1,86.5
+Covent Garden,193.7,95.6
+Russell Square,192.9,104.7
+Caledonian Road,196,128.8
+Holloway Road,200.2,132.5
+Arsenal,202.7,137.9
+Finsbury Park,203.8,143.9
+Manor House,208.6,149.6
+Turnpike Lane,204.2,165.8
+Wood Green,200.5,172.4
+Bounds Green,190.4,181.2
+Arnos Grove,186.3,189
+Southgate,188.2,201.3
+Oakwood,186.3,216.8
+Cockfosters,177.6,220.3
+Brixton,201.7,52.2
+Vauxhall,194.7,72.4
+Pimlico,189.8,75.5
+Highbury & Islington,204.1,126
+Seven Sisters,219.2,160.5
+Tottenham Hale,228.2,164.8
+Blackhorse Road,238.5,162.7
+Walthamstow Central,253.4,161.1
+Limehouse,239.2,97.1
+Westferry,246.8,95.3
+Poplar,254.6,93.8
+All Saints,256.2,96.4
+Devons Road,253.3,103.8
+Bow Church,250.9,108.9
+Pudding Mill Lane,255.8,115.7
+West India Quay,252.2,91.3
+Heron Quay,252,86.8
+South Quay,254.1,85.5
+Crossharbour and London Arena,256.1,80.3
+Mudchute,257.1,76.5
+Island Gardens,259,74.3
+Cutty Sark,259.2,69.3
+Greenwich,256.1,65.7
+Deptford Bridge,253.9,63.7
+Elverston Road,254.6,58.3
+Lewisham,256.5,54.5
+Blackwall,258.7,93.7
+East India,263.3,94.3
+Royal Victoria,272.5,93
+Custom House,277.9,93.2
+Prince Regent,281.4,93.3
+Royal Albert,288.9,93.2
+Beckton Park,292.7,93.3
+Cyprus,296.6,93.3
+Gallions Reach,301.5,94.2
+Beckton,296,99.3
+Tower Gateway,222.7,94.7
diff --git a/src/3rdparty/2geom/src/toys/data/london.txt b/src/3rdparty/2geom/src/toys/data/london.txt
new file mode 100644
index 0000000..49e6f9c
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/data/london.txt
@@ -0,0 +1,86 @@
+Bakerloo Line:
+Harrow & Wealdstone,Kenton,South Kenton,North Wembley,Wembley Central,Stonebridge Park,Harlesden,Willesden Junction,Kensal Green,Queen's Park,Kilburn Park,Maida Vale,Warwick Avenue,Paddington,Edgware Road,Marylebone,Baker Street,Regent's Park,Oxford Circus,Piccadilly Circus,Charing Cross,Embankment,Waterloo,Lambeth North,Elephant & Castle
+
+Central Line 1:
+West Ruislip,Ruislip Gardens,South Ruislip,Northolt,Greenford,Perivale,Hanger Lane,North Acton,East Acton,White City,Shepherd's Bush,Holland Park,Notting Hill Gate,Queensway,Lancaster Gate,Marble Arch,Bond Street,Oxford Circus,Tottenham Court Road,Holborn,Chancery Lane,St Paul's,Bank,Liverpool Street,Bethnal Green,Mile End,Stratford,Leyton,Leytonstone,Snaresbrook,South Woodford,Woodford,Buckhurst Hill,Loughton,Debden,Theydon Bois,Epping
+
+Central Line 2:
+West Ruislip,Ruislip Gardens,South Ruislip,Northolt,Greenford,Perivale,Hanger Lane,North Acton,East Acton,White City,Shepherd's Bush,Holland Park,Notting Hill Gate,Queensway,Lancaster Gate,Marble Arch,Bond Street,Oxford Circus,Tottenham Court Road,Holborn,Chancery Lane,St Paul's,Bank,Liverpool Street,Bethnal Green,Mile End,Stratford,Leyton,Leytonstone,Wanstead,Redbridge,Gants Hill,Newbury Park,Barkingside,Fairlop,Hainault,Grange Hill,Chigwell,Roding Valley,Woodford
+
+Central Line 3:
+Ealing Broadway,West Acton,North Acton,East Acton,White City,Shepherd's Bush,Holland Park,Notting Hill Gate,Queensway,Lancaster Gate,Marble Arch,Bond Street,Oxford Circus,Tottenham Court Road,Holborn,Chancery Lane,St Paul's,Bank,Liverpool Street,Bethnal Green,Mile End,Stratford,Leyton,Leytonstone,Snaresbrook,South Woodford,Woodford,Buckhurst Hill,Loughton,Debden,Theydon Bois,Epping
+
+Central Line 4:
+Ealing Broadway,West Acton,North Acton,East Acton,White City,Shepherd's Bush,Holland Park,Notting Hill Gate,Queensway,Lancaster Gate,Marble Arch,Bond Street,Oxford Circus,Tottenham Court Road,Holborn,Chancery Lane,St Paul's,Bank,Liverpool Street,Bethnal Green,Mile End,Stratford,Leyton,Leytonstone,Wanstead,Redbridge,Gants Hill,Newbury Park,Barkingside,Fairlop,Hainault,Grange Hill,Chigwell,Roding Valley,Woodford
+
+Circle Line 1:
+Westminster,St James's Park,Victoria,Sloane Square,South Kensington,Gloucester Road,High Street Kensington,Notting Hill Gate,Bayswater,Paddington,Edgware Road,Baker Street,Great Portland Street,Euston Square,King's Cross St Pancras,Farringdon,Barbican,Moorgate,Liverpool Street,Aldgate
+
+Circle Line 2:
+Tower Hill,Monument,Cannon Street,Mansion House,Blackfriars,Temple,Embankment,Westminster
+
+Hammersmith & City Line:
+Hammersmith,Goldhawk Road,Shepherd's Bush,Latimer Road,Ladbroke Grove,Westbourne Park,Royal Oak,Paddington,Edgware Road,Baker Street,Great Portland Street,Euston Square,King's Cross St Pancras,Farringdon,Barbican,Moorgate,Liverpool Street,Aldgate East,Whitechapel,Stepney Green,Mile End,Bow Road,Bromley-by-Bow,West Ham,Plaistow,Upton Park,East Ham,Barking
+
+District Line 1:
+Ealing Broadway,Ealing Common,Acton Town,Chiswick Park,Turnham Green,Stamford Brook,Ravenscourt Park,Hammersmith,Barons Court,West Kensington,Earl's Court,Gloucester Road,South Kensington,Sloane Square,Victoria,St James's Park,Westminster,Embankment,Temple,Blackfriars,Mansion House,Cannon Street,Monument,Tower Hill,Aldgate East,Whitechapel,Stepney Green,Mile End,Bow Road,Bromley-by-Bow,West Ham,Plaistow,Upton Park,East Ham,Barking,Upney,Becontree,Dagenham Heathway,Dagenham East,Elm Park,Hornchurch,Upminster Bridge,Upminster
+
+District Line 2:
+Richmond,Kew Gardens,Gunnersbury,Turnham Green,Stamford Brook,Ravenscourt Park,Hammersmith,Barons Court,West Kensington,Earl's Court,Gloucester Road,South Kensington,Sloane Square,Victoria,St James's Park,Westminster,Embankment,Temple,Blackfriars,Mansion House,Cannon Street,Monument,Tower Hill,Aldgate East,Whitechapel,Stepney Green,Mile End,Bow Road,Bromley-by-Bow,West Ham,Plaistow,Upton Park,East Ham,Barking,Upney,Becontree,Dagenham Heathway,Dagenham East,Elm Park,Hornchurch,Upminster Bridge,Upminster
+
+District Line 3:
+Wimbledon,Wimbledon Park,Southfields,East Putney,Putney Bridge,Parsons Green,Fulham Broadway,West Brompton,Earl's Court,Gloucester Road,South Kensington,Sloane Square,Victoria,St James's Park,Westminster,Embankment,Temple,Blackfriars,Mansion House,Cannon Street,Monument,Tower Hill,Aldgate East,Whitechapel,Stepney Green,Mile End,Bow Road,Bromley-by-Bow,West Ham,Plaistow,Upton Park,East Ham,Barking,Upney,Becontree,Dagenham Heathway,Dagenham East,Elm Park,Hornchurch,Upminster Bridge,Upminster
+
+District Line 4:
+Kensington (Olympia),Earl's Court,High Street Kensington,Notting Hill Gate,Bayswater,Paddington,Edgware Road
+
+East London Line 1:
+Shoreditch,Whitechapel,Shadwell,Wapping,Rotherhithe,Canada Water,Surrey Quays,New Cross
+
+East London Line 2:
+Shoreditch,Whitechapel,Shadwell,Wapping,Rotherhithe,Canada Water,Surrey Quays,New Cross Gate
+
+Jubilee Line:
+Stratford,West Ham,Canning Town,North Greenwich,Canary Wharf,Canada Water,Bermondsey,London Bridge,Southwark,Waterloo,Westminster,Green Park,Bond Street,Baker Street,St John's Wood,Swiss Cottage,Finchley Road,West Hampstead,Kilburn,Willesden Green,Dollis Hill,Neasden,Wembley Park,Kingsbury,Queensbury,Canons Park,Stanmore
+
+Metropolitan Line 1:
+Moor Park,Northwood,Northwood Hills,Pinner,North Harrow,Harrow-on-the-Hill,Northwick Park,Preston Road,Wembley Park,Finchley Road,Baker Street,Great Portland Street,Euston Square,King's Cross St Pancras,Farringdon,Barbican,Moorgate,Liverpool Street,Aldgate
+
+Metropolitan Line 2:
+Watford,Croxley,Moor Park,Northwood,Northwood Hills,Pinner,North Harrow,Harrow-on-the-Hill,Northwick Park,Preston Road,Wembley Park,Finchley Road,Baker Street,Great Portland Street,Euston Square,King's Cross St Pancras,Farringdon,Barbican,Moorgate,Liverpool Street,Aldgate
+
+Metropolitan Line 3:
+Uxbridge,Hillingdon,Ickenham,Ruislip,Ruislip Manor,Eastcote,Rayners Lane,West Harrow,Harrow-on-the-Hill,Northwick Park,Preston Road,Wembley Park,Finchley Road,Baker Street,Great Portland Street,Euston Square,King's Cross St Pancras,Farringdon,Barbican,Moorgate,Liverpool Street,Aldgate
+
+Northern Line 1:
+High Barnet,Totteridge & Whetstone,Woodside Park,West Finchley,Finchley Central,East Finchley,Highgate,Archway,Tufnell Park,Kentish Town,Camden Town,Euston,King's Cross St Pancras,Angel,Old Street,Moorgate,Bank,London Bridge,Borough,Elephant & Castle,Kennington,Oval,Stockwell,Clapham North,Clapham Common,Clapham South,Balham,Tooting Bec,Tooting Broadway,Colliers Wood,South Wimbledon,Morden
+
+Northern Line 2:
+High Barnet,Totteridge & Whetstone,Woodside Park,West Finchley,Finchley Central,East Finchley,Highgate,Archway,Tufnell Park,Kentish Town,Camden Town,Mornington Crescent,Euston,Warren Street,Goodge Street,Tottenham Court Road,Leicester Square,Charing Cross,Embankment,Waterloo,Kennington,Oval,Stockwell,Clapham North,Clapham Common,Clapham South,Balham,Tooting Bec,Tooting Broadway,Colliers Wood,South Wimbledon,Morden
+
+Northern Line 3:
+Mill Hill East,Finchley Central,East Finchley,Highgate,Archway,Tufnell Park,Kentish Town,Camden Town,Euston,King's Cross St Pancras,Angel,Old Street,Moorgate,Bank,London Bridge,Borough,Elephant & Castle,Kennington,Oval,Stockwell,Clapham North,Clapham Common,Clapham South,Balham,Tooting Bec,Tooting Broadway,Colliers Wood,South Wimbledon,Morden
+
+Northern Line 4:
+Mill Hill East,Finchley Central,East Finchley,Highgate,Archway,Tufnell Park,Kentish Town,Camden Town,Mornington Crescent,Euston,Warren Street,Goodge Street,Tottenham Court Road,Leicester Square,Charing Cross,Embankment,Waterloo,Kennington,Oval,Stockwell,Clapham North,Clapham Common,Clapham South,Balham,Tooting Bec,Tooting Broadway,Colliers Wood,South Wimbledon,Morden
+
+Northern Line 5:
+Edgware,Burnt Oak,Colindale,Hendon Central,Bent Cross,Golders Green,Hampstead,Belsize Park,Chalk Farm,Camden Town,Euston,King's Cross St Pancras,Angel,Old Street,Moorgate,Bank,London Bridge,Borough,Elephant & Castle,Kennington,Oval,Stockwell,Clapham North,Clapham Common,Clapham South,Balham,Tooting Bec,Tooting Broadway,Colliers Wood,South Wimbledon,Morden
+
+Northern Line 6:
+Edgware,Burnt Oak,Colindale,Hendon Central,Bent Cross,Golders Green,Hampstead,Belsize Park,Chalk Farm,Camden Town,Mornington Crescent,Euston,Warren Street,Goodge Street,Tottenham Court Road,Leicester Square,Charing Cross,Embankment,Waterloo,Kennington,Oval,Stockwell,Clapham North,Clapham Common,Clapham South,Balham,Tooting Bec,Tooting Broadway,Colliers Wood,South Wimbledon,Morden
+
+Piccadilly Line 1:
+Uxbridge,Hillingdon,Ickenham,Ruislip,Ruislip Manor,Eastcote,Rayners Lane,South Harrow,Sudbury Hill,Sudbury Town,Alperton,Park Royal,North Ealing,Ealing Common,Acton Town,Turnham Green,Hammersmith,Barons Court,Earl's Court,Gloucester Road,South Kensington,Knightsbridge,Hyde Park Corner,Green Park,Piccadilly Circus,Leicester Square,Covent Garden,Holborn,Russell Square,King's Cross St Pancras,Caledonian Road,Holloway Road,Arsenal,Finsbury Park,Manor House,Turnpike Lane,Wood Green,Bounds Green,Arnos Grove,Southgate,Oakwood,Cockfosters
+
+Piccadilly Line 2:
+Heathrow Terminal 4,Hatton Cross,Hounslow West,Hounslow Central,Hounslow East,Osterley,Boston Manor,Northfields,South Ealing,Acton Town,Turnham Green,Hammersmith,Barons Court,Earl's Court,Gloucester Road,South Kensington,Knightsbridge,Hyde Park Corner,Green Park,Piccadilly Circus,Leicester Square,Covent Garden,Holborn,Russell Square,King's Cross St Pancras,Caledonian Road,Holloway Road,Arsenal,Finsbury Park,Manor House,Turnpike Lane,Wood Green,Bounds Green,Arnos Grove,Southgate,Oakwood,Cockfosters
+
+Piccadilly Line 3:
+Hatton Cross,Heathrow Terminals 1-2-3,Heathrow Terminal 4
+
+Victoria Line:
+Walthamstow Central,Blackhorse Road,Tottenham Hale,Seven Sisters,Finsbury Park,Highbury & Islington,King's Cross St Pancras,Euston,Warren Street,Oxford Circus,Green Park,Victoria,Pimlico,Vauxhall,Stockwell,Brixton
+
+Waterloo & City Line:
+Waterloo,Bank
diff --git a/src/3rdparty/2geom/src/toys/data/nsw-centre.txt b/src/3rdparty/2geom/src/toys/data/nsw-centre.txt
new file mode 100644
index 0000000..73b6817
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/data/nsw-centre.txt
@@ -0,0 +1,56 @@
+Olympic Park I:
+Central,Redfern,Macdonaldtown,Newtown,Stanmore,Petersham,Lewisham,Summer Hill,Ashfield,Croydon,Burwood,Strathfield,Homebush,Flemington,Olympic Park
+
+Olympic Park II:
+Blacktown,Seven Hills,Toongabbie,Pendle Hill,Wentworthville,Westmead,Parramatta,Harris Park,Granville,Clyde,Auburn,Lidcombe,Olympic Park
+
+Eastern Suburbs & Illawarra 1:
+Waterfall,Heathcote,Engadine,Loftus,Sutherland,Jannali,Como,Oatley,Mortdale,Penshurst,Hurstville,Allawah,Carlton,Kogarah,Rockdale,Banksia,Arncliffe,Wolli Creek,Tempe,Sydenham,St Peters,Erskineville,Redfern,Central,Town Hall,Martin Place,Kings Cross,Edgecliff,Bondi Junction
+
+Eastern Suburbs & Illawarra 2:
+Cronulla,Woolooware,Caringbah,Miranda,Gymea,Kirrawee,Sutherland,Jannali,Como,Oatley,Mortdale,Penshurst,Hurstville,Allawah,Carlton,Kogarah,Rockdale,Banksia,Arncliffe,Wolli Creek,Tempe,Sydenham,St Peters,Erskineville,Redfern,Central,Town Hall,Martin Place,Kings Cross,Edgecliff,Bondi Junction
+
+Bankstown Line a:
+Town Hall,Wynyard,Circular Quay,St James,Museum,Central,Redfern,Erskineville,St Peters,Sydenham,Marrickville,Dulwich Hill,Hurlstone Park,Canterbury,Campsie,Belmore,Lakemba,Wiley Park,Punchbowl,Bankstown,Yagoona,Birrong,Regents Park,Berala,Lidcombe
+
+Bankstown Line b:
+Lidcombe,Berala,Regents Park,Birrong,Sefton,Chester Hill,Leightonfield,Villawood,Carramar,Cabramatta,Warwick Farm,Liverpool
+
+Inner West 1a:
+Liverpool,Warwick Farm,Cabramatta,Carramar,Villawood,Leightonfield,Chester Hill,Sefton,Regents Park,Berala,Lidcombe,Flemington,Homebush,Strathfield,Burwood,Croydon,Ashfield,Summer Hill,Lewisham,Petersham,Stanmore,Newtown,Macdonaldtown,Redfern,Central,Town Hall,Wynyard,Circular Quay,St James,Museum
+
+Inner West 1b:
+Central,Town Hall,Wynyard,Milsons Point,North Sydney,Waverton,Wollstonecraft,St Leonards,Artarmon,Chatswood
+
+Inner West 2a:
+Parramatta,Harris Park,Granville,Clyde,Auburn,Lidcombe,Flemington,Homebush,Strathfield,Burwood,Croydon,Ashfield,Summer Hill,Lewisham,Petersham,Stanmore,Newtown,Macdonaldtown,Redfern,Central,Town Hall,Wynyard,Circular Quay,St James,Museum
+
+Inner West 2b:
+Central,Town Hall,Wynyard,Milsons Point,North Sydney,Waverton,Wollstonecraft,St Leonards,Artarmon,Chatswood
+
+Airport & East Hills 1:
+Macarthur,Campbelltown,Leumeah,Minto,Ingleburn,Macquarie Fields,Glenfield,Holsworthy,East Hills,Panania,Revesby,Padstow,Riverwood,Narwee,Beverly Hills,Kingsgrove,Bexley North,Bardwell Park,Turrella,Wolli Creek,International,Domestic,Mascot,Green Square,Central,Museum,St James,Circular Quay,Wynyard,Town Hall
+
+Airport & East Hills 2:
+Macarthur,Campbelltown,Leumeah,Minto,Ingleburn,Macquarie Fields,Glenfield,Holsworthy,East Hills,Panania,Revesby,Padstow,Riverwood,Narwee,Beverly Hills,Kingsgrove,Bexley North,Bardwell Park,Turrella,Tempe,Sydenham,St Peters,Erskineville,Redfern,Central,Museum,St James,Circular Quay,Wynyard,Town Hall
+
+South:
+Macarthur,Campbelltown,Leumeah,Minto,Ingleburn,Macquarie Fields,Glenfield,Casula,Liverpool,Warwick Farm,Cabramatta,Canley Vale,Fairfield,Yennora,Guildford,Merrylands,Granville,Clyde,Auburn,Lidcombe,Flemington,Homebush,Strathfield,Burwood,Croydon,Ashfield,Summer Hill,Lewisham,Petersham,Stanmore,Newtown,Macdonaldtown,Redfern,Central,Town Hall,Wynyard,Circular Quay,St James,Museum
+
+Cumberland:
+Campbelltown,Leumeah,Minto,Ingleburn,Macquarie Fields,Glenfield,Casula,Liverpool,Warwick Farm,Cabramatta,Canley Vale,Fairfield,Yennora,Guildford,Merrylands,Harris Park,Parramatta,Westmead,Wentworthville,Pendle Hill,Toongabbie,Seven Hills,Blacktown,Doonside,Rooty Hill,Mt Druitt,St Marys
+
+Carlingford Line:
+Carlingford,Telopea,Dundas,Rydalmere,Camellia,Rosehill,Clyde
+
+Western 1:
+Richmond,East Richmond,Clarendon,Windsor,Mulgrave,Vineyard,Riverstone,Schofields,Quakers Hill,Marayong,Blacktown,Seven Hills,Toongabbie,Pendle Hill,Wentworthville,Westmead,Parramatta,Harris Park,Granville,Clyde,Auburn,Lidcombe,Flemington,Homebush,Strathfield,Burwood,Croydon,Ashfield,Summer Hill,Lewisham,Petersham,Stanmore,Newtown,Macdonaldtown,Redfern,Central,Town Hall,Wynyard,Milsons Point,North Sydney
+
+Western 2:
+Emu Plains,Penrith,Kingswood,Werrington,St Marys,Mt Druitt,Rooty Hill,Doonside,Blacktown,Seven Hills,Toongabbie,Pendle Hill,Wentworthville,Westmead,Parramatta,Harris Park,Granville,Clyde,Auburn,Lidcombe,Flemington,Homebush,Strathfield,Burwood,Croydon,Ashfield,Summer Hill,Lewisham,Petersham,Stanmore,Newtown,Macdonaldtown,Redfern,Central,Town Hall,Wynyard,Milsons Point,North Sydney
+
+North Shore:
+Berowra,Mt Kuring-gai,Mt Colah,Asquith,Hornsby,Waitara,Wahroonga,Warrawee,Turramurra,Pymble,Gordon,Killara,Lindfield,Roseville,Chatswood,Artarmon,St Leonards,Wollstonecraft,Waverton,North Sydney,Milsons Point,Wynyard,Town Hall,Central,Redfern,Macdonaldtown,Newtown,Stanmore,Petersham,Lewisham,Summer Hill,Ashfield,Croydon,Burwood,Strathfield,Homebush,Flemington,Lidcombe,Auburn,Clyde,Granville,Harris Park,Parramatta
+
+Northern:
+Berowra,Mt Kuring-gai,Mt Colah,Asquith,Hornsby,Normanhurst,Thornleigh,Pennant Hills,Beecroft,Cheltenham,Epping,Eastwood,Denistone,West Ryde,Meadowbank,Rhodes,Concord West,North Strathfield,Strathfield,Burwood,Croydon,Ashfield,Summer Hill,Lewisham,Petersham,Stanmore,Newtown,Macdonaldtown,Redfern,Central,Town Hall,Wynyard,Milsons Point,North Sydney
diff --git a/src/3rdparty/2geom/src/toys/data/nsw-locations.csv b/src/3rdparty/2geom/src/toys/data/nsw-locations.csv
new file mode 100644
index 0000000..2cb6d13
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/data/nsw-locations.csv
@@ -0,0 +1,805 @@
+Aberdare Junction,151.513199,-32.773602
+Aberdeen,150.892593,-32.165401
+Adamstown,151.718307,-32.933899
+Albion Park,150.798203,-34.562698
+Albury,146.922302,-36.0863
+Alectown West,148.171906,-32.934101
+Allandale,151.416306,-32.720699
+Allawah,151.113098,-33.9692
+Alleena,147.134903,-34.072399
+Antiene,150.984695,-32.335999
+Ariah Park,147.2164,-34.344398
+Armidale,151.652206,-30.514
+Arncliffe,151.147095,-33.935299
+Artarmon,151.185593,-33.8069
+Ashfield,151.125504,-33.886799
+Ashley,149.800201,-29.297001
+Asquith,151.1082,-33.688202
+Athol,149.303604,-33.5452
+Auburn,151.032501,-33.8489
+Austinmer,150.928207,-34.305901
+Awaba,151.540604,-33.012501
+Baan Baa,149.951096,-30.599501
+Balldale,146.515106,-35.846199
+Ballina,153.554993,-28.860001
+Balmoral,150.521194,-34.305901
+Bangaroo,148.632599,-33.627602
+Banksia,151.138702,-33.944099
+Bankstown,151.034897,-33.917
+Barairmol,152.995102,-28.719601
+Barbigal,148.839905,-32.223202
+Bardwell Park,151.124405,-33.930901
+Bargo,150.579102,-34.291
+Bathurst,149.582199,-33.425999
+Beanbri,148.405701,-29.9536
+Beecroft,151.066803,-33.749199
+Beelbangera,146.099792,-34.254002
+Belford,151.274902,-32.6544
+Bell,150.278107,-33.506001
+Bellambi,150.909195,-34.362099
+Bellarwi,147.194702,-34.095001
+Bellata,149.786407,-29.918501
+Belmore,151.089203,-33.9161
+Bengerang,149.519608,-29.0714
+Beni,148.750595,-32.195099
+Berala,151.031906,-33.870998
+Beresfield,151.6586,-32.798901
+Berowra,151.153397,-33.623699
+Berry,150.695694,-34.780701
+Bethungra,147.860306,-34.763699
+Beverly Hills,151.082108,-33.9478
+Bexhill,153.346893,-28.761101
+Bexley North,151.111404,-33.937099
+Birrong,151.024399,-33.892601
+Black Springs,150.629395,-30.442801
+Blackheath,150.281998,-33.633301
+Blacktown,150.908707,-33.7668
+Blandford,150.898605,-31.788799
+Blaxland,150.608902,-33.742001
+Blayney,149.253799,-33.5261
+Bloomfield,149.105606,-33.319401
+Blue Cow,148.389801,-36.383701
+Boambee,153.1073,-30.348801
+Bogan Gate,147.801498,-33.108299
+Boggabri,150.038803,-30.702999
+Bomaderry,150.609695,-34.853298
+Bombo,150.852707,-34.658001
+Bomera,149.798798,-31.548
+Bon Accord,147.190903,-35.226501
+Bonalbo,152.623154,-28.73671
+Bondi Junction,151.246506,-33.893101
+Bonville,153.061996,-30.379
+Boomley,149.1035,-32.026798
+Booragul,151.604797,-32.970798
+Boothenba,148.689606,-32.198101
+Borenore,148.975693,-33.253101
+Bourke,145.933701,-30.094601
+Bowenfels,150.135406,-33.474998
+Bowral,150.416107,-34.4781
+Box Tank,142.2276,-32.201099
+Braemar,150.498596,-34.412498
+Branxton,151.345703,-32.6614
+Braunstone,152.961807,-29.8027
+Brightling,148.404999,-31.2185
+Broadmeadow,151.734406,-32.921902
+Broken Hill,141.466003,-31.9604
+Brolgan,148.063507,-33.142502
+Buddigower,147.008698,-34.0438
+Bullaburra,150.412796,-33.722301
+Bulli,150.9142,-34.333401
+Bulliac,152.035599,-31.914499
+Bullocks Flat,148.443207,-36.444698
+Bundanoon,150.300705,-34.655399
+Bundook,152.1259,-31.891199
+Bungabbee,153.146393,-28.780199
+Bungendore,149.444901,-35.254601
+Bunyan,149.158997,-36.1712
+Buralyang,146.760498,-33.974098
+Burgooney,146.574097,-33.385399
+Burradoo,150.397293,-34.493999
+Burrawang,150.529999,-34.581402
+Burren,148.966705,-30.1061
+Burringbar,153.471497,-28.4331
+Burwood,151.104706,-33.876301
+Buxton,150.532501,-34.2547
+Bygalorie,146.781693,-33.469002
+Byron,151.093994,-29.736401
+Cabramatta,150.938995,-33.8927
+Calleen,147.105804,-33.787701
+Calwalla,150.474304,-34.5625
+Camden,150.696899,-34.050701
+Camellia,151.025604,-33.817001
+Camira Creek,152.964203,-29.250401
+Campbelltown,150.812607,-34.063801
+Campsie,151.101303,-33.909901
+Canberra,149.150497,-35.3167
+Canberra (Civic),149.132904,-35.262299
+Canley Vale,150.944199,-33.886501
+Canterbury,151.117493,-33.91
+Capertee,149.986496,-33.149899
+Caragabal,147.740707,-33.839802
+Cardiff,151.662292,-32.941299
+Caringbah,151.121094,-34.0415
+Carlingford,151.046204,-33.780102
+Carlton,151.123795,-33.967701
+Carramar,150.960907,-33.884201
+Casino,153.037903,-28.860201
+Casula,150.910797,-33.9487
+Central,151.205704,-33.882999
+Cessnock,151.361694,-32.8419
+Chakola,149.184296,-36.099602
+Charity Creek,152.231003,-31.9016
+Chatswood,151.181,-33.796799
+Cheltenham,151.078796,-33.754601
+Chester Hill,150.996597,-33.883202
+Circular Quay,151.210907,-33.861198
+Civic,151.772903,-32.9249
+Clarendon,150.790497,-33.610001
+Clifton,150.967804,-34.2584
+Clyde,151.017197,-33.8349
+Coalcliff,150.976501,-34.241001
+Cobar,145.845398,-31.4939
+Cockle Creek,151.622406,-32.9426
+Coffs Harbour,153.138596,-30.3027
+Coledale,150.942596,-34.288799
+Collombatti,152.825699,-30.9755
+Colo Vale,150.4869,-34.3993
+Combara,148.370193,-31.1229
+Como,151.067902,-34.004799
+Compton Downs,146.571304,-30.4224
+Concord West,151.0858,-33.847599
+Condobolin,147.147995,-33.083302
+Coniston,150.884598,-34.437
+Conoble,144.707703,-32.9739
+Cooerwull,150.142105,-33.4818
+Cookamidgera,148.302902,-33.202801
+Coolalie,148.983704,-34.7854
+Coolamon,147.202194,-34.8167
+Cooma,149.133804,-36.2355
+Coombell,152.971893,-29.0159
+Coonong,146.122101,-35.1297
+Coopernook,152.600098,-31.8057
+Cootamundra,148.031006,-34.6399
+Coramba,153.019608,-30.2251
+Coreinbob,147.630905,-35.210999
+Corowa,146.384399,-35.996399
+Corrimal,150.904099,-34.374901
+Corringle,147.347397,-33.632801
+Couridjah,150.547897,-34.232601
+Cowan,151.170593,-33.591999
+Cowra,148.699005,-33.834702
+Cowra West,148.68248,-33.833015
+Crabbes Creek,153.501007,-28.457001
+Craboon,149.460297,-32.0294
+Craven,151.941498,-32.153999
+Cringila,150.877106,-34.465302
+Cronulla,151.150497,-34.056198
+Crooble,150.253998,-29.266199
+Croppa Creek,150.304703,-29.1269
+Crowther,148.502502,-34.0979
+Croydon,151.115799,-33.8829
+Cubbaroo,149.125198,-30.171499
+Culcairn,147.035797,-35.669899
+Culgoora,149.5849,-30.2798
+Cullen Bullen,150.006699,-33.3009
+Cullerin,149.407104,-34.783901
+Cullivel,146.379593,-35.259701
+Cullya,149.109695,-33.199699
+Curlewis,150.270401,-31.116699
+Currabubula,150.7341,-31.2626
+Dapto,150.790695,-34.492599
+Darnick,143.637894,-32.849602
+Daroobalgie,148.052002,-33.329899
+Deepwater,151.851593,-29.4387
+Denistone,151.087799,-33.798401
+Deringulla,149.326797,-31.3883
+Dingadee,151.7901,-32.368
+Domestic,151.179596,-33.930401
+Doonside,150.866196,-33.7631
+Dora Creek,151.500107,-33.080502
+Dorrigo,152.707199,-30.3319
+Douglas Park,150.709305,-34.182598
+Dripstone,148.990494,-32.644001
+Dubbo,148.605392,-32.245602
+Dulwich Hill,151.139801,-33.909302
+Dumaresq,151.580795,-30.459801
+Dunbible,153.401703,-28.380199
+Dundas,151.033096,-33.804001
+Dungog,151.759003,-32.398602
+Dunmore,150.839493,-34.605301
+East Hills,150.9841,-33.960602
+East Maitland,151.587494,-32.744499
+East Richmond,150.758194,-33.6017
+Eastwood,151.082794,-33.789501
+Edgecliff,151.239105,-33.879902
+Edgeroi,149.797394,-30.1171
+Elderslie,150.704895,-34.053299
+Eltham,153.3974,-28.753799
+Emerald Hill,150.104706,-30.8857
+Emu Plains,150.671799,-33.744202
+Engadine,151.013702,-34.067299
+Epping,151.082397,-33.770901
+Erigolia,146.356293,-33.8568
+Erskineville,151.184799,-33.9006
+Ettamogah,146.978806,-36.022499
+Euabalong West,146.391296,-33.054401
+Eulomogo,148.692795,-32.2887
+Eungai,152.900101,-30.848801
+Eurabba,147.8255,-34.055199
+Euratha,146.548401,-33.878799
+Eurie Eurie,148.252899,-29.964899
+Euston,142.764008,-34.569801
+Excelsior,149.974899,-33.0681
+Exeter,150.317307,-34.613499
+Fairfield,150.957703,-33.871101
+Fairview,148.159698,-32.378201
+Fairy Hill,153.008804,-28.770901
+Fairy Meadow,150.895203,-34.394699
+Farley,151.519501,-32.726398
+Fassifern,151.580902,-32.984798
+Faulconbridge,150.536194,-33.696499
+Finley,145.572998,-35.649799
+Fish River,149.3125,-34.7589
+Flemington,151.069901,-33.864101
+Forbes,148.010193,-33.374802
+Frampton,147.922501,-34.695301
+Gadara,148.158798,-35.320999
+Garah,149.634598,-29.0818
+Garema,147.937805,-33.551498
+Garoolgan,146.441101,-34.25
+Gerringong,150.8172,-34.744801
+Geurie,148.828995,-32.397301
+Gidginbung,147.4711,-34.3246
+Gidley,150.846893,-31.0065
+Girral,147.071106,-33.707699
+Glen Innes,151.726898,-29.7372
+Glenbrook,150.617905,-33.767601
+Glencoe,151.723694,-29.9231
+Glenfield,150.892105,-33.970699
+Glenlogan,148.653,-33.7691
+Glenroy,147.944107,-35.7495
+Gloucester,151.965897,-32.0042
+Gobondery,147.594193,-32.691002
+Gooloogong,148.449097,-33.567402
+Goondah,148.730499,-34.733601
+Goonumbla,148.1353,-32.9809
+Gooramma,148.622101,-34.493
+Gordon,151.155701,-33.754501
+Gosford,151.341003,-33.422699
+Gosford Racecourse,151.327194,-33.422401
+Goulburn,149.718002,-34.757801
+Grafton,152.925797,-29.683701
+Grafton City,152.941803,-29.7027
+Grahams Hill,150.730301,-34.040798
+Granville,151.012604,-33.831799
+Grasstree,150.965607,-32.285702
+Grawlin Plains,148.035995,-33.467701
+Green Square,151.1996,-33.9053
+Greenethorpe,148.401398,-33.997898
+Greenwood,151.008896,-29.731701
+Gresham,149.405197,-33.569199
+Greta,151.384201,-32.685799
+Griffith,146.045197,-34.285801
+Gubbata,146.5513,-33.637299
+Guildford,150.983795,-33.853699
+Gum Lake,143.177399,-32.679699
+Gunebang,146.682602,-33.014
+Gungal,150.500397,-32.266998
+Gunnedah,150.253098,-30.9821
+Gunning,149.262802,-34.776798
+Gunningbland,147.915207,-33.132801
+Gurley,149.799393,-29.7342
+Gurranang,152.996506,-29.459299
+Gwabegar,148.969101,-30.611
+Gymea,151.084305,-34.035
+Hadleigh,150.453598,-29.5877
+Hamilton,151.747696,-32.916901
+Hannan,146.417999,-33.6222
+Harden,148.370193,-34.5541
+Harris Park,151.007095,-33.822498
+Hartley Vale,150.261993,-33.5392
+Hawkesbury River,151.226196,-33.545399
+Hay,144.842102,-34.498299
+Hazelbrook,150.452606,-33.7229
+Heathcote,151.007706,-34.087502
+Helensburgh,150.993607,-34.1759
+Henty,147.032501,-35.516602
+Hermidale,146.723694,-31.548401
+Herons Creek,152.727295,-31.5891
+Hexham,151.684006,-32.8302
+High Street,151.561905,-32.740601
+Hilldale,151.648499,-32.504002
+Hillston,145.535507,-33.479099
+Hill Top,150.4936,-34.3540
+Holsworthy,150.955704,-33.961601
+Homebush,151.086594,-33.8661
+Hopefield,146.435806,-35.8918
+Hornsby,151.098495,-33.701302
+Horse Lake,142.065903,-32.115002
+Hurlstone Park,151.131897,-33.909698
+Hurstville,151.100601,-33.966099
+Illabo,147.741699,-34.814098
+Illalong Creek,148.656204,-34.715599
+Ingleburn,150.865494,-33.995701
+International,151.166107,-33.935001
+Ivanhoe,144.304092,-32.913502
+Jannali,151.064194,-34.015598
+Jaspers Brush,150.667007,-34.805401
+Jerilderie,145.723206,-35.361198
+Jindalee,148.088806,-34.577301
+Junee,147.582596,-34.870098
+Kadungle,147.621902,-32.758701
+Kahibah,151.718201,-32.9618
+Kamarah,146.7827,-34.324299
+Kamber,148.608795,-31.6383
+Kandos,149.968704,-32.859299
+Kankool,150.772705,-31.6975
+Kapooka,147.298492,-35.159302
+Karaak Flat,152.285004,-31.9237
+Katoomba,150.310593,-33.710701
+Kellys Plains,151.646393,-30.5667
+Kelso,149.604401,-33.422199
+Kembla Grange Racecourse,150.817795,-34.468899
+Kempsey,152.832993,-31.0765
+Kendall,152.706696,-31.6341
+Kenebri,149.0224,-30.7768
+Kentucky,151.449799,-30.7621
+Kiama,150.854095,-34.671902
+Kikoira,146.659698,-33.653198
+Kilgra,152.975906,-28.5497
+Killara,151.162598,-33.763901
+Killawarra,152.311707,-31.889999
+Kinalung,141.959396,-32.058701
+Kings Cross,151.219193,-33.8717
+Kingsgrove,151.098801,-33.940498
+Kingswood,150.719894,-33.756001
+Kirkham,150.715302,-34.046001
+Kirrawee,151.070801,-34.034599
+Kogarah,151.132095,-33.961498
+Kolodong,152.429092,-31.888399
+Komungla,149.645599,-34.864799
+Koolbury,150.902893,-32.216599
+Koolewong,151.315994,-33.464401
+Koolkhan,152.935303,-29.619699
+Koonadan,146.365097,-34.479801
+Koorakee,142.9245,-34.454498
+Kootingal,151.058502,-31.055799
+Korangi,153.045105,-30.256901
+Kotara,151.703094,-32.938599
+Kundabung,152.835495,-31.2082
+Kungala,153.008194,-29.948099
+Kurrajong,150.665604,-33.555
+Kyogle,153.002502,-28.6206
+Lake Cowal,147.357407,-33.688499
+Lakemba,151.076202,-33.919102
+Langtree,145.564499,-33.661598
+Langunyah,145.572205,-35.729198
+Lanitza,153.000305,-29.881399
+Lapstone,150.642807,-33.773499
+Larras Lee,148.859406,-33.000801
+Laureldale,153.414597,-28.7514
+Lawrance Road,153.009399,-29.3965
+Lawson,150.428101,-33.718102
+Leeton,146.395096,-34.553001
+Leeville,152.994202,-28.943399
+Leightonfield,150.9841,-33.881599
+Leniston,145.681503,-35.6506
+Lette,143.170593,-34.354198
+Leumeah,150.828903,-34.051399
+Leura,150.328201,-33.711201
+Lewisham,151.148193,-33.893101
+Leycester,153.196899,-28.7803
+Liamena,149.336304,-31.9685
+Lidcombe,151.044907,-33.862099
+Lilyvale,151.006195,-34.191002
+Limbri,151.156296,-31.033701
+Linden,150.504501,-33.713001
+Lindfield,151.169907,-33.773201
+Lisarow,151.369598,-33.3806
+Lithgow,150.156204,-33.479301
+Liverpool,150.9263,-33.923599
+Lochinvar,151.449707,-32.720299
+Loftus,151.0504,-34.044701
+Lucan,148.988998,-33.719002
+Lysaghts,150.875305,-34.453999
+Macarthur,150.795898,-34.071201
+Macdonaldtown,151.186203,-33.896301
+Macksville,152.912796,-30.7082
+Macquarie Fields,150.878098,-33.983799
+Maitland,151.550995,-32.737202
+Maldon,150.633301,-34.191299
+Marayong,150.8992,-33.7458
+Marrangaroo,150.112701,-33.449699
+Marrickville,151.155502,-33.9132
+Martin Place,151.211807,-33.8666
+Martins Creek,151.617599,-32.557899
+Marulan,150.006104,-34.7113
+Mary Vale,148.906799,-32.473999
+Mascot,151.1866,-33.921501
+Matakana,145.903595,-32.990002
+Meadowbank,151.090103,-33.815399
+Medlow Bath,150.281494,-33.674301
+Melinga,152.519104,-31.808901
+Menangle,150.743301,-34.124401
+Menangle Park,150.743805,-34.1021
+Mendooran,149.128693,-31.833401
+Menindee,142.425003,-32.3895
+Merah North,149.293793,-30.183901
+Merrylands,150.992203,-33.835602
+Merrywinebone,148.815399,-29.686001
+Metford,151.614807,-32.761501
+Michelago,149.165298,-35.710499
+Mickibri,148.194702,-32.8606
+Middlefield,147.575302,-32.4356
+Milguy,150.202805,-29.350901
+Milsons Point,151.211395,-33.8456
+Milsons Point (1st),151.209396,-33.850498
+Milsons Point (2nd),151.210297,-33.8475
+Mindaribba,151.5844,-32.6667
+Minemoorong,147.450195,-32.282299
+Minnamurra,150.8517,-34.625401
+Minto,150.8414,-34.026901
+Miowera,147.333298,-31.636499
+Miranda,151.102005,-34.036499
+Mittagong,150.447006,-34.452099
+Moleton,152.903503,-30.1607
+Molong,148.869904,-33.094299
+Molonglo,149.173996,-35.330601
+Mooball,153.492996,-28.440399
+Moombooldool,146.672897,-34.299999
+Mooren,149.336502,-31.6875
+Moppin,149.747299,-29.204901
+Moree,149.846405,-29.4736
+Morisset,151.486298,-33.110298
+Morpeth,151.626907,-32.724602
+Morpeth (1st),151.626877,-32.72459
+Morrisons Hill,148.109497,-34.533901
+Mortdale,151.0811,-33.9702
+Mortuary,151.202393,-33.885601
+Moss Vale,150.372803,-34.5452
+Moulamein,144.038895,-35.0882
+Mt Colah,151.115204,-33.6712
+Mt Druitt,150.818893,-33.768799
+Mount Gipps,141.598007,-31.898899
+Mt Kuring-gai,151.137497,-33.652302
+Mount Lion,152.9552,-28.4338
+Mount Rae,149.718201,-34.446301
+Mt Victoria,150.257599,-33.588299
+Mudgee,149.586594,-32.6012
+Mugincoble,148.225403,-33.190201
+Mulgrave,150.830597,-33.625198
+Mullion Creek,149.1185,-33.137699
+Mulwala,146.001495,-35.9809
+Mumbil,149.046295,-32.723
+Mungindi,148.973297,-28.968901
+Muronbung,148.960403,-32.174301
+Murrawal,149.336502,-31.4646
+Murrays Flats,149.787903,-34.723701
+Murrulla,150.919495,-31.8349
+Murrurundi,150.839294,-31.766399
+Museum,151.211304,-33.8755
+Muswellbrook,150.891006,-32.265202
+Myambat,150.617203,-32.3745
+Myocum,153.510803,-28.578199
+Myrtle Creek,152.945908,-29.110001
+Nambucca,152.977707,-30.628799
+Nammoona,153.022293,-28.8269
+Nana Glen,153.018097,-30.135599
+Nanardine,148.113297,-33.060799
+Napier,146.766998,-35.250401
+Narara,151.344193,-33.394001
+Narellan,150.735992,-34.039398
+Nargong,148.9366,-33.727699
+Narrabri,149.792206,-30.326
+Narrabri West,149.751205,-30.339399
+Narrandera,146.555496,-34.739799
+Narriah,146.725998,-33.948101
+Narwee,151.069595,-33.946602
+Narwonah,148.191498,-32.306599
+Neeworra,149.082504,-29.0266
+Neible,149.637207,-31.642401
+Nemingah,150.988098,-31.119101
+Nevertire,147.714005,-31.838301
+Newbridge,149.365799,-33.581799
+Newcastle,151.783905,-32.9249
+Newnes,150.237701,-33.176998
+Newtown,151.179703,-33.898201
+Niagara Park,151.352997,-33.382099
+No 1 Mortuary Station,151.047195,-33.868401
+No 2 Mortuary Station,151.048996,-33.875599
+No 3 Mortuary Station,151.054199,-33.877899
+No 4 Mortuary Station,151.058701,-33.872601
+Normanhurst,151.097504,-33.719898
+North Menangle,150.742401,-34.115601
+North Richmond,150.715805,-33.579899
+North Star,150.388702,-28.9307
+North Strathfield,151.087997,-33.858002
+North Sydney,151.205399,-33.841099
+North Wollongong,150.890594,-34.410999
+North Yathong,145.901001,-35.244301
+Norwood,149.731995,-34.680302
+Nubba,148.220398,-34.523399
+Nyngan,147.195007,-31.562901
+Nyrang Creek,148.556,-33.5467
+Oak Flats,150.815598,-34.57
+Oakey Creek,149.699493,-31.625799
+Oaklands,146.166,-35.5495
+Oatley,151.078705,-33.9799
+Oberon,149.852493,-33.701199
+Old Burren,148.905899,-29.9447
+Old Casino,153.046707,-28.854799
+Olympic Park,151.069,-33.847099
+Oolong,149.172501,-34.777
+Orange,149.1035,-33.286499
+Otford,151.005295,-34.210701
+Otford,151.005295,-34.210701
+Ourimbah,151.370102,-33.353901
+Padstow,151.031998,-33.950699
+Panania,150.996201,-33.953701
+Pangela,150.793503,-31.755199
+Parkes,148.174896,-33.141899
+Parkville,150.868393,-31.988701
+Parramatta,151.006195,-33.8167
+Paterson,151.612701,-32.602798
+Pendle Hill,150.953506,-33.800999
+Pennant Hills,151.073303,-33.735298
+Penrith,150.6922,-33.748199
+Penrose,150.210693,-34.673801
+Penshurst,151.089005,-33.965199
+Perisher,148.407501,-36.4025
+Petersham,151.155106,-33.893101
+Piambra,149.3741,-31.6329
+Picton,150.610992,-34.1782
+Pipers Flat,149.996704,-33.371201
+Pippita,151.063202,-33.8564
+Point Clare,151.328903,-33.445099
+Polona,149.205002,-33.489899
+Port Kembla,150.899597,-34.476898
+Port Kembla North,150.886505,-34.4715
+Portland,149.993393,-33.360298
+Premer,149.899597,-31.459
+Pucawan,147.349396,-34.396599
+Puggoon,149.470901,-32.250301
+Punchbowl,151.057098,-33.9245
+Pymble,151.144104,-33.7425
+Quakers Hill,150.886795,-33.726799
+Quandary,147.312607,-34.3857
+Quandialla,147.796906,-34.0117
+Quandong,148.176498,-33.9221
+Queanbeyan,149.225403,-35.3419
+Queens Wharf,151.620895,-32.7244
+Quipolly,150.655594,-31.4242
+Quirindi,150.680695,-31.504299
+Raglan,149.6510,-33.4344
+Raleigh,153.017807,-30.4541
+Ralvona,147.191101,-35.691101
+Rappville,152.953293,-29.086
+Ravensworth,151.057999,-32.439701
+Raworth,151.613998,-32.725101
+Red Bend,148.014404,-33.384102
+Redfern,151.1978,-33.8913
+Regents Park,151.025299,-33.881001
+Remep,149.845596,-31.495399
+Revesby,151.013794,-33.951401
+Rhodes,151.085403,-33.830101
+Richmond,150.753998,-33.5998
+Riverstone,150.857498,-33.678299
+Riverwood,151.050507,-33.951199
+Robertson,150.592194,-34.590599
+Rockdale,151.135406,-33.9519
+Rocky Ponds,148.503799,-34.583401
+Rookwood,151.055099,-33.863453
+Rooty Hill,150.843903,-33.770401
+Rosehill,151.022903,-33.822201
+Roseville,151.177795,-33.7817
+Rosewood,147.866196,-35.676399
+Roto,145.462402,-33.050804
+Rowena,148.908203,-29.814899
+Roxburgh,150.759003,-32.312698
+Royalla,149.149399,-35.510101
+Rutherford Racecourse,151.503006,-32.712101
+Ryan,146.910507,-35.5172
+Rydal,150.031006,-33.4846
+Rydalmere,151.0289,-33.8102
+Rylstone,149.973404,-32.7962
+Sandgate,151.702103,-32.870499
+Sandy Hollow,150.570007,-32.3382
+Sawtell,153.098007,-30.358101
+Sayers Lake,143.275299,-32.7225
+Scarborough,150.964905,-34.2635
+Schofields,150.867996,-33.6973
+Scone,150.866898,-32.045898
+Sefton,151.010895,-33.8848
+Seven Hills,150.936996,-33.7738
+Singleton,151.165695,-32.570499
+Somerset,152.164902,-31.884199
+South Gundagai,148.0979,-35.077202
+South Wyalong,147.2341,-33.934502
+Spring Ridge,150.253494,-31.396601
+Springdale,147.724701,-34.469299
+Springwood,150.563904,-33.7001
+Sproules Lagoon,147.500397,-34.387199
+St Helena,153.578903,-28.6658
+St James,151.211304,-33.870899
+St Leonards,151.195297,-33.823601
+St Marys,150.774902,-33.7612
+St Peters,151.178299,-33.906799
+Stanmore,151.163498,-33.893501
+Stanwell Park,150.978806,-34.2271
+Stokers,153.404404,-28.394501
+Stratford,151.9375,-32.118801
+Strathaird,149.746399,-34.423901
+Strathfield,151.093994,-33.871201
+Stuart Town,149.077393,-32.8008
+Summer Hill,151.139404,-33.889599
+Summervale,147.058899,-31.428499
+Sutherland,151.056396,-34.031502
+Sydenham,151.168503,-33.9133
+Tabbita,145.844803,-34.1022
+Table Top,147.001694,-35.9706
+Tahmoor,150.588501,-34.223999
+Taleeban,146.462097,-33.8699
+Tallawang,149.453293,-32.204201
+Tallimba,146.881897,-33.992298
+Tallong,150.085693,-34.7197
+Tamboolba,147.559692,-35.231499
+Tamworth,150.930603,-31.0839
+Tarago,149.649002,-35.069801
+Tarana,149.906494,-33.525101
+Tarcutta,147.710999,-35.2953
+Taree,152.458603,-31.905001
+Tarro,151.669998,-32.808201
+Tascott,151.316895,-33.448898
+Telarah,151.5392,-32.723202
+Telegraph Point,152.800507,-31.3214
+Telopea,151.042496,-33.793598
+Temora,147.5271,-34.444401
+Tempe,151.156906,-33.922901
+Tenterfield,152.005493,-29.053301
+Teralba,151.602997,-32.962299
+Tharbogang,145.992599,-34.254002
+The Gorge,141.675095,-31.9126
+The Risk,152.939407,-28.48
+The Rock,147.113907,-35.271999
+The Royal National Park,151.055603,-34.062199
+The Troffs,147.653702,-32.827599
+Thirlmere,150.570801,-34.204201
+Thirroul,150.917496,-34.318298
+Thornleigh,151.078003,-33.730598
+Thornton,151.640793,-32.783901
+Thulloo,146.768005,-33.659
+Tichborne,148.120605,-33.222099
+Tomingley West,148.152405,-32.5728
+Toolijooa,150.780807,-34.764702
+Toongabbie,150.949402,-33.786999
+Tootool,146.996994,-35.262001
+Torbane,149.989197,-33.112301
+Toronto,151.598007,-33.0154
+Tottenham,147.354797,-32.240501
+Towealgra,149.327698,-31.9305
+Town Hall,151.207108,-33.872398
+Towradgi,150.900406,-34.383801
+Trajere,148.387802,-33.492901
+Trangie,147.985001,-32.0299
+Trewilga,148.213303,-32.7883
+Trida,145.004501,-33.0182
+Trundle,147.708893,-32.916599
+Tubbul Road,147.936005,-34.255299
+Tuggerah,151.420898,-33.307201
+Tullamore,147.561996,-32.631401
+Tumblong,148.008194,-35.138802
+Tumulla,149.480606,-33.516899
+Turramurra,151.128403,-33.730099
+Turrawan,149.883804,-30.457399
+Turrella,151.139694,-33.929401
+Tweed Heads,153.5401,-28.1735
+Ulamambri,149.383194,-31.3298
+Ulinda,149.481705,-31.582199
+Umbango Creek,147.766205,-35.382702
+Unanderra,150.845795,-34.453701
+Upper Manilla,150.664001,-30.636101
+Uralla,151.505295,-30.6437
+Urana,146.273407,-35.328999
+Uranagong,146.235397,-35.4007
+Uranquinty,147.243698,-35.191399
+Urunga,153.017593,-30.4979
+Valley Heights,150.581497,-33.703602
+Victoria Street,151.592102,-32.7491
+Villawood,150.973907,-33.880402
+Vineyard,150.849792,-33.6497
+Wagga Wagga,147.366501,-35.119801
+Wahroonga,151.117401,-33.715698
+Waitara,151.104401,-33.707901
+Walcha Road,151.400497,-30.941799
+Wallangarra,151.931595,-28.9226
+Wallarobba,151.6946,-32.4951
+Wallerawang,150.0681,-33.4090
+Wallsend,151.667206,-32.902802
+Wambool,149.7789,-33.5158
+Wamboyne,147.279602,-33.5695
+Warabrook,151.709793,-32.886299
+Waratah,151.730896,-32.901001
+Wards River,151.938599,-32.217098
+Wargambeal,146.492294,-33.3606
+Wargin,147.253601,-34.115299
+Warnecliffe,149.084595,-32.987202
+Warnervale,151.447205,-33.247601
+Warragai Creek,152.988495,-29.547701
+Warral,150.860992,-31.1595
+Warrawee,151.121994,-33.722698
+Warrell Creek,152.892502,-30.7694
+Warren,147.826096,-31.697599
+Warrimoo,150.601196,-33.720001
+Warwick Farm,150.933807,-33.9147
+Waterfall,150.993393,-34.133999
+Wauchope,152.736694,-31.455099
+Waverton,151.197998,-33.8377
+Wee Elwah,145.197906,-33.045399
+Weedallion,147.936707,-34.193802
+Weemelah,149.255905,-29.0165
+Weetaliba,149.582504,-31.638901
+Weethalle,146.619904,-33.876499
+Weja,146.8228,-33.533401
+Wellington,148.945007,-32.5522
+Wentworth Falls,150.376801,-33.709099
+Wentworthville,150.971497,-33.806099
+Werai,150.345505,-34.590599
+Werrington,150.759705,-33.7589
+Werris Creek,150.646194,-31.3487
+West Ryde,151.091095,-33.805
+West Tamworth,150.912994,-31.0905
+West Wyalong,147.200195,-33.928398
+Westmead,150.986801,-33.8069
+Wickham,151.758194,-32.923
+Wiley Park,151.065994,-33.923
+Willie Ploma,148.075897,-35.093899
+Willow Tree,150.726593,-31.6476
+Wimborne,150.643494,-30.670799
+Windsor,150.809402,-33.612801
+Wingello,150.157593,-34.693298
+Wingen,150.880997,-31.8934
+Wingham,152.367004,-31.8659
+Winnunga,146.863907,-33.5965
+Wiragulla,151.742203,-32.4613
+Wirrinya,147.802994,-33.670898
+Wittenbra,149.085403,-31.044201
+Wolli Creek,151.154999,-33.925999
+Wollongong,150.887405,-34.425701
+Wollstonecraft,151.191498,-33.831299
+Wombarra,150.9524,-34.2752
+Wondabyne,151.255005,-33.491299
+Wongabinda,150.072098,-29.385401
+Wongarbon,148.759293,-32.336399
+Wongoni,149.278503,-31.871099
+Woodford,150.480698,-33.735802
+Woodlawn,153.319199,-28.7757
+Woodstock,148.8452,-33.743301
+Woolbrook,151.351898,-30.965099
+Woollahra,151.242401,-33.8848
+Woolooware,151.143494,-34.0476
+Woonona,150.913803,-34.3493
+Woy Woy,151.321899,-33.482601
+Wubbera,150.145004,-29.546301
+Wumbulgal,146.209198,-34.358601
+Wyanga,148.131104,-32.458302
+Wyangaree,152.963806,-28.5117
+Wybalena,148.163498,-35.4944
+Wyee,151.485001,-33.180401
+Wynyard,151.205795,-33.865101
+Wyong,151.426895,-33.284
+Wyrra,147.268005,-33.823002
+Wyuna Downs,146.488495,-30.5005
+Yagoona,151.023804,-33.904202
+Yallah,150.784195,-34.5364
+Yarra,149.630096,-34.786301
+Yass Junction,148.912903,-34.8088
+Yass Town,148.9086,-34.844002
+Yearinan,149.179199,-31.1819
+Yennora,150.969803,-33.8638
+Yerrinbool,150.542603,-34.3713
+Yethera,147.574799,-32.525398
+Yiddah,147.317795,-34.0364
+Yoogali,146.081497,-34.300499
+Youngareen,146.852203,-33.650398
+Yullundry,148.713898,-32.843201
+Zig Zag,150.2001,-33.4717
diff --git a/src/3rdparty/2geom/src/toys/data/nsw-london.zip b/src/3rdparty/2geom/src/toys/data/nsw-london.zip
new file mode 100644
index 0000000..d0c0050
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/data/nsw-london.zip
Binary files differ
diff --git a/src/3rdparty/2geom/src/toys/data/nsw.txt b/src/3rdparty/2geom/src/toys/data/nsw.txt
new file mode 100644
index 0000000..6f33691
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/data/nsw.txt
@@ -0,0 +1,86 @@
+Olympic Park I:
+Central,Redfern,Macdonaldtown,Newtown,Stanmore,Petersham,Lewisham,Summer Hill,Ashfield,Croydon,Burwood,Strathfield,Homebush,Flemington,Olympic Park
+
+Olympic Park II:
+Blacktown,Seven Hills,Toongabbie,Pendle Hill,Wentworthville,Westmead,Parramatta,Harris Park,Granville,Clyde,Auburn,Lidcombe,Olympic Park
+
+Eastern Suburbs & Illawarra 1:
+Waterfall,Heathcote,Engadine,Loftus,Sutherland,Jannali,Como,Oatley,Mortdale,Penshurst,Hurstville,Allawah,Carlton,Kogarah,Rockdale,Banksia,Arncliffe,Wolli Creek,Tempe,Sydenham,St Peters,Erskineville,Redfern,Central,Town Hall,Martin Place,Kings Cross,Edgecliff,Bondi Junction
+
+Eastern Suburbs & Illawarra 2:
+Cronulla,Woolooware,Caringbah,Miranda,Gymea,Kirrawee,Sutherland,Jannali,Como,Oatley,Mortdale,Penshurst,Hurstville,Allawah,Carlton,Kogarah,Rockdale,Banksia,Arncliffe,Wolli Creek,Tempe,Sydenham,St Peters,Erskineville,Redfern,Central,Town Hall,Martin Place,Kings Cross,Edgecliff,Bondi Junction
+
+South Coast 1:
+Bomaderry,Berry,Gerringong,Kiama,Bombo,Minnamurra,Dunmore,Oak Flats,Albion Park,Dapto,Kembla Grange Racecourse,Unanderra,Coniston,Wollongong,North Wollongong,Fairy Meadow,Towradgi,Corrimal,Bellambi,Woonona,Bulli,Thirroul,Austinmer,Coledale,Wombarra,Scarborough,Coalcliff,Stanwell Park,Otford,Helensburgh,Waterfall,Heathcote,Engadine,Loftus,Sutherland,Jannali,Como,Oatley,Mortdale,Penshurst,Hurstville,Allawah,Carlton,Kogarah,Rockdale,Banksia,Arncliffe,Wolli Creek,Tempe,Sydenham,St Peters,Erskineville,Redfern,Central,Town Hall,Martin Place,Kings Cross,Edgecliff,Bondi Junction
+
+South Coast 2:
+Port Kembla,Port Kembla North,Cringila,Lysaghts,Coniston,Wollongong,North Wollongong,Fairy Meadow,Towradgi,Corrimal,Bellambi,Woonona,Bulli,Thirroul,Austinmer,Coledale,Wombarra,Scarborough,Coalcliff,Stanwell Park,Otford,Helensburgh,Waterfall,Heathcote,Engadine,Loftus,Sutherland,Jannali,Como,Oatley,Mortdale,Penshurst,Hurstville,Allawah,Carlton,Kogarah,Rockdale,Banksia,Arncliffe,Wolli Creek,Tempe,Sydenham,St Peters,Erskineville,Redfern,Central,Town Hall,Martin Place,Kings Cross,Edgecliff,Bondi Junction
+
+Bankstown Line a:
+Town Hall,Wynyard,Circular Quay,St James,Museum,Central,Redfern,Erskineville,St Peters,Sydenham,Marrickville,Dulwich Hill,Hurlstone Park,Canterbury,Campsie,Belmore,Lakemba,Wiley Park,Punchbowl,Bankstown,Yagoona,Birrong,Regents Park,Berala,Lidcombe
+
+Bankstown Line b:
+Lidcombe,Berala,Regents Park,Birrong,Sefton,Chester Hill,Leightonfield,Villawood,Carramar,Cabramatta,Warwick Farm,Liverpool
+
+Inner West 1a:
+Liverpool,Warwick Farm,Cabramatta,Carramar,Villawood,Leightonfield,Chester Hill,Sefton,Regents Park,Berala,Lidcombe,Flemington,Homebush,Strathfield,Burwood,Croydon,Ashfield,Summer Hill,Lewisham,Petersham,Stanmore,Newtown,Macdonaldtown,Redfern,Central,Town Hall,Wynyard,Circular Quay,St James,Museum
+
+Inner West 1b:
+Central,Town Hall,Wynyard,Milsons Point,North Sydney,Waverton,Wollstonecraft,St Leonards,Artarmon,Chatswood
+
+Inner West 2a:
+Parramatta,Harris Park,Granville,Clyde,Auburn,Lidcombe,Flemington,Homebush,Strathfield,Burwood,Croydon,Ashfield,Summer Hill,Lewisham,Petersham,Stanmore,Newtown,Macdonaldtown,Redfern,Central,Town Hall,Wynyard,Circular Quay,St James,Museum
+
+Inner West 2b:
+Central,Town Hall,Wynyard,Milsons Point,North Sydney,Waverton,Wollstonecraft,St Leonards,Artarmon,Chatswood
+
+Airport & East Hills 1:
+Macarthur,Campbelltown,Leumeah,Minto,Ingleburn,Macquarie Fields,Glenfield,Holsworthy,East Hills,Panania,Revesby,Padstow,Riverwood,Narwee,Beverly Hills,Kingsgrove,Bexley North,Bardwell Park,Turrella,Wolli Creek,International,Domestic,Mascot,Green Square,Central,Museum,St James,Circular Quay,Wynyard,Town Hall
+
+Airport & East Hills 2:
+Macarthur,Campbelltown,Leumeah,Minto,Ingleburn,Macquarie Fields,Glenfield,Holsworthy,East Hills,Panania,Revesby,Padstow,Riverwood,Narwee,Beverly Hills,Kingsgrove,Bexley North,Bardwell Park,Turrella,Tempe,Sydenham,St Peters,Erskineville,Redfern,Central,Museum,St James,Circular Quay,Wynyard,Town Hall
+
+South:
+Macarthur,Campbelltown,Leumeah,Minto,Ingleburn,Macquarie Fields,Glenfield,Casula,Liverpool,Warwick Farm,Cabramatta,Canley Vale,Fairfield,Yennora,Guildford,Merrylands,Granville,Clyde,Auburn,Lidcombe,Flemington,Homebush,Strathfield,Burwood,Croydon,Ashfield,Summer Hill,Lewisham,Petersham,Stanmore,Newtown,Macdonaldtown,Redfern,Central,Town Hall,Wynyard,Circular Quay,St James,Museum
+
+Southern Highlands:
+Goulburn,Marulan,Tallong,Wingello,Penrose,Bundanoon,Exeter,Moss Vale,Burradoo,Bowral,Mittagong,Yerrinbool,Bargo,Tahmoor,Picton,Douglas Park,Menangle,Menangle Park,Macarthur,Campbelltown,Leumeah,Minto,Ingleburn,Macquarie Fields,Glenfield,Casula,Liverpool,Warwick Farm,Cabramatta,Canley Vale,Fairfield,Yennora,Guildford,Merrylands,Harris Park,Parramatta,Westmead,Wentworthville,Pendle Hill,Toongabbie,Seven Hills,Blacktown
+
+Southern Highlands ROAD COACH:
+Bowral,Mittagong,Colo Vale,Hill Top,Balmoral,Buxton,Couridjah,Thirlmere,Picton
+
+Cumberland:
+Campbelltown,Leumeah,Minto,Ingleburn,Macquarie Fields,Glenfield,Casula,Liverpool,Warwick Farm,Cabramatta,Canley Vale,Fairfield,Yennora,Guildford,Merrylands,Harris Park,Parramatta,Westmead,Wentworthville,Pendle Hill,Toongabbie,Seven Hills,Blacktown,Doonside,Rooty Hill,Mt Druitt,St Marys
+
+Carlingford Line:
+Carlingford,Telopea,Dundas,Rydalmere,Camellia,Rosehill,Clyde
+
+Western 1:
+Richmond,East Richmond,Clarendon,Windsor,Mulgrave,Vineyard,Riverstone,Schofields,Quakers Hill,Marayong,Blacktown,Seven Hills,Toongabbie,Pendle Hill,Wentworthville,Westmead,Parramatta,Harris Park,Granville,Clyde,Auburn,Lidcombe,Flemington,Homebush,Strathfield,Burwood,Croydon,Ashfield,Summer Hill,Lewisham,Petersham,Stanmore,Newtown,Macdonaldtown,Redfern,Central,Town Hall,Wynyard,Milsons Point,North Sydney
+
+Western 2:
+Emu Plains,Penrith,Kingswood,Werrington,St Marys,Mt Druitt,Rooty Hill,Doonside,Blacktown,Seven Hills,Toongabbie,Pendle Hill,Wentworthville,Westmead,Parramatta,Harris Park,Granville,Clyde,Auburn,Lidcombe,Flemington,Homebush,Strathfield,Burwood,Croydon,Ashfield,Summer Hill,Lewisham,Petersham,Stanmore,Newtown,Macdonaldtown,Redfern,Central,Town Hall,Wynyard,Milsons Point,North Sydney
+
+Blue Mountains:
+Lithgow,Zig Zag,Bell,Mt Victoria,Blackheath,Medlow Bath,Katoomba,Leura,Wentworth Falls,Bullaburra,Lawson,Hazelbrook,Woodford,Linden,Faulconbridge,Springwood,Valley Heights,Warrimoo,Blaxland,Glenbrook,Lapstone,Emu Plains,Penrith,Kingswood,Werrington,St Marys,Mt Druitt,Rooty Hill,Doonside,Blacktown,Seven Hills,Toongabbie,Pendle Hill,Wentworthville,Westmead,Parramatta,Harris Park,Granville,Clyde,Auburn,Lidcombe,Flemington,Homebush,Strathfield,Burwood,Croydon,Ashfield,Summer Hill,Lewisham,Petersham,Stanmore,Newtown,Macdonaldtown,Redfern,Central,Town Hall,Wynyard,Milsons Point,North Sydney
+
+North Shore:
+Berowra,Mt Kuring-gai,Mt Colah,Asquith,Hornsby,Waitara,Wahroonga,Warrawee,Turramurra,Pymble,Gordon,Killara,Lindfield,Roseville,Chatswood,Artarmon,St Leonards,Wollstonecraft,Waverton,North Sydney,Milsons Point,Wynyard,Town Hall,Central,Redfern,Macdonaldtown,Newtown,Stanmore,Petersham,Lewisham,Summer Hill,Ashfield,Croydon,Burwood,Strathfield,Homebush,Flemington,Lidcombe,Auburn,Clyde,Granville,Harris Park,Parramatta
+
+Northern:
+Berowra,Mt Kuring-gai,Mt Colah,Asquith,Hornsby,Normanhurst,Thornleigh,Pennant Hills,Beecroft,Cheltenham,Epping,Eastwood,Denistone,West Ryde,Meadowbank,Rhodes,Concord West,North Strathfield,Strathfield,Burwood,Croydon,Ashfield,Summer Hill,Lewisham,Petersham,Stanmore,Newtown,Macdonaldtown,Redfern,Central,Town Hall,Wynyard,Milsons Point,North Sydney
+
+Newcastle & Central Coast 1:
+Newcastle,Civic,Wickham,Hamilton,Broadmeadow,Adamstown,Kotara,Cardiff,Cockle Creek,Teralba,Booragul,Fassifern,Awaba,Dora Creek,Morisset,Wyee,Warnervale,Wyong,Tuggerah,Ourimbah,Lisarow,Niagara Park,Narara,Gosford,Point Clare,Tascott,Koolewong,Woy Woy,Wondabyne,Hawkesbury River,Cowan,Berowra,Mt Kuring-gai,Mt Colah,Asquith,Hornsby,Waitara,Wahroonga,Warrawee,Turramurra,Pymble,Gordon,Killara,Lindfield,Roseville,Chatswood,Artarmon,St Leonards,Wollstonecraft,Waverton,North Sydney,Milsons Point,Wynyard,Town Hall,Central
+
+Newcastle & Central Coast 2:
+Newcastle,Civic,Wickham,Hamilton,Broadmeadow,Adamstown,Kotara,Cardiff,Cockle Creek,Teralba,Booragul,Fassifern,Awaba,Dora Creek,Morisset,Wyee,Warnervale,Wyong,Tuggerah,Ourimbah,Lisarow,Niagara Park,Narara,Gosford,Point Clare,Tascott,Koolewong,Woy Woy,Wondabyne,Hawkesbury River,Cowan,Berowra,Mt Kuring-gai,Mt Colah,Asquith,Hornsby,Normanhurst,Thornleigh,Pennant Hills,Beecroft,Cheltenham,Epping,Eastwood,Denistone,West Ryde,Meadowbank,Rhodes,Concord West,North Strathfield,Strathfield,Burwood,Croydon,Ashfield,Summer Hill,Lewisham,Petersham,Stanmore,Newtown,Macdonaldtown,Redfern,Central
+
+Wyong Line:
+Wyong,Tuggerah,Ourimbah,Lisarow,Niagara Park,Narara,Gosford,Point Clare,Tascott,Koolewong,Woy Woy,Wondabyne,Hawkesbury River,Cowan,Berowra,Mt Kuring-gai,Mt Colah,Asquith,Hornsby,Normanhurst,Thornleigh,Pennant Hills,Beecroft,Cheltenham,Epping,Eastwood,Denistone,West Ryde,Meadowbank,Rhodes,Concord West,North Strathfield,Strathfield,Homebush,Flemington,Lidcombe,Auburn,Clyde,Granville,Harris Park,Parramatta,Westmead,Wentworthville,Pendle Hill,Toongabbie,Seven Hills,Blacktown,Doonside,Rooty Hill,Mt Druitt,St Marys
+
+Hunter 1:
+Scone,Aberdeen,Muswellbrook,Singleton,Belford,Branxton,Greta,Allandale,Lochinvar,Maitland,High Street,East Maitland,Victoria Street,Metford,Thornton,Beresfield,Tarro,Hexham,Sandgate,Warabrook,Waratah,Hamilton,Wickham,Civic,Newcastle
+
+Hunter 2:
+Dungog,Wiragulla,Wallarobba,Hilldale,Martins Creek,Paterson,Mindaribba,Telarah,Maitland,High Street,East Maitland,Victoria Street,Metford,Thornton,Beresfield,Tarro,Hexham,Sandgate,Warabrook,Waratah,Hamilton,Wickham,Civic,Newcastle
diff --git a/src/3rdparty/2geom/src/toys/data/parser.cpp b/src/3rdparty/2geom/src/toys/data/parser.cpp
new file mode 100644
index 0000000..cc5c6f0
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/data/parser.cpp
@@ -0,0 +1,47 @@
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <vector>
+#include <map>
+using namespace std;
+typedef pair<double,double> Point;
+int main(void)
+{
+ ifstream location_file("london-locations.csv"), path_file("london.txt");
+ string id,sx,sy;
+ map<string,Point> idlookup;
+ while (getline(location_file,id,','))
+ {
+ getline(location_file,sx,',');
+ getline(location_file,sy,'\n');
+ char *e;
+ double x = strtod(sx.c_str(),&e), y = strtod(sy.c_str(),&e);
+ cout << id << " (" << x << "," << y << ")"<< endl;
+ idlookup[id]=make_pair(x,y);
+ }
+ string l;
+ vector<vector<Point> > paths;
+ while (getline(path_file,l,'\n')) {
+ vector<Point> ps;
+ if(l.size() < 2) continue; // skip blank lines
+ if(l.find(":",0)!=string::npos) continue; // skip labels
+ string::size_type p=0,q;
+ while((q=l.find(",",p))!=string::npos || p < l.size() && (q = l.size()-1)) {
+ id = l.substr(p,q-p);
+ cout << id << ",";
+ ps.push_back(idlookup[id]);
+ p=q+1;
+ }
+ paths.push_back(ps);
+ cout << "*******************************************" << endl;
+ }
+ for(unsigned i=0;i<paths.size();i++) {
+ vector<Point> ps=paths[i];
+ for(unsigned j=0;j<ps.size();j++) {
+ double x=ps[j].first, y=ps[j].second;
+ cout << "(" << x << "," << y << ")" << ",";
+ }
+ cout << endl;
+ }
+ return(0);
+}
diff --git a/src/3rdparty/2geom/src/toys/differential-constraint.cpp b/src/3rdparty/2geom/src/toys/differential-constraint.cpp
new file mode 100644
index 0000000..501eb76
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/differential-constraint.cpp
@@ -0,0 +1,132 @@
+/** Differential constraint solver hack
+ * based on idea from Michael Glissner
+ * (njh)
+ */
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/bezier-to-sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework.h>
+
+using std::vector;
+using namespace Geom;
+
+unsigned total_pieces_sub;
+unsigned total_pieces_inc;
+
+#include <stdio.h>
+#include <gsl/gsl_errno.h>
+#include <gsl/gsl_matrix.h>
+#include <gsl/gsl_odeiv.h>
+
+vector<Geom::Point> *handlesptr = NULL;
+
+const unsigned order = 6;
+
+class SBez: public Toy {
+ static int
+ func (double /*t*/, const double y[], double f[],
+ void */*params*/)
+ {
+ //double mu = *(double *)params;
+ D2<SBasis> B = handles_to_sbasis(handlesptr->begin(), order);
+ D2<SBasis> dB = derivative(B);
+ Geom::Point tan = dB(y[0]);//Geom::unit_vector();
+ tan /= dot(tan,tan);
+ Geom::Point yp = B(y[0]);
+ double dtau = -dot(tan, yp - (*handlesptr)[order+1]);
+ f[0] = dtau;
+
+ return GSL_SUCCESS;
+ }
+
+ static int
+ jac (double /*t*/, const double y[], double *dfdy,
+ double dfdt[], void *params)
+ {
+ double mu = *(double *)params;
+ gsl_matrix_view dfdy_mat
+ = gsl_matrix_view_array (dfdy, 2, 2);
+ gsl_matrix * m = &dfdy_mat.matrix;
+ gsl_matrix_set (m, 0, 0, 0.0);
+ gsl_matrix_set (m, 0, 1, 1.0);
+ gsl_matrix_set (m, 1, 0, -2.0*mu*y[0]*y[1] - 1.0);
+ gsl_matrix_set (m, 1, 1, -mu*(y[0]*y[0] - 1.0));
+ dfdt[0] = 0.0;
+ dfdt[1] = 0.0;
+ return GSL_SUCCESS;
+ }
+
+ double y[2];
+
+ virtual void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) {
+ handlesptr = &handles;
+ cairo_set_line_width (cr, 0.5);
+
+ D2<SBasis> B = handles_to_sbasis(handles.begin(), order);
+ cairo_d2_sb(cr, B);
+
+ const gsl_odeiv_step_type * T
+ = gsl_odeiv_step_rk8pd;
+
+ gsl_odeiv_step * s
+ = gsl_odeiv_step_alloc (T, 1);
+ gsl_odeiv_control * c
+ = gsl_odeiv_control_y_new (1e-6, 0.0);
+ gsl_odeiv_evolve * e
+ = gsl_odeiv_evolve_alloc (1);
+
+ double mu = 10;
+ gsl_odeiv_system sys = {func, jac, 1, &mu};
+
+ static double t = 0.0;
+ double t1 = t + 1;
+ double h = 1e-6;
+
+ while (t < t1)
+ {
+ int status = gsl_odeiv_evolve_apply (e, c, s,
+ &sys,
+ &t, t1,
+ &h, y);
+
+ if (status != GSL_SUCCESS)
+ break;
+
+ //printf ("%.5e %.5e %.5e\n", t, y[0], y[1]);
+ }
+
+ draw_cross(cr, B(y[0]));
+
+ gsl_odeiv_evolve_free (e);
+ gsl_odeiv_control_free (c);
+ gsl_odeiv_step_free (s);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+public:
+ SBez() {
+ y[0] = 0;
+ for(unsigned i = 0; i <= order+1; i++) {
+ handles.push_back(Geom::Point(uniform()*400, uniform()*400));
+ }
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new SBez());
+
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/draw-toy.cpp b/src/3rdparty/2geom/src/toys/draw-toy.cpp
new file mode 100644
index 0000000..f5bd315
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/draw-toy.cpp
@@ -0,0 +1,116 @@
+#include <2geom/path.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+class DrawToy: public Toy {
+ PointSetHandle hand;
+ //Knot : Och : Och : Knot : Och : Och : Knot : Och : Och : ...
+ void draw(cairo_t *cr, std::ostringstream */*notify*/, int /*width*/, int /*height*/, bool save, std::ostringstream*) override {
+ if(!save) {
+ cairo_set_source_rgba (cr, 0, 0.5, 0, 1);
+ cairo_set_line_width (cr, 1);
+ for(unsigned i = 0; i < hand.pts.size(); i+=3) {
+ draw_circ(cr, hand.pts[i]);
+ draw_number(cr, hand.pts[i], i/3);
+ }
+ cairo_set_source_rgba (cr, 0, 0, 0.5, 1);
+ for(unsigned i = 2; i < hand.pts.size(); i+=3) {
+ draw_circ(cr, hand.pts[i]);
+ draw_circ(cr, hand.pts[i-1]);
+ }
+
+ cairo_set_source_rgba (cr, 0.5, 0, 0, 1);
+ for(unsigned i = 3; i < hand.pts.size(); i+=3) {
+ draw_line_seg(cr, hand.pts[i-2], hand.pts[i-3]);
+ draw_line_seg(cr, hand.pts[i], hand.pts[i-1]);
+ }
+ }
+ cairo_set_source_rgba (cr, 0, 0, 0, 1);
+ Geom::Path pb;
+ if(hand.pts.size() > 3) {
+ pb.start(hand.pts[0]);
+ for(unsigned i = 1; i < hand.pts.size() - 3; i+=3) {
+ pb.appendNew<Geom::CubicBezier>(hand.pts[i], hand.pts[i+1], hand.pts[i+2]);
+ }
+ }
+ cairo_path(cr, pb);
+ cairo_stroke(cr);
+ }
+ void mouse_pressed(GdkEventButton* e) override {
+ selected = NULL;
+ Geom::Point mouse(e->x, e->y);
+ int close_i = 0;
+ float close_d = 1000;
+ for(unsigned i = 0; i < hand.pts.size(); i+=1) {
+ if(Geom::distance(mouse, hand.pts[i]) < close_d) {
+ close_d = Geom::distance(mouse, hand.pts[i]);
+ close_i = i;
+ }
+ }
+ if(close_d < 5) {
+ if(e->button==3)
+ hand.pts.erase(hand.pts.begin() + close_i);
+ else {
+ selected = &hand;
+ hit_data = (void*)(intptr_t)close_i;
+ }
+ } else {
+ if(e->button==1) {
+ if(hand.pts.size() > 0) {
+ if(hand.pts.size() == 1) {
+ hand.pts.push_back((hand.pts[0] * 2 + mouse) / 3);
+ hand.pts.push_back((hand.pts[0] + mouse * 2) / 3);
+ } else {
+ Geom::Point prev = hand.pts[hand.pts.size() - 1];
+ Geom::Point curve = prev - hand.pts[hand.pts.size() - 2];
+ hand.pts.push_back(prev + curve);
+ hand.pts.push_back(mouse + curve);
+ }
+ }
+ hand.pts.push_back(mouse);
+ } else {
+ selected = &hand;
+ hit_data = (void*)(intptr_t)close_i;
+ }
+ }
+ }
+
+ void mouse_moved(GdkEventMotion* e) override {
+ Geom::Point mouse(e->x, e->y);
+
+ if(e->state & (GDK_BUTTON1_MASK) && selected != NULL) {
+ // NOTE this is completely broken.
+ int hd = 0;
+ if (hd % 3 == 0) {
+ Geom::Point diff = mouse - hand.pts[hd];
+ if(int(hand.pts.size() - 1) > hd) hand.pts[hd + 1] += diff;
+ if(hd != 0) hand.pts[hd - 1] += diff;
+ }
+ Toy::mouse_moved(e);
+ }
+ }
+
+ bool should_draw_numbers() override { return false; }
+public:
+ DrawToy() {
+
+ handles.push_back(&hand);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new DrawToy());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/ellipse-area-minimizer.cpp b/src/3rdparty/2geom/src/toys/ellipse-area-minimizer.cpp
new file mode 100644
index 0000000..48df598
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/ellipse-area-minimizer.cpp
@@ -0,0 +1,352 @@
+/*
+ * Ellipse and Elliptical Arc Fitting Example
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#include <2geom/numeric/fitting-tool.h>
+#include <2geom/numeric/fitting-model.h>
+
+#include <2geom/ellipse.h>
+#include <2geom/elliptical-arc.h>
+#include <2geom/utils.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <stdio.h>
+
+#include <gsl/gsl_errno.h>
+#include <gsl/gsl_math.h>
+#include <gsl/gsl_min.h>
+
+
+
+
+using namespace Geom;
+
+
+class LFMEllipseArea
+ : public NL::LinearFittingModelWithFixedTerms<Point, double, Ellipse>
+{
+ public:
+ LFMEllipseArea(double coeff)
+ : m_coeff(coeff*coeff)
+ {
+ }
+ void feed( NL::VectorView & coeff, double & fixed_term, Point const& p ) const
+ {
+ coeff[0] = p[X] * p[Y];
+ coeff[1] = p[X];
+ coeff[2] = p[Y];
+ coeff[3] = 1;
+ fixed_term = p[X] * p[X] + m_coeff * p[Y] * p[Y];
+ }
+
+ size_t size() const
+ {
+ return 4;
+ }
+
+ void instance(Ellipse & e, NL::ConstVectorView const& coeff) const
+ {
+// std::cerr << " B = " << coeff[0]
+// << " C = " << decimal_round(m_coeff,10)
+// << " D = " << coeff[1]
+// << " E = " << coeff[2]
+// << " F = " << coeff[3]
+// << std::endl;
+ e.setCoefficients(1, coeff[0], m_coeff, coeff[1], coeff[2], coeff[3]);
+ }
+
+ private:
+ double m_coeff;
+};
+
+inline
+Ellipse fitting(std::vector<Point> const& points, double coeff)
+{
+ size_t sz = points.size();
+ if (sz != 4)
+ {
+ THROW_RANGEERROR("fitting error: too few points passed");
+ }
+ LFMEllipseArea model(coeff);
+ NL::least_squeares_fitter<LFMEllipseArea> fitter(model, sz);
+
+ for (size_t i = 0; i < sz; ++i)
+ {
+ fitter.append(points[i]);
+ }
+ fitter.update();
+
+ NL::Vector z(sz, 0.0);
+ Ellipse e;
+ model.instance(e, fitter.result(z));
+ return e;
+}
+
+
+inline
+double area_goal(double coeff, void* params)
+{
+ typedef std::vector<Point> point_set_t;
+ const point_set_t & points = *static_cast<point_set_t*>(params);
+ Ellipse e;
+ try
+ {
+ e = fitting(points, coeff);
+ }
+ catch(LogicalError exc)
+ {
+ //std::cerr << exc.what() << std::endl;
+ return 1e18;
+ }
+ return e.ray(X) * e.ray(Y);
+}
+
+
+inline
+double perimeter_goal(double coeff, void* params)
+{
+ typedef std::vector<Point> point_set_t;
+ const point_set_t & points = *static_cast<point_set_t*>(params);
+ Ellipse e;
+ try
+ {
+ e = fitting(points, coeff);
+ }
+ catch(LogicalError exc)
+ {
+ //std::cerr << exc.what() << std::endl;
+ return 1e18;
+ }
+ return e.ray(X) + e.ray(Y);
+}
+
+void no_minimum_error_handler (const char * reason,
+ const char * file,
+ int line,
+ int gsl_errno)
+{
+ if (gsl_errno == GSL_EINVAL)
+ {
+ std::cerr << "gsl: " << file << ":" << line << " ERROR: " << reason << std::endl;
+ }
+ else
+ {
+ gsl_error(reason, file, line, gsl_errno);
+ }
+}
+
+typedef double goal_function_type(double coeff, void* params);
+
+double minimizer (std::vector<Point> & points, goal_function_type* gf)
+{
+ int status;
+ int iter = 0, max_iter = 1000;
+ const gsl_min_fminimizer_type *T;
+ gsl_min_fminimizer *s;
+ double m = 1.0;
+ double a = 1e-2, b = 1e2;
+ gsl_function F;
+
+ F.function = gf;
+ F.params = static_cast<void*>(&points);
+
+ //T = gsl_min_fminimizer_goldensection;
+ T = gsl_min_fminimizer_brent;
+ s = gsl_min_fminimizer_alloc (T);
+ gsl_min_fminimizer_set (s, &F, m, a, b);
+
+// printf ("using %s method\n",
+// gsl_min_fminimizer_name (s));
+//
+// printf ("%5s [%9s, %9s] %9s %10s %9s\n",
+// "iter", "lower", "upper", "min",
+// "err", "err(est)");
+//
+// printf ("%5d [%.7f, %.7f] %.7f %+.7f %.7f\n",
+// iter, a, b,
+// m, m - m_expected, b - a);
+
+ do
+ {
+ iter++;
+ status = gsl_min_fminimizer_iterate (s);
+
+ m = gsl_min_fminimizer_x_minimum (s);
+ a = gsl_min_fminimizer_x_lower (s);
+ b = gsl_min_fminimizer_x_upper (s);
+
+ status
+ = gsl_min_test_interval (a, b, 1e-3, 0.0);
+
+// if (status == GSL_SUCCESS)
+// printf ("Converged:\n");
+//
+// printf ("%5d [%.7f, %.7f] "
+// "%.7f %+.7f %.7f\n",
+// iter, a, b,
+// m, m - m_expected, b - a);
+ }
+ while (status == GSL_CONTINUE && iter < max_iter);
+
+ gsl_min_fminimizer_free (s);
+
+ if (status != GSL_SUCCESS) return 0;
+
+ return m;
+}
+
+
+
+class EllipseAreaMinimizer : public Toy
+{
+ public:
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ Point toggle_sp( 300, height - 50);
+ toggles[0].bounds = Rect( toggle_sp, toggle_sp + Point(135,25) );
+ ConvexHull ch(psh.pts);
+ bool non_convex = false;
+ for(auto & pt : psh.pts) {
+ if (ch.contains(pt))
+ non_convex = true;
+ }
+
+ if(non_convex) {
+ Circle circ;
+ std::vector<Point> boundary(ch.begin(), ch.end());
+ circ.fit(boundary);
+ e = Ellipse(circ);
+ } else {
+ goal_function_type* gf = &area_goal;
+ if (!toggles[0].on) gf = &perimeter_goal;
+ double coeff = minimizer(psh.pts, gf);
+
+ try
+ {
+ e = fitting(psh.pts, coeff);
+ }
+ catch(LogicalError exc)
+ {
+ std::cerr << exc.what() << std::endl;
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ return;
+ }
+ }
+ cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, 1.0);
+ cairo_set_line_width (cr, 0.3);
+ draw_elliptical_arc_with_cairo( cr,
+ e.center(X), e.center(Y),
+ e.ray(X), e.ray(Y),
+ 0, 2*M_PI,
+ e.rotationAngle() );
+ if (toggles[0].on)
+ *notify << "Area: " << e.ray(X)*e.ray(Y);
+ else
+ *notify << "Perimeter: " << 2* (e.ray(X) + e.ray(Y));
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ void draw_elliptical_arc_with_cairo(
+ cairo_t *cr,
+ double _cx, double _cy,
+ double _rx, double _ry,
+ double _sa, double _ea,
+ double _ra = 0
+ ) const
+ {
+ double cos_rot_angle = std::cos(_ra);
+ double sin_rot_angle = std::sin(_ra);
+ cairo_matrix_t transform_matrix;
+ cairo_matrix_init( &transform_matrix,
+ _rx * cos_rot_angle, _rx * sin_rot_angle,
+ -_ry * sin_rot_angle, _ry * cos_rot_angle,
+ _cx, _cy
+ );
+ cairo_save(cr);
+ cairo_transform(cr, &transform_matrix);
+ cairo_arc(cr, 0, 0, 1, _sa, _ea);
+ cairo_restore(cr);
+ }
+
+ public:
+ EllipseAreaMinimizer()
+ {
+ gsl_set_error_handler(&no_minimum_error_handler);
+
+ first_time = true;
+
+ psh.pts.resize(4);
+ psh.pts[0] = Point(450, 250);
+ psh.pts[1] = Point(250, 100);
+ psh.pts[2] = Point(250, 400);
+ psh.pts[3] = Point(400, 320);
+
+ handles.push_back(&psh);
+
+ toggles.emplace_back("Area/Perimeter", true);
+ handles.push_back(&(toggles[0]));
+ }
+
+ public:
+ Ellipse e;
+ bool first_time;
+ PointSetHandle psh;
+ std::vector<Toggle> toggles;
+};
+
+
+
+
+int main(int argc, char **argv)
+{
+ init( argc, argv, new EllipseAreaMinimizer(), 600, 600 );
+ return 0;
+}
+
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/ellipse-bezier-intersect-toy.cpp b/src/3rdparty/2geom/src/toys/ellipse-bezier-intersect-toy.cpp
new file mode 100644
index 0000000..5468d97
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/ellipse-bezier-intersect-toy.cpp
@@ -0,0 +1,74 @@
+#include <2geom/cairo-path-sink.h>
+#include <2geom/ellipse.h>
+#include <2geom/line.h>
+#include <2geom/polynomial.h>
+#include <toys/toy-framework-2.h>
+
+using namespace Geom;
+
+class CircleIntersect : public Toy {
+ PointSetHandle eh, bh;
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+
+ Rect all(Point(0,0), Point(width, height));
+
+ double rx = Geom::distance(eh.pts[0], eh.pts[1]);
+ double ry = Geom::distance(eh.pts[0], eh.pts[2]);
+ double rot = Geom::atan2(eh.pts[1] - eh.pts[0]);
+
+ Ellipse e(eh.pts[0], Point(rx, ry), rot);
+ D2<Bezier> b(bh.pts);
+
+ cairo_set_line_width(cr, 1.0);
+ Geom::CairoPathSink cps(cr);
+
+ // draw Bezier control polygon
+ cairo_set_source_rgba(cr, 0, 0, 1, 0.3);
+ cps.moveTo(bh.pts[0]);
+ for (unsigned i = 1; i < bh.pts.size(); ++i) {
+ cps.lineTo(bh.pts[i]);
+ }
+ cairo_stroke(cr);
+
+ // draw Bezier curve and ellipse
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ cps.feed(BezierCurve(b), true);
+ cps.feed(e);
+ cairo_stroke(cr);
+
+ std::vector<ShapeIntersection> result = e.intersect(b);
+
+ cairo_set_source_rgb(cr, 1, 0, 0);
+ for (auto & i : result) {
+ draw_handle(cr, i.point());
+ }
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ CircleIntersect(){
+ eh.push_back(300,300); eh.push_back(450,150); eh.push_back(250, 350);
+ bh.push_back(100,100); bh.push_back(500,100); bh.push_back(100,500); bh.push_back(500,500);
+ handles.push_back(&eh);
+ handles.push_back(&bh);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new CircleIntersect());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/ellipse-fitting.cpp b/src/3rdparty/2geom/src/toys/ellipse-fitting.cpp
new file mode 100644
index 0000000..de8c81a
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/ellipse-fitting.cpp
@@ -0,0 +1,191 @@
+/*
+ * Ellipse and Elliptical Arc Fitting Example
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#include <2geom/numeric/fitting-tool.h>
+#include <2geom/numeric/fitting-model.h>
+
+#include <2geom/ellipse.h>
+#include <2geom/elliptical-arc.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+
+using namespace Geom;
+
+
+class EllipseFitting : public Toy
+{
+ private:
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ if (first_time)
+ {
+ first_time = false;
+ Point toggle_sp( 300, height - 50);
+ toggles[0].bounds = Rect( toggle_sp, toggle_sp + Point(120,25) );
+ sliders[0].geometry(Point(50, height - 50), 100);
+ }
+
+ size_t n = (size_t)(sliders[0].value()) + 5;
+ if (n < psh.pts.size())
+ {
+ psh.pts.resize(n);
+ }
+ else if (n > psh.pts.size())
+ {
+ psh.push_back(400*uniform()+50, 300*uniform()+50);
+ }
+
+ try
+ {
+ e.fit(psh.pts);
+ }
+ catch(LogicalError exc)
+ {
+ std::cerr << exc.what() << std::endl;
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ return;
+ }
+
+ if (toggles[0].on)
+ {
+ try
+ {
+ std::unique_ptr<EllipticalArc> eap( e.arc(psh.pts[0], psh.pts[2], psh.pts[4]) );
+ ea = *eap;
+ }
+ catch(RangeError exc)
+ {
+ std::cerr << exc.what() << std::endl;
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ return;
+ }
+ }
+
+ cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, 1.0);
+ cairo_set_line_width (cr, 0.3);
+ if (!toggles[0].on)
+ {
+ draw_elliptical_arc_with_cairo( cr,
+ e.center(X), e.center(Y),
+ e.ray(X), e.ray(Y),
+ 0, 2*M_PI,
+ e.rotationAngle() );
+ }
+ else
+ {
+ draw_text(cr, psh.pts[0], "initial");
+ draw_text(cr, psh.pts[2], "inner");
+ draw_text(cr, psh.pts[4], "final");
+
+ D2<SBasis> easb = ea.toSBasis();
+ cairo_d2_sb(cr, easb);
+ }
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ void draw_elliptical_arc_with_cairo(
+ cairo_t *cr,
+ double _cx, double _cy,
+ double _rx, double _ry,
+ double _sa, double _ea,
+ double _ra = 0
+ ) const
+ {
+ double cos_rot_angle = std::cos(_ra);
+ double sin_rot_angle = std::sin(_ra);
+ cairo_matrix_t transform_matrix;
+ cairo_matrix_init( &transform_matrix,
+ _rx * cos_rot_angle, _rx * sin_rot_angle,
+ -_ry * sin_rot_angle, _ry * cos_rot_angle,
+ _cx, _cy
+ );
+ cairo_save(cr);
+ cairo_transform(cr, &transform_matrix);
+ cairo_arc(cr, 0, 0, 1, _sa, _ea);
+ cairo_restore(cr);
+ }
+
+ public:
+ EllipseFitting()
+ {
+ first_time = true;
+
+ psh.pts.resize(5);
+ psh.pts[0] = Point(450, 250);
+ psh.pts[1] = Point(250, 100);
+ psh.pts[2] = Point(250, 400);
+ psh.pts[3] = Point(400, 320);
+ psh.pts[4] = Point(50, 250);
+
+
+ toggles.emplace_back(" arc / ellipse ", false);
+ sliders.emplace_back(0, 5, 1, 0, "more handles");
+
+ handles.push_back(&psh);
+ handles.push_back(&(toggles[0]));
+ handles.push_back(&(sliders[0]));
+ }
+
+ private:
+ Ellipse e;
+ EllipticalArc ea;
+ bool first_time;
+ PointSetHandle psh;
+ std::vector<Toggle> toggles;
+ std::vector<Slider> sliders;
+};
+
+
+
+int main(int argc, char **argv)
+{
+ init( argc, argv, new EllipseFitting(), 600, 600 );
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/ellipse-intersect-toy.cpp b/src/3rdparty/2geom/src/toys/ellipse-intersect-toy.cpp
new file mode 100644
index 0000000..3d65baa
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/ellipse-intersect-toy.cpp
@@ -0,0 +1,158 @@
+#include <2geom/cairo-path-sink.h>
+#include <2geom/ellipse.h>
+#include <2geom/line.h>
+#include <2geom/polynomial.h>
+#include <toys/toy-framework-2.h>
+
+using namespace Geom;
+
+class CircleIntersect : public Toy {
+ PointSetHandle psh[2];
+ Ellipse ea, eb;
+ Line l[6];
+
+ void intersect() {
+ // This is code is almost the same as in ellipse.cpp.
+ // We use it here to get the lines.
+ double A, B, C, D, E, F;
+ double a, b, c, d, e, f;
+
+ ea.coefficients(A, E, B, C, D, F);
+ eb.coefficients(a, e, b, c, d, f);
+
+ double I, J, K, L;
+ I = (-E*E*F + 4*A*B*F + C*D*E - A*D*D - B*C*C) / 4;
+ J = -((E*E - 4*A*B) * f + (2*E*F - C*D) * e + (2*A*D - C*E) * d +
+ (2*B*C - D*E) * c + (C*C - 4*A*F) * b + (D*D - 4*B*F) * a) / 4;
+ K = -((e*e - 4*a*b) * F + (2*e*f - c*d) * E + (2*a*d - c*e) * D +
+ (2*b*c - d*e) * C + (c*c - 4*a*f) * B + (d*d - 4*b*f) * A) / 4;
+ L = (-e*e*f + 4*a*b*f + c*d*e - a*d*d - b*c*c) / 4;
+
+ std::vector<double> mu = solve_cubic(I, J, K, L);
+
+ for (unsigned i = 0; i < mu.size(); ++i) {
+ double aa = mu[i] * A + a;
+ double bb = mu[i] * B + b;
+ double cc = mu[i] * C + c;
+ double dd = mu[i] * D + d;
+ double ee = mu[i] * E + e;
+ double ff = mu[i] * F + f;
+ double delta = ee*ee - 4*aa*bb;
+ if (delta < 0) {
+ continue;
+ }
+
+ if (aa != 0) {
+ bb /= aa; cc /= aa; dd /= aa; ee /= aa; ff /= aa;
+ double s = (ee + std::sqrt(ee*ee - 4*bb)) / 2;
+ double q = ee - s;
+ double alpha = (dd - cc*q) / (s - q);
+ double beta = cc - alpha;
+
+ l[i*2] = Line(1, q, alpha);
+ l[i*2+1] = Line(1, s, beta);
+ } else if (bb != 0) {
+ cc /= bb; dd /= bb; ee /= bb; ff /= bb;
+ double s = ee;
+ double q = 0;
+ double alpha = cc / ee;
+ double beta = ff * ee / cc;
+
+ l[i*2] = Line(q, 1, alpha);
+ l[i*2+1] = Line(s, 1, beta);
+ } else {
+ // both aa and bb are zero
+ l[i*2] = Line(ee, 1, dd);
+ l[i*2+1] = Line(0, 1, cc/ee);
+ }
+ }
+ }
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+
+ Rect all(Point(0,0), Point(width, height));
+
+ double r1x = Geom::distance(psh[0].pts[0], psh[0].pts[1]);
+ double r1y = Geom::distance(psh[0].pts[0], psh[0].pts[2]);
+ double rot1 = Geom::atan2(psh[0].pts[1] - psh[0].pts[0]);
+
+ double r2x = Geom::distance(psh[1].pts[0], psh[1].pts[1]);
+ double r2y = Geom::distance(psh[1].pts[0], psh[1].pts[2]);
+ double rot2 = Geom::atan2(psh[1].pts[1] - psh[1].pts[0]);
+
+ ea = Ellipse(psh[0].pts[0], Point(r1x, r1y), rot1);
+ eb = Ellipse(psh[1].pts[0], Point(r2x, r2y), rot2);
+
+ for (auto & i : l) {
+ i = Line(0, 0, 0);
+ }
+
+ cairo_set_line_width(cr, 1.0);
+
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ Geom::CairoPathSink cps(cr);
+ cps.feed(ea);
+ cps.feed(eb);
+ cairo_stroke(cr);
+
+ try {
+ intersect();
+ std::vector<ShapeIntersection> result = ea.intersect(eb);
+
+ if (!l[0].isDegenerate() && !l[1].isDegenerate()) {
+ cairo_set_source_rgba(cr, 1, 0, 0, 0.2);
+ draw_line(cr, l[0], all);
+ draw_line(cr, l[1], all);
+ cairo_stroke(cr);
+ }
+ if (!l[2].isDegenerate() && !l[3].isDegenerate()) {
+ cairo_set_source_rgba(cr, 0, 1, 0, 0.2);
+ draw_line(cr, l[2], all);
+ draw_line(cr, l[3], all);
+ cairo_stroke(cr);
+ }
+ if (!l[4].isDegenerate() && !l[5].isDegenerate()) {
+ cairo_set_source_rgba(cr, 0, 0, 1, 0.2);
+ draw_line(cr, l[4], all);
+ draw_line(cr, l[5], all);
+ cairo_stroke(cr);
+ }
+
+ cairo_set_source_rgb(cr, 1, 0, 0);
+ for (auto & i : result) {
+ draw_handle(cr, i.point());
+ }
+ cairo_stroke(cr);
+ } catch(...) {
+ *notify << "Exception";
+ }
+
+ // TODO: draw_handle at intersections
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ CircleIntersect(){
+ psh[0].push_back(300,300); psh[0].push_back(450,150); psh[0].push_back(250, 250);
+ psh[1].push_back(350,300); psh[1].push_back(500,500); psh[1].push_back(300, 350);
+ handles.push_back(&psh[0]);
+ handles.push_back(&psh[1]);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new CircleIntersect());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/ellipse-line-intersect-toy.cpp b/src/3rdparty/2geom/src/toys/ellipse-line-intersect-toy.cpp
new file mode 100644
index 0000000..4172852
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/ellipse-line-intersect-toy.cpp
@@ -0,0 +1,67 @@
+#include <2geom/cairo-path-sink.h>
+#include <2geom/ellipse.h>
+#include <2geom/line.h>
+#include <2geom/polynomial.h>
+#include <toys/toy-framework-2.h>
+
+using namespace Geom;
+
+class CircleIntersect : public Toy {
+ PointSetHandle eh, lh;
+ Ellipse e;
+ Line l;
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+
+ Rect all(Point(0,0), Point(width, height));
+
+ double rx = Geom::distance(eh.pts[0], eh.pts[1]);
+ double ry = Geom::distance(eh.pts[0], eh.pts[2]);
+ double rot = Geom::atan2(eh.pts[1] - eh.pts[0]);
+
+ Ellipse e(eh.pts[0], Point(rx, ry), rot);
+ LineSegment l(lh.pts[0], lh.pts[1]);
+
+ cairo_set_line_width(cr, 1.0);
+
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ draw_line_segment(cr, l, all);
+ Geom::CairoPathSink cps(cr);
+ cps.feed(e);
+ cairo_stroke(cr);
+
+ std::vector<ShapeIntersection> result = e.intersect(l);
+
+ cairo_set_source_rgb(cr, 1, 0, 0);
+ for (auto & i : result) {
+ draw_handle(cr, i.point());
+ }
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ CircleIntersect(){
+ eh.push_back(300,300); eh.push_back(450,150); eh.push_back(250, 350);
+ lh.push_back(280, 50); lh.push_back(320,550);
+ handles.push_back(&eh);
+ handles.push_back(&lh);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new CircleIntersect());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/elliptiarc-3point-center-fitting.cpp b/src/3rdparty/2geom/src/toys/elliptiarc-3point-center-fitting.cpp
new file mode 100644
index 0000000..d2330a1
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/elliptiarc-3point-center-fitting.cpp
@@ -0,0 +1,266 @@
+/*
+ * make up an elliptical arc knowing 3 points lying on the arc
+ * and the ellipse centre
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <2geom/elliptical-arc.h>
+#include <2geom/numeric/linear_system.h>
+
+namespace Geom
+{
+
+bool make_elliptical_arc( EllipticalArc & ea,
+ Point const& centre,
+ Point const& initial,
+ Point const& final,
+ Point const& inner )
+{
+
+ Point p[3] = { initial, inner, final };
+ double x1, x2, x3, x4;
+ double y1, y2, y3, y4;
+ double x1y1, x2y2, x3y1, x1y3;
+ NL::Matrix m(3,3);
+ NL::Vector v(3);
+ NL::LinearSystem ls(m, v);
+
+ m.set_all(0);
+ v.set_all(0);
+ for (auto & k : p)
+ {
+ // init_x_y
+ x1 = k[X] - centre[X]; x2 = x1 * x1; x3 = x2 * x1; x4 = x3 * x1;
+ y1 = k[Y] - centre[Y]; y2 = y1 * y1; y3 = y2 * y1; y4 = y3 * y1;
+ x1y1 = x1 * y1;
+ x2y2 = x2 * y2;
+ x3y1 = x3 * y1; x1y3 = x1 * y3;
+
+ // init linear system
+ m(0,0) += x4;
+ m(0,1) += x3y1;
+ m(0,2) += x2y2;
+
+ m(1,0) += x3y1;
+ m(1,1) += x2y2;
+ m(1,2) += x1y3;
+
+ m(2,0) += x2y2;
+ m(2,1) += x1y3;
+ m(2,2) += y4;
+
+ v[0] += x2;
+ v[1] += x1y1;
+ v[2] += y2;
+ }
+
+ ls.SV_solve();
+
+ double A = ls.solution()[0];
+ double B = ls.solution()[1];
+ double C = ls.solution()[2];
+
+
+ //evaluate ellipse rotation angle
+ double rot = std::atan2( -B, -(A - C) )/2;
+ std::cerr << "rot = " << rot << std::endl;
+ bool swap_axes = false;
+ if ( are_near(rot, 0) ) rot = 0;
+ if ( are_near(rot, M_PI/2) || rot < 0 )
+ {
+ swap_axes = true;
+ }
+
+ // evaluate the length of the ellipse rays
+ double cosrot = std::cos(rot);
+ double sinrot = std::sin(rot);
+ double cos2 = cosrot * cosrot;
+ double sin2 = sinrot * sinrot;
+ double cossin = cosrot * sinrot;
+
+ double den = A * cos2 + B * cossin + C * sin2;
+ if ( den <= 0 )
+ {
+ std::cerr << "!(den > 0) error" << std::endl;
+ std::cerr << "evaluating rx" << std::endl;
+ return false;
+ }
+ double rx = std::sqrt(1/den);
+
+ den = C * cos2 - B * cossin + A * sin2;
+ if ( den <= 0 )
+ {
+ std::cerr << "!(den > 0) error" << std::endl;
+ std::cerr << "evaluating ry" << std::endl;
+ return false;
+ }
+ double ry = std::sqrt(1/den);
+
+
+ // the solution is not unique so we choose always the ellipse
+ // with a rotation angle between 0 and PI/2
+ if ( swap_axes ) std::swap(rx, ry);
+ if ( are_near(rot, M_PI/2)
+ || are_near(rot, -M_PI/2)
+ || are_near(rx, ry) )
+ {
+ rot = 0;
+ }
+ else if ( rot < 0 )
+ {
+ rot += M_PI/2;
+ }
+
+ std::cerr << "swap axes: " << swap_axes << std::endl;
+ std::cerr << "rx = " << rx << " ry = " << ry << std::endl;
+ std::cerr << "rot = " << deg_from_rad(rot) << std::endl;
+ std::cerr << "centre: " << centre << std::endl;
+
+
+ // find out how we should set the large_arc_flag and sweep_flag
+ bool large_arc_flag = true;
+ bool sweep_flag = true;
+
+ Point sp_cp = initial - centre;
+ Point ep_cp = final - centre;
+ Point ip_cp = inner - centre;
+
+ double angle1 = angle_between(sp_cp, ep_cp);
+ double angle2 = angle_between(sp_cp, ip_cp);
+ double angle3 = angle_between(ip_cp, ep_cp);
+
+ if ( angle1 > 0 )
+ {
+ if ( angle2 > 0 && angle3 > 0 )
+ {
+ large_arc_flag = false;
+ sweep_flag = true;
+ }
+ else
+ {
+ large_arc_flag = true;
+ sweep_flag = false;
+ }
+ }
+ else
+ {
+ if ( angle2 < 0 && angle3 < 0 )
+ {
+ large_arc_flag = false;
+ sweep_flag = false;
+ }
+ else
+ {
+ large_arc_flag = true;
+ sweep_flag = true;
+ }
+ }
+
+ // finally we're going to create the elliptical arc!
+ try
+ {
+ ea.set( initial, rx, ry, rot,
+ large_arc_flag, sweep_flag, final );
+ }
+ catch( RangeError e )
+ {
+ std::cerr << e.what() << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+
+}
+
+
+
+using namespace Geom;
+
+class ElliptiArcMaker : public Toy
+{
+ private:
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ cairo_set_line_width (cr, 0.3);
+ cairo_set_source_rgb(cr, 0,0,0.3);
+ draw_text(cr, O.pos, "centre");
+ draw_text(cr, A.pos, "initial");
+ draw_text(cr, B.pos, "final");
+ draw_text(cr, C.pos, "inner");
+ cairo_stroke(cr);
+ cairo_set_source_rgb(cr, 0.7,0,0);
+ bool status
+ = make_elliptical_arc(ea, O.pos, A.pos, B.pos, C.pos);
+ if (status)
+ {
+ D2<Geom::SBasis> easb = ea.toSBasis();
+ cairo_d2_sb(cr, easb);
+ }
+ cairo_stroke(cr);
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ ElliptiArcMaker()
+ : O(443, 441),
+ A(516, 275),
+ B(222, 455),
+ C(190, 234)
+ {
+ handles.push_back(&O);
+ handles.push_back(&A);
+ handles.push_back(&B);
+ handles.push_back(&C);
+ }
+
+ private:
+ PointHandle O, A, B, C;
+ EllipticalArc ea;
+};
+
+
+
+
+
+
+
+
+int main(int argc, char **argv)
+{
+ init( argc, argv, new ElliptiArcMaker() );
+ return 0;
+}
+
diff --git a/src/3rdparty/2geom/src/toys/elliptiarc-curve-fitting.cpp b/src/3rdparty/2geom/src/toys/elliptiarc-curve-fitting.cpp
new file mode 100644
index 0000000..6c47f8d
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/elliptiarc-curve-fitting.cpp
@@ -0,0 +1,127 @@
+/*
+ * Elliptical Arc Fitting Toy
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <gsl/gsl_linalg.h>
+
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/path.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/elliptical-arc.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+
+
+using namespace Geom;
+
+
+
+class EAFittingToy : public Toy
+{
+ private:
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ cairo_set_line_width (cr, 0.2);
+ cairo_set_source_rgb(cr, 0.0, 0.0, 0.);
+ //D2<SBasis> SB = handles_to_sbasis(handles.begin(), total_handles - 1);
+ D2<SBasis> SB = psh.asBezier();
+ cairo_d2_sb(cr, SB);
+ cairo_stroke(cr);
+
+ cairo_set_line_width (cr, 0.4);
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.7, 1.0);
+ try
+ {
+ EllipticalArc EA;
+ if (!arc_from_sbasis(EA, SB, tolerance, 10)) {
+// *notify << "distance error: " << convert.get_error()
+// << " ( " << convert.get_bound() << " )" << std::endl
+// << "angle error: " << convert.get_angle_error()
+// << " ( " << convert.get_angle_tolerance() << " )";
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ return;
+ }
+ D2<SBasis> easb = EA.toSBasis();
+ cairo_d2_sb(cr, easb);
+ cairo_stroke(cr);
+ }
+ catch( RangeError e )
+ {
+ std::cerr << e.what() << std::endl;
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ return;
+ }
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ EAFittingToy( double _tolerance )
+ : tolerance(_tolerance)
+ {
+ handles.push_back(&psh);
+ total_handles = 6;
+ for ( unsigned int i = 0; i < total_handles; ++i )
+ {
+ psh.push_back(uniform()*400, uniform()*400);
+ }
+ }
+
+ PointSetHandle psh;
+ unsigned int total_handles;
+ double tolerance;
+};
+
+
+
+int main(int argc, char **argv)
+{
+ double tolerance = 8;
+ if(argc > 1)
+ sscanf(argv[1], "%lf", &tolerance);
+ init( argc, argv, new EAFittingToy(tolerance) );
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
diff --git a/src/3rdparty/2geom/src/toys/elliptical-arc-toy.cpp b/src/3rdparty/2geom/src/toys/elliptical-arc-toy.cpp
new file mode 100644
index 0000000..e2518f0
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/elliptical-arc-toy.cpp
@@ -0,0 +1,903 @@
+/** @file
+ * @brief Demonstration of elliptical arc functions
+ *//*
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ * Copyright 2008-2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/elliptical-arc.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <2geom/cairo-path-sink.h>
+
+#include <vector>
+#include <string>
+
+
+using namespace Geom;
+
+
+
+std::string angle_formatter(double angle)
+{
+ return default_formatter(decimal_round(deg_from_rad(angle),2));
+}
+
+
+
+class EllipticalArcToy: public Toy
+{
+
+ enum menu_item_t
+ {
+ SHOW_MENU = 0,
+ TEST_BASIC,
+ TEST_COMPARISON,
+ TEST_PORTION,
+ TEST_REVERSE,
+ TEST_NEAREST_POINTS,
+ TEST_DERIVATIVE,
+ TEST_ROOTS,
+ TEST_BOUNDS,
+ TEST_FITTING,
+ TEST_TRANSFORM,
+ TOTAL_ITEMS // this one must be the last item
+ };
+
+ enum handle_label_t
+ {
+ START_POINT = 0,
+ END_POINT,
+ POINT
+ };
+
+ enum toggle_label_t
+ {
+ LARGE_ARC_FLAG = 0,
+ SWEEP_FLAG,
+ X_Y_TOGGLE
+ };
+
+ enum slider_label_t
+ {
+ RX_SLIDER = 0,
+ RY_SLIDER,
+ ROT_ANGLE_SLIDER,
+ T_SLIDER,
+ FROM_SLIDER = T_SLIDER,
+ TO_SLIDER,
+ TM0_SLIDER = T_SLIDER,
+ TM1_SLIDER,
+ TM2_SLIDER,
+ TM3_SLIDER
+ };
+
+ static const char* menu_items[TOTAL_ITEMS];
+ static const char keys[TOTAL_ITEMS];
+
+ void first_time(int /*argc*/, char** /*argv*/) override
+ {
+ draw_f = &EllipticalArcToy::draw_menu;
+ }
+
+ void init_common()
+ {
+ set_common_control_geometry = true;
+ set_control_geometry = true;
+
+ double start_angle = (10.0/6.0) * M_PI;
+ double sweep_angle = (4.0/6.0) * M_PI;
+ double end_angle = start_angle + sweep_angle;
+ double rot_angle = (0.0/6.0) * M_PI;
+ double rx = 200;
+ double ry = 150;
+ double cx = 300;
+ double cy = 300;
+
+ Point start_point( cx + rx * std::cos(start_angle),
+ cy + ry * std::sin(start_angle) );
+ Point end_point( cx + rx * std::cos(end_angle),
+ cy + ry * std::sin(end_angle) );
+
+ bool large_arc = false;
+ bool sweep = true;
+
+
+ initial_point.pos = start_point;
+ final_point.pos = end_point;
+
+ try
+ {
+ ea.set (initial_point.pos,
+ rx, ry, rot_angle,
+ large_arc, sweep,
+ final_point.pos);
+ }
+ catch (RangeError const &e)
+ {
+ no_solution = true;
+ std::cerr << e.what() << std::endl;
+ }
+
+ sliders.clear();
+ sliders.reserve(50);
+ sliders.emplace_back(0, 500, 0, ea.ray(X), "ray X");
+ sliders.emplace_back(0, 500, 0, ea.ray(Y), "ray Y");
+ sliders.emplace_back(0, 2*M_PI, 0, ea.rotationAngle(), "rot angle");
+ sliders[ROT_ANGLE_SLIDER].formatter(&angle_formatter);
+
+ toggles.clear();
+ toggles.reserve(50);
+ toggles.emplace_back("Large Arc Flag", ea.largeArc());
+ toggles.emplace_back("Sweep Flag", ea.sweep());
+
+ handles.clear();
+ handles.push_back(&initial_point);
+ handles.push_back(&final_point);
+ handles.push_back(&(sliders[RX_SLIDER]));
+ handles.push_back(&(sliders[RY_SLIDER]));
+ handles.push_back(&(sliders[ROT_ANGLE_SLIDER]));
+ handles.push_back(&(toggles[LARGE_ARC_FLAG]));
+ handles.push_back(&(toggles[SWEEP_FLAG]));
+ }
+
+ virtual void draw_common( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool /*save*/,
+ std::ostringstream *timer_stream=0)
+ {
+ if(timer_stream == 0)
+ timer_stream = notify;
+ init_common_ctrl_geom(cr, width, height, notify);
+
+ no_solution = false;
+ try
+ {
+ ea.set( initial_point.pos,
+ sliders[0].value(),
+ sliders[1].value(),
+ sliders[2].value(),
+ toggles[0].on,
+ toggles[1].on,
+ final_point.pos );
+ }
+ catch (RangeError const &e)
+ {
+ no_solution = true;
+ std::cerr << e.what() << std::endl;
+ return;
+ }
+
+ degenerate = ea.isDegenerate();
+
+ point_overlap = false;
+ if ( are_near(ea.initialPoint(), ea.finalPoint()) )
+ {
+ point_overlap = true;
+ }
+
+ // calculate the center of the two possible ellipse supporting the arc
+ std::pair<Point,Point> centers
+ = calculate_ellipse_centers( ea.initialPoint(), ea.finalPoint(),
+ ea.ray(X), ea.ray(Y), ea.rotationAngle(),
+ ea.largeArc(), ea.sweep() );
+
+
+ // draw axes passing through the center of the ellipse supporting the arc
+ cairo_set_source_rgba(cr, 0.0, 1.0, 0.0, 1.0);
+ cairo_set_line_width(cr, 0.5);
+ draw_axes(cr);
+
+ // draw the 2 ellipse with rays rx, ry passing through
+ // the 2 given point and with the x-axis inclined of rot_angle
+ if ( !(are_near(ea.ray(X), 0) || are_near(ea.ray(Y), 0)) )
+ {
+ cairo_elliptiarc( cr,
+ centers.first[X], centers.first[Y],
+ ea.ray(X), ea.ray(Y),
+ 0, 2*M_PI,
+ ea.rotationAngle() );
+ cairo_stroke(cr);
+ cairo_elliptiarc( cr,
+ centers.second[X], centers.second[Y],
+ ea.ray(X), ea.ray(Y),
+ 0, 2*M_PI,
+ ea.rotationAngle() );
+ cairo_stroke(cr);
+ }
+
+ // convert the elliptical arc to a sbasis path and draw it
+ D2<SBasis> easb = ea.toSBasis();
+ cairo_set_line_width(cr, 0.5);
+ cairo_set_source_rgba(cr, 0.0, 0.0, 1.0, 1.0);
+ cairo_d2_sb(cr, easb);
+ cairo_stroke(cr);
+
+ // draw initial and final point labels
+ draw_text(cr, ea.initialPoint() + Point(5, -15), "initial");
+ draw_text(cr, ea.finalPoint() + Point(5, 0), "final");
+ cairo_stroke(cr);
+
+ // TODO re-enable this
+ //*notify << ea;
+ }
+
+
+ void draw_comparison(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+ if ( no_solution || point_overlap ) return;
+
+ // draw the arc with cairo in order to make a visual comparison
+ cairo_set_line_width(cr, 1);
+ cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 1.0);
+
+ if (ea.isDegenerate())
+ {
+ cairo_move_to(cr, ea.initialPoint());
+ cairo_line_to(cr, ea.finalPoint());
+ }
+ else
+ {
+ if ( ea.sweep() )
+ {
+ cairo_elliptiarc( cr,
+ ea.center(X), ea.center(Y),
+ ea.ray(X), ea.ray(Y),
+ ea.initialAngle(), ea.finalAngle(),
+ ea.rotationAngle() );
+ }
+ else
+ {
+ cairo_elliptiarc( cr,
+ ea.center(X), ea.center(Y),
+ ea.ray(X), ea.ray(Y),
+ ea.finalAngle(), ea.initialAngle(),
+ ea.rotationAngle() );
+ }
+ }
+ cairo_stroke(cr);
+ }
+
+
+ void init_portion()
+ {
+ init_common();
+
+ from_t = 0;
+ to_t = 1;
+
+ sliders.emplace_back(0, 1, 0, from_t, "from");
+ sliders.emplace_back(0, 1, 0, to_t, "to");
+
+ handles.push_back(&(sliders[FROM_SLIDER]));
+ handles.push_back(&(sliders[TO_SLIDER]));
+ }
+
+ void draw_portion(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+ init_portion_ctrl_geom(cr, notify, width, height);
+ if ( no_solution || point_overlap ) return;
+
+ from_t = sliders[FROM_SLIDER].value();
+ to_t = sliders[TO_SLIDER].value();
+
+ EllipticalArc* eapp
+ = static_cast<EllipticalArc*>(ea.portion(from_t, to_t));
+ EllipticalArc& eap = *eapp;
+
+ cairo_set_line_width(cr, 0.8);
+ cairo_set_source_rgba(cr, 0.0, 1.0, 1.0, 1.0);
+ cairo_move_to(cr, eap.center(X), eap.center(Y));
+ cairo_line_to(cr, eap.initialPoint()[X], eap.initialPoint()[Y]);
+ cairo_move_to(cr, eap.center(X), eap.center(Y));
+ cairo_line_to(cr, eap.finalPoint()[X], eap.finalPoint()[Y]);
+ cairo_stroke(cr);
+ D2<SBasis> sub_arc = eap.toSBasis();
+ cairo_d2_sb(cr, sub_arc);
+ cairo_stroke(cr);
+
+ delete eapp;
+
+ }
+
+
+ void init_reverse()
+ {
+ init_common();
+ time = 0;
+
+ sliders.emplace_back(0, 1, 0, time, "t");
+ handles.push_back(&(sliders[T_SLIDER]));
+ }
+
+ void draw_reverse(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+ init_reverse_ctrl_geom(cr, notify, width, height);
+ if ( no_solution || point_overlap ) return;
+
+
+ time = sliders[T_SLIDER].value();
+
+ EllipticalArc* eapp = static_cast<EllipticalArc*>(ea.reverse());
+ EllipticalArc& eap = *eapp;
+
+ cairo_set_line_width(cr, 0.8);
+ cairo_set_source_rgba(cr, 0.2, 0.2, 0.2, 1.0);
+
+ cairo_move_to(cr, eap.center(X), eap.center(Y));
+ cairo_line_to(cr, eap.valueAt(time,X), eap.valueAt(time,Y));
+ draw_circ(cr, eap.pointAt(time));
+ cairo_stroke(cr);
+ cairo_set_source_rgba(cr, 0.0, 1.0, 1.0, 1.0);
+ D2<SBasis> sub_arc = eap.toSBasis();
+ cairo_d2_sb(cr, sub_arc);
+ cairo_stroke(cr);
+
+ delete eapp;
+
+ }
+
+
+ void init_np()
+ {
+ init_common();
+ nph.pos = Point(10,10);
+ handles.push_back(&nph);
+ }
+
+ void draw_np(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+ if ( no_solution || point_overlap ) return;
+
+ std::vector<double> times = ea.allNearestTimes( nph.pos );
+ for (double time : times)
+ {
+ cairo_move_to(cr,nph.pos);
+ cairo_line_to( cr, ea.pointAt(time) );
+ }
+ cairo_stroke(cr);
+ }
+
+
+ void init_derivative()
+ {
+ init_common();
+ time = 0;
+
+ sliders.emplace_back(0, 1, 0, time, "t");
+ handles.push_back(&(sliders[T_SLIDER]));
+ }
+
+ void draw_derivative(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+ init_reverse_ctrl_geom(cr, notify, width, height);
+ if ( no_solution || point_overlap ) return;
+
+ time = sliders[T_SLIDER].value();
+
+ Curve* der = ea.derivative();
+ Point p = ea.pointAt(time);
+ Point v = der->pointAt(time) + p;
+ delete der;
+// std::vector<Point> points = ea.pointAndDerivatives(time, 8);
+// Point p = points[0];
+// Point v = points[1] + p;
+ cairo_move_to(cr, p);
+ cairo_line_to(cr, v);
+ cairo_stroke(cr);
+ }
+
+
+ void init_roots()
+ {
+ init_common();
+ ph.pos = Point(10,10);
+ toggles.emplace_back("X/Y roots", true );
+
+ handles.push_back(&ph);
+ handles.push_back(&(toggles[X_Y_TOGGLE]));
+ }
+
+ void draw_roots(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+ init_roots_ctrl_geom(cr, notify, width, height);
+ if ( no_solution || point_overlap ) return;
+
+ Dim2 DIM = toggles[X_Y_TOGGLE].on ? X : Y;
+
+ Point p1[2] = { Point(ph.pos[X], -1000),
+ Point(-1000, ph.pos[Y]) };
+ Point p2[2] = { Point(ph.pos[X], 1000),
+ Point(1000, ph.pos[Y]) };
+ cairo_set_line_width(cr, 0.5);
+ cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, 1.0);
+ cairo_move_to(cr, p1[DIM]);
+ cairo_line_to(cr, p2[DIM]);
+
+ std::vector<double> times;
+ try
+ {
+ times = ea.roots(ph.pos[DIM], DIM);
+ *notify << "winding: " << ea.winding(ph.pos);
+ }
+ catch(Geom::Exception e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+ for (double time : times)
+ {
+ draw_handle(cr, ea.pointAt(time));
+ }
+ cairo_stroke(cr);
+ }
+
+
+ void init_bounds()
+ {
+ init_common();
+ }
+
+ void draw_bounds(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+ if ( no_solution || point_overlap ) return;
+
+// const char* msg[] = { "xmax", "xmin", "ymax", "ymin" };
+
+ Rect bb = ea.boundsFast();
+
+// for ( unsigned int i = 0; i < limits.size(); ++i )
+// {
+// std::cerr << "angle[" << i << "] = " << deg_from_rad(limits[i]) << std::endl;
+// Point extreme = ea.pointAtAngle(limits[i]);
+// draw_handle(cr, extreme );
+// draw_text(cr, extreme, msg[i]);
+// }
+ cairo_rectangle( cr, bb.left(), bb.top(), bb.width(), bb.height() );
+ cairo_stroke(cr);
+ }
+
+
+ void init_fitting()
+ {
+ init_common();
+ }
+
+ void draw_fitting(cairo_t * cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+ if ( no_solution || point_overlap ) return;
+
+ D2<SBasis> easb = ea.toSBasis();
+ try
+ {
+ EllipticalArc earc;
+ if (!arc_from_sbasis(earc, easb, 0.1, 5)) return;
+
+ D2<SBasis> arc = earc.toSBasis();
+ arc[0] += Linear(50, 50);
+ cairo_d2_sb(cr, arc);
+ cairo_stroke(cr);
+ }
+ catch (RangeError const &e)
+ {
+ std::cerr << "conversion failure" << std::endl;
+ std::cerr << e.what() << std::endl;
+ return;
+ }
+ }
+
+ void init_transform()
+ {
+ init_common();
+
+ double max = 4;
+ double min = -max;
+
+ sliders.emplace_back(min, max, 0, 1, "TM0");
+ sliders.emplace_back(min, max, 0, 0, "TM1");
+ sliders.emplace_back(min, max, 0, 0, "TM2");
+ sliders.emplace_back(min, max, 0, 1, "TM3");
+
+ handles.push_back(&(sliders[TM0_SLIDER]));
+ handles.push_back(&(sliders[TM1_SLIDER]));
+ handles.push_back(&(sliders[TM2_SLIDER]));
+ handles.push_back(&(sliders[TM3_SLIDER]));
+ }
+
+ void draw_transform(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+ init_transform_ctrl_geom(cr, notify, width, height);
+ if ( no_solution || point_overlap ) return;
+
+ Affine TM(sliders[TM0_SLIDER].value(), sliders[TM1_SLIDER].value(),
+ sliders[TM2_SLIDER].value(), sliders[TM3_SLIDER].value(),
+ ea.center(X), ea.center(Y));
+
+ Affine tm( 1, 0,
+ 0, 1,
+ -ea.center(X), -ea.center(Y) );
+
+
+ EllipticalArc* tea = static_cast<EllipticalArc*>(ea.transformed(tm));
+ EllipticalArc* eat = NULL;
+ eat = static_cast<EllipticalArc*>(tea->transformed(TM));
+ delete tea;
+ if (eat == NULL)
+ {
+ std::cerr << "elliptiarc transformation failed" << std::endl;
+ return;
+ }
+
+ CairoPathSink ps(cr);
+
+ //D2<SBasis> sb = eat->toSBasis();
+ cairo_set_line_width(cr, 0.8);
+ cairo_set_source_rgba(cr, 0.8, 0.1, 0.1, 1.0);
+ //cairo_d2_sb(cr, sb);
+ ps.feed(*eat);
+ cairo_stroke(cr);
+ delete eat;
+ }
+
+ void init_common_ctrl_geom(cairo_t* /*cr*/, int /*width*/, int height, std::ostringstream* /*notify*/)
+ {
+ if ( set_common_control_geometry )
+ {
+ set_common_control_geometry = false;
+
+ sliders[RX_SLIDER].geometry(Point(50, height-120), 250);
+ sliders[RY_SLIDER].geometry(Point(50, height-85), 250);
+ sliders[ROT_ANGLE_SLIDER].geometry(Point(50, height-50), 180);
+
+ toggles[LARGE_ARC_FLAG].bounds = Rect(Point(400, height-120), Point(540, height-95));
+ toggles[SWEEP_FLAG].bounds = Rect(Point(400, height-70), Point(520, height-45));
+ }
+ }
+
+ void init_portion_ctrl_geom(cairo_t* /*cr*/, std::ostringstream* /*notify*/, int /*width*/, int height)
+ {
+ if ( set_control_geometry )
+ {
+ set_control_geometry = false;
+
+ Point from_sp = Point(600, height - 120);
+ Point to_sp = from_sp + Point(0,45);
+ double from_to_len = 100;
+
+ sliders[FROM_SLIDER].geometry(from_sp, from_to_len);
+ sliders[TO_SLIDER].geometry(to_sp, from_to_len);
+ }
+ }
+
+ void init_reverse_ctrl_geom(cairo_t* /*cr*/, std::ostringstream* /*notify*/, int /*width*/, int height)
+ {
+ if ( set_control_geometry )
+ {
+ set_control_geometry = false;
+
+ Point t_sp = Point(600, height - 120);
+ double t_len = 200;
+
+ sliders[T_SLIDER].geometry(t_sp, t_len);
+ }
+ }
+
+ void init_roots_ctrl_geom(cairo_t* /*cr*/, std::ostringstream* /*notify*/, int /*width*/, int height)
+ {
+ if ( set_control_geometry )
+ {
+ set_control_geometry = false;
+ Point T(600, height - 120);
+ toggles[X_Y_TOGGLE].bounds = Rect( T, T + Point(100,25) );
+ }
+ }
+
+ void init_transform_ctrl_geom(cairo_t* /*cr*/, std::ostringstream* /*notify*/, int /*width*/, int height)
+ {
+ if ( set_control_geometry )
+ {
+ set_control_geometry = false;
+
+ Point sp = Point(600, height - 140);
+ Point op = Point(0, 30);
+ double len = 200;
+
+ sliders[TM0_SLIDER].geometry(sp, len);
+ sliders[TM1_SLIDER].geometry(sp += op, len);
+ sliders[TM2_SLIDER].geometry(sp += op, len);
+ sliders[TM3_SLIDER].geometry(sp += op, len);
+ }
+ }
+
+ void init_menu()
+ {
+ handles.clear();
+ sliders.clear();
+ toggles.clear();
+ }
+
+ void draw_menu( cairo_t * /*cr*/, std::ostringstream *notify,
+ int /*width*/, int /*height*/, bool /*save*/,
+ std::ostringstream */*timer_stream*/)
+ {
+ *notify << std::endl;
+ for (int i = SHOW_MENU; i < TOTAL_ITEMS; ++i)
+ {
+ *notify << " " << keys[i] << " - " << menu_items[i] << std::endl;
+ }
+ }
+
+ void key_hit(GdkEventKey *e) override
+ {
+ char choice = std::toupper(e->keyval);
+ switch ( choice )
+ {
+ case 'A':
+ init_menu();
+ draw_f = &EllipticalArcToy::draw_menu;
+ break;
+ case 'B':
+ init_common();
+ draw_f = &EllipticalArcToy::draw_common;
+ break;
+ case 'C':
+ init_common();
+ draw_f = &EllipticalArcToy::draw_comparison;
+ break;
+ case 'D':
+ draw_f = &EllipticalArcToy::draw_menu;
+ init_portion();
+ draw_f = &EllipticalArcToy::draw_portion;
+ break;
+ case 'E':
+ init_reverse();
+ draw_f = &EllipticalArcToy::draw_reverse;
+ break;
+ case 'F':
+ init_np();
+ draw_f = &EllipticalArcToy::draw_np;
+ break;
+ case 'G':
+ init_derivative();
+ draw_f = &EllipticalArcToy::draw_derivative;
+ break;
+ case 'H':
+ init_roots();
+ draw_f = &EllipticalArcToy::draw_roots;
+ break;
+ case 'I':
+ init_bounds();
+ draw_f = &EllipticalArcToy::draw_bounds;
+ break;
+ case 'J':
+ init_fitting();
+ draw_f = &EllipticalArcToy::draw_fitting;
+ break;
+ case 'K':
+ init_transform();
+ draw_f = &EllipticalArcToy::draw_transform;
+ break;
+ }
+ redraw();
+ }
+
+
+ void draw_axes(cairo_t* cr) const
+ {
+ Point D(std::cos(ea.rotationAngle()), std::sin(ea.rotationAngle()));
+ Point Dx = (ea.ray(X) + 20) * D;
+ Point Dy = (ea.ray(Y) + 20) * D.cw();
+ Point C(ea.center(X),ea.center(Y));
+ Point LP = C - Dx;
+ Point RP = C + Dx;
+ Point UP = C - Dy;
+ Point DP = C + Dy;
+
+ cairo_move_to(cr, LP[X], LP[Y]);
+ cairo_line_to(cr, RP[X], RP[Y]);
+ cairo_move_to(cr, UP[X], UP[Y]);
+ cairo_line_to(cr, DP[X], DP[Y]);
+ cairo_move_to(cr, 0, 0);
+ cairo_stroke(cr);
+ }
+
+ void cairo_elliptiarc( cairo_t *cr,
+ double _cx, double _cy,
+ double _rx, double _ry,
+ double _sa, double _ea,
+ double _ra = 0
+ ) const
+ {
+ double cos_rot_angle = std::cos(_ra);
+ double sin_rot_angle = std::sin(_ra);
+ cairo_matrix_t transform_matrix;
+ cairo_matrix_init( &transform_matrix,
+ _rx * cos_rot_angle, _rx * sin_rot_angle,
+ -_ry * sin_rot_angle, _ry * cos_rot_angle,
+ _cx, _cy
+ );
+ cairo_save(cr);
+ cairo_transform(cr, &transform_matrix);
+ cairo_arc(cr, 0, 0, 1, _sa, _ea);
+ cairo_restore(cr);
+ }
+
+
+ std::pair<Point,Point>
+ calculate_ellipse_centers( Point _initial_point, Point _final_point,
+ double m_rx, double m_ry,
+ double m_rot_angle,
+ bool m_large_arc, bool m_sweep
+ )
+ {
+ std::pair<Point,Point> result;
+ if ( _initial_point == _final_point )
+ {
+ result.first = result.second = _initial_point;
+ return result;
+ }
+
+ m_rx = std::fabs(m_rx);
+ m_ry = std::fabs(m_ry);
+
+ Point d = _initial_point - _final_point;
+
+ if ( are_near(m_rx, 0) || are_near(m_ry, 0) )
+ {
+ result.first = result.second
+ = middle_point(_initial_point, _final_point);
+ return result;
+ }
+
+ double sin_rot_angle = std::sin(m_rot_angle);
+ double cos_rot_angle = std::cos(m_rot_angle);
+
+
+ Affine m( cos_rot_angle, -sin_rot_angle,
+ sin_rot_angle, cos_rot_angle,
+ 0, 0 );
+
+ Point p = (d / 2) * m;
+ double rx2 = m_rx * m_rx;
+ double ry2 = m_ry * m_ry;
+ double rxpy = m_rx * p[Y];
+ double rypx = m_ry * p[X];
+ double rx2py2 = rxpy * rxpy;
+ double ry2px2 = rypx * rypx;
+ double num = rx2 * ry2;
+ double den = rx2py2 + ry2px2;
+ assert(den != 0);
+ double rad = num / den;
+ Point c(0,0);
+ if (rad > 1)
+ {
+ rad -= 1;
+ rad = std::sqrt(rad);
+
+ if (m_large_arc == m_sweep) rad = -rad;
+ c = rad * Point(rxpy / m_ry, -rypx / m_rx);
+
+ m[1] = -m[1];
+ m[2] = -m[2];
+
+ c = c * m;
+ }
+
+ d = middle_point(_initial_point, _final_point);
+
+ result.first = c + d;
+ result.second = -c + d;
+ return result;
+
+ }
+
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ (this->*draw_f)(cr, notify, width, height, save, timer_stream);
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ EllipticalArcToy() {}
+
+ private:
+ typedef void (EllipticalArcToy::* draw_func_t) (cairo_t*, std::ostringstream*, int, int, bool, std::ostringstream*);
+ draw_func_t draw_f;
+ bool set_common_control_geometry;
+ bool set_control_geometry;
+ bool no_solution, point_overlap;
+ bool degenerate;
+ PointHandle initial_point, final_point;
+ PointHandle nph, ph;
+ std::vector<Toggle> toggles;
+ std::vector<Slider> sliders;
+ EllipticalArc ea;
+
+ double from_t;
+ double to_t;
+ double time;
+
+};
+
+
+const char* EllipticalArcToy::menu_items[] =
+{
+ "show this menu",
+ "basic",
+ "comparison",
+ "portion, pointAt",
+ "reverse, valueAt",
+ "nearest points",
+ "derivative",
+ "roots",
+ "bounding box",
+ "fitting",
+ "transformation"
+};
+
+const char EllipticalArcToy::keys[] =
+{
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K'
+};
+
+
+int main(int argc, char **argv)
+{
+ init( argc, argv, new EllipticalArcToy(), 850, 780 );
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/evolute.cpp b/src/3rdparty/2geom/src/toys/evolute.cpp
new file mode 100644
index 0000000..a5deb08
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/evolute.cpp
@@ -0,0 +1,93 @@
+#include <2geom/basic-intersection.h>
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/bezier-to-sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+using std::vector;
+using namespace Geom;
+
+/*
+jfb: I think the evolute goes to infinity at inflection points, in which case you cannot "join" the pieces by hand.
+jfb: for the evolute toy, you could not only cut at inflection points, but event remove the domains where cross(dda,da)<c*|da|^3, where c is a small constant, as these points will be off screen anyway.
+*/
+
+class Evolution: public Toy {
+ PointSetHandle psh;
+void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_line_width (cr, 0.5);
+ cairo_set_source_rgba (cr, 0., 0., 0, 1);
+
+ D2<SBasis> A(psh.asBezier());
+
+ D2<SBasis> dA = derivative(A);
+ D2<SBasis> ddA = derivative(dA);
+ SBasis crs = cross(ddA, dA);
+ cairo_d2_sb(cr, D2<SBasis>(Linear(0,1000), crs*(500./bounds_exact(crs)->extent())));
+ vector<double> rts = roots(crs);
+ for(double rt : rts) {
+ draw_handle(cr, A(rt));
+ }
+ cairo_d2_sb(cr, A);
+ cairo_stroke(cr);
+ Interval r(0, 1);
+ if(!rts.empty())
+ r.setMax(rts[0]);
+ //if(rts[0] == 0)
+ //rts.erase(rts.begin(), rts.begin()+1);
+ A = portion(A, r.min(), r.max());
+ dA = portion(dA, r.min(), r.max());
+ ddA = portion(ddA, r.min(), r.max());
+ crs = portion(crs, r.min(), r.max());
+ cairo_stroke(cr);
+ Piecewise<SBasis> s = divide(dA[0]*dot(dA,dA), crs, 100, 1);
+ D2<Piecewise<SBasis> > ev4(Piecewise<SBasis>(A[0]) + divide(-dA[1]*dot(dA,dA), crs, 100, 1),
+ Piecewise<SBasis>(A[1]) + divide(dA[0]*dot(dA,dA), crs, 100, 1));
+ cairo_d2_pw_sb(cr, ev4);
+ cairo_stroke(cr);
+ if(1) {
+ std::cout << "bnd" << *bounds_exact(dot(ev4, ev4)) << std::endl;
+ cairo_d2_pw_sb(cr, D2<Piecewise<SBasis> >(Piecewise<SBasis>(SBasis(Linear(0,1000))), dot(ev4, ev4)*1000));
+ cairo_stroke(cr);
+ vector<double> rts = roots(dot(ev4, ev4)-1);
+ for(double rt : rts) {
+ std::cout << rt << std::endl;
+ draw_handle(cr, ev4(rt));
+ }
+ }
+ cairo_set_source_rgba (cr, 1., 0., 1, 1);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+}
+public:
+Evolution (unsigned bez_ord) {
+ handles.push_back(&psh);
+ for(unsigned i = 0; i < bez_ord; i++)
+ psh.push_back(uniform()*400, uniform()*400);
+}
+};
+
+int main(int argc, char **argv) {
+ unsigned bez_ord=5;
+ if(argc > 1)
+ sscanf(argv[1], "%d", &bez_ord);
+ init(argc, argv, new Evolution(bez_ord));
+
+ return 0;
+}
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/filet-minion.cpp b/src/3rdparty/2geom/src/toys/filet-minion.cpp
new file mode 100644
index 0000000..e94e354
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/filet-minion.cpp
@@ -0,0 +1,159 @@
+#include <iostream>
+#include <2geom/path.h>
+#include <2geom/svg-path-parser.h>
+#include <2geom/path-intersection.h>
+#include <2geom/basic-intersection.h>
+#include <2geom/pathvector.h>
+#include <2geom/exception.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/path-intersection.h>
+#include <2geom/nearest-time.h>
+#include <2geom/circle.h>
+
+#include <cstdlib>
+#include <map>
+#include <vector>
+#include <algorithm>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/ord.h>
+using namespace Geom;
+using namespace std;
+
+class IntersectDataTester: public Toy {
+ int nb_paths;
+ int nb_curves_per_path;
+ int degree;
+
+ std::vector<PointSetHandle> paths_handles;
+ std::vector<Slider> sliders;
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_source_rgba (cr, 0., 0., 0, 1);
+ cairo_set_line_width (cr, 1);
+
+ std::vector<D2<SBasis> > pieces;
+ PathVector paths;
+ for (int i = 0; i < nb_paths; i++){
+ paths.push_back(Path(paths_handles[i].pts[0]));
+ for (unsigned j = 0; j+degree < paths_handles[i].size(); j+=degree){
+ D2<SBasis> c = handles_to_sbasis(paths_handles[i].pts.begin()+j, degree);
+ paths[i].append(c);
+ pieces.push_back(c);
+ }
+ }
+
+ cairo_path(cr, paths);
+ cairo_set_source_rgba (cr, 0., 0., 0, 1);
+ cairo_set_line_width (cr, 1);
+ cairo_stroke(cr);
+ double r = sliders[0].value();
+
+ D2<SBasis> B = pieces[0];
+ Piecewise<D2<SBasis> > offset_curve0 = Piecewise<D2<SBasis> >(pieces[0])+rot90(unitVector(derivative(pieces[0])))*(-r);
+ Piecewise<D2<SBasis> > offset_curve1 = Piecewise<D2<SBasis> >(pieces[1])+rot90(unitVector(derivative(pieces[1])))*(-r);
+
+ //cairo_pw_d2_sb(cr, offset_curve0);
+ //cairo_pw_d2_sb(cr, offset_curve1);
+ //cairo_stroke(cr);
+
+
+ Path p0 = path_from_piecewise(offset_curve0, 0.1)[0];
+ Path p1 = path_from_piecewise(offset_curve1, 0.1)[0];
+ Crossings cs = crossings(p0, p1);
+
+
+ for(auto & c : cs) {
+ *notify << c.ta << ", " << c.tb << '\n';
+ Point cp =p0(c.ta);
+ //draw_circ(cr, cp);
+ //cairo_stroke(cr);
+ double p0pt = nearest_time(cp, pieces[0]);
+ double p1pt = nearest_time(cp, pieces[1]);
+ Circle circ(cp[0], cp[1], r);
+ //cairo_arc(cr, circ.center(X), circ.center(Y), circ.ray(), 0, 2*M_PI);
+
+ std::unique_ptr<EllipticalArc> eap(
+ circ.arc(pieces[0](p0pt), pieces[0](1), pieces[1](p1pt)) );
+ D2<SBasis> easb = eap->toSBasis();
+ cairo_d2_sb(cr, easb);
+ cairo_stroke(cr);
+ }
+
+ Point ends[2];
+ if (0)
+ for(int endi = 0; endi < 2; endi++) {
+ D2<SBasis> dist = pieces[endi]-pieces[0].at1();
+ *notify << dist << "\n";
+ vector<double> locs = roots(dot(dist,dist) - SBasis(r*r));
+ for(double loc : locs) {
+ //draw_circ(cr, pieces[endi](locs[i]));
+ *notify << loc << ' ';
+ }
+ if(locs.size()) {
+ std::sort(locs.begin(), locs.end());
+ if (endi)
+ ends[endi] = pieces[endi](locs[0]);
+ else
+ ends[endi] = pieces[endi](locs.back());
+ draw_circ(cr, ends[endi]);
+ }
+ }
+
+ Toy::draw(cr, notify, width, height, save, timer_stream);
+ }
+
+ public:
+ IntersectDataTester(int paths, int curves_in_path, int degree) :
+ nb_paths(paths), nb_curves_per_path(curves_in_path), degree(degree) {
+ for (int i = 0; i < nb_paths; i++){
+ paths_handles.emplace_back();
+ }
+ for(int i = 0; i < nb_paths; i++){
+ for(int j = 0; j < (nb_curves_per_path*degree)+1; j++){
+ paths_handles[i].push_back(uniform()*400, 100+ uniform()*300);
+ }
+ handles.push_back(&paths_handles[i]);
+ }
+ sliders.emplace_back(0.0, 100.0, 1, 30.0, "min radius");
+ sliders.emplace_back(0.0, 100.0, 1, 0.0, "ray chooser");
+ sliders.emplace_back(0.0, 100.0, 1, 0.0, "area chooser");
+ handles.push_back(&(sliders[0]));
+ handles.push_back(&(sliders[1]));
+ handles.push_back(&(sliders[2]));
+ sliders[0].geometry(Point(50, 20), 250);
+ sliders[1].geometry(Point(50, 50), 250);
+ sliders[2].geometry(Point(50, 80), 250);
+ }
+
+ void first_time(int /*argc*/, char** /*argv*/) override {
+
+ }
+};
+
+int main(int argc, char **argv) {
+ unsigned paths=1;
+ unsigned curves_in_path=2;
+ unsigned degree=3;
+ if(argc > 3)
+ sscanf(argv[3], "%d", &degree);
+ if(argc > 2)
+ sscanf(argv[2], "%d", &curves_in_path);
+ if(argc > 1)
+ sscanf(argv[1], "%d", &paths);
+ init(argc, argv, new IntersectDataTester(paths, curves_in_path, degree));
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/find-derivative.cpp b/src/3rdparty/2geom/src/toys/find-derivative.cpp
new file mode 100644
index 0000000..e4c64f5
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/find-derivative.cpp
@@ -0,0 +1,500 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-geometric.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <2geom/angle.h>
+
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+// Author: Johan Engelen, 2009
+//
+// Shows how to find the locations on a path where the derivative is parallel to a certain vector.
+//-----------------------------------------------
+
+
+std::string angle_formatter(double angle)
+{
+ return default_formatter(decimal_round(deg_from_rad(angle),2));
+}
+
+
+
+class FindDerivatives : public Toy
+{
+ enum menu_item_t
+ {
+ SHOW_MENU = 0,
+ TEST_CREATE,
+ TEST_PROJECTION,
+ TEST_ORTHO,
+ TEST_DISTANCE,
+ TEST_POSITION,
+ TEST_SEG_BISEC,
+ TEST_ANGLE_BISEC,
+ TEST_COLLINEAR,
+ TEST_INTERSECTIONS,
+ TEST_COEFFICIENTS,
+ TOTAL_ITEMS // this one must be the last item
+ };
+
+ enum handle_label_t
+ {
+ };
+
+ enum toggle_label_t
+ {
+ };
+
+ enum slider_label_t
+ {
+ END_SHARED_SLIDERS = 0,
+ ANGLE_SLIDER = END_SHARED_SLIDERS,
+ A_COEFF_SLIDER = END_SHARED_SLIDERS,
+ B_COEFF_SLIDER,
+ C_COEFF_SLIDER
+ };
+
+ static const char* menu_items[TOTAL_ITEMS];
+ static const char keys[TOTAL_ITEMS];
+
+ PointSetHandle curve_handle;
+ PointHandle sample_point;
+
+ void first_time(int /*argc*/, char** /*argv*/) override
+ {
+ draw_f = &FindDerivatives::draw_menu;
+ }
+
+ void init_common()
+ {
+ set_common_control_geometry = true;
+ set_control_geometry = true;
+
+ sliders.clear();
+ toggles.clear();
+ handles.clear();
+ }
+
+
+ virtual void draw_common( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool /*save*/ )
+ {
+ init_common_ctrl_geom(cr, width, height, notify);
+ }
+
+
+ void init_create()
+ {
+ init_common();
+
+ p1.pos = Point(400, 50);
+ p2.pos = Point(450, 450);
+ O.pos = Point(50, 400);
+
+ sliders.emplace_back(0, 2*M_PI, 0, 0, "angle");
+ sliders[ANGLE_SLIDER].formatter(&angle_formatter);
+
+ handles.push_back(&p1);
+ handles.push_back(&p2);
+ handles.push_back(&O);
+ handles.push_back(&(sliders[ANGLE_SLIDER]));
+ }
+
+ void draw_create(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+ init_create_ctrl_geom(cr, notify, width, height);
+
+ Line l1(p1.pos, p2.pos);
+ Line l2(O.pos, sliders[ANGLE_SLIDER].value());
+
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_set_line_width(cr, 0.3);
+ draw_line(cr, l1);
+ draw_line(cr, l2);
+ cairo_stroke(cr);
+
+ draw_label(cr, p1, "P1");
+ draw_label(cr, p2, "P2");
+ draw_label(cr, O, "O");
+ draw_label(cr, l1, "L(P1,P2)");
+ draw_label(cr, l2, "L(O,angle)");
+ }
+
+
+ void init_projection()
+ {
+ init_common();
+ p1.pos = Point(400, 50);
+ p2.pos = Point(450, 450);
+ p3.pos = Point(100, 250);
+ p4.pos = Point(200, 450);
+ O.pos = Point(50, 150);
+
+ handles.push_back(&p1);
+ handles.push_back(&p2);
+ handles.push_back(&p3);
+ handles.push_back(&p4);
+ handles.push_back(&O);
+ }
+
+ void draw_projection(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+
+ Line l1(p1.pos, p2.pos);
+ LineSegment ls(p3.pos, p4.pos);
+
+ Point np = projection(O.pos, l1);
+ LineSegment lsp = projection(ls, l1);
+
+ cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, 1.0);
+ cairo_set_line_width(cr, 0.2);
+ draw_line(cr, l1);
+ draw_segment(cr, ls);
+ cairo_stroke(cr);
+
+ cairo_set_line_width(cr, 0.3);
+ cairo_set_source_rgba(cr, 0.0, 0.0, 1.0, 1.0);
+ draw_segment(cr, lsp);
+ draw_handle(cr, lsp[0]);
+ draw_handle(cr, lsp[1]);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba(cr, 0.8, 0.0, 0.0, 1.0);
+ draw_circ(cr, np);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba(cr, 0.5, 0.5, 0.5, 1.0);
+ draw_label(cr, p1, "P1");
+ draw_label(cr, p2, "P2");
+ draw_label(cr, ls, "S");
+ draw_label(cr, lsp, "prj(S)");
+ draw_label(cr, O, "P");
+ draw_text(cr, np, "prj(P)");
+
+ cairo_stroke(cr);
+ }
+
+ void init_derivative() {
+ init_common();
+ handles.push_back(&curve_handle);
+ handles.push_back(&sample_point);
+ for(unsigned i = 0; i < 4; i++)
+ curve_handle.push_back(150+uniform()*300,150+uniform()*300);
+ sample_point.pos = Geom::Point(250,300);
+ }
+
+ void draw_derivative(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) {
+
+ D2<SBasis> B = curve_handle.asBezier();
+
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0., 0.5, 0., 1);
+ cairo_d2_sb(cr, B);
+ cairo_stroke(cr);
+
+ Point vector = sample_point.pos - Geom::Point(400,400);
+ cairo_move_to(cr, Geom::Point(400,400));
+ cairo_line_to(cr, sample_point.pos);
+ cairo_set_source_rgba (cr, 0., 0., 0.5, 0.8);
+ cairo_stroke(cr);
+
+ // How to find location of points with certain derivative along a path:
+ D2<SBasis> deriv = derivative(B);
+ SBasis dotp = dot(deriv, rot90(vector));
+ std::vector<double> sol = roots(dotp);
+ for (double i : sol) {
+ draw_handle(cr, B.valueAt(i)); // the solutions are in vector 'sol'
+ }
+
+ cairo_set_source_rgba (cr, 0.5, 0.2, 0., 0.8);
+ cairo_stroke(cr);
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ void init_find_tangents() {
+ init_common();
+ handles.push_back(&curve_handle);
+ handles.push_back(&sample_point);
+
+ toggles.emplace_back(" tangent / normal ", false);
+ handles.push_back(&(toggles[0]));
+ for(unsigned i = 0; i < 4; i++)
+ curve_handle.push_back(150+uniform()*300,150+uniform()*300);
+ sample_point.pos = Geom::Point(250,300);
+ Point toggle_sp( 30, 30);
+ toggles[0].bounds = Rect( toggle_sp, toggle_sp + Point(200,25) );
+ }
+
+ void draw_find_tangents(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) {
+
+ D2<SBasis> B = curve_handle.asBezier();
+
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0., 0.5, 0., 1);
+ cairo_d2_sb(cr, B);
+ cairo_stroke(cr);
+
+ std::vector<double> sol = toggles[0].on ?
+ find_tangents(sample_point.pos, B)
+ : find_normals(sample_point.pos, B);
+ for (double i : sol) {
+ draw_handle(cr, B.valueAt(i)); // the solutions are in vector 'sol'
+ draw_segment(cr, B.valueAt(i), sample_point.pos);
+ }
+
+ cairo_set_source_rgba (cr, 0.5, 0.2, 0., 0.8);
+ cairo_stroke(cr);
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ void init_ortho()
+ {
+ init_common();
+ p1.pos = Point(400, 50);
+ p2.pos = Point(450, 450);
+ p3.pos = Point(100, 50);
+ p4.pos = Point(150, 450);
+
+ handles.push_back(&p1);
+ handles.push_back(&p2);
+ handles.push_back(&p3);
+ handles.push_back(&p4);
+ }
+
+ void draw_ortho(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+
+ Line l1(p1.pos, p2.pos);
+ Line l2 = make_orthogonal_line(p3.pos, l1);
+ Line l3 = make_parallel_line(p4.pos, l1);
+
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_set_line_width(cr, 0.3);
+ draw_line(cr, l1);
+ draw_line(cr, l2);
+ draw_line(cr, l3);
+ cairo_stroke(cr);
+
+ draw_label(cr, p1, "P1");
+ draw_label(cr, p2, "P2");
+ draw_label(cr, p3, "O1");
+ draw_label(cr, p4, "O2");
+
+ draw_label(cr, l1, "L");
+ draw_label(cr, l2, "L1 _|_ L");
+ draw_label(cr, l3, "L2 // L");
+
+ }
+
+
+
+
+ void init_common_ctrl_geom(cairo_t* /*cr*/, int /*width*/, int /*height*/, std::ostringstream* /*notify*/)
+ {
+ if ( set_common_control_geometry )
+ {
+ set_common_control_geometry = false;
+ }
+ }
+
+ void init_create_ctrl_geom(cairo_t* /*cr*/, std::ostringstream* /*notify*/, int /*width*/, int height)
+ {
+ if ( set_control_geometry )
+ {
+ set_control_geometry = false;
+
+ sliders[ANGLE_SLIDER].geometry(Point(50, height - 50), 180);
+ }
+ }
+
+ void init_coefficients_ctrl_geom(cairo_t* /*cr*/, std::ostringstream* /*notify*/, int /*width*/, int height)
+ {
+ if ( set_control_geometry )
+ {
+ set_control_geometry = false;
+
+ sliders[A_COEFF_SLIDER].geometry(Point(50, height - 160), 400);
+ sliders[B_COEFF_SLIDER].geometry(Point(50, height - 110), 400);
+ sliders[C_COEFF_SLIDER].geometry(Point(50, height - 60), 400);
+ }
+ }
+
+
+ void draw_segment(cairo_t* cr, Point const& p1, Point const& p2)
+ {
+ cairo_move_to(cr, p1);
+ cairo_line_to(cr, p2);
+ }
+
+ void draw_segment(cairo_t* cr, Point const& p1, double angle, double length)
+ {
+ Point p2;
+ p2[X] = length * std::cos(angle);
+ p2[Y] = length * std::sin(angle);
+ p2 += p1;
+ draw_segment(cr, p1, p2);
+ }
+
+ void draw_segment(cairo_t* cr, LineSegment const& ls)
+ {
+ draw_segment(cr, ls[0], ls[1]);
+ }
+
+ void draw_ray(cairo_t* cr, Ray const& r)
+ {
+ double angle = r.angle();
+ draw_segment(cr, r.origin(), angle, m_length);
+ }
+
+ void draw_line(cairo_t* cr, Line const& l)
+ {
+ double angle = l.angle();
+ draw_segment(cr, l.origin(), angle, m_length);
+ draw_segment(cr, l.origin(), angle, -m_length);
+ }
+
+ void draw_label(cairo_t* cr, PointHandle const& ph, const char* label)
+ {
+ draw_text(cr, ph.pos+op, label);
+ }
+
+ void draw_label(cairo_t* cr, Line const& l, const char* label)
+ {
+ draw_text(cr, projection(Point(m_width/2-30, m_height/2-30), l)+op, label);
+ }
+
+ void draw_label(cairo_t* cr, LineSegment const& ls, const char* label)
+ {
+ draw_text(cr, middle_point(ls[0], ls[1])+op, label);
+ }
+
+ void draw_label(cairo_t* cr, Ray const& r, const char* label)
+ {
+ Point prj = r.pointAt(r.nearestTime(Point(m_width/2-30, m_height/2-30)));
+ if (L2(r.origin() - prj) < 100)
+ {
+ prj = r.origin() + 100*r.vector();
+ }
+ draw_text(cr, prj+op, label);
+ }
+
+ void init_menu()
+ {
+ handles.clear();
+ sliders.clear();
+ toggles.clear();
+ }
+
+ void draw_menu( cairo_t * /*cr*/, std::ostringstream *notify,
+ int /*width*/, int /*height*/, bool /*save*/,
+ std::ostringstream */*timer_stream*/ )
+ {
+ *notify << std::endl;
+ for (int i = SHOW_MENU; i < TOTAL_ITEMS; ++i)
+ {
+ *notify << " " << keys[i] << " - " << menu_items[i] << std::endl;
+ }
+ }
+
+ void key_hit(GdkEventKey *e) override
+ {
+ char choice = std::toupper(e->keyval);
+ switch ( choice )
+ {
+ case 'A':
+ init_menu();
+ draw_f = &FindDerivatives::draw_menu;
+ break;
+ case 'B':
+ init_derivative();
+ draw_f = &FindDerivatives::draw_derivative;
+ break;
+ case 'C':
+ init_find_tangents();
+ draw_f = &FindDerivatives::draw_find_tangents;
+ break;
+ case 'D':
+ init_ortho();
+ draw_f = &FindDerivatives::draw_ortho;
+ break;
+ }
+ redraw();
+ }
+
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ m_width = width;
+ m_height = height;
+ m_length = (m_width > m_height) ? m_width : m_height;
+ m_length *= 2;
+ (this->*draw_f)(cr, notify, width, height, save, timer_stream);
+ Toy::draw(cr, notify, width, height, save, timer_stream);
+ }
+
+ public:
+ FindDerivatives()
+ {
+ op = Point(5,5);
+ }
+
+ private:
+ typedef void (FindDerivatives::* draw_func_t) (cairo_t*, std::ostringstream*, int, int, bool, std::ostringstream*);
+ draw_func_t draw_f;
+ bool set_common_control_geometry;
+ bool set_control_geometry;
+ PointHandle p1, p2, p3, p4, p5, p6, O;
+ std::vector<Toggle> toggles;
+ std::vector<Slider> sliders;
+ Point op;
+ double m_width, m_height, m_length;
+
+}; // end class FindDerivatives
+
+
+const char* FindDerivatives::menu_items[] =
+{
+ "show this menu",
+ "derivative matching on curve",
+ "find normals",
+ "find tangents"
+};
+
+const char FindDerivatives::keys[] =
+{
+ 'A', 'B', 'C', 'D'
+};
+
+
+
+int main(int argc, char **argv)
+{
+ init( argc, argv, new FindDerivatives());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+//vim:expandtab:shiftwidth = 4:tabstop = 8:softtabstop = 4:encoding = utf-8:textwidth = 99 :
+
+
diff --git a/src/3rdparty/2geom/src/toys/gear.cpp b/src/3rdparty/2geom/src/toys/gear.cpp
new file mode 100644
index 0000000..d2f2de2
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/gear.cpp
@@ -0,0 +1,317 @@
+/*
+ * GearToy - displays involute gears
+ *
+ * Copyright 2006 Michael G. Sloan <mgsloan@gmail.com>
+ * Copyright 2006 Aaron Spike <aaron@ekips.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/path.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+using std::vector;
+using namespace Geom;
+
+class Gear {
+public:
+ // pitch circles touch on two properly meshed gears
+ // all measurements are taken from the pitch circle
+ double pitch_diameter() {return (_number_of_teeth * _module) / M_PI;}
+ double pitch_radius() {return pitch_diameter() / 2.0;}
+ void pitch_radius(double R) {_module = (2 * M_PI * R) / _number_of_teeth;}
+
+ // base circle serves as the basis for the involute toothe profile
+ double base_diameter() {return pitch_diameter() * cos(_pressure_angle);}
+ double base_radius() {return base_diameter() / 2.0;}
+
+ // diametrical pitch
+ double diametrical_pitch() {return _number_of_teeth / pitch_diameter();}
+
+ // height of the tooth above the pitch circle
+ double addendum() {return 1.0 / diametrical_pitch();}
+ // depth of the tooth below the pitch circle
+ double dedendum() {return addendum() + _clearance;}
+
+ // root circle specifies the bottom of the fillet between teeth
+ double root_radius() {return pitch_radius() - dedendum();}
+ double root_diameter() {return root_radius() * 2.0;}
+
+ // outer circle is the outside diameter of the gear
+ double outer_radius() {return pitch_radius() + addendum();}
+ double outer_diameter() {return outer_radius() * 2.0;}
+
+ // angle covered by the tooth on the pitch circle
+ double tooth_thickness_angle() {return M_PI / _number_of_teeth;}
+
+ Geom::Point centre() {return _centre;}
+ void centre(Geom::Point c) {_centre = c;}
+
+ double angle() {return _angle;}
+ void angle(double a) {_angle = a;}
+
+ int number_of_teeth() {return _number_of_teeth;}
+
+ Geom::Path path();
+ Gear spawn(int N, double a);
+
+ Gear(int n, double m, double phi) {
+ _number_of_teeth = n;
+ _module = m;
+ _pressure_angle = phi;
+ _clearance = 0.0;
+ _angle = 0.0;
+ _centre = Geom::Point(0.0,0.0);
+ }
+private:
+ int _number_of_teeth;
+ double _pressure_angle;
+ double _module;
+ double _clearance;
+ double _angle;
+ Geom::Point _centre;
+ D2<SBasis> _involute(double start, double stop) {
+ D2<SBasis> B;
+ D2<SBasis> I;
+ Linear bo = Linear(start,stop);
+
+ B[0] = cos(bo,2);
+ B[1] = sin(bo,2);
+
+ I = B - Linear(0,1) * derivative(B);
+ I = I*base_radius() + _centre;
+ return I;
+ }
+ D2<SBasis> _arc(double start, double stop, double R) {
+ D2<SBasis> B;
+ Linear bo = Linear(start,stop);
+
+ B[0] = cos(bo,2);
+ B[1] = sin(bo,2);
+
+ B = B*R + _centre;
+ return B;
+ }
+ // angle of the base circle used to create the involute to a certain radius
+ double involute_swath_angle(double R) {
+ if (R <= base_radius()) return 0.0;
+ return sqrt(R*R - base_radius()*base_radius())/base_radius();
+ }
+
+ // angle of the base circle between the origin of the involute and the intersection on another radius
+ double involute_intersect_angle(double R) {
+ if (R <= base_radius()) return 0.0;
+ return (sqrt(R*R - base_radius()*base_radius())/base_radius()) - acos(base_radius()/R);
+ }
+};
+
+void makeContinuous(D2<SBasis> &a, Point const b) {
+ for(unsigned d=0;d<2;d++)
+ a[d][0][0] = b[d];
+}
+
+Geom::Path Gear::path() {
+ Geom::Path pb;
+
+ // angle covered by a full tooth and fillet
+ double tooth_rotation = 2.0 * tooth_thickness_angle();
+ // angle covered by an involute
+ double involute_advance = involute_intersect_angle(outer_radius()) - involute_intersect_angle(root_radius());
+ // angle covered by the tooth tip
+ double tip_advance = tooth_thickness_angle() - (2 * (involute_intersect_angle(outer_radius()) - involute_intersect_angle(pitch_radius())));
+ // angle covered by the toothe root
+ double root_advance = (tooth_rotation - tip_advance) - (2.0 * involute_advance);
+ // begin drawing the involute at t if the root circle is larger than the base circle
+ double involute_t = involute_swath_angle(root_radius())/involute_swath_angle(outer_radius());
+
+ //rewind angle to start drawing from the leading edge of the tooth
+ double first_tooth_angle = _angle - ((0.5 * tip_advance) + involute_advance);
+
+ Geom::Point prev;
+ for (int i=0; i < _number_of_teeth; i++)
+ {
+ double cursor = first_tooth_angle + (i * tooth_rotation);
+
+ D2<SBasis> leading_I = compose(_involute(cursor, cursor + involute_swath_angle(outer_radius())), Linear(involute_t,1));
+ if(i != 0) makeContinuous(leading_I, prev);
+ pb.append(SBasisCurve(leading_I));
+ cursor += involute_advance;
+ prev = leading_I.at1();
+
+ D2<SBasis> tip = _arc(cursor, cursor+tip_advance, outer_radius());
+ makeContinuous(tip, prev);
+ pb.append(SBasisCurve(tip));
+ cursor += tip_advance;
+ prev = tip.at1();
+
+ cursor += involute_advance;
+ D2<SBasis> trailing_I = compose(_involute(cursor, cursor - involute_swath_angle(outer_radius())), Linear(1,involute_t));
+ makeContinuous(trailing_I, prev);
+ pb.append(SBasisCurve(trailing_I));
+ prev = trailing_I.at1();
+
+ if (base_radius() > root_radius()) {
+ Geom::Point leading_start = trailing_I.at1();
+ Geom::Point leading_end = (root_radius() * unit_vector(leading_start - _centre)) + _centre;
+ prev = leading_end;
+ pb.appendNew<LineSegment>(leading_end);
+ }
+
+ D2<SBasis> root = _arc(cursor, cursor+root_advance, root_radius());
+ makeContinuous(root, prev);
+ pb.append(SBasisCurve(root));
+ cursor += root_advance;
+ prev = root.at1();
+
+ if (base_radius() > root_radius()) {
+ Geom::Point trailing_start = root.at1();
+ Geom::Point trailing_end = (base_radius() * unit_vector(trailing_start - _centre)) + _centre;
+ pb.appendNew<LineSegment>(trailing_end);
+ prev = trailing_end;
+ }
+ }
+
+ return pb;
+}
+Gear Gear::spawn(int N, double a) {
+ Gear gear(N, _module, _pressure_angle);
+ double dist = gear.pitch_radius() + pitch_radius();
+ gear.centre(Geom::Point::polar(a, dist) + _centre);
+ double new_angle = 0.0;
+ if (gear.number_of_teeth() % 2 == 0)
+ new_angle -= gear.tooth_thickness_angle();
+ new_angle -= (_angle) * (pitch_radius() / gear.pitch_radius());
+ new_angle += (a) * (pitch_radius() / gear.pitch_radius());
+ gear.angle(new_angle + a);
+ return gear;
+}
+
+class GearToy: public Toy {
+ public:
+ PointSetHandle hand;
+ GearToy () {
+ for(unsigned i = 0; i < 4; i++)
+ hand.pts.emplace_back(uniform()*400, uniform()*400);
+ handles.push_back(&hand);
+ }
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_source_rgba (cr, 0., 0., 0, 0.8);
+ cairo_set_line_width (cr, 0.5);
+
+ //Geom::Point centre = Geom::Point(width/2,height/2);
+ /* draw cross hairs
+ double dominant_dim = std::max(width,height);
+ double minor_dim = std::min(width,height);
+ for(unsigned i = 1; i < 2; i++) {
+ cairo_move_to(cr, centre[0]-minor_dim/4, centre[1]);
+ cairo_line_to(cr, centre[0]+minor_dim/4, centre[1]);
+ cairo_move_to(cr, centre[0], centre[1]-minor_dim/4);
+ cairo_line_to(cr, centre[0], centre[1]+minor_dim/4);
+ }
+ cairo_stroke(cr);*/
+
+ double pressure_angle = (hand.pts[3][0] / 10) * M_PI / 180;
+ Gear gear(int(hand.pts[2][0] / 10),200.0,pressure_angle);
+ Geom::Point gear_centre = hand.pts[1];
+ gear.pitch_radius(Geom::distance(gear_centre, hand.pts[0]));
+ gear.angle(atan2(hand.pts[0] - gear_centre));
+ gear.centre(gear_centre);
+
+ // draw radii
+ cairo_new_sub_path(cr);
+ cairo_arc(cr, gear_centre[0], gear_centre[1], gear.base_radius(), 0, M_PI*2);
+ cairo_set_source_rgba (cr, 0., 0., 0.5, 1);
+ cairo_stroke(cr);
+
+ cairo_new_sub_path(cr);
+ cairo_arc(cr, gear_centre[0], gear_centre[1], gear.pitch_radius(), 0, M_PI*2);
+ cairo_set_source_rgba (cr, 0.5, 0., 0., 1);
+ cairo_stroke(cr);
+
+ cairo_new_sub_path(cr);
+ cairo_arc(cr, gear_centre[0], gear_centre[1], gear.outer_radius(), 0, M_PI*2);
+ cairo_set_source_rgba (cr, 0., 0.5, 0., 1);
+ cairo_stroke(cr);
+
+ cairo_new_sub_path(cr);
+ cairo_arc(cr, gear_centre[0], gear_centre[1], gear.root_radius(), 0, M_PI*2);
+ cairo_set_source_rgba (cr, 0., 0.5, 0., 1);
+ cairo_stroke(cr);
+
+ //draw gear
+ Geom::Path p = gear.path();
+ cairo_path(cr, p);
+ cairo_set_source_rgba (cr, 0., 0., 0., 0.5);
+ cairo_set_line_width (cr, 2.0);
+ cairo_stroke(cr);
+
+ Gear gear2 = gear.spawn(5, -2.0 * M_PI / 8.0);
+ Geom::Path p2 = gear2.path();
+ cairo_path(cr, p2);
+ cairo_set_source_rgba (cr, 0., 0., 0., 0.5);
+ cairo_set_line_width (cr, 2.0);
+ cairo_stroke(cr);
+
+ Gear gear3 = gear2.spawn(8, 0.0 * M_PI / 8.0);
+ Geom::Path p3 = gear3.path();
+ cairo_path(cr, p3);
+ cairo_set_source_rgba (cr, 0., 0., 0., 0.5);
+ cairo_set_line_width (cr, 2.0);
+ cairo_stroke(cr);
+
+ Gear gear4 = gear.spawn(6, 3.0 * M_PI / 4.0);
+ Geom::Path p4 = gear4.path();
+ cairo_path(cr, p4);
+ cairo_set_source_rgba (cr, 0., 0., 0., 0.5);
+ cairo_set_line_width (cr, 2.0);
+ cairo_stroke(cr);
+
+ *notify << "angle = " << gear.angle();
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new GearToy());
+
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/hatches.cpp b/src/3rdparty/2geom/src/toys/hatches.cpp
new file mode 100644
index 0000000..28fe440
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/hatches.cpp
@@ -0,0 +1,386 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-geometric.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <cstdlib>
+#include <vector>
+using std::vector;
+using namespace Geom;
+
+#define SIZE 4
+#define NB_SLIDER 8
+
+//------------------------------------------------
+// Some goodies to navigate through curve's levels.
+//------------------------------------------------
+struct LevelCrossing{
+ Point pt;
+ double t;
+ bool sign;
+ bool used;
+};
+struct LevelCrossingOrder {
+ bool operator()(LevelCrossing a, LevelCrossing b) {
+ return a.pt[Y] < b.pt[Y];
+ }
+};
+
+typedef std::vector<LevelCrossing> LevelCrossings;
+
+class LevelsCrossings: public std::vector<LevelCrossings>{
+public:
+ LevelsCrossings():std::vector<LevelCrossings>(){};
+ LevelsCrossings(std::vector<std::vector<double> > const &times,
+ Piecewise<D2<SBasis> > const &f,
+ Piecewise<SBasis> const &dx){
+ for (const auto & time : times){
+ LevelCrossings lcs;
+ for (double j : time){
+ LevelCrossing lc;
+ lc.pt = f.valueAt(j);
+ lc.t = j;
+ lc.sign = ( dx.valueAt(j)>0 );
+ lc.used = false;
+ lcs.push_back(lc);
+ }
+ std::sort(lcs.begin(), lcs.end(), LevelCrossingOrder());
+ //TODO: reverse all "in" flag if we had the wrong orientation!
+ push_back(lcs);
+ }
+ }
+ void flipInOut(){
+ for (unsigned i=0; i<size(); i++){
+ for (auto & j : (*this)){
+ j.sign = !j.sign;
+ }
+ }
+ }
+ void findFirstUnused(unsigned &level, unsigned &idx){
+ level = size();
+ idx = 0;
+ for (unsigned i=0; i<size(); i++){
+ for (unsigned j=0; j<(*this)[i].size(); j++){
+ if (!(*this)[i][j].used){
+ level = i;
+ idx = j;
+ return;
+ }
+ }
+ }
+ }
+ //set indexes to point to the next point in the "snake walk"
+ //follow_level's meaning:
+ // 0=yes upward
+ // 1=no, last move was upward,
+ // 2=yes downward
+ // 3=no, last move was downward.
+ void step(unsigned &level, unsigned &idx, int &direction){
+ std::cout << "Entering step: "<<level<<","<<idx<<", dir="<< direction<<"\n";
+
+ if ( direction % 2 == 0 ){
+ if (direction == 0) {
+ if ( idx >= (*this)[level].size()-1 || (*this)[level][idx+1].used ) {
+ level = size();
+ std::cout << "max end of level reached...\n";
+ return;
+ }
+ idx += 1;
+ }else{
+ if ( idx <= 0 || (*this)[level][idx-1].used ) {
+ level = size();
+ std::cout << "min end of level reached...\n";
+ return;
+ }
+ idx -= 1;
+ }
+ direction += 1;
+ std::cout << "exit with: "<<level<<","<<idx<<", dir="<< direction<<"\n";
+ return;
+ }
+ double t = (*this)[level][idx].t;
+ double sign = ((*this)[level][idx].sign ? 1 : -1);
+ double next_t = t;
+ level += 1;
+ direction = (direction + 1)%4;
+ if (level == size()){
+ std::cout << "max level reached\n";
+ return;
+ }
+ for (unsigned j=0; j<(*this)[level].size(); j++){
+ double tj = (*this)[level][j].t;
+ if ( sign*(tj-t) > 0 ){
+ if( next_t == t || sign*(tj-next_t)<0 ){
+ next_t = tj;
+ idx = j;
+ }
+ }
+ }
+ if ( next_t == t ){//not found.
+ level = size();
+ std::cout << "no next time found\n";
+ return;
+ }
+ //TODO: time is periodic!!!
+ //TODO: allow several components.
+ if ( (*this)[level][idx].used ) {
+ level = size();
+ std::cout << " reached a point already used\n";
+ return;
+ }
+ std::cout << "exit with: "<<level<<","<<idx<<"\n";
+ return;
+ }
+};
+
+
+//------------------------------------------------
+// Generate the levels with random, growth...
+//------------------------------------------------
+std::vector<double>generateLevels(Interval const &domain,
+ double const width,
+ double const growth,
+ double randomness){
+ std::vector<double> result;
+ std::srand(0);
+ double x = domain.min() + width/2;
+ double step = width;
+ while (x<domain.max()){
+ result.push_back(x);
+ double rdm = 1+ ( (rand() % 100) - 50) /100.*randomness;
+ x+= step*growth*rdm;
+ step*=growth;
+ }
+ return result;
+}
+
+
+//-------------------------------------------------------
+// Walk through the intersections to create linear hatches
+//-------------------------------------------------------
+std::vector<Point> linearSnake(Piecewise<D2<SBasis> > const &f, double dy,double growth, double rdmness){
+
+ std::vector<Point> result;
+
+ Piecewise<SBasis> x = make_cuts_independent(f)[X];
+ //Rque: derivative is computed twice in the 2 lines below!!
+ Piecewise<SBasis> dx = derivative(x);
+ OptInterval range = bounds_exact(x);
+ //TODO: test range non emptyness!!
+ std::vector<double> levels = generateLevels((*range), dy, growth, rdmness);
+ std::vector<std::vector<double> > times;
+ times = multi_roots(x,levels);
+
+//TODO: fix multi_roots!!!*****************************************
+//remove doubles :-(
+ std::vector<std::vector<double> > cleaned_times(levels.size(),std::vector<double>());
+ for (unsigned i=0; i<times.size(); i++){
+ if ( times[i].size()>0 ){
+ double last_t = times[i][0]-1;//ugly hack!!
+ for (unsigned j=0; j<times[i].size(); j++){
+ if (times[i][j]-last_t >0.000001){
+ last_t = times[i][j];
+ cleaned_times[i].push_back(last_t);
+ }
+ }
+ }
+ }
+ times = cleaned_times;
+ for (unsigned i=0; i<times.size(); i++){
+ std::cout << "roots on level "<<i<<": ";
+ for (double j : times){
+ std::cout << j <<" ";
+ }
+ std::cout <<"\n";
+ }
+//*******************************************************************
+ LevelsCrossings lscs(times,f,dx);
+ unsigned i,j;
+ lscs.findFirstUnused(i,j);
+ while ( i < lscs.size() ){
+ int dir = 0;
+ while ( i < lscs.size() ){
+ result.push_back(lscs[i][j].pt);
+ lscs[i][j].used = true;
+ lscs.step(i,j, dir);
+ }
+ //TODO: handle "non convex cases" where hatches have to be restarted at some point.
+ //This needs some care in linearSnake->smoothSnake.
+ //
+ lscs.findFirstUnused(i,j);
+ }
+ return result;
+}
+
+//-------------------------------------------------------
+// Smooth the linear hatches according to params...
+//-------------------------------------------------------
+Piecewise<D2<SBasis> > smoothSnake(std::vector<Point> const &linearSnake,
+ double scale_bf = 1, double scale_bb = 1,
+ double scale_tf = 1, double scale_tb = 1){
+
+ if (linearSnake.size()<2) return Piecewise<D2<SBasis> >();
+ bool is_top = true;
+ Point last_pt = linearSnake[0];
+ Point last_hdle = linearSnake[0];
+ Path result(last_pt);
+ unsigned i=1;
+ while( i+1<linearSnake.size() ){
+ Point pt0 = linearSnake[i];
+ Point pt1 = linearSnake[i+1];
+ Point new_pt = (pt0+pt1)/2;
+ double scale = (is_top ? scale_tf : scale_bf );
+ Point new_hdle = new_pt+(pt0-new_pt)*scale;
+
+ result.appendNew<CubicBezier>(last_hdle,new_hdle,new_pt);
+
+ last_pt = new_pt;
+ scale = (is_top ? scale_tb : scale_bb );
+ last_hdle = new_pt+(pt1-new_pt)*scale;
+ i+=2;
+ is_top = !is_top;
+ }
+ if ( i<linearSnake.size() )
+ result.appendNew<CubicBezier>(last_hdle,linearSnake[i],linearSnake[i]);
+ return result.toPwSb();
+}
+
+//-------------------------------------------------------
+// Bend a path...
+//-------------------------------------------------------
+
+Piecewise<D2<SBasis> > bend(Piecewise<D2<SBasis> > const &f, Piecewise<SBasis> bending){
+ D2<Piecewise<SBasis> > ff = make_cuts_independent(f);
+ ff[X] += compose(bending, ff[Y]);
+ return sectionize(ff);
+}
+
+//-------------------------------------------------------
+// The toy!
+//-------------------------------------------------------
+class HatchesToy: public Toy {
+
+ PointHandle adjuster[NB_SLIDER];
+
+public:
+ PointSetHandle b1_handle;
+ PointSetHandle b2_handle;
+ void draw(cairo_t *cr,
+ std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override {
+ for(unsigned i=0; i<NB_SLIDER; i++){
+ adjuster[i].pos[X] = 30+i*20;
+ if (adjuster[i].pos[Y]<100) adjuster[i].pos[Y] = 100;
+ if (adjuster[i].pos[Y]>400) adjuster[i].pos[Y] = 400;
+ cairo_move_to(cr, Point(30+i*20,100));
+ cairo_line_to(cr, Point(30+i*20,400));
+ cairo_set_line_width (cr, .5);
+ cairo_set_source_rgba (cr, 0., 0., 0., 1);
+ cairo_stroke(cr);
+ }
+ double hatch_width = (400-adjuster[0].pos[Y])/300.*50;
+ double scale_topfront = (250-adjuster[1].pos[Y])/150.*5;
+ double scale_topback = (250-adjuster[2].pos[Y])/150.*5;
+ double scale_botfront = (250-adjuster[3].pos[Y])/150.*5;
+ double scale_botback = (250-adjuster[4].pos[Y])/150.*5;
+ double growth = 1+(250-adjuster[5].pos[Y])/150.*.1;
+ double rdmness = 1+(400-adjuster[6].pos[Y])/300.*.9;
+ double bend_amount = (250-adjuster[7].pos[Y])/300.*100.;
+
+ b1_handle.pts.back() = b2_handle.pts.front();
+ b1_handle.pts.front() = b2_handle.pts.back();
+ D2<SBasis> B1 = b1_handle.asBezier();
+ D2<SBasis> B2 = b2_handle.asBezier();
+
+ {
+ cairo_save(cr);
+ cairo_set_line_width(cr, 0.3);
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ cairo_d2_sb(cr, B1);
+ cairo_d2_sb(cr, B2);
+ cairo_restore(cr);
+ }
+
+ Piecewise<D2<SBasis> >B;
+ B.concat(Piecewise<D2<SBasis> >(B1));
+ B.continuousConcat(Piecewise<D2<SBasis> >(B2));
+
+ Piecewise<SBasis> bending = Piecewise<SBasis>(shift(Linear(bend_amount),1));
+ //TODO: test optrect non empty!!
+ bending.setDomain((*bounds_exact(B))[Y]);
+ Piecewise<D2<SBasis> >bentB = bend(B, bending);
+
+ std::vector<Point> snakePoints;
+ snakePoints = linearSnake(bentB, hatch_width, growth, rdmness);
+ Piecewise<D2<SBasis> >smthSnake = smoothSnake(snakePoints,
+ scale_topfront,
+ scale_topback,
+ scale_botfront,
+ scale_botback);
+
+ smthSnake = bend(smthSnake, -bending);
+ cairo_pw_d2_sb(cr, smthSnake);
+ cairo_set_line_width (cr, 1.5);
+ cairo_set_source_rgba (cr, 0., 0., 0., 1);
+ cairo_stroke(cr);
+
+ if ( snakePoints.size() > 0 ){
+ Path snake(snakePoints.front());
+ for (unsigned i=1; i<snakePoints.size(); i++){
+ snake.appendNew<LineSegment>(snakePoints[i]);
+ }
+ //cairo_pw_d2_sb(cr, snake.toPwSb() );
+ }
+
+ //cairo_pw_d2_sb(cr, B);
+ cairo_set_line_width (cr, .5);
+ cairo_set_source_rgba (cr, 0.7, 0.2, 0., 1);
+ cairo_stroke(cr);
+
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+public:
+ HatchesToy(){
+ for(int i = 0; i < SIZE; i++) {
+ b1_handle.push_back(150+uniform()*300,150+uniform()*300);
+ b2_handle.push_back(150+uniform()*300,150+uniform()*300);
+ }
+ b1_handle.pts[0] = Geom::Point(400,300);
+ b1_handle.pts[1] = Geom::Point(400,400);
+ b1_handle.pts[2] = Geom::Point(100,400);
+ b1_handle.pts[3] = Geom::Point(100,300);
+
+ b2_handle.pts[0] = Geom::Point(100,300);
+ b2_handle.pts[1] = Geom::Point(100,200);
+ b2_handle.pts[2] = Geom::Point(400,200);
+ b2_handle.pts[3] = Geom::Point(400,300);
+ handles.push_back(&b1_handle);
+ handles.push_back(&b2_handle);
+
+ for(unsigned i = 0; i < NB_SLIDER; i++) {
+ adjuster[i].pos = Geom::Point(30+i*20,250);
+ handles.push_back(&(adjuster[i]));
+ }
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new HatchesToy);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+//vim:filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99:
diff --git a/src/3rdparty/2geom/src/toys/implicit-toy.cpp b/src/3rdparty/2geom/src/toys/implicit-toy.cpp
new file mode 100644
index 0000000..c90c082
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/implicit-toy.cpp
@@ -0,0 +1,510 @@
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <2geom/geom.h>
+#include <2geom/d2.h>
+#include <2geom/polynomial.h>
+#include <2geom/sbasis-poly.h>
+#include <2geom/transforms.h>
+
+#include <2geom/symbolic/implicit.h>
+
+#include <aa.h>
+
+#include <algorithm>
+#include <ctime>
+#include <functional>
+
+
+using namespace Geom;
+
+
+
+struct PtLexCmp{
+ bool operator()(const Point &a, const Point &b) {
+ return (a[0] < b[0]) || ((a[0] == b[0]) and (a[1] < b[1]));
+ }
+};
+
+//typedef AAF (*implicit_curve_t)(AAF, AAF);
+typedef std::function<AAF (AAF const&, AAF const&)> implicit_curve_t;
+
+// draw ax + by + c = 0
+void draw_line_in_rect(cairo_t*cr, Rect &r, Point n, double c)
+{
+ vector<Geom::Point> result;
+ Point resultp;
+ if(intersects == line_intersection(Point(1, 0), r.left(),
+ n, c,
+ resultp) && r[1].contains(resultp[1]))
+ result.push_back(resultp);
+ if(intersects == line_intersection(Point(1, 0), r.right(),
+ n, c,
+ resultp) && r[1].contains(resultp[1]))
+ result.push_back(resultp);
+ if(intersects == line_intersection(Point(0, 1), r.top(),
+ n, c,
+ resultp) && r[0].contains(resultp[0]))
+ result.push_back(resultp);
+ if(intersects == line_intersection(Point(0, 1), r.bottom(),
+ n, c,
+ resultp) && r[0].contains(resultp[0]))
+ result.push_back(resultp);
+ if(result.size() > 2) {
+ std::sort(result.begin(), result.end(), PtLexCmp());
+ vector<Geom::Point>::iterator new_end = std::unique(result.begin(), result.end());
+ result.resize(new_end-result.begin());
+ }
+ if(result.size() == 2)
+ {
+ cairo_move_to(cr, result[0]);
+ cairo_line_to(cr, result[1]);
+ cairo_stroke(cr);
+ }
+}
+
+OptRect tighten(Rect const&r, Point n, Interval lu)
+{
+ vector<Geom::Point> result;
+ Point resultp;
+ for(int i = 0; i < 4; i++)
+ {
+ Point cnr = r.corner(i);
+ double z = dot(cnr, n);
+ if ((z > lu[0]) && (z < lu[1]))
+ result.push_back(cnr);
+ }
+ for(int i = 0; i < 2; i++)
+ {
+ double c = lu[i];
+ if(intersects == line_intersection(Point(1, 0), r.left(),
+ n, c,
+ resultp) && r[1].contains(resultp[1]))
+ result.push_back(resultp);
+ if(intersects == line_intersection(Point(1, 0), r.right(),
+ n, c,
+ resultp) && r[1].contains(resultp[1]))
+ result.push_back(resultp);
+ if(intersects == line_intersection(Point(0, 1), r.top(),
+ n, c,
+ resultp) && r[0].contains(resultp[0]))
+ result.push_back(resultp);
+ if(intersects == line_intersection(Point(0, 1), r.bottom(),
+ n, c,
+ resultp) && r[0].contains(resultp[0]))
+ result.push_back(resultp);
+ }
+ if(result.size() < 2)
+ return OptRect;
+ Rect nr(result[0], result[1]);
+ for(size_t i = 2; i < result.size(); i++)
+ {
+ nr.expandTo(result[i]);
+ }
+ return intersect(nr, r);
+}
+
+static const unsigned int DEG = 5;
+double bvp[DEG+1][DEG+1]
+ = {{-1, 0.00945115, -4.11799e-05, 1.01365e-07, -1.35037e-10, 7.7868e-14},
+ {0.00837569, -6.24676e-05, 1.96093e-07, -3.09683e-10, 1.95681e-13, 0},
+ {-2.39448e-05, 1.3331e-07, -2.65787e-10, 1.96698e-13, 0, 0},
+ {2.76173e-08, -1.01069e-10, 9.88596e-14, 0, 0, 0},
+ {-1.43584e-11, 2.48433e-14, 0, 0, 0, 0}, {2.49723e-15, 0, 0, 0, 0, 0}};
+
+
+AAF trial_eval(AAF const& x, AAF const& y) {
+// AAF x = _x/100;
+// AAF y = _y/100;
+ //return x*x - 1;
+ //return y - pow(x,3);
+ //return y - pow_sample_based(x,2.5);
+ //return y - log_sample_based(x);
+ //return y - log(x);
+ //return y - exp_sample_based(x*log(x));
+ //return y - sqrt(sin(x));
+ //return sqrt(y)*x - sqrt(x) - y - 1;
+ //return y-1/x;
+ //return exp(x)-y;
+ //return sin(x)-y;
+ //return exp_sample_based(x)-y;
+ //return atan(x)-y;
+ //return atan_sample_based(x)-y;
+ //return atanh(x)-y;
+ //return x*y;
+ //return 4*x+3*y-1;
+ //return x*x + y*y - 1;
+ //return sin(x*y) + cos(pow(x, 3)) - atan(x);
+ //return pow((x*x + y*y), 2) - (x*x-y*y);
+ //return x*x-y;
+ //return (x*x*x-y*x)*sin(x) + (x-y*y)*cos(y)-0.5;
+// return -120.75 +(-64.4688 +(-16.6875 +(0.53125 -0.00390625*y)*y)*y)*y
+// + (-15.9375 + ( 1.5 +( 4.375 -0.0625*y)*y)*y
+// + (17 +( 9.5 -0.375*y)*y + (2 + -1*y -1*x)*x)*x)*x;
+
+// AAF v(0);
+// for (size_t i = DEG; i > 0; --i)
+// {
+// AAF vy(0);
+// for (size_t j = DEG - i; j > 0; --j)
+// {
+// vy += bvp[i][j];
+// vy *= y;
+// }
+// vy += bvp[i][0];
+// v += vy;
+// v *= x;
+// }
+// AAF vy(0);
+// for (size_t j = DEG; j > 0; --j)
+// {
+// vy += bvp[0][j];
+// vy *= y;
+// }
+// vy += bvp[0][0];
+// v += vy;
+// return v;
+
+ int i = DEG;
+ int j = DEG - i;
+ AAF vy(bvp[i][j]);
+ --j;
+ for (; j >= 0; --j)
+ {
+ vy *= y;
+ vy += bvp[DEG][j];
+ }
+ AAF v(vy);
+ --i;
+ for (; i >= 0; --i)
+ {
+ int j = DEG - i;
+ AAF vy(bvp[i][j]);
+ --j;
+ for (; j >= 0; --j)
+ {
+ vy *= y;
+ vy += bvp[i][j];
+ }
+ v *= x;
+ v += vy;
+ }
+ return v;
+
+// return
+// -1 +( 0.00945115 +( -4.11799e-05 +( 1.01365e-07 +( -1.35037e-10 + 7.7868e-14*y)*y)*y)*y)*y
+// + (0.00837569 +( -6.24676e-05 +( 1.96093e-07 +( -3.09683e-10 + 1.95681e-13*y)*y)*y)*y
+// + (-2.39448e-05 +( 1.3331e-07 +( -2.65787e-10 + 1.96698e-13*y)*y)*y
+// + (2.76173e-08 +( -1.01069e-10 + 9.88596e-14*y)*y
+// + (-1.43584e-11 + 2.48433e-14*y + 2.49723e-15*x)*x)*x)*x)*x;
+}
+
+
+
+double max_modulus (SL::MVPoly2 const& p)
+{
+ double a, m = 1;
+
+ for (size_t i = 0; i < p.get_poly().size(); ++i)
+ for (double j : p)
+ {
+ a = std::abs(j);
+ if (m < a) m = a;
+ }
+ return m;
+}
+
+void poly_to_mvpoly1(SL::MVPoly1& p, Geom::Poly const& q)
+{
+ for (size_t i = 0; i < q.size(); ++i)
+ {
+ p.coefficient(i, q[i]);
+ }
+ p.normalize();
+}
+
+void make_implicit_curve (SL::MVPoly2& ic, D2<SBasis> const& pc)
+{
+ Geom::Poly pc0 = sbasis_to_poly(pc[0]);
+ Geom::Poly pc1 = sbasis_to_poly(pc[1]);
+
+// std::cerr << "parametrization: \n";
+// std::cerr << "pc0 = " << pc0 << std::endl;
+// std::cerr << "pc1 = " << pc1 << "\n\n";
+
+ SL::MVPoly1 f, g;
+ poly_to_mvpoly1(f, pc0);
+ poly_to_mvpoly1(g, pc1);
+
+// std::cerr << "parametrization: \n";
+// std::cerr << "f = " << f << std::endl;
+// std::cerr << "g = " << g << "\n\n";
+
+ Geom::SL::basis_type b;
+ microbasis(b, f, g);
+
+ Geom::SL::MVPoly3 p, q;
+ basis_to_poly(p, b[0]);
+ basis_to_poly(q, b[1]);
+
+// std::cerr << "generators as polynomial in R[t,x,y] : \n";
+// std::cerr << "p = " << p << std::endl;
+// std::cerr << "q = " << q << "\n\n";
+
+
+ Geom::SL::Matrix<Geom::SL::MVPoly2> B = make_bezout_matrix(p, q);
+ ic = determinant_minor(B);
+ ic.normalize();
+ double m = max_modulus(ic);
+ ic /= m;
+
+// std::cerr << "Bezout matrix: (entries are bivariate polynomials) \n";
+// std::cerr << "B = " << B << "\n\n";
+// std::cerr << "determinant: \n";
+// std::cerr << "r(x, y) = " << ic << "\n\n";
+
+}
+
+//namespace Geom{ namespace SL{
+//
+//template<>
+//struct zero<AAF, false>
+//{
+// AAF operator() () const
+// {
+// return AAF(0);
+// }
+//};
+//
+//} }
+
+class ImplicitToy : public Toy
+{
+ bool contains_zero (implicit_curve_t const& eval,
+ Rect r, double w=1e-5)
+ {
+ ++iters;
+ AAF x(interval(r.left(), r.right()));
+ AAF y(interval(r.top(), r.bottom()));
+ AAF f = eval(x, y);
+ double a = f.index_coeff(x.get_index(0)) / x.index_coeff(x.get_index(0));
+ double b = f.index_coeff(y.get_index(0)) / y.index_coeff(y.get_index(0));
+ AAF d = a*x + b*y - f;
+ interval ivl(d);
+ Point n(a,b);
+ OptRect out = tighten(r, n, Interval(ivl.min(), ivl.max()));
+ if (f.straddles_zero())
+ {
+ if ((r.width() > w) || (r.height() > w))
+ {
+ Point c = r.midpoint();
+ Rect oldr = r;
+ if (out) r = *out;
+ // Three possibilities:
+ // 1) the trim operation buys us enough that we should just iterate
+ if (1 && (r.area() < oldr.area()*0.25))
+ {
+ return contains_zero(eval, r, w);
+ }
+ // 2) one dimension is significantly smaller
+ else if (1 && (r[1].extent() < oldr[1].extent()*0.5))
+ {
+ return contains_zero (eval,
+ Rect(Interval(r.left(), r.right()),
+ Interval(r.top(), c[1])), w)
+ || contains_zero (eval,
+ Rect(Interval(r.left(), r.right()),
+ Interval(c[1], r.bottom())), w);
+ }
+ else if (1 && (r[0].extent() < oldr[0].extent()*0.5))
+ {
+ return contains_zero (eval,
+ Rect(Interval(r.left(), c[0]),
+ Interval(r.top(), r.bottom())), w)
+ || contains_zero (eval,
+ Rect(Interval(c[0], r.right()),
+ Interval(r.top(), r.bottom())), w);
+ }
+ // 3) to ensure progress we must do a four way split
+ else
+ {
+ return contains_zero (eval,
+ Rect(Interval(r.left(), c[0]),
+ Interval(r.top(), c[1])), w)
+ || contains_zero (eval,
+ Rect(Interval(c[0], r.right()),
+ Interval(r.top(), c[1])), w)
+ || contains_zero (eval,
+ Rect(Interval(r.left(), c[0]),
+ Interval(c[1], r.bottom())), w)
+ || contains_zero (eval,
+ Rect(Interval(c[0], r.right()),
+ Interval(c[1], r.bottom())), w);
+ }
+ }
+ //std::cout << w << " < " << r.width() << " , " << r.height() << std::endl;
+ //std::cout << r.min() << " - " << r.max() << std::endl;
+ return true;
+ }
+ return false;
+ } // end recursive_implicit
+
+
+ void draw_implicit_curve (cairo_t*cr, implicit_curve_t const& eval,
+ Point const& origin, Rect r, double w)
+ {
+ ++iters;
+ AAF x(interval(r.left(), r.right()));
+ AAF y(interval(r.top(), r.bottom()));
+ //assert(x.rad() > 0);
+ //assert(y.rad() > 0);
+// time(&t0);
+ AAF f = eval(x-origin[X], y-origin[Y]);
+// time(&t1);
+// d1 += std::difftime(t1, t0);
+ // pivot
+// time(&t2);
+ double a = f.index_coeff(x.get_index(0)) / x.index_coeff(x.get_index(0));
+ double b = f.index_coeff(y.get_index(0)) / y.index_coeff(y.get_index(0));
+ AAF d = a*x + b*y - f;
+ interval ivl(d);
+ Point n(a,b);
+ OptRect out = tighten(r, n, Interval(ivl.min(), ivl.max()));
+ if (ivl.extent() < 0.5*L2(n))
+ {
+ draw_line_in_rect(cr, r, n, ivl.middle());
+ return;
+ }
+// time(&t3);
+// d2 += std::difftime(t3, t2);
+ if ((r.width() > w) || (r.height() > w))
+ {
+ if (f.straddles_zero())
+ {
+ Point c = r.midpoint();
+ Rect oldr = r;
+ if (out) r = *out;
+ // Three possibilities:
+ // 1) the trim operation buys us enough that we should just iterate
+ if (1 && (r.area() < oldr.area()*0.25))
+ {
+ draw_implicit_curve(cr, eval, origin, r, w);
+ }
+ // 2) one dimension is significantly smaller
+ else if (1 && (r[1].extent() < oldr[1].extent()*0.5))
+ {
+ draw_implicit_curve (cr, eval, origin,
+ Rect(Interval(r.left(), r.right()),
+ Interval(r.top(), c[1])), w);
+ draw_implicit_curve (cr, eval, origin,
+ Rect(Interval(r.left(), r.right()),
+ Interval(c[1], r.bottom())), w);
+ }
+ else if (1 && (r[0].extent() < oldr[0].extent()*0.5))
+ {
+ draw_implicit_curve (cr, eval, origin,
+ Rect(Interval(r.left(), c[0]),
+ Interval(r.top(), r.bottom())), w);
+ draw_implicit_curve (cr, eval, origin,
+ Rect(Interval(c[0], r.right()),
+ Interval(r.top(), r.bottom())), w);
+ }
+ // 3) to ensure progress we must do a four way split
+ else
+ {
+ draw_implicit_curve (cr, eval, origin,
+ Rect(Interval(r.left(), c[0]),
+ Interval(r.top(), c[1])), w);
+ draw_implicit_curve (cr, eval, origin,
+ Rect(Interval(c[0], r.right()),
+ Interval(r.top(), c[1])), w);
+ draw_implicit_curve (cr, eval, origin,
+ Rect(Interval(r.left(), c[0]),
+ Interval(c[1], r.bottom())), w);
+ draw_implicit_curve (cr, eval, origin,
+ Rect(Interval(c[0], r.right()),
+ Interval(c[1], r.bottom())), w);
+ }
+ }
+ } else {
+ if(contains_zero(eval, r*Geom::Translate(-origin))) {
+ cairo_save(cr);
+ cairo_set_source_rgb(cr, 0,0.5,0);
+ cairo_rectangle(cr, r);
+ cairo_fill(cr);
+ cairo_restore(cr);
+ }
+ }
+ } // end recursive_implicit
+
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ iters = 0;
+ d1 = d2 = 0;
+ cairo_set_line_width (cr, 0.3);
+ D2<SBasis> A = pshA.asBezier();
+ cairo_d2_sb(cr, A);
+ cairo_stroke(cr);
+
+ SL::MVPoly2 ic;
+ make_implicit_curve(ic, A);
+
+ cairo_set_source_rgba (cr, 0., 0., 0, 1);
+ cairo_set_line_width (cr, 0.8);
+ draw_implicit_curve (cr, ic, orig_handle.pos,
+ Rect(Interval(0,width), Interval(0, height)), 1);
+ cairo_stroke(cr);
+
+// std::cerr << "D1 = " << d1 << std::endl;
+// std::cerr << "D2 = " << d2 << std::endl;
+
+ *notify << "iter: " << iters;
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+
+public:
+ ImplicitToy(unsigned int _A_bez_ord)
+ : A_bez_ord(_A_bez_ord)
+ {
+ handles.push_back(&orig_handle);
+ orig_handle.pos = Point(0,0); //Point(300,300);
+
+ handles.push_back(&pshA);
+ for (unsigned int i = 0; i < A_bez_ord; ++i)
+ pshA.push_back(Geom::Point(uniform()*400, uniform()*400));
+ }
+
+private:
+ unsigned int A_bez_ord;
+ PointHandle orig_handle;
+ PointSetHandle pshA;
+ time_t t0, t1, t2, t3;
+ double d1, d2;
+ unsigned int iters;
+};
+
+
+int main(int argc, char **argv)
+{
+ unsigned int A_bez_ord=5;
+ if(argc > 1)
+ sscanf(argv[1], "%d", &A_bez_ord);
+
+
+ init( argc, argv, new ImplicitToy(A_bez_ord));
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/ineaa.cpp b/src/3rdparty/2geom/src/toys/ineaa.cpp
new file mode 100644
index 0000000..75b9d41
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/ineaa.cpp
@@ -0,0 +1,655 @@
+#include <2geom/convex-hull.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <2geom/d2.h>
+#include <2geom/geom.h>
+#include <2geom/numeric/linear_system.h>
+
+#include <aa.h>
+#include <complex>
+#include <algorithm>
+#include <optional>
+
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+typedef std::complex<AAF> CAAF;
+
+struct PtLexCmp{
+ bool operator()(const Point &a, const Point &b) {
+ return (a[0] < b[0]) || ((a[0] == b[0]) and (a[1] < b[1]));
+ }
+};
+
+// draw ax + by + c = 0
+void draw_line_in_rect(cairo_t*cr, Rect &r, Point n, double c) {
+ std::optional<Geom::LineSegment> ls =
+ rect_line_intersect(r, Line::fromNormalDistance(n, c));
+
+ if(ls) {
+ cairo_move_to(cr, (*ls)[0]);
+ cairo_line_to(cr, (*ls)[1]);
+ cairo_stroke(cr);
+
+ }
+}
+
+void fill_line_in_rect(cairo_t*cr, Rect &r, Point n, double c) {
+ ConvexHull ch;
+
+ std::optional<Geom::LineSegment> ls =
+ rect_line_intersect(r, Line::fromNormalDistance(n, c));
+
+ if(ls) {
+ ch.boundary.push_back((*ls)[0]);
+ ch.boundary.push_back((*ls)[1]);
+ }
+ for(int i = 0; i < 4; i++) {
+ Point p = r.corner(i);
+ if(dot(n,p) < c) {
+ ch.boundary.push_back(p);
+ }
+ }
+ ch.graham();
+ cairo_convex_hull(cr, ch.boundary);
+}
+
+OptRect tighten(Rect &r, Point n, Interval lu) {
+ vector<Geom::Point> result;
+ Point resultp;
+ for(int i = 0; i < 4; i++) {
+ Point cnr = r.corner(i);
+ double z = dot(cnr, n);
+ if((z > lu[0]) and (z < lu[1]))
+ result.push_back(cnr);
+ }
+ for(int i = 0; i < 2; i++) {
+ double c = lu[i];
+
+ std::optional<Geom::LineSegment> ls =
+ rect_line_intersect(r, Line::fromNormalDistance(n, c));
+
+ if(ls) {
+ result.push_back((*ls)[0]);
+ result.push_back((*ls)[1]);
+ }
+ }
+ if(result.size() < 2)
+ return OptRect();
+ Rect nr(result[0], result[1]);
+ for(size_t i = 2; i < result.size(); i++) {
+ nr.expandTo(result[i]);
+ }
+ return intersect(nr, r);
+}
+
+AAF ls_sample_based(AAF x, vector<Point> pts) {
+ NL::Matrix m(pts.size(), 2);
+ NL::Vector v(pts.size());
+ NL::LinearSystem ls(m, v);
+
+ m.set_all(0);
+ v.set_all(0);
+ for (unsigned int k = 0; k < pts.size(); ++k)
+ {
+ m(k,0) += pts[k][0];
+ m(k,1) += 1;
+ //std::cout << pts[k] << " ";
+
+ v[k] += pts[k][1];
+ //v[1] += pts[k][1];
+ //v[2] += y2;
+ }
+
+ ls.SV_solve();
+
+ double A = ls.solution()[0];
+ double B = ls.solution()[1];
+ // Ax + B = y
+ Interval bnd(0,0);
+ for (unsigned int k = 0; k < pts.size(); ++k)
+ {
+ bnd.extendTo(A*pts[k][0]+B - pts[k][1]);
+ }
+ //std::cout << A << "," << B << std::endl;
+ return AAF(x, A, B, bnd.extent(),
+ x.special);
+}
+
+AAF md_sample_based(AAF x, vector<Point> pts) {
+ Geom::ConvexHull ch1(pts);
+ Point a, b, c;
+ ch1.narrowest_diameter(a, b, c);
+ Point db = c-b;
+ double A = db[1]/db[0];
+ Point aa = db*(dot(db, a-b)/dot(db,db))+b;
+ Point mid = (a+aa)/2;
+ double B = mid[1] - A*mid[0];
+ double dB = (a[1] - A*a[0]) - B;
+ // Ax + B = y
+ //std::cout << A << "," << B << std::endl;
+ return AAF(x, A, B, dB,
+ x.special);
+}
+
+AAF atan_sample_based(AAF x) {
+ interval ab(x);
+ const double a = ab.min(); // [a,b] is our interval
+ const double b = ab.max();
+
+ const double ea = atan(a);
+ const double eb = atan(b);
+ vector<Point> pts;
+ pts.push_back(Point(a,ea));
+ pts.push_back(Point(b,eb));
+ const double alpha = (eb-ea)/(b-a);
+ double xs = sqrt(1/alpha-1);
+ if((a < xs) and (xs < b))
+ pts.push_back(Point(xs,atan(xs)));
+ xs = -xs;
+ if((a < xs) and (xs < b))
+ pts.push_back(Point(xs,atan(xs)));
+
+ return md_sample_based(x, pts);
+}
+
+AAF log_sample_based(AAF x) {
+ interval ab(x);
+ const double a = ab.min(); // [a,b] is our interval
+ const double b = ab.max();
+ AAF_TYPE type;
+ if(a > 0)
+ type = AAF_TYPE_AFFINE;
+ else if(b < 0) { // no point in continuing
+ type = AAF_TYPE_NAN;
+ return AAF(type);
+ }
+ else if(a <= 0) { // undefined, can we do better?
+ type = (AAF_TYPE)(AAF_TYPE_AFFINE | AAF_TYPE_NAN);
+ return AAF(type);
+ // perhaps we should make a = 0+eps and try to continue?
+ }
+
+ const double ea = log(a);
+ const double eb = log(b);
+ vector<Point> pts;
+ pts.push_back(Point(a,ea));
+ pts.push_back(Point(b,eb));
+ const double alpha = (eb-ea)/(b-a);
+ // dlog(xs) = alpha
+ double xs = 1/(alpha);
+ if((a < xs) and (xs < b))
+ pts.push_back(Point(xs,log(xs)));
+
+ return md_sample_based(x, pts);
+}
+
+AAF exp_sample_based(AAF x) {
+ interval ab(x);
+ const double a = ab.min(); // [a,b] is our interval
+ const double b = ab.max();
+
+ const double ea = exp(a);
+ const double eb = exp(b);
+ vector<Point> pts;
+ pts.push_back(Point(a,ea));
+ pts.push_back(Point(b,eb));
+ const double alpha = (eb-ea)/(b-a);
+ // dexp(xs) = alpha
+ double xs = log(alpha);
+ if((a < xs) and (xs < b))
+ pts.push_back(Point(xs,exp(xs)));
+
+ return md_sample_based(x, pts);
+}
+
+double
+desy_lambert_W(double x) {
+ if (x <= 500.0) {
+ double lx1 = log(x + 1.0);
+ return 0.665 * (1 + 0.0195 * lx1) * lx1 + 0.04;
+ }
+ return log(x - 4.0) - (1.0 - 1.0/log(x)) * log(log(x));
+}
+
+double lambertW(double x, double prec = 1E-12, int maxiters = 100) {
+ double w = desy_lambert_W(x);
+ const double e = exp(1);
+ for(int i = 0; i < maxiters; i++) {
+ double we = w * pow(e,w);
+ double w1e = (w + 1) * pow(e,w);
+ if( prec > abs((x - we) / w1e))
+ return w;
+ w -= (we - x) / (w1e - (w+2) * (we-x) / (2*w+2));
+ }
+ //raise ValueError("W doesn't converge fast enough for abs(z) = %f" % abs(x))
+ return 0./0.;
+}
+
+#include <gsl/gsl_errno.h>
+#include <gsl/gsl_math.h>
+#include <gsl/gsl_min.h>
+
+typedef struct{
+ double a, b;
+} param_W;
+
+double fn1 (double x, void * params)
+{
+ param_W *pw = (param_W*)params;
+ return (pw->a*x+pw->b) - lambertW(x);
+}
+
+double optimise(void * params, double a, double b) {
+ int status;
+ //param_W *pw = (param_W*)params;
+ int iter = 0, max_iter = 100;
+ double m = (a+b)/2;
+ gsl_function F;
+
+ F.function = &fn1;
+ F.params = params;
+
+ const gsl_min_fminimizer_type *T = gsl_min_fminimizer_brent;
+ gsl_min_fminimizer *s = gsl_min_fminimizer_alloc (T);
+ if(a+1e-10 >= b) return m;
+#if 0
+ cout << a << " " << b << " " << m << endl;
+ cout << "fn:" << fn1(a, params) << " " << fn1(b, params) << " " << fn1(m, params) << endl;
+ cout << "fn:" << (pw->a*a+pw->b) << " " << (pw->a*b+pw->b) << " " << (pw->a*m+pw->b) << endl;
+#endif
+ gsl_min_fminimizer_set (s, &F, m, a, b);
+ do
+ {
+ iter++;
+ status = gsl_min_fminimizer_iterate (s);
+
+ m = gsl_min_fminimizer_x_minimum (s);
+ a = gsl_min_fminimizer_x_lower (s);
+ b = gsl_min_fminimizer_x_upper (s);
+
+ status
+ = gsl_min_test_interval (a, b, 0.001, 0.0);
+
+ }
+ while (status == GSL_CONTINUE && iter < max_iter);
+
+ gsl_min_fminimizer_free (s);
+
+ return m;
+}
+
+
+AAF W_sample_based(AAF x) {
+ interval ab(x);
+ const double a = ab.min(); // [a,b] is our interval
+ const double b = ab.max();
+ const double e = exp(1);
+ AAF_TYPE type;
+ if(a >= -1./e)
+ type = AAF_TYPE_AFFINE;
+ else if(b < 0) { // no point in continuing
+ type = AAF_TYPE_NAN;
+ return AAF(type);
+ }
+ else if(a <= 0) { // undefined, can we do better?
+ type = (AAF_TYPE)(AAF_TYPE_AFFINE | AAF_TYPE_NAN);
+ return AAF(type);
+ // perhaps we should make a = 0+eps and try to continue?
+ }
+ const double ea = lambertW(a);
+ const double eb = lambertW(b);
+ vector<Point> pts;
+ pts.push_back(Point(a,ea));
+ pts.push_back(Point(b,eb));
+ const double alpha = (eb-ea)/(b-a);
+ // d(W(xs)) = alpha
+ // W =
+ param_W pw;
+ pw.a = alpha;
+ pw.b = ea - alpha*a;
+ if(a < b) {
+ double xs = optimise(&pw, a, b);
+ if((a < xs) and (xs < b))
+ pts.push_back(Point(xs,lambertW(xs)));
+ }
+ return md_sample_based(x, pts);
+}
+
+AAF pow_sample_based(AAF x, double p) {
+ interval ab(x);
+ const double a = ab.min(); // [a,b] is our interval
+ const double b = ab.max();
+ AAF_TYPE type;
+ if(floor(p) != p) {
+ if(a >= 0)
+ type = AAF_TYPE_AFFINE;
+ else if(b < 0) { // no point in continuing
+ type = AAF_TYPE_NAN;
+ return AAF(type);
+ }
+ else if(a <= 0) { // undefined, can we do better?
+ type = (AAF_TYPE)(AAF_TYPE_AFFINE | AAF_TYPE_NAN);
+ return AAF(type);
+ // perhaps we should make a = 0+eps and try to continue?
+ }
+ }
+ const double ea = pow(a, p);
+ const double eb = pow(b, p);
+ vector<Point> pts;
+ pts.push_back(Point(a,ea));
+ pts.push_back(Point(b,eb));
+ const double alpha = (eb-ea)/(b-a);
+ // d(xs^p) = alpha
+ // p xs^(p-1) = alpha
+ // xs = (alpha/p)^(1-p)
+ double xs = pow(alpha/p, 1./(p-1));
+ if((a < xs) and (xs < b))
+ pts.push_back(Point(xs,pow(xs, p)));
+ xs = -xs;
+ if((a < xs) and (xs < b))
+ pts.push_back(Point(xs,pow(xs, p)));
+
+ return md_sample_based(x, pts);
+}
+
+Point origin;
+AAF trial_eval(AAF x, AAF y) {
+ x = x-origin[0];
+ y = y-origin[1];
+ x = x/200;
+ y = y/200;
+ AAF x2 = pow_sample_based(x,2);
+ AAF y2 = pow_sample_based(y,2);
+ //return x2 + y2 - 1;
+ //return y - pow(x,3);
+ return y + W_sample_based(x);
+ //return y - pow_sample_based(x,2.5);
+ //return y - log_sample_based(x);
+ //return y - log(x);
+ //return -y + -exp_sample_based(x*log(x));
+ return -x + -exp_sample_based(y*log(y));
+ //return y - sqrt(sin(x));
+ //return sqrt(y)*x - sqrt(x) - y - 1;
+ //return y-1/x;
+ //return exp(x)-y;
+ //return sin(x)-y;
+ //return exp_sample_based(x)-y;
+ //return atan(x)-y;
+ //return atan_sample_based(x)-y;
+ //return atanh(x)-y;
+ //return x*y;
+ //return 4*x+3*y-1;
+ //return x*x + y*y - 1;
+ return pow_sample_based((x2 + y2), 2) - (x2-y2);
+ //return x*x-y;
+ //return (x*x*x-y*x)*sin(x) + (x-y*y)*cos(y)-0.5;
+}
+
+AAF xaxis(AAF x, AAF y) {
+ (void)x;
+ y = y-origin[1];
+ y = y/200;
+ return y;
+}
+
+AAF yaxis(AAF x, AAF y) {
+ (void)y;
+ x = x-origin[0];
+ x = x/200;
+ return x;
+}
+
+class ConvexTest: public Toy {
+public:
+ PointSetHandle test_window;
+ PointSetHandle samples;
+ PointHandle orig_handle;
+ ConvexTest () {
+ toggles.push_back(Toggle("Show trials", false));
+ handles.push_back(&test_window);
+ handles.push_back(&samples);
+ handles.push_back(&orig_handle);
+ orig_handle.pos = Point(00,300);
+ test_window.push_back(Point(100,100));
+ test_window.push_back(Point(200,200));
+ for(int i = 0; i < 0; i++) {
+ samples.push_back(Point(i*100, i*100+25));
+ }
+ }
+ int iters;
+ int splits[4];
+ bool show_splits;
+ std::vector<Toggle> toggles;
+ AAF (*eval)(AAF, AAF);
+ void recursive_implicit(Rect r, cairo_t*cr, double w) {
+ if(show_splits) {
+ cairo_save(cr);
+ cairo_set_line_width(cr, 0.3);
+ /*if(f.is_partial())
+ cairo_set_source_rgba(cr, 1, 0, 1, 0.25);
+ else*/
+ cairo_set_source_rgba(cr, 0, 1, 0, 0.25);
+ cairo_rectangle(cr, r);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ }
+ iters++;
+ AAF x(interval(r.left(), r.right()));
+ AAF y(interval(r.top(), r.bottom()));
+ //assert(x.rad() > 0);
+ //assert(y.rad() > 0);
+ AAF f = (*eval)(x, y);
+ double a = f.index_coeff(x.get_index(0))/x.index_coeff(x.get_index(0));
+ double b = f.index_coeff(y.get_index(0))/y.index_coeff(y.get_index(0));
+ AAF d = a*x + b*y - f;
+ interval ivl(d);
+ Point n(a,b);
+ OptRect out = tighten(r, n, Interval(ivl.min(), ivl.max()));
+ if(ivl.extent() < 0.5*L2(n)) {
+
+ cairo_save(cr);
+ cairo_set_source_rgba(cr, 0,1,0,0.125);
+ fill_line_in_rect(cr, r, n, ivl.middle());
+ cairo_fill(cr);
+ cairo_restore(cr);
+ draw_line_in_rect(cr, r, n, ivl.middle());
+ return;
+ }
+ if(f.strictly_neg()) {
+ cairo_save(cr);
+ cairo_set_source_rgba(cr, 0,1,0,0.125);
+ cairo_rectangle(cr, r);
+ cairo_fill(cr);
+ cairo_restore(cr);
+ return;
+ }
+ if(!f.is_partial() and f.is_indeterminate()) {
+ cairo_save(cr);
+ cairo_set_line_width(cr, 0.3);
+ if(f.is_infinite()) {
+ cairo_set_source_rgb(cr, 1, 0.5, 0.5);
+ } else if(f.is_nan()) {
+ cairo_set_source_rgb(cr, 1, 1, 0);
+ } else {
+ cairo_set_source_rgb(cr, 1, 0, 0);
+ }
+ cairo_rectangle(cr, r);
+ if(show_splits) {
+ cairo_stroke(cr);
+ } else {
+ cairo_fill(cr);
+ }
+ cairo_restore(cr);
+ return;
+ }
+
+ if((r.width() > w) or (r.height()>w)) {
+ if(f.strictly_neg() or f.straddles_zero()) {
+ // Three possibilities:
+ // 1) the trim operation buys us enough that we should just iterate
+ Point c = r.midpoint();
+ Rect oldr = r;
+ if(1 && out) {
+ r = *out;
+ for(int i = 0; i < 4; i++) {
+ Point p = oldr.corner(i);
+ if(dot(n,p) < ivl.middle()) {
+ r.expandTo(p);
+ }
+ }
+ }
+ if(1 && out && (r.area() < oldr.area()*0.25)) {
+ splits[0] ++;
+ recursive_implicit(r, cr, w);
+ // 2) one dimension is significantly smaller
+ } else if(1 && (r[1].extent() < oldr[1].extent()*0.5)) {
+ splits[1]++;
+ recursive_implicit(Rect(Interval(r.left(), r.right()),
+ Interval(r.top(), c[1])), cr,w);
+ recursive_implicit(Rect(Interval(r.left(), r.right()),
+ Interval(c[1], r.bottom())), cr,w);
+ } else if(1 && (r[0].extent() < oldr[0].extent()*0.5)) {
+ splits[2]++;
+ recursive_implicit(Rect(Interval(r.left(), c[0]),
+ Interval(r.top(), r.bottom())), cr,w);
+ recursive_implicit(Rect(Interval(c[0], r.right()),
+ Interval(r.top(), r.bottom())), cr,w);
+ // 3) to ensure progress we must do a four way split
+ } else {
+ splits[3]++;
+ recursive_implicit(Rect(Interval(r.left(), c[0]),
+ Interval(r.top(), c[1])), cr,w);
+ recursive_implicit(Rect(Interval(c[0], r.right()),
+ Interval(r.top(), c[1])), cr,w);
+ recursive_implicit(Rect(Interval(r.left(), c[0]),
+ Interval(c[1], r.bottom())), cr,w);
+ recursive_implicit(Rect(Interval(c[0], r.right()),
+ Interval(c[1], r.bottom())), cr,w);
+ }
+ }
+ } else {
+ }
+ }
+
+ void key_hit(GdkEventKey *e) override {
+ if(e->keyval == 'w') toggles[0].toggle(); else
+ if(e->keyval == 'a') toggles[1].toggle(); else
+ if(e->keyval == 'q') toggles[2].toggle(); else
+ if(e->keyval == 's') toggles[3].toggle();
+ redraw();
+ }
+ void mouse_pressed(GdkEventButton* e) override {
+ toggle_events(toggles, e);
+ Toy::mouse_pressed(e);
+ }
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_source_rgba (cr, 0., 0., 0, 1);
+ cairo_set_line_width (cr, 1);
+ origin = orig_handle.pos;
+ if(1) {
+ cairo_save(cr);
+ cairo_set_line_width(cr, 0.3);
+ cairo_set_source_rgb(cr, 0.5, 0.5, 1);
+ eval = xaxis;
+ //recursive_implicit(Rect(Interval(0,width), Interval(0, height)), cr, 3);
+ eval = yaxis;
+ //recursive_implicit(Rect(Interval(0,width), Interval(0, height)), cr, 3);
+ cairo_restore(cr);
+ iters = 0;
+ for(int & split : splits)
+ split = 0;
+ show_splits = toggles[0].on;
+ eval = trial_eval;
+ recursive_implicit(Rect(Interval(0,width), Interval(0, height)), cr, 3);
+ for(int split : splits)
+ *notify << split << " + ";
+ *notify << " = " << iters;
+ }
+ if(1) {
+ Rect r(test_window.pts[0], test_window.pts[1]);
+ AAF x(interval(r.left(), r.right()));
+ AAF y(interval(r.top(), r.bottom()));
+ //AAF f = md_sample_based(x, samples.pts)-y;
+ if(0) {
+ x = x-500;
+ y = y-300;
+ x = x/200;
+ y = y/200;
+ AAF f = atan_sample_based(x)-y;
+ cout << f << endl;
+ }
+ AAF f = (*eval)(x, y);
+ double a = f.index_coeff(x.get_index(0))/x.index_coeff(x.get_index(0));
+ double b = f.index_coeff(y.get_index(0))/y.index_coeff(y.get_index(0));
+ AAF d = a*x + b*y - f;
+ //cout << d << endl;
+ interval ivl(d);
+ Point n(a,b);
+ OptRect out = tighten(r, n, Interval(ivl.min(), ivl.max()));
+ if(out)
+ cairo_rectangle(cr, *out);
+ cairo_rectangle(cr, r);
+ draw_line_in_rect(cr, r, n, ivl.min());
+ if(f.strictly_neg()) {
+ cairo_save(cr);
+ cairo_set_source_rgba(cr, .5, 0.5, 0, 0.125);
+ cairo_fill(cr);
+ cairo_restore(cr);
+ } else
+ cairo_stroke(cr);
+ cairo_save(cr);
+ cairo_set_line_width(cr, 0.3);
+ cairo_set_source_rgb(cr, 0.5, 0.5, 0);
+ draw_line_in_rect(cr, r, n, ivl.middle());
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ //fill_line_in_rect(cr, r, n, c);
+ draw_line_in_rect(cr, r, n, ivl.max());
+ cairo_stroke(cr);
+ }
+ if(0) {
+ Geom::ConvexHull gm(samples.pts);
+ cairo_convex_hull(cr, gm);
+ cairo_stroke(cr);
+ Point a, b, c;
+ gm.narrowest_diameter(a, b, c);
+ cairo_save(cr);
+ cairo_set_line_width(cr, 2);
+ cairo_set_source_rgba(cr, 1, 0, 0, 0.5);
+ cairo_move_to(cr, b);
+ cairo_line_to(cr, c);
+ cairo_move_to(cr, a);
+ cairo_line_to(cr, (c-b)*dot(a-b, c-b)/dot(c-b,c-b)+b);
+ cairo_stroke(cr);
+ //std::cout << a << ", " << b << ", " << c << ": " << dia << "\n";
+ cairo_restore(cr);
+ }
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ Point d(25,25);
+ toggles[0].bounds = Rect(Point(10, height-80)+d,
+ Point(10+120, height-80+d[1])+d);
+
+ draw_toggles(cr, toggles);
+ }
+
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new ConvexTest());
+
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/inner-product-clip.cpp b/src/3rdparty/2geom/src/toys/inner-product-clip.cpp
new file mode 100644
index 0000000..9ada56b
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/inner-product-clip.cpp
@@ -0,0 +1,174 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/transforms.h>
+#include <2geom/sbasis-math.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <2geom/path.h>
+#include <2geom/svg-path-parser.h>
+
+#include <gsl/gsl_matrix.h>
+
+#include <vector>
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+unsigned total_pieces_sub;
+unsigned total_pieces_inc;
+
+void cairo_pw(cairo_t *cr, Piecewise<SBasis> p) {
+ for(unsigned i = 0; i < p.size(); i++) {
+ D2<SBasis> B;
+ B[0] = Linear(p.cuts[i], p.cuts[i+1]);
+ B[1] = p[i];
+ cairo_d2_sb(cr, B);
+ }
+}
+
+void draw_line(cairo_t* cr, Geom::Point n, double d) {
+ cairo_move_to(cr, d*n + rot90(n)*1000);
+ cairo_line_to(cr, d*n - rot90(n)*1000);
+ cairo_move_to(cr, d*n);
+ cairo_line_to(cr, (d+10)*n);
+}
+
+class InnerProductClip: public Toy {
+ Path path_a;
+ Piecewise<D2<SBasis> > path_a_pw;
+ std::vector<Toggle> togs;
+ PointHandle start_handle, end_handle;
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_source_rgba (cr, 0., 0.125, 0, 1);
+
+ D2<Piecewise<SBasis> > B = make_cuts_independent(path_a_pw);
+
+ Point n;
+ double d;
+ {
+ double x = width - 60, y = height - 60;
+ Point p(x, y), dpoint(25,25), xo(25,0), yo(0,25);
+ togs[0].bounds = Rect(p, p + dpoint);
+ togs[1].bounds = Rect(p + xo, p + xo + dpoint);
+ draw_toggles(cr, togs);
+ }
+ if(togs[0].on) {
+ d = L2(end_handle.pos - start_handle.pos);
+ cairo_save(cr);
+ cairo_set_line_width(cr, 0.3);
+ cairo_new_sub_path(cr);
+ cairo_arc(cr, start_handle.pos[0], start_handle.pos[1], d, 0, M_PI*2);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ } else {
+ n = unit_vector(rot90(end_handle.pos - start_handle.pos));
+ d = dot(n, start_handle.pos);
+ draw_line(cr, n, d);
+ }
+ //printf("%g\n", d);
+
+ vector<double> all_roots;
+ for(unsigned i = 0; i <= path_a.size(); i++) {
+ //deriv = p[i].derivative();
+ D2<SBasis> curpw = path_a[i].toSBasis();
+ SBasis inner;
+ if(togs[0].on) {
+ D2<SBasis> test = curpw - start_handle.pos;
+ inner = test[0]*test[0] + test[0]*test[1] + 2*test[1]*test[1] - d*d;
+ } else {
+ inner = n[0]*curpw[0] + n[1]*curpw[1] - d;
+ }
+ vector<double> lr = roots(inner);
+ all_roots.insert(all_roots.end(), lr.begin(), lr.end());
+ for(double i : lr)
+ draw_handle(cr, curpw(i));
+ sort(lr.begin(), lr.end());
+ lr.insert(lr.begin(), 0);
+ lr.insert(lr.end(), 1);
+ Path out;
+ for(unsigned j = 0; j < lr.size()-1; j++) {
+ //Point s = curpw(lr[j]);
+ Point m = curpw((lr[j] + lr[j+1])/2);
+ if(togs[0].on)
+ m -= start_handle.pos;
+ //Point e = curpw(lr[j+1]);
+ double dd;
+ if(togs[0].on)
+ //dd = dot(m, m) - d*d;
+ dd = m[0]*m[0] + m[0]*m[1] + 2*m[1]*m[1] - d*d;
+ else
+ dd = dot(n, m) - d;
+ if(togs[1].on)
+ dd = -dd;
+ //printf("%d [%g, %g] %g (%g, %g) (%g, %g)\n",
+ // i, lr[j], lr[j+1], dd, s[0], s[1], e[0], e[1]);
+ if(0 > dd) {
+ //Curve * cv = path_a[i].portion(lr[j], lr[j+1]);
+ cairo_d2_sb(cr, portion(curpw, lr[j], lr[j+1]));
+ cairo_set_source_rgba (cr, 0., 0.125, 0, 1);
+ cairo_stroke(cr);
+ /*cairo_curve(cr, path_a[i]);
+ cairo_set_source_rgba (cr, 0., 0.125, 0, 1);
+ cairo_stroke(cr);*/
+ }
+
+ }
+ }
+
+ //cairo_pw_d2_sb(cr, path_a_pw);
+ cairo_set_source_rgba (cr, 0., 0.125, 0, 1);
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+ void key_hit(GdkEventKey *e) override {
+ if(e->keyval == 's') togs[1].toggle(); else
+ if(e->keyval == 'c') togs[0].toggle();
+ redraw();
+ }
+ void mouse_pressed(GdkEventButton* e) override {
+ toggle_events(togs, e);
+ Toy::mouse_pressed(e);
+ }
+ void first_time(int argc, char** argv) override {
+ const char *path_a_name="star.svgd";
+ if(argc > 1)
+ path_a_name = argv[1];
+ PathVector paths_a = read_svgd(path_a_name);
+ assert(paths_a.size() > 0);
+ path_a = paths_a[0];
+
+ path_a.close(true);
+ path_a_pw = path_a.toPwSb();
+
+ // Finite images of the three vanishing points and the origin
+ handles.push_back(&start_handle);
+ handles.push_back(&end_handle);
+ togs.emplace_back("C", true);
+ togs.emplace_back("S", true);
+ }
+public:
+ InnerProductClip() : start_handle(150,300),
+ end_handle(380,40) {}
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new InnerProductClip);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/intersect-data.cpp b/src/3rdparty/2geom/src/toys/intersect-data.cpp
new file mode 100644
index 0000000..d262684
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/intersect-data.cpp
@@ -0,0 +1,436 @@
+#include <iostream>
+#include <2geom/path.h>
+#include <2geom/svg-path-parser.h>
+#include <2geom/path-intersection.h>
+#include <2geom/basic-intersection.h>
+#include <2geom/pathvector.h>
+#include <2geom/exception.h>
+
+#include <cstdlib>
+#include <cstdio>
+#include <set>
+#include <vector>
+#include <algorithm>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/ord.h>
+
+#include "topology.cpp"
+
+
+static double exp_rescale(double x){ return pow(10, x);}
+std::string exp_formatter(double x){ return default_formatter(exp_rescale(x));}
+
+
+class IntersectDataTester: public Toy {
+ unsigned nb_paths;
+ unsigned nb_curves_per_path;
+ unsigned degree;
+ double tol;
+
+ PathVector cmd_line_paths;
+
+ std::vector<PointSetHandle> paths_handles;
+ std::vector<Slider> sliders;
+ int nb_steps;
+
+ Topology topo;
+
+ //TODO conversions to path should be owned by the relevant classes.
+ Path edgeToPath(Topology::OrientedEdge o_edge){
+ Topology::Edge e = topo.edges[o_edge.edge];
+ D2<SBasis> p = topo.input_paths[e.path][e.curve].toSBasis();
+ Interval dom = e.portion;
+ p = portion(p, dom);
+ if ( o_edge.reversed ){
+ p = compose( p, Linear(1.,0.) );
+ }
+ Path ret;
+ ret.setStitching(true);
+ Point center;
+ unsigned c_idx = topo.source(o_edge, true);
+ if ( c_idx == NULL_IDX ){
+ ret.append(p);
+ }else{
+ center = topo.vertices[c_idx].bounds.midpoint();
+ ret = Path(center);
+ ret.append(p);
+ }
+ c_idx = topo.target(o_edge, true);
+ if ( c_idx == NULL_IDX ){
+ return ret;
+ }else{
+ center = topo.vertices[c_idx].bounds.midpoint();
+ if ( center != p.at1() ) ret.appendNew<LineSegment>(center);
+ return ret;
+ }
+ }
+
+ Path boundaryToPath(Topology::Boundary b){
+ Point pt;
+ Path bndary;
+ bndary.setStitching(true);
+
+ if (b.size()==0){ return Path(); }
+
+ Topology::OrientedEdge o_edge = b.front();
+ unsigned first_v = topo.source(o_edge, true);
+ if ( first_v != NULL_IDX ){
+ pt = topo.vertices[first_v].bounds.midpoint();
+ bndary = Path(pt);
+ }
+
+ for (unsigned i = 0; i < b.size(); i++){
+ bndary.append( edgeToPath(b[i]));
+ }
+ bndary.close();
+ return bndary;
+ }
+
+ //TODO:this should return a path vector, but we glue the components for easy drawing in the toy.
+ Path areaToPath(unsigned a){
+ Path bndary;
+ bndary.setStitching(true);
+ if ( topo.areas[a].boundary.size()==0 ){//this is the unbounded component...
+ OptRect bbox = bounds_fast( topo.input_paths );
+ if (!bbox ){return Path();}//???
+ bbox->expandBy(50);
+ bndary = Path(bbox->corner(0));
+ bndary.appendNew<LineSegment>(bbox->corner(1));
+ bndary.appendNew<LineSegment>(bbox->corner(2));
+ bndary.appendNew<LineSegment>(bbox->corner(3));
+ bndary.appendNew<LineSegment>(bbox->corner(0));
+ }else{
+ bndary = boundaryToPath(topo.areas[a].boundary);
+ }
+ for (auto & inner_boundarie : topo.areas[a].inner_boundaries){
+ bndary.append( boundaryToPath(inner_boundarie));
+ bndary.appendNew<LineSegment>( bndary.initialPoint() );
+ }
+ bndary.close();
+ return bndary;
+ }
+ void drawAreas( cairo_t *cr, Topology const &topo, bool fill=true ){
+ //don't draw the first one...
+ for (unsigned a=0; a<topo.areas.size(); a++){
+ drawArea(cr, topo, a, fill);
+ }
+ }
+ void drawArea( cairo_t *cr, Topology const &topo, unsigned a, bool fill=true ){
+ if (a>=topo.areas.size()) return;
+ Path bndary = areaToPath(a);
+ cairo_path(cr, bndary);
+ double r,g,b;
+
+ int winding = 0;
+ for (int k : topo.areas[a].windings){
+ winding += k;
+ }
+
+ //convertHSVtoRGB(0, 1., .5 + winding/10, r,g,b);
+ //convertHSVtoRGB(360*a/topo.areas.size(), 1., .5, r,g,b);
+ convertHSVtoRGB(180+30*winding, 1., .5, r,g,b);
+ cairo_set_source_rgba (cr, r, g, b, 1);
+ //cairo_set_source_rgba (cr, 1., 0., 1., .3);
+
+ if (fill){
+ cairo_fill(cr);
+ }else{
+ cairo_set_line_width (cr, 5);
+ cairo_stroke(cr);
+ }
+ }
+
+ void highlightRay( cairo_t *cr, Topology &topo, unsigned b, unsigned r ){
+ if (b>=topo.vertices.size()) return;
+ if (r>=topo.vertices[b].boundary.size()) return;
+ Rect box = topo.vertices[b].bounds;
+ //box.expandBy(2);
+ cairo_rectangle(cr, box);
+ cairo_set_source_rgba (cr, 1., 0., 0, 1.0);
+ cairo_set_line_width (cr, 1);
+ cairo_fill(cr);
+ unsigned eidx = topo.vertices[b].boundary[r].edge;
+ Topology::Edge e = topo.edges[eidx];
+ D2<SBasis> p = topo.input_paths[e.path][e.curve].toSBasis();
+ Interval dom = e.portion;
+ if (topo.vertices[b].boundary[r].reversed){
+ //dom[0] += e.portion.extent()*2./3;
+ cairo_set_source_rgba (cr, 0., 1., 0., 1.0);
+ }else{
+ //dom[1] -= e.portion.extent()*2./3;
+ cairo_set_source_rgba (cr, 0., 0., 1., 1.0);
+ }
+ p = portion(p, dom);
+ cairo_d2_sb(cr, p);
+ cairo_set_source_rgba (cr, 1., 0., 0, 1.0);
+ cairo_set_line_width (cr, 5);
+ cairo_stroke(cr);
+ }
+
+ void drawEdge( cairo_t *cr, Topology const &topo, unsigned eidx ){
+ if (eidx>=topo.edges.size()) return;
+ Topology::Edge e = topo.edges[eidx];
+ D2<SBasis> p = topo.input_paths[e.path][e.curve].toSBasis();
+ Interval dom = e.portion;
+ p = portion(p, dom);
+ cairo_d2_sb(cr, p);
+ if (e.start == NULL_IDX || e.end == NULL_IDX )
+ cairo_set_source_rgba (cr, 0., 1., 0, 1.0);
+ else
+ cairo_set_source_rgba (cr, 0., 0., 0, 1.0);
+ cairo_set_line_width (cr, 1);
+ cairo_stroke(cr);
+ }
+ void drawEdges( cairo_t *cr, Topology const &topo ){
+ for (unsigned e=0; e<topo.edges.size(); e++){
+ drawEdge(cr, topo, e);
+ }
+ }
+ void drawKnownEdges( cairo_t *cr, Topology const &topo ){
+ for (unsigned v=0; v<topo.vertices.size(); v++){
+ for (unsigned e=0; e<topo.vertices[v].boundary.size(); e++){
+ drawEdge(cr, topo, topo.vertices[v].boundary[e].edge);
+ }
+ }
+ }
+
+
+ void drawBox( cairo_t *cr, Topology const &topo, unsigned b ){
+ if (b>=topo.vertices.size()) return;
+ Rect box = topo.vertices[b].bounds;
+ //box.expandBy(5);
+ cairo_rectangle(cr, box);
+ cairo_set_source_rgba (cr, 1., 0., 0, .5);
+ cairo_set_line_width (cr, 1);
+ cairo_stroke(cr);
+ cairo_rectangle(cr, box);
+ cairo_set_source_rgba (cr, 1., 0., 0, .2);
+ cairo_fill(cr);
+
+// //std::cout<<"\nintersection boundary:\n";
+// for (unsigned i = 0; i < topo.vertices[b].boundary.size(); i++){
+// unsigned eidx = topo.vertices[b].boundary[i].edge;
+// Topology::Edge e = topo.edges[eidx];
+// D2<SBasis> p = topo.input_paths[e.path][e.curve].toSBasis();
+// Interval dom = e.portion;
+// if (topo.vertices[b].boundary[i].reversed){
+// dom[0] += e.portion.extent()*2./3;
+// cairo_set_source_rgba (cr, 0., 1., .5, 1);
+// }else{
+// dom[1] -= e.portion.extent()*2./3;
+// cairo_set_source_rgba (cr, 0., .5, 1., 1);
+// }
+// p = portion(p, dom);
+// cairo_d2_sb(cr, p);
+// cairo_set_line_width (cr, 2);
+// cairo_stroke(cr);
+// }
+ }
+ void drawBoxes( cairo_t *cr, Topology const &topo ){
+ for (unsigned b=0; b<topo.vertices.size(); b++){
+ drawBox(cr, topo, b);
+ }
+ }
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ *notify<<"line command args: svgd file or (nb paths, nb curves/path, degree of curves).\n";
+ cairo_set_source_rgba (cr, 0., 0., 0, 1);
+ cairo_set_line_width (cr, 1);
+
+ PathVector paths;
+ if (!cmd_line_paths.empty()){
+ paths = cmd_line_paths;
+ for (unsigned i = 0; i < paths.size(); i++){
+ paths[i] *= Translate( paths_handles[i].pts[0] - paths[i].initialPoint() );
+ }
+ }else{
+ for (unsigned i = 0; i < nb_paths; i++){
+ paths_handles[i].pts.back()=paths_handles[i].pts.front();
+ paths.push_back(Path(paths_handles[i].pts[0]));
+ for (unsigned j = 0; j+degree < paths_handles[i].size(); j+=degree){
+ D2<SBasis> c = handles_to_sbasis(paths_handles[i].pts.begin()+j, degree);
+ if ( j + degree == paths_handles[i].size()-1 ){
+ c[X].at(0)[1] = paths_handles[i].pts.front()[X];
+ c[Y].at(0)[1] = paths_handles[i].pts.front()[Y];
+ }
+ paths[i].append(c);
+ }
+ paths[i].close();
+ }
+ }
+ *notify<<"Use '<' and '>' keys to move backward/forward in the sweep: (currently doing "<<nb_steps<<" steps)\n";
+ *notify<<"nb_steps: "<<nb_steps<<"\n";
+
+
+#if 0
+ cairo_path(cr, paths);
+ cairo_set_source_rgba (cr, 0., 0., 0, 1);
+ cairo_set_line_width (cr, 1);
+ cairo_stroke(cr);
+#endif
+
+ tol = exp_rescale( sliders[3].value() );
+ topo = Topology(paths, cr, tol, nb_steps );
+
+#if 1
+ unsigned v = (unsigned)(sliders[0].value()*(double(topo.vertices.size())));
+ unsigned r = (unsigned)(sliders[1].value()*(double(topo.vertices[v].boundary.size())));
+ unsigned a = (unsigned)(sliders[2].value()*(double(topo.areas.size())));
+ if( v == topo.vertices.size() ) v--;
+ if( r == topo.vertices[v].boundary.size()) r--;
+ if( a == topo.areas.size()) a--;
+ drawAreas(cr, topo);
+ drawKnownEdges(cr, topo);
+ //drawArea(cr, topo, a, false);
+ //highlightRay(cr, topo, v, r );
+ //*notify<<"highlighted edge: "<< topo.vertices[v].boundary[r].edge<<"\n";
+
+ //drawBox(cr,topo, unsigned(sliders[0].value()));
+ drawBoxes(cr,topo);
+#endif
+ Toy::draw(cr, notify, width, height, save, timer_stream);
+ }
+
+
+ void initSliders(){
+ sliders.emplace_back(0.0, 1, 0, 0.0, "intersection chooser");
+ sliders.emplace_back(0.0, 1, 0, 0.0, "ray chooser");
+ sliders.emplace_back(0.0, 1, 0, 0.0, "area chooser");
+ sliders.emplace_back(-5.0, 2, 0, 0.0, "tolerance chooser");
+
+ handles.push_back(&(sliders[0]));
+ handles.push_back(&(sliders[1]));
+ handles.push_back(&(sliders[2]));
+ handles.push_back(&(sliders[3]));
+
+ sliders[0].geometry(Point(50, 20), 250);
+ sliders[1].geometry(Point(50, 50), 250);
+ sliders[2].geometry(Point(50, 80), 250);
+ sliders[3].geometry(Point(50, 110), 250);
+ sliders[3].formatter( &exp_formatter );
+
+ }
+
+ public:
+ IntersectDataTester(PathVector input_paths){
+ cmd_line_paths = input_paths;
+ //nb_paths=0; nb_curves_per_path = 0; degree = 0;//meaningless
+ paths_handles = std::vector<PointSetHandle>( cmd_line_paths.size(), PointSetHandle() );
+ for(unsigned i = 0; i < cmd_line_paths.size(); i++){
+ //TODO: use path iterators to deal with closed/open paths!!!
+ //cmd_line_paths[i].close();
+ if ( cmd_line_paths[i].closed() ){
+ cmd_line_paths[i].appendNew<LineSegment>(cmd_line_paths[i].initialPoint() );
+ }
+ Point p = cmd_line_paths[i].initialPoint();
+ paths_handles.emplace_back();
+ paths_handles[i].push_back(p);
+ handles.push_back( &paths_handles[i] );
+ }
+ initSliders();
+ }
+
+ IntersectDataTester(unsigned paths, unsigned curves_in_path, unsigned degree) :
+ nb_paths(paths), nb_curves_per_path(curves_in_path), degree(degree) {
+
+ paths_handles = std::vector<PointSetHandle>( nb_paths, PointSetHandle() );
+ for(unsigned i = 0; i < nb_paths; i++){
+ for(unsigned j = 0; j < (nb_curves_per_path*degree)+1; j++){
+ paths_handles[i].push_back(uniform()*400, 100+ uniform()*300);
+ }
+ handles.push_back(&paths_handles[i]);
+ }
+ initSliders();
+ }
+
+ IntersectDataTester(){
+ nb_paths=3; nb_curves_per_path = 5; degree = 1;
+
+ paths_handles.emplace_back();
+ paths_handles[0].push_back(100,100);
+ paths_handles[0].push_back(100,200);
+ paths_handles[0].push_back(300,200);
+ paths_handles[0].push_back(300,100);
+ paths_handles[0].push_back(100,100);
+
+ paths_handles.emplace_back();
+ paths_handles[1].push_back(120,190);
+ paths_handles[1].push_back(200,210);
+ paths_handles[1].push_back(280,190);
+ paths_handles[1].push_back(200,300);
+ paths_handles[1].push_back(120,190);
+
+ paths_handles.emplace_back();
+ paths_handles[2].push_back(180,150);
+ paths_handles[2].push_back(200,140);
+ paths_handles[2].push_back(220,150);
+ paths_handles[2].push_back(300,160);
+ paths_handles[2].push_back(180,150);
+
+ handles.push_back(&paths_handles[0]);
+ handles.push_back(&paths_handles[1]);
+ handles.push_back(&paths_handles[2]);
+
+ initSliders();
+ }
+
+
+ void first_time(int /*argc*/, char** /*argv*/) override {
+ nb_steps = -1;
+ }
+
+ void key_hit(GdkEventKey *e) override
+ {
+ char choice = std::toupper(e->keyval);
+ switch ( choice )
+ {
+ case '>':
+ nb_steps++;
+ break;
+ case '<':
+ if ( nb_steps > -1 ) nb_steps--;
+ break;
+ }
+ redraw();
+ }
+
+};
+
+int main(int argc, char **argv) {
+ if(argc == 2){
+ const char *path_name = argv[1];
+ PathVector cmd_line_paths = read_svgd(path_name); //* Scale(3);
+ OptRect bounds = bounds_exact(cmd_line_paths);
+ if (bounds) {
+ cmd_line_paths *= Translate(Point(10,10) - bounds->min());
+ }
+ init(argc, argv, new IntersectDataTester(cmd_line_paths));
+ }else{
+ unsigned nb_paths=3, nb_curves_per_path = 5, degree = 1;
+ if(argc > 3)
+ sscanf(argv[3], "%d", &degree);
+ if(argc > 2)
+ sscanf(argv[2], "%d", &nb_curves_per_path);
+ if(argc > 1){
+ sscanf(argv[1], "%d", &nb_paths);
+ init(argc, argv, new IntersectDataTester( nb_paths, nb_curves_per_path, degree ) );
+ }else{
+ init(argc, argv, new IntersectDataTester());
+ }
+ }
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/inverse-test.cpp b/src/3rdparty/2geom/src/toys/inverse-test.cpp
new file mode 100644
index 0000000..c339419
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/inverse-test.cpp
@@ -0,0 +1,174 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/bezier-to-sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <time.h>
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+static void plot(cairo_t* cr, SBasis const &B,double vscale=1,double a=0,double b=1){
+ D2<SBasis> plot;
+ plot[0]=SBasis(Linear(150+a*300,150+b*300));
+ plot[1]=B*-vscale;
+ plot[1]+=450;
+ cairo_d2_sb(cr, plot);
+ cairo_stroke(cr);
+}
+static void plot(cairo_t* cr, Piecewise<SBasis> const &f,double vscale=1){
+ for (unsigned i=0;i<f.size();i++){
+ plot(cr,f.segs[i],vscale,f.cuts[i],f.cuts[i+1]);
+ draw_cross(cr,Geom::Point(f.cuts[i]*300 + 150, f.segs[i][0][0]*(-vscale) + 450));
+ }
+}
+
+static SBasis my_inverse(SBasis f, int order){
+ double a0 = f[0][0];
+ if(a0 != 0) {
+ f -= a0;
+ }
+ double a1 = f[0][1];
+ if(a1 == 0)
+ THROW_NOTINVERTIBLE();
+ //assert(a1 != 0);// not invertible.
+ if(a1 != 1) {
+ f /= a1;
+ }
+
+ SBasis g=SBasis(order, Linear());
+ g[0] = Linear(0,1);
+ double df0=derivative(f)(0);
+ double df1=derivative(f)(1);
+ SBasis r = Linear(0,1)-g(f);
+
+ for(int i=1; i<order; i++){
+ //std::cout<<"i: "<<i<<std::endl;
+ r=Linear(0,1)-g(f);
+ //std::cout<<"t-gof="<<r<<std::endl;
+ r.normalize();
+ if (r.size()==0) return(g);
+ double a=r[i][0]/std::pow(df0,i);
+ double b=r[i][1]/std::pow(df1,i);
+ g[i] = Linear(a,b);
+ }
+
+ return(g);
+}
+
+static Piecewise<SBasis> pw_inverse(SBasis const &f, int order,double tol=.1,int depth=0){
+ SBasis g=SBasis(Linear(0,1)),r;
+ Piecewise<SBasis> res,res1,res2;
+
+ //std::cout<<"depth: "<<depth<<std::endl;
+ g=my_inverse(f,order);
+ r=g(f);
+ //std::cout<<"error: "<<g.tail_error(1)<<std::endl;
+ if (g.tailError(1)<tol){
+ res.segs.push_back(g);
+ res.cuts.push_back(f[0][0]);
+ res.cuts.push_back(f[0][1]);
+ }else if (depth<200){
+ SBasis ff;
+ ff=f(Linear(0,.5));
+ res=pw_inverse(ff,order,tol,depth+1);
+ for (unsigned i=0;i<res.size();i++){
+ res.segs[i]*=.5;
+ }
+ ff=f(Linear(.5,1));
+ res1=pw_inverse(ff,order,tol,depth+1);
+ for (unsigned i=0;i<res1.size();i++){
+ res1.segs[i]*=.5;
+ res1.segs[i]+=.5;
+ }
+ res.concat(res1);
+ }
+ return(res);
+}
+
+
+
+class InverseTester: public Toy {
+ int size;
+ PointSetHandle hand;
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+
+ for (int i=0;i<size;i++){
+ hand.pts[i ][0]=150+15*(i-size);
+ hand.pts[i+size][0]=450+15*(i+1);
+ cairo_move_to(cr, Geom::Point(hand.pts[i ][0],150));
+ cairo_line_to(cr, Geom::Point(hand.pts[i ][0],450));
+ cairo_move_to(cr, Geom::Point(hand.pts[i+size][0],150));
+ cairo_line_to(cr, Geom::Point(hand.pts[i+size][0],450));
+ }
+ cairo_move_to(cr, Geom::Point(0,300));
+ cairo_line_to(cr, Geom::Point(600,300));
+
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0.2, 0.2, 0.2, 1);
+ cairo_stroke(cr);
+
+ SBasis f(size, Linear());//=SBasis(Linear(0,.5));
+ for (int i=0;i<size;i++){
+ f[i] = Linear(-(hand.pts[i ][1]-300)*std::pow(4.,i)/150,
+ -(hand.pts[i+size][1]-300)*std::pow(4.,i)/150 );
+ }
+ plot(cr,Linear(0,1),300);
+
+ f.normalize();
+ cairo_set_line_width (cr, 2);
+ cairo_set_source_rgba (cr, 0., 0., 0.8, 1);
+ plot(cr,f,300);
+
+ *notify<<"Use hand.pts to set the coefficients of the (blue) s-basis."<<std::endl;
+ *notify<<" (keep it monotonic!)"<<std::endl;
+ *notify<<"red=flipped inverse; should be the same as the blue one."<<std::endl;
+
+ try {
+ Piecewise<SBasis> g=pw_inverse(f,3);
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0.8, 0., 0., 1);
+ plot(cr,g,300);
+ Piecewise<SBasis> h=compose(g,f);
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0., 0.8, 0., 1);
+ plot(cr,h,300);
+ *notify<<g.size()<<" segments.";
+ } catch(NotInvertible) {
+ *notify << "function not invertible!" << std::endl;
+ }
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+public:
+ InverseTester() {
+ size=4;
+ if(hand.pts.empty()) {
+ for(int i = 0; i < 2*size; i++)
+ hand.pts.emplace_back(0,150+150+uniform()*300*0);
+ }
+ hand.pts[0][1]=300;
+ hand.pts[size][1]=150;
+ handles.push_back(&hand);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new InverseTester);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+//vim:filetype = cpp:expandtab:shiftwidth = 4:tabstop = 8:softtabstop = 4:encoding = utf-8:textwidth = 99 :
diff --git a/src/3rdparty/2geom/src/toys/kinematic_templates.cpp b/src/3rdparty/2geom/src/toys/kinematic_templates.cpp
new file mode 100644
index 0000000..0089a1a
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/kinematic_templates.cpp
@@ -0,0 +1,365 @@
+#include <toys/toy-framework-2.h>
+
+/*
+ * Copyright cilix42
+ * Kinematic template toy. The aim is to manipulate the cursor movement
+ * so that it stays closer to a given shape (e.g., a circle or a line).
+ * For details, see http://hci.uwaterloo.ca/Publications/Papers/uist222-fung.pdf
+ *
+ * Each kinematic template has a radius of action outside of which it
+ * has no effect (this is indicated by a red circle).
+ */
+
+#include <vector>
+#include <2geom/point.h>
+#include <2geom/transforms.h>
+
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+// I feel a little uneasy using a Point for polar coords.
+Point cartesian_to_polar(Point const &pt, Point const &center = Point(0,0)) {
+ Point rvec = pt - center;
+ // use atan2 unless you want to measure between two vectors
+ return Point(L2(rvec), atan2(rvec));
+}
+
+Point polar_to_cartesian(Point const &pt, Point const &center = Point(0,0)) {
+ return center + Point(pt[0],0) * Rotate(pt[1]);
+}
+
+class KinematicTemplate {
+public:
+ KinematicTemplate(double const sx = 0.0, double const sy = 0.0, double const cx = 0.0, double const cy = 0.0);
+ ~KinematicTemplate();
+
+ /*
+ * To facilitate the creation of templates, we can use different coordinates at each point
+ * (e.g., radial coordinates around a fixed center)
+ */
+ virtual std::pair<Point, Point> local_coordinate_system(Point const &/*at*/) {
+ // Return standard cartesian coordinates
+ return std::make_pair(Point(1,0), Point(0,1));
+ }
+
+ virtual Point next_point(Point const &at, Point const &delta);// { return at; }
+ virtual void draw_visual_cue(cairo_t *cr);
+
+ Point const get_center() { return center; }
+ void set_center(Point const &pos) { center = pos; }
+
+ double get_radius_of_action() { return radius; }
+ void set_radius_of_action(double const r) { radius = r; }
+ void enlarge_radius_of_action(double const by) {
+ if (radius > -by)
+ radius += by;
+ else
+ radius = 0;
+ }
+
+
+protected:
+ double sx, sy, cx, cy;
+ Point center;
+ double radius;
+};
+
+KinematicTemplate::KinematicTemplate(double const sx, double const sy, double const cx, double const cy)
+ : sx(sx),
+ sy(sy),
+ cx(cx),
+ cy(cy),
+ center(300,300),
+ radius(100)
+{
+}
+
+KinematicTemplate::~KinematicTemplate()
+{
+}
+
+Point
+KinematicTemplate::next_point(Point const &last_pt, Point const &delta)
+{
+// Point new_pt = last_pushed + kinematic_delta(last_pushed, delta, 0);
+
+ /* Compute the "relative" coordinates w.r.t. the "local coordinate system" at the current point */
+ Point v = local_coordinate_system(last_pt).first;
+ Point w = local_coordinate_system(last_pt).second;
+ double dotv = dot(v, delta);
+ double dotw = dot(w, delta);
+
+ Point new_delta;
+ if (L2(last_pt + delta - center) < radius) {
+ /*
+ * We are within the radius of action of the kinematic template.
+ * Compute displacement w.r.t. the v/w-coordinate system.
+ */
+ new_delta = (dotv*sx + cx)*v + (dotw*sy + cy)*w;
+ } else {
+ new_delta = delta;
+ }
+
+ return last_pt + new_delta;
+}
+
+void
+KinematicTemplate::draw_visual_cue(cairo_t *cr) {
+ cairo_set_source_rgba (cr, 1, 0, 0, 1);
+ cairo_set_line_width (cr, 0.5);
+ cairo_new_sub_path(cr);
+ cairo_arc(cr, center[X], center[Y], radius, 0, M_PI*2);
+ cairo_stroke(cr);
+}
+
+class RadialKinematicTemplate : public KinematicTemplate {
+public:
+ RadialKinematicTemplate(Point const &center, double const sx, double const sy, double const cx, double const cy);
+
+ std::pair<Point, Point> local_coordinate_system(Point const &at) override {
+ /* Return 'radial' coordinates around polar_center */
+ Point v = unit_vector(at - center);
+ return std::make_pair(v, rot90(v));
+ }
+
+private:
+ Point radial_center;
+};
+
+RadialKinematicTemplate::RadialKinematicTemplate(Point const &center, double const sx, double const sy,
+ double const cx = 0.0, double const cy = 0.0)
+ : KinematicTemplate(sx, sy, cx, cy)
+{
+ radial_center = center;
+}
+
+class GridKinematicTemplate : public KinematicTemplate {
+public:
+ GridKinematicTemplate(double const sx = 0.0, double const sy = 0.0, double const cx = 0.0, double const cy = 0.0)
+ : KinematicTemplate(sx, sy, cx, cy) {};
+ Point next_point(Point const &at, Point const &delta) override;// { return at; }
+};
+
+Point
+GridKinematicTemplate::next_point(Point const &at, Point const &delta) {
+ if (L2(at + delta - center) < radius) {
+ // we are within the radius of action
+ Point new_delta = delta;
+
+ if (fabs(delta[0]) > fabs(delta[1]))
+ new_delta[1] *= sy;
+ else
+ new_delta[0] *= sx;
+
+ return at + new_delta;
+ } else {
+ return at + delta;
+ }
+}
+
+
+// My idea was to compute the gradient of an arbitrary potential function as the transform. Probably the right way to do this is to use the hessian as the integrand -- njh
+class ImplicitKinematicTemplate : public KinematicTemplate {
+public:
+ ImplicitKinematicTemplate() {}
+
+ Point next_point(Point const &at, Point const &delta) override {
+ if (L2(at + delta - center) < radius) {
+ // we are within the radius of action
+
+ // the 0.7dx+1 includes a weakened version of the constraining force
+ // I can't help but think this is really a form of differential constraint solver, let's discuss.
+ return at + delta*Scale(0.7*sin(at[0]/10.0)+1, 0.7*cos(at[1]/10.0)+1);
+ } else {
+ return at + delta;
+ }
+ }
+};
+
+
+
+vector<KinematicTemplate*> kin;
+KinematicTemplate *cur_kin;
+std::string cur_choice = "A";
+
+class KinematicTemplatesToy : public Toy {
+
+ enum menu_item_t
+ {
+ KT_HORIZONTAL = 0,
+ KT_VERTICAL,
+ KT_GRID,
+ KT_CIRCLE,
+ KT_RADIAL,
+ KT_CONVEYOR,
+ KT_IMP,
+ TOTAL_ITEMS // this one must be the last item
+ };
+
+ static const char* menu_items[TOTAL_ITEMS];
+ static const char keys[TOTAL_ITEMS];
+
+ Point cur, last_pushed;
+ vector<vector<Point>*> pts;
+
+ bool dragging_center; // to prevent drawing while dragging the center
+
+ void draw_menu( cairo_t * /*cr*/, std::ostringstream *notify,
+ int /*width*/, int /*height*/, bool /*save*/,
+ std::ostringstream */*timer_stream*/ )
+ {
+ *notify << std::endl;
+ for (int i = KT_HORIZONTAL; i < TOTAL_ITEMS; ++i)
+ {
+ *notify << " " << keys[i] << " - " << menu_items[i] << std::endl;
+ }
+ *notify << "+/- - enlarge/shrink radius of action" << endl << endl << endl << endl;
+ *notify << "Current choice: " << cur_choice << endl;
+ }
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_source_rgba (cr, 0., 0.125, 0, 1);
+ cairo_set_line_width (cr, 1);
+
+ //draw_handle(cr, cur_kin->get_center());
+ draw_menu(cr, notify, width, height, save, timer_stream);
+
+ // draw all points accumulated so far
+ for (auto & pt : pts) {
+ if (pt->size() > 0) {
+ cairo_move_to(cr, (*pt)[0]);
+ }
+ for (auto & j : *pt) {
+ //cout << " --> drawing line to point #" << j << endl;
+ cairo_line_to(cr, j);
+ }
+ }
+
+ cairo_stroke(cr);
+
+ cur_kin->draw_visual_cue(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ void first_time(int /*argc*/, char** /*argv*/) override {
+ p1.pos = Point(200, 200);
+ handles.push_back(&p1);
+
+ pts.clear();
+ kin.push_back(new KinematicTemplate(1.0, 0.1)); // horizontal lines
+ kin.push_back(new KinematicTemplate(0.1, 1.0)); // horizontal lines
+ kin.push_back(new GridKinematicTemplate(0.1, 0.1));
+ kin.push_back(new RadialKinematicTemplate(p1.pos, 0.1, 1.0));
+ kin.push_back(new RadialKinematicTemplate(p1.pos, 1.0, 0.1));
+ kin.push_back(new KinematicTemplate(1.0, 0.1, 1, 0)); // horiz conveyor
+ kin.push_back(new ImplicitKinematicTemplate());
+ cur_kin = kin[0];
+ cur_kin->set_center(p1.pos);
+
+ dragging_center = false;
+ }
+
+ void mouse_pressed(GdkEventButton *e) override {
+ Point at(e->x, e->y);
+
+ if(L2(at - p1.pos) < 5) {
+ dragging_center = true;
+ } else {
+ if(e->button == 1) {
+ vector<Point> *vec = new vector<Point>;
+ vec->clear();
+ vec->push_back(at);
+ last_pushed = at;
+ pts.push_back(vec);
+ }
+ }
+
+ Toy::mouse_pressed(e);
+ }
+
+ void mouse_released(GdkEventButton */*e*/) override {
+ dragging_center = false;
+ }
+
+ void mouse_moved(GdkEventMotion* e) override {
+ if (!dragging_center) {
+ Point at(e->x, e->y);
+
+ Point delta = at - cur;
+ //cout << "Mouse moved to: " << at << " (difference: " << delta << ")" << endl;
+ if(e->state & GDK_BUTTON1_MASK) {
+ Point new_pt = cur_kin->next_point(last_pushed, delta);
+
+ pts.back()->push_back(new_pt);
+ last_pushed = new_pt;
+ }
+ cur = at;
+ } else {
+ cur_kin->set_center(p1.pos);
+ }
+
+ Toy::mouse_moved(e);
+ }
+
+ void key_hit(GdkEventKey *e) override
+ {
+ char choice = std::toupper(e->keyval);
+ // No need to copy and paste code
+ if(choice >= 'A' and choice < 'A' + TOTAL_ITEMS) {
+ cur_kin = kin[choice - 'A'];
+ cur_choice = choice;
+
+ } else
+ switch (choice)
+ {
+ case '+':
+ cur_kin->enlarge_radius_of_action(5);
+ break;
+ case '-':
+ cur_kin->enlarge_radius_of_action(-5);
+ break;
+ default:
+ break;
+ }
+ p1.pos = cur_kin->get_center();
+ redraw();
+ }
+
+private:
+ PointHandle p1;
+};
+
+const char* KinematicTemplatesToy::menu_items[] =
+{
+ "horizontal",
+ "vertical",
+ "grid",
+ "circular",
+ "radial",
+ "conveyor",
+ "implicit"
+};
+
+const char KinematicTemplatesToy::keys[] =
+{
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G'
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new KinematicTemplatesToy);
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/levelsets-test.cpp b/src/3rdparty/2geom/src/toys/levelsets-test.cpp
new file mode 100644
index 0000000..cd5874e
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/levelsets-test.cpp
@@ -0,0 +1,155 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/bezier-to-sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+using std::vector;
+using namespace std;
+using namespace Geom;
+
+static double exp_rescale(double x){ return std::pow(10, x);}
+std::string exp_formatter(double x){ return default_formatter(exp_rescale(x));}
+
+
+static void plot(cairo_t* cr, SBasis const &B,double vscale=1,double a=0,double b=1){
+ D2<SBasis> plot;
+ plot[0]=SBasis(Linear(150+a*300,150+b*300));
+ plot[1]=B*(-vscale);
+ plot[1]+=300;
+ cairo_d2_sb(cr, plot);
+ cairo_stroke(cr);
+}
+static void plot_bar(cairo_t* cr, double height, double vscale=1,double a=0,double b=1){
+ cairo_move_to(cr, Geom::Point(150+300*a,-height*vscale+300));
+ cairo_line_to(cr, Geom::Point(150+300*b,-height*vscale+300));
+}
+static void plot_bar(cairo_t* cr, Interval height, double vscale=1,double a=0,double b=1){
+ Point A(150+300*a,-height.max()*vscale+300);
+ Point B(150+300*b,-height.min()*vscale+300);
+ cairo_rectangle(cr, Rect(A,B) );
+}
+
+class BoundsTester: public Toy {
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+
+ for (unsigned i=0;i<size;i++){
+ hand.pts[i ][0]=150+15*(i-size);
+ hand.pts[i+size][0]=450+15*(i+1);
+ cairo_move_to(cr, Geom::Point(hand.pts[i ][0],150));
+ cairo_line_to(cr, Geom::Point(hand.pts[i ][0],450));
+ cairo_move_to(cr, Geom::Point(hand.pts[i+size][0],150));
+ cairo_line_to(cr, Geom::Point(hand.pts[i+size][0],450));
+ }
+ cairo_move_to(cr, Geom::Point(0,300));
+ cairo_line_to(cr, Geom::Point(600,300));
+
+ cairo_set_line_width (cr, .3);
+ cairo_set_source_rgba (cr, 0.2, 0.2, 0.2, 1);
+ cairo_stroke(cr);
+
+ SBasis B(size, Linear());
+ for (unsigned i=0;i<size;i++){
+ B[i] = Linear(-(hand.pts[i ][1]-300)*std::pow(4.,(int)i),
+ -(hand.pts[i+size][1]-300)*std::pow(4.,(int)i) );
+ }
+ B.normalize();
+ plot(cr,B,1);
+ cairo_set_source_rgba (cr, 0., 0., 0.8, 1);
+ cairo_stroke(cr);
+
+ double vtol = exp_rescale(slider.value());
+ if (vtol<1e-4) vtol=0;
+
+ hand.pts[2*size ][X]=150;
+ hand.pts[2*size+1][X]=150;
+ hand.pts[2*size+2][X]=150;
+ hand.pts[2*size+1][Y]=std::max(hand.pts[2*size+1][Y],hand.pts[2*size+2][Y]+2*vtol);
+ hand.pts[2*size ][Y]=std::max(hand.pts[2*size ][Y],hand.pts[2*size+1][Y]+2*vtol);
+
+ vector<Interval> levels;
+ levels.emplace_back(300-(hand.pts[2*size ][Y]-vtol), 300-(hand.pts[2*size ][Y]+vtol) );
+ levels.emplace_back(300-(hand.pts[2*size+1][Y]-vtol), 300-(hand.pts[2*size+1][Y]+vtol) );
+ levels.emplace_back(300-(hand.pts[2*size+2][Y]-vtol), 300-(hand.pts[2*size+2][Y]+vtol) );
+
+ for (auto & level : levels) plot_bar(cr,level.middle());
+ cairo_set_source_rgba( cr, 1., 0., 0., 1);
+ cairo_stroke(cr);
+ for (auto & level : levels) plot_bar(cr,level);
+ cairo_set_source_rgba( cr, 1., 0., 0., .2);
+ cairo_fill(cr);
+
+ cairo_set_source_rgba (cr, 0., 0.5, 0., 1);
+
+ *notify<<"Use hand.pts to set the coefficients of the s-basis."<<std::endl;
+
+ vector<vector<Interval> > sols=level_sets(B,levels,0,1);
+ for (unsigned i=0;i<sols.size();i++){
+ for (unsigned j=0;j<sols[i].size();j++){
+ Interval ys = levels[i];
+ ys.expandTo(0.);
+ cairo_set_line_width (cr, .3);
+ plot_bar(cr,ys, 1., sols[i][j].min(), sols[i][j].max());
+ cairo_set_source_rgba( cr, 0., 0., 1., .3);
+ cairo_fill(cr);
+ plot_bar(cr,ys, 1., sols[i][j].min(), sols[i][j].max());
+ cairo_set_source_rgba( cr, 0., 0., 1., .3);
+ cairo_stroke(cr);
+ cairo_set_line_width (cr, 1.6);
+ cairo_set_source_rgba( cr, 0., 0., 1, 1);
+ plot_bar(cr,0., 1., sols[i][j].min(), sols[i][j].max());
+ Point sol ( 150 + 300 * sols[i][j].middle(), 300);
+ draw_cross(cr, sol);
+ cairo_stroke(cr);
+ }
+ }
+
+ cairo_set_source_rgba( cr, 0., 0., 1., .5);
+ cairo_fill(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+
+public:
+ BoundsTester(){
+ size=5;
+ if(hand.pts.empty()) {
+ for(unsigned i = 0; i < 2*size; i++)
+ hand.pts.emplace_back(0,150+150+uniform()*300*0);
+ }
+ hand.pts.emplace_back(150,300+ 50+uniform()*100);
+ hand.pts.emplace_back(150,300- 50+uniform()*100);
+ hand.pts.emplace_back(150,300-150+uniform()*100);
+ handles.push_back(&hand);
+ slider = Slider(-5, 2, 0, 0.5, "tolerance");
+ slider.geometry(Point(50, 20), 250);
+ slider.formatter(&exp_formatter);
+ handles.push_back(&slider);
+ }
+
+
+private:
+ unsigned size;
+ PointSetHandle hand;
+ Slider slider;
+
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new BoundsTester);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype = cpp:expandtab:shiftwidth = 4:tabstop = 8:softtabstop = 4:encoding = utf-8:textwidth = 99 :
diff --git a/src/3rdparty/2geom/src/toys/line-toy.cpp b/src/3rdparty/2geom/src/toys/line-toy.cpp
new file mode 100644
index 0000000..0090d3a
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/line-toy.cpp
@@ -0,0 +1,916 @@
+/*
+ * Line Toy
+ *
+ * Copyright 2008 Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#include <2geom/line.h>
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <2geom/angle.h>
+
+#include <vector>
+#include <string>
+#include <optional>
+
+using namespace Geom;
+
+
+
+std::string angle_formatter(double angle)
+{
+ return default_formatter(decimal_round(deg_from_rad(angle),2));
+}
+
+
+
+class LineToy : public Toy
+{
+ enum menu_item_t
+ {
+ SHOW_MENU = 0,
+ TEST_CREATE,
+ TEST_PROJECTION,
+ TEST_ORTHO,
+ TEST_DISTANCE,
+ TEST_POSITION,
+ TEST_SEG_BISEC,
+ TEST_ANGLE_BISEC,
+ TEST_COLLINEAR,
+ TEST_INTERSECTIONS,
+ TEST_COEFFICIENTS,
+ TEST_SEGMENT_INSIDE,
+ TOTAL_ITEMS // this one must be the last item
+ };
+
+ enum handle_label_t
+ {
+ };
+
+ enum toggle_label_t
+ {
+ };
+
+ enum slider_label_t
+ {
+ END_SHARED_SLIDERS = 0,
+ ANGLE_SLIDER = END_SHARED_SLIDERS,
+ A_COEFF_SLIDER = END_SHARED_SLIDERS,
+ B_COEFF_SLIDER,
+ C_COEFF_SLIDER
+ };
+
+ static const char* menu_items[TOTAL_ITEMS];
+ static const char keys[TOTAL_ITEMS];
+
+ void first_time(int /*argc*/, char** /*argv*/) override
+ {
+ draw_f = &LineToy::draw_menu;
+ }
+
+ void init_common()
+ {
+ set_common_control_geometry = true;
+ set_control_geometry = true;
+
+ sliders.clear();
+ toggles.clear();
+ handles.clear();
+ }
+
+
+ virtual void draw_common( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool /*save*/ )
+ {
+ init_common_ctrl_geom(cr, width, height, notify);
+ }
+
+
+ void init_create()
+ {
+ init_common();
+
+ p1.pos = Point(400, 50);
+ p2.pos = Point(450, 450);
+ O.pos = Point(50, 400);
+
+ sliders.emplace_back(0, 2*M_PI, 0, 0, "angle");
+ sliders[ANGLE_SLIDER].formatter(&angle_formatter);
+
+ handles.push_back(&p1);
+ handles.push_back(&p2);
+ handles.push_back(&O);
+ handles.push_back(&(sliders[ANGLE_SLIDER]));
+ }
+
+ void draw_create(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+ init_create_ctrl_geom(cr, notify, width, height);
+
+ Line l1(p1.pos, p2.pos);
+ Line l2(O.pos, sliders[ANGLE_SLIDER].value());
+
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_set_line_width(cr, 0.3);
+ draw_line(cr, l1);
+ draw_line(cr, l2);
+ cairo_stroke(cr);
+
+ draw_label(cr, p1, "P1");
+ draw_label(cr, p2, "P2");
+ draw_label(cr, O, "O");
+ draw_label(cr, l1, "L(P1,P2)");
+ draw_label(cr, l2, "L(O,angle)");
+ }
+
+
+ void init_projection()
+ {
+ init_common();
+ p1.pos = Point(400, 50);
+ p2.pos = Point(450, 450);
+ p3.pos = Point(100, 250);
+ p4.pos = Point(200, 450);
+ O.pos = Point(50, 150);
+
+ handles.push_back(&p1);
+ handles.push_back(&p2);
+ handles.push_back(&p3);
+ handles.push_back(&p4);
+ handles.push_back(&O);
+ }
+
+ void draw_projection(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+
+ Line l1(p1.pos, p2.pos);
+ LineSegment ls(p3.pos, p4.pos);
+
+ Point np = projection(O.pos, l1);
+ LineSegment lsp = projection(ls, l1);
+
+ cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, 1.0);
+ cairo_set_line_width(cr, 0.2);
+ draw_line(cr, l1);
+ draw_segment(cr, ls);
+ cairo_stroke(cr);
+
+ cairo_set_line_width(cr, 0.3);
+ cairo_set_source_rgba(cr, 0.0, 0.0, 1.0, 1.0);
+ draw_segment(cr, lsp);
+ draw_handle(cr, lsp[0]);
+ draw_handle(cr, lsp[1]);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba(cr, 0.8, 0.0, 0.0, 1.0);
+ draw_circ(cr, np);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba(cr, 0.5, 0.5, 0.5, 1.0);
+ draw_label(cr, p1, "P1");
+ draw_label(cr, p2, "P2");
+ draw_label(cr, ls, "S");
+ draw_label(cr, lsp, "prj(S)");
+ draw_label(cr, O, "P");
+ draw_text(cr, np, "prj(P)");
+
+ cairo_stroke(cr);
+ }
+
+
+ void init_ortho()
+ {
+ init_common();
+ p1.pos = Point(400, 50);
+ p2.pos = Point(450, 450);
+ p3.pos = Point(100, 50);
+ p4.pos = Point(150, 450);
+
+ handles.push_back(&p1);
+ handles.push_back(&p2);
+ handles.push_back(&p3);
+ handles.push_back(&p4);
+ }
+
+ void draw_ortho(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+
+ Line l1(p1.pos, p2.pos);
+ Line l2 = make_orthogonal_line(p3.pos, l1);
+ Line l3 = make_parallel_line(p4.pos, l1);
+
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_set_line_width(cr, 0.3);
+ draw_line(cr, l1);
+ draw_line(cr, l2);
+ draw_line(cr, l3);
+ cairo_stroke(cr);
+
+ draw_label(cr, p1, "P1");
+ draw_label(cr, p2, "P2");
+ draw_label(cr, p3, "O1");
+ draw_label(cr, p4, "O2");
+
+ draw_label(cr, l1, "L");
+ draw_label(cr, l2, "L1 _|_ L");
+ draw_label(cr, l3, "L2 // L");
+
+ }
+
+
+ void init_distance()
+ {
+ init_common();
+ p1.pos = Point(400, 50);
+ p2.pos = Point(450, 450);
+ p3.pos = Point(100, 250);
+ p4.pos = Point(200, 450);
+ p5.pos = Point(50, 150);
+ p6.pos = Point(480, 60);
+ O.pos = Point(300, 300);
+
+ handles.push_back(&p1);
+ handles.push_back(&p2);
+ handles.push_back(&p3);
+ handles.push_back(&p4);
+ handles.push_back(&p5);
+ handles.push_back(&p6);
+ handles.push_back(&O);
+ }
+
+ void draw_distance(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+
+ Line l1(p1.pos, p2.pos);
+ LineSegment ls(p3.pos, p4.pos);
+ Ray r1(p5.pos, p6.pos);
+
+ Point q1 = l1.pointAt(l1.nearestTime(O.pos));
+ Point q2 = ls.pointAt(ls.nearestTime(O.pos));
+ Point q3 = r1.pointAt(r1.nearestTime(O.pos));
+
+ double d1 = distance(O.pos, l1);
+ double d2 = distance(O.pos, ls);
+ double d3 = distance(O.pos, r1);
+
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_set_line_width(cr, 0.3);
+ draw_line(cr, l1);
+ draw_segment(cr, ls);
+ draw_ray(cr, r1);
+ cairo_stroke(cr);
+
+
+ draw_label(cr, l1, "L");
+ draw_label(cr, ls, "S");
+ draw_label(cr, r1, "R");
+ draw_label(cr, O, "P");
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba(cr, 0.5, 0.5, 0.8, 1.0);
+ cairo_set_line_width(cr, 0.2);
+ draw_segment(cr, O.pos, q1);
+ draw_segment(cr, O.pos, q2);
+ draw_segment(cr, O.pos, q3);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba(cr, 0.8, 0.0, 0.0, 1.0);
+ cairo_set_line_width(cr, 0.3);
+ draw_handle(cr, q1);
+ draw_handle(cr, q2);
+ draw_handle(cr, q3);
+ cairo_stroke(cr);
+
+ *notify << " distance(P,L) = " << d1 << std::endl;
+ *notify << " distance(P,S) = " << d2 << std::endl;
+ *notify << " distance(P,R) = " << d3 << std::endl;
+ }
+
+
+ void init_position()
+ {
+ init_common();
+ p1.pos = Point(400, 50);
+ p2.pos = Point(450, 450);
+ p3.pos = Point(100, 50);
+ p4.pos = Point(150, 450);
+
+ handles.push_back(&p1);
+ handles.push_back(&p2);
+ handles.push_back(&p3);
+ handles.push_back(&p4);
+ }
+
+ void draw_position(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+
+ Line l1(p1.pos, p2.pos);
+ Line l2(p3.pos, p4.pos);
+
+ bool b1 = are_same(l1, l2, 0.01);
+ bool b2 = are_parallel(l1, l2, 0.01);
+ bool b3 = are_orthogonal(l1, l2, 0.01);
+
+ double a = angle_between(l1,l2);
+
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_set_line_width(cr, 0.3);
+ draw_line(cr, l1);
+ draw_line(cr, l2);
+ cairo_stroke(cr);
+
+ draw_label(cr, l1, "A");
+ draw_label(cr, l2, "B");
+ cairo_stroke(cr);
+
+ if (b1)
+ {
+ *notify << " A is coincident with B" << std::endl;
+ }
+ else if (b2)
+ {
+ *notify << " A is parallel to B" << std::endl;
+ }
+ else if (b3)
+ {
+ *notify << " A is orthogonal to B" << std::endl;
+ }
+ else
+ {
+ *notify << " A is incident with B: angle(A,B) = " << angle_formatter(a) << std::endl;
+ }
+ }
+
+
+ void init_seg_bisec()
+ {
+ init_common();
+ p1.pos = Point(100, 50);
+ p2.pos = Point(150, 450);
+
+ handles.push_back(&p1);
+ handles.push_back(&p2);
+ }
+
+ void draw_seg_bisec(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+
+ LineSegment ls(p1.pos, p2.pos);
+ Line l = make_bisector_line(ls);
+ Point M = middle_point(p1.pos, p2.pos);
+
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_set_line_width(cr, 0.3);
+ draw_label(cr, p1, "P");
+ draw_label(cr, p2, "Q");
+ draw_label(cr, M, "M");
+ draw_segment(cr, ls);
+ draw_line(cr, l);
+ cairo_stroke(cr);
+
+ draw_label(cr, l, "axis");
+ cairo_stroke(cr);
+ }
+
+
+ void init_angle_bisec()
+ {
+ init_common();
+ p1.pos = Point(100, 50);
+ p2.pos = Point(150, 450);
+ O.pos = Point(50, 200);
+
+ handles.push_back(&p1);
+ handles.push_back(&p2);
+ handles.push_back(&O);
+ }
+
+ void draw_angle_bisec(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+
+ Ray r1(O.pos, p1.pos);
+ Ray r2(O.pos, p2.pos);
+ Ray rb = make_angle_bisector_ray(r1, r2);
+
+ double a1 = angle_between(r1,rb);
+ double a2 = angle_between(rb,r2);
+
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_set_line_width(cr, 0.3);
+ draw_label(cr, O, "O");
+ draw_ray(cr, r1);
+ draw_ray(cr, r2);
+ draw_ray(cr, rb);
+ cairo_stroke(cr);
+
+ draw_label(cr, r1, "R1");
+ draw_label(cr, r2, "R2");
+ draw_label(cr, rb, "bisector ray");
+
+ *notify << " angle(R1, bisector ray) = " << angle_formatter(a1)
+ << " angle(bisector ray, R2) = " << angle_formatter(a2)
+ << std::endl;
+ }
+
+
+ void init_collinear()
+ {
+ init_common();
+ p1.pos = Point(100, 50);
+ p2.pos = Point(450, 450);
+ p3.pos = Point(400, 50);
+
+ handles.push_back(&p1);
+ handles.push_back(&p2);
+ handles.push_back(&p3);
+ }
+
+ void draw_collinear(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+
+ Point A = p1.pos;
+ Point B = p2.pos;
+ Point C = p3.pos;
+
+ LineSegment AB(A, B);
+ LineSegment BC(B, C);
+ Line l(A, C);
+
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_set_line_width(cr, 0.3);
+ draw_label(cr, p1, "A");
+ draw_label(cr, p2, "B");
+ draw_label(cr, p3, "C");
+ cairo_stroke(cr);
+
+
+ double turn = cross(C, B) - cross(C, A) + cross(B, A);
+ //*notify << " turn: " << turn << std::endl;
+
+ bool collinear = are_collinear(A, B, C, 200);
+ if (collinear)
+ {
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_set_line_width(cr, 0.3);
+ draw_line(cr, l);
+ cairo_stroke(cr);
+ *notify << " A,B,C are collinear!" << std::endl;
+ }
+ else
+ {
+ cairo_set_source_rgba(cr, 0.5, 0.5, 0.8, 1.0);
+ cairo_set_line_width(cr, 0.2);
+ draw_segment(cr, AB);
+ draw_segment(cr, BC);
+ cairo_stroke(cr);
+ if (turn < 0)
+ *notify << " A,B,C is a left turn: " << turn << std::endl;
+ else
+ *notify << " A,B,C is a right turn: " << turn << std::endl;
+ }
+
+ }
+
+
+ void init_intersections()
+ {
+ init_common();
+ p1.pos = Point(400, 50);
+ p2.pos = Point(450, 450);
+ p3.pos = Point(100, 250);
+ p4.pos = Point(200, 450);
+ p5.pos = Point(50, 150);
+ p6.pos = Point(480, 60);
+
+ handles.push_back(&p1);
+ handles.push_back(&p2);
+ handles.push_back(&p3);
+ handles.push_back(&p4);
+ handles.push_back(&p5);
+ handles.push_back(&p6);
+ }
+
+ void draw_intersections(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+
+ Line l1(p1.pos, p2.pos);
+ Ray r1(p3.pos, p4.pos);
+ LineSegment s1(p5.pos, p6.pos);
+
+ std::vector<ShapeIntersection> cl1r1 = l1.intersect(r1);
+ std::vector<ShapeIntersection> cl1s1 = l1.intersect(s1);
+ std::vector<ShapeIntersection> cr1s1 = Line(r1).intersect(s1);
+ filter_ray_intersections(cr1s1, true, false);
+
+ std::vector<Point> ip;
+
+ if (!cl1r1.empty()) {
+ ip.push_back(l1.pointAt(cl1r1[0].first));
+ }
+ if (!cl1s1.empty()) {
+ ip.push_back(l1.pointAt(cl1s1[0].first));
+ }
+ if (!cr1s1.empty()) {
+ ip.push_back(r1.pointAt(cr1s1[0].first));
+ }
+
+ cairo_set_source_rgba(cr, 0.2, 0.2, 0.2, 1.0);
+ cairo_set_line_width(cr, 0.3);
+ draw_line(cr, l1);
+ draw_ray(cr, r1);
+ draw_segment(cr, s1);
+ cairo_stroke(cr);
+
+
+ draw_label(cr, l1, "L");
+ draw_label(cr, r1, "R");
+ draw_label(cr, s1, "S");
+ cairo_stroke(cr);
+
+ std::string label("A");
+ cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 1.0);
+ cairo_set_line_width(cr, 0.5);
+ for (auto & i : ip)
+ {
+ draw_handle(cr, i);
+ draw_text(cr, i+op, label.c_str());
+ label[0] += 1;
+ }
+ cairo_stroke(cr);
+
+ }
+
+
+ void init_coefficients()
+ {
+ init_common();
+ p1.pos = Point(400, 50);
+ p2.pos = Point(450, 450);
+
+ Line l(p1.pos, p2.pos);
+ std::vector<double> coeff = l.coefficients();
+ sliders.emplace_back(-1, 1, 0, coeff[0], "A");
+ sliders.emplace_back(-1, 1, 0, coeff[1], "B");
+ sliders.emplace_back(-500, 500, 0, coeff[2], "C");
+
+ handles.push_back(&p1);
+ handles.push_back(&p2);
+ handles.push_back(&(sliders[A_COEFF_SLIDER]));
+ handles.push_back(&(sliders[B_COEFF_SLIDER]));
+ handles.push_back(&(sliders[C_COEFF_SLIDER]));
+ }
+
+ void draw_coefficients(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+ init_coefficients_ctrl_geom(cr, notify, width, height);
+
+ Line l1(p1.pos, p2.pos);
+ std::vector<double> coeff1 = l1.coefficients();
+ Line l2(sliders[A_COEFF_SLIDER].value(),
+ sliders[B_COEFF_SLIDER].value(),
+ sliders[C_COEFF_SLIDER].value());
+
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_set_line_width(cr, 0.8);
+ draw_line(cr, l1);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 1.0);
+ cairo_set_line_width(cr, 0.4);
+ draw_line(cr, l2);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ draw_label(cr, p1, "P");
+ draw_label(cr, p2, "Q");
+ //draw_label(cr, l1, "L(P,Q)");
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 1.0);
+ draw_label(cr, l2, "L(A, B, C)");
+ cairo_stroke(cr);
+
+ *notify << " L(P,Q): a = " << coeff1[0]
+ << ", b = " << coeff1[1]
+ << ", c = " << coeff1[2] << std::endl;
+
+ }
+
+ void init_segment_inside()
+ {
+ init_common();
+ p1.pos = Point(200, 300);
+ p2.pos = Point(400, 200);
+ p3.pos = Point(250, 200);
+ p4.pos = Point(350, 300);
+
+ handles.push_back(&p1);
+ handles.push_back(&p2);
+ handles.push_back(&p3);
+ handles.push_back(&p4);
+ }
+
+ void draw_segment_inside(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+ Line l(p1.pos, p2.pos);
+ Rect r(p3.pos, p4.pos);
+
+ cairo_set_source_rgba(cr, 0, 0, 0, 1);
+ cairo_set_line_width(cr, 0.5);
+ draw_line(cr, l);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba(cr, 0, 0, 1, 1);
+ cairo_rectangle(cr, r);
+ cairo_stroke(cr);
+
+ std::optional<LineSegment> seg = l.clip(r);
+ if (seg) {
+ cairo_set_source_rgba(cr, 1, 0, 0, 1);
+ draw_line_seg(cr, seg->initialPoint(), seg->finalPoint());
+ cairo_stroke(cr);
+ }
+ }
+
+
+ void init_common_ctrl_geom(cairo_t* /*cr*/, int /*width*/, int /*height*/, std::ostringstream* /*notify*/)
+ {
+ if ( set_common_control_geometry )
+ {
+ set_common_control_geometry = false;
+ }
+ }
+
+ void init_create_ctrl_geom(cairo_t* /*cr*/, std::ostringstream* /*notify*/, int /*width*/, int height)
+ {
+ if ( set_control_geometry )
+ {
+ set_control_geometry = false;
+
+ sliders[ANGLE_SLIDER].geometry(Point(50, height - 50), 180);
+ }
+ }
+
+ void init_coefficients_ctrl_geom(cairo_t* /*cr*/, std::ostringstream* /*notify*/, int /*width*/, int height)
+ {
+ if ( set_control_geometry )
+ {
+ set_control_geometry = false;
+
+ sliders[A_COEFF_SLIDER].geometry(Point(50, height - 160), 400);
+ sliders[B_COEFF_SLIDER].geometry(Point(50, height - 110), 400);
+ sliders[C_COEFF_SLIDER].geometry(Point(50, height - 60), 400);
+ }
+ }
+
+
+ void draw_segment(cairo_t* cr, Point const& p1, Point const& p2)
+ {
+ cairo_move_to(cr, p1);
+ cairo_line_to(cr, p2);
+ }
+
+ void draw_segment(cairo_t* cr, Point const& p1, double angle, double length)
+ {
+ Point p2;
+ p2[X] = length * std::cos(angle);
+ p2[Y] = length * std::sin(angle);
+ p2 += p1;
+ draw_segment(cr, p1, p2);
+ }
+
+ void draw_segment(cairo_t* cr, LineSegment const& ls)
+ {
+ draw_segment(cr, ls[0], ls[1]);
+ }
+
+ void draw_ray(cairo_t* cr, Ray const& r)
+ {
+ double angle = r.angle();
+ draw_segment(cr, r.origin(), angle, m_length);
+ }
+
+ void draw_line(cairo_t* cr, Line const& l)
+ {
+ double angle = l.angle();
+ draw_segment(cr, l.origin(), angle, m_length);
+ draw_segment(cr, l.origin(), angle, -m_length);
+ }
+
+ void draw_label(cairo_t* cr, PointHandle const& ph, const char* label)
+ {
+ draw_text(cr, ph.pos+op, label);
+ }
+
+ void draw_label(cairo_t* cr, Line const& l, const char* label)
+ {
+ draw_text(cr, projection(Point(m_width/2-30, m_height/2-30), l)+op, label);
+ }
+
+ void draw_label(cairo_t* cr, LineSegment const& ls, const char* label)
+ {
+ draw_text(cr, middle_point(ls[0], ls[1])+op, label);
+ }
+
+ void draw_label(cairo_t* cr, Ray const& r, const char* label)
+ {
+ Point prj = r.pointAt(r.nearestTime(Point(m_width/2-30, m_height/2-30)));
+ if (L2(r.origin() - prj) < 100)
+ {
+ prj = r.origin() + 100*r.vector();
+ }
+ draw_text(cr, prj+op, label);
+ }
+
+ void init_menu()
+ {
+ handles.clear();
+ sliders.clear();
+ toggles.clear();
+ }
+
+ void draw_menu( cairo_t * /*cr*/, std::ostringstream *notify,
+ int /*width*/, int /*height*/, bool /*save*/,
+ std::ostringstream */*timer_stream*/ )
+ {
+ *notify << std::endl;
+ for (int i = SHOW_MENU; i < TOTAL_ITEMS; ++i)
+ {
+ *notify << " " << keys[i] << " - " << menu_items[i] << std::endl;
+ }
+ }
+
+ void key_hit(GdkEventKey *e) override
+ {
+ char choice = std::toupper(e->keyval);
+ switch ( choice )
+ {
+ case 'A':
+ init_menu();
+ draw_f = &LineToy::draw_menu;
+ break;
+ case 'B':
+ init_create();
+ draw_f = &LineToy::draw_create;
+ break;
+ case 'C':
+ init_projection();
+ draw_f = &LineToy::draw_projection;
+ break;
+ case 'D':
+ init_ortho();
+ draw_f = &LineToy::draw_ortho;
+ break;
+ case 'E':
+ init_distance();
+ draw_f = &LineToy::draw_distance;
+ break;
+ case 'F':
+ init_position();
+ draw_f = &LineToy::draw_position;
+ break;
+ case 'G':
+ init_seg_bisec();
+ draw_f = &LineToy::draw_seg_bisec;
+ break;
+ case 'H':
+ init_angle_bisec();
+ draw_f = &LineToy::draw_angle_bisec;
+ break;
+ case 'I':
+ init_collinear();
+ draw_f = &LineToy::draw_collinear;
+ break;
+ case 'J':
+ init_intersections();
+ draw_f = &LineToy::draw_intersections;
+ break;
+ case 'K':
+ init_coefficients();
+ draw_f = &LineToy::draw_coefficients;
+ break;
+ case 'L':
+ init_segment_inside();
+ draw_f = &LineToy::draw_segment_inside;
+ }
+ redraw();
+ }
+
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ m_width = width;
+ m_height = height;
+ m_length = (m_width > m_height) ? m_width : m_height;
+ m_length *= 2;
+ (this->*draw_f)(cr, notify, width, height, save, timer_stream);
+ Toy::draw(cr, notify, width, height, save, timer_stream);
+ }
+
+ public:
+ LineToy()
+ {
+ op = Point(5,5);
+ }
+
+ private:
+ typedef void (LineToy::* draw_func_t) (cairo_t*, std::ostringstream*, int, int, bool, std::ostringstream*);
+ draw_func_t draw_f;
+ bool set_common_control_geometry;
+ bool set_control_geometry;
+ PointHandle p1, p2, p3, p4, p5, p6, O;
+ std::vector<Toggle> toggles;
+ std::vector<Slider> sliders;
+ Point op;
+ double m_width, m_height, m_length;
+
+}; // end class LineToy
+
+
+const char* LineToy::menu_items[] =
+{
+ "show this menu",
+ "line generation",
+ "projection on a line",
+ "make orthogonal/parallel",
+ "distance",
+ "position",
+ "segment bisector",
+ "angle bisector",
+ "collinear",
+ "intersection",
+ "coefficients",
+ "segment inside"
+};
+
+const char LineToy::keys[] =
+{
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L'
+};
+
+
+
+int main(int argc, char **argv)
+{
+ init( argc, argv, new LineToy());
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/load-svgd.cpp b/src/3rdparty/2geom/src/toys/load-svgd.cpp
new file mode 100644
index 0000000..68b1495
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/load-svgd.cpp
@@ -0,0 +1,76 @@
+#include <2geom/path.h>
+#include <2geom/pathvector.h>
+#include <2geom/svg-path-parser.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <2geom/cairo-path-sink.h>
+#include <2geom/svg-path-writer.h>
+
+#include <cstdlib>
+
+using namespace Geom;
+
+/**
+ * @brief SVG path data loading toy.
+ *
+ * A very simple toy that loads a file containing raw SVG path data
+ * and displays it scaled so that it fits inside the window.
+ *
+ * Use this toy to see what the path data looks like without
+ * pasting it into the d= attribute of a path in Inkscape.
+ */
+class LoadSVGD: public Toy {
+ PathVector pv;
+ OptRect bounds;
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+
+ Rect viewport(Point(10, 10), Point(width-10, height-10));
+ PathVector res = pv * bounds->transformTo(viewport, Aspect(ALIGN_XMID_YMID));
+
+ CairoPathSink sink(cr);
+ sink.feed(res);
+
+ cairo_set_source_rgb(cr, 1, 0, 0);
+ cairo_fill_preserve(cr);
+ cairo_set_line_width(cr, 1);
+ cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_set_source_rgb(cr, 0,0,0);
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+ public:
+ LoadSVGD() {}
+
+ void first_time(int argc, char** argv) override {
+ const char *path_b_name="star.svgd";
+ if (argc > 1)
+ path_b_name = argv[1];
+ pv = read_svgd(path_b_name);
+ bounds = pv.boundsExact();
+ if (!bounds) {
+ std::cerr << "Empty path, aborting" << std::endl;
+ std::exit(1);
+ }
+ }
+};
+
+int main(int argc, char **argv) {
+ LoadSVGD x;
+ init(argc, argv, &x);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/load-svgd.py b/src/3rdparty/2geom/src/toys/load-svgd.py
new file mode 100644
index 0000000..26bcef3
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/load-svgd.py
@@ -0,0 +1,68 @@
+#!/usr/bin/python
+
+import py2geom
+import toyframework
+import random,gtk
+from py2geom_glue import *
+
+def cairo_region(cr, r):
+ cr.save()
+ cr.set_source_rgba(0, 0, 0, 1);
+ if not r.isFill():
+ pass#cr.set_dash([]1, 0)
+ cairo_path(cr, r)
+ cr.fill()
+ cr.restore()
+
+def cairo_regions(cr, p):
+ for j in p:
+ cairo_region(cr, j)
+
+def cairo_shape(cr, s):
+ cairo_regions(cr, s.getContent())
+
+
+
+def cleanup(ps):
+ pw = py2geom.paths_to_pw(ps)
+ centre, area = py2geom.centroid(pw)
+ if(area > 1):
+ return py2geom.sanitize(ps) * py2geom.Translate(-centre)
+ else:
+ return py2geom.sanitize(ps)
+
+class LoadSVGD(toyframework.Toy):
+ def __init__(self):
+ toyframework.Toy.__init__(self)
+ self.bs = []
+ self.offset_handle = toyframework.PointHandle(0,0)
+ self.handles.append(self.offset_handle)
+ def draw(self, cr, pos, save):
+ t = py2geom.Translate(*self.offset_handle.pos)
+ #self.paths_b[0] * t
+ m = py2geom.Matrix()
+ m.setIdentity()
+ bst = self.bs * (m * t)
+ #bt = Region(b * t, b.isFill())
+
+ cr.set_line_width(1)
+
+ cairo_shape(cr, bst)
+
+ toyframework.Toy.draw(self, cr, pos, save)
+
+ def first_time(self, argv):
+ path_b_name="star.svgd"
+ if len(argv) > 1:
+ path_b_name = argv[1]
+ self.paths_b = py2geom.read_svgd(path_b_name)
+
+ bounds = py2geom.bounds_exact(self.paths_b)
+ self.offset_handle.pos = bounds.midpoint() - bounds.corner(0)
+
+ self.bs = cleanup(self.paths_b)
+t = LoadSVGD()
+import sys
+
+toyframework.init(sys.argv, t, 500, 500)
+
diff --git a/src/3rdparty/2geom/src/toys/lpe-framework.cpp b/src/3rdparty/2geom/src/toys/lpe-framework.cpp
new file mode 100644
index 0000000..19f7267
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/lpe-framework.cpp
@@ -0,0 +1,128 @@
+/*
+ * A framework for writing an Inkscape Live Path Effect (LPE) toy.
+ *
+ * Copyright 2009 Johan Engelen <goejendaagh@zonnet.nl>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <string.h>
+#include <stdint.h>
+#include <toys/lpe-framework.h>
+
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/affine.h>
+#include <2geom/pathvector.h>
+
+#define LPE_CONVERSION_TOLERANCE 0.01
+
+/**
+ * When the input path handles are moved, this method is called to re-execute the LPE and draw the result.
+ */
+void LPEToy::draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream)
+{
+ using namespace Geom;
+
+ Piecewise<D2<SBasis> > pwd2(curve_handle.asBezier());
+ PathVector A = Geom::path_from_piecewise( pwd2, LPE_CONVERSION_TOLERANCE);
+ cairo_set_line_width (cr, 2);
+ cairo_set_source_rgba (cr, 1., 0.0, 0., 1);
+ cairo_path(cr, A);
+ cairo_stroke(cr);
+
+ // perform the effect:
+ PathVector B = doEffect_path(A);
+
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0., 0.0, 0., 1);
+ cairo_path(cr, B);
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+}
+
+/**
+ * Initializes the LPE toy, and sets a simple default input path.
+ */
+LPEToy::LPEToy(){
+ if(handles.empty()) {
+ handles.push_back(&curve_handle);
+ for(unsigned i = 0; i < 4; i++) {
+ curve_handle.push_back(150+uniform()*300,150+uniform()*300);
+ }
+ }
+}
+
+/*
+ * Here be the doEffect function chain: (this is copied code from Inkscape)
+ */
+Geom::PathVector
+LPEToy::doEffect_path (Geom::PathVector const &path_in)
+{
+ Geom::PathVector path_out;
+
+ if ( !concatenate_before_pwd2 ) {
+ // default behavior
+ for (const auto & i : path_in) {
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_in = i.toPwSb();
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_out = doEffect_pwd2(pwd2_in);
+ Geom::PathVector path = Geom::path_from_piecewise( pwd2_out, LPE_CONVERSION_TOLERANCE);
+ // add the output path vector to the already accumulated vector:
+ for (const auto & j : path) {
+ path_out.push_back(j);
+ }
+ }
+ } else {
+ // concatenate the path into possibly discontinuous pwd2
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_in;
+ for (const auto & i : path_in) {
+ pwd2_in.concat( i.toPwSb() );
+ }
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_out = doEffect_pwd2(pwd2_in);
+ path_out = Geom::path_from_piecewise( pwd2_out, LPE_CONVERSION_TOLERANCE);
+ }
+
+ return path_out;
+}
+
+Geom::Piecewise<Geom::D2<Geom::SBasis> >
+LPEToy::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
+{
+ // default effect does nothing
+ return pwd2_in;
+}
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+ */
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/lpe-test.cpp b/src/3rdparty/2geom/src/toys/lpe-test.cpp
new file mode 100644
index 0000000..ff397c0
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/lpe-test.cpp
@@ -0,0 +1,93 @@
+/**
+ * \file lpe-test.cpp
+ * \brief Example file showing how to write an Inkscape Live Path Effect toy.
+ */
+/*
+ * Copyright 2009 Johan Engelen <goejendaagh@zonnet.nl>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <toys/lpe-framework.h>
+
+// This is usually very bad practice: don't do it in your LPE
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+class LPETest: public LPEToy {
+public:
+ LPETest() {
+ concatenate_before_pwd2 = false;
+ }
+
+ Geom::Piecewise<Geom::D2<Geom::SBasis> >
+ doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in) override
+ {
+ using namespace Geom;
+
+ Piecewise<D2<SBasis> > pwd2_out = pwd2_in;
+
+ Point vector(50,100);
+ // generate extrusion bottom: (just a copy of original path, displaced a bit)
+ pwd2_out.concat( pwd2_in + vector );
+
+ // generate connecting lines (the 'sides' of the extrusion)
+ Path path(Point(0.,0.));
+ path.appendNew<Geom::LineSegment>( vector );
+ Piecewise<D2<SBasis> > connector = path.toPwSb();
+ // connecting lines should be put at cusps
+ Piecewise<D2<SBasis> > deriv = derivative(pwd2_in);
+ std::vector<double> cusps; // = roots(deriv);
+ for (double cusp : cusps) {
+ pwd2_out.concat( connector + pwd2_in.valueAt(cusp) );
+ }
+ // connecting lines should be put where the tangent of the path equals the extrude_vector in direction
+ std::vector<double> rts = roots(dot(deriv, rot90(vector)));
+ for (double rt : rts) {
+ pwd2_out.concat( connector + pwd2_in.valueAt(rt) );
+ }
+
+ return pwd2_out;
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new LPETest);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+//vim:expandtab:shiftwidth = 4:tabstop = 8:softtabstop = 4:encoding = utf-8:textwidth = 99 :
+
+
diff --git a/src/3rdparty/2geom/src/toys/match-curve.cpp b/src/3rdparty/2geom/src/toys/match-curve.cpp
new file mode 100644
index 0000000..60e81a5
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/match-curve.cpp
@@ -0,0 +1,162 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/path.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#define ZROOTS_TEST 0
+#if ZROOTS_TEST
+#include <2geom/zroots.c>
+#endif
+
+#include <vector>
+using std::vector;
+using namespace Geom;
+
+//#define HAVE_GSL
+
+template <typename T>
+void shift(T &a, T &b, T const &c) {
+ a = b;
+ b = c;
+}
+template <typename T>
+void shift(T &a, T &b, T &c, T const &d) {
+ a = b;
+ b = c;
+ c = d;
+}
+
+extern unsigned total_steps, total_subs;
+
+class MatchCurve: public Toy {
+public:
+ double timer_precision;
+ double units;
+ PointSetHandle psh;
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgb(cr, 0,0,0);
+ std::vector<Geom::Point> trans;
+ trans.resize(psh.size());
+ for(unsigned i = 0; i < psh.size(); i++) {
+ trans[i] = psh.pts[i] - Geom::Point(0, 3*width/4);
+ }
+
+ std::vector<double> solutions;
+
+ D2<SBasis> test_sb = psh.asBezier();
+
+
+ D2<SBasis> B = psh.asBezier();
+ Geom::Path pb;
+ pb.append(B);
+ pb.close(false);
+ cairo_path(cr, pb);
+ cairo_stroke(cr);
+
+ D2<SBasis> m;
+ D2<SBasis> dB = derivative(B);
+ D2<SBasis> ddB = derivative(dB);
+ D2<SBasis> dddB = derivative(ddB);
+
+ Geom::Point pt = B(0);
+ Geom::Point tang = dB(0);
+ Geom::Point dtang = ddB(0);
+ Geom::Point ddtang = dddB(0);
+ for(int dim = 0; dim < 2; dim++) {
+ m[dim] = Linear(pt[dim],pt[dim]+tang[dim]);
+ m[dim] += Linear(0, 1)*Linear(0, 1*dtang[dim])/2;
+ m[dim] += Linear(0, 1)*Linear(0, 1)*Linear(0, ddtang[dim])/6;
+ }
+
+ double lo = 0, hi = 1;
+ double eps = 5;
+ while(hi - lo > 0.0001) {
+ double mid = (hi + lo)/2;
+ //double Bmid = (Bhi + Blo)/2;
+
+ m = truncate(compose(B, Linear(0, mid)), 2);
+ // perform golden section search
+ double best_f = 0, best_x = 1;
+ for(int n = 2; n < 4; n++) {
+ Geom::Point m_pt = m(double(n)/6);
+ double x0 = 0, x3 = 1.; // just a guess!
+ const double R = 0.61803399;
+ const double C = 1 - R;
+ double x1 = C*x0 + R*x3;
+ double x2 = C*x1 + R*x3;
+ double f1 = Geom::distance(m_pt, B(x1));
+ double f2 = Geom::distance(m_pt, B(x2));
+ while(fabs(x3 - x0) > 1e-3*(fabs(x1) + fabs(x2))) {
+ if(f2 < f1) {
+ shift(x0, x1, x2, R*x1 + C*x3);
+ shift(f1, f2, Geom::distance(m_pt, B(x2)));
+ } else {
+ shift(x3, x2, x1, R*x2 + C*x0);
+ shift(f2, f1, Geom::distance(m_pt, B(x2)));
+ }
+ std::cout << x0 << ","
+ << x1 << ","
+ << x2 << ","
+ << x3 << ","
+ << std::endl;
+ }
+ if(f2 < f1) {
+ f1 = f2;
+ x1 = x2;
+ }
+ if(f1 > best_f) {
+ best_f = f1;
+ best_x = x1;
+ }
+ }
+ std::cout << mid << ":" << best_x << "->" << best_f << std::endl;
+ //draw_cross(cr, point_at(B, x1));
+
+ if(best_f > eps) {
+ hi = mid;
+ } else {
+ lo = mid;
+ }
+ }
+ std::cout << std::endl;
+ //draw_cross(cr, point_at(B, hi));
+ draw_circ(cr, m(hi));
+ {
+ Geom::Path pb;
+ pb.append(m);
+ pb.close(false);
+ cairo_path(cr, pb);
+ }
+
+ cairo_stroke(cr);
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+ MatchCurve() : timer_precision(0.1), units(1e6) // microseconds
+ {
+ handles.push_back(&psh);
+ for(int i = 0; i < 6; i++)
+ psh.push_back(uniform()*400, uniform()*400);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new MatchCurve());
+
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/mesh-grad.cpp b/src/3rdparty/2geom/src/toys/mesh-grad.cpp
new file mode 100644
index 0000000..c71f5f0
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/mesh-grad.cpp
@@ -0,0 +1,134 @@
+/**
+ * Generate approximate mesh gradients for blurring technique suggested by bbyak.
+ * (njh)
+ */
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/path.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+
+#include <vector>
+using std::vector;
+using namespace Geom;
+
+unsigned total_pieces_sub;
+unsigned total_pieces_inc;
+
+const double u_subs = 5,
+ v_subs = 5,
+ fudge = .01;
+
+const double inv_u_subs = 1 / u_subs,
+ inv_v_subs = 1 / v_subs;
+
+class Sb2d2: public Toy {
+public:
+ PointSetHandle hand;
+ Sb2d2() {
+ handles.push_back(&hand);
+ }
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ D2<SBasis2d> sb2;
+ for(unsigned dim = 0; dim < 2; dim++) {
+ sb2[dim].us = 2;
+ sb2[dim].vs = 2;
+ const int depth = sb2[dim].us*sb2[dim].vs;
+ sb2[dim].resize(depth, Linear2d(0));
+ }
+ Geom::Point dir(1,-2);
+ if(hand.pts.empty()) {
+ for(unsigned vi = 0; vi < sb2[0].vs; vi++)
+ for(unsigned ui = 0; ui < sb2[0].us; ui++)
+ for(unsigned iv = 0; iv < 2; iv++)
+ for(unsigned iu = 0; iu < 2; iu++)
+ hand.pts.emplace_back((2*(iu+ui)/(2.*ui+1)+1)*width/4.,
+ (2*(iv+vi)/(2.*vi+1)+1)*width/4.);
+
+ }
+
+ for(int dim = 0; dim < 2; dim++) {
+ Geom::Point dir(0,0);
+ dir[dim] = 1;
+ for(unsigned vi = 0; vi < sb2[dim].vs; vi++)
+ for(unsigned ui = 0; ui < sb2[dim].us; ui++)
+ for(unsigned iv = 0; iv < 2; iv++)
+ for(unsigned iu = 0; iu < 2; iu++) {
+ unsigned corner = iu + 2*iv;
+ unsigned i = ui + vi*sb2[dim].us;
+ Geom::Point base((2*(iu+ui)/(2.*ui+1)+1)*width/4.,
+ (2*(iv+vi)/(2.*vi+1)+1)*width/4.);
+ if(vi == 0 && ui == 0) {
+ base = Geom::Point(width/4., width/4.);
+ }
+ double dl = dot((hand.pts[corner+4*i] - base), dir)/dot(dir,dir);
+ sb2[dim][i][corner] = dl/(width/2)*pow(4.0,(double)ui+vi);
+ }
+ }
+ cairo_d2_sb2d(cr, sb2, dir*0.1, width);
+ cairo_set_source_rgba (cr, 0., 0., 0, 0.5);
+ cairo_stroke(cr);
+ for(unsigned vi = 0; vi < v_subs; vi++) {
+ double tv = vi * inv_v_subs;
+ for(unsigned ui = 0; ui < u_subs; ui++) {
+ double tu = ui * inv_u_subs;
+
+ Geom::Path pb;
+ D2<SBasis> B;
+ D2<SBasis> tB;
+
+ B[0] = Linear(tu-fudge, tu+fudge + inv_u_subs );
+ B[1] = Linear(tv-fudge, tv-fudge);
+ tB = compose_each(sb2, B);
+ tB = tB*(width/2) + Geom::Point(width/4, width/4);
+ pb.append(tB);
+
+ B[0] = Linear(tu+fudge + inv_u_subs , tu+fudge + inv_u_subs);
+ B[1] = Linear(tv-fudge, tv+fudge + inv_v_subs);
+ tB = compose_each(sb2, B);
+ tB = tB*(width/2) + Geom::Point(width/4, width/4);
+ pb.append(tB);
+
+ B[0] = Linear(tu+fudge + inv_u_subs, tu-fudge);
+ B[1] = Linear(tv+fudge + inv_v_subs, tv+fudge + inv_v_subs);
+ tB = compose_each(sb2, B);
+ tB = tB*(width/2) + Geom::Point(width/4, width/4);
+ pb.append(tB);
+
+ B[0] = Linear(tu-fudge, tu-fudge);
+ B[1] = Linear(tv+fudge + inv_v_subs, tv-fudge);
+ tB = compose_each(sb2, B);
+ tB = tB*(width/2) + Geom::Point(width/4, width/4);
+ pb.append(tB);
+
+ cairo_path(cr, pb);
+
+ //std::cout << pb.peek().end() - pb.peek().begin() << std::endl;
+ cairo_set_source_rgba (cr, tu, tv, 0, 1);
+ cairo_fill(cr);
+ }
+ }
+ //*notify << "bo = " << sb2.index(0,0);
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new Sb2d2);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/metro.cpp b/src/3rdparty/2geom/src/toys/metro.cpp
new file mode 100644
index 0000000..5d2804c
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/metro.cpp
@@ -0,0 +1,922 @@
+/** Generates approximate metromap lines
+ * Copyright njh
+ * Copyright Tim Dwyer
+ * Published in ISVC 2008, Las Vegas, Nevada, USA
+ */
+
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+#include <cmath>
+
+#include <gtk/gtk.h>
+#include <cassert>
+#include <algorithm>
+#include <sstream>
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <string>
+#include <map>
+#include <cairo-pdf.h>
+#include <2geom/point.h>
+#include <2geom/geom.h>
+#include <toys/toy-framework-2.h>
+
+using std::string;
+using std::vector;
+using std::pair;
+using std::make_pair;
+using std::ifstream;
+using std::map;
+using std::cout;
+using std::endl;
+using namespace Geom;
+
+vector<vector<Point> > paths;
+
+class sufficient_stats{
+public:
+ double Sx, Sy, Sxx, Syy, Sxy;
+ double n;
+
+ sufficient_stats() : Sx(0), Sy(0), Sxx(0), Syy(0), Sxy(0), n(0) {}
+ void
+ operator+=(Point p) {
+ Sx += p[0];
+ Sy += p[1];
+ Sxx += p[0]*p[0];
+ Syy += p[1]*p[1];
+ Sxy += p[0]*p[1];
+ n += 1.0;
+ }
+ void
+ operator-=(Point p) {
+ Sx -= p[0];
+ Sy -= p[1];
+ Sxx -= p[0]*p[0];
+ Syy -= p[1]*p[1];
+ Sxy -= p[0]*p[1];
+ n -= 1.0;
+ }
+ /*** What is the best regression we can do? . */
+ Point best_normal() {
+ return rot90(unit_vector(Point(n*Sxx - Sx*Sx,
+ n*Sxy - Sx*Sy)));
+ }
+ /*** Compute the best line for the points, given normal. */
+ double best_line(Point normal, const double dist,
+ double & mean) {
+ mean = (normal[0]*Sx + normal[1]*Sy);
+ return normal[0]*normal[0]*Sxx
+ + normal[1]*normal[1]*Syy
+ + 2*normal[0]*normal[1]*Sxy
+ - 2*dist*mean + n*dist*dist;
+ }
+ /*** Returns the index to the angle in angles that has the line of best fit
+ * passing through mean */
+ unsigned best_schematised_line(vector<Point>& angles, Point p,
+ double & /*mean*/, double & cost) {
+ cost = DBL_MAX;
+ unsigned bestAngle = 0;
+ for(unsigned i=0;i<angles.size();i++) {
+ Point n = unit_vector(rot90(angles[i]));
+ double dist = dot(n, p);
+ double mean;
+ double bl = best_line(n, dist, mean);
+ if(bl < cost) {
+ cost = bl;
+ bestAngle = i;
+ }
+ }
+ return bestAngle;
+ }
+ /*** Compute the best line for the points, given normal. */
+ double best_angled_line(Point normal,
+ double & mean) {
+ mean = (normal[0]*Sx + normal[1]*Sy);
+ double dist = mean/n;
+ return normal[0]*normal[0]*Sxx
+ + normal[1]*normal[1]*Syy
+ + 2*normal[0]*normal[1]*Sxy
+ - 2*dist*mean + n*dist*dist;
+ }
+};
+
+sufficient_stats
+operator+(sufficient_stats const & a, sufficient_stats const &b) {
+ sufficient_stats ss;
+ ss.Sx = a.Sx + b.Sx;
+ ss.Sy = a.Sy + b.Sy;
+ ss.Sxx = a.Sxx + b.Sxx;
+ ss.Sxy = a.Sxy + b.Sxy;
+ ss.Syy = a.Syy + b.Syy;
+ ss.n = a.n + b.n;
+ return ss;
+}
+
+sufficient_stats
+operator-(sufficient_stats const & a, sufficient_stats const &b) {
+ sufficient_stats ss;
+ ss.Sx = a.Sx - b.Sx;
+ ss.Sy = a.Sy - b.Sy;
+ ss.Sxx = a.Sxx - b.Sxx;
+ ss.Sxy = a.Sxy - b.Sxy;
+ ss.Syy = a.Syy - b.Syy;
+ ss.n = a.n - b.n;
+ return ss;
+}
+
+inline std::ostream &operator<< (std::ostream &out_file, const sufficient_stats &s) {
+ out_file << "Sx: " << s.Sx
+ << "Sy: " << s.Sy
+ << "Sxx: " << s.Sxx
+ << "Sxy: " << s.Sxy
+ << "Syy: " << s.Syy
+ << "n: " << s.n;
+ return out_file;
+}
+
+
+
+class fit{
+public:
+ vector<Point> input;
+ vector<Point> solution;
+
+ vector<pair<Point,Point> > lines;
+ vector<int> thickness;
+
+ void
+ draw(cairo_t* cr) {
+ /*
+ if(solution.size() > 1) {
+ //cairo_set_line_width (cr, 1);
+ cairo_move_to(cr, solution[0]);
+ for(unsigned i = 1; i < solution.size(); i++) {
+ cairo_line_to(cr, solution[i]);
+ }
+ }
+ */
+ //cairo_stroke(cr);
+ for(unsigned i = 0;i<lines.size();i++) {
+ if(thickness.size()>i) {
+ cairo_set_line_width (cr, thickness[i]);
+ }
+ cairo_move_to(cr, lines[i].first);
+ cairo_line_to(cr, lines[i].second);
+ cairo_stroke(cr);
+ }
+ }
+
+ void endpoints() {
+ solution.push_back(input[0]);
+ solution.push_back(input.back());
+ }
+
+ void arbitrary();
+ void linear_reg();
+
+ // sufficient stats from start to each point
+ vector<sufficient_stats> ac_ss;
+
+ /*** Compute the least squares error for a line between two points on the line. */
+ double measure(unsigned from, unsigned to, double & mean) {
+ sufficient_stats ss = ac_ss[to+1] - ac_ss[from];
+
+ Point n = unit_vector(rot90(input[to] - input[from]));
+ double dist = dot(n, input[from]);
+ return ss.best_line(n, dist, mean);
+ }
+
+ /*** Compute the best line for the points, given normal. */
+ double best_angled_line(unsigned from, unsigned to,
+ Point n,
+ double & mean) {
+ sufficient_stats ss = ac_ss[to+1] - ac_ss[from];
+ return ss.best_angled_line(n, mean);
+ }
+
+ double simple_measure(unsigned from, unsigned to, double & mean) {
+ Point n = unit_vector(rot90(input[to] - input[from]));
+ double dist = dot(n, input[from]); // distance from origin
+ double error = 0;
+ mean = 0;
+ for(unsigned l = from; l <= to; l++) {
+ double d = dot(input[l], n) - dist;
+ mean += dot(input[l], n);
+ error += d*d;
+ }
+ return error;
+ }
+
+ void simple_dp();
+ void C_simple_dp();
+
+ void C_endpoint();
+
+ vector<Geom::Point> angles;
+ fit(vector<Point> const & in)
+ :input(in) {
+ /*
+ Geom::Point as[] = {Point(0,1), Point(1,0), Point(1,1), Point(1,-1)};
+ for(unsigned c = 0; c < 4; c++) {
+ angles.push_back(unit_vector(as[c]));
+ }
+ */
+ sufficient_stats ss;
+ ss.Sx = ss.Sy = ss.Sxx = ss.Sxy = ss.Syy = 0;
+ ac_ss.push_back(ss);
+ for(auto & l : input) {
+ ss += l;
+ ac_ss.push_back(ss);
+ }
+ }
+
+ class block{
+ public:
+ unsigned next;
+ unsigned angle;
+ sufficient_stats ss;
+ double cost;
+ };
+ vector<block> blocks;
+ void test();
+ void merging_version();
+ void schematised_merging(unsigned number_of_directions);
+
+ double get_block_line(block& b, Point& d, Point& n, Point& c) {
+ n = unit_vector(rot90(d));
+ c = Point(b.ss.Sx/b.ss.n,b.ss.Sy/b.ss.n);
+ return 0;
+ }
+};
+
+class build_bounds{
+public:
+ int total_n;
+ Point starting[2];
+ Rect combined;
+ void add_point(Point const &P) {
+ if(total_n < 2) {
+ starting[total_n] = P;
+ total_n += 1;
+ if(total_n == 2)
+ combined = Rect(starting[0], starting[1]);
+ } else {
+ combined.expandTo(P);
+ total_n += 1;
+ }
+ }
+ OptRect result() const {
+ if(total_n > 1)
+ return combined;
+ return OptRect();
+ }
+ build_bounds() : total_n(0) {}
+};
+
+/**
+ * returns a point which is portionally between topleft and bottomright in the same way that p was
+ * in src.
+ */
+Point map_point(Point p, Rect src, Point topleft, Point bottomright) {
+ p -= src.min();
+ p[0] /= src[0].extent();
+ p[1] /= src[1].extent();
+ //cout << p << endl;
+ return Point(topleft[0]*(1-p[0]) + bottomright[0]*p[0],
+ topleft[1]*(1-p[1]) + bottomright[1]*p[1]);
+}
+
+void parse_data(vector<vector<Point> >& paths,
+ string location_file_name,
+ string path_file_name) {
+ ifstream location_file(location_file_name.c_str()),
+ path_file(path_file_name.c_str());
+ string id,sx,sy;
+ map<string,Point> idlookup;
+ build_bounds bld_bounds;
+ while (getline(location_file,id,','))
+ {
+ getline(location_file,sx,',');
+ getline(location_file,sy,'\n');
+ char *e;
+ // negative for coordinate system
+ Point p(strtod(sx.c_str(),&e), strtod(sy.c_str(),&e));
+ //cout << id << p << endl;
+ idlookup[id] = p;
+ }
+
+
+ string l;
+ while (getline(path_file,l,'\n')) {
+ vector<Point> ps;
+ if(l.size() < 2) continue; // skip blank lines
+ if(l.find(":",0)!=string::npos) continue; // skip labels
+ string::size_type p=0,q;
+ while((q=l.find(",",p))!=string::npos || (p < l.size() && (q = l.size()))) {
+ id = l.substr(p,q-p);
+ //cout << id << endl;
+ Point pt = 2*idlookup[id];
+ //cout << pt << endl;
+ bld_bounds.add_point(pt);
+ ps.push_back(pt);
+ p=q+1;
+ }
+ paths.push_back(ps);
+ //cout << "*******************************************" << endl;
+ }
+ Rect bounds = *bld_bounds.result();
+ //cout << bounds.min() << " - " << bounds.max() << endl;
+ for(auto & path : paths) {
+ for(auto & j : path) {
+ j = map_point(j, bounds,
+ Point(0,512), Point(512*bounds[0].extent()/bounds[1].extent(),0));
+ }
+ }
+ /*
+ for(map<string,Point>::iterator it = idlookup.begin();
+ it != idlookup.end(); it++) {
+ (*it).second = map_point((*it).second, bounds,
+ Point(0,0), Point(100,100));
+ //Point(0, 512), Point(512,0));
+ cout << (*it).first << ":" << (*it).second << endl;
+ }*/
+ /*
+ unsigned biggest = 0, biggest_i;
+ for(unsigned i=0;i<paths.size();i++) {
+ vector<Point> ps=paths[i];
+ if(ps.size()>biggest) {
+ biggest_i=i;
+ biggest = ps.size();
+ }
+ for(unsigned j=0;j<ps.size();j++) {
+ double x=ps[j][0], y=ps[j][1];
+ cout << "(" << x << "," << y << ")" << ",";
+ }
+ cout << endl;
+ }
+ */
+}
+
+void extremePoints(vector<Point> const & pts, Point const & dir,
+ Point & min, Point & max) {
+ double minProj = DBL_MAX, maxProj = -DBL_MAX;
+ for(auto pt : pts) {
+ double p = dot(pt,dir);
+ if(p < minProj) {
+ minProj = p;
+ min = pt;
+ }
+ if(p > maxProj) {
+ maxProj = p;
+ max = pt;
+ }
+ }
+}
+
+void fit::test() {
+ sufficient_stats ss;
+ const unsigned N = input.size();
+ for(unsigned i = 0; i < N; i++) {
+ ss += input[i];
+ }
+ double best_bl = DBL_MAX;
+ unsigned best = 0;
+ for(unsigned i=0;i<angles.size();i++) {
+ Point n = unit_vector(rot90(angles[i]));
+ double dist = dot(n, input[0]);
+ double mean;
+ double bl = ss.best_line(n, dist, mean);
+ if(bl < best_bl) {
+ best = i;
+ best_bl = bl;
+ }
+ mean/=N;
+ Point d = angles[i];
+ Point a = mean*n;
+ Point min, max;
+ extremePoints(input,d,min,max);
+ Point b = dot(min,d)*d;
+ Point c = dot(max,d)*d;
+ Point start = a+b;
+ Point end = a+c;
+ lines.emplace_back(start,end);
+ thickness.push_back(1);
+ }
+ thickness[best] = 4;
+}
+
+void fit::schematised_merging(unsigned number_of_directions) {
+ const double link_cost = 0;
+ const unsigned N = input.size()-1;
+ blocks.resize(N);
+ for(unsigned i = 0; i<number_of_directions ; i++) {
+ double t = M_PI*i/float(number_of_directions);
+ angles.emplace_back(cos(t),sin(t));
+ }
+ // pairs
+ for(unsigned i = 0; i < N; i++) {
+ block b;
+ sufficient_stats ss;
+ ss += input[i];
+ ss += input[i+1];
+ b.ss = ss;
+ double mean, newcost;
+ b.angle = ss.best_schematised_line(angles, input[i], mean, newcost);
+ b.cost = link_cost + newcost;
+ b.next = i+1;
+ blocks[i] = b;
+ //std::cout << ss
+ //<< std::endl;
+ }
+
+ // merge(a,b)
+ while(N>1)
+ {
+ block best_block;
+ unsigned best_idx = 0;
+ double best = 0;
+ unsigned beg = 0;
+ unsigned middle = blocks[beg].next;
+ unsigned end = blocks[middle].next;
+ while(middle < N) {
+ sufficient_stats ss = blocks[beg].ss + blocks[middle].ss;
+ //ss -= input[middle];
+ double mean, newcost;
+ unsigned bestAngle = ss.best_schematised_line(angles, input[beg], mean, newcost);
+ double deltaCost = -link_cost - blocks[beg].cost - blocks[middle].cost
+ + newcost;
+ /*std::cout << beg << ", "
+ << middle << ", "
+ << end << ", "
+ << deltaCost <<"; "
+ << newcost <<"; "
+ << mean << ": "
+ << ss
+ << std::endl;*/
+ //if(deltaCost < best) {
+ if(blocks[beg].angle==blocks[middle].angle) {
+ best = deltaCost;
+ best = -1;
+ best_idx = beg;
+ best_block.ss = ss;
+ best_block.cost = newcost;
+ best_block.next = end;
+ best_block.angle = bestAngle;
+ }
+ beg = middle;
+ middle = end;
+ end = blocks[end].next;
+ }
+ if(best < 0)
+ blocks[best_idx] = best_block;
+ else // no improvement possible
+ break;
+ }
+ {
+ solution.resize(0); // empty list
+ unsigned beg = 0;
+ unsigned prev = 0;
+ while(beg < N) {
+ block b = blocks[beg];
+ {
+ Point n, c;
+ Point n1, c1;
+ Point d = angles[b.angle];
+ get_block_line(b,d,n,c);
+ Point start = c, end = c+10*angles[b.angle];
+ Line ln = Line::from_normal_distance(n, dot(c,n));
+ if(beg==0) {
+ //start = intersection of b.line and
+ // line through input[0] orthogonal to b.line
+ OptCrossing c = intersection(ln,
+ Line::from_normal_distance(d, dot(d,input[0])));
+ assert(c);
+ start = ln.pointAt(c->ta);
+ //line_intersection(n, dot(c,n), d, dot(d,input[0]), start);
+ } else {
+ //start = intersection of b.line and blocks[prev].line
+ block p = blocks[prev];
+ if(b.angle!=p.angle) {
+ get_block_line(p,angles[p.angle],n1,c1);
+ //line_intersection(n, dot(c,n), n1, dot(c1,n1), start);
+ OptCrossing c = intersection(ln,
+ Line::from_normal_distance(n1, dot(c1,n1)));
+ assert(c);
+ start = ln.pointAt(c->ta);
+ }
+ }
+
+ if (b.next < N) {
+ //end = intersection of b.line and blocks[b.next].line
+ block next = blocks[b.next];
+ if(b.angle!=next.angle) {
+ get_block_line(next,angles[next.angle],n1,c1);
+ //line_intersection(n, dot(c,n), n1, dot(c1,n1), end);
+ OptCrossing c = intersection(ln,
+ Line::from_normal_distance(n1, dot(c1,n1)));
+ assert(c);
+ end = ln.pointAt(c->ta);
+ }
+ } else {
+ //end = intersection of b.line and
+ // line through input[N-1] orthogonal to b.line
+ //line_intersection(n, dot(c,n), d, dot(d,input[N]), end);
+ OptCrossing c = intersection(ln,
+ Line::from_normal_distance(d, dot(d,input[N])));
+ assert(c);
+ end = ln.pointAt(c->ta);
+ }
+ lines.emplace_back(start,end);
+ }
+ prev = beg;
+ beg = b.next;
+ }
+ }
+}
+void fit::merging_version() {
+ const double link_cost = 100;
+ const unsigned N = input.size();
+ blocks.resize(N);
+ // pairs
+ for(unsigned i = 0; i < N; i++) {
+ block b;
+ sufficient_stats ss;
+ ss.Sx = ss.Sy = ss.Sxx = ss.Sxy = ss.Syy = 0;
+ ss.n = 0;
+ ss += input[i];
+ ss += input[i+1];
+ b.ss = ss;
+ b.cost = link_cost;
+ b.next = i+1;
+ blocks[i] = b;
+ //std::cout << ss
+ //<< std::endl;
+ }
+
+ // merge(a,b)
+ while(1)
+ {
+ block best_block;
+ unsigned best_idx = 0;
+ double best = 0;
+ unsigned beg = 0;
+ unsigned middle = blocks[beg].next;
+ unsigned end = blocks[middle].next;
+ while(end != N) {
+ sufficient_stats ss = blocks[beg].ss + blocks[middle].ss;
+ ss -= input[middle];
+ double mean;
+ Point normal = unit_vector(rot90(input[end] - input[beg]));
+ double dist = dot(normal, input[beg]);
+ double newcost = ss.best_line(normal, dist, mean);
+ double deltaCost = -link_cost - blocks[beg].cost - blocks[middle].cost
+ + newcost;
+ /*std::cout << beg << ", "
+ << middle << ", "
+ << end << ", "
+ << deltaCost <<"; "
+ << newcost <<"; "
+ << mean << ": "
+ << ss
+ << std::endl;*/
+ if(deltaCost < best) {
+ best = deltaCost;
+ best_idx = beg;
+ best_block.ss = ss;
+ best_block.cost = newcost;
+ best_block.next = end;
+ }
+ beg = middle;
+ middle = end;
+ end = blocks[end].next;
+ }
+ if(best < 0)
+ blocks[best_idx] = best_block;
+ else // no improvement possible
+ break;
+ }
+ {
+ solution.resize(0); // empty list
+ unsigned beg = 0;
+ while(beg != N) {
+ solution.push_back(input[beg]);
+ beg = blocks[beg].next;
+ }
+ }
+}
+
+
+void fit::arbitrary() {
+ /*solution.resize(input.size());
+ copy(input.begin(), input.end(), solution.begin());*/
+ // normals
+
+ double best_error = INFINITY;
+ double best_mean = 0;
+ unsigned best_angle = 0;
+ for(unsigned i = 0; i < angles.size(); i++) {
+ Point angle = angles[i];
+ double mean = 0;
+ double error = 0;
+ for(unsigned l = 0; l < input.size(); l++) {
+ mean += dot(input[i], angle);
+ }
+ mean /= input.size();
+ for(unsigned l = 0; l < input.size(); l++) {
+ double d = dot(input[i], angle) - mean;
+ error += d*d;
+ }
+ if(error < best_error) {
+ best_mean = mean;
+ best_error = error;
+ best_angle = i;
+ }
+ }
+ Point angle = angles[best_angle];
+ solution.push_back(angle*best_mean + dot(input[0], rot90(angle))*rot90(angle));
+ solution.push_back(angle*best_mean + dot(input.back(), rot90(angle))*rot90(angle));
+}
+
+class reg_line{
+public:
+ Point parallel, centre, normal;
+ double Sr, Srr;
+ unsigned n;
+};
+
+template<class T>
+reg_line
+line_best_fit(T b, T e) {
+ double Sx = 0,
+ Sy = 0,
+ Sxx = 0,
+ Syy = 0,
+ Sxy = 0;
+ unsigned n = e - b;
+ reg_line rl;
+ rl.n = n;
+ for(T p = b; p != e; p++) {
+ Sx += (*p)[0];
+ Sy += (*p)[1];
+ Sxx += (*p)[0]*(*p)[0];
+ Syy += (*p)[1]*(*p)[1];
+ Sxy += (*p)[0]*(*p)[1];
+ }
+
+ rl.parallel = unit_vector(Point(n*Sxx - Sx*Sx,
+ n*Sxy - Sx*Sy));
+ rl.normal = rot90(rl.parallel);
+ rl.centre = Point(Sx/n, Sy/n);
+ rl.Sr = rl.Srr = 0;
+ for(T p = b; p != e; p++) {
+ double r = dot(rl.parallel, (*p) - rl.centre);
+ rl.Sr += fabs(r);
+ rl.Srr += r*r;
+ }
+ return rl;
+}
+
+void fit::linear_reg() {
+ reg_line rl = line_best_fit(input.begin(),
+ input.end());
+ solution.push_back(rl.centre + dot(rl.parallel, input[0] - rl.centre)*rl.parallel);
+ solution.push_back(rl.centre + dot(rl.parallel, input.back() - rl.centre)*rl.parallel);
+}
+
+void fit::simple_dp() {
+ const unsigned N = input.size();
+ vector<unsigned> prev(N);
+ vector<double> penalty(N);
+ const double bend_pen = 100;
+
+ for(unsigned i = 1; i < input.size(); i++) {
+ double mean;
+ double best = measure(0, i, mean);
+ unsigned best_prev = 0;
+ for(unsigned j = 1; j < i; j++) {
+ double err = penalty[j] + bend_pen + measure(j, i, mean);
+ if(err < best) {
+ best = err;
+ best_prev = j;
+ }
+ }
+ penalty[i] = best;
+ prev[i] = best_prev;
+ }
+
+ unsigned i = prev.size()-1;
+ while(i > 0) {
+ solution.push_back(input[i]);
+ i = prev[i];
+ }
+ solution.push_back(input[i]);
+ reverse(solution.begin(), solution.end());
+}
+
+void fit::C_endpoint() {
+ const unsigned N = input.size();
+
+ double best_mean;
+ double best = best_angled_line(0, N-1, angles[0], best_mean);
+ unsigned best_dir = 0;
+ for(unsigned c = 1; c < angles.size(); c++) {
+ double m;
+ double err = best_angled_line(0, N-1, angles[c], m);
+ if(err < best) {
+ best = err;
+ best_mean = m;
+ best_dir = c;
+ }
+
+ }
+ Point dir = angles[best_dir];
+ Point dirT = rot90(dir);
+ Point centre = dir*best_mean/N;
+
+ solution.push_back(centre + dot(dirT, input[0] - centre)*dirT);
+ solution.push_back(centre + dot(dirT, input.back() - centre)*dirT);
+}
+
+void fit::C_simple_dp() {
+ const unsigned N = input.size();
+
+ vector<int> prev(N);
+ vector<double> penalty(N);
+ vector<unsigned> dir(N);
+ vector<double> mean(N);
+ const double bend_pen = 0;
+
+ for(unsigned i = 1; i < input.size(); i++) {
+ double best_mean;
+ double best = best_angled_line(0, i, angles[0], best_mean);
+ unsigned best_prev = 0;
+ unsigned best_dir = 0;
+ for(unsigned c = 1; c < angles.size(); c++) {
+ double m;
+ double err = best_angled_line(0, i, angles[c], m);
+ if(err < best) {
+ best = err;
+ best_mean = m;
+ best_dir = c;
+ best_prev = 0;
+ }
+
+ }
+ for(unsigned j = 1; j < i; j++) {
+ for(unsigned c = 0; c < angles.size(); c++) {
+ double m;
+ if(c == dir[j])
+ continue;
+ double err = penalty[j] + bend_pen +
+ best_angled_line(j, i, angles[c], m);
+ if(err < best) {
+ best = err;
+ best_mean = m;
+ best_dir = c;
+ best_prev = j;
+ }
+
+ }
+ }
+ penalty[i] = best;
+ prev[i] = best_prev;
+ dir[i] = best_dir;
+ mean[i] = best_mean;
+ }
+
+ prev[0] = -1;
+ unsigned i = prev.size()-1;
+ unsigned pi = i;
+ while(i > 0) {
+ Point bdir = angles[dir[i]];
+ Point bdirT = rot90(bdir);
+ Point centre = bdir*mean[i]/N;
+ solution.push_back(centre + dot(bdirT, input[i] - centre)*bdirT);
+ solution.push_back(centre + dot(bdirT, input[pi] - centre)*bdirT);
+ pi = i;
+ i = prev[i];
+ }
+ /*Point a = angles[dir[i]];
+ Point aT = rot90(a);
+ solution.push_back(a*mean[i] +
+ dot(input[i], aT)*aT);*/
+ reverse(solution.begin(), solution.end());
+}
+
+
+
+
+
+
+class MetroMap: public Toy {
+public:
+ vector<PointSetHandle> metro_lines;
+ PointHandle directions;
+
+ bool should_draw_numbers() override { return false; }
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ double slider_margin = 20;
+ double slider_top = 20;
+ double slider_bot = 200;
+ directions.pos[X] = slider_margin;
+ if (directions.pos[Y]<slider_top) directions.pos[Y] = slider_top;
+ if (directions.pos[Y]>slider_bot) directions.pos[Y] = slider_bot;
+
+ unsigned num_directions = 2 + 15*(slider_bot-directions.pos[Y])/(slider_bot-slider_top);
+
+ cairo_move_to(cr,Geom::Point(slider_margin,slider_bot));
+ cairo_line_to(cr,Geom::Point(slider_margin,slider_top));
+ cairo_set_line_width(cr,.5);
+ cairo_set_source_rgba (cr, 0., 0.3, 0., 1.);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba (cr, 0., 0.5, 0, 1);
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0., 0., 0, 0.8);
+ cairo_set_line_width (cr, 1);
+
+ unsigned N= paths.size();
+ for(unsigned i=0;i<N;i++) {
+ double R,G,B;
+ convertHSVtoRGB(360.*double(i)/double(N),1,0.75,R,G,B);
+ metro_lines[i].rgb[0] = R;
+ metro_lines[i].rgb[1] = G;
+ metro_lines[i].rgb[2] = B;
+ cairo_set_source_rgba (cr, R, G, B, 0.8);
+ fit f(metro_lines[i].pts);
+ f.schematised_merging(num_directions);
+ f.draw(cr);
+ cairo_stroke(cr);
+ }
+ cairo_set_source_rgba (cr, 0., 0., 0, 1);
+ {
+ PangoLayout* layout = pango_cairo_create_layout (cr);
+ pango_layout_set_text(layout,
+ notify->str().c_str(), -1);
+
+ PangoFontDescription *font_desc = pango_font_description_new();
+ pango_font_description_set_family(font_desc, "Sans");
+ const unsigned size_px = 10;
+ pango_font_description_set_absolute_size(font_desc, size_px * 1024.0);
+ pango_layout_set_font_description(layout, font_desc);
+ PangoRectangle logical_extent;
+ pango_layout_get_pixel_extents(layout,
+ NULL,
+ &logical_extent);
+ cairo_move_to(cr, 0, height-logical_extent.height);
+ pango_cairo_show_layout(cr, layout);
+ }
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ void first_time(int argc, char** argv) override {
+ string location_file_name("data/london-locations.csv");
+ string path_file_name("data/london.txt");
+ if(argc > 2) {
+ location_file_name = argv[1];
+ path_file_name = argv[2];
+ }
+ cout << location_file_name << ", " << path_file_name << endl;
+ parse_data(paths, location_file_name, path_file_name);
+ for(auto & path : paths) {
+ metro_lines.emplace_back();
+ for(auto & j : path) {
+ metro_lines.back().push_back(j);
+ }
+ }
+ for(auto & metro_line : metro_lines) {
+ handles.push_back(&metro_line);
+ }
+ handles.push_back(&directions);
+ }
+
+ MetroMap() {
+ }
+
+};
+
+
+
+
+
+int main(int argc, char **argv) {
+ init(argc, argv, new MetroMap());
+
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+
diff --git a/src/3rdparty/2geom/src/toys/minsb2d-solver.cpp b/src/3rdparty/2geom/src/toys/minsb2d-solver.cpp
new file mode 100644
index 0000000..f2df9d9
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/minsb2d-solver.cpp
@@ -0,0 +1,376 @@
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-math.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/bezier-to-sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+using std::vector;
+using namespace Geom;
+
+
+//see a sb2d as an sb of u with coef in sbasis of v.
+void
+u_coef(SBasis2d f, unsigned deg, SBasis &a, SBasis &b) {
+ a = SBasis(f.vs, Linear());
+ b = SBasis(f.vs, Linear());
+ for (unsigned v=0; v<f.vs; v++){
+ a[v] = Linear(f.index(deg,v)[0], f.index(deg,v)[2]);
+ b[v] = Linear(f.index(deg,v)[1], f.index(deg,v)[3]);
+ }
+}
+void
+v_coef(SBasis2d f, unsigned deg, SBasis &a, SBasis &b) {
+ a = SBasis(f.us, Linear());
+ b = SBasis(f.us, Linear());
+ for (unsigned u=0; u<f.us; u++){
+ a[u] = Linear(f.index(deg,u)[0], f.index(deg,u)[1]);
+ b[u] = Linear(f.index(deg,u)[2], f.index(deg,u)[3]);
+ }
+}
+
+
+
+//TODO: implement sb2d algebra!!
+SBasis2d y_x2(){
+ SBasis2d result(Linear2d(0,-1,1,0));
+ result.push_back(Linear2d(1,1,1,1));
+ result.us = 2;
+ result.vs = 1;
+ return result;
+}
+
+SBasis2d x2_plus_y2_1(){
+/*TODO: implement sb2d algebra!!
+ SBasis2d one(Linear2d(1,1,1,1));
+ SBasis2d u(Linear2d(0,1,0,1));
+ SBasis2d v(Linear2d(0,0,1,1));
+ return(u*u+v*v-one);
+*/
+ SBasis2d result(Linear2d(-1,0,0,1));//x+y-1
+ result.push_back(Linear2d(-1,-1,-1,-1));
+ result.push_back(Linear2d(-4,-1,-1,-1));
+ result.push_back(Linear2d(0,0,0,0));
+ result.us = 2;
+ result.vs = 2;
+ return result;
+}
+
+struct Frame
+{
+ Geom::Point O;
+ Geom::Point x;
+ Geom::Point y;
+ Geom::Point z;
+};
+
+void
+plot3d(cairo_t *cr, SBasis const &x, SBasis const &y, SBasis const &z, Frame frame){
+ D2<SBasis> curve;
+ for (unsigned dim=0; dim<2; dim++){
+ curve[dim] = x*frame.x[dim] + y*frame.y[dim] + z*frame.z[dim];
+ curve[dim] += frame.O[dim];
+ }
+ cairo_d2_sb(cr, curve);
+}
+
+void
+plot3d(cairo_t *cr,
+ Piecewise<SBasis> const &x,
+ Piecewise<SBasis> const &y,
+ Piecewise<SBasis> const &z, Frame frame){
+
+ Piecewise<SBasis> xx = partition(x,y.cuts);
+ Piecewise<SBasis> xxx = partition(xx,z.cuts);
+ Piecewise<SBasis> yyy = partition(y,xxx.cuts);
+ Piecewise<SBasis> zzz = partition(z,xxx.cuts);
+
+ for (unsigned i=0; i<xxx.size(); i++){
+ plot3d(cr, xxx[i], yyy[i], zzz[i], frame);
+ }
+}
+
+void
+plot3d(cairo_t *cr, SBasis2d const &f, Frame frame, int NbRays=5){
+ for (int i=0; i<=NbRays; i++){
+ D2<SBasis> seg(SBasis(0.,1.), SBasis(i*1./NbRays, i*1./NbRays));
+ SBasis f_on_seg = compose(f,seg);
+ plot3d(cr,seg[X],seg[Y],f_on_seg,frame);
+ }
+ for (int i=0; i<NbRays; i++){
+ D2<SBasis> seg(SBasis(i*1./NbRays, i*1./NbRays), SBasis(0.,1.));
+ SBasis f_on_seg = compose(f,seg);
+ plot3d(cr,seg[X],seg[Y],f_on_seg,frame);
+ }
+}
+
+void
+plot3d_top(cairo_t *cr, SBasis2d const &f, Frame frame, int NbRays=5){
+ for (int i=0; i<=NbRays; i++){
+ for(int j=0; j<2; j++){
+ D2<SBasis> seg;
+ if (j==0){
+ seg = D2<SBasis>(SBasis(0.,1.), SBasis(i*1./NbRays, i*1./NbRays));
+ }else{
+ seg = D2<SBasis>(SBasis(i*1./NbRays,i*1./NbRays), SBasis(0.,1.));
+ }
+ SBasis f_on_seg = compose(f,seg);
+ std::vector<double> rts = roots(f_on_seg);
+ if (rts.size()==0||rts.back()<1) rts.push_back(1.);
+ double t1,t0 = 0;
+ for (unsigned i=(rts.front()<=0?1:0); i<rts.size(); i++){
+ t1 = rts[i];
+ if (f_on_seg((t0+t1)/2)>0)
+ plot3d(cr,seg[X](Linear(t0,t1)),seg[Y](Linear(t0,t1)),f_on_seg(Linear(t0,t1)),frame);
+ t0=t1;
+ }
+ //plot3d(cr,seg[X],seg[Y],f_on_seg,frame);
+ }
+ }
+}
+#include <gsl/gsl_multimin.h>
+
+class Sb2dSolverToy: public Toy {
+public:
+ PointSetHandle hand;
+ Sb2dSolverToy() {
+ handles.push_back(&hand);
+ }
+
+ class bits_n_bobs{
+ public:
+ SBasis2d * ff;
+ Point A, B;
+ Point dA, dB;
+ };
+ static double
+ my_f (const gsl_vector *v, void *params)
+ {
+ double x, y;
+ bits_n_bobs* bnb = (bits_n_bobs *)params;
+
+ x = gsl_vector_get(v, 0);
+ y = gsl_vector_get(v, 1);
+ Bezier b0(bnb->B[0], bnb->B[0]+bnb->dB[0]*x, bnb->A[0]+bnb->dA[0]*y, bnb->A[0]);
+ Bezier b1(bnb->B[1], bnb->B[1]+bnb->dB[1]*x, bnb->A[1]+bnb->dA[1]*y, bnb->A[1]);
+
+ D2<SBasis> zeroset(b0.toSBasis(), b1.toSBasis());
+
+ SBasis comp = compose((*bnb->ff),zeroset);
+ Interval bounds = *bounds_fast(comp);
+ double error = (bounds.max()>-bounds.min() ? bounds.max() : -bounds.min() );
+ //printf("error = %g %g %g\n", bounds.max(), bounds.min(), error);
+ return error*error;
+ }
+
+
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+
+ double slider_top = width/4.;
+ double slider_bot = width*3./4.;
+ double slider_margin = width/8.;
+ if(hand.pts.empty()) {
+ hand.pts.emplace_back(width*3./16., 3*width/4.);
+ hand.pts.push_back(hand.pts[0] + Geom::Point(width/2., 0));
+ hand.pts.push_back(hand.pts[0] + Geom::Point(width/8., -width/12.));
+ hand.pts.push_back(hand.pts[0] + Geom::Point(0,-width/4.));
+ hand.pts.emplace_back(slider_margin,slider_bot);
+ hand.pts.emplace_back(width-slider_margin,slider_top);
+ }
+
+ hand.pts[4][X] = slider_margin;
+ if (hand.pts[4][Y]<slider_top) hand.pts[4][Y] = slider_top;
+ if (hand.pts[4][Y]>slider_bot) hand.pts[4][Y] = slider_bot;
+ hand.pts[5][X] = width-slider_margin;
+ if (hand.pts[5][Y]<slider_top) hand.pts[5][Y] = slider_top;
+ if (hand.pts[5][Y]>slider_bot) hand.pts[5][Y] = slider_bot;
+
+ double tA = (slider_bot-hand.pts[4][Y])/(slider_bot-slider_top);
+ double tB = (slider_bot-hand.pts[5][Y])/(slider_bot-slider_top);
+
+ cairo_move_to(cr,Geom::Point(slider_margin,slider_bot));
+ cairo_line_to(cr,Geom::Point(slider_margin,slider_top));
+ cairo_move_to(cr,Geom::Point(width-slider_margin,slider_bot));
+ cairo_line_to(cr,Geom::Point(width-slider_margin,slider_top));
+ cairo_set_line_width(cr,.5);
+ cairo_set_source_rgba (cr, 0., 0.3, 0., 1.);
+ cairo_stroke(cr);
+
+ Frame frame;
+ frame.O = hand.pts[0];//
+ frame.x = hand.pts[1]-hand.pts[0];//
+ frame.y = hand.pts[2]-hand.pts[0];//
+ frame.z = hand.pts[3]-hand.pts[0];//
+
+/*
+ SBasis2d f = y_x2();
+ D2<SBasis> true_solution(Linear(0,1),Linear(0,1));
+ true_solution[Y].push_back(Linear(-1,-1));
+ SBasis zero = SBasis(Linear(0.));
+ Geom::Point A = true_solution(tA);
+ Geom::Point B = true_solution(tB);
+*/
+
+ SBasis2d f = x2_plus_y2_1();
+ D2<Piecewise<SBasis> > true_solution;
+ true_solution[X] = cos(SBasis(Linear(0,3.141592/2)));
+ true_solution[Y] = sin(SBasis(Linear(0,3.141592/2)));
+ Piecewise<SBasis> zero = Piecewise<SBasis>(SBasis(Linear(0.)));
+ //Geom::Point A(cos(tA*M_PI/2), sin(tA*M_PI/2));// = true_solution(tA);
+ //Geom::Point B(cos(tB*M_PI/2), sin(tB*M_PI/2));// = true_solution(tB);
+ Geom::Point A = true_solution(tA);
+ Geom::Point B = true_solution(tB);
+ Point dA(-sin(tA*M_PI/2), cos(tA*M_PI/2));
+ Geom::Point dB(-sin(tB*M_PI/2), cos(tB*M_PI/2));
+ SBasis2d dfdu = partial_derivative(f, 0);
+ SBasis2d dfdv = partial_derivative(f, 1);
+ Geom::Point dfA(dfdu.apply(A[X],A[Y]),dfdv.apply(A[X],A[Y]));
+ Geom::Point dfB(dfdu.apply(B[X],B[Y]),dfdv.apply(B[X],B[Y]));
+ dA = rot90(dfA);
+ dB = rot90(dfB);
+
+ plot3d(cr,Linear(0,1),Linear(0,0),Linear(0,0),frame);
+ plot3d(cr,Linear(0,1),Linear(1,1),Linear(0,0),frame);
+ plot3d(cr,Linear(0,0),Linear(0,1),Linear(0,0),frame);
+ plot3d(cr,Linear(1,1),Linear(0,1),Linear(0,0),frame);
+ cairo_set_line_width(cr,.2);
+ cairo_set_source_rgba (cr, 0., 0., 0., 1.);
+ cairo_stroke(cr);
+
+ plot3d_top(cr,f,frame);
+ cairo_set_line_width(cr,1);
+ cairo_set_source_rgba (cr, .5, 0.5, 0.5, 1.);
+ cairo_stroke(cr);
+ plot3d(cr,f,frame);
+ cairo_set_line_width(cr,.2);
+ cairo_set_source_rgba (cr, .5, 0.5, 0.5, 1.);
+ cairo_stroke(cr);
+
+ plot3d(cr, true_solution[X], true_solution[Y], zero, frame);
+ cairo_set_line_width(cr,.5);
+ cairo_set_source_rgba (cr, 0., 0., 0., 1.);
+ cairo_stroke(cr);
+ double error;
+ for(int degree = 2; degree < 2; degree++) {
+ D2<SBasis> zeroset = sb2dsolve(f,A,B,degree);
+ plot3d(cr, zeroset[X], zeroset[Y], SBasis(Linear(0.)),frame);
+ cairo_set_line_width(cr,1);
+ cairo_set_source_rgba (cr, 0.9, 0., 0., 1.);
+ cairo_stroke(cr);
+
+ SBasis comp = compose(f,zeroset);
+ plot3d(cr, zeroset[X], zeroset[Y], comp, frame);
+ cairo_set_source_rgba (cr, 0.7, 0., 0.7, 1.);
+ cairo_stroke(cr);
+ //Fix Me: bounds_exact does not work here?!?!
+ Interval bounds = *bounds_fast(comp);
+ error = (bounds.max()>-bounds.min() ? bounds.max() : -bounds.min() );
+ }
+ if (1) {
+
+ bits_n_bobs par = {&f, A, B, dA, dB};
+ bits_n_bobs* bnb = &par;
+ std::cout << f[0] << "= initial f \n";
+ const gsl_multimin_fminimizer_type *T =
+ gsl_multimin_fminimizer_nmsimplex;
+ gsl_multimin_fminimizer *s = NULL;
+ gsl_vector *ss, *x;
+ gsl_multimin_function minex_func;
+
+ size_t iter = 0;
+ int status;
+ double size;
+
+ /* Starting point */
+ x = gsl_vector_alloc (2);
+ gsl_vector_set (x, 0, 0.552); // magic number for quarter circle
+ gsl_vector_set (x, 1, 0.552);
+
+ /* Set initial step sizes to 1 */
+ ss = gsl_vector_alloc (2);
+ gsl_vector_set_all (ss, 0.1);
+
+ /* Initialize method and iterate */
+ minex_func.n = 2;
+ minex_func.f = &my_f;
+ minex_func.params = (void *)&par;
+
+ s = gsl_multimin_fminimizer_alloc (T, 2);
+ gsl_multimin_fminimizer_set (s, &minex_func, x, ss);
+
+ do
+ {
+ iter++;
+ status = gsl_multimin_fminimizer_iterate(s);
+
+ if (status)
+ break;
+
+ size = gsl_multimin_fminimizer_size (s);
+ status = gsl_multimin_test_size (size, 1e-7);
+
+ if (status == GSL_SUCCESS)
+ {
+ printf ("converged to minimum at\n");
+ }
+
+ }
+ while (status == GSL_CONTINUE && iter < 100);
+ printf ("%5lu %g %gf f() = %g size = %g\n",
+ iter,
+ gsl_vector_get (s->x, 0),
+ gsl_vector_get (s->x, 1),
+ s->fval, size);
+ {
+ double x = gsl_vector_get(s->x, 0);
+ double y = gsl_vector_get(s->x, 1);
+ Bezier b0(bnb->B[0], bnb->B[0]+bnb->dB[0]*x, bnb->A[0]+bnb->dA[0]*y, bnb->A[0]);
+ Bezier b1(bnb->B[1], bnb->B[1]+bnb->dB[1]*x, bnb->A[1]+bnb->dA[1]*y, bnb->A[1]);
+
+ D2<SBasis> zeroset(b0.toSBasis(), b1.toSBasis());
+ plot3d(cr, zeroset[X], zeroset[Y], SBasis(Linear(0.)),frame);
+ cairo_set_line_width(cr,1);
+ cairo_set_source_rgba (cr, 0.9, 0., 0., 1.);
+ cairo_stroke(cr);
+
+ SBasis comp = compose(f,zeroset);
+ plot3d(cr, zeroset[X], zeroset[Y], comp, frame);
+ cairo_set_source_rgba (cr, 0.7, 0., 0.7, 1.);
+ cairo_stroke(cr);
+ //Fix Me: bounds_exact does not work here?!?!
+ Interval bounds = *bounds_fast(comp);
+ error = (bounds.max()>-bounds.min() ? bounds.max() : -bounds.min() );
+
+ }
+
+ gsl_vector_free(x);
+ gsl_vector_free(ss);
+ gsl_multimin_fminimizer_free (s);
+ }
+ *notify << "Gray: f-graph and true solution,\n";
+ *notify << "Red: solver solution,\n";
+ *notify << "Purple: value of f over solver solution.\n";
+ *notify << " error: "<< error <<".\n";
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new Sb2dSolverToy());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+
diff --git a/src/3rdparty/2geom/src/toys/nasty.svg b/src/3rdparty/2geom/src/toys/nasty.svg
new file mode 100644
index 0000000..4457044
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/nasty.svg
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.45"
+ sodipodi:modified="true">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.35"
+ inkscape:cx="375"
+ inkscape:cy="481.62572"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="910"
+ inkscape:window-height="626"
+ inkscape:window-x="5"
+ inkscape:window-y="49" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 387.63906,267.9784 L 106.72661,469.82569 L 106.72661,267.9784 L 387.63906,469.82569 L 387.63906,267.9784 z "
+ id="path2160"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 540.4278,232.25903 C 440.92573,232.25903 646.18067,452.19982 540.4278,452.19982 C 437.36839,452.19982 639.73953,232.25903 540.4278,232.25903 z "
+ id="path2162"
+ sodipodi:nodetypes="csz" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 282.85714,578.07647 C 74.285714,832.36218 165.33193,1033.3172 288.57143,900.93361 C 410.47619,769.98377 73.333332,831.45467 282.85714,578.07647 z "
+ id="path2182"
+ sodipodi:nodetypes="czc" />
+ <path
+ id="path2186"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 548.57143,662.36218 C 615.72948,662.36218 625.35777,906.64794 728.57143,906.64794 C 832.06154,906.64794 637.327,662.36218 548.57143,662.36218 C 459.95393,662.36218 291.30957,906.64794 428.57143,906.64794 C 534.44005,906.64794 481.41338,662.36218 548.57143,662.36218 z "
+ sodipodi:nodetypes="czzsz" />
+ </g>
+</svg>
diff --git a/src/3rdparty/2geom/src/toys/nearest-times.cpp b/src/3rdparty/2geom/src/toys/nearest-times.cpp
new file mode 100644
index 0000000..66803d6
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/nearest-times.cpp
@@ -0,0 +1,258 @@
+/*
+ * Nearest Points Toy
+ *
+ * Authors:
+ * Nathan Hurst <njh at njhurst.com>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/path.h>
+#include <2geom/bezier-to-sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework.h>
+
+
+using namespace Geom;
+
+
+class np_finder
+{
+public:
+ np_finder(cairo_t* _cr, D2<SBasis> const& _c1, D2<SBasis> const& _c2)
+ : cr(_cr), c1(_c1), c2(_c2)
+ {
+ dc1 = derivative(c1);
+ dc2 = derivative(c2);
+ cd1 = dot(c1,dc1);
+ cd2 = dot(c2,dc2);
+ dsq = 10e30;
+ }
+
+ void operator() ()
+ {
+ nearest_times_impl(0.5, 0, 1);
+ d = sqrt(dsq);
+ }
+
+ Point firstPoint() const
+ {
+ return p1;
+ }
+
+ Point secondPoint() const
+ {
+ return p2;
+ }
+
+ double firstValue() const
+ {
+ return t1;
+ }
+
+ double secondValue() const
+ {
+ return t2;
+ }
+
+ double distance() const
+ {
+ return d;
+ }
+
+private:
+ void nearest_times_impl( double t, double from = 0, double to = 1 )
+ {
+ //std::cerr << "[" << from << "," << to << "] t: " << t << std::endl;
+
+ double st = t, et = t;
+ std::pair<double, double> npc = loc_nearest_times(t, from, to);
+ //std::cerr << "(" << npc.first << "," << npc.second << ")" << std::endl;
+ if ( npc.second != -1 && dsq > L2sq(c1(npc.first) - c2(npc.second)) )
+ {
+ t1 = npc.first;
+ t2 = npc.second;
+ p1 = c1(t1);
+ p2 = c2(t2);
+ dsq = L2sq(p1 - p2);
+ }
+ if (npc.first < t)
+ st = npc.first;
+ else
+ et = npc.first;
+ //std::cerr << "[" << st << "," << et << "]" << std::endl;
+ double d1 = std::fabs(st - from);
+ double d2 = std::fabs(to - et);
+ if ( d1 > EPSILON )
+ nearest_times_impl(from + d1/2, from, st);
+ if ( d2 > EPSILON )
+ nearest_times_impl(et + d2/2, et, to);
+ }
+
+ std::pair<double, double>
+ loc_nearest_times( double t, double from = 0, double to = 1 )
+ {
+ unsigned int i = 0;
+ std::pair<double, double> np(-1,-1);
+ std::pair<double, double> npf(from, -1);
+ std::pair<double, double> npt(to, -1);
+ double ct = t;
+ double pt = -1;
+ double s;
+ //cairo_set_source_rgba(cr, 1/(t+1), t*t, t, 1.0);
+ //cairo_move_to(cr, c1(t));
+ while( !are_near(ct, pt) )
+ {
+ ++i;
+ pt = ct;
+ s = nearest_time(c1(ct), c2, dc2, cd2);
+ //std::cerr << "s: " << s << std::endl;
+ //cairo_line_to(cr, c2(s));
+ ct = nearest_time(c2(s), c1, dc1, cd1, from, to);
+ //std::cerr << "t: " << t1 << std::endl;
+ //cairo_line_to(cr, c1(ct));
+ if ( ct < from ) return npf;
+ if ( ct > to ) return npt;
+ }
+ //std::cerr << "\n \n";
+ //std::cerr << "iterations: " << i << std::endl;
+ cairo_stroke(cr);
+ np.first = ct;
+ np.second = s;
+ return np;
+ }
+
+ double nearest_time( Point const& p, D2<SBasis> const&c, D2<SBasis> const& dc, SBasis const& cd, double from = 0, double to = 1 )
+ {
+ D2<SBasis> sbc = c - p;
+ SBasis dd = cd - dotp(p, dc);
+ std::vector<double> zeros = roots(dd);
+ double closest = from;
+ double distsq = L2sq(sbc(from));
+ for ( unsigned int i = 0; i < zeros.size(); ++i )
+ {
+ if ( distsq > L2sq(sbc(zeros[i])) )
+ {
+ closest = zeros[i];
+ distsq = L2sq(sbc(closest));
+ }
+ }
+ if ( distsq > L2sq(sbc(to)) )
+ closest = to;
+ return closest;
+ }
+
+ SBasis dotp(Point const& p, D2<SBasis> const& c)
+ {
+ SBasis d;
+ d.resize(c[X].size());
+ for ( unsigned int i = 0; i < c[0].size(); ++i )
+ {
+ for( unsigned int j = 0; j < 2; ++j )
+ d[i][j] = p[X] * c[X][i][j] + p[Y] * c[Y][i][j];
+ }
+ return d;
+ }
+
+private:
+ static const Coord EPSILON = 10e-3;
+ cairo_t* cr;
+ D2<SBasis> const& c1, c2;
+ D2<SBasis> dc1, dc2;
+ SBasis cd1, cd2;
+ double t1, t2, d, dsq;
+ Point p1, p2;
+};
+
+
+
+
+class NearestPoints : public Toy
+{
+ private:
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream)
+ {
+ cairo_set_line_width (cr, 0.2);
+ D2<SBasis> A = handles_to_sbasis(handles.begin(), A_bez_ord-1);
+ cairo_d2_sb(cr, A);
+ D2<SBasis> B = handles_to_sbasis(handles.begin()+A_bez_ord, B_bez_ord-1);
+ cairo_d2_sb(cr, B);
+
+
+ np_finder np(cr, A, B);
+ np();
+ cairo_move_to(cr, np.firstPoint());
+ cairo_line_to(cr, np.secondPoint());
+ cairo_stroke(cr);
+ //std::cerr << "np: (" << np.firstValue() << "," << np.secondValue() << ")" << std::endl;
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ NearestPoints(unsigned int _A_bez_ord, unsigned int _B_bez_ord)
+ : A_bez_ord(_A_bez_ord), B_bez_ord(_B_bez_ord)
+ {
+ unsigned int total_handles = A_bez_ord + B_bez_ord;
+ for ( unsigned int i = 0; i < total_handles; ++i )
+ handles.push_back(Geom::Point(uniform()*400, uniform()*400));
+ }
+
+ private:
+ unsigned int A_bez_ord;
+ unsigned int B_bez_ord;
+};
+
+
+int main(int argc, char **argv)
+{
+ unsigned int A_bez_ord=8;
+ unsigned int B_bez_ord=5;
+ if(argc > 2)
+ sscanf(argv[2], "%d", &B_bez_ord);
+ if(argc > 1)
+ sscanf(argv[1], "%d", &A_bez_ord);
+
+ init( argc, argv, new NearestPoints(A_bez_ord, B_bez_ord));
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/nearest-times2.cpp b/src/3rdparty/2geom/src/toys/nearest-times2.cpp
new file mode 100644
index 0000000..04cd9e6
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/nearest-times2.cpp
@@ -0,0 +1,313 @@
+/*
+ * Nearest Points Toy 2
+ *
+ * Authors:
+ * Nathan Hurst <njh at njhurst.com>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/path.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-geometric.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework.h>
+
+#include <algorithm>
+
+
+using namespace Geom;
+
+
+class np_finder
+{
+public:
+ np_finder(cairo_t* _cr, D2<SBasis> const& _c1, D2<SBasis> const& _c2)
+ : cr(_cr), c1(_c1), c2(_c2)
+ {
+ dc1 = derivative(c1);
+ dc2 = derivative(c2);
+ cd1 = dot(c1,dc1);
+ cd2 = dot(c2,dc2);
+ dsq = 10e30;
+
+ Piecewise<SBasis> k1 = curvature(c1, EPSILON);
+ Piecewise<SBasis> k2 = curvature(c2, EPSILON);
+ Piecewise<SBasis> dk1 = derivative(k1);
+ Piecewise<SBasis> dk2 = derivative(k2);
+ std::vector<double> k1_roots = roots(k1);
+ std::vector<double> k2_roots = roots(k2);
+ std::vector<double> dk1_roots = roots(dk1);
+ std::vector<double> dk2_roots = roots(dk2);
+ tlist.clear();
+ tlist.resize(k1_roots.size() + k2_roots.size() + dk1_roots.size() + dk2_roots.size() + 4);
+ tlist.push_back(0);
+ tlist.insert(tlist.end(), dk1_roots.begin(), dk1_roots.end());
+ tlist.insert(tlist.end(), k1_roots.begin(), k1_roots.end());
+// std::cerr << "dk1 roots: ";
+// for ( unsigned int i = 0; i < dk1_roots.size(); ++i )
+// {
+// std::cerr << dk1_roots[i] << " ";
+// }
+// std::cerr << "\n";
+ for ( unsigned int i = 0; i < k2_roots.size(); ++i )
+ {
+ tlist.push_back(nearest_time(c2(k2_roots[i]), c1, dc1, cd1));
+ }
+
+ for ( unsigned int i = 0; i < dk2_roots.size(); ++i )
+ {
+ tlist.push_back(nearest_time(c2(dk2_roots[i]), c1, dc1, cd1));
+ }
+ tlist.push_back(nearest_time(c2(0), c1, dc1, cd1));
+ tlist.push_back(nearest_time(c2(1), c1, dc1, cd1));
+ tlist.push_back(1);
+ std::sort(tlist.begin(), tlist.end());
+ std::vector<double>::iterator pos
+ = std::unique(tlist.begin(), tlist.end(), are_near_() );
+ if (pos != tlist.end())
+ {
+ tlist.erase(pos, tlist.end());
+ }
+ for( unsigned int i = 0; i < tlist.size(); ++i )
+ {
+ draw_circ(cr, c1(tlist[i]) );
+ }
+ }
+
+ void operator() ()
+ {
+ //nearest_times_impl( tlist.size() / 2, 0, tlist.size() - 1 );
+ nearest_times_impl();
+ d = sqrt(dsq);
+ }
+
+ Point firstPoint() const
+ {
+ return p1;
+ }
+
+ Point secondPoint() const
+ {
+ return p2;
+ }
+
+ double firstValue() const
+ {
+ return t1;
+ }
+
+ double secondValue() const
+ {
+ return t2;
+ }
+
+ double distance() const
+ {
+ return d;
+ }
+
+private:
+ void nearest_times_impl()
+ {
+ double t;
+ double from = tlist[0];
+ double to;
+ for ( unsigned int i = 1; i < tlist.size(); ++i )
+ {
+ to = tlist[i];
+ t = from + (to - from) / 2 ;
+ std::pair<double, double> npc = loc_nearest_times(t, from, to);
+ if ( npc.second != -1 && dsq > L2sq(c1(npc.first) - c2(npc.second)) )
+ {
+ t1 = npc.first;
+ t2 = npc.second;
+ p1 = c1(t1);
+ p2 = c2(t2);
+ dsq = L2sq(p1 - p2);
+ }
+ from = tlist[i];
+ }
+ }
+
+ std::pair<double, double>
+ loc_nearest_times( double t, double from = 0, double to = 1 )
+ {
+ //std::cerr << "[" << from << "," << to << "] t: " << t << std::endl;
+ unsigned int i = 0;
+ std::pair<double, double> np(-1,-1);
+ std::pair<double, double> npf(from, -1);
+ std::pair<double, double> npt(to, -1);
+ double ct = t;
+ double pt = -1;
+ double s;
+ //cairo_set_source_rgba(cr, 1/(t+1), t*t, t, 1.0);
+ cairo_move_to(cr, c1(t));
+ while( !are_near(ct, pt) )
+ {
+ ++i;
+ pt = ct;
+ s = nearest_time(c1(ct), c2, dc2, cd2);
+ //std::cerr << "s: " << s << std::endl;
+ //cairo_line_to(cr, c2(s));
+ ct = nearest_time(c2(s), c1, dc1, cd1, from, to);
+ //std::cerr << "t: " << ct << std::endl;
+ //cairo_line_to(cr, c1(ct));
+ //std::cerr << "d(pt, ct) = " << std::fabs(ct - pt) << std::endl;
+ if ( ct < from ) return npf;
+ if ( ct > to ) return npt;
+ }
+ //std::cerr << "\n \n";
+ std::cerr << "iterations: " << i << std::endl;
+ //cairo_move_to(cr, c1(ct));
+ //cairo_line_to(cr, c2(s));
+ cairo_stroke(cr);
+ np.first = ct;
+ np.second = s;
+ return np;
+ }
+
+ double nearest_time( Point const& p, D2<SBasis> const&c, D2<SBasis> const& dc, SBasis const& cd, double from = 0, double to = 1 )
+ {
+ D2<SBasis> sbc = c - p;
+ SBasis dd = cd - dotp(p, dc);
+ std::vector<double> zeros = roots(dd);
+ double closest = from;
+ double distsq = L2sq(sbc(from));
+ for ( unsigned int i = 0; i < zeros.size(); ++i )
+ {
+ if ( distsq > L2sq(sbc(zeros[i])) )
+ {
+ closest = zeros[i];
+ distsq = L2sq(sbc(closest));
+ }
+ }
+ if ( distsq > L2sq(sbc(to)) )
+ closest = to;
+ return closest;
+ }
+
+ SBasis dotp(Point const& p, D2<SBasis> const& c)
+ {
+ SBasis d;
+ d.resize(c[X].size());
+ for ( unsigned int i = 0; i < c[0].size(); ++i )
+ {
+ for( unsigned int j = 0; j < 2; ++j )
+ d[i][j] = p[X] * c[X][i][j] + p[Y] * c[Y][i][j];
+ }
+ return d;
+ }
+
+ struct are_near_
+ {
+ bool operator() (double x, double y, double eps = Geom::EPSILON )
+ {
+ return are_near(x, y, eps);
+ }
+ };
+
+private:
+ static const Coord EPSILON = 10e-5;
+ cairo_t* cr;
+ D2<SBasis> const& c1, c2;
+ D2<SBasis> dc1, dc2;
+ SBasis cd1, cd2;
+ double t1, t2, d, dsq;
+ Point p1, p2;
+ std::vector<double> tlist;
+};
+
+
+
+
+class NearestPoints : public Toy
+{
+ private:
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream)
+ {
+ cairo_set_line_width (cr, 0.2);
+ D2<SBasis> A = handles_to_sbasis(handles.begin(), A_bez_ord-1);
+ cairo_d2_sb(cr, A);
+ D2<SBasis> B = handles_to_sbasis(handles.begin()+A_bez_ord, B_bez_ord-1);
+ cairo_d2_sb(cr, B);
+
+
+ np_finder np(cr, A, B);
+ np();
+ cairo_move_to(cr, np.firstPoint());
+ cairo_line_to(cr, np.secondPoint());
+ cairo_stroke(cr);
+ //std::cerr << "np: (" << np.firstValue() << "," << np.secondValue() << ")" << std::endl;
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ NearestPoints(unsigned int _A_bez_ord, unsigned int _B_bez_ord)
+ : A_bez_ord(_A_bez_ord), B_bez_ord(_B_bez_ord)
+ {
+ unsigned int total_handles = A_bez_ord + B_bez_ord;
+ for ( unsigned int i = 0; i < total_handles; ++i )
+ handles.push_back(Geom::Point(uniform()*400, uniform()*400));
+ }
+
+ private:
+ unsigned int A_bez_ord;
+ unsigned int B_bez_ord;
+};
+
+
+int main(int argc, char **argv)
+{
+ unsigned int A_bez_ord=8;
+ unsigned int B_bez_ord=5;
+ if(argc > 2)
+ sscanf(argv[2], "%d", &B_bez_ord);
+ if(argc > 1)
+ sscanf(argv[1], "%d", &A_bez_ord);
+
+ init( argc, argv, new NearestPoints(A_bez_ord, B_bez_ord));
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/normal-bundle.cpp b/src/3rdparty/2geom/src/toys/normal-bundle.cpp
new file mode 100644
index 0000000..efe7536
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/normal-bundle.cpp
@@ -0,0 +1,230 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/bezier-to-sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <vector>
+using std::vector;
+using namespace Geom;
+
+class NormalBundle : public std::vector<D2<SBasis2d> >{
+public:
+ vector<double> lengths;
+ NormalBundle(){lengths.push_back(0.);}
+ void setBase(D2<SBasis> const &B, double tol);
+ void draw(cairo_t* cr, unsigned NbSections =5,unsigned NbFibre=5);
+};
+vector<D2<SBasis> > compose(NormalBundle const &NB,
+ D2<SBasis> const &Binit,
+ Geom::Point Origin=Geom::Point(0,0));
+
+//--------------------------------------------
+
+void SBasis1d_to_2d(D2<SBasis> C0,
+ D2<SBasis> C1,
+ D2<SBasis2d> &S){
+ for(unsigned dim = 0; dim < 2; dim++) {
+//**** C0 and C1 should have the same size...
+ for (unsigned i=C0[dim].size();i<C1[dim].size(); i++)
+ C0[dim].push_back(Linear(0));
+ for (unsigned i=C1[dim].size();i<C0[dim].size(); i++)
+ C1[dim].push_back(Linear(0));
+ S[dim].clear();
+ S[dim].us = C0[dim].size();
+ S[dim].vs = 1;
+ for(unsigned v = 0; v < S[dim].vs; v++)
+ for(unsigned u = 0; u < S[dim].us; u++)
+ S[dim].push_back(Linear2d(C0[dim][u][0],C0[dim][u][1],
+ C1[dim][u][0],C1[dim][u][1]));
+ }
+}
+
+void NormalBundle::setBase(D2<SBasis> const &B, double tol=0.01) {
+
+ D2<SBasis> dB = derivative(B);
+ vector<double> cuts;
+ Piecewise<D2<SBasis> > unitV=unitVector(dB);
+
+ //TODO: clean this up, use arc_length_parametrization...
+ cuts=unitV.cuts;
+ double t0=0,t1,L=0;
+ for(unsigned i=1;i<cuts.size();i++){
+ t1=cuts[i];
+ D2<SBasis> subB=compose(B,Linear(t0,t1));
+ D2<SBasis2d> S;
+ SBasis1d_to_2d(subB, subB+rot90(unitV[i]), S);
+ push_back(S);
+
+ SBasis s=integral(dot(compose(dB,Linear(t0,t1)),unitV[i]));
+ L+=(s(1)-s(0))*(t1-t0);
+ lengths.push_back(L);
+
+ t0=t1;
+ }
+}
+
+void NormalBundle::draw(cairo_t *cr, unsigned NbLi, unsigned NbCol) {
+ D2<SBasis> B;
+ vector<D2<SBasis> > tB;
+ //Geom::Point Seg[2];
+ B[1]=Linear(-100,100);
+ double width=*(lengths.rbegin());
+ if (NbCol>0)
+ for(unsigned ui = 0; ui <= NbCol; ui++) {
+ B[0]=Linear(ui*width/NbCol);
+ tB = compose(*this,B);
+ if (tB.size()>0) cairo_d2_sb(cr, tB[0]);
+ }
+
+ B[0]=SBasis(Linear(0,1));
+ for(unsigned ui = 0; ui <= NbLi; ui++) {
+ B[1]=Linear(-100+ui*200/NbLi);
+ for(unsigned i = 0; i <size(); i++) {
+ D2<SBasis> section=composeEach((*this)[i],B);
+ cairo_d2_sb(cr, section);
+ }
+ }
+}
+
+
+vector<D2<SBasis> > compose(NormalBundle const &NB,
+ D2<SBasis> const &Binit,
+ Geom::Point Origin){
+ vector<D2<SBasis> > result;
+ D2<SBasis> B=Binit;
+ D2<SBasis> Bcut;
+ vector<double> Roots;
+ std::map<double,unsigned> Cuts;
+ unsigned idx;
+
+ B = B + (-Origin);
+
+ //--Find intersections with fibers over segment ends.
+ for(unsigned i=0; i<=NB.size();i++){
+ Roots=roots(B[0]);
+ for (vector<double>::iterator root=Roots.begin();
+ root!=Roots.end();root++)
+ Cuts[*root]=i;
+ if((Cuts.count(0.)==0) and
+ ((B[0].valueAt(0.)<=0) or i==NB.size()))
+ Cuts[0.]=i;
+ if((Cuts.count(1.)==0) and
+ ((B[0].valueAt(1.)<=0) or i==NB.size()))
+ Cuts[1.]=i;
+ if (i<NB.size())
+ B[0]-=(NB.lengths[i+1]-NB.lengths[i]);
+ }
+ B[0]+=*(NB.lengths.rbegin());
+
+ //-- Compose each piece with the relevant sbasis2d.
+ // TODO: use a uniform parametrization of the base.
+ std::map<double,unsigned>::iterator cut=Cuts.begin();
+ std::map<double,unsigned>::iterator next=cut; next++;
+ while(next!=Cuts.end()){
+ double t0=(*cut).first;
+ unsigned idx0=(*cut).second;
+ double t1=(*next).first;
+ unsigned idx1=(*next).second;
+ if (idx0 != idx1){
+ idx=std::min(idx0,idx1);
+ } else if(B[0]((t0+t1)/2) < NB.lengths[idx0]) { // we have a left 'bump',
+ idx=idx0-1;
+ } else if(B[0]((t0+t1)/2) == NB.lengths[idx0]) { //we have a vertical segment!...
+ idx= (idx0==NB.size())? idx0-1:idx0;
+ } else //we have a right 'bump'.
+ idx=idx0;
+
+ //--trim version...
+ if (idx>=0 and idx<NB.size()) {
+ for (unsigned dim=0;dim<2;dim++)
+ Bcut[dim]=compose(B[dim], Linear(t0,t1));
+ double width=NB.lengths[idx+1]-NB.lengths[idx];
+ Bcut[0]=compose(Linear(-NB.lengths[idx]/width,
+ (1-NB.lengths[idx])/width),Bcut[0]);
+ Bcut = composeEach(NB[idx], Bcut);
+ result.push_back(Bcut);
+ }
+ cut++;
+ next++;
+ }
+ return(result);
+}
+
+
+
+class NormalBundleToy: public Toy {
+ PointSetHandle B_handle;
+ PointSetHandle P_handle;
+ PointHandle O_handle;
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) {
+ D2<SBasis> B = B_handle.asBezier();
+ D2<SBasis> P = P_handle.asBezier();
+ Geom::Point O = O_handle.pos;
+
+ NormalBundle NBdle;
+ NBdle.setBase(B);
+ Geom::Point Oo(O[0]+*(NBdle.lengths.rbegin()),O[1]);
+
+ vector<D2<SBasis> > Q=compose(NBdle,P,O);
+
+ cairo_set_line_width (cr, 0.5);
+ //Base lines
+ cairo_set_source_rgba (cr, 0.9, 0., 0., 1);
+ cairo_d2_sb(cr, B);
+ draw_line_seg(cr, O, Oo);
+ cairo_stroke(cr);
+
+ //Sections
+ cairo_set_source_rgba (cr, 0, 0, 0.9, 1);
+ cairo_d2_sb(cr, P);
+ for (unsigned i=0;i<Q.size();i++){
+ cairo_d2_sb(cr, Q[i]);
+ }
+ cairo_stroke(cr);
+
+ //Normal bundle
+ cairo_set_source_rgba (cr, 0., 0., 0., 1);
+ NBdle.draw(cr,3,5);
+ cairo_stroke(cr);
+
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+public:
+ NormalBundleToy(){
+ if(handles.empty()) {
+ handles.push_back(&B_handle);
+ handles.push_back(&P_handle);
+ handles.push_back(&O_handle);
+ for(unsigned i = 0; i < 4; i++)
+ B_handle.push_back(200+50*i,400);
+ for(unsigned i = 0; i < 4; i++)
+ P_handle.push_back(100+uniform()*400,
+ 150+uniform()*100);
+ O_handle.pos = Geom::Point(200,200);
+ }
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new NormalBundleToy);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+
+
diff --git a/src/3rdparty/2geom/src/toys/offset-toy.cpp b/src/3rdparty/2geom/src/toys/offset-toy.cpp
new file mode 100644
index 0000000..4b3e617
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/offset-toy.cpp
@@ -0,0 +1,156 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/sbasis-math.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/path-intersection.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <sstream>
+
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+// TODO:
+// use path2
+// replace Ray stuff with path2 line segments.
+
+//-----------------------------------------------
+
+static void
+plot_offset(cairo_t* cr, D2<SBasis> const &M,
+ Coord offset = 10,
+ unsigned NbPts = 10){
+ D2<SBasis> dM = derivative(M);
+ for (unsigned i = 0;i < NbPts;i++){
+ double t = i*1./NbPts;
+ Point V = dM(t);
+ V = offset*rot90(unit_vector(V));
+ draw_handle(cr, M(t)+V);
+ }
+}
+
+static void plot(cairo_t* cr, Piecewise<SBasis> const &f,double vscale=1){
+ D2<Piecewise<SBasis> > plot;
+ plot[1]=-f*vscale;
+ plot[1]+=450;
+
+ plot[0].cuts.push_back(f.cuts.front());
+ plot[0].cuts.push_back(f.cuts.back());
+ plot[0].segs.emplace_back(Linear(150,450));
+
+ for (unsigned i=1; i<f.size(); i++){
+ double t=f.cuts[i],ft=f.segs[i].at0();
+ cairo_move_to(cr, Point(150+t*300, 450));
+ cairo_line_to(cr, Point(150+t*300, 450-ft*vscale));
+ }
+ cairo_d2_pw_sb(cr, plot);
+}
+
+
+
+class OffsetTester: public Toy {
+ PointSetHandle psh;
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ D2<SBasis> B = psh.asBezier();
+ *notify << "Curve offset:" << endl;
+ *notify << " -blue: pointwise plotted offset," << endl;
+ *notify << " -red: rot90(unitVector(derivative(.)))+rays at cut" << endl;
+ *notify << " -gray: cos(atan2),sin(atan2)" << endl;
+
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0., 0.5, 0., 1);
+ cairo_d2_sb(cr, B);
+ cairo_stroke(cr);
+
+ Coord offset = -100;
+ plot_offset(cr,B,offset,11);
+ cairo_set_source_rgba (cr, 0, 0, 1, 1);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba (cr, 0.5, 0.2, 0., 0.8);
+ Piecewise<D2<SBasis> > n = rot90(unitVector(derivative(B)));
+ Piecewise<D2<SBasis> > offset_curve = Piecewise<D2<SBasis> >(B)+n*offset;
+ PathVector offset_path = path_from_piecewise(offset_curve, 0.1);
+
+ cairo_path(cr, offset_path);
+ cairo_stroke(cr);
+ for(const auto & pi : offset_path) {
+ Crossings cs = self_crossings(pi);
+ for(auto & c : cs) {
+ draw_cross(cr, pi.pointAt(c.ta));
+ std::stringstream s;
+ Point Pa = pi.pointAt(c.ta);
+ Point Pb = pi.pointAt(c.tb);
+ s << L1(Pa - Pb) << std::endl;
+ std::string ss = s.str();
+ draw_text(cr, Pa+Point(3,3), ss.c_str(), false, "Serif 6");
+
+ }
+ }
+
+ for(unsigned i = 0; i < n.size()+1;i++){
+ Point ptA=B(n.cuts[i]), ptB;
+ if (i==n.size())
+ ptB=ptA+n.segs[i-1].at1()*offset;
+ else
+ ptB=ptA+n.segs[i].at0()*offset;
+ cairo_move_to(cr,ptA);
+ cairo_line_to(cr,ptB);
+ cairo_set_source_rgba (cr, 1, 0, 0, 1);
+ cairo_stroke(cr);
+ }
+
+ Piecewise<SBasis> alpha = atan2(derivative(B),1e-2,3);
+ plot(cr,alpha,75/M_PI);
+
+ Piecewise<D2<SBasis> >n2 = sectionize(D2<Piecewise<SBasis> >(sin(alpha),cos(alpha)));
+ cairo_pw_d2_sb(cr,Piecewise<D2<SBasis> >(B)+n2*offset*.9);
+ cairo_set_source_rgba (cr, 0.5, 0.2, 0.5, 0.8);
+ cairo_stroke(cr);
+
+ Piecewise<SBasis> k = curvature(B);
+ cairo_pw_d2_sb(cr,Piecewise<D2<SBasis> >(B)+k*n*100);
+ cairo_set_source_rgba (cr, 0.5, 0.2, 0.5, 0.8);
+ cairo_stroke(cr);
+
+ *notify << "Total length: " << length(B) << endl;
+ *notify << "(nb of cuts of unitVector: " << n.size()-1 << ")" << endl;
+ *notify << "(nb of cuts of cos,sin(atan2): " << n2.size()-1 << ")" << endl;
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+public:
+ OffsetTester(int order) {
+ handles.push_back(&psh);
+ for(int i = 0; i < order; i++)
+ psh.push_back(200+50*i,300+70*uniform());
+ }
+};
+
+int main(int argc, char **argv) {
+ int A_bez_ord = 6;
+ if(argc > 1)
+ sscanf(argv[1], "%d", &A_bez_ord);
+ init(argc, argv, new OffsetTester(A_bez_ord));
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+//vim:filetype = cpp:expandtab:shiftwidth = 4:tabstop = 8:softtabstop = 4:encoding = utf-8:textwidth = 99 :
+
+
diff --git a/src/3rdparty/2geom/src/toys/pair-intersect.cpp b/src/3rdparty/2geom/src/toys/pair-intersect.cpp
new file mode 100644
index 0000000..9cc01ca
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/pair-intersect.cpp
@@ -0,0 +1,147 @@
+#include <2geom/basic-intersection.h>
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/path-intersection.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+using std::vector;
+using namespace Geom;
+
+class PairIntersect: public Toy {
+ PointSetHandle A_handles;
+ PointSetHandle B_handles;
+ std::vector<Toggle> toggles;
+ void mouse_pressed(GdkEventButton* e) override {
+ toggle_events(toggles, e);
+ Toy::mouse_pressed(e);
+ }
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+
+ draw_toggles(cr, toggles);
+ cairo_save(cr);
+ cairo_set_source_rgba(cr, 0, 0, 0, 1.0);
+ cairo_set_line_width (cr, 0.5);
+ D2<SBasis> A = A_handles.asBezier();
+ cairo_d2_sb(cr, A);
+ cairo_stroke(cr);
+ cairo_set_source_rgba(cr, 0.0, 0, 0.8, 1.0);
+ cairo_set_line_width (cr, 0.5);
+ D2<SBasis> B = B_handles.asBezier();
+ cairo_d2_sb(cr, B);
+ cairo_stroke(cr);
+
+ cairo_save(cr);
+ cairo_set_source_rgba(cr, 0, 0, 0, 1.0);
+ cairo_set_line_width (cr, 0.5);
+ SBasis crs (cross(A - A(0), derivative(A)));
+ crs = shift(crs*Linear(-1, 0)*Linear(-1, 0), -2);
+ crs = crs * (300/(*bounds_exact(crs)).extent());
+ vector<double> rts = roots(crs);
+ for(double t : rts) {
+ cairo_move_to(cr, A(0));
+ cairo_line_to(cr, A(t));
+ cairo_stroke(cr);
+ }
+ cairo_restore(cr);
+ cairo_move_to(cr, 0, 300);
+ cairo_line_to(cr, width, 300);
+ crs += 300;
+ D2<SBasis > are_graph(SBasis(Linear(0, width)), crs );
+ cairo_save(cr);
+ cairo_d2_sb(cr, are_graph);
+ cairo_set_line_width (cr, .5);
+ cairo_set_source_rgba (cr, 0., 0., 0., 1);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+
+ Path PB;
+ PB.append(B);
+ Path PA;
+ PA.append(A);
+
+ if (toggles[0].on) {
+ PathVector ps;
+ ps.push_back(PA);
+ ps.push_back(PB);
+ CrossingSet cs = crossings_among(ps);
+ *notify << "total intersections: " << cs.size() << '\n';
+ cairo_stroke(cr);
+ cairo_set_source_rgba (cr, 1., 0., 0, 0.8);
+ for(unsigned i = 0; i < cs.size(); i++) {
+ Crossings section = cs[i];
+ *notify << "section " << i << ": " << section.size() << '\n';
+ for(auto & j : section) {
+ draw_handle(cr, A(j.ta));
+ *notify << Geom::distance(A(j.ta), B(j.tb))
+ << std::endl;
+ }
+ }
+
+ cairo_stroke(cr);
+ } else {
+ vector<Geom::Point> Ab = A_handles.pts, Bb = B_handles.pts;
+ std::vector<std::pair<double, double> > section;
+ find_intersections( section, A, B);
+ std::vector<std::pair<double, double> > polished_section = section;
+ *notify << "total intersections: " << section.size();
+ polish_intersections( polished_section, A, B);
+ cairo_stroke(cr);
+ cairo_set_source_rgba (cr, 1., 0., 0, 0.8);
+ for(unsigned i = 0; i < section.size(); i++) {
+ draw_handle(cr, A(section[i].first));
+ *notify << Geom::distance(A(section[i].first), B(section[i].second))
+ << " polished "
+ << Geom::distance(A(polished_section[i].first), B(polished_section[i].second))
+ << std::endl;
+ }
+
+ cairo_stroke(cr);
+ }
+ cairo_restore(cr);
+
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+}
+public:
+ PairIntersect (unsigned A_bez_ord, unsigned B_bez_ord) {
+ toggles.emplace_back("Path", true);
+ toggles[0].bounds = Rect(Point(10,100), Point(100, 130));
+ //toggles.push_back(Toggle("Curve", true));
+ //toggles[1].bounds = Rect(Point(10,130), Point(100, 160));
+ handles.push_back(&A_handles);
+ handles.push_back(&B_handles);
+ A_handles.name = "A";
+ B_handles.name = "B";
+ for(unsigned i = 0; i < A_bez_ord; i++)
+ A_handles.push_back(uniform()*400, uniform()*400);
+ for(unsigned i = 0; i < B_bez_ord; i++)
+ B_handles.push_back(uniform()*400, uniform()*400);
+}
+};
+
+int main(int argc, char **argv) {
+unsigned A_bez_ord=10;
+unsigned B_bez_ord=3;
+ if(argc > 2)
+ sscanf(argv[2], "%d", &B_bez_ord);
+ if(argc > 1)
+ sscanf(argv[1], "%d", &A_bez_ord);
+ init(argc, argv, new PairIntersect(A_bez_ord, B_bez_ord));
+
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/paptest.cpp b/src/3rdparty/2geom/src/toys/paptest.cpp
new file mode 100644
index 0000000..4ea2cd2
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/paptest.cpp
@@ -0,0 +1,107 @@
+/*
+ * A simple toy to test the path along path
+ *
+ * Copyright 2007 Johan Engelen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+
+#include <iostream>
+#include <2geom/path-sink.h>
+#include <2geom/svg-path-parser.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/d2.h>
+#include <2geom/piecewise.h>
+
+Geom::Piecewise<Geom::D2<Geom::SBasis> >
+doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > & pwd2_in, Geom::Piecewise<Geom::D2<Geom::SBasis> > & pattern)
+{
+ using namespace Geom;
+
+ Piecewise<D2<SBasis> > uskeleton = arc_length_parametrization(pwd2_in, 2, .1);
+ uskeleton = remove_short_cuts(uskeleton,.01);
+ Piecewise<D2<SBasis> > n = rot90(derivative(uskeleton));
+ n = force_continuity(remove_short_cuts(n,.1));
+
+ D2<Piecewise<SBasis> > patternd2 = make_cuts_independent(pattern);
+ Piecewise<SBasis> x = Piecewise<SBasis>(patternd2[0]);
+ Piecewise<SBasis> y = Piecewise<SBasis>(patternd2[1]);
+ Interval pattBnds = *bounds_exact(x);
+ x -= pattBnds.min();
+ Interval pattBndsY = *bounds_exact(y);
+ y -= (pattBndsY.max()+pattBndsY.min())/2;
+
+ int nbCopies = int(uskeleton.cuts.back()/pattBnds.extent());
+ double scaling = 1;
+
+ double pattWidth = pattBnds.extent() * scaling;
+
+ if (scaling != 1.0) {
+ x*=scaling;
+ }
+
+ double offs = 0;
+ Piecewise<D2<SBasis> > output;
+ for (int i=0; i<nbCopies; i++){
+ output.concat(compose(uskeleton,x+offs)+y*compose(n,x+offs));
+ offs+=pattWidth;
+ }
+
+ return output;
+}
+
+int main(int argc, char **argv) {
+ if (argc > 1) {
+ Geom::PathVector originald = Geom::parse_svg_path(&*argv[1]);
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > originaldpwd2;
+ for (const auto & i : originald) {
+ originaldpwd2.concat( i.toPwSb() );
+ }
+
+ Geom::PathVector pattern = Geom::parse_svg_path(&*argv[2]);
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > patternpwd2;
+ for (const auto & i : pattern) {
+ patternpwd2.concat( i.toPwSb() );
+ }
+
+ doEffect_pwd2(originaldpwd2, patternpwd2);
+ }
+ return 0;
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/parametrics.cpp b/src/3rdparty/2geom/src/toys/parametrics.cpp
new file mode 100644
index 0000000..2d2538c
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/parametrics.cpp
@@ -0,0 +1,229 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/path.h>
+#include <2geom/svg-path-parser.h>
+#include <2geom/sbasis-math.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <2geom/affine.h>
+
+#include <glib.h>
+#include <vector>
+#include <iostream>
+using std::vector;
+using namespace Geom;
+
+int mode;
+
+static void dot_plot(cairo_t *cr, Piecewise<D2<SBasis> > const &M, double max, double space=10){
+ Piecewise<D2<SBasis> > Mperp = rot90(derivative(M)) * 3;
+ for( double t = M.cuts.front(); t < max; t += space) {
+ Point pos = M(t), perp = Mperp(t);
+ draw_line_seg(cr, pos + perp, pos - perp);
+ }
+ cairo_stroke(cr);
+}
+
+static void draw_axis(cairo_t *cr, Piecewise<D2<SBasis> > const &pw, unsigned d, Affine m) {
+ double mult;
+ if(abs(mode)==1) mult = 20;
+ if(abs(mode)==2) mult = 1;
+ if(abs(mode)==3) mult = 100;
+ if(abs(mode)==4) mult = 20;
+ if(abs(mode)==5) mult = 20;
+ if(abs(mode)==6) mult = 100;
+ for(unsigned i = 0; i < pw.size(); i++) {
+ cairo_d2_sb(cr, D2<SBasis>(SBasis(pw.cuts[i]-pw.cuts[0], pw.cuts[i+1]-pw.cuts[0])*mult, SBasis(pw[i][d]))*m);
+ }
+}
+/*
+void dump_latex(PathVector ps) {
+ for(unsigned d = 0; d < 2; d++) {
+ std::cout << "$$\n" << (d?"y":"x") << "(t) = \\left\\{\n\\begin{array}{ll}\n";
+ int seg = 0;
+ for(unsigned i = 0; i < ps.size(); i++)
+ for(unsigned j = 0; j < ps[i].size(); j++) {
+ Bezier<3> &b = dynamic_cast<Bezier<3>& >(const_cast<Curve&>(ps[i][j]));
+ std::cout << b[0][d] << "(" << seg+1 << "-t)^3 + "
+ << 3*b[1][d] << "t(" << seg+1 << "-t)^2 + "
+ << 3*b[2][d] << "t^2(" << seg+1 << "-t) + "
+ << b[3][d] << "t^3,& " << seg << "\\leq t < " << seg+1 << "\\\\\n";
+ seg++;
+ }
+ std::cout << "\\end{array}\n$$\n";
+ }
+}
+*/
+class Parametrics: public Toy {
+ Piecewise<D2<SBasis> > cat, alcat, box, arc, monk, traj;
+#ifdef USE_TIME
+ GTimer* time;
+ bool st;
+#endif
+ double waitt;
+ double t;
+ int count;
+ void draw(cairo_t *cr,
+ std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override {
+ //double t = handles[0][0] / 20.;
+
+#ifdef USE_TIME
+ gulong* foo = 0;
+ t = g_timer_elapsed(time, foo) * 100;
+#else
+ double inc;
+ if(mode==1) inc = .1;
+ if(mode==2) inc = 5;
+ if(mode==3) inc = .01;
+ if(mode==4) inc = .04;
+ if(mode==5) inc = .1;
+ if(mode==6) inc = .01;
+ if(mode<0) inc = .01*M_PI;
+ if(!save && !waitt) {
+ t += inc;
+ }
+ if(waitt) waitt += 1;
+ if(waitt>20) waitt = 0;
+#endif
+ Piecewise<D2<SBasis> > obj;
+ if(abs(mode)==1) obj = cat;
+ if(abs(mode)==2) obj = alcat;
+ if(abs(mode)==3) obj = arc;
+ if(abs(mode)==4) obj = box;
+ if(abs(mode)==5) obj = monk;
+ if(abs(mode)==6) obj = traj;
+ if(t==obj.cuts.back()) t += inc/2;
+ cairo_set_source_rgb(cr, 1,1,1);
+ if(save) {
+ cairo_rectangle(cr, 0, 0, width, height);
+ cairo_fill(cr);
+ }
+ Piecewise<D2<SBasis> > port, rport;
+ if(mode>0) {
+ port = portion(obj, 0, t);
+ rport = mode>0? portion(obj, t, obj.cuts[obj.size()]) : obj;
+ cairo_set_source_rgba (cr, 0., 0., 0., 1);
+ Point curpt = rport[0].at0();
+ if(t<obj.cuts.back()) {
+ draw_line_seg(cr, curpt, Point(curpt[0], 350));
+ draw_line_seg(cr, curpt, Point(350, curpt[1]));
+ cairo_stroke(cr);
+ }
+
+ char tlab[64];
+ sprintf(tlab, "t=%.02f", t);
+ draw_text(cr, curpt, tlab , true);
+
+ cairo_set_line_width (cr, 2);
+ cairo_set_source_rgba (cr, 0., 0.5, 0., 1);
+ cairo_pw_d2_sb(cr, port);
+ cairo_stroke(cr);
+ }
+ if(mode>=0 && t>=obj.cuts.back()+inc) t = 0;
+ cairo_set_source_rgba (cr, 0.9, 0., 0., 1);
+ if(mode<0) {
+ draw_axis(cr, obj, 0, from_basis(Point(cos(t),sin(t)),Point(sin(t),-cos(t)),Point(0, 350)));
+ if(cos(t) <= 0) {
+ mode = -mode;
+ t = 0;
+ waitt = 1;
+ }
+ } else
+ draw_axis(cr, rport, 0, from_basis(Point(0,1),Point(1,0),Point(0, 350)));
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba (cr, 0., 0., 0.9, 1);
+ if(mode<0)
+ draw_axis(cr, obj, 1, from_basis(Point(1,0),Point(0,1),Point(350*t/M_PI*2, 0)));
+ else
+ draw_axis(cr, rport, 1, from_basis(Point(1,0),Point(0,1),Point(350, 0)));
+ cairo_stroke(cr);
+
+ if(mode==2 && t>0) {
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0., 0., 0.9, 1);
+ dot_plot(cr, port, t);
+ cairo_stroke(cr);
+ }
+
+ if(!save) {
+ char file[100];
+ sprintf(file, "output/%04d.png", count);
+ //take_screenshot(file);
+ count++;
+ }
+ // *notify << "pieces = " << alcat.size() << ";\n";
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ redraw();
+ }
+
+#ifdef USE_TIME
+ virtual void mouse_moved(GdkEventMotion* e) {
+ if(st) {
+ g_timer_start(time);
+ st = false;
+ }
+ Toy::mouse_moved(e);
+ }
+#endif
+
+ public:
+ Parametrics(){
+ mode = 2;
+ PathVector cp = read_svgd("cat.svgd");
+ //dump_latex(cp);
+ cat = paths_to_pw(cp);
+ cat *= .3;
+ cat += Point(50, 50);
+ alcat = arc_length_parametrization(cat);
+
+ monk = paths_to_pw(read_svgd("monkey.svgd"));
+ //monk *= .3;
+ monk += Point(50,50);
+
+ arc = sectionize(D2<Piecewise<SBasis> >(cos(Linear(0,M_PI))*120, sin(Linear(0,M_PI))*-120));
+ arc += Point(200, 200);
+
+ box = Piecewise<D2<SBasis> >();
+ box.push_cut(0);
+ box.push(D2<SBasis>(SBasis(100.,300.), SBasis(100.)), 1);
+ box.push(D2<SBasis>(SBasis(300.), SBasis(100.,300.)), 2);
+ box.push(D2<SBasis>(SBasis(300.,100.), SBasis(300.)), 3);
+ box.push(D2<SBasis>(SBasis(100.), SBasis(300.,100.)), 4);
+ //handles.push_back(Point(100, 100));
+ traj = Piecewise<D2<SBasis> >();
+ SBasis quad = Linear(0,1)*Linear(0,1)*256-Linear(0,256)+200;
+ traj.push_cut(0);
+ traj.push(D2<SBasis>(SBasis(100.,300.),SBasis(quad)), 1);
+#ifdef USE_TIME
+ time = g_timer_new();
+ g_timer_reset(time);
+ st = true;
+#endif
+ waitt = 0;
+ count = 0;
+ t = 0;
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new Parametrics, 720, 480);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+//vim:filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99:
diff --git a/src/3rdparty/2geom/src/toys/parser.cpp b/src/3rdparty/2geom/src/toys/parser.cpp
new file mode 100644
index 0000000..c7950e5
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/parser.cpp
@@ -0,0 +1,108 @@
+/*
+ * A simple toy to test the parser
+ *
+ * Copyright 2007 Aaron Spike <aaron@ekips.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+
+#include <iostream>
+#include <2geom/path-sink.h>
+#include <2geom/svg-path-parser.h>
+
+class SVGPathTestPrinter : public Geom::PathSink {
+public:
+ void moveTo(Geom::Point const &p) override {
+ std::cout << "M " << p << std::endl;
+ }
+
+ void hlineTo(Geom::Coord v) {
+ std::cout << "H " << v << std::endl;
+ }
+
+ void vlineTo(Geom::Coord v) {
+ std::cout << "V " << v << std::endl;
+ }
+
+ void lineTo(Geom::Point const &p) override {
+ std::cout << "L " << p << std::endl;
+ }
+
+ void curveTo(Geom::Point const &c0, Geom::Point const &c1, Geom::Point const &p) override {
+ std::cout << "C " << c0 << " " << c1 << " " << p << std::endl;
+ }
+
+ void quadTo(Geom::Point const &c, Geom::Point const &p) override {
+ std::cout << "Q " << c << " " << p << std::endl;
+ }
+
+ void arcTo(double rx, double ry, double angle,
+ bool large_arc, bool sweep, Geom::Point const &p) override
+ {
+ std::cout << "A " << rx << " " << ry << " " << angle << " " << large_arc << " " << sweep << " " << p << std::endl;
+ }
+
+ bool backspace() override
+ {
+ //std::cout << "[remove last segment]" << std::endl;
+ return false;
+ }
+
+ void closePath() override {
+ std::cout << "Z" << std::endl;
+ }
+
+ void flush() override {
+ ;
+ }
+
+};
+
+
+int main(int argc, char **argv) {
+ if (argc > 1) {
+ SVGPathTestPrinter sink;
+ Geom::parse_svg_path(&*argv[1], sink);
+ std::cout << "Try real pathsink:" << std::endl;
+ Geom::PathVector testpath = Geom::parse_svg_path(&*argv[1]);
+ std::cout << "Geom::PathVector length: " << testpath.size() << std::endl;
+ if ( !testpath.empty() )
+ std::cout << "Path curves: " << testpath.front().size() << std::endl;
+ std::cout << "success!" << std::endl;
+ }
+ return 0;
+};
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/path-along-path.cpp b/src/3rdparty/2geom/src/toys/path-along-path.cpp
new file mode 100644
index 0000000..a2a6a1b
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/path-along-path.cpp
@@ -0,0 +1,112 @@
+#include <2geom/d2.h>
+#include <2geom/piecewise.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/bezier-to-sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <algorithm>
+using std::vector;
+using namespace Geom;
+
+class PathAlongPathToy: public Toy {
+ PointSetHandle skel_handles, pat_handles;
+ PointHandle origin_handle;
+ bool should_draw_numbers() override{return false;}
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ D2<SBasis> skeleton = skel_handles.asBezier();
+ D2<SBasis> pattern = pat_handles.asBezier();
+
+
+ cairo_set_line_width(cr,1.);
+ cairo_pw_d2_sb(cr, Piecewise<D2<SBasis> >(skeleton));
+ cairo_set_source_rgba(cr,0.0,0.0,1.0,1.0);
+ cairo_stroke(cr);
+
+ cairo_pw_d2_sb(cr, Piecewise<D2<SBasis> >(pattern));
+ cairo_set_source_rgba(cr,1.0,0.0,1.0,1.0);
+ cairo_stroke(cr);
+
+ origin_handle.pos[0]=150;
+ Geom::Point origin = origin_handle.pos;
+
+ Piecewise<D2<SBasis> > uskeleton = arc_length_parametrization(Piecewise<D2<SBasis> >(skeleton),2,.1);
+ uskeleton = remove_short_cuts(uskeleton,.01);
+ Piecewise<D2<SBasis> > n = rot90(derivative(uskeleton));
+ n = force_continuity(remove_short_cuts(n,.1));
+
+ Piecewise<SBasis> x=Piecewise<SBasis>(pattern[0]-origin[0]);
+ Piecewise<SBasis> y=Piecewise<SBasis>(pattern[1]-origin[1]);
+ Interval pattBnds = *bounds_exact(x);
+ int nbCopies = int(uskeleton.cuts.back()/pattBnds.extent());
+
+ //double pattWidth = uskeleton.cuts.back()/nbCopies;
+ double pattWidth = pattBnds.extent();
+
+ double offs = 0;
+ x-=pattBnds.min();
+ //x*=pattWidth/pattBnds.extent();
+
+ Piecewise<D2<SBasis> >output;
+ for (int i=0; i<nbCopies; i++){
+ output.concat(compose(uskeleton,x+offs)+y*compose(n,x+offs));
+ offs+=pattWidth;
+ }
+
+ //Perform cut for last segment
+ double tt = uskeleton.cuts.back() - offs;
+ if(tt > 0.) {
+ vector<double> rs = roots(x - tt);
+ rs.push_back(0); rs.push_back(1); //regard endpoints
+ std::sort(rs.begin(), rs.end());
+ std::unique(rs.begin(), rs.end());
+ //enumerate indices of sections to the left of the line
+ for(unsigned i = (x[0].at0()>tt ? 1 : 0); i < rs.size()-1; i+=2) {
+ Piecewise<SBasis> port = portion(x+offs, rs[i], rs[i+1]);
+ output.concat(compose(uskeleton,port)+portion(y, rs[i], rs[i+1])*compose(n,port));
+ }
+ }
+
+ cairo_pw_d2_sb(cr, output);
+ cairo_set_source_rgba(cr,1.0,0.0,1.0,1.0);
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+public:
+ PathAlongPathToy() : origin_handle(150,150) {
+ if(handles.empty()) {
+ handles.push_back(&skel_handles);
+ handles.push_back(&pat_handles);
+ for(int i = 0; i < 8; i++)
+ skel_handles.push_back(200+50*i,400);
+ for(int i = 0; i < 4; i++)
+ pat_handles.push_back(100+uniform()*400,
+ 150+uniform()*100);
+
+ handles.push_back(&origin_handle);
+ }
+ }
+};
+
+
+int main(int argc, char **argv) {
+ init(argc, argv, new PathAlongPathToy);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+
diff --git a/src/3rdparty/2geom/src/toys/path-cairo.cpp b/src/3rdparty/2geom/src/toys/path-cairo.cpp
new file mode 100644
index 0000000..73c2a59
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/path-cairo.cpp
@@ -0,0 +1,342 @@
+#include <cairo.h>
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/utils.h>
+#include <sstream>
+#include <optional>
+
+using namespace Geom;
+
+void cairo_rectangle(cairo_t *cr, Rect const& r) {
+ cairo_rectangle(cr, r.left(), r.top(), r.width(), r.height());
+}
+
+void cairo_convex_hull(cairo_t *cr, ConvexHull const& ch) {
+ if(ch.empty()) return;
+ cairo_move_to(cr, ch[ch.size()-1]);
+ for(auto i : ch) {
+ cairo_line_to(cr, i);
+ }
+}
+
+void cairo_curve(cairo_t *cr, Curve const& c) {
+ if(!cairo_has_current_point(cr))
+ cairo_move_to(cr, c.initialPoint());
+
+ if(LineSegment const* line_segment = dynamic_cast<LineSegment const*>(&c)) {
+ cairo_line_to(cr, (*line_segment)[1][0], (*line_segment)[1][1]);
+ }
+ else if(QuadraticBezier const *quadratic_bezier = dynamic_cast<QuadraticBezier const*>(&c)) {
+ std::vector<Point> points = quadratic_bezier->controlPoints();
+ Point b1 = points[0] + (2./3) * (points[1] - points[0]);
+ Point b2 = b1 + (1./3) * (points[2] - points[0]);
+ cairo_curve_to(cr, b1[0], b1[1],
+ b2[0], b2[1],
+ points[2][0], points[2][1]);
+ }
+ else if(CubicBezier const *cubic_bezier = dynamic_cast<CubicBezier const*>(&c)) {
+ std::vector<Point> points = cubic_bezier->controlPoints();
+ cairo_curve_to(cr, points[1][0], points[1][1], points[2][0], points[2][1], points[3][0], points[3][1]);
+ }
+// else if(EllipticalArc const *svg_elliptical_arc = dynamic_cast<EllipticalArc *>(c)) {
+// //TODO: get at the innards and spit them out to cairo
+// }
+ else {
+ //this case handles sbasis as well as all other curve types
+ Path sbasis_path = cubicbezierpath_from_sbasis(c.toSBasis(), 0.1);
+
+ //recurse to convert the new path resulting from the sbasis to svgd
+ for(const auto & iter : sbasis_path) {
+ cairo_curve(cr, iter);
+ }
+ }
+}
+
+void cairo_path(cairo_t *cr, Path const &p) {
+ cairo_move_to(cr, p.initialPoint()[0], p.initialPoint()[1]);
+ if(p.size() == 0) { // naked moveto
+ cairo_move_to(cr, p.finalPoint()+Point(8,0));
+ cairo_line_to(cr, p.finalPoint()+Point(-8,0));
+ cairo_move_to(cr, p.finalPoint()+Point(0,8));
+ cairo_line_to(cr, p.finalPoint()+Point(0,-8));
+ return;
+ }
+
+ for(const auto & iter : p) {
+ cairo_curve(cr, iter);
+ }
+ if(p.closed())
+ cairo_close_path(cr);
+}
+
+void cairo_path_stitches(cairo_t *cr, Path const &p) {
+ Path::const_iterator iter;
+ for ( iter = p.begin() ; iter != p.end() ; ++iter ) {
+ Curve const &c=*iter;
+ if (dynamic_cast<Path::StitchSegment const *>(&c)) {
+ cairo_move_to(cr, c.initialPoint()[X], c.initialPoint()[Y]);
+ cairo_line_to(cr, c.finalPoint()[X], c.finalPoint()[Y]);
+
+ std::stringstream s;
+ s << L1(c.finalPoint() - c.initialPoint());
+ std::string ss = s.str();
+ draw_text(cr, c.initialPoint()+Point(5,5), ss.c_str(), false, "Serif 6");
+
+ //std::cout << c.finalPoint() - c.initialPoint() << std::endl;
+ }
+ }
+}
+
+void cairo_path_handles(cairo_t */*cr*/, Path const &/*p*/) {
+ //TODO
+}
+
+void cairo_path(cairo_t *cr, PathVector const &p) {
+ PathVector::const_iterator it;
+ for(it = p.begin(); it != p.end(); ++it) {
+ cairo_path(cr, *it);
+ }
+}
+
+void cairo_path_stitches(cairo_t *cr, PathVector const &p) {
+ PathVector::const_iterator it;
+ for ( it = p.begin() ; it != p.end() ; ++it ) {
+ cairo_path_stitches(cr, *it);
+ }
+}
+
+void cairo_d2_sb(cairo_t *cr, D2<SBasis> const &B) {
+ cairo_path(cr, path_from_sbasis(B, 0.1));
+}
+
+void cairo_d2_sb2d(cairo_t* cr, D2<SBasis2d> const &sb2, Point /*dir*/, double width) {
+ D2<SBasis> B;
+ for(int ui = 0; ui <= 10; ui++) {
+ double u = ui/10.;
+ B[0] = extract_u(sb2[0], u);// + Linear(u);
+ B[1] = extract_u(sb2[1], u);
+ for(unsigned i = 0; i < 2; i ++) {
+ B[i] = B[i]*(width/2) + Linear(width/4);
+ }
+ cairo_d2_sb(cr, B);
+ }
+ for(int vi = 0; vi <= 10; vi++) {
+ double v = vi/10.;
+ B[1] = extract_v(sb2[1], v);// + Linear(v);
+ B[0] = extract_v(sb2[0], v);
+ for(unsigned i = 0; i < 2; i ++) {
+ B[i] = B[i]*(width/2) + Linear(width/4);
+ }
+ cairo_d2_sb(cr, B);
+ }
+}
+
+void cairo_sb2d(cairo_t* cr, SBasis2d const &sb2, Point dir, double width) {
+ D2<SBasis> B;
+ for(int ui = 0; ui <= 10; ui++) {
+ double u = ui/10.;
+ B[0] = extract_u(sb2, u)*dir[0] + Linear(u);
+ B[1] = SBasis(Linear(0,1)) + extract_u(sb2, u)*dir[1];
+ for(unsigned i = 0; i < 2; i ++) {
+ B[i] = B[i]*(width/2) + Linear(width/4);
+ }
+ cairo_d2_sb(cr, B);
+ }
+ for(int vi = 0; vi <= 10; vi++) {
+ double v = vi/10.;
+ B[1] = extract_v(sb2, v)*dir[1] + Linear(v);
+ B[0] = SBasis(Linear(0,1)) + extract_v(sb2, v)*dir[0];
+ for(unsigned i = 0; i < 2; i ++) {
+ B[i] = B[i]*(width/2) + Linear(width/4);
+ }
+ cairo_d2_sb(cr, B);
+ }
+}
+
+void cairo_d2_pw_sb(cairo_t *cr, D2<Piecewise<SBasis> > const &p) {
+ cairo_pw_d2_sb(cr, sectionize(p));
+}
+
+void cairo_pw_d2_sb(cairo_t *cr, Piecewise<D2<SBasis> > const &p) {
+ for(unsigned i = 0; i < p.size(); i++)
+ cairo_d2_sb(cr, p[i]);
+}
+
+
+void draw_line_seg(cairo_t *cr, Geom::Point a, Geom::Point b) {
+ cairo_move_to(cr, a[0], a[1]);
+ cairo_line_to(cr, b[0], b[1]);
+ cairo_stroke(cr);
+}
+
+void draw_spot(cairo_t *cr, Geom::Point h) {
+ draw_line_seg(cr, h, h);
+}
+
+void draw_handle(cairo_t *cr, Geom::Point h) {
+ double x = h[Geom::X];
+ double y = h[Geom::Y];
+ cairo_move_to(cr, x-3, y);
+ cairo_line_to(cr, x+3, y);
+ cairo_move_to(cr, x, y-3);
+ cairo_line_to(cr, x, y+3);
+}
+
+void draw_cross(cairo_t *cr, Geom::Point h) {
+ double x = h[Geom::X];
+ double y = h[Geom::Y];
+ cairo_move_to(cr, x-3, y-3);
+ cairo_line_to(cr, x+3, y+3);
+ cairo_move_to(cr, x+3, y-3);
+ cairo_line_to(cr, x-3, y+3);
+}
+
+void draw_circ(cairo_t *cr, Geom::Point h) {
+ int x = int(h[Geom::X]);
+ int y = int(h[Geom::Y]);
+ cairo_new_sub_path(cr);
+ cairo_arc(cr, x, y, 3, 0, M_PI*2);
+ cairo_stroke(cr);
+}
+
+void draw_ray(cairo_t *cr, Geom::Point h, Geom::Point dir) {
+ draw_line_seg(cr, h, h+dir);
+ Point unit = 3*unit_vector(dir),
+ rot = rot90(unit);
+ draw_line_seg(cr, h+dir, h + dir - unit + rot);
+ draw_line_seg(cr, h+dir, h + dir - unit - rot);
+}
+
+
+void
+cairo_move_to (cairo_t *cr, Geom::Point p1) {
+ cairo_move_to(cr, p1[0], p1[1]);
+}
+
+void
+cairo_line_to (cairo_t *cr, Geom::Point p1) {
+ cairo_line_to(cr, p1[0], p1[1]);
+}
+
+void
+cairo_curve_to (cairo_t *cr, Geom::Point p1,
+ Geom::Point p2, Geom::Point p3) {
+ cairo_curve_to(cr, p1[0], p1[1],
+ p2[0], p2[1],
+ p3[0], p3[1]);
+}
+/*
+ void draw_string(GtkWidget *widget, string s, int x, int y) {
+ PangoLayout *layout = gtk_widget_create_pango_layout(widget, s.c_str());
+ cairo_t* cr = gdk_cairo_create (widget->window);
+ cairo_move_to(cr, x, y);
+ pango_cairo_show_layout(cr, layout);
+ cairo_destroy (cr);
+ }*/
+
+// H in [0,360)
+// S, V, R, G, B in [0,1]
+void convertHSVtoRGB(const double H, const double S, const double V,
+ double& R, double& G, double& B) {
+ int Hi = int(floor(H/60.)) % 6;
+ double f = H/60. - Hi;
+ double p = V*(1-S);
+ double q = V*(1-f*S);
+ double t = V*(1-(1-f)*S);
+ switch(Hi) {
+ case 0: R=V, G=t, B=p; break;
+ case 1: R=q, G=V, B=p; break;
+ case 2: R=p, G=V, B=t; break;
+ case 3: R=p, G=q, B=V; break;
+ case 4: R=t, G=p, B=V; break;
+ case 5: R=V, G=p, B=q; break;
+ }
+}
+
+void draw_line(cairo_t *cr, double a, double b, double c, const Geom::Rect& r) {
+ Geom::Line l(a, b, c);
+ std::optional<Geom::LineSegment> seg = l.clip(r);
+ if (seg) {
+ cairo_move_to(cr, seg->initialPoint());
+ cairo_line_to(cr, seg->finalPoint());
+ cairo_stroke(cr);
+ }
+}
+
+
+void draw_line(cairo_t* cr, const Geom::Line& l, const Geom::Rect& r)
+{
+ std::vector<double> coeff = l.coefficients();
+ draw_line (cr, coeff[0], coeff[1], coeff[2], r);
+}
+
+
+void draw_line(cairo_t *cr, Geom::Point n, double dist, Geom::Rect r) {
+ draw_line(cr, n[0], n[1], dist, r);
+}
+
+
+void draw_ray(cairo_t *cr, const Geom::Ray& ray, const Geom::Rect& r)
+{
+ LineSegment ls;
+
+ for (size_t i = 0; i < 4; ++i)
+ {
+ ls.setInitial (r.corner(i));
+ ls.setFinal (r.corner(i+1));
+ OptCrossing cx = intersection (ls, ray);
+ if (cx)
+ {
+ Point P = ray.pointAt ((*cx).tb);
+ draw_line_seg (cr, ray.origin(), P);
+ break;
+ }
+ }
+}
+
+void draw_line_segment(cairo_t *cr, const Geom::LineSegment& ls, const Geom::Rect& r)
+{
+ if(r.contains(ls[0])) {
+ if(r.contains(ls[1])) {
+ draw_line_seg(cr, ls[0], ls[1]);
+ } else {
+ draw_ray(cr, Geom::Ray(ls[0], ls[1]), r);
+ }
+
+ } else {
+ if(r.contains(ls[1])) {
+ draw_ray(cr, Geom::Ray(ls[1], ls[0]), r);
+ } else {
+ draw_line(cr, Geom::Line(ls[0], ls[1]), r);
+ }
+
+ }
+}
+
+void draw_line_seg_with_arrow(cairo_t *cr, Geom::Point a, Geom::Point b, double dangle, double radius) {
+ double angle = atan2(a-b);
+ cairo_move_to(cr, a);
+ cairo_line_to(cr, b);
+
+ cairo_move_to(cr, b);
+ cairo_line_to(cr, Point::polar(angle + dangle, radius) + b);
+ cairo_move_to(cr, b);
+ cairo_line_to(cr, Point::polar(angle - dangle, radius) + b);
+ cairo_stroke(cr);
+}
+
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(substatement-open . 0))
+ indent-tabs-mode:nil
+ c-brace-offset:0
+ fill-column:99
+ End:
+ vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+*/
diff --git a/src/3rdparty/2geom/src/toys/path-effects.cpp b/src/3rdparty/2geom/src/toys/path-effects.cpp
new file mode 100644
index 0000000..fdd7ef0
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/path-effects.cpp
@@ -0,0 +1,140 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+
+#include <2geom/path.h>
+#include <2geom/pathvector.h>
+#include <2geom/svg-path-parser.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <2geom/transforms.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/sbasis-math.h>
+
+#include <cstdlib>
+
+using namespace Geom;
+
+Piecewise<SBasis > sore_tooth(Interval intv) {
+ Piecewise<SBasis > out;
+ double t = intv.min();
+ Point p(0,0);
+ out.push_cut(0);
+ double r = 20;
+ double dir = 0.5;
+ while(t < intv.max()) {
+ double nt = t + 10;
+ if(nt > intv.max())
+ nt = intv.max();
+ SBasis zag(r*Linear(dir,-dir));
+ out.push(zag, nt);
+ t = nt;
+ dir = -dir;
+ }
+ return out;
+}
+
+Piecewise< D2<SBasis> > zaggy(Interval intv, double dt, double radius) {
+ Piecewise<D2<SBasis> > out;
+ double t = intv.min();
+ Point p(0,0);
+ out.push_cut(0);
+ while(t < intv.max()) {
+ double nt = t + uniform()*dt;
+ if(nt > intv.max())
+ nt = intv.max();
+ Point np = Point((uniform()-0.5)*2*radius, (uniform()-0.5)*2*radius);
+ D2<SBasis> zag(SBasis(p[0],np[0]), SBasis(p[1],np[1]));
+ p = np;
+ //std::cout << t <<","<< nt << p << np << std::endl;
+ out.push(zag, nt);
+ t = nt;
+ }
+ return out;
+}
+
+
+class BoolOps: public Toy {
+ PathVector pv;
+ PointHandle offset_handle;
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ Geom::Translate t(offset_handle.pos);
+
+ cairo_set_line_width(cr, 1);
+ cairo_set_source_rgb(cr, 0.75,0.75,1);
+
+ //cairo_shape(cr, bst);
+ cairo_path(cr, pv*t);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgb(cr, 0,0,0);
+ for(const auto & i : pv) {
+ Piecewise<D2<SBasis> > B = i.toPwSb();
+ Piecewise<D2<SBasis> > n = rot90(unitVector(derivative(B)));
+ Piecewise<SBasis > al = arcLengthSb(B);
+
+#if 0
+ Piecewise<D2<SBasis> > offset_curve = Piecewise<D2<SBasis> >(B)+n*offset;
+ PathVector offset_path = path_from_piecewise(offset_curve, 0.1);
+
+ cairo_path(cr, offset_path*t);
+ cairo_stroke(cr);
+#endif
+ //Piecewise<D2<SBasis> > zz_curve = B+zaggy(B.domain(), 0.1, 20);//al*n;
+ //Piecewise<D2<SBasis> > zz_curve = Piecewise<D2<SBasis> >(B)+
+ // compose(sore_tooth(Interval(al.firstValue(),al.lastValue())), al)*n;
+ Piecewise<D2<SBasis> > zz_curve = Piecewise<D2<SBasis> >(B)+
+ sin(al*0.1)*10*n;
+ PathVector zz_path = path_from_piecewise(zz_curve, 0.1);
+
+ cairo_path(cr, zz_path*t);
+ cairo_stroke(cr);
+ }
+ for(const auto & i : pv) {
+ if(i.size() == 0) {
+ *notify << "naked moveto;";
+ } else
+ for(const auto & j : i) {
+ const Curve* c = &j;
+ *notify << typeid(*c).name() << ';' ;
+ }
+ }
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+ public:
+ BoolOps () {}
+
+ void first_time(int argc, char** argv) override {
+ const char *path_b_name="star.svgd";
+ if(argc > 1)
+ path_b_name = argv[1];
+ pv = read_svgd(path_b_name);
+ std::cout << pv.size() << "\n";
+ std::cout << pv[0].size() << "\n";
+ pv *= Translate(-pv[0].initialPoint());
+
+ Rect bounds = *pv[0].boundsExact();
+ handles.push_back(&offset_handle);
+ offset_handle.pos = bounds.midpoint() - bounds.corner(0);
+
+ //bs = cleanup(pv);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new BoolOps());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/path-toy.py b/src/3rdparty/2geom/src/toys/path-toy.py
new file mode 100644
index 0000000..631482f
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/path-toy.py
@@ -0,0 +1,41 @@
+#!/usr/bin/python
+
+import py2geom
+import toyframework
+import random,gtk
+from py2geom_glue import *
+
+class PathToy(toyframework.Toy):
+ def __init__(self):
+ toyframework.Toy.__init__(self)
+ self.handles.append(toyframework.PointHandle(200, 200))
+ self.path_b_name="star.svgd"
+ self.pv = py2geom.read_svgd(self.path_b_name);
+ centr = py2geom.Point()
+ for p in self.pv:
+ c,area = py2geom.centroid(p.toPwSb())
+ centr += c
+ self.pv = self.pv*py2geom.Matrix(py2geom.Translate(-centr))
+ def draw(self, cr, pos, save):
+ cr.set_source_rgba (0., 0., 0., 1)
+ cr.set_line_width (1)
+
+
+ B = (self.pv[0]*py2geom.Matrix(py2geom.Translate(*self.handles[0].pos))).toPwSb();
+ n = py2geom.rot90(py2geom.unit_vector(py2geom.derivative(B), 0.01, 3));
+ al = py2geom.arcLengthSb(B, 0.1);
+ offset = 10.
+
+ offset_curve = B+py2geom.sin(al*0.1, 0.01, 2)*n*10.
+ offset_path = py2geom.path_from_piecewise(offset_curve, 0.1, True)
+
+ py2geom.cairo_path(cr, offset_path)
+ cr.stroke()
+
+ self.notify = ''
+ toyframework.Toy.draw(self, cr, pos, save)
+
+t = PathToy()
+import sys
+
+toyframework.init(sys.argv, t, 500, 500)
diff --git a/src/3rdparty/2geom/src/toys/pencil-2.cpp b/src/3rdparty/2geom/src/toys/pencil-2.cpp
new file mode 100644
index 0000000..a312083
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/pencil-2.cpp
@@ -0,0 +1,1133 @@
+/*
+ * pencil-2 Toy - point fitting.
+ *
+ * 2009 njh
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/basic-intersection.h>
+#include <2geom/math-utils.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#define SP_HUGE 1e5
+#define noBEZIER_DEBUG
+
+#ifdef HAVE_IEEEFP_H
+# include <ieeefp.h>
+#endif
+
+namespace Geom{
+
+namespace BezierFitter{
+
+typedef Point BezierCurve[];
+
+/* Forward declarations */
+static void generate_bezier(Point b[], Point const d[], double const u[], unsigned len,
+ Point const &tHat1, Point const &tHat2, double tolerance_sq);
+static void estimate_lengths(Point bezier[],
+ Point const data[], double const u[], unsigned len,
+ Point const &tHat1, Point const &tHat2);
+static void estimate_bi(Point b[4], unsigned ei,
+ Point const data[], double const u[], unsigned len);
+static void reparameterize(Point const d[], unsigned len, double u[], CubicBezier const & bezCurve);
+static double NewtonRaphsonRootFind(CubicBezier const & Q, Point const &P, double u);
+static Point darray_center_tangent(Point const d[], unsigned center, unsigned length);
+static Point darray_right_tangent(Point const d[], unsigned const len);
+static unsigned copy_without_nans_or_adjacent_duplicates(Point const src[], unsigned src_len, Point dest[]);
+static void chord_length_parameterize(Point const d[], double u[], unsigned len);
+static double compute_max_error_ratio(Point const d[], double const u[], unsigned len,
+ BezierCurve const bezCurve, double tolerance,
+ unsigned *splitPoint);
+static double compute_hook(Point const &a, Point const &b, double const u,
+ CubicBezier const & bezCurve,
+ double const tolerance);
+static double compute_hook(Point const &a, Point const &b, double const u,
+ BezierCurve const bezCurve,
+ double const tolerance) {
+ CubicBezier cb(bezCurve[0], bezCurve[1], bezCurve[2], bezCurve[3]);
+ return compute_hook(a, b, u, cb, tolerance);
+
+}
+
+
+static void reparameterize_pts(Point const d[], unsigned len, double u[], BezierCurve const bezCurve) {
+ CubicBezier cb(bezCurve[0], bezCurve[1], bezCurve[2], bezCurve[3]);
+ reparameterize(d, len, u, cb);
+}
+
+
+
+static Point const unconstrained_tangent(0, 0);
+
+
+/*
+ * B0, B1, B2, B3 : Bezier multipliers
+ */
+
+#define B0(u) ( ( 1.0 - u ) * ( 1.0 - u ) * ( 1.0 - u ) )
+#define B1(u) ( 3 * u * ( 1.0 - u ) * ( 1.0 - u ) )
+#define B2(u) ( 3 * u * u * ( 1.0 - u ) )
+#define B3(u) ( u * u * u )
+
+#ifdef BEZIER_DEBUG
+# define DOUBLE_ASSERT(x) assert( ( (x) > -SP_HUGE ) && ( (x) < SP_HUGE ) )
+# define BEZIER_ASSERT(b) do { \
+ DOUBLE_ASSERT((b)[0][X]); DOUBLE_ASSERT((b)[0][Y]); \
+ DOUBLE_ASSERT((b)[1][X]); DOUBLE_ASSERT((b)[1][Y]); \
+ DOUBLE_ASSERT((b)[2][X]); DOUBLE_ASSERT((b)[2][Y]); \
+ DOUBLE_ASSERT((b)[3][X]); DOUBLE_ASSERT((b)[3][Y]); \
+ } while(0)
+#else
+# define DOUBLE_ASSERT(x) do { } while(0)
+# define BEZIER_ASSERT(b) do { } while(0)
+#endif
+
+
+Point
+bezier_pt(unsigned const degree, Point const V[], double const t)
+{
+ return bernstein_value_at(t, V, degree);
+
+}
+
+/*
+ * ComputeLeftTangent, ComputeRightTangent, ComputeCenterTangent :
+ * Approximate unit tangents at endpoints and "center" of digitized curve
+ */
+
+/**
+ * Estimate the (forward) tangent at point d[first + 0.5].
+ *
+ * Unlike the center and right versions, this calculates the tangent in
+ * the way one might expect, i.e., wrt increasing index into d.
+ * \pre (2 \<= len) and (d[0] != d[1]).
+ **/
+Point
+darray_left_tangent(Point const d[], unsigned const len)
+{
+ assert( len >= 2 );
+ assert( d[0] != d[1] );
+ return unit_vector( d[1] - d[0] );
+}
+
+/**
+ * Estimates the (backward) tangent at d[last - 0.5].
+ *
+ * \note The tangent is "backwards", i.e. it is with respect to
+ * decreasing index rather than increasing index.
+ *
+ * \pre 2 \<= len.
+ * \pre d[len - 1] != d[len - 2].
+ * \pre all[p in d] in_svg_plane(p).
+ */
+static Point
+darray_right_tangent(Point const d[], unsigned const len)
+{
+ assert( 2 <= len );
+ unsigned const last = len - 1;
+ unsigned const prev = last - 1;
+ assert( d[last] != d[prev] );
+ return unit_vector( d[prev] - d[last] );
+}
+
+/**
+ * Estimate the (forward) tangent at point d[0].
+ *
+ * Unlike the center and right versions, this calculates the tangent in
+ * the way one might expect, i.e., wrt increasing index into d.
+ *
+ * \pre 2 \<= len.
+ * \pre d[0] != d[1].
+ * \pre all[p in d] in_svg_plane(p).
+ * \post is_unit_vector(ret).
+ **/
+Point
+darray_left_tangent(Point const d[], unsigned const len, double const tolerance_sq)
+{
+ assert( 2 <= len );
+ assert( 0 <= tolerance_sq );
+ for (unsigned i = 1;;) {
+ Point const pi(d[i]);
+ Point const t(pi - d[0]);
+ double const distsq = dot(t, t);
+ if ( tolerance_sq < distsq ) {
+ return unit_vector(t);
+ }
+ ++i;
+ if (i == len) {
+ return ( distsq == 0
+ ? darray_left_tangent(d, len)
+ : unit_vector(t) );
+ }
+ }
+}
+
+/**
+ * Estimates the (backward) tangent at d[last].
+ *
+ * \note The tangent is "backwards", i.e. it is with respect to
+ * decreasing index rather than increasing index.
+ *
+ * \pre 2 \<= len.
+ * \pre d[len - 1] != d[len - 2].
+ * \pre all[p in d] in_svg_plane(p).
+ */
+Point
+darray_right_tangent(Point const d[], unsigned const len, double const tolerance_sq)
+{
+ assert( 2 <= len );
+ assert( 0 <= tolerance_sq );
+ unsigned const last = len - 1;
+ for (unsigned i = last - 1;; i--) {
+ Point const pi(d[i]);
+ Point const t(pi - d[last]);
+ double const distsq = dot(t, t);
+ if ( tolerance_sq < distsq ) {
+ return unit_vector(t);
+ }
+ if (i == 0) {
+ return ( distsq == 0
+ ? darray_right_tangent(d, len)
+ : unit_vector(t) );
+ }
+ }
+}
+
+/**
+ * Estimates the (backward) tangent at d[center], by averaging the two
+ * segments connected to d[center] (and then normalizing the result).
+ *
+ * \note The tangent is "backwards", i.e. it is with respect to
+ * decreasing index rather than increasing index.
+ *
+ * \pre (0 \< center \< len - 1) and d is uniqued (at least in
+ * the immediate vicinity of \a center).
+ */
+static Point
+darray_center_tangent(Point const d[],
+ unsigned const center,
+ unsigned const len)
+{
+ assert( center != 0 );
+ assert( center < len - 1 );
+
+ Point ret;
+ if ( d[center + 1] == d[center - 1] ) {
+ /* Rotate 90 degrees in an arbitrary direction. */
+ Point const diff = d[center] - d[center - 1];
+ ret = rot90(diff);
+ } else {
+ ret = d[center - 1] - d[center + 1];
+ }
+ ret.normalize();
+ return ret;
+}
+
+
+int
+bezier_fit_cubic_r(Point bezier[], Point const data[], int const len, double const error, unsigned const max_beziers);
+
+int
+bezier_fit_cubic_full(Point bezier[], int split_points[],
+ Point const data[], int const len,
+ Point const &tHat1, Point const &tHat2,
+ double const error, unsigned const max_beziers);
+
+
+/**
+ * Fit a single-segment Bezier curve to a set of digitized points.
+ *
+ * \return Number of segments generated, or -1 on error.
+ */
+int
+bezier_fit_cubic(Point *bezier, Point const *data, int len, double error)
+{
+ return bezier_fit_cubic_r(bezier, data, len, error, 1);
+}
+
+/**
+ * Fit a multi-segment Bezier curve to a set of digitized points, with
+ * possible weedout of identical points and NaNs.
+ *
+ * \param max_beziers Maximum number of generated segments
+ * \param Result array, must be large enough for n. segments * 4 elements.
+ *
+ * \return Number of segments generated, or -1 on error.
+ */
+int
+bezier_fit_cubic_r(Point bezier[], Point const data[], int const len, double const error, unsigned const max_beziers)
+{
+ if(bezier == NULL ||
+ data == NULL ||
+ len <= 0 ||
+ max_beziers >= (1ul << (31 - 2 - 1 - 3)))
+ return -1;
+
+ Point *uniqued_data = new Point[len];
+ unsigned uniqued_len = copy_without_nans_or_adjacent_duplicates(data, len, uniqued_data);
+
+ if ( uniqued_len < 2 ) {
+ delete[] uniqued_data;
+ return 0;
+ }
+
+ /* Call fit-cubic function with recursion. */
+ int const ret = bezier_fit_cubic_full(bezier, NULL, uniqued_data, uniqued_len,
+ unconstrained_tangent, unconstrained_tangent,
+ error, max_beziers);
+ delete[] uniqued_data;
+ return ret;
+}
+
+
+
+/**
+ * Copy points from src to dest, filter out points containing NaN and
+ * adjacent points with equal x and y.
+ * \return length of dest
+ */
+static unsigned
+copy_without_nans_or_adjacent_duplicates(Point const src[], unsigned src_len, Point dest[])
+{
+ unsigned si = 0;
+ for (;;) {
+ if ( si == src_len ) {
+ return 0;
+ }
+ if (!std::isnan(src[si][X]) &&
+ !std::isnan(src[si][Y])) {
+ dest[0] = Point(src[si]);
+ ++si;
+ break;
+ }
+ si++;
+ }
+ unsigned di = 0;
+ for (; si < src_len; ++si) {
+ Point const src_pt = Point(src[si]);
+ if ( src_pt != dest[di]
+ && !std::isnan(src_pt[X])
+ && !std::isnan(src_pt[Y])) {
+ dest[++di] = src_pt;
+ }
+ }
+ unsigned dest_len = di + 1;
+ assert( dest_len <= src_len );
+ return dest_len;
+}
+
+/**
+ * Fit a multi-segment Bezier curve to a set of digitized points, without
+ * possible weedout of identical points and NaNs.
+ *
+ * \pre data is uniqued, i.e. not exist i: data[i] == data[i + 1].
+ * \param max_beziers Maximum number of generated segments
+ * \param Result array, must be large enough for n. segments * 4 elements.
+ */
+int
+bezier_fit_cubic_full(Point bezier[], int split_points[],
+ Point const data[], int const len,
+ Point const &tHat1, Point const &tHat2,
+ double const error, unsigned const max_beziers)
+{
+ int const maxIterations = 4; /* std::max times to try iterating */
+
+ if(!(bezier != NULL) ||
+ !(data != NULL) ||
+ !(len > 0) ||
+ !(max_beziers >= 1) ||
+ !(error >= 0.0))
+ return -1;
+
+ if ( len < 2 ) return 0;
+
+ if ( len == 2 ) {
+ /* We have 2 points, which can be fitted trivially. */
+ bezier[0] = data[0];
+ bezier[3] = data[len - 1];
+ double const dist = distance(bezier[0], bezier[3]) / 3.0;
+ if (std::isnan(dist)) {
+ /* Numerical problem, fall back to straight line segment. */
+ bezier[1] = bezier[0];
+ bezier[2] = bezier[3];
+ } else {
+ bezier[1] = ( is_zero(tHat1)
+ ? ( 2 * bezier[0] + bezier[3] ) / 3.
+ : bezier[0] + dist * tHat1 );
+ bezier[2] = ( is_zero(tHat2)
+ ? ( bezier[0] + 2 * bezier[3] ) / 3.
+ : bezier[3] + dist * tHat2 );
+ }
+ BEZIER_ASSERT(bezier);
+ return 1;
+ }
+
+ /* Parameterize points, and attempt to fit curve */
+ unsigned splitPoint; /* Point to split point set at. */
+ bool is_corner;
+ {
+ double *u = new double[len];
+ chord_length_parameterize(data, u, len);
+ if ( u[len - 1] == 0.0 ) {
+ /* Zero-length path: every point in data[] is the same.
+ *
+ * (Clients aren't allowed to pass such data; handling the case is defensive
+ * programming.)
+ */
+ delete[] u;
+ return 0;
+ }
+
+ generate_bezier(bezier, data, u, len, tHat1, tHat2, error);
+ reparameterize_pts(data, len, u, bezier);
+
+ /* Find max deviation of points to fitted curve. */
+ double const tolerance = std::sqrt(error + 1e-9);
+ double maxErrorRatio = compute_max_error_ratio(data, u, len, bezier, tolerance, &splitPoint);
+
+ if ( fabs(maxErrorRatio) <= 1.0 ) {
+ BEZIER_ASSERT(bezier);
+ delete[] u;
+ return 1;
+ }
+
+ /* If error not too large, then try some reparameterization and iteration. */
+ if ( 0.0 <= maxErrorRatio && maxErrorRatio <= 3.0 ) {
+ for (int i = 0; i < maxIterations; i++) {
+ generate_bezier(bezier, data, u, len, tHat1, tHat2, error);
+ reparameterize_pts(data, len, u, bezier);
+ maxErrorRatio = compute_max_error_ratio(data, u, len, bezier, tolerance, &splitPoint);
+ if ( fabs(maxErrorRatio) <= 1.0 ) {
+ BEZIER_ASSERT(bezier);
+ delete[] u;
+ return 1;
+ }
+ }
+ }
+ delete[] u;
+ is_corner = (maxErrorRatio < 0);
+ }
+
+ if (is_corner) {
+ assert(splitPoint < unsigned(len));
+ if (splitPoint == 0) {
+ if (is_zero(tHat1)) {
+ /* Got spike even with unconstrained initial tangent. */
+ ++splitPoint;
+ } else {
+ return bezier_fit_cubic_full(bezier, split_points, data, len, unconstrained_tangent, tHat2,
+ error, max_beziers);
+ }
+ } else if (splitPoint == unsigned(len - 1)) {
+ if (is_zero(tHat2)) {
+ /* Got spike even with unconstrained final tangent. */
+ --splitPoint;
+ } else {
+ return bezier_fit_cubic_full(bezier, split_points, data, len, tHat1, unconstrained_tangent,
+ error, max_beziers);
+ }
+ }
+ }
+
+ if ( 1 < max_beziers ) {
+ /*
+ * Fitting failed -- split at max error point and fit recursively
+ */
+ unsigned const rec_max_beziers1 = max_beziers - 1;
+
+ Point recTHat2, recTHat1;
+ if (is_corner) {
+ if(!(0 < splitPoint && splitPoint < unsigned(len - 1)))
+ return -1;
+ recTHat1 = recTHat2 = unconstrained_tangent;
+ } else {
+ /* Unit tangent vector at splitPoint. */
+ recTHat2 = darray_center_tangent(data, splitPoint, len);
+ recTHat1 = -recTHat2;
+ }
+ int const nsegs1 = bezier_fit_cubic_full(bezier, split_points, data, splitPoint + 1,
+ tHat1, recTHat2, error, rec_max_beziers1);
+ if ( nsegs1 < 0 ) {
+#ifdef BEZIER_DEBUG
+ g_print("fit_cubic[1]: recursive call failed\n");
+#endif
+ return -1;
+ }
+ assert( nsegs1 != 0 );
+ if (split_points != NULL) {
+ split_points[nsegs1 - 1] = splitPoint;
+ }
+ unsigned const rec_max_beziers2 = max_beziers - nsegs1;
+ int const nsegs2 = bezier_fit_cubic_full(bezier + nsegs1*4,
+ ( split_points == NULL
+ ? NULL
+ : split_points + nsegs1 ),
+ data + splitPoint, len - splitPoint,
+ recTHat1, tHat2, error, rec_max_beziers2);
+ if ( nsegs2 < 0 ) {
+#ifdef BEZIER_DEBUG
+ g_print("fit_cubic[2]: recursive call failed\n");
+#endif
+ return -1;
+ }
+
+#ifdef BEZIER_DEBUG
+ g_print("fit_cubic: success[nsegs: %d+%d=%d] on max_beziers:%u\n",
+ nsegs1, nsegs2, nsegs1 + nsegs2, max_beziers);
+#endif
+ return nsegs1 + nsegs2;
+ } else {
+ return -1;
+ }
+}
+
+
+/**
+ * Fill in \a bezier[] based on the given data and tangent requirements, using
+ * a least-squares fit.
+ *
+ * Each of tHat1 and tHat2 should be either a zero vector or a unit vector.
+ * If it is zero, then bezier[1 or 2] is estimated without constraint; otherwise,
+ * it bezier[1 or 2] is placed in the specified direction from bezier[0 or 3].
+ *
+ * \param tolerance_sq Used only for an initial guess as to tangent directions
+ * when \a tHat1 or \a tHat2 is zero.
+ */
+static void
+generate_bezier(Point bezier[],
+ Point const data[], double const u[], unsigned const len,
+ Point const &tHat1, Point const &tHat2,
+ double const tolerance_sq)
+{
+ bool const est1 = is_zero(tHat1);
+ bool const est2 = is_zero(tHat2);
+ Point est_tHat1( est1
+ ? darray_left_tangent(data, len, tolerance_sq)
+ : tHat1 );
+ Point est_tHat2( est2
+ ? darray_right_tangent(data, len, tolerance_sq)
+ : tHat2 );
+ estimate_lengths(bezier, data, u, len, est_tHat1, est_tHat2);
+ /* We find that darray_right_tangent tends to produce better results
+ for our current freehand tool than full estimation. */
+ if (est1) {
+ estimate_bi(bezier, 1, data, u, len);
+ if (bezier[1] != bezier[0]) {
+ est_tHat1 = unit_vector(bezier[1] - bezier[0]);
+ }
+ estimate_lengths(bezier, data, u, len, est_tHat1, est_tHat2);
+ }
+}
+
+
+static void
+estimate_lengths(Point bezier[],
+ Point const data[], double const uPrime[], unsigned const len,
+ Point const &tHat1, Point const &tHat2)
+{
+ double C[2][2]; /* Matrix C. */
+ double X[2]; /* Matrix X. */
+
+ /* Create the C and X matrices. */
+ C[0][0] = 0.0;
+ C[0][1] = 0.0;
+ C[1][0] = 0.0;
+ C[1][1] = 0.0;
+ X[0] = 0.0;
+ X[1] = 0.0;
+
+ /* First and last control points of the Bezier curve are positioned exactly at the first and
+ last data points. */
+ bezier[0] = data[0];
+ bezier[3] = data[len - 1];
+
+ for (unsigned i = 0; i < len; i++) {
+ /* Bezier control point coefficients. */
+ double const b0 = B0(uPrime[i]);
+ double const b1 = B1(uPrime[i]);
+ double const b2 = B2(uPrime[i]);
+ double const b3 = B3(uPrime[i]);
+
+ /* rhs for eqn */
+ Point const a1 = b1 * tHat1;
+ Point const a2 = b2 * tHat2;
+
+ C[0][0] += dot(a1, a1);
+ C[0][1] += dot(a1, a2);
+ C[1][0] = C[0][1];
+ C[1][1] += dot(a2, a2);
+
+ /* Additional offset to the data point from the predicted point if we were to set bezier[1]
+ to bezier[0] and bezier[2] to bezier[3]. */
+ Point const shortfall
+ = ( data[i]
+ - ( ( b0 + b1 ) * bezier[0] )
+ - ( ( b2 + b3 ) * bezier[3] ) );
+ X[0] += dot(a1, shortfall);
+ X[1] += dot(a2, shortfall);
+ }
+
+ /* We've constructed a pair of equations in the form of a matrix product C * alpha = X.
+ Now solve for alpha. */
+ double alpha_l, alpha_r;
+
+ /* Compute the determinants of C and X. */
+ double const det_C0_C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1];
+ if ( det_C0_C1 != 0 ) {
+ /* Apparently Kramer's rule. */
+ double const det_C0_X = C[0][0] * X[1] - C[0][1] * X[0];
+ double const det_X_C1 = X[0] * C[1][1] - X[1] * C[0][1];
+ alpha_l = det_X_C1 / det_C0_C1;
+ alpha_r = det_C0_X / det_C0_C1;
+ } else {
+ /* The matrix is under-determined. Try requiring alpha_l == alpha_r.
+ *
+ * One way of implementing the constraint alpha_l == alpha_r is to treat them as the same
+ * variable in the equations. We can do this by adding the columns of C to form a single
+ * column, to be multiplied by alpha to give the column vector X.
+ *
+ * We try each row in turn.
+ */
+ double const c0 = C[0][0] + C[0][1];
+ if (c0 != 0) {
+ alpha_l = alpha_r = X[0] / c0;
+ } else {
+ double const c1 = C[1][0] + C[1][1];
+ if (c1 != 0) {
+ alpha_l = alpha_r = X[1] / c1;
+ } else {
+ /* Let the below code handle this. */
+ alpha_l = alpha_r = 0.;
+ }
+ }
+ }
+
+ /* If alpha negative, use the Wu/Barsky heuristic (see text). (If alpha is 0, you get
+ coincident control points that lead to divide by zero in any subsequent
+ NewtonRaphsonRootFind() call.) */
+ /// \todo Check whether this special-casing is necessary now that
+ /// NewtonRaphsonRootFind handles non-positive denominator.
+ if ( alpha_l < 1.0e-6 ||
+ alpha_r < 1.0e-6 )
+ {
+ alpha_l = alpha_r = distance(data[0], data[len-1]) / 3.0;
+ }
+
+ /* Control points 1 and 2 are positioned an alpha distance out on the tangent vectors, left and
+ right, respectively. */
+ bezier[1] = alpha_l * tHat1 + bezier[0];
+ bezier[2] = alpha_r * tHat2 + bezier[3];
+
+ return;
+}
+
+static double lensq(Point const p) {
+ return dot(p, p);
+}
+
+static void
+estimate_bi(Point bezier[4], unsigned const ei,
+ Point const data[], double const u[], unsigned const len)
+{
+ if(!(1 <= ei && ei <= 2))
+ return;
+ unsigned const oi = 3 - ei;
+ double num[2] = {0., 0.};
+ double den = 0.;
+ for (unsigned i = 0; i < len; ++i) {
+ double const ui = u[i];
+ double const b[4] = {
+ B0(ui),
+ B1(ui),
+ B2(ui),
+ B3(ui)
+ };
+
+ for (unsigned d = 0; d < 2; ++d) {
+ num[d] += b[ei] * (b[0] * bezier[0][d] +
+ b[oi] * bezier[oi][d] +
+ b[3] * bezier[3][d] +
+ - data[i][d]);
+ }
+ den -= b[ei] * b[ei];
+ }
+
+ if (den != 0.) {
+ for (unsigned d = 0; d < 2; ++d) {
+ bezier[ei][d] = num[d] / den;
+ }
+ } else {
+ bezier[ei] = ( oi * bezier[0] + ei * bezier[3] ) / 3.;
+ }
+}
+
+/**
+ * Given set of points and their parameterization, try to find a better assignment of parameter
+ * values for the points.
+ *
+ * \param d Array of digitized points.
+ * \param u Current parameter values.
+ * \param bezCurve Current fitted curve.
+ * \param len Number of values in both d and u arrays.
+ * Also the size of the array that is allocated for return.
+ */
+static void
+reparameterize(Point const d[],
+ unsigned const len,
+ double u[],
+ CubicBezier const &bezCurve)
+{
+ assert( 2 <= len );
+
+ unsigned const last = len - 1;
+ assert( bezCurve[0] == d[0] );
+ assert( bezCurve[3] == d[last] );
+ assert( u[0] == 0.0 );
+ assert( u[last] == 1.0 );
+ /* Otherwise, consider including 0 and last in the below loop. */
+
+ for (unsigned i = 1; i < last; i++) {
+ u[i] = NewtonRaphsonRootFind(bezCurve, d[i], u[i]);
+ }
+}
+
+/**
+ * Use Newton-Raphson iteration to find better root.
+ *
+ * \param Q Current fitted curve
+ * \param P Digitized point
+ * \param u Parameter value for "P"
+ *
+ * \return Improved u
+ */
+static double
+NewtonRaphsonRootFind(CubicBezier const &Q, Point const &P, double const u)
+{
+ assert( 0.0 <= u );
+ assert( u <= 1.0 );
+
+ std::vector<Point> Q_u = Q.pointAndDerivatives(u, 2);
+
+ /* Compute f(u)/f'(u), where f is the derivative wrt u of distsq(u) = 0.5 * the square of the
+ distance from P to Q(u). Here we're using Newton-Raphson to find a stationary point in the
+ distsq(u), hopefully corresponding to a local minimum in distsq (and hence a local minimum
+ distance from P to Q(u)). */
+ Point const diff = Q_u[0] - P;
+ double numerator = dot(diff, Q_u[1]);
+ double denominator = dot(Q_u[1], Q_u[1]) + dot(diff, Q_u[2]);
+
+ double improved_u;
+ if ( denominator > 0. ) {
+ /* One iteration of Newton-Raphson:
+ improved_u = u - f(u)/f'(u) */
+ improved_u = u - ( numerator / denominator );
+ } else {
+ /* Using Newton-Raphson would move in the wrong direction (towards a local maximum rather
+ than local minimum), so we move an arbitrary amount in the right direction. */
+ if ( numerator > 0. ) {
+ improved_u = u * .98 - .01;
+ } else if ( numerator < 0. ) {
+ /* Deliberately asymmetrical, to reduce the chance of cycling. */
+ improved_u = .031 + u * .98;
+ } else {
+ improved_u = u;
+ }
+ }
+
+ if (!std::isfinite(improved_u)) {
+ improved_u = u;
+ } else if ( improved_u < 0.0 ) {
+ improved_u = 0.0;
+ } else if ( improved_u > 1.0 ) {
+ improved_u = 1.0;
+ }
+
+ /* Ensure that improved_u isn't actually worse. */
+ {
+ double const diff_lensq = lensq(diff);
+ for (double proportion = .125; ; proportion += .125) {
+ if ( lensq( Q.pointAt(improved_u) - P ) > diff_lensq ) {
+ if ( proportion > 1.0 ) {
+ //g_warning("found proportion %g", proportion);
+ improved_u = u;
+ break;
+ }
+ improved_u = ( ( 1 - proportion ) * improved_u +
+ proportion * u );
+ } else {
+ break;
+ }
+ }
+ }
+
+ DOUBLE_ASSERT(improved_u);
+ return improved_u;
+}
+
+
+/**
+ * Assign parameter values to digitized points using relative distances between points.
+ *
+ * \pre Parameter array u must have space for \a len items.
+ */
+static void
+chord_length_parameterize(Point const d[], double u[], unsigned const len)
+{
+ if(!( 2 <= len ))
+ return;
+
+ /* First let u[i] equal the distance travelled along the path from d[0] to d[i]. */
+ u[0] = 0.0;
+ for (unsigned i = 1; i < len; i++) {
+ double const dist = distance(d[i], d[i-1]);
+ u[i] = u[i-1] + dist;
+ }
+
+ /* Then scale to [0.0 .. 1.0]. */
+ double tot_len = u[len - 1];
+ if(!( tot_len != 0 ))
+ return;
+ if (std::isfinite(tot_len)) {
+ for (unsigned i = 1; i < len; ++i) {
+ u[i] /= tot_len;
+ }
+ } else {
+ /* We could do better, but this probably never happens anyway. */
+ for (unsigned i = 1; i < len; ++i) {
+ u[i] = i / (double) ( len - 1 );
+ }
+ }
+
+ /** \todo
+ * It's been reported that u[len - 1] can differ from 1.0 on some
+ * systems (amd64), despite it having been calculated as x / x where x
+ * is isFinite and non-zero.
+ */
+ if (u[len - 1] != 1) {
+ double const diff = u[len - 1] - 1;
+ if (fabs(diff) > 1e-13) {
+ assert(0); // No warnings in 2geom
+ //g_warning("u[len - 1] = %19g (= 1 + %19g), expecting exactly 1",
+ // u[len - 1], diff);
+ }
+ u[len - 1] = 1;
+ }
+
+#ifdef BEZIER_DEBUG
+ assert( u[0] == 0.0 && u[len - 1] == 1.0 );
+ for (unsigned i = 1; i < len; i++) {
+ assert( u[i] >= u[i-1] );
+ }
+#endif
+}
+
+
+
+
+/**
+ * Find the maximum squared distance of digitized points to fitted curve, and (if this maximum
+ * error is non-zero) set \a *splitPoint to the corresponding index.
+ *
+ * \pre 2 \<= len.
+ * \pre u[0] == 0.
+ * \pre u[len - 1] == 1.0.
+ * \post ((ret == 0.0)
+ * || ((*splitPoint \< len - 1)
+ * \&\& (*splitPoint != 0 || ret \< 0.0))).
+ */
+static double
+compute_max_error_ratio(Point const d[], double const u[], unsigned const len,
+ BezierCurve const bezCurve, double const tolerance,
+ unsigned *const splitPoint)
+{
+ assert( 2 <= len );
+ unsigned const last = len - 1;
+ assert( bezCurve[0] == d[0] );
+ assert( bezCurve[3] == d[last] );
+ assert( u[0] == 0.0 );
+ assert( u[last] == 1.0 );
+ /* I.e. assert that the error for the first & last points is zero.
+ * Otherwise we should include those points in the below loop.
+ * The assertion is also necessary to ensure 0 < splitPoint < last.
+ */
+
+ double maxDistsq = 0.0; /* Maximum error */
+ double max_hook_ratio = 0.0;
+ unsigned snap_end = 0;
+ Point prev = bezCurve[0];
+ for (unsigned i = 1; i <= last; i++) {
+ Point const curr = bezier_pt(3, bezCurve, u[i]);
+ double const distsq = lensq( curr - d[i] );
+ if ( distsq > maxDistsq ) {
+ maxDistsq = distsq;
+ *splitPoint = i;
+ }
+ double const hook_ratio = compute_hook(prev, curr, .5 * (u[i - 1] + u[i]), bezCurve, tolerance);
+ if (max_hook_ratio < hook_ratio) {
+ max_hook_ratio = hook_ratio;
+ snap_end = i;
+ }
+ prev = curr;
+ }
+
+ double const dist_ratio = std::sqrt(maxDistsq) / tolerance;
+ double ret;
+ if (max_hook_ratio <= dist_ratio) {
+ ret = dist_ratio;
+ } else {
+ assert(0 < snap_end);
+ ret = -max_hook_ratio;
+ *splitPoint = snap_end - 1;
+ }
+ assert( ret == 0.0
+ || ( ( *splitPoint < last )
+ && ( *splitPoint != 0 || ret < 0. ) ) );
+ return ret;
+}
+
+/**
+ * Whereas compute_max_error_ratio() checks for itself that each data point
+ * is near some point on the curve, this function checks that each point on
+ * the curve is near some data point (or near some point on the polyline
+ * defined by the data points, or something like that: we allow for a
+ * "reasonable curviness" from such a polyline). "Reasonable curviness"
+ * means we draw a circle centred at the midpoint of a..b, of radius
+ * proportional to the length |a - b|, and require that each point on the
+ * segment of bezCurve between the parameters of a and b be within that circle.
+ * If any point P on the bezCurve segment is outside of that allowable
+ * region (circle), then we return some metric that increases with the
+ * distance from P to the circle.
+ *
+ * Given that this is a fairly arbitrary criterion for finding appropriate
+ * places for sharp corners, we test only one point on bezCurve, namely
+ * the point on bezCurve with parameter halfway between our estimated
+ * parameters for a and b. (Alternatives are taking the farthest of a
+ * few parameters between those of a and b, or even using a variant of
+ * NewtonRaphsonFindRoot() for finding the maximum rather than minimum
+ * distance.)
+ */
+static double
+compute_hook(Point const &a, Point const &b, double const u, CubicBezier const & bezCurve,
+ double const tolerance)
+{
+ Point const P = bezCurve.pointAt(u);
+ double const dist = distance((a+b)*.5, P);
+ if (dist < tolerance) {
+ return 0;
+ }
+ double const allowed = distance(a, b) + tolerance;
+ return dist / allowed;
+ /** \todo
+ * effic: Hooks are very rare. We could start by comparing
+ * distsq, only resorting to the more expensive L2 in cases of
+ * uncertainty.
+ */
+}
+
+}
+
+}
+
+#include <2geom/bezier-utils.h>
+
+
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+class PointToBezierTester: public Toy {
+ //std::vector<Slider> sliders;
+ PointHandle adjuster, adjuster2, adjuster3;
+ std::vector<Toggle> toggles;
+ Piecewise<D2<SBasis > > stroke;
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_save(cr);
+
+ cairo_set_source_rgba (cr, 0., 0., 0., 1);
+ cairo_set_line_width (cr, 0.5);
+ adjuster2.pos[0]=150;
+ adjuster2.pos[1]=std::min(std::max(adjuster2.pos[1],150.),450.);
+ cairo_move_to(cr, 150, 150);
+ cairo_line_to(cr, 150, 450);
+ cairo_stroke(cr);
+ ostringstream val_s;
+ double scale0=(450-adjuster2.pos[1])/300;
+ double curve_precision = pow(10, scale0*5-2);
+ val_s << curve_precision;
+ draw_text(cr, adjuster2.pos, val_s.str().c_str());
+ cairo_restore(cr);
+
+ cairo_save(cr);
+
+ cairo_set_source_rgba (cr, 0., 0., 0., 1);
+ cairo_set_line_width (cr, 0.5);
+
+ if(!mouses.empty()) {
+ cairo_move_to(cr, mouses[0]);
+ for(auto & mouse : mouses) {
+ cairo_line_to(cr, mouse);
+ }
+ cairo_stroke(cr);
+ }
+
+ if(!mouses.empty()) {
+ Point bezier[1000];
+ int segsgenerated;
+ {
+ Timer tm;
+
+ tm.ask_for_timeslice();
+ tm.start();
+ segsgenerated = bezier_fit_cubic_r(bezier, &mouses[0],
+ mouses.size(), curve_precision, 240);
+
+ Timer::Time als_time = tm.lap();
+ *notify << "original time = " << als_time << std::endl;
+ }
+
+ if(1) {
+ cairo_save(cr);
+ cairo_set_source_rgba (cr, 0., 1., 0., 1);
+ cairo_move_to(cr, bezier[0]);
+ int bezi=1;
+ for(int i = 0; i < segsgenerated; i ++) {
+ cairo_curve_to(cr, bezier[bezi], bezier[bezi+1], bezier[bezi+2]);
+ bezi += 4;
+ }
+ cairo_stroke(cr);
+ cairo_restore(cr);
+
+ }
+ {
+ Timer tm;
+
+ tm.ask_for_timeslice();
+ tm.start();
+ segsgenerated = Geom::BezierFitter::bezier_fit_cubic_r(bezier, &mouses[0],
+ mouses.size(), curve_precision, 240);
+
+ Timer::Time als_time = tm.lap();
+ *notify << "experimental version time = " << als_time << std::endl;
+ }
+
+ if (1) {
+ cairo_save(cr);
+ cairo_set_source_rgba (cr, 0., 0., 0., 1);
+ cairo_move_to(cr, bezier[0]);
+ int bezi=1;
+ for(int i = 0; i < segsgenerated; i ++) {
+ cairo_curve_to(cr, bezier[bezi], bezier[bezi+1], bezier[bezi+2]);
+ bezi += 4;
+ }
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ }
+ *notify << "segments : "<< segsgenerated <<"\n";
+ }
+ cairo_restore(cr);
+
+ /*
+ Point p(25, height - 50), d(50,25);
+ toggles[0].bounds = Rect(p, p + d);
+ p+= Point(75, 0);
+ toggles[1].bounds = Rect(p, p + d);
+ draw_toggles(cr, toggles);
+ */
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+public:
+ void key_hit(GdkEventKey *e) override {
+ if(e->keyval == 's') toggles[0].toggle();
+ redraw();
+ }
+ vector<Point> mouses;
+ int mouse_drag;
+
+ void mouse_pressed(GdkEventButton* e) override {
+ toggle_events(toggles, e);
+ Toy::mouse_pressed(e);
+ if(!selected) {
+ mouse_drag = 1;
+ mouses.clear();
+ }
+ }
+
+
+ void mouse_moved(GdkEventMotion* e) override {
+ if(mouse_drag) {
+ mouses.emplace_back(e->x, e->y);
+ redraw();
+ } else {
+ Toy::mouse_moved(e);
+ }
+ }
+
+ void mouse_released(GdkEventButton* e) override {
+ mouse_drag = 0;
+ stroke.clear();
+ stroke.push_cut(0);
+ Path pth;
+ for(unsigned i = 2; i < mouses.size(); i+=2) {
+ pth.append(QuadraticBezier(mouses[i-2], mouses[i-1], mouses[i]));
+ }
+ stroke = pth.toPwSb();
+ Toy::mouse_released(e);
+ }
+
+ PointToBezierTester() {
+ adjuster2.pos = Geom::Point(150,300);
+ handles.push_back(&adjuster2);
+ toggles.emplace_back("Seq", false);
+ toggles.emplace_back("Linfty", true);
+ //}
+ //sliders.push_back(Slider(0.0, 1.0, 0.0, 0.0, "t"));
+ //handles.push_back(&(sliders[0]));
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new PointToBezierTester);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype = cpp:expandtab:shiftwidth = 4:tabstop = 8:softtabstop = 4:encoding = utf-8:textwidth = 99 :
diff --git a/src/3rdparty/2geom/src/toys/pencil.cpp b/src/3rdparty/2geom/src/toys/pencil.cpp
new file mode 100644
index 0000000..1ac3587
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/pencil.cpp
@@ -0,0 +1,374 @@
+/*
+ * sb-to-bez Toy - Tests conversions from sbasis to cubic bezier.
+ *
+ * Copyright 2007 jf barraud.
+ * 2008 njh
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+// mainly experimental atm...
+// do not expect to find anything understandable here atm.
+
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/basic-intersection.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#define ZERO 1e-7
+
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+#include <stdio.h>
+#include <gsl/gsl_poly.h>
+
+void cairo_pw(cairo_t *cr, Piecewise<SBasis> p, double hscale=1., double vscale=1.) {
+ for(unsigned i = 0; i < p.size(); i++) {
+ D2<SBasis> B;
+ B[0] = Linear(150+p.cuts[i]*hscale, 150+p.cuts[i+1]*hscale);
+ B[1] = Linear(450) - p[i]*vscale;
+ cairo_d2_sb(cr, B);
+ }
+}
+
+//===================================================================================
+
+D2<SBasis>
+naive_sb_seg_to_bez(Piecewise<D2<SBasis> > const &M,double t0,double t1){
+
+ Piecewise<D2<SBasis> > dM = derivative(M);
+ Point M0 = M(t0);
+ Point dM0 = dM(t0)*(t1-t0);
+ Point M1 = M(t1);
+ Point dM1 = dM(t1)*(t1-t0);
+ D2<SBasis> result;
+ for (unsigned dim=0; dim<2; dim++){
+ SBasis r(2, Linear());
+ r[0] = Linear(M0[dim],M1[dim]);
+ r[1] = Linear(M0[dim]-M1[dim]+dM0[dim],-(M0[dim]-M1[dim]+dM1[dim]));
+ result[dim] = r;
+ }
+ return result;
+}
+
+D2<SBasis>
+sb_seg_to_bez(Piecewise<D2<SBasis> > const &M,double t0,double t1){
+ Point M0,dM0,d2M0,M1,dM1,d2M1,A0,V0,A1,V1;
+ Piecewise<D2<SBasis> > dM,d2M;
+ dM=derivative(M);
+ d2M=derivative(dM);
+ M0 =M(t0);
+ M1 =M(t1);
+ dM0 =dM(t0);
+ dM1 =dM(t1);
+ d2M0=d2M(t0);
+ d2M1=d2M(t1);
+ A0=M(t0);
+ A1=M(t1);
+
+ std::vector<D2<SBasis> > candidates = cubics_fitting_curvature(M0,M1,dM0,dM1,d2M0,d2M1);
+ if (candidates.size()==0){
+ return D2<SBasis>(SBasis(M0[X],M1[X]),SBasis(M0[Y],M1[Y])) ;
+ }
+ double maxlength = -1;
+ unsigned best = 0;
+ for (unsigned i=0; i<candidates.size(); i++){
+ double l = length(candidates[i]);
+ if ( l < maxlength || maxlength < 0 ){
+ maxlength = l;
+ best = i;
+ }
+ }
+ return candidates[best];
+}
+#include <2geom/sbasis-to-bezier.h>
+
+int goal_function_type = 0;
+
+double goal_function(Piecewise<D2<SBasis> >const &A,
+ Piecewise<D2<SBasis> >const&B) {
+ if(goal_function_type) {
+ OptInterval bnds = bounds_fast(dot(derivative(A), rot90(derivative(B))));
+ //double h_dist = bnds.dimensions().length();
+//0 is in the rect!, TODO:gain factor ~2 for free.
+// njh: not really, the benefit is actually rather small.
+ double h_dist = 0;
+ if(bnds)
+ h_dist = bnds->extent();
+ return h_dist ;
+ } else {
+ Rect bnds = *bounds_fast(A - B);
+ return max(bnds.min().length(), bnds.max().length());
+ }
+}
+
+int recursive_curvature_fitter(cairo_t* cr, Piecewise<D2<SBasis> > const &f, double t0, double t1, double precision) {
+ if (t0>=t1) return 0;//TODO: fix me...
+ if (t0+0.001>=t1) return 0;//TODO: fix me...
+
+ //TODO: don't re-compute derivative(f) at each try!!
+ D2<SBasis> k_bez = sb_seg_to_bez(f,t0,t1);
+
+ if(k_bez[0].size() > 1 and k_bez[1].size() > 1) {
+ Piecewise<SBasis> s = arcLengthSb(k_bez);
+ s *= (t1-t0)/arcLengthSb(k_bez).segs.back().at1();
+ s += t0;
+ double h_dist = goal_function(compose(f,s), Piecewise<D2<SBasis> >(k_bez));
+ if(h_dist < precision) {
+ cairo_save(cr);
+ cairo_set_line_width (cr, 0.93);
+ cairo_set_source_rgba (cr, 0.7, 0.0, 0.0, 1);
+ draw_handle(cr, k_bez.at0());
+ cairo_d2_sb(cr, k_bez);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ return 1;
+ }
+ }
+ //TODO: find a better place where to cut (at the worst fit?).
+ return recursive_curvature_fitter(cr, f, t0, (t0+t1)/2, precision) +
+ recursive_curvature_fitter(cr, f, (t0+t1)/2, t1, precision);
+}
+
+double single_curvature_fitter(Piecewise<D2<SBasis> > const &f, double t0, double t1) {
+ if (t0>=t1) return 0;//TODO: fix me...
+ if (t0+0.001>=t1) return 0;//TODO: fix me...
+
+ D2<SBasis> k_bez = sb_seg_to_bez(f,t0,t1);
+
+ if(k_bez[0].size() > 1 and k_bez[1].size() > 1) {
+ Piecewise<SBasis> s = arcLengthSb(k_bez);
+ s *= (t1-t0)/arcLengthSb(k_bez).segs.back().at1();
+ s += t0;
+ return goal_function(compose(f,s), Piecewise<D2<SBasis> >(k_bez));
+ }
+ return 1e100;
+}
+
+struct quadratic_params
+{
+ Piecewise<D2<SBasis> > const *f;
+ double t0, precision;
+};
+
+
+double quadratic (double x, void *params) {
+ struct quadratic_params *p
+ = (struct quadratic_params *) params;
+
+ return single_curvature_fitter(*p->f, p->t0, x) - p->precision;
+}
+
+#include <stdio.h>
+#include <gsl/gsl_errno.h>
+#include <gsl/gsl_math.h>
+#include <gsl/gsl_roots.h>
+
+
+int sequential_curvature_fitter(cairo_t* cr, Piecewise<D2<SBasis> > const &f, double t0, double t1, double precision) {
+ if(t0 >= t1) return 0;
+
+ double r = t1;
+ if(single_curvature_fitter(f, t0, t1) > precision) {
+ int status;
+ int iter = 0, max_iter = 100;
+ const gsl_root_fsolver_type *T;
+ gsl_root_fsolver *s;
+ gsl_function F;
+ struct quadratic_params params = {&f, t0, precision};
+
+ F.function = &quadratic;
+ F.params = &params;
+
+ T = gsl_root_fsolver_brent;
+ s = gsl_root_fsolver_alloc (T);
+ gsl_root_fsolver_set (s, &F, t0, t1);
+
+ do
+ {
+ iter++;
+ status = gsl_root_fsolver_iterate (s);
+ r = gsl_root_fsolver_root (s);
+ double x_lo = gsl_root_fsolver_x_lower (s);
+ double x_hi = gsl_root_fsolver_x_upper (s);
+ status = gsl_root_test_interval (x_lo, x_hi,
+ 0, 0.001);
+
+
+ }
+ while (status == GSL_CONTINUE && iter < max_iter);
+
+ double x_lo = gsl_root_fsolver_x_lower (s);
+ double x_hi = gsl_root_fsolver_x_upper (s);
+ printf ("%5d [%.7f, %.7f] %.7f %.7f\n",
+ iter, x_lo, x_hi,
+ r,
+ x_hi - x_lo);
+ gsl_root_fsolver_free (s);
+ }
+ D2<SBasis> k_bez = sb_seg_to_bez(f,t0,r);
+
+ cairo_save(cr);
+ cairo_set_line_width (cr, 0.93);
+ cairo_set_source_rgba (cr, 0.7, 0.0, 0.0, 1);
+ draw_handle(cr, k_bez.at0());
+ cairo_d2_sb(cr, k_bez);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+
+ if(r < t1)
+ return sequential_curvature_fitter(cr, f, r, t1, precision) + 1;
+ return 1;
+}
+
+
+class SbToBezierTester: public Toy {
+ //std::vector<Slider> sliders;
+ PointHandle adjuster, adjuster2, adjuster3;
+ std::vector<Toggle> toggles;
+ Piecewise<D2<SBasis > > stroke;
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_save(cr);
+
+ cairo_set_source_rgba (cr, 0., 0., 0., 1);
+ cairo_set_line_width (cr, 0.5);
+
+ if(!mouses.empty()) {
+ cairo_move_to(cr, mouses[0]);
+ for(auto & mouse : mouses) {
+ cairo_line_to(cr, mouse);
+ }
+ cairo_stroke(cr);
+ }
+ adjuster2.pos[0]=150;
+ adjuster2.pos[1]=std::min(std::max(adjuster2.pos[1],150.),450.);
+ cairo_move_to(cr, 150, 150);
+ cairo_line_to(cr, 150, 450);
+ cairo_stroke(cr);
+ ostringstream val_s;
+ double scale0=(450-adjuster2.pos[1])/300;
+ double curve_precision = pow(10, scale0*5-2);
+ val_s << curve_precision;
+ draw_text(cr, adjuster2.pos, val_s.str().c_str());
+
+
+ Piecewise<D2<SBasis> > f_as_pw = stroke;
+ cairo_pw_d2_sb(cr, f_as_pw);
+ cairo_stroke(cr);
+ if(!stroke.empty()) {
+ f_as_pw = arc_length_parametrization(f_as_pw);
+ int segs = 0;
+ goal_function_type = toggles[1].on;
+ if(toggles[0].on)
+ segs = sequential_curvature_fitter(cr, f_as_pw, 0, f_as_pw.cuts.back(), curve_precision);
+ else {
+ segs = recursive_curvature_fitter(cr, f_as_pw, 0, f_as_pw.cuts.back(),curve_precision);
+ }
+ *notify << " total segments: "<< segs <<"\n";
+ }
+ cairo_restore(cr);
+ Point p(25, height - 50), d(50,25);
+ toggles[0].bounds = Rect(p, p + d);
+ p+= Point(75, 0);
+ toggles[1].bounds = Rect(p, p + d);
+ draw_toggles(cr, toggles);
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+public:
+ void key_hit(GdkEventKey *e) override {
+ if(e->keyval == 's') toggles[0].toggle();
+ redraw();
+ }
+ vector<Point> mouses;
+ int mouse_drag;
+
+ void mouse_pressed(GdkEventButton* e) override {
+ toggle_events(toggles, e);
+ Toy::mouse_pressed(e);
+ if(!selected) {
+ mouse_drag = 1;
+ mouses.clear();
+ }
+ }
+
+
+ void mouse_moved(GdkEventMotion* e) override {
+ if(mouse_drag) {
+ mouses.emplace_back(e->x, e->y);
+ redraw();
+ } else {
+ Toy::mouse_moved(e);
+ }
+ }
+
+ void mouse_released(GdkEventButton* e) override {
+ mouse_drag = 0;
+ stroke.clear();
+ stroke.push_cut(0);
+ Path pth;
+ for(unsigned i = 2; i < mouses.size(); i+=2) {
+ pth.append(QuadraticBezier(mouses[i-2], mouses[i-1], mouses[i]));
+ }
+ stroke = pth.toPwSb();
+ Toy::mouse_released(e);
+ }
+
+ SbToBezierTester() {
+ adjuster.pos = Geom::Point(150+300*uniform(),150+300*uniform());
+ handles.push_back(&adjuster);
+ adjuster2.pos = Geom::Point(150,300);
+ handles.push_back(&adjuster2);
+ adjuster3.pos = Geom::Point(450,300);
+ handles.push_back(&adjuster3);
+ toggles.emplace_back("Seq", false);
+ toggles.emplace_back("Linfty", true);
+ //}
+ //sliders.push_back(Slider(0.0, 1.0, 0.0, 0.0, "t"));
+ //handles.push_back(&(sliders[0]));
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new SbToBezierTester);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype = cpp:expandtab:shiftwidth = 4:tabstop = 8:softtabstop = 4:encoding = utf-8:textwidth = 99 :
diff --git a/src/3rdparty/2geom/src/toys/plane3d.cpp b/src/3rdparty/2geom/src/toys/plane3d.cpp
new file mode 100644
index 0000000..8710869
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/plane3d.cpp
@@ -0,0 +1,130 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/transforms.h>
+#include <2geom/sbasis-math.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <2geom/path.h>
+#include <2geom/svg-path-parser.h>
+
+#include <gsl/gsl_matrix.h>
+
+#include <vector>
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+class Box3d: public Toy {
+ double tmat[3][4];
+ PointHandle origin_handle;
+ PointSetHandle vanishing_points_handles;
+ PathVector paths_a;
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+
+ Geom::Point orig = origin_handle.pos;
+ cairo_set_source_rgba (cr, 0., 0.125, 0, 1);
+
+ /* create the transformation matrix for the map P^3 --> P^2 that has the following effect:
+ (1 : 0 : 0 : 0) --> vanishing point in x direction (= handle #0)
+ (0 : 1 : 0 : 0) --> vanishing point in y direction (= handle #1)
+ (0 : 0 : 1 : 0) --> vanishing point in z direction (= handle #2)
+ (0 : 0 : 0 : 1) --> origin (= handle #3)
+ */
+ for (int j = 0; j < 4; ++j) {
+ tmat[0][j] = vanishing_points_handles.pts[j][0];
+ tmat[1][j] = vanishing_points_handles.pts[j][1];
+ tmat[2][j] = 1;
+ }
+
+ *notify << "Projection matrix:" << endl;
+ for (auto & i : tmat) {
+ for (double j : i) {
+ *notify << j << " ";
+ }
+ *notify << endl;
+ }
+
+ for(const auto & i : paths_a) {
+ Piecewise<D2<SBasis> > path_a_pw = i.toPwSb();
+
+ D2<Piecewise<SBasis> > B = make_cuts_independent(path_a_pw);
+ Piecewise<SBasis> preimage[4];
+
+ preimage[0] = (B[0] - orig[0]) / 100;
+ preimage[1] = -(B[1] - orig[1]) / 100;
+ Piecewise<SBasis> res[3];
+ for (int j = 0; j < 3; ++j) {
+ res[j] = preimage[0] * tmat[j][0]
+ + preimage[1] * tmat[j][1]
+ + tmat[j][3];
+ }
+
+ //if (fabs (res[2]) > 0.000001) {
+ D2<Piecewise<SBasis> > result(divide(res[0],res[2], 2),
+ divide(res[1],res[2], 2));
+
+ cairo_d2_pw_sb(cr, result);
+ cairo_set_source_rgba (cr, 0., 0.125, 0, 1);
+ cairo_stroke(cr);
+ }
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+ void first_time(int argc, char** argv) override {
+ const char *path_a_name="ptitle.svgd";
+ if(argc > 1)
+ path_a_name = argv[1];
+ paths_a = read_svgd(path_a_name);
+ assert(paths_a.size() > 0);
+
+ // Finite images of the three vanishing points and the origin
+ handles.push_back(&origin_handle);
+ handles.push_back(&vanishing_points_handles);
+ vanishing_points_handles.push_back(550,350);
+ vanishing_points_handles.push_back(150,300);
+ vanishing_points_handles.push_back(380,40);
+ vanishing_points_handles.push_back(340,450);
+ // plane origin
+ origin_handle.pos = Point(180,65);
+ }
+ //int should_draw_bounds() {return 1;}
+
+ Geom::Point proj_image (cairo_t *cr, const double pt[4], const vector<Geom::Point> &/*handles*/)
+ {
+ double res[3];
+ for (int j = 0; j < 3; ++j) {
+ res[j] = 0;
+ for (int i = 0; i < 3; ++i)
+ res[j] += tmat[j][i] * pt[i];
+ }
+ if (fabs (res[2]) > 0.000001) {
+ Geom::Point result = Geom::Point (res[0]/res[2], res[1]/res[2]);
+ draw_handle(cr, result);
+ return result;
+ }
+ assert(0); // unclipped point
+ return Geom::Point(0,0);
+ }
+
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new Box3d);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/plane3d.py b/src/3rdparty/2geom/src/toys/plane3d.py
new file mode 100644
index 0000000..0ffcb51
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/plane3d.py
@@ -0,0 +1,78 @@
+#!/usr/bin/python
+
+import py2geom
+import toyframework
+import random,gtk
+import numpy
+from py2geom_glue import *
+
+class Box3d(toyframework.Toy):
+ def __init__(self):
+ toyframework.Toy.__init__(self)
+ self.tmat = numpy.zeros([3,4])
+ # plane origin
+ self.origin_handle = toyframework.PointHandle(180,65)
+ self.handles.append(self.origin_handle)
+ self.vanishing_points_handles = toyframework.PointSetHandle()
+ path_a_name="ptitle.svgd"
+ import sys
+ if len(sys.argv) > 1:
+ path_a_name = sys.argv[1]
+ self.paths_a = py2geom.read_svgd(path_a_name)
+
+
+ # Finite images of the three vanishing points and the origin
+ self.handles.append(self.vanishing_points_handles)
+ self.vanishing_points_handles.append(550,350)
+ self.vanishing_points_handles.append(150,300)
+ self.vanishing_points_handles.append(380,40)
+ self.vanishing_points_handles.append(340,450)
+ def draw(self, cr, pos, save):
+ orig = self.origin_handle.pos;
+ cr.set_source_rgba (0., 0.125, 0, 1)
+
+ # create the transformation matrix for the map P^3 --> P^2 that has the following effect:
+ # (1 : 0 : 0 : 0) --> vanishing point in x direction (= handle #0)
+ # (0 : 1 : 0 : 0) --> vanishing point in y direction (= handle #1)
+ # (0 : 0 : 1 : 0) --> vanishing point in z direction (= handle #2)
+ # (0 : 0 : 0 : 1) --> origin (= handle #3)
+
+ tmat = numpy.zeros([3,4])
+ for j in range(4):
+ tmat[0][j] = self.vanishing_points_handles.pts[j][0]
+ tmat[1][j] = self.vanishing_points_handles.pts[j][1]
+ tmat[2][j] = 1
+
+ self.notify = "Projection matrix:\n"
+ for i in range(3):
+ for j in range(4):
+ self.notify += str(tmat[i][j]) + " "
+ self.notify += '\n'
+
+ for p in self.paths_a:
+ B = py2geom.make_cuts_independant(p.toPwSb())
+ preimage = [None]*4
+
+ preimage[0] = (B[0] - orig[0]) / 100;
+ preimage[1] = -(B[1] - orig[1]) / 100;
+ Piecewise<SBasis> res[3];
+ for j in range(3):
+ res[j] = (preimage[0] * tmat[j][0] +
+ preimage[1] * tmat[j][1] +
+ + tmat[j][3])
+
+ result = D2PiecewiseSBasis(divide(res[0],res[2], 2),
+ divide(res[1],res[2], 2))
+
+ toyframework.cairo_d2_pw(cr, result)
+ cr.set_source_rgba (0., 0.125, 0, 1)
+ cr.stroke()
+
+ toyframework.Toy.draw(self, cr, pos, save)
+
+t = Box3d()
+import sys
+
+toyframework.init(sys.argv, t, 500, 500)
+
+
diff --git a/src/3rdparty/2geom/src/toys/point-curve-nearest-time.cpp b/src/3rdparty/2geom/src/toys/point-curve-nearest-time.cpp
new file mode 100644
index 0000000..0067920
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/point-curve-nearest-time.cpp
@@ -0,0 +1,397 @@
+/*
+ * point-curve nearest point routines testing
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/path.h>
+#include <2geom/curves.h>
+#include <2geom/angle.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/piecewise.h>
+
+#include <2geom/svg-path-parser.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <2geom/transforms.h>
+#include <2geom/pathvector.h>
+
+
+#include <algorithm>
+
+using namespace Geom;
+
+std::ostream&
+operator<< (std::ostream &out, PathVectorTime const &pvp)
+{
+ return out << pvp.path_index << "." << pvp.curve_index << "." << pvp.t;
+}
+
+class NearestPoints : public Toy
+{
+ enum menu_item_t
+ {
+ FIRST_ITEM = 1,
+ LINE_SEGMENT = FIRST_ITEM,
+ ELLIPTICAL_ARC,
+ SBASIS_CURVE,
+ PIECEWISE,
+ PATH,
+ PATH_SVGD,
+ TOTAL_ITEMS
+ };
+
+ static const char* menu_items[TOTAL_ITEMS];
+
+private:
+ PathVector paths_b;
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+
+ Point p = ph.pos;
+ Point np = p;
+ std::vector<Point> nps;
+
+ cairo_set_line_width (cr, 0.3);
+ cairo_set_source_rgb(cr, 0,0,0);
+ switch ( choice )
+ {
+ case '1':
+ {
+ LineSegment seg(psh.pts[0], psh.pts[1]);
+ cairo_move_to(cr, psh.pts[0]);
+ cairo_curve(cr, seg);
+ double t = seg.nearestTime(p);
+ np = seg.pointAt(t);
+ if ( toggles[0].on )
+ {
+ nps.push_back(np);
+ }
+ break;
+ }
+ case '2':
+ {
+ EllipticalArc earc;
+ bool earc_constraints_satisfied = true;
+ try
+ {
+ earc.set(psh.pts[0], 200, 150, 0, true, true, psh.pts[1]);
+ }
+ catch( RangeError e )
+ {
+ earc_constraints_satisfied = false;
+ }
+ if ( earc_constraints_satisfied )
+ {
+ cairo_d2_sb(cr, earc.toSBasis());
+ if ( toggles[0].on )
+ {
+ std::vector<double> t = earc.allNearestTimes(p);
+ for (double i : t)
+ nps.push_back(earc.pointAt(i));
+ }
+ else
+ {
+ double t = earc.nearestTime(p);
+ np = earc.pointAt(t);
+ }
+ }
+ break;
+ }
+ case '3':
+ {
+ D2<SBasis> A = psh.asBezier();
+ cairo_d2_sb(cr, A);
+ if ( toggles[0].on )
+ {
+ std::vector<double> t = Geom::all_nearest_times(p, A);
+ for (double i : t)
+ nps.push_back(A(i));
+ }
+ else
+ {
+ double t = nearest_time(p, A);
+ np = A(t);
+ }
+ break;
+ }
+ case '4':
+ {
+ D2<SBasis> A = handles_to_sbasis(psh.pts.begin(), 3);
+ D2<SBasis> B = handles_to_sbasis(psh.pts.begin() + 3, 3);
+ D2<SBasis> C = handles_to_sbasis(psh.pts.begin() + 6, 3);
+ D2<SBasis> D = handles_to_sbasis(psh.pts.begin() + 9, 3);
+ cairo_d2_sb(cr, A);
+ cairo_d2_sb(cr, B);
+ cairo_d2_sb(cr, C);
+ cairo_d2_sb(cr, D);
+ Piecewise< D2<SBasis> > pwc;
+ pwc.push_cut(0);
+ pwc.push_seg(A);
+ pwc.push_cut(0.25);
+ pwc.push_seg(B);
+ pwc.push_cut(0.50);
+ pwc.push_seg(C);
+ pwc.push_cut(0.75);
+ pwc.push_seg(D);
+ pwc.push_cut(1);
+ if ( toggles[0].on )
+ {
+ std::vector<double> t = Geom::all_nearest_times(p, pwc);
+ for (double i : t)
+ nps.push_back(pwc(i));
+ }
+ else
+ {
+ double t = Geom::nearest_time(p, pwc);
+ np = pwc(t);
+ }
+ break;
+ }
+ case '5':
+ {
+ closed_toggle = true;
+ BezierCurveN<3> A(psh.pts[0], psh.pts[1], psh.pts[2], psh.pts[3]);
+ BezierCurveN<2> B(psh.pts[3], psh.pts[4], psh.pts[5]);
+ BezierCurveN<3> C(psh.pts[5], psh.pts[6], psh.pts[7], psh.pts[8]);
+ Path path;
+ path.append(A);
+ path.append(B);
+ path.append(C);
+ EllipticalArc D;
+ bool earc_constraints_satisfied = true;
+ try
+ {
+ D.set(psh.pts[8], 160, 80, 0, true, true, psh.pts[9]);
+ }
+ catch( RangeError e )
+ {
+ earc_constraints_satisfied = false;
+ }
+ if ( earc_constraints_satisfied ) path.append(D);
+ if ( toggles[1].on ) path.close(true);
+
+ cairo_path(cr, path);
+
+ if ( toggles[0].on )
+ {
+ std::vector<double> t = path.allNearestTimes(p);
+ for (double i : t)
+ nps.push_back(path.pointAt(i));
+ }
+ else
+ {
+ PathTime pt = path.nearestTime(p);
+ np = path.pointAt(pt);
+ }
+ break;
+ }
+ case '6':
+ {
+ closed_toggle = true;
+ PathVector pathv = paths_b*Translate(psh.pts[0]-paths_b[0][0].initialPoint());
+ //std::cout << pathv.size() << std::endl;
+ OptRect optRect = bounds_fast(pathv);
+
+ cairo_rectangle(cr, *optRect);
+ cairo_stroke(cr);
+
+ cairo_path(cr, pathv);
+
+ if ( toggles[0].on )
+ {
+ std::vector<PathVectorTime> t = pathv.allNearestTimes(p);
+ for (auto & i : t)
+ nps.push_back(pathv.pointAt(i));
+ }
+ else
+ {
+ //std::optional<PathVectorTime>
+ double s = 0, e = 1;
+ draw_cross(cr, pathv[0].pointAt(s));
+ draw_cross(cr, pathv[0].pointAt(e));
+ double t = pathv[0][0].nearestTime(p, 0, 1);
+ if(t) {
+ *notify << p+psh.pts[0] << std::endl;
+ *notify << t << std::endl;
+ np = pathv[0].pointAt(t);
+ }
+ }
+ break;
+ }
+ default:
+ {
+ *notify << std::endl;
+ for (int i = FIRST_ITEM; i < TOTAL_ITEMS; ++i)
+ {
+ *notify << " " << i << " - " << menu_items[i] << std::endl;
+ }
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ return;
+ }
+ }
+
+ if ( toggles[0].on )
+ {
+ for (auto & np : nps)
+ {
+ cairo_move_to(cr, p);
+ cairo_line_to(cr, np);
+ }
+ }
+ else
+ {
+ cairo_move_to(cr, p);
+ cairo_line_to(cr, np);
+ }
+ cairo_stroke(cr);
+
+ toggles[0].bounds = Rect( Point(10, height - 50), Point(10, height - 50) + Point(80,25) );
+ toggles[0].draw(cr);
+ if ( closed_toggle )
+ {
+ toggles[1].bounds = Rect( Point(100, height - 50), Point(100, height - 50) + Point(80,25) );
+ toggles[1].draw(cr);
+ closed_toggle = false;
+ }
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ void key_hit(GdkEventKey *e) override
+ {
+ choice = e->keyval;
+ switch ( choice )
+ {
+ case '1':
+ total_handles = 2;
+ break;
+ case '2':
+ total_handles = 2;
+ break;
+ case '3':
+ total_handles = 6;
+ break;
+ case '4':
+ total_handles = 13;
+ break;
+ case '5':
+ total_handles = 10;
+ break;
+ case '6':
+ total_handles = 1;
+ break;
+ default:
+ total_handles = 0;
+ }
+ psh.pts.clear();
+ psh.push_back( 262.6037,35.824151);
+ psh.pts[0] += Point(300,300);
+ psh.push_back(0,0);
+ psh.pts[1] += psh.pts[0];
+ psh.push_back(-92.64892,-187.405851);
+ psh.pts[2] += psh.pts[0];
+ psh.push_back(30,-149.999981);
+ psh.pts[3] += psh.pts[0];
+ for ( unsigned int i = 0; i < total_handles; ++i )
+ {
+ psh.push_back(uniform()*400, uniform()*400);
+ }
+ ph.pos = Point(uniform()*400, uniform()*400);
+ redraw();
+ }
+
+ void mouse_pressed(GdkEventButton* e) override
+ {
+ toggle_events(toggles, e);
+ Toy::mouse_pressed(e);
+ }
+
+public:
+ void first_time(int argc, char** argv) override {
+ const char *path_b_name="star.svgd";
+ if(argc > 1)
+ path_b_name = argv[1];
+ paths_b = read_svgd(path_b_name);
+ }
+ NearestPoints()
+ : total_handles(0), choice('0'), closed_toggle(false)
+ {
+ handles.push_back(&psh);
+ handles.push_back(&ph);
+ ph.pos = Point(uniform()*400, uniform()*400);
+ toggles.emplace_back("ALL NP", false );
+ toggles.emplace_back("CLOSED", false );
+ }
+
+private:
+ PointSetHandle psh;
+ PointHandle ph;
+ std::vector<Toggle> toggles;
+ unsigned int total_handles;
+ char choice;
+ bool closed_toggle;
+};
+
+const char* NearestPoints::menu_items[] =
+{
+ "",
+ "LineSegment",
+ "EllipticalArc",
+ "SBasisCurve",
+ "Piecewise",
+ "Path",
+ "Path from SVGD"
+};
+
+
+
+int main(int argc, char **argv)
+{
+ init( argc, argv, new NearestPoints() );
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/portion-test.cpp b/src/3rdparty/2geom/src/toys/portion-test.cpp
new file mode 100644
index 0000000..bc64db3
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/portion-test.cpp
@@ -0,0 +1,105 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-geometric.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <time.h>
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+// TODO:
+// use path2
+// replace Ray stuff with path2 line segments.
+
+//-----------------------------------------------
+
+class PortionTester: public Toy {
+ PointSetHandle curve_handle;
+ PointHandle sample_point1, sample_point2;
+ std::vector<Toggle> toggles;
+ void mouse_pressed(GdkEventButton* e) override {
+ toggle_events(toggles, e);
+ Toy::mouse_pressed(e);
+ }
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+
+ draw_toggles(cr, toggles);
+ D2<SBasis> B = curve_handle.asBezier();
+
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0., 0.5, 0., 1);
+ cairo_d2_sb(cr, B);
+ cairo_stroke(cr);
+
+ sample_point1.pos[1]=400;
+ sample_point1.pos[0]=std::max(150.,sample_point1.pos[0]);
+ sample_point1.pos[0]=std::min(450.,sample_point1.pos[0]);
+ sample_point2.pos[1]=400;
+ sample_point2.pos[0]=std::max(150.,sample_point2.pos[0]);
+ sample_point2.pos[0]=std::min(450.,sample_point2.pos[0]);
+ cairo_move_to(cr, Geom::Point(150,400));
+ cairo_line_to(cr, Geom::Point(450,400));
+ cairo_set_source_rgba (cr, 0., 0., 0.5, 0.8);
+ cairo_stroke(cr);
+
+ double t0=std::max(0.,std::min(1.,(sample_point1.pos[0]-150)/300.));
+ double t1=std::max(0.,std::min(1.,(sample_point2.pos[0]-150)/300.));
+
+ Path P;
+ P.append(B);
+
+ if (toggles[0].on) {
+ if (toggles[1].on)
+ cairo_curve(cr, P.portion(t0,t1)[0]);
+ else
+ cairo_path(cr, P.portion(t0,t1));
+ } else
+ cairo_d2_sb(cr, portion(B,t0,t1));
+
+
+ cairo_set_source_rgba (cr, 0.5, 0.2, 0., 0.8);
+ cairo_stroke(cr);
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+public:
+ PortionTester(){
+ toggles.emplace_back("Path", true);
+ toggles[0].bounds = Rect(Point(10,100), Point(100, 130));
+ toggles.emplace_back("Curve", true);
+ toggles[1].bounds = Rect(Point(10,130), Point(100, 160));
+ if(handles.empty()) {
+ handles.push_back(&curve_handle);
+ handles.push_back(&sample_point1);
+ handles.push_back(&sample_point2);
+ for(unsigned i = 0; i < 4; i++)
+ curve_handle.push_back(150+uniform()*300,150+uniform()*300);
+ sample_point1.pos = Geom::Point(250,300);
+ sample_point2.pos = Geom::Point(350,300);
+ }
+ }
+};
+
+int main(int argc, char **argv) {
+ std::cout << "testing unit_normal(multidim_sbasis) based offset." << std::endl;
+ init(argc, argv, new PortionTester);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+//vim:expandtab:shiftwidth = 4:tabstop = 8:softtabstop = 4:encoding = utf-8:textwidth = 99 :
+
+
diff --git a/src/3rdparty/2geom/src/toys/precise-flat.cpp b/src/3rdparty/2geom/src/toys/precise-flat.cpp
new file mode 100644
index 0000000..0113619
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/precise-flat.cpp
@@ -0,0 +1,86 @@
+/**
+ * efficient and precise flattening of curves.
+ * incomplete rewrite (njh)
+ */
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/bezier-to-sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+using std::vector;
+using namespace Geom;
+
+unsigned total_pieces_sub;
+unsigned total_pieces_inc;
+
+class PreciseFlat: public Toy {
+ PointSetHandle hand;
+void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_line_width (cr, 0.5);
+
+ D2<SBasis> B = hand.asBezier();
+ D2<SBasis> dB = derivative(B);
+ D2<SBasis> ddB = derivative(dB);
+ cairo_set_source_rgb(cr, 0,0,0);
+ cairo_d2_sb(cr, B);
+ cairo_stroke(cr);
+
+ // draw the longest chord that is no worse than tol from the curve.
+
+ Geom::Point st = unit_vector(dB(0));
+ double s3 = fabs(dot(hand.pts[2] - hand.pts[0], rot90(st)));
+
+ SBasis inflect = dot(dB, rot90(ddB));
+ std::vector<double> rts = roots(inflect);
+ double f = 3;
+ for(double rt : rts) {
+ draw_handle(cr, B(rt));
+
+ double tp = rt;
+ Geom::Point st = unit_vector(dB(tp));
+ Geom::Point O = B(tp);
+ double s4 = fabs(dot(hand.pts[3] - O, rot90(st)));
+ double tf = pow(f/s4, 1./3);
+ Geom::Point t1p = B(tp + tf*(1-tp));
+ Geom::Point t1m = B(tp - tf*(1-tp));
+ cairo_move_to(cr, t1m);
+ cairo_line_to(cr, t1p);
+ cairo_stroke(cr);
+ //std::cout << tp << ", " << t1m << ", " << t1p << std::endl;
+ }
+
+ cairo_move_to(cr, B(0));
+ double t0 = 2*sqrt(f/(3*s3));
+ //std::cout << t0 << std::endl;
+ cairo_line_to(cr, B(t0));
+ cairo_stroke(cr);
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+}
+
+public:
+PreciseFlat () {
+ for(unsigned i = 0; i < 4; i++)
+ hand.pts.emplace_back(uniform()*400, uniform()*400);
+ handles.push_back(&hand);
+}
+
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new PreciseFlat());
+
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/pw-compose-test.cpp b/src/3rdparty/2geom/src/toys/pw-compose-test.cpp
new file mode 100644
index 0000000..a7e9438
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/pw-compose-test.cpp
@@ -0,0 +1,98 @@
+#include <2geom/piecewise.h>
+#include <2geom/sbasis.h>
+#include <2geom/bezier-to-sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+using namespace Geom;
+
+class PwToy: public Toy {
+public:
+ vector<PointSetHandle*> pw_handles;
+ PointSetHandle slids;
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_source_rgba (cr, 0., 0.5, 0, 1);
+ cairo_set_line_width (cr, 1);
+
+ D2<Piecewise<SBasis> > pws;
+ for(unsigned i = 0; i < pw_handles.size(); i++) {
+ D2<SBasis> foo = pw_handles[i]->asBezier();
+ cairo_d2_sb(cr, foo);
+ for(unsigned d = 0; d < 2; d++) {
+ pws[d].cuts.push_back(150*i);
+ pws[d].segs.push_back(foo[d]);
+ }
+ }
+ for(unsigned d = 0; d < 2; d++)
+ pws[d].cuts.push_back(150*pw_handles.size());
+
+ slids.pts[0][1]=450;
+ slids.pts[1][1]=450;
+ slids.pts[2][1]=450;
+ slids.pts[3][1]=450;
+
+ cairo_set_source_rgba (cr, 0.2, 0.2, 0.2, 1);
+ D2<SBasis> foo = slids.asBezier();
+ SBasis g = foo[0] - Linear(150);
+ cairo_d2_sb(cr, foo);
+ for(unsigned i=0;i<20;i++){
+ double t=i/20.;
+ draw_handle(cr, foo(t));
+ }
+ cairo_stroke(cr);
+ foo[1]=foo[0];
+ foo[0]=Linear(150,450);
+ cairo_d2_sb(cr, foo);
+
+ cairo_d2_pw_sb(cr, pws);
+
+ cairo_stroke(cr);
+ cairo_set_source_rgba (cr, 0.9, 0., 0., 1);
+ D2<Piecewise<SBasis> > res = compose(pws, Piecewise<SBasis>(g));
+ cairo_d2_pw_sb(cr, res);
+ for(unsigned i=0;i<20;i++){
+ double t=(res[0].cuts.back()-res[0].cuts.front())*i/20.;
+ draw_handle(cr, Point(res[0](t),res[1](t)));
+ }
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ bool should_draw_numbers() override { return false; }
+
+ public:
+ PwToy () {
+ unsigned segs = 5;
+ unsigned handles_per_seg = 4;
+ double x = 150;
+ for(unsigned a = 0; a < segs; a++) {
+ PointSetHandle* psh = new PointSetHandle;
+
+ for(unsigned i = 0; i < handles_per_seg; i++, x+= 25)
+ psh->push_back(Point(x, uniform() * 150));
+ pw_handles.push_back(psh);
+ handles.push_back(psh);
+ }
+ for(unsigned i = 0; i < 4; i++)
+ slids.push_back(Point(150 + segs*50*i,100));
+ handles.push_back(&slids);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new PwToy());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/pw-funcs.cpp b/src/3rdparty/2geom/src/toys/pw-funcs.cpp
new file mode 100644
index 0000000..f4c6471
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/pw-funcs.cpp
@@ -0,0 +1,100 @@
+#include <2geom/piecewise.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-math.h>
+#include <2geom/bezier-to-sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <vector>
+
+using namespace Geom;
+using namespace std;
+
+void cairo_pw(cairo_t *cr, Piecewise<SBasis> p) {
+ for(unsigned i = 0; i < p.size(); i++) {
+ D2<SBasis> B;
+ B[0] = Linear(p.cuts[i], p.cuts[i+1]);
+ B[1] = p[i];
+ cairo_d2_sb(cr, B);
+ }
+}
+
+void cairo_horiz(cairo_t *cr, double y, vector<double> p) {
+ for(double i : p) {
+ cairo_move_to(cr, i, y);
+ cairo_rel_line_to(cr, 0, 10);
+ }
+}
+
+void cairo_vert(cairo_t *cr, double x, vector<double> p) {
+ for(double i : p) {
+ cairo_move_to(cr, x, i);
+ cairo_rel_line_to(cr, 10, 0);
+ }
+}
+
+Piecewise<SBasis> log(Interval in) {
+ Piecewise<SBasis> I = integral(Geom::reciprocal(Linear(in.min(), in.max())));
+ return I + Piecewise<SBasis> (-I.segs[0][0] + log(in.min()));
+}
+
+Piecewise<SBasis> xlogx(Interval in) {
+ Piecewise<SBasis> I = integral(log(in) + Piecewise<SBasis>(1));
+ return I + Piecewise<SBasis> (-I.segs[0][0] + in.min()*log(in.min()));
+}
+
+class PwToy: public Toy {
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_source_rgba (cr, 0., 0., 0., 1);
+ cairo_set_line_width (cr, 1);
+
+ Piecewise<SBasis> pws;
+
+ //pws = Geom::cos(Linear(0,100)) + 3;
+ pws = Geom::sqrt(Linear(0,100));
+ //pws = log(Interval(1,8));
+ //Piecewise<SBasis> l(Linear(-100,100));
+ //Piecewise<SBasis> one(Linear(1,1));
+ //pws = Geom::reciprocal(l*l + one)*l + l;
+ //pws = xlogx(Interval(0.5,3));
+ //pws = Geom::reciprocal(pws);
+ //pws = -integral(Geom::reciprocal(Linear(1,2)))*Piecewise<SBasis>(Linear(1,2));
+
+ pws = -pws*width/4 + width/2;
+ pws.scaleDomain(width/2);
+ pws.offsetDomain(width/4);
+
+ cairo_pw(cr, pws);
+
+ cairo_stroke(cr);
+ cairo_set_source_rgba (cr, 0., 0., .5, 1.);
+ cairo_horiz(cr, 500, pws.cuts);
+ cairo_stroke(cr);
+
+ *notify << "total pieces: " << pws.size();
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ bool should_draw_numbers() override { return false; }
+ int should_draw_bounds() override { return 2; }
+ public:
+ PwToy () {}
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new PwToy());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/pw-toy.cpp b/src/3rdparty/2geom/src/toys/pw-toy.cpp
new file mode 100644
index 0000000..93ca8ea
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/pw-toy.cpp
@@ -0,0 +1,117 @@
+#include <2geom/piecewise.h>
+#include <2geom/sbasis.h>
+#include <2geom/bezier-to-sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <vector>
+
+using namespace Geom;
+using namespace std;
+
+void cairo_pw(cairo_t *cr, Piecewise<SBasis> p) {
+ for(unsigned i = 0; i < p.size(); i++) {
+ D2<SBasis> B;
+ B[0] = Linear(p.cuts[i], p.cuts[i+1]);
+ B[1] = Linear(150) + p[i];
+ cairo_d2_sb(cr, B);
+ }
+}
+
+void cairo_horiz(cairo_t *cr, double y, vector<double> p) {
+ for(double i : p) {
+ cairo_move_to(cr, i, y);
+ cairo_rel_line_to(cr, 0, 10);
+ }
+}
+
+void cairo_vert(cairo_t *cr, double x, vector<double> p) {
+ for(double i : p) {
+ cairo_move_to(cr, x, i);
+ cairo_rel_line_to(cr, 10, 0);
+ }
+}
+
+#include "pwsbhandle.cpp" // FIXME: This looks like it may give problems later, (including a .cpp file)
+
+class PwToy: public Toy {
+ unsigned segs, handles_per_curve, curves;
+ PWSBHandle pwsbh[2];
+ PointHandle interval_test[2];
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_source_rgba (cr, 0., 0., 0., 1);
+ cairo_set_line_width (cr, 1);
+
+ std::vector<Piecewise<SBasis> > pws(curves);
+ for(unsigned a = 0; a < curves; a++) {
+ pws[a] = pwsbh[a].value();
+ cairo_pw(cr, pws[a]);
+ }
+ cairo_stroke(cr);
+
+ Piecewise<SBasis> pw_out = pws[0] + pws[1];
+
+ cairo_set_source_rgba (cr, 0., 0., .5, 1.);
+ cairo_horiz(cr, 500, pw_out.cuts);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba (cr, 0., 0., .5, 1.);
+ cairo_pw(cr, pws[0] + pws[1]);
+ cairo_stroke(cr);
+
+ Interval bs = *bounds_local(pw_out, Interval(interval_test[0].pos[0],
+ interval_test[1].pos[0]));
+ vector<double> vec;
+ vec.push_back(bs.min() + 150); vec.push_back(bs.max() + 150);
+ cairo_set_source_rgba (cr, .5, 0., 0., 1.);
+ cairo_vert(cr, 100, vec);
+ cairo_stroke(cr);
+
+ /* Portion demonstration
+ Piecewise<SBasis> pw_out = portion(pws[0], handles[handles.size() - 2][0], handles[handles.size() - 1][0]);
+ cairo_set_source_rgba (cr, 0, .5, 0, .25);
+ cairo_set_line_width(cr, 3);
+ cairo_pw(cr, pw_out);
+ cairo_stroke(cr);
+ */
+
+ *notify << pws[0].segN(interval_test[0].pos[0]) << "; " << pws[0].segT(interval_test[0].pos[0]);
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ bool should_draw_numbers() override { return false; }
+
+ public:
+ PwToy () {
+ segs = 3;
+ handles_per_curve = 4 * segs;
+ curves = 2;
+ for(unsigned a = 0; a < curves; a++) {
+ pwsbh[a] = PWSBHandle(4, 3);
+ handles.push_back(&pwsbh[a]);
+ for(unsigned i = 0; i < handles_per_curve; i++)
+ pwsbh[a].push_back(150 + 300*i/(4*segs), uniform() * 150 + 150 - 50 * a);
+ }
+ interval_test[0].pos = Point(150, 400);
+ interval_test[1].pos = Point(300, 400);
+ handles.push_back(&interval_test[0]);
+ handles.push_back(&interval_test[1]);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new PwToy());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/pw-toy.py b/src/3rdparty/2geom/src/toys/pw-toy.py
new file mode 100644
index 0000000..011c917
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/pw-toy.py
@@ -0,0 +1,180 @@
+#!/usr/bin/python
+
+import py2geom
+import toyframework
+import random,gtk
+from py2geom_glue import *
+
+def cairo_pw(cr, p):
+ for i in range(p.size()):
+ a,b = p.cuts[i], p.cuts[i+1]
+ bez = sbasis_to_bezier(p[i], 0)
+ cr.move_to(a, bez[0])
+ cr.curve_to(lerp(a, b, 1./3), bez[1],
+ lerp(a,b, 2./3), bez[2],
+ b, bez[3])
+
+def cairo_horiz(cr, y, ps):
+ for p in ps:
+ cr.move_to(p, y);
+ cr.rel_line_to(0, 10)
+
+def cairo_vert(cr, x, ps):
+ for p in ps:
+ cr.move_to(x, p)
+ cr.rel_line_to(10, 0)
+
+def l2s(l):
+ sb = py2geom.SBasis(l)
+ return sb
+
+def constant(l):
+ pws = py2geom.PiecewiseSBasis()
+
+ pws.push_cut(0)
+ pws.push_seg(l2s(py2geom.Linear(l,l)) )
+ pws.push_cut(1000)
+ return pws
+
+X = l2s(py2geom.Linear(0, 1))
+OmX = l2s(py2geom.Linear(1, 0))
+def bezier_to_sbasis(handles, order):
+ if(order == 0):
+ return l2s(py2geom.Linear(handles[0]))
+ elif(order == 1):
+ return l2s(py2geom.Linear(handles[0], handles[1]))
+ else:
+ return (py2geom.multiply(OmX, bezier_to_sbasis(handles[:-1], order-1)) +
+ py2geom.multiply(X, bezier_to_sbasis(handles[1:], order-1)))
+
+
+def bez_to_sbasis(handles, order):
+ return bezier_to_sbasis([h[1] for h in handles], order)
+
+class PWSBHandle(toyframework.Handle):
+ def __init__(self, cs, segs):
+ self.handles_per_curve = cs*segs
+ self.curve_size = cs
+ self.segs = segs
+ self.pts = []
+ def append(self, x, y):
+ self.pts.append(py2geom.Point(x,y))
+ def value(self, y_0=0):
+ pws = py2geom.PiecewiseSBasis()
+ for i in range(0, self.handles_per_curve, self.curve_size):
+ pws.push_cut(self.pts[i][0]);
+ for j in range(i, i + self.curve_size):
+ self.pts[j] = py2geom.Point(self.pts[j][0], self.pts[j][1] - y_0)
+ hnd = self.pts[i:i+self.curve_size]
+ pws.push_seg( bez_to_sbasis(hnd, self.curve_size-1));
+ for j in range(i, i + self.curve_size):
+ self.pts[j] = py2geom.Point(self.pts[j][0], self.pts[j][1] + y_0);
+
+ pws.push_cut(self.pts[self.handles_per_curve - 1][0]);
+ assert(pws.invariants());
+ return pws
+
+ def draw(self, cr, annotes):
+ for p in self.pts:
+ toyframework.draw_circ(cr, p)
+
+ def hit(self, mouse):
+ for i,p in enumerate(self.pts):
+ if(py2geom.distance(py2geom.Point(*mouse), p) < 5):
+ return i
+ return None
+
+ def move_to(self, hit, om, m):
+ om = py2geom.Point(*om)
+ m = py2geom.Point(*m)
+ if hit != None:
+ i,hand = hit
+ self.pts[hand] = m
+ for i in range(self.curve_size, self.handles_per_curve, self.curve_size):
+ self.pts[i-1] = py2geom.Point(self.pts[i][0],self.pts[i-1][1])
+
+ for i in range(0, self.handles_per_curve, self.curve_size):
+ for j in range(1, (self.curve_size-1)):
+ t = float(j)/(self.curve_size-1)
+ x = lerp(self.pts[i][0], self.pts[i+self.curve_size-1][0],t)
+ self.pts[i+j] = py2geom.Point(x, self.pts[i+j][1])
+
+
+
+class PwToy(toyframework.Toy):
+ def __init__(self):
+ toyframework.Toy.__init__(self)
+ self.segs = 2
+ self.handles_per_curve = 4 * self.segs
+ self.curves = 2
+ self.pwsbh = []
+ self.interval_test = []
+ for a in range(self.curves):
+ self.pwsbh.append(PWSBHandle(4, self.curves))
+ self.handles.append(self.pwsbh[a])
+ for i in range(self.handles_per_curve):
+ t = 150 + 300*i/(4*self.segs)
+ self.pwsbh[a].append(t, random.uniform(0,1) * 150 + 150 - 50 * a)
+ self.interval_test.append(toyframework.PointHandle(150, 400))
+ self.interval_test.append(toyframework.PointHandle(300, 400))
+ self.handles.append(self.interval_test[0])
+ self.handles.append(self.interval_test[1])
+ self.func = "pws[0] + pws[1]"
+ def gtk_ready(self):
+ import gtk
+ self.sb_entry = gtk.Entry()
+ self.sb_entry.connect("changed", self.sb_changed)
+ toyframework.get_vbox().add(self.sb_entry)
+ toyframework.get_vbox().show_all()
+ self.sb_entry.set_text(self.func)
+ def sb_changed(self, sb):
+ self.func = sb.get_text()
+ self.redraw()
+ def draw(self, cr, pos, save):
+ cr.set_source_rgba (0., 0., 0., 1)
+ cr.set_line_width (1)
+
+ pws = [self.pwsbh[i].value() for i in range(self.curves)]
+ for p in pws:
+ cairo_pw(cr, p)
+ cr.stroke()
+
+ d = locals().copy()
+ for i in dir(py2geom):
+ d[i] = py2geom.__dict__[i]
+ d['l2s'] = l2s
+ d['constant'] = constant
+ pw_out = eval(self.func, d)
+
+ bs = py2geom.bounds_local(pw_out, py2geom.OptInterval(
+ py2geom.Interval(self.interval_test[0].pos[0],
+ self.interval_test[1].pos[0])));
+ if not bs.isEmpty():
+ bs = bs.toInterval()
+ for ph in self.interval_test:
+ ph.pos= py2geom.Point(ph.pos[0], bs.middle())
+ cr.save()
+ cr.set_source_rgba (.0, 0.25, 0.5, 1.)
+ cr.rectangle(self.interval_test[0].pos[0], bs.min(),
+ self.interval_test[1].pos[0]-self.interval_test[0].pos[0], bs.extent())
+ cr.stroke()
+ bs = py2geom.bounds_exact(pw_out);
+ cr.set_source_rgba (0.25, 0.25, .5, 1.);
+ if not bs.isEmpty():
+ bs = bs.toInterval()
+ cairo_horiz(cr, bs.middle(), pw_out.cuts);
+ cr.stroke()
+ cr.restore()
+
+ cr.set_source_rgba (0., 0., .5, 1.);
+ cairo_pw(cr, pw_out)
+ cr.stroke()
+
+
+ self.notify = str(bs)
+ toyframework.Toy.draw(self, cr, pos, save)
+
+t = PwToy()
+import sys
+
+toyframework.init(sys.argv, t, 500, 500)
diff --git a/src/3rdparty/2geom/src/toys/pwsbhandle.cpp b/src/3rdparty/2geom/src/toys/pwsbhandle.cpp
new file mode 100644
index 0000000..ce4f21e
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/pwsbhandle.cpp
@@ -0,0 +1,77 @@
+class PWSBHandle : public Handle{
+public:
+ unsigned handles_per_curve, curve_size, segs;
+ PWSBHandle() {}
+ PWSBHandle(unsigned cs, unsigned segs) :handles_per_curve(cs*segs),curve_size(cs), segs(segs) {}
+ std::vector<Geom::Point> pts;
+ virtual void draw(cairo_t *cr, bool annotes = false);
+
+ virtual void* hit(Geom::Point mouse);
+ virtual void move_to(void* hit, Geom::Point om, Geom::Point m);
+ void push_back(double x, double y) {pts.push_back(Geom::Point(x,y));}
+ Piecewise<SBasis> value(double y_0=150) {
+ Piecewise<SBasis> pws;
+ Point* base = &pts[0];
+ for(unsigned i = 0; i < handles_per_curve; i+=curve_size) {
+ pws.push_cut(base[i][0]);
+ //Bad hack to move 0 to 150
+ for(unsigned j = i; j < i + curve_size; j++)
+ base[j] = Point(base[j][0], base[j][1] - y_0);
+ pws.push_seg( Geom::handles_to_sbasis(base+i, curve_size-1)[1]);
+ for(unsigned j = i; j < i + curve_size; j++)
+ base[j] = Point(base[j][0], base[j][1] + y_0);
+ }
+ pws.push_cut(base[handles_per_curve - 1][0]);
+ assert(pws.invariants());
+ return pws;
+ }
+ virtual void load(FILE* f);
+ virtual void save(FILE* f);
+};
+
+void PWSBHandle::draw(cairo_t *cr, bool /*annotes*/) {
+ for(auto & pt : pts) {
+ draw_circ(cr, pt);
+ }
+}
+
+void* PWSBHandle::hit(Geom::Point mouse) {
+ for(auto & pt : pts) {
+ if(Geom::distance(mouse, pt) < 5)
+ return (void*)(&pt);
+ }
+ return 0;
+}
+
+void PWSBHandle::move_to(void* hit, Geom::Point /*om*/, Geom::Point m) {
+ if(hit) {
+ *(Geom::Point*)hit = m;
+ Point* base = &pts[0];
+ for(unsigned i = curve_size; i < handles_per_curve; i+=curve_size) {
+ base[i-1][0] = base[i][0];
+ }
+ for(unsigned i = 0; i < handles_per_curve; i+=curve_size) {
+ for(unsigned j = 1; j < (curve_size-1); j++) {
+ double t = float(j)/(curve_size-1);
+ base[i+j][0] = (1 - t)*base[i][0] + t*base[i+curve_size-1][0];
+ }
+ }
+ }
+}
+
+void PWSBHandle::load(FILE* f) {
+ unsigned n = 0;
+ assert(3 == fscanf(f, "%d %d %d\n", &curve_size, &segs, &n));
+ assert(n == curve_size*segs);
+ pts.clear();
+ for(unsigned i = 0; i < n; i++) {
+ pts.push_back(read_point(f));
+ }
+}
+
+void PWSBHandle::save(FILE* f) {
+ fprintf(f, "%d %d %lu\n", curve_size, segs, pts.size());
+ for(auto & pt : pts) {
+ fprintf(f, "%lf %lf\n", pt[0], pt[1]);
+ }
+}
diff --git a/src/3rdparty/2geom/src/toys/py2geom_glue.py b/src/3rdparty/2geom/src/toys/py2geom_glue.py
new file mode 100644
index 0000000..fa2b5ae
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/py2geom_glue.py
@@ -0,0 +1,42 @@
+#!/usr/bin/python
+
+def choose(n, k):
+ r = 1
+ for i in range(1, k+1):
+ r = (r*(n-k+i))/i
+ return r
+
+def W(n, j, k):
+ q = (n+1)/2.
+ if((n & 1) == 0 and j == q and k == q):
+ return 1
+ if(k > n-k):
+ return W(n, n-j, n-k)
+ assert((k <= q))
+ if(k >= q):
+ return 0
+ # assert(!(j >= n-k));
+ if(j >= n-k):
+ return 0
+ # assert(!(j < k));
+ if(j < k):
+ return 0
+ return float(choose(n-2*k-1, j-k)) / choose(n,j);
+
+# this produces a degree 2q bezier from a degree k sbasis
+def sbasis_to_bezier(B, q):
+ if(q == 0):
+ q = len(B)
+ n = q*2
+ result = [0.0 for i in range(n)]
+ if(q > len(B)):
+ q = len(B)
+ n -= 1
+ for k in range(q):
+ for j in range(n-k+1):
+ result[j] += (W(n, j, k)*B[k][0] +
+ W(n, n-j, k)*B[k][1])
+ return result
+
+def lerp(a, b, t):
+ return (1-t)*a + t*b
diff --git a/src/3rdparty/2geom/src/toys/ray_test.py b/src/3rdparty/2geom/src/toys/ray_test.py
new file mode 100644
index 0000000..6ec8b01
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/ray_test.py
@@ -0,0 +1,20 @@
+# test of 2geom ray bindings
+
+import py2geom as g
+
+# find one point along a ray
+a = g.Point(0,0)
+b = g.Point(2,2)
+
+r = g.Ray(a,b)
+from math import sqrt
+print r.pointAt(sqrt(2))
+
+# measure the angle between two rays
+c = g.Point(2,-2)
+r2 = g.Ray(a,c)
+from math import degrees
+# FIXME: the third argument (clockwise) ought to be optional, but has to be supplied
+print degrees(g.angle_between(r, r2, True))
+print degrees(g.angle_between(r, r2))
+
diff --git a/src/3rdparty/2geom/src/toys/rdm-area.cpp b/src/3rdparty/2geom/src/toys/rdm-area.cpp
new file mode 100644
index 0000000..22cc104
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/rdm-area.cpp
@@ -0,0 +1,479 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-geometric.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <cstdlib>
+#include <vector>
+#include <list>
+#include <algorithm>
+using std::vector;
+using namespace Geom;
+
+#define SIZE 4
+#define NB_SLIDER 2
+
+struct Triangle{
+ Point a,b,c;
+ double area;
+};
+
+//TODO: this would work only for C1 pw<d2<sb>> input. Split the input at corners to work with pwd2sb...
+//TODO: for more general purpose, return a path...
+void toPoly(D2<SBasis> const &f, std::list<Point> &p, double tol, bool include_first=true){
+ D2<SBasis> df = derivative(f);
+ D2<SBasis> d2f = derivative(df);
+ double t=0;
+ if ( include_first ){ p.push_back( f.at0() );}
+ while (t<1){
+ Point v = unit_vector(df.valueAt(t));
+ //OptInterval bounds = bounds_local(df[X]*v[Y]-df[Y]*v[X], Interval(t,1));
+ OptInterval bounds = bounds_local(d2f[X]*v[Y]-d2f[Y]*v[X], Interval(t,1));
+ if (bounds) {
+ double bds_max = (-bounds->min()>bounds->max() ? -bounds->min() : bounds->max());
+ double dt;
+ //if (bds_max<tol) dt = 1;
+ //else dt = tol/bds_max;
+ if (bds_max<tol/4) dt = 1;
+ else dt = 2*std::sqrt( tol / bds_max );
+ t+=dt*5;
+ if (t>1) t = 1;
+ }else{
+ t = 1;
+ }
+ p.push_back( f.valueAt(t) );
+ }
+ return;
+}
+
+std::list<Point> toPoly(std::vector<Piecewise<D2<SBasis> > > f, double tol){
+ assert ( f.size() >0 && f[0].size() >0 );
+ std::list<Point> res;
+
+ for (unsigned i = 0; i<f.size(); i++){
+ for (unsigned j = 0; j<f[i].size(); j++){
+ toPoly(f[i][j],res,tol, j==0);
+ }
+ if ( f[i].segs.front().at0() != f[i].segs.back().at1() ){
+ res.push_back( f[i].segs.front().at0() );
+ }
+ if ( i>0 ) res.push_back( f[0][0].at0() );
+ }
+ return res;
+}
+
+//TODO: this is an ugly hack, use path intersection instead!!
+bool intersect(Point const &a0, Point const &b0, Point const &a1, Point const &b1, Point &c, double tol=.0001){
+ double abaa1 = cross( b0-a0, a1-a0);
+ double abab1 = cross( b0-a0, b1-a0);
+ double abaa0 = cross( b1-a1, a0-a1);
+ double abab0 = cross( b1-a1, b0-a1);
+ if ( abaa1 * abab1 < -tol && abaa0 * abab0 < -tol ){
+ c = a1 - (b1-a1) * abaa1/(abab1-abaa1);
+ return true;
+ }
+#if 1
+ return false;//TODO: handle limit cases!!
+#else
+ if ( abaa1 == 0 && dot( a0-a1, b0-a1 ) < 0 ) {
+ c = a1;
+ return true;
+ }
+ if ( abab1 == 0 && dot( a0-b1, b0-b1 ) < 0 ) {
+ c = b1;
+ return true;
+ }
+ if ( abaa0 == 0 && dot( a1-a0, b1-a0 ) < 0 ) {
+ c = a0;
+ return true;
+ }
+ if ( abab0 == 0 && dot( a1-b0, b1-b0 ) < 0 ) {
+ c = b0;
+ return true;
+ }
+ return false;
+#endif
+}
+
+//TODO: use path intersection stuff!
+void uncross(std::list<Point> &loop){
+ std::list<Point>::iterator b0 = loop.begin(),a0,b1,a1;
+ if ( b0 == loop.end() ) return;
+ a0 = b0;
+ ++b0;
+ if ( b0 == loop.end() ) return;
+ //now a0,b0 are 2 consecutive points.
+ while ( b0 != loop.end() ){
+ b1 = b0;
+ ++b1;
+ if ( b1 != loop.end() ) {
+ a1 = b1;
+ ++b1;
+ if ( b1 != loop.end() ) {
+ //now a0,b0,a1,b1 are 4 consecutive points.
+ Point c;
+ while ( b1 != loop.end() ){
+ if ( intersect(*a0,*b0,*a1,*b1,c) ){
+ if ( c != (*a0) && c != (*b0) ){
+ loop.insert(b1,c);
+ loop.insert(b0,c);
+ ++a1;
+ std::list<Point> loop_piece;
+ loop_piece.insert(loop_piece.begin(), b0, a1 );
+ loop_piece.reverse();
+ loop.erase( b0, a1 );
+ loop.splice( a1, loop_piece );
+ b0 = a0;
+ ++b0;
+ //a1 = b1; a1--;//useless
+ }else{
+ //TODO: handle degenerated crossings...
+ }
+ }else{
+ a1=b1;
+ ++b1;
+ }
+ }
+ }
+ }
+ a0 = b0;
+ ++b0;
+ }
+ return;//We should never reach this point.
+}
+//------------------------------------------------------------
+//------------------------------------------------------------
+//------------------------------------------------------------
+void triangulate(std::list<Point> &pts, std::vector<Triangle> &tri, bool clockwise = false, double tol=.001){
+ pts.unique();
+ while ( !pts.empty() && pts.front() == pts.back() ){ pts.pop_back(); }
+ if ( pts.size() < 3 ) return;
+ //cycle by 1 to have a better looking output...
+ pts.push_back(pts.front()); pts.pop_front();
+ std::list<Point>::iterator a,b,c,m;
+ int sign = (clockwise ? -1 : 1 );
+ a = pts.end(); --a;
+ b = pts.begin();
+ c = b; ++c;
+ //now a,b,c are 3 consecutive points.
+ if ( pts.size() == 3 ) {
+ Triangle abc;
+ abc.a = (*a);
+ abc.b = (*b);
+ abc.c = (*c);
+ abc.area = sign *( cross((*b) - (*a),(*c) - (*b))/2) ;
+ if ( abc.area >0 ){
+ tri.push_back(abc);
+ pts.clear();
+ }
+ return;
+ }
+ bool found = false;
+ while( c != pts.end() ){
+ double abac = cross((*b)-(*a),(*c)-(*a));
+ if ( fabs(abac)<tol && dot( *b-*a, *c-*b ) <= 0) {
+ //this is a degenerated triangle. Remove it and continue.
+ pts.erase(b);
+ triangulate(pts,tri,clockwise);
+ return;
+ }
+ m = c;
+ ++m;
+ while ( m != pts.end() && !found && m!=a){
+ bool pointing_inside;
+ double abam = cross((*b)-(*a),(*m)-(*a));
+ double bcbm = cross((*c)-(*b),(*m)-(*b));
+ if ( sign * abac > 0 ){
+ pointing_inside = ( sign * abam >= 0 ) && ( sign * bcbm >= 0 );
+ }else {
+ pointing_inside = ( sign * abam >=0 ) || ( sign * bcbm >=0);
+ }
+ if ( pointing_inside ){
+ std::list<Point>::iterator p=c,q=++p;
+ Point inter;
+ while ( q != pts.end() && !intersect(*b,*m,*p,*q,inter) ){
+ p=q;
+ ++q;
+ }
+ if ( q == pts.end() ){
+ found = true;
+ }else{
+ ++m;
+ }
+ }else{
+ ++m;
+ }
+ }
+ if ( found ){
+ std::list<Point>pts_beg;
+ pts.insert(b,*b);
+ pts.insert(m,*m);
+ pts_beg.splice(pts_beg.begin(), pts, b, m);
+ triangulate(pts_beg,tri,clockwise);
+ triangulate(pts,tri,clockwise);
+ return;
+ }else{
+ a = b;
+ b = c;
+ ++c;
+ }
+ }
+ //we should never reach this point.
+}
+
+double
+my_rand_generator(){
+ double x = std::rand();
+ return x/RAND_MAX;
+}
+
+class RandomGenerator {
+public:
+ RandomGenerator();
+ RandomGenerator(Piecewise<D2<SBasis> >f_in, double tol=.1);
+ ~RandomGenerator(){};
+ void setDomain(Piecewise<D2<SBasis> >f_in, double tol=.1);
+ void set_generator(double (*rand_func)());
+ void resetRandomizer();
+ Point pt();
+ double area();
+
+protected:
+ double (*rand)();//set this to your favorite generator of numbers in [0,1] (an inkscape param for instance!)
+ long start_seed;
+ long seed;
+ std::vector<Triangle> triangles;
+ std::vector<double> areas;
+};
+
+RandomGenerator::RandomGenerator(){
+ seed = start_seed = 10;
+ rand = &my_rand_generator;//set this to your favorite generator of numbers in [0,1]!
+}
+RandomGenerator::RandomGenerator(Piecewise<D2<SBasis> >f_in, double tol){
+ seed = start_seed = 10;
+ rand = &my_rand_generator;//set this to your favorite generator of numbers in [0,1]!
+ setDomain(f_in, tol);
+}
+void RandomGenerator::setDomain(Piecewise<D2<SBasis> >f_in, double tol){
+ std::vector<Piecewise<D2<SBasis> > >f = split_at_discontinuities(f_in);
+ std::list<Point> p = toPoly( f, tol);
+ uncross(p);
+ if ( p.size()<3) return;
+ double tot_area = 0;
+ std::list<Point>::iterator a = p.begin(), b=a;
+ ++b;
+ while(b!=p.end()){
+ tot_area += ((*b)[X]-(*a)[X]) * ((*b)[Y]+(*a)[Y])/2;
+ ++a;++b;
+ }
+ bool clockwise = tot_area < 0;
+ triangles = std::vector<Triangle>();
+ triangulate(p,triangles,clockwise);
+ areas = std::vector<double>(triangles.size(),0.);
+ double cumul = 0;
+ for (unsigned i = 0; i<triangles.size(); i++){
+ cumul += triangles[i].area;
+ areas[i] = cumul;
+ }
+}
+
+void RandomGenerator::resetRandomizer(){
+ seed = start_seed;
+}
+Point RandomGenerator::pt(){
+ if (areas.empty()) return Point(0,0);
+ double pick_area = rand()*areas.back();
+ std::vector<double>::iterator picked = std::lower_bound( areas.begin(), areas.end(), pick_area);
+ unsigned i = picked - areas.begin();
+ double x = (*rand)();
+ double y = (*rand)();
+ if ( x+y > 1) {
+ x = 1-x;
+ y = 1-y;
+ }
+ //x=.3; y=.3;
+ Point res;
+ res = triangles[i].a;
+ res += x * ( triangles[i].b - triangles[i].a );
+ res += y * ( triangles[i].c - triangles[i].a );
+ return res;
+}
+double RandomGenerator::area(){
+ if (areas.empty()) return 0;
+ return areas.back();
+}
+void RandomGenerator::set_generator(double (*f)()){
+ rand = f;//set this to your favorite generator of numbers in [0,1]!
+}
+
+
+
+
+
+
+//-------------------------------------------------------
+// The toy!
+//-------------------------------------------------------
+class RandomToy: public Toy {
+
+ PointHandle adjuster[NB_SLIDER];
+
+public:
+ PointSetHandle b1_handle;
+ PointSetHandle b2_handle;
+ void draw(cairo_t *cr,
+ std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override {
+ srand(10);
+ for(unsigned i=0; i<NB_SLIDER; i++){
+ adjuster[i].pos[X] = 30+i*20;
+ if (adjuster[i].pos[Y]<100) adjuster[i].pos[Y] = 100;
+ if (adjuster[i].pos[Y]>400) adjuster[i].pos[Y] = 400;
+ cairo_move_to(cr, Point(30+i*20,100));
+ cairo_line_to(cr, Point(30+i*20,400));
+ cairo_set_line_width (cr, .5);
+ cairo_set_source_rgba (cr, 0., 0., 0., 1);
+ cairo_stroke(cr);
+ }
+ double tol = (400-adjuster[0].pos[Y])/300.*5+0.05;
+ double tau = (400-adjuster[1].pos[Y])/300.;
+// double scale_topback = (250-adjuster[2].pos[Y])/150.*5;
+// double scale_botfront = (250-adjuster[3].pos[Y])/150.*5;
+// double scale_botback = (250-adjuster[4].pos[Y])/150.*5;
+// double growth = 1+(250-adjuster[5].pos[Y])/150.*.1;
+// double rdmness = 1+(400-adjuster[6].pos[Y])/300.*.9;
+// double bend_amount = (250-adjuster[7].pos[Y])/300.*100.;
+
+ b1_handle.pts.back() = b2_handle.pts.front();
+ b1_handle.pts.front() = b2_handle.pts.back();
+ D2<SBasis> B1 = b1_handle.asBezier();
+ D2<SBasis> B2 = b2_handle.asBezier();
+
+ cairo_set_line_width(cr, 0.3);
+ cairo_set_source_rgba(cr, 0, 0, 0, 1);
+ cairo_d2_sb(cr, B1);
+ cairo_d2_sb(cr, B2);
+ cairo_set_line_width (cr, .5);
+ cairo_set_source_rgba (cr, 0., 0., 0., 1);
+ cairo_stroke(cr);
+
+
+ Piecewise<D2<SBasis> >B;
+ B.concat(Piecewise<D2<SBasis> >(B1));
+ B.continuousConcat(Piecewise<D2<SBasis> >(B2));
+
+ Piecewise<SBasis> are;
+
+ Point centroid_tmp(0,0);
+ are = integral(dot(B, rot90(derivative(B))))*0.5;
+ are = (are - are.firstValue())*(height/10) / (are.lastValue() - are.firstValue());
+
+ D2<Piecewise<SBasis> > are_graph(Piecewise<SBasis>(Linear(0, width)), are );
+ std::cout << are.firstValue() << "," << are.lastValue() << std::endl;
+ cairo_save(cr);
+ cairo_d2_pw_sb(cr, are_graph);
+ cairo_set_line_width (cr, .5);
+ cairo_set_source_rgba (cr, 0., 0., 0., 1);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+
+
+#if 0
+ std::vector<Piecewise<D2<SBasis> > >f = split_at_discontinuities(B);
+ std::list<Point> p = toPoly( f, tol);
+ uncross(p);
+ cairo_move_to(cr, p.front());
+ for (std::list<Point>::iterator pt = p.begin(); pt!=p.end(); ++pt){
+ cairo_line_to(cr, *pt);
+ //if (i++>p.size()*tau) break;
+ }
+ cairo_set_line_width (cr, 3);
+ cairo_set_source_rgba (cr, 1., 0., 0., .5);
+ cairo_stroke(cr);
+
+ if ( p.size()<3) return;
+ double tot_area = 0;
+ std::list<Point>::iterator a = p.begin(), b=a;
+ b++;
+ while(b!=p.end()){
+ tot_area += ((*b)[X]-(*a)[X]) * ((*b)[Y]+(*a)[Y])/2;
+ a++;b++;
+ }
+ bool clockwise = tot_area < 0;
+
+ std::vector<Triangle> tri;
+ int nbiter =0;
+ triangulate(p,tri,clockwise);
+ cairo_set_source_rgba (cr, 1., 1., 0., 1);
+ cairo_stroke(cr);
+ for (unsigned i=0; i<tri.size(); i++){
+ cairo_move_to(cr, tri[i].a);
+ cairo_line_to(cr, tri[i].b);
+ cairo_line_to(cr, tri[i].c);
+ cairo_line_to(cr, tri[i].a);
+ cairo_set_line_width (cr, .5);
+ cairo_set_source_rgba (cr, 0., 0., .9, .5);
+ cairo_stroke(cr);
+ cairo_move_to(cr, tri[i].a);
+ cairo_line_to(cr, tri[i].b);
+ cairo_line_to(cr, tri[i].c);
+ cairo_line_to(cr, tri[i].a);
+ cairo_set_source_rgba (cr, 0.5, 0., .9, .1);
+ cairo_fill(cr);
+ }
+#endif
+
+ RandomGenerator rdm = RandomGenerator(B, tol);
+ for(int i = 0; i < rdm.area()/5*tau; i++) {
+ draw_handle(cr, rdm.pt());
+ }
+ cairo_set_source_rgba (cr, 0., 0., 0., 1);
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+public:
+ RandomToy(){
+ for(int i = 0; i < SIZE; i++) {
+ b1_handle.push_back(150+uniform()*300,150+uniform()*300);
+ b2_handle.push_back(150+uniform()*300,150+uniform()*300);
+ }
+ b1_handle.pts[0] = Geom::Point(400,300);
+ b1_handle.pts[1] = Geom::Point(400,400);
+ b1_handle.pts[2] = Geom::Point(100,400);
+ b1_handle.pts[3] = Geom::Point(100,300);
+
+ b2_handle.pts[0] = Geom::Point(100,300);
+ b2_handle.pts[1] = Geom::Point(100,200);
+ b2_handle.pts[2] = Geom::Point(400,200);
+ b2_handle.pts[3] = Geom::Point(400,300);
+ handles.push_back(&b1_handle);
+ handles.push_back(&b2_handle);
+
+ for(unsigned i = 0; i < NB_SLIDER; i++) {
+ adjuster[i].pos = Geom::Point(30+i*20,250);
+ handles.push_back(&(adjuster[i]));
+ }
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new RandomToy);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+//vim:filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99:
diff --git a/src/3rdparty/2geom/src/toys/rect-toy.cpp b/src/3rdparty/2geom/src/toys/rect-toy.cpp
new file mode 100644
index 0000000..929afb7
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/rect-toy.cpp
@@ -0,0 +1,395 @@
+/*
+ * Rect Toy
+ *
+ * Copyright 2008 njh <>
+ * multitoy approach
+ * Copyright 2008 Marco <>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#include <2geom/line.h>
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <2geom/transforms.h>
+
+#include <2geom/angle.h>
+
+#include <vector>
+#include <string>
+#include <optional>
+
+using namespace Geom;
+
+
+
+std::string angle_formatter(double angle)
+{
+ return default_formatter(decimal_round(deg_from_rad(angle),2));
+}
+
+class LineToy : public Toy
+{
+ enum menu_item_t
+ {
+ SHOW_MENU = 0,
+ TEST_CREATE,
+ TEST_PROJECTION,
+ TEST_ORTHO,
+ TEST_DISTANCE,
+ TEST_POSITION,
+ TEST_SEG_BISEC,
+ TEST_ANGLE_BISEC,
+ TEST_COLLINEAR,
+ TEST_INTERSECTIONS,
+ TOTAL_ITEMS // this one must be the last item
+ };
+
+ enum handle_label_t
+ {
+ };
+
+ enum toggle_label_t
+ {
+ };
+
+ enum slider_label_t
+ {
+ ANGLE_SLIDER = 0,
+ };
+
+ static const char* menu_items[TOTAL_ITEMS];
+ static const char keys[TOTAL_ITEMS];
+
+ void first_time(int /*argc*/, char** /*argv*/) override
+ {
+ draw_f = &LineToy::draw_menu;
+ }
+
+ void init_common()
+ {
+ set_common_control_geometry = true;
+ set_control_geometry = true;
+
+ sliders.clear();
+ toggles.clear();
+ handles.clear();
+ }
+
+
+ virtual void draw_common( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool /*save*/ )
+ {
+ init_common_ctrl_geom(cr, width, height, notify);
+ }
+
+
+ void init_create()
+ {
+ init_common();
+
+ p1.pos = Point(400, 50);
+ p2.pos = Point(450, 450);
+
+ sliders.emplace_back(0, 2*M_PI, 0, 0, "angle");
+ sliders[ANGLE_SLIDER].formatter(&angle_formatter);
+
+ handles.push_back(&p1);
+ handles.push_back(&p2);
+ handles.push_back(&(sliders[ANGLE_SLIDER]));
+ }
+
+ void draw_create(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+ init_create_ctrl_geom(cr, notify, width, height);
+
+ Rect r1(p1.pos, p2.pos);
+
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_set_line_width(cr, 0.3);
+ cairo_rectangle(cr, r1);
+
+ Affine rot = Translate(-r1.midpoint())*Rotate(sliders[ANGLE_SLIDER].value())*Translate(r1.midpoint());
+ cairo_rectangle(cr, r1*rot);
+ cairo_move_to(cr, r1.corner(3)*rot);
+ for(int i = 0; i < 4; i++) {
+ cairo_line_to(cr, r1.corner(i)*rot);
+ }
+
+ cairo_stroke(cr);
+
+ draw_label(cr, p1, "P1");
+ draw_label(cr, p2, "P2");
+ }
+
+
+
+ void init_intersections()
+ {
+ init_common();
+ p1.pos = Point(400, 50);
+ p2.pos = Point(450, 450);
+ p3.pos = Point(100, 250);
+ p4.pos = Point(200, 450);
+ p5.pos = Point(50, 150);
+ p6.pos = Point(480, 60);
+
+ handles.push_back(&p1);
+ handles.push_back(&p2);
+ handles.push_back(&p3);
+ handles.push_back(&p4);
+ handles.push_back(&p5);
+ handles.push_back(&p6);
+ }
+
+ void draw_intersections(cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save,
+ std::ostringstream */*timer_stream*/)
+ {
+ draw_common(cr, notify, width, height, save);
+
+ Rect r1(p1.pos, p2.pos);
+ Rect r2(p3.pos, p4.pos);
+ Line l1(p5.pos, p6.pos);
+
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_set_line_width(cr, 0.3);
+ cairo_rectangle(cr, r1);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba(cr, 0.0, 0.3, 0.0, 1.0);
+ cairo_rectangle(cr, r2);
+ cairo_stroke(cr);
+
+ OptRect r1xr2 = intersect(r1, r2);
+ if(r1xr2) {
+ cairo_set_source_rgba(cr, 1.0, 0.7, 0.7, 1.0);
+ cairo_rectangle(cr, *r1xr2);
+ cairo_fill(cr);
+ }
+
+ cairo_set_source_rgba(cr, 0.2, 0.2, 0.2, 1.0);
+ cairo_set_line_width(cr, 0.3);
+ draw_line(cr, l1);
+ cairo_stroke(cr);
+
+
+ std::optional<LineSegment> ls = rect_line_intersect(r1, LineSegment(p5.pos, p6.pos));
+ *notify << "intersects: " << ((ls)?"true":"false") << std::endl;
+ if(ls) {
+ draw_handle(cr, (*ls)[0]);
+ draw_handle(cr, (*ls)[1]);
+ cairo_save(cr);
+ cairo_set_line_width(cr, 2);
+ cairo_move_to(cr, (*ls)[0]);
+ cairo_line_to(cr, (*ls)[1]);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ }
+
+
+ }
+
+ void init_common_ctrl_geom(cairo_t* /*cr*/, int /*width*/, int /*height*/, std::ostringstream* /*notify*/)
+ {
+ if ( set_common_control_geometry )
+ {
+ set_common_control_geometry = false;
+ }
+ }
+
+ void init_create_ctrl_geom(cairo_t* /*cr*/, std::ostringstream* /*notify*/, int /*width*/, int height)
+ {
+ if ( set_control_geometry )
+ {
+ set_control_geometry = false;
+
+ sliders[ANGLE_SLIDER].geometry(Point(50, height - 50), 180);
+ }
+ }
+
+
+
+ void draw_segment(cairo_t* cr, Point const& p1, Point const& p2)
+ {
+ cairo_move_to(cr, p1);
+ cairo_line_to(cr, p2);
+ }
+
+ void draw_segment(cairo_t* cr, Point const& p1, double angle, double length)
+ {
+ Point p2;
+ p2[X] = length * std::cos(angle);
+ p2[Y] = length * std::sin(angle);
+ p2 += p1;
+ draw_segment(cr, p1, p2);
+ }
+
+ void draw_segment(cairo_t* cr, LineSegment const& ls)
+ {
+ draw_segment(cr, ls[0], ls[1]);
+ }
+
+ void draw_ray(cairo_t* cr, Ray const& r)
+ {
+ double angle = r.angle();
+ draw_segment(cr, r.origin(), angle, m_length);
+ }
+
+ void draw_line(cairo_t* cr, Line const& l)
+ {
+ double angle = l.angle();
+ draw_segment(cr, l.origin(), angle, m_length);
+ draw_segment(cr, l.origin(), angle, -m_length);
+ }
+
+ void draw_label(cairo_t* cr, PointHandle const& ph, const char* label)
+ {
+ draw_text(cr, ph.pos+op, label);
+ }
+
+ void draw_label(cairo_t* cr, Line const& l, const char* label)
+ {
+ draw_text(cr, projection(Point(m_width/2-30, m_height/2-30), l)+op, label);
+ }
+
+ void draw_label(cairo_t* cr, LineSegment const& ls, const char* label)
+ {
+ draw_text(cr, middle_point(ls[0], ls[1])+op, label);
+ }
+
+ void draw_label(cairo_t* cr, Ray const& r, const char* label)
+ {
+ Point prj = r.pointAt(r.nearestTime(Point(m_width/2-30, m_height/2-30)));
+ if (L2(r.origin() - prj) < 100)
+ {
+ prj = r.origin() + 100*r.vector();
+ }
+ draw_text(cr, prj+op, label);
+ }
+
+ void init_menu()
+ {
+ handles.clear();
+ sliders.clear();
+ toggles.clear();
+ }
+
+ void draw_menu( cairo_t * /*cr*/, std::ostringstream *notify,
+ int /*width*/, int /*height*/, bool /*save*/,
+ std::ostringstream */*timer_stream*/)
+ {
+ *notify << std::endl;
+ for (int i = SHOW_MENU; i < TOTAL_ITEMS; ++i)
+ {
+ *notify << " " << keys[i] << " - " << menu_items[i] << std::endl;
+ }
+ }
+
+ void key_hit(GdkEventKey *e) override
+ {
+ char choice = std::toupper(e->keyval);
+ switch ( choice )
+ {
+ case 'A':
+ init_menu();
+ draw_f = &LineToy::draw_menu;
+ break;
+ case 'B':
+ init_create();
+ draw_f = &LineToy::draw_create;
+ break;
+ case 'C':
+ init_intersections();
+ draw_f = &LineToy::draw_intersections;
+ break;
+ }
+ redraw();
+ }
+
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ m_width = width;
+ m_height = height;
+ m_length = (m_width > m_height) ? m_width : m_height;
+ m_length *= 2;
+ (this->*draw_f)(cr, notify, width, height, save, timer_stream);
+ Toy::draw(cr, notify, width, height, save, timer_stream);
+ }
+
+ public:
+ LineToy()
+ {
+ op = Point(5,5);
+ }
+
+ private:
+ typedef void (LineToy::* draw_func_t) (cairo_t*, std::ostringstream*, int, int, bool, std::ostringstream*);
+ draw_func_t draw_f;
+ bool set_common_control_geometry;
+ bool set_control_geometry;
+ PointHandle p1, p2, p3, p4, p5, p6, O;
+ std::vector<Toggle> toggles;
+ std::vector<Slider> sliders;
+ Point op;
+ double m_width, m_height, m_length;
+
+}; // end class LineToy
+
+
+const char* LineToy::menu_items[] =
+{
+ "show this menu",
+ "rect generation",
+ "intersection with a line"
+};
+
+const char LineToy::keys[] =
+{
+ 'A', 'B', 'C'
+};
+
+
+
+int main(int argc, char **argv)
+{
+ init( argc, argv, new LineToy());
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/rect_01.cpp b/src/3rdparty/2geom/src/toys/rect_01.cpp
new file mode 100644
index 0000000..333843b
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/rect_01.cpp
@@ -0,0 +1,98 @@
+/*
+ * SimpleRect examples
+ *
+ * Copyright 2009 Evangelos Katsikaros <vkatsikaros at yahoo dot gr>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+/*
+Very Simple example of a toy that creates a rectangle on screen
+
+I am still very inexperienced with lib2geom
+so don't use these examples as a reference :)
+*/
+
+
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+
+#include <2geom/transforms.h>
+
+using std::vector;
+using namespace Geom;
+
+
+
+
+class SimpleRect: public Toy {
+ PointSetHandle psh;
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ {
+ cairo_save(cr);
+ Path p1;
+ p1.appendNew<LineSegment>(Point(0, 0));
+ p1.appendNew<LineSegment>(Point(100, 0));
+ p1.appendNew<LineSegment>(Point(100, 100));
+ p1.appendNew<LineSegment>(Point(0, 100));
+ p1.appendNew<LineSegment>(Point(0, 0));
+ p1.close();
+
+ Path p2 = p1 * Rotate::from_degrees(45); //
+
+ cairo_set_source_rgb(cr, 0,0,0);
+ cairo_path(cr, p1);
+ cairo_path(cr, p2);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ }
+ PointHandle p1, p2;
+ p1.pos = Point(300, 50);
+ p2.pos = Point(450, 450);
+
+ Rect r1(p1.pos, p2.pos);
+
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_set_line_width(cr, 0.3);
+ cairo_rectangle(cr, r1);
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save, timer_stream);
+ }
+
+ public:
+ SimpleRect(){
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new SimpleRect());
+
+ return 0;
+}
+
diff --git a/src/3rdparty/2geom/src/toys/rect_02.cpp b/src/3rdparty/2geom/src/toys/rect_02.cpp
new file mode 100644
index 0000000..a903e2d
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/rect_02.cpp
@@ -0,0 +1,81 @@
+/*
+ * SimpleRect examples
+ *
+ * Copyright 2009 Evangelos Katsikaros <vkatsikaros at yahoo dot gr>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+/*
+Simple example of a toy that creates a rectangle on screen.
+We also add two handles (that we don't use in our program)
+
+I am still very inexperienced with lib2geom
+so don't use these examples as a reference :)
+*/
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+using std::vector;
+using namespace Geom;
+
+
+class SimpleRect: public Toy {
+ PointSetHandle psh;
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+
+ PointHandle p1, p2;
+ p1.pos = Point(400, 50);
+ p2.pos = Point(450, 450);
+
+ Rect r1(p1.pos, p2.pos);
+
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_set_line_width(cr, 0.3);
+ cairo_rectangle(cr, r1);
+
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save, timer_stream);
+ }
+ public:
+ SimpleRect (unsigned no_of_handles) {
+ handles.push_back(&psh);
+ for(unsigned i = 0; i < no_of_handles; i++)
+ psh.push_back( 200 + ( i * 10 ), 300 + ( i * 10 ) );
+ }
+};
+
+int main(int argc, char **argv) {
+ unsigned no_of_handles=2;
+ if(argc > 1)
+ sscanf(argv[1], "%d", &no_of_handles);
+ init(argc, argv, new SimpleRect(no_of_handles));
+
+ return 0;
+}
+
diff --git a/src/3rdparty/2geom/src/toys/rect_03.cpp b/src/3rdparty/2geom/src/toys/rect_03.cpp
new file mode 100644
index 0000000..89be320
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/rect_03.cpp
@@ -0,0 +1,78 @@
+/*
+ * SimpleRect examples
+ *
+ * Copyright 2009 Evangelos Katsikaros <vkatsikaros at yahoo dot gr>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+/*
+Simple example of a toy that creates a rectangle on screen.
+Now we use the 2 handles to define the rect
+
+I am still very inexperienced with lib2geom
+so don't use these examples as a reference :)
+*/
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+using std::vector;
+using namespace Geom;
+
+
+
+class SimpleRect: public Toy {
+ PointSetHandle psh;
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ Rect r1(psh.pts[0], psh.pts[1]);
+
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_set_line_width(cr, 0.3);
+ cairo_rectangle(cr, r1);
+
+
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save, timer_stream);
+}
+ public:
+ SimpleRect (unsigned no_of_handles) {
+ handles.push_back(&psh);
+ for(unsigned i = 0; i < no_of_handles; i++)
+ psh.push_back( 200 + ( i * 20 ), 300 + ( i * 20 ) );
+ }
+};
+
+int main(int argc, char **argv) {
+ unsigned no_of_handles=2;
+ if(argc > 1)
+ sscanf(argv[1], "%d", &no_of_handles);
+ init(argc, argv, new SimpleRect(no_of_handles));
+
+ return 0;
+}
+
diff --git a/src/3rdparty/2geom/src/toys/root-finder-comparer.cpp b/src/3rdparty/2geom/src/toys/root-finder-comparer.cpp
new file mode 100644
index 0000000..3952d7c
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/root-finder-comparer.cpp
@@ -0,0 +1,247 @@
+#include <2geom/sbasis.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/solver.h>
+#include <2geom/sbasis-poly.h>
+#include "../2geom/orphan-code/nearestpoint.cpp" // FIXME: This looks like it may give problems later, (including a .cpp file)
+#include <2geom/path.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#define ZROOTS_TEST 0
+#if ZROOTS_TEST
+#include <2geom/zroots.c>
+#endif
+
+using std::swap;
+
+namespace Geom{
+extern void subdiv_sbasis(SBasis const & s,
+ std::vector<double> & roots,
+ double left, double right);
+};
+
+double eval_bernstein(double* w, double t, unsigned N) {
+ double Vtemp[2*N];
+ //const int degree = N-1;
+ for (unsigned i = 0; i < N; i++)
+ Vtemp[i] = w[i];
+
+ /* Triangle computation */
+ const double omt = (1-t);
+ //Left[0] = Vtemp[0];
+ //Right[degree] = Vtemp[degree];
+ double *prev_row = Vtemp;
+ double *row = Vtemp + N;
+ for (unsigned i = 1; i < N; i++) {
+ for (unsigned j = 0; j < N - i; j++) {
+ row[j] = omt*prev_row[j] + t*prev_row[j+1];
+ }
+ //Left[i] = row[0];
+ //Right[degree-i] = row[degree-i];
+ swap(prev_row, row);
+ }
+ return prev_row[0];
+}
+
+#include <vector>
+using std::vector;
+using namespace Geom;
+
+#ifdef HAVE_GSL
+#include <complex>
+using std::complex;
+#endif
+
+class RootFinderComparer: public Toy {
+public:
+ PointSetHandle psh;
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ std::vector<Geom::Point> trans;
+ trans.resize(psh.size());
+ for(unsigned i = 0; i < handles.size(); i++) {
+ trans[i] = psh.pts[i] - Geom::Point(0, height/2);
+ }
+
+ Timer tm;
+
+
+ std::vector<double> solutions;
+ solutions.resize(6);
+
+ tm.ask_for_timeslice();
+ tm.start();
+ FindRoots(&trans[0], 5, &solutions[0], 0);
+ Timer::Time als_time = tm.lap();
+ *notify << "original time = " << als_time << std::endl;
+
+ D2<SBasis> test_sb = psh.asBezier();//handles_to_sbasis(handles.begin(),5);
+ Interval bs = *bounds_exact(test_sb[1]);
+ cairo_move_to(cr, test_sb[0](0), bs.min());
+ cairo_line_to(cr, test_sb[0](1), bs.min());
+ cairo_move_to(cr, test_sb[0](0), bs.max());
+ cairo_line_to(cr, test_sb[0](1), bs.max());
+ cairo_stroke(cr);
+ *notify << "sb bounds = "<<bs.min()<< ", " <<bs.max()<<std::endl;
+ Poly ply = sbasis_to_poly(test_sb[1]);
+ ply = Poly(height/2) - ply;
+ cairo_move_to(cr, 0, height/2);
+ cairo_line_to(cr, width, height/2);
+ cairo_stroke(cr);
+#ifdef HAVE_GSL
+ vector<complex<double> > complex_solutions;
+ complex_solutions = solve(ply);
+#if 1
+ *notify << "gsl: ";
+ std::copy(complex_solutions.begin(), complex_solutions.end(), std::ostream_iterator<std::complex<double> >(*notify, ",\t"));
+ *notify << std::endl;
+#endif
+#endif
+
+#if ZROOTS_TEST
+ fcomplex a[ply.size()];
+ for(unsigned i = 0; i < ply.size(); i++) {
+ a[i] = ply[i];
+ }
+ //copy(a, a+ply.size(), ply.begin());
+ fcomplex rts[ply.size()];
+
+ zroots(a, ply.size(), rts, true);
+ for(unsigned i = 0; i < ply.size(); i++) {
+ if(! a[i].imag())
+ solutions[i] = a[i].real();
+ }
+#endif
+
+#ifdef HAVE_GSL
+
+ tm.ask_for_timeslice();
+ tm.start();
+ solve(ply);
+ als_time = tm.lap();
+ *timer_stream << "gsl poly = " << als_time << std::endl;
+#endif
+
+ #if ZROOTS_TEST
+ tm.ask_for_timeslice();
+ tm.start();
+ zroots(a, ply.size(), rts, false);
+ als_time = tm.lap();
+ *timer_stream << "zroots poly = " << als_time << std::endl;
+ #endif
+
+ #if LAGUERRE_TEST
+ tm.ask_for_timeslice();
+ tm.start();
+ Laguerre(ply);
+ als_time = tm.lap();
+ *timer_stream << "Laguerre poly = " << als_time << std::endl;
+ complex_solutions = Laguerre(ply);
+
+ #endif
+
+ #define SBASIS_SUBDIV_TEST 0
+ #if SBASIS_SUBDIV_TEST
+ tm.ask_for_timeslice();
+ tm.start();
+ subdiv_sbasis(-test_sb[1] + Linear(3*width/4),
+ rts, 0, 1);
+ als_time = tm.lap();
+ *timer_stream << "sbasis subdivision = " << als_time << std::endl;
+ #endif
+ #if 0
+ tm.ask_for_timeslice();
+ tm.start();
+ solutions.resize(0);
+ find_parametric_bezier_roots(&trans[0], 5, solutions, 0);
+ als_time = tm.lap();
+ *timer_stream << "solver parametric = " << als_time << std::endl;
+ #endif
+ double ys[trans.size()];
+ for(unsigned i = 0; i < trans.size(); i++) {
+ ys[i] = trans[i][1];
+ double x = double(i)/(trans.size()-1);
+ x = (1-x)*height/4 + x*height*3/4;
+ draw_handle(cr, Geom::Point(x, height/2 + ys[i]));
+ }
+
+ solutions.resize(0);
+ tm.ask_for_timeslice();
+ tm.start();
+ find_bernstein_roots(ys, 5, solutions, 0, 0, 1, false);
+ als_time = tm.lap();
+ *notify << "found sub solutions at:\n";
+ std::copy(solutions.begin(), solutions.end(), std::ostream_iterator<double >(*notify, ","));
+ *notify << "solver 1d bernstein subdivision n_slns = " << solutions.size()
+ << ", time = " << als_time << std::endl;
+
+ solutions.resize(0);
+ tm.ask_for_timeslice();
+ tm.start();
+ find_bernstein_roots(ys, 5, solutions, 0, 0, 1, true);
+ als_time = tm.lap();
+
+ *notify << "solver 1d bernstein secant subdivision slns" << solutions.size()
+ << ", time = " << als_time << std::endl;
+ *notify << "found secant solutions at:\n";
+ std::copy(solutions.begin(), solutions.end(), std::ostream_iterator<double >(*notify, ","));
+ *notify << "solver 1d bernstein subdivision accuracy:"
+ << std::endl;
+ for(double solution : solutions) {
+ *notify << solution << ":" << eval_bernstein(ys, solution, trans.size()) << ",";
+ }
+ tm.ask_for_timeslice();
+ tm.start();
+ solutions = roots( -test_sb[1] + Linear(height/2));
+ als_time = tm.lap();
+#if 1
+ *notify << "sbasis roots: ";
+ std::copy(solutions.begin(), solutions.end(), std::ostream_iterator<double>(*notify, ",\t"));
+ *notify << "\n time = " << als_time << std::endl;
+#endif
+ for(double solution : solutions) {
+ double x = test_sb[0](solution);
+ draw_cross(cr, Geom::Point(x, height/2));
+
+ }
+
+ *notify << "found " << solutions.size() << "solutions at:\n";
+ std::copy(solutions.begin(), solutions.end(), std::ostream_iterator<double >(*notify, ","));
+
+ D2<SBasis> B = psh.asBezier();//handles_to_sbasis(handles.begin(), 5);
+ Geom::Path pb;
+ pb.append(B);
+ pb.close(false);
+ cairo_path(cr, pb);
+
+ B[0] = Linear(width/4, 3*width/4);
+ cairo_d2_sb(cr, B);
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+ RootFinderComparer(unsigned degree)
+ {
+ for(unsigned i = 0; i < degree; i++) psh.push_back(Geom::Point(uniform()*400, uniform()*400));
+ handles.push_back(&psh);
+ }
+};
+
+int main(int argc, char **argv) {
+ unsigned bez_ord = 6;
+ if(argc > 1)
+ sscanf(argv[1], "%d", &bez_ord);
+ init(argc, argv, new RootFinderComparer(bez_ord));
+
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/rtree-toy.cpp b/src/3rdparty/2geom/src/toys/rtree-toy.cpp
new file mode 100644
index 0000000..b7872fa
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/rtree-toy.cpp
@@ -0,0 +1,573 @@
+/*
+ * Copyright 2009 Evangelos Katsikaros <vkatsikaros at yahoo dot gr>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+/*
+ initial toy for redblack trees
+*/
+
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <time.h>
+#include <vector>
+#include <sstream>
+#include <getopt.h>
+
+#include <2geom/orphan-code/rtree.h>
+#include "../2geom/orphan-code/rtree.cpp"
+
+
+//using std::vector;
+using namespace Geom;
+using namespace std;
+
+// make sure that in RTreeToy() constructor you assign the same number of colors
+// otherwise, they extra will be black :P
+const int no_of_colors = 8;
+const string search_str = "Mode: Search (Area: Click whitespace and Drag)";
+const string update_str = "Mode: Update (Click Bounding Box (dark gray) and Drag) NOT implemented";
+const string insert_str = "Mode: Insert (Click whitespace and Drag)" ;
+const string erase_str = "Mode: Delete (Click on Bounding Box (dark gray))";
+const string help_str = "'I': Insert, 'U': Update, 'S': Search, 'D': Delete";
+
+
+const char* program_name;
+
+class RTreeToy: public Toy
+{
+
+// PointSetHandle handle_set;
+// std::vector< Handle > rectangle_handles;
+ std::vector< RectHandle > rectangles;
+
+ Geom::Point starting_point; // during click and drag: start point of click
+ Geom::Point ending_point; // during click and drag: end point of click (release)
+ Geom::Point highlight_point; // not used
+
+ // colors we are going to use for different purposes
+ colour color_shape, color_shape_guide;
+ colour color_select_area, color_select_area_guide; // red(a=0.6), red
+
+ bool add_new_rect;
+ bool delete_rect;
+
+ Rect rect_chosen; // the rectangle of the search area
+ Rect dummy_draw; // the "helper" rectangle that is shown during the click and drag (before the mouse release)
+
+ // save the bounding boxes of the tree in here
+ std::vector< std::vector< Rect > > rects_level;
+ std::vector<colour> color_rtree_level;
+ unsigned drawBB_color;
+ bool drawBB_color_all;
+
+ enum the_modes {
+ INSERT_MODE = 0,
+ UPDATE_MODE,
+ DELETE_MODE,
+ SEARCH_MODE,
+ } mode; // insert/alter, search, delete modes
+ bool drawBB; // draw bounding boxes of RTree
+ string out_str, drawBB_str, drawBB_color_str;
+
+ // printing of the tree
+ //int help_counter; // the "x" of the label of each node
+ static const int label_size = 15 ; // size the label of each node
+
+ Geom::RTree rtree;
+
+ void * hit;
+ unsigned rect_id;
+
+
+ // used for the keys that switch between modes
+ enum menu_item_t
+ {
+ INSERT_I = 0,
+ UPDATE_U,
+ DELETE_D,
+ SEARCH_S,
+ BB_TOGGLE_T,
+ BB_DRAW_0,
+ BB_DRAW_1,
+ BB_DRAW_2,
+ BB_DRAW_3,
+ BB_DRAW_4,
+ BB_DRAW_5,
+ BB_DRAW_ALL_O,
+ TOTAL_ITEMS // this one must be the last item
+ };
+ static const char* menu_items[TOTAL_ITEMS];
+ static const char keys[TOTAL_ITEMS];
+
+
+
+ void draw( cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream ) override {
+ cairo_set_line_width( cr, 1 );
+ cairo_set_source_rgba( cr, color_shape );
+ cairo_stroke( cr );
+
+ // draw the shapes we save in the rtree
+ for(auto & rectangle : rectangles){
+ rectangle.draw( cr, true );
+ }
+ cairo_set_source_rgba( cr, color_shape );
+ cairo_stroke( cr );
+
+ // draw a rect if we did click & drag (so that we know what we are going to create)
+ if( add_new_rect ){
+ dummy_draw = Rect( starting_point, ending_point );
+ cairo_rectangle( cr, dummy_draw );
+ if( mode == INSERT_MODE ){
+ cairo_set_source_rgba( cr, color_shape_guide );
+ }
+ else if( mode == SEARCH_MODE ){
+ cairo_set_source_rgba( cr, color_select_area_guide );
+ }
+ cairo_stroke( cr );
+ }
+
+ // draw a rect for the search area
+ cairo_rectangle( cr, rect_chosen );
+ cairo_set_source_rgba( cr, color_select_area );
+ cairo_stroke( cr );
+
+ *notify << help_str << "\n"
+ << "'T': Bounding Boxes: " << drawBB_str << ", '0'-'" << no_of_colors << "', 'P': Show Layer: " << drawBB_color_str << "\n"
+ << out_str;
+
+ if( drawBB ){
+ for(unsigned color = 0 ; color < rects_level.size() ; color++ ){
+ if( drawBB_color == color || drawBB_color_all ){
+ for(auto & j : rects_level){
+ cairo_rectangle( cr, j );
+ }
+ cairo_set_source_rgba( cr, color_rtree_level[color] );
+ cairo_stroke( cr );
+ }
+ }
+ }
+
+ Toy::draw( cr, notify, width, height, save,timer_stream );
+ }
+
+ void mouse_moved( GdkEventMotion* e ) override{
+ if(add_new_rect &&
+ ( mode == INSERT_MODE || mode == SEARCH_MODE ) )
+ {
+ Toy::mouse_moved( e );
+ ending_point = Point( e->x, e->y );
+ }
+ }
+
+ void mouse_pressed( GdkEventButton* e ) override {
+ Toy::mouse_pressed( e );
+ if(e->button == 1){ // left mouse button
+ if( mode == INSERT_MODE ){
+ starting_point = Point( e->x, e->y );
+ ending_point = starting_point;
+ add_new_rect = true;
+ }
+ else if( mode == SEARCH_MODE ){
+ starting_point = Point( e->x, e->y );
+ ending_point = starting_point;
+ add_new_rect = true;
+ }
+ else if( mode == DELETE_MODE ) {
+ Geom::Point mouse(e->x, e->y);
+ unsigned i = 0;
+ for( i = 0; i < rectangles.size(); i++) {
+ hit = rectangles[i].hit(mouse);
+ if( hit ) {
+ break;
+ }
+ }
+ if( hit ){
+ // erase specific element
+ stringstream shape_id( rectangles[i].name );
+ unsigned shape_id_int;
+ shape_id >> shape_id_int;
+
+ rtree.erase( rectangles[i].pos, shape_id_int );
+ rectangles.erase( rectangles.begin() + i );
+// check_if_deleted( );
+// check_if_duplicates( );
+ delete_rect = true;
+ }
+ hit = NULL;
+ }
+ }
+ else if( e->button == 2 ){ //middle button
+ }
+ else if( e->button == 3 ){ //right button
+ }
+ }
+
+ void mouse_released( GdkEventButton* e ) override {
+ Toy::mouse_released( e );
+ if( e->button == 1 ) { //left mouse button
+ if( mode == INSERT_MODE ) {
+ if( add_new_rect ){
+ ending_point = Point( e->x, e->y );
+ RectHandle t( Rect(starting_point, ending_point), false );
+
+ std::stringstream out;
+ out << rect_id;;
+ t.name = out.str();
+ rectangles.push_back( t );
+ rect_id++;
+
+ insert_in_tree_the_last_rect();
+ find_rtree_subtrees_bounding_boxes( rtree );
+ add_new_rect = false;
+ }
+ }
+ else if( mode == SEARCH_MODE ){
+ if( add_new_rect ){
+ ending_point = Point( e->x, e->y );
+ rect_chosen = Rect( starting_point, ending_point );
+
+ std::vector< int > result(0);
+
+ if( rtree.root ){
+ rtree.search( rect_chosen, &result, rtree.root );
+ }
+ std::cout << "Search results: " << result.size() << std::endl;
+ for(int i : result){
+ std::cout << i << ", " ;
+ }
+ std::cout << std::endl;
+
+ add_new_rect = false;
+ }
+ }
+ else if( mode == DELETE_MODE ) { // mode: delete
+ if( delete_rect ){
+ delete_rect = false;
+ if( rtree.root ){
+ find_rtree_subtrees_bounding_boxes( rtree );
+ }
+ std::cout << " \nTree:\n" << std::endl;
+ rtree.print_tree( rtree.root, 0 );
+ std::cout << "...done\n" << std::endl;
+ }
+ }
+ }
+ else if( e->button == 2 ){ //middle button
+ }
+ else if( e->button == 3 ){ //right button
+ }
+ }
+
+
+ void key_hit( GdkEventKey *e ) override
+ {
+ char choice = std::toupper( e->keyval );
+ switch ( choice )
+ {
+ case 'I':
+ mode = INSERT_MODE;
+ out_str = insert_str;
+ break;
+ case 'S':
+ mode = SEARCH_MODE;
+ out_str = search_str;
+ break;
+ case 'D':
+ mode = DELETE_MODE;
+ out_str = erase_str;
+ break;
+ case 'U':
+ mode = UPDATE_MODE;
+ out_str = update_str;
+ break;
+ case 'T':
+ if( drawBB ){
+ drawBB = false;
+ drawBB_str = "OFF";
+ }
+ else{
+ drawBB = true;
+ drawBB_str = "ON";
+ }
+ break;
+ case 'P':
+ drawBB_color_all = true;
+ drawBB_color = 9;
+ drawBB_color_str = "all";
+ break;
+ case '0':
+ drawBB_color_all = false;
+ drawBB_color = 0;
+ drawBB_color_str = "0";
+ break;
+ case '1':
+ drawBB_color_all = false;
+ drawBB_color = 1;
+ drawBB_color_str = "1";
+ break;
+ case '2':
+ drawBB_color_all = false;
+ drawBB_color = 2;
+ drawBB_color_str = "2";
+ break;
+ case '3':
+ drawBB_color_all = false;
+ drawBB_color = 3;
+ drawBB_color_str = "3";
+ break;
+ case '4':
+ drawBB_color_all = false;
+ drawBB_color = 4;
+ drawBB_color_str = "4";
+ break;
+ case '5':
+ drawBB_color_all = false;
+ drawBB_color = 5;
+ drawBB_color_str = "5";
+ break;
+ case '6':
+ drawBB_color_all = false;
+ drawBB_color = 6;
+ drawBB_color_str = "6";
+ break;
+ case '7':
+ drawBB_color_all = false;
+ drawBB_color = 7;
+ drawBB_color_str = "7";
+ break;
+ }
+ redraw();
+ }
+
+
+ void insert_in_tree_the_last_rect(){
+ unsigned i = rectangles.size() - 1;
+ Rect r1 = rectangles[i].pos;
+
+ stringstream shape_id( rectangles[i].name );
+ unsigned shape_id_int;
+ shape_id >> shape_id_int;
+
+ // insert in R tree
+ rtree.insert( r1, shape_id_int );
+ std::cout << " \nTree:\n" << std::endl;
+ rtree.print_tree( rtree.root, 0 );
+ std::cout << "...done\n" << std::endl;
+ };
+
+
+ void find_rtree_subtrees_bounding_boxes( Geom::RTree tree ){
+ if( tree.root ){
+ // clear existing bounding boxes
+ for(auto & color : rects_level){
+ color.clear();
+ }
+ save_bb( tree.root, 0);
+ }
+ };
+
+ // TODO fix this.
+ void save_bb( Geom::RTreeNode* subtree_root, int depth )
+ {
+ if( subtree_root->children_nodes.size() > 0 ){
+
+ // descend in each one of the elements and call print_tree
+ for(auto & children_node : subtree_root->children_nodes){
+ Rect r1( children_node.bounding_box );
+ rects_level[ depth ].push_back( r1 );
+
+ if( depth == no_of_colors - 1 ){ // if we reached Nth levels of colors, roll back to color 0
+ save_bb( children_node.data, 0);
+ }
+ else{
+ save_bb( children_node.data, depth+1);
+ }
+ }
+ }
+ // else do nothing, entries are the rects themselves...
+ };
+
+
+
+public:
+ RTreeToy(unsigned rmin, unsigned rmax, char /*handlefile*/):
+ rectangles(0),
+ color_shape(0, 0, 0, 0.9), color_shape_guide(1, 0, 0, 1),
+ color_select_area(1, 0, 0, 0.6 ), color_select_area_guide(1, 0, 0, 1 ), //1, 0, 0, 1
+ add_new_rect( false ), delete_rect( false ),
+ rect_chosen(), dummy_draw(),
+ rects_level( no_of_colors ),
+ color_rtree_level( no_of_colors, colour(0, 0, 0, 0) ),
+ drawBB_color(9), drawBB_color_all(true),
+ mode( INSERT_MODE ), drawBB(true),
+ out_str( insert_str ),
+ drawBB_str("ON"), drawBB_color_str("all"),
+ rtree( rmin, rmax, QUADRATIC_SPIT ),
+ hit( 0 ), rect_id( 0 )
+ {
+ // only "bright" colors
+ color_rtree_level[0] = colour(0, 0.80, 1, 1); // cyan
+ color_rtree_level[1] = colour(0, 0.85, 0, 1); // green
+ color_rtree_level[2] = colour(0.75, 0, 0.75, 1); // purple
+ color_rtree_level[3] = colour(0, 0, 1, 1); // blue
+ color_rtree_level[4] = colour(1, 0.62, 0, 1); // orange
+ color_rtree_level[5] = colour(1, 0, 0.8, 1); // pink
+ color_rtree_level[6] = colour(0.47, 0.26, 0.12, 1);
+ color_rtree_level[7] = colour(1, 0.90, 0, 1); // yellow
+ }
+
+};
+
+
+
+int main(int argc, char **argv) {
+
+ char* min_arg = NULL;
+ char* max_arg = NULL;
+
+ int set_min_max = 0;
+
+ int c;
+
+ while (1)
+ {
+ static struct option long_options[] =
+ {
+ /* These options set a flag. */
+ /* These options don't set a flag.
+ We distinguish them by their indices. */
+ {"min-nodes", required_argument, 0, 'n'},
+ {"max-nodes", required_argument, 0, 'm'},
+ {"help", no_argument, 0, 'h'},
+ {0, 0, 0, 0}
+ };
+ /* getopt_long stores the option index here. */
+ int option_index = 0;
+
+ c = getopt_long (argc, argv, "n:m:h",
+ long_options, &option_index);
+
+ /* Detect the end of the options. */
+ if (c == -1){
+ break;
+ }
+
+ switch (c)
+ {
+ case 'n':
+ min_arg = optarg;
+ set_min_max += 1;
+ break;
+
+
+ case 'm':
+ max_arg = optarg;
+ set_min_max += 2;
+ break;
+
+
+ case 'h':
+ std::cerr << "Usage: " << argv[0] << " options\n" << std::endl ;
+ std::cerr <<
+ " -n --min-nodes=NUMBER minimum number in node.\n" <<
+ " -m --max-nodes=NUMBER maximum number in node.\n" <<
+ " -h --help Print this help.\n" << std::endl;
+ exit(1);
+ break;
+
+
+ case '?':
+ /* getopt_long already printed an error message. */
+ break;
+
+ default:
+ abort ();
+ }
+ }
+
+ unsigned rmin = 0;
+ unsigned rmax = 0;
+
+ if( set_min_max == 3 ){
+ stringstream s1( min_arg );
+ s1 >> rmin;
+
+ stringstream s2( max_arg );
+ s2 >> rmax;
+ if( rmax <= rmin || rmax < 2 || rmin < 1 ){
+ std::cerr << "Rtree set to 2, 3" << std::endl ;
+ rmin = 2;
+ rmax = 3;
+ }
+ }
+ else{
+ std::cerr << "Rtree set to 2, 3 ." << std::endl ;
+ rmin = 2;
+ rmax = 3;
+ }
+
+
+ char handlefile = 'T';
+ std::cout << "rmin: " << rmin << " rmax:" << rmax << std::endl;
+ init(argc, argv, new RTreeToy( rmin, rmax, handlefile) );
+
+ return 0;
+}
+
+
+
+const char* RTreeToy::menu_items[] =
+{
+ "Insert / Alter Rectangle",
+ "Search Rectangle",
+ "Delete Reactangle",
+ "Toggle"
+};
+
+const char RTreeToy::keys[] =
+{
+ 'I', 'U', 'S', 'D', 'T',
+ '0', '1', '2', '3', '4', '5', 'P'
+};
+
+
+
+
+
+
+/*
+intersection test
+ Rect r1( Point(100, 100), Point(150, 150)),
+ r2( Point(200, 200), Point(250, 250)),
+ r3( Point(50, 50), Point(100, 100));
+ OptRect a_intersection_b;
+ a_intersection_b = intersect( r1, r2 );
+ std::cout << "r1, r2 " << a_intersection_b.empty() << std::endl;
+ a_intersection_b = intersect( r1, r3 );
+ std::cout << "r1, r3 " << a_intersection_b.empty() << std::endl;
+*/
diff --git a/src/3rdparty/2geom/src/toys/sanitize.cpp b/src/3rdparty/2geom/src/toys/sanitize.cpp
new file mode 100644
index 0000000..1d9a81f
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/sanitize.cpp
@@ -0,0 +1,204 @@
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <2geom/svg-path-parser.h>
+#include <2geom/utils.h>
+#include <cstdlib>
+#include <2geom/crossing.h>
+#include <2geom/path-intersection.h>
+#include <2geom/transforms.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/pathvector.h>
+
+using namespace Geom;
+
+struct EndPoint {
+ public:
+ Point point, norm;
+ double time;
+ EndPoint() : time(0) { }
+ EndPoint(Point p, Point n, double t) : point(p), norm(n), time(t) { }
+};
+
+struct Edge {
+ public:
+ EndPoint from, to;
+ int ix;
+ bool cw;
+ Edge() { }
+ Edge(EndPoint f, EndPoint t, int i, bool c) : from(f), to(t), ix(i), cw(c) { }
+ bool operator==(Edge const &other) { return from.time == other.from.time && to.time == other.to.time; }
+};
+
+typedef std::vector<Edge> Edges;
+
+Edges edges(Path const &p, Crossings const &cr, unsigned ix) {
+ Edges ret = Edges();
+ EndPoint prev;
+ for(unsigned i = 0; i <= cr.size(); i++) {
+ double t = cr[i == cr.size() ? 0 : i].getTime(ix);
+ Point pnt = p.pointAt(t);
+ Point normal = p.pointAt(t+0.01) - pnt;
+ normal.normalize();
+ std::cout << pnt << "\n";
+ EndPoint cur(pnt, normal, t);
+ if(i == 0) { prev = cur; continue; }
+ ret.push_back(Edge(prev, cur, ix, false));
+ ret.push_back(Edge(prev, cur, ix, true));
+ prev = cur;
+ }
+ return ret;
+}
+
+template<class T>
+void append(std::vector<T> &vec, std::vector<T> const &other) {
+ vec.insert(vec.end(),other.begin(), other.end());
+}
+
+Edges edges(PathVector const &ps, CrossingSet const &crs) {
+ Edges ret = Edges();
+ for(unsigned i = 0; i < crs.size(); i++) {
+ Edges temp = edges(ps[i], crs[i], i);
+ append(ret, temp);
+ }
+ return ret;
+}
+
+PathVector edges_to_paths(Edges const &es, PathVector const &ps) {
+ PathVector ret;
+ for(const auto & e : es) {
+ ret.push_back(ps[e.ix].portion(e.from.time, e.to.time));
+ }
+ return ret;
+}
+
+void draw_cell(cairo_t *cr, Edges const &es, PathVector const &ps) {
+ cairo_set_source_rgba(cr, uniform(), uniform(), uniform(), 0.5);
+ cairo_set_line_width(cr, uniform() * 10);
+ PathVector paths = edges_to_paths(es, ps);
+ Piecewise<D2<SBasis> > pw = paths_to_pw(paths);
+ double area;
+ Point centre;
+ Geom::centroid(pw, centre, area);
+ cairo_path(cr, paths); //* (Translate(-centre) * Scale(0.2) * Translate(centre*2)));
+ cairo_stroke(cr);
+}
+
+//Only works for normal
+double ang(Point n1, Point n2) {
+ return (dot(n1, n2)+1) * (cross(n1, n2) < 0 ? -1 : 1);
+}
+
+template<class T>
+void remove(std::vector<T> &vec, T const &val) {
+ for (typename std::vector<T>::iterator it = vec.begin(); it != vec.end(); ++it) {
+ if(*it == val) {
+ vec.erase(it);
+ return;
+ }
+ }
+}
+
+std::vector<Edges> cells(cairo_t */*cr*/, PathVector const &ps) {
+ CrossingSet crs = crossings_among(ps);
+ Edges es = edges(ps, crs);
+ std::vector<Edges> ret = std::vector<Edges>();
+
+ while(!es.empty()) {
+ std::cout << "hello!\n";
+ Edge start = es.front();
+ Path p = Path();
+ Edge cur = start;
+ bool rev = false;
+ Edges cell = Edges();
+ do {
+ std::cout << rev << " " << cur.from.time << ", " << cur.to.time << "\n";
+ double a = 0;
+ Edge was = cur;
+ EndPoint curpnt = rev ? cur.from : cur.to;
+ Point norm = rev ? -curpnt.norm : curpnt.norm;
+ //Point to = curpnt.point + norm *20;
+
+ //std::cout << norm;
+ for(auto & e : es) {
+ if(e == was || e.cw != start.cw) continue;
+ if((!are_near(curpnt.time, e.from.time)) &&
+ are_near(curpnt.point, e.from.point, 0.1)) {
+ double v = ang(norm, e.from.norm);
+ //draw_line_seg(cr, curpnt.point, to);
+ //draw_line_seg(cr, to, es[i].from.point + es[i].from.norm*30);
+ //std::cout << v << "\n";
+ if(start.cw ? v < a : v > a ) {
+ a = v;
+ cur = e;
+ rev = false;
+ }
+ }
+ if((!are_near(curpnt.time, e.to.time)) &&
+ are_near(curpnt.point, e.to.point, 0.1)) {
+ double v = ang(norm, -e.to.norm);
+ if(start.cw ? v < a : v > a) {
+ a = v;
+ cur = e;
+ rev = true;
+ }
+ }
+ }
+ cell.push_back(cur);
+ remove(es, cur);
+ if(cur == was) break;
+ } while(!(cur == start));
+ if(are_near(start.to.point, rev ? cur.from.point : cur.to.point)) {
+ ret.push_back(cell);
+ }
+ }
+ return ret;
+}
+
+int cellWinding(Edges const &/*es*/, PathVector const &/*ps*/) {
+ return 0;
+}
+
+class Sanitize: public Toy {
+ PathVector paths;
+ std::vector<Edges> es;
+ PointSetHandle angh;
+ PointSetHandle pathix;
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save,
+ std::ostringstream *timer_stream) override
+ {
+ int ix = pathix.pts[0][X] / 10;
+ es = cells(cr, paths);
+ draw_cell(cr, es[ix], paths);
+
+ cairo_set_source_rgba(cr, 0, 0, 0, 1);
+ //cairo_path(cr, paths);
+ //cairo_stroke(cr);
+
+ Point ap = angh.pts[1] - angh.pts[0], bp = angh.pts[2] - angh.pts[0];
+ ap.normalize(); bp.normalize();
+ *notify << ang(ap, bp);
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ Sanitize () {}
+ void first_time(int argc, char** argv) override {
+ const char *path_name="sanitize_examples.svgd";
+ if(argc > 1)
+ path_name = argv[1];
+ paths = read_svgd(path_name);
+
+ handles.push_back(&angh); handles.push_back(&pathix);
+ angh.push_back(100, 100);
+ angh.push_back(80, 100);
+ angh.push_back(100, 80);
+ pathix.push_back(30, 200);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new Sanitize());
+ return 0;
+}
diff --git a/src/3rdparty/2geom/src/toys/sb-math-test.cpp b/src/3rdparty/2geom/src/toys/sb-math-test.cpp
new file mode 100644
index 0000000..9964e32
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/sb-math-test.cpp
@@ -0,0 +1,164 @@
+/*
+ * sb-math-test.cpp - some std functions to work with (pw)s-basis
+ *
+ * Authors:
+ * Jean-Francois Barraud
+ *
+ * Copyright (C) 2006-2007 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/sbasis-math.h>
+#include <2geom/piecewise.h>
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/bezier-to-sbasis.h>
+
+#include <2geom/path.h>
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+
+#define ZERO 1e-3
+
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+#include <stdio.h>
+#include <math.h>
+
+#include "pwsbhandle.cpp" // FIXME: This looks like it may give problems later, (including a .cpp file)
+
+//-Plot---------------------------------------------------------------
+static void plot(cairo_t* cr, double (*f)(double), Piecewise<SBasis> const &x, double vscale=1){
+ int NbPts=40;
+ for(int i=0; i<NbPts; i++){
+ double t=double(i)/NbPts;
+ t=x.cuts.front()*(1-t) + x.cuts.back()*t;
+ draw_handle(cr, Point(150+i*300./NbPts,300-(*f)(x(t))*vscale));
+ cairo_stroke(cr);
+ }
+}
+
+static void plot(cairo_t* cr, Piecewise<SBasis> const &f,double vscale=1){
+ D2<Piecewise<SBasis> > plot;
+ plot[1]=-f;
+ plot[1]*=vscale;
+ plot[1]+=300;
+
+ plot[0].cuts.push_back(f.cuts.front());
+ plot[0].cuts.push_back(f.cuts.back());
+ plot[0].segs.emplace_back(Linear(150,450));
+
+ cairo_d2_pw_sb(cr, plot);
+
+ for (unsigned i=1; i<f.size(); i++){
+ cairo_move_to(cr, Point(150+f.cuts[i]*300,300));
+ cairo_line_to(cr, Point(150+f.cuts[i]*300,300-vscale*f.segs[i].at0()));
+ }
+}
+
+double my_inv(double x){return (1./x);}
+
+#define SIZE 4
+
+class SbCalculusToy: public Toy {
+ PWSBHandle pwsbh;
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+
+ //Let the user input sbasis coefs.
+ cairo_move_to(cr, Geom::Point(0,300));
+ cairo_line_to(cr, Geom::Point(600,300));
+
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0.2, 0.2, 0.2, 1);
+ cairo_stroke(cr);
+
+ Piecewise<SBasis> f = pwsbh.value(300);
+
+ cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, .8);
+ plot(cr,f,1);
+ cairo_stroke(cr);
+
+/* cairo_set_source_rgba (cr, 0.3, 0.3, 0.3,.8);
+ plot(cr,abs(f),1);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba (cr, 0.3, 0.3, 0.3,.8);
+ plot(cr,signSb(f),75);
+ cairo_stroke(cr);*/
+
+// cairo_set_source_rgba (cr, 0.3, 0.3, 0.3,.8);
+// plot(cr,maxSb(f, -f+50),1);
+// cairo_stroke(cr);
+
+// cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1);
+// plot(cr,sqrt(abs(f),.01,3),10);
+// plot(cr,&sqrt,abs(f),10);
+// cairo_stroke(cr);
+
+// cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 1);
+// plot(cr,cos(f,.01,3),75);
+// plot(cr,&cos,f,75);
+// cairo_stroke(cr);
+
+// cairo_set_source_rgba (cr, 0.9, 0.0, 0.7, 1);
+// plot(cr,sin(f,.01,3),75);
+// plot(cr,&sin,f,75);
+// cairo_stroke(cr);
+
+ cairo_set_source_rgba (cr, 0.9, 0.0, 0.7, 1);
+ plot(cr,divide(Linear(1),f,.01,3),2);
+ plot(cr,&my_inv,f,10);
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+public:
+ SbCalculusToy() : pwsbh(4,1){
+ for(int i = 0; i < 2*SIZE; i++)
+ pwsbh.push_back(i*100,150+150+uniform()*300*0);
+ handles.push_back(&pwsbh);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new SbCalculusToy);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype = cpp:expandtab:shiftwidth = 4:tabstop = 8:softtabstop = 4:encoding = utf-8:textwidth = 99 :
diff --git a/src/3rdparty/2geom/src/toys/sb-of-interval.cpp b/src/3rdparty/2geom/src/toys/sb-of-interval.cpp
new file mode 100644
index 0000000..3044620
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/sb-of-interval.cpp
@@ -0,0 +1,187 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/bezier-to-sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <time.h>
+#include <vector>
+
+#include <2geom/orphan-code/sbasis-of.h>
+
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+#define SIZE 4
+
+static void plot(cairo_t* cr, SBasis const &B,double vscale=1,double a=0,double b=1){
+ D2<SBasis> plot;
+ plot[0]=SBasis(Linear(150+a*300,150+b*300));
+ plot[1]=B*(-vscale);
+ plot[1]+=300;
+ cairo_d2_sb(cr, plot);
+// cairo_stroke(cr);
+}
+static void plot(cairo_t* cr, SBasisOf<Interval> const &f, double vscale=1,double /*dx*/=.05, double a=0,double b=1){
+ cairo_save(cr);
+#if 0
+ double t = a;
+ while (t<=b){
+ Interval i = f.valueAt(t);
+ std::cout<<i.min()<<","<<i.max()<<"\n";
+ draw_cross(cr, Geom::Point( 150+t*300, 300-i.min()*vscale ) );
+ draw_cross(cr, Geom::Point( 150+t*300, 300-i.max()*vscale ) );
+ t+=dx;
+ }
+#endif
+ D2<SBasis> plot;
+ Path pth;
+ pth.setStitching(true);
+ SBasis fmin(f.size(), Linear());
+ SBasis fmax(f.size(), Linear());
+ for(unsigned i = 0; i < f.size(); i++) {
+ for(unsigned j = 0; j < 2; j++) {
+ fmin[i][j] = f[i][j].min();
+ fmax[i][j] = f[i][j].max();
+ }
+ }
+ plot[0]=SBasis(Linear(150+a*300,150+b*300));
+ plot[1]=fmin*(-vscale);
+ plot[1]+=300;
+ pth.append(plot);
+ plot[1]=fmax*(-vscale);
+ plot[1]+=300;
+ pth.append(reverse(plot));
+ cairo_path(cr, pth);
+
+ cairo_set_source_rgba(cr, 0, 0, 0, 0.1);
+ cairo_fill(cr);
+ cairo_restore(cr);
+}
+
+
+
+class SbOfInterval: public Toy {
+
+ unsigned size;
+ PointHandle adjuster_a[3*SIZE];
+ PointHandle adjuster_b[3*SIZE];
+
+ void drawSliders(cairo_t *cr, PointHandle adjuster[], double y_min, double y_max){
+ for (unsigned i=0; i < size; i++){
+ cairo_move_to(cr, Geom::Point(adjuster[3*i].pos[X],y_min));
+ cairo_line_to(cr, Geom::Point(adjuster[3*i].pos[X],y_max));
+ }
+ }
+ void drawIntervals(cairo_t *cr, PointHandle adjuster[], double /*x*/, double /*dx*/, double /*y_min*/, double /*y_max*/){
+ for (unsigned i=0; i < size; i++){
+ cairo_move_to(cr, adjuster[3*i+1].pos);
+ cairo_line_to(cr, adjuster[3*i+2].pos);
+ }
+ }
+ void setupSliders(PointHandle adjuster[], double x, double dx, double y_min, double y_max){
+ for (unsigned i=0; i < size; i++){
+ for (unsigned j=0; j < 3; j++){
+ adjuster[3*i+j].pos[X] = x + dx*i;
+ if (adjuster[3*i+j].pos[Y] < y_min) adjuster[3*i+j].pos[Y] = y_min;
+ if (adjuster[3*i+j].pos[Y] > y_max) adjuster[3*i+j].pos[Y] = y_max;
+ }
+ if (adjuster[3*i+1].pos[Y] < adjuster[3*i+2].pos[Y]) adjuster[3*i+1].pos[Y] = adjuster[3*i+2].pos[Y];
+ if (adjuster[3*i ].pos[Y] < adjuster[3*i+2].pos[Y]) adjuster[3*i ].pos[Y] = adjuster[3*i+2].pos[Y];
+ if (adjuster[3*i ].pos[Y] > adjuster[3*i+1].pos[Y]) adjuster[3*i ].pos[Y] = adjuster[3*i+1].pos[Y];
+ }
+ }
+
+ PointSetHandle hand;
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+
+ SBasisOf<Interval> f;
+ double min=150, max=450;
+ setupSliders(adjuster_a, 100, 15, min, max);
+ setupSliders(adjuster_b, 500, 15, min, max);
+ drawSliders(cr, adjuster_a, min, max);
+ drawSliders(cr, adjuster_b, min, max);
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0.2, 0.2, 0.2, 1);
+ cairo_stroke(cr);
+ drawIntervals(cr, adjuster_a, 100, 15, min, max);
+ drawIntervals(cr, adjuster_b, 500, 15, min, max);
+ cairo_set_line_width (cr, 3);
+ cairo_set_source_rgba (cr, 0.8, 0.2, 0.2, 1);
+ cairo_stroke(cr);
+
+ cairo_move_to(cr, Geom::Point(150,300));
+ cairo_line_to(cr, Geom::Point(450,300));
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0.2, 0.2, 0.2, 1);
+ cairo_stroke(cr);
+
+ for (unsigned i=0; i < size; i++){
+ double amin = (max+min)/2 - adjuster_a[3*i+1].pos[Y];
+ double amax = (max+min)/2 - adjuster_a[3*i+2].pos[Y];
+ Interval ai(amin*std::pow(4.,(int)i), amax*std::pow(4.,(int)i));
+ double bmin = (max+min)/2 - adjuster_b[3*i+1].pos[Y];
+ double bmax = (max+min)/2 - adjuster_b[3*i+2].pos[Y];
+ Interval bi(bmin*std::pow(4.,(int)i), bmax*std::pow(4.,(int)i));
+ f.push_back(LinearOf<Interval>(ai,bi));
+ }
+ SBasis f_dble(size, Linear());
+ for (unsigned i=0; i < size; i++){
+ double ai = (max+min)/2 - adjuster_a[3*i].pos[Y];
+ double bi = (max+min)/2 - adjuster_b[3*i].pos[Y];
+ f_dble[i] = Linear(ai*std::pow(4.,(int)i),bi*std::pow(4.,(int)i));
+ }
+
+ plot(cr,f_dble);
+ plot(cr,f);
+ cairo_set_source_rgba (cr, 0., 0., 0.8, 1);
+ cairo_stroke(cr);
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+public:
+ SbOfInterval(){
+ size=SIZE;
+ for(unsigned i=0; i < size; i++){
+ adjuster_a[3*i].pos[X] = 0;
+ adjuster_a[3*i].pos[Y] = 300;
+ adjuster_a[3*i+1].pos[X] = 0;
+ adjuster_a[3*i+1].pos[Y] = 350;
+ adjuster_a[3*i+2].pos[X] = 0;
+ adjuster_a[3*i+2].pos[Y] = 250;
+ adjuster_b[3*i].pos[X] = 0;
+ adjuster_b[3*i].pos[Y] = 300;
+ adjuster_b[3*i+1].pos[X] = 0;
+ adjuster_b[3*i+1].pos[Y] = 350;
+ adjuster_b[3*i+2].pos[X] = 0;
+ adjuster_b[3*i+2].pos[Y] = 250;
+ }
+
+ for(unsigned i = 0; i < size; i++) {
+ handles.push_back(&(adjuster_a[3*i]));
+ handles.push_back(&(adjuster_a[3*i+1]));
+ handles.push_back(&(adjuster_a[3*i+2]));
+ handles.push_back(&(adjuster_b[3*i]));
+ handles.push_back(&(adjuster_b[3*i+1]));
+ handles.push_back(&(adjuster_b[3*i+2]));
+ }
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new SbOfInterval);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype = cpp:expandtab:shiftwidth = 4:tabstop = 8:softtabstop = 4:encoding = utf-8:textwidth = 99 :
diff --git a/src/3rdparty/2geom/src/toys/sb-of-sb.cpp b/src/3rdparty/2geom/src/toys/sb-of-sb.cpp
new file mode 100644
index 0000000..d2ee2e6
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/sb-of-sb.cpp
@@ -0,0 +1,478 @@
+#include <time.h>
+#include <vector>
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/bezier-to-sbasis.h>
+
+#include <2geom/orphan-code/sbasis-of.h>
+
+using namespace Geom;
+using namespace std;
+
+SBasis toSBasis(SBasisOf<double> const &f){
+ SBasis result(f.size(), Linear());
+ for (unsigned i=0; i<f.size(); i++){
+ result[i] = Linear(f[i][0],f[i][1]);
+ }
+ return result;
+}
+SBasisOf<double> toSBasisOfDouble(SBasis const &f){
+ SBasisOf<double> result;
+ for (auto i : f){
+ result.push_back(LinearOf<double>(i[0],i[1]));
+ }
+ return result;
+}
+
+
+#if 0
+template<unsigned dim>
+class LinearDim;
+template<unsigned dim>
+class SBasisDim;
+
+template<unsigned dim>
+class LinearDim : public LinearOf<SBasisDim<dim-1> >{
+public:
+ LinearDim() : LinearOf<SBasisDim<dim-1> >() {};
+ LinearDim(SBasisDim <dim-1> const &a, SBasisDim<dim-1> const &b ) : LinearOf<SBasisDim<dim-1> >(a,b) {};
+ LinearDim(LinearDim <dim-1> const &a, LinearDim<dim-1> const &b ) :
+ LinearOf<SBasisDim<dim-1> >(SBasisDim<dim-1>(a),SBasisDim<dim-1>(b)) {};
+};
+
+template<>
+class LinearDim<1> : public LinearOf<double>{
+public:
+ LinearDim() : LinearOf<double>() {};
+ LinearDim(double const &a, double const &b ) : LinearOf<double>(a,b) {};
+};
+
+
+template<unsigned dim>
+class SBasisDim : public SBasisOf<SBasisDim<dim-1> >{
+public:
+ SBasisDim() : SBasisOf<SBasisDim<dim-1> >() {};
+ SBasisDim(LinearDim<dim> const &lin) :
+ SBasisOf<SBasisDim<dim-1> >(LinearOf<SBasisDim<dim-1> >(lin[0],lin[1])) {};
+};
+
+template<>
+class SBasisDim<1> : public SBasisOf<double>{
+/*
+public:
+ SBasisDim<1>() : SBasisOf<double>() {};
+ SBasisDim(SBasisOf<double> other) : SBasisOf<double>(other) {};
+ SBasisDim(LinearOf<double> other) : SBasisOf<double>(other) {};
+*/
+};
+
+SBasis toSBasis(SBasisDim<1> f){
+ SBasis result(f.size(), Linear());
+ for (unsigned i=0; i<f.size(); i++){
+ result[i] = Linear(f[i][0],f[i][1]);
+ }
+ return result;
+}
+
+template<unsigned dim_f,unsigned dim_g>
+SBasisDim<dim_g> compose(SBasisDim<dim_f> const &f, std::vector<SBasisDim<dim_g> > const &g ){
+
+ assert( dim_f <= g.size() );
+
+ SBasisDim<dim_g> u0 = g[dim_f-1];
+ SBasisDim<dim_g> u1 = -u0 + 1;
+ SBasisDim<dim_g> s = multiply(u0,u1);
+ SBasisDim<dim_g> r;
+
+ for(int i = f.size()-1; i >= 0; i--) {
+ if ( dim_f>1 ){
+ r = s*r + compose(f[i][0],g)*u0 + compose(f[i][1],g)*u1;
+ }else{
+ r = s*r + f[i][0]*u0 + f[i][1]*u1;
+ }
+ }
+ return r;
+}
+
+#endif
+
+template <typename T>
+SBasisOf<T> multi_compose(SBasisOf<double> const &f, SBasisOf<T> const &g ){
+
+ //assert( f.input_dim() <= g.size() );
+
+ SBasisOf<T> u0 = g;
+ SBasisOf<T> u1 = -u0 + LinearOf<SBasisOf<double> >(SBasisOf<double>(LinearOf<double>(1,1)));
+ SBasisOf<T> s = multiply(u0,u1);
+ SBasisOf<T> r;
+
+ for(int i = f.size()-1; i >= 0; i--) {
+ r = s*r + f[i][0]*u0 + f[i][1]*u1;
+ }
+ return r;
+}
+SBasisOf<double> compose(SBasisOf<SBasisOf<double> > const &f,
+ SBasisOf<double> const &x,
+ SBasisOf<double> const &y){
+ SBasisOf<double> y0 = -y + LinearOf<double>(1,1);
+ SBasisOf<double> s = multiply(y0,y);
+ SBasisOf<double> r;
+
+ for(int i = f.size()-1; i >= 0; i--) {
+ r = s*r + compose(f[i][0],x)*y0 + compose(f[i][1],x)*y;
+ }
+ return r;
+}
+
+SBasisOf<double> compose(SBasisOf<SBasisOf<double> > const &f,
+ D2<SBasisOf<double> > const &X){
+ return compose(f, X[0], X[1]);
+}
+
+SBasisOf<double> compose(SBasisOf<SBasisOf<double> > const &f,
+ D2<SBasis> const &X){
+ return compose(f, toSBasisOfDouble(X[0]), toSBasisOfDouble(X[1]));
+}
+
+/*
+static
+SBasis eval_v(SBasisOf<SBasis> const &f, double v){
+ SBasis result(f.size(), Linear());
+ for (unsigned i=0; i<f.size(); i++){
+ result[i] = Linear(f[i][0].valueAt(v),f[i][1].valueAt(v));
+ }
+ return result;
+}
+static
+SBasis eval_v(SBasisOf<SBasisOf<double> > const &f, double v){
+ SBasis result(f.size(), Linear());
+ for (unsigned i=0; i<f.size(); i++){
+ result[i] = Linear(f[i][0].valueAt(v),f[i][1].valueAt(v));
+ }
+ return result;
+}*/
+static
+SBasisOf<double> eval_dim(SBasisOf<SBasisOf<double> > const &f, double t, unsigned dim){
+ if (dim == 1) return f.valueAt(t);
+ SBasisOf<double> result;
+ for (unsigned i=0; i<f.size(); i++){
+ result.push_back(LinearOf<double>(f[i][0].valueAt(t),f[i][1].valueAt(t)));
+ }
+ return result;
+}
+
+/*
+static
+SBasis eval_v(SBasisDim<2> const &f, double v){
+ SBasis result;
+ for (unsigned i=0; i<f.size(); i++){
+ result.push_back(Linear(f[i][0].valueAt(v),f[i][1].valueAt(v)));
+ }
+ return result;
+}
+*/
+
+struct Frame
+{
+ Geom::Point O;
+ Geom::Point x;
+ Geom::Point y;
+ Geom::Point z;
+ // find the point on the x,y plane that projects to P
+ Point unproject(Point P) {
+ return P * from_basis(x, y, O).inverse();
+ }
+};
+
+void
+plot3d(cairo_t *cr, SBasis const &x, SBasis const &y, SBasis const &z, Frame frame){
+ D2<SBasis> curve;
+ for (unsigned dim=0; dim<2; dim++){
+ curve[dim] = x*frame.x[dim] + y*frame.y[dim] + z*frame.z[dim];
+ curve[dim] += frame.O[dim];
+ }
+ cairo_d2_sb(cr, curve);
+}
+void
+plot3d(cairo_t *cr, SBasis const &x, SBasis const &y, SBasisOf<double> const &z, Frame frame){
+ D2<SBasis> curve;
+ for (unsigned dim=0; dim<2; dim++){
+ curve[dim] = x*frame.x[dim] + y*frame.y[dim] + toSBasis(z)*frame.z[dim];
+ curve[dim] += frame.O[dim];
+ }
+ cairo_d2_sb(cr, curve);
+}
+
+void
+plot3d(cairo_t *cr,
+ Piecewise<SBasis> const &x,
+ Piecewise<SBasis> const &y,
+ Piecewise<SBasis> const &z, Frame frame){
+
+ Piecewise<SBasis> xx = partition(x,y.cuts);
+ Piecewise<SBasis> xxx = partition(xx,z.cuts);
+ Piecewise<SBasis> yyy = partition(y,xxx.cuts);
+ Piecewise<SBasis> zzz = partition(z,xxx.cuts);
+
+ for (unsigned i=0; i<xxx.size(); i++){
+ plot3d(cr, xxx[i], yyy[i], zzz[i], frame);
+ }
+}
+
+void
+plot3d(cairo_t *cr, SBasisOf<SBasisOf<double> > const &f, Frame frame){
+ int iMax = 5;
+ for (int i=0; i<iMax; i++){
+ plot3d(cr, Linear(0,1), Linear(i/(iMax-1.)), eval_dim(f, i/(iMax-1.), 0), frame);
+ plot3d(cr, Linear(i/(iMax-1.)), Linear(0,1), eval_dim(f, i/(iMax-1.), 1), frame);
+ }
+}
+
+SBasisOf<SBasisOf<double> > integral(SBasisOf<SBasisOf<double> > const &f, unsigned var){
+ //variable of f = 1, variable of f's coefficients = 0.
+ if (var == 1) return integral(f);
+ SBasisOf<SBasisOf<double> > result;
+ for(unsigned i = 0; i< f.size(); i++) {
+ result.push_back(LinearOf<SBasisOf<double> >( integral(f[i][0]),integral(f[i][1])));
+ }
+ return result;
+}
+
+Piecewise<SBasis> convole(SBasisOf<double> const &f, Interval dom_f,
+ SBasisOf<double> const &g, Interval dom_g){
+
+ if ( dom_f.extent() < dom_g.extent() ) return convole(g, dom_g, f, dom_f);
+
+ SBasisOf<SBasisOf<double> > u,v;
+ u.push_back(LinearOf<SBasisOf<double> >(LinearOf<double>(0,1),
+ LinearOf<double>(0,1)));
+ v.push_back(LinearOf<SBasisOf<double> >(LinearOf<double>(0,0),
+ LinearOf<double>(1,1)));
+ SBasisOf<SBasisOf<double> > v_u = v - u*(dom_f.extent()/dom_g.extent());
+ v_u += SBasisOf<SBasisOf<double> >(SBasisOf<double>(dom_f.min()/dom_g.extent()));
+ SBasisOf<SBasisOf<double> > gg = multi_compose(g,(v - u*(dom_f.extent()/dom_g.extent())));
+ SBasisOf<SBasisOf<double> > ff = SBasisOf<SBasisOf<double> >(f);
+ SBasisOf<SBasisOf<double> > hh = integral(ff*gg,0);
+
+ Piecewise<SBasis> result;
+ result.cuts.push_back(dom_f.min()+dom_g.min());
+ //Note: we know dom_f.extent() >= dom_g.extent()!!
+ double rho = dom_f.extent()/dom_g.extent();
+ SBasisOf<double> a,b,t;
+ SBasis seg;
+ a = SBasisOf<double>(LinearOf<double>(0.,0.));
+ b = SBasisOf<double>(LinearOf<double>(0.,1/rho));
+ t = SBasisOf<double>(LinearOf<double>(dom_f.min()/dom_g.extent(),dom_f.min()/dom_g.extent()+1));
+ seg = toSBasis(compose(hh,b,t)-compose(hh,a,t));
+ result.push(seg,dom_f.min() + dom_g.max());
+ if (dom_f.extent() > dom_g.extent()){
+ a = SBasisOf<double>(LinearOf<double>(0.,1-1/rho));
+ b = SBasisOf<double>(LinearOf<double>(1/rho,1.));
+ t = SBasisOf<double>(LinearOf<double>(dom_f.min()/dom_g.extent()+1, dom_f.max()/dom_g.extent() ));
+ seg = toSBasis(compose(hh,b,t)-compose(hh,a,t));
+ result.push(seg,dom_f.max() + dom_g.min());
+ }
+ a = SBasisOf<double>(LinearOf<double>(1.-1/rho,1.));
+ b = SBasisOf<double>(LinearOf<double>(1.,1.));
+ t = SBasisOf<double>(LinearOf<double>(dom_f.max()/dom_g.extent(), dom_f.max()/dom_g.extent()+1 ));
+ seg = toSBasis(compose(hh,b,t)-compose(hh,a,t));
+ result.push(seg,dom_f.max() + dom_g.max());
+ return result;
+}
+
+template <typename T>
+SBasisOf<T> subderivative(SBasisOf<T> const& f) {
+ SBasisOf<T> res;
+ for(unsigned i = 0; i < f.size(); i++) {
+ res.push_back(LinearOf<T>(derivative(f[i][0]), derivative(f[i][1])));
+ }
+ return res;
+}
+
+OptInterval bounds_fast(SBasisOf<double> const &f) {
+ return bounds_fast(toSBasis(f));
+}
+
+/**
+ * Finds a path which traces the 0 contour of f, traversing from A to B as a single cubic d2<sbasis>.
+ * The algorithm is based on matching direction and curvature at each end point.
+ */
+//TODO: handle the case when B is "behind" A for the natural orientation of the level set.
+//TODO: more generally, there might be up to 4 solutions. Choose the best one!
+D2<SBasis>
+sbofsb_cubic_solve(SBasisOf<SBasisOf<double> > const &f, Geom::Point const &A, Geom::Point const &B){
+ D2<SBasis>result;//(Linear(A[X],B[X]),Linear(A[Y],B[Y]));
+ //g_warning("check 0 = %f = %f!", f.apply(A[X],A[Y]), f.apply(B[X],B[Y]));
+
+ SBasisOf<SBasisOf<double> > f_u = derivative(f);
+ SBasisOf<SBasisOf<double> > f_v = subderivative(f);
+ SBasisOf<SBasisOf<double> > f_uu = derivative(f_u);
+ SBasisOf<SBasisOf<double> > f_uv = derivative(f_v);
+ SBasisOf<SBasisOf<double> > f_vv = subderivative(f_v);
+
+ Geom::Point dfA(f_u.valueAt(A[X]).valueAt(A[Y]),f_v.valueAt(A[X]).valueAt(A[Y]));
+ Geom::Point dfB(f_u.valueAt(B[X]).valueAt(B[Y]),f_v.valueAt(B[X]).valueAt(B[Y]));
+
+ Geom::Point V0 = rot90(dfA);
+ Geom::Point V1 = rot90(dfB);
+
+ double D2fVV0 = f_uu.valueAt(A[X]).valueAt(A[Y])*V0[X]*V0[X]+
+ 2*f_uv.valueAt(A[X]).valueAt(A[Y])*V0[X]*V0[Y]+
+ f_vv.valueAt(A[X]).valueAt(A[Y])*V0[Y]*V0[Y];
+ double D2fVV1 = f_uu.valueAt(B[X]).valueAt(B[Y])*V1[X]*V1[X]+
+ 2*f_uv.valueAt(B[X]).valueAt(B[Y])*V1[X]*V1[Y]+
+ f_vv.valueAt(B[X]).valueAt(B[Y])*V1[Y]*V1[Y];
+
+ std::vector<D2<SBasis> > candidates = cubics_fitting_curvature(A,B,V0,V1,D2fVV0,D2fVV1);
+ if (candidates.size()==0) {
+ return D2<SBasis>(SBasis(A[X],B[X]),SBasis(A[Y],B[Y]));
+ }
+ //TODO: I'm sure std algorithm could do that for me...
+ double error = -1;
+ unsigned best = 0;
+ for (unsigned i=0; i<candidates.size(); i++){
+ Interval bounds = *bounds_fast(compose(f,candidates[i]));
+ double new_error = (fabs(bounds.max())>fabs(bounds.min()) ? fabs(bounds.max()) : fabs(bounds.min()) );
+ if ( new_error < error || error < 0 ){
+ error = new_error;
+ best = i;
+ }
+ }
+ return candidates[best];
+}
+
+class SBasis0fSBasisToy: public Toy {
+ PointSetHandle hand;
+ PointSetHandle cut_hand;
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+
+ double slider_top = width/4.;
+ double slider_bot = width*3./4.;
+ double slider_margin = width/8.;
+ if(hand.pts.empty()) {
+ hand.pts.emplace_back(width*3./16., 3*width/4.);
+ hand.pts.push_back(hand.pts[0] + Geom::Point(width/2., 0));
+ hand.pts.push_back(hand.pts[0] + Geom::Point(width/8., -width/12.));
+ hand.pts.push_back(hand.pts[0] + Geom::Point(0,-width/4.));
+ hand.pts.emplace_back(slider_margin,slider_bot);
+ hand.pts.emplace_back(width-slider_margin,slider_top);
+ }
+
+ hand.pts[4][X] = slider_margin;
+ if (hand.pts[4][Y]<slider_top) hand.pts[4][Y] = slider_top;
+ if (hand.pts[4][Y]>slider_bot) hand.pts[4][Y] = slider_bot;
+ hand.pts[5][X] = width-slider_margin;
+ if (hand.pts[5][Y]<slider_top) hand.pts[5][Y] = slider_top;
+ if (hand.pts[5][Y]>slider_bot) hand.pts[5][Y] = slider_bot;
+
+ //double tA = (slider_bot-hand.pts[4][Y])/(slider_bot-slider_top);
+ //double tB = (slider_bot-hand.pts[5][Y])/(slider_bot-slider_top);
+
+ cairo_move_to(cr,Geom::Point(slider_margin,slider_bot));
+ cairo_line_to(cr,Geom::Point(slider_margin,slider_top));
+ cairo_move_to(cr,Geom::Point(width-slider_margin,slider_bot));
+ cairo_line_to(cr,Geom::Point(width-slider_margin,slider_top));
+ cairo_set_line_width(cr,.5);
+ cairo_set_source_rgba (cr, 0., 0.3, 0., 1.);
+ cairo_stroke(cr);
+
+ Frame frame;
+ frame.O = hand.pts[0];//
+ frame.x = hand.pts[1]-hand.pts[0];//
+ frame.y = hand.pts[2]-hand.pts[0];//
+ frame.z = hand.pts[3]-hand.pts[0];//
+
+ plot3d(cr,Linear(0,1),Linear(0,0),Linear(0,0),frame);
+ plot3d(cr,Linear(0,1),Linear(1,1),Linear(0,0),frame);
+ plot3d(cr,Linear(0,0),Linear(0,1),Linear(0,0),frame);
+ plot3d(cr,Linear(1,1),Linear(0,1),Linear(0,0),frame);
+ cairo_set_line_width(cr,.2);
+ cairo_set_source_rgba (cr, 0., 0., 0., 1.);
+ cairo_stroke(cr);
+
+
+
+ SBasisOf<SBasisOf<double> > f,u,v;
+ u.push_back(LinearOf<SBasisOf<double> >(LinearOf<double>(-1,-1),LinearOf<double>(1,1)));
+ v.push_back(LinearOf<SBasisOf<double> >(LinearOf<double>(-1,1),LinearOf<double>(-1,1)));
+#if 1
+ f = u*u + v*v - LinearOf<SBasisOf<double> >(LinearOf<double>(1,1),LinearOf<double>(1,1));
+ //*notify << "input dim = " << f.input_dim() <<"\n";
+ plot3d(cr,f,frame);
+ cairo_set_line_width(cr,1);
+ cairo_set_source_rgba (cr, .5, 0.5, 0.5, 1.);
+ cairo_stroke(cr);
+
+ LineSegment ls(frame.unproject(cut_hand.pts[0]),
+ frame.unproject(cut_hand.pts[1]));
+ SBasis cutting = toSBasis(compose(f, ls.toSBasis()));
+ //cairo_sb(cr, cutting);
+ //cairo_stroke(cr);
+ plot3d(cr, ls.toSBasis()[0], ls.toSBasis()[1], SBasis(0.0), frame);
+ vector<double> rts = roots(cutting);
+ if(rts.size() >= 2) {
+ Geom::Point A = ls.pointAt(rts[0]);
+ Geom::Point B = ls.pointAt(rts[1]);
+
+ //Geom::Point A(1,0.5);
+ //Geom::Point B(0.5,1);
+ D2<SBasis> zeroset = sbofsb_cubic_solve(f,A,B);
+ plot3d(cr, zeroset[X], zeroset[Y], SBasis(Linear(0.)),frame);
+ cairo_set_line_width(cr,1);
+ cairo_set_source_rgba (cr, 0.9, 0., 0., 1.);
+ cairo_stroke(cr);
+ }
+#else
+
+ SBasisOf<SBasisOf<double> > g = u - v ;
+ g += LinearOf<SBasisOf<double> >(SBasisOf<double>(LinearOf<double>(.5,.5)));
+ SBasisOf<double> h;
+ h.push_back(LinearOf<double>(0,0));
+ h.push_back(LinearOf<double>(0,0));
+ h.push_back(LinearOf<double>(1,1));
+
+ f = multi_compose(h,g);
+ plot3d(cr,f,frame);
+ cairo_set_line_width(cr,1);
+ cairo_set_source_rgba (cr, .75, 0.25, 0.25, 1.);
+ cairo_stroke(cr);
+/*
+ SBasisDim<1> g = SBasisOf<double>(LinearOf<double>(0,1));
+ g.push_back(LinearOf<double>(-1,-1));
+ std::vector<SBasisDim<2> > vars;
+ vars.push_back(ff);
+ plot3d(cr,compose(g,vars),frame);
+ cairo_set_source_rgba (cr, .5, 0.9, 0.5, 1.);
+ cairo_stroke(cr);
+*/
+#endif
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+public:
+ SBasis0fSBasisToy(){
+ handles.push_back(&hand);
+ handles.push_back(&cut_hand);
+ cut_hand.push_back(100,100);
+ cut_hand.push_back(500,500);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new SBasis0fSBasisToy);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype = cpp:expandtab:shiftwidth = 4:tabstop = 8:softtabstop = 4:encoding = utf-8:textwidth = 99 :
diff --git a/src/3rdparty/2geom/src/toys/sb-to-bez.cpp b/src/3rdparty/2geom/src/toys/sb-to-bez.cpp
new file mode 100644
index 0000000..337180f
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/sb-to-bez.cpp
@@ -0,0 +1,404 @@
+/*
+ * sb-to-bez Toy - Tests conversions from sbasis to cubic bezier.
+ *
+ * Copyright 2007 jf barraud.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+// mainly experimental atm...
+// do not expect to find anything understandable here atm.
+
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/basic-intersection.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#define ZERO 1e-7
+
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+#include <stdio.h>
+#include <gsl/gsl_poly.h>
+
+void cairo_pw(cairo_t *cr, Piecewise<SBasis> p, double hscale=1., double vscale=1.) {
+ for(unsigned i = 0; i < p.size(); i++) {
+ D2<SBasis> B;
+ B[0] = Linear(150+p.cuts[i]*hscale, 150+p.cuts[i+1]*hscale);
+ B[1] = Linear(450) - p[i]*vscale;
+ cairo_d2_sb(cr, B);
+ }
+}
+
+//===================================================================================
+
+D2<SBasis>
+naive_sb_seg_to_bez(Piecewise<D2<SBasis> > const &M,double t0,double t1){
+
+ Piecewise<D2<SBasis> > dM = derivative(M);
+ Point M0 = M(t0);
+ Point dM0 = dM(t0)*(t1-t0);
+ Point M1 = M(t1);
+ Point dM1 = dM(t1)*(t1-t0);
+ D2<SBasis> result;
+ for (unsigned dim=0; dim<2; dim++){
+ SBasis r(2, Linear());
+ r[0] = Linear(M0[dim],M1[dim]);
+ r[1] = Linear(M0[dim]-M1[dim]+dM0[dim],-(M0[dim]-M1[dim]+dM1[dim]));
+ result[dim] = r;
+ }
+ return result;
+}
+
+D2<SBasis>
+sb_seg_to_bez(Piecewise<D2<SBasis> > const &M,double t0,double t1){
+ Point M0,dM0,d2M0,M1,dM1,d2M1,A0,V0,A1,V1;
+ Piecewise<D2<SBasis> > dM,d2M;
+ dM=derivative(M);
+ d2M=derivative(dM);
+ M0 =M(t0);
+ M1 =M(t1);
+ dM0 =dM(t0);
+ dM1 =dM(t1);
+ d2M0=d2M(t0);
+ d2M1=d2M(t1);
+ A0=M(t0);
+ A1=M(t1);
+
+ std::vector<D2<SBasis> > candidates = cubics_fitting_curvature(M0,M1,dM0,dM1,d2M0,d2M1);
+ if (candidates.empty()){
+ return D2<SBasis>(SBasis(M0[X],M1[X]),SBasis(M0[Y],M1[Y])) ;
+ }
+ double maxlength = -1;
+ unsigned best = 0;
+ for (unsigned i=0; i<candidates.size(); i++){
+ double l = length(candidates[i]);
+ if ( l < maxlength || maxlength < 0 ){
+ maxlength = l;
+ best = i;
+ }
+ }
+ return candidates[best];
+}
+#include <2geom/sbasis-to-bezier.h>
+
+int goal_function_type = 0;
+
+double goal_function(Piecewise<D2<SBasis> >const &A,
+ Piecewise<D2<SBasis> >const&B) {
+ if(goal_function_type) {
+ OptInterval bnds = bounds_fast(dot(derivative(A), rot90(derivative(B))));
+ //double h_dist = bnds.dimensions().length();
+//0 is in the rect!, TODO:gain factor ~2 for free.
+// njh: not really, the benefit is actually rather small.
+ double h_dist = 0;
+ if(bnds)
+ h_dist = bnds->extent();
+ return h_dist ;
+ } else {
+ Rect bnds = *bounds_fast(A - B);
+ return max(bnds.min().length(), bnds.max().length());
+ }
+}
+
+int recursive_curvature_fitter(cairo_t* cr, Piecewise<D2<SBasis> > const &f, double t0, double t1, double precision) {
+ if (t0>=t1) return 0;//TODO: fix me...
+ if (t0+0.001>=t1) return 0;//TODO: fix me...
+
+ //TODO: don't re-compute derivative(f) at each try!!
+ D2<SBasis> k_bez = sb_seg_to_bez(f,t0,t1);
+
+ if(k_bez[0].size() > 1 and k_bez[1].size() > 1) {
+ Piecewise<SBasis> s = arcLengthSb(k_bez);
+ s *= (t1-t0)/arcLengthSb(k_bez).segs.back().at1();
+ s += t0;
+ double h_dist = goal_function(compose(f,s), Piecewise<D2<SBasis> >(k_bez));
+ if(h_dist < precision) {
+ cairo_save(cr);
+ cairo_set_line_width (cr, 0.93);
+ cairo_set_source_rgba (cr, 0.7, 0.0, 0.0, 1);
+ draw_handle(cr, k_bez.at0());
+ cairo_d2_sb(cr, k_bez);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ return 1;
+ }
+ }
+ //TODO: find a better place where to cut (at the worst fit?).
+ return recursive_curvature_fitter(cr, f, t0, (t0+t1)/2, precision) +
+ recursive_curvature_fitter(cr, f, (t0+t1)/2, t1, precision);
+}
+
+double single_curvature_fitter(Piecewise<D2<SBasis> > const &f, double t0, double t1) {
+ if (t0>=t1) return 0;//TODO: fix me...
+ if (t0+0.001>=t1) return 0;//TODO: fix me...
+
+ D2<SBasis> k_bez = sb_seg_to_bez(f,t0,t1);
+
+ if(k_bez[0].size() > 1 and k_bez[1].size() > 1) {
+ Piecewise<SBasis> s = arcLengthSb(k_bez);
+ s *= (t1-t0)/arcLengthSb(k_bez).segs.back().at1();
+ s += t0;
+ return goal_function(compose(f,s), Piecewise<D2<SBasis> >(k_bez));
+ }
+ return 1e100;
+}
+
+struct quadratic_params
+{
+ Piecewise<D2<SBasis> > const *f;
+ double t0, precision;
+};
+
+
+double quadratic (double x, void *params) {
+ struct quadratic_params *p
+ = (struct quadratic_params *) params;
+
+ return single_curvature_fitter(*p->f, p->t0, x) - p->precision;
+}
+
+#include <stdio.h>
+#include <gsl/gsl_errno.h>
+#include <gsl/gsl_math.h>
+#include <gsl/gsl_roots.h>
+
+
+int sequential_curvature_fitter(cairo_t* cr, Piecewise<D2<SBasis> > const &f, double t0, double t1, double precision) {
+ if(t0 >= t1) return 0;
+
+ double r = t1;
+ if(single_curvature_fitter(f, t0, t1) > precision) {
+ int status;
+ int iter = 0, max_iter = 100;
+ const gsl_root_fsolver_type *T;
+ gsl_root_fsolver *s;
+ gsl_function F;
+ struct quadratic_params params = {&f, t0, precision};
+
+ F.function = &quadratic;
+ F.params = &params;
+
+ T = gsl_root_fsolver_brent;
+ s = gsl_root_fsolver_alloc (T);
+ gsl_root_fsolver_set (s, &F, t0, t1);
+
+ do
+ {
+ iter++;
+ status = gsl_root_fsolver_iterate (s);
+ r = gsl_root_fsolver_root (s);
+ double x_lo = gsl_root_fsolver_x_lower (s);
+ double x_hi = gsl_root_fsolver_x_upper (s);
+ status = gsl_root_test_interval (x_lo, x_hi,
+ 0, 0.001);
+
+
+ }
+ while (status == GSL_CONTINUE && iter < max_iter);
+
+ double x_lo = gsl_root_fsolver_x_lower (s);
+ double x_hi = gsl_root_fsolver_x_upper (s);
+ printf ("%5d [%.7f, %.7f] %.7f %.7f\n",
+ iter, x_lo, x_hi,
+ r,
+ x_hi - x_lo);
+ gsl_root_fsolver_free (s);
+ }
+ D2<SBasis> k_bez = sb_seg_to_bez(f,t0,r);
+
+ cairo_save(cr);
+ cairo_set_line_width (cr, 0.93);
+ cairo_set_source_rgba (cr, 0.7, 0.0, 0.0, 1);
+ draw_handle(cr, k_bez.at0());
+ cairo_d2_sb(cr, k_bez);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+
+ if(r < t1)
+ return sequential_curvature_fitter(cr, f, r, t1, precision) + 1;
+ return 1;
+}
+
+
+class SbToBezierTester: public Toy {
+ //std::vector<Slider> sliders;
+ std::vector<PointSetHandle*> path_psh;
+ PointHandle adjuster, adjuster2;
+ std::vector<Toggle> toggles;
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_save(cr);
+ for(unsigned i = 1; i < path_psh.size(); i++)
+ path_psh[i-1]->pts.back() = path_psh[i]->pts[0];
+ Piecewise<D2<SBasis> > f_as_pw(path_psh[0]->asBezier());
+ for(unsigned i = 1; i < path_psh.size(); i++) {
+ f_as_pw.push_seg(path_psh[i]->asBezier());
+ }
+ //f=handles_to_sbasis(handles.begin(), SIZE-1);
+ adjuster.pos[1]=450;
+ adjuster.pos[0]=std::max(adjuster.pos[0],150.);
+ adjuster.pos[0]=std::min(adjuster.pos[0],450.);
+ double t0=0;//(adjuster.pos[0]-150)/300;
+ double t1=(adjuster.pos[0]-150)/300;
+ //if (t0>t1) {double temp=t0;t0=t1;t1=temp;}
+
+ cairo_set_source_rgba (cr, 0., 0., 0., 1);
+ cairo_set_line_width (cr, 0.5);
+ cairo_pw_d2_sb(cr, f_as_pw);
+ cairo_stroke(cr);
+ if (t0==t1) return;//TODO: fix me...
+#if 0
+ if(0) {
+ Piecewise<D2<SBasis> > g = f_as_pw;
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0., 0., 0.9, .7);
+ double error=0;
+
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0.9, 0., 0., .7);
+ D2<SBasis> naive_bez = naive_sb_seg_to_bez(g,0,t1);
+ cairo_d2_sb(cr, naive_bez);
+ cairo_stroke(cr);
+
+ adjuster2.pos[0]=150;
+ adjuster2.pos[1]=std::min(std::max(adjuster2.pos[1],150.),450.);
+
+ double scale0=(450-adjuster2.pos[1])/150;
+
+ cairo_set_line_width (cr, 1);
+ cairo_set_source_rgba (cr, 0.7, 0., 0.7, .7);
+ D2<SBasis> k_bez = sb_seg_to_bez(g,t0,t1);
+ cairo_d2_sb(cr, k_bez);
+ cairo_stroke(cr);
+ double h_a_t = 0, h_b_t = 0;
+
+ double h_dist = hausdorfl( k_bez, f, 1e-6, &h_a_t, &h_b_t);
+ {
+ Point At = k_bez(h_a_t);
+ Point Bu = f(h_b_t);
+ cairo_move_to(cr, At);
+ cairo_line_to(cr, Bu);
+ draw_handle(cr, At);
+ draw_handle(cr, Bu);
+ cairo_save(cr);
+ cairo_set_line_width (cr, 0.3);
+ cairo_set_source_rgba (cr, 0.7, 0.0, 0.0, 1);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ }
+ *notify << "Move handle 6 to set the segment to be approximated by cubic bezier.\n";
+ *notify << " -red: bezier approx derived from parametrization.\n";
+ *notify << " -blue: bezier approx derived from curvature.\n";
+ *notify << " max distance (to original): "<<h_dist<<"\n";
+ }
+#endif
+
+
+ f_as_pw = arc_length_parametrization(f_as_pw);
+ adjuster2.pos[0]=150;
+ adjuster2.pos[1]=std::min(std::max(adjuster2.pos[1],150.),450.);
+ cairo_move_to(cr, 150, 150);
+ cairo_line_to(cr, 150, 450);
+ cairo_stroke(cr);
+ ostringstream val_s;
+ double scale0=(450-adjuster2.pos[1])/300;
+ double curve_precision = pow(10, scale0*5-2);
+ val_s << curve_precision;
+ draw_text(cr, adjuster2.pos, val_s.str().c_str());
+
+ int segs = 0;
+ goal_function_type = toggles[1].on;
+ if(toggles[0].on)
+ segs = sequential_curvature_fitter(cr, f_as_pw, 0, f_as_pw.cuts.back(), curve_precision);
+ else {
+ segs = recursive_curvature_fitter(cr, f_as_pw, 0, f_as_pw.cuts.back(),curve_precision);
+ }
+ Geom::PathVector vpt = path_from_piecewise(f_as_pw, curve_precision, true);
+ unsigned default_number_curves = 0;
+ for(const auto & i : vpt) {
+ default_number_curves += i.size();
+ }
+
+ *notify << " segments from default algorithm: "<< default_number_curves <<"\n";
+ *notify << " total segments: "<< segs <<"\n";
+ cairo_restore(cr);
+ Point p(25, height - 100), d(50,25);
+ toggles[0].bounds = Rect(p, p + d);
+ p+= Point(75, 0);
+ toggles[1].bounds = Rect(p, p + d);
+ draw_toggles(cr, toggles);
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+public:
+ void key_hit(GdkEventKey *e) override {
+ if(e->keyval == 's') toggles[0].toggle();
+ redraw();
+ }
+ void mouse_pressed(GdkEventButton* e) override {
+ toggle_events(toggles, e);
+ Toy::mouse_pressed(e);
+ }
+ SbToBezierTester() {
+ //if(handles.empty()) {
+ for(int j = 0; j < 3; j++) {
+ path_psh.push_back(new PointSetHandle());
+ for(unsigned i = 0; i < 6; i++)
+ path_psh.back()->push_back(150+300*uniform(),150+300*uniform());
+ handles.push_back(path_psh.back());
+ }
+ adjuster.pos = Geom::Point(150+300*uniform(),150+300*uniform());
+ handles.push_back(&adjuster);
+ adjuster2.pos = Geom::Point(150,300);
+ handles.push_back(&adjuster2);
+ toggles.emplace_back("Seq", true);
+ toggles.emplace_back("Linfty", true);
+ //}
+ //sliders.push_back(Slider(0.0, 1.0, 0.0, 0.0, "t"));
+ //handles.push_back(&(sliders[0]));
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new SbToBezierTester);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype = cpp:expandtab:shiftwidth = 4:tabstop = 8:softtabstop = 4:encoding = utf-8:textwidth = 99 :
diff --git a/src/3rdparty/2geom/src/toys/sb-zeros.cpp b/src/3rdparty/2geom/src/toys/sb-zeros.cpp
new file mode 100644
index 0000000..ebe3aea
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/sb-zeros.cpp
@@ -0,0 +1,63 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+using namespace Geom;
+
+#define SIZE 4
+
+class SBZeros: public Toy {
+ PointSetHandle pB1, pB2;
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ D2<SBasis> B1 = pB1.asBezier();
+ D2<SBasis> B2 = pB2.asBezier();
+ Piecewise<D2<SBasis> >B;
+ B.concat(Piecewise<D2<SBasis> >(B1));
+ B.concat(Piecewise<D2<SBasis> >(B2));
+ std::vector<Point> e;
+ std::vector<Piecewise<D2<SBasis> > > s;
+ s.push_back(derivative(B));
+ for(int j = 0; j < 5; j++) s.push_back(derivative(s.back()));
+ for(int j = 0; j <= 5; j++) {
+ for(unsigned d = 0; d < 2; d++) {
+ std::vector<double> r = roots(make_cuts_independent(s[j])[d]);
+ for(double k : r) e.push_back(B.valueAt(k));
+ }
+ }
+ for(auto & i : e) draw_cross(cr, i);
+
+ cairo_set_line_width (cr, .5);
+ cairo_set_source_rgba (cr, 0., 0.5, 0., 1);
+ cairo_pw_d2_sb(cr, B);
+ cairo_stroke(cr);
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ SBZeros () {
+ for(unsigned i = 0; i < SIZE; i++)
+ pB1.push_back(150+uniform()*300,150+uniform()*300);
+ for(unsigned i = 0; i < SIZE; i++)
+ pB2.push_back(150+uniform()*300,150+uniform()*300);
+ handles.push_back(&pB1);
+ handles.push_back(&pB2);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new SBZeros());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/sb1d.cpp b/src/3rdparty/2geom/src/toys/sb1d.cpp
new file mode 100644
index 0000000..dabbebb
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/sb1d.cpp
@@ -0,0 +1,125 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/choose.h>
+#include <2geom/convex-hull.h>
+
+#include <2geom/path.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <vector>
+using std::vector;
+using namespace Geom;
+
+extern unsigned total_steps, total_subs;
+
+double& handle_to_sb(unsigned i, unsigned n, SBasis &sb) {
+ assert(i < n);
+ assert(n <= sb.size()*2);
+ unsigned k = i;
+ if(k >= n/2) {
+ k = n - k - 1;
+ return sb[k][1];
+ } else
+ return sb[k][0];
+}
+
+double handle_to_sb_t(unsigned i, unsigned n) {
+ double k = i;
+ if(i >= n/2)
+ k = n - k - 1;
+ double t = k/(2*k+1);
+ if(i >= n/2)
+ return 1 - t;
+ else
+ return t;
+}
+
+class Sb1d: public Toy {
+public:
+ PointSetHandle hand;
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_source_rgba (cr, 0., 0.5, 0, 1);
+ cairo_set_line_width (cr, 1);
+
+ if(!save) {
+ for(unsigned i = 0; i < hand.pts.size(); i++) {
+ hand.pts[i][0] = width*handle_to_sb_t(i, hand.pts.size())/2 + width/4;
+ if(i)
+ cairo_line_to(cr, hand.pts[i]);
+ else
+ cairo_move_to(cr, hand.pts[i]);
+ }
+ }
+
+ D2<SBasis> B;
+ B[0] = Linear(width/4, 3*width/4);
+ B[1].resize(hand.pts.size()/2);
+ for(auto & i : B) {
+ i = Linear(0);
+ }
+ for(unsigned i = 0; i < hand.pts.size(); i++) {
+ handle_to_sb(i, hand.pts.size(), B[1]) = 3*width/4 - hand.pts[i][1];
+ }
+ for(unsigned i = 1; i < B[1].size(); i++) {
+ B[1][i] = B[1][i]*choose<double>(2*i+1, i);
+ }
+
+ Interval bs = *bounds_fast(B[1]);
+ double lo, hi;
+ lo = 3*width/4 - bs.min();
+ hi = 3*width/4 - bs.max();
+ cairo_move_to(cr, B[0](0), lo);
+ cairo_line_to(cr, B[0](1), lo);
+ cairo_move_to(cr, B[0](0), hi);
+ cairo_line_to(cr, B[0](1), hi);
+ cairo_stroke(cr);
+ *notify << "sb bounds = "<<lo << ", " <<hi<<std::endl;
+ //B[1] = SBasis(Linear(3*width/4)) - B[1];
+ *notify << B[0] << ", ";
+ *notify << B[1];
+ Geom::Path pb;
+ B[1] = SBasis(Linear(3*width/4)) - B[1];
+ pb.append(B);
+ pb.close(false);
+ cairo_path(cr, pb);
+
+ cairo_set_source_rgba (cr, 0., 0.125, 0, 1);
+ cairo_stroke(cr);
+
+ Geom::ConvexHull ch(hand.pts);
+
+ cairo_move_to(cr, ch.back());
+ for(auto i : ch) {
+ cairo_line_to(cr, i);
+ }
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+public:
+Sb1d () {
+ hand.pts.emplace_back(0,450);
+ for(unsigned i = 0; i < 4; i++)
+ hand.pts.emplace_back(uniform()*400, uniform()*400);
+ hand.pts.emplace_back(0,450);
+ handles.push_back(&hand);
+}
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new Sb1d());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/sb2d-solver.cpp b/src/3rdparty/2geom/src/toys/sb2d-solver.cpp
new file mode 100644
index 0000000..a60f8cd
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/sb2d-solver.cpp
@@ -0,0 +1,282 @@
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/sbasis-math.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/bezier-to-sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <gsl/gsl_poly.h>
+
+using std::vector;
+using namespace Geom;
+
+//see a sb2d as an sb of u with coef in sbasis of v.
+void
+u_coef(SBasis2d f, unsigned deg, SBasis &a, SBasis &b) {
+ a = SBasis(f.vs, Linear());
+ b = SBasis(f.vs, Linear());
+ for (unsigned v=0; v<f.vs; v++){
+ a[v] = Linear(f.index(deg,v)[0], f.index(deg,v)[2]);
+ b[v] = Linear(f.index(deg,v)[1], f.index(deg,v)[3]);
+ }
+}
+void
+v_coef(SBasis2d f, unsigned deg, SBasis &a, SBasis &b) {
+ a = SBasis(f.us, Linear());
+ b = SBasis(f.us, Linear());
+ for (unsigned u=0; u<f.us; u++){
+ a[u] = Linear(f.index(deg,u)[0], f.index(deg,u)[1]);
+ b[u] = Linear(f.index(deg,u)[2], f.index(deg,u)[3]);
+ }
+}
+
+
+
+//TODO: implement sb2d algebra!!
+SBasis2d y_x2(){
+ SBasis2d result(Linear2d(0,-1,1,0));
+ result.push_back(Linear2d(1,1,1,1));
+ result.us = 2;
+ result.vs = 1;
+ return result;
+}
+
+SBasis2d x2_plus_y2_1(){
+/*TODO: implement sb2d algebra!!
+ SBasis2d one(Linear2d(1,1,1,1));
+ SBasis2d u(Linear2d(0,1,0,1));
+ SBasis2d v(Linear2d(0,0,1,1));
+ return(u*u+v*v-one);
+*/
+ SBasis2d result(Linear2d(-1,0,0,1));//x+y-1
+ result.push_back(Linear2d(-1,-1,-1,-1));
+ result.push_back(Linear2d(-1,-1,-1,-1));
+ result.push_back(Linear2d(0,0,0,0));
+ result.us = 2;
+ result.vs = 2;
+ return result;
+}
+
+SBasis2d conic_sb2d(vector<double> /*coeff*/) {
+/*TODO: implement sb2d algebra!!
+ SBasis2d one(Linear2d(1,1,1,1));
+ SBasis2d u(Linear2d(0,1,0,1));
+ SBasis2d v(Linear2d(0,0,1,1));
+ return(u*u+v*v-one);
+*/
+ SBasis2d result(Linear2d(-1,0,0,1));//x+y-1
+ result.push_back(Linear2d(-1,-1,-1,-1));
+ result.push_back(Linear2d(-1,-1,-1,-1));
+ result.push_back(Linear2d(0,0,0,0));
+ result.us = 2;
+ result.vs = 2;
+ return result;
+}
+
+struct Frame
+{
+ Geom::Point O;
+ Geom::Point x;
+ Geom::Point y;
+ Geom::Point z;
+};
+
+void
+plot3d(cairo_t *cr, SBasis const &x, SBasis const &y, SBasis const &z, Frame frame){
+ D2<SBasis> curve;
+ for (unsigned dim=0; dim<2; dim++){
+ curve[dim] = x*frame.x[dim] + y*frame.y[dim] + z*frame.z[dim];
+ curve[dim] += frame.O[dim];
+ }
+ cairo_d2_sb(cr, curve);
+}
+
+void
+plot3d(cairo_t *cr,
+ Piecewise<SBasis> const &x,
+ Piecewise<SBasis> const &y,
+ Piecewise<SBasis> const &z, Frame frame){
+
+ Piecewise<SBasis> xx = partition(x,y.cuts);
+ Piecewise<SBasis> xxx = partition(xx,z.cuts);
+ Piecewise<SBasis> yyy = partition(y,xxx.cuts);
+ Piecewise<SBasis> zzz = partition(z,xxx.cuts);
+
+ for (unsigned i=0; i<xxx.size(); i++){
+ plot3d(cr, xxx[i], yyy[i], zzz[i], frame);
+ }
+}
+
+void
+plot3d(cairo_t *cr, SBasis2d const &f, Frame frame, int NbRays=5){
+ for (int i=0; i<=NbRays; i++){
+ D2<SBasis> seg(SBasis(0.,1.), SBasis(i*1./NbRays,i*1./NbRays));
+ SBasis f_on_seg = compose(f,seg);
+ plot3d(cr,seg[X],seg[Y],f_on_seg,frame);
+ }
+ for (int i=0; i<NbRays; i++){
+ D2<SBasis> seg(SBasis(i*1./NbRays, i*1./NbRays), SBasis(0.,1.));
+ SBasis f_on_seg = compose(f,seg);
+ plot3d(cr,seg[X],seg[Y],f_on_seg,frame);
+ }
+}
+
+void
+plot3d_top(cairo_t *cr, SBasis2d const &f, Frame frame, int NbRays=5){
+ for (int i=0; i<=NbRays; i++){
+ for(int j=0; j<2; j++){
+ D2<SBasis> seg;
+ if (j==0){
+ seg = D2<SBasis>(SBasis(0.,1.), SBasis(i*1./NbRays,i*1./NbRays));
+ }else{
+ seg = D2<SBasis>(SBasis(i*1./NbRays,i*1./NbRays), SBasis(0.,1.));
+ }
+ SBasis f_on_seg = compose(f,seg);
+ std::vector<double> rts = roots(f_on_seg);
+ if (rts.empty()||rts.back()<1) rts.push_back(1.);
+ double t1,t0 = 0;
+ for (unsigned i=(rts.front()<=0?1:0); i<rts.size(); i++){
+ t1 = rts[i];
+ if (f_on_seg((t0+t1)/2)>0)
+ plot3d(cr,seg[X](Linear(t0,t1)),seg[Y](Linear(t0,t1)),f_on_seg(Linear(t0,t1)),frame);
+ t0=t1;
+ }
+ //plot3d(cr,seg[X],seg[Y],f_on_seg,frame);
+ }
+ }
+}
+
+class Sb2dSolverToy: public Toy {
+public:
+ PointSetHandle hand;
+ Sb2dSolverToy() {
+ handles.push_back(&hand);
+ }
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+
+ double slider_top = width/4.;
+ double slider_bot = width*3./4.;
+ double slider_margin = width/8.;
+ if(hand.pts.empty()) {
+ hand.pts.emplace_back(width*3./16., 3*width/4.);
+ hand.pts.push_back(hand.pts[0] + Geom::Point(width/2., 0));
+ hand.pts.push_back(hand.pts[0] + Geom::Point(width/8., -width/12.));
+ hand.pts.push_back(hand.pts[0] + Geom::Point(0,-width/4.));
+ hand.pts.emplace_back(slider_margin,slider_bot);
+ hand.pts.emplace_back(width-slider_margin,slider_top);
+ }
+
+ hand.pts[4][X] = slider_margin;
+ if (hand.pts[4][Y]<slider_top) hand.pts[4][Y] = slider_top;
+ if (hand.pts[4][Y]>slider_bot) hand.pts[4][Y] = slider_bot;
+ hand.pts[5][X] = width-slider_margin;
+ if (hand.pts[5][Y]<slider_top) hand.pts[5][Y] = slider_top;
+ if (hand.pts[5][Y]>slider_bot) hand.pts[5][Y] = slider_bot;
+
+ double tA = (slider_bot-hand.pts[4][Y])/(slider_bot-slider_top);
+ double tB = (slider_bot-hand.pts[5][Y])/(slider_bot-slider_top);
+
+ cairo_move_to(cr,Geom::Point(slider_margin,slider_bot));
+ cairo_line_to(cr,Geom::Point(slider_margin,slider_top));
+ cairo_move_to(cr,Geom::Point(width-slider_margin,slider_bot));
+ cairo_line_to(cr,Geom::Point(width-slider_margin,slider_top));
+ cairo_set_line_width(cr,.5);
+ cairo_set_source_rgba (cr, 0., 0.3, 0., 1.);
+ cairo_stroke(cr);
+
+ Frame frame;
+ frame.O = hand.pts[0];//
+ frame.x = hand.pts[1]-hand.pts[0];//
+ frame.y = hand.pts[2]-hand.pts[0];//
+ frame.z = hand.pts[3]-hand.pts[0];//
+
+#if 0
+ SBasis2d f = y_x2();
+ D2<SBasis> true_solution(Linear(0,1),Linear(0,1));
+ true_solution[Y].push_back(Linear(-1,-1));
+ SBasis zero = SBasis(Linear(0.));
+ Geom::Point A = true_solution(tA);
+ Geom::Point B = true_solution(tB);
+
+#elif 0
+ SBasis2d f = x2_plus_y2_1();
+ D2<Piecewise<SBasis> > true_solution;
+ true_solution[X] = cos(SBasis(Linear(0,3.14/2)));
+ true_solution[Y] = sin(SBasis(Linear(0,3.14/2)));
+ Piecewise<SBasis> zero = Piecewise<SBasis>(SBasis(Linear(0.)));
+ Geom::Point A = true_solution(tA);
+ Geom::Point B = true_solution(tB);
+#else
+ SBasis2d f = conic_sb2d(vector<double>());
+ D2<Piecewise<SBasis> > true_solution;
+ true_solution[X] = cos(SBasis(Linear(0,3.14/2)));
+ true_solution[Y] = sin(SBasis(Linear(0,3.14/2)));
+ Piecewise<SBasis> zero = Piecewise<SBasis>(SBasis(Linear(0.)));
+ Geom::Point A = true_solution(tA);
+ Geom::Point B = true_solution(tB);
+#endif
+
+ plot3d(cr,Linear(0,1),Linear(0,0),Linear(0,0),frame);
+ plot3d(cr,Linear(0,1),Linear(1,1),Linear(0,0),frame);
+ plot3d(cr,Linear(0,0),Linear(0,1),Linear(0,0),frame);
+ plot3d(cr,Linear(1,1),Linear(0,1),Linear(0,0),frame);
+ cairo_set_line_width(cr,.2);
+ cairo_set_source_rgba (cr, 0., 0., 0., 1.);
+ cairo_stroke(cr);
+
+ plot3d_top(cr,f,frame);
+ cairo_set_line_width(cr,1);
+ cairo_set_source_rgba (cr, .5, 0.5, 0.5, 1.);
+ cairo_stroke(cr);
+ plot3d(cr,f,frame);
+ cairo_set_line_width(cr,.2);
+ cairo_set_source_rgba (cr, .5, 0.5, 0.5, 1.);
+ cairo_stroke(cr);
+
+ plot3d(cr, true_solution[X], true_solution[Y], zero, frame);
+ cairo_set_line_width(cr,.5);
+ cairo_set_source_rgba (cr, 0., 0., 0., 1.);
+ cairo_stroke(cr);
+ double error;
+ for(int degree = 1; degree < 4; degree++) {
+ //D2<SBasis> zeroset = sb2dsolve(f,A,B,degree);
+ D2<SBasis> zeroset = sb2d_cubic_solve(f,A,B);
+ plot3d(cr, zeroset[X], zeroset[Y], SBasis(Linear(0.)),frame);
+ cairo_set_line_width(cr,1);
+ cairo_set_source_rgba (cr, 0.9, 0., 0., 1.);
+ cairo_stroke(cr);
+
+ SBasis comp = compose(f,zeroset);
+ plot3d(cr, zeroset[X], zeroset[Y], comp, frame);
+ cairo_set_source_rgba (cr, 0.7, 0., 0.7, 1.);
+ cairo_stroke(cr);
+ //Fix Me: bounds_exact does not work here?!?!
+ Interval bounds = *bounds_fast(comp);
+ error = (bounds.max()>-bounds.min() ? bounds.max() : -bounds.min() );
+ }
+ *notify << "Gray: f-graph and true solution,\n";
+ *notify << "Red: solver solution,\n";
+ *notify << "Purple: value of f over solver solution.\n";
+ *notify << " error: "<< error <<".\n";
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new Sb2dSolverToy());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/sb2d.cpp b/src/3rdparty/2geom/src/toys/sb2d.cpp
new file mode 100644
index 0000000..b449d01
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/sb2d.cpp
@@ -0,0 +1,83 @@
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/bezier-to-sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+using std::vector;
+using namespace Geom;
+
+unsigned total_pieces_sub;
+unsigned total_pieces_inc;
+
+class Sb2d: public Toy {
+public:
+ PointSetHandle hand;
+ Sb2d() {
+ handles.push_back(&hand);
+ }
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ SBasis2d sb2;
+ sb2.us = 2;
+ sb2.vs = 2;
+ const int depth = sb2.us*sb2.vs;
+ const int surface_handles = 4*depth;
+ sb2.resize(depth, Linear2d(0));
+ vector<Geom::Point> display_handles(surface_handles);
+ Geom::Point dir(1,-2);
+ if(hand.pts.empty()) {
+ for(unsigned vi = 0; vi < sb2.vs; vi++)
+ for(unsigned ui = 0; ui < sb2.us; ui++)
+ for(unsigned iv = 0; iv < 2; iv++)
+ for(unsigned iu = 0; iu < 2; iu++)
+ hand.pts.emplace_back((2*(iu+ui)/(2.*ui+1)+1)*width/4.,
+ (2*(iv+vi)/(2.*vi+1)+1)*width/4.);
+
+ hand.pts.push_back(Geom::Point(3*width/4., width/4.) + 30*dir);
+ }
+ dir = (hand.pts[surface_handles] - Geom::Point(3*width/4., width/4.)) / 30;
+ if(!save) {
+ cairo_move_to(cr, 3*width/4., width/4.);
+ cairo_line_to(cr, hand.pts[surface_handles]);
+ }
+ for(unsigned vi = 0; vi < sb2.vs; vi++)
+ for(unsigned ui = 0; ui < sb2.us; ui++)
+ for(unsigned iv = 0; iv < 2; iv++)
+ for(unsigned iu = 0; iu < 2; iu++) {
+ unsigned corner = iu + 2*iv;
+ unsigned i = ui + vi*sb2.us;
+ Geom::Point base((2*(iu+ui)/(2.*ui+1)+1)*width/4.,
+ (2*(iv+vi)/(2.*vi+1)+1)*width/4.);
+ double dl = dot((hand.pts[corner+4*i] - base), dir)/dot(dir,dir);
+ display_handles[corner+4*i] = dl*dir + base;
+ sb2[i][corner] = dl*10/(width/2)*pow(4.,(double)ui+vi);
+ }
+ cairo_sb2d(cr, sb2, dir*0.1, width);
+
+ *notify << "bo = " << sb2.index(0,0);
+
+ cairo_set_source_rgba (cr, 0., 0.125, 0, 1);
+ cairo_stroke(cr);
+ if(!save)
+ for(auto & display_handle : display_handles)
+ draw_circ(cr, display_handle);
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new Sb2d());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/sbasis-fitting.cpp b/src/3rdparty/2geom/src/toys/sbasis-fitting.cpp
new file mode 100644
index 0000000..9963790
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/sbasis-fitting.cpp
@@ -0,0 +1,214 @@
+/*
+ * SBasis Fitting Example
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#include <2geom/numeric/fitting-tool.h>
+#include <2geom/numeric/fitting-model.h>
+
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+
+using namespace Geom;
+
+
+class SBasisFitting : public Toy
+{
+ private:
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ sliders[0].geometry(Point(50, 30), 100);
+
+ size_t value = (size_t)(sliders[0].value());
+
+ if (degree != value)
+ {
+ degree = value;
+ total_handles = degree + 1;
+ order = total_handles/2 - 1;
+ dstep = interval_length/degree;
+ step = 1.0/degree;
+
+ double x = sx;
+ psh.pts.clear();
+ for (size_t i = 0; i < total_handles; ++i)
+ {
+ psh.push_back(x, 300*uniform()+50);
+ x += dstep;
+ }
+
+ handles[0] = &psh;
+
+ if (fmsb != NULL) delete fmsb;
+ fmsb = new NL::LFMSBasis(order);
+ assert(fmsb != NULL);
+ if (lsf_sb != NULL) delete lsf_sb;
+ lsf_sb = new NL::least_squeares_fitter<NL::LFMSBasis>(*fmsb, 25);
+ assert(lsf_sb != NULL);
+
+ double t = 0;
+ for (size_t i = 0; i < total_handles; ++i)
+ {
+ lsf_sb->append(t);
+ t += step;
+ }
+ lsf_sb->update();
+
+ curr_ys.clear();
+ curr_ys.resize(total_handles);
+ for (size_t i = 0; i < total_handles; ++i)
+ {
+ curr_ys[i] = psh.pts[i][Y];
+ }
+ prev_ys = curr_ys;
+
+ fmsb->instance(sb_curve, lsf_sb->result(curr_ys));
+ }
+ else
+ {
+ double x = sx;
+ for (size_t i = 0; i < total_handles; ++i)
+ {
+ psh.pts[i][X] = x;
+ curr_ys[i] = psh.pts[i][Y];
+ x += dstep;
+ }
+ fmsb->instance(sb_curve, lsf_sb->result(prev_ys, curr_ys));
+ prev_ys = curr_ys;
+ }
+
+
+ D2<SBasis> curve;
+ curve[X] = SBasis(Linear(sx,sx) + interval_length * Linear(0, 1));
+ curve[Y] = sb_curve;
+
+ cairo_set_source_rgba(cr, 0.3, 0.3, 0.3, 1.0);
+ cairo_set_line_width (cr, 0.3);
+ cairo_d2_sb(cr, curve);
+ cairo_stroke(cr);
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ SBasisFitting()
+ : degree(3),
+ total_handles(degree+1),
+ order(total_handles/2 - 1),
+ interval_length(400),
+ dstep(interval_length/degree),
+ step(1.0/degree)
+ {
+ sx = 50;
+ double x = sx;
+ for (size_t i = 0; i < total_handles; ++i)
+ {
+ psh.push_back(x, 300*uniform()+50);
+ x += dstep;
+ }
+
+ handles.push_back(&psh);
+
+ fmsb = new NL::LFMSBasis(order);
+ assert(fmsb != NULL);
+ lsf_sb = new NL::least_squeares_fitter<NL::LFMSBasis>(*fmsb, 25);
+ assert(lsf_sb != NULL);
+
+ double t = 0;
+ for (size_t i = 0; i < total_handles; ++i)
+ {
+ lsf_sb->append(t);
+ t += step;
+ }
+ lsf_sb->update();
+
+ curr_ys.clear();
+ curr_ys.resize(total_handles);
+ for (size_t i = 0; i < total_handles; ++i)
+ {
+ curr_ys[i] = psh.pts[i][Y];
+ }
+ prev_ys = curr_ys;
+
+ fmsb->instance(sb_curve, lsf_sb->result(curr_ys));
+
+
+ sliders.emplace_back(1, 11, 2, 3, "degree");
+ handles.push_back(&(sliders[0]));
+ }
+
+ ~SBasisFitting() override
+ {
+ if (fmsb != NULL) delete fmsb;
+ if (lsf_sb != NULL) delete lsf_sb;
+ }
+
+ private:
+ size_t degree;
+ size_t total_handles;
+ size_t order;
+ double interval_length;
+ double dstep;
+ double step;
+ double sx;
+ std::vector<double> curr_ys, prev_ys;
+ SBasis sb_curve;
+ NL::LFMSBasis* fmsb;
+ NL::least_squeares_fitter<NL::LFMSBasis>* lsf_sb;
+ PointSetHandle psh;
+ std::vector<Slider> sliders;
+};
+
+
+
+
+int main(int argc, char **argv)
+{
+ init( argc, argv, new SBasisFitting(), 600, 600 );
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+
diff --git a/src/3rdparty/2geom/src/toys/sbasisdim.cpp b/src/3rdparty/2geom/src/toys/sbasisdim.cpp
new file mode 100644
index 0000000..3804090
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/sbasisdim.cpp
@@ -0,0 +1,262 @@
+#include <iostream>
+#include <2geom/sbasis.h>
+#include <2geom/bezier-to-sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <time.h>
+#include <vector>
+
+#include <2geom/orphan-code/linearN.h>
+#include <2geom/orphan-code/sbasisN.h>
+
+using namespace Geom;
+using namespace std;
+
+
+struct Frame
+{
+ Geom::Point O;
+ Geom::Point x;
+ Geom::Point y;
+ Geom::Point z;
+};
+
+void
+plot3d(cairo_t *cr, double x, double y, double z, Frame frame){
+ Point p;
+ for (unsigned dim=0; dim<2; dim++){
+ p[dim] = x*frame.x[dim] + y*frame.y[dim] + z*frame.z[dim];
+ p[dim] += frame.O[dim];
+ }
+ draw_cross(cr, p);
+}
+void
+plot3d(cairo_t *cr, SBasis const &x, SBasis const &y, SBasis const &z, Frame frame){
+ D2<SBasis> curve;
+ for (unsigned dim=0; dim<2; dim++){
+ curve[dim] = x*frame.x[dim] + y*frame.y[dim] + z*frame.z[dim];
+ curve[dim] += frame.O[dim];
+ }
+ cairo_d2_sb(cr, curve);
+}
+
+void
+plot3d(cairo_t *cr, LinearN<2> const &f, Frame frame){
+ int iMax = 5;
+ for (int i=0; i<iMax; i++){
+ double t = i/(iMax-1.);
+ plot3d(cr, Linear(0,1), Linear(t), toLinear(f.partialEval(t, 1)), frame);
+ plot3d(cr, Linear(t), Linear(0,1), toLinear(f.partialEval(t, 0)), frame);
+ }
+}
+void
+plot3d(cairo_t *cr, SBasisN<2> const &f, Frame frame){
+ int iMax = 5;
+ for (int i=0; i<iMax; i++){
+ double t = i/(iMax-1.);
+ plot3d(cr, Linear(0,1), Linear(t), toSBasis(f.partialEval(t, 1)), frame);
+ plot3d(cr, Linear(t), Linear(0,1), toSBasis(f.partialEval(t, 0)), frame);
+ }
+}
+void
+dot_plot3d(cairo_t *cr, SBasisN<2> const &f, Frame frame){
+ int iMax = 15;
+ double t[2];
+ for (int i=0; i<iMax; i++){
+ t[0] = i/(iMax-1.);
+ for (int j=0; j<iMax; j++){
+ t[1] = j/(iMax-1.);
+ plot3d(cr, t[0], t[1], f.valueAt(t), frame);
+ }
+ }
+}
+
+
+class SBasisDimToy: public Toy {
+ PointSetHandle hand;
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+
+ double slider_top = width/4.;
+ double slider_bot = width*3./4.;
+ double slider_margin = width/8.;
+ if(hand.pts.empty()) {
+ hand.pts.emplace_back(width*3./16., 3*width/4.);
+ hand.pts.push_back(hand.pts[0] + Geom::Point(width/2., 0));
+ hand.pts.push_back(hand.pts[0] + Geom::Point(width/8., -width/12.));
+ hand.pts.push_back(hand.pts[0] + Geom::Point(0,-width/4.));
+ hand.pts.emplace_back(slider_margin,slider_bot);
+ hand.pts.emplace_back(width-slider_margin,slider_top);
+ }
+
+ hand.pts[4][X] = slider_margin;
+ if (hand.pts[4][Y]<slider_top) hand.pts[4][Y] = slider_top;
+ if (hand.pts[4][Y]>slider_bot) hand.pts[4][Y] = slider_bot;
+ hand.pts[5][X] = width-slider_margin;
+ if (hand.pts[5][Y]<slider_top) hand.pts[5][Y] = slider_top;
+ if (hand.pts[5][Y]>slider_bot) hand.pts[5][Y] = slider_bot;
+
+ double tA = (slider_bot-hand.pts[4][Y])/(slider_bot-slider_top);
+ double tB = (slider_bot-hand.pts[5][Y])/(slider_bot-slider_top);
+
+ cairo_move_to(cr,Geom::Point(slider_margin,slider_bot));
+ cairo_line_to(cr,Geom::Point(slider_margin,slider_top));
+ cairo_move_to(cr,Geom::Point(width-slider_margin,slider_bot));
+ cairo_line_to(cr,Geom::Point(width-slider_margin,slider_top));
+ cairo_set_line_width(cr,.5);
+ cairo_set_source_rgba (cr, 0., 0.3, 0., 1.);
+ cairo_stroke(cr);
+
+ Frame frame;
+ frame.O = hand.pts[0];//
+ frame.x = hand.pts[1]-hand.pts[0];//
+ frame.y = hand.pts[2]-hand.pts[0];//
+ frame.z = hand.pts[3]-hand.pts[0];//
+
+ plot3d(cr,Linear(0,1),Linear(0,0),Linear(0,0),frame);
+ plot3d(cr,Linear(0,1),Linear(1,1),Linear(0,0),frame);
+ plot3d(cr,Linear(0,0),Linear(0,1),Linear(0,0),frame);
+ plot3d(cr,Linear(1,1),Linear(0,1),Linear(0,0),frame);
+ cairo_set_line_width(cr,.2);
+ cairo_set_source_rgba (cr, 0., 0., 0., 1.);
+ cairo_stroke(cr);
+
+ SBasisN<1> t = LinearN<1>(0,1);
+
+ LinearN<2> u,v;
+ setToVariable(u,0);
+ setToVariable(v,1);
+ SBasisN<2> f, x = u, y = v; //x,y are used for conversion :-(
+
+
+//--------------------
+//Basic MultiDegree<2> tests...
+//--------------------
+#if 0
+ unsigned sizes[2];
+ sizes[0] = 4;
+ sizes[1] = 3;
+ MultiDegree<2> d0;
+ d0.p[0]=3;
+ d0.p[1]=2;
+ std::cout<<"(3,2)->"<< d0.asIdx(sizes) <<"\n";
+ MultiDegree<2> d1(11,sizes);
+ std::cout<<"11->"<< d1.p[0] <<","<<d1.p[1] <<"\n";
+#endif
+
+//--------------------
+//Basic LinearN tests
+//--------------------
+#if 0
+ plot3d(cr, u, frame);
+ cairo_set_line_width(cr,1);
+ cairo_set_source_rgba (cr, .75, 0., 0., 1.);
+ cairo_stroke(cr);
+ plot3d(cr, v, frame);
+ cairo_set_line_width(cr,1);
+ cairo_set_source_rgba (cr, 0., 0., 0.75, 1.);
+ cairo_stroke(cr);
+#endif
+
+//--------------------
+//Basic SBasisN tests
+//--------------------
+#if 1
+ f = x*x + y*y;//(x-one*.5)*(x-one*.5);
+ std::cout<<"\nf: "<<f<<"\n";
+ std::cout<<"Degrees:\n";
+ std::cout<<"quick_deg: "<< f.quick_degree(0)<<", "<<f.quick_degree(1)<<"\n";
+ std::cout<<"real s_deg: "<< f.degree(0)<<", "<<f.degree(1)<<"\n";
+ std::cout<<"real t_deg: "<< f.real_t_degree(0)<<", "<<f.real_t_degree(1)<<"\n";
+ plot3d(cr, f, frame);
+ cairo_set_line_width(cr,1);
+ cairo_set_source_rgba (cr, 0., 0.75, 0., 1.);
+ cairo_stroke(cr);
+#endif
+
+//--------------------
+// SBasisOf<SBasisOf<double> > simulation tests
+//--------------------
+#if 1
+ SBasisN<1> y1d = LinearN<1>(0,1);
+ SBasisN<2> g,g1;
+ g.appendCoef(LinearN<1>(0.), y1d*y1d , 0);
+ g.appendCoef(y1d + 1, y1d, 0);
+ g1 = x*y*y + x*(-x+1)*( (-x+1)*(y+1) + x*y );
+ plot3d(cr, g-g1, frame);
+ cairo_set_line_width(cr,1);
+ cairo_set_source_rgba (cr, 0., 0.75, 0., 1.);
+ cairo_stroke(cr);
+#endif
+//--------------------
+// SBasisN composition tests
+//--------------------
+#if 1
+ SBasisN<1> z;
+ std::vector<SBasisN<1> > var;
+ t -=.5;
+ var.push_back( t*t + tA);
+ var.push_back( (t+.3)*t*(t-.3) + tB);
+ z = compose(f,var);
+ cairo_set_line_width(cr,1);
+ plot3d(cr, toSBasis(var[0]), toSBasis(var[1]), Linear(0.), frame);
+ cairo_set_source_rgba (cr, 0., 0., 0.75, 1.);
+ cairo_stroke(cr);
+ plot3d(cr, toSBasis(var[0]), toSBasis(var[1]), toSBasis(z), frame);
+ cairo_set_source_rgba (cr, 0.75, 0., 0., 1.);
+ cairo_stroke(cr);
+#endif
+
+//--------------------
+//Some timing. TODO: Compare to SBasisOf<SBasisOf<double> >
+//--------------------
+#if 0
+ double units = 1e6;
+ std::string units_string("us");
+ double timer_precision = 0.1;
+ clock_t end_t = clock()+clock_t(timer_precision*CLOCKS_PER_SEC);
+ // Base loop to remove overhead
+ end_t = clock()+clock_t(timer_precision*CLOCKS_PER_SEC);
+ long iterations = 0;
+ while(end_t > clock()) {
+ iterations++;
+ }
+ double overhead = timer_precision*units/iterations;
+
+ end_t = clock()+clock_t(timer_precision*CLOCKS_PER_SEC);
+ iterations = 0;
+ while(end_t > clock()) {
+ f.valueAt(t);
+ iterations++;
+ }
+ *notify << "recursive eval: "
+ << ", time = " << timer_precision*units/iterations-overhead
+ << units_string << std::endl;
+#endif
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+public:
+ SBasisDimToy(){
+ handles.push_back(&hand);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new SBasisDimToy);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype = cpp:expandtab:shiftwidth = 4:tabstop = 8:softtabstop = 4:encoding = utf-8:textwidth = 99 :
diff --git a/src/3rdparty/2geom/src/toys/scribble.cpp b/src/3rdparty/2geom/src/toys/scribble.cpp
new file mode 100644
index 0000000..afaff65
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/scribble.cpp
@@ -0,0 +1,366 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/sbasis-math.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/path-intersection.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/transforms.h>
+#include <2geom/angle.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <sstream>
+
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+// TODO:
+// use path2
+// replace Ray stuff with path2 line segments.
+
+//-----------------------------------------------
+
+void draw_segment(cairo_t* cr, Point const& p1, Point const& p2)
+{
+ cairo_move_to(cr, p1);
+ cairo_line_to(cr, p2);
+}
+
+void draw_segment(cairo_t* cr, Point const& p1, double angle, double length)
+{
+ Point p2;
+ p2[X] = length * std::cos(angle);
+ p2[Y] = length * std::sin(angle);
+ p2 += p1;
+ draw_segment(cr, p1, p2);
+}
+
+void draw_segment(cairo_t* cr, LineSegment const& ls)
+{
+ draw_segment(cr, ls[0], ls[1]);
+}
+
+int num = 30;
+vector<double> c1_bot;
+vector<double> c1_top;
+vector<double> c2_bot;
+vector<double> c2_top;
+vector<double> c3_bot;
+vector<double> c3_top;
+vector<double> c4_bot;
+vector<double> c4_top;
+
+CubicBezier create_bezier(Point const &anchor, double angle /* in degrees */,
+ double length, double dx1, double dx2, cairo_t *cr = NULL) {
+ Point A = anchor;
+ Point dir = Point(1.0, 0) * Rotate(-angle) * length;
+ Point B = anchor + dir;
+
+ Point C = A - Point(1.0, 0) * dx1;
+ Point D = B + Point(1.0, 0) * dx1;
+ Point E = A + Point(1.0, 0) * dx2;
+ Point F = B - Point(1.0, 0) * dx2;
+
+ if (cr) {
+ draw_cross(cr, A);
+ draw_cross(cr, B);
+ draw_cross(cr, C);
+ draw_cross(cr, D);
+ draw_cross(cr, E);
+ draw_cross(cr, F);
+ }
+
+ return CubicBezier(C, E, F, D);
+}
+
+/*
+ * Draws a single "scribble segment" (we use many of these to cover the whole curve).
+ *
+ * Let I1, I2 be two adjacent intervals (bounded by the points A1, A2, A3) on the lower and J1, J2
+ * two adjacent intervals (bounded by B1, B2, B3) on the upper parallel. Then we specify:
+ *
+ * - The point in I1 where the scribble line starts (given by a value in [0,1])
+ * - The point in J2 where the scribble line ends (given by a value in [0,1])
+ * - A point in I2 (1st intermediate point of the Bezier curve)
+ * - A point in J1 (2nd intermediate point of the Bezier curve)
+ *
+ */
+CubicBezier
+create_bezier_again(Point const &anchor1, Point const &anchor2, Point const &dir1, Point const &dir2,
+ double /*c1*/, double /*c2*/, double c3, double c4, double mu, cairo_t *cr = NULL) {
+ Point A = anchor1;// - dir * c1;
+ Point B = anchor1 + dir1 * (c3 + mu);
+ Point C = anchor2 - dir2 * (c4 + mu);
+ Point D = anchor2;// + dir * c2;
+
+ if (cr) {
+ draw_cross(cr, A);
+ //draw_cross(cr, B);
+ //draw_cross(cr, C);
+ //draw_cross(cr, D);
+ }
+
+ return CubicBezier(A, B, C, D);
+}
+
+CubicBezier
+create_bezier_along_curve(Piecewise<D2<SBasis> > const &curve1,
+ Piecewise<D2<SBasis> > const &curve2,
+ double segdist,
+ Coord const t1, Coord const t2, Point const &n,
+ double c1, double c2, double /*c3*/, double /*c4*/, double /*mu*/, cairo_t *cr = NULL) {
+ cout << "create_bezier_along_curve -- start" << endl;
+ /*
+ Point A = curve1.valueAt(t1 - c1);
+ Point B = curve1.valueAt(t1) + n * (c3 + mu);
+ Point C = curve2.valueAt(t2) - n * (c4 + mu);
+ Point D = curve2.valueAt(t2 + c2);
+ */
+ Point A = curve1.valueAt(t1 - c1 * segdist);
+ Point B = curve1.valueAt(t1) + n * 0.1;
+ Point C = curve2.valueAt(t2) - n * 0.1;
+ Point D = curve2.valueAt(t2 + c2 * segdist);
+
+ if (cr) {
+ draw_cross(cr, A);
+ //draw_cross(cr, B);
+ //draw_cross(cr, C);
+ //draw_cross(cr, D);
+ }
+
+ cout << "create_bezier_along_curve -- end" << endl;
+ return CubicBezier(A, B, C, D);
+}
+
+class OffsetTester: public Toy {
+ PointSetHandle psh;
+ PointSetHandle psh_rand;
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ double w = 600;
+ double slider_top = w/4.;
+ double slider_bot = w*3./4.;
+ double slider_margin = 40;
+ double slider_middle = (slider_top + slider_bot) / 2;
+
+ if(psh.pts.empty()) {
+ psh.pts.emplace_back(200,300);
+ psh.pts.emplace_back(350,250);
+ psh.pts.emplace_back(500,280);
+ psh.pts.emplace_back(700,300);
+
+ psh.pts.emplace_back(400,300);
+ psh.pts.emplace_back(550,250);
+ psh.pts.emplace_back(700,280);
+ psh.pts.emplace_back(900,300);
+
+ psh.pts.emplace_back(900,500);
+ psh.pts.emplace_back(700,480);
+ psh.pts.emplace_back(550,450);
+ psh.pts.emplace_back(400,500);
+
+ psh_rand.pts.emplace_back(slider_margin,slider_bot);
+ psh_rand.pts.emplace_back(slider_margin,slider_top);
+ psh_rand.pts.emplace_back(slider_margin,slider_top);
+ psh_rand.pts.emplace_back(slider_margin,slider_top);
+ psh_rand.pts.emplace_back(slider_margin,slider_top);
+ psh_rand.pts.emplace_back(slider_margin,slider_bot);
+ psh_rand.pts.emplace_back(slider_margin,slider_middle);
+ }
+
+ psh_rand.pts[0][X] = slider_margin;
+ if (psh_rand.pts[0][Y]<slider_top) psh_rand.pts[0][Y] = slider_top;
+ if (psh_rand.pts[0][Y]>slider_bot) psh_rand.pts[0][Y] = slider_bot;
+ psh_rand.pts[1][X] = slider_margin + 15;
+ if (psh_rand.pts[1][Y]<slider_top) psh_rand.pts[1][Y] = slider_top;
+ if (psh_rand.pts[1][Y]>slider_bot) psh_rand.pts[1][Y] = slider_bot;
+ psh_rand.pts[2][X] = slider_margin + 30;
+ if (psh_rand.pts[2][Y]<slider_top) psh_rand.pts[2][Y] = slider_top;
+ if (psh_rand.pts[2][Y]>slider_bot) psh_rand.pts[2][Y] = slider_bot;
+ psh_rand.pts[3][X] = slider_margin + 45;
+ if (psh_rand.pts[3][Y]<slider_top) psh_rand.pts[3][Y] = slider_top;
+ if (psh_rand.pts[3][Y]>slider_bot) psh_rand.pts[3][Y] = slider_bot;
+ psh_rand.pts[4][X] = slider_margin + 60;
+ if (psh_rand.pts[4][Y]<slider_top) psh_rand.pts[4][Y] = slider_top;
+ if (psh_rand.pts[4][Y]>slider_bot) psh_rand.pts[4][Y] = slider_bot;
+ psh_rand.pts[5][X] = slider_margin + 75;
+ if (psh_rand.pts[5][Y]<slider_top) psh_rand.pts[5][Y] = slider_top;
+ if (psh_rand.pts[5][Y]>slider_bot) psh_rand.pts[5][Y] = slider_bot;
+ psh_rand.pts[6][X] = slider_margin + 90;
+ if (psh_rand.pts[6][Y]<slider_top) psh_rand.pts[6][Y] = slider_top;
+ if (psh_rand.pts[6][Y]>slider_bot) psh_rand.pts[6][Y] = slider_bot;
+
+ *notify << "Sliders:" << endl << endl << endl << endl;
+ *notify << "0 - segment distance" << endl;
+ *notify << "1 - start anchor randomization" << endl;
+ *notify << "2 - end anchor randomization" << endl;
+ *notify << "3 - start rounding randomization" << endl;
+ *notify << "4 - end rounding randomization" << endl;
+ *notify << "5 - start/end rounding increase randomization" << endl;
+ *notify << "6 - additional offset of the upper anchors (to modify the segment angle)" << endl;
+
+ for(unsigned i = 0; i < psh_rand.size(); ++i) {
+ cairo_move_to(cr,Geom::Point(slider_margin + 15.0 * i, slider_bot));
+ cairo_line_to(cr,Geom::Point(slider_margin + 15.0 * i, slider_top));
+ }
+ cairo_set_line_width(cr,.5);
+ cairo_set_source_rgba (cr, 0., 0.3, 0., 1.);
+ cairo_stroke(cr);
+
+ cairo_set_line_width (cr, 2);
+ cairo_set_source_rgba (cr, 0., 0., 0.8, 1);
+
+ // Draw the curve and its offsets
+ D2<SBasis> B = psh.asBezier();
+ cairo_d2_sb(cr, B);
+ cairo_stroke(cr);
+
+ Coord offset = 30;
+ Piecewise<D2<SBasis> > n = rot90(unitVector(derivative(B)));
+ Piecewise<D2<SBasis> > offset_curve1 = Piecewise<D2<SBasis> >(B)+n*offset;
+ Piecewise<D2<SBasis> > offset_curve2 = Piecewise<D2<SBasis> >(B)-n*offset;
+ PathVector offset_path1 = path_from_piecewise(offset_curve1, 0.1);
+ PathVector offset_path2 = path_from_piecewise(offset_curve2, 0.1);
+ Piecewise<D2<SBasis> > tangent1 = unitVector(derivative(offset_curve1));
+ Piecewise<D2<SBasis> > tangent2 = unitVector(derivative(offset_curve2));
+ cairo_set_line_width (cr, 1);
+ cairo_path(cr, offset_path1);
+ cairo_path(cr, offset_path2);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba (cr, 0., 0.5, 0., 1);
+
+ double lambda1 = 1.0 - (psh_rand.pts[1][Y] - slider_top) * 2.0/w;
+ double lambda2 = 1.0 - (psh_rand.pts[2][Y] - slider_top) * 2.0/w;
+ double lambda3 = 1.0 - (psh_rand.pts[3][Y] - slider_top) * 2.0/w;
+ double lambda4 = 1.0 - (psh_rand.pts[4][Y] - slider_top) * 2.0/w;
+ double mu = 1.0 - (psh_rand.pts[5][Y] - slider_top) * 2.0/w;
+ //Point dir = Point(1,0) * (slider_bot - psh_rand.pts[0][Y]) / 2.5;
+ double off = 0.5 - (psh_rand.pts[6][Y] - slider_top) * 2.0/w;
+
+ double segdist = (slider_bot - psh_rand.pts[0][Y]) / (slider_bot - slider_top) * 0.1;
+ if (segdist < 0.01) {
+ segdist = 0.01;
+ }
+
+ vector<Point> pts_bot;
+ vector<Point> pts_top;
+ vector<Point> dirs_bot;
+ vector<Point> dirs_top;
+ int counter = 0;
+ for(double i = 0.0; i < 1.0; i += segdist) {
+ draw_cross(cr, offset_curve1.valueAt(i));
+ pts_bot.push_back(offset_curve1.valueAt(i + segdist * c1_bot[counter] * lambda1));
+ pts_top.push_back(offset_curve2.valueAt(i + segdist * (c2_top[counter] * lambda2 + 1/2.0) + off));
+ dirs_bot.push_back(tangent1.valueAt(i) * 20);
+ dirs_top.push_back(tangent2.valueAt(i) * 20);
+ ++counter;
+ }
+
+ for(int i = 0; i < num; ++i) {
+ cout << "c1_bot[" << i << "]: " << c1_bot[i] << endl;
+ }
+
+ for (int i = 0; i < num-1; ++i) {
+ Path path1;
+ //cout << "dirs_bot[" << i << "]: " << dirs_bot[i] << endl;
+ cout << "c3_bot[" << i << "]: " << c3_bot[i] << endl;
+ CubicBezier bc = create_bezier_again(pts_bot[i], pts_top[i],
+ dirs_bot[i], dirs_top[i],
+ 0, 0, c3_bot[i] * lambda3, c4_top[i] * lambda4, mu, cr);
+ //c1_bot[i] * lambda1,
+ //c2_top[i] * lambda2,
+ //c3_bot[i] * lambda3,
+ //c4_top[i] * lambda4, mu, cr);
+
+ path1.append(bc);
+ cairo_path(cr, path1);
+
+ Path path2;
+ bc = create_bezier_again(pts_top[i], pts_bot[i+1],
+ dirs_top[i], dirs_bot[i+1],
+ 0, 0, c4_bot[i] * lambda4, c3_top[i] * lambda3, mu, cr);
+ /*
+ bc = create_bezier_again(pts_top[i+1], pts_bot[i], dir,
+ 1.0 - c2_top[i] * lambda2,
+ 1.0 - c1_bot[i+1] * lambda1,
+ c3_top[i] * lambda3,
+ c4_bot[i] * lambda4, mu, cr);
+ */
+ path2.append(bc);
+ cairo_path(cr, path2);
+ }
+
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+public:
+ OffsetTester() {
+ handles.push_back(&psh);
+ handles.push_back(&psh_rand);
+ /*
+ psh.pts.clear();
+ Point A(100,300);
+ //Point B(100,200);
+ //Point C(200,330);
+ Point D(200,100);
+ psh.push_back(A);
+ //psh.push_back(B);
+ //psh.push_back(C);
+ psh.push_back(D);
+ psh.push_back(Geom::Point(slider_margin,slider_bot));
+ */
+
+ for (int i = 0; i < num; ++i) {
+ c1_bot.push_back(uniform() - 0.5);
+ c1_top.push_back(uniform() - 0.5);
+ //c1_bot.push_back(1.0);
+ //c1_top.push_back(1.0);
+ c2_bot.push_back(uniform() - 0.5);
+ c2_top.push_back(uniform() - 0.5);
+
+ c3_bot.push_back(uniform());
+ c3_top.push_back(uniform());
+ c4_bot.push_back(uniform());
+ c4_top.push_back(uniform());
+ }
+
+ /*
+ for (int i = 0; i < num; ++i) {
+ c1_bot[i] = c1_bot[i] / 10.0;
+ c2_bot[i] = c2_bot[i] / 10.0;
+ c3_bot[i] = c3_bot[i] / 10.0;
+ c4_bot[i] = c4_bot[i] / 10.0;
+
+ c1_top[i] = c1_top[i] / 10.0;
+ c2_top[i] = c2_top[i] / 10.0;
+ c3_top[i] = c3_top[i] / 10.0;
+ c4_top[i] = c4_top[i] / 10.0;
+ }
+ */
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new OffsetTester);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+//vim:filetype = cpp:expandtab:shiftwidth = 4:tabstop = 8:softtabstop = 4:encoding = utf-8:textwidth = 99 :
+
+
diff --git a/src/3rdparty/2geom/src/toys/self-intersect.cpp b/src/3rdparty/2geom/src/toys/self-intersect.cpp
new file mode 100644
index 0000000..840e058
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/self-intersect.cpp
@@ -0,0 +1,67 @@
+#include <2geom/basic-intersection.h>
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-2d.h>
+#include <2geom/bezier-to-sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+using std::vector;
+using namespace Geom;
+
+class SelfIntersect: public Toy {
+ PointSetHandle psh;
+void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_line_width (cr, 0.5);
+ cairo_set_source_rgba (cr, 0., 0., 0, 1);
+
+ D2<SBasis> A = psh.asBezier();
+ //Rect Ar = *bounds_fast(A);
+ cairo_d2_sb(cr, A);
+ cairo_stroke(cr);
+
+ std::vector<std::pair<double, double> > all_si;
+
+ find_self_intersections(all_si, A);
+
+ cairo_stroke(cr);
+ cairo_set_source_rgba (cr, 1., 0., 1, 1);
+ for(auto & i : all_si) {
+ draw_handle(cr, A(i.first));
+ }
+ cairo_stroke(cr);
+
+ *notify << "total intersections: " << all_si.size();
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+}
+public:
+SelfIntersect (unsigned bez_ord) {
+ handles.push_back(&psh);
+ for(unsigned i = 0; i < bez_ord; i++)
+ psh.push_back(uniform()*400, uniform()*400);
+}
+};
+
+int main(int argc, char **argv) {
+ unsigned bez_ord=5;
+ if(argc > 1)
+ sscanf(argv[1], "%d", &bez_ord);
+ init(argc, argv, new SelfIntersect(bez_ord));
+
+ return 0;
+}
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/sketch-fitter.cpp b/src/3rdparty/2geom/src/toys/sketch-fitter.cpp
new file mode 100644
index 0000000..2a74924
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/sketch-fitter.cpp
@@ -0,0 +1,923 @@
+/*
+ * sb-to-bez Toy - Tests conversions from sbasis to cubic bezier.
+ *
+ * Copyright 2007 jf barraud.
+ * 2008 njh
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ */
+
+// mainly experimental atm...
+// do not expect to find anything understandable here atm.
+
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/sbasis-math.h>
+#include <2geom/basic-intersection.h>
+#include <2geom/bezier-utils.h>
+
+#include <2geom/circle.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#define ZERO 1e-7
+
+using std::vector;
+using namespace Geom;
+using namespace std;
+
+#include <stdio.h>
+#include <gsl/gsl_poly.h>
+
+std::vector<Point> neighbors(std::vector<Point> const &pts, unsigned idx, double radius){
+ std::vector<Point> res;
+ Point p0 = pts[idx];
+ for (auto p : pts){
+ if ( L2(p-p0) < radius ) res.push_back(p);
+ }
+ return res;
+}
+
+double curvature(Point const &a, Point const &b, Point const &c){
+ Line med_ab = Line( (a+b)/2, (a+b)/2+rot90(b-a) );
+ Line med_bc = Line( (b+c)/2, (b+c)/2+rot90(c-b) );
+ OptCrossing o = intersection(med_ab, med_bc);
+ if (o){
+ Point oo = med_ab.pointAt(o->ta);
+ return(1./L2(oo-a));
+ }
+ else
+ return 0;
+}
+
+double avarageCurvature(std::vector<Point> const &pts, unsigned idx, double radius){
+ std::vector<Point> ngbrs = neighbors(pts, idx, radius);
+ if (ngbrs.size()<3) return 0;
+ double k=0;
+ double mass = 0;
+ for (unsigned i=0; i<5; i++){
+ unsigned ia = 0, ib = 0, ic = 0;
+ ia = rand()%ngbrs.size();
+ while (ib == ia)
+ ib = rand()%ngbrs.size();
+ while (ic == ia || ic == ib)
+ ic = rand()%ngbrs.size();
+ k += curvature(pts[ia],pts[ib],pts[ic]);
+ mass += 1; //smaller mass to closer triplets?
+ }
+ k /= mass;
+ return k;
+}
+
+Point massCenter(std::vector<Point> const &pts){
+ Point g = Point(0,0);
+ for (unsigned i=0; i<pts.size(); i++){
+ g += pts[i]/pts.size();
+ }
+ return g;
+}
+
+Line meanSquareLine(std::vector<Point> const &pts){
+ Point g = massCenter(pts);
+ double a = 0, b = 0, c = 0;
+ for (auto pt : pts){
+ a += (pt[Y]-g[Y])*(pt[Y]-g[Y]);
+ b +=-(pt[X]-g[X])*(pt[Y]-g[Y]);
+ c += (pt[X]-g[X])*(pt[X]-g[X]);
+ }
+ double eigen = ( (a+c) - sqrt((a-c)*(a-c)+4*b*b) )/2;
+ Point u(-b,a-eigen);
+ return Line(g, g+u);
+}
+
+void tighten(std::vector<Point> &pts, double radius, bool linear){
+ for (unsigned i=0; i<pts.size(); i++){
+ std::vector<Point> ngbrs = neighbors(pts,i,radius);
+ if (linear){
+ Line d = meanSquareLine(ngbrs);
+ Point proj = projection( pts[i], d );
+ double t = 2./3.;
+ pts[i] = pts[i]*(1-t) + proj*t;
+ }else if (ngbrs.size()>=3) {
+ Circle c;
+ c.fit(ngbrs);
+ Point o = c.center();
+ double r = c.radius();
+ pts[i] = o + unit_vector(pts[i]-o)*r;
+ }
+ }
+}
+
+double dist_to(std::vector<Point> const &pts, Point const &p, unsigned *idx=NULL){
+ double d,d_min = std::numeric_limits<float>::infinity();
+ if (idx) *idx = pts.size();
+ for (unsigned i = 0; i<pts.size(); i++){
+ d = L2(pts[i]-p);
+ if ( d < d_min ){
+ d_min = d;
+ if (idx) *idx = i;
+ }
+ }
+ return d_min;
+}
+
+void fuse_close_points(std::vector<Point> &pts, double dist_min){
+ if (pts.size()==0) return;
+ std::vector<Point> reduced_pts;
+ reduced_pts.push_back(pts[0]);
+ for (auto & pt : pts){
+ double d = dist_to(reduced_pts, pt);
+ if ( d > dist_min ) reduced_pts.push_back(pt);
+ }
+ pts = reduced_pts;
+ return;
+}
+
+
+unsigned nearest_after(std::vector<Point>const &pts, unsigned idx, double *dist = NULL){
+ if ( idx >= pts.size()-1 ) return pts.size();
+ Point p = pts[idx];
+ unsigned res = idx+1;
+ double d_min = L2(p-pts[res]);
+ for (unsigned i=idx+2; i<pts.size(); i++){
+ double d = L2(p-pts[i]);
+ if (d < d_min) {
+ d_min = d;
+ res = i;
+ }
+ }
+ if (dist) *dist = d_min;
+ return res;
+}
+
+//TEST ME: use direction information to separate exaeco?
+void sort_nearest(std::vector<Point> &pts, double no_longer_than = 0){
+ double d;
+ Point p;
+ for (unsigned i=0; i<pts.size()-1; i++){
+ unsigned j = nearest_after(pts,i,&d);
+ if (no_longer_than >0.1 && d > no_longer_than){
+ pts.erase(pts.begin()+i+1, pts.end());
+ return;
+ }
+ p = pts[i+1];
+ pts[i+1] = pts[j];
+ pts[j] = p;
+ }
+}
+
+//FIXME: optimize me if further used...
+void sort_nearest_bis(std::vector<Point> &pts, double radius){
+ double d;
+ Point p;
+ for (unsigned i=0; i<pts.size()-1; i++){
+ bool already_visited = true;
+ unsigned next = 0; // silence warning
+ while ( i < pts.size()-1 && already_visited ){
+ next = nearest_after(pts,i,&d);
+ already_visited = false;
+ for (unsigned k=0; k<i; k++){
+ double d_k_next = L2( pts[next] - pts[k]);
+ if ( d_k_next < d && d_k_next < radius ){
+ already_visited = true;
+ pts.erase(pts.begin()+next);
+ break;
+ }
+ }
+ }
+ if (!already_visited){
+ p = pts[i+1];
+ pts[i+1] = pts[next];
+ pts[next] = p;
+ }
+ }
+}
+
+Path ordered_fit(std::vector<Point> &pts, double tol){
+ unsigned n_points = pts.size();
+ Geom::Point * b = g_new(Geom::Point, 4*n_points);
+ Geom::Point * points = g_new(Geom::Point, 4*n_points);
+ for (unsigned int i = 0; i < pts.size(); i++) {
+ points[i] = pts[i];
+ }
+ int max_segs = 4*n_points;
+ int const n_segs = bezier_fit_cubic_r(b, points, n_points,
+ tol*tol, max_segs);
+ Path res;
+ if ( n_segs > 0){
+ res = Path(b[0]);
+ for (int i=0; i<n_segs; i++){
+ res.appendNew<CubicBezier>(b[4*i+1],b[4*i+2],b[4*i+3]);
+ }
+ }
+ g_free(b);
+ g_free(points);
+ return res;
+}
+
+//-----------------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------------------
+
+
+std::vector<Point> eat(std::vector<Point> const &pts, double sampling){
+ std::vector<bool> visited(pts.size(),false);
+ std::vector<Point> res;
+ Point p = pts.front();
+ //Point q = p;
+ res.push_back(p);
+ while(true){
+ double num_nghbrs = 0;
+ Point next(0,0);
+ for(unsigned i = 0; i < pts.size(); i++) {
+ if (!visited[i] && L2(pts[i]-p)<sampling){
+ //TODO: rotate pts[i] so that last step was in dir -pi...
+ //dir += atan2(pts[i]-p);
+ visited[i] = true;
+ next+= pts[i]-p;
+ num_nghbrs += 1;
+ }
+ }
+ if (num_nghbrs == 0) break;
+ //q=p;
+ next *= 1./num_nghbrs;
+ p += next;
+ res.push_back(p);
+ }
+ return res;
+}
+
+
+
+
+
+//-----------------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------------------
+
+double exp_rescale(double x)
+{
+ return pow(10, x*5-2);
+}
+std::string exp_formatter(double x)
+{
+ return default_formatter(exp_rescale(x));
+}
+
+class SketchFitterToy: public Toy {
+
+ enum menu_item_t
+ {
+ SHOW_MENU = 0,
+ TEST_TIGHTEN,
+ TEST_EAT_BY_STEP,
+ TEST_TIGHTEN_EAT,
+ TEST_CURVATURE,
+ TEST_SORT,
+ TEST_NUMERICAL,
+ SHOW_HELP,
+ TOTAL_ITEMS // this one must be the last item
+ };
+
+ enum handle_label_t
+ {
+ };
+
+ enum toggle_label_t
+ {
+ DRAW_MOUSES = 0,
+ DRAW_IMPROVED_MOUSES,
+ DRAW_STROKE,
+ TIGHTEN_USE_CIRCLE,
+ SORT_BIS,
+ TOTAL_TOGGLES // this one must be the last item
+ };
+
+ enum slider_label_t
+ {
+ TIGHTEN_NBHD_SIZE = 0,
+ TIGHTEN_ITERRATIONS,
+ EAT_NBHD_SIZE,
+ SORT_RADIUS,
+ FUSE_RADIUS,
+ INTERPOLATE_RADIUS,
+ CURVATURE_NBHD_SIZE,
+ POINT_CHOOSER,
+ TOTAL_SLIDERS // this one must be the last item
+ };
+
+ static const char* menu_items[TOTAL_ITEMS];
+ static const char keys[TOTAL_ITEMS];
+
+ void fit_empty(){}
+ void first_time(int /*argc*/, char** /*argv*/) override
+ {
+ draw_f = &SketchFitterToy::draw_menu;
+ fit_f = &SketchFitterToy::fit_empty;
+ }
+
+ void init_common()
+ {
+ set_common_control_geometry = true;
+ set_control_geometry = true;
+
+ handles.clear();
+ handles.push_back(&(toggles[DRAW_MOUSES]));
+ handles.push_back(&(toggles[DRAW_IMPROVED_MOUSES]));
+ handles.push_back(&(toggles[DRAW_STROKE]));
+
+ //sliders.clear();
+ //toggles.clear();
+ //handles.clear();
+ }
+ void init_common_ctrl_geom(cairo_t* /*cr*/, int width, int /*height*/, std::ostringstream* /*notify*/)
+ {
+ if ( set_common_control_geometry )
+ {
+ set_common_control_geometry = false;
+ Point p(10, 20), d(width/3-20,25);
+ toggles[DRAW_MOUSES].bounds = Rect(p, p + d);
+ p += Point ((width)/3, 0);
+ toggles[DRAW_IMPROVED_MOUSES].bounds = Rect(p, p + d);
+ p += Point ((width)/3, 0);
+ toggles[DRAW_STROKE].bounds = Rect(p, p + d);
+ }
+ }
+ virtual void draw_common( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool /*save*/, std::ostringstream */*timer_stream*/)
+ {
+ init_common_ctrl_geom(cr, width, height, notify);
+ if(!mouses.empty() && toggles[DRAW_MOUSES].on ) {
+ //cairo_move_to(cr, mouses[0]);
+ //for(unsigned i = 0; i < mouses.size(); i++) {
+ // cairo_line_to(cr, mouses[i]);
+ //}
+ for(auto & mouse : mouses) {
+ draw_cross(cr, mouse);
+ }
+ cairo_set_source_rgba (cr, 0., 0., 0., .25);
+ cairo_set_line_width (cr, 0.5);
+ cairo_stroke(cr);
+ }
+
+ if(!improved_mouses.empty() && toggles[DRAW_IMPROVED_MOUSES].on ) {
+ cairo_move_to(cr, improved_mouses[0]);
+ for(auto & improved_mouse : improved_mouses) {
+ draw_cross(cr, improved_mouse);
+ }
+ cairo_set_source_rgba (cr, 1., 0., 0., 1);
+ cairo_set_line_width (cr, .75);
+ cairo_stroke(cr);
+ }
+
+ if(!stroke.empty() && toggles[DRAW_STROKE].on) {
+ cairo_pw_d2_sb(cr, stroke);
+ cairo_set_source_rgba (cr, 0., 0., 1., 1);
+ cairo_set_line_width (cr, .75);
+ cairo_stroke(cr);
+ }
+
+ *notify << "Press SHIFT to continue sketching. 'Z' to apply changes";
+ }
+
+
+//-----------------------------------------------------------------------------------------
+// Tighten: tries to move the points toward the common curve
+//-----------------------------------------------------------------------------------------
+ void init_tighten()
+ {
+ init_common();
+ handles.push_back(&(sliders[TIGHTEN_NBHD_SIZE]));
+ handles.push_back(&(sliders[TIGHTEN_ITERRATIONS]));
+ handles.push_back(&(toggles[TIGHTEN_USE_CIRCLE]));
+ }
+ void init_tighten_ctrl_geom(cairo_t* /*cr*/, std::ostringstream* /*notify*/, int width, int height)
+ {
+ if ( set_control_geometry ){
+ set_control_geometry = false;
+ sliders[TIGHTEN_NBHD_SIZE ].geometry(Point(50, height - 35*2), 180);
+ sliders[TIGHTEN_ITERRATIONS].geometry(Point(50, height - 35*3), 180);
+
+ Point p(width-250, height - 50), d(225,25);
+ toggles[TIGHTEN_USE_CIRCLE].bounds = Rect(p, p + d);
+ }
+ }
+ void fit_tighten(){
+ improved_mouses = mouses;
+ double radius = exp_rescale(sliders[TIGHTEN_NBHD_SIZE].value());
+ for (unsigned i=1; i<=sliders[TIGHTEN_ITERRATIONS].value(); i++){
+ tighten(improved_mouses, radius, !toggles[TIGHTEN_USE_CIRCLE].on);
+ }
+ }
+ void draw_tighten(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) {
+ draw_common(cr, notify, width, height, save, timer_stream);
+ init_tighten_ctrl_geom(cr, notify, width, height);
+ }
+
+//-----------------------------------------------------------------------------------------
+// Eat by step: eats the curve moving at each step in the average direction of the neighbors.
+//-----------------------------------------------------------------------------------------
+ void init_eat()
+ {
+ init_common();
+ handles.push_back(&(sliders[EAT_NBHD_SIZE]));
+ }
+ void init_eat_ctrl_geom(cairo_t* /*cr*/, std::ostringstream* /*notify*/, int /*width*/, int height)
+ {
+ if ( set_control_geometry ){
+ set_control_geometry = false;
+ sliders[EAT_NBHD_SIZE].geometry(Point(50, height - 35*(0+2)), 180);
+ }
+ }
+ void fit_eat(){
+ double radius = exp_rescale(sliders[EAT_NBHD_SIZE].value());
+ improved_mouses = mouses;
+
+ tighten(improved_mouses, 20, true);
+
+ stroke = Piecewise<D2<SBasis> >();
+ improved_mouses = eat(improved_mouses, radius);
+ Path p(improved_mouses[0]);
+ for(unsigned i = 1; i < improved_mouses.size(); i++) {
+ p.appendNew<LineSegment>(improved_mouses[i]);
+ }
+ stroke = p.toPwSb();
+ }
+ void draw_eat(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) {
+ draw_common(cr, notify, width, height, save, timer_stream);
+ init_eat_ctrl_geom(cr, notify, width, height);
+ }
+
+//-----------------------------------------------------------------------------------------
+// Tighten + Eat
+//-----------------------------------------------------------------------------------------
+ void init_tighten_eat()
+ {
+ init_common();
+ handles.push_back(&(sliders[TIGHTEN_NBHD_SIZE]));
+ handles.push_back(&(sliders[TIGHTEN_ITERRATIONS]));
+ handles.push_back(&(sliders[EAT_NBHD_SIZE]));
+ }
+ void init_tighten_eat_ctrl_geom(cairo_t* /*cr*/, std::ostringstream* /*notify*/, int /*width*/, int height)
+ {
+ if ( set_control_geometry ){
+ set_control_geometry = false;
+ sliders[TIGHTEN_NBHD_SIZE ].geometry(Point(50, height - 35*2), 180);
+ sliders[TIGHTEN_ITERRATIONS].geometry(Point(50, height - 35*3), 180);
+ sliders[EAT_NBHD_SIZE ].geometry(Point(50, height - 35*4), 180);
+ }
+ }
+ void fit_tighten_eat(){
+ improved_mouses = mouses;
+ double radius = exp_rescale(sliders[TIGHTEN_NBHD_SIZE].value());
+ for (unsigned i=1; i<=sliders[TIGHTEN_ITERRATIONS].value(); i++){
+ tighten(improved_mouses, radius, toggles[0].on);
+ }
+ stroke = Piecewise<D2<SBasis> >();
+ radius = exp_rescale(sliders[EAT_NBHD_SIZE].value());
+ improved_mouses = eat(improved_mouses, radius);
+ Path p(improved_mouses[0]);
+ for(unsigned i = 1; i < improved_mouses.size(); i++) {
+ p.appendNew<LineSegment>(improved_mouses[i]);
+ }
+ stroke = p.toPwSb();
+ }
+ void draw_tighten_eat(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) {
+ draw_common(cr, notify, width, height, save, timer_stream);
+ init_tighten_eat_ctrl_geom(cr, notify, width, height);
+ }
+
+//-----------------------------------------------------------------------------------------
+// Sort: tighten, then sort and eventually fuse.
+//-----------------------------------------------------------------------------------------
+ void init_sort()
+ {
+ init_common();
+ handles.push_back(&(sliders[TIGHTEN_NBHD_SIZE]));
+ handles.push_back(&(sliders[TIGHTEN_ITERRATIONS]));
+ handles.push_back(&(sliders[SORT_RADIUS]));
+ handles.push_back(&(sliders[FUSE_RADIUS]));
+ handles.push_back(&(sliders[INTERPOLATE_RADIUS]));
+ handles.push_back(&(toggles[TIGHTEN_USE_CIRCLE]));
+ handles.push_back(&(toggles[SORT_BIS]));
+ }
+ void init_sort_ctrl_geom(cairo_t* /*cr*/, std::ostringstream* /*notify*/, int width, int height)
+ {
+ if ( set_control_geometry ){
+ set_control_geometry = false;
+ sliders[TIGHTEN_NBHD_SIZE].geometry(Point(50, height - 35*2), 180);
+ sliders[TIGHTEN_ITERRATIONS].geometry(Point(50, height - 35*3), 180);
+ sliders[SORT_RADIUS].geometry(Point(50, height - 35*4), 180);
+ sliders[FUSE_RADIUS].geometry(Point(50, height - 35*5), 180);
+ sliders[INTERPOLATE_RADIUS].geometry(Point(50, height - 35*6), 180);
+
+ Point p(width-250, height - 50), d(225,25);
+ toggles[TIGHTEN_USE_CIRCLE].bounds = Rect(p, p + d);
+ p += Point(0,-30);
+ toggles[SORT_BIS].bounds = Rect(p, p + d);
+ }
+ }
+ void fit_sort(){
+ improved_mouses = mouses;
+ double radius = exp_rescale(sliders[TIGHTEN_NBHD_SIZE].value());
+ for (unsigned i=1; i<=sliders[TIGHTEN_ITERRATIONS].value(); i++){
+ tighten(improved_mouses, radius, !toggles[TIGHTEN_USE_CIRCLE].on);
+ }
+ double max_jump = exp_rescale(sliders[SORT_RADIUS].value());
+ if (toggles[SORT_BIS].on){
+ sort_nearest_bis(improved_mouses, max_jump);
+ }else{
+ sort_nearest(improved_mouses, max_jump);
+ }
+ radius = exp_rescale(sliders[FUSE_RADIUS].value());
+ fuse_close_points(improved_mouses, radius);
+
+ radius = exp_rescale(sliders[INTERPOLATE_RADIUS].value());
+ Path p = ordered_fit(improved_mouses, radius/5);
+ stroke = p.toPwSb();
+ }
+ void draw_sort(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) {
+ draw_common(cr, notify, width, height, save, timer_stream);
+ init_sort_ctrl_geom(cr, notify, width, height);
+
+ if(!improved_mouses.empty() && toggles[DRAW_IMPROVED_MOUSES].on ) {
+ cairo_move_to(cr, improved_mouses[0]);
+ for(unsigned i = 1; i < improved_mouses.size(); i++) {
+ cairo_line_to(cr, improved_mouses[i]);
+ }
+ cairo_set_source_rgba (cr, 1., 0., 0., 1);
+ cairo_set_line_width (cr, .75);
+ cairo_stroke(cr);
+ }
+ }
+
+//-----------------------------------------------------------------------------------------
+// Average curvature.
+//-----------------------------------------------------------------------------------------
+ void init_curvature()
+ {
+ init_common();
+ handles.push_back(&(sliders[CURVATURE_NBHD_SIZE]));
+ handles.push_back(&(sliders[POINT_CHOOSER]));
+ }
+ void init_curvature_ctrl_geom(cairo_t* /*cr*/, std::ostringstream* /*notify*/, int /*width*/, int height)
+ {
+ if ( set_control_geometry ){
+ set_control_geometry = false;
+ sliders[CURVATURE_NBHD_SIZE].geometry(Point(50, height - 60), 180);
+ sliders[POINT_CHOOSER ].geometry(Point(50, height - 90), 180);
+ }
+ }
+ //just for fun!
+ void fit_curvature(){
+ std::vector<double> curvatures(mouses.size(),0);
+ std::vector<double> lengths(mouses.size(),0);
+ for (unsigned i=0; i<mouses.size(); i++){
+ double radius = exp_rescale(sliders[CURVATURE_NBHD_SIZE].value());
+ std::vector<Point> ngbrs = neighbors(mouses,i,radius);
+ if ( ngbrs.size()>2 ){
+ Circle c;
+ c.fit(ngbrs);
+ curvatures[i] = 1./c.radius();
+ Point v = (i<mouses.size()-1) ? mouses[i+1]-mouses[i] : mouses[i]-mouses[i-1];
+ if (cross(v, c.center()-mouses[i]) > 0 )
+ curvatures[i] *= -1;
+ }else{
+ curvatures[i] = 0;
+ }
+ if (i>0){
+ lengths[i] = lengths[i-1] + L2(mouses[i]-mouses[i-1]);
+ }
+ }
+ Piecewise<SBasis> k = interpolate( lengths, curvatures , 1);
+ Piecewise<SBasis> alpha = integral(k);
+ Piecewise<D2<SBasis> > v = sectionize(tan2(alpha));
+ stroke = integral(v) + mouses[0];
+
+ Point sp = stroke.lastValue()-stroke.firstValue();
+ Point mp = mouses.back()-mouses.front();
+ Affine mat1 = Affine(sp[X], sp[Y], -sp[Y], sp[X], stroke.firstValue()[X], stroke.firstValue()[Y]);
+ Affine mat2 = Affine(mp[X], mp[Y], -mp[Y], mp[X], mouses[0][X], mouses[0][Y]);
+ mat1 = mat1.inverse()*mat2;
+ stroke = stroke*mat1;
+
+ }
+ void draw_curvature(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) {
+ draw_common(cr, notify, width, height, save, timer_stream);
+ init_curvature_ctrl_geom(cr, notify, width, height);
+ if(!mouses.empty()) {
+ double radius = exp_rescale(sliders[CURVATURE_NBHD_SIZE].value());
+ unsigned i = unsigned( (mouses.size()-1)*sliders[POINT_CHOOSER].value()/100. );
+ std::vector<Point> ngbrs = neighbors(mouses,i,radius);
+ if ( ngbrs.size()>2 ){
+ draw_cross(cr, mouses[i]);
+ Circle c;
+ c.fit(ngbrs);
+ cairo_arc(cr, c.center(X), c.center(Y), c.radius(), 0, 2*M_PI);
+ cairo_set_source_rgba (cr, 1., 0., 0., 1);
+ cairo_set_line_width (cr, .75);
+ cairo_stroke(cr);
+ }
+ cairo_pw_d2_sb(cr, stroke);
+ }
+ }
+
+//-----------------------------------------------------------------------------------------
+// Brutal optimization, number of segment fixed.
+//-----------------------------------------------------------------------------------------
+ void init_numerical()
+ {
+ init_common();
+ //sliders.push_back(Slider(0, 10, 1, 1, "Number of curves"));
+ //handles.push_back(&(sliders[0]));
+ }
+ void init_numerical_ctrl_geom(cairo_t* /*cr*/, std::ostringstream* /*notify*/, int /*width*/, int /*height*/)
+ {
+ if ( set_control_geometry ){
+ set_control_geometry = false;
+ //sliders[0].geometry(Point(50, height - 35*(0+2)), 180);
+ }
+ }
+ void fit_numerical(){
+ //Not implemented
+ }
+ void draw_numerical(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) {
+ draw_common(cr, notify, width, height, save, timer_stream);
+ init_numerical_ctrl_geom(cr, notify, width, height);
+ if(!mouses.empty()) {
+ cairo_pw_d2_sb(cr, stroke);
+ cairo_set_source_rgba (cr, 1., 0., 0., 1);
+ cairo_set_line_width (cr, .75);
+ cairo_stroke(cr);
+ }
+ }
+//-----------------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------------------
+
+ void init_help()
+ {
+ handles.clear();
+ //sliders.clear();
+ //toggles.clear();
+ }
+ void draw_help( cairo_t * /*cr*/, std::ostringstream *notify,
+ int /*width*/, int /*height*/, bool /*save*/, std::ostringstream */*timer_stream*/)
+ {
+ *notify << "Tighten:\n";
+ *notify << " move points toward local\n";
+ *notify << " mean square line (or circle).\n";
+ *notify << "Eat:\n";
+ *notify << " eat points like a pacman; at each step, move to the\n";
+ *notify << " average of the not already visited neighbor points.\n";
+ *notify << "Sort:\n";
+ *notify << " move from one point to the nearest one.\n";
+ *notify << " Stop at the first jump longer than sort-radius\n";
+ *notify << "Sort-bis:\n";
+ *notify << " move from one point to the nearest one,\n";
+ *notify << " unless it was 'already visited' (i.e. it is closer to\n";
+ *notify << " an already sorted point with distance < sort-radius.\n";
+ *notify << "Fuse: \n";
+ *notify << " start from first point, remove all points closer to it\n";
+ *notify << " than fuse-radius, move to the first one that is not, and repeat.\n";
+ *notify << "Curvature: \n";
+ *notify << " Compute the curvature at a given point from the circle fitting the\n";
+ *notify << " nearby points (just for fun: the stroke is the 'integral' of this\n";
+ *notify << " average curvature)\n";
+ *notify << "Numerical: \n";
+ *notify << " still waiting for someone to implement me ;-)\n\n";
+ *notify << std::endl;
+ }
+
+//-----------------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------------------
+
+public:
+ vector<Point> mouses;
+ int mouse_drag;
+ vector<Point> improved_mouses;
+ Piecewise<D2<SBasis > > stroke;
+
+ void mouse_pressed(GdkEventButton* e) override {
+ //toggle_events(toggles, e);
+ Toy::mouse_pressed(e);
+ if(!selected) {
+ mouse_drag = 1;
+ if (!(e->state & (GDK_SHIFT_MASK))){
+ mouses.clear();
+ }
+ }
+ }
+
+ void mouse_moved(GdkEventMotion* e) override {
+ if(mouse_drag) {
+ mouses.emplace_back(e->x, e->y);
+ redraw();
+ } else {
+ Toy::mouse_moved(e);
+ }
+ }
+
+ void mouse_released(GdkEventButton* e) override {
+ mouse_drag = 0;
+ if(!mouses.empty()) {
+ (this->*fit_f)();
+ }
+ Toy::mouse_released(e);
+ }
+
+ void init_menu()
+ {
+ handles.clear();
+ //sliders.clear();
+ //toggles.clear();
+ }
+ void draw_menu( cairo_t * cr, std::ostringstream *notify,
+ int /*width*/, int /*height*/, bool /*save*/, std::ostringstream */*timer_stream*/)
+ {
+ *notify << "Sketch some shape on canvas (press SHIFT to use several 'strokes')\n";
+ *notify << "Each menu below will transform your input.\n";
+ *notify << "Press 'Z' to make the result the new input\n";
+ *notify << " \n \n \n";
+ *notify << std::endl;
+ for (int i = SHOW_MENU; i < TOTAL_ITEMS; ++i)
+ {
+ *notify << " " << keys[i] << " - " << menu_items[i] << std::endl;
+ }
+ if(!mouses.empty()) {
+ cairo_move_to(cr, mouses[0]);
+ for(auto & mouse : mouses) {
+ cairo_line_to(cr, mouse);
+ }
+ for(auto & mouse : mouses) {
+ draw_cross(cr, mouse);
+ }
+ cairo_set_source_rgba (cr, 0., 0., 0., .25);
+ cairo_set_line_width (cr, 0.5);
+ cairo_stroke(cr);
+ }
+ }
+
+ void key_hit(GdkEventKey *e) override
+ {
+ char choice = std::toupper(e->keyval);
+ switch ( choice )
+ {
+ case 'A':
+ init_menu();
+ draw_f = &SketchFitterToy::draw_menu;
+ break;
+ case 'B':
+ init_tighten();
+ fit_f = &SketchFitterToy::fit_tighten;
+ draw_f = &SketchFitterToy::draw_tighten;
+ break;
+ case 'C':
+ init_eat();
+ fit_f = &SketchFitterToy::fit_eat;
+ draw_f = &SketchFitterToy::draw_eat;
+ break;
+ case 'D':
+ init_tighten_eat();
+ fit_f = &SketchFitterToy::fit_tighten_eat;
+ draw_f = &SketchFitterToy::draw_tighten_eat;
+ break;
+ case 'E':
+ init_sort();
+ fit_f = &SketchFitterToy::fit_sort;
+ draw_f = &SketchFitterToy::draw_sort;
+ break;
+ case 'F':
+ init_curvature();
+ fit_f = &SketchFitterToy::fit_curvature;
+ draw_f = &SketchFitterToy::draw_curvature;
+ break;
+ case 'G':
+ init_numerical();
+ fit_f = &SketchFitterToy::fit_numerical;
+ draw_f = &SketchFitterToy::draw_numerical;
+ break;
+ case 'H':
+ init_help();
+ draw_f = &SketchFitterToy::draw_help;
+ break;
+ case 'Z':
+ mouses = improved_mouses;
+ break;
+ }
+ redraw();
+ }
+
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream ) override
+ {
+ m_width = width;
+ m_height = height;
+ m_length = (m_width > m_height) ? m_width : m_height;
+ m_length *= 2;
+ (this->*draw_f)(cr, notify, width, height, save, timer_stream);
+ Toy::draw(cr, notify, width, height, save, timer_stream);
+ }
+
+
+ public:
+ SketchFitterToy()
+ {
+ srand ( time(NULL) );
+ sliders = std::vector<Slider>(TOTAL_SLIDERS, Slider(0., 1., 0, 0., ""));
+
+ sliders[TIGHTEN_NBHD_SIZE ] = Slider(0., 1., 0, 0.65, "neighborhood size");
+ sliders[TIGHTEN_NBHD_SIZE ].formatter(&exp_formatter);
+ sliders[TIGHTEN_ITERRATIONS] = Slider(0, 10, 1, 3, "iterrations");
+ sliders[EAT_NBHD_SIZE ] = Slider(0., 1., 0, 0.65, "eating neighborhood size");
+ sliders[EAT_NBHD_SIZE ].formatter(&exp_formatter);
+ sliders[SORT_RADIUS ] = Slider(0., 1., 0, 0.65, "sort radius");
+ sliders[SORT_RADIUS ].formatter(&exp_formatter);
+ sliders[FUSE_RADIUS ] = Slider(0., 1., 0, 0.65, "fuse radius");
+ sliders[FUSE_RADIUS ].formatter(&exp_formatter);
+ sliders[INTERPOLATE_RADIUS ] = Slider(0., 1., 0, 0.65, "intrepolate precision");
+ sliders[INTERPOLATE_RADIUS ].formatter(&exp_formatter);
+ sliders[CURVATURE_NBHD_SIZE] = Slider(0., 1., 0, 0.65, "curvature nbhd size");
+ sliders[CURVATURE_NBHD_SIZE].formatter(&exp_formatter);
+ sliders[POINT_CHOOSER ] = Slider(0, 100, 0, 50, "Point chooser(%)");
+
+ toggles = std::vector<Toggle>(TOTAL_TOGGLES, Toggle("",true));
+ toggles[DRAW_MOUSES] = Toggle("Draw mouses",true);
+ toggles[DRAW_IMPROVED_MOUSES] = Toggle("Draw new mouses",true);
+ toggles[DRAW_STROKE] = Toggle("Draw stroke",true);
+ toggles[TIGHTEN_USE_CIRCLE] = Toggle("Tighten: use circle",false);
+ toggles[SORT_BIS ] = Toggle("Sort: bis",false);
+ }
+
+ private:
+ typedef void (SketchFitterToy::* draw_func_t) (cairo_t*, std::ostringstream*, int, int, bool, std::ostringstream*);
+ draw_func_t draw_f;
+ typedef void (SketchFitterToy::* fit_func_t) ();
+ fit_func_t fit_f;
+ bool set_common_control_geometry;
+ bool set_control_geometry;
+ std::vector<Toggle> toggles;
+ std::vector<Slider> sliders;
+ double m_width, m_height, m_length;
+
+}; // end class SketchFitterToy
+
+
+const char* SketchFitterToy::menu_items[] =
+{
+ "show this menu",
+ "tighten",
+ "eat points step by step",
+ "tighten + eat",
+ "tighten + sort + fuse",
+ "curvature",
+ "numerical",
+ "help",
+};
+
+const char SketchFitterToy::keys[] =
+{
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new SketchFitterToy);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype = cpp:expandtab:shiftwidth = 4:tabstop = 8:softtabstop = 4:encoding = utf-8:textwidth = 99 :
diff --git a/src/3rdparty/2geom/src/toys/smash-intersector.cpp b/src/3rdparty/2geom/src/toys/smash-intersector.cpp
new file mode 100644
index 0000000..b01acfb
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/smash-intersector.cpp
@@ -0,0 +1,583 @@
+/*
+ * Diffeomorphism-based intersector: given two curves
+ * M(t)=(x(t),y(t)) and N(u)=(X(u),Y(u))
+ * and supposing M is a graph over the x-axis, we compute y(x) and solve
+ * Y(u) - y(X(u)) = 0
+ * to get the intersections of the two curves...
+ *
+ * Notice the result can be far from intuitive because of the choice we have
+ * to make to consider a curve as a graph over x or y. For instance the two
+ * branches of xy=eps are never close from this point of view (!)...
+ *
+ * Authors:
+ * J.-F. Barraud <jfbarraud at gmail.com>
+ * Copyright 2010 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/path.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-geometric.h>
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <cstdlib>
+#include <cstdio>
+#include <set>
+#include <vector>
+#include <algorithm>
+
+#include <2geom/orphan-code/intersection-by-smashing.h>
+#include "../2geom/orphan-code/intersection-by-smashing.cpp"
+
+using namespace Geom;
+
+#define VERBOSE 0
+
+static double exp_rescale(double x){ return ::pow(10, x);}
+std::string exp_formatter(double x){ return default_formatter(exp_rescale(x));}
+
+
+
+#if 0
+//useless here;
+Piecewise<D2<SBasis> > linearizeCusps( D2<SBasis> f, double tol){
+ D2<SBasis> df = derivative( f );
+ std::vector<Interval> xdoms = level_set( df[X], 0., tol);
+ std::vector<Interval> ydoms = level_set( df[Y], 0., tol);
+ std::vector<Interval> doms;
+ //TODO: use order!!
+ for ( unsigned i=0; i<xdoms.size(); i++ ){
+ OptInterval inter = xdoms[i];
+ for ( unsigned j=0; j<ydoms.size(); j++ ){
+ inter &= ydoms[j];
+ }
+ if (inter) {
+ doms.push_back( *inter );
+ }
+ }
+ Piecewise<D2<SBasis> > result;
+ if (doms.size() == 0 ) return Piecewise<D2<SBasis> >(f);
+ if (doms[0].min() > 0 ){
+ result.cuts.push_back( 0 );
+ result.cuts.push_back( doms[0].min() );
+ result.segs.push_back( portion( f, Interval( 0, doms[0].min() ) ) );
+ }
+ for ( unsigned i=0; i<doms.size(); i++ ){
+ Point a = result.segs.back().at1();
+ Point b = f.valueAt( doms[i].middle() );
+ Point c = f.valueAt( doms[i].max() );
+ result.cuts.push_back( doms[i].middle() );
+ result.segs.push_back( D2<SBasis>( Linear( a[X], b[X] ), Linear( a[Y], b[Y] ) ) );
+ result.cuts.push_back( doms[i].max() );
+ result.segs.push_back( D2<SBasis>( Linear( b[X], c[X] ), Linear( b[Y], c[Y] ) ) );
+ double t = ( i+1 == doms.size() )? 1 : doms[i+1].min();
+ result.cuts.push_back( t );
+ result.segs.push_back( portion( f, Interval( doms[i].max(), t ) ) );
+ }
+ return result;
+}
+#endif
+
+#if 0
+/* Computes the intersection of two sets given as (ordered) union intervals.
+ */
+std::vector<Interval> intersect( std::vector<Interval> const &a, std::vector<Interval> const &b){
+ std::vector<Interval> result;
+ //TODO: use order!
+ for (unsigned i=0; i < a.size(); i++){
+ for (unsigned j=0; j < b.size(); j++){
+ OptInterval c( a[i] );
+ c &= b[j];
+ if ( c ) {
+ result.push_back( *c );
+ }
+ }
+ }
+ return result;
+}
+
+/* Computes the top and bottom boundaries of the L_\infty neighborhood
+ * of a curve. The curve is supposed to be a graph over the x-axis.
+ */
+void computeLinfinityNeighborhood( D2<SBasis > const &f, double tol, D2<Piecewise<SBasis> > &topside, D2<Piecewise<SBasis> > &botside ){
+ double signx = ( f[X].at0() > f[X].at1() )? -1 : 1;
+ double signy = ( f[Y].at0() > f[Y].at1() )? -1 : 1;
+
+ Piecewise<D2<SBasis> > top, bot;
+ top = Piecewise<D2<SBasis> > (f);
+ top.cuts.insert( top.cuts.end(), 2);
+ top.segs.insert( top.segs.end(), D2<SBasis>(Linear( f[X].at1(), f[X].at1()+2*tol*signx),
+ Linear( f[Y].at1() )) );
+ bot = Piecewise<D2<SBasis> >(f);
+ bot.cuts.insert( bot.cuts.begin(), - 1 );
+ bot.segs.insert( bot.segs.begin(), D2<SBasis>(Linear( f[X].at0()-2*tol*signx, f[X].at0()),
+ Linear( f[Y].at0() )) );
+ top += Point(-tol*signx, tol);
+ bot += Point( tol*signx, -tol);
+
+ if ( signy < 0 ){
+ swap( top, bot );
+ top += Point( 0, 2*tol);
+ bot += Point( 0, -2*tol);
+ }
+ topside = make_cuts_independent(top);
+ botside = make_cuts_independent(bot);
+}
+
+
+/*Compute top and bottom boundaries of the L^infty nbhd of the graph of a *monotonic* function f.
+ * if f is increasing, it is given by [f(t-tol)-tol, f(t+tol)+tol].
+ * if not, it is [f(t+tol)-tol, f(t-tol)+tol].
+ */
+void computeLinfinityNeighborhood( Piecewise<SBasis> const &f, double tol, Piecewise<SBasis> &top, Piecewise<SBasis> &bot){
+ top = f + tol;
+ top.offsetDomain( - tol );
+ top.cuts.insert( top.cuts.end(), f.domain().max() + tol);
+ top.segs.insert( top.segs.end(), SBasis(Linear( f.lastValue() + tol )) );
+
+ bot = f - tol;
+ bot.offsetDomain( tol );
+ bot.cuts.insert( bot.cuts.begin(), f.domain().min() - tol);
+ bot.segs.insert( bot.segs.begin(), SBasis(Linear( f.firstValue() - tol )) );
+
+ if ( f.firstValue() > f.lastValue() ){
+ swap( top, bot );
+ top += 2*tol;
+ bot -= 2*tol;
+ }
+}
+
+std::vector<Interval> level_set( D2<SBasis> const &f, Rect region){
+ std::vector<Interval> x_in_reg = level_set( f[X], region[X] );
+ std::vector<Interval> y_in_reg = level_set( f[Y], region[Y] );
+ std::vector<Interval> result = intersect ( x_in_reg, y_in_reg );
+ return result;
+}
+
+void prolongateByConstants( Piecewise<SBasis> &f, double paddle_width ){
+ if ( f.size() == 0 ) return; //do we have a covention about the domain of empty pwsb?
+ f.cuts.insert( f.cuts.begin(), f.cuts.front() - paddle_width );
+ f.segs.insert( f.segs.begin(), SBasis( f.segs.front().at0() ) );
+ f.cuts.insert( f.cuts.end(), f.cuts.back() + paddle_width );
+ f.segs.insert( f.segs.end(), SBasis( f.segs.back().at1() ) );
+}
+
+
+
+/* Returns the intervals over which the curve keeps its slope
+ * in one of the 8 sectors delimited by x=0, y=0, y=x, y=-x.
+ * WARNING: both curves are supposed to be a graphs over x or y axis,
+ * and the smaller the slopes the better (typically <=45°).
+ */
+std::vector<std::pair<Interval, Interval> > smash_intersect( D2<SBasis> const &a, D2<SBasis> const &b,
+ double tol, cairo_t *cr , bool draw_more_stuff=false ){
+
+ std::vector<std::pair<Interval, Interval> > res;
+
+ // a and b or X and Y may have to be exchanged, so make local copies.
+ D2<SBasis> aa = a;
+ D2<SBasis> bb = b;
+ bool swapresult = false;
+ bool swapcoord = false;//debug only!
+
+ if ( draw_more_stuff ){
+ cairo_set_line_width (cr, 3);
+ cairo_set_source_rgba(cr, .5, .9, .7, 1 );
+ cairo_d2_sb(cr, aa);
+ cairo_d2_sb(cr, bb);
+ cairo_stroke(cr);
+ }
+
+#if 1
+ //if the (enlarged) bounding boxes don't intersect, stop.
+ if ( !draw_more_stuff ){
+ OptRect abounds = bounds_fast( a );
+ OptRect bbounds = bounds_fast( b );
+ if ( !abounds || !bbounds ) return res;
+ abounds->expandBy(tol);
+ if ( !(abounds->intersects(*bbounds))){
+ return res;
+ }
+ }
+#endif
+
+ //Choose the best curve to be re-parametrized by x or y values.
+ OptRect dabounds = bounds_exact(derivative(a));
+ OptRect dbbounds = bounds_exact(derivative(b));
+ if ( dbbounds->min().length() > dabounds->min().length() ){
+ aa=b;
+ bb=a;
+ swap( dabounds, dbbounds );
+ swapresult = true;
+ }
+
+ //Choose the best coordinate to use as new parameter
+ double dxmin = std::min( abs((*dabounds)[X].max()), abs((*dabounds)[X].min()) );
+ double dymin = std::min( abs((*dabounds)[Y].max()), abs((*dabounds)[Y].min()) );
+ if ( (*dabounds)[X].max()*(*dabounds)[X].min() < 0 ) dxmin=0;
+ if ( (*dabounds)[Y].max()*(*dabounds)[Y].min() < 0 ) dymin=0;
+ assert (dxmin>=0 && dymin>=0);
+
+ if (dxmin < dymin) {
+ aa = D2<SBasis>( aa[Y], aa[X] );
+ bb = D2<SBasis>( bb[Y], bb[X] );
+ swapcoord = true;
+ }
+
+ //re-parametrize aa by the value of x.
+ Interval x_range_strict( aa[X].at0(), aa[X].at1() );
+ Piecewise<SBasis> y_of_x = pw_compose_inverse(aa[Y],aa[X], 2, 1e-5);
+
+ //Compute top and bottom boundaries of the L^infty nbhd of aa.
+ Piecewise<SBasis> top_ay, bot_ay;
+ computeLinfinityNeighborhood( y_of_x, tol, top_ay, bot_ay);
+
+ Interval ax_range = top_ay.domain();//i.e. aa[X] domain ewpanded by tol.
+
+ if ( draw_more_stuff ){
+ Piecewise<SBasis> dbg_x( SBasis( Linear( top_ay.domain().min(), top_ay.domain().max() ) ) );
+ dbg_x.setDomain( top_ay.domain() );
+ D2<Piecewise<SBasis> > dbg_side ( Piecewise<SBasis>( SBasis( Linear( 0 ) ) ),
+ Piecewise<SBasis>( SBasis( Linear( 0, 2*tol) ) ) );
+
+ D2<Piecewise<SBasis> > dbg_rgn;
+ unsigned h = ( swapcoord ) ? Y : X;
+ dbg_rgn[h].concat ( dbg_x );
+ dbg_rgn[h].concat ( dbg_side[X] + dbg_x.lastValue() );
+ dbg_rgn[h].concat ( reverse(dbg_x) );
+ dbg_rgn[h].concat ( dbg_side[X] + dbg_x.firstValue() );
+
+ dbg_rgn[1-h].concat ( bot_ay );
+ dbg_rgn[1-h].concat ( dbg_side[Y] + bot_ay.lastValue() );
+ dbg_rgn[1-h].concat ( reverse(top_ay) );
+ dbg_rgn[1-h].concat ( reverse( dbg_side[Y] ) + bot_ay.firstValue() );
+
+ cairo_set_line_width (cr, 1.);
+ cairo_set_source_rgba(cr, 0., 1., 0., .75 );
+ cairo_d2_pw_sb(cr, dbg_rgn );
+ cairo_stroke(cr);
+
+ D2<SBasis> bbb = bb;
+ if ( swapcoord ) swap( bbb[X], bbb[Y] );
+ //Piecewise<D2<SBasis> > dbg_rgnB = neighborhood( bbb, tol );
+ D2<Piecewise<SBasis> > dbg_topB, dbg_botB;
+ computeLinfinityNeighborhood( bbb, tol, dbg_topB, dbg_botB );
+ cairo_set_line_width (cr, 1.);
+ cairo_set_source_rgba(cr, .2, 8., .2, .4 );
+// cairo_pw_d2_sb(cr, dbg_rgnB );
+ cairo_d2_pw_sb(cr, dbg_topB );
+ cairo_d2_pw_sb(cr, dbg_botB );
+ cairo_stroke(cr);
+ }
+
+ std::vector<Interval> bx_in_ax_range = level_set(bb[X], ax_range );
+
+ // find times when bb is in the neighborhood of aa.
+ std::vector<Interval> tbs;
+ for (unsigned i=0; i<bx_in_ax_range.size(); i++){
+ D2<Piecewise<SBasis> > bb_in;
+ bb_in[X] = Piecewise<SBasis> ( portion( bb[X], bx_in_ax_range[i] ) );
+ bb_in[Y] = Piecewise<SBasis> ( portion( bb[Y], bx_in_ax_range[i]) );
+ bb_in[X].setDomain( bx_in_ax_range[i] );
+ bb_in[Y].setDomain( bx_in_ax_range[i] );
+
+ Piecewise<SBasis> h;
+ Interval level;
+ h = bb_in[Y] - compose( top_ay, bb_in[X] );
+ level = Interval( -infinity(), 0 );
+ std::vector<Interval> rts_lo = level_set( h, level);
+ h = bb_in[Y] - compose( bot_ay, bb_in[X] );
+ level = Interval( 0, infinity());
+ std::vector<Interval> rts_hi = level_set( h, level);
+
+ std::vector<Interval> rts = intersect( rts_lo, rts_hi );
+ tbs.insert(tbs.end(), rts.begin(), rts.end() );
+ }
+
+ std::vector<std::pair<Interval, Interval> > result(tbs.size(),std::pair<Interval,Interval>());
+
+ /* for each solution I, find times when aa is in the neighborhood of bb(I).
+ * (Note: the preimage of bb[X](I) by aa[X], enlarged by tol, is a good approximation of this:
+ * it would give points in the 2*tol neighborhood of bb (if the slope of aa is never more than 1).
+ * + faster computation.
+ * - implies little jumps depending on the subdivision of the input curve into monotonic pieces
+ * and on the choice of preferred axis. If noticeable, these jumps would feel random to the user :-(
+ */
+ for (unsigned j=0; j<tbs.size(); j++){
+ result[j].second = tbs[j];
+ std::vector<Interval> tas;
+ Piecewise<SBasis> fat_y_of_x = y_of_x;
+ prolongateByConstants( fat_y_of_x, 100*(1+tol) );
+
+ D2<Piecewise<SBasis> > top_b, bot_b;
+ D2<SBasis> bbj = portion( bb, tbs[j] );
+ computeLinfinityNeighborhood( bbj, tol, top_b, bot_b );
+
+ Piecewise<SBasis> h;
+ Interval level;
+ h = top_b[Y] - compose( fat_y_of_x, top_b[X] );
+ level = Interval( +infinity(), 0 );
+ std::vector<Interval> rts_top = level_set( h, level);
+ for (unsigned idx=0; idx < rts_top.size(); idx++){
+ rts_top[idx] = Interval( top_b[X].valueAt( rts_top[idx].min() ),
+ top_b[X].valueAt( rts_top[idx].max() ) );
+ }
+ assert( rts_top.size() == 1 );
+
+ h = bot_b[Y] - compose( fat_y_of_x, bot_b[X] );
+ level = Interval( 0, -infinity());
+ std::vector<Interval> rts_bot = level_set( h, level);
+ for (unsigned idx=0; idx < rts_bot.size(); idx++){
+ rts_bot[idx] = Interval( bot_b[X].valueAt( rts_bot[idx].min() ),
+ bot_b[X].valueAt( rts_bot[idx].max() ) );
+ }
+ assert( rts_bot.size() == 1 );
+
+#if VERBOSE
+ printf("range(aa[X]) = [%f, %f];\n", y_of_x.domain().min(), y_of_x.domain().max());
+ printf("range(bbj[X]) = [%f, %f]; tol= %f\n", bbj[X].at0(), bbj[X].at1(), tol);
+
+ printf("rts_top = ");
+ for (unsigned dbgi=0; dbgi<rts_top.size(); dbgi++){
+ printf("[%f,%f]U", rts_top[dbgi].min(), rts_top[dbgi].max() );
+ }
+ printf("\n");
+ printf("rts_bot = ");
+ for (unsigned dbgi=0; dbgi<rts_bot.size(); dbgi++){
+ printf("[%f,%f]U", rts_bot[dbgi].min(), rts_bot[dbgi].max() );
+ }
+ printf("\n");
+#endif
+ rts_top = intersect( rts_top, rts_bot );
+#if VERBOSE
+ printf("intersection = ");
+ for (unsigned dbgi=0; dbgi<rts_top.size(); dbgi++){
+ printf("[%f,%f]U", rts_top[dbgi].min(), rts_top[dbgi].max() );
+ }
+ printf("\n\n");
+
+ if (rts_top.size() != 1){
+ printf("!!!!!!!!!!!!!!!!!!!!!!\n!!!!!!!!!!!!!!!!!!!!!!\n");
+ rts_top[0].unionWith( rts_top[1] );
+ assert( false );
+ }
+#endif
+ assert (rts_top.size() == 1);
+ Interval x_dom = rts_top[0];
+
+ if ( x_dom.max() <= x_range_strict.min() ){
+ tas.push_back( Interval ( ( aa[X].at0() < aa[X].at1() ) ? 0 : 1 ) );
+ }else if ( x_dom.min() >= x_range_strict.max() ){
+ tas.push_back( Interval ( ( aa[X].at0() < aa[X].at1() ) ? 1 : 0 ) );
+ }else{
+ tas = level_set(aa[X], x_dom );
+ }
+
+#if VERBOSE
+ if ( tas.size() != 1 ){
+ printf("Error: preimage of [%f, %f] by x:[0,1]->[%f, %f] is ",
+ x_dom.min(), x_dom.max(), x_range_strict.min(), x_range_strict.max());
+ if ( tas.size() == 0 ){
+ printf( "empty.\n");
+ }else{
+ printf("\n [%f,%f]", tas[0].min(), tas[0].max() );
+ for (unsigned toto=1; toto<tas.size(); toto++){
+ printf(" U [%f,%f]", tas[toto].min(), tas[toto].max() );
+ }
+ }
+ }
+#endif
+ assert( tas.size()==1 );
+ result[j].first = tas.front();
+ }
+
+ if (swapresult) {
+ for ( unsigned i=0; i<result.size(); i++){
+ Interval temp = result[i].first;
+ result[i].first = result[i].second;
+ result[i].second = temp;
+ }
+ }
+ return result;
+}
+
+#endif
+
+class Intersector : public Toy
+{
+ private:
+ void draw( cairo_t *cr, std::ostringstream *notify,
+ int width, int height, bool save, std::ostringstream *timer_stream) override
+ {
+ double tol = exp_rescale(slider.value());
+ D2<SBasis> A = handles_to_sbasis(psh.pts.begin(), A_bez_ord-1);
+ D2<SBasis> B = handles_to_sbasis(psh.pts.begin()+A_bez_ord, B_bez_ord-1);
+ cairo_set_line_width (cr, .8);
+ cairo_set_source_rgba(cr,0.,0.,0.,.6);
+ cairo_d2_sb(cr, A);
+ cairo_d2_sb(cr, B);
+ cairo_stroke(cr);
+
+ Rect tolbytol( anchor.pos, anchor.pos );
+ tolbytol.expandBy( tol );
+ cairo_rectangle(cr, tolbytol);
+ cairo_stroke(cr);
+/*
+ Piecewise<D2<SBasis> > smthA = linearizeCusps(A+Point(0,10), tol);
+ cairo_set_line_width (cr, 1.);
+ cairo_set_source_rgba(cr, 1., 0., 1., 1. );
+ cairo_pw_d2_sb(cr, smthA);
+ cairo_stroke(cr);
+*/
+
+ std::vector<Interval> Acuts = monotonicSplit(A);
+ std::vector<Interval> Bcuts = monotonicSplit(B);
+
+#if 0
+ for (unsigned i=0; i<Acuts.size(); i++){
+ D2<SBasis> Ai = portion( A, Acuts[i]);
+ cairo_set_line_width (cr, .2);
+ cairo_set_source_rgba(cr, 0., 0., 0., 1. );
+ draw_cross(cr, Ai.at0());
+ cairo_stroke(cr);
+ for (unsigned j=0; j<Bcuts.size(); j++){
+ std::vector<std::pair<Interval, Interval> > my_intersections;
+ D2<SBasis> Bj = portion( B, Bcuts[j]);
+ cairo_set_line_width (cr, .2);
+ cairo_set_source_rgba(cr, 0., 0., 0., 1. );
+ draw_cross(cr, Bj.at0());
+ cairo_stroke(cr);
+ }
+ }
+#endif
+
+ std::vector<SmashIntersection> my_intersections;
+ my_intersections = smash_intersect( A, B, tol );
+
+ for (auto & my_intersection : my_intersections){
+ cairo_set_line_width (cr, 2.5);
+ cairo_set_source_rgba(cr, 1., 0., 0., .8 );
+ cairo_d2_sb(cr, portion( A, my_intersection.times[X]));
+ cairo_stroke(cr);
+ cairo_set_line_width (cr, 2.5);
+ cairo_set_source_rgba(cr, 0., 0., 1., .8 );
+ cairo_d2_sb(cr, portion( B, my_intersection.times[Y]));
+ cairo_stroke(cr);
+ }
+#if 0
+
+ unsigned apiece( slidera.value()/100. * Acuts.size() );
+ unsigned bpiece( sliderb.value()/100. * Bcuts.size() );
+
+
+ for (unsigned i=0; i<Acuts.size(); i++){
+ D2<SBasis> Ai = portion( A, Acuts[i]);
+ for (unsigned j=0; j<Bcuts.size(); j++){
+ if ( toggle.on && (i != apiece || j != bpiece) ) continue;
+
+ std::vector<SmashIntersection> my_intersections;
+ D2<SBasis> Bj = portion( B, Bcuts[j]);
+ bool draw_more = toggle.on && i == apiece && j == bpiece;
+// my_intersections = smash_intersect( Ai, Bj, tol, cr, draw_more );
+ my_intersections = monotonic_smash_intersect( Ai, Bj, tol );
+
+ for (unsigned k=0; k<my_intersections.size(); k++){
+ cairo_set_line_width (cr, 2.5);
+ cairo_set_source_rgba(cr, 1., 0., 0., .8 );
+ cairo_d2_sb(cr, portion( Ai, my_intersections[k].times[X]));
+ cairo_stroke(cr);
+ cairo_set_line_width (cr, 2.5);
+ cairo_set_source_rgba(cr, 0., 0., 1., .8 );
+ cairo_d2_sb(cr, portion( Bj, my_intersections[k].times[Y]));
+ cairo_stroke(cr);
+ }
+ }
+ }
+#endif
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ Intersector(unsigned int _A_bez_ord, unsigned int _B_bez_ord)
+ : A_bez_ord(_A_bez_ord), B_bez_ord(_B_bez_ord)
+ {
+ unsigned int total_handles = A_bez_ord + B_bez_ord;
+ for ( unsigned int i = 0; i < total_handles; ++i )
+ psh.push_back(Geom::Point(uniform()*400, uniform()*400));
+ handles.push_back(&psh);
+ slider = Slider(-4, 2, 0, 1.2, "tolerance");
+ slider.geometry(Point(30, 20), 250);
+ slider.formatter(&exp_formatter);
+ handles.push_back(&slider);
+ slidera = Slider(0, 100, 1, 0., "piece on A");
+ slidera.geometry(Point(300, 50), 250);
+ handles.push_back(&slidera);
+ sliderb = Slider(0, 100, 1, 0., "piece on B");
+ sliderb.geometry(Point(300, 80), 250);
+ handles.push_back(&sliderb);
+ toggle = Toggle( Rect(Point(300,10), Point(440,30)), "Piece by piece", false );
+ handles.push_back(&toggle);
+ anchor = PointHandle ( Point(100, 100 ) );
+ handles.push_back(&anchor);
+ }
+
+ private:
+ unsigned int A_bez_ord;
+ unsigned int B_bez_ord;
+ PointSetHandle psh;
+ PointHandle anchor;
+ Slider slider,slidera,sliderb;
+ Toggle toggle;
+};
+
+
+int main(int argc, char **argv)
+{
+ unsigned int A_bez_ord=4;
+ unsigned int B_bez_ord=4;
+ if(argc > 2)
+ sscanf(argv[2], "%d", &B_bez_ord);
+ if(argc > 1)
+ sscanf(argv[1], "%d", &A_bez_ord);
+
+ init( argc, argv, new Intersector(A_bez_ord, B_bez_ord));
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/squiggles.cpp b/src/3rdparty/2geom/src/toys/squiggles.cpp
new file mode 100644
index 0000000..eef33ad
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/squiggles.cpp
@@ -0,0 +1,216 @@
+#include <2geom/piecewise.h>
+#include <2geom/sbasis.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/sbasis-math.h>
+#include <2geom/sbasis-geometric.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+#include <vector>
+
+#define NB_CTL_PTS 6
+#define K_SCALE .002
+
+using namespace Geom;
+using namespace std;
+
+void cairo_pw(cairo_t *cr, Piecewise<SBasis> p) {
+ for(unsigned i = 0; i < p.size(); i++) {
+ D2<SBasis> B;
+ B[0] = Linear(p.cuts[i], p.cuts[i+1]);
+ B[1] = Linear(150) + p[i];
+ cairo_d2_sb(cr, B);
+ }
+}
+
+void cairo_horiz(cairo_t *cr, double y, vector<double> p) {
+ for(double i : p) {
+ cairo_move_to(cr, i, y);
+ cairo_rel_line_to(cr, 0, 10);
+ }
+}
+
+void cairo_vert(cairo_t *cr, double x, vector<double> p) {
+ for(double i : p) {
+ cairo_move_to(cr, x, i);
+ cairo_rel_line_to(cr, 10, 0);
+ }
+}
+
+/*
+Piecewise<SBasis> interpolate(std::vector<double> values, std::vector<double> times){
+ assert ( values.size() == times.size() );
+ if ( values.size() == 0 ) return Piecewise<SBasis>();
+ if ( values.size() == 1 ) return Piecewise<SBasis>(values[0]);//what about time??
+
+ SBasis bump_in = Linear(0,1);//Enough for piecewise linear interpolation.
+ //bump_in.push_back(Linear(-1,1));//uncomment for C^1 interpolation
+ SBasis bump_out = Linear(1,0);
+ //bump_out.push_back(Linear(1,-1));
+
+ Piecewise<SBasis> result;
+ result.cuts.push_back(times[0]);
+ for (unsigned i = 0; i<values.size()-1; i++){
+ result.push(bump_out*values[i]+bump_in*values[i+1],times[i+1]);
+ }
+ return result;
+}
+*/
+
+//#include <toys/pwsbhandle.cpp // FIXME: This looks like it may give problems later, (including a .cpp file)
+
+class Squiggles: public Toy {
+ PointSetHandle hand;
+ unsigned current_ctl_pt;
+ Point current_pos;
+ Point current_dir;
+ std::vector<double> curvatures;
+ std::vector<double> times;
+ Piecewise<D2<SBasis> > curve;
+ double tot_length;
+ int mode; //0=set curvature, 1=set curv.+rotation, 2=translate, 3=slide time.
+
+ void mouse_moved(GdkEventMotion* e) override{
+ mode = 0;
+ if((e->state & (GDK_SHIFT_MASK)) &&
+ (e->state & (GDK_CONTROL_MASK))) {
+ mode = 3;
+ }else if(e->state & (GDK_CONTROL_MASK)) {
+ mode = 1;
+ }else if(e->state & (GDK_SHIFT_MASK)) {
+ mode = 2;
+ }
+ Toy::mouse_moved(e);
+ }
+
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_source_rgba (cr, 0., 0., 0., 1);
+ cairo_set_line_width (cr, 1);
+
+ *notify << "Drag to set curvature,\n";
+ *notify << "SHIFT-Drag to move curve,\n";
+ *notify << "CTRL-Drag to rotate,\n";
+ *notify << "SHIFT-CTRL-Drag to slide handles.";
+ //Get user input
+ if (mouse_down && selected) {
+ for(unsigned i = 0; i < handles.size(); i++) {
+ if(selected == handles[i]){
+ current_ctl_pt = i;
+ break;
+ }
+ }
+ double time = times[current_ctl_pt];
+ current_pos = curve.valueAt(time);
+ current_dir = derivative(curve).valueAt(time);//*This should be a unit vector!*
+ Point hdle = dynamic_cast<PointHandle*>(handles[current_ctl_pt])->pos;
+ if (mode == 0){
+ curvatures[current_ctl_pt] = cross(hdle - current_pos,current_dir)*K_SCALE;
+ }else if (mode == 1){//Rotate
+ double sign = ( curvatures[current_ctl_pt]>=0 ? 1 : -1 );
+ //curvatures[current_ctl_pt] = sign*L2(hdle - current_pos)*K_SCALE;
+ current_dir = -sign*unit_vector(rot90(hdle - current_pos));
+ }else if (mode == 2){//Translate
+ Point old_pos = current_pos + curvatures[current_ctl_pt]/K_SCALE*rot90(current_dir);
+ current_pos += hdle - old_pos;
+ curve += hdle - old_pos;
+ }else if (mode == 3){//Slide time
+ Point old_pos = current_pos + curvatures[current_ctl_pt]/K_SCALE*rot90(current_dir);
+ double delta = dot(hdle - old_pos,current_dir);
+ double epsilon = 2;
+ if (current_ctl_pt>0 && times[current_ctl_pt]+delta < times[current_ctl_pt-1]+epsilon){
+ delta = times[current_ctl_pt-1] + epsilon - times[current_ctl_pt];
+ }
+ if (current_ctl_pt<times.size()-1 && times[current_ctl_pt]+delta > times[current_ctl_pt+1]-epsilon){
+ delta = times[current_ctl_pt+1] - epsilon - times[current_ctl_pt];
+ }
+ times[current_ctl_pt] += delta;
+ current_pos += delta*current_dir;
+ }
+ }
+
+ //Compute new curve
+
+ Piecewise<SBasis> curvature = interpolate( times, curvatures , 1);
+ Piecewise<SBasis> alpha = integral(curvature);
+ Piecewise<D2<SBasis> > v = sectionize(tan2(alpha));
+ curve = integral(v)+Point(100,100);
+
+ //transform to keep current point in place
+ double time = times[current_ctl_pt];
+ Point new_pos = curve.valueAt(time);
+ Point new_dir = v.valueAt(time);
+ Affine mat1 = Affine( new_dir[X], new_dir[Y], -new_dir[Y], new_dir[X], new_pos[X], new_pos[Y]);
+ Affine mat2 = Affine(current_dir[X],current_dir[Y],-current_dir[Y],current_dir[X],current_pos[X],current_pos[Y]);
+ mat1 = mat1.inverse()*mat2;
+ curve = curve*mat1;
+ v = v*mat1.withoutTranslation();
+
+ //update handles
+ cairo_save(cr);
+ double dashes[2] = {3, 2};
+ cairo_set_dash(cr, dashes, 2, 0);
+ cairo_set_line_width(cr, .5);
+ cairo_set_source_rgba (cr, 0., 0., 0.5, 1);
+ for(unsigned i = 0; i < NB_CTL_PTS; i++) {
+ Point m = curve.valueAt(times[i]);
+ dynamic_cast<PointHandle*>(handles[i])->pos = m +
+ curvatures[i]/K_SCALE*rot90(v.valueAt(times[i]));
+ draw_handle(cr, m);
+ cairo_move_to(cr, m);
+ cairo_line_to(cr, dynamic_cast<PointHandle*>(handles[i])->pos);
+ }
+
+#if 0
+ D2<Piecewise<SBasis> > graphe;
+ graphe[X] = Piecewise<SBasis>(Linear(100,300));
+ graphe[Y] = -curvature/K_SCALE+400;
+ graphe[X].setDomain(graphe[Y].domain());
+ cairo_d2_pw_sb(cr, graphe);
+#endif
+
+ cairo_stroke(cr);
+ cairo_restore(cr);
+
+ cairo_pw_d2_sb(cr, curve);
+ cairo_set_source_rgba (cr, 0., 0., 0, 1);
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ bool should_draw_numbers() override { return false; }
+
+public:
+ Squiggles () {
+ current_ctl_pt = 0;
+ current_dir = Point(1,0);
+ current_pos = Point(100,100);
+ tot_length = 300;
+
+ curve = Piecewise<D2<SBasis> >(D2<SBasis>(SBasis(100.,300.),SBasis(100.,100.)));
+ for(unsigned i = 0; i < NB_CTL_PTS; i++) {
+ curvatures.push_back(0);
+ times.push_back(i*tot_length/(NB_CTL_PTS-1));
+ PointHandle *pt_hdle = new PointHandle(Geom::Point(100+i*tot_length/(NB_CTL_PTS-1), 100.));
+ handles.push_back(pt_hdle);
+ }
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new Squiggles());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/star-gap.hand b/src/3rdparty/2geom/src/toys/star-gap.hand
new file mode 100644
index 0000000..6506970
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/star-gap.hand
@@ -0,0 +1 @@
+300.000000 300.000000
diff --git a/src/3rdparty/2geom/src/toys/svgd/2rect.svgd b/src/3rdparty/2geom/src/toys/svgd/2rect.svgd
new file mode 100644
index 0000000..2d8cdc2
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/2rect.svgd
@@ -0,0 +1 @@
+M 111.42857,92.362183 L 494.28572,92.362183 L 494.28572,275.21933 L 111.42857,275.21933 L 111.42857,92.362183 zM 217.14285,192.36218 L 660,192.36218 L 660,389.50504 L 217.14285,389.50504 L 217.14285,192.36218 z \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/toys/svgd/4rect.svgd b/src/3rdparty/2geom/src/toys/svgd/4rect.svgd
new file mode 100644
index 0000000..af15296
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/4rect.svgd
@@ -0,0 +1 @@
+M 92.73692,69.488149 L 412.73692,69.488149 L 412.73692,266.63103 L 92.73692,266.63103 L 92.73692,69.488149 z M 430.12021,178.5218 L 564.40593,178.5218 L 564.40593,275.66466 L 430.12021,275.66466 L 430.12021,178.5218 z M 430.12021,286.66478 L 564.40593,286.66478 L 564.40593,383.80764 L 430.12021,383.80764 L 430.12021,286.66478 z M 430.12021,69.488149 L 564.40593,69.488149 L 564.40593,166.63101 L 430.12021,166.63101 L 430.12021,69.488149 z \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/toys/svgd/ant.svgd b/src/3rdparty/2geom/src/toys/svgd/ant.svgd
new file mode 100644
index 0000000..a92d01a
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/ant.svgd
@@ -0,0 +1 @@
+M 60.03,2.56 C 58.71,2.43 57.16,15.65 57.09,16.44 C 56.11,27.39 60.84,32.53 60.56,34.03 C 60.29,35.53 60.27,41.43 64.63,47.53 C 63.29,48.91 62.08,50.27 61.0,51.63 C 58.67,47.53 55.81,43.15 53.78,41.13 C 51.65,38.99 42.4,33.78 40.5,33.09 C 39.83,32.85 31.78,24.38 30.88,25.28 C 29.97,26.19 37.86,34.75 38.66,34.63 C 41.17,38.09 51.17,45.0 51.91,46.06 C 52.64,47.13 57.55,56.07 57.59,56.13 C 55.72,59.04 55.17,61.1 54.47,63.59 C 51.13,60.05 41.55,57.28 34.66,57.28 C 28.94,57.28 19.55,57.14 17.81,57.44 C 11.32,58.55 0.64,71.64 2.13,73.13 C 3.3,74.3 11.14,60.86 17.63,59.75 C 19.5,59.43 34.08,62.18 36.25,62.03 C 38.42,61.88 45.45,65.59 49.38,66.16 C 45.65,65.36 41.81,66.1 38.66,69.25 C 26.96,80.95 28.35,91.77 32.88,96.41 C 32.88,96.41 32.87,96.43 32.88,96.44 C 32.89,96.45 32.9,96.46 32.91,96.47 C 32.92,96.48 32.93,96.49 32.94,96.5 C 32.95,96.51 32.96,96.52 32.97,96.53 C 37.61,101.05 48.41,102.4 60.09,90.72 C 63.03,87.79 63.88,84.23 63.34,80.75 C 64.22,84.76 67.48,91.09 67.34,93.13 C 67.2,95.3 69.91,109.84 69.59,111.72 C 68.49,118.21 55.04,126.07 56.22,127.25 C 57.7,128.73 70.8,118.05 71.91,111.56 C 72.2,109.82 72.06,100.44 72.06,94.72 C 72.06,87.82 69.3,78.25 65.75,74.91 C 68.24,74.21 70.33,73.62 73.25,71.75 C 73.3,71.79 82.21,76.73 83.28,77.47 C 84.35,78.21 91.25,88.21 94.72,90.72 C 94.59,91.52 103.16,99.41 104.06,98.5 C 104.97,97.6 96.49,89.51 96.25,88.84 C 95.57,86.94 90.39,77.73 88.25,75.59 C 86.22,73.57 81.81,70.68 77.72,68.34 C 79.07,67.27 80.46,66.09 81.84,64.75 C 87.95,69.1 93.85,69.09 95.34,68.81 C 96.84,68.54 101.98,73.27 112.94,72.28 C 113.72,72.21 126.95,70.66 126.81,69.34 C 126.65,67.79 114.41,69.33 113.59,69.72 C 111.42,68.99 99.94,66.69 98.78,66.19 C 97.62,65.68 91.92,62.98 84.78,61.19 C 86.71,57.89 86.76,54.39 85.59,51.34 C 88.51,54.25 91.2,55.8 94.41,52.59 C 97.92,49.08 100.48,45.17 101.94,41.44 C 106.66,42.93 110.64,43.45 111.56,43.88 C 112.49,44.3 113.68,43.63 114.75,40.0 C 116.5,34.03 117.56,28.4 116.88,28.09 C 116.19,27.79 110.98,37.62 111.34,41.22 C 108.58,39.29 106.28,38.51 102.97,37.91 C 103.76,34.04 103.18,30.66 101.03,28.44 C 101.03,28.43 101.04,28.41 101.03,28.41 C 101.01,28.39 100.99,28.36 100.97,28.34 C 98.75,26.18 95.31,25.58 91.44,26.38 C 90.83,23.07 90.08,20.76 88.16,18.0 C 91.75,18.37 101.59,13.18 101.28,12.5 C 100.97,11.82 95.35,12.84 89.38,14.59 C 85.74,15.66 85.07,16.89 85.5,17.81 C 85.93,18.74 86.45,22.72 87.94,27.44 C 84.21,28.89 80.29,31.46 76.78,34.97 C 73.58,38.17 75.12,40.87 78.03,43.78 C 74.98,42.62 71.48,42.67 68.19,44.59 C 66.4,37.45 63.66,31.75 63.16,30.59 C 62.65,29.43 60.39,17.92 59.66,15.75 C 60.05,14.94 61.59,2.72 60.03,2.56 z \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/toys/svgd/arcs.svgd b/src/3rdparty/2geom/src/toys/svgd/arcs.svgd
new file mode 100644
index 0000000..8a69290
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/arcs.svgd
@@ -0,0 +1 @@
+M50,50 l 50,-25 a25,25 -30 0,1 50,-25 l 50,-25 a25,50 -30 0,1 50,-25 l 50,-25 a25,75 -30 0,1 50,-25 l 50,-25 a25,100 -30 0,1 50,-25 l 50,-25
diff --git a/src/3rdparty/2geom/src/toys/svgd/banana.svgd b/src/3rdparty/2geom/src/toys/svgd/banana.svgd
new file mode 100644
index 0000000..37a385e
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/banana.svgd
@@ -0,0 +1 @@
+M 265.71429,158.07648 C 190.6809,177.20365 122.07669,234.71591 104.63056,312.25563 C 77.156999,399.83651 70.794763,500.27985 114.77866,583.69036 C 144.53063,634.44937 199.36676,669.20393 257.74302,675.53709 C 270.81001,702.04856 314.06907,671.3079 286.33697,654.18295 C 255.1688,600.99542 216.46623,548.3017 211.13947,484.83476 C 202.31209,421.03768 205.02251,351.85571 239.06833,295.30186 C 257.00587,263.44474 279.73092,234.67917 301.98406,205.79097 C 300.02661,180.33683 358.06043,134.08979 326.58199,129.37189 C 312.92978,127.95692 277.30454,151.73686 265.71429,158.07648 z
diff --git a/src/3rdparty/2geom/src/toys/svgd/cat.svgd b/src/3rdparty/2geom/src/toys/svgd/cat.svgd
new file mode 100644
index 0000000..557f13d
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/cat.svgd
@@ -0,0 +1 @@
+M 153.04,308.88 C 67.07,342.82 57.97,453.92 130.83,506.41 C 245.3,553.77 426.19,542.77 445.18,392.24 C 446.78,351.09 426.76,300.40 382.24,291.24 M 338.24,282.24 C 285.72,273.19442 231.95477,285.06235 181.03,297.88016 M 308.58,391.49 C 327.09,380.94 348.61,376.39128 369.74,375.64253 M 118.31907,386.96814 C 134.17,392.253 150.03,397.53 165.88,402.82 M 206.65,418.65109 C 211.53912,410.76 255.11,411.00542 258.75668,418.65109 C 262.66,426.86 238.25,466.21 229.31,466.21866 C 220.88,466.21866 201.72358,426.62348 206.65,418.65109 z M 270.08,465.68 C 345.58,465.84 421.09,466.04 496.59,466.21 M 276.87,445.83 C 346.34,439.03 415.80,432.24 485.26,425.44 M 202.12,459.95 C 159.09,469.59 116.05,479.23 73.01,488.86 M 196.66,443.29 C 148.65,444.89 100.64,446.49 52.63,448.09769 M 205.04,480.06 C 221.65,480.065 238.26,480.06 254.87,480.06 M 95.66,350.69 C 91.13,315.21 86.60,279.72 82.07,244.23 C 133.11,252.96 156.26,279.88 190.80,312.19 M 338.03,289.53 C 360.08,241.80 427.37,231.27 452.87,221.21 C 450.44,257.57 440.48,289.67 428.64,323.51 M 196.76,290.19 C 201.26,252.13 242.44,234.63 272.70,219.28 C 417.48,158.60 583.94,152.87 733.23,201.03 C 853.85,234.84 966.06,304.90 931.20,445.90 C 850.68,533.28 734.22,618.52 613.28,632.83 C 572.66,633.17 536.29,602.83 578.98,592.96 C 664.47,600.17 743.16,553.80 807.85,502.83 C 831.31,480.70 855.70,455.39 863.54,423.18 M 742.13,302.52 C 696.70,300.78 645.69,308.71 616,347.22 C 578.46,386.94 583.35,447.38 587.45,497.88 C 584.24,518.69 614.07,549.65 579.61,545.01 C 533.59,551.10 487.13,554.76 441.40,562.48 C 397.18,588.94 462.84,613.68 489.95,609.31 C 514.10,610.80 538.52,610.13 562.38,605.92 M 211.18,531.90 C 167.07,548.50 234.68,593.43 260.49,576.39 C 326.21,562.34 388.19,535.46 447.53,504.56 C 489.62,482.86 548.71,461.63 557.51,412.45 C 563.23,380.53 543.26,346.99 536.94,314.20 C 532.43,276.36 513.09,264.81 475.14,265.25 M 450.71,504.40 C 494.88,523 543.39,525.09 590.45,519.27 M 100.78,485.00 C 87.77,505.40 71.18,555.90 114.73,539.59 C 131.70,538.38 137.48,525.86 139.17,510.47
diff --git a/src/3rdparty/2geom/src/toys/svgd/circle.svgd b/src/3rdparty/2geom/src/toys/svgd/circle.svgd
new file mode 100644
index 0000000..fb276fa
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/circle.svgd
@@ -0,0 +1 @@
+M 0 0 A 100 100 0 0 0 200 0 A 100 100 0 0 0 0 0 z \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/toys/svgd/degenerate-line.svgd b/src/3rdparty/2geom/src/toys/svgd/degenerate-line.svgd
new file mode 100644
index 0000000..832bb17
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/degenerate-line.svgd
@@ -0,0 +1 @@
+m 23,42 0,0
diff --git a/src/3rdparty/2geom/src/toys/svgd/diederik.svgd b/src/3rdparty/2geom/src/toys/svgd/diederik.svgd
new file mode 100644
index 0000000..7e422ab
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/diederik.svgd
@@ -0,0 +1 @@
+m 262.6037,35.824151 c 0,0 -92.64892,-187.405851 30,-149.999981 104.06976,31.739531 170,109.9999815 170,109.9999815 l -10,-59.9999905 c 0,0 40,79.99999 -40,79.99999 -80,0 -70,-129.999981 -70,-129.999981 l 50,0 C 435.13571,-131.5667 652.76275,126.44872 505.74322,108.05672 358.73876,89.666591 292.6037,-14.175849 292.6037,15.824151 c 0,30 -30,20 -30,20 z \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/toys/svgd/diederik1.svgd b/src/3rdparty/2geom/src/toys/svgd/diederik1.svgd
new file mode 100644
index 0000000..be181f5
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/diederik1.svgd
@@ -0,0 +1 @@
+m 262.6037,35.824151 c 0,0 -92.64892,-187.405851 30,-149.999981 \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/toys/svgd/double-move.svgd b/src/3rdparty/2geom/src/toys/svgd/double-move.svgd
new file mode 100644
index 0000000..d2be8c3
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/double-move.svgd
@@ -0,0 +1 @@
+m 23,42 m 10,0
diff --git a/src/3rdparty/2geom/src/toys/svgd/ellipses.svgd b/src/3rdparty/2geom/src/toys/svgd/ellipses.svgd
new file mode 100644
index 0000000..c0f3a2c
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/ellipses.svgd
@@ -0,0 +1 @@
+M 310 640 A 290 320 0 0 1 310 0 A 290 320 0 0 1 310 640 z M 310 635 A 285 315 0 0 0 310 5 A 285 315 0 0 0 310 635 z M 310 630 A 280 310 0 0 1 310 10 A 280 310 0 0 1 310 630 z M 310 625 A 275 305 0 0 0 310 15 A 275 305 0 0 0 310 625 z M 310 620 A 270 300 0 0 1 310 20 A 270 300 0 0 1 310 620 z M 310 615 A 265 295 0 0 0 310 25 A 265 295 0 0 0 310 615 z M 310 610 A 260 290 0 0 1 310 30 A 260 290 0 0 1 310 610 z M 310 605 A 255 285 0 0 0 310 35 A 255 285 0 0 0 310 605 z M 310 600 A 250 280 0 0 1 310 40 A 250 280 0 0 1 310 600 z M 310 595 A 245 275 0 0 0 310 45 A 245 275 0 0 0 310 595 z M 310 590 A 240 270 0 0 1 310 50 A 240 270 0 0 1 310 590 z M 310 585 A 235 265 0 0 0 310 55 A 235 265 0 0 0 310 585 z M 310 580 A 230 260 0 0 1 310 60 A 230 260 0 0 1 310 580 z M 310 575 A 225 255 0 0 0 310 65 A 225 255 0 0 0 310 575 z M 310 570 A 220 250 0 0 1 310 70 A 220 250 0 0 1 310 570 z M 310 565 A 215 245 0 0 0 310 75 A 215 245 0 0 0 310 565 z M 310 560 A 210 240 0 0 1 310 80 A 210 240 0 0 1 310 560 z M 310 555 A 205 235 0 0 0 310 85 A 205 235 0 0 0 310 555 z M 310 550 A 200 230 0 0 1 310 90 A 200 230 0 0 1 310 550 z M 310 545 A 195 225 0 0 0 310 95 A 195 225 0 0 0 310 545 z M 310 540 A 190 220 0 0 1 310 100 A 190 220 0 0 1 310 540 z M 310 535 A 185 215 0 0 0 310 105 A 185 215 0 0 0 310 535 z M 310 530 A 180 210 0 0 1 310 110 A 180 210 0 0 1 310 530 z M 310 525 A 175 205 0 0 0 310 115 A 175 205 0 0 0 310 525 z M 310 520 A 170 200 0 0 1 310 120 A 170 200 0 0 1 310 520 z M 310 515 A 165 195 0 0 0 310 125 A 165 195 0 0 0 310 515 z M 310 510 A 160 190 0 0 1 310 130 A 160 190 0 0 1 310 510 z M 310 505 A 155 185 0 0 0 310 135 A 155 185 0 0 0 310 505 z M 310 500 A 150 180 0 0 1 310 140 A 150 180 0 0 1 310 500 z M 310 495 A 145 175 0 0 0 310 145 A 145 175 0 0 0 310 495 z M 310 490 A 140 170 0 0 1 310 150 A 140 170 0 0 1 310 490 z M 310 485 A 135 165 0 0 0 310 155 A 135 165 0 0 0 310 485 z M 310 480 A 130 160 0 0 1 310 160 A 130 160 0 0 1 310 480 z M 310 475 A 125 155 0 0 0 310 165 A 125 155 0 0 0 310 475 z M 310 470 A 120 150 0 0 1 310 170 A 120 150 0 0 1 310 470 z M 310 465 A 115 145 0 0 0 310 175 A 115 145 0 0 0 310 465 z M 310 460 A 110 140 0 0 1 310 180 A 110 140 0 0 1 310 460 z M 310 455 A 105 135 0 0 0 310 185 A 105 135 0 0 0 310 455 z M 310 450 A 100 130 0 0 1 310 190 A 100 130 0 0 1 310 450 z M 310 445 A 95 125 0 0 0 310 195 A 95 125 0 0 0 310 445 z M 310 440 A 90 120 0 0 1 310 200 A 90 120 0 0 1 310 440 z M 310 435 A 85 115 0 0 0 310 205 A 85 115 0 0 0 310 435 z M 310 430 A 80 110 0 0 1 310 210 A 80 110 0 0 1 310 430 z M 310 425 A 75 105 0 0 0 310 215 A 75 105 0 0 0 310 425 z M 310 420 A 70 100 0 0 1 310 220 A 70 100 0 0 1 310 420 z M 310 415 A 65 95 0 0 0 310 225 A 65 95 0 0 0 310 415 z M 310 410 A 60 90 0 0 1 310 230 A 60 90 0 0 1 310 410 z M 310 405 A 55 85 0 0 0 310 235 A 55 85 0 0 0 310 405 z M 310 400 A 50 80 0 0 1 310 240 A 50 80 0 0 1 310 400 z M 310 395 A 45 75 0 0 0 310 245 A 45 75 0 0 0 310 395 z M 310 390 A 40 70 0 0 1 310 250 A 40 70 0 0 1 310 390 z M 310 385 A 35 65 0 0 0 310 255 A 35 65 0 0 0 310 385 z M 310 380 A 30 60 0 0 1 310 260 A 30 60 0 0 1 310 380 z M 310 375 A 25 55 0 0 0 310 265 A 25 55 0 0 0 310 375 z M 310 370 A 20 50 0 0 1 310 270 A 20 50 0 0 1 310 370 z M 310 365 A 15 45 0 0 0 310 275 A 15 45 0 0 0 310 365 z M 310 360 A 10 40 0 0 1 310 280 A 10 40 0 0 1 310 360 z M 310 355 A 5 35 0 0 0 310 285 A 5 35 0 0 0 310 355 z \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/toys/svgd/emptyset.svgd b/src/3rdparty/2geom/src/toys/svgd/emptyset.svgd
new file mode 100644
index 0000000..7e91eeb
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/emptyset.svgd
@@ -0,0 +1 @@
+M 551.42857,252.36218 52.857143,750.93361 M 440,495.21933 c 0,77.31986 -62.68014,140 -140,140 -77.31986,0 -140,-62.68014 -140,-140 0,-77.31987 62.68014,-140 140,-140 77.31986,0 140,62.68013 140,140 z \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/toys/svgd/fan.svgd b/src/3rdparty/2geom/src/toys/svgd/fan.svgd
new file mode 100644
index 0000000..940fb71
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/fan.svgd
@@ -0,0 +1 @@
+ M 470 350 L 750 350 L 749.5904551097586 364.7203022982254 L 469.92772737231036 352.9440604596451 L 469.7110836003318 355.88102841977366 L 748.362807068547 379.4051420988682 L 746.3200133880255 394.01914233660864 L 469.3505905978869 358.80382846732175 L 468.84711682419385 361.70541932096774 L 743.4669953370983 408.5270966048386 L 739.810626086145 422.8940539709793 L 468.2018751916726 364.5788107941959 L 467.41642014393256 367.4170806352678 L 735.3597141489511 437.0854031763389 L 730.1249821622271 451.06695601766626 L 466.49264391098126 370.21339120353326 L 465.4327719506772 372.96100594190546 L 724.1190410538375 464.80502970952716 L 717.3563596619706 478.2665280290849 L 464.2393575874066 375.65330560581697 L 462.91527586090126 378.28380420955995 L 709.8532298784406 491.4190210477996 L 701.6277274000925 504.2308232579669 L 461.4637166000163 380.84616465159337 L 459.88817673815265 383.3342139811762 L 692.6996681828653 516.671069905881 L 683.090560703419 528.7097913477304 L 458.19245188883866 385.7419582695461 L 456.3806272017642 388.0635970498188 L 672.8235541433303 540.317985249094 L 661.9233826206857 551.4676864541059 L 454.4570675212975 390.2935372908212 L 452.4264068711928 392.4264068711929 L 650.4163056034258 562.1320343559646 L 638.3300446479859 572.2853376064882 L 450.29353729082106 394.45706752129763 L 448.06359704981867 396.3806272017643 L 625.693716615639 581.9031360088215 L 612.5377635274268 590.9622594441939 L 445.74195826954593 398.1924518888388 L 443.33421398117605 399.8881767381528 L 598.8938792266642 599.4408836907639 L 584.7949330256947 607.3185830000821 L 440.8461646515932 401.4637166000164 L 438.2838042095597 402.9152758609014 L 570.2748905208385 614.5763793045069 L 555.3687317662951 621.1967879370334 L 435.6533056058168 404.2393575874067 L 432.9610059419052 405.4327719506773 L 540.1123670041297 627.1638597533864 L 524.5425501533539 632.4632195549066 L 430.21339120353304 406.4926439109813 L 427.41708063526755 407.4164201439326 L 508.69679026651625 637.082100719663 L 492.6132611671087 641.0093759583635 L 424.57881079419565 408.2018751916727 L 421.7054193209675 408.8471168241939 L 476.33070948548254 644.2355841209694 L 459.8883613148219 646.7529529894346 L 418.8038284673215 409.35059059788694 L 415.88102841977343 409.71108360033185 L 443.3258277120495 648.5554180016593 L 426.68300927132094 649.638636861552 L 412.94406045964485 409.92772737231036 L 409.9999999999998 410 L 409.99999999999875 650.0000000000001 L 393.3169907286766 649.6386368615517 L 407.0559395403547 409.92772737231036 L 404.1189715802261 409.7110836003318 L 376.67417228794807 648.5554180016591 L 360.11163868517565 646.7529529894343 L 401.1961715326781 409.3505905978869 L 398.29458067903204 408.8471168241938 L 343.669290514515 644.235584120969 L 327.38673883288885 641.0093759583631 L 395.4211892058039 408.2018751916726 L 392.582919364732 407.4164201439325 L 311.30320973348137 637.0821007196624 L 295.4574498466437 632.4632195549059 L 389.78660879646657 406.4926439109812 L 387.0389940580944 405.43277195067714 L 279.887632995868 627.1638597533856 L 264.6312682337026 621.1967879370326 L 384.3466943941828 404.2393575874065 L 381.7161957904399 402.9152758609012 L 249.72510947915927 614.5763793045061 L 235.2050669743031 607.3185830000812 L 379.1538353484064 401.4637166000162 L 376.6657860188236 399.8881767381526 L 221.1061207733337 599.440883690763 L 207.4622364725711 590.9622594441928 L 374.2580417304537 398.19245188883855 L 371.936402950181 396.38062720176407 L 194.30628338435898 581.9031360088203 L 181.6699553520122 572.2853376064868 L 369.7064627091786 394.45706752129735 L 367.57359312880686 392.4264068711926 L 169.58369439657233 562.1320343559632 L 158.07661737931238 551.4676864541045 L 365.5429324787022 390.2935372908209 L 363.61937279823553 388.0635970498185 L 147.17644585666795 540.3179852490925 L 136.9094392965793 528.7097913477288 L 361.80754811116105 385.74195826954576 L 360.111823261847 383.3342139811759 L 127.30033181713321 516.6710699058793 L 118.37227259990618 504.2308232579651 L 358.53628339998346 380.846164651593 L 357.08472413909845 378.28380420955955 L 110.14677012155806 491.4190210477978 L 102.64364033802809 478.266528029083 L 355.7606424125932 375.6533056058166 L 354.5672280493226 372.96100594190506 L 95.8809589461614 464.8050297095253 L 89.87501783777185 451.0669560176643 L 353.5073560890186 370.21339120353286 L 352.5835798560673 367.4170806352674 L 84.64028585104796 437.0854031763369 L 80.18937391385413 422.8940539709773 L 351.7981248083272 364.5788107941955 L 351.15288317580604 361.70541932096734 L 76.53300466290085 408.5270966048366 L 73.67998661197373 394.01914233660654 L 350.649409402113 358.8038284673213 L 350.2889163996681 355.8810284197732 L 71.63719293145243 379.4051420988661 L 70.40954489024085 364.7203022982233 L 350.0722726276896 352.9440604596447 L 349.99999999999994 349.99999999999955 L 69.99999999999955 349.99999999999784 L 70.40954489024102 335.27969770177236 L 350.0722726276896 347.0559395403545 L 350.28891639966815 344.1189715802259 L 71.63719293145283 320.59485790112956 L 73.67998661197436 305.98085766338914 L 350.6494094021131 341.19617153267785 L 351.1528831758062 338.2945806790318 L 76.5330046629017 291.47290339515916 L 80.1893739138552 277.10594602901847 L 351.7981248083274 335.42118920580367 L 352.5835798560675 332.58291936473177 L 84.64028585104933 262.9145968236589 L 89.87501783777338 248.93304398233158 L 353.50735608901886 329.78660879646634 L 354.5672280493229 327.03899405809415 L 95.88095894616305 235.19497029047068 L 102.64364033802997 221.73347197091297 L 355.76064241259354 324.3466943941826 L 357.08472413909885 321.71619579043966 L 110.14677012156017 208.58097895219828 L 118.37227259990851 195.76917674203108 L 358.53628339998386 319.15383534840623 L 360.11182326184746 316.6657860188234 L 127.30033181713577 183.32893009411694 L 136.90943929658204 171.29020865226764 L 361.8075481111615 314.25804173045356 L 363.61937279823604 311.9364029501808 L 147.1764458566709 159.68201475090402 L 158.07661737931554 148.5323135458922 L 365.5429324787027 309.7064627091784 L 367.5735931288075 307.5735931288067 L 169.5836943965756 137.8679656440335 L 181.66995535201565 127.71466239351008 L 369.7064627091792 305.542932478702 L 371.9364029501816 303.61937279823536 L 194.3062833843626 118.09686399117678 L 207.46223647257486 109.03774055580445 L 374.2580417304544 301.8075481111609 L 376.6657860188243 300.1118232618469 L 221.10612077333755 100.55911630923444 L 235.20506697430704 92.68141699991645 L 379.15383534840714 298.5362833999833 L 381.71619579044057 297.08472413909834 L 249.72510947916334 85.4236206954917 L 264.6312682337068 78.80321206296531 L 384.34669439418354 295.76064241259303 L 387.0389940580951 294.56722804932247 L 279.8876329958723 72.83614024661233 L 295.4574498466481 67.53678044509223 L 389.7866087964673 293.50735608901846 L 392.5829193647328 292.58357985606716 L 311.3032097334858 62.91789928033586 L 327.3867388328934 58.99062404163544 L 395.4211892058047 291.7981248083271 L 398.2945806790329 291.1528831758059 L 343.6692905145196 55.76441587902963 L 360.11163868518037 53.247047010564586 L 401.1961715326789 290.64940940211295 L 404.11897158022697 290.288916399668 L 376.67417228795284 51.44458199833997 L 393.3169907286814 50.36136313844747 L 407.05593954035555 290.0722726276895 L 410.0000000000006 289.9999999999999 L 410.0000000000036 49.99999999999932 L 426.6830092713258 50.36136313844776 L 412.94406045964575 290.0722726276896 L 415.8810284197743 290.2889163996681 L 443.3258277120543 51.444581998340595 L 459.8883613148268 53.24704701056555 L 418.8038284673224 290.6494094021131 L 421.70541932096836 291.15288317580615 L 476.33070948548743 55.76441587903088 L 492.6132611671136 58.99062404163698 L 424.5788107941965 291.7981248083274 L 427.4170806352684 292.58357985606756 L 508.69679026652113 62.91789928033768 L 524.5425501533587 67.53678044509428 L 430.2133912035339 293.50735608901886 L 432.9610059419061 294.5672280493229 L 540.1123670041344 72.83614024661466 L 555.3687317662998 78.80321206296787 L 435.6533056058176 295.7606424125936 L 438.28380420956057 297.0847241390989 L 570.2748905208431 85.42362069549449 L 584.7949330256993 92.68141699991958 L 440.846164651594 298.5362833999839 L 443.3342139811768 300.1118232618476 L 598.8938792266686 100.5591163092378 L 612.5377635274311 109.03774055580809 L 445.74195826954667 301.8075481111616 L 448.0635970498194 303.61937279823616 L 625.6937166156432 118.09686399118067 L 638.3300446479899 127.7146623935142 L 450.29353729082175 305.5429324787028 L 452.4264068711935 307.57359312880754 L 650.4163056034297 137.86796564403784 L 661.9233826206896 148.53231354589673 L 454.45706752129814 309.70646270917933 L 456.3806272017648 311.9364029501818 L 672.8235541433339 159.6820147509088 L 683.0905607034226 171.2902086522726 L 458.1924518888393 314.2580417304545 L 459.8881767381533 316.6657860188244 L 692.6996681828685 183.32893009412211 L 701.6277274000955 195.76917674203642 L 461.4637166000169 319.1538353484073 L 462.91527586090183 321.71619579044074 L 709.8532298784436 208.5809789522038 L 717.3563596619734 221.7334719709186 L 464.2393575874071 324.3466943941837 L 465.43277195067765 327.0389940580953 L 724.1190410538401 235.19497029047645 L 730.1249821622295 248.9330439823375 L 466.49264391098166 329.7866087964675 L 467.4164201439329 332.582919364733 L 735.3597141489532 262.91459682366497 L 739.8106260861471 277.1059460290246 L 468.201875191673 335.4211892058049 L 468.84711682419413 338.29458067903306 L 743.4669953371001 291.4729033951654 L 746.3200133880272 305.98085766339545 L 469.35059059788716 341.1961715326791 L 469.7110836003321 344.1189715802272 L 748.3628070685484 320.5948579011359 L 749.5904551097599 335.2796977017788 L 469.9277273723105 347.0559395403558 z
diff --git a/src/3rdparty/2geom/src/toys/svgd/lotsarect.svgd b/src/3rdparty/2geom/src/toys/svgd/lotsarect.svgd
new file mode 100644
index 0000000..ab2d186
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/lotsarect.svgd
@@ -0,0 +1 @@
+M 39.75993,80.899849 L 359.75993,80.899849 L 359.75993,278.04273 L 39.75993,278.04273 L 39.75993,80.899849 zM 377.14322,406.21942 L 511.42894,406.21942 L 511.42894,503.36228 L 377.14322,503.36228 L 377.14322,406.21942 zM 377.14322,189.9335 L 511.42894,189.9335 L 511.42894,287.07636 L 377.14322,287.07636 L 377.14322,189.9335 zM 377.14322,298.07648 L 511.42894,298.07648 L 511.42894,395.21934 L 377.14322,395.21934 L 377.14322,298.07648 zM 377.14322,80.899849 L 511.42894,80.899849 L 511.42894,178.04271 L 377.14322,178.04271 L 377.14322,80.899849 zM 377.14322,514.36237 L 511.42894,514.36237 L 511.42894,611.50523 L 377.14322,611.50523 L 377.14322,514.36237 zM 49.495197,612.79767 L 359.4294,612.79767 L 359.4294,622.22533 L 49.495197,622.22533 L 49.495197,612.79767 zM 374.74936,625.76074 L 512.62885,625.76074 L 512.62885,757.74794 L 374.74936,757.74794 L 374.74936,625.76074 z \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/toys/svgd/monkey.svgd b/src/3rdparty/2geom/src/toys/svgd/monkey.svgd
new file mode 100644
index 0000000..9bdbbc3
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/monkey.svgd
@@ -0,0 +1 @@
+M 5.9562726,54.79058 C 13.541683,37.50935 29.441883,27.76099 41.447803,33.03085 c 12.00591,5.26987 15.59357,23.57221 8.00816,40.85344 -7.58541,17.28124 -9.90029,25.53083 -32.70294,16.30215 C 4.5991026,85.26753 -1.6291374,72.07182 5.9562726,54.79058 z M 59.77575,139.78799 c 17.6347,24.11274 67.29975,30.95068 91.77238,0.71978 m -34.6436,-37.40404 c 0,3.47102 -5.75618,6.2881 -12.84862,6.2881 -7.09242,0 -12.848597,-2.81708 -12.848597,-6.2881 0,-3.471028 5.756177,-6.288105 12.848597,-6.288105 7.09244,0 12.84862,2.817077 12.84862,6.288105 z m 8.28521,-17.104633 c -2.97718,0.127204 -5.59649,-4.52155 -5.84666,-10.376686 -0.25017,-5.855125 1.96307,-10.710355 4.94026,-10.837559 2.97718,-0.127204 5.59649,4.52155 5.84665,10.376676 0.25017,5.855135 -1.96307,10.710365 -4.94025,10.837569 z M 83.28913,64.783523 c 2.977573,-0.11776 5.582124,4.539282 5.813719,10.395185 0.231594,5.855893 -1.997037,10.704081 -4.97461,10.821841 -2.977572,0.11776 -5.582124,-4.539282 -5.813718,-10.395175 -0.231594,-5.855903 1.997036,-10.704092 4.974609,-10.821851 z M 45.217471,85.556076 c 0.822591,11.141413 3.633402,22.142554 10.599469,31.583504 0,0 -15.4694,5.45785 -13.31599,26.99188 2.87914,28.79134 33.63174,40.93745 66.22007,40.66777 27.38883,-0.21003 58.61221,-13.31662 59.02225,-39.2282 0.29666,-23.0823 -6.83795,-24.11275 -12.95611,-28.79134 6.43867,-10.04933 9.12075,-19.882931 9.80868,-31.216258 m -7.09398,-26.793307 c -5.29439,-5.661365 -13.31177,-9.59154 -23.94831,-11.089645 -10.28695,-1.43893 -26.99188,5.03849 -29.15123,5.03849 -1.79946,0 -23.47674,-7.30799 -34.5496,-4.6786 -6.377516,1.507416 -11.596875,4.060909 -15.573817,7.756776 M 47.116071,35.239853 C 60.692058,16.061922 81.318474,3.8164724 104.40235,3.8164724 c 24.26701,0 45.81819,13.5328816 59.31755,34.4261516 m 14.55081,56.509427 c -0.76518,14.403499 -4.61365,27.847529 -10.79081,39.459189 M 42.237336,135.88313 C 35.362956,123.6046 31.132611,109.16372 30.481189,93.641902 M 204.76611,54.79058 C 197.1807,37.50935 181.2805,27.76099 169.27458,33.03085 c -12.00591,5.26987 -15.59357,23.57221 -8.00816,40.85344 7.58541,17.28124 9.90029,25.53083 32.70294,16.30215 12.15392,-4.91891 18.38216,-18.11462 10.79675,-35.39586 z
diff --git a/src/3rdparty/2geom/src/toys/svgd/nasty.svgd b/src/3rdparty/2geom/src/toys/svgd/nasty.svgd
new file mode 100644
index 0000000..2a26bd2
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/nasty.svgd
@@ -0,0 +1,3 @@
+M 387.63906,267.9784 L 106.72661,469.82569 L 106.72661,267.9784 L 387.63906,469.82569 L 387.63906,267.9784 z M 540.4278,232.25903 C 440.92573,232.25903 646.18067,452.19982 540.4278,452.19982 C 437.36839,452.19982 639.73953,232.25903 540.4278,232.25903 z
+M 282.85714,578.07647 C 74.285714,832.36218 165.33193,1033.3172 288.57143,900.93361 C 410.47619,769.98377 73.333332,831.45467 282.85714,578.07647 z
+M 548.57143,662.36218 C 615.72948,662.36218 625.35777,906.64794 728.57143,906.64794 C 832.06154,906.64794 637.327,662.36218 548.57143,662.36218 C 459.95393,662.36218 291.30957,906.64794 428.57143,906.64794 C 534.44005,906.64794 481.41338,662.36218 548.57143,662.36218 z
diff --git a/src/3rdparty/2geom/src/toys/svgd/onlyarcs.svgd b/src/3rdparty/2geom/src/toys/svgd/onlyarcs.svgd
new file mode 100644
index 0000000..b8fe8d1
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/onlyarcs.svgd
@@ -0,0 +1,10 @@
+M 0,0
+A 40,20 0 0 0 100,0
+ 40,20 0 0 0 200,0
+ 40,20 90 0 0 200,100
+ 40,20 90 0 0 200,200
+ 40,20 0 0 0 100,200
+ 40,20 0 0 0 0,200
+ 40,20 90 0 0 0,100
+ 40,20 90 0 0 0,0
+ z
diff --git a/src/3rdparty/2geom/src/toys/svgd/ptitle.svgd b/src/3rdparty/2geom/src/toys/svgd/ptitle.svgd
new file mode 100644
index 0000000..2df8860
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/ptitle.svgd
@@ -0,0 +1 @@
+M 115.1808,25.588188 C 127.80826,26.557245 141.79964,22.715822 153.00893,30.053032 C 167.1951,42.822758 151.75887,64.216819 134.75853,59.865532 C 126.06809,57.038779 129.18533,66.019697 128.71596,71.414009 C 131.4913,80.259661 123.09665,77.935329 117.16748,78.076469 C 112.56276,76.886302 116.47422,67.179968 115.1808,62.6785 C 115.1808,50.315063 115.1808,37.951625 115.1808,25.588188 z M 131.60308,50.056938 C 148.57642,53.813235 146.23212,30.658565 130.43,35.396782 C 127.29211,38.94083 127.23081,46.355022 131.60308,50.056938 z M 183.06752,60.357719 C 165.63447,60.295503 183.24033,80.518401 189.00011,65.31476 C 192.06883,58.337714 187.11171,60.778459 183.06752,60.357719 z M 202.29799,55.611626 C 202.29799,63.099907 202.29799,70.588188 202.29799,78.076469 C 197.62085,76.91918 187.20205,81.503563 189.60658,73.264604 C 182.8671,85.729177 152.16107,75.907493 165.13563,57.951724 C 168.48007,47.659856 195.18552,59.239016 187.25111,47.525688 C 177.86756,43.881758 158.53169,53.222176 167.93494,39.294753 C 181.3394,36.315116 203.97321,35.500521 202.29799,55.611626 z M 243.32533,49.424126 C 229.50261,42.165491 224.74932,58.12986 226.66127,68.597202 C 228.09365,76.076455 226.04486,80.074546 217.99991,78.076469 C 210.48863,79.788485 215.52906,68.948786 214.07533,64.603246 C 214.07533,55.969321 214.07533,47.335395 214.07533,38.701469 C 218.71947,39.856601 229.10169,35.273643 226.66127,43.513335 C 227.95656,41.232134 248.09079,31.257919 243.31691,46.694818 C 243.31972,47.604587 243.32252,48.514356 243.32533,49.424126 z M 267.30191,60.357719 C 249.86884,60.295482 267.47469,80.518412 273.23449,65.31476 C 276.30322,58.33771 271.34611,60.778461 267.30191,60.357719 z M 286.53235,55.611626 C 286.53235,63.099907 286.53235,70.588188 286.53235,78.076469 C 281.85522,76.919181 271.43643,81.503563 273.84097,73.264604 C 267.10148,85.729174 236.39544,75.907495 249.37001,57.951724 C 252.71445,47.659856 279.41992,59.239015 271.48549,47.525688 C 262.10194,43.88176 242.76606,53.222171 252.16932,39.294753 C 265.57378,36.315114 288.20758,35.500525 286.53236,55.611626 M 334.80191,45.240532 C 345.49046,28.171278 366.87108,43.167474 361.59096,59.874146 C 361.59097,65.941587 361.59097,72.009028 361.59097,78.076469 C 356.92475,76.919987 346.51835,81.503682 348.93472,73.264604 C 348.50839,65.231031 349.97235,56.898734 347.77455,49.142876 C 335.14645,42.504341 335.807,61.093114 336.24329,69.326636 C 337.9621,76.849177 335.16475,79.855557 327.58193,78.076469 C 320.00816,79.827535 325.02155,68.991435 323.58704,64.603246 C 326.31279,55.038882 318.58105,38.272161 311.38782,53.827464 C 310.41918,61.855715 311.09896,69.997063 310.89566,78.076469 C 306.22944,76.919987 295.82304,81.503682 298.23941,73.264604 C 298.23941,61.743559 298.23941,50.222514 298.23941,38.701469 C 302.90563,39.857951 313.31203,35.274257 310.89566,43.513335 C 314.6641,37.643381 330.44834,33.922886 334.8019,45.240532 M 412.70816,58.283501 C 413.74716,65.329673 402.8183,60.407999 398.27256,61.869438 C 392.57307,62.588118 377.07559,58.69943 386.48158,68.513969 C 394.57691,78.279659 414.21137,57.534567 410.84485,73.681704 C 404.09284,81.288741 385.15052,81.142742 376.35658,73.681938 C 363.9865,62.168354 371.67984,37.148572 389.80164,37.838507 C 401.97647,35.889384 413.6668,45.751205 412.70815,58.283501 M 399.77066,54.099907 C 393.61653,30.04231 370.10862,61.928589 399.77066,54.099907 z M 435.94644,27.521782 C 435.96201,33.478312 433.93472,41.4777 442.68305,38.701469 C 449.91823,34.769304 451.1939,46.589839 446.99432,47.701469 C 441.05173,47.687042 433.16506,45.728538 435.94644,54.438081 C 435.39823,61.49483 434.91359,71.865095 445.20998,69.076469 C 450.19974,68.732922 449.24732,82.168413 442.05502,78.076469 C 430.09932,80.727323 420.36946,71.930596 423.36049,59.588823 C 422.71262,54.349502 426.24292,44.932013 417.58627,47.701469 C 415.00348,41.807039 418.08141,37.377201 423.3605,37.739096 C 422.6103,31.016795 422.60176,25.036149 431.05949,27.521782 C 432.68847,27.521782 434.31746,27.521782 435.94644,27.521782 z M 485.90347,49.424126 C 472.08074,42.165489 467.32744,58.129851 469.2394,68.597202 C 470.67179,76.076455 468.62301,80.074546 460.57805,78.076469 C 453.06677,79.788485 458.1072,68.948786 456.65347,64.603246 C 456.65347,55.969321 456.65347,47.335395 456.65347,38.701469 C 461.29761,39.856601 471.67983,35.273643 469.23941,43.513335 C 470.53469,41.232124 490.6689,31.257926 485.89505,46.694818 C 485.89785,47.604587 485.90066,48.514356 485.90347,49.424126 z M 492.23157,38.701469 C 496.8757,39.856601 507.25793,35.273643 504.8175,43.513335 C 504.8175,55.03438 504.8175,66.555425 504.8175,78.076469 C 500.17337,76.921338 489.79114,81.504296 492.23157,73.264604 C 492.23157,61.743559 492.23157,50.222514 492.23157,38.701469 z M 492.23157,23.373344 C 496.8757,24.528476 507.25793,19.945518 504.8175,28.18521 C 507.42558,36.781485 497.41711,32.761224 492.30665,33.638969 C 492.13675,30.373397 492.27768,26.760041 492.23157,23.373344 z M 548.79797,39.931938 C 552.97763,56.979712 538.66501,41.438745 530.05971,49.846001 C 518.41065,63.70638 539.40292,76.166974 548.79799,67.577905 C 553.09286,81.766505 534.23374,80.517459 525.20155,76.9674 C 507.36245,69.798238 511.84153,38.785564 531.6681,38.095047 C 537.4159,37.270461 543.34813,37.942021 548.79799,39.931938 M 590.49329,39.931938 C 594.79689,57.039848 577.52986,40.882708 568.9513,48.158523 C 572.15538,57.881524 601.33708,52.315812 591.96984,71.985653 C 585.95746,81.25109 561.1725,82.610066 558.00892,72.785571 C 554.84332,59.391839 574.62439,78.16019 582.36692,66.985848 C 570.73978,64.945587 547.5903,55.865125 561.70033,40.775688 C 570.39079,35.821962 581.23811,37.826772 590.4933,39.931938
diff --git a/src/3rdparty/2geom/src/toys/svgd/rect.svgd b/src/3rdparty/2geom/src/toys/svgd/rect.svgd
new file mode 100644
index 0000000..29ee442
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/rect.svgd
@@ -0,0 +1 @@
+M 120,98.076469 L 551.42856,98.076469 L 551.42856,323.79075 L 120,323.79075 L 120,98.076469 z \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/toys/svgd/sanitize-examples.svgd b/src/3rdparty/2geom/src/toys/svgd/sanitize-examples.svgd
new file mode 100644
index 0000000..486188d
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/sanitize-examples.svgd
@@ -0,0 +1 @@
+m 103.3207,92.186815 c 61.67475,0 77.09344,123.349515 138.76821,123.349515 92.51214,0 92.51214,-123.349515 0,-123.349515 -61.67476,0 -77.09345,123.349515 -138.76821,123.349515 -92.512144,0 -92.512144,-123.349515 0,-123.349515 m 172.70652,592.36216 c -116.436115,0 -206.29787,-170 -79.999995,-170 119.740085,0 239.999995,110 79.999995,110 -159.999995,0 -39.74009,-110 80,-110 126.29788,0 36.43613,170 -80,170 \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/toys/svgd/scribble.svgd b/src/3rdparty/2geom/src/toys/svgd/scribble.svgd
new file mode 100644
index 0000000..206563d
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/scribble.svgd
@@ -0,0 +1 @@
+M 205.71429,509.50504 C 191.27639,435.33396 124.96983,282.9985 237.14286,240.93361 C 298.33002,217.98843 410.42812,416.03951 425.71429,458.07647 C 456.36209,542.35792 211.91703,513.49252 165.71429,483.79075 C 20.478436,390.42485 89.745454,432.24443 157.14286,589.50504 C 207.33723,706.62525 264.31061,792.65288 391.42857,818.07647 C 466.24819,833.04039 419.17914,844.21704 428.57143,806.6479 C 455.45597,699.10972 205.78614,535.50673 188.57143,466.6479 C 186.58441,458.69982 179.04762,453.31456 174.28571,446.6479 C 173.27225,445.22905 206.50053,444.8262 242.85714,426.6479 C 302.27468,396.93913 311.42857,331.66273 311.42857,272.36218 C 311.42857,232.18181 300.5556,209.69024 257.14286,195.21933 C 217.28192,181.93235 106.94618,129.21667 94.285714,123.79075 C 79.18517,117.31909 126.94244,129.50504 168.57143,129.50504 C 301.00757,129.50504 430.66079,118.07647 562.85714,118.07647 C 597.38432,118.07647 452.97541,72.362183 425.71429,72.362183 C 289.53604,72.362183 290.63424,45.059235 377.14286,218.07647 C 439.49432,342.7794 589.94279,380.17165 680,455.21933 C 715.67553,484.94893 625.63444,427.43 577.14286,406.6479 C 390.81914,326.79487 363.97733,373.48237 502.85714,512.36218 C 519.79024,529.29528 656.23138,719.67741 540,680.93361 C 493.67741,665.49275 225.40147,535.28189 382.85714,503.79075 C 399.28655,500.50487 561.71346,472.36218 517.14286,472.36218 C 410.68431,472.36218 181.50374,350.75815 111.42857,292.36218 C 21.960157,217.80517 195.28155,363.95164 220,378.07647 C 486.98782,530.64094 333.26177,540.93361 142.85714,540.93361 C 33.897473,540.93361 -105.50257,492.78561 -34.285714,635.21933 C 4.462011,712.71478 133.2726,753.67122 208.57143,783.79075 C 234.8422,794.29906 219.78391,839.52186 208.57143,855.21933 C 168.50791,911.30825 225.30435,836.44417 274.28571,826.6479 C 322.06141,817.09276 466.28439,799.2233 485.71429,740.93361 C 493.89344,716.39615 516.95233,712.23517 474.28571,683.79075 C 439.34382,660.49616 441.2221,580.11609 397.14286,558.07647 C 373.83188,546.42098 339.15563,564.21294 322.85714,572.36218 C 305.88053,580.85049 256.57431,543.50648 240,535.21933 C 222.14649,526.29257 195.2496,535.66674 205.71429,509.50504 C 206.5716,507.36174 165.95426,541.31306 205.71429,509.50504 C 209.43271,506.5303 205.71429,519.02885 205.71429,523.79075 C 205.71429,528.55266 205.71429,514.26694 205.71429,509.50504 z \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/toys/svgd/spiral.svgd b/src/3rdparty/2geom/src/toys/svgd/spiral.svgd
new file mode 100644
index 0000000..cf096f9
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/spiral.svgd
@@ -0,0 +1 @@
+M 425.71429,452.36218 C 428.61778,445.53492 436.34979,452.9077 437.06166,457.18797 C 438.99077,468.78726 426.04452,475.99734 416.06271,475.05691 C 398.20761,473.37469 388.47706,454.23374 391.67221,437.88481 C 396.36121,413.89211 422.40756,401.33715 445.01745,406.97273 C 475.15289,414.48407 490.6018,447.65442 482.45111,476.49113 C 472.1943,512.7792 431.80767,531.14987 396.75955,520.44636 C 354.31159,507.48297 333.00474,459.83266 346.28275,418.58165 C 361.93043,369.96877 416.872,345.71719 464.32061,361.58328 C 519.10192,379.9013 546.30379,442.1516 527.84056,495.79429 C 506.86147,556.74653 437.29069,586.90252 377.45639,565.83581 C 310.33136,542.20215 277.21849,465.30257 300.8933,399.27849 C 327.17683,325.97925 411.41129,289.90746 483.62377,316.19383 \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/toys/svgd/star.svg b/src/3rdparty/2geom/src/toys/svgd/star.svg
new file mode 100644
index 0000000..113f523
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/star.svg
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.45.1"
+ sodipodi:docbase="/home/njh/svn/lib2geom/src/toys"
+ sodipodi:docname="star.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.35"
+ inkscape:cx="375"
+ inkscape:cy="520"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="910"
+ inkscape:window-height="631"
+ inkscape:window-x="0"
+ inkscape:window-y="25" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ style="fill:#ffff00;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 268.57143,258.07648 L 377.39465,340.01528 L 414.5031,208.94498 L 454.38051,339.19955 L 561.44306,254.97326 L 517.14286,383.79077 L 653.26525,378.58005 L 541.7086,456.7566 L 654.89671,532.55178 L 518.69446,530.22658 L 565.71428,658.07648 L 456.89106,576.13768 L 419.78261,707.20797 L 379.9052,576.95341 L 272.84264,661.1797 L 317.14285,532.36219 L 181.02045,537.5729 L 292.57711,459.39635 L 179.38899,383.60117 L 315.59124,385.92637 L 268.57143,258.07648 z "
+ id="path3134" />
+ </g>
+</svg>
diff --git a/src/3rdparty/2geom/src/toys/svgd/star.svgd b/src/3rdparty/2geom/src/toys/svgd/star.svgd
new file mode 100644
index 0000000..c6eb2d4
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/star.svgd
@@ -0,0 +1 @@
+M 268.57143,258.07648 L 377.39465,340.01528 L 414.5031,208.94498 L 454.38051,339.19955 L 561.44306,254.97326 L 517.14286,383.79077 L 653.26525,378.58005 L 541.7086,456.7566 L 654.89671,532.55178 L 518.69446,530.22658 L 565.71428,658.07648 L 456.89106,576.13768 L 419.78261,707.20797 L 379.9052,576.95341 L 272.84264,661.1797 L 317.14285,532.36219 L 181.02045,537.5729 L 292.57711,459.39635 L 179.38899,383.60117 L 315.59124,385.92637 L 268.57143,258.07648 z \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/toys/svgd/tadpole.svgd b/src/3rdparty/2geom/src/toys/svgd/tadpole.svgd
new file mode 100644
index 0000000..8895582
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/tadpole.svgd
@@ -0,0 +1 @@
+m 371.42857,212.36218 c -32.48101,-26.68142 -91.58939,10.54383 -64.64475,49.96244 5.57459,42.57277 70.53374,68.98077 78.10803,11.90685 14.41443,-52.55004 -40.97633,-99.82411 -91.27953,-91.66162 -45.76637,3.77115 -95.66566,43.4207 -88.25336,93.06866 8.10715,43.84559 57.30139,51.48387 83.49912,79.21169 62.5378,56.33364 174.00162,56.411 226.54697,-13.71412 33.15536,-44.32089 27.37475,-103.8585 15.40989,-154.44966 C 518.94598,147.80633 481.97543,121.49829 442.21462,117.80826 360.77206,103.76604 275.59142,128.77168 196.14437,100.04722 138.26682,85.91059 75.980997,126.30734 62.339274,183.76981 43.90764,241.6785 65.723336,304.74593 104.98132,348.74653 179.31517,452.93484 311.47528,524.69632 441.07626,499.66492 521.15261,482.71575 593.45793,431.55112 633.57498,359.85355 666.74394,302.92229 686.82287,232.82246 669.17746,167.67963 652.45446,117.60598 601.61006,86.174529 550.15809,84.370797 388.03362,61.260938 223.67779,65.532229 60.679408,54.420286 c -85.3275,5.078677 -174.754978,36.378483 -230.507428,103.801754 -26.33214,35.75102 -22.70039,88.23391 8.40942,120.02678 31.2681,37.67952 76.41934,59.44396 112.847171,91.25622 \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/toys/svgd/touchboxes.svgd b/src/3rdparty/2geom/src/toys/svgd/touchboxes.svgd
new file mode 100644
index 0000000..55e6f9d
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/touchboxes.svgd
@@ -0,0 +1 @@
+m 350,380 200,0 0,300 -200,0 0,-300 z M 80,180 l 270,0 0,400 -270,0 0,-400 z \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/toys/svgd/toy.svgd b/src/3rdparty/2geom/src/toys/svgd/toy.svgd
new file mode 100644
index 0000000..9983796
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/toy.svgd
@@ -0,0 +1 @@
+M 685.71429 132.36218 L 337.14286+238.07647 608.57143,298.07647 C 608.57143,298.07647 685.71429,543.79075 517.14286,552.36218 348.57143,560.93361 280,858.07647 422.85714,852.36218 565.71429,846.6479 691.42857,612.36218 691.42857,612.36218 Q 348.57143,560.93361 685.71429,132.36218 Z
diff --git a/src/3rdparty/2geom/src/toys/svgd/triarrange.svgd b/src/3rdparty/2geom/src/toys/svgd/triarrange.svgd
new file mode 100644
index 0000000..f5d82ee
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/triarrange.svgd
@@ -0,0 +1 @@
+M 495,400 45,380 M 210,230 450,460 M 100,440 370,230 \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/toys/svgd/tricky.svgd b/src/3rdparty/2geom/src/toys/svgd/tricky.svgd
new file mode 100644
index 0000000..1b2fa9a
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/tricky.svgd
@@ -0,0 +1 @@
+M 458.65625,31.34375 L 455.0625,31.4375 L 451.6875,32.65625 C 434.07714,39.013007 420.84501,52.305976 414.03125,67.25 C 407.21749,82.194024 405.96292,98.410997 408.28125,113.8125 C 412.4771,141.68706 428.51783,169.60215 456.40625,181.6875 C 538.70194,312.80904 554.38602,481.52856 510.34375,629.90625 L 509.8125,631.71875 L 509.5625,633.59375 C 506.87733,655.34401 495.49324,679.1849 479.46875,695.25 C 463.70165,711.05705 445.14595,719.37248 423.84375,716.625 C 403.50709,711.46674 391.72366,697.93145 383.4375,677.25 C 375.01895,656.2381 372.48837,628.78961 374.375,606.03125 C 385.44095,485.85838 388.01837,349.21084 313,239 C 270.11084,152.28462 127.55134,177.04972 109.25,269.96875 L 108.5,273.6875 L 109.03125,277.4375 C 117.41998,339.02101 116.06431,402.35901 112.375,466.09375 L 112.21875,469.125 L 112.84375,472.09375 C 117.1301,492.47365 108.37169,516.28486 92.03125,532.75 C 78.58177,546.30212 61.816491,553.83892 44.78125,552.625 C 26.079739,485.94082 42.403549,411.80134 67.125,342.90625 L 24.3125,327.53125 C -3.3082192,404.50618 -24.482689,494.297 5.71875,580.03125 L 9.5625,590.90625 L 20.5625,594.25 C 59.671156,606.15028 98.586445,590.76637 124.34375,564.8125 C 149.33808,539.62742 164.42386,503.26605 157.9375,466.125 C 161.49046,403.72415 162.85377,340.00411 154.65625,276.1875 C 166.8006,229.69869 250.73728,213.68098 272.65625,260.03125 L 273.46875,261.6875 L 274.5,263.21875 C 340.18519,358.54848 339.90385,483.98933 329.03125,602.0625 L 329.03125,602.15625 L 329.03125,602.25 C 326.66071,630.84572 329.10103,663.98958 341.1875,694.15625 C 353.27397,724.32292 377.30928,752.4189 414.28125,761.1875 L 415.28125,761.40625 L 416.25,761.5625 C 453.7973,767.02344 487.87231,751.21921 511.65625,727.375 C 534.86042,704.11203 549.85821,673.25525 554.3125,641.53125 C 602.10825,479.2135 584.5466,295.0552 490.8125,150.71875 L 486.125,143.53125 L 477.90625,141.21875 C 466.97267,138.13618 455.72384,123.25825 453.28125,107.03125 C 452.05996,98.91775 453.07904,91.297618 455.4375,86.125 C 457.36175,81.904709 459.73336,79.094036 464.03125,76.90625 C 495.13555,76.980202 529.29685,90.275009 566.03125,101.59375 C 610.4676,115.59228 646.8459,148.41525 668.6875,190.40625 L 668.8125,190.65625 L 668.9375,190.875 C 697.92762,243.68554 717.84744,301.48146 706.25,356.90625 L 706.21875,357.15625 L 706.15625,357.40625 C 694.18886,421.72169 679.2601,488.02392 680.625,557.96875 C 678.68079,606.53403 686.86775,651.99143 686.21875,693.84375 C 670.05571,787.71759 590.84823,878.44142 494,879.59375 L 493.96875,879.59375 L 493.9375,879.59375 C 395.82741,881.09756 293.40089,802.00173 289.84375,701.78125 L 289.8125,700.875 L 289.71875,700 C 282.30077,635.83434 290.72304,569.30623 297.15625,501.21875 L 298.0625,491.5625 L 291.75,484.21875 C 284.80041,476.14619 277.49477,469.76476 268.21875,465.84375 C 258.94273,461.92274 247.2182,461.69521 238.125,465.375 C 219.9386,472.73458 212.83021,487.30247 206.46875,501.0625 C 200.10729,514.82253 195.45919,529.80289 191.34375,543.03125 C 187.22831,556.25961 183.18481,568.24935 181.34375,571.875 L 181.28125,572.03125 L 181.21875,572.1875 C 142.65707,651.07426 94.549143,727.5865 58.8125,812.3125 C 49.294957,829.15506 36.457563,832.16994 22.90625,829.09375 C 9.2095614,825.98456 -3.2515511,815.31431 -6,797.40625 L -6.28125,795.53125 L -6.875,793.71875 C -20.296536,753.1447 -21.015532,704.32135 -39.625,654.96875 C -73.90942,524.31702 -90.602855,380.79943 -28.71875,262.375 C 1.9598227,205.26365 67.457357,164.07188 103.28125,90.9375 L 62.4375,70.9375 C 33.995201,129.00238 -30.775413,170.01981 -68.9375,241.0625 L -69,241.1875 L -69.0625,241.28125 C -139.47511,376.02623 -119.00391,531.98526 -83.5,667.0625 L -83.1875,668.28125 L -82.71875,669.46875 C -67.458776,708.96795 -66.587036,756.94282 -50.5625,806.375 C -44.27864,841.61077 -17.523667,866.57525 12.84375,873.46875 C 43.80863,880.49788 80.448846,867.38803 98.96875,833.78125 L 99.5625,832.71875 L 100.03125,831.59375 C 133.90634,750.79708 181.84088,674.53399 222.09375,592.1875 C 227.62217,581.30025 230.72079,569.58288 234.78125,556.53125 C 238.84171,543.47962 243.26444,529.92624 247.78125,520.15625 C 248.49865,518.60449 249.23407,517.44847 249.96875,516.1875 C 243.90866,577.21519 237.04535,640.29773 244.46875,704.90625 C 244.48076,705.01077 244.48792,705.11422 244.5,705.21875 C 250.176,833.46768 372.77047,926.96151 494.625,925.09375 C 619.20181,923.6115 712.56579,813.78448 731.40625,699.875 L 731.65625,698.28125 L 731.6875,696.65625 C 732.75618,647.53405 724.20107,601.36335 726.09375,558.53125 L 726.125,557.8125 L 726.125,557.09375 C 724.89958,494.29702 738.71436,431.07277 750.875,365.71875 C 765.84238,294.18884 740.23516,226.21058 708.8125,168.96875 C 681.8812,117.19267 636.59507,76.122901 579.5625,58.15625 L 579.5,58.125 L 579.4375,58.125 C 544.17995,47.261312 504.09579,29.800274 458.65625,31.34375 z \ No newline at end of file
diff --git a/src/3rdparty/2geom/src/toys/svgd/winding.svgd b/src/3rdparty/2geom/src/toys/svgd/winding.svgd
new file mode 100644
index 0000000..e0d9b59
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/svgd/winding.svgd
@@ -0,0 +1 @@
+M 237.8317,-0.00079806585 C 209.05129,2.0908553 194.49466,33.03178 168.59187,39.198673 C 144.83493,42.756195 133.04439,64.090923 112.23618,72.228008 C 96.390481,93.25412 79.059139,109.36615 55.144754,121.38967 C 28.073728,135.55225 28.749612,175.16363 61.142614,182.29572 C 59.032188,207.27758 51.935234,245.41728 19.327194,232.92932 C -15.949549,243.07701 3.1745321,287.497 13.519564,310.39525 C 17.791104,331.61525 13.405542,357.01005 26.625846,375.92214 C 24.121233,402.01179 53.313158,415.34704 52.967142,440.29059 C 53.481143,471.00236 85.579755,514.66901 114.61929,479.98667 C 130.54404,473.62405 176.35717,503.20612 155.39995,524.08371 C 144.17379,562.84736 195.91996,565.77913 221.73596,560.74671 C 247.29609,564.51298 273.27675,571.81621 298.92308,570.02889 C 324.04728,573.62413 345.47989,554.14368 370.64594,564.03304 C 402.54533,573.02054 442.7131,544.20356 415.3454,511.64988 C 431.35565,493.15457 459.52837,465.86203 478.13411,494.82269 C 512.36196,508.17908 524.21953,461.82677 528.84872,436.94541 C 539.13223,415.75136 555.80382,396.04476 559.09515,372.30135 C 573.74637,351.25358 558.73087,324.13051 575.26348,304.02273 C 593.5935,277.76628 586.3979,225.87087 544.09643,239.90933 C 527.05985,225.53034 511.89014,182.31837 545.28987,174.97401 C 567.85671,145.99111 526.28917,121.32068 504.46509,108.82388 C 488.46914,94.238944 477.21301,71.049919 455.38968,63.601767 C 442.2435,41.019814 410.90027,47.427299 396.59221,27.25649 C 378.5237,4.3455996 329.19512,-15.054231 323.43731,28.290685 C 321.44896,48.974453 272.63938,43.051302 266.79567,31.393533 C 265.68977,16.25095 255.66504,-2.8664064 237.8317,-0.00079806585 z M 214.63232,41.285294 C 229.03834,39.461472 281.82707,44.654146 243.16774,50.095915 C 215.41861,55.13544 186.824,66.887416 160.08963,70.064158 C 171.40031,49.377676 189.54369,36.977634 214.63232,41.285294 z M 364.21881,43.044488 C 389.3526,38.086584 423.75203,50.784111 426.68647,74.129598 C 394.45708,65.080185 361.92396,54.41391 328.76005,47.772323 C 335.0792,39.285706 353.90158,45.472989 364.21881,43.044488 z M 299.89827,49.421568 C 334.38633,45.796396 318.92415,87.04827 327.35648,107.9555 C 332.43473,138.01064 340.0154,167.56295 347.72637,197.02897 C 326.17931,210.45393 292.14883,198.94677 265.91081,202.13508 C 245.36668,206.92129 230.45935,196.7415 243.8515,176.32177 C 254.2743,135.80305 265.45003,94.976539 267.46313,52.939957 C 278.24641,51.687903 288.9237,47.465671 299.89827,49.421568 z M 137.22777,69.707278 C 166.23618,69.494992 120.49304,93.04016 137.22777,69.707278 z M 451.29893,73.445566 C 466.93112,101.11163 425.11973,69.858477 451.29893,73.445566 z M 161.69157,80.207469 C 195.12998,110.69979 212.21109,153.72778 229.83786,194.32162 C 218.52396,208.95034 195.22647,168.57531 181.29522,159.91955 C 163.37572,141.33152 146.8742,120.6359 137.28274,96.425042 C 142.33212,87.653771 151.47682,79.604025 161.69157,80.207469 z M 432.38759,84.605455 C 469.44406,97.732695 430.28001,132.80731 416.73442,150.68472 C 399.36069,169.02554 380.60198,186.72201 360.97525,202.252 C 349.31821,186.47906 377.05703,160.7322 382.09772,141.74406 C 393.9733,119.90955 408.28746,98.903859 427.49484,82.84626 L 432.38759,84.605455 z M 128.54175,91.752182 C 115.85675,118.87612 92.85066,143.11942 78.60652,170.73021 C 62.000206,188.85762 85.067031,127.73706 91.166453,114.95867 C 96.261463,99.592362 115.43004,97.567564 128.54175,91.752182 z M 461.79912,96.095193 C 494.61461,101.4137 503.85761,132.95303 510.27958,161.07074 C 516.23377,173.44499 515.53354,194.75452 505.81343,172.70604 C 492.0604,146.83354 474.56757,123.01553 458.88546,98.239211 C 458.10505,96.914376 460.38765,93.356115 461.79912,96.095193 z M 79.944004,189.00264 C 125.91433,201.82926 173.80854,204.82394 221.2293,207.58413 C 227.40504,232.22763 205.75574,261.03157 200.77991,287.0056 C 198.98453,308.21225 184.56547,318.80777 169.17926,299.94722 C 133.95987,277.46442 98.659981,254.15242 59.27347,239.46953 C 61.480079,223.18569 64.663812,195.41065 79.944004,189.00264 z M 511.49636,197.57872 C 525.19335,217.70705 535.43047,253.2069 500.46557,254.90752 C 464.15836,271.3807 430.27042,292.57043 396.81888,314.12534 C 377.50066,297.83942 377.83971,261.83829 366.73344,237.87322 C 355.70058,219.68486 361.03872,202.51102 384.63974,208.83172 C 426.3772,206.34293 468.63407,204.30758 509.18742,193.18073 L 511.49636,197.57872 z M 254.26917,235.40139 C 267.88776,248.222 300.90986,260.92788 269.02803,272.58167 C 260.2717,268.87591 255.10883,237.44794 254.26917,235.40139 z M 331.50879,237.05064 C 324.01248,255.18663 320.23797,289.128 300.05044,261.46924 C 304.69039,252.09852 327.86234,239.96464 331.50879,237.05064 z M 50.312574,243.81254 C 48.701291,276.28009 44.929165,308.91572 44.438642,341.59724 C 38.920345,352.62589 18.235924,313.83416 27.328216,302.38831 C 33.148841,283.15159 39.24851,257.94992 50.312574,243.81254 z M 536.45493,250.2446 C 543.88366,277.15913 566.74879,308.63556 551.43159,335.47436 C 546.44721,350.66062 532.20173,359.53588 537.73084,335.75981 C 539.32919,307.71959 531.27597,272.91081 536.06286,249.15412 L 536.45493,250.2446 z M 263.28504,288.34215 C 282.51337,317.65756 244.52942,307.7959 226.78176,309.61741 C 238.1088,304.60141 254.71447,286.66664 263.28504,288.34215 z M 326.06629,289.99139 C 335.50507,298.75069 371.96349,315.98071 340.11655,310.44928 C 318.61751,314.37824 306.58789,306.07219 322.5447,287.44802 L 326.06629,289.99139 z M 281.9215,316.10443 C 315.80881,306.99659 294.53894,340.10829 290.93737,357.61043 C 289.75062,345.2197 277.62158,323.68751 281.9215,316.10443 z M 184.01134,318.7982 C 187.74469,337.09704 148.67935,342.5761 134.89818,354.17134 C 111.56567,365.55352 86.689349,375.07418 60.537891,376.68669 C 34.857135,351.83888 71.020358,335.11628 93.620682,331.96846 C 123.12694,324.08505 153.65422,321.18138 184.01134,318.7982 z M 384.50452,320.1176 C 389.61697,323.73995 377.26894,318.84237 384.50452,320.1176 z M 398.90793,321.38202 C 443.1239,326.51593 489.45667,330.51222 528.63386,353.62958 C 538.96391,391.76884 496.17809,381.49967 476.30611,371.10904 C 448.0456,360.17677 421.89729,344.64344 396.10421,328.91357 C 393.51601,325.98521 395.11468,321.97061 398.90793,321.38202 z M 203.30751,332.26703 C 227.72727,353.07009 264.71284,370.58598 280.20641,394.90874 C 262.93503,412.3019 241.56903,425.95006 223.50819,442.94849 C 205.20907,458.95886 187.67677,475.97038 172.41166,494.93753 C 148.89686,486.37063 113.76917,464.1279 143.2293,439.75157 C 162.91673,405.20393 177.76059,368.20734 192.14762,331.22251 C 195.29635,327.04196 200.53018,328.93547 203.30751,332.26703 z M 386.48362,331.16754 C 400.18586,350.95872 404.22928,376.64387 415.28715,398.36989 C 425.20431,421.90616 436.33007,445.05076 450.41934,466.4056 C 434.12186,488.50845 401.66036,511.25603 387.04573,475.11066 C 360.70616,446.5202 330.78928,421.55644 300.72289,397.02737 C 310.13036,373.45503 344.5899,362.82508 363.91108,344.81642 C 371.25297,341.05885 379.09963,331.94719 386.48362,331.16754 z M 42.781023,362.72308 C 57.078154,387.91587 19.840772,365.01162 42.781023,362.72308 z M 542.33724,366.4064 C 556.06367,380.56137 523.55694,385.37945 539.8395,367.13493 C 539.57763,366.48977 542.65437,362.78508 542.33724,366.4064 z M 53.336189,383.50357 C 75.268719,404.32092 91.325113,433.37386 113.18698,455.63259 C 124.54299,476.44851 74.161701,435.968 63.852016,426.25618 C 50.708583,416.70395 54.964638,397.77227 53.336189,383.50357 z M 528.09876,391.41994 C 533.1255,424.20402 506.16623,442.7593 481.40591,457.52287 C 471.49835,466.88801 451.01521,473.12226 468.89427,456.9389 C 489.1958,435.80533 506.44563,411.83156 525.1851,389.27592 C 526.23268,388.092 530.2919,389.29239 528.09876,391.41994 z M 294.45576,401.04054 C 302.97032,444.77201 314.18465,490.50238 303.45686,534.78351 C 269.8116,555.70792 267.45319,510.26453 271.11797,487.87885 C 272.91786,458.43851 279.8073,429.65527 286.31949,400.98556 C 288.31716,397.74595 292.52433,397.64886 294.45576,401.04054 z M 180.49295,506.64717 C 207.67798,522.26301 246.52699,528.98157 268.55252,545.52857 C 242.42325,558.17886 217.83828,546.5235 198.29377,527.97033 C 194.69189,524.69972 159.29181,498.82287 180.49295,506.64717 z M 404.51536,507.63672 C 390.01309,525.27528 368.18947,538.74082 347.86304,550.23549 C 335.91524,557.74156 287.21939,542.66729 323.67227,537.66117 C 350.78566,529.02491 379.06974,516.04027 404.51536,507.63672 z M 292.69657,548.86784 C 304.93678,562.57073 267.95665,553.48912 288.01486,547.90629 L 290.34982,548.11682 L 292.69657,548.86784 z
diff --git a/src/3rdparty/2geom/src/toys/sweep.cpp b/src/3rdparty/2geom/src/toys/sweep.cpp
new file mode 100644
index 0000000..4f26b81
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/sweep.cpp
@@ -0,0 +1,89 @@
+#include <2geom/sweep-bounds.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+using namespace Geom;
+
+class Sweep: public Toy {
+public:
+ PointSetHandle hand;
+ unsigned count_a, count_b;
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ std::vector<Rect> rects_a, rects_b;
+ cairo_set_source_rgb(cr, 0,0,0);
+
+ for(unsigned i = 0; i < count_a; i++)
+ rects_a.emplace_back(hand.pts[i*2], hand.pts[i*2+1]);
+
+ for(unsigned i = 0; i < count_b; i++)
+ rects_b.emplace_back(hand.pts[i*2 + count_a*2], hand.pts[i*2+1 + count_a*2]);
+
+ {
+ std::vector<std::vector<unsigned> > res = sweep_bounds(rects_a);
+ cairo_set_line_width(cr,0.5);
+ cairo_save(cr);
+ cairo_set_source_rgb(cr, 1, 0, 0);
+ for(unsigned i = 0; i < res.size(); i++) {
+ for(unsigned j = 0; j < res[i].size(); j++) {
+ draw_line_seg(cr, rects_a[i].midpoint(), rects_a[res[i][j]].midpoint());
+ cairo_stroke(cr);
+ }
+ }
+ cairo_restore(cr);
+ }{
+ std::vector<std::vector<unsigned> > res = sweep_bounds(rects_a, rects_b);
+ cairo_set_line_width(cr,0.5);
+ cairo_save(cr);
+ cairo_set_source_rgb(cr, 0.5, 0, 0.5);
+ for(unsigned i = 0; i < res.size(); i++) {
+ for(unsigned j = 0; j < res[i].size(); j++) {
+ draw_line_seg(cr, rects_a[i].midpoint(), rects_b[res[i][j]].midpoint());
+ cairo_stroke(cr);
+ }
+ }
+ cairo_restore(cr);
+ }
+ cairo_set_line_width(cr,3);
+ cairo_set_source_rgba(cr,1,0,0,1);
+ for(unsigned i = 0; i < count_a; i++)
+ cairo_rectangle(cr, rects_a[i].left(), rects_a[i].top(), rects_a[i].width(), rects_a[i].height());
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba(cr,0,0,1,1);
+ for(unsigned i = 0; i < count_b; i++)
+ cairo_rectangle(cr, rects_b[i].left(), rects_b[i].top(), rects_b[i].width(), rects_b[i].height());
+ cairo_stroke(cr);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+ bool should_draw_numbers() override { return false; }
+ public:
+ Sweep () {
+ count_a = 20;
+ count_b = 10;
+ for(unsigned i = 0; i < (count_a + count_b); i++) {
+ Point dim(uniform() * 90 + 10, uniform() * 90 + 10),
+ pos(uniform() * 500 + 50, uniform() * 500 + 50);
+ hand.pts.push_back(pos - dim/2);
+ hand.pts.push_back(pos + dim/2);
+ }
+ handles.push_back(&hand);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new Sweep());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/sweeper-toy.cpp b/src/3rdparty/2geom/src/toys/sweeper-toy.cpp
new file mode 100644
index 0000000..5ca28db
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/sweeper-toy.cpp
@@ -0,0 +1,170 @@
+#include <iostream>
+#include <2geom/path.h>
+#include <2geom/svg-path-parser.h>
+#include <2geom/path-intersection.h>
+#include <2geom/basic-intersection.h>
+#include <2geom/pathvector.h>
+#include <2geom/exception.h>
+
+
+#include <cstdlib>
+#include <set>
+#include <vector>
+#include <algorithm>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <2geom/bezier-to-sbasis.h>
+#include <2geom/ord.h>
+
+using namespace Geom;
+using namespace std;
+
+#include "sweeper.cpp"
+
+double exp_rescale(double x){ return pow(10, x);}
+std::string exp_formatter(double x){ return default_formatter(exp_rescale(x));}
+
+
+class SweeperToy: public Toy {
+ int nb_paths;
+ int nb_curves_per_path;
+ int degree;
+
+ std::vector<PointSetHandle> paths_handles;
+ std::vector<Slider> sliders;
+ Sweeper sweeper;
+
+ void drawTile( cairo_t *cr, unsigned idx , unsigned line_width=1){
+ if (idx>=sweeper.tiles_data.size()) return;
+ Rect box;
+ box = sweeper.tiles_data[idx].fbox;
+ box[X].expandBy(1);
+ cairo_rectangle(cr, box);
+ cairo_set_source_rgba (cr, 1., 0., 0., .5);
+ cairo_set_line_width (cr, line_width);
+ cairo_stroke(cr);
+ box = sweeper.tiles_data[idx].tbox;
+ box[Y].expandBy(1);
+ cairo_rectangle(cr, box);
+ cairo_set_source_rgba (cr, 0., 0., 1., .5);
+ cairo_set_line_width (cr, line_width);
+ cairo_stroke(cr);
+
+ Sweeper::Tile tile = sweeper.tiles_data[idx];
+ D2<SBasis> p = sweeper.paths[tile.path][tile.curve].toSBasis();
+ Interval dom = Interval(tile.f,tile.t);
+ cairo_set_source_rgba (cr, 0., 1., .5, .8);
+ p = portion(p, dom);
+ cairo_d2_sb(cr, p);
+ cairo_set_line_width (cr, line_width);
+ cairo_stroke(cr);
+ }
+
+ void drawTiles( cairo_t *cr ){
+ for (unsigned i=0; i<sweeper.tiles_data.size(); i++){
+ drawTile( cr, i );
+ }
+
+// for (unsigned i=0; i<sweeper.vtxboxes.size(); i++){
+// cairo_rectangle(cr, sweeper.vtxboxes[i]);
+// cairo_set_source_rgba (cr, 0., 0., 0, 1);
+// cairo_set_line_width (cr, 1);
+// cairo_stroke(cr);
+// }
+ }
+
+ void enlightTile( cairo_t *cr, unsigned idx){
+ drawTile(cr, idx, 4);
+ }
+
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_source_rgba (cr, 0., 0., 0, 1);
+ cairo_set_line_width (cr, 1);
+
+ PathVector paths;
+ for (int i = 0; i < nb_paths; i++){
+ paths_handles[i].pts.back()=paths_handles[i].pts.front();
+ paths.push_back(Path(paths_handles[i].pts[0]));
+ for (unsigned j = 0; j+degree < paths_handles[i].size(); j+=degree){
+ D2<SBasis> c = handles_to_sbasis(paths_handles[i].pts.begin()+j, degree);
+ paths[i].append(c);
+ }
+ paths[i].close();
+ }
+
+ //cairo_path(cr, paths);
+ cairo_set_source_rgba (cr, 0., 0., 0, 1);
+ cairo_set_line_width (cr, 1);
+ cairo_stroke(cr);
+
+ double tol = exp_rescale(sliders[3].value());
+ Rect tolbytol( Point(50,110), Point(50,110) );
+ tolbytol.expandBy( tol );
+ cairo_rectangle(cr, tolbytol);
+ cairo_stroke(cr);
+
+ sweeper = Sweeper(paths,X, tol);
+ unsigned idx = (unsigned)(sliders[0].value()*(sweeper.tiles_data.size()-1));
+ drawTiles(cr);
+ enlightTile(cr, idx);
+
+ Toy::draw(cr, notify, width, height, save, timer_stream);
+ }
+
+ public:
+ SweeperToy(int paths, int curves_in_path, int degree) :
+ nb_paths(paths), nb_curves_per_path(curves_in_path), degree(degree) {
+ for (int i = 0; i < nb_paths; i++){
+ paths_handles.emplace_back();
+ }
+ for(int i = 0; i < nb_paths; i++){
+ for(int j = 0; j < (nb_curves_per_path*degree)+1; j++){
+ paths_handles[i].push_back(uniform()*400, 100+ uniform()*300);
+ }
+ handles.push_back(&paths_handles[i]);
+ }
+ sliders.emplace_back(0.0, 1, 0, 0.0, "intersection chooser");
+ sliders.emplace_back(0.0, 1, 0, 0.0, "ray chooser");
+ sliders.emplace_back(0.0, 1, 0, 0.0, "area chooser");
+ sliders.emplace_back(-5.0, 2, 0, 0.0, "tolerance chooser");
+ handles.push_back(&(sliders[0]));
+ handles.push_back(&(sliders[1]));
+ handles.push_back(&(sliders[2]));
+ handles.push_back(&(sliders[3]));
+ sliders[0].geometry(Point(50, 20), 250);
+ sliders[1].geometry(Point(50, 50), 250);
+ sliders[2].geometry(Point(50, 80), 250);
+ sliders[3].geometry(Point(50, 110), 250);
+ sliders[3].formatter(&exp_formatter);
+ }
+
+ void first_time(int /*argc*/, char** /*argv*/) override {
+
+ }
+};
+
+int main(int argc, char **argv) {
+ unsigned paths=10;
+ unsigned curves_in_path=3;
+ unsigned degree=1;
+ if(argc > 3)
+ sscanf(argv[3], "%d", &degree);
+ if(argc > 2)
+ sscanf(argv[2], "%d", &curves_in_path);
+ if(argc > 1)
+ sscanf(argv[1], "%d", &paths);
+ init(argc, argv, new SweeperToy(paths, curves_in_path, degree));
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/sweeper.cpp b/src/3rdparty/2geom/src/toys/sweeper.cpp
new file mode 100644
index 0000000..7dae586
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/sweeper.cpp
@@ -0,0 +1,1135 @@
+#include <iostream>
+#include <2geom/path.h>
+#include <2geom/basic-intersection.h>
+#include <2geom/pathvector.h>
+#include <2geom/exception.h>
+
+#include <cstdlib>
+#include <cstdio>
+#include <set>
+#include <vector>
+#include <algorithm>
+
+#include <limits.h>
+#define NULL_IDX UINT_MAX
+
+#include <2geom/orphan-code/intersection-by-smashing.h>
+#include "../2geom/orphan-code/intersection-by-smashing.cpp"
+
+using namespace Geom;
+using namespace std;
+
+
+/*
+The sweeper class takes a PathVector as input and generates "events" to let clients construct the relevant graph.
+
+The basic strategy is the following:
+The path is split into "tiles": a tile consists in 2 boxes related by a (monotonic) curve.
+
+The tiles are created at the very beginning, using a sweep, but *no care* is taken to topology
+information at this step! All the boxes of all the tiles are then enlarged so that they are
+either equal or disjoint.
+[TODO: we should look for curves traversing boxes, split them and repeat the process...]
+
+The sweeper maintains a virtual sweepline, that is the limit of the "known area". The tiles can have 2 states:
+open if they have one end in the known area, and one in the unknown, closed otherwise.
+[TODO: open/close should belong to tiles pointers, not tiles...]
+
+The sorted list of open tiles intersecting the sweep line is called the "context".
+*!*WARNING*!*: because the sweep line is not straight, closed tiles can still be in the context!!
+they can only be removed once the end of the last box is reached.
+
+The events are changes in the context when the sweep line crosses boxes.
+They are obtained by sorting the tiles according to one or the other of theire end boxes depending
+on the open/close state.
+
+A "big" event happens when the sweep line reaches a new 'box'. After such a "big" event, the sweep
+line goes round the new box along it's 3 other sides.
+N.B.: in an ideal world, all tiles ending at one box would be on one side, all the tiles starting
+there on the other. Unfortunately, because we have boxes as vertices, things are not that nice:
+open/closed tiles can appear in any order around a vertex, even in the monotonic case(!). Morover,
+our fat vertices have a non zero "duration", during which many things can happen: this is why we
+have to keep closed edges in the context until both ends of theire boxes are reached...
+
+
+To keep things uniform, such "big" events are split into elementary ones: opening/closing of a single
+edge. One such event is generated for each tile around the current 'box', in CCW order (geometrically,
+the sweepline is deformed in a neighborhood of the box to go round it for a certain amount, enter the
+box and come back inside the box; the piece inside the box is a "virtual edge" that is not added for
+good but that we keep track of). The event knows if it's the last one in such a sequence, so that the
+client knows when to do the additional work required to "close" the vertex construction. Hmmm. It's
+hard to explain the moves without a drawing here...(see sweep.svg in the doc dir). There are
+
+*Closings: insert a new the relevant tile in the context with a "exit" flag.
+
+*Openings: insert a new the relevant tile in the context with a "entry" flag.
+
+At the end of a box, the relevant exit/entries are purged from the context.
+
+
+N.B. I doubt we can do boolops without building the full graph, i.e. having different clients to obtain
+different outputs. So splitting sweeper/grpah builder is maybe not so relevant w/r to functionality
+(only code organization).
+*/
+
+
+//TODO: decline intersections algorithms for each kind of curves...
+//TODO: write an intersector that can work on sub domains.
+//TODO: factor computation of derivative and the like out.
+std::vector<SmashIntersection> monotonic_smash_intersect( Curve const &a, Interval a_dom,
+ Curve const &b, Interval b_dom, double tol){
+ std::vector<SmashIntersection> result;
+ D2<SBasis> asb = a.toSBasis();
+ asb = portion( asb, a_dom );
+ D2<SBasis> bsb = b.toSBasis();
+ bsb = portion( bsb, b_dom );
+ result = monotonic_smash_intersect(asb, bsb, tol );
+ for (auto & i : result){
+ i.times[X] *= a_dom.extent();
+ i.times[X] += a_dom.min();
+ i.times[Y] *= b_dom.extent();
+ i.times[Y] += b_dom.min();
+ }
+ return result;
+}
+
+
+
+class Sweeper{
+public:
+
+ //---------------------------
+ // utils...
+ //---------------------------
+
+ //near predicate utilized in process_splits
+ template<typename T>
+ struct NearPredicate {
+ double tol;
+ NearPredicate(double eps):tol(eps){}
+ NearPredicate(){tol = EPSILON;}//???
+ bool operator()(T x, T y) { return are_near(x, y, tol); } };
+
+ // ensures that f and t are elements of a vector, sorts and uniqueifies
+ // also asserts that no values fall outside of f and t
+ // if f is greater than t, the sort is in reverse
+ void process_splits(std::vector<double> &splits, double f, double t, double tol=EPSILON) {
+ //splits.push_back(f);
+ //splits.push_back(t);
+ std::sort(splits.begin(), splits.end());
+ std::vector<double>::iterator end = std::unique(splits.begin(), splits.end(), NearPredicate<double>(tol));
+ splits.resize(end - splits.begin());
+
+ //remove any splits which fall outside t / f
+ while(!splits.empty() && splits.front() < f+tol) splits.erase(splits.begin());
+ splits.insert(splits.begin(), f);
+ //splits[0] = f;
+ while(!splits.empty() && splits.back() > t-tol) splits.erase(splits.end() - 1);
+ splits.push_back(t);
+ //splits.back() = t;
+ }
+
+ struct IntersectionMinTimeOrder {
+ unsigned which;
+ IntersectionMinTimeOrder (unsigned idx) : which(idx) {}
+ bool operator()(SmashIntersection const &a, SmashIntersection const &b) const {
+ return a.times[which].min() < b.times[which].min();
+ }
+ };
+
+ // ensures that f and t are elements of a vector, sorts and uniqueifies
+ // also asserts that no values fall outside of f and t
+ // if f is greater than t, the sort is in reverse
+ std::vector<std::pair<Interval, Rect> >
+ process_intersections(std::vector<SmashIntersection> &inters, unsigned which, unsigned tileidx) {
+ std::vector<std::pair<Interval, Rect> > result;
+ std::pair<Interval, Rect> apair;
+ Interval dom ( tiles_data[tileidx].f, tiles_data[tileidx].t );
+ apair.first = Interval( dom.min() );
+ apair.second = tiles_data[tileidx].fbox;
+ result.push_back( apair );
+
+ std::sort(inters.begin(), inters.end(), IntersectionMinTimeOrder(which) );
+ for (auto & inter : inters){
+ if ( !inter.times[which].intersects( dom ) )//this should never happen.
+ continue;
+ if ( result.back().first.intersects( inter.times[which] ) ){
+ result.back().first.unionWith( inter.times[which] );
+ result.back().second.unionWith( inter.bbox );
+ }else{
+ apair.first = inter.times[which];
+ apair.second = inter.bbox;
+ result.push_back( apair );
+ }
+ }
+ apair.first = Interval( dom.max() );
+ apair.second = tiles_data[tileidx].tbox;
+ if ( result.size() > 1 && result.back().first.intersects( apair.first ) ){
+ result.back().first.unionWith( apair.first );
+ result.back().second.unionWith( apair.second );
+ }else{
+ result.push_back( apair );
+ }
+ return result;
+ }
+
+
+ //---------------------------
+ // Tiles.
+ //---------------------------
+
+ //A tile is a "light edge": just two boxes, joint by a curve.
+ //it is open iff intersected by the sweepline.
+ class Tile{
+ public:
+ unsigned path;
+ unsigned curve;
+ double f;
+ double t;
+ Rect fbox, tbox;
+ bool reversed;//with respect to sweep direction. Flip f/t instead?
+ bool open;//means sweepline currently cuts it (i.e. one end in the known area, the other in the unknown).
+ int state;//-1: both ends in unknown area, 0:one end in each, 1: both in known area.
+ //Warning: we can not delete a tile immediately when it's past(=closed again), only when the end of it's tbox is!.
+ Rect bbox(){Rect b = fbox; b.unionWith(tbox); return b;}
+ Point min(){return ( bbox().min() ); }
+ Point max(){return ( bbox().max() ); }
+// Rect cur_box() const {return ((open)^(reversed) ) ? tbox : fbox; }
+ Rect cur_box() const { return ((state>=0)^(reversed) ) ? tbox : fbox; }
+ Rect first_box() const {return ( reversed ) ? tbox : fbox; }
+ Rect last_box() const {return ( reversed ) ? fbox : tbox; }
+ };
+
+ D2<SBasis> tileToSB(Tile const &tile){
+ //TODO: don't convert each time!!!!!!
+ assert( tile.path < paths.size() );
+ assert( tile.curve < paths[tile.path].size() );
+ D2<SBasis> c = paths[tile.path][tile.curve].toSBasis();
+ c = portion( c, Interval( tile.f, tile.t ) );
+ return c;
+ }
+
+ //SweepOrder for Rects or Tiles.
+ class SweepOrder{
+ public:
+ Dim2 dim;
+ SweepOrder(Dim2 d) : dim(d) {}
+ bool operator()(const Rect &a, const Rect &b) const {
+ return Point::LexLessRt(dim)(a.min(), b.min());
+ }
+ bool operator()(const Tile &a, const Tile &b) const {
+ return Point::LexLessRt(dim)(a.cur_box().min(), b.cur_box().min());
+ }
+ };
+
+ class PtrSweepOrder{
+ public:
+ Dim2 dim;
+ std::vector<Tile>::iterator const begin;
+ PtrSweepOrder(std::vector<Tile>::iterator const beg, Dim2 d) : dim(d), begin(beg){}
+ bool operator()(const unsigned a, const unsigned b) const {
+ return Point::LexLessRt(dim)((begin+a)->cur_box().min(), (begin+b)->cur_box().min());
+ }
+ };
+
+
+ //---------------------------
+ // Vertices.
+ //---------------------------
+
+ //A ray is nothing but an edge ending or starting at a given vertex, + some info about when/where it exited a "separating" box;
+ struct Ray{
+ public:
+ unsigned tile;
+ bool centrifuge;//true if the intrinsic orientation of curve points away from the vertex.
+ //exit info:
+ unsigned exit_side;//0:y=min; 1:x=max; 2:y=max; 3:x=min.
+ double exit_place; //x or y value on the exit line.
+ double exit_time; //exit time on curve.
+ Ray(){tile = NULL_IDX; exit_side = 4;}
+ Ray(unsigned tile_idx, unsigned s, double p, double t){
+ tile = tile_idx;
+ exit_side =s;
+ exit_place = p;
+ exit_time = t;
+ }
+ Ray(unsigned tile_idx, bool outward){
+ tile = tile_idx;
+ exit_side = 4;
+ centrifuge = outward;
+ exit_time = (centrifuge) ? 2 : -1 ;
+ }
+ void setExitInfo( unsigned side, double place, double time){
+ exit_side = side;
+ exit_place = place;
+ exit_time = time;
+ }
+ };
+
+ class FatVertex : public Rect{
+ public:
+ std::vector<Ray> rays;
+ FatVertex(const Rect &r, unsigned const tile, bool centrifuge) : Rect(r){
+ rays.push_back( Ray(tile, centrifuge) );
+ }
+ FatVertex(Rect r) : Rect(r){}
+ FatVertex() : Rect(){}
+ void erase(unsigned from, unsigned to){
+ unsigned size = to-from;
+ from = from % rays.size();
+ to = from + size;
+
+ if (to >= rays.size() ){
+ to = to % rays.size();
+ rays.erase( rays.begin()+from, rays.end() );
+ rays.erase( rays.begin(), rays.begin()+to );
+ }else{
+ rays.erase( rays.begin()+from, rays.begin()+to );
+ }
+
+ }
+ };
+
+ //---------------------------
+ // Context related stuff.
+ //---------------------------
+
+ class Event{
+ public:
+ bool opening;//true means an edge is added, otherwise an edge is removed from context.
+ unsigned tile;//which tile to open/close.
+ unsigned insert_at;//where to insert the next tile in the context.
+ //unsigned erase_at;//idx of the tile to close in the context. = context.find(tile).
+ bool to_be_continued;
+ bool empty(){
+ return tile==NULL_IDX;
+ }
+ Event(){
+ opening = false;
+ insert_at = 0;
+ //erase_at = 0;
+ tile = NULL_IDX;
+ to_be_continued = false;
+ }
+ };
+
+ void printEvent(Event const &e){
+ std::printf("Event: ");
+ std::printf("%s, ", e.opening?"opening":"closing");
+ std::printf("insert_at:%u, ", e.insert_at);
+ //std::printf("erase_at:%u, ", e.erase_at);
+ std::printf("tile:%u.\n", e.tile);
+ }
+
+ class Context : public std::vector<std::pair<unsigned,bool> >{//first = tile, second = true if it's a birth (+).
+ public:
+ Point last_pos;
+ FatVertex pending_vertex;
+ Event pending_event;
+
+ unsigned find(unsigned const tile, bool positive_only=false){
+ for (unsigned i=0; i<size(); i++){
+ if ( (*this)[i].first == tile ){
+ if ( (*this)[i].second || !positive_only ) return i;
+ }
+ }
+ return (*this).size();
+ }
+ };
+ void printContext(){
+ std::printf("context:[");
+ for (unsigned i=0; i<context.size(); i++){
+ unsigned tile = context[i].first;
+ assert( tile<tiles_data.size() );
+ std::printf(" %s%u%s", (tiles_data[ tile ].reversed)?"-":"+", tile, (context[i].second)?"o":"c");
+// assert( context[i].second || !tiles_data[ tile ].open);
+ assert( context[i].second || tiles_data[ tile ].state==1);
+ }
+ std::printf("]\n");
+ }
+
+
+
+ //----
+ //This is the heart of it all!! Take particular care to non linear sweep line...
+ //----
+ //Given a point on the sweep line, (supposed to be the min() of a vertex not yet connected to the already known part),
+ //find the first edge "after" it in the context. Pretty tricky atm :-(
+ //TODO: implement this as a lower_bound (?).
+
+ unsigned contextRanking(Point const &pt){
+
+// std::printf("contextRanking:------------------------------------\n");
+
+ unsigned rank = context.size();
+ std::vector<unsigned> unmatched_closed_tiles = std::vector<unsigned>();
+
+// std::printf("Scan context.\n");
+
+ for (unsigned i=0; i<context.size(); i++){
+
+ unsigned tile_idx = context[i].first;
+ assert( tile_idx < tiles_data.size() );
+// std::printf("testing %u (e=%u),", i, tile_idx);
+
+ Tile tile = tiles_data[tile_idx];
+ assert( tile.state >= 0 );
+
+ //if the tile is open (i.e. not both ends in the known area) and point is below/above the tile's bbox:
+ if ( tile.state == 0 ){
+// std::printf("opened tile, ");
+ if (pt[1-dim] < tile.min()[1-dim] ) {
+// printContext();
+// std::printf("below bbox %u!\n", i);
+ rank = i;
+ break;
+ }
+ if (pt[1-dim] > tile.max()[1-dim] ){
+// std::printf("above bbox %u!\n", i);
+ continue;
+ }
+
+ //TODO: don't convert each time!!!!!!
+ D2<SBasis> c = tileToSB( tile );
+
+ std::vector<double> times = roots(c[dim]-pt[dim]);
+ if (times.size()==0){
+ assert( tile.first_box()[dim].contains(pt[dim]) );
+ if ( pt[1-dim] < tile.first_box()[1-dim].min() ){
+// std::printf("open+hit box %u!\n", i);
+ rank = i;
+ break;
+ }else{
+ continue;
+ }
+ }
+ if ( pt[1-dim] < c[1-dim](times.front()) ){
+// std::printf("open+hit curve %u!\n", i);
+ rank = i;
+ break;
+ }
+ }
+
+// std::printf("closed tile, ");
+
+
+ //At this point, the tile is closed (i.e. both ends are in the known area)
+ //Such tiles do 'nested parens' like travels in the unknown area.
+ //We are interested in the second occurrence only (to give a chance to open tiles to exist in between).
+ if ( unmatched_closed_tiles.size()==0 || tile_idx != unmatched_closed_tiles.back() ){
+ unmatched_closed_tiles.push_back( tile_idx );
+// std::printf("open paren %u\n",tile_idx);
+ continue;
+ }
+ unmatched_closed_tiles.pop_back();
+
+// std::printf("close paren, ");
+
+ if ( !tile.bbox().contains( pt ) ){
+ continue;
+ }
+
+// std::printf("in bbox, ");
+
+ //At least one of fbox[dim], tbox[dim] has to contain the pt[dim]: assert it?
+
+ //Find intersection with the hline(vline if dim=Y) through the point
+ double hit_place;
+ //TODO: don't convert each time!!!!!!
+ D2<SBasis> c = tileToSB( tile );
+ std::vector<double> times = roots(c[1-dim]-pt[1-dim]);
+ if ( times.size()>0 ){
+// std::printf("hit curve,");
+ hit_place = c[dim](times.front());
+ }else{
+// std::printf("hit box, ");
+ //if there was no intersection, the line went through the first_box
+ assert( tile.first_box()[1-dim].contains(pt[1-dim]) );
+ continue;
+ }
+
+ if ( pt[dim] > hit_place ){
+// std::printf("wrong side, ");
+ continue;
+ }
+// std::printf("good side, ");
+ rank = i;
+ break;
+ }
+
+// std::printf("rank %u.\n", rank);
+// printContext();
+ assert( rank<=tiles_data.size() );
+ return rank;
+ }
+
+ //TODO: optimize this.
+ //it's done the slow way for debugging purpose...
+ void purgeDeadTiles(){
+ //std::printf("purge ");
+ //printContext();
+ for (unsigned i=0; i<context.size(); i++){
+ assert( context[i].first<tiles_data.size() );
+ Tile tile = tiles_data[context[i].first];
+ if (tile.state==1 && Point::LexLessRt(dim)( tile.fbox.max(), context.last_pos ) && Point::LexLessRt(dim)( tile.tbox.max(), context.last_pos ) ){
+// if (!tile.open && Point::LexLessRt(dim)( tile.fbox.max(), context.last_pos ) && Point::LexLessRt(dim)( tile.tbox.max(), context.last_pos ) ){
+ unsigned j;
+ for (j=i+1; j<context.size() && context[j].first != context[i].first; j++){}
+ assert ( j < context.size() );
+ if ( context[j].first == context[i].first){
+ assert ( context[j].second == !context[i].second );
+ context.erase(context.begin()+j);
+ context.erase(context.begin()+i);
+// printContext();
+ i--;
+ }
+ }
+ }
+ return;
+ }
+
+ void applyEvent(Event event){
+// std::printf("Apply event : ");
+ if(event.empty()){
+// std::printf("empty event!\n");
+ return;
+ }
+
+// printEvent(event);
+// std::printf(" old ");
+// printContext();
+
+ assert ( context.begin() + event.insert_at <= context.end() );
+
+ if (!event.opening){
+// unsigned idx = event.erase_at;
+// assert( idx == context.find(event.tile) );
+// assert( context[idx].first == event.tile);
+ tiles_data[event.tile].open = false;
+ tiles_data[event.tile].state = 1;
+ //context.erase(context.begin()+idx);
+ unsigned idx = event.insert_at;
+ context.insert(context.begin()+idx, std::pair<unsigned, bool>(event.tile, false) );
+ }else{
+ unsigned idx = event.insert_at;
+ tiles_data[event.tile].open = true;
+ tiles_data[event.tile].state = 0;
+ context.insert(context.begin()+idx, std::pair<unsigned, bool>(event.tile, true) );
+ sortTiles();
+ }
+ context.last_pos = context.pending_vertex.min();
+ context.last_pos[1-dim] = context.pending_vertex.max()[1-dim];
+
+// std::printf(" new ");
+// printContext();
+// std::printf("\n");
+ //context.pending_event = Event();is this a good idea?
+ }
+
+
+
+ //---------------------------
+ // Sweeper.
+ //---------------------------
+
+ PathVector paths;
+ std::vector<Tile> tiles_data;
+ std::vector<unsigned> tiles;
+ std::vector<Rect> vtxboxes;
+ Context context;
+ double tol;
+ Dim2 dim;
+
+
+ //-------------------------------
+ //-- Tiles preparation.
+ //-------------------------------
+
+ //split input paths into monotonic pieces...
+ void createMonotonicTiles(){
+ for ( unsigned i=0; i<paths.size(); i++){
+ for ( unsigned j=0; j<paths[i].size(); j++){
+ //find the points where slope is 0°, 45°, 90°, 135°...
+ D2<SBasis> deriv = derivative( paths[i][j].toSBasis() );
+ std::vector<double> splits0 = roots( deriv[X] );
+ std::vector<double> splits90 = roots( deriv[Y] );
+ std::vector<double> splits45 = roots( deriv[X]- deriv[Y] );
+ std::vector<double> splits135 = roots( deriv[X] + deriv[Y] );
+ std::vector<double> splits;
+ splits.insert(splits.begin(), splits0.begin(), splits0.end() );
+ splits.insert(splits.begin(), splits90.begin(), splits90.end() );
+ splits.insert(splits.begin(), splits45.begin(), splits45.end() );
+ splits.insert(splits.begin(), splits135.begin(), splits135.end() );
+ process_splits(splits,0,1);
+
+ for(unsigned k = 1; k < splits.size(); k++){
+ Tile tile;
+ tile.path = i;
+ tile.curve = j;
+ tile.f = splits[k-1];
+ tile.t = splits[k];
+ //TODO: use meaningful tolerance here!!
+ Point fp = paths[i][j].pointAt(tile.f);
+ Point tp = paths[i][j].pointAt(tile.t);
+ tile.fbox = Rect(fp, fp );
+ tile.tbox = Rect(tp, tp );
+ tile.open = false;
+ tile.state = -1;
+ tile.reversed = Point::LexLessRt(dim)(tp, fp);
+
+ tiles_data.push_back(tile);
+ }
+ }
+ }
+ std::sort(tiles_data.begin(), tiles_data.end(), SweepOrder(dim) );
+ }
+
+ void splitTile(unsigned i, double t, double tolerance=0, bool sort = true){
+ assert( i<tiles_data.size() );
+ Tile newtile = tiles_data[i];
+ assert( newtile.f < t && t < newtile.t );
+ newtile.f = t;
+ //newtile.fbox = fatPoint(paths[newtile.path][newtile.curve].pointAt(t), tolerance );
+ Point p = paths[newtile.path][newtile.curve].pointAt(t);
+ newtile.fbox = Rect(p, p);
+ newtile.fbox.expandBy( tolerance );
+ tiles_data[i].tbox = newtile.fbox;
+ tiles_data[i].t = t;
+ tiles_data.insert(tiles_data.begin()+i+1, newtile);
+ if (sort)
+ std::sort(tiles_data.begin()+i+1, tiles_data.end(), SweepOrder(dim) );
+ }
+ void splitTile(unsigned i, SmashIntersection inter, unsigned which,bool sort = true){
+ double t = inter.times[which].middle();
+ assert( i<tiles_data.size() );
+ Tile newtile = tiles_data[i];
+ assert( newtile.f < t && t < newtile.t );
+ newtile.f = t;
+ newtile.fbox = inter.bbox;
+ tiles_data[i].tbox = newtile.fbox;
+ tiles_data[i].t = t;
+ tiles_data.insert(tiles_data.begin()+i+1, newtile);
+ if (sort)
+ std::sort(tiles_data.begin()+i+1, tiles_data.end(), SweepOrder(dim) );
+ }
+#if 0
+ void splitTile(unsigned i, std::vector<double> const &times, double tolerance=0, bool sort = true){
+ if ( times.size()<3 ) return;
+ assert( i<tiles_data.size() );
+ std::vector<Tile> pieces ( times.size()-2, tiles_data[i] );
+ Rect prevbox = tiles_data[i].fbox;
+ for (unsigned k=0; k < times.size()-2; k++){
+ pieces[k].f = times[k];
+ pieces[k].t = times[k+1];
+ pieces[k].fbox = prevbox;
+ //TODO: use relevant precision here.
+ prevbox = fatPoint(paths[tiles_data[i].path][tiles_data[i].curve].pointAt(times[k+1]), tolerance );
+ pieces[k].tbox = prevbox;
+ }
+ tiles_data.insert(tiles_data.begin()+i, pieces.begin(), pieces.end() );
+ unsigned newi = i + times.size()-2;
+ assert( newi<tiles_data.size() );
+ assert( newi>=1 );
+ tiles_data[newi].f = tiles_data[newi-1].t;
+ tiles_data[newi].fbox = tiles_data[newi-1].tbox;
+
+ if (sort)
+ std::sort(tiles_data.begin()+i, tiles_data.end(), SweepOrder(dim) );
+ }
+#else
+ void splitTile(unsigned i, std::vector<std::pair<Interval,Rect> > const &cuts, bool sort = true){
+ assert ( cuts.size() >= 2 );
+ assert( i<tiles_data.size() );
+ std::vector<Tile> pieces ( cuts.size()-1, tiles_data[i] );
+ for (unsigned k=1; k+1 < cuts.size(); k++){
+ pieces[k-1].t = cuts[k].first.middle();
+ pieces[k ].f = cuts[k].first.middle();
+ pieces[k-1].tbox = cuts[k].second;
+ pieces[k ].fbox = cuts[k].second;
+ }
+ pieces.front().fbox.unionWith( cuts[0].second );
+ pieces.back().tbox.unionWith( cuts.back().second );
+
+ tiles_data.insert(tiles_data.begin()+i, pieces.begin(), pieces.end()-1 );
+ unsigned newi = i + cuts.size()-2;
+ assert( newi < tiles_data.size() );
+ tiles_data[newi] = pieces.back();
+
+ if (sort)
+ std::sort(tiles_data.begin()+i, tiles_data.end(), SweepOrder(dim) );
+ }
+#endif
+
+ //TODO: maybe not optimal. For a fully optimized sweep, it would be nice to have
+ //an efficient way to way find *only the first* intersection (in sweep direction)...
+ void splitIntersectingTiles(){
+ //make sure it is sorted, but should be ok. (remove sorting at the end of monotonic tiles creation?
+ std::sort(tiles_data.begin(), tiles_data.end(), SweepOrder(dim) );
+
+// std::printf("\nFind intersections: tiles_data.size():%u\n", tiles_data.size() );
+
+ for (unsigned i=0; i+1<tiles_data.size(); i++){
+ //std::printf("\ni=%u (%u([%f,%f]))\n", i, tiles_data[i].curve, tiles_data[i].f, tiles_data[i].t );
+ std::vector<SmashIntersection> inters_on_i;
+ for (unsigned j=i+1; j<tiles_data.size(); j++){
+ //std::printf(" j=%u (%u)\n", j,tiles_data[j].curve );
+ if ( Point::LexLessRt(dim)(tiles_data[i].max(), tiles_data[j].min()) ) break;
+
+ unsigned pi = tiles_data[i].path;
+ unsigned ci = tiles_data[i].curve;
+ unsigned pj = tiles_data[j].path;
+ unsigned cj = tiles_data[j].curve;
+ std::vector<SmashIntersection> intersections;
+
+ intersections = monotonic_smash_intersect(paths[pi][ci], Interval(tiles_data[i].f, tiles_data[i].t),
+ paths[pj][cj], Interval(tiles_data[j].f, tiles_data[j].t), tol );
+ inters_on_i.insert( inters_on_i.end(), intersections.begin(), intersections.end() );
+ std::vector<std::pair<Interval, Rect> > cuts = process_intersections(intersections, 1, j);
+
+// std::printf(" >|%u/%u|=%u. times_j:%u", i, j, crossings.size(), times_j.size() );
+
+ splitTile(j, cuts, false);
+ j += cuts.size()-2;
+ }
+
+ //process_splits(times_i, tiles_data[i].f, tiles_data[i].t);
+ //assert(times_i.size()>=2);
+ //splitTile(i, times_i, tol, false);
+ //i+=times_i.size()-2;
+ std::vector<std::pair<Interval, Rect> > cuts_on_i = process_intersections(inters_on_i, 0, i);
+ splitTile(i, cuts_on_i, false);
+ i += cuts_on_i.size()-2;
+ //std::printf("new i:%u, tiles_data: %u\n",i ,tiles_data.size());
+ //std::sort(tiles_data.begin()+i+1, tiles_data.end(), SweepOrder(dim) );
+ std::sort(tiles_data.begin()+i+1, tiles_data.end(), SweepOrder(dim) );
+ }
+ //this last sorting should be useless!!
+ std::sort(tiles_data.begin(), tiles_data.end(), SweepOrder(dim) );
+ }
+
+ void sortTiles(){
+ std::sort(tiles.begin(), tiles.end(), PtrSweepOrder(tiles_data.begin(), dim) );
+ }
+
+
+ //-------------------------------
+ //-- Vertices boxes cookup.
+ //-------------------------------
+
+ void fuseInsert(const Rect &b, std::vector<Rect> &boxes, Dim2 dim){
+ //TODO: this can be optimized...
+ for (unsigned i=0; i<boxes.size(); i++){
+ if ( Point::LexLessRt(dim)( b.max(), boxes[i].min() ) ) break;
+ if ( b.intersects( boxes[i] ) ){
+ Rect bigb = b;
+ bigb.unionWith( boxes[i] );
+ boxes.erase( boxes.begin()+i );
+ fuseInsert( bigb, boxes, dim);
+ return;
+ }
+ }
+ std::vector<Rect>::iterator pos = std::lower_bound(boxes.begin(), boxes.end(), b, SweepOrder(dim) );
+ boxes.insert( pos, b );
+ }
+
+ //debug only!!
+ bool isContained(Rect b, std::vector<Rect> const &boxes ){
+ for (const auto & boxe : boxes){
+ if ( boxe.contains(b) ) return true;
+ }
+ return false;
+ }
+
+ //Collect vertex boxes. Fuse overlapping ones.
+ //NB: enlarging a vertex may create intersection with already scanned ones...
+ std::vector<Rect> collectBoxes(){
+ std::vector<Rect> ret;
+ for (auto & i : tiles_data){
+ fuseInsert(i.fbox, ret, dim);
+ fuseInsert(i.tbox, ret, dim);
+ }
+ return ret;
+ }
+
+ //enlarge tiles ends to match the vertices bounding boxes.
+ //remove edges fully contained in one vertex bbox.
+ void enlargeTilesEnds(const std::vector<Rect> &boxes ){
+ for (unsigned i=0; i<tiles_data.size(); i++){
+ std::vector<Rect>::const_iterator f_it;
+ f_it = std::lower_bound(boxes.begin(), boxes.end(), tiles_data[i].fbox, SweepOrder(dim) );
+ if ( f_it==boxes.end() ) f_it--;
+ while (!(*f_it).contains(tiles_data[i].fbox) && f_it != boxes.begin()){
+ f_it--;
+ }
+ assert( (*f_it).contains(tiles_data[i].fbox) );
+ tiles_data[i].fbox = *f_it;
+
+ std::vector<Rect>::const_iterator t_it;
+ t_it = std::lower_bound(boxes.begin(), boxes.end(), tiles_data[i].tbox, SweepOrder(dim) );
+ if ( t_it==boxes.end() ) t_it--;
+ while (!(*t_it).contains(tiles_data[i].tbox) && t_it != boxes.begin()){
+ t_it--;
+ }
+ assert( (*t_it).contains(tiles_data[i].tbox) );
+ tiles_data[i].tbox = *t_it;
+
+ //NB: enlarging the ends may swapp their sweep order!!!
+ tiles_data[i].reversed = Point::LexLessRt(dim)( tiles_data[i].tbox.min(), tiles_data[i].fbox.min());
+
+ if ( f_it==t_it ){
+ tiles_data.erase(tiles_data.begin()+i);
+ i-=1;
+ }
+ }
+ }
+
+ //Make sure tiles stop at vertices. Split them if needed.
+ //Returns true if at least one tile was split.
+ bool splitTilesThroughFatPoints(std::vector<Rect> &boxes ){
+
+ std::sort(tiles.begin(), tiles.end(), PtrSweepOrder(tiles_data.begin(), dim) );
+ std::sort(boxes.begin(), boxes.end(), SweepOrder(dim) );
+
+ bool result = false;
+ for (unsigned i=0; i<tiles_data.size(); i++){
+ for (auto & boxe : boxes){
+ if ( Point::LexLessRt(dim)( tiles_data[i].max(), boxe.min()) ) break;
+ if ( Point::LexLessRt(dim)( boxe.max(), tiles_data[i].min()) ) continue;
+ if ( !boxe.intersects( tiles_data[i].bbox() ) ) continue;
+ if ( tiles_data[i].fbox.intersects( boxe ) ) continue;
+ if ( tiles_data[i].tbox.intersects( boxe ) ) continue;
+
+ //at this point box[k] intersects the curve bbox away from the fbox and tbox.
+
+ D2<SBasis> c = tileToSB( tiles_data[i] );
+//----------> use level-set!!
+ for (unsigned corner=0; corner<4; corner++){
+ unsigned D = corner % 2;
+ double val = boxe.corner(corner)[D];
+ std::vector<double> times = roots( c[D] - val );
+ if ( times.size()>0 ){
+ double t = lerp( times.front(), tiles_data[i].f, tiles_data[i].t );
+ double hit_place = c[1-D](times.front());
+ if ( boxe[1-D].contains(hit_place) ){
+ result = true;
+ //taking a point on the boundary is dangerous!!
+ //Either use >0 tolerance here, or find 2 intersection points and split in between.
+ splitTile( i, t, tol, false);
+ break;
+ }
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+
+
+
+
+ //TODO: rewrite all this!...
+ //-------------------------------------------------------------------------------------------
+ //-------------------------------------------------------------------------------------------
+ //-------------------------------------------------------------------------------------------
+ //-------------------------------
+ //-- ccw Sorting of rays around a vertex.
+ //-------------------------------
+ //-------------------------------------------------------------------------------------------
+ //-------------------------------------------------------------------------------------------
+ //-------------------------------------------------------------------------------------------
+ //returns an (infinite) rect around "a" separating it from "b". Nota: 3 sides are infinite!
+ //TODO: place the cut where there is most space...
+ OptRect separate(Rect const &a, Rect const &b){
+ Rect ret ( Interval( -infinity(), infinity() ) , Interval(-infinity(), infinity() ) );
+ double gap = 0;
+ unsigned dir = 4;
+ if (b[X].min() - a[X].max() > gap){
+ gap = b[X].min() - a[X].max();
+ dir = 0;
+ }
+ if (a[X].min() - b[X].max() > gap){
+ gap = a[X].min() - b[X].max();
+ dir = 1;
+ }
+ if (b[Y].min() - a[Y].max() > gap){
+ gap = b[Y].min() - a[Y].max();
+ dir = 2;
+ }
+ if (a[Y].min() - b[Y].max() > gap){
+ gap = a[Y].min() - b[Y].max();
+ dir = 3;
+ }
+ switch (dir) {
+ case 0: ret[X].setMax(( a.max()[X] + b.min()[X] )/ 2); break;
+ case 1: ret[X].setMin(( b.max()[X] + a.min()[X] )/ 2); break;
+ case 2: ret[Y].setMax(( a.max()[Y] + b.min()[Y] )/ 2); break;
+ case 3: ret[Y].setMin(( b.max()[Y] + a.min()[Y] )/ 2); break;
+ case 4: return OptRect();
+ }
+ return OptRect(ret);
+ }
+
+ //Find 4 lines (returned as a Rect sides) that cut all the rays (=edges). *!* some side might be infinite.
+ OptRect isolateVertex(Rect const &box){
+ OptRect sep ( Interval( -infinity(), infinity() ) , Interval(-infinity(), infinity() ) );
+ //separate this vertex from the others. Find a better way.
+ for (auto & vtxboxe : vtxboxes){
+ if ( Point::LexLessRt(dim)( sep->max(), vtxboxe.min() ) ){
+ break;
+ }
+ if ( vtxboxe!=box ){//&& !vtxboxes[i].intersects(box) ){
+ OptRect sepi = separate(box, vtxboxe);
+ if ( sep && sepi ){
+ sep = intersect(*sep, *sepi);
+ }else{
+ std::cout<<"box="<<box<<"\n";
+ std::cout<<"vtxboxes[i]="<<vtxboxe<<"\n";
+ assert(sepi);
+ }
+ }
+ }
+ if (!sep) THROW_EXCEPTION("Invalid intersection data.");
+ return sep;
+ }
+
+ //TODO: argh... rewrite to have "dim"=min first place.
+ struct ExitPoint{
+ public:
+ unsigned side; //0:y=min; 1:x=max; 2:y=max; 3:x=min.
+ double place; //x or y value on the exit line.
+ unsigned ray_idx;
+ double time; //exit time on curve.
+ ExitPoint(){}
+ ExitPoint(unsigned s, double p, unsigned r, double t){
+ side =s;
+ place = p;
+ ray_idx = r;
+ time = t;
+ }
+ };
+
+
+ class ExitOrder{
+ public:
+ bool operator()(Ray a, Ray b) const {
+ if ( a.exit_side < b.exit_side ) return true;
+ if ( a.exit_side > b.exit_side ) return false;
+ if ( a.exit_side <= 1) {
+ return ( a.exit_place < b.exit_place );
+ }
+ return ( a.exit_place > b.exit_place );
+ }
+ };
+
+ void printRay(Ray const &r){
+ std::printf("Ray: tile=%u, centrifuge=%u, side=%u, place=%f\n",
+ r.tile, r.centrifuge, r.exit_side, r.exit_place);
+ }
+ void printVertex(FatVertex const &v){
+ std::printf("Vertex: [%f,%f]x[%f,%f]\n", v[X].min(),v[X].max(),v[Y].min(),v[Y].max() );
+ for (const auto & ray : v.rays){
+ printRay(ray);
+ }
+ }
+
+ //TODO: use a partial order on input coming from the context + Try quadrant order just in case it's enough.
+ //TODO: use monotonic assumption.
+ void sortRays( FatVertex &v ){
+ OptRect sep = isolateVertex(v);
+
+ for (unsigned i=0; i < v.rays.size(); i++){
+ v.rays[i].centrifuge = (tiles_data[ v.rays[i].tile ].fbox == v);
+ v.rays[i].exit_time = v.rays[i].centrifuge ? 1 : 0 ;
+ }
+
+ for (unsigned i=0; i < v.rays.size(); i++){
+ //TODO: don't convert each time!!!
+ assert( v.rays[i].tile < tiles_data.size() );
+ D2<SBasis> c = tileToSB( tiles_data[ v.rays[i].tile ] );
+
+ for (unsigned side=0; side<4; side++){//scan X or Y direction, on level min or max...
+ double level = sep->corner( side )[1-side%2];
+ if (level != infinity() && level != -infinity() ){
+ std::vector<double> times = roots(c[1-side%2]-level);
+ if ( times.size() > 0 ) {
+ double t;
+ assert( v.rays[i].tile < tiles_data.size() );
+ if (tiles_data[ v.rays[i].tile ].fbox == v){
+ t = times.front();
+ if ( v.rays[i].exit_side > 3 || v.rays[i].exit_time > t ){
+ v.rays[i].setExitInfo( side, c[side%2](t), t);
+ }
+ }else{
+ t = times.back();
+ if ( v.rays[i].exit_side > 3 || v.rays[i].exit_time < t ){
+ v.rays[i].setExitInfo( side, c[side%2](t), t);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //Rk: at this point, side == 4 means the edge is contained in the intersection box (?)...;
+ std::sort( v.rays.begin(), v.rays.end(), ExitOrder() );
+ }
+
+
+ //-------------------------------
+ //-- initialize all data.
+ //-------------------------------
+
+ Sweeper(){}
+ Sweeper(PathVector const &input_paths, Dim2 sweep_dir, double tolerance=1e-5){
+ paths = input_paths;//use a ptr...
+ dim = sweep_dir;
+ tol = tolerance;
+
+ //split paths into monotonic tiles
+ createMonotonicTiles();
+
+ //split at tiles intersections
+ splitIntersectingTiles();
+
+ //handle overlapping end boxes/and tiles traversing boxes.
+ do{
+ vtxboxes = collectBoxes();
+ }while ( splitTilesThroughFatPoints(vtxboxes) );
+
+ enlargeTilesEnds(vtxboxes);
+
+ //now create the pointers to the tiles.
+ tiles = std::vector<unsigned>(tiles_data.size(), 0);
+ for (unsigned i=0; i<tiles_data.size(); i++){
+ tiles[i] = i;
+ }
+ sortTiles();
+
+ //initialize the context.
+ if (tiles_data.size()>0){
+ context.clear();
+ context.last_pos = tiles_data[tiles.front()].min();
+ context.last_pos[dim] -= 1;
+ context.pending_vertex = FatVertex();
+ context.pending_event = Event();
+ }
+
+// std::printf("Sweeper initialized (%u tiles)\n", tiles_data.size());
+ }
+
+
+ //-------------------------------
+ //-- Event walk.
+ //-------------------------------
+
+
+ Event getNextEvent(){
+// std::printf("getNextEvent():\n");
+
+// std::printf("initial contex:\n");
+// printContext();
+ Event old_event = context.pending_event, event;
+// std::printf("apply old event\n");
+ applyEvent(context.pending_event);
+// printContext();
+
+ if (context.pending_vertex.rays.size()== 0){
+// std::printf("cook up a new vertex\n");
+
+ //find the edges at the next vertex.
+ //TODO: implement this as a lower bound!!
+ std::vector<unsigned>::iterator low, high;
+ //Warning: bad looking test, but make sure we advance even in case of 0 width boxes...
+ for ( low = tiles.begin(); low != tiles.end() &&
+ ( tiles_data[*low].state==1 || Point::LexLessRt(dim)(tiles_data[*low].cur_box().min(), context.last_pos) ); low++){}
+
+ if ( low == tiles.end() ){
+// std::printf("no more event found\n");
+ return(Event());
+ }
+ Rect pos = tiles_data[ *low ].cur_box();
+ context.last_pos = pos.min();
+ context.last_pos[1-dim] = pos.max()[1-dim];
+
+// printContext();
+// std::printf("purgeDeadTiles\n");
+ purgeDeadTiles();
+// printContext();
+
+ FatVertex v(pos);
+ high = low;
+ do{
+// v.rays.push_back( Ray(*high, !tiles_data[*high].open) );
+ v.rays.push_back( Ray(*high, tiles_data[*high].state!=0) );
+ high++;
+ }while( high != tiles.end() && tiles_data[ *high ].cur_box()==pos );
+
+// std::printf("sortRays\n");
+ sortRays(v);
+
+ //Look for an opened tile
+ unsigned i=0;
+
+ for( i=0; i<v.rays.size(); ++i){assert( v.rays[i].tile<tiles_data.size() );}
+// for( i=0; i<v.rays.size() && !tiles_data[ v.rays[i].tile ].open; ++i){}
+ for( i=0; i<v.rays.size() && tiles_data[ v.rays[i].tile ].state!=0; ++i){}
+
+ //if there are only openings:
+ if (i == v.rays.size() ){
+// std::printf("only openings!\n");
+ event.insert_at = contextRanking(pos.min());
+ }
+ //if there is at least one closing: make it first, and catch 'insert_at'.
+ else{
+// std::printf("not only openings\n");
+ if( i > 0 ){
+ std::vector<Ray> head;
+ head.assign ( v.rays.begin(), v.rays.begin()+i );
+ v.rays.erase ( v.rays.begin(), v.rays.begin()+i );
+ v.rays.insert( v.rays.end(), head.begin(), head.end());
+ }
+ //assert( tiles_data[ v.rays[0].tile ].open );
+ assert( tiles_data[ v.rays[0].tile ].state==0 );
+ event.insert_at = context.find( v.rays.front().tile )+1;
+// event.erase_at = context.find( v.rays.front().tile );
+// std::printf("at least one closing!\n");
+ }
+ context.pending_vertex = v;
+ }else{
+// std::printf("continue biting exiting vertex\n");
+ event.tile = context.pending_vertex.rays.front().tile;
+ event.insert_at = old_event.insert_at;
+// if (old_event.opening){
+// event.insert_at++;
+// }else{
+// if (old_event.erase_at < old_event.insert_at){
+// event.insert_at--;
+// }
+// }
+ event.insert_at++;
+ }
+ event.tile = context.pending_vertex.rays.front().tile;
+// event.opening = !tiles_data[ event.tile ].open;
+ event.opening = tiles_data[ event.tile ].state!=0;
+ event.to_be_continued = context.pending_vertex.rays.size()>1;
+// if ( !event.opening ) event.erase_at = context.find(event.tile);
+
+ context.pending_vertex.rays.erase(context.pending_vertex.rays.begin());
+ context.pending_event = event;
+// printEvent(event);
+ return event;
+ }
+};
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/topology.cpp b/src/3rdparty/2geom/src/toys/topology.cpp
new file mode 100644
index 0000000..25830ce
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/topology.cpp
@@ -0,0 +1,668 @@
+#include <2geom/path.h>
+#include <2geom/svg-path-parser.h>
+#include <2geom/path-intersection.h>
+#include <2geom/basic-intersection.h>
+#include <2geom/pathvector.h>
+#include <2geom/exception.h>
+
+#include <vector>
+#include <algorithm>
+#include "sweeper.cpp"
+
+/*
+Topology Class:
+This class mainly consists in 3 vectors: vertices, edges, and areas.
+-edges: have start/end, left/right pointing to vertices or areas.
+-vertices: have a "boundary"= the sequence of edges sorted in CCW order.
+-areas: have one outer "boundary" + a vector of inner boundaries, which are
+ sequence of edges.
+
+To build this data, the strategy is to let a line sweep the plane (from left
+to right, say) and consider the topology of what is on the left of the sweep line.
+Topology changes are called events, and we call an external "sweeper" to generate
+them for us.
+
+So we start with an empty data, and respond to events to always describe the
+topology of what is on the left of the sweep line. [more precisely, we start with
+one region that has empty boundary, and since the external sweeper knows how many
+edges we'll have at the end, so we create them from scratch, leaving their ends
+as "unknown"]
+
+Note: see the sweeper for more info about events; they are essentially generated
+when the sweep line crosses a vertex (which is in fact a box), but are in fact split
+into smaller events, one for each edge around the vertex...
+
+
+The code is using a lot of vectors: unsing pointers instead of vectors could speed
+things up (?), but vector indices are easier to debug than memory addresses.:P
+*/
+
+using namespace Geom;
+using namespace std;
+
+class Topology {
+public:
+
+ // -!- convention:
+ // In a boundary, reversed edges point away from the vertex or CW around the area.
+ struct OrientedEdge{
+ unsigned edge; //edge index.
+ bool reversed; //true if the intrinsic edge orientation points away (from vertex) or backward (along area boundary)
+ OrientedEdge(unsigned edge_idx, bool o){
+ edge = edge_idx;
+ reversed = o;
+ }
+ OrientedEdge(){
+ edge = NULL_IDX;
+ reversed = false;
+ }
+ bool operator == ( OrientedEdge const &other) const {
+ return (edge == other.edge && edge!=NULL_IDX && reversed == other.reversed);
+ }
+ };
+
+ class Boundary : public std::vector<OrientedEdge>{
+ public:
+ bool of_area;//true if this is the boundary of an area. Fix this with templates?
+ Boundary(bool area_type): of_area(area_type){}
+ };
+
+ class Vertex{
+ public:
+ Boundary boundary; // list of edges in CCW order around the vertex
+ Geom::Rect bounds;
+ Vertex():boundary(false){}
+ };
+
+ class Area {//an area is a connected comp of the complement of the graph. .
+ public:
+ Boundary boundary; // outermost boundary component, CCW oriented (i.e. area is on the left of the boundary).
+ std::vector<Boundary> inner_boundaries;//same conventions, area on the left, so this gives the CW orientation for inner components.
+ std::vector<int> windings;//one winding number for each input path.
+ Area(unsigned size): boundary(true), windings(size, 0){}
+ };
+
+ class Edge {
+ public:
+ unsigned left, right;// the indices of the areas on the left and on the right this edge.
+ unsigned start, end; // the indices of vertices at start and at end of this edge.
+ Geom::Interval portion;
+ unsigned path;
+ unsigned curve;
+ Edge(){
+ left = NULL_IDX;
+ right =NULL_IDX;
+ start = NULL_IDX;
+ end = NULL_IDX;
+ portion = Interval();
+ path = NULL_IDX;
+ curve = NULL_IDX;
+ }
+ };
+
+ vector<Area> areas;
+ vector<Edge> edges;
+ vector<Vertex> vertices;
+
+ PathVector input_paths;//we don't need our own copy...
+ cairo_t* cr;
+
+ //debug only!!
+ int steps_max;
+ //----------
+
+
+ //----------------------------------------------------
+ //-- utils...
+ //----------------------------------------------------
+
+ void printIdx(unsigned idx){ (idx == NULL_IDX)? std::printf("?") : std::printf("%u", idx); }
+ void printVertex(unsigned i){
+ std::printf("vertex %u: ", i);
+ printBoundary(vertices[i].boundary);
+ std::printf("\n");
+ }
+ void printEdge(unsigned i){
+ std::printf("edge %u: ", i);
+ printIdx(edges[i].start);
+ std::printf(" -> ");
+ printIdx(edges[i].end);
+ std::printf(" ^");
+ printIdx(edges[i].left);
+ std::printf(" _");
+ printIdx(edges[i].right);
+ std::printf("\n");
+ }
+ void printArea(unsigned i){
+ std::printf("area %u: ", i);
+ printBoundary(areas[i].boundary);
+ for (auto & inner_boundarie : areas[i].inner_boundaries){
+ std::printf(", ");
+ printBoundary(inner_boundarie);
+ }
+ std::printf("\n");
+ }
+
+ void printOrientedEdge(OrientedEdge const &f){
+ ( f.reversed ) ? std::printf("-") : std::printf("+");
+ printIdx(f.edge);
+ std::printf(" ");
+ }
+ void printBoundary(Boundary const &bndry){
+ (bndry.of_area) ? std::printf("[") : std::printf("<");
+ for (unsigned i=0; i<bndry.size(); i++){
+ printOrientedEdge(bndry[i]);
+ }
+ (bndry.of_area) ? std::printf("]") : std::printf(">");
+ }
+
+ void print(){
+ std::cout<<"\nCrossing Data:\n";
+ for (unsigned i=0; i<vertices.size(); i++){
+ printVertex(i);
+ }
+ std::cout<<"\n";
+ for (unsigned i=0; i<edges.size(); i++){
+ printEdge(i);
+ }
+ std::cout<<"\n";
+ for (unsigned i=0; i<areas.size(); i++){
+ printArea(i);
+ }
+ }
+
+ D2<SBasis> edgeAsSBasis(unsigned e){
+ //beurk! optimize me.
+ D2<SBasis> c = input_paths[edges[e].path][edges[e].curve].toSBasis();
+ return portion(c, edges[e].portion);
+ }
+
+ Path edgeToPath(Topology::OrientedEdge o_edge){
+ Topology::Edge e = edges[o_edge.edge];
+ D2<SBasis> p = input_paths[e.path][e.curve].toSBasis();
+ Interval dom = e.portion;
+ p = portion(p, dom);
+ if ( o_edge.reversed ){
+ p = compose( p, Linear(1.,0.) );
+ }
+ Path ret;
+ ret.setStitching(true);
+ Point center;
+ unsigned c_idx = source(o_edge, true);
+ if ( c_idx == NULL_IDX ){
+ ret.append(p);
+ }else{
+ center = vertices[c_idx].bounds.midpoint();
+ ret = Path(center);
+ ret.append(p);
+ }
+ c_idx = target(o_edge, true);
+ if ( c_idx == NULL_IDX ){
+ return ret;
+ }else{
+ center = vertices[c_idx].bounds.midpoint();
+ if ( center != p.at1() ) ret.appendNew<LineSegment>(center);
+ return ret;
+ }
+ }
+
+ Path boundaryToPath(Topology::Boundary b){
+ Point pt;
+ Path bndary;
+ bndary.setStitching(true);
+
+ if (b.size()==0){ return Path(); }
+
+ Topology::OrientedEdge o_edge = b.front();
+ unsigned first_v = source(o_edge, true);
+ if ( first_v != NULL_IDX ){
+ pt = vertices[first_v].bounds.midpoint();
+ bndary = Path(pt);
+ }
+
+ for (unsigned i = 0; i < b.size(); i++){
+ bndary.append( edgeToPath(b[i]));
+ }
+ bndary.close();
+ return bndary;
+ }
+
+
+
+ //----------------------------------------------------
+ //-- Boundary Navigation/Modification
+ //----------------------------------------------------
+
+ //TODO: this should be an OrientedEdge method, be requires access to the edges.
+ unsigned source(OrientedEdge const &f, bool as_area_bndry){
+ unsigned prev;
+ if (f.reversed )
+ prev = (as_area_bndry)? edges[f.edge].end : edges[f.edge].right;
+ else
+ prev = (as_area_bndry)? edges[f.edge].start : edges[f.edge].left;
+ return prev;
+ }
+ unsigned target(OrientedEdge const &f, bool as_area_bndry){
+ unsigned prev;
+ if (f.reversed )
+ prev = (as_area_bndry)? edges[f.edge].start : edges[f.edge].left;
+ else
+ prev = (as_area_bndry)? edges[f.edge].end : edges[f.edge].right;
+ return prev;
+ }
+
+ //TODO: this should be a Boundary method, but access to the full data is required...
+ bool prolongate( Boundary &bndry, OrientedEdge const &f){
+ if ( bndry.empty() ){
+ bndry.push_back(f);
+ return true;
+ }
+ unsigned src = source(f, bndry.of_area);
+ if ( src == target( bndry.back(), bndry.of_area ) && src != NULL_IDX ){
+ bndry.push_back(f);
+ return true;
+ }
+ unsigned tgt = target( f, bndry.of_area );
+ if ( tgt == source( bndry.front(), bndry.of_area ) && tgt != NULL_IDX ){
+ bndry.insert( bndry.begin(), f);
+ return true;
+ }
+ return false;
+ }
+
+ bool prolongate(Boundary &a, Boundary &b){
+ if (a.size()==0 || b.size()==0 || (a.of_area != b.of_area) ) return false;
+ unsigned src;
+ src = source(a.front(), a.of_area);
+
+// unsigned af = a.front().edge, as=source(a.front(), a.of_area), ab=a.back().edge, at=target(a.back(), a.of_area);
+// unsigned bf = b.front().edge, bs=source(b.front(), b.of_area), bb=b.back().edge, bt=target(b.back(), b.of_area);
+// std::printf("a=%u(%u)...(%u)%u\n", as, af,ab,at);
+// std::printf("b=%u(%u)...(%u)%u\n", bs, bf,bb,bt);
+
+// std::printf("%u == %u?\n", src, target( b.back(), b.of_area ));
+ if ( src == target( b.back(), b.of_area ) && src != NULL_IDX ){
+ a.insert( a.begin(), b.begin(), b.end() );
+// std::printf("boundaries fused!!\n");
+ return true;
+ }
+ src = source(b.front(), b.of_area);
+ if ( src == target( a.back(), a.of_area ) && src != NULL_IDX ){
+ a.insert( a.end(), b.begin(), b.end() );
+ return true;
+ }
+ return false;
+ }
+
+ //TODO: this should be a Boundary or Area method, but requires access to the full data...
+ //TODO: systematically check for connected boundaries before returning?
+ void addAreaBoundaryPiece(unsigned a, OrientedEdge const &f){
+ if ( areas[a].boundary.size()>0 && prolongate( areas[a].boundary, f ) ) return;
+ for (auto & inner_boundarie : areas[a].inner_boundaries){
+// printBoundary(areas[a].inner_boundaries[i]);
+// printf(" matches ");
+// printOrientedEdge(f);
+// printf("?");
+ if ( inner_boundarie.size()>0 && prolongate( inner_boundarie, f) ) return;
+// printf("no. (%u vs %u)", target(areas[a].inner_boundaries[i].back(), true), source(f, true));
+ }
+ Boundary new_comp(true);
+ new_comp.push_back(f);
+ areas[a].inner_boundaries.push_back(new_comp);
+ }
+
+
+ bool fuseConnectedBoundaries(unsigned a){
+// std::printf(" fuseConnectedBoundaries %u\n",a);
+
+ bool ret = false;
+ if ( areas[a].boundary.size()>0 ){
+ for ( unsigned i=0; i<areas[a].inner_boundaries.size(); i++){
+ if ( prolongate( areas[a].boundary, areas[a].inner_boundaries[i] ) ){
+ areas[a].inner_boundaries.erase(areas[a].inner_boundaries.begin()+i);
+ i--;
+ ret = true;
+ }
+ }
+ }
+ for ( unsigned i=0; i<areas[a].inner_boundaries.size(); i++){
+ for ( unsigned j=i+1; j<areas[a].inner_boundaries.size(); j++){
+ if ( prolongate( areas[a].inner_boundaries[i], areas[a].inner_boundaries[j] ) ){
+ areas[a].inner_boundaries.erase(areas[a].inner_boundaries.begin()+j);
+ j--;
+ ret = true;
+ }
+ }
+ }
+ return ret;
+ }
+
+ //-------------------------------
+ //-- Some basic area manipulation.
+ //-------------------------------
+
+ void renameArea(unsigned oldi, unsigned newi){
+ for (auto & edge : edges){
+ if ( edge.left == oldi ) edge.left = newi;
+ if ( edge.right == oldi ) edge.right = newi;
+ }
+ }
+ void deleteArea(unsigned a0){//ptrs would definitely be helpful here...
+ assert(a0<areas.size());
+ for (unsigned a=a0+1; a<areas.size(); a++){
+ renameArea(a,a-1);
+ }
+ areas.erase(areas.begin()+a0);
+ }
+
+ //fuse open(=not finished!) areas. The boundaries are supposed to match. true on success.
+ void fuseAreas(unsigned a, unsigned b){
+// std::printf("fuse Areas %u and %u\n", a, b);
+ if (a==b) return;
+ if (a>b) swap(a,b);//this is important to keep track of the outermost component!!
+
+ areas[a].inner_boundaries.push_back(areas[b].boundary);
+ for (unsigned i=0; i<areas[b].inner_boundaries.size(); i++){
+ areas[a].inner_boundaries.push_back(areas[b].inner_boundaries[i]);
+ }
+ renameArea(b,a);
+ deleteArea(b);
+ assert( fuseConnectedBoundaries(a) );
+ return;
+ }
+
+ PathVector areaToPath(unsigned a){
+ PathVector bndary;
+ if ( areas[a].boundary.size()!=0 ){//this is not the unbounded component...
+ bndary.push_back( boundaryToPath(areas[a].boundary ) );
+ }
+ for (auto & inner_boundarie : areas[a].inner_boundaries){
+ bndary.push_back( boundaryToPath(inner_boundarie) );
+ }
+ return bndary;
+ }
+
+ //DEBUG ONLY: we add a rect round the unbounded comp, and glue the bndries
+ //for easy drawing in the toys...
+ Path glued_areaToPath(unsigned a){
+ Path bndary;
+ if ( areas[a].boundary.size()==0 ){//this is the unbounded component...
+ OptRect bbox = bounds_fast( input_paths );
+ if (!bbox ){return Path();}//???
+ bbox->expandBy(50);
+ bndary = Path(bbox->corner(0));
+ bndary.appendNew<LineSegment>(bbox->corner(1));
+ bndary.appendNew<LineSegment>(bbox->corner(2));
+ bndary.appendNew<LineSegment>(bbox->corner(3));
+ bndary.appendNew<LineSegment>(bbox->corner(0));
+ }else{
+ bndary = boundaryToPath(areas[a].boundary);
+ }
+ for (auto & inner_boundarie : areas[a].inner_boundaries){
+ bndary.append( boundaryToPath(inner_boundarie));
+ bndary.appendNew<LineSegment>( bndary.initialPoint() );
+ }
+ bndary.close();
+ return bndary;
+ }
+
+ void drawAreas( cairo_t *cr, bool fill=true ){
+ //don't draw the first one...
+ for (unsigned a=0; a<areas.size(); a++){
+ drawArea(cr, a, fill);
+ }
+ }
+ void drawArea( cairo_t *cr, unsigned a, bool fill=true ){
+ if (a>=areas.size()) return;
+ Path bndary = glued_areaToPath(a);
+ cairo_path(cr, bndary);
+ if (fill){
+ cairo_fill(cr);
+ }else{
+ cairo_stroke(cr);
+ }
+ }
+ void highlightRay( cairo_t *cr, unsigned b, unsigned r ){
+ if (b>=vertices.size()) return;
+ if (r>=vertices[b].boundary.size()) return;
+ Rect box = vertices[b].bounds;
+ //box.expandBy(2);
+ cairo_rectangle(cr, box);
+ cairo_set_source_rgba (cr, 1., 0., 0, 1.0);
+ cairo_set_line_width (cr, 1);
+ cairo_fill(cr);
+ unsigned eidx = vertices[b].boundary[r].edge;
+ Topology::Edge e = edges[eidx];
+ D2<SBasis> p = input_paths[e.path][e.curve].toSBasis();
+ Interval dom = e.portion;
+ if (vertices[b].boundary[r].reversed){
+ //dom[0] += e.portion.extent()*2./3;
+ cairo_set_source_rgba (cr, 0., 1., 0., 1.0);
+ }else{
+ //dom[1] -= e.portion.extent()*2./3;
+ cairo_set_source_rgba (cr, 0., 0., 1., 1.0);
+ }
+ p = portion(p, dom);
+ cairo_d2_sb(cr, p);
+ cairo_set_source_rgba (cr, 1., 0., 0, 1.0);
+ cairo_set_line_width (cr, 5);
+ cairo_stroke(cr);
+ }
+
+ void drawEdge( cairo_t *cr, unsigned eidx ){
+ if (eidx>=edges.size()) return;
+ Topology::Edge e = edges[eidx];
+ D2<SBasis> p = input_paths[e.path][e.curve].toSBasis();
+ Interval dom = e.portion;
+ p = portion(p, dom);
+ cairo_d2_sb(cr, p);
+ if (e.start == NULL_IDX || e.end == NULL_IDX )
+ cairo_set_source_rgba (cr, 0., 1., 0, 1.0);
+ else
+ cairo_set_source_rgba (cr, 0., 0., 0, 1.0);
+ cairo_set_line_width (cr, 1);
+ cairo_stroke(cr);
+ }
+ void drawEdges( cairo_t *cr){
+ for (unsigned e=0; e<edges.size(); e++){
+ drawEdge(cr, e);
+ }
+ }
+ void drawKnownEdges( cairo_t *cr){
+ for (auto & vertice : vertices){
+ for (unsigned e=0; e<vertice.boundary.size(); e++){
+ drawEdge(cr, vertice.boundary[e].edge);
+ }
+ }
+ }
+
+
+ void drawBox( cairo_t *cr, unsigned b ){
+ if (b>=vertices.size()) return;
+ Rect box = vertices[b].bounds;
+ //box.expandBy(5);
+ cairo_rectangle(cr, box);
+ cairo_set_source_rgba (cr, 1., 0., 0, .5);
+ cairo_set_line_width (cr, 1);
+ cairo_stroke(cr);
+ cairo_rectangle(cr, box);
+ cairo_set_source_rgba (cr, 1., 0., 0, .2);
+ cairo_fill(cr);
+ }
+
+ void drawBoxes( cairo_t *cr){
+ for (unsigned b=0; b<vertices.size(); b++){
+ drawBox(cr, b);
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+ //----------------------------------------------------
+ //-- Fill data using a sweeper...
+ //----------------------------------------------------
+
+ Topology(){}
+ ~Topology(){}
+ Topology(PathVector const &paths, cairo_t* cairo, double tol=EPSILON, int stepsmax=-1){
+// std::printf("\n---------------------\n---------------------\n---------------------\n");
+// std::printf("Topology creation\n");
+ cr = cairo;
+
+ //debug only:
+ steps_max = stepsmax;
+ //-------------
+
+ input_paths = paths;
+
+ vertices.clear();
+ edges.clear();
+ areas.clear();
+ Area empty( input_paths.size() );
+ areas.push_back(empty);
+
+ Sweeper sweeper( paths, X, tol );
+
+ edges = std::vector<Edge>( sweeper.tiles_data.size(), Edge() );
+ for (unsigned i=0; i<edges.size(); i++){
+ edges[i].path = sweeper.tiles_data[i].path;
+ edges[i].curve = sweeper.tiles_data[i].curve;
+ edges[i].portion = Interval(sweeper.tiles_data[i].f, sweeper.tiles_data[i].t);
+ }
+
+ //std::printf("entering event loop:\n");
+ int step=0;
+ for(Sweeper::Event event = sweeper.getNextEvent(); ; event = sweeper.getNextEvent() ){
+// std::printf(" new event received: ");
+ //print();
+ //debug only!!!
+ if ( steps_max >= 0 && step > steps_max ){
+ break;
+ }else{
+ step++;
+ }
+ //---------
+
+ if (event.empty()){
+ //std::printf(" empty event received\n");
+ break;
+ }
+
+ //std::printf(" non empty event received:");
+ //sweeper.printEvent(event);
+
+ //is this a new event or the continuation of an old one?
+ unsigned v;
+ Rect r = sweeper.context.pending_vertex;
+ if (vertices.empty() || !r.intersects( vertices.back().bounds ) ){
+ v = vertices.size();
+ vertices.push_back(Vertex());
+ vertices[v].bounds = r;
+// std::printf(" new intersection created (%u).\n",v);
+ }else{
+ v = vertices.size()-1;
+// std::printf(" continue last intersection (%u).\n",v);
+ }
+
+ //--Closing an edge:-------------
+ if( !event.opening ){
+ unsigned e = event.tile, a, b;
+// std::printf(" closing edge %u\n", e);
+ bool reversed = sweeper.tiles_data[e].reversed;//Warning: true means v==e.start
+ if (reversed){
+ edges[e].start = v;
+ a = edges[e].right;
+ b = edges[e].left;
+ }else{
+ edges[e].end = v;
+ a = edges[e].left;
+ b = edges[e].right;
+ }
+ OrientedEdge vert_edge(e, reversed);
+ if (vertices[v].boundary.size()>0){//Make sure areas are compatible (only relevant if the last event was an opening).
+ fuseAreas ( a, target( vertices[v].boundary.back(), false ) );
+ }
+ assert( prolongate( vertices[v].boundary, vert_edge) );
+ fuseConnectedBoundaries(a);//there is no doing both: tests are performed twice but for 2 areas.
+ fuseConnectedBoundaries(b);//
+ }else{
+ //--Opening an edge:-------------
+ unsigned e = event.tile;
+// std::printf(" opening edge %u\n", e);
+ bool reversed = !sweeper.tiles_data[e].reversed;//Warning: true means v==start.
+
+ //--Find first and last area around this vertex:-------------
+ unsigned cur_a;
+ if ( vertices[v].boundary.size() > 0 ){
+ cur_a = target( vertices[v].boundary.back(), false );
+ }else{//this vertex is empty
+ if ( event.insert_at < sweeper.context.size() ){
+ unsigned upper_tile = sweeper.context[event.insert_at].first;
+ cur_a = (sweeper.tiles_data[upper_tile].reversed) ? edges[upper_tile].left : edges[upper_tile].right;
+ }else{
+ cur_a = 0;
+ }
+ }
+
+ unsigned new_a = areas.size();
+
+ Area new_area(paths.size());
+ new_area.boundary.push_back( OrientedEdge(e, !reversed ) );
+ new_area.windings = areas[cur_a].windings;//FIXME: escape boundary cases!!!
+ if ( input_paths[edges[e].path].closed() ){
+ new_area.windings[edges[e].path] += (reversed) ? +1 : -1;
+ }
+ areas.push_back(new_area);
+
+ //update edge
+ if (reversed){
+ edges[e].start = v;
+ edges[e].left = new_a;
+ edges[e].right = cur_a;
+ }else{
+ edges[e].end = v;
+ edges[e].left = cur_a;
+ edges[e].right = new_a;
+ }
+ //update vertex
+ OrientedEdge f(e, reversed);
+ assert( prolongate( vertices[v].boundary, f) );
+ addAreaBoundaryPiece(cur_a, OrientedEdge(e, reversed) );
+ }
+ if (!event.to_be_continued && vertices[v].boundary.size()>0){
+ unsigned first_a = source( vertices[v].boundary.front(), false );
+ unsigned last_a = target( vertices[v].boundary.back(), false );
+ fuseAreas(first_a, last_a);
+ }
+
+// this->print();
+// std::printf("----------------\n");
+ //std::printf("\n");
+ }
+ }
+
+
+
+ //----------------------------------------------------
+ //-- done.
+ //----------------------------------------------------
+};
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/toy-framework-2.cpp b/src/3rdparty/2geom/src/toys/toy-framework-2.cpp
new file mode 100644
index 0000000..54166cf
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/toy-framework-2.cpp
@@ -0,0 +1,972 @@
+#include <cstring>
+#include <cstdint>
+#include <typeinfo>
+#include <cairo.h>
+#include <gtk/gtk.h>
+#include <toys/toy-framework-2.h>
+
+#include <cairo-features.h>
+#if CAIRO_HAS_PDF_SURFACE
+#include <cairo-pdf.h>
+#endif
+#if CAIRO_HAS_SVG_SURFACE
+#include <cairo-svg.h>
+#endif
+
+GtkApplicationWindow* the_window = nullptr;
+static GtkWidget *the_canvas = nullptr;
+Toy* the_toy = nullptr;
+int the_requested_height = 0;
+int the_requested_width = 0;
+gchar **the_emulated_argv = nullptr;
+
+gchar *arg_spool_filename = nullptr;
+gchar *arg_handles_filename = nullptr;
+gchar *arg_screenshot_filename = nullptr;
+gchar **arg_extra_files = nullptr;
+
+//Utility functions
+
+double uniform() {
+ return double(rand()) / RAND_MAX;
+}
+
+colour colour::from_hsv( float H, // hue shift (in degrees)
+ float S, // saturation shift (scalar)
+ float V, // value multiplier (scalar)
+ float A
+ )
+{
+ double inr = 1;
+ double ing = 0;
+ double inb = 0;
+ float k = V/3;
+ float a = V*S*cos(H)/3;
+ float b = V*S*sin(H)/3;
+
+ return colour(
+ (k+2*a)*inr - 2*b*ing + (k-a-b)*inb,
+ (-k+a+3*b)*inr + (3*a-b)*ing + (-k+a+2*b)*inb,
+ (2*k-2*a)*inr + 2*b*ing + (2*k+a+b)*inb,
+ A);
+}
+
+ // Given H,S,L in range of 0-1
+
+ // Returns a Color (RGB struct) in range of 0-255
+
+colour colour::from_hsl(float h, float sl, float l, float a) {
+ h /= M_PI*2;
+ colour rgba(l,l,l,a); // default to gray
+
+ double v = (l <= 0.5) ? (l * (1.0 + sl)) : (l + sl - l * sl);
+
+ if (v > 0) {
+ double m;
+ double sv;
+ int sextant;
+ double fract, vsf, mid1, mid2;
+
+ m = l + l - v;
+ sv = (v - m ) / v;
+ h *= 6.0;
+ sextant = (int)h;
+ fract = h - sextant;
+ vsf = v * sv * fract;
+ mid1 = m + vsf;
+ mid2 = v - vsf;
+ switch (sextant%6) {
+ case 0:
+ rgba.r = v;
+ rgba.g = mid1;
+ rgba.b = m;
+ break;
+
+ case 1:
+ rgba.r = mid2;
+ rgba.g = v;
+ rgba.b = m;
+ break;
+
+ case 2:
+ rgba.r = m;
+ rgba.g = v;
+ rgba.b = mid1;
+ break;
+
+ case 3:
+ rgba.r = m;
+ rgba.g = mid2;
+ rgba.b = v;
+ break;
+
+ case 4:
+ rgba.r = mid1;
+ rgba.g = m;
+ rgba.b = v;
+ break;
+
+ case 5:
+ rgba.r = v;
+ rgba.g = m;
+ rgba.b = mid2;
+ break;
+ }
+ }
+ return rgba;
+}
+
+void cairo_set_source_rgba(cairo_t* cr, colour c) {
+ cairo_set_source_rgba(cr, c.r, c.g, c.b, c.a);
+}
+
+void draw_text(cairo_t *cr, Geom::Point loc, const char* txt, bool bottom, const char* fontdesc) {
+ PangoLayout* layout = pango_cairo_create_layout (cr);
+ pango_layout_set_text(layout, txt, -1);
+ PangoFontDescription *font_desc = pango_font_description_from_string(fontdesc);
+ pango_layout_set_font_description(layout, font_desc);
+ pango_font_description_free (font_desc);
+ PangoRectangle logical_extent;
+ pango_layout_get_pixel_extents(layout, NULL, &logical_extent);
+ cairo_move_to(cr, loc - Geom::Point(0, bottom ? logical_extent.height : 0));
+ pango_cairo_show_layout(cr, layout);
+}
+
+void draw_text(cairo_t *cr, Geom::Point loc, const std::string& txt, bool bottom, const std::string& fontdesc) {
+ draw_text(cr, loc, txt.c_str(), bottom, fontdesc.c_str());
+}
+
+void draw_number(cairo_t *cr, Geom::Point pos, int num, std::string name, bool bottom) {
+ std::ostringstream number;
+ if (name.size())
+ number << name;
+ number << num;
+ draw_text(cr, pos, number.str().c_str(), bottom);
+}
+
+void draw_number(cairo_t *cr, Geom::Point pos, unsigned num, std::string name, bool bottom) {
+ std::ostringstream number;
+ if (name.size())
+ number << name;
+ number << num;
+ draw_text(cr, pos, number.str().c_str(), bottom);
+}
+
+void draw_number(cairo_t *cr, Geom::Point pos, double num, std::string name, bool bottom) {
+ std::ostringstream number;
+ if (name.size())
+ number << name;
+ number << num;
+ draw_text(cr, pos, number.str().c_str(), bottom);
+}
+
+//Framework Accessors
+void redraw() { gtk_widget_queue_draw(GTK_WIDGET(the_window)); }
+
+void Toy::draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool /*save*/, std::ostringstream *timer_stream)
+{
+ if(should_draw_bounds() == 1) {
+ cairo_set_source_rgba (cr, 0., 0., 0, 0.8);
+ cairo_set_line_width (cr, 0.5);
+ for(unsigned i = 1; i < 4; i+=2) {
+ cairo_move_to(cr, 0, i*width/4);
+ cairo_line_to(cr, width, i*width/4);
+ cairo_move_to(cr, i*width/4, 0);
+ cairo_line_to(cr, i*width/4, height);
+ }
+ }
+ else if(should_draw_bounds() == 2) {
+ cairo_set_source_rgba (cr, 0., 0., 0, 0.8);
+ cairo_set_line_width (cr, 0.5);
+ cairo_move_to(cr, 0, width/2);
+ cairo_line_to(cr, width, width/2);
+ cairo_move_to(cr, width/2, 0);
+ cairo_line_to(cr, width/2, height);
+ }
+
+ cairo_set_line_width (cr, 1);
+ for(auto & handle : handles) {
+ cairo_set_source_rgb (cr, handle->rgb[0], handle->rgb[1], handle->rgb[2]);
+ handle->draw(cr, should_draw_numbers());
+ }
+
+ cairo_set_source_rgba (cr, 0.5, 0, 0, 1);
+ if(selected && mouse_down == true)
+ selected->draw(cr, should_draw_numbers());
+
+ cairo_set_source_rgba (cr, 0.5, 0.25, 0, 1);
+ cairo_stroke(cr);
+
+ cairo_set_source_rgba (cr, 0., 0.5, 0, 0.8);
+ {
+ *notify << std::ends;
+ draw_text(cr, Geom::Point(0, height-notify_offset), notify->str().c_str(), true);
+ }
+ if(show_timings) {
+ *timer_stream << std::ends;
+ draw_text(cr, Geom::Point(0, notify_offset), timer_stream->str().c_str(), false);
+ }
+}
+
+void Toy::mouse_moved(GdkEventMotion* e)
+{
+ Geom::Point mouse(e->x, e->y);
+
+ if(e->state & (GDK_BUTTON1_MASK | GDK_BUTTON3_MASK)) {
+ if(selected)
+ selected->move_to(hit_data, old_mouse_point, mouse);
+ }
+ old_mouse_point = mouse;
+ redraw();
+}
+
+void Toy::mouse_pressed(GdkEventButton* e) {
+ Geom::Point mouse(e->x, e->y);
+ selected = NULL;
+ hit_data = NULL;
+ canvas_click_button = e->button;
+ if(e->button == 1) {
+ for(auto & handle : handles) {
+ void * hit = handle->hit(mouse);
+ if(hit) {
+ selected = handle;
+ hit_data = hit;
+ }
+ }
+ mouse_down = true;
+ }
+ old_mouse_point = mouse;
+ redraw();
+}
+
+void Toy::scroll(GdkEventScroll* /*e*/) {
+}
+
+void Toy::canvas_click(Geom::Point at, int button) {
+ (void)at;
+ (void)button;
+}
+
+void Toy::mouse_released(GdkEventButton* e) {
+ if(selected == NULL) {
+ Geom::Point mouse(e->x, e->y);
+ canvas_click(mouse, canvas_click_button);
+ canvas_click_button = 0;
+ }
+ selected = NULL;
+ hit_data = NULL;
+ if(e->button == 1)
+ mouse_down = false;
+ redraw();
+}
+
+void Toy::load(FILE* f) {
+ char data[1024];
+ if (fscanf(f, "%1024s", data)) {
+ name = data;
+ }
+ for(auto & handle : handles) {
+ handle->load(f);
+ }
+}
+
+void Toy::save(FILE* f) {
+ fprintf(f, "%s\n", name.c_str());
+ for(auto & handle : handles)
+ handle->save(f);
+}
+
+//Gui Event Callbacks
+
+void show_about_dialog(GSimpleAction *, GVariant *, gpointer) {
+ GtkWidget* about_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(about_window), "About");
+ gtk_window_set_resizable(GTK_WINDOW(about_window), FALSE);
+
+ GtkWidget* about_text = gtk_text_view_new();
+ GtkTextBuffer* buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(about_text));
+ gtk_text_buffer_set_text(buf, "Toy lib2geom application", -1);
+ gtk_container_add(GTK_CONTAINER(about_window), about_text);
+
+ gtk_widget_show_all(about_window);
+}
+
+void quit(GSimpleAction *, GVariant *, gpointer) {
+ g_application_quit(g_application_get_default());
+}
+
+Geom::Point read_point(FILE* f) {
+ Geom::Point p;
+ for(unsigned i = 0; i < 2; i++)
+ assert(fscanf(f, " %lf ", &p[i]));
+ return p;
+}
+
+Geom::Interval read_interval(FILE* f) {
+ Geom::Interval p;
+ Geom::Coord a, b;
+ assert(fscanf(f, " %lf ", &a));
+ assert(fscanf(f, " %lf ", &b));
+ p.setEnds(a, b);
+ return p;
+}
+
+void open_handles(GSimpleAction *, GVariant *, gpointer) {
+ if (!the_toy) return;
+ GtkWidget* d = gtk_file_chooser_dialog_new(
+ "Open handle configuration", GTK_WINDOW(the_window), GTK_FILE_CHOOSER_ACTION_OPEN,
+ "Cancel", GTK_RESPONSE_CANCEL, "Open", GTK_RESPONSE_ACCEPT, NULL);
+ if (gtk_dialog_run(GTK_DIALOG(d)) == GTK_RESPONSE_ACCEPT) {
+ const char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d));
+ FILE* f = fopen(filename, "r");
+ the_toy->load(f);
+ fclose(f);
+ }
+ gtk_widget_destroy(d);
+}
+
+void save_handles(GSimpleAction *, GVariant *, gpointer) {
+ if (!the_toy) return;
+ GtkWidget* d = gtk_file_chooser_dialog_new(
+ "Save handle configuration", GTK_WINDOW(the_window), GTK_FILE_CHOOSER_ACTION_SAVE,
+ "Cancel", GTK_RESPONSE_CANCEL, "Save", GTK_RESPONSE_ACCEPT, NULL);
+ if (gtk_dialog_run(GTK_DIALOG(d)) == GTK_RESPONSE_ACCEPT) {
+ const char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d));
+ FILE* f = fopen(filename, "w");
+ the_toy->save(f);
+ fclose(f);
+ }
+ gtk_widget_destroy(d);
+}
+
+void write_image(const char* filename) {
+ cairo_surface_t* cr_s;
+ unsigned l = strlen(filename);
+ int width = gdk_window_get_width(gtk_widget_get_window(the_canvas));
+ int height = gdk_window_get_height(gtk_widget_get_window(the_canvas));
+ bool save_png = false;
+
+ if (l >= 4 && strcmp(filename + l - 4, ".png") == 0) {
+ cr_s = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, width, height );
+ save_png = true;
+ }
+
+#if CAIRO_HAS_PDF_SURFACE
+ else if (l >= 4 && strcmp(filename + l - 4, ".pdf") == 0)
+ cr_s = cairo_pdf_surface_create(filename, width, height);
+#endif
+#if CAIRO_HAS_SVG_SURFACE
+#if CAIRO_HAS_PDF_SURFACE
+ else
+#endif
+ cr_s = cairo_svg_surface_create(filename, width, height);
+#endif
+ cairo_t* cr = cairo_create(cr_s);
+
+ if(save_png) {
+ cairo_save(cr);
+ cairo_set_source_rgb(cr, 1,1,1);
+ cairo_paint(cr);
+ cairo_restore(cr);
+ }
+ if(the_toy != NULL) {
+ std::ostringstream * notify = new std::ostringstream;
+ std::ostringstream * timer_stream = new std::ostringstream;
+ the_toy->draw(cr, notify, width, height, true, timer_stream);
+ delete notify;
+ delete timer_stream;
+ }
+
+ cairo_show_page(cr);
+ if(save_png)
+ cairo_surface_write_to_png(cr_s, filename);
+ cairo_destroy (cr);
+ cairo_surface_destroy (cr_s);
+}
+
+void save_cairo(GSimpleAction *, GVariant *, gpointer) {
+ GtkWidget* d = gtk_file_chooser_dialog_new(
+ "Save file as svg, pdf or png", GTK_WINDOW(the_window), GTK_FILE_CHOOSER_ACTION_SAVE,
+ "Cancel", GTK_RESPONSE_CANCEL, "Save", GTK_RESPONSE_ACCEPT, NULL);
+ if (gtk_dialog_run(GTK_DIALOG(d)) == GTK_RESPONSE_ACCEPT) {
+ const gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(d));
+ write_image(filename);
+ }
+ gtk_widget_destroy(d);
+}
+
+static gint delete_event(GtkWidget*, GdkEventAny*, gpointer) {
+ quit(nullptr, nullptr, nullptr);
+ return FALSE;
+}
+
+
+static void toggle_action(GSimpleAction *action, GVariant *, gpointer) {
+ GVariant *state = g_action_get_state(G_ACTION(action));
+ g_action_change_state(G_ACTION(action), g_variant_new_boolean(!g_variant_get_boolean(state)));
+ g_variant_unref(state);
+}
+
+static void set_show_timings(GSimpleAction *action, GVariant *variant, gpointer) {
+ the_toy->show_timings = g_variant_get_boolean(variant);
+ g_simple_action_set_state(action, variant);
+}
+
+static gboolean draw_callback(GtkWidget *widget, cairo_t *cr)
+{
+ int width = gdk_window_get_width(gtk_widget_get_window(widget));
+ int height = gdk_window_get_height(gtk_widget_get_window(widget));
+
+ std::ostringstream notify;
+
+ static bool resized = false;
+ if(!resized) {
+ Geom::Rect alloc_size(Geom::Interval(0, width),
+ Geom::Interval(0, height));
+ if(the_toy != NULL)
+ the_toy->resize_canvas(alloc_size);
+ resized = true;
+ }
+ cairo_rectangle(cr, 0, 0, width, height);
+ cairo_set_source_rgba(cr,1,1,1,1);
+ cairo_fill(cr);
+ if (the_toy != NULL) {
+ std::ostringstream * timer_stream = new std::ostringstream;
+
+ if (the_toy->spool_file) {
+ the_toy->save(the_toy->spool_file);
+ }
+
+ the_toy->draw(cr, &notify, width, height, false, timer_stream);
+ delete timer_stream;
+ }
+
+ return TRUE;
+}
+
+static gint mouse_motion_event(GtkWidget* widget, GdkEventMotion* e, gpointer data) {
+ (void)(data);
+ (void)(widget);
+
+ if(the_toy != NULL) the_toy->mouse_moved(e);
+
+ return FALSE;
+}
+
+static gint mouse_event(GtkWidget* widget, GdkEventButton* e, gpointer data) {
+ (void)(data);
+ (void)(widget);
+
+ if(the_toy != NULL) the_toy->mouse_pressed(e);
+
+ return FALSE;
+}
+
+static gint scroll_event(GtkWidget* widget, GdkEventScroll* e, gpointer data) {
+ (void)(data);
+ (void)(widget);
+ if(the_toy != NULL) the_toy->scroll(e);
+
+ return FALSE;
+}
+
+static gint mouse_release_event(GtkWidget* widget, GdkEventButton* e, gpointer data) {
+ (void)(data);
+ (void)(widget);
+
+ if(the_toy != NULL) the_toy->mouse_released(e);
+
+ return FALSE;
+}
+
+static gint key_press_event(GtkWidget *widget, GdkEventKey *e, gpointer data) {
+ (void)(data);
+ (void)(widget);
+
+ if(the_toy != NULL) the_toy->key_hit(e);
+
+ return FALSE;
+}
+
+static gint size_allocate_event(GtkWidget* widget, GtkAllocation *allocation, gpointer data) {
+ (void)(data);
+ (void)(widget);
+
+ Geom::Rect alloc_size(Geom::Interval(allocation->x, allocation->x+ allocation->width),
+ Geom::Interval(allocation->y, allocation->y+allocation->height));
+ if(the_toy != NULL) the_toy->resize_canvas(alloc_size);
+
+ return FALSE;
+}
+
+
+const char *the_builder_xml = R"xml(
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <menu id="menu">
+ <submenu>
+ <attribute name="label">File</attribute>
+ <section>
+ <item>
+ <attribute name="label">Open Handles...</attribute>
+ <attribute name="action">app.open-handles</attribute>
+ </item>
+ <item>
+ <attribute name="label">Save Handles...</attribute>
+ <attribute name="action">app.save-handles</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label">Save as SVG of PDF...</attribute>
+ <attribute name="action">app.save-image</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label">Show Timings</attribute>
+ <attribute name="action">app.show-timings</attribute>
+ </item>
+ <item>
+ <attribute name="label">Quit</attribute>
+ <attribute name="action">app.quit</attribute>
+ </item>
+ </section>
+ </submenu>
+ <submenu>
+ <attribute name="label">Help</attribute>
+ <item>
+ <attribute name="label">About...</attribute>
+ <attribute name="action">app.about</attribute>
+ </item>
+ </submenu>
+ </menu>
+</interface>
+)xml";
+
+static GActionEntry the_actions[] =
+{
+ {"open-handles", open_handles, nullptr, nullptr, nullptr},
+ {"save-handles", save_handles, nullptr, nullptr, nullptr},
+ {"save-image", save_cairo, nullptr, nullptr, nullptr},
+ {"show-timings", toggle_action, nullptr, "false", set_show_timings},
+ {"quit", quit, nullptr, nullptr, nullptr},
+ {"about", show_about_dialog, nullptr, nullptr, nullptr},
+};
+
+static GOptionEntry const the_options[] = {
+ {"handles", 'h', G_OPTION_FLAG_NONE, G_OPTION_ARG_FILENAME, &arg_handles_filename,
+ "Load handle positions from given file", "FILE"},
+ {"spool", 'm', G_OPTION_FLAG_NONE, G_OPTION_ARG_FILENAME, &arg_spool_filename,
+ "Record all interaction to the given file", "FILE"},
+ {"screenshot", 's', G_OPTION_FLAG_NONE, G_OPTION_ARG_FILENAME, &arg_screenshot_filename,
+ "Take screenshot and exit", nullptr},
+ {G_OPTION_REMAINING, 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_FILENAME_ARRAY, &arg_extra_files,
+ "Additional data files", "FILES..."},
+ {nullptr, 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, nullptr, nullptr, nullptr},
+};
+
+static void activate(GApplication *app, gpointer);
+static void startup(GApplication *app, gpointer);
+
+void init(int argc, char **argv, Toy* t, int width, int height) {
+ the_toy = t;
+ the_requested_width = width;
+ the_requested_height = height;
+
+ std::string app_name = "org.inkscape.lib2geom.toy.";
+ char const *dir_pos = strrchr(argv[0], G_DIR_SEPARATOR);
+ std::string argv_name = dir_pos ? dir_pos + 1 : argv[0];
+
+ // Erase extension for Windows
+ size_t dot_pos = argv_name.rfind('.');
+ if (dot_pos != std::string::npos) {
+ argv_name.erase(dot_pos);
+ }
+ the_toy->name = argv_name;
+ app_name += argv_name;
+
+ GtkApplication* app = gtk_application_new(app_name.c_str(), G_APPLICATION_FLAGS_NONE);
+ g_application_add_main_option_entries(G_APPLICATION(app), the_options);
+ g_action_map_add_action_entries(G_ACTION_MAP(app), the_actions, G_N_ELEMENTS(the_actions), nullptr);
+ g_signal_connect(G_OBJECT(app), "startup", G_CALLBACK(startup), nullptr);
+ g_signal_connect(G_OBJECT(app), "activate", G_CALLBACK(activate), nullptr);
+
+ g_application_run(G_APPLICATION(app), argc, argv);
+ g_object_unref(app);
+}
+
+static void startup(GApplication *app, gpointer) {
+ GtkBuilder *builder = gtk_builder_new_from_string(the_builder_xml, -1);
+ GMenuModel *menu = G_MENU_MODEL(gtk_builder_get_object(builder, "menu"));
+ gtk_application_set_menubar(GTK_APPLICATION(app), menu);
+ g_object_unref(builder);
+}
+
+static void activate(GApplication *app, gpointer) {
+ if (arg_spool_filename) {
+ the_toy->spool_file = fopen(arg_spool_filename, "w");
+ }
+
+ int const emulated_argc = arg_extra_files ? g_strv_length(arg_extra_files) + 1 : 1;
+ gchar const **emulated_argv = new gchar const*[emulated_argc];
+ emulated_argv[0] = the_toy->name.c_str();
+ for (int i = 1; i < emulated_argc; ++i) {
+ emulated_argv[i] = arg_extra_files[i-1];
+ }
+ the_toy->first_time(emulated_argc, const_cast<char**>(emulated_argv));
+ delete[] emulated_argv;
+
+ if (arg_handles_filename) {
+ FILE *handles_file = fopen(arg_handles_filename, "r");
+ the_toy->load(handles_file);
+ fclose(handles_file);
+ }
+
+ if (arg_screenshot_filename) {
+ write_image(arg_screenshot_filename);
+ g_application_quit(app);
+ return;
+ }
+
+ the_window = GTK_APPLICATION_WINDOW(gtk_application_window_new(GTK_APPLICATION(g_application_get_default())));
+ gtk_window_set_title(GTK_WINDOW(the_window), the_toy->name.c_str());
+ g_signal_connect(G_OBJECT(the_window), "delete_event", G_CALLBACK(delete_event), NULL);
+
+ the_canvas = gtk_drawing_area_new();
+ gtk_widget_add_events(the_canvas, (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK));
+ g_signal_connect(G_OBJECT(the_canvas), "draw", G_CALLBACK(draw_callback), 0);
+ g_signal_connect(G_OBJECT(the_canvas), "scroll-event", G_CALLBACK(scroll_event), 0);
+ g_signal_connect(G_OBJECT(the_canvas), "button-press-event", G_CALLBACK(mouse_event), 0);
+ g_signal_connect(G_OBJECT(the_canvas), "button-release-event", G_CALLBACK(mouse_release_event), 0);
+ g_signal_connect(G_OBJECT(the_canvas), "motion-notify-event", G_CALLBACK(mouse_motion_event), 0);
+ g_signal_connect(G_OBJECT(the_canvas), "key-press-event", G_CALLBACK(key_press_event), 0);
+ g_signal_connect(G_OBJECT(the_canvas), "size-allocate", G_CALLBACK(size_allocate_event), 0);
+
+ gtk_container_add(GTK_CONTAINER(the_window), the_canvas);
+ gtk_window_set_default_size(GTK_WINDOW(the_window), the_requested_width, the_requested_height);
+ gtk_widget_show_all(GTK_WIDGET(the_window));
+
+ // Make sure the canvas can receive key press events.
+ gtk_widget_set_can_focus(the_canvas, TRUE);
+ gtk_widget_grab_focus(the_canvas);
+ assert(gtk_widget_is_focus(the_canvas));
+}
+
+
+void Toggle::draw(cairo_t *cr, bool /*annotes*/) {
+ cairo_pattern_t* source = cairo_get_source(cr);
+ double rc, gc, bc, aa;
+ cairo_pattern_get_rgba(source, &rc, &gc, &bc, &aa);
+ cairo_set_source_rgba(cr,0,0,0,1);
+ cairo_rectangle(cr, bounds.left(), bounds.top(),
+ bounds.width(), bounds.height());
+ if(on) {
+ cairo_fill(cr);
+ cairo_set_source_rgba(cr,1,1,1,1);
+ } //else cairo_stroke(cr);
+ cairo_stroke(cr);
+ draw_text(cr, bounds.corner(0) + Geom::Point(5,2), text);
+ cairo_set_source_rgba(cr, rc, gc, bc, aa);
+}
+
+void Toggle::toggle() {
+ on = !on;
+}
+void Toggle::set(bool state) {
+ on = state;
+}
+
+
+void Toggle::handle_click(GdkEventButton* e) {
+ if(bounds.contains(Geom::Point(e->x, e->y)) && e->button == 1) toggle();
+}
+
+void* Toggle::hit(Geom::Point mouse)
+{
+ if (bounds.contains(mouse))
+ {
+ toggle();
+ return this;
+ }
+ return 0;
+}
+
+void toggle_events(std::vector<Toggle> &ts, GdkEventButton* e) {
+ for(auto & t : ts) t.handle_click(e);
+}
+
+void draw_toggles(cairo_t *cr, std::vector<Toggle> &ts) {
+ for(auto & t : ts) t.draw(cr);
+}
+
+
+
+Slider::value_type Slider::value() const
+{
+ Slider::value_type v = m_handle.pos[m_dir] - m_pos[m_dir];
+ v = ((m_max - m_min) / m_length) * v;
+ //std::cerr << "v : " << v << std::endl;
+ if (m_step != 0)
+ {
+ int k = std::floor(v / m_step);
+ v = k * m_step;
+ }
+ v = v + m_min;
+ //std::cerr << "v : " << v << std::endl;
+ return v;
+}
+
+void Slider::value(Slider::value_type _value)
+{
+ if ( _value < m_min ) _value = m_min;
+ if ( _value > m_max ) _value = m_max;
+ if (m_step != 0)
+ {
+ _value = _value - m_min;
+ int k = std::floor(_value / m_step);
+ _value = k * m_step + m_min;
+ }
+ m_handle.pos[m_dir]
+ = (m_length / (m_max - m_min)) * (_value - m_min) + m_pos[m_dir];
+}
+
+void Slider::max_value(Slider::value_type _value)
+{
+ Slider::value_type v = value();
+ m_max = _value;
+ value(v);
+}
+
+void Slider::min_value(Slider::value_type _value)
+{
+ Slider::value_type v = value();
+ m_min = _value;
+ value(v);
+}
+
+// dir = X horizontal slider dir = Y vertical slider
+void Slider::geometry( Geom::Point _pos,
+ Slider::value_type _length,
+ Geom::Dim2 _dir )
+{
+ Slider::value_type v = value();
+ m_pos = _pos;
+ m_length = _length;
+ m_dir = _dir;
+ Geom::Dim2 fix_dir = static_cast<Geom::Dim2>( (m_dir + 1) % 2 );
+ m_handle.pos[fix_dir] = m_pos[fix_dir];
+ value(v);
+}
+
+void Slider::draw(cairo_t* cr, bool annotate)
+{
+ cairo_pattern_t* source = cairo_get_source(cr);
+ double rc, gc, bc, aa;
+ cairo_pattern_get_rgba(source, &rc, &gc, &bc, &aa);
+ double lw = cairo_get_line_width(cr);
+ std::ostringstream os;
+ os << m_label << ": " << (*m_formatter)(value());
+ cairo_set_source_rgba(cr, 0.1, 0.1, 0.7, 1.0);
+ cairo_set_line_width(cr, 0.7);
+ m_handle.draw(cr, annotate);
+ cairo_stroke(cr);
+ cairo_set_source_rgba(cr, 0.1, 0.1, 0.1, 1.0);
+ cairo_set_line_width(cr, 0.4);
+ m_handle.draw(cr, annotate);
+ cairo_move_to(cr, m_pos[Geom::X], m_pos[Geom::Y]);
+ Geom::Point offset;
+ if ( m_dir == Geom::X )
+ {
+ cairo_rel_line_to(cr, m_length, 0);
+ offset = Geom::Point(0,5);
+ }
+ else
+ {
+ cairo_rel_line_to(cr, 0, m_length);
+ offset = Geom::Point(5,0);
+ }
+ cairo_stroke(cr);
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ draw_text(cr, m_pos + offset, os.str().c_str());
+ cairo_set_source_rgba(cr, rc, gc, bc, aa);
+ cairo_set_line_width(cr, lw);
+}
+
+void Slider::move_to(void* hit, Geom::Point om, Geom::Point m)
+{
+ // fix_dir == ! m_dir
+ Geom::Dim2 fix_dir = static_cast<Geom::Dim2>( (m_dir + 1) % 2 );
+ m[fix_dir] = m_pos[fix_dir];
+ double diff = m[m_dir] - m_pos[m_dir];
+// if (m_step != 0)
+// {
+// double step = (m_step * m_length) / (m_max - m_min) ;
+// int k = std::floor(diff / step);
+// double v = k * step;
+// m[m_dir] = v + m_pos[m_dir];
+// }
+ if ( diff < 0 ) m[m_dir] = m_pos[m_dir];
+ if ( diff > m_length ) m[m_dir] = m_pos[m_dir] + m_length;
+ m_handle.move_to(hit, om, m);
+}
+
+
+
+void PointHandle::draw(cairo_t *cr, bool /*annotes*/) {
+ draw_circ(cr, pos);
+}
+
+void* PointHandle::hit(Geom::Point mouse) {
+ if(Geom::distance(mouse, pos) < 5)
+ return this;
+ return 0;
+}
+
+void PointHandle::move_to(void* /*hit*/, Geom::Point /*om*/, Geom::Point m) {
+ pos = m;
+}
+
+void PointHandle::load(FILE* f) {
+ pos = read_point(f);
+}
+
+void PointHandle::save(FILE* f) {
+ fprintf(f, "%lf %lf\n", pos[0], pos[1]);
+}
+
+void PointSetHandle::draw(cairo_t *cr, bool annotes) {
+ for(unsigned i = 0; i < pts.size(); i++) {
+ draw_circ(cr, pts[i]);
+ if(annotes) draw_number(cr, pts[i], i, name);
+ }
+}
+
+void* PointSetHandle::hit(Geom::Point mouse) {
+ for(auto & pt : pts) {
+ if(Geom::distance(mouse, pt) < 5)
+ return (void*)(&pt);
+ }
+ return 0;
+}
+
+void PointSetHandle::move_to(void* hit, Geom::Point /*om*/, Geom::Point m) {
+ if(hit) {
+ *(Geom::Point*)hit = m;
+ }
+}
+
+void PointSetHandle::load(FILE* f) {
+ int n = 0;
+ assert(1 == fscanf(f, "%d\n", &n));
+ pts.clear();
+ for(int i = 0; i < n; i++) {
+ pts.push_back(read_point(f));
+ }
+}
+
+void PointSetHandle::save(FILE* f) {
+ fprintf(f, "%d\n", (int)pts.size());
+ for(auto & pt : pts) {
+ fprintf(f, "%lf %lf\n", pt[0], pt[1]);
+ }
+}
+
+#include <2geom/bezier-to-sbasis.h>
+
+Geom::D2<Geom::SBasis> PointSetHandle::asBezier() {
+ return handles_to_sbasis(pts.begin(), size()-1);
+}
+
+void RectHandle::draw(cairo_t *cr, bool /*annotes*/) {
+ cairo_rectangle(cr, pos);
+ cairo_stroke(cr);
+ if(show_center_handle) {
+ draw_circ(cr, pos.midpoint());
+ }
+ draw_text(cr, pos.corner(0), name);
+}
+
+void* RectHandle::hit(Geom::Point mouse) {
+ if(show_center_handle) {
+ if(Geom::distance(mouse, pos.midpoint()) < 5)
+ return (void*)(intptr_t)1;
+ }
+ for(int i = 0; i < 4; i++) {
+ if(Geom::distance(mouse, pos.corner(i)) < 5)
+ return (void*)(intptr_t)(2+i);
+ }
+ for(int i = 0; i < 4; i++) {
+ Geom::LineSegment ls(pos.corner(i), pos.corner(i+1));
+ if(Geom::distance(ls.pointAt(ls.nearestTime(mouse)),mouse) < 5)
+ return (void*)(intptr_t)(6+i);
+ }
+ return 0;
+
+}
+
+void RectHandle::move_to(void* hit, Geom::Point om, Geom::Point m) {
+ using Geom::X;
+ using Geom::Y;
+
+ unsigned h = (unsigned)(uintptr_t)(hit);
+ if(h == 1)
+ pos += (m-om);
+ else if(h >= 2 and h <= 5) {// corners
+ int xi = (h-2)& 1;
+ int yi = (h-2)&2;
+ if(yi)
+ xi = 1-xi; // clockwise
+ if (xi) {
+ pos[X].setMax(m[0]);
+ } else {
+ pos[X].setMin(m[0]);
+ }
+ if (yi/2) {
+ pos[Y].setMax(m[1]);
+ } else {
+ pos[Y].setMax(m[1]);
+ }
+ } else if(h >= 6 and h <= 9) {// edges
+ int side, d;
+ switch(h-6) {
+ case 0: d = 1; side = 0; break;
+ case 1: d = 0; side = 1; break;
+ case 2: d = 1; side = 1; break;
+ case 3: d = 0; side = 0; break;
+ }
+ if (side) {
+ pos[d].setMax(m[d]);
+ } else {
+ pos[d].setMin(m[d]);
+ }
+ }
+}
+
+void RectHandle::load(FILE* f) {
+ assert(0 == fscanf(f, "r\n"));
+ for(int i = 0; i < 2; i++) {
+ pos[i] = read_interval(f);
+ }
+
+}
+
+void RectHandle::save(FILE* f) {
+ fprintf(f, "r\n");
+ for(unsigned i = 0; i < 2; i++) {
+ fprintf(f, "%lf %lf\n", pos[i].min(), pos[i].max());
+ }
+}
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+ */
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/toy-template.cpp b/src/3rdparty/2geom/src/toys/toy-template.cpp
new file mode 100644
index 0000000..f7e5090
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/toy-template.cpp
@@ -0,0 +1,35 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework.h>
+
+using namespace Geom;
+
+class MyToy: public Toy {
+ virtual void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) {
+ //draw code here
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ MyToy () {
+ //Initialization here
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new MyToy());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/toyframework.py b/src/3rdparty/2geom/src/toys/toyframework.py
new file mode 100644
index 0000000..c580c1e
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/toyframework.py
@@ -0,0 +1,435 @@
+#!/usr/bin/python
+
+import gtk,math
+import pangocairo,cairo
+import gobject
+
+# def draw_text(cr, pos, txt, bottom = False):
+# def draw_number(cr, pos, num):
+
+def draw_circ(cr, (x, y)):
+ cr.new_sub_path()
+ cr.arc(x, y, 3, 0, math.pi*2)
+ cr.stroke()
+def draw_cross(cr, (x, y)):
+ cr.move_to(x-3, y-3)
+ cr.line_to(x+3, y+3)
+ cr.move_to(x-3, y+3)
+ cr.line_to(x+3, y-3)
+ cr.stroke()
+
+class Handle:
+ def __init__(self):
+ pass
+ def draw(self, cr, annotes):
+ pass
+ def hit(self, (x, y)):
+ return None
+ def move_to(self, hit, om, m):
+ pass
+ def scroll(self, pos, dir):
+ pass
+
+class PointHandle(Handle):
+ def __init__(self, x, y, name=""):
+ Handle.__init__(self)
+ self.pos = (x,y)
+ self.name = name
+ def draw(self, cr, annotes):
+ draw_circ(cr, self.pos)
+ if annotes:
+ draw_text(cr, self.pos, str(self.name))
+ def hit(self, mouse):
+ if math.hypot(mouse[0] - self.pos[0], mouse[1] - self.pos[1]) < 5:
+ return 0
+ return None
+ def move_to(self, hit, om, m):
+ self.pos = m
+
+class PointSetHandle(Handle):
+ def __init__(self, pts=None, name=""):
+ Handle.__init__(self)
+ self.pts = pts or []
+ self.name = name
+ def draw(self, cr, annotes):
+ for p in self.pts:
+ draw_circ(cr, p)
+ if annotes:
+ draw_text(cr, p, str(self.name))
+ def hit(self, mouse):
+ for i,p in enumerate(self.pts):
+ if math.hypot(mouse[0] - p[0], mouse[1] - p[1]) < 5:
+ return i
+ return None
+ def move_to(self, hit, om, m):
+ self.pts[hit[1]] = m
+ def append(self, x,y):
+ self.pts.append((x,y))
+
+class Toy:
+ def __init__(self):
+ self.handles = []
+ self.mouse_down = False
+ self.old_mouse = None
+ self.selected = None
+ self.notify = "notify"
+ self.origin = [0,0]
+ self.interactive_level = 0
+ self.transform = None
+
+ def draw(self, cr, (width, height), save):
+ bounds = self.should_draw_bounds()
+ self.transform = cr.get_matrix()
+ self.transform.invert()
+ if bounds == 1:
+ cr.set_source_rgba(0., 0., 0, 0.8)
+ cr.set_line_width (0.5)
+ for i in [1,3]:
+ cr.move_to(0, i*width/4)
+ cr.line_to(width, i*width/4)
+ cr.move_to(i*width/4, 0)
+ cr.line_to(i*width/4, height)
+ elif bounds == 2:
+ cr.set_source_rgba (0., 0., 0, 0.8)
+ cr.set_line_width (0.5)
+ cr.move_to(0, width/2)
+ cr.line_to(width, width/2)
+ cr.move_to(width/2, 0)
+ cr.line_to(width/2, height)
+
+ cr.set_source_rgba (0., 0.5, 0, 1)
+ cr.set_line_width (1)
+ annotes = self.should_draw_numbers()
+ for i,h in enumerate(self.handles):
+ cr.save()
+ if self.selected and i == self.selected[0]:
+ cr.set_source_rgba (0.5, 0, 0, 1)
+ h.draw(cr, annotes)
+ cr.restore()
+
+ cr.set_source_rgba (0., 0.5, 0, 0.8)
+ if self.notify:
+ cr.save()
+ cr.identity_matrix()
+ bnds = draw_text(cr, (0, height), self.notify, True)
+ l,t,w,h = bnds[1]
+ cr.set_source_rgba(1,1,1,0.9)
+ cr.rectangle(l,t+height-h, w, h)
+ cr.fill()
+ cr.set_source_rgba(0,0,0,1)
+ draw_text(cr, (0, height), self.notify, True)
+ cr.restore()
+
+ def mouse_moved(self, e):
+ mouse = (e.x, e.y)
+ if self.transform != None:
+ mouse = self.transform.transform_point(e.x, e.y)
+
+ if e.state & (gtk.gdk.BUTTON1_MASK | gtk.gdk.BUTTON3_MASK):
+ self.interactive_level = 2
+ if self.selected:
+ self.handles[self.selected[0]].move_to(self.selected, self.old_mouse, mouse)
+ self.old_mouse = mouse
+ self.canvas.queue_draw()
+ #self.redraw()
+ def mouse_pressed(self, e):
+ self.interactive_level = 1
+ mouse = (e.x, e.y)
+ if self.transform != None:
+ mouse = self.transform.transform_point(e.x, e.y)
+ if e.button == 1:
+ for i,h in enumerate(self.handles):
+ hit = h.hit(mouse)
+ if hit != None:
+ self.selected = (i, hit)
+ self.mouse_down = True
+ self.old_mouse = mouse
+ self.canvas.queue_draw()
+ #self.redraw()
+
+ def mouse_released(self, e):
+ self.interactive_level = 1
+ self.selected = None
+ if e.button == 1:
+ self.mouse_down = False
+ self.canvas.queue_draw()
+ #self.redraw()
+
+ def scroll_event(self, da, ev):
+ self.interactive_level = 1
+ #print 'scroll:'+'\n'.join([str((x, getattr(ev, x))) for x in dir(ev)])
+ #print 'end'
+ da.queue_draw()
+ hit = None
+ for i,h in enumerate(self.handles):
+ hit = h.scroll((ev.x,ev.y), ev.direction)
+ if hit != None:
+ break
+ return hit != None
+
+ def key_hit(self, e):
+ pass
+
+ def should_draw_numbers(self):
+ return True
+ def should_draw_bounds(self):
+ return 0
+
+ def first_time(self, argv):
+ pass
+
+ def gtk_ready(self):
+ pass
+
+ def resize_canvas(self, s):
+ pass
+ def redraw(self):
+ self.window.queue_draw()
+ def get_save_size(self):
+ return (0,0)+self.window.window.get_size()
+ def delete_event(self, window, e):
+ gtk.main_quit()
+ return False
+
+ def expose_event(self, widget, event):
+ cr = widget.window.cairo_create()
+
+ width, height = widget.window.get_size()
+ global resized
+
+ if not resized:
+ alloc_size = ((0, width), (0, height))
+ self.resize_canvas(alloc_size)
+ resized = True
+ cr.translate(self.origin[0], self.origin[1])
+ self.draw(cr, (width, height), False)
+
+ return True
+
+ def mouse_motion_event(self, widget, e):
+ e.x -= self.origin[0]
+ e.y -= self.origin[1]
+ self.mouse_moved(e)
+
+ return False
+
+ def mouse_event(self, widget, e):
+ e.x -= self.origin[0]
+ e.y -= self.origin[1]
+ self.mouse_pressed(e)
+
+ return False
+
+ def mouse_release_event(self, widget, e):
+ e.x -= self.origin[0]
+ e.y -= self.origin[1]
+ self.mouse_released(e)
+
+ return False
+
+ def key_release_event(self, widget, e):
+ self.key_hit(e)
+
+ return False
+
+ def size_allocate_event(self, widget, allocation):
+ alloc_size = ((allocation.x, allocation.x + allocation.width),
+ (allocation.y, allocation.y+allocation.height))
+ self.resize_canvas(alloc_size)
+
+ return False
+
+ def relax_interaction_timeout(self):
+ if self.interactive_level > 0:
+ self.interactive_level -= 1
+ self.canvas.queue_draw()
+ return True
+
+
+class Toggle:
+ def __init__(self):
+ self.bounds = (0,0,0,0)
+ self.text = ""
+ self.on = False
+ def draw(self, cr):
+ cr.set_source_rgba(0,0,0,1)
+ cr.rectangle(bounds.left(), bounds.top(),
+ bounds.width(), bounds.height())
+ if(on):
+ cr.fill()
+ cr.set_source_rgba(1,1,1,1)
+ else:
+ cr.stroke()
+ draw_text(cr, bounds.corner(0) + (5,2), text)
+
+ def toggle(self):
+ self.on = not self.on
+ def set(self, state):
+ self.on = state
+ def handle_click(self, e):
+ if bounds.contains((e.x, e,y)) and e.button == 1:
+ toggle()
+
+def toggle_events(toggles, e):
+ for t in toggles:
+ t.handle_click(e)
+
+def draw_toggles(cr, toggles):
+ for t in toggles:
+ t.draw(cr)
+
+
+current_toys = []
+
+def draw_text(cr, loc, txt, bottom = False, font="Sans 12"):
+ import pango
+ layout = pangocairo.CairoContext.create_layout (cr)
+ layout.set_font_description (pango.FontDescription(font))
+
+ layout.set_text(txt)
+ bounds = layout.get_pixel_extents()
+ cr.move_to(loc[0], loc[1])
+ if bottom:
+ if bottom == "topright":
+ cr.move_to(loc[0] - bounds[1][2],
+ loc[1])
+ elif bottom == "bottomright":
+ cr.move_to(loc[0] - bounds[1][2],
+ loc[1] - bounds[1][3])
+ elif bottom == "topleft":
+ cr.move_to(loc[0],
+ loc[1])
+ else:
+ cr.move_to(loc[0], loc[1] - bounds[1][3])
+ cr.show_layout(layout)
+ return bounds
+
+# Framework Accessors
+
+# Gui Event Callbacks
+
+def make_about(evt):
+ about_window = gtk.Window(gtk.WINDOW_TOPLEVEL)
+ about_window.set_title("About")
+ about_window.set_resizable(True)
+
+ about_text = gtk.TextView()
+ buf = about_text.get_buffer()
+ buf.set_text("Toy lib2geom application", -1)
+ about_window.add(about_text)
+
+ about_window.show_all()
+
+def save_cairo(evt):
+ d = gtk.FileChooserDialog("Save file as svg, png or pdf",
+ None,
+ gtk.FILE_CHOOSER_ACTION_SAVE,
+ (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
+ gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT))
+
+ if(d.run() == gtk.RESPONSE_ACCEPT):
+ filename = d.get_filename()
+ cr_s = None
+ left, top, width, height = current_toys[0].get_save_size()
+
+ if filename[-4:] == ".pdf":
+ cr_s = cairo.PDFSurface(filename, width, height)
+ elif filename[-4:] == ".png":
+ cr_s = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height )
+ else:
+ cr_s = cairo.SVGSurface(filename, width, height)
+ cr = cairo.Context(cr_s)
+ cr = pangocairo.CairoContext(cairo.Context(cr_s))
+ cr.translate(-left, -top)
+ current_toys[0].draw(cr, (width, height), True)
+
+ cr.show_page()
+ del cr
+ del cr_s
+ d.destroy()
+
+resized = False
+
+
+def FileMenuAction():
+ pass
+
+ui = """
+<ui>
+ <menubar>
+ <menu name="FileMenu" action="FileMenuAction">
+ <menuitem name="Save" action="save_cairo" />
+ <menuitem name="Quit" action="gtk.main_quit" />
+ <placeholder name="FileMenuAdditions" />
+ </menu>
+ <menu name="HelpMenu" action="HelpMenuAction">
+ <menuitem name="About" action="make_about" />
+ </menu>
+ </menubar>
+</ui>
+"""
+
+def init(argv, t, width, height):
+ global current_toys
+ current_toys.append(t)
+
+ t.first_time(argv)
+
+ t.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
+ t.window.set_title("title")
+
+# Creates the menu from the menu data above
+ uim = gtk.UIManager()
+ ag = gtk.ActionGroup('menu_actiongroup')
+ ag.add_actions([('FileMenuAction', None, 'File', None, None, None),
+ ('save_cairo', None, 'Save screenshot', None, None, save_cairo),
+ ('gtk.main_quit', None, 'Quit', None, None, gtk.main_quit),
+ ('HelpMenuAction', None, 'Help', None, None, None),
+ ('make_about', None, 'About', None, None, make_about)
+ ])
+ uim.insert_action_group(ag, 0)
+ uim.add_ui_from_string(ui)
+ menu = uim.get_widget("/ui/menubar")
+ # Creates the menu from the menu data above
+ #uim = gtk.UIManager()
+ #uim.add_ui_from_string(ui)
+ #menu = uim.get_widget("ui/menubar")
+
+ t.window.connect("delete_event", t.delete_event)
+
+ t.canvas = gtk.DrawingArea()
+
+ t.canvas.add_events((gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.KEY_PRESS_MASK | gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.SCROLL_MASK))
+
+ t.canvas.connect("expose_event", t.expose_event)
+ t.canvas.connect("button_press_event", t.mouse_event)
+ t.canvas.connect("button_release_event", t.mouse_release_event)
+ t.canvas.connect("motion_notify_event", t.mouse_motion_event)
+ t.canvas.connect("key_press_event", t.key_release_event)
+ t.canvas.connect("size-allocate", t.size_allocate_event)
+ t.canvas.connect("scroll_event", t.scroll_event)
+
+ t.vbox = gtk.VBox(False, 0)
+ t.window.add(t.vbox)
+
+ t.vbox.pack_start (menu, False, False, 0)
+
+ pain = gtk.VPaned()
+ t.vbox.pack_start(pain, True, True, 0)
+ pain.add1(t.canvas)
+
+ t.canvas.set_size_request(width, height)
+ t.window.show_all()
+
+ # Make sure the canvas can receive key press events.
+ t.canvas.set_flags(gtk.CAN_FOCUS)
+ t.canvas.grab_focus()
+ assert(t.canvas.is_focus())
+
+ t.gtk_ready()
+ gobject.timeout_add(1000, t.relax_interaction_timeout)
+
+ gtk.main()
+
+def get_vbox():
+ return current_toys[0].vbox
diff --git a/src/3rdparty/2geom/src/toys/uncross.cpp b/src/3rdparty/2geom/src/toys/uncross.cpp
new file mode 100644
index 0000000..aea5438
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/uncross.cpp
@@ -0,0 +1,500 @@
+#include <iostream>
+#include <2geom/path.h>
+#include <2geom/svg-path-parser.h>
+#include <2geom/path-intersection.h>
+#include <2geom/basic-intersection.h>
+#include <2geom/pathvector.h>
+
+#include <cstdlib>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <2geom/ord.h>
+using namespace Geom;
+using namespace std;
+
+void draw_rect(cairo_t *cr, Point tl, Point br) {
+ cairo_move_to(cr, tl[X], tl[Y]);
+ cairo_line_to(cr, br[X], tl[Y]);
+ cairo_line_to(cr, br[X], br[Y]);
+ cairo_line_to(cr, tl[X], br[Y]);
+ cairo_close_path(cr);
+}
+
+void draw_bounds(cairo_t *cr, PathVector ps) {
+ srand(0);
+ vector<Rect> bnds;
+ for(auto & p : ps) {
+ for(const auto & it : p) {
+ Rect bounds = (it.boundsFast());
+ bnds.push_back(bounds);
+ cairo_set_source_rgba(cr, uniform(), uniform(), uniform(), .5);
+ //draw_rect(cr, bounds.min(), bounds.max());
+ cairo_stroke(cr);
+ }
+ }
+ {
+ std::vector<std::vector<unsigned> > res = sweep_bounds(bnds);
+ cairo_set_line_width(cr,0.5);
+ cairo_save(cr);
+ cairo_set_source_rgb(cr, 1, 0, 0);
+ for(unsigned i = 0; i < res.size(); i++) {
+ for(unsigned j = 0; j < res[i].size(); j++) {
+ draw_line_seg(cr, bnds[i].midpoint(), bnds[res[i][j]].midpoint());
+ cairo_stroke(cr);
+ }
+ }
+ cairo_restore(cr);
+ }
+}
+
+void mark_verts(cairo_t *cr, PathVector ps) {
+ for(auto & p : ps)
+ for(const auto & it : p)
+ draw_cross(cr, it.initialPoint());
+}
+
+int winding(PathVector ps, Point p) {
+ int wind = 0;
+ for(const auto & i : ps)
+ wind += winding(i,p);
+ return wind;
+}
+
+template<typename T>
+//std::vector<T>::iterator
+T* insort(std::vector<T> &v, const T& val)
+{
+ T* iter = upper_bound(v.begin(), v.end(), val);
+
+ unsigned offset = iter - v.begin();
+ v.insert(iter, val);
+
+ return offset + v.begin();
+}
+
+
+class Uncross{
+public:
+ class Piece{
+ public:
+ Rect bounds;
+ Interval parameters;
+ Curve const* curve;
+ D2<SBasis> sb;
+ int mark;
+ int id;
+ };
+ class Crossing{
+ public:
+ vector<int> joins;
+ //double crossing_product; // first cross(d^nA, d^nB) for n that is non-zero, or 0 if the two curves are the same
+ };
+ vector<Rect> rs;
+ PathVector* pths;
+ cairo_t* cr;
+ std::vector<Piece> pieces;
+
+ Uncross(PathVector &pt, cairo_t* cr):pths(&pt), cr(cr) {}
+
+ void build() {
+ cairo_save(cr);
+ PathVector &ps(*pths);
+ for(auto & p : ps) {
+ for(const auto & it : p) {
+ Rect bounds = (it.boundsExact());
+ rs.push_back(bounds);
+ //cairo_set_source_rgba(cr, uniform(), uniform(), uniform(), .5);
+ //draw_rect(cr, bounds.min(), bounds.max());
+ cairo_stroke(cr);
+ pieces.emplace_back();
+ pieces.back().bounds = bounds;
+ pieces.back().curve = &it;
+ pieces.back().parameters = Interval(0,1);
+ pieces.back().sb = it.toSBasis();
+ }
+ }
+ cairo_restore(cr);
+ }
+
+ struct Event {
+ double x;
+ unsigned ix;
+ bool closing;
+ Event(double pos, unsigned i, bool c) : x(pos), ix(i), closing(c) {}
+// Lexicographic ordering by x then closing
+ bool operator<(Event const &other) const {
+ if(x < other.x) return true;
+ if(x > other.x) return false;
+ return closing < other.closing;
+ }
+
+ };
+
+ std::vector<Event> events;
+ std::vector<unsigned> open;
+
+ int cmpy(Piece* a, Piece* b, Interval X) {
+ if(a->bounds[Y].max() < b->bounds[Y].min()) { // bounds are strictly ordered
+ return -1;
+ }
+ if(a->bounds[Y].min() > b->bounds[Y].max()) { // bounds are strictly ordered
+ return 1;
+ }
+ std::vector<std::pair<double, double> > xs;
+ find_intersections(xs, a->sb, b->sb);
+ if(!xs.empty()) {
+ polish_intersections( xs, a->sb, b->sb);
+ // must split around these points to make new Pieces
+ for(auto & x : xs) {
+ std::cout << "cross:" << x.first << " , " << x.second << "\n";
+
+ cairo_save(cr);
+ draw_circ(cr, a->sb(x.first));
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ int ix = events[0].ix;
+ if(0){
+ pop_heap(events.begin(), events.end());
+ events.pop_back();
+ std::vector<unsigned>::iterator iter = std::find(open.begin(), open.end(), ix);
+ open.erase(iter);
+ std::cout << "kill\n";
+ }
+
+ }
+ } else { // any point gives an order
+ vector<double> ar = roots(a->sb[0] - X.middle());
+ vector<double> br = roots(b->sb[0] - X.middle());
+ if ((ar.size() == 1) and (br.size() == 1))
+
+ return a->sb[1](ar[0]) < b->sb[1](br[0]);
+ }
+ return 0; // FIXME
+ }
+
+
+ static void
+ draw_interval(cairo_t* cr, Interval I, Point origin, Point /*dir*/) {
+ cairo_save(cr);
+ cairo_set_line_width(cr, 0.5);
+
+ cairo_move_to(cr, Point(I.min(), -3) + origin);
+ cairo_line_to(cr, Point(I.min(), +3) + origin);
+ cairo_move_to(cr, Point(I.max(), -3) + origin);
+ cairo_line_to(cr, Point(I.max(), +3) + origin);
+
+ cairo_move_to(cr, Point(I.min(), 0) + origin);
+ cairo_line_to(cr, Point(I.min(), 0) + origin);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ }
+ void broke_sweep_bounds() {
+ cairo_save(cr);
+
+ cairo_set_source_rgb(cr, 1, 0, 0);
+ events.reserve(rs.size()*2);
+ std::vector<std::vector<unsigned> > pairs(rs.size());
+
+ for(unsigned i = 0; i < rs.size(); i++) {
+ events.emplace_back(rs[i].left(), i, false);
+ events.emplace_back(rs[i].right(), i, true);
+ }
+ //std::sort(events.begin(), events.end());
+ std::make_heap(events.begin(), events.end());
+
+ //for(unsigned i = 0; i < events.size(); i++) {
+
+ int i = 0;
+ while(!events.empty()) {
+ unsigned ix = events[0].ix;
+ if(events[0].closing) {
+ std::vector<unsigned>::iterator iter = std::find(open.begin(), open.end(), ix);
+ if(iter != open.end()) {
+ cairo_save(cr);
+ cairo_set_source_rgb(cr, 0, 1, 0);
+ cairo_set_line_width(cr, 0.25);
+ cairo_rectangle(cr, rs[*iter]);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ open.erase(iter);}
+ } else {
+ draw_interval(cr, rs[ix][0], Point(0,5*i+10), Point(0, 1));
+ for(unsigned int jx : open) {
+ OptInterval oiy = intersect(rs[ix][Y], rs[jx][Y]);
+ if(oiy) {
+ pairs[jx].push_back(ix);
+ std::cout << "oiy:" << *oiy << std::endl;
+ OptInterval oix = intersect(rs[ix][X], rs[jx][X]);
+ if(oix) {
+ std::cout << *oix;
+ std::cout << cmpy(&pieces[ix], &pieces[jx], *oix);
+ continue;
+ }
+ //draw_line_seg(cr, rs[ix].midpoint(), rs[jx].midpoint());
+ cairo_stroke(cr);
+ }
+ }
+ open.push_back(ix);
+ }
+ pop_heap(events.begin(), events.end());
+ events.pop_back();
+ i++;
+ }
+ //return pairs;
+ cairo_restore(cr);
+ }
+
+ void sweep_bounds() {
+ cairo_save(cr);
+
+ cairo_set_source_rgb(cr, 1, 0, 0);
+ events.reserve(rs.size()*2);
+ std::vector<std::vector<unsigned> > pairs(rs.size());
+
+ for(unsigned i = 0; i < rs.size(); i++) {
+ events.emplace_back(rs[i].left(), i, false);
+ events.emplace_back(rs[i].right(), i, true);
+ }
+ std::sort(events.begin(), events.end());
+
+ for(unsigned i = 0; i < events.size(); i++) {
+ unsigned ix = events[i].ix;
+ if(events[i].closing) {
+ std::vector<unsigned>::iterator iter = std::find(open.begin(), open.end(), ix);
+ if(iter != open.end()) {
+ cairo_save(cr);
+ cairo_set_source_rgb(cr, 0, 1, 0);
+ cairo_set_line_width(cr, 0.25);
+ cairo_rectangle(cr, rs[*iter]);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ open.erase(iter);
+ }
+ } else {
+ draw_interval(cr, rs[ix][0], Point(0,5*i+10), Point(0, 1));
+ for(unsigned int jx : open) {
+ OptInterval oiy = intersect(rs[ix][Y], rs[jx][Y]);
+ if(oiy) {
+ pairs[jx].push_back(ix);
+ std::cout << "oiy:" << *oiy << std::endl;
+ OptInterval oix = intersect(rs[ix][X], rs[jx][X]);
+ if(oix) {
+ std::cout << *oix;
+ std::cout << cmpy(&pieces[ix], &pieces[jx], *oix);
+ continue;
+ }
+ //draw_line_seg(cr, rs[ix].midpoint(), rs[jx].midpoint());
+ cairo_stroke(cr);
+ }
+ }
+ open.push_back(ix);
+ }
+ }
+
+ cairo_restore(cr);
+ }
+
+
+};
+
+class WindingTest: public Toy {
+ PathVector path;
+ PointHandle test_pt_handle;
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ cairo_set_line_width(cr, 0.5);
+ cairo_save(cr);
+ cairo_path(cr, path);
+ cairo_set_source_rgb(cr, 1, 1, 0);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ //mark_verts(cr, path);
+ cairo_stroke(cr);
+ cairo_set_line_width(cr, 1);
+ //draw_bounds(cr, path);
+ if(0) {
+ Uncross uc(path, cr);
+ uc.build();
+
+ uc.sweep_bounds();
+
+ //draw_bounds(cr, path); mark_verts(cr, path);
+ }
+
+ cairo_save(cr);
+ PathVector &ps(path);
+ vector<Rect> rs;
+ std::vector<Uncross::Piece> pieces;
+ std::vector<Uncross::Crossing> crosses;
+ int id_counter = 0;
+ for(auto & p : ps) {
+ int piece_start = pieces.size();
+ for(Path::iterator it = p.begin(); it != p.end(); ++it) {
+ Rect bounds = (it->boundsExact());
+ rs.push_back(bounds);
+ /*cairo_set_source_rgba(cr, uniform(), uniform(), uniform(), .5);
+ draw_rect(cr, bounds.min(), bounds.max());
+ cairo_stroke(cr);*/
+ pieces.emplace_back();
+ pieces.back().bounds = bounds;
+ pieces.back().curve = &*it;
+ pieces.back().parameters = Interval(0,1);
+ pieces.back().sb = it->toSBasis();
+ pieces.back().mark = 0;
+ pieces.back().id = id_counter++;
+ if(it != p.begin() and !crosses.empty())
+ crosses.back().joins.push_back(pieces.back().id);
+ crosses.emplace_back();
+ crosses.back().joins.push_back(pieces.back().id);
+ }
+ crosses.back().joins.push_back(pieces[piece_start].id);
+ //crosses[cross_start].joins.push_back(pieces.back().id);
+ }
+ cairo_restore(cr);
+ std::vector<std::vector<unsigned> > prs = sweep_bounds(rs);
+
+ cairo_save(cr);
+ std::vector<Uncross::Piece> new_pieces;
+ for(unsigned i = 0; i < prs.size(); i++) {
+ int ix = i;
+ Uncross::Piece& A = pieces[ix];
+ for(int jx : prs) {
+ Uncross::Piece& B = pieces[jx];
+ cairo_set_source_rgb(cr, 0, 1, 0);
+ draw_line_seg(cr, rs[ix].midpoint(), rs[jx].midpoint());
+ cairo_stroke(cr);
+ cout << ix << ", " << jx << endl;
+ std::vector<std::pair<double, double> > xs;
+ find_intersections(xs, A.sb, B.sb);
+ if(not xs.empty()) {
+ polish_intersections( xs, A.sb, B.sb);
+ // must split around these points to make new Pieces
+ double A_t_prev = 0;
+ double B_t_prev = 0;
+ int A_prec_id = A.id;
+ int B_prec_id = B.id;
+ for(unsigned cv_idx = 0; cv_idx <= xs.size(); cv_idx++) {
+ double A_t = 1;
+ double B_t = 1;
+ if(cv_idx < xs.size()) {
+ A_t = xs[cv_idx].first;
+ B_t = xs[cv_idx].second;
+ }
+
+ cairo_save(cr);
+ draw_circ(cr, A.sb(xs[cv_idx].first));
+ cairo_stroke(cr);
+ cairo_restore(cr);
+
+ Interval A_slice(A_t_prev, A_t);
+ Interval B_slice(B_t_prev, B_t);
+ if((A_slice.extent() > 0) or (B_slice.extent() > 0)) {
+ cout << "Aslice" <<A_slice << endl;
+ D2<SBasis> Asb = portion(A.sb, A_slice);
+ OptRect Abnds = bounds_exact(Asb);
+ if(Abnds) {
+ new_pieces.emplace_back();
+ new_pieces.back().bounds = *Abnds;
+ new_pieces.back().curve = A.curve;
+ new_pieces.back().parameters = A_slice;
+ new_pieces.back().sb = Asb;
+ new_pieces.back().id = id_counter++;
+ crosses.emplace_back();
+ crosses.back().joins.push_back(A_prec_id);
+ crosses.back().joins.push_back(new_pieces.back().id);
+ A.mark = 1;
+ A_prec_id = new_pieces.back().id;
+ }
+
+ cout << "Bslice" <<B_slice << endl;
+ D2<SBasis> Bsb = portion(B.sb, B_slice);
+ OptRect Bbnds = bounds_exact(Bsb);
+ if(Bbnds) {
+ new_pieces.emplace_back();
+ new_pieces.back().bounds = *Bbnds;
+ new_pieces.back().curve = B.curve;
+ new_pieces.back().parameters = B_slice;
+ new_pieces.back().sb = Bsb;
+ new_pieces.back().id = id_counter++;
+ crosses.emplace_back();
+ crosses.back().joins.push_back(B_prec_id);
+ crosses.back().joins.push_back(new_pieces.back().id);
+ B.mark = 1;
+ B_prec_id = new_pieces.back().id;
+ }
+ }
+ A_t_prev = A_t;
+ B_t_prev = B_t;
+ }
+ }
+ }
+ }
+ if(1)for(unsigned i = 0; i < prs.size(); i++) {
+ if(not pieces[i].mark)
+ new_pieces.push_back(pieces[i]);
+ }
+ cairo_restore(cr);
+
+ for(auto & new_piece : new_pieces) {
+ cout << new_piece.parameters << ", " <<new_piece.id <<endl;
+ cairo_save(cr);
+ cairo_rectangle(cr, new_piece.bounds);
+ cairo_set_source_rgba(cr, 0,1,0,0.1);
+ cairo_fill(cr);
+ cairo_set_source_rgba(cr, 0.3,0.3,0,0.1);
+ cairo_rectangle(cr, new_piece.bounds);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+ cairo_d2_sb(cr, new_piece.sb);
+ cairo_stroke(cr);
+ }
+
+
+ cout << "crossings:";
+ for(auto & cr : crosses) {
+ for(int join : cr.joins) {
+ cout << join << ", ";
+ }
+ cout << endl;
+ }
+
+ std::streambuf* cout_buffer = std::cout.rdbuf();
+ std::cout.rdbuf(notify->rdbuf());
+ *notify << "\nwinding:" << winding(path, test_pt_handle.pos) << "\n";
+ std::cout.rdbuf(cout_buffer);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ WindingTest () : test_pt_handle(300,300) {}
+ void first_time(int argc, char** argv) override {
+ const char *path_name="winding.svgd";
+ if(argc > 1)
+ path_name = argv[1];
+ path = read_svgd(path_name);
+ OptRect bounds = bounds_exact(path);
+ if (bounds) {
+ path *= Translate(Point(10,10) - bounds->min());
+ }
+
+ handles.push_back(&test_pt_handle);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new WindingTest());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/winding-test.cpp b/src/3rdparty/2geom/src/toys/winding-test.cpp
new file mode 100644
index 0000000..a0f7608
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/winding-test.cpp
@@ -0,0 +1,107 @@
+#include <2geom/path.h>
+#include <2geom/svg-path-parser.h>
+#include <2geom/path-intersection.h>
+
+#include <iostream>
+#include <cstdlib>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+#include <2geom/ord.h>
+using namespace Geom;
+
+void draw_rect(cairo_t *cr, Point tl, Point br) {
+ cairo_move_to(cr, tl[X], tl[Y]);
+ cairo_line_to(cr, br[X], tl[Y]);
+ cairo_line_to(cr, br[X], br[Y]);
+ cairo_line_to(cr, tl[X], br[Y]);
+ cairo_close_path(cr);
+}
+
+void draw_bounds(cairo_t *cr, PathVector ps) {
+ srand(0);
+ vector<Rect> bnds;
+ for(auto & p : ps) {
+ for(const auto & it : p) {
+ Rect bounds = (it.boundsFast());
+ bnds.push_back(bounds);
+ cairo_set_source_rgba(cr, uniform(), uniform(), uniform(), .5);
+ //draw_rect(cr, bounds.min(), bounds.max());
+ cairo_stroke(cr);
+ }
+ }
+ {
+ std::vector<std::vector<unsigned> > res = sweep_bounds(bnds);
+ cairo_set_line_width(cr,0.5);
+ cairo_save(cr);
+ cairo_set_source_rgb(cr, 1, 0, 0);
+ for(unsigned i = 0; i < res.size(); i++) {
+ for(unsigned j = 0; j < res[i].size(); j++) {
+ draw_line_seg(cr, bnds[i].midpoint(), bnds[res[i][j]].midpoint());
+ cairo_stroke(cr);
+ }
+ }
+ cairo_restore(cr);
+ }
+}
+
+void mark_verts(cairo_t *cr, PathVector ps) {
+ for(auto & p : ps)
+ for(const auto & it : p)
+ draw_cross(cr, it.initialPoint());
+}
+
+int winding(PathVector ps, Point p) {
+ int wind = 0;
+ for(const auto & i : ps)
+ wind += winding(i,p);
+ return wind;
+}
+
+class WindingTest: public Toy {
+ PathVector path;
+ PointHandle test_pt_handle;
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ cairo_set_source_rgb(cr, 0, 0, 0);
+ cairo_path(cr, path);
+ cairo_stroke(cr);
+ mark_verts(cr, path);
+ draw_bounds(cr, path);
+
+ //draw_bounds(cr, path); mark_verts(cr, path);
+
+ std::streambuf* cout_buffer = std::cout.rdbuf();
+ std::cout.rdbuf(notify->rdbuf());
+ *notify << "\nwinding:" << winding(path, test_pt_handle.pos) << "\n";
+ std::cout.rdbuf(cout_buffer);
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ }
+
+ public:
+ WindingTest () : test_pt_handle(300,300) {}
+ void first_time(int argc, char** argv) override {
+ const char *path_name="winding.svgd";
+ if(argc > 1)
+ path_name = argv[1];
+ path = read_svgd(path_name);
+
+ handles.push_back(&test_pt_handle);
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new WindingTest());
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/src/toys/worms.cpp b/src/3rdparty/2geom/src/toys/worms.cpp
new file mode 100644
index 0000000..81e7558
--- /dev/null
+++ b/src/3rdparty/2geom/src/toys/worms.cpp
@@ -0,0 +1,138 @@
+#include <2geom/d2.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/svg-path-parser.h>
+#include <2geom/sbasis-math.h>
+
+#include <toys/path-cairo.h>
+#include <toys/toy-framework-2.h>
+
+//Random walkers toy, written by mgsloan, initially for a school video proj.
+
+using namespace Geom;
+
+static void dot_plot(cairo_t *cr, Piecewise<D2<SBasis> > const &M, double min, double max, double space=10){
+ for( double t = min; t < max; t += space) {
+ Point pos = M(t), perp = M.valueAndDerivatives(t, 2)[1].cw() * 3;
+ draw_line_seg(cr, pos + perp, pos - perp);
+ }
+ cairo_stroke(cr);
+}
+
+D2<SBasis> random_d2() {
+ D2<SBasis> ret(SBasis(6, Linear()),
+ SBasis(6, Linear()));
+ ret[0][0] = Linear(uniform()*720, uniform()*720);
+ ret[1][0] = Linear(uniform()*480, uniform()*480);
+
+ int mul = 1;
+ for(int i = 1; i < 6; i++) {
+ ret[0][i] = Linear(uniform()*2000*mul - 1000, uniform()*2000*mul - 1000);
+ ret[1][i] = Linear(uniform()*2000*mul - 1000, uniform()*2000*mul - 1000);
+ mul*=2;
+ }
+ return ret;
+}
+
+class Worm {
+ Piecewise<D2<SBasis> > path;
+ int spawn_time, last_time;
+ double red, green, blue, length;
+ public:
+ void tele(int t) {
+ Piecewise<D2<SBasis> > new_path(portion(path, 0, t - last_time));
+ new_path.push(random_d2(), path.domain().max()+1);
+ path = arc_length_parametrization(new_path);
+ }
+ void add_section(const D2<SBasis> x) {
+ Piecewise<D2<SBasis> > new_path(path);
+ D2<SBasis> seg(x);
+ seg[0][0][0] = path.segs.back()[0][0][1];
+ seg[1][0][0] = path.segs.back()[1][0][1];
+ new_path.push(seg, path.domain().max()+1);
+ path = arc_length_parametrization(new_path);
+ }
+ Worm (int t, double r, double g, double b, double l) : spawn_time(t), last_time(t), red(r), green(g), blue(b), length(l) {
+ path = Piecewise<D2<SBasis> >(random_d2());
+ add_section(random_d2());
+ }
+ void draw(cairo_t *cr, int t) {
+ if(t - last_time > path.domain().max()) add_section(random_d2());
+ if(t - last_time - length > path.cuts[1]) {
+ Piecewise<D2<SBasis> > new_path;
+ new_path.push_cut(0);
+ for(unsigned i = 1; i < path.size(); i++) {
+ new_path.push(path[i], path.cuts[i+1] - path.cuts[1]);
+ }
+ last_time = t - length;
+ path = new_path;
+ }
+ cairo_set_source_rgb(cr, red, green, blue);
+ Piecewise<D2<SBasis> > port = portion(path, std::max(t - last_time - length, 0.), t - last_time);
+ cairo_pw_d2_sb(cr, port);
+ cairo_stroke(cr);
+
+ double d = 4;
+ cairo_set_dash(cr, &d, 1, 0);
+ for(unsigned i = 1; i < path.size(); i++) {
+ if(path[i].at0() != path[i-1].at1()) {
+ draw_line_seg(cr, path[i].at0(), path[i-1].at1());
+ }
+ }
+ cairo_stroke(cr);
+ cairo_set_dash(cr, &d, 0, 0);
+
+ cairo_set_source_rgb(cr, 0., 0., 1.);
+ dot_plot(cr, path, std::max(t - last_time - length, 0.), t - last_time);
+ }
+ void reverse_direction(int t) {
+ path = portion(path, 0, t - last_time);
+ D2<SBasis> seg = random_d2(), last = path[path.size()-1];
+ for(unsigned c = 0; c < 2; c++)
+ for(unsigned d = 1; d < seg[c].size() && d < last[c].size(); d++)
+ seg[c][d][0] = -last[c][d][1];
+ add_section(seg);
+ }
+};
+
+class Intro: public Toy {
+ int t;
+ vector<Worm> worms;
+ void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
+ t++;
+ if(t < 40 && t % 2 == 0) {
+ worms.emplace_back(t, uniform(), uniform(), uniform(), uniform() * 200 + 50);
+ }
+
+ for(auto & worm : worms) {
+ worm.draw(cr, t);
+ if(uniform() > .999) worm.tele(t);
+ }
+
+ Toy::draw(cr, notify, width, height, save,timer_stream);
+ redraw();
+ }
+
+ int should_draw_bounds() override { return 0; }
+
+ public:
+ Intro () {
+ t = 0;
+ }
+};
+
+int main(int argc, char **argv) {
+ init(argc, argv, new Intro(), 720, 480);
+ return 0;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/tests/CMakeLists.txt b/src/3rdparty/2geom/tests/CMakeLists.txt
new file mode 100644
index 0000000..95e10d4
--- /dev/null
+++ b/src/3rdparty/2geom/tests/CMakeLists.txt
@@ -0,0 +1,56 @@
+
+find_package(GTest REQUIRED MODULE)
+# Use this variable for tests which provide their own main().
+SET(2GEOM_TESTS_SRC
+#bezier-utils-test
+#lin_alg_test
+sbasis-text-test
+root-find-test
+implicitization-test
+#timing-test
+#rtree-performance-test
+)
+
+# Use this variable for GTest tests which should have a default main().
+SET(2GEOM_GTESTS_SRC
+affine-test
+angle-test
+bezier-test
+choose-test
+circle-test
+convex-hull-test
+coord-test
+ellipse-test
+elliptical-arc-test
+intersection-graph-test
+interval-test
+line-test
+nl-vector-test
+parallelogram-test
+path-test
+planar-graph-test
+point-test
+polynomial-test
+rect-test
+sbasis-test
+self-intersections-test
+)
+
+foreach(source ${2GEOM_GTESTS_SRC})
+ add_executable(${source} ${source}.cpp)
+ target_include_directories(${source} PRIVATE ${GSL_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS})
+ target_link_libraries(${source} 2geom GTest::Main ${GSL_LIBRARIES} ${GTK3_LIBRARIES})
+ add_test(NAME ${source} COMMAND ${source})
+endforeach()
+
+foreach(source ${2GEOM_TESTS_SRC})
+ add_executable(${source} ${source}.cpp)
+ target_include_directories(${source} PRIVATE ${GSL_INCLUDE_DIRS} ${GTK3_INCLUDE_DIRS})
+ target_link_libraries(${source} 2geom GTest::GTest ${GSL_LIBRARIES} ${GTK3_LIBRARIES})
+ add_test(NAME ${source} COMMAND ${source})
+endforeach(source)
+
+if(WIN32 AND 2GEOM_BUILD_SHARED)
+ add_custom_target(copy ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_BINARY_DIR}/src/2geom/lib2geom.dll ${CMAKE_BINARY_DIR}/src/tests/lib2geom.dll)
+ add_dependencies(copy 2geom)
+endif()
diff --git a/src/3rdparty/2geom/tests/WontSnapToSomeCurveSegments.svg b/src/3rdparty/2geom/tests/WontSnapToSomeCurveSegments.svg
new file mode 100644
index 0000000..b7e8dfb
--- /dev/null
+++ b/src/3rdparty/2geom/tests/WontSnapToSomeCurveSegments.svg
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="800"
+ height="400"
+ id="svg3975"
+ version="1.1"
+ inkscape:version="0.48+devel r10639 custom"
+ sodipodi:docname="825840-geom-bbox-nan-stroke-width-2.svg">
+ <defs
+ id="defs3977">
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lend"
+ style="overflow:visible">
+ <path
+ id="path3915"
+ style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Mend"
+ style="overflow:visible">
+ <path
+ id="path3921"
+ style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="scale(-0.6,-0.6)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.76013979"
+ inkscape:cx="406.66823"
+ inkscape:cy="300.66798"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1047"
+ inkscape:window-height="815"
+ inkscape:window-x="736"
+ inkscape:window-y="62"
+ inkscape:window-maximized="0"
+ borderlayer="false"
+ inkscape:showpageshadow="false"
+ inkscape:snap-center="false"
+ inkscape:snap-text-baseline="false"
+ inkscape:object-nodes="false"
+ inkscape:snap-midpoints="false"
+ inkscape:object-paths="true"
+ inkscape:snap-global="true"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:snap-intersection-paths="false"
+ inkscape:snap-others="false"
+ inkscape:snap-bbox="false"
+ inkscape:bbox-paths="false"
+ inkscape:bbox-nodes="false"
+ inkscape:snap-bbox-edge-midpoints="false"
+ inkscape:snap-bbox-midpoints="false"
+ inkscape:snap-smooth-nodes="false"
+ inkscape:snap-object-midpoints="false"
+ inkscape:snap-page="false">
+ <inkscape:grid
+ type="xygrid"
+ id="grid4495"
+ empspacing="2"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true"
+ dotted="false"
+ color="#009862"
+ opacity="0.40392157"
+ empcolor="#ff0000"
+ empopacity="0.1254902"
+ spacingx="50px"
+ spacingy="50px" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata3980">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 262.6037,35.824151 c 0,0 -92.64892,-187.405851 30,-149.999981 104.06976,31.739531 170,109.9999815 170,109.9999815 l -10,-59.9999905 c 0,0 40,79.99999 -40,79.99999 -80,0 -70,-129.999981 -70,-129.999981 l 50,0 C 435.13571,-131.5667 652.76275,126.44872 505.74322,108.05672 358.73876,89.666591 292.6037,-14.175849 292.6037,15.824151 c 0,30 -30,20 -30,20 z"
+ id="path3132"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="csccsccssc" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="illustrate" />
+</svg>
diff --git a/src/3rdparty/2geom/tests/affine-test.cpp b/src/3rdparty/2geom/tests/affine-test.cpp
new file mode 100644
index 0000000..2ddeb1d
--- /dev/null
+++ b/src/3rdparty/2geom/tests/affine-test.cpp
@@ -0,0 +1,429 @@
+/** @file
+ * @brief Unit tests for Affine
+ * Uses the Google Testing Framework
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2010 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <gtest/gtest.h>
+#include <2geom/affine.h>
+#include <2geom/transforms.h>
+
+namespace Geom {
+
+TEST(AffineTest, Equality) {
+ Affine e; // identity
+ Affine a(1, 2, 3, 4, 5, 6);
+ EXPECT_EQ(e, e);
+ EXPECT_EQ(e, Geom::identity());
+ EXPECT_EQ(e, Geom::Affine::identity());
+ EXPECT_NE(e, a);
+}
+
+TEST(AffineTest, Classification) {
+ {
+ Affine a; // identity
+ EXPECT_TRUE(a.isIdentity());
+ EXPECT_TRUE(a.isTranslation());
+ EXPECT_TRUE(a.isScale());
+ EXPECT_TRUE(a.isUniformScale());
+ EXPECT_TRUE(a.isRotation());
+ EXPECT_TRUE(a.isHShear());
+ EXPECT_TRUE(a.isVShear());
+ EXPECT_TRUE(a.isZoom());
+ EXPECT_FALSE(a.isNonzeroTranslation());
+ EXPECT_FALSE(a.isNonzeroScale());
+ EXPECT_FALSE(a.isNonzeroUniformScale());
+ EXPECT_FALSE(a.isNonzeroRotation());
+ EXPECT_FALSE(a.isNonzeroNonpureRotation());
+ EXPECT_FALSE(a.isNonzeroHShear());
+ EXPECT_FALSE(a.isNonzeroVShear());
+ EXPECT_TRUE(a.preservesArea());
+ EXPECT_TRUE(a.preservesAngles());
+ EXPECT_TRUE(a.preservesDistances());
+ EXPECT_FALSE(a.flips());
+ EXPECT_FALSE(a.isSingular());
+ }
+ {
+ Affine a = Translate(10, 15); // pure translation
+ EXPECT_FALSE(a.isIdentity());
+ EXPECT_TRUE(a.isTranslation());
+ EXPECT_FALSE(a.isScale());
+ EXPECT_FALSE(a.isUniformScale());
+ EXPECT_FALSE(a.isRotation());
+ EXPECT_FALSE(a.isHShear());
+ EXPECT_FALSE(a.isVShear());
+ EXPECT_TRUE(a.isZoom());
+ EXPECT_TRUE(a.isNonzeroTranslation());
+ EXPECT_FALSE(a.isNonzeroScale());
+ EXPECT_FALSE(a.isNonzeroUniformScale());
+ EXPECT_FALSE(a.isNonzeroRotation());
+ EXPECT_FALSE(a.isNonzeroNonpureRotation());
+ EXPECT_FALSE(a.isNonzeroHShear());
+ EXPECT_FALSE(a.isNonzeroVShear());
+ EXPECT_TRUE(a.preservesArea());
+ EXPECT_TRUE(a.preservesAngles());
+ EXPECT_TRUE(a.preservesDistances());
+ EXPECT_FALSE(a.flips());
+ EXPECT_FALSE(a.isSingular());
+ }
+ {
+ Affine a = Scale(-1.0, 1.0); // flip on the X axis
+ EXPECT_FALSE(a.isIdentity());
+ EXPECT_FALSE(a.isTranslation());
+ EXPECT_TRUE(a.isScale());
+ EXPECT_TRUE(a.isUniformScale());
+ EXPECT_FALSE(a.isRotation());
+ EXPECT_FALSE(a.isHShear());
+ EXPECT_FALSE(a.isVShear());
+ EXPECT_FALSE(a.isZoom()); // zoom must be non-flipping
+ EXPECT_FALSE(a.isNonzeroTranslation());
+ EXPECT_TRUE(a.isNonzeroScale());
+ EXPECT_TRUE(a.isNonzeroUniformScale());
+ EXPECT_FALSE(a.isNonzeroRotation());
+ EXPECT_FALSE(a.isNonzeroNonpureRotation());
+ EXPECT_FALSE(a.isNonzeroHShear());
+ EXPECT_FALSE(a.isNonzeroVShear());
+ EXPECT_TRUE(a.preservesArea());
+ EXPECT_TRUE(a.preservesAngles());
+ EXPECT_TRUE(a.preservesDistances());
+ EXPECT_TRUE(a.flips());
+ EXPECT_FALSE(a.isSingular());
+ }
+ {
+ Affine a = Scale(0.5, 0.5); // pure uniform scale
+ EXPECT_FALSE(a.isIdentity());
+ EXPECT_FALSE(a.isTranslation());
+ EXPECT_TRUE(a.isScale());
+ EXPECT_TRUE(a.isUniformScale());
+ EXPECT_FALSE(a.isRotation());
+ EXPECT_FALSE(a.isHShear());
+ EXPECT_FALSE(a.isVShear());
+ EXPECT_TRUE(a.isZoom());
+ EXPECT_FALSE(a.isNonzeroTranslation());
+ EXPECT_TRUE(a.isNonzeroScale());
+ EXPECT_TRUE(a.isNonzeroUniformScale());
+ EXPECT_FALSE(a.isNonzeroRotation());
+ EXPECT_FALSE(a.isNonzeroNonpureRotation());
+ EXPECT_FALSE(a.isNonzeroHShear());
+ EXPECT_FALSE(a.isNonzeroVShear());
+ EXPECT_FALSE(a.preservesArea());
+ EXPECT_TRUE(a.preservesAngles());
+ EXPECT_FALSE(a.preservesDistances());
+ EXPECT_FALSE(a.flips());
+ EXPECT_FALSE(a.isSingular());
+ }
+ {
+ Affine a = Scale(0.5, -0.5); // pure uniform flipping scale
+ EXPECT_FALSE(a.isIdentity());
+ EXPECT_FALSE(a.isTranslation());
+ EXPECT_TRUE(a.isScale());
+ EXPECT_TRUE(a.isUniformScale());
+ EXPECT_FALSE(a.isRotation());
+ EXPECT_FALSE(a.isHShear());
+ EXPECT_FALSE(a.isVShear());
+ EXPECT_FALSE(a.isZoom()); // zoom must be non-flipping
+ EXPECT_FALSE(a.isNonzeroTranslation());
+ EXPECT_TRUE(a.isNonzeroScale());
+ EXPECT_TRUE(a.isNonzeroUniformScale());
+ EXPECT_FALSE(a.isNonzeroRotation());
+ EXPECT_FALSE(a.isNonzeroNonpureRotation());
+ EXPECT_FALSE(a.isNonzeroHShear());
+ EXPECT_FALSE(a.isNonzeroVShear());
+ EXPECT_FALSE(a.preservesArea());
+ EXPECT_TRUE(a.preservesAngles());
+ EXPECT_FALSE(a.preservesDistances());
+ EXPECT_TRUE(a.flips());
+ EXPECT_FALSE(a.isSingular());
+ }
+ {
+ Affine a = Scale(0.5, 0.7); // pure non-uniform scale
+ EXPECT_FALSE(a.isIdentity());
+ EXPECT_FALSE(a.isTranslation());
+ EXPECT_TRUE(a.isScale());
+ EXPECT_FALSE(a.isUniformScale());
+ EXPECT_FALSE(a.isRotation());
+ EXPECT_FALSE(a.isHShear());
+ EXPECT_FALSE(a.isVShear());
+ EXPECT_FALSE(a.isZoom());
+ EXPECT_FALSE(a.isNonzeroTranslation());
+ EXPECT_TRUE(a.isNonzeroScale());
+ EXPECT_FALSE(a.isNonzeroUniformScale());
+ EXPECT_FALSE(a.isNonzeroRotation());
+ EXPECT_FALSE(a.isNonzeroNonpureRotation());
+ EXPECT_FALSE(a.isNonzeroHShear());
+ EXPECT_FALSE(a.isNonzeroVShear());
+ EXPECT_FALSE(a.preservesArea());
+ EXPECT_FALSE(a.preservesAngles());
+ EXPECT_FALSE(a.preservesDistances());
+ EXPECT_FALSE(a.flips());
+ EXPECT_FALSE(a.isSingular());
+ }
+ {
+ Affine a = Scale(0.5, 2.0); // "squeeze" transform (non-uniform scale with det=1)
+ EXPECT_FALSE(a.isIdentity());
+ EXPECT_FALSE(a.isTranslation());
+ EXPECT_TRUE(a.isScale());
+ EXPECT_FALSE(a.isUniformScale());
+ EXPECT_FALSE(a.isRotation());
+ EXPECT_FALSE(a.isHShear());
+ EXPECT_FALSE(a.isVShear());
+ EXPECT_FALSE(a.isZoom());
+ EXPECT_FALSE(a.isNonzeroTranslation());
+ EXPECT_TRUE(a.isNonzeroScale());
+ EXPECT_FALSE(a.isNonzeroUniformScale());
+ EXPECT_FALSE(a.isNonzeroRotation());
+ EXPECT_FALSE(a.isNonzeroNonpureRotation());
+ EXPECT_FALSE(a.isNonzeroHShear());
+ EXPECT_FALSE(a.isNonzeroVShear());
+ EXPECT_TRUE(a.preservesArea());
+ EXPECT_FALSE(a.preservesAngles());
+ EXPECT_FALSE(a.preservesDistances());
+ EXPECT_FALSE(a.flips());
+ EXPECT_FALSE(a.isSingular());
+ }
+ {
+ Affine a = Rotate(0.7); // pure rotation
+ EXPECT_FALSE(a.isIdentity());
+ EXPECT_FALSE(a.isTranslation());
+ EXPECT_FALSE(a.isScale());
+ EXPECT_FALSE(a.isUniformScale());
+ EXPECT_TRUE(a.isRotation());
+ EXPECT_FALSE(a.isHShear());
+ EXPECT_FALSE(a.isVShear());
+ EXPECT_FALSE(a.isZoom());
+ EXPECT_FALSE(a.isNonzeroTranslation());
+ EXPECT_FALSE(a.isNonzeroScale());
+ EXPECT_FALSE(a.isNonzeroUniformScale());
+ EXPECT_TRUE(a.isNonzeroRotation());
+ EXPECT_TRUE(a.isNonzeroNonpureRotation());
+ EXPECT_EQ(a.rotationCenter(), Point(0.0,0.0));
+ EXPECT_FALSE(a.isNonzeroHShear());
+ EXPECT_FALSE(a.isNonzeroVShear());
+ EXPECT_TRUE(a.preservesArea());
+ EXPECT_TRUE(a.preservesAngles());
+ EXPECT_TRUE(a.preservesDistances());
+ EXPECT_FALSE(a.flips());
+ EXPECT_FALSE(a.isSingular());
+ }
+ {
+ Point rotation_center(1.23,4.56);
+ Affine a = Translate(-rotation_center) * Rotate(0.7) * Translate(rotation_center); // rotation around (1.23,4.56)
+ EXPECT_FALSE(a.isIdentity());
+ EXPECT_FALSE(a.isTranslation());
+ EXPECT_FALSE(a.isScale());
+ EXPECT_FALSE(a.isUniformScale());
+ EXPECT_FALSE(a.isRotation());
+ EXPECT_FALSE(a.isHShear());
+ EXPECT_FALSE(a.isVShear());
+ EXPECT_FALSE(a.isZoom());
+ EXPECT_FALSE(a.isNonzeroTranslation());
+ EXPECT_FALSE(a.isNonzeroScale());
+ EXPECT_FALSE(a.isNonzeroUniformScale());
+ EXPECT_FALSE(a.isNonzeroRotation());
+ EXPECT_TRUE(a.isNonzeroNonpureRotation());
+ EXPECT_TRUE(are_near(a.rotationCenter(), rotation_center, 1e-7));
+ EXPECT_FALSE(a.isNonzeroHShear());
+ EXPECT_FALSE(a.isNonzeroVShear());
+ EXPECT_TRUE(a.preservesArea());
+ EXPECT_TRUE(a.preservesAngles());
+ EXPECT_TRUE(a.preservesDistances());
+ EXPECT_FALSE(a.flips());
+ EXPECT_FALSE(a.isSingular());
+ }
+ {
+ Affine a = HShear(0.5); // pure horizontal shear
+ EXPECT_FALSE(a.isIdentity());
+ EXPECT_FALSE(a.isTranslation());
+ EXPECT_FALSE(a.isScale());
+ EXPECT_FALSE(a.isUniformScale());
+ EXPECT_FALSE(a.isRotation());
+ EXPECT_TRUE(a.isHShear());
+ EXPECT_FALSE(a.isVShear());
+ EXPECT_FALSE(a.isZoom());
+ EXPECT_FALSE(a.isNonzeroTranslation());
+ EXPECT_FALSE(a.isNonzeroScale());
+ EXPECT_FALSE(a.isNonzeroUniformScale());
+ EXPECT_FALSE(a.isNonzeroRotation());
+ EXPECT_FALSE(a.isNonzeroNonpureRotation());
+ EXPECT_TRUE(a.isNonzeroHShear());
+ EXPECT_FALSE(a.isNonzeroVShear());
+ EXPECT_TRUE(a.preservesArea());
+ EXPECT_FALSE(a.preservesAngles());
+ EXPECT_FALSE(a.preservesDistances());
+ EXPECT_FALSE(a.flips());
+ EXPECT_FALSE(a.isSingular());
+ }
+ {
+ Affine a = VShear(0.5); // pure vertical shear
+ EXPECT_FALSE(a.isIdentity());
+ EXPECT_FALSE(a.isTranslation());
+ EXPECT_FALSE(a.isScale());
+ EXPECT_FALSE(a.isUniformScale());
+ EXPECT_FALSE(a.isRotation());
+ EXPECT_FALSE(a.isHShear());
+ EXPECT_TRUE(a.isVShear());
+ EXPECT_FALSE(a.isZoom());
+ EXPECT_FALSE(a.isNonzeroTranslation());
+ EXPECT_FALSE(a.isNonzeroScale());
+ EXPECT_FALSE(a.isNonzeroUniformScale());
+ EXPECT_FALSE(a.isNonzeroRotation());
+ EXPECT_FALSE(a.isNonzeroNonpureRotation());
+ EXPECT_FALSE(a.isNonzeroHShear());
+ EXPECT_TRUE(a.isNonzeroVShear());
+ EXPECT_TRUE(a.preservesArea());
+ EXPECT_FALSE(a.preservesAngles());
+ EXPECT_FALSE(a.preservesDistances());
+ EXPECT_FALSE(a.flips());
+ EXPECT_FALSE(a.isSingular());
+ }
+ {
+ Affine a = Zoom(3.0, Translate(10, 15)); // zoom
+ EXPECT_FALSE(a.isIdentity());
+ EXPECT_FALSE(a.isTranslation());
+ EXPECT_FALSE(a.isScale());
+ EXPECT_FALSE(a.isUniformScale());
+ EXPECT_FALSE(a.isRotation());
+ EXPECT_FALSE(a.isHShear());
+ EXPECT_FALSE(a.isVShear());
+ EXPECT_TRUE(a.isZoom());
+ EXPECT_FALSE(a.isNonzeroTranslation());
+ EXPECT_FALSE(a.isNonzeroScale());
+ EXPECT_FALSE(a.isNonzeroUniformScale());
+ EXPECT_FALSE(a.isNonzeroRotation());
+ EXPECT_FALSE(a.isNonzeroNonpureRotation());
+ EXPECT_FALSE(a.isNonzeroHShear());
+ EXPECT_FALSE(a.isNonzeroVShear());
+ EXPECT_FALSE(a.preservesArea());
+ EXPECT_TRUE(a.preservesAngles());
+ EXPECT_FALSE(a.preservesDistances());
+ EXPECT_FALSE(a.flips());
+ EXPECT_FALSE(a.isSingular());
+
+ EXPECT_TRUE(a.withoutTranslation().isUniformScale());
+ EXPECT_TRUE(a.withoutTranslation().isNonzeroUniformScale());
+ }
+ {
+ Affine a(0, 0, 0, 0, 0, 0); // zero matrix (singular)
+ EXPECT_FALSE(a.isIdentity());
+ EXPECT_FALSE(a.isTranslation());
+ EXPECT_FALSE(a.isScale());
+ EXPECT_FALSE(a.isUniformScale());
+ EXPECT_FALSE(a.isRotation());
+ EXPECT_FALSE(a.isHShear());
+ EXPECT_FALSE(a.isVShear());
+ EXPECT_FALSE(a.isZoom());
+ EXPECT_FALSE(a.isNonzeroTranslation());
+ EXPECT_FALSE(a.isNonzeroScale());
+ EXPECT_FALSE(a.isNonzeroUniformScale());
+ EXPECT_FALSE(a.isNonzeroRotation());
+ EXPECT_FALSE(a.isNonzeroNonpureRotation());
+ EXPECT_FALSE(a.isNonzeroHShear());
+ EXPECT_FALSE(a.isNonzeroVShear());
+ EXPECT_FALSE(a.preservesArea());
+ EXPECT_FALSE(a.preservesAngles());
+ EXPECT_FALSE(a.preservesDistances());
+ EXPECT_FALSE(a.flips());
+ EXPECT_TRUE(a.isSingular());
+ }
+ {
+ Affine a(0, 1, 0, 1, 10, 10); // another singular matrix
+ EXPECT_FALSE(a.isIdentity());
+ EXPECT_FALSE(a.isTranslation());
+ EXPECT_FALSE(a.isScale());
+ EXPECT_FALSE(a.isUniformScale());
+ EXPECT_FALSE(a.isRotation());
+ EXPECT_FALSE(a.isHShear());
+ EXPECT_FALSE(a.isVShear());
+ EXPECT_FALSE(a.isZoom());
+ EXPECT_FALSE(a.isNonzeroTranslation());
+ EXPECT_FALSE(a.isNonzeroScale());
+ EXPECT_FALSE(a.isNonzeroUniformScale());
+ EXPECT_FALSE(a.isNonzeroRotation());
+ EXPECT_FALSE(a.isNonzeroNonpureRotation());
+ EXPECT_FALSE(a.isNonzeroHShear());
+ EXPECT_FALSE(a.isNonzeroVShear());
+ EXPECT_FALSE(a.preservesArea());
+ EXPECT_FALSE(a.preservesAngles());
+ EXPECT_FALSE(a.preservesDistances());
+ EXPECT_FALSE(a.flips());
+ EXPECT_TRUE(a.isSingular());
+ }
+}
+
+TEST(AffineTest, Inversion) {
+ Affine i(1, 2, 1, -2, 10, 15); // invertible
+ Affine n(1, 2, 1, 2, 15, 30); // non-invertible
+ Affine e; // identity
+ EXPECT_EQ(i * i.inverse(), e);
+ EXPECT_EQ(i.inverse().inverse(), i);
+ EXPECT_EQ(n.inverse(), e);
+ EXPECT_EQ(e.inverse(), e);
+}
+
+TEST(AffineTest, CoordinateAccess) {
+ Affine a(0, 1, 2, 3, 4, 5);
+ for (int i=0; i<6; ++i) {
+ EXPECT_EQ(a[i], i);
+ }
+ for (int i=0; i<6; ++i) {
+ a[i] = 5*i;
+ }
+ for (int i=0; i<6; ++i) {
+ EXPECT_EQ(a[i], 5*i);
+ }
+}
+
+TEST(AffineTest, Nearness) {
+ Affine a1(1, 0, 1, 2, 1e-8, 1e-8);
+ Affine a2(1+1e-8, 0, 1, 2-1e-8, -1e-8, -1e-8);
+ EXPECT_TRUE(are_near(a1, a2, 1e-7));
+ EXPECT_FALSE(are_near(a1, a2, 1e-9));
+}
+
+TEST(AffineTest, Multiplication) {
+ // test whether noncommutative multiplications work correctly
+ Affine a1 = Scale(0.1), a2 = Translate(10, 10), a3 = Scale(10.0);
+ Affine t1 = Translate(1, 1), t100 = Translate(100, 100);
+ EXPECT_EQ(a1 * a2 * a3, t100);
+ EXPECT_EQ(a3 * a2 * a1, t1);
+}
+
+} // end namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/tests/angle-test.cpp b/src/3rdparty/2geom/tests/angle-test.cpp
new file mode 100644
index 0000000..687be65
--- /dev/null
+++ b/src/3rdparty/2geom/tests/angle-test.cpp
@@ -0,0 +1,209 @@
+/** @file
+ * @brief Unit tests for Angle and AngleInterval.
+ * Uses the Google Testing Framework
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/angle.h>
+#include <glib.h>
+#include "testing.h"
+
+using namespace Geom;
+
+TEST(AngleIntervalTest, InnerAngleConstrutor) {
+ std::vector<AngleInterval> ivs;
+
+ ivs.emplace_back(0, M_PI, true);
+ ivs.emplace_back(0, M_PI, false);
+ ivs.emplace_back(M_PI, 0, true);
+ ivs.emplace_back(M_PI, 0, false);
+ ivs.emplace_back(Angle(0), Angle(0), Angle(M_PI));
+
+ for (auto & iv : ivs) {
+ AngleInterval inner(iv.angleAt(0), iv.angleAt(0.5), iv.angleAt(1));
+ EXPECT_EQ(inner, iv);
+ }
+}
+
+TEST(AngleIntervalTest, Containment) {
+ AngleInterval a(0, M_PI, true);
+ AngleInterval b(0, M_PI, false);
+ AngleInterval c(M_PI, 0, true);
+ AngleInterval d(M_PI, 0, false);
+ AngleInterval e = AngleInterval::create_full(M_PI, true);
+
+ EXPECT_TRUE(a.contains(1.));
+ EXPECT_FALSE(a.contains(5.));
+ EXPECT_EQ(a.extent(), M_PI);
+
+ EXPECT_FALSE(b.contains(1.));
+ EXPECT_TRUE(b.contains(5.));
+ EXPECT_EQ(b.extent(), M_PI);
+
+ EXPECT_FALSE(c.contains(1.));
+ EXPECT_TRUE(c.contains(5.));
+ EXPECT_EQ(c.extent(), M_PI);
+
+ EXPECT_TRUE(d.contains(1.));
+ EXPECT_FALSE(d.contains(5.));
+ EXPECT_EQ(d.extent(), M_PI);
+
+ EXPECT_TRUE(e.contains(1.));
+ EXPECT_TRUE(e.contains(5.));
+ EXPECT_EQ(e.extent(), 2*M_PI);
+}
+
+TEST(AngleIntervalTest, TimeAtAngle) {
+ Coord pi32 = (3./2.)*M_PI;
+ AngleInterval a(M_PI, pi32, true);
+ AngleInterval b(pi32, M_PI, true);
+ AngleInterval c(M_PI, 0, false);
+ AngleInterval d(M_PI/2, M_PI, false);
+ AngleInterval e = AngleInterval::create_full(M_PI, true);
+ AngleInterval f = AngleInterval::create_full(M_PI, false);
+ Interval unit(0, 1);
+
+ EXPECT_EQ(a.timeAtAngle(M_PI), 0);
+ EXPECT_EQ(a.timeAtAngle(pi32), 1);
+ EXPECT_EQ(a.extent(), M_PI/2);
+ for (Coord t = -1; t <= 2; t += 0.125) {
+ Coord angle = lerp(t, M_PI, pi32);
+ Coord ti = a.timeAtAngle(angle);
+ EXPECT_EQ(unit.contains(ti), a.contains(angle));
+ EXPECT_FLOAT_EQ(ti, t);
+ }
+
+ EXPECT_EQ(b.timeAtAngle(pi32), 0);
+ EXPECT_EQ(b.timeAtAngle(M_PI), 1);
+ EXPECT_EQ(b.extent(), pi32);
+ EXPECT_FLOAT_EQ(b.timeAtAngle(M_PI/4), 0.5);
+ EXPECT_FLOAT_EQ(b.timeAtAngle(0), 1./3.);
+ EXPECT_FLOAT_EQ(b.timeAtAngle((11./8)*M_PI), -1./12);
+ for (Coord t = -0.125; t <= 1.125; t += 0.0625) {
+ Coord angle = lerp(t, pi32, 3*M_PI);
+ Coord ti = b.timeAtAngle(angle);
+ EXPECT_EQ(unit.contains(ti), b.contains(angle));
+ EXPECT_FLOAT_EQ(ti, t);
+ }
+
+ EXPECT_EQ(c.timeAtAngle(M_PI), 0);
+ EXPECT_EQ(c.timeAtAngle(0), 1);
+ EXPECT_EQ(c.extent(), M_PI);
+ EXPECT_FLOAT_EQ(c.timeAtAngle(M_PI/2), 0.5);
+ for (Coord t = -0.25; t <= 1.25; t += 0.125) {
+ Coord angle = lerp(t, M_PI, 0);
+ Coord ti = c.timeAtAngle(angle);
+ EXPECT_EQ(unit.contains(ti), c.contains(angle));
+ EXPECT_FLOAT_EQ(ti, t);
+ }
+
+ EXPECT_EQ(d.timeAtAngle(M_PI/2), 0);
+ EXPECT_EQ(d.timeAtAngle(M_PI), 1);
+ EXPECT_EQ(d.extent(), pi32);
+ EXPECT_FLOAT_EQ(d.timeAtAngle(-M_PI/4), 0.5);
+ for (Coord t = -0.125; t <= 1.125; t += 0.0625) {
+ Coord angle = lerp(t, M_PI/2, -M_PI);
+ Coord ti = d.timeAtAngle(angle);
+ EXPECT_EQ(unit.contains(ti), d.contains(angle));
+ EXPECT_FLOAT_EQ(ti, t);
+ }
+
+ EXPECT_EQ(e.timeAtAngle(M_PI), 0);
+ EXPECT_EQ(e.extent(), 2*M_PI);
+ EXPECT_FLOAT_EQ(e.timeAtAngle(0), 0.5);
+ for (Coord t = 0; t < 1; t += 0.125) {
+ Coord angle = lerp(t, M_PI, 3*M_PI);
+ Coord ti = e.timeAtAngle(angle);
+ EXPECT_EQ(unit.contains(ti), true);
+ EXPECT_EQ(e.contains(angle), true);
+ EXPECT_FLOAT_EQ(ti, t);
+ }
+
+ EXPECT_EQ(f.timeAtAngle(M_PI), 0);
+ EXPECT_EQ(f.extent(), 2*M_PI);
+ EXPECT_FLOAT_EQ(e.timeAtAngle(0), 0.5);
+ for (Coord t = 0; t < 1; t += 0.125) {
+ Coord angle = lerp(t, M_PI, -M_PI);
+ Coord ti = f.timeAtAngle(angle);
+ EXPECT_EQ(unit.contains(ti), true);
+ EXPECT_EQ(f.contains(angle), true);
+ EXPECT_FLOAT_EQ(ti, t);
+ }
+}
+
+TEST(AngleIntervalTest, AngleAt) {
+ Coord pi32 = (3./2.)*M_PI;
+ AngleInterval a(M_PI, pi32, true);
+ AngleInterval c(M_PI, 0, false);
+ AngleInterval f1 = AngleInterval::create_full(0, true);
+ AngleInterval f2 = AngleInterval::create_full(M_PI, false);
+
+ EXPECT_EQ(a.angleAt(0), M_PI);
+ EXPECT_EQ(a.angleAt(1), pi32);
+ EXPECT_EQ(a.extent(), M_PI/2);
+ for (Coord t = -1; t <= 2; t += 0.125) {
+ EXPECT_FLOAT_EQ(a.angleAt(t), Angle(lerp(t, M_PI, pi32)));
+ }
+
+ EXPECT_EQ(c.angleAt(0), M_PI);
+ EXPECT_EQ(c.angleAt(1), 0.);
+ EXPECT_EQ(c.extent(), M_PI);
+ for (Coord t = -0.25; t <= 1.25; t += 0.0625) {
+ EXPECT_FLOAT_EQ(c.angleAt(t), Angle(lerp(t, M_PI, 0)));
+ }
+
+ EXPECT_EQ(f1.angleAt(0), 0.);
+ EXPECT_EQ(f1.angleAt(1), 0.);
+ for (Coord t = 0; t < 1; t += 0.125) {
+ EXPECT_FLOAT_EQ(f1.angleAt(t), Angle(lerp(t, 0, 2*M_PI)));
+ }
+ EXPECT_EQ(f2.angleAt(0), M_PI);
+ EXPECT_EQ(f2.angleAt(1), M_PI);
+ for (Coord t = 0; t < 1; t += 0.125) {
+ EXPECT_FLOAT_EQ(f2.angleAt(t), Angle(lerp(t, M_PI, -M_PI)));
+ }
+}
+
+TEST(AngleIntervalTest, Extent) {
+ Coord pi32 = (3./2.)*M_PI;
+ AngleInterval a(M_PI, pi32, true);
+ AngleInterval b(pi32, M_PI, true);
+ AngleInterval c(M_PI, 0, false);
+ AngleInterval d(M_PI/2, M_PI, false);
+
+ EXPECT_EQ(a.extent(), M_PI/2);
+ EXPECT_EQ(a.sweepAngle(), M_PI/2);
+ EXPECT_EQ(b.extent(), pi32);
+ EXPECT_EQ(b.sweepAngle(), pi32);
+ EXPECT_EQ(c.extent(), M_PI);
+ EXPECT_EQ(c.sweepAngle(), -M_PI);
+ EXPECT_EQ(d.extent(), pi32);
+ EXPECT_EQ(d.sweepAngle(), -pi32);
+}
diff --git a/src/3rdparty/2geom/tests/bezier-sbasis-transforms.py b/src/3rdparty/2geom/tests/bezier-sbasis-transforms.py
new file mode 100644
index 0000000..1dc850f
--- /dev/null
+++ b/src/3rdparty/2geom/tests/bezier-sbasis-transforms.py
@@ -0,0 +1,72 @@
+#!/usr/bin/python
+
+from Numeric import *
+from LinearAlgebra import *
+
+pascals_triangle = []
+rows_done = 0
+
+def choose(n, k):
+ r = 1
+ for i in range(1,k+1):
+ r *= n-k+i
+ r /= i
+ return r
+
+# http://www.research.att.com/~njas/sequences/A109954
+def T(n, k):
+ return ((-1)**(n+k))*choose(n+k+2, 2*k+2)
+
+def inver(q):
+ result = zeros((q+2,q+2))
+ q2 = q/2+1
+ for i in range(q2):
+ for j in range(i+1):
+ val = T(i,j)
+ result[q/2-j][q/2-i] = val
+ result[q/2+j+2][q/2+i+2] = val
+ result[q/2+j+2][q/2-i-1] = -val
+ if q/2+i+3 < q+2:
+ result[q/2-j][q/2+i+3] = -val
+
+ for i in range(q+2):
+ result[q2][i] = [1,-1][(i-q2)%2]
+ return result
+
+def simple(q):
+ result = zeros((q+2,q+2))
+ for i in range(q/2+1):
+ for j in range(q+1):
+ result[j][i] = choose(q-2*i, j-i)
+ result[j+1][q-i+1] = choose(q-2*i, j-i)
+ result[q/2+1][q/2+1] = 1
+ return result
+
+print "The aim of the game is to work out the correct indexing to make the two matrices match :)"
+
+s = simple(4)
+si = floor(inverse(s)+0.5)
+print si.astype(Int)
+print inver(4)
+exit(0)
+print "<html><head><title></title></head><body>"
+
+def arrayhtml(a):
+ s = "<table>"
+ r,c = a.shape
+ for i in range(r):
+ s += "<tr>";
+ for j in range(c):
+ s += "<td>%g</td>" % a[i,j]
+ s += "</tr>"
+ s += "</table>"
+ return s
+
+for i in [21]:#range(1,13,2):
+ s = simple(i)
+ print "<h1>T<sup>-1</sup> = </h1>"
+ print arrayhtml(s)
+ print "<h1>T = </h1>"
+ print arrayhtml(floor(inverse(s)+0.5))
+
+print "</body></html>"
diff --git a/src/3rdparty/2geom/tests/bezier-test.cpp b/src/3rdparty/2geom/tests/bezier-test.cpp
new file mode 100644
index 0000000..0799393
--- /dev/null
+++ b/src/3rdparty/2geom/tests/bezier-test.cpp
@@ -0,0 +1,680 @@
+/** @file
+ * @brief Unit tests for Affine.
+ * Uses the Google Testing Framework
+ *//*
+ * Authors:
+ * Nathan Hurst <njh@njhurst.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ * Johan Engelen <j.b.c.engelen@alumnus.utwente.nl>
+ *
+ * Copyright 2010 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include "testing.h"
+#include <iostream>
+
+#include <2geom/bezier.h>
+#include <2geom/polynomial.h>
+#include <2geom/basic-intersection.h>
+#include <2geom/bezier-curve.h>
+#include <vector>
+#include <iterator>
+#include <glib.h>
+
+using std::vector, std::min, std::max;
+using namespace Geom;
+
+Poly lin_poly(double a, double b) { // ax + b
+ Poly p;
+ p.push_back(b);
+ p.push_back(a);
+ return p;
+}
+
+bool are_equal(Bezier A, Bezier B) {
+ int maxSize = max(A.size(), B.size());
+ double t = 0., dt = 1./maxSize;
+
+ for(int i = 0; i <= maxSize; i++) {
+ EXPECT_FLOAT_EQ(A.valueAt(t), B.valueAt(t));// return false;
+ t += dt;
+ }
+ return true;
+}
+
+class BezierTest : public ::testing::Test {
+protected:
+
+ BezierTest()
+ : zero(fragments[0])
+ , unit(fragments[1])
+ , hump(fragments[2])
+ , wiggle(fragments[3])
+ {
+ zero = Bezier(0.0,0.0);
+ unit = Bezier(0.0,1.0);
+ hump = Bezier(0,1,0);
+ wiggle = Bezier(0,1,-2,3);
+ }
+
+ Bezier fragments[4];
+ Bezier &zero, &unit, &hump, &wiggle;
+};
+
+TEST_F(BezierTest, Basics) {
+
+ //std::cout << unit <<std::endl;
+ //std::cout << hump <<std::endl;
+
+ EXPECT_TRUE(Bezier(0,0,0,0).isZero());
+ EXPECT_TRUE(Bezier(0,1,2,3).isFinite());
+
+ EXPECT_EQ(3u, Bezier(0,2,4,5).order());
+
+ ///cout << " Bezier::Bezier(const Bezier& b);\n";
+ //cout << Bezier(wiggle) << " == " << wiggle << endl;
+
+ //cout << "explicit Bezier(unsigned ord);\n";
+ //cout << Bezier(10) << endl;
+
+ //cout << "Bezier(Coord c0, Coord c1);\n";
+ //cout << Bezier(0.0,1.0) << endl;
+
+ //cout << "Bezier(Coord c0, Coord c1, Coord c2);\n";
+ //cout << Bezier(0,1, 2) << endl;
+
+ //cout << "Bezier(Coord c0, Coord c1, Coord c2, Coord c3);\n";
+ //cout << Bezier(0,1,2,3) << endl;
+
+ //cout << "unsigned degree();\n";
+ EXPECT_EQ(2u, hump.degree());
+
+ //cout << "unsigned size();\n";
+ EXPECT_EQ(3u, hump.size());
+}
+
+TEST_F(BezierTest, ValueAt) {
+ EXPECT_EQ(0.0, wiggle.at0());
+ EXPECT_EQ(3.0, wiggle.at1());
+
+ EXPECT_EQ(0.0, wiggle.valueAt(0.5));
+
+ EXPECT_EQ(0.0, wiggle(0.5));
+
+ //cout << "SBasis toSBasis();\n";
+ //cout << unit.toSBasis() << endl;
+ //cout << hump.toSBasis() << endl;
+ //cout << wiggle.toSBasis() << endl;
+}
+
+TEST_F(BezierTest, Casteljau) {
+ unsigned N = wiggle.order() + 1;
+ std::vector<Coord> left(N), right(N);
+ std::vector<Coord> left2(N), right2(N);
+ double eps = 1e-15;
+
+ for (unsigned i = 0; i < 10000; ++i) {
+ double t = g_random_double_range(0, 1);
+ double vok = bernstein_value_at(t, &wiggle[0], wiggle.order());
+ double v = casteljau_subdivision<double>(t, &wiggle[0], &left[0], &right[0], wiggle.order());
+ EXPECT_near(v, vok, eps);
+ EXPECT_EQ(left[0], wiggle.at0());
+ EXPECT_EQ(left[wiggle.order()], right[0]);
+ EXPECT_EQ(right[wiggle.order()], wiggle.at1());
+
+ double vl = casteljau_subdivision<double>(t, &wiggle[0], &left2[0], NULL, wiggle.order());
+ double vr = casteljau_subdivision<double>(t, &wiggle[0], NULL, &right2[0], wiggle.order());
+ EXPECT_EQ(vl, vok);
+ EXPECT_near(vr, vok, eps);
+ EXPECT_vector_near(left2, left, eps);
+ EXPECT_vector_equal(right2, right);
+
+ double vnone = casteljau_subdivision<double>(t, &wiggle[0], NULL, NULL, wiggle.order());
+ EXPECT_near(vnone, vok, 1e-12);
+ }
+}
+
+TEST_F(BezierTest, Portion) {
+ constexpr Coord eps{1e-12};
+
+ for (unsigned i = 0; i < 10000; ++i) {
+ double from = g_random_double_range(0, 1);
+ double to = g_random_double_range(0, 1);
+ for (auto & input : fragments) {
+ Bezier result = portion(input, from, to);
+
+ // the endpoints must correspond exactly
+ EXPECT_near(result.at0(), input.valueAt(from), eps);
+ EXPECT_near(result.at1(), input.valueAt(to), eps);
+ }
+ }
+}
+
+TEST_F(BezierTest, Subdivide) {
+ std::vector<std::pair<Bezier, double> > errors;
+ for (unsigned i = 0; i < 10000; ++i) {
+ double t = g_random_double_range(0, 1e-6);
+ for (auto & input : fragments) {
+ std::pair<Bezier, Bezier> result = input.subdivide(t);
+
+ // the endpoints must correspond exactly
+ // moreover, the subdivision point must be exactly equal to valueAt(t)
+ EXPECT_DOUBLE_EQ(result.first.at0(), input.at0());
+ EXPECT_DOUBLE_EQ(result.first.at1(), result.second.at0());
+ EXPECT_DOUBLE_EQ(result.second.at0(), input.valueAt(t));
+ EXPECT_DOUBLE_EQ(result.second.at1(), input.at1());
+
+ // ditto for valueAt
+ EXPECT_DOUBLE_EQ(result.first.valueAt(0), input.valueAt(0));
+ EXPECT_DOUBLE_EQ(result.first.valueAt(1), result.second.valueAt(0));
+ EXPECT_DOUBLE_EQ(result.second.valueAt(0), input.valueAt(t));
+ EXPECT_DOUBLE_EQ(result.second.valueAt(1), input.valueAt(1));
+
+ if (result.first.at1() != result.second.at0()) {
+ errors.emplace_back(input, t);
+ }
+ }
+ }
+ if (!errors.empty()) {
+ std::cout << "Found " << errors.size() << " subdivision errors" << std::endl;
+ for (unsigned i = 0; i < errors.size(); ++i) {
+ std::cout << "Error #" << i << ":\n"
+ << errors[i].first << "\n"
+ << "t: " << format_coord_nice(errors[i].second) << std::endl;
+ }
+ }
+}
+
+TEST_F(BezierTest, Mutation) {
+//Coord &operator[](unsigned ix);
+//Coord const &operator[](unsigned ix);
+//void setCoeff(unsigned ix double val);
+ //cout << "bigun\n";
+ Bezier bigun(Bezier::Order(30));
+ bigun.setCoeff(5,10.0);
+ for(unsigned i = 0; i < bigun.size(); i++) {
+ EXPECT_EQ((i == 5) ? 10 : 0, bigun[i]);
+ }
+
+ bigun[5] = -3;
+ for(unsigned i = 0; i < bigun.size(); i++) {
+ EXPECT_EQ((i == 5) ? -3 : 0, bigun[i]);
+ }
+}
+
+TEST_F(BezierTest, MultiDerivative) {
+ vector<double> vnd = wiggle.valueAndDerivatives(0.5, 5);
+ expect_array((const double[]){0,0,12,72,0,0}, vnd);
+}
+
+TEST_F(BezierTest, DegreeElevation) {
+ EXPECT_TRUE(are_equal(wiggle, wiggle));
+ Bezier Q = wiggle;
+ Bezier P = Q.elevate_degree();
+ EXPECT_EQ(P.size(), Q.size()+1);
+ //EXPECT_EQ(0, P.forward_difference(1)[0]);
+ EXPECT_TRUE(are_equal(Q, P));
+ Q = wiggle;
+ P = Q.elevate_to_degree(10);
+ EXPECT_EQ(10u, P.order());
+ EXPECT_TRUE(are_equal(Q, P));
+ //EXPECT_EQ(0, P.forward_difference(10)[0]);
+ /*Q = wiggle.elevate_degree();
+ P = Q.reduce_degree();
+ EXPECT_EQ(P.size()+1, Q.size());
+ EXPECT_TRUE(are_equal(Q, P));*/
+}
+//std::pair<Bezier, Bezier > subdivide(Coord t);
+
+// Constructs a linear Bezier with root at t
+Bezier linear_root(double t) {
+ return Bezier(0-t, 1-t);
+}
+
+// Constructs a Bezier with roots at the locations in x
+Bezier array_roots(vector<double> x) {
+ Bezier b(1);
+ for(double i : x) {
+ b = multiply(b, linear_root(i));
+ }
+ return b;
+}
+
+TEST_F(BezierTest, Deflate) {
+ Bezier b = array_roots(vector_from_array((const double[]){0,0.25,0.5}));
+ EXPECT_FLOAT_EQ(0, b.at0());
+ b = b.deflate();
+ EXPECT_FLOAT_EQ(0, b.valueAt(0.25));
+ b = b.subdivide(0.25).second;
+ EXPECT_FLOAT_EQ(0, b.at0());
+ b = b.deflate();
+ const double rootposition = (0.5-0.25) / (1-0.25);
+ constexpr Coord eps{1e-12};
+ EXPECT_near(0.0, b.valueAt(rootposition), eps);
+ b = b.subdivide(rootposition).second;
+ EXPECT_near(0.0, b.at0(), eps);
+}
+
+TEST_F(BezierTest, Roots) {
+ expect_array((const double[]){0, 0.5, 0.5}, wiggle.roots());
+
+ /*Bezier bigun(Bezier::Order(30));
+ for(unsigned i = 0; i < bigun.size(); i++) {
+ bigun.setCoeff(i,rand()-0.5);
+ }
+ cout << bigun.roots() << endl;*/
+
+ // The results of our rootfinding are at the moment fairly inaccurate.
+ double eps = 5e-4;
+
+ vector<vector<double> > tests;
+ tests.push_back(vector_from_array((const double[]){0}));
+ tests.push_back(vector_from_array((const double[]){1}));
+ tests.push_back(vector_from_array((const double[]){0, 0}));
+ tests.push_back(vector_from_array((const double[]){0.5}));
+ tests.push_back(vector_from_array((const double[]){0.5, 0.5}));
+ tests.push_back(vector_from_array((const double[]){0.1, 0.1}));
+ tests.push_back(vector_from_array((const double[]){0.1, 0.1, 0.1}));
+ tests.push_back(vector_from_array((const double[]){0.25,0.75}));
+ tests.push_back(vector_from_array((const double[]){0.5,0.5}));
+ tests.push_back(vector_from_array((const double[]){0, 0.2, 0.6, 0.6, 1}));
+ tests.push_back(vector_from_array((const double[]){.1,.2,.3,.4,.5,.6}));
+ tests.push_back(vector_from_array((const double[]){0.25,0.25,0.25,0.75,0.75,0.75}));
+
+ for(auto & test : tests) {
+ Bezier b = array_roots(test);
+ //std::cout << tests[test_i] << ": " << b << std::endl;
+ //std::cout << b.roots() << std::endl;
+ EXPECT_vector_near(test, b.roots(), eps);
+ }
+}
+
+TEST_F(BezierTest, BoundsExact) {
+ OptInterval unit_bounds = bounds_exact(unit);
+ EXPECT_EQ(unit_bounds->min(), 0);
+ EXPECT_EQ(unit_bounds->max(), 1);
+
+ OptInterval hump_bounds = bounds_exact(hump);
+ EXPECT_EQ(hump_bounds->min(), 0);
+ EXPECT_FLOAT_EQ(hump_bounds->max(), hump.valueAt(0.5));
+
+ OptInterval wiggle_bounds = bounds_exact(wiggle);
+ EXPECT_EQ(wiggle_bounds->min(), 0);
+ EXPECT_EQ(wiggle_bounds->max(), 3);
+}
+
+TEST_F(BezierTest, Operators) {
+ // Test equality operators
+ EXPECT_EQ(zero, zero);
+ EXPECT_EQ(hump, hump);
+ EXPECT_EQ(wiggle, wiggle);
+ EXPECT_EQ(unit, unit);
+
+ EXPECT_NE(zero, hump);
+ EXPECT_NE(hump, zero);
+ EXPECT_NE(wiggle, hump);
+ EXPECT_NE(zero, wiggle);
+ EXPECT_NE(wiggle, unit);
+
+ // Recall that hump == Bezier(0,1,0);
+ EXPECT_EQ(hump + 3, Bezier(3, 4, 3));
+ EXPECT_EQ(hump - 3, Bezier(-3, -2, -3));
+ EXPECT_EQ(hump * 3, Bezier(0, 3, 0));
+ EXPECT_EQ(hump / 3, Bezier(0, 1.0/3.0, 0));
+ EXPECT_EQ(-hump, Bezier(0, -1, 0));
+
+ Bezier reverse_wiggle = reverse(wiggle);
+ EXPECT_EQ(reverse_wiggle.at0(), wiggle.at1());
+ EXPECT_EQ(reverse_wiggle.at1(), wiggle.at0());
+ EXPECT_TRUE(are_equal(reverse(reverse_wiggle), wiggle));
+
+ //cout << "Bezier portion(const Bezier & a, double from, double to);\n";
+ //cout << portion(Bezier(0.0,2.0), 0.5, 1) << endl;
+
+// std::vector<Point> bezier_points(const D2<Bezier > & a) {
+
+ /*cout << "Bezier derivative(const Bezier & a);\n";
+ std::cout << derivative(hump) <<std::endl;
+ std::cout << integral(hump) <<std::endl;*/
+
+ EXPECT_TRUE(are_equal(derivative(integral(wiggle)), wiggle));
+ //std::cout << derivative(integral(hump)) <<std::endl;
+ expect_array((const double []){0.5}, derivative(hump).roots());
+
+ EXPECT_TRUE(bounds_fast(hump)->contains(Interval(0,hump.valueAt(0.5))));
+
+ EXPECT_EQ(Interval(0,hump.valueAt(0.5)), *bounds_exact(hump));
+
+ Interval tight_local_bounds(min(hump.valueAt(0.3),hump.valueAt(0.6)),
+ hump.valueAt(0.5));
+ EXPECT_TRUE(bounds_local(hump, Interval(0.3, 0.6))->contains(tight_local_bounds));
+
+ Bezier Bs[] = {unit, hump, wiggle};
+ for(auto B : Bs) {
+ Bezier product = multiply(B, B);
+ for(int i = 0; i <= 16; i++) {
+ double t = i/16.0;
+ double b = B.valueAt(t);
+ EXPECT_near(b*b, product.valueAt(t), 1e-12);
+ }
+ }
+}
+
+struct XPt {
+ XPt(Coord x, Coord y, Coord ta, Coord tb)
+ : p(x, y), ta(ta), tb(tb)
+ {}
+ XPt() {}
+ Point p;
+ Coord ta, tb;
+};
+
+struct XTest {
+ D2<Bezier> a;
+ D2<Bezier> b;
+ std::vector<XPt> s;
+};
+
+struct CILess {
+ bool operator()(CurveIntersection const &a, CurveIntersection const &b) const {
+ if (a.first < b.first) return true;
+ if (a.first == b.first && a.second < b.second) return true;
+ return false;
+ }
+};
+
+TEST_F(BezierTest, Intersection) {
+ /* Intersection test cases taken from:
+ * Dieter Lasser (1988), Calculating the Self-Intersections of Bezier Curves
+ * https://archive.org/stream/calculatingselfi00lass
+ *
+ * The intersection points are not actually calculated to a high precision
+ * in the paper. The most relevant tests are whether the curves actually
+ * intersect at the returned time values (i.e. whether a(ta) = b(tb))
+ * and whether the number of intersections is correct.
+ */
+ typedef D2<Bezier> D2Bez;
+ std::vector<XTest> tests;
+
+ // Example 1
+ tests.emplace_back();
+ tests.back().a = D2Bez(Bezier(-3.3, -3.3, 0, 3.3, 3.3), Bezier(1.3, -0.7, 2.3, -0.7, 1.3));
+ tests.back().b = D2Bez(Bezier(-4.0, -4.0, 0, 4.0, 4.0), Bezier(-0.35, 3.0, -2.6, 3.0, -0.35));
+ tests.back().s.resize(4);
+ tests.back().s[0] = XPt(-3.12109, 0.76362, 0.09834, 0.20604);
+ tests.back().s[1] = XPt(-1.67341, 0.60298, 0.32366, 0.35662);
+ tests.back().s[2] = XPt(1.67341, 0.60298, 0.67634, 0.64338);
+ tests.back().s[3] = XPt(3.12109, 0.76362, 0.90166, 0.79396);
+
+ // Example 2
+ tests.emplace_back();
+ tests.back().a = D2Bez(Bezier(0, 0, 3, 3), Bezier(0, 14, -9, 5));
+ tests.back().b = D2Bez(Bezier(-1, 13, -10, 4), Bezier(4, 4, 1, 1));
+ tests.back().s.resize(9);
+ tests.back().s[0] = XPt(0.00809, 1.17249, 0.03029, 0.85430);
+ tests.back().s[1] = XPt(0.02596, 1.97778, 0.05471, 0.61825);
+ tests.back().s[2] = XPt(0.17250, 3.99191, 0.14570, 0.03029);
+ tests.back().s[3] = XPt(0.97778, 3.97404, 0.38175, 0.05471);
+ tests.back().s[4] = XPt(1.5, 2.5, 0.5, 0.5);
+ tests.back().s[5] = XPt(2.02221, 1.02596, 0.61825, 0.94529);
+ tests.back().s[6] = XPt(2.82750, 1.00809, 0.85430, 0.96971);
+ tests.back().s[7] = XPt(2.97404, 3.02221, 0.94529, 0.38175);
+ tests.back().s[8] = XPt(2.99191, 3.82750, 0.96971, 0.14570);
+
+ // Example 3
+ tests.emplace_back();
+ tests.back().a = D2Bez(Bezier(-5, -5, -3, 0, 3, 5, 5), Bezier(0, 3.555, -1, 4.17, -1, 3.555, 0));
+ tests.back().b = D2Bez(Bezier(-6, -6, -3, 0, 3, 6, 6), Bezier(3, -0.555, 4, -1.17, 4, -0.555, 3));
+ tests.back().s.resize(6);
+ tests.back().s[0] = XPt(-3.64353, 1.49822, 0.23120, 0.27305);
+ tests.back().s[1] = XPt(-2.92393, 1.50086, 0.29330, 0.32148);
+ tests.back().s[2] = XPt(-0.77325, 1.49989, 0.44827, 0.45409);
+ tests.back().s[3] = XPt(0.77325, 1.49989, 0.55173, 0.54591);
+ tests.back().s[4] = XPt(2.92393, 1.50086, 0.70670, 0.67852);
+ tests.back().s[5] = XPt(3.64353, 1.49822, 0.76880, 0.72695);
+
+ // Example 4
+ tests.emplace_back();
+ tests.back().a = D2Bez(Bezier(-4, -10, -2, -2, 2, 2, 10, 4), Bezier(0, 6, 6, 0, 0, 6, 6, 0));
+ tests.back().b = D2Bez(Bezier(-8, 0, 8), Bezier(1, 6, 1));
+ tests.back().s.resize(4);
+ tests.back().s[0] = XPt(-5.69310, 2.23393, 0.06613, 0.14418);
+ tests.back().s[1] = XPt(-2.68113, 3.21920, 0.35152, 0.33243);
+ tests.back().s[2] = XPt(2.68113, 3.21920, 0.64848, 0.66757);
+ tests.back().s[3] = XPt(5.69310, 2.23393, 0.93387, 0.85582);
+
+ //std::cout << std::setprecision(5);
+
+ for (unsigned i = 0; i < tests.size(); ++i) {
+ BezierCurve a(tests[i].a), b(tests[i].b);
+ std::vector<CurveIntersection> xs;
+ xs = a.intersect(b, 1e-8);
+ std::sort(xs.begin(), xs.end(), CILess());
+ //xs.erase(std::unique(xs.begin(), xs.end(), XEqual()), xs.end());
+
+ std::cout << "\n\n"
+ << "===============================\n"
+ << "=== Intersection Testcase " << i+1 << " ===\n"
+ << "===============================\n" << std::endl;
+
+ EXPECT_EQ(xs.size(), tests[i].s.size());
+ //if (xs.size() != tests[i].s.size()) continue;
+
+ for (unsigned j = 0; j < std::min(xs.size(), tests[i].s.size()); ++j) {
+ std::cout << xs[j].first << " = " << a.pointAt(xs[j].first) << " "
+ << xs[j].second << " = " << b.pointAt(xs[j].second) << "\n"
+ << tests[i].s[j].ta << " = " << tests[i].a.valueAt(tests[i].s[j].ta) << " "
+ << tests[i].s[j].tb << " = " << tests[i].b.valueAt(tests[i].s[j].tb) << std::endl;
+ }
+
+ EXPECT_intersections_valid(a, b, xs, 1e-6);
+ }
+
+ #if 0
+ // these contain second-order intersections
+ Coord a5x[] = {-1.5, -1.5, -10, -10, 0, 10, 10, 1.5, 1.5};
+ Coord a5y[] = {0, -8, -8, 9, 9, 9, -8, -8, 0};
+ Coord b5x[] = {-3, -12, 0, 12, 3};
+ Coord b5y[] = {-5, 8, 2.062507, 8, -5};
+ Coord p5x[] = {-3.60359, -5.44653, 0, 5.44653, 3.60359};
+ Coord p5y[] = {-4.10631, -0.76332, 4.14844, -0.76332, -4.10631};
+ Coord p5ta[] = {0.01787, 0.10171, 0.5, 0.89829, 0.98213};
+ Coord p5tb[] = {0.12443, 0.28110, 0.5, 0.71890, 0.87557};
+
+ Coord a6x[] = {5, 14, 10, -12, -12, -2};
+ Coord a6y[] = {1, 6, -6, -6, 2, 2};
+ Coord b6x[] = {0, 2, -10.5, -10.5, 3.5, 3, 8, 6};
+ Coord b6y[] = {0, -8, -8, 9, 9, -4.129807, -4.129807, 3};
+ Coord p6x[] = {6.29966, 5.87601, 0.04246, -4.67397, -3.57214};
+ Coord p6y[] = {1.63288, -0.86192, -2.38219, -2.17973, 1.91463};
+ Coord p6ta[] = {0.03184, 0.33990, 0.49353, 0.62148, 0.96618};
+ Coord p6tb[] = {0.96977, 0.85797, 0.05087, 0.28232, 0.46102};
+ #endif
+}
+
+/** Basic test for intersecting a quadratic Bézier with a line segment. */
+TEST_F(BezierTest, QuadraticIntersectLineSeg)
+{
+ double const EPS = 1e-12;
+ auto const bow = QuadraticBezier({0, 0}, {1, 1}, {2, 0});
+ auto const highhoriz = LineSegment(Point(0, 0), Point(2, 0));
+ auto const midhoriz = LineSegment(Point(0, 0.25), Point(2, 0.25));
+ auto const lowhoriz = LineSegment(Point(0, 0.5), Point(2, 0.5));
+ auto const noninters = LineSegment(Point(0, 0.5 + EPS), Point(2, 0.5 + EPS));
+ auto const noninters2 = LineSegment(Point(1, 0), Point(1, 0.5 - EPS));
+
+ auto const endpoint_intersections = bow.intersect(highhoriz, EPS);
+ EXPECT_EQ(endpoint_intersections.size(), 2);
+ EXPECT_intersections_valid(bow, highhoriz, endpoint_intersections, EPS);
+ for (auto const &ex : endpoint_intersections) {
+ EXPECT_DOUBLE_EQ(ex.point()[Y], 0.0);
+ }
+
+ auto const mid_intersections = bow.intersect(midhoriz, EPS);
+ EXPECT_EQ(mid_intersections.size(), 2);
+ EXPECT_intersections_valid(bow, midhoriz, mid_intersections, EPS);
+ for (auto const &mx : mid_intersections) {
+ EXPECT_DOUBLE_EQ(mx.point()[Y], 0.25);
+ }
+
+ auto const tangent_intersection = bow.intersect(lowhoriz, EPS);
+ EXPECT_EQ(tangent_intersection.size(), 1);
+ EXPECT_intersections_valid(bow, lowhoriz, tangent_intersection, EPS);
+ for (auto const &tx : tangent_intersection) {
+ EXPECT_DOUBLE_EQ(tx.point()[Y], 0.5);
+ }
+
+ auto no_intersections = bow.intersect(noninters, EPS);
+ EXPECT_TRUE(no_intersections.empty());
+
+ no_intersections = bow.intersect(noninters2, EPS);
+ EXPECT_TRUE(no_intersections.empty());
+}
+
+TEST_F(BezierTest, QuadraticIntersectLineRandom)
+{
+ g_random_set_seed(0xB747A380);
+ auto const diagonal = LineSegment(Point(0, 0), Point(1, 1));
+ double const EPS = 1e-12;
+
+ for (unsigned i = 0; i < 10'000; i++) {
+ auto q = QuadraticBezier({0, 1}, {g_random_double_range(0.0, 1.0), g_random_double_range(0.0, 1.0)}, {1, 0});
+ auto xings = q.intersect(diagonal, EPS);
+ ASSERT_EQ(xings.size(), 1);
+ auto pt = xings[0].point();
+ EXPECT_TRUE(are_near(pt[X], pt[Y], EPS));
+ EXPECT_intersections_valid(q, diagonal, xings, EPS);
+ }
+}
+
+/** Basic test for intersecting a cubic Bézier with a line segment. */
+TEST_F(BezierTest, CubicIntersectLine)
+{
+ double const EPS = 1e-12;
+ auto const wavelet = CubicBezier({0, 0}, {1, 2}, {0, -2}, {1, 0});
+
+ auto const unit_seg = LineSegment(Point(0, 0), Point(1, 0));
+ auto const expect3 = wavelet.intersect(unit_seg, EPS);
+ EXPECT_EQ(expect3.size(), 3);
+ EXPECT_intersections_valid(wavelet, unit_seg, expect3, EPS);
+
+ auto const half_seg = LineSegment(Point(0, 0), Point(0.5, 0));
+ auto const expect2 = wavelet.intersect(half_seg, EPS);
+ EXPECT_EQ(expect2.size(), 2);
+ EXPECT_intersections_valid(wavelet, half_seg, expect2, EPS);
+
+ auto const less_than_half = LineSegment(Point(0, 0), Point(0.5 - EPS, 0));
+ auto const expect1 = wavelet.intersect(less_than_half, EPS);
+ EXPECT_EQ(expect1.size(), 1);
+ EXPECT_intersections_valid(wavelet, less_than_half, expect1, EPS);
+
+ auto const dollar_stroke = LineSegment(Point(0, 0.5), Point(1, -0.5));
+ auto const dollar_xings = wavelet.intersect(dollar_stroke, EPS);
+ EXPECT_EQ(dollar_xings.size(), 3);
+ EXPECT_intersections_valid(wavelet, dollar_stroke, dollar_xings, EPS);
+}
+
+TEST_F(BezierTest, CubicIntersectLineRandom)
+{
+ g_random_set_seed(0xCAFECAFE);
+ auto const diagonal = LineSegment(Point(0, 0), Point(1, 1));
+ double const EPS = 1e-8;
+
+ for (unsigned i = 0; i < 10'000; i++) {
+ double a1 = g_random_double_range(0.0, 1.0);
+ double a2 = g_random_double_range(a1, 1.0);
+ double b1 = g_random_double_range(0.0, 1.0);
+ double b2 = g_random_double_range(0.0, b1);
+
+ auto c = CubicBezier({0, 1}, {a1, a2}, {b1, b2}, {1, 0});
+ auto xings = c.intersect(diagonal, EPS);
+ ASSERT_EQ(xings.size(), 1);
+ auto pt = xings[0].point();
+ EXPECT_TRUE(are_near(pt[X], pt[Y], EPS));
+ EXPECT_intersections_valid(c, diagonal, xings, EPS);
+ }
+}
+
+/** Regression test for issue https://gitlab.com/inkscape/lib2geom/-/issues/47 . */
+TEST_F(BezierTest, Balloon)
+{
+ auto const loop = CubicBezier({0, 0}, {4, -2}, {4, 2}, {0, 0});
+ auto const seghoriz = LineSegment(Point(-1, 0), Point(0, 0));
+
+ for (double EPS : {1e-6, 1e-9, 1e-12}) {
+ // We expect that 2 intersections are found: one at each end of the loop,
+ // both at the coordinates (0, 0).
+ auto xings_horiz = loop.intersect(seghoriz, EPS);
+ EXPECT_EQ(xings_horiz.size(), 2);
+ EXPECT_intersections_valid(loop, seghoriz, xings_horiz, EPS);
+ }
+}
+
+TEST_F(BezierTest, ExpandToTransformedTest)
+{
+ auto test_curve = [] (Curve const &c) {
+ constexpr int N = 50;
+ for (int i = 0; i < N; i++) {
+ auto angle = 2 * M_PI * i / N;
+ auto transform = Affine(Rotate(angle));
+
+ auto copy = std::unique_ptr<Curve>(c.duplicate());
+ *copy *= transform;
+ auto box1 = copy->boundsExact();
+
+ auto pt = c.initialPoint() * transform;
+ auto box2 = Rect(pt, pt);
+ c.expandToTransformed(box2, transform);
+
+ for (auto i : { X, Y }) {
+ EXPECT_DOUBLE_EQ(box1[i].min(), box2[i].min());
+ EXPECT_DOUBLE_EQ(box1[i].max(), box2[i].max());
+ }
+ }
+ };
+
+ test_curve(LineSegment(Point(-1, 0), Point(1, 2)));
+ test_curve(QuadraticBezier(Point(-1, 0), Point(1, 1), Point(3, 0)));
+ test_curve(CubicBezier(Point(-1, 0), Point(1, 1), Point(2, -2), Point(3, 0)));
+}
+
+TEST_F(BezierTest, ForwardDifferenceTest)
+{
+ auto b = Bezier(3, 4, 2, -5, 7);
+ EXPECT_EQ(b.forward_difference(1), Bezier(19, 34, 22, 5));
+ EXPECT_EQ(b.forward_difference(2), Bezier(-3, 2, 2));
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/tests/bezier-utils-test.cpp b/src/3rdparty/2geom/tests/bezier-utils-test.cpp
new file mode 100644
index 0000000..6f95ccd
--- /dev/null
+++ b/src/3rdparty/2geom/tests/bezier-utils-test.cpp
@@ -0,0 +1,333 @@
+#include "utest.h"
+#include <glib.h>
+
+/* MenTaLguY disclaims all responsibility for this evil idea for testing
+ static functions. The main disadvantages are that we retain the
+ #define's and `using' directives of the included file. */
+#include "../bezier-utils.cpp"
+
+using Geom::Point;
+
+static bool range_approx_equal(double const a[], double const b[], unsigned len);
+
+/* (Returns false if NaN encountered.) */
+template<class T>
+static bool range_equal(T const a[], T const b[], unsigned len) {
+ for (unsigned i = 0; i < len; ++i) {
+ if ( a[i] != b[i] ) {
+ return false;
+ }
+ }
+ return true;
+}
+
+inline bool point_approx_equal(Geom::Point const &a, Geom::Point const &b, double const eps)
+{
+ using Geom::X; using Geom::Y;
+ return ( Geom_DF_TEST_CLOSE(a[X], b[X], eps) &&
+ Geom_DF_TEST_CLOSE(a[Y], b[Y], eps) );
+}
+
+static inline double square(double const x) {
+ return x * x;
+}
+
+/** Determine whether the found control points are the same as previously found on some developer's
+ machine. Doesn't call utest__fail, just writes a message to stdout for diagnostic purposes:
+ the most important test is that the root-mean-square of errors in the estimation are low rather
+ than that the control points found are the same.
+**/
+static void compare_ctlpts(Point const est_b[], Point const exp_est_b[])
+{
+ unsigned diff_mask = 0;
+ for (unsigned i = 0; i < 4; ++i) {
+ for (unsigned d = 0; d < 2; ++d) {
+ if ( fabs( est_b[i][d] - exp_est_b[i][d] ) > 1.1e-5 ) {
+ diff_mask |= 1 << ( i * 2 + d );
+ }
+ }
+ }
+ if ( diff_mask != 0 ) {
+ printf("Warning: got different control points from previously-coded (diffs=0x%x).\n",
+ diff_mask);
+ printf(" Previous:");
+ for (unsigned i = 0; i < 4; ++i) {
+ printf(" (%g, %g)", exp_est_b[i][0], exp_est_b[i][1]); // localizing ok
+ }
+ putchar('\n');
+ printf(" Found: ");
+ for (unsigned i = 0; i < 4; ++i) {
+ printf(" (%g, %g)", est_b[i][0], est_b[i][1]); // localizing ok
+ }
+ putchar('\n');
+ }
+}
+
+static void compare_rms(Point const est_b[], double const t[], Point const d[], unsigned const n,
+ double const exp_rms_error)
+{
+ double sum_errsq = 0.0;
+ for (unsigned i = 0; i < n; ++i) {
+ Point const fit_pt = bezier_pt(3, est_b, t[i]);
+ Point const diff = fit_pt - d[i];
+ sum_errsq += dot(diff, diff);
+ }
+ double const rms_error = sqrt( sum_errsq / n );
+ UTEST_ASSERT( rms_error <= exp_rms_error + 1.1e-6 );
+ if ( rms_error < exp_rms_error - 1.1e-6 ) {
+ /* The fitter code appears to have improved [or the floating point calculations differ
+ on this machine from the machine where exp_rms_error was calculated]. */
+ printf("N.B. rms_error regression requirement can be decreased: have rms_error=%g.\n", rms_error); // localizing ok
+ }
+}
+
+int main(int argc, char *argv[]) {
+ utest_start("bezier-utils.cpp");
+
+ UTEST_TEST("copy_without_nans_or_adjacent_duplicates") {
+ Geom::Point const src[] = {
+ Point(2., 3.),
+ Point(2., 3.),
+ Point(0., 0.),
+ Point(2., 3.),
+ Point(2., 3.),
+ Point(1., 9.),
+ Point(1., 9.)
+ };
+ Point const exp_dest[] = {
+ Point(2., 3.),
+ Point(0., 0.),
+ Point(2., 3.),
+ Point(1., 9.)
+ };
+ g_assert( G_N_ELEMENTS(src) == 7 );
+ Point dest[7];
+ struct tst {
+ unsigned src_ix0;
+ unsigned src_len;
+ unsigned exp_dest_ix0;
+ unsigned exp_dest_len;
+ } const test_data[] = {
+ /* src start ix, src len, exp_dest start ix, exp dest len */
+ {0, 0, 0, 0},
+ {2, 1, 1, 1},
+ {0, 1, 0, 1},
+ {0, 2, 0, 1},
+ {0, 3, 0, 2},
+ {1, 3, 0, 3},
+ {0, 5, 0, 3},
+ {0, 6, 0, 4},
+ {0, 7, 0, 4}
+ };
+ for (unsigned i = 0 ; i < G_N_ELEMENTS(test_data) ; ++i) {
+ tst const &t = test_data[i];
+ UTEST_ASSERT( t.exp_dest_len
+ == copy_without_nans_or_adjacent_duplicates(src + t.src_ix0,
+ t.src_len,
+ dest) );
+ UTEST_ASSERT(range_equal(dest,
+ exp_dest + t.exp_dest_ix0,
+ t.exp_dest_len));
+ }
+ }
+
+ UTEST_TEST("bezier_pt(1)") {
+ Point const a[] = {Point(2.0, 4.0),
+ Point(1.0, 8.0)};
+ UTEST_ASSERT( bezier_pt(1, a, 0.0) == a[0] );
+ UTEST_ASSERT( bezier_pt(1, a, 1.0) == a[1] );
+ UTEST_ASSERT( bezier_pt(1, a, 0.5) == Point(1.5, 6.0) );
+ double const t[] = {0.5, 0.25, 0.3, 0.6};
+ for (unsigned i = 0; i < G_N_ELEMENTS(t); ++i) {
+ double const ti = t[i], si = 1.0 - ti;
+ UTEST_ASSERT( bezier_pt(1, a, ti) == si * a[0] + ti * a[1] );
+ }
+ }
+
+ UTEST_TEST("bezier_pt(2)") {
+ Point const b[] = {Point(1.0, 2.0),
+ Point(8.0, 4.0),
+ Point(3.0, 1.0)};
+ UTEST_ASSERT( bezier_pt(2, b, 0.0) == b[0] );
+ UTEST_ASSERT( bezier_pt(2, b, 1.0) == b[2] );
+ UTEST_ASSERT( bezier_pt(2, b, 0.5) == Point(5.0, 2.75) );
+ double const t[] = {0.5, 0.25, 0.3, 0.6};
+ for (unsigned i = 0; i < G_N_ELEMENTS(t); ++i) {
+ double const ti = t[i], si = 1.0 - ti;
+ Point const exp_pt( si*si * b[0] + 2*si*ti * b[1] + ti*ti * b[2] );
+ Point const pt(bezier_pt(2, b, ti));
+ UTEST_ASSERT(point_approx_equal(pt, exp_pt, 1e-11));
+ }
+ }
+
+ Point const c[] = {Point(1.0, 2.0),
+ Point(8.0, 4.0),
+ Point(3.0, 1.0),
+ Point(-2.0, -4.0)};
+ UTEST_TEST("bezier_pt(3)") {
+ UTEST_ASSERT( bezier_pt(3, c, 0.0) == c[0] );
+ UTEST_ASSERT( bezier_pt(3, c, 1.0) == c[3] );
+ UTEST_ASSERT( bezier_pt(3, c, 0.5) == Point(4.0, 13.0/8.0) );
+ double const t[] = {0.5, 0.25, 0.3, 0.6};
+ for (unsigned i = 0; i < G_N_ELEMENTS(t); ++i) {
+ double const ti = t[i], si = 1.0 - ti;
+ UTEST_ASSERT( LInfty( bezier_pt(3, c, ti)
+ - ( si*si*si * c[0] +
+ 3*si*si*ti * c[1] +
+ 3*si*ti*ti * c[2] +
+ ti*ti*ti * c[3] ) )
+ < 1e-4 );
+ }
+ }
+
+ struct Err_tst {
+ Point pt;
+ double u;
+ double err;
+ } const err_tst[] = {
+ {c[0], 0.0, 0.0},
+ {Point(4.0, 13.0/8.0), 0.5, 0.0},
+ {Point(4.0, 2.0), 0.5, 9.0/64.0},
+ {Point(3.0, 2.0), 0.5, 1.0 + 9.0/64.0},
+ {Point(6.0, 2.0), 0.5, 4.0 + 9.0/64.0},
+ {c[3], 1.0, 0.0},
+ };
+
+ UTEST_TEST("compute_max_error_ratio") {
+ Point d[G_N_ELEMENTS(err_tst)];
+ double u[G_N_ELEMENTS(err_tst)];
+ for (unsigned i = 0; i < G_N_ELEMENTS(err_tst); ++i) {
+ Err_tst const &t = err_tst[i];
+ d[i] = t.pt;
+ u[i] = t.u;
+ }
+ g_assert( G_N_ELEMENTS(u) == G_N_ELEMENTS(d) );
+ unsigned max_ix = ~0u;
+ double const err_ratio = compute_max_error_ratio(d, u, G_N_ELEMENTS(d), c, 1.0, &max_ix);
+ UTEST_ASSERT( fabs( sqrt(err_tst[4].err) - err_ratio ) < 1e-12 );
+ UTEST_ASSERT( max_ix == 4 );
+ }
+
+ UTEST_TEST("chord_length_parameterize") {
+ /* n == 2 */
+ {
+ Point const d[] = {Point(2.9415, -5.8149),
+ Point(23.021, 4.9814)};
+ double u[G_N_ELEMENTS(d)];
+ double const exp_u[] = {0.0, 1.0};
+ g_assert( G_N_ELEMENTS(u) == G_N_ELEMENTS(exp_u) );
+ chord_length_parameterize(d, u, G_N_ELEMENTS(d));
+ UTEST_ASSERT(range_equal(u, exp_u, G_N_ELEMENTS(exp_u)));
+ }
+
+ /* Straight line. */
+ {
+ double const exp_u[] = {0.0, 0.1829, 0.2105, 0.2105, 0.619, 0.815, 0.999, 1.0};
+ unsigned const n = G_N_ELEMENTS(exp_u);
+ Point d[n];
+ double u[n];
+ Point const a(-23.985, 4.915), b(4.9127, 5.203);
+ for (unsigned i = 0; i < n; ++i) {
+ double bi = exp_u[i], ai = 1.0 - bi;
+ d[i] = ai * a + bi * b;
+ }
+ chord_length_parameterize(d, u, n);
+ UTEST_ASSERT(range_approx_equal(u, exp_u, n));
+ }
+ }
+
+ /* Feed it some points that can be fit exactly with a single bezier segment, and see how
+ well it manages. */
+ Point const src_b[4] = {Point(5., -3.),
+ Point(8., 0.),
+ Point(4., 2.),
+ Point(3., 3.)};
+ double const t[] = {0.0, .001, .03, .05, .09, .13, .18, .25, .29, .33, .39, .44,
+ .51, .57, .62, .69, .75, .81, .91, .93, .97, .98, .999, 1.0};
+ unsigned const n = G_N_ELEMENTS(t);
+ Point d[n];
+ for (unsigned i = 0; i < n; ++i) {
+ d[i] = bezier_pt(3, src_b, t[i]);
+ }
+ Point const tHat1(unit_vector( src_b[1] - src_b[0] ));
+ Point const tHat2(unit_vector( src_b[2] - src_b[3] ));
+
+ UTEST_TEST("generate_bezier") {
+ Point est_b[4];
+ generate_bezier(est_b, d, t, n, tHat1, tHat2, 1.0);
+
+ compare_ctlpts(est_b, src_b);
+
+ /* We're being unfair here in using our t[] rather than best t[] for est_b: we
+ may over-estimate RMS of errors. */
+ compare_rms(est_b, t, d, n, 1e-8);
+ }
+
+ UTEST_TEST("sp_bezier_fit_cubic_full") {
+ Point est_b[4];
+ int splitpoints[2];
+ gint const succ = sp_bezier_fit_cubic_full(est_b, splitpoints, d, n, tHat1, tHat2, square(1.2), 1);
+ UTEST_ASSERT( succ == 1 );
+
+ Point const exp_est_b[4] = {
+ Point(5.000000, -3.000000),
+ Point(7.5753, -0.4247),
+ Point(4.77533, 1.22467),
+ Point(3, 3)
+ };
+ compare_ctlpts(est_b, exp_est_b);
+
+ /* We're being unfair here in using our t[] rather than best t[] for est_b: we
+ may over-estimate RMS of errors. */
+ compare_rms(est_b, t, d, n, .307911);
+ }
+
+ UTEST_TEST("sp_bezier_fit_cubic") {
+ Point est_b[4];
+ gint const succ = sp_bezier_fit_cubic(est_b, d, n, square(1.2));
+ UTEST_ASSERT( succ == 1 );
+
+ Point const exp_est_b[4] = {
+ Point(5.000000, -3.000000),
+ Point(7.57134, -0.423509),
+ Point(4.77929, 1.22426),
+ Point(3, 3)
+ };
+ compare_ctlpts(est_b, exp_est_b);
+
+#if 1 /* A change has been made to right_tangent. I believe that usually this change
+ will result in better fitting, but it won't do as well for this example where
+ we happen to be feeding a t=0.999 point to the fitter. */
+ printf("TODO: Update this test case for revised right_tangent implementation.\n");
+ /* In particular, have a test case to show whether the new implementation
+ really is likely to be better on average. */
+#else
+ /* We're being unfair here in using our t[] rather than best t[] for est_b: we
+ may over-estimate RMS of errors. */
+ compare_rms(est_b, t, d, n, .307983);
+#endif
+ }
+
+ return !utest_end();
+}
+
+/* (Returns false if NaN encountered.) */
+static bool range_approx_equal(double const a[], double const b[], unsigned const len) {
+ for (unsigned i = 0; i < len; ++i) {
+ if (!( fabs( a[i] - b[i] ) < 1e-4 )) {
+ return false;
+ }
+ }
+ return true;
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/tests/choose-test.cpp b/src/3rdparty/2geom/tests/choose-test.cpp
new file mode 100644
index 0000000..c2b2b50
--- /dev/null
+++ b/src/3rdparty/2geom/tests/choose-test.cpp
@@ -0,0 +1,79 @@
+/** @file
+ * @brief Unit tests for the binomial coefficient function.
+ * Uses the Google Testing Framework
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include "testing.h"
+#include <2geom/choose.h>
+#include <glib.h>
+
+using namespace Geom;
+
+TEST(ChooseTest, PascalsTriangle) {
+ // check whether the values match Pascal's triangle
+ for (unsigned i = 0; i < 500; ++i) {
+ int n = g_random_int_range(3, 100);
+ int k = g_random_int_range(1, n-1);
+
+ double a = choose<double>(n, k);
+ double b = choose<double>(n-1, k);
+ double c = choose<double>(n-1, k-1);
+
+ EXPECT_NEAR((b + c) / a, 1.0, 1e-14);
+ }
+}
+
+TEST(ChooseTest, Values) {
+ // test some well-known values
+ EXPECT_EQ(choose<double>(0, 0), 1);
+ EXPECT_EQ(choose<double>(1, 0), 1);
+ EXPECT_EQ(choose<double>(1, 1), 1);
+ EXPECT_EQ(choose<double>(127, 127), 1);
+ EXPECT_EQ(choose<double>(92, 0), 1);
+ EXPECT_EQ(choose<double>(2, 1), 2);
+
+ // number of possible flops in Texas Hold 'Em Poker
+ EXPECT_EQ(choose<double>(50, 3), 19600.);
+ EXPECT_EQ(choose<double>(50, 47), 19600.);
+ // number of possible hands in bridge
+ EXPECT_EQ(choose<double>(52, 13), 635013559600.);
+ EXPECT_EQ(choose<double>(52, 39), 635013559600.);
+ // number of possible Lotto results
+ EXPECT_EQ(choose<double>(49, 6), 13983816.);
+ EXPECT_EQ(choose<double>(49, 43), 13983816.);
+}
+
+TEST(ChooseTest, Unsigned) {
+ auto const BIG = std::numeric_limits<unsigned>::max() - 1;
+ EXPECT_EQ(choose<unsigned>(BIG, BIG - 1), BIG);
+ EXPECT_EQ(choose<unsigned>(BIG, BIG), 1);
+ EXPECT_EQ(choose<unsigned>(BIG, BIG + 1), 0);
+}
diff --git a/src/3rdparty/2geom/tests/circle-test.cpp b/src/3rdparty/2geom/tests/circle-test.cpp
new file mode 100644
index 0000000..5ff6493
--- /dev/null
+++ b/src/3rdparty/2geom/tests/circle-test.cpp
@@ -0,0 +1,141 @@
+/** @file
+ * @brief Unit tests for Circle and related functions.
+ * Uses the Google Testing Framework
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include "testing.h"
+#include <2geom/circle.h>
+#include <2geom/line.h>
+
+using namespace Geom;
+
+TEST(CircleTest, Equality) {
+ Circle a(4, 5, 6);
+ Circle b(Point(4, 5), 6);
+ Circle c(4.00000001, 5, 6);
+
+ EXPECT_EQ(a, b);
+ EXPECT_NE(a, c);
+ EXPECT_NE(b, c);
+}
+
+TEST(CircleTest, Nearness) {
+ Circle a(4, 5, 6);
+ Circle b(4.000007, 5, 6);
+ Circle c(4, 5, 6.000007);
+ Circle d(4.000007, 5, 6.000007);
+ Circle e(4, 5, 7);
+
+ EXPECT_TRUE(are_near(a, b, 1e-5));
+ EXPECT_TRUE(are_near(a, c, 1e-5));
+ EXPECT_TRUE(are_near(c, d, 1e-5));
+ EXPECT_FALSE(are_near(a, d, 1e-5));
+ EXPECT_FALSE(are_near(a, e, 1e-2));
+ EXPECT_FALSE(are_near(b, e, 1e-2));
+ EXPECT_FALSE(are_near(c, e, 1e-2));
+}
+
+TEST(CircleTest, UnitCircleTransform) {
+ Circle c(17, 23, 22);
+
+ Point q = c.pointAt(M_PI/2);
+ Point p = Point(0, 1) * c.unitCircleTransform();
+ Point r = q * c.inverseUnitCircleTransform();
+
+ EXPECT_FLOAT_EQ(p[X], q[X]);
+ EXPECT_FLOAT_EQ(p[Y], q[Y]);
+ EXPECT_FLOAT_EQ(r[X], 0);
+ EXPECT_FLOAT_EQ(r[Y], 1);
+}
+
+TEST(CircleTest, Coefficients) {
+ Circle circ(5, 12, 87), circ2;
+
+ Coord a, b, c, d;
+ circ.coefficients(a, b, c, d);
+ circ2.setCoefficients(a, b, c, d);
+
+ EXPECT_TRUE(are_near(circ, circ2, 1e-15));
+
+ for (unsigned i = 0; i < 100; ++i) {
+ Coord t = -5 + 0.111 * i;
+ Point p = circ.pointAt(t);
+ Coord eqres = a * p[X]*p[X] + a*p[Y]*p[Y] + b*p[X] + c*p[Y] + d;
+ EXPECT_NEAR(eqres, 0, 1e-11);
+ }
+}
+
+TEST(CircleTest, CircleIntersection) {
+ Circle a(5, 5, 5), b(15, 5, 5), c(10, 10, 6), d(-5, 5, 2);
+ std::vector<ShapeIntersection> r1, r2, r3;
+
+ r1 = a.intersect(b);
+ ASSERT_EQ(r1.size(), 1u);
+ EXPECT_EQ(r1[0].point(), Point(10,5));
+ EXPECT_intersections_valid(a, b, r1, 1e-15);
+
+ r2 = a.intersect(c);
+ EXPECT_EQ(r2.size(), 2u);
+ EXPECT_intersections_valid(a, c, r2, 1e-15);
+
+ r3 = b.intersect(c);
+ EXPECT_EQ(r3.size(), 2u);
+ EXPECT_intersections_valid(b, c, r3, 4e-15);
+
+ EXPECT_TRUE(a.intersect(d).empty());
+ EXPECT_TRUE(b.intersect(d).empty());
+ EXPECT_TRUE(c.intersect(d).empty());
+}
+
+TEST(CircleTest, LineIntersection) {
+ Circle c(5, 5, 10);
+ Line l1(Point(-5, -20), Point(-5, 20));
+ Line l2(Point(0, 0), Point(10, 2.3));
+ Line l3(Point(20, -20), Point(0, -20));
+
+ EXPECT_TRUE(c.intersects(l1));
+ EXPECT_TRUE(c.intersects(l2));
+ EXPECT_FALSE(c.intersects(l3));
+
+ std::vector<ShapeIntersection> r1, r2, r3;
+
+ r1 = c.intersect(l1);
+ ASSERT_EQ(r1.size(), 1u);
+ EXPECT_EQ(r1[0].point(), Point(-5, 5));
+ EXPECT_intersections_valid(c, l1, r1, 1e-15);
+
+ r2 = c.intersect(l2);
+ EXPECT_EQ(r2.size(), 2u);
+ EXPECT_intersections_valid(c, l2, r2, 1e-14);
+
+ r3 = c.intersect(l3);
+ EXPECT_TRUE(r3.empty());
+}
diff --git a/src/3rdparty/2geom/tests/convex-hull-test.cpp b/src/3rdparty/2geom/tests/convex-hull-test.cpp
new file mode 100644
index 0000000..2f20f43
--- /dev/null
+++ b/src/3rdparty/2geom/tests/convex-hull-test.cpp
@@ -0,0 +1,335 @@
+/** @file
+ * @brief Unit tests for ConvexHull and related functions.
+ * Uses the Google Testing Framework
+ *//*
+ * Authors:
+ * Nathan Hurst <njh@njhurst.com>
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2011-2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include "testing.h"
+#include <iostream>
+
+#include <2geom/convex-hull.h>
+#include <vector>
+#include <iterator>
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
+using namespace std;
+using namespace Geom;
+
+void points_from_shape(std::vector<Point> &pts, std::string const &shape) {
+ pts.clear();
+ int x = 0, y = 0;
+ for (char c : shape) {
+ if (c == '\n') {
+ x = 0; ++y;
+ continue;
+ }
+ if (c == ' ') {
+ ++x;
+ continue;
+ }
+ pts.emplace_back(x, y);
+ ++x;
+ }
+}
+
+class ConvexHullTest : public ::testing::Test {
+protected:
+ ConvexHullTest()
+ : null(hulls[0])
+ , point(hulls[1])
+ , line(hulls[2])
+ , triangle(hulls[3])
+ , square(hulls[4])
+ , hexagon(hulls[5])
+ , antihexagon(hulls[6])
+ , gem(hulls[7])
+ , diamond(hulls[8])
+ {
+ null = ConvexHull();
+
+ std::vector<Point> pts;
+
+ pts.emplace_back(0,0);
+ point = ConvexHull(pts);
+ pts.emplace_back(1,0);
+ line = ConvexHull(pts);
+ pts.emplace_back(0,1);
+ triangle = ConvexHull(pts);
+ pts.emplace_back(1,1);
+ square = ConvexHull(pts);
+ pts.clear();
+
+ for(int i = 0; i < 6; i++) {
+ pts.emplace_back(cos(i*M_PI*2/6), sin(i*M_PI*2/6));
+ }
+ hexagon = ConvexHull(pts);
+ pts.clear();
+
+ for(int i = 0; i < 6; i++) {
+ pts.emplace_back(cos((1-i*2)*M_PI/6), sin((1-i*2)*M_PI/6));
+ }
+ antihexagon = ConvexHull(pts);
+ pts.clear();
+
+ gem_shape =
+ " ++++ \n"
+ "++++++ \n"
+ "++++++ \n"
+ "++++++ \n"
+ " ++++ \n";
+ points_from_shape(pts, gem_shape);
+ gem.swap(pts);
+
+ diamond_shape =
+ " + \n"
+ " +++++ \n"
+ " +++++ \n"
+ "+++++++ \n"
+ " +++++ \n"
+ " +++++ \n"
+ " + \n";
+ points_from_shape(pts, diamond_shape);
+ diamond.swap(pts);
+ }
+
+ ConvexHull hulls[9];
+ ConvexHull &null, &point, &line, &triangle, &square, &hexagon, &antihexagon, &gem, &diamond;
+ std::string gem_shape, diamond_shape;
+};
+
+void check_convex(ConvexHull &/*ch*/) {
+ // TODO
+}
+
+TEST_F(ConvexHullTest, SizeAndDegeneracy) {
+ EXPECT_EQ(0u, null.size());
+ EXPECT_TRUE(null.empty());
+ EXPECT_TRUE(null.isDegenerate());
+ EXPECT_FALSE(null.isSingular());
+ EXPECT_FALSE(null.isLinear());
+
+ EXPECT_EQ(1u, point.size());
+ EXPECT_FALSE(point.empty());
+ EXPECT_TRUE(point.isDegenerate());
+ EXPECT_TRUE(point.isSingular());
+ EXPECT_FALSE(point.isLinear());
+
+ EXPECT_EQ(2u, line.size());
+ EXPECT_FALSE(line.empty());
+ EXPECT_TRUE(line.isDegenerate());
+ EXPECT_FALSE(line.isSingular());
+ EXPECT_TRUE(line.isLinear());
+
+ EXPECT_EQ(3u, triangle.size());
+ EXPECT_FALSE(triangle.empty());
+ EXPECT_FALSE(triangle.isDegenerate());
+ EXPECT_FALSE(triangle.isSingular());
+ EXPECT_FALSE(triangle.isLinear());
+
+ EXPECT_EQ(4u, square.size());
+ EXPECT_FALSE(square.empty());
+ EXPECT_FALSE(square.isDegenerate());
+ EXPECT_FALSE(square.isSingular());
+ EXPECT_FALSE(square.isLinear());
+
+ EXPECT_EQ(6u, hexagon.size());
+ EXPECT_FALSE(hexagon.empty());
+ EXPECT_FALSE(hexagon.isDegenerate());
+ EXPECT_FALSE(hexagon.isSingular());
+ EXPECT_FALSE(hexagon.isLinear());
+
+ EXPECT_EQ(6u, antihexagon.size());
+ EXPECT_FALSE(antihexagon.empty());
+ EXPECT_FALSE(antihexagon.isDegenerate());
+ EXPECT_FALSE(antihexagon.isSingular());
+ EXPECT_FALSE(antihexagon.isLinear());
+
+ EXPECT_EQ(8u, gem.size());
+ EXPECT_FALSE(gem.empty());
+ EXPECT_FALSE(gem.isDegenerate());
+ EXPECT_FALSE(gem.isSingular());
+ EXPECT_FALSE(gem.isLinear());
+
+ EXPECT_EQ(8u, diamond.size());
+ EXPECT_FALSE(diamond.empty());
+ EXPECT_FALSE(diamond.isDegenerate());
+ EXPECT_FALSE(diamond.isSingular());
+ EXPECT_FALSE(diamond.isLinear());
+}
+
+
+TEST_F(ConvexHullTest, Area) {
+ EXPECT_EQ(0, null.area());
+ EXPECT_EQ(0, point.area());
+ EXPECT_EQ(0, line.area());
+ EXPECT_EQ(0.5, triangle.area());
+ EXPECT_EQ(1, square.area());
+ EXPECT_EQ(18, gem.area());
+ EXPECT_EQ(24, diamond.area());
+ EXPECT_FLOAT_EQ(6*(0.5*1*sin(M_PI/3)), hexagon.area());
+ EXPECT_FLOAT_EQ(6*(0.5*1*sin(M_PI/3)), antihexagon.area());
+}
+
+TEST_F(ConvexHullTest, Bounds) {
+ //Rect hexbounds(-1,sin(M_PI/3),1,-sin(M_PI/3));
+
+ EXPECT_EQ(OptRect(), null.bounds());
+ EXPECT_EQ(OptRect(0,0,0,0), point.bounds());
+ EXPECT_EQ(OptRect(0,0,1,0), line.bounds());
+ EXPECT_EQ(OptRect(0,0,1,1), triangle.bounds());
+ EXPECT_EQ(OptRect(0,0,1,1), square.bounds());
+ EXPECT_EQ(OptRect(0,0,5,4), gem.bounds());
+ EXPECT_EQ(OptRect(0,0,6,6), diamond.bounds());
+ //EXPECT_TRUE(hexbounds == hexagon.bounds());
+ //EXPECT_TRUE(hexbounds == antihexagon.bounds());
+}
+
+::testing::AssertionResult HullContainsPoint(ConvexHull const &h, Point const &p) {
+ if (h.contains(p)) {
+ return ::testing::AssertionSuccess();
+ } else {
+ return ::testing::AssertionFailure()
+ << "Convex hull:\n"
+ << h << "\ndoes not contain " << p;
+ }
+}
+
+TEST_F(ConvexHullTest, PointContainment) {
+ Point zero(0,0), half(0.5, 0.5), x(0.25, 0.25);
+ EXPECT_FALSE(HullContainsPoint(null, zero));
+ EXPECT_TRUE(HullContainsPoint(point, zero));
+ EXPECT_TRUE(HullContainsPoint(line, zero));
+ EXPECT_TRUE(HullContainsPoint(triangle, zero));
+ EXPECT_TRUE(HullContainsPoint(square, zero));
+ EXPECT_FALSE(HullContainsPoint(line, half));
+ EXPECT_TRUE(HullContainsPoint(triangle, x));
+ EXPECT_TRUE(HullContainsPoint(triangle, half));
+ EXPECT_TRUE(HullContainsPoint(square, half));
+ EXPECT_TRUE(HullContainsPoint(hexagon, zero));
+ EXPECT_TRUE(HullContainsPoint(antihexagon, zero));
+
+ std::vector<Point> pts;
+
+ points_from_shape(pts, gem_shape);
+ for (auto & pt : pts) {
+ EXPECT_TRUE(HullContainsPoint(gem, pt));
+ }
+
+ points_from_shape(pts, diamond_shape);
+ for (auto & pt : pts) {
+ EXPECT_TRUE(HullContainsPoint(diamond, pt));
+ }
+
+ /*EXPECT_FALSE(null.interiorContains(zero));
+ EXPECT_FALSE(point.interiorContains(zero));
+ EXPECT_FALSE(line.interiorContains(zero));
+ EXPECT_FALSE(triangle.interiorContains(zero));
+ EXPECT_FALSE(square.interiorContains(zero));
+ EXPECT_FALSE(line.interiorContains(half));
+ EXPECT_FALSE(triangle.interiorContains(Point(0,0.5)));
+ EXPECT_FALSE(triangle.interiorContains(half));
+ EXPECT_TRUE(square.interiorContains(half));*/
+}
+
+TEST_F(ConvexHullTest, ExtremePoints) {
+ Point zero(0,0);
+ EXPECT_EQ(0., point.top());
+ EXPECT_EQ(0., point.right());
+ EXPECT_EQ(0., point.bottom());
+ EXPECT_EQ(0., point.left());
+ EXPECT_EQ(zero, point.topPoint());
+ EXPECT_EQ(zero, point.rightPoint());
+ EXPECT_EQ(zero, point.bottomPoint());
+ EXPECT_EQ(zero, point.leftPoint());
+
+ // line from 0,0 to 1,0
+ EXPECT_EQ(0., line.top());
+ EXPECT_EQ(1., line.right());
+ EXPECT_EQ(0., line.bottom());
+ EXPECT_EQ(0., line.left());
+ EXPECT_EQ(Point(1,0), line.topPoint());
+ EXPECT_EQ(Point(1,0), line.rightPoint());
+ EXPECT_EQ(Point(0,0), line.bottomPoint());
+ EXPECT_EQ(Point(0,0), line.leftPoint());
+
+ // triangle 0,0 1,0 0,1
+ EXPECT_EQ(0., triangle.top());
+ EXPECT_EQ(1., triangle.right());
+ EXPECT_EQ(1., triangle.bottom());
+ EXPECT_EQ(0., triangle.left());
+ EXPECT_EQ(Point(1,0), triangle.topPoint());
+ EXPECT_EQ(Point(1,0), triangle.rightPoint());
+ EXPECT_EQ(Point(0,1), triangle.bottomPoint());
+ EXPECT_EQ(Point(0,0), triangle.leftPoint());
+
+ // square 0,0 to 1,1
+ EXPECT_EQ(0., square.top());
+ EXPECT_EQ(1., square.right());
+ EXPECT_EQ(1., square.bottom());
+ EXPECT_EQ(0., square.left());
+ EXPECT_EQ(Point(1,0), square.topPoint());
+ EXPECT_EQ(Point(1,1), square.rightPoint());
+ EXPECT_EQ(Point(0,1), square.bottomPoint());
+ EXPECT_EQ(Point(0,0), square.leftPoint());
+
+ EXPECT_EQ(0., gem.top());
+ EXPECT_EQ(5., gem.right());
+ EXPECT_EQ(4., gem.bottom());
+ EXPECT_EQ(0., gem.left());
+ EXPECT_EQ(Point(4,0), gem.topPoint());
+ EXPECT_EQ(Point(5,3), gem.rightPoint());
+ EXPECT_EQ(Point(1,4), gem.bottomPoint());
+ EXPECT_EQ(Point(0,1), gem.leftPoint());
+
+ EXPECT_EQ(0., diamond.top());
+ EXPECT_EQ(6., diamond.right());
+ EXPECT_EQ(6., diamond.bottom());
+ EXPECT_EQ(0., diamond.left());
+ EXPECT_EQ(Point(3,0), diamond.topPoint());
+ EXPECT_EQ(Point(6,3), diamond.rightPoint());
+ EXPECT_EQ(Point(3,6), diamond.bottomPoint());
+ EXPECT_EQ(Point(0,3), diamond.leftPoint());
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/tests/coord-test.cpp b/src/3rdparty/2geom/tests/coord-test.cpp
new file mode 100644
index 0000000..c96b095
--- /dev/null
+++ b/src/3rdparty/2geom/tests/coord-test.cpp
@@ -0,0 +1,90 @@
+/** @file
+ * @brief Unit tests for functions related to Coord.
+ * Uses the Google Testing Framework
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2014 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <gtest/gtest.h>
+#include <2geom/coord.h>
+#include <climits>
+#include <stdint.h>
+#include <glib.h>
+#include <iostream>
+
+namespace Geom {
+
+TEST(CoordTest, StringRoundtripShortest) {
+ union {
+ uint64_t u;
+ double d;
+ };
+ for (unsigned i = 0; i < 100000; ++i) {
+ u = uint64_t(g_random_int()) | (uint64_t(g_random_int()) << 32);
+ if (!std::isfinite(d)) continue;
+
+ std::string str = format_coord_shortest(d);
+ double x = parse_coord(str);
+ if (x != d) {
+ std::cout << std::endl << d << " -> " << str << " -> " << x << std::endl;
+ }
+ EXPECT_EQ(d, x);
+ }
+}
+
+TEST(CoordTest, StringRoundtripNice) {
+ union {
+ uint64_t u;
+ double d;
+ };
+ for (unsigned i = 0; i < 100000; ++i) {
+ u = uint64_t(g_random_int()) | (uint64_t(g_random_int()) << 32);
+ if (!std::isfinite(d)) continue;
+
+ std::string str = format_coord_nice(d);
+ double x = parse_coord(str);
+ if (x != d) {
+ std::cout << std::endl << d << " -> " << str << " -> " << x << std::endl;
+ }
+ EXPECT_EQ(d, x);
+ }
+}
+
+} // end namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/tests/dependent-project/CMakeLists.txt b/src/3rdparty/2geom/tests/dependent-project/CMakeLists.txt
new file mode 100644
index 0000000..c371114
--- /dev/null
+++ b/src/3rdparty/2geom/tests/dependent-project/CMakeLists.txt
@@ -0,0 +1,27 @@
+cmake_minimum_required(VERSION 3.1)
+project(test_dep_2geom CXX C)
+set(CMAKE_CXX_STANDARD 17)
+
+option(2GEOM_AS_SUBPROJECT "include 2geom as subproject" OFF)
+
+if (2GEOM_AS_SUBPROJECT)
+ message("Using 2geom as subdirectory")
+ set(2GEOM_BUILD_SHARED ON CACHE BOOL "Build 2geom shared version")
+ add_subdirectory("../../" 2geom)
+else()
+ message("Using installed 2geom")
+ find_package(2Geom REQUIRED)
+endif()
+
+add_library(my_lib SHARED my_lib.cpp)
+add_executable(main main.cpp)
+target_link_libraries(main my_lib)
+target_link_libraries(my_lib PUBLIC 2Geom::2geom)
+
+install(TARGETS
+ main
+ my_lib
+ RUNTIME DESTINATION bin
+ ARCHIVE DESTINATION lib
+ LIBRARY DESTINATION lib
+ )
diff --git a/src/3rdparty/2geom/tests/dependent-project/main.cpp b/src/3rdparty/2geom/tests/dependent-project/main.cpp
new file mode 100644
index 0000000..6b6469c
--- /dev/null
+++ b/src/3rdparty/2geom/tests/dependent-project/main.cpp
@@ -0,0 +1,12 @@
+#include <2geom/2geom.h>
+#include <iostream>
+#include "my_lib.h"
+
+int main() {
+ Geom::Rect rect1(0, 0, 1, 1);
+ Geom::Rect rect2(0.5, 0.5, 1.5, 1.5);
+
+ std::cout << sum_of_three_points(Geom::Point(1, 1), Geom::Point(1, 2), Geom::Point(2, 3));
+
+ return rect1.intersects(rect2) ? 0 : 1;
+}
diff --git a/src/3rdparty/2geom/tests/dependent-project/my_lib.cpp b/src/3rdparty/2geom/tests/dependent-project/my_lib.cpp
new file mode 100644
index 0000000..d5af62a
--- /dev/null
+++ b/src/3rdparty/2geom/tests/dependent-project/my_lib.cpp
@@ -0,0 +1,6 @@
+#include "my_lib.h"
+
+using namespace Geom;
+Point sum_of_three_points(const Point&a, const Point&b, const Point&c){
+ return a+b+c;
+} \ No newline at end of file
diff --git a/src/3rdparty/2geom/tests/dependent-project/my_lib.h b/src/3rdparty/2geom/tests/dependent-project/my_lib.h
new file mode 100644
index 0000000..2278aaf
--- /dev/null
+++ b/src/3rdparty/2geom/tests/dependent-project/my_lib.h
@@ -0,0 +1,4 @@
+#pragma once
+#include <2geom/2geom.h>
+
+Geom::Point sum_of_three_points(const Geom::Point&a, const Geom::Point&b, const Geom::Point&c); \ No newline at end of file
diff --git a/src/3rdparty/2geom/tests/ellipse-test.cpp b/src/3rdparty/2geom/tests/ellipse-test.cpp
new file mode 100644
index 0000000..38eca0e
--- /dev/null
+++ b/src/3rdparty/2geom/tests/ellipse-test.cpp
@@ -0,0 +1,410 @@
+/** @file
+ * @brief Unit tests for Ellipse and related functions
+ * Uses the Google Testing Framework
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <iostream>
+#include <glib.h>
+
+#include <2geom/angle.h>
+#include <2geom/ellipse.h>
+#include <2geom/elliptical-arc.h>
+#include <memory>
+
+#include "testing.h"
+
+#ifndef M_SQRT2
+# define M_SQRT2 1.41421356237309504880
+#endif
+
+using namespace Geom;
+
+TEST(EllipseTest, Arcs) {
+ Ellipse e(Point(5,10), Point(5, 10), 0);
+
+ std::unique_ptr<EllipticalArc> arc1(e.arc(Point(5,0), Point(0,0), Point(0,10)));
+
+ EXPECT_EQ(arc1->initialPoint(), Point(5,0));
+ EXPECT_EQ(arc1->finalPoint(), Point(0,10));
+ EXPECT_EQ(arc1->boundsExact(), Rect::from_xywh(0,0,5,10));
+ EXPECT_EQ(arc1->center(), e.center());
+ EXPECT_EQ(arc1->largeArc(), false);
+ EXPECT_EQ(arc1->sweep(), false);
+
+ std::unique_ptr<EllipticalArc> arc1r(e.arc(Point(0,10), Point(0,0), Point(5,0)));
+
+ EXPECT_EQ(arc1r->boundsExact(), arc1->boundsExact());
+ EXPECT_EQ(arc1r->sweep(), true);
+ EXPECT_EQ(arc1r->largeArc(), false);
+
+ std::unique_ptr<EllipticalArc> arc2(e.arc(Point(5,0), Point(10,20), Point(0,10)));
+
+ EXPECT_EQ(arc2->boundsExact(), Rect::from_xywh(0,0,10,20));
+ EXPECT_EQ(arc2->largeArc(), true);
+ EXPECT_EQ(arc2->sweep(), true);
+
+ std::unique_ptr<EllipticalArc> arc2r(e.arc(Point(0,10), Point(10,20), Point(5,0)));
+
+ EXPECT_EQ(arc2r->boundsExact(), arc2->boundsExact());
+ EXPECT_EQ(arc2r->largeArc(), true);
+ EXPECT_EQ(arc2r->sweep(), false);
+
+ // exactly half arc
+ std::unique_ptr<EllipticalArc> arc3(e.arc(Point(5,0), Point(0,10), Point(5,20)));
+
+ EXPECT_EQ(arc3->boundsExact(), Rect::from_xywh(0,0,5,20));
+ EXPECT_EQ(arc3->largeArc(), false);
+ EXPECT_EQ(arc3->sweep(), false);
+
+ // inner point exactly at midpoint between endpoints
+ std::unique_ptr<EllipticalArc> arc4(e.arc(Point(5,0), Point(2.5,5), Point(0,10)));
+
+ EXPECT_EQ(arc4->initialPoint(), Point(5,0));
+ EXPECT_EQ(arc4->finalPoint(), Point(0,10));
+ EXPECT_EQ(arc4->boundsExact(), Rect::from_xywh(0,0,5,10));
+ EXPECT_EQ(arc4->largeArc(), false);
+ EXPECT_EQ(arc4->sweep(), false);
+
+ std::unique_ptr<EllipticalArc> arc4r(e.arc(Point(0,10), Point(2.5,5), Point(5,0)));
+
+ EXPECT_EQ(arc4r->initialPoint(), Point(0,10));
+ EXPECT_EQ(arc4r->finalPoint(), Point(5,0));
+ EXPECT_EQ(arc4r->boundsExact(), Rect::from_xywh(0,0,5,10));
+ EXPECT_EQ(arc4r->largeArc(), false);
+ EXPECT_EQ(arc4r->sweep(), true);
+}
+
+TEST(EllipseTest, AreNear) {
+ Ellipse e1(Point(5.000001,10), Point(5,10), Angle::from_degrees(45));
+ Ellipse e2(Point(5.000000,10), Point(5,10), Angle::from_degrees(225));
+ Ellipse e3(Point(4.999999,10), Point(10,5), Angle::from_degrees(135));
+ Ellipse e4(Point(5.000001,10), Point(10,5), Angle::from_degrees(315));
+
+ EXPECT_TRUE(are_near(e1, e2, 1e-5));
+ EXPECT_TRUE(are_near(e1, e3, 1e-5));
+ EXPECT_TRUE(are_near(e1, e4, 1e-5));
+
+ Ellipse c1(Point(20.000001,35.000001), Point(5.000001,4.999999), Angle::from_degrees(180.00001));
+ Ellipse c2(Point(19.999999,34.999999), Point(4.999999,5.000001), Angle::from_degrees(179.99999));
+ //std::cout << c1 << "\n" << c2 << std::endl;
+ EXPECT_TRUE(are_near(c1, c2, 2e-5));
+
+ EXPECT_FALSE(are_near(c1, e1, 1e-5));
+ EXPECT_FALSE(are_near(c2, e1, 1e-5));
+ EXPECT_FALSE(are_near(c1, e2, 1e-5));
+ EXPECT_FALSE(are_near(c2, e2, 1e-5));
+ EXPECT_FALSE(are_near(c1, e3, 1e-5));
+ EXPECT_FALSE(are_near(c2, e3, 1e-5));
+ EXPECT_FALSE(are_near(c1, e4, 1e-5));
+ EXPECT_FALSE(are_near(c2, e4, 1e-5));
+}
+
+TEST(EllipseTest, Transformations) {
+ Ellipse e(Point(5,10), Point(5,10), Angle::from_degrees(45));
+
+ Ellipse er = e * Rotate::around(Point(5,10), Angle::from_degrees(45));
+ Ellipse ercmp(Point(5,10), Point(5,10), Angle::from_degrees(90));
+ //std::cout << e << "\n" << er << "\n" << ercmp << std::endl;
+ EXPECT_TRUE(are_near(er, ercmp, 1e-12));
+
+ Ellipse eflip = e * Affine(Scale(-1,1));
+ Ellipse eflipcmp(Point(-5, 10), Point(5,10), Angle::from_degrees(135));
+ EXPECT_TRUE(are_near(eflip, eflipcmp, 1e-12));
+}
+
+TEST(EllipseTest, TimeAt) {
+ Ellipse e(Point(4, 17), Point(22, 34), 2);
+
+ for (unsigned i = 0; i < 100; ++i) {
+ Coord t = g_random_double_range(0, 2*M_PI);
+ Point p = e.pointAt(t);
+ Coord t2 = e.timeAt(p);
+ EXPECT_FLOAT_EQ(t, t2);
+ }
+}
+
+TEST(EllipseTest, LineIntersection) {
+ Ellipse e(Point(0, 0), Point(3, 2), 0);
+ Line l(Point(0, -2), Point(1, 0));
+
+ std::vector<ShapeIntersection> xs = e.intersect(l);
+
+ ASSERT_EQ(xs.size(), 2ul);
+
+ // due to numeric imprecision when evaluating Ellipse,
+ // the points may deviate by around 2e-16
+ EXPECT_NEAR(xs[0].point()[X], 0, 1e-15);
+ EXPECT_NEAR(xs[0].point()[Y], -2, 1e-15);
+ EXPECT_NEAR(xs[1].point()[X], 9./5, 1e-15);
+ EXPECT_NEAR(xs[1].point()[Y], 8./5, 1e-15);
+
+ EXPECT_intersections_valid(e, l, xs, 1e-15);
+
+ // Test with a degenerate ellipse
+ auto degen = Ellipse({0, 0}, {3, 2}, 0);
+ degen *= Scale(1.0, 0.0); // Squash to the X-axis interval [-3, 3].
+
+ g_random_set_seed(0xCAFECAFE);
+ // Intersect with a line
+ for (size_t _ = 0; _ < 10'000; _++) {
+ auto line = Line(Point(g_random_double_range(-3.0, 3.0), g_random_double_range(-3.0, -1.0)),
+ Point(g_random_double_range(-3.0, 3.0), g_random_double_range(1.0, 3.0)));
+ auto xings = degen.intersect(line);
+ EXPECT_EQ(xings.size(), 2u);
+ EXPECT_intersections_valid(degen, line, xings, 1e-14);
+ }
+ // Intersect with another, non-degenerate ellipse
+ for (size_t _ = 0; _ < 10'000; _++) {
+ auto other = Ellipse(Point(g_random_double_range(-1.0, 1.0), g_random_double_range(-1.0, 1.0)),
+ Point(g_random_double_range(1.0, 2.0), g_random_double_range(1.0, 3.0)), 0);
+ auto xings = degen.intersect(other);
+ EXPECT_intersections_valid(degen, other, xings, 1e-14);
+ }
+ // Intersect with another ellipse which is also degenerate
+ for (size_t _ = 0; _ < 10'000; _++) {
+ auto other = Ellipse({0, 0}, {1, 1}, 0); // Unit circle
+ other *= Scale(0.0, g_random_double_range(0.5, 4.0)); // Squash to Y axis
+ other *= Rotate(g_random_double_range(-1.5, 1.5)); // Rotate a little (still passes through the origin)
+ other *= Translate(g_random_double_range(-2.9, 2.9), 0.0);
+ auto xings = degen.intersect(other);
+ EXPECT_EQ(xings.size(), 4u);
+ EXPECT_intersections_valid(degen, other, xings, 1e-14);
+ }
+}
+
+TEST(EllipseTest, EllipseIntersection) {
+ Ellipse e1;
+ Ellipse e2;
+ std::vector<ShapeIntersection> xs;
+
+ e1.set(Point(300, 300), Point(212, 70), -0.785);
+ e2.set(Point(250, 300), Point(230, 90), 1.321);
+ xs = e1.intersect(e2);
+ EXPECT_EQ(xs.size(), 4ul);
+ EXPECT_intersections_valid(e1, e2, xs, 4e-10);
+
+ e1.set(Point(0, 0), Point(1, 1), 0);
+ e2.set(Point(0, 1), Point(1, 1), 0);
+ xs = e1.intersect(e2);
+ EXPECT_EQ(xs.size(), 2ul);
+ EXPECT_intersections_valid(e1, e2, xs, 1e-10);
+
+ e1.set(Point(0, 0), Point(1, 1), 0);
+ e2.set(Point(1, 0), Point(1, 1), 0);
+ xs = e1.intersect(e2);
+ EXPECT_EQ(xs.size(), 2ul);
+ EXPECT_intersections_valid(e1, e2, xs, 1e-10);
+
+ // === Test detection of external tangency between ellipses ===
+ // Perpendicular major axes
+ e1.set({0, 0}, {5, 3}, 0); // rightmost point (5, 0)
+ e2.set({6, 0}, {1, 2}, 0); // leftmost point (5, 0)
+ xs = e1.intersect(e2);
+ ASSERT_GT(xs.size(), 0);
+ EXPECT_intersections_valid(e1, e2, xs, 1e-10);
+ EXPECT_TRUE(are_near(xs[0].point(), Point(5, 0)));
+
+ // Collinear major axes
+ e1.set({30, 0}, {9, 1}, 0); // leftmost point (21, 0)
+ e2.set({18, 0}, {3, 2}, 0); // rightmost point (21, 0)
+ xs = e1.intersect(e2);
+ ASSERT_GT(xs.size(), 0);
+ EXPECT_intersections_valid(e1, e2, xs, 1e-10);
+ EXPECT_TRUE(are_near(xs[0].point(), Point(21, 0)));
+
+ // Circles not aligned to an axis (Pythagorean triple: 3^2 + 4^2 == 5^2)
+ e1.set({0, 0}, {3, 3}, 0); // radius 3
+ e2.set({3, 4}, {2, 2}, 0); // radius 2
+ // We know 2 + 3 == 5 == distance((0, 0), (3, 4)) so there's an external tangency
+ // between these circles, at a point at distance 3 from the origin, on the line x = 0.75 y.
+ xs = e1.intersect(e2);
+ ASSERT_GT(xs.size(), 0);
+ EXPECT_intersections_valid(e1, e2, xs, 1e-6);
+
+ // === Test the detection of internal tangency between ellipses ===
+ // Perpendicular major axes
+ e1.set({0, 0}, {8, 17}, 0); // rightmost point (8, 0)
+ e2.set({6, 0}, {2, 1}, 0); // rightmost point (8, 0)
+ xs = e1.intersect(e2);
+ ASSERT_GT(xs.size(), 0);
+ EXPECT_intersections_valid(e1, e2, xs, 1e-10);
+ EXPECT_TRUE(are_near(xs[0].point(), Point(8, 0)));
+
+ // Collinear major axes
+ e1.set({30, 0}, {9, 5}, 0); // rightmost point (39, 0)
+ e2.set({36, 0}, {3, 1}, 0); // rightmost point (39, 0)
+ xs = e1.intersect(e2);
+ ASSERT_GT(xs.size(), 0);
+ EXPECT_intersections_valid(e1, e2, xs, 1e-6);
+ EXPECT_TRUE(are_near(xs[0].point(), Point(39, 0)));
+
+ // Circles not aligned to an axis (Pythagorean triple: 3^2 + 4^2 == 5^2)
+ e1.set({4, 3}, {5, 5}, 0); // Passes through (0, 0), center on the line y = 0.75 x
+ e2.set({8, 6}, {10, 10}, 0); // Also passes through (0, 0), center on the same line.
+ xs = e1.intersect(e2);
+ ASSERT_GT(xs.size(), 0);
+ EXPECT_intersections_valid(e1, e2, xs, 1e-6);
+ EXPECT_TRUE(are_near(xs[0].point(), Point(0, 0)));
+}
+
+TEST(EllipseTest, BezierIntersection) {
+ Ellipse e(Point(300, 300), Point(212, 70), -3.926);
+ D2<Bezier> b(Bezier(100, 300, 100, 500), Bezier(100, 100, 500, 500));
+
+ std::vector<ShapeIntersection> xs = e.intersect(b);
+
+ EXPECT_EQ(xs.size(), 2ul);
+ EXPECT_intersections_valid(e, b, xs, 6e-12);
+}
+
+TEST(EllipseTest, Coefficients) {
+ std::vector<Ellipse> es;
+ es.emplace_back(Point(-15,25), Point(10,15), Angle::from_degrees(45).radians0());
+ es.emplace_back(Point(-10,33), Point(40,20), M_PI);
+ es.emplace_back(Point(10,-33), Point(40,20), Angle::from_degrees(135).radians0());
+ es.emplace_back(Point(-10,-33), Point(50,10), Angle::from_degrees(330).radians0());
+
+ for (auto & i : es) {
+ Coord a, b, c, d, e, f;
+ i.coefficients(a, b, c, d, e, f);
+ Ellipse te(a, b, c, d, e, f);
+ EXPECT_near(i, te, 1e-10);
+ for (Coord t = -5; t < 5; t += 0.125) {
+ Point p = i.pointAt(t);
+ Coord eq = a*p[X]*p[X] + b*p[X]*p[Y] + c*p[Y]*p[Y]
+ + d*p[X] + e*p[Y] + f;
+ EXPECT_NEAR(eq, 0, 1e-10);
+ }
+ }
+}
+
+TEST(EllipseTest, UnitCircleTransform) {
+ std::vector<Ellipse> es;
+ es.emplace_back(Point(-15,25), Point(10,15), Angle::from_degrees(45));
+ es.emplace_back(Point(-10,33), Point(40,20), M_PI);
+ es.emplace_back(Point(10,-33), Point(40,20), Angle::from_degrees(135));
+ es.emplace_back(Point(-10,-33), Point(50,10), Angle::from_degrees(330));
+
+ for (auto & e : es) {
+ EXPECT_near(e.unitCircleTransform() * e.inverseUnitCircleTransform(), Affine::identity(), 1e-8);
+
+ for (Coord t = -1; t < 10; t += 0.25) {
+ Point p = e.pointAt(t);
+ p *= e.inverseUnitCircleTransform();
+ EXPECT_near(p.length(), 1., 1e-10);
+ p *= e.unitCircleTransform();
+ EXPECT_near(e.pointAt(t), p, 1e-10);
+ }
+ }
+}
+
+TEST(EllipseTest, PointAt) {
+ Ellipse a(Point(0,0), Point(10,20), 0);
+ EXPECT_near(a.pointAt(0), Point(10,0), 1e-10);
+ EXPECT_near(a.pointAt(M_PI/2), Point(0,20), 1e-10);
+ EXPECT_near(a.pointAt(M_PI), Point(-10,0), 1e-10);
+ EXPECT_near(a.pointAt(3*M_PI/2), Point(0,-20), 1e-10);
+
+ Ellipse b(Point(0,0), Point(10,20), M_PI/2);
+ EXPECT_near(b.pointAt(0), Point(0,10), 1e-10);
+ EXPECT_near(b.pointAt(M_PI/2), Point(-20,0), 1e-10);
+ EXPECT_near(b.pointAt(M_PI), Point(0,-10), 1e-10);
+ EXPECT_near(b.pointAt(3*M_PI/2), Point(20,0), 1e-10);
+}
+
+TEST(EllipseTest, UnitTangentAt) {
+ Ellipse a(Point(14,-7), Point(20,10), 0);
+ Ellipse b(Point(-77,23), Point(40,10), Angle::from_degrees(45));
+
+ EXPECT_near(a.unitTangentAt(0), Point(0,1), 1e-12);
+ EXPECT_near(a.unitTangentAt(M_PI/2), Point(-1,0), 1e-12);
+ EXPECT_near(a.unitTangentAt(M_PI), Point(0,-1), 1e-12);
+ EXPECT_near(a.unitTangentAt(3*M_PI/2), Point(1,0), 1e-12);
+
+ EXPECT_near(b.unitTangentAt(0), Point(-M_SQRT2/2, M_SQRT2/2), 1e-12);
+ EXPECT_near(b.unitTangentAt(M_PI/2), Point(-M_SQRT2/2, -M_SQRT2/2), 1e-12);
+ EXPECT_near(b.unitTangentAt(M_PI), Point(M_SQRT2/2, -M_SQRT2/2), 1e-12);
+ EXPECT_near(b.unitTangentAt(3*M_PI/2), Point(M_SQRT2/2, M_SQRT2/2), 1e-12);
+}
+
+TEST(EllipseTest, Bounds)
+{
+ // Create example ellipses
+ std::vector<Ellipse> es;
+ es.emplace_back(Point(-15,25), Point(10,15), Angle::from_degrees(45));
+ es.emplace_back(Point(-10,33), Point(40,20), M_PI);
+ es.emplace_back(Point(10,-33), Point(40,20), Angle::from_degrees(111));
+ es.emplace_back(Point(-10,-33), Point(50,10), Angle::from_degrees(222));
+
+ // for reproducibility
+ g_random_set_seed(1234);
+
+ for (auto & e : es) {
+ Rect r = e.boundsExact();
+ Rect f = e.boundsFast();
+ for (unsigned j = 0; j < 10000; ++j) {
+ Coord t = g_random_double_range(-M_PI, M_PI);
+ auto const p = e.pointAt(t);
+ EXPECT_TRUE(r.contains(p));
+ EXPECT_TRUE(f.contains(p));
+ }
+ }
+
+ Ellipse e(Point(0,0), Point(10, 10), M_PI);
+ Rect bounds = e.boundsExact();
+ Rect coarse = e.boundsFast();
+ EXPECT_EQ(bounds, Rect(Point(-10,-10), Point(10,10)));
+ EXPECT_TRUE(bounds.contains(e.pointAt(0)));
+ EXPECT_TRUE(bounds.contains(e.pointAt(M_PI/2)));
+ EXPECT_TRUE(bounds.contains(e.pointAt(M_PI)));
+ EXPECT_TRUE(bounds.contains(e.pointAt(3*M_PI/2)));
+ EXPECT_TRUE(bounds.contains(e.pointAt(2*M_PI)));
+ EXPECT_TRUE(coarse.contains(e.pointAt(0)));
+ EXPECT_TRUE(coarse.contains(e.pointAt(M_PI/2)));
+ EXPECT_TRUE(coarse.contains(e.pointAt(M_PI)));
+ EXPECT_TRUE(coarse.contains(e.pointAt(3*M_PI/2)));
+ EXPECT_TRUE(coarse.contains(e.pointAt(2*M_PI)));
+
+ e = Ellipse(Point(0,0), Point(10, 10), M_PI/2);
+ bounds = e.boundsExact();
+ coarse = e.boundsFast();
+ EXPECT_EQ(bounds, Rect(Point(-10,-10), Point(10,10)));
+ EXPECT_TRUE(bounds.contains(e.pointAt(0)));
+ EXPECT_TRUE(bounds.contains(e.pointAt(M_PI/2)));
+ EXPECT_TRUE(bounds.contains(e.pointAt(M_PI)));
+ EXPECT_TRUE(bounds.contains(e.pointAt(3*M_PI/2)));
+ EXPECT_TRUE(bounds.contains(e.pointAt(2*M_PI)));
+ EXPECT_TRUE(coarse.contains(e.pointAt(0)));
+ EXPECT_TRUE(coarse.contains(e.pointAt(M_PI/2)));
+ EXPECT_TRUE(coarse.contains(e.pointAt(M_PI)));
+ EXPECT_TRUE(coarse.contains(e.pointAt(3*M_PI/2)));
+ EXPECT_TRUE(coarse.contains(e.pointAt(2*M_PI)));
+}
diff --git a/src/3rdparty/2geom/tests/elliptical-arc-test.cpp b/src/3rdparty/2geom/tests/elliptical-arc-test.cpp
new file mode 100644
index 0000000..1f6eff7
--- /dev/null
+++ b/src/3rdparty/2geom/tests/elliptical-arc-test.cpp
@@ -0,0 +1,275 @@
+/** @file
+ * @brief Unit tests for EllipticalArc.
+ * Uses the Google Testing Framework
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include "testing.h"
+#include <2geom/elliptical-arc.h>
+#include <glib.h>
+
+using namespace Geom;
+
+TEST(EllipticalArcTest, PointAt) {
+ EllipticalArc a(Point(0,0), Point(10,20), M_PI/2, false, true, Point(-40,0));
+ EXPECT_near(a.pointAt(0), a.initialPoint(), 1e-14);
+ EXPECT_near(a.pointAt(1), a.finalPoint(), 1e-14);
+ EXPECT_near(a.pointAt(0.5), Point(-20,10), 1e-14);
+
+ EllipticalArc b(Point(0,0), Point(10,20), 0, false, true, Point(-40,0));
+ EXPECT_near(b.pointAt(0), b.initialPoint(), 1e-14);
+ EXPECT_near(b.pointAt(1), b.finalPoint(), 1e-14);
+ EXPECT_near(b.pointAt(0.5), Point(-20,40), 1e-14);
+
+ EllipticalArc c(Point(200,0), Point(40,20), Angle::from_degrees(90), false, false, Point(200,100));
+ EXPECT_near(c.pointAt(0), c.initialPoint(), 1e-13);
+ EXPECT_near(c.pointAt(1), c.finalPoint(), 1e-13);
+ EXPECT_near(c.pointAt(0.5), Point(175, 50), 1e-13);
+}
+
+TEST(EllipticalArc, Transform) {
+ EllipticalArc a(Point(0,0), Point(10,20), M_PI/2, false, true, Point(-40,0));
+ EllipticalArc b(Point(-40,0), Point(10,20), M_PI/2, false, true, Point(0,0));
+ EllipticalArc c = a;
+ Affine m = Rotate::around(Point(-20,0), M_PI);
+ c.transform(m);
+
+ for (unsigned i = 0; i <= 100; ++i) {
+ Coord t = i/100.;
+ EXPECT_near(c.pointAt(t), b.pointAt(t), 1e-12);
+ EXPECT_near(a.pointAt(t)*m, c.pointAt(t), 1e-12);
+ }
+}
+
+TEST(EllipticalArcTest, Duplicate) {
+ EllipticalArc a(Point(0,0), Point(10,20), M_PI/2, true, false, Point(-40,0));
+ EllipticalArc *b = static_cast<EllipticalArc*>(a.duplicate());
+ EXPECT_EQ(a, *b);
+ delete b;
+}
+
+TEST(EllipticalArcTest, LineSegmentIntersection) {
+ std::vector<CurveIntersection> r1;
+ EllipticalArc a3(Point(0,0), Point(5,1.5), 0, true, true, Point(0,2));
+ LineSegment ls(Point(0,5), Point(7,-3));
+ r1 = a3.intersect(ls);
+ EXPECT_EQ(r1.size(), 2u);
+ EXPECT_intersections_valid(a3, ls, r1, 1e-10);
+
+ g_random_set_seed(0xB747A380);
+ // Test with randomized arcs and segments.
+ for (size_t _ = 0; _ < 10'000; _++) {
+ auto arc = EllipticalArc({g_random_double_range(1.0, 5.0), 0.0},
+ {g_random_double_range(6.0, 8.0), g_random_double_range(2.0, 7.0)},
+ g_random_double_range(-0.5, 0.5), true, g_random_boolean(),
+ {g_random_double_range(-5.0, -1.0), 0.0});
+ Coord x = g_random_double_range(15, 30);
+ Coord y = g_random_double_range(10, 20);
+ auto seg = LineSegment(Point(-x, y), Point(x, -y));
+ auto xings = arc.intersect(seg);
+ EXPECT_EQ(xings.size(), 1u);
+ EXPECT_intersections_valid(arc, seg, xings, 1e-12);
+ }
+
+ // Test with degenerate arcs
+ EllipticalArc x_squash_pos{{3.0, 0.0}, {3.0, 2.0}, 0, true, true, {-3.0, 0.0}};
+ EllipticalArc x_squash_neg{{3.0, 0.0}, {3.0, 2.0}, 0, true, false, {-3.0, 0.0}};
+ auto const squash_to_x = Scale(1.0, 0.0);
+ x_squash_pos *= squash_to_x; // squash to X axis interval [-3, 3].
+ x_squash_neg *= squash_to_x;
+
+ for (size_t _ = 0; _ < 10'000; _++) {
+ auto seg = LineSegment(Point(g_random_double_range(-3.0, 3.0), g_random_double_range(-3.0, -1.0)),
+ Point(g_random_double_range(-3.0, 3.0), g_random_double_range(1.0, 3.0)));
+ auto xings = x_squash_pos.intersect(seg);
+ EXPECT_EQ(xings.size(), 1u);
+ EXPECT_intersections_valid(x_squash_pos, seg, xings, 1e-12);
+
+ std::unique_ptr<Curve> rev{x_squash_pos.reverse()};
+ xings = rev->intersect(seg);
+ EXPECT_EQ(xings.size(), 1u);
+ EXPECT_intersections_valid(*rev, seg, xings, 1e-12);
+
+ xings = x_squash_neg.intersect(seg);
+ EXPECT_EQ(xings.size(), 1u);
+ EXPECT_intersections_valid(x_squash_neg, seg, xings, 1e-12);
+
+ rev.reset(x_squash_neg.reverse());
+ xings = rev->intersect(seg);
+ EXPECT_EQ(xings.size(), 1u);
+ EXPECT_intersections_valid(*rev, seg, xings, 1e-12);
+ }
+
+ // Now test with an arc squashed to the Y-axis.
+ EllipticalArc y_squash_pos{{0.0, -2.0}, {3.0, 2.0}, 0, true, true, {0.0, 2.0}};
+ EllipticalArc y_squash_neg{{0.0, -2.0}, {3.0, 2.0}, 0, true, false, {0.0, 2.0}};
+ auto const squash_to_y = Scale(0.0, 1.0);
+ y_squash_pos *= squash_to_y; // Y-axis interval [-2, 2].
+ y_squash_neg *= squash_to_y;
+
+ for (size_t _ = 0; _ < 10'000; _++) {
+ auto seg = LineSegment(Point(g_random_double_range(-3.0, -1.0), g_random_double_range(-2.0, 2.0)),
+ Point(g_random_double_range(1.0, 3.0), g_random_double_range(-2.0, 2.0)));
+ auto xings = y_squash_pos.intersect(seg, 1e-10);
+ EXPECT_EQ(xings.size(), 1u);
+ EXPECT_intersections_valid(y_squash_pos, seg, xings, 1e-12);
+
+ std::unique_ptr<Curve> rev{y_squash_pos.reverse()};
+ xings = rev->intersect(seg, 1e-12);
+ EXPECT_EQ(xings.size(), 1u);
+ EXPECT_intersections_valid(*rev, seg, xings, 1e-12);
+
+ xings = y_squash_neg.intersect(seg, 1e-12);
+ EXPECT_EQ(xings.size(), 1u);
+ EXPECT_intersections_valid(y_squash_neg, seg, xings, 1e-12);
+
+ rev.reset(y_squash_neg.reverse());
+ xings = rev->intersect(seg, 1e-12);
+ EXPECT_EQ(xings.size(), 1u);
+ EXPECT_intersections_valid(*rev, seg, xings, 1e-12);
+ }
+
+ // Test whether the coincidence between the common endpoints of an
+ // arc and a segment is correctly detected as an intersection.
+ {
+ Point const from{1, 0};
+ Point const to{0.30901699437494745, 0.9510565162951535};
+ auto arc = EllipticalArc(from, {1, 1}, 0, false, true, to);
+ auto seg = LineSegment({0, 0}, to);
+ auto xings = arc.intersect(seg);
+ ASSERT_EQ(xings.size(), 1);
+ EXPECT_TRUE(are_near(xings[0].point(), to, 1e-12));
+ EXPECT_TRUE(are_near(xings[0].first, 1.0, 1e-24));
+ EXPECT_TRUE(are_near(xings[0].second, 1.0, 1e-24));
+
+ auto seg2 = LineSegment(Point{1, 1}, from);
+ xings = arc.intersect(seg2);
+ ASSERT_EQ(xings.size(), 1);
+ EXPECT_TRUE(are_near(xings[0].point(), from, 1e-12));
+ EXPECT_TRUE(are_near(xings[0].first, 0.0, 1e-24));
+ EXPECT_TRUE(are_near(xings[0].second, 1.0, 1e-24));
+ }
+}
+
+TEST(EllipticalArcTest, ArcIntersection) {
+ std::vector<CurveIntersection> r1, r2;
+
+ EllipticalArc a1(Point(0,0), Point(6,3), 0.1, false, false, Point(10,0));
+ EllipticalArc a2(Point(0,2), Point(6,3), -0.1, false, true, Point(10,2));
+ r1 = a1.intersect(a2);
+ EXPECT_EQ(r1.size(), 2u);
+ EXPECT_intersections_valid(a1, a2, r1, 1e-10);
+
+ EllipticalArc a3(Point(0,0), Point(5,1.5), 0, true, true, Point(0,2));
+ EllipticalArc a4(Point(3,5), Point(5,1.5), M_PI/2, true, true, Point(5,0));
+ r2 = a3.intersect(a4);
+ EXPECT_EQ(r2.size(), 3u);
+ EXPECT_intersections_valid(a3, a4, r2, 1e-10);
+
+ // Make sure intersections are found between two identical arcs on the unit circle.
+ EllipticalArc const upper(Point(1, 0), Point(1, 1), 0, true, true, Point(-1, 0));
+ auto self_intersect = upper.intersect(upper);
+ EXPECT_EQ(self_intersect.size(), 2u);
+
+ // Make sure intersections are found between overlapping arcs.
+ EllipticalArc const right(Point(0, -1), Point(1, 1), 0, true, true, Point(0, 1));
+ auto quartering_overlap_xings = right.intersect(upper);
+ EXPECT_EQ(quartering_overlap_xings.size(), 2u);
+
+ // Make sure intersecections are found between an arc and its sub-arc.
+ EllipticalArc const middle(upper.pointAtAngle(0.25 * M_PI), Point(1, 1), 0, true, true, upper.pointAtAngle(-0.25 * M_PI));
+ EXPECT_EQ(middle.intersect(upper).size(), 2u);
+
+ // Make sure intersections are NOT found between non-overlapping sub-arcs of the same circle.
+ EllipticalArc const arc1{Point(1, 0), Point(1, 1), 0, true, true, Point(0, 1)};
+ EllipticalArc const arc2{Point(-1, 0), Point(1, 1), 0, true, true, Point(0, -1)};
+ EXPECT_EQ(arc1.intersect(arc2).size(), 0u);
+
+ // Overlapping sub-arcs but on an Ellipse with different rays.
+ EllipticalArc const eccentric{Point(2, 0), Point(2, 1), 0, true, true, Point(-2, 0)};
+ EllipticalArc const subarc{eccentric.pointAtAngle(0.8), Point(2, 1), 0, true, true, eccentric.pointAtAngle(2)};
+ EXPECT_EQ(eccentric.intersect(subarc).size(), 2u);
+
+ // Check intersection times for two touching arcs.
+ EllipticalArc const lower{Point(-1, 0), Point(1, 1), 0, false, true, Point(0, -1)};
+ auto expected_neg_x = upper.intersect(lower);
+ ASSERT_EQ(expected_neg_x.size(), 1);
+ auto const &left_pt = expected_neg_x[0];
+ EXPECT_EQ(left_pt.point(), Point(-1, 0));
+ EXPECT_DOUBLE_EQ(left_pt.first, 1.0); // Expect (-1, 0) reached at the end of upper
+ EXPECT_DOUBLE_EQ(left_pt.second, 0.0); // Expect (-1, 0) passed at the start of lower
+}
+
+TEST(EllipticalArcTest, BezierIntersection) {
+ std::vector<CurveIntersection> r1, r2;
+
+ EllipticalArc a3(Point(0,0), Point(1.5,5), M_PI/2, true, true, Point(0,2));
+ CubicBezier bez1(Point(0,3), Point(7,3), Point(0,-1), Point(7,-1));
+ r1 = a3.intersect(bez1);
+ EXPECT_EQ(r1.size(), 2u);
+ EXPECT_intersections_valid(a3, bez1, r1, 1e-10);
+
+ EllipticalArc a4(Point(3,5), Point(5,1.5), 3*M_PI/2, true, true, Point(5,5));
+ CubicBezier bez2(Point(0,5), Point(10,-4), Point(10,5), Point(0,-4));
+ r2 = a4.intersect(bez2);
+ EXPECT_EQ(r2.size(), 4u);
+ EXPECT_intersections_valid(a4, bez2, r2, 1e-10);
+}
+
+TEST(EllipticalArcTest, ExpandToTransformedTest)
+{
+ auto test_curve = [] (EllipticalArc const &c) {
+ constexpr int N = 50;
+ for (int i = 0; i < N; i++) {
+ auto angle = 2 * M_PI * i / N;
+ auto transform = Affine(Rotate(angle)) * Scale(0.9, 1.2);
+
+ auto copy = std::unique_ptr<Curve>(c.duplicate());
+ *copy *= transform;
+ auto box1 = copy->boundsExact();
+
+ auto pt = c.initialPoint() * transform;
+ auto box2 = Rect(pt, pt);
+ c.expandToTransformed(box2, transform);
+
+ for (auto i : { X, Y }) {
+ EXPECT_NEAR(box1[i].min(), box2[i].min(), 2e-15);
+ EXPECT_NEAR(box1[i].max(), box2[i].max(), 2e-15);
+ }
+ }
+ };
+
+ test_curve(EllipticalArc(Point(0, 0), 1.0, 2.0, 0.0, false, false, Point(1, 1)));
+ test_curve(EllipticalArc(Point(0, 0), 3.0, 2.0, M_PI / 6, false, false, Point(1, 1)));
+ test_curve(EllipticalArc(Point(0, 0), 1.0, 2.0, M_PI / 5, true, true, Point(1, 1)));
+ test_curve(EllipticalArc(Point(1, 0), 1.0, 0.0, M_PI / 5, false, false, Point(1, 1)));
+ test_curve(EllipticalArc(Point(1, 0), 0.0, 0.0, 0.0, false, false, Point(2, 0)));
+ test_curve(EllipticalArc(Point(1, 0), 0.0, 0.0, 0.0, false, false, Point(1, 0)));
+}
diff --git a/src/3rdparty/2geom/tests/implicitization-test.cpp b/src/3rdparty/2geom/tests/implicitization-test.cpp
new file mode 100644
index 0000000..bfc4c58
--- /dev/null
+++ b/src/3rdparty/2geom/tests/implicitization-test.cpp
@@ -0,0 +1,130 @@
+/*
+ * Test program for implicitization routines
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+
+#include <2geom/symbolic/implicit.h>
+
+#include "pick.h"
+
+#include <iostream>
+
+
+
+
+void print_basis(Geom::SL::basis_type const& b)
+{
+ for (size_t i= 0; i < 2; ++i)
+ {
+ for (size_t j= 0; j < 3; ++j)
+ {
+ std::cout << "b[" << i << "][" << j << "] = " << b[i][j] << "\n";
+ }
+ }
+}
+
+
+
+
+int main( int argc, char * argv[] )
+{
+ // degree of polinomial parametrization
+ // warning: not set N to a value greater than 20!
+ // (10 in case you don't utilize the micro-basis)
+ // determinant computation becomes very expensive
+ unsigned int N = 4;
+ // max modulus of polynomial coefficients
+ unsigned int M = 1000;
+
+ if (argc > 1)
+ N = std::atoi(argv[1]);
+ if (argc > 2)
+ M = std::atoi(argv[2]);
+
+ Geom::SL::MVPoly1 f, g;
+ Geom::SL::basis_type b;
+ Geom::SL::MVPoly3 p, q;
+ Geom::SL::Matrix<Geom::SL::MVPoly2> B;
+ Geom::SL::MVPoly2 r;
+
+ // generate two univariate polynomial with degree N
+ // and coeffcient in the range [-M, M]
+ f = pick_multipoly_max<1>(N, M);
+ g = pick_multipoly_max<1>(N, M);
+
+ std::cout << "parametrization: \n";
+ std::cout << "f = " << f << std::endl;
+ std::cout << "g = " << g << "\n\n";
+
+ // computes the micro-basis
+ microbasis(b, f, g);
+ // in case you want utilize directly the initial basis
+ // you should uncomment the next row and comment
+ // the microbasis function call
+ //make_initial_basis(b, f, g);
+
+ std::cout << "generators in vector form : \n";
+ print_basis(b);
+ std::cout << std::endl;
+
+ // micro-basis generators
+ basis_to_poly(p, b[0]);
+ basis_to_poly(q, b[1]);
+
+ std::cout << "generators as polynomial in R[t,x,y] : \n";
+ std::cout << "p = " << p << std::endl;
+ std::cout << "q = " << q << "\n\n";
+
+ // make up the Bezout matrix and compute the determinant
+ B = make_bezout_matrix(p, q);
+ r = determinant_minor(B);
+ r.normalize();
+
+ std::cout << "Bezout matrix: (entries are bivariate polynomials) \n";
+ std::cout << "B = " << B << "\n\n";
+ std::cout << "determinant: \n";
+ std::cout << "r(x, y) = " << r << "\n\n";
+
+ return EXIT_SUCCESS;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/tests/intersection-graph-test.cpp b/src/3rdparty/2geom/tests/intersection-graph-test.cpp
new file mode 100644
index 0000000..19fb25c
--- /dev/null
+++ b/src/3rdparty/2geom/tests/intersection-graph-test.cpp
@@ -0,0 +1,266 @@
+/** @file
+ * @brief Unit tests for PathIntersectionGraph, aka Boolean operations.
+ * Uses the Google Testing Framework
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include "testing.h"
+#include <iostream>
+
+#include <2geom/intersection-graph.h>
+#include <2geom/pathvector.h>
+#include <2geom/svg-path-parser.h>
+#include <2geom/svg-path-writer.h>
+#include <glib.h>
+
+using namespace std;
+using namespace Geom;
+
+Path string_to_path(const char* s) {
+ PathVector pv = parse_svg_path(s);
+ assert(pv.size() == 1u);
+ return pv[0];
+}
+
+enum Operation {
+ UNION,
+ INTERSECTION,
+ XOR,
+ A_MINUS_B,
+ B_MINUS_A
+};
+
+class IntersectionGraphTest : public ::testing::Test {
+protected:
+ IntersectionGraphTest() {
+ rectangle = string_to_path("M 0,0 L 5,0 5,8 0,8 Z");
+ bigrect = string_to_path("M -3,-4 L 7,-4 7,12 -3,12 Z");
+ bigh = string_to_path("M 2,-3 L 3,-2 1,2 3,4 4,2 6,3 2,11 0,10 2,5 1,4 -1,6 -2,5 Z");
+ smallrect = string_to_path("M 7,4 L 9,4 9,7 7,7 Z");
+ g_random_set_seed(2345);
+ }
+
+ void checkRandomPoints(PathVector const &a, PathVector const &b, PathVector const &result,
+ Operation op, unsigned npts = 5000)
+ {
+ Rect bounds = *(a.boundsFast() | b.boundsFast());
+ for (unsigned i = 0; i < npts; ++i) {
+ Point p;
+ p[X] = g_random_double_range(bounds[X].min(), bounds[X].max());
+ p[Y] = g_random_double_range(bounds[Y].min(), bounds[Y].max());
+ bool in_a = a.winding(p) % 2;
+ bool in_b = b.winding(p) % 2;
+ bool in_res = result.winding(p) % 2;
+
+ switch (op) {
+ case UNION:
+ EXPECT_EQ(in_res, in_a || in_b);
+ break;
+ case INTERSECTION:
+ EXPECT_EQ(in_res, in_a && in_b);
+ break;
+ case XOR:
+ EXPECT_EQ(in_res, in_a ^ in_b);
+ break;
+ case A_MINUS_B:
+ EXPECT_EQ(in_res, in_a && !in_b);
+ break;
+ case B_MINUS_A:
+ EXPECT_EQ(in_res, !in_a && in_b);
+ break;
+ }
+ }
+ }
+
+ Path rectangle, bigrect, bigh, smallrect;
+};
+
+TEST_F(IntersectionGraphTest, Union) {
+ PathIntersectionGraph graph(rectangle, bigh);
+ //std::cout << graph << std::endl;
+ PathVector r = graph.getUnion();
+ EXPECT_EQ(r.size(), 1u);
+ EXPECT_EQ(r.curveCount(), 19u);
+
+ checkRandomPoints(rectangle, bigh, r, UNION);
+
+ /*SVGPathWriter wr;
+ wr.feed(r);
+ std::cout << wr.str() << std::endl;*/
+}
+
+TEST_F(IntersectionGraphTest, DisjointUnion) {
+ PathIntersectionGraph graph(rectangle, smallrect);
+
+ PathVector r = graph.getUnion();
+ EXPECT_EQ(r.size(), 2u);
+ checkRandomPoints(rectangle, smallrect, r, UNION);
+}
+
+TEST_F(IntersectionGraphTest, CoverUnion) {
+ PathIntersectionGraph graph(bigrect, bigh);
+ PathVector r = graph.getUnion();
+ EXPECT_EQ(r.size(), 1u);
+ EXPECT_EQ(r, bigrect);
+}
+
+TEST_F(IntersectionGraphTest, Subtraction) {
+ PathIntersectionGraph graph(rectangle, bigh);
+ PathVector a = graph.getAminusB();
+ EXPECT_EQ(a.size(), 4u);
+ EXPECT_EQ(a.curveCount(), 17u);
+ checkRandomPoints(rectangle, bigh, a, A_MINUS_B);
+
+ PathVector b = graph.getBminusA();
+ EXPECT_EQ(b.size(), 4u);
+ EXPECT_EQ(b.curveCount(), 15u);
+ checkRandomPoints(rectangle, bigh, b, B_MINUS_A);
+
+ PathVector x = graph.getXOR();
+ EXPECT_EQ(x.size(), 8u);
+ EXPECT_EQ(x.curveCount(), 32u);
+ checkRandomPoints(rectangle, bigh, x, XOR);
+}
+
+TEST_F(IntersectionGraphTest, PointOnEdge) {
+ PathVector a = string_to_path("M 0,0 L 10,0 10,10 0,10 z");
+ PathVector b = string_to_path("M -5,2 L 0,2 5,5 0,8 -5,8 z");
+
+ PathIntersectionGraph graph(a, b);
+ PathVector u = graph.getUnion();
+ //std::cout << u << std::endl;
+ EXPECT_EQ(u.size(), 1u);
+ EXPECT_EQ(u.curveCount(), 8u);
+ checkRandomPoints(a, b, u, UNION);
+
+ PathVector i = graph.getIntersection();
+ //std::cout << i << std::endl;
+ EXPECT_EQ(i.size(), 1u);
+ EXPECT_EQ(i.curveCount(), 3u);
+ checkRandomPoints(a, b, i, INTERSECTION);
+
+ PathVector s1 = graph.getAminusB();
+ //std::cout << s1 << std::endl;
+ EXPECT_EQ(s1.size(), 1u);
+ EXPECT_EQ(s1.curveCount(), 7u);
+ checkRandomPoints(a, b, s1, A_MINUS_B);
+
+ PathVector s2 = graph.getBminusA();
+ //std::cout << s2 << std::endl;
+ EXPECT_EQ(s2.size(), 1u);
+ EXPECT_EQ(s2.curveCount(), 4u);
+ checkRandomPoints(a, b, s2, B_MINUS_A);
+
+ PathVector x = graph.getXOR();
+ //std::cout << x << std::endl;
+ EXPECT_EQ(x.size(), 2u);
+ EXPECT_EQ(x.curveCount(), 11u);
+ checkRandomPoints(a, b, x, XOR);
+}
+
+TEST_F(IntersectionGraphTest, RhombusInSquare) {
+ PathVector square = string_to_path("M 0,0 L 10,0 10,10 0,10 z");
+ PathVector rhombus = string_to_path("M 5,0 L 10,5 5,10 0,5 z");
+
+ PathIntersectionGraph graph(square, rhombus);
+ //std::cout << graph << std::endl;
+ PathVector u = graph.getUnion();
+ EXPECT_EQ(u.size(), 1u);
+ EXPECT_EQ(u.curveCount(), 4u);
+ checkRandomPoints(square, rhombus, u, UNION);
+
+ PathVector i = graph.getIntersection();
+ EXPECT_EQ(i.size(), 1u);
+ EXPECT_EQ(i.curveCount(), 4u);
+ checkRandomPoints(square, rhombus, i, INTERSECTION);
+
+ PathVector s1 = graph.getAminusB();
+ EXPECT_EQ(s1.size(), 2u);
+ EXPECT_EQ(s1.curveCount(), 8u);
+ checkRandomPoints(square, rhombus, s1, A_MINUS_B);
+
+ PathVector s2 = graph.getBminusA();
+ EXPECT_EQ(s2.size(), 0u);
+ EXPECT_EQ(s2.curveCount(), 0u);
+ checkRandomPoints(square, rhombus, s2, B_MINUS_A);
+}
+
+TEST_F(IntersectionGraphTest, EmptyOperand) {
+ PathVector square = string_to_path("M 0,0 L 20, 0 L 20, 20 L 0, 20 Z");
+ PathVector empty;
+
+ auto graph = PathIntersectionGraph(square, empty);
+ // Taking union with the empty set should be a no-op: A ∪ ∅ = A
+ PathVector u = graph.getUnion();
+ EXPECT_EQ(u.size(), 1u);
+ EXPECT_EQ(u.curveCount(), 4u);
+
+ // Intersection with empty should produce empty: A ∩ ∅ = ∅
+ PathVector i = graph.getIntersection();
+ EXPECT_EQ(i.size(), 0u);
+
+ // Subtracting empty set should be a no-op: A ∖ ∅ = A
+ PathVector rd = graph.getAminusB();
+ EXPECT_EQ(rd.size(), 1u);
+ EXPECT_EQ(rd.curveCount(), 4u);
+
+ // Subtracting FROM the empty set should produce the empty set: ∅ ∖ A = ∅
+ PathVector ld = graph.getBminusA();
+ EXPECT_EQ(ld.size(), 0u);
+}
+
+// this test is disabled, since we cannot handle overlapping segments for now.
+#if 0
+TEST_F(IntersectionGraphTest, EqualUnionAndIntersection) {
+ PathVector shape = string_to_path("M 0,0 L 2,1 -1,2 -1,3 0,3 z");
+ PathIntersectionGraph graph(shape, shape);
+ std::cout << graph << std::endl;
+ PathVector a = graph.getUnion();
+ std::cout << shape << std::endl;
+ std::cout << a << std::endl;
+ checkRandomPoints(shape, shape, a, UNION);
+
+ PathIntersectionGraph graph2(bigh, bigh);
+ PathVector b = graph2.getIntersection();
+ checkRandomPoints(bigh, bigh, b, INTERSECTION);
+ std::cout << b <<std::endl;
+}
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/tests/interval-test.cpp b/src/3rdparty/2geom/tests/interval-test.cpp
new file mode 100644
index 0000000..eccea70
--- /dev/null
+++ b/src/3rdparty/2geom/tests/interval-test.cpp
@@ -0,0 +1,54 @@
+/** @file
+ * @brief Unit tests for Interval, OptInterval, IntInterval, OptIntInterval.
+ *//*
+ * Authors:
+ * Thomas Holder
+ *
+ * Copyright 2021 Authors
+ *
+ * SPDX-License-Identifier: LGPL-2.1 OR MPL-1.1
+ */
+
+#include <2geom/interval.h>
+#include <gtest/gtest.h>
+
+TEST(IntervalTest, EqualityTest)
+{
+ Geom::Interval a(3, 5), a2(a), b(4, 7);
+ Geom::OptInterval empty, oa = a;
+
+ EXPECT_TRUE(a == a);
+ EXPECT_FALSE(a != a);
+ EXPECT_TRUE(a == a2);
+ EXPECT_FALSE(a != a2);
+ EXPECT_TRUE(empty == empty);
+ EXPECT_FALSE(empty != empty);
+ EXPECT_FALSE(a == empty);
+ EXPECT_TRUE(a != empty);
+ EXPECT_FALSE(empty == a);
+ EXPECT_TRUE(empty != a);
+ EXPECT_FALSE(a == b);
+ EXPECT_TRUE(a != b);
+ EXPECT_TRUE(a == oa);
+ EXPECT_FALSE(a != oa);
+
+ Geom::IntInterval ia(3, 5), ia2(ia), ib(4, 7);
+ Geom::OptIntInterval iempty, ioa = ia;
+
+ EXPECT_TRUE(ia == ia);
+ EXPECT_FALSE(ia != ia);
+ EXPECT_TRUE(ia == ia2);
+ EXPECT_FALSE(ia != ia2);
+ EXPECT_TRUE(iempty == iempty);
+ EXPECT_FALSE(iempty != iempty);
+ EXPECT_FALSE(ia == iempty);
+ EXPECT_TRUE(ia != iempty);
+ EXPECT_FALSE(iempty == ia);
+ EXPECT_TRUE(iempty != ia);
+ EXPECT_FALSE(ia == ib);
+ EXPECT_TRUE(ia != ib);
+ EXPECT_TRUE(ia == ioa);
+ EXPECT_FALSE(ia != ioa);
+}
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/tests/linalg-test.cpp b/src/3rdparty/2geom/tests/linalg-test.cpp
new file mode 100644
index 0000000..b7e2f42
--- /dev/null
+++ b/src/3rdparty/2geom/tests/linalg-test.cpp
@@ -0,0 +1,502 @@
+
+
+#include "numeric/vector.h"
+#include "numeric/matrix.h"
+
+#include <iostream>
+
+using namespace Geom;
+
+
+template< class charT >
+inline
+std::basic_ostream<charT> &
+operator<< (std::basic_ostream<charT> & os, const std::pair<size_t, size_t>& index_pair)
+{
+ os << "{" << index_pair.first << "," << index_pair.second << "}";
+ return os;
+}
+
+template< typename T, typename U>
+void check_test( const char* description, T output, U expected )
+{
+ bool result = ( output == expected );
+ std::cout << "# " << description << " : ";
+ if ( result )
+ std::cout << "success!" << std::endl;
+ else
+ std::cout << "fail!" << std::endl
+ << " output: " << output << std::endl
+ << " expected: " << expected << std::endl;
+}
+
+
+void vector_test()
+{
+ // Deprecated. Replaced by ** Vector examples **
+ // in nl-vector-test.cpp
+ /*
+ NL::Vector v1(10), v2(10), v3(5);
+ for (unsigned int i = 0; i < v1.size(); ++i)
+ {
+ v1[i] = i;
+ }
+ std::cout << "v1: " << v1 << std::endl;
+ v2 = v1;
+ std::cout << "v2 = v1 : " << v2 << std::endl;
+ bool value = (v1 == v2);
+ std::cout << "(v1 == v2) : " << value << std::endl;
+ v2.scale(10);
+ std::cout << "v2.scale(10) : " << v2 << std::endl;
+ value = (v1 == v2);
+ std::cout << "(v1 == v2) : " << value << std::endl;
+ v2.translate(20);
+ std::cout << "v2.translate(20) : " << v2 << std::endl;
+ v2 += v1;
+ std::cout << "v2 += v1 : " << v2 << std::endl;
+ v2.swap_elements(3, 9);
+ std::cout << "v2.swap_elements(3, 9) : " << v2 << std::endl;
+ v2.reverse();
+ std::cout << "v2.reverse() : " << v2 << std::endl;
+ value = v2.is_positive();
+ std::cout << "v2.is_positive() : " << value << std::endl;
+ v2 -= v1;
+ std::cout << "v2 -= v1 : " << v2 << std::endl;
+ double bound = v2.max();
+ std::cout << "v2.max() : " << bound << std::endl;
+ bound = v2.min();
+ std::cout << "v2.min() : " << bound << std::endl;
+ unsigned int index = v2.max_index();
+ std::cout << "v2.max_index() : " << index << std::endl;
+ index = v2.min_index();
+ std::cout << "v2.min_index() : " << index << std::endl;
+ v2.set_basis(4);
+ std::cout << "v2.set_basis(4) : " << v2 << std::endl;
+ value = v2.is_non_negative();
+ std::cout << "v2.is_non_negative() : " << value << std::endl;
+ v2.set_all(0);
+ std::cout << "v2.set_all(0) : " << v2 << std::endl;
+ value = v2.is_zero();
+ std::cout << "v2.is_zero() : " << value << std::endl;
+ NL::swap(v1, v2);
+ std::cout << "swap(v1, v2) : v1: " << v1 << " v2: " << v2 << std::endl;
+ */
+}
+
+
+void const_vector_view_test()
+{
+ NL::Vector v1(10);
+ for (unsigned int i = 0; i < v1.size(); ++i)
+ v1[i] = i;
+ NL::VectorView vv1(v1, 5, 1, 2);
+ vv1.scale(10);
+ std::cout << "v1 = " << v1 << std::endl;
+
+ NL::ConstVectorView cvv1(v1, 6, 1);
+ check_test( "cvv1(v1, 6, 1)", cvv1.str(), "[10, 2, 30, 4, 50, 6]");
+ NL::ConstVectorView cvv2(v1, 3, 1, 3);
+ check_test( "cvv2(v1, 3, 1, 3)", cvv2.str(), "[10, 4, 70]");
+ NL::ConstVectorView cvv3(vv1, 3, 0, 2);
+ std::cout << "vv1 = " << vv1 << std::endl;
+ check_test( "cvv3(vv1, 3, 0, 2)", cvv3.str(), "[10, 50, 90]");
+ NL::ConstVectorView cvv4(cvv1, 3, 1, 2);
+ check_test( "cvv4(cvv1, 3, 1, 2)", cvv4.str(), "[2, 4, 6]");
+ bool value = (cvv2 == cvv4);
+ check_test( "(cvv2 == cvv4)", value, false);
+
+ value = cvv2.is_zero();
+ check_test( "cvv2.is_zero()", value, false);
+ value = cvv2.is_negative();
+ check_test( "cvv2.is_negative()", value, false);
+ value = cvv2.is_positive();
+ check_test( "cvv2.is_positive()", value, true);
+ value = cvv2.is_non_negative();
+ check_test( "cvv2.is_non_negative()", value, true);
+
+ NL::VectorView vv2(v1, 3, 1, 3);
+ vv2.scale(-1);
+ value = cvv2.is_zero();
+ std::cout << "v1 = " << v1 << std::endl;
+ check_test( "cvv2.is_zero()", value, false);
+ value = cvv2.is_negative();
+ check_test( "cvv2.is_negative()", value, true);
+ value = cvv2.is_positive();
+ check_test( "cvv2.is_positive()", value, false);
+ value = cvv2.is_non_negative();
+ check_test( "cvv2.is_non_negative()", value, false);
+
+ vv2.set_all(0);
+ std::cout << "v1 = " << v1 << std::endl;
+ value = cvv2.is_zero();
+ check_test( "cvv2.is_zero()", value, true);
+ value = cvv2.is_negative();
+ check_test( "cvv2.is_negative()", value, false);
+ value = cvv2.is_positive();
+ check_test( "cvv2.is_positive()", value, false);
+ value = cvv2.is_non_negative();
+ check_test( "cvv2.is_non_negative()", value, true);
+
+ vv1.reverse();
+ vv2[0] = -1;
+ std::cout << "v1 = " << v1 << std::endl;
+ value = cvv2.is_zero();
+ check_test( "cvv2.is_zero()", value, false);
+ value = cvv2.is_negative();
+ check_test( "cvv2.is_negative()", value, false);
+ value = cvv2.is_positive();
+ check_test( "cvv2.is_positive()", value, false);
+ value = cvv2.is_non_negative();
+ check_test( "cvv2.is_non_negative()", value, false);
+
+ vv2 = cvv2;
+ value = (vv2 == cvv2);
+ std::cout << "vv2 = " << vv2 << std::endl;
+ check_test( "(vv2 == cvv2)", value, true);
+ NL::Vector v2(cvv2.size());
+ v2 = cvv4;
+ value = (v2 == cvv2);
+ std::cout << "v2 = " << v2 << std::endl;
+ check_test( "(v2 == cvv2)", value, false);
+ const NL::Vector v3(cvv2.size());
+ NL::ConstVectorView cvv5(v3, v3.size());
+ check_test( "cvv5(v3, v3.size())", cvv4.str(), "[2, 0, 6]");
+
+}
+
+void vector_view_test()
+{
+ // Deprecated. Replaced by ** VectorView examples **
+ // in nl-vector-test.cpp
+ /*
+ NL::Vector v1(10);
+ for (unsigned int i = 0; i < v1.size(); ++i)
+ v1[i] = i;
+ NL::VectorView vv1(v1, 5), vv2(v1, 5, 3), vv3(v1, 5, 0, 2), vv4(v1, 5, 1, 2);
+ std::cout << "v1 = " << v1 << std::endl;
+ check_test( "vv1(v1, 5)", vv1.str(), "[0, 1, 2, 3, 4]");
+ check_test( "vv2(v1, 5, 3)", vv2.str(), "[3, 4, 5, 6, 7]");
+ check_test( "vv3(v1, 5, 0, 2)", vv3.str(), "[0, 2, 4, 6, 8]");
+ check_test( "vv4(v1, 5, 1, 2)", vv4.str(), "[1, 3, 5, 7, 9]");
+
+ NL::VectorView vv5(vv4, 3, 0, 2);
+ std::cout << "vv4 = " << vv4 << std::endl;
+ check_test( "vv5(vv4, 3, 0, 2)", vv5.str(), "[1, 5, 9]");
+ vv5.scale(10);
+ check_test( "vv5.scale(10) : vv5", vv5.str(), "[10, 50, 90]");
+ check_test( " : v1", v1.str(), "[0, 10, 2, 3, 4, 50, 6, 7, 8, 90]");
+ vv5.translate(20);
+ check_test( "vv5.translate(20) : vv5", vv5.str(), "[30, 70, 110]");
+ check_test( " : v1", v1.str(), "[0, 30, 2, 3, 4, 70, 6, 7, 8, 110]");
+ vv1 += vv2;
+ check_test("vv1 += vv2", vv1.str(), "[3, 34, 72, 9, 11]");
+ vv1 -= vv2;
+ check_test("vv1 -= vv2", vv1.str(), "[-6, 23, 2, 3, 4]");
+ NL::ConstVectorView cvv1(vv3, 3);
+ vv5 = cvv1;
+ check_test("vv5 = cvv1", vv5.str(), "[-6, 2, 4]");
+ vv5 += cvv1;
+ check_test("vv5 += cvv1", vv5.str(), "[-12, 4, 8]");
+ vv5 -= cvv1;
+ check_test("vv5 -= cvv1", vv5.str(), "[-6, 2, 4]");
+ NL::Vector v2(vv1);
+ std::cout << "v2 = " << v2 << std::endl;
+ vv1 = v2;
+ check_test( "vv1 = v2", vv1.str(), "[-6, -6, 2, 3, 4]");
+ vv1 += v2;
+ check_test( "vv1 += v2", vv1.str(), "[-12, -12, 4, 6, 8]");
+ vv1 -= v2;
+ check_test( "vv1 -= v2", vv1.str(), "[-6, -6, 2, 3, 4]");
+ NL::swap_view(vv1, vv4);
+ check_test( "swap_view(vv1, vv4)", v1.str(), "[-6, -6, 2, 3, 4, 2, 6, 7, 8, 4]");
+ */
+}
+
+
+void const_matrix_view_test()
+{
+ NL::Matrix m0(8,4);
+ for (size_t i = 0; i < m0.rows(); ++i)
+ {
+ for (size_t j = 0; j < m0.columns(); ++j)
+ {
+ m0(i,j) = 10 * i + j;
+ }
+ }
+ std::cout << "m0 = " << m0 << std::endl;
+
+ // constructor test
+ NL::Matrix m1(m0);
+ NL::ConstMatrixView cmv1(m1, 2, 1, 4, 2);
+ check_test("cmv1(m1, 2, 1, 4, 2)", cmv1.str(), "[[21, 22], [31, 32], [41, 42], [51, 52]]");
+ NL::MatrixView mv1(m1, 2, 0, 4, 4);
+ NL::ConstMatrixView cmv2(mv1, 2, 1, 2, 2);
+ check_test("cmv2(mv1, 2, 1, 2, 2)", cmv2.str(), "[[41, 42], [51, 52]]");
+ NL::ConstMatrixView cmv3(cmv1, 1, 1, 3, 1);
+ check_test("cmv3(cmv1, 1, 1, 2, 1)", cmv3.str(), "[[32], [42], [52]]");
+ const NL::Matrix & m2 = m1;
+ NL::ConstMatrixView cmv4(m2, 2, 1, 4, 2);
+ check_test("cmv4(m2, 2, 1, 4, 2)", cmv4.str(), "[[21, 22], [31, 32], [41, 42], [51, 52]]");
+ const NL::MatrixView & mv2 = mv1;
+ NL::ConstMatrixView cmv5(mv2, 2, 1, 2, 2);
+ check_test("cmv5(mv2, 2, 1, 2, 2)", cmv5.str(), "[[41, 42], [51, 52]]");
+
+ // row and column view test
+ NL::ConstVectorView cvv1 = cmv1.row_const_view(2);
+ check_test("cvv1 = cmv1.row_const_view(2)", cvv1.str(), "[41, 42]");
+ NL::ConstVectorView cvv2 = cmv1.column_const_view(0);
+ check_test("cvv2 = cmv1.column_const_view(0)", cvv2.str(), "[21, 31, 41, 51]");
+
+ // property test
+ bool value = cmv1.is_negative();
+ check_test("cmv1.is_negative()", value, false);
+ value = cmv1.is_non_negative();
+ check_test("cmv1.is_non_negative()", value, true);
+ value = cmv1.is_positive();
+ check_test("cmv1.is_positive()", value, true);
+ value = cmv1.is_zero();
+ check_test("cmv1.is_zero()", value, false);
+
+ m1.scale(-1);
+ value = cmv1.is_negative();
+ check_test("cmv1.is_negative()", value, true);
+ value = cmv1.is_non_negative();
+ check_test("cmv1.is_non_negative()", value, false);
+ value = cmv1.is_positive();
+ check_test("cmv1.is_positive()", value, false);
+ value = cmv1.is_zero();
+ check_test("cmv1.is_zero()", value, false);
+
+ m1.translate(35);
+ value = cmv1.is_negative();
+ check_test("cmv1.is_negative()", value, false);
+ value = cmv1.is_non_negative();
+ check_test("cmv1.is_non_negative()", value, false);
+ value = cmv1.is_positive();
+ check_test("cmv1.is_positive()", value, false);
+ value = cmv1.is_zero();
+ check_test("cmv1.is_zero()", value, false);
+
+ m1.set_all(0);
+ value = cmv1.is_negative();
+ check_test("cmv1.is_negative()", value, false);
+ value = cmv1.is_non_negative();
+ check_test("cmv1.is_non_negative()", value, true);
+ value = cmv1.is_positive();
+ check_test("cmv1.is_positive()", value, false);
+ value = cmv1.is_zero();
+ check_test("cmv1.is_zero()", value, true);
+
+ m1.set_identity();
+ value = cmv1.is_negative();
+ check_test("cmv1.is_negative()", value, false);
+ value = cmv1.is_non_negative();
+ check_test("cmv1.is_non_negative()", value, true);
+ value = cmv1.is_positive();
+ check_test("cmv1.is_positive()", value, false);
+ value = cmv1.is_zero();
+ check_test("cmv1.is_zero()", value, false);
+
+ // max, min test
+ m1 = m0;
+ std::cout << "cmv1 = " << cmv1 << std::endl;
+ std::pair<size_t, size_t> out_elem = cmv1.max_index();
+ std::pair<size_t, size_t> exp_elem(3,1);
+ check_test("cmv1.max_index()", out_elem, exp_elem);
+ double bound = cmv1.max();
+ check_test("cmv1.max()", bound, cmv1(exp_elem.first, exp_elem.second));
+ out_elem = cmv1.min_index();
+ exp_elem.first = 0; exp_elem.second = 0;
+ check_test("cmv1.min_index()", out_elem, exp_elem);
+ bound = cmv1.min();
+ check_test("cmv1.min()", bound, cmv1(exp_elem.first, exp_elem.second));
+
+}
+
+
+void matrix_view_test()
+{
+ NL::Matrix m0(8,4);
+ for (size_t i = 0; i < m0.rows(); ++i)
+ {
+ for (size_t j = 0; j < m0.columns(); ++j)
+ {
+ m0(i,j) = 10 * i + j;
+ }
+ }
+ std::cout << "m0 = " << m0 << std::endl;
+
+ // constructor test
+ NL::Matrix m1(m0);
+ NL::MatrixView mv1(m1, 2, 1, 4, 2);
+ check_test("mv1(m1, 2, 1, 4, 2)", mv1.str(), "[[21, 22], [31, 32], [41, 42], [51, 52]]");
+ NL::MatrixView mv2(mv1, 2, 1, 2, 1);
+ check_test("mv2(mv1, 2, 1, 2, 1)", mv2.str(), "[[42], [52]]");
+
+ // operator = test
+ NL::Matrix m2(4,2);
+ m2.set_all(0);
+ mv1 = m2;
+ check_test("mv1 = m2", m1.str(), "[[0, 1, 2, 3], [10, 11, 12, 13], [20, 0, 0, 23], [30, 0, 0, 33], [40, 0, 0, 43], [50, 0, 0, 53], [60, 61, 62, 63], [70, 71, 72, 73]]");
+ m1 = m0;
+ NL::MatrixView mv3(m2, 0, 0, 4, 2);
+ mv1 = mv3;
+ check_test("mv1 = mv3", m1.str(), "[[0, 1, 2, 3], [10, 11, 12, 13], [20, 0, 0, 23], [30, 0, 0, 33], [40, 0, 0, 43], [50, 0, 0, 53], [60, 61, 62, 63], [70, 71, 72, 73]]");
+ m1 = m0;
+ NL::ConstMatrixView cmv1(m2, 0, 0, 4, 2);
+ mv1 = cmv1;
+ check_test("mv1 = cmv1", m1.str(), "[[0, 1, 2, 3], [10, 11, 12, 13], [20, 0, 0, 23], [30, 0, 0, 33], [40, 0, 0, 43], [50, 0, 0, 53], [60, 61, 62, 63], [70, 71, 72, 73]]");
+
+ // operator == test
+ m2.set_identity();
+ mv1 = m2;
+ bool value = (mv1 == m2);
+ check_test("(mv1 == m2)", value, true);
+ value = (mv1 == mv3);
+ check_test("(mv1 == mv3)", value, true);
+ value = (mv1 == cmv1);
+ check_test("(mv1 == cmv1)", value, true);
+
+ // row and column view test
+ m1 = m0;
+ NL::ConstVectorView cvv1 = mv1.row_const_view(2);
+ check_test("cvv1 = mv1.row_const_view(2)", cvv1.str(), "[41, 42]");
+ NL::ConstVectorView cvv2 = mv1.column_const_view(0);
+ check_test("cvv2 = mv1.column_const_view(0)", cvv2.str(), "[21, 31, 41, 51]");
+ NL::VectorView vv1 = mv1.row_view(2);
+ check_test("vv1 = mv1.row_view(2)", vv1.str(), "[41, 42]");
+ NL::VectorView vv2 = mv1.column_view(0);
+ check_test("vv2 = mv1.column_view(0)", vv2.str(), "[21, 31, 41, 51]");
+
+ // swap_view test
+ m1 = m0;
+ swap_view(mv1, mv3);
+ check_test("swap_view(mv1, mv3) : mv1", mv1.str(), "[[1, 0], [0, 1], [0, 0], [0, 0]]");
+ check_test(" : m1", m1.str(), m0.str());
+ check_test(" : mv3", mv3.str(), "[[21, 22], [31, 32], [41, 42], [51, 52]]");
+ check_test(" : m2", m2.str(), "[[1, 0], [0, 1], [0, 0], [0, 0]]");
+ swap_view(mv1, mv3);
+
+ // modifying operations test
+ m1 = m0;
+ m2.set_all(10);
+ mv1 += m2;
+ check_test("mv1 += m2", m1.str(), "[[0, 1, 2, 3], [10, 11, 12, 13], [20, 31, 32, 23], [30, 41, 42, 33], [40, 51, 52, 43], [50, 61, 62, 53], [60, 61, 62, 63], [70, 71, 72, 73]]");
+ mv1 -= m2;
+ check_test("mv1 -= m2", m1.str(), m0.str());
+ mv1 += mv3;
+ check_test("mv1 += mv3", m1.str(), "[[0, 1, 2, 3], [10, 11, 12, 13], [20, 31, 32, 23], [30, 41, 42, 33], [40, 51, 52, 43], [50, 61, 62, 53], [60, 61, 62, 63], [70, 71, 72, 73]]");
+ mv1 -= mv3;
+ check_test("mv1 -= mv3", m1.str(), m0.str());
+ mv1 += cmv1;
+ check_test("mv1 += cmv1", m1.str(), "[[0, 1, 2, 3], [10, 11, 12, 13], [20, 31, 32, 23], [30, 41, 42, 33], [40, 51, 52, 43], [50, 61, 62, 53], [60, 61, 62, 63], [70, 71, 72, 73]]");
+ mv1 -= cmv1;
+ check_test("mv1 -= cmv1", m1.str(), m0.str());
+
+ m1 = m0;
+ mv1.swap_rows(0,3);
+ check_test("mv1.swap_rows(0,3)", m1.str(), "[[0, 1, 2, 3], [10, 11, 12, 13], [20, 51, 52, 23], [30, 31, 32, 33], [40, 41, 42, 43], [50, 21, 22, 53], [60, 61, 62, 63], [70, 71, 72, 73]]");
+ m1 = m0;
+ mv1.swap_columns(0,1);
+ check_test("mv1.swap_columns(0,3)", m1.str(), "[[0, 1, 2, 3], [10, 11, 12, 13], [20, 22, 21, 23], [30, 32, 31, 33], [40, 42, 41, 43], [50, 52, 51, 53], [60, 61, 62, 63], [70, 71, 72, 73]]");
+
+ m1 = m0;
+ NL::MatrixView mv4(m1, 0, 0, 4, 4);
+ mv4.transpose();
+ check_test("mv4.transpose()", m1.str(), "[[0, 10, 20, 30], [1, 11, 21, 31], [2, 12, 22, 32], [3, 13, 23, 33], [40, 41, 42, 43], [50, 51, 52, 53], [60, 61, 62, 63], [70, 71, 72, 73]]");
+
+}
+
+void matrix_test()
+{
+ NL::Matrix m0(8,4);
+ for (size_t i = 0; i < m0.rows(); ++i)
+ {
+ for (size_t j = 0; j < m0.columns(); ++j)
+ {
+ m0(i,j) = 10 * i + j;
+ }
+ }
+ std::cout << "m0 = " << m0 << std::endl;
+
+ // constructor test
+ NL::Matrix m1(m0);
+ check_test("m1(m0)", m1.str(), m0.str());
+ NL::MatrixView mv1(m0, 2, 1, 4, 2);
+ NL::Matrix m2(mv1);
+ check_test("m2(mv1)", m2.str(), mv1.str());
+ NL::MatrixView cmv1(m0, 2, 1, 4, 2);
+ NL::Matrix m3(cmv1);
+ check_test("m3(cmv1)", m3.str(), cmv1.str());
+
+ // operator = and operator == test
+ m1.set_all(0);
+ m1 = m0;
+ check_test("m1 = m0", m1.str(), m0.str());
+ bool value = (m1 == m0);
+ check_test("m1 == m0", value, true);
+ m2.set_all(0);
+ m2 = mv1;
+ check_test("m2 = mv1", m2.str(), mv1.str());
+ value = (m2 == mv1);
+ check_test("m2 == mv1", value, true);
+ m2.set_all(0);
+ m2 = cmv1;
+ check_test("m2 = cmv1", m2.str(), cmv1.str());
+ value = (m2 == cmv1);
+ check_test("m2 == cmv1", value, true);
+
+ // row and column view test
+ NL::ConstVectorView cvv1 = m2.row_const_view(2);
+ check_test("cvv1 = m2.row_const_view(2)", cvv1.str(), "[41, 42]");
+ NL::ConstVectorView cvv2 = m2.column_const_view(0);
+ check_test("cvv2 = m2.column_const_view(0)", cvv2.str(), "[21, 31, 41, 51]");
+ NL::VectorView vv1 = m2.row_view(2);
+ check_test("vv1 = m2.row_view(2)", vv1.str(), "[41, 42]");
+ NL::VectorView vv2 = m2.column_view(0);
+ check_test("vv2 = m2.column_view(0)", vv2.str(), "[21, 31, 41, 51]");
+
+
+ // modifying operations test
+ NL::Matrix m4(8,4);
+ m4.set_all(0);
+ m1.set_all(0);
+ m1 += m0;
+ check_test("m1 += m0", m1.str(), m0.str());
+ m1 -= m0;
+ check_test("m1 -= m0", m1.str(), m4.str());
+ NL::Matrix m5(4,2);
+ m5.set_all(0);
+ m2.set_all(0);
+ m2 += mv1;
+ check_test("m2 += mv1", m2.str(), mv1.str());
+ m2 -= mv1;
+ check_test("m2 -= mv1", m2.str(), m5.str());
+ m2.set_all(0);
+ m2 += cmv1;
+ check_test("m2 += cmv1", m2.str(), cmv1.str());
+ m2 -= cmv1;
+ check_test("m2 -= cmv1", m2.str(), m5.str());
+
+ // swap test
+ m3.set_identity();
+ m5.set_identity();
+ m1 = m0;
+ m2 = mv1;
+ swap(m2, m3);
+ check_test("swap(m2, m3) : m2", m2.str(), m5.str());
+ check_test(" : m3", m3.str(), mv1.str());
+
+}
+
+int main(int argc, char **argv)
+{
+ //const_vector_view_test();
+ //vector_view_test();
+ const_matrix_view_test();
+ //matrix_view_test();
+ //matrix_test();
+ return 0;
+}
+
+
diff --git a/src/3rdparty/2geom/tests/line-test.cpp b/src/3rdparty/2geom/tests/line-test.cpp
new file mode 100644
index 0000000..0625566
--- /dev/null
+++ b/src/3rdparty/2geom/tests/line-test.cpp
@@ -0,0 +1,185 @@
+/** @file
+ * @brief Unit tests for Line and related functions
+ * Uses the Google Testing Framework
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include "testing.h"
+#include <iostream>
+#include <glib.h>
+
+#include <2geom/line.h>
+#include <2geom/affine.h>
+
+using namespace Geom;
+
+TEST(LineTest, VectorAndVersor) {
+ Line a(Point(10, 10), Point(-10, 20));
+ Line b(Point(10, 10), Point(15, 15));
+ EXPECT_EQ(a.vector(), Point(-20, 10));
+ EXPECT_EQ(b.vector(), Point(5, 5));
+ EXPECT_EQ(a.versor(), a.vector().normalized());
+ EXPECT_EQ(b.versor(), b.vector().normalized());
+}
+
+TEST(LineTest, AngleBisector) {
+ Point o(0,0), a(1,1), b(3,0), c(-4, 0);
+ Point d(0.5231, 0.75223);
+
+ // normal
+ Line ab1 = make_angle_bisector_line(a + d, o + d, b + d);
+ Line ab2 = make_angle_bisector_line(a - d, o - d, b - d);
+ EXPECT_FLOAT_EQ(ab1.angle(), Angle::from_degrees(22.5));
+ EXPECT_FLOAT_EQ(ab2.angle(), Angle::from_degrees(22.5));
+
+ // half angle
+ Line bc1 = make_angle_bisector_line(b + d, o + d, c + d);
+ Line bc2 = make_angle_bisector_line(b - d, o - d, c - d);
+ EXPECT_FLOAT_EQ(bc1.angle(), Angle::from_degrees(90));
+ EXPECT_FLOAT_EQ(bc2.angle(), Angle::from_degrees(90));
+
+ // zero angle
+ Line aa1 = make_angle_bisector_line(a + d, o + d, a + d);
+ Line aa2 = make_angle_bisector_line(a - d, o - d, a - d);
+ EXPECT_FLOAT_EQ(aa1.angle(), Angle::from_degrees(45));
+ EXPECT_FLOAT_EQ(aa2.angle(), Angle::from_degrees(45));
+}
+
+TEST(LineTest, Equality) {
+ Line a(Point(0,0), Point(2,2));
+ Line b(Point(2,2), Point(5,5));
+
+ EXPECT_EQ(a, a);
+ EXPECT_EQ(b, b);
+ EXPECT_EQ(a, b);
+}
+
+TEST(LineTest, Reflection) {
+ Line a(Point(10, 0), Point(15,5));
+ Point pa(10,5), ra(15,0);
+
+ Line b(Point(1,-2), Point(2,0));
+ Point pb(5,1), rb(1,3);
+ Affine reflecta = a.reflection(), reflectb = b.reflection();
+
+ Point testra = pa * reflecta;
+ Point testrb = pb * reflectb;
+
+ constexpr Coord eps{1e-12};
+ EXPECT_near(testra[X], ra[X], eps);
+ EXPECT_near(testra[Y], ra[Y], eps);
+ EXPECT_near(testrb[X], rb[X], eps);
+ EXPECT_near(testrb[Y], rb[Y], eps);
+}
+
+TEST(LineTest, RotationToZero) {
+ Line a(Point(-5,23), Point(15,27));
+ Affine mx = a.rotationToZero(X);
+ Affine my = a.rotationToZero(Y);
+
+ for (unsigned i = 0; i <= 12; ++i) {
+ double t = -1 + 0.25 * i;
+ Point p = a.pointAt(t);
+ Point rx = p * mx;
+ Point ry = p * my;
+ //std::cout << rx[X] << " " << ry[Y] << std::endl;
+ // unfortunately this is precise only to about 1e-14
+ EXPECT_NEAR(rx[X], 0, 1e-14);
+ EXPECT_NEAR(ry[Y], 0, 1e-14);
+ }
+}
+
+TEST(LineTest, Coefficients) {
+ std::vector<Line> lines;
+ lines.emplace_back(Point(1e3,1e3), Point(1,1));
+ //the case below will never work without normalizing the line
+ //lines.emplace_back(Point(1e5,1e5), Point(1e-15,0));
+ lines.emplace_back(Point(1e5,1e5), Point(1e5,-1e5));
+ lines.emplace_back(Point(-3,10), Point(3,10));
+ lines.emplace_back(Point(250,333), Point(-72,121));
+
+ for (auto & line : lines) {
+ Coord a, b, c, A, B, C;
+ line.coefficients(a, b, c);
+ /*std::cout << format_coord_nice(a) << " "
+ << format_coord_nice(b) << " "
+ << format_coord_nice(c) << std::endl;*/
+ Line k(a, b, c);
+ //std::cout << k.initialPoint() << " " << k.finalPoint() << std::endl;
+ k.coefficients(A, B, C);
+ /*std::cout << format_coord_nice(A) << " "
+ << format_coord_nice(B) << " "
+ << format_coord_nice(C) << std::endl;*/
+ EXPECT_DOUBLE_EQ(a, A);
+ EXPECT_DOUBLE_EQ(b, B);
+ EXPECT_DOUBLE_EQ(c, C);
+
+ for (unsigned j = 0; j <= 10; ++j) {
+ double t = j / 10.;
+ Point p = line.pointAt(t);
+ /*std::cout << t << " " << p << " "
+ << A*p[X] + B*p[Y] + C << " "
+ << A*(p[X]-1) + B*(p[Y]+1) + C << std::endl;*/
+ EXPECT_near(A*p[X] + B*p[Y] + C, 0., 2e-11);
+ EXPECT_not_near(A*(p[X]-1) + B*(p[Y]+1) + C, 0., 1e-6);
+ }
+ }
+}
+
+TEST(LineTest, Intersection) {
+ Line a(Point(0,3), Point(1,2));
+ Line b(Point(0,-3), Point(1,-2));
+ LineSegment lsa(Point(0,3), Point(1,2));
+ LineSegment lsb(Point(0,-3), Point(1,-2));
+ LineSegment lsc(Point(3,1), Point(3, -1));
+
+ std::vector<ShapeIntersection> r1, r2, r3;
+
+ r1 = a.intersect(b);
+ ASSERT_EQ(r1.size(), 1u);
+ EXPECT_EQ(r1[0].point(), Point(3,0));
+ EXPECT_intersections_valid(a, b, r1, 1e-15);
+
+ r2 = a.intersect(lsc);
+ ASSERT_EQ(r2.size(), 1u);
+ EXPECT_EQ(r2[0].point(), Point(3,0));
+ EXPECT_intersections_valid(a, lsc, r2, 1e-15);
+
+ r3 = b.intersect(lsc);
+ ASSERT_EQ(r3.size(), 1u);
+ EXPECT_EQ(r3[0].point(), Point(3,0));
+ EXPECT_intersections_valid(a, lsc, r3, 1e-15);
+
+ EXPECT_TRUE(lsa.intersect(lsb).empty());
+ EXPECT_TRUE(lsa.intersect(lsc).empty());
+ EXPECT_TRUE(lsb.intersect(lsc).empty());
+ EXPECT_TRUE(a.intersect(lsb).empty());
+ EXPECT_TRUE(b.intersect(lsa).empty());
+}
diff --git a/src/3rdparty/2geom/tests/mersennetwister.h b/src/3rdparty/2geom/tests/mersennetwister.h
new file mode 100644
index 0000000..bc19d8e
--- /dev/null
+++ b/src/3rdparty/2geom/tests/mersennetwister.h
@@ -0,0 +1,427 @@
+/**
+ * 2Geom developers:
+ * For licence reasons, Do not copy code from this header into other files
+ * */
+// MersenneTwister.h
+// Mersenne Twister random number generator -- a C++ class MTRand
+// Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
+// Richard J. Wagner v1.0 15 May 2003 rjwagner@writeme.com
+
+// The Mersenne Twister is an algorithm for generating random numbers. It
+// was designed with consideration of the flaws in various other generators.
+// The period, 2^19937-1, and the order of equidistribution, 623 dimensions,
+// are far greater. The generator is also fast; it avoids multiplication and
+// division, and it benefits from caches and pipelines. For more information
+// see the inventors' web page at http://www.math.keio.ac.jp/~matumoto/emt.html
+
+// Reference
+// M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally
+// Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on
+// Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30.
+
+// Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+// Copyright (C) 2000 - 2003, Richard J. Wagner
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// 3. The names of its contributors may not be used to endorse or promote
+// products derived from this software without specific prior written
+// permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The original code included the following notice:
+//
+// When you use this, send an email to: matumoto@math.keio.ac.jp
+// with an appropriate reference to your work.
+//
+// It would be nice to CC: rjwagner@writeme.com and Cokus@math.washington.edu
+// when you write.
+
+#ifndef MERSENNETWISTER_H
+#define MERSENNETWISTER_H
+
+// Not thread safe (unless auto-initialization is avoided and each thread has
+// its own MTRand object)
+
+#include <iostream>
+#include <limits.h>
+#include <stdio.h>
+#include <time.h>
+#include <math.h>
+
+class MTRand {
+ // Data
+ public:
+ typedef unsigned long uint32; // unsigned integer type, at least 32 bits
+
+ enum { N = 624 }; // length of state vector
+ enum { SAVE = N + 1 }; // length of array for save()
+
+ protected:
+ enum { M = 397 }; // period parameter
+
+ uint32 state[N]; // internal state
+ uint32 *pNext; // next value to get from state
+ int left; // number of values left before reload needed
+
+
+ //Methods
+ public:
+ MTRand( const uint32& oneSeed ); // initialize with a simple uint32
+ MTRand( uint32 *const bigSeed, uint32 const seedLength = N ); // or an array
+ MTRand(); // auto-initialize with /dev/urandom or time() and clock()
+
+ // Do NOT use for CRYPTOGRAPHY without securely hashing several returned
+ // values together, otherwise the generator state can be learned after
+ // reading 624 consecutive values.
+
+ // Access to 32-bit random numbers
+ double rand(); // real number in [0,1]
+ double rand( const double& n ); // real number in [0,n]
+ double randExc(); // real number in [0,1)
+ double randExc( const double& n ); // real number in [0,n)
+ double randDblExc(); // real number in (0,1)
+ double randDblExc( const double& n ); // real number in (0,n)
+ uint32 randInt(); // integer in [0,2^32-1]
+ uint32 randInt( const uint32& n ); // integer in [0,n] for n < 2^32
+ double operator()() { return rand(); } // same as rand()
+
+ // Access to 53-bit random numbers (capacity of IEEE double precision)
+ double rand53(); // real number in [0,1)
+
+ // Access to nonuniform random number distributions
+ double randNorm( const double& mean = 0.0, const double& variance = 1.0 );
+
+ // Re-seeding functions with same behavior as initializers
+ void seed( const uint32 oneSeed );
+ void seed( uint32 *const bigSeed, const uint32 seedLength = N );
+ void seed();
+
+ // Saving and loading generator state
+ void save( uint32* saveArray ) const; // to array of size SAVE
+ void load( uint32 *const loadArray ); // from such array
+ friend std::ostream& operator<<( std::ostream& os, const MTRand& mtrand );
+ friend std::istream& operator>>( std::istream& is, MTRand& mtrand );
+
+ protected:
+ void initialize( const uint32 oneSeed );
+ void reload();
+ uint32 hiBit( const uint32& u ) const { return u & 0x80000000UL; }
+ uint32 loBit( const uint32& u ) const { return u & 0x00000001UL; }
+ uint32 loBits( const uint32& u ) const { return u & 0x7fffffffUL; }
+ uint32 mixBits( const uint32& u, const uint32& v ) const
+ { return hiBit(u) | loBits(v); }
+ uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const
+ { return m ^ (mixBits(s0,s1)>>1) ^ (-loBit(s1) & 0x9908b0dfUL); }
+ static uint32 hash( time_t t, clock_t c );
+};
+
+
+inline MTRand::MTRand( const uint32& oneSeed )
+{ seed(oneSeed); }
+
+inline MTRand::MTRand( uint32 *const bigSeed, const uint32 seedLength )
+{ seed(bigSeed,seedLength); }
+
+inline MTRand::MTRand()
+{ seed(); }
+
+inline double MTRand::rand()
+{ return double(randInt()) * (1.0/4294967295.0); }
+
+inline double MTRand::rand( const double& n )
+{ return rand() * n; }
+
+inline double MTRand::randExc()
+{ return double(randInt()) * (1.0/4294967296.0); }
+
+inline double MTRand::randExc( const double& n )
+{ return randExc() * n; }
+
+inline double MTRand::randDblExc()
+{ return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); }
+
+inline double MTRand::randDblExc( const double& n )
+{ return randDblExc() * n; }
+
+inline double MTRand::rand53()
+{
+ uint32 a = randInt() >> 5, b = randInt() >> 6;
+ return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0); // by Isaku Wada
+}
+
+inline double MTRand::randNorm( const double& mean, const double& variance )
+{
+ // Return a real number from a normal (Gaussian) distribution with given
+ // mean and variance by Box-Muller method
+ double r = sqrt( -2.0 * log( 1.0-randDblExc()) ) * variance;
+ double phi = 2.0 * 3.14159265358979323846264338328 * randExc();
+ return mean + r * cos(phi);
+}
+
+inline MTRand::uint32 MTRand::randInt()
+{
+ // Pull a 32-bit integer from the generator state
+ // Every other access function simply transforms the numbers extracted here
+
+ if( left == 0 ) reload();
+ --left;
+
+ register uint32 s1;
+ s1 = *pNext++;
+ s1 ^= (s1 >> 11);
+ s1 ^= (s1 << 7) & 0x9d2c5680UL;
+ s1 ^= (s1 << 15) & 0xefc60000UL;
+ return ( s1 ^ (s1 >> 18) );
+}
+
+inline MTRand::uint32 MTRand::randInt( const uint32& n )
+{
+ // Find which bits are used in n
+ // Optimized by Magnus Jonsson (magnus@smartelectronix.com)
+ uint32 used = n;
+ used |= used >> 1;
+ used |= used >> 2;
+ used |= used >> 4;
+ used |= used >> 8;
+ used |= used >> 16;
+
+ // Draw numbers until one is found in [0,n]
+ uint32 i;
+ do
+ i = randInt() & used; // toss unused bits to shorten search
+ while( i > n );
+ return i;
+}
+
+
+inline void MTRand::seed( const uint32 oneSeed )
+{
+ // Seed the generator with a simple uint32
+ initialize(oneSeed);
+ reload();
+}
+
+
+inline void MTRand::seed( uint32 *const bigSeed, const uint32 seedLength )
+{
+ // Seed the generator with an array of uint32's
+ // There are 2^19937-1 possible initial states. This function allows
+ // all of those to be accessed by providing at least 19937 bits (with a
+ // default seed length of N = 624 uint32's). Any bits above the lower 32
+ // in each element are discarded.
+ // Just call seed() if you want to get array from /dev/urandom
+ initialize(19650218UL);
+ register int i = 1;
+ register uint32 j = 0;
+ register int k = ( uint32(N) > seedLength ? uint32(N) : seedLength );
+ for( ; k; --k )
+ {
+ state[i] =
+ state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL );
+ state[i] += ( bigSeed[j] & 0xffffffffUL ) + j;
+ state[i] &= 0xffffffffUL;
+ ++i; ++j;
+ if( i >= N ) { state[0] = state[N-1]; i = 1; }
+ if( j >= seedLength ) j = 0;
+ }
+ for( k = N - 1; k; --k )
+ {
+ state[i] =
+ state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL );
+ state[i] -= i;
+ state[i] &= 0xffffffffUL;
+ ++i;
+ if( i >= N ) { state[0] = state[N-1]; i = 1; }
+ }
+ state[0] = 0x80000000UL; // MSB is 1, assuring non-zero initial array
+ reload();
+}
+
+
+inline void MTRand::seed()
+{
+ // Seed the generator with an array from /dev/urandom if available
+ // Otherwise use a hash of time() and clock() values
+
+ // First try getting an array from /dev/urandom
+ FILE* urandom = fopen( "/dev/urandom", "rb" );
+ if( urandom )
+ {
+ uint32 bigSeed[N];
+ register uint32 *s = bigSeed;
+ register int i = N;
+ register bool success = true;
+ while( success && i-- )
+ success = fread( s++, sizeof(uint32), 1, urandom );
+ fclose(urandom);
+ if( success ) { seed( bigSeed, N ); return; }
+ }
+
+ // Was not successful, so use time() and clock() instead
+ seed( hash( time(NULL), clock() ) );
+}
+
+
+inline void MTRand::initialize( const uint32 seed )
+{
+ // Initialize generator state with seed
+ // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
+ // In previous versions, most significant bits (MSBs) of the seed affect
+ // only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto.
+ register uint32 *s = state;
+ register uint32 *r = state;
+ register int i = 1;
+ *s++ = seed & 0xffffffffUL;
+ for( ; i < N; ++i )
+ {
+ *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL;
+ r++;
+ }
+}
+
+
+inline void MTRand::reload()
+{
+ // Generate N new values in state
+ // Made clearer and faster by Matthew Bellew (matthew.bellew@home.com)
+ register uint32 *p = state;
+ register int i;
+ for( i = N - M; i--; ++p )
+ *p = twist( p[M], p[0], p[1] );
+ for( i = M; --i; ++p )
+ *p = twist( p[M-N], p[0], p[1] );
+ *p = twist( p[M-N], p[0], state[0] );
+
+ left = N, pNext = state;
+}
+
+
+inline MTRand::uint32 MTRand::hash( time_t t, clock_t c )
+{
+ // Get a uint32 from t and c
+ // Better than uint32(x) in case x is floating point in [0,1]
+ // Based on code by Lawrence Kirby (fred@genesis.demon.co.uk)
+
+ static uint32 differ = 0; // guarantee time-based seeds will change
+
+ uint32 h1 = 0;
+ unsigned char *p = (unsigned char *) &t;
+ for( size_t i = 0; i < sizeof(t); ++i )
+ {
+ h1 *= UCHAR_MAX + 2U;
+ h1 += p[i];
+ }
+ uint32 h2 = 0;
+ p = (unsigned char *) &c;
+ for( size_t j = 0; j < sizeof(c); ++j )
+ {
+ h2 *= UCHAR_MAX + 2U;
+ h2 += p[j];
+ }
+ return ( h1 + differ++ ) ^ h2;
+}
+
+
+inline void MTRand::save( uint32* saveArray ) const
+{
+ register uint32 *sa = saveArray;
+ register const uint32 *s = state;
+ register int i = N;
+ for( ; i--; *sa++ = *s++ ) {}
+ *sa = left;
+}
+
+
+inline void MTRand::load( uint32 *const loadArray )
+{
+ register uint32 *s = state;
+ register uint32 *la = loadArray;
+ register int i = N;
+ for( ; i--; *s++ = *la++ ) {}
+ left = *la;
+ pNext = &state[N-left];
+}
+
+
+inline std::ostream& operator<<( std::ostream& os, const MTRand& mtrand )
+{
+ register const MTRand::uint32 *s = mtrand.state;
+ register int i = mtrand.N;
+ for( ; i--; os << *s++ << "\t" ) {}
+ return os << mtrand.left;
+}
+
+
+inline std::istream& operator>>( std::istream& is, MTRand& mtrand )
+{
+ register MTRand::uint32 *s = mtrand.state;
+ register int i = mtrand.N;
+ for( ; i--; is >> *s++ ) {}
+ is >> mtrand.left;
+ mtrand.pNext = &mtrand.state[mtrand.N-mtrand.left];
+ return is;
+}
+
+#endif // MERSENNETWISTER_H
+
+// Change log:
+//
+// v0.1 - First release on 15 May 2000
+// - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
+// - Translated from C to C++
+// - Made completely ANSI compliant
+// - Designed convenient interface for initialization, seeding, and
+// obtaining numbers in default or user-defined ranges
+// - Added automatic seeding from /dev/urandom or time() and clock()
+// - Provided functions for saving and loading generator state
+//
+// v0.2 - Fixed bug which reloaded generator one step too late
+//
+// v0.3 - Switched to clearer, faster reload() code from Matthew Bellew
+//
+// v0.4 - Removed trailing newline in saved generator format to be consistent
+// with output format of built-in types
+//
+// v0.5 - Improved portability by replacing static const int's with enum's and
+// clarifying return values in seed(); suggested by Eric Heimburg
+// - Removed MAXINT constant; use 0xffffffffUL instead
+//
+// v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits
+// - Changed integer [0,n] generator to give better uniformity
+//
+// v0.7 - Fixed operator precedence ambiguity in reload()
+// - Added access for real numbers in (0,1) and (0,n)
+//
+// v0.8 - Included time.h header to properly support time_t and clock_t
+//
+// v1.0 - Revised seeding to match 26 Jan 2002 update of Nishimura and Matsumoto
+// - Allowed for seeding with arrays of any length
+// - Added access for real numbers in [0,1) with 53-bit resolution
+// - Added access for real numbers from normal (Gaussian) distributions
+// - Increased overall speed by optimizing twist()
+// - Doubled speed of integer [0,n] generation
+// - Fixed out-of-range number generation on 64-bit machines
+// - Improved portability by substituting literal constants for long enum's
+// - Changed license from GNU LGPL to BSD
diff --git a/src/3rdparty/2geom/tests/nl-vector-test.cpp b/src/3rdparty/2geom/tests/nl-vector-test.cpp
new file mode 100644
index 0000000..53e8eaa
--- /dev/null
+++ b/src/3rdparty/2geom/tests/nl-vector-test.cpp
@@ -0,0 +1,333 @@
+/** @file
+ * @brief Unit tests for Vector, VectorView
+ *//*
+ * Authors:
+ * Olof Bjarnason <olof.bjarnason@gmail.com>
+ *
+ * Copyright 2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <gtest/gtest.h>
+
+#include <2geom/numeric/vector.h>
+
+namespace Geom {
+
+////
+// Test fixture used in many tests.
+// v1 = [0, 1, ..., 8, 9]
+////
+class CountingVectorFixture : public ::testing::Test {
+public:
+ CountingVectorFixture() : v1(10) { }
+
+protected:
+ void SetUp() override {
+ for (unsigned int i = 0; i < this->v1.size(); ++i)
+ this->v1[i] = i;
+ }
+
+ NL::Vector v1;
+};
+
+// These types are only here to differentiate
+// between categories of tests - they both use
+// the same v1 test fixture variable.
+class VectorTest : public CountingVectorFixture { };
+class VectorViewTest : public CountingVectorFixture { };
+
+////
+// Helper method to write simple tests
+////
+NL::Vector V3(double a, double b, double c) {
+ NL::Vector v(3);
+ v[0] = a;
+ v[1] = b;
+ v[2] = c;
+ return v;
+}
+
+////
+// ** Vector examples **
+////
+
+TEST_F(VectorTest, VectorStringRepresentation) {
+ EXPECT_EQ(v1.str(), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
+}
+
+TEST_F(VectorTest, VectorConstructFromAnother) {
+ NL::Vector v2(v1);
+ EXPECT_EQ(v1.str(), v2.str());
+}
+
+TEST_F(VectorTest, OperatorEqualIsDefined) {
+ EXPECT_TRUE(v1 == v1);
+ NL::Vector v2(v1);
+ EXPECT_TRUE(v1 == v2);
+ // TODO: This operation compares doubles
+ // with operator ==. Should it use a distance
+ // threshold instead?
+}
+
+TEST_F(VectorTest, OperatorNotEqualIsntDefined) {
+ SUCCEED();
+ //NL::Vector v3(4);
+ //EXPECT_TRUE(v1 != v3); // Not expressible in C++;
+ // gives compile time error
+}
+
+TEST_F(VectorTest, VectorAssignment) {
+ NL::Vector v2(v1.size());
+ v2 = v1;
+ EXPECT_EQ(v1, v2);
+}
+
+#ifndef NDEBUG
+TEST_F(VectorTest, AssignedVectorMustBeSameSize) {
+ NL::Vector v2(5);
+ // On Linux, the assertion message is:
+ // Assertion ... failed ...
+ // On OSX, it is:
+ // Assertion failed: (...), function ..., file ..., line ...
+ // Thus we just look for the word "Assertion".
+ EXPECT_DEATH({v2 = v1;}, "Assertion");
+}
+#endif
+
+TEST_F(VectorTest, VectorScalesInplace) {
+ v1.scale(2);
+ EXPECT_EQ(v1.str(), "[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]");
+}
+
+TEST_F(VectorTest, VectorTranslatesInplace) {
+ v1.translate(1);
+ EXPECT_EQ(v1.str(), "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]");
+}
+
+TEST_F(VectorTest, ScaleAndTranslateUsesFluentSyntax) {
+ NL::VectorView vv(v1, 3);
+ EXPECT_EQ(vv.translate(5).scale(10).str(), "[50, 60, 70]");
+}
+
+TEST_F(VectorTest, AddAssignment) {
+ NL::Vector v2(v1);
+ v2 += v1;
+ EXPECT_EQ(v2.str(), "[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]");
+}
+
+TEST_F(VectorTest, SubtractAssignment) {
+ NL::Vector v2(v1);
+ v2 -= v1;
+ EXPECT_EQ(v2.str(), "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]");
+}
+
+TEST_F(VectorTest, SwappingElements) {
+ v1.swap_elements(0, 9);
+ EXPECT_EQ(v1.str(), "[9, 1, 2, 3, 4, 5, 6, 7, 8, 0]");
+}
+
+TEST_F(VectorTest, Reverse) {
+ v1.reverse();
+ EXPECT_EQ(v1.str(), "[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]");
+}
+
+TEST(Vector, IsPositive) {
+ EXPECT_TRUE(V3(1, 1, 1).is_positive());
+ EXPECT_FALSE(V3(0, 0, 0).is_positive());
+ EXPECT_FALSE(V3(-1, 0, 1).is_positive());
+}
+
+TEST_F(VectorTest, IsZero) {
+ EXPECT_FALSE(v1.is_zero());
+ EXPECT_TRUE(V3(0, 0, 0).is_zero());
+}
+
+TEST_F(VectorTest, IsNonNegative) {
+ EXPECT_TRUE(V3(1, 1, 1).is_non_negative());
+ EXPECT_TRUE(V3(0, 0, 0).is_non_negative());
+ EXPECT_FALSE(V3(-1, 1, 1).is_non_negative());
+}
+
+TEST(Vector, Max) {
+ EXPECT_EQ(V3(1, 5, 3).max(), 5);
+}
+
+TEST(Vector, MaxIndex) {
+ EXPECT_EQ(V3(1, 5, 3).max_index(), 1u);
+}
+
+TEST(Vector, Min) {
+ EXPECT_EQ(V3(1, -5, -300).min(), -300);
+}
+
+TEST(Vector, MinIndex) {
+ EXPECT_EQ(V3(1, 5, 3).min_index(), 0u);
+}
+
+TEST_F(VectorTest, SetAll) {
+ v1.set_all(5);
+ EXPECT_EQ(v1.str(), "[5, 5, 5, 5, 5, 5, 5, 5, 5, 5]");
+}
+
+TEST_F(VectorTest, SetBasis) {
+ v1.set_basis(1);
+ EXPECT_EQ(v1.str(), "[0, 1, 0, 0, 0, 0, 0, 0, 0, 0]");
+}
+
+TEST(Vector, SwappingVectors) {
+ NL::Vector a(V3(1, 2, 3));
+ NL::Vector b(V3(7, 7, 7));
+ NL::swap(a, b);
+ EXPECT_EQ(V3(7, 7, 7), a);
+ EXPECT_EQ(V3(1, 2, 3), b);
+}
+
+////
+// ** VectorView tests **
+////
+
+// Construction examples
+
+TEST_F(VectorViewTest, ViewCountOnly) {
+ // VectorView(vector, showCount)
+ EXPECT_EQ(NL::VectorView(v1, 5).str(), "[0, 1, 2, 3, 4]");
+}
+
+TEST_F(VectorViewTest, SkipSomeInitialElements) {
+ // VectorView(vector, showCount, startIndex)
+ EXPECT_EQ(NL::VectorView(v1, 5, 3).str(), "[3, 4, 5, 6, 7]");
+}
+
+TEST_F(VectorViewTest, SparseViewConstruction) {
+ // VectorView(vector, showCount, startIndex, step)
+ EXPECT_EQ(NL::VectorView(v1, 5, 0, 2).str(), "[0, 2, 4, 6, 8]");
+ EXPECT_EQ(NL::VectorView(v1, 5, 1, 2).str(), "[1, 3, 5, 7, 9]");
+}
+
+TEST_F(VectorViewTest, ConstructFromAnotherView) {
+ // VectorView(vectorview, showCount, startIndex, step)
+ NL::VectorView vv(v1, 5, 1, 2);
+ NL::VectorView view(vv, 3, 0, 2);
+ EXPECT_EQ(view.str(), "[1, 5, 9]");
+}
+
+// Operations modify source vectors
+
+TEST_F(VectorViewTest, PartialSourceModification) {
+ NL::VectorView vv(v1, 3);
+ vv.translate(10);
+ EXPECT_EQ(v1.str(),
+ "[10, 11, 12, 3, 4, 5, 6, 7, 8, 9]");
+ EXPECT_EQ(vv.str(),
+ "[10, 11, 12]");
+}
+
+// Scale and translate examples
+
+TEST_F(VectorViewTest, ViewScalesInplace) {
+ v1.scale(10);
+ EXPECT_EQ(NL::VectorView(v1, 3).str(), "[0, 10, 20]");
+}
+
+TEST_F(VectorViewTest, ViewScaleAndTranslateUsesFluentSyntax) {
+ EXPECT_EQ(NL::VectorView(v1, 3).scale(10).translate(1).str(),
+ "[1, 11, 21]");
+}
+
+// Assignment
+
+TEST_F(VectorViewTest, AssignmentFromVectorAvailableForViews) {
+ NL::VectorView vv(v1, v1.size());
+ vv = v1;
+ EXPECT_EQ(vv.str(), v1.str());
+}
+
+#ifndef NDEBUG
+TEST_F(VectorViewTest, AssignmentFromVectorMustBeSameSize) {
+ NL::VectorView vv(v1, 5);
+ EXPECT_DEATH({vv = v1;}, "Assertion");
+}
+#endif
+
+TEST_F(VectorViewTest, AssignmentFromViewAvailableForViews) {
+ NL::VectorView view1(v1, v1.size());
+ view1 = v1;
+ NL::VectorView view2(view1);
+ view2 = view1;
+ EXPECT_EQ(view1.str(), view2.str());
+}
+
+#ifndef NDEBUG
+TEST_F(VectorViewTest, AssignmentFromViewMustBeSameSize) {
+ NL::VectorView view1(v1, v1.size());
+ NL::VectorView view2(view1, view1.size() - 1);
+ EXPECT_DEATH({view2 = view1;}, "Assertion");
+}
+#endif
+
+// Add- and subtract assignment
+
+TEST_F(VectorViewTest, AddAssignAvailableForViews) {
+ NL::VectorView v2(v1);
+ v1 += v2;
+ EXPECT_EQ(v1.str(), "[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]");
+}
+
+TEST_F(VectorViewTest, SubtractAssignAvailableForViews) {
+ NL::Vector v2(v1);
+ v1 -= v2;
+ EXPECT_TRUE(v1.is_zero());
+}
+
+// View swapping
+
+TEST_F(VectorViewTest, SwappingFromSameSourceVectorDoesNotModifySource) {
+ NL::VectorView vv1(v1, 2, 0);
+ NL::VectorView vv2(v1, 2, 8);
+ NL::swap_view(vv1, vv2);
+ EXPECT_EQ(v1.str(), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
+}
+
+TEST_F(VectorViewTest, SwappingFromSameSourceVectorModifiesViews) {
+ NL::VectorView viewStart(v1, 2, 0);
+ NL::VectorView viewEnd(v1, 2, 8);
+ EXPECT_EQ(viewStart.str(), "[0, 1]");
+ EXPECT_EQ(viewEnd.str(), "[8, 9]");
+ NL::swap_view(viewStart, viewEnd);
+ EXPECT_EQ(viewStart.str(), "[8, 9]");
+ EXPECT_EQ(viewEnd.str(), "[0, 1]");
+}
+
+#ifndef NDEBUG
+TEST_F(VectorViewTest, SwappingDifferentLengthViewFails) {
+ NL::VectorView vv1(v1, 4);
+ NL::VectorView vv2(v1, 3);
+ EXPECT_DEATH({NL::swap_view(vv1, vv2);}, "Assertion");
+}
+#endif
+
+
+} // namespace Geom
diff --git a/src/3rdparty/2geom/tests/parallelogram-test.cpp b/src/3rdparty/2geom/tests/parallelogram-test.cpp
new file mode 100644
index 0000000..70ccea1
--- /dev/null
+++ b/src/3rdparty/2geom/tests/parallelogram-test.cpp
@@ -0,0 +1,161 @@
+/** @file
+ * @brief Unit tests for Parallelogram
+ *
+ * Includes all tests from RotatedRect to demonstrate that it is a generalized
+ * version of the rotated rectangle.
+ */
+/*
+ * Authors:
+ * Thomas Holder
+ * Sergei Izmailov
+ *
+ * SPDX-License-Identifier: LGPL-2.1 or MPL-1.1
+ */
+
+#include <2geom/coord.h>
+#include <2geom/parallelogram.h>
+#include <2geom/transforms.h>
+
+#include <gtest/gtest.h>
+
+using namespace Geom;
+
+// Analogous to RotatedRect::from_rect_rotate
+static Parallelogram parallelogram_from_rect_rotate(Rect const &rect, Rotate const &rotate, Point const &point)
+{
+ Affine affine = Translate(-point) * rotate * Translate(point);
+ return Parallelogram(rect) * affine;
+}
+static Parallelogram parallelogram_from_rect_rotate(Rect const &rect, Rotate const &rotate)
+{
+ return parallelogram_from_rect_rotate(rect, rotate, rect.midpoint());
+}
+
+TEST(ParallelogramTest, midpoint)
+{
+ Rect r(-0.5, -0.5, 5.5, 5.5);
+ auto center = Point(2.5, 2.5);
+
+ EXPECT_EQ(r.midpoint(), center);
+ for (double angle : { 0, 1, 25, 45, 90, 135 }) {
+ auto rotated_rect = parallelogram_from_rect_rotate(r, Rotate::from_degrees(angle), Point(0, 0));
+ auto rotated_center = center * Rotate(angle / 180.0 * M_PI);
+ EXPECT_TRUE(Geom::are_near(rotated_rect.midpoint(), rotated_center, 1e-6)) << "Angle = " << angle << " deg";
+ }
+}
+
+TEST(ParallelogramTest, containsPoint1)
+{
+ Rect r(0, 0, 1, 1);
+ auto rotated_rect = r;
+ EXPECT_TRUE(rotated_rect.contains(Point(0, 0)));
+ EXPECT_TRUE(rotated_rect.contains(Point(1, 1)));
+ EXPECT_TRUE(rotated_rect.contains(Point(0.5, 0.5)));
+ EXPECT_FALSE(rotated_rect.contains(Point(1.1, 0.5)));
+ EXPECT_FALSE(rotated_rect.contains(Point(0.5, 1.1)));
+}
+
+TEST(ParallelogramTest, containsPoint2)
+{
+ Rect r(0, 0, 1, 1);
+ auto rotated_rect = parallelogram_from_rect_rotate(r, Rotate::from_degrees(45), Point(0, 0));
+ EXPECT_TRUE(rotated_rect.contains(Point(0, 0)));
+ EXPECT_TRUE(rotated_rect.contains(Point(0, 1.2)));
+ EXPECT_TRUE(rotated_rect.contains(Point(0.5, 0.9)));
+ EXPECT_FALSE(rotated_rect.contains(Point(1, 1)));
+ EXPECT_FALSE(rotated_rect.contains(Point(0.1, 0)));
+}
+
+TEST(ParallelogramTest, intersects_aligned)
+{
+ Rect r(0, 0, 1, 1);
+ auto rotated_rect = r;
+ // point within rect
+ EXPECT_TRUE(rotated_rect.intersects(Rect(-1, -1, 2, 2)));
+ EXPECT_TRUE(rotated_rect.intersects(Rect(0.1, 0.1, 0.2, 0.2)));
+ EXPECT_TRUE(rotated_rect.intersects(Rect(-0.1, -0.1, 0.1, 0.1)));
+ EXPECT_FALSE(rotated_rect.intersects(Rect(-0.2, -0.2, -0.1, -0.1)));
+ EXPECT_FALSE(rotated_rect.intersects(Rect(1.1, 1.1, 1.2, 1.2)));
+ // edge intersection
+ EXPECT_TRUE(rotated_rect.intersects(Rect(0.5, -0.1, 0.6, 1.2)));
+ EXPECT_TRUE(rotated_rect.intersects(Rect(-0.1, 0.5, 1.2, 0.6)));
+}
+
+TEST(ParallelogramTest, bounds)
+{
+ auto r = Rect::from_xywh(1.260, 0.547, 8.523, 11.932);
+ auto rrect = parallelogram_from_rect_rotate(r, Rotate::from_degrees(15.59));
+ auto bbox = rrect.bounds();
+ auto expected_bbox = Rect::from_xywh(-0.186, -0.378, 11.415, 13.783);
+ for (int i = 0; i < 4; i++) {
+ EXPECT_TRUE(Geom::are_near(bbox.corner(i), expected_bbox.corner(i), 1e-3));
+ }
+}
+
+TEST(ParallelogramTest, isSheared)
+{
+ Parallelogram p(Rect(2, 4, 7, 8));
+ EXPECT_FALSE(p.isSheared());
+ p *= Rotate(M_PI / 4.0); // 45°
+ EXPECT_FALSE(p.isSheared());
+ p *= HShear(2);
+ EXPECT_TRUE(p.isSheared());
+}
+
+TEST(ParallelogramTest, area)
+{
+ Rect r(2, 4, 7, 8);
+ Parallelogram p(r);
+ EXPECT_DOUBLE_EQ(p.area(), r.area());
+ p *= Rotate(M_PI / 4.0); // 45°
+ EXPECT_DOUBLE_EQ(p.area(), r.area());
+ p *= HShear(2);
+ EXPECT_DOUBLE_EQ(p.area(), r.area());
+ p *= Scale(2);
+ EXPECT_DOUBLE_EQ(p.area(), r.area() * 4);
+}
+
+class ParallelogramTest
+ : public testing::TestWithParam<std::tuple<Rect /*rect*/, double /*degrees*/, bool /*intersects*/>> {
+
+ void SetUp() override { target = Rect::from_xywh(0, 0, 11, 13); }
+
+ public:
+ Rect target;
+};
+
+TEST_P(ParallelogramTest, intersects)
+{
+ Rect rect;
+ double degrees;
+ bool intersects;
+ std::tie(rect, degrees, intersects) = GetParam();
+ EXPECT_EQ(parallelogram_from_rect_rotate(rect, Rotate::from_degrees(degrees)).intersects(target), intersects)
+ << "ERROR: rect {" << rect << "} rotated by {" << degrees << "} degrees " << (!intersects ? "" : "NOT ")
+ << "intersects with {" << target << "} but MUST " << (intersects ? "" : "NOT");
+}
+
+// clang-format off
+INSTANTIATE_TEST_CASE_P(intesect_non_aligned, ParallelogramTest,
+ testing::Values(
+ std::make_tuple(Rect::from_xywh(10.456, -4.479, 7, 5), 0, true),
+ std::make_tuple(Rect::from_xywh(10.456, -4.479, 7, 5), 15, false),
+ std::make_tuple(Rect::from_xywh(9.929, 12.313, 7, 5), 93.2, false),
+ std::make_tuple(Rect::from_xywh(9.929, 12.313, 7, 5), 91.37, true),
+ std::make_tuple(Rect::from_xywh(-1, 4, 13, 3), 0, true),
+ std::make_tuple(Rect::from_xywh(4, -2, 3, 16), 0, true),
+ std::make_tuple(Rect::from_xywh(-5.113, -3.283, 5.000, 7.000), 11.81, false),
+ std::make_tuple(Rect::from_xywh(-5.113, -3.283, 5.000, 7.000), 13.35, true),
+ std::make_tuple(Rect::from_xywh(1.260, 0.547, 8.523, 11.932), 15.59, true),
+ std::make_tuple(Rect::from_xywh(5.328, 0.404, 11, 2), 28.16, true),
+ std::make_tuple(Rect::from_xywh(4.853, 10.691, 11, 2), -30.4, true),
+ std::make_tuple(Rect::from_xywh(-4.429, 10.752, 11, 2), 29.7, true),
+ std::make_tuple(Rect::from_xywh(-4.538, 0.314, 11, 2), -34.19, true),
+ std::make_tuple(Rect::from_xywh(8.398, -3.790, 2, 11), -34, true),
+ std::make_tuple(Rect::from_xywh(8.614, 6.163, 2, 11), 30.38, true),
+ std::make_tuple(Rect::from_xywh(0.492, 6.904, 2, 11), -37.29, true),
+ std::make_tuple(Rect::from_xywh(0.202, -3.148, 2, 11), 31.12, true)));
+
+// clang-format on
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/tests/parser-test.py b/src/3rdparty/2geom/tests/parser-test.py
new file mode 100644
index 0000000..86b2deb
--- /dev/null
+++ b/src/3rdparty/2geom/tests/parser-test.py
@@ -0,0 +1,94 @@
+# * A simple toy to test the parser
+# *
+# * Copyright 2008 Aaron Spike <aaron@ekips.org>
+# *
+# * This library is free software; you can redistribute it and/or
+# * modify it either under the terms of the GNU Lesser General Public
+# * License version 2.1 as published by the Free Software Foundation
+# * (the "LGPL") or, at your option, under the terms of the Mozilla
+# * Public License Version 1.1 (the "MPL"). If you do not alter this
+# * notice, a recipient may use your version of this file under either
+# * the MPL or the LGPL.
+# *
+# * You should have received a copy of the LGPL along with this library
+# * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+# * You should have received a copy of the MPL along with this library
+# * in the file COPYING-MPL-1.1
+# *
+# * The contents of this file are subject to the Mozilla Public License
+# * Version 1.1 (the "License"); you may not use this file except in
+# * compliance with the License. You may obtain a copy of the License at
+# * http://www.mozilla.org/MPL/
+# *
+# * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+# * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+# * the specific language governing rights and limitations.
+
+import sys
+sys.path.append(os.path.join(os.path.dirname(__file__), "..", "py2geom"))
+import py2geom
+
+class TestSink(py2geom.SVGPathSink):
+ def __init__(self):
+ py2geom.SVGPathSink.__init__(self)
+ self.data = []
+ def __str__(self):
+ return ' '.join(self.data)
+ def moveTo(self, p):
+ x,y = p
+ self.data.append('M %s, %s' % (x,y))
+ def lineTo(self, p):
+ x,y = p
+ self.data.append('L %s, %s' % (x,y))
+ def curveTo(self, c0, c1, p):
+ c0x,c0y = c0
+ c1x,c1y = c1
+ x,y = p
+ self.data.append('C %s, %s %s, %s %s, %s' % (c0x,c0y,c1x,c1y,x,y))
+ def quadTo(self, c, p):
+ cx,cy = c
+ x,y = p
+ self.data.append('Q %s, %s %s, %s' % (cx,cy,x,y))
+ def arcTo(self, rx, ry, angle, large_arc, sweep, p):
+ x,y = p
+ self.data.append('A %s, %s %s %i %i %s, %s' % (rx,ry,angle,large_arc,sweep,x,y))
+ def closePath(self):
+ self.data.append('Z')
+ def flush(self):
+ pass
+
+def test_path(description, in_path, out_path):
+ s = TestSink()
+ py2geom.parse_svg_path(in_path, s)
+ if str(s) == out_path:
+ print 'Success: %s' % description
+ return True
+ else:
+ print 'Error: %s' % description
+ print ' given "%s"' % in_path
+ print ' got "%s"' % str(s)
+ print ' expected "%s"' % out_path
+ return False
+
+def run_tests(tests):
+ successes = 0
+ failures = 0
+ for description, in_path, out_path in tests:
+ if test_path(description, in_path, out_path):
+ successes += 1
+ else:
+ failures += 1
+ print '=' * 20
+ print 'Tests: %s' % (successes + failures)
+ print 'Good: %s' % successes
+ print 'Bad: %s' % failures
+
+if __name__=='__main__':
+ tests = [
+ ('lineto', 'M 10,10 L 4,4', 'M 10.0, 10.0 L 4.0, 4.0'),
+ ('implicit lineto', 'M 10,10 L 4,4 5,5 6,6', 'M 10.0, 10.0 L 4.0, 4.0 L 5.0, 5.0 L 6.0, 6.0'),
+ ('implicit lineto after moveto', 'M1.2.3.4.5.6.7', 'M 1.2, 0.3 L 0.4, 0.5 L 0.6, 0.7'),
+ ('arcto', 'M 300 150 A 150, 120, 30, 1, 0, 200 100', 'M 300.0, 150.0 A 150.0, 120.0 30.0 1 0 200.0, 100.0'),
+ ]
+ run_tests(tests)
diff --git a/src/3rdparty/2geom/tests/path-test.cpp b/src/3rdparty/2geom/tests/path-test.cpp
new file mode 100644
index 0000000..dd6f347
--- /dev/null
+++ b/src/3rdparty/2geom/tests/path-test.cpp
@@ -0,0 +1,991 @@
+#include <cmath>
+#include <vector>
+#include <iterator>
+#include <iostream>
+
+#include <glib.h>
+
+#include <2geom/bezier.h>
+#include <2geom/path.h>
+#include <2geom/pathvector.h>
+#include <2geom/path-intersection.h>
+#include <2geom/svg-path-parser.h>
+#include <2geom/svg-path-writer.h>
+
+#include "testing.h"
+
+using namespace std;
+using namespace Geom;
+
+Path string_to_path(const char* s) {
+ PathVector pv = parse_svg_path(s);
+ assert(pv.size() == 1);
+ return pv[0];
+}
+
+// Path fixture
+class PathTest : public ::testing::Test {
+protected:
+ PathTest() {
+ line.append(LineSegment(Point(0,0), Point(1,0)));
+ square = string_to_path("M 0,0 1,0 1,1 0,1 z");
+ circle = string_to_path("M 0,0 a 4.5,4.5 0 1 1 -9,0 4.5,4.5 0 1 1 9,0 z");
+ arcs = string_to_path("M 0,0 a 5,10 45 0 1 10,10 a 5,10 45 0 1 0,0 z");
+ diederik = string_to_path("m 262.6037,35.824151 c 0,0 -92.64892,-187.405851 30,-149.999981 104.06976,31.739531 170,109.9999815 170,109.9999815 l -10,-59.9999905 c 0,0 40,79.99999 -40,79.99999 -80,0 -70,-129.999981 -70,-129.999981 l 50,0 C 435.13571,-131.5667 652.76275,126.44872 505.74322,108.05672 358.73876,89.666591 292.6037,-14.175849 292.6037,15.824151 c 0,30 -30,20 -30,20 z");
+ cmds = string_to_path("M 0,0 V 100 H 100 Q 100,0 0,0 L 200,0 C 200,100 300,100 300,0 S 200,-100 200,0");
+
+ p_open = string_to_path("M 0,0 L 0,5 5,5 5,0");
+ p_closed = p_open;
+ p_closed.close(true);
+ p_add = string_to_path("M -1,6 L 6,6");
+
+ p_open.setStitching(true);
+ p_closed.setStitching(true);
+ }
+
+ // Objects declared here can be used by all tests in the test case for Foo.
+ Path line, square, circle, arcs, diederik, cmds;
+ Path p_open, p_closed, p_add;
+};
+
+TEST_F(PathTest, CopyConstruction) {
+ Path pa = p_closed;
+ Path pc(p_closed);
+ EXPECT_EQ(pa, p_closed);
+ EXPECT_EQ(pa.closed(), p_closed.closed());
+ EXPECT_EQ(pc, p_closed);
+ EXPECT_EQ(pc.closed(), p_closed.closed());
+
+ Path poa = cmds;
+ Path poc(cmds);
+ EXPECT_EQ(poa, cmds);
+ EXPECT_EQ(poa.closed(), cmds.closed());
+ EXPECT_EQ(poc, cmds);
+ EXPECT_EQ(poc.closed(), cmds.closed());
+
+ PathVector pvc(pa);
+ EXPECT_EQ(pvc[0], pa);
+ PathVector pva((Geom::Path()));
+ pva[0] = pa;
+ EXPECT_EQ(pva[0], pa);
+}
+
+TEST_F(PathTest, PathInterval) {
+ PathTime n2_before(1, 0.9995), n2_after(2, 0.0005),
+ n3_before(2, 0.9995), n3_after(3, 0.0005),
+ mid2(2, 0.5), mid3(3, 0.5);
+
+ // ival[x][0] - normal
+ // ival[x][1] - reversed
+ // ival[x][2] - crosses start
+ // ival[x][3] - reversed, crosses start
+ PathInterval ival[5][4];
+
+ ival[0][0] = PathInterval(n2_before, n2_after, false, 4);
+ ival[0][1] = PathInterval(n2_after, n2_before, false, 4);
+ ival[0][2] = PathInterval(n2_before, n2_after, true, 4);
+ ival[0][3] = PathInterval(n2_after, n2_before, true, 4);
+ ival[1][0] = PathInterval(n2_before, n3_after, false, 4);
+ ival[1][1] = PathInterval(n3_after, n2_before, false, 4);
+ ival[1][2] = PathInterval(n2_before, n3_after, true, 4);
+ ival[1][3] = PathInterval(n3_after, n2_before, true, 4);
+ ival[2][0] = PathInterval(n2_before, mid2, false, 4);
+ ival[2][1] = PathInterval(mid2, n2_before, false, 4);
+ ival[2][2] = PathInterval(n2_before, mid2, true, 4);
+ ival[2][3] = PathInterval(mid2, n2_before, true, 4);
+ ival[3][0] = PathInterval(mid2, mid3, false, 4);
+ ival[3][1] = PathInterval(mid3, mid2, false, 4);
+ ival[3][2] = PathInterval(mid2, mid3, true, 4);
+ ival[3][3] = PathInterval(mid3, mid2, true, 4);
+ ival[4][0] = PathInterval(n2_after, n3_before, false, 4);
+ ival[4][1] = PathInterval(n3_before, n2_after, false, 4);
+ ival[4][2] = PathInterval(n2_after, n3_before, true, 4);
+ ival[4][3] = PathInterval(n3_before, n2_after, true, 4);
+
+ EXPECT_TRUE(ival[0][0].contains(n2_before));
+ EXPECT_TRUE(ival[0][0].contains(n2_after));
+ EXPECT_TRUE(ival[0][1].contains(n2_before));
+ EXPECT_TRUE(ival[0][1].contains(n2_after));
+
+ for (unsigned i = 0; i <= 4; ++i) {
+ EXPECT_FALSE(ival[i][0].reverse());
+ EXPECT_TRUE(ival[i][1].reverse());
+ EXPECT_TRUE(ival[i][2].reverse());
+ EXPECT_FALSE(ival[i][3].reverse());
+ }
+
+ for (unsigned i = 0; i <= 4; ++i) {
+ for (unsigned j = 0; j <= 3; ++j) {
+ //std::cout << i << " " << j << " " << ival[i][j] << std::endl;
+ EXPECT_TRUE(ival[i][j].contains(ival[i][j].inside(1e-3)));
+ }
+ }
+
+ PathTime n1(1, 0.0), n1x(0, 1.0),
+ n2(2, 0.0), n2x(1, 1.0),
+ n3(3, 0.0), n3x(2, 1.0);
+ PathTime tests[8] = { n1, n1x, n2, n2x, n3, n3x, mid2, mid3 };
+
+ // 0: false for both
+ // 1: true for normal, false for cross_start
+ // 2: false for normal, true for cross_start
+ // 3: true for both
+
+ int const NORMAL = 1, CROSS = 2, BOTH = 3;
+
+ int includes[5][8] = {
+ { CROSS, CROSS, NORMAL, NORMAL, CROSS, CROSS, CROSS, CROSS },
+ { CROSS, CROSS, NORMAL, NORMAL, NORMAL, NORMAL, NORMAL, CROSS },
+ { CROSS, CROSS, NORMAL, NORMAL, CROSS, CROSS, BOTH, CROSS },
+ { CROSS, CROSS, CROSS, CROSS, NORMAL, NORMAL, BOTH, BOTH },
+ { CROSS, CROSS, CROSS, CROSS, CROSS, CROSS, NORMAL, CROSS }
+ };
+ unsigned sizes[5][2] = {
+ { 2, 4 },
+ { 3, 3 },
+ { 2, 4 },
+ { 2, 4 },
+ { 1, 5 }
+ };
+
+ for (unsigned i = 0; i < 5; ++i) {
+ for (unsigned j = 0; j < 8; ++j) {
+ EXPECT_EQ(ival[i][0].contains(tests[j]), bool(includes[i][j] & NORMAL));
+ EXPECT_EQ(ival[i][1].contains(tests[j]), bool(includes[i][j] & NORMAL));
+ EXPECT_EQ(ival[i][2].contains(tests[j]), bool(includes[i][j] & CROSS));
+ EXPECT_EQ(ival[i][3].contains(tests[j]), bool(includes[i][j] & CROSS));
+ }
+ EXPECT_EQ(ival[i][0].curveCount(), sizes[i][0]);
+ EXPECT_EQ(ival[i][1].curveCount(), sizes[i][0]);
+ EXPECT_EQ(ival[i][2].curveCount(), sizes[i][1]);
+ EXPECT_EQ(ival[i][3].curveCount(), sizes[i][1]);
+ }
+}
+
+TEST_F(PathTest, Continuity) {
+ line.checkContinuity();
+ square.checkContinuity();
+ circle.checkContinuity();
+ diederik.checkContinuity();
+ cmds.checkContinuity();
+}
+
+TEST_F(PathTest, RectConstructor) {
+ Rect r(Point(0,0), Point(10,10));
+ Path rpath(r);
+
+ EXPECT_EQ(rpath.size(), 4u);
+ EXPECT_TRUE(rpath.closed());
+ for (unsigned i = 0; i < 4; ++i) {
+ EXPECT_TRUE(dynamic_cast<LineSegment const *>(&rpath[i]) != NULL);
+ EXPECT_EQ(rpath[i].initialPoint(), r.corner(i));
+ }
+}
+
+TEST_F(PathTest, Reversed) {
+ std::vector<Path> a, r;
+ a.push_back(p_open);
+ a.push_back(p_closed);
+ a.push_back(circle);
+ a.push_back(diederik);
+ a.push_back(cmds);
+
+ for (auto & i : a) {
+ r.push_back(i.reversed());
+ }
+
+ for (unsigned i = 0; i < a.size(); ++i) {
+ EXPECT_EQ(r[i].size(), a[i].size());
+ EXPECT_EQ(r[i].initialPoint(), a[i].finalPoint());
+ EXPECT_EQ(r[i].finalPoint(), a[i].initialPoint());
+ EXPECT_EQ(r[i].reversed(), a[i]);
+ Point p1 = r[i].pointAt(0.75);
+ Point p2 = a[i].pointAt(a[i].size() - 0.75);
+ EXPECT_FLOAT_EQ(p1[X], p2[X]);
+ EXPECT_FLOAT_EQ(p1[Y], p2[Y]);
+ EXPECT_EQ(r[i].closed(), a[i].closed());
+ a[i].checkContinuity();
+ }
+}
+
+TEST_F(PathTest, ValueAt) {
+ EXPECT_EQ(Point(0,0), line.initialPoint());
+ EXPECT_EQ(Point(1,0), line.finalPoint());
+
+ EXPECT_EQ(Point(0.5, 0.0), line.pointAt(0.5));
+
+ EXPECT_EQ(Point(0,0), square.initialPoint());
+ EXPECT_EQ(Point(0,0), square.finalPoint());
+ EXPECT_EQ(Point(1,0), square.pointAt(1));
+ EXPECT_EQ(Point(0.5,1), square.pointAt(2.5));
+ EXPECT_EQ(Point(0,0.5), square.pointAt(3.5));
+ EXPECT_EQ(Point(0,0), square.pointAt(4));
+}
+
+TEST_F(PathTest, NearestPoint) {
+ EXPECT_EQ(0, line.nearestTime(Point(0,0)).asFlatTime());
+ EXPECT_EQ(0.5, line.nearestTime(Point(0.5,0)).asFlatTime());
+ EXPECT_EQ(0.5, line.nearestTime(Point(0.5,1)).asFlatTime());
+ EXPECT_EQ(1, line.nearestTime(Point(100,0)).asFlatTime());
+ EXPECT_EQ(0, line.nearestTime(Point(-100,1000)).asFlatTime());
+
+ EXPECT_EQ(0, square.nearestTime(Point(0,0)).asFlatTime());
+ EXPECT_EQ(1, square.nearestTime(Point(1,0)).asFlatTime());
+ EXPECT_EQ(3, square.nearestTime(Point(0,1)).asFlatTime());
+
+ //cout << diederik.nearestTime(Point(247.32293,-43.339507)) << endl;
+
+ Point p(511.75,40.85);
+ EXPECT_FLOAT_EQ(6.5814033, diederik.nearestTime(p).asFlatTime());
+ /*cout << diederik.pointAt(diederik.nearestTime(p)) << endl
+ << diederik.pointAt(6.5814033) << endl
+ << distance(diederik.pointAt(diederik.nearestTime(p)), p) << " "
+ << distance(diederik.pointAt(6.5814033), p) << endl;*/
+
+}
+
+TEST_F(PathTest, Winding) {
+ // test points in special positions
+ EXPECT_EQ(line.winding(Point(-1, 0)), 0);
+ EXPECT_EQ(line.winding(Point(2, 0)), 0);
+ EXPECT_EQ(line.winding(Point(0, 1)), 0);
+ EXPECT_EQ(line.winding(Point(0, -1)), 0);
+ EXPECT_EQ(line.winding(Point(1, 1)), 0);
+ EXPECT_EQ(line.winding(Point(1, -1)), 0);
+
+ EXPECT_EQ(square.winding(Point(0, -1)), 0);
+ EXPECT_EQ(square.winding(Point(1, -1)), 0);
+ EXPECT_EQ(square.winding(Point(0, 2)), 0);
+ EXPECT_EQ(square.winding(Point(1, 2)), 0);
+ EXPECT_EQ(square.winding(Point(-1, 0)), 0);
+ EXPECT_EQ(square.winding(Point(-1, 1)), 0);
+ EXPECT_EQ(square.winding(Point(2, 0)), 0);
+ EXPECT_EQ(square.winding(Point(2, 1)), 0);
+ EXPECT_EQ(square.winding(Point(0.5, 0.5)), 1);
+
+ EXPECT_EQ(circle.winding(Point(-4.5,0)), 1);
+ EXPECT_EQ(circle.winding(Point(-3.5,0)), 1);
+ EXPECT_EQ(circle.winding(Point(-4.5,1)), 1);
+ EXPECT_EQ(circle.winding(Point(-10,0)), 0);
+ EXPECT_EQ(circle.winding(Point(1,0)), 0);
+
+ Path yellipse = string_to_path("M 0,0 A 40 20 90 0 0 0,-80 40 20 90 0 0 0,0 z");
+ EXPECT_EQ(yellipse.winding(Point(-1, 0)), 0);
+ EXPECT_EQ(yellipse.winding(Point(-1, -80)), 0);
+ EXPECT_EQ(yellipse.winding(Point(1, 0)), 0);
+ EXPECT_EQ(yellipse.winding(Point(1, -80)), 0);
+ EXPECT_EQ(yellipse.winding(Point(0, -40)), -1);
+ std::vector<double> r[4];
+ r[0] = yellipse[0].roots(0, Y);
+ r[1] = yellipse[0].roots(-80, Y);
+ r[2] = yellipse[1].roots(0, Y);
+ r[3] = yellipse[1].roots(-80, Y);
+ for (auto & i : r) {
+ for (double j : i) {
+ std::cout << format_coord_nice(j) << " ";
+ }
+ std::cout << std::endl;
+ }
+ std::cout << yellipse[0].unitTangentAt(0) << " "
+ << yellipse[0].unitTangentAt(1) << " "
+ << yellipse[1].unitTangentAt(0) << " "
+ << yellipse[1].unitTangentAt(1) << std::endl;
+
+ Path half_ellipse = string_to_path("M 0,0 A 40 20 90 0 0 0,-80 L -20,-40 z");
+ EXPECT_EQ(half_ellipse.winding(Point(-1, 0)), 0);
+ EXPECT_EQ(half_ellipse.winding(Point(-1, -80)), 0);
+ EXPECT_EQ(half_ellipse.winding(Point(1, 0)), 0);
+ EXPECT_EQ(half_ellipse.winding(Point(1, -80)), 0);
+ EXPECT_EQ(half_ellipse.winding(Point(0, -40)), -1);
+
+ // extra nasty cases with exact double roots
+ Path hump = string_to_path("M 0,0 Q 1,1 2,0 L 2,2 0,2 Z");
+ EXPECT_EQ(hump.winding(Point(0.25, 0.5)), 1);
+ EXPECT_EQ(hump.winding(Point(1.75, 0.5)), 1);
+
+ Path hump2 = string_to_path("M 0,0 L 2,0 2,2 Q 1,1 0,2 Z");
+ EXPECT_EQ(hump2.winding(Point(0.25, 1.5)), 1);
+ EXPECT_EQ(hump2.winding(Point(1.75, 1.5)), 1);
+}
+
+/// Regression test for issue https://gitlab.com/inkscape/lib2geom/-/issues/58
+TEST_F(PathTest, Issue58)
+{
+ auto const random_point_in = [](Geom::Rect const &box) -> Point {
+ Coord const x = g_random_double_range(box[X].min(), box[X].max());
+ Coord const y = g_random_double_range(box[Y].min(), box[Y].max());
+ return {x, y};
+ };
+
+ auto const verify_windings = [](Ellipse const &e, Path const &path, Point const &pt) {
+ int const winding = path.winding(pt);
+ if (e.contains(pt)) {
+ EXPECT_EQ(winding, 1);
+ } else {
+ EXPECT_EQ(winding, 0);
+ }
+ };
+
+ // Example elliptical path from issue https://gitlab.com/inkscape/lib2geom/-/issues/58
+ char const *const issue_d = "M 495.8157837290847 280.07459226562503"
+ "A 166.63407933993605 132.04407218873035 0 0 1 329.1817043891487 412.11866445435544"
+ "A 166.63407933993605 132.04407218873035 0 0 1 162.54762504921263 280.07459226562503"
+ "A 166.63407933993605 132.04407218873035 0 0 1 329.1817043891487 148.0305200768947"
+ "A 166.63407933993605 132.04407218873035 0 0 1 495.8157837290847 280.07459226562503"
+ "z";
+ auto const pv = parse_svg_path(issue_d);
+ auto const issue_ellipse = Ellipse(Point(329.1817043891487, 280.07459226562503),
+ Point(166.63407933993605, 132.04407218873035), 0);
+
+ auto box = issue_ellipse.boundsExact();
+ box.expandBy(1.0);
+
+ g_random_set_seed(0xE111BB5E);
+ for (size_t _ = 0; _ < 10'000; _++) {
+ verify_windings(issue_ellipse, pv[0], random_point_in(box));
+ }
+}
+
+TEST_F(PathTest, SVGRoundtrip) {
+ SVGPathWriter sw;
+
+ Path transformed = diederik * (Rotate(1.23456789) * Scale(1e-8) * Translate(1e-9, 1e-9));
+
+ for (unsigned i = 0; i < 4; ++i) {
+ sw.setOptimize(i & 1);
+ sw.setUseShorthands(i & 2);
+
+ sw.feed(line);
+ //cout << sw.str() << endl;
+ Path line_svg = string_to_path(sw.str().c_str());
+ EXPECT_TRUE(line_svg == line);
+ sw.clear();
+
+ sw.feed(square);
+ //cout << sw.str() << endl;
+ Path square_svg = string_to_path(sw.str().c_str());
+ EXPECT_TRUE(square_svg == square);
+ sw.clear();
+
+ sw.feed(circle);
+ //cout << sw.str() << endl;
+ Path circle_svg = string_to_path(sw.str().c_str());
+ EXPECT_TRUE(circle_svg == circle);
+ sw.clear();
+
+ sw.feed(arcs);
+ //cout << sw.str() << endl;
+ Path arcs_svg = string_to_path(sw.str().c_str());
+ EXPECT_TRUE(arcs_svg == arcs);
+ sw.clear();
+
+ sw.feed(diederik);
+ //cout << sw.str() << endl;
+ Path diederik_svg = string_to_path(sw.str().c_str());
+ EXPECT_TRUE(diederik_svg == diederik);
+ sw.clear();
+
+ sw.feed(transformed);
+ //cout << sw.str() << endl;
+ Path transformed_svg = string_to_path(sw.str().c_str());
+ EXPECT_TRUE(transformed_svg == transformed);
+ sw.clear();
+
+ sw.feed(cmds);
+ //cout << sw.str() << endl;
+ Path cmds_svg = string_to_path(sw.str().c_str());
+ EXPECT_TRUE(cmds_svg == cmds);
+ sw.clear();
+ }
+}
+
+TEST_F(PathTest, Portion) {
+ PathTime a(0, 0.5), b(3, 0.5);
+ PathTime c(1, 0.25), d(1, 0.75);
+
+ EXPECT_EQ(square.portion(a, b), string_to_path("M 0.5, 0 L 1,0 1,1 0,1 0,0.5"));
+ EXPECT_EQ(square.portion(b, a), string_to_path("M 0,0.5 L 0,1 1,1 1,0 0.5,0"));
+ EXPECT_EQ(square.portion(a, b, true), string_to_path("M 0.5,0 L 0,0 0,0.5"));
+ EXPECT_EQ(square.portion(b, a, true), string_to_path("M 0,0.5 L 0,0 0.5,0"));
+ EXPECT_EQ(square.portion(c, d), string_to_path("M 1,0.25 L 1,0.75"));
+ EXPECT_EQ(square.portion(d, c), string_to_path("M 1,0.75 L 1,0.25"));
+ EXPECT_EQ(square.portion(c, d, true), string_to_path("M 1,0.25 L 1,0 0,0 0,1 1,1 1,0.75"));
+ EXPECT_EQ(square.portion(d, c, true), string_to_path("M 1,0.75 L 1,1 0,1 0,0 1,0 1,0.25"));
+
+ // verify that no matter how an endpoint is specified, the result is the same
+ PathTime a1(0, 1.0), a2(1, 0.0);
+ PathTime b1(2, 1.0), b2(3, 0.0);
+ Path result = string_to_path("M 1,0 L 1,1 0,1");
+ EXPECT_EQ(square.portion(a1, b1), result);
+ EXPECT_EQ(square.portion(a1, b2), result);
+ EXPECT_EQ(square.portion(a2, b1), result);
+ EXPECT_EQ(square.portion(a2, b2), result);
+}
+
+TEST_F(PathTest, AppendSegment) {
+ Path p_open = line, p_closed = line;
+ p_open.setStitching(true);
+ p_open.append(new LineSegment(Point(10,20), Point(10,25)));
+ EXPECT_EQ(p_open.size(), 3u);
+ EXPECT_NO_THROW(p_open.checkContinuity());
+
+ p_closed.setStitching(true);
+ p_closed.close(true);
+ p_closed.append(new LineSegment(Point(10,20), Point(10,25)));
+ EXPECT_EQ(p_closed.size(), 4u);
+ EXPECT_NO_THROW(p_closed.checkContinuity());
+}
+
+TEST_F(PathTest, AppendPath) {
+ p_open.append(p_add);
+ Path p_expected = string_to_path("M 0,0 L 0,5 5,5 5,0 -1,6 6,6");
+ EXPECT_EQ(p_open.size(), 5u);
+ EXPECT_EQ(p_open, p_expected);
+ EXPECT_NO_THROW(p_open.checkContinuity());
+
+ p_expected.close(true);
+ p_closed.append(p_add);
+ EXPECT_EQ(p_closed.size(), 6u);
+ EXPECT_EQ(p_closed, p_expected);
+ EXPECT_NO_THROW(p_closed.checkContinuity());
+}
+
+TEST_F(PathTest, AppendPortion) {
+ // A closed path with two curves:
+ Path bigon = string_to_path("M 0,0 Q 1,1 2,0 Q 1,-1 0,0 Z");
+ Path target{Point(0, 0)};
+
+ PathTime end_time{1, 1.0}; // End of the closed path
+ PathTime mid_time{1, 0.0}; // Middle of the closed path (juncture between the two curves)
+ bigon.appendPortionTo(target, end_time, mid_time, true /* do cross start */);
+
+ // We expect that the target path now contains the entire first curve "M 0,0 Q 1,1 2,0",
+ // since we started at the end of a closed path and requested to cross its start.
+ EXPECT_EQ(target.size(), 1);
+ EXPECT_EQ(target, string_to_path("M 0,0 Q 1,1 2,0"));
+
+ // Similar test but with reversal (swapped times)
+ Path target_reverse{Point(2, 0)};
+ bigon.appendPortionTo(target_reverse, mid_time, end_time, true /* do cross start please */);
+ // What do we expect? To cross start going from the midpoint to the endpoint requires
+ // not taking the obvious route (bigon[1]) but rather taking bigon[0] in reverse.
+ EXPECT_EQ(target_reverse.size(), 1);
+ EXPECT_EQ(target_reverse, string_to_path("M 2,0 Q 1,1 0,0"));
+
+ // Similar test but using start time
+ PathTime start_time{0, 0.0};
+ Path mid_target{Point(2, 0)};
+ bigon.appendPortionTo(mid_target, mid_time, start_time, true /* cross start to 0:0 */);
+ // We expect to go forward from mid_time and cross over the start to start_time.
+ EXPECT_EQ(mid_target.size(), 1);
+ EXPECT_EQ(mid_target, string_to_path("M 2,0 Q 1,-1 0,0"));
+
+ // Use start time with reversal
+ Path mid_reverse{Point(0, 0)};
+ bigon.appendPortionTo(mid_reverse, start_time, mid_time, true /* Cross start, going backwards. */);
+ // We expect that we don't go forwards from start_time to mid_time, but rather cross over the starting
+ // point and backtrack over bigon[1] to the midpoint.
+ EXPECT_EQ(mid_reverse.size(), 1);
+ EXPECT_EQ(mid_reverse, string_to_path("M 0,0 Q 1,-1 2,0"));
+}
+
+TEST_F(PathTest, ReplaceMiddle) {
+ p_open.replace(p_open.begin() + 1, p_open.begin() + 2, p_add);
+ EXPECT_EQ(p_open.size(), 5u);
+ EXPECT_NO_THROW(p_open.checkContinuity());
+
+ p_closed.replace(p_closed.begin() + 1, p_closed.begin() + 2, p_add);
+ EXPECT_EQ(p_closed.size(), 6u);
+ EXPECT_NO_THROW(p_closed.checkContinuity());
+}
+
+TEST_F(PathTest, ReplaceStart) {
+ p_open.replace(p_open.begin(), p_open.begin() + 2, p_add);
+ EXPECT_EQ(p_open.size(), 3u);
+ EXPECT_NO_THROW(p_open.checkContinuity());
+
+ p_closed.replace(p_closed.begin(), p_closed.begin() + 2, p_add);
+ EXPECT_EQ(p_closed.size(), 5u);
+ EXPECT_NO_THROW(p_closed.checkContinuity());
+}
+
+TEST_F(PathTest, ReplaceEnd) {
+ p_open.replace(p_open.begin() + 1, p_open.begin() + 3, p_add);
+ EXPECT_EQ(p_open.size(), 3u);
+ EXPECT_NO_THROW(p_open.checkContinuity());
+
+ p_closed.replace(p_closed.begin() + 1, p_closed.begin() + 3, p_add);
+ EXPECT_EQ(p_closed.size(), 5u);
+ EXPECT_NO_THROW(p_closed.checkContinuity());
+}
+
+TEST_F(PathTest, ReplaceClosing) {
+ p_open.replace(p_open.begin() + 1, p_open.begin() + 4, p_add);
+ EXPECT_EQ(p_open.size(), 3u);
+ EXPECT_NO_THROW(p_open.checkContinuity());
+
+ p_closed.replace(p_closed.begin() + 1, p_closed.begin() + 4, p_add);
+ EXPECT_EQ(p_closed.size(), 4u);
+ EXPECT_NO_THROW(p_closed.checkContinuity());
+}
+
+TEST_F(PathTest, ReplaceEverything) {
+ p_open.replace(p_open.begin(), p_open.end(), p_add);
+ EXPECT_EQ(p_open.size(), 1u);
+ EXPECT_NO_THROW(p_open.checkContinuity());
+
+ // TODO: in this specific case, it may make sense to set the path to open...
+ // Need to investigate what behavior is sensible here
+ p_closed.replace(p_closed.begin(), p_closed.end(), p_add);
+ EXPECT_EQ(p_closed.size(), 2u);
+ EXPECT_NO_THROW(p_closed.checkContinuity());
+}
+
+TEST_F(PathTest, EraseLast) {
+ p_open.erase_last();
+ Path p_expected = string_to_path("M 0,0 L 0,5 5,5");
+ EXPECT_EQ(p_open, p_expected);
+ EXPECT_NO_THROW(p_open.checkContinuity());
+}
+
+TEST_F(PathTest, AreNear) {
+ Path nudged_arcs1 = string_to_path("M 0,0 a 5,10 45 0 1 10,10.0000005 a 5,10 45 0 1 0,0 z");
+ Path nudged_arcs2 = string_to_path("M 0,0 a 5,10 45 0 1 10,10.00005 a 5,10 45 0 1 0,0 z");
+ EXPECT_EQ(are_near(diederik, diederik, 0), true);
+ EXPECT_EQ(are_near(cmds, diederik, 1e-6), false);
+ EXPECT_EQ(are_near(arcs, nudged_arcs1, 1e-6), true);
+ EXPECT_EQ(are_near(arcs, nudged_arcs2, 1e-6), false);
+}
+
+TEST_F(PathTest, Roots) {
+ Path path;
+ path.start(Point(0, 0));
+ path.appendNew<Geom::LineSegment>(Point(1, 1));
+ path.appendNew<Geom::LineSegment>(Point(2, 0));
+
+ EXPECT_FALSE(path.closed());
+
+ // Trivial case: make sure that path is not closed
+ std::vector<PathTime> roots = path.roots(0.5, Geom::X);
+ EXPECT_EQ(roots.size(), 1u);
+ EXPECT_EQ(path.valueAt(roots[0], Geom::Y), 0.5);
+
+ // Now check that it is closed if we make it so
+ path.close(true);
+ roots = path.roots(0.5, Geom::X);
+ EXPECT_EQ(roots.size(), 2u);
+}
+
+TEST_F(PathTest, PartingPoint)
+{
+ // === Test complete overlaps between identical curves ===
+ // Line segment
+ auto line = string_to_path("M 0,0 L 3.33, 7.77");
+ auto pt = parting_point(line, line);
+ EXPECT_TRUE(are_near(pt.point(), line.finalPoint()));
+ EXPECT_TRUE(are_near(pt.first.t, 1.0));
+
+ // Cubic Bézier
+ auto bezier = string_to_path("M 0,0 C 1,1 14,1 15,0");
+ pt = parting_point(bezier, bezier);
+ EXPECT_TRUE(are_near(pt.point(), bezier.finalPoint()));
+ EXPECT_TRUE(are_near(pt.first.t, 1.0));
+
+ // Eliptical arc
+ auto const arc = string_to_path("M 0,0 A 100,20 0,0,0 200,0");
+ pt = parting_point(arc, arc);
+ EXPECT_TRUE(are_near(pt.point(), arc.finalPoint()));
+ EXPECT_TRUE(are_near(pt.first.t, 1.0));
+
+ // === Test complete overlap between degree-elevated and degree-shrunk Béziers ===
+ auto artificially_cubic = string_to_path("M 0,0 C 10,10 20,10 30,0");
+ auto really_quadratic = string_to_path("M 0,0 Q 15,15 30,0");
+ pt = parting_point(artificially_cubic, really_quadratic);
+ EXPECT_TRUE(are_near(pt.point(), artificially_cubic.finalPoint()));
+ EXPECT_TRUE(are_near(pt.first.asFlatTime(), 1.0));
+ EXPECT_TRUE(are_near(pt.second.asFlatTime(), 1.0));
+
+ // === Test complete overlaps between a curve and its subdivision ===
+ // Straight line
+ line = string_to_path("M 0,0 L 15,15");
+ auto subdivided_line = string_to_path("M 0,0 L 3,3 L 4,4 L 9,9 L 15,15");
+ pt = parting_point(line, subdivided_line);
+ EXPECT_TRUE(are_near(pt.point(), line.finalPoint()));
+ EXPECT_TRUE(are_near(pt.first.t, 1.0));
+
+ // Cubic Bézier
+ bezier = string_to_path("M 0,0 C 0,40 50,40 50,0");
+ auto de_casteljau = string_to_path("M 0,0 C 0,10 3.125,17.5 7.8125,22.5 12.5,27.5 18.75,30 25,30"
+ " 31.25,30 37.5,27.5 42.1875,22.5 46.875,17.5 50,10 50,0");
+ pt = parting_point(bezier, de_casteljau);
+ EXPECT_TRUE(are_near(pt.point(), bezier.finalPoint()));
+ EXPECT_TRUE(are_near(pt.first.t, 1.0));
+
+ // Eliptical arc
+ auto subdivided_arc = string_to_path("M 0,0 A 100,20, 0,0,0 100,20 A 100,20 0,0,0 200,0");
+ pt = parting_point(arc, subdivided_arc);
+ EXPECT_TRUE(are_near(pt.point(), arc.finalPoint()));
+ EXPECT_TRUE(are_near(pt.first.t, 1.0));
+
+ // === Test complete overlap between different subdivisions ===
+ auto line1 = string_to_path("M 0,0 L 3,3 L 5,5 L 10,10");
+ auto line2 = string_to_path("M 0,0 L 2,2 L 4.2,4.2 L 4.5,4.5 L 6,6 L 10,10");
+ pt = parting_point(line1, line2);
+ EXPECT_TRUE(are_near(pt.point(), line1.finalPoint()));
+ EXPECT_TRUE(are_near(pt.first.asFlatTime(), line1.timeRange().max()));
+ EXPECT_TRUE(are_near(pt.second.asFlatTime(), line2.timeRange().max()));
+
+ // === Test complete overlaps in the presence of degenerate segments ===
+ // Straight line
+ line = string_to_path("M 0,0 L 15,15");
+ subdivided_line = string_to_path("M 0,0 L 3,3 H 3 V 3 L 3,3 L 4,4 H 4 V 4 L 4,4 L 9,9 H 9 L 15,15");
+ pt = parting_point(line, subdivided_line);
+ EXPECT_TRUE(are_near(pt.point(), line.finalPoint()));
+ EXPECT_TRUE(are_near(pt.first.asFlatTime(), 1.0));
+
+ // Eliptical arc
+ auto arc_degen = string_to_path("M 0,0 A 100,20, 0,0,0 100,20 H 100 V 20 L 100,20 A 100,20 0,0,0 200,0");
+ pt = parting_point(arc, arc_degen);
+ EXPECT_TRUE(are_near(pt.point(), arc.finalPoint()));
+ EXPECT_TRUE(are_near(pt.first.asFlatTime(), 1.0));
+
+ // === Paths that overlap but one is shorter than the other ===
+ // Straight lines
+ auto long_line = string_to_path("M 0,0 L 20,10");
+ auto short_line = string_to_path("M 0,0 L 4,2");
+ pt = parting_point(long_line, short_line);
+ EXPECT_TRUE(are_near(pt.point(), short_line.finalPoint()));
+ EXPECT_TRUE(are_near(pt.first.t, 0.2));
+ EXPECT_TRUE(are_near(pt.second.t, 1.0));
+
+ // Cubic Bézier
+ auto const s_shape = string_to_path("M 0,0 C 10, 0 0,10 10,10");
+ auto half_s = string_to_path("M 0,0 C 5,0 5,2.5 5,5");
+ pt = parting_point(s_shape, half_s);
+ EXPECT_TRUE(are_near(pt.first.t, 0.5));
+ EXPECT_TRUE(are_near(pt.second.t, 1.0));
+
+ // Elliptical arc
+ auto quarter_ellipse = string_to_path("M 0,0 A 100,20, 0,0,0 100,20");
+ pt = parting_point(arc, quarter_ellipse);
+ EXPECT_TRUE(are_near(pt.point(), quarter_ellipse.finalPoint()));
+ EXPECT_TRUE(are_near(pt.first.t, 0.5));
+ EXPECT_TRUE(are_near(pt.second.t, 1.0));
+
+ // === Paths that overlap initially but then they split ===
+ // Straight lines
+ auto boring_line = string_to_path("M 0,0 L 50,10");
+ auto line_then_arc = string_to_path("M 0,0 L 5,1 A 1,1 0,0,0 7,1");
+ pt = parting_point(boring_line, line_then_arc);
+ EXPECT_TRUE(are_near(pt.point(), Point(5, 1)));
+ EXPECT_TRUE(are_near(pt.first.t, 0.1));
+ EXPECT_TRUE(are_near(pt.second.asFlatTime(), 1.0));
+
+ // Cubic Bézier
+ auto half_s_then_line = string_to_path("M 0,0 C 5,0 5,2.5 5,5 L 10,10");
+ pt = parting_point(s_shape, half_s_then_line);
+ EXPECT_TRUE(are_near(pt.point(), Point(5, 5)));
+ EXPECT_TRUE(are_near(pt.first.t, 0.5));
+ EXPECT_TRUE(are_near(pt.second.asFlatTime(), 1.0));
+
+ // Elliptical arc
+ auto quarter_ellipse_then_quadratic = string_to_path("M 0,0 A 100,20, 0,0,0 100,20 Q 120,40 140,60");
+ pt = parting_point(arc, quarter_ellipse_then_quadratic);
+ EXPECT_TRUE(are_near(pt.point(), Point(100, 20)));
+ EXPECT_TRUE(are_near(pt.first.t, 0.5));
+ EXPECT_TRUE(are_near(pt.second.asFlatTime(), 1.0));
+
+ // === Paths that split at a common node ===
+ // Polylines
+ auto branch_90 = string_to_path("M 0,0 H 3 H 6 V 7");
+ auto branch_45 = string_to_path("M 0,0 H 2 H 6 L 7,7");
+ pt = parting_point(branch_90, branch_45);
+ EXPECT_TRUE(are_near(pt.point(), Point(6, 0)));
+ EXPECT_TRUE(are_near(pt.first.asFlatTime(), 2.0));
+ EXPECT_TRUE(are_near(pt.second.asFlatTime(), 2.0));
+
+ // Arcs
+ auto quarter_circle_then_horiz = string_to_path("M 0,0 A 1,1 0,0,0 1,1 H 10");
+ auto quarter_circle_then_slant = string_to_path("M 0,0 A 1,1 0,0,0 1,1 L 10, 1.1");
+ pt = parting_point(quarter_circle_then_horiz, quarter_circle_then_slant);
+ EXPECT_TRUE(are_near(pt.point(), Point(1, 1)));
+ EXPECT_TRUE(are_near(pt.first.asFlatTime(), 1.0));
+ EXPECT_TRUE(are_near(pt.second.asFlatTime(), 1.0));
+
+ // Last common nodes followed by degenerates
+ auto degen_horiz = string_to_path("M 0,0 A 1,1 0,0,0 1,1 V 1 H 1 L 1,1 H 10");
+ auto degen_slant = string_to_path("M 0,0 A 1,1 0,0,0 1,1 V 1 H 1 L 1,1 L 10, 1.1");
+ pt = parting_point(quarter_circle_then_horiz, quarter_circle_then_slant);
+ EXPECT_TRUE(are_near(pt.point(), Point(1, 1)));
+
+ // === Paths that split at the starting point ===
+ auto vertical = string_to_path("M 0,0 V 1");
+ auto quarter = string_to_path("M 0,0 A 1,1 0,0,0, 1,1");
+ pt = parting_point(vertical, quarter);
+ EXPECT_TRUE(are_near(pt.point(), Point(0, 0)));
+ EXPECT_TRUE(are_near(pt.first.asFlatTime(), 0.0));
+ EXPECT_TRUE(are_near(pt.second.asFlatTime(), 0.0));
+
+ // === Symmetric split (both legs of the same length) ===
+ auto left_leg = string_to_path("M 1,0 L 0,10");
+ auto right_leg = string_to_path("M 1,0 L 2,10");
+ pt = parting_point(left_leg, right_leg);
+ EXPECT_TRUE(are_near(pt.point(), Point(1, 0)));
+ EXPECT_TRUE(are_near(pt.first.asFlatTime(), 0.0));
+ EXPECT_TRUE(are_near(pt.second.asFlatTime(), 0.0));
+
+ // === Different starting points ===
+ auto start_at_0_0 = string_to_path("M 0,0 C 1,0 0,1 1,1");
+ auto start_at_10_10 = string_to_path("M 10,10 L 50,50");
+ pt = parting_point(start_at_0_0, start_at_10_10);
+ EXPECT_TRUE(are_near(pt.point(), Point (5,5)));
+ EXPECT_DOUBLE_EQ(pt.first.t, -1.0);
+ EXPECT_DOUBLE_EQ(pt.second.t, -1.0);
+ EXPECT_EQ(pt.first.curve_index, 0);
+ EXPECT_EQ(pt.second.curve_index, 0);
+}
+
+TEST_F(PathTest, InitialFinalTangents) {
+ // Test tangents for an open path
+ auto L_shape = string_to_path("M 1,1 H 0 V 0");
+ EXPECT_EQ(L_shape.initialUnitTangent(), Point(-1.0, 0.0));
+ EXPECT_EQ(L_shape.finalUnitTangent(), Point(0.0, -1.0));
+
+ // Closed path with non-degenerate closing segment
+ auto triangle = string_to_path("M 0,0 H 2 L 0,3 Z");
+ EXPECT_EQ(triangle.initialUnitTangent(), Point(1.0, 0.0));
+ EXPECT_EQ(triangle.finalUnitTangent(), Point(0.0, -1.0));
+
+ // Closed path with a degenerate closing segment
+ auto full360 = string_to_path("M 0,0 A 1,1, 0,1,1, 0,2 A 1,1 0,1,1 0,0 Z");
+ EXPECT_EQ(full360.initialUnitTangent(), Point(1.0, 0.0));
+ EXPECT_EQ(full360.finalUnitTangent(), Point(1.0, 0.0));
+
+ // Test multiple degenerate segments at the start
+ auto start_degen = string_to_path("M 0,0 L 0,0 H 0 V 0 Q 1,0 1,1");
+ EXPECT_EQ(start_degen.initialUnitTangent(), Point(1.0, 0.0));
+
+ // Test multiple degenerate segments at the end
+ auto end_degen = string_to_path("M 0,0 L 1,1 H 1 V 1 L 1,1");
+ double comp = 1.0 / sqrt(2.0);
+ EXPECT_EQ(end_degen.finalUnitTangent(), Point(comp, comp));
+
+ // Test a long and complicated path with both tangents along the positive x-axis.
+ auto complicated = string_to_path("M 0,0 H 0 L 1,0 C 2,1 3,2 1,0 L 1,0 H 1 Q 2,3 0,5 H 2");
+ EXPECT_EQ(complicated.initialUnitTangent(), Point(1.0, 0.0));
+ EXPECT_EQ(complicated.finalUnitTangent(), Point(1.0, 0.0));
+}
+
+TEST_F(PathTest, WithoutDegenerates) {
+ // Ensure nothing changes when there are no degenerate segments to remove.
+ auto plain_open = string_to_path("M 0,0 Q 5,5 10,10");
+ EXPECT_EQ(plain_open, plain_open.withoutDegenerateCurves());
+
+ auto closed_nondegen_closing = string_to_path("M 0,0 L 5,5 H 0 Z");
+ EXPECT_EQ(closed_nondegen_closing,closed_nondegen_closing.withoutDegenerateCurves());
+
+ // Ensure that a degenerate closing segment is left alone.
+ auto closed_degen_closing = string_to_path("M 0,0 L 2,4 H 0 L 0,0 Z");
+ EXPECT_EQ(closed_degen_closing, closed_degen_closing.withoutDegenerateCurves());
+
+ // Ensure that a trivial path is left alone (both open and closed).
+ auto trivial_open = string_to_path("M 0,0");
+ EXPECT_EQ(trivial_open, trivial_open.withoutDegenerateCurves());
+
+ auto trivial_closed = string_to_path("M 0,0 Z");
+ EXPECT_EQ(trivial_closed, trivial_closed.withoutDegenerateCurves());
+
+ // Ensure that initial degenerate segments are removed
+ auto degen_start = string_to_path("M 0,0 L 0,0 H 0 V 0 Q 5,5 10,10");
+ auto degen_start_cleaned = degen_start.withoutDegenerateCurves();
+ EXPECT_EQ(degen_start_cleaned, string_to_path("M 0,0 Q 5,5 10,10"));
+ EXPECT_NE(degen_start.size(), degen_start_cleaned.size());
+
+ // Ensure that degenerate segments are removed from the middle
+ auto degen_middle = string_to_path("M 0,0 L 1,1 H 1 V 1 L 1,1 Q 6,6 10,10");
+ auto degen_middle_cleaned = degen_middle.withoutDegenerateCurves();
+ EXPECT_EQ(degen_middle_cleaned, string_to_path("M 0,0 L 1,1 Q 6,6 10,10"));
+ EXPECT_NE(degen_middle.size(), degen_middle_cleaned.size());
+
+ // Ensure that degenerate segment are removed from the end of an open path
+ auto end_open = string_to_path("M 0,0 L 1,1 H 1 V 1 L 1,1");
+ auto end_open_cleaned = end_open.withoutDegenerateCurves();
+ EXPECT_EQ(end_open_cleaned, string_to_path("M 0,0 L 1,1"));
+ EXPECT_NE(end_open.size(), end_open_cleaned.size());
+
+ // Ensure removal of degenerates just before the closing segment
+ auto end_nondegen = string_to_path("M 0,0 L 1,1 L 0,1 H 0 V 1 Z");
+ auto end_nondegen_cleaned = end_nondegen.withoutDegenerateCurves();
+ EXPECT_EQ(end_nondegen_cleaned, string_to_path("M 0,0 L 1,1 L 0,1 Z"));
+ EXPECT_NE(end_nondegen.size(), end_nondegen_cleaned.size());
+}
+
+/** Test Path::extrema() */
+TEST_F(PathTest, GetExtrema) {
+
+ // Circle of radius 4.5 centered at (-4.5, 0).
+ auto extrema_x = circle.extrema(X);
+ EXPECT_EQ(extrema_x.min_point, Point(-9, 0));
+ EXPECT_EQ(extrema_x.max_point, Point( 0, 0));
+ EXPECT_DOUBLE_EQ(extrema_x.min_time.asFlatTime(), 1.0);
+ EXPECT_DOUBLE_EQ(extrema_x.max_time.asFlatTime(), 0.0);
+ EXPECT_EQ(extrema_x.glance_direction_at_min, -1.0);
+ EXPECT_EQ(extrema_x.glance_direction_at_max, 1.0);
+
+ auto extrema_y = circle.extrema(Y);
+ EXPECT_EQ(extrema_y.min_point, Point(-4.5, -4.5));
+ EXPECT_EQ(extrema_y.max_point, Point(-4.5, 4.5));
+ EXPECT_DOUBLE_EQ(extrema_y.min_time.asFlatTime(), 1.5);
+ EXPECT_DOUBLE_EQ(extrema_y.max_time.asFlatTime(), 0.5);
+ EXPECT_FLOAT_EQ(extrema_y.glance_direction_at_min, 1.0);
+ EXPECT_FLOAT_EQ(extrema_y.glance_direction_at_max, -1.0);
+
+ // Positively oriented unit square
+ extrema_x = square.extrema(X);
+ EXPECT_DOUBLE_EQ(extrema_x.min_point[X], 0.0);
+ EXPECT_DOUBLE_EQ(extrema_x.max_point[X], 1.0);
+ EXPECT_FLOAT_EQ(extrema_x.glance_direction_at_min, -1.0);
+ EXPECT_FLOAT_EQ(extrema_x.glance_direction_at_max, 1.0);
+
+ extrema_y = square.extrema(Y);
+ EXPECT_DOUBLE_EQ(extrema_y.min_point[Y], 0.0);
+ EXPECT_DOUBLE_EQ(extrema_y.max_point[Y], 1.0);
+ EXPECT_FLOAT_EQ(extrema_y.glance_direction_at_min, 1.0);
+ EXPECT_FLOAT_EQ(extrema_y.glance_direction_at_max, -1.0);
+
+ // Path glancing its min X line while going towards negative Y
+ auto down_glance = string_to_path("M 1,18 L 0,0 1,-20");
+ extrema_x = down_glance.extrema(X);
+ EXPECT_EQ(extrema_x.min_point, Point(0, 0));
+ EXPECT_FLOAT_EQ(extrema_x.glance_direction_at_min, -1.0);
+ EXPECT_DOUBLE_EQ(extrema_x.min_time.asFlatTime(), 1.0);
+
+ // Similar but not at a node
+ auto down_glance_smooth = string_to_path("M 1,20 C 0,20 0,-20 1,-20");
+ extrema_x = down_glance_smooth.extrema(X);
+ EXPECT_TRUE(are_near(extrema_x.min_point[Y], 0.0));
+ EXPECT_FLOAT_EQ(extrema_x.glance_direction_at_min, -1.0);
+ EXPECT_DOUBLE_EQ(extrema_x.min_time.asFlatTime(), 0.5);
+
+ // Path coming down to the min X and then retreating horizontally
+ auto retreat = string_to_path("M 1,20 L 0,0 H 5 L 4,-20");
+ extrema_x = retreat.extrema(X);
+ EXPECT_EQ(extrema_x.min_point, Point(0, 0));
+ EXPECT_EQ(extrema_x.max_point, Point(5, 0));
+ EXPECT_FLOAT_EQ(extrema_x.glance_direction_at_min, -1.0);
+ EXPECT_FLOAT_EQ(extrema_x.glance_direction_at_max, -1.0);
+ EXPECT_DOUBLE_EQ(extrema_x.min_time.asFlatTime(), 1.0);
+ EXPECT_DOUBLE_EQ(extrema_x.max_time.asFlatTime(), 2.0);
+
+ // Perfectly horizontal path
+ auto horizontal = string_to_path("M 0,0 H 12");
+ extrema_x = horizontal.extrema(X);
+ extrema_y = horizontal.extrema(Y);
+ EXPECT_EQ(extrema_x.min_point, Point(0, 0));
+ EXPECT_EQ(extrema_x.max_point, Point(12, 0));
+ EXPECT_DOUBLE_EQ(extrema_y.min_point[Y], 0.0);
+ EXPECT_DOUBLE_EQ(extrema_y.max_point[Y], 0.0);
+ EXPECT_FLOAT_EQ(extrema_x.glance_direction_at_min, 0.0);
+ EXPECT_FLOAT_EQ(extrema_x.glance_direction_at_max, 0.0);
+ EXPECT_FLOAT_EQ(extrema_y.glance_direction_at_min, 1.0);
+ EXPECT_FLOAT_EQ(extrema_y.glance_direction_at_max, 1.0);
+ EXPECT_DOUBLE_EQ(extrema_x.min_time.asFlatTime(), 0.0);
+ EXPECT_DOUBLE_EQ(extrema_x.max_time.asFlatTime(), 1.0);
+
+ // Perfectly vertical path
+ auto vertical = string_to_path("M 0,0 V 42");
+ extrema_y = vertical.extrema(Y);
+ extrema_x = vertical.extrema(X);
+ EXPECT_DOUBLE_EQ(extrema_x.min_point[Y], 0.0);
+ EXPECT_DOUBLE_EQ(extrema_x.max_point[Y], 0.0);
+ EXPECT_EQ(extrema_y.min_point, Point(0, 0));
+ EXPECT_EQ(extrema_y.max_point, Point(0, 42));
+ EXPECT_FLOAT_EQ(extrema_x.glance_direction_at_min, 1.0);
+ EXPECT_FLOAT_EQ(extrema_x.glance_direction_at_max, 1.0);
+ EXPECT_FLOAT_EQ(extrema_y.glance_direction_at_min, 0.0);
+ EXPECT_FLOAT_EQ(extrema_y.glance_direction_at_max, 0.0);
+ EXPECT_DOUBLE_EQ(extrema_y.min_time.asFlatTime(), 0.0);
+ EXPECT_DOUBLE_EQ(extrema_y.max_time.asFlatTime(), 1.0);
+
+ // Detect downward glance at the closing point (degenerate closing segment)
+ auto closed = string_to_path("M 0,0 L 1,-2 H 3 V 5 H 1 L 0,0 Z");
+ extrema_x = closed.extrema(X);
+ EXPECT_EQ(extrema_x.min_point, Point(0, 0));
+ EXPECT_FLOAT_EQ(extrema_x.glance_direction_at_min, -1.0);
+
+ // Same but with a non-degenerate closing segment
+ auto closed_nondegen = string_to_path("M 0,0 L 1,-2 H 3 V 5 H 1 Z");
+ extrema_x = closed_nondegen.extrema(X);
+ EXPECT_EQ(extrema_x.min_point, Point(0, 0));
+ EXPECT_FLOAT_EQ(extrema_x.glance_direction_at_min, -1.0);
+
+ // Collapsed Bezier not glancing up nor down
+ auto collapsed = string_to_path("M 10, 0 Q -10 0 10, 0");
+ extrema_x = collapsed.extrema(X);
+ EXPECT_EQ(extrema_x.min_point, Point(0, 0));
+ EXPECT_EQ(extrema_x.max_point, Point(10, 0));
+ EXPECT_FLOAT_EQ(extrema_x.glance_direction_at_min, 0.0);
+ EXPECT_FLOAT_EQ(extrema_x.glance_direction_at_max, 0.0);
+
+ // Degenerate segments at min X
+ auto degen = string_to_path("M 0.01,20 L 0, 0 H 0 V 0 L 0,0 V 0 L 0.02 -30");
+ extrema_x = degen.extrema(X);
+ EXPECT_EQ(extrema_x.min_point, Point(0, 0));
+ EXPECT_FLOAT_EQ(extrema_x.glance_direction_at_min, -1.0);
+}
+
+/** Regression test for issue https://gitlab.com/inkscape/lib2geom/-/issues/50 */
+TEST_F(PathTest, PizzaSlice)
+{
+ auto pv = parse_svg_path("M 0 0 L 0.30901699437494745 0.9510565162951535 "
+ "A 1 1 0 0 1 -0.8090169943749473 0.5877852522924732 z");
+ auto &sector = pv[0];
+ Path piece;
+ EXPECT_NO_THROW(piece = sector.portion(PathTime(0, 0.0), PathTime(2, 0.0), false));
+ EXPECT_FALSE(piece.closed());
+ EXPECT_TRUE(piece.size() == 2 ||
+ (piece.size() == 3 && piece[2].isDegenerate()));
+ EXPECT_EQ(piece.finalPoint(), Point(-0.8090169943749473, 0.5877852522924732));
+
+ // Test slicing in the middle of an arc and past its end
+ pv = parse_svg_path("M 0,0 H 1 A 1,1 0 0 1 0.3080657835086775,0.9513650577098072 z");
+ EXPECT_NO_THROW(piece = pv[0].portion(PathTime(1, 0.5), PathTime(2, 1.0)));
+ EXPECT_FALSE(piece.closed());
+ EXPECT_EQ(piece.finalPoint(), pv[0].finalPoint());
+
+ // Test slicing from before the start to a point on the arc
+ EXPECT_NO_THROW(piece = pv[0].portion(PathTime(0, 0.5), PathTime(1, 0.5)));
+ EXPECT_FALSE(piece.closed());
+ EXPECT_EQ(piece.initialPoint(), pv[0].pointAt(PathTime(0, 0.5)));
+ EXPECT_EQ(piece.finalPoint(), pv[0].pointAt(PathTime(1, 0.5)));
+
+ // Test slicing a part of the arc
+ EXPECT_NO_THROW(piece = pv[0].portion(PathTime(1, 0.25), PathTime(1, 0.75)));
+ EXPECT_FALSE(piece.closed());
+ EXPECT_EQ(piece.size(), 1);
+
+ // Test slicing in reverse
+ EXPECT_NO_THROW(piece = pv[0].portion(PathTime(2, 1.0), PathTime(1, 0.5)));
+ EXPECT_FALSE(piece.closed());
+ EXPECT_EQ(piece.finalPoint(), pv[0].pointAt(PathTime(1, 0.5)));
+
+ EXPECT_NO_THROW(piece = pv[0].portion(PathTime(1, 0.5), PathTime(0, 0.5)));
+ EXPECT_FALSE(piece.closed());
+ EXPECT_EQ(piece.initialPoint(), pv[0].pointAt(PathTime(1, 0.5)));
+ EXPECT_EQ(piece.finalPoint(), pv[0].pointAt(PathTime(0, 0.5)));
+
+ EXPECT_NO_THROW(piece = pv[0].portion(PathTime(1, 0.75), PathTime(1, 0.25)));
+ EXPECT_FALSE(piece.closed());
+ EXPECT_EQ(piece.size(), 1);
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/tests/pick.h b/src/3rdparty/2geom/tests/pick.h
new file mode 100644
index 0000000..3e43bd5
--- /dev/null
+++ b/src/3rdparty/2geom/tests/pick.h
@@ -0,0 +1,172 @@
+/*
+ * Routines for generating anything randomly
+ *
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef _GEOM_SL_PICK_H_
+#define _GEOM_SL_PICK_H_
+
+
+#include <2geom/symbolic/multipoly.h>
+#include <2geom/symbolic/matrix.h>
+
+inline
+size_t pick_uint(size_t max)
+{
+ return (std::rand() % (max+1));
+}
+
+inline
+int pick_int(size_t max)
+{
+ int s = pick_uint(2);
+ if (s == 0) s = -1;
+ return s * (std::rand() % (max+1));
+}
+
+inline
+Geom::SL::multi_index_type pick_multi_index(size_t N, size_t max)
+{
+ Geom::SL::multi_index_type I(N);
+ for (size_t i = 0; i < I.size(); ++i)
+ I[i] = pick_uint(max);
+ return I;
+}
+
+template <size_t N>
+inline
+typename Geom::SL::mvpoly<N, double>::type
+pick_polyN(size_t d, size_t m)
+{
+ typename Geom::SL::mvpoly<N, double>::type p;
+ size_t d0 = pick_uint(d);
+ for (size_t i = 0; i <= d0; ++i)
+ {
+ p.coefficient(i, pick_polyN<N-1>(d, m));
+ }
+ return p;
+}
+
+template <>
+inline
+double pick_polyN<0>(size_t /*d*/, size_t m)
+{
+ return pick_int(m);
+}
+
+
+template <size_t N>
+inline
+typename Geom::SL::mvpoly<N, double>::type
+pick_poly_max(size_t d, size_t m)
+{
+ typename Geom::SL::mvpoly<N, double>::type p;
+ for (size_t i = 0; i <= d; ++i)
+ {
+ p.coefficient(i, pick_poly_max<N-1>(d-i, m));
+ }
+ return p;
+}
+
+template <>
+inline
+double pick_poly_max<0>(size_t /*d*/, size_t m)
+{
+ return pick_int(m);
+}
+
+
+template <size_t N>
+inline
+Geom::SL::MultiPoly<N, double>
+pick_multipoly(size_t d, size_t m)
+{
+ return Geom::SL::MultiPoly<N, double>(pick_polyN<N>(d, m));
+}
+
+template <size_t N>
+inline
+Geom::SL::MultiPoly<N, double>
+pick_multipoly_max(size_t d, size_t m)
+{
+ return Geom::SL::MultiPoly<N, double>(pick_poly_max<N>(d, m));
+}
+
+
+
+inline
+Geom::SL::Matrix< Geom::SL::MultiPoly<2, double> >
+pick_matrix(size_t n, size_t d, size_t m)
+{
+ Geom::SL::Matrix< Geom::SL::MultiPoly<2, double> > M(n, n);
+ for (size_t i = 0; i < n; ++i)
+ {
+ for (size_t j = 0; j < n; ++j)
+ {
+ M(i,j) = pick_multipoly_max<2>(d, m);
+ }
+ }
+ return M;
+}
+
+
+inline
+Geom::SL::Matrix< Geom::SL::MultiPoly<2, double> >
+pick_symmetric_matrix(size_t n, size_t d, size_t m)
+{
+ Geom::SL::Matrix< Geom::SL::MultiPoly<2, double> > M(n, n);
+ for (size_t i = 0; i < n; ++i)
+ {
+ for (size_t j = 0; j < i; ++j)
+ {
+ M(i,j) = M(j,i) = pick_multipoly_max<2>(d, m);
+ }
+ }
+ for (size_t i = 0; i < n; ++i)
+ {
+ M(i,i) = pick_multipoly_max<2>(d, m);
+ }
+ return M;
+}
+
+
+#endif // _GEOM_SL_PICK_H_
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/tests/planar-graph-test.cpp b/src/3rdparty/2geom/tests/planar-graph-test.cpp
new file mode 100644
index 0000000..f19e2eb
--- /dev/null
+++ b/src/3rdparty/2geom/tests/planar-graph-test.cpp
@@ -0,0 +1,457 @@
+/** @file
+ * @brief Unit tests for PlanarGraph class template
+ */
+/*
+ * Authors:
+ * Rafał Siejakowski <rs@rs-math.net>
+ *
+ * Copyright 2022 the Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <gtest/gtest.h>
+#include <iostream>
+
+#include <2geom/point.h>
+#include <2geom/pathvector.h>
+#include <2geom/svg-path-parser.h>
+#include <2geom/svg-path-writer.h>
+
+#include "planar-graph.h"
+#include "testing.h"
+
+using namespace Geom;
+
+#define PV(d) (parse_svg_path(d))
+#define PTH(d) (std::move(PV(d)[0]))
+#define REV(d) ((PV(d)[0]).reversed())
+
+/** An edge label for the purpose of tests. */
+struct TestLabel
+{
+ unsigned reversal_count = 0, merge_count = 0, detachment_count = 0;
+ void onReverse() { reversal_count++; }
+ void onMergeWith(TestLabel const &) { merge_count++; }
+ void onDetach() { detachment_count++; }
+};
+
+using TestGraph = PlanarGraph<TestLabel>;
+
+static std::vector<TestLabel> extract_labels(TestGraph const &graph)
+{
+ // Find labels of edges remaining in the graph.
+ std::vector<TestLabel> result;
+ for (auto &e : graph.getEdges()) {
+ if (!e.detached) {
+ result.push_back(e.label);
+ }
+ }
+ return result;
+}
+
+class PlanarGraphTest : public ::testing::Test
+{
+};
+
+/** Test edge insertion and vertex clumping to within the tolerance. */
+TEST(PlanarGraphTest, EdgeInsertion)
+{
+ double const precision = 1e-3;
+ auto graph = TestGraph(precision);
+ graph.insertEdge(PTH("M 0, 0 L 1, 0"));
+ graph.insertEdge(PTH("M 0, 1 L 1, 1")); // } Endpoints near
+ graph.insertEdge(PTH("M 1, 0 L 1, 1.0009")); // } but not exact.
+
+ auto vertices = graph.getVertices();
+
+ // Test vertex clumping within the given precision
+ EXPECT_EQ(vertices.size(), 4);
+ EXPECT_EQ(graph.numEdges(), 3);
+
+ // Test lexicographic vertex position sorting by X and then Y
+ EXPECT_EQ(vertices.front().point(), Point(0, 0));
+ auto after = std::next(vertices.begin());
+ EXPECT_EQ(after->point(), Point(0, 1));
+ ++after;
+ EXPECT_EQ(after->point(), Point(1, 0));
+ EXPECT_TRUE(are_near(vertices.back().point(), Point(1, 1), precision));
+
+ EXPECT_FALSE(graph.isRegularized());
+}
+
+/** Test PlanarGraph<T>::insertDetached(). */
+TEST(PlanarGraphTest, InsertDetached)
+{
+ TestGraph graph;
+ auto detached = graph.insertDetached(PTH("M 0,0 A 1,1 0,0,1 2,0 V -2 H 0 Z"));
+
+ auto const &edges = graph.getEdges();
+ EXPECT_EQ(edges.size(), 1);
+ EXPECT_TRUE(edges.at(detached).detached);
+ EXPECT_TRUE(edges.at(detached).inserted_as_detached);
+
+ EXPECT_EQ(graph.numVertices(), 0);
+ EXPECT_EQ(graph.numEdges(false), 0);
+ EXPECT_TRUE(graph.isRegularized());
+}
+
+/** Test signed area calculation. */
+TEST(PlanarGraphTest, ClosedPathArea)
+{
+ // Square with counter-clockwise oriented boundary, when imagining that the y-axis
+ // points up – expect the area to be +1.
+ auto square_positive = PTH("M 0,0 H 1 V 1 H 0 Z");
+ EXPECT_DOUBLE_EQ(TestGraph::closedPathArea(square_positive), 1.0);
+
+ // Expect negative area for a negatively oriented path.
+ auto triangle_negative = PTH("M 0,0 V 1 L 1,1 Z");
+ EXPECT_DOUBLE_EQ(TestGraph::closedPathArea(triangle_negative), -0.5);
+}
+
+/** Test the detection of direction of deviation of initially tangent paths. */
+TEST(PlanarGraphTest, Deviation)
+{
+ auto vertical_up = PTH("M 0,0 V 1");
+ auto arc_right1 = PTH("M 0,0 A 1,1 0,1,0 2,0");
+ auto arc_left1 = PTH("M 0,0 A 1,1 0,1,1 -2,0");
+ auto arc_right2 = PTH("M 0,0 A 2,2 0,1,0, 4,0");
+ auto arc_left2 = PTH("M 0,0 A 2,2 0,1,1 -4,0");
+ // A very "flat" Bézier curve deviating to the right but slower than the large arc
+ auto bezier_right = PTH("M 0,0 C 0,50 1,20 2,10");
+
+ EXPECT_TRUE(TestGraph::deviatesLeft(arc_left1, arc_left2));
+ EXPECT_TRUE(TestGraph::deviatesLeft(arc_left2, vertical_up));
+ EXPECT_TRUE(TestGraph::deviatesLeft(vertical_up, arc_right2));
+ EXPECT_TRUE(TestGraph::deviatesLeft(vertical_up, bezier_right));
+ EXPECT_TRUE(TestGraph::deviatesLeft(bezier_right, arc_right2));
+ EXPECT_TRUE(TestGraph::deviatesLeft(arc_right2, arc_right1));
+ EXPECT_TRUE(TestGraph::deviatesLeft(arc_left1, arc_right1));
+ EXPECT_TRUE(TestGraph::deviatesLeft(arc_left2, arc_right1));
+
+ EXPECT_FALSE(TestGraph::deviatesLeft(arc_right1, vertical_up));
+ EXPECT_FALSE(TestGraph::deviatesLeft(arc_right1, arc_right2));
+ EXPECT_FALSE(TestGraph::deviatesLeft(vertical_up, arc_left2));
+ EXPECT_FALSE(TestGraph::deviatesLeft(arc_left2, arc_left1));
+ EXPECT_FALSE(TestGraph::deviatesLeft(arc_right1, arc_left1));
+ EXPECT_FALSE(TestGraph::deviatesLeft(arc_right1, arc_left2));
+}
+
+/** Test sorting of incidences at a vertex by the outgoing heading. */
+TEST(PlanarGraphTest, BasicAzimuthalSort)
+{
+ TestGraph graph;
+
+ // Imagine the Y-axis pointing up (as in mathematics)!
+ bool const clockwise = true;
+ unsigned const num_rays = 9;
+ unsigned edges[num_rays];
+
+ // Insert the edges randomly but store them in what we know to be the
+ // clockwise order of outgoing azimuths from the vertex at the origin.
+ edges[7] = graph.insertEdge(PTH("M -0.2, -1 L 0, 0"));
+ edges[1] = graph.insertEdge(PTH("M -1, 0.2 L 0, 0"));
+ edges[4] = graph.insertEdge(PTH("M 0, 0 L 1, 0.2"));
+ edges[6] = graph.insertEdge(PTH("M 0.1, -1 L 0, 0"));
+ edges[2] = graph.insertEdge(PTH("M 0, 0 L -0.3, 1"));
+ edges[0] = graph.insertEdge(PTH("M -1, 0 H 0"));
+ edges[5] = graph.insertEdge(PTH("M 0, 0 L 1, -0.2"));
+ edges[3] = graph.insertEdge(PTH("M 0.2, 1 L 0, 0"));
+ edges[8] = graph.insertEdge(PTH("M -1, -0.1 L 0, 0"));
+
+ // We expect the incidence to edges[0] to be the last one
+ // in the sort order so it should appear first when going clockwise.
+ auto [origin, incidence] = graph.getIncidence(edges[0], TestGraph::Incidence::END);
+ ASSERT_TRUE(origin);
+ ASSERT_TRUE(incidence);
+
+ // Expect ±pi as the azimuth
+ EXPECT_DOUBLE_EQ(std::abs(incidence->azimuth), M_PI);
+
+ // Test sort order
+ for (unsigned i = 0; i < num_rays; i++) {
+ EXPECT_EQ(incidence->index, edges[i]);
+ incidence = (TestGraph::Incidence *)&graph.nextIncidence(*origin, *incidence, clockwise);
+ }
+}
+
+/** Test retrieval of a path inserted as an edge in both orientations. */
+TEST(PlanarGraphTest, PathRetrieval)
+{
+ TestGraph graph;
+
+ Path const path = PTH("M 0,0 L 1,1 C 2,2 4,2 5,1");
+ Path const htap = path.reversed();
+
+ auto edge = graph.insertEdge(path);
+
+ ASSERT_EQ(graph.numEdges(), 1);
+
+ auto [start_point, start_incidence] = graph.getIncidence(edge, TestGraph::Incidence::START);
+ ASSERT_TRUE(start_point);
+ ASSERT_TRUE(start_incidence);
+ EXPECT_EQ(graph.getOutgoingPath(start_incidence), path);
+ EXPECT_EQ(graph.getIncomingPath(start_incidence), htap);
+
+ auto [end_point, end_incidence] = graph.getIncidence(edge, TestGraph::Incidence::END);
+ ASSERT_TRUE(end_point);
+ ASSERT_TRUE(end_incidence);
+ EXPECT_EQ(graph.getIncomingPath(end_incidence), path);
+ EXPECT_EQ(graph.getOutgoingPath(end_incidence), htap);
+}
+
+/** Make sure the edge labels are correctly stored. */
+TEST(PlanarGraphTest, LabelRetrieval)
+{
+ TestGraph graph;
+ TestLabel label;
+
+ label.reversal_count = 420;
+ label.merge_count = 69;
+ label.detachment_count = 111;
+
+ auto edge = graph.insertEdge(PTH("M 0,0 L 1,1"), std::move(label));
+
+ auto retrieved = graph.getEdge(edge).label;
+ EXPECT_EQ(retrieved.reversal_count, 420);
+ EXPECT_EQ(retrieved.merge_count, 69);
+ EXPECT_EQ(retrieved.detachment_count, 111);
+}
+
+/** Regularization of duplicate edges. */
+TEST(PlanarGraphTest, MergeDuplicate)
+{
+ char const *const d = "M 2, 3 H 0 C 1,4 1,5 0,6 H 10 L 8, 0";
+ char const *const near_d = "M 2.0009,3 H 0 C 1,4 1,5 0,6 H 10.0009 L 8, 0.0005";
+
+ // Test removal of perfect overlap:
+ TestGraph graph;
+ graph.insertEdge(PTH(d));
+ graph.insertEdge(PTH(d)); // exact duplicate
+ graph.regularize();
+
+ EXPECT_TRUE(graph.isRegularized());
+
+ auto remaining = extract_labels(graph);
+
+ // Expect there to be only 1 edge after regularization.
+ ASSERT_EQ(remaining.size(), 1);
+
+ EXPECT_EQ(remaining[0].merge_count, 1); // expect one merge,
+ EXPECT_EQ(remaining[0].reversal_count, 0); // no reversals,
+ EXPECT_EQ(remaining[0].detachment_count, 0); // no detachments.
+
+ // Test removal of imperfect overlaps within numerical precision
+ TestGraph fuzzy{1e-3};
+ fuzzy.insertEdge(PTH(d));
+ fuzzy.insertEdge(PTH(near_d));
+ fuzzy.regularize();
+
+ EXPECT_TRUE(fuzzy.isRegularized());
+
+ auto fuzmaining = extract_labels(fuzzy);
+ ASSERT_EQ(fuzmaining.size(), 1);
+
+ EXPECT_EQ(fuzmaining[0].merge_count, 1); // expect one merge,
+ EXPECT_EQ(fuzmaining[0].reversal_count, 0); // no reversals,
+ EXPECT_EQ(fuzmaining[0].detachment_count, 0); // no detachments.
+
+ // Test overlap of edges with oppositie orientations.
+ TestGraph twoway;
+ twoway.insertEdge(PTH(d));
+ twoway.insertEdge(REV(d));
+ twoway.regularize();
+
+ EXPECT_TRUE(twoway.isRegularized());
+
+ auto left = extract_labels(twoway);
+ ASSERT_EQ(left.size(), 1);
+
+ EXPECT_EQ(left[0].merge_count, 1); // expect one merge,
+ EXPECT_TRUE(left[0].reversal_count == 0 || left[0].reversal_count == 1); // 0 or 1 reversals
+ EXPECT_EQ(left[0].detachment_count, 0); // no detachments.
+}
+
+/** Regularization of a shorter edge overlapping a longer one. */
+TEST(PlanarGraphTest, MergePartial)
+{
+ TestGraph graph;
+ auto longer = graph.insertEdge(PTH("M 0, 0 L 10, 10"));
+ auto shorter = graph.insertEdge(PTH("M 0, 0 L 6, 6"));
+
+ EXPECT_EQ(graph.numVertices(), 3);
+
+ graph.regularize();
+
+ EXPECT_EQ(graph.numVertices(), 3);
+ EXPECT_TRUE(graph.isRegularized());
+
+ auto labels = extract_labels(graph);
+ ASSERT_EQ(labels.size(), 2);
+
+ EXPECT_EQ(labels[longer].merge_count, 0);
+ EXPECT_EQ(labels[longer].reversal_count, 0);
+ EXPECT_EQ(labels[longer].detachment_count, 0);
+
+ EXPECT_EQ(labels[shorter].merge_count, 1);
+ EXPECT_EQ(labels[shorter].reversal_count, 0);
+ EXPECT_EQ(labels[shorter].detachment_count, 0);
+
+ // Now the same thing but with edges of opposite orientations.
+ TestGraph graphopp;
+ longer = graphopp.insertEdge(PTH("M 0, 0 L 10, 0"));
+ shorter = graphopp.insertEdge(PTH("M 10, 0 L 5, 0"));
+
+ EXPECT_EQ(graphopp.numVertices(), 3);
+
+ graphopp.regularize();
+
+ EXPECT_EQ(graphopp.numVertices(), 3);
+ EXPECT_TRUE(graphopp.isRegularized());
+
+ labels = extract_labels(graphopp);
+ ASSERT_EQ(labels.size(), 2);
+
+ EXPECT_EQ(labels[longer].merge_count, 0);
+ EXPECT_EQ(labels[longer].reversal_count, 0);
+ EXPECT_EQ(labels[longer].detachment_count, 0);
+
+ EXPECT_EQ(labels[shorter].merge_count, 1);
+ EXPECT_EQ(labels[shorter].reversal_count, 0);
+ EXPECT_EQ(labels[shorter].detachment_count, 0);
+}
+
+/** Regularization of a Y-split. */
+TEST(PlanarGraphTest, MergeY)
+{
+ TestGraph graph;
+ auto left = graph.insertEdge(PTH("M 1 0 V 1 L 0, 2"));
+ auto right = graph.insertEdge(PTH("M 1,0 V 1 L 2, 2"));
+
+ EXPECT_EQ(graph.numVertices(), 3);
+ graph.regularize();
+ EXPECT_EQ(graph.numVertices(), 4);
+
+ auto edges = graph.getEdges();
+ EXPECT_EQ(edges.size(), 3);
+
+ EXPECT_TRUE(are_near(edges[right].start->point(), Point(1, 1)));
+}
+
+/** Test reversal of a wrongly oriented teardrop */
+TEST(PlanarGraphTest, Teardrop)
+{
+ TestGraph graph;
+ auto loop = graph.insertEdge(PTH("M 1,0 A 1,1, 0,0,1 0,1 L 2,2 V 1 H 1 V 0"));
+ // Insert a few unrelated edges
+ auto before = graph.insertEdge(PTH("M 1,0 H 10"));
+ auto after = graph.insertEdge(PTH("M 1,0 H -10"));
+
+ EXPECT_EQ(graph.numVertices(), 3);
+
+ graph.regularize();
+
+ EXPECT_EQ(graph.numVertices(), 3);
+ auto [start_vertex, start_incidence] = graph.getIncidence(loop, TestGraph::Incidence::START);
+ auto [end_vertex, end_incidence] = graph.getIncidence(loop, TestGraph::Incidence::END);
+
+ EXPECT_EQ(start_vertex, end_vertex);
+ ASSERT_NE(start_vertex, nullptr);
+
+ // Check that the incidences have been swapped
+ EXPECT_EQ(start_vertex->cyclicNextIncidence(end_incidence), start_incidence);
+ EXPECT_EQ(start_vertex->cyclicPrevIncidence(start_incidence), end_incidence);
+ auto [b, before_incidence] = graph.getIncidence(before, TestGraph::Incidence::START);
+ EXPECT_EQ(start_vertex->cyclicNextIncidence(before_incidence), end_incidence);
+ auto [a, after_incidence] = graph.getIncidence(after, TestGraph::Incidence::START);
+ EXPECT_EQ(start_vertex->cyclicPrevIncidence(after_incidence), start_incidence);
+}
+
+/** Test the regularization of a lasso-shaped path. */
+TEST(PlanarGraphTest, ReglueLasso)
+{
+ TestGraph graph;
+ // Insert a lasso-shaped path (a teardrop with initial self-overlap).
+ auto original_lasso = graph.insertEdge(PTH("M 0,0 V 1 C 0,2 1,3 1,4 "
+ "A 1,1 0,1,1 -1,4 C -1,3 0,2 0,1 V 0"));
+ EXPECT_EQ(graph.numVertices(), 1);
+
+ graph.regularize();
+ EXPECT_EQ(graph.numVertices(), 2);
+ EXPECT_EQ(graph.numEdges(false), 2);
+ EXPECT_TRUE(graph.getEdge(original_lasso).detached);
+
+ auto const &edges = graph.getEdges();
+ // Find the edge from origin and ensure it got glued.
+ auto from_origin = std::find_if(edges.begin(), edges.end(), [](auto const &edge) -> bool {
+ return !edge.detached && (edge.start->point() == Point(0, 0) ||
+ edge.end->point() == Point(0, 0));
+ });
+ ASSERT_NE(from_origin, edges.end());
+ ASSERT_EQ(from_origin->label.merge_count, 1);
+}
+
+/** Test the removal of a collapsed loop. */
+TEST(PlanarGraphTest, RemoveCollapsed)
+{
+ TestGraph graph;
+ // Insert a collapsed loop
+ auto collapsed = graph.insertEdge(PTH("M 0,0 L 1,1 L 0,0"));
+ ASSERT_EQ(graph.numEdges(), 1);
+ graph.regularize();
+ ASSERT_EQ(graph.numEdges(false), 0);
+ ASSERT_TRUE(graph.getEdge(collapsed).detached);
+
+ TestGraph fuzzy(1e-3);
+ // Insert a nearly collapsed loop
+ auto nearly = fuzzy.insertEdge(PTH("M 0,0 H 2 V 0.001 L 1,0 H 0"));
+ ASSERT_EQ(fuzzy.numEdges(), 1);
+ fuzzy.regularize();
+ ASSERT_EQ(fuzzy.numEdges(false), 0);
+ ASSERT_TRUE(fuzzy.getEdge(nearly).detached);
+}
+
+/** Test regularization of straddling runs. */
+TEST(PlanarGraphTest, RemoveWisp)
+{
+ TestGraph graph;
+ // Insert a horizontal segment at the origin towards positive X:
+ graph.insertEdge(PTH("M 0 0 H 1"));
+ // Insert a path with a collapsed Bézier curve towards negative X:
+ graph.insertEdge(PTH("M 0 0 C -1 0 -1 0 0 0"));
+ graph.regularize();
+
+ // Ensure that the folded Bézier is removed (and no segfault occurs).
+ EXPECT_EQ(graph.numEdges(false), 1);
+}
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/tests/point-test.cpp b/src/3rdparty/2geom/tests/point-test.cpp
new file mode 100644
index 0000000..16596a5
--- /dev/null
+++ b/src/3rdparty/2geom/tests/point-test.cpp
@@ -0,0 +1,119 @@
+/** @file
+ * @brief Unit tests for Point, IntPoint and related functions.
+ * Uses the Google Testing Framework
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2014-2015 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <gtest/gtest.h>
+#include <2geom/point.h>
+
+namespace Geom {
+
+TEST(PointTest, Normalize) {
+ Point a(1e-18, 0);
+ Point b = a;
+ a.normalize();
+
+ EXPECT_EQ(a, Point(1, 0));
+ EXPECT_EQ(b.normalized(), a);
+ EXPECT_NE(b, a);
+}
+
+TEST(PointTest, ScalarOps) {
+ Point a(1,2);
+ EXPECT_EQ(a * 2, Point(2, 4));
+ EXPECT_EQ(2 * a, Point(2, 4));
+ EXPECT_EQ(a / 2, Point(0.5, 1));
+
+ Point b = a;
+ a *= 2;
+ a /= 2;
+ EXPECT_EQ(a, b);
+}
+
+TEST(PointTest, Rounding) {
+ Point a(-0.7, 0.7);
+ IntPoint aceil(0, 1), afloor(-1, 0), around(-1, 1);
+ EXPECT_TRUE(a.ceil() == aceil);
+ EXPECT_TRUE(a.floor() == afloor);
+ EXPECT_TRUE(a.round() == around);
+}
+
+TEST(PointTest, Near) {
+ EXPECT_TRUE(are_near(Point(), Point(0, 1e-6)));
+ EXPECT_FALSE(are_near(Point(), Point(0, 1e-4)));
+
+ EXPECT_TRUE(are_near_rel(Point(100, 0), Point(100, 1e-4)));
+ EXPECT_FALSE(are_near_rel(Point(100, 0), Point(100, 1e-2)));
+}
+
+TEST(PointTest, Multiplicative) {
+ EXPECT_EQ(Point(2, 3) * Point(4, 5), Point(8, 15));
+ EXPECT_EQ(IntPoint(2, 3) * IntPoint(4, 5), IntPoint(8, 15));
+ EXPECT_EQ(Point(10, 11) / Point(2, 3), Point(5, 11.0 / 3.0));
+ EXPECT_EQ(IntPoint(10, 11) / IntPoint(2, 3), IntPoint(5, 11 / 3));
+}
+
+TEST(PointTest, PointCtors) {
+ Point a(2, 3);
+ EXPECT_EQ(a[X], 2);
+ EXPECT_EQ(a[Y], 3);
+
+ a.~Point();
+ new (&a) Point;
+ EXPECT_EQ(a, Point(0, 0));
+
+ a = Point(IntPoint(4, 5));
+ EXPECT_EQ(a[X], 4);
+ EXPECT_EQ(a[Y], 5);
+}
+
+TEST(PointTest, IntPointCtors) {
+ IntPoint a(2, 3);
+ EXPECT_EQ(a[X], 2);
+ EXPECT_EQ(a[Y], 3);
+
+ a.~IntPoint();
+ new (&a) IntPoint;
+ EXPECT_EQ(a, IntPoint(0, 0));
+}
+
+} // end namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/tests/polybez-cases.svg b/src/3rdparty/2geom/tests/polybez-cases.svg
new file mode 100644
index 0000000..1fa653a
--- /dev/null
+++ b/src/3rdparty/2geom/tests/polybez-cases.svg
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="1024"
+ height="768"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.47 r22583"
+ sodipodi:docname="polybez-cases.svg">
+ <defs
+ id="defs4">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="11.2"
+ inkscape:cx="338.56564"
+ inkscape:cy="493.11416"
+ inkscape:document-units="px"
+ inkscape:current-layer="sweep1"
+ showgrid="true"
+ inkscape:snap-grids="true"
+ inkscape:window-width="1440"
+ inkscape:window-height="825"
+ inkscape:window-x="0"
+ inkscape:window-y="24"
+ inkscape:window-maximized="1">
+ <inkscape:grid
+ type="xygrid"
+ id="grid2820"
+ empspacing="5"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="false" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-284.36218)">
+ <g
+ id="g2829">
+ <path
+ id="path2824"
+ d="m 335,532 0,-15 10,-10 10,0 0,12 -7,0 0,7 7,0 0,6 -20,0 z"
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ id="path2826"
+ d="m 338,524 0,-10 5,-5 12,0 0,15 -17,0 z"
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 370,507 15,0 -15,20 15,0 -15,-20 z"
+ id="path2828" />
+ <g
+ id="g2836">
+ <path
+ id="path2830"
+ d="m 395,507 0,20 15,0 0,-20 -15,0 z"
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ id="path2832"
+ d="m 400,512 0,10 5,0 0,-10 -5,0 z"
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ <g
+ id="g2840">
+ <path
+ id="path2834"
+ d="m 420,507 0,20 10,0 0,-20 -10,0 z"
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ id="path2838"
+ d="m 420,512 10,0 0,10 -10,0 0,-10 z"
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ <g
+ id="g2844">
+ <path
+ transform="translate(0,284.36218)"
+ id="path2861"
+ d="m 335,273 5,-10 5,0 -5,10 -5,0 z"
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ transform="translate(0,284.36218)"
+ id="path2863"
+ d="m 335,263 5,10 5,0 -5,-10 -5,0 z"
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ <g
+ id="g2848">
+ <path
+ transform="translate(0,284.36218)"
+ id="path2865"
+ d="m 355,273 c 0,-10 5,-15 15,-15 10,0 15,15 5,15 -10,0 -19.82143,0 -20,0 z"
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ transform="translate(0,284.36218)"
+ id="path2867"
+ d="m 355,258 15,15 5,0 -15,-15 -5,0 z"
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 390,273 c 0,0 0,-20 0,-15 0,5 5,-5 5,-5 l 5,0 0,20 -10,0 z"
+ id="path2869"
+ transform="translate(0,284.36218)" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 405,273 c 0,0 0,-10 0,-15 0,-5 0,-5 5,-5 5,0 5,0 5,5 0,5 -10,14.82143 -10,15 z"
+ id="path2871"
+ transform="translate(0,284.36218)" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 339.46429,565.30861 c -4.5365,-2.22147 -11.77743,5.69134 -5.21169,7.66819 2.96423,0.36599 10.83771,-2.10029 8.78922,3.46024 -1.13154,2.4938 -6.48404,5.18119 -7.60122,3.87235 4.97889,-1.66476 5.51215,4.06019 3.64354,6.27906 2.59991,2.27135 9.90909,-2.08687 10.22789,-0.44567 -5.83309,2.53694 -12.2305,3.77526 -18.58139,3.51925 -5.55304,-1.87666 0.0508,-8.52008 3.64017,-9.2859 3.14953,-0.57328 11.95334,1.68857 9.98614,-3.95731 -2.41191,-3.92307 -8.83522,2.26895 -9.24309,-2.87701 1.90388,-1.51652 8.28914,-1.45159 6.19223,-5.58351 -2.15792,-0.14937 -0.81405,-2.34484 -1.8418,-2.64969 z"
+ id="path2873" />
+ <g
+ id="sweep1">
+ <path
+ id="path2892"
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 307,259 c 0,0 8,8 -3,11 -5,1 -5,9 -5,9 m 4,-17 1,3 m -6,-8 3,12 m -9,-11 1,4 2,3 -1,4 3,3 -2,5 m -9,-19 4,14"
+ transform="translate(0,284.36218)" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 296,280 5,-11"
+ id="path2908"
+ transform="translate(0,284.36218)" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 309,283 -5,-18"
+ id="path2904"
+ transform="translate(0,284.36218)" />
+ </g>
+ </g>
+</svg>
diff --git a/src/3rdparty/2geom/tests/polynomial-test.cpp b/src/3rdparty/2geom/tests/polynomial-test.cpp
new file mode 100644
index 0000000..699820a
--- /dev/null
+++ b/src/3rdparty/2geom/tests/polynomial-test.cpp
@@ -0,0 +1,126 @@
+/** @file
+ * @brief Unit tests for Polynomial and related functions.
+ * Uses the Google Testing Framework
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2015-2019 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include "testing.h"
+#include <iostream>
+#include <glib.h>
+
+#include <2geom/polynomial.h>
+
+using namespace Geom;
+
+TEST(PolynomialTest, SolveQuadratic) {
+ for (unsigned i = 0; i < 1000; ++i) {
+ Coord x1 = g_random_double_range(-100, 100);
+ Coord x2 = g_random_double_range(-100, 100);
+
+ Coord a = g_random_double_range(-10, 10);
+ Coord b = -a * (x1 + x2);
+ Coord c = a * x1 * x2;
+
+ std::vector<Coord> result = solve_quadratic(a, b, c);
+
+ EXPECT_EQ(result.size(), 2u);
+ if (x1 < x2) {
+ EXPECT_FLOAT_EQ(result[0], x1);
+ EXPECT_FLOAT_EQ(result[1], x2);
+ } else {
+ EXPECT_FLOAT_EQ(result[0], x2);
+ EXPECT_FLOAT_EQ(result[1], x1);
+ }
+ }
+}
+
+TEST(PolynomialTest, SolvePathologicalQuadratic) {
+ std::vector<Coord> r;
+
+ r = solve_quadratic(1, -1e9, 1);
+ ASSERT_EQ(r.size(), 2u);
+ EXPECT_FLOAT_EQ(r[0], 1e-9);
+ EXPECT_FLOAT_EQ(r[1], 1e9);
+
+ r = solve_quadratic(1, -4, 3.999999);
+ ASSERT_EQ(r.size(), 2u);
+ EXPECT_FLOAT_EQ(r[0], 1.999);
+ EXPECT_FLOAT_EQ(r[1], 2.001);
+
+ r = solve_quadratic(1, 0, -4);
+ ASSERT_EQ(r.size(), 2u);
+ EXPECT_FLOAT_EQ(r[0], -2);
+ EXPECT_FLOAT_EQ(r[1], 2);
+
+ r = solve_quadratic(1, 0, -16);
+ ASSERT_EQ(r.size(), 2u);
+ EXPECT_FLOAT_EQ(r[0], -4);
+ EXPECT_FLOAT_EQ(r[1], 4);
+
+ r = solve_quadratic(1, 0, -100);
+ ASSERT_EQ(r.size(), 2u);
+ EXPECT_FLOAT_EQ(r[0], -10);
+ EXPECT_FLOAT_EQ(r[1], 10);
+}
+
+TEST(PolynomialTest, SolveCubic) {
+ for (unsigned i = 0; i < 1000; ++i) {
+ Coord x1 = g_random_double_range(-100, 100);
+ Coord x2 = g_random_double_range(-100, 100);
+ Coord x3 = g_random_double_range(-100, 100);
+
+ Coord a = g_random_double_range(-10, 10);
+ Coord b = -a * (x1 + x2 + x3);
+ Coord c = a * (x1*x2 + x2*x3 + x1*x3);
+ Coord d = -a * x1 * x2 * x3;
+
+ std::vector<Coord> result = solve_cubic(a, b, c, d);
+ std::vector<Coord> x(3); x[0] = x1; x[1] = x2; x[2] = x3;
+ std::sort(x.begin(), x.end());
+
+ ASSERT_EQ(result.size(), 3u);
+ EXPECT_FLOAT_EQ(result[0], x[0]);
+ EXPECT_FLOAT_EQ(result[1], x[1]);
+ EXPECT_FLOAT_EQ(result[2], x[2]);
+ }
+
+ // corner cases
+ // (x^2 + 7)(x - 2)
+ std::vector<Coord> r1 = solve_cubic(1, -2, 7, -14);
+ EXPECT_EQ(r1.size(), 1u);
+ EXPECT_FLOAT_EQ(r1[0], 2);
+
+ // (x + 1)^2 (x-2)
+ std::vector<Coord> r2 = solve_cubic(1, 0, -3, -2);
+ ASSERT_EQ(r2.size(), 3u);
+ EXPECT_FLOAT_EQ(r2[0], -1);
+ EXPECT_FLOAT_EQ(r2[1], -1);
+ EXPECT_FLOAT_EQ(r2[2], 2);
+}
diff --git a/src/3rdparty/2geom/tests/rect-test.cpp b/src/3rdparty/2geom/tests/rect-test.cpp
new file mode 100644
index 0000000..93733e5
--- /dev/null
+++ b/src/3rdparty/2geom/tests/rect-test.cpp
@@ -0,0 +1,368 @@
+/** @file
+ * @brief Unit tests for Rect, OptRect, IntRect, and OptIntRect.
+ * Uses the Google Testing Framework
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright 2010 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <gtest/gtest.h>
+#include <2geom/coord.h>
+#include <2geom/rect.h>
+
+namespace Geom {
+
+typedef ::testing::Types<Coord, IntCoord> CoordTypes;
+
+TEST(RectTest, Upconversion) {
+ IntRect ir(0, -27, 10, 202);
+ Rect r_a(ir);
+ Rect r_b = ir;
+ OptIntRect oir_a(ir);
+ OptIntRect oir_b = ir;
+ OptRect or_a(oir_a);
+ OptRect or_b = oir_b;
+
+ EXPECT_EQ(r_a, ir);
+ EXPECT_EQ(r_a, r_b);
+ EXPECT_EQ(r_a, *oir_a);
+ EXPECT_EQ(r_a, *oir_b);
+ EXPECT_EQ(r_a, *or_a);
+ EXPECT_EQ(r_a, *or_b);
+ EXPECT_EQ(oir_a, oir_b);
+ EXPECT_EQ(or_a, or_b);
+}
+
+TEST(RectTest, Rounding) {
+ Rect r(-0.5, -0.5, 5.5, 5.5);
+ Rect r_small(0.3, 0.0, 0.6, 10.0);
+ Rect r_int(0,0,10,10);
+ IntRect out(-1, -1, 6, 6);
+ IntRect out_small(0, 0, 1, 10);
+ IntRect out_int(0,0,10,10);
+ OptIntRect in = IntRect(0, 0, 5, 5);
+ EXPECT_EQ(r.roundOutwards(), out);
+ EXPECT_EQ(r_small.roundOutwards(), out_small);
+ EXPECT_EQ(r_int.roundOutwards(), out_int);
+ EXPECT_EQ(r.roundInwards(), in);
+ EXPECT_EQ(r_small.roundInwards(), OptIntRect());
+}
+
+template <typename C>
+class GenericRectTest : public ::testing::Test {
+public:
+ typedef typename CoordTraits<C>::PointType CPoint;
+ typedef typename CoordTraits<C>::RectType CRect;
+ typedef typename CoordTraits<C>::OptRectType OptCRect;
+ CRect a, a2, b, c, d;
+ CRect int_ab, int_bc, uni_ab, uni_bc;
+ GenericRectTest()
+ : a(0, 0, 10, 10)
+ , a2(0, 0, 10, 10)
+ , b(-5, -5, 5, 5)
+ , c(-10, -10, -1, -1)
+ , d(1, 1, 9, 9)
+ , int_ab(0, 0, 5, 5)
+ , int_bc(-5, -5, -1, -1)
+ , uni_ab(-5, -5, 10, 10)
+ , uni_bc(-10, -10, 5, 5)
+ {}
+};
+
+TYPED_TEST_CASE(GenericRectTest, CoordTypes);
+
+TYPED_TEST(GenericRectTest, EqualityTest) {
+ typename TestFixture::CRect a(0, 0, 10, 10), a2(a), b(-5, -5, 5, 5);
+ typename TestFixture::OptCRect empty, oa = a;
+
+ EXPECT_TRUE (a == a);
+ EXPECT_FALSE(a != a);
+ EXPECT_TRUE (a == a2);
+ EXPECT_FALSE(a != a2);
+ EXPECT_TRUE (empty == empty);
+ EXPECT_FALSE(empty != empty);
+ EXPECT_FALSE(a == empty);
+ EXPECT_TRUE (a != empty);
+ EXPECT_FALSE(empty == a);
+ EXPECT_TRUE (empty != a);
+ EXPECT_FALSE(a == b);
+ EXPECT_TRUE (a != b);
+ EXPECT_TRUE (a == oa);
+ EXPECT_FALSE(a != oa);
+}
+
+TYPED_TEST(GenericRectTest, Intersects) {
+ typename TestFixture::CRect a(0, 0, 10, 10), b(-5, -5, 5, 5), c(-10, -10, -1, -1), d(1, 1, 9, 9);
+ typename TestFixture::OptCRect empty, oa(a), oc(c), od(d);
+ EXPECT_TRUE(a.intersects(a));
+ EXPECT_TRUE(a.intersects(b));
+ EXPECT_TRUE(b.intersects(a));
+ EXPECT_TRUE(b.intersects(c));
+ EXPECT_TRUE(c.intersects(b));
+ EXPECT_TRUE(a.intersects(d));
+ EXPECT_TRUE(d.intersects(a));
+ EXPECT_FALSE(a.intersects(c));
+ EXPECT_FALSE(c.intersects(a));
+ EXPECT_FALSE(c.intersects(d));
+ EXPECT_FALSE(empty.intersects(empty));
+ EXPECT_FALSE(empty.intersects(oa));
+ EXPECT_FALSE(oa.intersects(empty));
+ EXPECT_TRUE(oa.intersects(od));
+ EXPECT_FALSE(oa.intersects(oc));
+}
+
+/**
+ JonCruz failure: (10, 20)-(55,30) and (45,20)-(100,30) should intersect.
+*/
+
+TYPED_TEST(GenericRectTest, JonCruzRect) {
+ typename TestFixture::CRect a(10, 20, 55, 30), b(45, 20, 100,30);
+ typename TestFixture::OptCRect empty, oa(a), ob(b);
+ EXPECT_TRUE(a.intersects(a));
+ EXPECT_TRUE(a.intersects(b));
+ EXPECT_TRUE(b.intersects(a));
+ EXPECT_TRUE(oa.intersects(oa));
+ EXPECT_TRUE(oa.intersects(ob));
+ EXPECT_TRUE(ob.intersects(oa));
+}
+
+TYPED_TEST(GenericRectTest, Intersection) {
+ typename TestFixture::CRect a(0, 0, 10, 10), b(-5, -5, 5, 5), c(-10, -10, -1, -1), d(1, 1, 9, 9);
+ typename TestFixture::CRect int_ab(0, 0, 5, 5), int_bc(-5, -5, -1, -1);
+ typename TestFixture::OptCRect empty, oa(a), ob(b);
+
+ EXPECT_EQ(a & a, a);
+ EXPECT_EQ(a & b, int_ab);
+ EXPECT_EQ(b & c, int_bc);
+ EXPECT_EQ(intersect(b, c), int_bc);
+ EXPECT_EQ(intersect(a, a), a);
+ EXPECT_EQ(a & c, empty);
+ EXPECT_EQ(a & d, d);
+ EXPECT_EQ(a & empty, empty);
+ EXPECT_EQ(empty & empty, empty);
+
+ oa &= ob;
+ EXPECT_EQ(oa, int_ab);
+ oa = a;
+ oa &= b;
+ EXPECT_EQ(oa, int_ab);
+ oa = a;
+ oa &= empty;
+ EXPECT_EQ(oa, empty);
+}
+
+TYPED_TEST(GenericRectTest, Contains) {
+ typename TestFixture::CRect a(0, 0, 10, 10), b(-5, -5, 5, 5), c(-10, -10, -1, -1), d(1, 1, 9, 9);
+ typename TestFixture::CRect int_ab(0, 0, 5, 5), int_bc(-5, -5, -1, -1);
+ typename TestFixture::OptCRect empty, oa(a), od(d);
+ EXPECT_TRUE(a.contains(a));
+ EXPECT_FALSE(a.contains(b));
+ EXPECT_FALSE(b.contains(a));
+ EXPECT_FALSE(a.contains(c));
+ EXPECT_FALSE(c.contains(a));
+ EXPECT_TRUE(a.contains(d));
+ EXPECT_FALSE(d.contains(a));
+ EXPECT_TRUE(a.contains(int_ab));
+ EXPECT_TRUE(b.contains(int_ab));
+ EXPECT_TRUE(b.contains(int_bc));
+ EXPECT_TRUE(c.contains(int_bc));
+ EXPECT_FALSE(int_ab.contains(a));
+ EXPECT_FALSE(int_ab.contains(b));
+ EXPECT_FALSE(int_bc.contains(b));
+ EXPECT_FALSE(int_bc.contains(c));
+ EXPECT_FALSE(empty.contains(empty));
+ EXPECT_FALSE(empty.contains(od));
+ EXPECT_TRUE(oa.contains(empty));
+ EXPECT_TRUE(oa.contains(od));
+ EXPECT_FALSE(od.contains(oa));
+}
+
+TYPED_TEST(GenericRectTest, Union) {
+ typename TestFixture::CRect a(0, 0, 10, 10), old_a(a), b(-5, -5, 5, 5), c(-10, -10, -1, -1), d(1, 1, 9, 9);
+ typename TestFixture::CRect int_ab(0, 0, 5, 5), int_bc(-5, -5, -1, -1);
+ typename TestFixture::CRect uni_ab(-5, -5, 10, 10), uni_bc(-10, -10, 5, 5);
+ typename TestFixture::OptCRect empty, oa(a), ob(b);
+ EXPECT_EQ(a | b, uni_ab);
+ EXPECT_EQ(b | c, uni_bc);
+ EXPECT_EQ(a | a, a);
+ EXPECT_EQ(a | d, a);
+ EXPECT_EQ(a | int_ab, a);
+ EXPECT_EQ(b | int_ab, b);
+ EXPECT_EQ(uni_ab | a, uni_ab);
+ EXPECT_EQ(uni_bc | c, uni_bc);
+ EXPECT_EQ(a | empty, a);
+ EXPECT_EQ(empty | empty, empty);
+
+ a |= b;
+ EXPECT_EQ(a, uni_ab);
+ a = old_a;
+ a |= ob;
+ EXPECT_EQ(a, uni_ab);
+ a = old_a;
+ a |= empty;
+ EXPECT_EQ(a, old_a);
+ oa |= ob;
+ EXPECT_EQ(oa, uni_ab);
+ oa = old_a;
+ oa |= b;
+ EXPECT_EQ(oa, uni_ab);
+}
+
+TYPED_TEST(GenericRectTest, Area) {
+ typename TestFixture::CRect a(0, 0, 10, 10), b(-5, -5, 5, 5), c(-10, -10, -1, -1), d(1, 1, 9, 9);
+ typename TestFixture::CRect zero(0,0,0,0);
+ EXPECT_EQ(a.area(), 100);
+ EXPECT_EQ(a.area(), a.width() * a.height());
+ EXPECT_EQ(b.area(), 100);
+ EXPECT_EQ(c.area(), 81);
+ EXPECT_EQ(d.area(), 64);
+ EXPECT_FALSE(a.hasZeroArea());
+ EXPECT_TRUE(zero.hasZeroArea());
+}
+
+TYPED_TEST(GenericRectTest, Emptiness) {
+ typename TestFixture::OptCRect empty, oa(0, 0, 10, 10);
+ EXPECT_TRUE(empty.empty());
+ EXPECT_FALSE(empty);
+ EXPECT_TRUE(!empty);
+ EXPECT_FALSE(oa.empty());
+ EXPECT_TRUE(oa);
+ EXPECT_FALSE(!oa);
+}
+
+TYPED_TEST(GenericRectTest, Dimensions) {
+ typedef typename TestFixture::CPoint CPoint;
+ typename TestFixture::CRect a(-10, -20, 10, 20), b(-15, 30, 45, 90);
+ EXPECT_EQ(a.width(), 20);
+ EXPECT_EQ(a.height(), 40);
+ EXPECT_EQ(a.left(), -10);
+ EXPECT_EQ(a.top(), -20);
+ EXPECT_EQ(a.right(), 10);
+ EXPECT_EQ(a.bottom(), 20);
+ EXPECT_EQ(a.min(), CPoint(-10, -20));
+ EXPECT_EQ(a.max(), CPoint(10, 20));
+ EXPECT_EQ(a.minExtent(), a.width());
+ EXPECT_EQ(a.maxExtent(), a.height());
+ EXPECT_EQ(a.dimensions(), CPoint(20, 40));
+ EXPECT_EQ(a.midpoint(), CPoint(0, 0));
+
+ EXPECT_EQ(b.width(), 60);
+ EXPECT_EQ(b.height(), 60);
+ EXPECT_EQ(b.left(), -15);
+ EXPECT_EQ(b.top(), 30);
+ EXPECT_EQ(b.right(), 45);
+ EXPECT_EQ(b.bottom(), 90);
+ EXPECT_EQ(b.min(), CPoint(-15, 30));
+ EXPECT_EQ(b.max(), CPoint(45, 90));
+ EXPECT_EQ(b.minExtent(), b.maxExtent());
+ EXPECT_EQ(b.dimensions(), CPoint(60, 60));
+ EXPECT_EQ(b.midpoint(), CPoint(15, 60));
+}
+
+TYPED_TEST(GenericRectTest, Modification) {
+ typedef typename TestFixture::CRect CRect;
+ typedef typename TestFixture::OptCRect OptCRect;
+ typedef typename TestFixture::CPoint CPoint;
+ CRect a(-1, -1, 1, 1);
+ a.expandBy(9);
+ EXPECT_EQ(a, CRect(-10, -10, 10, 10));
+ a.setMin(CPoint(0, 0));
+ EXPECT_EQ(a, CRect(0, 0, 10, 10));
+ a.setMax(CPoint(20, 30));
+ EXPECT_EQ(a, CRect(0, 0, 20, 30));
+ a.setMax(CPoint(-5, -5));
+ EXPECT_EQ(a, CRect(-5, -5, -5, -5));
+ a.expandTo(CPoint(5, 5));
+ EXPECT_EQ(a, CRect(-5, -5, 5, 5));
+ a.expandTo(CPoint(0, 0));
+ EXPECT_EQ(a, CRect(-5, -5, 5, 5));
+ a.expandTo(CPoint(0, 15));
+ EXPECT_EQ(a, CRect(-5, -5, 5, 15));
+ a.expandBy(-10);
+ EXPECT_EQ(a, CRect(0, 5, 0, 5));
+ EXPECT_EQ(a.midpoint(), CPoint(0, 5));
+ a.unionWith(CRect(-20, 0, -10, 20));
+ EXPECT_EQ(a, CRect(-20, 0, 0, 20));
+ OptCRect oa(a);
+ oa.intersectWith(CRect(-10, -5, 5, 15));
+ EXPECT_EQ(oa, OptCRect(-10, 0, 0, 15));
+}
+
+TYPED_TEST(GenericRectTest, OptRectDereference) {
+ typename TestFixture::CRect a(0, 0, 5, 5);
+ typename TestFixture::OptCRect oa(0, 0, 10, 10);
+ EXPECT_NE(a, oa);
+ a = *oa;
+ EXPECT_EQ(a, oa);
+}
+
+TYPED_TEST(GenericRectTest, Offset) {
+ typename TestFixture::CRect a(0, 0, 5, 5), old_a(a), app1(-5, 0, 0, 5), amp1(5, 0, 10, 5),
+ app2(5, -10, 10, -5), amp2(-5, 10, 0, 15);
+ typename TestFixture::CPoint p1(-5, 0), p2(5, -10);
+ EXPECT_EQ(a + p1, app1);
+ EXPECT_EQ(a + p2, app2);
+ EXPECT_EQ(a - p1, amp1);
+ EXPECT_EQ(a - p2, amp2);
+
+ a += p1;
+ EXPECT_EQ(a, app1);
+ a = old_a;
+ a += p2;
+ EXPECT_EQ(a, app2);
+ a = old_a;
+ a -= p1;
+ EXPECT_EQ(a, amp1);
+ a = old_a;
+ a -= p2;
+ EXPECT_EQ(a, amp2);
+}
+
+TYPED_TEST(GenericRectTest, NearestEdgePoint) {
+ typename TestFixture::CRect a(0, 0, 10, 10);
+ typename TestFixture::CPoint p1(-5, 5), p2(15, 17), p3(6, 5), p4(3, 9);
+ typename TestFixture::CPoint r1(0, 5), r2(10, 10), r3(10, 5), r4(3, 10);
+
+ EXPECT_EQ(a.nearestEdgePoint(p1), r1);
+ EXPECT_EQ(a.nearestEdgePoint(p2), r2);
+ EXPECT_EQ(a.nearestEdgePoint(p3), r3);
+ EXPECT_EQ(a.nearestEdgePoint(p4), r4);
+}
+
+} // end namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/tests/root-find-test.cpp b/src/3rdparty/2geom/tests/root-find-test.cpp
new file mode 100644
index 0000000..b866f66
--- /dev/null
+++ b/src/3rdparty/2geom/tests/root-find-test.cpp
@@ -0,0 +1,156 @@
+#include <2geom/polynomial.h>
+#include <vector>
+#include <iterator>
+
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-poly.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/solver.h>
+#include <time.h>
+
+using namespace std;
+using namespace Geom;
+
+Poly lin_poly(double a, double b) { // ax + b
+ Poly p;
+ p.push_back(b);
+ p.push_back(a);
+ return p;
+}
+
+Linear linear(double ax, double b) {
+ return Linear(b, ax+b);
+}
+
+double uniform() {
+ return double(rand()) / RAND_MAX;
+}
+
+int main() {
+ Poly a, b, r;
+ double timer_precision = 0.01;
+ double units = 1e6; // us
+
+ a = Poly::linear(1, -0.3)*Poly::linear(1, -0.25)*Poly::linear(1, -0.2);
+
+ std::cout << a <<std::endl;
+ SBasis B = poly_to_sbasis(a);
+ std::cout << B << std::endl;
+ Bezier bez;
+ sbasis_to_bezier(bez, B);
+ cout << bez << endl;
+ //copy(bez.begin(), bez.end(), ostream_iterator<double>(cout, ", "));
+ cout << endl;
+ cout << endl;
+ cout << endl;
+
+ std::vector<std::vector<double> > trials;
+
+ // evenly spaced roots
+ for(int N = 2; N <= 5; N++)
+ {
+ std::vector<double> r;
+ for(int i = 0; i < N; i++)
+ r.push_back(double(i)/(N-1));
+ trials.push_back(r);
+ }
+ // sort of evenish
+ for(int N = 0; N <= 5; N++)
+ {
+ std::vector<double> r;
+ for(int i = 0; i < N; i++)
+ r.push_back(double(i+0.5)/(2*N));
+ trials.push_back(r);
+ }
+ // one at 0.1
+ for(int N = 0; N <= 5; N++)
+ {
+ std::vector<double> r;
+ for(int i = 0; i < N; i++)
+ r.push_back(i+0.1);
+ trials.push_back(r);
+ }
+ for(int N = 0; N <= 6; N++)
+ {
+ std::vector<double> r;
+ for(int i = 0; i < N; i++)
+ r.push_back(i*0.8+0.1);
+ trials.push_back(r);
+ }
+ for(int N = 0; N <= 20; N++)
+ {
+ std::vector<double> r;
+ for(int i = 0; i < N/2; i++) {
+ r.push_back(0.1);
+ r.push_back(0.9);
+ }
+ trials.push_back(r);
+ }
+ for(int i = 0; i <= 20; i++)
+ {
+ std::vector<double> r;
+ for(int i = 0; i < 4; i++) {
+ r.push_back(uniform()*5 - 2.5);
+ r.push_back(0.9);
+ }
+ trials.push_back(r);
+ }
+ double ave_left = 0;
+ cout << "err from exact\n";
+ for(auto & trial : trials) {
+ SBasis B = Linear(1.,1);
+ sort(trial.begin(), trial.end());
+ for(double j : trial) {
+ B = B*linear(1, -j);
+ }
+ double left_time;
+ clock_t end_t = clock()+clock_t(timer_precision*CLOCKS_PER_SEC);
+ unsigned iterations = 0;
+ while(end_t > clock()) {
+ roots(B);
+ iterations++;
+ }
+ left_time = timer_precision*units/iterations;
+ vector<double> rt = roots(B);
+ double err = 0;
+ for(double r : rt) {
+ double best = fabs(r - trial[0]);
+ for(unsigned j = 1; j < trial.size(); j++) {
+ if(fabs(r - trial[j]) < best)
+ best = fabs(r - trial[j]);
+ }
+ err += best;
+ }
+ if(err > 1e-8){
+ for(double j : trial) {
+ cout << j << ", ";
+ }
+ cout << endl;
+ }
+ cout << " e: " << err << std::endl;
+ ave_left += left_time;
+ }
+ cout << "average time = " << ave_left/trials.size() << std::endl;
+
+ for(int i = 10; i >= 0; i--) {
+ vector<double> rt = roots(Linear(i,-1));
+ for(double j : rt) {
+ cout << j << ", ";
+ }
+ cout << endl;
+ }
+
+ return 0;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/tests/rtree-performance-test.cpp b/src/3rdparty/2geom/tests/rtree-performance-test.cpp
new file mode 100644
index 0000000..cf4bcd7
--- /dev/null
+++ b/src/3rdparty/2geom/tests/rtree-performance-test.cpp
@@ -0,0 +1,361 @@
+/*
+ * Copyright 2010 Evangelos Katsikaros <vkatsikaros at yahoo dot gr>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/toys/toy-framework-2.h>
+
+#include <sstream>
+#include <getopt.h>
+
+#include <SpatialIndex.h>
+#include <glib.h>
+//#include <glib/gtypes.h>
+
+using namespace Geom;
+
+// cmd argument stuff
+char* arg_area_limit = NULL;
+bool arg_area_limit_set = false;
+bool arg_debug = false;
+
+int limit = 0;
+
+// spatial index ID management
+SpatialIndex::id_type indexID;
+
+// list of rectangles
+GList *items = NULL;
+
+// tree of rectangles
+SpatialIndex::ISpatialIndex *tree;
+
+SpatialIndex::id_type test_indexID;
+
+void add_rectangle( int x, int y );
+
+/* Simple Visitor used to search the tree. When Data is encountered
+ * we are supposed to call the render function of the Data
+ * */
+class SearchVisitor : public SpatialIndex::IVisitor {
+public:
+
+ void visitNode(const SpatialIndex::INode& n){
+ }
+
+ void visitData(const SpatialIndex::IData& d){
+ /* this prototype: do nothing
+ * otherwise, render on buffer
+ * */
+ }
+
+ void visitData(std::vector<const SpatialIndex::IData*>& v) {
+ }
+};
+
+
+/* we use the this visitor after each insertion in the tree
+ * The purpose is to validate that everything was stored properly
+ * and test the GList pointer storage. It has no other functional
+ * purpose.
+ * */
+class TestSearchVisitor : public SpatialIndex::IVisitor {
+public:
+
+ void visitNode(const SpatialIndex::INode& n) {
+ }
+
+ void visitData(const SpatialIndex::IData& d){
+ if( test_indexID == d.getIdentifier() ){
+ byte* pData = 0;
+ uint32_t cLen = sizeof(GList*);
+ d.getData(cLen, &pData);
+ //do something...
+ GList* gl = reinterpret_cast<GList*>(pData);
+ Geom::Rect *member_data = (Geom::Rect *)gl->data;
+ double lala = member_data->bottom();
+ std::cout << " Tree: " << lala << std::endl;
+
+ delete[] pData;
+ }
+ }
+
+ void visitData(std::vector<const SpatialIndex::IData*>& v) {
+ }
+};
+
+
+int main(int argc, char **argv) {
+
+ int c;
+
+ //--------------------------------------------------------------------------
+ // read cmd options
+ while (1) {
+ static struct option long_options[] =
+ {
+ /* These options set a flag. */
+ /* These options don't set a flag.
+ We distinguish them by their indices. */
+ {"area-limit", required_argument, 0, 'l'},
+ {"help", no_argument, 0, 'h'},
+ {"debug", no_argument, 0, 'd'},
+ {0, 0, 0, 0}
+ };
+ /* getopt_long stores the option index here. */
+ int option_index = 0;
+
+ c = getopt_long (argc, argv, "l:h:d",
+ long_options, &option_index);
+
+ /* Detect the end of the options. */
+ if (c == -1){
+ break;
+ }
+
+ switch (c)
+ {
+ case 'l':
+ arg_area_limit = optarg;
+ arg_area_limit_set = true;
+ break;
+ case 'h':
+ std::cerr << "Usage: " << argv[0] << " options\n" << std::endl ;
+ std::cerr <<
+ " -l --area-limit=NUMBER minimum number in node.\n" <<
+ " -d --debug Enable debug info (list/tree related).\n" <<
+ " -h --help Print this help.\n" << std::endl;
+ exit(1);
+ break;
+ case 'd':
+ arg_debug = true;
+ break;
+ case '?':
+ /* getopt_long already printed an error message. */
+ break;
+
+ default:
+ abort ();
+ }
+ }
+
+ // use some of the cmd options
+ if( arg_area_limit_set ) {
+ std::stringstream s1( arg_area_limit );
+ s1 >> limit;
+ }
+ else {
+ limit = 100;
+ }
+ // end cmd options
+ //--------------------------------------------------------------------------
+
+
+ double plow[2], phigh[2];
+ // spatial index memory storage manager
+ SpatialIndex::IStorageManager *mem_mngr;
+ // initialize spatial indexing stuff
+ mem_mngr = SpatialIndex::StorageManager::createNewMemoryStorageManager();
+ // fillFactor, indexCapacity, leafCapacity, dimensionality=2, variant=R*, indexIdentifier
+ tree = SpatialIndex::RTree::createNewRTree(*mem_mngr, 0.7, 25, 25, 2, SpatialIndex::RTree::RV_RSTAR, indexID);
+
+ //-------------------------------------------
+ /* generate items. add_rectangle() stores them in both list and tree
+ * add rect every (20, 20).
+ * In area ((0,0), (1000, 1000)) add every (100,100)
+ * */
+ for( int x_coord = -limit; x_coord <= limit; x_coord += 20 ) {
+ for( int y_coord = -limit; y_coord <= limit; y_coord += 20 ) {
+ if( x_coord >= 0 && x_coord <= 1000 &&
+ y_coord >= 0 && y_coord <= 1000 )
+ {
+ if( x_coord % 100 == 0 && y_coord % 100 == 0) {
+ add_rectangle( x_coord, y_coord );
+ }
+ else{
+ add_rectangle( x_coord, y_coord );
+ }
+ }
+ else{
+ add_rectangle( x_coord, y_coord );
+ }
+
+ }
+ }
+ std::cout << "Area of objects: ( -" << limit
+ << ", -" << limit
+ << " ), ( " << limit
+ << ", " << limit
+ << " )" << std::endl;
+ std::cout << "Number of Objects (indexID): " << indexID << std::endl;
+ // std::cout << "GListElements: " << g_list_length << std::endl;
+
+ //-------------------------------------------
+ // Traverse list
+ Geom::Point sa_start = Point( 0, 0 );
+ Geom::Point sa_end = Point( 1000, 1000 );
+ Geom::Rect search_area = Rect( sa_start, sa_end );
+
+ Timer list_timer;
+ list_timer.ask_for_timeslice();
+ list_timer.start();
+
+ for (GList *list = items; list; list = list->next) {
+ Geom::Rect *child = (Geom::Rect *)list->data;
+ if ( search_area.intersects( *child ) )
+ {
+ /* this prototype: do nothing
+ * otherwise, render on buffer
+ * */
+ }
+ }
+ Timer::Time the_list_time = list_timer.lap();
+
+ std::cout << std::endl;
+ std::cout << "GList (full scan): " << the_list_time << std::endl;
+
+ //-------------------------------------------
+ // Search tree - good case
+ Timer tree_timer;
+ tree_timer.ask_for_timeslice();
+ tree_timer.start();
+
+ /* We search only the (0,0), (1000, 1000) where the items are less dense.
+ * We expect a good performance versus the list
+ * */
+ // TODO IMPORTANT !!! check the plow, phigh
+ // plow[0] = x1; plow[1] = y1;
+ // phigh[0] = x2; phigh[1] = y2;
+
+ plow[0] = 0;
+ plow[1] = 0;
+ phigh[0] = 1000;
+ phigh[1] = 1000;
+
+ SpatialIndex::Region search_region = SpatialIndex::Region(plow, phigh, 2);
+ SearchVisitor vis = SearchVisitor();
+ tree->intersectsWithQuery( search_region, vis );
+
+ Timer::Time the_tree_time = tree_timer.lap();
+ std::cout << "Rtree (good): " << the_tree_time << std::endl;
+
+
+ //-------------------------------------------
+ // Search tree - worst case
+ Timer tree_timer_2;
+ tree_timer_2.ask_for_timeslice();
+ tree_timer_2.start();
+
+ /* search the whole area, so all items are returned */
+ plow[0] = -limit - 100;
+ plow[1] = -limit - 100;
+ phigh[0] = limit + 100;
+ phigh[1] = limit + 100;
+
+ SpatialIndex::Region search_region_2 = SpatialIndex::Region(plow, phigh, 2);
+ SearchVisitor vis_2 = SearchVisitor();
+ tree->intersectsWithQuery( search_region_2, vis_2 );
+
+ Timer::Time the_tree_time_2 = tree_timer_2.lap();
+ std::cout << "Rtree (full scan): " << the_tree_time_2 << std::endl;
+
+ return 0;
+}
+
+
+
+/* Adds rectangles in a GList and a SpatialIndex rtree
+ * */
+void add_rectangle( int x, int y ) {
+
+ Geom::Point starting_point = Point( x, y );
+ Geom::Point ending_point = Point( x + 10, y + 10 );
+ Geom::Rect rect_to_add = Rect( starting_point, ending_point );
+ items = g_list_append( items, &rect_to_add );
+
+ if( arg_debug ) {
+ // fetch the last rect from the list
+ Geom::Rect *member_data = (Geom::Rect *)( g_list_last( items ) )->data;
+ double lala = member_data->bottom();
+ std::cout << "List (" << indexID << "): " << lala;
+ }
+
+ /* Create a SpatialIndex region
+ * plow = left-bottom corner
+ * phigh = top-right corner
+ * [0] = dimension X
+ * [1] = dimension Y
+ * */
+ double plow[2], phigh[2];
+
+ plow[0] = rect_to_add.left() ;
+ plow[1] = rect_to_add.bottom();
+ phigh[0] = rect_to_add.right();
+ phigh[1] = rect_to_add.top();
+
+ SpatialIndex::Region r = SpatialIndex::Region(plow, phigh, 2);
+ /* Store Glist pointer size and GList pointer as the associated data
+ * In inkscape this can be used to directly call render hooked functions
+ * from SPCanvasItems
+ * */
+ tree->insertData( sizeof(GList*), reinterpret_cast<const byte*>( g_list_last( items ) ), r, indexID);
+
+ // tree->insertData(0, 0, r, indexID);
+ /* not used. Store zero size and a null pointer as the associated data.
+ * indexId is used to retrieve from a mapping each rect
+ * (example a hash map, or the indexID is also vector index)
+ * */
+
+ if( arg_debug ) {
+ test_indexID = indexID;
+ /* every time we add a rect, search all the tree to find the last
+ * inserted ID. This is not performance-wise good (rtree only good for
+ * spatial queries) this is just used for debugging reasons
+ * */
+ plow[0] = -limit - 100;
+ plow[1] = -limit - 100;
+ phigh[0] = limit + 100;
+ phigh[1] = limit + 100;
+
+ SpatialIndex::Region test_search_region = SpatialIndex::Region(plow, phigh, 2);
+ TestSearchVisitor test_vis = TestSearchVisitor();
+ // search the tree for the region. Visitor implements the search function hooks
+ tree->intersectsWithQuery( test_search_region, test_vis );
+ }
+
+ indexID++;
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)(c-basic-offset . 4))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/tests/rtree-test.cpp b/src/3rdparty/2geom/tests/rtree-test.cpp
new file mode 100644
index 0000000..f01007a
--- /dev/null
+++ b/src/3rdparty/2geom/tests/rtree-test.cpp
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2009 Evangelos Katsikaros <vkatsikaros at yahoo dot gr>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+/*
+ initial toy for redblack trees
+*/
+
+
+#include <2geom/rtree.h>
+
+#include <time.h>
+#include <vector>
+
+#include <sstream>
+#include <getopt.h>
+
+
+
+
+//using std::vector;
+using namespace Geom;
+using namespace std;
+
+sadfsdfasdfasdfa
+
+int main(int argc, char **argv) {
+
+ long test_seed = 1243716824;
+
+ char* min_arg = NULL;
+ char* max_arg = NULL;
+ char* filename_arg = NULL;
+
+ int set_min_max = 0;
+
+ int c;
+
+ while (1)
+ {
+ static struct option long_options[] =
+ {
+ /* These options set a flag. */
+ /* These options don't set a flag.
+ We distinguish them by their indices. */
+ {"min-nodes", required_argument, 0, 'n'},
+ {"max-nodes", required_argument, 0, 'm'},
+ {"input-file", required_argument, 0, 'f'},
+ {"help", no_argument, 0, 'h'},
+ {0, 0, 0, 0}
+ };
+ /* getopt_long stores the option index here. */
+ int option_index = 0;
+
+ c = getopt_long (argc, argv, "n:m:f:h",
+ long_options, &option_index);
+
+ /* Detect the end of the options. */
+ if (c == -1){
+ break;
+ }
+
+ switch (c)
+ {
+ case 'n':
+ min_arg = optarg;
+ set_min_max += 1;
+ break;
+
+
+ case 'm':
+ max_arg = optarg;
+ set_min_max += 2;
+ break;
+
+ case 'f':
+ filename_arg = optarg;
+ set_min_max += 3;
+ break;
+
+
+ case 'h':
+ std::cerr << "Usage: " << argv[0] << " options\n" << std::endl ;
+ std::cerr <<
+ " -n --min-nodes=NUMBER minimum number in node.\n" <<
+ " -m --max-nodes=NUMBER maximum number in node.\n" <<
+ " -f --max-nodes=NUMBER maximum number in node.\n" <<
+ " -h --help Print this help.\n" << std::endl;
+ exit(1);
+ break;
+
+
+ case '?':
+ /* getopt_long already printed an error message. */
+ break;
+
+ default:
+ abort ();
+ }
+ }
+
+ unsigned rmin = 0;
+ unsigned rmax = 0;
+
+ if( set_min_max == 6 ){
+ stringstream s1( min_arg );
+ s1 >> rmin;
+
+ stringstream s2( max_arg );
+ s2 >> rmax;
+
+
+ if( rmax <= rmin || rmax < 2 || rmin < 1 ){
+ std::cerr << "Rtree set to 2, 3" << std::endl ;
+ rmin = 2;
+ rmax = 3;
+ }
+ }
+ else{
+ std::cerr << "Rtree set to 2, 3 ." << std::endl ;
+ rmin = 2;
+ rmax = 3;
+ }
+
+
+
+ std::cout << "rmin: " << rmin << " rmax:" << rmax << " filename_arg:" << filename_arg << std::endl;
+
+ RTree rtree( rmin, rmax, QUADRATIC_SPIT );
+
+ srand(1243716824);
+ rand() % 10;
+
+ return 0;
+}
diff --git a/src/3rdparty/2geom/tests/sbasis-test.cpp b/src/3rdparty/2geom/tests/sbasis-test.cpp
new file mode 100644
index 0000000..045d409
--- /dev/null
+++ b/src/3rdparty/2geom/tests/sbasis-test.cpp
@@ -0,0 +1,268 @@
+#include "testing.h"
+#include <iostream>
+
+#include <2geom/bezier.h>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <vector>
+#include <iterator>
+#include <glib.h>
+
+using namespace std;
+using namespace Geom;
+
+bool are_equal(SBasis const &A, SBasis const &B) {
+ int maxSize = max(A.size(), B.size());
+ double t = 0., dt = 1./maxSize;
+
+ for(int i = 0; i <= maxSize; i++) {
+ EXPECT_FLOAT_EQ(A.valueAt(t), B.valueAt(t));// return false;
+ t += dt;
+ }
+ return true;
+}
+
+class SBasisTest : public ::testing::Test {
+protected:
+ friend class Geom::SBasis;
+ SBasisTest()
+ : zero(fragments[0])
+ , unit(fragments[1])
+ , hump(fragments[2])
+ , wiggle(fragments[3])
+ {
+ zero = SBasis(Bezier(0.0).toSBasis());
+ unit = SBasis(Bezier(0.0,1.0).toSBasis());
+ hump = SBasis(Bezier(0,1,0).toSBasis());
+ wiggle = SBasis(Bezier(0,1,-2,3).toSBasis());
+ }
+
+ SBasis fragments[4];
+ SBasis &zero, &unit, &hump, &wiggle;
+};
+
+TEST_F(SBasisTest, UnitTests) {
+ EXPECT_TRUE(Bezier(0,0,0,0).toSBasis().isZero());
+ EXPECT_TRUE(Bezier(0,1,2,3).toSBasis().isFinite());
+
+ // note: "size" of sbasis equals half the number of coefficients
+ EXPECT_EQ(2u, Bezier(0,2,4,5).toSBasis().size());
+ EXPECT_EQ(2u, hump.size());
+}
+
+TEST_F(SBasisTest, ValueAt) {
+ EXPECT_EQ(0.0, wiggle.at0());
+ EXPECT_EQ(3.0, wiggle.at1());
+ EXPECT_EQ(0.0, wiggle.valueAt(0.5));
+ EXPECT_EQ(0.0, wiggle(0.5));
+}
+
+TEST_F(SBasisTest, MultiDerivative) {
+ vector<double> vnd = wiggle.valueAndDerivatives(0.5, 5);
+ expect_array((const double[]){0,0,12,72,0,0}, vnd);
+}
+ /*
+TEST_F(SBasisTest, DegreeElevation) {
+ EXPECT_TRUE(are_equal(wiggle, wiggle));
+ SBasis Q = wiggle;
+ SBasis P = Q.elevate_degree();
+ EXPECT_EQ(P.size(), Q.size()+1);
+ //EXPECT_EQ(0, P.forward_difference(1)[0]);
+ EXPECT_TRUE(are_equal(Q, P));
+ Q = wiggle;
+ P = Q.elevate_to_degree(10);
+ EXPECT_EQ(10, P.order());
+ EXPECT_TRUE(are_equal(Q, P));
+ //EXPECT_EQ(0, P.forward_difference(10)[0]);
+}*/
+//std::pair<SBasis, SBasis > subdivide(Coord t);
+
+SBasis linear_root(double t) {
+ return SBasis(Linear(0-t, 1-t));
+}
+
+SBasis array_roots(vector<double> x) {
+ SBasis b(1);
+ for(double i : x) {
+ b = multiply(b, linear_root(i));
+ }
+ return b;
+}
+
+ /*TEST_F(SBasisTest, Deflate) {
+ SBasis b = array_roots(vector_from_array((const double[]){0,0.25,0.5}));
+ EXPECT_FLOAT_EQ(0, b.at0());
+ b = b.deflate();
+ EXPECT_FLOAT_EQ(0, b.valueAt(0.25));
+ b = b.subdivide(0.25).second;
+ EXPECT_FLOAT_EQ(0, b.at0());
+ b = b.deflate();
+ const double rootposition = (0.5-0.25) / (1-0.25);
+ EXPECT_FLOAT_EQ(0, b.valueAt(rootposition));
+ b = b.subdivide(rootposition).second;
+ EXPECT_FLOAT_EQ(0, b.at0());
+}*/
+
+TEST_F(SBasisTest, Roots) {
+ expect_array((const double[]){0, 0.5, 0.5}, roots(wiggle));
+
+ // The results of our rootfinding are at the moment fairly inaccurate.
+ double eps = 5e-4;
+
+ vector<vector<double> > tests;
+ tests.push_back(vector_from_array((const double[]){0}));
+ tests.push_back(vector_from_array((const double[]){0.5}));
+ tests.push_back(vector_from_array((const double[]){0.25,0.75}));
+ tests.push_back(vector_from_array((const double[]){0.5,0.5}));
+ tests.push_back(vector_from_array((const double[]){0, 0.2, 0.6,0.6, 1}));
+ tests.push_back(vector_from_array((const double[]){.1,.2,.3,.4,.5,.6}));
+ tests.push_back(vector_from_array((const double[]){0.25,0.25,0.25,0.75,0.75,0.75}));
+
+ for(auto & test : tests) {
+ SBasis b = array_roots(test);
+ std::cout << test << ": " << b << std::endl;
+ std::cout << roots(b) << std::endl;
+ EXPECT_vector_near(test, roots(b), eps);
+ }
+
+ vector<Linear> broken;
+ broken.emplace_back(0, 42350.1);
+ broken.emplace_back(-71082.3, -67071.5);
+ broken.emplace_back(1783.41, 796047);
+ SBasis b(broken);
+ Bezier bz;
+ sbasis_to_bezier(bz, b);
+ cout << "roots(SBasis(broken))\n";
+ for(int i = 0; i < 10; i++) {
+ double t = i*0.01 + 0.1;
+ cout << b(t) << "," << bz(t) << endl;
+ }
+ cout << roots(b) << endl;
+ EXPECT_EQ(0, bz[0]);
+ //bz = bz.deflate();
+ cout << bz << endl;
+ cout << bz.roots() << endl;
+}
+
+TEST_F(SBasisTest, Subdivide) {
+ std::vector<std::pair<SBasis, double> > errors;
+ for (unsigned i = 0; i < 10000; ++i) {
+ double t = g_random_double_range(0, 1e-6);
+ for (auto & input : fragments) {
+ std::pair<SBasis, SBasis> result;
+ result.first = portion(input, 0, t);
+ result.second = portion(input, t, 1);
+
+ // the endpoints must correspond exactly
+ EXPECT_EQ(result.first.at0(), input.at0());
+ EXPECT_EQ(result.first.at1(), result.second.at0());
+ EXPECT_EQ(result.second.at1(), input.at1());
+
+ // ditto for valueAt
+ EXPECT_EQ(result.first.valueAt(0), input.valueAt(0));
+ EXPECT_EQ(result.first.valueAt(1), result.second.valueAt(0));
+ EXPECT_EQ(result.second.valueAt(1), input.valueAt(1));
+
+ if (result.first.at1() != result.second.at0()) {
+ errors.emplace_back(input, t);
+ }
+ }
+ }
+ if (!errors.empty()) {
+ std::cout << "Found " << errors.size() << " subdivision errors" << std::endl;
+ for (unsigned i = 0; i < errors.size(); ++i) {
+ std::cout << "Error #" << i << ":\n"
+ << "SBasis: " << errors[i].first << "\n"
+ << "t: " << format_coord_nice(errors[i].second) << std::endl;
+ }
+ }
+}
+
+TEST_F(SBasisTest, Reverse) {
+ SBasis reverse_wiggle = reverse(wiggle);
+ EXPECT_EQ(reverse_wiggle.at0(), wiggle.at1());
+ EXPECT_EQ(reverse_wiggle.at1(), wiggle.at0());
+ EXPECT_EQ(reverse_wiggle.valueAt(0.5), wiggle.valueAt(0.5));
+ EXPECT_EQ(reverse_wiggle.valueAt(0.25), wiggle.valueAt(0.75));
+ EXPECT_TRUE(are_equal(reverse(reverse_wiggle), wiggle));
+}
+
+TEST_F(SBasisTest,Operators) {
+ //cout << "scalar operators\n";
+ //cout << hump + 3 << endl;
+ //cout << hump - 3 << endl;
+ //cout << hump*3 << endl;
+ //cout << hump/3 << endl;
+
+ //cout << "SBasis derivative(const SBasis & a);\n";
+ //std::cout << derivative(hump) <<std::endl;
+ //std::cout << integral(hump) <<std::endl;
+
+ EXPECT_TRUE(are_equal(derivative(integral(wiggle)), wiggle));
+ //std::cout << derivative(integral(hump)) << std::endl;
+ expect_array((const double []){0.5}, roots(derivative(hump)));
+
+ EXPECT_TRUE(bounds_fast(hump)->contains(Interval(0,hump.valueAt(0.5))));
+
+ EXPECT_EQ(Interval(0,hump.valueAt(0.5)), *bounds_exact(hump));
+
+ Interval tight_local_bounds(min(hump.valueAt(0.3),hump.valueAt(0.6)),
+ hump.valueAt(0.5));
+ EXPECT_TRUE(bounds_local(hump, Interval(0.3, 0.6))->contains(tight_local_bounds));
+
+ SBasis Bs[] = {unit, hump, wiggle};
+ for(auto B : Bs) {
+ SBasis product = multiply(B, B);
+ for(int i = 0; i <= 16; i++) {
+ double t = i/16.0;
+ double b = B.valueAt(t);
+ EXPECT_FLOAT_EQ(b*b, product.valueAt(t));
+ }
+ }
+}
+
+TEST_F(SBasisTest, ToCubicBezier)
+{
+ vector<double> params = { 0, 1, -2, 3 };
+
+ D2<SBasis> sb(wiggle, wiggle);
+ vector<Point> bz;
+ sbasis_to_cubic_bezier(bz, sb);
+ for (int i = 0; i < params.size(); i++) {
+ EXPECT_FLOAT_EQ(bz[i][0], params[i]);
+ EXPECT_FLOAT_EQ(bz[i][1], params[i]);
+ }
+}
+
+TEST_F(SBasisTest, Roundtrip)
+{
+ auto bz1 = Bezier(1, -2, 3, 7, 11, -24, 42, -1, 9, 1);
+ auto sbasis = bz1.toSBasis();
+ Bezier bz2;
+ sbasis_to_bezier(bz2, sbasis);
+ ASSERT_EQ(bz1, bz2);
+
+ std::vector<Point> pts;
+ for (int i = 0; i < bz1.size(); i++) {
+ pts.emplace_back(bz1[i], bz1[i]);
+ }
+ D2<SBasis> sbasis_d2;
+ bezier_to_sbasis(sbasis_d2, pts);
+ ASSERT_EQ(sbasis_d2[X], sbasis);
+ ASSERT_EQ(sbasis_d2[Y], sbasis);
+ D2<Bezier> bz2_d2;
+ sbasis_to_bezier(bz2_d2, sbasis_d2);
+ ASSERT_EQ(bz2_d2[X], bz1);
+ ASSERT_EQ(bz2_d2[Y], bz1);
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/tests/sbasis-text-test.cpp b/src/3rdparty/2geom/tests/sbasis-text-test.cpp
new file mode 100644
index 0000000..ef96407
--- /dev/null
+++ b/src/3rdparty/2geom/tests/sbasis-text-test.cpp
@@ -0,0 +1,225 @@
+#include <iostream>
+#include <math.h>
+#include <cassert>
+#include <2geom/sbasis.h>
+#include <2geom/sbasis-poly.h>
+#include <iterator>
+#include <2geom/point.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/solver.h>
+
+using namespace Geom;
+
+Poly roots_to_poly(double *a, unsigned n) {
+ Poly r;
+ r.push_back(1);
+
+ for(unsigned i = 0; i < n; i++) {
+ Poly p;
+ p.push_back(-a[i]);
+ p.push_back(1);
+ r = r*p;
+ }
+ return r;
+}
+
+unsigned small_rand() {
+ return (rand() & 0xff) + 1;
+}
+
+double uniform() {
+ return double(rand()) / RAND_MAX;
+}
+
+int main() {
+ SBasis P0(Linear(0.5, -1)), P1(Linear(3, 1));
+ Linear one(1,1);
+
+ std::cout << "round tripping of poly conversions\n";
+ std::cout << P0
+ << "=>" << sbasis_to_poly(P0)
+ << "=>" << poly_to_sbasis(sbasis_to_poly(P0))
+ << std::endl;
+
+ std::cout << "derivatives and integrals\n";
+
+ Poly test;
+ for(int i = 0; i < 4; i++)
+ test.push_back(1);
+
+ SBasis test_sb = poly_to_sbasis(test);
+ std::cout << test << "(" << test.size() << ")"
+ << " == "
+ << test_sb << "(" << test_sb.size() << ")"
+ << std::endl;
+ std::cout << "derivative\n";
+ std::cout << derivative(test)
+ << " == "
+ << sbasis_to_poly(derivative(test_sb))
+ << std::endl;
+
+ std::cout << "integral\n";
+ std::cout << integral(test)
+ << " == "
+ << sbasis_to_poly(integral(test_sb))
+ << std::endl;
+
+ std::cout << "evaluation\n";
+ std::cout << integral(test)(0.3) - integral(test)(0.)
+ << " == "
+ << integral(test_sb)(0.3) - integral(test_sb)(0.)
+ << std::endl;
+
+ std::cout << "multiplication\n";
+ std::cout << (test*test)
+ << "\n == \n"
+ << sbasis_to_poly(multiply(test_sb,test_sb))
+ << std::endl;
+ std::cout << poly_to_sbasis(test*test)
+ << "\n == \n"
+ << multiply(test_sb,test_sb)
+ << std::endl;
+
+ std::cout << "sqrt\n";
+ std::cout << test
+ << "\n == \n"
+ << sbasis_to_poly(sqrt(multiply(test_sb,test_sb),10))
+ << std::endl;
+ SBasis radicand = sqrt(test_sb,10);
+ std::cout << sbasis_to_poly(truncate(multiply(radicand, radicand),5))
+ << "\n == \n"
+ << test
+ << std::endl;
+
+ std::cout << "division\n";
+ std::cout << test
+ << "\n == \n"
+ << sbasis_to_poly(divide(multiply(test_sb,test_sb),test_sb, 20))
+ << std::endl;
+ std::cout << divide(test_sb, radicand,5)
+ << "\n == \n"
+ << truncate(radicand,6)
+ << std::endl;
+
+ std::cout << "composition\n";
+ std::cout << (compose(test,sbasis_to_poly(Linear(0.5,1))))
+ << "\n == \n"
+ << sbasis_to_poly(compose(test_sb,Linear(0.5,1)))
+ << std::endl;
+ std::cout << poly_to_sbasis(compose(test,test))
+ << "\n == \n"
+ << compose(test_sb,test_sb)
+ << std::endl
+ << std::endl;
+ std::cout << (compose(sbasis_to_poly(Linear(1,2)),sbasis_to_poly(Linear(-1,0))))
+ << std::endl;
+ std::cout << (compose(SBasis(Linear(1,2)),SBasis(Linear(-1,0))))
+ << std::endl;
+
+ std::cout << "inverse of x - 1\n";
+ std::cout << sbasis_to_poly(inverse(Linear(-1,0),2))
+ << " == y + 1\n";
+ std::cout << "f^-1(f(x)) = "
+ << sbasis_to_poly(compose(inverse(Linear(-1,0),2),
+ Linear(-1,0)))
+ << std::endl
+ << std::endl;
+
+ std::cout << "inverse of 3x - 2\n";
+ std::cout << sbasis_to_poly(inverse(Linear(-2,1),2))
+ << " == (y + 2)/3\n";
+ std::cout << "f^-1(f(x)) = "
+ << sbasis_to_poly(compose(inverse(Linear(-2,1),2),
+ Linear(-2,1)))
+ << std::endl
+ << std::endl;
+
+
+ std::cout << "inverse of sqrt(" << sbasis_to_poly(Linear(1,4)) << ") - 1\n";
+ SBasis A = sqrt(Linear(1,4), 5) - one;
+ Poly P;
+ P.push_back(0);
+ P.push_back(2./3);
+ P.push_back(1./3);
+
+ std::cout << "2 term approximation\n";
+ std::cout << sbasis_to_poly(inverse(A,2))
+ << "\n == \n"
+ << P
+ << std::endl;
+ std::cout << "general approximation\n";
+ std::cout << sbasis_to_poly(inverse(A,5))
+ << "\n == \n"
+ << P
+ << std::endl;
+
+ {
+ std::cout << "inverse of (x^2+2x)/3\n";
+ SBasis A = poly_to_sbasis(P);
+ SBasis I = inverse(A,10);
+ std::cout << sbasis_to_poly(truncate(compose(A, I), 10))
+ << " == x\n"
+ << std::endl;
+ std::cout << sbasis_to_poly(truncate(compose(I, A), 10))
+ << " == x\n"
+ << std::endl;
+ std::cout << sbasis_to_poly(truncate(I - (sqrt(Linear(1,4), 10) - one), 10))
+ << std::endl;
+ }
+#ifdef HAVE_GSL
+ for(int i = 0 ; i < 10; i++) {
+ Poly P;
+ P.push_back(0);
+ P.push_back(1);
+ for(int j = 0 ; j < 2; j++) {
+ P.push_back((uniform()-0.5)/10);
+ }
+ std::vector<std::complex<double> > prod_root = solve(derivative(P));
+ copy(prod_root.begin(), prod_root.end(),
+ std::ostream_iterator<std::complex<double> >(std::cout, ",\t"));
+ std::cout << std::endl;
+ std::cout << "inverse of (" << P << " )\n";
+ for(int k = 1; k < 30; k++) {
+ SBasis A = poly_to_sbasis(P);
+ SBasis I = inverse(A,k);
+ SBasis err = compose(A, I) - Linear(0,1); // ideally is 0
+ std::cout << truncate(err, k).tailError(0)
+ << std::endl;
+ /*std::cout << sbasis_to_poly(err)
+ << " == x\n"
+ << std::endl;*/
+ }
+ }
+#endif
+ /*double roots[] = {0.1,0.2,0.6};
+ Poly prod = roots_to_poly(roots, sizeof(roots)/sizeof(double));
+ std::cout << "real solve\n";
+ std::cout << prod
+ << " solves as ";
+ std::vector<std::complex<double> > prod_root = solve(prod);
+ copy(prod_root.begin(), prod_root.end(),
+ std::ostream_iterator<std::complex<double> >(std::cout, ",\t"));
+ std::cout << std::endl;
+
+ SBasis prod_sb = poly_to_sbasis(prod);
+ std::vector<double> bez = sbasis_to_bezier(prod_sb, prod_sb.size());
+
+ copy(bez.begin(), bez.end(),
+ std::ostream_iterator<double>(std::cout, ",\t"));
+ std::cout << std::endl;*/
+
+ /*std::cout << "crossing count = "
+ << crossing_count(bez, bez.size())
+ << std::endl;*/
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/tests/self-intersections-test.cpp b/src/3rdparty/2geom/tests/self-intersections-test.cpp
new file mode 100644
index 0000000..268273f
--- /dev/null
+++ b/src/3rdparty/2geom/tests/self-intersections-test.cpp
@@ -0,0 +1,219 @@
+/** @file
+ * @brief Unit tests for PathVector::intersectSelf()
+ */
+/*
+ * Authors:
+ * Rafał Siejakowski <rs@rs-math.net>
+ *
+ * Copyright 2022 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <gtest/gtest.h>
+#include <2geom/pathvector.h>
+#include <2geom/svg-path-parser.h>
+
+using namespace Geom;
+
+#define PV(d) (parse_svg_path(d))
+#define PTH(d) (PV(d)[0])
+
+class PVSelfIntersections : public testing::Test
+{
+protected:
+ PathVector const _rectangle, _bowtie, _bowtie_curved, _bowtie_node, _openpath,
+ _open_closed_nonintersecting, _open_closed_intersecting, _tangential, _degenerate_segments,
+ _degenerate_closing, _degenerate_multiple;
+
+ PVSelfIntersections()
+ // A simple rectangle.
+ : _rectangle{PV("M 0,0 L 5,0 5,8 0,8 Z")}
+ // A polyline path with a self-intersection @(2,1).
+ , _bowtie{PV("M 0,0 L 4,2 V 0 L 0,2 Z")}
+ // A curved bow-tie path with a self-intersection @(10,5) between cubic Béziers.
+ , _bowtie_curved{PV("M 0,0 V 10 C 10,10 10,0 20,0 V 10 C 10,10 10,0 0,0 Z")}
+ // As above, but twice as large and the self-intersection @(20,10) happens at a node.
+ , _bowtie_node{PV("M 0,0 V 20 C 0,20 10,20 20,10 25,5 30,0 40,0 V 20 "
+ "C 30,20 25,15 20,10 10,0 0,0 0,0 Z")}
+ // An open path with no self-intersections ◠―◡
+ , _openpath{PV("M 0,0 A 10,10 0,0,1 20,0 L 40,0 Q 50,10 60,0")}
+ // A line and a square with no intersections | â–¡
+ , _open_closed_nonintersecting{PV("M 0,0 V 20 M 10,0 V 20 H 30 V 0 Z")}
+ // A line slicing through a square; two self-intersections ⎅
+ , _open_closed_intersecting{PV("M 10,0 V 40 M 0,10 V 30 H 20 V 10 Z")}
+ // A circle whose diameter precisely coincides with the top side of a rectangle.
+ , _tangential{PV("M 0,0 A 10,10 0,0,1 20,0 A 10,10, 0,0,1 0,0 Z M 0,0 H 20 V 30 H 0 Z")}
+ // A rectangle containing degenerate segments.
+ , _degenerate_segments{PV("M 0,0 H 5 V 4 L 5,4 V 8 H 5 L 5,8 H 0 Z")}
+ // A rectangle with a degenerate closing segment.
+ , _degenerate_closing{PV("M 0,0 H 5 V 8 H 0 L 0,0 Z")}
+ // Multiple consecutive degenerate segments, with a degenerate closing segment in the middle.
+ , _degenerate_multiple{PV("M 0,0 L 0,0 V 0 H 0 L 5,0 V 8 H 0 L 0,0 V 0 H 0 Z")}
+ {
+ }
+};
+
+/* Ensure that no spurious intersections are returned. */
+TEST_F(PVSelfIntersections, NoSpurious)
+{
+ auto empty = PathVector();
+ EXPECT_EQ(empty.intersectSelf().size(), 0u);
+
+ auto r = _rectangle.intersectSelf();
+ EXPECT_EQ(r.size(), 0u);
+
+ auto o = _openpath.intersectSelf();
+ EXPECT_EQ(o.size(), 0u);
+
+ auto n = _open_closed_nonintersecting.intersectSelf();
+ EXPECT_EQ(n.size(), 0u);
+
+ auto d = _degenerate_segments.intersectSelf();
+ EXPECT_EQ(d.size(), 0u);
+
+ auto dc = _degenerate_closing.intersectSelf();
+ EXPECT_EQ(dc.size(), 0u);
+
+ auto dm = _degenerate_multiple.intersectSelf();
+ EXPECT_EQ(dm.size(), 0u);
+
+ auto cusp_node = PTH("M 1 3 C 12 8 42 101 86 133 C 78 168 136 83 80 64");
+ EXPECT_EQ(cusp_node.intersectSelf().size(), 0u);
+}
+
+/* Test figure-eight shaped paths */
+TEST_F(PVSelfIntersections, Bowties)
+{
+ // Simple triangular bowtie: intersection between straight lines
+ auto triangular = _bowtie.intersectSelf();
+ EXPECT_EQ(triangular.size(), 1u);
+ ASSERT_GT(triangular.size(), 0u); // To ensure access to [0]
+ EXPECT_TRUE(are_near(triangular[0].point(), Point(2, 1)));
+
+ // Curved bowtie: intersection between cubic Bézier curves
+ auto curved_intersections = _bowtie_curved.intersectSelf();
+ EXPECT_EQ(curved_intersections.size(), 1u);
+ ASSERT_GT(curved_intersections.size(), 0u);
+ EXPECT_TRUE(are_near(curved_intersections[0].point(), Point(10, 5)));
+
+ // Curved bowtie but the intersection point is a node on both paths
+ auto node_case_intersections = _bowtie_node.intersectSelf();
+ EXPECT_EQ(node_case_intersections.size(), 1u);
+ ASSERT_GT(node_case_intersections.size(), 0u);
+ EXPECT_TRUE(are_near(node_case_intersections[0].point(), Point(20, 10)));
+}
+
+/* Test intersecting an open path with a closed one */
+TEST_F(PVSelfIntersections, OpenClosed)
+{
+ // Square cut by a vertical line
+ auto open_closed = _open_closed_intersecting.intersectSelf();
+ auto const P1 = Point(10, 10);
+ auto const P2 = Point(10, 30);
+
+ ASSERT_EQ(open_closed.size(), 2u); // Prevent crash on out-of-bounds access
+ // This test doesn't care about how the intersections are ordered.
+ bool points_as_expected = (are_near(open_closed[0].point(), P1) && are_near(open_closed[1].point(), P2))
+ || (are_near(open_closed[0].point(), P2) && are_near(open_closed[1].point(), P1));
+ EXPECT_TRUE(points_as_expected);
+}
+
+/* Test some nasty, tangential crossings: a circle with a rectangle built on its diameter. */
+TEST_F(PVSelfIntersections, Tangential)
+{
+ auto circle_x_rect = _tangential.intersectSelf();
+ auto const P1 = Point(0, 0);
+ auto const P2 = Point(20, 0);
+
+ ASSERT_EQ(circle_x_rect.size(), 2u); // Prevent crash on out-of-bounds access
+ // This test doesn't care how the intersections are ordered.
+ bool points_as_expected = (are_near(circle_x_rect[0].point(), P1) && are_near(circle_x_rect[1].point(), P2))
+ || (are_near(circle_x_rect[0].point(), P2) && are_near(circle_x_rect[1].point(), P1));
+ EXPECT_TRUE(points_as_expected);
+}
+
+/* Regression test for issue https://gitlab.com/inkscape/lib2geom/-/issues/33 */
+TEST_F(PVSelfIntersections, Regression33)
+{
+ // Test case provided by Pascal Bies in the issue description.
+ auto const line = LineSegment(Point(486, 597), Point(313, 285));
+ Point const c{580.1377046525328, 325.5830744834947};
+ Point const d{289.35338528516013, 450.62476639303753};
+ auto const curve = CubicBezier(c, c, d, d);
+
+ EXPECT_EQ(curve.intersect(line).size(), 1);
+}
+
+/* Regression test for issue https://gitlab.com/inkscape/lib2geom/-/issues/46 */
+TEST_F(PVSelfIntersections, NumericalInstability)
+{
+ // Test examples provided by M.B. Fraga in the issue report.
+ auto missing_intersection = PTH("M 138 237 C 293 207 129 12 167 106 Q 205 200 309 198 z");
+ auto missing_xings = missing_intersection.intersectSelf();
+ EXPECT_EQ(missing_xings.size(), 2);
+
+ auto duplicate_intersection = PTH("M 60 280 C 60 213 236 227 158 178 S 174 306 127 310 Q 80 314 60 280 z");
+ auto const only_expected = Point(130.9693916417836, 224.587385497877);
+ auto duplicate_xings = duplicate_intersection.intersectSelf();
+ ASSERT_EQ(duplicate_xings.size(), 1);
+ EXPECT_TRUE(are_near(duplicate_xings[0].point(), only_expected));
+}
+
+/* Check various numerically challenging paths consisting of 2 cubic Béziers. */
+TEST_F(PVSelfIntersections, NumericallyChallenging)
+{
+ auto two_kinks = PTH("M 85 88 C 4 425 19 6 72 426 C 128 6 122 456 68 96");
+ EXPECT_EQ(two_kinks.intersectSelf().size(), 3);
+
+ auto omega = PTH("M 47 132 C 179 343 0 78 106 74 C 187 74 0 358 174 106");
+ EXPECT_EQ(omega.intersectSelf().size(), 0);
+
+ auto spider = PTH("M 47 132 C 203 339 0 78 106 74 C 187 74 0 358 174 106");
+ EXPECT_EQ(spider.intersectSelf().size(), 4);
+
+ auto egret = PTH("M 38 340 C 183 141 16 76 255 311 C 10 79 116 228 261 398");
+ EXPECT_EQ(egret.intersectSelf().size(), 0);
+}
+
+/* Test a regression from 88040ea2aeab8ccec2b0e96c7bda2fc7d500d5ec */
+TEST_F(PVSelfIntersections, BigonFiltering)
+{
+ auto const lens = PTH("M 0,0 C 2,1 3,1 5,0 A 2.5,1 0 1 0 0,0 Z");
+ auto const xings = lens.intersectSelf();
+ // This is a simple closed path, so we expect that no self-intersections are reported.
+ EXPECT_EQ(xings.size(), 0);
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/tests/test_pwsb.py b/src/3rdparty/2geom/tests/test_pwsb.py
new file mode 100644
index 0000000..6182d40
--- /dev/null
+++ b/src/3rdparty/2geom/tests/test_pwsb.py
@@ -0,0 +1,67 @@
+#!/usr/bin/python
+
+import sys
+sys.path.append(os.path.join(os.path.dirname(__file__), "..", "py2geom"))
+
+from py2geom import *
+import py2geom
+import numpy
+import random
+from py2geom_glue import *
+
+def poly_to_sbasis(p):
+ sb = SBasis()
+ s = numpy.poly1d([-1, 1, 0])
+ while True:
+ q,r = p / s
+ x = Linear(r[0],r[1]+r[0])
+ sb.append(x)
+ p = q
+ if len(list(p)) <= 1 and p[0] == 0:
+ return sb
+
+def sbasis_to_poly(sb):
+ p = numpy.poly1d([0])
+ s = numpy.poly1d([-1, 1, 0])
+ sp = numpy.poly1d([1])
+ for sbt in sb:
+ p += sp*(sbt[0]*(numpy.poly1d([-1,1])) + sbt[1]*(numpy.poly1d([1,0])))
+ sp *= s
+ return p
+
+random.seed(1)
+trial = numpy.poly1d([random.randrange(0,10) for x in range(6)])
+
+sb = poly_to_sbasis(trial)
+
+pwsb = PiecewiseSBasis()
+pwsb.push_seg(sb)
+pwsb.push_cut(0)
+pwsb.push_cut(1)
+print pwsb.size()
+print "invariants:", pwsb.invariants()
+print pwsb(0)
+
+def l2s(l):
+ sb = py2geom.SBasis()
+ sb.append(l)
+ return sb
+
+X = l2s(py2geom.Linear(0, 1))
+OmX = l2s(py2geom.Linear(1, 0))
+def bezier_to_sbasis(handles, order):
+ print "b2s:", handles, order
+ if(order == 0):
+ return l2s(py2geom.Linear(handles[0]))
+ elif(order == 1):
+ return l2s(py2geom.Linear(handles[0], handles[1]))
+ else:
+ return (py2geom.multiply(OmX, bezier_to_sbasis(handles[:-1], order-1)) +
+ py2geom.multiply(X, bezier_to_sbasis(handles[1:], order-1)))
+
+
+for bz in [[0,1,0], [0,1,2,3]]:
+ sb = bezier_to_sbasis(bz, len(bz)-1)
+ print bz
+ print sb
+ print sbasis_to_bezier(sb,0)
diff --git a/src/3rdparty/2geom/tests/test_py2geom.py b/src/3rdparty/2geom/tests/test_py2geom.py
new file mode 100644
index 0000000..d6ec83e
--- /dev/null
+++ b/src/3rdparty/2geom/tests/test_py2geom.py
@@ -0,0 +1,75 @@
+#!/usr/bin/python
+
+import sys
+sys.path.append(os.path.join(os.path.dirname(__file__), "..", "py2geom"))
+
+from py2geom import *
+import py2geom
+
+P = Point(1,2)
+Q = Point(3,5)
+print P, Q, P+Q
+
+print L2(P)
+print cross(P,Q)
+#print dir(py2geom)
+
+import numpy
+
+ply = numpy.poly1d([1,0,2])
+
+print ply(0.5)
+t = numpy.poly1d([1,0])
+q,r = ply / t
+print q,r
+
+print ply
+print q*t + r
+print ply
+
+def poly_to_sbasis(p):
+ sb = SBasis()
+ s = numpy.poly1d([-1, 1, 0])
+ while True:
+ q,r = p / s
+ #print "r:", r
+ print "r:", repr(r)
+ x = Linear(r[0],r[1]+r[0])
+ sb.append(x)
+ p = q
+ print "q:", repr(p), len(list(p))
+ if len(list(p)) <= 1 and p[0] == 0:
+ return sb
+
+def sbasis_to_poly(sb):
+ p = numpy.poly1d([0])
+ s = numpy.poly1d([-1, 1, 0])
+ sp = numpy.poly1d([1])
+ for sbt in sb:
+ p += sp*(sbt[0]*(numpy.poly1d([-1,1])) + sbt[1]*(numpy.poly1d([1,0])))
+ sp *= s
+ return p
+
+trial = numpy.poly1d([1,0,2])
+sb = poly_to_sbasis(trial)
+print repr(trial),"p2sb:", sb
+print "and back again:", repr(sbasis_to_poly(sb))
+print repr(sbasis_to_poly(derivative(sb))), repr(trial.deriv())
+
+print "unit tests:"
+x = Linear(0,1)
+sb = SBasis()
+sb.append(x)
+print sb
+sb = sb*sb
+print sb
+print sb[0]
+
+print "terms"
+for i in range(6):
+ sb = SBasis()
+ for j in range(3):
+ sb.append(Linear(i==2*j,i==2*j+1))
+ print sb
+
+ print sbasis_to_poly(sb)
diff --git a/src/3rdparty/2geom/tests/testing.h b/src/3rdparty/2geom/tests/testing.h
new file mode 100644
index 0000000..40a588d
--- /dev/null
+++ b/src/3rdparty/2geom/tests/testing.h
@@ -0,0 +1,186 @@
+#include "gtest/gtest.h"
+#include <vector>
+#include <2geom/coord.h>
+#include <2geom/interval.h>
+#include <2geom/intersection.h>
+
+// streams out a vector
+template <class T>
+std::ostream&
+operator<< (std::ostream &out, const std::vector<T,
+ std::allocator<T> > &v)
+{
+ typedef std::ostream_iterator<T, char,
+ std::char_traits<char> > Iter;
+
+ std::copy (v.begin (), v.end (), Iter (out, " "));
+
+ return out;
+}
+
+template <typename T, unsigned xn>
+std::vector<T> vector_from_array(const T (&x)[xn]) {
+ std::vector<T> v;
+ for(unsigned i = 0; i < xn; i++) {
+ v.push_back(x[i]);
+ }
+ return v;
+}
+
+template <typename T, unsigned xn>
+void expect_array(const T (&x)[xn], std::vector<T> y) {
+ EXPECT_EQ(xn, y.size());
+ for(unsigned i = 0; i < y.size(); i++) {
+ EXPECT_EQ(x[i], y[i]);
+ }
+}
+
+Geom::Interval bound_vector(std::vector<double> const &v) {
+ double low = v[0];
+ double high = v[0];
+ for(double i : v) {
+ low = std::min(i, low);
+ high = std::max(i, high);
+ }
+ return Geom::Interval(low-1, high-1);
+}
+
+
+// Custom assertion formatting predicates
+
+template <typename T>
+::testing::AssertionResult ObjectNear(char const *l_expr,
+ char const *r_expr,
+ char const */*eps_expr*/,
+ T const &l,
+ T const &r,
+ Geom::Coord eps)
+{
+ if (!Geom::are_near(l, r, eps)) {
+ return ::testing::AssertionFailure() << "Objects are not near\n"
+ << "First object: " << l_expr << "\n"
+ << "Value: " << l << "\n"
+ << "Second object: " << r_expr << "\n"
+ << "Value: " << r << "\n"
+ << "Threshold: " << Geom::format_coord_nice(eps) << std::endl;
+ }
+ return ::testing::AssertionSuccess();
+}
+
+template <typename T>
+::testing::AssertionResult ObjectNotNear(char const *l_expr,
+ char const *r_expr,
+ char const */*eps_expr*/,
+ T const &l,
+ T const &r,
+ Geom::Coord eps)
+{
+ if (Geom::are_near(l, r, eps)) {
+ return ::testing::AssertionFailure() << "Objects are near\n"
+ << "First object: " << l_expr << "\n"
+ << "Value: " << l << "\n"
+ << "Second object: " << r_expr << "\n"
+ << "Value: " << r << "\n"
+ << "Threshold: " << Geom::format_coord_nice(eps) << std::endl;
+ }
+ return ::testing::AssertionSuccess();
+}
+
+#define EXPECT_near(a, b, eps) EXPECT_PRED_FORMAT3(ObjectNear, a, b, eps)
+#define EXPECT_not_near(a, b, eps) EXPECT_PRED_FORMAT3(ObjectNotNear, a, b, eps)
+
+
+
+template <typename T>
+::testing::AssertionResult VectorEqual(char const *l_expr,
+ char const *r_expr,
+ std::vector<T> const &l,
+ std::vector<T> const &r)
+{
+ if (l.size() != r.size()) {
+ return ::testing::AssertionFailure() << "Vectors differ in size\n"
+ << l_expr << " has size " << l.size() << "\n"
+ << r_expr << " has size " << r.size() << std::endl;
+ }
+ for (unsigned i = 0; i < l.size(); ++i) {
+ if (!(l[i] == r[i])) {
+ return ::testing::AssertionFailure() << "Vectors differ"
+ << "\nVector: " << l_expr
+ << "\nindex " << i << " contains: " << l[i]
+ << "\nVector:" << r_expr
+ << "\nindex " << i << " contains: " << r[i] << std::endl;
+ }
+ }
+ return ::testing::AssertionSuccess();
+}
+
+template <typename T>
+::testing::AssertionResult VectorNear(char const *l_expr,
+ char const *r_expr,
+ char const */*eps_expr*/,
+ std::vector<T> const &l,
+ std::vector<T> const &r,
+ Geom::Coord eps)
+{
+ if (l.size() != r.size()) {
+ return ::testing::AssertionFailure() << "Vectors differ in size\n"
+ << l_expr << "has size " << l.size() << "\n"
+ << r_expr << "has size " << r.size() << std::endl;
+ }
+ for (unsigned i = 0; i < l.size(); ++i) {
+ if (!Geom::are_near(l[i], r[i], eps)) {
+ return ::testing::AssertionFailure() << "Vectors differ by more than "
+ << Geom::format_coord_nice(eps)
+ << "\nVector: " << l_expr
+ << "\nindex " << i << " contains: " << l[i]
+ << "\nVector:" << r_expr
+ << "\nindex " << i << " contains: " << r[i] << std::endl;
+ }
+ }
+ return ::testing::AssertionSuccess();
+}
+
+#define EXPECT_vector_equal(a, b) EXPECT_PRED_FORMAT2(VectorEqual, a, b)
+#define EXPECT_vector_near(a, b, eps) EXPECT_PRED_FORMAT3(VectorNear, a, b, eps)
+
+
+
+template <typename TA, typename TB>
+::testing::AssertionResult IntersectionsValid(
+ char const *l_expr, char const *r_expr, const char */*xs_expr*/, const char */*eps_expr*/,
+ TA const &shape_a, TB const &shape_b,
+ std::vector<Geom::Intersection<typename Geom::ShapeTraits<TA>::TimeType,
+ typename Geom::ShapeTraits<TB>::TimeType> > const &xs,
+ Geom::Coord eps)
+{
+ std::ostringstream os;
+ bool failed = false;
+
+ for (unsigned i = 0; i < xs.size(); ++i) {
+ Geom::Point pa = shape_a.pointAt(xs[i].first);
+ Geom::Point pb = shape_b.pointAt(xs[i].second);
+ if (!Geom::are_near(pa, xs[i].point(), eps) ||
+ !Geom::are_near(pb, xs[i].point(), eps) ||
+ !Geom::are_near(pb, pa, eps))
+ {
+ os << "Intersection " << i << " does not match\n"
+ << Geom::format_coord_nice(xs[i].first) << " evaluates to " << pa << "\n"
+ << Geom::format_coord_nice(xs[i].second) << " evaluates to " << pb << "\n"
+ << "Reported intersection point is " << xs[i].point() << std::endl;
+ failed = true;
+ }
+ }
+
+ if (failed) {
+ return ::testing::AssertionFailure()
+ << "Intersections do not match\n"
+ << "Shape A: " << l_expr << "\n"
+ << "Shape B: " << r_expr << "\n"
+ << os.str()
+ << "Threshold: " << Geom::format_coord_nice(eps) << std::endl;
+ }
+
+ return ::testing::AssertionSuccess();
+}
+
+#define EXPECT_intersections_valid(a, b, xs, eps) EXPECT_PRED_FORMAT4(IntersectionsValid, a, b, xs, eps)
diff --git a/src/3rdparty/2geom/tests/timing-test.cpp b/src/3rdparty/2geom/tests/timing-test.cpp
new file mode 100644
index 0000000..b5714f7
--- /dev/null
+++ b/src/3rdparty/2geom/tests/timing-test.cpp
@@ -0,0 +1,270 @@
+#include <sys/time.h>
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <algorithm>
+#include <assert.h>
+#include <time.h>
+#include <sched.h>
+#include <math.h>
+
+const long long US_PER_SECOND = 1000000L;
+const long long NS_PER_US = 1000L;
+
+using namespace std;
+
+class Timer{
+public:
+ Timer() {}
+ // note that CPU time is tracked per-thread, so the timer is only useful
+ // in the thread it was start()ed from.
+ void start() {
+ usec(start_time);
+ }
+ void lap(long long &us) {
+ usec(us);
+ us -= start_time;
+ }
+ long long lap() {
+ long long us;
+ usec(us);
+ return us - start_time;
+ }
+ void usec(long long &us) {
+ clock_gettime(clock, &ts);
+ us = ts.tv_sec * US_PER_SECOND + ts.tv_nsec / NS_PER_US;
+ }
+ /** Ask the OS nicely for a big time slice */
+ void ask_for_timeslice() {
+ sched_yield();
+ }
+private:
+ long long start_time;
+ struct timespec ts;
+#ifdef _POSIX_THREAD_CPUTIME
+ static const clockid_t clock = CLOCK_THREAD_CPUTIME_ID;
+#else
+# ifdef CLOCK_MONOTONIC
+ static const clockid_t clock = CLOCK_MONOTONIC;
+# else
+ static const clockid_t clock = CLOCK_REALTIME;
+# endif
+#endif
+};
+
+int estimate_useful_window()
+{
+ Timer tm;
+ tm.ask_for_timeslice();
+ int window = 1;
+
+ while(1) {
+ tm.start();
+ for(int i = 0; i < window; i++) {}
+ long long base_line = tm.lap();
+ if(base_line > 1 and window > 100)
+ return window;
+ window *= 2;
+ }
+}
+
+template <typename T>
+string robust_timer(T &t) {
+ static int base_rate = estimate_useful_window();
+ //cout << "base line iterations:" << base_rate << endl;
+ double sum = 0;
+ vector<double> results;
+ const int n_trials = 20;
+ results.reserve(n_trials);
+ for(int trials = 0; trials < n_trials; trials++) {
+ Timer tm;
+ tm.ask_for_timeslice();
+ tm.start();
+ int iters = 0;
+ while(tm.lap() < 10000) {
+ for(int i = 0; i < base_rate; i++)
+ t();
+ iters+=base_rate;
+ }
+ base_rate = iters;
+ double lap_time = double(tm.lap());
+ double individual_time = lap_time/base_rate;
+ sum += individual_time;
+ results.push_back(individual_time);
+ //cout << individual_time << endl;
+ }
+ double resS = 0;
+ double resN = 0;
+ sort(results.begin(), results.end());
+ double ave = results[results.size()/2];//sum/n_trials; // median
+ //cout << "median:" << ave << endl;
+ double least = ave;
+ double resSS = 0;
+ for(int i = 0; i < n_trials; i++) {
+ double dt = results[i];
+ if(dt <= ave*1.1) {
+ resS += dt;
+ resN += 1;
+ resSS += dt*dt;
+ if(least < dt)
+ least = dt;
+ }
+ }
+
+ double filtered_ave = resS / resN;
+ double stddev = sqrt((resSS - 2*resS*filtered_ave + resN*filtered_ave*filtered_ave)/(resN-1)); // sum(x-u)^2 = sum(x^2-2xu+u*u)
+ assert (least > filtered_ave*0.7); // If this throws something was really screwy
+ std::basic_stringstream<char> ss;
+ ss << filtered_ave << " +/-" << stddev << "us";
+ return ss.str();
+}
+
+struct nop{
+ void operator()() const {}
+};
+
+#define degenerate_imported 1
+#include "degenerate.cpp"
+using namespace Geom;
+
+template <typename T>
+struct copy{
+ T a, b;
+ void operator()() {
+ T c = a;
+ }
+};
+
+template <typename T>
+struct add{
+ T a, b;
+ void operator()() {
+ T c = a + b;
+ }
+};
+
+template <typename T>
+struct add_mutate{
+ T a, b;
+ void operator()() {
+ a += b;
+ }
+};
+
+template <typename T>
+struct scale{
+ T a;
+ double b;
+ void operator()() {
+ T c = a * b;
+ }
+};
+
+template <typename T>
+struct scale_mutate{
+ T a;
+ double b;
+ void operator()() {
+ a *= b;
+ }
+};
+
+template <typename T>
+struct mult{
+ T a, b;
+ void operator()() {
+ T c = a * b;
+ }
+};
+
+template <typename T>
+struct mult_mutate{
+ T a, b, c;
+ void operator()() {
+ c = a;
+ c *= b;
+ }
+};
+
+template <typename T>
+void basic_arith(T const & a, T const & b) {
+ {
+ ::copy<T> A;
+ A.a = a;
+ A.b = b;
+ cout << "copy:"
+ << robust_timer(A) << endl;
+ }
+ {
+ add<T> A;
+ A.a = a;
+ A.b = b;
+ cout << "add:"
+ << robust_timer(A) << endl;
+ }
+ {
+ add_mutate<T> A;
+ A.a = a;
+ A.b = b;
+ cout << "add_mutate:"
+ << robust_timer(A) << endl;
+ }
+ {
+ ::scale<T> A;
+ A.a = a;
+ A.b = 1;
+ cout << "scale:"
+ << robust_timer(A) << endl;
+ }
+ {
+ scale_mutate<T> A;
+ A.a = a;
+ A.b = 1;
+ cout << "scale_mutate:"
+ << robust_timer(A) << endl;
+ }
+ {
+ mult<T> A;
+ A.a = a;
+ A.b = b;
+ cout << "mult:"
+ << robust_timer(A) << endl;
+ }
+ {
+ mult_mutate<T> A;
+ A.a = a;
+ A.b = b;
+ cout << "mult_mutate:"
+ << robust_timer(A) << endl;
+ }
+
+}
+
+#include <valarray>
+#include <2geom/orphan-code/sbasisN.h>
+#include <2geom/piecewise.h>
+int main(int /*argc*/, char** /*argv*/) {
+
+ {
+ nop N;
+ cout << "nop:" << robust_timer(N) << endl;
+ }
+
+ vector<SBasis> sbs;
+ valarray<double> va(4), vb(4);
+ generate_random_sbasis(sbs);
+ cout << "double\n";
+ basic_arith(sbs[0][0][0], sbs[1][0][0]);
+ cout << "valarray\n";
+ basic_arith(va, vb);
+ //cout << "Linear\n";
+ //basic_arith(sbs[0][0], sbs[1][0]);
+ cout << "SBasis\n";
+ basic_arith(sbs[0], sbs[1]);
+ cout << "pw<SBasis>\n";
+ basic_arith(Piecewise<SBasis>(sbs[0]), Piecewise<SBasis>(sbs[1]));
+ /*cout << "SBasisN<1>\n";
+ SBasisN<1> sbnA = sbs[0];
+ SBasisN<1> sbnB = sbs[0];
+ basic_arith(sbnA, sbnB);*/
+}
diff --git a/src/3rdparty/2geom/tests/utest.h b/src/3rdparty/2geom/tests/utest.h
new file mode 100644
index 0000000..eda1eb4
--- /dev/null
+++ b/src/3rdparty/2geom/tests/utest.h
@@ -0,0 +1,134 @@
+#ifndef SEEN_UTEST_UTEST_H
+#define SEEN_UTEST_UTEST_H
+
+/* Ultra-minimal unit testing framework */
+/* This file is in the public domain */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <setjmp.h>
+//#include <glib/gstrfuncs.h> /* g_strdup_printf */
+#ifdef __cplusplus
+};
+#endif
+
+jmp_buf utest__jmp_buf;
+int utest__tests;
+int utest__passed;
+int utest__running;
+const char *utest__name;
+
+/** \brief Initializes the framework for running a series of tests.
+ * \param name A descriptive label for this series of tests.
+ */
+void utest_start(const char *name) {
+ printf("Testing %s...\n", name);
+ utest__name = name;
+ utest__tests = utest__passed = 0;
+ utest__running = 0;
+}
+
+void utest__pass(void) {
+ utest__passed++;
+ utest__running = 0;
+ printf("OK\n");
+}
+
+
+/** \brief Write \a a, \a b, \a c, and exit the current block of tests.
+ *
+ * In the current implementation, any of \a a, \a b, \a c may be NULL, considered equivalent to
+ * empty string; but don't rely on that unless you also change this documentation string. (No
+ * callers use this functionality at the time of writing.)
+ *
+ * No newline needed in the arguments.
+ */
+int
+utest__fail(const char *a, const char *b, const char *c)
+{
+ utest__running = 0;
+ fflush(stdout);
+ fprintf (stderr, "%s%s%s\n",
+ (a ? a : ""),
+ (b ? b : ""),
+ (c ? c : ""));
+ fflush(stderr);
+ longjmp(utest__jmp_buf, 0);
+ return 0;
+}
+
+
+/** \brief Marks a C block constituting a single test.
+ * \param name A descriptive name for this test.
+ *
+ * The block effectively becomes a try statement; if code within the
+ * block triggers an assertion, control will resume at the end of the
+ * block.
+ */
+#define UTEST_TEST(name) if (!setjmp(utest__jmp_buf)&&utest__test((name)))
+
+/** \brief Terminates the current test if \a cond evaluates to nonzero.
+ * \param cond The condition to test.
+ */
+#define UTEST_ASSERT(cond) UTEST_NAMED_ASSERT( #cond, (cond))
+
+/** \brief Terminates the current tests if \a _cond evaluates to nonzero,
+ * and prints a descriptive \a _name instead of the condition
+ * that caused it to fail.
+ * \param _name The descriptive label to use.
+ * \param _cond The condition to test.
+ */
+#define UTEST_NAMED_ASSERT(_name, _cond) static_cast<void>((_cond) || utest__fail("Assertion `", (_name), "' failed"))
+
+#define UTEST_ASSERT_SHOW(_cond, _printf_args) \
+ static_cast<void>((_cond) \
+ || (utest__fail("\nAssertion `" #_cond "' failed; ", "", \
+ g_strdup_printf _printf_args)))
+
+int utest__test(const char *name) {
+ utest__tests++;
+ if (utest__running) {
+ utest__pass();
+ }
+ printf("\t%s...", name);
+ fflush(stdout);
+ utest__running = 1;
+ return 1;
+}
+
+/** \brief Ends a series of tests, reporting test statistics.
+ *
+ * Test statistics are printed to stdout or stderr, then the function returns
+ * nonzero iff all the tests have passed, zero otherwise.
+ */
+int utest_end(void) {
+ if (utest__running) {
+ utest__pass();
+ }
+ if ( utest__passed == utest__tests ) {
+ printf("%s: OK (all %d passed)\n",
+ utest__name, utest__tests);
+ return 1;
+ } else {
+ fflush(stdout);
+ fprintf(stderr, "%s: FAILED (%d/%d tests passed)\n",
+ utest__name, utest__passed, utest__tests);
+ fflush(stderr);
+ return 0;
+ }
+}
+
+
+#endif /* !SEEN_UTEST_UTEST_H */
+
+/*
+ Local Variables:
+ mode:c
+ c-file-style:"linux"
+ fill-column:99
+ End:
+*/
+// vim: filetype=c:noexpandtab:shiftwidth=8:tabstop=8:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/2geom/tools/lib2geom_gdb.py b/src/3rdparty/2geom/tools/lib2geom_gdb.py
new file mode 100644
index 0000000..f98421c
--- /dev/null
+++ b/src/3rdparty/2geom/tools/lib2geom_gdb.py
@@ -0,0 +1,107 @@
+import gdb.printing
+import math
+
+def xstr(val):
+ if val.is_optimized_out:
+ return "<optimized out>"
+ else:
+ return str(val)
+
+class GeomPointPrinter:
+ def __init__(self, val):
+ self.val = val
+ def to_string(self):
+ return "(" + xstr(self.val["_pt"][0]) + ", " + xstr(self.val["_pt"][1]) + ")"
+
+class GeomIntervalPrinter:
+ def __init__(self, val):
+ self.val = val
+ def to_string(self):
+ return "[" + xstr(self.val["_b"][0]) + ", " + xstr(self.val["_b"][1]) + ")"
+
+class GeomOptIntervalPrinter:
+ def __init__(self, val):
+ self.val = val
+ def to_string(self):
+ if self.val["m_initialized"]:
+ addr = self.val["m_storage"]["dummy_"]["data"].address
+ if self.val.type == gdb.lookup_type('Geom::OptInterval'):
+ return str(addr.cast(gdb.lookup_type('Geom::Interval').pointer()).dereference())
+ else:
+ return str(addr.cast(gdb.lookup_type('Geom::GenericInterval<int>').pointer()).dereference())
+ else:
+ return "empty"
+
+class GeomRectPrinter:
+ def __init__(self, val):
+ self.val = val
+ def to_string(self):
+ return str(self.val["f"][0]) + " x " + str(self.val["f"][1])
+
+class GeomOptRectPrinter:
+ def __init__(self, val):
+ self.val = val
+ def to_string(self):
+ if self.val["m_initialized"]:
+ addr = self.val["m_storage"]["dummy_"]["data"].address
+ if self.val.type == gdb.lookup_type('Geom::OptRect'):
+ return str(addr.cast(gdb.lookup_type('Geom::Rect').pointer()).dereference())
+ else:
+ return str(addr.cast(gdb.lookup_type('Geom::GenericRect<int>').pointer()).dereference())
+ else:
+ return "empty"
+
+class GeomAffinePrinter:
+ def __init__(self, val):
+ self.val = val
+ def to_string(self):
+ return ("\n | %8f %8f 0 |" +
+ "\n | %8f %8f 0 |" +
+ "\n | %8f %8f 1 |") % tuple(self.val["_c"][x] for x in range(0,6))
+
+class GeomTranslatePrinter:
+ def __init__(self, val):
+ self.val = val
+ def to_string(self):
+ return "translate by " + str(self.val["vec"])
+
+class GeomScalePrinter:
+ def __init__(self, val):
+ self.val = val
+ def to_string(self):
+ return "scale by " + str(self.val["vec"])
+
+class GeomRotatePrinter:
+ def __init__(self, val):
+ self.val = val
+ def to_string(self):
+ x = self.val["vec"][0]
+ y = self.val["vec"][1]
+ angle = math.atan2(y, x) / math.pi * 180.0
+ return "rotate by %s = %f degrees" % (str(self.val["vec"]), angle)
+
+class GeomZoomPrinter:
+ def __init__(self, val):
+ self.val = val
+ def to_string(self):
+ return "zoom %f%% at %s" % (self.val["_scale"] * 100, str(self.val["_trans"]))
+
+
+def lib2geom_pretty_printer():
+ pp = gdb.printing.RegexpCollectionPrettyPrinter("lib2geom")
+ pp.add_printer('Geom::Point', '^Geom::(Int)?Point$', GeomPointPrinter)
+ pp.add_printer('Geom::Interval', '^(Geom::Interval|Geom::GenericInterval<int>)$', GeomIntervalPrinter)
+ pp.add_printer('Geom::OptInterval', '^(Geom::OptInterval|Geom::GenericOptInterval<int>)$', GeomOptIntervalPrinter)
+ pp.add_printer('Geom::Rect', '^(Geom::Rect|Geom::GenericRect<int>)$', GeomRectPrinter)
+ pp.add_printer('Geom::OptRect', '^(Geom::OptRect|Geom::GenericOptRect<int>)$', GeomOptRectPrinter)
+ pp.add_printer('Geom::Affine', '^Geom::Affine$', GeomAffinePrinter)
+ pp.add_printer('Geom::Translate', '^Geom::Translate$', GeomTranslatePrinter)
+ pp.add_printer('Geom::Scale', '^Geom::Scale', GeomScalePrinter)
+ pp.add_printer('Geom::Rotate', '^Geom::Rotate$', GeomRotatePrinter)
+ pp.add_printer('Geom::Zoom', '^Geom::Zoom$', GeomZoomPrinter)
+ return pp
+
+def register_lib2geom_printers():
+ gdb.printing.register_pretty_printer(
+ gdb.current_objfile(),
+ lib2geom_pretty_printer())
diff --git a/src/3rdparty/2geom/toy.pc.in b/src/3rdparty/2geom/toy.pc.in
new file mode 100644
index 0000000..e2e64f7
--- /dev/null
+++ b/src/3rdparty/2geom/toy.pc.in
@@ -0,0 +1,13 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: toy
+Description: A library for creating toy apps for 2geom
+Version: @2GEOM_VERSION@
+
+Requires: 2geom
+Libs: -L${libdir} -l2geom
+Cflags: -I${includedir}/2geom
+
diff --git a/src/3rdparty/CMakeLists.txt b/src/3rdparty/CMakeLists.txt
new file mode 100644
index 0000000..0c70845
--- /dev/null
+++ b/src/3rdparty/CMakeLists.txt
@@ -0,0 +1,34 @@
+add_subdirectory(libuemf)
+add_subdirectory(libcroco)
+add_subdirectory(libdepixelize)
+add_subdirectory(adaptagrams)
+add_subdirectory(autotrace)
+
+if(WITH_INTERNAL_2GEOM)
+ set(2GEOM_BUILD_SHARED ${BUILD_SHARED_LIBS} CACHE BOOL "")
+ add_subdirectory(2geom)
+endif()
+
+if(WITH_INTERNAL_CAIRO)
+ include(ExternalProject)
+ # Used by windows CI/CD/packaging, Linux appimages
+
+ # Change, don't remove options.
+ # Otherwise the values are not reset in existing builds.
+ set(CAIRO_CONF --buildtype=debugoptimized -Dgtk_doc=false)
+ if (NOT WIN32)
+ set(CAIRO_CONF ${CAIRO_CONF} --prefix=${CMAKE_INSTALL_PREFIX})
+ endif()
+
+ ExternalProject_Add(cairo_ext
+ PREFIX cairo
+ GIT_REPOSITORY https://gitlab.com/inkscape/deps/cairo.git
+ GIT_TAG NAMED_12cd2bcbb260f4ed64a72b64bd2fdd593f683bbc
+ GIT_SHALLOW TRUE
+ SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/cairo
+ PATCH_COMMAND git checkout ${CMAKE_CURRENT_SOURCE_DIR}/cairo/src && git apply --unsafe-paths --directory ${CMAKE_CURRENT_SOURCE_DIR}/cairo/ ${CMAKE_SOURCE_DIR}/packaging/cairo.patch
+ CONFIGURE_COMMAND meson setup . ${CMAKE_CURRENT_SOURCE_DIR}/cairo && meson setup --reconfigure ${CAIRO_CONF} . ${CMAKE_CURRENT_SOURCE_DIR}/cairo
+ BUILD_COMMAND meson compile
+ INSTALL_COMMAND meson install
+ )
+endif()
diff --git a/src/3rdparty/adaptagrams/CMakeLists.txt b/src/3rdparty/adaptagrams/CMakeLists.txt
new file mode 100644
index 0000000..60db79d
--- /dev/null
+++ b/src/3rdparty/adaptagrams/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_subdirectory(libavoid)
+add_subdirectory(libcola)
+add_subdirectory(libvpsc)
diff --git a/src/3rdparty/adaptagrams/libavoid/CMakeLists.txt b/src/3rdparty/adaptagrams/libavoid/CMakeLists.txt
new file mode 100644
index 0000000..e14f8ea
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/CMakeLists.txt
@@ -0,0 +1,58 @@
+
+set(libavoid_SRC
+ actioninfo.cpp
+ connectionpin.cpp
+ connector.cpp
+ connend.cpp
+ geometry.cpp
+ geomtypes.cpp
+ graph.cpp
+ hyperedge.cpp
+ hyperedgeimprover.cpp
+ hyperedgetree.cpp
+ junction.cpp
+ makepath.cpp
+ mtst.cpp
+ obstacle.cpp
+ orthogonal.cpp
+ router.cpp
+ scanline.cpp
+ shape.cpp
+ timer.cpp
+ vertices.cpp
+ viscluster.cpp
+ visibility.cpp
+ vpsc.cpp
+
+
+ # -------
+ # Headers
+ actioninfo.h
+ assertions.h
+ connectionpin.h
+ connector.h
+ connend.h
+ debug.h
+ geometry.h
+ geomtypes.h
+ graph.h
+ hyperedge.h
+ hyperedgeimprover.h
+ hyperedgetree.h
+ junction.h
+ libavoid.h
+ makepath.h
+ mtst.h
+ obstacle.h
+ orthogonal.h
+ router.h
+ scanline.h
+ shape.h
+ timer.h
+ vertices.h
+ viscluster.h
+ visibility.h
+ vpsc.h
+)
+include_directories("${CMAKE_CURRENT_SOURCE_DIR}/..")
+add_inkscape_lib(avoid_LIB "${libavoid_SRC}")
diff --git a/src/3rdparty/adaptagrams/libavoid/Doxyfile b/src/3rdparty/adaptagrams/libavoid/Doxyfile
new file mode 100644
index 0000000..929c6d3
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/Doxyfile
@@ -0,0 +1,2423 @@
+# Doxyfile 1.8.13
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = libavoid
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = doc
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = YES
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = YES
+
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 0.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS = 0
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = NO
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = YES
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO, these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = YES
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES, upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS = LIBAVOID_DOC
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered.
+# The default value is: NO.
+
+WARN_AS_ERROR = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = . \
+ doc
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
+# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
+# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf.
+
+FILE_PATTERNS = *.cpp \
+ *.h \
+ *.doc
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = NO
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER = doc/header.html
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE =
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = NONE
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
+# with syntax highlighting in the RTF output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_SOURCE_CODE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sf.net) file that captures the
+# structure of the code including all documentation. Note that this feature is
+# still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+
+PLANTUML_JAR_PATH =
+
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
diff --git a/src/3rdparty/adaptagrams/libavoid/LICENSE.LGPL b/src/3rdparty/adaptagrams/libavoid/LICENSE.LGPL
new file mode 100644
index 0000000..9c8ccde
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/LICENSE.LGPL
@@ -0,0 +1,460 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/Makefile.am b/src/3rdparty/adaptagrams/libavoid/Makefile.am
new file mode 100644
index 0000000..837dacb
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/Makefile.am
@@ -0,0 +1,91 @@
+EXTRA_DIST=libavoid.pc.in
+
+lib_LTLIBRARIES = libavoid.la
+libavoid_la_CPPFLAGS = -I$(top_srcdir) -I$(includedir)/libavoid -fPIC
+libavoid_la_LDFLAGS = -no-undefined
+
+libavoid_la_SOURCES = connectionpin.cpp \
+ connector.cpp \
+ connend.cpp \
+ geometry.cpp \
+ geomtypes.cpp \
+ graph.cpp \
+ junction.cpp \
+ makepath.cpp \
+ obstacle.cpp \
+ orthogonal.cpp \
+ router.cpp \
+ shape.cpp \
+ timer.cpp \
+ vertices.cpp \
+ viscluster.cpp \
+ visibility.cpp \
+ vpsc.cpp \
+ hyperedge.cpp \
+ hyperedgeimprover.cpp \
+ mtst.cpp \
+ hyperedgetree.cpp \
+ scanline.cpp \
+ actioninfo.cpp \
+ assertions.h \
+ connector.h \
+ connectionpin.h \
+ connend.h \
+ debug.h \
+ geometry.h \
+ geomtypes.h \
+ graph.h \
+ junction.h \
+ libavoid.h \
+ makepath.h \
+ obstacle.h \
+ orthogonal.h \
+ router.h \
+ shape.h \
+ timer.h \
+ vertices.h \
+ viscluster.h \
+ visibility.h \
+ hyperedge.h \
+ mtst.h \
+ hyperedgetree.h \
+ scanline.h \
+ actioninfo.h \
+ vpsc.h \
+ debughandler.h
+
+libavoidincludedir = $(includedir)/libavoid
+libavoidinclude_HEADERS = assertions.h \
+ connector.h \
+ connectionpin.h \
+ connend.h \
+ debug.h \
+ dllexport.h \
+ geometry.h \
+ geomtypes.h \
+ graph.h \
+ junction.h \
+ libavoid.h \
+ makepath.h \
+ obstacle.h \
+ orthogonal.h \
+ router.h \
+ shape.h \
+ timer.h \
+ vertices.h \
+ viscluster.h \
+ visibility.h \
+ hyperedge.h \
+ hyperedgeimprover.h \
+ mtst.h \
+ hyperedgetree.h \
+ scanline.h \
+ actioninfo.h \
+ vpsc.h \
+ debughandler.h
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = libavoid.pc
+
+SUBDIRS = . tests
+
diff --git a/src/3rdparty/adaptagrams/libavoid/README b/src/3rdparty/adaptagrams/libavoid/README
new file mode 100644
index 0000000..fe62f13
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/README
@@ -0,0 +1,35 @@
+libavoid - Fast, Incremental, Object-avoiding Line Router
+
+Copyright (C) 2004-2009 Monash University
+
+A cross-platform C++ library providing fast, object-avoiding connector
+routing for use in interactive diagram editors.
+
+Documentation is available for libavoid through Doxygen. Install Doxygen and
+run it in the libavoid directory to generate documentation for the interface.
+
+libavoid is written and maintained by Michael Wybrow, a member of the
+Adaptive Diagrams and Documents lab at Monash University, Australia.
+
+libavoid is available under the terms of open-source GNU Lesser General Public
+License v2.1. Commercial licenses are also available, for more information
+please contact Michael Wybrow <http://www.csse.monash.edu.au/~mwybrow/>.
+
+The algorithms used for the connector routing are described in:
+
+ M. Wybrow, K. Marriott, and P.J. Stuckey. Incremental connector routing.
+ In Proceedings of 13th International Symposium on Graph Drawing, LNCS 3843,
+ pages 446-457. Springer-Verlag, 2006.
+ http://www.csse.monash.edu.au/~mwybrow/papers/wybrow-gd-2005.pdf
+
+ M. Wybrow, K. Marriott, and P.J. Stuckey. Orthogonal connector routing.
+ In Proceedings of 17th International Symposium on Graph Drawing (GD '09),
+ To appear 2010.
+ http://www.csse.monash.edu.au/~mwybrow/papers/wybrow-gd-2009.pdf
+
+libavoid is currently used in the prototype research diagram editor "Dunnart":
+ http://www.csse.monash.edu.au/~mwybrow/dunnart/
+As well as the professional open-source vector graphics editor "Inkscape":
+ http://www.inkscape.org/
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/actioninfo.cpp b/src/3rdparty/adaptagrams/libavoid/actioninfo.cpp
new file mode 100644
index 0000000..b896cb9
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/actioninfo.cpp
@@ -0,0 +1,187 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2011 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+
+#include <algorithm>
+
+#include "libavoid/actioninfo.h"
+#include "libavoid/shape.h"
+#include "libavoid/connector.h"
+#include "libavoid/junction.h"
+
+namespace Avoid {
+
+
+ActionInfo::ActionInfo(ActionType t, ShapeRef *s, const Polygon& p, bool fM)
+ : type(t),
+ objPtr(s),
+ newPoly(p),
+ firstMove(fM)
+{
+ COLA_ASSERT(type == ShapeMove);
+}
+
+
+ActionInfo::ActionInfo(ActionType t, ShapeRef *s)
+ : type(t),
+ objPtr(s)
+
+{
+ COLA_ASSERT((type == ShapeAdd) || (type == ShapeRemove) ||
+ (type == ShapeMove));
+}
+
+
+ActionInfo::ActionInfo(ActionType t, JunctionRef *j, const Point& p)
+ : type(t),
+ objPtr(j),
+ newPosition(p)
+{
+ COLA_ASSERT(type == JunctionMove);
+}
+
+
+ActionInfo::ActionInfo(ActionType t, JunctionRef *j)
+ : type(t),
+ objPtr(j)
+{
+ COLA_ASSERT((type == JunctionAdd) || (type == JunctionRemove) ||
+ (type == JunctionMove));
+}
+
+ActionInfo::ActionInfo(ActionType t, ConnRef *c)
+ : type(t),
+ objPtr(c)
+{
+ COLA_ASSERT(type == ConnChange);
+}
+
+
+ActionInfo::ActionInfo(ActionType t, ShapeConnectionPin *p)
+ : type(t),
+ objPtr(p)
+{
+ COLA_ASSERT(type == ConnectionPinChange);
+}
+
+
+ActionInfo::~ActionInfo()
+{
+}
+
+
+Obstacle *ActionInfo::obstacle(void) const
+{
+ COLA_ASSERT((type == ShapeMove) || (type == ShapeAdd) ||
+ (type == ShapeRemove) || (type == JunctionMove) ||
+ (type == JunctionAdd) || (type == JunctionRemove));
+ return (static_cast<Obstacle *> (objPtr));
+}
+
+
+ShapeRef *ActionInfo::shape(void) const
+{
+ return (dynamic_cast<ShapeRef *> (obstacle()));
+}
+
+
+ConnRef *ActionInfo::conn(void) const
+{
+ COLA_ASSERT(type == ConnChange);
+ return (static_cast<ConnRef *> (objPtr));
+}
+
+JunctionRef *ActionInfo::junction(void) const
+{
+ return (dynamic_cast<JunctionRef *> (obstacle()));
+}
+
+
+void ActionInfo::addConnEndUpdate(const unsigned int type,
+ const ConnEnd& connEnd, bool isConnPinMoveUpdate)
+{
+ bool alreadyExists = false;
+ for (ConnUpdateList::iterator conn = conns.begin();
+ conn != conns.end(); ++conn)
+ {
+ // Look for an existing queued change to the same end.
+ if (conn->first == type)
+ {
+ // Found a queued change to the same endpoint of the
+ // connector. If this is a pin change as a result of a
+ // shape move, then leave the user created update
+ // that was found (since it may be moving the connection
+ // to connect to a different shape/pin. But if this is a
+ // user change, then overwrite the previous change.
+ alreadyExists = true;
+ if (!isConnPinMoveUpdate)
+ {
+ // Overwrite the queued change with this one.
+ conn->second = connEnd;
+ }
+ break;
+ }
+ }
+
+ if (!alreadyExists)
+ {
+ // Matching change not found, so add this one.
+ conns.push_back(std::make_pair(type, connEnd));
+ }
+}
+
+
+bool ActionInfo::operator==(const ActionInfo& rhs) const
+{
+ return (type == rhs.type) && (objPtr == rhs.objPtr);
+}
+
+
+bool ActionInfo::operator<(const ActionInfo& rhs) const
+{
+ if (type != rhs.type)
+ {
+ return type < rhs.type;
+ }
+
+ if (type == ConnChange)
+ {
+ return conn()->id() < rhs.conn()->id();
+ }
+ else if (type == ConnectionPinChange)
+ {
+ // NOTE Comparing pointers may not preserve the order of
+ // objects, but the order of Connection Pins is not
+ // used so this is not an issue here.
+ return objPtr < rhs.objPtr;
+ }
+ else
+ {
+ return obstacle()->id() < rhs.obstacle()->id();
+ }
+}
+
+
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/actioninfo.h b/src/3rdparty/adaptagrams/libavoid/actioninfo.h
new file mode 100644
index 0000000..32f009f
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/actioninfo.h
@@ -0,0 +1,88 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2011 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+#ifndef AVOID_ACTIONINFO_H
+#define AVOID_ACTIONINFO_H
+
+#include <list>
+
+#include "libavoid/actioninfo.h"
+#include "libavoid/connend.h"
+#include "libavoid/geomtypes.h"
+
+namespace Avoid {
+
+// This class is not intended for public use.
+// It is used internally by Router to track actions performed on objects
+// during transactions.
+
+
+
+class ShapeRef;
+class JunctionRef;
+
+
+enum ActionType {
+ ShapeMove,
+ ShapeAdd,
+ ShapeRemove,
+ JunctionMove,
+ JunctionAdd,
+ JunctionRemove,
+ ConnChange,
+ ConnectionPinChange
+};
+
+typedef std::list<std::pair<unsigned int, ConnEnd> > ConnUpdateList;
+
+class ActionInfo {
+ public:
+ ActionInfo(ActionType t, ShapeRef *s, const Polygon& p, bool fM);
+ ActionInfo(ActionType t, ShapeRef *s);
+ ActionInfo(ActionType t, JunctionRef *j, const Point& p);
+ ActionInfo(ActionType t, JunctionRef *j);
+ ActionInfo(ActionType t, ConnRef *c);
+ ActionInfo(ActionType t, ShapeConnectionPin *p);
+ ~ActionInfo();
+ Obstacle *obstacle(void) const;
+ ShapeRef *shape(void) const;
+ ConnRef *conn(void) const;
+ JunctionRef *junction(void) const;
+ void addConnEndUpdate(const unsigned int type, const ConnEnd& connEnd,
+ bool isConnPinMoveUpdate);
+ bool operator==(const ActionInfo& rhs) const;
+ bool operator<(const ActionInfo& rhs) const;
+
+ ActionType type;
+ void *objPtr;
+ Polygon newPoly;
+ Point newPosition;
+ bool firstMove;
+ ConnUpdateList conns;
+};
+typedef std::list<ActionInfo> ActionInfoList;
+
+
+}
+#endif
diff --git a/src/3rdparty/adaptagrams/libavoid/assertions.h b/src/3rdparty/adaptagrams/libavoid/assertions.h
new file mode 100644
index 0000000..1715622
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/assertions.h
@@ -0,0 +1,60 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2009 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+#ifndef AVOID_ASSERTIONS_H
+#define AVOID_ASSERTIONS_H
+
+#define COLA_UNUSED(expr) do { (void)(expr); } while (0)
+
+#ifdef NDEBUG
+
+ #define COLA_ASSERT(expr) static_cast<void>(0)
+
+#else // Not NDEBUG
+
+ #ifdef _MSC_VER
+ // Compiling with Microsoft Visual C++ compiler
+
+ // Prevent inclusion of min and max macros.
+ #define NOMINMAX
+
+ #include <afx.h>
+ #define COLA_ASSERT(expr) ASSERT(expr)
+
+ #elif defined(USE_ASSERT_EXCEPTIONS)
+
+ #include "libvpsc/assertions.h"
+
+ #else
+
+ #include <cassert>
+ #define COLA_ASSERT(expr) assert(expr)
+
+ #endif
+
+#endif
+
+
+#endif // AVOID_ASSERTIONS_H
+
diff --git a/src/3rdparty/adaptagrams/libavoid/connectionpin.cpp b/src/3rdparty/adaptagrams/libavoid/connectionpin.cpp
new file mode 100644
index 0000000..3d9ba46
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/connectionpin.cpp
@@ -0,0 +1,476 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2010-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+#include <cfloat>
+
+#include "libavoid/connectionpin.h"
+#include "libavoid/shape.h"
+#include "libavoid/junction.h"
+#include "libavoid/vertices.h"
+#include "libavoid/router.h"
+#include "libavoid/visibility.h"
+#include "libavoid/debug.h"
+
+
+namespace Avoid {
+
+ShapeConnectionPin::ShapeConnectionPin(ShapeRef *shape,
+ const unsigned int classId, const double xPortionOffset,
+ const double yPortionOffset, const bool proportional,
+ const double insideOffset, const ConnDirFlags visDirs)
+ : m_shape(shape),
+ m_junction(nullptr),
+ m_class_id(classId),
+ m_x_offset(xPortionOffset),
+ m_y_offset(yPortionOffset),
+ m_inside_offset(insideOffset),
+ m_visibility_directions(visDirs),
+ m_exclusive(true),
+ m_connection_cost(0.0),
+ m_vertex(nullptr),
+ m_using_proportional_offsets(proportional)
+{
+ commonInitForShapeConnection();
+}
+
+ShapeConnectionPin::ShapeConnectionPin(ShapeRef *shape,
+ const unsigned int classId, const double xOffset,
+ const double yOffset, const double insideOffset,
+ const ConnDirFlags visDirs)
+ : m_shape(shape),
+ m_junction(nullptr),
+ m_class_id(classId),
+ m_x_offset(xOffset),
+ m_y_offset(yOffset),
+ m_inside_offset(insideOffset),
+ m_visibility_directions(visDirs),
+ m_exclusive(true),
+ m_connection_cost(0.0),
+ m_vertex(nullptr),
+ m_using_proportional_offsets(true)
+{
+ commonInitForShapeConnection();
+}
+
+
+void ShapeConnectionPin::commonInitForShapeConnection(void)
+{
+ COLA_ASSERT(m_shape != nullptr);
+ COLA_ASSERT(m_class_id > 0);
+
+ if (m_using_proportional_offsets)
+ {
+ // Parameter checking
+ if ((m_x_offset < 0) || (m_x_offset > 1))
+ {
+ err_printf("xPortionOffset value (%g) in ShapeConnectionPin "
+ "constructor not between 0 and 1.\n", m_x_offset);
+ }
+ if ((m_y_offset < 0) || (m_y_offset > 1))
+ {
+ err_printf("yPortionOffset value (%g) in ShapeConnectionPin "
+ "constructor not between 0 and 1.\n", m_y_offset);
+ }
+ }
+ else
+ {
+ const Box shapeBox = m_shape->polygon().offsetBoundingBox(0.0);
+ // Parameter checking
+ if (m_x_offset > shapeBox.width())
+ {
+ err_printf("xOffset value (%g) in ShapeConnectionPin constructor "
+ "greater than shape width (%g).\n", m_x_offset,
+ shapeBox.width());
+ }
+ if (m_y_offset > shapeBox.height())
+ {
+ err_printf("yOffset value (%g) in ShapeConnectionPin constructor "
+ "greater than shape height (%g).\n", m_y_offset,
+ shapeBox.height());
+ }
+ }
+
+ m_router = m_shape->router();
+ m_shape->addConnectionPin(this);
+
+ // Create a visibility vertex for this ShapeConnectionPin.
+ VertID id(m_shape->id(), kShapeConnectionPin,
+ VertID::PROP_ConnPoint | VertID::PROP_ConnectionPin);
+ m_vertex = new VertInf(m_router, id, this->position());
+ m_vertex->visDirections = this->directions();
+
+ if (m_vertex->visDirections == ConnDirAll)
+ {
+ // A pin with visibility in all directions is not exclusive
+ // by default.
+ m_exclusive = false;
+ }
+
+ if (m_router->m_allows_polyline_routing)
+ {
+ vertexVisibility(m_vertex, nullptr, true, true);
+ }
+}
+
+
+ShapeConnectionPin::ShapeConnectionPin(JunctionRef *junction,
+ const unsigned int classId, const ConnDirFlags visDirs)
+ : m_shape(nullptr),
+ m_junction(junction),
+ m_class_id(classId),
+ m_x_offset(0.0),
+ m_y_offset(0.0),
+ m_inside_offset(0.0),
+ m_visibility_directions(visDirs),
+ m_exclusive(true),
+ m_connection_cost(0.0),
+ m_vertex(nullptr),
+ m_using_proportional_offsets(false)
+{
+ COLA_ASSERT(m_junction != nullptr);
+ m_router = m_junction->router();
+ m_junction->addConnectionPin(this);
+
+ // Create a visibility vertex for this ShapeConnectionPin.
+ // XXX These IDs should really be uniquely identifiable in case there
+ // are multiple pins on a shape. I think currently this case will
+ // break rubber-band routing.
+ VertID id(m_junction->id(), kShapeConnectionPin,
+ VertID::PROP_ConnPoint | VertID::PROP_ConnectionPin);
+ m_vertex = new VertInf(m_router, id, m_junction->position());
+ m_vertex->visDirections = visDirs;
+
+ if (m_router->m_allows_polyline_routing)
+ {
+ vertexVisibility(m_vertex, nullptr, true, true);
+ }
+}
+
+
+ShapeConnectionPin::~ShapeConnectionPin()
+{
+ COLA_ASSERT(m_shape || m_junction);
+ if (m_shape)
+ {
+ m_shape->removeConnectionPin(this);
+ }
+ else if (m_junction)
+ {
+ m_junction->removeConnectionPin(this);
+ }
+
+ // Disconnect connend using this pin.
+ while (!m_connend_users.empty())
+ {
+ ConnEnd *connend = *(m_connend_users.begin());
+ connend->freeActivePin();
+ }
+
+ if (m_vertex)
+ {
+ m_vertex->removeFromGraph();
+ m_router->vertices.removeVertex(m_vertex);
+ delete m_vertex;
+ m_vertex = nullptr;
+ }
+}
+
+void ShapeConnectionPin::updatePositionAndVisibility(void)
+{
+ m_vertex->Reset(this->position());
+ m_vertex->visDirections = this->directions();
+ updateVisibility();
+}
+
+void ShapeConnectionPin::updateVisibility(void)
+{
+ m_vertex->removeFromGraph();
+ if (m_router->m_allows_polyline_routing)
+ {
+ vertexVisibility(m_vertex, nullptr, true, true);
+ }
+}
+
+void ShapeConnectionPin::setConnectionCost(const double cost)
+{
+ COLA_ASSERT(cost >= 0);
+
+ m_connection_cost = cost;
+}
+
+
+void ShapeConnectionPin::setExclusive(const bool exclusive)
+{
+ m_exclusive = exclusive;
+}
+
+bool ShapeConnectionPin::isExclusive(void) const
+{
+ return m_exclusive;
+}
+
+void ShapeConnectionPin::updatePosition(const Point& newPosition)
+{
+ m_vertex->Reset(newPosition);
+}
+
+
+void ShapeConnectionPin::updatePosition(const Polygon& newPoly)
+{
+ m_vertex->Reset(position(newPoly));
+}
+
+
+const Point ShapeConnectionPin::position(const Polygon& newPoly) const
+{
+ if (m_junction)
+ {
+ return m_junction->position();
+ }
+
+ const Polygon& poly = (newPoly.empty()) ? m_shape->polygon() : newPoly;
+ const Box shapeBox = poly.offsetBoundingBox(0.0);
+
+ Point point;
+
+ if (m_using_proportional_offsets)
+ {
+ // We want to place connection points exactly on the edges of shapes,
+ // or possibly slightly inside them (if m_insideOfset is set).
+ if (m_x_offset == ATTACH_POS_LEFT)
+ {
+ point.x = shapeBox.min.x + m_inside_offset;
+ point.vn = 6;
+ }
+ else if (m_x_offset == ATTACH_POS_RIGHT)
+ {
+ point.x = shapeBox.max.x - m_inside_offset;
+ point.vn = 4;
+ }
+ else
+ {
+ point.x = shapeBox.min.x + (m_x_offset * shapeBox.width());
+ }
+
+ if (m_y_offset == ATTACH_POS_TOP)
+ {
+ point.y = shapeBox.min.y + m_inside_offset;
+ point.vn = 5;
+ }
+ else if (m_y_offset == ATTACH_POS_BOTTOM)
+ {
+ point.y = shapeBox.max.y - m_inside_offset;
+ point.vn = 7;
+ }
+ else
+ {
+ point.y = shapeBox.min.y + (m_y_offset * shapeBox.height());
+ }
+ }
+ else
+ {
+ // Using absolute offsets for connection pin position.
+ if (m_x_offset == ATTACH_POS_MIN_OFFSET)
+ {
+ point.x = shapeBox.min.x + m_inside_offset;
+ point.vn = 6;
+ }
+ else if ((m_x_offset == ATTACH_POS_MAX_OFFSET) ||
+ (m_x_offset == shapeBox.width()))
+ {
+ point.x = shapeBox.max.x - m_inside_offset;
+ point.vn = 4;
+ }
+ else
+ {
+ point.x = shapeBox.min.x + m_x_offset;
+ }
+
+ if (m_y_offset == ATTACH_POS_MIN_OFFSET)
+ {
+ point.y = shapeBox.min.y + m_inside_offset;
+ point.vn = 5;
+ }
+ else if ((m_y_offset == ATTACH_POS_MAX_OFFSET) ||
+ (m_y_offset == shapeBox.height()))
+ {
+ point.y = shapeBox.max.y - m_inside_offset;
+ point.vn = 7;
+ }
+ else
+ {
+ point.y = shapeBox.min.y + m_y_offset;
+ }
+ }
+
+ return point;
+}
+
+
+ConnDirFlags ShapeConnectionPin::directions(void) const
+{
+ ConnDirFlags visDir = m_visibility_directions;
+ if (m_visibility_directions == ConnDirNone)
+ {
+ // None is set, use the defaults:
+ if (m_x_offset == ATTACH_POS_LEFT)
+ {
+ visDir |= ConnDirLeft;
+ }
+ else if (m_x_offset == ATTACH_POS_RIGHT)
+ {
+ visDir |= ConnDirRight;
+ }
+
+ if (m_y_offset == ATTACH_POS_TOP)
+ {
+ visDir |= ConnDirUp;
+ }
+ else if (m_y_offset == ATTACH_POS_BOTTOM)
+ {
+ visDir |= ConnDirDown;
+ }
+
+ if (visDir == ConnDirNone)
+ {
+ visDir = ConnDirAll;
+ }
+ }
+ return visDir;
+}
+
+void ShapeConnectionPin::outputCode(FILE *fp) const
+{
+ COLA_ASSERT(m_shape || m_junction);
+ if (m_shape)
+ {
+ fprintf(fp, " connPin = new ShapeConnectionPin(shapeRef%u, %u, "
+ "%" PREC "g, %" PREC "g, %s, %g, (ConnDirFlags) %u);\n",
+ m_shape->id(), m_class_id, m_x_offset, m_y_offset,
+ (m_using_proportional_offsets ? "true" : "false"),
+ m_inside_offset, (unsigned int) m_visibility_directions);
+ }
+ else if (m_junction)
+ {
+ fprintf(fp, " connPin = new ShapeConnectionPin(junctionRef%u, %u, "
+ "(ConnDirFlags) %u);\n", m_junction->id(), m_class_id,
+ (unsigned int) m_visibility_directions);
+ }
+
+ if ((m_vertex->visDirections != ConnDirAll) && (m_exclusive == false))
+ {
+ // Directional port is not exclusive (the default), so output this.
+ fprintf(fp, " connPin->setExclusive(false);\n");
+ }
+}
+
+ConnectionPinIds ShapeConnectionPin::ids(void) const
+{
+ return std::make_pair(containingObjectId(), m_class_id);
+}
+
+unsigned int ShapeConnectionPin::containingObjectId(void) const
+{
+ COLA_ASSERT(m_shape || m_junction);
+ return (m_shape) ? m_shape->id() : m_junction->id();
+}
+
+bool ShapeConnectionPin::operator==(const ShapeConnectionPin& rhs) const
+{
+ COLA_ASSERT(m_router == rhs.m_router);
+
+ if (containingObjectId() != rhs.containingObjectId())
+ {
+ return false;
+ }
+
+ // The shape/junction is equal, so examine the unique members.
+ if (m_class_id != rhs.m_class_id)
+ {
+ return false;
+ }
+ if (m_visibility_directions != rhs.m_visibility_directions)
+ {
+ return false;
+ }
+ if (m_x_offset != rhs.m_x_offset)
+ {
+ return false;
+ }
+ if (m_y_offset != rhs.m_y_offset)
+ {
+ return false;
+ }
+ if (m_inside_offset != rhs.m_inside_offset)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool ShapeConnectionPin::operator<(const ShapeConnectionPin& rhs) const
+{
+ COLA_ASSERT(m_router == rhs.m_router);
+
+ if (containingObjectId() != rhs.containingObjectId())
+ {
+ return containingObjectId() < rhs.containingObjectId();
+ }
+ // Note: operator< is used for set ordering within each shape or junction,
+ // so the m_shape/m_junction values should match and we needn't perform the
+ // above test in most cases and could just assert the following:
+ // COLA_ASSERT(m_shape == rhs.m_shape);
+ // COLA_ASSERT(m_junction == rhs.m_junction);
+
+ if (m_class_id != rhs.m_class_id)
+ {
+ return m_class_id < rhs.m_class_id;
+ }
+ if (m_visibility_directions != rhs.m_visibility_directions)
+ {
+ return m_visibility_directions < rhs.m_visibility_directions;
+ }
+ if (m_x_offset != rhs.m_x_offset)
+ {
+ return m_x_offset < rhs.m_x_offset;
+ }
+ if (m_y_offset != rhs.m_y_offset)
+ {
+ return m_y_offset < rhs.m_y_offset;
+ }
+ if (m_inside_offset != rhs.m_inside_offset)
+ {
+ return m_inside_offset < rhs.m_inside_offset;
+ }
+
+ // Otherwise, they are considered the same.
+ return false;
+}
+
+
+//============================================================================
+
+}
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/connectionpin.h b/src/3rdparty/adaptagrams/libavoid/connectionpin.h
new file mode 100644
index 0000000..5e33793
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/connectionpin.h
@@ -0,0 +1,303 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2010-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+//! @file connectionpin.h
+//! @brief Contains the interface for the ShapeConnectionPin class.
+
+
+#ifndef AVOID_CONNECTIONPIN_H
+#define AVOID_CONNECTIONPIN_H
+
+#include <cstdio>
+#include <set>
+#include <climits>
+#include <utility>
+
+#include "libavoid/dllexport.h"
+#include "libavoid/connend.h"
+#include "libavoid/geomtypes.h"
+
+namespace Avoid {
+
+
+static const unsigned int CONNECTIONPIN_UNSET = INT_MAX;
+static const unsigned int CONNECTIONPIN_CENTRE = INT_MAX - 1;
+
+class Router;
+class ShapeRef;
+class JunctionRef;
+class ConnEnd;
+class VertInf;
+
+typedef std::pair<unsigned int, unsigned int> ConnectionPinIds;
+
+// Used to specify position on shape when constructing a shape-attached ConnEnd.
+//
+static const double ATTACH_POS_TOP = 0;
+static const double ATTACH_POS_CENTRE = 0.5;
+static const double ATTACH_POS_BOTTOM = 1;
+static const double ATTACH_POS_LEFT = ATTACH_POS_TOP;
+static const double ATTACH_POS_RIGHT = ATTACH_POS_BOTTOM;
+
+static const double ATTACH_POS_MIN_OFFSET = 0;
+static const double ATTACH_POS_MAX_OFFSET = -1;
+
+
+//! @brief The ShapeConnectionPin class represents a fixed point or "pin"
+//! on a shape that can be connected to.
+//!
+//! A pin has a position that is specified relative to its parent shape.
+//! When the shape is moved or resized, the pin will be automatically moved
+//! accordingly. Connectors attached to the pin will be rerouted.
+//!
+//! Pins have a visibility direction and numeric ID used to identify them.
+//! This ID, known as their classId, may be shared by multiple pins on the
+//! same shape. You can use classIds when you want libavoid to choose from
+//! multiple potential choices (e.g., to specify multiple types of pins such
+//! as "input" or "output" pins on circuit elements).
+//!
+//! If you would like connectors that attach to a single specific position
+//! on a shape, then just give each pin a unique classId (for that shape)
+//! and tell the connector to attach to that particular pin.
+//!
+//! Pins may optionally be given a connection cost, via setConnectionCost().
+//! In the case of multiple pins with the same classId, this causes the
+//! lower-cost pins to be chosen first, rather than libavoid choosing the
+//! best pin with that classId based solely on connector path cost.
+//!
+//! Pins can be exclusive, which means subsequent connectors routed to the
+//! same classId will choose a different pin. Pins with a specified direction
+//! are exclusive by default, those with visibility in all directions are
+//! non-exclusive by default. This behaviour can be changed by calling the
+//! ShapeConnectionPin::setExclusive() method. Exclusive pins may only have
+//! a single connector attached to them.
+//!
+class AVOID_EXPORT ShapeConnectionPin
+{
+ public:
+ //! @brief Constructs a ShapeConnectionPin at a specified absolute or
+ //! proportional position relative to the parent shape.
+ //!
+ //! Ownership of this ShapeConnectionPin is passed to the parent shape.
+ //!
+ //! The connection point position offsets can be specified as absolute
+ //! or proportional. If absolute, the xOffset and yOffset values are
+ //! absolute offsets relative to the lower X and Y shape rectangle
+ //! border positions. If proportional, the xOffset and yOffset values
+ //! represent proportions of the shape's total width and height using
+ //! a floating point value between 0 and 1.
+ //!
+ //! Note that if you need the connection pin to appear at an exact
+ //! position this may not be possible via proportional positions due
+ //! to numerical inaccuracy in floating point multiplications. In
+ //! this case you should use absolute offsets instead.
+ //!
+ //! There are some predefined values for specifying the xOffset
+ //! and yOffset arguments for proportional offsets:
+ //! - ATTACH_POS_TOP = 0
+ //! - ATTACH_POS_LEFT = 0
+ //! - ATTACH_POS_CENTRE = 0.5
+ //! - ATTACH_POS_BOTTOM = 1
+ //! - ATTACH_POS_RIGHT = 1
+ //! And two more for specifying absolute offsets:
+ //! - ATTACH_POS_MIN_OFFSET = offset of zero
+ //! - ATTACH_POS_MAX_OFFSET = offset of shape width/height
+ //!
+ //! Importantly, shape connection pins will be moved automatically when
+ //! the parent shape is moved or resized. Attachment for connectors
+ //! will be chosen based on the classId specified to ConnEnd and these
+ //! connectors will be subsequently rerouted.
+ //!
+ //! If no value is given for the visDirs argument, then visibility is
+ //! automatically determined based on the position of the connection
+ //! point. Points on the shape boundary will have visibility from the
+ //! shape out of that edge while points in the interior will have
+ //! visibility in all directions. Note: Pins with visibility in a
+ //! specific direction are exclusive by default, whereas those with
+ //! visibility in all directions are non-exclusive by default.
+ //!
+ //! The insideOffset argument can be used to set a distance to
+ //! automatically offset the point within the shape. This is useful
+ //! for orthogonal routing, where you usually want the connection
+ //! point to lie inside the shape rather than exactly on its boundary.
+ //! This offset will only be applied for connection pins specified
+ //! with a position exactly on the shape boundary.
+ //!
+ //! @param[in] shape A pointer to the containing parent
+ //! shape's ShapeRef.
+ //! @param[in] classId A non-zero integer used to identify
+ //! this pin and other equivalent
+ //! connection point, and used to specify
+ //! attachment via the ConnEnd class.
+ //! @param[in] xOffset The X offset for the connection pin from
+ //! the shape's lower X border position.
+ //! @param[in] yOffset The Y offset for the connection pin from
+ //! the shape's lower Y border position.
+ //! @param[in] proportional A boolean specifying whether the X and Y
+ //! offsets are proportional or not.
+ //! @param[in] insideOffset A distance to offset the connection
+ //! point inside the shape if it lies on
+ //! the boundary. Use 0.0 for no offset.
+ //! @param[in] visDirs One or more Avoid::ConnDirFlag options
+ //! specifying the directions that this
+ //! connection point has visibility.
+ //! Use ConnDirNone to have visibility
+ //! be directional if a pin is on the shape
+ //! edge or in all directions otherwise.
+ //!
+ ShapeConnectionPin(ShapeRef *shape, const unsigned int classId,
+ const double xOffset, const double yOffset,
+ const bool proportional, const double insideOffset,
+ const ConnDirFlags visDirs);
+
+ // Old constructor. Provided for compatibility with old debug files.
+ ShapeConnectionPin(ShapeRef *shape, const unsigned int classId,
+ const double xOffset, const double yOffset,
+ const double insideOffset, const ConnDirFlags visDirs);
+
+ //! @brief Constructs a ShapeConnectionPin on a JunctionRef.
+ //!
+ //! Ownership of this ShapeConnectionPin is passed to the parent
+ //! junction.
+ //!
+ //! This will usually be automatically called by the JunctionRef
+ //! constructor to give the Junction four ShapeConnectionPins,
+ //! facing up, down, left and right.
+ //!
+ //! @param[in] junction A pointer to the containing parent
+ //! junction's JunctionRef.
+ //! @param[in] classId An integer used to mark the class or
+ //! group of this connection point, used
+ //! for specifying attachment to ConnEnd.
+ //! @param[in] visDirs One or more Avoid::ConnDirFlag options
+ //! specifying the directions that this
+ //! connection point has visibility.
+ //!
+ ShapeConnectionPin(JunctionRef *junction, const unsigned int classId,
+ const ConnDirFlags visDirs = ConnDirNone);
+
+// To prevent C++ objects from being destroyed in garbage collected languages
+// when the libraries are called from SWIG, we hide the declarations of the
+// destructors and prevent generation of default destructors.
+#ifndef SWIG
+ ~ShapeConnectionPin();
+#endif
+
+ //! @brief Sets a cost used when selecting whether connectors should be
+ //! be attached to this connection pin.
+ //!
+ //! @param[in] cost A routing cost applied to a route when selecting
+ //! this connection pin.
+ //!
+ void setConnectionCost(const double cost);
+
+ //! @brief Returns the position of this connection pin.
+ //!
+ //! @return The position of this connection pin.
+ //!
+ const Point position(const Polygon& newPoly = Polygon()) const;
+
+ //! @brief Returns the directions in which this connection pin
+ //! has visibility.
+ //!
+ //! @return The visibility directions for this connection pin.
+ //!
+ ConnDirFlags directions(void) const;
+
+ //! @brief Sets whether the pin is exclusive, i.e., only one connector
+ //! can attach to it. This defaults to true for connection
+ //! pins with visibility in a specific directions and false for
+ //! pins with visibility in all directions.
+ //!
+ //! @param[in] exclusive A bool representing whether this pin should
+ //! be exclusive.
+ //!
+ void setExclusive(const bool exclusive);
+
+ //! @brief Returns whether the connection pin is exclusive,
+ //! i.e., only one connector can attach to it.
+ //!
+ //! @return A boolean denoting whether this pin is exclusive.
+ //!
+ bool isExclusive(void) const;
+
+ ConnectionPinIds ids(void) const;
+
+ bool operator==(const ShapeConnectionPin& rhs) const;
+ bool operator<(const ShapeConnectionPin& rhs) const;
+ private:
+ friend class ShapeRef;
+ friend class JunctionRef;
+ friend class Obstacle;
+ friend class ConnEnd;
+ friend class Router;
+
+ void commonInitForShapeConnection(void);
+ void updatePosition(const Point& newPosition);
+ void updatePosition(const Polygon& newPoly);
+ void updatePositionAndVisibility(void);
+ void updateVisibility(void);
+ void outputCode(FILE *fp) const;
+ unsigned int containingObjectId(void) const;
+
+ // Unique properties
+ Router *m_router;
+ ShapeRef *m_shape;
+ JunctionRef *m_junction;
+ unsigned int m_class_id;
+ double m_x_offset;
+ double m_y_offset;
+ double m_inside_offset;
+ ConnDirFlags m_visibility_directions;
+
+ // Some extra properties.
+ bool m_exclusive;
+ double m_connection_cost;
+ // The set of connends using this pin.
+ std::set<ConnEnd *> m_connend_users;
+ VertInf *m_vertex;
+ bool m_using_proportional_offsets;
+};
+
+class CmpConnPinPtr
+{
+ public:
+ CmpConnPinPtr()
+ {
+ }
+ bool operator()(const ShapeConnectionPin *lhs,
+ const ShapeConnectionPin *rhs) const
+ {
+ return (*lhs) < (*rhs);
+ }
+};
+
+typedef std::set<ShapeConnectionPin *, CmpConnPinPtr> ShapeConnectionPinSet;
+
+}
+
+
+#endif
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/connector.cpp b/src/3rdparty/adaptagrams/libavoid/connector.cpp
new file mode 100644
index 0000000..24ab289
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/connector.cpp
@@ -0,0 +1,2487 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+
+#include <cstring>
+#include <cfloat>
+#include <cmath>
+#include <cstdlib>
+#include <algorithm>
+#include <queue>
+#include <limits>
+
+#include "libavoid/connector.h"
+#include "libavoid/connend.h"
+#include "libavoid/router.h"
+#include "libavoid/visibility.h"
+#include "libavoid/debug.h"
+#include "libavoid/assertions.h"
+#include "libavoid/junction.h"
+#include "libavoid/makepath.h"
+#include "libavoid/debughandler.h"
+
+
+namespace Avoid {
+
+
+ConnRef::ConnRef(Router *router, const unsigned int id)
+ : m_router(router),
+ m_type(router->validConnType()),
+ m_reroute_flag_ptr(nullptr),
+ m_needs_reroute_flag(true),
+ m_false_path(false),
+ m_needs_repaint(false),
+ m_active(false),
+ m_hate_crossings(false),
+ m_has_fixed_route(false),
+ m_route_dist(0),
+ m_src_vert(nullptr),
+ m_dst_vert(nullptr),
+ m_start_vert(nullptr),
+ m_callback_func(nullptr),
+ m_connector(nullptr),
+ m_src_connend(nullptr),
+ m_dst_connend(nullptr)
+{
+ COLA_ASSERT(m_router != nullptr);
+ m_id = m_router->assignId(id);
+
+ // TODO: Store endpoints and details.
+ m_route.clear();
+
+ m_reroute_flag_ptr = m_router->m_conn_reroute_flags.addConn(this);
+}
+
+
+ConnRef::ConnRef(Router *router, const ConnEnd& src, const ConnEnd& dst,
+ const unsigned int id)
+ : m_router(router),
+ m_type(router->validConnType()),
+ m_reroute_flag_ptr(nullptr),
+ m_needs_reroute_flag(true),
+ m_false_path(false),
+ m_needs_repaint(false),
+ m_active(false),
+ m_hate_crossings(false),
+ m_has_fixed_route(false),
+ m_route_dist(0),
+ m_src_vert(nullptr),
+ m_dst_vert(nullptr),
+ m_callback_func(nullptr),
+ m_connector(nullptr),
+ m_src_connend(nullptr),
+ m_dst_connend(nullptr)
+{
+ COLA_ASSERT(m_router != nullptr);
+ m_id = m_router->assignId(id);
+ m_route.clear();
+
+ // Set endpoint values.
+ setEndpoints(src, dst);
+
+ m_reroute_flag_ptr = m_router->m_conn_reroute_flags.addConn(this);
+}
+
+
+ConnRef::~ConnRef()
+{
+ COLA_ASSERT(m_router);
+
+ if (m_router->m_currently_calling_destructors == false)
+ {
+ err_printf("ERROR: ConnRef::~ConnRef() shouldn't be called directly.\n");
+ err_printf(" It is owned by the router. Call Router::deleteConnector() instead.\n");
+ abort();
+ }
+
+ m_router->m_conn_reroute_flags.removeConn(this);
+
+ m_router->removeObjectFromQueuedActions(this);
+
+ freeRoutes();
+
+ if (m_src_vert)
+ {
+ m_src_vert->removeFromGraph();
+ m_router->vertices.removeVertex(m_src_vert);
+ delete m_src_vert;
+ m_src_vert = nullptr;
+ }
+ if (m_src_connend)
+ {
+ m_src_connend->disconnect();
+ m_src_connend->freeActivePin();
+ delete m_src_connend;
+ m_src_connend = nullptr;
+ }
+
+ if (m_dst_vert)
+ {
+ m_dst_vert->removeFromGraph();
+ m_router->vertices.removeVertex(m_dst_vert);
+ delete m_dst_vert;
+ m_dst_vert = nullptr;
+ }
+ if (m_dst_connend)
+ {
+ m_dst_connend->disconnect();
+ m_dst_connend->freeActivePin();
+ delete m_dst_connend;
+ m_dst_connend = nullptr;
+ }
+
+ // Clear checkpoint vertices.
+ for (size_t i = 0; i < m_checkpoint_vertices.size(); ++i)
+ {
+ m_checkpoint_vertices[i]->removeFromGraph(true);
+ m_router->vertices.removeVertex(m_checkpoint_vertices[i]);
+ delete m_checkpoint_vertices[i];
+ }
+ m_checkpoint_vertices.clear();
+
+ if (m_active)
+ {
+ makeInactive();
+ }
+}
+
+
+ConnType ConnRef::routingType(void) const
+{
+ return m_type;
+}
+
+
+void ConnRef::setRoutingType(ConnType type)
+{
+ type = m_router->validConnType(type);
+ if (m_type != type)
+ {
+ m_type = type;
+
+ makePathInvalid();
+
+ m_router->modifyConnector(this);
+ }
+}
+
+
+std::vector<Checkpoint> ConnRef::routingCheckpoints(void) const
+{
+ return m_checkpoints;
+}
+
+
+void ConnRef::setRoutingCheckpoints(const std::vector<Checkpoint>& checkpoints)
+{
+ m_checkpoints = checkpoints;
+
+ // Clear previous checkpoint vertices.
+ for (size_t i = 0; i < m_checkpoint_vertices.size(); ++i)
+ {
+ m_checkpoint_vertices[i]->removeFromGraph(true);
+ m_router->vertices.removeVertex(m_checkpoint_vertices[i]);
+ delete m_checkpoint_vertices[i];
+ }
+ m_checkpoint_vertices.clear();
+
+ for (size_t i = 0; i < m_checkpoints.size(); ++i)
+ {
+ VertID ptID(m_id, 2 + i,
+ VertID::PROP_ConnPoint | VertID::PROP_ConnCheckpoint);
+ VertInf *vertex = new VertInf(m_router, ptID, m_checkpoints[i].point);
+ vertex->visDirections = ConnDirAll;
+
+ m_checkpoint_vertices.push_back(vertex);
+ }
+ if (m_router->m_allows_polyline_routing)
+ {
+ for (size_t i = 0; i < m_checkpoints.size(); ++i)
+ {
+ vertexVisibility(m_checkpoint_vertices[i], nullptr, true, true);
+ }
+ }
+}
+
+
+void ConnRef::common_updateEndPoint(const unsigned int type, ConnEnd connEnd)
+{
+ const Point& point = connEnd.position();
+ //db_printf("common_updateEndPoint(%d,(pid=%d,vn=%d,(%f,%f)))\n",
+ // type,point.id,point.vn,point.x,point.y);
+ COLA_ASSERT((type == (unsigned int) VertID::src) ||
+ (type == (unsigned int) VertID::tar));
+
+ // The connEnd is a copy of a ConnEnd that will get disconnected,
+ // so don't leave it looking like it is still connected.
+ connEnd.m_conn_ref = nullptr;
+
+ if (!m_active)
+ {
+ makeActive();
+ }
+
+ VertInf *altered = nullptr;
+
+ VertIDProps properties = VertID::PROP_ConnPoint;
+ if (connEnd.isPinConnection())
+ {
+ properties |= VertID::PROP_DummyPinHelper;
+ }
+ VertID ptID(m_id, type, properties);
+ if (type == (unsigned int) VertID::src)
+ {
+ if (m_src_vert)
+ {
+ m_src_vert->Reset(ptID, point);
+ }
+ else
+ {
+ m_src_vert = new VertInf(m_router, ptID, point);
+ }
+ m_src_vert->visDirections = connEnd.directions();
+
+ if (m_src_connend)
+ {
+ m_src_connend->disconnect();
+ m_src_connend->freeActivePin();
+ delete m_src_connend;
+ m_src_connend = nullptr;
+ }
+ if (connEnd.isPinConnection())
+ {
+ m_src_connend = new ConnEnd(connEnd);
+ m_src_connend->connect(this);
+ // Don't need this to have visibility since we won't
+ // be connecting to it.
+ m_src_vert->visDirections = ConnDirNone;
+ }
+
+ altered = m_src_vert;
+ }
+ else // if (type == (unsigned int) VertID::tar)
+ {
+ if (m_dst_vert)
+ {
+ m_dst_vert->Reset(ptID, point);
+ }
+ else
+ {
+ m_dst_vert = new VertInf(m_router, ptID, point);
+ }
+ m_dst_vert->visDirections = connEnd.directions();
+
+ if (m_dst_connend)
+ {
+ m_dst_connend->disconnect();
+ m_dst_connend->freeActivePin();
+ delete m_dst_connend;
+ m_dst_connend = nullptr;
+ }
+ if (connEnd.isPinConnection())
+ {
+ m_dst_connend = new ConnEnd(connEnd);
+ m_dst_connend->connect(this);
+ // Don't need this to have visibility since we won't
+ // be connecting to it.
+ m_dst_vert->visDirections = ConnDirNone;
+ }
+
+ altered = m_dst_vert;
+ }
+
+ // XXX: Seems to be faster to just remove the edges and recreate
+ bool isConn = true;
+ altered->removeFromGraph(isConn);
+
+ makePathInvalid();
+ m_router->setStaticGraphInvalidated(true);
+}
+
+
+void ConnRef::setEndpoints(const ConnEnd& srcPoint, const ConnEnd& dstPoint)
+{
+ m_router->modifyConnector(this, VertID::src, srcPoint);
+ m_router->modifyConnector(this, VertID::tar, dstPoint);
+}
+
+
+void ConnRef::setEndpoint(const unsigned int type, const ConnEnd& connEnd)
+{
+ m_router->modifyConnector(this, type, connEnd);
+}
+
+
+void ConnRef::setSourceEndpoint(const ConnEnd& srcPoint)
+{
+ m_router->modifyConnector(this, VertID::src, srcPoint);
+}
+
+
+void ConnRef::setDestEndpoint(const ConnEnd& dstPoint)
+{
+ m_router->modifyConnector(this, VertID::tar, dstPoint);
+}
+
+
+// Given the start or end vertex of a connector, returns the ConnEnd that
+// can be used to reproduce that endpoint. This is used for hyperedge routing.
+//
+bool ConnRef::getConnEndForEndpointVertex(VertInf *vertex,
+ ConnEnd& connEnd) const
+{
+ if (vertex == nullptr)
+ {
+ err_printf("Warning: In ConnRef::getConnEndForEndpointVertex():\n"
+ " ConnEnd for connector %d is uninitialised. It may have been\n"
+ " set but Router::processTrancaction has not yet been called.\n",
+ (int) id());
+ return false;
+ }
+
+ if (vertex == m_src_vert)
+ {
+ if (m_src_connend)
+ {
+ connEnd = *m_src_connend;
+ }
+ else
+ {
+ connEnd = ConnEnd(Point(m_src_vert->point.x, m_src_vert->point.y),
+ m_src_vert->visDirections);
+ }
+ return true;
+ }
+ else if (vertex == m_dst_vert)
+ {
+ if (m_dst_connend)
+ {
+ connEnd = *m_dst_connend;
+ }
+ else
+ {
+ connEnd = ConnEnd(Point(m_dst_vert->point.x, m_dst_vert->point.y),
+ m_dst_vert->visDirections);
+ }
+ return true;
+ }
+ return false;
+}
+
+
+void ConnRef::updateEndPoint(const unsigned int type, const ConnEnd& connEnd)
+{
+ common_updateEndPoint(type, connEnd);
+
+ if (m_has_fixed_route)
+ {
+ // Don't need to continue and compute visibility if route is fixed.
+ return;
+ }
+
+ if (m_router->m_allows_polyline_routing)
+ {
+ bool knownNew = true;
+ bool genContains = true;
+ if (type == (unsigned int) VertID::src)
+ {
+ bool dummySrc = m_src_connend && m_src_connend->isPinConnection();
+ if (!dummySrc)
+ {
+ // Only generate visibility if not attached to a pin.
+ vertexVisibility(m_src_vert, m_dst_vert, knownNew, genContains);
+ }
+ }
+ else
+ {
+ bool dummyDst = m_dst_connend && m_dst_connend->isPinConnection();
+ if (!dummyDst)
+ {
+ // Only generate visibility if not attached to a pin.
+ vertexVisibility(m_dst_vert, m_src_vert, knownNew, genContains);
+ }
+ }
+ }
+}
+
+
+void ConnRef::outputCode(FILE *fp) const
+{
+ fprintf(fp, " // connRef%u\n", id());
+ fprintf(fp, " connRef = new ConnRef(router, %u);\n", id());
+ if (m_src_connend)
+ {
+ m_src_connend->outputCode(fp, "src");
+ fprintf(fp, " connRef->setSourceEndpoint(srcPt);\n");
+ }
+ else if (src())
+ {
+ fprintf(fp, " srcPt = ConnEnd(Point(%" PREC "g, %" PREC "g), %u);\n",
+ src()->point.x, src()->point.y, src()->visDirections);
+ fprintf(fp, " connRef->setSourceEndpoint(srcPt);\n");
+ }
+ if (m_dst_connend)
+ {
+ m_dst_connend->outputCode(fp, "dst");
+ fprintf(fp, " connRef->setDestEndpoint(dstPt);\n");
+ }
+ else if (dst())
+ {
+ fprintf(fp, " dstPt = ConnEnd(Point(%" PREC "g, %" PREC "g), %u);\n",
+ dst()->point.x, dst()->point.y, dst()->visDirections);
+ fprintf(fp, " connRef->setDestEndpoint(dstPt);\n");
+ }
+ fprintf(fp, " connRef->setRoutingType((ConnType)%u);\n", routingType());
+
+ if (m_has_fixed_route)
+ {
+ PolyLine currRoute = route();
+ fprintf(fp, " newRoute._id = %u;\n", id());
+ fprintf(fp, " newRoute.ps.resize(%d);\n", (int)currRoute.size());
+ for (size_t i = 0; i < currRoute.size(); ++i)
+ {
+ fprintf(fp, " newRoute.ps[%d] = Point(%" PREC "g, %" PREC "g);\n",
+ (int) i, currRoute.ps[i].x, currRoute.ps[i].y);
+ fprintf(fp, " newRoute.ps[%d].id = %u;\n",
+ (int) i, currRoute.ps[i].id);
+ fprintf(fp, " newRoute.ps[%d].vn = %u;\n",
+ (int) i, currRoute.ps[i].vn);
+ }
+ fprintf(fp, " connRef->setFixedRoute(newRoute);\n");
+ }
+
+ if (!m_checkpoints.empty())
+ {
+ fprintf(fp, " std::vector<Checkpoint> checkpoints%u(%d);\n", id(),
+ (int) m_checkpoints.size());
+ for (size_t cInd = 0; cInd < m_checkpoints.size(); ++cInd)
+ {
+ fprintf(fp, " checkpoints%u[%d] = Checkpoint(Point("
+ "%" PREC "g, %" PREC "g), (ConnDirFlags) %d, "
+ "(ConnDirFlags) %d);\n", id(), (int) cInd,
+ m_checkpoints[cInd].point.x, m_checkpoints[cInd].point.y,
+ m_checkpoints[cInd].arrivalDirections,
+ m_checkpoints[cInd].departureDirections);
+ }
+ fprintf(fp, " connRef->setRoutingCheckpoints(checkpoints%u);\n",
+ id());
+ }
+ fprintf(fp, "\n");
+}
+
+
+std::pair<Obstacle *, Obstacle *> ConnRef::endpointAnchors(void) const
+{
+ std::pair<Obstacle *, Obstacle *> anchors;
+ anchors.first = nullptr;
+ anchors.second = nullptr;
+
+ if (m_src_connend)
+ {
+ anchors.first = m_src_connend->m_anchor_obj;
+ }
+ if (m_dst_connend)
+ {
+ anchors.second = m_dst_connend->m_anchor_obj;
+ }
+ return anchors;
+}
+
+std::pair<ConnEnd, ConnEnd> ConnRef::endpointConnEnds(void) const
+{
+ std::pair<ConnEnd, ConnEnd> endpoints;
+ getConnEndForEndpointVertex(m_src_vert, endpoints.first);
+ getConnEndForEndpointVertex(m_dst_vert, endpoints.second);
+ return endpoints;
+}
+
+bool ConnRef::setEndpoint(const unsigned int type, const VertID& pointID,
+ Point *pointSuggestion)
+{
+ VertInf *vInf = m_router->vertices.getVertexByID(pointID);
+ if (vInf == nullptr)
+ {
+ return false;
+ }
+ Point& point = vInf->point;
+ if (pointSuggestion)
+ {
+ if (euclideanDist(point, *pointSuggestion) > 0.5)
+ {
+ return false;
+ }
+ }
+
+ common_updateEndPoint(type, point);
+
+ // Give this visibility just to the point it is over.
+ EdgeInf *edge = new EdgeInf(
+ (type == VertID::src) ? m_src_vert : m_dst_vert, vInf);
+ // XXX: We should be able to set this to zero, but can't due to
+ // assumptions elsewhere in the code.
+ edge->setDist(0.001);
+
+ m_router->processTransaction();
+ return true;
+}
+
+
+void ConnRef::makeActive(void)
+{
+ COLA_ASSERT(!m_active);
+
+ // Add to connRefs list.
+ m_connrefs_pos = m_router->connRefs.insert(m_router->connRefs.begin(), this);
+ m_active = true;
+}
+
+
+void ConnRef::freeActivePins(void)
+{
+ if (m_src_connend)
+ {
+ m_src_connend->freeActivePin();
+ }
+ if (m_dst_connend)
+ {
+ m_dst_connend->freeActivePin();
+ }
+}
+
+
+void ConnRef::makeInactive(void)
+{
+ COLA_ASSERT(m_active);
+
+ // Remove from connRefs list.
+ m_router->connRefs.erase(m_connrefs_pos);
+ m_active = false;
+}
+
+
+void ConnRef::freeRoutes(void)
+{
+ m_route.clear();
+ m_display_route.clear();
+}
+
+
+const PolyLine& ConnRef::route(void) const
+{
+ return m_route;
+}
+
+
+PolyLine& ConnRef::routeRef(void)
+{
+ return m_route;
+}
+
+
+void ConnRef::set_route(const PolyLine& route)
+{
+ if (&m_display_route == &route)
+ {
+ db_printf("Error:\tTrying to update libavoid route with itself.\n");
+ return;
+ }
+ m_display_route.ps = route.ps;
+
+ //_display_route.clear();
+}
+
+void ConnRef::setFixedExistingRoute(void)
+{
+ COLA_ASSERT(m_route.size() >= 2);
+ m_has_fixed_route = true;
+ m_router->registerSettingsChange();
+}
+
+void ConnRef::setFixedRoute(const PolyLine& route)
+{
+ if (route.size() >= 2)
+ {
+ // Set endpoints based on the fixed route incase the
+ // fixed route is later cleared.
+ setEndpoints(route.ps[0], route.ps[route.size() - 1]);
+ }
+ m_has_fixed_route = true;
+ m_route = route;
+ m_display_route = m_route.simplify();
+ m_router->registerSettingsChange();
+}
+
+bool ConnRef::hasFixedRoute(void) const
+{
+ return m_has_fixed_route;
+}
+
+void ConnRef::clearFixedRoute(void)
+{
+ m_has_fixed_route = false;
+ makePathInvalid();
+ m_router->registerSettingsChange();
+}
+
+Polygon& ConnRef::displayRoute(void)
+{
+ if (m_display_route.empty())
+ {
+ // No displayRoute is set. Simplify the current route to get it.
+ m_display_route = m_route.simplify();
+ }
+ return m_display_route;
+}
+
+
+void ConnRef::calcRouteDist(void)
+{
+ double (*dist)(const Point& a, const Point& b) =
+ (m_type == ConnType_PolyLine) ? euclideanDist : manhattanDist;
+
+ m_route_dist = 0;
+ for (size_t i = 1; i < m_route.size(); ++i)
+ {
+ m_route_dist += dist(m_route.at(i), m_route.at(i - 1));
+ }
+}
+
+
+bool ConnRef::needsRepaint(void) const
+{
+ return m_needs_repaint;
+}
+
+
+unsigned int ConnRef::id(void) const
+{
+ return m_id;
+}
+
+
+Point midpoint(Point a, Point b)
+{
+ Point midpoint;
+
+ midpoint.x = (a.x + b.x) / 2.0;
+ midpoint.y = (a.y + b.y) / 2.0;
+
+ return midpoint;
+}
+
+
+std::pair<JunctionRef *, ConnRef *> ConnRef::splitAtSegment(
+ const size_t segmentN)
+{
+ ConnRef *newConn = nullptr;
+ JunctionRef *newJunction = nullptr;
+
+ if (m_display_route.size() > segmentN)
+ {
+ // Position the junction at the midpoint of the desired segment.
+ Point junctionPos = midpoint(m_display_route.at(segmentN - 1),
+ m_display_route.at(segmentN));
+
+ // Create the new junction.
+ newJunction = new JunctionRef(router(), junctionPos);
+ router()->addJunction(newJunction);
+ newJunction->preferOrthogonalDimension(
+ (m_display_route.at(segmentN - 1).x ==
+ m_display_route.at(segmentN).x) ? YDIM : XDIM);
+
+ // Create a new connection routing from the junction to the original
+ // connector's endpoint.
+ ConnEnd newConnSrc = ConnEnd(newJunction);
+ ConnEnd newConnDst = *m_dst_connend;
+ newConn = new ConnRef(router(), newConnSrc, newConnDst);
+
+ // Reroute the endpoint of the original connector to attach to the
+ // new junction.
+ ConnEnd oldConnDst = ConnEnd(newJunction);
+ this->setDestEndpoint(oldConnDst);
+ }
+
+ return std::make_pair(newJunction, newConn);
+}
+
+
+VertInf *ConnRef::src(void) const
+{
+ return m_src_vert;
+}
+
+
+VertInf *ConnRef::dst(void) const
+{
+ return m_dst_vert;
+}
+
+
+VertInf *ConnRef::start(void)
+{
+ return m_start_vert;
+}
+
+
+bool ConnRef::isInitialised(void) const
+{
+ return m_active;
+}
+
+
+void ConnRef::unInitialise(void)
+{
+ m_router->vertices.removeVertex(m_src_vert);
+ m_router->vertices.removeVertex(m_dst_vert);
+ makeInactive();
+}
+
+
+void ConnRef::removeFromGraph(void)
+{
+ if (m_src_vert)
+ {
+ m_src_vert->removeFromGraph();
+ }
+
+ if (m_dst_vert)
+ {
+ m_dst_vert->removeFromGraph();
+ }
+}
+
+
+void ConnRef::setCallback(void (*cb)(void *), void *ptr)
+{
+ m_callback_func = cb;
+ m_connector = ptr;
+}
+
+
+void ConnRef::performCallback(void)
+{
+ if (m_callback_func)
+ {
+ m_callback_func(m_connector);
+ }
+}
+
+
+void ConnRef::makePathInvalid(void)
+{
+ m_needs_reroute_flag = true;
+}
+
+
+Router *ConnRef::router(void) const
+{
+ return m_router;
+}
+
+
+// Validates a bend point on a path to check it does not form a zigzag corner.
+// a, b, c are consecutive points on the path. d and e are b's neighbours,
+// forming the shape corner d-b-e.
+//
+bool validateBendPoint(VertInf *aInf, VertInf *bInf, VertInf *cInf)
+{
+ if (bInf->id.isConnectionPin() || bInf->id.isConnCheckpoint())
+ {
+ // We shouldn't check connection pins or checkpoints.
+ return true;
+ }
+ bool bendOkay = true;
+
+ if ((aInf == nullptr) || (cInf == nullptr))
+ {
+ // Not a bendpoint, i.e., the end of the connector, so don't test.
+ return bendOkay;
+ }
+
+ COLA_ASSERT(bInf != nullptr);
+ VertInf *dInf = bInf->shPrev;
+ VertInf *eInf = bInf->shNext;
+ COLA_ASSERT(dInf != nullptr);
+ COLA_ASSERT(eInf != nullptr);
+
+ Point& a = aInf->point;
+ Point& b = bInf->point;
+ Point& c = cInf->point;
+ Point& d = dInf->point;
+ Point& e = eInf->point;
+
+ if ((a == b) || (b == c))
+ {
+ return bendOkay;
+ }
+
+#ifdef PATHDEBUG
+ db_printf("a=(%g, %g)\n", a.x, a.y);
+ db_printf("b=(%g, %g)\n", b.x, b.y);
+ db_printf("c=(%g, %g)\n", c.x, c.y);
+ db_printf("d=(%g, %g)\n", d.x, d.y);
+ db_printf("e=(%g, %g)\n", e.x, e.y);
+#endif
+ // Check angle:
+ int abc = vecDir(a, b, c);
+#ifdef PATHDEBUG
+ db_printf("(abc == %d) ", abc);
+#endif
+
+ if (abc == 0)
+ {
+ // The three consecutive point on the path are in a line.
+ // There should always be an equally short path that skips this
+ // bend point, but this check is used during rubber-band routing
+ // so we allow this case.
+ bendOkay = true;
+ }
+ else // (abc != 0)
+ {
+ COLA_ASSERT(vecDir(d, b, e) > 0);
+ int abe = vecDir(a, b, e);
+ int abd = vecDir(a, b, d);
+ int bce = vecDir(b, c, e);
+ int bcd = vecDir(b, c, d);
+#ifdef PATHDEBUG
+ db_printf("&& (abe == %d) && (abd == %d) &&\n(bce == %d) && (bcd == %d)",
+ abe, abd, bce, bcd);
+#endif
+
+ bendOkay = false;
+ if (abe > 0)
+ {
+ if ((abc > 0) && (abd >= 0) && (bce >= 0))
+ {
+ bendOkay = true;
+ }
+ }
+ else if (abd < 0)
+ {
+ if ((abc < 0) && (abe <= 0) && (bcd <= 0))
+ {
+ bendOkay = true;
+ }
+ }
+ }
+#ifdef PATHDEBUG
+ db_printf("\n");
+#endif
+ return bendOkay;
+}
+
+
+std::pair<bool, bool> ConnRef::assignConnectionPinVisibility(const bool connect)
+{
+ // XXX This is kind of a hack for connection pins. Probably we want to
+ // not use m_src_vert and m_dst_vert. For the moment we will clear
+ // their visibility and give them visibility to the pins.
+ bool dummySrc = m_src_connend && m_src_connend->isPinConnection();
+ if (dummySrc)
+ {
+ m_src_vert->removeFromGraph();
+ if (connect)
+ {
+ m_src_connend->assignPinVisibilityTo(m_src_vert, m_dst_vert);
+ }
+ }
+ bool dummyDst = m_dst_connend && m_dst_connend->isPinConnection();
+ if (dummyDst)
+ {
+ m_dst_vert->removeFromGraph();
+ if (connect)
+ {
+ m_dst_connend->assignPinVisibilityTo(m_dst_vert, m_src_vert);
+ }
+ }
+
+ return std::make_pair(dummySrc, dummyDst);
+}
+
+
+bool ConnRef::generatePath(void)
+{
+ // XXX Currently rubber-band routing only works when dragging the
+ // destination point of a connector, but not the source. The code
+ // needs to be reworked to work in both directions.
+
+ if (!m_false_path && !m_needs_reroute_flag)
+ {
+ // This connector is up to date.
+ return false;
+ }
+
+ if (!m_dst_vert || !m_src_vert)
+ {
+ // Connector is not fully initialised.
+ return false;
+ }
+
+ //COLA_ASSERT(_srcVert->point != _dstVert->point);
+
+ m_false_path = false;
+ m_needs_reroute_flag = false;
+
+ m_start_vert = m_src_vert;
+
+ // Some connectors may attach to connection pins, which means they route
+ // to the closest of multiple pins on a shape. How we handle this is to
+ // add a dummy vertex as the source or target vertex. This is then given
+ // visibility to each of the possible pins and tiny distance. Here we
+ // assign this visibility by adding edges to the visibility graph that we
+ // later remove.
+ std::pair<bool, bool> isDummyAtEnd = assignConnectionPinVisibility(true);
+
+
+ if (m_router->RubberBandRouting && route().size() > 0)
+ {
+ if (isDummyAtEnd.first)
+ {
+ //ShapeConnectionPin *activePin = m_src_connend->active
+ Point firstPoint = m_src_vert->point;
+ firstPoint.id = m_src_vert->id.objID;
+ firstPoint.vn = m_src_vert->id.vn;
+ PolyLine& existingRoute = routeRef();
+ existingRoute.ps.insert(existingRoute.ps.begin(), 1, firstPoint);
+ }
+ }
+
+ std::vector<Point> path;
+ std::vector<VertInf *> vertices;
+ if (m_checkpoints.empty())
+ {
+ generateStandardPath(path, vertices);
+ }
+ else
+ {
+ generateCheckpointsPath(path, vertices);
+ }
+
+ COLA_ASSERT(vertices.size() >= 2);
+ COLA_ASSERT(vertices[0] == src());
+ COLA_ASSERT(vertices[vertices.size() - 1] == dst());
+ COLA_ASSERT(m_reroute_flag_ptr != nullptr);
+
+ for (size_t i = 1; i < vertices.size(); ++i)
+ {
+ if (m_router->InvisibilityGrph && (m_type == ConnType_PolyLine))
+ {
+ // TODO: Again, we could know this edge without searching.
+ EdgeInf *edge = EdgeInf::existingEdge(vertices[i - 1], vertices[i]);
+ if (edge) {
+ edge->addConn(m_reroute_flag_ptr);
+ }
+ }
+ else
+ {
+ m_false_path = true;
+ }
+
+ VertInf *vertex = vertices[i];
+ if (vertex->pathNext &&
+ (vertex->pathNext->point == vertex->point))
+ {
+ if (!(vertex->pathNext->id.isConnPt()) && !(vertex->id.isConnPt()))
+ {
+ // Check for consecutive points on opposite
+ // corners of two touching shapes.
+ COLA_ASSERT(abs(vertex->pathNext->id.vn - vertex->id.vn) != 2);
+ }
+ }
+ }
+
+ // Get rid of dummy ShapeConnectionPin bridging points at beginning
+ // and end of path.
+ std::vector<Point> clippedPath;
+ std::vector<Point>::iterator pathBegin = path.begin();
+ std::vector<Point>::iterator pathEnd = path.end();
+ if (path.size() > 2 && isDummyAtEnd.first)
+ {
+ ++pathBegin;
+ m_src_connend->usePinVertex(vertices[1]);
+ }
+ if (path.size() > 2 && isDummyAtEnd.second)
+ {
+ --pathEnd;
+ m_dst_connend->usePinVertex(vertices[vertices.size() - 2]);
+ }
+ clippedPath.insert(clippedPath.end(), pathBegin, pathEnd);
+
+ // Clear visibility edges added for connection pins dummy vertices.
+ assignConnectionPinVisibility(false);
+
+ freeRoutes();
+ PolyLine& output_route = m_route;
+ output_route.ps = clippedPath;
+
+#ifdef PATHDEBUG
+ db_printf("Output route:\n");
+ for (size_t i = 0; i < output_route.ps.size(); ++i)
+ {
+ db_printf("[%d,%d] %g, %g ", output_route.ps[i].id,
+ output_route.ps[i].vn, output_route.ps[i].x,
+ output_route.ps[i].y);
+ }
+ db_printf("\n\n");
+#endif
+
+#ifdef DEBUGHANDLER
+ if (m_router->debugHandler())
+ {
+ m_router->debugHandler()->updateConnectorRoute(this, -1, -1);
+ }
+#endif
+
+ return true;
+}
+
+void ConnRef::generateCheckpointsPath(std::vector<Point>& path,
+ std::vector<VertInf *>& vertices)
+{
+ std::vector<VertInf *> checkpoints = m_checkpoint_vertices;
+ checkpoints.insert(checkpoints.begin(), src());
+ checkpoints.push_back(dst());
+
+ path.clear();
+ vertices.clear();
+ path.push_back(src()->point);
+ vertices.push_back(src());
+
+ size_t lastSuccessfulIndex = 0;
+ for (size_t i = 1; i < checkpoints.size(); ++i)
+ {
+ VertInf *start = checkpoints[lastSuccessfulIndex];
+ VertInf *end = checkpoints[i];
+
+ // Handle checkpoint directions by disabling some visibility edges.
+ if (lastSuccessfulIndex > 0)
+ {
+ Checkpoint& srcCP = m_checkpoints[lastSuccessfulIndex - 1];
+ if (srcCP.departureDirections != ConnDirAll)
+ {
+ start->setVisibleDirections(srcCP.departureDirections);
+ }
+ }
+ if ((i + 1) < checkpoints.size())
+ {
+ Checkpoint& dstCP = m_checkpoints[i - 1];
+ if (dstCP.arrivalDirections != ConnDirAll)
+ {
+ end->setVisibleDirections(dstCP.arrivalDirections);
+ }
+ }
+
+ AStarPath aStar;
+ // Route the connector
+ aStar.search(this, start, end, nullptr);
+
+ // Restore changes made for checkpoint visibility directions.
+ if (lastSuccessfulIndex > 0)
+ {
+ start->setVisibleDirections(ConnDirAll);
+ }
+ if ((i + 1) < checkpoints.size())
+ {
+ end->setVisibleDirections(ConnDirAll);
+ }
+
+ // Process the path.
+ int pathlen = end->pathLeadsBackTo(start);
+ if (pathlen >= 2)
+ {
+ size_t prev_path_size = path.size();
+ path.resize(prev_path_size + (pathlen - 1));
+ vertices.resize(prev_path_size + (pathlen - 1));
+ VertInf *vertInf = end;
+ for (size_t index = path.size() - 1; index >= prev_path_size;
+ --index)
+ {
+ path[index] = vertInf->point;
+ if (vertInf->id.isConnPt())
+ {
+ path[index].id = m_id;
+ path[index].vn = kUnassignedVertexNumber;
+ }
+ else
+ {
+ path[index].id = vertInf->id.objID;
+ path[index].vn = vertInf->id.vn;
+ }
+ vertices[index] = vertInf;
+ vertInf = vertInf->pathNext;
+ }
+ lastSuccessfulIndex = i;
+ }
+ else if (i + 1 == checkpoints.size())
+ {
+ // There is no valid path.
+ db_printf("Warning: Path not found...\n");
+ m_needs_reroute_flag = true;
+
+ path.push_back(dst()->point);
+ vertices.push_back(dst());
+
+ COLA_ASSERT(path.size() >= 2);
+ }
+ else
+ {
+ err_printf("Warning: skipping checkpoint for connector "
+ "%d at (%g, %g).\n", (int) id(),
+ checkpoints[i]->point.x, checkpoints[i]->point.y);
+ fflush(stderr);
+ }
+ }
+ // Use topbit to differentiate between start and end point of connector.
+ // They need unique IDs for nudging.
+ unsigned int topbit = ((unsigned int) 1) << 31;
+ path[path.size() - 1].id = m_id | topbit;
+ path[path.size() - 1].vn = kUnassignedVertexNumber;
+}
+
+
+void ConnRef::generateStandardPath(std::vector<Point>& path,
+ std::vector<VertInf *>& vertices)
+{
+ VertInf *tar = m_dst_vert;
+ size_t existingPathStart = 0;
+ const PolyLine& currRoute = route();
+ if (m_router->RubberBandRouting)
+ {
+ COLA_ASSERT(m_router->IgnoreRegions == true);
+
+#ifdef PATHDEBUG
+ db_printf("\n");
+ src()->id.db_print();
+ db_printf(": %g, %g\n", src()->point.x, src()->point.y);
+ tar->id.db_print();
+ db_printf(": %g, %g\n", tar->point.x, tar->point.y);
+ for (size_t i = 0; i < currRoute.ps.size(); ++i)
+ {
+ db_printf("%g, %g ", currRoute.ps[i].x, currRoute.ps[i].y);
+ }
+ db_printf("\n");
+#endif
+ if (currRoute.size() > 2)
+ {
+ if (m_src_vert->point == currRoute.ps[0])
+ {
+ existingPathStart = currRoute.size() - 2;
+ COLA_ASSERT(existingPathStart != 0);
+ const Point& pnt = currRoute.at(existingPathStart);
+ VertID vID(pnt.id, pnt.vn);
+
+ m_start_vert = m_router->vertices.getVertexByID(vID);
+ COLA_ASSERT(m_start_vert);
+ }
+ }
+ }
+ //db_printf("GO\n");
+ //db_printf("src: %X strt: %X dst: %X\n", (int) m_src_vert, (int) m_start_vert, (int) m_dst_vert);
+ unsigned int pathlen = 0;
+ while (pathlen == 0)
+ {
+ AStarPath aStar;
+ aStar.search(this, src(), dst(), start());
+ pathlen = dst()->pathLeadsBackTo(src());
+ if (pathlen < 2)
+ {
+ if (existingPathStart == 0)
+ {
+ break;
+ }
+#ifdef PATHDEBUG
+ db_printf("BACK\n");
+#endif
+ existingPathStart--;
+ const Point& pnt = currRoute.at(existingPathStart);
+ VertIDProps props = (existingPathStart > 0) ? 0 :
+ VertID::PROP_ConnPoint;
+ VertID vID(pnt.id, pnt.vn, props);
+
+ m_start_vert = m_router->vertices.getVertexByID(vID);
+ COLA_ASSERT(m_start_vert);
+ }
+ else if (m_router->RubberBandRouting)
+ {
+ // found.
+ bool unwind = false;
+
+#ifdef PATHDEBUG
+ db_printf("\n\n\nSTART:\n\n");
+#endif
+ VertInf *prior = nullptr;
+ for (VertInf *curr = tar; curr != m_start_vert->pathNext;
+ curr = curr->pathNext)
+ {
+ if (!validateBendPoint(curr->pathNext, curr, prior))
+ {
+ unwind = true;
+ break;
+ }
+ prior = curr;
+ }
+ if (unwind)
+ {
+#ifdef PATHDEBUG
+ db_printf("BACK II\n");
+#endif
+ if (existingPathStart == 0)
+ {
+ break;
+ }
+ existingPathStart--;
+ const Point& pnt = currRoute.at(existingPathStart);
+ VertIDProps props = (existingPathStart > 0) ? 0 :
+ VertID::PROP_ConnPoint;
+ VertID vID(pnt.id, pnt.vn, props);
+
+ m_start_vert = m_router->vertices.getVertexByID(vID);
+ COLA_ASSERT(m_start_vert);
+
+ pathlen = 0;
+ }
+ }
+ }
+
+ if (pathlen < 2)
+ {
+ // There is no valid path.
+ db_printf("Warning: Path not found...\n");
+ m_needs_reroute_flag = true;
+ pathlen = 2;
+ tar->pathNext = m_src_vert;
+ if ((m_type == ConnType_PolyLine) && m_router->InvisibilityGrph)
+ {
+ // TODO: Could we know this edge already?
+ //EdgeInf *edge = EdgeInf::existingEdge(m_src_vert, tar);
+ //COLA_ASSERT(edge != nullptr);
+ //edge->addCycleBlocker();
+ }
+ }
+ path.resize(pathlen);
+ vertices.resize(pathlen);
+
+ unsigned int j = pathlen - 1;
+ for (VertInf *i = tar; i != m_src_vert; i = i->pathNext)
+ {
+ path[j] = i->point;
+ vertices[j] = i;
+ path[j].id = i->id.objID;
+ path[j].vn = i->id.vn;
+
+ j--;
+ }
+ vertices[0] = m_src_vert;
+ path[0] = m_src_vert->point;
+ path[0].id = m_src_vert->id.objID;
+ path[0].vn =m_src_vert->id.vn;
+}
+
+
+void ConnRef::setHateCrossings(bool value)
+{
+ m_hate_crossings = value;
+}
+
+
+bool ConnRef::doesHateCrossings(void) const
+{
+ return m_hate_crossings;
+}
+
+
+std::vector<Point> ConnRef::possibleDstPinPoints(void) const
+{
+ std::vector<Point> points;
+ if (m_dst_connend)
+ {
+ points = m_dst_connend->possiblePinPoints();
+ }
+ return points;
+}
+
+
+PtOrder::PtOrder()
+{
+ // We have sorted neither list initially.
+ for (size_t dim = 0; dim < 2; ++dim)
+ {
+ sorted[dim] = false;
+ }
+}
+
+
+PtOrder::~PtOrder()
+{
+}
+
+
+PointRepVector PtOrder::sortedPoints(const size_t dim)
+{
+ // Sort if not already sorted.
+ if (sorted[dim] == false)
+ {
+ sort(dim);
+ }
+ return sortedConnVector[dim];
+}
+
+
+int PtOrder::positionFor(const size_t dim, const ConnRef *conn)
+{
+ // Sort if not already sorted.
+ if (sorted[dim] == false)
+ {
+ sort(dim);
+ }
+
+ // Just return position from the sorted list.
+ size_t i = 0;
+ for ( ; i < sortedConnVector[dim].size(); ++i)
+ {
+ if (sortedConnVector[dim][i].second == conn)
+ {
+ return (int) i;
+ }
+ }
+ return -1;
+}
+
+
+size_t PtOrder::insertPoint(const size_t dim, const PtConnPtrPair& pointPair)
+{
+ // Is this connector bendpoint already inserted?
+ size_t i = 0;
+ for ( ; i < nodes[dim].size(); ++i)
+ {
+ if (nodes[dim][i].second == pointPair.second)
+ {
+ return i;
+ }
+ }
+ // Not found, insert.
+ nodes[dim].push_back(pointPair);
+ return nodes[dim].size() - 1;
+}
+
+void PtOrder::addPoints(const size_t dim, const PtConnPtrPair& arg1,
+ const PtConnPtrPair& arg2)
+{
+ // Add points, but not ordering information.
+ insertPoint(dim, arg1);
+ insertPoint(dim, arg2);
+}
+
+
+void PtOrder::addOrderedPoints(const size_t dim, const PtConnPtrPair& innerArg,
+ const PtConnPtrPair& outerArg, bool swapped)
+{
+ PtConnPtrPair inner = (swapped) ? outerArg : innerArg;
+ PtConnPtrPair outer = (swapped) ? innerArg : outerArg;
+ COLA_ASSERT(inner != outer);
+
+ // Add points.
+ size_t innerIndex = insertPoint(dim, inner);
+ size_t outerIndex = insertPoint(dim, outer);
+
+ // And edge for ordering information.
+ links[dim].push_back(std::make_pair(outerIndex, innerIndex));
+}
+
+
+void PtOrder::sort(const size_t dim)
+{
+ // This is just a topological sort of the points using the edges info.
+
+ sorted[dim] = true;
+
+ size_t n = nodes[dim].size();
+
+ // Build an adjacency matrix for easy lookup.
+ std::vector<std::vector<bool> > adjacencyMatrix(n);
+ for (size_t i = 0; i < n; ++i)
+ {
+ adjacencyMatrix[i].assign(n, false);
+ }
+ std::vector<int> incomingDegree(n);
+ std::queue<size_t> queue;
+
+ // Populate the dependency matrix.
+ for (NodeIndexPairLinkList::iterator it = links[dim].begin();
+ it != links[dim].end(); ++it)
+ {
+ adjacencyMatrix[it->first][it->second] = true;
+ }
+
+ // Build incoming degree lookup structure, and add nodes with no
+ // incoming edges to queue.
+ for (size_t i = 0; i < n; ++i)
+ {
+ int degree = 0;
+
+ for (size_t j = 0; j < n; ++j)
+ {
+ if (adjacencyMatrix[j][i])
+ {
+ degree++;
+ }
+ }
+ incomingDegree[i] = degree;
+
+ if (degree == 0)
+ {
+ queue.push(i);
+ }
+ }
+
+ while (queue.empty() == false)
+ {
+ size_t k = queue.front();
+ assert(k < nodes[dim].size());
+ queue.pop();
+
+ // Insert node k into the sorted list
+ sortedConnVector[dim].push_back(nodes[dim][k]);
+
+ // Remove all edges leaving node k:
+ for (size_t i = 0; i < n; ++i)
+ {
+ if (adjacencyMatrix[k][i])
+ {
+ adjacencyMatrix[k][i] = false;
+ incomingDegree[i]--;
+
+ if (incomingDegree[i] == 0)
+ {
+ queue.push(i);
+ }
+ }
+ }
+ }
+}
+
+
+// Returns a vertex number representing a point on the line between
+// two shape corners, represented by p0 and p1.
+//
+static int midVertexNumber(const Point& p0, const Point& p1, const Point& c)
+{
+ if (c.vn != kUnassignedVertexNumber)
+ {
+ // The split point is a shape corner, so doesn't need its
+ // vertex number adjusting.
+ return c.vn;
+ }
+ if ((p0.vn >= 4) && (p0.vn < kUnassignedVertexNumber))
+ {
+ // The point next to this has the correct nudging direction,
+ // so use that.
+ return p0.vn;
+ }
+ if ((p1.vn >= 4) && (p1.vn < kUnassignedVertexNumber))
+ {
+ // The point next to this has the correct nudging direction,
+ // so use that.
+ return p1.vn;
+ }
+ if ((p0.vn < 4) && (p1.vn < 4))
+ {
+ if (p0.vn != p1.vn)
+ {
+ return p0.vn;
+ }
+ // Splitting between two ordinary shape corners.
+ int vn_mid = std::min(p0.vn, p1.vn);
+ if ((std::max(p0.vn, p1.vn) == 3) && (vn_mid == 0))
+ {
+ vn_mid = 3; // Next vn is effectively 4.
+ }
+ return vn_mid + 4;
+ }
+ COLA_ASSERT((p0.x == p1.x) || (p0.y == p1.y));
+ if (p0.vn != kUnassignedVertexNumber)
+ {
+ if (p0.x == p1.x)
+ {
+ if ((p0.vn == 2) || (p0.vn == 3))
+ {
+ return 6;
+ }
+ return 4;
+ }
+ else
+ {
+ if ((p0.vn == 0) || (p0.vn == 3))
+ {
+ return 7;
+ }
+ return 5;
+ }
+ }
+ else if (p1.vn != kUnassignedVertexNumber)
+ {
+ if (p0.x == p1.x)
+ {
+ if ((p1.vn == 2) || (p1.vn == 3))
+ {
+ return 6;
+ }
+ return 4;
+ }
+ else
+ {
+ if ((p1.vn == 0) || (p1.vn == 3))
+ {
+ return 7;
+ }
+ return 5;
+ }
+ }
+
+ // Shouldn't both be new (kUnassignedVertexNumber) points.
+ db_printf("midVertexNumber(): p0.vn and p1.vn both = "
+ "kUnassignedVertexNumber\n");
+ db_printf("p0.vn %d p1.vn %d\n", p0.vn, p1.vn);
+ return kUnassignedVertexNumber;
+}
+
+
+// Break up overlapping parallel segments that are not the same edge in
+// the visibility graph, i.e., where one segment is a subsegment of another.
+void splitBranchingSegments(Avoid::Polygon& poly, bool polyIsConn,
+ Avoid::Polygon& conn, const double tolerance)
+{
+ for (std::vector<Avoid::Point>::iterator i = conn.ps.begin();
+ i != conn.ps.end(); ++i)
+ {
+ if (i == conn.ps.begin())
+ {
+ // Skip the first point.
+ // There are points-1 segments in a connector.
+ continue;
+ }
+
+ for (std::vector<Avoid::Point>::iterator j = poly.ps.begin();
+ j != poly.ps.end(); )
+ {
+ if (polyIsConn && (j == poly.ps.begin()))
+ {
+ // Skip the first point.
+ // There are points-1 segments in a connector.
+ ++j;
+ continue;
+ }
+ Point& c0 = *(i - 1);
+ Point& c1 = *i;
+
+ Point& p0 = (j == poly.ps.begin()) ? poly.ps.back() : *(j - 1);
+ Point& p1 = *j;
+
+ // Check the first point of the first segment.
+ if (((i - 1) == conn.ps.begin()) &&
+ pointOnLine(p0, p1, c0, tolerance))
+ {
+ //db_printf("add to poly %g %g\n", c0.x, c0.y);
+
+ c0.vn = midVertexNumber(p0, p1, c0);
+ j = poly.ps.insert(j, c0);
+ if (j != poly.ps.begin())
+ {
+ --j;
+ }
+ continue;
+ }
+ // And the second point of every segment.
+ if (pointOnLine(p0, p1, c1, tolerance))
+ {
+ //db_printf("add to poly %g %g\n", c1.x, c1.y);
+
+ c1.vn = midVertexNumber(p0, p1, c1);
+ j = poly.ps.insert(j, c1);
+ if (j != poly.ps.begin())
+ {
+ --j;
+ }
+ continue;
+ }
+
+ // Check the first point of the first segment.
+ if (polyIsConn && ((j - 1) == poly.ps.begin()) &&
+ pointOnLine(c0, c1, p0, tolerance))
+ {
+ //db_printf("add to conn %g %g\n", p0.x, p0.y);
+
+ p0.vn = midVertexNumber(c0, c1, p0);
+ i = conn.ps.insert(i, p0);
+ continue;
+ }
+ // And the second point of every segment.
+ if (pointOnLine(c0, c1, p1, tolerance))
+ {
+ //db_printf("add to conn %g %g\n", p1.x, p1.y);
+
+ p1.vn = midVertexNumber(c0, c1, p1);
+ i = conn.ps.insert(i, p1);
+ }
+ ++j;
+ }
+ }
+}
+
+
+static int segDir(const Point& p1, const Point& p2)
+{
+ int result = 1;
+ if (p1.x == p2.x)
+ {
+ if (p2.y > p1.y)
+ {
+ result = -1;
+ }
+ }
+ else if (p1.y == p2.y)
+ {
+ if (p2.x < p1.x)
+ {
+ result = -1;
+ }
+ }
+ return result;
+}
+
+
+static bool posInlineWithConnEndSegs(const double pos, const size_t dim,
+ const Avoid::Polygon& poly, const Avoid::Polygon& conn)
+{
+ size_t pLast = poly.size() - 1;
+ size_t cLast = conn.size() - 1;
+ if ((
+ // Is inline with the beginning of the "poly" line
+ ((pos == poly.ps[0][dim]) && (pos == poly.ps[1][dim])) ||
+ // Is inline with the end of the "poly" line
+ ((pos == poly.ps[pLast][dim]) && (pos == poly.ps[pLast - 1][dim]))
+ ) && (
+ // Is inline with the beginning of the "conn" line
+ ((pos == conn.ps[0][dim]) && (pos == conn.ps[1][dim])) ||
+ // Is inline with the end of the "conn" line
+ ((pos == conn.ps[cLast][dim]) && (pos == conn.ps[cLast - 1][dim]))
+ ))
+ {
+ return true;
+ }
+ return false;
+}
+
+ConnectorCrossings::ConnectorCrossings(Avoid::Polygon& poly, bool polyIsConn,
+ Avoid::Polygon& conn, ConnRef *polyConnRef, ConnRef *connConnRef)
+ : poly(poly),
+ polyIsConn(polyIsConn),
+ conn(conn),
+ checkForBranchingSegments(false),
+ polyConnRef(polyConnRef),
+ connConnRef(connConnRef),
+ crossingPoints(nullptr),
+ pointOrders(nullptr),
+ sharedPaths(nullptr)
+{
+}
+
+void ConnectorCrossings::clear(void)
+{
+ crossingCount = 0;
+ crossingFlags = CROSSING_NONE;
+ firstSharedPathAtEndLength = DBL_MAX;
+ secondSharedPathAtEndLength = DBL_MAX;
+}
+
+
+// Computes the *shared* length of these two shared paths.
+//
+static double pathLength(Avoid::Point **c_path, Avoid::Point **p_path,
+ size_t size)
+{
+ double length = 0;
+
+ for (unsigned int ind = 1; ind < size; ++ind)
+ {
+ if ( (*(c_path[ind - 1]) == *(p_path[ind - 1])) &&
+ (*(c_path[ind]) == *(p_path[ind])) )
+ {
+ // This segment is shared by both paths.
+ //
+ // This function will only be used for orthogonal paths, so we
+ // can use Manhattan distance here since it will be faster to
+ // compute.
+ length += manhattanDist(*(c_path[ind - 1]), *(c_path[ind]));
+ }
+ }
+
+ return length;
+}
+
+// Works out if the segment conn[cIndex-1]--conn[cIndex] really crosses poly.
+// This does not not count non-crossing shared paths as crossings.
+// poly can be either a connector (polyIsConn = true) or a cluster
+// boundary (polyIsConn = false).
+//
+void ConnectorCrossings::countForSegment(size_t cIndex, const bool finalSegment)
+{
+ clear();
+
+ bool polyIsOrthogonal = (polyConnRef &&
+ (polyConnRef->routingType() == ConnType_Orthogonal));
+ bool connIsOrthogonal = (connConnRef &&
+ (connConnRef->routingType() == ConnType_Orthogonal));
+
+ // Fixed routes will not have segment breaks at possible crossings.
+ bool polyIsFixed = (polyConnRef && polyConnRef->hasFixedRoute());
+ bool connIsFixed = (connConnRef && connConnRef->hasFixedRoute());
+
+ // We need to split apart connectors at potential crossing points if
+ // either has a fixed route or it is a polyline connector. This is not
+ // needed for orthogonal connectors where crossings occur at vertices
+ // in visibility graph and on the raw connector routes.
+ if (checkForBranchingSegments || polyIsFixed || connIsFixed ||
+ !polyIsOrthogonal || !connIsOrthogonal)
+ {
+ double epsilon = std::numeric_limits<double>::epsilon();
+ size_t conn_pn = conn.size();
+ // XXX When doing the pointOnLine test we allow the points to be
+ // slightly non-collinear. This addresses a problem with clustered
+ // routing where connectors could otherwise route cheaply through
+ // shape corners that were not quite on the cluster boundary, but
+ // reported to be on there by the line segment intersection code,
+ // which I suspect is not numerically accurate enough. This occurred
+ // for points that only differed by about 10^-12 in the y-dimension.
+ double tolerance = (!polyIsConn) ? epsilon : 0.0;
+ splitBranchingSegments(poly, polyIsConn, conn, tolerance);
+ // cIndex is going to be the last, so take into account added points.
+ cIndex += (conn.size() - conn_pn);
+ }
+ COLA_ASSERT(cIndex >= 1);
+ COLA_ASSERT(cIndex < conn.size());
+
+ size_t poly_size = poly.size();
+
+ Avoid::Point& a1 = conn.ps[cIndex - 1];
+ Avoid::Point& a2 = conn.ps[cIndex];
+ //db_printf("a1: %g %g\n", a1.x, a1.y);
+ //db_printf("a2: %g %g\n", a2.x, a2.y);
+
+ // Allocate arrays for computing shared paths.
+ // Don't use dynamic array due to portablity issues.
+ size_t max_path_size = std::min(poly_size, conn.size());
+ Avoid::Point **c_path = new Avoid::Point*[max_path_size];
+ Avoid::Point **p_path = new Avoid::Point*[max_path_size];
+ size_t size = 0;
+
+ for (size_t j = ((polyIsConn) ? 1 : 0); j < poly_size; ++j)
+ {
+ Avoid::Point& b1 = poly.ps[(j - 1 + poly_size) % poly_size];
+ Avoid::Point& b2 = poly.ps[j];
+ //db_printf("b1: %g %g\n", b1.x, b1.y);
+ //db_printf("b2: %g %g\n", b2.x, b2.y);
+
+ size = 0;
+
+ bool converging = false;
+
+ const bool a1_eq_b1 = (a1 == b1);
+ const bool a2_eq_b1 = (a2 == b1);
+ const bool a2_eq_b2 = (a2 == b2);
+ const bool a1_eq_b2 = (a1 == b2);
+
+ if ( (a1_eq_b1 && a2_eq_b2) ||
+ (a2_eq_b1 && a1_eq_b2) )
+ {
+ if (finalSegment)
+ {
+ converging = true;
+ }
+ else
+ {
+ // Route along same segment: no penalty. We detect
+ // crossovers when we see the segments diverge.
+ continue;
+ }
+ }
+ else if (a2_eq_b1 || a2_eq_b2 || a1_eq_b2)
+ {
+ // Each crossing that is at a vertex in the
+ // visibility graph gets noticed four times.
+ // We ignore three of these cases.
+ // This also catches the case of a shared path,
+ // but this is one that terminates at a common
+ // endpoint, so we don't care about it.
+ continue;
+ }
+
+ if (a1_eq_b1 || converging)
+ {
+ if (!converging)
+ {
+ if (polyIsConn && (j == 1))
+ {
+ // Can't be the end of a shared path or crossing path
+ // since the common point is the first point of the
+ // connector path. This is not a shared path at all.
+ continue;
+ }
+
+ Avoid::Point& b0 = poly.ps[(j - 2 + poly_size) % poly_size];
+ // The segments share an endpoint -- a1==b1.
+ if (a2 == b0)
+ {
+ // a2 is not a split, continue.
+ continue;
+ }
+ }
+
+ // If here and not converging, then we know that a2 != b2
+ // And a2 and its pair in b are a split.
+ COLA_ASSERT(converging || !a2_eq_b2);
+
+ bool shared_path = false;
+
+ // Initial values here don't matter. They are only used after
+ // being set to sensible values, but we set them to stop a MSVC
+ // warning.
+ bool p_dir_back;
+ int p_dir = 0;
+ int trace_c = 0;
+ int trace_p = 0;
+
+ if (converging)
+ {
+ // Determine direction we have to look through
+ // the points of connector b.
+ p_dir_back = a2_eq_b2 ? true : false;
+ p_dir = p_dir_back ? -1 : 1;
+ trace_c = (int) cIndex;
+ trace_p = (int) j;
+ if (!p_dir_back)
+ {
+ if (finalSegment)
+ {
+ trace_p--;
+ }
+ else
+ {
+ trace_c--;
+ }
+ }
+
+ shared_path = true;
+ }
+ else if (cIndex >= 2)
+ {
+ Avoid::Point& b0 = poly.ps[(j - 2 + poly_size) % poly_size];
+ Avoid::Point& a0 = conn.ps[cIndex - 2];
+
+ //db_printf("a0: %g %g\n", a0.x, a0.y);
+ //db_printf("b0: %g %g\n", b0.x, b0.y);
+
+ if ((a0 == b2) || (a0 == b0))
+ {
+ // Determine direction we have to look through
+ // the points of connector b.
+ p_dir_back = (a0 == b0) ? true : false;
+ p_dir = p_dir_back ? -1 : 1;
+ trace_c = (int) cIndex;
+ trace_p = (int) (p_dir_back ? j : j - 2);
+
+ shared_path = true;
+ }
+ }
+
+ if (shared_path)
+ {
+ crossingFlags |= CROSSING_SHARES_PATH;
+ // Shouldn't be here if p_dir is still equal to zero.
+ COLA_ASSERT(p_dir != 0);
+
+ // Build the shared path, including the diverging points at
+ // each end if the connector does not end at a common point.
+ while ( (trace_c >= 0) && (!polyIsConn ||
+ ((trace_p >= 0) && (trace_p < (int) poly_size))) )
+ {
+ // If poly is a cluster boundary, then it is a closed
+ // poly-line and so it wraps around.
+ size_t index_p = (size_t)
+ ((trace_p + (2 * poly_size)) % poly_size);
+ size_t index_c = (size_t) trace_c;
+ c_path[size] = &conn.ps[index_c];
+ p_path[size] = &poly.ps[index_p];
+ ++size;
+ if ((size > 1) && (conn.ps[index_c] != poly.ps[index_p]))
+ {
+ // Points don't match, so break out of loop.
+ break;
+ }
+ trace_c--;
+ trace_p += p_dir;
+ }
+
+ // Are there diverging points at the ends of the shared path.
+ bool front_same = (*(c_path[0]) == *(p_path[0]));
+ bool back_same = (*(c_path[size - 1]) == *(p_path[size - 1]));
+
+ // Determine if the shared path originates at a junction.
+ bool terminatesAtJunction = false;
+ if (polyConnRef && connConnRef && (front_same || back_same))
+ {
+ // To do this we find the two ConnEnds at the common
+ // end of the shared path. Then check if they are
+ // attached to a junction and it is the same one.
+ std::pair<ConnEnd, ConnEnd> connEnds =
+ connConnRef->endpointConnEnds();
+ JunctionRef *connJunction = nullptr;
+
+ std::pair<ConnEnd, ConnEnd> polyEnds =
+ polyConnRef->endpointConnEnds();
+ JunctionRef *polyJunction = nullptr;
+
+ // The front of the c_path corresponds to destination
+ // of the connector.
+ connJunction = (front_same) ? connEnds.second.junction() :
+ connEnds.first.junction();
+ bool use_first = back_same;
+ if (p_dir_back)
+ {
+ // Reversed, so use opposite.
+ use_first = !use_first;
+ }
+ // The front of the p_path corresponds to destination
+ // of the connector.
+ polyJunction = (use_first) ? polyEnds.second.junction() :
+ polyEnds.first.junction();
+
+ terminatesAtJunction = (connJunction &&
+ (connJunction == polyJunction));
+ }
+
+ if (sharedPaths)
+ {
+ // Store a copy of the shared path
+ size_t start = (front_same) ? 0 : 1;
+ size_t limit = size - ((back_same) ? 0 : 1);
+
+ PointList sPath(limit - start);
+ for (size_t i = start; i < limit; ++i)
+ {
+ sPath[i - start] = *(c_path[i]);
+ }
+ sharedPaths->push_back(sPath);
+ }
+
+ // Check to see if these share a fixed segment.
+ if (polyIsOrthogonal && connIsOrthogonal)
+ {
+ size_t startPt = (front_same) ? 0 : 1;
+ size_t endPt = size - ((back_same) ? 1 : 2);
+ for (size_t dim = 0; dim < 2; ++dim)
+ {
+ if ((*c_path[startPt])[dim] == (*c_path[endPt])[dim])
+ {
+ double pos = (*c_path[startPt])[dim];
+ // See if this is inline with either the start
+ // or end point of both connectors. We don't
+ // count them as crossing if they originate at a
+ // junction and are part of the same hyperedge.
+ if ( ((pos == poly.ps[0][dim]) ||
+ (pos == poly.ps[poly_size - 1][dim])) &&
+ ((pos == conn.ps[0][dim]) ||
+ (pos == conn.ps[cIndex][dim])) &&
+ (terminatesAtJunction == false))
+ {
+ crossingFlags |= CROSSING_SHARES_FIXED_SEGMENT;
+ }
+ }
+ }
+
+ if (!front_same && !back_same)
+ {
+ // Find overlapping segments that are constrained by
+ // the fact that both the adjoining segments are fixed
+ // in the other dimension, i.e.,
+ //
+ // X------++---X
+ // ||
+ // ||
+ // X---++------X
+ //
+ // In the example above, altDim is X, and dim is Y.
+ //
+
+ // For each dimension...
+ for (size_t dim = 0; dim < 2; ++dim)
+ {
+ size_t end = size - 1;
+ size_t altDim = (dim + 1) % 2;
+ // If segment is in this dimension...
+ if ((*c_path[1])[altDim] == (*c_path[end - 1])[altDim])
+ {
+ double posBeg = (*c_path[1])[dim];
+ double posEnd = (*c_path[end - 1])[dim];
+ // If both segment ends diverge at right-angles...
+ if ( (posBeg == (*c_path[0])[dim]) &&
+ (posBeg == (*p_path[0])[dim]) &&
+ (posEnd == (*c_path[end])[dim]) &&
+ (posEnd == (*p_path[end])[dim]) )
+ {
+ // and these segments are inline with the conn and path ends themselves...
+ if (posInlineWithConnEndSegs(posBeg, dim,
+ conn, poly) &&
+ posInlineWithConnEndSegs(posEnd, dim,
+ conn, poly))
+ {
+ // If all endpoints branch at right angles,
+ // then penalise this since it is a segment
+ // will will not be able to nudge apart
+ // without introducing fixed segment
+ // crossings.
+ crossingFlags |=
+ CROSSING_SHARES_FIXED_SEGMENT;
+ }
+ }
+ }
+ }
+ }
+
+#if 0
+ // XXX: What is this code for? It is pretty much
+ // incomprehensible and also causes one of the test
+ // cases to fail.
+ //
+ if (!front_same && !back_same)
+ {
+ for (size_t dim = 0; dim < 2; ++dim)
+ {
+ size_t altDim = (dim + 1) % 2;
+ if ((*c_path[1])[altDim] == (*c_path[1])[altDim])
+ {
+ size_t n = c_path.size();
+ double yPosB = (*c_path[1])[dim];
+ if ( (yPosB == (*c_path[0])[dim]) &&
+ (yPosB == (*p_path[0])[dim]) )
+ {
+ crossingFlags |=
+ CROSSING_SHARES_FIXED_SEGMENT;
+ }
+
+ double yPosE = (*c_path[n - 2])[dim];
+ if ( (yPosE == (*c_path[n - 1])[dim]) &&
+ (yPosE == (*p_path[n - 1])[dim]) )
+ {
+ crossingFlags |=
+ CROSSING_SHARES_FIXED_SEGMENT;
+ }
+ }
+ }
+ }
+#endif
+ }
+
+ // {start,end}CornerSide specifies which side of conn the
+ // poly path enters and leaves.
+ int startCornerSide = 1;
+ int endCornerSide = 1;
+
+ bool reversed = false;
+ if (!front_same)
+ {
+ // If there is a divergence at the beginning,
+ // then order the shared path based on this.
+ startCornerSide = Avoid::cornerSide(*c_path[0], *c_path[1],
+ *c_path[2], *p_path[0]);
+ }
+ if (!back_same)
+ {
+ // If there is a divergence at the end of the path,
+ // then order the shared path based on this.
+ endCornerSide = Avoid::cornerSide(*c_path[size - 3],
+ *c_path[size - 2], *c_path[size - 1],
+ *p_path[size - 1]);
+ }
+ else
+ {
+ endCornerSide = startCornerSide;
+ }
+ if (front_same)
+ {
+ startCornerSide = endCornerSide;
+ }
+
+ if (endCornerSide != startCornerSide)
+ {
+ // Mark that the shared path crosses.
+ //db_printf("shared path crosses.\n");
+ crossingCount += 1;
+ if (crossingPoints)
+ {
+ crossingPoints->insert(*c_path[1]);
+ }
+ }
+
+ if (front_same || back_same)
+ {
+ crossingFlags |= CROSSING_SHARES_PATH_AT_END;
+
+ // Reduce the cost of paths that stay straight after
+ // the split, and make this length available so that the
+ // paths can be ordered during the improveCrossings()
+ // step and the straight (usually better) paths will be
+ // left alone while the router attempts to find better
+ // paths for the others.
+ double straightModifier = 200;
+ firstSharedPathAtEndLength = secondSharedPathAtEndLength =
+ pathLength(c_path, p_path, size);
+ if (back_same && (size > 2))
+ {
+ if (vecDir(*p_path[0], *p_path[1], *p_path[2]) == 0)
+ {
+ firstSharedPathAtEndLength -= straightModifier;
+ }
+
+ if (vecDir(*c_path[0], *c_path[1], *c_path[2]) == 0)
+ {
+ secondSharedPathAtEndLength -= straightModifier;
+ }
+ }
+ else if (front_same && (size > 2))
+ {
+ if (vecDir(*p_path[size - 3], *p_path[size - 2],
+ *p_path[size - 1]) == 0)
+ {
+ firstSharedPathAtEndLength -= straightModifier;
+ }
+
+ if (vecDir(*c_path[size - 3], *c_path[size - 2],
+ *c_path[size - 1]) == 0)
+ {
+ secondSharedPathAtEndLength -= straightModifier;
+ }
+ }
+ }
+ else if (polyIsOrthogonal && connIsOrthogonal)
+ {
+ int cStartDir = vecDir(*c_path[0], *c_path[1], *c_path[2]);
+ int pStartDir = vecDir(*p_path[0], *p_path[1], *p_path[2]);
+ if ((cStartDir != 0) && (cStartDir == -pStartDir))
+ {
+ // The start segments diverge at 180 degrees to each
+ // other. So order based on not introducing overlap
+ // of the diverging segments when these are nudged
+ // apart.
+ startCornerSide = -cStartDir;
+ }
+ else
+ {
+ int cEndDir = vecDir(*c_path[size - 3],
+ *c_path[size - 2], *c_path[size - 1]);
+ int pEndDir = vecDir(*p_path[size - 3],
+ *p_path[size - 2], *p_path[size - 1]);
+ if ((cEndDir != 0) && (cEndDir == -pEndDir))
+ {
+ // The end segments diverge at 180 degrees to
+ // each other. So order based on not introducing
+ // overlap of the diverging segments when these
+ // are nudged apart.
+ startCornerSide = -cEndDir;
+ }
+ }
+ }
+
+#if 0
+ int prevTurnDir = 0;
+ if (pointOrders)
+ {
+ // Return the ordering for the shared path.
+ COLA_ASSERT(c_path.size() > 0 || back_same);
+ size_t adj_size = (c_path.size() - ((back_same) ? 0 : 1));
+ for (size_t i = (front_same) ? 0 : 1; i < adj_size; ++i)
+ {
+ Avoid::Point& an = *(c_path[i]);
+ Avoid::Point& bn = *(p_path[i]);
+ int currTurnDir = ((i > 0) && (i < (adj_size - 1))) ?
+ vecDir(*c_path[i - 1], an,
+ *c_path[i + 1]) : 0;
+ VertID vID(an.id, true, an.vn);
+ if ( (currTurnDir == (-1 * prevTurnDir)) &&
+ (currTurnDir != 0) && (prevTurnDir != 0) )
+ {
+ // The connector turns the opposite way around
+ // this shape as the previous bend on the path,
+ // so reverse the order so that the inner path
+ // become the outer path and vice versa.
+ reversed = !reversed;
+ }
+ bool orderSwapped = (*pointOrders)[an].addOrderedPoints(
+ &bn, &an, reversed);
+ if (orderSwapped)
+ {
+ // Reverse the order for later points.
+ reversed = !reversed;
+ }
+ prevTurnDir = currTurnDir;
+ }
+ }
+#endif
+ if (pointOrders)
+ {
+ reversed = false;
+ size_t startPt = (front_same) ? 0 : 1;
+
+ // Orthogonal should always have at least one segment.
+ COLA_ASSERT(size > (startPt + 1));
+
+ if (startCornerSide > 0)
+ {
+ reversed = !reversed;
+ }
+
+ int prevDir = 0;
+ // Return the ordering for the shared path.
+ COLA_ASSERT(size > 0 || back_same);
+ size_t adj_size = (size - ((back_same) ? 0 : 1));
+ for (size_t i = startPt; i < adj_size; ++i)
+ {
+ Avoid::Point& an = *(c_path[i]);
+ Avoid::Point& bn = *(p_path[i]);
+ COLA_ASSERT(an == bn);
+
+ if (i > startPt)
+ {
+ Avoid::Point& ap = *(c_path[i - 1]);
+ Avoid::Point& bp = *(p_path[i - 1]);
+
+ int thisDir = segDir(ap, an);
+ if (prevDir == 0)
+ {
+ if (thisDir > 0)
+ {
+ reversed = !reversed;
+ }
+ }
+ else if (thisDir != prevDir)
+ {
+ reversed = !reversed;
+ }
+
+ int orientation = (ap.x == an.x) ? 0 : 1;
+ //printf("prevOri %d\n", prevOrientation);
+ //printf("1: %X, %X\n", (int) &(bn), (int) &(an));
+ (*pointOrders)[an].addOrderedPoints(
+ orientation,
+ std::make_pair(&bn, polyConnRef),
+ std::make_pair(&an, connConnRef),
+ reversed);
+ COLA_ASSERT(ap == bp);
+ //printf("2: %X, %X\n", (int) &bp, (int) &ap);
+ (*pointOrders)[ap].addOrderedPoints(
+ orientation,
+ std::make_pair(&bp, polyConnRef),
+ std::make_pair(&ap, connConnRef),
+ reversed);
+ prevDir = thisDir;
+ }
+ }
+ }
+#if 0
+ int ymod = -1;
+ if ((id.vn == 1) || (id.vn == 2))
+ {
+ // bottom.
+ ymod = +1;
+ }
+
+ int xmod = -1;
+ if ((id.vn == 0) || (id.vn == 1))
+ {
+ // right.
+ xmod = +1;
+ }
+ if(id.vn > 3)
+ {
+ xmod = ymod = 0;
+ if (id.vn == 4)
+ {
+ // right.
+ xmod = +1;
+ }
+ else if (id.vn == 5)
+ {
+ // bottom.
+ ymod = +1;
+ }
+ else if (id.vn == 6)
+ {
+ // left.
+ xmod = -1;
+ }
+ else if (id.vn == 7)
+ {
+ // top.
+ ymod = -1;
+ }
+ }
+#endif
+
+ crossingFlags |= CROSSING_TOUCHES;
+ }
+ else if (cIndex >= 2)
+ {
+ // The connectors cross or touch at this point.
+ //db_printf("Cross or touch at point... \n");
+
+ // Crossing shouldn't be at an endpoint.
+ COLA_ASSERT(cIndex >= 2);
+ COLA_ASSERT(!polyIsConn || (j >= 2));
+
+ Avoid::Point& b0 = poly.ps[(j - 2 + poly_size) % poly_size];
+ Avoid::Point& a0 = conn.ps[cIndex - 2];
+
+ int side1 = Avoid::cornerSide(a0, a1, a2, b0);
+ int side2 = Avoid::cornerSide(a0, a1, a2, b2);
+ if (side1 != side2)
+ {
+ // The connectors cross at this point.
+ //db_printf("cross.\n");
+ crossingCount += 1;
+ if (crossingPoints)
+ {
+ crossingPoints->insert(a1);
+ }
+ }
+
+ crossingFlags |= CROSSING_TOUCHES;
+ if (pointOrders)
+ {
+ if (polyIsOrthogonal && connIsOrthogonal)
+ {
+ // Orthogonal case:
+ // Just order based on which comes from the left and
+ // top in each dimension because this can only be two
+ // L-shaped segments touching at the bend.
+ bool reversedX = ((a0.x < a1.x) || (a2.x < a1.x));
+ bool reversedY = ((a0.y < a1.y) || (a2.y < a1.y));
+ // XXX: Why do we need to invert the reversed values
+ // here? Are they wrong for orthogonal points
+ // in the other places?
+ (*pointOrders)[b1].addOrderedPoints(0,
+ std::make_pair(&b1, polyConnRef),
+ std::make_pair(&a1, connConnRef),
+ !reversedX);
+ (*pointOrders)[b1].addOrderedPoints(1,
+ std::make_pair(&b1, polyConnRef),
+ std::make_pair(&a1, connConnRef),
+ !reversedY);
+ }
+#if 0
+// Unused code.
+ else
+ {
+ int turnDirA = vecDir(a0, a1, a2);
+ int turnDirB = vecDir(b0, b1, b2);
+ bool reversed = (side1 != -turnDirA);
+ if (side1 != side2)
+ {
+ // Interesting case where a connector routes round
+ // the edge of a shape and intersects a connector
+ // which is connected to a port on the edge of the
+ // shape.
+ if (turnDirA == 0)
+ {
+ // We'll make B the outer by preference,
+ // because the points of A are collinear.
+ reversed = false;
+ }
+ else if (turnDirB == 0)
+ {
+ reversed = true;
+ }
+ // TODO COLA_ASSERT((turnDirB != 0) ||
+ // (turnDirA != 0));
+ }
+ VertID vID(b1.id, b1.vn);
+ //(*pointOrders)[b1].addOrderedPoints(&b1, &a1, reversed);
+ }
+#endif
+ }
+ }
+ }
+ else
+ {
+ if ( polyIsOrthogonal && connIsOrthogonal)
+ {
+ // All crossings in orthogonal connectors will be at a
+ // vertex in the visibility graph, so we need not bother
+ // doing normal line intersection.
+ continue;
+ }
+
+ // No endpoint is shared between these two line segments,
+ // so just calculate normal segment intersection.
+
+ Point cPt;
+ int intersectResult = Avoid::segmentIntersectPoint(
+ a1, a2, b1, b2, &(cPt.x), &(cPt.y));
+
+ if (intersectResult == Avoid::DO_INTERSECT)
+ {
+ if (!polyIsConn &&
+ ((a1 == cPt) || (a2 == cPt) || (b1 == cPt) || (b2 == cPt)))
+ {
+ // XXX: This shouldn't actually happen, because these
+ // points should be added as bends to each line by
+ // splitBranchingSegments(). Thus, lets ignore them.
+ COLA_ASSERT(a1 != cPt);
+ COLA_ASSERT(a2 != cPt);
+ COLA_ASSERT(b1 != cPt);
+ COLA_ASSERT(b2 != cPt);
+ continue;
+ }
+ //db_printf("crossing lines:\n");
+ //db_printf("cPt: %g %g\n", cPt.x, cPt.y);
+ crossingCount += 1;
+ if (crossingPoints)
+ {
+ crossingPoints->insert(cPt);
+ }
+ }
+ }
+ }
+ //db_printf("crossingcount %d %d\n", crossingCount, crossingFlags);
+
+ // Free shared path memory.
+ delete[] c_path;
+ delete[] p_path;
+}
+
+
+//============================================================================
+
+}
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/connector.h b/src/3rdparty/adaptagrams/libavoid/connector.h
new file mode 100644
index 0000000..7457139
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/connector.h
@@ -0,0 +1,547 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2015 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+//! @file connector.h
+//! @brief Contains the interface for the ConnRef class.
+
+
+#ifndef AVOID_CONNECTOR_H
+#define AVOID_CONNECTOR_H
+
+#include <utility>
+#include <list>
+#include <vector>
+
+#include "libavoid/dllexport.h"
+#include "libavoid/vertices.h"
+#include "libavoid/geometry.h"
+#include "libavoid/connend.h"
+
+
+namespace Avoid {
+
+class Router;
+class ConnRef;
+class JunctionRef;
+class ShapeRef;
+typedef std::list<ConnRef *> ConnRefList;
+
+
+//! @brief Describes the type of routing that is performed for each
+//! connector.
+enum ConnType {
+ ConnType_None = 0,
+ //! @brief The connector path will be a shortest-path poly-line that
+ //! routes around obstacles.
+ ConnType_PolyLine = 1,
+ //! @brief The connector path will be a shortest-path orthogonal
+ //! poly-line (only vertical and horizontal line segments) that
+ //! routes around obstacles.
+ ConnType_Orthogonal = 2
+};
+
+//! @brief A checkpoint is a point that the route for a particular connector
+//! must visit. They may optionally be given an arrival/departure
+//! direction.
+//!
+class AVOID_EXPORT Checkpoint
+{
+ public:
+ //! @brief A point that a route must visit.
+ //!
+ //! The connector will be able to enter and leave this checkpoint from
+ //! any direction.
+ //!
+ //! @param[in] p The Point that must be visited.
+ Checkpoint(const Point& p)
+ : point(p),
+ arrivalDirections(ConnDirAll),
+ departureDirections(ConnDirAll)
+ {
+ }
+ //! @brief A point that a route must visit.
+ //!
+ //! The connector will be able to enter and leave this checkpoint from
+ //! the directions specified. Give Avoid::ConnDirAll to specify all
+ //! directions.
+ //!
+ //! @param[in] p The Point that must be visited.
+ //! @param[in] ad Avoid::ConnDirFlags denoting arrival directions for
+ //! the connector portion leading up to this checkpoint.
+ //! @param[in] dd Avoid::ConnDirFlags denoting departure directions
+ //! for the connector portion leading away from this
+ //! checkpoint.
+ Checkpoint(const Point& p, ConnDirFlags ad, ConnDirFlags dd)
+ : point(p),
+ arrivalDirections(ad),
+ departureDirections(dd)
+ {
+ }
+ // Default constructor.
+ Checkpoint()
+ : point(Point()),
+ arrivalDirections(ConnDirAll),
+ departureDirections(ConnDirAll)
+ {
+ }
+
+ Point point;
+ ConnDirFlags arrivalDirections;
+ ConnDirFlags departureDirections;
+};
+
+
+//! @brief The ConnRef class represents a connector object.
+//!
+//! Connectors are a (possible multi-segment) line between two points.
+//! They are routed intelligently so as not to overlap any of the shape
+//! objects in the Router scene.
+//!
+//! Routing penalties can be applied, resulting in more aesthetically pleasing
+//! connector paths with fewer segments or less severe bend-points.
+//!
+//! You can set a function to be called when the connector has been rerouted
+//! and needs to be redrawn. Alternatively, you can query the connector's
+//! needsRepaint() function to determine this manually.
+//!
+//! Usually, it is expected that you would create a ConnRef for each connector
+//! in your diagram and keep that reference in your own connector class.
+//!
+class AVOID_EXPORT ConnRef
+{
+ public:
+ //! @brief Constructs a connector with no endpoints specified.
+ //!
+ //! The constructor requires a valid Router instance. This router
+ //! will take ownership of the connector. Hence, you should not
+ //! call the destructor yourself, but should instead call
+ //! Router::deleteConnector() and the router instance will remove
+ //! and then free the connector's memory.
+ //!
+ //! @note Regarding IDs:
+ //! You can let libavoid manually handle IDs by not specifying
+ //! them. Alternatively, you can specify all IDs yourself, but
+ //! you must be careful to makes sure that each object in the
+ //! scene (shape, connector, cluster, etc) is given a unique,
+ //! positive ID. This uniqueness is checked if assertions are
+ //! enabled, but if not and there are clashes then strange
+ //! things can happen.
+ //!
+ //! @param[in] router The router scene to place the connector into.
+ //! @param[in] id Optionally, a positive integer ID unique
+ //! among all objects.
+ //!
+ ConnRef(Router *router, const unsigned int id = 0);
+ //! @brief Constructs a connector with endpoints specified.
+ //!
+ //! The constructor requires a valid Router instance. This router
+ //! will take ownership of the connector. Hence, you should not
+ //! call the destructor yourself, but should instead call
+ //! Router::deleteConnector() and the router instance will remove
+ //! and then free the connector's memory.
+ //!
+ //! If an ID is not specified, then one will be assigned to the shape.
+ //! If assigning an ID yourself, note that it should be a unique
+ //! positive integer. Also, IDs are given to all objects in a scene,
+ //! so the same ID cannot be given to a shape and a connector for
+ //! example.
+ //!
+ //! @param[in] router The router scene to place the connector into.
+ //! @param[in] id A unique positive integer ID for the connector.
+ //! @param[in] src The source endpoint of the connector.
+ //! @param[in] dst The destination endpoint of the connector.
+ //!
+ ConnRef(Router *router, const ConnEnd& src, const ConnEnd& dst,
+ const unsigned int id = 0);
+
+// To prevent C++ objects from being destroyed in garbage collected languages
+// when the libraries are called from SWIG, we hide the declarations of the
+// destructors and prevent generation of default destructors.
+#ifndef SWIG
+ //! @brief Connector reference destuctor.
+ //!
+ //! Do not call this yourself, instead call
+ //! Router::deleteConnector(). Ownership of this object
+ //! belongs to the router scene.
+ ~ConnRef();
+#endif
+ //! @brief Sets both a new source and destination endpoint for this
+ //! connector.
+ //!
+ //! If the router is using transactions, then this action will occur
+ //! the next time Router::processTransaction() is called. See
+ //! Router::setTransactionUse() for more information.
+ //!
+ //! @param[in] srcPoint New source endpoint for the connector.
+ //! @param[in] dstPoint New destination endpoint for the connector.
+ void setEndpoints(const ConnEnd& srcPoint, const ConnEnd& dstPoint);
+
+ //! @brief Sets just a new source endpoint for this connector.
+ //!
+ //! If the router is using transactions, then this action will occur
+ //! the next time Router::processTransaction() is called. See
+ //! Router::setTransactionUse() for more information.
+ //!
+ //! @param[in] srcPoint New source endpoint for the connector.
+ void setSourceEndpoint(const ConnEnd& srcPoint);
+
+ //! @brief Sets just a new destination endpoint for this connector.
+ //!
+ //! If the router is using transactions, then this action will occur
+ //! the next time Router::processTransaction() is called. See
+ //! Router::setTransactionUse() for more information.
+ //!
+ //! @param[in] dstPoint New destination endpoint for the connector.
+ void setDestEndpoint(const ConnEnd& dstPoint);
+
+ //! @brief Returns the ID of this connector.
+ //! @returns The ID of the connector.
+ unsigned int id(void) const;
+
+ //! @brief Returns a pointer to the router scene this connector is in.
+ //! @returns A pointer to the router scene for this connector.
+ Router *router(void) const;
+
+ //! @brief Returns an indication of whether this connector has a
+ //! new route and thus needs to be repainted.
+ //!
+ //! If the connector has been rerouted and need repainting, the
+ //! displayRoute() method can be called to get a reference to the
+ //! new route.
+ //!
+ //! @returns Returns true if the connector requires repainting, or
+ //! false if it does not.
+ bool needsRepaint(void) const;
+
+ //! @brief Returns a reference to the current raw "debug" route for
+ //! the connector.
+ //!
+ //! This is a raw "debug" shortest path version of the route, where
+ //! each line segment in the route may be made up of multiple collinear
+ //! line segments. It also has no post-processing (i.e., centering,
+ //! nudging apart of overlapping paths, or curving of corners) applied
+ //! to it. A route to display to the user can be obtained by calling
+ //! displayRoute().
+ //!
+ //! @returns The PolyLine route for the connector.
+ const PolyLine& route(void) const;
+
+ //! @brief Returns a reference to the current display version of the
+ //! route for the connector.
+ //!
+ //! The display version of a route has been simplified to collapse all
+ //! collinear line segments into single segments. It also has all
+ //! post-processing applied to the route, including centering, curved
+ //! corners and nudging apart of overlapping segments.
+ //!
+ //! @returns The PolyLine display route for the connector.
+ PolyLine& displayRoute(void);
+
+ //! @brief Sets a callback function that will called to indicate that
+ //! the connector needs rerouting.
+ //!
+ //! The cb function will be called when shapes are added to, removed
+ //! from or moved about on the page. The pointer ptr will be passed
+ //! as an argument to the callback function.
+ //!
+ //! @param[in] cb A pointer to the callback function.
+ //! @param[in] ptr A generic pointer that will be passed to the
+ //! callback function.
+ void setCallback(void (*cb)(void *), void *ptr);
+
+ //! @brief Returns the type of routing performed for this connector.
+ //! @return The type of routing performed.
+ //!
+ ConnType routingType(void) const;
+
+ //! @brief Sets the type of routing to be performed for this
+ //! connector.
+ //!
+ //! If a call to this method changes the current type of routing
+ //! being used for the connector, then it will get rerouted during
+ //! the next processTransaction() call, or immediately if
+ //! transactions are not being used.
+ //!
+ //! @param type The type of routing to be performed.
+ //!
+ void setRoutingType(ConnType type);
+
+ //! @brief Splits a connector in the centre of the segmentNth
+ //! segment and creates a junction point there as well
+ //! as a second connector.
+ //!
+ //! The new junction and connector will be automatically added to
+ //! the router scene. A slight preference will be given to the
+ //! connectors connecting to the junction in the same orientation
+ //! the line segment already existed in.
+ //!
+ //! @return A pair containing pointers to the new JunctionRef and
+ //! ConnRef.
+ std::pair<JunctionRef *, ConnRef *> splitAtSegment(
+ const size_t segmentN);
+
+ //! @brief Allows the user to specify a set of checkpoints that this
+ //! connector will route via.
+ //!
+ //! When routing, the connector will attempt to visit each of the
+ //! points in the checkpoints list in order. It will route from the
+ //! source point to the first checkpoint, to the second checkpoint,
+ //! etc. If a checkpoint is unreachable because it lies inside an
+ //! obstacle, then that checkpoint will be skipped.
+ //!
+ //! @param[in] checkpoints An ordered list of Checkpoints that the
+ //! connector will attempt to route via.
+ void setRoutingCheckpoints(const std::vector<Checkpoint>& checkpoints);
+
+ //! @brief Returns the current set of routing checkpoints for this
+ //! connector.
+ //! @returns The ordered list of Checkpoints that this connector will
+ //! route via.
+ std::vector<Checkpoint> routingCheckpoints(void) const;
+
+ //! @brief Returns ConnEnds specifying what this connector is
+ //! attached to.
+ //!
+ //! This may be useful during hyperedge rerouting. You can check the
+ //! type and properties of the ConnEnd objects to find out what this
+ //! connector is attached to. The ConnEnd::type() will be ConnEndEmpty
+ //! if the connector has not had its endpoints initialised.
+ //!
+ //! @note If the router is using transactions, you might get
+ //! unexpected results if you call this after changing objects
+ //! but before calling Router::processTransaction(). In this
+ //! case changes to ConnEnds for the connector may be queued
+ //! and not yet applied, so you will get old (or empty) values.
+ //!
+ //! @returns A pair of ConnEnd objects specifying what the connector
+ //! is attached to.
+ //!
+ std::pair<ConnEnd, ConnEnd> endpointConnEnds(void) const;
+
+ // @brief Returns the source endpoint vertex in the visibility graph.
+ // @returns The source endpoint vertex.
+ VertInf *src(void) const;
+ // @brief Returns the destination endpoint vertex in the
+ // visibility graph.
+ // @returns The destination endpoint vertex.
+ VertInf *dst(void) const;
+
+ //! @brief Sets a fixed user-specified route for this connector.
+ //!
+ //! libavoid will no longer calculate object-avoiding paths for this
+ //! connector but instead just return the specified route. The path
+ //! of this connector will still be considered for the purpose of
+ //! nudging and routing other non-fixed connectors.
+ //!
+ //! @note This will reset the endpoints of the connector to the two
+ //! ends of the given route, which may cause it to become
+ //! dettached from any shapes or junctions. You can
+ //! alternatively call setFixedExistingRoute() for connectors
+ //! with valid routes in hyperedges that you would like to
+ //! remain attached.
+ //!
+ //! @param[in] route The new fixed route for the connector.
+ //! @sa setFixedExistingRoute()
+ //! @sa clearFixedRoute()
+ //!
+ void setFixedRoute(const PolyLine& route);
+
+ //! @brief Sets a fixed existing route for this connector.
+ //!
+ //! libavoid will no longer calculate object-avoiding paths for this
+ //! connector but instead just return the current exisitng route.
+ //! The path of this connector will still be considered for the
+ //! purpose of nudging and routing other non-fixed connectors.
+ //!
+ //! @note The endpoints of this connector will remain at their current
+ //! positions, even while remaining 'attached' to shapes
+ //! or junctions that move.
+ //!
+ //! @sa setFixedRoute()
+ //! @sa clearFixedRoute()
+ //!
+ void setFixedExistingRoute(void);
+
+ //! @brief Returns whether the connector route is marked as fixed.
+ //!
+ //! @return True if the connector route is fixed, false otherwise.
+ //!
+ bool hasFixedRoute(void) const;
+
+ //! @brief Returns the connector to being automatically routed if it
+ //! was marked as fixed.
+ //!
+ //! @sa setFixedRoute()
+ //!
+ void clearFixedRoute(void);
+
+ void set_route(const PolyLine& route);
+ void calcRouteDist(void);
+ void makeActive(void);
+ void makeInactive(void);
+ VertInf *start(void);
+ void removeFromGraph(void);
+ bool isInitialised(void) const;
+ void makePathInvalid(void);
+ void setHateCrossings(bool value);
+ bool doesHateCrossings(void) const;
+ void setEndpoint(const unsigned int type, const ConnEnd& connEnd);
+ bool setEndpoint(const unsigned int type, const VertID& pointID,
+ Point *pointSuggestion = nullptr);
+ std::vector<Point> possibleDstPinPoints(void) const;
+
+ private:
+ friend class Router;
+ friend class ConnEnd;
+ friend class JunctionRef;
+ friend class ConnRerouteFlagDelegate;
+ friend class HyperedgeImprover;
+ friend struct HyperedgeTreeEdge;
+ friend struct HyperedgeTreeNode;
+ friend class HyperedgeRerouter;
+
+ PolyLine& routeRef(void);
+ void freeRoutes(void);
+ void performCallback(void);
+ bool generatePath(void);
+ void generateCheckpointsPath(std::vector<Point>& path,
+ std::vector<VertInf *>& vertices);
+ void generateStandardPath(std::vector<Point>& path,
+ std::vector<VertInf *>& vertices);
+ void unInitialise(void);
+ void updateEndPoint(const unsigned int type, const ConnEnd& connEnd);
+ void common_updateEndPoint(const unsigned int type, ConnEnd connEnd);
+ void freeActivePins(void);
+ bool getConnEndForEndpointVertex(VertInf *vertex, ConnEnd& connEnd)
+ const;
+ std::pair<Obstacle *, Obstacle *> endpointAnchors(void) const;
+ void outputCode(FILE *fp) const;
+ std::pair<bool, bool> assignConnectionPinVisibility(const bool connect);
+
+
+ Router *m_router;
+ unsigned int m_id;
+ ConnType m_type;
+ bool *m_reroute_flag_ptr;
+ bool m_needs_reroute_flag:1;
+ bool m_false_path:1;
+ bool m_needs_repaint:1;
+ bool m_active:1;
+ bool m_initialised:1;
+ bool m_hate_crossings:1;
+ bool m_has_fixed_route:1;
+ PolyLine m_route;
+ Polygon m_display_route;
+ double m_route_dist;
+ ConnRefList::iterator m_connrefs_pos;
+ VertInf *m_src_vert;
+ VertInf *m_dst_vert;
+ VertInf *m_start_vert;
+ void (*m_callback_func)(void *);
+ void *m_connector;
+ ConnEnd *m_src_connend;
+ ConnEnd *m_dst_connend;
+ std::vector<Checkpoint> m_checkpoints;
+ std::vector<VertInf *> m_checkpoint_vertices;
+};
+
+
+typedef std::pair<Point *, ConnRef *> PtConnPtrPair;
+
+typedef std::vector< PtConnPtrPair > PointRepVector;
+typedef std::list<std::pair<size_t, size_t> > NodeIndexPairLinkList;
+
+class PtOrder
+{
+ public:
+ PtOrder();
+ ~PtOrder();
+ void addPoints(const size_t dim, const PtConnPtrPair& arg1,
+ const PtConnPtrPair& arg2);
+ void addOrderedPoints(const size_t dim, const PtConnPtrPair& innerArg,
+ const PtConnPtrPair& outerArg, bool swapped);
+ int positionFor(const size_t dim, const ConnRef *conn);
+ PointRepVector sortedPoints(const size_t dim);
+ private:
+ size_t insertPoint(const size_t dim, const PtConnPtrPair& point);
+ void sort(const size_t dim);
+
+ // One for each dimension.
+ bool sorted[2];
+ PointRepVector nodes[2];
+ NodeIndexPairLinkList links[2];
+ PointRepVector sortedConnVector[2];
+};
+
+typedef std::map<Avoid::Point,PtOrder> PtOrderMap;
+typedef std::set<Avoid::Point> PointSet;
+
+
+const unsigned int CROSSING_NONE = 0;
+const unsigned int CROSSING_TOUCHES = 1;
+const unsigned int CROSSING_SHARES_PATH = 2;
+const unsigned int CROSSING_SHARES_PATH_AT_END = 4;
+const unsigned int CROSSING_SHARES_FIXED_SEGMENT = 8;
+
+
+typedef std::pair<int, unsigned int> CrossingsInfoPair;
+typedef std::vector<Avoid::Point> PointList;
+typedef std::vector<PointList> SharedPathList;
+
+class ConnectorCrossings
+{
+ public:
+ ConnectorCrossings(Avoid::Polygon& poly, bool polyIsConn,
+ Avoid::Polygon& conn, ConnRef *polyConnRef = nullptr,
+ ConnRef *connConnRef = nullptr);
+ void clear(void);
+ void countForSegment(size_t cIndex, const bool finalSegment);
+
+ Avoid::Polygon& poly;
+ bool polyIsConn;
+ Avoid::Polygon& conn;
+ bool checkForBranchingSegments;
+ ConnRef *polyConnRef;
+ ConnRef *connConnRef;
+
+ unsigned int crossingCount;
+ unsigned int crossingFlags;
+ PointSet *crossingPoints;
+ PtOrderMap *pointOrders;
+ SharedPathList *sharedPaths;
+
+ double firstSharedPathAtEndLength;
+ double secondSharedPathAtEndLength;
+};
+
+extern void splitBranchingSegments(Avoid::Polygon& poly, bool polyIsConn,
+ Avoid::Polygon& conn, const double tolerance = 0);
+extern bool validateBendPoint(VertInf *aInf, VertInf *bInf, VertInf *cInf);
+
+}
+
+
+#endif
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/connend.cpp b/src/3rdparty/adaptagrams/libavoid/connend.cpp
new file mode 100644
index 0000000..7a5f6c1
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/connend.cpp
@@ -0,0 +1,435 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2009 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+#include <cstring>
+#include <cmath>
+#include <cstdlib>
+#include <cfloat>
+#include <algorithm>
+
+#include "libavoid/router.h"
+#include "libavoid/connend.h"
+#include "libavoid/connector.h"
+#include "libavoid/connectionpin.h"
+#include "libavoid/junction.h"
+#include "libavoid/shape.h"
+#include "libavoid/debug.h"
+#include "libavoid/graph.h"
+#include "libavoid/visibility.h"
+
+namespace Avoid {
+
+
+ConnEnd::ConnEnd()
+ : m_type(ConnEndEmpty),
+ m_point(Point(0,0)),
+ m_directions(ConnDirAll),
+ m_connection_pin_class_id(CONNECTIONPIN_UNSET),
+ m_anchor_obj(nullptr),
+ m_conn_ref(nullptr),
+ m_active_pin(nullptr)
+{
+}
+
+ConnEnd::ConnEnd(const Point& point)
+ : m_type(ConnEndPoint),
+ m_point(point),
+ m_directions(ConnDirAll),
+ m_connection_pin_class_id(CONNECTIONPIN_UNSET),
+ m_anchor_obj(nullptr),
+ m_conn_ref(nullptr),
+ m_active_pin(nullptr)
+{
+}
+
+
+ConnEnd::ConnEnd(const Point& point, const ConnDirFlags visDirs)
+ : m_type(ConnEndPoint),
+ m_point(point),
+ m_directions(visDirs),
+ m_connection_pin_class_id(CONNECTIONPIN_UNSET),
+ m_anchor_obj(nullptr),
+ m_conn_ref(nullptr),
+ m_active_pin(nullptr)
+{
+}
+
+
+ConnEnd::ConnEnd(ShapeRef *shapeRef, const unsigned int connectionPinClassID)
+ : m_type(ConnEndShapePin),
+ m_point(Point(0,0)),
+ m_directions(ConnDirAll),
+ m_connection_pin_class_id(connectionPinClassID),
+ m_anchor_obj(shapeRef),
+ m_conn_ref(nullptr),
+ m_active_pin(nullptr)
+{
+ COLA_ASSERT(m_anchor_obj != nullptr);
+ COLA_ASSERT(m_connection_pin_class_id > 0);
+
+ m_point = m_anchor_obj->position();
+ COLA_ASSERT(m_connection_pin_class_id != CONNECTIONPIN_UNSET);
+}
+
+
+ConnEnd::ConnEnd(JunctionRef *junctionRef)
+ : m_type(ConnEndJunction),
+ m_directions(ConnDirAll),
+ m_connection_pin_class_id(CONNECTIONPIN_CENTRE),
+ m_anchor_obj(junctionRef),
+ m_conn_ref(nullptr),
+ m_active_pin(nullptr)
+{
+ COLA_ASSERT(m_anchor_obj != nullptr);
+ m_point = m_anchor_obj->position();
+}
+
+
+ConnEnd::~ConnEnd()
+{
+}
+
+
+ConnEndType ConnEnd::type(void) const
+{
+ return m_type;
+}
+
+
+const Point ConnEnd::position(void) const
+{
+ if (m_active_pin) // Attached to a pin!
+ {
+ return m_active_pin->position();
+ }
+ else if (m_anchor_obj)
+ {
+ return m_anchor_obj->position();
+ }
+ else
+ {
+ return m_point;
+ }
+}
+
+
+ConnDirFlags ConnEnd::directions(void) const
+{
+ if (m_active_pin) // Attached to a pin!
+ {
+ return m_active_pin->directions();
+ }
+ else
+ {
+ return m_directions;
+ }
+}
+
+
+ShapeRef *ConnEnd::shape(void) const
+{
+ return dynamic_cast<ShapeRef *> (m_anchor_obj);
+}
+
+
+JunctionRef *ConnEnd::junction(void) const
+{
+ return dynamic_cast<JunctionRef *> (m_anchor_obj);
+}
+
+
+unsigned int ConnEnd::pinClassId(void) const
+{
+ return m_connection_pin_class_id;
+}
+
+
+
+bool ConnEnd::isPinConnection(void) const
+{
+ return (m_type == ConnEndShapePin) || (m_type == ConnEndJunction);
+}
+
+unsigned int ConnEnd::endpointType(void) const
+{
+ COLA_ASSERT(m_conn_ref != nullptr);
+ return (m_conn_ref->m_dst_connend == this) ? VertID::tar : VertID::src;
+}
+
+
+// Marks this ConnEnd as using a particular ShapeConnectionPin.
+void ConnEnd::usePin(ShapeConnectionPin *pin)
+{
+ COLA_ASSERT(m_active_pin == nullptr);
+
+ m_active_pin = pin;
+ if (m_active_pin)
+ {
+ m_active_pin->m_connend_users.insert(this);
+ }
+}
+
+
+// Marks this ConnEnd as using a particular ShapeConnectionPin's vertex.
+void ConnEnd::usePinVertex(VertInf *pinVert)
+{
+ COLA_ASSERT(m_active_pin == nullptr);
+
+ for (ShapeConnectionPinSet::iterator curr =
+ m_anchor_obj->m_connection_pins.begin();
+ curr != m_anchor_obj->m_connection_pins.end(); ++curr)
+ {
+ ShapeConnectionPin *currPin = *curr;
+ if (currPin->m_vertex == pinVert)
+ {
+ usePin(currPin);
+ break;
+ }
+ }
+}
+
+
+// Returns a vector of the possible Points for this ConnEnd
+std::vector<Point> ConnEnd::possiblePinPoints(void) const
+{
+ std::vector<Point> points;
+ if (!m_anchor_obj || (m_connection_pin_class_id == CONNECTIONPIN_UNSET))
+ {
+ return points;
+ }
+
+ return m_anchor_obj->possiblePinPoints(m_connection_pin_class_id);
+}
+
+// Marks this ConnEnd as no longer using the active ShapeConnectionPin
+void ConnEnd::freeActivePin(void)
+{
+ if (m_active_pin)
+ {
+ m_active_pin->m_connend_users.erase(this);
+ }
+ m_active_pin = nullptr;
+}
+
+
+// Creates the connection between a connector and a shape/junction.
+void ConnEnd::connect(ConnRef *conn)
+{
+ COLA_ASSERT(isPinConnection());
+ COLA_ASSERT(m_anchor_obj);
+ COLA_ASSERT(m_conn_ref == nullptr);
+
+ m_anchor_obj->addFollowingConnEnd(this);
+ m_conn_ref = conn;
+}
+
+
+// Removes the connection between a connector and a shape/junction.
+void ConnEnd::disconnect(const bool shapeDeleted)
+{
+ if (m_conn_ref == nullptr)
+ {
+ // Not connected.
+ return;
+ }
+
+ m_point = position();
+ m_anchor_obj->removeFollowingConnEnd(this);
+ m_conn_ref = nullptr;
+
+ if (shapeDeleted)
+ {
+ // Turn this into a manual ConnEnd.
+ m_point = position();
+ m_anchor_obj = nullptr;
+ m_type = ConnEndPoint;
+ m_connection_pin_class_id = CONNECTIONPIN_UNSET;
+ }
+}
+
+
+// Assign visibility to a dummy vertex representing all the possible pins
+// for this pinClassId.
+void ConnEnd::assignPinVisibilityTo(VertInf *dummyConnectionVert,
+ VertInf *targetVert)
+{
+ unsigned int validPinCount = 0;
+
+ COLA_ASSERT(m_anchor_obj);
+ COLA_ASSERT(m_connection_pin_class_id != CONNECTIONPIN_UNSET);
+
+ Router *router = m_anchor_obj->router();
+ for (ShapeConnectionPinSet::iterator curr =
+ m_anchor_obj->m_connection_pins.begin();
+ curr != m_anchor_obj->m_connection_pins.end(); ++curr)
+ {
+ ShapeConnectionPin *currPin = *curr;
+ if ((currPin->m_class_id == m_connection_pin_class_id) &&
+ (!currPin->m_exclusive || currPin->m_connend_users.empty()))
+ {
+ double routingCost = currPin->m_connection_cost;
+ Point adjTargetPt = targetVert->point - currPin->m_vertex->point;
+ double angle = rotationalAngle(adjTargetPt);
+ bool inVisibilityRange = false;
+
+ if (angle <= 45 || angle >= 315)
+ {
+ if (currPin->directions() & ConnDirRight)
+ {
+ inVisibilityRange = true;
+ }
+ }
+ if (angle >= 45 && angle <= 135)
+ {
+ if (currPin->directions() & ConnDirDown)
+ {
+ inVisibilityRange = true;
+ }
+ }
+ if (angle >= 135 && angle <= 225)
+ {
+ if (currPin->directions() & ConnDirLeft)
+ {
+ inVisibilityRange = true;
+ }
+ }
+ if (angle >= 225 && angle <= 315)
+ {
+ if (currPin->directions() & ConnDirUp)
+ {
+ inVisibilityRange = true;
+ }
+ }
+ if (!inVisibilityRange)
+ {
+ routingCost += router->routingParameter(portDirectionPenalty);
+ }
+
+ if (router->m_allows_orthogonal_routing)
+ {
+ // This has same ID and is either unconnected or not
+ // exclusive, so give it visibility.
+ EdgeInf *edge = new EdgeInf(dummyConnectionVert,
+ currPin->m_vertex, true);
+ // XXX Can't use a zero cost due to assumptions
+ // elsewhere in code.
+ edge->setDist(manhattanDist(dummyConnectionVert->point,
+ currPin->m_vertex->point) +
+ std::max(0.001, routingCost));
+ }
+
+ if (router->m_allows_polyline_routing)
+ {
+ // This has same ID and is either unconnected or not
+ // exclusive, so give it visibility.
+ EdgeInf *edge = new EdgeInf(dummyConnectionVert,
+ currPin->m_vertex, false);
+ // XXX Can't use a zero cost due to assumptions
+ // elsewhere in code.
+ edge->setDist(euclideanDist(dummyConnectionVert->point,
+ currPin->m_vertex->point) +
+ std::max(0.001, routingCost));
+ }
+
+ // Increment the number of valid pins for this ConnEnd connection.
+ validPinCount++;
+ }
+ }
+
+ if (validPinCount == 0)
+ {
+ // There should be at least one pin, otherwise we will have
+ // problems finding connector routes.
+ err_printf("Warning: In ConnEnd::assignPinVisibilityTo():\n"
+ " ConnEnd for connector %d can't connect to shape %d\n"
+ " since it has no pins with class id of %u.\n",
+ (int) m_conn_ref->id(), (int) m_anchor_obj->id(),
+ m_connection_pin_class_id);
+ }
+}
+
+
+std::pair<bool, VertInf *> ConnEnd::getHyperedgeVertex(Router *router) const
+{
+ bool addedVertex = false;
+ VertInf *vertex = nullptr;
+
+ if (m_anchor_obj)
+ {
+ for (ShapeConnectionPinSet::iterator curr =
+ m_anchor_obj->m_connection_pins.begin();
+ curr != m_anchor_obj->m_connection_pins.end(); ++curr)
+ {
+ ShapeConnectionPin *currPin = *curr;
+ if ((currPin->m_class_id == m_connection_pin_class_id) &&
+ (!currPin->m_exclusive || currPin->m_connend_users.empty()))
+ {
+ vertex = currPin->m_vertex;
+ }
+ }
+ COLA_ASSERT(vertex != nullptr);
+ }
+ else
+ {
+ VertID id(0, kUnassignedVertexNumber,
+ VertID::PROP_ConnPoint);
+ vertex = new VertInf(router, id, m_point);
+ vertex->visDirections = m_directions;
+ addedVertex = true;
+
+ if (router->m_allows_polyline_routing)
+ {
+ vertexVisibility(vertex, nullptr, true, true);
+ }
+ }
+
+ return std::make_pair(addedVertex, vertex);
+}
+
+
+void ConnEnd::outputCode(FILE *fp, const char *srcDst) const
+{
+ if (junction())
+ {
+ fprintf(fp, " %sPt = ConnEnd(junctionRef%u);\n", srcDst,
+ m_anchor_obj->id());
+ }
+ else if (shape())
+ {
+ fprintf(fp, " %sPt = ConnEnd(shapeRef%u, %u);\n", srcDst,
+ m_anchor_obj->id(), m_connection_pin_class_id);
+ }
+ else
+ {
+ fprintf(fp, " %sPt = ConnEnd(Point(%" PREC "g, %" PREC "g), (ConnDirFlags) %u);\n",
+ srcDst, m_point.x, m_point.y, m_directions);
+ }
+}
+
+
+//============================================================================
+
+}
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/connend.h b/src/3rdparty/adaptagrams/libavoid/connend.h
new file mode 100644
index 0000000..74f8cbc
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/connend.h
@@ -0,0 +1,267 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+//! @file connend.h
+//! @brief Contains the interface for the ConnEnd class.
+
+
+#ifndef AVOID_CONNEND_H
+#define AVOID_CONNEND_H
+
+
+#include <cstdio>
+#include <list>
+#include <vector>
+#include <utility>
+
+#include "libavoid/dllexport.h"
+#include "libavoid/geometry.h"
+
+
+namespace Avoid {
+
+class Obstacle;
+class ShapeRef;
+class JunctionRef;
+class Router;
+class ConnRef;
+class ShapeConnectionPin;
+typedef std::list<ConnRef *> ConnRefList;
+class VertInf;
+
+
+//! @brief Flags that can be passed to the ConnEnd constructor to specify
+//! which sides of a shape this point should have visibility to if
+//! it is located within the shape's area.
+//!
+//! Like SVG, libavoid considers the Y-axis to point downwards, that is,
+//! like screen coordinates the coordinates increase from left-to-right and
+//! also from top-to-bottom.
+//!
+enum ConnDirFlag {
+ ConnDirNone = 0,
+ //! @brief This option specifies the point should be given visibility
+ //! to the top of the shape that it is located within.
+ ConnDirUp = 1,
+ //! @brief This option specifies the point should be given visibility
+ //! to the bottom of the shape that it is located within.
+ ConnDirDown = 2,
+ //! @brief This option specifies the point should be given visibility
+ //! to the left side of the shape that it is located within.
+ ConnDirLeft = 4,
+ //! @brief This option specifies the point should be given visibility
+ //! to the right side of the shape that it is located within.
+ ConnDirRight = 8,
+ //! @brief This option, provided for convenience, specifies the point
+ //! should be given visibility to all four sides of the shape
+ //! that it is located within.
+ ConnDirAll = 15
+};
+//! @brief One or more Avoid::ConnDirFlag options.
+//!
+typedef unsigned int ConnDirFlags;
+
+
+//! @brief Types that describe the kind a connection that a ConnEnd
+//! represents.
+//!
+enum ConnEndType {
+ //! @brief The ConnEnd represents a free-floating point that may or may
+ //! not have visibility in specific directions.
+ ConnEndPoint,
+ //! @brief The ConnEnd attaches to a specific ShapeConnectionPin on a
+ //! shape.
+ ConnEndShapePin,
+ //! @brief The ConnEnd attaches to a junction.
+ ConnEndJunction,
+ //! @brief The ConnEnd is empty and doesn't have any information set.
+ ConnEndEmpty
+};
+
+
+//! @brief The ConnEnd class represents different possible endpoints for
+//! connectors.
+//!
+//! ConnEnds may be free-floating points, points attached to junctions (between
+//! multiple connectors), or points attached to shapes (either to the centre of
+//! the shape or to particular pin positions on the shape).
+//!
+class AVOID_EXPORT ConnEnd
+{
+ public:
+ //! @brief Constructs a ConnEnd from a free-floating point.
+ //!
+ //! @param[in] point The position of the connector endpoint.
+ //!
+ ConnEnd(const Point& point);
+
+ //! @brief Constructs a ConnEnd from a free-floating point as well
+ //! as a set of flags specifying visibility for this point
+ //! if it is located inside a shape.
+ //!
+ //! @param[in] point The position of the connector endpoint.
+ //! @param[in] visDirs One or more Avoid::ConnDirFlag options
+ //! specifying the directions that this point
+ //! should be given visibility if it is inside
+ //! a shape. Currently has no effect if outside
+ //! of shapes.
+ //!
+ ConnEnd(const Point& point, const ConnDirFlags visDirs);
+
+ //! @brief Constructs a ConnEnd attached to one of a particular set of
+ //! connection pins on a shape.
+ //!
+ //! This is the recommended method for connecting to shapes that may
+ //! later be moved or resized and for which you don't want to track
+ //! and specify the connector endpoints yourself. See the
+ //! ShapeConnectionPin documentation for more information.
+ //!
+ //! If you to just connect to the centre of a shape you should just
+ //! create a centre connection pin
+ //! @code
+ //! const unsigned int CENTRE = 1;
+ //! new Avoid::ShapeConnectionPin(shapeRef, CENTRE, Avoid::ATTACH_POS_CENTRE, Avoid::ATTACH_POS_CENTRE);
+ //! @endcode
+ //! and attach to that with
+ //! @code
+ //! ConnEnd(shapeRef, CENTRE);
+ //! @endcode
+ //!
+ //! If a pin with the specified pin class ID doesn't exist then you
+ //! will get a warning and a straight-line path between the source
+ //! and destination endpoints of the connector will be returned
+ //! during routing.
+ //!
+ //! @param[in] shapeRef A pointer to the containing shape's
+ //! ShapeRef.
+ //! @param[in] connectionPinClassID A non-zero integer denoting the
+ //! class ID for the set of pins to
+ //! connect to.
+ //!
+ ConnEnd(ShapeRef *shapeRef, const unsigned int connectionPinClassID);
+
+ //! @brief Constructs a ConnEnd attached to one of the connection
+ //! pins on a junction.
+ //!
+ //! This is the recommended method for connecting to junctions that
+ //! may later be moved. See the ShapeConnectionPin documentation for
+ //! more information.
+ //!
+ //! @param[in] junctionRef A pointer to the containing
+ //! junction's junctionRef.
+ //!
+ ConnEnd(JunctionRef *junctionRef);
+
+
+ //! @brief Returns the kind of connection this ConnEnd represents.
+ //!
+ //! @return The ConnEndType represented by this ConnEnd.
+ //!
+ ConnEndType type(void) const;
+
+ //! @brief Returns the position of this connector endpoint.
+ //!
+ //! @return The position of this connector endpoint.
+ //!
+ const Point position(void) const;
+
+ //! @brief Returns the directions in which this connector endpoint
+ //! should be given visibility.
+ //!
+ //! @return The visibility directions for this connector endpoint.
+ //!
+ ConnDirFlags directions(void) const;
+
+ //! @brief Returns the shape this ConnEnd attaches to, or nullptr.
+ //!
+ //! Will be valid only if type() == ConnEndShapePin.
+ //!
+ //! @return The ShapeRef pointer that the ConnEnd attaches to, or nullptr.
+ //!
+ ShapeRef *shape(void) const;
+
+ //! @brief Returns the junction this ConnEnd attaches to, or nullptr.
+ //!
+ //! Will be valid only if type() == ConnEndJunction.
+ //!
+ //! @return The JunctionRef pointer that the ConnEnd attaches to,
+ //! or nullptr.
+ //!
+ JunctionRef *junction(void) const;
+
+ //! @brief Returns the pin class ID for a ConnEnd attached to a shape.
+ //!
+ //! Will be valid only if type() == ConnEndShapePin.
+ //!
+ //! @return An unsigned int representing the pin class ID for the
+ //! ConnEnd.
+ //!
+ unsigned int pinClassId(void) const;
+
+ ConnEnd();
+ ~ConnEnd();
+ private:
+ friend class Obstacle;
+ friend class JunctionRef;
+ friend class ShapeRef;
+ friend class ConnRef;
+ friend class Router;
+ friend class HyperedgeRerouter;
+ friend class ShapeConnectionPin;
+ friend class HyperedgeImprover;
+ friend class CrossingConnectorsInfo;
+
+ void connect(ConnRef *conn);
+ void disconnect(const bool shapeDeleted = false);
+ void usePin(ShapeConnectionPin *pin);
+ void usePinVertex(VertInf *pinVert);
+ void freeActivePin(void);
+ unsigned int endpointType(void) const;
+ bool isPinConnection(void) const;
+ std::vector<Point> possiblePinPoints(void) const;
+ void assignPinVisibilityTo(VertInf *dummyConnectionVert,
+ VertInf *targetVert);
+ void outputCode(FILE *fp, const char *srcDst) const;
+ std::pair<bool, VertInf *> getHyperedgeVertex(Router *router) const;
+
+ ConnEndType m_type;
+ Point m_point;
+ ConnDirFlags m_directions;
+ unsigned int m_connection_pin_class_id;
+
+ // For referencing ConnEnds
+ Obstacle *m_anchor_obj; // The shape/junction this is attached to.
+ ConnRef *m_conn_ref; // The parent connector.
+
+ // The pin to which the ConnEnd is attached.
+ ShapeConnectionPin *m_active_pin;
+};
+
+
+}
+
+
+#endif
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/debug.h b/src/3rdparty/adaptagrams/libavoid/debug.h
new file mode 100644
index 0000000..5f73dcf
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/debug.h
@@ -0,0 +1,100 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+
+#ifndef AVOID_DEBUG_H
+#define AVOID_DEBUG_H
+
+
+#if defined(_MSC_VER) && defined(USE_ATLTRACE)
+ // Using Microsoft Visual C++ compiler and we want to use ATLTRACE
+ // to send warnings and error messages to a GUI window.
+
+ // Prevent inclusion of min and max macros.
+ #define NOMINMAX
+
+ #include <afx.h>
+#endif
+
+#include <cstdarg>
+#include <cstdio>
+#include <iostream>
+
+
+namespace Avoid {
+
+// db_printf is debugging output for verifying behaviour of the router:
+#ifdef LIBAVOID_DEBUG
+
+ #if defined(_MSC_VER) && defined(USE_ATLTRACE)
+ #define db_printf ATL::AtlTrace
+ #else
+ inline void db_printf(const char *fmt, ...)
+ {
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(stdout, fmt, ap);
+ va_end(ap);
+ }
+ #endif
+
+#else
+
+ inline void db_printf(const char *, ...)
+ {
+ }
+
+#endif
+
+// err_printf are critical errors that mean something pretty bad has happened:
+#if defined(_MSC_VER) && defined(USE_ATLTRACE)
+
+ #define err_printf ATL::AtlTrace
+
+#else
+
+ // For other environments we always show these errors.
+ inline void err_printf(const char *fmt, ...)
+ {
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ }
+
+#endif
+
+}
+
+// Precision of numbers in libavoid SVG debug file. Used in printf
+// strings ("%" PREC "g"), e.g., "%.16g"
+#if defined(HIGH_PRECISION_DEBUG)
+ #define PREC ".16"
+#else
+ #define PREC ""
+#endif
+
+#endif
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/debughandler.h b/src/3rdparty/adaptagrams/libavoid/debughandler.h
new file mode 100644
index 0000000..52d803c
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/debughandler.h
@@ -0,0 +1,138 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+// @file debughandler.h
+// @brief Contains the interface for the DebugHandler class.
+
+#ifndef AVOID_DEBUGHANDLER_H
+#define AVOID_DEBUGHANDLER_H
+
+#include "libavoid/assertions.h"
+#include "libavoid/dllexport.h"
+
+// Add -DDEBUGHANDLER to compile in debug handler with optimisations enabled.
+#ifndef NDEBUG
+ #define DEBUGHANDLER
+#endif
+
+namespace Avoid {
+
+// @brief You can subclass DebugHandler and register an instance with Router
+// to recieve debugging information.
+//
+// @note This is currently intended for internal use.
+//
+class AVOID_EXPORT DebugHandler
+{
+ public:
+ DebugHandler()
+ {
+ }
+
+ virtual ~DebugHandler()
+ {
+ }
+
+ // @brief The obstacles being routed around.
+ //
+ virtual void updateObstacleBoxes(std::vector<Avoid::Box> obstacles)
+ {
+ COLA_UNUSED(obstacles);
+ }
+
+ // @brief An updated connector route. Optionally the ends of a just
+ // updated segment within the route between the indexes index1
+ // and index2.
+ //
+ virtual void updateConnectorRoute(ConnRef *conn, int index1, int index2)
+ {
+ COLA_UNUSED(conn);
+ COLA_UNUSED(index1);
+ COLA_UNUSED(index2);
+ }
+
+ // @brief The current endpoints that a path is being searched for
+ // between src and tar
+ //
+ virtual void beginningSearchWithEndpoints(VertInf *src, VertInf *tar)
+ {
+ COLA_UNUSED(src);
+ COLA_UNUSED(tar);
+ }
+
+ // @brief The current search path.
+ //
+ virtual void updateCurrentSearchPath(Avoid::PolyLine currentPath)
+ {
+ COLA_UNUSED(currentPath);
+ }
+
+ // @brief The current hyperedge endpoints for hyperedge rerouting
+ //
+ virtual void beginningHyperedgeReroutingWithEndpoints(std::set<VertInf *> endpoints)
+ {
+ COLA_UNUSED(endpoints);
+ }
+
+
+ // @brief The Minimum Terminal Spanning Tree for hyperedge rerouting
+ // is being grown with the edge between vertices u and v.
+ //
+ // @param shouldWait Boolean indicating the forest is being grown
+ // with this edge, or otherwise being immediately
+ // repopulated after pruning.
+ //
+ virtual void mtstGrowForestWithEdge(Avoid::VertInf *u, Avoid::VertInf *v, bool shouldWait)
+ {
+ COLA_UNUSED(u);
+ COLA_UNUSED(v);
+ COLA_UNUSED(shouldWait);
+ }
+
+ // @brief The Minimum Terminal Spanning Tree for hyperedge rerouting
+ // is potentiall bridged by the edge between vertices u and v.
+ //
+ virtual void mtstPotentialBridgingEdge(Avoid::VertInf *u, Avoid::VertInf *v)
+ {
+ COLA_UNUSED(u);
+ COLA_UNUSED(v);
+ }
+
+ // @brief The Minimum Terminal Spanning Tree for hyperedge rerouting
+ // is being finalised with the edge between vertices u and v.
+ //
+ // @param isBridge Boolean indicating whether edge was a bridge.
+ //
+ virtual void mtstCommitToEdge(Avoid::VertInf *u, Avoid::VertInf *v, bool isBridge)
+ {
+ COLA_UNUSED(u);
+ COLA_UNUSED(v);
+ COLA_UNUSED(isBridge);
+ }
+};
+
+
+}
+
+#endif
diff --git a/src/3rdparty/adaptagrams/libavoid/dllexport.h b/src/3rdparty/adaptagrams/libavoid/dllexport.h
new file mode 100644
index 0000000..d8c63d6
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/dllexport.h
@@ -0,0 +1,39 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2012 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+
+#ifndef AVOID_DLLEXPORT_H
+#define AVOID_DLLEXPORT_H
+
+#if defined(_MSC_VER) && !defined(LIBAVOID_NO_DLL)
+ #ifdef LIBAVOID_EXPORTS
+ #define AVOID_EXPORT __declspec(dllexport)
+ #else
+ #define AVOID_EXPORT __declspec(dllimport)
+ #endif
+#else
+ #define AVOID_EXPORT
+#endif
+
+#endif
diff --git a/src/3rdparty/adaptagrams/libavoid/doc/description.doc b/src/3rdparty/adaptagrams/libavoid/doc/description.doc
new file mode 100644
index 0000000..8a3655f
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/doc/description.doc
@@ -0,0 +1,73 @@
+/*!
+
+\if LIBAVOID_DOC
+@mainpage libavoid: Object-avoiding orthogonal and polyline connector routing library
+\endif
+
+\if ADAPTAGRAMS_DOC
+@page libavoid libavoid &mdash; Overview
+\endif
+
+libavoid is a cross-platform C++ library providing fast, object-avoiding
+orthogonal and polyline connector routing for use in interactive diagram
+editors.
+
+libavoid is part of the
+<a href="http://www.adaptagrams.org/">Adaptagrams project</a>.
+There are no official releases yet, though the code is stable and
+available from the Adaptagrams
+<a href="https://github.com/mjwybrow/adaptagrams">GitHub
+repository</a>.
+
+The API is documented using Doxygen. The documentation you are currently
+reading can be obtained by running doxygen in the cola or libavoid directory.
+There is also
+a simple <a href="libavoid_example.html">documented example</a> to help you get started.
+
+libavoid is written and maintained by
+<a href="http://users.monash.edu/~mwybrow/">Michael Wybrow</a>,
+a member of <a href="http://ialab.it.monash.edu/">Immersive Analytics Lab</a> at Monash University, Australia.
+
+The algorithms used for the connector routing are described in the following papers. If you use libavoid, please cite the relevant paper.
+- M. Wybrow, K. Marriott, and P.J. Stuckey. Orthogonal connector
+ routing.\n
+ In Proceedings of 17th International Symposium on Graph Drawing
+ (GD '09),\n
+ LNCS 5849, pages 219–231. Spring-Verlag, 2010.
+ [<a href="http://dx.doi.org/10.1007/978-3-642-11805-0_22">DOI</a>]
+ [<a href="http://users.monash.edu/~mwybrow/papers/wybrow-gd-2009.pdf">PDF</a>]
+- M. Wybrow, K. Marriott, and P.J. Stuckey. Incremental connector
+ routing.\n
+ In Proceedings of 13th International Symposium on Graph Drawing
+ (GD '05),\n
+ LNCS 3843, pages 446—457. Springer-Verlag, 2006.
+ [<a href="http://dx.doi.org/10.1007/11618058_40">DOI</a>]
+ [<a href="http://users.monash.edu/~mwybrow/papers/wybrow-gd-2005.pdf">PDF</a>]
+- M. Wybrow, K. Marriott and P.J. Stuckey. Orthogonal hyperedge routing.\n
+ In Proceedings of 7th International Conference on the Theory and Application of Diagrams (Diagrams 2012),\n
+ LNCS (LNAI) 7352, pages 51&ndash;64. Springer-Verlag, 2012.
+ [<a href="http://dx.doi.org/10.1007/978-3-642-31223-6_10">DOI</a>]
+ [<a href="http://users.monash.edu/~mwybrow/papers/wybrow-diagrams-2012.pdf">PDF</a>]
+- K. Marriott, P.J. Stuckey, and M. Wybrow. Seeing Around Corners: Fast Orthogonal Connector Routing.\n
+ In Proceedings of the 8th International Conference on the Theory and Application of Diagrams (Diagrams 2014),\n
+ LNCS 8578, pages 31&ndash;37. Springer-Verlag, 2014.
+ [<a href="http://doi.acm.org/10.1007/978-3-662-44043-8_4">DOI</a>]
+ [<a href="http://users.monash.edu/~mwybrow/papers/marriott-diagrams-2014.pdf">PDF</a>]
+
+libavoid is currently used in the following software:
+- A commercial circuit diagram editor;
+- <a href="http://users.monash.edu/~mwybrow/dunnart/">Dunnart</a>, a prototype research
+ constraint-based diagram editor;
+- <a href="http://www.inkscape.org/">Inkscape</a>, the popular Open
+ Source vector graphics editor;
+- <a href="http://arcadiapathways.sourceforge.net/">Arcadia</a>, a
+ visualisation tool for metabolic pathways;
+- <a href="http://gaphor.sourceforge.net/">Gaphas</a>, an open source diagramming widget for GTK+, written in Python;
+- <a href="http://brlcad.org/">BRL-CAD</a>, Constructive Solid Geometry (CSG) solid modeling system;
+- <a href="http://www.qxorm.com/">QxOrm</a>, a C++ library designed to provide Object Relational Mapping (ORM) feature to C++ users; and
+- <a href="http://www.qxorm.com/">QxEntityEditor</a>, a graphic editor for QxOrm library, providing a graphic way to manage a data model.
+
+
+*/
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/doc/example.doc b/src/3rdparty/adaptagrams/libavoid/doc/example.doc
new file mode 100644
index 0000000..a23933d
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/doc/example.doc
@@ -0,0 +1,122 @@
+
+/*!
+
+@page libavoid_example libavoid &mdash; Documented code example
+
+libavoid is a C++ library. Its code is all within the Avoid namespace.
+
+First, you must create an instance of the router.
+@code
+Avoid::Router *router = new Avoid::Router(Avoid::PolyLineRouting); @endcode
+
+To add a shape (obstacle) to the router, you first create a Avoid::ShapeRef by giving the bounding box of the obstacle. This adds the shape to the router (and cause rerouting of connectors it intersects). It also passes ownership of the shapeRef object to the router instance, though it is still fine for you to keep a reference to it.
+@code
+// Create the ShapeRef:
+Avoid::Rectangle rectangle(Avoid::Point(20.0, 35.0), Avoid::Point(40.0, 12.0));
+Avoid::ShapeRef *shapeRef = new Avoid::ShapeRef(router, rectangle); @endcode
+or
+@code
+Avoid::Polygon shapePoly(3);
+shapePoly.ps[0] = Avoid::Point(1.0, 1.0);
+shapePoly.ps[1] = Avoid::Point(2.5, 1.5);
+shapePoly.ps[2] = Avoid::Point(1.5, 2.5);
+Avoid::ShapeRef *shapeRef = new Avoid::ShapeRef(router, shapePoly); @endcode
+
+The relevant prototypes (all in the Avoid namespace) are as follows. If a shape ID is specified, it should be non-zero and unique among all shapes and connectors.
+@code
+Avoid::Rectangle(const Avoid::Point& topLeft, const Avoid::Point& bottomRight);
+Avoid::Rectangle(const Avoid::Point& centre, const double width, const double height);
+Avoid::ShapeRef(Avoid::Router *router, const Avoid::Polygon& polygon, unsigned int id = 0); @endcode
+
+
+To move or resize a shape already in the router, you do the following:
+@code
+router->moveShape(shapeRef, newPolygon); @endcode
+or
+@code
+double xmove = 20, ymove = 15;
+router->moveShape(shapeRef, xmove, ymove); @endcode
+
+In its default mode the router will queue multiple shape movements and perform the changes to the visibility graph in an optimised order. Thus you make several calls to Avoid::Router::moveShape() for different shapes and then tell the router to process the moves. This tend to be useful in interactive applications where the user may move multiple shapes at once.
+@code
+router->moveShape(shapeRef1, newPolygon1);
+router->moveShape(shapeRef2, newPolygon2);
+router->processTransaction();
+ @endcode
+
+To delete a shape from the router (and reroute connectors that then have a better path) you do the following.
+@code
+router->deleteShape(shapeRef); @endcode
+This will cause the router to free the memory for the shapeRef. You should discard your reference to the shapeRef after this call.
+
+To add a new connector to the router, you do the following:
+@code
+Avoid::ConnEnd srcPt(Avoid::Point(1.2, 0.5));
+Avoid::ConnEnd dstPt(Avoid::Point(3.0, 4.0));
+Avoid::ConnRef *connRef = new Avoid::ConnRef(router, srcPt, dstPt); @endcode
+This passes ownership of the connRef object to the router instance, though it is still fine for you to keep a reference to it.
+
+To remove a connector from the router:
+@code
+router->deleteConnector(connRef); @endcode
+This will cause the router to free the memory for the connRef. You should discard your reference to the connRef after this call.
+
+You can set a function to be called when the connector needs to be redrawn. When called, this function will be passed the pointer given as a second argument to Avoid::ConnRef::setCallback():
+@code
+void connCallback(void *ptr)
+{
+ Avoid::ConnRef *connRef = (Avoid::ConnRef *) ptr;
+ printf("Connector %u needs rerouting!\n", connRef->id());
+}
+connRef->setCallback(connCallback, connRef); @endcode
+
+The callback will be triggered by movement, addition and deletion of shapes, as well as by adjustment of the connector endpoints, or by processing a transaction that includes any of these events. You can check if a connector path has changed, and hence the object requires repainting (say because a better path is available due to a shape being deleted):
+@code
+if (connRef->needsRepaint()) ... @endcode
+
+If you want to trigger the callback for a connector after moving its endpoints (or when it is first created you can do this via:
+@code
+connRef->processTransaction(); @endcode
+
+You can then get the new path as follows:
+
+@code
+const Avoid::PolyLine route = connRef->dispayRoute();
+for (size_t i = 0; i &lt; route.size(); ++i)
+{
+ Avoid::Point point = route.at(i);
+ printf("%f, %f\n", point.x, point.y);
+} @endcode
+
+Obviously the alternative to using the callback mechanism is to iterate through all connectors and check their needsRepaint() value after having called processTransaction().
+
+You can update the endpoints of a connector with:
+@code
+Avoid::ConnEnd newSrcPt(Avoid::Point(6, 3));
+Avoid::ConnEnd newDstPt(Avoid::Point(12, 67));
+connRef->setEndpoints(newSrcPt, newDstPt); @endcode
+or
+@code
+Avoid::ConnEnd newSrcPt(Avoid::Point(6, 3));
+connRef->setSourceEndpoint(newSrcPt);
+
+Avoid::ConnEnd newDstPt(Avoid::Point(6, 3));
+connRef->setDestEndpoint(newDstPt); @endcode
+
+You can also create connection pins on shapes and attach connectors directly to these. Then when you move or resize the shapes, the connector endpoints attached to them will be automatically rerouted.
+
+You can create a connection pin as follows:
+@code
+const unsigned int CENTRE = 1;
+new Avoid::ShapeConnectionPin(shapeRef, CENTRE, Avoid::ATTACH_POS_CENTRE, Avoid::ATTACH_POS_CENTRE); @endcode
+This one connects to the centre of the shape, but the position can be specified anywhere within the shape as a proportion of the shape's width and height.
+
+You can then attach a connector to the connection pin be doing the following:
+@code
+Avoid::ConnEnd newSrcPt(shapeRef, CENTRE);
+connRef->setSourceEndpoint(newSrcPt); @endcode
+
+
+See also a short example: example.cpp in the libavoid/tests directory
+
+*/
diff --git a/src/3rdparty/adaptagrams/libavoid/doc/header.html b/src/3rdparty/adaptagrams/libavoid/doc/header.html
new file mode 100644
index 0000000..d1c7c61
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/doc/header.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<title>$title</title>
+<link href="tabs.css" rel="stylesheet" type="text/css"/>
+<link href="doxygen.css" rel="stylesheet" type="text/css"/>
+<style>
+pre {
+ border: dotted 1px #900;
+ padding: 5px;
+ background-color: #ffe;
+}
+a.anchor:hover {
+ text-decoration: none;
+}
+</style>
+</head>
+<body>
diff --git a/src/3rdparty/adaptagrams/libavoid/geometry.cpp b/src/3rdparty/adaptagrams/libavoid/geometry.cpp
new file mode 100644
index 0000000..7f50800
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/geometry.cpp
@@ -0,0 +1,641 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2011 Monash University
+ *
+ * --------------------------------------------------------------------
+ * Much of the code in this module is based on code published with
+ * and/or described in "Computational Geometry in C" (Second Edition),
+ * Copyright (C) 1998 Joseph O'Rourke <orourke@cs.smith.edu>
+ * --------------------------------------------------------------------
+ * The segmentIntersectPoint function is based on code published and
+ * described in Franklin Antonio, Faster Line Segment Intersection,
+ * Graphics Gems III, p. 199-202, code: p. 500-501.
+ * --------------------------------------------------------------------
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+
+// For M_PI:
+#define _USE_MATH_DEFINES
+#include <cmath>
+
+#include <limits>
+
+#include "libavoid/graph.h"
+#include "libavoid/geometry.h"
+#include "libavoid/assertions.h"
+
+
+namespace Avoid {
+
+
+// Returns true iff the point c lies on the closed segment ab.
+// To be used when the points are known to be collinear.
+//
+// Based on the code of 'Between'.
+//
+bool inBetween(const Point& a, const Point& b, const Point& c)
+{
+ double epsilon = std::numeric_limits<double>::epsilon();
+
+ // We only call this when we know the points are collinear,
+ // otherwise we should be checking this here.
+ COLA_ASSERT(vecDir(a, b, c, epsilon) == 0);
+
+ if (fabs(a.x - b.x) > epsilon)
+ {
+ // not vertical
+ return (((a.x < c.x) && (c.x < b.x)) ||
+ ((b.x < c.x) && (c.x < a.x)));
+ }
+ else
+ {
+ return (((a.y < c.y) && (c.y < b.y)) ||
+ ((b.y < c.y) && (c.y < a.y)));
+ }
+}
+
+
+// Returns true iff the three points are colinear.
+//
+bool colinear(const Point& a, const Point& b, const Point& c,
+ const double tolerance)
+{
+
+ // Do this a bit more optimally for orthogonal AB line segments.
+ if (a == b)
+ {
+ return true;
+ }
+ else if (a.x == b.x)
+ {
+ return (a.x == c.x);
+ }
+ else if (a.y == b.y)
+ {
+ return (a.y == c.y);
+ }
+
+ // Or use the general case.
+ return (vecDir(a, b, c, tolerance) == 0);
+
+}
+
+
+// Returns true iff the point c lies on the closed segment ab.
+//
+bool pointOnLine(const Point& a, const Point& b, const Point& c,
+ const double tolerance)
+{
+ // Do this a bit more optimally for orthogonal AB line segments.
+ if (a.x == b.x)
+ {
+ return (a.x == c.x) &&
+ (((a.y < c.y) && (c.y < b.y)) ||
+ ((b.y < c.y) && (c.y < a.y)));
+ }
+ else if (a.y == b.y)
+ {
+ return (a.y == c.y) &&
+ (((a.x < c.x) && (c.x < b.x)) ||
+ ((b.x < c.x) && (c.x < a.x)));
+ }
+
+ // Or use the general case.
+ return (vecDir(a, b, c, tolerance) == 0) && inBetween(a, b, c);
+}
+
+
+// Returns true if the segment cd intersects the segment ab, blocking
+// visibility.
+//
+// Based on the code of 'IntersectProp' and 'Intersect'.
+//
+bool segmentIntersect(const Point& a, const Point& b, const Point& c,
+ const Point& d)
+{
+ int ab_c = vecDir(a, b, c);
+ if (ab_c == 0)
+ {
+ return false;
+ }
+
+ int ab_d = vecDir(a, b, d);
+ if (ab_d == 0)
+ {
+ return false;
+ }
+
+ // It's ok for either of the points a or b to be on the line cd,
+ // so we don't have to check the other two cases.
+
+ int cd_a = vecDir(c, d, a);
+ int cd_b = vecDir(c, d, b);
+
+ // Is an intersection if a and b are on opposite sides of cd,
+ // and c and d are on opposite sides of the line ab.
+ //
+ // Note: this is safe even though the textbook warns about it
+ // since, unlike them, our vecDir is equivilent to 'AreaSign'
+ // rather than 'Area2'.
+ return (((ab_c * ab_d) < 0) && ((cd_a * cd_b) < 0));
+}
+
+
+// Returns true if the segment e1-e2 intersects the shape boundary
+// segment s1-s2, blocking visibility.
+//
+bool segmentShapeIntersect(const Point& e1, const Point& e2, const Point& s1,
+ const Point& s2, bool& seenIntersectionAtEndpoint)
+{
+ if (segmentIntersect(e1, e2, s1, s2))
+ {
+ // Basic intersection of segments.
+ return true;
+ }
+ else if ( (((s2 == e1) || pointOnLine(s1, s2, e1)) &&
+ (vecDir(s1, s2, e2) != 0))
+ ||
+ (((s2 == e2) || pointOnLine(s1, s2, e2)) &&
+ (vecDir(s1, s2, e1) != 0)) )
+ {
+ // Segments intersect at the endpoint of one of the segments. We
+ // allow this once, but the second one blocks visibility. Otherwise
+ // shapes butted up against each other could have visibility through
+ // shapes.
+ if (seenIntersectionAtEndpoint)
+ {
+ return true;
+ }
+ seenIntersectionAtEndpoint = true;
+ }
+ return false;
+}
+
+
+// Returns true iff the point p in a valid region that can contain
+// shortest paths. a0, a1, a2 are ordered vertices of a shape.
+//
+// Based on the code of 'InCone'.
+//
+bool inValidRegion(bool IgnoreRegions, const Point& a0, const Point& a1,
+ const Point& a2, const Point& b)
+{
+ // r is a0--a1
+ // s is a1--a2
+
+ int rSide = vecDir(b, a0, a1);
+ int sSide = vecDir(b, a1, a2);
+
+ bool rOutOn = (rSide <= 0);
+ bool sOutOn = (sSide <= 0);
+
+ bool rOut = (rSide < 0);
+ bool sOut = (sSide < 0);
+
+ if (vecDir(a0, a1, a2) > 0)
+ {
+ // Convex at a1:
+ //
+ // !rO rO
+ // sO sO
+ //
+ // ---s---+
+ // |
+ // !rO r rO
+ // !sO | !sO
+ //
+ //
+ if (IgnoreRegions)
+ {
+ return (rOutOn && !sOut) || (!rOut && sOutOn);
+ }
+ return (rOutOn || sOutOn);
+ }
+ else
+ {
+ // Concave at a1:
+ //
+ // !rO rO
+ // !sO !sO
+ //
+ // +---s---
+ // |
+ // !rO r rO
+ // sO | sO
+ //
+ //
+ return (IgnoreRegions ? false : (rOutOn && sOutOn));
+ }
+}
+
+
+// Gives the side of a corner that a point lies on:
+// 1 anticlockwise
+// -1 clockwise
+// e.g. /|s2
+// /s3 -1 / |
+// / / |
+// 1 |s2 -1 / 1 | -1
+// | / |
+// |s1 s3/ |s1
+//
+int cornerSide(const Point &c1, const Point &c2, const Point &c3,
+ const Point& p)
+{
+ int s123 = vecDir(c1, c2, c3);
+ int s12p = vecDir(c1, c2, p);
+ int s23p = vecDir(c2, c3, p);
+
+ if (s123 == 1)
+ {
+ if ((s12p >= 0) && (s23p >= 0))
+ {
+ return 1;
+ }
+ return -1;
+ }
+ else if (s123 == -1)
+ {
+ if ((s12p <= 0) && (s23p <= 0))
+ {
+ return -1;
+ }
+ return 1;
+ }
+
+ // c1-c2-c3 are collinear, so just return vecDir from c1-c2
+ return s12p;
+}
+
+
+// Returns the Euclidean distance between points a and b.
+//
+double euclideanDist(const Point& a, const Point& b)
+{
+ double xdiff = a.x - b.x;
+ double ydiff = a.y - b.y;
+
+ return sqrt((xdiff * xdiff) + (ydiff * ydiff));
+}
+
+// Returns the Manhattan distance between points a and b.
+//
+double manhattanDist(const Point& a, const Point& b)
+{
+ return fabs(a.x - b.x) + fabs(a.y - b.y);
+}
+
+
+// Returns the Euclidean distance between points a and b.
+//
+double dist(const Point& a, const Point& b)
+{
+ double xdiff = a.x - b.x;
+ double ydiff = a.y - b.y;
+
+ return sqrt((xdiff * xdiff) + (ydiff * ydiff));
+}
+
+// Returns the total length of all line segments in the polygon
+double totalLength(const Polygon& poly)
+{
+ double l = 0;
+ for (size_t i = 1; i < poly.size(); ++i)
+ {
+ l += dist(poly.ps[i-1], poly.ps[i]);
+ }
+ return l;
+}
+
+// Uses the dot-product rule to find the angle (radians) between ab and bc
+double angle(const Point& a, const Point& b, const Point& c)
+{
+ double ux = b.x - a.x,
+ uy = b.y - a.y,
+ vx = c.x - b.x,
+ vy = c.y - b.y,
+ lu = sqrt(ux*ux+uy*uy),
+ lv = sqrt(vx*vx+vy*vy),
+ udotv = ux * vx + uy * vy,
+ costheta = udotv / (lu * lv);
+ return acos(costheta);
+}
+
+// Returns true iff the point q is inside (or on the edge of) the
+// polygon argpoly.
+//
+// This is a fast version that only works for convex shapes. The
+// other version (inPolyGen) is more general.
+//
+bool inPoly(const Polygon& poly, const Point& q, bool countBorder)
+{
+ size_t n = poly.size();
+ const std::vector<Point>& P = poly.ps;
+ bool onBorder = false;
+ for (size_t i = 0; i < n; i++)
+ {
+ // point index; i1 = i-1 mod n
+ size_t prev = (i + n - 1) % n;
+ int dir = vecDir(P[prev], P[i], q);
+ if (dir == -1)
+ {
+ // Point is outside
+ return false;
+ }
+ // Record if point was on a boundary.
+ onBorder |= (dir == 0);
+ }
+ if (!countBorder && onBorder)
+ {
+ return false;
+ }
+ return true;
+}
+
+
+// Returns true iff the point q is inside (or on the edge of) the
+// polygon argpoly.
+//
+// Based on the code of 'InPoly'.
+//
+bool inPolyGen(const PolygonInterface& argpoly, const Point& q)
+{
+ // Numbers of right and left edge/ray crossings.
+ int Rcross = 0;
+ int Lcross = 0;
+
+ // Copy the argument polygon
+ Polygon poly = argpoly;
+ std::vector<Point>& P = poly.ps;
+ size_t n = poly.size();
+
+ // Shift so that q is the origin. This is done for pedagogical clarity.
+ for (size_t i = 0; i < n; ++i)
+ {
+ P[i].x = P[i].x - q.x;
+ P[i].y = P[i].y - q.y;
+ }
+
+ // For each edge e=(i-1,i), see if crosses ray.
+ for (size_t i = 0; i < n; ++i)
+ {
+ // First see if q=(0,0) is a vertex.
+ if ((P[i].x == 0) && (P[i].y == 0))
+ {
+ // We count a vertex as inside.
+ return true;
+ }
+
+ // point index; i1 = i-1 mod n
+ size_t i1 = ( i + n - 1 ) % n;
+
+ // if e "straddles" the x-axis...
+ // The commented-out statement is logically equivalent to the one
+ // following.
+ // if( ((P[i].y > 0) && (P[i1].y <= 0)) ||
+ // ((P[i1].y > 0) && (P[i].y <= 0)) )
+
+ if ((P[i].y > 0) != (P[i1].y > 0))
+ {
+ // e straddles ray, so compute intersection with ray.
+ double x = (P[i].x * P[i1].y - P[i1].x * P[i].y)
+ / (P[i1].y - P[i].y);
+
+ // crosses ray if strictly positive intersection.
+ if (x > 0)
+ {
+ Rcross++;
+ }
+ }
+
+ // if e straddles the x-axis when reversed...
+ // if( ((P[i].y < 0) && (P[i1].y >= 0)) ||
+ // ((P[i1].y < 0) && (P[i].y >= 0)) )
+
+ if ((P[i].y < 0) != (P[i1].y < 0))
+ {
+ // e straddles ray, so compute intersection with ray.
+ double x = (P[i].x * P[i1].y - P[i1].x * P[i].y)
+ / (P[i1].y - P[i].y);
+
+ // crosses ray if strictly positive intersection.
+ if (x < 0)
+ {
+ Lcross++;
+ }
+ }
+ }
+
+ // q on the edge if left and right cross are not the same parity.
+ if ( (Rcross % 2) != (Lcross % 2) )
+ {
+ // We count the edge as inside.
+ return true;
+ }
+
+ // Inside iff an odd number of crossings.
+ if ((Rcross % 2) == 1)
+ {
+ return true;
+ }
+
+ // Outside.
+ return false;
+}
+
+
+
+// Line Segment Intersection
+// Original code by Franklin Antonio
+//
+// The SAME_SIGNS macro assumes arithmetic where the exclusive-or
+// operation will work on sign bits. This works for twos-complement,
+// and most other machine arithmetic.
+#define SAME_SIGNS( a, b ) \
+ (((long) ((unsigned long) a ^ (unsigned long) b)) >= 0 )
+//
+int segmentIntersectPoint(const Point& a1, const Point& a2,
+ const Point& b1, const Point& b2, double *x, double *y)
+{
+ double Ax,Bx,Cx,Ay,By,Cy,d,e,f,num;
+ double x1lo,x1hi,y1lo,y1hi;
+
+ Ax = a2.x - a1.x;
+ Bx = b1.x - b2.x;
+
+ // X bound box test:
+ if (Ax < 0)
+ {
+ x1lo = a2.x;
+ x1hi = a1.x;
+ }
+ else
+ {
+ x1hi = a2.x;
+ x1lo = a1.x;
+ }
+ if (Bx > 0)
+ {
+ if (x1hi < b2.x || b1.x < x1lo) return DONT_INTERSECT;
+ }
+ else
+ {
+ if (x1hi < b1.x || b2.x < x1lo) return DONT_INTERSECT;
+ }
+
+ Ay = a2.y - a1.y;
+ By = b1.y - b2.y;
+
+ // Y bound box test:
+ if (Ay < 0)
+ {
+ y1lo = a2.y;
+ y1hi = a1.y;
+ }
+ else
+ {
+ y1hi = a2.y;
+ y1lo = a1.y;
+ }
+ if (By > 0)
+ {
+ if (y1hi < b2.y || b1.y < y1lo) return DONT_INTERSECT;
+ }
+ else
+ {
+ if (y1hi < b1.y || b2.y < y1lo) return DONT_INTERSECT;
+ }
+
+ Cx = a1.x - b1.x;
+ Cy = a1.y - b1.y;
+ // alpha numerator:
+ d = By*Cx - Bx*Cy;
+ // Both denominator:
+ f = Ay*Bx - Ax*By;
+ // alpha tests:
+ if (f > 0)
+ {
+ if (d < 0 || d > f) return DONT_INTERSECT;
+ }
+ else
+ {
+ if (d > 0 || d < f) return DONT_INTERSECT;
+ }
+
+ // beta numerator:
+ e = Ax*Cy - Ay*Cx;
+ // beta tests:
+ if (f > 0)
+ {
+ if (e < 0 || e > f) return DONT_INTERSECT;
+ }
+ else
+ {
+ if (e > 0 || e < f) return DONT_INTERSECT;
+ }
+
+ // compute intersection coordinates:
+
+ if (f == 0) return PARALLEL;
+
+ // Numerator:
+ num = d*Ax;
+ // Intersection X:
+ *x = a1.x + (num) / f;
+
+ num = d*Ay;
+ // Intersection Y:
+ *y = a1.y + (num) / f;
+
+ return DO_INTERSECT;
+}
+
+
+// Line Segment Intersection
+// Original code by Franklin Antonio
+//
+int rayIntersectPoint(const Point& a1, const Point& a2,
+ const Point& b1, const Point& b2, double *x, double *y)
+{
+ double Ax,Bx,Cx,Ay,By,Cy,d,f,num;
+
+ Ay = a2.y - a1.y;
+ By = b1.y - b2.y;
+ Ax = a2.x - a1.x;
+ Bx = b1.x - b2.x;
+
+ Cx = a1.x - b1.x;
+ Cy = a1.y - b1.y;
+ // alpha numerator:
+ d = By*Cx - Bx*Cy;
+ // Both denominator:
+ f = Ay*Bx - Ax*By;
+
+ // compute intersection coordinates:
+
+ if (f == 0) return PARALLEL;
+
+ // Numerator:
+ num = d*Ax;
+ // Intersection X:
+ *x = a1.x + (num) / f;
+
+ num = d*Ay;
+ // Intersection Y:
+ *y = a1.y + (num) / f;
+
+ return DO_INTERSECT;
+}
+
+// Returns the rotationalAngle, between 0 and 360, of this point from (0,0).
+//
+double rotationalAngle(const Point& p)
+{
+ if (p.y == 0)
+ {
+ return ((p.x < 0) ? 180 : 0);
+ }
+ else if (p.x == 0)
+ {
+ return ((p.y < 0) ? 270 : 90);
+ }
+
+ double ang = atan(p.y / p.x);
+ ang = (ang * 180) / M_PI;
+
+ if (p.x < 0)
+ {
+ ang += 180;
+ }
+ else if (p.y < 0)
+ {
+ ang += 360;
+ }
+ COLA_ASSERT(ang >= 0);
+ COLA_ASSERT(ang <= 360);
+
+ return ang;
+}
+
+
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/geometry.h b/src/3rdparty/adaptagrams/libavoid/geometry.h
new file mode 100644
index 0000000..47f1199
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/geometry.h
@@ -0,0 +1,129 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2011 Monash University
+ *
+ * --------------------------------------------------------------------
+ * Much of the code in this module is based on code published with
+ * and/or described in "Computational Geometry in C" (Second Edition),
+ * Copyright (C) 1998 Joseph O'Rourke <orourke@cs.smith.edu>
+ * --------------------------------------------------------------------
+ * The segmentIntersectPoint function is based on code published and
+ * described in Franklin Antonio, Faster Line Segment Intersection,
+ * Graphics Gems III, p. 199-202, code: p. 500-501.
+ * --------------------------------------------------------------------
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+
+#ifndef AVOID_GEOMETRY_H
+#define AVOID_GEOMETRY_H
+
+#include "libavoid/geomtypes.h"
+#include "libavoid/assertions.h"
+
+namespace Avoid {
+
+
+extern double euclideanDist(const Point& a, const Point& b);
+extern double manhattanDist(const Point& a, const Point& b);
+extern double totalLength(const Polygon& poly);
+extern double angle(const Point& a, const Point& b, const Point& c);
+extern bool segmentIntersect(const Point& a, const Point& b,
+ const Point& c, const Point& d);
+extern bool segmentShapeIntersect(const Point& e1, const Point& e2,
+ const Point& s1, const Point& s2, bool& seenIntersectionAtEndpoint);
+extern bool inPoly(const Polygon& poly, const Point& q, bool countBorder = true);
+extern bool inPolyGen(const PolygonInterface& poly, const Point& q);
+extern bool inValidRegion(bool IgnoreRegions, const Point& a0,
+ const Point& a1, const Point& a2, const Point& b);
+extern int cornerSide(const Point &c1, const Point &c2, const Point &c3,
+ const Point& p);
+extern bool pointOnLine(const Point& a, const Point& b, const Point& c,
+ const double tolerance = 0.0);
+extern bool colinear(const Point& a, const Point& b, const Point& c,
+ const double tolerance = 0.0);
+// To be used only when the points are known to be colinear.
+extern bool inBetween(const Point& a, const Point& b, const Point& c);
+
+
+// Direction from vector.
+// Looks at the position of point c from the directed segment ab and
+// returns the following:
+// 1 counterclockwise
+// 0 collinear
+// -1 clockwise
+//
+// Based on the code of 'AreaSign'.
+//
+// The 'maybeZero' argument can be used to adjust the tolerance of the
+// function. It will be most accurate when 'maybeZero' == 0.0, the default.
+//
+static inline int vecDir(const Point& a, const Point& b, const Point& c,
+ const double maybeZero = 0.0)
+{
+ COLA_ASSERT(maybeZero >= 0);
+
+ double area2 = ((b.x - a.x) * (c.y - a.y)) -
+ ((c.x - a.x) * (b.y - a.y));
+
+ if (area2 < (-maybeZero))
+ {
+ return -1;
+ }
+ else if (area2 > maybeZero)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+// Finds the projection point of (a,b) onto (a,c)
+static inline Point projection(const Point& a, const Point& b, const Point& c)
+{
+ double ux = c.x - a.x,
+ uy = c.y - a.y,
+ vx = b.x - a.x,
+ vy = b.y - a.y,
+ scalarProj = ux * vx + uy * vy;
+ scalarProj /= ux * ux + uy * uy;
+ Point p;
+ p.x = scalarProj * ux + a.x;
+ p.y = scalarProj * uy + a.y;
+ return p;
+}
+
+// Line Segment Intersection
+// Original code by Franklin Antonio
+//
+static const int DONT_INTERSECT = 0;
+static const int DO_INTERSECT = 1;
+static const int PARALLEL = 3;
+extern int segmentIntersectPoint(const Point& a1, const Point& a2,
+ const Point& b1, const Point& b2, double *x, double *y);
+extern int rayIntersectPoint(const Point& a1, const Point& a2,
+ const Point& b1, const Point& b2, double *x, double *y);
+extern double rotationalAngle(const Point& p);
+
+
+}
+
+
+#endif
diff --git a/src/3rdparty/adaptagrams/libavoid/geomtypes.cpp b/src/3rdparty/adaptagrams/libavoid/geomtypes.cpp
new file mode 100644
index 0000000..4987834
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/geomtypes.cpp
@@ -0,0 +1,761 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+
+#include <cmath>
+#include <cfloat>
+#include <cstdlib>
+#include <algorithm>
+
+#include "libavoid/geomtypes.h"
+#include "libavoid/shape.h"
+#include "libavoid/router.h"
+#include "libavoid/assertions.h"
+
+
+namespace Avoid
+{
+
+
+Point::Point() :
+ id(0),
+ vn(kUnassignedVertexNumber)
+{
+}
+
+
+Point::Point(const double xv, const double yv) :
+ x(xv),
+ y(yv),
+ id(0),
+ vn(kUnassignedVertexNumber)
+{
+}
+
+
+bool Point::operator==(const Point& rhs) const
+{
+ if ((x == rhs.x) && (y == rhs.y))
+ {
+ return true;
+ }
+ return false;
+}
+
+
+bool Point::operator!=(const Point& rhs) const
+{
+ if ((x != rhs.x) || (y != rhs.y))
+ {
+ return true;
+ }
+ return false;
+}
+
+
+bool Point::equals(const Point& rhs, double epsilon) const
+{
+ if ( (fabs(x - rhs.x) < epsilon) && (fabs(y - rhs.y) < epsilon) )
+ {
+ return true;
+ }
+ return false;
+}
+
+
+// Just defined to allow std::set<Point>. Not particularly meaningful!
+bool Point::operator<(const Point& rhs) const
+{
+ if (x == rhs.x)
+ {
+ return (y < rhs.y);
+ }
+ return (x < rhs.x);
+}
+
+
+double& Point::operator[](const size_t dimension)
+{
+ COLA_ASSERT((dimension == 0) || (dimension == 1));
+ return ((dimension == 0) ? x : y);
+}
+
+
+const double& Point::operator[](const size_t dimension) const
+{
+ COLA_ASSERT((dimension == 0) || (dimension == 1));
+ return ((dimension == 0) ? x : y);
+}
+
+Point Point::operator+(const Point& rhs) const
+{
+ return Point(x + rhs.x, y + rhs.y);
+}
+
+
+Point Point::operator-(const Point& rhs) const
+{
+ return Point(x - rhs.x, y - rhs.y);
+}
+
+
+ReferencingPolygon::ReferencingPolygon(const Polygon& poly, const Router *router)
+ : PolygonInterface(),
+ _id(poly._id),
+ psRef(poly.size()),
+ psPoints(poly.size())
+{
+ COLA_ASSERT(router != nullptr);
+ for (size_t i = 0; i < poly.size(); ++i)
+ {
+ if (poly.ps[i].id == 0)
+ {
+ // Can't be referenced, so just make a copy of the point.
+ psRef[i] = std::make_pair((Polygon *) nullptr,
+ kUnassignedVertexNumber);
+ psPoints[i] = poly.ps[i];
+ }
+ else
+ {
+ const Polygon *polyPtr = nullptr;
+ for (ObstacleList::const_iterator sh = router->m_obstacles.begin();
+ sh != router->m_obstacles.end(); ++sh)
+ {
+ if ((*sh)->id() == poly.ps[i].id)
+ {
+ const Polygon& poly = (*sh)->polygon();
+ polyPtr = &poly;
+ break;
+ }
+ }
+ COLA_ASSERT(polyPtr != nullptr);
+ psRef[i] = std::make_pair(polyPtr, poly.ps[i].vn);
+ }
+ }
+}
+
+
+ReferencingPolygon::ReferencingPolygon()
+ : PolygonInterface()
+{
+ clear();
+}
+
+
+void ReferencingPolygon::clear(void)
+{
+ psRef.clear();
+ psPoints.clear();
+}
+
+
+bool ReferencingPolygon::empty(void) const
+{
+ return psRef.empty();
+}
+
+
+size_t ReferencingPolygon::size(void) const
+{
+ return psRef.size();
+}
+
+
+int ReferencingPolygon::id(void) const
+{
+ return _id;
+}
+
+
+const Point& ReferencingPolygon::at(size_t index) const
+{
+ COLA_ASSERT(index < size());
+
+ if (psRef[index].first != nullptr)
+ {
+ const Polygon& poly = *(psRef[index].first);
+ unsigned short poly_index = psRef[index].second;
+ COLA_ASSERT(poly_index < poly.size());
+
+ return poly.ps[poly_index];
+ }
+ else
+ {
+ return psPoints[index];
+ }
+}
+
+
+Box PolygonInterface::offsetBoundingBox(double offset) const
+{
+ Box bBox;
+ bBox.min.x = DBL_MAX;
+ bBox.min.y = DBL_MAX;
+ bBox.max.x = -DBL_MAX;
+ bBox.max.y = -DBL_MAX;
+
+ for (size_t i = 0; i < size(); ++i)
+ {
+ bBox.min.x = std::min(bBox.min.x, at(i).x);
+ bBox.min.y = std::min(bBox.min.y, at(i).y);
+ bBox.max.x = std::max(bBox.max.x, at(i).x);
+ bBox.max.y = std::max(bBox.max.y, at(i).y);
+ }
+
+ // Add buffer space.
+ bBox.min.x -= offset;
+ bBox.min.y -= offset;
+ bBox.max.x += offset;
+ bBox.max.y += offset;
+
+ return bBox;
+}
+
+double Box::length(size_t dimension) const
+{
+ if (dimension == 0)
+ {
+ return (max.x - min.x);
+ }
+ return (max.y - min.y);
+}
+
+double Box::width(void) const
+{
+ return (max.x - min.x);
+}
+
+double Box::height(void) const
+{
+ return (max.y - min.y);
+}
+
+Polygon::Polygon()
+ : PolygonInterface(),
+ _id(0)
+{
+ clear();
+}
+
+
+Polygon::Polygon(const int pn)
+ : PolygonInterface(),
+ _id(0),
+ ps(pn)
+{
+}
+
+
+Polygon::Polygon(const PolygonInterface& poly)
+ : PolygonInterface(),
+ _id(poly.id()),
+ ps(poly.size())
+{
+ for (size_t i = 0; i < poly.size(); ++i)
+ {
+ ps[i] = poly.at(i);
+ }
+}
+
+
+Polygon PolygonInterface::boundingRectPolygon(void) const
+{
+ Box boundingBox = offsetBoundingBox(0.0);
+
+ return Rectangle(boundingBox.min, boundingBox.max);
+}
+
+static Point unitNormalForEdge(const Point &pt1, const Point &pt2)
+{
+ if (pt2 == pt1)
+ {
+ return Point(0, 0);
+ }
+ double dx = pt2.x - pt1.x;
+ double dy = pt2.y - pt1.y;
+ double f = 1.0 / std::sqrt((dx * dx) + (dy * dy));
+ dx *= f;
+ dy *= f;
+ return Point(dy, -dx);
+}
+
+Polygon PolygonInterface::offsetPolygon(double offset) const
+{
+ Polygon newPoly;
+ newPoly._id = id();
+ if (offset == 0)
+ {
+ for (size_t i = 0; i < size(); ++i)
+ {
+ newPoly.ps.push_back(at(i));
+ }
+ return newPoly;
+ }
+
+ size_t numOfEdges = size();
+ std::vector<Vector> normals(numOfEdges);
+ for (size_t i = 0; i < numOfEdges; ++i)
+ {
+ normals[i] = unitNormalForEdge(at(i), at((i + 1) % numOfEdges));
+ }
+
+ size_t j = numOfEdges - 1;
+ for (size_t i = 0; i < numOfEdges; ++i)
+ {
+ double R = 1 + ((normals[i].x * normals[j].x) +
+ (normals[i].y * normals[j].y));
+ if (((normals[j].x * normals[i].y) - (normals[i].x * normals[j].y)) *
+ offset >= 0)
+ {
+ double q = offset / R;
+ Point pt = Point(at(i).x + (normals[j].x + normals[i].x) * q,
+ at(i).y + (normals[j].y + normals[i].y) * q);
+
+ pt.id = id();
+ pt.vn = newPoly.size();
+ newPoly.ps.push_back(pt);
+ }
+ else
+ {
+ Point pt1 = Point(at(i).x + normals[j].x * offset,
+ at(i).y + normals[j].y * offset);
+ Point pt2 = at(i);
+ Point pt3 = Point(at(i).x + normals[i].x * offset,
+ at(i).y + normals[i].y * offset);
+
+ pt1.id = id();
+ pt1.vn = newPoly.size();
+ newPoly.ps.push_back(pt1);
+
+ pt2.id = id();
+ pt2.vn = newPoly.size();
+ newPoly.ps.push_back(pt2);
+
+ pt3.id = id();
+ pt3.vn = newPoly.size();
+ newPoly.ps.push_back(pt3);
+ }
+ j = i;
+ }
+
+ return newPoly;
+}
+
+void Polygon::clear(void)
+{
+ ps.clear();
+ ts.clear();
+}
+
+
+bool Polygon::empty(void) const
+{
+ return ps.empty();
+}
+
+
+size_t Polygon::size(void) const
+{
+ return ps.size();
+}
+
+
+int Polygon::id(void) const
+{
+ return _id;
+}
+
+
+const Point& Polygon::at(size_t index) const
+{
+ COLA_ASSERT(index < size());
+
+ return ps[index];
+}
+
+void Polygon::setPoint(size_t index, const Point& point)
+{
+ COLA_ASSERT(index < size());
+
+ ps[index] = point;
+}
+
+
+static const unsigned int SHORTEN_NONE = 0;
+static const unsigned int SHORTEN_START = 1;
+static const unsigned int SHORTEN_END = 2;
+static const unsigned int SHORTEN_BOTH = SHORTEN_START | SHORTEN_END;
+
+// shorten_line():
+// Given the two endpoints of a line segment, this function adjusts the
+// endpoints of the line to shorten the line by shorten_length at either
+// or both ends.
+//
+static void shorten_line(double& x1, double& y1, double& x2, double& y2,
+ const unsigned int mode, const double shorten_length)
+{
+ if (mode == SHORTEN_NONE)
+ {
+ return;
+ }
+
+ double rise = y1 - y2;
+ double run = x1 - x2;
+ double disty = fabs(rise);
+ double distx = fabs(run);
+
+ // Handle case where shorten length is greater than the length of the
+ // line segment.
+ if ((mode == SHORTEN_BOTH) &&
+ (((distx > disty) && ((shorten_length * 2) > distx)) ||
+ ((disty >= distx) && ((shorten_length * 2) > disty))))
+ {
+ x1 = x2 = x1 - (run / 2);
+ y1 = y2 = y1 - (rise / 2);
+ return;
+ }
+ else if ((mode == SHORTEN_START) &&
+ (((distx > disty) && (shorten_length > distx)) ||
+ ((disty >= distx) && (shorten_length > disty))))
+ {
+ x1 = x2;
+ y1 = y2;
+ return;
+ }
+ else if ((mode == SHORTEN_END) &&
+ (((distx > disty) && (shorten_length > distx)) ||
+ ((disty >= distx) && (shorten_length > disty))))
+ {
+ x2 = x1;
+ y2 = y1;
+ return;
+ }
+
+ // Handle orthogonal line segments.
+ if (x1 == x2)
+ {
+ // Vertical
+ int sign = (y1 < y2) ? 1: -1;
+
+ if (mode & SHORTEN_START)
+ {
+ y1 += (sign * shorten_length);
+ }
+ if (mode & SHORTEN_END)
+ {
+ y2 -= (sign * shorten_length);
+ }
+ return;
+ }
+ else if (y1 == y2)
+ {
+ // Horizontal
+ int sign = (x1 < x2) ? 1: -1;
+
+ if (mode & SHORTEN_START)
+ {
+ x1 += (sign * shorten_length);
+ }
+ if (mode & SHORTEN_END)
+ {
+ x2 -= (sign * shorten_length);
+ }
+ return;
+ }
+
+ int xpos = (x1 < x2) ? -1 : 1;
+ int ypos = (y1 < y2) ? -1 : 1;
+
+ double tangent = rise / run;
+
+ if (mode & SHORTEN_END)
+ {
+ if (disty > distx)
+ {
+ y2 += shorten_length * ypos;
+ x2 += shorten_length * ypos * (1 / tangent);
+ }
+ else if (disty < distx)
+ {
+ y2 += shorten_length * xpos * tangent;
+ x2 += shorten_length * xpos;
+ }
+ }
+
+ if (mode & SHORTEN_START)
+ {
+ if (disty > distx)
+ {
+ y1 -= shorten_length * ypos;
+ x1 -= shorten_length * ypos * (1 / tangent);
+ }
+ else if (disty < distx)
+ {
+ y1 -= shorten_length * xpos * tangent;
+ x1 -= shorten_length * xpos;
+ }
+ }
+}
+
+
+void Polygon::translate(const double xDist, const double yDist)
+{
+ for (size_t i = 0; i < size(); ++i)
+ {
+ ps[i].x += xDist;
+ ps[i].y += yDist;
+ }
+}
+
+
+Polygon Polygon::simplify(void) const
+{
+ // Copy the PolyLine.
+ Polygon simplified = *this;
+
+ std::vector<std::pair<size_t, Point> >& checkpoints =
+ simplified.checkpointsOnRoute;
+ bool hasCheckpointInfo = !(checkpoints.empty());
+
+ std::vector<Point>::iterator it = simplified.ps.begin();
+ if (it != simplified.ps.end()) ++it;
+
+ // Combine collinear line segments into single segments:
+ for (size_t j = 2; j < simplified.size(); )
+ {
+ if (vecDir(simplified.ps[j - 2], simplified.ps[j - 1],
+ simplified.ps[j]) == 0)
+ {
+ // These three points make up two collinear segments, so just
+ // combine them into a single segment.
+ it = simplified.ps.erase(it);
+
+ if (hasCheckpointInfo)
+ {
+ // 0 1 2 3 4 <- vertices on path
+ // +-----+-----+-----+-----+
+ // 0 1 2 3 4 5 6 7 8 <- checkpoints on points & edges
+ // |
+ // \_ deletedPointValue = 4
+ //
+ // If 1-2-3 is collinear then we want to end up with
+ //
+ // 0 1 2 3
+ // +-----+-----------+-----+
+ // 0 1 2 3 3 3 4 5 6
+ //
+ //
+ //
+ size_t deletedPointValue = (j - 1) - 1;
+ for (size_t i = 0; i < checkpoints.size(); ++i)
+ {
+ if (checkpoints[i].first == deletedPointValue)
+ {
+ checkpoints[i].first -= 1;
+ }
+ else if (checkpoints[i].first > deletedPointValue)
+ {
+ checkpoints[i].first -= 2;
+ }
+ }
+ }
+ }
+ else
+ {
+ ++j;
+ ++it;
+ }
+ }
+
+ return simplified;
+}
+
+std::vector<Point> Polygon::checkpointsOnSegment(size_t segmentLowerIndex,
+ int indexModifier) const
+{
+ std::vector<Point> checkpoints;
+ // 0 1 2 3 4 <- vertices on path
+ // +-----+-----+-----+-----+
+ // 0 1 2 3 4 5 6 7 8 <- checkpoints on points & edges
+
+ size_t checkpointLowerValue = 2 * segmentLowerIndex;
+ size_t checkpointUpperValue = checkpointLowerValue + 2;
+ size_t index = 0;
+
+ if (indexModifier > 0)
+ {
+ checkpointLowerValue++;
+ }
+ else if (indexModifier < 0)
+ {
+ checkpointUpperValue--;
+ }
+
+ while (index < checkpointsOnRoute.size())
+ {
+ if ((checkpointsOnRoute[index].first >= checkpointLowerValue) &&
+ (checkpointsOnRoute[index].first <= checkpointUpperValue))
+ {
+ checkpoints.push_back(checkpointsOnRoute[index].second);
+ }
+ ++index;
+ }
+ return checkpoints;
+}
+
+
+#define mid(a, b) ((a < b) ? a + ((b - a) / 2) : b + ((a - b) / 2))
+
+
+// curvedPolyline():
+// Returns a curved approximation of this multi-segment PolyLine, with
+// the corners replaced by smooth Bezier curves. curve_amount describes
+// how large to make the curves.
+// The ts value for each point in the returned Polygon describes the
+// drawing operation: 'M' (move) marks the first point, a line segment
+// is marked with an 'L' and three 'C's (along with the previous point)
+// describe the control points of a Bezier curve.
+//
+Polygon Polygon::curvedPolyline(const double curve_amount,
+ const bool closed) const
+{
+ Polygon simplified = this->simplify();
+
+ Polygon curved;
+ size_t num_of_points = size();
+ if (num_of_points <= 2)
+ {
+ // There is only a single segment, do nothing.
+ curved = *this;
+ curved.ts.push_back('M');
+ curved.ts.push_back('L');
+ return curved;
+ }
+
+ // Build the curved polyline:
+ curved._id = _id;
+ double last_x = 0;
+ double last_y = 0;
+ if (closed)
+ {
+ double x1 = simplified.ps[0].x;
+ double y1 = simplified.ps[0].y;
+ double x2 = simplified.ps[1].x;
+ double y2 = simplified.ps[1].y;
+ shorten_line(x1, y1, x2, y2, SHORTEN_START, curve_amount);
+ curved.ps.push_back(Point(x1, y1));
+ curved.ts.push_back('M');
+ }
+ else
+ {
+ curved.ps.push_back(ps[0]);
+ curved.ts.push_back('M');
+ }
+
+ size_t simpSize = simplified.size();
+ size_t finish = (closed) ? simpSize + 2 : simpSize;
+ for (size_t j = 1; j < finish; ++j)
+ {
+ double x1 = simplified.ps[(simpSize + j - 1) % simpSize].x;
+ double y1 = simplified.ps[(simpSize + j - 1) % simpSize].y;
+ double x2 = simplified.ps[j % simpSize].x;
+ double y2 = simplified.ps[j % simpSize].y;
+
+ double old_x = x1;
+ double old_y = y1;
+
+ unsigned int mode = SHORTEN_BOTH;
+ if (!closed)
+ {
+ if (j == 1)
+ {
+ mode = SHORTEN_END;
+ }
+ else if (j == (size() - 1))
+ {
+ mode = SHORTEN_START;
+ }
+ }
+ shorten_line(x1, y1, x2, y2, mode, curve_amount);
+
+ if (j > 1)
+ {
+ curved.ts.insert(curved.ts.end(), 3, 'C');
+ curved.ps.push_back(Point(mid(last_x, old_x), mid(last_y, old_y)));
+ curved.ps.push_back(Point(mid(x1, old_x), mid(y1, old_y)));
+ curved.ps.push_back(Point(x1, y1));
+ }
+ if (closed && (j == (finish - 1)))
+ {
+ // Close the path.
+ curved.ts.push_back('Z');
+ curved.ps.push_back(Point(x1, y1));
+ break;
+ }
+ curved.ts.push_back('L');
+ curved.ps.push_back(Point(x2, y2));
+
+ last_x = x2;
+ last_y = y2;
+ }
+
+ return curved;
+}
+
+
+Rectangle::Rectangle(const Point& topLeft, const Point& bottomRight)
+ : Polygon(4)
+{
+ double xMin = std::min(topLeft.x, bottomRight.x);
+ double xMax = std::max(topLeft.x, bottomRight.x);
+ double yMin = std::min(topLeft.y, bottomRight.y);
+ double yMax = std::max(topLeft.y, bottomRight.y);
+
+ ps[0] = Point(xMax, yMin);
+ ps[1] = Point(xMax, yMax);
+ ps[2] = Point(xMin, yMax);
+ ps[3] = Point(xMin, yMin);
+}
+
+
+Rectangle::Rectangle(const Point& centre, const double width,
+ const double height)
+ : Polygon(4)
+{
+ double halfWidth = width / 2.0;
+ double halfHeight = height / 2.0;
+ double xMin = centre.x - halfWidth;
+ double xMax = centre.x + halfWidth;
+ double yMin = centre.y - halfHeight;
+ double yMax = centre.y + halfHeight;
+
+ ps[0] = Point(xMax, yMin);
+ ps[1] = Point(xMax, yMax);
+ ps[2] = Point(xMin, yMax);
+ ps[3] = Point(xMin, yMin);
+}
+
+
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/geomtypes.h b/src/3rdparty/adaptagrams/libavoid/geomtypes.h
new file mode 100644
index 0000000..e370360
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/geomtypes.h
@@ -0,0 +1,381 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+//! @file geomtypes.h
+//! @brief Contains the interface for various geometry types and classes.
+
+
+#ifndef AVOID_GEOMTYPES_H
+#define AVOID_GEOMTYPES_H
+
+#include <cstdlib>
+#include <vector>
+#include <utility>
+
+#include "libavoid/dllexport.h"
+
+
+namespace Avoid
+{
+
+static const size_t XDIM = 0;
+static const size_t YDIM = 1;
+
+class Polygon;
+
+//! @brief The Point class defines a point in the plane.
+//!
+//! Points consist of an x and y value. They may also have an ID and vertex
+//! number associated with them.
+//!
+class AVOID_EXPORT Point
+{
+ public:
+ //! @brief Default constructor.
+ //!
+ Point();
+ //! @brief Standard constructor.
+ //!
+ //! @param[in] xv The x position of the point.
+ //! @param[in] yv The y position of the point.
+ //!
+ Point(const double xv, const double yv);
+
+ //! @brief Comparison operator. Returns true if at same position.
+ //!
+ //! @param[in] rhs The point to compare with this one.
+ //! @return The result of the comparison.
+ //! @sa equals()
+ bool operator==(const Point& rhs) const;
+ //! @brief Comparison operator. Returns true if at same position,
+ //! or at effectively the same position for a given value of
+ //! epsilson.
+ //!
+ //! @param[in] rhs The point to compare with this one.
+ //! @param[in] epsilon Value of epsilon to use during comparison.
+ //! @return The result of the comparison.
+ //! @sa operator==()
+ bool equals(const Point& rhs, double epsilon = 0.0001) const;
+ //! @brief Comparison operator. Returns true if at different positions.
+ //!
+ //! @param[in] rhs The point to compare with this one.
+ //! @return The result of the comparison.
+ //!
+ bool operator!=(const Point& rhs) const;
+ //! @brief Comparison operator. Returns true if less-then rhs point.
+ //!
+ //! @note This operator is not particularly useful, but is defined
+ //! to allow std::set<Point>.
+ //!
+ //! @param[in] rhs The point to compare with this one.
+ //! @return The result of the comparison.
+ //!
+ bool operator<(const Point& rhs) const;
+
+ //! @brief Returns the x or y value of the point, given the dimension.
+ //!
+ //! @param[in] dimension The dimension: 0 for x, 1 for y.
+ //! @return The component of the point in that dimension.
+ double& operator[](const size_t dimension);
+ const double& operator[](const size_t dimension) const;
+
+ Point operator+(const Point& rhs) const;
+ Point operator-(const Point& rhs) const;
+
+ //! The x position.
+ double x;
+ //! The y position.
+ double y;
+ //! The ID associated with this point.
+ unsigned int id;
+ //! The vertex number associated with this point.
+ unsigned short vn;
+
+};
+
+
+//! Constant value representing an unassigned vertex number.
+//!
+static const unsigned short kUnassignedVertexNumber = 8;
+
+//! Constant value representing a ShapeConnectionPin.
+static const unsigned short kShapeConnectionPin = 9;
+
+
+//! @brief A vector, represented by the Point class.
+//!
+typedef Point Vector;
+
+//! @brief A bounding box, represented by the top-left and
+//! bottom-right corners.
+//!
+class AVOID_EXPORT Box
+{
+ public:
+ //! The top-left point.
+ Point min;
+ //! The bottom-right point.
+ Point max;
+
+ double length(size_t dimension) const;
+ double width(void) const;
+ double height(void) const;
+};
+
+
+
+//! @brief A common interface used by the Polygon classes.
+//!
+class AVOID_EXPORT PolygonInterface
+{
+ public:
+ //! @brief Constructor.
+ PolygonInterface() { }
+ //! @brief Destructor.
+ virtual ~PolygonInterface() { }
+ //! @brief Resets this to the empty polygon.
+ virtual void clear(void) = 0;
+ //! @brief Returns true if this polygon is empty.
+ virtual bool empty(void) const = 0;
+ //! @brief Returns the number of points in this polygon.
+ virtual size_t size(void) const = 0;
+ //! @brief Returns the ID value associated with this polygon.
+ virtual int id(void) const = 0;
+ //! @brief Returns a specific point in the polygon.
+ //! @param[in] index The array index of the point to be returned.
+ virtual const Point& at(size_t index) const = 0;
+ //! @brief Returns the bounding rectangle for this polygon.
+ //!
+ //! @return A new Rectangle representing the bounding box.
+ Polygon boundingRectPolygon(void) const;
+ //! @brief Returns the bounding rectangle that contains this polygon
+ //! with optionally some buffer space around it for routing.
+ //!
+ //! If a buffer distance of zero is given, then this method returns
+ //! the bounding rectangle for the shape's polygon.
+ //!
+ //! @param offset Extra distance to pad each side of the rect.
+ //! @return The bounding box for the polygon.
+ Box offsetBoundingBox(double offset) const;
+
+ Polygon offsetPolygon(double offset) const;
+};
+
+
+//! @brief A line between two points.
+//!
+class AVOID_EXPORT Edge
+{
+ public:
+ //! The first point.
+ Point a;
+ //! The second point.
+ Point b;
+};
+
+
+class Router;
+class ReferencingPolygon;
+
+
+//! @brief A dynamic Polygon, to which points can be easily added and removed.
+//!
+//! @note The Rectangle class can be used as an easy way of constructing a
+//! square or rectangular polygon.
+//!
+class AVOID_EXPORT Polygon : public PolygonInterface
+{
+ public:
+ //! @brief Constructs an empty polygon (with zero points).
+ Polygon();
+ //! @brief Constructs a new polygon with n points.
+ //!
+ //! A rectangle would be comprised of four point. An n segment
+ //! PolyLine (represented as a Polygon) would be comprised of n+1
+ //! points. Whether a particular Polygon is closed or not, depends
+ //! on whether it is a Polygon or Polyline. Shape polygons are always
+ //! considered to be closed, meaning the last point joins back to the
+ //! first point.
+ //!
+ //! The values for points can be set by setting the Polygon:ps vector,
+ //! or via the Polygon::setPoint() method.
+ //!
+ //! @param[in] n Number of points in the polygon.
+ //!
+ Polygon(const int n);
+ //! @brief Constructs a new polygon from an existing Polygon.
+ //!
+ //! @param[in] poly An existing polygon to copy the new polygon from.
+ //!
+ Polygon(const PolygonInterface& poly);
+ //! @brief Resets this to the empty polygon.
+ void clear(void);
+ //! @brief Returns true if this polygon is empty.
+ bool empty(void) const;
+ //! @brief Returns the number of points in this polygon.
+ size_t size(void) const;
+ //! @brief Returns the ID value associated with this polygon.
+ int id(void) const;
+ //! @brief Returns a specific point in the polygon.
+ //! @param[in] index The array index of the point to be returned.
+ const Point& at(size_t index) const;
+ //! @brief Sets a position for a particular point in the polygon..
+ //! @param[in] index The array index of the point to be set.
+ //! @param[in] point The point value to be assigned..
+ void setPoint(size_t index, const Point& point);
+ //! @brief Returns a simplified Polyline, where all collinear line
+ //! segments have been collapsed down into single line
+ //! segments.
+ //!
+ //! @return A new polyline with a simplified representation.
+ //!
+ Polygon simplify(void) const;
+ //! @brief Returns a curved approximation of this multi-segment
+ //! PolyLine, with the corners replaced by smooth Bezier
+ //! curves.
+ //!
+ //! This function does not do any further obstacle avoidance with the
+ //! curves produced. Hence, you would usually specify a curve_amount
+ //! in similar size to the space buffer around obstacles in the scene.
+ //! This way the curves will cut the corners around shapes but still
+ //! run within this buffer space.
+ //!
+ //! @param curve_amount Describes the distance along the end of each
+ //! line segment to turn into a curve.
+ //! @param closed Describes whether the Polygon should be
+ //! treated as closed. Defaults to false.
+ //! @return A new polyline (polygon) representing the curved path.
+ //! Its points represent endpoints of line segments and
+ //! Bezier spline control points. The Polygon::ts vector for
+ //! this returned polygon is populated with a character for
+ //! each point describing its type.
+ //! @sa ts
+ Polygon curvedPolyline(const double curve_amount,
+ const bool closed = false) const;
+ //! @brief Translates the polygon position by a relative amount.
+ //!
+ //! @param[in] xDist Distance to move polygon in the x dimension.
+ //! @param[in] yDist Distance to move polygon in the y dimension.
+ void translate(const double xDist, const double yDist);
+
+ //! @brief An ID for the polygon.
+ int _id;
+ //! @brief A vector of the points that make up the Polygon.
+ std::vector<Point> ps;
+ //! @brief If used, denotes whether the corresponding point in ps is
+ //! a move-to operation or a Bezier curve-to.
+ //!
+ //! Each character describes the drawing operation for the
+ //! corresponding point in the ps vector. Possible values are:
+ //! - 'M': A moveto operation, marks the first point;
+ //! - 'L': A lineto operation, is a line from the previous point to
+ //! the current point; or
+ //! - 'C': A curveto operation, three consecutive 'C' points
+ //! (along with the previous point) describe the control points
+ //! of a Bezier curve.
+ //! - 'Z': Closes the path (used for cluster boundaries).
+ //!
+ //! @note This vector will currently only be populated for polygons
+ //! returned by curvedPolyline().
+ std::vector<char> ts;
+
+ // @brief If used, denotes checkpoints through which the route travels
+ // and the relevant segment of the route.
+ //
+ // Set and used by the orthogonal routing code. Note the first value
+ // in the pair doesn't correspond to the segment index containing the
+ // checkpoint, but rather the segment or bendpoint on which it lies.
+ // 0 if on ps[0]
+ // 1 if on line ps[0]-ps[1]
+ // 2 if on ps[1]
+ // 3 if on line ps[1]-ps[2]
+ // etc.
+ std::vector<std::pair<size_t, Point> > checkpointsOnRoute;
+
+ // Returns true if at least one checkpoint lies on the line segment
+ // or at either end of it. An indexModifier of +1 will cause it to
+ // ignore a checkpoint on the corner at the start of the segment and
+ // -1 will cause it to do the same for the corner at the end of the
+ // segment.
+ std::vector<Point> checkpointsOnSegment(size_t segmentLowerIndex,
+ int indexModifier = 0) const;
+};
+
+
+//! @brief A multi-segment line, represented with the Polygon class.
+//!
+typedef Polygon PolyLine;
+
+
+//! @brief A Polygon which just references its points from other Polygons.
+//!
+//! This type of Polygon is used to accurately represent cluster boundaries
+//! made up from the corner points of shapes.
+//!
+class AVOID_EXPORT ReferencingPolygon : public PolygonInterface
+{
+ public:
+ ReferencingPolygon();
+ ReferencingPolygon(const Polygon& poly, const Router *router);
+ void clear(void);
+ bool empty(void) const;
+ size_t size(void) const;
+ int id(void) const;
+ const Point& at(size_t index) const;
+
+ int _id;
+ std::vector<std::pair<const Polygon *, unsigned short> > psRef;
+ std::vector<Point> psPoints;
+};
+
+
+//! @brief A Rectangle, a simpler way to define the polygon for square or
+//! rectangular shapes.
+//!
+class AVOID_EXPORT Rectangle : public Polygon
+{
+ public:
+ //! @brief Constructs a rectangular polygon given two opposing
+ //! corner points.
+ //!
+ //! @param[in] topLeft The first corner point of the rectangle.
+ //! @param[in] bottomRight The opposing corner point of the rectangle.
+ //!
+ Rectangle(const Point& topLeft, const Point& bottomRight);
+
+ //! @brief Constructs a rectangular polygon given the centre, width
+ //! and height.
+ //!
+ //! @param[in] centre The centre of the rectangle, specified as
+ //! a point.
+ //! @param[in] width The width of the rectangle.
+ //! @param[in] height The height of the rectangle.
+ //!
+ Rectangle(const Point& centre, const double width, const double height);
+};
+
+
+}
+
+#endif
diff --git a/src/3rdparty/adaptagrams/libavoid/graph.cpp b/src/3rdparty/adaptagrams/libavoid/graph.cpp
new file mode 100644
index 0000000..5169ddb
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/graph.cpp
@@ -0,0 +1,785 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2011 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+
+#include <cmath>
+
+#include "libavoid/debug.h"
+#include "libavoid/graph.h"
+#include "libavoid/connector.h"
+#include "libavoid/geometry.h"
+#include "libavoid/timer.h"
+#include "libavoid/vertices.h"
+#include "libavoid/router.h"
+#include "libavoid/assertions.h"
+
+
+using std::pair;
+
+namespace Avoid {
+
+
+EdgeInf::EdgeInf(VertInf *v1, VertInf *v2, const bool orthogonal)
+ : lstPrev(nullptr),
+ lstNext(nullptr),
+ m_router(nullptr),
+ m_blocker(0),
+ m_added(false),
+ m_visible(false),
+ m_orthogonal(orthogonal),
+ m_isHyperedgeSegment(false),
+ m_disabled(false),
+ m_vert1(v1),
+ m_vert2(v2),
+ m_dist(-1)
+{
+ // Not passed nullptr values.
+ COLA_ASSERT(v1 && v2);
+
+ // We are in the same instance
+ COLA_ASSERT(m_vert1->_router == m_vert2->_router);
+ m_router = m_vert1->_router;
+
+ m_conns.clear();
+}
+
+
+EdgeInf::~EdgeInf()
+{
+ if (m_added)
+ {
+ makeInactive();
+ }
+}
+
+
+// Gives an order value between 0 and 3 for the point c, given the last
+// segment was from a to b. Returns the following value:
+// 0 : Point c is directly backwards from point b.
+// 1 : Point c is a left-hand 90 degree turn.
+// 2 : Point c is a right-hand 90 degree turn.
+// 3 : Point c is straight ahead (collinear).
+// 4 : Point c is not orthogonally positioned.
+//
+static inline int orthogTurnOrder(const Point& a, const Point& b,
+ const Point& c)
+{
+ if ( ((c.x != b.x) && (c.y != b.y)) || ((a.x != b.x) && (a.y != b.y)) )
+ {
+ // Not orthogonally positioned.
+ return 4;
+ }
+
+ int direction = vecDir(a, b, c);
+
+ if (direction > 0)
+ {
+ // Counterclockwise := left
+ return 1;
+ }
+ else if (direction < 0)
+ {
+ // Clockwise := right
+ return 2;
+ }
+
+ if (b.x == c.x)
+ {
+ if ( ((a.y < b.y) && (c.y < b.y)) ||
+ ((a.y > b.y) && (c.y > b.y)) )
+ {
+ // Behind.
+ return 0;
+ }
+ }
+ else
+ {
+ if ( ((a.x < b.x) && (c.x < b.x)) ||
+ ((a.x > b.x) && (c.x > b.x)) )
+ {
+ // Behind.
+ return 0;
+ }
+ }
+
+ // Ahead.
+ return 3;
+}
+
+
+// Returns a less than operation for a set exploration order for orthogonal
+// searching. Forward, then left, then right. Or if there is no previous
+// point, then the order is north, east, south, then west.
+// Note: This method assumes the two Edges that share a common point.
+bool EdgeInf::rotationLessThan(const VertInf *lastV, const EdgeInf *rhs) const
+{
+ if ((m_vert1 == rhs->m_vert1) && (m_vert2 == rhs->m_vert2))
+ {
+ // Effectively the same visibility edge, so they are equal.
+ return false;
+ }
+ VertInf *lhsV = nullptr, *rhsV = nullptr, *commonV = nullptr;
+
+ // Determine common Point and the comparison point on the left- and
+ // the right-hand-side.
+ if (m_vert1 == rhs->m_vert1)
+ {
+ commonV = m_vert1;
+ lhsV = m_vert2;
+ rhsV = rhs->m_vert2;
+ }
+ else if (m_vert1 == rhs->m_vert2)
+ {
+ commonV = m_vert1;
+ lhsV = m_vert2;
+ rhsV = rhs->m_vert1;
+ }
+ else if (m_vert2 == rhs->m_vert1)
+ {
+ commonV = m_vert2;
+ lhsV = m_vert1;
+ rhsV = rhs->m_vert2;
+ }
+ else if (m_vert2 == rhs->m_vert2)
+ {
+ commonV = m_vert2;
+ lhsV = m_vert1;
+ rhsV = rhs->m_vert1;
+ }
+
+ const Point& lhsPt = lhsV->point;
+ const Point& rhsPt = rhsV->point;
+ const Point& commonPt = commonV->point;
+
+ // If no lastPt, use one directly to the left;
+ Point lastPt = (lastV) ? lastV->point : Point(commonPt.x - 10, commonPt.y);
+
+ int lhsVal = orthogTurnOrder(lastPt, commonPt, lhsPt);
+ int rhsVal = orthogTurnOrder(lastPt, commonPt, rhsPt);
+
+ return lhsVal < rhsVal;
+}
+
+
+void EdgeInf::makeActive(void)
+{
+ COLA_ASSERT(m_added == false);
+
+ if (m_orthogonal)
+ {
+ COLA_ASSERT(m_visible);
+ m_router->visOrthogGraph.addEdge(this);
+ m_pos1 = m_vert1->orthogVisList.insert(m_vert1->orthogVisList.begin(), this);
+ m_vert1->orthogVisListSize++;
+ m_pos2 = m_vert2->orthogVisList.insert(m_vert2->orthogVisList.begin(), this);
+ m_vert2->orthogVisListSize++;
+ }
+ else
+ {
+ if (m_visible)
+ {
+ m_router->visGraph.addEdge(this);
+ m_pos1 = m_vert1->visList.insert(m_vert1->visList.begin(), this);
+ m_vert1->visListSize++;
+ m_pos2 = m_vert2->visList.insert(m_vert2->visList.begin(), this);
+ m_vert2->visListSize++;
+ }
+ else // if (invisible)
+ {
+ m_router->invisGraph.addEdge(this);
+ m_pos1 = m_vert1->invisList.insert(m_vert1->invisList.begin(), this);
+ m_vert1->invisListSize++;
+ m_pos2 = m_vert2->invisList.insert(m_vert2->invisList.begin(), this);
+ m_vert2->invisListSize++;
+ }
+ }
+ m_added = true;
+}
+
+
+void EdgeInf::makeInactive(void)
+{
+ COLA_ASSERT(m_added == true);
+
+ if (m_orthogonal)
+ {
+ COLA_ASSERT(m_visible);
+ m_router->visOrthogGraph.removeEdge(this);
+ m_vert1->orthogVisList.erase(m_pos1);
+ m_vert1->orthogVisListSize--;
+ m_vert2->orthogVisList.erase(m_pos2);
+ m_vert2->orthogVisListSize--;
+ }
+ else
+ {
+ if (m_visible)
+ {
+ m_router->visGraph.removeEdge(this);
+ m_vert1->visList.erase(m_pos1);
+ m_vert1->visListSize--;
+ m_vert2->visList.erase(m_pos2);
+ m_vert2->visListSize--;
+ }
+ else // if (invisible)
+ {
+ m_router->invisGraph.removeEdge(this);
+ m_vert1->invisList.erase(m_pos1);
+ m_vert1->invisListSize--;
+ m_vert2->invisList.erase(m_pos2);
+ m_vert2->invisListSize--;
+ }
+ }
+ m_blocker = 0;
+ m_conns.clear();
+ m_added = false;
+}
+
+
+void EdgeInf::setDist(double dist)
+{
+ //COLA_ASSERT(dist != 0);
+
+ if (m_added && !m_visible)
+ {
+ makeInactive();
+ COLA_ASSERT(!m_added);
+ }
+ if (!m_added)
+ {
+ m_visible = true;
+ makeActive();
+ }
+ m_dist = dist;
+ m_blocker = 0;
+}
+
+
+void EdgeInf::setMtstDist(const double joinCost)
+{
+ m_mtst_dist = joinCost;
+}
+
+double EdgeInf::mtstDist(void) const
+{
+ return m_mtst_dist;
+}
+
+bool EdgeInf::isHyperedgeSegment(void) const
+{
+ return m_isHyperedgeSegment;
+}
+
+bool EdgeInf::isDisabled(void) const
+{
+ return m_disabled;
+}
+
+void EdgeInf::setDisabled(const bool disabled)
+{
+ m_disabled = disabled;
+}
+
+void EdgeInf::setHyperedgeSegment(const bool hyperedge)
+{
+ m_isHyperedgeSegment = hyperedge;
+}
+
+bool EdgeInf::added(void)
+{
+ return m_added;
+}
+
+int EdgeInf::blocker(void) const
+{
+ return m_blocker;
+}
+
+void EdgeInf::alertConns(void)
+{
+ FlagList::iterator finish = m_conns.end();
+ for (FlagList::iterator i = m_conns.begin(); i != finish; ++i)
+ {
+ *(*i) = true;
+ }
+ m_conns.clear();
+}
+
+
+void EdgeInf::addConn(bool *flag)
+{
+ m_conns.push_back(flag);
+}
+
+
+void EdgeInf::addCycleBlocker(void)
+{
+ // Needs to be in invisibility graph.
+ addBlocker(-1);
+}
+
+
+void EdgeInf::addBlocker(int b)
+{
+ COLA_ASSERT(m_router->InvisibilityGrph);
+
+ if (m_added && m_visible)
+ {
+ makeInactive();
+ COLA_ASSERT(!m_added);
+ }
+ if (!m_added)
+ {
+ m_visible = false;
+ makeActive();
+ }
+ m_dist = 0;
+ m_blocker = b;
+}
+
+
+pair<VertID, VertID> EdgeInf::ids(void) const
+{
+ return std::make_pair(m_vert1->id, m_vert2->id);
+}
+
+
+pair<Point, Point> EdgeInf::points(void) const
+{
+ return std::make_pair(m_vert1->point, m_vert2->point);
+}
+
+
+void EdgeInf::db_print(void)
+{
+ db_printf("Edge(");
+ m_vert1->id.db_print();
+ db_printf(",");
+ m_vert2->id.db_print();
+ db_printf(")\n");
+}
+
+
+void EdgeInf::checkVis(void)
+{
+ if (m_added && !m_visible)
+ {
+ db_printf("\tChecking visibility for existing invisibility edge..."
+ "\n\t\t");
+ db_print();
+ }
+ else if (m_added && m_visible)
+ {
+ db_printf("\tChecking visibility for existing visibility edge..."
+ "\n\t\t");
+ db_print();
+ }
+
+ int blocker = 0;
+ bool cone1 = true;
+ bool cone2 = true;
+
+ VertInf *i = m_vert1;
+ VertInf *j = m_vert2;
+ const VertID& iID = i->id;
+ const VertID& jID = j->id;
+ const Point& iPoint = i->point;
+ const Point& jPoint = j->point;
+
+ m_router->st_checked_edges++;
+
+ if (!(iID.isConnPt()))
+ {
+ cone1 = inValidRegion(m_router->IgnoreRegions, i->shPrev->point,
+ iPoint, i->shNext->point, jPoint);
+ }
+ else if (m_router->IgnoreRegions == false)
+ {
+ // If Ignoring regions then this case is already caught by
+ // the invalid regions, so only check it when not ignoring
+ // regions.
+ ShapeSet& ss = m_router->contains[iID];
+
+ if (!(jID.isConnPt()) && (ss.find(jID.objID) != ss.end()))
+ {
+ db_printf("1: Edge of bounding shape\n");
+ // Don't even check this edge, it should be zero,
+ // since a point in a shape can't see it's corners
+ cone1 = false;
+ }
+ }
+
+ if (cone1)
+ {
+ // If outside the first cone, don't even bother checking.
+ if (!(jID.isConnPt()))
+ {
+ cone2 = inValidRegion(m_router->IgnoreRegions, j->shPrev->point,
+ jPoint, j->shNext->point, iPoint);
+ }
+ else if (m_router->IgnoreRegions == false)
+ {
+ // If Ignoring regions then this case is already caught by
+ // the invalid regions, so only check it when not ignoring
+ // regions.
+ ShapeSet& ss = m_router->contains[jID];
+
+ if (!(iID.isConnPt()) && (ss.find(iID.objID) != ss.end()))
+ {
+ db_printf("2: Edge of bounding shape\n");
+ // Don't even check this edge, it should be zero,
+ // since a point in a shape can't see it's corners
+ cone2 = false;
+ }
+ }
+ }
+
+ if (cone1 && cone2 && ((blocker = firstBlocker()) == 0))
+ {
+
+ // if i and j see each other, add edge
+ db_printf("\tSetting visibility edge... \n\t\t");
+ db_print();
+
+ double d = euclideanDist(iPoint, jPoint);
+
+ setDist(d);
+
+ }
+ else if (m_router->InvisibilityGrph)
+ {
+#if 0
+ db_printf("%d, %d, %d\n", cone1, cone2, blocker);
+ db_printf("\t(%d, %d)--(%d, %d)\n", (int) iInfo.point.x,
+ (int) iInfo.point.y, (int) jInfo.point.x,
+ (int) jInfo.point.y);
+#endif
+
+ // if i and j can't see each other, add blank edge
+ db_printf("\tSetting invisibility edge... \n\t\t");
+ db_print();
+ addBlocker(blocker);
+ }
+}
+
+
+int EdgeInf::firstBlocker(void)
+{
+ ShapeSet ss = ShapeSet();
+
+ Point& pti = m_vert1->point;
+ Point& ptj = m_vert2->point;
+ VertID& iID = m_vert1->id;
+ VertID& jID = m_vert2->id;
+
+ ContainsMap &contains = m_router->contains;
+ if (iID.isConnPt())
+ {
+ ss.insert(contains[iID].begin(), contains[iID].end());
+ }
+ if (jID.isConnPt())
+ {
+ ss.insert(contains[jID].begin(), contains[jID].end());
+ }
+
+ VertInf *last = m_router->vertices.end();
+ unsigned int lastId = 0;
+ bool seenIntersectionAtEndpoint = false;
+ for (VertInf *k = m_router->vertices.shapesBegin(); k != last; )
+ {
+ VertID kID = k->id;
+ if (k->id == dummyOrthogID)
+ {
+ // Don't include orthogonal dummy vertices.
+ k = k->lstNext;
+ continue;
+ }
+ if (kID.objID != lastId)
+ {
+ if ((ss.find(kID.objID) != ss.end()))
+ {
+ unsigned int shapeID = kID.objID;
+ db_printf("Endpoint is inside shape %u so ignore shape "
+ "edges.\n", kID.objID);
+ // One of the endpoints is inside this shape so ignore it.
+ while ((k != last) && (k->id.objID == shapeID))
+ {
+ // And skip the other vertices from this shape.
+ k = k->lstNext;
+ }
+ continue;
+ }
+ seenIntersectionAtEndpoint = false;
+ lastId = kID.objID;
+ }
+ Point& kPoint = k->point;
+ Point& kPrevPoint = k->shPrev->point;
+ if (segmentShapeIntersect(pti, ptj, kPrevPoint, kPoint,
+ seenIntersectionAtEndpoint))
+ {
+ ss.clear();
+ return kID.objID;
+ }
+ k = k->lstNext;
+ }
+ ss.clear();
+ return 0;
+}
+
+
+bool EdgeInf::isBetween(VertInf *i, VertInf *j)
+{
+ if ( ((i == m_vert1) && (j == m_vert2)) ||
+ ((i == m_vert2) && (j == m_vert1)) )
+ {
+ return true;
+ }
+ return false;
+}
+
+
+ // Returns true if this edge is a vertical or horizontal line segment.
+bool EdgeInf::isOrthogonal(void) const
+{
+ return ((m_vert1->point.x == m_vert2->point.x) ||
+ (m_vert1->point.y == m_vert2->point.y));
+}
+
+
+bool EdgeInf::isDummyConnection(void) const
+{
+ // This is a dummy edge from a shape centre to
+ // a set of its ShapeConnectionPins.
+ return ((m_vert1->id.isConnectionPin() && m_vert2->id.isConnPt()) ||
+ (m_vert2->id.isConnectionPin() && m_vert1->id.isConnPt()));
+}
+
+
+VertInf *EdgeInf::otherVert(const VertInf *vert) const
+{
+ COLA_ASSERT((vert == m_vert1) || (vert == m_vert2));
+
+ return (vert == m_vert1) ? m_vert2 : m_vert1;
+}
+
+
+EdgeInf *EdgeInf::checkEdgeVisibility(VertInf *i, VertInf *j, bool knownNew)
+{
+ // This is for polyline routing, so check we're not
+ // considering orthogonal vertices.
+ COLA_ASSERT(i->id != dummyOrthogID);
+ COLA_ASSERT(j->id != dummyOrthogID);
+
+ Router *router = i->_router;
+ EdgeInf *edge = nullptr;
+
+ if (knownNew)
+ {
+ COLA_ASSERT(existingEdge(i, j) == nullptr);
+ edge = new EdgeInf(i, j);
+ }
+ else
+ {
+ edge = existingEdge(i, j);
+ if (edge == nullptr)
+ {
+ edge = new EdgeInf(i, j);
+ }
+ }
+ edge->checkVis();
+ if (!(edge->m_added) && !(router->InvisibilityGrph))
+ {
+ delete edge;
+ edge = nullptr;
+ }
+
+ return edge;
+}
+
+
+ // XXX: This function is inefficient, and shouldn't even really be
+ // required.
+EdgeInf *EdgeInf::existingEdge(VertInf *i, VertInf *j)
+{
+ VertInf *selected = nullptr;
+
+ // Look through poly-line visibility edges.
+ selected = (i->visListSize <= j->visListSize) ? i : j;
+ EdgeInfList& visList = selected->visList;
+ EdgeInfList::const_iterator finish = visList.end();
+ for (EdgeInfList::const_iterator edge = visList.begin(); edge != finish;
+ ++edge)
+ {
+ if ((*edge)->isBetween(i, j))
+ {
+ return (*edge);
+ }
+ }
+
+ // Look through orthogonal visibility edges.
+ selected = (i->orthogVisListSize <= j->orthogVisListSize) ? i : j;
+ EdgeInfList& orthogVisList = selected->orthogVisList;
+ finish = orthogVisList.end();
+ for (EdgeInfList::const_iterator edge = orthogVisList.begin();
+ edge != finish; ++edge)
+ {
+ if ((*edge)->isBetween(i, j))
+ {
+ return (*edge);
+ }
+ }
+
+ // Look through poly-line invisibility edges.
+ selected = (i->invisListSize <= j->invisListSize) ? i : j;
+ EdgeInfList& invisList = selected->invisList;
+ finish = invisList.end();
+ for (EdgeInfList::const_iterator edge = invisList.begin(); edge != finish;
+ ++edge)
+ {
+ if ((*edge)->isBetween(i, j))
+ {
+ return (*edge);
+ }
+ }
+
+ return nullptr;
+}
+
+
+//===========================================================================
+
+
+EdgeList::EdgeList(bool orthogonal)
+ : m_orthogonal(orthogonal),
+ m_first_edge(nullptr),
+ m_last_edge(nullptr),
+ m_count(0)
+{
+}
+
+
+EdgeList::~EdgeList()
+{
+ clear();
+}
+
+
+void EdgeList::clear(void)
+{
+ while (m_first_edge)
+ {
+ // The Edge destructor results in EdgeList:::removeEdge() being called
+ // for this edge and m_first_edge being updated to the subsequent edge
+ // in the EdgeList.
+ delete m_first_edge;
+ }
+ COLA_ASSERT(m_count == 0);
+ m_last_edge = nullptr;
+}
+
+
+int EdgeList::size(void) const
+{
+ return m_count;
+}
+
+
+void EdgeList::addEdge(EdgeInf *edge)
+{
+ // Dummy connections for ShapeConnectionPins won't be orthogonal,
+ // even in the orthogonal visibility graph.
+ COLA_UNUSED(m_orthogonal);
+ COLA_ASSERT(!m_orthogonal || edge->isOrthogonal() ||
+ edge->isDummyConnection());
+
+ if (m_first_edge == nullptr)
+ {
+ COLA_ASSERT(m_last_edge == nullptr);
+
+ m_last_edge = edge;
+ m_first_edge = edge;
+
+ edge->lstPrev = nullptr;
+ edge->lstNext = nullptr;
+ }
+ else
+ {
+ COLA_ASSERT(m_last_edge != nullptr);
+
+ m_last_edge->lstNext = edge;
+ edge->lstPrev = m_last_edge;
+
+ m_last_edge = edge;
+
+ edge->lstNext = nullptr;
+ }
+ m_count++;
+}
+
+
+void EdgeList::removeEdge(EdgeInf *edge)
+{
+ if (edge->lstPrev)
+ {
+ edge->lstPrev->lstNext = edge->lstNext;
+ }
+ if (edge->lstNext)
+ {
+ edge->lstNext->lstPrev = edge->lstPrev;
+ }
+ if (edge == m_last_edge)
+ {
+ m_last_edge = edge->lstPrev;
+ if (edge == m_first_edge)
+ {
+ m_first_edge = nullptr;
+ }
+ }
+ else if (edge == m_first_edge)
+ {
+ m_first_edge = edge->lstNext;
+ }
+
+
+ edge->lstPrev = nullptr;
+ edge->lstNext = nullptr;
+
+ m_count--;
+}
+
+
+EdgeInf *EdgeList::begin(void)
+{
+ return m_first_edge;
+}
+
+
+EdgeInf *EdgeList::end(void)
+{
+ return nullptr;
+}
+
+
+}
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/graph.h b/src/3rdparty/adaptagrams/libavoid/graph.h
new file mode 100644
index 0000000..9e1a7a3
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/graph.h
@@ -0,0 +1,135 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2011 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+
+#ifndef AVOID_GRAPH_H
+#define AVOID_GRAPH_H
+
+
+#include <cassert>
+#include <list>
+#include <utility>
+#include "libavoid/vertices.h"
+
+namespace Avoid {
+
+
+class ConnRef;
+class Router;
+
+
+typedef std::list<int> ShapeList;
+typedef std::list<bool *> FlagList;
+
+
+class EdgeInf
+{
+ public:
+ EdgeInf(VertInf *v1, VertInf *v2, const bool orthogonal = false);
+ ~EdgeInf();
+ inline double getDist(void)
+ {
+ return m_dist;
+ }
+ void setDist(double dist);
+ void alertConns(void);
+ void addConn(bool *flag);
+ void addCycleBlocker(void);
+ void addBlocker(int b);
+ bool added(void);
+ bool isOrthogonal(void) const;
+ bool isDummyConnection(void) const;
+ bool isDisabled(void) const;
+ void setDisabled(const bool disabled);
+ bool rotationLessThan(const VertInf* last, const EdgeInf *rhs) const;
+ std::pair<VertID, VertID> ids(void) const;
+ std::pair<Point, Point> points(void) const;
+ void db_print(void);
+ void checkVis(void);
+ VertInf *otherVert(const VertInf *vert) const;
+ static EdgeInf *checkEdgeVisibility(VertInf *i, VertInf *j,
+ bool knownNew = false);
+ static EdgeInf *existingEdge(VertInf *i, VertInf *j);
+ int blocker(void) const;
+
+ bool isHyperedgeSegment(void) const;
+ void setHyperedgeSegment(const bool hyperedge);
+ double mtstDist(void) const;
+ void setMtstDist(const double joinCost);
+
+ EdgeInf *lstPrev;
+ EdgeInf *lstNext;
+ private:
+ friend class MinimumTerminalSpanningTree;
+ friend class VertInf;
+
+ void makeActive(void);
+ void makeInactive(void);
+ int firstBlocker(void);
+ bool isBetween(VertInf *i, VertInf *j);
+
+ Router *m_router;
+ int m_blocker;
+ bool m_added;
+ bool m_visible;
+ bool m_orthogonal;
+ bool m_isHyperedgeSegment;
+ bool m_disabled;
+ VertInf *m_vert1;
+ VertInf *m_vert2;
+ EdgeInfList::iterator m_pos1;
+ EdgeInfList::iterator m_pos2;
+ FlagList m_conns;
+ double m_dist;
+ double m_mtst_dist;
+};
+
+
+class EdgeList
+{
+ public:
+ friend class EdgeInf;
+ EdgeList(bool orthogonal = false);
+ ~EdgeList();
+ void clear(void);
+ EdgeInf *begin(void);
+ EdgeInf *end(void);
+ int size(void) const;
+ private:
+ void addEdge(EdgeInf *edge);
+ void removeEdge(EdgeInf *edge);
+
+ bool m_orthogonal;
+ EdgeInf *m_first_edge;
+ EdgeInf *m_last_edge;
+ unsigned int m_count;
+};
+
+
+}
+
+
+#endif
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/hyperedge.cpp b/src/3rdparty/adaptagrams/libavoid/hyperedge.cpp
new file mode 100644
index 0000000..d6f2a40
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/hyperedge.cpp
@@ -0,0 +1,388 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2011-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+#include "libavoid/hyperedge.h"
+#include "libavoid/hyperedgetree.h"
+#include "libavoid/mtst.h"
+#include "libavoid/junction.h"
+#include "libavoid/connector.h"
+#include "libavoid/vertices.h"
+#include "libavoid/connend.h"
+#include "libavoid/shape.h"
+#include "libavoid/router.h"
+#include "libavoid/assertions.h"
+#include "libavoid/debughandler.h"
+#include "libavoid/debug.h"
+
+
+namespace Avoid {
+
+HyperedgeRerouter::HyperedgeRerouter()
+ : m_router(nullptr)
+{
+}
+
+void HyperedgeRerouter::setRouter(Router *router)
+{
+ m_router = router;
+}
+
+size_t HyperedgeRerouter::registerHyperedgeForRerouting(
+ ConnEndList terminals)
+{
+ m_terminals_vector.push_back(terminals);
+ m_root_junction_vector.push_back(nullptr);
+
+ return m_terminals_vector.size() - 1;
+}
+
+size_t HyperedgeRerouter::registerHyperedgeForRerouting(
+ JunctionRef *junction)
+{
+ m_terminals_vector.push_back(ConnEndList());
+ m_root_junction_vector.push_back(junction);
+
+ return m_terminals_vector.size() - 1;
+}
+
+size_t HyperedgeRerouter::count(void) const
+{
+ return m_terminals_vector.size();
+}
+
+HyperedgeNewAndDeletedObjectLists HyperedgeRerouter::newAndDeletedObjectLists(
+ size_t index) const
+{
+ COLA_ASSERT(index <= count());
+
+ HyperedgeNewAndDeletedObjectLists result;
+
+ result.newJunctionList = m_new_junctions_vector[index];
+ result.deletedJunctionList = m_deleted_junctions_vector[index];
+ result.newConnectorList = m_new_connectors_vector[index];
+ result.deletedConnectorList = m_deleted_connectors_vector[index];
+
+ return result;
+}
+
+
+void HyperedgeRerouter::outputInstanceToSVG(FILE *fp)
+{
+ if (count() == 0)
+ {
+ return;
+ }
+
+ fprintf(fp, " HyperedgeRerouter *hyperedgeRerouter = router->hyperedgeRerouter();\n");
+ const size_t num_hyperedges = count();
+ for (size_t i = 0; i < num_hyperedges; ++i)
+ {
+ if (m_root_junction_vector[i])
+ {
+ fprintf(fp, " hyperedgeRerouter->registerHyperedgeForRerouting(junctionRef%u);\n",
+ m_root_junction_vector[i]->id());
+ }
+ else
+ {
+ fprintf(fp, " ConnEndList heConnList%u;\n", (unsigned int) i);
+ for (ConnEndList::const_iterator it = m_terminals_vector[i].begin();
+ it != m_terminals_vector[i].end(); ++it)
+ {
+ (*it).outputCode(fp, "heEnd");
+ fprintf(fp, " heConnList%u.push_back(heEndPt);\n",
+ (unsigned int) i);
+ }
+ fprintf(fp, " hyperedgeRerouter->registerHyperedgeForRerouting(heConnList%u);\n",
+ (unsigned int) i);
+
+ }
+ }
+ fprintf(fp, "\n");
+}
+
+
+// Follow connected junctions and connectors from the given connector to
+// determine the hyperedge topology, saving objects to the deleted-objects
+// vectors as we go.
+bool HyperedgeRerouter::findAttachedObjects(size_t index,
+ ConnRef *connector, JunctionRef *ignore, ConnRefSet& hyperedgeConns)
+{
+ bool validHyperedge = false;
+
+ connector->assignConnectionPinVisibility(true);
+
+ m_deleted_connectors_vector[index].push_back(connector);
+ hyperedgeConns.insert(connector);
+
+ std::pair<Obstacle *, Obstacle *> anchors = connector->endpointAnchors();
+ JunctionRef *jFirst = dynamic_cast<JunctionRef *> (anchors.first);
+ JunctionRef *jSecond = dynamic_cast<JunctionRef *> (anchors.second);
+
+ if (jFirst)
+ {
+ // If attached to a junction and not one we've explored, then continue.
+ if (jFirst != ignore)
+ {
+ validHyperedge |= findAttachedObjects(index, jFirst, connector, hyperedgeConns);
+ }
+ }
+ else
+ {
+ // If its an endpoint, then record the vertex for this endpoint.
+ COLA_ASSERT(connector->m_src_vert);
+ m_terminal_vertices_vector[index].insert(connector->m_src_vert);
+ }
+
+ if (jSecond)
+ {
+ // If attached to a junction and not one we've explored, then continue.
+ if (jSecond != ignore)
+ {
+ validHyperedge |= findAttachedObjects(index, jSecond, connector, hyperedgeConns);
+ }
+ }
+ else
+ {
+ // If its an endpoint, then record the vertex for this endpoint.
+ COLA_ASSERT(connector->m_dst_vert);
+ m_terminal_vertices_vector[index].insert(connector->m_dst_vert);
+ }
+ return validHyperedge;
+}
+
+
+// Follow connected junctions and connectors from the given junction to
+// determine the hyperedge topology, saving objects to the deleted-objects
+// vectors as we go.
+bool HyperedgeRerouter::findAttachedObjects(size_t index,
+ JunctionRef *junction, ConnRef *ignore, ConnRefSet& hyperedgeConns)
+{
+ bool validHyperedge = false;
+
+ m_deleted_junctions_vector[index].push_back(junction);
+
+ ConnRefList connectors = junction->attachedConnectors();
+
+ if (connectors.size() > 2)
+ {
+ // A valid hyperedge must have at least one junction with three
+ // connectors attached, i.e., more than two endpoints.
+ validHyperedge |= true;
+ }
+
+ for (ConnRefList::iterator curr = connectors.begin();
+ curr != connectors.end(); ++curr)
+ {
+ if (*curr == ignore)
+ {
+ continue;
+ }
+
+ COLA_ASSERT(*curr != nullptr);
+ validHyperedge |= findAttachedObjects(index, (*curr), junction, hyperedgeConns);
+ }
+ return validHyperedge;
+}
+
+
+// Populate the deleted-object vectors with all the connectors and junctions
+// that form the registered hyperedges. Then return the set of all these
+// connectors so they can be ignored for individual rerouting.
+ConnRefSet HyperedgeRerouter::calcHyperedgeConnectors(void)
+{
+ COLA_ASSERT(m_router != nullptr);
+
+ ConnRefSet allRegisteredHyperedgeConns;
+
+ // Clear the deleted-object vectors. We populate them here if necessary.
+ m_deleted_junctions_vector.clear();
+ m_deleted_junctions_vector.resize(count());
+ m_deleted_connectors_vector.clear();
+ m_deleted_connectors_vector.resize(count());
+
+ m_terminal_vertices_vector.clear();
+ m_terminal_vertices_vector.resize(count());
+ m_added_vertices.clear();
+
+ // Populate the deleted-object vectors.
+ const size_t num_hyperedges = count();
+ for (size_t i = 0; i < num_hyperedges; ++i)
+ {
+ if (m_root_junction_vector[i])
+ {
+ // Follow objects attached to junction to find the hyperedge.
+ bool valid = findAttachedObjects(i, m_root_junction_vector[i], nullptr,
+ allRegisteredHyperedgeConns);
+ if (!valid)
+ {
+ err_printf("Warning: Hyperedge %d registered with "
+ "HyperedgeRerouter is invalid and will be "
+ "ignored.\n", (int) i);
+ // Hyperedge is invalid. Clear the terminals and other info
+ // so it will be ignored, and rerouted as a normal set of
+ // connectors.
+ m_terminals_vector[i].clear();
+ m_terminal_vertices_vector[i].clear();
+ m_deleted_junctions_vector[i].clear();
+ m_deleted_connectors_vector[i].clear();
+ }
+ continue;
+ }
+
+ // Alternatively, we have a set of ConnEnds, so store the
+ // corresponding terminals
+ std::pair<bool, VertInf *> maybeNewVertex;
+ for (ConnEndList::const_iterator it = m_terminals_vector[i].begin();
+ it != m_terminals_vector[i].end(); ++it)
+ {
+ maybeNewVertex = it->getHyperedgeVertex(m_router);
+ COLA_ASSERT(maybeNewVertex.second != nullptr);
+ m_terminal_vertices_vector[i].insert(maybeNewVertex.second);
+
+ if (maybeNewVertex.first)
+ {
+ // This is a newly created vertex. Remember it so we can
+ // free it and it's visibility edges later.
+ m_added_vertices.push_back(maybeNewVertex.second);
+ }
+ }
+ }
+
+ // Return these connectors that don't require rerouting.
+ return allRegisteredHyperedgeConns;
+}
+
+
+void HyperedgeRerouter::performRerouting(void)
+{
+ COLA_ASSERT(m_router != nullptr);
+
+ m_new_junctions_vector.clear();
+ m_new_junctions_vector.resize(count());
+ m_new_connectors_vector.clear();
+ m_new_connectors_vector.resize(count());
+
+#ifdef DEBUGHANDLER
+ if (m_router->debugHandler())
+ {
+ std::vector<Box> obstacleBoxes;
+ ObstacleList::iterator obstacleIt = m_router->m_obstacles.begin();
+ while (obstacleIt != m_router->m_obstacles.end())
+ {
+ Obstacle *obstacle = *obstacleIt;
+ JunctionRef *junction = dynamic_cast<JunctionRef *> (obstacle);
+ if (junction && ! junction->positionFixed())
+ {
+ // Junctions that are free to move are not treated as obstacles.
+ ++obstacleIt;
+ continue;
+ }
+ Box bbox = obstacle->routingBox();
+ obstacleBoxes.push_back(bbox);
+ ++obstacleIt;
+ }
+ m_router->debugHandler()->updateObstacleBoxes(obstacleBoxes);
+ }
+#endif
+
+ // For each hyperedge...
+ const size_t num_hyperedges = count();
+ for (size_t i = 0; i < num_hyperedges; ++i)
+ {
+ if (m_terminal_vertices_vector[i].empty())
+ {
+ // Invalid hyperedge, ignore.
+ continue;
+ }
+
+ // Execute the MTST method to find good junction positions and an
+ // initial path. A hyperedge tree will be built for the new route.
+ JunctionHyperedgeTreeNodeMap hyperedgeTreeJunctions;
+ MinimumTerminalSpanningTree mtst(m_router,
+ m_terminal_vertices_vector[i], &hyperedgeTreeJunctions);
+
+ // The older MTST construction method (faster, worse results).
+ //mtst.constructSequential();
+
+ // The preferred MTST construction method.
+ // Slightly slower, better quality results.
+ mtst.constructInterleaved();
+
+ HyperedgeTreeNode *treeRoot = mtst.rootJunction();
+ COLA_ASSERT(treeRoot);
+
+ // Fill in connector information and join them to junctions of endpoints
+ // of original connectors.
+ treeRoot->addConns(nullptr, m_router,
+ m_deleted_connectors_vector[i], nullptr);
+
+ // Output the list of new junctions and connectors from hyperedge tree.
+ treeRoot->listJunctionsAndConnectors(nullptr, m_new_junctions_vector[i],
+ m_new_connectors_vector[i]);
+
+ // Write paths from the hyperedge tree back into individual
+ // connector routes.
+ for (size_t pass = 0; pass < 2; ++pass)
+ {
+ treeRoot->writeEdgesToConns(nullptr, pass);
+ }
+
+ // Tell the router that we are deleting the objects used for the
+ // previous path for the hyperedge.
+ for (ConnRefList::iterator curr =
+ m_deleted_connectors_vector[i].begin();
+ curr != m_deleted_connectors_vector[i].end(); ++curr)
+ {
+ // Clear visibility assigned for connection pins.
+ (*curr)->assignConnectionPinVisibility(false);
+
+ m_router->deleteConnector(*curr);
+ }
+ for (JunctionRefList::iterator curr =
+ m_deleted_junctions_vector[i].begin();
+ curr != m_deleted_junctions_vector[i].end(); ++curr)
+ {
+ m_router->deleteJunction(*curr);
+ }
+ }
+
+ // Clear the input to this class, so that new objects can be registered
+ // for rerouting for the next time that transaction that is processed.
+ m_terminals_vector.clear();
+ m_root_junction_vector.clear();
+
+ // Free temporarily added vertices.
+ for (VertexList::iterator curr = m_added_vertices.begin();
+ curr != m_added_vertices.end(); ++curr)
+ {
+ (*curr)->removeFromGraph();
+ m_router->vertices.removeVertex(*curr);
+ delete *curr;
+ }
+ m_added_vertices.clear();
+}
+
+
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/hyperedge.h b/src/3rdparty/adaptagrams/libavoid/hyperedge.h
new file mode 100644
index 0000000..47ee42c
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/hyperedge.h
@@ -0,0 +1,223 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2011-2015 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+//! @file hyperedge.h
+//! @brief Contains the interface for the HyperedgeRerouter class.
+
+#ifndef AVOID_HYPEREDGE_H
+#define AVOID_HYPEREDGE_H
+
+#include <cstdio>
+#include <list>
+#include <vector>
+#include <set>
+
+#include "libavoid/dllexport.h"
+
+namespace Avoid {
+
+class ConnRef;
+class JunctionRef;
+class Router;
+class ConnEnd;
+class VertInf;
+
+//! @brief A list of ConnEnd objects.
+typedef std::list<ConnEnd> ConnEndList;
+
+//! @brief A list of ConnRef objects.
+typedef std::list<ConnRef *> ConnRefList;
+
+//! @brief A list of JunctionRef objects.
+typedef std::list<JunctionRef *> JunctionRefList;
+
+typedef std::list<VertInf *> VertexList;
+typedef std::set<ConnRef *> ConnRefSet;
+typedef std::set<VertInf *> VertexSet;
+
+typedef std::vector<JunctionRef *> JunctionRefVector;
+typedef std::vector<ConnEndList> ConnEndListVector;
+typedef std::vector<ConnRefList> ConnRefListVector;
+typedef std::vector<JunctionRefList> JunctionRefListVector;
+typedef std::vector<VertexSet> VertexSetVector;
+
+//! @brief The HyperedgeNewAndDeletedObjectLists class stores lists of
+//! objects created and deleted during hyperedge improvement.
+//!
+//! After hyperedge improvement, this information can be produced by calling
+//! the Router::newAndDeletedObjectListsFromHyperedgeImprovement() method.
+//!
+//! After hyperedge rerouting, this information can be produced by calling
+//! the HyperedgeRerouter::newAndDeletedObjectLists() method for each
+//! hyperedge being fully rerouted.
+//!
+//! The HyperedgeNewAndDeletedObjectLists::changedConnectorList attribute
+//! will only be used for hyperedge improvement and will always be empty
+//! for hyperedge rerouting.
+//!
+struct HyperedgeNewAndDeletedObjectLists
+{
+ //! A list of newly created junctions.
+ JunctionRefList newJunctionList;
+
+ //! A list of newly created connectors.
+ ConnRefList newConnectorList;
+
+ //! A list of deleted junctions.
+ JunctionRefList deletedJunctionList;
+
+ //! A list of deleted connectors.
+ ConnRefList deletedConnectorList;
+
+ //! A list of changed connectors.
+ ConnRefList changedConnectorList;
+};
+
+
+//! @brief The HyperedgeRerouter class is a convenience object that can be
+//! used to register hyperedges to be rerouted, improving the
+//! placement of their junctions and connector paths.
+//!
+//! To work with this class, you should get a copy from the router instance
+//! via a call to Router::hyperedgeRerouter().
+//!
+//! If you would like a particular hyperedge to be completely rerouted with
+//! new junction positions then you should register it with this class via a
+//! call to registerHyperedgeForRerouting. A hyperedge can either be
+//! specified as a set of terminal vertices, or as a single JunctionRef.
+//! Passing a JunctionRef will cause HyperedgeRerouter to follow the attached
+//! connectors and junctions to determine the hyperedge. When you register
+//! a hyperedge you get an index number that can be used to later find
+//! information about it.
+//!
+//! The rerouting will actually occur the next time the Router processes a
+//! transaction, see Router::processTransaction(). The rerouting will
+//! effectively create new junctions (JunctionRefs) and connectors (ConnRefs)
+//! for the hyperedge.
+//!
+//! Since hyperedges are composed of multiple connections and junction objects,
+//! rerouting a hyperedge can cause creation of new or deletion of existing
+//! connectors and/or junctions. Thus once the transaction has been completed
+//! you should call the newAndDeletedObjectLists() to get an object containing
+//! the lists of created and deleted junctions and connectors. After the
+//! transaction You should not use references to these deleted objects any
+//! more from your own code (since the router will free their memory at its
+//! convenience) and you should refer only to the unaffected objects and the
+//! new connectors and junctions.
+//!
+class AVOID_EXPORT HyperedgeRerouter
+{
+ public:
+ //! @brief Constructor for hyperedge rerouter object.
+ //!
+ //! @note You shouldn't create this object yourself. The Router
+ //! instance has one that you can request a reference to
+ //! via Router::hyperedgeRerouter().
+ //!
+ HyperedgeRerouter();
+
+ //! @brief Registers a hyperedge to be fully rerouted the next time
+ //! the router processes a transaction.
+ //!
+ //! @param[in] terminals The ConnEnds that form the endpoints of the
+ //! hyperedge.
+ //! @return An index that can be used to request information on the
+ //! resulting routing of the hyperedge.
+ //!
+ size_t registerHyperedgeForRerouting(ConnEndList terminals);
+
+ //! @brief Registers a hyperedge to be fully rerouted the next time
+ //! the router processes a transaction.
+ //!
+ //! In this case the connectors and junctions attached to the given
+ //! junction will be traversed to determine the endpoints of the
+ //! hyperedge. These endpoints will then be used for the rerouting.
+ //! The junctions and connectors forming the old route will be
+ //! deleted.
+ //!
+ //! @param[in] junction One of the junctions that forms the
+ //! hyperedge.
+ //! @return An index that can be used to request information on the
+ //! resulting routing of the hyperedge.
+ //!
+ size_t registerHyperedgeForRerouting(JunctionRef *junction);
+
+ //! @brief Returns a HyperedgeNewAndDeletedObjectLists detailing the
+ //! lists of junctions and connectors created and deleted
+ //! during hyperedge improvement.
+ //!
+ //! This method will only return information once the router has
+ //! processed the transaction. You should read this information
+ //! before processTransaction() is called again.
+ //!
+ //! After calling this you should no longer refer to any of the
+ //! objects in the "deleted" lists --- the router will delete these
+ //! and free their memory at its convenience.
+ //!
+ //! @param index The index of the hyperedge to return junctions for.
+ //! @return A HyperedgeNewAndDeletedObjectLists containing lists of
+ //! junctions and connectors created and deleted.
+ //!
+ HyperedgeNewAndDeletedObjectLists newAndDeletedObjectLists(
+ size_t index) const;
+
+ // @brief The number of hyperedges that are being or have been
+ // rerouted.
+ // @return The number of rerouted hyperedges.
+ //
+ size_t count(void) const;
+
+ private:
+ friend class Router;
+
+ // @brief Sets the router instance that this object operates on.
+ //
+ // @param[in] router The router instance to operate on.
+ //
+ void setRouter(Router *router);
+
+ ConnRefSet calcHyperedgeConnectors(void);
+ // Called by Router during processTransaction().
+ void performRerouting(void);
+ void outputInstanceToSVG(FILE *fp);
+ bool findAttachedObjects(size_t index, ConnRef *connector,
+ JunctionRef *ignore, ConnRefSet& hyperedgeConns);
+ bool findAttachedObjects(size_t index, JunctionRef *junction,
+ ConnRef *ignore, ConnRefSet& hyperedgeConns);
+
+ Router *m_router;
+ ConnEndListVector m_terminals_vector;
+ JunctionRefVector m_root_junction_vector;
+ JunctionRefListVector m_new_junctions_vector;
+ JunctionRefListVector m_deleted_junctions_vector;
+ ConnRefListVector m_new_connectors_vector;
+ ConnRefListVector m_deleted_connectors_vector;
+ VertexSetVector m_terminal_vertices_vector;
+ VertexList m_added_vertices;
+};
+
+
+}
+
+#endif
diff --git a/src/3rdparty/adaptagrams/libavoid/hyperedgeimprover.cpp b/src/3rdparty/adaptagrams/libavoid/hyperedgeimprover.cpp
new file mode 100644
index 0000000..bf7c357
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/hyperedgeimprover.cpp
@@ -0,0 +1,1232 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2009-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+#include <algorithm>
+#include <sstream>
+#include <iomanip>
+
+#include "libavoid/router.h"
+#include "libavoid/shape.h"
+#include "libavoid/junction.h"
+#include "libavoid/vpsc.h"
+#include "libavoid/assertions.h"
+#include "libavoid/hyperedgetree.h"
+#include "libavoid/hyperedgeimprover.h"
+#include "libavoid/scanline.h"
+#include "libavoid/debug.h"
+
+namespace Avoid {
+
+class HyperedgeShiftSegment : public ShiftSegment
+{
+ public:
+ HyperedgeShiftSegment(HyperedgeTreeNode *n1, HyperedgeTreeNode *n2,
+ const size_t dim, bool immovable)
+ : ShiftSegment(dim),
+ nodes((dim + 1) % 2),
+ isImmovable(immovable),
+ m_balance_count(0),
+ m_balance_count_set(false),
+ m_at_limit(false)
+ {
+ nodes.insert(n1);
+ nodes.insert(n2);
+ n1->shiftSegmentNodeSet = &nodes;
+ n2->shiftSegmentNodeSet = &nodes;
+
+ minSpaceLimit = -CHANNEL_MAX;
+ maxSpaceLimit = CHANNEL_MAX;
+ }
+ virtual ~HyperedgeShiftSegment()
+ {
+ for (OrderedHENodeSet::const_iterator curr = nodes.begin();
+ curr != nodes.end(); ++curr)
+ {
+ (*curr)->shiftSegmentNodeSet = nullptr;
+ }
+ }
+
+ Point& lowPoint(void)
+ {
+ return (*nodes.begin())->point;
+ }
+ Point& highPoint(void)
+ {
+ return (*nodes.rbegin())->point;
+ }
+ const Point& lowPoint(void) const
+ {
+ return (*nodes.begin())->point;
+ }
+ const Point& highPoint(void) const
+ {
+ return (*nodes.rbegin())->point;
+ }
+ // Counts the number of segments diverging on each side and returns
+ // a count: a negative number if there a more on the lower side,
+ // a positive number if there are more on the upper side, or zero if
+ // there are an equal number of segments.
+ void setBalanceCount(void)
+ {
+ size_t altDim = (dimension + 1) % 2;
+ m_next_pos_lower = minSpaceLimit;
+ m_next_pos_upper = maxSpaceLimit;
+ m_balance_count = 0;
+ if ( isImmovable )
+ {
+ m_balance_count_set = true;
+ return;
+ }
+ for (OrderedHENodeSet::const_iterator curr = nodes.begin();
+ curr != nodes.end(); ++curr)
+ {
+ const Point& currPoint = (*curr)->point;
+ for (std::list<HyperedgeTreeEdge *>::const_iterator currEdge =
+ (*curr)->edges.begin(); currEdge != (*curr)->edges.end();
+ ++currEdge)
+ {
+ const HyperedgeTreeNode *node = (*currEdge)->followFrom(*curr);
+ const Point& otherPoint = node->point;
+ if (currPoint[altDim] == otherPoint[altDim])
+ {
+ if (otherPoint[dimension] < currPoint[dimension])
+ {
+ m_next_pos_lower = std::max(m_next_pos_lower,
+ otherPoint[dimension]);
+ --m_balance_count;
+ }
+ else if (otherPoint[dimension] > currPoint[dimension])
+ {
+ m_next_pos_upper = std::min(m_next_pos_upper,
+ otherPoint[dimension]);
+ ++m_balance_count;
+ }
+ }
+ }
+ }
+ m_balance_count_set = true;
+ }
+ int balanceCount(void) const
+ {
+ COLA_ASSERT( m_balance_count_set );
+ return m_balance_count;
+ }
+ void adjustPosition(void)
+ {
+ COLA_ASSERT(m_balance_count_set);
+ COLA_ASSERT(m_balance_count != 0);
+
+ double newPos = (m_balance_count < 0) ?
+ m_next_pos_lower : m_next_pos_upper;
+ double limit = (m_balance_count < 0) ?
+ minSpaceLimit : maxSpaceLimit;
+ if (lowPoint()[dimension] == newPos)
+ {
+ // If aren't actually moving this segment, then mark it
+ // as at-limit.
+ // XXX This seems to be because of a segment with an
+ // incorrectly marked limit, possibly due to a
+ // junction positioned within a shape.
+ m_at_limit = true;
+ }
+
+ for (OrderedHENodeSet::iterator curr = nodes.begin();
+ curr != nodes.end(); ++curr)
+ {
+ (*curr)->point[dimension] = newPos;
+ }
+
+ if (newPos == limit)
+ {
+ m_at_limit = true;
+ }
+
+ // Add nodes from collapsed segments, in case they are not part of
+ // a segment that will be merged.
+ for (OrderedHENodeSet::iterator curr = nodes.begin();
+ curr != nodes.end(); ++curr)
+ {
+ Point& currPoint = (*curr)->point;
+ for (std::list<HyperedgeTreeEdge *>::iterator currEdge =
+ (*curr)->edges.begin(); currEdge != (*curr)->edges.end();
+ ++currEdge)
+ {
+ HyperedgeTreeNode *node = (*currEdge)->followFrom(*curr);
+ Point& otherPoint = node->point;
+ if (currPoint == otherPoint)
+ {
+ nodes.insert(node);
+ node->shiftSegmentNodeSet = &nodes;
+ }
+ }
+ }
+ }
+ bool overlapsWith(const ShiftSegment *rhs, const size_t dim) const
+ {
+ size_t altDim = (dim + 1) % 2;
+ const Point& lowPt = lowPoint();
+ const Point& highPt = highPoint();
+ const Point& rhsLowPt = rhs->lowPoint();
+ const Point& rhsHighPt = rhs->highPoint();
+ if ( (lowPt[altDim] <= rhsHighPt[altDim]) &&
+ (rhsLowPt[altDim] <= highPt[altDim]))
+ {
+ // The segments overlap.
+ if ( (minSpaceLimit <= rhs->maxSpaceLimit) &&
+ (rhs->minSpaceLimit <= maxSpaceLimit) )
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ bool immovable(void) const
+ {
+ return isImmovable;
+ }
+ bool settled(void) const
+ {
+ return isImmovable || m_at_limit || (balanceCount() == 0);
+ }
+ bool mergesWith(HyperedgeShiftSegment *other)
+ {
+ size_t altDim = (dimension + 1) % 2;
+ const Point& lowPt = lowPoint();
+ const Point& highPt = highPoint();
+ const Point& otherLowPt = other->lowPoint();
+ const Point& otherHighPt = other->highPoint();
+ if ( (lowPt[dimension] == otherLowPt[dimension]) &&
+ (lowPt[altDim] <= otherHighPt[altDim]) &&
+ (otherLowPt[altDim] <= highPt[altDim]))
+ {
+ isImmovable |= other->isImmovable;
+ m_at_limit |= m_at_limit;
+ minSpaceLimit = std::max(minSpaceLimit, other->minSpaceLimit);
+ maxSpaceLimit = std::min(maxSpaceLimit, other->maxSpaceLimit);
+ nodes.insert(other->nodes.begin(), other->nodes.end());
+ other->nodes.clear();
+ for (OrderedHENodeSet::iterator curr = nodes.begin();
+ curr != nodes.end(); ++curr)
+ {
+ (*curr)->shiftSegmentNodeSet = &nodes;
+ }
+ setBalanceCount();
+ return true;
+ }
+ setBalanceCount();
+ return false;
+ }
+
+ std::set<HyperedgeTreeNode *, CmpNodesInDim> nodes;
+ bool isImmovable;
+private:
+ int m_balance_count;
+ bool m_balance_count_set;
+ double m_next_pos_lower;
+ double m_next_pos_upper;
+ bool m_at_limit;
+};
+
+#if 0
+// UNUSED
+static bool CmpHyperedgeSegmentDirOrder(const ShiftSegment *lhsSuper,
+ const ShiftSegment *rhsSuper)
+{
+ const HyperedgeShiftSegment *lhs =
+ dynamic_cast<const HyperedgeShiftSegment *> (lhsSuper);
+ const HyperedgeShiftSegment *rhs =
+ dynamic_cast<const HyperedgeShiftSegment *> (rhsSuper);
+
+ return fabs(lhs->balanceCount()) > fabs(rhs->balanceCount());
+}
+#endif
+
+
+// Constructor.
+HyperedgeImprover::HyperedgeImprover()
+ : m_router(nullptr)
+{
+ clear();
+}
+
+void HyperedgeImprover::setRouter(Router *router)
+{
+ m_router = router;
+}
+
+void HyperedgeImprover::clear(void)
+{
+ m_hyperedge_tree_junctions.clear();
+ m_hyperedge_tree_roots.clear();
+ m_root_shift_segments.clear();
+ m_all_shift_segments.clear();
+ m_new_junctions.clear();
+ m_deleted_junctions.clear();
+ m_new_connectors.clear();
+ m_deleted_connectors.clear();
+ m_changed_connectors.clear();
+ m_debug_count = 0;
+}
+
+// Helper method for buildHyperedgeSegments() for hyperedge tree nodes.
+void HyperedgeImprover::createShiftSegmentsForDimensionExcluding(
+ HyperedgeTreeNode *node, const size_t dim, HyperedgeTreeEdge *ignore,
+ ShiftSegmentList& segments)
+{
+ for (std::list<HyperedgeTreeEdge *>::iterator curr = node->edges.begin();
+ curr != node->edges.end(); ++curr)
+ {
+ HyperedgeTreeEdge *edge = *curr;
+ if (edge != ignore)
+ {
+ createShiftSegmentsForDimensionExcluding(edge, dim,
+ node, segments);
+ }
+ }
+}
+
+// Helper method for buildHyperedgeSegments() for hyperedge tree edges.
+void HyperedgeImprover::createShiftSegmentsForDimensionExcluding(
+ HyperedgeTreeEdge *edge, const size_t dim, HyperedgeTreeNode *ignore,
+ ShiftSegmentList& segments)
+{
+ if (edge->hasOrientation(dim) && ! edge->zeroLength())
+ {
+ bool immovable = (edge->ends.first->isImmovable() ||
+ edge->ends.second->isImmovable());
+
+ HyperedgeShiftSegment *newSegment =
+ new HyperedgeShiftSegment(edge->ends.first,
+ edge->ends.second, dim, immovable);
+ segments.push_back(newSegment);
+ }
+
+ if (edge->ends.first && (edge->ends.first != ignore))
+ {
+ createShiftSegmentsForDimensionExcluding(edge->ends.first, dim,
+ edge, segments);
+ }
+
+ if (edge->ends.second && (edge->ends.second != ignore))
+ {
+ createShiftSegmentsForDimensionExcluding(edge->ends.second, dim,
+ edge, segments);
+ }
+}
+
+// During creation and nudging of shift segments it is often necessary
+// to merge collinear or overlapping segments. This method does the
+// merging for these cases. Effectively merging is done by adding
+// additional vertex pointers to the shift segment.
+void HyperedgeImprover::mergeOverlappingSegments(ShiftSegmentList& segments)
+{
+ for (ShiftSegmentList::iterator curr = segments.begin();
+ curr != segments.end(); ++curr)
+ {
+ HyperedgeShiftSegment *edge1 =
+ static_cast<HyperedgeShiftSegment *> (*curr);
+ for (ShiftSegmentList::iterator curr2 = segments.begin();
+ curr2 != segments.end(); )
+ {
+ if (curr2 == curr)
+ {
+ ++curr2;
+ continue;
+ }
+ HyperedgeShiftSegment *edge2 =
+ static_cast<HyperedgeShiftSegment *> (*curr2);
+ if (edge1->mergesWith(edge2))
+ {
+ delete edge2;
+ curr2 = segments.erase(curr2);
+ }
+ else
+ {
+ ++curr2;
+ }
+ }
+ }
+}
+
+// Given a hyperedge tree and a dimension, this method creates shift
+// segments for all edges in that orientation. These segments are the
+// objects on which the local improvement nudging operates, and they
+// in turn make changes back to the hyperedge tree.
+void HyperedgeImprover::buildHyperedgeSegments(const size_t dim)
+{
+ for (JunctionSet::iterator curr = m_hyperedge_tree_roots.begin();
+ curr != m_hyperedge_tree_roots.end(); ++curr)
+ {
+ ShiftSegmentList& segments = m_root_shift_segments[*curr];
+
+ HyperedgeTreeNode *node = m_hyperedge_tree_junctions[*curr];
+ createShiftSegmentsForDimensionExcluding(node, dim, nullptr, segments);
+
+ // Merge overlapping segment.
+ mergeOverlappingSegments(segments);
+
+ m_all_shift_segments.insert(m_all_shift_segments.begin(),
+ segments.begin(), segments.end());
+ }
+}
+
+// This method looks for and corrects situations where the middle section
+// of a zigzag is optimised away by bringing the outside segments in line
+// and leading to the middle segment being zero length. These zero length
+// edges are removed.
+void HyperedgeImprover::removeZeroLengthEdges(void)
+{
+ for (JunctionSet::iterator curr = m_hyperedge_tree_roots.begin();
+ curr != m_hyperedge_tree_roots.end(); ++curr)
+ {
+ HyperedgeTreeNode *node = m_hyperedge_tree_junctions[*curr];
+
+ removeZeroLengthEdges(node, nullptr);
+ }
+}
+
+// This method looks for and correct situations where multiple overlapping
+// edges lead to a junction and one or more of these segments could be
+// removed by moving the junction (and thus divergence point) along the
+// edge.
+void HyperedgeImprover::moveJunctionsAlongCommonEdges(void)
+{
+ for (JunctionHyperedgeTreeNodeMap::iterator curr =
+ m_hyperedge_tree_junctions.begin();
+ curr != m_hyperedge_tree_junctions.end(); )
+ {
+ HyperedgeTreeNode *node = curr->second;
+
+ bool nodeMapHasChanged = false;
+ // For each junction, try and move it.
+ while ((node = moveJunctionAlongCommonEdge(node, nodeMapHasChanged)))
+ {
+ if (node)
+ {
+ // Junction has moved, rewrite the pointer in
+ // the m_hyperedge_tree_junctions map.
+ curr->second = node;
+ }
+ }
+
+ if (nodeMapHasChanged)
+ {
+ // Objects have been added to m_hyperedge_tree_junctions and
+ // this may be earlier than our current iterator, so restart.
+ curr = m_hyperedge_tree_junctions.begin();
+ }
+ else
+ {
+ ++curr;
+ }
+ }
+}
+
+// This method traverses the hyperedge tree removing zero length edges.
+//
+void HyperedgeImprover::removeZeroLengthEdges(HyperedgeTreeEdge *self,
+ HyperedgeTreeNode *ignored)
+{
+ if (self->ends.first != ignored)
+ {
+ removeZeroLengthEdges(self->ends.first, self);
+ }
+
+ if (self->ends.second != ignored)
+ {
+ removeZeroLengthEdges(self->ends.second, self);
+ }
+}
+
+
+// This method traverses the hyperedge tree removing zero length edges.
+//
+void HyperedgeImprover::removeZeroLengthEdges(HyperedgeTreeNode *self,
+ HyperedgeTreeEdge *ignored)
+{
+ for (std::list<HyperedgeTreeEdge *>::iterator curr = self->edges.begin();
+ curr != self->edges.end(); ++curr)
+ {
+ HyperedgeTreeEdge *edge = *curr;
+ if (edge != ignored)
+ {
+ if (!edge->hasFixedRoute && edge->zeroLength())
+ {
+ HyperedgeTreeNode *other = edge->followFrom(self);
+ HyperedgeTreeNode *target = nullptr;
+ HyperedgeTreeNode *source = nullptr;
+ if (other->junction && ! self->junction)
+ {
+ target = other;
+ source = self;
+ }
+ else if ( ! other->junction && self->junction)
+ {
+ target = self;
+ source = other;
+ }
+ else if ( ! other->junction && ! self->junction)
+ {
+ target = self;
+ source = other;
+ }
+ else if ( other->junction && self->junction &&
+ m_can_make_major_changes)
+ {
+ // Only delete junctions if we can make major changes.
+
+#ifdef MAJOR_HYPEREDGE_IMPROVEMENT_DEBUG
+ fprintf(stderr, "HyperedgeImprover: Coalescing junctions "
+ "%u and %u:\n", self->junction->id(),
+ other->junction->id());
+ fprintf(stderr, " Deleted junction %u\n",
+ other->junction->id());
+ fprintf(stderr, " Deleted connector %u\n",
+ edge->conn->id());
+#endif
+
+ // Delete one of the junctions.
+ m_deleted_junctions.push_back(other->junction);
+ m_hyperedge_tree_junctions.erase(other->junction);
+ if (m_hyperedge_tree_roots.count(other->junction) > 0)
+ {
+ // If 'other' was the root for the hyperedge, we need
+ // to make 'self' the new root.
+ m_hyperedge_tree_roots.erase(other->junction);
+ m_hyperedge_tree_roots.insert(self->junction);
+ // It should already be in the junctions list.
+ COLA_ASSERT(m_hyperedge_tree_junctions.
+ count(self->junction) == 1);
+ }
+ other->junction = nullptr;
+
+ // Delete the connector on the zero length edge.
+ m_deleted_connectors.push_back(edge->conn);
+ edge->conn = nullptr;
+
+ target = self;
+ source = other;
+ }
+
+ if (target)
+ {
+ edge->disconnectEdge();
+ delete edge;
+ target->spliceEdgesFrom(source);
+ delete source;
+ removeZeroLengthEdges(target, ignored);
+ return;
+ }
+ }
+
+ // Recursive call.
+ removeZeroLengthEdges(edge, self);
+ }
+ }
+}
+
+
+
+// Given a set of hyperedge shift segments in a particular dimension,
+// with limits and balance values precomputed, this method shifts and
+// merges segments to improve the overall cost (length + bend penalties)
+// for the hyperedge.
+void HyperedgeImprover::nudgeHyperedgeSegments(size_t dimension,
+ unsigned int& versionNumber)
+{
+ // For each hyperedge...
+ for (JunctionSet::iterator curr = m_hyperedge_tree_roots.begin();
+ curr != m_hyperedge_tree_roots.end(); ++curr)
+ {
+ ++m_debug_count;
+ versionNumber = (int)dimension * 10000;
+ versionNumber += m_debug_count * 1000;
+
+ // Calculate the balance for each shift segment.
+ ShiftSegmentList& segmentList = m_root_shift_segments[*curr];
+ for (ShiftSegmentList::iterator currSeg = segmentList.begin();
+ currSeg != segmentList.end(); )
+ {
+ HyperedgeShiftSegment *segment =
+ static_cast<HyperedgeShiftSegment *> (*currSeg);
+ segment->setBalanceCount();
+
+ ++currSeg;
+ }
+
+ //segmentList.sort(CmpHyperedgeSegmentDirOrder);
+
+ bool change = false;
+ ShiftSegmentList::iterator currSeg = segmentList.begin();
+ while (currSeg != segmentList.end())
+ {
+ // While we haven't considered every segment...
+
+ HyperedgeShiftSegment *segment =
+ static_cast<HyperedgeShiftSegment *> (*currSeg);
+
+ if ( ! segment->settled() )
+ {
+ // The segment is not settled, so move it to the next
+ // ideal position and then merge it with overlapping
+ // segments. Note, the merged segment will have a new
+ // balance value calculated for it.
+ segment->adjustPosition();
+ outputHyperedgesToSVG(++versionNumber, segment);
+ mergeOverlappingSegments(segmentList);
+ change = true;
+ }
+
+ if (change)
+ {
+ // We made a change, so start again from the beginning
+ // of the list of segments.
+ change = false;
+ currSeg = segmentList.begin();
+ }
+ else
+ {
+ // Consider the next segment.
+ ++currSeg;
+ }
+ }
+ }
+}
+
+// Write the paths from an improved hyperedgetree object back as routes
+// to the component connectors that form the hyperedge.
+void HyperedgeImprover::writeHyperedgeSegmentsBackToConnPaths(void)
+{
+ // Write segments in two passes. The first to clear the existing
+ // connector routes and the second to build and set new routes.
+ for (size_t pass = 0; pass < 2; ++pass)
+ {
+ for (JunctionSet::iterator curr = m_hyperedge_tree_roots.begin();
+ curr != m_hyperedge_tree_roots.end(); ++curr)
+ {
+ HyperedgeTreeNode *node = m_hyperedge_tree_junctions[*curr];
+
+ node->writeEdgesToConns(nullptr, pass);
+ }
+ }
+}
+
+// Output the hyperedge tree to an SVG file, optionally highlighting
+// a segment of interest (usually the segment being moved).
+void HyperedgeImprover::outputHyperedgesToSVG(unsigned int pass,
+ HyperedgeShiftSegment *activeSegment)
+{
+#ifndef HYPEREDGE_DEBUG
+ return;
+#endif
+
+ // Reasonable initial limit for diagram bounds.
+ const double LIMIT = 100000000;
+
+ std::stringstream filename;
+ filename << "DEBUG/hyperedges-" << std::setfill('0') << std::setw(5) << pass << ".svg";
+ FILE *fp = fopen(filename.str().c_str(), "w");
+
+ double minX = LIMIT;
+ double minY = LIMIT;
+ double maxX = -LIMIT;
+ double maxY = -LIMIT;
+
+ VertInf *curr = m_router->vertices.connsBegin();
+ while (curr)
+ {
+ Point p = curr->point;
+
+ if (p.x > -LIMIT)
+ {
+ minX = std::min(minX, p.x);
+ }
+ if (p.x < LIMIT)
+ {
+ maxX = std::max(maxX, p.x);
+ }
+ if (p.y > -LIMIT)
+ {
+ minY = std::min(minY, p.y);
+ }
+ if (p.y < LIMIT)
+ {
+ maxY = std::max(maxY, p.y);
+ }
+ curr = curr->lstNext;
+ }
+ minX -= 50;
+ minY -= 50;
+ maxX += 50;
+ maxY += 50;
+
+
+ fprintf(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ fprintf(fp, "<svg xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\" xmlns=\"http://www.w3.org/2000/svg\" width=\"100%%\" height=\"100%%\" viewBox=\"%g %g %g %g\">\n", minX, minY, maxX - minX, maxY - minY);
+
+ fprintf(fp, "<g inkscape:groupmode=\"layer\" "
+ "inkscape:label=\"ShapesRect\">\n");
+ ObstacleList::iterator obstacleIt = m_router->m_obstacles.begin();
+ while (obstacleIt != m_router->m_obstacles.end())
+ {
+ Obstacle *obstacle = *obstacleIt;
+ bool isShape = (nullptr != dynamic_cast<ShapeRef *> (obstacle));
+
+ if ( ! isShape )
+ {
+ // Don't output obstacles here, for now.
+ ++obstacleIt;
+ continue;
+ }
+
+ Box bBox = obstacle->polygon().offsetBoundingBox(0.0);
+
+ fprintf(fp, "<rect id=\"rect-%u\" x=\"%g\" y=\"%g\" width=\"%g\" "
+ "height=\"%g\" style=\"stroke-width: 1px; stroke: %s; "
+ "fill: blue; fill-opacity: 0.3;\" />\n",
+ obstacle->id(), bBox.min.x, bBox.min.y,
+ bBox.max.x - bBox.min.x, bBox.max.y - bBox.min.y,
+ (isShape) ? "blue" : "red");
+ ++obstacleIt;
+ }
+ fprintf(fp, "</g>\n");
+
+ fprintf(fp, "<g inkscape:groupmode=\"layer\" "
+ "inkscape:label=\"Hyperedge-%u\">\n", pass);
+ if (activeSegment)
+ {
+ fprintf(fp, "<path d=\"M %g %g L %g %g\" "
+ "style=\"fill: none; stroke: %s; stroke-width: 12px; "
+ "stroke-opacity: 0.5;\" />\n",
+ activeSegment->lowPoint().x, activeSegment->lowPoint().y,
+ activeSegment->highPoint().x, activeSegment->highPoint().y,
+ activeSegment->settled() ? "red" : "orange");
+ }
+
+ for (JunctionSet::iterator curr = m_hyperedge_tree_roots.begin();
+ curr != m_hyperedge_tree_roots.end(); ++curr)
+ {
+ HyperedgeTreeNode *node = m_hyperedge_tree_junctions[*curr];
+
+ node->outputEdgesExcept(fp, nullptr);
+ }
+ fprintf(fp, "</g>\n");
+ fprintf(fp, "</svg>\n");
+
+ fclose(fp);
+}
+
+// Given a junction, this method follows the attached connectors and
+// junctions to determine a hyperedge and returns the set of vertices
+// representing its endpoints.
+void HyperedgeImprover::getEndpoints(JunctionRef *junction, JunctionRef *ignore,
+ std::set<VertInf *>& endpoints)
+{
+ for (std::set<ConnEnd *>::iterator curr =
+ junction->m_following_conns.begin();
+ curr != junction->m_following_conns.end(); ++curr)
+ {
+ ConnEnd *connEnd = *curr;
+ COLA_ASSERT(connEnd->m_conn_ref != nullptr);
+ ConnRef *connRef = connEnd->m_conn_ref;
+ std::pair<Obstacle *, Obstacle *> anchors =
+ connRef->endpointAnchors();
+
+ JunctionRef *junction1 =
+ dynamic_cast<JunctionRef *> (anchors.first);
+ if (junction1)
+ {
+ if (junction1 != junction && junction1 != ignore)
+ {
+ getEndpoints(junction1, junction, endpoints);
+ }
+ }
+ else
+ {
+ endpoints.insert(connRef->m_src_vert);
+ }
+
+ JunctionRef *junction2 =
+ dynamic_cast<JunctionRef *> (anchors.second);
+ if (junction2)
+ {
+ if (junction2 != junction && junction2 != ignore)
+ {
+ getEndpoints(junction2, junction, endpoints);
+ }
+ }
+ else
+ {
+ endpoints.insert(connRef->m_dst_vert);
+ }
+ }
+}
+
+// Execute local improvement process.
+void HyperedgeImprover::execute(bool canMakeMajorChanges)
+{
+ m_can_make_major_changes = canMakeMajorChanges;
+
+ // Build Hyperedge trees.
+ ConnRefList::iterator connRefIt = m_router->connRefs.begin();
+ while (connRefIt != m_router->connRefs.end())
+ {
+ ConnRef *connRef = *connRefIt;
+ JunctionRef *jFront = nullptr;
+ JunctionRef *jBack = nullptr;
+
+ if (connRef->m_src_connend)
+ {
+ jFront = connRef->m_src_connend->junction();
+ }
+
+ if (connRef->m_dst_connend)
+ {
+ jBack = connRef->m_dst_connend->junction();
+ }
+
+ if ( ! jFront && ! jBack )
+ {
+ ++connRefIt;
+ continue;
+ }
+
+ bool seenFront = (m_hyperedge_tree_junctions.find(jFront) !=
+ m_hyperedge_tree_junctions.end());
+ bool seenBack = (m_hyperedge_tree_junctions.find(jBack) !=
+ m_hyperedge_tree_junctions.end());
+
+ HyperedgeTreeNode *nodeFront = nullptr;
+ HyperedgeTreeNode *nodeBack = nullptr;
+
+ if (jFront)
+ {
+ if ( ! seenFront)
+ {
+ nodeFront = new HyperedgeTreeNode();
+ nodeFront->point = jFront->position();
+ nodeFront->junction = jFront;
+
+ m_hyperedge_tree_junctions[jFront] = nodeFront;
+ }
+ else
+ {
+ nodeFront = m_hyperedge_tree_junctions[jFront];
+ }
+ }
+ else
+ {
+ nodeFront = new HyperedgeTreeNode();
+ }
+
+ if (jBack)
+ {
+ if ( ! seenBack)
+ {
+ nodeBack = new HyperedgeTreeNode();
+ nodeBack->point = jBack->position();
+ nodeBack->junction = jBack;
+
+ m_hyperedge_tree_junctions[jBack] = nodeBack;
+ }
+ else
+ {
+ nodeBack = m_hyperedge_tree_junctions[jBack];
+ }
+ }
+ else
+ {
+ nodeBack = new HyperedgeTreeNode();
+ }
+
+ PolyLine& route = connRef->displayRoute();
+ HyperedgeTreeNode *prev = nullptr;
+ for (unsigned int i = 1; i < route.size(); ++i)
+ {
+ HyperedgeTreeNode *node;
+ if (i + 1 == route.size())
+ {
+ node = nodeBack;
+ }
+ else
+ {
+ node = new HyperedgeTreeNode();
+ }
+ node->point = route.at(i);
+ if (i == 1)
+ {
+ prev = nodeFront;
+ nodeFront->point = route.at(0);
+ nodeFront->isConnectorSource = true;
+ }
+ new HyperedgeTreeEdge(prev, node, connRef);
+ prev = node;
+ }
+ ++connRefIt;
+ }
+
+ // Make a list that contains a single junction from each tree.
+ for (JunctionHyperedgeTreeNodeMap::iterator curr =
+ m_hyperedge_tree_junctions.begin();
+ curr != m_hyperedge_tree_junctions.end(); ++curr)
+ {
+ HyperedgeTreeNode *node = curr->second;
+ m_hyperedge_tree_roots.insert(node->junction);
+ }
+ JunctionRefList cyclicHyperedgeTreeRoots;
+ for (JunctionSet::iterator curr = m_hyperedge_tree_roots.begin();
+ curr != m_hyperedge_tree_roots.end(); ++curr)
+ {
+ HyperedgeTreeNode *node = m_hyperedge_tree_junctions[*curr];
+ bool containsCycle = node->removeOtherJunctionsFrom(nullptr,
+ m_hyperedge_tree_roots);
+ if (containsCycle)
+ {
+ // This hyperedge has a cycle. We will need to remove it.
+ cyclicHyperedgeTreeRoots.push_back(node->junction);
+ }
+ }
+ // Remove roots of cyclic hyperedges, we can't improve these.
+ for (JunctionRefList::iterator curr = cyclicHyperedgeTreeRoots.begin();
+ curr != cyclicHyperedgeTreeRoots.end(); ++curr)
+ {
+ JunctionRef *junction = *curr;
+ err_printf("Warning: Skipping cyclic hyperedge rooted at junction %u\n",
+ junction->id());
+ m_hyperedge_tree_roots.erase(junction);
+ }
+
+ TIMER_START(m_router, tmHyperedgeImprove);
+
+ // Debug output.
+ unsigned int versionNumber = 1;
+ outputHyperedgesToSVG(versionNumber);
+
+ // Remove zero length edges.
+ removeZeroLengthEdges();
+
+ // Move junctions to divergence points.
+ moveJunctionsAlongCommonEdges();
+
+ // Debug output.
+ outputHyperedgesToSVG(++versionNumber);
+
+ for (size_t count = 0; count < 4; ++count)
+ {
+ size_t dimension = count % 2;
+
+ // Set a version number for debug output.
+ versionNumber = 100 * (int)(dimension + 1);
+
+ // Build shift segments.
+ buildHyperedgeSegments(dimension);
+ // Calculate channel information for this dimension.
+ buildOrthogonalChannelInfo(m_router, dimension, m_all_shift_segments);
+ // Nudge hyperedge segments to locally improve the route.
+ nudgeHyperedgeSegments(dimension, versionNumber);
+ // Remove resulting zero length edges.
+ removeZeroLengthEdges();
+ // Move junctions to divergence points.
+ moveJunctionsAlongCommonEdges();
+ // Debug output.
+ outputHyperedgesToSVG(++versionNumber);
+
+ // Clean up shift segments.
+ for (JunctionSet::iterator curr = m_hyperedge_tree_roots.begin();
+ curr != m_hyperedge_tree_roots.end(); ++curr)
+ {
+ ShiftSegmentList& segmentList = m_root_shift_segments[*curr];
+ for_each(segmentList.begin(), segmentList.end(),
+ delete_object());
+ }
+ m_root_shift_segments.clear();
+ m_all_shift_segments.clear();
+ }
+
+ // Rewrite updated connector attachments to junctions.
+ if (m_can_make_major_changes)
+ {
+ for (JunctionSet::iterator curr = m_hyperedge_tree_roots.begin();
+ curr != m_hyperedge_tree_roots.end(); ++curr)
+ {
+ HyperedgeTreeNode *treeRoot = m_hyperedge_tree_junctions[*curr];
+ COLA_ASSERT(treeRoot);
+ treeRoot->updateConnEnds(nullptr, m_router, m_changed_connectors);
+
+ // Validate the rewrtten connections.
+ treeRoot->validateHyperedge(nullptr, 0);
+ }
+ }
+
+ // Write back final recommended positions to junctions.
+ for (JunctionHyperedgeTreeNodeMap::iterator curr =
+ m_hyperedge_tree_junctions.begin();
+ curr != m_hyperedge_tree_junctions.end(); ++curr)
+ {
+ HyperedgeTreeNode *node = curr->second;
+
+ node->junction->setRecommendedPosition(node->point);
+ }
+
+ // Write paths from the hyperedge tree back into individual
+ // connector routes.
+ writeHyperedgeSegmentsBackToConnPaths();
+
+ // Free HyperedgeTree structure.
+ for (JunctionSet::iterator curr = m_hyperedge_tree_roots.begin();
+ curr != m_hyperedge_tree_roots.end(); ++curr)
+ {
+ HyperedgeTreeNode *node = m_hyperedge_tree_junctions[*curr];
+
+ node->deleteEdgesExcept(nullptr);
+ delete node;
+ }
+
+ // Tell the router that we are deleting the objects used for the
+ // previous path for the hyperedge.
+ for (ConnRefList::iterator curr = m_deleted_connectors.begin();
+ curr != m_deleted_connectors.end(); ++curr)
+ {
+ // Clear visibility assigned for connection pins.
+ (*curr)->assignConnectionPinVisibility(false);
+
+ m_router->deleteConnector(*curr);
+ }
+ for (JunctionRefList::iterator curr = m_deleted_junctions.begin();
+ curr != m_deleted_junctions.end(); ++curr)
+ {
+ m_router->deleteJunction(*curr);
+ }
+
+ TIMER_STOP(m_router);
+}
+
+
+HyperedgeNewAndDeletedObjectLists
+ HyperedgeImprover::newAndDeletedObjectLists(void) const
+{
+ HyperedgeNewAndDeletedObjectLists result;
+
+ result.newJunctionList = m_new_junctions;
+ result.deletedJunctionList = m_deleted_junctions;
+ result.newConnectorList = m_new_connectors;
+ result.deletedConnectorList = m_deleted_connectors;
+ result.changedConnectorList = m_changed_connectors;
+
+ return result;
+}
+
+
+// This method moves the junction at the given node along any shared paths
+// (so long as this action would not create any additional shared paths),
+// while also removing and freeing merged edges and nodes in the process.
+// It returns the new node where the junction is now located.
+//
+HyperedgeTreeNode *HyperedgeImprover::moveJunctionAlongCommonEdge(
+ HyperedgeTreeNode *self, bool& nodeMapHasChanged)
+{
+ COLA_ASSERT(self->junction);
+
+ HyperedgeTreeNode *newSelf = nullptr;
+ std::vector<HyperedgeTreeEdge *> commonEdges;
+ std::vector<HyperedgeTreeEdge *> otherEdges;
+
+ // Consider each edge from this node in turn.
+ for (std::list<HyperedgeTreeEdge *>::iterator curr = self->edges.begin();
+ curr != self->edges.end(); ++curr)
+ {
+ HyperedgeTreeEdge *currEdge = *curr;
+ HyperedgeTreeNode *currNode = currEdge->followFrom(self);
+ commonEdges.clear();
+ otherEdges.clear();
+
+ if (currNode->junction)
+ {
+ // Don't shift junctions onto other junctions.
+ continue;
+ }
+ if (currEdge->hasFixedRoute)
+ {
+ // Don't move junctions along fixed edges.
+ continue;
+ }
+
+ // The current edge is a common edge we are looking to shift along.
+ commonEdges.push_back(currEdge);
+
+ // Consider each of the other edges.
+ for (std::list<HyperedgeTreeEdge *>::iterator curr2 =
+ self->edges.begin(); curr2 != self->edges.end(); ++curr2)
+ {
+ if (curr == curr2)
+ {
+ // Except the current (curr) one.
+ continue;
+ }
+
+ HyperedgeTreeEdge *otherEdge = *curr2;
+ if (otherEdge->hasFixedRoute)
+ {
+ // Don't shift junctions along fixed route connectors.
+ otherEdges.push_back(otherEdge);
+ continue;
+ }
+
+ HyperedgeTreeNode *otherNode = otherEdge->followFrom(self);
+ if (otherNode->point == currNode->point)
+ {
+ // A common edge can be at the same point, but can't have
+ // a junction at it.
+ if (otherNode->junction)
+ {
+ otherEdges.push_back(otherEdge);
+ }
+ else
+ {
+ commonEdges.push_back(otherEdge);
+ }
+ }
+ else if (pointOnLine(self->point, otherNode->point,
+ currNode->point))
+ {
+ // A common edge can be a (longer) collinear line, but we
+ // need to split the longer line at the other end of curr.
+ otherEdge->splitFromNodeAtPoint(self, currNode->point);
+ commonEdges.push_back(otherEdge);
+ }
+ else
+ {
+ // If the edge goes in another direction it is not common.
+ otherEdges.push_back(otherEdge);
+ }
+ }
+
+ // For the purpose of these changes a junction is considered fixed
+ // only when not performing major improvements.
+ bool selfFixed = self->junction->positionFixed() &&
+ !m_can_make_major_changes;
+
+ if ((commonEdges.size() > 1) && (otherEdges.size() <= 1) && !selfFixed)
+ {
+ // One of the common nodes becomes the target node, we move
+ // all connections from the other common nodes to this node.
+ // We also move the junction there and remove it from the
+ // current node.
+ HyperedgeTreeNode *targetNode = commonEdges[0]->followFrom(self);
+ for (size_t i = 1; i < commonEdges.size(); ++i)
+ {
+ HyperedgeTreeNode *thisNode = commonEdges[i]->followFrom(self);
+ commonEdges[i]->disconnectEdge();
+ targetNode->spliceEdgesFrom(thisNode);
+ delete thisNode;
+ delete commonEdges[i];
+ }
+ targetNode->junction = self->junction;
+ self->junction = nullptr;
+
+ if (otherEdges.empty())
+ {
+ // Nothing else connected to this node, so remove the node
+ // and the edge to the target node.
+ commonEdges[0]->disconnectEdge();
+
+ delete commonEdges[0];
+ delete self;
+ }
+ else
+ {
+ // We need to mark commonEdges[0] as being from the connector
+ // of the otherEdges[0].
+ commonEdges[0]->conn = otherEdges[0]->conn;
+ }
+ newSelf = targetNode;
+
+ break;
+ }
+ else if (m_can_make_major_changes && (commonEdges.size() > 1) &&
+ (otherEdges.size() > 1))
+ {
+ // Case where this is one junction we need to split into two,
+ // because we have a common path leading to it that we want to
+ // move the junction along, but multiple other edges leaving
+ // this junction that need to stay in place.
+
+ // One of the common nodes becomes the target node, we move
+ // all connections from the other common nodes to this node.
+ // We will also create a new junction there.
+ HyperedgeTreeNode *targetNode = commonEdges[0]->followFrom(self);
+ for (size_t i = 1; i < commonEdges.size(); ++i)
+ {
+ HyperedgeTreeNode *thisNode = commonEdges[i]->followFrom(self);
+ commonEdges[i]->disconnectEdge();
+ targetNode->spliceEdgesFrom(thisNode);
+ delete thisNode;
+ delete commonEdges[i];
+ }
+
+ // Create the additional junction at the target node for
+ // the otherEdges to attach to.
+ targetNode->junction = new JunctionRef(m_router, targetNode->point);
+ m_router->removeObjectFromQueuedActions(targetNode->junction);
+ targetNode->junction->makeActive();
+ m_hyperedge_tree_junctions[targetNode->junction] = targetNode;
+ nodeMapHasChanged = true;
+ m_new_junctions.push_back(targetNode->junction);
+
+ // And we create a new connector between the original junction
+ // and the new junction.
+ ConnRef *conn = new ConnRef(m_router);
+ m_router->removeObjectFromQueuedActions(conn);
+ conn->makeActive();
+ conn->m_initialised = true;
+ ConnEnd srcConnend(targetNode->junction);
+ conn->updateEndPoint(VertID::src, srcConnend);
+ ConnEnd tarConnend(self->junction);
+ conn->updateEndPoint(VertID::tar, tarConnend);
+ commonEdges[0]->conn = conn;
+ m_new_connectors.push_back(conn);
+
+#ifdef MAJOR_HYPEREDGE_IMPROVEMENT_DEBUG
+ fprintf(stderr, "HyperedgeImprover: Split junction %u:\n",
+ self->junction->id());
+ fprintf(stderr, " Added junction %u\n",
+ targetNode->junction->id());
+ fprintf(stderr, " Added connector %u "
+ "(between junctions %u and %u)\n", conn->id(),
+ self->junction->id(), targetNode->junction->id());
+#endif
+
+ newSelf = self;
+
+ break;
+ }
+ }
+
+ return newSelf;
+}
+
+
+
+
+}
diff --git a/src/3rdparty/adaptagrams/libavoid/hyperedgeimprover.h b/src/3rdparty/adaptagrams/libavoid/hyperedgeimprover.h
new file mode 100644
index 0000000..958c877
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/hyperedgeimprover.h
@@ -0,0 +1,159 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2011-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+#ifndef AVOID_IMPROVEHYPEREDGES_H
+#define AVOID_IMPROVEHYPEREDGES_H
+
+#include <map>
+#include <set>
+#include <list>
+
+
+namespace Avoid {
+
+struct HyperedgeTreeNode;
+struct HyperedgeTreeEdge;
+class HyperedgeShiftSegment;
+class ConnRef;
+class JunctionRef;
+class ShiftSegment;
+class VertInf;
+
+typedef std::list<ShiftSegment *> ShiftSegmentList;
+typedef std::map<JunctionRef *, ShiftSegmentList> RootSegmentsMap;
+typedef std::map<JunctionRef *, HyperedgeTreeNode *>
+ JunctionHyperedgeTreeNodeMap;
+typedef std::set<JunctionRef *> JunctionSet;
+typedef std::list<ConnRef *> ConnRefList;
+typedef std::list<JunctionRef *> JunctionRefList;
+
+class HyperedgeImprover
+{
+public:
+ // Constructor.
+ HyperedgeImprover();
+
+ void clear(void);
+
+ // Set the router that this HyperedgeImprover will act upon.
+ void setRouter(Router *router);
+
+ // Returns lists of junctions and connectors created and deleted during
+ // hyperedge improvement.
+ HyperedgeNewAndDeletedObjectLists newAndDeletedObjectLists(void) const;
+
+ // Execute local improvement process.
+ void execute(bool canMakeMajorChanges);
+
+private:
+ // Helper method for buildHyperedgeSegments() for hyperedge tree nodes.
+ void createShiftSegmentsForDimensionExcluding(HyperedgeTreeNode *node,
+ const size_t dim, HyperedgeTreeEdge *ignore,
+ ShiftSegmentList& segments);
+
+ // Helper method for buildHyperedgeSegments() for hyperedge tree edges.
+ void createShiftSegmentsForDimensionExcluding(HyperedgeTreeEdge *edge,
+ const size_t dim, HyperedgeTreeNode *ignore,
+ ShiftSegmentList& segments);
+
+ // During creation and nudging of shift segments it is often necessary
+ // to merge collinear or overlapping segments. This method does the
+ // merging for these cases. Effectively merging is done by adding
+ // additional vertex pointers to the shift segment.
+ void mergeOverlappingSegments(ShiftSegmentList& segments);
+
+ // Given a hyperedge tree and a dimension, this method creates shift
+ // segments for all edges in that orientation. These segments are the
+ // objects on which the local improvement nudging operates, and they
+ // in turn make changes back to the hyperedge tree.
+ void buildHyperedgeSegments(const size_t dim);
+
+ // This method looks for and corrects situations where the middle section
+ // of a zigzag is optimised away by bringing the outside segments in line
+ // and leading to the middle segment being zero length. These zero length
+ // edges are removed.
+ void removeZeroLengthEdges(void);
+
+ // This method looks for and correct situations where multiple overlapping
+ // edges lead to a junction and one or more of these segments could be
+ // removed by moving the junction (and thus divergence point) along the
+ // edge.
+ void moveJunctionsAlongCommonEdges(void);
+
+ // Given a set of hyperedge shift segments in a particular dimension,
+ // with limits and balance values precomputed, this method shifts and
+ // merges segments to improve the overall cost (length + bend penalties)
+ // for the hyperedge.
+ void nudgeHyperedgeSegments(size_t dimension, unsigned int& versionNumber);
+
+ // Write the paths from an improved hyperedgetree object back as routes
+ // to the component connectors that form the hyperedge.
+ void writeHyperedgeSegmentsBackToConnPaths(void);
+
+ // Output the hyperedge tree to an SVG file, optionally highlighting
+ // a segment of interest (usually the segment being moved).
+ void outputHyperedgesToSVG(unsigned int pass,
+ HyperedgeShiftSegment *activeSegment = nullptr);
+
+ // Given a junction, this method follows the attached connectors and
+ // junctions to determine a hyperedge and returns the set of vertices
+ // representing its endpoints.
+ void getEndpoints(JunctionRef *junction, JunctionRef *ignore,
+ std::set<VertInf *>& endpoints);
+
+ // This method moves the junction at the given node along any shared paths
+ // (so long as this action would not create any additional shared paths),
+ // while also removing and freeing merged edges and nodes in the process.
+ // It returns the new node where the junction is now located.
+ HyperedgeTreeNode *moveJunctionAlongCommonEdge(HyperedgeTreeNode *self,
+ bool& nodeMapHasChanged);
+
+ // This method traverses the hyperedge tree removing zero length edges.
+ //
+ void removeZeroLengthEdges(HyperedgeTreeNode *self,
+ HyperedgeTreeEdge *ignored);
+
+ // This method traverses the hyperedge tree removing zero length edges.
+ //
+ void removeZeroLengthEdges(HyperedgeTreeEdge *self,
+ HyperedgeTreeNode *ignored);
+
+ Router *m_router;
+ JunctionHyperedgeTreeNodeMap m_hyperedge_tree_junctions;
+ JunctionSet m_hyperedge_tree_roots;
+ RootSegmentsMap m_root_shift_segments;
+ ShiftSegmentList m_all_shift_segments;
+ JunctionRefList m_new_junctions;
+ JunctionRefList m_deleted_junctions;
+ ConnRefList m_new_connectors;
+ ConnRefList m_deleted_connectors;
+ ConnRefList m_changed_connectors;
+ int m_debug_count;
+ bool m_can_make_major_changes;
+};
+
+
+}
+#endif
+
diff --git a/src/3rdparty/adaptagrams/libavoid/hyperedgetree.cpp b/src/3rdparty/adaptagrams/libavoid/hyperedgetree.cpp
new file mode 100644
index 0000000..b9cf1a0
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/hyperedgetree.cpp
@@ -0,0 +1,821 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2011-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+#include <algorithm>
+
+#include "libavoid/hyperedgetree.h"
+#include "libavoid/geometry.h"
+#include "libavoid/connector.h"
+#include "libavoid/router.h"
+#include "libavoid/connend.h"
+#include "libavoid/assertions.h"
+#include "libavoid/junction.h"
+#include "libavoid/debughandler.h"
+
+namespace Avoid {
+
+
+// Constructs a new hyperedge tree node.
+//
+HyperedgeTreeNode::HyperedgeTreeNode()
+ : junction(nullptr),
+ shiftSegmentNodeSet(nullptr),
+ finalVertex(nullptr),
+ isConnectorSource(false),
+ isPinDummyEndpoint(false),
+ visited(false)
+{
+}
+
+HyperedgeTreeNode::~HyperedgeTreeNode()
+{
+ if (shiftSegmentNodeSet)
+ {
+ shiftSegmentNodeSet->erase(this);
+ shiftSegmentNodeSet = nullptr;
+ }
+}
+
+
+// This method traverses the hyperedge tree and outputs each of the edges
+// and junction positions as SVG objects to the file fp.
+//
+void HyperedgeTreeNode::outputEdgesExcept(FILE *fp, HyperedgeTreeEdge *ignored)
+{
+ if (junction)
+ {
+ fprintf(fp, "<circle cx=\"%g\" cy=\"%g\" r=\"6\" "
+ "style=\"fill: green; stroke: none;\" />\n", point.x, point.y);
+ }
+ for (std::list<HyperedgeTreeEdge *>::iterator curr = edges.begin();
+ curr != edges.end(); ++curr)
+ {
+ if (*curr != ignored)
+ {
+ (*curr)->outputNodesExcept(fp, this);
+ }
+ }
+}
+
+
+// This method traverses the hyperedge tree and removes from treeRoots any
+// junction nodes (other than this one).
+
+bool HyperedgeTreeNode::removeOtherJunctionsFrom(HyperedgeTreeEdge *ignored,
+ JunctionSet& treeRoots)
+{
+ bool containsCycle = false;
+ if (visited)
+ {
+ // We've encountered this node before, so there must be cycles in
+ // the hyperedge. Don't recurse any further.
+ containsCycle = true;
+ return containsCycle;
+ }
+
+ if (junction && (ignored != nullptr))
+ {
+ // Remove junctions other than the first (when ignored == nullptr).
+ treeRoots.erase(junction);
+ }
+ visited = true;
+ for (std::list<HyperedgeTreeEdge *>::iterator curr = edges.begin();
+ curr != edges.end(); ++curr)
+ {
+ if (*curr != ignored)
+ {
+ containsCycle |= (*curr)->removeOtherJunctionsFrom(this, treeRoots);
+ }
+ }
+ return containsCycle;
+}
+
+
+// This method traverses the hyperedge tree and writes each of the paths
+// back to the individual connectors as routes.
+//
+void HyperedgeTreeNode::writeEdgesToConns(HyperedgeTreeEdge *ignored,
+ size_t pass)
+{
+ for (std::list<HyperedgeTreeEdge *>::iterator curr = edges.begin();
+ curr != edges.end(); ++curr)
+ {
+ if (*curr != ignored)
+ {
+ (*curr)->writeEdgesToConns(this, pass);
+ }
+ }
+}
+
+// This method traverses the hyperedge tree and creates connectors for each
+// segment bridging junction and/or terminals. It also sets the
+// appropriate ConnEnds for each connector.
+//
+void HyperedgeTreeNode::addConns(HyperedgeTreeEdge *ignored, Router *router,
+ ConnRefList& oldConns, ConnRef *conn)
+{
+ // If no connector is set, then we must be starting off at a junction.
+ COLA_ASSERT(conn || junction);
+
+ for (std::list<HyperedgeTreeEdge *>::iterator curr = edges.begin();
+ curr != edges.end(); ++curr)
+ {
+ if (*curr != ignored)
+ {
+ // If we're not at a junction, then use the connector value being
+ // passed in to the method.
+
+ if (junction)
+ {
+ // If we're at a junction, then we are effectively starting
+ // our traversal along a connector, so create this new connector
+ // and set it's start ConnEnd to be this junction.
+ conn = new ConnRef(router);
+ router->removeObjectFromQueuedActions(conn);
+ conn->makeActive();
+ conn->m_initialised = true;
+ ConnEnd connend(junction);
+ conn->updateEndPoint(VertID::src, connend);
+ }
+
+ // Set the connector for this edge.
+ (*curr)->conn = conn;
+
+ // Continue recursive traversal.
+ (*curr)->addConns(this, router, oldConns);
+ }
+ }
+}
+
+static bool travellingForwardOnConnector(ConnRef *conn, JunctionRef *junction)
+{
+ std::pair<ConnEnd, ConnEnd> connEnds = conn->endpointConnEnds();
+
+ if (connEnds.first.junction() == junction)
+ {
+ return true;
+ }
+ if (connEnds.second.junction() == junction)
+ {
+ return false;
+ }
+ if (connEnds.first.type() != ConnEndJunction &&
+ connEnds.first.type() != ConnEndEmpty)
+ {
+ return false;
+ }
+ if (connEnds.second.type() != ConnEndJunction &&
+ connEnds.second.type() != ConnEndEmpty)
+ {
+ return true;
+ }
+ return true;
+}
+
+// This method traverses the hyperedge tree and rewrites connector ends
+// that may have changed junctions due to major hyperedge improvement.
+//
+void HyperedgeTreeNode::updateConnEnds(HyperedgeTreeEdge *ignored,
+ bool forward, ConnRefList& changedConns)
+{
+ for (std::list<HyperedgeTreeEdge *>::iterator curr = edges.begin();
+ curr != edges.end(); ++curr)
+ {
+ HyperedgeTreeEdge *edge = *curr;
+ if (edge != ignored)
+ {
+ if (junction)
+ {
+ // If we're at a junction, then we are effectively starting
+ // our traversal along a connector, so create this new connector
+ // and set it's start ConnEnd to be this junction.
+ forward = travellingForwardOnConnector(edge->conn, junction);
+
+ std::pair<ConnEnd, ConnEnd> existingEnds =
+ edge->conn->endpointConnEnds();
+ ConnEnd existingEnd = (forward) ?
+ existingEnds.first : existingEnds.second;
+ if (existingEnd.junction() != junction)
+ {
+#ifdef MAJOR_HYPEREDGE_IMPROVEMENT_DEBUG
+ fprintf(stderr, "HyperedgeImprover: changed %s of "
+ "connector %u (from junction %u to %u)\n",
+ (forward) ? "src" : "tar", edge->conn->id(),
+ existingEnd.junction()->id(), junction->id());
+#endif
+ unsigned short end = (forward) ? VertID::src : VertID::tar;
+ ConnEnd connend(junction);
+ edge->conn->updateEndPoint(end, connend);
+ changedConns.push_back(edge->conn);
+ }
+ }
+
+ // Continue recursive traversal.
+ edge->updateConnEnds(this, forward, changedConns);
+ }
+ }
+}
+
+
+// This method traverses the hyperedge tree and returns a list of the junctions
+// and connectors that make up the hyperedge.
+//
+void HyperedgeTreeNode::listJunctionsAndConnectors(HyperedgeTreeEdge *ignored,
+ JunctionRefList& junctions, ConnRefList& connectors)
+{
+ if (junction)
+ {
+ junctions.push_back(junction);
+ }
+
+ for (std::list<HyperedgeTreeEdge *>::iterator curr = edges.begin();
+ curr != edges.end(); ++curr)
+ {
+ if (*curr != ignored)
+ {
+ (*curr)->listJunctionsAndConnectors(this, junctions, connectors);
+ }
+ }
+}
+
+
+void HyperedgeTreeNode::validateHyperedge(const HyperedgeTreeEdge *ignored,
+ const size_t dist) const
+{
+ size_t newDist = dist;
+#ifdef MAJOR_HYPEREDGE_IMPROVEMENT_DEBUG
+ if (junction)
+ {
+ if (newDist == 0)
+ {
+ fprintf(stderr,"\nHyperedge topology:\n");
+ }
+ else
+ {
+ ++newDist;
+ }
+ for (size_t d = 0; d < newDist; ++d)
+ {
+ fprintf(stderr," ");
+ }
+ fprintf(stderr, "j(%d)\n", junction->id());
+ ++newDist;
+ }
+ else if (edges.size() == 1)
+ {
+ ++newDist;
+ for (size_t d = 0; d < newDist; ++d)
+ {
+ fprintf(stderr, " ");
+ }
+ fprintf(stderr, "t()\n");
+ ++newDist;
+ }
+#endif
+ for (std::list<HyperedgeTreeEdge *>::const_iterator curr = edges.begin();
+ curr != edges.end(); ++curr)
+ {
+ HyperedgeTreeEdge *edge = *curr;
+ std::pair<ConnEnd, ConnEnd> connEnds = edge->conn->endpointConnEnds();
+
+ if (junction)
+ {
+ COLA_ASSERT((connEnds.first.junction() == junction) ||
+ (connEnds.second.junction() == junction));
+ COLA_ASSERT(connEnds.first.junction() != connEnds.second.junction());
+ }
+ else if (edges.size() == 1)
+ {
+ COLA_ASSERT(!connEnds.first.junction() ||
+ !connEnds.second.junction());
+ }
+
+ if (edge != ignored)
+ {
+ edge->validateHyperedge(this, newDist);
+ }
+ }
+}
+
+
+// This method traverses the hyperedge tree, clearing up the objects and
+// memory used to store the tree.
+//
+void HyperedgeTreeNode::deleteEdgesExcept(HyperedgeTreeEdge *ignored)
+{
+ for (std::list<HyperedgeTreeEdge *>::iterator curr = edges.begin();
+ curr != edges.end(); ++curr)
+ {
+ if (*curr != ignored)
+ {
+ (*curr)->deleteNodesExcept(this);
+ delete *curr;
+ }
+ }
+ edges.clear();
+}
+
+
+// This method disconnects a specific hyperedge tree edge from the given node.
+//
+void HyperedgeTreeNode::disconnectEdge(HyperedgeTreeEdge *edge)
+{
+ for (std::list<HyperedgeTreeEdge *>::iterator curr = edges.begin();
+ curr != edges.end(); )
+ {
+ if (*curr == edge)
+ {
+ curr = edges.erase(curr);
+ }
+ else
+ {
+ ++curr;
+ }
+ }
+
+}
+
+
+// This method moves all edges attached to oldNode to instead be attached to
+// the given hyperedge tree node.
+//
+void HyperedgeTreeNode::spliceEdgesFrom(HyperedgeTreeNode *oldNode)
+{
+ COLA_ASSERT(oldNode != this);
+ for (std::list<HyperedgeTreeEdge *>::iterator curr = oldNode->edges.begin();
+ curr != oldNode->edges.end(); curr = oldNode->edges.begin())
+ {
+ (*curr)->replaceNode(oldNode, this);
+ }
+}
+
+
+bool HyperedgeTreeNode::isImmovable(void) const
+{
+ if ((edges.size() == 1) || (junction && junction->positionFixed()))
+ {
+ return true;
+ }
+ for (std::list<HyperedgeTreeEdge *>::const_iterator curr = edges.begin();
+ curr != edges.end(); ++curr)
+ {
+ if ((*curr)->hasFixedRoute)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Constructs a new hyperedge tree edge, given two endpoint nodes.
+//
+HyperedgeTreeEdge::HyperedgeTreeEdge(HyperedgeTreeNode *node1,
+ HyperedgeTreeNode *node2, ConnRef *conn)
+ : conn(conn),
+ hasFixedRoute(false)
+{
+ if (conn)
+ {
+ hasFixedRoute = conn->hasFixedRoute();
+ }
+ ends = std::make_pair(node1, node2);
+ node1->edges.push_back(this);
+ node2->edges.push_back(this);
+}
+
+
+// Given one endpoint of the hyperedge tree edge, returns the other endpoint.
+//
+HyperedgeTreeNode *HyperedgeTreeEdge::followFrom(HyperedgeTreeNode *from) const
+{
+ return (ends.first == from) ? ends.second : ends.first;
+}
+
+
+// Returns true if the length of this edge is zero, i.e., the endpoints are
+// located at the same position.
+//
+bool HyperedgeTreeEdge::zeroLength(void) const
+{
+ return (ends.first->point == ends.second->point);
+}
+
+
+// This method traverses the hyperedge tree and outputs each of the edges
+// and junction positions as SVG objects to the file fp.
+//
+void HyperedgeTreeEdge::outputNodesExcept(FILE *fp, HyperedgeTreeNode *ignored)
+{
+ fprintf(fp, "<path d=\"M %g %g L %g %g\" "
+ "style=\"fill: none; stroke: %s; stroke-width: 2px; "
+ "stroke-opacity: 0.5;\" />\n",
+ ends.first->point.x, ends.first->point.y,
+ ends.second->point.x, ends.second->point.y, "purple");
+ if (ends.first != ignored)
+ {
+ ends.first->outputEdgesExcept(fp, this);
+ }
+
+ if (ends.second != ignored)
+ {
+ ends.second->outputEdgesExcept(fp, this);
+ }
+}
+
+
+// This method returns true if the edge is in the dimension given, i.e.,
+// either horizontal or vertical.
+//
+bool HyperedgeTreeEdge::hasOrientation(const size_t dimension) const
+{
+ return (ends.first->point[dimension] == ends.second->point[dimension]);
+}
+
+
+// This method updates any of the given hyperedge tree edge's endpoints that
+// are attached to oldNode to instead be attached to newNode.
+//
+void HyperedgeTreeEdge::replaceNode(HyperedgeTreeNode *oldNode,
+ HyperedgeTreeNode *newNode)
+{
+ if (ends.first == oldNode)
+ {
+ oldNode->disconnectEdge(this);
+ newNode->edges.push_back(this);
+ ends.first = newNode;
+ }
+ else if (ends.second == oldNode)
+ {
+ oldNode->disconnectEdge(this);
+ newNode->edges.push_back(this);
+ ends.second = newNode;
+ }
+}
+
+
+// This method traverses the hyperedge tree and writes each of the paths
+// back to the individual connectors as routes.
+//
+void HyperedgeTreeEdge::writeEdgesToConns(HyperedgeTreeNode *ignored,
+ size_t pass)
+{
+ COLA_ASSERT(ignored != nullptr);
+ COLA_ASSERT(ends.first != nullptr);
+ COLA_ASSERT(ends.second != nullptr);
+
+ HyperedgeTreeNode *prevNode =
+ (ignored == ends.first) ? ends.first : ends.second;
+ HyperedgeTreeNode *nextNode =
+ (ignored == ends.first) ? ends.second : ends.first;
+
+ if (pass == 0)
+ {
+ conn->m_display_route.clear();
+ }
+ else if (pass == 1)
+ {
+ if (conn->m_display_route.empty())
+ {
+ //printf("[%u] - %g %g\n", conn->id(), prevNode->point.x, prevNode->point.y);
+ conn->m_display_route.ps.push_back(prevNode->point);
+ }
+ //printf("[%u] + %g %g\n", conn->id(), nextNode->point.x, nextNode->point.y);
+ conn->m_display_route.ps.push_back(nextNode->point);
+
+ size_t nextNodeEdges = nextNode->edges.size();
+ if (nextNodeEdges != 2)
+ {
+ // We have finished writing a connector. If the node has just
+ // two edges then it is an intermediate node on a connector.
+ bool shouldReverse = false;
+ if (nextNodeEdges == 1)
+ {
+ // This connector led to a terminal.
+ if (nextNode->isConnectorSource)
+ {
+ shouldReverse = true;
+ }
+
+ if (nextNode->isPinDummyEndpoint)
+ {
+ // If may be that the hyperedge has an extra segment or
+ // two leading to the centre dummy pin used for connection
+ // pin routing. If so, remove these points from the
+ // resulting route.
+ conn->m_display_route.ps.pop_back();
+ if (prevNode->point == nextNode->point)
+ {
+ // Duplicated dummy point. Remove second one.
+ conn->m_display_route.ps.pop_back();
+ }
+ }
+ }
+ else // if (nextNodeEdges > 2)
+ {
+ // This connector was between two junctions.
+ COLA_ASSERT(conn->m_dst_connend);
+ JunctionRef *correctEndJunction =
+ conn->m_dst_connend->junction();
+ if (nextNode->junction != correctEndJunction)
+ {
+ shouldReverse = true;
+ }
+ }
+
+ if (shouldReverse == true)
+ {
+ // Reverse the written connector route.
+ std::reverse(conn->m_display_route.ps.begin(),
+ conn->m_display_route.ps.end());
+ }
+ }
+
+#ifdef DEBUGHANDLER
+ if (conn->router()->debugHandler())
+ {
+ conn->router()->debugHandler()->updateConnectorRoute(
+ conn, -1, -1);
+ }
+#endif
+ }
+
+ nextNode->writeEdgesToConns(this, pass);
+}
+
+// This method traverses the hyperedge tree and creates connectors for each
+// segment bridging junction and/or terminals. It also sets the
+// appropriate ConnEnds for each connector.
+//
+void HyperedgeTreeEdge::addConns(HyperedgeTreeNode *ignored, Router *router,
+ ConnRefList& oldConns)
+{
+ COLA_ASSERT(conn != nullptr);
+ HyperedgeTreeNode *endNode = nullptr;
+ if (ends.first && (ends.first != ignored))
+ {
+ endNode = ends.first;
+ ends.first->addConns(this, router, oldConns, conn);
+ }
+
+ if (ends.second && (ends.second != ignored))
+ {
+ endNode = ends.second;
+ ends.second->addConns(this, router, oldConns, conn);
+ }
+
+ if (endNode->finalVertex)
+ {
+ // We have reached a terminal of the hyperedge, so set a ConnEnd for
+ // the original connector endpoint
+ ConnEnd connend;
+ bool result = false;
+ // Find the ConnEnd from the list of original connectors.
+ for (ConnRefList::iterator curr = oldConns.begin();
+ curr != oldConns.end(); ++curr)
+ {
+ result |= (*curr)->getConnEndForEndpointVertex(
+ endNode->finalVertex, connend);
+ if (result)
+ {
+ break;
+ }
+ }
+ if (result)
+ {
+ // XXX: Create new conn here.
+ conn->updateEndPoint(VertID::tar, connend);
+ }
+ }
+ else if (endNode->junction)
+ {
+ // Or, set a ConnEnd connecting to the junction we have reached.
+ ConnEnd connend(endNode->junction);
+ conn->updateEndPoint(VertID::tar, connend);
+ }
+}
+
+
+// This method traverses the hyperedge tree and rewrites connector ends
+// that may have changed junctions due to major hyperedge improvement.
+//
+void HyperedgeTreeEdge::updateConnEnds(HyperedgeTreeNode *ignored,
+ bool forward, ConnRefList& changedConns)
+{
+ HyperedgeTreeNode *endNode = nullptr;
+ if (ends.first && (ends.first != ignored))
+ {
+ endNode = ends.first;
+ ends.first->updateConnEnds(this, forward, changedConns);
+ }
+
+ if (ends.second && (ends.second != ignored))
+ {
+ endNode = ends.second;
+ ends.second->updateConnEnds(this, forward, changedConns);
+ }
+
+ if (endNode->junction)
+ {
+ // We've reached a junction at the end of this connector, and it's
+ // not an endpoint of the hyperedge. So the connector ConnEnd to
+ // connect to the junction we have reached.
+ std::pair<ConnEnd, ConnEnd> existingEnds = conn->endpointConnEnds();
+ ConnEnd existingEnd = (forward) ?
+ existingEnds.second : existingEnds.first;
+ if (existingEnd.junction() != endNode->junction)
+ {
+#ifdef MAJOR_HYPEREDGE_IMPROVEMENT_DEBUG
+ fprintf(stderr, "HyperedgeImprover: changed %s of "
+ "connector %u (from junction %u to %u)\n",
+ (forward) ? "tar" : "src", conn->id(),
+ existingEnd.junction()->id(), endNode->junction->id());
+#endif
+ ConnEnd connend(endNode->junction);
+ unsigned short end = (forward) ? VertID::tar : VertID::src;
+ conn->updateEndPoint(end, connend);
+
+ // Record that this connector was changed (so long as it wasn't
+ // already recorded).
+ if (changedConns.empty() || (changedConns.back() != conn))
+ {
+ changedConns.push_back(conn);
+ }
+ }
+ }
+}
+
+// This method traverses the hyperedge tree and returns a list of the junctions
+// and connectors that make up the hyperedge.
+//
+void HyperedgeTreeEdge::listJunctionsAndConnectors(HyperedgeTreeNode *ignored,
+ JunctionRefList& junctions, ConnRefList& connectors)
+{
+ ConnRefList::iterator foundPosition =
+ std::find(connectors.begin(), connectors.end(), conn);
+ if (foundPosition == connectors.end())
+ {
+ // Add connector if it isn't already in the list.
+ connectors.push_back(conn);
+ }
+
+ if (ends.first != ignored)
+ {
+ ends.first->listJunctionsAndConnectors(this, junctions, connectors);
+ }
+ else if (ends.second != ignored)
+ {
+ ends.second->listJunctionsAndConnectors(this, junctions, connectors);
+ }
+}
+
+
+void HyperedgeTreeEdge::validateHyperedge(
+ const HyperedgeTreeNode *ignored, const size_t dist) const
+{
+#ifdef MAJOR_HYPEREDGE_IMPROVEMENT_DEBUG
+ for (size_t d = 0; d < dist; ++d)
+ {
+ fprintf(stderr, " ");
+ }
+ fprintf(stderr, "-(%d)\n", conn->id());
+#endif
+ if (ends.first != ignored)
+ {
+ ends.first->validateHyperedge(this, dist);
+ }
+ else if (ends.second != ignored)
+ {
+ ends.second->validateHyperedge(this, dist);
+ }
+}
+
+
+// This method splits the current edge, adding a node at the given point.
+// The current edge will connect the source node and the newly created node.
+// A new edge will connect the new node and the node at the other end of the
+// original edge.
+//
+void HyperedgeTreeEdge::splitFromNodeAtPoint(HyperedgeTreeNode *source,
+ const Point& point)
+{
+ // Make the source the first of the two nodes.
+ if (ends.second == source)
+ {
+ std::swap(ends.second, ends.first);
+ }
+ COLA_ASSERT(ends.first == source);
+
+ // Remember the other end.
+ HyperedgeTreeNode *target = ends.second;
+
+ // Create a new node for the split point at the given position.
+ HyperedgeTreeNode *split = new HyperedgeTreeNode();
+ split->point = point;
+
+ // Create a new edge between the split point and the other end.
+ new HyperedgeTreeEdge(split, target, conn);
+
+ // Disconnect the current edge from the other end and connect it to
+ // the new split point node.
+ target->disconnectEdge(this);
+ ends.second = split;
+ split->edges.push_back(this);
+}
+
+
+// This method disconnects the hyperedge tree edge nodes that it's attached to.
+//
+void HyperedgeTreeEdge::disconnectEdge(void)
+{
+ COLA_ASSERT(ends.first != nullptr);
+ COLA_ASSERT(ends.second != nullptr);
+
+ ends.first->disconnectEdge(this);
+ ends.second->disconnectEdge(this);
+ ends.first = nullptr;
+ ends.second = nullptr;
+}
+
+
+// This method traverses the hyperedge tree and removes from treeRoots any
+// junction nodes.
+//
+bool HyperedgeTreeEdge::removeOtherJunctionsFrom(HyperedgeTreeNode *ignored,
+ JunctionSet& treeRoots)
+{
+ bool containsCycle = false;
+ if (ends.first && (ends.first != ignored))
+ {
+ containsCycle |= ends.first->removeOtherJunctionsFrom(this, treeRoots);
+ }
+
+ if (ends.second && (ends.second != ignored))
+ {
+ containsCycle |= ends.second->removeOtherJunctionsFrom(this, treeRoots);
+ }
+ return containsCycle;
+}
+
+
+// This method traverses the hyperedge tree, clearing up the objects and
+// memory used to store the tree.
+//
+void HyperedgeTreeEdge::deleteNodesExcept(HyperedgeTreeNode *ignored)
+{
+ if (ends.first && (ends.first != ignored))
+ {
+ ends.first->deleteEdgesExcept(this);
+ delete ends.first;
+ }
+ ends.first = nullptr;
+
+ if (ends.second && (ends.second != ignored))
+ {
+ ends.second->deleteEdgesExcept(this);
+ delete ends.second;
+ }
+ ends.second = nullptr;
+}
+
+
+CmpNodesInDim::CmpNodesInDim(const size_t dim)
+ : m_dimension(dim)
+{
+}
+
+
+// Nodes in set are ordered by position along a line in a certain dimension,
+// and then by Node pointer since multiple may exist at a particular position.
+bool CmpNodesInDim::operator()(const HyperedgeTreeNode *lhs,
+ const HyperedgeTreeNode *rhs) const
+{
+ if (lhs->point[m_dimension] != rhs->point[m_dimension])
+ {
+ return lhs->point[m_dimension] < rhs->point[m_dimension];
+ }
+ return lhs < rhs;
+}
+
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/hyperedgetree.h b/src/3rdparty/adaptagrams/libavoid/hyperedgetree.h
new file mode 100644
index 0000000..91c30ad
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/hyperedgetree.h
@@ -0,0 +1,143 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2011-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+#ifndef AVOID_HYPEREDGETREE_H
+#define AVOID_HYPEREDGETREE_H
+
+#include <cstdio>
+#include <list>
+#include <map>
+#include <set>
+#include <utility>
+
+#include "libavoid/geomtypes.h"
+
+//#define MAJOR_HYPEREDGE_IMPROVEMENT_DEBUG
+
+namespace Avoid {
+
+// These classes are not intended for public use.
+// They are used to represent a hyperedge as a tree that certain
+// transformations can be easily performed on to improve the routing
+// of the hyperedge.
+
+class JunctionRef;
+class ConnRef;
+class HyperedgeShiftSegment;
+class VertInf;
+class Router;
+
+struct HyperedgeTreeEdge;
+struct HyperedgeTreeNode;
+
+typedef std::map<JunctionRef *, HyperedgeTreeNode *>
+ JunctionHyperedgeTreeNodeMap;
+typedef std::set<JunctionRef *> JunctionSet;
+typedef std::list<JunctionRef *> JunctionRefList;
+typedef std::list<ConnRef *> ConnRefList;
+
+class CmpNodesInDim;
+
+typedef std::set<HyperedgeTreeNode *, CmpNodesInDim> OrderedHENodeSet;
+
+struct HyperedgeTreeNode
+{
+ HyperedgeTreeNode();
+ ~HyperedgeTreeNode();
+
+ void deleteEdgesExcept(HyperedgeTreeEdge *ignored);
+ bool removeOtherJunctionsFrom(HyperedgeTreeEdge *ignored,
+ JunctionSet &treeRoots);
+ void outputEdgesExcept(FILE *fp, HyperedgeTreeEdge *ignored);
+ void disconnectEdge(HyperedgeTreeEdge *edge);
+ void spliceEdgesFrom(HyperedgeTreeNode *oldNode);
+ void writeEdgesToConns(HyperedgeTreeEdge *ignored, size_t pass);
+ void addConns(HyperedgeTreeEdge *ignored, Router *router,
+ ConnRefList& oldConns, ConnRef *conn);
+ void updateConnEnds(HyperedgeTreeEdge *ignored, bool forward,
+ ConnRefList& changedConns);
+ void listJunctionsAndConnectors(HyperedgeTreeEdge *ignored,
+ JunctionRefList& junctions, ConnRefList& connectors);
+ bool isImmovable(void) const;
+ void validateHyperedge(const HyperedgeTreeEdge *ignored,
+ const size_t dist) const;
+
+ std::list<HyperedgeTreeEdge *> edges;
+ JunctionRef *junction;
+ Point point;
+ OrderedHENodeSet *shiftSegmentNodeSet;
+ VertInf *finalVertex;
+ bool isConnectorSource;
+ bool isPinDummyEndpoint;
+ bool visited;
+};
+
+struct HyperedgeTreeEdge
+{
+ HyperedgeTreeEdge(HyperedgeTreeNode *node1, HyperedgeTreeNode *node2,
+ ConnRef *conn);
+
+ HyperedgeTreeNode *followFrom(HyperedgeTreeNode *from) const;
+ bool zeroLength(void) const;
+ void splitFromNodeAtPoint(HyperedgeTreeNode *source, const Point& point);
+ bool hasOrientation(const size_t dimension) const;
+ void outputNodesExcept(FILE *file, HyperedgeTreeNode *ignored);
+ void deleteNodesExcept(HyperedgeTreeNode *ignored);
+ bool removeOtherJunctionsFrom(HyperedgeTreeNode *ignored,
+ JunctionSet &treeRoots);
+ void writeEdgesToConns(HyperedgeTreeNode *ignored, size_t pass);
+ void addConns(HyperedgeTreeNode *ignored, Router *router,
+ ConnRefList& oldConns);
+ void updateConnEnds(HyperedgeTreeNode *ignored, bool forward,
+ ConnRefList& changedConns);
+ void disconnectEdge(void);
+ void replaceNode(HyperedgeTreeNode *oldNode,
+ HyperedgeTreeNode *newNode);
+ void listJunctionsAndConnectors(HyperedgeTreeNode *ignored,
+ JunctionRefList& junctions, ConnRefList& connectors);
+ void validateHyperedge(const HyperedgeTreeNode *ignored,
+ const size_t dist) const;
+
+ std::pair<HyperedgeTreeNode *, HyperedgeTreeNode *> ends;
+ ConnRef *conn;
+ bool hasFixedRoute;
+};
+
+
+typedef std::map<VertInf *, HyperedgeTreeNode *> VertexNodeMap;
+
+
+class CmpNodesInDim
+{
+ public:
+ CmpNodesInDim(const size_t dim);
+ bool operator()(const HyperedgeTreeNode *lhs,
+ const HyperedgeTreeNode *rhs) const;
+ private:
+ const size_t m_dimension;
+};
+
+}
+
+#endif
diff --git a/src/3rdparty/adaptagrams/libavoid/junction.cpp b/src/3rdparty/adaptagrams/libavoid/junction.cpp
new file mode 100644
index 0000000..f17e37e
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/junction.cpp
@@ -0,0 +1,233 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2010-2011 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+#include <cstdlib>
+#include <algorithm>
+
+#include "libavoid/junction.h"
+#include "libavoid/router.h"
+#include "libavoid/connectionpin.h"
+#include "libavoid/debug.h"
+
+
+namespace Avoid {
+
+
+JunctionRef::JunctionRef(Router *router, Point position, const unsigned int id)
+ : Obstacle(router, makeRectangle(router, position), id),
+ m_position(position),
+ m_recommended_position(position),
+ m_position_fixed(false)
+{
+ // For Junctions we use a single non-exclusive pin.
+ ShapeConnectionPin *pin = new Avoid::ShapeConnectionPin(this,
+ Avoid::CONNECTIONPIN_CENTRE, ConnDirAll);
+ pin->setExclusive(false);
+ m_connection_pins.insert(pin);
+
+ m_router->addJunction(this);
+}
+
+JunctionRef::~JunctionRef()
+{
+ if (m_router->m_currently_calling_destructors == false)
+ {
+ err_printf("ERROR: JunctionRef::~JunctionRef() shouldn't be called directly.\n");
+ err_printf(" It is owned by the router. Call Router::deleteJunction() instead.\n");
+ abort();
+ }
+}
+
+
+Rectangle JunctionRef::makeRectangle(Router *router, const Point& position)
+{
+ COLA_ASSERT(router);
+
+ // A suitably small value.
+ double nudgeDist = router->routingParameter(idealNudgingDistance);
+ nudgeDist = std::min(1.0, nudgeDist);
+
+ Point low = position;
+ low.x -= nudgeDist;
+ low.y -= nudgeDist;
+
+ Point high = position;
+ high.x += nudgeDist;
+ high.y += nudgeDist;
+
+ return Rectangle(low, high);
+}
+
+
+void JunctionRef::setPositionFixed(bool fixed)
+{
+ m_position_fixed = fixed;
+ m_router->registerSettingsChange();
+}
+
+
+bool JunctionRef::positionFixed(void) const
+{
+ return m_position_fixed;
+}
+
+
+void JunctionRef::preferOrthogonalDimension(const size_t dim)
+{
+ const double smallPenalty = 1.0;
+ for (ShapeConnectionPinSet::iterator curr =
+ m_connection_pins.begin(); curr != m_connection_pins.end(); ++curr)
+ {
+ ShapeConnectionPin *pin = *curr;
+ if (dim == YDIM)
+ {
+ if (pin->directions() & (ConnDirLeft | ConnDirRight))
+ {
+ pin->setConnectionCost(smallPenalty);
+ }
+ }
+ else if (dim == XDIM)
+ {
+ if (pin->directions() & (ConnDirUp | ConnDirDown))
+ {
+ pin->setConnectionCost(smallPenalty);
+ }
+ }
+ }
+}
+
+
+Point JunctionRef::position(void) const
+{
+ return m_position;
+}
+
+
+void JunctionRef::setPosition(const Point& position)
+{
+ m_position = position;
+ m_recommended_position = position;
+ m_polygon = makeRectangle(m_router, m_position);
+ setNewPoly(m_polygon);
+}
+
+
+Point JunctionRef::recommendedPosition(void) const
+{
+ return m_recommended_position;
+}
+
+
+void JunctionRef::setRecommendedPosition(const Point& position)
+{
+ m_recommended_position = position;
+}
+
+
+void JunctionRef::outputCode(FILE *fp) const
+{
+ fprintf(fp, " JunctionRef *junctionRef%u = new JunctionRef(router, "
+ "Point(%g, %g), %u);\n", id(), position().x, position().y, id());
+ if (m_position_fixed)
+ {
+ fprintf(fp, " junctionRef%u->setPositionFixed(true);\n", id());
+ }
+
+ fprintf(fp, " /*\n");
+ fprintf(fp, " // This may be useful if junction pins are modified.\n");
+ for (ShapeConnectionPinSet::const_iterator curr =
+ m_connection_pins.begin();
+ curr != m_connection_pins.end(); ++curr)
+ {
+ (*curr)->outputCode(fp);
+ }
+ fprintf(fp, " */\n");
+ fprintf(fp, "\n");
+}
+
+
+void JunctionRef::moveAttachedConns(const Point& newPosition)
+{
+ // Update positions of attached connector ends.
+ for (std::set<ConnEnd *>::iterator curr = m_following_conns.begin();
+ curr != m_following_conns.end(); ++curr)
+ {
+ ConnEnd *connEnd = *curr;
+ COLA_ASSERT(connEnd->m_conn_ref != nullptr);
+ m_router->modifyConnector(connEnd->m_conn_ref, connEnd->endpointType(),
+ *connEnd);
+ }
+ for (ShapeConnectionPinSet::iterator curr =
+ m_connection_pins.begin(); curr != m_connection_pins.end(); ++curr)
+ {
+ ShapeConnectionPin *pin = *curr;
+ pin->updatePosition(newPosition);
+ }
+}
+
+
+ConnRef *JunctionRef::removeJunctionAndMergeConnectors(void)
+{
+ if (m_following_conns.size() != 2)
+ {
+ return nullptr;
+ }
+
+ std::set<ConnEnd *>::iterator curr = m_following_conns.begin();
+ ConnEnd *connEnd1 = *curr;
+ ++curr;
+ ConnEnd *connEnd2 = *curr;
+ COLA_ASSERT(connEnd2->m_conn_ref != nullptr);
+ COLA_ASSERT(connEnd1->m_conn_ref != nullptr);
+
+ // The second conn will be the one we will delete.
+ ConnRef *conn2 = connEnd2->m_conn_ref;
+ // Determine its endpoint that is not attached to the junction.
+ ConnEnd *connEnd2Other = (conn2->m_src_connend == connEnd2) ?
+ conn2->m_dst_connend : conn2->m_src_connend;
+ if (connEnd2Other == nullptr)
+ {
+ // If it doesn't have a valid other endpoint, then ignore.
+ return nullptr;
+ }
+ // Modify the first connector's junction endpoint to connect to the
+ // other end of the second connector.
+ m_router->modifyConnector(connEnd1->m_conn_ref,
+ connEnd1->endpointType(), *connEnd2Other);
+
+ // Delete the second connector.
+ m_router->deleteConnector(conn2);
+
+ // Remove the junction from the router scene. It should get deleted later.
+ m_router->deleteJunction(this);
+
+ // Return the first (i.e. merged) connector.
+ return connEnd1->m_conn_ref;
+}
+
+
+//============================================================================
+}
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/junction.h b/src/3rdparty/adaptagrams/libavoid/junction.h
new file mode 100644
index 0000000..f348c39
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/junction.h
@@ -0,0 +1,197 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2010-2015 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+//! @file junction.h
+//! @brief Contains the interface for the JunctionRef class.
+
+
+#ifndef AVOID_JUNCTION_H
+#define AVOID_JUNCTION_H
+
+#include <list>
+#include <set>
+
+#include "libavoid/geomtypes.h"
+#include "libavoid/obstacle.h"
+#include "libavoid/dllexport.h"
+
+namespace Avoid {
+
+class Router;
+class VertInf;
+class ConnEnd;
+class ConnRef;
+class ShapeConnectionPin;
+class JunctionRef;
+typedef std::list<JunctionRef *> JunctionRefList;
+
+
+//! @brief The JunctionRef class represents a fixed or free-floating point that
+//! connectors can be attached to.
+//!
+//! A JunctionRef represents a junction between multiple connectors, or could
+//! be used to specify an intermediate point that a single connector must route
+//! through.
+//!
+class AVOID_EXPORT JunctionRef : public Obstacle
+{
+ public:
+ //! @brief Junction reference constructor.
+ //!
+ //! Creates a junction object reference, and adds it to the router
+ //! scene. This junction will be considered to be an obstacle.
+ //! This will cause connectors intersecting the newly added junction
+ //! to be marked as needing to be rerouted.
+ //!
+ //! If the router is using transactions, then changes will occur
+ //! the next time Router::processTransaction() is called. See
+ //! Router::setTransactionUse() for more information.
+ //!
+ //! The junction can be moved with Router::moveJunction() and removed
+ //! from the scene and freed with Router::deleteJunction().
+ //!
+ //! libavoid expects junctions to have sensible positions (i.e.,
+ //! for junctions to be positioned outside of shapes). When routing
+ //! it will simplify hyperedges by moving junctions while preserving
+ //! hyperedge topology, i.e., not altering the sides of shapes the
+ //! hyperedge routes around.
+ //!
+ //! If you don't have sensible positions for junctions or want to
+ //! disregard the junction position and reroute the entire hyperedge
+ //! considering only the endpoints, then this can be achieved by
+ //! registering the hyperedge with the HyperedgeRerouter class
+ //! obtained by calling the Router::hyperedgeRerouter() method.
+ //!
+ //! When the improveHyperedgeRoutesMovingJunctions router option is
+ //! set (the default) the junction position is a suggestion used for
+ //! initial routing, but subsequent hyperedge path improvement may
+ //! suggest new junction positions for the updated routings. This
+ //! position can be accessed via the recommendedPosition() method.
+ //!
+ //! When the improveHyperedgeRoutesMovingAddingAndDeletingJunctions
+ //! router option is set (not the default) junctions and connectors
+ //! can be added or removed to further improve hyperedges, see also
+ //! Router::newAndDeletedObjectListsFromHyperedgeImprovement().
+ //!
+ //! @note Regarding IDs:
+ //! You can let libavoid manually handle IDs by not specifying
+ //! them. Alternatively, you can specify all IDs yourself, but
+ //! you must be careful to makes sure that each object in the
+ //! scene (shape, connector, cluster, etc.) is given a unique,
+ //! positive ID. This uniqueness is checked if assertions are
+ //! enabled, but if not and there are clashes then strange
+ //! things can happen.
+ //!
+ //! @param[in] router The router scene to place the junction into.
+ //! @param[in] position A Point representing the position of the
+ //! junction.
+ //! @param[in] id Optionally, a positive integer ID unique
+ //! among all objects.
+ //!
+ JunctionRef(Router *router, Point position, const unsigned int id = 0);
+
+// To prevent C++ objects from being destroyed in garbage collected languages
+// when the libraries are called from SWIG, we hide the declarations of the
+// destructors and prevent generation of default destructors.
+#ifndef SWIG
+ //! @brief Junction reference destructor.
+ //!
+ //! Do not call this yourself, instead call Router::deleteJunction().
+ //! Ownership of this object belongs to the router scene.
+ virtual ~JunctionRef();
+#endif
+
+ //! @brief Removes a junction that has only two connectors attached
+ //! to it and merges them into a single connector.
+ //!
+ //! The junction and one of the connectors will be removed from the
+ //! router scene and the connector deleted. A pointer to the
+ //! remaining (merged) connector will be returned by this method.
+ //!
+ //! Currently this method does not delete and free the Junction itself.
+ //! The user needs to do this after the transaction has been
+ //! processed by the router.
+ //!
+ //! If there are more than two connectors attached to the junction
+ //! then nothing will be changed and this method will return nullptr.
+ //!
+ //! @return The merged connector, or nullptr if the junction was not
+ //! removed.
+ ConnRef *removeJunctionAndMergeConnectors(void);
+
+ //! @brief Returns the position of this junction.
+ //! @returns A point representing the position of this junction.
+ Point position(void) const;
+
+ //! @brief Sets whether the junction has a fixed position and
+ //! therefore can't be moved by the Router during routing.
+ //!
+ //! This property is ignored for hyperedge improvement if the option
+ //! improveHyperedgeRoutesMovingAddingAndDeletingJunctions is set and
+ //! when it would lead to confusing hyperedge topology, such as two
+ //! overlapping junctions with a zero length connector between them
+ //! or an unnecessary junction bridging two connectors.
+ //!
+ //! @param[in] fixed Boolean indicating whether the junction position
+ //! should be marked as fixed.
+ void setPositionFixed(bool fixed);
+
+ //! @brief Returns whether this junction has a fixed position (that
+ //! can't be moved by the Router during routing).
+ //! @returns A point representing the position of this junction.
+ bool positionFixed(void) const;
+
+ //! @brief Returns a recommended position for the junction based on
+ //! improving hyperedge routes. This value will be set during
+ //! routing when the improveHyperedgeRoutesMovingJunctions
+ //! router option is set (the default).
+ //! @returns A point indicating the ideal position for this junction.
+ Point recommendedPosition(void) const;
+
+ Rectangle makeRectangle(Router *router, const Point& position);
+ void preferOrthogonalDimension(const size_t dim);
+
+ private:
+ friend class Router;
+ friend class ShapeConnectionPin;
+ friend class ConnEnd;
+ friend class HyperedgeImprover;
+
+ void outputCode(FILE *fp) const;
+ void setPosition(const Point& position);
+ void setRecommendedPosition(const Point& position);
+ void moveAttachedConns(const Point& newPosition);
+
+ Point m_position;
+ Point m_recommended_position;
+ bool m_position_fixed;
+};
+
+
+}
+
+
+#endif
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/libavoid.h b/src/3rdparty/adaptagrams/libavoid/libavoid.h
new file mode 100644
index 0000000..3151a3e
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/libavoid.h
@@ -0,0 +1,55 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2009 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+//! @file libavoid.h
+//! @brief Standard libavoid include file which includes all libavoid
+//! header files.
+
+/**
+ * @namespace Avoid
+ * @brief libavoid: Object-avoiding orthogonal and polyline connector
+ * routing library.
+ *
+ * You should use libavoid via an instance of the Router class.
+ */
+#ifndef AVOID_LIBAVOID_H
+#define AVOID_LIBAVOID_H
+
+#include "libavoid/geomtypes.h"
+#include "libavoid/shape.h"
+#include "libavoid/connector.h"
+#include "libavoid/connend.h"
+#include "libavoid/graph.h"
+#include "libavoid/debug.h"
+#include "libavoid/timer.h"
+#include "libavoid/vertices.h"
+#include "libavoid/visibility.h"
+#include "libavoid/router.h"
+#include "libavoid/connectionpin.h"
+#include "libavoid/junction.h"
+#include "libavoid/viscluster.h"
+
+#endif
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/libavoid.pc.in b/src/3rdparty/adaptagrams/libavoid/libavoid.pc.in
new file mode 100644
index 0000000..8f16d06
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/libavoid.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libavoid
+Description: A library for object-avoiding polyline and orthogonal connector routing for use in interactive diagram editors.
+URL: http://www.adaptagrams.org/
+Version: @VERSION@
+Requires:
+Libs: -L${libdir} -lavoid
+Cflags: -I${includedir}/libavoid \ No newline at end of file
diff --git a/src/3rdparty/adaptagrams/libavoid/libavoid.sln b/src/3rdparty/adaptagrams/libavoid/libavoid.sln
new file mode 100755
index 0000000..aa9f8e1
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/libavoid.sln
@@ -0,0 +1,196 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libavoid", "libavoid.vcxproj", "{798C3D94-BF71-4C72-A29D-0E74C2EB296A}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "2junctions", "tests\msctests\2junctions.vcxproj", "{4C07F666-EB74-44E9-811C-57CFCCC553C8}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example", "tests\msctests\example.vcxproj", "{6943E11D-22DE-4F6A-A30E-C7D23681B507}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "buildOrthogonalChannelInfo1", "tests\msctests\buildOrthogonalChannelInfo1.vcxproj", "{022C18E8-4B2A-4CF0-8660-9B691473C20E}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "checkpointNudging1", "tests\msctests\checkpointNudging1.vcxproj", "{33240DD8-FDA7-4157-B022-C71E0B29467B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "checkpointNudging2", "tests\msctests\checkpointNudging2.vcxproj", "{97CCD32F-F345-4B41-BC79-50EE7644FCCD}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "checkpoints01", "tests\msctests\checkpoints01.vcxproj", "{6C2BA2FB-CD3A-409E-B87B-6A105C7CCA48}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "junction01", "tests\msctests\junction01.vcxproj", "{35D83117-8DA7-495E-A045-DFDC555227C8}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "complex", "tests\msctests\complex.vcxproj", "{EE121773-CBA2-473D-8C8C-4FCA709DE828}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "connectionpin01", "tests\msctests\connectionpin01.vcxproj", "{F77FA86C-07F5-468C-A162-479EEE7AEC45}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "connectionpin02", "tests\msctests\connectionpin02.vcxproj", "{E570E7C6-CFF4-4639-855E-4C1E02F0DD85}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "connectionpin03", "tests\msctests\connectionpin03.vcxproj", "{69ED412A-63E6-4057-9517-D06A55DD99B0}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "connendmove", "tests\msctests\connendmove.vcxproj", "{980B4C23-428F-48A1-9111-40AA4777C246}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "corneroverlap01", "tests\msctests\corneroverlap01.vcxproj", "{8E4B6939-A58A-4DF0-B799-5662E25B7BAD}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "finalSegmentNudging1", "tests\msctests\finalSegmentNudging1.vcxproj", "{DDD617A0-FFE1-4C05-8144-06F637FB1C7B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "finalSegmentNudging2", "tests\msctests\finalSegmentNudging2.vcxproj", "{A5A5A67A-A961-4AA1-A248-196D91406169}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "finalSegmentNudging3", "tests\msctests\finalSegmentNudging3.vcxproj", "{6C94F0E2-5A2C-4D6D-93FC-43B9A5A578AF}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "freeFloatingDirection01", "tests\msctests\freeFloatingDirection01.vcxproj", "{8DB197B1-20B2-485D-B89E-D9A7674193BD}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {798C3D94-BF71-4C72-A29D-0E74C2EB296A}.Debug|Win32.ActiveCfg = Debug|Win32
+ {798C3D94-BF71-4C72-A29D-0E74C2EB296A}.Debug|Win32.Build.0 = Debug|Win32
+ {798C3D94-BF71-4C72-A29D-0E74C2EB296A}.Debug|x64.ActiveCfg = Debug|x64
+ {798C3D94-BF71-4C72-A29D-0E74C2EB296A}.Debug|x64.Build.0 = Debug|x64
+ {798C3D94-BF71-4C72-A29D-0E74C2EB296A}.Release|Win32.ActiveCfg = Release|Win32
+ {798C3D94-BF71-4C72-A29D-0E74C2EB296A}.Release|Win32.Build.0 = Release|Win32
+ {798C3D94-BF71-4C72-A29D-0E74C2EB296A}.Release|x64.ActiveCfg = Release|x64
+ {798C3D94-BF71-4C72-A29D-0E74C2EB296A}.Release|x64.Build.0 = Release|x64
+ {4C07F666-EB74-44E9-811C-57CFCCC553C8}.Debug|Win32.ActiveCfg = Debug|Win32
+ {4C07F666-EB74-44E9-811C-57CFCCC553C8}.Debug|Win32.Build.0 = Debug|Win32
+ {4C07F666-EB74-44E9-811C-57CFCCC553C8}.Debug|x64.ActiveCfg = Debug|x64
+ {4C07F666-EB74-44E9-811C-57CFCCC553C8}.Debug|x64.Build.0 = Debug|x64
+ {4C07F666-EB74-44E9-811C-57CFCCC553C8}.Release|Win32.ActiveCfg = Release|Win32
+ {4C07F666-EB74-44E9-811C-57CFCCC553C8}.Release|Win32.Build.0 = Release|Win32
+ {4C07F666-EB74-44E9-811C-57CFCCC553C8}.Release|x64.ActiveCfg = Release|x64
+ {4C07F666-EB74-44E9-811C-57CFCCC553C8}.Release|x64.Build.0 = Release|x64
+ {6943E11D-22DE-4F6A-A30E-C7D23681B507}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6943E11D-22DE-4F6A-A30E-C7D23681B507}.Debug|Win32.Build.0 = Debug|Win32
+ {6943E11D-22DE-4F6A-A30E-C7D23681B507}.Debug|x64.ActiveCfg = Debug|x64
+ {6943E11D-22DE-4F6A-A30E-C7D23681B507}.Debug|x64.Build.0 = Debug|x64
+ {6943E11D-22DE-4F6A-A30E-C7D23681B507}.Release|Win32.ActiveCfg = Release|Win32
+ {6943E11D-22DE-4F6A-A30E-C7D23681B507}.Release|Win32.Build.0 = Release|Win32
+ {6943E11D-22DE-4F6A-A30E-C7D23681B507}.Release|x64.ActiveCfg = Release|x64
+ {6943E11D-22DE-4F6A-A30E-C7D23681B507}.Release|x64.Build.0 = Release|x64
+ {022C18E8-4B2A-4CF0-8660-9B691473C20E}.Debug|Win32.ActiveCfg = Debug|Win32
+ {022C18E8-4B2A-4CF0-8660-9B691473C20E}.Debug|Win32.Build.0 = Debug|Win32
+ {022C18E8-4B2A-4CF0-8660-9B691473C20E}.Debug|x64.ActiveCfg = Debug|x64
+ {022C18E8-4B2A-4CF0-8660-9B691473C20E}.Debug|x64.Build.0 = Debug|x64
+ {022C18E8-4B2A-4CF0-8660-9B691473C20E}.Release|Win32.ActiveCfg = Release|Win32
+ {022C18E8-4B2A-4CF0-8660-9B691473C20E}.Release|Win32.Build.0 = Release|Win32
+ {022C18E8-4B2A-4CF0-8660-9B691473C20E}.Release|x64.ActiveCfg = Release|x64
+ {022C18E8-4B2A-4CF0-8660-9B691473C20E}.Release|x64.Build.0 = Release|x64
+ {33240DD8-FDA7-4157-B022-C71E0B29467B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {33240DD8-FDA7-4157-B022-C71E0B29467B}.Debug|Win32.Build.0 = Debug|Win32
+ {33240DD8-FDA7-4157-B022-C71E0B29467B}.Debug|x64.ActiveCfg = Debug|x64
+ {33240DD8-FDA7-4157-B022-C71E0B29467B}.Debug|x64.Build.0 = Debug|x64
+ {33240DD8-FDA7-4157-B022-C71E0B29467B}.Release|Win32.ActiveCfg = Release|Win32
+ {33240DD8-FDA7-4157-B022-C71E0B29467B}.Release|Win32.Build.0 = Release|Win32
+ {33240DD8-FDA7-4157-B022-C71E0B29467B}.Release|x64.ActiveCfg = Release|x64
+ {33240DD8-FDA7-4157-B022-C71E0B29467B}.Release|x64.Build.0 = Release|x64
+ {97CCD32F-F345-4B41-BC79-50EE7644FCCD}.Debug|Win32.ActiveCfg = Debug|Win32
+ {97CCD32F-F345-4B41-BC79-50EE7644FCCD}.Debug|Win32.Build.0 = Debug|Win32
+ {97CCD32F-F345-4B41-BC79-50EE7644FCCD}.Debug|x64.ActiveCfg = Debug|x64
+ {97CCD32F-F345-4B41-BC79-50EE7644FCCD}.Debug|x64.Build.0 = Debug|x64
+ {97CCD32F-F345-4B41-BC79-50EE7644FCCD}.Release|Win32.ActiveCfg = Release|Win32
+ {97CCD32F-F345-4B41-BC79-50EE7644FCCD}.Release|Win32.Build.0 = Release|Win32
+ {97CCD32F-F345-4B41-BC79-50EE7644FCCD}.Release|x64.ActiveCfg = Release|x64
+ {97CCD32F-F345-4B41-BC79-50EE7644FCCD}.Release|x64.Build.0 = Release|x64
+ {6C2BA2FB-CD3A-409E-B87B-6A105C7CCA48}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6C2BA2FB-CD3A-409E-B87B-6A105C7CCA48}.Debug|Win32.Build.0 = Debug|Win32
+ {6C2BA2FB-CD3A-409E-B87B-6A105C7CCA48}.Debug|x64.ActiveCfg = Debug|x64
+ {6C2BA2FB-CD3A-409E-B87B-6A105C7CCA48}.Debug|x64.Build.0 = Debug|x64
+ {6C2BA2FB-CD3A-409E-B87B-6A105C7CCA48}.Release|Win32.ActiveCfg = Release|Win32
+ {6C2BA2FB-CD3A-409E-B87B-6A105C7CCA48}.Release|Win32.Build.0 = Release|Win32
+ {6C2BA2FB-CD3A-409E-B87B-6A105C7CCA48}.Release|x64.ActiveCfg = Release|x64
+ {6C2BA2FB-CD3A-409E-B87B-6A105C7CCA48}.Release|x64.Build.0 = Release|x64
+ {35D83117-8DA7-495E-A045-DFDC555227C8}.Debug|Win32.ActiveCfg = Debug|Win32
+ {35D83117-8DA7-495E-A045-DFDC555227C8}.Debug|Win32.Build.0 = Debug|Win32
+ {35D83117-8DA7-495E-A045-DFDC555227C8}.Debug|x64.ActiveCfg = Debug|x64
+ {35D83117-8DA7-495E-A045-DFDC555227C8}.Debug|x64.Build.0 = Debug|x64
+ {35D83117-8DA7-495E-A045-DFDC555227C8}.Release|Win32.ActiveCfg = Release|Win32
+ {35D83117-8DA7-495E-A045-DFDC555227C8}.Release|Win32.Build.0 = Release|Win32
+ {35D83117-8DA7-495E-A045-DFDC555227C8}.Release|x64.ActiveCfg = Release|x64
+ {35D83117-8DA7-495E-A045-DFDC555227C8}.Release|x64.Build.0 = Release|x64
+ {EE121773-CBA2-473D-8C8C-4FCA709DE828}.Debug|Win32.ActiveCfg = Debug|Win32
+ {EE121773-CBA2-473D-8C8C-4FCA709DE828}.Debug|Win32.Build.0 = Debug|Win32
+ {EE121773-CBA2-473D-8C8C-4FCA709DE828}.Debug|x64.ActiveCfg = Debug|x64
+ {EE121773-CBA2-473D-8C8C-4FCA709DE828}.Debug|x64.Build.0 = Debug|x64
+ {EE121773-CBA2-473D-8C8C-4FCA709DE828}.Release|Win32.ActiveCfg = Release|Win32
+ {EE121773-CBA2-473D-8C8C-4FCA709DE828}.Release|Win32.Build.0 = Release|Win32
+ {EE121773-CBA2-473D-8C8C-4FCA709DE828}.Release|x64.ActiveCfg = Release|x64
+ {EE121773-CBA2-473D-8C8C-4FCA709DE828}.Release|x64.Build.0 = Release|x64
+ {F77FA86C-07F5-468C-A162-479EEE7AEC45}.Debug|Win32.ActiveCfg = Debug|Win32
+ {F77FA86C-07F5-468C-A162-479EEE7AEC45}.Debug|Win32.Build.0 = Debug|Win32
+ {F77FA86C-07F5-468C-A162-479EEE7AEC45}.Debug|x64.ActiveCfg = Debug|x64
+ {F77FA86C-07F5-468C-A162-479EEE7AEC45}.Debug|x64.Build.0 = Debug|x64
+ {F77FA86C-07F5-468C-A162-479EEE7AEC45}.Release|Win32.ActiveCfg = Release|Win32
+ {F77FA86C-07F5-468C-A162-479EEE7AEC45}.Release|Win32.Build.0 = Release|Win32
+ {F77FA86C-07F5-468C-A162-479EEE7AEC45}.Release|x64.ActiveCfg = Release|x64
+ {F77FA86C-07F5-468C-A162-479EEE7AEC45}.Release|x64.Build.0 = Release|x64
+ {E570E7C6-CFF4-4639-855E-4C1E02F0DD85}.Debug|Win32.ActiveCfg = Debug|Win32
+ {E570E7C6-CFF4-4639-855E-4C1E02F0DD85}.Debug|Win32.Build.0 = Debug|Win32
+ {E570E7C6-CFF4-4639-855E-4C1E02F0DD85}.Debug|x64.ActiveCfg = Debug|x64
+ {E570E7C6-CFF4-4639-855E-4C1E02F0DD85}.Debug|x64.Build.0 = Debug|x64
+ {E570E7C6-CFF4-4639-855E-4C1E02F0DD85}.Release|Win32.ActiveCfg = Release|Win32
+ {E570E7C6-CFF4-4639-855E-4C1E02F0DD85}.Release|Win32.Build.0 = Release|Win32
+ {E570E7C6-CFF4-4639-855E-4C1E02F0DD85}.Release|x64.ActiveCfg = Release|x64
+ {E570E7C6-CFF4-4639-855E-4C1E02F0DD85}.Release|x64.Build.0 = Release|x64
+ {69ED412A-63E6-4057-9517-D06A55DD99B0}.Debug|Win32.ActiveCfg = Debug|Win32
+ {69ED412A-63E6-4057-9517-D06A55DD99B0}.Debug|Win32.Build.0 = Debug|Win32
+ {69ED412A-63E6-4057-9517-D06A55DD99B0}.Debug|x64.ActiveCfg = Debug|x64
+ {69ED412A-63E6-4057-9517-D06A55DD99B0}.Debug|x64.Build.0 = Debug|x64
+ {69ED412A-63E6-4057-9517-D06A55DD99B0}.Release|Win32.ActiveCfg = Release|Win32
+ {69ED412A-63E6-4057-9517-D06A55DD99B0}.Release|Win32.Build.0 = Release|Win32
+ {69ED412A-63E6-4057-9517-D06A55DD99B0}.Release|x64.ActiveCfg = Release|x64
+ {69ED412A-63E6-4057-9517-D06A55DD99B0}.Release|x64.Build.0 = Release|x64
+ {980B4C23-428F-48A1-9111-40AA4777C246}.Debug|Win32.ActiveCfg = Debug|Win32
+ {980B4C23-428F-48A1-9111-40AA4777C246}.Debug|Win32.Build.0 = Debug|Win32
+ {980B4C23-428F-48A1-9111-40AA4777C246}.Debug|x64.ActiveCfg = Debug|x64
+ {980B4C23-428F-48A1-9111-40AA4777C246}.Debug|x64.Build.0 = Debug|x64
+ {980B4C23-428F-48A1-9111-40AA4777C246}.Release|Win32.ActiveCfg = Release|Win32
+ {980B4C23-428F-48A1-9111-40AA4777C246}.Release|Win32.Build.0 = Release|Win32
+ {980B4C23-428F-48A1-9111-40AA4777C246}.Release|x64.ActiveCfg = Release|x64
+ {980B4C23-428F-48A1-9111-40AA4777C246}.Release|x64.Build.0 = Release|x64
+ {8E4B6939-A58A-4DF0-B799-5662E25B7BAD}.Debug|Win32.ActiveCfg = Debug|Win32
+ {8E4B6939-A58A-4DF0-B799-5662E25B7BAD}.Debug|Win32.Build.0 = Debug|Win32
+ {8E4B6939-A58A-4DF0-B799-5662E25B7BAD}.Debug|x64.ActiveCfg = Debug|x64
+ {8E4B6939-A58A-4DF0-B799-5662E25B7BAD}.Debug|x64.Build.0 = Debug|x64
+ {8E4B6939-A58A-4DF0-B799-5662E25B7BAD}.Release|Win32.ActiveCfg = Release|Win32
+ {8E4B6939-A58A-4DF0-B799-5662E25B7BAD}.Release|Win32.Build.0 = Release|Win32
+ {8E4B6939-A58A-4DF0-B799-5662E25B7BAD}.Release|x64.ActiveCfg = Release|x64
+ {8E4B6939-A58A-4DF0-B799-5662E25B7BAD}.Release|x64.Build.0 = Release|x64
+ {DDD617A0-FFE1-4C05-8144-06F637FB1C7B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {DDD617A0-FFE1-4C05-8144-06F637FB1C7B}.Debug|Win32.Build.0 = Debug|Win32
+ {DDD617A0-FFE1-4C05-8144-06F637FB1C7B}.Debug|x64.ActiveCfg = Debug|x64
+ {DDD617A0-FFE1-4C05-8144-06F637FB1C7B}.Debug|x64.Build.0 = Debug|x64
+ {DDD617A0-FFE1-4C05-8144-06F637FB1C7B}.Release|Win32.ActiveCfg = Release|Win32
+ {DDD617A0-FFE1-4C05-8144-06F637FB1C7B}.Release|Win32.Build.0 = Release|Win32
+ {DDD617A0-FFE1-4C05-8144-06F637FB1C7B}.Release|x64.ActiveCfg = Release|x64
+ {DDD617A0-FFE1-4C05-8144-06F637FB1C7B}.Release|x64.Build.0 = Release|x64
+ {A5A5A67A-A961-4AA1-A248-196D91406169}.Debug|Win32.ActiveCfg = Debug|Win32
+ {A5A5A67A-A961-4AA1-A248-196D91406169}.Debug|Win32.Build.0 = Debug|Win32
+ {A5A5A67A-A961-4AA1-A248-196D91406169}.Debug|x64.ActiveCfg = Debug|x64
+ {A5A5A67A-A961-4AA1-A248-196D91406169}.Debug|x64.Build.0 = Debug|x64
+ {A5A5A67A-A961-4AA1-A248-196D91406169}.Release|Win32.ActiveCfg = Release|Win32
+ {A5A5A67A-A961-4AA1-A248-196D91406169}.Release|Win32.Build.0 = Release|Win32
+ {A5A5A67A-A961-4AA1-A248-196D91406169}.Release|x64.ActiveCfg = Release|x64
+ {A5A5A67A-A961-4AA1-A248-196D91406169}.Release|x64.Build.0 = Release|x64
+ {6C94F0E2-5A2C-4D6D-93FC-43B9A5A578AF}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6C94F0E2-5A2C-4D6D-93FC-43B9A5A578AF}.Debug|Win32.Build.0 = Debug|Win32
+ {6C94F0E2-5A2C-4D6D-93FC-43B9A5A578AF}.Debug|x64.ActiveCfg = Debug|x64
+ {6C94F0E2-5A2C-4D6D-93FC-43B9A5A578AF}.Debug|x64.Build.0 = Debug|x64
+ {6C94F0E2-5A2C-4D6D-93FC-43B9A5A578AF}.Release|Win32.ActiveCfg = Release|Win32
+ {6C94F0E2-5A2C-4D6D-93FC-43B9A5A578AF}.Release|Win32.Build.0 = Release|Win32
+ {6C94F0E2-5A2C-4D6D-93FC-43B9A5A578AF}.Release|x64.ActiveCfg = Release|x64
+ {6C94F0E2-5A2C-4D6D-93FC-43B9A5A578AF}.Release|x64.Build.0 = Release|x64
+ {8DB197B1-20B2-485D-B89E-D9A7674193BD}.Debug|Win32.ActiveCfg = Debug|Win32
+ {8DB197B1-20B2-485D-B89E-D9A7674193BD}.Debug|Win32.Build.0 = Debug|Win32
+ {8DB197B1-20B2-485D-B89E-D9A7674193BD}.Debug|x64.ActiveCfg = Debug|x64
+ {8DB197B1-20B2-485D-B89E-D9A7674193BD}.Debug|x64.Build.0 = Debug|x64
+ {8DB197B1-20B2-485D-B89E-D9A7674193BD}.Release|Win32.ActiveCfg = Release|Win32
+ {8DB197B1-20B2-485D-B89E-D9A7674193BD}.Release|Win32.Build.0 = Release|Win32
+ {8DB197B1-20B2-485D-B89E-D9A7674193BD}.Release|x64.ActiveCfg = Release|x64
+ {8DB197B1-20B2-485D-B89E-D9A7674193BD}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/3rdparty/adaptagrams/libavoid/libavoid.vcxproj b/src/3rdparty/adaptagrams/libavoid/libavoid.vcxproj
new file mode 100755
index 0000000..e563b75
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/libavoid.vcxproj
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{798C3D94-BF71-4C72-A29D-0E74C2EB296A}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>libavoid</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBAVOID_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBAVOID_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBAVOID_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBAVOID_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="actioninfo.cpp" />
+ <ClCompile Include="connectionpin.cpp" />
+ <ClCompile Include="connector.cpp" />
+ <ClCompile Include="connend.cpp" />
+ <ClCompile Include="geometry.cpp" />
+ <ClCompile Include="geomtypes.cpp" />
+ <ClCompile Include="graph.cpp" />
+ <ClCompile Include="hyperedge.cpp" />
+ <ClCompile Include="hyperedgeimprover.cpp" />
+ <ClCompile Include="hyperedgetree.cpp" />
+ <ClCompile Include="junction.cpp" />
+ <ClCompile Include="makepath.cpp" />
+ <ClCompile Include="mtst.cpp" />
+ <ClCompile Include="obstacle.cpp" />
+ <ClCompile Include="orthogonal.cpp" />
+ <ClCompile Include="router.cpp" />
+ <ClCompile Include="scanline.cpp" />
+ <ClCompile Include="shape.cpp" />
+ <ClCompile Include="timer.cpp" />
+ <ClCompile Include="vertices.cpp" />
+ <ClCompile Include="viscluster.cpp" />
+ <ClCompile Include="visibility.cpp" />
+ <ClCompile Include="vpsc.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="actioninfo.h" />
+ <ClInclude Include="assertions.h" />
+ <ClInclude Include="connectionpin.h" />
+ <ClInclude Include="connector.h" />
+ <ClInclude Include="connend.h" />
+ <ClInclude Include="debug.h" />
+ <ClInclude Include="dllexport.h" />
+ <ClInclude Include="geometry.h" />
+ <ClInclude Include="geomtypes.h" />
+ <ClInclude Include="graph.h" />
+ <ClInclude Include="hyperedge.h" />
+ <ClInclude Include="hyperedgeimprover.h" />
+ <ClInclude Include="hyperedgetree.h" />
+ <ClInclude Include="junction.h" />
+ <ClInclude Include="libavoid.h" />
+ <ClInclude Include="makepath.h" />
+ <ClInclude Include="mtst.h" />
+ <ClInclude Include="obstacle.h" />
+ <ClInclude Include="orthogonal.h" />
+ <ClInclude Include="router.h" />
+ <ClInclude Include="scanline.h" />
+ <ClInclude Include="shape.h" />
+ <ClInclude Include="timer.h" />
+ <ClInclude Include="vertices.h" />
+ <ClInclude Include="viscluster.h" />
+ <ClInclude Include="visibility.h" />
+ <ClInclude Include="vpsc.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/src/3rdparty/adaptagrams/libavoid/makepath.cpp b/src/3rdparty/adaptagrams/libavoid/makepath.cpp
new file mode 100644
index 0000000..8e8f4f0
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/makepath.cpp
@@ -0,0 +1,1554 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+// For M_PI.
+// This should be first include for MSVC.
+#define _USE_MATH_DEFINES
+#include <cmath>
+
+#include <algorithm>
+#include <vector>
+#include <climits>
+#include <cfloat>
+
+#include "libavoid/makepath.h"
+#include "libavoid/vertices.h"
+#include "libavoid/geometry.h"
+#include "libavoid/connector.h"
+#include "libavoid/viscluster.h"
+#include "libavoid/graph.h"
+#include "libavoid/router.h"
+#include "libavoid/debug.h"
+#include "libavoid/assertions.h"
+#include "libavoid/debughandler.h"
+
+//#define ESTIMATED_COST_DEBUG
+
+namespace Avoid {
+
+class ANode
+{
+ public:
+ VertInf* inf;
+ double g; // Gone
+ double h; // Heuristic
+ double f; // Formula f = g + h
+
+ ANode *prevNode; // VertInf for the previous ANode.
+ int timeStamp; // Time-stamp used to determine exploration order of
+ // seemingly equal paths during orthogonal routing.
+
+ ANode(VertInf *vinf, int time)
+ : inf(vinf),
+ g(0),
+ h(0),
+ f(0),
+ prevNode(nullptr),
+ timeStamp(time)
+ {
+ }
+ ANode()
+ : inf(nullptr),
+ g(0),
+ h(0),
+ f(0),
+ prevNode(nullptr),
+ timeStamp(-1)
+ {
+ }
+};
+
+class AStarPathPrivate
+{
+ public:
+ AStarPathPrivate()
+ : m_available_nodes(),
+ m_available_array_size(0),
+ m_available_array_index(0),
+ m_available_node_index(0)
+ {
+ }
+ ~AStarPathPrivate()
+ {
+ // Free memory
+ for (size_t i = 0; i < m_available_nodes.size(); ++i)
+ {
+ delete[] m_available_nodes[i];
+ }
+ }
+ // Returns a pointer to an ANode for aStar search, but allocates
+ // these in blocks
+ ANode *newANode(const ANode& node, const bool addToPending = true)
+ {
+ const size_t blockSize = 5000;
+ if ((m_available_array_index + 1 > m_available_array_size) ||
+ (m_available_node_index >= blockSize))
+ {
+ m_available_nodes.push_back(new ANode[blockSize]);
+ ++m_available_array_size;
+ m_available_node_index = 0;
+ m_available_array_index = m_available_array_size - 1;
+ }
+
+ ANode *nodes = m_available_nodes[m_available_array_index];
+ ANode *newNode = &(nodes[m_available_node_index++]);
+ *newNode = node;
+ if (addToPending)
+ {
+ node.inf->aStarPendingNodes.push_back(newNode);
+ }
+ return newNode;
+ }
+ void search(ConnRef *lineRef, VertInf *src, VertInf *tar,
+ VertInf *start);
+
+ private:
+ void determineEndPointLocation(double dist, VertInf *start,
+ VertInf *target, VertInf *other, int level);
+ double estimatedCost(ConnRef *lineRef, const Point *last,
+ const Point& curr) const;
+
+ std::vector<ANode *> m_available_nodes;
+ size_t m_available_array_size;
+ size_t m_available_array_index;
+ size_t m_available_node_index;
+
+ // For determining estimated cost target.
+ std::vector<VertInf *> m_cost_targets;
+ std::vector<unsigned int> m_cost_targets_directions;
+ std::vector<double> m_cost_targets_displacements;
+};
+
+
+
+// This returns the opposite result (>) so that when used with stl::make_heap,
+// the head node of the heap will be the smallest value, rather than the
+// largest. This saves us from having to sort the heap (and then reorder
+// it back into a heap) when getting the next node to examine. This way we
+// get better complexity -- logarithmic pushes and pops to the heap.
+//
+class ANodeCmp
+{
+ public:
+ ANodeCmp()
+ {
+ }
+bool operator()(const ANode *a, const ANode *b)
+{
+ // We need to use an epsilon here since otherwise the multiple addition
+ // of floating point numbers that makes up the 'f' values cause a problem
+ // with routings occasionally being non-deterministic.
+ if (fabs(a->f - b->f) > 0.0000001)
+ {
+ return a->f > b->f;
+ }
+ if (a->timeStamp != b->timeStamp)
+ {
+ // Tiebreaker, if two paths have equal cost, then choose the one with
+ // the highest timeStamp. This corresponds to the furthest point
+ // explored along the straight-line path. When exploring we give the
+ // directions the following timeStamps; left:1, right:2 and forward:3,
+ // then we always try to explore forward first.
+ return a->timeStamp < b->timeStamp;
+ }
+ return false;
+}
+};
+
+
+static double Dot(const Point& l, const Point& r)
+{
+ return (l.x * r.x) + (l.y * r.y);
+}
+
+static double CrossLength(const Point& l, const Point& r)
+{
+ return (l.x * r.y) - (l.y * r.x);
+}
+
+
+// Return the angle between the two line segments made by the
+// points p1--p2 and p2--p3. Return value is in radians.
+//
+static double angleBetween(const Point& p1, const Point& p2, const Point& p3)
+{
+ if ((p1.x == p2.x && p1.y == p2.y) || (p2.x == p3.x && p2.y == p3.y))
+ {
+ // If two of the points are the same, then we can't say anything
+ // about the angle between. Treat them as being collinear.
+ return M_PI;
+ }
+
+ Point v1(p1.x - p2.x, p1.y - p2.y);
+ Point v2(p3.x - p2.x, p3.y - p2.y);
+
+ return fabs(atan2(CrossLength(v1, v2), Dot(v1, v2)));
+}
+
+
+// Construct a temporary Polygon path given several VertInf's for a connector.
+//
+static void constructPolygonPath(Polygon& connRoute, VertInf *inf2,
+ VertInf *inf3, ANode *inf1Node)
+{
+ // Don't include colinear points.
+ bool simplified = true;
+
+ int routeSize = 2;
+ for (ANode *curr = inf1Node; curr != nullptr; curr = curr->prevNode)
+ {
+ routeSize += 1;
+ }
+ connRoute.ps.resize(routeSize);
+ int arraySize = routeSize;
+ connRoute.ps[routeSize - 1] = inf3->point;
+ connRoute.ps[routeSize - 2] = inf2->point;
+ routeSize -= 3;
+ for (ANode *curr = inf1Node; curr != nullptr; curr = curr->prevNode)
+ {
+ // For connection pins, we stop and don't include the fake shape
+ // center as part of this path.
+ bool isConnectionPin = curr->inf->id.isConnectionPin();
+
+ if (!simplified)
+ {
+ // If this is non-simplified, we don't need to do anything
+ // clever and can simply add the new point.
+ connRoute.ps[routeSize] = curr->inf->point;
+ routeSize -= 1;
+
+ if (isConnectionPin)
+ {
+ // Stop at the connection pin.
+ break;
+ }
+ continue;
+ }
+
+ if ((curr == inf1Node) ||
+ vecDir(curr->inf->point, connRoute.ps[routeSize + 1],
+ connRoute.ps[routeSize + 2]) != 0)
+ {
+ // Add new point if this is the earlier than the last segment
+ // and it is not colinear with the other points.
+ // Note, you can't collapse the 'last' segment with previous
+ // segments, or if this just intersects another line you risk
+ // penalising it once for each collapsed line segment.
+ connRoute.ps[routeSize] = curr->inf->point;
+ routeSize -= 1;
+ }
+ else
+ {
+ // The last point is inline with this one, so update it.
+ connRoute.ps[routeSize + 1] = curr->inf->point;
+ }
+
+ if (isConnectionPin)
+ {
+ // Stop at the connection pin.
+ break;
+ }
+ }
+
+ // If the vector is not filled, move entries to the beginning and
+ // remove the unused end of the vector.
+ int diff = routeSize + 1;
+ COLA_ASSERT(simplified || (diff == 0));
+ if (diff > 0)
+ {
+ for (int i = diff; i < arraySize; ++i)
+ {
+ connRoute.ps[i - diff] = connRoute.ps[i];
+ }
+ connRoute.ps.resize(connRoute.size() - diff);
+ }
+}
+
+// Used to get an indication of if a diffence is positive (1),
+// negative (-1) or no different (0).
+static inline int dimDirection(double difference)
+{
+ if (difference > 0)
+ {
+ return 1;
+ }
+ else if (difference < 0)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+// Given the two points for a new segment of a path (inf2 & inf3)
+// as well as the distance between these points (dist), as well as
+// possibly the previous point (inf1) [from inf1--inf2], return a
+// cost associated with this route.
+//
+static double cost(ConnRef *lineRef, const double dist, VertInf *inf2,
+ VertInf *inf3, ANode *inf1Node)
+{
+ bool isOrthogonal = (lineRef->routingType() == ConnType_Orthogonal);
+ VertInf *inf1 = (inf1Node) ? inf1Node->inf : nullptr;
+ double result = dist;
+ Polygon connRoute;
+
+ Router *router = inf2->_router;
+ if (inf1 != nullptr)
+ {
+ const double angle_penalty = router->routingParameter(anglePenalty);
+ const double segmt_penalty = router->routingParameter(segmentPenalty);
+
+ // This is not the first segment, so there is a bend
+ // between it and the last one in the existing path.
+ if ((angle_penalty > 0) || (segmt_penalty > 0))
+ {
+ Point p1 = inf1->point;
+ Point p2 = inf2->point;
+ Point p3 = inf3->point;
+
+ double rad = M_PI - angleBetween(p1, p2, p3);
+
+ if ((rad > 0) && !isOrthogonal)
+ {
+ // Make `xval' between 0--10 then take its log so small
+ // angles are not penalised as much as large ones.
+ //
+ double xval = rad * 10 / M_PI;
+ double yval = xval * log10(xval + 1) / 10.5;
+ result += (angle_penalty * yval);
+ //db_printf("deg from straight: %g\tpenalty: %g\n",
+ // rad * 180 / M_PI, (angle_penalty * yval));
+ }
+
+ if (rad == M_PI)
+ {
+ // Needs to double back
+ result += (2 * segmt_penalty);
+ }
+ else if (rad > 0)
+ {
+ // Only penalise as an extra segment if the two
+ // segments are not collinear.
+ result += segmt_penalty;
+ }
+ }
+ }
+
+ const double cluster_crossing_penalty =
+ router->routingParameter(clusterCrossingPenalty);
+ // XXX: Clustered routing doesn't yet work with orthogonal connectors.
+ if (router->ClusteredRouting && !router->clusterRefs.empty() &&
+ (cluster_crossing_penalty > 0))
+ {
+ if (connRoute.empty())
+ {
+ constructPolygonPath(connRoute, inf2, inf3, inf1Node);
+ }
+ // There are clusters so do cluster routing.
+ for (ClusterRefList::const_iterator cl = router->clusterRefs.begin();
+ cl != router->clusterRefs.end(); ++cl)
+ {
+ Polygon cBoundary = (isOrthogonal) ?
+ (*cl)->rectangularPolygon() : (*cl)->polygon();
+ if (cBoundary.size() <= 2)
+ {
+ continue;
+ }
+ COLA_ASSERT(cBoundary.ps[0] != cBoundary.ps[cBoundary.size() - 1]);
+ for (size_t j = 0; j < cBoundary.size(); ++j)
+ {
+ // Non-orthogonal cluster boundary points should correspond to
+ // shape vertices and hence already be in the list of vertices.
+ COLA_ASSERT(isOrthogonal ||
+ router->vertices.getVertexByPos(cBoundary.at(j)));
+ }
+
+ bool isConn = false;
+ Polygon dynamic_conn_route(connRoute);
+ const bool finalSegment = (inf3 == lineRef->dst());
+ ConnectorCrossings cross(cBoundary, isConn, dynamic_conn_route);
+ cross.checkForBranchingSegments = true;
+ cross.countForSegment(connRoute.size() - 1, finalSegment);
+
+ result += (cross.crossingCount * cluster_crossing_penalty);
+ }
+ }
+
+ // This penalty penalises route segments that head in a direction opposite
+ // of the direction(s) toward the target point.
+ const double reversePenalty = router->routingParameter(
+ reverseDirectionPenalty);
+ if (reversePenalty)
+ {
+ // X and Y direction of destination from source point.
+ const Point& srcPoint = lineRef->src()->point;
+ const Point& dstPoint = lineRef->dst()->point;
+ int xDir = dimDirection(dstPoint.x - srcPoint.x);
+ int yDir = dimDirection(dstPoint.y - srcPoint.y);
+
+ bool doesReverse = false;
+
+ if ((xDir != 0) &&
+ (-xDir == dimDirection(inf3->point.x - inf2->point.x)))
+ {
+ // Connector has an X component and the segment heads in the
+ // opposite direction.
+ doesReverse |= true;
+ }
+
+ if ((yDir != 0) &&
+ (-yDir == dimDirection(inf3->point.y - inf2->point.y)))
+ {
+ // Connector has an Y component and the segment heads in the
+ // opposite direction.
+ doesReverse |= true;
+ }
+
+ if (doesReverse)
+ {
+ result += reversePenalty;
+ }
+ }
+
+ if (!router->isInCrossingPenaltyReroutingStage())
+ {
+ // Return here if we are not in the post-processing stage
+ return result;
+ }
+
+ const double crossing_penalty = router->routingParameter(crossingPenalty);
+ const double shared_path_penalty =
+ router->routingParameter(fixedSharedPathPenalty);
+ if ((shared_path_penalty > 0) || (crossing_penalty > 0))
+ {
+ if (connRoute.empty())
+ {
+ constructPolygonPath(connRoute, inf2, inf3, inf1Node);
+ }
+ ConnRefList::const_iterator curr, finish = router->connRefs.end();
+ for (curr = router->connRefs.begin(); curr != finish; ++curr)
+ {
+ ConnRef *connRef = *curr;
+
+ if (connRef->id() == lineRef->id())
+ {
+ continue;
+ }
+ const Avoid::PolyLine& route2 = connRef->displayRoute();
+
+ bool isConn = true;
+ Polygon dynamic_route2(route2);
+ Polygon dynamic_conn_route(connRoute);
+ const bool finalSegment = (inf3->point == lineRef->dst()->point);
+ ConnectorCrossings cross(dynamic_route2, isConn,
+ dynamic_conn_route, connRef, lineRef);
+ cross.checkForBranchingSegments = true;
+ cross.countForSegment(connRoute.size() - 1, finalSegment);
+
+ if ((cross.crossingFlags & CROSSING_SHARES_PATH) &&
+ (cross.crossingFlags & CROSSING_SHARES_FIXED_SEGMENT) &&
+ (router->routingOption(
+ penaliseOrthogonalSharedPathsAtConnEnds) ||
+ !(cross.crossingFlags & CROSSING_SHARES_PATH_AT_END)))
+ {
+ // Penalise unnecessary shared paths in the middle of
+ // connectors.
+ result += shared_path_penalty;
+ }
+ result += (cross.crossingCount * crossing_penalty);
+ }
+ }
+
+ return result;
+}
+
+// Directions for estimated orthgonal cost, as bitflags.
+static const unsigned int CostDirectionN = 1;
+static const unsigned int CostDirectionE = 2;
+static const unsigned int CostDirectionS = 4;
+static const unsigned int CostDirectionW = 8;
+
+#ifdef ESTIMATED_COST_DEBUG
+static void printDirections(FILE *fp, unsigned int directions)
+{
+ if (directions & CostDirectionN)
+ {
+ fprintf(fp, "N ");
+ }
+ if (directions & CostDirectionE)
+ {
+ fprintf(fp, "E ");
+ }
+ if (directions & CostDirectionS)
+ {
+ fprintf(fp, "S ");
+ }
+ if (directions & CostDirectionW)
+ {
+ fprintf(fp, "W ");
+ }
+}
+#endif
+
+// Returns the number of directions for the argument.
+static unsigned int orthogonalDirectionsCount(const unsigned int directions)
+{
+ unsigned int count = 0;
+ if (directions & CostDirectionN)
+ {
+ ++count;
+ }
+ if (directions & CostDirectionE)
+ {
+ ++count;
+ }
+ if (directions & CostDirectionS)
+ {
+ ++count;
+ }
+ if (directions & CostDirectionW)
+ {
+ ++count;
+ }
+ return count;
+}
+
+// Returns the directions of point b from point a.
+static unsigned int orthogonalDirection(const Point &a, const Point &b)
+{
+ unsigned int result = 0;
+
+ if (b.y > a.y)
+ {
+ result |= CostDirectionS;
+ }
+ else if (b.y < a.y)
+ {
+ result |= CostDirectionN;
+ }
+
+ if (b.x > a.x)
+ {
+ result |= CostDirectionE;
+ }
+ else if (b.x < a.x)
+ {
+ result |= CostDirectionW;
+ }
+
+ return result;
+}
+
+// Returns the direction to the right of the given direction.
+static unsigned int dirRight(unsigned int direction)
+{
+ if (direction == CostDirectionN)
+ {
+ return CostDirectionE;
+ }
+ else if (direction == CostDirectionE)
+ {
+ return CostDirectionS;
+ }
+ else if (direction == CostDirectionS)
+ {
+ return CostDirectionW;
+ }
+ else if (direction == CostDirectionW)
+ {
+ return CostDirectionN;
+ }
+
+ // Should not be possible to reach here.
+ COLA_ASSERT(false);
+ return direction;
+}
+
+// Returns the direction to the left of the given direction.
+static unsigned int dirLeft(unsigned int direction)
+{
+ if (direction == CostDirectionN)
+ {
+ return CostDirectionW;
+ }
+ else if (direction == CostDirectionE)
+ {
+ return CostDirectionN;
+ }
+ else if (direction == CostDirectionS)
+ {
+ return CostDirectionE;
+ }
+ else if (direction == CostDirectionW)
+ {
+ return CostDirectionS;
+ }
+
+ // Should not be possible to reach here.
+ COLA_ASSERT(false);
+ return direction;
+}
+
+// Returns the reverse direction to the given direction.
+static unsigned int dirReverse(unsigned int direction)
+{
+ if (direction == CostDirectionN)
+ {
+ return CostDirectionS;
+ }
+ else if (direction == CostDirectionE)
+ {
+ return CostDirectionW;
+ }
+ else if (direction == CostDirectionS)
+ {
+ return CostDirectionN;
+ }
+ else if (direction == CostDirectionW)
+ {
+ return CostDirectionE;
+ }
+
+ // Should not be possible to reach here.
+ COLA_ASSERT(false);
+ return direction;
+}
+
+// Given Point curr with a direction of currDir, returns the nimimum number
+// of bends to reach Point dest with the entry direction of destDir
+//
+// This is used for estimating the bend penalty cost to the target point
+// from the current point of the search. The geometry was described in the
+// "Orthogonal Connector Routing" paper, although the version described
+// there is incorrect.
+//
+int bends(const Point& curr, unsigned int currDir, const Point& dest,
+ unsigned int destDir)
+{
+ // Bend counts from 'o' to 'D' should be:
+ //
+ // 1 1 3
+ // v v v
+ // 2 > o < 2 2 > o < 2 4 > o < 2
+ // ^ ^ ^
+ // 3 3 3
+ //
+ // 0 > o < 4 D--> 4 > o < 4
+ // ^ ^
+ // 1 3
+ //
+ COLA_ASSERT(currDir != 0);
+ unsigned int currToDestDir = orthogonalDirection(curr, dest);
+ unsigned int reverseDestDir = dirReverse(destDir);
+ bool currDirPerpendicularToDestDir =
+ (currDir == dirLeft(destDir)) || (currDir == dirRight(destDir));
+
+ if ((currDir == destDir) &&
+ (currToDestDir == currDir))
+ {
+ //
+ // 0 > o D-->
+ //
+ return 0;
+ }
+ else if (currDirPerpendicularToDestDir &&
+ (currToDestDir == (destDir | currDir)))
+ {
+ //
+ // 1
+ // v
+ // o
+ //
+ //
+ // D-->
+ //
+ return 1;
+ }
+ else if (currDirPerpendicularToDestDir &&
+ (currToDestDir == currDir))
+ {
+ //
+ // 1
+ // v
+ // o
+ //
+ //
+ // D-->
+ //
+ return 1;
+ }
+ else if (currDirPerpendicularToDestDir &&
+ (currToDestDir == destDir))
+ {
+ //
+ // o D-->
+ // ^
+ // 1
+ //
+ return 1;
+ }
+ else if ((currDir == destDir) &&
+ (currToDestDir != currDir) &&
+ !(currToDestDir & reverseDestDir))
+ {
+ //
+ // 2 > o 2 > o
+ //
+ //
+ // D-->
+ //
+ return 2;
+ }
+ else if (currDir == reverseDestDir &&
+ (currToDestDir != destDir) &&
+ (currToDestDir != currDir))
+ {
+ //
+ // o < 2 o < 2 o < 2
+ //
+ //
+ // D-->
+ //
+ return 2;
+ }
+ else if (currDirPerpendicularToDestDir &&
+ (currToDestDir != (destDir | currDir)) &&
+ (currToDestDir != currDir))
+ {
+ //
+ // 3
+ // v
+ // o o o
+ // ^ ^ ^
+ // 3 3 3
+ //
+ // D--> o
+ // ^
+ // 3
+ //
+ return 3;
+ }
+ else if ((currDir == reverseDestDir) &&
+ ((currToDestDir == destDir) || (currToDestDir == currDir)))
+ {
+ //
+ //
+ //
+ // o < 4 D--> o < 4
+ //
+ return 4;
+ }
+ else if ((currDir == destDir) &&
+ (currToDestDir & reverseDestDir))
+ {
+ //
+ // 4 > o
+ //
+ //
+ // D--> 4 > o
+ //
+ return 4;
+ }
+
+ // Should not be possible to reach here.
+ COLA_ASSERT(false);
+ return 0;
+}
+
+
+static double estimatedCostSpecific(ConnRef *lineRef, const Point *last,
+ const Point& curr, const VertInf *costTar,
+ const unsigned int costTarDirs)
+{
+ Point costTarPoint = costTar->point;
+
+ if (lineRef->routingType() == ConnType_PolyLine)
+ {
+ return euclideanDist(curr, costTarPoint);
+ }
+ else // Orthogonal
+ {
+ // Really doesn't make sense to route orthogonal paths without
+ // a segment penalty.
+ COLA_ASSERT(lineRef->router()->routingParameter(segmentPenalty) > 0);
+
+ double dist = manhattanDist(curr, costTarPoint);
+
+ int bendCount = 0;
+ double xmove = costTarPoint.x - curr.x;
+ double ymove = costTarPoint.y - curr.y;
+ if (last == nullptr)
+ {
+ // This is just the initial point. Penalise it simply if it is
+ // not inline with the target in either the x- or y-dimension.
+ if ((xmove != 0) && (ymove != 0))
+ {
+ bendCount += 1;
+ }
+ }
+ else if (dist > 0)
+ {
+ // We have two points and a non-zero distance, so we know
+ // the segment direction.
+
+ unsigned int currDir = orthogonalDirection(*last, curr);
+ if ((currDir > 0) && (orthogonalDirectionsCount(currDir) == 1))
+ {
+ // Suitably high value, then we find the minimum.
+ bendCount = 10;
+
+ // Find the minimum bent penalty given all the possible
+ // directions at the target point.
+ if (costTarDirs & CostDirectionN)
+ {
+ bendCount = std::min(bendCount,
+ bends(curr, currDir, costTarPoint, CostDirectionN));
+ }
+ if (costTarDirs & CostDirectionE)
+ {
+ bendCount = std::min(bendCount,
+ bends(curr, currDir, costTarPoint, CostDirectionE));
+ }
+ if (costTarDirs & CostDirectionS)
+ {
+ bendCount = std::min(bendCount,
+ bends(curr, currDir, costTarPoint, CostDirectionS));
+ }
+ if (costTarDirs & CostDirectionW)
+ {
+ bendCount = std::min(bendCount,
+ bends(curr, currDir, costTarPoint, CostDirectionW));
+ }
+ }
+ }
+ double penalty = bendCount *
+ lineRef->router()->routingParameter(segmentPenalty);
+
+ return dist + penalty;
+ }
+}
+
+
+
+double AStarPathPrivate::estimatedCost(ConnRef *lineRef, const Point *last,
+ const Point& curr) const
+{
+ double estimate = DBL_MAX;
+ COLA_ASSERT(m_cost_targets.size() > 0);
+
+ // Find the minimum cost from the estimates to each of the possible
+ // target points from this current point.
+ for (size_t i = 0; i < m_cost_targets.size(); ++i)
+ {
+ double iEstimate = estimatedCostSpecific(lineRef, last,
+ curr, m_cost_targets[i], m_cost_targets_directions[i]);
+
+ // Add on the distance to the real target, otherwise this difference
+ // might may make the comparisons unfair if they vary between targets.
+ iEstimate += m_cost_targets_displacements[i];
+
+ estimate = std::min(estimate, iEstimate);
+ }
+ return estimate;
+}
+
+
+class CmpVisEdgeRotation
+{
+ public:
+ CmpVisEdgeRotation(const VertInf* lastPt)
+ : _lastPt(lastPt)
+ {
+ }
+ bool operator() (const EdgeInf* u, const EdgeInf* v) const
+ {
+ // Dummy ShapeConnectionPin edges are not orthogonal and
+ // therefore can't be compared in the same way.
+ if (u->isOrthogonal() && v->isOrthogonal())
+ {
+ return u->rotationLessThan(_lastPt, v);
+ }
+ return u < v;
+ }
+ private:
+ const VertInf *_lastPt;
+};
+
+
+static inline bool pointAlignedWithOneOf(const Point& point,
+ const std::vector<Point>& points, const size_t dim)
+{
+ for (size_t i = 0; i < points.size(); ++i)
+ {
+ if (point[dim] == points[i][dim])
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+AStarPath::AStarPath(void)
+ : m_private(new AStarPathPrivate())
+{
+}
+
+AStarPath::~AStarPath(void)
+{
+ delete m_private;
+}
+
+void AStarPath::search(ConnRef *lineRef, VertInf *src, VertInf *tar, VertInf *start)
+{
+ m_private->search(lineRef, src, tar, start);
+}
+
+void AStarPathPrivate::determineEndPointLocation(double dist, VertInf *start,
+ VertInf *target, VertInf *other, int level)
+{
+ COLA_UNUSED(dist);
+ COLA_UNUSED(start);
+ COLA_UNUSED(level);
+
+ Point otherPoint = other->point;
+ unsigned int thisDirs = orthogonalDirection(otherPoint, target->point);
+ COLA_ASSERT(orthogonalDirectionsCount(thisDirs) > 0);
+ double displacement = manhattanDist(otherPoint, target->point);
+
+ m_cost_targets.push_back(other);
+ m_cost_targets_directions.push_back(thisDirs);
+ m_cost_targets_displacements.push_back(displacement);
+
+#ifdef ESTIMATED_COST_DEBUG
+ fprintf(stderr," - %g %g ", otherPoint.x, otherPoint.y);
+ if (manhattanDist(start->point, otherPoint) > dist)
+ {
+ fprintf(stderr,"far ");
+ }
+ fprintf(stderr, "%s", (level == 1) ? "--" : "- ");
+ printDirections(stderr, thisDirs);
+ fprintf(stderr,"\n");
+#endif
+}
+
+// Returns the best path from src to tar using the cost function.
+//
+// The path is worked out using the aStar algorithm, and is encoded via
+// prevNode values for each ANode which point back to the previous ANode.
+// At completion, this order is written into the pathNext links in each
+// of the VerInfs along the path.
+//
+// The aStar STL code is originally based on public domain code available
+// on the internet.
+//
+void AStarPathPrivate::search(ConnRef *lineRef, VertInf *src, VertInf *tar, VertInf *start)
+{
+ ANodeCmp pendingCmp;
+
+ bool isOrthogonal = (lineRef->routingType() == ConnType_Orthogonal);
+
+ if (start == nullptr)
+ {
+ start = src;
+ }
+
+#ifdef DEBUGHANDLER
+ if (lineRef->router()->debugHandler())
+ {
+ lineRef->router()->debugHandler()->beginningSearchWithEndpoints(start, tar);
+ }
+#endif
+
+ // Find a target point to use for cost estimate for orthogonal routing.
+ //
+ // If the connectivity is only on the far side we need to estimate to the
+ // point on the far side. Otherwise for orthogonal routing we can explore
+ // all the space in between before we pay the extra cost to explore this
+ // area. This is especially true given many orthogonal routes have
+ // equivalent costs.
+#ifdef ESTIMATED_COST_DEBUG
+ fprintf(stderr,"== aStar %g %g ==\n", tar->point.x, tar->point.y);
+#endif
+ if (isOrthogonal && tar->id.isConnPt() && !tar->id.isConnCheckpoint())
+ {
+ // The target is a connector endpoint and the connector is orthogonal.
+ double dist = manhattanDist(start->point, tar->point);
+ for (EdgeInfList::const_iterator it = tar->orthogVisList.begin();
+ it != tar->orthogVisList.end(); ++it)
+ {
+ // For each edge from the target endpoint, find the other vertex.
+ EdgeInf *edge = *it;
+ VertInf *other = edge->otherVert(tar);
+ if (other->id.isConnectionPin())
+ {
+ // If this is a connection pin we need to do this process
+ // another time since the current edge will be a dummy
+ // zero-length edge.
+ VertInf *replacementTar = other;
+ for (EdgeInfList::const_iterator it =
+ replacementTar->orthogVisList.begin();
+ it != replacementTar->orthogVisList.end(); ++it)
+ {
+ EdgeInf *edge = *it;
+ VertInf *other = edge->otherVert(replacementTar);
+ if ((other == tar) ||
+ (other->point == tar->point))
+ {
+ // Ignore edge we came from, or zero-length edges.
+ continue;
+ }
+
+ // Determine possible target endpoint directions and
+ // position.
+ determineEndPointLocation(dist, start, replacementTar,
+ other, 2);
+ }
+ continue;
+ }
+
+ // Determine possible target endpoint directions and position.
+ determineEndPointLocation(dist, start, tar, other, 1);
+ }
+ }
+
+
+ if (m_cost_targets.empty())
+ {
+ m_cost_targets.push_back(tar);
+ // For polyline routing, assume target has visibility is all
+ // directions for the purpose of cost estimations.
+ m_cost_targets_directions.push_back(CostDirectionN |
+ CostDirectionE | CostDirectionS | CostDirectionW);
+ m_cost_targets_displacements.push_back(0.0);
+ }
+
+#ifdef ESTIMATED_COST_DEBUG
+ fprintf(stderr, "------------\n");
+ for (size_t i = 0; i < m_cost_targets.size(); ++i)
+ {
+ fprintf(stderr,"== %g %g - ", m_cost_targets[i]->point.x,
+ m_cost_targets[i]->point.y);
+ printDirections(stderr, m_cost_targets_directions[i]);
+ fprintf(stderr,"\n");
+ }
+#endif
+
+
+ double (*dist)(const Point& a, const Point& b) =
+ (isOrthogonal) ? manhattanDist : euclideanDist;
+
+ // We need to know the possible endpoints for doing an orthogonal
+ // routing optimisation where we only turn when we are heading beside
+ // a shape or are in line with a possible endpoint.
+ std::vector<Point> endPoints;
+ if (isOrthogonal)
+ {
+ endPoints = lineRef->possibleDstPinPoints();
+ }
+ endPoints.push_back(tar->point);
+
+ // Heap of PENDING nodes.
+ std::vector<ANode *> PENDING;
+ PENDING.reserve(1000);
+
+ size_t exploredCount = 0;
+ ANode node, ati;
+ ANode *bestNode = nullptr; // Temporary bestNode
+ bool bNodeFound = false; // Flag if node is found in container
+ int timestamp = 1;
+
+ Router *router = lineRef->router();
+ if (router->RubberBandRouting && (start != src))
+ {
+ COLA_ASSERT(router->IgnoreRegions == true);
+
+ const PolyLine& currRoute = lineRef->route();
+ VertInf *last = nullptr;
+ int rIndx = 0;
+ while (last != start)
+ {
+ const Point& pnt = currRoute.at(rIndx);
+ VertIDProps props = (rIndx > 0) ? 0 : VertID::PROP_ConnPoint;
+ VertID vID(pnt.id, pnt.vn, props);
+
+#ifdef PATHDEBUG
+ db_printf("/// %d %d\n", pnt.id, pnt.vn);
+#endif
+ VertInf *curr = router->vertices.getVertexByID(vID);
+ COLA_ASSERT(curr != nullptr);
+
+ node = ANode(curr, timestamp++);
+ if (!last)
+ {
+ node.inf = src;
+ node.g = 0;
+ node.h = estimatedCost(lineRef, nullptr, node.inf->point);
+
+ node.f = node.g + node.h;
+ }
+ else
+ {
+ double edgeDist = dist(bestNode->inf->point, curr->point);
+
+ node.g = bestNode->g + cost(lineRef, edgeDist, bestNode->inf,
+ node.inf, bestNode->prevNode);
+
+ // Calculate the Heuristic.
+ node.h = estimatedCost(lineRef, &(bestNode->inf->point),
+ node.inf->point);
+
+ // The A* formula
+ node.f = node.g + node.h;
+
+ // Point parent to last bestNode
+ node.prevNode = bestNode;
+ }
+
+ if (curr != start)
+ {
+ bool addToPending = false;
+ bestNode = newANode(node, addToPending);
+ bestNode->inf->aStarDoneNodes.push_back(bestNode);
+ ++exploredCount;
+ }
+ else
+ {
+ ANode * newNode = newANode(node);
+ PENDING.push_back(newNode);
+ }
+
+ rIndx++;
+ last = curr;
+ }
+ }
+ else
+ {
+ if (start->pathNext)
+ {
+ // If we are doing checkpoint routing and have already done one
+ // path, then we have an existing segment to consider for the
+ // cost of the choice from the start node, so we add a dummy
+ // nodes as if they were already in the Done set. This causes
+ // us to first search in a collinear direction from the previous
+ // segment.
+ bool addToPending = false;
+ bestNode = newANode(ANode(start->pathNext, timestamp++),
+ addToPending);
+ bestNode->inf->aStarDoneNodes.push_back(bestNode);
+ ++exploredCount;
+ }
+
+ // Create the start node
+ node = ANode(src, timestamp++);
+ node.g = 0;
+ node.h = estimatedCost(lineRef, nullptr, node.inf->point);
+ node.f = node.g + node.h;
+ // Set a nullptr parent, so cost function knows this is the first segment.
+ node.prevNode = bestNode;
+
+ // Populate the PENDING container with the first location
+ ANode *newNode = newANode(node);
+ PENDING.push_back(newNode);
+ }
+
+ tar->pathNext = nullptr;
+
+ // Create a heap from PENDING for sorting
+ using std::make_heap; using std::push_heap; using std::pop_heap;
+ make_heap( PENDING.begin(), PENDING.end(), pendingCmp);
+
+ // Continue until the queue is empty.
+ while (!PENDING.empty())
+ {
+ TIMER_VAR_ADD(router, 0, 1);
+ // Set the Node with lowest f value to BESTNODE.
+ // Since the ANode operator< is reversed, the head of the
+ // heap is the node with the lowest f value.
+ bestNode = PENDING.front();
+ VertInf *bestNodeInf = bestNode->inf;
+
+#ifdef DEBUGHANDLER
+ if (router->debugHandler())
+ {
+ PolyLine currentSearchPath;
+
+ ANode *curr = bestNode;
+ while (curr)
+ {
+ currentSearchPath.ps.push_back(curr->inf->point);
+ curr = curr->prevNode;
+ }
+ router->debugHandler()->updateCurrentSearchPath(currentSearchPath);
+ }
+#endif
+
+ // Remove this node from the aStarPendingList
+ std::list<ANode *>::iterator finishIt =
+ bestNodeInf->aStarPendingNodes.end();
+ for (std::list<ANode *>::iterator currInd =
+ bestNodeInf->aStarPendingNodes.begin(); currInd != finishIt;
+ ++currInd)
+ {
+ if (*currInd == bestNode)
+ {
+ bestNodeInf->aStarPendingNodes.erase(currInd);
+ break;
+ }
+ }
+
+ // Pop off the heap. Actually this moves the
+ // far left value to the far right. The node
+ // is not actually removed since the pop is to
+ // the heap and not the container.
+ pop_heap(PENDING.begin(), PENDING.end(), pendingCmp);
+ // Remove node from right (the value we pop_heap'd)
+ PENDING.pop_back();
+
+ // Add the bestNode into the Done set.
+ bestNodeInf->aStarDoneNodes.push_back(bestNode);
+ ++exploredCount;
+
+ VertInf *prevInf = (bestNode->prevNode) ? bestNode->prevNode->inf : nullptr;
+#ifdef ASTAR_DEBUG
+ db_printf("Considering... ");
+ db_printf(" %g %g ", bestNodeInf->point.x, bestNodeInf->point.y);
+ bestNodeInf->id.db_print();
+ db_printf(" - g: %3.1f h: %3.1f back: ", bestNode->g, bestNode->h);
+ if (prevInf)
+ {
+ db_printf(" %g %g", prevInf->point.x, prevInf->point.y);
+ //prevInf->id.db_print();
+ }
+ db_printf("\n");
+#endif
+
+ if (bestNodeInf == tar)
+ {
+ TIMER_VAR_ADD(router, 1, PENDING.size());
+ // This node is our goal.
+#ifdef ASTAR_DEBUG
+ db_printf("LINE %10d Steps: %4d Cost: %g\n", lineRef->id(),
+ (int) exploredCount, bestNode->f);
+#endif
+
+ // Correct all the pathNext pointers.
+ for (ANode *curr = bestNode; curr->prevNode; curr = curr->prevNode)
+ {
+#ifdef ASTAR_DEBUG
+ db_printf("[%.12f, %.12f]\n", curr->inf->point.x, curr->inf->point.y);
+#endif
+ curr->inf->pathNext = curr->prevNode->inf;
+ }
+#ifdef ASTAR_DEBUG
+ db_printf("\n");
+#endif
+
+ // Exit from the search
+ break;
+ }
+
+ // Check adjacent points in graph and add them to the queue.
+ EdgeInfList& visList = (!isOrthogonal) ?
+ bestNodeInf->visList : bestNodeInf->orthogVisList;
+ if (isOrthogonal)
+ {
+ // We would like to explore in a structured way,
+ // so sort the points in the visList...
+ CmpVisEdgeRotation compare(prevInf);
+ visList.sort(compare);
+ }
+ EdgeInfList::const_iterator finish = visList.end();
+ for (EdgeInfList::const_iterator edge = visList.begin();
+ edge != finish; ++edge)
+ {
+ if ((*edge)->isDisabled())
+ {
+ // Skip disabled edges.
+ continue;
+ }
+
+ node = ANode((*edge)->otherVert(bestNodeInf), timestamp++);
+
+ // Set the index to the previous ANode that we reached
+ // this ANode via.
+ node.prevNode = bestNode;
+
+ VertInf *prevInf = (bestNode->prevNode) ?
+ bestNode->prevNode->inf : nullptr;
+
+ // Don't bother looking at the segment we just arrived along.
+ if (prevInf && (prevInf == node.inf))
+ {
+ continue;
+ }
+ if (node.inf->id.isConnectionPin() &&
+ !node.inf->id.isConnCheckpoint())
+ {
+ if ( !( (bestNodeInf == lineRef->src()) &&
+ lineRef->src()->id.isDummyPinHelper()
+ ) &&
+ !( node.inf->hasNeighbour(lineRef->dst(), isOrthogonal) &&
+ lineRef->dst()->id.isDummyPinHelper())
+ )
+ {
+ // Don't check connection pins if they don't have the
+ // target vertex as a direct neighbour, or are directly
+ // leaving the source vertex.
+ continue;
+ }
+ }
+ else if (node.inf->id.isConnPt())
+ {
+ if ((node.inf != tar))
+ {
+ // Don't check connector endpoints vertices unless they
+ // are the target endpoint.
+ continue;
+ }
+ }
+
+ if (isOrthogonal && !(*edge)->isDummyConnection())
+ {
+ // Orthogonal routing optimisation.
+ // Skip the edges that don't lead to shape edges, or the
+ // connection point we are looking for. Though allow them
+ // if we haven't yet turned from the source point, since it
+ // may be a free-floating endpoint with directional visibility.
+ // Also, don't check if the previous point was a dummy for a
+ // connection pin and this happens to be placed diagonally
+ // from here, i.e., when both of notInline{X,Y} are true.
+ Point& bestPt = bestNodeInf->point;
+ Point& nextPt = node.inf->point;
+
+ bool notInlineX = prevInf && (prevInf->point.x != bestPt.x);
+ bool notInlineY = prevInf && (prevInf->point.y != bestPt.y);
+ if ((bestPt.x == nextPt.x) && notInlineX && !notInlineY &&
+ (bestPt[YDIM] != src->point[YDIM]))
+ {
+ if (nextPt.y < bestPt.y)
+ {
+ if (!(bestNodeInf->orthogVisPropFlags & YL_EDGE) &&
+ !pointAlignedWithOneOf(bestPt, endPoints, XDIM))
+ {
+ continue;
+ }
+ }
+ else if (nextPt.y > bestPt.y)
+ {
+ if (!(bestNodeInf->orthogVisPropFlags & YH_EDGE) &&
+ !pointAlignedWithOneOf(bestPt, endPoints, XDIM))
+ {
+ continue;
+ }
+ }
+ }
+ if ((bestPt.y == nextPt.y) && notInlineY && !notInlineX &&
+ (bestPt[XDIM] != src->point[XDIM]))
+ {
+ if (nextPt.x < bestPt.x)
+ {
+ if (!(bestNodeInf->orthogVisPropFlags & XL_EDGE) &&
+ !pointAlignedWithOneOf(bestPt, endPoints, YDIM))
+ {
+ continue;
+ }
+ }
+ else if (nextPt.x > bestPt.x)
+ {
+ if (!(bestNodeInf->orthogVisPropFlags & XH_EDGE) &&
+ !pointAlignedWithOneOf(bestPt, endPoints, YDIM))
+ {
+ continue;
+ }
+ }
+ }
+ }
+
+ double edgeDist = (*edge)->getDist();
+
+ if (edgeDist == 0)
+ {
+ continue;
+ }
+
+ if (!isOrthogonal &&
+ (!router->RubberBandRouting || (start == src)) &&
+ (validateBendPoint(prevInf, bestNodeInf, node.inf) == false))
+ {
+ // The bendpoint is not valid, i.e., is a zigzag corner, so...
+ continue;
+ // For RubberBand routing we want to allow these routes and
+ // unwind them later, otherwise instead or unwinding, paths
+ // can go the *really* long way round.
+ }
+
+ // Figure out if we are at one of the cost targets.
+ bool atCostTarget = false;
+ for (size_t i = 0; i < m_cost_targets.size(); ++i)
+ {
+ if (bestNode->inf == m_cost_targets[i])
+
+ {
+ atCostTarget = true;
+ break;
+ }
+ }
+
+ if (atCostTarget &&
+ (node.inf->id.isConnectionPin() || (node.inf == tar)))
+ {
+ // This is a point on the side of an obstacle that connects
+ // to the target or a connection pin. It should have no
+ // further cost and the heuristic should be zero.
+ node.g = bestNode->g;
+ node.h = 0;
+ }
+ else
+ {
+ if (node.inf == tar)
+ {
+ // We've reached the target. The heuristic should be zero.
+ node.h = 0;
+ }
+ else
+ {
+ // Otherwise, calculate the heuristic value.
+ node.h = estimatedCost(lineRef, &(bestNodeInf->point),
+ node.inf->point);
+ }
+
+ if (node.inf->id.isDummyPinHelper())
+ {
+ // This is connecting to a connection pin helper vertex.
+ // There should be no additional cost for this step.
+ node.g = bestNode->g;
+ }
+ else
+ {
+ // Otherwise, calculate the cost of this step.
+ node.g = bestNode->g + cost(lineRef, edgeDist, bestNodeInf,
+ node.inf, bestNode->prevNode);
+ }
+ }
+
+ // The A* formula
+ node.f = node.g + node.h;
+
+#ifdef ASTAR_DEBUG
+ db_printf("-- Adding: %g %g ", node.inf->point.x,
+ node.inf->point.y);
+ node.inf->id.db_print();
+ db_printf(" - g: %3.1f h: %3.1f \n", node.g, node.h);
+#endif
+
+ bNodeFound = false;
+
+
+ // Check to see if already on PENDING
+ std::list<ANode *>::const_iterator finish = node.inf->aStarPendingNodes.end();
+ for (std::list<ANode *>::const_iterator currInd =
+ node.inf->aStarPendingNodes.begin(); currInd != finish; ++currInd)
+ {
+ ati = **currInd;
+ // The (node.prevNode == ati.prevNode) is redundant, but may
+ // save checking the mosre costly prevNode->inf test if the
+ // Nodes are the same.
+ if ((node.inf == ati.inf) &&
+ ((node.prevNode == ati.prevNode) ||
+ (node.prevNode->inf == ati.prevNode->inf)))
+ {
+ // If already on PENDING
+ if (node.g < ati.g)
+ {
+ // Replace the existing node in PENDING
+ **currInd = node;
+ make_heap( PENDING.begin(), PENDING.end(), pendingCmp);
+ }
+ bNodeFound = true;
+ break;
+ }
+ }
+ if ( !bNodeFound ) // If Node NOT found on PENDING
+ {
+ // Check to see if it is already in the Done set for this
+ // vertex.
+ for (std::list<ANode *>::const_iterator currInd =
+ node.inf->aStarDoneNodes.begin();
+ currInd != node.inf->aStarDoneNodes.end(); ++currInd)
+ {
+ ati = **currInd;
+ // The (node.prevNode == ati.prevNode) is redundant, but may
+ // save checking the mosre costly prevNode->inf test if the
+ // Nodes are the same.
+ if ((node.inf == ati.inf) && ati.prevNode &&
+ ((node.prevNode == ati.prevNode) ||
+ (node.prevNode->inf == ati.prevNode->inf)))
+ {
+ //COLA_ASSERT(node.g >= (ati.g - 10e-10));
+ // This node is already in the Done set and the
+ // current node also has a higher g-value, so we
+ // don't need to consider this node.
+ bNodeFound = true;
+ break;
+ }
+ }
+ }
+
+ if (!bNodeFound ) // If Node NOT in either Pending or Done.
+ {
+ // Push NewNode onto PENDING
+ ANode *newNode = newANode(node);
+ PENDING.push_back(newNode);
+ // Push NewNode onto heap
+ push_heap( PENDING.begin(), PENDING.end(), pendingCmp);
+
+#if 0
+ using std::cout; using std::endl;
+ // Display PENDING container (For Debugging)
+ cout << "PENDING: ";
+ for (unsigned int i = 0; i < PENDING.size(); i++)
+ {
+ cout << PENDING[i]->g << "," << PENDING[i]->h << ",";
+ cout << PENDING[i]->inf << "," << PENDING[i]->pp << " ";
+ }
+ cout << endl << endl;
+#endif
+ }
+ }
+ }
+
+ // Cleanup lists used to store Done and Pending sets for each vertex.
+ VertInf *endVert = router->vertices.end();
+ for (VertInf *k = router->vertices.connsBegin(); k != endVert;
+ k = k->lstNext)
+ {
+ k->aStarDoneNodes.clear();
+ k->aStarPendingNodes.clear();
+ }
+}
+
+
+}
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/makepath.h b/src/3rdparty/adaptagrams/libavoid/makepath.h
new file mode 100644
index 0000000..2e4b5ba
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/makepath.h
@@ -0,0 +1,52 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+
+#ifndef AVOID_MAKEPATH_H
+#define AVOID_MAKEPATH_H
+
+
+namespace Avoid {
+
+class ConnRef;
+class AStarPathPrivate;
+class ANode;
+class VertInf;
+
+class AStarPath
+{
+ public:
+ AStarPath();
+ ~AStarPath();
+ void search(ConnRef *lineRef, VertInf *src, VertInf *tar,
+ VertInf *start);
+ private:
+ AStarPathPrivate *m_private;
+};
+
+}
+
+#endif
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/mtst.cpp b/src/3rdparty/adaptagrams/libavoid/mtst.cpp
new file mode 100644
index 0000000..d6c288f
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/mtst.cpp
@@ -0,0 +1,1094 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2011-2014 Monash University
+ *
+ * --------------------------------------------------------------------
+ * Sequential Construction of the Minimum Terminal Spanning Tree is an
+ * extended version of the method described in Section IV.B of:
+ * Long, J., Zhou, H., Memik, S.O. (2008). EBOARST: An efficient
+ * edge-based obstacle-avoiding rectilinear Steiner tree construction
+ * algorithm. IEEE Trans. on Computer-Aided Design of Integrated
+ * Circuits and Systems 27(12), pages 2169--2182.
+ * --------------------------------------------------------------------
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+#include <cfloat>
+#include <vector>
+#include <algorithm>
+#include <string>
+#include <cstring>
+
+
+#include "libavoid/hyperedgetree.h"
+#include "libavoid/router.h"
+#include "libavoid/mtst.h"
+#include "libavoid/vertices.h"
+#include "libavoid/timer.h"
+#include "libavoid/junction.h"
+#include "libavoid/debughandler.h"
+
+namespace Avoid {
+
+
+// Comparison for the vertex heap in the extended Dijkstra's algorithm.
+bool HeapCmpVertInf::operator()(const VertInf *a, const VertInf *b) const
+{
+ return a->sptfDist > b->sptfDist;
+}
+
+
+// Comparison for the bridging edge heap in the extended Kruskal's algorithm.
+bool CmpEdgeInf::operator()(const EdgeInf *a, const EdgeInf *b) const
+{
+ return a->mtstDist() > b->mtstDist();
+}
+
+
+struct delete_vertex
+{
+ void operator()(VertInf *ptr)
+ {
+ ptr->removeFromGraph(false);
+ delete ptr;
+ }
+};
+
+
+MinimumTerminalSpanningTree::MinimumTerminalSpanningTree(Router *router,
+ std::set<VertInf *> terminals, JunctionHyperedgeTreeNodeMap *hyperedgeTreeJunctions)
+ : router(router),
+ isOrthogonal(true),
+ terminals(terminals),
+ hyperedgeTreeJunctions(hyperedgeTreeJunctions),
+ m_rootJunction(nullptr),
+ bendPenalty(2000),
+ dimensionChangeVertexID(0, 42)
+{
+
+}
+
+MinimumTerminalSpanningTree::~MinimumTerminalSpanningTree()
+{
+ // Free the temporary hyperedge tree representation.
+ m_rootJunction->deleteEdgesExcept(nullptr);
+ delete m_rootJunction;
+ m_rootJunction = nullptr;
+}
+
+
+HyperedgeTreeNode *MinimumTerminalSpanningTree::rootJunction(void) const
+{
+ return m_rootJunction;
+}
+
+
+void MinimumTerminalSpanningTree::makeSet(VertInf *vertex)
+{
+ VertexSet newSet;
+ newSet.insert(vertex);
+ allsets.push_back(newSet);
+}
+
+VertexSetList::iterator MinimumTerminalSpanningTree::findSet(VertInf *vertex)
+{
+ for (VertexSetList::iterator it = allsets.begin();
+ it != allsets.end(); ++it)
+ {
+ if (it->find(vertex) != it->end())
+ {
+ return it;
+ }
+ }
+ return allsets.end();
+}
+
+void MinimumTerminalSpanningTree::unionSets(VertexSetList::iterator s1,
+ VertexSetList::iterator s2)
+{
+ std::set<VertInf *> s = *s1;
+ s.insert(s2->begin(), s2->end());
+
+ allsets.erase(s1);
+ allsets.erase(s2);
+ allsets.push_back(s);
+}
+
+HyperedgeTreeNode *MinimumTerminalSpanningTree::addNode(VertInf *vertex,
+ HyperedgeTreeNode *prevNode)
+{
+ HyperedgeTreeNode *node = nullptr;
+
+ // Do we already have a node for this vertex?
+ VertexNodeMap::iterator match = nodes.find(vertex);
+ if (match == nodes.end())
+ {
+ // Not found. Create new node.
+ HyperedgeTreeNode *newNode = new HyperedgeTreeNode();
+ newNode->point = vertex->point;
+ // Remember it.
+ nodes[vertex] = newNode;
+
+ node = newNode;
+ }
+ else
+ {
+ // Found.
+ HyperedgeTreeNode *junctionNode = match->second;
+ if (junctionNode->junction == nullptr)
+ {
+ // Create a junction, if one has not already been created.
+ junctionNode->junction = new JunctionRef(router, vertex->point);
+ if (m_rootJunction == nullptr)
+ {
+ // Remember the first junction node, so we can use it to
+ // traverse the tree, added and connecting connectors to
+ // junctions and endpoints.
+ m_rootJunction = junctionNode;
+ }
+ router->removeObjectFromQueuedActions(junctionNode->junction);
+ junctionNode->junction->makeActive();
+ }
+ node = junctionNode;
+ }
+
+ if (prevNode)
+ {
+ // Join this node to the previous node.
+ new HyperedgeTreeEdge(prevNode, node, nullptr);
+ }
+
+ return node;
+}
+
+void MinimumTerminalSpanningTree::buildHyperedgeTreeToRoot(VertInf *currVert,
+ HyperedgeTreeNode *prevNode, VertInf *prevVert, bool markEdges)
+{
+ if (prevNode->junction)
+ {
+ // We've reached a junction, so stop.
+ return;
+ }
+
+ COLA_ASSERT(currVert != nullptr);
+
+ // This method follows branches in a shortest path tree back to the
+ // root, generating hyperedge tree nodes and branches as it goes.
+ while (currVert)
+ {
+ // Add the node, if necessary.
+ HyperedgeTreeNode *currentNode = addNode(currVert, prevNode);
+
+ if (markEdges)
+ {
+ //COLA_ASSERT( !(currVert->id == dimensionChangeVertexID) );
+ //COLA_ASSERT( !(prevVert->id == dimensionChangeVertexID) );
+ EdgeInf *edge = prevVert->hasNeighbour(currVert, isOrthogonal);
+ if (edge == nullptr && (currVert->id == dimensionChangeVertexID))
+ {
+ VertInf *modCurr = (currVert->id == dimensionChangeVertexID) ?
+ currVert->m_orthogonalPartner : currVert;
+ VertInf *modPrev = (prevVert->id == dimensionChangeVertexID) ?
+ prevVert->m_orthogonalPartner : prevVert;
+ edge = modPrev->hasNeighbour(modCurr, isOrthogonal);
+ }
+ COLA_ASSERT(edge);
+ edge->setHyperedgeSegment(true);
+ }
+
+#ifdef DEBUGHANDLER
+ if (router->debugHandler())
+ {
+ router->debugHandler()->mtstCommitToEdge(currVert, prevVert, false);
+ }
+#endif
+
+ if (currentNode->junction)
+ {
+ // We've reached a junction, so stop.
+ break;
+ }
+
+ if (currVert->pathNext == nullptr)
+ {
+ // This is a terminal of the hyperedge, mark the node with the
+ // vertex representing the endpoint of the connector so we can
+ // later use this to set the correct ConnEnd for the connector.
+ currentNode->finalVertex = currVert;
+ }
+
+ if (currVert->id.isDummyPinHelper())
+ {
+ // Note if we have an extra dummy vertex for connecting
+ // to possible connection pins.
+ currentNode->isPinDummyEndpoint = true;
+ }
+
+ prevNode = currentNode;
+ prevVert = currVert;
+ currVert = currVert->pathNext;
+ }
+}
+
+
+VertInf **MinimumTerminalSpanningTree::resetDistsForPath(VertInf *currVert, VertInf **newRootVertPtr)
+{
+ COLA_ASSERT(currVert != nullptr);
+
+ // This method follows branches in a shortest path tree back to the
+ // root, generating hyperedge tree nodes and branches as it goes.
+ while (currVert)
+ {
+ if (currVert->sptfDist == 0)
+ {
+ VertInf **oldTreeRootPtr = currVert->treeRootPointer();
+ // We've reached a junction, so stop.
+ rewriteRestOfHyperedge(currVert, newRootVertPtr);
+ return oldTreeRootPtr;
+ }
+
+ currVert->sptfDist = 0;
+ currVert->setTreeRootPointer(newRootVertPtr);
+
+ terminals.insert(currVert);
+
+ currVert = currVert->pathNext;
+ }
+
+ // Shouldn't get here.
+ COLA_ASSERT(false);
+ return nullptr;
+}
+
+
+void MinimumTerminalSpanningTree::constructSequential(void)
+{
+ // First, perform extended Dijkstra's algorithm
+ // ============================================
+ //
+ TIMER_START(router, tmHyperedgeForest);
+
+ // Vertex heap for extended Dijkstra's algorithm.
+ std::vector<VertInf *> vHeap;
+ HeapCmpVertInf vHeapCompare;
+
+ // Bridging edge heap for the extended Kruskal's algorithm.
+ std::vector<EdgeInf *> beHeap;
+ CmpEdgeInf beHeapCompare;
+
+#ifdef DEBUGHANDLER
+ if (router->debugHandler())
+ {
+ router->debugHandler()->beginningHyperedgeReroutingWithEndpoints(
+ terminals);
+ }
+#endif
+
+ // Initialisation
+ //
+ VertInf *endVert = router->vertices.end();
+ for (VertInf *k = router->vertices.connsBegin(); k != endVert;
+ k = k->lstNext)
+ {
+ k->sptfDist = DBL_MAX;
+ k->pathNext = nullptr;
+ k->setSPTFRoot(k);
+ }
+ for (std::set<VertInf *>::iterator ti = terminals.begin();
+ ti != terminals.end(); ++ti)
+ {
+ VertInf *t = *ti;
+ // This is a terminal, set a distance of zero.
+ t->sptfDist = 0;
+ makeSet(t);
+ vHeap.push_back(t);
+
+ }
+ std::make_heap(vHeap.begin(), vHeap.end(), vHeapCompare);
+
+ // Shortest path terminal forest construction
+ //
+ while ( ! vHeap.empty() )
+ {
+ // Take the lowest vertex from heap.
+ VertInf *u = vHeap.front();
+
+ // Pop the lowest vertex off the heap.
+ std::pop_heap(vHeap.begin(), vHeap.end(), vHeapCompare);
+ vHeap.pop_back();
+
+ // For each edge from this vertex...
+ EdgeInfList& visList = (!isOrthogonal) ? u->visList : u->orthogVisList;
+ EdgeInfList::const_iterator finish = visList.end();
+ VertInf *extraVertex = nullptr;
+ for (EdgeInfList::const_iterator edge = visList.begin();
+ edge != finish; ++edge)
+ {
+ VertInf *v = (*edge)->otherVert(u);
+ double edgeDist = (*edge)->getDist();
+
+ // Assign a distance (length) of 1 for dummy visibility edges
+ // which may not accurately reflect the real distance of the edge.
+ if (v->id.isDummyPinHelper() || u->id.isDummyPinHelper())
+ {
+ edgeDist = 1;
+ }
+
+ // Ignore an edge we have already explored.
+ if (u->pathNext == v ||
+ (u->pathNext && u->pathNext->pathNext == v))
+ {
+ continue;
+ }
+
+ // Don't do anything more here if this is an intra-tree edge that
+ // would just bridge branches of the same tree.
+ if (u->sptfRoot() == v->sptfRoot())
+ {
+ continue;
+ }
+
+ // This is an extension to the original method that takes a bend
+ // cost into account. When edges from this node, we take into
+ // account the direction of the branch in the tree that got us
+ // here. For an edge colinear to this we do the normal thing,
+ // and add it to the heap. For edges at right angle, we don't
+ // immediately add these, but instead add a dummy segment and node
+ // at the current position and give the edge an distance equal to
+ // the bend penalty. We add equivalent edges for the right-angled
+ // original edges, so these may be explored when the algorithm
+ // explores the dummy node. Obviously we also need to clean up
+ // these dummy nodes and edges later.
+ double newCost = (u->sptfDist + edgeDist);
+
+ double freeConnection = connectsWithoutBend(u, v);
+ COLA_ASSERT(!freeConnection == (u->pathNext && ! colinear(u->pathNext->point,
+ u->point, v->point)));
+ if (!freeConnection)
+ {
+ // This edge is not colinear, so add it to the dummy node and
+ // ignore it.
+ COLA_ASSERT(u->id != dimensionChangeVertexID);
+ if ( ! extraVertex )
+ {
+ // Create the dummy node if necessary.
+ extraVertex = new VertInf(router, dimensionChangeVertexID,
+ u->point, false);
+ extraVertices.push_back(extraVertex);
+ extraVertex->sptfDist = bendPenalty + u->sptfDist;
+ extraVertex->pathNext = u;
+ extraVertex->setSPTFRoot(u->sptfRoot());
+ vHeap.push_back(extraVertex);
+ std::push_heap(vHeap.begin(), vHeap.end(), vHeapCompare);
+ }
+ // Add a copy of the ignored edge to the dummy node, so it
+ // may be explored later.
+ EdgeInf *extraEdge = new EdgeInf(extraVertex, v, isOrthogonal);
+ extraEdge->setDist(edgeDist);
+ continue;
+ }
+
+ if (newCost < v->sptfDist && v->sptfRoot() == v)
+ {
+ // We have got to a node we haven't explored to from any tree.
+ // So attach it to the tree and update it with the distance
+ // from the root to reach this vertex. Then add the vertex
+ // to the heap of potentials to explore.
+ v->sptfDist = newCost;
+ v->pathNext = u;
+ v->setSPTFRoot(u->sptfRoot());
+ vHeap.push_back(v);
+ std::push_heap(vHeap.begin(), vHeap.end(), vHeapCompare);
+#ifdef DEBUGHANDLER
+ if (router->debugHandler())
+ {
+ router->debugHandler()->mtstGrowForestWithEdge(u, v, true);
+ }
+#endif
+ }
+ else
+ {
+ // We have reached a node that has been reached already through
+ // a different tree. Set the MTST distance for the bridging
+ // edge and push it to the priority queue of edges to consider
+ // during the extended Kruskal's algorithm.
+ double secondJoinCost = connectsWithoutBend(v, u) ?
+ 0.0 : bendPenalty;
+
+ // The default cost is the cost back to the root of each
+ // forest plus the length of this edge.
+ double cost = (*edge)->m_vert1->sptfDist +
+ (*edge)->m_vert2->sptfDist + secondJoinCost +
+ (*edge)->getDist();
+ (*edge)->setMtstDist(cost);
+ beHeap.push_back(*edge);
+
+#ifdef DEBUGHANDLER
+ if (router->debugHandler())
+ {
+ router->debugHandler()->mtstPotentialBridgingEdge(u, v);
+ }
+#endif
+ }
+ }
+ }
+ // Make the bridging edge heap.
+ std::make_heap(beHeap.begin(), beHeap.end(), beHeapCompare);
+ TIMER_STOP(router);
+
+ // Next, perform extended Kruskal's algorithm
+ // ==========================================
+ //
+ TIMER_START(router, tmHyperedgeMTST);
+ while ( ! beHeap.empty() )
+ {
+ // Take the lowest cost edge.
+ EdgeInf *e = beHeap.front();
+
+ // Pop the lowest cost edge off of the heap.
+ std::pop_heap(beHeap.begin(), beHeap.end(), beHeapCompare);
+ beHeap.pop_back();
+
+ // Find the sets of terminals that each of the trees connects.
+ VertexSetList::iterator s1 = findSet(e->m_vert1->sptfRoot());
+ VertexSetList::iterator s2 = findSet(e->m_vert2->sptfRoot());
+
+ if ((s1 == allsets.end()) || (s2 == allsets.end()))
+ {
+ // This is a special case if we would be connecting to something
+ // that isn't a standard terminal shortest path tree, and thus
+ // doesn't have a root.
+ continue;
+ }
+
+ // We ignore edges that don't connect us to anything new, i.e., when
+ // the terminal sets are the same.
+ if (s1 != s2)
+ {
+ // This is bridging us to one or more new terminals.
+
+ // Union the terminal sets.
+ unionSets(s1, s2);
+
+ // Connect this edge into the MTST by building HyperedgeTree nodes
+ // and edges for this edge and the path back to the tree root.
+ HyperedgeTreeNode *node1 = nullptr;
+ HyperedgeTreeNode *node2 = nullptr;
+ if (hyperedgeTreeJunctions)
+ {
+ node1 = addNode(e->m_vert1, nullptr);
+ node2 = addNode(e->m_vert2, node1);
+ }
+
+#ifdef DEBUGHANDLER
+ if (router->debugHandler())
+ {
+ router->debugHandler()->mtstCommitToEdge(
+ e->m_vert1, e->m_vert2, true);
+ }
+#endif
+
+ buildHyperedgeTreeToRoot(e->m_vert1->pathNext, node1, e->m_vert1);
+ buildHyperedgeTreeToRoot(e->m_vert2->pathNext, node2, e->m_vert2);
+ }
+ }
+
+ // Free the dummy nodes and edges created earlier.
+ for_each(extraVertices.begin(), extraVertices.end(), delete_vertex());
+ extraVertices.clear();
+ nodes.clear();
+ allsets.clear();
+
+ TIMER_STOP(router);
+}
+
+VertInf *MinimumTerminalSpanningTree::orthogonalPartner(VertInf *vert,
+ double penalty)
+{
+ if (penalty == 0)
+ {
+ penalty = bendPenalty;
+ }
+ if (vert->m_orthogonalPartner == nullptr)
+ {
+ vert->m_orthogonalPartner = new VertInf(router,
+ dimensionChangeVertexID, vert->point, false);
+ vert->m_orthogonalPartner->m_orthogonalPartner = vert;
+ extraVertices.push_back(vert->m_orthogonalPartner);
+ EdgeInf *extraEdge = new EdgeInf(vert->m_orthogonalPartner, vert,
+ isOrthogonal);
+ extraEdge->setDist(penalty);
+ }
+ return vert->m_orthogonalPartner;
+}
+
+void MinimumTerminalSpanningTree::removeInvalidBridgingEdges()
+{
+ // Look through the bridging edge heap for any now invalidated edges and
+ // remove these by only copying valid edges to the beHeapNew array.
+ size_t beHeapSize = beHeap.size();
+ std::vector<EdgeInf *> beHeapNew(beHeapSize);
+ size_t j = 0;
+ for (size_t i = 0; i < beHeapSize; ++i)
+ {
+ EdgeInf *e = beHeap[i];
+
+ VertexPair ends = realVerticesCountingPartners(e);
+ bool valid = (ends.first->treeRoot() != ends.second->treeRoot()) &&
+ ends.first->treeRoot() && ends.second->treeRoot() &&
+ (origTerminals.find(ends.first->treeRoot()) != origTerminals.end()) &&
+ (origTerminals.find(ends.second->treeRoot()) != origTerminals.end());
+ if (!valid)
+ {
+ // This is an invalid edge, don't copy it to beHeapNew.
+ continue;
+ }
+
+ // Copy the other bridging edges to beHeapNew.
+ beHeapNew[j] = beHeap[i];
+ ++j;
+ }
+ beHeapNew.resize(j);
+ // Replace beHeap with beHeapNew
+ beHeap = beHeapNew;
+
+ // Remake the bridging edge heap, since we've deleted many elements.
+ std::make_heap(beHeap.begin(), beHeap.end(), beHeapCompare);
+}
+
+LayeredOrthogonalEdgeList MinimumTerminalSpanningTree::
+ getOrthogonalEdgesFromVertex(VertInf *vert, VertInf *prev)
+{
+ LayeredOrthogonalEdgeList edgeList;
+
+ COLA_ASSERT(vert);
+
+ double penalty = (prev == nullptr) ? 0.1 : 0;
+ orthogonalPartner(vert, penalty);
+
+ bool isRealVert = (vert->id != dimensionChangeVertexID);
+ VertInf *realVert = (isRealVert) ? vert : orthogonalPartner(vert);
+ COLA_ASSERT(realVert->id != dimensionChangeVertexID);
+ EdgeInfList& visList = (!isOrthogonal) ? realVert->visList : realVert->orthogVisList;
+ EdgeInfList::const_iterator finish = visList.end();
+ for (EdgeInfList::const_iterator edge = visList.begin(); edge != finish; ++edge)
+ {
+ VertInf *other = (*edge)->otherVert(realVert);
+
+ if (other == orthogonalPartner(realVert))
+ {
+ VertInf *partner = (isRealVert) ? other : orthogonalPartner(other);
+ if (partner != prev)
+ {
+ edgeList.push_back(std::make_pair(*edge, partner));
+ }
+ continue;
+ }
+
+ VertInf *partner = (isRealVert) ? other : orthogonalPartner(other);
+ COLA_ASSERT(partner);
+
+ if (other->point.y == realVert->point.y)
+ {
+ if (isRealVert && (prev != partner))
+ {
+ edgeList.push_back(std::make_pair(*edge, partner));
+ }
+ }
+ else if (other->point.x == realVert->point.x)
+ {
+ if (!isRealVert && (prev != partner))
+ {
+ edgeList.push_back(std::make_pair(*edge, partner));
+ }
+ }
+ else
+ {
+ printf("Warning, nonorthogonal edge.\n");
+ edgeList.push_back(std::make_pair(*edge, other));
+ }
+ }
+
+ return edgeList;
+}
+
+void MinimumTerminalSpanningTree::constructInterleaved(void)
+{
+ // Perform an interleaved construction of the MTST and SPTF
+ // ========================================================
+ //
+ TIMER_START(router, tmHyperedgeAlt);
+
+ origTerminals = terminals;
+
+ // Initialisation
+ //
+ VertInf *endVert = router->vertices.end();
+ for (VertInf *k = router->vertices.connsBegin(); k != endVert;
+ k = k->lstNext)
+ {
+ k->sptfDist = DBL_MAX;
+ k->pathNext = nullptr;
+ k->setTreeRootPointer(nullptr);
+ k->m_orthogonalPartner = nullptr;
+ }
+
+#ifdef DEBUGHANDLER
+ if (router->debugHandler())
+ {
+ router->debugHandler()->beginningHyperedgeReroutingWithEndpoints(
+ terminals);
+ }
+#endif
+
+ COLA_ASSERT(rootVertexPointers.empty());
+ for (std::set<VertInf *>::iterator ti = terminals.begin();
+ ti != terminals.end(); ++ti)
+ {
+ VertInf *t = *ti;
+ // This is a terminal, set a distance of zero.
+ t->sptfDist = 0;
+ rootVertexPointers.push_back(t->makeTreeRootPointer(t));
+ vHeap.push_back(t);
+ }
+ for (EdgeInf *t = router->visOrthogGraph.begin();
+ t != router->visOrthogGraph.end(); t = t->lstNext)
+ {
+ t->setHyperedgeSegment(false);
+ }
+
+ std::make_heap(vHeap.begin(), vHeap.end(), vHeapCompare);
+
+ // Shortest Path Terminal Forest construction
+ //
+ while ( ! vHeap.empty() )
+ {
+ // Take the lowest vertex from heap.
+ VertInf *u = vHeap.front();
+
+ // There should be no orphaned vertices.
+ COLA_ASSERT(u->treeRoot() != nullptr);
+ COLA_ASSERT(u->pathNext || (u->sptfDist == 0));
+
+ if (!beHeap.empty() && u->sptfDist >= (0.5 * beHeap.front()->mtstDist()))
+ {
+ // Take the lowest cost edge.
+ EdgeInf *e = beHeap.front();
+
+ // Pop the lowest cost edge off of the heap.
+ std::pop_heap(beHeap.begin(), beHeap.end(), beHeapCompare);
+ beHeap.pop_back();
+
+#ifndef NDEBUG
+ VertexPair ends = realVerticesCountingPartners(e);
+#endif
+ COLA_ASSERT(origTerminals.find(ends.first->treeRoot()) != origTerminals.end());
+ COLA_ASSERT(origTerminals.find(ends.second->treeRoot()) != origTerminals.end());
+
+ commitToBridgingEdge(e);
+
+ if (origTerminals.size() == 1)
+ {
+ break;
+ }
+
+ removeInvalidBridgingEdges();
+
+ // Don't pop this vertex, but continue.
+ continue;
+ }
+
+ // Pop the lowest vertex off the heap.
+ std::pop_heap(vHeap.begin(), vHeap.end(), vHeapCompare);
+ vHeap.pop_back();
+
+ // For each edge from this vertex...
+ LayeredOrthogonalEdgeList edgeList = getOrthogonalEdgesFromVertex(u,
+ u->pathNext);
+ for (LayeredOrthogonalEdgeList::const_iterator edge = edgeList.begin();
+ edge != edgeList.end(); ++edge)
+ {
+ VertInf *v = edge->second;
+ EdgeInf *e = edge->first;
+ double edgeDist = e->getDist();
+
+ // Assign a distance (length) of 1 for dummy visibility edges
+ // which may not accurately reflect the real distance of the edge.
+ if (v->id.isDummyPinHelper() || u->id.isDummyPinHelper())
+ {
+ edgeDist = 1;
+ }
+
+ // Don't do anything more here if this is an intra-tree edge that
+ // would just bridge branches of the same tree.
+ if (u->treeRoot() == v->treeRoot())
+ {
+ continue;
+ }
+
+ // This is an extension to the original method that takes a bend
+ // cost into account. For edges from this node, we take into
+ // account the direction of the branch in the tree that got us
+ // here. For an edge colinear to this we do the normal thing,
+ // and add it to the heap. For edges at right angle, we don't
+ // immediately add these, but instead add a dummy segment and node
+ // at the current position and give the edge an distance equal to
+ // the bend penalty. We add equivalent edges for the right-angled
+ // original edges, so these may be explored when the algorithm
+ // explores the dummy node. Obviously we also need to clean up
+ // these dummy nodes and edges later.
+ if (v->treeRoot() == nullptr)
+ {
+ double newCost = (u->sptfDist + edgeDist);
+
+ // We have got to a node we haven't explored to from any tree.
+ // So attach it to the tree and update it with the distance
+ // from the root to reach this vertex. Then add the vertex
+ // to the heap of potentials to explore.
+ v->sptfDist = newCost;
+ v->pathNext = u;
+ v->setTreeRootPointer(u->treeRootPointer());
+ vHeap.push_back(v);
+ // This can change the cost of other vertices in the heap,
+ // so we need to remake it.
+ std::make_heap(vHeap.begin(), vHeap.end(), vHeapCompare);
+
+#ifdef DEBUGHANDLER
+ if (router->debugHandler())
+ {
+ router->debugHandler()->mtstGrowForestWithEdge(u, v, true);
+ }
+#endif
+ }
+ else
+ {
+ // We have reached a node that has been reached already through
+ // a different tree. Set the MTST distance for the bridging
+ // edge and push it to the priority queue of edges to consider
+ // during the extended Kruskal's algorithm.
+ double cost = v->sptfDist + u->sptfDist + e->getDist();
+ bool found = std::find(beHeap.begin(), beHeap.end(), e) != beHeap.end();
+ if (!found)
+ {
+ // We need to add the edge to the bridging edge heap.
+ e->setMtstDist(cost);
+ beHeap.push_back(e);
+ std::push_heap(beHeap.begin(), beHeap.end(), beHeapCompare);
+#ifdef DEBUGHANDLER
+ if (router->debugHandler())
+ {
+ router->debugHandler()->mtstPotentialBridgingEdge(u, v);
+ }
+#endif
+ }
+ else
+ {
+ // This edge is already in the bridging edge heap.
+ if (cost < e->mtstDist())
+ {
+ // Update the edge's mtstDist if we compute a lower
+ // cost than we had before.
+ e->setMtstDist(cost);
+ std::make_heap(beHeap.begin(), beHeap.end(), beHeapCompare);
+ }
+ }
+ }
+ }
+ }
+ COLA_ASSERT(origTerminals.size() == 1);
+ TIMER_STOP(router);
+
+ // Free Root Vertex Points from all vertices.
+ for (std::list<VertInf **>::iterator curr = rootVertexPointers.begin();
+ curr != rootVertexPointers.end(); ++curr)
+ {
+ free(*curr);
+ }
+ rootVertexPointers.clear();
+
+ // Free the dummy nodes and edges created earlier.
+ for_each(extraVertices.begin(), extraVertices.end(), delete_vertex());
+ extraVertices.clear();
+}
+
+bool MinimumTerminalSpanningTree::connectsWithoutBend(VertInf *oldLeaf,
+ VertInf *newLeaf)
+{
+ COLA_ASSERT(isOrthogonal);
+
+ if (oldLeaf->sptfDist == 0)
+ {
+ bool hyperedgeConnection = false;
+ EdgeInfList& visList = (!isOrthogonal) ?
+ oldLeaf->visList : oldLeaf->orthogVisList;
+ EdgeInfList::const_iterator finish = visList.end();
+ for (EdgeInfList::const_iterator edge = visList.begin();
+ edge != finish; ++edge)
+ {
+ VertInf *other = (*edge)->otherVert(oldLeaf);
+
+ if (other == newLeaf)
+ {
+ continue;
+ }
+
+ if (other->point == oldLeaf->point)
+ {
+ continue;
+ }
+
+ if ((*edge)->isHyperedgeSegment())
+ {
+ hyperedgeConnection = true;
+ if (colinear(other->point, oldLeaf->point, newLeaf->point))
+ {
+ return true;
+ }
+ }
+ }
+ // If there was no hyperedge to connect to, then its a tree source
+ // and we can connect without a bend.
+ return (!hyperedgeConnection) ? true : false;
+ }
+ else
+ {
+ if (oldLeaf->pathNext)
+ {
+ return colinear(oldLeaf->pathNext->point, oldLeaf->point,
+ newLeaf->point);
+ }
+ else
+ {
+ // No penalty.
+ return true;
+ }
+ }
+}
+
+void MinimumTerminalSpanningTree::rewriteRestOfHyperedge(VertInf *vert,
+ VertInf **newTreeRootPtr)
+{
+ vert->setTreeRootPointer(newTreeRootPtr);
+
+ LayeredOrthogonalEdgeList edgeList = getOrthogonalEdgesFromVertex(vert,
+ nullptr);
+ for (LayeredOrthogonalEdgeList::const_iterator edge = edgeList.begin();
+ edge != edgeList.end(); ++edge)
+ {
+ VertInf *v = edge->second;
+
+ if (v->treeRootPointer() == newTreeRootPtr)
+ {
+ // Already marked.
+ continue;
+ }
+
+ if (v->sptfDist == 0)
+ {
+ // This is part of the rest of an existing hyperedge,
+ // so mark it and continue.
+ rewriteRestOfHyperedge(v, newTreeRootPtr);
+ }
+ }
+}
+
+void MinimumTerminalSpanningTree::drawForest(VertInf *vert, VertInf *prev)
+{
+ if (prev == nullptr)
+ {
+ std::string colour = "green";
+ /*
+ if (vert->id == dimensionChangeVertexID)
+ {
+ colour = "blue";
+ }
+ */
+
+ if (vert->treeRoot() == nullptr)
+ {
+ colour = "red";
+ }
+
+ COLA_ASSERT(vert->treeRootPointer() != nullptr);
+ COLA_ASSERT(vert->treeRoot() != nullptr);
+ //fprintf(debug_fp, "<circle cx=\"%g\" cy=\"%g\" r=\"3\" db:sptfDist=\"%g\" "
+ // "style=\"fill: %s; stroke: %s; fill-opacity: 0.5; "
+ // "stroke-width: 1px; stroke-opacity:0.5\" />\n",
+ // vert->point.x, vert->point.y, vert->sptfDist, colour.c_str(), "black");
+ }
+
+ LayeredOrthogonalEdgeList edgeList = getOrthogonalEdgesFromVertex(vert,
+ prev);
+ for (LayeredOrthogonalEdgeList::const_iterator edge = edgeList.begin();
+ edge != edgeList.end(); ++edge)
+ {
+ VertInf *v = edge->second;
+
+ if (v->sptfDist == 0)
+ {
+ continue;
+ }
+
+ if (v->treeRoot() == vert->treeRoot())
+ {
+ if (v->pathNext == vert)
+ {
+ if (vert->point != v->point)
+ {
+ router->debugHandler()->mtstGrowForestWithEdge(vert, v, false);
+ }
+ drawForest(v, vert);
+ }
+ }
+ }
+}
+
+VertexPair MinimumTerminalSpanningTree::
+ realVerticesCountingPartners(EdgeInf *edge)
+{
+ VertInf *v1 = edge->m_vert1;
+ VertInf *v2 = edge->m_vert2;
+
+ VertexPair realVertices = std::make_pair(v1, v2);
+
+ if ((v1->id != dimensionChangeVertexID) &&
+ (v2->id != dimensionChangeVertexID) &&
+ (v1->point != v2->point) &&
+ (v1->point.x == v2->point.x))
+ {
+ if (v1->m_orthogonalPartner)
+ {
+ realVertices.first = v1->m_orthogonalPartner;
+ }
+ if (v2->m_orthogonalPartner)
+ {
+ realVertices.second = v2->m_orthogonalPartner;
+ }
+ }
+
+ return realVertices;
+}
+
+
+void MinimumTerminalSpanningTree::commitToBridgingEdge(EdgeInf *e)
+{
+ VertexPair ends = realVerticesCountingPartners(e);
+ VertInf *newRoot = std::min(ends.first->treeRoot(), ends.second->treeRoot());
+ VertInf *oldRoot = std::max(ends.first->treeRoot(), ends.second->treeRoot());
+
+ // Connect this edge into the MTST by building HyperedgeTree nodes
+ // and edges for this edge and the path back to the tree root.
+ HyperedgeTreeNode *node1 = nullptr;
+ HyperedgeTreeNode *node2 = nullptr;
+
+ VertInf *vert1 = ends.first;
+ VertInf *vert2 = ends.second;
+ if (hyperedgeTreeJunctions)
+ {
+ node1 = addNode(vert1, nullptr);
+ node2 = addNode(vert2, node1);
+ e->setHyperedgeSegment(true);
+ }
+
+#ifdef DEBUGHANDLER
+ if (router->debugHandler())
+ {
+ router->debugHandler()->mtstCommitToEdge(vert1, vert2, true);
+ for (std::set<VertInf *>::iterator ti = terminals.begin();
+ ti != terminals.end(); ++ti)
+ {
+ drawForest(*ti, nullptr);
+ }
+ }
+#endif
+
+ buildHyperedgeTreeToRoot(vert1->pathNext, node1, vert1, true);
+ buildHyperedgeTreeToRoot(vert2->pathNext, node2, vert2, true);
+
+ // We are commmitting to a particular path and pruning back the shortest
+ // path terminal forests from the roots of that path. We do this by
+ // rewriting the treeRootPointers for all the points on the current
+ // hyperedge path to newTreeRootPtr. The rest of the vertices in the
+ // forest will be pruned by rewriting their treeRootPointer to nullptr.
+ VertInf **oldTreeRootPtr1 = vert1->treeRootPointer();
+ VertInf **oldTreeRootPtr2 = vert2->treeRootPointer();
+ origTerminals.erase(oldRoot);
+ VertInf **newTreeRootPtr = vert1->makeTreeRootPointer(newRoot);
+ rootVertexPointers.push_back(newTreeRootPtr);
+ vert2->setTreeRootPointer(newTreeRootPtr);
+
+ // Zero paths and rewrite the vertices on the hyperedge path to the
+ // newTreeRootPtr. Also, add vertices on path to the terminal set.
+ COLA_ASSERT(newRoot);
+ resetDistsForPath(vert1, newTreeRootPtr);
+ resetDistsForPath(vert2, newTreeRootPtr);
+
+ // Prune the forests from the joined vertex sets by setting their
+ // treeRootPointers to nullptr.
+ COLA_ASSERT(oldTreeRootPtr1);
+ COLA_ASSERT(oldTreeRootPtr2);
+ *oldTreeRootPtr1 = nullptr;
+ *oldTreeRootPtr2 = nullptr;
+
+ // We have found the full hyperedge path when we have joined all the
+ // terminal sets into one.
+ if (origTerminals.size() == 1)
+ {
+ return;
+ }
+
+ // Remove newly orphaned vertices from vertex heap by only copying the
+ // valid vertices to vHeapNew array which then replaces vHeap.
+ std::vector<VertInf *> vHeapNew(vHeap.size());
+ size_t j = 0;
+ size_t vHeapSize = vHeap.size();
+ for (size_t i = 0; i < vHeapSize; ++i)
+ {
+ VertInf *v = vHeap[i];
+
+ if ((v->treeRoot() == nullptr))
+ {
+ // This is an orphaned vertex.
+ continue;
+ }
+
+ // Copy the other vertices to vHeapNew.
+ vHeapNew[j] = vHeap[i];
+ ++j;
+ }
+ vHeapNew.resize(j);
+ // Replace vHeap with vHeapNew
+ vHeap = vHeapNew;
+
+ // Reset all terminals to zero.
+ for (std::set<VertInf *>::iterator v2 = terminals.begin();
+ v2 != terminals.end(); ++v2)
+ {
+ COLA_ASSERT((*v2)->sptfDist == 0);
+ vHeap.push_back(*v2);
+ }
+
+ // Rebuild the heap since some terminals will have had distances
+ // rewritten as well as the orphaned vertices being removed.
+ std::make_heap(vHeap.begin(), vHeap.end(), vHeapCompare);
+}
+
+}
diff --git a/src/3rdparty/adaptagrams/libavoid/mtst.h b/src/3rdparty/adaptagrams/libavoid/mtst.h
new file mode 100644
index 0000000..3789ad4
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/mtst.h
@@ -0,0 +1,134 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2011-2013 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+#ifndef AVOID_MTST_H
+#define AVOID_MTST_H
+
+#include <cstdio>
+#include <set>
+#include <list>
+#include <utility>
+
+#include "libavoid/vertices.h"
+#include "libavoid/hyperedgetree.h"
+
+
+namespace Avoid {
+
+class VertInf;
+class Router;
+class ConnRef;
+class EdgeInf;
+
+typedef std::list<VertexSet> VertexSetList;
+
+typedef std::pair<EdgeInf *, VertInf *> LayeredOrthogonalEdge;
+typedef std::list<LayeredOrthogonalEdge> LayeredOrthogonalEdgeList;
+
+// Comparison for the vertex heap in the extended Dijkstra's algorithm.
+struct HeapCmpVertInf
+{
+ bool operator()(const VertInf *a, const VertInf *b) const;
+};
+
+
+// Comparison for the bridging edge heap in the extended Kruskal's algorithm.
+struct CmpEdgeInf
+{
+ bool operator()(const EdgeInf *a, const EdgeInf *b) const;
+};
+
+
+// This class is not intended for public use.
+// It is used by the hyperedge routing code to build a minimum terminal
+// spanning tree for a set of terminal vertices.
+class MinimumTerminalSpanningTree
+{
+ public:
+ MinimumTerminalSpanningTree(Router *router,
+ std::set<VertInf *> terminals,
+ JunctionHyperedgeTreeNodeMap *hyperedgeTreeJunctions = nullptr);
+ ~MinimumTerminalSpanningTree();
+
+ // Uses Interleaved construction of the MTST and SPTF (heuristic 2
+ // from paper). This is the preferred construction approach.
+ void constructInterleaved(void);
+ // Uses Sequential construction of the MTST (heuristic 1 from paper).
+ void constructSequential(void);
+
+ void setDebuggingOutput(FILE *fp, unsigned int counter);
+ HyperedgeTreeNode *rootJunction(void) const;
+
+ private:
+ void buildHyperedgeTreeToRoot(VertInf *curr,
+ HyperedgeTreeNode *prevNode, VertInf *prevVert,
+ bool markEdges = false);
+ VertInf **resetDistsForPath(VertInf *currVert, VertInf **newRootVertPtr);
+ void rewriteRestOfHyperedge(VertInf *vert, VertInf **newTreeRootPtr);
+ void drawForest(VertInf *vert, VertInf *prev);
+
+ void makeSet(VertInf *vertex);
+ VertexSetList::iterator findSet(VertInf *vertex);
+ void unionSets(VertexSetList::iterator s1, VertexSetList::iterator s2);
+ HyperedgeTreeNode *addNode(VertInf *vertex, HyperedgeTreeNode *prevNode);
+
+ void removeInvalidBridgingEdges(void);
+ void commitToBridgingEdge(EdgeInf *e);
+ bool connectsWithoutBend(VertInf *oldLeaf, VertInf *newLeaf);
+ LayeredOrthogonalEdgeList getOrthogonalEdgesFromVertex(VertInf *vert,
+ VertInf *prev);
+ VertInf *orthogonalPartner(VertInf *vert, double penalty = 0);
+ VertexPair realVerticesCountingPartners(EdgeInf *edge);
+
+
+ Router *router;
+ bool isOrthogonal;
+ std::set<VertInf *> terminals;
+ std::set<VertInf *> origTerminals;
+ JunctionHyperedgeTreeNodeMap *hyperedgeTreeJunctions;
+
+ VertexNodeMap nodes;
+ HyperedgeTreeNode *m_rootJunction;
+ double bendPenalty;
+ VertexSetList allsets;
+ std::list<VertInf *> visitedVertices;
+ std::list<VertInf *> extraVertices;
+ std::list<VertInf *> unusedVertices;
+ std::list<VertInf **> rootVertexPointers;
+
+ // Vertex heap for extended Dijkstra's algorithm.
+ std::vector<VertInf *> vHeap;
+ HeapCmpVertInf vHeapCompare;
+
+ // Bridging edge heap for the extended Kruskal's algorithm.
+ std::vector<EdgeInf *> beHeap;
+ CmpEdgeInf beHeapCompare;
+
+ const VertID dimensionChangeVertexID;
+};
+
+
+}
+
+#endif
diff --git a/src/3rdparty/adaptagrams/libavoid/obstacle.cpp b/src/3rdparty/adaptagrams/libavoid/obstacle.cpp
new file mode 100644
index 0000000..ac7139b
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/obstacle.cpp
@@ -0,0 +1,355 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+
+#include "libavoid/obstacle.h"
+#include "libavoid/router.h"
+#include "libavoid/connectionpin.h"
+#include "libavoid/debug.h"
+
+namespace Avoid {
+
+
+Obstacle::Obstacle(Router *router, Polygon ply, const unsigned int id)
+ : m_router(router),
+ m_polygon(ply),
+ m_active(false),
+ m_first_vert(nullptr),
+ m_last_vert(nullptr)
+{
+ COLA_ASSERT(m_router != nullptr);
+ m_id = m_router->assignId(id);
+
+ VertID i = VertID(m_id, 0);
+
+ Polygon routingPoly = routingPolygon();
+ const bool addToRouterNow = false;
+ VertInf *last = nullptr;
+ VertInf *node = nullptr;
+ for (size_t pt_i = 0; pt_i < routingPoly.size(); ++pt_i)
+ {
+ node = new VertInf(m_router, i, routingPoly.ps[pt_i], addToRouterNow);
+
+ if (!m_first_vert)
+ {
+ m_first_vert = node;
+ }
+ else
+ {
+ node->shPrev = last;
+ last->shNext = node;
+ //node->lstPrev = last;
+ //last->lstNext = node;
+ }
+
+ last = node;
+ i++;
+ }
+ m_last_vert = node;
+
+ m_last_vert->shNext = m_first_vert;
+ m_first_vert->shPrev = m_last_vert;
+}
+
+
+Obstacle::~Obstacle()
+{
+ COLA_ASSERT(m_active == false);
+ COLA_ASSERT(m_first_vert != nullptr);
+
+ VertInf *it = m_first_vert;
+ do
+ {
+ VertInf *tmp = it;
+ it = it->shNext;
+
+ delete tmp;
+ }
+ while (it != m_first_vert);
+ m_first_vert = m_last_vert = nullptr;
+
+ // Free and clear any connection pins.
+ while (!m_connection_pins.empty())
+ {
+ delete *(m_connection_pins.begin());
+ }
+}
+
+
+void Obstacle::setNewPoly(const Polygon& poly)
+{
+ COLA_ASSERT(m_first_vert != nullptr);
+ COLA_ASSERT(m_polygon.size() == poly.size());
+
+ m_polygon = poly;
+ Polygon routingPoly = routingPolygon();
+
+ VertInf *curr = m_first_vert;
+ for (size_t pt_i = 0; pt_i < routingPoly.size(); ++pt_i)
+ {
+ COLA_ASSERT(curr->visListSize == 0);
+ COLA_ASSERT(curr->invisListSize == 0);
+
+ // Reset with the new polygon point.
+ curr->Reset(routingPoly.ps[pt_i]);
+ curr->pathNext = nullptr;
+
+ curr = curr->shNext;
+ }
+ COLA_ASSERT(curr == m_first_vert);
+
+ // It may be that the polygon for the obstacle has been updated after
+ // creating the shape. These events may have been combined for a single
+ // transaction, so update pin positions.
+ for (ShapeConnectionPinSet::iterator curr =
+ m_connection_pins.begin(); curr != m_connection_pins.end(); ++curr)
+ {
+ ShapeConnectionPin *pin = *curr;
+ pin->updatePosition(m_polygon);
+ }
+}
+
+
+void Obstacle::makeActive(void)
+{
+ COLA_ASSERT(!m_active);
+
+ // Add to shapeRefs list.
+ m_router_obstacles_pos = m_router->m_obstacles.insert(
+ m_router->m_obstacles.begin(), this);
+
+ // Add points to vertex list.
+ VertInf *it = m_first_vert;
+ do
+ {
+ VertInf *tmp = it;
+ it = it->shNext;
+
+ m_router->vertices.addVertex(tmp);
+ }
+ while (it != m_first_vert);
+
+ m_active = true;
+}
+
+
+void Obstacle::makeInactive(void)
+{
+ COLA_ASSERT(m_active);
+
+ // Remove from shapeRefs list.
+ m_router->m_obstacles.erase(m_router_obstacles_pos);
+
+ // Remove points from vertex list.
+ VertInf *it = m_first_vert;
+ do
+ {
+ VertInf *tmp = it;
+ it = it->shNext;
+
+ m_router->vertices.removeVertex(tmp);
+ }
+ while (it != m_first_vert);
+
+ m_active = false;
+
+ // Turn attached ConnEnds into manual points.
+ bool deletedShape = true;
+ while (!m_following_conns.empty())
+ {
+ ConnEnd *connEnd = *(m_following_conns.begin());
+ connEnd->disconnect(deletedShape);
+ }
+}
+
+
+void Obstacle::updatePinPolyLineVisibility(void)
+{
+ for (ShapeConnectionPinSet::iterator curr =
+ m_connection_pins.begin();
+ curr != m_connection_pins.end(); ++curr)
+ {
+ (*curr)->updateVisibility();
+ }
+}
+
+
+std::vector<Point> Obstacle::possiblePinPoints(unsigned int pinClassId) const
+{
+ std::vector<Point> points;
+ for (ShapeConnectionPinSet::const_iterator curr =
+ m_connection_pins.begin();
+ curr != m_connection_pins.end(); ++curr)
+ {
+ ShapeConnectionPin *currPin = *curr;
+ if ((currPin->m_class_id == pinClassId) &&
+ (!currPin->m_exclusive || currPin->m_connend_users.empty()))
+ {
+ points.push_back(currPin->m_vertex->point);
+ }
+ }
+ return points;
+}
+
+
+size_t Obstacle::addConnectionPin(ShapeConnectionPin *pin)
+{
+ m_connection_pins.insert(pin);
+ m_router->modifyConnectionPin(pin);
+
+ return m_connection_pins.size();
+}
+
+void Obstacle::removeConnectionPin(ShapeConnectionPin *pin)
+{
+ m_connection_pins.erase(pin);
+ m_router->modifyConnectionPin(pin);
+}
+
+
+bool Obstacle::isActive(void) const
+{
+ return m_active;
+}
+
+
+VertInf *Obstacle::firstVert(void)
+{
+ return m_first_vert;
+}
+
+
+VertInf *Obstacle::lastVert(void)
+{
+ return m_last_vert;
+}
+
+
+unsigned int Obstacle::id(void) const
+{
+ return m_id;
+}
+
+
+const Polygon& Obstacle::polygon(void) const
+{
+ return m_polygon;
+}
+
+
+Router *Obstacle::router(void) const
+{
+ return m_router;
+}
+
+
+Box Obstacle::routingBox(void) const
+{
+ COLA_ASSERT(!m_polygon.empty());
+ COLA_ASSERT(m_router);
+
+ double bufferSpace = m_router->routingParameter(shapeBufferDistance);
+ return m_polygon.offsetBoundingBox(bufferSpace);
+}
+
+
+Polygon Obstacle::routingPolygon(void) const
+{
+ COLA_ASSERT(!m_polygon.empty());
+ COLA_ASSERT(m_router);
+
+ double bufferSpace = m_router->routingParameter(shapeBufferDistance);
+ return m_polygon.offsetPolygon(bufferSpace);
+}
+
+
+Point Obstacle::shapeCentre(void)
+{
+ Box bb = routingBox();
+
+ Point centre;
+ centre.x = bb.min.x + (0.5 * (bb.max.x - bb.min.x));
+ centre.y = bb.min.y + (0.5 * (bb.max.y - bb.min.y));
+ return centre;
+}
+
+
+void Obstacle::removeFromGraph(void)
+{
+ bool isConnPt = false;
+ for (VertInf *iter = firstVert(); iter != lastVert()->lstNext; )
+ {
+ VertInf *tmp = iter;
+ iter = iter->lstNext;
+
+ tmp->removeFromGraph(isConnPt);
+ }
+}
+
+
+VertInf *Obstacle::getPointVertex(const Point& point)
+{
+ VertInf *curr = m_first_vert;
+ do
+ {
+ if (curr->point == point)
+ {
+ return curr;
+ }
+ curr = curr->shNext;
+ }
+ while (curr != m_first_vert);
+
+ return nullptr;
+}
+
+
+void Obstacle::addFollowingConnEnd(ConnEnd *connEnd)
+{
+ m_following_conns.insert(connEnd);
+}
+
+
+void Obstacle::removeFollowingConnEnd(ConnEnd *connEnd)
+{
+ m_following_conns.erase(connEnd);
+}
+
+
+ConnRefList Obstacle::attachedConnectors(void) const
+{
+ ConnRefList attachedConns;
+ for (std::set<ConnEnd *>::const_iterator curr = m_following_conns.begin();
+ curr != m_following_conns.end(); ++curr)
+ {
+ ConnEnd *connEnd = *curr;
+ COLA_ASSERT(connEnd->m_conn_ref != nullptr);
+ attachedConns.push_back(connEnd->m_conn_ref);
+ }
+ return attachedConns;
+}
+
+}
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/obstacle.h b/src/3rdparty/adaptagrams/libavoid/obstacle.h
new file mode 100644
index 0000000..12c5eca
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/obstacle.h
@@ -0,0 +1,150 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+//! @file obstacle.h
+//! @brief Contains the interface for the Obstacle class,
+//! the superclass for ShapeRef and JunctionRef.
+
+
+#ifndef AVOID_OBSTACLE_H
+#define AVOID_OBSTACLE_H
+
+#include <list>
+#include <set>
+
+#include <cstdio>
+
+#include "libavoid/geometry.h"
+#include "libavoid/connectionpin.h"
+
+
+namespace Avoid {
+
+class VertInf;
+class Router;
+class Obstacle;
+class ConnEnd;
+class ConnRef;
+typedef std::list<Obstacle *> ObstacleList;
+typedef std::list<ConnRef *> ConnRefList;
+
+
+// @brief The Obstacle class represents an obstacle that must be
+// routed around. Superclass of ShapeRef and JunctionRef.
+//
+class Obstacle
+{
+ public:
+ //! @brief Obstacle reference constructor.
+ //!
+ //! Creates an obstacle object reference. It is expected that you
+ //! would not instantiate an Obstacle directly, but would instead
+ //! use either ShapeRef() or JunctionRef().
+ //!
+ //! @param[in] router The router scene to place the shape into.
+ //! @param[in] poly A Polygon representing the boundary of the
+ //! shape.
+ //! @param[in] id A unique positive integer ID for the shape.
+ Obstacle(Router *router, Polygon poly, const unsigned int id = 0);
+
+// To prevent C++ objects from being destroyed in garbage collected languages
+// when the libraries are called from SWIG, we hide the declarations of the
+// destructors and prevent generation of default destructors.
+#ifndef SWIG
+ //! @brief Obstacle reference destructor.
+ //!
+ virtual ~Obstacle();
+#endif
+
+ //! @brief Returns the ID of this obstacle.
+ //! @returns The ID of the obstacle.
+ unsigned int id(void) const;
+ //! @brief Returns a reference to the polygon boundary of this
+ //! obstacle.
+ //! @returns A reference to the polygon boundary of the obstacle.
+ const Polygon& polygon(void) const;
+ //! @brief Returns a pointer to the router scene this obstacle
+ //! is in.
+ //! @returns A pointer to the router scene for this obstacle.
+ Router *router(void) const;
+ //! @brief Returns the position of this obstacle.
+ //! @returns A point representing the position of this obstacle.
+ virtual Point position(void) const = 0;
+
+ void setNewPoly(const Polygon& poly);
+ VertInf *firstVert(void);
+ VertInf *lastVert(void);
+ Box routingBox(void) const;
+ Polygon routingPolygon(void) const;
+ ConnRefList attachedConnectors(void) const;
+
+ private:
+ friend class Router;
+ friend class ConnEnd;
+ friend class ShapeConnectionPin;
+ friend class HyperedgeRerouter;
+ friend class HyperedgeImprover;
+ friend class MinimumTerminalSpanningTree;
+
+ // Defined in visibility.cpp:
+ void computeVisibilityNaive(void);
+ void computeVisibilitySweep(void);
+
+ virtual void outputCode(FILE *fp) const = 0;
+ void makeActive(void);
+ void makeInactive(void);
+ bool isActive(void) const;
+ void updatePinPolyLineVisibility(void);
+ void removeFromGraph(void);
+ Point shapeCentre(void);
+
+ VertInf *getPointVertex(const Point& point);
+
+ void addFollowingConnEnd(ConnEnd *connEnd);
+ void removeFollowingConnEnd(ConnEnd *connEnd);
+ size_t addConnectionPin(ShapeConnectionPin *pin);
+ void removeConnectionPin(ShapeConnectionPin *pin);
+ void assignPinVisibilityTo(const unsigned int pinClassId,
+ VertInf *dummyConnectionVert);
+ std::vector<Point> possiblePinPoints(unsigned int pinClassId) const;
+
+ protected:
+ Router *m_router;
+ unsigned int m_id;
+ Polygon m_polygon;
+ bool m_active;
+ ObstacleList::iterator m_router_obstacles_pos;
+ VertInf *m_first_vert;
+ VertInf *m_last_vert;
+ std::set<ConnEnd *> m_following_conns;
+ ShapeConnectionPinSet m_connection_pins;
+};
+
+
+}
+
+
+#endif
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/orthogonal.cpp b/src/3rdparty/adaptagrams/libavoid/orthogonal.cpp
new file mode 100644
index 0000000..f213955
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/orthogonal.cpp
@@ -0,0 +1,3259 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2009-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+
+#include <cstdlib>
+#include <cfloat>
+#include <cmath>
+#include <set>
+#include <list>
+#include <algorithm>
+
+#include "libavoid/router.h"
+#include "libavoid/geomtypes.h"
+#include "libavoid/shape.h"
+#include "libavoid/orthogonal.h"
+#include "libavoid/connend.h"
+#include "libavoid/connector.h"
+#include "libavoid/junction.h"
+#include "libavoid/vpsc.h"
+#include "libavoid/assertions.h"
+#include "libavoid/scanline.h"
+#include "libavoid/debughandler.h"
+
+// For debugging:
+//#define NUDGE_DEBUG
+//#define DEBUG_JUST_UNIFY
+
+
+namespace Avoid {
+
+
+// IDs:
+static const int freeSegmentID = 0;
+static const int fixedSegmentID = 1;
+static const int channelLeftID = 2;
+static const int channelRightID = 3;
+// Weights:
+static const double freeWeight = 0.00001;
+static const double strongWeight = 0.001;
+static const double strongerWeight = 1.0;
+static const double fixedWeight = 100000;
+
+
+// A pair of unsigned values that can be compared and used as the keys
+// for sets and maps.
+class UnsignedPair
+{
+ public:
+ UnsignedPair(unsigned ind1, unsigned ind2)
+ {
+ COLA_ASSERT(ind1 != ind2);
+ // Assign the lesser value to m_index1.
+ m_index1 = (ind1 < ind2) ? ind1 : ind2;
+ // Assign the greater value to m_index2.
+ m_index2 = (ind1 > ind2) ? ind1 : ind2;
+ }
+
+ bool operator<(const UnsignedPair& rhs) const
+ {
+ if (m_index1 != rhs.m_index1)
+ {
+ return m_index1 < rhs.m_index1;
+ }
+ return m_index2 < rhs.m_index2;
+ }
+ private:
+ unsigned short m_index1;
+ unsigned short m_index2;
+};
+typedef std::set<UnsignedPair> UnsignedPairSet;
+
+
+// Used to sort points when merging NudgingShiftSegments.
+// Sorts the indexes, by point position in one dimension.
+class CmpIndexes
+{
+ public:
+ CmpIndexes(ConnRef *conn, size_t dim)
+ : connRef(conn),
+ dimension(dim)
+ {
+ }
+ bool operator()(size_t lhs, size_t rhs)
+ {
+ return connRef->displayRoute().ps[lhs][dimension] <
+ connRef->displayRoute().ps[rhs][dimension];
+ }
+ private:
+ ConnRef *connRef;
+ size_t dimension;
+};
+
+
+class NudgingShiftSegment : public ShiftSegment
+{
+ public:
+ // For shiftable segments.
+ NudgingShiftSegment(ConnRef *conn, const size_t low, const size_t high,
+ bool isSBend, bool isZBend, const size_t dim, double minLim,
+ double maxLim)
+ : ShiftSegment(dim),
+ connRef(conn),
+ variable(nullptr),
+ fixed(false),
+ finalSegment(false),
+ endsInShape(false),
+ singleConnectedSegment(false),
+ sBend(isSBend),
+ zBend(isZBend)
+ {
+ indexes.push_back(low);
+ indexes.push_back(high);
+ minSpaceLimit = minLim;
+ maxSpaceLimit = maxLim;
+ }
+ // For fixed segments.
+ NudgingShiftSegment(ConnRef *conn, const size_t low, const size_t high,
+ const size_t dim)
+ : ShiftSegment(dim),
+ connRef(conn),
+ variable(nullptr),
+ fixed(true),
+ finalSegment(false),
+ endsInShape(false),
+ singleConnectedSegment(false),
+ sBend(false),
+ zBend(false)
+ {
+ indexes.push_back(low);
+ indexes.push_back(high);
+ // This has no space to shift.
+ minSpaceLimit = lowPoint()[dim];
+ maxSpaceLimit = lowPoint()[dim];
+ }
+ virtual ~NudgingShiftSegment()
+ {
+ }
+ Point& lowPoint(void)
+ {
+ return connRef->displayRoute().ps[indexes.front()];
+ }
+ Point& highPoint(void)
+ {
+ return connRef->displayRoute().ps[indexes.back()];
+ }
+ const Point& lowPoint(void) const
+ {
+ return connRef->displayRoute().ps[indexes.front()];
+ }
+ const Point& highPoint(void) const
+ {
+ return connRef->displayRoute().ps[indexes.back()];
+ }
+ double nudgeDistance(void) const
+ {
+ return connRef->router()->routingParameter(idealNudgingDistance);
+ }
+ bool immovable(void) const
+ {
+ return ! zigzag();
+ }
+ void createSolverVariable(const bool justUnifying)
+ {
+ bool nudgeFinalSegments = connRef->router()->routingOption(
+ nudgeOrthogonalSegmentsConnectedToShapes);
+ int varID = freeSegmentID;
+ double varPos = lowPoint()[dimension];
+ double weight = freeWeight;
+ if (nudgeFinalSegments && finalSegment)
+ {
+ weight = strongWeight;
+
+ if (singleConnectedSegment && !justUnifying)
+ {
+ // This is a single segment connector bridging
+ // two shapes. So, we want to try to keep it
+ // centred rather than shift it.
+ // Don't do this during Unifying stage, or else
+ // these connectors could end up at slightly
+ // different positions and get the wrong ordering
+ // for nudging.
+ weight = strongerWeight;
+ }
+ }
+ else if (checkpoints.size() > 0)
+ {
+ weight = strongWeight;
+ }
+ else if (zigzag())
+ {
+ COLA_ASSERT(minSpaceLimit > -CHANNEL_MAX);
+ COLA_ASSERT(maxSpaceLimit < CHANNEL_MAX);
+
+ // For zigzag bends, take the middle as ideal.
+ varPos = minSpaceLimit + ((maxSpaceLimit - minSpaceLimit) / 2);
+ }
+ else if (fixed)
+ {
+ // Fixed segments shouldn't get moved.
+ weight = fixedWeight;
+ varID = fixedSegmentID;
+ }
+ else if ( ! finalSegment )
+ {
+ // Set a higher weight for c-bends to stop them sometimes
+ // getting pushed out into channels by more-free connectors
+ // to the "inner" side of them.
+ weight = strongWeight;
+ }
+
+ variable = new Variable(varID, varPos, weight);
+ }
+
+ void updatePositionsFromSolver(const bool justUnifying)
+ {
+ if (fixed)
+ {
+ return;
+ }
+ double newPos = variable->finalPosition;
+
+ // The solver can sometimes cause variables to be outside their
+ // limits by a tiny amount, since all variables are held by
+ // weights. Thus, just make sure they stay in their limits.
+ newPos = std::max(newPos, minSpaceLimit);
+ newPos = std::min(newPos, maxSpaceLimit);
+
+#ifdef NUDGE_DEBUG
+ printf("Pos: %lX, %.16f\n", (long) connRef, newPos);
+#endif
+ for (size_t it = 0; it < indexes.size(); ++it)
+ {
+ size_t index = indexes[it];
+ connRef->displayRoute().ps[index][dimension] = newPos;
+ }
+
+#ifdef DEBUGHANDLER
+ if (!justUnifying && connRef->router()->debugHandler())
+ {
+ connRef->router()->debugHandler()->updateConnectorRoute(
+ connRef, indexes[0], indexes[indexes.size() - 1]);
+ }
+#endif
+ }
+ int fixedOrder(bool& isFixed) const
+ {
+ double nudgeDist = nudgeDistance();
+ double pos = lowPoint()[dimension];
+ bool minLimited = ((pos - minSpaceLimit) < nudgeDist);
+ bool maxLimited = ((maxSpaceLimit - pos) < nudgeDist);
+
+ if (fixed || (minLimited && maxLimited))
+ {
+ isFixed = true;
+ return 0;
+ }
+ else if (minLimited)
+ {
+ return 1;
+ }
+ else if (maxLimited)
+ {
+ return -1;
+ }
+ return 0;
+ }
+ int order(void) const
+ {
+ if (lowC())
+ {
+ return -1;
+ }
+ else if (highC())
+ {
+ return 1;
+ }
+ return 0;
+ }
+ bool zigzag(void) const
+ {
+ return sBend || zBend;
+ }
+ // This counts segments that are collinear and share an endpoint as
+ // overlapping. This allows them to be nudged apart where possible.
+ bool overlapsWith(const ShiftSegment *rhsSuper, const size_t dim) const
+ {
+ const NudgingShiftSegment *rhs =
+ static_cast<const NudgingShiftSegment *> (rhsSuper);
+ size_t altDim = (dim + 1) % 2;
+ const Point& lowPt = lowPoint();
+ const Point& highPt = highPoint();
+ const Point& rhsLowPt = rhs->lowPoint();
+ const Point& rhsHighPt = rhs->highPoint();
+ if ( (lowPt[altDim] < rhsHighPt[altDim]) &&
+ (rhsLowPt[altDim] < highPt[altDim]))
+ {
+ // The segments overlap.
+ if ( (minSpaceLimit <= rhs->maxSpaceLimit) &&
+ (rhs->minSpaceLimit <= maxSpaceLimit) )
+ {
+ return true;
+ }
+ }
+ else if ( (lowPt[altDim] == rhsHighPt[altDim]) ||
+ (rhsLowPt[altDim] == highPt[altDim]) )
+ {
+ bool nudgeColinearSegments = connRef->router()->routingOption(
+ nudgeOrthogonalTouchingColinearSegments);
+
+ if ( (minSpaceLimit <= rhs->maxSpaceLimit) &&
+ (rhs->minSpaceLimit <= maxSpaceLimit) )
+ {
+ // The segments could touch at one end.
+ if (connRef->router()->routingParameter(
+ fixedSharedPathPenalty) > 0)
+ {
+ // If we are routing with a fixedSharedPathPenalty
+ // then we don't want these segments to ever touch
+ // or slide past each other, so they are always
+ // considered to be overlapping.
+ return true;
+ }
+ else if ((rhs->sBend && sBend) || (rhs->zBend && zBend))
+ {
+ // Count them as overlapping for nudging if they
+ // are both s-bends or both z-bends, i.e., when
+ // the ordering would matter.
+ return nudgeColinearSegments;
+ }
+ else if ((rhs->finalSegment && finalSegment) &&
+ (rhs->connRef == connRef))
+ {
+ return nudgeColinearSegments;
+ }
+ }
+ }
+ return false;
+ }
+ // These segments are allowed to drift into alignment but don't have to.
+ bool canAlignWith(const NudgingShiftSegment *rhs,
+ const size_t dim) const
+ {
+ COLA_UNUSED(dim);
+
+ if (connRef != rhs->connRef)
+ {
+ return false;
+ }
+
+ // Don't allow segments of the same connector to drift together
+ // where one of them goes via a checkpoint. We want the path
+ // through the checkpoint to be maintained.
+ bool hasCheckpoints = checkpoints.size() > 0;
+ bool rhsHasCheckpoints = rhs->checkpoints.size() > 0;
+ if (hasCheckpoints || rhsHasCheckpoints)
+ {
+ return false;
+ }
+ return true;
+ }
+ // These segments should align with each other.
+ bool shouldAlignWith(const ShiftSegment *rhsSuper,
+ const size_t dim) const
+ {
+ const NudgingShiftSegment *rhs =
+ static_cast<const NudgingShiftSegment *> (rhsSuper);
+ if ((connRef == rhs->connRef) && finalSegment &&
+ rhs->finalSegment && overlapsWith(rhs, dim))
+ {
+ // If both the segments are in shapes then we know limits
+ // and can align. Otherwise we do this just for segments
+ // that are very close together, since these will often
+ // prevent nudging, or force it to have a tiny separation
+ // value.
+ if ((endsInShape && rhs->endsInShape) ||
+ (fabs(lowPoint()[dim] - rhs->lowPoint()[dim]) < 10))
+ {
+ return true;
+ }
+ }
+ else if ((connRef == rhs->connRef) &&
+ // Not both final
+ ((finalSegment & rhs->finalSegment) != true))
+ {
+ bool hasCheckpoints = checkpoints.size() > 0;
+ bool rhsHasCheckpoints = rhs->checkpoints.size() > 0;
+
+ if (hasCheckpoints != rhsHasCheckpoints)
+ {
+ // At least one segment has checkpoints, but not both.
+
+ size_t altDim = (dim + 1) % 2;
+ double space = fabs(lowPoint()[dim] - rhs->lowPoint()[dim]);
+ double touchPos;
+ bool couldTouch = false;
+ if (lowPoint()[altDim] == rhs->highPoint()[altDim])
+ {
+ couldTouch = true;
+ touchPos = lowPoint()[altDim];
+ }
+ else if (highPoint()[altDim] == rhs->lowPoint()[altDim])
+ {
+ couldTouch = true;
+ touchPos = highPoint()[altDim];
+ }
+
+ // We should align these so long as they are close
+ // together (<= 10) and there isn't a checkpoint at the
+ // touch point, i.e., we'd be altering the edges leading
+ // into the checkpoint. We want to keep these in place
+ // and opportunistically move other edges to align with
+ // them.
+ return couldTouch && (space <= 10) &&
+ !hasCheckpointAtPosition(touchPos, altDim) &&
+ !rhs->hasCheckpointAtPosition(touchPos, altDim);
+ }
+ }
+ return false;
+ }
+ // Used for merging segments with end segments that should appear as
+ // a single segment.
+ void mergeWith(const ShiftSegment *rhsSuper, const size_t dim)
+ {
+ // Adjust limits.
+ minSpaceLimit = std::max(minSpaceLimit, rhsSuper->minSpaceLimit);
+ maxSpaceLimit = std::min(maxSpaceLimit, rhsSuper->maxSpaceLimit);
+
+ // Find a new position for the segment, taking into account
+ // the two original positions and the combined limits.
+ double segmentPos = lowPoint()[dimension];
+ double segment2Pos = rhsSuper->lowPoint()[dimension];
+ if (segment2Pos < segmentPos)
+ {
+ segmentPos -= ((segmentPos - segment2Pos) / 2.0);
+ }
+ else if (segment2Pos > segmentPos)
+ {
+ segmentPos += ((segment2Pos - segmentPos) / 2.0);
+ }
+ segmentPos = std::max(minSpaceLimit, segmentPos);
+ segmentPos = std::min(maxSpaceLimit, segmentPos);
+
+ // Merge the index lists and sort the new list.
+ const NudgingShiftSegment *rhs =
+ static_cast<const NudgingShiftSegment *> (rhsSuper);
+ indexes.insert(indexes.end(), rhs->indexes.begin(), rhs->indexes.end());
+ size_t altDim = (dim + 1) % 2;
+ CmpIndexes compare(connRef, altDim);
+ sort(indexes.begin(), indexes.end(), compare);
+
+ // Apply the new positon to all points to keep them constant.
+ for (size_t it = 0; it < indexes.size(); ++it)
+ {
+ size_t index = indexes[it];
+ connRef->displayRoute().ps[index][dimension] = segmentPos;
+ }
+ }
+ bool hasCheckpointAtPosition(const double position,
+ const size_t dim) const
+ {
+ for (size_t cp = 0; cp < checkpoints.size(); ++cp)
+ {
+ if (checkpoints[cp][dim] == position)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ ConnRef *connRef;
+ Variable *variable;
+ std::vector<size_t> indexes;
+ bool fixed;
+ bool finalSegment;
+ bool endsInShape;
+ bool singleConnectedSegment;
+ std::vector<Point> checkpoints;
+ private:
+ bool sBend;
+ bool zBend;
+ bool lowC(void) const
+ {
+ // This is true if this is a cBend and its adjoining points
+ // are at lower positions.
+ if (!finalSegment && !zigzag() && !fixed &&
+ (minSpaceLimit == lowPoint()[dimension]))
+ {
+ return true;
+ }
+ return false;
+ }
+ bool highC(void) const
+ {
+ // This is true if this is a cBend and its adjoining points
+ // are at higher positions.
+ if (!finalSegment && !zigzag() && !fixed &&
+ (maxSpaceLimit == lowPoint()[dimension]))
+ {
+ return true;
+ }
+ return false;
+ }
+};
+
+
+
+enum ScanVisDirFlag {
+ VisDirNone = 0,
+ VisDirUp = 1,
+ VisDirDown = 2
+};
+typedef unsigned int ScanVisDirFlags;
+
+
+// Returns a bitfield of the directions of visibility in terms of the scanline
+// in a particular dimension dimension. It will return either ConnDirDown
+// (meaning visibility to lower position values) or ConnDirUp (for visibility
+// towards higher position values).
+//
+static ScanVisDirFlags getPosVertInfDirections(VertInf *v, size_t dim)
+{
+ if (dim == XDIM) // X-dimension
+ {
+ unsigned int dirs = v->visDirections & (ConnDirLeft | ConnDirRight);
+ if (dirs == (ConnDirLeft | ConnDirRight))
+ {
+ return (VisDirDown | VisDirUp);
+ }
+ else if (dirs == ConnDirLeft)
+ {
+ return VisDirDown;
+ }
+ else if (dirs == ConnDirRight)
+ {
+ return VisDirUp;
+ }
+ }
+ else if (dim == YDIM) // Y-dimension
+ {
+ unsigned int dirs = v->visDirections & (ConnDirDown | ConnDirUp);
+ if (dirs == (ConnDirDown | ConnDirUp))
+ {
+ return (VisDirDown | VisDirUp);
+ }
+ else if (dirs == ConnDirDown)
+ {
+ // libavoid's Y-axis points downwards, so where the user has
+ // specified visibility downwards, this results in visibility to
+ // higher scanline positition values.
+ return VisDirUp;
+ }
+ else if (dirs == ConnDirUp)
+ {
+ // libavoid's Y-axis points downwards, so where the user has
+ // specified visibility upwards, this results in visibility to
+ // lower scanline positition values.
+ return VisDirDown;
+ }
+ }
+
+ // Can occur for ConnDirNone visibility.
+ return VisDirNone;
+}
+
+
+struct PosVertInf
+{
+ PosVertInf(double p, VertInf *vI, ScanVisDirFlags d = VisDirNone)
+ : pos(p),
+ vert(vI),
+ dirs(d)
+ {
+ }
+
+ bool operator<(const PosVertInf& rhs) const
+ {
+ if (pos != rhs.pos)
+ {
+ return pos < rhs.pos;
+ }
+ if ((vert->id == rhs.vert->id) && (vert->id == dummyOrthogID))
+ {
+ // Multiple dummy nodes can get placed at the same point for
+ // multiple ShapeConnectionPins on junctions (outside of shapes).
+ // We only need one at each position, so multiples can be seen
+ // as equal here.
+ return false;
+ }
+ if (vert->id != rhs.vert->id)
+ {
+ return vert->id < rhs.vert->id;
+ }
+ return dirs < rhs.dirs;
+ }
+
+ double pos;
+ VertInf *vert;
+
+ // A bitfield marking the direction of visibility (in this dimension)
+ // made up of VisDirDown (for visibility towards lower position values)
+ // and VisDirUp (for visibility towards higher position values).
+ //
+ ScanVisDirFlags dirs;
+};
+
+
+struct CmpVertInf
+{
+ bool operator()(const VertInf* u, const VertInf* v) const
+ {
+ // Comparator for VertSet, an ordered set of VertInf pointers.
+ // It is assumed vertical sets of points will all have the same
+ // x position and horizontal sets all share a y position, so this
+ // method can be used to sort both these sets.
+ COLA_ASSERT((u->point.x == v->point.x) || (u->point.y == v->point.y));
+ if (u->point.x != v->point.x)
+ {
+ return u->point.x < v->point.x;
+ }
+ else if (u->point.y != v->point.y)
+ {
+ return u->point.y < v->point.y;
+ }
+ return u < v;
+ }
+};
+
+
+typedef std::set<VertInf *, CmpVertInf> VertSet;
+
+// A set of points to break the line segment,
+// along with vertices for these points.
+typedef std::set<PosVertInf> BreakpointSet;
+
+// Temporary structure used to store the possible horizontal visibility
+// lines arising from the vertical sweep.
+class LineSegment
+{
+public:
+ LineSegment(const double& b, const double& f, const double& p,
+ bool ss = false, VertInf *bvi = nullptr, VertInf *fvi = nullptr)
+ : begin(b),
+ finish(f),
+ pos(p),
+ shapeSide(ss)
+ {
+ COLA_ASSERT(begin < finish);
+
+ if (bvi)
+ {
+ vertInfs.insert(bvi);
+ }
+ if (fvi)
+ {
+ vertInfs.insert(fvi);
+ }
+ }
+ LineSegment(const double& bf, const double& p, VertInf *bfvi = nullptr)
+ : begin(bf),
+ finish(bf),
+ pos(p),
+ shapeSide(false)
+ {
+ if (bfvi)
+ {
+ vertInfs.insert(bfvi);
+ }
+ }
+
+ // Order by begin, pos, finish.
+ bool operator<(const LineSegment& rhs) const
+ {
+ if (begin != rhs.begin)
+ {
+ return begin < rhs.begin;
+ }
+ if (pos != rhs.pos)
+ {
+ return pos < rhs.pos;
+ }
+ if (finish != rhs.finish)
+ {
+ return finish < rhs.finish;
+ }
+ COLA_ASSERT(shapeSide == rhs.shapeSide);
+ return false;
+ }
+
+ bool overlaps(const LineSegment& rhs) const
+ {
+ if ((begin == rhs.begin) && (pos == rhs.pos) &&
+ (finish == rhs.finish))
+ {
+ // Lines are exactly equal.
+ return true;
+ }
+
+ if (pos == rhs.pos)
+ {
+ if (((begin >= rhs.begin) && (begin <= rhs.finish)) ||
+ ((rhs.begin >= begin) && (rhs.begin <= finish)) )
+ {
+ // They are colinear and overlap by some amount.
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void mergeVertInfs(const LineSegment& segment)
+ {
+ begin = std::min(begin, segment.begin);
+ finish = std::max(finish, segment.finish);
+ vertInfs.insert(segment.vertInfs.begin(), segment.vertInfs.end());
+ }
+
+ VertInf *beginVertInf(void) const
+ {
+ if (vertInfs.empty())
+ {
+ return nullptr;
+ }
+ VertInf *inf = *vertInfs.begin();
+ if ( ((inf->point.y == begin) && (inf->point.x == pos)) ||
+ ((inf->point.x == begin) && (inf->point.y == pos)) )
+ {
+ // Only return the point if it is actually at the begin pos.
+ return inf;
+ }
+ return nullptr;
+ }
+ VertInf *finishVertInf(void) const
+ {
+ if (vertInfs.empty())
+ {
+ return nullptr;
+ }
+ VertInf *inf = *vertInfs.rbegin();
+ if ( ((inf->point.y == finish) && (inf->point.x == pos)) ||
+ ((inf->point.x == finish) && (inf->point.y == pos)) )
+ {
+ // Only return the point if it is actually at the finish pos.
+ return inf;
+ }
+ return nullptr;
+ }
+
+ VertInf *commitPositionX(Router *router, double posX)
+ {
+ VertInf *found = nullptr;
+ for (VertSet::iterator v = vertInfs.begin();
+ v != vertInfs.end(); ++v)
+ {
+ if ((*v)->point.x == posX)
+ {
+ found = *v;
+ break;
+ }
+ }
+ if (!found)
+ {
+ found = new VertInf(router, dummyOrthogID, Point(posX, pos));
+ vertInfs.insert(found);
+ }
+ return found;
+ }
+ // Set begin endpoint vertex if none has been assigned.
+ void horiCommitBegin(Router *router, VertInf *vert = nullptr)
+ {
+ if (vert)
+ {
+ vertInfs.insert(vert);
+ }
+
+ if (vertInfs.empty() ||
+ ((*vertInfs.begin())->point.x != begin))
+ {
+ if (begin != -DBL_MAX)
+ {
+ vertInfs.insert(new
+ VertInf(router, dummyOrthogID, Point(begin, pos)));
+ }
+ }
+ }
+
+ // Set begin endpoint vertex if none has been assigned.
+ void horiCommitFinish(Router *router, VertInf *vert = nullptr)
+ {
+ if (vert)
+ {
+ vertInfs.insert(vert);
+ }
+
+ if (vertInfs.empty() ||
+ ((*vertInfs.rbegin())->point.x != finish))
+ {
+ if (finish != DBL_MAX)
+ {
+ vertInfs.insert(new
+ VertInf(router, dummyOrthogID, Point(finish, pos)));
+ }
+ }
+ }
+
+ // Converts a section of the points list to a set of breakPoints.
+ // Returns the first of the intersection points occurring at finishPos.
+ VertSet::iterator addSegmentsUpTo(double finishPos)
+ {
+ VertSet::iterator firstIntersectionPt = vertInfs.end();
+ for (VertSet::iterator vert = vertInfs.begin();
+ vert != vertInfs.end(); ++vert)
+ {
+ if ((*vert)->point.x > finishPos)
+ {
+ // We're done.
+ break;
+ }
+
+ breakPoints.insert(PosVertInf((*vert)->point.x, (*vert),
+ getPosVertInfDirections(*vert, XDIM)));
+
+ if ((firstIntersectionPt == vertInfs.end()) &&
+ ((*vert)->point.x == finishPos))
+ {
+ firstIntersectionPt = vert;
+ }
+ }
+ // Returns the first of the intersection points at finishPos.
+ return firstIntersectionPt;
+ }
+
+ // Add visibility edge(s) for this segment. There may be multiple if
+ // one of the endpoints is shared by multiple connector endpoints.
+ void addEdgeHorizontal(Router *router)
+ {
+ horiCommitBegin(router);
+ horiCommitFinish(router);
+
+ addSegmentsUpTo(finish);
+ }
+
+ // Set flags to show what can be passed on this visibility line.
+ // This can be used later to disregard some edges in the visibility
+ // graph when routing particular connectors.
+ void setLongRangeVisibilityFlags(size_t dim)
+ {
+ // First, travel in one direction
+ bool seenConnPt = false;
+ bool seenShapeEdge = false;
+ for (BreakpointSet::iterator nvert = breakPoints.begin();
+ nvert != breakPoints.end(); ++nvert)
+ {
+ VertIDProps mask = 0;
+ if (dim == XDIM)
+ {
+ if (seenConnPt)
+ {
+ mask |= XL_CONN;
+ }
+ if (seenShapeEdge)
+ {
+ mask |= XL_EDGE;
+ }
+ }
+ else // if (dim == YDIM)
+ {
+ if (seenConnPt)
+ {
+ mask |= YL_CONN;
+ }
+ if (seenShapeEdge)
+ {
+ mask |= YL_EDGE;
+ }
+ }
+ nvert->vert->orthogVisPropFlags |= mask;
+
+ if (nvert->vert->id.isConnPt())
+ {
+ seenConnPt = true;
+ }
+ if (nvert->vert->id.isOrthShapeEdge())
+ {
+ seenShapeEdge = true;
+ }
+ }
+ // Then in the other direction
+ seenConnPt = false;
+ seenShapeEdge = false;
+ for (BreakpointSet::reverse_iterator rvert = breakPoints.rbegin();
+ rvert != breakPoints.rend(); ++rvert)
+ {
+ VertIDProps mask = 0;
+ if (dim == XDIM)
+ {
+ if (seenConnPt)
+ {
+ mask |= XH_CONN;
+ }
+ if (seenShapeEdge)
+ {
+ mask |= XH_EDGE;
+ }
+ }
+ else // if (dim == YDIM)
+ {
+ if (seenConnPt)
+ {
+ mask |= YH_CONN;
+ }
+ if (seenShapeEdge)
+ {
+ mask |= YH_EDGE;
+ }
+ }
+ rvert->vert->orthogVisPropFlags |= mask;
+
+ if (rvert->vert->id.isConnPt())
+ {
+ seenConnPt = true;
+ }
+ if (rvert->vert->id.isOrthShapeEdge())
+ {
+ seenShapeEdge = true;
+ }
+ }
+ }
+
+ // Add visibility edge(s) for this segment up until an intersection.
+ // Then, move the segment beginning to the intersection point, so we
+ // later only consider the remainder of the segment.
+ // There may be multiple segments added to the graph if the beginning
+ // endpoint of the segment is shared by multiple connector endpoints.
+ VertSet addEdgeHorizontalTillIntersection(Router *router,
+ LineSegment& vertLine)
+ {
+ VertSet intersectionSet;
+
+ horiCommitBegin(router);
+
+ // Does a vertex already exist for this point.
+ commitPositionX(router, vertLine.pos);
+
+ // Generate segments and set end iterator to the first point
+ // at the intersection position.
+ VertSet::iterator restBegin = addSegmentsUpTo(vertLine.pos);
+
+ // Add the intersections points to intersectionSet.
+ VertSet::iterator restEnd = restBegin;
+ while ((restEnd != vertInfs.end()) &&
+ (*restEnd)->point.x == vertLine.pos)
+ {
+ ++restEnd;
+ }
+ intersectionSet.insert(restBegin, restEnd);
+
+ // Adjust segment to remove processed portion.
+ begin = vertLine.pos;
+ vertInfs.erase(vertInfs.begin(), restBegin);
+
+ return intersectionSet;
+ }
+
+ // Insert vertical breakpoints.
+ void insertBreakpointsBegin(Router *router, LineSegment& vertLine)
+ {
+ VertInf *vert = nullptr;
+ if (pos == vertLine.begin && vertLine.beginVertInf())
+ {
+ vert = vertLine.beginVertInf();
+ }
+ else if (pos == vertLine.finish && vertLine.finishVertInf())
+ {
+ vert = vertLine.finishVertInf();
+ }
+ horiCommitBegin(router, vert);
+
+ for (VertSet::iterator v = vertInfs.begin();
+ v != vertInfs.end(); ++v)
+ {
+ if ((*v)->point.x == begin)
+ {
+ vertLine.breakPoints.insert(PosVertInf(pos, *v,
+ getPosVertInfDirections(*v, YDIM)));
+ }
+ }
+ }
+
+ // Insert vertical breakpoints.
+ void insertBreakpointsFinish(Router *router, LineSegment& vertLine)
+ {
+ VertInf *vert = nullptr;
+ if (pos == vertLine.begin && vertLine.beginVertInf())
+ {
+ vert = vertLine.beginVertInf();
+ }
+ else if (pos == vertLine.finish && vertLine.finishVertInf())
+ {
+ vert = vertLine.finishVertInf();
+ }
+ horiCommitFinish(router, vert);
+
+ for (VertSet::iterator v = vertInfs.begin();
+ v != vertInfs.end(); ++v)
+ {
+ if ((*v)->point.x == finish)
+ {
+ vertLine.breakPoints.insert(PosVertInf(pos, *v,
+ getPosVertInfDirections(*v, YDIM)));
+ }
+ }
+ }
+ void generateVisibilityEdgesFromBreakpointSet(Router *router, size_t dim)
+ {
+ if (breakPoints.empty() || ((breakPoints.begin())->pos > begin))
+ {
+ // Add a begin point if there was not already an intersection
+ // found at that point. Though, don't do this if the line
+ // segment goes off to infinity -- we can't reach anything
+ // by going in that direction!
+ if (begin == -DBL_MAX)
+ {
+ // Shorten line to first intersection point.
+ COLA_ASSERT(!breakPoints.empty());
+ begin = breakPoints.begin()->pos;
+ }
+ else
+ {
+ // Add begin point.
+ Point point(pos, pos);
+ point[dim] = begin;
+ VertInf *vert = new VertInf(router, dummyOrthogID, point);
+ breakPoints.insert(PosVertInf(begin, vert));
+ }
+ }
+ if (breakPoints.empty() || ((breakPoints.rbegin())->pos < finish))
+ {
+ // Add a finish point if there was not already an intersection
+ // found at that point. Though, don't do this if the line
+ // segment goes off to infinity -- we can't reach anything
+ // by going in that direction!
+ if (finish == DBL_MAX)
+ {
+ // Shorten line to last intersection point.
+ finish = breakPoints.rbegin()->pos;
+ }
+ else
+ {
+ // Add finish point.
+ Point point(pos, pos);
+ point[dim] = finish;
+ VertInf *vert = new VertInf(router, dummyOrthogID, point);
+ breakPoints.insert(PosVertInf(finish, vert));
+ }
+ }
+
+ // Set flags for orthogonal routing optimisation.
+ setLongRangeVisibilityFlags(dim);
+
+ const bool orthogonal = true;
+ BreakpointSet::iterator vert, last;
+#if 0
+ last = breakPoints.end();
+ for (vert = breakPoints.begin(); vert != breakPoints.end();)
+ {
+ if (vert->vert->id == dummyOrthogID)
+ {
+ if (last == breakPoints.end() ||
+ (last->vert->point != vert->vert->point))
+ {
+ last = vert;
+ }
+ else
+ {
+ // Already seen a dummy orthogonal point at this
+ // position, delete it.
+
+ }
+ else
+ {
+ ++vert;
+ }
+ }
+#endif
+ for (vert = last = breakPoints.begin(); vert != breakPoints.end();)
+ {
+ BreakpointSet::iterator firstPrev = last;
+ while (last->vert->point[dim] != vert->vert->point[dim])
+ {
+ COLA_ASSERT(vert != last);
+ // Assert points are not at the same position.
+ COLA_ASSERT(vert->vert->point != last->vert->point);
+
+ if (vert->vert->id.isConnPt() && last->vert->id.isConnPt())
+ {
+ // Here we have a pair of two endpoints that are both
+ // connector endpoints and both are inside a shape.
+
+ // Give vert visibility back to the first non-connector
+ // endpoint vertex (i.e., the side of the shape).
+ BreakpointSet::iterator side = last;
+ while (side->vert->id.isConnPt())
+ {
+ if (side == breakPoints.begin())
+ {
+ break;
+ }
+ --side;
+ }
+ bool canSeeDown = (vert->dirs & VisDirDown);
+ if (canSeeDown && !(side->vert->id.isConnPt()))
+ {
+ EdgeInf *edge = new
+ EdgeInf(side->vert, vert->vert, orthogonal);
+ edge->setDist(vert->vert->point[dim] -
+ side->vert->point[dim]);
+ }
+
+ // Give last visibility back to the first non-connector
+ // endpoint vertex (i.e., the side of the shape).
+ side = vert;
+ while ((side != breakPoints.end()) &&
+ side->vert->id.isConnPt())
+ {
+ ++side;
+ }
+ bool canSeeUp = (last->dirs & VisDirUp);
+ if (canSeeUp && (side != breakPoints.end()))
+ {
+ EdgeInf *edge = new
+ EdgeInf(last->vert, side->vert, orthogonal);
+ edge->setDist(side->vert->point[dim] -
+ last->vert->point[dim]);
+ }
+ }
+
+ // The normal case.
+ //
+ // Note: It's okay to give two connector endpoints visibility
+ // here since we only consider the partner endpoint as a
+ // candidate while searching if it is the other endpoint of
+ // the connector in question.
+ //
+ bool generateEdge = true;
+ if (last->vert->id.isConnPt() && !(last->dirs & VisDirUp))
+ {
+ // Don't generate the visibility segment if the ConnEnd
+ // doesn't have visibility in that direction.
+ generateEdge = false;
+ }
+ else if (vert->vert->id.isConnPt() && !(vert->dirs & VisDirDown))
+ {
+ // Don't generate the visibility segment if the ConnEnd
+ // doesn't have visibility in that direction.
+ generateEdge = false;
+ }
+ if (generateEdge)
+ {
+ EdgeInf *edge =
+ new EdgeInf(last->vert, vert->vert, orthogonal);
+ edge->setDist(vert->vert->point[dim] -
+ last->vert->point[dim]);
+ }
+
+ ++last;
+ }
+
+ ++vert;
+
+ if ((vert != breakPoints.end()) &&
+ (last->vert->point[dim] == vert->vert->point[dim]))
+ {
+ // Still looking at same pair, just reset prev number pointer.
+ last = firstPrev;
+ }
+ else
+ {
+ // vert has moved to the beginning of a group at a new
+ // position. Last is now in the right place, so do nothing.
+ }
+ }
+ }
+
+ double begin;
+ double finish;
+ double pos;
+
+ // XXX shapeSide is unused and could possibly be removed?
+ bool shapeSide;
+
+ VertSet vertInfs;
+ BreakpointSet breakPoints;
+private:
+ // MSVC wants to generate the assignment operator and the default
+ // constructor, but fails. Therefore we declare them private and
+ // don't implement them.
+ LineSegment & operator=(LineSegment const &);
+ LineSegment();
+};
+
+typedef std::list<LineSegment> SegmentList;
+
+class SegmentListWrapper
+{
+ public:
+ LineSegment *insert(LineSegment segment)
+ {
+ SegmentList::iterator found = _list.end();
+ for (SegmentList::iterator curr = _list.begin();
+ curr != _list.end(); ++curr)
+ {
+ if (curr->overlaps(segment))
+ {
+ if (found != _list.end())
+ {
+ // This is not the first segment that overlaps,
+ // so we need to merge and then delete an existing
+ // segment.
+ curr->mergeVertInfs(*found);
+ _list.erase(found);
+ found = curr;
+ }
+ else
+ {
+ // This is the first overlapping segment, so just
+ // merge the new segment with this one.
+ curr->mergeVertInfs(segment);
+ found = curr;
+ }
+ }
+ }
+
+ if (found == _list.end())
+ {
+ // Add this line.
+ _list.push_back(segment);
+ return &(_list.back());
+ }
+
+ return &(*found);
+ }
+ SegmentList& list(void)
+ {
+ return _list;
+ }
+ private:
+ SegmentList _list;
+};
+
+
+// Given a router instance and a set of possible horizontal segments, and a
+// possible vertical visibility segment, compute and add edges to the
+// orthogonal visibility graph for all the visibility edges.
+static void intersectSegments(Router *router, SegmentList& segments,
+ LineSegment& vertLine)
+{
+ // XXX: It seems that this case can sometimes occur... maybe when
+ // there are many overlapping rectangles.
+ //COLA_ASSERT(vertLine.beginVertInf() == nullptr);
+ //COLA_ASSERT(vertLine.finishVertInf() == nullptr);
+
+ COLA_ASSERT(!segments.empty());
+ for (SegmentList::iterator it = segments.begin(); it != segments.end(); )
+ {
+ LineSegment& horiLine = *it;
+
+ bool inVertSegRegion = ((vertLine.begin <= horiLine.pos) &&
+ (vertLine.finish >= horiLine.pos));
+
+ if (vertLine.pos < horiLine.begin)
+ {
+ // We've yet to reach this segment in the sweep, so ignore.
+ ++it;
+ continue;
+ }
+ else if (vertLine.pos == horiLine.begin)
+ {
+ if (inVertSegRegion)
+ {
+ horiLine.insertBreakpointsBegin(router, vertLine);
+ }
+ }
+ else if (vertLine.pos == horiLine.finish)
+ {
+ if (inVertSegRegion)
+ {
+ // Add horizontal visibility segment.
+ horiLine.addEdgeHorizontal(router);
+
+ horiLine.insertBreakpointsFinish(router, vertLine);
+
+ size_t dim = XDIM; // x-dimension
+ horiLine.generateVisibilityEdgesFromBreakpointSet(router, dim);
+
+ // And we've now finished with the segment, so delete.
+ it = segments.erase(it);
+ continue;
+ }
+ }
+ else if (vertLine.pos > horiLine.finish)
+ {
+ // Add horizontal visibility segment.
+ horiLine.addEdgeHorizontal(router);
+
+ size_t dim = XDIM; // x-dimension
+ horiLine.generateVisibilityEdgesFromBreakpointSet(router, dim);
+
+ // We've now swept past this horizontal segment, so delete.
+ it = segments.erase(it);
+ continue;
+ }
+ else
+ {
+ COLA_ASSERT(vertLine.pos > horiLine.begin);
+ COLA_ASSERT(vertLine.pos < horiLine.finish);
+
+ if (inVertSegRegion)
+ {
+ // Add horizontal visibility segment.
+ VertSet intersectionVerts =
+ horiLine.addEdgeHorizontalTillIntersection(
+ router, vertLine);
+
+ for (VertSet::iterator v = intersectionVerts.begin();
+ v != intersectionVerts.end(); ++v)
+ {
+ vertLine.breakPoints.insert(PosVertInf(horiLine.pos, *v,
+ getPosVertInfDirections(*v, YDIM)));
+ }
+ }
+ }
+ ++it;
+ }
+
+ // Split breakPoints set into visibility segments.
+ size_t dimension = YDIM; // y-dimension
+ vertLine.generateVisibilityEdgesFromBreakpointSet(router, dimension);
+}
+
+
+// Processes an event for the vertical sweep used for computing the static
+// orthogonal visibility graph. This adds possible horizontal visibility
+// segments to the segments list.
+// The first pass is adding the event to the scanline, the second is for
+// processing the event and the third for removing it from the scanline.
+static void processEventVert(Router *router, NodeSet& scanline,
+ SegmentListWrapper& segments, Event *e, unsigned int pass)
+{
+ Node *v = e->v;
+
+ if ( ((pass == 1) && (e->type == Open)) ||
+ ((pass == 2) && (e->type == ConnPoint)) )
+ {
+ std::pair<NodeSet::iterator, bool> result = scanline.insert(v);
+ v->iter = result.first;
+ COLA_ASSERT(result.second);
+
+ NodeSet::iterator it = v->iter;
+ // Work out neighbours
+ if (it != scanline.begin())
+ {
+ Node *u = *(--it);
+ v->firstAbove = u;
+ u->firstBelow = v;
+ }
+ it = v->iter;
+ if (++it != scanline.end())
+ {
+ Node *u = *it;
+ v->firstBelow = u;
+ u->firstAbove = v;
+ }
+ }
+
+ if (pass == 2)
+ {
+ if ((e->type == Open) || (e->type == Close))
+ {
+ // Only difference between Open and Close is whether the line
+ // segments are at the top or bottom of the shape. Decide here.
+ double lineY = (e->type == Open) ? v->min[YDIM] : v->max[YDIM];
+
+ // Shape edge positions.
+ double minShape = v->min[XDIM];
+ double maxShape = v->max[XDIM];
+ // As far as we can see.
+ double minLimit, maxLimit;
+ double minLimitMax, maxLimitMin;
+ v->findFirstPointAboveAndBelow(XDIM, lineY, minLimit, maxLimit,
+ minLimitMax, maxLimitMin);
+
+ // Insert possible visibility segments.
+ if (minLimitMax >= maxLimitMin)
+ {
+ // These vertices represent the shape corners.
+ VertInf *vI1 = new VertInf(router, dummyOrthogShapeID,
+ Point(minShape, lineY));
+ VertInf *vI2 = new VertInf(router, dummyOrthogShapeID,
+ Point(maxShape, lineY));
+
+ // There are no overlapping shapes, so give full visibility.
+ if (minLimit < minShape)
+ {
+ segments.insert(LineSegment(minLimit, minShape, lineY,
+ true, nullptr, vI1));
+ }
+ segments.insert(LineSegment(minShape, maxShape, lineY,
+ true, vI1, vI2));
+ if (maxShape < maxLimit)
+ {
+ segments.insert(LineSegment(maxShape, maxLimit, lineY,
+ true, vI2, nullptr));
+ }
+ }
+ else
+ {
+ // There are overlapping shapes along this shape edge.
+
+ if ((minLimitMax > minLimit) && (minLimitMax >= minShape))
+ {
+ LineSegment *line = segments.insert(
+ LineSegment(minLimit, minLimitMax, lineY, true));
+ // Shape corner:
+ VertInf *vI1 = new VertInf(router, dummyOrthogShapeID,
+ Point(minShape, lineY));
+ line->vertInfs.insert(vI1);
+ }
+ if ((maxLimitMin < maxLimit) && (maxLimitMin <= maxShape))
+ {
+ LineSegment *line = segments.insert(
+ LineSegment(maxLimitMin, maxLimit, lineY, true));
+ // Shape corner:
+ VertInf *vI2 = new VertInf(router, dummyOrthogShapeID,
+ Point(maxShape, lineY));
+ line->vertInfs.insert(vI2);
+ }
+ }
+ }
+ else if (e->type == ConnPoint)
+ {
+ // Connection point.
+ VertInf *centreVert = e->v->c;
+ Point& cp = centreVert->point;
+
+ // As far as we can see.
+ double minLimit = v->firstPointAbove(XDIM);
+ double maxLimit = v->firstPointBelow(XDIM);
+ bool inShape = v->isInsideShape(XDIM);
+
+ // Insert if we have visibility in that direction and the segment
+ // length is greater than zero.
+ LineSegment *line1 = nullptr, *line2 = nullptr;
+ if ((centreVert->visDirections & ConnDirLeft) && (minLimit < cp.x))
+ {
+ line1 = segments.insert(LineSegment(minLimit, cp.x, e->pos,
+ true, nullptr, centreVert));
+ }
+ if ((centreVert->visDirections & ConnDirRight) && (cp.x < maxLimit))
+ {
+ line2 = segments.insert(LineSegment(cp.x, maxLimit, e->pos,
+ true, centreVert, nullptr));
+ // If there was a line1, then we just merged with it, so
+ // that pointer will be invalid (and now unnecessary).
+ line1 = nullptr;
+ }
+ if (!line1 && !line2)
+ {
+ // Add a point segment for the centre point.
+ segments.insert(LineSegment(cp.x, e->pos, centreVert));
+ }
+
+ if (!inShape)
+ {
+ // This is not contained within a shape so add a normal
+ // visibility graph point here too (since paths won't route
+ // *through* connector endpoint vertices).
+ if (line1 || line2)
+ {
+ VertInf *cent = new VertInf(router, dummyOrthogID, cp);
+ if (line1)
+ {
+ line1->vertInfs.insert(cent);
+ }
+ if (line2)
+ {
+ line2->vertInfs.insert(cent);
+ }
+ }
+ }
+ }
+ }
+
+ if ( ((pass == 3) && (e->type == Close)) ||
+ ((pass == 2) && (e->type == ConnPoint)) )
+ {
+ // Clean up neighbour pointers.
+ Node *l = v->firstAbove, *r = v->firstBelow;
+ if (l != nullptr)
+ {
+ l->firstBelow = v->firstBelow;
+ }
+ if (r != nullptr)
+ {
+ r->firstAbove = v->firstAbove;
+ }
+
+ if (e->type == ConnPoint)
+ {
+ scanline.erase(v->iter);
+ delete v;
+ }
+ else // if (e->type == Close)
+ {
+ size_t result;
+ result = scanline.erase(v);
+ COLA_ASSERT(result == 1);
+ COLA_UNUSED(result); // Avoid warning.
+ delete v;
+ }
+ }
+}
+
+
+// Processes an event for the vertical sweep used for computing the static
+// orthogonal visibility graph. This adds possible vertical visibility
+// segments to the segments list.
+// The first pass is adding the event to the scanline, the second is for
+// processing the event and the third for removing it from the scanline.
+static void processEventHori(Router *router, NodeSet& scanline,
+ SegmentListWrapper& segments, Event *e, unsigned int pass)
+{
+ Node *v = e->v;
+
+ if ( ((pass == 1) && (e->type == Open)) ||
+ ((pass == 2) && (e->type == ConnPoint)) )
+ {
+ std::pair<NodeSet::iterator, bool> result = scanline.insert(v);
+ v->iter = result.first;
+ COLA_ASSERT(result.second);
+
+ NodeSet::iterator it = v->iter;
+ // Work out neighbours
+ if (it != scanline.begin())
+ {
+ Node *u = *(--it);
+ v->firstAbove = u;
+ u->firstBelow = v;
+ }
+ it = v->iter;
+ if (++it != scanline.end())
+ {
+ Node *u = *it;
+ v->firstBelow = u;
+ u->firstAbove = v;
+ }
+ }
+
+ if (pass == 2)
+ {
+ if ((e->type == Open) || (e->type == Close))
+ {
+ // Only difference between Open and Close is whether the line
+ // segments are at the left or right of the shape. Decide here.
+ double lineX = (e->type == Open) ? v->min[XDIM] : v->max[XDIM];
+
+ // Shape edge positions.
+ double minShape = v->min[YDIM];
+ double maxShape = v->max[YDIM];
+ // As far as we can see.
+ double minLimit, maxLimit;
+ double minLimitMax, maxLimitMin;
+ v->findFirstPointAboveAndBelow(YDIM, lineX, minLimit, maxLimit,
+ minLimitMax, maxLimitMin);
+
+ if (minLimitMax >= maxLimitMin)
+ {
+ LineSegment *line = segments.insert(
+ LineSegment(minLimit, maxLimit, lineX));
+
+ // Shape corners:
+ VertInf *vI1 = new VertInf(router, dummyOrthogShapeID,
+ Point(lineX, minShape));
+ VertInf *vI2 = new VertInf(router, dummyOrthogShapeID,
+ Point(lineX, maxShape));
+ line->vertInfs.insert(vI1);
+ line->vertInfs.insert(vI2);
+ }
+ else
+ {
+ if ((minLimitMax > minLimit) && (minLimitMax >= minShape))
+ {
+ LineSegment *line = segments.insert(
+ LineSegment(minLimit, minLimitMax, lineX));
+
+ // Shape corner:
+ VertInf *vI1 = new VertInf(router, dummyOrthogShapeID,
+ Point(lineX, minShape));
+ line->vertInfs.insert(vI1);
+ }
+ if ((maxLimitMin < maxLimit) && (maxLimitMin <= maxShape))
+ {
+ LineSegment *line = segments.insert(
+ LineSegment(maxLimitMin, maxLimit, lineX));
+
+ // Shape corner:
+ VertInf *vI2 = new VertInf(router, dummyOrthogShapeID,
+ Point(lineX, maxShape));
+ line->vertInfs.insert(vI2);
+ }
+ }
+ }
+ else if (e->type == ConnPoint)
+ {
+ // Connection point.
+ VertInf *centreVert = e->v->c;
+ Point& cp = centreVert->point;
+
+ // As far as we can see.
+ double minLimit = v->firstPointAbove(YDIM);
+ double maxLimit = v->firstPointBelow(YDIM);
+
+ // Insert if we have visibility in that direction and the segment
+ // length is greater than zero.
+ if ((centreVert->visDirections & ConnDirUp) && (minLimit < cp.y))
+ {
+ segments.insert(LineSegment(minLimit, cp.y, e->pos));
+ }
+
+ if ((centreVert->visDirections & ConnDirDown) && (cp.y < maxLimit))
+ {
+ segments.insert(LineSegment(cp.y, maxLimit, e->pos));
+ }
+ }
+ }
+
+ if ( ((pass == 3) && (e->type == Close)) ||
+ ((pass == 2) && (e->type == ConnPoint)) )
+ {
+ // Clean up neighbour pointers.
+ Node *l = v->firstAbove, *r = v->firstBelow;
+ if (l != nullptr)
+ {
+ l->firstBelow = v->firstBelow;
+ }
+ if (r != nullptr)
+ {
+ r->firstAbove = v->firstAbove;
+ }
+
+ if (e->type == ConnPoint)
+ {
+ scanline.erase(v->iter);
+ delete v;
+ }
+ else // if (e->type == Close)
+ {
+ size_t result;
+ result = scanline.erase(v);
+ COLA_ASSERT(result == 1);
+ COLA_UNUSED(result); // Avoid warning.
+ delete v;
+ }
+ }
+}
+
+// Correct visibility for pins or connector endpoints on the leading or
+// trailing edge of the visibility graph which may only have visibility in
+// the outward direction where there will not be a possible path.
+void fixConnectionPointVisibilityOnOutsideOfVisibilityGraph(Event **events,
+ size_t totalEvents, ConnDirFlags addedVisibility)
+{
+ if (totalEvents > 0)
+ {
+ double firstPos = events[0]->pos;
+ size_t index = 0;
+ while (index < totalEvents)
+ {
+ if (events[index]->pos > firstPos)
+ {
+ break;
+ }
+
+ if (events[index]->v->c)
+ {
+ events[index]->v->c->visDirections |= addedVisibility;
+ }
+ ++index;
+ }
+ index = 0;
+ double lastPos = events[totalEvents - 1]->pos;
+ while (index < totalEvents)
+ {
+ size_t revIndex = totalEvents - 1 - index;
+ if (events[revIndex]->pos < lastPos)
+ {
+ break;
+ }
+
+ if (events[revIndex]->v->c)
+ {
+ events[revIndex]->v->c->visDirections |= addedVisibility;
+ }
+ ++index;
+ }
+ }
+}
+
+extern void generateStaticOrthogonalVisGraph(Router *router)
+{
+ const size_t n = router->m_obstacles.size();
+ const unsigned cpn = router->vertices.connsSize();
+ // Set up the events for the vertical sweep.
+ size_t totalEvents = (2 * n) + cpn;
+ Event **events = new Event*[totalEvents];
+ unsigned ctr = 0;
+ ObstacleList::iterator obstacleIt = router->m_obstacles.begin();
+ for (unsigned i = 0; i < n; i++)
+ {
+ Obstacle *obstacle = *obstacleIt;
+#ifndef PAPER
+ JunctionRef *junction = dynamic_cast<JunctionRef *> (obstacle);
+ if (junction && ! junction->positionFixed())
+ {
+ // Junctions that are free to move are not treated as obstacles.
+ ++obstacleIt;
+ totalEvents -= 2;
+ continue;
+ }
+#endif
+
+ Box bbox = obstacle->routingBox();
+ double midX = bbox.min.x + ((bbox.max.x - bbox.min.x) / 2);
+ Node *v = new Node(obstacle, midX);
+ events[ctr++] = new Event(Open, v, bbox.min.y);
+ events[ctr++] = new Event(Close, v, bbox.max.y);
+
+ ++obstacleIt;
+ }
+
+#ifdef DEBUGHANDLER
+ if (router->debugHandler())
+ {
+ std::vector<Box> obstacleBoxes;
+ ObstacleList::iterator obstacleIt = router->m_obstacles.begin();
+ for (unsigned i = 0; i < n; i++)
+ {
+ Obstacle *obstacle = *obstacleIt;
+ JunctionRef *junction = dynamic_cast<JunctionRef *> (obstacle);
+ if (junction && ! junction->positionFixed())
+ {
+ // Junctions that are free to move are not treated as obstacles.
+ ++obstacleIt;
+ continue;
+ }
+ Box bbox = obstacle->routingBox();
+ obstacleBoxes.push_back(bbox);
+ ++obstacleIt;
+ }
+ router->debugHandler()->updateObstacleBoxes(obstacleBoxes);
+ }
+#endif
+
+ for (VertInf *curr = router->vertices.connsBegin();
+ curr && (curr != router->vertices.shapesBegin());
+ curr = curr->lstNext)
+ {
+ if (curr->visDirections == ConnDirNone)
+ {
+ // This is a connector endpoint that is attached to a connection
+ // pin on a shape, so it doesn't need to be given visibility.
+ // Thus, skip it and record that there is one less total event.
+ --totalEvents;
+ continue;
+ }
+ Point& point = curr->point;
+
+ Node *v = new Node(curr, point.x);
+ events[ctr++] = new Event(ConnPoint, v, point.y);
+ }
+ qsort((Event*)events, (size_t) totalEvents, sizeof(Event*), compare_events);
+
+ // Correct visibility for pins or connector endpoints on the leading or
+ // trailing edge of the visibility graph which may only have visibility in
+ // the outward direction where there will not be a possible path. We
+ // fix this by giving them visibility left and right.
+ fixConnectionPointVisibilityOnOutsideOfVisibilityGraph(events, totalEvents,
+ (ConnDirLeft | ConnDirRight));
+
+ // Process the vertical sweep -- creating cadidate horizontal edges.
+ // We do multiple passes over sections of the list so we can add relevant
+ // entries to the scanline that might follow, before processing them.
+ SegmentListWrapper segments;
+ NodeSet scanline;
+ double thisPos = (totalEvents > 0) ? events[0]->pos : 0;
+ unsigned int posStartIndex = 0;
+ unsigned int posFinishIndex = 0;
+ for (unsigned i = 0; i <= totalEvents; ++i)
+ {
+ // Progress reporting and continuation check.
+ router->performContinuationCheck(
+ TransactionPhaseOrthogonalVisibilityGraphScanX,
+ i, totalEvents);
+
+ // If we have finished the current scanline or all events, then we
+ // process the events on the current scanline in a couple of passes.
+ if ((i == totalEvents) || (events[i]->pos != thisPos))
+ {
+ posFinishIndex = i;
+ for (int pass = 2; pass <= 3; ++pass)
+ {
+ for (unsigned j = posStartIndex; j < posFinishIndex; ++j)
+ {
+ processEventVert(router, scanline, segments,
+ events[j], pass);
+ }
+ }
+
+ if (i == totalEvents)
+ {
+ // We have cleaned up, so we can now break out of loop.
+ break;
+ }
+
+ thisPos = events[i]->pos;
+ posStartIndex = i;
+ }
+
+ // Do the first sweep event handling -- building the correct
+ // structure of the scanline.
+ const int pass = 1;
+ processEventVert(router, scanline, segments, events[i], pass);
+ }
+ COLA_ASSERT(scanline.size() == 0);
+ for (unsigned i = 0; i < totalEvents; ++i)
+ {
+ delete events[i];
+ }
+
+ segments.list().sort();
+
+ // Set up the events for the horizontal sweep.
+ SegmentListWrapper vertSegments;
+ ctr = 0;
+ obstacleIt = router->m_obstacles.begin();
+ for (unsigned i = 0; i < n; i++)
+ {
+ Obstacle *obstacle = *obstacleIt;
+#ifndef PAPER
+ JunctionRef *junction = dynamic_cast<JunctionRef *> (obstacle);
+ if (junction && ! junction->positionFixed())
+ {
+ // Junctions that are free to move are not treated as obstacles.
+ ++obstacleIt;
+ continue;
+ }
+#endif
+ Box bbox = obstacle->routingBox();
+ double midY = bbox.min.y + ((bbox.max.y - bbox.min.y) / 2);
+ Node *v = new Node(obstacle, midY);
+ events[ctr++] = new Event(Open, v, bbox.min.x);
+ events[ctr++] = new Event(Close, v, bbox.max.x);
+
+ ++obstacleIt;
+ }
+ for (VertInf *curr = router->vertices.connsBegin();
+ curr && (curr != router->vertices.shapesBegin());
+ curr = curr->lstNext)
+ {
+ if (curr->visDirections == ConnDirNone)
+ {
+ // This is a connector endpoint that is attached to a connection
+ // pin on a shape, so it doesn't need to be given visibility.
+ // Thus, skip it.
+ continue;
+ }
+ Point& point = curr->point;
+
+ Node *v = new Node(curr, point.y);
+ events[ctr++] = new Event(ConnPoint, v, point.x);
+ }
+ qsort((Event*)events, (size_t) totalEvents, sizeof(Event*), compare_events);
+
+ // Correct visibility for pins or connector endpoints on the leading or
+ // trailing edge of the visibility graph which may only have visibility in
+ // the outward direction where there will not be a possible path. We
+ // fix this by giving them visibility up and down.
+ fixConnectionPointVisibilityOnOutsideOfVisibilityGraph(events, totalEvents,
+ (ConnDirUp | ConnDirDown));
+
+ // Process the horizontal sweep -- creating vertical visibility edges.
+ thisPos = (totalEvents > 0) ? events[0]->pos : 0;
+ posStartIndex = 0;
+ for (unsigned i = 0; i <= totalEvents; ++i)
+ {
+ // Progress reporting and continuation check.
+ router->performContinuationCheck(
+ TransactionPhaseOrthogonalVisibilityGraphScanY,
+ i, totalEvents);
+
+ // If we have finished the current scanline or all events, then we
+ // process the events on the current scanline in a couple of passes.
+ if ((i == totalEvents) || (events[i]->pos != thisPos))
+ {
+ posFinishIndex = i;
+ for (int pass = 2; pass <= 3; ++pass)
+ {
+ for (unsigned j = posStartIndex; j < posFinishIndex; ++j)
+ {
+ processEventHori(router, scanline, vertSegments,
+ events[j], pass);
+ }
+ }
+
+ // Process the merged line segments.
+ vertSegments.list().sort();
+ for (SegmentList::iterator curr = vertSegments.list().begin();
+ curr != vertSegments.list().end(); ++curr)
+ {
+ intersectSegments(router, segments.list(), *curr);
+ }
+ vertSegments.list().clear();
+
+ if (i == totalEvents)
+ {
+ // We have cleaned up, so we can now break out of loop.
+ break;
+ }
+
+ thisPos = events[i]->pos;
+ posStartIndex = i;
+ }
+
+ // Do the first sweep event handling -- building the correct
+ // structure of the scanline.
+ const int pass = 1;
+ processEventHori(router, scanline, vertSegments, events[i], pass);
+ }
+ COLA_ASSERT(scanline.size() == 0);
+ for (unsigned i = 0; i < totalEvents; ++i)
+ {
+ delete events[i];
+ }
+ delete [] events;
+
+ // Add portions of horizontal lines that are after the final vertical
+ // position we considered.
+ for (SegmentList::iterator it = segments.list().begin();
+ it != segments.list().end(); )
+ {
+ LineSegment& horiLine = *it;
+
+ horiLine.addEdgeHorizontal(router);
+
+ size_t dim = XDIM; // x-dimension
+ horiLine.generateVisibilityEdgesFromBreakpointSet(router, dim);
+
+ it = segments.list().erase(it);
+ }
+}
+
+
+//============================================================================
+// Path Adjustment code
+//============================================================================
+
+
+typedef std::pair<Point, Point> RectBounds;
+
+static bool insideRectBounds(const Point& point, const RectBounds& rectBounds)
+{
+ Point zero(0, 0);
+ if ((rectBounds.first == zero) && (rectBounds.second == zero))
+ {
+ // We can't be inside the invalid rectangle.
+ return false;
+ }
+
+ for (size_t i = 0; i < 2; ++i)
+ {
+ if (point[i] < rectBounds.first[i])
+ {
+ return false;
+ }
+ if (point[i] > rectBounds.second[i])
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+static void buildOrthogonalNudgingSegments(Router *router,
+ const size_t dim, ShiftSegmentList& segmentList)
+{
+ if (router->routingParameter(segmentPenalty) == 0)
+ {
+ // The nudging code assumes the routes are pretty optimal. This will
+ // only be true if a segment penalty is set, so just return if this
+ // is not the case.
+ return;
+ }
+ bool nudgeFinalSegments =
+ router->routingOption(nudgeOrthogonalSegmentsConnectedToShapes);
+ std::vector<RectBounds> shapeLimits;
+ if (nudgeFinalSegments)
+ {
+ // If we're going to nudge final segments, then cache the shape
+ // rectangles to save us rebuilding them multiple times.
+ const size_t n = router->m_obstacles.size();
+ shapeLimits = std::vector<RectBounds>(n);
+
+ double zeroBufferDist = 0.0;
+
+ ObstacleList::iterator obstacleIt = router->m_obstacles.begin();
+ for (unsigned i = 0; i < n; i++)
+ {
+ ShapeRef *shape = dynamic_cast<ShapeRef *> (*obstacleIt);
+ JunctionRef *junction = dynamic_cast<JunctionRef *> (*obstacleIt);
+ if (shape)
+ {
+ // Take the real bounds of the shape
+ Box bBox = shape->polygon().offsetBoundingBox(zeroBufferDist);
+ shapeLimits[i] = std::make_pair(bBox.min, bBox.max);
+ }
+ else if (junction)
+ {
+ // Don't nudge segments attached to junctions,
+ // so just use the junction position here.
+ Point pos = junction->position();
+ shapeLimits[i] = std::make_pair(pos, pos);
+ }
+ ++obstacleIt;
+ }
+ }
+
+ size_t altDim = (dim + 1) % 2;
+ // For each connector.
+ for (ConnRefList::const_iterator curr = router->connRefs.begin();
+ curr != router->connRefs.end(); ++curr)
+ {
+ if ((*curr)->routingType() != ConnType_Orthogonal)
+ {
+ continue;
+ }
+ Polygon& displayRoute = (*curr)->displayRoute();
+ // Determine all line segments that we are interested in shifting.
+ // We don't consider the first or last segment of a path.
+ for (size_t i = 1; i < displayRoute.size(); ++i)
+ {
+ if (displayRoute.ps[i - 1][dim] == displayRoute.ps[i][dim])
+ {
+ // It's a segment in the dimension we are processing,
+ size_t indexLow = i - 1;
+ size_t indexHigh = i;
+ if (displayRoute.ps[i - 1][altDim] ==
+ displayRoute.ps[i][altDim])
+ {
+ // This is a zero length segment, so ignore it.
+ continue;
+ }
+ else if (displayRoute.ps[i - 1][altDim] >
+ displayRoute.ps[i][altDim])
+ {
+ indexLow = i;
+ indexHigh = i - 1;
+ }
+
+ // Find the checkpoints on the current segment and the
+ // checkpoints on the adjoining segments that aren't on
+ // the corner (hence the +1 and -1 modifiers).
+ std::vector<Point> checkpoints =
+ displayRoute.checkpointsOnSegment(i - 1);
+ std::vector<Point> prevCheckpoints =
+ displayRoute.checkpointsOnSegment(i - 2, -1);
+ std::vector<Point> nextCheckpoints =
+ displayRoute.checkpointsOnSegment(i, +1);
+ bool hasCheckpoints = (checkpoints.size() > 0);
+ if (hasCheckpoints && !nudgeFinalSegments)
+ {
+ // This segment includes one of the routing
+ // checkpoints so we shouldn't shift it.
+ segmentList.push_back(new NudgingShiftSegment(
+ *curr, indexLow, indexHigh, dim));
+ continue;
+ }
+
+ double thisPos = displayRoute.ps[i][dim];
+
+ if ((i == 1) || ((i + 1) == displayRoute.size()))
+ {
+ // Is first or last segment of route.
+
+ if (nudgeFinalSegments)
+ {
+ // Determine available space for nudging these
+ // final segments.
+ double minLim = -CHANNEL_MAX;
+ double maxLim = CHANNEL_MAX;
+
+ // If the position of the opposite end of the
+ // attached segment is within the shape boundaries
+ // then we want to use this as an ideal position
+ // for the segment.
+
+ // Bitflags indicating whether this segment starts
+ // and/or ends in a shape.
+ unsigned int endsInShapes = 0;
+ // Also limit their movement to the edges of the
+ // shapes they begin or end within.
+ for (size_t k = 0; k < shapeLimits.size(); ++k)
+ {
+ double shapeMin = shapeLimits[k].first[dim];
+ double shapeMax = shapeLimits[k].second[dim];
+ if (insideRectBounds(displayRoute.ps[i - 1],
+ shapeLimits[k]))
+ {
+ minLim = std::max(minLim, shapeMin);
+ maxLim = std::min(maxLim, shapeMax);
+ endsInShapes |= 0x01;
+ }
+ if (insideRectBounds(displayRoute.ps[i],
+ shapeLimits[k]))
+ {
+ minLim = std::max(minLim, shapeMin);
+ maxLim = std::min(maxLim, shapeMax);
+ endsInShapes |= 0x10;
+ }
+ }
+
+ if ( endsInShapes == 0 )
+ {
+ // If the segment is not within a shape, then we
+ // should limit it's nudging buffer so we don't
+ // combine many unnecessary regions.
+ double pos = displayRoute.ps[i - 1][dim];
+ double freeConnBuffer = 15;
+ minLim = std::max(minLim, pos - freeConnBuffer);
+ maxLim = std::min(maxLim, pos + freeConnBuffer);
+ }
+
+ if ((minLim == maxLim) || (*curr)->hasFixedRoute())
+ {
+ // Fixed.
+ segmentList.push_back(new NudgingShiftSegment(*curr,
+ indexLow, indexHigh, dim));
+ }
+ else
+ {
+ // Shiftable.
+ NudgingShiftSegment *segment = new NudgingShiftSegment(
+ *curr, indexLow, indexHigh, false, false, dim,
+ minLim, maxLim);
+ segment->finalSegment = true;
+ segment->endsInShape = (endsInShapes > 0);
+ if ((displayRoute.size() == 2) &&
+ (endsInShapes == 0x11))
+ {
+ // This is a single segment connector bridging
+ // two shapes. So, we want to try to keep the
+ // segment centred rather than shift it.
+ segment->singleConnectedSegment = true;
+ }
+ segmentList.push_back(segment);
+ }
+ }
+ else
+ {
+ // The first and last segment of a connector can't be
+ // shifted. We call them fixed segments.
+ segmentList.push_back(new NudgingShiftSegment(*curr,
+ indexLow, indexHigh, dim));
+ }
+ continue;
+ }
+
+
+ // The segment probably has space to be shifted.
+ double minLim = -CHANNEL_MAX;
+ double maxLim = CHANNEL_MAX;
+
+ // Constrain these segments by checkpoints along the
+ // adjoining segments. Ignore checkpoints at ends of
+ // those segments. XXX Perhaps this should not
+ // affect the ideal centre position in the channel.
+ for (size_t cp = 0; cp < nextCheckpoints.size(); ++cp)
+ {
+ if (nextCheckpoints[cp][dim] < thisPos)
+ {
+ // Not at thisPoint, so constrain.
+ minLim = std::max(minLim, nextCheckpoints[cp][dim]);
+ }
+ else if (nextCheckpoints[cp][dim] > thisPos)
+ {
+ // Not at thisPoint, so constrain.
+ maxLim = std::min(maxLim, nextCheckpoints[cp][dim]);
+ }
+ }
+ for (size_t cp = 0; cp < prevCheckpoints.size(); ++cp)
+ {
+ if (prevCheckpoints[cp][dim] < thisPos)
+ {
+ // Not at thisPoint, so constrain.
+ minLim = std::max(minLim, prevCheckpoints[cp][dim]);
+ }
+ else if (prevCheckpoints[cp][dim] > thisPos)
+ {
+ // Not at thisPoint, so constrain.
+ maxLim = std::min(maxLim, prevCheckpoints[cp][dim]);
+ }
+ }
+
+ bool isSBend = false;
+ bool isZBend = false;
+
+ if (checkpoints.empty())
+ {
+ // Segments with checkpoints are held in place, but for
+ // other segments, we should limit their movement based
+ // on the limits of the segments at either end.
+
+ double prevPos = displayRoute.ps[i - 2][dim];
+ double nextPos = displayRoute.ps[i + 1][dim];
+ if ( ((prevPos < thisPos) && (nextPos > thisPos)) ||
+ ((prevPos > thisPos) && (nextPos < thisPos)) )
+ {
+ // Determine limits if the s-bend is not due to an
+ // obstacle. In this case we need to limit the channel
+ // to the span of the adjoining segments to this one.
+ if ((prevPos < thisPos) && (nextPos > thisPos))
+ {
+ minLim = std::max(minLim, prevPos);
+ maxLim = std::min(maxLim, nextPos);
+ isZBend = true;
+ }
+ else // if ((prevPos > thisPos) && (nextPos < thisPos))
+ {
+ minLim = std::max(minLim, nextPos);
+ maxLim = std::min(maxLim, prevPos);
+ isSBend = true;
+ }
+ }
+ }
+
+ NudgingShiftSegment *nss = new NudgingShiftSegment(*curr,
+ indexLow, indexHigh, isSBend, isZBend, dim,
+ minLim, maxLim);
+ nss->checkpoints = checkpoints;
+ segmentList.push_back(nss);
+ }
+ }
+ }
+}
+
+
+typedef std::vector<ConnRef *> ConnRefVector;
+typedef std::vector<Polygon> RouteVector;
+
+
+class CmpLineOrder
+{
+ public:
+ CmpLineOrder(PtOrderMap& ord, const size_t dim)
+ : orders(ord),
+ dimension(dim)
+ {
+ }
+ bool operator()(const ShiftSegment *lhsSuper,
+ const ShiftSegment *rhsSuper,
+ bool *comparable = nullptr) const
+ {
+ const NudgingShiftSegment *lhs =
+ static_cast<const NudgingShiftSegment *> (lhsSuper);
+ const NudgingShiftSegment *rhs =
+ static_cast<const NudgingShiftSegment *> (rhsSuper);
+ if (comparable)
+ {
+ *comparable = true;
+ }
+ Point lhsLow = lhs->lowPoint();
+ Point rhsLow = rhs->lowPoint();
+ size_t altDim = (dimension + 1) % 2;
+#ifndef NDEBUG
+ const Point& lhsHigh = lhs->highPoint();
+ const Point& rhsHigh = rhs->highPoint();
+ COLA_ASSERT(lhsLow[dimension] == lhsHigh[dimension]);
+ COLA_ASSERT(rhsLow[dimension] == rhsHigh[dimension]);
+#endif
+
+ // We consider things at effectively the same position to
+ // be ordered based on their order and fixedOrder, so only
+ // compare segments further apart than the nudgeDistance.
+ if (lhsLow[dimension] != rhsLow[dimension])
+ {
+ return lhsLow[dimension] < rhsLow[dimension];
+ }
+
+ // If one of these is fixed, then determine order based on
+ // fixed segment, that is, order so the fixed segment doesn't
+ // block movement.
+ bool oneIsFixed = false;
+ const int lhsFixedOrder = lhs->fixedOrder(oneIsFixed);
+ const int rhsFixedOrder = rhs->fixedOrder(oneIsFixed);
+ if (oneIsFixed && (lhsFixedOrder != rhsFixedOrder))
+ {
+ return lhsFixedOrder < rhsFixedOrder;
+ }
+
+ // C-bends that did not have a clear order with s-bends might
+ // not have a good ordering here, so compare their order in
+ // terms of C-bend direction and S-bends and use that if it
+ // differs for the two segments.
+ const int lhsOrder = lhs->order();
+ const int rhsOrder = rhs->order();
+ if (lhsOrder != rhsOrder)
+ {
+ return lhsOrder < rhsOrder;
+ }
+
+ // Need to index using the original point into the map, so find it.
+ Point& unchanged = (lhsLow[altDim] > rhsLow[altDim]) ?
+ lhsLow : rhsLow;
+
+ PtOrder& lowOrder = orders[unchanged];
+ int lhsPos = lowOrder.positionFor(dimension, lhs->connRef);
+ int rhsPos = lowOrder.positionFor(dimension, rhs->connRef);
+ if ((lhsPos == -1) || (rhsPos == -1))
+ {
+ // A value for rhsPos or lhsPos mean the points are not directly
+ // comparable, meaning they are at the same position but cannot
+ // overlap (they are just collinear. The relative order for
+ // these segments is not important since we do not constrain
+ // them against each other.
+ //COLA_ASSERT(lhs->overlapsWith(rhs, dimension) == false);
+ // We do need to be consistent though.
+ if (comparable)
+ {
+ *comparable = false;
+ }
+ return lhsLow[altDim] < rhsLow[altDim];
+ }
+ return lhsPos < rhsPos;
+ }
+
+ PtOrderMap& orders;
+ const size_t dimension;
+};
+
+
+// We can't use the normal sort algorithm for lists since it is not possible
+// to compare all elements, but there will be an ordering defined between
+// most of the elements. Hence we order these, using insertion sort, and
+// the case of them not being able to be compared is handled by not setting
+// up any constraints between such segments when doing the nudging.
+//
+static ShiftSegmentList linesort(bool nudgeFinalSegments,
+ ShiftSegmentList origList, CmpLineOrder& comparison)
+{
+ // Cope with end segments that are getting moved and will line up with
+ // other segments of the same connector. We do this by merging them into
+ // a single NudgingShiftSegment.
+ if (nudgeFinalSegments)
+ {
+ for (ShiftSegmentList::iterator currSegIt = origList.begin();
+ currSegIt != origList.end(); ++currSegIt)
+ {
+ for (ShiftSegmentList::iterator otherSegIt = currSegIt;
+ otherSegIt != origList.end(); )
+ {
+ NudgingShiftSegment *currSeg =
+ static_cast<NudgingShiftSegment *> (*currSegIt);
+ NudgingShiftSegment *otherSeg =
+ static_cast<NudgingShiftSegment *> (*otherSegIt);
+ if ((currSegIt != otherSegIt) && currSeg && otherSeg &&
+ currSeg->shouldAlignWith(otherSeg, comparison.dimension))
+ {
+ currSeg->mergeWith(otherSeg, comparison.dimension);
+ delete otherSeg;
+ otherSegIt = origList.erase(otherSegIt);
+ }
+ else
+ {
+ ++otherSegIt;
+ }
+ }
+ }
+ }
+
+ ShiftSegmentList resultList;
+
+ size_t origListSize = origList.size();
+ size_t deferredN = 0;
+ while (!origList.empty())
+ {
+ // Get and remove the first element from the origList.
+ ShiftSegment *segment = origList.front();
+ origList.pop_front();
+
+ // Find the insertion point in the resultList.
+ bool allComparable = true;
+ ShiftSegmentList::iterator curr;
+ for (curr = resultList.begin(); curr != resultList.end(); ++curr)
+ {
+ bool comparable = false;
+ bool lessThan = comparison(segment, *curr, &comparable);
+ allComparable &= comparable;
+
+ if (comparable && lessThan)
+ {
+ // If it is comparable and lessThan, then we have found the
+ // insertion point.
+ break;
+ }
+ }
+
+ if (resultList.empty() || allComparable || (deferredN >= origListSize))
+ {
+ // Insert the element into the resultList at the required point.
+ resultList.insert(curr, segment);
+ // Reset the origListSize and deferred counter.
+ deferredN = 0;
+ origListSize = origList.size();
+ }
+ else
+ {
+ // This wasn't comparable to anything in the sorted list,
+ // so defer addition of the segment till later.
+ origList.push_back(segment);
+ deferredN++;
+ }
+ }
+
+ return resultList;
+}
+
+
+typedef std::list<ShiftSegment *> ShiftSegmentPtrList;
+
+class PotentialSegmentConstraint
+{
+ public:
+ PotentialSegmentConstraint(size_t index1, size_t index2,
+ const Variables& vs)
+ : index1(index1),
+ index2(index2),
+ vs(vs)
+ {
+ }
+
+ bool operator<(const PotentialSegmentConstraint rhs) const
+ {
+ return sepDistance() < rhs.sepDistance();
+ }
+ double sepDistance(void) const
+ {
+ if (!stillValid())
+ {
+ return 0;
+ }
+ return fabs(vs[index1]->finalPosition - vs[index2]->finalPosition);
+ }
+ bool stillValid(void) const
+ {
+ return (index1 != index2);
+ }
+ void rewriteIndex(size_t oldIndex, size_t newIndex)
+ {
+ if (index1 == oldIndex)
+ {
+ index1 = newIndex;
+ }
+
+ if (index2 == oldIndex)
+ {
+ index2 = newIndex;
+ }
+ }
+
+ size_t index1;
+ size_t index2;
+
+ private:
+ const Variables& vs;
+};
+
+
+class ImproveOrthogonalRoutes
+{
+public:
+ ImproveOrthogonalRoutes(Router *router);
+ void execute(void);
+
+private:
+ void simplifyOrthogonalRoutes(void);
+ void buildOrthogonalNudgingOrderInfo(void);
+ void nudgeOrthogonalRoutes(size_t dimension,
+ bool justUnifying = false);
+
+ Router *m_router;
+ PtOrderMap m_point_orders;
+ UnsignedPairSet m_shared_path_connectors_with_common_endpoints;
+ ShiftSegmentList m_segment_list;
+};
+
+
+ImproveOrthogonalRoutes::ImproveOrthogonalRoutes(Router *router)
+ : m_router(router)
+{
+}
+
+void ImproveOrthogonalRoutes::execute(void)
+{
+ TIMER_START(m_router, tmOrthogNudge);
+
+ m_shared_path_connectors_with_common_endpoints.clear();
+
+ // Simplify routes.
+ simplifyOrthogonalRoutes();
+
+ // Build a cache that denotes whether a certain segment of a connector
+ // contains a checkpoint. We can't just compare positions, since routes
+ // can be moved away from their original positions during nudging.
+ buildConnectorRouteCheckpointCache(m_router);
+
+ // Do Unifying first, by itself. This greedily tries to position free
+ // segments in overlapping channels at the same position. This way they
+ // have correct nudging orders determined for them since they will form
+ // shared paths, rather than segments just positioned as an results of
+ // the routing process. Of course, don't do this when rerouting with
+ // a fixedSharedPathPenalty since these routes include extra segments
+ // we want to keep apart which prevent some shared paths.
+ if (m_router->routingOption(performUnifyingNudgingPreprocessingStep) &&
+ (m_router->routingParameter(fixedSharedPathPenalty) == 0))
+ {
+ for (size_t dimension = 0; dimension < 2; ++dimension)
+ {
+ // Just perform Unifying operation.
+ bool justUnifying = true;
+ m_segment_list.clear();
+ buildOrthogonalNudgingSegments(m_router, dimension, m_segment_list);
+ buildOrthogonalChannelInfo(m_router, dimension, m_segment_list);
+ nudgeOrthogonalRoutes(dimension, justUnifying);
+ }
+ }
+
+#ifndef DEBUG_JUST_UNIFY
+ // Do the Nudging and centring.
+ for (size_t dimension = 0; dimension < 2; ++dimension)
+ {
+ m_point_orders.clear();
+ // Build nudging info.
+ // XXX Needs to be rebuilt for each dimension, cause of shifting
+ // points. Maybe we could modify the point orders.
+ buildOrthogonalNudgingOrderInfo();
+
+ // Do the centring and nudging.
+ m_segment_list.clear();
+ buildOrthogonalNudgingSegments(m_router, dimension, m_segment_list);
+ buildOrthogonalChannelInfo(m_router, dimension, m_segment_list);
+ nudgeOrthogonalRoutes(dimension);
+ }
+#endif // DEBUG_JUST_UNIFY
+
+ // Resimplify all the display routes that may have been split.
+ simplifyOrthogonalRoutes();
+
+ m_router->improveOrthogonalTopology();
+
+ // Clear the segment-checkpoint cache for connectors.
+ clearConnectorRouteCheckpointCache(m_router);
+
+ TIMER_STOP(m_router);
+}
+
+void ImproveOrthogonalRoutes::nudgeOrthogonalRoutes(size_t dimension,
+ bool justUnifying)
+{
+ bool nudgeFinalSegments = m_router->routingOption(
+ nudgeOrthogonalSegmentsConnectedToShapes);
+ bool nudgeSharedPathsWithCommonEnd = m_router->routingOption(
+ nudgeSharedPathsWithCommonEndPoint);
+ double baseSepDist = m_router->routingParameter(idealNudgingDistance);
+ COLA_ASSERT(baseSepDist >= 0);
+ // If we can fit things with the desired separation distance, then
+ // we try 10 times, reducing each time by a 10th of the original amount.
+ double reductionSteps = 10.0;
+
+ size_t totalSegmentsToShift = m_segment_list.size();
+ size_t numOfSegmentsShifted = 0;
+ // Do the actual nudging.
+ ShiftSegmentList currentRegion;
+ while (!m_segment_list.empty())
+ {
+ // Progress reporting and continuation check.
+ numOfSegmentsShifted = totalSegmentsToShift - m_segment_list.size();
+ m_router->performContinuationCheck(
+ (dimension == XDIM) ? TransactionPhaseOrthogonalNudgingX :
+ TransactionPhaseOrthogonalNudgingY, numOfSegmentsShifted,
+ totalSegmentsToShift);
+
+ // Take a reference segment
+ ShiftSegment *currentSegment = m_segment_list.front();
+ // Then, find the segments that overlap this one.
+ currentRegion.clear();
+ currentRegion.push_back(currentSegment);
+ m_segment_list.erase(m_segment_list.begin());
+ for (ShiftSegmentList::iterator curr = m_segment_list.begin();
+ curr != m_segment_list.end(); )
+ {
+ bool overlaps = false;
+ for (ShiftSegmentList::iterator curr2 = currentRegion.begin();
+ curr2 != currentRegion.end(); ++curr2)
+ {
+ if ((*curr)->overlapsWith(*curr2, dimension))
+ {
+ overlaps = true;
+ break;
+ }
+ }
+ if (overlaps)
+ {
+ currentRegion.push_back(*curr);
+ m_segment_list.erase(curr);
+ // Consider segments from the beginning, since we may have
+ // since passed segments that overlap with the new set.
+ curr = m_segment_list.begin();
+ }
+ else
+ {
+ ++curr;
+ }
+ }
+
+ if (! justUnifying)
+ {
+ CmpLineOrder lineSortComp(m_point_orders, dimension);
+ currentRegion = linesort(nudgeFinalSegments, currentRegion,
+ lineSortComp);
+ }
+
+ if (currentRegion.size() == 1)
+ {
+ // Save creating the solver instance if there is just one
+ // immovable segment, or if we are in the unifying stage.
+ if (currentRegion.front()->immovable() || justUnifying)
+ {
+ delete currentRegion.front();
+ continue;
+ }
+ }
+
+ // Process these segments.
+ std::list<size_t> freeIndexes;
+ Variables vs;
+ Constraints cs;
+ Constraints gapcs;
+ ShiftSegmentPtrList prevVars;
+ double sepDist = baseSepDist;
+#ifdef NUDGE_DEBUG
+ fprintf(stderr, "-------------------------------------------------------\n");
+ fprintf(stderr, "%s -- size: %d\n", (justUnifying) ? "Unifying" : "Nudging",
+ (int) currentRegion.size());
+#endif
+#ifdef NUDGE_DEBUG_SVG
+ printf("\n\n");
+#endif
+ for (ShiftSegmentList::iterator currSegmentIt = currentRegion.begin();
+ currSegmentIt != currentRegion.end(); ++currSegmentIt )
+ {
+ NudgingShiftSegment *currSegment = static_cast<NudgingShiftSegment *> (*currSegmentIt);
+
+ // Create a solver variable for the position of this segment.
+ currSegment->createSolverVariable(justUnifying);
+
+ vs.push_back(currSegment->variable);
+ size_t index = vs.size() - 1;
+#ifdef NUDGE_DEBUG
+ fprintf(stderr,"line(%d) %.15f dim: %d pos: %.16f\n"
+ "min: %.16f max: %.16f\n"
+ "minEndPt: %.16f maxEndPt: %.16f weight: %g cc: %d\n",
+ currSegment->connRef->id(),
+ currSegment->lowPoint()[dimension], (int) dimension,
+ currSegment->variable->desiredPosition,
+ currSegment->minSpaceLimit, currSegment->maxSpaceLimit,
+ currSegment->lowPoint()[!dimension], currSegment->highPoint()[!dimension],
+ currSegment->variable->weight,
+ (int) currSegment->checkpoints.size());
+#endif
+#ifdef NUDGE_DEBUG_SVG
+ // Debugging info:
+ double minP = std::max(currSegment->minSpaceLimit, -5000.0);
+ double maxP = std::min(currSegment->maxSpaceLimit, 5000.0);
+ fprintf(stdout, "<rect style=\"fill: #f00; opacity: 0.2;\" "
+ "x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" />\n",
+ currSegment->lowPoint()[XDIM], minP,
+ currSegment->highPoint()[XDIM] - currSegment->lowPoint()[XDIM],
+ maxP - minP);
+ fprintf(stdout, "<line style=\"stroke: #000;\" x1=\"%g\" "
+ "y1=\"%g\" x2=\"%g\" y2=\"%g\" />\n",
+ currSegment->lowPoint()[XDIM], currSegment->lowPoint()[YDIM],
+ currSegment->highPoint()[XDIM], currSegment->highPoint()[YDIM]);
+#endif
+
+ if (justUnifying)
+ {
+ // Just doing centring, not nudging.
+ // Record the index of the variable so we can use it as
+ // a segment to potentially constrain to other segments.
+ if (currSegment->variable->weight == freeWeight)
+ {
+ freeIndexes.push_back(index);
+ }
+ // Thus, we don't need to constrain position against other
+ // segments.
+ prevVars.push_back(&(*currSegment));
+ continue;
+ }
+
+ // The constraints generated here must be in order of
+ // leftBoundary-segment ... segment-segment ... segment-rightBoundary
+ // since this order is leveraged later for rewriting the
+ // separations of unsatisfable channel groups.
+
+ // Constrain to channel boundary.
+ if (!currSegment->fixed)
+ {
+ // If this segment sees a channel boundary to its left,
+ // then constrain its placement as such.
+ if (currSegment->minSpaceLimit > -CHANNEL_MAX)
+ {
+ vs.push_back(new Variable(channelLeftID,
+ currSegment->minSpaceLimit, fixedWeight));
+ cs.push_back(new Constraint(vs[vs.size() - 1], vs[index],
+ 0.0));
+ }
+ }
+
+ // Constrain position in relation to previously seen segments,
+ // if necessary (i.e. when they could overlap).
+ for (ShiftSegmentPtrList::iterator prevVarIt = prevVars.begin();
+ prevVarIt != prevVars.end(); ++prevVarIt)
+ {
+ NudgingShiftSegment *prevSeg =
+ static_cast<NudgingShiftSegment *> (*prevVarIt);
+ Variable *prevVar = prevSeg->variable;
+
+ if (currSegment->overlapsWith(prevSeg, dimension) &&
+ (!(currSegment->fixed) || !(prevSeg->fixed)))
+ {
+ // If there is a previous segment to the left that
+ // could overlap this in the shift direction, then
+ // constrain the two segments to be separated.
+ // Though don't add the constraint if both the
+ // segments are fixed in place.
+ double thisSepDist = sepDist;
+ bool equality = false;
+ if (currSegment->shouldAlignWith(prevSeg, dimension))
+ {
+ // Handles the case where the two end segments can
+ // be brought together to make a single segment. This
+ // can help in situations where having the small kink
+ // can restrict other kinds of nudging.
+ thisSepDist = 0;
+ equality = true;
+ }
+ else if (currSegment->canAlignWith(prevSeg, dimension))
+ {
+ // We need to address the problem of two neighbouring
+ // segments of the same connector being kept separated
+ // due only to a kink created in the other dimension.
+ // Here, we let such segments drift back together.
+ thisSepDist = 0;
+ }
+ else if (!nudgeSharedPathsWithCommonEnd &&
+ (m_shared_path_connectors_with_common_endpoints.count(
+ UnsignedPair(currSegment->connRef->id(), prevSeg->connRef->id())) > 0))
+ {
+ // We don't want to nudge apart these two segments
+ // since they are from a shared path with a common
+ // endpoint. There might be multiple chains of
+ // segments that don't all have the same endpoints
+ // so we need to make this an equality to prevent
+ // some of them possibly getting nudged apart.
+ thisSepDist = 0;
+ equality = true;
+ }
+
+ Constraint *constraint = new Constraint(prevVar,
+ vs[index], thisSepDist, equality);
+ cs.push_back(constraint);
+ if (thisSepDist)
+ {
+ // Add to the list of gap constraints so we can
+ // rewrite the separation distance later.
+ gapcs.push_back(constraint);
+ }
+ }
+ }
+
+ if (!currSegment->fixed)
+ {
+ // If this segment sees a channel boundary to its right,
+ // then constrain its placement as such.
+ if (currSegment->maxSpaceLimit < CHANNEL_MAX)
+ {
+ vs.push_back(new Variable(channelRightID,
+ currSegment->maxSpaceLimit, fixedWeight));
+ cs.push_back(new Constraint(vs[index], vs[vs.size() - 1],
+ 0.0));
+ }
+ }
+
+ prevVars.push_back(&(*currSegment));
+ }
+
+ std::list<PotentialSegmentConstraint> potentialConstraints;
+ if (justUnifying)
+ {
+ for (std::list<size_t>::iterator curr = freeIndexes.begin();
+ curr != freeIndexes.end(); ++curr)
+ {
+ for (std::list<size_t>::iterator curr2 = curr;
+ curr2 != freeIndexes.end(); ++curr2)
+ {
+ if (curr == curr2)
+ {
+ continue;
+ }
+ potentialConstraints.push_back(
+ PotentialSegmentConstraint(*curr, *curr2, vs));
+ }
+ }
+ }
+#ifdef NUDGE_DEBUG
+ for (unsigned i = 0;i < vs.size(); ++i)
+ {
+ fprintf(stderr, "-vs[%d]=%f\n", i, vs[i]->desiredPosition);
+ }
+#endif
+ // Repeatedly try solving this. There are two cases:
+ // - When Unifying, we greedily place as many free segments as
+ // possible at the same positions, that way they have more
+ // accurate nudging orders determined for them in the Nudging
+ // stage.
+ // - When Nudging, if we can't fit all the segments with the
+ // default nudging distance we try smaller separation
+ // distances till we find a solution that is satisfied.
+ bool justAddedConstraint = false;
+ bool satisfied;
+
+ typedef std::pair<size_t, size_t> UnsatisfiedRange;
+ std::list<UnsatisfiedRange> unsatisfiedRanges;
+ do
+ {
+ IncSolver f(vs, cs);
+ f.solve();
+
+ // Determine if the problem was satisfied.
+ satisfied = true;
+ for (size_t i = 0; i < vs.size(); ++i)
+ {
+ // For each variable...
+ if (vs[i]->id != freeSegmentID)
+ {
+ // If it is a fixed segment (should stay still)...
+ if (fabs(vs[i]->finalPosition -
+ vs[i]->desiredPosition) > 0.0001)
+ {
+ // and it is not at it's desired position, then
+ // we consider the problem to be unsatisfied.
+ satisfied = false;
+
+ // We record ranges of unsatisfied variables based on
+ // the channel edges.
+ if (vs[i]->id == channelLeftID)
+ {
+ // This is the left-hand-side of a channel.
+ if (unsatisfiedRanges.empty() ||
+ (unsatisfiedRanges.back().first !=
+ unsatisfiedRanges.back().second))
+ {
+ // There are no existing unsatisfied ranges,
+ // or there are but they are a valid range
+ // (we've encountered the right-hand channel
+ // edges already).
+ // So, start a new unsatisfied range.
+ unsatisfiedRanges.push_back(
+ std::make_pair(i, i + 1));
+ }
+ }
+ else if (vs[i]->id == channelRightID)
+ {
+ // This is the right-hand-side of a channel.
+ if (unsatisfiedRanges.empty())
+ {
+ // There are no existing unsatisfied ranges,
+ // so start a new unsatisfied range.
+ // We are looking at a unsatisfied right side
+ // where the left side was satisfied, so the
+ // range begins at the previous variable
+ // which should be a left channel side.
+ COLA_ASSERT(i > 0);
+ COLA_ASSERT(vs[i - 1]->id == channelLeftID);
+ unsatisfiedRanges.push_back(
+ std::make_pair(i - 1, i));
+ }
+ else
+ {
+ // Expand the existing range to include index.
+ unsatisfiedRanges.back().second = i;
+ }
+ }
+ else if (vs[i]->id == fixedSegmentID)
+ {
+ // Fixed connector segments can also start and
+ // extend unsatisfied variable ranges.
+ if (unsatisfiedRanges.empty())
+ {
+ // There are no existing unsatisfied ranges,
+ // so start a new unsatisfied range.
+ unsatisfiedRanges.push_back(
+ std::make_pair(i, i));
+ }
+ else
+ {
+ // Expand the existing range to include index.
+ unsatisfiedRanges.back().second = i;
+ }
+ }
+ }
+ }
+ }
+
+#ifdef NUDGE_DEBUG
+ if (!satisfied)
+ {
+ fprintf(stderr,"unsatisfied\n");
+ }
+#endif
+
+ if (justUnifying)
+ {
+ // When we're centring, we'd like to greedily place as many
+ // segments as possible at the same positions, that way they
+ // have more accurate nudging orders determined for them.
+ //
+ // We do this by taking pairs of adjoining free segments and
+ // attempting to constrain them to have the same position,
+ // starting from the closest up to the furthest.
+
+ if (justAddedConstraint)
+ {
+ COLA_ASSERT(potentialConstraints.size() > 0);
+ if (!satisfied)
+ {
+ // We couldn't satisfy the problem with the added
+ // potential constraint, so we can't position these
+ // segments together. Roll back.
+ potentialConstraints.pop_front();
+ delete cs.back();
+ cs.pop_back();
+ }
+ else
+ {
+ // We could position these two segments together.
+ PotentialSegmentConstraint& pc =
+ potentialConstraints.front();
+
+ // Rewrite the indexes of these two variables to
+ // one, so we need not worry about redundant
+ // equality constraints.
+ for (std::list<PotentialSegmentConstraint>::iterator
+ it = potentialConstraints.begin();
+ it != potentialConstraints.end(); ++it)
+ {
+ it->rewriteIndex(pc.index1, pc.index2);
+ }
+ potentialConstraints.pop_front();
+ }
+ }
+ potentialConstraints.sort();
+ justAddedConstraint = false;
+
+ // Remove now invalid potential segment constraints.
+ // This could have been caused by the variable rewriting.
+ while (!potentialConstraints.empty() &&
+ !potentialConstraints.front().stillValid())
+ {
+ potentialConstraints.pop_front();
+ }
+
+ if (!potentialConstraints.empty())
+ {
+ // We still have more possibilities to consider.
+ // Create a constraint for this, add it, and mark as
+ // unsatisfied, so the problem gets re-solved.
+ PotentialSegmentConstraint& pc =
+ potentialConstraints.front();
+ COLA_ASSERT(pc.index1 != pc.index2);
+ cs.push_back(new Constraint(vs[pc.index1], vs[pc.index2],
+ 0, true));
+ satisfied = false;
+ justAddedConstraint = true;
+ }
+ }
+ else
+ {
+ if (!satisfied)
+ {
+ COLA_ASSERT(unsatisfiedRanges.size() > 0);
+ // Reduce the separation distance.
+ sepDist -= (baseSepDist / reductionSteps);
+#ifndef NDEBUG
+ for (std::list<UnsatisfiedRange>::iterator it =
+ unsatisfiedRanges.begin();
+ it != unsatisfiedRanges.end(); ++it)
+ {
+ COLA_ASSERT(vs[it->first]->id != freeSegmentID);
+ COLA_ASSERT(vs[it->second]->id != freeSegmentID);
+ }
+#endif
+#ifdef NUDGE_DEBUG
+ for (std::list<UnsatisfiedRange>::iterator it =
+ unsatisfiedRanges.begin();
+ it != unsatisfiedRanges.end(); ++it)
+ {
+ fprintf(stderr, "unsatisfiedVarRange(%ld, %ld)\n",
+ it->first, it->second);
+ }
+ fprintf(stderr, "unsatisfied, trying %g\n", sepDist);
+#endif
+ // And rewrite all the gap constraints to have the new
+ // reduced separation distance.
+ bool withinUnsatisfiedGroup = false;
+ for (Constraints::iterator cIt = cs.begin();
+ cIt != cs.end(); ++cIt)
+ {
+ UnsatisfiedRange& range = unsatisfiedRanges.front();
+ Constraint *constraint = *cIt;
+
+ if (constraint->left == vs[range.first])
+ {
+ // Entered an unsatisfied range of variables.
+ withinUnsatisfiedGroup = true;
+ }
+
+ if (withinUnsatisfiedGroup && (constraint->gap > 0))
+ {
+ // Rewrite constraints in unsatisfied ranges
+ // that have a non-zero gap.
+ constraint->gap = sepDist;
+ }
+
+ if (constraint->right == vs[range.second])
+ {
+ // Left an unsatisfied range of variables.
+ withinUnsatisfiedGroup = false;
+ unsatisfiedRanges.pop_front();
+ if (unsatisfiedRanges.empty())
+ {
+ // And there are no more unsatisfied variables.
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ while (!satisfied && (sepDist > 0.0001));
+
+ if (satisfied)
+ {
+#ifdef NUDGE_DEBUG
+ fprintf(stderr,"satisfied at nudgeDist = %g\n", sepDist);
+#endif
+ for (ShiftSegmentList::iterator currSegment = currentRegion.begin();
+ currSegment != currentRegion.end(); ++currSegment)
+ {
+ NudgingShiftSegment *segment =
+ static_cast<NudgingShiftSegment *> (*currSegment);
+
+ segment->updatePositionsFromSolver(justUnifying);
+ }
+ }
+#ifdef NUDGE_DEBUG
+ for(unsigned i=0;i<vs.size();i++) {
+ fprintf(stderr, "+vs[%d]=%f\n",i,vs[i]->finalPosition);
+ }
+#endif
+#ifdef NUDGE_DEBUG_SVG
+ for (ShiftSegmentList::iterator currSegment = currentRegion.begin();
+ currSegment != currentRegion.end(); ++currSegment)
+ {
+ NudgingShiftSegment *segment =
+ static_cast<NudgingShiftSegment *> (*currSegment);
+
+ fprintf(stdout, "<line style=\"stroke: #00F;\" x1=\"%g\" "
+ "y1=\"%g\" x2=\"%g\" y2=\"%g\" />\n",
+ segment->lowPoint()[XDIM], segment->variable->finalPosition,
+ segment->highPoint()[XDIM], segment->variable->finalPosition);
+ }
+#endif
+ for_each(currentRegion.begin(), currentRegion.end(), delete_object());
+ for_each(vs.begin(), vs.end(), delete_object());
+ for_each(cs.begin(), cs.end(), delete_object());
+ }
+}
+
+
+void ImproveOrthogonalRoutes::simplifyOrthogonalRoutes(void)
+{
+ // Simplify routes.
+ for (ConnRefList::const_iterator curr = m_router->connRefs.begin();
+ curr != m_router->connRefs.end(); ++curr)
+ {
+ if ((*curr)->routingType() != ConnType_Orthogonal)
+ {
+ continue;
+ }
+ (*curr)->set_route((*curr)->displayRoute().simplify());
+ }
+}
+
+
+// Populates m_point_orders and m_shared_path_connectors_with_common_endpoints.
+void ImproveOrthogonalRoutes::buildOrthogonalNudgingOrderInfo(void)
+{
+ // Simplify routes.
+ simplifyOrthogonalRoutes();
+
+ int crossingsN = 0;
+
+ bool buildSharedPathInfo = false;
+ if (!m_router->routingOption(Avoid::nudgeSharedPathsWithCommonEndPoint) &&
+ m_shared_path_connectors_with_common_endpoints.empty())
+ {
+ // We're not going to nudge apart shared paths with common ends so we
+ // will need to store information about this during the crossing
+ // detection.
+ buildSharedPathInfo = true;
+ }
+
+
+ // Make a vector of the ConnRefList, for convenience.
+ ConnRefVector connRefs(m_router->connRefs.begin(), m_router->connRefs.end());
+
+ // Make a temporary copy of all the connector displayRoutes.
+ RouteVector connRoutes(connRefs.size());
+ for (size_t ind = 0; ind < connRefs.size(); ++ind)
+ {
+ connRoutes[ind] = connRefs[ind]->displayRoute();
+ }
+
+ // Do segment splitting.
+ for (size_t ind1 = 0; ind1 < connRefs.size(); ++ind1)
+ {
+ ConnRef *conn = connRefs[ind1];
+ if (conn->routingType() != ConnType_Orthogonal)
+ {
+ continue;
+ }
+
+ for (size_t ind2 = 0; ind2 < connRefs.size(); ++ind2)
+ {
+ if (ind1 == ind2)
+ {
+ continue;
+ }
+
+ ConnRef *conn2 = connRefs[ind2];
+ if (conn2->routingType() != ConnType_Orthogonal)
+ {
+ continue;
+ }
+
+ Avoid::Polygon& route = connRoutes[ind1];
+ Avoid::Polygon& route2 = connRoutes[ind2];
+ splitBranchingSegments(route2, true, route);
+ }
+ }
+
+ for (size_t ind1 = 0; ind1 < connRefs.size(); ++ind1)
+ {
+ ConnRef *conn = connRefs[ind1];
+ if (conn->routingType() != ConnType_Orthogonal)
+ {
+ continue;
+ }
+
+ for (size_t ind2 = ind1 + 1; ind2 < connRefs.size(); ++ind2)
+ {
+ ConnRef *conn2 = connRefs[ind2];
+ if (conn2->routingType() != ConnType_Orthogonal)
+ {
+ continue;
+ }
+
+ Avoid::Polygon& route = connRoutes[ind1];
+ Avoid::Polygon& route2 = connRoutes[ind2];
+ int crossings = 0;
+ unsigned int crossingFlags = 0;
+ ConnectorCrossings cross(route2, true, route, conn2, conn);
+ cross.pointOrders = &m_point_orders;
+ for (size_t i = 1; i < route.size(); ++i)
+ {
+ const bool finalSegment = ((i + 1) == route.size());
+ cross.countForSegment(i, finalSegment);
+
+ crossings += cross.crossingCount;
+ crossingFlags |= cross.crossingFlags;
+ }
+ if (crossings > 0)
+ {
+ crossingsN += crossings;
+ }
+
+ if (buildSharedPathInfo &&
+ (crossingFlags & CROSSING_SHARES_PATH_AT_END))
+ {
+ // Record if these two connectors have a shared path with a
+ // common end point.
+ m_shared_path_connectors_with_common_endpoints.insert(
+ UnsignedPair(conn->id(), conn2->id()));
+ }
+ }
+ }
+}
+
+
+extern void improveOrthogonalRoutes(Router *router)
+{
+ ImproveOrthogonalRoutes improver(router);
+ improver.execute();
+}
+
+
+}
diff --git a/src/3rdparty/adaptagrams/libavoid/orthogonal.h b/src/3rdparty/adaptagrams/libavoid/orthogonal.h
new file mode 100644
index 0000000..00ee465
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/orthogonal.h
@@ -0,0 +1,39 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2009-2011 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+
+#ifndef AVOID_ORTHOGONAL_H
+#define AVOID_ORTHOGONAL_H
+
+namespace Avoid {
+
+class Router;
+
+extern void generateStaticOrthogonalVisGraph(Router *router);
+extern void improveOrthogonalRoutes(Router *router);
+
+
+}
+
+#endif
diff --git a/src/3rdparty/adaptagrams/libavoid/router.cpp b/src/3rdparty/adaptagrams/libavoid/router.cpp
new file mode 100644
index 0000000..f10e933
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/router.cpp
@@ -0,0 +1,3131 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+
+#include <algorithm>
+#include <cmath>
+#include <cfloat>
+
+#include "libavoid/shape.h"
+#include "libavoid/router.h"
+#include "libavoid/visibility.h"
+#include "libavoid/connector.h"
+#include "libavoid/junction.h"
+#include "libavoid/viscluster.h"
+#include "libavoid/connend.h"
+#include "libavoid/debug.h"
+#include "libavoid/orthogonal.h"
+#include "libavoid/assertions.h"
+#include "libavoid/connectionpin.h"
+
+
+namespace Avoid {
+
+
+Router::Router(const unsigned int flags)
+ : visOrthogGraph(),
+ PartialTime(false),
+ SimpleRouting(false),
+ ClusteredRouting(true),
+ // Poly-line algorithm options:
+ IgnoreRegions(true),
+ UseLeesAlgorithm(true),
+ InvisibilityGrph(true),
+ // General algorithm options:
+ SelectiveReroute(true),
+ PartialFeedback(false),
+ RubberBandRouting(false),
+ // Instrumentation:
+ st_checked_edges(0),
+ m_largest_assigned_id(0),
+ m_consolidate_actions(true),
+ m_currently_calling_destructors(false),
+ m_topology_addon(new TopologyAddonInterface()),
+ // Mode options:
+ m_allows_polyline_routing(false),
+ m_allows_orthogonal_routing(false),
+ m_static_orthogonal_graph_invalidated(true),
+ m_in_crossing_rerouting_stage(false),
+ m_settings_changes(false),
+ m_debug_handler(nullptr)
+{
+ // At least one of the Routing modes must be set.
+ COLA_ASSERT(flags & (PolyLineRouting | OrthogonalRouting));
+
+ if (flags & PolyLineRouting)
+ {
+ m_allows_polyline_routing = true;
+ }
+ if (flags & OrthogonalRouting)
+ {
+ m_allows_orthogonal_routing = true;
+ }
+
+ for (size_t p = 0; p < lastRoutingParameterMarker; ++p)
+ {
+ m_routing_parameters[p] = 0.0;
+ }
+ m_routing_parameters[segmentPenalty] = 10;
+ m_routing_parameters[clusterCrossingPenalty] = 4000;
+ m_routing_parameters[idealNudgingDistance] = 4.0;
+
+ m_routing_options[nudgeOrthogonalSegmentsConnectedToShapes] = false;
+ m_routing_options[improveHyperedgeRoutesMovingJunctions] = true;
+ m_routing_options[penaliseOrthogonalSharedPathsAtConnEnds] = false;
+ m_routing_options[nudgeOrthogonalTouchingColinearSegments] = false;
+ m_routing_options[performUnifyingNudgingPreprocessingStep] = true;
+ m_routing_options[improveHyperedgeRoutesMovingAddingAndDeletingJunctions] =
+ false;
+ m_routing_options[nudgeSharedPathsWithCommonEndPoint] = true;
+
+ m_hyperedge_improver.setRouter(this);
+ m_hyperedge_rerouter.setRouter(this);
+}
+
+
+Router::~Router()
+{
+ m_currently_calling_destructors = true;
+
+ // Delete remaining connectors.
+ ConnRefList::iterator conn = connRefs.begin();
+ while (conn != connRefs.end())
+ {
+ db_printf("Deleting connector %u in ~Router()\n", (*conn)->id());
+ delete *conn;
+ conn = connRefs.begin();
+ }
+
+ // Remove remaining obstacles (shapes and junctions).
+ ObstacleList::iterator obstacle = m_obstacles.begin();
+ while (obstacle != m_obstacles.end())
+ {
+ Obstacle *obstaclePtr = *obstacle;
+ ShapeRef *shape = dynamic_cast<ShapeRef *> (obstaclePtr);
+ db_printf("Deleting %s %u in ~Router()\n",
+ (shape) ? "shape" : "junction", obstaclePtr->id());
+ if (obstaclePtr->isActive())
+ {
+ obstaclePtr->removeFromGraph();
+ obstaclePtr->makeInactive();
+ }
+ delete obstaclePtr;
+ obstacle = m_obstacles.begin();
+ }
+ m_currently_calling_destructors = false;
+
+ // Cleanup orphaned orthogonal graph vertices.
+ destroyOrthogonalVisGraph();
+
+ COLA_ASSERT(m_obstacles.size() == 0);
+ COLA_ASSERT(connRefs.size() == 0);
+ COLA_ASSERT(visGraph.size() == 0);
+
+ delete m_topology_addon;
+}
+
+void Router::setDebugHandler(DebugHandler *handler)
+{
+ m_debug_handler = handler;
+}
+
+DebugHandler *Router::debugHandler(void) const
+{
+ return m_debug_handler;
+}
+
+ShapeRef *Router::shapeContainingPoint(const Point& point)
+{
+ // Count points on the border as being inside.
+ bool countBorder = true;
+
+ // Compute enclosing shapes.
+ ObstacleList::const_iterator finish = m_obstacles.end();
+ for (ObstacleList::const_iterator i = m_obstacles.begin(); i != finish; ++i)
+ {
+ ShapeRef *shape = dynamic_cast<ShapeRef *>(*i);
+ if (shape && inPoly(shape->routingPolygon(), point, countBorder))
+ {
+ return shape;
+ }
+ }
+ return nullptr;
+}
+
+void Router::modifyConnector(ConnRef *conn, const unsigned int type,
+ const ConnEnd& connEnd, bool connPinMoveUpdate)
+{
+ ActionInfo modInfo(ConnChange, conn);
+
+ ActionInfoList::iterator found =
+ find(actionList.begin(), actionList.end(), modInfo);
+ if (found == actionList.end())
+ {
+ // Matching action not found, so add.
+ modInfo.conns.push_back(std::make_pair(type, connEnd));
+ actionList.push_back(modInfo);
+ }
+ else
+ {
+ // Update the found action as necessary.
+ found->addConnEndUpdate(type, connEnd, connPinMoveUpdate);
+ }
+
+ if (!m_consolidate_actions)
+ {
+ processTransaction();
+ }
+}
+
+
+void Router::modifyConnector(ConnRef *conn)
+{
+ ActionInfo modInfo(ConnChange, conn);
+
+ ActionInfoList::iterator found =
+ find(actionList.begin(), actionList.end(), modInfo);
+ if (found == actionList.end())
+ {
+ actionList.push_back(modInfo);
+ }
+
+ if (!m_consolidate_actions)
+ {
+ processTransaction();
+ }
+}
+
+
+void Router::modifyConnectionPin(ShapeConnectionPin *pin)
+{
+ ActionInfo modInfo(ConnectionPinChange, pin);
+
+ ActionInfoList::iterator found =
+ find(actionList.begin(), actionList.end(), modInfo);
+ if (found == actionList.end())
+ {
+ actionList.push_back(modInfo);
+ }
+
+ if (!m_consolidate_actions)
+ {
+ processTransaction();
+ }
+}
+
+
+void Router::removeObjectFromQueuedActions(const void *object)
+{
+ for (ActionInfoList::iterator curr = actionList.begin();
+ curr != actionList.end(); )
+ {
+ if (curr->objPtr == object)
+ {
+ curr = actionList.erase(curr);
+ }
+ else
+ {
+ ++curr;
+ }
+ }
+}
+
+
+void Router::addShape(ShapeRef *shape)
+{
+ // There shouldn't be remove events or move events for the same shape
+ // already in the action list.
+ // XXX: Possibly we could handle this by ordering them intelligently.
+ COLA_ASSERT(find(actionList.begin(), actionList.end(),
+ ActionInfo(ShapeRemove, shape)) == actionList.end());
+ COLA_ASSERT(find(actionList.begin(), actionList.end(),
+ ActionInfo(ShapeMove, shape)) == actionList.end());
+
+ ActionInfo addInfo(ShapeAdd, shape);
+
+ ActionInfoList::iterator found =
+ find(actionList.begin(), actionList.end(), addInfo);
+ if (found == actionList.end())
+ {
+ actionList.push_back(addInfo);
+ }
+
+ if (!m_consolidate_actions)
+ {
+ processTransaction();
+ }
+}
+
+
+void Router::deleteShape(ShapeRef *shape)
+{
+ // There shouldn't be add events events for the same shape already
+ // in the action list.
+ // XXX: Possibly we could handle this by ordering them intelligently.
+ COLA_ASSERT(find(actionList.begin(), actionList.end(),
+ ActionInfo(ShapeAdd, shape)) == actionList.end());
+
+ // Delete any ShapeMove entries for this shape in the action list.
+ ActionInfoList::iterator found = find(actionList.begin(),
+ actionList.end(), ActionInfo(ShapeMove, shape));
+ if (found != actionList.end())
+ {
+ actionList.erase(found);
+ }
+
+ // Add the ShapeRemove entry.
+ ActionInfo remInfo(ShapeRemove, shape);
+ found = find(actionList.begin(), actionList.end(), remInfo);
+ if (found == actionList.end())
+ {
+ actionList.push_back(remInfo);
+ }
+
+ if (!m_consolidate_actions)
+ {
+ processTransaction();
+ }
+}
+
+
+void Router::deleteConnector(ConnRef *connector)
+{
+ m_currently_calling_destructors = true;
+ delete connector;
+ m_currently_calling_destructors = false;
+}
+
+void Router::moveShape(ShapeRef *shape, const double xDiff, const double yDiff)
+{
+ ActionInfo moveInfo(ShapeMove, shape, Polygon(), false);
+ ActionInfoList::iterator found =
+ find(actionList.begin(), actionList.end(), moveInfo);
+
+ Polygon newPoly;
+ if (found != actionList.end())
+ {
+ // The shape already has a queued move, so use that shape position.
+ newPoly = found->newPoly;
+ }
+ else
+ {
+ // Just use the existing position.
+ newPoly = shape->polygon();
+ }
+ newPoly.translate(xDiff, yDiff);
+
+ moveShape(shape, newPoly);
+}
+
+
+void Router::markAllObstaclesAsMoved(void)
+{
+ for (ObstacleList::iterator obstacleIt = m_obstacles.begin();
+ obstacleIt != m_obstacles.end(); ++obstacleIt)
+ {
+ ShapeRef *shape = dynamic_cast<ShapeRef *> (*obstacleIt);
+ JunctionRef *junction = dynamic_cast<JunctionRef *> (*obstacleIt);
+ if (shape)
+ {
+ moveShape(shape, 0, 0);
+ }
+ else if (junction)
+ {
+ moveJunction(junction, 0, 0);
+ }
+ }
+}
+
+void Router::moveShape(ShapeRef *shape, const Polygon& newPoly,
+ const bool first_move)
+{
+ // There shouldn't be remove events or add events for the same shape
+ // already in the action list.
+ // XXX: Possibly we could handle this by ordering them intelligently.
+ COLA_ASSERT(find(actionList.begin(), actionList.end(),
+ ActionInfo(ShapeRemove, shape)) == actionList.end());
+
+ ActionInfoList::iterator found = find(actionList.begin(),
+ actionList.end(), ActionInfo(ShapeAdd, shape));
+ if (found != actionList.end())
+ {
+ // The Add is enough, no need for the Move action too.
+ // The shape will be added with it's existing polygon,
+ // so set this to be the newPoly passed for the move.
+ found->shape()->setNewPoly(newPoly);
+ return;
+ }
+
+ ActionInfo moveInfo(ShapeMove, shape, newPoly, first_move);
+ // Sanely cope with the case where the user requests moving the same
+ // shape multiple times before rerouting connectors.
+ found = find(actionList.begin(), actionList.end(), moveInfo);
+
+ if (found != actionList.end())
+ {
+ // Just update the ActionInfo with the second polygon, but
+ // leave the firstMove setting alone.
+ found->newPoly = newPoly;
+ }
+ else
+ {
+ actionList.push_back(moveInfo);
+ }
+
+ if (!m_consolidate_actions)
+ {
+ processTransaction();
+ }
+}
+
+
+void Router::setStaticGraphInvalidated(const bool invalidated)
+{
+ m_static_orthogonal_graph_invalidated = invalidated;
+}
+
+
+void Router::destroyOrthogonalVisGraph(void)
+{
+ // Remove orthogonal visibility graph edges.
+ visOrthogGraph.clear();
+
+ // Remove the now orphaned vertices.
+ VertInf *curr = vertices.shapesBegin();
+ while (curr)
+ {
+ if (curr->orphaned() && (curr->id == dummyOrthogID))
+ {
+ VertInf *following = vertices.removeVertex(curr);
+ delete curr;
+ curr = following;
+ continue;
+ }
+ curr = curr->lstNext;
+ }
+}
+
+
+void Router::regenerateStaticBuiltGraph(void)
+{
+ // Here we do talks involved in updating the static-built visibility
+ // graph (if necessary) before we do any routing.
+ if (m_static_orthogonal_graph_invalidated)
+ {
+ if (m_allows_orthogonal_routing)
+ {
+ destroyOrthogonalVisGraph();
+
+ TIMER_START(this, tmOrthogGraph);
+ // Regenerate a new visibility graph.
+ generateStaticOrthogonalVisGraph(this);
+
+ TIMER_STOP(this);
+ }
+ m_static_orthogonal_graph_invalidated = false;
+ }
+}
+
+
+bool Router::transactionUse(void) const
+{
+ return m_consolidate_actions;
+}
+
+
+void Router::setTransactionUse(const bool transactions)
+{
+ m_consolidate_actions = transactions;
+}
+
+
+// Processes the action list.
+void Router::processActions(void)
+{
+ bool notPartialTime = !(PartialFeedback && PartialTime);
+ bool seenShapeMovesOrDeletes = false;
+
+ m_transaction_start_time = clock();
+ m_abort_transaction = false;
+
+ std::list<unsigned int> deletedObstacles;
+ actionList.sort();
+ ActionInfoList::iterator curr;
+ ActionInfoList::iterator finish = actionList.end();
+ for (curr = actionList.begin(); curr != finish; ++curr)
+ {
+ ActionInfo& actInf = *curr;
+ if (!((actInf.type == ShapeRemove) || (actInf.type == ShapeMove) ||
+ (actInf.type == JunctionRemove) || (actInf.type == JunctionMove)))
+ {
+ // Not a move or remove action, so don't do anything.
+ continue;
+ }
+ seenShapeMovesOrDeletes = true;
+
+ Obstacle *obstacle = actInf.obstacle();
+ ShapeRef *shape = actInf.shape();
+ JunctionRef *junction = actInf.junction();
+ bool isMove = (actInf.type == ShapeMove) ||
+ (actInf.type == JunctionMove);;
+ bool first_move = actInf.firstMove;
+
+ unsigned int pid = obstacle->id();
+
+ // o Remove entries related to this shape's vertices
+ obstacle->removeFromGraph();
+
+ if (SelectiveReroute && (!isMove || notPartialTime || first_move))
+ {
+ markPolylineConnectorsNeedingReroutingForDeletedObstacle(obstacle);
+ }
+
+ adjustContainsWithDel(pid);
+
+ if (isMove)
+ {
+ if (shape)
+ {
+ shape->moveAttachedConns(actInf.newPoly);
+ }
+ else if (junction)
+ {
+ junction->moveAttachedConns(actInf.newPosition);
+ }
+ }
+
+ // Ignore this shape for visibility.
+ // XXX: We don't really need to do this if we're not using Partial
+ // Feedback. Without this the blocked edges still route
+ // around the shape until it leaves the connector.
+ obstacle->makeInactive();
+
+ if (!isMove)
+ {
+ // Free deleted obstacle.
+ m_currently_calling_destructors = true;
+ deletedObstacles.push_back(obstacle->id());
+ delete obstacle;
+ m_currently_calling_destructors = false;
+ }
+ }
+
+ if (seenShapeMovesOrDeletes && m_allows_polyline_routing)
+ {
+ if (InvisibilityGrph)
+ {
+ // Check edges for obstacles that were moved or removed.
+ for (curr = actionList.begin(); curr != finish; ++curr)
+ {
+ ActionInfo& actInf = *curr;
+ if ((actInf.type == ShapeMove) || (actInf.type == JunctionMove))
+ {
+ // o Check all edges that were blocked by moved obstacle.
+ checkAllBlockedEdges(actInf.obstacle()->id());
+ }
+ }
+
+ for (std::list<unsigned int>::iterator it = deletedObstacles.begin();
+ it != deletedObstacles.end(); ++it)
+ {
+ // o Check all edges that were blocked by deleted obstacle.
+ checkAllBlockedEdges(*it);
+ }
+ }
+ else
+ {
+ // check all edges not in graph
+ checkAllMissingEdges();
+ }
+ }
+
+ for (curr = actionList.begin(); curr != finish; ++curr)
+ {
+ ActionInfo& actInf = *curr;
+ if (!((actInf.type == ShapeAdd) || (actInf.type == ShapeMove) ||
+ (actInf.type == JunctionAdd) || (actInf.type == JunctionMove)))
+ {
+ // Not a move or add action, so don't do anything.
+ continue;
+ }
+
+ Obstacle *obstacle = actInf.obstacle();
+ ShapeRef *shape = actInf.shape();
+ JunctionRef *junction = actInf.junction();
+ Polygon& newPoly = actInf.newPoly;
+ bool isMove = (actInf.type == ShapeMove) ||
+ (actInf.type == JunctionMove);
+
+ unsigned int pid = obstacle->id();
+
+ // Restore this shape for visibility.
+ obstacle->makeActive();
+
+ if (isMove)
+ {
+ if (shape)
+ {
+ shape->setNewPoly(newPoly);
+ }
+ else
+ {
+ junction->setPosition(actInf.newPosition);
+ }
+ }
+ const Polygon& shapePoly = obstacle->routingPolygon();
+
+ adjustContainsWithAdd(shapePoly, pid);
+
+ if (m_allows_polyline_routing)
+ {
+ // o Check all visibility edges to see if this one shape
+ // blocks them.
+ if (!isMove || notPartialTime)
+ {
+ newBlockingShape(shapePoly, pid);
+ }
+
+ // o Calculate visibility for the new vertices.
+ if (UseLeesAlgorithm)
+ {
+ obstacle->computeVisibilitySweep();
+ }
+ else
+ {
+ obstacle->computeVisibilityNaive();
+ }
+ obstacle->updatePinPolyLineVisibility();
+ }
+ }
+
+ // Update connector endpoints.
+ for (curr = actionList.begin(); curr != finish; ++curr)
+ {
+ ActionInfo& actInf = *curr;
+ if (actInf.type != ConnChange)
+ {
+ continue;
+ }
+ for (ConnUpdateList::iterator conn = actInf.conns.begin();
+ conn != actInf.conns.end(); ++conn)
+ {
+ actInf.conn()->updateEndPoint(conn->first, conn->second);
+ }
+ }
+ // Clear the actionList.
+ actionList.clear();
+}
+
+bool Router::processTransaction(void)
+{
+ // If SimpleRouting, then don't update here.
+ if ((actionList.empty() && (m_hyperedge_rerouter.count() == 0) &&
+ (m_settings_changes == false)) || SimpleRouting)
+ {
+ return false;
+ }
+ m_settings_changes = false;
+
+ processActions();
+
+ m_static_orthogonal_graph_invalidated = true;
+ rerouteAndCallbackConnectors();
+
+ return true;
+}
+
+
+void Router::addJunction(JunctionRef *junction)
+{
+ // There shouldn't be remove events or move events for the same junction
+ // already in the action list.
+ // XXX: Possibly we could handle this by ordering them intelligently.
+ COLA_ASSERT(find(actionList.begin(), actionList.end(),
+ ActionInfo(JunctionRemove, junction)) == actionList.end());
+ COLA_ASSERT(find(actionList.begin(), actionList.end(),
+ ActionInfo(JunctionMove, junction)) == actionList.end());
+
+ ActionInfo addInfo(JunctionAdd, junction);
+
+ ActionInfoList::iterator found =
+ find(actionList.begin(), actionList.end(), addInfo);
+ if (found == actionList.end())
+ {
+ actionList.push_back(addInfo);
+ }
+
+ if (!m_consolidate_actions)
+ {
+ processTransaction();
+ }
+}
+
+
+void Router::deleteJunction(JunctionRef *junction)
+{
+ // There shouldn't be add events events for the same junction already
+ // in the action list.
+ // XXX: Possibly we could handle this by ordering them intelligently.
+ COLA_ASSERT(find(actionList.begin(), actionList.end(),
+ ActionInfo(JunctionAdd, junction)) == actionList.end());
+
+ // Delete any ShapeMove entries for this shape in the action list.
+ ActionInfoList::iterator found = find(actionList.begin(),
+ actionList.end(), ActionInfo(JunctionMove, junction));
+ if (found != actionList.end())
+ {
+ actionList.erase(found);
+ }
+
+ // Add the ShapeRemove entry.
+ ActionInfo remInfo(JunctionRemove, junction);
+ found = find(actionList.begin(), actionList.end(), remInfo);
+ if (found == actionList.end())
+ {
+ actionList.push_back(remInfo);
+ }
+
+ if (!m_consolidate_actions)
+ {
+ processTransaction();
+ }
+}
+
+
+void Router::moveJunction(JunctionRef *junction, const double xDiff,
+ const double yDiff)
+{
+ ActionInfo moveInfo(JunctionMove, junction, Point());
+ ActionInfoList::iterator found =
+ find(actionList.begin(), actionList.end(), moveInfo);
+
+ Point newPosition;
+ if (found != actionList.end())
+ {
+ // The junction already has a queued move, so use that position.
+ newPosition = found->newPosition;
+ }
+ else
+ {
+ // Just use the existing position.
+ newPosition = junction->position();
+ }
+ newPosition.x += xDiff;
+ newPosition.y += yDiff;
+
+ moveJunction(junction, newPosition);
+}
+
+
+void Router::moveJunction(JunctionRef *junction, const Point& newPosition)
+{
+ // There shouldn't be remove events or add events for the same junction
+ // already in the action list.
+ // XXX: Possibly we could handle this by ordering them intelligently.
+ COLA_ASSERT(find(actionList.begin(), actionList.end(),
+ ActionInfo(JunctionRemove, junction)) == actionList.end());
+
+ ActionInfoList::iterator found = find(actionList.begin(),
+ actionList.end(), ActionInfo(JunctionAdd, junction));
+ if (found != actionList.end())
+ {
+ // The Add is enough, no need for the Move action too.
+ // The junction will be added with the new position.
+ found->junction()->setPosition(newPosition);
+ return;
+ }
+
+ ActionInfo moveInfo(JunctionMove, junction, newPosition);
+ // Sanely cope with the case where the user requests moving the same
+ // shape multiple times before rerouting connectors.
+ found = find(actionList.begin(), actionList.end(), moveInfo);
+
+ if (found != actionList.end())
+ {
+ // Just update the ActionInfo with the second position.
+ found->newPosition = newPosition;
+ }
+ else
+ {
+ actionList.push_back(moveInfo);
+ }
+
+ if (!m_consolidate_actions)
+ {
+ processTransaction();
+ }
+}
+
+void Router::addCluster(ClusterRef *cluster)
+{
+ cluster->makeActive();
+
+ unsigned int pid = cluster->id();
+ ReferencingPolygon& poly = cluster->polygon();
+
+ adjustClustersWithAdd(poly, pid);
+}
+
+
+void Router::deleteCluster(ClusterRef *cluster)
+{
+ cluster->makeInactive();
+
+ unsigned int pid = cluster->id();
+
+ adjustClustersWithDel(pid);
+}
+
+
+unsigned int Router::newObjectId(void) const
+{
+ return m_largest_assigned_id + 1;
+}
+
+
+unsigned int Router::assignId(const unsigned int suggestedId)
+{
+ // If the suggestedId is zero, then we assign the object the next
+ // smallest unassigned ID, otherwise we trust the ID given is unique.
+ unsigned int assignedId = (suggestedId == 0) ? newObjectId() : suggestedId;
+
+ // If assertions are enabled, then we check that this ID really is unique.
+ COLA_ASSERT(objectIdIsUnused(assignedId));
+
+ // Have the router record if this ID is larger than the largest assigned ID.
+ m_largest_assigned_id = std::max(m_largest_assigned_id, assignedId);
+
+ return assignedId;
+}
+
+
+ // Returns whether the given ID is unique among all objects known by the
+ // router. It is expected this is only going to be called from assertions
+ // while debugging, so efficiency is not an issue and we just iterate over
+ // all objects.
+bool Router::objectIdIsUnused(const unsigned int id) const
+{
+ // Examine shapes/junctions.
+ for (ObstacleList::const_iterator i = m_obstacles.begin();
+ i != m_obstacles.end(); ++i)
+ {
+ if ((*i)->id() == id)
+ {
+ return false;
+ }
+ }
+
+ // Examine connectors.
+ for (ConnRefList::const_iterator i = connRefs.begin();
+ i != connRefs.end(); ++i)
+ {
+ if ((*i)->id() == id)
+ {
+ return false;
+ }
+ }
+
+ // Examine clusters.
+ for (ClusterRefList::const_iterator i = clusterRefs.begin();
+ i != clusterRefs.end(); ++i)
+ {
+ if ((*i)->id() == id)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+//----------------------------------------------------------------------------
+
+ // Returns a list of connector Ids of all the connectors of type
+ // 'type' attached to the shape with the ID 'shapeId'.
+void Router::attachedConns(IntList &conns, const unsigned int shapeId,
+ const unsigned int type)
+{
+ ConnRefList::const_iterator fin = connRefs.end();
+ for (ConnRefList::const_iterator i = connRefs.begin(); i != fin; ++i)
+ {
+ std::pair<Obstacle *, Obstacle *> anchors = (*i)->endpointAnchors();
+
+ if ((type & runningTo) &&
+ (anchors.second && (anchors.second->id() == shapeId)))
+ {
+ conns.push_back((*i)->id());
+ }
+ else if ((type & runningFrom) &&
+ (anchors.first && (anchors.first->id() == shapeId)))
+ {
+ conns.push_back((*i)->id());
+ }
+ }
+}
+
+
+ // Returns a list of shape Ids of all the shapes attached to the
+ // shape with the ID 'shapeId' with connection type 'type'.
+void Router::attachedShapes(IntList &shapes, const unsigned int shapeId,
+ const unsigned int type)
+{
+ ConnRefList::const_iterator fin = connRefs.end();
+ for (ConnRefList::const_iterator i = connRefs.begin(); i != fin; ++i)
+ {
+ std::pair<Obstacle *, Obstacle *> anchors = (*i)->endpointAnchors();
+
+ if ((type & runningTo) &&
+ (anchors.second && (anchors.second->id() == shapeId)))
+ {
+ if (anchors.first)
+ {
+ // Only if there is a shape attached to the other end.
+ shapes.push_back(anchors.first->id());
+ }
+ }
+ else if ((type & runningFrom) &&
+ (anchors.first && (anchors.first->id() == shapeId)))
+ {
+ if (anchors.second)
+ {
+ // Only if there is a shape attached to the other end.
+ shapes.push_back(anchors.second->id());
+ }
+ }
+ }
+}
+
+
+ // It's intended this function is called after visibility changes
+ // resulting from shape movement have happened. It will alert
+ // rerouted connectors (via a callback) that they need to be redrawn.
+void Router::rerouteAndCallbackConnectors(void)
+{
+ ConnRefList reroutedConns;
+ ConnRefList::const_iterator fin = connRefs.end();
+
+ this->m_conn_reroute_flags.alertConns();
+
+ // Updating the orthogonal visibility graph if necessary.
+ regenerateStaticBuiltGraph();
+
+ for (ConnRefList::const_iterator i = connRefs.begin(); i != fin; ++i)
+ {
+ (*i)->freeActivePins();
+ }
+
+ // Calculate and return connectors that are part of hyperedges and will
+ // be completely rerouted by that code and thus don't need to have routes
+ // generated here.
+ ConnRefSet hyperedgeConns =
+ m_hyperedge_rerouter.calcHyperedgeConnectors();
+
+ // TODO: It might be worth sorting connectors and routing them from
+ // smallest to largest estimated cost. This way we likely get
+ // better exclusive pin assignment during initial routing.
+
+ size_t totalConns = connRefs.size();
+ size_t numOfReroutedConns = 0;
+ for (ConnRefList::const_iterator i = connRefs.begin(); i != fin; ++i)
+ {
+ // Progress reporting and continuation check.
+ performContinuationCheck(TransactionPhaseRouteSearch,
+ numOfReroutedConns, totalConns);
+ ++numOfReroutedConns;
+
+ ConnRef *connector = *i;
+ if (hyperedgeConns.find(connector) != hyperedgeConns.end())
+ {
+ // This will be rerouted by the hyperedge code, so do nothing.
+ continue;
+ }
+
+ if (connector->hasFixedRoute())
+ {
+ // We don't reroute connectors with fixed routes.
+ continue;
+ }
+
+ TIMER_START(this, tmOrthogRoute);
+ connector->m_needs_repaint = false;
+ bool rerouted = connector->generatePath();
+ if (rerouted)
+ {
+ reroutedConns.push_back(connector);
+ }
+ TIMER_STOP(this);
+ }
+
+
+ // Perform any complete hyperedge rerouting that has been requested.
+ m_hyperedge_rerouter.performRerouting();
+
+ // Find and reroute crossing connectors if crossing penalties are set.
+ improveCrossings();
+
+ bool withMinorImprovements = routingOption(
+ improveHyperedgeRoutesMovingJunctions);
+ bool withMajorImprovements = routingOption(
+ improveHyperedgeRoutesMovingAddingAndDeletingJunctions);
+ if (withMinorImprovements || withMajorImprovements)
+ {
+ m_hyperedge_improver.clear();
+ m_hyperedge_improver.execute(withMajorImprovements);
+ }
+
+ // Perform centring and nudging for orthogonal routes.
+ improveOrthogonalRoutes(this);
+
+ // Find a list of all the deleted connectors in hyperedges.
+ HyperedgeNewAndDeletedObjectLists changedHyperedgeObjs =
+ m_hyperedge_improver.newAndDeletedObjectLists();
+ ConnRefList deletedConns = changedHyperedgeObjs.deletedConnectorList;
+ for (size_t index = 0; index < m_hyperedge_rerouter.count(); ++index)
+ {
+ changedHyperedgeObjs =
+ m_hyperedge_rerouter.newAndDeletedObjectLists(index);
+ deletedConns.merge(changedHyperedgeObjs.deletedConnectorList);
+ }
+
+ // Alert connectors that they need redrawing.
+ fin = reroutedConns.end();
+ for (ConnRefList::const_iterator i = reroutedConns.begin(); i != fin; ++i)
+ {
+ ConnRef *conn = *i;
+
+ // Skip hyperedge connectors which have been deleted.
+ ConnRefList::iterator findIt = std::find(
+ deletedConns.begin(), deletedConns.end(), conn);
+ if (findIt != deletedConns.end())
+ {
+ // Connector deleted, skip.
+ continue;
+ }
+
+ conn->m_needs_repaint = true;
+ conn->performCallback();
+ }
+
+ // Progress reporting.
+ performContinuationCheck(TransactionPhaseCompleted, 1, 1);
+}
+
+// Type holding a cost estimate and ConnRef.
+typedef std::pair<double, ConnRef *> ConnCostRef;
+
+// A comparison class used to order a set of ConnCostRefs.
+class CmpConnCostRef
+{
+ public:
+ CmpConnCostRef()
+ {
+ }
+ bool operator() (const ConnCostRef& u, const ConnCostRef& v) const
+ {
+ return (u.second->id() < v.second->id());
+ }
+};
+
+typedef std::set<ConnCostRef, CmpConnCostRef> ConnCostRefSet;
+typedef std::list<ConnCostRefSet> ConnCostRefSetList;
+
+
+static double cheapEstimatedCost(ConnRef *lineRef)
+{
+ // We use an estimate of overall connector length, reduced by a count
+ // of the number of segments. In the case of equal length, This causes
+ // straight line connectors to be left alone and connectors with more
+ // complex paths to be rerouted.
+ bool isPolyLine = (lineRef->routingType() == ConnType_PolyLine);
+ const PolyLine& route = lineRef->displayRoute();
+ double length = 0;
+
+ for (size_t i = 1; i < route.size(); ++i)
+ {
+ const Point& a = route.ps[i - 1];
+ const Point& b = route.ps[i];
+
+ double segmentLength = (isPolyLine) ?
+ euclideanDist(a, b) : manhattanDist(a, b);
+ length += segmentLength;
+ }
+ return length - (route.size() + 1);
+}
+
+// A map of connectors to the set of connectors that cross them.
+typedef std::map<ConnRef *, std::set<ConnRef *> > CrossingConnectorsMap;
+
+// A list of connector crossing maps that don't interact with each other.
+typedef std::list<CrossingConnectorsMap> CrossingConnectorsMapList;
+
+// This class maintains the list of connector crossing maps and provides
+// methods for adding crossing connector pairs and getting the minimal sets
+// of connectors that can be removed from each group to prevent crossings.
+class CrossingConnectorsInfo
+{
+ public:
+
+ // Add information that a pair of connectors cross.
+ void addCrossing(ConnRef *conn1, ConnRef *conn2)
+ {
+ // Find the existing or new group that this crossing
+ // should be recorded in.
+ CrossingConnectorsMapList::iterator it =
+ groupForCrossingConns(conn1, conn2);
+ CrossingConnectorsMap& pairsSet = *it;
+
+ // Record the crossing.
+ pairsSet[conn1].insert(conn2);
+ pairsSet[conn2].insert(conn1);
+ }
+
+ // This method builds and returns a list of non-interacting sets of
+ // connectors (with crossing counts) that need to be removed so there
+ // are no crossings. These are the connectors we reroute. Where
+ // these connectors attach to exclusive connection pins, we return
+ // and thus reroute all connectors attached to the exlcusive pins. We
+ // do this so we are no so committed to possible bad pin assignemnts.
+ ConnCostRefSetList crossingSetsListToRemoveCrossingsFromGroups(void)
+ {
+ // A list of the minimal sets of connectors that cause crossings
+ // in all groups of crossingconnectors.
+ ConnCostRefSetList crossingSetsList;
+
+ // For each group of crossing connectors.
+ for (CrossingConnectorsMapList::iterator it = pairsSetList.begin();
+ it != pairsSetList.end(); ++it)
+ {
+ // The minimal set of crossing-causing connectors.
+ // We will build this.
+ ConnCostRefSet crossingSet;
+
+ // Set of exclusive pins that the crossing-causing connectors
+ // attach to.
+ std::set<ConnectionPinIds> exclusivePins;
+
+ // The group of all crossing pairs.
+ CrossingConnectorsMap& pairsSet = *it;
+
+ // For each crossing-causing connector.
+ ConnCostRef crossingCausingConnector;
+ while ( (crossingCausingConnector =
+ removeConnectorWithMostCrossings(pairsSet)).second != nullptr )
+ {
+ // Add it to our crossing-causing set.
+ crossingSet.insert(crossingCausingConnector);
+
+ // Determine if it attaches to any exclusive pins and
+ // record these.
+ std::pair<ConnEnd, ConnEnd> ends =
+ crossingCausingConnector.second->endpointConnEnds();
+ // Look at one end.
+ ShapeConnectionPin *pin = ends.first.m_active_pin;
+ if (pin && pin->isExclusive())
+ {
+ exclusivePins.insert(pin->ids());
+ }
+ // Look at other end.
+ pin = ends.second.m_active_pin;
+ if (pin && pin->isExclusive())
+ {
+ exclusivePins.insert(pin->ids());
+ }
+ }
+
+ // For each of the remaining connectors which are not
+ // crossing-causing, add them to our crossing set if they
+ // attach to one of the exclusive pin classes which the
+ // crossing-causing connectors attached to.
+ for (CrossingConnectorsMap::const_iterator it2 =
+ pairsSet.begin(); it2 != pairsSet.end(); ++it2)
+ {
+ ConnRef *conn = it2->first;
+ std::pair<ConnEnd, ConnEnd> ends = conn->endpointConnEnds();
+ // Look at one end.
+ ShapeConnectionPin *pin = ends.first.m_active_pin;
+ if (pin && pin->isExclusive())
+ {
+ if (exclusivePins.count(pin->ids()) > 0)
+ {
+ // Attaches to an exclusive pin and it matches
+ // one attached to by the crossing-causing
+ // connectors. So add the conn to the
+ // crossing set and continue..
+ crossingSet.insert(std::make_pair(0, conn));
+ continue;
+ }
+ }
+ // Look at other end.
+ pin = ends.second.m_active_pin;
+ if (pin && pin->isExclusive())
+ {
+ if (exclusivePins.count(pin->ids()) > 0)
+ {
+ // Attaches to an exclusive pin and it matches
+ // one attached to by the crossing-causing
+ // connectors. So add the conn to the
+ // crossing set.
+ crossingSet.insert(std::make_pair(0, conn));
+ }
+ }
+ }
+
+ if (!crossingSet.empty())
+ {
+ crossingSetsList.push_back(crossingSet);
+ }
+ }
+ return crossingSetsList;
+ }
+
+ // Returns whether this pair of connector is already known to cross.
+ bool connsKnownToCross(ConnRef *conn1, ConnRef *conn2)
+ {
+ CrossingConnectorsMapList::iterator it1 = groupForConn(conn1);
+ CrossingConnectorsMapList::iterator it2 = groupForConn(conn2);
+
+ // The connectors cross if
+ if ((it1 == it2) && (it1 != pairsSetList.end()))
+ {
+ // They are in the same group and conn2 is in crossing
+ // connectors set of conn1.
+ CrossingConnectorsMap& pairsSet = *it1;
+ return ((pairsSet.count(conn1) > 0) &&
+ (pairsSet[conn1].count(conn2) > 0));
+ }
+ return false;
+ }
+
+ private:
+
+ // Given a particular group (pairsSet), removes the connector with
+ // the most crossings withing the group and returns it along with its
+ // crossing count.
+ ConnCostRef removeConnectorWithMostCrossings(
+ CrossingConnectorsMap& pairsSet)
+ {
+ // Tracking of the greatest number of crossings.
+ ConnRef *candidateConnector = nullptr;
+ size_t candidateCrossingCount = 0;
+ double candidateEstimatedCost = 0;
+
+ // For each connector in the group...
+ for (CrossingConnectorsMap::const_iterator it = pairsSet.begin();
+ it != pairsSet.end(); ++it)
+ {
+ // ... check if it has any crossings.
+ size_t crossings = it->second.size();
+ if (crossings == 0)
+ {
+ // If not, skip.
+ continue;
+ }
+
+ // It has crossings. Determine if it has the most crossings
+ // of the connectors we've seen, or if it is tied but has
+ // a greater estimated cost. If so, it is our new candidate.
+ double cost = cheapEstimatedCost(it->first);
+ if ((crossings > candidateCrossingCount) ||
+ ((crossings == candidateCrossingCount) &&
+ (cost > candidateEstimatedCost)))
+ {
+ // Update with new candidate.
+ candidateConnector = it->first;
+ candidateCrossingCount = crossings;
+ candidateEstimatedCost = cost;
+ }
+ }
+
+ if (candidateConnector == nullptr)
+ {
+ // If no candidate, return nullptr connector.
+ return std::make_pair(0, (ConnRef *) nullptr);
+ }
+
+ // Remove the candidate from the group. To do this we find the
+ // set of all connectors it crosses.
+ std::set<ConnRef *>& connSet = pairsSet[candidateConnector];
+ // For each of these
+ for (std::set<ConnRef *>::const_iterator it = connSet.begin();
+ it != connSet.end(); ++it)
+ {
+ // we remove the candidate from their crossing lists
+ pairsSet[*it].erase(candidateConnector);
+ }
+ // And then clear the crossing list for the candidate itself.
+ connSet.clear();
+
+ // Return the candidate connector and its original crossing count.
+ return std::make_pair(static_cast<double>(candidateCrossingCount), candidateConnector);
+ }
+
+ // Returns the iterator to the group that the given conn is in,
+ // if it is part of any crossing group.
+ CrossingConnectorsMapList::iterator groupForConn(ConnRef *conn)
+ {
+ // For each group...
+ for (CrossingConnectorsMapList::iterator it = pairsSetList.begin();
+ it != pairsSetList.end(); ++it)
+ {
+ // ... check if the connector is in it.
+ if (it->count(conn) > 0)
+ {
+ // If so, return it.
+ return it;
+ }
+ }
+ // Connector was not in any existing group.
+ return pairsSetList.end();
+ }
+
+ // Given a pair of crossing connectors, returns an iterator to the
+ // crossing connector group they are part of. If neither are part
+ // of any group, one is created and returned. If one connector is
+ // part of an exisitng group, that group is returned. If they are
+ // part of two different groups, the groups are merged and the
+ // merged group is returned.
+ CrossingConnectorsMapList::iterator groupForCrossingConns(
+ ConnRef *conn1, ConnRef *conn2)
+ {
+ CrossingConnectorsMapList::iterator it1 = groupForConn(conn1);
+ CrossingConnectorsMapList::iterator it2 = groupForConn(conn2);
+
+ // groupIt will be the iterator to the appropriate group.
+ CrossingConnectorsMapList::iterator groupIt = pairsSetList.end();
+
+ if ((it1 == pairsSetList.end()) && (it2 == pairsSetList.end()))
+ {
+ // Neither are part of a group. Create one.
+ CrossingConnectorsMap newSet;
+ groupIt = pairsSetList.insert(pairsSetList.end(), newSet);
+ }
+ else if ((it1 != pairsSetList.end()) && (it2 == pairsSetList.end()))
+ {
+ // it1 is the appropriate existing group.
+ groupIt = it1;
+ }
+ else if ((it1 == pairsSetList.end()) && (it2 != pairsSetList.end()))
+ {
+ // it2 is the appropriate exisitng group.
+ groupIt = it2;
+ }
+ else if (it1 != it2)
+ {
+ // There are two different existing groups, so merge them.
+ COLA_ASSERT(it1 != pairsSetList.end());
+ COLA_ASSERT(it2 != pairsSetList.end());
+ it1->insert(it2->begin(), it2->end());
+ pairsSetList.erase(it2);
+ groupIt = it1;
+ }
+ else
+ {
+ // These are already part of the same group. Do nothing.
+ COLA_ASSERT(it1 == it2);
+ groupIt = it1;
+ }
+ return groupIt;
+ }
+
+ CrossingConnectorsMapList pairsSetList;
+};
+
+
+void Router::performContinuationCheck(unsigned int phaseNumber,
+ size_t stepNumber, size_t totalSteps)
+{
+ // Compute the elapsed time in msec since the beginning of the transaction.
+ unsigned int elapsedMsec = (unsigned int)
+ ((clock() - m_transaction_start_time) /
+ (CLOCKS_PER_SEC / (double) 1000));
+
+ bool shouldContinue = shouldContinueTransactionWithProgress(elapsedMsec,
+ phaseNumber, TransactionPhaseCompleted,
+ stepNumber / (double)totalSteps);
+ if (shouldContinue == false)
+ {
+ // Host program has asked us not to continue the transaction.
+ m_abort_transaction = true;
+ }
+}
+
+
+bool Router::shouldContinueTransactionWithProgress(unsigned int elapsedTime,
+ unsigned int phaseNumber, unsigned int totalPhases,
+ double proportion)
+{
+ COLA_UNUSED(elapsedTime);
+ COLA_UNUSED(phaseNumber);
+ COLA_UNUSED(totalPhases);
+ COLA_UNUSED(proportion);
+
+#if 0
+ printf("Progress: %8u, phase %u of %u... %.2f%%\n", elapsedTime,
+ phaseNumber, totalPhases, proportion * 100);
+#endif
+
+ // We always continue. Subclasses can override this behaviour.
+ return true;
+}
+
+
+class CmpOrderedConnCostRef
+{
+ public:
+ CmpOrderedConnCostRef()
+ {
+ }
+ bool operator() (const ConnCostRef& u, const ConnCostRef& v) const
+ {
+ return (u.first < v.first);
+ }
+};
+typedef std::list<ConnCostRef> ConnCostRefList;
+
+
+void Router::improveCrossings(void)
+{
+ const double crossing_penalty = routingParameter(crossingPenalty);
+ const double shared_path_penalty = routingParameter(fixedSharedPathPenalty);
+ if ((crossing_penalty == 0) && (shared_path_penalty == 0))
+ {
+ // No penalties, return.
+ return;
+ }
+
+ // Information on crossing connector groups.
+ CrossingConnectorsInfo crossingConnInfo;
+
+ size_t numOfConns = connRefs.size();
+ size_t numOfConnsChecked = 0;
+
+ // Find crossings and reroute connectors.
+ m_in_crossing_rerouting_stage = true;
+ ConnRefList::iterator fin = connRefs.end();
+ for (ConnRefList::iterator i = connRefs.begin(); i != fin; ++i)
+ {
+ // Progress reporting and continuation check.
+ ++numOfConnsChecked;
+ performContinuationCheck(TransactionPhaseCrossingDetection,
+ numOfConnsChecked, numOfConns);
+ if (m_abort_transaction)
+ {
+ m_in_crossing_rerouting_stage = false;
+ return;
+ }
+
+ Avoid::Polygon& iRoute = (*i)->routeRef();
+ if (iRoute.size() == 0)
+ {
+ // Rerouted hyperedges will have an empty route.
+ // We can't reroute these.
+ continue;
+ }
+ ConnRefList::iterator j = i;
+ for (++j; j != fin; ++j)
+ {
+ if (crossingConnInfo.connsKnownToCross(*i, *j))
+ {
+ // We already know both these have crossings.
+ continue;
+ }
+
+ // Determine if this pair cross.
+ Avoid::Polygon& jRoute = (*j)->routeRef();
+ ConnectorCrossings cross(iRoute, true, jRoute, *i, *j);
+ for (size_t jInd = 1; jInd < jRoute.size(); ++jInd)
+ {
+ const bool finalSegment = ((jInd + 1) == jRoute.size());
+ cross.countForSegment(jInd, finalSegment);
+
+ if ((shared_path_penalty > 0) &&
+ (cross.crossingFlags & CROSSING_SHARES_PATH) &&
+ (cross.crossingFlags & CROSSING_SHARES_FIXED_SEGMENT) &&
+ (m_routing_options[penaliseOrthogonalSharedPathsAtConnEnds] ||
+ !(cross.crossingFlags & CROSSING_SHARES_PATH_AT_END)))
+ {
+ // We are penalising fixedSharedPaths and there is a
+ // fixedSharedPath.
+ crossingConnInfo.addCrossing(*i, *j);
+ break;
+ }
+ else if ((crossing_penalty > 0) && (cross.crossingCount > 0))
+ {
+ // We are penalising crossings and this is a crossing.
+ crossingConnInfo.addCrossing(*i, *j);
+ break;
+ }
+ }
+ }
+ }
+
+ // Find the list of connector sets that need to be removed to avoid any
+ // crossings in all crossing groups. This is our candidate set for
+ // rerouting. Where these connectors connect to exlusive pins, all
+ // connectors attached to exclusive pins with the same IDs will also
+ // be rerouted, starting with the shortest.
+ ConnCostRefSetList crossingConnsGroups =
+ crossingConnInfo.crossingSetsListToRemoveCrossingsFromGroups();
+
+ // At this point we have a list containing crossings for rerouting.
+ // We do this rerouting via two passes, for each group of interacting
+ // crossing connectors:
+ // 1) clear existing routes and free pin assignments, and
+ // 2) compute new routes.
+ unsigned int numOfConnsToReroute = 1;
+ unsigned int numOfConnsRerouted = 1;
+ for (ConnCostRefSetList::iterator setIt = crossingConnsGroups.begin();
+ setIt != crossingConnsGroups.end(); ++setIt)
+ {
+ // Sort the connectors we will be rerouting from lowest to
+ // highest cost.
+ ConnCostRefList orderedConnList(setIt->begin(), setIt->end());
+ orderedConnList.sort(CmpOrderedConnCostRef());
+
+ // Perform rerouting of this set of connectors.
+ for (int pass = 0; pass < 2; ++pass)
+ {
+ for (ConnCostRefList::iterator connIt = orderedConnList.begin();
+ connIt != orderedConnList.end(); ++connIt)
+ {
+ ConnRef *conn = connIt->second;
+ if (pass == 0)
+ {
+ ++numOfConnsToReroute;
+
+ // Mark the fixed shared path as being invalid.
+ conn->makePathInvalid();
+
+ // Free the previous path, so it is not noticed by other
+ // connectors during rerouting.
+ conn->freeRoutes();
+
+ // Free pin assignments.
+ conn->freeActivePins();
+ }
+ else if (pass == 1)
+ {
+ // Progress reporting and continuation check.
+ performContinuationCheck(TransactionPhaseRerouteSearch,
+ numOfConnsRerouted, numOfConnsToReroute);
+ if (m_abort_transaction)
+ {
+ m_in_crossing_rerouting_stage = false;
+ return;
+ }
+ ++numOfConnsRerouted;
+
+ // Recompute this path.
+ conn->generatePath();
+ }
+ }
+ }
+ }
+ m_in_crossing_rerouting_stage = false;
+}
+
+
+void Router::newBlockingShape(const Polygon& poly, int pid)
+{
+ // o Check all visibility edges to see if this one shape
+ // blocks them.
+ EdgeInf *finish = visGraph.end();
+ for (EdgeInf *iter = visGraph.begin(); iter != finish ; )
+ {
+ EdgeInf *tmp = iter;
+ iter = iter->lstNext;
+
+ if (tmp->getDist() != 0)
+ {
+ std::pair<VertID, VertID> ids(tmp->ids());
+ VertID eID1 = ids.first;
+ VertID eID2 = ids.second;
+ std::pair<Point, Point> points(tmp->points());
+ Point e1 = points.first;
+ Point e2 = points.second;
+ bool blocked = false;
+
+ bool countBorder = false;
+ bool ep_in_poly1 = (eID1.isConnPt()) ?
+ inPoly(poly, e1, countBorder) : false;
+ bool ep_in_poly2 = (eID2.isConnPt()) ?
+ inPoly(poly, e2, countBorder) : false;
+ if (ep_in_poly1 || ep_in_poly2)
+ {
+ // Don't check edges that have a connector endpoint
+ // and are inside the shape being added.
+ continue;
+ }
+
+ bool seenIntersectionAtEndpoint = false;
+ for (size_t pt_i = 0; pt_i < poly.size(); ++pt_i)
+ {
+ size_t pt_n = (pt_i == (poly.size() - 1)) ? 0 : pt_i + 1;
+ const Point& pi = poly.ps[pt_i];
+ const Point& pn = poly.ps[pt_n];
+ if (segmentShapeIntersect(e1, e2, pi, pn,
+ seenIntersectionAtEndpoint))
+ {
+ blocked = true;
+ break;
+ }
+ }
+ if (blocked)
+ {
+ db_printf("\tRemoving newly blocked edge (by shape %3d)"
+ "... \n\t\t", pid);
+ tmp->alertConns();
+ tmp->db_print();
+ if (InvisibilityGrph)
+ {
+ tmp->addBlocker(pid);
+ }
+ else
+ {
+ delete tmp;
+ }
+ }
+ }
+ }
+}
+
+
+void Router::checkAllBlockedEdges(int pid)
+{
+ COLA_ASSERT(InvisibilityGrph);
+
+ for (EdgeInf *iter = invisGraph.begin(); iter != invisGraph.end() ; )
+ {
+ EdgeInf *tmp = iter;
+ iter = iter->lstNext;
+
+ if (tmp->blocker() == -1)
+ {
+ tmp->alertConns();
+ tmp->checkVis();
+ }
+ else if (tmp->blocker() == pid)
+ {
+ tmp->checkVis();
+ }
+ }
+}
+
+
+void Router::checkAllMissingEdges(void)
+{
+ COLA_ASSERT(!InvisibilityGrph);
+
+ VertInf *first = vertices.connsBegin();
+
+ VertInf *pend = vertices.end();
+ for (VertInf *i = first; i != pend; i = i->lstNext)
+ {
+ VertID iID = i->id;
+
+ // Check remaining, earlier vertices
+ for (VertInf *j = first ; j != i; j = j->lstNext)
+ {
+ VertID jID = j->id;
+ if (iID.isConnPt() && !iID.isConnectionPin() &&
+ (iID.objID != jID.objID))
+ {
+ // Don't keep visibility between edges of different conns
+ continue;
+ }
+
+ // See if the edge is already there?
+ bool found = (EdgeInf::existingEdge(i, j) != nullptr);
+
+ if (!found)
+ {
+ // Didn't already exist, check.
+ bool knownNew = true;
+ EdgeInf::checkEdgeVisibility(i, j, knownNew);
+ }
+ }
+ }
+}
+
+
+void Router::generateContains(VertInf *pt)
+{
+ contains[pt->id].clear();
+ enclosingClusters[pt->id].clear();
+
+ // Don't count points on the border as being inside.
+ bool countBorder = false;
+
+ // Compute enclosing shapes.
+ ObstacleList::const_iterator finish = m_obstacles.end();
+ for (ObstacleList::const_iterator i = m_obstacles.begin(); i != finish; ++i)
+ {
+ if (inPoly((*i)->routingPolygon(), pt->point, countBorder))
+ {
+ contains[pt->id].insert((*i)->id());
+ }
+ }
+
+ // Computer enclosing Clusters
+ ClusterRefList::const_iterator clFinish = clusterRefs.end();
+ for (ClusterRefList::const_iterator i = clusterRefs.begin();
+ i != clFinish; ++i)
+ {
+ if (inPolyGen((*i)->polygon(), pt->point))
+ {
+ enclosingClusters[pt->id].insert((*i)->id());
+ }
+ }
+}
+
+
+void Router::adjustClustersWithAdd(const PolygonInterface& poly,
+ const int p_cluster)
+{
+ for (VertInf *k = vertices.connsBegin(); k != vertices.shapesBegin();
+ k = k->lstNext)
+ {
+ if (inPolyGen(poly, k->point))
+ {
+ enclosingClusters[k->id].insert(p_cluster);
+ }
+ }
+}
+
+
+void Router::adjustClustersWithDel(const int p_cluster)
+{
+ for (ContainsMap::iterator k = enclosingClusters.begin();
+ k != enclosingClusters.end(); ++k)
+ {
+ (*k).second.erase(p_cluster);
+ }
+}
+
+
+void Router::adjustContainsWithAdd(const Polygon& poly, const int p_shape)
+{
+ // Don't count points on the border as being inside.
+ bool countBorder = false;
+
+ for (VertInf *k = vertices.connsBegin(); k != vertices.shapesBegin();
+ k = k->lstNext)
+ {
+ if (inPoly(poly, k->point, countBorder))
+ {
+ contains[k->id].insert(p_shape);
+ }
+ }
+}
+
+
+void Router::adjustContainsWithDel(const int p_shape)
+{
+ for (ContainsMap::iterator k = contains.begin(); k != contains.end(); ++k)
+ {
+ (*k).second.erase(p_shape);
+ }
+}
+
+
+#ifdef SELECTIVE_DEBUG
+static double AngleAFromThreeSides(const double a, const double b,
+ const double c)
+{
+ // returns angle A, the angle opposite from side a, in radians
+ return acos((pow(b, 2) + pow(c, 2) - pow(a, 2)) / (2 * b * c));
+}
+#endif
+
+// Given an deleted obstacle, uses a simple heauristic to determine polyline
+// connectors that may now have a better path through the region occupied by
+// the shape and mark them as needing to be rerouted.
+// See the "Incremental Connector Routing" paper which explains this code.
+//
+void Router::markPolylineConnectorsNeedingReroutingForDeletedObstacle(
+ Obstacle *obstacle)
+{
+ if (RubberBandRouting)
+ {
+ // When rubber-band routing, we do not reroute connectors that
+ // may have a better route, only invalid connectors.
+ return;
+ }
+
+ COLA_ASSERT(SelectiveReroute);
+
+ // For each connector...
+ ConnRefList::const_iterator end = connRefs.end();
+ for (ConnRefList::const_iterator it = connRefs.begin(); it != end; ++it)
+ {
+ ConnRef *conn = (*it);
+
+ if (conn->m_route.empty())
+ {
+ // Ignore uninitialised connectors.
+ continue;
+ }
+ else if (conn->m_needs_reroute_flag)
+ {
+ // Already marked, so skip.
+ continue;
+ }
+ else if (conn->routingType() != ConnType_PolyLine)
+ {
+ // This test only works for polyline connectors, so skip others.
+ continue;
+ }
+
+ Point start = conn->m_route.ps[0];
+ Point end = conn->m_route.ps[conn->m_route.size() - 1];
+
+ double conndist = conn->m_route_dist;
+
+ double estdist;
+ double e1, e2;
+
+ // For each vertex of the obstacle...
+ VertInf *beginV = obstacle->firstVert();
+ VertInf *endV = obstacle->lastVert()->lstNext;
+ for (VertInf *i = beginV; i != endV; i = i->lstNext)
+ {
+ const Point& p1 = i->point;
+ const Point& p2 = i->shNext->point;
+
+ double offy;
+ double a;
+ double b;
+ double c;
+ double d;
+
+ double min;
+ double max;
+
+ if (p1.y == p2.y)
+ {
+ // Standard case
+ offy = p1.y;
+ a = start.x;
+ b = start.y - offy;
+ c = end.x;
+ d = end.y - offy;
+
+ min = std::min(p1.x, p2.x);
+ max = std::max(p1.x, p2.x);
+ }
+ else if (p1.x == p2.x)
+ {
+ // Other Standard case
+ offy = p1.x;
+ a = start.y;
+ b = start.x - offy;
+ c = end.y;
+ d = end.x - offy;
+
+ min = std::min(p1.y, p2.y);
+ max = std::max(p1.y, p2.y);
+ }
+ else
+ {
+ // Need to do rotation
+ Point n_p2(p2.x - p1.x, p2.y - p1.y);
+ Point n_start(start.x - p1.x, start.y - p1.y);
+ Point n_end(end.x - p1.x, end.y - p1.y);
+ //db_printf("n_p2: (%.1f, %.1f)\n", n_p2.x, n_p2.y);
+ //db_printf("n_start: (%.1f, %.1f)\n", n_start.x, n_start.y);
+ //db_printf("n_end: (%.1f, %.1f)\n", n_end.x, n_end.y);
+
+ double theta = 0 - atan2(n_p2.y, n_p2.x);
+ //db_printf("theta = %.2f\n", theta * (180 / PI));
+
+ Point r_p1(0, 0);
+ Point r_p2 = n_p2;
+ start = n_start;
+ end = n_end;
+
+ double cosv = cos(theta);
+ double sinv = sin(theta);
+
+ r_p2.x = cosv * n_p2.x - sinv * n_p2.y;
+ r_p2.y = cosv * n_p2.y + sinv * n_p2.x;
+ start.x = cosv * n_start.x - sinv * n_start.y;
+ start.y = cosv * n_start.y + sinv * n_start.x;
+ end.x = cosv * n_end.x - sinv * n_end.y;
+ end.y = cosv * n_end.y + sinv * n_end.x;
+ //db_printf("r_p2: (%.1f, %.1f)\n", r_p2.x, r_p2.y);
+ //db_printf("r_start: (%.1f, %.1f)\n", start.x, start.y);
+ //db_printf("r_end: (%.1f, %.1f)\n", end.x, end.y);
+
+ // This might be slightly off.
+ if (fabs(r_p2.y) > 0.0001)
+ {
+ db_printf("r_p2.y: %f != 0\n", r_p2.y);
+ }
+ r_p2.y = 0;
+
+ offy = r_p1.y;
+ a = start.x;
+ b = start.y - offy;
+ c = end.x;
+ d = end.y - offy;
+
+ min = std::min(r_p1.x, r_p2.x);
+ max = std::max(r_p1.x, r_p2.x);
+
+ }
+
+ double x;
+ if ((b + d) == 0)
+ {
+ db_printf("WARNING: (b + d) == 0\n");
+ d = d * -1;
+ }
+
+ if ((b == 0) && (d == 0))
+ {
+ db_printf("WARNING: b == d == 0\n");
+ if (((a < min) && (c < min)) ||
+ ((a > max) && (c > max)))
+ {
+ // It's going to get adjusted.
+ x = a;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ else
+ {
+ x = ((b*c) + (a*d)) / (b + d);
+ }
+
+ //db_printf("%.1f, %.1f, %.1f, %.1f\n", a, b, c, d);
+ //db_printf("x = %.1f\n", x);
+
+ x = std::max(min, x);
+ x = std::min(max, x);
+
+ //db_printf("x = %.1f\n", x);
+
+ Point xp;
+ if (p1.x == p2.x)
+ {
+ xp.x = offy;
+ xp.y = x;
+ }
+ else
+ {
+ xp.x = x;
+ xp.y = offy;
+ }
+ //db_printf("(%.1f, %.1f)\n", xp.x, xp.y);
+
+ e1 = euclideanDist(start, xp);
+ e2 = euclideanDist(xp, end);
+ estdist = e1 + e2;
+
+
+ //db_printf("is %.1f < %.1f\n", estdist, conndist);
+ if (estdist < conndist)
+ {
+#ifdef SELECTIVE_DEBUG
+ //double angle = AngleAFromThreeSides(dist(start, end),
+ // e1, e2);
+ db_printf("[%3d] - Possible better path found (%.1f < %.1f)\n",
+ conn->_id, estdist, conndist);
+#endif
+ conn->m_needs_reroute_flag = true;
+ break;
+ }
+
+ }
+ }
+}
+
+
+ConnType Router::validConnType(const ConnType select) const
+{
+ if (select != ConnType_None)
+ {
+ if ((select == ConnType_Orthogonal) && m_allows_orthogonal_routing)
+ {
+ return ConnType_Orthogonal;
+ }
+ else if ((select == ConnType_PolyLine) && m_allows_polyline_routing)
+ {
+ return ConnType_PolyLine;
+ }
+ }
+
+ if (m_allows_polyline_routing)
+ {
+ return ConnType_PolyLine;
+ }
+ else if (m_allows_orthogonal_routing)
+ {
+ return ConnType_Orthogonal;
+ }
+ return ConnType_None;
+}
+
+
+void Router::setRoutingParameter(const RoutingParameter parameter,
+ const double value)
+{
+ COLA_ASSERT(parameter < lastRoutingParameterMarker);
+ if (value < 0)
+ {
+ // Set some sensible parameter value for the parameter being 'active'.
+ switch (parameter)
+ {
+ case segmentPenalty:
+ m_routing_parameters[parameter] = 50;
+ break;
+ case fixedSharedPathPenalty:
+ m_routing_parameters[parameter] = 110;
+ break;
+ case anglePenalty:
+ m_routing_parameters[parameter] = 50;
+ break;
+ case crossingPenalty:
+ m_routing_parameters[parameter] = 200;
+ break;
+ case clusterCrossingPenalty:
+ m_routing_parameters[parameter] = 4000;
+ break;
+ case idealNudgingDistance:
+ m_routing_parameters[parameter] = 4.0;
+ break;
+ case portDirectionPenalty:
+ m_routing_parameters[parameter] = 100;
+ break;
+ default:
+ m_routing_parameters[parameter] = 50;
+ break;
+ }
+ }
+ else
+ {
+ m_routing_parameters[parameter] = value;
+ }
+ m_settings_changes = true;
+}
+
+
+double Router::routingParameter(const RoutingParameter parameter) const
+{
+ COLA_ASSERT(parameter < lastRoutingParameterMarker);
+ return m_routing_parameters[parameter];
+}
+
+
+void Router::setRoutingOption(const RoutingOption option, const bool value)
+{
+ COLA_ASSERT(option < lastRoutingOptionMarker);
+ m_routing_options[option] = value;
+ m_settings_changes = true;
+}
+
+
+bool Router::routingOption(const RoutingOption option) const
+{
+ COLA_ASSERT(option < lastRoutingOptionMarker);
+ return m_routing_options[option];
+}
+
+
+void Router::setRoutingPenalty(const RoutingParameter penType,
+ const double penValue)
+{
+ setRoutingParameter(penType, penValue);
+}
+
+void Router::registerSettingsChange(void)
+{
+ m_settings_changes = true;
+}
+
+HyperedgeRerouter *Router::hyperedgeRerouter(void)
+{
+ return &m_hyperedge_rerouter;
+}
+
+
+bool Router::isInCrossingPenaltyReroutingStage(void) const
+{
+ return m_in_crossing_rerouting_stage;
+}
+
+
+void Router::printInfo(void)
+{
+ FILE *fp = stdout;
+ fprintf(fp, "\nVisibility Graph info:\n");
+ fprintf(fp, "----------------------\n");
+
+ unsigned int currshape = 0;
+ int st_shapes = 0;
+ int st_vertices = 0;
+ int st_endpoints = 0;
+ int st_valid_shape_visedges = 0;
+ int st_valid_endpt_visedges = 0;
+ int st_orthogonal_visedges = 0;
+ int st_invalid_visedges = 0;
+ VertInf *finish = vertices.end();
+ for (VertInf *t = vertices.connsBegin(); t != finish; t = t->lstNext)
+ {
+ VertID pID = t->id;
+
+ if (!(pID.isConnPt()) && (pID.objID != currshape))
+ {
+ currshape = pID.objID;
+ st_shapes++;
+ }
+ if (!(pID.isConnPt()))
+ {
+ st_vertices++;
+ }
+ else
+ {
+ // The shape 0 ones are temporary and not considered.
+ st_endpoints++;
+ }
+ }
+ for (EdgeInf *t = visGraph.begin(); t != visGraph.end();
+ t = t->lstNext)
+ {
+ std::pair<VertID, VertID> idpair = t->ids();
+
+ if (idpair.first.isConnPt() || idpair.second.isConnPt())
+ {
+ st_valid_endpt_visedges++;
+ }
+ else
+ {
+ st_valid_shape_visedges++;
+ }
+ }
+ for (EdgeInf *t = invisGraph.begin(); t != invisGraph.end();
+ t = t->lstNext)
+ {
+ st_invalid_visedges++;
+ }
+ for (EdgeInf *t = visOrthogGraph.begin(); t != visOrthogGraph.end();
+ t = t->lstNext)
+ {
+ st_orthogonal_visedges++;
+ }
+ fprintf(fp, "Number of shapes: %d\n", st_shapes);
+ fprintf(fp, "Number of vertices: %d (%d real, %d endpoints)\n",
+ st_vertices + st_endpoints, st_vertices, st_endpoints);
+ fprintf(fp, "Number of orthog_vis_edges: %d\n", st_orthogonal_visedges);
+ fprintf(fp, "Number of vis_edges: %d (%d valid [%d normal, %d endpt], "
+ "%d invalid)\n", st_valid_shape_visedges + st_invalid_visedges +
+ st_valid_endpt_visedges, st_valid_shape_visedges +
+ st_valid_endpt_visedges, st_valid_shape_visedges,
+ st_valid_endpt_visedges, st_invalid_visedges);
+ fprintf(fp, "----------------------\n");
+ fprintf(fp, "checkVisEdge tally: %d\n", st_checked_edges);
+ fprintf(fp, "----------------------\n");
+
+#ifdef AVOID_PROFILE
+ timers.printAll(fp);
+ timers.reset();
+#endif
+}
+
+
+static const double LIMIT = 100000000;
+
+static void reduceRange(double& val)
+{
+ val = std::min(val, LIMIT);
+ val = std::max(val, -LIMIT);
+}
+
+
+//=============================================================================
+// The following methods are for testing and debugging.
+
+
+bool Router::existsOrthogonalSegmentOverlap(const bool atEnds)
+{
+ ConnRefList::iterator fin = connRefs.end();
+ for (ConnRefList::iterator i = connRefs.begin(); i != fin; ++i)
+ {
+ Avoid::Polygon iRoute = (*i)->displayRoute();
+ ConnRefList::iterator j = i;
+ for (++j; j != fin; ++j)
+ {
+ // Determine if this pair overlap
+ Avoid::Polygon jRoute = (*j)->displayRoute();
+ ConnectorCrossings cross(iRoute, true, jRoute, *i, *j);
+ cross.checkForBranchingSegments = true;
+ for (size_t jInd = 1; jInd < jRoute.size(); ++jInd)
+ {
+ const bool finalSegment = ((jInd + 1) == jRoute.size());
+ cross.countForSegment(jInd, finalSegment);
+
+ if ((cross.crossingFlags & CROSSING_SHARES_PATH) &&
+ (atEnds ||
+ !(cross.crossingFlags & CROSSING_SHARES_PATH_AT_END)))
+ {
+ // We are looking for fixedSharedPaths and there is a
+ // fixedSharedPath.
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+
+bool Router::existsOrthogonalFixedSegmentOverlap(const bool atEnds)
+{
+ ConnRefList::iterator fin = connRefs.end();
+ for (ConnRefList::iterator i = connRefs.begin(); i != fin; ++i)
+ {
+ Avoid::Polygon iRoute = (*i)->displayRoute();
+ ConnRefList::iterator j = i;
+ for (++j; j != fin; ++j)
+ {
+ // Determine if this pair overlap
+ Avoid::Polygon jRoute = (*j)->displayRoute();
+ ConnectorCrossings cross(iRoute, true, jRoute, *i, *j);
+ cross.checkForBranchingSegments = true;
+ for (size_t jInd = 1; jInd < jRoute.size(); ++jInd)
+ {
+ const bool finalSegment = ((jInd + 1) == jRoute.size());
+ cross.countForSegment(jInd, finalSegment);
+
+ if ((cross.crossingFlags & CROSSING_SHARES_PATH) &&
+ (cross.crossingFlags & CROSSING_SHARES_FIXED_SEGMENT) &&
+ (atEnds ||
+ !(cross.crossingFlags & CROSSING_SHARES_PATH_AT_END)))
+ {
+ // We are looking for fixedSharedPaths and there is a
+ // fixedSharedPath.
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+
+bool Router::existsOrthogonalTouchingPaths(void)
+{
+ ConnRefList::iterator fin = connRefs.end();
+ for (ConnRefList::iterator i = connRefs.begin(); i != fin; ++i)
+ {
+ Avoid::Polygon iRoute = (*i)->displayRoute();
+ ConnRefList::iterator j = i;
+ for (++j; j != fin; ++j)
+ {
+ // Determine if this pair overlap
+ Avoid::Polygon jRoute = (*j)->displayRoute();
+ ConnectorCrossings cross(iRoute, true, jRoute, *i, *j);
+ cross.checkForBranchingSegments = true;
+ for (size_t jInd = 1; jInd < jRoute.size(); ++jInd)
+ {
+ const bool finalSegment = ((jInd + 1) == jRoute.size());
+ cross.countForSegment(jInd, finalSegment);
+
+ if (cross.crossingFlags & CROSSING_TOUCHES)
+ {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+
+// Counts the number of crossings between all connectors.
+//
+// If optimisedForConnectorType is set, This will only count crossings
+// between orthogonal connectors if they appear at segment endpoints.
+// Thus, it can be used on raw connectors but not on simplified orthogonal
+// connectors.
+//
+int Router::existsCrossings(const bool optimisedForConnectorType)
+{
+ int count = 0;
+ ConnRefList::iterator fin = connRefs.end();
+ for (ConnRefList::iterator i = connRefs.begin(); i != fin; ++i)
+ {
+ Avoid::Polygon iRoute = (*i)->displayRoute();
+ ConnRefList::iterator j = i;
+ for (++j; j != fin; ++j)
+ {
+ // Determine if this pair overlap
+ Avoid::Polygon jRoute = (*j)->displayRoute();
+ ConnRef *iConn = (optimisedForConnectorType) ? *i : nullptr;
+ ConnRef *jConn = (optimisedForConnectorType) ? *j : nullptr;
+ ConnectorCrossings cross(iRoute, true, jRoute, iConn, jConn);
+ cross.checkForBranchingSegments = true;
+ for (size_t jInd = 1; jInd < jRoute.size(); ++jInd)
+ {
+ const bool finalSegment = ((jInd + 1) == jRoute.size());
+
+ // Normal crossings aren't counted if we pass the pointers
+ // for the connectors, so don't pass them.
+ cross.countForSegment(jInd, finalSegment);
+
+ count += cross.crossingCount;
+ }
+ }
+ }
+ return count;
+}
+
+// Looks for non-orthogonal segments in orthogonal connectors and
+// returns true if it finds any.
+bool Router::existsInvalidOrthogonalPaths(void)
+{
+ // For each connector...
+ ConnRefList::iterator fin = connRefs.end();
+ for (ConnRefList::iterator i = connRefs.begin(); i != fin; ++i)
+ {
+ // If it is an orthogonal connector...
+ if ((*i)->routingType() == Avoid::ConnType_Orthogonal)
+ {
+ // Check each segment of the path...
+ Avoid::Polygon iRoute = (*i)->displayRoute();
+ for (size_t iInd = 1; iInd < iRoute.size(); ++iInd)
+ {
+ // And if it isn't either vertical or horizontal...
+ if ( (iRoute.at(iInd - 1).x != iRoute.at(iInd).x) &&
+ (iRoute.at(iInd - 1).y != iRoute.at(iInd).y) )
+ {
+ // Then we've found an invalid path.
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+
+void Router::setTopologyAddon(TopologyAddonInterface *topologyAddon)
+{
+ COLA_ASSERT(m_topology_addon);
+ delete m_topology_addon;
+ if (topologyAddon)
+ {
+ m_topology_addon = topologyAddon->clone();
+ }
+ else
+ {
+ m_topology_addon = new TopologyAddonInterface();
+ }
+ registerSettingsChange();
+}
+
+void Router::improveOrthogonalTopology(void)
+{
+ COLA_ASSERT(m_topology_addon);
+ m_topology_addon->improveOrthogonalTopology(this);
+}
+
+void Router::outputInstanceToSVG(std::string instanceName)
+{
+ std::string filename;
+ if (!instanceName.empty())
+ {
+ filename = instanceName;
+ }
+ else
+ {
+ filename = "libavoid-debug";
+ }
+ filename += ".svg";
+ FILE *fp = fopen(filename.c_str(), "w");
+
+ if (fp == nullptr)
+ {
+ return;
+ }
+
+ double minX = LIMIT;
+ double minY = LIMIT;
+ double maxX = -LIMIT;
+ double maxY = -LIMIT;
+
+ VertInf *curr = vertices.connsBegin();
+ while (curr)
+ {
+ Point p = curr->point;
+
+ reduceRange(p.x);
+ reduceRange(p.y);
+
+ if (p.x > -LIMIT)
+ {
+ minX = std::min(minX, p.x);
+ }
+ if (p.x < LIMIT)
+ {
+ maxX = std::max(maxX, p.x);
+ }
+ if (p.y > -LIMIT)
+ {
+ minY = std::min(minY, p.y);
+ }
+ if (p.y < LIMIT)
+ {
+ maxY = std::max(maxY, p.y);
+ }
+ curr = curr->lstNext;
+ }
+ minX -= 8;
+ minY -= 8;
+ maxX += 8;
+ maxY += 8;
+
+ fprintf(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ fprintf(fp, "<svg xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\" xmlns=\"http://www.w3.org/2000/svg\" width=\"100%%\" height=\"100%%\" viewBox=\"%g %g %g %g\">\n", minX, minY, maxX - minX, maxY - minY);
+
+ // Output source code to generate this instance of the router.
+ fprintf(fp, "<!-- Source code to generate this instance:\n");
+ fprintf(fp, "#include \"libavoid/libavoid.h\"\n");
+ if (m_topology_addon->outputCode(nullptr))
+ {
+ fprintf(fp, "#include \"libcola/cola.h\"\n");
+ fprintf(fp, "#include \"libtopology/orthogonal_topology.h\"\n");
+ fprintf(fp, "using namespace cola;\n");
+ }
+ fprintf(fp, "using namespace Avoid;\n");
+ fprintf(fp, "int main(void) {\n");
+ fprintf(fp, " Router *router = new Router(");
+ if (m_allows_polyline_routing)
+ {
+ fprintf(fp, "PolyLineRouting");
+ }
+ if (m_allows_polyline_routing && m_allows_orthogonal_routing)
+ {
+ fprintf(fp, " | ");
+ }
+ if (m_allows_orthogonal_routing)
+ {
+ fprintf(fp, "OrthogonalRouting");
+ }
+ fprintf(fp, ");\n");
+ for (size_t p = 0; p < lastRoutingParameterMarker; ++p)
+ {
+ fprintf(fp, " router->setRoutingParameter((RoutingParameter)%lu, %g);\n",
+ (unsigned long)p, m_routing_parameters[p]);
+ }
+ for (size_t p = 0; p < lastRoutingOptionMarker; ++p)
+ {
+ fprintf(fp, " router->setRoutingOption((RoutingOption)%lu, %s);\n",
+ (unsigned long)p, (m_routing_options[p]) ? "true" : "false");
+ }
+ fprintf(fp, " Polygon polygon;\n");
+ fprintf(fp, " ConnRef *connRef = nullptr;\n");
+ fprintf(fp, " ConnEnd srcPt;\n");
+ fprintf(fp, " ConnEnd dstPt;\n");
+ fprintf(fp, " ConnEnd heConnPt;\n");
+ fprintf(fp, " PolyLine newRoute;\n");
+ fprintf(fp, " ShapeConnectionPin *connPin = nullptr;\n");
+ fprintf(fp, "\n");
+ ClusterRefList::reverse_iterator revClusterRefIt = clusterRefs.rbegin();
+ while (revClusterRefIt != clusterRefs.rend())
+ {
+ ClusterRef *cRef = *revClusterRefIt;
+ fprintf(fp, " polygon = Polygon(%lu);\n",
+ (unsigned long)cRef->polygon().size());
+ for (size_t i = 0; i <cRef->polygon().size(); ++i)
+ {
+ fprintf(fp, " polygon.ps[%lu] = Point(%g, %g);\n",
+ (unsigned long)i, cRef->polygon().at(i).x,
+ cRef->polygon().at(i).y);
+ }
+ fprintf(fp, " new ClusterRef(router, polygon, %u);\n", cRef->id());
+ ++revClusterRefIt;
+ }
+ ObstacleList::reverse_iterator revObstacleIt = m_obstacles.rbegin();
+ while (revObstacleIt != m_obstacles.rend())
+ {
+ Obstacle *obstacle = *revObstacleIt;
+ obstacle->outputCode(fp);
+ ++revObstacleIt;
+ }
+ ConnRefList::reverse_iterator revConnRefIt = connRefs.rbegin();
+ while (revConnRefIt != connRefs.rend())
+ {
+ ConnRef *connRef = *revConnRefIt;
+ connRef->outputCode(fp);
+ ++revConnRefIt;
+ }
+
+ m_topology_addon->outputCode(fp);
+
+ fprintf(fp, " router->processTransaction();\n");
+ fprintf(fp, " router->outputInstanceToSVG();\n");
+
+ m_topology_addon->outputDeletionCode(fp);
+ fprintf(fp, " delete router;\n");
+ fprintf(fp, " return 0;\n");
+ fprintf(fp, "};\n");
+ fprintf(fp, "-->\n");
+
+ fprintf(fp, "<g inkscape:groupmode=\"layer\" "
+ "inkscape:label=\"Clusters\">\n");
+ revClusterRefIt = clusterRefs.rbegin();
+ while (revClusterRefIt != clusterRefs.rend())
+ {
+ ClusterRef *cRef = *revClusterRefIt;
+ fprintf(fp, "<path id=\"cluster-%u\" style=\"stroke-width: 1px; "
+ "stroke: black; fill: green; opacity: 0.1;\" d=\"",
+ cRef->id());
+ for (size_t i = 0; i < cRef->polygon().size(); ++i)
+ {
+ fprintf(fp, "%c %g %g ", ((i == 0) ? 'M' : 'L'),
+ cRef->polygon().at(i).x, cRef->polygon().at(i).y);
+ }
+ fprintf(fp, "Z\" />\n");
+
+ fprintf(fp, "<path id=\"cluster-%u-rect\" style=\"stroke-width: 1px; "
+ "stroke: black; fill: green; opacity: 0.1;\" d=\"",
+ cRef->id());
+ for (size_t i = 0; i < cRef->rectangularPolygon().size(); ++i)
+ {
+ fprintf(fp, "%c %g %g ", ((i == 0) ? 'M' : 'L'),
+ cRef->rectangularPolygon().at(i).x,
+ cRef->rectangularPolygon().at(i).y);
+ }
+ fprintf(fp, "Z\" />\n");
+ ++revClusterRefIt;
+ }
+ fprintf(fp, "</g>\n");
+
+ fprintf(fp, "<g inkscape:groupmode=\"layer\" "
+ "style=\"display: none;\" "
+ "inkscape:label=\"ShapePolygons\">\n");
+ ObstacleList::iterator obstacleIt = m_obstacles.begin();
+ while (obstacleIt != m_obstacles.end())
+ {
+ Obstacle *obstacle = *obstacleIt;
+ bool isShape = (nullptr != dynamic_cast<ShapeRef *> (obstacle));
+
+ if ( ! isShape )
+ {
+ // Don't output obstacles here, for now.
+ ++obstacleIt;
+ continue;
+ }
+
+ fprintf(fp, "<path id=\"poly-%u\" style=\"stroke-width: 1px; "
+ "stroke: black; fill: %s; fill-opacity: 0.3;\" d=\"",
+ obstacle->id(), (isShape) ? "grey" : "red");
+ for (size_t i = 0; i < obstacle->polygon().size(); ++i)
+ {
+ fprintf(fp, "%c %g %g ", ((i == 0) ? 'M' : 'L'),
+ obstacle->polygon().at(i).x, obstacle->polygon().at(i).y);
+ }
+ fprintf(fp, "Z\" />\n");
+ ++obstacleIt;
+ }
+ fprintf(fp, "</g>\n");
+
+ fprintf(fp, "<g inkscape:groupmode=\"layer\" "
+ "style=\"display: none;\" "
+ "inkscape:label=\"ObstaclePolygons\">\n");
+ obstacleIt = m_obstacles.begin();
+ while (obstacleIt != m_obstacles.end())
+ {
+ Obstacle *obstacle = *obstacleIt;
+ bool isShape = (nullptr != dynamic_cast<ShapeRef *> (obstacle));
+
+ if ( ! isShape )
+ {
+ // Don't output obstacles here, for now.
+ ++obstacleIt;
+ continue;
+ }
+
+ Polygon polygon = obstacle->routingPolygon();
+ fprintf(fp, "<path id=\"poly-%u\" style=\"stroke-width: 1px; "
+ "stroke: black; fill: %s; fill-opacity: 0.3;\" d=\"",
+ obstacle->id(), (isShape) ? "grey" : "red");
+ for (size_t i = 0; i < polygon.size(); ++i)
+ {
+ fprintf(fp, "%c %g %g ", ((i == 0) ? 'M' : 'L'),
+ polygon.at(i).x, polygon.at(i).y);
+ }
+ fprintf(fp, "Z\" />\n");
+ ++obstacleIt;
+ }
+ fprintf(fp, "</g>\n");
+
+ fprintf(fp, "<g inkscape:groupmode=\"layer\" "
+ "style=\"display: none;\" "
+ "inkscape:label=\"IdealJunctions\">\n");
+ for (ObstacleList::iterator obstacleIt = m_obstacles.begin();
+ obstacleIt != m_obstacles.end(); ++obstacleIt)
+ {
+ JunctionRef *junction = dynamic_cast<JunctionRef *> (*obstacleIt);
+ if (junction)
+ {
+ fprintf(fp, "<circle id=\"idealJunction-%u\" cx=\"%g\" cy=\"%g\" "
+ "r=\"8\" style=\"stroke: none; fill: %s; "
+ "fill-opacity: 0.5;\" />\n", junction->id(),
+ junction->recommendedPosition().x,
+ junction->recommendedPosition().y, "green");
+ }
+
+ }
+ fprintf(fp, "</g>\n");
+
+ fprintf(fp, "<g inkscape:groupmode=\"layer\" "
+ "inkscape:label=\"ObstacleRects\">\n");
+ obstacleIt = m_obstacles.begin();
+ while (obstacleIt != m_obstacles.end())
+ {
+ Obstacle *obstacle = *obstacleIt;
+ bool isShape = (nullptr != dynamic_cast<ShapeRef *> (obstacle));
+
+ if ( ! isShape )
+ {
+ // Don't output obstacles here, for now.
+ ++obstacleIt;
+ continue;
+ }
+
+ Box bBox = obstacle->routingBox();
+
+ fprintf(fp, "<rect id=\"rect-%u\" x=\"%g\" y=\"%g\" width=\"%g\" "
+ "height=\"%g\" style=\"stroke-width: 1px; stroke: black; "
+ "fill: grey; stroke-opacity: 0.1; fill-opacity: 0.1;\" />\n",
+ obstacle->id(), bBox.min.x, bBox.min.y,
+ bBox.max.x - bBox.min.x, bBox.max.y - bBox.min.y);
+ ++obstacleIt;
+ }
+ fprintf(fp, "</g>\n");
+
+ fprintf(fp, "<g inkscape:groupmode=\"layer\" "
+ "inkscape:label=\"VisGraph\""
+ ">\n");
+ EdgeInf *finish = nullptr;
+ fprintf(fp, "<g inkscape:groupmode=\"layer\" "
+ "style=\"display: none;\" "
+ "inkscape:label=\"VisGraph-shape\""
+ ">\n");
+ finish = visGraph.end();
+ for (EdgeInf *t = visGraph.begin(); t != finish; t = t->lstNext)
+ {
+ std::pair<VertID, VertID> ids = t->ids();
+ bool isConn = ids.first.isConnPt() || ids.second.isConnPt();
+ if (isConn)
+ {
+ continue;
+ }
+ std::pair<Point, Point> ptpair = t->points();
+ Point p1 = ptpair.first;
+ Point p2 = ptpair.second;
+
+ reduceRange(p1.x);
+ reduceRange(p1.y);
+ reduceRange(p2.x);
+ reduceRange(p2.y);
+
+ fprintf(fp, "<path d=\"M %g %g L %g %g\" "
+ "style=\"fill: none; stroke: %s; stroke-width: 1px;\" />\n",
+ p1.x, p1.y, p2.x, p2.y,
+ (ids.first.isConnPt() || ids.second.isConnPt()) ? "blue" :
+ "red");
+ }
+ fprintf(fp, "</g>\n");
+ fprintf(fp, "<g inkscape:groupmode=\"layer\" "
+ "style=\"display: none;\" "
+ "inkscape:label=\"VisGraph-conn\""
+ ">\n");
+ finish = visGraph.end();
+ for (EdgeInf *t = visGraph.begin(); t != finish; t = t->lstNext)
+ {
+ std::pair<VertID, VertID> ids = t->ids();
+ bool isConn = ids.first.isConnPt() || ids.second.isConnPt();
+ if (!isConn)
+ {
+ continue;
+ }
+ std::pair<Point, Point> ptpair = t->points();
+ Point p1 = ptpair.first;
+ Point p2 = ptpair.second;
+
+ reduceRange(p1.x);
+ reduceRange(p1.y);
+ reduceRange(p2.x);
+ reduceRange(p2.y);
+
+ fprintf(fp, "<path d=\"M %g %g L %g %g\" "
+ "style=\"fill: none; stroke: %s; stroke-width: 1px;\" />\n",
+ p1.x, p1.y, p2.x, p2.y,
+ (ids.first.isConnPt() || ids.second.isConnPt()) ? "blue" :
+ "red");
+ }
+ fprintf(fp, "</g>\n");
+ fprintf(fp, "</g>\n");
+
+ fprintf(fp, "<g inkscape:groupmode=\"layer\" "
+ "style=\"display: none;\" "
+ "inkscape:label=\"OrthogVisGraph\">\n");
+ finish = visOrthogGraph.end();
+ for (EdgeInf *t = visOrthogGraph.begin(); t != finish; t = t->lstNext)
+ {
+ std::pair<Point, Point> ptpair = t->points();
+ Point p1 = ptpair.first;
+ Point p2 = ptpair.second;
+
+ reduceRange(p1.x);
+ reduceRange(p1.y);
+ reduceRange(p2.x);
+ reduceRange(p2.y);
+
+ std::pair<VertID, VertID> ids = t->ids();
+
+ fprintf(fp, "<path d=\"M %g %g L %g %g\" "
+ "style=\"fill: none; stroke: %s; stroke-width: 1px;\" />\n",
+ p1.x, p1.y, p2.x, p2.y,
+ (ids.first.isConnPt() || ids.second.isConnPt()) ? "green" :
+ "red");
+ }
+ fprintf(fp, "</g>\n");
+
+ fprintf(fp, "<g inkscape:groupmode=\"layer\" "
+ "style=\"display: none;\" "
+ "inkscape:label=\"RawConnectors\""
+ ">\n");
+ ConnRefList::iterator connRefIt = connRefs.begin();
+ while (connRefIt != connRefs.end())
+ {
+ ConnRef *connRef = *connRefIt;
+
+ PolyLine route = connRef->route();
+ if (!route.empty())
+ {
+ fprintf(fp, "<path id=\"raw-%u\" d=\"M %g %g ", connRef->id(),
+ route.ps[0].x, route.ps[0].y);
+ for (size_t i = 1; i < route.size(); ++i)
+ {
+ fprintf(fp, "L %g %g ", route.ps[i].x, route.ps[i].y);
+ }
+ fprintf(fp, "\" ");
+ if (connRef->src() && connRef->dst())
+ {
+ fprintf(fp, "debug=\"src: %d dst: %d\" ",
+ connRef->src()->visDirections,
+ connRef->dst()->visDirections);
+ }
+ fprintf(fp, "style=\"fill: none; stroke: black; "
+ "stroke-width: 1px;\" />\n");
+ }
+
+ ++connRefIt;
+ }
+ fprintf(fp, "</g>\n");
+
+ fprintf(fp, "<g inkscape:groupmode=\"layer\" "
+ "style=\"display: none;\" "
+ "inkscape:label=\"CurvedDisplayConnectors\""
+ ">\n");
+ connRefIt = connRefs.begin();
+ while (connRefIt != connRefs.end())
+ {
+ ConnRef *connRef = *connRefIt;
+
+ PolyLine route = connRef->displayRoute().curvedPolyline(8);
+ if (!route.empty())
+ {
+ fprintf(fp, "<path id=\"curved-%u\" d=\"M %g %g ", connRef->id(),
+ route.ps[0].x, route.ps[0].y);
+ for (size_t i = 1; i < route.size(); ++i)
+ {
+ if (route.ts[i] == 'C')
+ {
+ fprintf(fp, "%c %g %g %g %g %g %g", route.ts[i],
+ route.ps[i].x, route.ps[i].y,
+ route.ps[i+1].x, route.ps[i+1].y,
+ route.ps[i+2].x, route.ps[i+2].y);
+ i += 2;
+ }
+ else
+ {
+ fprintf(fp, "%c %g %g ", route.ts[i],
+ route.ps[i].x, route.ps[i].y);
+ }
+ }
+ fprintf(fp, "\" ");
+ if (connRef->src() && connRef->dst())
+ {
+ fprintf(fp, "debug=\"src: %d dst: %d\" ",
+ connRef->src()->visDirections,
+ connRef->dst()->visDirections);
+ }
+ fprintf(fp, "style=\"fill: none; stroke: black; "
+ "stroke-width: 1px;\" />\n");
+ }
+
+ ++connRefIt;
+ }
+ fprintf(fp, "</g>\n");
+
+
+ fprintf(fp, "<g inkscape:groupmode=\"layer\" "
+ "inkscape:label=\"DisplayConnectors\""
+ ">\n");
+ connRefIt = connRefs.begin();
+ while (connRefIt != connRefs.end())
+ {
+ ConnRef *connRef = *connRefIt;
+
+ PolyLine route = connRef->displayRoute();
+ if (!route.empty())
+ {
+ fprintf(fp, "<path id=\"disp-%u\" d=\"M %g %g ", connRef->id(),
+ route.ps[0].x, route.ps[0].y);
+ for (size_t i = 1; i < route.size(); ++i)
+ {
+ fprintf(fp, "L %g %g ", route.ps[i].x, route.ps[i].y);
+ }
+ fprintf(fp, "\" ");
+ if (connRef->src() && connRef->dst())
+ {
+ fprintf(fp, "debug=\"src: %d dst: %d\" ",
+ connRef->src()->visDirections,
+ connRef->dst()->visDirections);
+ }
+ fprintf(fp, "style=\"fill: none; stroke: black; "
+ "stroke-width: 1px;\" />\n");
+ }
+
+ ++connRefIt;
+ }
+ fprintf(fp, "</g>\n");
+
+ fprintf(fp, "<g inkscape:groupmode=\"layer\" "
+ "inkscape:label=\"ConnectorCheckpoints\""
+ ">\n");
+ connRefIt = connRefs.begin();
+ while (connRefIt != connRefs.end())
+ {
+ ConnRef *connRef = *connRefIt;
+
+ for (size_t i = 0; i < connRef->m_checkpoints.size(); ++i)
+ {
+ fprintf(fp, "<circle id=\"checkpoint-%u-%d\" cx=\"%g\" cy=\"%g\" "
+ "r=\"8\" style=\"stroke: none; fill: red; "
+ "fill-opacity: 0.25;\" />\n", connRef->id(), (int) i,
+ connRef->m_checkpoints[i].point.x,
+ connRef->m_checkpoints[i].point.y);
+ }
+
+ ++connRefIt;
+ }
+ fprintf(fp, "</g>\n");
+
+
+ fprintf(fp, "</svg>\n");
+ fclose(fp);
+ //printInfo();
+}
+
+void Router::outputDiagramSVG(std::string instanceName, LineReps *lineReps)
+{
+ std::string filename;
+ if (!instanceName.empty())
+ {
+ filename = instanceName;
+ }
+ else
+ {
+ filename = "libavoid-diagram";
+ }
+ filename += ".svg";
+ FILE *fp = fopen(filename.c_str(), "w");
+
+ if (fp == nullptr)
+ {
+ return;
+ }
+
+ double minX = LIMIT;
+ double minY = LIMIT;
+ double maxX = -LIMIT;
+ double maxY = -LIMIT;
+
+ VertInf *curr = vertices.connsBegin();
+ while (curr)
+ {
+ Point p = curr->point;
+
+ reduceRange(p.x);
+ reduceRange(p.y);
+
+ if (p.x > -LIMIT)
+ {
+ minX = std::min(minX, p.x);
+ }
+ if (p.x < LIMIT)
+ {
+ maxX = std::max(maxX, p.x);
+ }
+ if (p.y > -LIMIT)
+ {
+ minY = std::min(minY, p.y);
+ }
+ if (p.y < LIMIT)
+ {
+ maxY = std::max(maxY, p.y);
+ }
+ curr = curr->lstNext;
+ }
+ minX -= 8;
+ minY -= 8;
+ maxX += 8;
+ maxY += 8;
+
+ fprintf(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ fprintf(fp, "<svg xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\" xmlns=\"http://www.w3.org/2000/svg\" width=\"100%%\" height=\"100%%\" viewBox=\"%g %g %g %g\">\n", minX, minY, maxX - minX, maxY - minY);
+
+ fprintf(fp, "<g inkscape:groupmode=\"layer\" "
+ "inkscape:label=\"ShapesRect\">\n");
+ ObstacleList::iterator obstacleIt = m_obstacles.begin();
+ while (obstacleIt != m_obstacles.end())
+ {
+ Obstacle *obstacle = *obstacleIt;
+ bool isShape = (nullptr != dynamic_cast<ShapeRef *> (obstacle));
+
+ if ( ! isShape )
+ {
+ // Don't output non-shape obstacles here, for now.
+ ++obstacleIt;
+ continue;
+ }
+
+ Box bBox = obstacle->polygon().offsetBoundingBox(0.0);
+
+ fprintf(fp, "<rect id=\"rect-%u\" x=\"%g\" y=\"%g\" width=\"%g\" "
+ "height=\"%g\" style=\"stroke-width: 1px; stroke: black; "
+ "fill: grey; stroke-opacity: 0.5; fill-opacity: 0.4;\" />\n",
+ obstacle->id(), bBox.min.x, bBox.min.y,
+ bBox.max.x - bBox.min.x, bBox.max.y - bBox.min.y);
+ ++obstacleIt;
+ }
+ fprintf(fp, "</g>\n");
+
+ fprintf(fp, "<g inkscape:groupmode=\"layer\" "
+ "inkscape:label=\"DisplayConnectors\""
+ ">\n");
+ ConnRefList::iterator connRefIt = connRefs.begin();
+ while (connRefIt != connRefs.end())
+ {
+ ConnRef *connRef = *connRefIt;
+
+ PolyLine route = connRef->displayRoute();
+ if (!route.empty())
+ {
+ fprintf(fp, "<path id=\"disp-%u\" d=\"M %g %g ", connRef->id(),
+ route.ps[0].x, route.ps[0].y);
+ for (size_t i = 1; i < route.size(); ++i)
+ {
+ fprintf(fp, "L %g %g ", route.ps[i].x, route.ps[i].y);
+ }
+ fprintf(fp, "\" ");
+ fprintf(fp, "style=\"fill: none; stroke: black; "
+ "stroke-width: 1px;\" />\n");
+
+ /*
+ for (size_t i = 1; i < route.size(); ++i)
+ {
+ if (route.segmentHasCheckpoint[i - 1])
+ {
+ fprintf(fp, "<path d=\"M %g %g ",
+ route.ps[i - 1].x, route.ps[i - 1].y);
+ fprintf(fp, "L %g %g\" ", route.ps[i].x, route.ps[i].y);
+ fprintf(fp, "style=\"fill: none; stroke: red; "
+ "stroke-width: 1px; stroke-opacity: 1;\" />\n");
+ }
+ }
+ */
+ }
+
+ ++connRefIt;
+ }
+ fprintf(fp, "</g>\n");
+
+ if (lineReps)
+ {
+
+ for (LineReps::iterator it = lineReps->begin(); it != lineReps->end();
+ ++it)
+ {
+ fprintf(fp, "<path d=\"M %g %g ",
+ it->begin.x, it->begin.y);
+ fprintf(fp, "L %g %g\" ", it->end.x, it->end.y);
+ fprintf(fp, "style=\"fill: none; stroke: red; "
+ "stroke-width: 1px; stroke-opacity: 0.7;\" />\n");
+ }
+ }
+
+ fprintf(fp, "</svg>\n");
+ fclose(fp);
+}
+
+void Router::outputDiagram(std::string instanceName)
+{
+ outputDiagramText(instanceName);
+#ifdef SVG_OUTPUT
+ outputInstanceToSVG(instanceName);
+#endif
+}
+
+void Router::outputDiagramText(std::string instanceName)
+{
+ std::string filename;
+ if (!instanceName.empty())
+ {
+ filename = instanceName;
+ }
+ else
+ {
+ filename = "libavoid-diagram";
+ }
+ filename += ".txt";
+ FILE *fp = fopen(filename.c_str(), "w");
+
+ if (fp == nullptr)
+ {
+ return;
+ }
+
+ ObstacleList::iterator obstacleIt = m_obstacles.begin();
+ while (obstacleIt != m_obstacles.end())
+ {
+ Obstacle *obstacle = *obstacleIt;
+ bool isShape = (nullptr != dynamic_cast<ShapeRef *> (obstacle));
+
+ if ( ! isShape )
+ {
+ // Don't output non-shape obstacles here, for now.
+ ++obstacleIt;
+ continue;
+ }
+
+ Box bBox = obstacle->polygon().offsetBoundingBox(0.0);
+
+ fprintf(fp, "rect\n");
+ fprintf(fp, "id=%u\n", obstacle->id());
+ fprintf(fp, "x=%g\n", bBox.min.x);
+ fprintf(fp, "y=%g\n", bBox.min.y);
+ fprintf(fp, "width=%g\n", bBox.max.x - bBox.min.x);
+ fprintf(fp, "height=%g\n", bBox.max.y - bBox.min.y);
+ fprintf(fp, "\n");
+
+ ++obstacleIt;
+ }
+
+ ConnRefList::iterator connRefIt = connRefs.begin();
+ while (connRefIt != connRefs.end())
+ {
+ ConnRef *connRef = *connRefIt;
+
+ PolyLine route = connRef->displayRoute();
+ if (!route.empty())
+ {
+ fprintf(fp, "path\n");
+ fprintf(fp, "id=%u\n", connRef->id());
+ for (size_t i = 0; i < route.size(); ++i)
+ {
+ fprintf(fp, "p%zu: %g %g ", i, route.ps[i].x, route.ps[i].y);
+ fprintf(fp, "\n");
+ }
+ fprintf(fp, "\n");
+ }
+
+ ++connRefIt;
+ }
+
+ fprintf(fp, "\n");
+
+ fclose(fp);
+}
+
+HyperedgeNewAndDeletedObjectLists
+ Router::newAndDeletedObjectListsFromHyperedgeImprovement(void) const
+{
+ return m_hyperedge_improver.newAndDeletedObjectLists();
+}
+
+
+ConnRerouteFlagDelegate::ConnRerouteFlagDelegate()
+{
+}
+
+ConnRerouteFlagDelegate::~ConnRerouteFlagDelegate()
+{
+}
+
+bool *ConnRerouteFlagDelegate::addConn(ConnRef *conn)
+{
+ m_mapping.push_back(std::make_pair(conn, false));
+ return &(m_mapping.back().second);
+}
+
+void ConnRerouteFlagDelegate::removeConn(ConnRef *conn)
+{
+ std::list<std::pair<ConnRef *, bool> >::iterator it;
+ for (it = m_mapping.begin(); it != m_mapping.end(); ++it)
+ {
+ if (it->first == conn)
+ {
+ it->first = nullptr;
+ }
+ }
+}
+
+
+void ConnRerouteFlagDelegate::alertConns(void)
+{
+ std::list<std::pair<ConnRef *, bool> >::iterator it;
+ for (it = m_mapping.begin(); it != m_mapping.end(); ++it)
+ {
+ if ((it->first != nullptr) && (it->second == true))
+ {
+ it->second = false;
+ it->first->m_needs_reroute_flag = true;
+ }
+ }
+}
+
+
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/router.h b/src/3rdparty/adaptagrams/libavoid/router.h
new file mode 100644
index 0000000..4a551be
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/router.h
@@ -0,0 +1,888 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2015 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+//! @file router.h
+//! @brief Contains the interface for the Router class.
+
+
+#ifndef AVOID_ROUTER_H
+#define AVOID_ROUTER_H
+
+#include <ctime>
+#include <list>
+#include <utility>
+#include <string>
+
+#include "libavoid/dllexport.h"
+#include "libavoid/connector.h"
+#include "libavoid/vertices.h"
+#include "libavoid/graph.h"
+#include "libavoid/timer.h"
+#include "libavoid/hyperedge.h"
+#include "libavoid/actioninfo.h"
+#include "libavoid/hyperedgeimprover.h"
+
+
+namespace Avoid {
+
+// LineReps: Used for highlighting certain areas in debugging output.
+struct LineRep
+{
+ Point begin;
+ Point end;
+};
+typedef std::list<LineRep> LineReps;
+
+
+typedef std::list<unsigned int> IntList;
+
+class ShapeRef;
+class JunctionRef;
+class ClusterRef;
+typedef std::list<ClusterRef *> ClusterRefList;
+class Obstacle;
+typedef std::list<Obstacle *> ObstacleList;
+class DebugHandler;
+
+//! @brief Flags that can be passed to the router during initialisation
+//! to specify options.
+enum RouterFlag
+{
+ //! @brief This option specifies that the router should maintain the
+ //! structures necessary to allow poly-line connector routing.
+ PolyLineRouting = 1,
+ //! @brief This option specifies that the router should maintain the
+ //! structures necessary to allow orthogonal connector routing.
+ OrthogonalRouting = 2
+};
+
+
+static const unsigned int runningTo = 1;
+static const unsigned int runningFrom = 2;
+static const unsigned int runningToAndFrom = runningTo | runningFrom;
+
+//! @brief Types of routing parameters and penalties that can be used to
+//! tailor the style and improve the quality of the connector
+//! routes produced.
+enum RoutingParameter
+{
+ //! @brief This penalty is applied for each segment in the connector
+ //! path beyond the first. This should always normally be set
+ //! when doing orthogonal routing to prevent step-like connector
+ //! paths.
+ //! @note This penalty must be set (i.e., be greater than zero) in
+ //! order for orthogonal connector nudging to be performed, since
+ //! this requires reasonable initial routes.
+ segmentPenalty = 0,
+
+ //! @brief This penalty is applied in its full amount to tight acute
+ //! bends in the connector path. A smaller portion of the penalty
+ //! is applied for slight bends, i.e., where the bend is close to
+ //! 180 degrees. This is useful for polyline routing where there
+ //! is some evidence that tighter corners are worse for
+ //! readability, but that slight bends might not be so bad,
+ //! especially when smoothed by curves.
+ anglePenalty,
+
+ //! @brief This penalty is applied whenever a connector path crosses
+ //! another connector path. It takes shared paths into
+ //! consideration and the penalty is only applied if there
+ //! is an actual crossing.
+ //! @note This penalty is still experimental! It is not recommended
+ //! for normal use.
+ crossingPenalty,
+
+ //! @brief This penalty is applied whenever a connector path crosses
+ //! a cluster boundary.
+ //! @note This penalty is still experimental! It is not recommended
+ //! for normal use.
+ //! @note This penalty is very slow. You can override the method
+ //! Router::shouldContinueTransactionWithProgress() to check
+ //! progress and possibly cancel overly slow transactions.
+ clusterCrossingPenalty,
+
+ //! @brief This penalty is applied whenever a connector path shares
+ //! some segments with an immovable portion of an existing
+ //! connector route (such as the first or last segment of a
+ //! connector).
+ //! @note This penalty is still experimental! It is not recommended
+ //! for normal use.
+ fixedSharedPathPenalty,
+
+ //! @brief This penalty is applied to port selection choice when the
+ //! other end of the connector being routed does not appear in
+ //! any of the 90 degree visibility cones centered on the
+ //! visibility directions for the port.
+ //! @note This penalty is still experimental! It is not recommended
+ //! for normal use.
+ //! @note This penalty is very slow. You can override the method
+ //! Router::shouldContinueTransactionWithProgress() to check
+ //! progress and possibly cancel overly slow transactions.
+ portDirectionPenalty,
+
+ //! @brief This parameter defines the spacing distance that will be added
+ //! to the sides of each shape when determining obstacle sizes for
+ //! routing. This controls how closely connectors pass shapes, and
+ //! can be used to prevent connectors overlapping with shape
+ //! boundaries. By default, this distance is set to a value of 0.
+ shapeBufferDistance,
+
+ //! @brief This parameter defines the spacing distance that will be used
+ //! for nudging apart overlapping corners and line segments of
+ //! connectors. By default, this distance is set to a value of 4.
+ idealNudgingDistance,
+
+ //! @brief This penalty is applied whenever a connector path travels
+ //! in the direction opposite of the destination from the source
+ //! endpoint. By default this penalty is set to zero. This
+ //! shouldn't be needed in most cases but can be useful if you
+ //! use penalties such as ::crossingPenalty which cause connectors
+ //! to loop around obstacles.
+ reverseDirectionPenalty,
+
+ // Used for determining the size of the routing parameter array.
+ // This should always we the last value in the enum.
+ lastRoutingParameterMarker
+};
+
+// Backwards compatibility
+typedef enum RoutingParameter PenaltyType;
+
+
+//! @brief Types of routing options that can be enabled.
+enum RoutingOption
+{
+ //! This option causes the final segments of connectors, which are
+ //! attached to shapes, to be nudged apart. Usually these segments
+ //! are fixed, since they are considered to be attached to ports.
+ //!
+ //! Defaults to false.
+ //!
+ //! This option also causes routes running through the same checkpoint
+ //! to be nudged apart.
+ //!
+ //! This option has no effect if ::nudgeSharedPathsWithCommonEndPoint is
+ //! set to false,
+ //!
+ //! @note This will allow routes to be nudged up to the bounds of shapes.
+ //!
+ nudgeOrthogonalSegmentsConnectedToShapes = 0,
+
+ //! This option causes hyperedge routes to be locally improved fixing
+ //! obviously bad paths. As part of this process libavoid will
+ //! effectively move junctions, setting new ideal positions which can be
+ //! accessed via JunctionRef::recommendedPosition() for each junction.
+ //!
+ //! Defaults to true.
+ //!
+ //! This will not add or remove junctions, so will keep the hyperedge
+ //! topology the same. Better routes can be achieved by enabling the
+ //! ::improveHyperedgeRoutesMovingAddingAndDeletingJunctions option.
+ //!
+ //! If initial sensible positions for junctions in hyperedges are not
+ //! known you can register those hyperedges with the HyperedgeRerouter
+ //! class for complete rerouting.
+ //!
+ //! @sa improveHyperedgeRoutesMovingAddingAndDeletingJunctions
+ //! @sa Router::hyperedgeRerouter()
+ //!
+ improveHyperedgeRoutesMovingJunctions,
+
+ //! This option penalises and attempts to reroute orthogonal shared
+ //! connector paths terminating at a common junction or shape
+ //! connection pin. When multiple connector paths enter or leave
+ //! the same side of a junction (or shape pin), the router will
+ //! attempt to reroute these to different sides of the junction or
+ //! different shape pins.
+ //!
+ //! Defaults to false.
+ //!
+ //! This option depends on the ::fixedSharedPathPenalty penalty having
+ //! been set.
+ //!
+ //! @sa fixedSharedPathPenalty
+ //! @note This option is still experimental! It is not recommended
+ //! for normal use.
+ //!
+ penaliseOrthogonalSharedPathsAtConnEnds,
+
+ //! This option can be used to control whether collinear line
+ //! segments that touch just at their ends will be nudged apart.
+ //! The overlap will usually be resolved in the other dimension,
+ //! so this is not usually required.
+ //!
+ //! Defaults to false.
+ //!
+ nudgeOrthogonalTouchingColinearSegments,
+
+ //! This option can be used to control whether the router performs
+ //! a preprocessing step before orthogonal nudging where is tries
+ //! to unify segments and centre them in free space. This
+ //! generally results in better quality ordering and nudging.
+ //!
+ //! Defaults to true.
+ //!
+ //! You may wish to turn this off for large examples where it
+ //! can be very slow and will make little difference.
+ //!
+ performUnifyingNudgingPreprocessingStep,
+
+ //! This option causes hyperedge routes to be locally improved fixing
+ //! obviously bad paths.
+ //!
+ //! It can cause junctions and connectors to be added or removed from
+ //! hyperedges. To get details of these changes for each connector you can
+ //! call Router::newAndDeletedObjectListsFromHyperedgeImprovement().
+ //!
+ //! As part of this process libavoid will effectively move junctions by
+ //! setting new ideal positions for each remaining or added junction,
+ //! which can be read from JunctionRef::recommendedPosition() for each
+ //! junction.
+ //!
+ //! Defaults to false.
+ //!
+ //! If set, this option overrides the ::improveHyperedgeRoutesMovingJunctions
+ //! option.
+ //!
+ //! If initial sensible positions for junctions in hyperedges are not
+ //! known you can register those hyperedges with the HyperedgeRerouter
+ //! class for complete rerouting.
+ //!
+ //! @sa improveHyperedgeRoutesMovingJunctions
+ //! @sa Router::hyperedgeRerouter()
+ //!
+ improveHyperedgeRoutesMovingAddingAndDeletingJunctions,
+
+ //! This option determines whether intermediate segments of connectors that
+ //! are attached to common endpoints will be nudged apart. Usually these
+ //! segments get nudged apart, but you may want to turn this off if you would
+ //! prefer that entire shared paths terminating at a common end point should
+ //! overlap.
+ //!
+ //! Defaults to true.
+ //!
+ nudgeSharedPathsWithCommonEndPoint,
+
+
+ // Used for determining the size of the routing options array.
+ // This should always we the last value in the enum.
+ lastRoutingOptionMarker
+};
+
+//! @brief Types of routing phases reported by
+//! Router::shouldContinueTransactionWithProgress().
+//!
+//! This phases will occur in the order given here, but each phase may take
+//! varying amounts of time.
+//!
+enum TransactionPhases
+{
+ //! @brief The orthogonal visibility graph is built by conducting a
+ //! scan in each dimension. This is the x-dimension.
+ TransactionPhaseOrthogonalVisibilityGraphScanX = 1,
+ //! @brief The orthogonal visibility graph is built by conducting a
+ //! scan in each dimension. This is the y-dimension.
+ TransactionPhaseOrthogonalVisibilityGraphScanY,
+ //! @brief Initial routes are searched for in the visibility graph.
+ TransactionPhaseRouteSearch,
+ //! @brief With crossing penalties enabled, crossing detection is
+ //! performed to find all crossings.
+ TransactionPhaseCrossingDetection,
+ //! @brief Crossing connectors are rerouted to search for better routes.
+ TransactionPhaseRerouteSearch,
+ //! @brief Orthogonal edge segments are nudged apart in the x-dimension.
+ TransactionPhaseOrthogonalNudgingX,
+ //! @brief Orthogonal edge segments are nudged apart in the y-dimension.
+ TransactionPhaseOrthogonalNudgingY,
+ //! @brief Not a real phase, but represents the router is finished (or has
+ //! aborted) the transaction and you may interact with is again.
+ TransactionPhaseCompleted
+};
+
+// NOTE: This is an internal helper class that should not be used by the user.
+//
+// This class allows edges in the visibility graph to store a
+// pointer to a boolean registering when a connector needs to
+// reroute, while allowing connectors to be deleted without
+// needing to scan and remove these references from the visibility
+// graph. Instead the bool is stored in this delegate and the
+// connector is alerted later, so long as it hasn't since been
+// deleted.
+class ConnRerouteFlagDelegate {
+ public:
+ ConnRerouteFlagDelegate();
+ ~ConnRerouteFlagDelegate();
+ bool *addConn(ConnRef *conn);
+ void removeConn(ConnRef *conn);
+ void alertConns(void);
+ private:
+ std::list<std::pair<ConnRef *, bool> > m_mapping;
+};
+
+static const double zeroParamValue = 0;
+static const double chooseSensibleParamValue = -1;
+
+// NOTE: This is an internal helper class that should not be used by the user.
+//
+// It is used by libtopology to add additional functionality to libavoid
+// while keeping libavoid dependency free.
+class TopologyAddonInterface
+{
+ public:
+ TopologyAddonInterface()
+ {
+ }
+ virtual ~TopologyAddonInterface()
+ {
+ }
+ virtual TopologyAddonInterface *clone(void) const
+ {
+ return new TopologyAddonInterface(*this);
+ }
+
+ virtual void improveOrthogonalTopology(Router *router)
+ {
+ (void)(router); // Avoid unused parameter warning.
+ }
+ virtual bool outputCode(FILE *fp) const
+ {
+ (void)(fp); // Avoid unused parameter warning.
+ return false;
+ }
+ virtual bool outputDeletionCode(FILE *fp) const
+ {
+ (void)(fp); // Avoid unused parameter warning.
+ return false;
+ }
+};
+
+
+//! @brief The Router class represents a libavoid router instance.
+//!
+//! Usually you would keep a separate Router instance for each diagram
+//! or layout you have open in your application.
+//
+class AVOID_EXPORT Router {
+ public:
+ //! @brief Constructor for router instance.
+ //!
+ //! @param[in] flags One or more Avoid::RouterFlag options to
+ //! control the behaviour of the router.
+ Router(const unsigned int flags);
+
+ //! @brief Destructor for router instance.
+ //!
+ //! @note Destroying a router instance will delete all remaining
+ //! shapes and connectors, thereby invalidating any existing
+ //! pointers to them.
+ virtual ~Router();
+
+ ObstacleList m_obstacles;
+ ConnRefList connRefs;
+ ClusterRefList clusterRefs;
+ EdgeList visGraph;
+ EdgeList invisGraph;
+ EdgeList visOrthogGraph;
+ ContainsMap contains;
+ VertInfList vertices;
+ ContainsMap enclosingClusters;
+
+ bool PartialTime;
+ bool SimpleRouting;
+ bool ClusteredRouting;
+
+ // Poly-line routing options:
+ bool IgnoreRegions;
+ bool UseLeesAlgorithm;
+ bool InvisibilityGrph;
+
+ // General routing options:
+ bool SelectiveReroute;
+
+ bool PartialFeedback;
+ bool RubberBandRouting;
+
+
+ // Instrumentation:
+#ifdef AVOID_PROFILE
+ Timer timers;
+#endif
+ int st_checked_edges;
+
+ //! @brief Allows setting of the behaviour of the router in regard
+ //! to transactions. This controls whether transactions are
+ //! used to queue changes and process them efficiently at once
+ //! or they are instead processed immediately.
+ //!
+ //! It is more efficient to perform actions like shape movement,
+ //! addition or deletion as batch tasks, and reroute the necessary
+ //! connectors just once after these actions have been performed.
+ //! For this reason, libavoid allows you to group such actions into
+ //! "transactions" that are processed efficiently when the
+ //! processTransaction() method is called.
+ //!
+ //! By default, the router will process all actions as transactions.
+ //! If transactionUse() is set to false, then all actions will get
+ //! processed immediately, and cause immediate routing callbacks to
+ //! all affected connectors after each action.
+ //!
+ //! @param[in] transactions A boolean value specifying whether to
+ //! use transactions.
+ //!
+ void setTransactionUse(const bool transactions);
+
+ //! @brief Reports whether the router groups actions into transactions.
+ //!
+ //! @return A boolean value describing whether transactions are in use.
+ //!
+ //! @sa setTransactionUse
+ //! @sa processTransaction
+ //!
+ bool transactionUse(void) const;
+
+ //! @brief Finishes the current transaction and processes all the
+ //! queued object changes efficiently.
+ //!
+ //! This method will efficiently process all moves, additions and
+ //! deletions that have occurred since processTransaction() was
+ //! last called.
+ //!
+ //! If transactionUse() is false, then all actions will have been
+ //! processed immediately and this method will do nothing.
+ //!
+ //! @return A boolean value describing whether there were any actions
+ //! to process.
+ //!
+ //! @sa setTransactionUse
+ //!
+ bool processTransaction(void);
+
+ //! @brief Delete a shape from the router scene.
+ //!
+ //! Connectors that could have a better (usually shorter) path after
+ //! the removal of this shape will be marked as needing to be rerouted.
+ //!
+ //! If the router is using transactions, then this action will occur
+ //! the next time Router::processTransaction() is called. See
+ //! Router::setTransactionUse() for more information.
+ //!
+ //! You should not use the shape reference again after this call.
+ //! The router will handle freeing of the shape's memory.
+ //!
+ //! @param[in] shape Pointer reference to the shape being removed.
+ //!
+ void deleteShape(ShapeRef *shape);
+
+ //! @brief Move or resize an existing shape within the router scene.
+ //!
+ //! A new polygon for the shape can be given to effectively move or
+ //! resize the shape with the scene. Connectors that intersect the
+ //! new shape polygon, or that could have a better (usually shorter)
+ //! path after the change, will be marked as needing to be rerouted.
+ //!
+ //! If the router is using transactions, then this action will occur
+ //! the next time Router::processTransaction() is called. See
+ //! Router::setTransactionUse() for more information.
+ //!
+ //! @param[in] shape Pointer reference to the shape being
+ //! moved/resized.
+ //! @param[in] newPoly The new polygon boundary for the shape.
+ //! @param[in] first_move This option is used for some advanced
+ //! (currently undocumented) behaviour and
+ //! it should be ignored for the moment.
+ //!
+ void moveShape(ShapeRef *shape, const Polygon& newPoly,
+ const bool first_move = false);
+
+ //! @brief Move an existing shape within the router scene by a relative
+ //! distance.
+ //!
+ //! Connectors that intersect the shape's new position, or that could
+ //! have a better (usually shorter) path after the change, will be
+ //! marked as needing to be rerouted.
+ //!
+ //! If the router is using transactions, then this action will occur
+ //! the next time Router::processTransaction() is called. See
+ //! Router::setTransactionUse() for more information.
+ //!
+ //! @param[in] shape Pointer reference to the shape being moved.
+ //! @param[in] xDiff The distance to move the shape in the
+ //! x dimension.
+ //! @param[in] yDiff The distance to move the shape in the
+ //! y dimension.
+ //!
+ void moveShape(ShapeRef *shape, const double xDiff, const double yDiff);
+
+ //! @brief Remove a junction from the router scene.
+ //!
+ //! If the router is using transactions, then this action will occur
+ //! the next time Router::processTransaction() is called. See
+ //! Router::setTransactionUse() for more information.
+ //!
+ //! You should not use the junction reference again after this call.
+ //! The router will handle freeing of the junction's memory.
+ //!
+ //! @param[in] junction Pointer reference to the junction being
+ //! removed.
+ //!
+ void deleteJunction(JunctionRef *junction);
+
+ //! @brief Remove a connector from the router scene.
+ //!
+ //! If the router is using transactions, then this action will occur
+ //! the next time Router::processTransaction() is called. See
+ //! Router::setTransactionUse() for more information.
+ //!
+ //! You should not use the connector reference again after this call.
+ //! The router will handle freeing of the connector's memory.
+ //!
+ //! @param[in] connector Pointer reference to the connector being
+ //! removed.
+ //!
+ void deleteConnector(ConnRef *connector);
+
+ //! @brief Move an existing junction within the router scene.
+ //!
+ //! Connectors that are attached to this junction will be rerouted
+ //! as a result of the move.
+ //!
+ //! If the router is using transactions, then this action will occur
+ //! the next time Router::processTransaction() is called. See
+ //! Router::setTransactionUse() for more information.
+ //!
+ //! @param[in] junction Pointer reference to the junction being
+ //! moved.
+ //! @param[in] newPosition The new position for the junction.
+ //!
+ void moveJunction(JunctionRef *junction, const Point& newPosition);
+
+ //! @brief Move an existing junction within the router scene by a
+ //! relative distance.
+ //!
+ //! Connectors that are attached to this junction will be rerouted
+ //! as a result of the move.
+ //!
+ //! If the router is using transactions, then this action will occur
+ //! the next time Router::processTransaction() is called. See
+ //! Router::setTransactionUse() for more information.
+ //!
+ //! @param[in] junction Pointer reference to the junction being
+ //! moved.
+ //! @param[in] xDiff The distance to move the junction in the
+ //! x dimension.
+ //! @param[in] yDiff The distance to move the junction in the
+ //! y dimension.
+ //!
+ void moveJunction(JunctionRef *junction, const double xDiff,
+ const double yDiff);
+
+ //! @brief Sets values for routing parameters, including routing
+ //! penalties.
+ //!
+ //! libavoid uses a set of parameters to allow the user more control
+ //! over routing style and quality. These different parameters are
+ //! described and explained by the RoutingParameter enum. All
+ //! parameters have sensible defaults.
+ //!
+ //! Regarding routing penalties, libavoid will by default produce
+ //! shortest path routes between the source and destination points
+ //! for each connector. There are several penalties that can be
+ //! applied during this stage to penalise certain conditions and
+ //! thus improve the aesthetics of the routes generated.
+ //!
+ //! If a value of zero or Avoid::zeroParamValue is given then the
+ //! particular parameter value or penalty will be removed. If no
+ //! parameter value argument (or a negative value) is specified
+ //! when calling this method, then a sensible penalty value will
+ //! be automatically chosen.
+ //!
+ //! This method does not re-trigger processing of connectors. The new
+ //! parameter value will be used the next time rerouting is performed.
+ //!
+ //! @param[in] parameter The type of penalty, a RoutingParameter.
+ //! @param[in] value The value to be set for that parameter.
+ //!
+ void setRoutingParameter(const RoutingParameter parameter,
+ const double value = chooseSensibleParamValue);
+
+ //! @brief Returns the current value for a particular routing
+ //! parameter of a given type.
+ //!
+ //! @param[in] parameter The type of parameter, a RoutingParameter.
+ //! @return The value for the specified routing parameter.
+ //!
+ double routingParameter(const RoutingParameter parameter) const;
+
+ //! @brief Turn specific routing options on or off.
+ //!
+ //! @param[in] option The type of routing option, a RoutingOption.
+ //! @param[in] value A boolean representing the option state.
+ //!
+ void setRoutingOption(const RoutingOption option, const bool value);
+
+ //! @brief Returns the current state for a specific routing option.
+ //!
+ //! @param[in] option The type of routing option, a RoutingOption.
+ //! @return A boolean representing the option state.
+ //!
+ bool routingOption(const RoutingOption option) const;
+
+ //! @brief Sets or removes penalty values that are applied during
+ //! connector routing.
+ //!
+ //! @note This is a convenience wrapper for the setRoutingParameter()
+ // method. See its documentation for more details.
+ //!
+ //! @param[in] penType The type of penalty, a RoutingParameter.
+ //! @param[in] penVal The value to be applied for each occurrence
+ //! of the penalty case.
+ //!
+ void setRoutingPenalty(const RoutingParameter penType,
+ const double penVal = chooseSensibleParamValue);
+
+ //! @brief Returns a pointer to the hyperedge rerouter for the router.
+ //!
+ //! @return A HyperedgeRerouter object that can be used to register
+ //! hyperedges for rerouting.
+ //!
+ HyperedgeRerouter *hyperedgeRerouter(void);
+
+ //! @brief Generates an SVG file containing debug output and code that
+ //! can be used to regenerate the instance.
+ //!
+ //! If transactions are being used, then this method should be called
+ //! after processTransaction() has been called, so that it includes any
+ //! changes being queued by the router.
+ //!
+ //! @param[in] filename A string indicating the filename (without
+ //! extension) for the output file. Defaults to
+ //! "libavoid-debug.svg" if no filename is given.
+ //!
+ void outputInstanceToSVG(std::string filename = std::string());
+
+ //! @brief Returns the object ID used for automatically generated
+ //! objects, such as during hyperedge routing.
+ //!
+ //! Reimplement this in a subclass to set specific IDs for new objects.
+ //!
+ //! @note Your implementation should return a value that does not
+ //! fail objectIdIsUnused().
+ //!
+ //! @return The ID for a new object.
+ //!
+ virtual unsigned int newObjectId(void) const;
+
+ //! @brief Returns whether or not the given ID is already used.
+ //!
+ //! You should only need this if you reimplement newObjectId().
+ //!
+ //! @param[in] id An ID to test.
+ //! @return A boolean denoting that the given ID is unused.
+ //!
+ bool objectIdIsUnused(const unsigned int id) const;
+
+ //! @brief A method called at regular intervals during transaction
+ //! processing to report progress and ask if the Router
+ //! should continue the transaction.
+ //!
+ //! You can subclass the Avoid::Router class to implement your
+ //! own behaviour, such as to show a progress bar or cancel the
+ //! transaction at the user's request.
+ //!
+ //! Note that you can get a sense of progress by looking at the
+ //! phaseNumber divided by the totalPhases and the progress in the
+ //! current phase, but be aware that phases and the intervals and
+ //! proportions at which this method is called will vary, sometime
+ //! unpredictably.
+ //!
+ //! You can return false to request that the Router abort the current
+ //! transaction. Be aware that it may not abort in some phases. For
+ //! others it may need to clean up some state before it is safe for
+ //! you to interact with it again. Hence you should wait for a final
+ //! call to this method with the phase Avoid::TransactionPhaseCompleted
+ //! before continuing.
+ //!
+ //! @note Your implementation of this method should be very fast as
+ //! it will be called many times. Also, you should not change
+ //! or interact with the Router instance at all during these
+ //! calls. Wait till you have received a call with the
+ //! Avoid::TransactionPhaseCompleted phase.
+ //!
+ //! @param elapsedTime The number of msec spent on the transaction
+ //! since it began.
+ //! @param phaseNumber A Router::TransactionPhases representing the
+ //! current phase of the transaction.
+ //! @param totalPhases The total number of phases to be performed
+ //! during the transaction.
+ //! @param proportion A double representing the progress in the
+ //! current phase. Value will be between 0--1.
+ //!
+ //! @return Whether the router should continue the transaction.
+ //! This is true in the default (empty) implementation.
+ virtual bool shouldContinueTransactionWithProgress(
+ unsigned int elapsedTime, unsigned int phaseNumber,
+ unsigned int totalPhases, double proportion);
+
+ //! @brief Returns a HyperedgeNewAndDeletedObjectLists detailing the
+ //! lists of junctions and connectors created and deleted
+ //! during hyperedge improvement.
+ //!
+ //! This method will only return information once the router has
+ //! processed the transaction. You should read and act on this
+ //! information before processTransaction() is called again.
+ //!
+ //! After calling this you should no longer refer to any of the
+ //! objects in the "deleted" lists --- the router will delete these
+ //! and free their memory at its convenience.
+ //!
+ //! @return A HyperedgeNewAndDeletedObjectLists containing lists of
+ //! junctions and connectors created and deleted.
+ //!
+ HyperedgeNewAndDeletedObjectLists
+ newAndDeletedObjectListsFromHyperedgeImprovement(void) const;
+
+ void setDebugHandler(DebugHandler *handler);
+ DebugHandler *debugHandler(void) const;
+
+ // Processes the actions list for the transaction. You shouldn't
+ // need to cal this. Instead use processTransaction().
+ void processActions(void);
+
+ void deleteCluster(ClusterRef *cluster);
+ void attachedShapes(IntList &shapes, const unsigned int shapeId,
+ const unsigned int type);
+ void attachedConns(IntList &conns, const unsigned int shapeId,
+ const unsigned int type);
+ void markPolylineConnectorsNeedingReroutingForDeletedObstacle(
+ Obstacle *obstacle);
+ void generateContains(VertInf *pt);
+ void printInfo(void);
+ void regenerateStaticBuiltGraph(void);
+ void destroyOrthogonalVisGraph(void);
+ void setStaticGraphInvalidated(const bool invalidated);
+ ConnType validConnType(const ConnType select = ConnType_None) const;
+ bool isInCrossingPenaltyReroutingStage(void) const;
+ void markAllObstaclesAsMoved(void);
+ ShapeRef *shapeContainingPoint(const Point& point);
+ void performContinuationCheck(unsigned int phaseNumber,
+ size_t stepNumber, size_t totalSteps);
+ void registerSettingsChange(void);
+
+ /**
+ * @brief Set an addon for doing orthogonal topology improvement.
+ *
+ * It is expected that you would use the topology::AvoidTopologyAddon()
+ * from libtopology rather than write your own. This is done so that
+ * libavoid does not have to depend on libtopology.
+ */
+ void setTopologyAddon(TopologyAddonInterface *topologyAddon);
+ void improveOrthogonalTopology(void);
+
+ // Testing and debugging methods.
+ bool existsOrthogonalSegmentOverlap(const bool atEnds = false);
+ bool existsOrthogonalFixedSegmentOverlap(const bool atEnds = false);
+ bool existsOrthogonalTouchingPaths(void);
+ int existsCrossings(const bool optimisedForConnectorType = false);
+ bool existsInvalidOrthogonalPaths(void);
+
+ // Outputs the current diagram. Used for visualising individual
+ // steps of various algorithms. lineReps can be used to draw
+ // attention to specific parts of the diagram that have changed
+ // between steps.
+ void outputDiagramSVG(std::string instanceName = std::string(),
+ LineReps *lineReps = nullptr);
+
+ void outputDiagramText(std::string instanceName = std::string());
+ void outputDiagram(std::string instanceName = std::string());
+
+ private:
+ friend class ShapeRef;
+ friend class ConnRef;
+ friend class JunctionRef;
+ friend class Obstacle;
+ friend class ClusterRef;
+ friend class ShapeConnectionPin;
+ friend class MinimumTerminalSpanningTree;
+ friend class ConnEnd;
+ friend struct HyperedgeTreeNode;
+ friend class HyperedgeRerouter;
+ friend class HyperedgeImprover;
+
+ unsigned int assignId(const unsigned int suggestedId);
+ void addShape(ShapeRef *shape);
+ void addJunction(JunctionRef *junction);
+ void addCluster(ClusterRef *cluster);
+ void modifyConnector(ConnRef *conn);
+ void modifyConnector(ConnRef *conn, unsigned int type,
+ const ConnEnd &connEnd, bool connPinUpdate = false);
+ void modifyConnectionPin(ShapeConnectionPin *pin);
+
+ void removeObjectFromQueuedActions(const void *object);
+ void newBlockingShape(const Polygon& poly, int pid);
+ void checkAllBlockedEdges(int pid);
+ void checkAllMissingEdges(void);
+ void adjustContainsWithAdd(const Polygon& poly, const int p_shape);
+ void adjustContainsWithDel(const int p_shape);
+ void adjustClustersWithAdd(const PolygonInterface& poly,
+ const int p_cluster);
+ void adjustClustersWithDel(const int p_cluster);
+ void rerouteAndCallbackConnectors(void);
+ void improveCrossings(void);
+
+ ActionInfoList actionList;
+ unsigned int m_largest_assigned_id;
+ bool m_consolidate_actions;
+ bool m_currently_calling_destructors;
+ double m_routing_parameters[lastRoutingParameterMarker];
+ bool m_routing_options[lastRoutingOptionMarker];
+
+ ConnRerouteFlagDelegate m_conn_reroute_flags;
+ HyperedgeRerouter m_hyperedge_rerouter;
+
+ // Progress tracking and transaction cancelling.
+ clock_t m_transaction_start_time;
+ bool m_abort_transaction;
+
+ TopologyAddonInterface *m_topology_addon;
+
+ // Overall modes:
+ bool m_allows_polyline_routing;
+ bool m_allows_orthogonal_routing;
+
+ bool m_static_orthogonal_graph_invalidated;
+ bool m_in_crossing_rerouting_stage;
+
+ bool m_settings_changes;
+
+ HyperedgeImprover m_hyperedge_improver;
+
+ DebugHandler *m_debug_handler;
+};
+
+
+}
+
+
+
+#endif
diff --git a/src/3rdparty/adaptagrams/libavoid/scanline.cpp b/src/3rdparty/adaptagrams/libavoid/scanline.cpp
new file mode 100644
index 0000000..9351c36
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/scanline.cpp
@@ -0,0 +1,562 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2009-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+#include <cfloat>
+#include <algorithm>
+
+#include "libavoid/scanline.h"
+#include "libavoid/obstacle.h"
+#include "libavoid/vertices.h"
+#include "libavoid/connector.h"
+#include "libavoid/junction.h"
+#include "libavoid/router.h"
+
+namespace Avoid {
+
+bool CmpNodePos::operator() (const Node* u, const Node* v) const
+{
+ if (u->pos != v->pos)
+ {
+ return u->pos < v->pos;
+ }
+
+ // Use the pointers to the base objects to differentiate them.
+ void *up = (u->v) ? (void *) u->v :
+ ((u->c) ? (void *) u->c : (void *) u->ss);
+ void *vp = (v->v) ? (void *) v->v :
+ ((v->c) ? (void *) v->c : (void *) v->ss);
+ return up < vp;
+}
+
+
+Node::Node(Obstacle *v, const double p)
+ : v(v),
+ c(nullptr),
+ ss(nullptr),
+ pos(p),
+ firstAbove(nullptr),
+ firstBelow(nullptr)
+{
+ Box bBox = v->routingBox();
+ min[XDIM] = bBox.min.x;
+ min[YDIM] = bBox.min.y;
+ max[XDIM] = bBox.max.x;
+ max[YDIM] = bBox.max.y;
+ //COLA_ASSERT(r->width()<1e40);
+}
+
+Node::Node(VertInf *c, const double p)
+ : v(nullptr),
+ c(c),
+ ss(nullptr),
+ pos(p),
+ firstAbove(nullptr),
+ firstBelow(nullptr)
+{
+ min[XDIM] = max[XDIM] = c->point.x;
+ min[YDIM] = max[YDIM] = c->point.y;
+}
+
+Node::Node(ShiftSegment *ss, const double p)
+ : v(nullptr),
+ c(nullptr),
+ ss(ss),
+ pos(p),
+ firstAbove(nullptr),
+ firstBelow(nullptr)
+{
+ // These values shouldn't ever be used, so they don't matter.
+ min[XDIM] = max[XDIM] = min[YDIM] = max[YDIM] = 0;
+}
+
+Node::~Node()
+{
+}
+
+// Find the first Node above in the scanline that is a shape edge,
+// and does not have an open or close event at this position (meaning
+// it is just about to be removed).
+double Node::firstObstacleAbove(size_t dim)
+{
+ Node *curr = firstAbove;
+ while (curr && (curr->ss || (curr->max[dim] > pos)))
+ {
+ curr = curr->firstAbove;
+ }
+
+ if (curr)
+ {
+ return curr->max[dim];
+ }
+ return -DBL_MAX;
+}
+
+// Find the first Node below in the scanline that is a shape edge,
+// and does not have an open or close event at this position (meaning
+// it is just about to be removed).
+double Node::firstObstacleBelow(size_t dim)
+{
+ Node *curr = firstBelow;
+ while (curr && (curr->ss || (curr->min[dim] < pos)))
+ {
+ curr = curr->firstBelow;
+ }
+
+ if (curr)
+ {
+ return curr->min[dim];
+ }
+ return DBL_MAX;
+}
+
+// Mark all connector segments above in the scanline as being able
+// to see to this shape edge.
+void Node::markShiftSegmentsAbove(size_t dim)
+{
+ Node *curr = firstAbove;
+ while (curr && (curr->ss || (curr->pos > min[dim])))
+ {
+ if (curr->ss && (curr->pos <= min[dim]))
+ {
+ curr->ss->maxSpaceLimit =
+ std::min(min[dim], curr->ss->maxSpaceLimit);
+ }
+ curr = curr->firstAbove;
+ }
+}
+
+// Mark all connector segments below in the scanline as being able
+// to see to this shape edge.
+void Node::markShiftSegmentsBelow(size_t dim)
+{
+ Node *curr = firstBelow;
+ while (curr && (curr->ss || (curr->pos < max[dim])))
+ {
+ if (curr->ss && (curr->pos >= max[dim]))
+ {
+ curr->ss->minSpaceLimit =
+ std::max(max[dim], curr->ss->minSpaceLimit);
+ }
+ curr = curr->firstBelow;
+ }
+}
+
+void Node::findFirstPointAboveAndBelow(const size_t dim, const double linePos,
+ double& firstAbovePos, double& firstBelowPos,
+ double& lastAbovePos, double& lastBelowPos)
+{
+ firstAbovePos = -DBL_MAX;
+ firstBelowPos = DBL_MAX;
+ // We start looking left from the right side of the shape,
+ // and vice versa.
+ lastAbovePos = max[dim];
+ lastBelowPos = min[dim];
+
+ Node *curr = nullptr;
+ bool eventsAtSamePos = false;
+ for (int direction = 0; direction < 2; ++direction)
+ {
+ // Look for obstacles in one direction, then the other.
+ curr = (direction == 0) ? firstAbove: firstBelow;
+
+ while (curr)
+ {
+ // The events are at a shared beginning or end of a shape or
+ // connection point. Note, connection points have the same
+ // min and max value in the !dim dimension.
+ eventsAtSamePos =
+ (((linePos == max[!dim]) &&
+ (linePos == curr->max[!dim])) ||
+ ((linePos == min[!dim]) &&
+ (linePos == curr->min[!dim])));
+
+ if (curr->max[dim] <= min[dim])
+ {
+ // Curr shape is completely to the left,
+ // so add it's right side as a limit
+ firstAbovePos = std::max(curr->max[dim], firstAbovePos);
+ }
+ else if (curr->min[dim] >= max[dim])
+ {
+ // Curr shape is completely to the right,
+ // so add it's left side as a limit
+ firstBelowPos = std::min(curr->min[dim], firstBelowPos);
+ }
+ else if (!eventsAtSamePos)
+ {
+ // Shapes that open or close at the same position do not
+ // block visibility, so if they are not at same position
+ // determine where they overlap.
+ lastAbovePos = std::min(curr->min[dim], lastAbovePos);
+ lastBelowPos = std::max(curr->max[dim], lastBelowPos);
+ }
+ curr = (direction == 0) ? curr->firstAbove : curr->firstBelow;
+ }
+ }
+}
+
+double Node::firstPointAbove(size_t dim)
+{
+ // We are looking for the first obstacle above this position,
+ // though we ignore shape edges if this point is inline with
+ // the edge of the obstacle. That is, points have visibility
+ // along the edge of shapes.
+ size_t altDim = (dim + 1) % 2;
+ double result = -DBL_MAX;
+ Node *curr = firstAbove;
+ while (curr)
+ {
+ bool inLineWithEdge = (min[altDim] == curr->min[altDim]) ||
+ (min[altDim] == curr->max[altDim]);
+ if ( ! inLineWithEdge && (curr->max[dim] <= pos) )
+ {
+ result = std::max(curr->max[dim], result);
+ }
+ curr = curr->firstAbove;
+ }
+ return result;
+}
+
+double Node::firstPointBelow(size_t dim)
+{
+ // We are looking for the first obstacle below this position,
+ // though we ignore shape edges if this point is inline with
+ // the edge of the obstacle. That is, points have visibility
+ // along the edge of shapes.
+ size_t altDim = (dim + 1) % 2;
+ double result = DBL_MAX;
+ Node *curr = firstBelow;
+ while (curr)
+ {
+ bool inLineWithEdge = (min[altDim] == curr->min[altDim]) ||
+ (min[altDim] == curr->max[altDim]);
+ if ( ! inLineWithEdge && (curr->min[dim] >= pos) )
+ {
+ result = std::min(curr->min[dim], result);
+ }
+ curr = curr->firstBelow;
+ }
+ return result;
+}
+
+// This is a bit inefficient, but we won't need to do it once we have
+// connection points.
+bool Node::isInsideShape(size_t dimension)
+{
+ for (Node *curr = firstBelow; curr; curr = curr->firstBelow)
+ {
+ if ((curr->min[dimension] < pos) && (pos < curr->max[dimension]))
+ {
+ return true;
+ }
+ }
+ for (Node *curr = firstAbove; curr; curr = curr->firstAbove)
+ {
+ if ((curr->min[dimension] < pos) && (pos < curr->max[dimension]))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+Event::Event(EventType t, Node *v, double p)
+ : type(t),
+ v(v),
+ pos(p)
+{
+}
+
+
+// Used for quicksort. Must return <0, 0, or >0.
+int compare_events(const void *a, const void *b)
+{
+ Event *ea = *(Event**) a;
+ Event *eb = *(Event**) b;
+ if (ea->pos != eb->pos)
+ {
+ return (ea->pos < eb->pos) ? -1 : 1;
+ }
+ if (ea->type != eb->type)
+ {
+ return ea->type - eb->type;
+ }
+ COLA_ASSERT(ea->v != eb->v);
+ return (int)(ea->v - eb->v);
+}
+
+
+void buildConnectorRouteCheckpointCache(Router *router)
+{
+ for (ConnRefList::const_iterator curr = router->connRefs.begin();
+ curr != router->connRefs.end(); ++curr)
+ {
+ ConnRef *conn = *curr;
+ if (conn->routingType() != ConnType_Orthogonal)
+ {
+ continue;
+ }
+
+ PolyLine& displayRoute = conn->displayRoute();
+ std::vector<Checkpoint> checkpoints = conn->routingCheckpoints();
+
+ // Initialise checkpoint vector and set to false. There will be
+ // one entry for each *segment* in the path, and the value indicates
+ // whether the segment is affected by a checkpoint.
+ displayRoute.checkpointsOnRoute =
+ std::vector<std::pair<size_t, Point> >();
+
+ for (size_t ind = 0; ind < displayRoute.size(); ++ind)
+ {
+ if (ind > 0)
+ {
+ for (size_t cpi = 0; cpi < checkpoints.size(); ++cpi)
+ {
+ if (pointOnLine(displayRoute.ps[ind - 1],
+ displayRoute.ps[ind], checkpoints[cpi].point) )
+ {
+ // The checkpoint is on a segment.
+ displayRoute.checkpointsOnRoute.push_back(
+ std::make_pair((ind * 2) - 1,
+ checkpoints[cpi].point));
+ }
+ }
+ }
+
+ for (size_t cpi = 0; cpi < checkpoints.size(); ++cpi)
+ {
+ if (displayRoute.ps[ind].equals(checkpoints[cpi].point))
+ {
+ // The checkpoint is at a bendpoint.
+ displayRoute.checkpointsOnRoute.push_back(
+ std::make_pair(ind * 2, checkpoints[cpi].point));
+ }
+ }
+ }
+ }
+}
+
+
+void clearConnectorRouteCheckpointCache(Router *router)
+{
+ for (ConnRefList::const_iterator curr = router->connRefs.begin();
+ curr != router->connRefs.end(); ++curr)
+ {
+ ConnRef *conn = *curr;
+ if (conn->routingType() != ConnType_Orthogonal)
+ {
+ continue;
+ }
+
+ // Clear the cache.
+ PolyLine& displayRoute = conn->displayRoute();
+ displayRoute.checkpointsOnRoute.clear();
+ }
+}
+
+
+// Processes sweep events used to determine each horizontal and vertical
+// line segment in a connector's channel of visibility.
+// Four calls to this function are made at each position by the scanline:
+// 1) Handle all Close event processing.
+// 2) Remove Close event objects from the scanline.
+// 3) Add Open event objects to the scanline.
+// 4) Handle all Open event processing.
+//
+static void processShiftEvent(NodeSet& scanline, Event *e, size_t dim,
+ unsigned int pass)
+{
+ Node *v = e->v;
+
+ if ( ((pass == 3) && (e->type == Open)) ||
+ ((pass == 3) && (e->type == SegOpen)) )
+ {
+ std::pair<NodeSet::iterator, bool> result = scanline.insert(v);
+ v->iter = result.first;
+ COLA_ASSERT(result.second);
+
+ NodeSet::iterator it = v->iter;
+ // Work out neighbours
+ if (it != scanline.begin())
+ {
+ Node *u = *(--it);
+ v->firstAbove = u;
+ u->firstBelow = v;
+ }
+ it = v->iter;
+ if (++it != scanline.end())
+ {
+ Node *u = *it;
+ v->firstBelow = u;
+ u->firstAbove = v;
+ }
+ }
+
+ if ( ((pass == 4) && (e->type == Open)) ||
+ ((pass == 4) && (e->type == SegOpen)) ||
+ ((pass == 1) && (e->type == SegClose)) ||
+ ((pass == 1) && (e->type == Close)) )
+ {
+ if (v->ss)
+ {
+ // As far as we can see.
+ double minLimit = v->firstObstacleAbove(dim);
+ double maxLimit = v->firstObstacleBelow(dim);
+
+ v->ss->minSpaceLimit =
+ std::max(minLimit, v->ss->minSpaceLimit);
+ v->ss->maxSpaceLimit =
+ std::min(maxLimit, v->ss->maxSpaceLimit);
+ }
+ else
+ {
+ v->markShiftSegmentsAbove(dim);
+ v->markShiftSegmentsBelow(dim);
+ }
+ }
+
+ if ( ((pass == 2) && (e->type == SegClose)) ||
+ ((pass == 2) && (e->type == Close)) )
+ {
+ // Clean up neighbour pointers.
+ Node *l = v->firstAbove, *r = v->firstBelow;
+ if (l != nullptr)
+ {
+ l->firstBelow = v->firstBelow;
+ }
+ if (r != nullptr)
+ {
+ r->firstAbove = v->firstAbove;
+ }
+
+ size_t result;
+ result = scanline.erase(v);
+ COLA_ASSERT(result == 1);
+ COLA_UNUSED(result); // Avoid warning.
+ delete v;
+ }
+}
+
+void buildOrthogonalChannelInfo(Router *router,
+ const size_t dim, ShiftSegmentList& segmentList)
+{
+ if (segmentList.empty())
+ {
+ // There are no segments, so we can just return now.
+ return;
+ }
+
+ // Do a sweep to determine space for shifting segments.
+ size_t altDim = (dim + 1) % 2;
+ const size_t n = router->m_obstacles.size();
+ const size_t cpn = segmentList.size();
+ // Set up the events for the sweep.
+ size_t totalEvents = 2 * (n + cpn);
+ Event **events = new Event*[totalEvents];
+ unsigned ctr = 0;
+ ObstacleList::iterator obstacleIt = router->m_obstacles.begin();
+ for (unsigned i = 0; i < n; i++)
+ {
+ Obstacle *obstacle = *obstacleIt;
+ JunctionRef *junction = dynamic_cast<JunctionRef *> (obstacle);
+ if (junction && ! junction->positionFixed())
+ {
+ // Junctions that are free to move are not treated as obstacles.
+ ++obstacleIt;
+ totalEvents -= 2;
+ continue;
+ }
+ Box bBox = obstacle->routingBox();
+ Point min = bBox.min;
+ Point max = bBox.max;
+ double mid = min[dim] + ((max[dim] - min[dim]) / 2);
+ Node *v = new Node(obstacle, mid);
+ events[ctr++] = new Event(Open, v, min[altDim]);
+ events[ctr++] = new Event(Close, v, max[altDim]);
+
+ ++obstacleIt;
+ }
+ for (ShiftSegmentList::iterator curr = segmentList.begin();
+ curr != segmentList.end(); ++curr)
+ {
+ const Point& lowPt = (*curr)->lowPoint();
+ const Point& highPt = (*curr)->highPoint();
+
+ COLA_ASSERT(lowPt[dim] == highPt[dim]);
+ COLA_ASSERT(lowPt[altDim] < highPt[altDim]);
+ Node *v = new Node(*curr, lowPt[dim]);
+ events[ctr++] = new Event(SegOpen, v, lowPt[altDim]);
+ events[ctr++] = new Event(SegClose, v, highPt[altDim]);
+ }
+ qsort((Event*)events, (size_t) totalEvents, sizeof(Event*), compare_events);
+
+ // Process the sweep.
+ // We do multiple passes over sections of the list so we can add relevant
+ // entries to the scanline that might follow, before process them.
+ NodeSet scanline;
+ double thisPos = (totalEvents > 0) ? events[0]->pos : 0;
+ unsigned int posStartIndex = 0;
+ unsigned int posFinishIndex = 0;
+ for (unsigned i = 0; i <= totalEvents; ++i)
+ {
+ // If we have finished the current scanline or all events, then we
+ // process the events on the current scanline in a couple of passes.
+ if ((i == totalEvents) || (events[i]->pos != thisPos))
+ {
+ posFinishIndex = i;
+ for (int pass = 2; pass <= 4; ++pass)
+ {
+ for (unsigned j = posStartIndex; j < posFinishIndex; ++j)
+ {
+ processShiftEvent(scanline, events[j], dim, pass);
+ }
+ }
+
+ if (i == totalEvents)
+ {
+ // We have cleaned up, so we can now break out of loop.
+ break;
+ }
+
+ thisPos = events[i]->pos;
+ posStartIndex = i;
+ }
+
+ // Do the first sweep event handling -- building the correct
+ // structure of the scanline.
+ const int pass = 1;
+ processShiftEvent(scanline, events[i], dim, pass);
+ }
+ COLA_ASSERT(scanline.size() == 0);
+ for (unsigned i = 0; i < totalEvents; ++i)
+ {
+ delete events[i];
+ }
+ delete [] events;
+}
+
+
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/scanline.h b/src/3rdparty/adaptagrams/libavoid/scanline.h
new file mode 100644
index 0000000..5a6d029
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/scanline.h
@@ -0,0 +1,136 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2009-2013 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+
+#ifndef AVOID_SCANLINE_H
+#define AVOID_SCANLINE_H
+
+#include <set>
+#include <list>
+
+#include "libavoid/geomtypes.h"
+
+
+namespace Avoid {
+
+static const double CHANNEL_MAX = 100000000;
+
+
+class Obstacle;
+class VertInf;
+
+// ShiftSegment interface.
+class ShiftSegment
+{
+ public:
+ ShiftSegment(const size_t dim)
+ : dimension(dim)
+ {
+ }
+ virtual ~ShiftSegment()
+ {
+ }
+ virtual Point& lowPoint(void) = 0;
+ virtual Point& highPoint(void) = 0;
+ virtual const Point& lowPoint(void) const = 0;
+ virtual const Point& highPoint(void) const = 0;
+ virtual bool overlapsWith(const ShiftSegment *rhs,
+ const size_t dim) const = 0;
+ virtual bool immovable(void) const = 0;
+
+ size_t dimension;
+ double minSpaceLimit;
+ double maxSpaceLimit;
+};
+typedef std::list<ShiftSegment *> ShiftSegmentList;
+
+
+class Node;
+struct CmpNodePos
+{
+ bool operator()(const Node* u, const Node* v) const;
+};
+
+
+typedef std::set<Node*,CmpNodePos> NodeSet;
+
+class Node
+{
+ public:
+
+ Obstacle *v;
+ VertInf *c;
+ ShiftSegment *ss;
+ double pos;
+ double min[2], max[2];
+ Node *firstAbove, *firstBelow;
+ NodeSet::iterator iter;
+
+ Node(Obstacle *v, const double p);
+ Node(VertInf *c, const double p);
+ Node(ShiftSegment *ss, const double p);
+ virtual ~Node();
+ double firstObstacleAbove(size_t dim);
+ double firstObstacleBelow(size_t dim);
+ void markShiftSegmentsAbove(size_t dim);
+ void markShiftSegmentsBelow(size_t dim);
+ void findFirstPointAboveAndBelow(const size_t dim, const double linePos,
+ double& firstAbovePos, double& firstBelowPos,
+ double& lastAbovePos, double& lastBelowPos);
+ double firstPointAbove(size_t dim);
+ double firstPointBelow(size_t dim);
+ bool isInsideShape(size_t dimension);
+};
+
+
+// Note: Open must come first.
+typedef enum {
+ Open = 1,
+ SegOpen = 2,
+ ConnPoint = 3,
+ SegClose = 4,
+ Close = 5
+} EventType;
+
+
+struct Event
+{
+ Event(EventType t, Node *v, double p);
+
+ EventType type;
+ Node *v;
+ double pos;
+};
+
+
+extern int compare_events(const void *a, const void *b);
+extern void buildConnectorRouteCheckpointCache(Router *router);
+extern void clearConnectorRouteCheckpointCache(Router *router);
+extern void buildOrthogonalChannelInfo(Router *router,
+ const size_t dim, ShiftSegmentList& segmentList);
+
+
+}
+
+#endif
diff --git a/src/3rdparty/adaptagrams/libavoid/shape.cpp b/src/3rdparty/adaptagrams/libavoid/shape.cpp
new file mode 100644
index 0000000..7a80907
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/shape.cpp
@@ -0,0 +1,280 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2013 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+#include <cstdlib>
+
+#include "libavoid/shape.h"
+#include "libavoid/vertices.h"
+#include "libavoid/router.h"
+#include "libavoid/connend.h"
+#include "libavoid/debug.h"
+#include "libavoid/assertions.h"
+#include "libavoid/connectionpin.h"
+
+
+namespace Avoid {
+
+
+ShapeRef::ShapeRef(Router *router, Polygon& ply, const unsigned int id)
+ : Obstacle(router, ply, id)
+{
+ m_router->addShape(this);
+}
+
+
+ShapeRef::~ShapeRef()
+{
+ if (m_router->m_currently_calling_destructors == false)
+ {
+ err_printf("ERROR: ShapeRef::~ShapeRef() shouldn't be called directly.\n");
+ err_printf(" It is owned by the router. Call Router::deleteShape() instead.\n");
+ abort();
+ }
+}
+
+
+void ShapeRef::moveAttachedConns(const Polygon& newPoly)
+{
+ // Update positions of attached connector ends.
+ for (std::set<ConnEnd *>::iterator curr = m_following_conns.begin();
+ curr != m_following_conns.end(); ++curr)
+ {
+ ConnEnd *connEnd = *curr;
+ COLA_ASSERT(connEnd->m_conn_ref != nullptr);
+ bool connPinUpdate = true;
+ m_router->modifyConnector(connEnd->m_conn_ref, connEnd->endpointType(),
+ *connEnd, connPinUpdate);
+ }
+ for (ShapeConnectionPinSet::iterator curr =
+ m_connection_pins.begin(); curr != m_connection_pins.end(); ++curr)
+ {
+ ShapeConnectionPin *pin = *curr;
+ pin->updatePosition(newPoly);
+ }
+}
+
+static double absoluteOffsetInverse(double offset,
+ const Box& shapeBox, size_t toDim)
+{
+ if (offset == ATTACH_POS_MIN_OFFSET)
+ {
+ return ATTACH_POS_MAX_OFFSET;
+ }
+
+ if (offset == ATTACH_POS_MAX_OFFSET)
+ {
+ return ATTACH_POS_MIN_OFFSET;
+ }
+
+ return shapeBox.length(toDim) - offset;
+}
+
+void ShapeRef::transformConnectionPinPositions(
+ ShapeTransformationType transform)
+{
+ for (ShapeConnectionPinSet::iterator curr =
+ m_connection_pins.begin(); curr != m_connection_pins.end(); ++curr)
+ {
+ ShapeConnectionPin *pin = *curr;
+ double usingProportionalOffsets = pin->m_using_proportional_offsets;
+ double& xOffset = pin->m_x_offset;
+ double& yOffset = pin->m_y_offset;
+ ConnDirFlags& visDirs = pin->m_visibility_directions;
+ double tmpOffset;
+
+ // Number of clockwise 90 degree rotations;
+ unsigned int rotationN = 0;
+
+ if (usingProportionalOffsets)
+ {
+ // Translate to Origin.
+ xOffset -= 0.5;
+ yOffset -= 0.5;
+
+ switch (transform)
+ {
+ case TransformationType_CW90:
+ rotationN = 3;
+ // Y <- inverse X, X <- inverse Y
+ tmpOffset = yOffset;
+ yOffset = xOffset;
+ xOffset = -tmpOffset;
+ break;
+ case TransformationType_CW180:
+ rotationN = 2;
+ // Y <- inverse Y, X <- inverse X
+ yOffset = -yOffset;
+ xOffset = -xOffset;
+ break;
+ case TransformationType_CW270:
+ rotationN = 1;
+ // Y <- X, X <- Y
+ tmpOffset = yOffset;
+ yOffset = -xOffset;
+ xOffset = tmpOffset;
+ break;
+ case TransformationType_FlipX:
+ // Y <- Y, X <- inverse X
+ xOffset = -xOffset;
+ break;
+ case TransformationType_FlipY:
+ // X <- inverse X, Y <- Y
+ yOffset = -yOffset;
+ break;
+ }
+ // Translate back.
+ xOffset += 0.5;
+ yOffset += 0.5;
+ }
+ else
+ {
+ // Using absolute offsets for pin.
+
+ const Box shapeBox = pin->m_shape->polygon().offsetBoundingBox(0.0);
+ switch (transform)
+ {
+ case TransformationType_CW90:
+ rotationN = 3;
+ // Y <- inverse X, X <- inverse Y
+ tmpOffset = yOffset;
+ yOffset = xOffset;
+ xOffset = absoluteOffsetInverse(tmpOffset, shapeBox, XDIM);
+ break;
+ case TransformationType_CW180:
+ rotationN = 2;
+ // Y <- inverse Y, X <- inverse X
+ yOffset = absoluteOffsetInverse(yOffset, shapeBox, YDIM);
+ xOffset = absoluteOffsetInverse(xOffset, shapeBox, XDIM);
+ break;
+ case TransformationType_CW270:
+ rotationN = 1;
+ // Y <- X, X <- Y
+ tmpOffset = yOffset;
+ yOffset = absoluteOffsetInverse(xOffset, shapeBox, YDIM);
+ xOffset = tmpOffset;
+ break;
+ case TransformationType_FlipX:
+ // Y <- Y, X <- inverse X
+ xOffset = absoluteOffsetInverse(xOffset, shapeBox, XDIM);
+ break;
+ case TransformationType_FlipY:
+ // X <- inverse X, Y <- Y
+ yOffset = absoluteOffsetInverse(yOffset, shapeBox, YDIM);
+ break;
+ }
+ }
+
+ if ( (visDirs & ConnDirAll) && (visDirs != ConnDirAll) )
+ {
+ // Visibility is set, but not in all directions.
+
+ const unsigned int dirU = 0;
+ const unsigned int dirR = 1;
+ const unsigned int dirD = 2;
+ const unsigned int dirL = 3;
+
+ bool visInDir[4] = { false };
+ if (visDirs & ConnDirUp) visInDir[dirU] = true;
+ if (visDirs & ConnDirRight) visInDir[dirR] = true;
+ if (visDirs & ConnDirDown) visInDir[dirD] = true;
+ if (visDirs & ConnDirLeft) visInDir[dirL] = true;
+
+ if (transform == TransformationType_FlipY)
+ {
+ bool tmpBool = visInDir[dirU];
+ visInDir[dirU] = visInDir[dirD];
+ visInDir[dirD] = tmpBool;
+ }
+ else if (transform == TransformationType_FlipX)
+ {
+ bool tmpBool = visInDir[dirL];
+ visInDir[dirL] = visInDir[dirR];
+ visInDir[dirR] = tmpBool;
+ }
+
+ visDirs = ConnDirNone;
+ if (visInDir[(rotationN + dirU) % 4]) visDirs |= ConnDirUp;
+ if (visInDir[(rotationN + dirR) % 4]) visDirs |= ConnDirRight;
+ if (visInDir[(rotationN + dirD) % 4]) visDirs |= ConnDirDown;
+ if (visInDir[(rotationN + dirL) % 4]) visDirs |= ConnDirLeft;
+ }
+ pin->updatePositionAndVisibility();
+ m_router->modifyConnectionPin(pin);
+ }
+}
+
+
+const Polygon& ShapeRef::polygon(void) const
+{
+ return m_polygon;
+}
+
+
+void ShapeRef::outputCode(FILE *fp) const
+{
+ fprintf(fp, " // shapeRef%u\n", id());
+ fprintf(fp, " polygon = Polygon(%lu);\n", (unsigned long) polygon().size());
+ for (size_t i = 0; i < polygon().size(); ++i)
+ {
+ fprintf(fp, " polygon.ps[%lu] = Point(%" PREC "g, %" PREC "g);\n",
+ (unsigned long) i, polygon().at(i).x, polygon().at(i).y);
+ }
+
+ fprintf(fp, " ");
+ if (!m_connection_pins.empty())
+ {
+ fprintf(fp, "ShapeRef *shapeRef%u = ", id());
+ }
+ fprintf(fp, "new ShapeRef(router, polygon, %u);\n", id());
+ for (ShapeConnectionPinSet::const_iterator curr =
+ m_connection_pins.begin();
+ curr != m_connection_pins.end(); ++curr)
+ {
+ (*curr)->outputCode(fp);
+ }
+ fprintf(fp, "\n");
+}
+
+
+Point ShapeRef::position(void) const
+{
+ Box bBox = routingBox();
+
+ Point centre;
+
+ centre.x = bBox.min.x + (0.5 * (bBox.max.x - bBox.min.x));
+ centre.y = bBox.min.y + (0.5 * (bBox.max.y - bBox.min.y));
+
+ return centre;
+}
+
+
+void ShapeRef::setCentrePos(const Point& newCentre)
+{
+ Point diff = newCentre - position();
+ m_polygon.translate(diff.x, diff.y);
+}
+
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/shape.h b/src/3rdparty/adaptagrams/libavoid/shape.h
new file mode 100644
index 0000000..f6d7076
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/shape.h
@@ -0,0 +1,165 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2011 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+//! @file shape.h
+//! @brief Contains the interface for the ShapeRef class.
+
+
+#ifndef AVOID_SHAPE_H
+#define AVOID_SHAPE_H
+
+#include <list>
+#include <set>
+
+#include <cstdio>
+
+#include "libavoid/dllexport.h"
+#include "libavoid/geometry.h"
+#include "libavoid/obstacle.h"
+
+namespace topology {
+ class LayoutObstacle;
+}
+
+namespace Avoid {
+
+class VertInf;
+class Router;
+class ShapeRef;
+class ConnEnd;
+class ShapeConnectionPin;
+class ConnRef;
+typedef std::list<ShapeRef *> ShapeRefList;
+
+//! @brief Describes the type of transformation that has been applied to a
+//! shape having its transformConnectionPinPositions() method called.
+enum ShapeTransformationType
+{
+ //! @brief The shape has been rotated clockwise by 90 degrees.
+ TransformationType_CW90 = 0,
+ //! @brief The shape has been rotated clockwise by 180 degrees.
+ TransformationType_CW180 = 1,
+ //! @brief The shape has been rotated clockwise by 270 degrees.
+ TransformationType_CW270 = 2,
+ //! @brief The shape has been flipped horizontally in the X-dimension.
+ TransformationType_FlipX = 3,
+ //! @brief The shape has been flipped vertically in the Y-dimension.
+ TransformationType_FlipY = 4
+};
+
+
+//! @brief The ShapeRef class represents a shape object.
+//!
+//! Shapes are obstacles that connectors must be routed around. They can be
+//! placed into a Router scene and can be repositioned or resized (via
+//! Router::moveShape()).
+//!
+//! Usually, it is expected that you would create a ShapeRef for each shape
+//! in your diagram and keep that reference in your own shape class.
+//!
+class AVOID_EXPORT ShapeRef : public Obstacle
+{
+ public:
+ //! @brief Shape reference constructor.
+ //!
+ //! Creates a shape object reference, and adds it to the router
+ //! scene. This shape will be considered to be an obstacle.
+ //! This will cause connectors intersecting the newly added shape
+ //! to be marked as needing to be rerouted.
+ //!
+ //! If the router is using transactions, then changes will occur
+ //! the next time Router::processTransaction() is called. See
+ //! Router::setTransactionUse() for more information.
+ //!
+ //! The shape can be moved with Router::moveShape() and removed
+ //! from the scene and freed with Router::deleteShape().
+ //!
+ //! The poly argument will usually be the boundary of the shape in your
+ //! application with additional buffer of several pixels on each side.
+ //! Specifying such a buffer results in connectors leaving a small
+ //! amount of space around shapes, rather than touching them on the
+ //! corners or edges.
+ //!
+ //! @note Regarding IDs:
+ //! You can let libavoid manually handle IDs by not specifying
+ //! them. Alternatively, you can specify all IDs yourself, but
+ //! you must be careful to makes sure that each object in the
+ //! scene (shape, connector, cluster, etc) is given a unique,
+ //! positive ID. This uniqueness is checked if assertions are
+ //! enabled, but if not and there are clashes then strange
+ //! things can happen.
+ //!
+ //! @param[in] router The router scene to place the shape into.
+ //! @param[in] poly A Polygon representing the boundary of the
+ //! shape.
+ //! @param[in] id Optionally, a positive integer ID unique
+ //! among all objects.
+ //!
+ ShapeRef(Router *router, Polygon& poly, const unsigned int id = 0);
+
+// To prevent C++ objects from being destroyed in garbage collected languages
+// when the libraries are called from SWIG, we hide the declarations of the
+// destructors and prevent generation of default destructors.
+#ifndef SWIG
+ //! @brief Shape reference destructor.
+ //!
+ //! Do not call this yourself, instead call Router::deleteShape().
+ //! Ownership of this object belongs to the router scene.
+ virtual ~ShapeRef();
+#endif
+
+ //! @brief Returns a reference to the polygon boundary of this shape.
+ //! @returns A reference to the polygon boundary of the shape.
+ const Polygon& polygon(void) const;
+
+ //! @brief Adjusts all of the shape's connection pin positions and
+ //! visibility directions for a given transformation type.
+ //!
+ //! @param[in] transform A ShapeTransformationType specifying the
+ //! type of transform to be applied to all
+ //! connection pins for the shape.
+ //!
+ void transformConnectionPinPositions(ShapeTransformationType transform);
+
+ Point position(void) const;
+ private:
+ friend class Router;
+ friend class ConnEnd;
+ friend class ShapeConnectionPin;
+ friend class topology::LayoutObstacle;
+
+ void outputCode(FILE *fp) const;
+ void moveAttachedConns(const Polygon& newPoly);
+ void assignPinVisibilityTo(const unsigned int pinClassId,
+ VertInf *dummyConnectionVert);
+ void setCentrePos(const Point& newCentre);
+};
+
+
+}
+
+
+#endif
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/2junctions.cpp b/src/3rdparty/adaptagrams/libavoid/tests/2junctions.cpp
new file mode 100644
index 0000000..4ba4233
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/2junctions.cpp
@@ -0,0 +1,108 @@
+#include "libavoid/libavoid.h"
+#include <sstream>
+using namespace Avoid;
+
+int test()
+{
+ Avoid::ConnEnd end1;
+ Avoid::ConnEnd end2;
+ Avoid::Polygon poly;
+ Avoid::Router * router1 = new Avoid::Router(Avoid::OrthogonalRouting);
+ router1->setTransactionUse(true);
+ router1->setRoutingPenalty(Avoid::segmentPenalty);
+ router1->setRoutingPenalty(Avoid::crossingPenalty);
+ router1->setRoutingPenalty(Avoid::fixedSharedPathPenalty);
+ router1->setRoutingOption(Avoid::penaliseOrthogonalSharedPathsAtConnEnds, true);
+ router1->setRoutingParameter(idealNudgingDistance, 25);
+ poly = Avoid::Polygon(4);
+ poly.setPoint(0, Avoid::Point(51410, 50640));
+ poly.setPoint(1, Avoid::Point(51410, 50960));
+ poly.setPoint(2, Avoid::Point(51050, 50960));
+ poly.setPoint(3, Avoid::Point(51050, 50640));
+ Avoid::ShapeRef * shape365249936 = new Avoid::ShapeRef(router1, poly, 365249936);
+ Avoid::ShapeConnectionPin * pin365249936_2 = new Avoid::ShapeConnectionPin(shape365249936, 3, 0, 0.5, true, 10, 4);
+ pin365249936_2->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin365249936_4 = new Avoid::ShapeConnectionPin(shape365249936, 5, 0, 0.734375, true, 10, 4);
+ pin365249936_4->setExclusive(true);
+ poly = Avoid::Polygon(4);
+ poly.setPoint(0, Avoid::Point(50760, 50691));
+ poly.setPoint(1, Avoid::Point(50760, 50775));
+ poly.setPoint(2, Avoid::Point(50640, 50775));
+ poly.setPoint(3, Avoid::Point(50640, 50691));
+ Avoid::ShapeRef * shape386142480 = new Avoid::ShapeRef(router1, poly, 386142480);
+ Avoid::ShapeConnectionPin * pin386142480_1 = new Avoid::ShapeConnectionPin(shape386142480, 2, 0.5, 1, true, 10, 2);
+ pin386142480_1->setExclusive(true);
+ Avoid::JunctionRef * junction328922310 = new Avoid::JunctionRef(router1, Avoid::Point(50700, 50800), 328922310);
+ junction328922310->setPositionFixed(true);
+ end1 = Avoid::ConnEnd(shape365249936, 3);
+ end2 = Avoid::ConnEnd(junction328922310);
+ /*Avoid::ConnRef * conn152169328 = */ new Avoid::ConnRef(router1, end1, end2);
+ end1 = Avoid::ConnEnd(junction328922310);
+ end2 = Avoid::ConnEnd(shape386142480, 2);
+ /*Avoid::ConnRef * conn684888074 = */ new Avoid::ConnRef(router1, end1, end2);
+ end1 = Avoid::ConnEnd(shape365249936, 5);
+ end2 = Avoid::ConnEnd(junction328922310);
+ Avoid::ConnRef * conn18168360 = new Avoid::ConnRef(router1, end1, end2);
+ router1->processTransaction();
+
+ router1->outputDiagram("output/2junctions-1");
+ poly = Avoid::Polygon(4);
+ poly.setPoint(0, Avoid::Point(50879, 50885));
+ poly.setPoint(1, Avoid::Point(50879, 50960));
+ poly.setPoint(2, Avoid::Point(50821, 50960));
+ poly.setPoint(3, Avoid::Point(50821, 50885));
+ Avoid::ShapeRef * shape150429385 = new Avoid::ShapeRef(router1, poly, 150429385);
+ Avoid::ShapeConnectionPin * pin150429385_0 = new Avoid::ShapeConnectionPin(shape150429385, 1, 0.5, 0, true, 10, 1);
+ pin150429385_0->setExclusive(true);
+ Avoid::JunctionRef * junction550292508 = new Avoid::JunctionRef(router1, Avoid::Point(50850, 50875), 550292508);
+ router1->deleteConnector(conn18168360);
+ conn18168360 = nullptr;
+ end1 = Avoid::ConnEnd(shape365249936, 5);
+ end2 = Avoid::ConnEnd(junction550292508);
+ Avoid::ConnRef * conn795337150 = new Avoid::ConnRef(router1, end1, end2);
+ conn795337150->makePathInvalid();
+ end1 = Avoid::ConnEnd(junction550292508);
+ end2 = Avoid::ConnEnd(junction328922310);
+ Avoid::ConnRef * conn151961380 = new Avoid::ConnRef(router1, end1, end2);
+ conn151961380->makePathInvalid();
+ end1 = Avoid::ConnEnd(shape150429385, 1);
+ end2 = Avoid::ConnEnd(junction550292508);
+ Avoid::ConnRef * conn149180423 = new Avoid::ConnRef(router1, end1, end2);
+ conn149180423->makePathInvalid();
+ router1->processTransaction();
+
+ router1->outputDiagram("output/2junctions-2");
+ /*
+ junction550292508->setPositionFixed(true);
+ router1->deleteShape(shape365249936);
+ shape365249936 = nullptr;
+ router1->deleteShape(shape386142480);
+ shape386142480 = nullptr;
+ router1->deleteJunction(junction328922310);
+ junction328922310 = nullptr;
+ router1->deleteConnector(conn152169328);
+ conn152169328 = nullptr;
+ router1->deleteConnector(conn684888074);
+ conn684888074 = nullptr;
+ router1->deleteShape(shape150429385);
+ shape150429385 = nullptr;
+ router1->deleteJunction(junction550292508);
+ junction550292508 = nullptr;
+ router1->deleteConnector(conn795337150);
+ conn795337150 = nullptr;
+ router1->deleteConnector(conn151961380);
+ conn151961380 = nullptr;
+ router1->deleteConnector(conn149180423);
+ conn149180423 = nullptr;
+ router1->processTransaction();
+*/
+ bool atEnds = true;
+ bool overlap = router1->existsOrthogonalFixedSegmentOverlap(atEnds);
+ delete router1;
+ return (overlap) ? 1 : 0;
+}
+
+extern "C" int main(void)
+{
+ return test();
+}
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/Makefile.am b/src/3rdparty/adaptagrams/libavoid/tests/Makefile.am
new file mode 100644
index 0000000..3fc4324
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/Makefile.am
@@ -0,0 +1,217 @@
+AM_CPPFLAGS = -I$(top_srcdir)
+
+LDADD = $(top_builddir)/libavoid/libavoid.la
+
+# Disabled tests:
+# corneroverlap01
+# unsatisfiableRangeAssertion - really slow.
+
+check_PROGRAMS = \
+ removeJunctions01 \
+ penaltyRerouting01 \
+ treeRootCrash01 \
+ treeRootCrash02 \
+ forwardFlowingConnectors01 \
+ example \
+ endlessLoop01 \
+ complex \
+ multiconnact \
+ inline \
+ infinity \
+ latesetup \
+ inlineoverlap01 \
+ inlineoverlap02 \
+ inlineoverlap03 \
+ inlineoverlap04 \
+ inlineoverlap05 \
+ inlineoverlap06 \
+ inlineoverlap07 \
+ inlineoverlap08 \
+ inlineOverlap09 \
+ inlineOverlap10 \
+ inlineOverlap11 \
+ nudgeintobug \
+ slowrouting \
+ tjunct \
+ vertlineassertion \
+ orthordering01 \
+ orthordering02 \
+ orderassertion \
+ connendmove \
+ connectionpin01 \
+ connectionpin02 \
+ connectionpin03 \
+ junction01 \
+ junction02 \
+ junction03 \
+ junction04 \
+ nudgeold \
+ lineSegWrapperCrash1 \
+ lineSegWrapperCrash2 \
+ lineSegWrapperCrash3 \
+ lineSegWrapperCrash4 \
+ lineSegWrapperCrash5 \
+ lineSegWrapperCrash6 \
+ lineSegWrapperCrash7 \
+ lineSegWrapperCrash8 \
+ node1 \
+ overlappingRects \
+ inlineShapes \
+ checkpoints01 \
+ checkpoints02 \
+ checkpoints03 \
+ freeFloatingDirection01 \
+ restrictedNudging \
+ performance01 \
+ hyperedge01 \
+ hyperedge02 \
+ improveHyperedge01 \
+ improveHyperedge02 \
+ improveHyperedge03 \
+ improveHyperedge04 \
+ improveHyperedge05 \
+ improveHyperedge06 \
+ validPaths01 \
+ validPaths02 \
+ 2junctions \
+ hyperedgeLoop1 \
+ buildOrthogonalChannelInfo1 \
+ finalSegmentNudging1 \
+ finalSegmentNudging2 \
+ finalSegmentNudging3 \
+ checkpointNudging1 \
+ checkpointNudging2 \
+ checkpointNudging3 \
+ nudgeCrossing01 \
+ nudgingSkipsCheckpoint01 \
+ nudgingSkipsCheckpoint02 \
+ hola01 \
+ hyperedgeRerouting01
+
+# problem_SOURCES = problem.cpp
+
+hola01_SOURCES = hola01.cpp
+
+penaltyRerouting01_SOURCES = penaltyRerouting01.cpp
+
+treeRootCrash01_SOURCES = treeRootCrash01.cpp
+treeRootCrash02_SOURCES = treeRootCrash02.cpp
+
+hyperedgeRerouting01_SOURCES = hyperedgeRerouting01.cpp
+
+forwardFlowingConnectors01_SOURCES = forwardFlowingConnectors01.cpp
+
+# unsatisfiableRangeAssertion_SOURCES = unsatisfiableRangeAssertion.cpp
+
+removeJunctions01_SOURCES = removeJunctions01.cpp
+
+endlessLoop01_SOURCES = endlessLoop01.cpp
+
+nudgingSkipsCheckpoint01_SOURCES = nudgingSkipsCheckpoint01.cpp
+nudgingSkipsCheckpoint02_SOURCES = nudgingSkipsCheckpoint02.cpp
+
+nudgeCrossing01_SOURCES = nudgeCrossing01.cpp
+
+checkpointNudging1_SOURCES = checkpointNudging1.cpp
+checkpointNudging2_SOURCES = checkpointNudging2.cpp
+checkpointNudging3_SOURCES = checkpointNudging3.cpp
+
+finalSegmentNudging1_SOURCES = finalSegmentNudging1.cpp
+finalSegmentNudging2_SOURCES = finalSegmentNudging2.cpp
+finalSegmentNudging3_SOURCES = finalSegmentNudging3.cpp
+
+buildOrthogonalChannelInfo1_SOURCES = buildOrthogonalChannelInfo1.cpp
+
+hyperedgeLoop1_SOURCES = hyperedgeLoop1.cpp
+
+improveHyperedge01_SOURCES = improveHyperedge01.cpp
+improveHyperedge02_SOURCES = improveHyperedge02.cpp
+improveHyperedge03_SOURCES = improveHyperedge03.cpp
+improveHyperedge04_SOURCES = improveHyperedge04.cpp
+improveHyperedge05_SOURCES = improveHyperedge05.cpp
+improveHyperedge06_SOURCES = improveHyperedge06.cpp
+
+performance01_SOURCES = performance01.cpp
+
+restrictedNudging_SOURCES = restrictedNudging.cpp
+
+freeFloatingDirection01_SOURCES = freeFloatingDirection01.cpp
+
+checkpoints01_SOURCES = checkpoints01.cpp
+checkpoints02_SOURCES = checkpoints02.cpp
+checkpoints03_SOURCES = checkpoints03.cpp
+inlineShapes_SOURCES = inlineShapes.cpp
+
+2junctions_SOURCES = 2junctions.cpp
+overlappingRects_SOURCES = overlappingRects.cpp
+
+lineSegWrapperCrash1_SOURCES = lineSegWrapperCrash1.cpp
+lineSegWrapperCrash2_SOURCES = lineSegWrapperCrash2.cpp
+lineSegWrapperCrash3_SOURCES = lineSegWrapperCrash3.cpp
+lineSegWrapperCrash4_SOURCES = lineSegWrapperCrash4.cpp
+lineSegWrapperCrash5_SOURCES = lineSegWrapperCrash5.cpp
+lineSegWrapperCrash6_SOURCES = lineSegWrapperCrash6.cpp
+lineSegWrapperCrash7_SOURCES = lineSegWrapperCrash7.cpp
+lineSegWrapperCrash8_SOURCES = lineSegWrapperCrash8.cpp
+
+example_SOURCES = example.cpp
+validPaths01_SOURCES = validPaths01.cpp
+validPaths02_SOURCES = validPaths02.cpp
+
+multiconnact_SOURCES = multiconnact.cpp
+
+complex_SOURCES = complex.cpp
+
+inline_SOURCES = inline.cpp
+
+infinity_SOURCES = infinity.cpp
+
+latesetup_SOURCES = latesetup.cpp
+
+nudgeold_SOURCES = nudgeold.cpp
+
+node1_SOURCES = node1.cpp
+
+vertlineassertion_SOURCES = vertlineassertion.cpp
+
+inlineoverlap01_SOURCES = inlineoverlap01.cpp
+inlineoverlap02_SOURCES = inlineoverlap02.cpp
+inlineoverlap03_SOURCES = inlineoverlap03.cpp
+inlineoverlap04_SOURCES = inlineoverlap04.cpp
+inlineoverlap05_SOURCES = inlineoverlap05.cpp
+inlineoverlap06_SOURCES = inlineoverlap06.cpp
+inlineoverlap07_SOURCES = inlineoverlap07.cpp
+inlineoverlap08_SOURCES = inlineoverlap08.cpp
+inlineOverlap09_SOURCES = inlineOverlap09.cpp
+inlineOverlap10_SOURCES = inlineOverlap10.cpp
+inlineOverlap11_SOURCES = inlineOverlap11.cpp
+
+# corneroverlap01_SOURCES = corneroverlap01.cpp
+
+orthordering01_SOURCES = orthordering01.cpp
+orthordering02_SOURCES = orthordering02.cpp
+
+tjunct_SOURCES = tjunct.cpp
+
+hyperedge01_SOURCES = hyperedge01.cpp
+hyperedge02_SOURCES = hyperedge02.cpp
+
+nudgeintobug_SOURCES = nudgeintobug.cpp
+
+slowrouting_SOURCES = slowrouting.cpp
+
+orderassertion_SOURCES = orderassertion.cpp
+
+connendmove_SOURCES = connendmove.cpp
+
+connectionpin01_SOURCES = connectionpin01.cpp
+connectionpin02_SOURCES = connectionpin02.cpp
+connectionpin03_SOURCES = connectionpin03.cpp
+
+junction01_SOURCES = junction01.cpp
+junction02_SOURCES = junction02.cpp
+junction03_SOURCES = junction03.cpp
+junction04_SOURCES = junction04.cpp
+
+TESTS = $(check_PROGRAMS)
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/buildOrthogonalChannelInfo1.cpp b/src/3rdparty/adaptagrams/libavoid/tests/buildOrthogonalChannelInfo1.cpp
new file mode 100644
index 0000000..ef2144a
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/buildOrthogonalChannelInfo1.cpp
@@ -0,0 +1,65 @@
+#include "libavoid/libavoid.h"
+#include <sstream>
+using namespace Avoid;
+
+void test()
+{
+ Avoid::ConnEnd end1;
+ Avoid::ConnEnd end2;
+ Avoid::Polygon poly;
+ Avoid::Router * router1 = new Avoid::Router(Avoid::OrthogonalRouting);
+ router1->setTransactionUse(true);
+ router1->setRoutingPenalty(Avoid::segmentPenalty);
+ router1->setRoutingPenalty(Avoid::crossingPenalty);
+ router1->setRoutingPenalty(Avoid::fixedSharedPathPenalty, 9000);
+ router1->setRoutingOption(Avoid::penaliseOrthogonalSharedPathsAtConnEnds, true);
+ router1->setRoutingParameter(idealNudgingDistance, 25);
+ poly = Avoid::Polygon(4);
+ poly.setPoint(0, Avoid::Point(50760, 50691));
+ poly.setPoint(1, Avoid::Point(50760, 50775));
+ poly.setPoint(2, Avoid::Point(50640, 50775));
+ poly.setPoint(3, Avoid::Point(50640, 50691));
+ Avoid::ShapeRef * shape386142480 = new Avoid::ShapeRef(router1, poly, 386142480);
+ Avoid::ShapeConnectionPin * pin386142480_0 = new Avoid::ShapeConnectionPin(shape386142480, 1, 0.5, 0.40476190476190477, true, 0, 13);
+ pin386142480_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin386142480_1 = new Avoid::ShapeConnectionPin(shape386142480, 2, 0.5, 1, true, 10, 2);
+ pin386142480_1->setExclusive(true);
+ poly = Avoid::Polygon(4);
+ poly.setPoint(0, Avoid::Point(51185, 50765));
+ poly.setPoint(1, Avoid::Point(51185, 50935));
+ poly.setPoint(2, Avoid::Point(50975, 50935));
+ poly.setPoint(3, Avoid::Point(50975, 50765));
+ Avoid::ShapeRef * shape300136482 = new Avoid::ShapeRef(router1, poly, 300136482);
+ Avoid::ShapeConnectionPin * pin300136482_0 = new Avoid::ShapeConnectionPin(shape300136482, 1, 0, 0.5, true, 10, 4);
+ pin300136482_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin300136482_1 = new Avoid::ShapeConnectionPin(shape300136482, 2, 0.95238095238095233, 0.5, true, 10, 8);
+ pin300136482_1->setExclusive(true);
+ poly = Avoid::Polygon(4);
+ poly.setPoint(0, Avoid::Point(50854, 50840));
+ poly.setPoint(1, Avoid::Point(50854, 50935));
+ poly.setPoint(2, Avoid::Point(50796, 50935));
+ poly.setPoint(3, Avoid::Point(50796, 50840));
+ Avoid::ShapeRef * shape51003942 = new Avoid::ShapeRef(router1, poly, 51003942);
+ Avoid::ShapeConnectionPin * pin51003942_0 = new Avoid::ShapeConnectionPin(shape51003942, 1, 0.5, 0.10526315789473684, true, 10, 1);
+ pin51003942_0->setExclusive(true);
+ Avoid::JunctionRef * junction502411221 = new Avoid::JunctionRef(router1, Avoid::Point(50825, 50850), 502411221);
+ end1 = Avoid::ConnEnd(shape386142480, 2);
+ end2 = Avoid::ConnEnd(junction502411221);
+ new Avoid::ConnRef(router1, end1, end2);
+ end1 = Avoid::ConnEnd(junction502411221);
+ end2 = Avoid::ConnEnd(shape300136482, 1);
+ new Avoid::ConnRef(router1, end1, end2);
+ end1 = Avoid::ConnEnd(shape51003942, 1);
+ end2 = Avoid::ConnEnd(junction502411221);
+ new Avoid::ConnRef(router1, end1, end2);
+ router1->processTransaction();
+
+ router1->outputDiagram("output/buildOrthogonalChannelInfo1");
+ delete router1;
+}
+
+extern "C" int main(void)
+{
+ test();
+ return 0;
+}
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/checkpointNudging1.cpp b/src/3rdparty/adaptagrams/libavoid/tests/checkpointNudging1.cpp
new file mode 100644
index 0000000..7379e90
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/checkpointNudging1.cpp
@@ -0,0 +1,2592 @@
+// KEGG -> SBGN example #10
+//
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingParameter((RoutingParameter)0, 50);
+ router->setRoutingParameter((RoutingParameter)1, 0);
+ router->setRoutingParameter((RoutingParameter)2, 0);
+ router->setRoutingParameter((RoutingParameter)3, 4000);
+ router->setRoutingParameter((RoutingParameter)4, 0);
+ router->setRoutingParameter((RoutingParameter)5, 100);
+ router->setRoutingOption((RoutingOption)0, true);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, false);
+
+
+#ifdef ALL
+ Polygon poly1(4);
+ poly1.ps[0] = Point(1201.5, 1180.75);
+ poly1.ps[1] = Point(1201.5, 1212.75);
+ poly1.ps[2] = Point(1181.5, 1212.75);
+ poly1.ps[3] = Point(1181.5, 1180.75);
+ new ShapeRef(router, poly1, 1);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(785.5, 2338.79);
+ poly2.ps[1] = Point(785.5, 2358.79);
+ poly2.ps[2] = Point(753.5, 2358.79);
+ poly2.ps[3] = Point(753.5, 2338.79);
+ new ShapeRef(router, poly2, 2);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(261.5, 2215.42);
+ poly3.ps[1] = Point(261.5, 2247.42);
+ poly3.ps[2] = Point(241.5, 2247.42);
+ poly3.ps[3] = Point(241.5, 2215.42);
+ new ShapeRef(router, poly3, 3);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(785.5, 2400.79);
+ poly4.ps[1] = Point(785.5, 2420.79);
+ poly4.ps[2] = Point(753.5, 2420.79);
+ poly4.ps[3] = Point(753.5, 2400.79);
+ new ShapeRef(router, poly4, 4);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(282.5, 2348.79);
+ poly5.ps[1] = Point(282.5, 2410.79);
+ poly5.ps[2] = Point(220.5, 2410.79);
+ poly5.ps[3] = Point(220.5, 2348.79);
+ new ShapeRef(router, poly5, 5);
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(1643.5, 817.25);
+ poly6.ps[1] = Point(1643.5, 1194.25);
+ poly6.ps[2] = Point(1421.5, 1194.25);
+ poly6.ps[3] = Point(1421.5, 817.25);
+ new ShapeRef(router, poly6, 6);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(1311.5, 45);
+ poly7.ps[1] = Point(1311.5, 219);
+ poly7.ps[2] = Point(1191.5, 219);
+ poly7.ps[3] = Point(1191.5, 45);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(839.5, 2301.79);
+ poly8.ps[1] = Point(839.5, 2333.79);
+ poly8.ps[2] = Point(819.5, 2333.79);
+ poly8.ps[3] = Point(819.5, 2301.79);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(1105.5, 2263.79);
+ poly9.ps[1] = Point(1105.5, 2283.79);
+ poly9.ps[2] = Point(1073.5, 2283.79);
+ poly9.ps[3] = Point(1073.5, 2263.79);
+ new ShapeRef(router, poly9, 9);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(1105.5, 2338.79);
+ poly10.ps[1] = Point(1105.5, 2358.79);
+ poly10.ps[2] = Point(1073.5, 2358.79);
+ poly10.ps[3] = Point(1073.5, 2338.79);
+ new ShapeRef(router, poly10, 10);
+
+ Polygon poly11(4);
+ poly11.ps[0] = Point(1027.5, 2169.79);
+ poly11.ps[1] = Point(1027.5, 2189.79);
+ poly11.ps[2] = Point(995.5, 2189.79);
+ poly11.ps[3] = Point(995.5, 2169.79);
+ new ShapeRef(router, poly11, 11);
+
+ Polygon poly12(4);
+ poly12.ps[0] = Point(1021.5, 2082.42);
+ poly12.ps[1] = Point(1021.5, 2114.42);
+ poly12.ps[2] = Point(1001.5, 2114.42);
+ poly12.ps[3] = Point(1001.5, 2082.42);
+ new ShapeRef(router, poly12, 12);
+
+ Polygon poly13(4);
+ poly13.ps[0] = Point(721.5, 2159.42);
+ poly13.ps[1] = Point(721.5, 2179.42);
+ poly13.ps[2] = Point(689.5, 2179.42);
+ poly13.ps[3] = Point(689.5, 2159.42);
+ new ShapeRef(router, poly13, 13);
+
+ Polygon poly14(4);
+ poly14.ps[0] = Point(391.5, 2159.42);
+ poly14.ps[1] = Point(391.5, 2179.42);
+ poly14.ps[2] = Point(359.5, 2179.42);
+ poly14.ps[3] = Point(359.5, 2159.42);
+ new ShapeRef(router, poly14, 14);
+
+ Polygon poly15(4);
+ poly15.ps[0] = Point(1374.5, 2159.42);
+ poly15.ps[1] = Point(1374.5, 2179.42);
+ poly15.ps[2] = Point(1342.5, 2179.42);
+ poly15.ps[3] = Point(1342.5, 2159.42);
+ new ShapeRef(router, poly15, 15);
+
+ Polygon poly16(4);
+ poly16.ps[0] = Point(923.421, 1631.86);
+ poly16.ps[1] = Point(923.421, 1675.86);
+ poly16.ps[2] = Point(835.421, 1675.86);
+ poly16.ps[3] = Point(835.421, 1631.86);
+ new ShapeRef(router, poly16, 16);
+
+ Polygon poly17(4);
+ poly17.ps[0] = Point(1201.5, 1949.42);
+ poly17.ps[1] = Point(1201.5, 1981.42);
+ poly17.ps[2] = Point(1181.5, 1981.42);
+ poly17.ps[3] = Point(1181.5, 1949.42);
+ new ShapeRef(router, poly17, 17);
+
+ Polygon poly18(4);
+ poly18.ps[0] = Point(252, 1963.42);
+ poly18.ps[1] = Point(252, 2127.42);
+ poly18.ps[2] = Point(45, 2127.42);
+ poly18.ps[3] = Point(45, 1963.42);
+ new ShapeRef(router, poly18, 18);
+
+ Polygon poly19(4);
+ poly19.ps[0] = Point(1201.5, 1825.42);
+ poly19.ps[1] = Point(1201.5, 1857.42);
+ poly19.ps[2] = Point(1181.5, 1857.42);
+ poly19.ps[3] = Point(1181.5, 1825.42);
+ new ShapeRef(router, poly19, 19);
+
+ Polygon poly20(4);
+ poly20.ps[0] = Point(1201.5, 1701.42);
+ poly20.ps[1] = Point(1201.5, 1733.42);
+ poly20.ps[2] = Point(1181.5, 1733.42);
+ poly20.ps[3] = Point(1181.5, 1701.42);
+ new ShapeRef(router, poly20, 20);
+
+ Polygon poly21(4);
+ poly21.ps[0] = Point(1170.5, 1327.42);
+ poly21.ps[1] = Point(1170.5, 1359.42);
+ poly21.ps[2] = Point(1150.5, 1359.42);
+ poly21.ps[3] = Point(1150.5, 1327.42);
+ new ShapeRef(router, poly21, 21);
+
+ Polygon poly22(4);
+ poly22.ps[0] = Point(741, 1632.42);
+ poly22.ps[1] = Point(741, 1692.42);
+ poly22.ps[2] = Point(428, 1692.42);
+ poly22.ps[3] = Point(428, 1632.42);
+ new ShapeRef(router, poly22, 22);
+
+ Polygon poly23(4);
+ poly23.ps[0] = Point(996.5, 1281.42);
+ poly23.ps[1] = Point(996.5, 1301.42);
+ poly23.ps[2] = Point(964.5, 1301.42);
+ poly23.ps[3] = Point(964.5, 1281.42);
+ new ShapeRef(router, poly23, 23);
+
+ Polygon poly24(4);
+ poly24.ps[0] = Point(1232.5, 1047.75);
+ poly24.ps[1] = Point(1232.5, 1079.75);
+ poly24.ps[2] = Point(1212.5, 1079.75);
+ poly24.ps[3] = Point(1212.5, 1047.75);
+ new ShapeRef(router, poly24, 24);
+
+ Polygon poly25(4);
+ poly25.ps[0] = Point(1170.5, 1047.75);
+ poly25.ps[1] = Point(1170.5, 1079.75);
+ poly25.ps[2] = Point(1150.5, 1079.75);
+ poly25.ps[3] = Point(1150.5, 1047.75);
+ new ShapeRef(router, poly25, 25);
+
+ Polygon poly26(4);
+ poly26.ps[0] = Point(1343.5, 540.5);
+ poly26.ps[1] = Point(1343.5, 560.5);
+ poly26.ps[2] = Point(1311.5, 560.5);
+ poly26.ps[3] = Point(1311.5, 540.5);
+ new ShapeRef(router, poly26, 26);
+
+ Polygon poly27(4);
+ poly27.ps[0] = Point(1201.5, 724);
+ poly27.ps[1] = Point(1201.5, 756);
+ poly27.ps[2] = Point(1181.5, 756);
+ poly27.ps[3] = Point(1181.5, 724);
+ new ShapeRef(router, poly27, 27);
+
+ Polygon poly28(4);
+ poly28.ps[0] = Point(1201.5, 462);
+ poly28.ps[1] = Point(1201.5, 494);
+ poly28.ps[2] = Point(1181.5, 494);
+ poly28.ps[3] = Point(1181.5, 462);
+ new ShapeRef(router, poly28, 28);
+
+ Polygon poly29(4);
+ poly29.ps[0] = Point(934.5, 873);
+ poly29.ps[1] = Point(934.5, 893);
+ poly29.ps[2] = Point(902.5, 893);
+ poly29.ps[3] = Point(902.5, 873);
+ new ShapeRef(router, poly29, 29);
+
+ Polygon poly30(4);
+ poly30.ps[0] = Point(492.5, 767);
+ poly30.ps[1] = Point(492.5, 787);
+ poly30.ps[2] = Point(460.5, 787);
+ poly30.ps[3] = Point(460.5, 767);
+ new ShapeRef(router, poly30, 30);
+
+ Polygon poly31(4);
+ poly31.ps[0] = Point(492.5, 842);
+ poly31.ps[1] = Point(492.5, 862);
+ poly31.ps[2] = Point(460.5, 862);
+ poly31.ps[3] = Point(460.5, 842);
+ new ShapeRef(router, poly31, 31);
+
+ Polygon poly32(4);
+ poly32.ps[0] = Point(814.5, 730);
+ poly32.ps[1] = Point(814.5, 750);
+ poly32.ps[2] = Point(782.5, 750);
+ poly32.ps[3] = Point(782.5, 730);
+ new ShapeRef(router, poly32, 32);
+
+ Polygon poly33(4);
+ poly33.ps[0] = Point(653.5, 724);
+ poly33.ps[1] = Point(653.5, 756);
+ poly33.ps[2] = Point(633.5, 756);
+ poly33.ps[3] = Point(633.5, 724);
+ new ShapeRef(router, poly33, 33);
+
+ Polygon poly34(4);
+ poly34.ps[0] = Point(296.5, 724);
+ poly34.ps[1] = Point(296.5, 756);
+ poly34.ps[2] = Point(276.5, 756);
+ poly34.ps[3] = Point(276.5, 724);
+ new ShapeRef(router, poly34, 34);
+
+ Polygon poly35(4);
+ poly35.ps[0] = Point(723.5, 468);
+ poly35.ps[1] = Point(723.5, 488);
+ poly35.ps[2] = Point(691.5, 488);
+ poly35.ps[3] = Point(691.5, 468);
+ new ShapeRef(router, poly35, 35);
+
+ Polygon poly36(4);
+ poly36.ps[0] = Point(723.5, 543);
+ poly36.ps[1] = Point(723.5, 563);
+ poly36.ps[2] = Point(691.5, 563);
+ poly36.ps[3] = Point(691.5, 543);
+ new ShapeRef(router, poly36, 36);
+
+ Polygon poly37(4);
+ poly37.ps[0] = Point(723.5, 393);
+ poly37.ps[1] = Point(723.5, 413);
+ poly37.ps[2] = Point(691.5, 413);
+ poly37.ps[3] = Point(691.5, 393);
+ new ShapeRef(router, poly37, 37);
+
+ Polygon poly38(4);
+ poly38.ps[0] = Point(783.5, 331);
+ poly38.ps[1] = Point(783.5, 351);
+ poly38.ps[2] = Point(751.5, 351);
+ poly38.ps[3] = Point(751.5, 331);
+ new ShapeRef(router, poly38, 38);
+
+ Polygon poly39(4);
+ poly39.ps[0] = Point(783.5, 229);
+ poly39.ps[1] = Point(783.5, 249);
+ poly39.ps[2] = Point(751.5, 249);
+ poly39.ps[3] = Point(751.5, 229);
+ new ShapeRef(router, poly39, 39);
+
+ Polygon poly40(4);
+ poly40.ps[0] = Point(402, 96.5);
+ poly40.ps[1] = Point(402, 131.5);
+ poly40.ps[2] = Point(141, 131.5);
+ poly40.ps[3] = Point(141, 96.5);
+ new ShapeRef(router, poly40, 40);
+
+ Polygon poly41(4);
+ poly41.ps[0] = Point(508.5, 2302.46);
+ poly41.ps[1] = Point(508.5, 2322.46);
+ poly41.ps[2] = Point(476.5, 2322.46);
+ poly41.ps[3] = Point(476.5, 2302.46);
+ new ShapeRef(router, poly41, 41);
+
+ Polygon poly42(4);
+ poly42.ps[0] = Point(1201.5, 1553.42);
+ poly42.ps[1] = Point(1201.5, 1585.42);
+ poly42.ps[2] = Point(1181.5, 1585.42);
+ poly42.ps[3] = Point(1181.5, 1553.42);
+ new ShapeRef(router, poly42, 42);
+
+ Polygon poly43(4);
+ poly43.ps[0] = Point(723.5, 605);
+ poly43.ps[1] = Point(723.5, 625);
+ poly43.ps[2] = Point(691.5, 625);
+ poly43.ps[3] = Point(691.5, 605);
+ new ShapeRef(router, poly43, 43);
+
+ Polygon poly44(4);
+ poly44.ps[0] = Point(492.5, 904);
+ poly44.ps[1] = Point(492.5, 924);
+ poly44.ps[2] = Point(460.5, 924);
+ poly44.ps[3] = Point(460.5, 904);
+ new ShapeRef(router, poly44, 44);
+
+ Polygon poly45(4);
+ poly45.ps[0] = Point(302.5, 1066);
+ poly45.ps[1] = Point(302.5, 1086);
+ poly45.ps[2] = Point(270.5, 1086);
+ poly45.ps[3] = Point(270.5, 1066);
+ new ShapeRef(router, poly45, 45);
+
+ Polygon poly46(4);
+ poly46.ps[0] = Point(302.5, 1168);
+ poly46.ps[1] = Point(302.5, 1188);
+ poly46.ps[2] = Point(270.5, 1188);
+ poly46.ps[3] = Point(270.5, 1168);
+ new ShapeRef(router, poly46, 46);
+
+ Polygon poly47(4);
+ poly47.ps[0] = Point(570.5, 1066);
+ poly47.ps[1] = Point(570.5, 1086);
+ poly47.ps[2] = Point(538.5, 1086);
+ poly47.ps[3] = Point(538.5, 1066);
+ new ShapeRef(router, poly47, 47);
+
+ Polygon poly48(4);
+ poly48.ps[0] = Point(570.5, 1168);
+ poly48.ps[1] = Point(570.5, 1188);
+ poly48.ps[2] = Point(538.5, 1188);
+ poly48.ps[3] = Point(538.5, 1168);
+ new ShapeRef(router, poly48, 48);
+
+ Polygon poly49(4);
+ poly49.ps[0] = Point(1432.5, 519.5);
+ poly49.ps[1] = Point(1432.5, 581.5);
+ poly49.ps[2] = Point(1370.5, 581.5);
+ poly49.ps[3] = Point(1370.5, 519.5);
+ new ShapeRef(router, poly49, 49);
+
+ Polygon poly50(4);
+ poly50.ps[0] = Point(1222.5, 249);
+ poly50.ps[1] = Point(1222.5, 311);
+ poly50.ps[2] = Point(1160.5, 311);
+ poly50.ps[3] = Point(1160.5, 249);
+ new ShapeRef(router, poly50, 50);
+
+ Polygon poly51(4);
+ poly51.ps[0] = Point(1222.5, 1748.42);
+ poly51.ps[1] = Point(1222.5, 1810.42);
+ poly51.ps[2] = Point(1160.5, 1810.42);
+ poly51.ps[3] = Point(1160.5, 1748.42);
+ new ShapeRef(router, poly51, 51);
+
+ Polygon poly52(4);
+ poly52.ps[0] = Point(317.5, 553);
+ poly52.ps[1] = Point(317.5, 615);
+ poly52.ps[2] = Point(255.5, 615);
+ poly52.ps[3] = Point(255.5, 553);
+ new ShapeRef(router, poly52, 52);
+
+ Polygon poly53(4);
+ poly53.ps[0] = Point(317.5, 852);
+ poly53.ps[1] = Point(317.5, 914);
+ poly53.ps[2] = Point(255.5, 914);
+ poly53.ps[3] = Point(255.5, 852);
+ new ShapeRef(router, poly53, 53);
+
+ Polygon poly54(4);
+ poly54.ps[0] = Point(767.5, 1260.42);
+ poly54.ps[1] = Point(767.5, 1322.42);
+ poly54.ps[2] = Point(705.5, 1322.42);
+ poly54.ps[3] = Point(705.5, 1260.42);
+ new ShapeRef(router, poly54, 54);
+
+ Polygon poly55(4);
+ poly55.ps[0] = Point(767.5, 852);
+ poly55.ps[1] = Point(767.5, 914);
+ poly55.ps[2] = Point(705.5, 914);
+ poly55.ps[3] = Point(705.5, 852);
+ new ShapeRef(router, poly55, 55);
+
+ Polygon poly56(4);
+ poly56.ps[0] = Point(1222.5, 553);
+ poly56.ps[1] = Point(1222.5, 615);
+ poly56.ps[2] = Point(1160.5, 615);
+ poly56.ps[3] = Point(1160.5, 553);
+ new ShapeRef(router, poly56, 56);
+
+ Polygon poly57(4);
+ poly57.ps[0] = Point(1222.5, 852);
+ poly57.ps[1] = Point(1222.5, 914);
+ poly57.ps[2] = Point(1160.5, 914);
+ poly57.ps[3] = Point(1160.5, 852);
+ new ShapeRef(router, poly57, 57);
+
+ Polygon poly58(4);
+ poly58.ps[0] = Point(1222.5, 1872.42);
+ poly58.ps[1] = Point(1222.5, 1934.42);
+ poly58.ps[2] = Point(1160.5, 1934.42);
+ poly58.ps[3] = Point(1160.5, 1872.42);
+ new ShapeRef(router, poly58, 58);
+
+ Polygon poly59(4);
+ poly59.ps[0] = Point(1222.5, 1624.42);
+ poly59.ps[1] = Point(1222.5, 1686.42);
+ poly59.ps[2] = Point(1160.5, 1686.42);
+ poly59.ps[3] = Point(1160.5, 1624.42);
+ new ShapeRef(router, poly59, 59);
+
+ Polygon poly60(4);
+ poly60.ps[0] = Point(1222.5, 1424.42);
+ poly60.ps[1] = Point(1222.5, 1486.42);
+ poly60.ps[2] = Point(1160.5, 1486.42);
+ poly60.ps[3] = Point(1160.5, 1424.42);
+ new ShapeRef(router, poly60, 60);
+
+ Polygon poly61(4);
+ poly61.ps[0] = Point(1463.5, 2138.42);
+ poly61.ps[1] = Point(1463.5, 2200.42);
+ poly61.ps[2] = Point(1401.5, 2200.42);
+ poly61.ps[3] = Point(1401.5, 2138.42);
+ new ShapeRef(router, poly61, 61);
+
+ Polygon poly62(4);
+ poly62.ps[0] = Point(705.5, 2281.46);
+ poly62.ps[1] = Point(705.5, 2343.46);
+ poly62.ps[2] = Point(643.5, 2343.46);
+ poly62.ps[3] = Point(643.5, 2281.46);
+ new ShapeRef(router, poly62, 62);
+
+ Polygon poly63(4);
+ poly63.ps[0] = Point(1358.5, 2348.79);
+ poly63.ps[1] = Point(1358.5, 2410.79);
+ poly63.ps[2] = Point(1296.5, 2410.79);
+ poly63.ps[3] = Point(1296.5, 2348.79);
+ new ShapeRef(router, poly63, 63);
+
+ Polygon poly64(4);
+ poly64.ps[0] = Point(1222.5, 2138.42);
+ poly64.ps[1] = Point(1222.5, 2200.42);
+ poly64.ps[2] = Point(1160.5, 2200.42);
+ poly64.ps[3] = Point(1160.5, 2138.42);
+ new ShapeRef(router, poly64, 64);
+
+ Polygon poly65(4);
+ poly65.ps[0] = Point(860.5, 2138.42);
+ poly65.ps[1] = Point(860.5, 2200.42);
+ poly65.ps[2] = Point(798.5, 2200.42);
+ poly65.ps[3] = Point(798.5, 2138.42);
+ new ShapeRef(router, poly65, 65);
+
+ Polygon poly66(4);
+ poly66.ps[0] = Point(282.5, 2138.42);
+ poly66.ps[1] = Point(282.5, 2200.42);
+ poly66.ps[2] = Point(220.5, 2200.42);
+ poly66.ps[3] = Point(220.5, 2138.42);
+ new ShapeRef(router, poly66, 66);
+
+ Polygon poly67(4);
+ poly67.ps[0] = Point(860.5, 2348.79);
+ poly67.ps[1] = Point(860.5, 2410.79);
+ poly67.ps[2] = Point(798.5, 2410.79);
+ poly67.ps[3] = Point(798.5, 2348.79);
+ new ShapeRef(router, poly67, 67);
+
+ Polygon poly68(4);
+ poly68.ps[0] = Point(554.5, 2138.42);
+ poly68.ps[1] = Point(554.5, 2200.42);
+ poly68.ps[2] = Point(492.5, 2200.42);
+ poly68.ps[3] = Point(492.5, 2138.42);
+ new ShapeRef(router, poly68, 68);
+
+ Polygon poly69(4);
+ poly69.ps[0] = Point(406.5, 2281.46);
+ poly69.ps[1] = Point(406.5, 2343.46);
+ poly69.ps[2] = Point(344.5, 2343.46);
+ poly69.ps[3] = Point(344.5, 2281.46);
+ new ShapeRef(router, poly69, 69);
+
+ Polygon poly70(4);
+ poly70.ps[0] = Point(1222.5, 1084.75);
+ poly70.ps[1] = Point(1222.5, 1146.75);
+ poly70.ps[2] = Point(1160.5, 1146.75);
+ poly70.ps[3] = Point(1160.5, 1084.75);
+ new ShapeRef(router, poly70, 70);
+
+ Polygon poly71(4);
+ poly71.ps[0] = Point(247.5, 1045);
+ poly71.ps[1] = Point(247.5, 1107);
+ poly71.ps[2] = Point(185.5, 1107);
+ poly71.ps[3] = Point(185.5, 1045);
+ new ShapeRef(router, poly71, 71);
+
+ Polygon poly72(4);
+ poly72.ps[0] = Point(437.5, 1045);
+ poly72.ps[1] = Point(437.5, 1107);
+ poly72.ps[2] = Point(375.5, 1107);
+ poly72.ps[3] = Point(375.5, 1045);
+ new ShapeRef(router, poly72, 72);
+
+ Polygon poly73(4);
+ poly73.ps[0] = Point(437.5, 1147);
+ poly73.ps[1] = Point(437.5, 1209);
+ poly73.ps[2] = Point(375.5, 1209);
+ poly73.ps[3] = Point(375.5, 1147);
+ new ShapeRef(router, poly73, 73);
+
+ Polygon poly74(4);
+ poly74.ps[0] = Point(247.5, 1147);
+ poly74.ps[1] = Point(247.5, 1209);
+ poly74.ps[2] = Point(185.5, 1209);
+ poly74.ps[3] = Point(185.5, 1147);
+ new ShapeRef(router, poly74, 74);
+#endif
+ Polygon poly75(4);
+ poly75.ps[0] = Point(715.439, 1924.42);
+ poly75.ps[1] = Point(715.439, 1944.42);
+ poly75.ps[2] = Point(683.439, 1944.42);
+ poly75.ps[3] = Point(683.439, 1924.42);
+ new ShapeRef(router, poly75, 75);
+
+ Polygon poly76(4);
+ poly76.ps[0] = Point(282.5, 1872.42);
+ poly76.ps[1] = Point(282.5, 1934.42);
+ poly76.ps[2] = Point(220.5, 1934.42);
+ poly76.ps[3] = Point(220.5, 1872.42);
+ new ShapeRef(router, poly76, 76);
+
+#ifdef ALL
+ Polygon poly77(4);
+ poly77.ps[0] = Point(1105.5, 2400.79);
+ poly77.ps[1] = Point(1105.5, 2420.79);
+ poly77.ps[2] = Point(1073.5, 2420.79);
+ poly77.ps[3] = Point(1073.5, 2400.79);
+ new ShapeRef(router, poly77, 77);
+#endif
+
+ Polygon poly78(4);
+ poly78.ps[0] = Point(715.439, 1862.42);
+ poly78.ps[1] = Point(715.439, 1882.42);
+ poly78.ps[2] = Point(683.439, 1882.42);
+ poly78.ps[3] = Point(683.439, 1862.42);
+ new ShapeRef(router, poly78, 78);
+
+#ifdef ALL
+ Polygon poly79(4);
+ poly79.ps[0] = Point(1506.5, 2243.29);
+ poly79.ps[1] = Point(1506.5, 2408.29);
+ poly79.ps[2] = Point(1369.5, 2408.29);
+ poly79.ps[3] = Point(1369.5, 2243.29);
+ new ShapeRef(router, poly79, 79);
+
+ Polygon poly80(4);
+ poly80.ps[0] = Point(1232.5, 1327.42);
+ poly80.ps[1] = Point(1232.5, 1359.42);
+ poly80.ps[2] = Point(1212.5, 1359.42);
+ poly80.ps[3] = Point(1212.5, 1327.42);
+ new ShapeRef(router, poly80, 80);
+
+ Polygon poly81(4);
+ poly81.ps[0] = Point(1250.5, 1491.42);
+ poly81.ps[1] = Point(1250.5, 1523.42);
+ poly81.ps[2] = Point(1230.5, 1523.42);
+ poly81.ps[3] = Point(1230.5, 1491.42);
+ new ShapeRef(router, poly81, 81);
+
+ Polygon poly82(4);
+ poly82.ps[0] = Point(1341.5, 1491.42);
+ poly82.ps[1] = Point(1341.5, 1523.42);
+ poly82.ps[2] = Point(1321.5, 1523.42);
+ poly82.ps[3] = Point(1321.5, 1491.42);
+ new ShapeRef(router, poly82, 82);
+
+ Polygon poly83(4);
+ poly83.ps[0] = Point(570.5, 2030.42);
+ poly83.ps[1] = Point(570.5, 2050.42);
+ poly83.ps[2] = Point(538.5, 2050.42);
+ poly83.ps[3] = Point(538.5, 2030.42);
+ new ShapeRef(router, poly83, 83);
+
+ Polygon poly84(4);
+ poly84.ps[0] = Point(1432.5, 1491.42);
+ poly84.ps[1] = Point(1432.5, 1523.42);
+ poly84.ps[2] = Point(1412.5, 1523.42);
+ poly84.ps[3] = Point(1412.5, 1491.42);
+ new ShapeRef(router, poly84, 84);
+
+ Polygon poly85(4);
+ poly85.ps[0] = Point(980.5, 1538.42);
+ poly85.ps[1] = Point(980.5, 1600.42);
+ poly85.ps[2] = Point(918.5, 1600.42);
+ poly85.ps[3] = Point(918.5, 1538.42);
+ new ShapeRef(router, poly85, 85);
+
+ Polygon poly86(4);
+ poly86.ps[0] = Point(1116.5, 1639.42);
+ poly86.ps[1] = Point(1116.5, 1659.42);
+ poly86.ps[2] = Point(1084.5, 1659.42);
+ poly86.ps[3] = Point(1084.5, 1639.42);
+ new ShapeRef(router, poly86, 86);
+
+ Polygon poly87(4);
+ poly87.ps[0] = Point(1116.5, 1445.42);
+ poly87.ps[1] = Point(1116.5, 1465.42);
+ poly87.ps[2] = Point(1084.5, 1465.42);
+ poly87.ps[3] = Point(1084.5, 1445.42);
+ new ShapeRef(router, poly87, 87);
+
+ Polygon poly88(4);
+ poly88.ps[0] = Point(1222.5, 1260.42);
+ poly88.ps[1] = Point(1222.5, 1322.42);
+ poly88.ps[2] = Point(1160.5, 1322.42);
+ poly88.ps[3] = Point(1160.5, 1260.42);
+ new ShapeRef(router, poly88, 88);
+
+ Polygon poly89(4);
+ poly89.ps[0] = Point(170.5, 2215.42);
+ poly89.ps[1] = Point(170.5, 2247.42);
+ poly89.ps[2] = Point(150.5, 2247.42);
+ poly89.ps[3] = Point(150.5, 2215.42);
+ new ShapeRef(router, poly89, 89);
+
+ Polygon poly90(4);
+ poly90.ps[0] = Point(1323.5, 1047.75);
+ poly90.ps[1] = Point(1323.5, 1079.75);
+ poly90.ps[2] = Point(1303.5, 1079.75);
+ poly90.ps[3] = Point(1303.5, 1047.75);
+ new ShapeRef(router, poly90, 90);
+
+ Polygon poly91(4);
+ poly91.ps[0] = Point(723.5, 680);
+ poly91.ps[1] = Point(723.5, 700);
+ poly91.ps[2] = Point(691.5, 700);
+ poly91.ps[3] = Point(691.5, 680);
+ new ShapeRef(router, poly91, 91);
+
+ Polygon poly92(4);
+ poly92.ps[0] = Point(492.5, 979);
+ poly92.ps[1] = Point(492.5, 999);
+ poly92.ps[2] = Point(460.5, 999);
+ poly92.ps[3] = Point(460.5, 979);
+ new ShapeRef(router, poly92, 92);
+
+ Polygon poly93(4);
+ poly93.ps[0] = Point(1105.5, 2475.79);
+ poly93.ps[1] = Point(1105.5, 2495.79);
+ poly93.ps[2] = Point(1073.5, 2495.79);
+ poly93.ps[3] = Point(1073.5, 2475.79);
+ new ShapeRef(router, poly93, 93);
+
+ Polygon poly94(4);
+ poly94.ps[0] = Point(860.5, 2034.42);
+ poly94.ps[1] = Point(860.5, 2096.42);
+ poly94.ps[2] = Point(798.5, 2096.42);
+ poly94.ps[3] = Point(798.5, 2034.42);
+ new ShapeRef(router, poly94, 94);
+
+ Polygon poly95(4);
+ poly95.ps[0] = Point(1277.5, 1176.75);
+ poly95.ps[1] = Point(1277.5, 1216.75);
+ poly95.ps[2] = Point(1201.5, 1216.75);
+ poly95.ps[3] = Point(1201.5, 1176.75);
+ new ShapeRef(router, poly95, 95);
+
+ Polygon poly96(4);
+ poly96.ps[0] = Point(797.5, 2278.79);
+ poly96.ps[1] = Point(797.5, 2338.79);
+ poly96.ps[2] = Point(741.5, 2338.79);
+ poly96.ps[3] = Point(741.5, 2278.79);
+ new ShapeRef(router, poly96, 96);
+
+ Polygon poly97(4);
+ poly97.ps[0] = Point(241.5, 2211.42);
+ poly97.ps[1] = Point(241.5, 2251.42);
+ poly97.ps[2] = Point(165.5, 2251.42);
+ poly97.ps[3] = Point(165.5, 2211.42);
+ new ShapeRef(router, poly97, 97);
+
+ Polygon poly98(4);
+ poly98.ps[0] = Point(797.5, 2420.79);
+ poly98.ps[1] = Point(797.5, 2480.79);
+ poly98.ps[2] = Point(741.5, 2480.79);
+ poly98.ps[3] = Point(741.5, 2420.79);
+ new ShapeRef(router, poly98, 98);
+
+ Polygon poly99(4);
+ poly99.ps[0] = Point(915.5, 2297.79);
+ poly99.ps[1] = Point(915.5, 2337.79);
+ poly99.ps[2] = Point(839.5, 2337.79);
+ poly99.ps[3] = Point(839.5, 2297.79);
+ new ShapeRef(router, poly99, 99);
+
+ Polygon poly100(4);
+ poly100.ps[0] = Point(1117.5, 2203.79);
+ poly100.ps[1] = Point(1117.5, 2263.79);
+ poly100.ps[2] = Point(1061.5, 2263.79);
+ poly100.ps[3] = Point(1061.5, 2203.79);
+ new ShapeRef(router, poly100, 100);
+
+ Polygon poly101(4);
+ poly101.ps[0] = Point(1117.5, 2278.79);
+ poly101.ps[1] = Point(1117.5, 2338.79);
+ poly101.ps[2] = Point(1061.5, 2338.79);
+ poly101.ps[3] = Point(1061.5, 2278.79);
+ new ShapeRef(router, poly101, 101);
+
+ Polygon poly102(4);
+ poly102.ps[0] = Point(1039.5, 2189.79);
+ poly102.ps[1] = Point(1039.5, 2249.79);
+ poly102.ps[2] = Point(983.5, 2249.79);
+ poly102.ps[3] = Point(983.5, 2189.79);
+ new ShapeRef(router, poly102, 102);
+
+ Polygon poly103(4);
+ poly103.ps[0] = Point(1097.5, 2078.42);
+ poly103.ps[1] = Point(1097.5, 2118.42);
+ poly103.ps[2] = Point(1021.5, 2118.42);
+ poly103.ps[3] = Point(1021.5, 2078.42);
+ new ShapeRef(router, poly103, 103);
+
+ Polygon poly104(4);
+ poly104.ps[0] = Point(733.5, 2099.42);
+ poly104.ps[1] = Point(733.5, 2159.42);
+ poly104.ps[2] = Point(677.5, 2159.42);
+ poly104.ps[3] = Point(677.5, 2099.42);
+ new ShapeRef(router, poly104, 104);
+
+ Polygon poly105(4);
+ poly105.ps[0] = Point(403.5, 2099.42);
+ poly105.ps[1] = Point(403.5, 2159.42);
+ poly105.ps[2] = Point(347.5, 2159.42);
+ poly105.ps[3] = Point(347.5, 2099.42);
+ new ShapeRef(router, poly105, 105);
+
+ Polygon poly106(4);
+ poly106.ps[0] = Point(1386.5, 2099.42);
+ poly106.ps[1] = Point(1386.5, 2159.42);
+ poly106.ps[2] = Point(1330.5, 2159.42);
+ poly106.ps[3] = Point(1330.5, 2099.42);
+ new ShapeRef(router, poly106, 106);
+
+ Polygon poly107(4);
+ poly107.ps[0] = Point(1277.5, 1945.42);
+ poly107.ps[1] = Point(1277.5, 1985.42);
+ poly107.ps[2] = Point(1201.5, 1985.42);
+ poly107.ps[3] = Point(1201.5, 1945.42);
+ new ShapeRef(router, poly107, 107);
+
+ Polygon poly108(4);
+ poly108.ps[0] = Point(1277.5, 1821.42);
+ poly108.ps[1] = Point(1277.5, 1861.42);
+ poly108.ps[2] = Point(1201.5, 1861.42);
+ poly108.ps[3] = Point(1201.5, 1821.42);
+ new ShapeRef(router, poly108, 108);
+
+ Polygon poly109(4);
+ poly109.ps[0] = Point(1277.5, 1697.42);
+ poly109.ps[1] = Point(1277.5, 1737.42);
+ poly109.ps[2] = Point(1201.5, 1737.42);
+ poly109.ps[3] = Point(1201.5, 1697.42);
+ new ShapeRef(router, poly109, 109);
+
+ Polygon poly110(4);
+ poly110.ps[0] = Point(1150.5, 1323.42);
+ poly110.ps[1] = Point(1150.5, 1363.42);
+ poly110.ps[2] = Point(1074.5, 1363.42);
+ poly110.ps[3] = Point(1074.5, 1323.42);
+ new ShapeRef(router, poly110, 110);
+
+ Polygon poly111(4);
+ poly111.ps[0] = Point(1008.5, 1221.42);
+ poly111.ps[1] = Point(1008.5, 1281.42);
+ poly111.ps[2] = Point(952.5, 1281.42);
+ poly111.ps[3] = Point(952.5, 1221.42);
+ new ShapeRef(router, poly111, 111);
+
+ Polygon poly112(4);
+ poly112.ps[0] = Point(1308.5, 1043.75);
+ poly112.ps[1] = Point(1308.5, 1083.75);
+ poly112.ps[2] = Point(1232.5, 1083.75);
+ poly112.ps[3] = Point(1232.5, 1043.75);
+ new ShapeRef(router, poly112, 112);
+
+ Polygon poly113(4);
+ poly113.ps[0] = Point(1150.5, 1043.75);
+ poly113.ps[1] = Point(1150.5, 1083.75);
+ poly113.ps[2] = Point(1074.5, 1083.75);
+ poly113.ps[3] = Point(1074.5, 1043.75);
+ new ShapeRef(router, poly113, 113);
+
+ Polygon poly114(4);
+ poly114.ps[0] = Point(1355.5, 480.5);
+ poly114.ps[1] = Point(1355.5, 540.5);
+ poly114.ps[2] = Point(1299.5, 540.5);
+ poly114.ps[3] = Point(1299.5, 480.5);
+ new ShapeRef(router, poly114, 114);
+
+ Polygon poly115(4);
+ poly115.ps[0] = Point(1277.5, 720);
+ poly115.ps[1] = Point(1277.5, 760);
+ poly115.ps[2] = Point(1201.5, 760);
+ poly115.ps[3] = Point(1201.5, 720);
+ new ShapeRef(router, poly115, 115);
+
+ Polygon poly116(4);
+ poly116.ps[0] = Point(1277.5, 458);
+ poly116.ps[1] = Point(1277.5, 498);
+ poly116.ps[2] = Point(1201.5, 498);
+ poly116.ps[3] = Point(1201.5, 458);
+ new ShapeRef(router, poly116, 116);
+
+ Polygon poly117(4);
+ poly117.ps[0] = Point(946.5, 813);
+ poly117.ps[1] = Point(946.5, 873);
+ poly117.ps[2] = Point(890.5, 873);
+ poly117.ps[3] = Point(890.5, 813);
+ new ShapeRef(router, poly117, 117);
+
+ Polygon poly118(4);
+ poly118.ps[0] = Point(504.5, 707);
+ poly118.ps[1] = Point(504.5, 767);
+ poly118.ps[2] = Point(448.5, 767);
+ poly118.ps[3] = Point(448.5, 707);
+ new ShapeRef(router, poly118, 118);
+
+ Polygon poly119(4);
+ poly119.ps[0] = Point(504.5, 782);
+ poly119.ps[1] = Point(504.5, 842);
+ poly119.ps[2] = Point(448.5, 842);
+ poly119.ps[3] = Point(448.5, 782);
+ new ShapeRef(router, poly119, 119);
+
+ Polygon poly120(4);
+ poly120.ps[0] = Point(826.5, 670);
+ poly120.ps[1] = Point(826.5, 730);
+ poly120.ps[2] = Point(770.5, 730);
+ poly120.ps[3] = Point(770.5, 670);
+ new ShapeRef(router, poly120, 120);
+
+ Polygon poly121(4);
+ poly121.ps[0] = Point(633.5, 720);
+ poly121.ps[1] = Point(633.5, 760);
+ poly121.ps[2] = Point(557.5, 760);
+ poly121.ps[3] = Point(557.5, 720);
+ new ShapeRef(router, poly121, 121);
+
+ Polygon poly122(4);
+ poly122.ps[0] = Point(372.5, 720);
+ poly122.ps[1] = Point(372.5, 760);
+ poly122.ps[2] = Point(296.5, 760);
+ poly122.ps[3] = Point(296.5, 720);
+ new ShapeRef(router, poly122, 122);
+
+ Polygon poly123(4);
+ poly123.ps[0] = Point(735.5, 408);
+ poly123.ps[1] = Point(735.5, 468);
+ poly123.ps[2] = Point(679.5, 468);
+ poly123.ps[3] = Point(679.5, 408);
+ new ShapeRef(router, poly123, 123);
+
+ Polygon poly124(4);
+ poly124.ps[0] = Point(735.5, 483);
+ poly124.ps[1] = Point(735.5, 543);
+ poly124.ps[2] = Point(679.5, 543);
+ poly124.ps[3] = Point(679.5, 483);
+ new ShapeRef(router, poly124, 124);
+
+ Polygon poly125(4);
+ poly125.ps[0] = Point(735.5, 333);
+ poly125.ps[1] = Point(735.5, 393);
+ poly125.ps[2] = Point(679.5, 393);
+ poly125.ps[3] = Point(679.5, 333);
+ new ShapeRef(router, poly125, 125);
+
+ Polygon poly126(4);
+ poly126.ps[0] = Point(795.5, 271);
+ poly126.ps[1] = Point(795.5, 331);
+ poly126.ps[2] = Point(739.5, 331);
+ poly126.ps[3] = Point(739.5, 271);
+ new ShapeRef(router, poly126, 126);
+
+ Polygon poly127(4);
+ poly127.ps[0] = Point(795.5, 169);
+ poly127.ps[1] = Point(795.5, 229);
+ poly127.ps[2] = Point(739.5, 229);
+ poly127.ps[3] = Point(739.5, 169);
+ new ShapeRef(router, poly127, 127);
+
+ Polygon poly128(4);
+ poly128.ps[0] = Point(520.5, 2242.46);
+ poly128.ps[1] = Point(520.5, 2302.46);
+ poly128.ps[2] = Point(464.5, 2302.46);
+ poly128.ps[3] = Point(464.5, 2242.46);
+ new ShapeRef(router, poly128, 128);
+
+ Polygon poly129(4);
+ poly129.ps[0] = Point(1277.5, 1549.42);
+ poly129.ps[1] = Point(1277.5, 1589.42);
+ poly129.ps[2] = Point(1201.5, 1589.42);
+ poly129.ps[3] = Point(1201.5, 1549.42);
+ new ShapeRef(router, poly129, 129);
+
+ Polygon poly130(4);
+ poly130.ps[0] = Point(735.5, 625);
+ poly130.ps[1] = Point(735.5, 685);
+ poly130.ps[2] = Point(679.5, 685);
+ poly130.ps[3] = Point(679.5, 625);
+ new ShapeRef(router, poly130, 130);
+
+ Polygon poly131(4);
+ poly131.ps[0] = Point(504.5, 924);
+ poly131.ps[1] = Point(504.5, 984);
+ poly131.ps[2] = Point(448.5, 984);
+ poly131.ps[3] = Point(448.5, 924);
+ new ShapeRef(router, poly131, 131);
+
+ Polygon poly132(4);
+ poly132.ps[0] = Point(314.5, 1006);
+ poly132.ps[1] = Point(314.5, 1066);
+ poly132.ps[2] = Point(258.5, 1066);
+ poly132.ps[3] = Point(258.5, 1006);
+ new ShapeRef(router, poly132, 132);
+
+ Polygon poly133(4);
+ poly133.ps[0] = Point(314.5, 1108);
+ poly133.ps[1] = Point(314.5, 1168);
+ poly133.ps[2] = Point(258.5, 1168);
+ poly133.ps[3] = Point(258.5, 1108);
+ new ShapeRef(router, poly133, 133);
+
+ Polygon poly134(4);
+ poly134.ps[0] = Point(582.5, 1006);
+ poly134.ps[1] = Point(582.5, 1066);
+ poly134.ps[2] = Point(526.5, 1066);
+ poly134.ps[3] = Point(526.5, 1006);
+ new ShapeRef(router, poly134, 134);
+
+ Polygon poly135(4);
+ poly135.ps[0] = Point(582.5, 1108);
+ poly135.ps[1] = Point(582.5, 1168);
+ poly135.ps[2] = Point(526.5, 1168);
+ poly135.ps[3] = Point(526.5, 1108);
+ new ShapeRef(router, poly135, 135);
+#endif
+
+ Polygon poly136(4);
+ poly136.ps[0] = Point(727.439, 1944.42);
+ poly136.ps[1] = Point(727.439, 2004.42);
+ poly136.ps[2] = Point(671.439, 2004.42);
+ poly136.ps[3] = Point(671.439, 1944.42);
+ new ShapeRef(router, poly136, 136);
+
+#ifdef ALL
+ Polygon poly137(4);
+ poly137.ps[0] = Point(1117.5, 2420.79);
+ poly137.ps[1] = Point(1117.5, 2480.79);
+ poly137.ps[2] = Point(1061.5, 2480.79);
+ poly137.ps[3] = Point(1061.5, 2420.79);
+ new ShapeRef(router, poly137, 137);
+#endif
+
+ Polygon poly138(4);
+ poly138.ps[0] = Point(727.439, 1802.42);
+ poly138.ps[1] = Point(727.439, 1862.42);
+ poly138.ps[2] = Point(671.439, 1862.42);
+ poly138.ps[3] = Point(671.439, 1802.42);
+ new ShapeRef(router, poly138, 138);
+
+#ifdef ALL
+ Polygon poly139(4);
+ poly139.ps[0] = Point(1308.5, 1323.42);
+ poly139.ps[1] = Point(1308.5, 1363.42);
+ poly139.ps[2] = Point(1232.5, 1363.42);
+ poly139.ps[3] = Point(1232.5, 1323.42);
+ new ShapeRef(router, poly139, 139);
+
+ Polygon poly140(4);
+ poly140.ps[0] = Point(1326.5, 1487.42);
+ poly140.ps[1] = Point(1326.5, 1527.42);
+ poly140.ps[2] = Point(1250.5, 1527.42);
+ poly140.ps[3] = Point(1250.5, 1487.42);
+ new ShapeRef(router, poly140, 140);
+
+ Polygon poly141(4);
+ poly141.ps[0] = Point(1417.5, 1487.42);
+ poly141.ps[1] = Point(1417.5, 1527.42);
+ poly141.ps[2] = Point(1341.5, 1527.42);
+ poly141.ps[3] = Point(1341.5, 1487.42);
+ new ShapeRef(router, poly141, 141);
+
+ Polygon poly142(4);
+ poly142.ps[0] = Point(582.5, 1970.42);
+ poly142.ps[1] = Point(582.5, 2030.42);
+ poly142.ps[2] = Point(526.5, 2030.42);
+ poly142.ps[3] = Point(526.5, 1970.42);
+ new ShapeRef(router, poly142, 142);
+
+ Polygon poly143(4);
+ poly143.ps[0] = Point(1508.5, 1487.42);
+ poly143.ps[1] = Point(1508.5, 1527.42);
+ poly143.ps[2] = Point(1432.5, 1527.42);
+ poly143.ps[3] = Point(1432.5, 1487.42);
+ new ShapeRef(router, poly143, 143);
+
+ Polygon poly144(4);
+ poly144.ps[0] = Point(1128.5, 1579.42);
+ poly144.ps[1] = Point(1128.5, 1639.42);
+ poly144.ps[2] = Point(1072.5, 1639.42);
+ poly144.ps[3] = Point(1072.5, 1579.42);
+ new ShapeRef(router, poly144, 144);
+
+ Polygon poly145(4);
+ poly145.ps[0] = Point(1128.5, 1385.42);
+ poly145.ps[1] = Point(1128.5, 1445.42);
+ poly145.ps[2] = Point(1072.5, 1445.42);
+ poly145.ps[3] = Point(1072.5, 1385.42);
+ new ShapeRef(router, poly145, 145);
+
+ Polygon poly146(4);
+ poly146.ps[0] = Point(150.5, 2211.42);
+ poly146.ps[1] = Point(150.5, 2251.42);
+ poly146.ps[2] = Point(74.5, 2251.42);
+ poly146.ps[3] = Point(74.5, 2211.42);
+ new ShapeRef(router, poly146, 146);
+
+ Polygon poly147(4);
+ poly147.ps[0] = Point(1399.5, 1043.75);
+ poly147.ps[1] = Point(1399.5, 1083.75);
+ poly147.ps[2] = Point(1323.5, 1083.75);
+ poly147.ps[3] = Point(1323.5, 1043.75);
+ new ShapeRef(router, poly147, 147);
+
+ Polygon poly148(4);
+ poly148.ps[0] = Point(735.5, 700);
+ poly148.ps[1] = Point(735.5, 760);
+ poly148.ps[2] = Point(679.5, 760);
+ poly148.ps[3] = Point(679.5, 700);
+ new ShapeRef(router, poly148, 148);
+
+ Polygon poly149(4);
+ poly149.ps[0] = Point(504.5, 999);
+ poly149.ps[1] = Point(504.5, 1059);
+ poly149.ps[2] = Point(448.5, 1059);
+ poly149.ps[3] = Point(448.5, 999);
+ new ShapeRef(router, poly149, 149);
+
+ Polygon poly150(4);
+ poly150.ps[0] = Point(1117.5, 2495.79);
+ poly150.ps[1] = Point(1117.5, 2555.79);
+ poly150.ps[2] = Point(1061.5, 2555.79);
+ poly150.ps[3] = Point(1061.5, 2495.79);
+ new ShapeRef(router, poly150, 150);
+
+ Polygon poly151(4);
+ poly151.ps[0] = Point(1482, 966.25);
+ poly151.ps[1] = Point(1482, 1006.25);
+ poly151.ps[2] = Point(1422, 1006.25);
+ poly151.ps[3] = Point(1422, 966.25);
+ new ShapeRef(router, poly151, 151);
+
+ Polygon poly152(4);
+ poly152.ps[0] = Point(1482, 1006.25);
+ poly152.ps[1] = Point(1482, 1046.25);
+ poly152.ps[2] = Point(1422, 1046.25);
+ poly152.ps[3] = Point(1422, 1006.25);
+ new ShapeRef(router, poly152, 152);
+
+ Polygon poly153(4);
+ poly153.ps[0] = Point(1533, 1134.75);
+ poly153.ps[1] = Point(1533, 1194.75);
+ poly153.ps[2] = Point(1493, 1194.75);
+ poly153.ps[3] = Point(1493, 1134.75);
+ new ShapeRef(router, poly153, 153);
+
+ Polygon poly154(4);
+ poly154.ps[0] = Point(1573, 1134.75);
+ poly154.ps[1] = Point(1573, 1194.75);
+ poly154.ps[2] = Point(1533, 1194.75);
+ poly154.ps[3] = Point(1533, 1134.75);
+ new ShapeRef(router, poly154, 154);
+
+ Polygon poly155(4);
+ poly155.ps[0] = Point(1272, 159.5);
+ poly155.ps[1] = Point(1272, 219.5);
+ poly155.ps[2] = Point(1232, 219.5);
+ poly155.ps[3] = Point(1232, 159.5);
+ new ShapeRef(router, poly155, 155);
+
+ Polygon poly156(4);
+ poly156.ps[0] = Point(252.5, 2005.92);
+ poly156.ps[1] = Point(252.5, 2045.92);
+ poly156.ps[2] = Point(192.5, 2045.92);
+ poly156.ps[3] = Point(192.5, 2005.92);
+ new ShapeRef(router, poly156, 156);
+
+ Polygon poly157(4);
+ poly157.ps[0] = Point(252.5, 2045.92);
+ poly157.ps[1] = Point(252.5, 2085.92);
+ poly157.ps[2] = Point(192.5, 2085.92);
+ poly157.ps[3] = Point(192.5, 2045.92);
+ new ShapeRef(router, poly157, 157);
+
+ Polygon poly158(4);
+ poly158.ps[0] = Point(741.5, 1642.92);
+ poly158.ps[1] = Point(741.5, 1682.92);
+ poly158.ps[2] = Point(681.5, 1682.92);
+ poly158.ps[3] = Point(681.5, 1642.92);
+ new ShapeRef(router, poly158, 158);
+
+ Polygon poly159(4);
+ poly159.ps[0] = Point(1458.5, 2243.79);
+ poly159.ps[1] = Point(1458.5, 2303.79);
+ poly159.ps[2] = Point(1418.5, 2303.79);
+ poly159.ps[3] = Point(1418.5, 2243.79);
+ new ShapeRef(router, poly159, 159);
+
+ ConnRef *connRef160 = new ConnRef(router, 160);
+ ConnEnd srcPt160(Point(1191.5, 1211.75), 2);
+ connRef160->setSourceEndpoint(srcPt160);
+ ConnEnd dstPt160(Point(736.5, 1291.42), 15);
+ connRef160->setDestEndpoint(dstPt160);
+ connRef160->setRoutingType((ConnType)2);
+
+ ConnRef *connRef161 = new ConnRef(router, 161);
+ ConnEnd srcPt161(Point(1191.5, 1181.75), 1);
+ connRef161->setSourceEndpoint(srcPt161);
+ ConnEnd dstPt161(Point(1191.5, 1115.75), 15);
+ connRef161->setDestEndpoint(dstPt161);
+ connRef161->setRoutingType((ConnType)2);
+
+ ConnRef *connRef162 = new ConnRef(router, 162);
+ ConnEnd srcPt162(Point(1191.5, 1211.75), 2);
+ connRef162->setSourceEndpoint(srcPt162);
+ ConnEnd dstPt162(Point(1191.5, 1291.42), 15);
+ connRef162->setDestEndpoint(dstPt162);
+ connRef162->setRoutingType((ConnType)2);
+
+ ConnRef *connRef163 = new ConnRef(router, 163);
+ ConnEnd srcPt163(Point(754.5, 2348.79), 4);
+ connRef163->setSourceEndpoint(srcPt163);
+ ConnEnd dstPt163(Point(251.5, 2379.79), 15);
+ connRef163->setDestEndpoint(dstPt163);
+ connRef163->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints163(1);
+ checkpoints163[0] = Point(807.5, 2379.79);
+ connRef163->setRoutingCheckpoints(checkpoints163);
+
+ ConnRef *connRef164 = new ConnRef(router, 164);
+ ConnEnd srcPt164(Point(784.5, 2348.79), 8);
+ connRef164->setSourceEndpoint(srcPt164);
+ ConnEnd dstPt164(Point(829.5, 2379.79), 15);
+ connRef164->setDestEndpoint(dstPt164);
+ connRef164->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints164(1);
+ checkpoints164[0] = Point(731.5, 2379.79);
+ connRef164->setRoutingCheckpoints(checkpoints164);
+
+ ConnRef *connRef165 = new ConnRef(router, 165);
+ ConnEnd srcPt165(Point(251.5, 2246.42), 2);
+ connRef165->setSourceEndpoint(srcPt165);
+ ConnEnd dstPt165(Point(251.5, 2379.79), 15);
+ connRef165->setDestEndpoint(dstPt165);
+ connRef165->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints165(1);
+ checkpoints165[0] = Point(226.5, 2261.42);
+ connRef165->setRoutingCheckpoints(checkpoints165);
+
+ ConnRef *connRef166 = new ConnRef(router, 166);
+ ConnEnd srcPt166(Point(754.5, 2410.79), 4);
+ connRef166->setSourceEndpoint(srcPt166);
+ ConnEnd dstPt166(Point(251.5, 2379.79), 15);
+ connRef166->setDestEndpoint(dstPt166);
+ connRef166->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints166(1);
+ checkpoints166[0] = Point(807.5, 2379.79);
+ connRef166->setRoutingCheckpoints(checkpoints166);
+
+ ConnRef *connRef167 = new ConnRef(router, 167);
+ ConnEnd srcPt167(Point(784.5, 2410.79), 8);
+ connRef167->setSourceEndpoint(srcPt167);
+ ConnEnd dstPt167(Point(829.5, 2379.79), 15);
+ connRef167->setDestEndpoint(dstPt167);
+ connRef167->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints167(1);
+ checkpoints167[0] = Point(731.5, 2379.79);
+ connRef167->setRoutingCheckpoints(checkpoints167);
+
+ ConnRef *connRef168 = new ConnRef(router, 168);
+ ConnEnd srcPt168(Point(251.5, 2379.79), 15);
+ connRef168->setSourceEndpoint(srcPt168);
+ ConnEnd dstPt168(Point(160.5, 2246.42), 2);
+ connRef168->setDestEndpoint(dstPt168);
+ connRef168->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints168(1);
+ checkpoints168[0] = Point(226.5, 2261.42);
+ connRef168->setRoutingCheckpoints(checkpoints168);
+
+ ConnRef *connRef169 = new ConnRef(router, 169);
+ ConnEnd srcPt169(Point(829.5, 2332.79), 2);
+ connRef169->setSourceEndpoint(srcPt169);
+ ConnEnd dstPt169(Point(829.5, 2379.79), 15);
+ connRef169->setDestEndpoint(dstPt169);
+ connRef169->setRoutingType((ConnType)2);
+
+ ConnRef *connRef170 = new ConnRef(router, 170);
+ ConnEnd srcPt170(Point(1074.5, 2273.79), 4);
+ connRef170->setSourceEndpoint(srcPt170);
+ ConnEnd dstPt170(Point(829.5, 2379.79), 15);
+ connRef170->setDestEndpoint(dstPt170);
+ connRef170->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints170(1);
+ checkpoints170[0] = Point(1051.5, 2379.79);
+ connRef170->setRoutingCheckpoints(checkpoints170);
+
+ ConnRef *connRef171 = new ConnRef(router, 171);
+ ConnEnd srcPt171(Point(1074.5, 2348.79), 4);
+ connRef171->setSourceEndpoint(srcPt171);
+ ConnEnd dstPt171(Point(829.5, 2379.79), 15);
+ connRef171->setDestEndpoint(dstPt171);
+ connRef171->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints171(1);
+ checkpoints171[0] = Point(1051.5, 2379.79);
+ connRef171->setRoutingCheckpoints(checkpoints171);
+
+ ConnRef *connRef172 = new ConnRef(router, 172);
+ ConnEnd srcPt172(Point(996.5, 2179.79), 4);
+ connRef172->setSourceEndpoint(srcPt172);
+ ConnEnd dstPt172(Point(829.5, 2169.42), 15);
+ connRef172->setDestEndpoint(dstPt172);
+ connRef172->setRoutingType((ConnType)2);
+
+ ConnRef *connRef173 = new ConnRef(router, 173);
+ ConnEnd srcPt173(Point(1011.5, 2113.42), 2);
+ connRef173->setSourceEndpoint(srcPt173);
+ ConnEnd dstPt173(Point(829.5, 2169.42), 15);
+ connRef173->setDestEndpoint(dstPt173);
+ connRef173->setRoutingType((ConnType)2);
+
+ ConnRef *connRef174 = new ConnRef(router, 174);
+ ConnEnd srcPt174(Point(690.5, 2169.42), 4);
+ connRef174->setSourceEndpoint(srcPt174);
+ ConnEnd dstPt174(Point(523.5, 2169.42), 15);
+ connRef174->setDestEndpoint(dstPt174);
+ connRef174->setRoutingType((ConnType)2);
+
+ ConnRef *connRef175 = new ConnRef(router, 175);
+ ConnEnd srcPt175(Point(690.5, 2169.42), 4);
+ connRef175->setSourceEndpoint(srcPt175);
+ ConnEnd dstPt175(Point(829.5, 2065.42), 15);
+ connRef175->setDestEndpoint(dstPt175);
+ connRef175->setRoutingType((ConnType)2);
+
+ ConnRef *connRef176 = new ConnRef(router, 176);
+ ConnEnd srcPt176(Point(360.5, 2169.42), 4);
+ connRef176->setSourceEndpoint(srcPt176);
+ ConnEnd dstPt176(Point(251.5, 2169.42), 15);
+ connRef176->setDestEndpoint(dstPt176);
+ connRef176->setRoutingType((ConnType)2);
+
+ ConnRef *connRef177 = new ConnRef(router, 177);
+ ConnEnd srcPt177(Point(390.5, 2169.42), 8);
+ connRef177->setSourceEndpoint(srcPt177);
+ ConnEnd dstPt177(Point(523.5, 2169.42), 15);
+ connRef177->setDestEndpoint(dstPt177);
+ connRef177->setRoutingType((ConnType)2);
+
+ ConnRef *connRef178 = new ConnRef(router, 178);
+ ConnEnd srcPt178(Point(360.5, 2169.42), 4);
+ connRef178->setSourceEndpoint(srcPt178);
+ ConnEnd dstPt178(Point(375.5, 2312.46), 15);
+ connRef178->setDestEndpoint(dstPt178);
+ connRef178->setRoutingType((ConnType)2);
+
+ ConnRef *connRef179 = new ConnRef(router, 179);
+ ConnEnd srcPt179(Point(1373.5, 2169.42), 8);
+ connRef179->setSourceEndpoint(srcPt179);
+ ConnEnd dstPt179(Point(1432.5, 2169.42), 15);
+ connRef179->setDestEndpoint(dstPt179);
+ connRef179->setRoutingType((ConnType)2);
+
+ ConnRef *connRef180 = new ConnRef(router, 180);
+ ConnEnd srcPt180(Point(1343.5, 2169.42), 4);
+ connRef180->setSourceEndpoint(srcPt180);
+ ConnEnd dstPt180(Point(1191.5, 2169.42), 15);
+ connRef180->setDestEndpoint(dstPt180);
+ connRef180->setRoutingType((ConnType)2);
+
+ ConnRef *connRef181 = new ConnRef(router, 181);
+ ConnEnd srcPt181(Point(1191.5, 1980.42), 2);
+ connRef181->setSourceEndpoint(srcPt181);
+ ConnEnd dstPt181(Point(1191.5, 2169.42), 15);
+ connRef181->setDestEndpoint(dstPt181);
+ connRef181->setRoutingType((ConnType)2);
+
+ ConnRef *connRef182 = new ConnRef(router, 182);
+ ConnEnd srcPt182(Point(1191.5, 1826.42), 1);
+ connRef182->setSourceEndpoint(srcPt182);
+ ConnEnd dstPt182(Point(1191.5, 1779.42), 15);
+ connRef182->setDestEndpoint(dstPt182);
+ connRef182->setRoutingType((ConnType)2);
+
+ ConnRef *connRef183 = new ConnRef(router, 183);
+ ConnEnd srcPt183(Point(1191.5, 1856.42), 2);
+ connRef183->setSourceEndpoint(srcPt183);
+ ConnEnd dstPt183(Point(1191.5, 1903.42), 15);
+ connRef183->setDestEndpoint(dstPt183);
+ connRef183->setRoutingType((ConnType)2);
+
+ ConnRef *connRef184 = new ConnRef(router, 184);
+ ConnEnd srcPt184(Point(1191.5, 1732.42), 2);
+ connRef184->setSourceEndpoint(srcPt184);
+ ConnEnd dstPt184(Point(1191.5, 1779.42), 15);
+ connRef184->setDestEndpoint(dstPt184);
+ connRef184->setRoutingType((ConnType)2);
+
+ ConnRef *connRef185 = new ConnRef(router, 185);
+ ConnEnd srcPt185(Point(1191.5, 1702.42), 1);
+ connRef185->setSourceEndpoint(srcPt185);
+ ConnEnd dstPt185(Point(1191.5, 1655.42), 15);
+ connRef185->setDestEndpoint(dstPt185);
+ connRef185->setRoutingType((ConnType)2);
+
+ ConnRef *connRef186 = new ConnRef(router, 186);
+ ConnEnd srcPt186(Point(1160.5, 1358.42), 2);
+ connRef186->setSourceEndpoint(srcPt186);
+ ConnEnd dstPt186(Point(1191.5, 1455.42), 15);
+ connRef186->setDestEndpoint(dstPt186);
+ connRef186->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints186(1);
+ checkpoints186[0] = Point(1191.5, 1373.42);
+ connRef186->setRoutingCheckpoints(checkpoints186);
+
+ ConnRef *connRef187 = new ConnRef(router, 187);
+ ConnEnd srcPt187(Point(1160.5, 1328.42), 1);
+ connRef187->setSourceEndpoint(srcPt187);
+ ConnEnd dstPt187(Point(1191.5, 1291.42), 15);
+ connRef187->setDestEndpoint(dstPt187);
+ connRef187->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints187(1);
+ checkpoints187[0] = Point(1191.5, 1313.42);
+ connRef187->setRoutingCheckpoints(checkpoints187);
+
+ ConnRef *connRef188 = new ConnRef(router, 188);
+ ConnEnd srcPt188(Point(965.5, 1291.42), 4);
+ connRef188->setSourceEndpoint(srcPt188);
+ ConnEnd dstPt188(Point(736.5, 1291.42), 15);
+ connRef188->setDestEndpoint(dstPt188);
+ connRef188->setRoutingType((ConnType)2);
+
+ ConnRef *connRef189 = new ConnRef(router, 189);
+ ConnEnd srcPt189(Point(995.5, 1291.42), 8);
+ connRef189->setSourceEndpoint(srcPt189);
+ ConnEnd dstPt189(Point(1191.5, 1291.42), 15);
+ connRef189->setDestEndpoint(dstPt189);
+ connRef189->setRoutingType((ConnType)2);
+
+ ConnRef *connRef190 = new ConnRef(router, 190);
+ ConnEnd srcPt190(Point(1222.5, 1078.75), 2);
+ connRef190->setSourceEndpoint(srcPt190);
+ ConnEnd dstPt190(Point(1191.5, 1115.75), 15);
+ connRef190->setDestEndpoint(dstPt190);
+ connRef190->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints190(1);
+ checkpoints190[0] = Point(1191.5, 1033.75);
+ connRef190->setRoutingCheckpoints(checkpoints190);
+
+ ConnRef *connRef191 = new ConnRef(router, 191);
+ ConnEnd srcPt191(Point(1160.5, 1048.75), 1);
+ connRef191->setSourceEndpoint(srcPt191);
+ ConnEnd dstPt191(Point(1191.5, 883), 15);
+ connRef191->setDestEndpoint(dstPt191);
+ connRef191->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints191(1);
+ checkpoints191[0] = Point(1191.5, 1093.75);
+ connRef191->setRoutingCheckpoints(checkpoints191);
+
+ ConnRef *connRef192 = new ConnRef(router, 192);
+ ConnEnd srcPt192(Point(1312.5, 550.5), 4);
+ connRef192->setSourceEndpoint(srcPt192);
+ ConnEnd dstPt192(Point(1191.5, 584), 15);
+ connRef192->setDestEndpoint(dstPt192);
+ connRef192->setRoutingType((ConnType)2);
+
+ ConnRef *connRef193 = new ConnRef(router, 193);
+ ConnEnd srcPt193(Point(1191.5, 725), 1);
+ connRef193->setSourceEndpoint(srcPt193);
+ ConnEnd dstPt193(Point(1191.5, 584), 15);
+ connRef193->setDestEndpoint(dstPt193);
+ connRef193->setRoutingType((ConnType)2);
+
+ ConnRef *connRef194 = new ConnRef(router, 194);
+ ConnEnd srcPt194(Point(1191.5, 755), 2);
+ connRef194->setSourceEndpoint(srcPt194);
+ ConnEnd dstPt194(Point(1191.5, 883), 15);
+ connRef194->setDestEndpoint(dstPt194);
+ connRef194->setRoutingType((ConnType)2);
+
+ ConnRef *connRef195 = new ConnRef(router, 195);
+ ConnEnd srcPt195(Point(1191.5, 463), 1);
+ connRef195->setSourceEndpoint(srcPt195);
+ ConnEnd dstPt195(Point(1191.5, 280), 15);
+ connRef195->setDestEndpoint(dstPt195);
+ connRef195->setRoutingType((ConnType)2);
+
+ ConnRef *connRef196 = new ConnRef(router, 196);
+ ConnEnd srcPt196(Point(1191.5, 493), 2);
+ connRef196->setSourceEndpoint(srcPt196);
+ ConnEnd dstPt196(Point(1191.5, 584), 15);
+ connRef196->setDestEndpoint(dstPt196);
+ connRef196->setRoutingType((ConnType)2);
+
+ ConnRef *connRef197 = new ConnRef(router, 197);
+ ConnEnd srcPt197(Point(903.5, 883), 4);
+ connRef197->setSourceEndpoint(srcPt197);
+ ConnEnd dstPt197(Point(736.5, 883), 15);
+ connRef197->setDestEndpoint(dstPt197);
+ connRef197->setRoutingType((ConnType)2);
+
+ ConnRef *connRef198 = new ConnRef(router, 198);
+ ConnEnd srcPt198(Point(933.5, 883), 8);
+ connRef198->setSourceEndpoint(srcPt198);
+ ConnEnd dstPt198(Point(1191.5, 883), 15);
+ connRef198->setDestEndpoint(dstPt198);
+ connRef198->setRoutingType((ConnType)2);
+
+ ConnRef *connRef199 = new ConnRef(router, 199);
+ ConnEnd srcPt199(Point(491.5, 777), 8);
+ connRef199->setSourceEndpoint(srcPt199);
+ ConnEnd dstPt199(Point(736.5, 883), 15);
+ connRef199->setDestEndpoint(dstPt199);
+ connRef199->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints199(1);
+ checkpoints199[0] = Point(438.5, 883);
+ connRef199->setRoutingCheckpoints(checkpoints199);
+
+ ConnRef *connRef200 = new ConnRef(router, 200);
+ ConnEnd srcPt200(Point(491.5, 852), 8);
+ connRef200->setSourceEndpoint(srcPt200);
+ ConnEnd dstPt200(Point(736.5, 883), 15);
+ connRef200->setDestEndpoint(dstPt200);
+ connRef200->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints200(1);
+ checkpoints200[0] = Point(438.5, 883);
+ connRef200->setRoutingCheckpoints(checkpoints200);
+
+ ConnRef *connRef201 = new ConnRef(router, 201);
+ ConnEnd srcPt201(Point(783.5, 740), 4);
+ connRef201->setSourceEndpoint(srcPt201);
+ ConnEnd dstPt201(Point(736.5, 883), 15);
+ connRef201->setDestEndpoint(dstPt201);
+ connRef201->setRoutingType((ConnType)2);
+
+ ConnRef *connRef202 = new ConnRef(router, 202);
+ ConnEnd srcPt202(Point(813.5, 740), 8);
+ connRef202->setSourceEndpoint(srcPt202);
+ ConnEnd dstPt202(Point(1191.5, 584), 15);
+ connRef202->setDestEndpoint(dstPt202);
+ connRef202->setRoutingType((ConnType)2);
+
+ ConnRef *connRef203 = new ConnRef(router, 203);
+ ConnEnd srcPt203(Point(643.5, 755), 2);
+ connRef203->setSourceEndpoint(srcPt203);
+ ConnEnd dstPt203(Point(736.5, 883), 15);
+ connRef203->setDestEndpoint(dstPt203);
+ connRef203->setRoutingType((ConnType)2);
+
+ ConnRef *connRef204 = new ConnRef(router, 204);
+ ConnEnd srcPt204(Point(643.5, 725), 1);
+ connRef204->setSourceEndpoint(srcPt204);
+ ConnEnd dstPt204(Point(1191.5, 584), 15);
+ connRef204->setDestEndpoint(dstPt204);
+ connRef204->setRoutingType((ConnType)2);
+
+ ConnRef *connRef205 = new ConnRef(router, 205);
+ ConnEnd srcPt205(Point(286.5, 725), 1);
+ connRef205->setSourceEndpoint(srcPt205);
+ ConnEnd dstPt205(Point(286.5, 584), 15);
+ connRef205->setDestEndpoint(dstPt205);
+ connRef205->setRoutingType((ConnType)2);
+
+ ConnRef *connRef206 = new ConnRef(router, 206);
+ ConnEnd srcPt206(Point(286.5, 755), 2);
+ connRef206->setSourceEndpoint(srcPt206);
+ ConnEnd dstPt206(Point(286.5, 883), 15);
+ connRef206->setDestEndpoint(dstPt206);
+ connRef206->setRoutingType((ConnType)2);
+
+ ConnRef *connRef207 = new ConnRef(router, 207);
+ ConnEnd srcPt207(Point(722.5, 478), 8);
+ connRef207->setSourceEndpoint(srcPt207);
+ ConnEnd dstPt207(Point(1191.5, 584), 15);
+ connRef207->setDestEndpoint(dstPt207);
+ connRef207->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints207(1);
+ checkpoints207[0] = Point(669.5, 584);
+ connRef207->setRoutingCheckpoints(checkpoints207);
+
+ ConnRef *connRef208 = new ConnRef(router, 208);
+ ConnEnd srcPt208(Point(722.5, 553), 8);
+ connRef208->setSourceEndpoint(srcPt208);
+ ConnEnd dstPt208(Point(1191.5, 584), 15);
+ connRef208->setDestEndpoint(dstPt208);
+ connRef208->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints208(1);
+ checkpoints208[0] = Point(669.5, 584);
+ connRef208->setRoutingCheckpoints(checkpoints208);
+
+ ConnRef *connRef209 = new ConnRef(router, 209);
+ ConnEnd srcPt209(Point(692.5, 403), 4);
+ connRef209->setSourceEndpoint(srcPt209);
+ ConnEnd dstPt209(Point(286.5, 584), 15);
+ connRef209->setDestEndpoint(dstPt209);
+ connRef209->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints209(1);
+ checkpoints209[0] = Point(745.5, 584);
+ connRef209->setRoutingCheckpoints(checkpoints209);
+
+ ConnRef *connRef210 = new ConnRef(router, 210);
+ ConnEnd srcPt210(Point(752.5, 341), 4);
+ connRef210->setSourceEndpoint(srcPt210);
+ ConnEnd dstPt210(Point(286.5, 584), 15);
+ connRef210->setDestEndpoint(dstPt210);
+ connRef210->setRoutingType((ConnType)2);
+
+ ConnRef *connRef211 = new ConnRef(router, 211);
+ ConnEnd srcPt211(Point(752.5, 239), 4);
+ connRef211->setSourceEndpoint(srcPt211);
+ ConnEnd dstPt211(Point(286.5, 584), 15);
+ connRef211->setDestEndpoint(dstPt211);
+ connRef211->setRoutingType((ConnType)2);
+
+ ConnRef *connRef212 = new ConnRef(router, 212);
+ ConnEnd srcPt212(Point(507.5, 2312.46), 8);
+ connRef212->setSourceEndpoint(srcPt212);
+ ConnEnd dstPt212(Point(674.5, 2312.46), 15);
+ connRef212->setDestEndpoint(dstPt212);
+ connRef212->setRoutingType((ConnType)2);
+
+ ConnRef *connRef213 = new ConnRef(router, 213);
+ ConnEnd srcPt213(Point(1191.5, 1584.42), 2);
+ connRef213->setSourceEndpoint(srcPt213);
+ ConnEnd dstPt213(Point(1191.5, 1655.42), 15);
+ connRef213->setDestEndpoint(dstPt213);
+ connRef213->setRoutingType((ConnType)2);
+
+ ConnRef *connRef214 = new ConnRef(router, 214);
+ ConnEnd srcPt214(Point(1191.5, 1554.42), 1);
+ connRef214->setSourceEndpoint(srcPt214);
+ ConnEnd dstPt214(Point(1191.5, 1455.42), 15);
+ connRef214->setDestEndpoint(dstPt214);
+ connRef214->setRoutingType((ConnType)2);
+
+ ConnRef *connRef215 = new ConnRef(router, 215);
+ ConnEnd srcPt215(Point(722.5, 615), 8);
+ connRef215->setSourceEndpoint(srcPt215);
+ ConnEnd dstPt215(Point(1191.5, 584), 15);
+ connRef215->setDestEndpoint(dstPt215);
+ connRef215->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints215(1);
+ checkpoints215[0] = Point(669.5, 584);
+ connRef215->setRoutingCheckpoints(checkpoints215);
+
+ ConnRef *connRef216 = new ConnRef(router, 216);
+ ConnEnd srcPt216(Point(491.5, 914), 8);
+ connRef216->setSourceEndpoint(srcPt216);
+ ConnEnd dstPt216(Point(736.5, 883), 15);
+ connRef216->setDestEndpoint(dstPt216);
+ connRef216->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints216(1);
+ checkpoints216[0] = Point(438.5, 883);
+ connRef216->setRoutingCheckpoints(checkpoints216);
+
+ ConnRef *connRef217 = new ConnRef(router, 217);
+ ConnEnd srcPt217(Point(301.5, 1076), 8);
+ connRef217->setSourceEndpoint(srcPt217);
+ ConnEnd dstPt217(Point(406.5, 1076), 15);
+ connRef217->setDestEndpoint(dstPt217);
+ connRef217->setRoutingType((ConnType)2);
+
+ ConnRef *connRef218 = new ConnRef(router, 218);
+ ConnEnd srcPt218(Point(301.5, 1178), 8);
+ connRef218->setSourceEndpoint(srcPt218);
+ ConnEnd dstPt218(Point(406.5, 1178), 15);
+ connRef218->setDestEndpoint(dstPt218);
+ connRef218->setRoutingType((ConnType)2);
+
+ ConnRef *connRef219 = new ConnRef(router, 219);
+ ConnEnd srcPt219(Point(569.5, 1076), 8);
+ connRef219->setSourceEndpoint(srcPt219);
+ ConnEnd dstPt219(Point(736.5, 883), 15);
+ connRef219->setDestEndpoint(dstPt219);
+ connRef219->setRoutingType((ConnType)2);
+
+ ConnRef *connRef220 = new ConnRef(router, 220);
+ ConnEnd srcPt220(Point(569.5, 1178), 8);
+ connRef220->setSourceEndpoint(srcPt220);
+ ConnEnd dstPt220(Point(736.5, 883), 15);
+ connRef220->setDestEndpoint(dstPt220);
+ connRef220->setRoutingType((ConnType)2);
+
+ ConnRef *connRef221 = new ConnRef(router, 221);
+ ConnEnd srcPt221(Point(1401.5, 550.5), 15);
+ connRef221->setSourceEndpoint(srcPt221);
+ ConnEnd dstPt221(Point(1342.5, 550.5), 8);
+ connRef221->setDestEndpoint(dstPt221);
+ connRef221->setRoutingType((ConnType)2);
+
+ ConnRef *connRef222 = new ConnRef(router, 222);
+ ConnEnd srcPt222(Point(286.5, 584), 15);
+ connRef222->setSourceEndpoint(srcPt222);
+ ConnEnd dstPt222(Point(692.5, 615), 4);
+ connRef222->setDestEndpoint(dstPt222);
+ connRef222->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints222(1);
+ checkpoints222[0] = Point(745.5, 584);
+ connRef222->setRoutingCheckpoints(checkpoints222);
+
+ ConnRef *connRef223 = new ConnRef(router, 223);
+ ConnEnd srcPt223(Point(286.5, 584), 15);
+ connRef223->setSourceEndpoint(srcPt223);
+ ConnEnd dstPt223(Point(692.5, 690), 4);
+ connRef223->setDestEndpoint(dstPt223);
+ connRef223->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints223(1);
+ checkpoints223[0] = Point(745.5, 584);
+ connRef223->setRoutingCheckpoints(checkpoints223);
+
+ ConnRef *connRef224 = new ConnRef(router, 224);
+ ConnEnd srcPt224(Point(286.5, 883), 15);
+ connRef224->setSourceEndpoint(srcPt224);
+ ConnEnd dstPt224(Point(461.5, 914), 4);
+ connRef224->setDestEndpoint(dstPt224);
+ connRef224->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints224(1);
+ checkpoints224[0] = Point(514.5, 883);
+ connRef224->setRoutingCheckpoints(checkpoints224);
+
+ ConnRef *connRef225 = new ConnRef(router, 225);
+ ConnEnd srcPt225(Point(461.5, 989), 4);
+ connRef225->setSourceEndpoint(srcPt225);
+ ConnEnd dstPt225(Point(286.5, 883), 15);
+ connRef225->setDestEndpoint(dstPt225);
+ connRef225->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints225(1);
+ checkpoints225[0] = Point(514.5, 883);
+ connRef225->setRoutingCheckpoints(checkpoints225);
+
+ ConnRef *connRef226 = new ConnRef(router, 226);
+ ConnEnd srcPt226(Point(491.5, 989), 8);
+ connRef226->setSourceEndpoint(srcPt226);
+ ConnEnd dstPt226(Point(736.5, 883), 15);
+ connRef226->setDestEndpoint(dstPt226);
+ connRef226->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints226(1);
+ checkpoints226[0] = Point(438.5, 883);
+ connRef226->setRoutingCheckpoints(checkpoints226);
+
+ ConnRef *connRef227 = new ConnRef(router, 227);
+ ConnEnd srcPt227(Point(1191.5, 883), 15);
+ connRef227->setSourceEndpoint(srcPt227);
+ ConnEnd dstPt227(Point(1313.5, 1048.75), 1);
+ connRef227->setDestEndpoint(dstPt227);
+ connRef227->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints227(1);
+ checkpoints227[0] = Point(1191.5, 1093.75);
+ connRef227->setRoutingCheckpoints(checkpoints227);
+
+ ConnRef *connRef228 = new ConnRef(router, 228);
+ ConnEnd srcPt228(Point(714.439, 1872.42), 8);
+ connRef228->setSourceEndpoint(srcPt228);
+ ConnEnd dstPt228(Point(1191.5, 1903.42), 15);
+ connRef228->setDestEndpoint(dstPt228);
+ connRef228->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints228(1);
+ checkpoints228[0] = Point(737.439, 1903.42);
+ connRef228->setRoutingCheckpoints(checkpoints228);
+
+ ConnRef *connRef229 = new ConnRef(router, 229);
+ ConnEnd srcPt229(Point(1240.5, 1522.42), 2);
+ connRef229->setSourceEndpoint(srcPt229);
+ ConnEnd dstPt229(Point(1191.5, 1655.42), 15);
+ connRef229->setDestEndpoint(dstPt229);
+ connRef229->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints229(1);
+ checkpoints229[0] = Point(1265.5, 1537.42);
+ connRef229->setRoutingCheckpoints(checkpoints229);
+
+ ConnRef *connRef230 = new ConnRef(router, 230);
+ ConnEnd srcPt230(Point(1331.5, 1522.42), 2);
+ connRef230->setSourceEndpoint(srcPt230);
+ ConnEnd dstPt230(Point(1191.5, 1655.42), 15);
+ connRef230->setDestEndpoint(dstPt230);
+ connRef230->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints230(1);
+ checkpoints230[0] = Point(1265.5, 1537.42);
+ connRef230->setRoutingCheckpoints(checkpoints230);
+
+ ConnRef *connRef231 = new ConnRef(router, 231);
+ ConnEnd srcPt231(Point(1422.5, 1522.42), 2);
+ connRef231->setSourceEndpoint(srcPt231);
+ ConnEnd dstPt231(Point(1191.5, 1655.42), 15);
+ connRef231->setDestEndpoint(dstPt231);
+ connRef231->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints231(1);
+ checkpoints231[0] = Point(1265.5, 1537.42);
+ connRef231->setRoutingCheckpoints(checkpoints231);
+
+ ConnRef *connRef232 = new ConnRef(router, 232);
+ ConnEnd srcPt232(Point(1222.5, 1358.42), 2);
+ connRef232->setSourceEndpoint(srcPt232);
+ ConnEnd dstPt232(Point(1191.5, 1455.42), 15);
+ connRef232->setDestEndpoint(dstPt232);
+ connRef232->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints232(1);
+ checkpoints232[0] = Point(1191.5, 1373.42);
+ connRef232->setRoutingCheckpoints(checkpoints232);
+
+ ConnRef *connRef233 = new ConnRef(router, 233);
+ ConnEnd srcPt233(Point(1115.5, 1455.42), 8);
+ connRef233->setSourceEndpoint(srcPt233);
+ ConnEnd dstPt233(Point(1191.5, 1455.42), 15);
+ connRef233->setDestEndpoint(dstPt233);
+ connRef233->setRoutingType((ConnType)2);
+
+ ConnRef *connRef234 = new ConnRef(router, 234);
+ ConnEnd srcPt234(Point(1104.5, 2273.79), 8);
+ connRef234->setSourceEndpoint(srcPt234);
+ ConnEnd dstPt234(Point(1327.5, 2379.79), 15);
+ connRef234->setDestEndpoint(dstPt234);
+ connRef234->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints234(1);
+ checkpoints234[0] = Point(1127.5, 2379.79);
+ connRef234->setRoutingCheckpoints(checkpoints234);
+
+ ConnRef *connRef235 = new ConnRef(router, 235);
+ ConnEnd srcPt235(Point(1104.5, 2348.79), 8);
+ connRef235->setSourceEndpoint(srcPt235);
+ ConnEnd dstPt235(Point(1327.5, 2379.79), 15);
+ connRef235->setDestEndpoint(dstPt235);
+ connRef235->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints235(1);
+ checkpoints235[0] = Point(1127.5, 2379.79);
+ connRef235->setRoutingCheckpoints(checkpoints235);
+
+ ConnRef *connRef236 = new ConnRef(router, 236);
+ ConnEnd srcPt236(Point(1104.5, 2410.79), 8);
+ connRef236->setSourceEndpoint(srcPt236);
+ ConnEnd dstPt236(Point(1327.5, 2379.79), 15);
+ connRef236->setDestEndpoint(dstPt236);
+ connRef236->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints236(1);
+ checkpoints236[0] = Point(1127.5, 2379.79);
+ connRef236->setRoutingCheckpoints(checkpoints236);
+
+ ConnRef *connRef237 = new ConnRef(router, 237);
+ ConnEnd srcPt237(Point(1104.5, 2485.79), 8);
+ connRef237->setSourceEndpoint(srcPt237);
+ ConnEnd dstPt237(Point(1327.5, 2379.79), 15);
+ connRef237->setDestEndpoint(dstPt237);
+ connRef237->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints237(1);
+ checkpoints237[0] = Point(1127.5, 2379.79);
+ connRef237->setRoutingCheckpoints(checkpoints237);
+
+ ConnRef *connRef238 = new ConnRef(router, 238);
+ ConnEnd srcPt238(Point(569.5, 2040.42), 8);
+ connRef238->setSourceEndpoint(srcPt238);
+ ConnEnd dstPt238(Point(1191.5, 2169.42), 15);
+ connRef238->setDestEndpoint(dstPt238);
+ connRef238->setRoutingType((ConnType)2);
+
+ ConnRef *connRef239 = new ConnRef(router, 239);
+ ConnEnd srcPt239(Point(829.5, 2169.42), 15);
+ connRef239->setSourceEndpoint(srcPt239);
+ ConnEnd dstPt239(Point(829.5, 2302.79), 1);
+ connRef239->setDestEndpoint(dstPt239);
+ connRef239->setRoutingType((ConnType)2);
+
+ ConnRef *connRef240 = new ConnRef(router, 240);
+ ConnEnd srcPt240(Point(539.5, 2040.42), 4);
+ connRef240->setSourceEndpoint(srcPt240);
+ ConnEnd dstPt240(Point(251.5, 2169.42), 15);
+ connRef240->setDestEndpoint(dstPt240);
+ connRef240->setRoutingType((ConnType)2);
+
+ ConnRef *connRef241 = new ConnRef(router, 241);
+ ConnEnd srcPt241(Point(1074.5, 2410.79), 4);
+ connRef241->setSourceEndpoint(srcPt241);
+ ConnEnd dstPt241(Point(829.5, 2379.79), 15);
+ connRef241->setDestEndpoint(dstPt241);
+ connRef241->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints241(1);
+ checkpoints241[0] = Point(1051.5, 2379.79);
+ connRef241->setRoutingCheckpoints(checkpoints241);
+
+ ConnRef *connRef242 = new ConnRef(router, 242);
+ ConnEnd srcPt242(Point(1074.5, 2485.79), 4);
+ connRef242->setSourceEndpoint(srcPt242);
+ ConnEnd dstPt242(Point(829.5, 2379.79), 15);
+ connRef242->setDestEndpoint(dstPt242);
+ connRef242->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints242(1);
+ checkpoints242[0] = Point(1051.5, 2379.79);
+ connRef242->setRoutingCheckpoints(checkpoints242);
+
+ ConnRef *connRef243 = new ConnRef(router, 243);
+ ConnEnd srcPt243(Point(477.5, 2312.46), 4);
+ connRef243->setSourceEndpoint(srcPt243);
+ ConnEnd dstPt243(Point(375.5, 2312.46), 15);
+ connRef243->setDestEndpoint(dstPt243);
+ connRef243->setRoutingType((ConnType)2);
+
+ ConnRef *connRef244 = new ConnRef(router, 244);
+ ConnEnd srcPt244(Point(1191.5, 1115.75), 15);
+ connRef244->setSourceEndpoint(srcPt244);
+ ConnEnd dstPt244(Point(1160.5, 1078.75), 2);
+ connRef244->setDestEndpoint(dstPt244);
+ connRef244->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints244(1);
+ checkpoints244[0] = Point(1191.5, 1033.75);
+ connRef244->setRoutingCheckpoints(checkpoints244);
+
+ ConnRef *connRef245 = new ConnRef(router, 245);
+ ConnEnd srcPt245(Point(216.5, 1076), 15);
+ connRef245->setSourceEndpoint(srcPt245);
+ ConnEnd dstPt245(Point(271.5, 1076), 4);
+ connRef245->setDestEndpoint(dstPt245);
+ connRef245->setRoutingType((ConnType)2);
+
+ ConnRef *connRef246 = new ConnRef(router, 246);
+ ConnEnd srcPt246(Point(406.5, 1076), 15);
+ connRef246->setSourceEndpoint(srcPt246);
+ ConnEnd dstPt246(Point(539.5, 1076), 4);
+ connRef246->setDestEndpoint(dstPt246);
+ connRef246->setRoutingType((ConnType)2);
+
+ ConnRef *connRef247 = new ConnRef(router, 247);
+ ConnEnd srcPt247(Point(406.5, 1178), 15);
+ connRef247->setSourceEndpoint(srcPt247);
+ ConnEnd dstPt247(Point(539.5, 1178), 4);
+ connRef247->setDestEndpoint(dstPt247);
+ connRef247->setRoutingType((ConnType)2);
+
+ ConnRef *connRef248 = new ConnRef(router, 248);
+ ConnEnd srcPt248(Point(216.5, 1178), 15);
+ connRef248->setSourceEndpoint(srcPt248);
+ ConnEnd dstPt248(Point(271.5, 1178), 4);
+ connRef248->setDestEndpoint(dstPt248);
+ connRef248->setRoutingType((ConnType)2);
+
+ ConnRef *connRef249 = new ConnRef(router, 249);
+ ConnEnd srcPt249(Point(714.439, 1934.42), 8);
+ connRef249->setSourceEndpoint(srcPt249);
+ ConnEnd dstPt249(Point(1191.5, 1903.42), 15);
+ connRef249->setDestEndpoint(dstPt249);
+ connRef249->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints249(1);
+ checkpoints249[0] = Point(737.439, 1903.42);
+ connRef249->setRoutingCheckpoints(checkpoints249);
+#endif
+
+ ConnRef *connRef250 = new ConnRef(router, 250);
+ ConnEnd srcPt250(Point(251.5, 1903.42), 15);
+ connRef250->setSourceEndpoint(srcPt250);
+ ConnEnd dstPt250(Point(684.439, 1934.42), 4);
+ connRef250->setDestEndpoint(dstPt250);
+ connRef250->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints250(1);
+ checkpoints250[0] = Point(661.439, 1903.42);
+ connRef250->setRoutingCheckpoints(checkpoints250);
+
+ ConnRef *connRef251 = new ConnRef(router, 251);
+ ConnEnd srcPt251(Point(251.5, 1903.42), 15);
+ connRef251->setSourceEndpoint(srcPt251);
+ ConnEnd dstPt251(Point(684.439, 1872.42), 4);
+ connRef251->setDestEndpoint(dstPt251);
+ connRef251->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints251(1);
+ checkpoints251[0] = Point(661.439, 1903.42);
+ connRef251->setRoutingCheckpoints(checkpoints251);
+
+#ifdef ALL
+ ConnRef *connRef252 = new ConnRef(router, 252);
+ ConnEnd srcPt252(Point(1222.5, 1328.42), 1);
+ connRef252->setSourceEndpoint(srcPt252);
+ ConnEnd dstPt252(Point(1191.5, 1291.42), 15);
+ connRef252->setDestEndpoint(dstPt252);
+ connRef252->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints252(1);
+ checkpoints252[0] = Point(1191.5, 1313.42);
+ connRef252->setRoutingCheckpoints(checkpoints252);
+
+ ConnRef *connRef253 = new ConnRef(router, 253);
+ ConnEnd srcPt253(Point(1085.5, 1649.42), 4);
+ connRef253->setSourceEndpoint(srcPt253);
+ ConnEnd dstPt253(Point(949.5, 1569.42), 15);
+ connRef253->setDestEndpoint(dstPt253);
+ connRef253->setRoutingType((ConnType)2);
+
+ ConnRef *connRef254 = new ConnRef(router, 254);
+ ConnEnd srcPt254(Point(1115.5, 1649.42), 8);
+ connRef254->setSourceEndpoint(srcPt254);
+ ConnEnd dstPt254(Point(1191.5, 1655.42), 15);
+ connRef254->setDestEndpoint(dstPt254);
+ connRef254->setRoutingType((ConnType)2);
+
+ ConnRef *connRef255 = new ConnRef(router, 255);
+ ConnEnd srcPt255(Point(1085.5, 1455.42), 4);
+ connRef255->setSourceEndpoint(srcPt255);
+ ConnEnd dstPt255(Point(949.5, 1569.42), 15);
+ connRef255->setDestEndpoint(dstPt255);
+ connRef255->setRoutingType((ConnType)2);
+
+ ConnRef *connRef256 = new ConnRef(router, 256);
+ ConnEnd srcPt256(Point(1191.5, 1291.42), 15);
+ connRef256->setSourceEndpoint(srcPt256);
+ ConnEnd dstPt256(Point(1240.5, 1492.42), 1);
+ connRef256->setDestEndpoint(dstPt256);
+ connRef256->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints256(1);
+ checkpoints256[0] = Point(1265.5, 1477.42);
+ connRef256->setRoutingCheckpoints(checkpoints256);
+
+ ConnRef *connRef257 = new ConnRef(router, 257);
+ ConnEnd srcPt257(Point(1191.5, 1291.42), 15);
+ connRef257->setSourceEndpoint(srcPt257);
+ ConnEnd dstPt257(Point(1331.5, 1492.42), 1);
+ connRef257->setDestEndpoint(dstPt257);
+ connRef257->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints257(1);
+ checkpoints257[0] = Point(1265.5, 1477.42);
+ connRef257->setRoutingCheckpoints(checkpoints257);
+
+ ConnRef *connRef258 = new ConnRef(router, 258);
+ ConnEnd srcPt258(Point(1191.5, 1291.42), 15);
+ connRef258->setSourceEndpoint(srcPt258);
+ ConnEnd dstPt258(Point(1422.5, 1492.42), 1);
+ connRef258->setDestEndpoint(dstPt258);
+ connRef258->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints258(1);
+ checkpoints258[0] = Point(1265.5, 1477.42);
+ connRef258->setRoutingCheckpoints(checkpoints258);
+
+ ConnRef *connRef259 = new ConnRef(router, 259);
+ ConnEnd srcPt259(Point(160.5, 2216.42), 1);
+ connRef259->setSourceEndpoint(srcPt259);
+ ConnEnd dstPt259(Point(251.5, 2169.42), 15);
+ connRef259->setDestEndpoint(dstPt259);
+ connRef259->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints259(1);
+ checkpoints259[0] = Point(226.5, 2201.42);
+ connRef259->setRoutingCheckpoints(checkpoints259);
+
+ ConnRef *connRef260 = new ConnRef(router, 260);
+ ConnEnd srcPt260(Point(1313.5, 1078.75), 2);
+ connRef260->setSourceEndpoint(srcPt260);
+ ConnEnd dstPt260(Point(1191.5, 1115.75), 15);
+ connRef260->setDestEndpoint(dstPt260);
+ connRef260->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints260(1);
+ checkpoints260[0] = Point(1191.5, 1033.75);
+ connRef260->setRoutingCheckpoints(checkpoints260);
+
+ ConnRef *connRef261 = new ConnRef(router, 261);
+ ConnEnd srcPt261(Point(722.5, 690), 8);
+ connRef261->setSourceEndpoint(srcPt261);
+ ConnEnd dstPt261(Point(1191.5, 584), 15);
+ connRef261->setDestEndpoint(dstPt261);
+ connRef261->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints261(1);
+ checkpoints261[0] = Point(669.5, 584);
+ connRef261->setRoutingCheckpoints(checkpoints261);
+
+ ConnRef *connRef262 = new ConnRef(router, 262);
+ ConnEnd srcPt262(Point(829.5, 2065.42), 15);
+ connRef262->setSourceEndpoint(srcPt262);
+ ConnEnd dstPt262(Point(1026.5, 2179.79), 8);
+ connRef262->setDestEndpoint(dstPt262);
+ connRef262->setRoutingType((ConnType)2);
+
+ ConnRef *connRef263 = new ConnRef(router, 263);
+ ConnEnd srcPt263(Point(829.5, 2065.42), 15);
+ connRef263->setSourceEndpoint(srcPt263);
+ ConnEnd dstPt263(Point(1011.5, 2083.42), 1);
+ connRef263->setDestEndpoint(dstPt263);
+ connRef263->setRoutingType((ConnType)2);
+
+ ConnRef *connRef264 = new ConnRef(router, 264);
+ ConnEnd srcPt264(Point(1249.5, 1196.75), 4);
+ connRef264->setSourceEndpoint(srcPt264);
+ ConnEnd dstPt264(Point(1191.5, 1196.75), 8);
+ connRef264->setDestEndpoint(dstPt264);
+ connRef264->setRoutingType((ConnType)2);
+
+ ConnRef *connRef265 = new ConnRef(router, 265);
+ ConnEnd srcPt265(Point(769.5, 2298.79), 2);
+ connRef265->setSourceEndpoint(srcPt265);
+ ConnEnd dstPt265(Point(769.5, 2348.79), 1);
+ connRef265->setDestEndpoint(dstPt265);
+ connRef265->setRoutingType((ConnType)2);
+
+ ConnRef *connRef266 = new ConnRef(router, 266);
+ ConnEnd srcPt266(Point(193.5, 2231.42), 8);
+ connRef266->setSourceEndpoint(srcPt266);
+ ConnEnd dstPt266(Point(251.5, 2231.42), 4);
+ connRef266->setDestEndpoint(dstPt266);
+ connRef266->setRoutingType((ConnType)2);
+
+ ConnRef *connRef267 = new ConnRef(router, 267);
+ ConnEnd srcPt267(Point(769.5, 2460.79), 1);
+ connRef267->setSourceEndpoint(srcPt267);
+ ConnEnd dstPt267(Point(769.5, 2410.79), 2);
+ connRef267->setDestEndpoint(dstPt267);
+ connRef267->setRoutingType((ConnType)2);
+
+ ConnRef *connRef268 = new ConnRef(router, 268);
+ ConnEnd srcPt268(Point(887.5, 2317.79), 4);
+ connRef268->setSourceEndpoint(srcPt268);
+ ConnEnd dstPt268(Point(829.5, 2317.79), 8);
+ connRef268->setDestEndpoint(dstPt268);
+ connRef268->setRoutingType((ConnType)2);
+
+ ConnRef *connRef269 = new ConnRef(router, 269);
+ ConnEnd srcPt269(Point(1089.5, 2223.79), 2);
+ connRef269->setSourceEndpoint(srcPt269);
+ ConnEnd dstPt269(Point(1089.5, 2273.79), 1);
+ connRef269->setDestEndpoint(dstPt269);
+ connRef269->setRoutingType((ConnType)2);
+
+ ConnRef *connRef270 = new ConnRef(router, 270);
+ ConnEnd srcPt270(Point(1089.5, 2298.79), 2);
+ connRef270->setSourceEndpoint(srcPt270);
+ ConnEnd dstPt270(Point(1089.5, 2348.79), 1);
+ connRef270->setDestEndpoint(dstPt270);
+ connRef270->setRoutingType((ConnType)2);
+
+ ConnRef *connRef271 = new ConnRef(router, 271);
+ ConnEnd srcPt271(Point(1011.5, 2229.79), 1);
+ connRef271->setSourceEndpoint(srcPt271);
+ ConnEnd dstPt271(Point(1011.5, 2179.79), 2);
+ connRef271->setDestEndpoint(dstPt271);
+ connRef271->setRoutingType((ConnType)2);
+
+ ConnRef *connRef272 = new ConnRef(router, 272);
+ ConnEnd srcPt272(Point(1069.5, 2098.42), 4);
+ connRef272->setSourceEndpoint(srcPt272);
+ ConnEnd dstPt272(Point(1011.5, 2098.42), 8);
+ connRef272->setDestEndpoint(dstPt272);
+ connRef272->setRoutingType((ConnType)2);
+
+ ConnRef *connRef273 = new ConnRef(router, 273);
+ ConnEnd srcPt273(Point(705.5, 2119.42), 2);
+ connRef273->setSourceEndpoint(srcPt273);
+ ConnEnd dstPt273(Point(705.5, 2169.42), 1);
+ connRef273->setDestEndpoint(dstPt273);
+ connRef273->setRoutingType((ConnType)2);
+
+ ConnRef *connRef274 = new ConnRef(router, 274);
+ ConnEnd srcPt274(Point(375.5, 2119.42), 2);
+ connRef274->setSourceEndpoint(srcPt274);
+ ConnEnd dstPt274(Point(375.5, 2169.42), 1);
+ connRef274->setDestEndpoint(dstPt274);
+ connRef274->setRoutingType((ConnType)2);
+
+ ConnRef *connRef275 = new ConnRef(router, 275);
+ ConnEnd srcPt275(Point(1358.5, 2119.42), 2);
+ connRef275->setSourceEndpoint(srcPt275);
+ ConnEnd dstPt275(Point(1358.5, 2169.42), 1);
+ connRef275->setDestEndpoint(dstPt275);
+ connRef275->setRoutingType((ConnType)2);
+
+ ConnRef *connRef276 = new ConnRef(router, 276);
+ ConnEnd srcPt276(Point(1249.5, 1965.42), 4);
+ connRef276->setSourceEndpoint(srcPt276);
+ ConnEnd dstPt276(Point(1191.5, 1965.42), 8);
+ connRef276->setDestEndpoint(dstPt276);
+ connRef276->setRoutingType((ConnType)2);
+
+ ConnRef *connRef277 = new ConnRef(router, 277);
+ ConnEnd srcPt277(Point(1249.5, 1841.42), 4);
+ connRef277->setSourceEndpoint(srcPt277);
+ ConnEnd dstPt277(Point(1191.5, 1841.42), 8);
+ connRef277->setDestEndpoint(dstPt277);
+ connRef277->setRoutingType((ConnType)2);
+
+ ConnRef *connRef278 = new ConnRef(router, 278);
+ ConnEnd srcPt278(Point(1249.5, 1717.42), 4);
+ connRef278->setSourceEndpoint(srcPt278);
+ ConnEnd dstPt278(Point(1191.5, 1717.42), 8);
+ connRef278->setDestEndpoint(dstPt278);
+ connRef278->setRoutingType((ConnType)2);
+
+ ConnRef *connRef279 = new ConnRef(router, 279);
+ ConnEnd srcPt279(Point(1102.5, 1343.42), 8);
+ connRef279->setSourceEndpoint(srcPt279);
+ ConnEnd dstPt279(Point(1160.5, 1343.42), 4);
+ connRef279->setDestEndpoint(dstPt279);
+ connRef279->setRoutingType((ConnType)2);
+
+ ConnRef *connRef280 = new ConnRef(router, 280);
+ ConnEnd srcPt280(Point(980.5, 1241.42), 2);
+ connRef280->setSourceEndpoint(srcPt280);
+ ConnEnd dstPt280(Point(980.5, 1291.42), 1);
+ connRef280->setDestEndpoint(dstPt280);
+ connRef280->setRoutingType((ConnType)2);
+
+ ConnRef *connRef281 = new ConnRef(router, 281);
+ ConnEnd srcPt281(Point(1280.5, 1063.75), 4);
+ connRef281->setSourceEndpoint(srcPt281);
+ ConnEnd dstPt281(Point(1222.5, 1063.75), 8);
+ connRef281->setDestEndpoint(dstPt281);
+ connRef281->setRoutingType((ConnType)2);
+
+ ConnRef *connRef282 = new ConnRef(router, 282);
+ ConnEnd srcPt282(Point(1102.5, 1063.75), 8);
+ connRef282->setSourceEndpoint(srcPt282);
+ ConnEnd dstPt282(Point(1160.5, 1063.75), 4);
+ connRef282->setDestEndpoint(dstPt282);
+ connRef282->setRoutingType((ConnType)2);
+
+ ConnRef *connRef283 = new ConnRef(router, 283);
+ ConnEnd srcPt283(Point(1327.5, 500.5), 2);
+ connRef283->setSourceEndpoint(srcPt283);
+ ConnEnd dstPt283(Point(1327.5, 550.5), 1);
+ connRef283->setDestEndpoint(dstPt283);
+ connRef283->setRoutingType((ConnType)2);
+
+ ConnRef *connRef284 = new ConnRef(router, 284);
+ ConnEnd srcPt284(Point(1249.5, 740), 4);
+ connRef284->setSourceEndpoint(srcPt284);
+ ConnEnd dstPt284(Point(1191.5, 740), 8);
+ connRef284->setDestEndpoint(dstPt284);
+ connRef284->setRoutingType((ConnType)2);
+
+ ConnRef *connRef285 = new ConnRef(router, 285);
+ ConnEnd srcPt285(Point(1249.5, 478), 4);
+ connRef285->setSourceEndpoint(srcPt285);
+ ConnEnd dstPt285(Point(1191.5, 478), 8);
+ connRef285->setDestEndpoint(dstPt285);
+ connRef285->setRoutingType((ConnType)2);
+
+ ConnRef *connRef286 = new ConnRef(router, 286);
+ ConnEnd srcPt286(Point(918.5, 833), 2);
+ connRef286->setSourceEndpoint(srcPt286);
+ ConnEnd dstPt286(Point(918.5, 883), 1);
+ connRef286->setDestEndpoint(dstPt286);
+ connRef286->setRoutingType((ConnType)2);
+
+ ConnRef *connRef287 = new ConnRef(router, 287);
+ ConnEnd srcPt287(Point(476.5, 727), 2);
+ connRef287->setSourceEndpoint(srcPt287);
+ ConnEnd dstPt287(Point(476.5, 777), 1);
+ connRef287->setDestEndpoint(dstPt287);
+ connRef287->setRoutingType((ConnType)2);
+
+ ConnRef *connRef288 = new ConnRef(router, 288);
+ ConnEnd srcPt288(Point(476.5, 802), 2);
+ connRef288->setSourceEndpoint(srcPt288);
+ ConnEnd dstPt288(Point(476.5, 852), 1);
+ connRef288->setDestEndpoint(dstPt288);
+ connRef288->setRoutingType((ConnType)2);
+
+ ConnRef *connRef289 = new ConnRef(router, 289);
+ ConnEnd srcPt289(Point(798.5, 690), 2);
+ connRef289->setSourceEndpoint(srcPt289);
+ ConnEnd dstPt289(Point(798.5, 740), 1);
+ connRef289->setDestEndpoint(dstPt289);
+ connRef289->setRoutingType((ConnType)2);
+
+ ConnRef *connRef290 = new ConnRef(router, 290);
+ ConnEnd srcPt290(Point(585.5, 740), 8);
+ connRef290->setSourceEndpoint(srcPt290);
+ ConnEnd dstPt290(Point(643.5, 740), 4);
+ connRef290->setDestEndpoint(dstPt290);
+ connRef290->setRoutingType((ConnType)2);
+
+ ConnRef *connRef291 = new ConnRef(router, 291);
+ ConnEnd srcPt291(Point(344.5, 740), 4);
+ connRef291->setSourceEndpoint(srcPt291);
+ ConnEnd dstPt291(Point(286.5, 740), 8);
+ connRef291->setDestEndpoint(dstPt291);
+ connRef291->setRoutingType((ConnType)2);
+
+ ConnRef *connRef292 = new ConnRef(router, 292);
+ ConnEnd srcPt292(Point(707.5, 428), 2);
+ connRef292->setSourceEndpoint(srcPt292);
+ ConnEnd dstPt292(Point(707.5, 478), 1);
+ connRef292->setDestEndpoint(dstPt292);
+ connRef292->setRoutingType((ConnType)2);
+
+ ConnRef *connRef293 = new ConnRef(router, 293);
+ ConnEnd srcPt293(Point(707.5, 503), 2);
+ connRef293->setSourceEndpoint(srcPt293);
+ ConnEnd dstPt293(Point(707.5, 553), 1);
+ connRef293->setDestEndpoint(dstPt293);
+ connRef293->setRoutingType((ConnType)2);
+
+ ConnRef *connRef294 = new ConnRef(router, 294);
+ ConnEnd srcPt294(Point(707.5, 353), 2);
+ connRef294->setSourceEndpoint(srcPt294);
+ ConnEnd dstPt294(Point(707.5, 403), 1);
+ connRef294->setDestEndpoint(dstPt294);
+ connRef294->setRoutingType((ConnType)2);
+
+ ConnRef *connRef295 = new ConnRef(router, 295);
+ ConnEnd srcPt295(Point(767.5, 291), 2);
+ connRef295->setSourceEndpoint(srcPt295);
+ ConnEnd dstPt295(Point(767.5, 341), 1);
+ connRef295->setDestEndpoint(dstPt295);
+ connRef295->setRoutingType((ConnType)2);
+
+ ConnRef *connRef296 = new ConnRef(router, 296);
+ ConnEnd srcPt296(Point(767.5, 189), 2);
+ connRef296->setSourceEndpoint(srcPt296);
+ ConnEnd dstPt296(Point(767.5, 239), 1);
+ connRef296->setDestEndpoint(dstPt296);
+ connRef296->setRoutingType((ConnType)2);
+
+ ConnRef *connRef297 = new ConnRef(router, 297);
+ ConnEnd srcPt297(Point(492.5, 2262.46), 2);
+ connRef297->setSourceEndpoint(srcPt297);
+ ConnEnd dstPt297(Point(492.5, 2312.46), 1);
+ connRef297->setDestEndpoint(dstPt297);
+ connRef297->setRoutingType((ConnType)2);
+
+ ConnRef *connRef298 = new ConnRef(router, 298);
+ ConnEnd srcPt298(Point(1249.5, 1569.42), 4);
+ connRef298->setSourceEndpoint(srcPt298);
+ ConnEnd dstPt298(Point(1191.5, 1569.42), 8);
+ connRef298->setDestEndpoint(dstPt298);
+ connRef298->setRoutingType((ConnType)2);
+
+ ConnRef *connRef299 = new ConnRef(router, 299);
+ ConnEnd srcPt299(Point(707.5, 665), 1);
+ connRef299->setSourceEndpoint(srcPt299);
+ ConnEnd dstPt299(Point(707.5, 615), 2);
+ connRef299->setDestEndpoint(dstPt299);
+ connRef299->setRoutingType((ConnType)2);
+
+ ConnRef *connRef300 = new ConnRef(router, 300);
+ ConnEnd srcPt300(Point(476.5, 964), 1);
+ connRef300->setSourceEndpoint(srcPt300);
+ ConnEnd dstPt300(Point(476.5, 914), 2);
+ connRef300->setDestEndpoint(dstPt300);
+ connRef300->setRoutingType((ConnType)2);
+
+ ConnRef *connRef301 = new ConnRef(router, 301);
+ ConnEnd srcPt301(Point(286.5, 1026), 2);
+ connRef301->setSourceEndpoint(srcPt301);
+ ConnEnd dstPt301(Point(286.5, 1076), 1);
+ connRef301->setDestEndpoint(dstPt301);
+ connRef301->setRoutingType((ConnType)2);
+
+ ConnRef *connRef302 = new ConnRef(router, 302);
+ ConnEnd srcPt302(Point(286.5, 1128), 2);
+ connRef302->setSourceEndpoint(srcPt302);
+ ConnEnd dstPt302(Point(286.5, 1178), 1);
+ connRef302->setDestEndpoint(dstPt302);
+ connRef302->setRoutingType((ConnType)2);
+
+ ConnRef *connRef303 = new ConnRef(router, 303);
+ ConnEnd srcPt303(Point(554.5, 1026), 2);
+ connRef303->setSourceEndpoint(srcPt303);
+ ConnEnd dstPt303(Point(554.5, 1076), 1);
+ connRef303->setDestEndpoint(dstPt303);
+ connRef303->setRoutingType((ConnType)2);
+
+ ConnRef *connRef304 = new ConnRef(router, 304);
+ ConnEnd srcPt304(Point(554.5, 1128), 2);
+ connRef304->setSourceEndpoint(srcPt304);
+ ConnEnd dstPt304(Point(554.5, 1178), 1);
+ connRef304->setDestEndpoint(dstPt304);
+ connRef304->setRoutingType((ConnType)2);
+
+ ConnRef *connRef305 = new ConnRef(router, 305);
+ ConnEnd srcPt305(Point(699.439, 1984.42), 1);
+ connRef305->setSourceEndpoint(srcPt305);
+ ConnEnd dstPt305(Point(699.439, 1934.42), 2);
+ connRef305->setDestEndpoint(dstPt305);
+ connRef305->setRoutingType((ConnType)2);
+
+ ConnRef *connRef306 = new ConnRef(router, 306);
+ ConnEnd srcPt306(Point(1089.5, 2460.79), 1);
+ connRef306->setSourceEndpoint(srcPt306);
+ ConnEnd dstPt306(Point(1089.5, 2410.79), 2);
+ connRef306->setDestEndpoint(dstPt306);
+ connRef306->setRoutingType((ConnType)2);
+
+ ConnRef *connRef307 = new ConnRef(router, 307);
+ ConnEnd srcPt307(Point(699.439, 1822.42), 2);
+ connRef307->setSourceEndpoint(srcPt307);
+ ConnEnd dstPt307(Point(699.439, 1872.42), 1);
+ connRef307->setDestEndpoint(dstPt307);
+ connRef307->setRoutingType((ConnType)2);
+
+ ConnRef *connRef308 = new ConnRef(router, 308);
+ ConnEnd srcPt308(Point(1280.5, 1343.42), 4);
+ connRef308->setSourceEndpoint(srcPt308);
+ ConnEnd dstPt308(Point(1222.5, 1343.42), 8);
+ connRef308->setDestEndpoint(dstPt308);
+ connRef308->setRoutingType((ConnType)2);
+
+ ConnRef *connRef309 = new ConnRef(router, 309);
+ ConnEnd srcPt309(Point(1298.5, 1507.42), 4);
+ connRef309->setSourceEndpoint(srcPt309);
+ ConnEnd dstPt309(Point(1240.5, 1507.42), 8);
+ connRef309->setDestEndpoint(dstPt309);
+ connRef309->setRoutingType((ConnType)2);
+
+ ConnRef *connRef310 = new ConnRef(router, 310);
+ ConnEnd srcPt310(Point(1389.5, 1507.42), 4);
+ connRef310->setSourceEndpoint(srcPt310);
+ ConnEnd dstPt310(Point(1331.5, 1507.42), 8);
+ connRef310->setDestEndpoint(dstPt310);
+ connRef310->setRoutingType((ConnType)2);
+
+ ConnRef *connRef311 = new ConnRef(router, 311);
+ ConnEnd srcPt311(Point(554.5, 1990.42), 2);
+ connRef311->setSourceEndpoint(srcPt311);
+ ConnEnd dstPt311(Point(554.5, 2040.42), 1);
+ connRef311->setDestEndpoint(dstPt311);
+ connRef311->setRoutingType((ConnType)2);
+
+ ConnRef *connRef312 = new ConnRef(router, 312);
+ ConnEnd srcPt312(Point(1480.5, 1507.42), 4);
+ connRef312->setSourceEndpoint(srcPt312);
+ ConnEnd dstPt312(Point(1422.5, 1507.42), 8);
+ connRef312->setDestEndpoint(dstPt312);
+ connRef312->setRoutingType((ConnType)2);
+
+ ConnRef *connRef313 = new ConnRef(router, 313);
+ ConnEnd srcPt313(Point(1100.5, 1599.42), 2);
+ connRef313->setSourceEndpoint(srcPt313);
+ ConnEnd dstPt313(Point(1100.5, 1649.42), 1);
+ connRef313->setDestEndpoint(dstPt313);
+ connRef313->setRoutingType((ConnType)2);
+
+ ConnRef *connRef314 = new ConnRef(router, 314);
+ ConnEnd srcPt314(Point(1100.5, 1405.42), 2);
+ connRef314->setSourceEndpoint(srcPt314);
+ ConnEnd dstPt314(Point(1100.5, 1455.42), 1);
+ connRef314->setDestEndpoint(dstPt314);
+ connRef314->setRoutingType((ConnType)2);
+
+ ConnRef *connRef315 = new ConnRef(router, 315);
+ ConnEnd srcPt315(Point(102.5, 2231.42), 8);
+ connRef315->setSourceEndpoint(srcPt315);
+ ConnEnd dstPt315(Point(160.5, 2231.42), 4);
+ connRef315->setDestEndpoint(dstPt315);
+ connRef315->setRoutingType((ConnType)2);
+
+ ConnRef *connRef316 = new ConnRef(router, 316);
+ ConnEnd srcPt316(Point(1371.5, 1063.75), 4);
+ connRef316->setSourceEndpoint(srcPt316);
+ ConnEnd dstPt316(Point(1313.5, 1063.75), 8);
+ connRef316->setDestEndpoint(dstPt316);
+ connRef316->setRoutingType((ConnType)2);
+
+ ConnRef *connRef317 = new ConnRef(router, 317);
+ ConnEnd srcPt317(Point(707.5, 740), 1);
+ connRef317->setSourceEndpoint(srcPt317);
+ ConnEnd dstPt317(Point(707.5, 690), 2);
+ connRef317->setDestEndpoint(dstPt317);
+ connRef317->setRoutingType((ConnType)2);
+
+ ConnRef *connRef318 = new ConnRef(router, 318);
+ ConnEnd srcPt318(Point(476.5, 1039), 1);
+ connRef318->setSourceEndpoint(srcPt318);
+ ConnEnd dstPt318(Point(476.5, 989), 2);
+ connRef318->setDestEndpoint(dstPt318);
+ connRef318->setRoutingType((ConnType)2);
+
+ ConnRef *connRef319 = new ConnRef(router, 319);
+ ConnEnd srcPt319(Point(1089.5, 2535.79), 1);
+ connRef319->setSourceEndpoint(srcPt319);
+ ConnEnd dstPt319(Point(1089.5, 2485.79), 2);
+ connRef319->setDestEndpoint(dstPt319);
+ connRef319->setRoutingType((ConnType)2);
+
+ ConnRef *connRef320 = new ConnRef(router, 320);
+ ConnEnd srcPt320(Point(251.5, 2169.42), 15);
+ connRef320->setSourceEndpoint(srcPt320);
+ ConnEnd dstPt320(Point(251.5, 2216.42), 1);
+ connRef320->setDestEndpoint(dstPt320);
+ connRef320->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints320(1);
+ checkpoints320[0] = Point(226.5, 2201.42);
+ connRef320->setRoutingCheckpoints(checkpoints320);
+
+ ConnRef *connRef321 = new ConnRef(router, 321);
+ ConnEnd srcPt321(Point(1191.5, 2169.42), 15);
+ connRef321->setSourceEndpoint(srcPt321);
+ ConnEnd dstPt321(Point(1026.5, 2179.79), 8);
+ connRef321->setDestEndpoint(dstPt321);
+ connRef321->setRoutingType((ConnType)2);
+
+ ConnRef *connRef322 = new ConnRef(router, 322);
+ ConnEnd srcPt322(Point(1191.5, 2169.42), 15);
+ connRef322->setSourceEndpoint(srcPt322);
+ ConnEnd dstPt322(Point(1011.5, 2083.42), 1);
+ connRef322->setDestEndpoint(dstPt322);
+ connRef322->setRoutingType((ConnType)2);
+
+ ConnRef *connRef323 = new ConnRef(router, 323);
+ ConnEnd srcPt323(Point(674.5, 2312.46), 15);
+ connRef323->setSourceEndpoint(srcPt323);
+ ConnEnd dstPt323(Point(720.5, 2169.42), 8);
+ connRef323->setDestEndpoint(dstPt323);
+ connRef323->setRoutingType((ConnType)2);
+
+ ConnRef *connRef324 = new ConnRef(router, 324);
+ ConnEnd srcPt324(Point(829.5, 2169.42), 15);
+ connRef324->setSourceEndpoint(srcPt324);
+ ConnEnd dstPt324(Point(720.5, 2169.42), 8);
+ connRef324->setDestEndpoint(dstPt324);
+ connRef324->setRoutingType((ConnType)2);
+
+ ConnRef *connRef325 = new ConnRef(router, 325);
+ ConnEnd srcPt325(Point(1191.5, 1903.42), 15);
+ connRef325->setSourceEndpoint(srcPt325);
+ ConnEnd dstPt325(Point(1191.5, 1950.42), 1);
+ connRef325->setDestEndpoint(dstPt325);
+ connRef325->setRoutingType((ConnType)2);
+
+ ConnRef *connRef326 = new ConnRef(router, 326);
+ ConnEnd srcPt326(Point(1191.5, 883), 15);
+ connRef326->setSourceEndpoint(srcPt326);
+ ConnEnd dstPt326(Point(1222.5, 1048.75), 1);
+ connRef326->setDestEndpoint(dstPt326);
+ connRef326->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints326(1);
+ checkpoints326[0] = Point(1191.5, 1093.75);
+ connRef326->setRoutingCheckpoints(checkpoints326);
+
+ ConnRef *connRef327 = new ConnRef(router, 327);
+ ConnEnd srcPt327(Point(286.5, 883), 15);
+ connRef327->setSourceEndpoint(srcPt327);
+ ConnEnd dstPt327(Point(461.5, 777), 4);
+ connRef327->setDestEndpoint(dstPt327);
+ connRef327->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints327(1);
+ checkpoints327[0] = Point(514.5, 883);
+ connRef327->setRoutingCheckpoints(checkpoints327);
+
+ ConnRef *connRef328 = new ConnRef(router, 328);
+ ConnEnd srcPt328(Point(286.5, 883), 15);
+ connRef328->setSourceEndpoint(srcPt328);
+ ConnEnd dstPt328(Point(461.5, 852), 4);
+ connRef328->setDestEndpoint(dstPt328);
+ connRef328->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints328(1);
+ checkpoints328[0] = Point(514.5, 883);
+ connRef328->setRoutingCheckpoints(checkpoints328);
+
+ ConnRef *connRef329 = new ConnRef(router, 329);
+ ConnEnd srcPt329(Point(286.5, 584), 15);
+ connRef329->setSourceEndpoint(srcPt329);
+ ConnEnd dstPt329(Point(692.5, 478), 4);
+ connRef329->setDestEndpoint(dstPt329);
+ connRef329->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints329(1);
+ checkpoints329[0] = Point(745.5, 584);
+ connRef329->setRoutingCheckpoints(checkpoints329);
+
+ ConnRef *connRef330 = new ConnRef(router, 330);
+ ConnEnd srcPt330(Point(286.5, 584), 15);
+ connRef330->setSourceEndpoint(srcPt330);
+ ConnEnd dstPt330(Point(692.5, 553), 4);
+ connRef330->setDestEndpoint(dstPt330);
+ connRef330->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints330(1);
+ checkpoints330[0] = Point(745.5, 584);
+ connRef330->setRoutingCheckpoints(checkpoints330);
+
+ ConnRef *connRef331 = new ConnRef(router, 331);
+ ConnEnd srcPt331(Point(1191.5, 584), 15);
+ connRef331->setSourceEndpoint(srcPt331);
+ ConnEnd dstPt331(Point(722.5, 403), 8);
+ connRef331->setDestEndpoint(dstPt331);
+ connRef331->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints331(1);
+ checkpoints331[0] = Point(669.5, 584);
+ connRef331->setRoutingCheckpoints(checkpoints331);
+
+ ConnRef *connRef332 = new ConnRef(router, 332);
+ ConnEnd srcPt332(Point(1191.5, 280), 15);
+ connRef332->setSourceEndpoint(srcPt332);
+ ConnEnd dstPt332(Point(782.5, 341), 8);
+ connRef332->setDestEndpoint(dstPt332);
+ connRef332->setRoutingType((ConnType)2);
+
+ ConnRef *connRef333 = new ConnRef(router, 333);
+ ConnEnd srcPt333(Point(1191.5, 280), 15);
+ connRef333->setSourceEndpoint(srcPt333);
+ ConnEnd dstPt333(Point(782.5, 239), 8);
+ connRef333->setDestEndpoint(dstPt333);
+ connRef333->setRoutingType((ConnType)2);
+
+ ConnRef *connRef334 = new ConnRef(router, 334);
+ ConnEnd srcPt334(Point(1191.5, 584), 15);
+ connRef334->setSourceEndpoint(srcPt334);
+ ConnEnd dstPt334(Point(1427, 986.25), 4);
+ connRef334->setDestEndpoint(dstPt334);
+ connRef334->setRoutingType((ConnType)2);
+
+ ConnRef *connRef335 = new ConnRef(router, 335);
+ ConnEnd srcPt335(Point(1191.5, 1291.42), 15);
+ connRef335->setSourceEndpoint(srcPt335);
+ ConnEnd dstPt335(Point(1427, 1026.25), 4);
+ connRef335->setDestEndpoint(dstPt335);
+ connRef335->setRoutingType((ConnType)2);
+
+ ConnRef *connRef336 = new ConnRef(router, 336);
+ ConnEnd srcPt336(Point(1191.5, 1779.42), 15);
+ connRef336->setSourceEndpoint(srcPt336);
+ ConnEnd dstPt336(Point(1513, 1189.75), 2);
+ connRef336->setDestEndpoint(dstPt336);
+ connRef336->setRoutingType((ConnType)2);
+
+ ConnRef *connRef337 = new ConnRef(router, 337);
+ ConnEnd srcPt337(Point(1191.5, 2169.42), 15);
+ connRef337->setSourceEndpoint(srcPt337);
+ ConnEnd dstPt337(Point(1553, 1189.75), 2);
+ connRef337->setDestEndpoint(dstPt337);
+ connRef337->setRoutingType((ConnType)2);
+
+ ConnRef *connRef338 = new ConnRef(router, 338);
+ ConnEnd srcPt338(Point(1191.5, 280), 15);
+ connRef338->setSourceEndpoint(srcPt338);
+ ConnEnd dstPt338(Point(1252, 214.5), 2);
+ connRef338->setDestEndpoint(dstPt338);
+ connRef338->setRoutingType((ConnType)2);
+
+ ConnRef *connRef339 = new ConnRef(router, 339);
+ ConnEnd srcPt339(Point(251.5, 1903.42), 15);
+ connRef339->setSourceEndpoint(srcPt339);
+ ConnEnd dstPt339(Point(247.5, 2025.92), 8);
+ connRef339->setDestEndpoint(dstPt339);
+ connRef339->setRoutingType((ConnType)2);
+
+ ConnRef *connRef340 = new ConnRef(router, 340);
+ ConnEnd srcPt340(Point(251.5, 2169.42), 15);
+ connRef340->setSourceEndpoint(srcPt340);
+ ConnEnd dstPt340(Point(247.5, 2065.92), 8);
+ connRef340->setDestEndpoint(dstPt340);
+ connRef340->setRoutingType((ConnType)2);
+
+ ConnRef *connRef341 = new ConnRef(router, 341);
+ ConnEnd srcPt341(Point(1191.5, 1655.42), 15);
+ connRef341->setSourceEndpoint(srcPt341);
+ ConnEnd dstPt341(Point(736.5, 1662.92), 8);
+ connRef341->setDestEndpoint(dstPt341);
+ connRef341->setRoutingType((ConnType)2);
+
+ ConnRef *connRef342 = new ConnRef(router, 342);
+ ConnEnd srcPt342(Point(1432.5, 2169.42), 15);
+ connRef342->setSourceEndpoint(srcPt342);
+ ConnEnd dstPt342(Point(1438.5, 2248.79), 1);
+ connRef342->setDestEndpoint(dstPt342);
+ connRef342->setRoutingType((ConnType)2);
+#endif
+
+ router->processTransaction();
+ router->outputDiagram("output/checkpointNudging1");
+ bool atEnds = true;
+ bool overlap = router->existsOrthogonalFixedSegmentOverlap(atEnds);
+ delete router;
+ return (overlap) ? 1 : 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/checkpointNudging2.cpp b/src/3rdparty/adaptagrams/libavoid/tests/checkpointNudging2.cpp
new file mode 100644
index 0000000..f06b148
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/checkpointNudging2.cpp
@@ -0,0 +1,2606 @@
+// KEGG -> SBGN example #10
+//
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingParameter((RoutingParameter)0, 50);
+ router->setRoutingParameter((RoutingParameter)1, 0);
+ router->setRoutingParameter((RoutingParameter)2, 0);
+ router->setRoutingParameter((RoutingParameter)3, 4000);
+ router->setRoutingParameter((RoutingParameter)4, 0);
+ router->setRoutingParameter((RoutingParameter)5, 100);
+ router->setRoutingOption((RoutingOption)0, true);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, false);
+
+
+ Polygon poly1(4);
+ poly1.ps[0] = Point(1201.5, 1180.75);
+ poly1.ps[1] = Point(1201.5, 1212.75);
+ poly1.ps[2] = Point(1181.5, 1212.75);
+ poly1.ps[3] = Point(1181.5, 1180.75);
+ new ShapeRef(router, poly1, 1);
+
+#ifdef ALL
+ Polygon poly2(4);
+ poly2.ps[0] = Point(785.5, 2338.79);
+ poly2.ps[1] = Point(785.5, 2358.79);
+ poly2.ps[2] = Point(753.5, 2358.79);
+ poly2.ps[3] = Point(753.5, 2338.79);
+ new ShapeRef(router, poly2, 2);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(261.5, 2215.42);
+ poly3.ps[1] = Point(261.5, 2247.42);
+ poly3.ps[2] = Point(241.5, 2247.42);
+ poly3.ps[3] = Point(241.5, 2215.42);
+ new ShapeRef(router, poly3, 3);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(785.5, 2400.79);
+ poly4.ps[1] = Point(785.5, 2420.79);
+ poly4.ps[2] = Point(753.5, 2420.79);
+ poly4.ps[3] = Point(753.5, 2400.79);
+ new ShapeRef(router, poly4, 4);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(282.5, 2348.79);
+ poly5.ps[1] = Point(282.5, 2410.79);
+ poly5.ps[2] = Point(220.5, 2410.79);
+ poly5.ps[3] = Point(220.5, 2348.79);
+ new ShapeRef(router, poly5, 5);
+#endif
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(1643.5, 817.25);
+ poly6.ps[1] = Point(1643.5, 1194.25);
+ poly6.ps[2] = Point(1421.5, 1194.25);
+ poly6.ps[3] = Point(1421.5, 817.25);
+ new ShapeRef(router, poly6, 6);
+
+#ifdef ALL
+ Polygon poly7(4);
+ poly7.ps[0] = Point(1311.5, 45);
+ poly7.ps[1] = Point(1311.5, 219);
+ poly7.ps[2] = Point(1191.5, 219);
+ poly7.ps[3] = Point(1191.5, 45);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(839.5, 2301.79);
+ poly8.ps[1] = Point(839.5, 2333.79);
+ poly8.ps[2] = Point(819.5, 2333.79);
+ poly8.ps[3] = Point(819.5, 2301.79);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(1105.5, 2263.79);
+ poly9.ps[1] = Point(1105.5, 2283.79);
+ poly9.ps[2] = Point(1073.5, 2283.79);
+ poly9.ps[3] = Point(1073.5, 2263.79);
+ new ShapeRef(router, poly9, 9);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(1105.5, 2338.79);
+ poly10.ps[1] = Point(1105.5, 2358.79);
+ poly10.ps[2] = Point(1073.5, 2358.79);
+ poly10.ps[3] = Point(1073.5, 2338.79);
+ new ShapeRef(router, poly10, 10);
+
+ Polygon poly11(4);
+ poly11.ps[0] = Point(1027.5, 2169.79);
+ poly11.ps[1] = Point(1027.5, 2189.79);
+ poly11.ps[2] = Point(995.5, 2189.79);
+ poly11.ps[3] = Point(995.5, 2169.79);
+ new ShapeRef(router, poly11, 11);
+
+ Polygon poly12(4);
+ poly12.ps[0] = Point(1021.5, 2082.42);
+ poly12.ps[1] = Point(1021.5, 2114.42);
+ poly12.ps[2] = Point(1001.5, 2114.42);
+ poly12.ps[3] = Point(1001.5, 2082.42);
+ new ShapeRef(router, poly12, 12);
+
+ Polygon poly13(4);
+ poly13.ps[0] = Point(721.5, 2159.42);
+ poly13.ps[1] = Point(721.5, 2179.42);
+ poly13.ps[2] = Point(689.5, 2179.42);
+ poly13.ps[3] = Point(689.5, 2159.42);
+ new ShapeRef(router, poly13, 13);
+
+ Polygon poly14(4);
+ poly14.ps[0] = Point(391.5, 2159.42);
+ poly14.ps[1] = Point(391.5, 2179.42);
+ poly14.ps[2] = Point(359.5, 2179.42);
+ poly14.ps[3] = Point(359.5, 2159.42);
+ new ShapeRef(router, poly14, 14);
+
+ Polygon poly15(4);
+ poly15.ps[0] = Point(1374.5, 2159.42);
+ poly15.ps[1] = Point(1374.5, 2179.42);
+ poly15.ps[2] = Point(1342.5, 2179.42);
+ poly15.ps[3] = Point(1342.5, 2159.42);
+ new ShapeRef(router, poly15, 15);
+
+ Polygon poly16(4);
+ poly16.ps[0] = Point(923.421, 1631.86);
+ poly16.ps[1] = Point(923.421, 1675.86);
+ poly16.ps[2] = Point(835.421, 1675.86);
+ poly16.ps[3] = Point(835.421, 1631.86);
+ new ShapeRef(router, poly16, 16);
+
+ Polygon poly17(4);
+ poly17.ps[0] = Point(1201.5, 1949.42);
+ poly17.ps[1] = Point(1201.5, 1981.42);
+ poly17.ps[2] = Point(1181.5, 1981.42);
+ poly17.ps[3] = Point(1181.5, 1949.42);
+ new ShapeRef(router, poly17, 17);
+
+ Polygon poly18(4);
+ poly18.ps[0] = Point(252, 1963.42);
+ poly18.ps[1] = Point(252, 2127.42);
+ poly18.ps[2] = Point(45, 2127.42);
+ poly18.ps[3] = Point(45, 1963.42);
+ new ShapeRef(router, poly18, 18);
+
+ Polygon poly19(4);
+ poly19.ps[0] = Point(1201.5, 1825.42);
+ poly19.ps[1] = Point(1201.5, 1857.42);
+ poly19.ps[2] = Point(1181.5, 1857.42);
+ poly19.ps[3] = Point(1181.5, 1825.42);
+ new ShapeRef(router, poly19, 19);
+
+ Polygon poly20(4);
+ poly20.ps[0] = Point(1201.5, 1701.42);
+ poly20.ps[1] = Point(1201.5, 1733.42);
+ poly20.ps[2] = Point(1181.5, 1733.42);
+ poly20.ps[3] = Point(1181.5, 1701.42);
+ new ShapeRef(router, poly20, 20);
+
+ Polygon poly21(4);
+ poly21.ps[0] = Point(1170.5, 1327.42);
+ poly21.ps[1] = Point(1170.5, 1359.42);
+ poly21.ps[2] = Point(1150.5, 1359.42);
+ poly21.ps[3] = Point(1150.5, 1327.42);
+ new ShapeRef(router, poly21, 21);
+
+ Polygon poly22(4);
+ poly22.ps[0] = Point(741, 1632.42);
+ poly22.ps[1] = Point(741, 1692.42);
+ poly22.ps[2] = Point(428, 1692.42);
+ poly22.ps[3] = Point(428, 1632.42);
+ new ShapeRef(router, poly22, 22);
+
+ Polygon poly23(4);
+ poly23.ps[0] = Point(996.5, 1281.42);
+ poly23.ps[1] = Point(996.5, 1301.42);
+ poly23.ps[2] = Point(964.5, 1301.42);
+ poly23.ps[3] = Point(964.5, 1281.42);
+ new ShapeRef(router, poly23, 23);
+
+ Polygon poly24(4);
+ poly24.ps[0] = Point(1232.5, 1047.75);
+ poly24.ps[1] = Point(1232.5, 1079.75);
+ poly24.ps[2] = Point(1212.5, 1079.75);
+ poly24.ps[3] = Point(1212.5, 1047.75);
+ new ShapeRef(router, poly24, 24);
+
+ Polygon poly25(4);
+ poly25.ps[0] = Point(1170.5, 1047.75);
+ poly25.ps[1] = Point(1170.5, 1079.75);
+ poly25.ps[2] = Point(1150.5, 1079.75);
+ poly25.ps[3] = Point(1150.5, 1047.75);
+ new ShapeRef(router, poly25, 25);
+
+ Polygon poly26(4);
+ poly26.ps[0] = Point(1343.5, 540.5);
+ poly26.ps[1] = Point(1343.5, 560.5);
+ poly26.ps[2] = Point(1311.5, 560.5);
+ poly26.ps[3] = Point(1311.5, 540.5);
+ new ShapeRef(router, poly26, 26);
+
+ Polygon poly27(4);
+ poly27.ps[0] = Point(1201.5, 724);
+ poly27.ps[1] = Point(1201.5, 756);
+ poly27.ps[2] = Point(1181.5, 756);
+ poly27.ps[3] = Point(1181.5, 724);
+ new ShapeRef(router, poly27, 27);
+
+ Polygon poly28(4);
+ poly28.ps[0] = Point(1201.5, 462);
+ poly28.ps[1] = Point(1201.5, 494);
+ poly28.ps[2] = Point(1181.5, 494);
+ poly28.ps[3] = Point(1181.5, 462);
+ new ShapeRef(router, poly28, 28);
+
+ Polygon poly29(4);
+ poly29.ps[0] = Point(934.5, 873);
+ poly29.ps[1] = Point(934.5, 893);
+ poly29.ps[2] = Point(902.5, 893);
+ poly29.ps[3] = Point(902.5, 873);
+ new ShapeRef(router, poly29, 29);
+
+ Polygon poly30(4);
+ poly30.ps[0] = Point(492.5, 767);
+ poly30.ps[1] = Point(492.5, 787);
+ poly30.ps[2] = Point(460.5, 787);
+ poly30.ps[3] = Point(460.5, 767);
+ new ShapeRef(router, poly30, 30);
+
+ Polygon poly31(4);
+ poly31.ps[0] = Point(492.5, 842);
+ poly31.ps[1] = Point(492.5, 862);
+ poly31.ps[2] = Point(460.5, 862);
+ poly31.ps[3] = Point(460.5, 842);
+ new ShapeRef(router, poly31, 31);
+
+ Polygon poly32(4);
+ poly32.ps[0] = Point(814.5, 730);
+ poly32.ps[1] = Point(814.5, 750);
+ poly32.ps[2] = Point(782.5, 750);
+ poly32.ps[3] = Point(782.5, 730);
+ new ShapeRef(router, poly32, 32);
+
+ Polygon poly33(4);
+ poly33.ps[0] = Point(653.5, 724);
+ poly33.ps[1] = Point(653.5, 756);
+ poly33.ps[2] = Point(633.5, 756);
+ poly33.ps[3] = Point(633.5, 724);
+ new ShapeRef(router, poly33, 33);
+
+ Polygon poly34(4);
+ poly34.ps[0] = Point(296.5, 724);
+ poly34.ps[1] = Point(296.5, 756);
+ poly34.ps[2] = Point(276.5, 756);
+ poly34.ps[3] = Point(276.5, 724);
+ new ShapeRef(router, poly34, 34);
+
+ Polygon poly35(4);
+ poly35.ps[0] = Point(723.5, 468);
+ poly35.ps[1] = Point(723.5, 488);
+ poly35.ps[2] = Point(691.5, 488);
+ poly35.ps[3] = Point(691.5, 468);
+ new ShapeRef(router, poly35, 35);
+
+ Polygon poly36(4);
+ poly36.ps[0] = Point(723.5, 543);
+ poly36.ps[1] = Point(723.5, 563);
+ poly36.ps[2] = Point(691.5, 563);
+ poly36.ps[3] = Point(691.5, 543);
+ new ShapeRef(router, poly36, 36);
+
+ Polygon poly37(4);
+ poly37.ps[0] = Point(723.5, 393);
+ poly37.ps[1] = Point(723.5, 413);
+ poly37.ps[2] = Point(691.5, 413);
+ poly37.ps[3] = Point(691.5, 393);
+ new ShapeRef(router, poly37, 37);
+
+ Polygon poly38(4);
+ poly38.ps[0] = Point(783.5, 331);
+ poly38.ps[1] = Point(783.5, 351);
+ poly38.ps[2] = Point(751.5, 351);
+ poly38.ps[3] = Point(751.5, 331);
+ new ShapeRef(router, poly38, 38);
+
+ Polygon poly39(4);
+ poly39.ps[0] = Point(783.5, 229);
+ poly39.ps[1] = Point(783.5, 249);
+ poly39.ps[2] = Point(751.5, 249);
+ poly39.ps[3] = Point(751.5, 229);
+ new ShapeRef(router, poly39, 39);
+
+ Polygon poly40(4);
+ poly40.ps[0] = Point(402, 96.5);
+ poly40.ps[1] = Point(402, 131.5);
+ poly40.ps[2] = Point(141, 131.5);
+ poly40.ps[3] = Point(141, 96.5);
+ new ShapeRef(router, poly40, 40);
+
+ Polygon poly41(4);
+ poly41.ps[0] = Point(508.5, 2302.46);
+ poly41.ps[1] = Point(508.5, 2322.46);
+ poly41.ps[2] = Point(476.5, 2322.46);
+ poly41.ps[3] = Point(476.5, 2302.46);
+ new ShapeRef(router, poly41, 41);
+
+ Polygon poly42(4);
+ poly42.ps[0] = Point(1201.5, 1553.42);
+ poly42.ps[1] = Point(1201.5, 1585.42);
+ poly42.ps[2] = Point(1181.5, 1585.42);
+ poly42.ps[3] = Point(1181.5, 1553.42);
+ new ShapeRef(router, poly42, 42);
+
+ Polygon poly43(4);
+ poly43.ps[0] = Point(723.5, 605);
+ poly43.ps[1] = Point(723.5, 625);
+ poly43.ps[2] = Point(691.5, 625);
+ poly43.ps[3] = Point(691.5, 605);
+ new ShapeRef(router, poly43, 43);
+
+ Polygon poly44(4);
+ poly44.ps[0] = Point(492.5, 904);
+ poly44.ps[1] = Point(492.5, 924);
+ poly44.ps[2] = Point(460.5, 924);
+ poly44.ps[3] = Point(460.5, 904);
+ new ShapeRef(router, poly44, 44);
+
+ Polygon poly45(4);
+ poly45.ps[0] = Point(302.5, 1066);
+ poly45.ps[1] = Point(302.5, 1086);
+ poly45.ps[2] = Point(270.5, 1086);
+ poly45.ps[3] = Point(270.5, 1066);
+ new ShapeRef(router, poly45, 45);
+
+ Polygon poly46(4);
+ poly46.ps[0] = Point(302.5, 1168);
+ poly46.ps[1] = Point(302.5, 1188);
+ poly46.ps[2] = Point(270.5, 1188);
+ poly46.ps[3] = Point(270.5, 1168);
+ new ShapeRef(router, poly46, 46);
+
+ Polygon poly47(4);
+ poly47.ps[0] = Point(570.5, 1066);
+ poly47.ps[1] = Point(570.5, 1086);
+ poly47.ps[2] = Point(538.5, 1086);
+ poly47.ps[3] = Point(538.5, 1066);
+ new ShapeRef(router, poly47, 47);
+
+ Polygon poly48(4);
+ poly48.ps[0] = Point(570.5, 1168);
+ poly48.ps[1] = Point(570.5, 1188);
+ poly48.ps[2] = Point(538.5, 1188);
+ poly48.ps[3] = Point(538.5, 1168);
+ new ShapeRef(router, poly48, 48);
+
+ Polygon poly49(4);
+ poly49.ps[0] = Point(1432.5, 519.5);
+ poly49.ps[1] = Point(1432.5, 581.5);
+ poly49.ps[2] = Point(1370.5, 581.5);
+ poly49.ps[3] = Point(1370.5, 519.5);
+ new ShapeRef(router, poly49, 49);
+
+ Polygon poly50(4);
+ poly50.ps[0] = Point(1222.5, 249);
+ poly50.ps[1] = Point(1222.5, 311);
+ poly50.ps[2] = Point(1160.5, 311);
+ poly50.ps[3] = Point(1160.5, 249);
+ new ShapeRef(router, poly50, 50);
+
+ Polygon poly51(4);
+ poly51.ps[0] = Point(1222.5, 1748.42);
+ poly51.ps[1] = Point(1222.5, 1810.42);
+ poly51.ps[2] = Point(1160.5, 1810.42);
+ poly51.ps[3] = Point(1160.5, 1748.42);
+ new ShapeRef(router, poly51, 51);
+
+ Polygon poly52(4);
+ poly52.ps[0] = Point(317.5, 553);
+ poly52.ps[1] = Point(317.5, 615);
+ poly52.ps[2] = Point(255.5, 615);
+ poly52.ps[3] = Point(255.5, 553);
+ new ShapeRef(router, poly52, 52);
+
+ Polygon poly53(4);
+ poly53.ps[0] = Point(317.5, 852);
+ poly53.ps[1] = Point(317.5, 914);
+ poly53.ps[2] = Point(255.5, 914);
+ poly53.ps[3] = Point(255.5, 852);
+ new ShapeRef(router, poly53, 53);
+
+ Polygon poly54(4);
+ poly54.ps[0] = Point(767.5, 1260.42);
+ poly54.ps[1] = Point(767.5, 1322.42);
+ poly54.ps[2] = Point(705.5, 1322.42);
+ poly54.ps[3] = Point(705.5, 1260.42);
+ new ShapeRef(router, poly54, 54);
+
+ Polygon poly55(4);
+ poly55.ps[0] = Point(767.5, 852);
+ poly55.ps[1] = Point(767.5, 914);
+ poly55.ps[2] = Point(705.5, 914);
+ poly55.ps[3] = Point(705.5, 852);
+ new ShapeRef(router, poly55, 55);
+
+ Polygon poly56(4);
+ poly56.ps[0] = Point(1222.5, 553);
+ poly56.ps[1] = Point(1222.5, 615);
+ poly56.ps[2] = Point(1160.5, 615);
+ poly56.ps[3] = Point(1160.5, 553);
+ new ShapeRef(router, poly56, 56);
+
+ Polygon poly57(4);
+ poly57.ps[0] = Point(1222.5, 852);
+ poly57.ps[1] = Point(1222.5, 914);
+ poly57.ps[2] = Point(1160.5, 914);
+ poly57.ps[3] = Point(1160.5, 852);
+ new ShapeRef(router, poly57, 57);
+
+ Polygon poly58(4);
+ poly58.ps[0] = Point(1222.5, 1872.42);
+ poly58.ps[1] = Point(1222.5, 1934.42);
+ poly58.ps[2] = Point(1160.5, 1934.42);
+ poly58.ps[3] = Point(1160.5, 1872.42);
+ new ShapeRef(router, poly58, 58);
+
+ Polygon poly59(4);
+ poly59.ps[0] = Point(1222.5, 1624.42);
+ poly59.ps[1] = Point(1222.5, 1686.42);
+ poly59.ps[2] = Point(1160.5, 1686.42);
+ poly59.ps[3] = Point(1160.5, 1624.42);
+ new ShapeRef(router, poly59, 59);
+#endif
+
+ Polygon poly60(4);
+ poly60.ps[0] = Point(1222.5, 1424.42);
+ poly60.ps[1] = Point(1222.5, 1486.42);
+ poly60.ps[2] = Point(1160.5, 1486.42);
+ poly60.ps[3] = Point(1160.5, 1424.42);
+ new ShapeRef(router, poly60, 60);
+
+#ifdef ALL
+ Polygon poly61(4);
+ poly61.ps[0] = Point(1463.5, 2138.42);
+ poly61.ps[1] = Point(1463.5, 2200.42);
+ poly61.ps[2] = Point(1401.5, 2200.42);
+ poly61.ps[3] = Point(1401.5, 2138.42);
+ new ShapeRef(router, poly61, 61);
+
+ Polygon poly62(4);
+ poly62.ps[0] = Point(705.5, 2281.46);
+ poly62.ps[1] = Point(705.5, 2343.46);
+ poly62.ps[2] = Point(643.5, 2343.46);
+ poly62.ps[3] = Point(643.5, 2281.46);
+ new ShapeRef(router, poly62, 62);
+
+ Polygon poly63(4);
+ poly63.ps[0] = Point(1358.5, 2348.79);
+ poly63.ps[1] = Point(1358.5, 2410.79);
+ poly63.ps[2] = Point(1296.5, 2410.79);
+ poly63.ps[3] = Point(1296.5, 2348.79);
+ new ShapeRef(router, poly63, 63);
+
+ Polygon poly64(4);
+ poly64.ps[0] = Point(1222.5, 2138.42);
+ poly64.ps[1] = Point(1222.5, 2200.42);
+ poly64.ps[2] = Point(1160.5, 2200.42);
+ poly64.ps[3] = Point(1160.5, 2138.42);
+ new ShapeRef(router, poly64, 64);
+
+ Polygon poly65(4);
+ poly65.ps[0] = Point(860.5, 2138.42);
+ poly65.ps[1] = Point(860.5, 2200.42);
+ poly65.ps[2] = Point(798.5, 2200.42);
+ poly65.ps[3] = Point(798.5, 2138.42);
+ new ShapeRef(router, poly65, 65);
+
+ Polygon poly66(4);
+ poly66.ps[0] = Point(282.5, 2138.42);
+ poly66.ps[1] = Point(282.5, 2200.42);
+ poly66.ps[2] = Point(220.5, 2200.42);
+ poly66.ps[3] = Point(220.5, 2138.42);
+ new ShapeRef(router, poly66, 66);
+
+ Polygon poly67(4);
+ poly67.ps[0] = Point(860.5, 2348.79);
+ poly67.ps[1] = Point(860.5, 2410.79);
+ poly67.ps[2] = Point(798.5, 2410.79);
+ poly67.ps[3] = Point(798.5, 2348.79);
+ new ShapeRef(router, poly67, 67);
+
+ Polygon poly68(4);
+ poly68.ps[0] = Point(554.5, 2138.42);
+ poly68.ps[1] = Point(554.5, 2200.42);
+ poly68.ps[2] = Point(492.5, 2200.42);
+ poly68.ps[3] = Point(492.5, 2138.42);
+ new ShapeRef(router, poly68, 68);
+
+ Polygon poly69(4);
+ poly69.ps[0] = Point(406.5, 2281.46);
+ poly69.ps[1] = Point(406.5, 2343.46);
+ poly69.ps[2] = Point(344.5, 2343.46);
+ poly69.ps[3] = Point(344.5, 2281.46);
+ new ShapeRef(router, poly69, 69);
+
+ Polygon poly70(4);
+ poly70.ps[0] = Point(1222.5, 1084.75);
+ poly70.ps[1] = Point(1222.5, 1146.75);
+ poly70.ps[2] = Point(1160.5, 1146.75);
+ poly70.ps[3] = Point(1160.5, 1084.75);
+ new ShapeRef(router, poly70, 70);
+
+ Polygon poly71(4);
+ poly71.ps[0] = Point(247.5, 1045);
+ poly71.ps[1] = Point(247.5, 1107);
+ poly71.ps[2] = Point(185.5, 1107);
+ poly71.ps[3] = Point(185.5, 1045);
+ new ShapeRef(router, poly71, 71);
+
+ Polygon poly72(4);
+ poly72.ps[0] = Point(437.5, 1045);
+ poly72.ps[1] = Point(437.5, 1107);
+ poly72.ps[2] = Point(375.5, 1107);
+ poly72.ps[3] = Point(375.5, 1045);
+ new ShapeRef(router, poly72, 72);
+
+ Polygon poly73(4);
+ poly73.ps[0] = Point(437.5, 1147);
+ poly73.ps[1] = Point(437.5, 1209);
+ poly73.ps[2] = Point(375.5, 1209);
+ poly73.ps[3] = Point(375.5, 1147);
+ new ShapeRef(router, poly73, 73);
+
+ Polygon poly74(4);
+ poly74.ps[0] = Point(247.5, 1147);
+ poly74.ps[1] = Point(247.5, 1209);
+ poly74.ps[2] = Point(185.5, 1209);
+ poly74.ps[3] = Point(185.5, 1147);
+ new ShapeRef(router, poly74, 74);
+
+ Polygon poly75(4);
+ poly75.ps[0] = Point(715.439, 1924.42);
+ poly75.ps[1] = Point(715.439, 1944.42);
+ poly75.ps[2] = Point(683.439, 1944.42);
+ poly75.ps[3] = Point(683.439, 1924.42);
+ new ShapeRef(router, poly75, 75);
+
+ Polygon poly76(4);
+ poly76.ps[0] = Point(282.5, 1872.42);
+ poly76.ps[1] = Point(282.5, 1934.42);
+ poly76.ps[2] = Point(220.5, 1934.42);
+ poly76.ps[3] = Point(220.5, 1872.42);
+ new ShapeRef(router, poly76, 76);
+
+ Polygon poly77(4);
+ poly77.ps[0] = Point(1105.5, 2400.79);
+ poly77.ps[1] = Point(1105.5, 2420.79);
+ poly77.ps[2] = Point(1073.5, 2420.79);
+ poly77.ps[3] = Point(1073.5, 2400.79);
+ new ShapeRef(router, poly77, 77);
+
+ Polygon poly78(4);
+ poly78.ps[0] = Point(715.439, 1862.42);
+ poly78.ps[1] = Point(715.439, 1882.42);
+ poly78.ps[2] = Point(683.439, 1882.42);
+ poly78.ps[3] = Point(683.439, 1862.42);
+ new ShapeRef(router, poly78, 78);
+
+ Polygon poly79(4);
+ poly79.ps[0] = Point(1506.5, 2243.29);
+ poly79.ps[1] = Point(1506.5, 2408.29);
+ poly79.ps[2] = Point(1369.5, 2408.29);
+ poly79.ps[3] = Point(1369.5, 2243.29);
+ new ShapeRef(router, poly79, 79);
+
+ Polygon poly80(4);
+ poly80.ps[0] = Point(1232.5, 1327.42);
+ poly80.ps[1] = Point(1232.5, 1359.42);
+ poly80.ps[2] = Point(1212.5, 1359.42);
+ poly80.ps[3] = Point(1212.5, 1327.42);
+ new ShapeRef(router, poly80, 80);
+#endif
+
+ Polygon poly81(4);
+ poly81.ps[0] = Point(1250.5, 1491.42);
+ poly81.ps[1] = Point(1250.5, 1523.42);
+ poly81.ps[2] = Point(1230.5, 1523.42);
+ poly81.ps[3] = Point(1230.5, 1491.42);
+ new ShapeRef(router, poly81, 81);
+
+ Polygon poly82(4);
+ poly82.ps[0] = Point(1341.5, 1491.42);
+ poly82.ps[1] = Point(1341.5, 1523.42);
+ poly82.ps[2] = Point(1321.5, 1523.42);
+ poly82.ps[3] = Point(1321.5, 1491.42);
+ new ShapeRef(router, poly82, 82);
+
+#ifdef ALL
+ Polygon poly83(4);
+ poly83.ps[0] = Point(570.5, 2030.42);
+ poly83.ps[1] = Point(570.5, 2050.42);
+ poly83.ps[2] = Point(538.5, 2050.42);
+ poly83.ps[3] = Point(538.5, 2030.42);
+ new ShapeRef(router, poly83, 83);
+#endif
+
+ Polygon poly84(4);
+ poly84.ps[0] = Point(1432.5, 1491.42);
+ poly84.ps[1] = Point(1432.5, 1523.42);
+ poly84.ps[2] = Point(1412.5, 1523.42);
+ poly84.ps[3] = Point(1412.5, 1491.42);
+ new ShapeRef(router, poly84, 84);
+
+#ifdef ALL
+ Polygon poly85(4);
+ poly85.ps[0] = Point(980.5, 1538.42);
+ poly85.ps[1] = Point(980.5, 1600.42);
+ poly85.ps[2] = Point(918.5, 1600.42);
+ poly85.ps[3] = Point(918.5, 1538.42);
+ new ShapeRef(router, poly85, 85);
+
+ Polygon poly86(4);
+ poly86.ps[0] = Point(1116.5, 1639.42);
+ poly86.ps[1] = Point(1116.5, 1659.42);
+ poly86.ps[2] = Point(1084.5, 1659.42);
+ poly86.ps[3] = Point(1084.5, 1639.42);
+ new ShapeRef(router, poly86, 86);
+
+ Polygon poly87(4);
+ poly87.ps[0] = Point(1116.5, 1445.42);
+ poly87.ps[1] = Point(1116.5, 1465.42);
+ poly87.ps[2] = Point(1084.5, 1465.42);
+ poly87.ps[3] = Point(1084.5, 1445.42);
+ new ShapeRef(router, poly87, 87);
+#endif
+
+ Polygon poly88(4);
+ poly88.ps[0] = Point(1222.5, 1260.42);
+ poly88.ps[1] = Point(1222.5, 1322.42);
+ poly88.ps[2] = Point(1160.5, 1322.42);
+ poly88.ps[3] = Point(1160.5, 1260.42);
+ new ShapeRef(router, poly88, 88);
+
+#ifdef ALL
+ Polygon poly89(4);
+ poly89.ps[0] = Point(170.5, 2215.42);
+ poly89.ps[1] = Point(170.5, 2247.42);
+ poly89.ps[2] = Point(150.5, 2247.42);
+ poly89.ps[3] = Point(150.5, 2215.42);
+ new ShapeRef(router, poly89, 89);
+
+ Polygon poly90(4);
+ poly90.ps[0] = Point(1323.5, 1047.75);
+ poly90.ps[1] = Point(1323.5, 1079.75);
+ poly90.ps[2] = Point(1303.5, 1079.75);
+ poly90.ps[3] = Point(1303.5, 1047.75);
+ new ShapeRef(router, poly90, 90);
+
+ Polygon poly91(4);
+ poly91.ps[0] = Point(723.5, 680);
+ poly91.ps[1] = Point(723.5, 700);
+ poly91.ps[2] = Point(691.5, 700);
+ poly91.ps[3] = Point(691.5, 680);
+ new ShapeRef(router, poly91, 91);
+
+ Polygon poly92(4);
+ poly92.ps[0] = Point(492.5, 979);
+ poly92.ps[1] = Point(492.5, 999);
+ poly92.ps[2] = Point(460.5, 999);
+ poly92.ps[3] = Point(460.5, 979);
+ new ShapeRef(router, poly92, 92);
+
+ Polygon poly93(4);
+ poly93.ps[0] = Point(1105.5, 2475.79);
+ poly93.ps[1] = Point(1105.5, 2495.79);
+ poly93.ps[2] = Point(1073.5, 2495.79);
+ poly93.ps[3] = Point(1073.5, 2475.79);
+ new ShapeRef(router, poly93, 93);
+
+ Polygon poly94(4);
+ poly94.ps[0] = Point(860.5, 2034.42);
+ poly94.ps[1] = Point(860.5, 2096.42);
+ poly94.ps[2] = Point(798.5, 2096.42);
+ poly94.ps[3] = Point(798.5, 2034.42);
+ new ShapeRef(router, poly94, 94);
+
+ Polygon poly95(4);
+ poly95.ps[0] = Point(1277.5, 1176.75);
+ poly95.ps[1] = Point(1277.5, 1216.75);
+ poly95.ps[2] = Point(1201.5, 1216.75);
+ poly95.ps[3] = Point(1201.5, 1176.75);
+ new ShapeRef(router, poly95, 95);
+
+ Polygon poly96(4);
+ poly96.ps[0] = Point(797.5, 2278.79);
+ poly96.ps[1] = Point(797.5, 2338.79);
+ poly96.ps[2] = Point(741.5, 2338.79);
+ poly96.ps[3] = Point(741.5, 2278.79);
+ new ShapeRef(router, poly96, 96);
+
+ Polygon poly97(4);
+ poly97.ps[0] = Point(241.5, 2211.42);
+ poly97.ps[1] = Point(241.5, 2251.42);
+ poly97.ps[2] = Point(165.5, 2251.42);
+ poly97.ps[3] = Point(165.5, 2211.42);
+ new ShapeRef(router, poly97, 97);
+
+ Polygon poly98(4);
+ poly98.ps[0] = Point(797.5, 2420.79);
+ poly98.ps[1] = Point(797.5, 2480.79);
+ poly98.ps[2] = Point(741.5, 2480.79);
+ poly98.ps[3] = Point(741.5, 2420.79);
+ new ShapeRef(router, poly98, 98);
+
+ Polygon poly99(4);
+ poly99.ps[0] = Point(915.5, 2297.79);
+ poly99.ps[1] = Point(915.5, 2337.79);
+ poly99.ps[2] = Point(839.5, 2337.79);
+ poly99.ps[3] = Point(839.5, 2297.79);
+ new ShapeRef(router, poly99, 99);
+
+ Polygon poly100(4);
+ poly100.ps[0] = Point(1117.5, 2203.79);
+ poly100.ps[1] = Point(1117.5, 2263.79);
+ poly100.ps[2] = Point(1061.5, 2263.79);
+ poly100.ps[3] = Point(1061.5, 2203.79);
+ new ShapeRef(router, poly100, 100);
+
+ Polygon poly101(4);
+ poly101.ps[0] = Point(1117.5, 2278.79);
+ poly101.ps[1] = Point(1117.5, 2338.79);
+ poly101.ps[2] = Point(1061.5, 2338.79);
+ poly101.ps[3] = Point(1061.5, 2278.79);
+ new ShapeRef(router, poly101, 101);
+
+ Polygon poly102(4);
+ poly102.ps[0] = Point(1039.5, 2189.79);
+ poly102.ps[1] = Point(1039.5, 2249.79);
+ poly102.ps[2] = Point(983.5, 2249.79);
+ poly102.ps[3] = Point(983.5, 2189.79);
+ new ShapeRef(router, poly102, 102);
+
+ Polygon poly103(4);
+ poly103.ps[0] = Point(1097.5, 2078.42);
+ poly103.ps[1] = Point(1097.5, 2118.42);
+ poly103.ps[2] = Point(1021.5, 2118.42);
+ poly103.ps[3] = Point(1021.5, 2078.42);
+ new ShapeRef(router, poly103, 103);
+
+ Polygon poly104(4);
+ poly104.ps[0] = Point(733.5, 2099.42);
+ poly104.ps[1] = Point(733.5, 2159.42);
+ poly104.ps[2] = Point(677.5, 2159.42);
+ poly104.ps[3] = Point(677.5, 2099.42);
+ new ShapeRef(router, poly104, 104);
+
+ Polygon poly105(4);
+ poly105.ps[0] = Point(403.5, 2099.42);
+ poly105.ps[1] = Point(403.5, 2159.42);
+ poly105.ps[2] = Point(347.5, 2159.42);
+ poly105.ps[3] = Point(347.5, 2099.42);
+ new ShapeRef(router, poly105, 105);
+
+ Polygon poly106(4);
+ poly106.ps[0] = Point(1386.5, 2099.42);
+ poly106.ps[1] = Point(1386.5, 2159.42);
+ poly106.ps[2] = Point(1330.5, 2159.42);
+ poly106.ps[3] = Point(1330.5, 2099.42);
+ new ShapeRef(router, poly106, 106);
+
+ Polygon poly107(4);
+ poly107.ps[0] = Point(1277.5, 1945.42);
+ poly107.ps[1] = Point(1277.5, 1985.42);
+ poly107.ps[2] = Point(1201.5, 1985.42);
+ poly107.ps[3] = Point(1201.5, 1945.42);
+ new ShapeRef(router, poly107, 107);
+
+ Polygon poly108(4);
+ poly108.ps[0] = Point(1277.5, 1821.42);
+ poly108.ps[1] = Point(1277.5, 1861.42);
+ poly108.ps[2] = Point(1201.5, 1861.42);
+ poly108.ps[3] = Point(1201.5, 1821.42);
+ new ShapeRef(router, poly108, 108);
+
+ Polygon poly109(4);
+ poly109.ps[0] = Point(1277.5, 1697.42);
+ poly109.ps[1] = Point(1277.5, 1737.42);
+ poly109.ps[2] = Point(1201.5, 1737.42);
+ poly109.ps[3] = Point(1201.5, 1697.42);
+ new ShapeRef(router, poly109, 109);
+
+ Polygon poly110(4);
+ poly110.ps[0] = Point(1150.5, 1323.42);
+ poly110.ps[1] = Point(1150.5, 1363.42);
+ poly110.ps[2] = Point(1074.5, 1363.42);
+ poly110.ps[3] = Point(1074.5, 1323.42);
+ new ShapeRef(router, poly110, 110);
+
+ Polygon poly111(4);
+ poly111.ps[0] = Point(1008.5, 1221.42);
+ poly111.ps[1] = Point(1008.5, 1281.42);
+ poly111.ps[2] = Point(952.5, 1281.42);
+ poly111.ps[3] = Point(952.5, 1221.42);
+ new ShapeRef(router, poly111, 111);
+
+ Polygon poly112(4);
+ poly112.ps[0] = Point(1308.5, 1043.75);
+ poly112.ps[1] = Point(1308.5, 1083.75);
+ poly112.ps[2] = Point(1232.5, 1083.75);
+ poly112.ps[3] = Point(1232.5, 1043.75);
+ new ShapeRef(router, poly112, 112);
+
+ Polygon poly113(4);
+ poly113.ps[0] = Point(1150.5, 1043.75);
+ poly113.ps[1] = Point(1150.5, 1083.75);
+ poly113.ps[2] = Point(1074.5, 1083.75);
+ poly113.ps[3] = Point(1074.5, 1043.75);
+ new ShapeRef(router, poly113, 113);
+
+ Polygon poly114(4);
+ poly114.ps[0] = Point(1355.5, 480.5);
+ poly114.ps[1] = Point(1355.5, 540.5);
+ poly114.ps[2] = Point(1299.5, 540.5);
+ poly114.ps[3] = Point(1299.5, 480.5);
+ new ShapeRef(router, poly114, 114);
+
+ Polygon poly115(4);
+ poly115.ps[0] = Point(1277.5, 720);
+ poly115.ps[1] = Point(1277.5, 760);
+ poly115.ps[2] = Point(1201.5, 760);
+ poly115.ps[3] = Point(1201.5, 720);
+ new ShapeRef(router, poly115, 115);
+
+ Polygon poly116(4);
+ poly116.ps[0] = Point(1277.5, 458);
+ poly116.ps[1] = Point(1277.5, 498);
+ poly116.ps[2] = Point(1201.5, 498);
+ poly116.ps[3] = Point(1201.5, 458);
+ new ShapeRef(router, poly116, 116);
+
+ Polygon poly117(4);
+ poly117.ps[0] = Point(946.5, 813);
+ poly117.ps[1] = Point(946.5, 873);
+ poly117.ps[2] = Point(890.5, 873);
+ poly117.ps[3] = Point(890.5, 813);
+ new ShapeRef(router, poly117, 117);
+
+ Polygon poly118(4);
+ poly118.ps[0] = Point(504.5, 707);
+ poly118.ps[1] = Point(504.5, 767);
+ poly118.ps[2] = Point(448.5, 767);
+ poly118.ps[3] = Point(448.5, 707);
+ new ShapeRef(router, poly118, 118);
+
+ Polygon poly119(4);
+ poly119.ps[0] = Point(504.5, 782);
+ poly119.ps[1] = Point(504.5, 842);
+ poly119.ps[2] = Point(448.5, 842);
+ poly119.ps[3] = Point(448.5, 782);
+ new ShapeRef(router, poly119, 119);
+
+ Polygon poly120(4);
+ poly120.ps[0] = Point(826.5, 670);
+ poly120.ps[1] = Point(826.5, 730);
+ poly120.ps[2] = Point(770.5, 730);
+ poly120.ps[3] = Point(770.5, 670);
+ new ShapeRef(router, poly120, 120);
+
+ Polygon poly121(4);
+ poly121.ps[0] = Point(633.5, 720);
+ poly121.ps[1] = Point(633.5, 760);
+ poly121.ps[2] = Point(557.5, 760);
+ poly121.ps[3] = Point(557.5, 720);
+ new ShapeRef(router, poly121, 121);
+
+ Polygon poly122(4);
+ poly122.ps[0] = Point(372.5, 720);
+ poly122.ps[1] = Point(372.5, 760);
+ poly122.ps[2] = Point(296.5, 760);
+ poly122.ps[3] = Point(296.5, 720);
+ new ShapeRef(router, poly122, 122);
+
+ Polygon poly123(4);
+ poly123.ps[0] = Point(735.5, 408);
+ poly123.ps[1] = Point(735.5, 468);
+ poly123.ps[2] = Point(679.5, 468);
+ poly123.ps[3] = Point(679.5, 408);
+ new ShapeRef(router, poly123, 123);
+
+ Polygon poly124(4);
+ poly124.ps[0] = Point(735.5, 483);
+ poly124.ps[1] = Point(735.5, 543);
+ poly124.ps[2] = Point(679.5, 543);
+ poly124.ps[3] = Point(679.5, 483);
+ new ShapeRef(router, poly124, 124);
+
+ Polygon poly125(4);
+ poly125.ps[0] = Point(735.5, 333);
+ poly125.ps[1] = Point(735.5, 393);
+ poly125.ps[2] = Point(679.5, 393);
+ poly125.ps[3] = Point(679.5, 333);
+ new ShapeRef(router, poly125, 125);
+
+ Polygon poly126(4);
+ poly126.ps[0] = Point(795.5, 271);
+ poly126.ps[1] = Point(795.5, 331);
+ poly126.ps[2] = Point(739.5, 331);
+ poly126.ps[3] = Point(739.5, 271);
+ new ShapeRef(router, poly126, 126);
+
+ Polygon poly127(4);
+ poly127.ps[0] = Point(795.5, 169);
+ poly127.ps[1] = Point(795.5, 229);
+ poly127.ps[2] = Point(739.5, 229);
+ poly127.ps[3] = Point(739.5, 169);
+ new ShapeRef(router, poly127, 127);
+
+ Polygon poly128(4);
+ poly128.ps[0] = Point(520.5, 2242.46);
+ poly128.ps[1] = Point(520.5, 2302.46);
+ poly128.ps[2] = Point(464.5, 2302.46);
+ poly128.ps[3] = Point(464.5, 2242.46);
+ new ShapeRef(router, poly128, 128);
+
+ Polygon poly129(4);
+ poly129.ps[0] = Point(1277.5, 1549.42);
+ poly129.ps[1] = Point(1277.5, 1589.42);
+ poly129.ps[2] = Point(1201.5, 1589.42);
+ poly129.ps[3] = Point(1201.5, 1549.42);
+ new ShapeRef(router, poly129, 129);
+
+ Polygon poly130(4);
+ poly130.ps[0] = Point(735.5, 625);
+ poly130.ps[1] = Point(735.5, 685);
+ poly130.ps[2] = Point(679.5, 685);
+ poly130.ps[3] = Point(679.5, 625);
+ new ShapeRef(router, poly130, 130);
+
+ Polygon poly131(4);
+ poly131.ps[0] = Point(504.5, 924);
+ poly131.ps[1] = Point(504.5, 984);
+ poly131.ps[2] = Point(448.5, 984);
+ poly131.ps[3] = Point(448.5, 924);
+ new ShapeRef(router, poly131, 131);
+
+ Polygon poly132(4);
+ poly132.ps[0] = Point(314.5, 1006);
+ poly132.ps[1] = Point(314.5, 1066);
+ poly132.ps[2] = Point(258.5, 1066);
+ poly132.ps[3] = Point(258.5, 1006);
+ new ShapeRef(router, poly132, 132);
+
+ Polygon poly133(4);
+ poly133.ps[0] = Point(314.5, 1108);
+ poly133.ps[1] = Point(314.5, 1168);
+ poly133.ps[2] = Point(258.5, 1168);
+ poly133.ps[3] = Point(258.5, 1108);
+ new ShapeRef(router, poly133, 133);
+
+ Polygon poly134(4);
+ poly134.ps[0] = Point(582.5, 1006);
+ poly134.ps[1] = Point(582.5, 1066);
+ poly134.ps[2] = Point(526.5, 1066);
+ poly134.ps[3] = Point(526.5, 1006);
+ new ShapeRef(router, poly134, 134);
+
+ Polygon poly135(4);
+ poly135.ps[0] = Point(582.5, 1108);
+ poly135.ps[1] = Point(582.5, 1168);
+ poly135.ps[2] = Point(526.5, 1168);
+ poly135.ps[3] = Point(526.5, 1108);
+ new ShapeRef(router, poly135, 135);
+
+ Polygon poly136(4);
+ poly136.ps[0] = Point(727.439, 1944.42);
+ poly136.ps[1] = Point(727.439, 2004.42);
+ poly136.ps[2] = Point(671.439, 2004.42);
+ poly136.ps[3] = Point(671.439, 1944.42);
+ new ShapeRef(router, poly136, 136);
+
+ Polygon poly137(4);
+ poly137.ps[0] = Point(1117.5, 2420.79);
+ poly137.ps[1] = Point(1117.5, 2480.79);
+ poly137.ps[2] = Point(1061.5, 2480.79);
+ poly137.ps[3] = Point(1061.5, 2420.79);
+ new ShapeRef(router, poly137, 137);
+
+ Polygon poly138(4);
+ poly138.ps[0] = Point(727.439, 1802.42);
+ poly138.ps[1] = Point(727.439, 1862.42);
+ poly138.ps[2] = Point(671.439, 1862.42);
+ poly138.ps[3] = Point(671.439, 1802.42);
+ new ShapeRef(router, poly138, 138);
+#endif
+
+ Polygon poly139(4);
+ poly139.ps[0] = Point(1308.5, 1323.42);
+ poly139.ps[1] = Point(1308.5, 1363.42);
+ poly139.ps[2] = Point(1232.5, 1363.42);
+ poly139.ps[3] = Point(1232.5, 1323.42);
+ new ShapeRef(router, poly139, 139);
+
+ Polygon poly140(4);
+ poly140.ps[0] = Point(1326.5, 1487.42);
+ poly140.ps[1] = Point(1326.5, 1527.42);
+ poly140.ps[2] = Point(1250.5, 1527.42);
+ poly140.ps[3] = Point(1250.5, 1487.42);
+ new ShapeRef(router, poly140, 140);
+
+ Polygon poly141(4);
+ poly141.ps[0] = Point(1417.5, 1487.42);
+ poly141.ps[1] = Point(1417.5, 1527.42);
+ poly141.ps[2] = Point(1341.5, 1527.42);
+ poly141.ps[3] = Point(1341.5, 1487.42);
+ new ShapeRef(router, poly141, 141);
+
+#ifdef ALL
+ Polygon poly142(4);
+ poly142.ps[0] = Point(582.5, 1970.42);
+ poly142.ps[1] = Point(582.5, 2030.42);
+ poly142.ps[2] = Point(526.5, 2030.42);
+ poly142.ps[3] = Point(526.5, 1970.42);
+ new ShapeRef(router, poly142, 142);
+
+ Polygon poly143(4);
+ poly143.ps[0] = Point(1508.5, 1487.42);
+ poly143.ps[1] = Point(1508.5, 1527.42);
+ poly143.ps[2] = Point(1432.5, 1527.42);
+ poly143.ps[3] = Point(1432.5, 1487.42);
+ new ShapeRef(router, poly143, 143);
+
+ Polygon poly144(4);
+ poly144.ps[0] = Point(1128.5, 1579.42);
+ poly144.ps[1] = Point(1128.5, 1639.42);
+ poly144.ps[2] = Point(1072.5, 1639.42);
+ poly144.ps[3] = Point(1072.5, 1579.42);
+ new ShapeRef(router, poly144, 144);
+
+ Polygon poly145(4);
+ poly145.ps[0] = Point(1128.5, 1385.42);
+ poly145.ps[1] = Point(1128.5, 1445.42);
+ poly145.ps[2] = Point(1072.5, 1445.42);
+ poly145.ps[3] = Point(1072.5, 1385.42);
+ new ShapeRef(router, poly145, 145);
+
+ Polygon poly146(4);
+ poly146.ps[0] = Point(150.5, 2211.42);
+ poly146.ps[1] = Point(150.5, 2251.42);
+ poly146.ps[2] = Point(74.5, 2251.42);
+ poly146.ps[3] = Point(74.5, 2211.42);
+ new ShapeRef(router, poly146, 146);
+#endif
+
+ Polygon poly147(4);
+ poly147.ps[0] = Point(1399.5, 1043.75);
+ poly147.ps[1] = Point(1399.5, 1083.75);
+ poly147.ps[2] = Point(1323.5, 1083.75);
+ poly147.ps[3] = Point(1323.5, 1043.75);
+ new ShapeRef(router, poly147, 147);
+
+#ifdef ALL
+ Polygon poly148(4);
+ poly148.ps[0] = Point(735.5, 700);
+ poly148.ps[1] = Point(735.5, 760);
+ poly148.ps[2] = Point(679.5, 760);
+ poly148.ps[3] = Point(679.5, 700);
+ new ShapeRef(router, poly148, 148);
+
+ Polygon poly149(4);
+ poly149.ps[0] = Point(504.5, 999);
+ poly149.ps[1] = Point(504.5, 1059);
+ poly149.ps[2] = Point(448.5, 1059);
+ poly149.ps[3] = Point(448.5, 999);
+ new ShapeRef(router, poly149, 149);
+
+ Polygon poly150(4);
+ poly150.ps[0] = Point(1117.5, 2495.79);
+ poly150.ps[1] = Point(1117.5, 2555.79);
+ poly150.ps[2] = Point(1061.5, 2555.79);
+ poly150.ps[3] = Point(1061.5, 2495.79);
+ new ShapeRef(router, poly150, 150);
+
+ Polygon poly151(4);
+ poly151.ps[0] = Point(1482, 966.25);
+ poly151.ps[1] = Point(1482, 1006.25);
+ poly151.ps[2] = Point(1422, 1006.25);
+ poly151.ps[3] = Point(1422, 966.25);
+ new ShapeRef(router, poly151, 151);
+
+ Polygon poly152(4);
+ poly152.ps[0] = Point(1482, 1006.25);
+ poly152.ps[1] = Point(1482, 1046.25);
+ poly152.ps[2] = Point(1422, 1046.25);
+ poly152.ps[3] = Point(1422, 1006.25);
+ new ShapeRef(router, poly152, 152);
+
+ Polygon poly153(4);
+ poly153.ps[0] = Point(1533, 1134.75);
+ poly153.ps[1] = Point(1533, 1194.75);
+ poly153.ps[2] = Point(1493, 1194.75);
+ poly153.ps[3] = Point(1493, 1134.75);
+ new ShapeRef(router, poly153, 153);
+
+ Polygon poly154(4);
+ poly154.ps[0] = Point(1573, 1134.75);
+ poly154.ps[1] = Point(1573, 1194.75);
+ poly154.ps[2] = Point(1533, 1194.75);
+ poly154.ps[3] = Point(1533, 1134.75);
+ new ShapeRef(router, poly154, 154);
+
+ Polygon poly155(4);
+ poly155.ps[0] = Point(1272, 159.5);
+ poly155.ps[1] = Point(1272, 219.5);
+ poly155.ps[2] = Point(1232, 219.5);
+ poly155.ps[3] = Point(1232, 159.5);
+ new ShapeRef(router, poly155, 155);
+
+ Polygon poly156(4);
+ poly156.ps[0] = Point(252.5, 2005.92);
+ poly156.ps[1] = Point(252.5, 2045.92);
+ poly156.ps[2] = Point(192.5, 2045.92);
+ poly156.ps[3] = Point(192.5, 2005.92);
+ new ShapeRef(router, poly156, 156);
+
+ Polygon poly157(4);
+ poly157.ps[0] = Point(252.5, 2045.92);
+ poly157.ps[1] = Point(252.5, 2085.92);
+ poly157.ps[2] = Point(192.5, 2085.92);
+ poly157.ps[3] = Point(192.5, 2045.92);
+ new ShapeRef(router, poly157, 157);
+
+ Polygon poly158(4);
+ poly158.ps[0] = Point(741.5, 1642.92);
+ poly158.ps[1] = Point(741.5, 1682.92);
+ poly158.ps[2] = Point(681.5, 1682.92);
+ poly158.ps[3] = Point(681.5, 1642.92);
+ new ShapeRef(router, poly158, 158);
+
+ Polygon poly159(4);
+ poly159.ps[0] = Point(1458.5, 2243.79);
+ poly159.ps[1] = Point(1458.5, 2303.79);
+ poly159.ps[2] = Point(1418.5, 2303.79);
+ poly159.ps[3] = Point(1418.5, 2243.79);
+ new ShapeRef(router, poly159, 159);
+
+ ConnRef *connRef160 = new ConnRef(router, 160);
+ ConnEnd srcPt160(Point(1191.5, 1211.75), 2);
+ connRef160->setSourceEndpoint(srcPt160);
+ ConnEnd dstPt160(Point(736.5, 1291.42), 15);
+ connRef160->setDestEndpoint(dstPt160);
+ connRef160->setRoutingType((ConnType)2);
+
+ ConnRef *connRef161 = new ConnRef(router, 161);
+ ConnEnd srcPt161(Point(1191.5, 1181.75), 1);
+ connRef161->setSourceEndpoint(srcPt161);
+ ConnEnd dstPt161(Point(1191.5, 1115.75), 15);
+ connRef161->setDestEndpoint(dstPt161);
+ connRef161->setRoutingType((ConnType)2);
+
+ ConnRef *connRef162 = new ConnRef(router, 162);
+ ConnEnd srcPt162(Point(1191.5, 1211.75), 2);
+ connRef162->setSourceEndpoint(srcPt162);
+ ConnEnd dstPt162(Point(1191.5, 1291.42), 15);
+ connRef162->setDestEndpoint(dstPt162);
+ connRef162->setRoutingType((ConnType)2);
+
+ ConnRef *connRef163 = new ConnRef(router, 163);
+ ConnEnd srcPt163(Point(754.5, 2348.79), 4);
+ connRef163->setSourceEndpoint(srcPt163);
+ ConnEnd dstPt163(Point(251.5, 2379.79), 15);
+ connRef163->setDestEndpoint(dstPt163);
+ connRef163->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints163(1);
+ checkpoints163[0] = Point(807.5, 2379.79);
+ connRef163->setRoutingCheckpoints(checkpoints163);
+
+ ConnRef *connRef164 = new ConnRef(router, 164);
+ ConnEnd srcPt164(Point(784.5, 2348.79), 8);
+ connRef164->setSourceEndpoint(srcPt164);
+ ConnEnd dstPt164(Point(829.5, 2379.79), 15);
+ connRef164->setDestEndpoint(dstPt164);
+ connRef164->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints164(1);
+ checkpoints164[0] = Point(731.5, 2379.79);
+ connRef164->setRoutingCheckpoints(checkpoints164);
+
+ ConnRef *connRef165 = new ConnRef(router, 165);
+ ConnEnd srcPt165(Point(251.5, 2246.42), 2);
+ connRef165->setSourceEndpoint(srcPt165);
+ ConnEnd dstPt165(Point(251.5, 2379.79), 15);
+ connRef165->setDestEndpoint(dstPt165);
+ connRef165->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints165(1);
+ checkpoints165[0] = Point(226.5, 2261.42);
+ connRef165->setRoutingCheckpoints(checkpoints165);
+
+ ConnRef *connRef166 = new ConnRef(router, 166);
+ ConnEnd srcPt166(Point(754.5, 2410.79), 4);
+ connRef166->setSourceEndpoint(srcPt166);
+ ConnEnd dstPt166(Point(251.5, 2379.79), 15);
+ connRef166->setDestEndpoint(dstPt166);
+ connRef166->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints166(1);
+ checkpoints166[0] = Point(807.5, 2379.79);
+ connRef166->setRoutingCheckpoints(checkpoints166);
+
+ ConnRef *connRef167 = new ConnRef(router, 167);
+ ConnEnd srcPt167(Point(784.5, 2410.79), 8);
+ connRef167->setSourceEndpoint(srcPt167);
+ ConnEnd dstPt167(Point(829.5, 2379.79), 15);
+ connRef167->setDestEndpoint(dstPt167);
+ connRef167->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints167(1);
+ checkpoints167[0] = Point(731.5, 2379.79);
+ connRef167->setRoutingCheckpoints(checkpoints167);
+
+ ConnRef *connRef168 = new ConnRef(router, 168);
+ ConnEnd srcPt168(Point(251.5, 2379.79), 15);
+ connRef168->setSourceEndpoint(srcPt168);
+ ConnEnd dstPt168(Point(160.5, 2246.42), 2);
+ connRef168->setDestEndpoint(dstPt168);
+ connRef168->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints168(1);
+ checkpoints168[0] = Point(226.5, 2261.42);
+ connRef168->setRoutingCheckpoints(checkpoints168);
+
+ ConnRef *connRef169 = new ConnRef(router, 169);
+ ConnEnd srcPt169(Point(829.5, 2332.79), 2);
+ connRef169->setSourceEndpoint(srcPt169);
+ ConnEnd dstPt169(Point(829.5, 2379.79), 15);
+ connRef169->setDestEndpoint(dstPt169);
+ connRef169->setRoutingType((ConnType)2);
+
+ ConnRef *connRef170 = new ConnRef(router, 170);
+ ConnEnd srcPt170(Point(1074.5, 2273.79), 4);
+ connRef170->setSourceEndpoint(srcPt170);
+ ConnEnd dstPt170(Point(829.5, 2379.79), 15);
+ connRef170->setDestEndpoint(dstPt170);
+ connRef170->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints170(1);
+ checkpoints170[0] = Point(1051.5, 2379.79);
+ connRef170->setRoutingCheckpoints(checkpoints170);
+
+ ConnRef *connRef171 = new ConnRef(router, 171);
+ ConnEnd srcPt171(Point(1074.5, 2348.79), 4);
+ connRef171->setSourceEndpoint(srcPt171);
+ ConnEnd dstPt171(Point(829.5, 2379.79), 15);
+ connRef171->setDestEndpoint(dstPt171);
+ connRef171->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints171(1);
+ checkpoints171[0] = Point(1051.5, 2379.79);
+ connRef171->setRoutingCheckpoints(checkpoints171);
+
+ ConnRef *connRef172 = new ConnRef(router, 172);
+ ConnEnd srcPt172(Point(996.5, 2179.79), 4);
+ connRef172->setSourceEndpoint(srcPt172);
+ ConnEnd dstPt172(Point(829.5, 2169.42), 15);
+ connRef172->setDestEndpoint(dstPt172);
+ connRef172->setRoutingType((ConnType)2);
+
+ ConnRef *connRef173 = new ConnRef(router, 173);
+ ConnEnd srcPt173(Point(1011.5, 2113.42), 2);
+ connRef173->setSourceEndpoint(srcPt173);
+ ConnEnd dstPt173(Point(829.5, 2169.42), 15);
+ connRef173->setDestEndpoint(dstPt173);
+ connRef173->setRoutingType((ConnType)2);
+
+ ConnRef *connRef174 = new ConnRef(router, 174);
+ ConnEnd srcPt174(Point(690.5, 2169.42), 4);
+ connRef174->setSourceEndpoint(srcPt174);
+ ConnEnd dstPt174(Point(523.5, 2169.42), 15);
+ connRef174->setDestEndpoint(dstPt174);
+ connRef174->setRoutingType((ConnType)2);
+
+ ConnRef *connRef175 = new ConnRef(router, 175);
+ ConnEnd srcPt175(Point(690.5, 2169.42), 4);
+ connRef175->setSourceEndpoint(srcPt175);
+ ConnEnd dstPt175(Point(829.5, 2065.42), 15);
+ connRef175->setDestEndpoint(dstPt175);
+ connRef175->setRoutingType((ConnType)2);
+
+ ConnRef *connRef176 = new ConnRef(router, 176);
+ ConnEnd srcPt176(Point(360.5, 2169.42), 4);
+ connRef176->setSourceEndpoint(srcPt176);
+ ConnEnd dstPt176(Point(251.5, 2169.42), 15);
+ connRef176->setDestEndpoint(dstPt176);
+ connRef176->setRoutingType((ConnType)2);
+
+ ConnRef *connRef177 = new ConnRef(router, 177);
+ ConnEnd srcPt177(Point(390.5, 2169.42), 8);
+ connRef177->setSourceEndpoint(srcPt177);
+ ConnEnd dstPt177(Point(523.5, 2169.42), 15);
+ connRef177->setDestEndpoint(dstPt177);
+ connRef177->setRoutingType((ConnType)2);
+
+ ConnRef *connRef178 = new ConnRef(router, 178);
+ ConnEnd srcPt178(Point(360.5, 2169.42), 4);
+ connRef178->setSourceEndpoint(srcPt178);
+ ConnEnd dstPt178(Point(375.5, 2312.46), 15);
+ connRef178->setDestEndpoint(dstPt178);
+ connRef178->setRoutingType((ConnType)2);
+
+ ConnRef *connRef179 = new ConnRef(router, 179);
+ ConnEnd srcPt179(Point(1373.5, 2169.42), 8);
+ connRef179->setSourceEndpoint(srcPt179);
+ ConnEnd dstPt179(Point(1432.5, 2169.42), 15);
+ connRef179->setDestEndpoint(dstPt179);
+ connRef179->setRoutingType((ConnType)2);
+
+ ConnRef *connRef180 = new ConnRef(router, 180);
+ ConnEnd srcPt180(Point(1343.5, 2169.42), 4);
+ connRef180->setSourceEndpoint(srcPt180);
+ ConnEnd dstPt180(Point(1191.5, 2169.42), 15);
+ connRef180->setDestEndpoint(dstPt180);
+ connRef180->setRoutingType((ConnType)2);
+
+ ConnRef *connRef181 = new ConnRef(router, 181);
+ ConnEnd srcPt181(Point(1191.5, 1980.42), 2);
+ connRef181->setSourceEndpoint(srcPt181);
+ ConnEnd dstPt181(Point(1191.5, 2169.42), 15);
+ connRef181->setDestEndpoint(dstPt181);
+ connRef181->setRoutingType((ConnType)2);
+
+ ConnRef *connRef182 = new ConnRef(router, 182);
+ ConnEnd srcPt182(Point(1191.5, 1826.42), 1);
+ connRef182->setSourceEndpoint(srcPt182);
+ ConnEnd dstPt182(Point(1191.5, 1779.42), 15);
+ connRef182->setDestEndpoint(dstPt182);
+ connRef182->setRoutingType((ConnType)2);
+
+ ConnRef *connRef183 = new ConnRef(router, 183);
+ ConnEnd srcPt183(Point(1191.5, 1856.42), 2);
+ connRef183->setSourceEndpoint(srcPt183);
+ ConnEnd dstPt183(Point(1191.5, 1903.42), 15);
+ connRef183->setDestEndpoint(dstPt183);
+ connRef183->setRoutingType((ConnType)2);
+
+ ConnRef *connRef184 = new ConnRef(router, 184);
+ ConnEnd srcPt184(Point(1191.5, 1732.42), 2);
+ connRef184->setSourceEndpoint(srcPt184);
+ ConnEnd dstPt184(Point(1191.5, 1779.42), 15);
+ connRef184->setDestEndpoint(dstPt184);
+ connRef184->setRoutingType((ConnType)2);
+
+ ConnRef *connRef185 = new ConnRef(router, 185);
+ ConnEnd srcPt185(Point(1191.5, 1702.42), 1);
+ connRef185->setSourceEndpoint(srcPt185);
+ ConnEnd dstPt185(Point(1191.5, 1655.42), 15);
+ connRef185->setDestEndpoint(dstPt185);
+ connRef185->setRoutingType((ConnType)2);
+
+ ConnRef *connRef186 = new ConnRef(router, 186);
+ ConnEnd srcPt186(Point(1160.5, 1358.42), 2);
+ connRef186->setSourceEndpoint(srcPt186);
+ ConnEnd dstPt186(Point(1191.5, 1455.42), 15);
+ connRef186->setDestEndpoint(dstPt186);
+ connRef186->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints186(1);
+ checkpoints186[0] = Point(1191.5, 1373.42);
+ connRef186->setRoutingCheckpoints(checkpoints186);
+
+ ConnRef *connRef187 = new ConnRef(router, 187);
+ ConnEnd srcPt187(Point(1160.5, 1328.42), 1);
+ connRef187->setSourceEndpoint(srcPt187);
+ ConnEnd dstPt187(Point(1191.5, 1291.42), 15);
+ connRef187->setDestEndpoint(dstPt187);
+ connRef187->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints187(1);
+ checkpoints187[0] = Point(1191.5, 1313.42);
+ connRef187->setRoutingCheckpoints(checkpoints187);
+
+ ConnRef *connRef188 = new ConnRef(router, 188);
+ ConnEnd srcPt188(Point(965.5, 1291.42), 4);
+ connRef188->setSourceEndpoint(srcPt188);
+ ConnEnd dstPt188(Point(736.5, 1291.42), 15);
+ connRef188->setDestEndpoint(dstPt188);
+ connRef188->setRoutingType((ConnType)2);
+
+ ConnRef *connRef189 = new ConnRef(router, 189);
+ ConnEnd srcPt189(Point(995.5, 1291.42), 8);
+ connRef189->setSourceEndpoint(srcPt189);
+ ConnEnd dstPt189(Point(1191.5, 1291.42), 15);
+ connRef189->setDestEndpoint(dstPt189);
+ connRef189->setRoutingType((ConnType)2);
+
+ ConnRef *connRef190 = new ConnRef(router, 190);
+ ConnEnd srcPt190(Point(1222.5, 1078.75), 2);
+ connRef190->setSourceEndpoint(srcPt190);
+ ConnEnd dstPt190(Point(1191.5, 1115.75), 15);
+ connRef190->setDestEndpoint(dstPt190);
+ connRef190->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints190(1);
+ checkpoints190[0] = Point(1191.5, 1033.75);
+ connRef190->setRoutingCheckpoints(checkpoints190);
+
+ ConnRef *connRef191 = new ConnRef(router, 191);
+ ConnEnd srcPt191(Point(1160.5, 1048.75), 1);
+ connRef191->setSourceEndpoint(srcPt191);
+ ConnEnd dstPt191(Point(1191.5, 883), 15);
+ connRef191->setDestEndpoint(dstPt191);
+ connRef191->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints191(1);
+ checkpoints191[0] = Point(1191.5, 1093.75);
+ connRef191->setRoutingCheckpoints(checkpoints191);
+
+ ConnRef *connRef192 = new ConnRef(router, 192);
+ ConnEnd srcPt192(Point(1312.5, 550.5), 4);
+ connRef192->setSourceEndpoint(srcPt192);
+ ConnEnd dstPt192(Point(1191.5, 584), 15);
+ connRef192->setDestEndpoint(dstPt192);
+ connRef192->setRoutingType((ConnType)2);
+
+ ConnRef *connRef193 = new ConnRef(router, 193);
+ ConnEnd srcPt193(Point(1191.5, 725), 1);
+ connRef193->setSourceEndpoint(srcPt193);
+ ConnEnd dstPt193(Point(1191.5, 584), 15);
+ connRef193->setDestEndpoint(dstPt193);
+ connRef193->setRoutingType((ConnType)2);
+
+ ConnRef *connRef194 = new ConnRef(router, 194);
+ ConnEnd srcPt194(Point(1191.5, 755), 2);
+ connRef194->setSourceEndpoint(srcPt194);
+ ConnEnd dstPt194(Point(1191.5, 883), 15);
+ connRef194->setDestEndpoint(dstPt194);
+ connRef194->setRoutingType((ConnType)2);
+
+ ConnRef *connRef195 = new ConnRef(router, 195);
+ ConnEnd srcPt195(Point(1191.5, 463), 1);
+ connRef195->setSourceEndpoint(srcPt195);
+ ConnEnd dstPt195(Point(1191.5, 280), 15);
+ connRef195->setDestEndpoint(dstPt195);
+ connRef195->setRoutingType((ConnType)2);
+
+ ConnRef *connRef196 = new ConnRef(router, 196);
+ ConnEnd srcPt196(Point(1191.5, 493), 2);
+ connRef196->setSourceEndpoint(srcPt196);
+ ConnEnd dstPt196(Point(1191.5, 584), 15);
+ connRef196->setDestEndpoint(dstPt196);
+ connRef196->setRoutingType((ConnType)2);
+
+ ConnRef *connRef197 = new ConnRef(router, 197);
+ ConnEnd srcPt197(Point(903.5, 883), 4);
+ connRef197->setSourceEndpoint(srcPt197);
+ ConnEnd dstPt197(Point(736.5, 883), 15);
+ connRef197->setDestEndpoint(dstPt197);
+ connRef197->setRoutingType((ConnType)2);
+
+ ConnRef *connRef198 = new ConnRef(router, 198);
+ ConnEnd srcPt198(Point(933.5, 883), 8);
+ connRef198->setSourceEndpoint(srcPt198);
+ ConnEnd dstPt198(Point(1191.5, 883), 15);
+ connRef198->setDestEndpoint(dstPt198);
+ connRef198->setRoutingType((ConnType)2);
+
+ ConnRef *connRef199 = new ConnRef(router, 199);
+ ConnEnd srcPt199(Point(491.5, 777), 8);
+ connRef199->setSourceEndpoint(srcPt199);
+ ConnEnd dstPt199(Point(736.5, 883), 15);
+ connRef199->setDestEndpoint(dstPt199);
+ connRef199->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints199(1);
+ checkpoints199[0] = Point(438.5, 883);
+ connRef199->setRoutingCheckpoints(checkpoints199);
+
+ ConnRef *connRef200 = new ConnRef(router, 200);
+ ConnEnd srcPt200(Point(491.5, 852), 8);
+ connRef200->setSourceEndpoint(srcPt200);
+ ConnEnd dstPt200(Point(736.5, 883), 15);
+ connRef200->setDestEndpoint(dstPt200);
+ connRef200->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints200(1);
+ checkpoints200[0] = Point(438.5, 883);
+ connRef200->setRoutingCheckpoints(checkpoints200);
+
+ ConnRef *connRef201 = new ConnRef(router, 201);
+ ConnEnd srcPt201(Point(783.5, 740), 4);
+ connRef201->setSourceEndpoint(srcPt201);
+ ConnEnd dstPt201(Point(736.5, 883), 15);
+ connRef201->setDestEndpoint(dstPt201);
+ connRef201->setRoutingType((ConnType)2);
+
+ ConnRef *connRef202 = new ConnRef(router, 202);
+ ConnEnd srcPt202(Point(813.5, 740), 8);
+ connRef202->setSourceEndpoint(srcPt202);
+ ConnEnd dstPt202(Point(1191.5, 584), 15);
+ connRef202->setDestEndpoint(dstPt202);
+ connRef202->setRoutingType((ConnType)2);
+
+ ConnRef *connRef203 = new ConnRef(router, 203);
+ ConnEnd srcPt203(Point(643.5, 755), 2);
+ connRef203->setSourceEndpoint(srcPt203);
+ ConnEnd dstPt203(Point(736.5, 883), 15);
+ connRef203->setDestEndpoint(dstPt203);
+ connRef203->setRoutingType((ConnType)2);
+
+ ConnRef *connRef204 = new ConnRef(router, 204);
+ ConnEnd srcPt204(Point(643.5, 725), 1);
+ connRef204->setSourceEndpoint(srcPt204);
+ ConnEnd dstPt204(Point(1191.5, 584), 15);
+ connRef204->setDestEndpoint(dstPt204);
+ connRef204->setRoutingType((ConnType)2);
+
+ ConnRef *connRef205 = new ConnRef(router, 205);
+ ConnEnd srcPt205(Point(286.5, 725), 1);
+ connRef205->setSourceEndpoint(srcPt205);
+ ConnEnd dstPt205(Point(286.5, 584), 15);
+ connRef205->setDestEndpoint(dstPt205);
+ connRef205->setRoutingType((ConnType)2);
+
+ ConnRef *connRef206 = new ConnRef(router, 206);
+ ConnEnd srcPt206(Point(286.5, 755), 2);
+ connRef206->setSourceEndpoint(srcPt206);
+ ConnEnd dstPt206(Point(286.5, 883), 15);
+ connRef206->setDestEndpoint(dstPt206);
+ connRef206->setRoutingType((ConnType)2);
+
+ ConnRef *connRef207 = new ConnRef(router, 207);
+ ConnEnd srcPt207(Point(722.5, 478), 8);
+ connRef207->setSourceEndpoint(srcPt207);
+ ConnEnd dstPt207(Point(1191.5, 584), 15);
+ connRef207->setDestEndpoint(dstPt207);
+ connRef207->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints207(1);
+ checkpoints207[0] = Point(669.5, 584);
+ connRef207->setRoutingCheckpoints(checkpoints207);
+
+ ConnRef *connRef208 = new ConnRef(router, 208);
+ ConnEnd srcPt208(Point(722.5, 553), 8);
+ connRef208->setSourceEndpoint(srcPt208);
+ ConnEnd dstPt208(Point(1191.5, 584), 15);
+ connRef208->setDestEndpoint(dstPt208);
+ connRef208->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints208(1);
+ checkpoints208[0] = Point(669.5, 584);
+ connRef208->setRoutingCheckpoints(checkpoints208);
+
+ ConnRef *connRef209 = new ConnRef(router, 209);
+ ConnEnd srcPt209(Point(692.5, 403), 4);
+ connRef209->setSourceEndpoint(srcPt209);
+ ConnEnd dstPt209(Point(286.5, 584), 15);
+ connRef209->setDestEndpoint(dstPt209);
+ connRef209->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints209(1);
+ checkpoints209[0] = Point(745.5, 584);
+ connRef209->setRoutingCheckpoints(checkpoints209);
+
+ ConnRef *connRef210 = new ConnRef(router, 210);
+ ConnEnd srcPt210(Point(752.5, 341), 4);
+ connRef210->setSourceEndpoint(srcPt210);
+ ConnEnd dstPt210(Point(286.5, 584), 15);
+ connRef210->setDestEndpoint(dstPt210);
+ connRef210->setRoutingType((ConnType)2);
+
+ ConnRef *connRef211 = new ConnRef(router, 211);
+ ConnEnd srcPt211(Point(752.5, 239), 4);
+ connRef211->setSourceEndpoint(srcPt211);
+ ConnEnd dstPt211(Point(286.5, 584), 15);
+ connRef211->setDestEndpoint(dstPt211);
+ connRef211->setRoutingType((ConnType)2);
+
+ ConnRef *connRef212 = new ConnRef(router, 212);
+ ConnEnd srcPt212(Point(507.5, 2312.46), 8);
+ connRef212->setSourceEndpoint(srcPt212);
+ ConnEnd dstPt212(Point(674.5, 2312.46), 15);
+ connRef212->setDestEndpoint(dstPt212);
+ connRef212->setRoutingType((ConnType)2);
+
+ ConnRef *connRef213 = new ConnRef(router, 213);
+ ConnEnd srcPt213(Point(1191.5, 1584.42), 2);
+ connRef213->setSourceEndpoint(srcPt213);
+ ConnEnd dstPt213(Point(1191.5, 1655.42), 15);
+ connRef213->setDestEndpoint(dstPt213);
+ connRef213->setRoutingType((ConnType)2);
+
+ ConnRef *connRef214 = new ConnRef(router, 214);
+ ConnEnd srcPt214(Point(1191.5, 1554.42), 1);
+ connRef214->setSourceEndpoint(srcPt214);
+ ConnEnd dstPt214(Point(1191.5, 1455.42), 15);
+ connRef214->setDestEndpoint(dstPt214);
+ connRef214->setRoutingType((ConnType)2);
+
+ ConnRef *connRef215 = new ConnRef(router, 215);
+ ConnEnd srcPt215(Point(722.5, 615), 8);
+ connRef215->setSourceEndpoint(srcPt215);
+ ConnEnd dstPt215(Point(1191.5, 584), 15);
+ connRef215->setDestEndpoint(dstPt215);
+ connRef215->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints215(1);
+ checkpoints215[0] = Point(669.5, 584);
+ connRef215->setRoutingCheckpoints(checkpoints215);
+
+ ConnRef *connRef216 = new ConnRef(router, 216);
+ ConnEnd srcPt216(Point(491.5, 914), 8);
+ connRef216->setSourceEndpoint(srcPt216);
+ ConnEnd dstPt216(Point(736.5, 883), 15);
+ connRef216->setDestEndpoint(dstPt216);
+ connRef216->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints216(1);
+ checkpoints216[0] = Point(438.5, 883);
+ connRef216->setRoutingCheckpoints(checkpoints216);
+
+ ConnRef *connRef217 = new ConnRef(router, 217);
+ ConnEnd srcPt217(Point(301.5, 1076), 8);
+ connRef217->setSourceEndpoint(srcPt217);
+ ConnEnd dstPt217(Point(406.5, 1076), 15);
+ connRef217->setDestEndpoint(dstPt217);
+ connRef217->setRoutingType((ConnType)2);
+
+ ConnRef *connRef218 = new ConnRef(router, 218);
+ ConnEnd srcPt218(Point(301.5, 1178), 8);
+ connRef218->setSourceEndpoint(srcPt218);
+ ConnEnd dstPt218(Point(406.5, 1178), 15);
+ connRef218->setDestEndpoint(dstPt218);
+ connRef218->setRoutingType((ConnType)2);
+
+ ConnRef *connRef219 = new ConnRef(router, 219);
+ ConnEnd srcPt219(Point(569.5, 1076), 8);
+ connRef219->setSourceEndpoint(srcPt219);
+ ConnEnd dstPt219(Point(736.5, 883), 15);
+ connRef219->setDestEndpoint(dstPt219);
+ connRef219->setRoutingType((ConnType)2);
+
+ ConnRef *connRef220 = new ConnRef(router, 220);
+ ConnEnd srcPt220(Point(569.5, 1178), 8);
+ connRef220->setSourceEndpoint(srcPt220);
+ ConnEnd dstPt220(Point(736.5, 883), 15);
+ connRef220->setDestEndpoint(dstPt220);
+ connRef220->setRoutingType((ConnType)2);
+
+ ConnRef *connRef221 = new ConnRef(router, 221);
+ ConnEnd srcPt221(Point(1401.5, 550.5), 15);
+ connRef221->setSourceEndpoint(srcPt221);
+ ConnEnd dstPt221(Point(1342.5, 550.5), 8);
+ connRef221->setDestEndpoint(dstPt221);
+ connRef221->setRoutingType((ConnType)2);
+
+ ConnRef *connRef222 = new ConnRef(router, 222);
+ ConnEnd srcPt222(Point(286.5, 584), 15);
+ connRef222->setSourceEndpoint(srcPt222);
+ ConnEnd dstPt222(Point(692.5, 615), 4);
+ connRef222->setDestEndpoint(dstPt222);
+ connRef222->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints222(1);
+ checkpoints222[0] = Point(745.5, 584);
+ connRef222->setRoutingCheckpoints(checkpoints222);
+
+ ConnRef *connRef223 = new ConnRef(router, 223);
+ ConnEnd srcPt223(Point(286.5, 584), 15);
+ connRef223->setSourceEndpoint(srcPt223);
+ ConnEnd dstPt223(Point(692.5, 690), 4);
+ connRef223->setDestEndpoint(dstPt223);
+ connRef223->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints223(1);
+ checkpoints223[0] = Point(745.5, 584);
+ connRef223->setRoutingCheckpoints(checkpoints223);
+
+ ConnRef *connRef224 = new ConnRef(router, 224);
+ ConnEnd srcPt224(Point(286.5, 883), 15);
+ connRef224->setSourceEndpoint(srcPt224);
+ ConnEnd dstPt224(Point(461.5, 914), 4);
+ connRef224->setDestEndpoint(dstPt224);
+ connRef224->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints224(1);
+ checkpoints224[0] = Point(514.5, 883);
+ connRef224->setRoutingCheckpoints(checkpoints224);
+
+ ConnRef *connRef225 = new ConnRef(router, 225);
+ ConnEnd srcPt225(Point(461.5, 989), 4);
+ connRef225->setSourceEndpoint(srcPt225);
+ ConnEnd dstPt225(Point(286.5, 883), 15);
+ connRef225->setDestEndpoint(dstPt225);
+ connRef225->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints225(1);
+ checkpoints225[0] = Point(514.5, 883);
+ connRef225->setRoutingCheckpoints(checkpoints225);
+
+ ConnRef *connRef226 = new ConnRef(router, 226);
+ ConnEnd srcPt226(Point(491.5, 989), 8);
+ connRef226->setSourceEndpoint(srcPt226);
+ ConnEnd dstPt226(Point(736.5, 883), 15);
+ connRef226->setDestEndpoint(dstPt226);
+ connRef226->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints226(1);
+ checkpoints226[0] = Point(438.5, 883);
+ connRef226->setRoutingCheckpoints(checkpoints226);
+
+ ConnRef *connRef227 = new ConnRef(router, 227);
+ ConnEnd srcPt227(Point(1191.5, 883), 15);
+ connRef227->setSourceEndpoint(srcPt227);
+ ConnEnd dstPt227(Point(1313.5, 1048.75), 1);
+ connRef227->setDestEndpoint(dstPt227);
+ connRef227->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints227(1);
+ checkpoints227[0] = Point(1191.5, 1093.75);
+ connRef227->setRoutingCheckpoints(checkpoints227);
+
+ ConnRef *connRef228 = new ConnRef(router, 228);
+ ConnEnd srcPt228(Point(714.439, 1872.42), 8);
+ connRef228->setSourceEndpoint(srcPt228);
+ ConnEnd dstPt228(Point(1191.5, 1903.42), 15);
+ connRef228->setDestEndpoint(dstPt228);
+ connRef228->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints228(1);
+ checkpoints228[0] = Point(737.439, 1903.42);
+ connRef228->setRoutingCheckpoints(checkpoints228);
+
+ ConnRef *connRef229 = new ConnRef(router, 229);
+ ConnEnd srcPt229(Point(1240.5, 1522.42), 2);
+ connRef229->setSourceEndpoint(srcPt229);
+ ConnEnd dstPt229(Point(1191.5, 1655.42), 15);
+ connRef229->setDestEndpoint(dstPt229);
+ connRef229->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints229(1);
+ checkpoints229[0] = Point(1265.5, 1537.42);
+ connRef229->setRoutingCheckpoints(checkpoints229);
+
+ ConnRef *connRef230 = new ConnRef(router, 230);
+ ConnEnd srcPt230(Point(1331.5, 1522.42), 2);
+ connRef230->setSourceEndpoint(srcPt230);
+ ConnEnd dstPt230(Point(1191.5, 1655.42), 15);
+ connRef230->setDestEndpoint(dstPt230);
+ connRef230->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints230(1);
+ checkpoints230[0] = Point(1265.5, 1537.42);
+ connRef230->setRoutingCheckpoints(checkpoints230);
+
+ ConnRef *connRef231 = new ConnRef(router, 231);
+ ConnEnd srcPt231(Point(1422.5, 1522.42), 2);
+ connRef231->setSourceEndpoint(srcPt231);
+ ConnEnd dstPt231(Point(1191.5, 1655.42), 15);
+ connRef231->setDestEndpoint(dstPt231);
+ connRef231->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints231(1);
+ checkpoints231[0] = Point(1265.5, 1537.42);
+ connRef231->setRoutingCheckpoints(checkpoints231);
+
+ ConnRef *connRef232 = new ConnRef(router, 232);
+ ConnEnd srcPt232(Point(1222.5, 1358.42), 2);
+ connRef232->setSourceEndpoint(srcPt232);
+ ConnEnd dstPt232(Point(1191.5, 1455.42), 15);
+ connRef232->setDestEndpoint(dstPt232);
+ connRef232->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints232(1);
+ checkpoints232[0] = Point(1191.5, 1373.42);
+ connRef232->setRoutingCheckpoints(checkpoints232);
+
+ ConnRef *connRef233 = new ConnRef(router, 233);
+ ConnEnd srcPt233(Point(1115.5, 1455.42), 8);
+ connRef233->setSourceEndpoint(srcPt233);
+ ConnEnd dstPt233(Point(1191.5, 1455.42), 15);
+ connRef233->setDestEndpoint(dstPt233);
+ connRef233->setRoutingType((ConnType)2);
+
+ ConnRef *connRef234 = new ConnRef(router, 234);
+ ConnEnd srcPt234(Point(1104.5, 2273.79), 8);
+ connRef234->setSourceEndpoint(srcPt234);
+ ConnEnd dstPt234(Point(1327.5, 2379.79), 15);
+ connRef234->setDestEndpoint(dstPt234);
+ connRef234->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints234(1);
+ checkpoints234[0] = Point(1127.5, 2379.79);
+ connRef234->setRoutingCheckpoints(checkpoints234);
+
+ ConnRef *connRef235 = new ConnRef(router, 235);
+ ConnEnd srcPt235(Point(1104.5, 2348.79), 8);
+ connRef235->setSourceEndpoint(srcPt235);
+ ConnEnd dstPt235(Point(1327.5, 2379.79), 15);
+ connRef235->setDestEndpoint(dstPt235);
+ connRef235->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints235(1);
+ checkpoints235[0] = Point(1127.5, 2379.79);
+ connRef235->setRoutingCheckpoints(checkpoints235);
+
+ ConnRef *connRef236 = new ConnRef(router, 236);
+ ConnEnd srcPt236(Point(1104.5, 2410.79), 8);
+ connRef236->setSourceEndpoint(srcPt236);
+ ConnEnd dstPt236(Point(1327.5, 2379.79), 15);
+ connRef236->setDestEndpoint(dstPt236);
+ connRef236->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints236(1);
+ checkpoints236[0] = Point(1127.5, 2379.79);
+ connRef236->setRoutingCheckpoints(checkpoints236);
+
+ ConnRef *connRef237 = new ConnRef(router, 237);
+ ConnEnd srcPt237(Point(1104.5, 2485.79), 8);
+ connRef237->setSourceEndpoint(srcPt237);
+ ConnEnd dstPt237(Point(1327.5, 2379.79), 15);
+ connRef237->setDestEndpoint(dstPt237);
+ connRef237->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints237(1);
+ checkpoints237[0] = Point(1127.5, 2379.79);
+ connRef237->setRoutingCheckpoints(checkpoints237);
+
+ ConnRef *connRef238 = new ConnRef(router, 238);
+ ConnEnd srcPt238(Point(569.5, 2040.42), 8);
+ connRef238->setSourceEndpoint(srcPt238);
+ ConnEnd dstPt238(Point(1191.5, 2169.42), 15);
+ connRef238->setDestEndpoint(dstPt238);
+ connRef238->setRoutingType((ConnType)2);
+
+ ConnRef *connRef239 = new ConnRef(router, 239);
+ ConnEnd srcPt239(Point(829.5, 2169.42), 15);
+ connRef239->setSourceEndpoint(srcPt239);
+ ConnEnd dstPt239(Point(829.5, 2302.79), 1);
+ connRef239->setDestEndpoint(dstPt239);
+ connRef239->setRoutingType((ConnType)2);
+
+ ConnRef *connRef240 = new ConnRef(router, 240);
+ ConnEnd srcPt240(Point(539.5, 2040.42), 4);
+ connRef240->setSourceEndpoint(srcPt240);
+ ConnEnd dstPt240(Point(251.5, 2169.42), 15);
+ connRef240->setDestEndpoint(dstPt240);
+ connRef240->setRoutingType((ConnType)2);
+
+ ConnRef *connRef241 = new ConnRef(router, 241);
+ ConnEnd srcPt241(Point(1074.5, 2410.79), 4);
+ connRef241->setSourceEndpoint(srcPt241);
+ ConnEnd dstPt241(Point(829.5, 2379.79), 15);
+ connRef241->setDestEndpoint(dstPt241);
+ connRef241->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints241(1);
+ checkpoints241[0] = Point(1051.5, 2379.79);
+ connRef241->setRoutingCheckpoints(checkpoints241);
+
+ ConnRef *connRef242 = new ConnRef(router, 242);
+ ConnEnd srcPt242(Point(1074.5, 2485.79), 4);
+ connRef242->setSourceEndpoint(srcPt242);
+ ConnEnd dstPt242(Point(829.5, 2379.79), 15);
+ connRef242->setDestEndpoint(dstPt242);
+ connRef242->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints242(1);
+ checkpoints242[0] = Point(1051.5, 2379.79);
+ connRef242->setRoutingCheckpoints(checkpoints242);
+
+ ConnRef *connRef243 = new ConnRef(router, 243);
+ ConnEnd srcPt243(Point(477.5, 2312.46), 4);
+ connRef243->setSourceEndpoint(srcPt243);
+ ConnEnd dstPt243(Point(375.5, 2312.46), 15);
+ connRef243->setDestEndpoint(dstPt243);
+ connRef243->setRoutingType((ConnType)2);
+
+ ConnRef *connRef244 = new ConnRef(router, 244);
+ ConnEnd srcPt244(Point(1191.5, 1115.75), 15);
+ connRef244->setSourceEndpoint(srcPt244);
+ ConnEnd dstPt244(Point(1160.5, 1078.75), 2);
+ connRef244->setDestEndpoint(dstPt244);
+ connRef244->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints244(1);
+ checkpoints244[0] = Point(1191.5, 1033.75);
+ connRef244->setRoutingCheckpoints(checkpoints244);
+
+ ConnRef *connRef245 = new ConnRef(router, 245);
+ ConnEnd srcPt245(Point(216.5, 1076), 15);
+ connRef245->setSourceEndpoint(srcPt245);
+ ConnEnd dstPt245(Point(271.5, 1076), 4);
+ connRef245->setDestEndpoint(dstPt245);
+ connRef245->setRoutingType((ConnType)2);
+
+ ConnRef *connRef246 = new ConnRef(router, 246);
+ ConnEnd srcPt246(Point(406.5, 1076), 15);
+ connRef246->setSourceEndpoint(srcPt246);
+ ConnEnd dstPt246(Point(539.5, 1076), 4);
+ connRef246->setDestEndpoint(dstPt246);
+ connRef246->setRoutingType((ConnType)2);
+
+ ConnRef *connRef247 = new ConnRef(router, 247);
+ ConnEnd srcPt247(Point(406.5, 1178), 15);
+ connRef247->setSourceEndpoint(srcPt247);
+ ConnEnd dstPt247(Point(539.5, 1178), 4);
+ connRef247->setDestEndpoint(dstPt247);
+ connRef247->setRoutingType((ConnType)2);
+
+ ConnRef *connRef248 = new ConnRef(router, 248);
+ ConnEnd srcPt248(Point(216.5, 1178), 15);
+ connRef248->setSourceEndpoint(srcPt248);
+ ConnEnd dstPt248(Point(271.5, 1178), 4);
+ connRef248->setDestEndpoint(dstPt248);
+ connRef248->setRoutingType((ConnType)2);
+
+ ConnRef *connRef249 = new ConnRef(router, 249);
+ ConnEnd srcPt249(Point(714.439, 1934.42), 8);
+ connRef249->setSourceEndpoint(srcPt249);
+ ConnEnd dstPt249(Point(1191.5, 1903.42), 15);
+ connRef249->setDestEndpoint(dstPt249);
+ connRef249->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints249(1);
+ checkpoints249[0] = Point(737.439, 1903.42);
+ connRef249->setRoutingCheckpoints(checkpoints249);
+
+ ConnRef *connRef250 = new ConnRef(router, 250);
+ ConnEnd srcPt250(Point(251.5, 1903.42), 15);
+ connRef250->setSourceEndpoint(srcPt250);
+ ConnEnd dstPt250(Point(684.439, 1934.42), 4);
+ connRef250->setDestEndpoint(dstPt250);
+ connRef250->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints250(1);
+ checkpoints250[0] = Point(661.439, 1903.42);
+ connRef250->setRoutingCheckpoints(checkpoints250);
+
+ ConnRef *connRef251 = new ConnRef(router, 251);
+ ConnEnd srcPt251(Point(251.5, 1903.42), 15);
+ connRef251->setSourceEndpoint(srcPt251);
+ ConnEnd dstPt251(Point(684.439, 1872.42), 4);
+ connRef251->setDestEndpoint(dstPt251);
+ connRef251->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints251(1);
+ checkpoints251[0] = Point(661.439, 1903.42);
+ connRef251->setRoutingCheckpoints(checkpoints251);
+
+ ConnRef *connRef252 = new ConnRef(router, 252);
+ ConnEnd srcPt252(Point(1222.5, 1328.42), 1);
+ connRef252->setSourceEndpoint(srcPt252);
+ ConnEnd dstPt252(Point(1191.5, 1291.42), 15);
+ connRef252->setDestEndpoint(dstPt252);
+ connRef252->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints252(1);
+ checkpoints252[0] = Point(1191.5, 1313.42);
+ connRef252->setRoutingCheckpoints(checkpoints252);
+
+ ConnRef *connRef253 = new ConnRef(router, 253);
+ ConnEnd srcPt253(Point(1085.5, 1649.42), 4);
+ connRef253->setSourceEndpoint(srcPt253);
+ ConnEnd dstPt253(Point(949.5, 1569.42), 15);
+ connRef253->setDestEndpoint(dstPt253);
+ connRef253->setRoutingType((ConnType)2);
+
+ ConnRef *connRef254 = new ConnRef(router, 254);
+ ConnEnd srcPt254(Point(1115.5, 1649.42), 8);
+ connRef254->setSourceEndpoint(srcPt254);
+ ConnEnd dstPt254(Point(1191.5, 1655.42), 15);
+ connRef254->setDestEndpoint(dstPt254);
+ connRef254->setRoutingType((ConnType)2);
+
+ ConnRef *connRef255 = new ConnRef(router, 255);
+ ConnEnd srcPt255(Point(1085.5, 1455.42), 4);
+ connRef255->setSourceEndpoint(srcPt255);
+ ConnEnd dstPt255(Point(949.5, 1569.42), 15);
+ connRef255->setDestEndpoint(dstPt255);
+ connRef255->setRoutingType((ConnType)2);
+#endif
+
+ ConnRef *connRef256 = new ConnRef(router, 256);
+ ConnEnd srcPt256(Point(1191.5, 1291.42), 15);
+ connRef256->setSourceEndpoint(srcPt256);
+ ConnEnd dstPt256(Point(1240.5, 1492.42), 1);
+ connRef256->setDestEndpoint(dstPt256);
+ connRef256->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints256(1);
+ checkpoints256[0] = Point(1331.5, 1477.42);
+ connRef256->setRoutingCheckpoints(checkpoints256);
+
+ ConnRef *connRef257 = new ConnRef(router, 257);
+ ConnEnd srcPt257(Point(1191.5, 1291.42), 15);
+ connRef257->setSourceEndpoint(srcPt257);
+ ConnEnd dstPt257(Point(1331.5, 1492.42), 1);
+ connRef257->setDestEndpoint(dstPt257);
+ connRef257->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints257(1);
+ checkpoints257[0] = Point(1331.5, 1477.42);
+ connRef257->setRoutingCheckpoints(checkpoints256);
+
+ ConnRef *connRef258 = new ConnRef(router, 258);
+ ConnEnd srcPt258(Point(1191.5, 1291.42), 15);
+ connRef258->setSourceEndpoint(srcPt258);
+ ConnEnd dstPt258(Point(1422.5, 1492.42), 1);
+ connRef258->setDestEndpoint(dstPt258);
+ connRef258->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints258(1);
+ checkpoints258[0] = Point(1331.5, 1477.42);
+ connRef258->setRoutingCheckpoints(checkpoints256);
+
+#ifdef ALL
+ ConnRef *connRef259 = new ConnRef(router, 259);
+ ConnEnd srcPt259(Point(160.5, 2216.42), 1);
+ connRef259->setSourceEndpoint(srcPt259);
+ ConnEnd dstPt259(Point(251.5, 2169.42), 15);
+ connRef259->setDestEndpoint(dstPt259);
+ connRef259->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints259(1);
+ checkpoints259[0] = Point(226.5, 2201.42);
+ connRef259->setRoutingCheckpoints(checkpoints259);
+
+ ConnRef *connRef260 = new ConnRef(router, 260);
+ ConnEnd srcPt260(Point(1313.5, 1078.75), 2);
+ connRef260->setSourceEndpoint(srcPt260);
+ ConnEnd dstPt260(Point(1191.5, 1115.75), 15);
+ connRef260->setDestEndpoint(dstPt260);
+ connRef260->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints260(1);
+ checkpoints260[0] = Point(1191.5, 1033.75);
+ connRef260->setRoutingCheckpoints(checkpoints260);
+
+ ConnRef *connRef261 = new ConnRef(router, 261);
+ ConnEnd srcPt261(Point(722.5, 690), 8);
+ connRef261->setSourceEndpoint(srcPt261);
+ ConnEnd dstPt261(Point(1191.5, 584), 15);
+ connRef261->setDestEndpoint(dstPt261);
+ connRef261->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints261(1);
+ checkpoints261[0] = Point(669.5, 584);
+ connRef261->setRoutingCheckpoints(checkpoints261);
+
+ ConnRef *connRef262 = new ConnRef(router, 262);
+ ConnEnd srcPt262(Point(829.5, 2065.42), 15);
+ connRef262->setSourceEndpoint(srcPt262);
+ ConnEnd dstPt262(Point(1026.5, 2179.79), 8);
+ connRef262->setDestEndpoint(dstPt262);
+ connRef262->setRoutingType((ConnType)2);
+
+ ConnRef *connRef263 = new ConnRef(router, 263);
+ ConnEnd srcPt263(Point(829.5, 2065.42), 15);
+ connRef263->setSourceEndpoint(srcPt263);
+ ConnEnd dstPt263(Point(1011.5, 2083.42), 1);
+ connRef263->setDestEndpoint(dstPt263);
+ connRef263->setRoutingType((ConnType)2);
+
+ ConnRef *connRef264 = new ConnRef(router, 264);
+ ConnEnd srcPt264(Point(1249.5, 1196.75), 4);
+ connRef264->setSourceEndpoint(srcPt264);
+ ConnEnd dstPt264(Point(1191.5, 1196.75), 8);
+ connRef264->setDestEndpoint(dstPt264);
+ connRef264->setRoutingType((ConnType)2);
+
+ ConnRef *connRef265 = new ConnRef(router, 265);
+ ConnEnd srcPt265(Point(769.5, 2298.79), 2);
+ connRef265->setSourceEndpoint(srcPt265);
+ ConnEnd dstPt265(Point(769.5, 2348.79), 1);
+ connRef265->setDestEndpoint(dstPt265);
+ connRef265->setRoutingType((ConnType)2);
+
+ ConnRef *connRef266 = new ConnRef(router, 266);
+ ConnEnd srcPt266(Point(193.5, 2231.42), 8);
+ connRef266->setSourceEndpoint(srcPt266);
+ ConnEnd dstPt266(Point(251.5, 2231.42), 4);
+ connRef266->setDestEndpoint(dstPt266);
+ connRef266->setRoutingType((ConnType)2);
+
+ ConnRef *connRef267 = new ConnRef(router, 267);
+ ConnEnd srcPt267(Point(769.5, 2460.79), 1);
+ connRef267->setSourceEndpoint(srcPt267);
+ ConnEnd dstPt267(Point(769.5, 2410.79), 2);
+ connRef267->setDestEndpoint(dstPt267);
+ connRef267->setRoutingType((ConnType)2);
+
+ ConnRef *connRef268 = new ConnRef(router, 268);
+ ConnEnd srcPt268(Point(887.5, 2317.79), 4);
+ connRef268->setSourceEndpoint(srcPt268);
+ ConnEnd dstPt268(Point(829.5, 2317.79), 8);
+ connRef268->setDestEndpoint(dstPt268);
+ connRef268->setRoutingType((ConnType)2);
+
+ ConnRef *connRef269 = new ConnRef(router, 269);
+ ConnEnd srcPt269(Point(1089.5, 2223.79), 2);
+ connRef269->setSourceEndpoint(srcPt269);
+ ConnEnd dstPt269(Point(1089.5, 2273.79), 1);
+ connRef269->setDestEndpoint(dstPt269);
+ connRef269->setRoutingType((ConnType)2);
+
+ ConnRef *connRef270 = new ConnRef(router, 270);
+ ConnEnd srcPt270(Point(1089.5, 2298.79), 2);
+ connRef270->setSourceEndpoint(srcPt270);
+ ConnEnd dstPt270(Point(1089.5, 2348.79), 1);
+ connRef270->setDestEndpoint(dstPt270);
+ connRef270->setRoutingType((ConnType)2);
+
+ ConnRef *connRef271 = new ConnRef(router, 271);
+ ConnEnd srcPt271(Point(1011.5, 2229.79), 1);
+ connRef271->setSourceEndpoint(srcPt271);
+ ConnEnd dstPt271(Point(1011.5, 2179.79), 2);
+ connRef271->setDestEndpoint(dstPt271);
+ connRef271->setRoutingType((ConnType)2);
+
+ ConnRef *connRef272 = new ConnRef(router, 272);
+ ConnEnd srcPt272(Point(1069.5, 2098.42), 4);
+ connRef272->setSourceEndpoint(srcPt272);
+ ConnEnd dstPt272(Point(1011.5, 2098.42), 8);
+ connRef272->setDestEndpoint(dstPt272);
+ connRef272->setRoutingType((ConnType)2);
+
+ ConnRef *connRef273 = new ConnRef(router, 273);
+ ConnEnd srcPt273(Point(705.5, 2119.42), 2);
+ connRef273->setSourceEndpoint(srcPt273);
+ ConnEnd dstPt273(Point(705.5, 2169.42), 1);
+ connRef273->setDestEndpoint(dstPt273);
+ connRef273->setRoutingType((ConnType)2);
+
+ ConnRef *connRef274 = new ConnRef(router, 274);
+ ConnEnd srcPt274(Point(375.5, 2119.42), 2);
+ connRef274->setSourceEndpoint(srcPt274);
+ ConnEnd dstPt274(Point(375.5, 2169.42), 1);
+ connRef274->setDestEndpoint(dstPt274);
+ connRef274->setRoutingType((ConnType)2);
+
+ ConnRef *connRef275 = new ConnRef(router, 275);
+ ConnEnd srcPt275(Point(1358.5, 2119.42), 2);
+ connRef275->setSourceEndpoint(srcPt275);
+ ConnEnd dstPt275(Point(1358.5, 2169.42), 1);
+ connRef275->setDestEndpoint(dstPt275);
+ connRef275->setRoutingType((ConnType)2);
+
+ ConnRef *connRef276 = new ConnRef(router, 276);
+ ConnEnd srcPt276(Point(1249.5, 1965.42), 4);
+ connRef276->setSourceEndpoint(srcPt276);
+ ConnEnd dstPt276(Point(1191.5, 1965.42), 8);
+ connRef276->setDestEndpoint(dstPt276);
+ connRef276->setRoutingType((ConnType)2);
+
+ ConnRef *connRef277 = new ConnRef(router, 277);
+ ConnEnd srcPt277(Point(1249.5, 1841.42), 4);
+ connRef277->setSourceEndpoint(srcPt277);
+ ConnEnd dstPt277(Point(1191.5, 1841.42), 8);
+ connRef277->setDestEndpoint(dstPt277);
+ connRef277->setRoutingType((ConnType)2);
+
+ ConnRef *connRef278 = new ConnRef(router, 278);
+ ConnEnd srcPt278(Point(1249.5, 1717.42), 4);
+ connRef278->setSourceEndpoint(srcPt278);
+ ConnEnd dstPt278(Point(1191.5, 1717.42), 8);
+ connRef278->setDestEndpoint(dstPt278);
+ connRef278->setRoutingType((ConnType)2);
+
+ ConnRef *connRef279 = new ConnRef(router, 279);
+ ConnEnd srcPt279(Point(1102.5, 1343.42), 8);
+ connRef279->setSourceEndpoint(srcPt279);
+ ConnEnd dstPt279(Point(1160.5, 1343.42), 4);
+ connRef279->setDestEndpoint(dstPt279);
+ connRef279->setRoutingType((ConnType)2);
+
+ ConnRef *connRef280 = new ConnRef(router, 280);
+ ConnEnd srcPt280(Point(980.5, 1241.42), 2);
+ connRef280->setSourceEndpoint(srcPt280);
+ ConnEnd dstPt280(Point(980.5, 1291.42), 1);
+ connRef280->setDestEndpoint(dstPt280);
+ connRef280->setRoutingType((ConnType)2);
+
+ ConnRef *connRef281 = new ConnRef(router, 281);
+ ConnEnd srcPt281(Point(1280.5, 1063.75), 4);
+ connRef281->setSourceEndpoint(srcPt281);
+ ConnEnd dstPt281(Point(1222.5, 1063.75), 8);
+ connRef281->setDestEndpoint(dstPt281);
+ connRef281->setRoutingType((ConnType)2);
+
+ ConnRef *connRef282 = new ConnRef(router, 282);
+ ConnEnd srcPt282(Point(1102.5, 1063.75), 8);
+ connRef282->setSourceEndpoint(srcPt282);
+ ConnEnd dstPt282(Point(1160.5, 1063.75), 4);
+ connRef282->setDestEndpoint(dstPt282);
+ connRef282->setRoutingType((ConnType)2);
+
+ ConnRef *connRef283 = new ConnRef(router, 283);
+ ConnEnd srcPt283(Point(1327.5, 500.5), 2);
+ connRef283->setSourceEndpoint(srcPt283);
+ ConnEnd dstPt283(Point(1327.5, 550.5), 1);
+ connRef283->setDestEndpoint(dstPt283);
+ connRef283->setRoutingType((ConnType)2);
+
+ ConnRef *connRef284 = new ConnRef(router, 284);
+ ConnEnd srcPt284(Point(1249.5, 740), 4);
+ connRef284->setSourceEndpoint(srcPt284);
+ ConnEnd dstPt284(Point(1191.5, 740), 8);
+ connRef284->setDestEndpoint(dstPt284);
+ connRef284->setRoutingType((ConnType)2);
+
+ ConnRef *connRef285 = new ConnRef(router, 285);
+ ConnEnd srcPt285(Point(1249.5, 478), 4);
+ connRef285->setSourceEndpoint(srcPt285);
+ ConnEnd dstPt285(Point(1191.5, 478), 8);
+ connRef285->setDestEndpoint(dstPt285);
+ connRef285->setRoutingType((ConnType)2);
+
+ ConnRef *connRef286 = new ConnRef(router, 286);
+ ConnEnd srcPt286(Point(918.5, 833), 2);
+ connRef286->setSourceEndpoint(srcPt286);
+ ConnEnd dstPt286(Point(918.5, 883), 1);
+ connRef286->setDestEndpoint(dstPt286);
+ connRef286->setRoutingType((ConnType)2);
+
+ ConnRef *connRef287 = new ConnRef(router, 287);
+ ConnEnd srcPt287(Point(476.5, 727), 2);
+ connRef287->setSourceEndpoint(srcPt287);
+ ConnEnd dstPt287(Point(476.5, 777), 1);
+ connRef287->setDestEndpoint(dstPt287);
+ connRef287->setRoutingType((ConnType)2);
+
+ ConnRef *connRef288 = new ConnRef(router, 288);
+ ConnEnd srcPt288(Point(476.5, 802), 2);
+ connRef288->setSourceEndpoint(srcPt288);
+ ConnEnd dstPt288(Point(476.5, 852), 1);
+ connRef288->setDestEndpoint(dstPt288);
+ connRef288->setRoutingType((ConnType)2);
+
+ ConnRef *connRef289 = new ConnRef(router, 289);
+ ConnEnd srcPt289(Point(798.5, 690), 2);
+ connRef289->setSourceEndpoint(srcPt289);
+ ConnEnd dstPt289(Point(798.5, 740), 1);
+ connRef289->setDestEndpoint(dstPt289);
+ connRef289->setRoutingType((ConnType)2);
+
+ ConnRef *connRef290 = new ConnRef(router, 290);
+ ConnEnd srcPt290(Point(585.5, 740), 8);
+ connRef290->setSourceEndpoint(srcPt290);
+ ConnEnd dstPt290(Point(643.5, 740), 4);
+ connRef290->setDestEndpoint(dstPt290);
+ connRef290->setRoutingType((ConnType)2);
+
+ ConnRef *connRef291 = new ConnRef(router, 291);
+ ConnEnd srcPt291(Point(344.5, 740), 4);
+ connRef291->setSourceEndpoint(srcPt291);
+ ConnEnd dstPt291(Point(286.5, 740), 8);
+ connRef291->setDestEndpoint(dstPt291);
+ connRef291->setRoutingType((ConnType)2);
+
+ ConnRef *connRef292 = new ConnRef(router, 292);
+ ConnEnd srcPt292(Point(707.5, 428), 2);
+ connRef292->setSourceEndpoint(srcPt292);
+ ConnEnd dstPt292(Point(707.5, 478), 1);
+ connRef292->setDestEndpoint(dstPt292);
+ connRef292->setRoutingType((ConnType)2);
+
+ ConnRef *connRef293 = new ConnRef(router, 293);
+ ConnEnd srcPt293(Point(707.5, 503), 2);
+ connRef293->setSourceEndpoint(srcPt293);
+ ConnEnd dstPt293(Point(707.5, 553), 1);
+ connRef293->setDestEndpoint(dstPt293);
+ connRef293->setRoutingType((ConnType)2);
+
+ ConnRef *connRef294 = new ConnRef(router, 294);
+ ConnEnd srcPt294(Point(707.5, 353), 2);
+ connRef294->setSourceEndpoint(srcPt294);
+ ConnEnd dstPt294(Point(707.5, 403), 1);
+ connRef294->setDestEndpoint(dstPt294);
+ connRef294->setRoutingType((ConnType)2);
+
+ ConnRef *connRef295 = new ConnRef(router, 295);
+ ConnEnd srcPt295(Point(767.5, 291), 2);
+ connRef295->setSourceEndpoint(srcPt295);
+ ConnEnd dstPt295(Point(767.5, 341), 1);
+ connRef295->setDestEndpoint(dstPt295);
+ connRef295->setRoutingType((ConnType)2);
+
+ ConnRef *connRef296 = new ConnRef(router, 296);
+ ConnEnd srcPt296(Point(767.5, 189), 2);
+ connRef296->setSourceEndpoint(srcPt296);
+ ConnEnd dstPt296(Point(767.5, 239), 1);
+ connRef296->setDestEndpoint(dstPt296);
+ connRef296->setRoutingType((ConnType)2);
+
+ ConnRef *connRef297 = new ConnRef(router, 297);
+ ConnEnd srcPt297(Point(492.5, 2262.46), 2);
+ connRef297->setSourceEndpoint(srcPt297);
+ ConnEnd dstPt297(Point(492.5, 2312.46), 1);
+ connRef297->setDestEndpoint(dstPt297);
+ connRef297->setRoutingType((ConnType)2);
+
+ ConnRef *connRef298 = new ConnRef(router, 298);
+ ConnEnd srcPt298(Point(1249.5, 1569.42), 4);
+ connRef298->setSourceEndpoint(srcPt298);
+ ConnEnd dstPt298(Point(1191.5, 1569.42), 8);
+ connRef298->setDestEndpoint(dstPt298);
+ connRef298->setRoutingType((ConnType)2);
+
+ ConnRef *connRef299 = new ConnRef(router, 299);
+ ConnEnd srcPt299(Point(707.5, 665), 1);
+ connRef299->setSourceEndpoint(srcPt299);
+ ConnEnd dstPt299(Point(707.5, 615), 2);
+ connRef299->setDestEndpoint(dstPt299);
+ connRef299->setRoutingType((ConnType)2);
+
+ ConnRef *connRef300 = new ConnRef(router, 300);
+ ConnEnd srcPt300(Point(476.5, 964), 1);
+ connRef300->setSourceEndpoint(srcPt300);
+ ConnEnd dstPt300(Point(476.5, 914), 2);
+ connRef300->setDestEndpoint(dstPt300);
+ connRef300->setRoutingType((ConnType)2);
+
+ ConnRef *connRef301 = new ConnRef(router, 301);
+ ConnEnd srcPt301(Point(286.5, 1026), 2);
+ connRef301->setSourceEndpoint(srcPt301);
+ ConnEnd dstPt301(Point(286.5, 1076), 1);
+ connRef301->setDestEndpoint(dstPt301);
+ connRef301->setRoutingType((ConnType)2);
+
+ ConnRef *connRef302 = new ConnRef(router, 302);
+ ConnEnd srcPt302(Point(286.5, 1128), 2);
+ connRef302->setSourceEndpoint(srcPt302);
+ ConnEnd dstPt302(Point(286.5, 1178), 1);
+ connRef302->setDestEndpoint(dstPt302);
+ connRef302->setRoutingType((ConnType)2);
+
+ ConnRef *connRef303 = new ConnRef(router, 303);
+ ConnEnd srcPt303(Point(554.5, 1026), 2);
+ connRef303->setSourceEndpoint(srcPt303);
+ ConnEnd dstPt303(Point(554.5, 1076), 1);
+ connRef303->setDestEndpoint(dstPt303);
+ connRef303->setRoutingType((ConnType)2);
+
+ ConnRef *connRef304 = new ConnRef(router, 304);
+ ConnEnd srcPt304(Point(554.5, 1128), 2);
+ connRef304->setSourceEndpoint(srcPt304);
+ ConnEnd dstPt304(Point(554.5, 1178), 1);
+ connRef304->setDestEndpoint(dstPt304);
+ connRef304->setRoutingType((ConnType)2);
+
+ ConnRef *connRef305 = new ConnRef(router, 305);
+ ConnEnd srcPt305(Point(699.439, 1984.42), 1);
+ connRef305->setSourceEndpoint(srcPt305);
+ ConnEnd dstPt305(Point(699.439, 1934.42), 2);
+ connRef305->setDestEndpoint(dstPt305);
+ connRef305->setRoutingType((ConnType)2);
+
+ ConnRef *connRef306 = new ConnRef(router, 306);
+ ConnEnd srcPt306(Point(1089.5, 2460.79), 1);
+ connRef306->setSourceEndpoint(srcPt306);
+ ConnEnd dstPt306(Point(1089.5, 2410.79), 2);
+ connRef306->setDestEndpoint(dstPt306);
+ connRef306->setRoutingType((ConnType)2);
+
+ ConnRef *connRef307 = new ConnRef(router, 307);
+ ConnEnd srcPt307(Point(699.439, 1822.42), 2);
+ connRef307->setSourceEndpoint(srcPt307);
+ ConnEnd dstPt307(Point(699.439, 1872.42), 1);
+ connRef307->setDestEndpoint(dstPt307);
+ connRef307->setRoutingType((ConnType)2);
+
+ ConnRef *connRef308 = new ConnRef(router, 308);
+ ConnEnd srcPt308(Point(1280.5, 1343.42), 4);
+ connRef308->setSourceEndpoint(srcPt308);
+ ConnEnd dstPt308(Point(1222.5, 1343.42), 8);
+ connRef308->setDestEndpoint(dstPt308);
+ connRef308->setRoutingType((ConnType)2);
+
+ ConnRef *connRef309 = new ConnRef(router, 309);
+ ConnEnd srcPt309(Point(1298.5, 1507.42), 4);
+ connRef309->setSourceEndpoint(srcPt309);
+ ConnEnd dstPt309(Point(1240.5, 1507.42), 8);
+ connRef309->setDestEndpoint(dstPt309);
+ connRef309->setRoutingType((ConnType)2);
+
+ ConnRef *connRef310 = new ConnRef(router, 310);
+ ConnEnd srcPt310(Point(1389.5, 1507.42), 4);
+ connRef310->setSourceEndpoint(srcPt310);
+ ConnEnd dstPt310(Point(1331.5, 1507.42), 8);
+ connRef310->setDestEndpoint(dstPt310);
+ connRef310->setRoutingType((ConnType)2);
+
+ ConnRef *connRef311 = new ConnRef(router, 311);
+ ConnEnd srcPt311(Point(554.5, 1990.42), 2);
+ connRef311->setSourceEndpoint(srcPt311);
+ ConnEnd dstPt311(Point(554.5, 2040.42), 1);
+ connRef311->setDestEndpoint(dstPt311);
+ connRef311->setRoutingType((ConnType)2);
+
+ ConnRef *connRef312 = new ConnRef(router, 312);
+ ConnEnd srcPt312(Point(1480.5, 1507.42), 4);
+ connRef312->setSourceEndpoint(srcPt312);
+ ConnEnd dstPt312(Point(1422.5, 1507.42), 8);
+ connRef312->setDestEndpoint(dstPt312);
+ connRef312->setRoutingType((ConnType)2);
+
+ ConnRef *connRef313 = new ConnRef(router, 313);
+ ConnEnd srcPt313(Point(1100.5, 1599.42), 2);
+ connRef313->setSourceEndpoint(srcPt313);
+ ConnEnd dstPt313(Point(1100.5, 1649.42), 1);
+ connRef313->setDestEndpoint(dstPt313);
+ connRef313->setRoutingType((ConnType)2);
+
+ ConnRef *connRef314 = new ConnRef(router, 314);
+ ConnEnd srcPt314(Point(1100.5, 1405.42), 2);
+ connRef314->setSourceEndpoint(srcPt314);
+ ConnEnd dstPt314(Point(1100.5, 1455.42), 1);
+ connRef314->setDestEndpoint(dstPt314);
+ connRef314->setRoutingType((ConnType)2);
+
+ ConnRef *connRef315 = new ConnRef(router, 315);
+ ConnEnd srcPt315(Point(102.5, 2231.42), 8);
+ connRef315->setSourceEndpoint(srcPt315);
+ ConnEnd dstPt315(Point(160.5, 2231.42), 4);
+ connRef315->setDestEndpoint(dstPt315);
+ connRef315->setRoutingType((ConnType)2);
+
+ ConnRef *connRef316 = new ConnRef(router, 316);
+ ConnEnd srcPt316(Point(1371.5, 1063.75), 4);
+ connRef316->setSourceEndpoint(srcPt316);
+ ConnEnd dstPt316(Point(1313.5, 1063.75), 8);
+ connRef316->setDestEndpoint(dstPt316);
+ connRef316->setRoutingType((ConnType)2);
+
+ ConnRef *connRef317 = new ConnRef(router, 317);
+ ConnEnd srcPt317(Point(707.5, 740), 1);
+ connRef317->setSourceEndpoint(srcPt317);
+ ConnEnd dstPt317(Point(707.5, 690), 2);
+ connRef317->setDestEndpoint(dstPt317);
+ connRef317->setRoutingType((ConnType)2);
+
+ ConnRef *connRef318 = new ConnRef(router, 318);
+ ConnEnd srcPt318(Point(476.5, 1039), 1);
+ connRef318->setSourceEndpoint(srcPt318);
+ ConnEnd dstPt318(Point(476.5, 989), 2);
+ connRef318->setDestEndpoint(dstPt318);
+ connRef318->setRoutingType((ConnType)2);
+
+ ConnRef *connRef319 = new ConnRef(router, 319);
+ ConnEnd srcPt319(Point(1089.5, 2535.79), 1);
+ connRef319->setSourceEndpoint(srcPt319);
+ ConnEnd dstPt319(Point(1089.5, 2485.79), 2);
+ connRef319->setDestEndpoint(dstPt319);
+ connRef319->setRoutingType((ConnType)2);
+
+ ConnRef *connRef320 = new ConnRef(router, 320);
+ ConnEnd srcPt320(Point(251.5, 2169.42), 15);
+ connRef320->setSourceEndpoint(srcPt320);
+ ConnEnd dstPt320(Point(251.5, 2216.42), 1);
+ connRef320->setDestEndpoint(dstPt320);
+ connRef320->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints320(1);
+ checkpoints320[0] = Point(226.5, 2201.42);
+ connRef320->setRoutingCheckpoints(checkpoints320);
+
+ ConnRef *connRef321 = new ConnRef(router, 321);
+ ConnEnd srcPt321(Point(1191.5, 2169.42), 15);
+ connRef321->setSourceEndpoint(srcPt321);
+ ConnEnd dstPt321(Point(1026.5, 2179.79), 8);
+ connRef321->setDestEndpoint(dstPt321);
+ connRef321->setRoutingType((ConnType)2);
+
+ ConnRef *connRef322 = new ConnRef(router, 322);
+ ConnEnd srcPt322(Point(1191.5, 2169.42), 15);
+ connRef322->setSourceEndpoint(srcPt322);
+ ConnEnd dstPt322(Point(1011.5, 2083.42), 1);
+ connRef322->setDestEndpoint(dstPt322);
+ connRef322->setRoutingType((ConnType)2);
+
+ ConnRef *connRef323 = new ConnRef(router, 323);
+ ConnEnd srcPt323(Point(674.5, 2312.46), 15);
+ connRef323->setSourceEndpoint(srcPt323);
+ ConnEnd dstPt323(Point(720.5, 2169.42), 8);
+ connRef323->setDestEndpoint(dstPt323);
+ connRef323->setRoutingType((ConnType)2);
+
+ ConnRef *connRef324 = new ConnRef(router, 324);
+ ConnEnd srcPt324(Point(829.5, 2169.42), 15);
+ connRef324->setSourceEndpoint(srcPt324);
+ ConnEnd dstPt324(Point(720.5, 2169.42), 8);
+ connRef324->setDestEndpoint(dstPt324);
+ connRef324->setRoutingType((ConnType)2);
+
+ ConnRef *connRef325 = new ConnRef(router, 325);
+ ConnEnd srcPt325(Point(1191.5, 1903.42), 15);
+ connRef325->setSourceEndpoint(srcPt325);
+ ConnEnd dstPt325(Point(1191.5, 1950.42), 1);
+ connRef325->setDestEndpoint(dstPt325);
+ connRef325->setRoutingType((ConnType)2);
+
+ ConnRef *connRef326 = new ConnRef(router, 326);
+ ConnEnd srcPt326(Point(1191.5, 883), 15);
+ connRef326->setSourceEndpoint(srcPt326);
+ ConnEnd dstPt326(Point(1222.5, 1048.75), 1);
+ connRef326->setDestEndpoint(dstPt326);
+ connRef326->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints326(1);
+ checkpoints326[0] = Point(1191.5, 1093.75);
+ connRef326->setRoutingCheckpoints(checkpoints326);
+
+ ConnRef *connRef327 = new ConnRef(router, 327);
+ ConnEnd srcPt327(Point(286.5, 883), 15);
+ connRef327->setSourceEndpoint(srcPt327);
+ ConnEnd dstPt327(Point(461.5, 777), 4);
+ connRef327->setDestEndpoint(dstPt327);
+ connRef327->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints327(1);
+ checkpoints327[0] = Point(514.5, 883);
+ connRef327->setRoutingCheckpoints(checkpoints327);
+
+ ConnRef *connRef328 = new ConnRef(router, 328);
+ ConnEnd srcPt328(Point(286.5, 883), 15);
+ connRef328->setSourceEndpoint(srcPt328);
+ ConnEnd dstPt328(Point(461.5, 852), 4);
+ connRef328->setDestEndpoint(dstPt328);
+ connRef328->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints328(1);
+ checkpoints328[0] = Point(514.5, 883);
+ connRef328->setRoutingCheckpoints(checkpoints328);
+
+ ConnRef *connRef329 = new ConnRef(router, 329);
+ ConnEnd srcPt329(Point(286.5, 584), 15);
+ connRef329->setSourceEndpoint(srcPt329);
+ ConnEnd dstPt329(Point(692.5, 478), 4);
+ connRef329->setDestEndpoint(dstPt329);
+ connRef329->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints329(1);
+ checkpoints329[0] = Point(745.5, 584);
+ connRef329->setRoutingCheckpoints(checkpoints329);
+
+ ConnRef *connRef330 = new ConnRef(router, 330);
+ ConnEnd srcPt330(Point(286.5, 584), 15);
+ connRef330->setSourceEndpoint(srcPt330);
+ ConnEnd dstPt330(Point(692.5, 553), 4);
+ connRef330->setDestEndpoint(dstPt330);
+ connRef330->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints330(1);
+ checkpoints330[0] = Point(745.5, 584);
+ connRef330->setRoutingCheckpoints(checkpoints330);
+
+ ConnRef *connRef331 = new ConnRef(router, 331);
+ ConnEnd srcPt331(Point(1191.5, 584), 15);
+ connRef331->setSourceEndpoint(srcPt331);
+ ConnEnd dstPt331(Point(722.5, 403), 8);
+ connRef331->setDestEndpoint(dstPt331);
+ connRef331->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints331(1);
+ checkpoints331[0] = Point(669.5, 584);
+ connRef331->setRoutingCheckpoints(checkpoints331);
+
+ ConnRef *connRef332 = new ConnRef(router, 332);
+ ConnEnd srcPt332(Point(1191.5, 280), 15);
+ connRef332->setSourceEndpoint(srcPt332);
+ ConnEnd dstPt332(Point(782.5, 341), 8);
+ connRef332->setDestEndpoint(dstPt332);
+ connRef332->setRoutingType((ConnType)2);
+
+ ConnRef *connRef333 = new ConnRef(router, 333);
+ ConnEnd srcPt333(Point(1191.5, 280), 15);
+ connRef333->setSourceEndpoint(srcPt333);
+ ConnEnd dstPt333(Point(782.5, 239), 8);
+ connRef333->setDestEndpoint(dstPt333);
+ connRef333->setRoutingType((ConnType)2);
+
+ ConnRef *connRef334 = new ConnRef(router, 334);
+ ConnEnd srcPt334(Point(1191.5, 584), 15);
+ connRef334->setSourceEndpoint(srcPt334);
+ ConnEnd dstPt334(Point(1427, 986.25), 4);
+ connRef334->setDestEndpoint(dstPt334);
+ connRef334->setRoutingType((ConnType)2);
+#endif
+
+ ConnRef *connRef335 = new ConnRef(router, 335);
+ ConnEnd srcPt335(Point(1191.5, 1291.42), 15);
+ connRef335->setSourceEndpoint(srcPt335);
+ ConnEnd dstPt335(Point(1427, 1026.25), 4);
+ connRef335->setDestEndpoint(dstPt335);
+ connRef335->setRoutingType((ConnType)2);
+
+#ifdef ALL
+ ConnRef *connRef336 = new ConnRef(router, 336);
+ ConnEnd srcPt336(Point(1191.5, 1779.42), 15);
+ connRef336->setSourceEndpoint(srcPt336);
+ ConnEnd dstPt336(Point(1513, 1189.75), 2);
+ connRef336->setDestEndpoint(dstPt336);
+ connRef336->setRoutingType((ConnType)2);
+
+ ConnRef *connRef337 = new ConnRef(router, 337);
+ ConnEnd srcPt337(Point(1191.5, 2169.42), 15);
+ connRef337->setSourceEndpoint(srcPt337);
+ ConnEnd dstPt337(Point(1553, 1189.75), 2);
+ connRef337->setDestEndpoint(dstPt337);
+ connRef337->setRoutingType((ConnType)2);
+
+ ConnRef *connRef338 = new ConnRef(router, 338);
+ ConnEnd srcPt338(Point(1191.5, 280), 15);
+ connRef338->setSourceEndpoint(srcPt338);
+ ConnEnd dstPt338(Point(1252, 214.5), 2);
+ connRef338->setDestEndpoint(dstPt338);
+ connRef338->setRoutingType((ConnType)2);
+
+ ConnRef *connRef339 = new ConnRef(router, 339);
+ ConnEnd srcPt339(Point(251.5, 1903.42), 15);
+ connRef339->setSourceEndpoint(srcPt339);
+ ConnEnd dstPt339(Point(247.5, 2025.92), 8);
+ connRef339->setDestEndpoint(dstPt339);
+ connRef339->setRoutingType((ConnType)2);
+
+ ConnRef *connRef340 = new ConnRef(router, 340);
+ ConnEnd srcPt340(Point(251.5, 2169.42), 15);
+ connRef340->setSourceEndpoint(srcPt340);
+ ConnEnd dstPt340(Point(247.5, 2065.92), 8);
+ connRef340->setDestEndpoint(dstPt340);
+ connRef340->setRoutingType((ConnType)2);
+
+ ConnRef *connRef341 = new ConnRef(router, 341);
+ ConnEnd srcPt341(Point(1191.5, 1655.42), 15);
+ connRef341->setSourceEndpoint(srcPt341);
+ ConnEnd dstPt341(Point(736.5, 1662.92), 8);
+ connRef341->setDestEndpoint(dstPt341);
+ connRef341->setRoutingType((ConnType)2);
+
+ ConnRef *connRef342 = new ConnRef(router, 342);
+ ConnEnd srcPt342(Point(1432.5, 2169.42), 15);
+ connRef342->setSourceEndpoint(srcPt342);
+ ConnEnd dstPt342(Point(1438.5, 2248.79), 1);
+ connRef342->setDestEndpoint(dstPt342);
+ connRef342->setRoutingType((ConnType)2);
+#endif
+
+ router->processTransaction();
+ router->outputDiagram("output/checkpointNudging2");
+
+ // Second last segment of connector 256 and 258 should be in line with each other
+ // in the y dimension, in line with the checkpoint.
+ bool areInline = (connRef258->displayRoute().ps[2].y == connRef258->displayRoute().ps[3].y) &&
+ (connRef258->displayRoute().ps[2].y == connRef256->displayRoute().ps[2].y) &&
+ (connRef258->displayRoute().ps[2].y == connRef256->displayRoute().ps[3].y);
+
+ delete router;
+ return (areInline) ? 0 : 1;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/checkpointNudging3.cpp b/src/3rdparty/adaptagrams/libavoid/tests/checkpointNudging3.cpp
new file mode 100644
index 0000000..7c31d87
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/checkpointNudging3.cpp
@@ -0,0 +1,5242 @@
+// Based on ec00240-libavoid-debug-error-high-precision.svg
+// Problem where epsilon difference could cause a segment to be restricted
+// by a checkpoint on that segment, effectively not allowing it to move.
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingParameter((RoutingParameter)0, 50);
+ router->setRoutingParameter((RoutingParameter)1, 0);
+ router->setRoutingParameter((RoutingParameter)2, 0);
+ router->setRoutingParameter((RoutingParameter)3, 4000);
+ router->setRoutingParameter((RoutingParameter)4, 0);
+ router->setRoutingParameter((RoutingParameter)5, 100);
+ router->setRoutingParameter((RoutingParameter)6, 0);
+ router->setRoutingParameter((RoutingParameter)7, 4);
+ router->setRoutingOption((RoutingOption)0, true);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, false);
+ router->setRoutingOption((RoutingOption)3, false);
+
+#ifdef REST
+ Polygon poly1(4);
+ poly1.ps[0] = Point(191.62835648698, 1359.606854916126);
+ poly1.ps[1] = Point(191.62835648698, 1391.606854916126);
+ poly1.ps[2] = Point(171.62835648698, 1391.606854916126);
+ poly1.ps[3] = Point(171.62835648698, 1359.606854916126);
+ new ShapeRef(router, poly1, 1);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(1904.12835649198, 2.256854915126041);
+ poly2.ps[1] = Point(1904.12835649198, 64.25685491512604);
+ poly2.ps[2] = Point(1842.12835649198, 64.25685491512604);
+ poly2.ps[3] = Point(1842.12835649198, 2.256854915126041);
+ new ShapeRef(router, poly2, 2);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(1959.12835649298, 23.25685491512604);
+ poly3.ps[1] = Point(1959.12835649298, 43.25685491512604);
+ poly3.ps[2] = Point(1927.12835649298, 43.25685491512604);
+ poly3.ps[3] = Point(1927.12835649298, 23.25685491512604);
+ new ShapeRef(router, poly3, 3);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(443.62835648698, -329.4098117515406);
+ poly4.ps[1] = Point(443.62835648698, -309.4098117515406);
+ poly4.ps[2] = Point(411.62835648698, -309.4098117515406);
+ poly4.ps[3] = Point(411.62835648698, -329.4098117515406);
+ new ShapeRef(router, poly4, 4);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(47.62835648497997, 935.8568549161259);
+ poly5.ps[1] = Point(47.62835648497997, 955.8568549161259);
+ poly5.ps[2] = Point(15.62835648497997, 955.8568549161259);
+ poly5.ps[3] = Point(15.62835648497997, 935.8568549161259);
+ new ShapeRef(router, poly5, 5);
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(519.62835648798, 1326.606854916126);
+ poly6.ps[1] = Point(519.62835648798, 1358.606854916126);
+ poly6.ps[2] = Point(499.62835648798, 1358.606854916126);
+ poly6.ps[3] = Point(499.62835648798, 1326.606854916126);
+ new ShapeRef(router, poly6, 6);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(-975.12164351602, -157.4098117515406);
+ poly7.ps[1] = Point(-975.12164351602, -95.40981175154064);
+ poly7.ps[2] = Point(-1037.12164351602, -95.40981175154064);
+ poly7.ps[3] = Point(-1037.12164351602, -157.4098117515406);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(-996.12164351602, -281.4098117515406);
+ poly8.ps[1] = Point(-996.12164351602, -249.4098117515406);
+ poly8.ps[2] = Point(-1016.12164351602, -249.4098117515406);
+ poly8.ps[3] = Point(-1016.12164351602, -281.4098117515406);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(-827.12164351602, -964.4098117535407);
+ poly9.ps[1] = Point(-827.12164351602, -929.4098117535407);
+ poly9.ps[2] = Point(-1041.12164351602, -929.4098117535407);
+ poly9.ps[3] = Point(-1041.12164351602, -964.4098117535407);
+ new ShapeRef(router, poly9, 9);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(-657.62164351602, -907.4098117525407);
+ poly10.ps[1] = Point(-657.62164351602, -847.4098117525407);
+ poly10.ps[2] = Point(-964.62164351602, -847.4098117525407);
+ poly10.ps[3] = Point(-964.62164351602, -907.4098117525407);
+ new ShapeRef(router, poly10, 10);
+
+ Polygon poly11(4);
+ poly11.ps[0] = Point(-938.62164351602, 275.2568549161261);
+ poly11.ps[1] = Point(-938.62164351602, 449.2568549161261);
+ poly11.ps[2] = Point(-1073.62164351602, 449.2568549161261);
+ poly11.ps[3] = Point(-1073.62164351602, 275.2568549161261);
+ new ShapeRef(router, poly11, 11);
+
+ Polygon poly12(4);
+ poly12.ps[0] = Point(2313.295023161646, -400.4098117525406);
+ poly12.ps[1] = Point(2313.295023161646, -340.4098117525406);
+ poly12.ps[2] = Point(2030.295023161646, -340.4098117525406);
+ poly12.ps[3] = Point(2030.295023161646, -400.4098117525406);
+ new ShapeRef(router, poly12, 12);
+
+ Polygon poly13(4);
+ poly13.ps[0] = Point(2313.795023161646, 1545.106854916126);
+ poly13.ps[1] = Point(2313.795023161646, 1605.106854916126);
+ poly13.ps[2] = Point(2029.795023161646, 1605.106854916126);
+ poly13.ps[3] = Point(2029.795023161646, 1545.106854916126);
+ new ShapeRef(router, poly13, 13);
+
+ Polygon poly14(4);
+ poly14.ps[0] = Point(-996.12164351602, -513.4098117525407);
+ poly14.ps[1] = Point(-996.12164351602, -481.4098117525407);
+ poly14.ps[2] = Point(-1016.12164351602, -481.4098117525407);
+ poly14.ps[3] = Point(-1016.12164351602, -513.4098117525407);
+ new ShapeRef(router, poly14, 14);
+
+ Polygon poly15(4);
+ poly15.ps[0] = Point(-792.12164351602, -747.9812403239691);
+ poly15.ps[1] = Point(-792.12164351602, -727.9812403239691);
+ poly15.ps[2] = Point(-824.12164351602, -727.9812403239691);
+ poly15.ps[3] = Point(-824.12164351602, -747.9812403239691);
+ new ShapeRef(router, poly15, 15);
+#endif
+
+ Polygon poly16(4);
+ poly16.ps[0] = Point(-452.87164351602, -843.9812403239691);
+ poly16.ps[1] = Point(-452.87164351602, -823.9812403239691);
+ poly16.ps[2] = Point(-484.87164351602, -823.9812403239691);
+ poly16.ps[3] = Point(-484.87164351602, -843.9812403239691);
+ new ShapeRef(router, poly16, 16);
+
+ Polygon poly17(4);
+ poly17.ps[0] = Point(-452.87164351602, -768.9812403239691);
+ poly17.ps[1] = Point(-452.87164351602, -748.9812403239691);
+ poly17.ps[2] = Point(-484.87164351602, -748.9812403239691);
+ poly17.ps[3] = Point(-484.87164351602, -768.9812403239691);
+ new ShapeRef(router, poly17, 17);
+
+#ifdef REST
+ Polygon poly18(4);
+ poly18.ps[0] = Point(131.62835648698, -747.9812403239691);
+ poly18.ps[1] = Point(131.62835648698, -727.9812403239691);
+ poly18.ps[2] = Point(99.62835648697995, -727.9812403239691);
+ poly18.ps[3] = Point(99.62835648697995, -747.9812403239691);
+ new ShapeRef(router, poly18, 18);
+
+ Polygon poly19(4);
+ poly19.ps[0] = Point(-485.87164351602, -507.4098117525407);
+ poly19.ps[1] = Point(-485.87164351602, -487.4098117525407);
+ poly19.ps[2] = Point(-517.87164351602, -487.4098117525407);
+ poly19.ps[3] = Point(-517.87164351602, -507.4098117525407);
+ new ShapeRef(router, poly19, 19);
+
+ Polygon poly20(4);
+ poly20.ps[0] = Point(-485.87164351602, -388.4098117525406);
+ poly20.ps[1] = Point(-485.87164351602, -368.4098117525406);
+ poly20.ps[2] = Point(-517.87164351602, -368.4098117525406);
+ poly20.ps[3] = Point(-517.87164351602, -388.4098117525406);
+ new ShapeRef(router, poly20, 20);
+
+ Polygon poly21(4);
+ poly21.ps[0] = Point(112.62835648598, -287.4098117515406);
+ poly21.ps[1] = Point(112.62835648598, -267.4098117515406);
+ poly21.ps[2] = Point(80.62835648597996, -267.4098117515406);
+ poly21.ps[3] = Point(80.62835648597996, -287.4098117515406);
+ new ShapeRef(router, poly21, 21);
+
+ Polygon poly22(4);
+ poly22.ps[0] = Point(112.62835648598, -212.4098117515406);
+ poly22.ps[1] = Point(112.62835648598, -192.4098117515406);
+ poly22.ps[2] = Point(80.62835648597996, -192.4098117515406);
+ poly22.ps[3] = Point(80.62835648597996, -212.4098117515406);
+ new ShapeRef(router, poly22, 22);
+
+ Polygon poly23(4);
+ poly23.ps[0] = Point(443.62835648698, -287.4098117515406);
+ poly23.ps[1] = Point(443.62835648698, -267.4098117515406);
+ poly23.ps[2] = Point(411.62835648698, -267.4098117515406);
+ poly23.ps[3] = Point(411.62835648698, -287.4098117515406);
+ new ShapeRef(router, poly23, 23);
+
+ Polygon poly24(4);
+ poly24.ps[0] = Point(443.62835648698, -212.4098117515406);
+ poly24.ps[1] = Point(443.62835648698, -192.4098117515406);
+ poly24.ps[2] = Point(411.62835648698, -192.4098117515406);
+ poly24.ps[3] = Point(411.62835648698, -212.4098117515406);
+ new ShapeRef(router, poly24, 24);
+
+ Polygon poly25(4);
+ poly25.ps[0] = Point(-288.87164351602, -175.4098117515406);
+ poly25.ps[1] = Point(-288.87164351602, -143.4098117515406);
+ poly25.ps[2] = Point(-308.87164351602, -143.4098117515406);
+ poly25.ps[3] = Point(-308.87164351602, -175.4098117515406);
+ new ShapeRef(router, poly25, 25);
+
+ Polygon poly26(4);
+ poly26.ps[0] = Point(-330.87164351602, -175.4098117515406);
+ poly26.ps[1] = Point(-330.87164351602, -143.4098117515406);
+ poly26.ps[2] = Point(-350.87164351602, -143.4098117515406);
+ poly26.ps[3] = Point(-350.87164351602, -175.4098117515406);
+ new ShapeRef(router, poly26, 26);
+
+ Polygon poly27(4);
+ poly27.ps[0] = Point(112.62835648598, -404.4098117515406);
+ poly27.ps[1] = Point(112.62835648598, -384.4098117515406);
+ poly27.ps[2] = Point(80.62835648597996, -384.4098117515406);
+ poly27.ps[3] = Point(80.62835648597996, -404.4098117515406);
+ new ShapeRef(router, poly27, 27);
+
+ Polygon poly28(4);
+ poly28.ps[0] = Point(112.62835648598, -329.4098117515406);
+ poly28.ps[1] = Point(112.62835648598, -309.4098117515406);
+ poly28.ps[2] = Point(80.62835648597996, -309.4098117515406);
+ poly28.ps[3] = Point(80.62835648597996, -329.4098117515406);
+ new ShapeRef(router, poly28, 28);
+
+ Polygon poly29(4);
+ poly29.ps[0] = Point(443.62835648698, -479.4098117515406);
+ poly29.ps[1] = Point(443.62835648698, -459.4098117515406);
+ poly29.ps[2] = Point(411.62835648698, -459.4098117515406);
+ poly29.ps[3] = Point(411.62835648698, -479.4098117515406);
+ new ShapeRef(router, poly29, 29);
+
+ Polygon poly30(4);
+ poly30.ps[0] = Point(443.62835648698, -404.4098117515406);
+ poly30.ps[1] = Point(443.62835648698, -384.4098117515406);
+ poly30.ps[2] = Point(411.62835648698, -384.4098117515406);
+ poly30.ps[3] = Point(411.62835648698, -404.4098117515406);
+ new ShapeRef(router, poly30, 30);
+
+ Polygon poly31(4);
+ poly31.ps[0] = Point(861.62835648898, -242.4098117515406);
+ poly31.ps[1] = Point(861.62835648898, -222.4098117515406);
+ poly31.ps[2] = Point(829.62835648898, -222.4098117515406);
+ poly31.ps[3] = Point(829.62835648898, -242.4098117515406);
+ new ShapeRef(router, poly31, 31);
+
+ Polygon poly32(4);
+ poly32.ps[0] = Point(648.9873402531949, -287.4098117515406);
+ poly32.ps[1] = Point(648.9873402531949, -267.4098117515406);
+ poly32.ps[2] = Point(616.9873402531949, -267.4098117515406);
+ poly32.ps[3] = Point(616.9873402531949, -287.4098117515406);
+ new ShapeRef(router, poly32, 32);
+
+ Polygon poly33(4);
+ poly33.ps[0] = Point(648.9873402531949, -329.4098117515406);
+ poly33.ps[1] = Point(648.9873402531949, -309.4098117515406);
+ poly33.ps[2] = Point(616.9873402531949, -309.4098117515406);
+ poly33.ps[3] = Point(616.9873402531949, -329.4098117515406);
+ new ShapeRef(router, poly33, 33);
+
+ Polygon poly34(4);
+ poly34.ps[0] = Point(1078.914070775694, -329.4098117515406);
+ poly34.ps[1] = Point(1078.914070775694, -309.4098117515406);
+ poly34.ps[2] = Point(1046.914070775694, -309.4098117515406);
+ poly34.ps[3] = Point(1046.914070775694, -329.4098117515406);
+ new ShapeRef(router, poly34, 34);
+
+ Polygon poly35(4);
+ poly35.ps[0] = Point(1078.914070775694, -287.4098117515406);
+ poly35.ps[1] = Point(1078.914070775694, -267.4098117515406);
+ poly35.ps[2] = Point(1046.914070775694, -267.4098117515406);
+ poly35.ps[3] = Point(1046.914070775694, -287.4098117515406);
+ new ShapeRef(router, poly35, 35);
+
+ Polygon poly36(4);
+ poly36.ps[0] = Point(1610.12835648998, -329.4098117515406);
+ poly36.ps[1] = Point(1610.12835648998, -309.4098117515406);
+ poly36.ps[2] = Point(1578.12835648998, -309.4098117515406);
+ poly36.ps[3] = Point(1578.12835648998, -329.4098117515406);
+ new ShapeRef(router, poly36, 36);
+
+ Polygon poly37(4);
+ poly37.ps[0] = Point(1610.12835648998, -287.4098117515406);
+ poly37.ps[1] = Point(1610.12835648998, -267.4098117515406);
+ poly37.ps[2] = Point(1578.12835648998, -267.4098117515406);
+ poly37.ps[3] = Point(1578.12835648998, -287.4098117515406);
+ new ShapeRef(router, poly37, 37);
+
+ Polygon poly38(4);
+ poly38.ps[0] = Point(1786.12835649098, -308.4098117515406);
+ poly38.ps[1] = Point(1786.12835649098, -288.4098117515406);
+ poly38.ps[2] = Point(1754.12835649098, -288.4098117515406);
+ poly38.ps[3] = Point(1754.12835649098, -308.4098117515406);
+ new ShapeRef(router, poly38, 38);
+
+ Polygon poly39(4);
+ poly39.ps[0] = Point(1959.12835649298, -308.4098117515406);
+ poly39.ps[1] = Point(1959.12835649298, -288.4098117515406);
+ poly39.ps[2] = Point(1927.12835649298, -288.4098117515406);
+ poly39.ps[3] = Point(1927.12835649298, -308.4098117515406);
+ new ShapeRef(router, poly39, 39);
+
+ Polygon poly40(4);
+ poly40.ps[0] = Point(-485.87164351602, 89.25685491512604);
+ poly40.ps[1] = Point(-485.87164351602, 109.256854915126);
+ poly40.ps[2] = Point(-517.87164351602, 109.256854915126);
+ poly40.ps[3] = Point(-517.87164351602, 89.25685491512604);
+ new ShapeRef(router, poly40, 40);
+
+ Polygon poly41(4);
+ poly41.ps[0] = Point(-485.87164351602, 191.256854916126);
+ poly41.ps[1] = Point(-485.87164351602, 211.256854916126);
+ poly41.ps[2] = Point(-517.87164351602, 211.256854916126);
+ poly41.ps[3] = Point(-517.87164351602, 191.256854916126);
+ new ShapeRef(router, poly41, 41);
+
+ Polygon poly42(4);
+ poly42.ps[0] = Point(-10.87164351502003, 35.25685491512604);
+ poly42.ps[1] = Point(-10.87164351502003, 55.25685491512604);
+ poly42.ps[2] = Point(-42.87164351502003, 55.25685491512604);
+ poly42.ps[3] = Point(-42.87164351502003, 35.25685491512604);
+ new ShapeRef(router, poly42, 42);
+
+ Polygon poly43(4);
+ poly43.ps[0] = Point(-10.87164351502003, 77.25685491512604);
+ poly43.ps[1] = Point(-10.87164351502003, 97.25685491512604);
+ poly43.ps[2] = Point(-42.87164351502003, 97.25685491512604);
+ poly43.ps[3] = Point(-42.87164351502003, 77.25685491512604);
+ new ShapeRef(router, poly43, 43);
+
+ Polygon poly44(4);
+ poly44.ps[0] = Point(466.62835648698, 77.25685491512604);
+ poly44.ps[1] = Point(466.62835648698, 97.25685491512604);
+ poly44.ps[2] = Point(434.62835648698, 97.25685491512604);
+ poly44.ps[3] = Point(434.62835648698, 77.25685491512604);
+ new ShapeRef(router, poly44, 44);
+
+ Polygon poly45(4);
+ poly45.ps[0] = Point(466.62835648698, 35.25685491512604);
+ poly45.ps[1] = Point(466.62835648698, 55.25685491512604);
+ poly45.ps[2] = Point(434.62835648698, 55.25685491512604);
+ poly45.ps[3] = Point(434.62835648698, 35.25685491512604);
+ new ShapeRef(router, poly45, 45);
+
+ Polygon poly46(4);
+ poly46.ps[0] = Point(781.62835648798, 35.25685491512604);
+ poly46.ps[1] = Point(781.62835648798, 55.25685491512604);
+ poly46.ps[2] = Point(749.62835648798, 55.25685491512604);
+ poly46.ps[3] = Point(749.62835648798, 35.25685491512604);
+ new ShapeRef(router, poly46, 46);
+
+ Polygon poly47(4);
+ poly47.ps[0] = Point(781.62835648798, 77.25685491512604);
+ poly47.ps[1] = Point(781.62835648798, 97.25685491512604);
+ poly47.ps[2] = Point(749.62835648798, 97.25685491512604);
+ poly47.ps[3] = Point(749.62835648798, 77.25685491512604);
+ new ShapeRef(router, poly47, 47);
+
+ Polygon poly48(4);
+ poly48.ps[0] = Point(992.9140707746942, -142.4098117515406);
+ poly48.ps[1] = Point(992.9140707746942, -110.4098117515406);
+ poly48.ps[2] = Point(972.9140707746942, -110.4098117515406);
+ poly48.ps[3] = Point(972.9140707746942, -142.4098117515406);
+ new ShapeRef(router, poly48, 48);
+
+ Polygon poly49(4);
+ poly49.ps[0] = Point(1439.12835648898, -142.4098117515406);
+ poly49.ps[1] = Point(1439.12835648898, -110.4098117515406);
+ poly49.ps[2] = Point(1419.12835648898, -110.4098117515406);
+ poly49.ps[3] = Point(1419.12835648898, -142.4098117515406);
+ new ShapeRef(router, poly49, 49);
+
+ Polygon poly50(4);
+ poly50.ps[0] = Point(1117.12835648898, 35.25685491512604);
+ poly50.ps[1] = Point(1117.12835648898, 55.25685491512604);
+ poly50.ps[2] = Point(1085.12835648898, 55.25685491512604);
+ poly50.ps[3] = Point(1085.12835648898, 35.25685491512604);
+ new ShapeRef(router, poly50, 50);
+
+ Polygon poly51(4);
+ poly51.ps[0] = Point(1117.12835648898, 77.25685491512604);
+ poly51.ps[1] = Point(1117.12835648898, 97.25685491512604);
+ poly51.ps[2] = Point(1085.12835648898, 97.25685491512604);
+ poly51.ps[3] = Point(1085.12835648898, 77.25685491512604);
+ new ShapeRef(router, poly51, 51);
+
+ Polygon poly52(4);
+ poly52.ps[0] = Point(715.62835648798, 245.2568549161261);
+ poly52.ps[1] = Point(715.62835648798, 265.2568549161261);
+ poly52.ps[2] = Point(683.62835648798, 265.2568549161261);
+ poly52.ps[3] = Point(683.62835648798, 245.2568549161261);
+ new ShapeRef(router, poly52, 52);
+
+ Polygon poly53(4);
+ poly53.ps[0] = Point(1643.12835648998, 23.25685491512604);
+ poly53.ps[1] = Point(1643.12835648998, 43.25685491512604);
+ poly53.ps[2] = Point(1611.12835648998, 43.25685491512604);
+ poly53.ps[3] = Point(1611.12835648998, 23.25685491512604);
+ new ShapeRef(router, poly53, 53);
+
+ Polygon poly54(4);
+ poly54.ps[0] = Point(1786.12835649098, 23.25685491512604);
+ poly54.ps[1] = Point(1786.12835649098, 43.25685491512604);
+ poly54.ps[2] = Point(1754.12835649098, 43.25685491512604);
+ poly54.ps[3] = Point(1754.12835649098, 23.25685491512604);
+ new ShapeRef(router, poly54, 54);
+
+ Polygon poly55(4);
+ poly55.ps[0] = Point(-864.12164351602, 755.8568549161259);
+ poly55.ps[1] = Point(-864.12164351602, 787.8568549161259);
+ poly55.ps[2] = Point(-884.12164351602, 787.8568549161259);
+ poly55.ps[3] = Point(-884.12164351602, 755.8568549161259);
+ new ShapeRef(router, poly55, 55);
+
+ Polygon poly56(4);
+ poly56.ps[0] = Point(-718.12164351602, 755.8568549161259);
+ poly56.ps[1] = Point(-718.12164351602, 787.8568549161259);
+ poly56.ps[2] = Point(-738.12164351602, 787.8568549161259);
+ poly56.ps[3] = Point(-738.12164351602, 755.8568549161259);
+ new ShapeRef(router, poly56, 56);
+
+ Polygon poly57(4);
+ poly57.ps[0] = Point(-524.87164351602, 504.756854916126);
+ poly57.ps[1] = Point(-524.87164351602, 536.756854916126);
+ poly57.ps[2] = Point(-544.87164351602, 536.756854916126);
+ poly57.ps[3] = Point(-544.87164351602, 504.756854916126);
+ new ShapeRef(router, poly57, 57);
+
+ Polygon poly58(4);
+ poly58.ps[0] = Point(-309.87164351602, 504.756854916126);
+ poly58.ps[1] = Point(-309.87164351602, 536.756854916126);
+ poly58.ps[2] = Point(-329.87164351602, 536.756854916126);
+ poly58.ps[3] = Point(-329.87164351602, 504.756854916126);
+ new ShapeRef(router, poly58, 58);
+
+ Polygon poly59(4);
+ poly59.ps[0] = Point(-115.87164351502, 504.756854916126);
+ poly59.ps[1] = Point(-115.87164351502, 536.756854916126);
+ poly59.ps[2] = Point(-135.87164351502, 536.756854916126);
+ poly59.ps[3] = Point(-135.87164351502, 504.756854916126);
+ new ShapeRef(router, poly59, 59);
+
+ Polygon poly60(4);
+ poly60.ps[0] = Point(191.62835648698, 504.756854916126);
+ poly60.ps[1] = Point(191.62835648698, 536.756854916126);
+ poly60.ps[2] = Point(171.62835648698, 536.756854916126);
+ poly60.ps[3] = Point(171.62835648698, 504.756854916126);
+ new ShapeRef(router, poly60, 60);
+
+ Polygon poly61(4);
+ poly61.ps[0] = Point(47.62835648497997, 728.8568549161259);
+ poly61.ps[1] = Point(47.62835648497997, 748.8568549161259);
+ poly61.ps[2] = Point(15.62835648497997, 748.8568549161259);
+ poly61.ps[3] = Point(15.62835648497997, 728.8568549161259);
+ new ShapeRef(router, poly61, 61);
+
+ Polygon poly62(4);
+ poly62.ps[0] = Point(-342.87164351602, 962.8568549161259);
+ poly62.ps[1] = Point(-342.87164351602, 994.8568549161259);
+ poly62.ps[2] = Point(-362.87164351602, 994.8568549161259);
+ poly62.ps[3] = Point(-362.87164351602, 962.8568549161259);
+ new ShapeRef(router, poly62, 62);
+
+ Polygon poly63(4);
+ poly63.ps[0] = Point(-685.12164351602, 1028.856854916126);
+ poly63.ps[1] = Point(-685.12164351602, 1060.856854916126);
+ poly63.ps[2] = Point(-705.12164351602, 1060.856854916126);
+ poly63.ps[3] = Point(-705.12164351602, 1028.856854916126);
+ new ShapeRef(router, poly63, 63);
+
+ Polygon poly64(4);
+ poly64.ps[0] = Point(377.62835648698, 707.8568549161259);
+ poly64.ps[1] = Point(377.62835648698, 727.8568549161259);
+ poly64.ps[2] = Point(345.62835648698, 727.8568549161259);
+ poly64.ps[3] = Point(345.62835648698, 707.8568549161259);
+ new ShapeRef(router, poly64, 64);
+
+ Polygon poly65(4);
+ poly65.ps[0] = Point(682.62835648798, 569.006854916126);
+ poly65.ps[1] = Point(682.62835648798, 589.006854916126);
+ poly65.ps[2] = Point(650.62835648798, 589.006854916126);
+ poly65.ps[3] = Point(650.62835648798, 569.006854916126);
+ new ShapeRef(router, poly65, 65);
+
+ Polygon poly66(4);
+ poly66.ps[0] = Point(164.62835648698, 794.8568549161259);
+ poly66.ps[1] = Point(164.62835648698, 814.8568549161259);
+ poly66.ps[2] = Point(132.62835648698, 814.8568549161259);
+ poly66.ps[3] = Point(132.62835648698, 794.8568549161259);
+ new ShapeRef(router, poly66, 66);
+
+ Polygon poly67(4);
+ poly67.ps[0] = Point(814.62835648798, 707.8568549161259);
+ poly67.ps[1] = Point(814.62835648798, 727.8568549161259);
+ poly67.ps[2] = Point(782.62835648798, 727.8568549161259);
+ poly67.ps[3] = Point(782.62835648798, 707.8568549161259);
+ new ShapeRef(router, poly67, 67);
+
+ Polygon poly68(4);
+ poly68.ps[0] = Point(814.62835648798, 749.8568549161259);
+ poly68.ps[1] = Point(814.62835648798, 769.8568549161259);
+ poly68.ps[2] = Point(782.62835648798, 769.8568549161259);
+ poly68.ps[3] = Point(782.62835648798, 749.8568549161259);
+ new ShapeRef(router, poly68, 68);
+
+ Polygon poly69(4);
+ poly69.ps[0] = Point(606.62835648798, 841.8568549161259);
+ poly69.ps[1] = Point(606.62835648798, 873.8568549161259);
+ poly69.ps[2] = Point(586.62835648798, 873.8568549161259);
+ poly69.ps[3] = Point(586.62835648798, 841.8568549161259);
+ new ShapeRef(router, poly69, 69);
+
+ Polygon poly70(4);
+ poly70.ps[0] = Point(117.62835648598, 1011.856854916126);
+ poly70.ps[1] = Point(117.62835648598, 1031.856854916126);
+ poly70.ps[2] = Point(85.62835648597996, 1031.856854916126);
+ poly70.ps[3] = Point(85.62835648597996, 1011.856854916126);
+ new ShapeRef(router, poly70, 70);
+
+ Polygon poly71(4);
+ poly71.ps[0] = Point(-76.87164351502003, 1154.856854916126);
+ poly71.ps[1] = Point(-76.87164351502003, 1174.856854916126);
+ poly71.ps[2] = Point(-108.87164351502, 1174.856854916126);
+ poly71.ps[3] = Point(-108.87164351502, 1154.856854916126);
+ new ShapeRef(router, poly71, 71);
+
+ Polygon poly72(4);
+ poly72.ps[0] = Point(-76.87164351502003, 1112.856854916126);
+ poly72.ps[1] = Point(-76.87164351502003, 1132.856854916126);
+ poly72.ps[2] = Point(-108.87164351502, 1132.856854916126);
+ poly72.ps[3] = Point(-108.87164351502, 1112.856854916126);
+ new ShapeRef(router, poly72, 72);
+
+ Polygon poly73(4);
+ poly73.ps[0] = Point(344.62835648698, 1112.856854916126);
+ poly73.ps[1] = Point(344.62835648698, 1132.856854916126);
+ poly73.ps[2] = Point(312.62835648698, 1132.856854916126);
+ poly73.ps[3] = Point(312.62835648698, 1112.856854916126);
+ new ShapeRef(router, poly73, 73);
+
+ Polygon poly74(4);
+ poly74.ps[0] = Point(861.62835648898, 1100.856854916126);
+ poly74.ps[1] = Point(861.62835648898, 1120.856854916126);
+ poly74.ps[2] = Point(829.62835648898, 1120.856854916126);
+ poly74.ps[3] = Point(829.62835648898, 1100.856854916126);
+ new ShapeRef(router, poly74, 74);
+
+ Polygon poly75(4);
+ poly75.ps[0] = Point(971.9140707746942, 870.8568549171259);
+ poly75.ps[1] = Point(971.9140707746942, 902.8568549171259);
+ poly75.ps[2] = Point(951.9140707746942, 902.8568549171259);
+ poly75.ps[3] = Point(951.9140707746942, 870.8568549171259);
+ new ShapeRef(router, poly75, 75);
+
+ Polygon poly76(4);
+ poly76.ps[0] = Point(1177.12835648898, 995.8568549161259);
+ poly76.ps[1] = Point(1177.12835648898, 1027.856854916126);
+ poly76.ps[2] = Point(1157.12835648898, 1027.856854916126);
+ poly76.ps[3] = Point(1157.12835648898, 995.8568549161259);
+ new ShapeRef(router, poly76, 76);
+
+ Polygon poly77(4);
+ poly77.ps[0] = Point(1177.12835648898, 1094.856854916126);
+ poly77.ps[1] = Point(1177.12835648898, 1126.856854916126);
+ poly77.ps[2] = Point(1157.12835648898, 1126.856854916126);
+ poly77.ps[3] = Point(1157.12835648898, 1094.856854916126);
+ new ShapeRef(router, poly77, 77);
+
+ Polygon poly78(4);
+ poly78.ps[0] = Point(1183.12835648898, 1166.856854916126);
+ poly78.ps[1] = Point(1183.12835648898, 1186.856854916126);
+ poly78.ps[2] = Point(1151.12835648898, 1186.856854916126);
+ poly78.ps[3] = Point(1151.12835648898, 1166.856854916126);
+ new ShapeRef(router, poly78, 78);
+
+ Polygon poly79(4);
+ poly79.ps[0] = Point(41.62835648497997, 1359.606854916126);
+ poly79.ps[1] = Point(41.62835648497997, 1391.606854916126);
+ poly79.ps[2] = Point(21.62835648497997, 1391.606854916126);
+ poly79.ps[3] = Point(21.62835648497997, 1359.606854916126);
+ new ShapeRef(router, poly79, 79);
+
+ Polygon poly80(4);
+ poly80.ps[0] = Point(561.62835648798, 1326.606854916126);
+ poly80.ps[1] = Point(561.62835648798, 1358.606854916126);
+ poly80.ps[2] = Point(541.62835648798, 1358.606854916126);
+ poly80.ps[3] = Point(541.62835648798, 1326.606854916126);
+ new ShapeRef(router, poly80, 80);
+
+ Polygon poly81(4);
+ poly81.ps[0] = Point(-485.87164351602, 1637.106854917126);
+ poly81.ps[1] = Point(-485.87164351602, 1657.106854917126);
+ poly81.ps[2] = Point(-517.87164351602, 1657.106854917126);
+ poly81.ps[3] = Point(-517.87164351602, 1637.106854917126);
+ new ShapeRef(router, poly81, 81);
+
+ Polygon poly82(4);
+ poly82.ps[0] = Point(-43.87164351502003, 1658.106854917126);
+ poly82.ps[1] = Point(-43.87164351502003, 1678.106854917126);
+ poly82.ps[2] = Point(-75.87164351502003, 1678.106854917126);
+ poly82.ps[3] = Point(-75.87164351502003, 1658.106854917126);
+ new ShapeRef(router, poly82, 82);
+
+ Polygon poly83(4);
+ poly83.ps[0] = Point(-43.87164351502003, 1541.106854917126);
+ poly83.ps[1] = Point(-43.87164351502003, 1561.106854917126);
+ poly83.ps[2] = Point(-75.87164351502003, 1561.106854917126);
+ poly83.ps[3] = Point(-75.87164351502003, 1541.106854917126);
+ new ShapeRef(router, poly83, 83);
+
+ Polygon poly84(4);
+ poly84.ps[0] = Point(-43.87164351502003, 1616.106854917126);
+ poly84.ps[1] = Point(-43.87164351502003, 1636.106854917126);
+ poly84.ps[2] = Point(-75.87164351502003, 1636.106854917126);
+ poly84.ps[3] = Point(-75.87164351502003, 1616.106854917126);
+ new ShapeRef(router, poly84, 84);
+
+ Polygon poly85(4);
+ poly85.ps[0] = Point(410.62835648698, 1658.106854917126);
+ poly85.ps[1] = Point(410.62835648698, 1678.106854917126);
+ poly85.ps[2] = Point(378.62835648698, 1678.106854917126);
+ poly85.ps[3] = Point(378.62835648698, 1658.106854917126);
+ new ShapeRef(router, poly85, 85);
+
+ Polygon poly86(4);
+ poly86.ps[0] = Point(410.62835648698, 1616.106854917126);
+ poly86.ps[1] = Point(410.62835648698, 1636.106854917126);
+ poly86.ps[2] = Point(378.62835648698, 1636.106854917126);
+ poly86.ps[3] = Point(378.62835648698, 1616.106854917126);
+ new ShapeRef(router, poly86, 86);
+
+ Polygon poly87(4);
+ poly87.ps[0] = Point(648.9873402531949, 1616.106854917126);
+ poly87.ps[1] = Point(648.9873402531949, 1636.106854917126);
+ poly87.ps[2] = Point(616.9873402531949, 1636.106854917126);
+ poly87.ps[3] = Point(616.9873402531949, 1616.106854917126);
+ new ShapeRef(router, poly87, 87);
+
+ Polygon poly88(4);
+ poly88.ps[0] = Point(648.9873402531949, 1658.106854917126);
+ poly88.ps[1] = Point(648.9873402531949, 1678.106854917126);
+ poly88.ps[2] = Point(616.9873402531949, 1678.106854917126);
+ poly88.ps[3] = Point(616.9873402531949, 1658.106854917126);
+ new ShapeRef(router, poly88, 88);
+
+ Polygon poly89(4);
+ poly89.ps[0] = Point(1183.12835648898, 1557.106854916126);
+ poly89.ps[1] = Point(1183.12835648898, 1577.106854916126);
+ poly89.ps[2] = Point(1151.12835648898, 1577.106854916126);
+ poly89.ps[3] = Point(1151.12835648898, 1557.106854916126);
+ new ShapeRef(router, poly89, 89);
+
+ Polygon poly90(4);
+ poly90.ps[0] = Point(1183.12835648898, 1696.773521583792);
+ poly90.ps[1] = Point(1183.12835648898, 1716.773521583792);
+ poly90.ps[2] = Point(1151.12835648898, 1716.773521583792);
+ poly90.ps[3] = Point(1151.12835648898, 1696.773521583792);
+ new ShapeRef(router, poly90, 90);
+
+ Polygon poly91(4);
+ poly91.ps[0] = Point(1346.12835648898, 1423.106854916126);
+ poly91.ps[1] = Point(1346.12835648898, 1443.106854916126);
+ poly91.ps[2] = Point(1314.12835648898, 1443.106854916126);
+ poly91.ps[3] = Point(1314.12835648898, 1423.106854916126);
+ new ShapeRef(router, poly91, 91);
+
+ Polygon poly92(4);
+ poly92.ps[0] = Point(1643.12835648998, 1299.606854916126);
+ poly92.ps[1] = Point(1643.12835648998, 1319.606854916126);
+ poly92.ps[2] = Point(1611.12835648998, 1319.606854916126);
+ poly92.ps[3] = Point(1611.12835648998, 1299.606854916126);
+ new ShapeRef(router, poly92, 92);
+
+ Polygon poly93(4);
+ poly93.ps[0] = Point(1610.12835648998, 1616.106854917126);
+ poly93.ps[1] = Point(1610.12835648998, 1636.106854917126);
+ poly93.ps[2] = Point(1578.12835648998, 1636.106854917126);
+ poly93.ps[3] = Point(1578.12835648998, 1616.106854917126);
+ new ShapeRef(router, poly93, 93);
+
+ Polygon poly94(4);
+ poly94.ps[0] = Point(1610.12835648998, 1658.106854917126);
+ poly94.ps[1] = Point(1610.12835648998, 1678.106854917126);
+ poly94.ps[2] = Point(1578.12835648998, 1678.106854917126);
+ poly94.ps[3] = Point(1578.12835648998, 1658.106854917126);
+ new ShapeRef(router, poly94, 94);
+
+ Polygon poly95(4);
+ poly95.ps[0] = Point(1786.12835649098, 1299.606854916126);
+ poly95.ps[1] = Point(1786.12835649098, 1319.606854916126);
+ poly95.ps[2] = Point(1754.12835649098, 1319.606854916126);
+ poly95.ps[3] = Point(1754.12835649098, 1299.606854916126);
+ new ShapeRef(router, poly95, 95);
+
+ Polygon poly96(4);
+ poly96.ps[0] = Point(1786.12835649098, 1637.106854917126);
+ poly96.ps[1] = Point(1786.12835649098, 1657.106854917126);
+ poly96.ps[2] = Point(1754.12835649098, 1657.106854917126);
+ poly96.ps[3] = Point(1754.12835649098, 1637.106854917126);
+ new ShapeRef(router, poly96, 96);
+
+ Polygon poly97(4);
+ poly97.ps[0] = Point(1959.12835649298, 1637.106854917126);
+ poly97.ps[1] = Point(1959.12835649298, 1657.106854917126);
+ poly97.ps[2] = Point(1927.12835649298, 1657.106854917126);
+ poly97.ps[3] = Point(1927.12835649298, 1637.106854917126);
+ new ShapeRef(router, poly97, 97);
+
+ Polygon poly98(4);
+ poly98.ps[0] = Point(-1048.12164351702, -157.9098117515406);
+ poly98.ps[1] = Point(-1048.12164351702, 16.09018824845936);
+ poly98.ps[2] = Point(-1172.12164351702, 16.09018824845936);
+ poly98.ps[3] = Point(-1172.12164351702, -157.9098117515406);
+ new ShapeRef(router, poly98, 98);
+#endif
+
+ Polygon poly99(4);
+ poly99.ps[0] = Point(-452.87164351602, -726.9812403239691);
+ poly99.ps[1] = Point(-452.87164351602, -706.9812403239691);
+ poly99.ps[2] = Point(-484.87164351602, -706.9812403239691);
+ poly99.ps[3] = Point(-484.87164351602, -726.9812403239691);
+ new ShapeRef(router, poly99, 99);
+
+#ifdef REST
+ Polygon poly100(4);
+ poly100.ps[0] = Point(377.62835648698, 749.8568549161259);
+ poly100.ps[1] = Point(377.62835648698, 769.8568549161259);
+ poly100.ps[2] = Point(345.62835648698, 769.8568549161259);
+ poly100.ps[3] = Point(345.62835648698, 749.8568549161259);
+ new ShapeRef(router, poly100, 100);
+
+ Polygon poly101(4);
+ poly101.ps[0] = Point(344.62835648698, 1154.856854916126);
+ poly101.ps[1] = Point(344.62835648698, 1174.856854916126);
+ poly101.ps[2] = Point(312.62835648698, 1174.856854916126);
+ poly101.ps[3] = Point(312.62835648698, 1154.856854916126);
+ new ShapeRef(router, poly101, 101);
+
+ Polygon poly102(4);
+ poly102.ps[0] = Point(1013.914070774694, 870.8568549171259);
+ poly102.ps[1] = Point(1013.914070774694, 902.8568549171259);
+ poly102.ps[2] = Point(993.9140707746942, 902.8568549171259);
+ poly102.ps[3] = Point(993.9140707746942, 870.8568549171259);
+ new ShapeRef(router, poly102, 102);
+
+ Polygon poly103(4);
+ poly103.ps[0] = Point(1643.12835648998, -628.4098117525407);
+ poly103.ps[1] = Point(1643.12835648998, -608.4098117525407);
+ poly103.ps[2] = Point(1611.12835648998, -608.4098117525407);
+ poly103.ps[3] = Point(1611.12835648998, -628.4098117525407);
+ new ShapeRef(router, poly103, 103);
+
+ Polygon poly104(4);
+ poly104.ps[0] = Point(1819.12835649098, -568.5348117525407);
+ poly104.ps[1] = Point(1819.12835649098, -548.5348117525407);
+ poly104.ps[2] = Point(1787.12835649098, -548.5348117525407);
+ poly104.ps[3] = Point(1787.12835649098, -568.5348117525407);
+ new ShapeRef(router, poly104, 104);
+
+ Polygon poly105(4);
+ poly105.ps[0] = Point(476.62835648698, -747.9812403239691);
+ poly105.ps[1] = Point(476.62835648698, -727.9812403239691);
+ poly105.ps[2] = Point(444.62835648698, -727.9812403239691);
+ poly105.ps[3] = Point(444.62835648698, -747.9812403239691);
+ new ShapeRef(router, poly105, 105);
+
+ Polygon poly106(4);
+ poly106.ps[0] = Point(748.62835648798, -817.4098117525407);
+ poly106.ps[1] = Point(748.62835648798, -797.4098117525407);
+ poly106.ps[2] = Point(716.62835648798, -797.4098117525407);
+ poly106.ps[3] = Point(716.62835648798, -817.4098117525407);
+ new ShapeRef(router, poly106, 106);
+
+ Polygon poly107(4);
+ poly107.ps[0] = Point(748.62835648798, -691.4098117525407);
+ poly107.ps[1] = Point(748.62835648798, -671.4098117525407);
+ poly107.ps[2] = Point(716.62835648798, -671.4098117525407);
+ poly107.ps[3] = Point(716.62835648798, -691.4098117525407);
+ new ShapeRef(router, poly107, 107);
+
+ Polygon poly108(4);
+ poly108.ps[0] = Point(992.9140707746942, -480.4098117525406);
+ poly108.ps[1] = Point(992.9140707746942, -448.4098117525406);
+ poly108.ps[2] = Point(972.9140707746942, -448.4098117525406);
+ poly108.ps[3] = Point(972.9140707746942, -480.4098117525406);
+ new ShapeRef(router, poly108, 108);
+
+ Polygon poly109(4);
+ poly109.ps[0] = Point(1247.12835648898, -568.5348117525407);
+ poly109.ps[1] = Point(1247.12835648898, -548.5348117525407);
+ poly109.ps[2] = Point(1215.12835648898, -548.5348117525407);
+ poly109.ps[3] = Point(1215.12835648898, -568.5348117525407);
+ new ShapeRef(router, poly109, 109);
+
+ Polygon poly110(4);
+ poly110.ps[0] = Point(197.62835648698, -136.4098117515406);
+ poly110.ps[1] = Point(197.62835648698, -116.4098117515406);
+ poly110.ps[2] = Point(165.62835648698, -116.4098117515406);
+ poly110.ps[3] = Point(165.62835648698, -136.4098117515406);
+ new ShapeRef(router, poly110, 110);
+
+ Polygon poly111(4);
+ poly111.ps[0] = Point(682.62835648798, -30.40981175154064);
+ poly111.ps[1] = Point(682.62835648798, -10.40981175154064);
+ poly111.ps[2] = Point(650.62835648798, -10.40981175154064);
+ poly111.ps[3] = Point(650.62835648798, -30.40981175154064);
+ new ShapeRef(router, poly111, 111);
+
+ Polygon poly112(4);
+ poly112.ps[0] = Point(927.62835648898, 411.7568549161261);
+ poly112.ps[1] = Point(927.62835648898, 431.7568549161261);
+ poly112.ps[2] = Point(895.62835648898, 431.7568549161261);
+ poly112.ps[3] = Point(895.62835648898, 411.7568549161261);
+ new ShapeRef(router, poly112, 112);
+
+ Polygon poly113(4);
+ poly113.ps[0] = Point(509.62835648698, 411.7568549161261);
+ poly113.ps[1] = Point(509.62835648698, 431.7568549161261);
+ poly113.ps[2] = Point(477.62835648698, 431.7568549161261);
+ poly113.ps[3] = Point(477.62835648698, 411.7568549161261);
+ new ShapeRef(router, poly113, 113);
+
+ Polygon poly114(4);
+ poly114.ps[0] = Point(117.62835648598, 1053.856854916126);
+ poly114.ps[1] = Point(117.62835648598, 1073.856854916126);
+ poly114.ps[2] = Point(85.62835648597996, 1073.856854916126);
+ poly114.ps[3] = Point(85.62835648597996, 1053.856854916126);
+ new ShapeRef(router, poly114, 114);
+
+ Polygon poly115(4);
+ poly115.ps[0] = Point(47.62835648497997, -568.5348117525407);
+ poly115.ps[1] = Point(47.62835648497997, -548.5348117525407);
+ poly115.ps[2] = Point(15.62835648497997, -548.5348117525407);
+ poly115.ps[3] = Point(15.62835648497997, -568.5348117525407);
+ new ShapeRef(router, poly115, 115);
+
+ Polygon poly116(4);
+ poly116.ps[0] = Point(-975.12164351602, -768.9812403239691);
+ poly116.ps[1] = Point(-975.12164351602, -706.9812403239691);
+ poly116.ps[2] = Point(-1037.12164351602, -706.9812403239691);
+ poly116.ps[3] = Point(-1037.12164351602, -768.9812403239691);
+ new ShapeRef(router, poly116, 116);
+
+ Polygon poly117(4);
+ poly117.ps[0] = Point(-975.12164351602, -462.4098117525406);
+ poly117.ps[1] = Point(-975.12164351602, -400.4098117525406);
+ poly117.ps[2] = Point(-1037.12164351602, -400.4098117525406);
+ poly117.ps[3] = Point(-1037.12164351602, -462.4098117525406);
+ new ShapeRef(router, poly117, 117);
+#endif
+
+ Polygon poly118(4);
+ poly118.ps[0] = Point(-664.12164351602, -768.9812403239691);
+ poly118.ps[1] = Point(-664.12164351602, -706.9812403239691);
+ poly118.ps[2] = Point(-726.12164351602, -706.9812403239691);
+ poly118.ps[3] = Point(-726.12164351602, -768.9812403239691);
+ new ShapeRef(router, poly118, 118);
+
+#ifdef REST
+ Polygon poly119(4);
+ poly119.ps[0] = Point(-94.87164351502003, -908.4098117525407);
+ poly119.ps[1] = Point(-94.87164351502003, -846.4098117525407);
+ poly119.ps[2] = Point(-156.87164351502, -846.4098117525407);
+ poly119.ps[3] = Point(-156.87164351502, -908.4098117525407);
+ new ShapeRef(router, poly119, 119);
+
+ Polygon poly120(4);
+ poly120.ps[0] = Point(293.62835648698, -768.9812403239691);
+ poly120.ps[1] = Point(293.62835648698, -706.9812403239691);
+ poly120.ps[2] = Point(231.62835648698, -706.9812403239691);
+ poly120.ps[3] = Point(231.62835648698, -768.9812403239691);
+ new ShapeRef(router, poly120, 120);
+
+ Polygon poly121(4);
+ poly121.ps[0] = Point(-810.12164351602, 637.6568549161261);
+ poly121.ps[1] = Point(-810.12164351602, 699.6568549161261);
+ poly121.ps[2] = Point(-872.12164351602, 699.6568549161261);
+ poly121.ps[3] = Point(-872.12164351602, 637.6568549161261);
+ new ShapeRef(router, poly121, 121);
+
+ Polygon poly122(4);
+ poly122.ps[0] = Point(-810.12164351602, 859.8568549161259);
+ poly122.ps[1] = Point(-810.12164351602, 921.8568549161259);
+ poly122.ps[2] = Point(-872.12164351602, 921.8568549161259);
+ poly122.ps[3] = Point(-872.12164351602, 859.8568549161259);
+ new ShapeRef(router, poly122, 122);
+
+ Polygon poly123(4);
+ poly123.ps[0] = Point(-288.87164351602, -329.4098117515406);
+ poly123.ps[1] = Point(-288.87164351602, -267.4098117515406);
+ poly123.ps[2] = Point(-350.87164351602, -267.4098117515406);
+ poly123.ps[3] = Point(-350.87164351602, -329.4098117515406);
+ new ShapeRef(router, poly123, 123);
+
+ Polygon poly124(4);
+ poly124.ps[0] = Point(212.62835648698, -329.4098117515406);
+ poly124.ps[1] = Point(212.62835648698, -267.4098117515406);
+ poly124.ps[2] = Point(150.62835648698, -267.4098117515406);
+ poly124.ps[3] = Point(150.62835648698, -329.4098117515406);
+ new ShapeRef(router, poly124, 124);
+
+ Polygon poly125(4);
+ poly125.ps[0] = Point(561.62835648798, -329.4098117515406);
+ poly125.ps[1] = Point(561.62835648798, -267.4098117515406);
+ poly125.ps[2] = Point(499.62835648798, -267.4098117515406);
+ poly125.ps[3] = Point(499.62835648798, -329.4098117515406);
+ new ShapeRef(router, poly125, 125);
+
+ Polygon poly126(4);
+ poly126.ps[0] = Point(1013.914070774694, -329.4098117515406);
+ poly126.ps[1] = Point(1013.914070774694, -267.4098117515406);
+ poly126.ps[2] = Point(951.9140707746942, -267.4098117515406);
+ poly126.ps[3] = Point(951.9140707746942, -329.4098117515406);
+ new ShapeRef(router, poly126, 126);
+
+ Polygon poly127(4);
+ poly127.ps[0] = Point(1545.12835648898, -329.4098117515406);
+ poly127.ps[1] = Point(1545.12835648898, -267.4098117515406);
+ poly127.ps[2] = Point(1483.12835648898, -267.4098117515406);
+ poly127.ps[3] = Point(1483.12835648898, -329.4098117515406);
+ new ShapeRef(router, poly127, 127);
+
+ Polygon poly128(4);
+ poly128.ps[0] = Point(-664.12164351602, 35.25685491512604);
+ poly128.ps[1] = Point(-664.12164351602, 97.25685491512604);
+ poly128.ps[2] = Point(-726.12164351602, 97.25685491512604);
+ poly128.ps[3] = Point(-726.12164351602, 35.25685491512604);
+ new ShapeRef(router, poly128, 128);
+
+ Polygon poly129(4);
+ poly129.ps[0] = Point(-288.87164351602, 35.25685491512604);
+ poly129.ps[1] = Point(-288.87164351602, 97.25685491512604);
+ poly129.ps[2] = Point(-350.87164351602, 97.25685491512604);
+ poly129.ps[3] = Point(-350.87164351602, 35.25685491512604);
+ new ShapeRef(router, poly129, 129);
+
+ Polygon poly130(4);
+ poly130.ps[0] = Point(-664.12164351602, 1616.106854917126);
+ poly130.ps[1] = Point(-664.12164351602, 1678.106854917126);
+ poly130.ps[2] = Point(-726.12164351602, 1678.106854917126);
+ poly130.ps[3] = Point(-726.12164351602, 1616.106854917126);
+ new ShapeRef(router, poly130, 130);
+
+ Polygon poly131(4);
+ poly131.ps[0] = Point(-288.87164351602, 1616.106854917126);
+ poly131.ps[1] = Point(-288.87164351602, 1678.106854917126);
+ poly131.ps[2] = Point(-350.87164351602, 1678.106854917126);
+ poly131.ps[3] = Point(-350.87164351602, 1616.106854917126);
+ new ShapeRef(router, poly131, 131);
+
+ Polygon poly132(4);
+ poly132.ps[0] = Point(212.62835648698, 1616.106854917126);
+ poly132.ps[1] = Point(212.62835648698, 1678.106854917126);
+ poly132.ps[2] = Point(150.62835648698, 1678.106854917126);
+ poly132.ps[3] = Point(150.62835648698, 1616.106854917126);
+ new ShapeRef(router, poly132, 132);
+
+ Polygon poly133(4);
+ poly133.ps[0] = Point(561.62835648798, 1616.106854917126);
+ poly133.ps[1] = Point(561.62835648798, 1678.106854917126);
+ poly133.ps[2] = Point(499.62835648798, 1678.106854917126);
+ poly133.ps[3] = Point(499.62835648798, 1616.106854917126);
+ new ShapeRef(router, poly133, 133);
+
+ Polygon poly134(4);
+ poly134.ps[0] = Point(1013.914070774694, 1616.106854917126);
+ poly134.ps[1] = Point(1013.914070774694, 1678.106854917126);
+ poly134.ps[2] = Point(951.9140707746942, 1678.106854917126);
+ poly134.ps[3] = Point(951.9140707746942, 1616.106854917126);
+ new ShapeRef(router, poly134, 134);
+
+ Polygon poly135(4);
+ poly135.ps[0] = Point(1427.12835648898, 1708.773521583792);
+ poly135.ps[1] = Point(1427.12835648898, 1770.773521583792);
+ poly135.ps[2] = Point(1365.12835648898, 1770.773521583792);
+ poly135.ps[3] = Point(1365.12835648898, 1708.773521583792);
+ new ShapeRef(router, poly135, 135);
+
+ Polygon poly136(4);
+ poly136.ps[0] = Point(1731.12835648998, 1278.606854916126);
+ poly136.ps[1] = Point(1731.12835648998, 1340.606854916126);
+ poly136.ps[2] = Point(1669.12835648998, 1340.606854916126);
+ poly136.ps[3] = Point(1669.12835648998, 1278.606854916126);
+ new ShapeRef(router, poly136, 136);
+
+ Polygon poly137(4);
+ poly137.ps[0] = Point(1904.12835649198, 1278.606854916126);
+ poly137.ps[1] = Point(1904.12835649198, 1340.606854916126);
+ poly137.ps[2] = Point(1842.12835649198, 1340.606854916126);
+ poly137.ps[3] = Point(1842.12835649198, 1278.606854916126);
+ new ShapeRef(router, poly137, 137);
+
+ Polygon poly138(4);
+ poly138.ps[0] = Point(1545.12835648898, 1616.106854917126);
+ poly138.ps[1] = Point(1545.12835648898, 1678.106854917126);
+ poly138.ps[2] = Point(1483.12835648898, 1678.106854917126);
+ poly138.ps[3] = Point(1483.12835648898, 1616.106854917126);
+ new ShapeRef(router, poly138, 138);
+
+ Polygon poly139(4);
+ poly139.ps[0] = Point(1165.12835648898, 1402.106854916126);
+ poly139.ps[1] = Point(1165.12835648898, 1464.106854916126);
+ poly139.ps[2] = Point(1103.12835648898, 1464.106854916126);
+ poly139.ps[3] = Point(1103.12835648898, 1402.106854916126);
+ new ShapeRef(router, poly139, 139);
+
+ Polygon poly140(4);
+ poly140.ps[0] = Point(1731.12835648998, 1616.106854917126);
+ poly140.ps[1] = Point(1731.12835648998, 1678.106854917126);
+ poly140.ps[2] = Point(1669.12835648998, 1678.106854917126);
+ poly140.ps[3] = Point(1669.12835648998, 1616.106854917126);
+ new ShapeRef(router, poly140, 140);
+
+ Polygon poly141(4);
+ poly141.ps[0] = Point(1904.12835649198, 1616.106854917126);
+ poly141.ps[1] = Point(1904.12835649198, 1678.106854917126);
+ poly141.ps[2] = Point(1842.12835649198, 1678.106854917126);
+ poly141.ps[3] = Point(1842.12835649198, 1616.106854917126);
+ new ShapeRef(router, poly141, 141);
+
+ Polygon poly142(4);
+ poly142.ps[0] = Point(2077.795023159646, 1616.106854917126);
+ poly142.ps[1] = Point(2077.795023159646, 1678.106854917126);
+ poly142.ps[2] = Point(2015.795023159646, 1678.106854917126);
+ poly142.ps[3] = Point(2015.795023159646, 1616.106854917126);
+ new ShapeRef(router, poly142, 142);
+
+ Polygon poly143(4);
+ poly143.ps[0] = Point(2077.795023159646, 2.256854915126041);
+ poly143.ps[1] = Point(2077.795023159646, 64.25685491512604);
+ poly143.ps[2] = Point(2015.795023159646, 64.25685491512604);
+ poly143.ps[3] = Point(2015.795023159646, 2.256854915126041);
+ new ShapeRef(router, poly143, 143);
+
+ Polygon poly144(4);
+ poly144.ps[0] = Point(2011.795023159646, 68.25685491512604);
+ poly144.ps[1] = Point(2011.795023159646, 130.256854915126);
+ poly144.ps[2] = Point(1949.795023159646, 130.256854915126);
+ poly144.ps[3] = Point(1949.795023159646, 68.25685491512604);
+ new ShapeRef(router, poly144, 144);
+
+ Polygon poly145(4);
+ poly145.ps[0] = Point(1731.12835648998, 2.256854915126041);
+ poly145.ps[1] = Point(1731.12835648998, 64.25685491512604);
+ poly145.ps[2] = Point(1669.12835648998, 64.25685491512604);
+ poly145.ps[3] = Point(1669.12835648998, 2.256854915126041);
+ new ShapeRef(router, poly145, 145);
+
+ Polygon poly146(4);
+ poly146.ps[0] = Point(2077.795023159646, -329.4098117515406);
+ poly146.ps[1] = Point(2077.795023159646, -267.4098117515406);
+ poly146.ps[2] = Point(2015.795023159646, -267.4098117515406);
+ poly146.ps[3] = Point(2015.795023159646, -329.4098117515406);
+ new ShapeRef(router, poly146, 146);
+
+ Polygon poly147(4);
+ poly147.ps[0] = Point(1904.12835649198, -329.4098117515406);
+ poly147.ps[1] = Point(1904.12835649198, -267.4098117515406);
+ poly147.ps[2] = Point(1842.12835649198, -267.4098117515406);
+ poly147.ps[3] = Point(1842.12835649198, -329.4098117515406);
+ new ShapeRef(router, poly147, 147);
+
+ Polygon poly148(4);
+ poly148.ps[0] = Point(1731.12835648998, -329.4098117515406);
+ poly148.ps[1] = Point(1731.12835648998, -267.4098117515406);
+ poly148.ps[2] = Point(1669.12835648998, -267.4098117515406);
+ poly148.ps[3] = Point(1669.12835648998, -329.4098117515406);
+ new ShapeRef(router, poly148, 148);
+
+ Polygon poly149(4);
+ poly149.ps[0] = Point(1295.12835648898, 35.25685491512604);
+ poly149.ps[1] = Point(1295.12835648898, 97.25685491512604);
+ poly149.ps[2] = Point(1233.12835648898, 97.25685491512604);
+ poly149.ps[3] = Point(1233.12835648898, 35.25685491512604);
+ new ShapeRef(router, poly149, 149);
+
+ Polygon poly150(4);
+ poly150.ps[0] = Point(1013.914070774694, 35.25685491512604);
+ poly150.ps[1] = Point(1013.914070774694, 97.25685491512604);
+ poly150.ps[2] = Point(951.9140707746942, 97.25685491512604);
+ poly150.ps[3] = Point(951.9140707746942, 35.25685491512604);
+ new ShapeRef(router, poly150, 150);
+
+ Polygon poly151(4);
+ poly151.ps[0] = Point(561.62835648798, 35.25685491512604);
+ poly151.ps[1] = Point(561.62835648798, 97.25685491512604);
+ poly151.ps[2] = Point(499.62835648798, 97.25685491512604);
+ poly151.ps[3] = Point(499.62835648798, 35.25685491512604);
+ new ShapeRef(router, poly151, 151);
+
+ Polygon poly152(4);
+ poly152.ps[0] = Point(212.62835648698, 35.25685491512604);
+ poly152.ps[1] = Point(212.62835648698, 97.25685491512604);
+ poly152.ps[2] = Point(150.62835648698, 97.25685491512604);
+ poly152.ps[3] = Point(150.62835648698, 35.25685491512604);
+ new ShapeRef(router, poly152, 152);
+
+ Polygon poly153(4);
+ poly153.ps[0] = Point(212.62835648698, 1468.106854916126);
+ poly153.ps[1] = Point(212.62835648698, 1530.106854916126);
+ poly153.ps[2] = Point(150.62835648698, 1530.106854916126);
+ poly153.ps[3] = Point(150.62835648698, 1468.106854916126);
+ new ShapeRef(router, poly153, 153);
+
+ Polygon poly154(4);
+ poly154.ps[0] = Point(146.62835648698, 1435.106854916126);
+ poly154.ps[1] = Point(146.62835648698, 1497.106854916126);
+ poly154.ps[2] = Point(84.62835648697995, 1497.106854916126);
+ poly154.ps[3] = Point(84.62835648697995, 1435.106854916126);
+ new ShapeRef(router, poly154, 154);
+
+ Polygon poly155(4);
+ poly155.ps[0] = Point(146.62835648698, 1223.856854916126);
+ poly155.ps[1] = Point(146.62835648698, 1285.856854916126);
+ poly155.ps[2] = Point(84.62835648697995, 1285.856854916126);
+ poly155.ps[3] = Point(84.62835648697995, 1223.856854916126);
+ new ShapeRef(router, poly155, 155);
+
+ Polygon poly156(4);
+ poly156.ps[0] = Point(-288.87164351602, 1112.856854916126);
+ poly156.ps[1] = Point(-288.87164351602, 1174.856854916126);
+ poly156.ps[2] = Point(-350.87164351602, 1174.856854916126);
+ poly156.ps[3] = Point(-350.87164351602, 1112.856854916126);
+ new ShapeRef(router, poly156, 156);
+
+ Polygon poly157(4);
+ poly157.ps[0] = Point(212.62835648698, 1112.856854916126);
+ poly157.ps[1] = Point(212.62835648698, 1174.856854916126);
+ poly157.ps[2] = Point(150.62835648698, 1174.856854916126);
+ poly157.ps[3] = Point(150.62835648698, 1112.856854916126);
+ new ShapeRef(router, poly157, 157);
+
+ Polygon poly158(4);
+ poly158.ps[0] = Point(561.62835648798, 1112.856854916126);
+ poly158.ps[1] = Point(561.62835648798, 1174.856854916126);
+ poly158.ps[2] = Point(499.62835648798, 1174.856854916126);
+ poly158.ps[3] = Point(499.62835648798, 1112.856854916126);
+ new ShapeRef(router, poly158, 158);
+
+ Polygon poly159(4);
+ poly159.ps[0] = Point(1013.914070774694, 1112.856854916126);
+ poly159.ps[1] = Point(1013.914070774694, 1174.856854916126);
+ poly159.ps[2] = Point(951.9140707746942, 1174.856854916126);
+ poly159.ps[3] = Point(951.9140707746942, 1112.856854916126);
+ new ShapeRef(router, poly159, 159);
+
+ Polygon poly160(4);
+ poly160.ps[0] = Point(1013.914070774694, 707.8568549161259);
+ poly160.ps[1] = Point(1013.914070774694, 769.8568549161259);
+ poly160.ps[2] = Point(951.9140707746942, 769.8568549161259);
+ poly160.ps[3] = Point(951.9140707746942, 707.8568549161259);
+ new ShapeRef(router, poly160, 160);
+
+ Polygon poly161(4);
+ poly161.ps[0] = Point(561.62835648798, 707.8568549161259);
+ poly161.ps[1] = Point(561.62835648798, 769.8568549161259);
+ poly161.ps[2] = Point(499.62835648798, 769.8568549161259);
+ poly161.ps[3] = Point(499.62835648798, 707.8568549161259);
+ new ShapeRef(router, poly161, 161);
+
+ Polygon poly162(4);
+ poly162.ps[0] = Point(212.62835648698, 707.8568549161259);
+ poly162.ps[1] = Point(212.62835648698, 769.8568549161259);
+ poly162.ps[2] = Point(150.62835648698, 769.8568549161259);
+ poly162.ps[3] = Point(150.62835648698, 707.8568549161259);
+ new ShapeRef(router, poly162, 162);
+
+ Polygon poly163(4);
+ poly163.ps[0] = Point(-288.87164351602, 707.8568549161259);
+ poly163.ps[1] = Point(-288.87164351602, 769.8568549161259);
+ poly163.ps[2] = Point(-350.87164351602, 769.8568549161259);
+ poly163.ps[3] = Point(-350.87164351602, 707.8568549161259);
+ new ShapeRef(router, poly163, 163);
+
+ Polygon poly164(4);
+ poly164.ps[0] = Point(-404.87164351602, 604.6568549161261);
+ poly164.ps[1] = Point(-404.87164351602, 666.6568549161261);
+ poly164.ps[2] = Point(-466.87164351602, 666.6568549161261);
+ poly164.ps[3] = Point(-466.87164351602, 604.6568549161261);
+ new ShapeRef(router, poly164, 164);
+
+ Polygon poly165(4);
+ poly165.ps[0] = Point(-404.87164351602, 423.7568549161261);
+ poly165.ps[1] = Point(-404.87164351602, 485.7568549161261);
+ poly165.ps[2] = Point(-466.87164351602, 485.7568549161261);
+ poly165.ps[3] = Point(-466.87164351602, 423.7568549161261);
+ new ShapeRef(router, poly165, 165);
+
+ Polygon poly166(4);
+ poly166.ps[0] = Point(146.62835648698, 604.6568549161261);
+ poly166.ps[1] = Point(146.62835648698, 666.6568549161261);
+ poly166.ps[2] = Point(84.62835648697995, 666.6568549161261);
+ poly166.ps[3] = Point(84.62835648697995, 604.6568549161261);
+ new ShapeRef(router, poly166, 166);
+
+ Polygon poly167(4);
+ poly167.ps[0] = Point(146.62835648698, 423.7568549161261);
+ poly167.ps[1] = Point(146.62835648698, 485.7568549161261);
+ poly167.ps[2] = Point(84.62835648697995, 485.7568549161261);
+ poly167.ps[3] = Point(84.62835648697995, 423.7568549161261);
+ new ShapeRef(router, poly167, 167);
+
+ Polygon poly168(4);
+ poly168.ps[0] = Point(909.62835648898, 548.006854916126);
+ poly168.ps[1] = Point(909.62835648898, 610.006854916126);
+ poly168.ps[2] = Point(847.62835648898, 610.006854916126);
+ poly168.ps[3] = Point(847.62835648898, 548.006854916126);
+ new ShapeRef(router, poly168, 168);
+
+ Polygon poly169(4);
+ poly169.ps[0] = Point(1099.12835648898, 548.006854916126);
+ poly169.ps[1] = Point(1099.12835648898, 610.006854916126);
+ poly169.ps[2] = Point(1037.12835648898, 610.006854916126);
+ poly169.ps[3] = Point(1037.12835648898, 548.006854916126);
+ new ShapeRef(router, poly169, 169);
+
+ Polygon poly170(4);
+ poly170.ps[0] = Point(1328.12835648898, 548.006854916126);
+ poly170.ps[1] = Point(1328.12835648898, 610.006854916126);
+ poly170.ps[2] = Point(1266.12835648898, 610.006854916126);
+ poly170.ps[3] = Point(1266.12835648898, 548.006854916126);
+ new ShapeRef(router, poly170, 170);
+
+ Polygon poly171(4);
+ poly171.ps[0] = Point(1731.12835648998, -589.5348117525407);
+ poly171.ps[1] = Point(1731.12835648998, -527.5348117525407);
+ poly171.ps[2] = Point(1669.12835648998, -527.5348117525407);
+ poly171.ps[3] = Point(1669.12835648998, -589.5348117525407);
+ new ShapeRef(router, poly171, 171);
+
+ Polygon poly172(4);
+ poly172.ps[0] = Point(1904.12835649198, -589.5348117525407);
+ poly172.ps[1] = Point(1904.12835649198, -527.5348117525407);
+ poly172.ps[2] = Point(1842.12835649198, -527.5348117525407);
+ poly172.ps[3] = Point(1842.12835649198, -589.5348117525407);
+ new ShapeRef(router, poly172, 172);
+
+ Polygon poly173(4);
+ poly173.ps[0] = Point(-195.87164351502, -768.9812403239691);
+ poly173.ps[1] = Point(-195.87164351502, -706.9812403239691);
+ poly173.ps[2] = Point(-257.87164351502, -706.9812403239691);
+ poly173.ps[3] = Point(-257.87164351502, -768.9812403239691);
+ new ShapeRef(router, poly173, 173);
+
+ Polygon poly174(4);
+ poly174.ps[0] = Point(975.62835648898, -712.4098117525407);
+ poly174.ps[1] = Point(975.62835648898, -650.4098117525407);
+ poly174.ps[2] = Point(913.62835648898, -650.4098117525407);
+ poly174.ps[3] = Point(913.62835648898, -712.4098117525407);
+ new ShapeRef(router, poly174, 174);
+
+ Polygon poly175(4);
+ poly175.ps[0] = Point(975.62835648898, -838.4098117525407);
+ poly175.ps[1] = Point(975.62835648898, -776.4098117525407);
+ poly175.ps[2] = Point(913.62835648898, -776.4098117525407);
+ poly175.ps[3] = Point(913.62835648898, -838.4098117525407);
+ new ShapeRef(router, poly175, 175);
+
+ Polygon poly176(4);
+ poly176.ps[0] = Point(1099.12835648898, -589.5348117525407);
+ poly176.ps[1] = Point(1099.12835648898, -527.5348117525407);
+ poly176.ps[2] = Point(1037.12835648898, -527.5348117525407);
+ poly176.ps[3] = Point(1037.12835648898, -589.5348117525407);
+ new ShapeRef(router, poly176, 176);
+
+ Polygon poly177(4);
+ poly177.ps[0] = Point(1394.12835648898, -589.5348117525407);
+ poly177.ps[1] = Point(1394.12835648898, -527.5348117525407);
+ poly177.ps[2] = Point(1332.12835648898, -527.5348117525407);
+ poly177.ps[3] = Point(1332.12835648898, -589.5348117525407);
+ new ShapeRef(router, poly177, 177);
+
+ Polygon poly178(4);
+ poly178.ps[0] = Point(876.62835648898, -51.40981175154064);
+ poly178.ps[1] = Point(876.62835648898, 10.59018824845936);
+ poly178.ps[2] = Point(814.62835648898, 10.59018824845936);
+ poly178.ps[3] = Point(814.62835648898, -51.40981175154064);
+ new ShapeRef(router, poly178, 178);
+
+ Polygon poly179(4);
+ poly179.ps[0] = Point(326.62835648698, 390.7568549161261);
+ poly179.ps[1] = Point(326.62835648698, 452.7568549161261);
+ poly179.ps[2] = Point(264.62835648698, 452.7568549161261);
+ poly179.ps[3] = Point(264.62835648698, 390.7568549161261);
+ new ShapeRef(router, poly179, 179);
+
+ Polygon poly180(4);
+ poly180.ps[0] = Point(212.62835648698, -589.5348117525407);
+ poly180.ps[1] = Point(212.62835648698, -527.5348117525407);
+ poly180.ps[2] = Point(150.62835648698, -527.5348117525407);
+ poly180.ps[3] = Point(150.62835648698, -589.5348117525407);
+ new ShapeRef(router, poly180, 180);
+
+ Polygon poly181(4);
+ poly181.ps[0] = Point(594.62835648798, 390.7568549161261);
+ poly181.ps[1] = Point(594.62835648798, 452.7568549161261);
+ poly181.ps[2] = Point(532.62835648798, 452.7568549161261);
+ poly181.ps[3] = Point(532.62835648798, 390.7568549161261);
+ new ShapeRef(router, poly181, 181);
+
+ Polygon poly182(4);
+ poly182.ps[0] = Point(1698.12835648998, 604.6568549161261);
+ poly182.ps[1] = Point(1698.12835648998, 666.6568549161261);
+ poly182.ps[2] = Point(1636.12835648998, 666.6568549161261);
+ poly182.ps[3] = Point(1636.12835648998, 604.6568549161261);
+ new ShapeRef(router, poly182, 182);
+
+ Polygon poly183(4);
+ poly183.ps[0] = Point(1574.12835648898, 625.6568549161261);
+ poly183.ps[1] = Point(1574.12835648898, 645.6568549161261);
+ poly183.ps[2] = Point(1542.12835648898, 645.6568549161261);
+ poly183.ps[3] = Point(1542.12835648898, 625.6568549161261);
+ new ShapeRef(router, poly183, 183);
+
+ Polygon poly184(4);
+ poly184.ps[0] = Point(1753.12835649098, 625.6568549161261);
+ poly184.ps[1] = Point(1753.12835649098, 645.6568549161261);
+ poly184.ps[2] = Point(1721.12835649098, 645.6568549161261);
+ poly184.ps[3] = Point(1721.12835649098, 625.6568549161261);
+ new ShapeRef(router, poly184, 184);
+
+ Polygon poly185(4);
+ poly185.ps[0] = Point(1904.12835649198, 604.6568549161261);
+ poly185.ps[1] = Point(1904.12835649198, 666.6568549161261);
+ poly185.ps[2] = Point(1842.12835649198, 666.6568549161261);
+ poly185.ps[3] = Point(1842.12835649198, 604.6568549161261);
+ new ShapeRef(router, poly185, 185);
+
+ Polygon poly186(4);
+ poly186.ps[0] = Point(1867.12835649098, 456.756854916126);
+ poly186.ps[1] = Point(1867.12835649098, 518.756854916126);
+ poly186.ps[2] = Point(1805.12835649098, 518.756854916126);
+ poly186.ps[3] = Point(1805.12835649098, 456.756854916126);
+ new ShapeRef(router, poly186, 186);
+
+ Polygon poly187(4);
+ poly187.ps[0] = Point(2184.795023161646, 604.6568549161261);
+ poly187.ps[1] = Point(2184.795023161646, 666.6568549161261);
+ poly187.ps[2] = Point(2122.795023161646, 666.6568549161261);
+ poly187.ps[3] = Point(2122.795023161646, 604.6568549161261);
+ new ShapeRef(router, poly187, 187);
+
+ Polygon poly188(4);
+ poly188.ps[0] = Point(2249.795023162646, 604.6568549161261);
+ poly188.ps[1] = Point(2249.795023162646, 624.6568549161261);
+ poly188.ps[2] = Point(2217.795023162646, 624.6568549161261);
+ poly188.ps[3] = Point(2217.795023162646, 604.6568549161261);
+ new ShapeRef(router, poly188, 188);
+
+ Polygon poly189(4);
+ poly189.ps[0] = Point(2344.795023163646, 604.6568549161261);
+ poly189.ps[1] = Point(2344.795023163646, 666.6568549161261);
+ poly189.ps[2] = Point(2282.795023163646, 666.6568549161261);
+ poly189.ps[3] = Point(2282.795023163646, 604.6568549161261);
+ new ShapeRef(router, poly189, 189);
+
+ Polygon poly190(4);
+ poly190.ps[0] = Point(2044.795023159646, 604.6568549161261);
+ poly190.ps[1] = Point(2044.795023159646, 666.6568549161261);
+ poly190.ps[2] = Point(1982.795023159646, 666.6568549161261);
+ poly190.ps[3] = Point(1982.795023159646, 604.6568549161261);
+ new ShapeRef(router, poly190, 190);
+
+ Polygon poly191(4);
+ poly191.ps[0] = Point(2099.795023160646, 625.6568549161261);
+ poly191.ps[1] = Point(2099.795023160646, 645.6568549161261);
+ poly191.ps[2] = Point(2067.795023160646, 645.6568549161261);
+ poly191.ps[3] = Point(2067.795023160646, 625.6568549161261);
+ new ShapeRef(router, poly191, 191);
+
+ Polygon poly192(4);
+ poly192.ps[0] = Point(2249.795023162646, 646.6568549161261);
+ poly192.ps[1] = Point(2249.795023162646, 666.6568549161261);
+ poly192.ps[2] = Point(2217.795023162646, 666.6568549161261);
+ poly192.ps[3] = Point(2217.795023162646, 646.6568549161261);
+ new ShapeRef(router, poly192, 192);
+
+ Polygon poly193(4);
+ poly193.ps[0] = Point(1698.12835648998, 330.2568549161261);
+ poly193.ps[1] = Point(1698.12835648998, 392.2568549161261);
+ poly193.ps[2] = Point(1636.12835648998, 392.2568549161261);
+ poly193.ps[3] = Point(1636.12835648998, 330.2568549161261);
+ new ShapeRef(router, poly193, 193);
+
+ Polygon poly194(4);
+ poly194.ps[0] = Point(1753.12835649098, 351.2568549161261);
+ poly194.ps[1] = Point(1753.12835649098, 371.2568549161261);
+ poly194.ps[2] = Point(1721.12835649098, 371.2568549161261);
+ poly194.ps[3] = Point(1721.12835649098, 351.2568549161261);
+ new ShapeRef(router, poly194, 194);
+
+ Polygon poly195(4);
+ poly195.ps[0] = Point(1643.12835648998, -507.4098117525407);
+ poly195.ps[1] = Point(1643.12835648998, -487.4098117525407);
+ poly195.ps[2] = Point(1611.12835648998, -487.4098117525407);
+ poly195.ps[3] = Point(1611.12835648998, -507.4098117525407);
+ new ShapeRef(router, poly195, 195);
+
+ Polygon poly196(4);
+ poly196.ps[0] = Point(267.62835648698, 1355.606854916126);
+ poly196.ps[1] = Point(267.62835648698, 1395.606854916126);
+ poly196.ps[2] = Point(191.62835648698, 1395.606854916126);
+ poly196.ps[3] = Point(191.62835648698, 1355.606854916126);
+ new ShapeRef(router, poly196, 196);
+
+ Polygon poly197(4);
+ poly197.ps[0] = Point(1971.12835649298, -36.74314508487396);
+ poly197.ps[1] = Point(1971.12835649298, 23.25685491512604);
+ poly197.ps[2] = Point(1915.12835649298, 23.25685491512604);
+ poly197.ps[3] = Point(1915.12835649298, -36.74314508487396);
+ new ShapeRef(router, poly197, 197);
+
+ Polygon poly198(4);
+ poly198.ps[0] = Point(455.62835648698, -389.4098117515406);
+ poly198.ps[1] = Point(455.62835648698, -329.4098117515406);
+ poly198.ps[2] = Point(399.62835648698, -329.4098117515406);
+ poly198.ps[3] = Point(399.62835648698, -389.4098117515406);
+ new ShapeRef(router, poly198, 198);
+
+ Polygon poly199(4);
+ poly199.ps[0] = Point(59.62835648497997, 875.8568549161259);
+ poly199.ps[1] = Point(59.62835648497997, 935.8568549161259);
+ poly199.ps[2] = Point(3.628356484979975, 935.8568549161259);
+ poly199.ps[3] = Point(3.628356484979975, 875.8568549161259);
+ new ShapeRef(router, poly199, 199);
+
+ Polygon poly200(4);
+ poly200.ps[0] = Point(499.62835648798, 1322.606854916126);
+ poly200.ps[1] = Point(499.62835648798, 1362.606854916126);
+ poly200.ps[2] = Point(423.6283564879799, 1362.606854916126);
+ poly200.ps[3] = Point(423.6283564879799, 1322.606854916126);
+ new ShapeRef(router, poly200, 200);
+
+ Polygon poly201(4);
+ poly201.ps[0] = Point(-920.12164351602, -285.4098117515406);
+ poly201.ps[1] = Point(-920.12164351602, -245.4098117515406);
+ poly201.ps[2] = Point(-996.12164351602, -245.4098117515406);
+ poly201.ps[3] = Point(-996.12164351602, -285.4098117515406);
+ new ShapeRef(router, poly201, 201);
+
+ Polygon poly202(4);
+ poly202.ps[0] = Point(-920.12164351602, -517.4098117525407);
+ poly202.ps[1] = Point(-920.12164351602, -477.4098117525407);
+ poly202.ps[2] = Point(-996.12164351602, -477.4098117525407);
+ poly202.ps[3] = Point(-996.12164351602, -517.4098117525407);
+ new ShapeRef(router, poly202, 202);
+
+ Polygon poly203(4);
+ poly203.ps[0] = Point(-780.12164351602, -807.9812403239691);
+ poly203.ps[1] = Point(-780.12164351602, -747.9812403239691);
+ poly203.ps[2] = Point(-836.12164351602, -747.9812403239691);
+ poly203.ps[3] = Point(-836.12164351602, -807.9812403239691);
+ new ShapeRef(router, poly203, 203);
+
+ Polygon poly204(4);
+ poly204.ps[0] = Point(-440.87164351602, -903.9812403239691);
+ poly204.ps[1] = Point(-440.87164351602, -843.9812403239691);
+ poly204.ps[2] = Point(-496.87164351602, -843.9812403239691);
+ poly204.ps[3] = Point(-496.87164351602, -903.9812403239691);
+ new ShapeRef(router, poly204, 204);
+
+ Polygon poly205(4);
+ poly205.ps[0] = Point(-440.87164351602, -828.9812403239691);
+ poly205.ps[1] = Point(-440.87164351602, -768.9812403239691);
+ poly205.ps[2] = Point(-496.87164351602, -768.9812403239691);
+ poly205.ps[3] = Point(-496.87164351602, -828.9812403239691);
+ new ShapeRef(router, poly205, 205);
+
+ Polygon poly206(4);
+ poly206.ps[0] = Point(143.62835648698, -807.9812403239691);
+ poly206.ps[1] = Point(143.62835648698, -747.9812403239691);
+ poly206.ps[2] = Point(87.62835648697995, -747.9812403239691);
+ poly206.ps[3] = Point(87.62835648697995, -807.9812403239691);
+ new ShapeRef(router, poly206, 206);
+
+ Polygon poly207(4);
+ poly207.ps[0] = Point(-473.87164351602, -567.4098117525407);
+ poly207.ps[1] = Point(-473.87164351602, -507.4098117525407);
+ poly207.ps[2] = Point(-529.87164351602, -507.4098117525407);
+ poly207.ps[3] = Point(-529.87164351602, -567.4098117525407);
+ new ShapeRef(router, poly207, 207);
+
+ Polygon poly208(4);
+ poly208.ps[0] = Point(-473.87164351602, -448.4098117525406);
+ poly208.ps[1] = Point(-473.87164351602, -388.4098117525406);
+ poly208.ps[2] = Point(-529.87164351602, -388.4098117525406);
+ poly208.ps[3] = Point(-529.87164351602, -448.4098117525406);
+ new ShapeRef(router, poly208, 208);
+
+ Polygon poly209(4);
+ poly209.ps[0] = Point(124.62835648598, -267.4098117515406);
+ poly209.ps[1] = Point(124.62835648598, -207.4098117515406);
+ poly209.ps[2] = Point(68.62835648597996, -207.4098117515406);
+ poly209.ps[3] = Point(68.62835648597996, -267.4098117515406);
+ new ShapeRef(router, poly209, 209);
+
+ Polygon poly210(4);
+ poly210.ps[0] = Point(124.62835648598, -192.4098117515406);
+ poly210.ps[1] = Point(124.62835648598, -132.4098117515406);
+ poly210.ps[2] = Point(68.62835648597996, -132.4098117515406);
+ poly210.ps[3] = Point(68.62835648597996, -192.4098117515406);
+ new ShapeRef(router, poly210, 210);
+
+ Polygon poly211(4);
+ poly211.ps[0] = Point(455.62835648698, -267.4098117515406);
+ poly211.ps[1] = Point(455.62835648698, -207.4098117515406);
+ poly211.ps[2] = Point(399.62835648698, -207.4098117515406);
+ poly211.ps[3] = Point(399.62835648698, -267.4098117515406);
+ new ShapeRef(router, poly211, 211);
+
+ Polygon poly212(4);
+ poly212.ps[0] = Point(455.62835648698, -192.4098117515406);
+ poly212.ps[1] = Point(455.62835648698, -132.4098117515406);
+ poly212.ps[2] = Point(399.62835648698, -132.4098117515406);
+ poly212.ps[3] = Point(399.62835648698, -192.4098117515406);
+ new ShapeRef(router, poly212, 212);
+
+ Polygon poly213(4);
+ poly213.ps[0] = Point(-212.87164351602, -179.4098117515406);
+ poly213.ps[1] = Point(-212.87164351602, -139.4098117515406);
+ poly213.ps[2] = Point(-288.87164351602, -139.4098117515406);
+ poly213.ps[3] = Point(-288.87164351602, -179.4098117515406);
+ new ShapeRef(router, poly213, 213);
+
+ Polygon poly214(4);
+ poly214.ps[0] = Point(-350.87164351602, -179.4098117515406);
+ poly214.ps[1] = Point(-350.87164351602, -139.4098117515406);
+ poly214.ps[2] = Point(-426.87164351602, -139.4098117515406);
+ poly214.ps[3] = Point(-426.87164351602, -179.4098117515406);
+ new ShapeRef(router, poly214, 214);
+
+ Polygon poly215(4);
+ poly215.ps[0] = Point(124.62835648598, -464.4098117515406);
+ poly215.ps[1] = Point(124.62835648598, -404.4098117515406);
+ poly215.ps[2] = Point(68.62835648597996, -404.4098117515406);
+ poly215.ps[3] = Point(68.62835648597996, -464.4098117515406);
+ new ShapeRef(router, poly215, 215);
+
+ Polygon poly216(4);
+ poly216.ps[0] = Point(124.62835648598, -389.4098117515406);
+ poly216.ps[1] = Point(124.62835648598, -329.4098117515406);
+ poly216.ps[2] = Point(68.62835648597996, -329.4098117515406);
+ poly216.ps[3] = Point(68.62835648597996, -389.4098117515406);
+ new ShapeRef(router, poly216, 216);
+
+ Polygon poly217(4);
+ poly217.ps[0] = Point(455.62835648698, -539.4098117515407);
+ poly217.ps[1] = Point(455.62835648698, -479.4098117515406);
+ poly217.ps[2] = Point(399.62835648698, -479.4098117515406);
+ poly217.ps[3] = Point(399.62835648698, -539.4098117515407);
+ new ShapeRef(router, poly217, 217);
+
+ Polygon poly218(4);
+ poly218.ps[0] = Point(455.62835648698, -464.4098117515406);
+ poly218.ps[1] = Point(455.62835648698, -404.4098117515406);
+ poly218.ps[2] = Point(399.62835648698, -404.4098117515406);
+ poly218.ps[3] = Point(399.62835648698, -464.4098117515406);
+ new ShapeRef(router, poly218, 218);
+
+ Polygon poly219(4);
+ poly219.ps[0] = Point(873.62835648898, -222.4098117515406);
+ poly219.ps[1] = Point(873.62835648898, -162.4098117515406);
+ poly219.ps[2] = Point(817.62835648898, -162.4098117515406);
+ poly219.ps[3] = Point(817.62835648898, -222.4098117515406);
+ new ShapeRef(router, poly219, 219);
+
+ Polygon poly220(4);
+ poly220.ps[0] = Point(660.9873402531949, -267.4098117515406);
+ poly220.ps[1] = Point(660.9873402531949, -207.4098117515406);
+ poly220.ps[2] = Point(604.9873402531949, -207.4098117515406);
+ poly220.ps[3] = Point(604.9873402531949, -267.4098117515406);
+ new ShapeRef(router, poly220, 220);
+
+ Polygon poly221(4);
+ poly221.ps[0] = Point(660.9873402531949, -389.4098117515406);
+ poly221.ps[1] = Point(660.9873402531949, -329.4098117515406);
+ poly221.ps[2] = Point(604.9873402531949, -329.4098117515406);
+ poly221.ps[3] = Point(604.9873402531949, -389.4098117515406);
+ new ShapeRef(router, poly221, 221);
+
+ Polygon poly222(4);
+ poly222.ps[0] = Point(1090.914070775694, -389.4098117515406);
+ poly222.ps[1] = Point(1090.914070775694, -329.4098117515406);
+ poly222.ps[2] = Point(1034.914070775694, -329.4098117515406);
+ poly222.ps[3] = Point(1034.914070775694, -389.4098117515406);
+ new ShapeRef(router, poly222, 222);
+
+ Polygon poly223(4);
+ poly223.ps[0] = Point(1090.914070775694, -267.4098117515406);
+ poly223.ps[1] = Point(1090.914070775694, -207.4098117515406);
+ poly223.ps[2] = Point(1034.914070775694, -207.4098117515406);
+ poly223.ps[3] = Point(1034.914070775694, -267.4098117515406);
+ new ShapeRef(router, poly223, 223);
+
+ Polygon poly224(4);
+ poly224.ps[0] = Point(1622.12835648998, -389.4098117515406);
+ poly224.ps[1] = Point(1622.12835648998, -329.4098117515406);
+ poly224.ps[2] = Point(1566.12835648998, -329.4098117515406);
+ poly224.ps[3] = Point(1566.12835648998, -389.4098117515406);
+ new ShapeRef(router, poly224, 224);
+
+ Polygon poly225(4);
+ poly225.ps[0] = Point(1622.12835648998, -267.4098117515406);
+ poly225.ps[1] = Point(1622.12835648998, -207.4098117515406);
+ poly225.ps[2] = Point(1566.12835648998, -207.4098117515406);
+ poly225.ps[3] = Point(1566.12835648998, -267.4098117515406);
+ new ShapeRef(router, poly225, 225);
+
+ Polygon poly226(4);
+ poly226.ps[0] = Point(1798.12835649098, -368.4098117515406);
+ poly226.ps[1] = Point(1798.12835649098, -308.4098117515406);
+ poly226.ps[2] = Point(1742.12835649098, -308.4098117515406);
+ poly226.ps[3] = Point(1742.12835649098, -368.4098117515406);
+ new ShapeRef(router, poly226, 226);
+
+ Polygon poly227(4);
+ poly227.ps[0] = Point(1971.12835649298, -368.4098117515406);
+ poly227.ps[1] = Point(1971.12835649298, -308.4098117515406);
+ poly227.ps[2] = Point(1915.12835649298, -308.4098117515406);
+ poly227.ps[3] = Point(1915.12835649298, -368.4098117515406);
+ new ShapeRef(router, poly227, 227);
+
+ Polygon poly228(4);
+ poly228.ps[0] = Point(-473.87164351602, 109.256854915126);
+ poly228.ps[1] = Point(-473.87164351602, 169.256854915126);
+ poly228.ps[2] = Point(-529.87164351602, 169.256854915126);
+ poly228.ps[3] = Point(-529.87164351602, 109.256854915126);
+ new ShapeRef(router, poly228, 228);
+
+ Polygon poly229(4);
+ poly229.ps[0] = Point(-473.87164351602, 211.256854916126);
+ poly229.ps[1] = Point(-473.87164351602, 271.2568549161261);
+ poly229.ps[2] = Point(-529.87164351602, 271.2568549161261);
+ poly229.ps[3] = Point(-529.87164351602, 211.256854916126);
+ new ShapeRef(router, poly229, 229);
+
+ Polygon poly230(4);
+ poly230.ps[0] = Point(1.128356484979975, -24.74314508487396);
+ poly230.ps[1] = Point(1.128356484979975, 35.25685491512604);
+ poly230.ps[2] = Point(-54.87164351502003, 35.25685491512604);
+ poly230.ps[3] = Point(-54.87164351502003, -24.74314508487396);
+ new ShapeRef(router, poly230, 230);
+
+ Polygon poly231(4);
+ poly231.ps[0] = Point(1.128356484979975, 97.25685491512604);
+ poly231.ps[1] = Point(1.128356484979975, 157.256854915126);
+ poly231.ps[2] = Point(-54.87164351502003, 157.256854915126);
+ poly231.ps[3] = Point(-54.87164351502003, 97.25685491512604);
+ new ShapeRef(router, poly231, 231);
+
+ Polygon poly232(4);
+ poly232.ps[0] = Point(478.62835648698, 97.25685491512604);
+ poly232.ps[1] = Point(478.62835648698, 157.256854915126);
+ poly232.ps[2] = Point(422.62835648698, 157.256854915126);
+ poly232.ps[3] = Point(422.62835648698, 97.25685491512604);
+ new ShapeRef(router, poly232, 232);
+
+ Polygon poly233(4);
+ poly233.ps[0] = Point(478.62835648698, -24.74314508487396);
+ poly233.ps[1] = Point(478.62835648698, 35.25685491512604);
+ poly233.ps[2] = Point(422.62835648698, 35.25685491512604);
+ poly233.ps[3] = Point(422.62835648698, -24.74314508487396);
+ new ShapeRef(router, poly233, 233);
+
+ Polygon poly234(4);
+ poly234.ps[0] = Point(793.62835648798, -24.74314508487396);
+ poly234.ps[1] = Point(793.62835648798, 35.25685491512604);
+ poly234.ps[2] = Point(737.62835648798, 35.25685491512604);
+ poly234.ps[3] = Point(737.62835648798, -24.74314508487396);
+ new ShapeRef(router, poly234, 234);
+
+ Polygon poly235(4);
+ poly235.ps[0] = Point(793.62835648798, 97.25685491512604);
+ poly235.ps[1] = Point(793.62835648798, 157.256854915126);
+ poly235.ps[2] = Point(737.62835648798, 157.256854915126);
+ poly235.ps[3] = Point(737.62835648798, 97.25685491512604);
+ new ShapeRef(router, poly235, 235);
+
+ Polygon poly236(4);
+ poly236.ps[0] = Point(1068.914070774694, -146.4098117515406);
+ poly236.ps[1] = Point(1068.914070774694, -106.4098117515406);
+ poly236.ps[2] = Point(992.9140707746942, -106.4098117515406);
+ poly236.ps[3] = Point(992.9140707746942, -146.4098117515406);
+ new ShapeRef(router, poly236, 236);
+
+ Polygon poly237(4);
+ poly237.ps[0] = Point(1515.12835648898, -146.4098117515406);
+ poly237.ps[1] = Point(1515.12835648898, -106.4098117515406);
+ poly237.ps[2] = Point(1439.12835648898, -106.4098117515406);
+ poly237.ps[3] = Point(1439.12835648898, -146.4098117515406);
+ new ShapeRef(router, poly237, 237);
+
+ Polygon poly238(4);
+ poly238.ps[0] = Point(1129.12835648898, -24.74314508487396);
+ poly238.ps[1] = Point(1129.12835648898, 35.25685491512604);
+ poly238.ps[2] = Point(1073.12835648898, 35.25685491512604);
+ poly238.ps[3] = Point(1073.12835648898, -24.74314508487396);
+ new ShapeRef(router, poly238, 238);
+
+ Polygon poly239(4);
+ poly239.ps[0] = Point(1129.12835648898, 97.25685491512604);
+ poly239.ps[1] = Point(1129.12835648898, 157.256854915126);
+ poly239.ps[2] = Point(1073.12835648898, 157.256854915126);
+ poly239.ps[3] = Point(1073.12835648898, 97.25685491512604);
+ new ShapeRef(router, poly239, 239);
+
+ Polygon poly240(4);
+ poly240.ps[0] = Point(727.62835648798, 265.2568549161261);
+ poly240.ps[1] = Point(727.62835648798, 325.2568549161261);
+ poly240.ps[2] = Point(671.62835648798, 325.2568549161261);
+ poly240.ps[3] = Point(671.62835648798, 265.2568549161261);
+ new ShapeRef(router, poly240, 240);
+
+ Polygon poly241(4);
+ poly241.ps[0] = Point(1655.12835648998, -36.74314508487396);
+ poly241.ps[1] = Point(1655.12835648998, 23.25685491512604);
+ poly241.ps[2] = Point(1599.12835648998, 23.25685491512604);
+ poly241.ps[3] = Point(1599.12835648998, -36.74314508487396);
+ new ShapeRef(router, poly241, 241);
+
+ Polygon poly242(4);
+ poly242.ps[0] = Point(1798.12835649098, -36.74314508487396);
+ poly242.ps[1] = Point(1798.12835649098, 23.25685491512604);
+ poly242.ps[2] = Point(1742.12835649098, 23.25685491512604);
+ poly242.ps[3] = Point(1742.12835649098, -36.74314508487396);
+ new ShapeRef(router, poly242, 242);
+
+ Polygon poly243(4);
+ poly243.ps[0] = Point(-884.12164351602, 751.8568549161259);
+ poly243.ps[1] = Point(-884.12164351602, 791.8568549161259);
+ poly243.ps[2] = Point(-960.12164351602, 791.8568549161259);
+ poly243.ps[3] = Point(-960.12164351602, 751.8568549161259);
+ new ShapeRef(router, poly243, 243);
+
+ Polygon poly244(4);
+ poly244.ps[0] = Point(-738.12164351602, 751.8568549161259);
+ poly244.ps[1] = Point(-738.12164351602, 791.8568549161259);
+ poly244.ps[2] = Point(-814.12164351602, 791.8568549161259);
+ poly244.ps[3] = Point(-814.12164351602, 751.8568549161259);
+ new ShapeRef(router, poly244, 244);
+
+ Polygon poly245(4);
+ poly245.ps[0] = Point(-544.87164351602, 500.756854916126);
+ poly245.ps[1] = Point(-544.87164351602, 540.756854916126);
+ poly245.ps[2] = Point(-620.87164351602, 540.756854916126);
+ poly245.ps[3] = Point(-620.87164351602, 500.756854916126);
+ new ShapeRef(router, poly245, 245);
+
+ Polygon poly246(4);
+ poly246.ps[0] = Point(-233.87164351602, 500.756854916126);
+ poly246.ps[1] = Point(-233.87164351602, 540.756854916126);
+ poly246.ps[2] = Point(-309.87164351602, 540.756854916126);
+ poly246.ps[3] = Point(-309.87164351602, 500.756854916126);
+ new ShapeRef(router, poly246, 246);
+
+ Polygon poly247(4);
+ poly247.ps[0] = Point(-135.87164351502, 500.756854916126);
+ poly247.ps[1] = Point(-135.87164351502, 540.756854916126);
+ poly247.ps[2] = Point(-211.87164351502, 540.756854916126);
+ poly247.ps[3] = Point(-211.87164351502, 500.756854916126);
+ new ShapeRef(router, poly247, 247);
+
+ Polygon poly248(4);
+ poly248.ps[0] = Point(267.62835648698, 500.756854916126);
+ poly248.ps[1] = Point(267.62835648698, 540.756854916126);
+ poly248.ps[2] = Point(191.62835648698, 540.756854916126);
+ poly248.ps[3] = Point(191.62835648698, 500.756854916126);
+ new ShapeRef(router, poly248, 248);
+
+ Polygon poly249(4);
+ poly249.ps[0] = Point(59.62835648497997, 668.8568549161259);
+ poly249.ps[1] = Point(59.62835648497997, 728.8568549161259);
+ poly249.ps[2] = Point(3.628356484979975, 728.8568549161259);
+ poly249.ps[3] = Point(3.628356484979975, 668.8568549161259);
+ new ShapeRef(router, poly249, 249);
+
+ Polygon poly250(4);
+ poly250.ps[0] = Point(-362.87164351602, 958.8568549161259);
+ poly250.ps[1] = Point(-362.87164351602, 998.8568549161259);
+ poly250.ps[2] = Point(-438.87164351602, 998.8568549161259);
+ poly250.ps[3] = Point(-438.87164351602, 958.8568549161259);
+ new ShapeRef(router, poly250, 250);
+
+ Polygon poly251(4);
+ poly251.ps[0] = Point(-609.12164351602, 1024.856854916126);
+ poly251.ps[1] = Point(-609.12164351602, 1064.856854916126);
+ poly251.ps[2] = Point(-685.12164351602, 1064.856854916126);
+ poly251.ps[3] = Point(-685.12164351602, 1024.856854916126);
+ new ShapeRef(router, poly251, 251);
+
+ Polygon poly252(4);
+ poly252.ps[0] = Point(389.62835648698, 647.8568549161259);
+ poly252.ps[1] = Point(389.62835648698, 707.8568549161259);
+ poly252.ps[2] = Point(333.62835648698, 707.8568549161259);
+ poly252.ps[3] = Point(333.62835648698, 647.8568549161259);
+ new ShapeRef(router, poly252, 252);
+
+ Polygon poly253(4);
+ poly253.ps[0] = Point(694.62835648798, 509.006854916126);
+ poly253.ps[1] = Point(694.62835648798, 569.006854916126);
+ poly253.ps[2] = Point(638.62835648798, 569.006854916126);
+ poly253.ps[3] = Point(638.62835648798, 509.006854916126);
+ new ShapeRef(router, poly253, 253);
+
+ Polygon poly254(4);
+ poly254.ps[0] = Point(176.62835648698, 814.8568549161259);
+ poly254.ps[1] = Point(176.62835648698, 874.8568549161259);
+ poly254.ps[2] = Point(120.62835648698, 874.8568549161259);
+ poly254.ps[3] = Point(120.62835648698, 814.8568549161259);
+ new ShapeRef(router, poly254, 254);
+
+ Polygon poly255(4);
+ poly255.ps[0] = Point(826.62835648798, 647.8568549161259);
+ poly255.ps[1] = Point(826.62835648798, 707.8568549161259);
+ poly255.ps[2] = Point(770.62835648798, 707.8568549161259);
+ poly255.ps[3] = Point(770.62835648798, 647.8568549161259);
+ new ShapeRef(router, poly255, 255);
+
+ Polygon poly256(4);
+ poly256.ps[0] = Point(826.62835648798, 769.8568549161259);
+ poly256.ps[1] = Point(826.62835648798, 829.8568549161259);
+ poly256.ps[2] = Point(770.62835648798, 829.8568549161259);
+ poly256.ps[3] = Point(770.62835648798, 769.8568549161259);
+ new ShapeRef(router, poly256, 256);
+
+ Polygon poly257(4);
+ poly257.ps[0] = Point(682.62835648798, 837.8568549161259);
+ poly257.ps[1] = Point(682.62835648798, 877.8568549161259);
+ poly257.ps[2] = Point(606.62835648798, 877.8568549161259);
+ poly257.ps[3] = Point(606.62835648798, 837.8568549161259);
+ new ShapeRef(router, poly257, 257);
+
+ Polygon poly258(4);
+ poly258.ps[0] = Point(129.62835648598, 951.8568549161259);
+ poly258.ps[1] = Point(129.62835648598, 1011.856854916126);
+ poly258.ps[2] = Point(73.62835648597996, 1011.856854916126);
+ poly258.ps[3] = Point(73.62835648597996, 951.8568549161259);
+ new ShapeRef(router, poly258, 258);
+
+ Polygon poly259(4);
+ poly259.ps[0] = Point(-64.87164351502003, 1174.856854916126);
+ poly259.ps[1] = Point(-64.87164351502003, 1234.856854916126);
+ poly259.ps[2] = Point(-120.87164351502, 1234.856854916126);
+ poly259.ps[3] = Point(-120.87164351502, 1174.856854916126);
+ new ShapeRef(router, poly259, 259);
+
+ Polygon poly260(4);
+ poly260.ps[0] = Point(-64.87164351502003, 1052.856854916126);
+ poly260.ps[1] = Point(-64.87164351502003, 1112.856854916126);
+ poly260.ps[2] = Point(-120.87164351502, 1112.856854916126);
+ poly260.ps[3] = Point(-120.87164351502, 1052.856854916126);
+ new ShapeRef(router, poly260, 260);
+
+ Polygon poly261(4);
+ poly261.ps[0] = Point(356.62835648698, 1052.856854916126);
+ poly261.ps[1] = Point(356.62835648698, 1112.856854916126);
+ poly261.ps[2] = Point(300.62835648698, 1112.856854916126);
+ poly261.ps[3] = Point(300.62835648698, 1052.856854916126);
+ new ShapeRef(router, poly261, 261);
+
+ Polygon poly262(4);
+ poly262.ps[0] = Point(873.62835648898, 1040.856854916126);
+ poly262.ps[1] = Point(873.62835648898, 1100.856854916126);
+ poly262.ps[2] = Point(817.62835648898, 1100.856854916126);
+ poly262.ps[3] = Point(817.62835648898, 1040.856854916126);
+ new ShapeRef(router, poly262, 262);
+
+ Polygon poly263(4);
+ poly263.ps[0] = Point(951.9140707746942, 866.8568549171259);
+ poly263.ps[1] = Point(951.9140707746942, 906.8568549171259);
+ poly263.ps[2] = Point(875.9140707746942, 906.8568549171259);
+ poly263.ps[3] = Point(875.9140707746942, 866.8568549171259);
+ new ShapeRef(router, poly263, 263);
+
+ Polygon poly264(4);
+ poly264.ps[0] = Point(1253.12835648898, 991.8568549161259);
+ poly264.ps[1] = Point(1253.12835648898, 1031.856854916126);
+ poly264.ps[2] = Point(1177.12835648898, 1031.856854916126);
+ poly264.ps[3] = Point(1177.12835648898, 991.8568549161259);
+ new ShapeRef(router, poly264, 264);
+
+ Polygon poly265(4);
+ poly265.ps[0] = Point(1253.12835648898, 1090.856854916126);
+ poly265.ps[1] = Point(1253.12835648898, 1130.856854916126);
+ poly265.ps[2] = Point(1177.12835648898, 1130.856854916126);
+ poly265.ps[3] = Point(1177.12835648898, 1090.856854916126);
+ new ShapeRef(router, poly265, 265);
+
+ Polygon poly266(4);
+ poly266.ps[0] = Point(1195.12835648898, 1186.856854916126);
+ poly266.ps[1] = Point(1195.12835648898, 1246.856854916126);
+ poly266.ps[2] = Point(1139.12835648898, 1246.856854916126);
+ poly266.ps[3] = Point(1139.12835648898, 1186.856854916126);
+ new ShapeRef(router, poly266, 266);
+
+ Polygon poly267(4);
+ poly267.ps[0] = Point(21.62835648497997, 1355.606854916126);
+ poly267.ps[1] = Point(21.62835648497997, 1395.606854916126);
+ poly267.ps[2] = Point(-54.37164351502003, 1395.606854916126);
+ poly267.ps[3] = Point(-54.37164351502003, 1355.606854916126);
+ new ShapeRef(router, poly267, 267);
+
+ Polygon poly268(4);
+ poly268.ps[0] = Point(637.62835648798, 1322.606854916126);
+ poly268.ps[1] = Point(637.62835648798, 1362.606854916126);
+ poly268.ps[2] = Point(561.62835648798, 1362.606854916126);
+ poly268.ps[3] = Point(561.62835648798, 1322.606854916126);
+ new ShapeRef(router, poly268, 268);
+
+ Polygon poly269(4);
+ poly269.ps[0] = Point(-473.87164351602, 1577.106854917126);
+ poly269.ps[1] = Point(-473.87164351602, 1637.106854917126);
+ poly269.ps[2] = Point(-529.87164351602, 1637.106854917126);
+ poly269.ps[3] = Point(-529.87164351602, 1577.106854917126);
+ new ShapeRef(router, poly269, 269);
+
+ Polygon poly270(4);
+ poly270.ps[0] = Point(-31.87164351502003, 1678.106854917126);
+ poly270.ps[1] = Point(-31.87164351502003, 1738.106854917126);
+ poly270.ps[2] = Point(-87.87164351502003, 1738.106854917126);
+ poly270.ps[3] = Point(-87.87164351502003, 1678.106854917126);
+ new ShapeRef(router, poly270, 270);
+
+ Polygon poly271(4);
+ poly271.ps[0] = Point(-31.87164351502003, 1481.106854917126);
+ poly271.ps[1] = Point(-31.87164351502003, 1541.106854917126);
+ poly271.ps[2] = Point(-87.87164351502003, 1541.106854917126);
+ poly271.ps[3] = Point(-87.87164351502003, 1481.106854917126);
+ new ShapeRef(router, poly271, 271);
+
+ Polygon poly272(4);
+ poly272.ps[0] = Point(-31.87164351502003, 1556.106854917126);
+ poly272.ps[1] = Point(-31.87164351502003, 1616.106854917126);
+ poly272.ps[2] = Point(-87.87164351502003, 1616.106854917126);
+ poly272.ps[3] = Point(-87.87164351502003, 1556.106854917126);
+ new ShapeRef(router, poly272, 272);
+
+ Polygon poly273(4);
+ poly273.ps[0] = Point(422.62835648698, 1678.106854917126);
+ poly273.ps[1] = Point(422.62835648698, 1738.106854917126);
+ poly273.ps[2] = Point(366.62835648698, 1738.106854917126);
+ poly273.ps[3] = Point(366.62835648698, 1678.106854917126);
+ new ShapeRef(router, poly273, 273);
+
+ Polygon poly274(4);
+ poly274.ps[0] = Point(422.62835648698, 1556.106854917126);
+ poly274.ps[1] = Point(422.62835648698, 1616.106854917126);
+ poly274.ps[2] = Point(366.62835648698, 1616.106854917126);
+ poly274.ps[3] = Point(366.62835648698, 1556.106854917126);
+ new ShapeRef(router, poly274, 274);
+
+ Polygon poly275(4);
+ poly275.ps[0] = Point(660.9873402531949, 1556.106854917126);
+ poly275.ps[1] = Point(660.9873402531949, 1616.106854917126);
+ poly275.ps[2] = Point(604.9873402531949, 1616.106854917126);
+ poly275.ps[3] = Point(604.9873402531949, 1556.106854917126);
+ new ShapeRef(router, poly275, 275);
+
+ Polygon poly276(4);
+ poly276.ps[0] = Point(660.9873402531949, 1678.106854917126);
+ poly276.ps[1] = Point(660.9873402531949, 1738.106854917126);
+ poly276.ps[2] = Point(604.9873402531949, 1738.106854917126);
+ poly276.ps[3] = Point(604.9873402531949, 1678.106854917126);
+ new ShapeRef(router, poly276, 276);
+
+ Polygon poly277(4);
+ poly277.ps[0] = Point(1195.12835648898, 1497.106854916126);
+ poly277.ps[1] = Point(1195.12835648898, 1557.106854916126);
+ poly277.ps[2] = Point(1139.12835648898, 1557.106854916126);
+ poly277.ps[3] = Point(1139.12835648898, 1497.106854916126);
+ new ShapeRef(router, poly277, 277);
+
+ Polygon poly278(4);
+ poly278.ps[0] = Point(1195.12835648898, 1636.773521583792);
+ poly278.ps[1] = Point(1195.12835648898, 1696.773521583792);
+ poly278.ps[2] = Point(1139.12835648898, 1696.773521583792);
+ poly278.ps[3] = Point(1139.12835648898, 1636.773521583792);
+ new ShapeRef(router, poly278, 278);
+
+ Polygon poly279(4);
+ poly279.ps[0] = Point(1358.12835648898, 1363.106854916126);
+ poly279.ps[1] = Point(1358.12835648898, 1423.106854916126);
+ poly279.ps[2] = Point(1302.12835648898, 1423.106854916126);
+ poly279.ps[3] = Point(1302.12835648898, 1363.106854916126);
+ new ShapeRef(router, poly279, 279);
+
+ Polygon poly280(4);
+ poly280.ps[0] = Point(1655.12835648998, 1239.606854916126);
+ poly280.ps[1] = Point(1655.12835648998, 1299.606854916126);
+ poly280.ps[2] = Point(1599.12835648998, 1299.606854916126);
+ poly280.ps[3] = Point(1599.12835648998, 1239.606854916126);
+ new ShapeRef(router, poly280, 280);
+
+ Polygon poly281(4);
+ poly281.ps[0] = Point(1622.12835648998, 1556.106854917126);
+ poly281.ps[1] = Point(1622.12835648998, 1616.106854917126);
+ poly281.ps[2] = Point(1566.12835648998, 1616.106854917126);
+ poly281.ps[3] = Point(1566.12835648998, 1556.106854917126);
+ new ShapeRef(router, poly281, 281);
+
+ Polygon poly282(4);
+ poly282.ps[0] = Point(1622.12835648998, 1678.106854917126);
+ poly282.ps[1] = Point(1622.12835648998, 1738.106854917126);
+ poly282.ps[2] = Point(1566.12835648998, 1738.106854917126);
+ poly282.ps[3] = Point(1566.12835648998, 1678.106854917126);
+ new ShapeRef(router, poly282, 282);
+
+ Polygon poly283(4);
+ poly283.ps[0] = Point(1798.12835649098, 1239.606854916126);
+ poly283.ps[1] = Point(1798.12835649098, 1299.606854916126);
+ poly283.ps[2] = Point(1742.12835649098, 1299.606854916126);
+ poly283.ps[3] = Point(1742.12835649098, 1239.606854916126);
+ new ShapeRef(router, poly283, 283);
+
+ Polygon poly284(4);
+ poly284.ps[0] = Point(1798.12835649098, 1577.106854917126);
+ poly284.ps[1] = Point(1798.12835649098, 1637.106854917126);
+ poly284.ps[2] = Point(1742.12835649098, 1637.106854917126);
+ poly284.ps[3] = Point(1742.12835649098, 1577.106854917126);
+ new ShapeRef(router, poly284, 284);
+
+ Polygon poly285(4);
+ poly285.ps[0] = Point(1971.12835649298, 1577.106854917126);
+ poly285.ps[1] = Point(1971.12835649298, 1637.106854917126);
+ poly285.ps[2] = Point(1915.12835649298, 1637.106854917126);
+ poly285.ps[3] = Point(1915.12835649298, 1577.106854917126);
+ new ShapeRef(router, poly285, 285);
+
+ Polygon poly286(4);
+ poly286.ps[0] = Point(-440.87164351602, -706.9812403239691);
+ poly286.ps[1] = Point(-440.87164351602, -646.9812403239691);
+ poly286.ps[2] = Point(-496.87164351602, -646.9812403239691);
+ poly286.ps[3] = Point(-496.87164351602, -706.9812403239691);
+ new ShapeRef(router, poly286, 286);
+
+ Polygon poly287(4);
+ poly287.ps[0] = Point(389.62835648698, 769.8568549161259);
+ poly287.ps[1] = Point(389.62835648698, 829.8568549161259);
+ poly287.ps[2] = Point(333.62835648698, 829.8568549161259);
+ poly287.ps[3] = Point(333.62835648698, 769.8568549161259);
+ new ShapeRef(router, poly287, 287);
+
+ Polygon poly288(4);
+ poly288.ps[0] = Point(356.62835648698, 1174.856854916126);
+ poly288.ps[1] = Point(356.62835648698, 1234.856854916126);
+ poly288.ps[2] = Point(300.62835648698, 1234.856854916126);
+ poly288.ps[3] = Point(300.62835648698, 1174.856854916126);
+ new ShapeRef(router, poly288, 288);
+
+ Polygon poly289(4);
+ poly289.ps[0] = Point(1089.914070774694, 866.8568549171259);
+ poly289.ps[1] = Point(1089.914070774694, 906.8568549171259);
+ poly289.ps[2] = Point(1013.914070774694, 906.8568549171259);
+ poly289.ps[3] = Point(1013.914070774694, 866.8568549171259);
+ new ShapeRef(router, poly289, 289);
+
+ Polygon poly290(4);
+ poly290.ps[0] = Point(1655.12835648998, -688.4098117525407);
+ poly290.ps[1] = Point(1655.12835648998, -628.4098117525407);
+ poly290.ps[2] = Point(1599.12835648998, -628.4098117525407);
+ poly290.ps[3] = Point(1599.12835648998, -688.4098117525407);
+ new ShapeRef(router, poly290, 290);
+
+ Polygon poly291(4);
+ poly291.ps[0] = Point(1831.12835649098, -628.5348117525407);
+ poly291.ps[1] = Point(1831.12835649098, -568.5348117525407);
+ poly291.ps[2] = Point(1775.12835649098, -568.5348117525407);
+ poly291.ps[3] = Point(1775.12835649098, -628.5348117525407);
+ new ShapeRef(router, poly291, 291);
+
+ Polygon poly292(4);
+ poly292.ps[0] = Point(488.62835648698, -807.9812403239691);
+ poly292.ps[1] = Point(488.62835648698, -747.9812403239691);
+ poly292.ps[2] = Point(432.62835648698, -747.9812403239691);
+ poly292.ps[3] = Point(432.62835648698, -807.9812403239691);
+ new ShapeRef(router, poly292, 292);
+
+ Polygon poly293(4);
+ poly293.ps[0] = Point(760.62835648798, -877.4098117525407);
+ poly293.ps[1] = Point(760.62835648798, -817.4098117525407);
+ poly293.ps[2] = Point(704.62835648798, -817.4098117525407);
+ poly293.ps[3] = Point(704.62835648798, -877.4098117525407);
+ new ShapeRef(router, poly293, 293);
+
+ Polygon poly294(4);
+ poly294.ps[0] = Point(760.62835648798, -751.4098117525407);
+ poly294.ps[1] = Point(760.62835648798, -691.4098117525407);
+ poly294.ps[2] = Point(704.62835648798, -691.4098117525407);
+ poly294.ps[3] = Point(704.62835648798, -751.4098117525407);
+ new ShapeRef(router, poly294, 294);
+
+ Polygon poly295(4);
+ poly295.ps[0] = Point(1068.914070774694, -484.4098117525406);
+ poly295.ps[1] = Point(1068.914070774694, -444.4098117525406);
+ poly295.ps[2] = Point(992.9140707746942, -444.4098117525406);
+ poly295.ps[3] = Point(992.9140707746942, -484.4098117525406);
+ new ShapeRef(router, poly295, 295);
+
+ Polygon poly296(4);
+ poly296.ps[0] = Point(1259.12835648898, -628.5348117525407);
+ poly296.ps[1] = Point(1259.12835648898, -568.5348117525407);
+ poly296.ps[2] = Point(1203.12835648898, -568.5348117525407);
+ poly296.ps[3] = Point(1203.12835648898, -628.5348117525407);
+ new ShapeRef(router, poly296, 296);
+
+ Polygon poly297(4);
+ poly297.ps[0] = Point(209.62835648698, -116.4098117515406);
+ poly297.ps[1] = Point(209.62835648698, -56.40981175154064);
+ poly297.ps[2] = Point(153.62835648698, -56.40981175154064);
+ poly297.ps[3] = Point(153.62835648698, -116.4098117515406);
+ new ShapeRef(router, poly297, 297);
+
+ Polygon poly298(4);
+ poly298.ps[0] = Point(694.62835648798, -90.40981175154064);
+ poly298.ps[1] = Point(694.62835648798, -30.40981175154064);
+ poly298.ps[2] = Point(638.62835648798, -30.40981175154064);
+ poly298.ps[3] = Point(638.62835648798, -90.40981175154064);
+ new ShapeRef(router, poly298, 298);
+
+ Polygon poly299(4);
+ poly299.ps[0] = Point(939.62835648898, 351.7568549161261);
+ poly299.ps[1] = Point(939.62835648898, 411.7568549161261);
+ poly299.ps[2] = Point(883.62835648898, 411.7568549161261);
+ poly299.ps[3] = Point(883.62835648898, 351.7568549161261);
+ new ShapeRef(router, poly299, 299);
+
+ Polygon poly300(4);
+ poly300.ps[0] = Point(521.62835648698, 351.7568549161261);
+ poly300.ps[1] = Point(521.62835648698, 411.7568549161261);
+ poly300.ps[2] = Point(465.62835648698, 411.7568549161261);
+ poly300.ps[3] = Point(465.62835648698, 351.7568549161261);
+ new ShapeRef(router, poly300, 300);
+
+ Polygon poly301(4);
+ poly301.ps[0] = Point(129.62835648598, 1073.856854916126);
+ poly301.ps[1] = Point(129.62835648598, 1133.856854916126);
+ poly301.ps[2] = Point(73.62835648597996, 1133.856854916126);
+ poly301.ps[3] = Point(73.62835648597996, 1073.856854916126);
+ new ShapeRef(router, poly301, 301);
+
+ Polygon poly302(4);
+ poly302.ps[0] = Point(59.62835648497997, -628.5348117525407);
+ poly302.ps[1] = Point(59.62835648497997, -568.5348117525407);
+ poly302.ps[2] = Point(3.628356484979975, -568.5348117525407);
+ poly302.ps[3] = Point(3.628356484979975, -628.5348117525407);
+ new ShapeRef(router, poly302, 302);
+
+ Polygon poly303(4);
+ poly303.ps[0] = Point(1586.12835648898, 565.6568549161261);
+ poly303.ps[1] = Point(1586.12835648898, 625.6568549161261);
+ poly303.ps[2] = Point(1530.12835648898, 625.6568549161261);
+ poly303.ps[3] = Point(1530.12835648898, 565.6568549161261);
+ new ShapeRef(router, poly303, 303);
+
+ Polygon poly304(4);
+ poly304.ps[0] = Point(1765.12835649098, 565.6568549161261);
+ poly304.ps[1] = Point(1765.12835649098, 625.6568549161261);
+ poly304.ps[2] = Point(1709.12835649098, 625.6568549161261);
+ poly304.ps[3] = Point(1709.12835649098, 565.6568549161261);
+ new ShapeRef(router, poly304, 304);
+
+ Polygon poly305(4);
+ poly305.ps[0] = Point(2261.795023162646, 544.6568549161261);
+ poly305.ps[1] = Point(2261.795023162646, 604.6568549161261);
+ poly305.ps[2] = Point(2205.795023162646, 604.6568549161261);
+ poly305.ps[3] = Point(2205.795023162646, 544.6568549161261);
+ new ShapeRef(router, poly305, 305);
+
+ Polygon poly306(4);
+ poly306.ps[0] = Point(2111.795023160646, 565.6568549161261);
+ poly306.ps[1] = Point(2111.795023160646, 625.6568549161261);
+ poly306.ps[2] = Point(2055.795023160646, 625.6568549161261);
+ poly306.ps[3] = Point(2055.795023160646, 565.6568549161261);
+ new ShapeRef(router, poly306, 306);
+
+ Polygon poly307(4);
+ poly307.ps[0] = Point(2261.795023162646, 666.6568549161261);
+ poly307.ps[1] = Point(2261.795023162646, 726.6568549161261);
+ poly307.ps[2] = Point(2205.795023162646, 726.6568549161261);
+ poly307.ps[3] = Point(2205.795023162646, 666.6568549161261);
+ new ShapeRef(router, poly307, 307);
+
+ Polygon poly308(4);
+ poly308.ps[0] = Point(1765.12835649098, 291.2568549161261);
+ poly308.ps[1] = Point(1765.12835649098, 351.2568549161261);
+ poly308.ps[2] = Point(1709.12835649098, 351.2568549161261);
+ poly308.ps[3] = Point(1709.12835649098, 291.2568549161261);
+ new ShapeRef(router, poly308, 308);
+
+ Polygon poly309(4);
+ poly309.ps[0] = Point(1655.12835648998, -567.4098117525407);
+ poly309.ps[1] = Point(1655.12835648998, -507.4098117525407);
+ poly309.ps[2] = Point(1599.12835648998, -507.4098117525407);
+ poly309.ps[3] = Point(1599.12835648998, -567.4098117525407);
+ new ShapeRef(router, poly309, 309);
+
+ Polygon poly310(4);
+ poly310.ps[0] = Point(-657.12164351602, -896.9098117525407);
+ poly310.ps[1] = Point(-657.12164351602, -856.9098117525407);
+ poly310.ps[2] = Point(-717.12164351602, -856.9098117525407);
+ poly310.ps[3] = Point(-717.12164351602, -896.9098117525407);
+ new ShapeRef(router, poly310, 310);
+
+ Polygon poly311(4);
+ poly311.ps[0] = Point(-985.62164351602, 275.7568549161261);
+ poly311.ps[1] = Point(-985.62164351602, 335.7568549161261);
+ poly311.ps[2] = Point(-1025.62164351602, 335.7568549161261);
+ poly311.ps[3] = Point(-1025.62164351602, 275.7568549161261);
+ new ShapeRef(router, poly311, 311);
+
+ Polygon poly312(4);
+ poly312.ps[0] = Point(2090.795023161646, -389.9098117525406);
+ poly312.ps[1] = Point(2090.795023161646, -349.9098117525406);
+ poly312.ps[2] = Point(2030.795023161646, -349.9098117525406);
+ poly312.ps[3] = Point(2030.795023161646, -389.9098117525406);
+ new ShapeRef(router, poly312, 312);
+
+ Polygon poly313(4);
+ poly313.ps[0] = Point(2090.295023161646, 1555.606854916126);
+ poly313.ps[1] = Point(2090.295023161646, 1595.606854916126);
+ poly313.ps[2] = Point(2030.295023161646, 1595.606854916126);
+ poly313.ps[3] = Point(2030.295023161646, 1555.606854916126);
+ new ShapeRef(router, poly313, 313);
+
+ Polygon poly314(4);
+ poly314.ps[0] = Point(-1089.62164351702, -157.4098117515406);
+ poly314.ps[1] = Point(-1089.62164351702, -97.40981175154064);
+ poly314.ps[2] = Point(-1129.62164351702, -97.40981175154064);
+ poly314.ps[3] = Point(-1129.62164351702, -157.4098117515406);
+ new ShapeRef(router, poly314, 314);
+#endif
+
+ Polygon poly315(4);
+ poly315.ps[0] = Point(-430.97164351602, -833.9812403239691);
+ poly315.ps[1] = Point(-430.97164351602, -716.9812403239691);
+ poly315.ps[2] = Point(-506.77164351602, -716.9812403239691);
+ poly315.ps[3] = Point(-506.77164351602, -833.9812403239691);
+ new ShapeRef(router, poly315, 315);
+
+#ifdef REST
+ Polygon poly316(4);
+ poly316.ps[0] = Point(134.52835648598, -394.4098117515406);
+ poly316.ps[1] = Point(134.52835648598, -202.4098117515406);
+ poly316.ps[2] = Point(58.72835648597997, -202.4098117515406);
+ poly316.ps[3] = Point(58.72835648597997, -394.4098117515406);
+ new ShapeRef(router, poly316, 316);
+
+ Polygon poly317(4);
+ poly317.ps[0] = Point(-298.87164351602, -189.3098117515406);
+ poly317.ps[1] = Point(-298.87164351602, -129.5098117515406);
+ poly317.ps[2] = Point(-340.87164351602, -129.5098117515406);
+ poly317.ps[3] = Point(-340.87164351602, -189.3098117515406);
+ new ShapeRef(router, poly317, 317);
+
+ Polygon poly318(4);
+ poly318.ps[0] = Point(465.5283564869799, -469.4098117515406);
+ poly318.ps[1] = Point(465.5283564869799, -202.4098117515406);
+ poly318.ps[2] = Point(389.72835648698, -202.4098117515406);
+ poly318.ps[3] = Point(389.72835648698, -469.4098117515406);
+ new ShapeRef(router, poly318, 318);
+
+ Polygon poly319(4);
+ poly319.ps[0] = Point(670.8873402531949, -319.4098117515406);
+ poly319.ps[1] = Point(670.8873402531949, -277.4098117515406);
+ poly319.ps[2] = Point(595.087340253195, -277.4098117515406);
+ poly319.ps[3] = Point(595.087340253195, -319.4098117515406);
+ new ShapeRef(router, poly319, 319);
+
+ Polygon poly320(4);
+ poly320.ps[0] = Point(1100.814070775694, -319.4098117515406);
+ poly320.ps[1] = Point(1100.814070775694, -277.4098117515406);
+ poly320.ps[2] = Point(1025.014070775694, -277.4098117515406);
+ poly320.ps[3] = Point(1025.014070775694, -319.4098117515406);
+ new ShapeRef(router, poly320, 320);
+
+ Polygon poly321(4);
+ poly321.ps[0] = Point(1632.02835648998, -319.4098117515406);
+ poly321.ps[1] = Point(1632.02835648998, -277.4098117515406);
+ poly321.ps[2] = Point(1556.22835648998, -277.4098117515406);
+ poly321.ps[3] = Point(1556.22835648998, -319.4098117515406);
+ new ShapeRef(router, poly321, 321);
+
+ Polygon poly322(4);
+ poly322.ps[0] = Point(11.02835648497997, 45.25685491512604);
+ poly322.ps[1] = Point(11.02835648497997, 87.25685491512604);
+ poly322.ps[2] = Point(-64.77164351502003, 87.25685491512604);
+ poly322.ps[3] = Point(-64.77164351502003, 45.25685491512604);
+ new ShapeRef(router, poly322, 322);
+
+ Polygon poly323(4);
+ poly323.ps[0] = Point(-21.97164351502003, 1551.106854917126);
+ poly323.ps[1] = Point(-21.97164351502003, 1668.106854917126);
+ poly323.ps[2] = Point(-97.77164351502003, 1668.106854917126);
+ poly323.ps[3] = Point(-97.77164351502003, 1551.106854917126);
+ new ShapeRef(router, poly323, 323);
+
+ Polygon poly324(4);
+ poly324.ps[0] = Point(432.5283564869799, 1626.106854917126);
+ poly324.ps[1] = Point(432.5283564869799, 1668.106854917126);
+ poly324.ps[2] = Point(356.72835648698, 1668.106854917126);
+ poly324.ps[3] = Point(356.72835648698, 1626.106854917126);
+ new ShapeRef(router, poly324, 324);
+
+ Polygon poly325(4);
+ poly325.ps[0] = Point(551.62835648798, 1312.706854916126);
+ poly325.ps[1] = Point(551.62835648798, 1372.506854916126);
+ poly325.ps[2] = Point(509.62835648798, 1372.506854916126);
+ poly325.ps[3] = Point(509.62835648798, 1312.706854916126);
+ new ShapeRef(router, poly325, 325);
+
+ Polygon poly326(4);
+ poly326.ps[0] = Point(670.8873402531949, 1626.106854917126);
+ poly326.ps[1] = Point(670.8873402531949, 1668.106854917126);
+ poly326.ps[2] = Point(595.087340253195, 1668.106854917126);
+ poly326.ps[3] = Point(595.087340253195, 1626.106854917126);
+ new ShapeRef(router, poly326, 326);
+
+ Polygon poly327(4);
+ poly327.ps[0] = Point(1632.02835648998, 1626.106854917126);
+ poly327.ps[1] = Point(1632.02835648998, 1668.106854917126);
+ poly327.ps[2] = Point(1556.22835648998, 1668.106854917126);
+ poly327.ps[3] = Point(1556.22835648998, 1626.106854917126);
+ new ShapeRef(router, poly327, 327);
+
+ Polygon poly328(4);
+ poly328.ps[0] = Point(1139.02835648898, 45.25685491512604);
+ poly328.ps[1] = Point(1139.02835648898, 87.25685491512604);
+ poly328.ps[2] = Point(1063.22835648898, 87.25685491512604);
+ poly328.ps[3] = Point(1063.22835648898, 45.25685491512604);
+ new ShapeRef(router, poly328, 328);
+
+ Polygon poly329(4);
+ poly329.ps[0] = Point(803.52835648798, 45.25685491512604);
+ poly329.ps[1] = Point(803.52835648798, 87.25685491512604);
+ poly329.ps[2] = Point(727.72835648798, 87.25685491512604);
+ poly329.ps[3] = Point(727.72835648798, 45.25685491512604);
+ new ShapeRef(router, poly329, 329);
+
+ Polygon poly330(4);
+ poly330.ps[0] = Point(488.5283564869799, 45.25685491512604);
+ poly330.ps[1] = Point(488.5283564869799, 87.25685491512604);
+ poly330.ps[2] = Point(412.72835648698, 87.25685491512604);
+ poly330.ps[3] = Point(412.72835648698, 45.25685491512604);
+ new ShapeRef(router, poly330, 330);
+
+ Polygon poly331(4);
+ poly331.ps[0] = Point(-54.97164351502003, 1122.856854916126);
+ poly331.ps[1] = Point(-54.97164351502003, 1164.856854916126);
+ poly331.ps[2] = Point(-130.77164351502, 1164.856854916126);
+ poly331.ps[3] = Point(-130.77164351502, 1122.856854916126);
+ new ShapeRef(router, poly331, 331);
+
+ Polygon poly332(4);
+ poly332.ps[0] = Point(139.52835648598, 1021.856854916126);
+ poly332.ps[1] = Point(139.52835648598, 1063.856854916126);
+ poly332.ps[2] = Point(63.72835648597997, 1063.856854916126);
+ poly332.ps[3] = Point(63.72835648597997, 1021.856854916126);
+ new ShapeRef(router, poly332, 332);
+
+ Polygon poly333(4);
+ poly333.ps[0] = Point(366.5283564869799, 1122.856854916126);
+ poly333.ps[1] = Point(366.5283564869799, 1164.856854916126);
+ poly333.ps[2] = Point(290.72835648698, 1164.856854916126);
+ poly333.ps[3] = Point(290.72835648698, 1122.856854916126);
+ new ShapeRef(router, poly333, 333);
+
+ Polygon poly334(4);
+ poly334.ps[0] = Point(1003.914070774694, 856.956854917126);
+ poly334.ps[1] = Point(1003.914070774694, 916.7568549171259);
+ poly334.ps[2] = Point(961.9140707746942, 916.7568549171259);
+ poly334.ps[3] = Point(961.9140707746942, 856.956854917126);
+ new ShapeRef(router, poly334, 334);
+
+ Polygon poly335(4);
+ poly335.ps[0] = Point(836.52835648798, 717.8568549161259);
+ poly335.ps[1] = Point(836.52835648798, 759.8568549161259);
+ poly335.ps[2] = Point(760.72835648798, 759.8568549161259);
+ poly335.ps[3] = Point(760.72835648798, 717.8568549161259);
+ new ShapeRef(router, poly335, 335);
+
+ Polygon poly336(4);
+ poly336.ps[0] = Point(399.5283564869799, 717.8568549161259);
+ poly336.ps[1] = Point(399.5283564869799, 759.8568549161259);
+ poly336.ps[2] = Point(323.72835648698, 759.8568549161259);
+ poly336.ps[3] = Point(323.72835648698, 717.8568549161259);
+ new ShapeRef(router, poly336, 336);
+
+ Polygon poly337(4);
+ poly337.ps[0] = Point(2271.695023162647, 614.6568549161261);
+ poly337.ps[1] = Point(2271.695023162647, 656.6568549161261);
+ poly337.ps[2] = Point(2195.895023162646, 656.6568549161261);
+ poly337.ps[3] = Point(2195.895023162646, 614.6568549161261);
+ new ShapeRef(router, poly337, 337);
+
+ ConnRef *connRef338 = new ConnRef(router, 338);
+ ConnEnd srcPt338(Point(181.62835648698, 1360.606854916126), 1);
+ connRef338->setSourceEndpoint(srcPt338);
+ ConnEnd dstPt338(Point(115.62835648698, 1254.856854916126), 15);
+ connRef338->setDestEndpoint(dstPt338);
+ connRef338->setRoutingType((ConnType)2);
+
+ ConnRef *connRef339 = new ConnRef(router, 339);
+ ConnEnd srcPt339(Point(181.62835648698, 1360.606854916126), 1);
+ connRef339->setSourceEndpoint(srcPt339);
+ ConnEnd dstPt339(Point(181.62835648698, 1143.856854916126), 15);
+ connRef339->setDestEndpoint(dstPt339);
+ connRef339->setRoutingType((ConnType)2);
+
+ ConnRef *connRef340 = new ConnRef(router, 340);
+ ConnEnd srcPt340(Point(1873.12835649198, 33.25685491512604), 15);
+ connRef340->setSourceEndpoint(srcPt340);
+ ConnEnd dstPt340(Point(1928.12835649298, 33.25685491512604), 4);
+ connRef340->setDestEndpoint(dstPt340);
+ connRef340->setRoutingType((ConnType)2);
+
+ ConnRef *connRef341 = new ConnRef(router, 341);
+ ConnEnd srcPt341(Point(1785.12835649098, 33.25685491512604), 8);
+ connRef341->setSourceEndpoint(srcPt341);
+ ConnEnd dstPt341(Point(1873.12835649198, 33.25685491512604), 15);
+ connRef341->setDestEndpoint(dstPt341);
+ connRef341->setRoutingType((ConnType)2);
+
+ ConnRef *connRef342 = new ConnRef(router, 342);
+ ConnEnd srcPt342(Point(1958.12835649298, 33.25685491512604), 8);
+ connRef342->setSourceEndpoint(srcPt342);
+ ConnEnd dstPt342(Point(2046.795023159646, 33.25685491512604), 15);
+ connRef342->setDestEndpoint(dstPt342);
+ connRef342->setRoutingType((ConnType)2);
+
+ ConnRef *connRef343 = new ConnRef(router, 343);
+ ConnEnd srcPt343(Point(1958.12835649298, 33.25685491512604), 8);
+ connRef343->setSourceEndpoint(srcPt343);
+ ConnEnd dstPt343(Point(1980.795023159646, 99.25685491512604), 15);
+ connRef343->setDestEndpoint(dstPt343);
+ connRef343->setRoutingType((ConnType)2);
+
+ ConnRef *connRef344 = new ConnRef(router, 344);
+ ConnEnd srcPt344(Point(412.62835648698, -319.4098117515406), 4);
+ connRef344->setSourceEndpoint(srcPt344);
+ ConnEnd dstPt344(Point(181.62835648698, -298.4098117515406), 15);
+ connRef344->setDestEndpoint(dstPt344);
+ connRef344->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints344(1);
+ checkpoints344[0] = Checkpoint(Point(389.62835648698, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef344->setRoutingCheckpoints(checkpoints344);
+
+ ConnRef *connRef345 = new ConnRef(router, 345);
+ ConnEnd srcPt345(Point(442.62835648698, -319.4098117515406), 8);
+ connRef345->setSourceEndpoint(srcPt345);
+ ConnEnd dstPt345(Point(530.62835648798, -298.4098117515406), 15);
+ connRef345->setDestEndpoint(dstPt345);
+ connRef345->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints345(1);
+ checkpoints345[0] = Checkpoint(Point(465.62835648698, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef345->setRoutingCheckpoints(checkpoints345);
+
+ ConnRef *connRef346 = new ConnRef(router, 346);
+ ConnEnd srcPt346(Point(46.62835648497997, 945.8568549161259), 8);
+ connRef346->setSourceEndpoint(srcPt346);
+ ConnEnd dstPt346(Point(530.62835648798, 1143.856854916126), 15);
+ connRef346->setDestEndpoint(dstPt346);
+ connRef346->setRoutingType((ConnType)2);
+
+ ConnRef *connRef347 = new ConnRef(router, 347);
+ ConnEnd srcPt347(Point(-319.87164351602, 738.8568549161259), 15);
+ connRef347->setSourceEndpoint(srcPt347);
+ ConnEnd dstPt347(Point(16.62835648497997, 945.8568549161259), 4);
+ connRef347->setDestEndpoint(dstPt347);
+ connRef347->setRoutingType((ConnType)2);
+
+ ConnRef *connRef348 = new ConnRef(router, 348);
+ ConnEnd srcPt348(Point(509.62835648798, 1357.606854916126), 2);
+ connRef348->setSourceEndpoint(srcPt348);
+ ConnEnd dstPt348(Point(530.62835648798, 1647.106854917126), 15);
+ connRef348->setDestEndpoint(dstPt348);
+ connRef348->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints348(1);
+ checkpoints348[0] = Checkpoint(Point(530.62835648798, 1372.606854916126), (ConnDirFlags) 15, (ConnDirFlags) 1);
+ connRef348->setRoutingCheckpoints(checkpoints348);
+
+ ConnRef *connRef349 = new ConnRef(router, 349);
+ ConnEnd srcPt349(Point(509.62835648798, 1327.606854916126), 1);
+ connRef349->setSourceEndpoint(srcPt349);
+ ConnEnd dstPt349(Point(530.62835648798, 1143.856854916126), 15);
+ connRef349->setDestEndpoint(dstPt349);
+ connRef349->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints349(1);
+ checkpoints349[0] = Checkpoint(Point(530.62835648798, 1312.606854916126), (ConnDirFlags) 15, (ConnDirFlags) 2);
+ connRef349->setRoutingCheckpoints(checkpoints349);
+
+ ConnRef *connRef350 = new ConnRef(router, 350);
+ ConnEnd srcPt350(Point(-1006.12164351602, -126.4098117515406), 15);
+ connRef350->setSourceEndpoint(srcPt350);
+ ConnEnd dstPt350(Point(-1006.12164351602, -250.4098117515406), 2);
+ connRef350->setDestEndpoint(dstPt350);
+ connRef350->setRoutingType((ConnType)2);
+
+ ConnRef *connRef351 = new ConnRef(router, 351);
+ ConnEnd srcPt351(Point(-1006.12164351602, -280.4098117515406), 1);
+ connRef351->setSourceEndpoint(srcPt351);
+ ConnEnd dstPt351(Point(-1006.12164351602, -431.4098117525406), 15);
+ connRef351->setDestEndpoint(dstPt351);
+ connRef351->setRoutingType((ConnType)2);
+
+ ConnRef *connRef352 = new ConnRef(router, 352);
+ ConnEnd srcPt352(Point(-1006.12164351602, -512.4098117525407), 1);
+ connRef352->setSourceEndpoint(srcPt352);
+ ConnEnd dstPt352(Point(-1006.12164351602, -737.9812403239691), 15);
+ connRef352->setDestEndpoint(dstPt352);
+ connRef352->setRoutingType((ConnType)2);
+
+ ConnRef *connRef353 = new ConnRef(router, 353);
+ ConnEnd srcPt353(Point(-1006.12164351602, -431.4098117525406), 15);
+ connRef353->setSourceEndpoint(srcPt353);
+ ConnEnd dstPt353(Point(-1006.12164351602, -482.4098117525407), 2);
+ connRef353->setDestEndpoint(dstPt353);
+ connRef353->setRoutingType((ConnType)2);
+
+ ConnRef *connRef354 = new ConnRef(router, 354);
+ ConnEnd srcPt354(Point(-823.12164351602, -737.9812403239691), 4);
+ connRef354->setSourceEndpoint(srcPt354);
+ ConnEnd dstPt354(Point(-1006.12164351602, -737.9812403239691), 15);
+ connRef354->setDestEndpoint(dstPt354);
+ connRef354->setRoutingType((ConnType)2);
+
+ ConnRef *connRef355 = new ConnRef(router, 355);
+ ConnEnd srcPt355(Point(-695.12164351602, -737.9812403239691), 15);
+ connRef355->setSourceEndpoint(srcPt355);
+ ConnEnd dstPt355(Point(-793.12164351602, -737.9812403239691), 8);
+ connRef355->setDestEndpoint(dstPt355);
+ connRef355->setRoutingType((ConnType)2);
+
+ ConnRef *connRef356 = new ConnRef(router, 356);
+ ConnEnd srcPt356(Point(-453.87164351602, -833.9812403239691), 8);
+ connRef356->setSourceEndpoint(srcPt356);
+ ConnEnd dstPt356(Point(-226.87164351502, -737.9812403239691), 15);
+ connRef356->setDestEndpoint(dstPt356);
+ connRef356->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints356(1);
+ checkpoints356[0] = Checkpoint(Point(-430.87164351602, -737.9812403239691), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef356->setRoutingCheckpoints(checkpoints356);
+
+ ConnRef *connRef357 = new ConnRef(router, 357);
+ ConnEnd srcPt357(Point(-453.87164351602, -758.9812403239691), 8);
+ connRef357->setSourceEndpoint(srcPt357);
+ ConnEnd dstPt357(Point(-226.87164351502, -737.9812403239691), 15);
+ connRef357->setDestEndpoint(dstPt357);
+ connRef357->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints357(1);
+ checkpoints357[0] = Checkpoint(Point(-430.87164351602, -737.9812403239691), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef357->setRoutingCheckpoints(checkpoints357);
+
+ ConnRef *connRef358 = new ConnRef(router, 358);
+ ConnEnd srcPt358(Point(100.62835648698, -737.9812403239691), 4);
+ connRef358->setSourceEndpoint(srcPt358);
+ ConnEnd dstPt358(Point(-125.87164351502, -877.4098117525407), 15);
+ connRef358->setDestEndpoint(dstPt358);
+ connRef358->setRoutingType((ConnType)2);
+
+ ConnRef *connRef359 = new ConnRef(router, 359);
+ ConnEnd srcPt359(Point(262.62835648698, -737.9812403239691), 15);
+ connRef359->setSourceEndpoint(srcPt359);
+ ConnEnd dstPt359(Point(130.62835648698, -737.9812403239691), 8);
+ connRef359->setDestEndpoint(dstPt359);
+ connRef359->setRoutingType((ConnType)2);
+
+ ConnRef *connRef360 = new ConnRef(router, 360);
+ ConnEnd srcPt360(Point(100.62835648698, -737.9812403239691), 4);
+ connRef360->setSourceEndpoint(srcPt360);
+ ConnEnd dstPt360(Point(-226.87164351502, -737.9812403239691), 15);
+ connRef360->setDestEndpoint(dstPt360);
+ connRef360->setRoutingType((ConnType)2);
+
+ ConnRef *connRef361 = new ConnRef(router, 361);
+ ConnEnd srcPt361(Point(-486.87164351602, -497.4098117525407), 8);
+ connRef361->setSourceEndpoint(srcPt361);
+ ConnEnd dstPt361(Point(181.62835648698, -298.4098117515406), 15);
+ connRef361->setDestEndpoint(dstPt361);
+ connRef361->setRoutingType((ConnType)2);
+
+ ConnRef *connRef362 = new ConnRef(router, 362);
+ ConnEnd srcPt362(Point(-695.12164351602, 66.25685491512604), 15);
+ connRef362->setSourceEndpoint(srcPt362);
+ ConnEnd dstPt362(Point(-516.87164351602, -497.4098117525407), 4);
+ connRef362->setDestEndpoint(dstPt362);
+ connRef362->setRoutingType((ConnType)2);
+
+ ConnRef *connRef363 = new ConnRef(router, 363);
+ ConnEnd srcPt363(Point(-319.87164351602, -298.4098117515406), 15);
+ connRef363->setSourceEndpoint(srcPt363);
+ ConnEnd dstPt363(Point(-486.87164351602, -378.4098117525406), 8);
+ connRef363->setDestEndpoint(dstPt363);
+ connRef363->setRoutingType((ConnType)2);
+
+ ConnRef *connRef364 = new ConnRef(router, 364);
+ ConnEnd srcPt364(Point(-516.87164351602, -378.4098117525406), 4);
+ connRef364->setSourceEndpoint(srcPt364);
+ ConnEnd dstPt364(Point(-695.12164351602, 66.25685491512604), 15);
+ connRef364->setDestEndpoint(dstPt364);
+ connRef364->setRoutingType((ConnType)2);
+
+ ConnRef *connRef365 = new ConnRef(router, 365);
+ ConnEnd srcPt365(Point(81.62835648597996, -277.4098117515406), 4);
+ connRef365->setSourceEndpoint(srcPt365);
+ ConnEnd dstPt365(Point(-319.87164351602, -298.4098117515406), 15);
+ connRef365->setDestEndpoint(dstPt365);
+ connRef365->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints365(1);
+ checkpoints365[0] = Checkpoint(Point(58.62835648597996, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef365->setRoutingCheckpoints(checkpoints365);
+
+ ConnRef *connRef366 = new ConnRef(router, 366);
+ ConnEnd srcPt366(Point(111.62835648598, -277.4098117515406), 8);
+ connRef366->setSourceEndpoint(srcPt366);
+ ConnEnd dstPt366(Point(181.62835648698, -298.4098117515406), 15);
+ connRef366->setDestEndpoint(dstPt366);
+ connRef366->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints366(1);
+ checkpoints366[0] = Checkpoint(Point(134.62835648598, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef366->setRoutingCheckpoints(checkpoints366);
+
+ ConnRef *connRef367 = new ConnRef(router, 367);
+ ConnEnd srcPt367(Point(81.62835648597996, -202.4098117515406), 4);
+ connRef367->setSourceEndpoint(srcPt367);
+ ConnEnd dstPt367(Point(-319.87164351602, -298.4098117515406), 15);
+ connRef367->setDestEndpoint(dstPt367);
+ connRef367->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints367(1);
+ checkpoints367[0] = Checkpoint(Point(58.62835648597996, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef367->setRoutingCheckpoints(checkpoints367);
+
+ ConnRef *connRef368 = new ConnRef(router, 368);
+ ConnEnd srcPt368(Point(111.62835648598, -202.4098117515406), 8);
+ connRef368->setSourceEndpoint(srcPt368);
+ ConnEnd dstPt368(Point(181.62835648698, -298.4098117515406), 15);
+ connRef368->setDestEndpoint(dstPt368);
+ connRef368->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints368(1);
+ checkpoints368[0] = Checkpoint(Point(134.62835648598, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef368->setRoutingCheckpoints(checkpoints368);
+
+ ConnRef *connRef369 = new ConnRef(router, 369);
+ ConnEnd srcPt369(Point(412.62835648698, -277.4098117515406), 4);
+ connRef369->setSourceEndpoint(srcPt369);
+ ConnEnd dstPt369(Point(181.62835648698, -298.4098117515406), 15);
+ connRef369->setDestEndpoint(dstPt369);
+ connRef369->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints369(1);
+ checkpoints369[0] = Checkpoint(Point(389.62835648698, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef369->setRoutingCheckpoints(checkpoints369);
+
+ ConnRef *connRef370 = new ConnRef(router, 370);
+ ConnEnd srcPt370(Point(442.62835648698, -277.4098117515406), 8);
+ connRef370->setSourceEndpoint(srcPt370);
+ ConnEnd dstPt370(Point(530.62835648798, -298.4098117515406), 15);
+ connRef370->setDestEndpoint(dstPt370);
+ connRef370->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints370(1);
+ checkpoints370[0] = Checkpoint(Point(465.62835648698, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef370->setRoutingCheckpoints(checkpoints370);
+
+ ConnRef *connRef371 = new ConnRef(router, 371);
+ ConnEnd srcPt371(Point(412.62835648698, -202.4098117515406), 4);
+ connRef371->setSourceEndpoint(srcPt371);
+ ConnEnd dstPt371(Point(181.62835648698, -298.4098117515406), 15);
+ connRef371->setDestEndpoint(dstPt371);
+ connRef371->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints371(1);
+ checkpoints371[0] = Checkpoint(Point(389.62835648698, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef371->setRoutingCheckpoints(checkpoints371);
+
+ ConnRef *connRef372 = new ConnRef(router, 372);
+ ConnEnd srcPt372(Point(442.62835648698, -202.4098117515406), 8);
+ connRef372->setSourceEndpoint(srcPt372);
+ ConnEnd dstPt372(Point(530.62835648798, -298.4098117515406), 15);
+ connRef372->setDestEndpoint(dstPt372);
+ connRef372->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints372(1);
+ checkpoints372[0] = Checkpoint(Point(465.62835648698, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef372->setRoutingCheckpoints(checkpoints372);
+
+ ConnRef *connRef373 = new ConnRef(router, 373);
+ ConnEnd srcPt373(Point(-298.87164351602, -174.4098117515406), 1);
+ connRef373->setSourceEndpoint(srcPt373);
+ ConnEnd dstPt373(Point(-319.87164351602, -298.4098117515406), 15);
+ connRef373->setDestEndpoint(dstPt373);
+ connRef373->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints373(1);
+ checkpoints373[0] = Checkpoint(Point(-319.87164351602, -189.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 2);
+ connRef373->setRoutingCheckpoints(checkpoints373);
+
+ ConnRef *connRef374 = new ConnRef(router, 374);
+ ConnEnd srcPt374(Point(-298.87164351602, -144.4098117515406), 2);
+ connRef374->setSourceEndpoint(srcPt374);
+ ConnEnd dstPt374(Point(-319.87164351602, 66.25685491512604), 15);
+ connRef374->setDestEndpoint(dstPt374);
+ connRef374->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints374(1);
+ checkpoints374[0] = Checkpoint(Point(-319.87164351602, -129.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 1);
+ connRef374->setRoutingCheckpoints(checkpoints374);
+
+ ConnRef *connRef375 = new ConnRef(router, 375);
+ ConnEnd srcPt375(Point(-340.87164351602, -174.4098117515406), 1);
+ connRef375->setSourceEndpoint(srcPt375);
+ ConnEnd dstPt375(Point(-319.87164351602, -298.4098117515406), 15);
+ connRef375->setDestEndpoint(dstPt375);
+ connRef375->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints375(1);
+ checkpoints375[0] = Checkpoint(Point(-319.87164351602, -189.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 2);
+ connRef375->setRoutingCheckpoints(checkpoints375);
+
+ ConnRef *connRef376 = new ConnRef(router, 376);
+ ConnEnd srcPt376(Point(-340.87164351602, -144.4098117515406), 2);
+ connRef376->setSourceEndpoint(srcPt376);
+ ConnEnd dstPt376(Point(-319.87164351602, 66.25685491512604), 15);
+ connRef376->setDestEndpoint(dstPt376);
+ connRef376->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints376(1);
+ checkpoints376[0] = Checkpoint(Point(-319.87164351602, -129.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 1);
+ connRef376->setRoutingCheckpoints(checkpoints376);
+
+ ConnRef *connRef377 = new ConnRef(router, 377);
+ ConnEnd srcPt377(Point(81.62835648597996, -394.4098117515406), 4);
+ connRef377->setSourceEndpoint(srcPt377);
+ ConnEnd dstPt377(Point(-319.87164351602, -298.4098117515406), 15);
+ connRef377->setDestEndpoint(dstPt377);
+ connRef377->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints377(1);
+ checkpoints377[0] = Checkpoint(Point(58.62835648597996, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef377->setRoutingCheckpoints(checkpoints377);
+
+ ConnRef *connRef378 = new ConnRef(router, 378);
+ ConnEnd srcPt378(Point(111.62835648598, -394.4098117515406), 8);
+ connRef378->setSourceEndpoint(srcPt378);
+ ConnEnd dstPt378(Point(181.62835648698, -298.4098117515406), 15);
+ connRef378->setDestEndpoint(dstPt378);
+ connRef378->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints378(1);
+ checkpoints378[0] = Checkpoint(Point(134.62835648598, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef378->setRoutingCheckpoints(checkpoints378);
+
+ ConnRef *connRef379 = new ConnRef(router, 379);
+ ConnEnd srcPt379(Point(81.62835648597996, -319.4098117515406), 4);
+ connRef379->setSourceEndpoint(srcPt379);
+ ConnEnd dstPt379(Point(-319.87164351602, -298.4098117515406), 15);
+ connRef379->setDestEndpoint(dstPt379);
+ connRef379->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints379(1);
+ checkpoints379[0] = Checkpoint(Point(58.62835648597996, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef379->setRoutingCheckpoints(checkpoints379);
+
+ ConnRef *connRef380 = new ConnRef(router, 380);
+ ConnEnd srcPt380(Point(111.62835648598, -319.4098117515406), 8);
+ connRef380->setSourceEndpoint(srcPt380);
+ ConnEnd dstPt380(Point(181.62835648698, -298.4098117515406), 15);
+ connRef380->setDestEndpoint(dstPt380);
+ connRef380->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints380(1);
+ checkpoints380[0] = Checkpoint(Point(134.62835648598, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef380->setRoutingCheckpoints(checkpoints380);
+
+ ConnRef *connRef381 = new ConnRef(router, 381);
+ ConnEnd srcPt381(Point(442.62835648698, -469.4098117515406), 8);
+ connRef381->setSourceEndpoint(srcPt381);
+ ConnEnd dstPt381(Point(530.62835648798, -298.4098117515406), 15);
+ connRef381->setDestEndpoint(dstPt381);
+ connRef381->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints381(1);
+ checkpoints381[0] = Checkpoint(Point(465.62835648698, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef381->setRoutingCheckpoints(checkpoints381);
+
+ ConnRef *connRef382 = new ConnRef(router, 382);
+ ConnEnd srcPt382(Point(442.62835648698, -394.4098117515406), 8);
+ connRef382->setSourceEndpoint(srcPt382);
+ ConnEnd dstPt382(Point(530.62835648798, -298.4098117515406), 15);
+ connRef382->setDestEndpoint(dstPt382);
+ connRef382->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints382(1);
+ checkpoints382[0] = Checkpoint(Point(465.62835648698, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef382->setRoutingCheckpoints(checkpoints382);
+
+ ConnRef *connRef383 = new ConnRef(router, 383);
+ ConnEnd srcPt383(Point(530.62835648798, -298.4098117515406), 15);
+ connRef383->setSourceEndpoint(srcPt383);
+ ConnEnd dstPt383(Point(830.62835648898, -232.4098117515406), 4);
+ connRef383->setDestEndpoint(dstPt383);
+ connRef383->setRoutingType((ConnType)2);
+
+ ConnRef *connRef384 = new ConnRef(router, 384);
+ ConnEnd srcPt384(Point(860.62835648898, -232.4098117515406), 8);
+ connRef384->setSourceEndpoint(srcPt384);
+ ConnEnd dstPt384(Point(1514.12835648898, -298.4098117515406), 15);
+ connRef384->setDestEndpoint(dstPt384);
+ connRef384->setRoutingType((ConnType)2);
+
+ ConnRef *connRef385 = new ConnRef(router, 385);
+ ConnEnd srcPt385(Point(617.9873402531949, -277.4098117515406), 4);
+ connRef385->setSourceEndpoint(srcPt385);
+ ConnEnd dstPt385(Point(530.62835648798, -298.4098117515406), 15);
+ connRef385->setDestEndpoint(dstPt385);
+ connRef385->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints385(1);
+ checkpoints385[0] = Checkpoint(Point(594.9873402531949, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef385->setRoutingCheckpoints(checkpoints385);
+
+ ConnRef *connRef386 = new ConnRef(router, 386);
+ ConnEnd srcPt386(Point(647.9873402531949, -277.4098117515406), 8);
+ connRef386->setSourceEndpoint(srcPt386);
+ ConnEnd dstPt386(Point(982.9140707746942, -298.4098117515406), 15);
+ connRef386->setDestEndpoint(dstPt386);
+ connRef386->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints386(1);
+ checkpoints386[0] = Checkpoint(Point(670.9873402531949, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef386->setRoutingCheckpoints(checkpoints386);
+
+ ConnRef *connRef387 = new ConnRef(router, 387);
+ ConnEnd srcPt387(Point(617.9873402531949, -319.4098117515406), 4);
+ connRef387->setSourceEndpoint(srcPt387);
+ ConnEnd dstPt387(Point(530.62835648798, -298.4098117515406), 15);
+ connRef387->setDestEndpoint(dstPt387);
+ connRef387->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints387(1);
+ checkpoints387[0] = Checkpoint(Point(594.9873402531949, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef387->setRoutingCheckpoints(checkpoints387);
+
+ ConnRef *connRef388 = new ConnRef(router, 388);
+ ConnEnd srcPt388(Point(647.9873402531949, -319.4098117515406), 8);
+ connRef388->setSourceEndpoint(srcPt388);
+ ConnEnd dstPt388(Point(982.9140707746942, -298.4098117515406), 15);
+ connRef388->setDestEndpoint(dstPt388);
+ connRef388->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints388(1);
+ checkpoints388[0] = Checkpoint(Point(670.9873402531949, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef388->setRoutingCheckpoints(checkpoints388);
+
+ ConnRef *connRef389 = new ConnRef(router, 389);
+ ConnEnd srcPt389(Point(1047.914070775694, -319.4098117515406), 4);
+ connRef389->setSourceEndpoint(srcPt389);
+ ConnEnd dstPt389(Point(982.9140707746942, -298.4098117515406), 15);
+ connRef389->setDestEndpoint(dstPt389);
+ connRef389->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints389(1);
+ checkpoints389[0] = Checkpoint(Point(1024.914070775694, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef389->setRoutingCheckpoints(checkpoints389);
+
+ ConnRef *connRef390 = new ConnRef(router, 390);
+ ConnEnd srcPt390(Point(1077.914070775694, -319.4098117515406), 8);
+ connRef390->setSourceEndpoint(srcPt390);
+ ConnEnd dstPt390(Point(1514.12835648898, -298.4098117515406), 15);
+ connRef390->setDestEndpoint(dstPt390);
+ connRef390->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints390(1);
+ checkpoints390[0] = Checkpoint(Point(1100.914070775694, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef390->setRoutingCheckpoints(checkpoints390);
+
+ ConnRef *connRef391 = new ConnRef(router, 391);
+ ConnEnd srcPt391(Point(1047.914070775694, -277.4098117515406), 4);
+ connRef391->setSourceEndpoint(srcPt391);
+ ConnEnd dstPt391(Point(982.9140707746942, -298.4098117515406), 15);
+ connRef391->setDestEndpoint(dstPt391);
+ connRef391->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints391(1);
+ checkpoints391[0] = Checkpoint(Point(1024.914070775694, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef391->setRoutingCheckpoints(checkpoints391);
+
+ ConnRef *connRef392 = new ConnRef(router, 392);
+ ConnEnd srcPt392(Point(1077.914070775694, -277.4098117515406), 8);
+ connRef392->setSourceEndpoint(srcPt392);
+ ConnEnd dstPt392(Point(1514.12835648898, -298.4098117515406), 15);
+ connRef392->setDestEndpoint(dstPt392);
+ connRef392->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints392(1);
+ checkpoints392[0] = Checkpoint(Point(1100.914070775694, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef392->setRoutingCheckpoints(checkpoints392);
+
+ ConnRef *connRef393 = new ConnRef(router, 393);
+ ConnEnd srcPt393(Point(1579.12835648998, -319.4098117515406), 4);
+ connRef393->setSourceEndpoint(srcPt393);
+ ConnEnd dstPt393(Point(1514.12835648898, -298.4098117515406), 15);
+ connRef393->setDestEndpoint(dstPt393);
+ connRef393->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints393(1);
+ checkpoints393[0] = Checkpoint(Point(1556.12835648998, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef393->setRoutingCheckpoints(checkpoints393);
+
+ ConnRef *connRef394 = new ConnRef(router, 394);
+ ConnEnd srcPt394(Point(1609.12835648998, -319.4098117515406), 8);
+ connRef394->setSourceEndpoint(srcPt394);
+ ConnEnd dstPt394(Point(1700.12835648998, -298.4098117515406), 15);
+ connRef394->setDestEndpoint(dstPt394);
+ connRef394->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints394(1);
+ checkpoints394[0] = Checkpoint(Point(1632.12835648998, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef394->setRoutingCheckpoints(checkpoints394);
+
+ ConnRef *connRef395 = new ConnRef(router, 395);
+ ConnEnd srcPt395(Point(1579.12835648998, -277.4098117515406), 4);
+ connRef395->setSourceEndpoint(srcPt395);
+ ConnEnd dstPt395(Point(1514.12835648898, -298.4098117515406), 15);
+ connRef395->setDestEndpoint(dstPt395);
+ connRef395->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints395(1);
+ checkpoints395[0] = Checkpoint(Point(1556.12835648998, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef395->setRoutingCheckpoints(checkpoints395);
+
+ ConnRef *connRef396 = new ConnRef(router, 396);
+ ConnEnd srcPt396(Point(1609.12835648998, -277.4098117515406), 8);
+ connRef396->setSourceEndpoint(srcPt396);
+ ConnEnd dstPt396(Point(1700.12835648998, -298.4098117515406), 15);
+ connRef396->setDestEndpoint(dstPt396);
+ connRef396->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints396(1);
+ checkpoints396[0] = Checkpoint(Point(1632.12835648998, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef396->setRoutingCheckpoints(checkpoints396);
+
+ ConnRef *connRef397 = new ConnRef(router, 397);
+ ConnEnd srcPt397(Point(1785.12835649098, -298.4098117515406), 8);
+ connRef397->setSourceEndpoint(srcPt397);
+ ConnEnd dstPt397(Point(1873.12835649198, -298.4098117515406), 15);
+ connRef397->setDestEndpoint(dstPt397);
+ connRef397->setRoutingType((ConnType)2);
+
+ ConnRef *connRef398 = new ConnRef(router, 398);
+ ConnEnd srcPt398(Point(1958.12835649298, -298.4098117515406), 8);
+ connRef398->setSourceEndpoint(srcPt398);
+ ConnEnd dstPt398(Point(2046.795023159646, -298.4098117515406), 15);
+ connRef398->setDestEndpoint(dstPt398);
+ connRef398->setRoutingType((ConnType)2);
+
+ ConnRef *connRef399 = new ConnRef(router, 399);
+ ConnEnd srcPt399(Point(-516.87164351602, 99.25685491512604), 4);
+ connRef399->setSourceEndpoint(srcPt399);
+ ConnEnd dstPt399(Point(-695.12164351602, 66.25685491512604), 15);
+ connRef399->setDestEndpoint(dstPt399);
+ connRef399->setRoutingType((ConnType)2);
+
+ ConnRef *connRef400 = new ConnRef(router, 400);
+ ConnEnd srcPt400(Point(-319.87164351602, 66.25685491512604), 15);
+ connRef400->setSourceEndpoint(srcPt400);
+ ConnEnd dstPt400(Point(-486.87164351602, 99.25685491512604), 8);
+ connRef400->setDestEndpoint(dstPt400);
+ connRef400->setRoutingType((ConnType)2);
+
+ ConnRef *connRef401 = new ConnRef(router, 401);
+ ConnEnd srcPt401(Point(-486.87164351602, 201.256854916126), 8);
+ connRef401->setSourceEndpoint(srcPt401);
+ ConnEnd dstPt401(Point(181.62835648698, 66.25685491512604), 15);
+ connRef401->setDestEndpoint(dstPt401);
+ connRef401->setRoutingType((ConnType)2);
+
+ ConnRef *connRef402 = new ConnRef(router, 402);
+ ConnEnd srcPt402(Point(-41.87164351502003, 45.25685491512604), 4);
+ connRef402->setSourceEndpoint(srcPt402);
+ ConnEnd dstPt402(Point(-319.87164351602, 66.25685491512604), 15);
+ connRef402->setDestEndpoint(dstPt402);
+ connRef402->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints402(1);
+ checkpoints402[0] = Checkpoint(Point(-64.87164351502003, 66.25685491512604), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef402->setRoutingCheckpoints(checkpoints402);
+
+ ConnRef *connRef403 = new ConnRef(router, 403);
+ ConnEnd srcPt403(Point(-11.87164351502003, 45.25685491512604), 8);
+ connRef403->setSourceEndpoint(srcPt403);
+ ConnEnd dstPt403(Point(181.62835648698, 66.25685491512604), 15);
+ connRef403->setDestEndpoint(dstPt403);
+ connRef403->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints403(1);
+ checkpoints403[0] = Checkpoint(Point(11.12835648497997, 66.25685491512604), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef403->setRoutingCheckpoints(checkpoints403);
+
+ ConnRef *connRef404 = new ConnRef(router, 404);
+ ConnEnd srcPt404(Point(-41.87164351502003, 87.25685491512604), 4);
+ connRef404->setSourceEndpoint(srcPt404);
+ ConnEnd dstPt404(Point(-319.87164351602, 66.25685491512604), 15);
+ connRef404->setDestEndpoint(dstPt404);
+ connRef404->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints404(1);
+ checkpoints404[0] = Checkpoint(Point(-64.87164351502003, 66.25685491512604), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef404->setRoutingCheckpoints(checkpoints404);
+
+ ConnRef *connRef405 = new ConnRef(router, 405);
+ ConnEnd srcPt405(Point(-11.87164351502003, 87.25685491512604), 8);
+ connRef405->setSourceEndpoint(srcPt405);
+ ConnEnd dstPt405(Point(181.62835648698, 66.25685491512604), 15);
+ connRef405->setDestEndpoint(dstPt405);
+ connRef405->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints405(1);
+ checkpoints405[0] = Checkpoint(Point(11.12835648497997, 66.25685491512604), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef405->setRoutingCheckpoints(checkpoints405);
+
+ ConnRef *connRef406 = new ConnRef(router, 406);
+ ConnEnd srcPt406(Point(465.62835648698, 87.25685491512604), 8);
+ connRef406->setSourceEndpoint(srcPt406);
+ ConnEnd dstPt406(Point(530.62835648798, 66.25685491512604), 15);
+ connRef406->setDestEndpoint(dstPt406);
+ connRef406->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints406(1);
+ checkpoints406[0] = Checkpoint(Point(488.62835648698, 66.25685491512604), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef406->setRoutingCheckpoints(checkpoints406);
+
+ ConnRef *connRef407 = new ConnRef(router, 407);
+ ConnEnd srcPt407(Point(435.62835648698, 87.25685491512604), 4);
+ connRef407->setSourceEndpoint(srcPt407);
+ ConnEnd dstPt407(Point(181.62835648698, 66.25685491512604), 15);
+ connRef407->setDestEndpoint(dstPt407);
+ connRef407->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints407(1);
+ checkpoints407[0] = Checkpoint(Point(412.62835648698, 66.25685491512604), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef407->setRoutingCheckpoints(checkpoints407);
+
+ ConnRef *connRef408 = new ConnRef(router, 408);
+ ConnEnd srcPt408(Point(465.62835648698, 45.25685491512604), 8);
+ connRef408->setSourceEndpoint(srcPt408);
+ ConnEnd dstPt408(Point(530.62835648798, 66.25685491512604), 15);
+ connRef408->setDestEndpoint(dstPt408);
+ connRef408->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints408(1);
+ checkpoints408[0] = Checkpoint(Point(488.62835648698, 66.25685491512604), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef408->setRoutingCheckpoints(checkpoints408);
+
+ ConnRef *connRef409 = new ConnRef(router, 409);
+ ConnEnd srcPt409(Point(435.62835648698, 45.25685491512604), 4);
+ connRef409->setSourceEndpoint(srcPt409);
+ ConnEnd dstPt409(Point(181.62835648698, 66.25685491512604), 15);
+ connRef409->setDestEndpoint(dstPt409);
+ connRef409->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints409(1);
+ checkpoints409[0] = Checkpoint(Point(412.62835648698, 66.25685491512604), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef409->setRoutingCheckpoints(checkpoints409);
+
+ ConnRef *connRef410 = new ConnRef(router, 410);
+ ConnEnd srcPt410(Point(780.62835648798, 45.25685491512604), 8);
+ connRef410->setSourceEndpoint(srcPt410);
+ ConnEnd dstPt410(Point(982.9140707746942, 66.25685491512604), 15);
+ connRef410->setDestEndpoint(dstPt410);
+ connRef410->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints410(1);
+ checkpoints410[0] = Checkpoint(Point(803.62835648798, 66.25685491512604), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef410->setRoutingCheckpoints(checkpoints410);
+
+ ConnRef *connRef411 = new ConnRef(router, 411);
+ ConnEnd srcPt411(Point(750.62835648798, 45.25685491512604), 4);
+ connRef411->setSourceEndpoint(srcPt411);
+ ConnEnd dstPt411(Point(530.62835648798, 66.25685491512604), 15);
+ connRef411->setDestEndpoint(dstPt411);
+ connRef411->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints411(1);
+ checkpoints411[0] = Checkpoint(Point(727.62835648798, 66.25685491512604), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef411->setRoutingCheckpoints(checkpoints411);
+
+ ConnRef *connRef412 = new ConnRef(router, 412);
+ ConnEnd srcPt412(Point(780.62835648798, 87.25685491512604), 8);
+ connRef412->setSourceEndpoint(srcPt412);
+ ConnEnd dstPt412(Point(982.9140707746942, 66.25685491512604), 15);
+ connRef412->setDestEndpoint(dstPt412);
+ connRef412->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints412(1);
+ checkpoints412[0] = Checkpoint(Point(803.62835648798, 66.25685491512604), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef412->setRoutingCheckpoints(checkpoints412);
+
+ ConnRef *connRef413 = new ConnRef(router, 413);
+ ConnEnd srcPt413(Point(750.62835648798, 87.25685491512604), 4);
+ connRef413->setSourceEndpoint(srcPt413);
+ ConnEnd dstPt413(Point(530.62835648798, 66.25685491512604), 15);
+ connRef413->setDestEndpoint(dstPt413);
+ connRef413->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints413(1);
+ checkpoints413[0] = Checkpoint(Point(727.62835648798, 66.25685491512604), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef413->setRoutingCheckpoints(checkpoints413);
+
+ ConnRef *connRef414 = new ConnRef(router, 414);
+ ConnEnd srcPt414(Point(982.9140707746942, -141.4098117515406), 1);
+ connRef414->setSourceEndpoint(srcPt414);
+ ConnEnd dstPt414(Point(982.9140707746942, -298.4098117515406), 15);
+ connRef414->setDestEndpoint(dstPt414);
+ connRef414->setRoutingType((ConnType)2);
+
+ ConnRef *connRef415 = new ConnRef(router, 415);
+ ConnEnd srcPt415(Point(982.9140707746942, 66.25685491512604), 15);
+ connRef415->setSourceEndpoint(srcPt415);
+ ConnEnd dstPt415(Point(982.9140707746942, -111.4098117515406), 2);
+ connRef415->setDestEndpoint(dstPt415);
+ connRef415->setRoutingType((ConnType)2);
+
+ ConnRef *connRef416 = new ConnRef(router, 416);
+ ConnEnd srcPt416(Point(1429.12835648898, -141.4098117515406), 1);
+ connRef416->setSourceEndpoint(srcPt416);
+ ConnEnd dstPt416(Point(1514.12835648898, -298.4098117515406), 15);
+ connRef416->setDestEndpoint(dstPt416);
+ connRef416->setRoutingType((ConnType)2);
+
+ ConnRef *connRef417 = new ConnRef(router, 417);
+ ConnEnd srcPt417(Point(1264.12835648898, 66.25685491512604), 15);
+ connRef417->setSourceEndpoint(srcPt417);
+ ConnEnd dstPt417(Point(1429.12835648898, -111.4098117515406), 2);
+ connRef417->setDestEndpoint(dstPt417);
+ connRef417->setRoutingType((ConnType)2);
+
+ ConnRef *connRef418 = new ConnRef(router, 418);
+ ConnEnd srcPt418(Point(1116.12835648898, 45.25685491512604), 8);
+ connRef418->setSourceEndpoint(srcPt418);
+ ConnEnd dstPt418(Point(1264.12835648898, 66.25685491512604), 15);
+ connRef418->setDestEndpoint(dstPt418);
+ connRef418->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints418(1);
+ checkpoints418[0] = Checkpoint(Point(1139.12835648898, 66.25685491512604), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef418->setRoutingCheckpoints(checkpoints418);
+
+ ConnRef *connRef419 = new ConnRef(router, 419);
+ ConnEnd srcPt419(Point(1086.12835648898, 45.25685491512604), 4);
+ connRef419->setSourceEndpoint(srcPt419);
+ ConnEnd dstPt419(Point(982.9140707746942, 66.25685491512604), 15);
+ connRef419->setDestEndpoint(dstPt419);
+ connRef419->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints419(1);
+ checkpoints419[0] = Checkpoint(Point(1063.12835648898, 66.25685491512604), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef419->setRoutingCheckpoints(checkpoints419);
+
+ ConnRef *connRef420 = new ConnRef(router, 420);
+ ConnEnd srcPt420(Point(1116.12835648898, 87.25685491512604), 8);
+ connRef420->setSourceEndpoint(srcPt420);
+ ConnEnd dstPt420(Point(1264.12835648898, 66.25685491512604), 15);
+ connRef420->setDestEndpoint(dstPt420);
+ connRef420->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints420(1);
+ checkpoints420[0] = Checkpoint(Point(1139.12835648898, 66.25685491512604), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef420->setRoutingCheckpoints(checkpoints420);
+
+ ConnRef *connRef421 = new ConnRef(router, 421);
+ ConnEnd srcPt421(Point(1086.12835648898, 87.25685491512604), 4);
+ connRef421->setSourceEndpoint(srcPt421);
+ ConnEnd dstPt421(Point(982.9140707746942, 66.25685491512604), 15);
+ connRef421->setDestEndpoint(dstPt421);
+ connRef421->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints421(1);
+ checkpoints421[0] = Checkpoint(Point(1063.12835648898, 66.25685491512604), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef421->setRoutingCheckpoints(checkpoints421);
+
+ ConnRef *connRef422 = new ConnRef(router, 422);
+ ConnEnd srcPt422(Point(714.62835648798, 255.2568549161261), 8);
+ connRef422->setSourceEndpoint(srcPt422);
+ ConnEnd dstPt422(Point(1264.12835648898, 66.25685491512604), 15);
+ connRef422->setDestEndpoint(dstPt422);
+ connRef422->setRoutingType((ConnType)2);
+
+ ConnRef *connRef423 = new ConnRef(router, 423);
+ ConnEnd srcPt423(Point(530.62835648798, 66.25685491512604), 15);
+ connRef423->setSourceEndpoint(srcPt423);
+ ConnEnd dstPt423(Point(684.62835648798, 255.2568549161261), 4);
+ connRef423->setDestEndpoint(dstPt423);
+ connRef423->setRoutingType((ConnType)2);
+
+ ConnRef *connRef424 = new ConnRef(router, 424);
+ ConnEnd srcPt424(Point(1514.12835648898, -298.4098117515406), 15);
+ connRef424->setSourceEndpoint(srcPt424);
+ ConnEnd dstPt424(Point(1612.12835648998, 33.25685491512604), 4);
+ connRef424->setDestEndpoint(dstPt424);
+ connRef424->setRoutingType((ConnType)2);
+
+ ConnRef *connRef425 = new ConnRef(router, 425);
+ ConnEnd srcPt425(Point(1642.12835648998, 33.25685491512604), 8);
+ connRef425->setSourceEndpoint(srcPt425);
+ ConnEnd dstPt425(Point(1700.12835648998, 33.25685491512604), 15);
+ connRef425->setDestEndpoint(dstPt425);
+ connRef425->setRoutingType((ConnType)2);
+
+ ConnRef *connRef426 = new ConnRef(router, 426);
+ ConnEnd srcPt426(Point(-874.12164351602, 756.8568549161259), 1);
+ connRef426->setSourceEndpoint(srcPt426);
+ ConnEnd dstPt426(Point(-841.12164351602, 668.6568549161261), 15);
+ connRef426->setDestEndpoint(dstPt426);
+ connRef426->setRoutingType((ConnType)2);
+
+ ConnRef *connRef427 = new ConnRef(router, 427);
+ ConnEnd srcPt427(Point(-728.12164351602, 786.8568549161259), 2);
+ connRef427->setSourceEndpoint(srcPt427);
+ ConnEnd dstPt427(Point(-841.12164351602, 890.8568549161259), 15);
+ connRef427->setDestEndpoint(dstPt427);
+ connRef427->setRoutingType((ConnType)2);
+
+ ConnRef *connRef428 = new ConnRef(router, 428);
+ ConnEnd srcPt428(Point(-319.87164351602, -298.4098117515406), 15);
+ connRef428->setSourceEndpoint(srcPt428);
+ ConnEnd dstPt428(Point(-728.12164351602, 756.8568549161259), 1);
+ connRef428->setDestEndpoint(dstPt428);
+ connRef428->setRoutingType((ConnType)2);
+
+ ConnRef *connRef429 = new ConnRef(router, 429);
+ ConnEnd srcPt429(Point(-728.12164351602, 786.8568549161259), 2);
+ connRef429->setSourceEndpoint(srcPt429);
+ ConnEnd dstPt429(Point(-319.87164351602, 1143.856854916126), 15);
+ connRef429->setDestEndpoint(dstPt429);
+ connRef429->setRoutingType((ConnType)2);
+
+ ConnRef *connRef430 = new ConnRef(router, 430);
+ ConnEnd srcPt430(Point(-534.87164351602, 505.756854916126), 1);
+ connRef430->setSourceEndpoint(srcPt430);
+ ConnEnd dstPt430(Point(-435.87164351602, 454.7568549161261), 15);
+ connRef430->setDestEndpoint(dstPt430);
+ connRef430->setRoutingType((ConnType)2);
+
+ ConnRef *connRef431 = new ConnRef(router, 431);
+ ConnEnd srcPt431(Point(-319.87164351602, 535.756854916126), 2);
+ connRef431->setSourceEndpoint(srcPt431);
+ ConnEnd dstPt431(Point(-319.87164351602, 738.8568549161259), 15);
+ connRef431->setDestEndpoint(dstPt431);
+ connRef431->setRoutingType((ConnType)2);
+
+ ConnRef *connRef432 = new ConnRef(router, 432);
+ ConnEnd srcPt432(Point(-319.87164351602, 535.756854916126), 2);
+ connRef432->setSourceEndpoint(srcPt432);
+ ConnEnd dstPt432(Point(-435.87164351602, 635.6568549161261), 15);
+ connRef432->setDestEndpoint(dstPt432);
+ connRef432->setRoutingType((ConnType)2);
+
+ ConnRef *connRef433 = new ConnRef(router, 433);
+ ConnEnd srcPt433(Point(-125.87164351502, 505.756854916126), 1);
+ connRef433->setSourceEndpoint(srcPt433);
+ ConnEnd dstPt433(Point(115.62835648698, 454.7568549161261), 15);
+ connRef433->setDestEndpoint(dstPt433);
+ connRef433->setRoutingType((ConnType)2);
+
+ ConnRef *connRef434 = new ConnRef(router, 434);
+ ConnEnd srcPt434(Point(181.62835648698, 535.756854916126), 2);
+ connRef434->setSourceEndpoint(srcPt434);
+ ConnEnd dstPt434(Point(181.62835648698, 738.8568549161259), 15);
+ connRef434->setDestEndpoint(dstPt434);
+ connRef434->setRoutingType((ConnType)2);
+
+ ConnRef *connRef435 = new ConnRef(router, 435);
+ ConnEnd srcPt435(Point(181.62835648698, 535.756854916126), 2);
+ connRef435->setSourceEndpoint(srcPt435);
+ ConnEnd dstPt435(Point(115.62835648698, 635.6568549161261), 15);
+ connRef435->setDestEndpoint(dstPt435);
+ connRef435->setRoutingType((ConnType)2);
+
+ ConnRef *connRef436 = new ConnRef(router, 436);
+ ConnEnd srcPt436(Point(16.62835648497997, 738.8568549161259), 4);
+ connRef436->setSourceEndpoint(srcPt436);
+ ConnEnd dstPt436(Point(-319.87164351602, 738.8568549161259), 15);
+ connRef436->setDestEndpoint(dstPt436);
+ connRef436->setRoutingType((ConnType)2);
+
+ ConnRef *connRef437 = new ConnRef(router, 437);
+ ConnEnd srcPt437(Point(-352.87164351602, 993.8568549161259), 2);
+ connRef437->setSourceEndpoint(srcPt437);
+ ConnEnd dstPt437(Point(-319.87164351602, 1143.856854916126), 15);
+ connRef437->setDestEndpoint(dstPt437);
+ connRef437->setRoutingType((ConnType)2);
+
+ ConnRef *connRef438 = new ConnRef(router, 438);
+ ConnEnd srcPt438(Point(-319.87164351602, 738.8568549161259), 15);
+ connRef438->setSourceEndpoint(srcPt438);
+ ConnEnd dstPt438(Point(-352.87164351602, 963.8568549161259), 1);
+ connRef438->setDestEndpoint(dstPt438);
+ connRef438->setRoutingType((ConnType)2);
+
+ ConnRef *connRef439 = new ConnRef(router, 439);
+ ConnEnd srcPt439(Point(-695.12164351602, 1059.856854916126), 2);
+ connRef439->setSourceEndpoint(srcPt439);
+ ConnEnd dstPt439(Point(-695.12164351602, 1647.106854917126), 15);
+ connRef439->setDestEndpoint(dstPt439);
+ connRef439->setRoutingType((ConnType)2);
+
+ ConnRef *connRef440 = new ConnRef(router, 440);
+ ConnEnd srcPt440(Point(-319.87164351602, 738.8568549161259), 15);
+ connRef440->setSourceEndpoint(srcPt440);
+ ConnEnd dstPt440(Point(-695.12164351602, 1029.856854916126), 1);
+ connRef440->setDestEndpoint(dstPt440);
+ connRef440->setRoutingType((ConnType)2);
+
+ ConnRef *connRef441 = new ConnRef(router, 441);
+ ConnEnd srcPt441(Point(376.62835648698, 717.8568549161259), 8);
+ connRef441->setSourceEndpoint(srcPt441);
+ ConnEnd dstPt441(Point(530.62835648798, 738.8568549161259), 15);
+ connRef441->setDestEndpoint(dstPt441);
+ connRef441->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints441(1);
+ checkpoints441[0] = Checkpoint(Point(399.62835648698, 738.8568549161259), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef441->setRoutingCheckpoints(checkpoints441);
+
+ ConnRef *connRef442 = new ConnRef(router, 442);
+ ConnEnd srcPt442(Point(346.62835648698, 717.8568549161259), 4);
+ connRef442->setSourceEndpoint(srcPt442);
+ ConnEnd dstPt442(Point(181.62835648698, 738.8568549161259), 15);
+ connRef442->setDestEndpoint(dstPt442);
+ connRef442->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints442(1);
+ checkpoints442[0] = Checkpoint(Point(323.62835648698, 738.8568549161259), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef442->setRoutingCheckpoints(checkpoints442);
+
+ ConnRef *connRef443 = new ConnRef(router, 443);
+ ConnEnd srcPt443(Point(530.62835648798, 738.8568549161259), 15);
+ connRef443->setSourceEndpoint(srcPt443);
+ ConnEnd dstPt443(Point(651.62835648798, 579.006854916126), 4);
+ connRef443->setDestEndpoint(dstPt443);
+ connRef443->setRoutingType((ConnType)2);
+
+ ConnRef *connRef444 = new ConnRef(router, 444);
+ ConnEnd srcPt444(Point(681.62835648798, 579.006854916126), 8);
+ connRef444->setSourceEndpoint(srcPt444);
+ ConnEnd dstPt444(Point(878.62835648898, 579.006854916126), 15);
+ connRef444->setDestEndpoint(dstPt444);
+ connRef444->setRoutingType((ConnType)2);
+
+ ConnRef *connRef445 = new ConnRef(router, 445);
+ ConnEnd srcPt445(Point(163.62835648698, 804.8568549161259), 8);
+ connRef445->setSourceEndpoint(srcPt445);
+ ConnEnd dstPt445(Point(530.62835648798, 738.8568549161259), 15);
+ connRef445->setDestEndpoint(dstPt445);
+ connRef445->setRoutingType((ConnType)2);
+
+ ConnRef *connRef446 = new ConnRef(router, 446);
+ ConnEnd srcPt446(Point(813.62835648798, 717.8568549161259), 8);
+ connRef446->setSourceEndpoint(srcPt446);
+ ConnEnd dstPt446(Point(982.9140707746942, 738.8568549161259), 15);
+ connRef446->setDestEndpoint(dstPt446);
+ connRef446->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints446(1);
+ checkpoints446[0] = Checkpoint(Point(836.62835648798, 738.8568549161259), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef446->setRoutingCheckpoints(checkpoints446);
+
+ ConnRef *connRef447 = new ConnRef(router, 447);
+ ConnEnd srcPt447(Point(783.62835648798, 717.8568549161259), 4);
+ connRef447->setSourceEndpoint(srcPt447);
+ ConnEnd dstPt447(Point(530.62835648798, 738.8568549161259), 15);
+ connRef447->setDestEndpoint(dstPt447);
+ connRef447->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints447(1);
+ checkpoints447[0] = Checkpoint(Point(760.62835648798, 738.8568549161259), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef447->setRoutingCheckpoints(checkpoints447);
+
+ ConnRef *connRef448 = new ConnRef(router, 448);
+ ConnEnd srcPt448(Point(813.62835648798, 759.8568549161259), 8);
+ connRef448->setSourceEndpoint(srcPt448);
+ ConnEnd dstPt448(Point(982.9140707746942, 738.8568549161259), 15);
+ connRef448->setDestEndpoint(dstPt448);
+ connRef448->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints448(1);
+ checkpoints448[0] = Checkpoint(Point(836.62835648798, 738.8568549161259), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef448->setRoutingCheckpoints(checkpoints448);
+
+ ConnRef *connRef449 = new ConnRef(router, 449);
+ ConnEnd srcPt449(Point(783.62835648798, 759.8568549161259), 4);
+ connRef449->setSourceEndpoint(srcPt449);
+ ConnEnd dstPt449(Point(530.62835648798, 738.8568549161259), 15);
+ connRef449->setDestEndpoint(dstPt449);
+ connRef449->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints449(1);
+ checkpoints449[0] = Checkpoint(Point(760.62835648798, 738.8568549161259), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef449->setRoutingCheckpoints(checkpoints449);
+
+ ConnRef *connRef450 = new ConnRef(router, 450);
+ ConnEnd srcPt450(Point(596.62835648798, 872.8568549161259), 2);
+ connRef450->setSourceEndpoint(srcPt450);
+ ConnEnd dstPt450(Point(530.62835648798, 1143.856854916126), 15);
+ connRef450->setDestEndpoint(dstPt450);
+ connRef450->setRoutingType((ConnType)2);
+
+ ConnRef *connRef451 = new ConnRef(router, 451);
+ ConnEnd srcPt451(Point(530.62835648798, 738.8568549161259), 15);
+ connRef451->setSourceEndpoint(srcPt451);
+ ConnEnd dstPt451(Point(596.62835648798, 842.8568549161259), 1);
+ connRef451->setDestEndpoint(dstPt451);
+ connRef451->setRoutingType((ConnType)2);
+
+ ConnRef *connRef452 = new ConnRef(router, 452);
+ ConnEnd srcPt452(Point(86.62835648597996, 1021.856854916126), 4);
+ connRef452->setSourceEndpoint(srcPt452);
+ ConnEnd dstPt452(Point(-319.87164351602, 1143.856854916126), 15);
+ connRef452->setDestEndpoint(dstPt452);
+ connRef452->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints452(1);
+ checkpoints452[0] = Checkpoint(Point(63.62835648597996, 1042.856854916126), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef452->setRoutingCheckpoints(checkpoints452);
+
+ ConnRef *connRef453 = new ConnRef(router, 453);
+ ConnEnd srcPt453(Point(116.62835648598, 1021.856854916126), 8);
+ connRef453->setSourceEndpoint(srcPt453);
+ ConnEnd dstPt453(Point(530.62835648798, 1143.856854916126), 15);
+ connRef453->setDestEndpoint(dstPt453);
+ connRef453->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints453(1);
+ checkpoints453[0] = Checkpoint(Point(139.62835648598, 1042.856854916126), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef453->setRoutingCheckpoints(checkpoints453);
+
+ ConnRef *connRef454 = new ConnRef(router, 454);
+ ConnEnd srcPt454(Point(-107.87164351502, 1164.856854916126), 4);
+ connRef454->setSourceEndpoint(srcPt454);
+ ConnEnd dstPt454(Point(-319.87164351602, 1143.856854916126), 15);
+ connRef454->setDestEndpoint(dstPt454);
+ connRef454->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints454(1);
+ checkpoints454[0] = Checkpoint(Point(-130.87164351502, 1143.856854916126), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef454->setRoutingCheckpoints(checkpoints454);
+
+ ConnRef *connRef455 = new ConnRef(router, 455);
+ ConnEnd srcPt455(Point(-77.87164351502003, 1164.856854916126), 8);
+ connRef455->setSourceEndpoint(srcPt455);
+ ConnEnd dstPt455(Point(181.62835648698, 1143.856854916126), 15);
+ connRef455->setDestEndpoint(dstPt455);
+ connRef455->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints455(1);
+ checkpoints455[0] = Checkpoint(Point(-54.87164351502003, 1143.856854916126), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef455->setRoutingCheckpoints(checkpoints455);
+
+ ConnRef *connRef456 = new ConnRef(router, 456);
+ ConnEnd srcPt456(Point(-107.87164351502, 1122.856854916126), 4);
+ connRef456->setSourceEndpoint(srcPt456);
+ ConnEnd dstPt456(Point(-319.87164351602, 1143.856854916126), 15);
+ connRef456->setDestEndpoint(dstPt456);
+ connRef456->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints456(1);
+ checkpoints456[0] = Checkpoint(Point(-130.87164351502, 1143.856854916126), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef456->setRoutingCheckpoints(checkpoints456);
+
+ ConnRef *connRef457 = new ConnRef(router, 457);
+ ConnEnd srcPt457(Point(-77.87164351502003, 1122.856854916126), 8);
+ connRef457->setSourceEndpoint(srcPt457);
+ ConnEnd dstPt457(Point(181.62835648698, 1143.856854916126), 15);
+ connRef457->setDestEndpoint(dstPt457);
+ connRef457->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints457(1);
+ checkpoints457[0] = Checkpoint(Point(-54.87164351502003, 1143.856854916126), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef457->setRoutingCheckpoints(checkpoints457);
+
+ ConnRef *connRef458 = new ConnRef(router, 458);
+ ConnEnd srcPt458(Point(313.62835648698, 1122.856854916126), 4);
+ connRef458->setSourceEndpoint(srcPt458);
+ ConnEnd dstPt458(Point(181.62835648698, 1143.856854916126), 15);
+ connRef458->setDestEndpoint(dstPt458);
+ connRef458->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints458(1);
+ checkpoints458[0] = Checkpoint(Point(290.62835648698, 1143.856854916126), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef458->setRoutingCheckpoints(checkpoints458);
+
+ ConnRef *connRef459 = new ConnRef(router, 459);
+ ConnEnd srcPt459(Point(343.62835648698, 1122.856854916126), 8);
+ connRef459->setSourceEndpoint(srcPt459);
+ ConnEnd dstPt459(Point(530.62835648798, 1143.856854916126), 15);
+ connRef459->setDestEndpoint(dstPt459);
+ connRef459->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints459(1);
+ checkpoints459[0] = Checkpoint(Point(366.62835648698, 1143.856854916126), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef459->setRoutingCheckpoints(checkpoints459);
+
+ ConnRef *connRef460 = new ConnRef(router, 460);
+ ConnEnd srcPt460(Point(830.62835648898, 1110.856854916126), 4);
+ connRef460->setSourceEndpoint(srcPt460);
+ ConnEnd dstPt460(Point(530.62835648798, 1143.856854916126), 15);
+ connRef460->setDestEndpoint(dstPt460);
+ connRef460->setRoutingType((ConnType)2);
+
+ ConnRef *connRef461 = new ConnRef(router, 461);
+ ConnEnd srcPt461(Point(982.9140707746942, 1143.856854916126), 15);
+ connRef461->setSourceEndpoint(srcPt461);
+ ConnEnd dstPt461(Point(860.62835648898, 1110.856854916126), 8);
+ connRef461->setDestEndpoint(dstPt461);
+ connRef461->setRoutingType((ConnType)2);
+
+ ConnRef *connRef462 = new ConnRef(router, 462);
+ ConnEnd srcPt462(Point(961.9140707746942, 901.8568549171259), 2);
+ connRef462->setSourceEndpoint(srcPt462);
+ ConnEnd dstPt462(Point(982.9140707746942, 1143.856854916126), 15);
+ connRef462->setDestEndpoint(dstPt462);
+ connRef462->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints462(1);
+ checkpoints462[0] = Checkpoint(Point(982.9140707746942, 916.8568549171259), (ConnDirFlags) 15, (ConnDirFlags) 1);
+ connRef462->setRoutingCheckpoints(checkpoints462);
+
+ ConnRef *connRef463 = new ConnRef(router, 463);
+ ConnEnd srcPt463(Point(1167.12835648898, 996.8568549161259), 1);
+ connRef463->setSourceEndpoint(srcPt463);
+ ConnEnd dstPt463(Point(1514.12835648898, -298.4098117515406), 15);
+ connRef463->setDestEndpoint(dstPt463);
+ connRef463->setRoutingType((ConnType)2);
+
+ ConnRef *connRef464 = new ConnRef(router, 464);
+ ConnEnd srcPt464(Point(982.9140707746942, 1143.856854916126), 15);
+ connRef464->setSourceEndpoint(srcPt464);
+ ConnEnd dstPt464(Point(1167.12835648898, 1026.856854916126), 2);
+ connRef464->setDestEndpoint(dstPt464);
+ connRef464->setRoutingType((ConnType)2);
+
+ ConnRef *connRef465 = new ConnRef(router, 465);
+ ConnEnd srcPt465(Point(1167.12835648898, 1095.856854916126), 1);
+ connRef465->setSourceEndpoint(srcPt465);
+ ConnEnd dstPt465(Point(1514.12835648898, -298.4098117515406), 15);
+ connRef465->setDestEndpoint(dstPt465);
+ connRef465->setRoutingType((ConnType)2);
+
+ ConnRef *connRef466 = new ConnRef(router, 466);
+ ConnEnd srcPt466(Point(982.9140707746942, 1143.856854916126), 15);
+ connRef466->setSourceEndpoint(srcPt466);
+ ConnEnd dstPt466(Point(1167.12835648898, 1125.856854916126), 2);
+ connRef466->setDestEndpoint(dstPt466);
+ connRef466->setRoutingType((ConnType)2);
+
+ ConnRef *connRef467 = new ConnRef(router, 467);
+ ConnEnd srcPt467(Point(1182.12835648898, 1176.856854916126), 8);
+ connRef467->setSourceEndpoint(srcPt467);
+ ConnEnd dstPt467(Point(1514.12835648898, -298.4098117515406), 15);
+ connRef467->setDestEndpoint(dstPt467);
+ connRef467->setRoutingType((ConnType)2);
+
+ ConnRef *connRef468 = new ConnRef(router, 468);
+ ConnEnd srcPt468(Point(982.9140707746942, 1143.856854916126), 15);
+ connRef468->setSourceEndpoint(srcPt468);
+ ConnEnd dstPt468(Point(1152.12835648898, 1176.856854916126), 4);
+ connRef468->setDestEndpoint(dstPt468);
+ connRef468->setRoutingType((ConnType)2);
+
+ ConnRef *connRef469 = new ConnRef(router, 469);
+ ConnEnd srcPt469(Point(31.62835648497997, 1390.606854916126), 2);
+ connRef469->setSourceEndpoint(srcPt469);
+ ConnEnd dstPt469(Point(115.62835648698, 1466.106854916126), 15);
+ connRef469->setDestEndpoint(dstPt469);
+ connRef469->setRoutingType((ConnType)2);
+
+ ConnRef *connRef470 = new ConnRef(router, 470);
+ ConnEnd srcPt470(Point(551.62835648798, 1357.606854916126), 2);
+ connRef470->setSourceEndpoint(srcPt470);
+ ConnEnd dstPt470(Point(530.62835648798, 1647.106854917126), 15);
+ connRef470->setDestEndpoint(dstPt470);
+ connRef470->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints470(1);
+ checkpoints470[0] = Checkpoint(Point(530.62835648798, 1372.606854916126), (ConnDirFlags) 15, (ConnDirFlags) 1);
+ connRef470->setRoutingCheckpoints(checkpoints470);
+
+ ConnRef *connRef471 = new ConnRef(router, 471);
+ ConnEnd srcPt471(Point(551.62835648798, 1327.606854916126), 1);
+ connRef471->setSourceEndpoint(srcPt471);
+ ConnEnd dstPt471(Point(530.62835648798, 1143.856854916126), 15);
+ connRef471->setDestEndpoint(dstPt471);
+ connRef471->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints471(1);
+ checkpoints471[0] = Checkpoint(Point(530.62835648798, 1312.606854916126), (ConnDirFlags) 15, (ConnDirFlags) 2);
+ connRef471->setRoutingCheckpoints(checkpoints471);
+
+ ConnRef *connRef472 = new ConnRef(router, 472);
+ ConnEnd srcPt472(Point(-516.87164351602, 1647.106854917126), 4);
+ connRef472->setSourceEndpoint(srcPt472);
+ ConnEnd dstPt472(Point(-695.12164351602, 1647.106854917126), 15);
+ connRef472->setDestEndpoint(dstPt472);
+ connRef472->setRoutingType((ConnType)2);
+
+ ConnRef *connRef473 = new ConnRef(router, 473);
+ ConnEnd srcPt473(Point(-319.87164351602, 1647.106854917126), 15);
+ connRef473->setSourceEndpoint(srcPt473);
+ ConnEnd dstPt473(Point(-486.87164351602, 1647.106854917126), 8);
+ connRef473->setDestEndpoint(dstPt473);
+ connRef473->setRoutingType((ConnType)2);
+
+ ConnRef *connRef474 = new ConnRef(router, 474);
+ ConnEnd srcPt474(Point(-74.87164351502003, 1668.106854917126), 4);
+ connRef474->setSourceEndpoint(srcPt474);
+ ConnEnd dstPt474(Point(-319.87164351602, 1647.106854917126), 15);
+ connRef474->setDestEndpoint(dstPt474);
+ connRef474->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints474(1);
+ checkpoints474[0] = Checkpoint(Point(-97.87164351502003, 1647.106854917126), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef474->setRoutingCheckpoints(checkpoints474);
+
+ ConnRef *connRef475 = new ConnRef(router, 475);
+ ConnEnd srcPt475(Point(-44.87164351502003, 1668.106854917126), 8);
+ connRef475->setSourceEndpoint(srcPt475);
+ ConnEnd dstPt475(Point(181.62835648698, 1647.106854917126), 15);
+ connRef475->setDestEndpoint(dstPt475);
+ connRef475->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints475(1);
+ checkpoints475[0] = Checkpoint(Point(-21.87164351502003, 1647.106854917126), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef475->setRoutingCheckpoints(checkpoints475);
+
+ ConnRef *connRef476 = new ConnRef(router, 476);
+ ConnEnd srcPt476(Point(-44.87164351502003, 1551.106854917126), 8);
+ connRef476->setSourceEndpoint(srcPt476);
+ ConnEnd dstPt476(Point(181.62835648698, 1647.106854917126), 15);
+ connRef476->setDestEndpoint(dstPt476);
+ connRef476->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints476(1);
+ checkpoints476[0] = Checkpoint(Point(-21.87164351502003, 1647.106854917126), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef476->setRoutingCheckpoints(checkpoints476);
+
+ ConnRef *connRef477 = new ConnRef(router, 477);
+ ConnEnd srcPt477(Point(-44.87164351502003, 1626.106854917126), 8);
+ connRef477->setSourceEndpoint(srcPt477);
+ ConnEnd dstPt477(Point(181.62835648698, 1647.106854917126), 15);
+ connRef477->setDestEndpoint(dstPt477);
+ connRef477->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints477(1);
+ checkpoints477[0] = Checkpoint(Point(-21.87164351502003, 1647.106854917126), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef477->setRoutingCheckpoints(checkpoints477);
+
+ ConnRef *connRef478 = new ConnRef(router, 478);
+ ConnEnd srcPt478(Point(379.62835648698, 1668.106854917126), 4);
+ connRef478->setSourceEndpoint(srcPt478);
+ ConnEnd dstPt478(Point(181.62835648698, 1647.106854917126), 15);
+ connRef478->setDestEndpoint(dstPt478);
+ connRef478->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints478(1);
+ checkpoints478[0] = Checkpoint(Point(356.62835648698, 1647.106854917126), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef478->setRoutingCheckpoints(checkpoints478);
+
+ ConnRef *connRef479 = new ConnRef(router, 479);
+ ConnEnd srcPt479(Point(409.62835648698, 1668.106854917126), 8);
+ connRef479->setSourceEndpoint(srcPt479);
+ ConnEnd dstPt479(Point(530.62835648798, 1647.106854917126), 15);
+ connRef479->setDestEndpoint(dstPt479);
+ connRef479->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints479(1);
+ checkpoints479[0] = Checkpoint(Point(432.62835648698, 1647.106854917126), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef479->setRoutingCheckpoints(checkpoints479);
+
+ ConnRef *connRef480 = new ConnRef(router, 480);
+ ConnEnd srcPt480(Point(409.62835648698, 1626.106854917126), 8);
+ connRef480->setSourceEndpoint(srcPt480);
+ ConnEnd dstPt480(Point(530.62835648798, 1647.106854917126), 15);
+ connRef480->setDestEndpoint(dstPt480);
+ connRef480->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints480(1);
+ checkpoints480[0] = Checkpoint(Point(432.62835648698, 1647.106854917126), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef480->setRoutingCheckpoints(checkpoints480);
+
+ ConnRef *connRef481 = new ConnRef(router, 481);
+ ConnEnd srcPt481(Point(647.9873402531949, 1626.106854917126), 8);
+ connRef481->setSourceEndpoint(srcPt481);
+ ConnEnd dstPt481(Point(982.9140707746942, 1647.106854917126), 15);
+ connRef481->setDestEndpoint(dstPt481);
+ connRef481->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints481(1);
+ checkpoints481[0] = Checkpoint(Point(670.9873402531949, 1647.106854917126), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef481->setRoutingCheckpoints(checkpoints481);
+
+ ConnRef *connRef482 = new ConnRef(router, 482);
+ ConnEnd srcPt482(Point(617.9873402531949, 1668.106854917126), 4);
+ connRef482->setSourceEndpoint(srcPt482);
+ ConnEnd dstPt482(Point(530.62835648798, 1647.106854917126), 15);
+ connRef482->setDestEndpoint(dstPt482);
+ connRef482->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints482(1);
+ checkpoints482[0] = Checkpoint(Point(594.9873402531949, 1647.106854917126), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef482->setRoutingCheckpoints(checkpoints482);
+
+ ConnRef *connRef483 = new ConnRef(router, 483);
+ ConnEnd srcPt483(Point(647.9873402531949, 1668.106854917126), 8);
+ connRef483->setSourceEndpoint(srcPt483);
+ ConnEnd dstPt483(Point(982.9140707746942, 1647.106854917126), 15);
+ connRef483->setDestEndpoint(dstPt483);
+ connRef483->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints483(1);
+ checkpoints483[0] = Checkpoint(Point(670.9873402531949, 1647.106854917126), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef483->setRoutingCheckpoints(checkpoints483);
+
+ ConnRef *connRef484 = new ConnRef(router, 484);
+ ConnEnd srcPt484(Point(1182.12835648898, 1567.106854916126), 8);
+ connRef484->setSourceEndpoint(srcPt484);
+ ConnEnd dstPt484(Point(1514.12835648898, 1647.106854917126), 15);
+ connRef484->setDestEndpoint(dstPt484);
+ connRef484->setRoutingType((ConnType)2);
+
+ ConnRef *connRef485 = new ConnRef(router, 485);
+ ConnEnd srcPt485(Point(1182.12835648898, 1706.773521583792), 8);
+ connRef485->setSourceEndpoint(srcPt485);
+ ConnEnd dstPt485(Point(1396.12835648898, 1739.773521583792), 15);
+ connRef485->setDestEndpoint(dstPt485);
+ connRef485->setRoutingType((ConnType)2);
+
+ ConnRef *connRef486 = new ConnRef(router, 486);
+ ConnEnd srcPt486(Point(1182.12835648898, 1706.773521583792), 8);
+ connRef486->setSourceEndpoint(srcPt486);
+ ConnEnd dstPt486(Point(1514.12835648898, 1647.106854917126), 15);
+ connRef486->setDestEndpoint(dstPt486);
+ connRef486->setRoutingType((ConnType)2);
+
+ ConnRef *connRef487 = new ConnRef(router, 487);
+ ConnEnd srcPt487(Point(1345.12835648898, 1433.106854916126), 8);
+ connRef487->setSourceEndpoint(srcPt487);
+ ConnEnd dstPt487(Point(1514.12835648898, 1647.106854917126), 15);
+ connRef487->setDestEndpoint(dstPt487);
+ connRef487->setRoutingType((ConnType)2);
+
+ ConnRef *connRef488 = new ConnRef(router, 488);
+ ConnEnd srcPt488(Point(1642.12835648998, 1309.606854916126), 8);
+ connRef488->setSourceEndpoint(srcPt488);
+ ConnEnd dstPt488(Point(1700.12835648998, 1309.606854916126), 15);
+ connRef488->setDestEndpoint(dstPt488);
+ connRef488->setRoutingType((ConnType)2);
+
+ ConnRef *connRef489 = new ConnRef(router, 489);
+ ConnEnd srcPt489(Point(1514.12835648898, 1647.106854917126), 15);
+ connRef489->setSourceEndpoint(srcPt489);
+ ConnEnd dstPt489(Point(1612.12835648998, 1309.606854916126), 4);
+ connRef489->setDestEndpoint(dstPt489);
+ connRef489->setRoutingType((ConnType)2);
+
+ ConnRef *connRef490 = new ConnRef(router, 490);
+ ConnEnd srcPt490(Point(1579.12835648998, 1626.106854917126), 4);
+ connRef490->setSourceEndpoint(srcPt490);
+ ConnEnd dstPt490(Point(1514.12835648898, 1647.106854917126), 15);
+ connRef490->setDestEndpoint(dstPt490);
+ connRef490->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints490(1);
+ checkpoints490[0] = Checkpoint(Point(1556.12835648998, 1647.106854917126), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef490->setRoutingCheckpoints(checkpoints490);
+
+ ConnRef *connRef491 = new ConnRef(router, 491);
+ ConnEnd srcPt491(Point(1609.12835648998, 1626.106854917126), 8);
+ connRef491->setSourceEndpoint(srcPt491);
+ ConnEnd dstPt491(Point(1700.12835648998, 1647.106854917126), 15);
+ connRef491->setDestEndpoint(dstPt491);
+ connRef491->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints491(1);
+ checkpoints491[0] = Checkpoint(Point(1632.12835648998, 1647.106854917126), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef491->setRoutingCheckpoints(checkpoints491);
+
+ ConnRef *connRef492 = new ConnRef(router, 492);
+ ConnEnd srcPt492(Point(1579.12835648998, 1668.106854917126), 4);
+ connRef492->setSourceEndpoint(srcPt492);
+ ConnEnd dstPt492(Point(1514.12835648898, 1647.106854917126), 15);
+ connRef492->setDestEndpoint(dstPt492);
+ connRef492->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints492(1);
+ checkpoints492[0] = Checkpoint(Point(1556.12835648998, 1647.106854917126), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef492->setRoutingCheckpoints(checkpoints492);
+
+ ConnRef *connRef493 = new ConnRef(router, 493);
+ ConnEnd srcPt493(Point(1609.12835648998, 1668.106854917126), 8);
+ connRef493->setSourceEndpoint(srcPt493);
+ ConnEnd dstPt493(Point(1700.12835648998, 1647.106854917126), 15);
+ connRef493->setDestEndpoint(dstPt493);
+ connRef493->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints493(1);
+ checkpoints493[0] = Checkpoint(Point(1632.12835648998, 1647.106854917126), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef493->setRoutingCheckpoints(checkpoints493);
+
+ ConnRef *connRef494 = new ConnRef(router, 494);
+ ConnEnd srcPt494(Point(1785.12835649098, 1309.606854916126), 8);
+ connRef494->setSourceEndpoint(srcPt494);
+ ConnEnd dstPt494(Point(1873.12835649198, 1309.606854916126), 15);
+ connRef494->setDestEndpoint(dstPt494);
+ connRef494->setRoutingType((ConnType)2);
+
+ ConnRef *connRef495 = new ConnRef(router, 495);
+ ConnEnd srcPt495(Point(1785.12835649098, 1647.106854917126), 8);
+ connRef495->setSourceEndpoint(srcPt495);
+ ConnEnd dstPt495(Point(1873.12835649198, 1647.106854917126), 15);
+ connRef495->setDestEndpoint(dstPt495);
+ connRef495->setRoutingType((ConnType)2);
+
+ ConnRef *connRef496 = new ConnRef(router, 496);
+ ConnEnd srcPt496(Point(1958.12835649298, 1647.106854917126), 8);
+ connRef496->setSourceEndpoint(srcPt496);
+ ConnEnd dstPt496(Point(2046.795023159646, 1647.106854917126), 15);
+ connRef496->setDestEndpoint(dstPt496);
+ connRef496->setRoutingType((ConnType)2);
+
+ ConnRef *connRef497 = new ConnRef(router, 497);
+ ConnEnd srcPt497(Point(-453.87164351602, -716.9812403239691), 8);
+ connRef497->setSourceEndpoint(srcPt497);
+ ConnEnd dstPt497(Point(-226.87164351502, -737.9812403239691), 15);
+ connRef497->setDestEndpoint(dstPt497);
+ connRef497->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints497(1);
+ checkpoints497[0] = Checkpoint(Point(-430.87164351602, -737.9812403239691), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef497->setRoutingCheckpoints(checkpoints497);
+
+ ConnRef *connRef498 = new ConnRef(router, 498);
+ ConnEnd srcPt498(Point(376.62835648698, 759.8568549161259), 8);
+ connRef498->setSourceEndpoint(srcPt498);
+ ConnEnd dstPt498(Point(530.62835648798, 738.8568549161259), 15);
+ connRef498->setDestEndpoint(dstPt498);
+ connRef498->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints498(1);
+ checkpoints498[0] = Checkpoint(Point(399.62835648698, 738.8568549161259), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef498->setRoutingCheckpoints(checkpoints498);
+
+ ConnRef *connRef499 = new ConnRef(router, 499);
+ ConnEnd srcPt499(Point(313.62835648698, 1164.856854916126), 4);
+ connRef499->setSourceEndpoint(srcPt499);
+ ConnEnd dstPt499(Point(181.62835648698, 1143.856854916126), 15);
+ connRef499->setDestEndpoint(dstPt499);
+ connRef499->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints499(1);
+ checkpoints499[0] = Checkpoint(Point(290.62835648698, 1143.856854916126), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef499->setRoutingCheckpoints(checkpoints499);
+
+ ConnRef *connRef500 = new ConnRef(router, 500);
+ ConnEnd srcPt500(Point(343.62835648698, 1164.856854916126), 8);
+ connRef500->setSourceEndpoint(srcPt500);
+ ConnEnd dstPt500(Point(530.62835648798, 1143.856854916126), 15);
+ connRef500->setDestEndpoint(dstPt500);
+ connRef500->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints500(1);
+ checkpoints500[0] = Checkpoint(Point(366.62835648698, 1143.856854916126), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef500->setRoutingCheckpoints(checkpoints500);
+
+ ConnRef *connRef501 = new ConnRef(router, 501);
+ ConnEnd srcPt501(Point(1003.914070774694, 901.8568549171259), 2);
+ connRef501->setSourceEndpoint(srcPt501);
+ ConnEnd dstPt501(Point(982.9140707746942, 1143.856854916126), 15);
+ connRef501->setDestEndpoint(dstPt501);
+ connRef501->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints501(1);
+ checkpoints501[0] = Checkpoint(Point(982.9140707746942, 916.8568549171259), (ConnDirFlags) 15, (ConnDirFlags) 1);
+ connRef501->setRoutingCheckpoints(checkpoints501);
+
+ ConnRef *connRef502 = new ConnRef(router, 502);
+ ConnEnd srcPt502(Point(1642.12835648998, -618.4098117525407), 8);
+ connRef502->setSourceEndpoint(srcPt502);
+ ConnEnd dstPt502(Point(1700.12835648998, -558.5348117525407), 15);
+ connRef502->setDestEndpoint(dstPt502);
+ connRef502->setRoutingType((ConnType)2);
+
+ ConnRef *connRef503 = new ConnRef(router, 503);
+ ConnEnd srcPt503(Point(1788.12835649098, -558.5348117525407), 4);
+ connRef503->setSourceEndpoint(srcPt503);
+ ConnEnd dstPt503(Point(1700.12835648998, -558.5348117525407), 15);
+ connRef503->setDestEndpoint(dstPt503);
+ connRef503->setRoutingType((ConnType)2);
+
+ ConnRef *connRef504 = new ConnRef(router, 504);
+ ConnEnd srcPt504(Point(475.62835648698, -737.9812403239691), 8);
+ connRef504->setSourceEndpoint(srcPt504);
+ ConnEnd dstPt504(Point(530.62835648798, -298.4098117515406), 15);
+ connRef504->setDestEndpoint(dstPt504);
+ connRef504->setRoutingType((ConnType)2);
+
+ ConnRef *connRef505 = new ConnRef(router, 505);
+ ConnEnd srcPt505(Point(717.62835648798, -807.4098117525407), 4);
+ connRef505->setSourceEndpoint(srcPt505);
+ ConnEnd dstPt505(Point(530.62835648798, -298.4098117515406), 15);
+ connRef505->setDestEndpoint(dstPt505);
+ connRef505->setRoutingType((ConnType)2);
+
+ ConnRef *connRef506 = new ConnRef(router, 506);
+ ConnEnd srcPt506(Point(717.62835648798, -681.4098117525407), 4);
+ connRef506->setSourceEndpoint(srcPt506);
+ ConnEnd dstPt506(Point(530.62835648798, -298.4098117515406), 15);
+ connRef506->setDestEndpoint(dstPt506);
+ connRef506->setRoutingType((ConnType)2);
+
+ ConnRef *connRef507 = new ConnRef(router, 507);
+ ConnEnd srcPt507(Point(982.9140707746942, -449.4098117525406), 2);
+ connRef507->setSourceEndpoint(srcPt507);
+ ConnEnd dstPt507(Point(982.9140707746942, -298.4098117515406), 15);
+ connRef507->setDestEndpoint(dstPt507);
+ connRef507->setRoutingType((ConnType)2);
+
+ ConnRef *connRef508 = new ConnRef(router, 508);
+ ConnEnd srcPt508(Point(1068.12835648898, -558.5348117525407), 15);
+ connRef508->setSourceEndpoint(srcPt508);
+ ConnEnd dstPt508(Point(982.9140707746942, -479.4098117525406), 1);
+ connRef508->setDestEndpoint(dstPt508);
+ connRef508->setRoutingType((ConnType)2);
+
+ ConnRef *connRef509 = new ConnRef(router, 509);
+ ConnEnd srcPt509(Point(1216.12835648898, -558.5348117525407), 4);
+ connRef509->setSourceEndpoint(srcPt509);
+ ConnEnd dstPt509(Point(1068.12835648898, -558.5348117525407), 15);
+ connRef509->setDestEndpoint(dstPt509);
+ connRef509->setRoutingType((ConnType)2);
+
+ ConnRef *connRef510 = new ConnRef(router, 510);
+ ConnEnd srcPt510(Point(-319.87164351602, -298.4098117515406), 15);
+ connRef510->setSourceEndpoint(srcPt510);
+ ConnEnd dstPt510(Point(166.62835648698, -126.4098117515406), 4);
+ connRef510->setDestEndpoint(dstPt510);
+ connRef510->setRoutingType((ConnType)2);
+
+ ConnRef *connRef511 = new ConnRef(router, 511);
+ ConnEnd srcPt511(Point(196.62835648698, -126.4098117515406), 8);
+ connRef511->setSourceEndpoint(srcPt511);
+ ConnEnd dstPt511(Point(530.62835648798, -298.4098117515406), 15);
+ connRef511->setDestEndpoint(dstPt511);
+ connRef511->setRoutingType((ConnType)2);
+
+ ConnRef *connRef512 = new ConnRef(router, 512);
+ ConnEnd srcPt512(Point(651.62835648798, -20.40981175154064), 4);
+ connRef512->setSourceEndpoint(srcPt512);
+ ConnEnd dstPt512(Point(530.62835648798, 66.25685491512604), 15);
+ connRef512->setDestEndpoint(dstPt512);
+ connRef512->setRoutingType((ConnType)2);
+
+ ConnRef *connRef513 = new ConnRef(router, 513);
+ ConnEnd srcPt513(Point(926.62835648898, 421.7568549161261), 8);
+ connRef513->setSourceEndpoint(srcPt513);
+ ConnEnd dstPt513(Point(982.9140707746942, 66.25685491512604), 15);
+ connRef513->setDestEndpoint(dstPt513);
+ connRef513->setRoutingType((ConnType)2);
+
+ ConnRef *connRef514 = new ConnRef(router, 514);
+ ConnEnd srcPt514(Point(563.62835648798, 421.7568549161261), 15);
+ connRef514->setSourceEndpoint(srcPt514);
+ ConnEnd dstPt514(Point(896.62835648898, 421.7568549161261), 4);
+ connRef514->setDestEndpoint(dstPt514);
+ connRef514->setRoutingType((ConnType)2);
+
+ ConnRef *connRef515 = new ConnRef(router, 515);
+ ConnEnd srcPt515(Point(508.62835648698, 421.7568549161261), 8);
+ connRef515->setSourceEndpoint(srcPt515);
+ ConnEnd dstPt515(Point(563.62835648798, 421.7568549161261), 15);
+ connRef515->setDestEndpoint(dstPt515);
+ connRef515->setRoutingType((ConnType)2);
+
+ ConnRef *connRef516 = new ConnRef(router, 516);
+ ConnEnd srcPt516(Point(116.62835648598, 1063.856854916126), 8);
+ connRef516->setSourceEndpoint(srcPt516);
+ ConnEnd dstPt516(Point(530.62835648798, 1143.856854916126), 15);
+ connRef516->setDestEndpoint(dstPt516);
+ connRef516->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints516(1);
+ checkpoints516[0] = Checkpoint(Point(139.62835648598, 1042.856854916126), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef516->setRoutingCheckpoints(checkpoints516);
+
+ ConnRef *connRef517 = new ConnRef(router, 517);
+ ConnEnd srcPt517(Point(16.62835648497997, -558.5348117525407), 4);
+ connRef517->setSourceEndpoint(srcPt517);
+ ConnEnd dstPt517(Point(-319.87164351602, -298.4098117515406), 15);
+ connRef517->setDestEndpoint(dstPt517);
+ connRef517->setRoutingType((ConnType)2);
+#endif
+ ConnRef *connRef518 = new ConnRef(router, 518);
+ ConnEnd srcPt518(Point(-483.87164351602, -833.9812403239691), 4);
+ connRef518->setSourceEndpoint(srcPt518);
+ ConnEnd dstPt518(Point(-695.12164351602, -737.9812403239691), 15);
+ connRef518->setDestEndpoint(dstPt518);
+ connRef518->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints518(1);
+ checkpoints518[0] = Checkpoint(Point(-506.87164351602, -737.9812403239691), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef518->setRoutingCheckpoints(checkpoints518);
+
+ ConnRef *connRef519 = new ConnRef(router, 519);
+ ConnEnd srcPt519(Point(-483.87164351602, -758.9812403239691), 4);
+ connRef519->setSourceEndpoint(srcPt519);
+ ConnEnd dstPt519(Point(-695.12164351602, -737.9812403239691), 15);
+ connRef519->setDestEndpoint(dstPt519);
+ connRef519->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints519(1);
+ checkpoints519[0] = Checkpoint(Point(-506.87164351602, -737.9812403239691), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef519->setRoutingCheckpoints(checkpoints519);
+
+ ConnRef *connRef520 = new ConnRef(router, 520);
+ ConnEnd srcPt520(Point(-483.87164351602, -716.9812403239691), 4);
+ connRef520->setSourceEndpoint(srcPt520);
+ ConnEnd dstPt520(Point(-695.12164351602, -737.9812403239691), 15);
+ connRef520->setDestEndpoint(dstPt520);
+ connRef520->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints520(1);
+ checkpoints520[0] = Checkpoint(Point(-506.87164351602, -737.9812403239691), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef520->setRoutingCheckpoints(checkpoints520);
+
+#ifdef REST
+ ConnRef *connRef521 = new ConnRef(router, 521);
+ ConnEnd srcPt521(Point(262.62835648698, -737.9812403239691), 15);
+ connRef521->setSourceEndpoint(srcPt521);
+ ConnEnd dstPt521(Point(445.62835648698, -737.9812403239691), 4);
+ connRef521->setDestEndpoint(dstPt521);
+ connRef521->setRoutingType((ConnType)2);
+
+ ConnRef *connRef522 = new ConnRef(router, 522);
+ ConnEnd srcPt522(Point(-841.12164351602, 668.6568549161261), 15);
+ connRef522->setSourceEndpoint(srcPt522);
+ ConnEnd dstPt522(Point(-728.12164351602, 756.8568549161259), 1);
+ connRef522->setDestEndpoint(dstPt522);
+ connRef522->setRoutingType((ConnType)2);
+
+ ConnRef *connRef523 = new ConnRef(router, 523);
+ ConnEnd srcPt523(Point(-841.12164351602, 890.8568549161259), 15);
+ connRef523->setSourceEndpoint(srcPt523);
+ ConnEnd dstPt523(Point(-874.12164351602, 786.8568549161259), 2);
+ connRef523->setDestEndpoint(dstPt523);
+ connRef523->setRoutingType((ConnType)2);
+
+ ConnRef *connRef524 = new ConnRef(router, 524);
+ ConnEnd srcPt524(Point(412.62835648698, -469.4098117515406), 4);
+ connRef524->setSourceEndpoint(srcPt524);
+ ConnEnd dstPt524(Point(181.62835648698, -298.4098117515406), 15);
+ connRef524->setDestEndpoint(dstPt524);
+ connRef524->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints524(1);
+ checkpoints524[0] = Checkpoint(Point(389.62835648698, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef524->setRoutingCheckpoints(checkpoints524);
+
+ ConnRef *connRef525 = new ConnRef(router, 525);
+ ConnEnd srcPt525(Point(412.62835648698, -394.4098117515406), 4);
+ connRef525->setSourceEndpoint(srcPt525);
+ ConnEnd dstPt525(Point(181.62835648698, -298.4098117515406), 15);
+ connRef525->setDestEndpoint(dstPt525);
+ connRef525->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints525(1);
+ checkpoints525[0] = Checkpoint(Point(389.62835648698, -298.4098117515406), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef525->setRoutingCheckpoints(checkpoints525);
+
+ ConnRef *connRef526 = new ConnRef(router, 526);
+ ConnEnd srcPt526(Point(1514.12835648898, -298.4098117515406), 15);
+ connRef526->setSourceEndpoint(srcPt526);
+ ConnEnd dstPt526(Point(1612.12835648998, -618.4098117525407), 4);
+ connRef526->setDestEndpoint(dstPt526);
+ connRef526->setRoutingType((ConnType)2);
+
+ ConnRef *connRef527 = new ConnRef(router, 527);
+ ConnEnd srcPt527(Point(1514.12835648898, -298.4098117515406), 15);
+ connRef527->setSourceEndpoint(srcPt527);
+ ConnEnd dstPt527(Point(1543.12835648898, 635.6568549161261), 4);
+ connRef527->setDestEndpoint(dstPt527);
+ connRef527->setRoutingType((ConnType)2);
+
+ ConnRef *connRef528 = new ConnRef(router, 528);
+ ConnEnd srcPt528(Point(1514.12835648898, -298.4098117515406), 15);
+ connRef528->setSourceEndpoint(srcPt528);
+ ConnEnd dstPt528(Point(1612.12835648998, -497.4098117525407), 4);
+ connRef528->setDestEndpoint(dstPt528);
+ connRef528->setRoutingType((ConnType)2);
+
+ ConnRef *connRef529 = new ConnRef(router, 529);
+ ConnEnd srcPt529(Point(-695.12164351602, 66.25685491512604), 15);
+ connRef529->setSourceEndpoint(srcPt529);
+ ConnEnd dstPt529(Point(-516.87164351602, 201.256854916126), 4);
+ connRef529->setDestEndpoint(dstPt529);
+ connRef529->setRoutingType((ConnType)2);
+
+ ConnRef *connRef530 = new ConnRef(router, 530);
+ ConnEnd srcPt530(Point(-319.87164351602, 66.25685491512604), 15);
+ connRef530->setSourceEndpoint(srcPt530);
+ ConnEnd dstPt530(Point(-319.87164351602, 505.756854916126), 1);
+ connRef530->setDestEndpoint(dstPt530);
+ connRef530->setRoutingType((ConnType)2);
+
+ ConnRef *connRef531 = new ConnRef(router, 531);
+ ConnEnd srcPt531(Point(-74.87164351502003, 1551.106854917126), 4);
+ connRef531->setSourceEndpoint(srcPt531);
+ ConnEnd dstPt531(Point(-319.87164351602, 1647.106854917126), 15);
+ connRef531->setDestEndpoint(dstPt531);
+ connRef531->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints531(1);
+ checkpoints531[0] = Checkpoint(Point(-97.87164351502003, 1647.106854917126), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef531->setRoutingCheckpoints(checkpoints531);
+
+ ConnRef *connRef532 = new ConnRef(router, 532);
+ ConnEnd srcPt532(Point(-74.87164351502003, 1626.106854917126), 4);
+ connRef532->setSourceEndpoint(srcPt532);
+ ConnEnd dstPt532(Point(-319.87164351602, 1647.106854917126), 15);
+ connRef532->setDestEndpoint(dstPt532);
+ connRef532->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints532(1);
+ checkpoints532[0] = Checkpoint(Point(-97.87164351502003, 1647.106854917126), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef532->setRoutingCheckpoints(checkpoints532);
+
+ ConnRef *connRef533 = new ConnRef(router, 533);
+ ConnEnd srcPt533(Point(379.62835648698, 1626.106854917126), 4);
+ connRef533->setSourceEndpoint(srcPt533);
+ ConnEnd dstPt533(Point(181.62835648698, 1647.106854917126), 15);
+ connRef533->setDestEndpoint(dstPt533);
+ connRef533->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints533(1);
+ checkpoints533[0] = Checkpoint(Point(356.62835648698, 1647.106854917126), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef533->setRoutingCheckpoints(checkpoints533);
+
+ ConnRef *connRef534 = new ConnRef(router, 534);
+ ConnEnd srcPt534(Point(617.9873402531949, 1626.106854917126), 4);
+ connRef534->setSourceEndpoint(srcPt534);
+ ConnEnd dstPt534(Point(530.62835648798, 1647.106854917126), 15);
+ connRef534->setDestEndpoint(dstPt534);
+ connRef534->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints534(1);
+ checkpoints534[0] = Checkpoint(Point(594.9873402531949, 1647.106854917126), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef534->setRoutingCheckpoints(checkpoints534);
+
+ ConnRef *connRef535 = new ConnRef(router, 535);
+ ConnEnd srcPt535(Point(982.9140707746942, 1647.106854917126), 15);
+ connRef535->setSourceEndpoint(srcPt535);
+ ConnEnd dstPt535(Point(1152.12835648898, 1567.106854916126), 4);
+ connRef535->setDestEndpoint(dstPt535);
+ connRef535->setRoutingType((ConnType)2);
+
+ ConnRef *connRef536 = new ConnRef(router, 536);
+ ConnEnd srcPt536(Point(982.9140707746942, 1647.106854917126), 15);
+ connRef536->setSourceEndpoint(srcPt536);
+ ConnEnd dstPt536(Point(1152.12835648898, 1706.773521583792), 4);
+ connRef536->setDestEndpoint(dstPt536);
+ connRef536->setRoutingType((ConnType)2);
+
+ ConnRef *connRef537 = new ConnRef(router, 537);
+ ConnEnd srcPt537(Point(1700.12835648998, 1309.606854916126), 15);
+ connRef537->setSourceEndpoint(srcPt537);
+ ConnEnd dstPt537(Point(1755.12835649098, 1309.606854916126), 4);
+ connRef537->setDestEndpoint(dstPt537);
+ connRef537->setRoutingType((ConnType)2);
+
+ ConnRef *connRef538 = new ConnRef(router, 538);
+ ConnEnd srcPt538(Point(1134.12835648898, 1433.106854916126), 15);
+ connRef538->setSourceEndpoint(srcPt538);
+ ConnEnd dstPt538(Point(1315.12835648898, 1433.106854916126), 4);
+ connRef538->setDestEndpoint(dstPt538);
+ connRef538->setRoutingType((ConnType)2);
+
+ ConnRef *connRef539 = new ConnRef(router, 539);
+ ConnEnd srcPt539(Point(1700.12835648998, 1647.106854917126), 15);
+ connRef539->setSourceEndpoint(srcPt539);
+ ConnEnd dstPt539(Point(1755.12835649098, 1647.106854917126), 4);
+ connRef539->setDestEndpoint(dstPt539);
+ connRef539->setRoutingType((ConnType)2);
+
+ ConnRef *connRef540 = new ConnRef(router, 540);
+ ConnEnd srcPt540(Point(1873.12835649198, 1647.106854917126), 15);
+ connRef540->setSourceEndpoint(srcPt540);
+ ConnEnd dstPt540(Point(1928.12835649298, 1647.106854917126), 4);
+ connRef540->setDestEndpoint(dstPt540);
+ connRef540->setRoutingType((ConnType)2);
+
+ ConnRef *connRef541 = new ConnRef(router, 541);
+ ConnEnd srcPt541(Point(1700.12835648998, 33.25685491512604), 15);
+ connRef541->setSourceEndpoint(srcPt541);
+ ConnEnd dstPt541(Point(1755.12835649098, 33.25685491512604), 4);
+ connRef541->setDestEndpoint(dstPt541);
+ connRef541->setRoutingType((ConnType)2);
+
+ ConnRef *connRef542 = new ConnRef(router, 542);
+ ConnEnd srcPt542(Point(1873.12835649198, -298.4098117515406), 15);
+ connRef542->setSourceEndpoint(srcPt542);
+ ConnEnd dstPt542(Point(1928.12835649298, -298.4098117515406), 4);
+ connRef542->setDestEndpoint(dstPt542);
+ connRef542->setRoutingType((ConnType)2);
+
+ ConnRef *connRef543 = new ConnRef(router, 543);
+ ConnEnd srcPt543(Point(1700.12835648998, -298.4098117515406), 15);
+ connRef543->setSourceEndpoint(srcPt543);
+ ConnEnd dstPt543(Point(1755.12835649098, -298.4098117515406), 4);
+ connRef543->setDestEndpoint(dstPt543);
+ connRef543->setRoutingType((ConnType)2);
+
+ ConnRef *connRef544 = new ConnRef(router, 544);
+ ConnEnd srcPt544(Point(181.62835648698, 66.25685491512604), 15);
+ connRef544->setSourceEndpoint(srcPt544);
+ ConnEnd dstPt544(Point(181.62835648698, 505.756854916126), 1);
+ connRef544->setDestEndpoint(dstPt544);
+ connRef544->setRoutingType((ConnType)2);
+
+ ConnRef *connRef545 = new ConnRef(router, 545);
+ ConnEnd srcPt545(Point(181.62835648698, 1499.106854916126), 15);
+ connRef545->setSourceEndpoint(srcPt545);
+ ConnEnd dstPt545(Point(181.62835648698, 1390.606854916126), 2);
+ connRef545->setDestEndpoint(dstPt545);
+ connRef545->setRoutingType((ConnType)2);
+
+ ConnRef *connRef546 = new ConnRef(router, 546);
+ ConnEnd srcPt546(Point(115.62835648698, 1466.106854916126), 15);
+ connRef546->setSourceEndpoint(srcPt546);
+ ConnEnd dstPt546(Point(181.62835648698, 1390.606854916126), 2);
+ connRef546->setDestEndpoint(dstPt546);
+ connRef546->setRoutingType((ConnType)2);
+
+ ConnRef *connRef547 = new ConnRef(router, 547);
+ ConnEnd srcPt547(Point(115.62835648698, 1254.856854916126), 15);
+ connRef547->setSourceEndpoint(srcPt547);
+ ConnEnd dstPt547(Point(31.62835648497997, 1360.606854916126), 1);
+ connRef547->setDestEndpoint(dstPt547);
+ connRef547->setRoutingType((ConnType)2);
+
+ ConnRef *connRef548 = new ConnRef(router, 548);
+ ConnEnd srcPt548(Point(86.62835648597996, 1063.856854916126), 4);
+ connRef548->setSourceEndpoint(srcPt548);
+ ConnEnd dstPt548(Point(-319.87164351602, 1143.856854916126), 15);
+ connRef548->setDestEndpoint(dstPt548);
+ connRef548->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints548(1);
+ checkpoints548[0] = Checkpoint(Point(63.62835648597996, 1042.856854916126), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef548->setRoutingCheckpoints(checkpoints548);
+
+ ConnRef *connRef549 = new ConnRef(router, 549);
+ ConnEnd srcPt549(Point(961.9140707746942, 871.8568549171259), 1);
+ connRef549->setSourceEndpoint(srcPt549);
+ ConnEnd dstPt549(Point(982.9140707746942, 738.8568549161259), 15);
+ connRef549->setDestEndpoint(dstPt549);
+ connRef549->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints549(1);
+ checkpoints549[0] = Checkpoint(Point(982.9140707746942, 856.8568549171259), (ConnDirFlags) 15, (ConnDirFlags) 2);
+ connRef549->setRoutingCheckpoints(checkpoints549);
+
+ ConnRef *connRef550 = new ConnRef(router, 550);
+ ConnEnd srcPt550(Point(1003.914070774694, 871.8568549171259), 1);
+ connRef550->setSourceEndpoint(srcPt550);
+ ConnEnd dstPt550(Point(982.9140707746942, 738.8568549161259), 15);
+ connRef550->setDestEndpoint(dstPt550);
+ connRef550->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints550(1);
+ checkpoints550[0] = Checkpoint(Point(982.9140707746942, 856.8568549171259), (ConnDirFlags) 15, (ConnDirFlags) 2);
+ connRef550->setRoutingCheckpoints(checkpoints550);
+
+ ConnRef *connRef551 = new ConnRef(router, 551);
+ ConnEnd srcPt551(Point(181.62835648698, 738.8568549161259), 15);
+ connRef551->setSourceEndpoint(srcPt551);
+ ConnEnd dstPt551(Point(46.62835648497997, 738.8568549161259), 8);
+ connRef551->setDestEndpoint(dstPt551);
+ connRef551->setRoutingType((ConnType)2);
+
+ ConnRef *connRef552 = new ConnRef(router, 552);
+ ConnEnd srcPt552(Point(346.62835648698, 759.8568549161259), 4);
+ connRef552->setSourceEndpoint(srcPt552);
+ ConnEnd dstPt552(Point(181.62835648698, 738.8568549161259), 15);
+ connRef552->setDestEndpoint(dstPt552);
+ connRef552->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints552(1);
+ checkpoints552[0] = Checkpoint(Point(323.62835648698, 738.8568549161259), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef552->setRoutingCheckpoints(checkpoints552);
+
+ ConnRef *connRef553 = new ConnRef(router, 553);
+ ConnEnd srcPt553(Point(-319.87164351602, 738.8568549161259), 15);
+ connRef553->setSourceEndpoint(srcPt553);
+ ConnEnd dstPt553(Point(133.62835648698, 804.8568549161259), 4);
+ connRef553->setDestEndpoint(dstPt553);
+ connRef553->setRoutingType((ConnType)2);
+
+ ConnRef *connRef554 = new ConnRef(router, 554);
+ ConnEnd srcPt554(Point(-435.87164351602, 635.6568549161261), 15);
+ connRef554->setSourceEndpoint(srcPt554);
+ ConnEnd dstPt554(Point(-534.87164351602, 535.756854916126), 2);
+ connRef554->setDestEndpoint(dstPt554);
+ connRef554->setRoutingType((ConnType)2);
+
+ ConnRef *connRef555 = new ConnRef(router, 555);
+ ConnEnd srcPt555(Point(-435.87164351602, 454.7568549161261), 15);
+ connRef555->setSourceEndpoint(srcPt555);
+ ConnEnd dstPt555(Point(-319.87164351602, 505.756854916126), 1);
+ connRef555->setDestEndpoint(dstPt555);
+ connRef555->setRoutingType((ConnType)2);
+
+ ConnRef *connRef556 = new ConnRef(router, 556);
+ ConnEnd srcPt556(Point(115.62835648698, 635.6568549161261), 15);
+ connRef556->setSourceEndpoint(srcPt556);
+ ConnEnd dstPt556(Point(-125.87164351502, 535.756854916126), 2);
+ connRef556->setDestEndpoint(dstPt556);
+ connRef556->setRoutingType((ConnType)2);
+
+ ConnRef *connRef557 = new ConnRef(router, 557);
+ ConnEnd srcPt557(Point(115.62835648698, 454.7568549161261), 15);
+ connRef557->setSourceEndpoint(srcPt557);
+ ConnEnd dstPt557(Point(181.62835648698, 505.756854916126), 1);
+ connRef557->setDestEndpoint(dstPt557);
+ connRef557->setRoutingType((ConnType)2);
+
+ ConnRef *connRef558 = new ConnRef(router, 558);
+ ConnEnd srcPt558(Point(1873.12835649198, -558.5348117525407), 15);
+ connRef558->setSourceEndpoint(srcPt558);
+ ConnEnd dstPt558(Point(1818.12835649098, -558.5348117525407), 8);
+ connRef558->setDestEndpoint(dstPt558);
+ connRef558->setRoutingType((ConnType)2);
+
+ ConnRef *connRef559 = new ConnRef(router, 559);
+ ConnEnd srcPt559(Point(944.62835648898, -681.4098117525407), 15);
+ connRef559->setSourceEndpoint(srcPt559);
+ ConnEnd dstPt559(Point(747.62835648798, -681.4098117525407), 8);
+ connRef559->setDestEndpoint(dstPt559);
+ connRef559->setRoutingType((ConnType)2);
+
+ ConnRef *connRef560 = new ConnRef(router, 560);
+ ConnEnd srcPt560(Point(944.62835648898, -681.4098117525407), 15);
+ connRef560->setSourceEndpoint(srcPt560);
+ ConnEnd dstPt560(Point(166.62835648698, -126.4098117515406), 4);
+ connRef560->setDestEndpoint(dstPt560);
+ connRef560->setRoutingType((ConnType)2);
+
+ ConnRef *connRef561 = new ConnRef(router, 561);
+ ConnEnd srcPt561(Point(944.62835648898, -807.4098117525407), 15);
+ connRef561->setSourceEndpoint(srcPt561);
+ ConnEnd dstPt561(Point(747.62835648798, -807.4098117525407), 8);
+ connRef561->setDestEndpoint(dstPt561);
+ connRef561->setRoutingType((ConnType)2);
+
+ ConnRef *connRef562 = new ConnRef(router, 562);
+ ConnEnd srcPt562(Point(1363.12835648898, -558.5348117525407), 15);
+ connRef562->setSourceEndpoint(srcPt562);
+ ConnEnd dstPt562(Point(1246.12835648898, -558.5348117525407), 8);
+ connRef562->setDestEndpoint(dstPt562);
+ connRef562->setRoutingType((ConnType)2);
+
+ ConnRef *connRef563 = new ConnRef(router, 563);
+ ConnEnd srcPt563(Point(845.62835648898, -20.40981175154064), 15);
+ connRef563->setSourceEndpoint(srcPt563);
+ ConnEnd dstPt563(Point(681.62835648798, -20.40981175154064), 8);
+ connRef563->setDestEndpoint(dstPt563);
+ connRef563->setRoutingType((ConnType)2);
+
+ ConnRef *connRef564 = new ConnRef(router, 564);
+ ConnEnd srcPt564(Point(295.62835648698, 421.7568549161261), 15);
+ connRef564->setSourceEndpoint(srcPt564);
+ ConnEnd dstPt564(Point(478.62835648698, 421.7568549161261), 4);
+ connRef564->setDestEndpoint(dstPt564);
+ connRef564->setRoutingType((ConnType)2);
+
+ ConnRef *connRef565 = new ConnRef(router, 565);
+ ConnEnd srcPt565(Point(181.62835648698, -558.5348117525407), 15);
+ connRef565->setSourceEndpoint(srcPt565);
+ ConnEnd dstPt565(Point(46.62835648497997, -558.5348117525407), 8);
+ connRef565->setDestEndpoint(dstPt565);
+ connRef565->setRoutingType((ConnType)2);
+
+ ConnRef *connRef566 = new ConnRef(router, 566);
+ ConnEnd srcPt566(Point(1667.12835648998, 635.6568549161261), 15);
+ connRef566->setSourceEndpoint(srcPt566);
+ ConnEnd dstPt566(Point(1722.12835649098, 635.6568549161261), 4);
+ connRef566->setDestEndpoint(dstPt566);
+ connRef566->setRoutingType((ConnType)2);
+
+ ConnRef *connRef567 = new ConnRef(router, 567);
+ ConnEnd srcPt567(Point(1573.12835648898, 635.6568549161261), 8);
+ connRef567->setSourceEndpoint(srcPt567);
+ ConnEnd dstPt567(Point(1667.12835648998, 635.6568549161261), 15);
+ connRef567->setDestEndpoint(dstPt567);
+ connRef567->setRoutingType((ConnType)2);
+
+ ConnRef *connRef568 = new ConnRef(router, 568);
+ ConnEnd srcPt568(Point(1752.12835649098, 635.6568549161261), 8);
+ connRef568->setSourceEndpoint(srcPt568);
+ ConnEnd dstPt568(Point(1873.12835649198, 635.6568549161261), 15);
+ connRef568->setDestEndpoint(dstPt568);
+ connRef568->setRoutingType((ConnType)2);
+
+ ConnRef *connRef569 = new ConnRef(router, 569);
+ ConnEnd srcPt569(Point(1752.12835649098, 635.6568549161261), 8);
+ connRef569->setSourceEndpoint(srcPt569);
+ ConnEnd dstPt569(Point(1836.12835649098, 487.756854916126), 15);
+ connRef569->setDestEndpoint(dstPt569);
+ connRef569->setRoutingType((ConnType)2);
+
+ ConnRef *connRef570 = new ConnRef(router, 570);
+ ConnEnd srcPt570(Point(2218.795023162646, 614.6568549161261), 4);
+ connRef570->setSourceEndpoint(srcPt570);
+ ConnEnd dstPt570(Point(2153.795023161646, 635.6568549161261), 15);
+ connRef570->setDestEndpoint(dstPt570);
+ connRef570->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints570(1);
+ checkpoints570[0] = Checkpoint(Point(2195.795023162646, 635.6568549161261), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef570->setRoutingCheckpoints(checkpoints570);
+
+ ConnRef *connRef571 = new ConnRef(router, 571);
+ ConnEnd srcPt571(Point(2218.795023162646, 656.6568549161261), 4);
+ connRef571->setSourceEndpoint(srcPt571);
+ ConnEnd dstPt571(Point(2153.795023161646, 635.6568549161261), 15);
+ connRef571->setDestEndpoint(dstPt571);
+ connRef571->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints571(1);
+ checkpoints571[0] = Checkpoint(Point(2195.795023162646, 635.6568549161261), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef571->setRoutingCheckpoints(checkpoints571);
+
+ ConnRef *connRef572 = new ConnRef(router, 572);
+ ConnEnd srcPt572(Point(2248.795023162646, 614.6568549161261), 8);
+ connRef572->setSourceEndpoint(srcPt572);
+ ConnEnd dstPt572(Point(2313.795023163646, 635.6568549161261), 15);
+ connRef572->setDestEndpoint(dstPt572);
+ connRef572->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints572(1);
+ checkpoints572[0] = Checkpoint(Point(2271.795023162646, 635.6568549161261), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef572->setRoutingCheckpoints(checkpoints572);
+
+ ConnRef *connRef573 = new ConnRef(router, 573);
+ ConnEnd srcPt573(Point(2013.795023159646, 635.6568549161261), 15);
+ connRef573->setSourceEndpoint(srcPt573);
+ ConnEnd dstPt573(Point(2068.795023160646, 635.6568549161261), 4);
+ connRef573->setDestEndpoint(dstPt573);
+ connRef573->setRoutingType((ConnType)2);
+
+ ConnRef *connRef574 = new ConnRef(router, 574);
+ ConnEnd srcPt574(Point(2098.795023160646, 635.6568549161261), 8);
+ connRef574->setSourceEndpoint(srcPt574);
+ ConnEnd dstPt574(Point(2153.795023161646, 635.6568549161261), 15);
+ connRef574->setDestEndpoint(dstPt574);
+ connRef574->setRoutingType((ConnType)2);
+
+ ConnRef *connRef575 = new ConnRef(router, 575);
+ ConnEnd srcPt575(Point(2248.795023162646, 656.6568549161261), 8);
+ connRef575->setSourceEndpoint(srcPt575);
+ ConnEnd dstPt575(Point(2313.795023163646, 635.6568549161261), 15);
+ connRef575->setDestEndpoint(dstPt575);
+ connRef575->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints575(1);
+ checkpoints575[0] = Checkpoint(Point(2271.795023162646, 635.6568549161261), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef575->setRoutingCheckpoints(checkpoints575);
+
+ ConnRef *connRef576 = new ConnRef(router, 576);
+ ConnEnd srcPt576(Point(1667.12835648998, 361.2568549161261), 15);
+ connRef576->setSourceEndpoint(srcPt576);
+ ConnEnd dstPt576(Point(1722.12835649098, 361.2568549161261), 4);
+ connRef576->setDestEndpoint(dstPt576);
+ connRef576->setRoutingType((ConnType)2);
+
+ ConnRef *connRef577 = new ConnRef(router, 577);
+ ConnEnd srcPt577(Point(1752.12835649098, 361.2568549161261), 8);
+ connRef577->setSourceEndpoint(srcPt577);
+ ConnEnd dstPt577(Point(1836.12835649098, 487.756854916126), 15);
+ connRef577->setDestEndpoint(dstPt577);
+ connRef577->setRoutingType((ConnType)2);
+
+ ConnRef *connRef578 = new ConnRef(router, 578);
+ ConnEnd srcPt578(Point(1752.12835649098, 361.2568549161261), 8);
+ connRef578->setSourceEndpoint(srcPt578);
+ ConnEnd dstPt578(Point(2013.795023159646, 635.6568549161261), 15);
+ connRef578->setDestEndpoint(dstPt578);
+ connRef578->setRoutingType((ConnType)2);
+
+ ConnRef *connRef579 = new ConnRef(router, 579);
+ ConnEnd srcPt579(Point(1642.12835648998, -497.4098117525407), 8);
+ connRef579->setSourceEndpoint(srcPt579);
+ ConnEnd dstPt579(Point(1700.12835648998, -558.5348117525407), 15);
+ connRef579->setDestEndpoint(dstPt579);
+ connRef579->setRoutingType((ConnType)2);
+
+ ConnRef *connRef580 = new ConnRef(router, 580);
+ ConnEnd srcPt580(Point(239.62835648698, 1375.606854916126), 4);
+ connRef580->setSourceEndpoint(srcPt580);
+ ConnEnd dstPt580(Point(181.62835648698, 1375.606854916126), 8);
+ connRef580->setDestEndpoint(dstPt580);
+ connRef580->setRoutingType((ConnType)2);
+
+ ConnRef *connRef581 = new ConnRef(router, 581);
+ ConnEnd srcPt581(Point(1943.12835649298, -16.74314508487396), 2);
+ connRef581->setSourceEndpoint(srcPt581);
+ ConnEnd dstPt581(Point(1943.12835649298, 33.25685491512604), 1);
+ connRef581->setDestEndpoint(dstPt581);
+ connRef581->setRoutingType((ConnType)2);
+
+ ConnRef *connRef582 = new ConnRef(router, 582);
+ ConnEnd srcPt582(Point(427.62835648698, -369.4098117515406), 2);
+ connRef582->setSourceEndpoint(srcPt582);
+ ConnEnd dstPt582(Point(427.62835648698, -319.4098117515406), 1);
+ connRef582->setDestEndpoint(dstPt582);
+ connRef582->setRoutingType((ConnType)2);
+
+ ConnRef *connRef583 = new ConnRef(router, 583);
+ ConnEnd srcPt583(Point(31.62835648497997, 895.8568549161259), 2);
+ connRef583->setSourceEndpoint(srcPt583);
+ ConnEnd dstPt583(Point(31.62835648497997, 945.8568549161259), 1);
+ connRef583->setDestEndpoint(dstPt583);
+ connRef583->setRoutingType((ConnType)2);
+
+ ConnRef *connRef584 = new ConnRef(router, 584);
+ ConnEnd srcPt584(Point(451.6283564879799, 1342.606854916126), 8);
+ connRef584->setSourceEndpoint(srcPt584);
+ ConnEnd dstPt584(Point(509.62835648798, 1342.606854916126), 4);
+ connRef584->setDestEndpoint(dstPt584);
+ connRef584->setRoutingType((ConnType)2);
+
+ ConnRef *connRef585 = new ConnRef(router, 585);
+ ConnEnd srcPt585(Point(-948.12164351602, -265.4098117515406), 4);
+ connRef585->setSourceEndpoint(srcPt585);
+ ConnEnd dstPt585(Point(-1006.12164351602, -265.4098117515406), 8);
+ connRef585->setDestEndpoint(dstPt585);
+ connRef585->setRoutingType((ConnType)2);
+
+ ConnRef *connRef586 = new ConnRef(router, 586);
+ ConnEnd srcPt586(Point(-948.12164351602, -497.4098117525407), 4);
+ connRef586->setSourceEndpoint(srcPt586);
+ ConnEnd dstPt586(Point(-1006.12164351602, -497.4098117525407), 8);
+ connRef586->setDestEndpoint(dstPt586);
+ connRef586->setRoutingType((ConnType)2);
+
+ ConnRef *connRef587 = new ConnRef(router, 587);
+ ConnEnd srcPt587(Point(-808.12164351602, -787.9812403239691), 2);
+ connRef587->setSourceEndpoint(srcPt587);
+ ConnEnd dstPt587(Point(-808.12164351602, -737.9812403239691), 1);
+ connRef587->setDestEndpoint(dstPt587);
+ connRef587->setRoutingType((ConnType)2);
+
+ ConnRef *connRef588 = new ConnRef(router, 588);
+ ConnEnd srcPt588(Point(-468.87164351602, -883.9812403239691), 2);
+ connRef588->setSourceEndpoint(srcPt588);
+ ConnEnd dstPt588(Point(-468.87164351602, -833.9812403239691), 1);
+ connRef588->setDestEndpoint(dstPt588);
+ connRef588->setRoutingType((ConnType)2);
+
+ ConnRef *connRef589 = new ConnRef(router, 589);
+ ConnEnd srcPt589(Point(-468.87164351602, -808.9812403239691), 2);
+ connRef589->setSourceEndpoint(srcPt589);
+ ConnEnd dstPt589(Point(-468.87164351602, -758.9812403239691), 1);
+ connRef589->setDestEndpoint(dstPt589);
+ connRef589->setRoutingType((ConnType)2);
+
+ ConnRef *connRef590 = new ConnRef(router, 590);
+ ConnEnd srcPt590(Point(115.62835648698, -787.9812403239691), 2);
+ connRef590->setSourceEndpoint(srcPt590);
+ ConnEnd dstPt590(Point(115.62835648698, -737.9812403239691), 1);
+ connRef590->setDestEndpoint(dstPt590);
+ connRef590->setRoutingType((ConnType)2);
+
+ ConnRef *connRef591 = new ConnRef(router, 591);
+ ConnEnd srcPt591(Point(-501.87164351602, -547.4098117525407), 2);
+ connRef591->setSourceEndpoint(srcPt591);
+ ConnEnd dstPt591(Point(-501.87164351602, -497.4098117525407), 1);
+ connRef591->setDestEndpoint(dstPt591);
+ connRef591->setRoutingType((ConnType)2);
+
+ ConnRef *connRef592 = new ConnRef(router, 592);
+ ConnEnd srcPt592(Point(-501.87164351602, -428.4098117525406), 2);
+ connRef592->setSourceEndpoint(srcPt592);
+ ConnEnd dstPt592(Point(-501.87164351602, -378.4098117525406), 1);
+ connRef592->setDestEndpoint(dstPt592);
+ connRef592->setRoutingType((ConnType)2);
+
+ ConnRef *connRef593 = new ConnRef(router, 593);
+ ConnEnd srcPt593(Point(96.62835648597996, -227.4098117515406), 1);
+ connRef593->setSourceEndpoint(srcPt593);
+ ConnEnd dstPt593(Point(96.62835648597996, -277.4098117515406), 2);
+ connRef593->setDestEndpoint(dstPt593);
+ connRef593->setRoutingType((ConnType)2);
+
+ ConnRef *connRef594 = new ConnRef(router, 594);
+ ConnEnd srcPt594(Point(96.62835648597996, -152.4098117515406), 1);
+ connRef594->setSourceEndpoint(srcPt594);
+ ConnEnd dstPt594(Point(96.62835648597996, -202.4098117515406), 2);
+ connRef594->setDestEndpoint(dstPt594);
+ connRef594->setRoutingType((ConnType)2);
+
+ ConnRef *connRef595 = new ConnRef(router, 595);
+ ConnEnd srcPt595(Point(427.62835648698, -227.4098117515406), 1);
+ connRef595->setSourceEndpoint(srcPt595);
+ ConnEnd dstPt595(Point(427.62835648698, -277.4098117515406), 2);
+ connRef595->setDestEndpoint(dstPt595);
+ connRef595->setRoutingType((ConnType)2);
+
+ ConnRef *connRef596 = new ConnRef(router, 596);
+ ConnEnd srcPt596(Point(427.62835648698, -152.4098117515406), 1);
+ connRef596->setSourceEndpoint(srcPt596);
+ ConnEnd dstPt596(Point(427.62835648698, -202.4098117515406), 2);
+ connRef596->setDestEndpoint(dstPt596);
+ connRef596->setRoutingType((ConnType)2);
+
+ ConnRef *connRef597 = new ConnRef(router, 597);
+ ConnEnd srcPt597(Point(-240.87164351602, -159.4098117515406), 4);
+ connRef597->setSourceEndpoint(srcPt597);
+ ConnEnd dstPt597(Point(-298.87164351602, -159.4098117515406), 8);
+ connRef597->setDestEndpoint(dstPt597);
+ connRef597->setRoutingType((ConnType)2);
+
+ ConnRef *connRef598 = new ConnRef(router, 598);
+ ConnEnd srcPt598(Point(-398.87164351602, -159.4098117515406), 8);
+ connRef598->setSourceEndpoint(srcPt598);
+ ConnEnd dstPt598(Point(-340.87164351602, -159.4098117515406), 4);
+ connRef598->setDestEndpoint(dstPt598);
+ connRef598->setRoutingType((ConnType)2);
+
+ ConnRef *connRef599 = new ConnRef(router, 599);
+ ConnEnd srcPt599(Point(96.62835648597996, -444.4098117515406), 2);
+ connRef599->setSourceEndpoint(srcPt599);
+ ConnEnd dstPt599(Point(96.62835648597996, -394.4098117515406), 1);
+ connRef599->setDestEndpoint(dstPt599);
+ connRef599->setRoutingType((ConnType)2);
+
+ ConnRef *connRef600 = new ConnRef(router, 600);
+ ConnEnd srcPt600(Point(96.62835648597996, -369.4098117515406), 2);
+ connRef600->setSourceEndpoint(srcPt600);
+ ConnEnd dstPt600(Point(96.62835648597996, -319.4098117515406), 1);
+ connRef600->setDestEndpoint(dstPt600);
+ connRef600->setRoutingType((ConnType)2);
+
+ ConnRef *connRef601 = new ConnRef(router, 601);
+ ConnEnd srcPt601(Point(427.62835648698, -519.4098117515407), 2);
+ connRef601->setSourceEndpoint(srcPt601);
+ ConnEnd dstPt601(Point(427.62835648698, -469.4098117515406), 1);
+ connRef601->setDestEndpoint(dstPt601);
+ connRef601->setRoutingType((ConnType)2);
+
+ ConnRef *connRef602 = new ConnRef(router, 602);
+ ConnEnd srcPt602(Point(427.62835648698, -444.4098117515406), 2);
+ connRef602->setSourceEndpoint(srcPt602);
+ ConnEnd dstPt602(Point(427.62835648698, -394.4098117515406), 1);
+ connRef602->setDestEndpoint(dstPt602);
+ connRef602->setRoutingType((ConnType)2);
+
+ ConnRef *connRef603 = new ConnRef(router, 603);
+ ConnEnd srcPt603(Point(845.62835648898, -182.4098117515406), 1);
+ connRef603->setSourceEndpoint(srcPt603);
+ ConnEnd dstPt603(Point(845.62835648898, -232.4098117515406), 2);
+ connRef603->setDestEndpoint(dstPt603);
+ connRef603->setRoutingType((ConnType)2);
+
+ ConnRef *connRef604 = new ConnRef(router, 604);
+ ConnEnd srcPt604(Point(632.9873402531949, -227.4098117515406), 1);
+ connRef604->setSourceEndpoint(srcPt604);
+ ConnEnd dstPt604(Point(632.9873402531949, -277.4098117515406), 2);
+ connRef604->setDestEndpoint(dstPt604);
+ connRef604->setRoutingType((ConnType)2);
+
+ ConnRef *connRef605 = new ConnRef(router, 605);
+ ConnEnd srcPt605(Point(632.9873402531949, -369.4098117515406), 2);
+ connRef605->setSourceEndpoint(srcPt605);
+ ConnEnd dstPt605(Point(632.9873402531949, -319.4098117515406), 1);
+ connRef605->setDestEndpoint(dstPt605);
+ connRef605->setRoutingType((ConnType)2);
+
+ ConnRef *connRef606 = new ConnRef(router, 606);
+ ConnEnd srcPt606(Point(1062.914070775694, -369.4098117515406), 2);
+ connRef606->setSourceEndpoint(srcPt606);
+ ConnEnd dstPt606(Point(1062.914070775694, -319.4098117515406), 1);
+ connRef606->setDestEndpoint(dstPt606);
+ connRef606->setRoutingType((ConnType)2);
+
+ ConnRef *connRef607 = new ConnRef(router, 607);
+ ConnEnd srcPt607(Point(1062.914070775694, -227.4098117515406), 1);
+ connRef607->setSourceEndpoint(srcPt607);
+ ConnEnd dstPt607(Point(1062.914070775694, -277.4098117515406), 2);
+ connRef607->setDestEndpoint(dstPt607);
+ connRef607->setRoutingType((ConnType)2);
+
+ ConnRef *connRef608 = new ConnRef(router, 608);
+ ConnEnd srcPt608(Point(1594.12835648998, -369.4098117515406), 2);
+ connRef608->setSourceEndpoint(srcPt608);
+ ConnEnd dstPt608(Point(1594.12835648998, -319.4098117515406), 1);
+ connRef608->setDestEndpoint(dstPt608);
+ connRef608->setRoutingType((ConnType)2);
+
+ ConnRef *connRef609 = new ConnRef(router, 609);
+ ConnEnd srcPt609(Point(1594.12835648998, -227.4098117515406), 1);
+ connRef609->setSourceEndpoint(srcPt609);
+ ConnEnd dstPt609(Point(1594.12835648998, -277.4098117515406), 2);
+ connRef609->setDestEndpoint(dstPt609);
+ connRef609->setRoutingType((ConnType)2);
+
+ ConnRef *connRef610 = new ConnRef(router, 610);
+ ConnEnd srcPt610(Point(1770.12835649098, -348.4098117515406), 2);
+ connRef610->setSourceEndpoint(srcPt610);
+ ConnEnd dstPt610(Point(1770.12835649098, -298.4098117515406), 1);
+ connRef610->setDestEndpoint(dstPt610);
+ connRef610->setRoutingType((ConnType)2);
+
+ ConnRef *connRef611 = new ConnRef(router, 611);
+ ConnEnd srcPt611(Point(1943.12835649298, -348.4098117515406), 2);
+ connRef611->setSourceEndpoint(srcPt611);
+ ConnEnd dstPt611(Point(1943.12835649298, -298.4098117515406), 1);
+ connRef611->setDestEndpoint(dstPt611);
+ connRef611->setRoutingType((ConnType)2);
+
+ ConnRef *connRef612 = new ConnRef(router, 612);
+ ConnEnd srcPt612(Point(-501.87164351602, 149.256854915126), 1);
+ connRef612->setSourceEndpoint(srcPt612);
+ ConnEnd dstPt612(Point(-501.87164351602, 99.25685491512604), 2);
+ connRef612->setDestEndpoint(dstPt612);
+ connRef612->setRoutingType((ConnType)2);
+
+ ConnRef *connRef613 = new ConnRef(router, 613);
+ ConnEnd srcPt613(Point(-501.87164351602, 251.2568549161261), 1);
+ connRef613->setSourceEndpoint(srcPt613);
+ ConnEnd dstPt613(Point(-501.87164351602, 201.256854916126), 2);
+ connRef613->setDestEndpoint(dstPt613);
+ connRef613->setRoutingType((ConnType)2);
+
+ ConnRef *connRef614 = new ConnRef(router, 614);
+ ConnEnd srcPt614(Point(-26.87164351502003, -4.743145084873959), 2);
+ connRef614->setSourceEndpoint(srcPt614);
+ ConnEnd dstPt614(Point(-26.87164351502003, 45.25685491512604), 1);
+ connRef614->setDestEndpoint(dstPt614);
+ connRef614->setRoutingType((ConnType)2);
+
+ ConnRef *connRef615 = new ConnRef(router, 615);
+ ConnEnd srcPt615(Point(-26.87164351502003, 137.256854915126), 1);
+ connRef615->setSourceEndpoint(srcPt615);
+ ConnEnd dstPt615(Point(-26.87164351502003, 87.25685491512604), 2);
+ connRef615->setDestEndpoint(dstPt615);
+ connRef615->setRoutingType((ConnType)2);
+
+ ConnRef *connRef616 = new ConnRef(router, 616);
+ ConnEnd srcPt616(Point(450.62835648698, 137.256854915126), 1);
+ connRef616->setSourceEndpoint(srcPt616);
+ ConnEnd dstPt616(Point(450.62835648698, 87.25685491512604), 2);
+ connRef616->setDestEndpoint(dstPt616);
+ connRef616->setRoutingType((ConnType)2);
+
+ ConnRef *connRef617 = new ConnRef(router, 617);
+ ConnEnd srcPt617(Point(450.62835648698, -4.743145084873959), 2);
+ connRef617->setSourceEndpoint(srcPt617);
+ ConnEnd dstPt617(Point(450.62835648698, 45.25685491512604), 1);
+ connRef617->setDestEndpoint(dstPt617);
+ connRef617->setRoutingType((ConnType)2);
+
+ ConnRef *connRef618 = new ConnRef(router, 618);
+ ConnEnd srcPt618(Point(765.62835648798, -4.743145084873959), 2);
+ connRef618->setSourceEndpoint(srcPt618);
+ ConnEnd dstPt618(Point(765.62835648798, 45.25685491512604), 1);
+ connRef618->setDestEndpoint(dstPt618);
+ connRef618->setRoutingType((ConnType)2);
+
+ ConnRef *connRef619 = new ConnRef(router, 619);
+ ConnEnd srcPt619(Point(765.62835648798, 137.256854915126), 1);
+ connRef619->setSourceEndpoint(srcPt619);
+ ConnEnd dstPt619(Point(765.62835648798, 87.25685491512604), 2);
+ connRef619->setDestEndpoint(dstPt619);
+ connRef619->setRoutingType((ConnType)2);
+
+ ConnRef *connRef620 = new ConnRef(router, 620);
+ ConnEnd srcPt620(Point(1040.914070774694, -126.4098117515406), 4);
+ connRef620->setSourceEndpoint(srcPt620);
+ ConnEnd dstPt620(Point(982.9140707746942, -126.4098117515406), 8);
+ connRef620->setDestEndpoint(dstPt620);
+ connRef620->setRoutingType((ConnType)2);
+
+ ConnRef *connRef621 = new ConnRef(router, 621);
+ ConnEnd srcPt621(Point(1487.12835648898, -126.4098117515406), 4);
+ connRef621->setSourceEndpoint(srcPt621);
+ ConnEnd dstPt621(Point(1429.12835648898, -126.4098117515406), 8);
+ connRef621->setDestEndpoint(dstPt621);
+ connRef621->setRoutingType((ConnType)2);
+
+ ConnRef *connRef622 = new ConnRef(router, 622);
+ ConnEnd srcPt622(Point(1101.12835648898, -4.743145084873959), 2);
+ connRef622->setSourceEndpoint(srcPt622);
+ ConnEnd dstPt622(Point(1101.12835648898, 45.25685491512604), 1);
+ connRef622->setDestEndpoint(dstPt622);
+ connRef622->setRoutingType((ConnType)2);
+
+ ConnRef *connRef623 = new ConnRef(router, 623);
+ ConnEnd srcPt623(Point(1101.12835648898, 137.256854915126), 1);
+ connRef623->setSourceEndpoint(srcPt623);
+ ConnEnd dstPt623(Point(1101.12835648898, 87.25685491512604), 2);
+ connRef623->setDestEndpoint(dstPt623);
+ connRef623->setRoutingType((ConnType)2);
+
+ ConnRef *connRef624 = new ConnRef(router, 624);
+ ConnEnd srcPt624(Point(699.62835648798, 305.2568549161261), 1);
+ connRef624->setSourceEndpoint(srcPt624);
+ ConnEnd dstPt624(Point(699.62835648798, 255.2568549161261), 2);
+ connRef624->setDestEndpoint(dstPt624);
+ connRef624->setRoutingType((ConnType)2);
+
+ ConnRef *connRef625 = new ConnRef(router, 625);
+ ConnEnd srcPt625(Point(1627.12835648998, -16.74314508487396), 2);
+ connRef625->setSourceEndpoint(srcPt625);
+ ConnEnd dstPt625(Point(1627.12835648998, 33.25685491512604), 1);
+ connRef625->setDestEndpoint(dstPt625);
+ connRef625->setRoutingType((ConnType)2);
+
+ ConnRef *connRef626 = new ConnRef(router, 626);
+ ConnEnd srcPt626(Point(1770.12835649098, -16.74314508487396), 2);
+ connRef626->setSourceEndpoint(srcPt626);
+ ConnEnd dstPt626(Point(1770.12835649098, 33.25685491512604), 1);
+ connRef626->setDestEndpoint(dstPt626);
+ connRef626->setRoutingType((ConnType)2);
+
+ ConnRef *connRef627 = new ConnRef(router, 627);
+ ConnEnd srcPt627(Point(-932.12164351602, 771.8568549161259), 8);
+ connRef627->setSourceEndpoint(srcPt627);
+ ConnEnd dstPt627(Point(-874.12164351602, 771.8568549161259), 4);
+ connRef627->setDestEndpoint(dstPt627);
+ connRef627->setRoutingType((ConnType)2);
+
+ ConnRef *connRef628 = new ConnRef(router, 628);
+ ConnEnd srcPt628(Point(-786.12164351602, 771.8568549161259), 8);
+ connRef628->setSourceEndpoint(srcPt628);
+ ConnEnd dstPt628(Point(-728.12164351602, 771.8568549161259), 4);
+ connRef628->setDestEndpoint(dstPt628);
+ connRef628->setRoutingType((ConnType)2);
+
+ ConnRef *connRef629 = new ConnRef(router, 629);
+ ConnEnd srcPt629(Point(-592.87164351602, 520.756854916126), 8);
+ connRef629->setSourceEndpoint(srcPt629);
+ ConnEnd dstPt629(Point(-534.87164351602, 520.756854916126), 4);
+ connRef629->setDestEndpoint(dstPt629);
+ connRef629->setRoutingType((ConnType)2);
+
+ ConnRef *connRef630 = new ConnRef(router, 630);
+ ConnEnd srcPt630(Point(-261.87164351602, 520.756854916126), 4);
+ connRef630->setSourceEndpoint(srcPt630);
+ ConnEnd dstPt630(Point(-319.87164351602, 520.756854916126), 8);
+ connRef630->setDestEndpoint(dstPt630);
+ connRef630->setRoutingType((ConnType)2);
+
+ ConnRef *connRef631 = new ConnRef(router, 631);
+ ConnEnd srcPt631(Point(-183.87164351502, 520.756854916126), 8);
+ connRef631->setSourceEndpoint(srcPt631);
+ ConnEnd dstPt631(Point(-125.87164351502, 520.756854916126), 4);
+ connRef631->setDestEndpoint(dstPt631);
+ connRef631->setRoutingType((ConnType)2);
+
+ ConnRef *connRef632 = new ConnRef(router, 632);
+ ConnEnd srcPt632(Point(239.62835648698, 520.756854916126), 4);
+ connRef632->setSourceEndpoint(srcPt632);
+ ConnEnd dstPt632(Point(181.62835648698, 520.756854916126), 8);
+ connRef632->setDestEndpoint(dstPt632);
+ connRef632->setRoutingType((ConnType)2);
+
+ ConnRef *connRef633 = new ConnRef(router, 633);
+ ConnEnd srcPt633(Point(31.62835648497997, 688.8568549161259), 2);
+ connRef633->setSourceEndpoint(srcPt633);
+ ConnEnd dstPt633(Point(31.62835648497997, 738.8568549161259), 1);
+ connRef633->setDestEndpoint(dstPt633);
+ connRef633->setRoutingType((ConnType)2);
+
+ ConnRef *connRef634 = new ConnRef(router, 634);
+ ConnEnd srcPt634(Point(-410.87164351602, 978.8568549161259), 8);
+ connRef634->setSourceEndpoint(srcPt634);
+ ConnEnd dstPt634(Point(-352.87164351602, 978.8568549161259), 4);
+ connRef634->setDestEndpoint(dstPt634);
+ connRef634->setRoutingType((ConnType)2);
+
+ ConnRef *connRef635 = new ConnRef(router, 635);
+ ConnEnd srcPt635(Point(-637.12164351602, 1044.856854916126), 4);
+ connRef635->setSourceEndpoint(srcPt635);
+ ConnEnd dstPt635(Point(-695.12164351602, 1044.856854916126), 8);
+ connRef635->setDestEndpoint(dstPt635);
+ connRef635->setRoutingType((ConnType)2);
+
+ ConnRef *connRef636 = new ConnRef(router, 636);
+ ConnEnd srcPt636(Point(361.62835648698, 667.8568549161259), 2);
+ connRef636->setSourceEndpoint(srcPt636);
+ ConnEnd dstPt636(Point(361.62835648698, 717.8568549161259), 1);
+ connRef636->setDestEndpoint(dstPt636);
+ connRef636->setRoutingType((ConnType)2);
+
+ ConnRef *connRef637 = new ConnRef(router, 637);
+ ConnEnd srcPt637(Point(666.62835648798, 529.006854916126), 2);
+ connRef637->setSourceEndpoint(srcPt637);
+ ConnEnd dstPt637(Point(666.62835648798, 579.006854916126), 1);
+ connRef637->setDestEndpoint(dstPt637);
+ connRef637->setRoutingType((ConnType)2);
+
+ ConnRef *connRef638 = new ConnRef(router, 638);
+ ConnEnd srcPt638(Point(148.62835648698, 854.8568549161259), 1);
+ connRef638->setSourceEndpoint(srcPt638);
+ ConnEnd dstPt638(Point(148.62835648698, 804.8568549161259), 2);
+ connRef638->setDestEndpoint(dstPt638);
+ connRef638->setRoutingType((ConnType)2);
+
+ ConnRef *connRef639 = new ConnRef(router, 639);
+ ConnEnd srcPt639(Point(798.62835648798, 667.8568549161259), 2);
+ connRef639->setSourceEndpoint(srcPt639);
+ ConnEnd dstPt639(Point(798.62835648798, 717.8568549161259), 1);
+ connRef639->setDestEndpoint(dstPt639);
+ connRef639->setRoutingType((ConnType)2);
+
+ ConnRef *connRef640 = new ConnRef(router, 640);
+ ConnEnd srcPt640(Point(798.62835648798, 809.8568549161259), 1);
+ connRef640->setSourceEndpoint(srcPt640);
+ ConnEnd dstPt640(Point(798.62835648798, 759.8568549161259), 2);
+ connRef640->setDestEndpoint(dstPt640);
+ connRef640->setRoutingType((ConnType)2);
+
+ ConnRef *connRef641 = new ConnRef(router, 641);
+ ConnEnd srcPt641(Point(654.62835648798, 857.8568549161259), 4);
+ connRef641->setSourceEndpoint(srcPt641);
+ ConnEnd dstPt641(Point(596.62835648798, 857.8568549161259), 8);
+ connRef641->setDestEndpoint(dstPt641);
+ connRef641->setRoutingType((ConnType)2);
+
+ ConnRef *connRef642 = new ConnRef(router, 642);
+ ConnEnd srcPt642(Point(101.62835648598, 971.8568549161259), 2);
+ connRef642->setSourceEndpoint(srcPt642);
+ ConnEnd dstPt642(Point(101.62835648598, 1021.856854916126), 1);
+ connRef642->setDestEndpoint(dstPt642);
+ connRef642->setRoutingType((ConnType)2);
+
+ ConnRef *connRef643 = new ConnRef(router, 643);
+ ConnEnd srcPt643(Point(-92.87164351502003, 1214.856854916126), 1);
+ connRef643->setSourceEndpoint(srcPt643);
+ ConnEnd dstPt643(Point(-92.87164351502003, 1164.856854916126), 2);
+ connRef643->setDestEndpoint(dstPt643);
+ connRef643->setRoutingType((ConnType)2);
+
+ ConnRef *connRef644 = new ConnRef(router, 644);
+ ConnEnd srcPt644(Point(-92.87164351502003, 1072.856854916126), 2);
+ connRef644->setSourceEndpoint(srcPt644);
+ ConnEnd dstPt644(Point(-92.87164351502003, 1122.856854916126), 1);
+ connRef644->setDestEndpoint(dstPt644);
+ connRef644->setRoutingType((ConnType)2);
+
+ ConnRef *connRef645 = new ConnRef(router, 645);
+ ConnEnd srcPt645(Point(328.62835648698, 1072.856854916126), 2);
+ connRef645->setSourceEndpoint(srcPt645);
+ ConnEnd dstPt645(Point(328.62835648698, 1122.856854916126), 1);
+ connRef645->setDestEndpoint(dstPt645);
+ connRef645->setRoutingType((ConnType)2);
+
+ ConnRef *connRef646 = new ConnRef(router, 646);
+ ConnEnd srcPt646(Point(845.62835648898, 1060.856854916126), 2);
+ connRef646->setSourceEndpoint(srcPt646);
+ ConnEnd dstPt646(Point(845.62835648898, 1110.856854916126), 1);
+ connRef646->setDestEndpoint(dstPt646);
+ connRef646->setRoutingType((ConnType)2);
+
+ ConnRef *connRef647 = new ConnRef(router, 647);
+ ConnEnd srcPt647(Point(903.9140707746942, 886.8568549171259), 8);
+ connRef647->setSourceEndpoint(srcPt647);
+ ConnEnd dstPt647(Point(961.9140707746942, 886.8568549171259), 4);
+ connRef647->setDestEndpoint(dstPt647);
+ connRef647->setRoutingType((ConnType)2);
+
+ ConnRef *connRef648 = new ConnRef(router, 648);
+ ConnEnd srcPt648(Point(1225.12835648898, 1011.856854916126), 4);
+ connRef648->setSourceEndpoint(srcPt648);
+ ConnEnd dstPt648(Point(1167.12835648898, 1011.856854916126), 8);
+ connRef648->setDestEndpoint(dstPt648);
+ connRef648->setRoutingType((ConnType)2);
+
+ ConnRef *connRef649 = new ConnRef(router, 649);
+ ConnEnd srcPt649(Point(1225.12835648898, 1110.856854916126), 4);
+ connRef649->setSourceEndpoint(srcPt649);
+ ConnEnd dstPt649(Point(1167.12835648898, 1110.856854916126), 8);
+ connRef649->setDestEndpoint(dstPt649);
+ connRef649->setRoutingType((ConnType)2);
+
+ ConnRef *connRef650 = new ConnRef(router, 650);
+ ConnEnd srcPt650(Point(1167.12835648898, 1226.856854916126), 1);
+ connRef650->setSourceEndpoint(srcPt650);
+ ConnEnd dstPt650(Point(1167.12835648898, 1176.856854916126), 2);
+ connRef650->setDestEndpoint(dstPt650);
+ connRef650->setRoutingType((ConnType)2);
+
+ ConnRef *connRef651 = new ConnRef(router, 651);
+ ConnEnd srcPt651(Point(-26.37164351502003, 1375.606854916126), 8);
+ connRef651->setSourceEndpoint(srcPt651);
+ ConnEnd dstPt651(Point(31.62835648497997, 1375.606854916126), 4);
+ connRef651->setDestEndpoint(dstPt651);
+ connRef651->setRoutingType((ConnType)2);
+
+ ConnRef *connRef652 = new ConnRef(router, 652);
+ ConnEnd srcPt652(Point(609.62835648798, 1342.606854916126), 4);
+ connRef652->setSourceEndpoint(srcPt652);
+ ConnEnd dstPt652(Point(551.62835648798, 1342.606854916126), 8);
+ connRef652->setDestEndpoint(dstPt652);
+ connRef652->setRoutingType((ConnType)2);
+
+ ConnRef *connRef653 = new ConnRef(router, 653);
+ ConnEnd srcPt653(Point(-501.87164351602, 1597.106854917126), 2);
+ connRef653->setSourceEndpoint(srcPt653);
+ ConnEnd dstPt653(Point(-501.87164351602, 1647.106854917126), 1);
+ connRef653->setDestEndpoint(dstPt653);
+ connRef653->setRoutingType((ConnType)2);
+
+ ConnRef *connRef654 = new ConnRef(router, 654);
+ ConnEnd srcPt654(Point(-59.87164351502003, 1718.106854917126), 1);
+ connRef654->setSourceEndpoint(srcPt654);
+ ConnEnd dstPt654(Point(-59.87164351502003, 1668.106854917126), 2);
+ connRef654->setDestEndpoint(dstPt654);
+ connRef654->setRoutingType((ConnType)2);
+
+ ConnRef *connRef655 = new ConnRef(router, 655);
+ ConnEnd srcPt655(Point(-59.87164351502003, 1501.106854917126), 2);
+ connRef655->setSourceEndpoint(srcPt655);
+ ConnEnd dstPt655(Point(-59.87164351502003, 1551.106854917126), 1);
+ connRef655->setDestEndpoint(dstPt655);
+ connRef655->setRoutingType((ConnType)2);
+
+ ConnRef *connRef656 = new ConnRef(router, 656);
+ ConnEnd srcPt656(Point(-59.87164351502003, 1576.106854917126), 2);
+ connRef656->setSourceEndpoint(srcPt656);
+ ConnEnd dstPt656(Point(-59.87164351502003, 1626.106854917126), 1);
+ connRef656->setDestEndpoint(dstPt656);
+ connRef656->setRoutingType((ConnType)2);
+
+ ConnRef *connRef657 = new ConnRef(router, 657);
+ ConnEnd srcPt657(Point(394.62835648698, 1718.106854917126), 1);
+ connRef657->setSourceEndpoint(srcPt657);
+ ConnEnd dstPt657(Point(394.62835648698, 1668.106854917126), 2);
+ connRef657->setDestEndpoint(dstPt657);
+ connRef657->setRoutingType((ConnType)2);
+
+ ConnRef *connRef658 = new ConnRef(router, 658);
+ ConnEnd srcPt658(Point(394.62835648698, 1576.106854917126), 2);
+ connRef658->setSourceEndpoint(srcPt658);
+ ConnEnd dstPt658(Point(394.62835648698, 1626.106854917126), 1);
+ connRef658->setDestEndpoint(dstPt658);
+ connRef658->setRoutingType((ConnType)2);
+
+ ConnRef *connRef659 = new ConnRef(router, 659);
+ ConnEnd srcPt659(Point(632.9873402531949, 1576.106854917126), 2);
+ connRef659->setSourceEndpoint(srcPt659);
+ ConnEnd dstPt659(Point(632.9873402531949, 1626.106854917126), 1);
+ connRef659->setDestEndpoint(dstPt659);
+ connRef659->setRoutingType((ConnType)2);
+
+ ConnRef *connRef660 = new ConnRef(router, 660);
+ ConnEnd srcPt660(Point(632.9873402531949, 1718.106854917126), 1);
+ connRef660->setSourceEndpoint(srcPt660);
+ ConnEnd dstPt660(Point(632.9873402531949, 1668.106854917126), 2);
+ connRef660->setDestEndpoint(dstPt660);
+ connRef660->setRoutingType((ConnType)2);
+
+ ConnRef *connRef661 = new ConnRef(router, 661);
+ ConnEnd srcPt661(Point(1167.12835648898, 1517.106854916126), 2);
+ connRef661->setSourceEndpoint(srcPt661);
+ ConnEnd dstPt661(Point(1167.12835648898, 1567.106854916126), 1);
+ connRef661->setDestEndpoint(dstPt661);
+ connRef661->setRoutingType((ConnType)2);
+
+ ConnRef *connRef662 = new ConnRef(router, 662);
+ ConnEnd srcPt662(Point(1167.12835648898, 1656.773521583792), 2);
+ connRef662->setSourceEndpoint(srcPt662);
+ ConnEnd dstPt662(Point(1167.12835648898, 1706.773521583792), 1);
+ connRef662->setDestEndpoint(dstPt662);
+ connRef662->setRoutingType((ConnType)2);
+
+ ConnRef *connRef663 = new ConnRef(router, 663);
+ ConnEnd srcPt663(Point(1330.12835648898, 1383.106854916126), 2);
+ connRef663->setSourceEndpoint(srcPt663);
+ ConnEnd dstPt663(Point(1330.12835648898, 1433.106854916126), 1);
+ connRef663->setDestEndpoint(dstPt663);
+ connRef663->setRoutingType((ConnType)2);
+
+ ConnRef *connRef664 = new ConnRef(router, 664);
+ ConnEnd srcPt664(Point(1627.12835648998, 1259.606854916126), 2);
+ connRef664->setSourceEndpoint(srcPt664);
+ ConnEnd dstPt664(Point(1627.12835648998, 1309.606854916126), 1);
+ connRef664->setDestEndpoint(dstPt664);
+ connRef664->setRoutingType((ConnType)2);
+
+ ConnRef *connRef665 = new ConnRef(router, 665);
+ ConnEnd srcPt665(Point(1594.12835648998, 1576.106854917126), 2);
+ connRef665->setSourceEndpoint(srcPt665);
+ ConnEnd dstPt665(Point(1594.12835648998, 1626.106854917126), 1);
+ connRef665->setDestEndpoint(dstPt665);
+ connRef665->setRoutingType((ConnType)2);
+
+ ConnRef *connRef666 = new ConnRef(router, 666);
+ ConnEnd srcPt666(Point(1594.12835648998, 1718.106854917126), 1);
+ connRef666->setSourceEndpoint(srcPt666);
+ ConnEnd dstPt666(Point(1594.12835648998, 1668.106854917126), 2);
+ connRef666->setDestEndpoint(dstPt666);
+ connRef666->setRoutingType((ConnType)2);
+
+ ConnRef *connRef667 = new ConnRef(router, 667);
+ ConnEnd srcPt667(Point(1770.12835649098, 1259.606854916126), 2);
+ connRef667->setSourceEndpoint(srcPt667);
+ ConnEnd dstPt667(Point(1770.12835649098, 1309.606854916126), 1);
+ connRef667->setDestEndpoint(dstPt667);
+ connRef667->setRoutingType((ConnType)2);
+
+ ConnRef *connRef668 = new ConnRef(router, 668);
+ ConnEnd srcPt668(Point(1770.12835649098, 1597.106854917126), 2);
+ connRef668->setSourceEndpoint(srcPt668);
+ ConnEnd dstPt668(Point(1770.12835649098, 1647.106854917126), 1);
+ connRef668->setDestEndpoint(dstPt668);
+ connRef668->setRoutingType((ConnType)2);
+
+ ConnRef *connRef669 = new ConnRef(router, 669);
+ ConnEnd srcPt669(Point(1943.12835649298, 1597.106854917126), 2);
+ connRef669->setSourceEndpoint(srcPt669);
+ ConnEnd dstPt669(Point(1943.12835649298, 1647.106854917126), 1);
+ connRef669->setDestEndpoint(dstPt669);
+ connRef669->setRoutingType((ConnType)2);
+
+ ConnRef *connRef670 = new ConnRef(router, 670);
+ ConnEnd srcPt670(Point(-468.87164351602, -666.9812403239691), 1);
+ connRef670->setSourceEndpoint(srcPt670);
+ ConnEnd dstPt670(Point(-468.87164351602, -716.9812403239691), 2);
+ connRef670->setDestEndpoint(dstPt670);
+ connRef670->setRoutingType((ConnType)2);
+
+ ConnRef *connRef671 = new ConnRef(router, 671);
+ ConnEnd srcPt671(Point(361.62835648698, 809.8568549161259), 1);
+ connRef671->setSourceEndpoint(srcPt671);
+ ConnEnd dstPt671(Point(361.62835648698, 759.8568549161259), 2);
+ connRef671->setDestEndpoint(dstPt671);
+ connRef671->setRoutingType((ConnType)2);
+
+ ConnRef *connRef672 = new ConnRef(router, 672);
+ ConnEnd srcPt672(Point(328.62835648698, 1214.856854916126), 1);
+ connRef672->setSourceEndpoint(srcPt672);
+ ConnEnd dstPt672(Point(328.62835648698, 1164.856854916126), 2);
+ connRef672->setDestEndpoint(dstPt672);
+ connRef672->setRoutingType((ConnType)2);
+
+ ConnRef *connRef673 = new ConnRef(router, 673);
+ ConnEnd srcPt673(Point(1061.914070774694, 886.8568549171259), 4);
+ connRef673->setSourceEndpoint(srcPt673);
+ ConnEnd dstPt673(Point(1003.914070774694, 886.8568549171259), 8);
+ connRef673->setDestEndpoint(dstPt673);
+ connRef673->setRoutingType((ConnType)2);
+
+ ConnRef *connRef674 = new ConnRef(router, 674);
+ ConnEnd srcPt674(Point(1627.12835648998, -668.4098117525407), 2);
+ connRef674->setSourceEndpoint(srcPt674);
+ ConnEnd dstPt674(Point(1627.12835648998, -618.4098117525407), 1);
+ connRef674->setDestEndpoint(dstPt674);
+ connRef674->setRoutingType((ConnType)2);
+
+ ConnRef *connRef675 = new ConnRef(router, 675);
+ ConnEnd srcPt675(Point(1803.12835649098, -608.5348117525407), 2);
+ connRef675->setSourceEndpoint(srcPt675);
+ ConnEnd dstPt675(Point(1803.12835649098, -558.5348117525407), 1);
+ connRef675->setDestEndpoint(dstPt675);
+ connRef675->setRoutingType((ConnType)2);
+
+ ConnRef *connRef676 = new ConnRef(router, 676);
+ ConnEnd srcPt676(Point(460.62835648698, -787.9812403239691), 2);
+ connRef676->setSourceEndpoint(srcPt676);
+ ConnEnd dstPt676(Point(460.62835648698, -737.9812403239691), 1);
+ connRef676->setDestEndpoint(dstPt676);
+ connRef676->setRoutingType((ConnType)2);
+
+ ConnRef *connRef677 = new ConnRef(router, 677);
+ ConnEnd srcPt677(Point(732.62835648798, -857.4098117525407), 2);
+ connRef677->setSourceEndpoint(srcPt677);
+ ConnEnd dstPt677(Point(732.62835648798, -807.4098117525407), 1);
+ connRef677->setDestEndpoint(dstPt677);
+ connRef677->setRoutingType((ConnType)2);
+
+ ConnRef *connRef678 = new ConnRef(router, 678);
+ ConnEnd srcPt678(Point(732.62835648798, -731.4098117525407), 2);
+ connRef678->setSourceEndpoint(srcPt678);
+ ConnEnd dstPt678(Point(732.62835648798, -681.4098117525407), 1);
+ connRef678->setDestEndpoint(dstPt678);
+ connRef678->setRoutingType((ConnType)2);
+
+ ConnRef *connRef679 = new ConnRef(router, 679);
+ ConnEnd srcPt679(Point(1040.914070774694, -464.4098117525406), 4);
+ connRef679->setSourceEndpoint(srcPt679);
+ ConnEnd dstPt679(Point(982.9140707746942, -464.4098117525406), 8);
+ connRef679->setDestEndpoint(dstPt679);
+ connRef679->setRoutingType((ConnType)2);
+
+ ConnRef *connRef680 = new ConnRef(router, 680);
+ ConnEnd srcPt680(Point(1231.12835648898, -608.5348117525407), 2);
+ connRef680->setSourceEndpoint(srcPt680);
+ ConnEnd dstPt680(Point(1231.12835648898, -558.5348117525407), 1);
+ connRef680->setDestEndpoint(dstPt680);
+ connRef680->setRoutingType((ConnType)2);
+
+ ConnRef *connRef681 = new ConnRef(router, 681);
+ ConnEnd srcPt681(Point(181.62835648698, -76.40981175154064), 1);
+ connRef681->setSourceEndpoint(srcPt681);
+ ConnEnd dstPt681(Point(181.62835648698, -126.4098117515406), 2);
+ connRef681->setDestEndpoint(dstPt681);
+ connRef681->setRoutingType((ConnType)2);
+
+ ConnRef *connRef682 = new ConnRef(router, 682);
+ ConnEnd srcPt682(Point(666.62835648798, -70.40981175154064), 2);
+ connRef682->setSourceEndpoint(srcPt682);
+ ConnEnd dstPt682(Point(666.62835648798, -20.40981175154064), 1);
+ connRef682->setDestEndpoint(dstPt682);
+ connRef682->setRoutingType((ConnType)2);
+
+ ConnRef *connRef683 = new ConnRef(router, 683);
+ ConnEnd srcPt683(Point(911.62835648898, 371.7568549161261), 2);
+ connRef683->setSourceEndpoint(srcPt683);
+ ConnEnd dstPt683(Point(911.62835648898, 421.7568549161261), 1);
+ connRef683->setDestEndpoint(dstPt683);
+ connRef683->setRoutingType((ConnType)2);
+
+ ConnRef *connRef684 = new ConnRef(router, 684);
+ ConnEnd srcPt684(Point(493.62835648698, 371.7568549161261), 2);
+ connRef684->setSourceEndpoint(srcPt684);
+ ConnEnd dstPt684(Point(493.62835648698, 421.7568549161261), 1);
+ connRef684->setDestEndpoint(dstPt684);
+ connRef684->setRoutingType((ConnType)2);
+
+ ConnRef *connRef685 = new ConnRef(router, 685);
+ ConnEnd srcPt685(Point(101.62835648598, 1113.856854916126), 1);
+ connRef685->setSourceEndpoint(srcPt685);
+ ConnEnd dstPt685(Point(101.62835648598, 1063.856854916126), 2);
+ connRef685->setDestEndpoint(dstPt685);
+ connRef685->setRoutingType((ConnType)2);
+
+ ConnRef *connRef686 = new ConnRef(router, 686);
+ ConnEnd srcPt686(Point(31.62835648497997, -608.5348117525407), 2);
+ connRef686->setSourceEndpoint(srcPt686);
+ ConnEnd dstPt686(Point(31.62835648497997, -558.5348117525407), 1);
+ connRef686->setDestEndpoint(dstPt686);
+ connRef686->setRoutingType((ConnType)2);
+
+ ConnRef *connRef687 = new ConnRef(router, 687);
+ ConnEnd srcPt687(Point(1558.12835648898, 585.6568549161261), 2);
+ connRef687->setSourceEndpoint(srcPt687);
+ ConnEnd dstPt687(Point(1558.12835648898, 635.6568549161261), 1);
+ connRef687->setDestEndpoint(dstPt687);
+ connRef687->setRoutingType((ConnType)2);
+
+ ConnRef *connRef688 = new ConnRef(router, 688);
+ ConnEnd srcPt688(Point(1737.12835649098, 585.6568549161261), 2);
+ connRef688->setSourceEndpoint(srcPt688);
+ ConnEnd dstPt688(Point(1737.12835649098, 635.6568549161261), 1);
+ connRef688->setDestEndpoint(dstPt688);
+ connRef688->setRoutingType((ConnType)2);
+
+ ConnRef *connRef689 = new ConnRef(router, 689);
+ ConnEnd srcPt689(Point(2233.795023162646, 564.6568549161261), 2);
+ connRef689->setSourceEndpoint(srcPt689);
+ ConnEnd dstPt689(Point(2233.795023162646, 614.6568549161261), 1);
+ connRef689->setDestEndpoint(dstPt689);
+ connRef689->setRoutingType((ConnType)2);
+
+ ConnRef *connRef690 = new ConnRef(router, 690);
+ ConnEnd srcPt690(Point(2083.795023160646, 585.6568549161261), 2);
+ connRef690->setSourceEndpoint(srcPt690);
+ ConnEnd dstPt690(Point(2083.795023160646, 635.6568549161261), 1);
+ connRef690->setDestEndpoint(dstPt690);
+ connRef690->setRoutingType((ConnType)2);
+
+ ConnRef *connRef691 = new ConnRef(router, 691);
+ ConnEnd srcPt691(Point(2233.795023162646, 706.6568549161261), 1);
+ connRef691->setSourceEndpoint(srcPt691);
+ ConnEnd dstPt691(Point(2233.795023162646, 656.6568549161261), 2);
+ connRef691->setDestEndpoint(dstPt691);
+ connRef691->setRoutingType((ConnType)2);
+
+ ConnRef *connRef692 = new ConnRef(router, 692);
+ ConnEnd srcPt692(Point(1737.12835649098, 311.2568549161261), 2);
+ connRef692->setSourceEndpoint(srcPt692);
+ ConnEnd dstPt692(Point(1737.12835649098, 361.2568549161261), 1);
+ connRef692->setDestEndpoint(dstPt692);
+ connRef692->setRoutingType((ConnType)2);
+
+ ConnRef *connRef693 = new ConnRef(router, 693);
+ ConnEnd srcPt693(Point(1627.12835648998, -547.4098117525407), 2);
+ connRef693->setSourceEndpoint(srcPt693);
+ ConnEnd dstPt693(Point(1627.12835648998, -497.4098117525407), 1);
+ connRef693->setDestEndpoint(dstPt693);
+ connRef693->setRoutingType((ConnType)2);
+
+ ConnRef *connRef694 = new ConnRef(router, 694);
+ ConnEnd srcPt694(Point(-125.87164351502, -877.4098117525407), 15);
+ connRef694->setSourceEndpoint(srcPt694);
+ ConnEnd dstPt694(Point(-662.12164351602, -876.9098117525407), 8);
+ connRef694->setDestEndpoint(dstPt694);
+ connRef694->setRoutingType((ConnType)2);
+
+ ConnRef *connRef695 = new ConnRef(router, 695);
+ ConnEnd srcPt695(Point(-1006.12164351602, -126.4098117515406), 15);
+ connRef695->setSourceEndpoint(srcPt695);
+ ConnEnd dstPt695(Point(-1005.62164351602, 280.7568549161261), 1);
+ connRef695->setDestEndpoint(dstPt695);
+ connRef695->setRoutingType((ConnType)2);
+
+ ConnRef *connRef696 = new ConnRef(router, 696);
+ ConnEnd srcPt696(Point(2046.795023159646, -298.4098117515406), 15);
+ connRef696->setSourceEndpoint(srcPt696);
+ ConnEnd dstPt696(Point(2035.795023161646, -369.9098117525406), 4);
+ connRef696->setDestEndpoint(dstPt696);
+ connRef696->setRoutingType((ConnType)2);
+
+ ConnRef *connRef697 = new ConnRef(router, 697);
+ ConnEnd srcPt697(Point(2046.795023159646, 1647.106854917126), 15);
+ connRef697->setSourceEndpoint(srcPt697);
+ ConnEnd dstPt697(Point(2035.295023161646, 1575.606854916126), 4);
+ connRef697->setDestEndpoint(dstPt697);
+ connRef697->setRoutingType((ConnType)2);
+
+ ConnRef *connRef698 = new ConnRef(router, 698);
+ ConnEnd srcPt698(Point(-1006.12164351602, -431.4098117525406), 15);
+ connRef698->setSourceEndpoint(srcPt698);
+ ConnEnd dstPt698(Point(-1109.62164351702, -152.4098117515406), 1);
+ connRef698->setDestEndpoint(dstPt698);
+ connRef698->setRoutingType((ConnType)2);
+#endif
+
+ router->processTransaction();
+ router->outputDiagram("output/checkpointNudging3");
+ bool overlap = router->existsOrthogonalSegmentOverlap();
+ delete router;
+ return (overlap) ? 1 : 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/checkpoints01.cpp b/src/3rdparty/adaptagrams/libavoid/tests/checkpoints01.cpp
new file mode 100644
index 0000000..83ea0ff
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/checkpoints01.cpp
@@ -0,0 +1,62 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 105);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+ Rectangle rect478845150(Point(50695, 51070), Point(50705, 51080));
+ JunctionRef *junctionRef478845150 = new JunctionRef(router,
+ Point(50700, 51075), 478845150);
+
+ Rectangle rect92712048(Point(51246, 50475), Point(51304, 50585));
+ new ShapeRef(router, rect92712048, 92712048);
+ Rectangle rect23127921(Point(50365, 50766), Point(50485, 50834));
+ new ShapeRef(router, rect23127921, 23127921);
+ Rectangle rect159957148(Point(51740, 50891), Point(51860, 50959));
+ new ShapeRef(router, rect159957148, 159957148);
+ Rectangle rect1350214(Point(50375, 51015), Point(50625, 51135));
+ new ShapeRef(router, rect1350214, 1350214);
+ Rectangle rect247197258(Point(50265, 51046), Point(50375, 51104));
+ new ShapeRef(router, rect247197258, 247197258);
+ Rectangle rect281096654(Point(50700, 50390), Point(51000, 50610));
+ new ShapeRef(router, rect281096654, 281096654);
+ ConnEnd srcPt342420237(Point(50425, 50800), 15);
+ ConnEnd dstPt342420237(Point(50710, 50450), 4);
+ new ConnRef(router, srcPt342420237, dstPt342420237, 342420237);
+ ConnEnd srcPt352019675(Point(50990, 50500), 8);
+ ConnEnd dstPt352019675(junctionRef478845150);
+ //ConnEnd dstPt352019675(Point(50700, 51075), 15);
+ new ConnRef(router, srcPt352019675, dstPt352019675, 352019675);
+ ConnEnd srcPt42699400(junctionRef478845150);
+ //ConnEnd srcPt42699400(Point(50700, 51075), 15);
+ ConnEnd dstPt42699400(Point(50615, 51075), 8);
+ new ConnRef(router, srcPt42699400, dstPt42699400, 42699400);
+ ConnEnd srcPt94712625(Point(50710, 50550), 4);
+ ConnEnd dstPt94712625(junctionRef478845150);
+ //ConnEnd dstPt94712625(Point(50700, 51075), 15);
+ new ConnRef(router, srcPt94712625, dstPt94712625, 94712625);
+
+ ConnEnd srcPt92802970(Point(50990, 50450), 8);
+ ConnEnd dstPt92802970(Point(51275, 50485), 1);
+ ConnRef *conn = new ConnRef(router, srcPt92802970, dstPt92802970, 92802970);
+ std::vector<Checkpoint> checkpoints;
+ checkpoints.push_back(Point(50000, 50000));
+ checkpoints.push_back(Point(50200, 50000));
+ checkpoints.push_back(Point(50200, 50200));
+ conn->setRoutingCheckpoints(checkpoints);
+
+ ConnEnd srcPt716502036(Point(50710, 50500), 4);
+ ConnEnd dstPt716502036(Point(51800, 50925), 15);
+ new ConnRef(router, srcPt716502036, dstPt716502036, 716502036);
+ router->processTransaction();
+ router->outputDiagram("output/checkpoints01-1");
+ router->moveJunction(junctionRef478845150, 585, 0);
+ router->processTransaction();
+ router->outputDiagram("output/checkpoints01-2");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/checkpoints02.cpp b/src/3rdparty/adaptagrams/libavoid/tests/checkpoints02.cpp
new file mode 100644
index 0000000..c6fa9ee
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/checkpoints02.cpp
@@ -0,0 +1,105 @@
+// This is a regression test checking for a problem where orthogonal c-bends
+// due to checkpoints were being incorrectly limited in one dimension as if
+// they were bending around an obstacle.
+
+#include <cmath>
+
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingParameter((RoutingParameter)0, 50);
+ router->setRoutingParameter((RoutingParameter)1, 0);
+ router->setRoutingParameter((RoutingParameter)2, 0);
+ router->setRoutingParameter((RoutingParameter)3, 4000);
+ router->setRoutingParameter((RoutingParameter)4, 0);
+ router->setRoutingParameter((RoutingParameter)5, 100);
+ router->setRoutingParameter((RoutingParameter)6, 0);
+ router->setRoutingParameter((RoutingParameter)7, 4);
+ router->setRoutingOption((RoutingOption)0, true);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, false);
+ router->setRoutingOption((RoutingOption)3, false);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(365.3425124847556, 152.0752314071785);
+ poly5.ps[1] = Point(365.3425124847556, 214.0752314071785);
+ poly5.ps[2] = Point(303.3425124847556, 214.0752314071785);
+ poly5.ps[3] = Point(303.3425124847556, 152.0752314071785);
+ new ShapeRef(router, poly5, 5);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(365.3425124847556, 24.07523140617849);
+ poly7.ps[1] = Point(365.3425124847556, 86.07523140617849);
+ poly7.ps[2] = Point(303.3425124847556, 86.07523140617849);
+ poly7.ps[3] = Point(303.3425124847556, 24.07523140617849);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(541.6758458190889, 24.07523140617849);
+ poly8.ps[1] = Point(541.6758458190889, 44.07523140617849);
+ poly8.ps[2] = Point(509.6758458190889, 44.07523140617849);
+ poly8.ps[3] = Point(509.6758458190889, 24.07523140617849);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(541.6758458190889, 66.07523140617849);
+ poly10.ps[1] = Point(541.6758458190889, 86.07523140617849);
+ poly10.ps[2] = Point(509.6758458190889, 86.07523140617849);
+ poly10.ps[3] = Point(509.6758458190889, 66.07523140617849);
+ new ShapeRef(router, poly10, 10);
+
+ Polygon poly61(4);
+ poly61.ps[0] = Point(420.3425124847556, 101.0752314061785);
+ poly61.ps[1] = Point(420.3425124847556, 141.0752314061785);
+ poly61.ps[2] = Point(344.3425124847556, 141.0752314061785);
+ poly61.ps[3] = Point(344.3425124847556, 101.0752314061785);
+ new ShapeRef(router, poly61, 61);
+
+ Polygon poly92(4);
+ poly92.ps[0] = Point(563.5758458190888, 34.07523140617849);
+ poly92.ps[1] = Point(563.5758458190888, 76.07523140617849);
+ poly92.ps[2] = Point(487.7758458190889, 76.07523140617849);
+ poly92.ps[3] = Point(487.7758458190889, 34.07523140617849);
+ new ShapeRef(router, poly92, 92);
+
+ ConnRef *connRef109 = new ConnRef(router, 109);
+ ConnEnd srcPt109(Point(510.6758458190889, 34.07523140617849), 4);
+ connRef109->setSourceEndpoint(srcPt109);
+ ConnEnd dstPt109(Point(334.3425124847556, 183.0752314071785), 15);
+ connRef109->setDestEndpoint(dstPt109);
+ connRef109->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints109(1);
+ checkpoints109[0] = Checkpoint(Point(487.6758458190889, 55.07523140617849), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef109->setRoutingCheckpoints(checkpoints109);
+
+ ConnRef *connRef110 = new ConnRef(router, 110);
+ ConnEnd srcPt110(Point(510.6758458190889, 76.07523140617849), 4);
+ connRef110->setSourceEndpoint(srcPt110);
+ ConnEnd dstPt110(Point(334.3425124847556, 183.0752314071785), 15);
+ connRef110->setDestEndpoint(dstPt110);
+ connRef110->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints110(1);
+ checkpoints110[0] = Checkpoint(Point(487.6758458190889, 55.07523140617849), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef110->setRoutingCheckpoints(checkpoints110);
+
+ router->processTransaction();
+ router->outputDiagram("output/checkpoints02");
+
+ bool succeeded = true;
+ double checkpointY = 55.07523140617849;
+ Avoid::PolyLine route109 = connRef109->displayRoute();
+ if (fabs(route109.ps[route109.size() - 3].y - checkpointY) < 2)
+ {
+ succeeded = false;
+ }
+
+ Avoid::PolyLine route110 = connRef110->displayRoute();
+ if (fabs(route110.ps[route110.size() - 3].y - checkpointY) < 2)
+ {
+ succeeded = false;
+ }
+
+ delete router;
+ return (succeeded) ? 0 : 1;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/checkpoints03.cpp b/src/3rdparty/adaptagrams/libavoid/tests/checkpoints03.cpp
new file mode 100644
index 0000000..15da706
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/checkpoints03.cpp
@@ -0,0 +1,96 @@
+// This is a regression test for a problem where free segments slightly offset
+// from effectively fixed segments going through a checkpoint did not get
+// aligned.
+#include <cmath>
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingParameter((RoutingParameter)0, 50);
+ router->setRoutingParameter((RoutingParameter)1, 0);
+ router->setRoutingParameter((RoutingParameter)2, 0);
+ router->setRoutingParameter((RoutingParameter)3, 4000);
+ router->setRoutingParameter((RoutingParameter)4, 0);
+ router->setRoutingParameter((RoutingParameter)5, 100);
+ router->setRoutingParameter((RoutingParameter)6, 0);
+ router->setRoutingParameter((RoutingParameter)7, 4);
+ router->setRoutingOption((RoutingOption)0, true);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, false);
+ router->setRoutingOption((RoutingOption)3, false);
+
+ Polygon poly41(4);
+ poly41.ps[0] = Point(918.6758458220888, 441.0752314081785);
+ poly41.ps[1] = Point(918.6758458220888, 503.0752314081785);
+ poly41.ps[2] = Point(856.6758458220888, 503.0752314081785);
+ poly41.ps[3] = Point(856.6758458220888, 441.0752314081785);
+ new ShapeRef(router, poly41, 41);
+
+
+ Polygon poly43(4);
+ poly43.ps[0] = Point(710.6758458200889, 441.0752314081785);
+ poly43.ps[1] = Point(710.6758458200889, 461.0752314081785);
+ poly43.ps[2] = Point(678.6758458200889, 461.0752314081785);
+ poly43.ps[3] = Point(678.6758458200889, 441.0752314081785);
+ new ShapeRef(router, poly43, 43);
+
+ Polygon poly44(4);
+ poly44.ps[0] = Point(710.6758458200889, 483.0752314081785);
+ poly44.ps[1] = Point(710.6758458200889, 503.0752314081785);
+ poly44.ps[2] = Point(678.6758458200889, 503.0752314081785);
+ poly44.ps[3] = Point(678.6758458200889, 483.0752314081785);
+ new ShapeRef(router, poly44, 44);
+
+ ConnRef *connRef149 = new ConnRef(router, 149);
+ ConnEnd srcPt149(Point(709.6758458200889, 451.0752314081785), 8);
+ connRef149->setSourceEndpoint(srcPt149);
+ ConnEnd dstPt149(Point(887.6758458220888, 472.0752314081786), 15);
+ connRef149->setDestEndpoint(dstPt149);
+ connRef149->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints149(1);
+ checkpoints149[0] = Checkpoint(Point(732.6758458200889, 472.0752314081785), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef149->setRoutingCheckpoints(checkpoints149);
+
+ ConnRef *connRef150 = new ConnRef(router, 150);
+ ConnEnd srcPt150(Point(709.6758458200889, 493.0752314081785), 8);
+ connRef150->setSourceEndpoint(srcPt150);
+ ConnEnd dstPt150(Point(887.6758458220888, 472.0752314081786), 15);
+ connRef150->setDestEndpoint(dstPt150);
+ connRef150->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints150(1);
+ checkpoints150[0] = Checkpoint(Point(732.6758458200889, 472.0752314081785), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef150->setRoutingCheckpoints(checkpoints150);
+
+ router->processTransaction();
+ router->outputDiagram("output/checkpoints03");
+
+ bool succeeded = true;
+ Avoid::PolyLine route149 = connRef149->displayRoute();
+ Avoid::PolyLine route150 = connRef150->displayRoute();
+ if (route149.size() > 4 || route150.size() > 4)
+ {
+ // Five segments weren't merged into three. The segments in the shape
+ // on right weren't shifted to align with the segments going through
+ // the checkpoint.
+ succeeded = false;
+ }
+ if (succeeded == true)
+ {
+ // The segments were merged by were not centred around the
+ // checkpoint.
+ double checkpointY = 472.0752314081785;
+ if (fabs(route149.ps[route149.size() - 1].y - checkpointY) < 2)
+ {
+ succeeded = false;
+ }
+
+ if (fabs(route150.ps[route150.size() - 1].y - checkpointY) < 2)
+ {
+ succeeded = false;
+ }
+ }
+ delete router;
+ return (succeeded) ? 0 : 1;
+};
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/complex.cpp b/src/3rdparty/adaptagrams/libavoid/tests/complex.cpp
new file mode 100644
index 0000000..6335a11
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/complex.cpp
@@ -0,0 +1,107 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ * Copyright (C) 2004-2007 Michael Wybrow <mjwybrow@users.sourceforge.net>
+ * Copyright (C) 2009 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow <mjwybrow@users.sourceforge.net>
+*/
+
+#include "libavoid/libavoid.h"
+
+
+
+static void connCallback(void *ptr)
+{
+ Avoid::ConnRef *connRef = (Avoid::ConnRef *) ptr;
+
+ printf("Connector %u needs rerouting!\n", connRef->id());
+
+ const Avoid::PolyLine& route = connRef->route();
+ printf("New path: ");
+ for (size_t i = 0; i < route.ps.size(); ++i)
+ {
+ printf("%s(%f, %f)", (i > 0) ? "-" : "",
+ route.ps[i].x, route.ps[i].y);
+ }
+ printf("\n");
+}
+
+
+int main(void)
+{
+ Avoid::Router *router = new Avoid::Router(Avoid::OrthogonalRouting |
+ Avoid::PolyLineRouting);
+
+ Avoid::Point srcPt(1.2, 0.5);
+ Avoid::Point dstPt(1.5, 4);
+ Avoid::ConnRef *connRef = new Avoid::ConnRef(router, srcPt, dstPt);
+ connRef->setCallback(connCallback, connRef);
+ // Force inital callback:
+ router->processTransaction();
+
+ printf("\nAdding a shape.\n");
+ // Create the ShapeRef:
+ Avoid::Polygon shapePoly(3);
+ shapePoly.ps[0] = Avoid::Point(1, 1);
+ shapePoly.ps[1] = Avoid::Point(2.5, 1.5);
+ shapePoly.ps[2] = Avoid::Point(1.5, 2.5);
+ Avoid::ShapeRef *shapeRef = new Avoid::ShapeRef(router, shapePoly);
+ router->processTransaction();
+
+ printf("\nShifting endpoint.\n");
+ Avoid::Point dstPt2(6, 4.5);
+ connRef->setDestEndpoint(dstPt2);
+ // It's expected you know the connector needs rerouting, so the callback
+ // isn't called. You can force it to be called though, via:
+ router->processTransaction();
+
+ printf("\nMoving shape right by 0.5.\n");
+ router->moveShape(shapeRef, 0.5, 0);
+ router->processTransaction();
+
+ printf("\nChanging type to orthogonal.\n");
+ connRef->setRoutingType(Avoid::ConnType_Orthogonal);
+ router->processTransaction();
+
+ printf("\nChanging type back to polyline.\n");
+ connRef->setRoutingType(Avoid::ConnType_PolyLine);
+ router->processTransaction();
+
+ router->deleteConnector(connRef);
+ printf("\nRemoving shape.\n");
+ router->deleteShape(shapeRef);
+ router->processTransaction();
+
+ printf("\nReadding shape.\n");
+ shapeRef = new Avoid::ShapeRef(router, shapePoly);
+ router->processTransaction();
+
+ printf("\nMoving shape right by 0.5.\n");
+ router->moveShape(shapeRef, 0.5, 0);
+ router->processTransaction();
+
+ router->deleteShape(shapeRef);
+ shapeRef = nullptr;
+ router->processTransaction();
+
+ router->outputDiagram("output/complex");
+ delete router;
+ return 0;
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/connectionpin01.cpp b/src/3rdparty/adaptagrams/libavoid/tests/connectionpin01.cpp
new file mode 100644
index 0000000..92c3760
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/connectionpin01.cpp
@@ -0,0 +1,68 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ * Copyright (C) 2010 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow <mjwybrow@users.sourceforge.net>
+*/
+
+#include "libavoid/libavoid.h"
+#include "libavoid/connectionpin.h"
+
+// A testcase to check the functionality for connection pins.
+
+
+int main(void)
+{
+ Avoid::Router *router = new Avoid::Router(Avoid::OrthogonalRouting);
+
+ // Create the ShapeRef:
+ Avoid::Rectangle shapeRect1(Avoid::Point(0, 0), Avoid::Point(10, 10));
+ Avoid::ShapeRef *shapeRef1 = new Avoid::ShapeRef(router, shapeRect1);
+
+
+ Avoid::Rectangle shapeRect2(Avoid::Point(40, 20), Avoid::Point(50, 30));
+ Avoid::ShapeRef *shapeRef2 = new Avoid::ShapeRef(router, shapeRect2);
+
+ const unsigned int CENTRE = 1;
+ new Avoid::ShapeConnectionPin(shapeRef1, CENTRE, Avoid::ATTACH_POS_CENTRE,
+ Avoid::ATTACH_POS_CENTRE, true, 0.0, Avoid::ConnDirNone);
+ new Avoid::ShapeConnectionPin(shapeRef2, CENTRE, Avoid::ATTACH_POS_CENTRE,
+ Avoid::ATTACH_POS_CENTRE, true, 0.0, Avoid::ConnDirNone);
+
+ Avoid::ConnEnd dstEnd(shapeRef1, CENTRE);
+ Avoid::ConnEnd srcEnd(shapeRef2, CENTRE);
+ new Avoid::ConnRef(router, srcEnd, dstEnd);
+ // Force inital callback:
+ router->processTransaction();
+ router->outputDiagram("output/connectionpin01-1");
+
+ router->moveShape(shapeRef2, 5, 0);
+
+ router->processTransaction();
+ router->outputDiagram("output/connectionpin01-2");
+
+ router->moveShape(shapeRef1, 0, -10);
+
+ router->processTransaction();
+ router->outputDiagram("output/connectionpin01-3");
+
+ delete router;
+ return 0;
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/connectionpin02.cpp b/src/3rdparty/adaptagrams/libavoid/tests/connectionpin02.cpp
new file mode 100644
index 0000000..5724150
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/connectionpin02.cpp
@@ -0,0 +1,113 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ * Copyright (C) 2010 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow <mjwybrow@users.sourceforge.net>
+*/
+
+#include "libavoid/libavoid.h"
+#include "libavoid/connectionpin.h"
+
+// A testcase to check the functionality for connection pins.
+
+
+int main(void)
+{
+ Avoid::Router *router = new Avoid::Router(Avoid::OrthogonalRouting);
+ router->setRoutingPenalty((Avoid::PenaltyType)0, 50);
+
+ // Create the ShapeRef:
+ Avoid::Rectangle shapeRect1(Avoid::Point(0, 0), Avoid::Point(10, 10));
+ Avoid::ShapeRef *shapeRef1 = new Avoid::ShapeRef(router, shapeRect1);
+
+ Avoid::Rectangle shapeRect2(Avoid::Point(0, 90), Avoid::Point(20, 100));
+ Avoid::ShapeRef *shapeRef2 = new Avoid::ShapeRef(router, shapeRect2);
+
+ Avoid::Rectangle shapeRect3(Avoid::Point(50, 40), Avoid::Point(90, 80));
+ Avoid::ShapeRef *shapeRef3 = new Avoid::ShapeRef(router, shapeRect3);
+
+ // Create pins two input pins on the left side of shape 3.
+ const unsigned int INPUT = 1;
+ new Avoid::ShapeConnectionPin(shapeRef3, INPUT, 0.25,
+ 0.4, true, 0, Avoid::ConnDirLeft);
+ new Avoid::ShapeConnectionPin(shapeRef3, INPUT, 0.75,
+ 0.6, true, 0, Avoid::ConnDirLeft);
+
+ // And centre pins for two other shapes.
+ new Avoid::ShapeConnectionPin(shapeRef1, Avoid::CONNECTIONPIN_CENTRE,
+ Avoid::ATTACH_POS_CENTRE, Avoid::ATTACH_POS_CENTRE, true, 0.0, Avoid::ConnDirNone);
+ new Avoid::ShapeConnectionPin(shapeRef2, Avoid::CONNECTIONPIN_CENTRE,
+ Avoid::ATTACH_POS_CENTRE, Avoid::ATTACH_POS_CENTRE, true, 0.0, Avoid::ConnDirNone);
+
+ // Create connectors from each shape to an input pin on shape 3.
+ Avoid::ConnEnd srcEnd(shapeRef2, Avoid::CONNECTIONPIN_CENTRE);
+ Avoid::ConnEnd dstEnd(shapeRef3, INPUT);
+ new Avoid::ConnRef(router, srcEnd, dstEnd);
+
+ srcEnd = Avoid::ConnEnd(shapeRef1, Avoid::CONNECTIONPIN_CENTRE);
+ dstEnd = Avoid::ConnEnd(shapeRef3, INPUT);
+ new Avoid::ConnRef(router, srcEnd, dstEnd);
+
+ router->processTransaction();
+ router->outputDiagram("output/connectionpin02-1");
+
+ router->moveShape(shapeRef1, 0, 90);
+ router->moveShape(shapeRef2, 0, -90);
+
+ router->processTransaction();
+ router->outputDiagram("output/connectionpin02-2");
+
+ router->moveShape(shapeRef3, 0, -60);
+
+ router->processTransaction();
+ router->outputDiagram("output/connectionpin02-3");
+
+ shapeRef3->transformConnectionPinPositions(Avoid::TransformationType_CW90);
+ /*
+ delete pin1;
+ delete pin2;
+ pin1 = new Avoid::ShapeConnectionPin(shapeRef3, INPUT,
+ Avoid::ATTACH_POS_RIGHT, 0.25, 5, Avoid::ConnDirRight);
+ pin2 = new Avoid::ShapeConnectionPin(shapeRef3, INPUT,
+ Avoid::ATTACH_POS_RIGHT, 0.75, 5, Avoid::ConnDirRight);
+ */
+
+ router->processTransaction();
+ router->outputDiagram("output/connectionpin02-4");
+
+ shapeRef3->transformConnectionPinPositions(Avoid::TransformationType_CW180);
+ router->processTransaction();
+ router->outputDiagram("output/connectionpin02-5");
+
+ shapeRef3->transformConnectionPinPositions(Avoid::TransformationType_CW270);
+ router->processTransaction();
+ router->outputDiagram("output/connectionpin02-6");
+
+ shapeRef3->transformConnectionPinPositions(Avoid::TransformationType_FlipX);
+ router->processTransaction();
+ router->outputDiagram("output/connectionpin02-7");
+
+ shapeRef3->transformConnectionPinPositions(Avoid::TransformationType_FlipY);
+ router->processTransaction();
+ router->outputDiagram("output/connectionpin02-8");
+
+ delete router;
+ return 0;
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/connectionpin03.cpp b/src/3rdparty/adaptagrams/libavoid/tests/connectionpin03.cpp
new file mode 100644
index 0000000..a877817
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/connectionpin03.cpp
@@ -0,0 +1,328 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 200);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 110);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+ Polygon poly219926511(4);
+ poly219926511.ps[0] = Point(50760, 51240);
+ poly219926511.ps[1] = Point(50760, 51260);
+ poly219926511.ps[2] = Point(50740, 51260);
+ poly219926511.ps[3] = Point(50740, 51240);
+ ShapeRef *shapeRef219926511 = new ShapeRef(router, poly219926511, 219926511);
+ new ShapeConnectionPin(shapeRef219926511, 2147483646, 0.5, 0.5, true, 0, (ConnDirFlags) 4);
+ new ShapeConnectionPin(shapeRef219926511, 2147483646, 0.5, 0.5, true, 0, (ConnDirFlags) 1);
+ new ShapeConnectionPin(shapeRef219926511, 2147483646, 0.5, 0.5, true, 0, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef219926511, 2147483646, 0.5, 0.5, true, 0, (ConnDirFlags) 2);
+
+ JunctionRef *shapeRef171026375 = new JunctionRef(router, Point(51075, 51225), 171026375);
+
+ Polygon poly878674(4);
+ poly878674.ps[0] = Point(51454, 51200);
+ poly878674.ps[1] = Point(51454, 51285);
+ poly878674.ps[2] = Point(51396, 51285);
+ poly878674.ps[3] = Point(51396, 51200);
+ new ShapeRef(router, poly878674, 878674);
+
+ Polygon poly286906544(4);
+ poly286906544.ps[0] = Point(50704, 51250);
+ poly286906544.ps[1] = Point(50704, 51335);
+ poly286906544.ps[2] = Point(50646, 51335);
+ poly286906544.ps[3] = Point(50646, 51250);
+ new ShapeRef(router, poly286906544, 286906544);
+
+ Polygon poly170813081(4);
+ poly170813081.ps[0] = Point(51104, 51090);
+ poly170813081.ps[1] = Point(51104, 51175);
+ poly170813081.ps[2] = Point(51046, 51175);
+ poly170813081.ps[3] = Point(51046, 51090);
+ new ShapeRef(router, poly170813081, 170813081);
+
+ Polygon poly342721632(4);
+ poly342721632.ps[0] = Point(51910, 50946);
+ poly342721632.ps[1] = Point(51910, 51004);
+ poly342721632.ps[2] = Point(51825, 51004);
+ poly342721632.ps[3] = Point(51825, 50946);
+ new ShapeRef(router, poly342721632, 342721632);
+
+ Polygon poly223927132(4);
+ poly223927132.ps[0] = Point(51510, 51190);
+ poly223927132.ps[1] = Point(51510, 51210);
+ poly223927132.ps[2] = Point(51490, 51210);
+ poly223927132.ps[3] = Point(51490, 51190);
+ ShapeRef *shapeRef223927132 = new ShapeRef(router, poly223927132, 223927132);
+ new ShapeConnectionPin(shapeRef223927132, 2147483646, 0.5, 0.5, true, 0, (ConnDirFlags) 4);
+ new ShapeConnectionPin(shapeRef223927132, 2147483646, 0.5, 0.5, true, 0, (ConnDirFlags) 1);
+ new ShapeConnectionPin(shapeRef223927132, 2147483646, 0.5, 0.5, true, 0, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef223927132, 2147483646, 0.5, 0.5, true, 0, (ConnDirFlags) 2);
+
+ JunctionRef *shapeRef102578723 = new JunctionRef(router, Point(51275, 50725), 102578723);
+
+ JunctionRef *shapeRef17922268 = new JunctionRef(router, Point(50850, 50975), 17922268);
+
+ Polygon poly11057158(4);
+ poly11057158.ps[0] = Point(51679, 51200);
+ poly11057158.ps[1] = Point(51679, 51285);
+ poly11057158.ps[2] = Point(51621, 51285);
+ poly11057158.ps[3] = Point(51621, 51200);
+ new ShapeRef(router, poly11057158, 11057158);
+
+ Polygon poly322446045(4);
+ poly322446045.ps[0] = Point(50779, 51240);
+ poly322446045.ps[1] = Point(50779, 51335);
+ poly322446045.ps[2] = Point(50721, 51335);
+ poly322446045.ps[3] = Point(50721, 51240);
+ new ShapeRef(router, poly322446045, 322446045);
+
+ Polygon poly767565928(4);
+ poly767565928.ps[0] = Point(51004, 50741);
+ poly767565928.ps[1] = Point(51004, 50826);
+ poly767565928.ps[2] = Point(50946, 50826);
+ poly767565928.ps[3] = Point(50946, 50741);
+ new ShapeRef(router, poly767565928, 767565928);
+
+ Polygon poly280939374(4);
+ poly280939374.ps[0] = Point(51085, 50971);
+ poly280939374.ps[1] = Point(51085, 51029);
+ poly280939374.ps[2] = Point(51000, 51029);
+ poly280939374.ps[3] = Point(51000, 50971);
+ new ShapeRef(router, poly280939374, 280939374);
+
+ Polygon poly630623707(4);
+ poly630623707.ps[0] = Point(51279, 50925);
+ poly630623707.ps[1] = Point(51279, 51010);
+ poly630623707.ps[2] = Point(51221, 51010);
+ poly630623707.ps[3] = Point(51221, 50925);
+ new ShapeRef(router, poly630623707, 630623707);
+
+ Polygon poly28160455(4);
+ poly28160455.ps[0] = Point(50879, 51250);
+ poly28160455.ps[1] = Point(50879, 51335);
+ poly28160455.ps[2] = Point(50821, 51335);
+ poly28160455.ps[3] = Point(50821, 51250);
+ new ShapeRef(router, poly28160455, 28160455);
+
+ Polygon poly525890448(4);
+ poly525890448.ps[0] = Point(51174, 50721);
+ poly525890448.ps[1] = Point(51174, 50779);
+ poly525890448.ps[2] = Point(51089, 50779);
+ poly525890448.ps[3] = Point(51089, 50721);
+ new ShapeRef(router, poly525890448, 525890448);
+
+ Polygon poly157182552(4);
+ poly157182552.ps[0] = Point(51529, 51190);
+ poly157182552.ps[1] = Point(51529, 51285);
+ poly157182552.ps[2] = Point(51471, 51285);
+ poly157182552.ps[3] = Point(51471, 51190);
+ new ShapeRef(router, poly157182552, 157182552);
+
+ Polygon poly799637520(4);
+ poly799637520.ps[0] = Point(50625, 50896);
+ poly799637520.ps[1] = Point(50625, 50954);
+ poly799637520.ps[2] = Point(50540, 50954);
+ poly799637520.ps[3] = Point(50540, 50896);
+ new ShapeRef(router, poly799637520, 799637520);
+
+ Polygon poly60349320(4);
+ poly60349320.ps[0] = Point(50904, 51025);
+ poly60349320.ps[1] = Point(50904, 51110);
+ poly60349320.ps[2] = Point(50846, 51110);
+ poly60349320.ps[3] = Point(50846, 51025);
+ new ShapeRef(router, poly60349320, 60349320);
+
+ Polygon poly119851894(4);
+ poly119851894.ps[0] = Point(51179, 51225);
+ poly119851894.ps[1] = Point(51179, 51310);
+ poly119851894.ps[2] = Point(51121, 51310);
+ poly119851894.ps[3] = Point(51121, 51225);
+ new ShapeRef(router, poly119851894, 119851894);
+
+ Polygon poly233164275(4);
+ poly233164275.ps[0] = Point(51604, 51200);
+ poly233164275.ps[1] = Point(51604, 51285);
+ poly233164275.ps[2] = Point(51546, 51285);
+ poly233164275.ps[3] = Point(51546, 51200);
+ new ShapeRef(router, poly233164275, 233164275);
+
+ Polygon poly807558175(4);
+ poly807558175.ps[0] = Point(51604, 51000);
+ poly807558175.ps[1] = Point(51604, 51085);
+ poly807558175.ps[2] = Point(51546, 51085);
+ poly807558175.ps[3] = Point(51546, 51000);
+ new ShapeRef(router, poly807558175, 807558175);
+
+ JunctionRef *shapeRef265539540 = new JunctionRef(router, Point(51625, 50950), 265539540);
+
+ Polygon poly108859552(4);
+ poly108859552.ps[0] = Point(51560, 50721);
+ poly108859552.ps[1] = Point(51560, 50779);
+ poly108859552.ps[2] = Point(51475, 50779);
+ poly108859552.ps[3] = Point(51475, 50721);
+ new ShapeRef(router, poly108859552, 108859552);
+
+ Polygon poly404900496(4);
+ poly404900496.ps[0] = Point(51525, 50946);
+ poly404900496.ps[1] = Point(51525, 51004);
+ poly404900496.ps[2] = Point(51440, 51004);
+ poly404900496.ps[3] = Point(51440, 50946);
+ new ShapeRef(router, poly404900496, 404900496);
+
+ Polygon poly620445000(4);
+ poly620445000.ps[0] = Point(51029, 51225);
+ poly620445000.ps[1] = Point(51029, 51310);
+ poly620445000.ps[2] = Point(50971, 51310);
+ poly620445000.ps[3] = Point(50971, 51225);
+ new ShapeRef(router, poly620445000, 620445000);
+
+ ConnRef *connRef450684531 = new ConnRef(router, 450684531);
+ ConnEnd srcPt450684531(Point(51165, 50750), 8);
+ connRef450684531->setSourceEndpoint(srcPt450684531);
+ ConnEnd dstPt450684531(shapeRef102578723);
+ connRef450684531->setDestEndpoint(dstPt450684531);
+ connRef450684531->setRoutingType((ConnType)2);
+
+ ConnRef *connRef135371350 = new ConnRef(router, 135371350);
+ ConnEnd srcPt135371350(shapeRef102578723);
+ connRef135371350->setSourceEndpoint(srcPt135371350);
+ ConnEnd dstPt135371350(Point(51250, 50935), 1);
+ connRef135371350->setDestEndpoint(dstPt135371350);
+ connRef135371350->setRoutingType((ConnType)2);
+
+ ConnRef *connRef143333770 = new ConnRef(router, 143333770);
+ ConnEnd srcPt143333770(Point(51485, 50750), 4);
+ connRef143333770->setSourceEndpoint(srcPt143333770);
+ ConnEnd dstPt143333770(shapeRef102578723);
+ connRef143333770->setDestEndpoint(dstPt143333770);
+ connRef143333770->setRoutingType((ConnType)2);
+
+ ConnRef *connRef102966575 = new ConnRef(router, 102966575);
+ ConnEnd srcPt102966575(Point(50615, 50925), 8);
+ connRef102966575->setSourceEndpoint(srcPt102966575);
+ ConnEnd dstPt102966575(shapeRef17922268);
+ connRef102966575->setDestEndpoint(dstPt102966575);
+ connRef102966575->setRoutingType((ConnType)2);
+
+ ConnRef *connRef68998920 = new ConnRef(router, 68998920);
+ ConnEnd srcPt68998920(shapeRef17922268);
+ connRef68998920->setSourceEndpoint(srcPt68998920);
+ ConnEnd dstPt68998920(Point(50975, 50815), 2);
+ connRef68998920->setDestEndpoint(dstPt68998920);
+ connRef68998920->setRoutingType((ConnType)2);
+
+ ConnRef *connRef1625709 = new ConnRef(router, 1625709);
+ ConnEnd srcPt1625709(shapeRef17922268);
+ connRef1625709->setSourceEndpoint(srcPt1625709);
+ ConnEnd dstPt1625709(Point(50875, 51035), 1);
+ connRef1625709->setDestEndpoint(dstPt1625709);
+ connRef1625709->setRoutingType((ConnType)2);
+
+ ConnRef *connRef34178450 = new ConnRef(router, 34178450);
+ ConnEnd srcPt34178450(shapeRef17922268);
+ connRef34178450->setSourceEndpoint(srcPt34178450);
+ ConnEnd dstPt34178450(Point(51010, 51000), 4);
+ connRef34178450->setDestEndpoint(dstPt34178450);
+ connRef34178450->setRoutingType((ConnType)2);
+
+ ConnRef *connRef7982176 = new ConnRef(router, 7982176);
+ ConnEnd srcPt7982176(Point(50675, 51260), 1);
+ connRef7982176->setSourceEndpoint(srcPt7982176);
+ ConnEnd dstPt7982176(shapeRef219926511, 2147483646);
+ connRef7982176->setDestEndpoint(dstPt7982176);
+ connRef7982176->setRoutingType((ConnType)2);
+
+ ConnRef *connRef197177982 = new ConnRef(router, 197177982);
+ ConnEnd srcPt197177982(Point(50750, 51250), 15);
+ connRef197177982->setSourceEndpoint(srcPt197177982);
+ ConnEnd dstPt197177982(Point(50750, 51260), 1);
+ connRef197177982->setDestEndpoint(dstPt197177982);
+ connRef197177982->setRoutingType((ConnType)2);
+
+ ConnRef *connRef398066432 = new ConnRef(router, 398066432);
+ ConnEnd srcPt398066432(shapeRef219926511, 2147483646);
+ connRef398066432->setSourceEndpoint(srcPt398066432);
+ ConnEnd dstPt398066432(Point(50850, 51260), 1);
+ connRef398066432->setDestEndpoint(dstPt398066432);
+ connRef398066432->setRoutingType((ConnType)2);
+
+ ConnRef *connRef314512308 = new ConnRef(router, 314512308);
+ ConnEnd srcPt314512308(Point(51000, 51235), 1);
+ connRef314512308->setSourceEndpoint(srcPt314512308);
+ ConnEnd dstPt314512308(shapeRef171026375);
+ connRef314512308->setDestEndpoint(dstPt314512308);
+ connRef314512308->setRoutingType((ConnType)2);
+
+ ConnRef *connRef182776308 = new ConnRef(router, 182776308);
+ ConnEnd srcPt182776308(Point(51075, 51225), 15);
+ connRef182776308->setSourceEndpoint(srcPt182776308);
+ ConnEnd dstPt182776308(Point(51075, 51165), 2);
+ connRef182776308->setDestEndpoint(dstPt182776308);
+ connRef182776308->setRoutingType((ConnType)2);
+
+ ConnRef *connRef96504835 = new ConnRef(router, 96504835);
+ ConnEnd srcPt96504835(Point(51150, 51235), 1);
+ connRef96504835->setSourceEndpoint(srcPt96504835);
+ ConnEnd dstPt96504835(shapeRef171026375);
+ connRef96504835->setDestEndpoint(dstPt96504835);
+ connRef96504835->setRoutingType((ConnType)2);
+
+ ConnRef *connRef118099300 = new ConnRef(router, 118099300);
+ ConnEnd srcPt118099300(Point(51425, 51210), 1);
+ connRef118099300->setSourceEndpoint(srcPt118099300);
+ ConnEnd dstPt118099300(shapeRef223927132, 2147483646);
+ connRef118099300->setDestEndpoint(dstPt118099300);
+ connRef118099300->setRoutingType((ConnType)2);
+
+ ConnRef *connRef176080410 = new ConnRef(router, 176080410);
+ ConnEnd srcPt176080410(shapeRef223927132, 2147483646);
+ connRef176080410->setSourceEndpoint(srcPt176080410);
+ ConnEnd dstPt176080410(Point(51575, 51210), 1);
+ connRef176080410->setDestEndpoint(dstPt176080410);
+ connRef176080410->setRoutingType((ConnType)2);
+
+ ConnRef *connRef426666001 = new ConnRef(router, 426666001);
+ ConnEnd srcPt426666001(Point(51500, 51210), 1);
+ connRef426666001->setSourceEndpoint(srcPt426666001);
+ ConnEnd dstPt426666001(Point(51500, 51200), 15);
+ connRef426666001->setDestEndpoint(dstPt426666001);
+ connRef426666001->setRoutingType((ConnType)2);
+
+ ConnRef *connRef795762792 = new ConnRef(router, 795762792);
+ ConnEnd srcPt795762792(Point(51650, 51210), 1);
+ connRef795762792->setSourceEndpoint(srcPt795762792);
+ ConnEnd dstPt795762792(shapeRef223927132, 2147483646);
+ connRef795762792->setDestEndpoint(dstPt795762792);
+ connRef795762792->setRoutingType((ConnType)2);
+
+ ConnRef *connRef467016913 = new ConnRef(router, 467016913);
+ ConnEnd srcPt467016913(shapeRef265539540);
+ connRef467016913->setSourceEndpoint(srcPt467016913);
+ ConnEnd dstPt467016913(Point(51575, 51010), 1);
+ connRef467016913->setDestEndpoint(dstPt467016913);
+ connRef467016913->setRoutingType((ConnType)2);
+
+ ConnRef *connRef45740440 = new ConnRef(router, 45740440);
+ ConnEnd srcPt45740440(Point(51835, 50975), 4);
+ connRef45740440->setSourceEndpoint(srcPt45740440);
+ ConnEnd dstPt45740440(shapeRef265539540);
+ connRef45740440->setDestEndpoint(dstPt45740440);
+ connRef45740440->setRoutingType((ConnType)2);
+
+ ConnRef *connRef985644192 = new ConnRef(router, 985644192);
+ ConnEnd srcPt985644192(Point(51515, 50975), 8);
+ connRef985644192->setSourceEndpoint(srcPt985644192);
+ ConnEnd dstPt985644192(shapeRef265539540);
+ connRef985644192->setDestEndpoint(dstPt985644192);
+ connRef985644192->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/connectionpin03");
+ delete router;
+ return 0;
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/connendmove.cpp b/src/3rdparty/adaptagrams/libavoid/tests/connendmove.cpp
new file mode 100644
index 0000000..dfcbf8e
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/connendmove.cpp
@@ -0,0 +1,85 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ * Copyright (C) 2004-2007 Michael Wybrow <mjwybrow@users.sourceforge.net>
+ * Copyright (C) 2009 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow <mjwybrow@users.sourceforge.net>
+*/
+
+#include "libavoid/libavoid.h"
+
+// Regression test to catch a bug where moving detaching a connected
+// endpoint that was scheduled to move would result in a double free.
+
+
+int main(void)
+{
+ Avoid::Router *router = new Avoid::Router(Avoid::OrthogonalRouting);
+
+ // Create the ShapeRef:
+ Avoid::Rectangle shapeRect1(Avoid::Point(0, 0), Avoid::Point(10, 10));
+ Avoid::ShapeRef *shapeRef1 = new Avoid::ShapeRef(router, shapeRect1);
+ const unsigned int CENTRE = 1;
+ new Avoid::ShapeConnectionPin(shapeRef1, CENTRE,
+ Avoid::ATTACH_POS_CENTRE, Avoid::ATTACH_POS_CENTRE, true, 0.0, Avoid::ConnDirNone);
+
+ Avoid::Rectangle shapeRect2(Avoid::Point(0, 0), Avoid::Point(10, 10));
+ Avoid::ShapeRef *shapeRef2 = new Avoid::ShapeRef(router, shapeRect1);
+
+ Avoid::ConnEnd dstPt(shapeRef1, CENTRE);
+ Avoid::Point srcPt(1.5, 4);
+ Avoid::ConnRef *connRef = new Avoid::ConnRef(router, srcPt, dstPt);
+ // Force inital callback:
+ router->processTransaction();
+ router->outputDiagram("output/connendmove-1");
+
+ Avoid::Point dstPt2(20, 20);
+ connRef->setDestEndpoint(dstPt2);
+ router->moveShape(shapeRef1, 0.5, 0);
+
+ router->processTransaction();
+ router->outputDiagram("output/connendmove-2");
+
+ srcPt.x += 0.5;
+ connRef->setSourceEndpoint(srcPt);
+ router->moveShape(shapeRef1, 0.5, 0);
+ router->moveShape(shapeRef2, 0, 0.5);
+
+ srcPt.x += 0.5;
+ connRef->setSourceEndpoint(srcPt);
+ router->moveShape(shapeRef1, 0.5, 0);
+ router->moveShape(shapeRef2, 0, 0.5);
+
+ srcPt.x += 0.5;
+ connRef->setSourceEndpoint(srcPt);
+ router->moveShape(shapeRef1, 0.5, 0);
+ router->moveShape(shapeRef2, 0, 0.5);
+
+ srcPt.x += 0.5;
+ connRef->setSourceEndpoint(srcPt);
+ router->moveShape(shapeRef1, 0.5, 0);
+ router->moveShape(shapeRef2, 0, 0.5);
+
+ router->processTransaction();
+ router->outputDiagram("output/connendmove-3");
+
+ delete router;
+ return 0;
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/corneroverlap01.cpp b/src/3rdparty/adaptagrams/libavoid/tests/corneroverlap01.cpp
new file mode 100644
index 0000000..a0db76d
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/corneroverlap01.cpp
@@ -0,0 +1,154 @@
+// From cornertouching_libavoid-debug bug.
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 110);
+ router->setOrthogonalNudgeDistance(12);
+
+ Polygon poly21424960(4);
+ poly21424960.ps[0] = Point(29950, 27210);
+ poly21424960.ps[1] = Point(29950, 27290);
+ poly21424960.ps[2] = Point(29700, 27290);
+ poly21424960.ps[3] = Point(29700, 27210);
+ new ShapeRef(router, poly21424960, 21424960);
+
+ Polygon poly435105790(4);
+ poly435105790.ps[0] = Point(29950, 27110);
+ poly435105790.ps[1] = Point(29950, 27190);
+ poly435105790.ps[2] = Point(29700, 27190);
+ poly435105790.ps[3] = Point(29700, 27110);
+ new ShapeRef(router, poly435105790, 435105790);
+
+ Polygon poly40787191(4);
+ poly40787191.ps[0] = Point(29950, 27010);
+ poly40787191.ps[1] = Point(29950, 27090);
+ poly40787191.ps[2] = Point(29700, 27090);
+ poly40787191.ps[3] = Point(29700, 27010);
+ new ShapeRef(router, poly40787191, 40787191);
+
+ Polygon poly76911264(4);
+ poly76911264.ps[0] = Point(29950, 26910);
+ poly76911264.ps[1] = Point(29950, 26990);
+ poly76911264.ps[2] = Point(29700, 26990);
+ poly76911264.ps[3] = Point(29700, 26910);
+ new ShapeRef(router, poly76911264, 76911264);
+
+ Polygon poly506213376(4);
+ poly506213376.ps[0] = Point(29925, 26820);
+ poly506213376.ps[1] = Point(29925, 26880);
+ poly506213376.ps[2] = Point(29675, 26880);
+ poly506213376.ps[3] = Point(29675, 26820);
+ new ShapeRef(router, poly506213376, 506213376);
+
+ Polygon poly134604636(4);
+ poly134604636.ps[0] = Point(29925, 26720);
+ poly134604636.ps[1] = Point(29925, 26780);
+ poly134604636.ps[2] = Point(29675, 26780);
+ poly134604636.ps[3] = Point(29675, 26720);
+ new ShapeRef(router, poly134604636, 134604636);
+
+ Polygon poly14353632(4);
+ poly14353632.ps[0] = Point(29600, 26590);
+ poly14353632.ps[1] = Point(29600, 27660);
+ poly14353632.ps[2] = Point(28440, 27660);
+ poly14353632.ps[3] = Point(28440, 26590);
+ new ShapeRef(router, poly14353632, 14353632);
+
+ ConnRef *connRef70269732 = new ConnRef(router, 70269732);
+ ConnEnd srcPt70269732(Point(29590, 26700), 8);
+ connRef70269732->setSourceEndpoint(srcPt70269732);
+ ConnEnd dstPt70269732(Point(29915, 26750), 8);
+ connRef70269732->setDestEndpoint(dstPt70269732);
+ connRef70269732->setRoutingType((ConnType)2);
+
+ ConnRef *connRef371572709 = new ConnRef(router, 371572709);
+ ConnEnd srcPt371572709(Point(29590, 26800), 8);
+ connRef371572709->setSourceEndpoint(srcPt371572709);
+ ConnEnd dstPt371572709(Point(29915, 26850), 8);
+ connRef371572709->setDestEndpoint(dstPt371572709);
+ connRef371572709->setRoutingType((ConnType)2);
+
+ ConnRef *connRef876797766 = new ConnRef(router, 876797766);
+ ConnEnd srcPt876797766(Point(29590, 26900), 8);
+ connRef876797766->setSourceEndpoint(srcPt876797766);
+ ConnEnd dstPt876797766(Point(29940, 26950), 8);
+ connRef876797766->setDestEndpoint(dstPt876797766);
+ connRef876797766->setRoutingType((ConnType)2);
+
+ ConnRef *connRef134423590 = new ConnRef(router, 134423590);
+ ConnEnd srcPt134423590(Point(29590, 27000), 8);
+ connRef134423590->setSourceEndpoint(srcPt134423590);
+ ConnEnd dstPt134423590(Point(29940, 27050), 8);
+ connRef134423590->setDestEndpoint(dstPt134423590);
+ connRef134423590->setRoutingType((ConnType)2);
+
+ ConnRef *connRef872586669 = new ConnRef(router, 872586669);
+ ConnEnd srcPt872586669(Point(29590, 27100), 8);
+ connRef872586669->setSourceEndpoint(srcPt872586669);
+ ConnEnd dstPt872586669(Point(29940, 27150), 8);
+ connRef872586669->setDestEndpoint(dstPt872586669);
+ connRef872586669->setRoutingType((ConnType)2);
+
+ ConnRef *connRef23601612 = new ConnRef(router, 23601612);
+ ConnEnd srcPt23601612(Point(29590, 27200), 8);
+ connRef23601612->setSourceEndpoint(srcPt23601612);
+ ConnEnd dstPt23601612(Point(29940, 27250), 8);
+ connRef23601612->setDestEndpoint(dstPt23601612);
+ connRef23601612->setRoutingType((ConnType)2);
+
+ ConnRef *connRef737483980 = new ConnRef(router, 737483980);
+ ConnEnd srcPt737483980(Point(29685, 26750), 4);
+ connRef737483980->setSourceEndpoint(srcPt737483980);
+ ConnEnd dstPt737483980(Point(29590, 26650), 8);
+ connRef737483980->setDestEndpoint(dstPt737483980);
+ connRef737483980->setRoutingType((ConnType)2);
+
+ ConnRef *connRef410784855 = new ConnRef(router, 410784855);
+ ConnEnd srcPt410784855(Point(29685, 26850), 4);
+ connRef410784855->setSourceEndpoint(srcPt410784855);
+ ConnEnd dstPt410784855(Point(29590, 26750), 8);
+ connRef410784855->setDestEndpoint(dstPt410784855);
+ connRef410784855->setRoutingType((ConnType)2);
+
+ ConnRef *connRef15771480 = new ConnRef(router, 15771480);
+ ConnEnd srcPt15771480(Point(29710, 26950), 4);
+ connRef15771480->setSourceEndpoint(srcPt15771480);
+ ConnEnd dstPt15771480(Point(29590, 26850), 8);
+ connRef15771480->setDestEndpoint(dstPt15771480);
+ connRef15771480->setRoutingType((ConnType)2);
+
+ ConnRef *connRef34657402 = new ConnRef(router, 34657402);
+ ConnEnd srcPt34657402(Point(29710, 27050), 4);
+ connRef34657402->setSourceEndpoint(srcPt34657402);
+ ConnEnd dstPt34657402(Point(29590, 26950), 8);
+ connRef34657402->setDestEndpoint(dstPt34657402);
+ connRef34657402->setRoutingType((ConnType)2);
+
+ ConnRef *connRef98191218 = new ConnRef(router, 98191218);
+ ConnEnd srcPt98191218(Point(29710, 27150), 4);
+ connRef98191218->setSourceEndpoint(srcPt98191218);
+ ConnEnd dstPt98191218(Point(29590, 27050), 8);
+ connRef98191218->setDestEndpoint(dstPt98191218);
+ connRef98191218->setRoutingType((ConnType)2);
+
+ ConnRef *connRef23433311 = new ConnRef(router, 23433311);
+ ConnEnd srcPt23433311(Point(29710, 27250), 4);
+ connRef23433311->setSourceEndpoint(srcPt23433311);
+ ConnEnd dstPt23433311(Point(29590, 27150), 8);
+ connRef23433311->setDestEndpoint(dstPt23433311);
+ connRef23433311->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/corneroverlap01");
+ bool touching = router->existsOrthogonalTouchingPaths();
+ delete router;
+ return (touching) ? 1 : 0;
+};
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/endlessLoop01.cpp b/src/3rdparty/adaptagrams/libavoid/tests/endlessLoop01.cpp
new file mode 100644
index 0000000..8053be8
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/endlessLoop01.cpp
@@ -0,0 +1,142 @@
+#include "libavoid/libavoid.h"
+#include <sstream>
+using namespace Avoid;
+
+void outputDiagram(Avoid::Router * router)
+{
+ static int counter = 0;
+ std::ostringstream os;
+ os << (++counter);
+ router->outputDiagram(os.str());
+}
+
+void test()
+{
+ // The contents of this function can be replaced by the automatically generated test code from the debug svg file
+ Avoid::ConnEnd end1_0;
+ Avoid::ConnEnd end2_0;
+ Avoid::Polygon poly0;
+ std::vector<Avoid::Checkpoint> checkpoints_0;
+ Avoid::Router * router0 = new Avoid::Router(Avoid::OrthogonalRouting);
+ Avoid::HyperedgeNewAndDeletedObjectLists newanddeletedobjects_0;
+ Avoid::ConnRefList::const_iterator connit_0;
+ Avoid::JunctionRefList::const_iterator junctionit_0;
+ router0->setTransactionUse(true);
+ router0->setRoutingPenalty(Avoid::segmentPenalty);
+ router0->setRoutingPenalty(Avoid::crossingPenalty);
+ router0->setRoutingPenalty(Avoid::fixedSharedPathPenalty, 9000);
+ router0->setRoutingOption(Avoid::penaliseOrthogonalSharedPathsAtConnEnds, true);
+ router0->setRoutingParameter(Avoid::idealNudgingDistance, 25);
+ router0->setRoutingOption(Avoid::improveHyperedgeRoutesMovingAddingAndDeletingJunctions, true);
+
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(50700, 50615));
+ poly0.setPoint(1, Avoid::Point(50700, 51185));
+ poly0.setPoint(2, Avoid::Point(50365, 51185));
+ poly0.setPoint(3, Avoid::Point(50365, 50615));
+ Avoid::ShapeRef * shape0_355243155 = new Avoid::ShapeRef(router0, poly0, 355243155);
+ Avoid::ShapeConnectionPin * pin0_355243155_0 = new Avoid::ShapeConnectionPin(shape0_355243155, 1, 1, 0.149122807018, true, 10, 8);
+ pin0_355243155_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_355243155_1 = new Avoid::ShapeConnectionPin(shape0_355243155, 2, 1, 0.675438596491, true, 10, 8);
+ pin0_355243155_1->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_355243155_2 = new Avoid::ShapeConnectionPin(shape0_355243155, 3, 1, 0.80701754386, true, 10, 8);
+ pin0_355243155_2->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_355243155_3 = new Avoid::ShapeConnectionPin(shape0_355243155, 4, 1, 0.543859649123, true, 10, 8);
+ pin0_355243155_3->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_355243155_4 = new Avoid::ShapeConnectionPin(shape0_355243155, 5, 1, 0.280701754386, true, 10, 8);
+ pin0_355243155_4->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_355243155_5 = new Avoid::ShapeConnectionPin(shape0_355243155, 6, 1, 0.412280701754, true, 10, 8);
+ pin0_355243155_5->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_355243155_6 = new Avoid::ShapeConnectionPin(shape0_355243155, 7, 0.477611940299, 0.982456140351, true, 10, 2);
+ pin0_355243155_6->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_355243155_7 = new Avoid::ShapeConnectionPin(shape0_355243155, 8, 0.253731343284, 0.982456140351, true, 10, 2);
+ pin0_355243155_7->setExclusive(true);
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(51060, 50816));
+ poly0.setPoint(1, Avoid::Point(51060, 50884));
+ poly0.setPoint(2, Avoid::Point(50940, 50884));
+ poly0.setPoint(3, Avoid::Point(50940, 50816));
+ Avoid::ShapeRef * shape0_35177560 = new Avoid::ShapeRef(router0, poly0, 35177560);
+ Avoid::ShapeConnectionPin * pin0_35177560_0 = new Avoid::ShapeConnectionPin(shape0_35177560, 1, 0.5, 0.5, true, 0, 15);
+ pin0_35177560_0->setExclusive(true);
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(51060, 50966));
+ poly0.setPoint(1, Avoid::Point(51060, 51034));
+ poly0.setPoint(2, Avoid::Point(50940, 51034));
+ poly0.setPoint(3, Avoid::Point(50940, 50966));
+ Avoid::ShapeRef * shape0_214253640 = new Avoid::ShapeRef(router0, poly0, 214253640);
+ Avoid::ShapeConnectionPin * pin0_214253640_0 = new Avoid::ShapeConnectionPin(shape0_214253640, 1, 0.5, 0.5, true, 0, 15);
+ pin0_214253640_0->setExclusive(true);
+ Avoid::JunctionRef * junction0_636368600 = new Avoid::JunctionRef(router0, Avoid::Point(50875, 50850), 636368600);
+ Avoid::JunctionRef * junction0_503331836 = new Avoid::JunctionRef(router0, Avoid::Point(50875, 51000), 503331836);
+ Avoid::JunctionRef * junction0_46074711 = new Avoid::JunctionRef(router0, Avoid::Point(50775, 51000), 46074711);
+ Avoid::JunctionRef * junction0_390996481 = new Avoid::JunctionRef(router0, Avoid::Point(50775, 50850), 390996481);
+ end1_0 = Avoid::ConnEnd(junction0_636368600);
+ end2_0 = Avoid::ConnEnd(shape0_35177560, 1);
+ Avoid::ConnRef * conn0_929108568 = new Avoid::ConnRef(router0, end1_0, end2_0, 929108568);
+ end1_0 = Avoid::ConnEnd(junction0_503331836);
+ end2_0 = Avoid::ConnEnd(shape0_214253640, 1);
+ Avoid::ConnRef * conn0_627671070 = new Avoid::ConnRef(router0, end1_0, end2_0, 627671070);
+ end1_0 = Avoid::ConnEnd(junction0_636368600);
+ end2_0 = Avoid::ConnEnd(junction0_503331836);
+ Avoid::ConnRef * conn0_510680660 = new Avoid::ConnRef(router0, end1_0, end2_0, 510680660);
+ end1_0 = Avoid::ConnEnd(shape0_355243155, 2);
+ end2_0 = Avoid::ConnEnd(junction0_46074711);
+ Avoid::ConnRef * conn0_175131537 = new Avoid::ConnRef(router0, end1_0, end2_0, 175131537);
+ end1_0 = Avoid::ConnEnd(junction0_46074711);
+ end2_0 = Avoid::ConnEnd(junction0_503331836);
+ Avoid::ConnRef * conn0_545568780 = new Avoid::ConnRef(router0, end1_0, end2_0, 545568780);
+ end1_0 = Avoid::ConnEnd(shape0_355243155, 6);
+ end2_0 = Avoid::ConnEnd(junction0_390996481);
+ Avoid::ConnRef * conn0_17788857 = new Avoid::ConnRef(router0, end1_0, end2_0, 17788857);
+ end1_0 = Avoid::ConnEnd(junction0_390996481);
+ end2_0 = Avoid::ConnEnd(junction0_636368600);
+ Avoid::ConnRef * conn0_160581511 = new Avoid::ConnRef(router0, end1_0, end2_0, 160581511);
+ end1_0 = Avoid::ConnEnd(junction0_46074711);
+ end2_0 = Avoid::ConnEnd(junction0_390996481);
+ Avoid::ConnRef * conn0_92116728 = new Avoid::ConnRef(router0, end1_0, end2_0, 92116728);
+ router0->processTransaction();
+
+ newanddeletedobjects_0 = router0->newAndDeletedObjectListsFromHyperedgeImprovement();
+ outputDiagram(router0);
+ router0->deleteConnector(conn0_92116728);
+ conn0_92116728 = nullptr;
+ router0->deleteConnector(conn0_160581511);
+ conn0_160581511 = nullptr;
+ router0->deleteConnector(conn0_17788857);
+ conn0_17788857 = nullptr;
+ router0->deleteJunction(junction0_390996481);
+ junction0_390996481 = nullptr;
+ router0->deleteConnector(conn0_545568780);
+ conn0_545568780 = nullptr;
+ router0->deleteConnector(conn0_175131537);
+ conn0_175131537 = nullptr;
+ router0->deleteJunction(junction0_46074711);
+ junction0_46074711 = nullptr;
+ router0->deleteConnector(conn0_510680660);
+ conn0_510680660 = nullptr;
+ router0->deleteConnector(conn0_627671070);
+ conn0_627671070 = nullptr;
+ router0->deleteJunction(junction0_503331836);
+ junction0_503331836 = nullptr;
+ router0->deleteConnector(conn0_929108568);
+ conn0_929108568 = nullptr;
+ router0->deleteJunction(junction0_636368600);
+ junction0_636368600 = nullptr;
+ router0->deleteShape(shape0_214253640);
+ shape0_214253640 = nullptr;
+ router0->deleteShape(shape0_35177560);
+ shape0_35177560 = nullptr;
+ router0->deleteShape(shape0_355243155);
+ shape0_355243155 = nullptr;
+
+ router0->processTransaction();
+
+ delete router0;
+}
+
+extern "C" int main(void)
+{
+ test();
+ return 0;
+}
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/example.cpp b/src/3rdparty/adaptagrams/libavoid/tests/example.cpp
new file mode 100644
index 0000000..b4a24f7
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/example.cpp
@@ -0,0 +1,81 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ * Copyright (C) 2004-2007 Michael Wybrow <mjwybrow@users.sourceforge.net>
+ * Copyright (C) 2009 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow <mjwybrow@users.sourceforge.net>
+*/
+
+#include "libavoid/libavoid.h"
+
+
+
+static void connCallback(void *ptr)
+{
+ Avoid::ConnRef *connRef = (Avoid::ConnRef *) ptr;
+
+ printf("Connector %u needs rerouting!\n", connRef->id());
+
+ const Avoid::PolyLine& route = connRef->displayRoute();
+ printf("New path: ");
+ for (size_t i = 0; i < route.ps.size(); ++i)
+ {
+ printf("%s(%f, %f)", (i > 0) ? "-" : "",
+ route.ps[i].x, route.ps[i].y);
+ }
+ printf("\n");
+}
+
+
+int main(void)
+{
+ Avoid::Router *router = new Avoid::Router(Avoid::PolyLineRouting);
+
+ Avoid::Point srcPt(1.2, 0.5);
+ Avoid::Point dstPt(1.5, 4);
+ Avoid::ConnRef *connRef = new Avoid::ConnRef(router, srcPt, dstPt);
+ connRef->setCallback(connCallback, connRef);
+ // Force inital callback:
+ router->processTransaction();
+
+ printf("\nAdding a shape.\n");
+ // Create the ShapeRef:
+ Avoid::Polygon shapePoly(3);
+ shapePoly.ps[0] = Avoid::Point(1, 1);
+ shapePoly.ps[1] = Avoid::Point(2.5, 1.5);
+ shapePoly.ps[2] = Avoid::Point(1.5, 2.5);
+ Avoid::ShapeRef *shapeRef = new Avoid::ShapeRef(router, shapePoly);
+ router->processTransaction();
+
+ printf("\nShifting endpoint.\n");
+ Avoid::Point dstPt2(6, 4.5);
+ connRef->setDestEndpoint(dstPt2);
+ // It's expected you know the connector needs rerouting, so the callback
+ // isn't called. You can force it to be called though, via:
+ router->processTransaction();
+
+ printf("\nMoving shape right by 0.5.\n");
+ router->moveShape(shapeRef, 0.5, 0);
+ router->processTransaction();
+
+ router->outputDiagram("output/example");
+ delete router;
+ return 0;
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/finalSegmentNudging1.cpp b/src/3rdparty/adaptagrams/libavoid/tests/finalSegmentNudging1.cpp
new file mode 100644
index 0000000..0408e46
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/finalSegmentNudging1.cpp
@@ -0,0 +1,5227 @@
+// KEGG -> SBGN example #330
+//
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 0);
+ router->setRoutingPenalty((PenaltyType)5, 100);
+ router->setRoutingOption((RoutingOption)0, true);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, false);
+
+ /*
+ Polygon poly1(4);
+ poly1.ps[0] = Point(1337.46, 45);
+ poly1.ps[1] = Point(1337.46, 80);
+ poly1.ps[2] = Point(1028.46, 80);
+ poly1.ps[3] = Point(1028.46, 45);
+ new ShapeRef(router, poly1, 1);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(1793.79, 126.5);
+ poly2.ps[1] = Point(1793.79, 188.5);
+ poly2.ps[2] = Point(1731.79, 188.5);
+ poly2.ps[3] = Point(1731.79, 126.5);
+ new ShapeRef(router, poly2, 2);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(1416.86, 538.7);
+ poly3.ps[1] = Point(1416.86, 600.7);
+ poly3.ps[2] = Point(1354.86, 600.7);
+ poly3.ps[3] = Point(1354.86, 538.7);
+ new ShapeRef(router, poly3, 3);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(2072.79, 538.7);
+ poly4.ps[1] = Point(2072.79, 600.7);
+ poly4.ps[2] = Point(2010.79, 600.7);
+ poly4.ps[3] = Point(2010.79, 538.7);
+ new ShapeRef(router, poly4, 4);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(1594.6, 947.5);
+ poly5.ps[1] = Point(1594.6, 1009.5);
+ poly5.ps[2] = Point(1532.6, 1009.5);
+ poly5.ps[3] = Point(1532.6, 947.5);
+ new ShapeRef(router, poly5, 5);
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(641.333, 802.833);
+ poly6.ps[1] = Point(641.333, 864.833);
+ poly6.ps[2] = Point(579.333, 864.833);
+ poly6.ps[3] = Point(579.333, 802.833);
+ new ShapeRef(router, poly6, 6);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(421.333, 2368.05);
+ poly7.ps[1] = Point(421.333, 2430.05);
+ poly7.ps[2] = Point(359.333, 2430.05);
+ poly7.ps[3] = Point(359.333, 2368.05);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(1594.6, 2368.05);
+ poly8.ps[1] = Point(1594.6, 2430.05);
+ poly8.ps[2] = Point(1532.6, 2430.05);
+ poly8.ps[3] = Point(1532.6, 2368.05);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(1813.79, 1347.24);
+ poly9.ps[1] = Point(1813.79, 1409.24);
+ poly9.ps[2] = Point(1751.79, 1409.24);
+ poly9.ps[3] = Point(1751.79, 1347.24);
+ new ShapeRef(router, poly9, 9);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(1813.79, 1538.64);
+ poly10.ps[1] = Point(1813.79, 1600.64);
+ poly10.ps[2] = Point(1751.79, 1600.64);
+ poly10.ps[3] = Point(1751.79, 1538.64);
+ new ShapeRef(router, poly10, 10);
+
+ Polygon poly11(4);
+ poly11.ps[0] = Point(2072.79, 1538.64);
+ poly11.ps[1] = Point(2072.79, 1600.64);
+ poly11.ps[2] = Point(2010.79, 1600.64);
+ poly11.ps[3] = Point(2010.79, 1538.64);
+ new ShapeRef(router, poly11, 11);
+ */
+
+ Polygon poly12(4);
+ poly12.ps[0] = Point(2072.79, 1841.95);
+ poly12.ps[1] = Point(2072.79, 1903.95);
+ poly12.ps[2] = Point(2010.79, 1903.95);
+ poly12.ps[3] = Point(2010.79, 1841.95);
+ new ShapeRef(router, poly12, 12);
+
+ Polygon poly13(4);
+ poly13.ps[0] = Point(2272.79, 1841.95);
+ poly13.ps[1] = Point(2272.79, 1903.95);
+ poly13.ps[2] = Point(2210.79, 1903.95);
+ poly13.ps[3] = Point(2210.79, 1841.95);
+ new ShapeRef(router, poly13, 13);
+
+ /*
+ Polygon poly14(4);
+ poly14.ps[0] = Point(2578.71, 1841.95);
+ poly14.ps[1] = Point(2578.71, 1903.95);
+ poly14.ps[2] = Point(2516.71, 1903.95);
+ poly14.ps[3] = Point(2516.71, 1841.95);
+ new ShapeRef(router, poly14, 14);
+
+ Polygon poly15(4);
+ poly15.ps[0] = Point(2818.54, 1841.95);
+ poly15.ps[1] = Point(2818.54, 1903.95);
+ poly15.ps[2] = Point(2756.54, 1903.95);
+ poly15.ps[3] = Point(2756.54, 1841.95);
+ new ShapeRef(router, poly15, 15);
+
+ Polygon poly16(4);
+ poly16.ps[0] = Point(3150.9, 1841.95);
+ poly16.ps[1] = Point(3150.9, 1903.95);
+ poly16.ps[2] = Point(3088.9, 1903.95);
+ poly16.ps[3] = Point(3088.9, 1841.95);
+ new ShapeRef(router, poly16, 16);
+
+ Polygon poly17(4);
+ poly17.ps[0] = Point(1346.96, 281.5);
+ poly17.ps[1] = Point(1346.96, 343.5);
+ poly17.ps[2] = Point(1284.96, 343.5);
+ poly17.ps[3] = Point(1284.96, 281.5);
+ new ShapeRef(router, poly17, 17);
+
+ Polygon poly18(4);
+ poly18.ps[0] = Point(2072.79, 281.5);
+ poly18.ps[1] = Point(2072.79, 343.5);
+ poly18.ps[2] = Point(2010.79, 343.5);
+ poly18.ps[3] = Point(2010.79, 281.5);
+ new ShapeRef(router, poly18, 18);
+
+ Polygon poly19(4);
+ poly19.ps[0] = Point(3247.44, 2154.05);
+ poly19.ps[1] = Point(3247.44, 2216.05);
+ poly19.ps[2] = Point(3185.44, 2216.05);
+ poly19.ps[3] = Point(3185.44, 2154.05);
+ new ShapeRef(router, poly19, 19);
+
+ Polygon poly20(4);
+ poly20.ps[0] = Point(2578.71, 2154.05);
+ poly20.ps[1] = Point(2578.71, 2216.05);
+ poly20.ps[2] = Point(2516.71, 2216.05);
+ poly20.ps[3] = Point(2516.71, 2154.05);
+ new ShapeRef(router, poly20, 20);
+
+ Polygon poly21(4);
+ poly21.ps[0] = Point(1104.18, 2154.05);
+ poly21.ps[1] = Point(1104.18, 2216.05);
+ poly21.ps[2] = Point(1042.18, 2216.05);
+ poly21.ps[3] = Point(1042.18, 2154.05);
+ new ShapeRef(router, poly21, 21);
+
+ Polygon poly22(4);
+ poly22.ps[0] = Point(1104.18, 1409.24);
+ poly22.ps[1] = Point(1104.18, 1471.24);
+ poly22.ps[2] = Point(1042.18, 1471.24);
+ poly22.ps[3] = Point(1042.18, 1409.24);
+ new ShapeRef(router, poly22, 22);
+
+ Polygon poly23(4);
+ poly23.ps[0] = Point(354, 802.833);
+ poly23.ps[1] = Point(354, 864.833);
+ poly23.ps[2] = Point(292, 864.833);
+ poly23.ps[3] = Point(292, 802.833);
+ new ShapeRef(router, poly23, 23);
+
+ Polygon poly24(4);
+ poly24.ps[0] = Point(641.333, 1245.24);
+ poly24.ps[1] = Point(641.333, 1307.24);
+ poly24.ps[2] = Point(579.333, 1307.24);
+ poly24.ps[3] = Point(579.333, 1245.24);
+ new ShapeRef(router, poly24, 24);
+
+ Polygon poly25(4);
+ poly25.ps[0] = Point(907.358, 1245.24);
+ poly25.ps[1] = Point(907.358, 1307.24);
+ poly25.ps[2] = Point(845.358, 1307.24);
+ poly25.ps[3] = Point(845.358, 1245.24);
+ new ShapeRef(router, poly25, 25);
+
+ Polygon poly26(4);
+ poly26.ps[0] = Point(1104.18, 1245.24);
+ poly26.ps[1] = Point(1104.18, 1307.24);
+ poly26.ps[2] = Point(1042.18, 1307.24);
+ poly26.ps[3] = Point(1042.18, 1245.24);
+ new ShapeRef(router, poly26, 26);
+
+ Polygon poly27(4);
+ poly27.ps[0] = Point(1104.18, 947.5);
+ poly27.ps[1] = Point(1104.18, 1009.5);
+ poly27.ps[2] = Point(1042.18, 1009.5);
+ poly27.ps[3] = Point(1042.18, 947.5);
+ new ShapeRef(router, poly27, 27);
+
+ Polygon poly28(4);
+ poly28.ps[0] = Point(354, 344.5);
+ poly28.ps[1] = Point(354, 406.5);
+ poly28.ps[2] = Point(292, 406.5);
+ poly28.ps[3] = Point(292, 344.5);
+ new ShapeRef(router, poly28, 28);
+
+ Polygon poly29(4);
+ poly29.ps[0] = Point(2272.79, 809.75);
+ poly29.ps[1] = Point(2272.79, 871.75);
+ poly29.ps[2] = Point(2210.79, 871.75);
+ poly29.ps[3] = Point(2210.79, 809.75);
+ new ShapeRef(router, poly29, 29);
+
+ Polygon poly30(4);
+ poly30.ps[0] = Point(2578.71, 809.75);
+ poly30.ps[1] = Point(2578.71, 871.75);
+ poly30.ps[2] = Point(2516.71, 871.75);
+ poly30.ps[3] = Point(2516.71, 809.75);
+ new ShapeRef(router, poly30, 30);
+
+ Polygon poly31(4);
+ poly31.ps[0] = Point(2818.54, 809.75);
+ poly31.ps[1] = Point(2818.54, 871.75);
+ poly31.ps[2] = Point(2756.54, 871.75);
+ poly31.ps[3] = Point(2756.54, 809.75);
+ new ShapeRef(router, poly31, 31);
+
+ Polygon poly32(4);
+ poly32.ps[0] = Point(2999.99, 809.75);
+ poly32.ps[1] = Point(2999.99, 871.75);
+ poly32.ps[2] = Point(2937.99, 871.75);
+ poly32.ps[3] = Point(2937.99, 809.75);
+ new ShapeRef(router, poly32, 32);
+
+ Polygon poly33(4);
+ poly33.ps[0] = Point(2272.79, 189.875);
+ poly33.ps[1] = Point(2272.79, 251.875);
+ poly33.ps[2] = Point(2210.79, 251.875);
+ poly33.ps[3] = Point(2210.79, 189.875);
+ new ShapeRef(router, poly33, 33);
+
+ Polygon poly34(4);
+ poly34.ps[0] = Point(2578.71, 189.875);
+ poly34.ps[1] = Point(2578.71, 251.875);
+ poly34.ps[2] = Point(2516.71, 251.875);
+ poly34.ps[3] = Point(2516.71, 189.875);
+ new ShapeRef(router, poly34, 34);
+
+ Polygon poly35(4);
+ poly35.ps[0] = Point(2818.54, 189.875);
+ poly35.ps[1] = Point(2818.54, 251.875);
+ poly35.ps[2] = Point(2756.54, 251.875);
+ poly35.ps[3] = Point(2756.54, 189.875);
+ new ShapeRef(router, poly35, 35);
+
+ Polygon poly36(4);
+ poly36.ps[0] = Point(3145.24, 189.875);
+ poly36.ps[1] = Point(3145.24, 251.875);
+ poly36.ps[2] = Point(3083.24, 251.875);
+ poly36.ps[3] = Point(3083.24, 189.875);
+ new ShapeRef(router, poly36, 36);
+
+ Polygon poly37(4);
+ poly37.ps[0] = Point(2999.99, 1010.64);
+ poly37.ps[1] = Point(2999.99, 1072.64);
+ poly37.ps[2] = Point(2937.99, 1072.64);
+ poly37.ps[3] = Point(2937.99, 1010.64);
+ new ShapeRef(router, poly37, 37);
+
+ Polygon poly38(4);
+ poly38.ps[0] = Point(3145.24, 406.7);
+ poly38.ps[1] = Point(3145.24, 468.7);
+ poly38.ps[2] = Point(3083.24, 468.7);
+ poly38.ps[3] = Point(3083.24, 406.7);
+ new ShapeRef(router, poly38, 38);
+
+ Polygon poly39(4);
+ poly39.ps[0] = Point(2818.54, 406.7);
+ poly39.ps[1] = Point(2818.54, 468.7);
+ poly39.ps[2] = Point(2756.54, 468.7);
+ poly39.ps[3] = Point(2756.54, 406.7);
+ new ShapeRef(router, poly39, 39);
+
+ Polygon poly40(4);
+ poly40.ps[0] = Point(2578.71, 406.7);
+ poly40.ps[1] = Point(2578.71, 468.7);
+ poly40.ps[2] = Point(2516.71, 468.7);
+ poly40.ps[3] = Point(2516.71, 406.7);
+ new ShapeRef(router, poly40, 40);
+
+ Polygon poly41(4);
+ poly41.ps[0] = Point(1989.29, 1010.64);
+ poly41.ps[1] = Point(1989.29, 1072.64);
+ poly41.ps[2] = Point(1927.29, 1072.64);
+ poly41.ps[3] = Point(1927.29, 1010.64);
+ new ShapeRef(router, poly41, 41);
+
+ Polygon poly42(4);
+ poly42.ps[0] = Point(2272.79, 1010.64);
+ poly42.ps[1] = Point(2272.79, 1072.64);
+ poly42.ps[2] = Point(2210.79, 1072.64);
+ poly42.ps[3] = Point(2210.79, 1010.64);
+ new ShapeRef(router, poly42, 42);
+
+ Polygon poly43(4);
+ poly43.ps[0] = Point(2578.71, 1010.64);
+ poly43.ps[1] = Point(2578.71, 1072.64);
+ poly43.ps[2] = Point(2516.71, 1072.64);
+ poly43.ps[3] = Point(2516.71, 1010.64);
+ new ShapeRef(router, poly43, 43);
+
+ Polygon poly44(4);
+ poly44.ps[0] = Point(2272.79, 1538.64);
+ poly44.ps[1] = Point(2272.79, 1600.64);
+ poly44.ps[2] = Point(2210.79, 1600.64);
+ poly44.ps[3] = Point(2210.79, 1538.64);
+ new ShapeRef(router, poly44, 44);
+
+ Polygon poly45(4);
+ poly45.ps[0] = Point(2578.71, 1538.64);
+ poly45.ps[1] = Point(2578.71, 1600.64);
+ poly45.ps[2] = Point(2516.71, 1600.64);
+ poly45.ps[3] = Point(2516.71, 1538.64);
+ new ShapeRef(router, poly45, 45);
+
+ Polygon poly46(4);
+ poly46.ps[0] = Point(2272.79, 1347.24);
+ poly46.ps[1] = Point(2272.79, 1409.24);
+ poly46.ps[2] = Point(2210.79, 1409.24);
+ poly46.ps[3] = Point(2210.79, 1347.24);
+ new ShapeRef(router, poly46, 46);
+
+ Polygon poly47(4);
+ poly47.ps[0] = Point(2072.79, 1992.95);
+ poly47.ps[1] = Point(2072.79, 2054.95);
+ poly47.ps[2] = Point(2010.79, 2054.95);
+ poly47.ps[3] = Point(2010.79, 1992.95);
+ new ShapeRef(router, poly47, 47);
+
+ Polygon poly48(4);
+ poly48.ps[0] = Point(2272.79, 1992.95);
+ poly48.ps[1] = Point(2272.79, 2054.95);
+ poly48.ps[2] = Point(2210.79, 2054.95);
+ poly48.ps[3] = Point(2210.79, 1992.95);
+ new ShapeRef(router, poly48, 48);
+
+ Polygon poly49(4);
+ poly49.ps[0] = Point(2999.99, 1700.64);
+ poly49.ps[1] = Point(2999.99, 1762.64);
+ poly49.ps[2] = Point(2937.99, 1762.64);
+ poly49.ps[3] = Point(2937.99, 1700.64);
+ new ShapeRef(router, poly49, 49);
+
+ Polygon poly50(4);
+ poly50.ps[0] = Point(2766.54, 331.5);
+ poly50.ps[1] = Point(2766.54, 393.5);
+ poly50.ps[2] = Point(2704.54, 393.5);
+ poly50.ps[3] = Point(2704.54, 331.5);
+ new ShapeRef(router, poly50, 50);
+
+ Polygon poly51(4);
+ poly51.ps[0] = Point(1594.6, 2914.3);
+ poly51.ps[1] = Point(1594.6, 2976.3);
+ poly51.ps[2] = Point(1532.6, 2976.3);
+ poly51.ps[3] = Point(1532.6, 2914.3);
+ new ShapeRef(router, poly51, 51);
+
+ Polygon poly52(4);
+ poly52.ps[0] = Point(1594.6, 3382.3);
+ poly52.ps[1] = Point(1594.6, 3444.3);
+ poly52.ps[2] = Point(1532.6, 3444.3);
+ poly52.ps[3] = Point(1532.6, 3382.3);
+ new ShapeRef(router, poly52, 52);
+
+ Polygon poly53(4);
+ poly53.ps[0] = Point(641.333, 2498.3);
+ poly53.ps[1] = Point(641.333, 2560.3);
+ poly53.ps[2] = Point(579.333, 2560.3);
+ poly53.ps[3] = Point(579.333, 2498.3);
+ new ShapeRef(router, poly53, 53);
+
+ Polygon poly54(4);
+ poly54.ps[0] = Point(641.333, 2643.3);
+ poly54.ps[1] = Point(641.333, 2705.3);
+ poly54.ps[2] = Point(579.333, 2705.3);
+ poly54.ps[3] = Point(579.333, 2643.3);
+ new ShapeRef(router, poly54, 54);
+
+ Polygon poly55(4);
+ poly55.ps[0] = Point(641.333, 2914.3);
+ poly55.ps[1] = Point(641.333, 2976.3);
+ poly55.ps[2] = Point(579.333, 2976.3);
+ poly55.ps[3] = Point(579.333, 2914.3);
+ new ShapeRef(router, poly55, 55);
+
+ Polygon poly56(4);
+ poly56.ps[0] = Point(2272.79, 2914.3);
+ poly56.ps[1] = Point(2272.79, 2976.3);
+ poly56.ps[2] = Point(2210.79, 2976.3);
+ poly56.ps[3] = Point(2210.79, 2914.3);
+ new ShapeRef(router, poly56, 56);
+
+ Polygon poly57(4);
+ poly57.ps[0] = Point(2353.71, 2643.3);
+ poly57.ps[1] = Point(2353.71, 2705.3);
+ poly57.ps[2] = Point(2291.71, 2705.3);
+ poly57.ps[3] = Point(2291.71, 2643.3);
+ new ShapeRef(router, poly57, 57);
+
+ Polygon poly58(4);
+ poly58.ps[0] = Point(2578.71, 2914.3);
+ poly58.ps[1] = Point(2578.71, 2976.3);
+ poly58.ps[2] = Point(2516.71, 2976.3);
+ poly58.ps[3] = Point(2516.71, 2914.3);
+ new ShapeRef(router, poly58, 58);
+
+ Polygon poly59(4);
+ poly59.ps[0] = Point(2353.71, 2498.3);
+ poly59.ps[1] = Point(2353.71, 2560.3);
+ poly59.ps[2] = Point(2291.71, 2560.3);
+ poly59.ps[3] = Point(2291.71, 2498.3);
+ new ShapeRef(router, poly59, 59);
+
+ Polygon poly60(4);
+ poly60.ps[0] = Point(907.358, 2498.3);
+ poly60.ps[1] = Point(907.358, 2560.3);
+ poly60.ps[2] = Point(845.358, 2560.3);
+ poly60.ps[3] = Point(845.358, 2498.3);
+ new ShapeRef(router, poly60, 60);
+
+ Polygon poly61(4);
+ poly61.ps[0] = Point(907.358, 2643.3);
+ poly61.ps[1] = Point(907.358, 2705.3);
+ poly61.ps[2] = Point(845.358, 2705.3);
+ poly61.ps[3] = Point(845.358, 2643.3);
+ new ShapeRef(router, poly61, 61);
+
+ Polygon poly62(4);
+ poly62.ps[0] = Point(907.358, 2914.3);
+ poly62.ps[1] = Point(907.358, 2976.3);
+ poly62.ps[2] = Point(845.358, 2976.3);
+ poly62.ps[3] = Point(845.358, 2914.3);
+ new ShapeRef(router, poly62, 62);
+
+ Polygon poly63(4);
+ poly63.ps[0] = Point(3353.24, 2368.05);
+ poly63.ps[1] = Point(3353.24, 2430.05);
+ poly63.ps[2] = Point(3291.24, 2430.05);
+ poly63.ps[3] = Point(3291.24, 2368.05);
+ new ShapeRef(router, poly63, 63);
+
+ Polygon poly64(4);
+ poly64.ps[0] = Point(2999.99, 2266.05);
+ poly64.ps[1] = Point(2999.99, 2328.05);
+ poly64.ps[2] = Point(2937.99, 2328.05);
+ poly64.ps[3] = Point(2937.99, 2266.05);
+ new ShapeRef(router, poly64, 64);
+
+ Polygon poly65(4);
+ poly65.ps[0] = Point(3509.07, 1347.24);
+ poly65.ps[1] = Point(3509.07, 1409.24);
+ poly65.ps[2] = Point(3447.07, 1409.24);
+ poly65.ps[3] = Point(3447.07, 1347.24);
+ new ShapeRef(router, poly65, 65);
+
+ Polygon poly66(4);
+ poly66.ps[0] = Point(3509.07, 3382.3);
+ poly66.ps[1] = Point(3509.07, 3444.3);
+ poly66.ps[2] = Point(3447.07, 3444.3);
+ poly66.ps[3] = Point(3447.07, 3382.3);
+ new ShapeRef(router, poly66, 66);
+
+ Polygon poly67(4);
+ poly67.ps[0] = Point(230, 496.5);
+ poly67.ps[1] = Point(230, 528.5);
+ poly67.ps[2] = Point(210, 528.5);
+ poly67.ps[3] = Point(210, 496.5);
+ new ShapeRef(router, poly67, 67);
+
+ Polygon poly68(4);
+ poly68.ps[0] = Point(141, 632.5);
+ poly68.ps[1] = Point(141, 664.5);
+ poly68.ps[2] = Point(121, 664.5);
+ poly68.ps[3] = Point(121, 632.5);
+ new ShapeRef(router, poly68, 68);
+
+ Polygon poly69(4);
+ poly69.ps[0] = Point(556.333, 698.5);
+ poly69.ps[1] = Point(556.333, 718.5);
+ poly69.ps[2] = Point(524.333, 718.5);
+ poly69.ps[3] = Point(524.333, 698.5);
+ new ShapeRef(router, poly69, 69);
+
+ Polygon poly70(4);
+ poly70.ps[0] = Point(556.333, 823.833);
+ poly70.ps[1] = Point(556.333, 843.833);
+ poly70.ps[2] = Point(524.333, 843.833);
+ poly70.ps[3] = Point(524.333, 823.833);
+ new ShapeRef(router, poly70, 70);
+
+ Polygon poly71(4);
+ poly71.ps[0] = Point(1405.46, 692.5);
+ poly71.ps[1] = Point(1405.46, 724.5);
+ poly71.ps[2] = Point(1385.46, 724.5);
+ poly71.ps[3] = Point(1385.46, 692.5);
+ new ShapeRef(router, poly71, 71);
+
+ Polygon poly72(4);
+ poly72.ps[0] = Point(1558.46, 281.5);
+ poly72.ps[1] = Point(1558.46, 301.5);
+ poly72.ps[2] = Point(1526.46, 301.5);
+ poly72.ps[3] = Point(1526.46, 281.5);
+ new ShapeRef(router, poly72, 72);
+
+ Polygon poly73(4);
+ poly73.ps[0] = Point(1492.46, 57.5);
+ poly73.ps[1] = Point(1492.46, 231.5);
+ poly73.ps[2] = Point(1359.46, 231.5);
+ poly73.ps[3] = Point(1359.46, 57.5);
+ new ShapeRef(router, poly73, 73);
+
+ Polygon poly74(4);
+ poly74.ps[0] = Point(1958.29, 281.5);
+ poly74.ps[1] = Point(1958.29, 301.5);
+ poly74.ps[2] = Point(1926.29, 301.5);
+ poly74.ps[3] = Point(1926.29, 281.5);
+ new ShapeRef(router, poly74, 74);
+
+ Polygon poly75(4);
+ poly75.ps[0] = Point(2042.79, 767.5);
+ poly75.ps[1] = Point(2042.79, 787.5);
+ poly75.ps[2] = Point(2010.79, 787.5);
+ poly75.ps[3] = Point(2010.79, 767.5);
+ new ShapeRef(router, poly75, 75);
+
+ Polygon poly76(4);
+ poly76.ps[0] = Point(556.333, 1266.24);
+ poly76.ps[1] = Point(556.333, 1286.24);
+ poly76.ps[2] = Point(524.333, 1286.24);
+ poly76.ps[3] = Point(524.333, 1266.24);
+ new ShapeRef(router, poly76, 76);
+
+ Polygon poly77(4);
+ poly77.ps[0] = Point(727.958, 1266.24);
+ poly77.ps[1] = Point(727.958, 1286.24);
+ poly77.ps[2] = Point(695.958, 1286.24);
+ poly77.ps[3] = Point(695.958, 1266.24);
+ new ShapeRef(router, poly77, 77);
+
+ Polygon poly78(4);
+ poly78.ps[0] = Point(988.958, 1266.24);
+ poly78.ps[1] = Point(988.958, 1286.24);
+ poly78.ps[2] = Point(956.958, 1286.24);
+ poly78.ps[3] = Point(956.958, 1266.24);
+ new ShapeRef(router, poly78, 78);
+
+ Polygon poly79(4);
+ poly79.ps[0] = Point(1060.96, 1127.64);
+ poly79.ps[1] = Point(1060.96, 1159.64);
+ poly79.ps[2] = Point(1040.96, 1159.64);
+ poly79.ps[3] = Point(1040.96, 1127.64);
+ new ShapeRef(router, poly79, 79);
+
+ Polygon poly80(4);
+ poly80.ps[0] = Point(1401.86, 959.5);
+ poly80.ps[1] = Point(1401.86, 979.5);
+ poly80.ps[2] = Point(1369.86, 979.5);
+ poly80.ps[3] = Point(1369.86, 959.5);
+ new ShapeRef(router, poly80, 80);
+
+ Polygon poly81(4);
+ poly81.ps[0] = Point(1401.86, 1031.64);
+ poly81.ps[1] = Point(1401.86, 1051.64);
+ poly81.ps[2] = Point(1369.86, 1051.64);
+ poly81.ps[3] = Point(1369.86, 1031.64);
+ new ShapeRef(router, poly81, 81);
+
+ Polygon poly82(4);
+ poly82.ps[0] = Point(1401.86, 1133.64);
+ poly82.ps[1] = Point(1401.86, 1153.64);
+ poly82.ps[2] = Point(1369.86, 1153.64);
+ poly82.ps[3] = Point(1369.86, 1133.64);
+ new ShapeRef(router, poly82, 82);
+
+ Polygon poly83(4);
+ poly83.ps[0] = Point(1656.79, 1260.24);
+ poly83.ps[1] = Point(1656.79, 1292.24);
+ poly83.ps[2] = Point(1636.79, 1292.24);
+ poly83.ps[3] = Point(1636.79, 1260.24);
+ new ShapeRef(router, poly83, 83);
+
+ Polygon poly84(4);
+ poly84.ps[0] = Point(1967.87, 1581.64);
+ poly84.ps[1] = Point(1967.87, 1621.64);
+ poly84.ps[2] = Point(1891.87, 1621.64);
+ poly84.ps[3] = Point(1891.87, 1581.64);
+ new ShapeRef(router, poly84, 84);
+
+ Polygon poly85(4);
+ poly85.ps[0] = Point(1942.79, 1643.64);
+ poly85.ps[1] = Point(1942.79, 1663.64);
+ poly85.ps[2] = Point(1910.79, 1663.64);
+ poly85.ps[3] = Point(1910.79, 1643.64);
+ new ShapeRef(router, poly85, 85);
+
+ Polygon poly86(4);
+ poly86.ps[0] = Point(1973.29, 1347.24);
+ poly86.ps[1] = Point(1973.29, 1409.24);
+ poly86.ps[2] = Point(1911.29, 1409.24);
+ poly86.ps[3] = Point(1911.29, 1347.24);
+ new ShapeRef(router, poly86, 86);
+
+ Polygon poly87(4);
+ poly87.ps[0] = Point(1968.29, 1424.24);
+ poly87.ps[1] = Point(1968.29, 1456.24);
+ poly87.ps[2] = Point(1948.29, 1456.24);
+ poly87.ps[3] = Point(1948.29, 1424.24);
+ new ShapeRef(router, poly87, 87);
+
+ Polygon poly88(4);
+ poly88.ps[0] = Point(2004.87, 1914.95);
+ poly88.ps[1] = Point(2004.87, 1954.95);
+ poly88.ps[2] = Point(1948.87, 1954.95);
+ poly88.ps[3] = Point(1948.87, 1914.95);
+ new ShapeRef(router, poly88, 88);
+
+ Polygon poly89(4);
+ poly89.ps[0] = Point(2051.79, 1706.64);
+ poly89.ps[1] = Point(2051.79, 1738.64);
+ poly89.ps[2] = Point(2031.79, 1738.64);
+ poly89.ps[3] = Point(2031.79, 1706.64);
+ new ShapeRef(router, poly89, 89);
+
+ Polygon poly90(4);
+ poly90.ps[0] = Point(2187.79, 1559.64);
+ poly90.ps[1] = Point(2187.79, 1579.64);
+ poly90.ps[2] = Point(2155.79, 1579.64);
+ poly90.ps[3] = Point(2155.79, 1559.64);
+ new ShapeRef(router, poly90, 90);
+
+ Polygon poly91(4);
+ poly91.ps[0] = Point(2056.87, 1487.64);
+ poly91.ps[1] = Point(2056.87, 1527.64);
+ poly91.ps[2] = Point(2000.87, 1527.64);
+ poly91.ps[3] = Point(2000.87, 1487.64);
+ new ShapeRef(router, poly91, 91);
+
+ Polygon poly92(4);
+ poly92.ps[0] = Point(2251.79, 1424.24);
+ poly92.ps[1] = Point(2251.79, 1456.24);
+ poly92.ps[2] = Point(2231.79, 1456.24);
+ poly92.ps[3] = Point(2231.79, 1424.24);
+ new ShapeRef(router, poly92, 92);
+
+ Polygon poly93(4);
+ poly93.ps[0] = Point(2578.71, 1347.24);
+ poly93.ps[1] = Point(2578.71, 1409.24);
+ poly93.ps[2] = Point(2516.71, 1409.24);
+ poly93.ps[3] = Point(2516.71, 1347.24);
+ new ShapeRef(router, poly93, 93);
+
+ Polygon poly94(4);
+ poly94.ps[0] = Point(2493.71, 1499.44);
+ poly94.ps[1] = Point(2493.71, 1519.44);
+ poly94.ps[2] = Point(2461.71, 1519.44);
+ poly94.ps[3] = Point(2461.71, 1499.44);
+ new ShapeRef(router, poly94, 94);
+
+ Polygon poly95(4);
+ poly95.ps[0] = Point(2493.71, 1571.64);
+ poly95.ps[1] = Point(2493.71, 1591.64);
+ poly95.ps[2] = Point(2461.71, 1591.64);
+ poly95.ps[3] = Point(2461.71, 1571.64);
+ new ShapeRef(router, poly95, 95);
+ */
+
+ Polygon poly96(4);
+ poly96.ps[0] = Point(2187.79, 1862.95);
+ poly96.ps[1] = Point(2187.79, 1882.95);
+ poly96.ps[2] = Point(2155.79, 1882.95);
+ poly96.ps[3] = Point(2155.79, 1862.95);
+ new ShapeRef(router, poly96, 96);
+
+ Polygon poly97(4);
+ poly97.ps[0] = Point(2139.79, 1864.95);
+ poly97.ps[1] = Point(2139.79, 1904.95);
+ poly97.ps[2] = Point(2063.79, 1904.95);
+ poly97.ps[3] = Point(2063.79, 1864.95);
+ new ShapeRef(router, poly97, 97);
+
+ /*
+ Polygon poly98(4);
+ poly98.ps[0] = Point(2237.79, 1713.77);
+ poly98.ps[1] = Point(2237.79, 1753.77);
+ poly98.ps[2] = Point(2161.79, 1753.77);
+ poly98.ps[3] = Point(2161.79, 1713.77);
+ new ShapeRef(router, poly98, 98);
+
+ Polygon poly99(4);
+ poly99.ps[0] = Point(2493.71, 2003.95);
+ poly99.ps[1] = Point(2493.71, 2023.95);
+ poly99.ps[2] = Point(2461.71, 2023.95);
+ poly99.ps[3] = Point(2461.71, 2003.95);
+ new ShapeRef(router, poly99, 99);
+
+ Polygon poly100(4);
+ poly100.ps[0] = Point(2493.71, 2045.95);
+ poly100.ps[1] = Point(2493.71, 2065.95);
+ poly100.ps[2] = Point(2461.71, 2065.95);
+ poly100.ps[3] = Point(2461.71, 2045.95);
+ new ShapeRef(router, poly100, 100);
+
+ Polygon poly101(4);
+ poly101.ps[0] = Point(2676.54, 1802.64);
+ poly101.ps[1] = Point(2676.54, 1822.64);
+ poly101.ps[2] = Point(2644.54, 1822.64);
+ poly101.ps[3] = Point(2644.54, 1802.64);
+ new ShapeRef(router, poly101, 101);
+
+ Polygon poly102(4);
+ poly102.ps[0] = Point(2653.54, 1874.95);
+ poly102.ps[1] = Point(2653.54, 1894.95);
+ poly102.ps[2] = Point(2621.54, 1894.95);
+ poly102.ps[3] = Point(2621.54, 1874.95);
+ new ShapeRef(router, poly102, 102);
+
+ Polygon poly103(4);
+ poly103.ps[0] = Point(2751.54, 1874.95);
+ poly103.ps[1] = Point(2751.54, 1894.95);
+ poly103.ps[2] = Point(2719.54, 1894.95);
+ poly103.ps[3] = Point(2719.54, 1874.95);
+ new ShapeRef(router, poly103, 103);
+
+ Polygon poly104(4);
+ poly104.ps[0] = Point(2914.99, 1802.64);
+ poly104.ps[1] = Point(2914.99, 1822.64);
+ poly104.ps[2] = Point(2882.99, 1822.64);
+ poly104.ps[3] = Point(2882.99, 1802.64);
+ new ShapeRef(router, poly104, 104);
+
+ Polygon poly105(4);
+ poly105.ps[0] = Point(2891.99, 1874.95);
+ poly105.ps[1] = Point(2891.99, 1894.95);
+ poly105.ps[2] = Point(2859.99, 1894.95);
+ poly105.ps[3] = Point(2859.99, 1874.95);
+ new ShapeRef(router, poly105, 105);
+
+ Polygon poly106(4);
+ poly106.ps[0] = Point(2969.99, 1874.95);
+ poly106.ps[1] = Point(2969.99, 1894.95);
+ poly106.ps[2] = Point(2937.99, 1894.95);
+ poly106.ps[3] = Point(2937.99, 1874.95);
+ new ShapeRef(router, poly106, 106);
+
+ Polygon poly107(4);
+ poly107.ps[0] = Point(2251.79, 692.5);
+ poly107.ps[1] = Point(2251.79, 724.5);
+ poly107.ps[2] = Point(2231.79, 724.5);
+ poly107.ps[3] = Point(2231.79, 692.5);
+ new ShapeRef(router, poly107, 107);
+
+ Polygon poly108(4);
+ poly108.ps[0] = Point(2557.71, 692.5);
+ poly108.ps[1] = Point(2557.71, 724.5);
+ poly108.ps[2] = Point(2537.71, 724.5);
+ poly108.ps[3] = Point(2537.71, 692.5);
+ new ShapeRef(router, poly108, 108);
+
+ Polygon poly109(4);
+ poly109.ps[0] = Point(2797.54, 692.5);
+ poly109.ps[1] = Point(2797.54, 724.5);
+ poly109.ps[2] = Point(2777.54, 724.5);
+ poly109.ps[3] = Point(2777.54, 692.5);
+ new ShapeRef(router, poly109, 109);
+
+ Polygon poly110(4);
+ poly110.ps[0] = Point(2978.99, 692.5);
+ poly110.ps[1] = Point(2978.99, 724.5);
+ poly110.ps[2] = Point(2958.99, 724.5);
+ poly110.ps[3] = Point(2958.99, 692.5);
+ new ShapeRef(router, poly110, 110);
+
+ Polygon poly111(4);
+ poly111.ps[0] = Point(2978.99, 898.5);
+ poly111.ps[1] = Point(2978.99, 930.5);
+ poly111.ps[2] = Point(2958.99, 930.5);
+ poly111.ps[3] = Point(2958.99, 898.5);
+ new ShapeRef(router, poly111, 111);
+
+ Polygon poly112(4);
+ poly112.ps[0] = Point(2251.79, 285.75);
+ poly112.ps[1] = Point(2251.79, 317.75);
+ poly112.ps[2] = Point(2231.79, 317.75);
+ poly112.ps[3] = Point(2231.79, 285.75);
+ new ShapeRef(router, poly112, 112);
+
+ Polygon poly113(4);
+ poly113.ps[0] = Point(2493.71, 210.875);
+ poly113.ps[1] = Point(2493.71, 230.875);
+ poly113.ps[2] = Point(2461.71, 230.875);
+ poly113.ps[3] = Point(2461.71, 210.875);
+ new ShapeRef(router, poly113, 113);
+
+ Polygon poly114(4);
+ poly114.ps[0] = Point(2557.71, 285.75);
+ poly114.ps[1] = Point(2557.71, 317.75);
+ poly114.ps[2] = Point(2537.71, 317.75);
+ poly114.ps[3] = Point(2537.71, 285.75);
+ new ShapeRef(router, poly114, 114);
+
+ Polygon poly115(4);
+ poly115.ps[0] = Point(2681.54, 210.875);
+ poly115.ps[1] = Point(2681.54, 230.875);
+ poly115.ps[2] = Point(2649.54, 230.875);
+ poly115.ps[3] = Point(2649.54, 210.875);
+ new ShapeRef(router, poly115, 115);
+
+ Polygon poly116(4);
+ poly116.ps[0] = Point(2681.54, 427.7);
+ poly116.ps[1] = Point(2681.54, 447.7);
+ poly116.ps[2] = Point(2649.54, 447.7);
+ poly116.ps[3] = Point(2649.54, 427.7);
+ new ShapeRef(router, poly116, 116);
+
+ Polygon poly117(4);
+ poly117.ps[0] = Point(2935.99, 427.7);
+ poly117.ps[1] = Point(2935.99, 447.7);
+ poly117.ps[2] = Point(2903.99, 447.7);
+ poly117.ps[3] = Point(2903.99, 427.7);
+ new ShapeRef(router, poly117, 117);
+
+ Polygon poly118(4);
+ poly118.ps[0] = Point(3149.24, 285.75);
+ poly118.ps[1] = Point(3149.24, 317.75);
+ poly118.ps[2] = Point(3129.24, 317.75);
+ poly118.ps[3] = Point(3129.24, 285.75);
+ new ShapeRef(router, poly118, 118);
+
+ Polygon poly119(4);
+ poly119.ps[0] = Point(3494.07, 904.5);
+ poly119.ps[1] = Point(3494.07, 924.5);
+ poly119.ps[2] = Point(3462.07, 924.5);
+ poly119.ps[3] = Point(3462.07, 904.5);
+ new ShapeRef(router, poly119, 119);
+
+ Polygon poly120(4);
+ poly120.ps[0] = Point(3488.07, 1856.95);
+ poly120.ps[1] = Point(3488.07, 1888.95);
+ poly120.ps[2] = Point(3468.07, 1888.95);
+ poly120.ps[3] = Point(3468.07, 1856.95);
+ new ShapeRef(router, poly120, 120);
+
+ Polygon poly121(4);
+ poly121.ps[0] = Point(3488.07, 2596.3);
+ poly121.ps[1] = Point(3488.07, 2628.3);
+ poly121.ps[2] = Point(3468.07, 2628.3);
+ poly121.ps[3] = Point(3468.07, 2596.3);
+ new ShapeRef(router, poly121, 121);
+
+ Polygon poly122(4);
+ poly122.ps[0] = Point(2803.54, 3407.3);
+ poly122.ps[1] = Point(2803.54, 3427.3);
+ poly122.ps[2] = Point(2771.54, 3427.3);
+ poly122.ps[3] = Point(2771.54, 3407.3);
+ new ShapeRef(router, poly122, 122);
+
+ Polygon poly123(4);
+ poly123.ps[0] = Point(2803.54, 3509.3);
+ poly123.ps[1] = Point(2803.54, 3529.3);
+ poly123.ps[2] = Point(2771.54, 3529.3);
+ poly123.ps[3] = Point(2771.54, 3509.3);
+ new ShapeRef(router, poly123, 123);
+
+ Polygon poly124(4);
+ poly124.ps[0] = Point(3606.07, 2596.3);
+ poly124.ps[1] = Point(3606.07, 2628.3);
+ poly124.ps[2] = Point(3586.07, 2628.3);
+ poly124.ps[3] = Point(3586.07, 2596.3);
+ new ShapeRef(router, poly124, 124);
+
+ Polygon poly125(4);
+ poly125.ps[0] = Point(3606.07, 898.5);
+ poly125.ps[1] = Point(3606.07, 930.5);
+ poly125.ps[2] = Point(3586.07, 930.5);
+ poly125.ps[3] = Point(3586.07, 898.5);
+ new ShapeRef(router, poly125, 125);
+
+ Polygon poly126(4);
+ poly126.ps[0] = Point(3336.74, 898.5);
+ poly126.ps[1] = Point(3336.74, 930.5);
+ poly126.ps[2] = Point(3316.74, 930.5);
+ poly126.ps[3] = Point(3316.74, 898.5);
+ new ShapeRef(router, poly126, 126);
+
+ Polygon poly127(4);
+ poly127.ps[0] = Point(3232.44, 2389.05);
+ poly127.ps[1] = Point(3232.44, 2409.05);
+ poly127.ps[2] = Point(3200.44, 2409.05);
+ poly127.ps[3] = Point(3200.44, 2389.05);
+ new ShapeRef(router, poly127, 127);
+
+ Polygon poly128(4);
+ poly128.ps[0] = Point(3232.44, 2287.05);
+ poly128.ps[1] = Point(3232.44, 2307.05);
+ poly128.ps[2] = Point(3200.44, 2307.05);
+ poly128.ps[3] = Point(3200.44, 2287.05);
+ new ShapeRef(router, poly128, 128);
+
+ Polygon poly129(4);
+ poly129.ps[0] = Point(2803.54, 2287.05);
+ poly129.ps[1] = Point(2803.54, 2307.05);
+ poly129.ps[2] = Point(2771.54, 2307.05);
+ poly129.ps[3] = Point(2771.54, 2287.05);
+ new ShapeRef(router, poly129, 129);
+
+ Polygon poly130(4);
+ poly130.ps[0] = Point(3232.44, 904.5);
+ poly130.ps[1] = Point(3232.44, 924.5);
+ poly130.ps[2] = Point(3200.44, 924.5);
+ poly130.ps[3] = Point(3200.44, 904.5);
+ new ShapeRef(router, poly130, 130);
+
+ Polygon poly131(4);
+ poly131.ps[0] = Point(2803.54, 2175.05);
+ poly131.ps[1] = Point(2803.54, 2195.05);
+ poly131.ps[2] = Point(2771.54, 2195.05);
+ poly131.ps[3] = Point(2771.54, 2175.05);
+ new ShapeRef(router, poly131, 131);
+
+ Polygon poly132(4);
+ poly132.ps[0] = Point(2415.71, 2175.05);
+ poly132.ps[1] = Point(2415.71, 2195.05);
+ poly132.ps[2] = Point(2383.71, 2195.05);
+ poly132.ps[3] = Point(2383.71, 2175.05);
+ new ShapeRef(router, poly132, 132);
+
+ Polygon poly133(4);
+ poly133.ps[0] = Point(1942.79, 2175.05);
+ poly133.ps[1] = Point(1942.79, 2195.05);
+ poly133.ps[2] = Point(1910.79, 2195.05);
+ poly133.ps[3] = Point(1910.79, 2175.05);
+ new ShapeRef(router, poly133, 133);
+
+ Polygon poly134(4);
+ poly134.ps[0] = Point(727.958, 2175.05);
+ poly134.ps[1] = Point(727.958, 2195.05);
+ poly134.ps[2] = Point(695.958, 2195.05);
+ poly134.ps[3] = Point(695.958, 2175.05);
+ new ShapeRef(router, poly134, 134);
+
+ Polygon poly135(4);
+ poly135.ps[0] = Point(1573.6, 2007.95);
+ poly135.ps[1] = Point(1573.6, 2039.95);
+ poly135.ps[2] = Point(1553.6, 2039.95);
+ poly135.ps[3] = Point(1553.6, 2007.95);
+ new ShapeRef(router, poly135, 135);
+
+ Polygon poly136(4);
+ poly136.ps[0] = Point(727.958, 1368.24);
+ poly136.ps[1] = Point(727.958, 1388.24);
+ poly136.ps[2] = Point(695.958, 1388.24);
+ poly136.ps[3] = Point(695.958, 1368.24);
+ new ShapeRef(router, poly136, 136);
+
+ Polygon poly137(4);
+ poly137.ps[0] = Point(721.958, 1424.24);
+ poly137.ps[1] = Point(721.958, 1456.24);
+ poly137.ps[2] = Point(701.958, 1456.24);
+ poly137.ps[3] = Point(701.958, 1424.24);
+ new ShapeRef(router, poly137, 137);
+
+ Polygon poly138(4);
+ poly138.ps[0] = Point(1395.86, 1424.24);
+ poly138.ps[1] = Point(1395.86, 1456.24);
+ poly138.ps[2] = Point(1375.86, 1456.24);
+ poly138.ps[3] = Point(1375.86, 1424.24);
+ new ShapeRef(router, poly138, 138);
+
+ Polygon poly139(4);
+ poly139.ps[0] = Point(626.333, 2467.3);
+ poly139.ps[1] = Point(626.333, 2487.3);
+ poly139.ps[2] = Point(594.333, 2487.3);
+ poly139.ps[3] = Point(594.333, 2467.3);
+ new ShapeRef(router, poly139, 139);
+
+ Polygon poly140(4);
+ poly140.ps[0] = Point(620.333, 2596.3);
+ poly140.ps[1] = Point(620.333, 2628.3);
+ poly140.ps[2] = Point(600.333, 2628.3);
+ poly140.ps[3] = Point(600.333, 2596.3);
+ new ShapeRef(router, poly140, 140);
+
+ Polygon poly141(4);
+ poly141.ps[0] = Point(1508.87, 2033.77);
+ poly141.ps[1] = Point(1508.87, 2073.77);
+ poly141.ps[2] = Point(1452.87, 2073.77);
+ poly141.ps[3] = Point(1452.87, 2033.77);
+ new ShapeRef(router, poly141, 141);
+
+ Polygon poly142(4);
+ poly142.ps[0] = Point(626.333, 3061.3);
+ poly142.ps[1] = Point(626.333, 3081.3);
+ poly142.ps[2] = Point(594.333, 3081.3);
+ poly142.ps[3] = Point(594.333, 3061.3);
+ new ShapeRef(router, poly142, 142);
+
+ Polygon poly143(4);
+ poly143.ps[0] = Point(1207.96, 2596.3);
+ poly143.ps[1] = Point(1207.96, 2628.3);
+ poly143.ps[2] = Point(1187.96, 2628.3);
+ poly143.ps[3] = Point(1187.96, 2596.3);
+ new ShapeRef(router, poly143, 143);
+
+ Polygon poly144(4);
+ poly144.ps[0] = Point(1325.96, 2596.3);
+ poly144.ps[1] = Point(1325.96, 2628.3);
+ poly144.ps[2] = Point(1305.96, 2628.3);
+ poly144.ps[3] = Point(1305.96, 2596.3);
+ new ShapeRef(router, poly144, 144);
+
+ Polygon poly145(4);
+ poly145.ps[0] = Point(1656.79, 2741.3);
+ poly145.ps[1] = Point(1656.79, 2773.3);
+ poly145.ps[2] = Point(1636.79, 2773.3);
+ poly145.ps[3] = Point(1636.79, 2741.3);
+ new ShapeRef(router, poly145, 145);
+
+ Polygon poly146(4);
+ poly146.ps[0] = Point(1573.6, 2672.3);
+ poly146.ps[1] = Point(1573.6, 2704.3);
+ poly146.ps[2] = Point(1553.6, 2704.3);
+ poly146.ps[3] = Point(1553.6, 2672.3);
+ new ShapeRef(router, poly146, 146);
+
+ Polygon poly147(4);
+ poly147.ps[0] = Point(1548.46, 2741.3);
+ poly147.ps[1] = Point(1548.46, 2773.3);
+ poly147.ps[2] = Point(1528.46, 2773.3);
+ poly147.ps[3] = Point(1528.46, 2741.3);
+ new ShapeRef(router, poly147, 147);
+
+ Polygon poly148(4);
+ poly148.ps[0] = Point(1656.79, 3124.3);
+ poly148.ps[1] = Point(1656.79, 3156.3);
+ poly148.ps[2] = Point(1636.79, 3156.3);
+ poly148.ps[3] = Point(1636.79, 3124.3);
+ new ShapeRef(router, poly148, 148);
+
+ Polygon poly149(4);
+ poly149.ps[0] = Point(1548.46, 3124.3);
+ poly149.ps[1] = Point(1548.46, 3156.3);
+ poly149.ps[2] = Point(1528.46, 3156.3);
+ poly149.ps[3] = Point(1528.46, 3124.3);
+ new ShapeRef(router, poly149, 149);
+
+ Polygon poly150(4);
+ poly150.ps[0] = Point(1573.6, 3055.3);
+ poly150.ps[1] = Point(1573.6, 3087.3);
+ poly150.ps[2] = Point(1553.6, 3087.3);
+ poly150.ps[3] = Point(1553.6, 3055.3);
+ new ShapeRef(router, poly150, 150);
+
+ Polygon poly151(4);
+ poly151.ps[0] = Point(2245.79, 2739.3);
+ poly151.ps[1] = Point(2245.79, 2759.3);
+ poly151.ps[2] = Point(2213.79, 2759.3);
+ poly151.ps[3] = Point(2213.79, 2739.3);
+ new ShapeRef(router, poly151, 151);
+
+ Polygon poly152(4);
+ poly152.ps[0] = Point(2344.71, 2596.3);
+ poly152.ps[1] = Point(2344.71, 2628.3);
+ poly152.ps[2] = Point(2324.71, 2628.3);
+ poly152.ps[3] = Point(2324.71, 2596.3);
+ new ShapeRef(router, poly152, 152);
+
+ Polygon poly153(4);
+ poly153.ps[0] = Point(2493.71, 2945.3);
+ poly153.ps[1] = Point(2493.71, 2965.3);
+ poly153.ps[2] = Point(2461.71, 2965.3);
+ poly153.ps[3] = Point(2461.71, 2945.3);
+ new ShapeRef(router, poly153, 153);
+
+ Polygon poly154(4);
+ poly154.ps[0] = Point(860.958, 2461.3);
+ poly154.ps[1] = Point(860.958, 2493.3);
+ poly154.ps[2] = Point(840.958, 2493.3);
+ poly154.ps[3] = Point(840.958, 2461.3);
+ new ShapeRef(router, poly154, 154);
+
+ Polygon poly155(4);
+ poly155.ps[0] = Point(974.958, 2467.3);
+ poly155.ps[1] = Point(974.958, 2487.3);
+ poly155.ps[2] = Point(942.958, 2487.3);
+ poly155.ps[3] = Point(942.958, 2467.3);
+ new ShapeRef(router, poly155, 155);
+
+ Polygon poly156(4);
+ poly156.ps[0] = Point(886.358, 2596.3);
+ poly156.ps[1] = Point(886.358, 2628.3);
+ poly156.ps[2] = Point(866.358, 2628.3);
+ poly156.ps[3] = Point(866.358, 2596.3);
+ new ShapeRef(router, poly156, 156);
+
+ Polygon poly157(4);
+ poly157.ps[0] = Point(886.358, 2741.3);
+ poly157.ps[1] = Point(886.358, 2773.3);
+ poly157.ps[2] = Point(866.358, 2773.3);
+ poly157.ps[3] = Point(866.358, 2741.3);
+ new ShapeRef(router, poly157, 157);
+
+ Polygon poly158(4);
+ poly158.ps[0] = Point(892.358, 3061.3);
+ poly158.ps[1] = Point(892.358, 3081.3);
+ poly158.ps[2] = Point(860.358, 3081.3);
+ poly158.ps[3] = Point(860.358, 3061.3);
+ new ShapeRef(router, poly158, 158);
+
+ Polygon poly159(4);
+ poly159.ps[0] = Point(2187.79, 1031.64);
+ poly159.ps[1] = Point(2187.79, 1051.64);
+ poly159.ps[2] = Point(2155.79, 1051.64);
+ poly159.ps[3] = Point(2155.79, 1031.64);
+ new ShapeRef(router, poly159, 159);
+
+ Polygon poly160(4);
+ poly160.ps[0] = Point(2493.71, 1031.64);
+ poly160.ps[1] = Point(2493.71, 1051.64);
+ poly160.ps[2] = Point(2461.71, 1051.64);
+ poly160.ps[3] = Point(2461.71, 1031.64);
+ new ShapeRef(router, poly160, 160);
+
+ Polygon poly161(4);
+ poly161.ps[0] = Point(2257.79, 1133.64);
+ poly161.ps[1] = Point(2257.79, 1153.64);
+ poly161.ps[2] = Point(2225.79, 1153.64);
+ poly161.ps[3] = Point(2225.79, 1133.64);
+ new ShapeRef(router, poly161, 161);
+
+ Polygon poly162(4);
+ poly162.ps[0] = Point(1785.79, 496.5);
+ poly162.ps[1] = Point(1785.79, 516.5);
+ poly162.ps[2] = Point(1753.79, 516.5);
+ poly162.ps[3] = Point(1753.79, 496.5);
+ new ShapeRef(router, poly162, 162);
+
+ Polygon poly163(4);
+ poly163.ps[0] = Point(1785.79, 567.5);
+ poly163.ps[1] = Point(1785.79, 587.5);
+ poly163.ps[2] = Point(1753.79, 587.5);
+ poly163.ps[3] = Point(1753.79, 567.5);
+ new ShapeRef(router, poly163, 163);
+
+ Polygon poly164(4);
+ poly164.ps[0] = Point(3509.07, 2154.05);
+ poly164.ps[1] = Point(3509.07, 2216.05);
+ poly164.ps[2] = Point(3447.07, 2216.05);
+ poly164.ps[3] = Point(3447.07, 2154.05);
+ new ShapeRef(router, poly164, 164);
+
+ Polygon poly165(4);
+ poly165.ps[0] = Point(3627.07, 2154.05);
+ poly165.ps[1] = Point(3627.07, 2216.05);
+ poly165.ps[2] = Point(3565.07, 2216.05);
+ poly165.ps[3] = Point(3565.07, 2154.05);
+ new ShapeRef(router, poly165, 165);
+
+ Polygon poly166(4);
+ poly166.ps[0] = Point(2051.79, 1260.24);
+ poly166.ps[1] = Point(2051.79, 1292.24);
+ poly166.ps[2] = Point(2031.79, 1292.24);
+ poly166.ps[3] = Point(2031.79, 1260.24);
+ new ShapeRef(router, poly166, 166);
+
+ Polygon poly167(4);
+ poly167.ps[0] = Point(333, 1109.24);
+ poly167.ps[1] = Point(333, 1141.24);
+ poly167.ps[2] = Point(313, 1141.24);
+ poly167.ps[3] = Point(313, 1109.24);
+ new ShapeRef(router, poly167, 167);
+
+ Polygon poly168(4);
+ poly168.ps[0] = Point(291, 1127.64);
+ poly168.ps[1] = Point(291, 1159.64);
+ poly168.ps[2] = Point(271, 1159.64);
+ poly168.ps[3] = Point(271, 1127.64);
+ new ShapeRef(router, poly168, 168);
+
+ Polygon poly169(4);
+ poly169.ps[0] = Point(475.333, 1127.64);
+ poly169.ps[1] = Point(475.333, 1159.64);
+ poly169.ps[2] = Point(455.333, 1159.64);
+ poly169.ps[3] = Point(455.333, 1127.64);
+ new ShapeRef(router, poly169, 169);
+
+ Polygon poly170(4);
+ poly170.ps[0] = Point(3151.24, 1436.94);
+ poly170.ps[1] = Point(3151.24, 1601.94);
+ poly170.ps[2] = Point(3051.24, 1601.94);
+ poly170.ps[3] = Point(3051.24, 1436.94);
+ new ShapeRef(router, poly170, 170);
+
+ Polygon poly171(4);
+ poly171.ps[0] = Point(2153.8, 354.5);
+ poly171.ps[1] = Point(2153.8, 414.5);
+ poly171.ps[2] = Point(1901.8, 414.5);
+ poly171.ps[3] = Point(1901.8, 354.5);
+ new ShapeRef(router, poly171, 171);
+
+ Polygon poly172(4);
+ poly172.ps[0] = Point(1923.29, 1174.24);
+ poly172.ps[1] = Point(1923.29, 1234.24);
+ poly172.ps[2] = Point(1666.29, 1234.24);
+ poly172.ps[3] = Point(1666.29, 1174.24);
+ new ShapeRef(router, poly172, 172);
+
+ Polygon poly173(4);
+ poly173.ps[0] = Point(1521.6, 2799.3);
+ poly173.ps[1] = Point(1521.6, 2973.3);
+ poly173.ps[2] = Point(1228.6, 2973.3);
+ poly173.ps[3] = Point(1228.6, 2799.3);
+ new ShapeRef(router, poly173, 173);
+
+ Polygon poly174(4);
+ poly174.ps[0] = Point(1273.96, 211.5);
+ poly174.ps[1] = Point(1273.96, 385.5);
+ poly174.ps[2] = Point(1191.96, 385.5);
+ poly174.ps[3] = Point(1191.96, 211.5);
+ new ShapeRef(router, poly174, 174);
+
+ Polygon poly175(4);
+ poly175.ps[0] = Point(1335.86, 902.5);
+ poly175.ps[1] = Point(1335.86, 1076.5);
+ poly175.ps[2] = Point(1253.86, 1076.5);
+ poly175.ps[3] = Point(1253.86, 902.5);
+ new ShapeRef(router, poly175, 175);
+
+ Polygon poly176(4);
+ poly176.ps[0] = Point(2984.99, 1489.44);
+ poly176.ps[1] = Point(2984.99, 1549.44);
+ poly176.ps[2] = Point(2706.99, 1549.44);
+ poly176.ps[3] = Point(2706.99, 1489.44);
+ new ShapeRef(router, poly176, 176);
+
+ Polygon poly177(4);
+ poly177.ps[0] = Point(2646.54, 3113.3);
+ poly177.ps[1] = Point(2646.54, 3287.3);
+ poly177.ps[2] = Point(2566.54, 3287.3);
+ poly177.ps[3] = Point(2566.54, 3113.3);
+ new ShapeRef(router, poly177, 177);
+
+ Polygon poly178(4);
+ poly178.ps[0] = Point(1892.79, 3178.3);
+ poly178.ps[1] = Point(1892.79, 3240.3);
+ poly178.ps[2] = Point(1830.79, 3240.3);
+ poly178.ps[3] = Point(1830.79, 3178.3);
+ new ShapeRef(router, poly178, 178);
+
+ Polygon poly179(4);
+ poly179.ps[0] = Point(1798.79, 3391.3);
+ poly179.ps[1] = Point(1798.79, 3411.3);
+ poly179.ps[2] = Point(1766.79, 3411.3);
+ poly179.ps[3] = Point(1766.79, 3391.3);
+ new ShapeRef(router, poly179, 179);
+
+ Polygon poly180(4);
+ poly180.ps[0] = Point(1798.79, 3187.3);
+ poly180.ps[1] = Point(1798.79, 3207.3);
+ poly180.ps[2] = Point(1766.79, 3207.3);
+ poly180.ps[3] = Point(1766.79, 3187.3);
+ new ShapeRef(router, poly180, 180);
+
+ Polygon poly181(4);
+ poly181.ps[0] = Point(2791.54, 113.5);
+ poly181.ps[1] = Point(2791.54, 133.5);
+ poly181.ps[2] = Point(2759.54, 133.5);
+ poly181.ps[3] = Point(2759.54, 113.5);
+ new ShapeRef(router, poly181, 181);
+
+ Polygon poly182(4);
+ poly182.ps[0] = Point(2858.54, 2843.3);
+ poly182.ps[1] = Point(2858.54, 2903.3);
+ poly182.ps[2] = Point(2624.54, 2903.3);
+ poly182.ps[3] = Point(2624.54, 2843.3);
+ new ShapeRef(router, poly182, 182);
+
+ Polygon poly183(4);
+ poly183.ps[0] = Point(1969.79, 2935.3);
+ poly183.ps[1] = Point(1969.79, 2955.3);
+ poly183.ps[2] = Point(1937.79, 2955.3);
+ poly183.ps[3] = Point(1937.79, 2935.3);
+ new ShapeRef(router, poly183, 183);
+
+ Polygon poly184(4);
+ poly184.ps[0] = Point(2187.79, 210.875);
+ poly184.ps[1] = Point(2187.79, 230.875);
+ poly184.ps[2] = Point(2155.79, 230.875);
+ poly184.ps[3] = Point(2155.79, 210.875);
+ new ShapeRef(router, poly184, 184);
+
+ Polygon poly185(4);
+ poly185.ps[0] = Point(2072.79, 189.875);
+ poly185.ps[1] = Point(2072.79, 251.875);
+ poly185.ps[2] = Point(2010.79, 251.875);
+ poly185.ps[3] = Point(2010.79, 189.875);
+ new ShapeRef(router, poly185, 185);
+
+ Polygon poly186(4);
+ poly186.ps[0] = Point(2072.79, 2154.05);
+ poly186.ps[1] = Point(2072.79, 2216.05);
+ poly186.ps[2] = Point(2010.79, 2216.05);
+ poly186.ps[3] = Point(2010.79, 2154.05);
+ new ShapeRef(router, poly186, 186);
+
+ Polygon poly187(4);
+ poly187.ps[0] = Point(1806.79, 1841.95);
+ poly187.ps[1] = Point(1806.79, 1903.95);
+ poly187.ps[2] = Point(1744.79, 1903.95);
+ poly187.ps[3] = Point(1744.79, 1841.95);
+ new ShapeRef(router, poly187, 187);
+
+ Polygon poly188(4);
+ poly188.ps[0] = Point(1942.79, 1862.95);
+ poly188.ps[1] = Point(1942.79, 1882.95);
+ poly188.ps[2] = Point(1910.79, 1882.95);
+ poly188.ps[3] = Point(1910.79, 1862.95);
+ new ShapeRef(router, poly188, 188);
+
+ Polygon poly189(4);
+ poly189.ps[0] = Point(1104.18, 1841.95);
+ poly189.ps[1] = Point(1104.18, 1903.95);
+ poly189.ps[2] = Point(1042.18, 1903.95);
+ poly189.ps[3] = Point(1042.18, 1841.95);
+ new ShapeRef(router, poly189, 189);
+
+ Polygon poly190(4);
+ poly190.ps[0] = Point(1480.46, 1862.95);
+ poly190.ps[1] = Point(1480.46, 1882.95);
+ poly190.ps[2] = Point(1448.46, 1882.95);
+ poly190.ps[3] = Point(1448.46, 1862.95);
+ new ShapeRef(router, poly190, 190);
+
+ Polygon poly191(4);
+ poly191.ps[0] = Point(907.358, 1841.95);
+ poly191.ps[1] = Point(907.358, 1903.95);
+ poly191.ps[2] = Point(845.358, 1903.95);
+ poly191.ps[3] = Point(845.358, 1841.95);
+ new ShapeRef(router, poly191, 191);
+
+ Polygon poly192(4);
+ poly192.ps[0] = Point(988.958, 1862.95);
+ poly192.ps[1] = Point(988.958, 1882.95);
+ poly192.ps[2] = Point(956.958, 1882.95);
+ poly192.ps[3] = Point(956.958, 1862.95);
+ new ShapeRef(router, poly192, 192);
+
+ Polygon poly193(4);
+ poly193.ps[0] = Point(1104.18, 1700.64);
+ poly193.ps[1] = Point(1104.18, 1762.64);
+ poly193.ps[2] = Point(1042.18, 1762.64);
+ poly193.ps[3] = Point(1042.18, 1700.64);
+ new ShapeRef(router, poly193, 193);
+
+ Polygon poly194(4);
+ poly194.ps[0] = Point(1104.18, 1992.95);
+ poly194.ps[1] = Point(1104.18, 2054.95);
+ poly194.ps[2] = Point(1042.18, 2054.95);
+ poly194.ps[3] = Point(1042.18, 1992.95);
+ new ShapeRef(router, poly194, 194);
+
+ Polygon poly195(4);
+ poly195.ps[0] = Point(1551.87, 1611.77);
+ poly195.ps[1] = Point(1551.87, 1651.77);
+ poly195.ps[2] = Point(1475.87, 1651.77);
+ poly195.ps[3] = Point(1475.87, 1611.77);
+ new ShapeRef(router, poly195, 195);
+
+ Polygon poly196(4);
+ poly196.ps[0] = Point(2578.71, 1617.64);
+ poly196.ps[1] = Point(2578.71, 1679.64);
+ poly196.ps[2] = Point(2516.71, 1679.64);
+ poly196.ps[3] = Point(2516.71, 1617.64);
+ new ShapeRef(router, poly196, 196);
+
+ Polygon poly197(4);
+ poly197.ps[0] = Point(3099.24, 285.75);
+ poly197.ps[1] = Point(3099.24, 317.75);
+ poly197.ps[2] = Point(3079.24, 317.75);
+ poly197.ps[3] = Point(3079.24, 285.75);
+ new ShapeRef(router, poly197, 197);
+
+ Polygon poly198(4);
+ poly198.ps[0] = Point(2732.54, 2489.3);
+ poly198.ps[1] = Point(2732.54, 2533.3);
+ poly198.ps[2] = Point(2592.54, 2533.3);
+ poly198.ps[3] = Point(2592.54, 2489.3);
+ new ShapeRef(router, poly198, 198);
+
+ Polygon poly199(4);
+ poly199.ps[0] = Point(1822.83, 2270.38);
+ poly199.ps[1] = Point(1822.83, 2330.38);
+ poly199.ps[2] = Point(1504.83, 2330.38);
+ poly199.ps[3] = Point(1504.83, 2270.38);
+ new ShapeRef(router, poly199, 199);
+
+ Polygon poly200(4);
+ poly200.ps[0] = Point(2072.79, 2643.3);
+ poly200.ps[1] = Point(2072.79, 2705.3);
+ poly200.ps[2] = Point(2010.79, 2705.3);
+ poly200.ps[3] = Point(2010.79, 2643.3);
+ new ShapeRef(router, poly200, 200);
+
+ Polygon poly201(4);
+ poly201.ps[0] = Point(2051.79, 2733.3);
+ poly201.ps[1] = Point(2051.79, 2765.3);
+ poly201.ps[2] = Point(2031.79, 2765.3);
+ poly201.ps[3] = Point(2031.79, 2733.3);
+ new ShapeRef(router, poly201, 201);
+
+ Polygon poly202(4);
+ poly202.ps[0] = Point(1892.79, 2460.3);
+ poly202.ps[1] = Point(1892.79, 2522.3);
+ poly202.ps[2] = Point(1830.79, 2522.3);
+ poly202.ps[3] = Point(1830.79, 2460.3);
+ new ShapeRef(router, poly202, 202);
+
+ Polygon poly203(4);
+ poly203.ps[0] = Point(1892.79, 2643.3);
+ poly203.ps[1] = Point(1892.79, 2705.3);
+ poly203.ps[2] = Point(1830.79, 2705.3);
+ poly203.ps[3] = Point(1830.79, 2643.3);
+ new ShapeRef(router, poly203, 203);
+
+ Polygon poly204(4);
+ poly204.ps[0] = Point(1871.79, 2733.3);
+ poly204.ps[1] = Point(1871.79, 2765.3);
+ poly204.ps[2] = Point(1851.79, 2765.3);
+ poly204.ps[3] = Point(1851.79, 2733.3);
+ new ShapeRef(router, poly204, 204);
+
+ Polygon poly205(4);
+ poly205.ps[0] = Point(1892.79, 2780.3);
+ poly205.ps[1] = Point(1892.79, 2842.3);
+ poly205.ps[2] = Point(1830.79, 2842.3);
+ poly205.ps[3] = Point(1830.79, 2780.3);
+ new ShapeRef(router, poly205, 205);
+
+ Polygon poly206(4);
+ poly206.ps[0] = Point(1830.79, 2498.3);
+ poly206.ps[1] = Point(1830.79, 2560.3);
+ poly206.ps[2] = Point(1768.79, 2560.3);
+ poly206.ps[3] = Point(1768.79, 2498.3);
+ new ShapeRef(router, poly206, 206);
+
+ Polygon poly207(4);
+ poly207.ps[0] = Point(1793.79, 1914.95);
+ poly207.ps[1] = Point(1793.79, 1958.95);
+ poly207.ps[2] = Point(1713.79, 1958.95);
+ poly207.ps[3] = Point(1713.79, 1914.95);
+ new ShapeRef(router, poly207, 207);
+
+ Polygon poly208(4);
+ poly208.ps[0] = Point(1104.18, 538.7);
+ poly208.ps[1] = Point(1104.18, 600.7);
+ poly208.ps[2] = Point(1042.18, 600.7);
+ poly208.ps[3] = Point(1042.18, 538.7);
+ new ShapeRef(router, poly208, 208);
+
+ Polygon poly209(4);
+ poly209.ps[0] = Point(1083.18, 692.5);
+ poly209.ps[1] = Point(1083.18, 724.5);
+ poly209.ps[2] = Point(1063.18, 724.5);
+ poly209.ps[3] = Point(1063.18, 692.5);
+ new ShapeRef(router, poly209, 209);
+
+ Polygon poly210(4);
+ poly210.ps[0] = Point(1245.46, 559.7);
+ poly210.ps[1] = Point(1245.46, 579.7);
+ poly210.ps[2] = Point(1213.46, 579.7);
+ poly210.ps[3] = Point(1213.46, 559.7);
+ new ShapeRef(router, poly210, 210);
+
+ Polygon poly211(4);
+ poly211.ps[0] = Point(907.358, 344.5);
+ poly211.ps[1] = Point(907.358, 406.5);
+ poly211.ps[2] = Point(845.358, 406.5);
+ poly211.ps[3] = Point(845.358, 344.5);
+ new ShapeRef(router, poly211, 211);
+
+ Polygon poly212(4);
+ poly212.ps[0] = Point(886.358, 553.7);
+ poly212.ps[1] = Point(886.358, 585.7);
+ poly212.ps[2] = Point(866.358, 585.7);
+ poly212.ps[3] = Point(866.358, 553.7);
+ new ShapeRef(router, poly212, 212);
+
+ Polygon poly213(4);
+ poly213.ps[0] = Point(812.958, 684.5);
+ poly213.ps[1] = Point(812.958, 746.5);
+ poly213.ps[2] = Point(750.958, 746.5);
+ poly213.ps[3] = Point(750.958, 684.5);
+ new ShapeRef(router, poly213, 213);
+
+ Polygon poly214(4);
+ poly214.ps[0] = Point(414.333, 496.5);
+ poly214.ps[1] = Point(414.333, 528.5);
+ poly214.ps[2] = Point(394.333, 528.5);
+ poly214.ps[3] = Point(394.333, 496.5);
+ new ShapeRef(router, poly214, 214);
+
+ Polygon poly215(4);
+ poly215.ps[0] = Point(2493.71, 2854.3);
+ poly215.ps[1] = Point(2493.71, 2874.3);
+ poly215.ps[2] = Point(2461.71, 2874.3);
+ poly215.ps[3] = Point(2461.71, 2854.3);
+ new ShapeRef(router, poly215, 215);
+
+ Polygon poly216(4);
+ poly216.ps[0] = Point(3150.9, 2498.3);
+ poly216.ps[1] = Point(3150.9, 2560.3);
+ poly216.ps[2] = Point(3088.9, 2560.3);
+ poly216.ps[3] = Point(3088.9, 2498.3);
+ new ShapeRef(router, poly216, 216);
+
+ Polygon poly217(4);
+ poly217.ps[0] = Point(2999.99, 2643.3);
+ poly217.ps[1] = Point(2999.99, 2705.3);
+ poly217.ps[2] = Point(2937.99, 2705.3);
+ poly217.ps[3] = Point(2937.99, 2643.3);
+ new ShapeRef(router, poly217, 217);
+
+ Polygon poly218(4);
+ poly218.ps[0] = Point(2926.99, 2602.3);
+ poly218.ps[1] = Point(2926.99, 2622.3);
+ poly218.ps[2] = Point(2894.99, 2622.3);
+ poly218.ps[3] = Point(2894.99, 2602.3);
+ new ShapeRef(router, poly218, 218);
+
+ Polygon poly219(4);
+ poly219.ps[0] = Point(3150.9, 2841.3);
+ poly219.ps[1] = Point(3150.9, 2903.3);
+ poly219.ps[2] = Point(3088.9, 2903.3);
+ poly219.ps[3] = Point(3088.9, 2841.3);
+ new ShapeRef(router, poly219, 219);
+
+ Polygon poly220(4);
+ poly220.ps[0] = Point(2999.99, 3178.3);
+ poly220.ps[1] = Point(2999.99, 3240.3);
+ poly220.ps[2] = Point(2937.99, 3240.3);
+ poly220.ps[3] = Point(2937.99, 3178.3);
+ new ShapeRef(router, poly220, 220);
+
+ Polygon poly221(4);
+ poly221.ps[0] = Point(3252.24, 2643.3);
+ poly221.ps[1] = Point(3252.24, 2705.3);
+ poly221.ps[2] = Point(3190.24, 2705.3);
+ poly221.ps[3] = Point(3190.24, 2643.3);
+ new ShapeRef(router, poly221, 221);
+
+ Polygon poly222(4);
+ poly222.ps[0] = Point(3247.44, 3178.3);
+ poly222.ps[1] = Point(3247.44, 3240.3);
+ poly222.ps[2] = Point(3185.44, 3240.3);
+ poly222.ps[3] = Point(3185.44, 3178.3);
+ new ShapeRef(router, poly222, 222);
+
+ Polygon poly223(4);
+ poly223.ps[0] = Point(3252.24, 2596.3);
+ poly223.ps[1] = Point(3252.24, 2628.3);
+ poly223.ps[2] = Point(3232.24, 2628.3);
+ poly223.ps[3] = Point(3232.24, 2596.3);
+ new ShapeRef(router, poly223, 223);
+
+ Polygon poly224(4);
+ poly224.ps[0] = Point(2900.99, 3061.3);
+ poly224.ps[1] = Point(2900.99, 3081.3);
+ poly224.ps[2] = Point(2868.99, 3081.3);
+ poly224.ps[3] = Point(2868.99, 3061.3);
+ new ShapeRef(router, poly224, 224);
+
+ Polygon poly225(4);
+ poly225.ps[0] = Point(3336.74, 3055.3);
+ poly225.ps[1] = Point(3336.74, 3087.3);
+ poly225.ps[2] = Point(3316.74, 3087.3);
+ poly225.ps[3] = Point(3316.74, 3055.3);
+ new ShapeRef(router, poly225, 225);
+
+ Polygon poly226(4);
+ poly226.ps[0] = Point(1798.79, 3289.3);
+ poly226.ps[1] = Point(1798.79, 3309.3);
+ poly226.ps[2] = Point(1766.79, 3309.3);
+ poly226.ps[3] = Point(1766.79, 3289.3);
+ new ShapeRef(router, poly226, 226);
+
+ Polygon poly227(4);
+ poly227.ps[0] = Point(210, 492.5);
+ poly227.ps[1] = Point(210, 532.5);
+ poly227.ps[2] = Point(134, 532.5);
+ poly227.ps[3] = Point(134, 492.5);
+ new ShapeRef(router, poly227, 227);
+
+ Polygon poly228(4);
+ poly228.ps[0] = Point(121, 628.5);
+ poly228.ps[1] = Point(121, 668.5);
+ poly228.ps[2] = Point(45, 668.5);
+ poly228.ps[3] = Point(45, 628.5);
+ new ShapeRef(router, poly228, 228);
+
+ Polygon poly229(4);
+ poly229.ps[0] = Point(568.333, 638.5);
+ poly229.ps[1] = Point(568.333, 698.5);
+ poly229.ps[2] = Point(512.333, 698.5);
+ poly229.ps[3] = Point(512.333, 638.5);
+ new ShapeRef(router, poly229, 229);
+
+ Polygon poly230(4);
+ poly230.ps[0] = Point(568.333, 763.833);
+ poly230.ps[1] = Point(568.333, 823.833);
+ poly230.ps[2] = Point(512.333, 823.833);
+ poly230.ps[3] = Point(512.333, 763.833);
+ new ShapeRef(router, poly230, 230);
+
+ Polygon poly231(4);
+ poly231.ps[0] = Point(1481.46, 688.5);
+ poly231.ps[1] = Point(1481.46, 728.5);
+ poly231.ps[2] = Point(1405.46, 728.5);
+ poly231.ps[3] = Point(1405.46, 688.5);
+ new ShapeRef(router, poly231, 231);
+
+ Polygon poly232(4);
+ poly232.ps[0] = Point(1570.46, 221.5);
+ poly232.ps[1] = Point(1570.46, 281.5);
+ poly232.ps[2] = Point(1514.46, 281.5);
+ poly232.ps[3] = Point(1514.46, 221.5);
+ new ShapeRef(router, poly232, 232);
+
+ Polygon poly233(4);
+ poly233.ps[0] = Point(1970.29, 221.5);
+ poly233.ps[1] = Point(1970.29, 281.5);
+ poly233.ps[2] = Point(1914.29, 281.5);
+ poly233.ps[3] = Point(1914.29, 221.5);
+ new ShapeRef(router, poly233, 233);
+
+ Polygon poly234(4);
+ poly234.ps[0] = Point(2054.79, 707.5);
+ poly234.ps[1] = Point(2054.79, 767.5);
+ poly234.ps[2] = Point(1998.79, 767.5);
+ poly234.ps[3] = Point(1998.79, 707.5);
+ new ShapeRef(router, poly234, 234);
+
+ Polygon poly235(4);
+ poly235.ps[0] = Point(568.333, 1206.24);
+ poly235.ps[1] = Point(568.333, 1266.24);
+ poly235.ps[2] = Point(512.333, 1266.24);
+ poly235.ps[3] = Point(512.333, 1206.24);
+ new ShapeRef(router, poly235, 235);
+
+ Polygon poly236(4);
+ poly236.ps[0] = Point(739.958, 1206.24);
+ poly236.ps[1] = Point(739.958, 1266.24);
+ poly236.ps[2] = Point(683.958, 1266.24);
+ poly236.ps[3] = Point(683.958, 1206.24);
+ new ShapeRef(router, poly236, 236);
+
+ Polygon poly237(4);
+ poly237.ps[0] = Point(1000.96, 1206.24);
+ poly237.ps[1] = Point(1000.96, 1266.24);
+ poly237.ps[2] = Point(944.958, 1266.24);
+ poly237.ps[3] = Point(944.958, 1206.24);
+ new ShapeRef(router, poly237, 237);
+
+ Polygon poly238(4);
+ poly238.ps[0] = Point(1040.96, 1123.64);
+ poly238.ps[1] = Point(1040.96, 1163.64);
+ poly238.ps[2] = Point(964.958, 1163.64);
+ poly238.ps[3] = Point(964.958, 1123.64);
+ new ShapeRef(router, poly238, 238);
+
+ Polygon poly239(4);
+ poly239.ps[0] = Point(1413.86, 899.5);
+ poly239.ps[1] = Point(1413.86, 959.5);
+ poly239.ps[2] = Point(1357.86, 959.5);
+ poly239.ps[3] = Point(1357.86, 899.5);
+ new ShapeRef(router, poly239, 239);
+
+ Polygon poly240(4);
+ poly240.ps[0] = Point(1413.86, 1051.64);
+ poly240.ps[1] = Point(1413.86, 1111.64);
+ poly240.ps[2] = Point(1357.86, 1111.64);
+ poly240.ps[3] = Point(1357.86, 1051.64);
+ new ShapeRef(router, poly240, 240);
+
+ Polygon poly241(4);
+ poly241.ps[0] = Point(1413.86, 1153.64);
+ poly241.ps[1] = Point(1413.86, 1213.64);
+ poly241.ps[2] = Point(1357.86, 1213.64);
+ poly241.ps[3] = Point(1357.86, 1153.64);
+ new ShapeRef(router, poly241, 241);
+
+ Polygon poly242(4);
+ poly242.ps[0] = Point(1732.79, 1256.24);
+ poly242.ps[1] = Point(1732.79, 1296.24);
+ poly242.ps[2] = Point(1656.79, 1296.24);
+ poly242.ps[3] = Point(1656.79, 1256.24);
+ new ShapeRef(router, poly242, 242);
+
+ Polygon poly243(4);
+ poly243.ps[0] = Point(1954.79, 1663.64);
+ poly243.ps[1] = Point(1954.79, 1723.64);
+ poly243.ps[2] = Point(1898.79, 1723.64);
+ poly243.ps[3] = Point(1898.79, 1663.64);
+ new ShapeRef(router, poly243, 243);
+
+ Polygon poly244(4);
+ poly244.ps[0] = Point(2044.29, 1420.24);
+ poly244.ps[1] = Point(2044.29, 1460.24);
+ poly244.ps[2] = Point(1968.29, 1460.24);
+ poly244.ps[3] = Point(1968.29, 1420.24);
+ new ShapeRef(router, poly244, 244);
+
+ Polygon poly245(4);
+ poly245.ps[0] = Point(2127.79, 1702.64);
+ poly245.ps[1] = Point(2127.79, 1742.64);
+ poly245.ps[2] = Point(2051.79, 1742.64);
+ poly245.ps[3] = Point(2051.79, 1702.64);
+ new ShapeRef(router, poly245, 245);
+
+ Polygon poly246(4);
+ poly246.ps[0] = Point(2199.79, 1499.64);
+ poly246.ps[1] = Point(2199.79, 1559.64);
+ poly246.ps[2] = Point(2143.79, 1559.64);
+ poly246.ps[3] = Point(2143.79, 1499.64);
+ new ShapeRef(router, poly246, 246);
+
+ Polygon poly247(4);
+ poly247.ps[0] = Point(2327.79, 1420.24);
+ poly247.ps[1] = Point(2327.79, 1460.24);
+ poly247.ps[2] = Point(2251.79, 1460.24);
+ poly247.ps[3] = Point(2251.79, 1420.24);
+ new ShapeRef(router, poly247, 247);
+
+ Polygon poly248(4);
+ poly248.ps[0] = Point(2505.71, 1439.44);
+ poly248.ps[1] = Point(2505.71, 1499.44);
+ poly248.ps[2] = Point(2449.71, 1499.44);
+ poly248.ps[3] = Point(2449.71, 1439.44);
+ new ShapeRef(router, poly248, 248);
+
+ Polygon poly249(4);
+ poly249.ps[0] = Point(2505.71, 1591.64);
+ poly249.ps[1] = Point(2505.71, 1651.64);
+ poly249.ps[2] = Point(2449.71, 1651.64);
+ poly249.ps[3] = Point(2449.71, 1591.64);
+ new ShapeRef(router, poly249, 249);
+ */
+
+ Polygon poly250(4);
+ poly250.ps[0] = Point(2199.79, 1802.95);
+ poly250.ps[1] = Point(2199.79, 1862.95);
+ poly250.ps[2] = Point(2143.79, 1862.95);
+ poly250.ps[3] = Point(2143.79, 1802.95);
+ new ShapeRef(router, poly250, 250);
+
+ /*
+ Polygon poly251(4);
+ poly251.ps[0] = Point(2505.71, 1943.95);
+ poly251.ps[1] = Point(2505.71, 2003.95);
+ poly251.ps[2] = Point(2449.71, 2003.95);
+ poly251.ps[3] = Point(2449.71, 1943.95);
+ new ShapeRef(router, poly251, 251);
+
+ Polygon poly252(4);
+ poly252.ps[0] = Point(2505.71, 2065.95);
+ poly252.ps[1] = Point(2505.71, 2125.95);
+ poly252.ps[2] = Point(2449.71, 2125.95);
+ poly252.ps[3] = Point(2449.71, 2065.95);
+ new ShapeRef(router, poly252, 252);
+
+ Polygon poly253(4);
+ poly253.ps[0] = Point(2688.54, 1742.64);
+ poly253.ps[1] = Point(2688.54, 1802.64);
+ poly253.ps[2] = Point(2632.54, 1802.64);
+ poly253.ps[3] = Point(2632.54, 1742.64);
+ new ShapeRef(router, poly253, 253);
+
+ Polygon poly254(4);
+ poly254.ps[0] = Point(2665.54, 1894.95);
+ poly254.ps[1] = Point(2665.54, 1954.95);
+ poly254.ps[2] = Point(2609.54, 1954.95);
+ poly254.ps[3] = Point(2609.54, 1894.95);
+ new ShapeRef(router, poly254, 254);
+
+ Polygon poly255(4);
+ poly255.ps[0] = Point(2763.54, 1894.95);
+ poly255.ps[1] = Point(2763.54, 1954.95);
+ poly255.ps[2] = Point(2707.54, 1954.95);
+ poly255.ps[3] = Point(2707.54, 1894.95);
+ new ShapeRef(router, poly255, 255);
+
+ Polygon poly256(4);
+ poly256.ps[0] = Point(2926.99, 1742.64);
+ poly256.ps[1] = Point(2926.99, 1802.64);
+ poly256.ps[2] = Point(2870.99, 1802.64);
+ poly256.ps[3] = Point(2870.99, 1742.64);
+ new ShapeRef(router, poly256, 256);
+
+ Polygon poly257(4);
+ poly257.ps[0] = Point(2903.99, 1894.95);
+ poly257.ps[1] = Point(2903.99, 1954.95);
+ poly257.ps[2] = Point(2847.99, 1954.95);
+ poly257.ps[3] = Point(2847.99, 1894.95);
+ new ShapeRef(router, poly257, 257);
+
+ Polygon poly258(4);
+ poly258.ps[0] = Point(2981.99, 1894.95);
+ poly258.ps[1] = Point(2981.99, 1954.95);
+ poly258.ps[2] = Point(2925.99, 1954.95);
+ poly258.ps[3] = Point(2925.99, 1894.95);
+ new ShapeRef(router, poly258, 258);
+
+ Polygon poly259(4);
+ poly259.ps[0] = Point(2327.79, 688.5);
+ poly259.ps[1] = Point(2327.79, 728.5);
+ poly259.ps[2] = Point(2251.79, 728.5);
+ poly259.ps[3] = Point(2251.79, 688.5);
+ new ShapeRef(router, poly259, 259);
+
+ Polygon poly260(4);
+ poly260.ps[0] = Point(2633.71, 688.5);
+ poly260.ps[1] = Point(2633.71, 728.5);
+ poly260.ps[2] = Point(2557.71, 728.5);
+ poly260.ps[3] = Point(2557.71, 688.5);
+ new ShapeRef(router, poly260, 260);
+
+ Polygon poly261(4);
+ poly261.ps[0] = Point(2873.54, 688.5);
+ poly261.ps[1] = Point(2873.54, 728.5);
+ poly261.ps[2] = Point(2797.54, 728.5);
+ poly261.ps[3] = Point(2797.54, 688.5);
+ new ShapeRef(router, poly261, 261);
+
+ Polygon poly262(4);
+ poly262.ps[0] = Point(3054.99, 688.5);
+ poly262.ps[1] = Point(3054.99, 728.5);
+ poly262.ps[2] = Point(2978.99, 728.5);
+ poly262.ps[3] = Point(2978.99, 688.5);
+ new ShapeRef(router, poly262, 262);
+
+ Polygon poly263(4);
+ poly263.ps[0] = Point(3054.99, 894.5);
+ poly263.ps[1] = Point(3054.99, 934.5);
+ poly263.ps[2] = Point(2978.99, 934.5);
+ poly263.ps[3] = Point(2978.99, 894.5);
+ new ShapeRef(router, poly263, 263);
+
+ Polygon poly264(4);
+ poly264.ps[0] = Point(2327.79, 281.75);
+ poly264.ps[1] = Point(2327.79, 321.75);
+ poly264.ps[2] = Point(2251.79, 321.75);
+ poly264.ps[3] = Point(2251.79, 281.75);
+ new ShapeRef(router, poly264, 264);
+
+ Polygon poly265(4);
+ poly265.ps[0] = Point(2505.71, 150.875);
+ poly265.ps[1] = Point(2505.71, 210.875);
+ poly265.ps[2] = Point(2449.71, 210.875);
+ poly265.ps[3] = Point(2449.71, 150.875);
+ new ShapeRef(router, poly265, 265);
+
+ Polygon poly266(4);
+ poly266.ps[0] = Point(2633.71, 281.75);
+ poly266.ps[1] = Point(2633.71, 321.75);
+ poly266.ps[2] = Point(2557.71, 321.75);
+ poly266.ps[3] = Point(2557.71, 281.75);
+ new ShapeRef(router, poly266, 266);
+
+ Polygon poly267(4);
+ poly267.ps[0] = Point(2693.54, 150.875);
+ poly267.ps[1] = Point(2693.54, 210.875);
+ poly267.ps[2] = Point(2637.54, 210.875);
+ poly267.ps[3] = Point(2637.54, 150.875);
+ new ShapeRef(router, poly267, 267);
+
+ Polygon poly268(4);
+ poly268.ps[0] = Point(2693.54, 367.7);
+ poly268.ps[1] = Point(2693.54, 427.7);
+ poly268.ps[2] = Point(2637.54, 427.7);
+ poly268.ps[3] = Point(2637.54, 367.7);
+ new ShapeRef(router, poly268, 268);
+
+ Polygon poly269(4);
+ poly269.ps[0] = Point(2947.99, 367.7);
+ poly269.ps[1] = Point(2947.99, 427.7);
+ poly269.ps[2] = Point(2891.99, 427.7);
+ poly269.ps[3] = Point(2891.99, 367.7);
+ new ShapeRef(router, poly269, 269);
+
+ Polygon poly270(4);
+ poly270.ps[0] = Point(3225.24, 281.75);
+ poly270.ps[1] = Point(3225.24, 321.75);
+ poly270.ps[2] = Point(3149.24, 321.75);
+ poly270.ps[3] = Point(3149.24, 281.75);
+ new ShapeRef(router, poly270, 270);
+
+ Polygon poly271(4);
+ poly271.ps[0] = Point(3506.07, 844.5);
+ poly271.ps[1] = Point(3506.07, 904.5);
+ poly271.ps[2] = Point(3450.07, 904.5);
+ poly271.ps[3] = Point(3450.07, 844.5);
+ new ShapeRef(router, poly271, 271);
+
+ Polygon poly272(4);
+ poly272.ps[0] = Point(3564.07, 1852.95);
+ poly272.ps[1] = Point(3564.07, 1892.95);
+ poly272.ps[2] = Point(3488.07, 1892.95);
+ poly272.ps[3] = Point(3488.07, 1852.95);
+ new ShapeRef(router, poly272, 272);
+
+ Polygon poly273(4);
+ poly273.ps[0] = Point(3564.07, 2592.3);
+ poly273.ps[1] = Point(3564.07, 2632.3);
+ poly273.ps[2] = Point(3488.07, 2632.3);
+ poly273.ps[3] = Point(3488.07, 2592.3);
+ new ShapeRef(router, poly273, 273);
+
+ Polygon poly274(4);
+ poly274.ps[0] = Point(2815.54, 3427.3);
+ poly274.ps[1] = Point(2815.54, 3487.3);
+ poly274.ps[2] = Point(2759.54, 3487.3);
+ poly274.ps[3] = Point(2759.54, 3427.3);
+ new ShapeRef(router, poly274, 274);
+
+ Polygon poly275(4);
+ poly275.ps[0] = Point(2815.54, 3529.3);
+ poly275.ps[1] = Point(2815.54, 3589.3);
+ poly275.ps[2] = Point(2759.54, 3589.3);
+ poly275.ps[3] = Point(2759.54, 3529.3);
+ new ShapeRef(router, poly275, 275);
+
+ Polygon poly276(4);
+ poly276.ps[0] = Point(3682.07, 2592.3);
+ poly276.ps[1] = Point(3682.07, 2632.3);
+ poly276.ps[2] = Point(3606.07, 2632.3);
+ poly276.ps[3] = Point(3606.07, 2592.3);
+ new ShapeRef(router, poly276, 276);
+
+ Polygon poly277(4);
+ poly277.ps[0] = Point(3682.07, 894.5);
+ poly277.ps[1] = Point(3682.07, 934.5);
+ poly277.ps[2] = Point(3606.07, 934.5);
+ poly277.ps[3] = Point(3606.07, 894.5);
+ new ShapeRef(router, poly277, 277);
+
+ Polygon poly278(4);
+ poly278.ps[0] = Point(3412.74, 894.5);
+ poly278.ps[1] = Point(3412.74, 934.5);
+ poly278.ps[2] = Point(3336.74, 934.5);
+ poly278.ps[3] = Point(3336.74, 894.5);
+ new ShapeRef(router, poly278, 278);
+
+ Polygon poly279(4);
+ poly279.ps[0] = Point(3244.44, 2329.05);
+ poly279.ps[1] = Point(3244.44, 2389.05);
+ poly279.ps[2] = Point(3188.44, 2389.05);
+ poly279.ps[3] = Point(3188.44, 2329.05);
+ new ShapeRef(router, poly279, 279);
+
+ Polygon poly280(4);
+ poly280.ps[0] = Point(3244.44, 2227.05);
+ poly280.ps[1] = Point(3244.44, 2287.05);
+ poly280.ps[2] = Point(3188.44, 2287.05);
+ poly280.ps[3] = Point(3188.44, 2227.05);
+ new ShapeRef(router, poly280, 280);
+
+ Polygon poly281(4);
+ poly281.ps[0] = Point(2815.54, 2227.05);
+ poly281.ps[1] = Point(2815.54, 2287.05);
+ poly281.ps[2] = Point(2759.54, 2287.05);
+ poly281.ps[3] = Point(2759.54, 2227.05);
+ new ShapeRef(router, poly281, 281);
+
+ Polygon poly282(4);
+ poly282.ps[0] = Point(3244.44, 844.5);
+ poly282.ps[1] = Point(3244.44, 904.5);
+ poly282.ps[2] = Point(3188.44, 904.5);
+ poly282.ps[3] = Point(3188.44, 844.5);
+ new ShapeRef(router, poly282, 282);
+
+ Polygon poly283(4);
+ poly283.ps[0] = Point(2815.54, 2115.05);
+ poly283.ps[1] = Point(2815.54, 2175.05);
+ poly283.ps[2] = Point(2759.54, 2175.05);
+ poly283.ps[3] = Point(2759.54, 2115.05);
+ new ShapeRef(router, poly283, 283);
+
+ Polygon poly284(4);
+ poly284.ps[0] = Point(2427.71, 2115.05);
+ poly284.ps[1] = Point(2427.71, 2175.05);
+ poly284.ps[2] = Point(2371.71, 2175.05);
+ poly284.ps[3] = Point(2371.71, 2115.05);
+ new ShapeRef(router, poly284, 284);
+
+ Polygon poly285(4);
+ poly285.ps[0] = Point(1954.79, 2115.05);
+ poly285.ps[1] = Point(1954.79, 2175.05);
+ poly285.ps[2] = Point(1898.79, 2175.05);
+ poly285.ps[3] = Point(1898.79, 2115.05);
+ new ShapeRef(router, poly285, 285);
+
+ Polygon poly286(4);
+ poly286.ps[0] = Point(739.958, 2115.05);
+ poly286.ps[1] = Point(739.958, 2175.05);
+ poly286.ps[2] = Point(683.958, 2175.05);
+ poly286.ps[3] = Point(683.958, 2115.05);
+ new ShapeRef(router, poly286, 286);
+
+ Polygon poly287(4);
+ poly287.ps[0] = Point(1649.6, 2003.95);
+ poly287.ps[1] = Point(1649.6, 2043.95);
+ poly287.ps[2] = Point(1573.6, 2043.95);
+ poly287.ps[3] = Point(1573.6, 2003.95);
+ new ShapeRef(router, poly287, 287);
+
+ Polygon poly288(4);
+ poly288.ps[0] = Point(739.958, 1308.24);
+ poly288.ps[1] = Point(739.958, 1368.24);
+ poly288.ps[2] = Point(683.958, 1368.24);
+ poly288.ps[3] = Point(683.958, 1308.24);
+ new ShapeRef(router, poly288, 288);
+
+ Polygon poly289(4);
+ poly289.ps[0] = Point(797.958, 1420.24);
+ poly289.ps[1] = Point(797.958, 1460.24);
+ poly289.ps[2] = Point(721.958, 1460.24);
+ poly289.ps[3] = Point(721.958, 1420.24);
+ new ShapeRef(router, poly289, 289);
+
+ Polygon poly290(4);
+ poly290.ps[0] = Point(1375.86, 1420.24);
+ poly290.ps[1] = Point(1375.86, 1460.24);
+ poly290.ps[2] = Point(1299.86, 1460.24);
+ poly290.ps[3] = Point(1299.86, 1420.24);
+ new ShapeRef(router, poly290, 290);
+
+ Polygon poly291(4);
+ poly291.ps[0] = Point(638.333, 2407.3);
+ poly291.ps[1] = Point(638.333, 2467.3);
+ poly291.ps[2] = Point(582.333, 2467.3);
+ poly291.ps[3] = Point(582.333, 2407.3);
+ new ShapeRef(router, poly291, 291);
+
+ Polygon poly292(4);
+ poly292.ps[0] = Point(696.333, 2592.3);
+ poly292.ps[1] = Point(696.333, 2632.3);
+ poly292.ps[2] = Point(620.333, 2632.3);
+ poly292.ps[3] = Point(620.333, 2592.3);
+ new ShapeRef(router, poly292, 292);
+
+ Polygon poly293(4);
+ poly293.ps[0] = Point(638.333, 3081.3);
+ poly293.ps[1] = Point(638.333, 3141.3);
+ poly293.ps[2] = Point(582.333, 3141.3);
+ poly293.ps[3] = Point(582.333, 3081.3);
+ new ShapeRef(router, poly293, 293);
+
+ Polygon poly294(4);
+ poly294.ps[0] = Point(1187.96, 2592.3);
+ poly294.ps[1] = Point(1187.96, 2632.3);
+ poly294.ps[2] = Point(1111.96, 2632.3);
+ poly294.ps[3] = Point(1111.96, 2592.3);
+ new ShapeRef(router, poly294, 294);
+
+ Polygon poly295(4);
+ poly295.ps[0] = Point(1305.96, 2592.3);
+ poly295.ps[1] = Point(1305.96, 2632.3);
+ poly295.ps[2] = Point(1229.96, 2632.3);
+ poly295.ps[3] = Point(1229.96, 2592.3);
+ new ShapeRef(router, poly295, 295);
+
+ Polygon poly296(4);
+ poly296.ps[0] = Point(1732.79, 2737.3);
+ poly296.ps[1] = Point(1732.79, 2777.3);
+ poly296.ps[2] = Point(1656.79, 2777.3);
+ poly296.ps[3] = Point(1656.79, 2737.3);
+ new ShapeRef(router, poly296, 296);
+
+ Polygon poly297(4);
+ poly297.ps[0] = Point(1649.6, 2668.3);
+ poly297.ps[1] = Point(1649.6, 2708.3);
+ poly297.ps[2] = Point(1573.6, 2708.3);
+ poly297.ps[3] = Point(1573.6, 2668.3);
+ new ShapeRef(router, poly297, 297);
+
+ Polygon poly298(4);
+ poly298.ps[0] = Point(1528.46, 2737.3);
+ poly298.ps[1] = Point(1528.46, 2777.3);
+ poly298.ps[2] = Point(1452.46, 2777.3);
+ poly298.ps[3] = Point(1452.46, 2737.3);
+ new ShapeRef(router, poly298, 298);
+
+ Polygon poly299(4);
+ poly299.ps[0] = Point(1732.79, 3120.3);
+ poly299.ps[1] = Point(1732.79, 3160.3);
+ poly299.ps[2] = Point(1656.79, 3160.3);
+ poly299.ps[3] = Point(1656.79, 3120.3);
+ new ShapeRef(router, poly299, 299);
+
+ Polygon poly300(4);
+ poly300.ps[0] = Point(1528.46, 3120.3);
+ poly300.ps[1] = Point(1528.46, 3160.3);
+ poly300.ps[2] = Point(1452.46, 3160.3);
+ poly300.ps[3] = Point(1452.46, 3120.3);
+ new ShapeRef(router, poly300, 300);
+
+ Polygon poly301(4);
+ poly301.ps[0] = Point(1649.6, 3051.3);
+ poly301.ps[1] = Point(1649.6, 3091.3);
+ poly301.ps[2] = Point(1573.6, 3091.3);
+ poly301.ps[3] = Point(1573.6, 3051.3);
+ new ShapeRef(router, poly301, 301);
+
+ Polygon poly302(4);
+ poly302.ps[0] = Point(2257.79, 2679.3);
+ poly302.ps[1] = Point(2257.79, 2739.3);
+ poly302.ps[2] = Point(2201.79, 2739.3);
+ poly302.ps[3] = Point(2201.79, 2679.3);
+ new ShapeRef(router, poly302, 302);
+
+ Polygon poly303(4);
+ poly303.ps[0] = Point(2420.71, 2592.3);
+ poly303.ps[1] = Point(2420.71, 2632.3);
+ poly303.ps[2] = Point(2344.71, 2632.3);
+ poly303.ps[3] = Point(2344.71, 2592.3);
+ new ShapeRef(router, poly303, 303);
+
+ Polygon poly304(4);
+ poly304.ps[0] = Point(2505.71, 2965.3);
+ poly304.ps[1] = Point(2505.71, 3025.3);
+ poly304.ps[2] = Point(2449.71, 3025.3);
+ poly304.ps[3] = Point(2449.71, 2965.3);
+ new ShapeRef(router, poly304, 304);
+
+ Polygon poly305(4);
+ poly305.ps[0] = Point(840.958, 2457.3);
+ poly305.ps[1] = Point(840.958, 2497.3);
+ poly305.ps[2] = Point(764.958, 2497.3);
+ poly305.ps[3] = Point(764.958, 2457.3);
+ new ShapeRef(router, poly305, 305);
+
+ Polygon poly306(4);
+ poly306.ps[0] = Point(986.958, 2407.3);
+ poly306.ps[1] = Point(986.958, 2467.3);
+ poly306.ps[2] = Point(930.958, 2467.3);
+ poly306.ps[3] = Point(930.958, 2407.3);
+ new ShapeRef(router, poly306, 306);
+
+ Polygon poly307(4);
+ poly307.ps[0] = Point(962.358, 2592.3);
+ poly307.ps[1] = Point(962.358, 2632.3);
+ poly307.ps[2] = Point(886.358, 2632.3);
+ poly307.ps[3] = Point(886.358, 2592.3);
+ new ShapeRef(router, poly307, 307);
+
+ Polygon poly308(4);
+ poly308.ps[0] = Point(962.358, 2737.3);
+ poly308.ps[1] = Point(962.358, 2777.3);
+ poly308.ps[2] = Point(886.358, 2777.3);
+ poly308.ps[3] = Point(886.358, 2737.3);
+ new ShapeRef(router, poly308, 308);
+
+ Polygon poly309(4);
+ poly309.ps[0] = Point(904.358, 3001.3);
+ poly309.ps[1] = Point(904.358, 3061.3);
+ poly309.ps[2] = Point(848.358, 3061.3);
+ poly309.ps[3] = Point(848.358, 3001.3);
+ new ShapeRef(router, poly309, 309);
+
+ Polygon poly310(4);
+ poly310.ps[0] = Point(2199.79, 971.643);
+ poly310.ps[1] = Point(2199.79, 1031.64);
+ poly310.ps[2] = Point(2143.79, 1031.64);
+ poly310.ps[3] = Point(2143.79, 971.643);
+ new ShapeRef(router, poly310, 310);
+
+ Polygon poly311(4);
+ poly311.ps[0] = Point(2505.71, 971.643);
+ poly311.ps[1] = Point(2505.71, 1031.64);
+ poly311.ps[2] = Point(2449.71, 1031.64);
+ poly311.ps[3] = Point(2449.71, 971.643);
+ new ShapeRef(router, poly311, 311);
+
+ Polygon poly312(4);
+ poly312.ps[0] = Point(2269.79, 1153.64);
+ poly312.ps[1] = Point(2269.79, 1213.64);
+ poly312.ps[2] = Point(2213.79, 1213.64);
+ poly312.ps[3] = Point(2213.79, 1153.64);
+ new ShapeRef(router, poly312, 312);
+
+ Polygon poly313(4);
+ poly313.ps[0] = Point(1797.79, 436.5);
+ poly313.ps[1] = Point(1797.79, 496.5);
+ poly313.ps[2] = Point(1741.79, 496.5);
+ poly313.ps[3] = Point(1741.79, 436.5);
+ new ShapeRef(router, poly313, 313);
+
+ Polygon poly314(4);
+ poly314.ps[0] = Point(1797.79, 587.5);
+ poly314.ps[1] = Point(1797.79, 647.5);
+ poly314.ps[2] = Point(1741.79, 647.5);
+ poly314.ps[3] = Point(1741.79, 587.5);
+ new ShapeRef(router, poly314, 314);
+
+ Polygon poly315(4);
+ poly315.ps[0] = Point(2127.79, 1256.24);
+ poly315.ps[1] = Point(2127.79, 1296.24);
+ poly315.ps[2] = Point(2051.79, 1296.24);
+ poly315.ps[3] = Point(2051.79, 1256.24);
+ new ShapeRef(router, poly315, 315);
+
+ Polygon poly316(4);
+ poly316.ps[0] = Point(409, 1105.24);
+ poly316.ps[1] = Point(409, 1145.24);
+ poly316.ps[2] = Point(333, 1145.24);
+ poly316.ps[3] = Point(333, 1105.24);
+ new ShapeRef(router, poly316, 316);
+
+ Polygon poly317(4);
+ poly317.ps[0] = Point(271, 1123.64);
+ poly317.ps[1] = Point(271, 1163.64);
+ poly317.ps[2] = Point(195, 1163.64);
+ poly317.ps[3] = Point(195, 1123.64);
+ new ShapeRef(router, poly317, 317);
+
+ Polygon poly318(4);
+ poly318.ps[0] = Point(551.333, 1123.64);
+ poly318.ps[1] = Point(551.333, 1163.64);
+ poly318.ps[2] = Point(475.333, 1163.64);
+ poly318.ps[3] = Point(475.333, 1123.64);
+ new ShapeRef(router, poly318, 318);
+
+ Polygon poly319(4);
+ poly319.ps[0] = Point(1810.79, 3331.3);
+ poly319.ps[1] = Point(1810.79, 3391.3);
+ poly319.ps[2] = Point(1754.79, 3391.3);
+ poly319.ps[3] = Point(1754.79, 3331.3);
+ new ShapeRef(router, poly319, 319);
+
+ Polygon poly320(4);
+ poly320.ps[0] = Point(1810.79, 3127.3);
+ poly320.ps[1] = Point(1810.79, 3187.3);
+ poly320.ps[2] = Point(1754.79, 3187.3);
+ poly320.ps[3] = Point(1754.79, 3127.3);
+ new ShapeRef(router, poly320, 320);
+
+ Polygon poly321(4);
+ poly321.ps[0] = Point(2803.54, 53.5);
+ poly321.ps[1] = Point(2803.54, 113.5);
+ poly321.ps[2] = Point(2747.54, 113.5);
+ poly321.ps[3] = Point(2747.54, 53.5);
+ new ShapeRef(router, poly321, 321);
+
+ Polygon poly322(4);
+ poly322.ps[0] = Point(1981.79, 2875.3);
+ poly322.ps[1] = Point(1981.79, 2935.3);
+ poly322.ps[2] = Point(1925.79, 2935.3);
+ poly322.ps[3] = Point(1925.79, 2875.3);
+ new ShapeRef(router, poly322, 322);
+
+ Polygon poly323(4);
+ poly323.ps[0] = Point(2199.79, 150.875);
+ poly323.ps[1] = Point(2199.79, 210.875);
+ poly323.ps[2] = Point(2143.79, 210.875);
+ poly323.ps[3] = Point(2143.79, 150.875);
+ new ShapeRef(router, poly323, 323);
+
+ Polygon poly324(4);
+ poly324.ps[0] = Point(1954.79, 1802.95);
+ poly324.ps[1] = Point(1954.79, 1862.95);
+ poly324.ps[2] = Point(1898.79, 1862.95);
+ poly324.ps[3] = Point(1898.79, 1802.95);
+ new ShapeRef(router, poly324, 324);
+
+ Polygon poly325(4);
+ poly325.ps[0] = Point(1492.46, 1802.95);
+ poly325.ps[1] = Point(1492.46, 1862.95);
+ poly325.ps[2] = Point(1436.46, 1862.95);
+ poly325.ps[3] = Point(1436.46, 1802.95);
+ new ShapeRef(router, poly325, 325);
+
+ Polygon poly326(4);
+ poly326.ps[0] = Point(1000.96, 1802.95);
+ poly326.ps[1] = Point(1000.96, 1862.95);
+ poly326.ps[2] = Point(944.958, 1862.95);
+ poly326.ps[3] = Point(944.958, 1802.95);
+ new ShapeRef(router, poly326, 326);
+
+ Polygon poly327(4);
+ poly327.ps[0] = Point(3079.24, 281.75);
+ poly327.ps[1] = Point(3079.24, 321.75);
+ poly327.ps[2] = Point(3003.24, 321.75);
+ poly327.ps[3] = Point(3003.24, 281.75);
+ new ShapeRef(router, poly327, 327);
+
+ Polygon poly328(4);
+ poly328.ps[0] = Point(2127.79, 2729.3);
+ poly328.ps[1] = Point(2127.79, 2769.3);
+ poly328.ps[2] = Point(2051.79, 2769.3);
+ poly328.ps[3] = Point(2051.79, 2729.3);
+ new ShapeRef(router, poly328, 328);
+
+ Polygon poly329(4);
+ poly329.ps[0] = Point(1947.79, 2729.3);
+ poly329.ps[1] = Point(1947.79, 2769.3);
+ poly329.ps[2] = Point(1871.79, 2769.3);
+ poly329.ps[3] = Point(1871.79, 2729.3);
+ new ShapeRef(router, poly329, 329);
+
+ Polygon poly330(4);
+ poly330.ps[0] = Point(1159.18, 688.5);
+ poly330.ps[1] = Point(1159.18, 728.5);
+ poly330.ps[2] = Point(1083.18, 728.5);
+ poly330.ps[3] = Point(1083.18, 688.5);
+ new ShapeRef(router, poly330, 330);
+
+ Polygon poly331(4);
+ poly331.ps[0] = Point(1257.46, 499.7);
+ poly331.ps[1] = Point(1257.46, 559.7);
+ poly331.ps[2] = Point(1201.46, 559.7);
+ poly331.ps[3] = Point(1201.46, 499.7);
+ new ShapeRef(router, poly331, 331);
+
+ Polygon poly332(4);
+ poly332.ps[0] = Point(962.358, 549.7);
+ poly332.ps[1] = Point(962.358, 589.7);
+ poly332.ps[2] = Point(886.358, 589.7);
+ poly332.ps[3] = Point(886.358, 549.7);
+ new ShapeRef(router, poly332, 332);
+
+ Polygon poly333(4);
+ poly333.ps[0] = Point(490.333, 492.5);
+ poly333.ps[1] = Point(490.333, 532.5);
+ poly333.ps[2] = Point(414.333, 532.5);
+ poly333.ps[3] = Point(414.333, 492.5);
+ new ShapeRef(router, poly333, 333);
+
+ Polygon poly334(4);
+ poly334.ps[0] = Point(2505.71, 2794.3);
+ poly334.ps[1] = Point(2505.71, 2854.3);
+ poly334.ps[2] = Point(2449.71, 2854.3);
+ poly334.ps[3] = Point(2449.71, 2794.3);
+ new ShapeRef(router, poly334, 334);
+
+ Polygon poly335(4);
+ poly335.ps[0] = Point(2938.99, 2542.3);
+ poly335.ps[1] = Point(2938.99, 2602.3);
+ poly335.ps[2] = Point(2882.99, 2602.3);
+ poly335.ps[3] = Point(2882.99, 2542.3);
+ new ShapeRef(router, poly335, 335);
+
+ Polygon poly336(4);
+ poly336.ps[0] = Point(3328.24, 2592.3);
+ poly336.ps[1] = Point(3328.24, 2632.3);
+ poly336.ps[2] = Point(3252.24, 2632.3);
+ poly336.ps[3] = Point(3252.24, 2592.3);
+ new ShapeRef(router, poly336, 336);
+
+ Polygon poly337(4);
+ poly337.ps[0] = Point(2912.99, 3001.3);
+ poly337.ps[1] = Point(2912.99, 3061.3);
+ poly337.ps[2] = Point(2856.99, 3061.3);
+ poly337.ps[3] = Point(2856.99, 3001.3);
+ new ShapeRef(router, poly337, 337);
+
+ Polygon poly338(4);
+ poly338.ps[0] = Point(3412.74, 3051.3);
+ poly338.ps[1] = Point(3412.74, 3091.3);
+ poly338.ps[2] = Point(3336.74, 3091.3);
+ poly338.ps[3] = Point(3336.74, 3051.3);
+ new ShapeRef(router, poly338, 338);
+
+ Polygon poly339(4);
+ poly339.ps[0] = Point(1810.79, 3229.3);
+ poly339.ps[1] = Point(1810.79, 3289.3);
+ poly339.ps[2] = Point(1754.79, 3289.3);
+ poly339.ps[3] = Point(1754.79, 3229.3);
+ new ShapeRef(router, poly339, 339);
+
+ Polygon poly340(4);
+ poly340.ps[0] = Point(1446.46, 172);
+ poly340.ps[1] = Point(1446.46, 232);
+ poly340.ps[2] = Point(1406.46, 232);
+ poly340.ps[3] = Point(1406.46, 172);
+ new ShapeRef(router, poly340, 340);
+
+ Polygon poly341(4);
+ poly341.ps[0] = Point(3101.74, 1542.44);
+ poly341.ps[1] = Point(3101.74, 1602.44);
+ poly341.ps[2] = Point(3061.74, 1602.44);
+ poly341.ps[3] = Point(3061.74, 1542.44);
+ new ShapeRef(router, poly341, 341);
+
+ Polygon poly342(4);
+ poly342.ps[0] = Point(3141.74, 1542.44);
+ poly342.ps[1] = Point(3141.74, 1602.44);
+ poly342.ps[2] = Point(3101.74, 1602.44);
+ poly342.ps[3] = Point(3101.74, 1542.44);
+ new ShapeRef(router, poly342, 342);
+
+ Polygon poly343(4);
+ poly343.ps[0] = Point(1962.3, 365);
+ poly343.ps[1] = Point(1962.3, 405);
+ poly343.ps[2] = Point(1902.3, 405);
+ poly343.ps[3] = Point(1902.3, 365);
+ new ShapeRef(router, poly343, 343);
+
+ Polygon poly344(4);
+ poly344.ps[0] = Point(1726.79, 1184.74);
+ poly344.ps[1] = Point(1726.79, 1224.74);
+ poly344.ps[2] = Point(1666.79, 1224.74);
+ poly344.ps[3] = Point(1666.79, 1184.74);
+ new ShapeRef(router, poly344, 344);
+
+ Polygon poly345(4);
+ poly345.ps[0] = Point(1923.79, 1184.74);
+ poly345.ps[1] = Point(1923.79, 1224.74);
+ poly345.ps[2] = Point(1863.79, 1224.74);
+ poly345.ps[3] = Point(1863.79, 1184.74);
+ new ShapeRef(router, poly345, 345);
+
+ Polygon poly346(4);
+ poly346.ps[0] = Point(1522.1, 2866.8);
+ poly346.ps[1] = Point(1522.1, 2906.8);
+ poly346.ps[2] = Point(1462.1, 2906.8);
+ poly346.ps[3] = Point(1462.1, 2866.8);
+ new ShapeRef(router, poly346, 346);
+
+ Polygon poly347(4);
+ poly347.ps[0] = Point(1395.6, 2799.8);
+ poly347.ps[1] = Point(1395.6, 2859.8);
+ poly347.ps[2] = Point(1355.6, 2859.8);
+ poly347.ps[3] = Point(1355.6, 2799.8);
+ new ShapeRef(router, poly347, 347);
+
+ Polygon poly348(4);
+ poly348.ps[0] = Point(1253.46, 326);
+ poly348.ps[1] = Point(1253.46, 386);
+ poly348.ps[2] = Point(1213.46, 386);
+ poly348.ps[3] = Point(1213.46, 326);
+ new ShapeRef(router, poly348, 348);
+
+ Polygon poly349(4);
+ poly349.ps[0] = Point(1315.36, 903);
+ poly349.ps[1] = Point(1315.36, 963);
+ poly349.ps[2] = Point(1275.36, 963);
+ poly349.ps[3] = Point(1275.36, 903);
+ new ShapeRef(router, poly349, 349);
+
+ Polygon poly350(4);
+ poly350.ps[0] = Point(2767.49, 1499.94);
+ poly350.ps[1] = Point(2767.49, 1539.94);
+ poly350.ps[2] = Point(2707.49, 1539.94);
+ poly350.ps[3] = Point(2707.49, 1499.94);
+ new ShapeRef(router, poly350, 350);
+
+ Polygon poly351(4);
+ poly351.ps[0] = Point(2627.04, 3113.8);
+ poly351.ps[1] = Point(2627.04, 3173.8);
+ poly351.ps[2] = Point(2587.04, 3173.8);
+ poly351.ps[3] = Point(2587.04, 3113.8);
+ new ShapeRef(router, poly351, 351);
+
+ Polygon poly352(4);
+ poly352.ps[0] = Point(2685.04, 2853.8);
+ poly352.ps[1] = Point(2685.04, 2893.8);
+ poly352.ps[2] = Point(2625.04, 2893.8);
+ poly352.ps[3] = Point(2625.04, 2853.8);
+ new ShapeRef(router, poly352, 352);
+
+ Polygon poly353(4);
+ poly353.ps[0] = Point(1823.33, 2280.88);
+ poly353.ps[1] = Point(1823.33, 2320.88);
+ poly353.ps[2] = Point(1763.33, 2320.88);
+ poly353.ps[3] = Point(1763.33, 2280.88);
+ new ShapeRef(router, poly353, 353);
+
+ ConnRef *connRef354 = new ConnRef(router, 354);
+ ConnEnd srcPt354(Point(1762.79, 157.5), 15);
+ connRef354->setSourceEndpoint(srcPt354);
+ ConnEnd dstPt354(Point(1927.29, 291.5), 4);
+ connRef354->setDestEndpoint(dstPt354);
+ connRef354->setRoutingType((ConnType)2);
+
+ ConnRef *connRef355 = new ConnRef(router, 355);
+ ConnEnd srcPt355(Point(1395.46, 693.5), 1);
+ connRef355->setSourceEndpoint(srcPt355);
+ ConnEnd dstPt355(Point(1385.86, 569.7), 15);
+ connRef355->setDestEndpoint(dstPt355);
+ connRef355->setRoutingType((ConnType)2);
+
+ ConnRef *connRef356 = new ConnRef(router, 356);
+ ConnEnd srcPt356(Point(1385.86, 569.7), 15);
+ connRef356->setSourceEndpoint(srcPt356);
+ ConnEnd dstPt356(Point(1527.46, 291.5), 4);
+ connRef356->setDestEndpoint(dstPt356);
+ connRef356->setRoutingType((ConnType)2);
+
+ ConnRef *connRef357 = new ConnRef(router, 357);
+ ConnEnd srcPt357(Point(1754.79, 506.5), 4);
+ connRef357->setSourceEndpoint(srcPt357);
+ ConnEnd dstPt357(Point(1385.86, 569.7), 15);
+ connRef357->setDestEndpoint(dstPt357);
+ connRef357->setRoutingType((ConnType)2);
+
+ ConnRef *connRef358 = new ConnRef(router, 358);
+ ConnEnd srcPt358(Point(1754.79, 577.5), 4);
+ connRef358->setSourceEndpoint(srcPt358);
+ ConnEnd dstPt358(Point(1385.86, 569.7), 15);
+ connRef358->setDestEndpoint(dstPt358);
+ connRef358->setRoutingType((ConnType)2);
+
+ ConnRef *connRef359 = new ConnRef(router, 359);
+ ConnEnd srcPt359(Point(1244.46, 569.7), 8);
+ connRef359->setSourceEndpoint(srcPt359);
+ ConnEnd dstPt359(Point(1385.86, 569.7), 15);
+ connRef359->setDestEndpoint(dstPt359);
+ connRef359->setRoutingType((ConnType)2);
+
+ ConnRef *connRef360 = new ConnRef(router, 360);
+ ConnEnd srcPt360(Point(1957.29, 291.5), 8);
+ connRef360->setSourceEndpoint(srcPt360);
+ ConnEnd dstPt360(Point(2041.79, 569.7), 15);
+ connRef360->setDestEndpoint(dstPt360);
+ connRef360->setRoutingType((ConnType)2);
+
+ ConnRef *connRef361 = new ConnRef(router, 361);
+ ConnEnd srcPt361(Point(2041.79, 569.7), 15);
+ connRef361->setSourceEndpoint(srcPt361);
+ ConnEnd dstPt361(Point(2041.79, 777.5), 8);
+ connRef361->setDestEndpoint(dstPt361);
+ connRef361->setRoutingType((ConnType)2);
+
+ ConnRef *connRef362 = new ConnRef(router, 362);
+ ConnEnd srcPt362(Point(2241.79, 693.5), 1);
+ connRef362->setSourceEndpoint(srcPt362);
+ ConnEnd dstPt362(Point(2041.79, 569.7), 15);
+ connRef362->setDestEndpoint(dstPt362);
+ connRef362->setRoutingType((ConnType)2);
+
+ ConnRef *connRef363 = new ConnRef(router, 363);
+ ConnEnd srcPt363(Point(2547.71, 693.5), 1);
+ connRef363->setSourceEndpoint(srcPt363);
+ ConnEnd dstPt363(Point(2041.79, 569.7), 15);
+ connRef363->setDestEndpoint(dstPt363);
+ connRef363->setRoutingType((ConnType)2);
+
+ ConnRef *connRef364 = new ConnRef(router, 364);
+ ConnEnd srcPt364(Point(2041.79, 569.7), 15);
+ connRef364->setSourceEndpoint(srcPt364);
+ ConnEnd dstPt364(Point(2787.54, 693.5), 1);
+ connRef364->setDestEndpoint(dstPt364);
+ connRef364->setRoutingType((ConnType)2);
+
+ ConnRef *connRef365 = new ConnRef(router, 365);
+ ConnEnd srcPt365(Point(2041.79, 569.7), 15);
+ connRef365->setSourceEndpoint(srcPt365);
+ ConnEnd dstPt365(Point(2968.99, 693.5), 1);
+ connRef365->setDestEndpoint(dstPt365);
+ connRef365->setRoutingType((ConnType)2);
+
+ ConnRef *connRef366 = new ConnRef(router, 366);
+ ConnEnd srcPt366(Point(2241.79, 316.75), 2);
+ connRef366->setSourceEndpoint(srcPt366);
+ ConnEnd dstPt366(Point(2041.79, 569.7), 15);
+ connRef366->setDestEndpoint(dstPt366);
+ connRef366->setRoutingType((ConnType)2);
+
+ ConnRef *connRef367 = new ConnRef(router, 367);
+ ConnEnd srcPt367(Point(2041.79, 569.7), 15);
+ connRef367->setSourceEndpoint(srcPt367);
+ ConnEnd dstPt367(Point(3463.07, 914.5), 4);
+ connRef367->setDestEndpoint(dstPt367);
+ connRef367->setRoutingType((ConnType)2);
+
+ ConnRef *connRef368 = new ConnRef(router, 368);
+ ConnEnd srcPt368(Point(2041.79, 569.7), 15);
+ connRef368->setSourceEndpoint(srcPt368);
+ ConnEnd dstPt368(Point(3596.07, 899.5), 1);
+ connRef368->setDestEndpoint(dstPt368);
+ connRef368->setRoutingType((ConnType)2);
+
+ ConnRef *connRef369 = new ConnRef(router, 369);
+ ConnEnd srcPt369(Point(2041.79, 569.7), 15);
+ connRef369->setSourceEndpoint(srcPt369);
+ ConnEnd dstPt369(Point(3326.74, 899.5), 1);
+ connRef369->setDestEndpoint(dstPt369);
+ connRef369->setRoutingType((ConnType)2);
+
+ ConnRef *connRef370 = new ConnRef(router, 370);
+ ConnEnd srcPt370(Point(2041.79, 569.7), 15);
+ connRef370->setSourceEndpoint(srcPt370);
+ ConnEnd dstPt370(Point(3201.44, 914.5), 4);
+ connRef370->setDestEndpoint(dstPt370);
+ connRef370->setRoutingType((ConnType)2);
+
+ ConnRef *connRef371 = new ConnRef(router, 371);
+ ConnEnd srcPt371(Point(1784.79, 506.5), 8);
+ connRef371->setSourceEndpoint(srcPt371);
+ ConnEnd dstPt371(Point(2041.79, 569.7), 15);
+ connRef371->setDestEndpoint(dstPt371);
+ connRef371->setRoutingType((ConnType)2);
+
+ ConnRef *connRef372 = new ConnRef(router, 372);
+ ConnEnd srcPt372(Point(1784.79, 577.5), 8);
+ connRef372->setSourceEndpoint(srcPt372);
+ ConnEnd dstPt372(Point(2041.79, 569.7), 15);
+ connRef372->setDestEndpoint(dstPt372);
+ connRef372->setRoutingType((ConnType)2);
+
+ ConnRef *connRef373 = new ConnRef(router, 373);
+ ConnEnd srcPt373(Point(1563.6, 978.5), 15);
+ connRef373->setSourceEndpoint(srcPt373);
+ ConnEnd dstPt373(Point(1395.46, 723.5), 2);
+ connRef373->setDestEndpoint(dstPt373);
+ connRef373->setRoutingType((ConnType)2);
+
+ ConnRef *connRef374 = new ConnRef(router, 374);
+ ConnEnd srcPt374(Point(2011.79, 777.5), 4);
+ connRef374->setSourceEndpoint(srcPt374);
+ ConnEnd dstPt374(Point(1563.6, 978.5), 15);
+ connRef374->setDestEndpoint(dstPt374);
+ connRef374->setRoutingType((ConnType)2);
+
+ ConnRef *connRef375 = new ConnRef(router, 375);
+ ConnEnd srcPt375(Point(1400.86, 969.5), 8);
+ connRef375->setSourceEndpoint(srcPt375);
+ ConnEnd dstPt375(Point(1563.6, 978.5), 15);
+ connRef375->setDestEndpoint(dstPt375);
+ connRef375->setRoutingType((ConnType)2);
+
+ ConnRef *connRef376 = new ConnRef(router, 376);
+ ConnEnd srcPt376(Point(1400.86, 1041.64), 8);
+ connRef376->setSourceEndpoint(srcPt376);
+ ConnEnd dstPt376(Point(1563.6, 978.5), 15);
+ connRef376->setDestEndpoint(dstPt376);
+ connRef376->setRoutingType((ConnType)2);
+
+ ConnRef *connRef377 = new ConnRef(router, 377);
+ ConnEnd srcPt377(Point(1400.86, 1143.64), 8);
+ connRef377->setSourceEndpoint(srcPt377);
+ ConnEnd dstPt377(Point(1563.6, 978.5), 15);
+ connRef377->setDestEndpoint(dstPt377);
+ connRef377->setRoutingType((ConnType)2);
+
+ ConnRef *connRef378 = new ConnRef(router, 378);
+ ConnEnd srcPt378(Point(1646.79, 1261.24), 1);
+ connRef378->setSourceEndpoint(srcPt378);
+ ConnEnd dstPt378(Point(1563.6, 978.5), 15);
+ connRef378->setDestEndpoint(dstPt378);
+ connRef378->setRoutingType((ConnType)2);
+
+ ConnRef *connRef379 = new ConnRef(router, 379);
+ ConnEnd srcPt379(Point(1563.6, 978.5), 15);
+ connRef379->setSourceEndpoint(srcPt379);
+ ConnEnd dstPt379(Point(1563.6, 2008.95), 1);
+ connRef379->setDestEndpoint(dstPt379);
+ connRef379->setRoutingType((ConnType)2);
+
+ ConnRef *connRef380 = new ConnRef(router, 380);
+ ConnEnd srcPt380(Point(2041.79, 1261.24), 1);
+ connRef380->setSourceEndpoint(srcPt380);
+ ConnEnd dstPt380(Point(1563.6, 978.5), 15);
+ connRef380->setDestEndpoint(dstPt380);
+ connRef380->setRoutingType((ConnType)2);
+
+ ConnRef *connRef381 = new ConnRef(router, 381);
+ ConnEnd srcPt381(Point(555.333, 708.5), 8);
+ connRef381->setSourceEndpoint(srcPt381);
+ ConnEnd dstPt381(Point(610.333, 833.833), 15);
+ connRef381->setDestEndpoint(dstPt381);
+ connRef381->setRoutingType((ConnType)2);
+
+ ConnRef *connRef382 = new ConnRef(router, 382);
+ ConnEnd srcPt382(Point(555.333, 833.833), 8);
+ connRef382->setSourceEndpoint(srcPt382);
+ ConnEnd dstPt382(Point(610.333, 833.833), 15);
+ connRef382->setDestEndpoint(dstPt382);
+ connRef382->setRoutingType((ConnType)2);
+
+ ConnRef *connRef383 = new ConnRef(router, 383);
+ ConnEnd srcPt383(Point(610.333, 833.833), 15);
+ connRef383->setSourceEndpoint(srcPt383);
+ ConnEnd dstPt383(Point(1395.46, 723.5), 2);
+ connRef383->setDestEndpoint(dstPt383);
+ connRef383->setRoutingType((ConnType)2);
+
+ ConnRef *connRef384 = new ConnRef(router, 384);
+ ConnEnd srcPt384(Point(610.333, 833.833), 15);
+ connRef384->setSourceEndpoint(srcPt384);
+ ConnEnd dstPt384(Point(1073.18, 723.5), 2);
+ connRef384->setDestEndpoint(dstPt384);
+ connRef384->setRoutingType((ConnType)2);
+
+ ConnRef *connRef385 = new ConnRef(router, 385);
+ ConnEnd srcPt385(Point(610.333, 833.833), 15);
+ connRef385->setSourceEndpoint(srcPt385);
+ ConnEnd dstPt385(Point(876.358, 584.7), 2);
+ connRef385->setDestEndpoint(dstPt385);
+ connRef385->setRoutingType((ConnType)2);
+
+ ConnRef *connRef386 = new ConnRef(router, 386);
+ ConnEnd srcPt386(Point(390.333, 2399.05), 15);
+ connRef386->setSourceEndpoint(srcPt386);
+ ConnEnd dstPt386(Point(525.333, 1276.24), 4);
+ connRef386->setDestEndpoint(dstPt386);
+ connRef386->setRoutingType((ConnType)2);
+
+ ConnRef *connRef387 = new ConnRef(router, 387);
+ ConnEnd srcPt387(Point(696.958, 2185.05), 4);
+ connRef387->setSourceEndpoint(srcPt387);
+ ConnEnd dstPt387(Point(390.333, 2399.05), 15);
+ connRef387->setDestEndpoint(dstPt387);
+ connRef387->setRoutingType((ConnType)2);
+
+ ConnRef *connRef388 = new ConnRef(router, 388);
+ ConnEnd srcPt388(Point(696.958, 1378.24), 4);
+ connRef388->setSourceEndpoint(srcPt388);
+ ConnEnd dstPt388(Point(390.333, 2399.05), 15);
+ connRef388->setDestEndpoint(dstPt388);
+ connRef388->setRoutingType((ConnType)2);
+
+ ConnRef *connRef389 = new ConnRef(router, 389);
+ ConnEnd srcPt389(Point(390.333, 2399.05), 15);
+ connRef389->setSourceEndpoint(srcPt389);
+ ConnEnd dstPt389(Point(711.958, 1455.24), 2);
+ connRef389->setDestEndpoint(dstPt389);
+ connRef389->setRoutingType((ConnType)2);
+
+ ConnRef *connRef390 = new ConnRef(router, 390);
+ ConnEnd srcPt390(Point(390.333, 2399.05), 15);
+ connRef390->setSourceEndpoint(srcPt390);
+ ConnEnd dstPt390(Point(625.333, 2477.3), 8);
+ connRef390->setDestEndpoint(dstPt390);
+ connRef390->setRoutingType((ConnType)2);
+
+ ConnRef *connRef391 = new ConnRef(router, 391);
+ ConnEnd srcPt391(Point(625.333, 3071.3), 8);
+ connRef391->setSourceEndpoint(srcPt391);
+ ConnEnd dstPt391(Point(390.333, 2399.05), 15);
+ connRef391->setDestEndpoint(dstPt391);
+ connRef391->setRoutingType((ConnType)2);
+
+ ConnRef *connRef392 = new ConnRef(router, 392);
+ ConnEnd srcPt392(Point(323, 1140.24), 2);
+ connRef392->setSourceEndpoint(srcPt392);
+ ConnEnd dstPt392(Point(390.333, 2399.05), 15);
+ connRef392->setDestEndpoint(dstPt392);
+ connRef392->setRoutingType((ConnType)2);
+
+ ConnRef *connRef393 = new ConnRef(router, 393);
+ ConnEnd srcPt393(Point(281, 1158.64), 2);
+ connRef393->setSourceEndpoint(srcPt393);
+ ConnEnd dstPt393(Point(390.333, 2399.05), 15);
+ connRef393->setDestEndpoint(dstPt393);
+ connRef393->setRoutingType((ConnType)2);
+
+ ConnRef *connRef394 = new ConnRef(router, 394);
+ ConnEnd srcPt394(Point(465.333, 1158.64), 2);
+ connRef394->setSourceEndpoint(srcPt394);
+ ConnEnd dstPt394(Point(390.333, 2399.05), 15);
+ connRef394->setDestEndpoint(dstPt394);
+ connRef394->setRoutingType((ConnType)2);
+
+ ConnRef *connRef395 = new ConnRef(router, 395);
+ ConnEnd srcPt395(Point(1523.87, 1631.77), 15);
+ connRef395->setSourceEndpoint(srcPt395);
+ ConnEnd dstPt395(Point(390.333, 2399.05), 15);
+ connRef395->setDestEndpoint(dstPt395);
+ connRef395->setRoutingType((ConnType)2);
+
+ ConnRef *connRef396 = new ConnRef(router, 396);
+ ConnEnd srcPt396(Point(3201.44, 2399.05), 4);
+ connRef396->setSourceEndpoint(srcPt396);
+ ConnEnd dstPt396(Point(1563.6, 2399.05), 15);
+ connRef396->setDestEndpoint(dstPt396);
+ connRef396->setRoutingType((ConnType)2);
+
+ ConnRef *connRef397 = new ConnRef(router, 397);
+ ConnEnd srcPt397(Point(2772.54, 2297.05), 4);
+ connRef397->setSourceEndpoint(srcPt397);
+ ConnEnd dstPt397(Point(1563.6, 2399.05), 15);
+ connRef397->setDestEndpoint(dstPt397);
+ connRef397->setRoutingType((ConnType)2);
+
+ ConnRef *connRef398 = new ConnRef(router, 398);
+ ConnEnd srcPt398(Point(1563.6, 2038.95), 2);
+ connRef398->setSourceEndpoint(srcPt398);
+ ConnEnd dstPt398(Point(1563.6, 2399.05), 15);
+ connRef398->setDestEndpoint(dstPt398);
+ connRef398->setRoutingType((ConnType)2);
+
+ ConnRef *connRef399 = new ConnRef(router, 399);
+ ConnEnd srcPt399(Point(1563.6, 2399.05), 15);
+ connRef399->setSourceEndpoint(srcPt399);
+ ConnEnd dstPt399(Point(625.333, 2477.3), 8);
+ connRef399->setDestEndpoint(dstPt399);
+ connRef399->setRoutingType((ConnType)2);
+
+ ConnRef *connRef400 = new ConnRef(router, 400);
+ ConnEnd srcPt400(Point(1563.6, 2399.05), 15);
+ connRef400->setSourceEndpoint(srcPt400);
+ ConnEnd dstPt400(Point(1646.79, 2742.3), 1);
+ connRef400->setDestEndpoint(dstPt400);
+ connRef400->setRoutingType((ConnType)2);
+
+ ConnRef *connRef401 = new ConnRef(router, 401);
+ ConnEnd srcPt401(Point(1563.6, 2399.05), 15);
+ connRef401->setSourceEndpoint(srcPt401);
+ ConnEnd dstPt401(Point(2214.79, 2749.3), 4);
+ connRef401->setDestEndpoint(dstPt401);
+ connRef401->setRoutingType((ConnType)2);
+
+ ConnRef *connRef402 = new ConnRef(router, 402);
+ ConnEnd srcPt402(Point(1563.6, 2399.05), 15);
+ connRef402->setSourceEndpoint(srcPt402);
+ ConnEnd dstPt402(Point(850.958, 2462.3), 1);
+ connRef402->setDestEndpoint(dstPt402);
+ connRef402->setRoutingType((ConnType)2);
+
+ ConnRef *connRef403 = new ConnRef(router, 403);
+ ConnEnd srcPt403(Point(1563.6, 2399.05), 15);
+ connRef403->setSourceEndpoint(srcPt403);
+ ConnEnd dstPt403(Point(973.958, 2477.3), 8);
+ connRef403->setDestEndpoint(dstPt403);
+ connRef403->setRoutingType((ConnType)2);
+
+ ConnRef *connRef404 = new ConnRef(router, 404);
+ ConnEnd srcPt404(Point(1563.6, 2399.05), 15);
+ connRef404->setSourceEndpoint(srcPt404);
+ ConnEnd dstPt404(Point(2895.99, 2612.3), 4);
+ connRef404->setDestEndpoint(dstPt404);
+ connRef404->setRoutingType((ConnType)2);
+
+ ConnRef *connRef405 = new ConnRef(router, 405);
+ ConnEnd srcPt405(Point(1563.6, 2399.05), 15);
+ connRef405->setSourceEndpoint(srcPt405);
+ ConnEnd dstPt405(Point(2869.99, 3071.3), 4);
+ connRef405->setDestEndpoint(dstPt405);
+ connRef405->setRoutingType((ConnType)2);
+
+ ConnRef *connRef406 = new ConnRef(router, 406);
+ ConnEnd srcPt406(Point(726.958, 1378.24), 8);
+ connRef406->setSourceEndpoint(srcPt406);
+ ConnEnd dstPt406(Point(1782.79, 1378.24), 15);
+ connRef406->setDestEndpoint(dstPt406);
+ connRef406->setRoutingType((ConnType)2);
+
+ ConnRef *connRef407 = new ConnRef(router, 407);
+ ConnEnd srcPt407(Point(1782.79, 1569.64), 15);
+ connRef407->setSourceEndpoint(srcPt407);
+ ConnEnd dstPt407(Point(1385.86, 1455.24), 2);
+ connRef407->setDestEndpoint(dstPt407);
+ connRef407->setRoutingType((ConnType)2);
+
+ ConnRef *connRef408 = new ConnRef(router, 408);
+ ConnEnd srcPt408(Point(1919.87, 1601.64), 15);
+ connRef408->setSourceEndpoint(srcPt408);
+ ConnEnd dstPt408(Point(2041.79, 1569.64), 15);
+ connRef408->setDestEndpoint(dstPt408);
+ connRef408->setRoutingType((ConnType)2);
+
+ ConnRef *connRef409 = new ConnRef(router, 409);
+ ConnEnd srcPt409(Point(2041.79, 1569.64), 15);
+ connRef409->setSourceEndpoint(srcPt409);
+ ConnEnd dstPt409(Point(1941.79, 1653.64), 8);
+ connRef409->setDestEndpoint(dstPt409);
+ connRef409->setRoutingType((ConnType)2);
+
+ ConnRef *connRef410 = new ConnRef(router, 410);
+ ConnEnd srcPt410(Point(1958.29, 1455.24), 2);
+ connRef410->setSourceEndpoint(srcPt410);
+ ConnEnd dstPt410(Point(2041.79, 1569.64), 15);
+ connRef410->setDestEndpoint(dstPt410);
+ connRef410->setRoutingType((ConnType)2);
+
+ ConnRef *connRef411 = new ConnRef(router, 411);
+ ConnEnd srcPt411(Point(2041.79, 1569.64), 15);
+ connRef411->setSourceEndpoint(srcPt411);
+ ConnEnd dstPt411(Point(2041.79, 1707.64), 1);
+ connRef411->setDestEndpoint(dstPt411);
+ connRef411->setRoutingType((ConnType)2);
+
+ ConnRef *connRef412 = new ConnRef(router, 412);
+ ConnEnd srcPt412(Point(2041.79, 1569.64), 15);
+ connRef412->setSourceEndpoint(srcPt412);
+ ConnEnd dstPt412(Point(2156.79, 1569.64), 4);
+ connRef412->setDestEndpoint(dstPt412);
+ connRef412->setRoutingType((ConnType)2);
+
+ ConnRef *connRef413 = new ConnRef(router, 413);
+ ConnEnd srcPt413(Point(2041.79, 1569.64), 15);
+ connRef413->setSourceEndpoint(srcPt413);
+ ConnEnd dstPt413(Point(2028.87, 1507.64), 15);
+ connRef413->setDestEndpoint(dstPt413);
+ connRef413->setRoutingType((ConnType)2);
+
+ ConnRef *connRef414 = new ConnRef(router, 414);
+ ConnEnd srcPt414(Point(1976.87, 1934.95), 15);
+ connRef414->setSourceEndpoint(srcPt414);
+ ConnEnd dstPt414(Point(2041.79, 1872.95), 15);
+ connRef414->setDestEndpoint(dstPt414);
+ connRef414->setRoutingType((ConnType)2);
+
+ ConnRef *connRef415 = new ConnRef(router, 415);
+ ConnEnd srcPt415(Point(2041.79, 1737.64), 2);
+ connRef415->setSourceEndpoint(srcPt415);
+ ConnEnd dstPt415(Point(2041.79, 1872.95), 15);
+ connRef415->setDestEndpoint(dstPt415);
+ connRef415->setRoutingType((ConnType)2);
+ */
+
+ ConnRef *connRef416 = new ConnRef(router, 416);
+ ConnEnd srcPt416(Point(2041.79, 1872.95), 15);
+ connRef416->setSourceEndpoint(srcPt416);
+ ConnEnd dstPt416(Point(2156.79, 1872.95), 4);
+ connRef416->setDestEndpoint(dstPt416);
+ connRef416->setRoutingType((ConnType)2);
+
+ /*
+ ConnRef *connRef417 = new ConnRef(router, 417);
+ ConnEnd srcPt417(Point(2111.79, 1884.95), 15);
+ connRef417->setSourceEndpoint(srcPt417);
+ ConnEnd dstPt417(Point(2041.79, 1872.95), 15);
+ connRef417->setDestEndpoint(dstPt417);
+ connRef417->setRoutingType((ConnType)2);
+
+ ConnRef *connRef418 = new ConnRef(router, 418);
+ ConnEnd srcPt418(Point(1941.79, 1872.95), 8);
+ connRef418->setSourceEndpoint(srcPt418);
+ ConnEnd dstPt418(Point(2041.79, 1872.95), 15);
+ connRef418->setDestEndpoint(dstPt418);
+ connRef418->setRoutingType((ConnType)2);
+
+ ConnRef *connRef419 = new ConnRef(router, 419);
+ ConnEnd srcPt419(Point(2189.79, 1733.77), 15);
+ connRef419->setSourceEndpoint(srcPt419);
+ ConnEnd dstPt419(Point(2547.71, 1872.95), 15);
+ connRef419->setDestEndpoint(dstPt419);
+ connRef419->setRoutingType((ConnType)2);
+
+ ConnRef *connRef420 = new ConnRef(router, 420);
+ ConnEnd srcPt420(Point(2492.71, 2013.95), 8);
+ connRef420->setSourceEndpoint(srcPt420);
+ ConnEnd dstPt420(Point(2547.71, 1872.95), 15);
+ connRef420->setDestEndpoint(dstPt420);
+ connRef420->setRoutingType((ConnType)2);
+
+ ConnRef *connRef421 = new ConnRef(router, 421);
+ ConnEnd srcPt421(Point(2492.71, 2055.95), 8);
+ connRef421->setSourceEndpoint(srcPt421);
+ ConnEnd dstPt421(Point(2547.71, 1872.95), 15);
+ connRef421->setDestEndpoint(dstPt421);
+ connRef421->setRoutingType((ConnType)2);
+
+ ConnRef *connRef422 = new ConnRef(router, 422);
+ ConnEnd srcPt422(Point(2547.71, 1872.95), 15);
+ connRef422->setSourceEndpoint(srcPt422);
+ ConnEnd dstPt422(Point(2645.54, 1812.64), 4);
+ connRef422->setDestEndpoint(dstPt422);
+ connRef422->setRoutingType((ConnType)2);
+
+ ConnRef *connRef423 = new ConnRef(router, 423);
+ ConnEnd srcPt423(Point(2547.71, 1872.95), 15);
+ connRef423->setSourceEndpoint(srcPt423);
+ ConnEnd dstPt423(Point(2622.54, 1884.95), 4);
+ connRef423->setDestEndpoint(dstPt423);
+ connRef423->setRoutingType((ConnType)2);
+
+ ConnRef *connRef424 = new ConnRef(router, 424);
+ ConnEnd srcPt424(Point(2547.71, 1872.95), 15);
+ connRef424->setSourceEndpoint(srcPt424);
+ ConnEnd dstPt424(Point(2720.54, 1884.95), 4);
+ connRef424->setDestEndpoint(dstPt424);
+ connRef424->setRoutingType((ConnType)2);
+
+ ConnRef *connRef425 = new ConnRef(router, 425);
+ ConnEnd srcPt425(Point(2787.54, 1872.95), 15);
+ connRef425->setSourceEndpoint(srcPt425);
+ ConnEnd dstPt425(Point(2883.99, 1812.64), 4);
+ connRef425->setDestEndpoint(dstPt425);
+ connRef425->setRoutingType((ConnType)2);
+
+ ConnRef *connRef426 = new ConnRef(router, 426);
+ ConnEnd srcPt426(Point(2787.54, 1872.95), 15);
+ connRef426->setSourceEndpoint(srcPt426);
+ ConnEnd dstPt426(Point(2860.99, 1884.95), 4);
+ connRef426->setDestEndpoint(dstPt426);
+ connRef426->setRoutingType((ConnType)2);
+
+ ConnRef *connRef427 = new ConnRef(router, 427);
+ ConnEnd srcPt427(Point(2787.54, 1872.95), 15);
+ connRef427->setSourceEndpoint(srcPt427);
+ ConnEnd dstPt427(Point(2938.99, 1884.95), 4);
+ connRef427->setDestEndpoint(dstPt427);
+ connRef427->setRoutingType((ConnType)2);
+
+ ConnRef *connRef428 = new ConnRef(router, 428);
+ ConnEnd srcPt428(Point(1315.96, 312.5), 15);
+ connRef428->setSourceEndpoint(srcPt428);
+ ConnEnd dstPt428(Point(1527.46, 291.5), 4);
+ connRef428->setDestEndpoint(dstPt428);
+ connRef428->setRoutingType((ConnType)2);
+
+ ConnRef *connRef429 = new ConnRef(router, 429);
+ ConnEnd srcPt429(Point(3216.44, 2185.05), 15);
+ connRef429->setSourceEndpoint(srcPt429);
+ ConnEnd dstPt429(Point(2802.54, 2185.05), 8);
+ connRef429->setDestEndpoint(dstPt429);
+ connRef429->setRoutingType((ConnType)2);
+
+ ConnRef *connRef430 = new ConnRef(router, 430);
+ ConnEnd srcPt430(Point(2772.54, 2185.05), 4);
+ connRef430->setSourceEndpoint(srcPt430);
+ ConnEnd dstPt430(Point(2547.71, 2185.05), 15);
+ connRef430->setDestEndpoint(dstPt430);
+ connRef430->setRoutingType((ConnType)2);
+
+ ConnRef *connRef431 = new ConnRef(router, 431);
+ ConnEnd srcPt431(Point(2547.71, 2185.05), 15);
+ connRef431->setSourceEndpoint(srcPt431);
+ ConnEnd dstPt431(Point(2414.71, 2185.05), 8);
+ connRef431->setDestEndpoint(dstPt431);
+ connRef431->setRoutingType((ConnType)2);
+
+ ConnRef *connRef432 = new ConnRef(router, 432);
+ ConnEnd srcPt432(Point(1911.79, 2185.05), 4);
+ connRef432->setSourceEndpoint(srcPt432);
+ ConnEnd dstPt432(Point(1073.18, 2185.05), 15);
+ connRef432->setDestEndpoint(dstPt432);
+ connRef432->setRoutingType((ConnType)2);
+
+ ConnRef *connRef433 = new ConnRef(router, 433);
+ ConnEnd srcPt433(Point(1073.18, 2185.05), 15);
+ connRef433->setSourceEndpoint(srcPt433);
+ ConnEnd dstPt433(Point(726.958, 2185.05), 8);
+ connRef433->setDestEndpoint(dstPt433);
+ connRef433->setRoutingType((ConnType)2);
+
+ ConnRef *connRef434 = new ConnRef(router, 434);
+ ConnEnd srcPt434(Point(1073.18, 1440.24), 15);
+ connRef434->setSourceEndpoint(srcPt434);
+ ConnEnd dstPt434(Point(1385.86, 1455.24), 2);
+ connRef434->setDestEndpoint(dstPt434);
+ connRef434->setRoutingType((ConnType)2);
+
+ ConnRef *connRef435 = new ConnRef(router, 435);
+ ConnEnd srcPt435(Point(323, 833.833), 15);
+ connRef435->setSourceEndpoint(srcPt435);
+ ConnEnd dstPt435(Point(131, 663.5), 2);
+ connRef435->setDestEndpoint(dstPt435);
+ connRef435->setRoutingType((ConnType)2);
+
+ ConnRef *connRef436 = new ConnRef(router, 436);
+ ConnEnd srcPt436(Point(525.333, 708.5), 4);
+ connRef436->setSourceEndpoint(srcPt436);
+ ConnEnd dstPt436(Point(323, 833.833), 15);
+ connRef436->setDestEndpoint(dstPt436);
+ connRef436->setRoutingType((ConnType)2);
+
+ ConnRef *connRef437 = new ConnRef(router, 437);
+ ConnEnd srcPt437(Point(323, 833.833), 15);
+ connRef437->setSourceEndpoint(srcPt437);
+ ConnEnd dstPt437(Point(525.333, 833.833), 4);
+ connRef437->setDestEndpoint(dstPt437);
+ connRef437->setRoutingType((ConnType)2);
+
+ ConnRef *connRef438 = new ConnRef(router, 438);
+ ConnEnd srcPt438(Point(323, 1110.24), 1);
+ connRef438->setSourceEndpoint(srcPt438);
+ ConnEnd dstPt438(Point(323, 833.833), 15);
+ connRef438->setDestEndpoint(dstPt438);
+ connRef438->setRoutingType((ConnType)2);
+
+ ConnRef *connRef439 = new ConnRef(router, 439);
+ ConnEnd srcPt439(Point(281, 1128.64), 1);
+ connRef439->setSourceEndpoint(srcPt439);
+ ConnEnd dstPt439(Point(323, 833.833), 15);
+ connRef439->setDestEndpoint(dstPt439);
+ connRef439->setRoutingType((ConnType)2);
+
+ ConnRef *connRef440 = new ConnRef(router, 440);
+ ConnEnd srcPt440(Point(465.333, 1128.64), 1);
+ connRef440->setSourceEndpoint(srcPt440);
+ ConnEnd dstPt440(Point(323, 833.833), 15);
+ connRef440->setDestEndpoint(dstPt440);
+ connRef440->setRoutingType((ConnType)2);
+
+ ConnRef *connRef441 = new ConnRef(router, 441);
+ ConnEnd srcPt441(Point(610.333, 1276.24), 15);
+ connRef441->setSourceEndpoint(srcPt441);
+ ConnEnd dstPt441(Point(696.958, 1276.24), 4);
+ connRef441->setDestEndpoint(dstPt441);
+ connRef441->setRoutingType((ConnType)2);
+
+ ConnRef *connRef442 = new ConnRef(router, 442);
+ ConnEnd srcPt442(Point(876.358, 1276.24), 15);
+ connRef442->setSourceEndpoint(srcPt442);
+ ConnEnd dstPt442(Point(957.958, 1276.24), 4);
+ connRef442->setDestEndpoint(dstPt442);
+ connRef442->setRoutingType((ConnType)2);
+
+ ConnRef *connRef443 = new ConnRef(router, 443);
+ ConnEnd srcPt443(Point(1073.18, 1276.24), 15);
+ connRef443->setSourceEndpoint(srcPt443);
+ ConnEnd dstPt443(Point(1050.96, 1158.64), 2);
+ connRef443->setDestEndpoint(dstPt443);
+ connRef443->setRoutingType((ConnType)2);
+
+ ConnRef *connRef444 = new ConnRef(router, 444);
+ ConnEnd srcPt444(Point(1073.18, 978.5), 15);
+ connRef444->setSourceEndpoint(srcPt444);
+ ConnEnd dstPt444(Point(1370.86, 969.5), 4);
+ connRef444->setDestEndpoint(dstPt444);
+ connRef444->setRoutingType((ConnType)2);
+
+ ConnRef *connRef445 = new ConnRef(router, 445);
+ ConnEnd srcPt445(Point(1073.18, 978.5), 15);
+ connRef445->setSourceEndpoint(srcPt445);
+ ConnEnd dstPt445(Point(1370.86, 1041.64), 4);
+ connRef445->setDestEndpoint(dstPt445);
+ connRef445->setRoutingType((ConnType)2);
+
+ ConnRef *connRef446 = new ConnRef(router, 446);
+ ConnEnd srcPt446(Point(1370.86, 1143.64), 4);
+ connRef446->setSourceEndpoint(srcPt446);
+ ConnEnd dstPt446(Point(1073.18, 978.5), 15);
+ connRef446->setDestEndpoint(dstPt446);
+ connRef446->setRoutingType((ConnType)2);
+
+ ConnRef *connRef447 = new ConnRef(router, 447);
+ ConnEnd srcPt447(Point(1073.18, 978.5), 15);
+ connRef447->setSourceEndpoint(srcPt447);
+ ConnEnd dstPt447(Point(1073.18, 723.5), 2);
+ connRef447->setDestEndpoint(dstPt447);
+ connRef447->setRoutingType((ConnType)2);
+
+ ConnRef *connRef448 = new ConnRef(router, 448);
+ ConnEnd srcPt448(Point(220, 497.5), 1);
+ connRef448->setSourceEndpoint(srcPt448);
+ ConnEnd dstPt448(Point(323, 375.5), 15);
+ connRef448->setDestEndpoint(dstPt448);
+ connRef448->setRoutingType((ConnType)2);
+
+ ConnRef *connRef449 = new ConnRef(router, 449);
+ ConnEnd srcPt449(Point(404.333, 497.5), 1);
+ connRef449->setSourceEndpoint(srcPt449);
+ ConnEnd dstPt449(Point(323, 375.5), 15);
+ connRef449->setDestEndpoint(dstPt449);
+ connRef449->setRoutingType((ConnType)2);
+
+ ConnRef *connRef450 = new ConnRef(router, 450);
+ ConnEnd srcPt450(Point(2241.79, 723.5), 2);
+ connRef450->setSourceEndpoint(srcPt450);
+ ConnEnd dstPt450(Point(2241.79, 840.75), 15);
+ connRef450->setDestEndpoint(dstPt450);
+ connRef450->setRoutingType((ConnType)2);
+
+ ConnRef *connRef451 = new ConnRef(router, 451);
+ ConnEnd srcPt451(Point(2968.99, 840.75), 15);
+ connRef451->setSourceEndpoint(srcPt451);
+ ConnEnd dstPt451(Point(2968.99, 899.5), 1);
+ connRef451->setDestEndpoint(dstPt451);
+ connRef451->setRoutingType((ConnType)2);
+
+ ConnRef *connRef452 = new ConnRef(router, 452);
+ ConnEnd srcPt452(Point(2241.79, 286.75), 1);
+ connRef452->setSourceEndpoint(srcPt452);
+ ConnEnd dstPt452(Point(2241.79, 220.875), 15);
+ connRef452->setDestEndpoint(dstPt452);
+ connRef452->setRoutingType((ConnType)2);
+
+ ConnRef *connRef453 = new ConnRef(router, 453);
+ ConnEnd srcPt453(Point(2241.79, 220.875), 15);
+ connRef453->setSourceEndpoint(srcPt453);
+ ConnEnd dstPt453(Point(2462.71, 220.875), 4);
+ connRef453->setDestEndpoint(dstPt453);
+ connRef453->setRoutingType((ConnType)2);
+
+ ConnRef *connRef454 = new ConnRef(router, 454);
+ ConnEnd srcPt454(Point(2186.79, 220.875), 8);
+ connRef454->setSourceEndpoint(srcPt454);
+ ConnEnd dstPt454(Point(2241.79, 220.875), 15);
+ connRef454->setDestEndpoint(dstPt454);
+ connRef454->setRoutingType((ConnType)2);
+
+ ConnRef *connRef455 = new ConnRef(router, 455);
+ ConnEnd srcPt455(Point(2547.71, 220.875), 15);
+ connRef455->setSourceEndpoint(srcPt455);
+ ConnEnd dstPt455(Point(2547.71, 286.75), 1);
+ connRef455->setDestEndpoint(dstPt455);
+ connRef455->setRoutingType((ConnType)2);
+
+ ConnRef *connRef456 = new ConnRef(router, 456);
+ ConnEnd srcPt456(Point(2547.71, 220.875), 15);
+ connRef456->setSourceEndpoint(srcPt456);
+ ConnEnd dstPt456(Point(2650.54, 220.875), 4);
+ connRef456->setDestEndpoint(dstPt456);
+ connRef456->setRoutingType((ConnType)2);
+
+ ConnRef *connRef457 = new ConnRef(router, 457);
+ ConnEnd srcPt457(Point(3114.24, 220.875), 15);
+ connRef457->setSourceEndpoint(srcPt457);
+ ConnEnd dstPt457(Point(3139.24, 286.75), 1);
+ connRef457->setDestEndpoint(dstPt457);
+ connRef457->setRoutingType((ConnType)2);
+
+ ConnRef *connRef458 = new ConnRef(router, 458);
+ ConnEnd srcPt458(Point(2790.54, 123.5), 8);
+ connRef458->setSourceEndpoint(srcPt458);
+ ConnEnd dstPt458(Point(3114.24, 220.875), 15);
+ connRef458->setDestEndpoint(dstPt458);
+ connRef458->setRoutingType((ConnType)2);
+
+ ConnRef *connRef459 = new ConnRef(router, 459);
+ ConnEnd srcPt459(Point(3114.24, 220.875), 15);
+ connRef459->setSourceEndpoint(srcPt459);
+ ConnEnd dstPt459(Point(3089.24, 286.75), 1);
+ connRef459->setDestEndpoint(dstPt459);
+ connRef459->setRoutingType((ConnType)2);
+
+ ConnRef *connRef460 = new ConnRef(router, 460);
+ ConnEnd srcPt460(Point(2934.99, 437.7), 8);
+ connRef460->setSourceEndpoint(srcPt460);
+ ConnEnd dstPt460(Point(3114.24, 437.7), 15);
+ connRef460->setDestEndpoint(dstPt460);
+ connRef460->setRoutingType((ConnType)2);
+
+ ConnRef *connRef461 = new ConnRef(router, 461);
+ ConnEnd srcPt461(Point(3139.24, 316.75), 2);
+ connRef461->setSourceEndpoint(srcPt461);
+ ConnEnd dstPt461(Point(3114.24, 437.7), 15);
+ connRef461->setDestEndpoint(dstPt461);
+ connRef461->setRoutingType((ConnType)2);
+
+ ConnRef *connRef462 = new ConnRef(router, 462);
+ ConnEnd srcPt462(Point(2787.54, 437.7), 15);
+ connRef462->setSourceEndpoint(srcPt462);
+ ConnEnd dstPt462(Point(2680.54, 437.7), 8);
+ connRef462->setDestEndpoint(dstPt462);
+ connRef462->setRoutingType((ConnType)2);
+
+ ConnRef *connRef463 = new ConnRef(router, 463);
+ ConnEnd srcPt463(Point(2904.99, 437.7), 4);
+ connRef463->setSourceEndpoint(srcPt463);
+ ConnEnd dstPt463(Point(2787.54, 437.7), 15);
+ connRef463->setDestEndpoint(dstPt463);
+ connRef463->setRoutingType((ConnType)2);
+
+ ConnRef *connRef464 = new ConnRef(router, 464);
+ ConnEnd srcPt464(Point(2650.54, 437.7), 4);
+ connRef464->setSourceEndpoint(srcPt464);
+ ConnEnd dstPt464(Point(2547.71, 437.7), 15);
+ connRef464->setDestEndpoint(dstPt464);
+ connRef464->setRoutingType((ConnType)2);
+
+ ConnRef *connRef465 = new ConnRef(router, 465);
+ ConnEnd srcPt465(Point(2156.79, 1041.64), 4);
+ connRef465->setSourceEndpoint(srcPt465);
+ ConnEnd dstPt465(Point(1958.29, 1041.64), 15);
+ connRef465->setDestEndpoint(dstPt465);
+ connRef465->setRoutingType((ConnType)2);
+
+ ConnRef *connRef466 = new ConnRef(router, 466);
+ ConnEnd srcPt466(Point(1958.29, 1041.64), 15);
+ connRef466->setSourceEndpoint(srcPt466);
+ ConnEnd dstPt466(Point(2226.79, 1143.64), 4);
+ connRef466->setDestEndpoint(dstPt466);
+ connRef466->setRoutingType((ConnType)2);
+
+ ConnRef *connRef467 = new ConnRef(router, 467);
+ ConnEnd srcPt467(Point(2241.79, 1041.64), 15);
+ connRef467->setSourceEndpoint(srcPt467);
+ ConnEnd dstPt467(Point(2462.71, 1041.64), 4);
+ connRef467->setDestEndpoint(dstPt467);
+ connRef467->setRoutingType((ConnType)2);
+
+ ConnRef *connRef468 = new ConnRef(router, 468);
+ ConnEnd srcPt468(Point(2256.79, 1143.64), 8);
+ connRef468->setSourceEndpoint(srcPt468);
+ ConnEnd dstPt468(Point(2547.71, 1041.64), 15);
+ connRef468->setDestEndpoint(dstPt468);
+ connRef468->setRoutingType((ConnType)2);
+
+ ConnRef *connRef469 = new ConnRef(router, 469);
+ ConnEnd srcPt469(Point(2186.79, 1569.64), 8);
+ connRef469->setSourceEndpoint(srcPt469);
+ ConnEnd dstPt469(Point(2241.79, 1569.64), 15);
+ connRef469->setDestEndpoint(dstPt469);
+ connRef469->setRoutingType((ConnType)2);
+
+ ConnRef *connRef470 = new ConnRef(router, 470);
+ ConnEnd srcPt470(Point(2241.79, 1569.64), 15);
+ connRef470->setSourceEndpoint(srcPt470);
+ ConnEnd dstPt470(Point(2241.79, 1455.24), 2);
+ connRef470->setDestEndpoint(dstPt470);
+ connRef470->setRoutingType((ConnType)2);
+
+ ConnRef *connRef471 = new ConnRef(router, 471);
+ ConnEnd srcPt471(Point(2241.79, 1569.64), 15);
+ connRef471->setSourceEndpoint(srcPt471);
+ ConnEnd dstPt471(Point(2462.71, 1509.44), 4);
+ connRef471->setDestEndpoint(dstPt471);
+ connRef471->setRoutingType((ConnType)2);
+
+ ConnRef *connRef472 = new ConnRef(router, 472);
+ ConnEnd srcPt472(Point(2241.79, 1569.64), 15);
+ connRef472->setSourceEndpoint(srcPt472);
+ ConnEnd dstPt472(Point(2462.71, 1581.64), 4);
+ connRef472->setDestEndpoint(dstPt472);
+ connRef472->setRoutingType((ConnType)2);
+
+ ConnRef *connRef473 = new ConnRef(router, 473);
+ ConnEnd srcPt473(Point(2241.79, 1425.24), 1);
+ connRef473->setSourceEndpoint(srcPt473);
+ ConnEnd dstPt473(Point(2241.79, 1378.24), 15);
+ connRef473->setDestEndpoint(dstPt473);
+ connRef473->setRoutingType((ConnType)2);
+
+ ConnRef *connRef474 = new ConnRef(router, 474);
+ ConnEnd srcPt474(Point(2041.79, 2023.95), 15);
+ connRef474->setSourceEndpoint(srcPt474);
+ ConnEnd dstPt474(Point(1976.87, 1934.95), 15);
+ connRef474->setDestEndpoint(dstPt474);
+ connRef474->setRoutingType((ConnType)2);
+
+ ConnRef *connRef475 = new ConnRef(router, 475);
+ ConnEnd srcPt475(Point(2241.79, 2023.95), 15);
+ connRef475->setSourceEndpoint(srcPt475);
+ ConnEnd dstPt475(Point(2462.71, 2013.95), 4);
+ connRef475->setDestEndpoint(dstPt475);
+ connRef475->setRoutingType((ConnType)2);
+
+ ConnRef *connRef476 = new ConnRef(router, 476);
+ ConnEnd srcPt476(Point(2241.79, 2023.95), 15);
+ connRef476->setSourceEndpoint(srcPt476);
+ ConnEnd dstPt476(Point(2462.71, 2055.95), 4);
+ connRef476->setDestEndpoint(dstPt476);
+ connRef476->setRoutingType((ConnType)2);
+
+ ConnRef *connRef477 = new ConnRef(router, 477);
+ ConnEnd srcPt477(Point(1563.6, 2945.3), 15);
+ connRef477->setSourceEndpoint(srcPt477);
+ ConnEnd dstPt477(Point(1646.79, 3125.3), 1);
+ connRef477->setDestEndpoint(dstPt477);
+ connRef477->setRoutingType((ConnType)2);
+
+ ConnRef *connRef478 = new ConnRef(router, 478);
+ ConnEnd srcPt478(Point(1563.6, 2945.3), 15);
+ connRef478->setSourceEndpoint(srcPt478);
+ ConnEnd dstPt478(Point(1538.46, 3125.3), 1);
+ connRef478->setDestEndpoint(dstPt478);
+ connRef478->setRoutingType((ConnType)2);
+
+ ConnRef *connRef479 = new ConnRef(router, 479);
+ ConnEnd srcPt479(Point(1563.6, 2945.3), 15);
+ connRef479->setSourceEndpoint(srcPt479);
+ ConnEnd dstPt479(Point(1563.6, 3056.3), 1);
+ connRef479->setDestEndpoint(dstPt479);
+ connRef479->setRoutingType((ConnType)2);
+
+ ConnRef *connRef480 = new ConnRef(router, 480);
+ ConnEnd srcPt480(Point(1938.79, 2945.3), 4);
+ connRef480->setSourceEndpoint(srcPt480);
+ ConnEnd dstPt480(Point(1563.6, 2945.3), 15);
+ connRef480->setDestEndpoint(dstPt480);
+ connRef480->setRoutingType((ConnType)2);
+
+ ConnRef *connRef481 = new ConnRef(router, 481);
+ ConnEnd srcPt481(Point(2772.54, 3417.3), 4);
+ connRef481->setSourceEndpoint(srcPt481);
+ ConnEnd dstPt481(Point(1563.6, 3413.3), 15);
+ connRef481->setDestEndpoint(dstPt481);
+ connRef481->setRoutingType((ConnType)2);
+
+ ConnRef *connRef482 = new ConnRef(router, 482);
+ ConnEnd srcPt482(Point(1563.6, 3413.3), 15);
+ connRef482->setSourceEndpoint(srcPt482);
+ ConnEnd dstPt482(Point(2772.54, 3519.3), 4);
+ connRef482->setDestEndpoint(dstPt482);
+ connRef482->setRoutingType((ConnType)2);
+
+ ConnRef *connRef483 = new ConnRef(router, 483);
+ ConnEnd srcPt483(Point(625.333, 3071.3), 8);
+ connRef483->setSourceEndpoint(srcPt483);
+ ConnEnd dstPt483(Point(1563.6, 3413.3), 15);
+ connRef483->setDestEndpoint(dstPt483);
+ connRef483->setRoutingType((ConnType)2);
+
+ ConnRef *connRef484 = new ConnRef(router, 484);
+ ConnEnd srcPt484(Point(1646.79, 3155.3), 2);
+ connRef484->setSourceEndpoint(srcPt484);
+ ConnEnd dstPt484(Point(1563.6, 3413.3), 15);
+ connRef484->setDestEndpoint(dstPt484);
+ connRef484->setRoutingType((ConnType)2);
+
+ ConnRef *connRef485 = new ConnRef(router, 485);
+ ConnEnd srcPt485(Point(1538.46, 3155.3), 2);
+ connRef485->setSourceEndpoint(srcPt485);
+ ConnEnd dstPt485(Point(1563.6, 3413.3), 15);
+ connRef485->setDestEndpoint(dstPt485);
+ connRef485->setRoutingType((ConnType)2);
+
+ ConnRef *connRef486 = new ConnRef(router, 486);
+ ConnEnd srcPt486(Point(1563.6, 3086.3), 2);
+ connRef486->setSourceEndpoint(srcPt486);
+ ConnEnd dstPt486(Point(1563.6, 3413.3), 15);
+ connRef486->setDestEndpoint(dstPt486);
+ connRef486->setRoutingType((ConnType)2);
+
+ ConnRef *connRef487 = new ConnRef(router, 487);
+ ConnEnd srcPt487(Point(891.358, 3071.3), 8);
+ connRef487->setSourceEndpoint(srcPt487);
+ ConnEnd dstPt487(Point(1563.6, 3413.3), 15);
+ connRef487->setDestEndpoint(dstPt487);
+ connRef487->setRoutingType((ConnType)2);
+
+ ConnRef *connRef488 = new ConnRef(router, 488);
+ ConnEnd srcPt488(Point(1767.79, 3401.3), 4);
+ connRef488->setSourceEndpoint(srcPt488);
+ ConnEnd dstPt488(Point(1563.6, 3413.3), 15);
+ connRef488->setDestEndpoint(dstPt488);
+ connRef488->setRoutingType((ConnType)2);
+
+ ConnRef *connRef489 = new ConnRef(router, 489);
+ ConnEnd srcPt489(Point(1563.6, 3413.3), 15);
+ connRef489->setSourceEndpoint(srcPt489);
+ ConnEnd dstPt489(Point(1767.79, 3197.3), 4);
+ connRef489->setDestEndpoint(dstPt489);
+ connRef489->setRoutingType((ConnType)2);
+
+ ConnRef *connRef490 = new ConnRef(router, 490);
+ ConnEnd srcPt490(Point(1563.6, 3413.3), 15);
+ connRef490->setSourceEndpoint(srcPt490);
+ ConnEnd dstPt490(Point(1767.79, 3299.3), 4);
+ connRef490->setDestEndpoint(dstPt490);
+ connRef490->setRoutingType((ConnType)2);
+
+ ConnRef *connRef491 = new ConnRef(router, 491);
+ ConnEnd srcPt491(Point(610.333, 2529.3), 15);
+ connRef491->setSourceEndpoint(srcPt491);
+ ConnEnd dstPt491(Point(610.333, 2597.3), 1);
+ connRef491->setDestEndpoint(dstPt491);
+ connRef491->setRoutingType((ConnType)2);
+
+ ConnRef *connRef492 = new ConnRef(router, 492);
+ ConnEnd srcPt492(Point(610.333, 2674.3), 15);
+ connRef492->setSourceEndpoint(srcPt492);
+ ConnEnd dstPt492(Point(1480.87, 2053.77), 15);
+ connRef492->setDestEndpoint(dstPt492);
+ connRef492->setRoutingType((ConnType)2);
+
+ ConnRef *connRef493 = new ConnRef(router, 493);
+ ConnEnd srcPt493(Point(610.333, 2945.3), 15);
+ connRef493->setSourceEndpoint(srcPt493);
+ ConnEnd dstPt493(Point(595.333, 3071.3), 4);
+ connRef493->setDestEndpoint(dstPt493);
+ connRef493->setRoutingType((ConnType)2);
+
+ ConnRef *connRef494 = new ConnRef(router, 494);
+ ConnEnd srcPt494(Point(2244.79, 2749.3), 8);
+ connRef494->setSourceEndpoint(srcPt494);
+ ConnEnd dstPt494(Point(2241.79, 2945.3), 15);
+ connRef494->setDestEndpoint(dstPt494);
+ connRef494->setRoutingType((ConnType)2);
+
+ ConnRef *connRef495 = new ConnRef(router, 495);
+ ConnEnd srcPt495(Point(2241.79, 2945.3), 15);
+ connRef495->setSourceEndpoint(srcPt495);
+ ConnEnd dstPt495(Point(2462.71, 2955.3), 4);
+ connRef495->setDestEndpoint(dstPt495);
+ connRef495->setRoutingType((ConnType)2);
+
+ ConnRef *connRef496 = new ConnRef(router, 496);
+ ConnEnd srcPt496(Point(2241.79, 2945.3), 15);
+ connRef496->setSourceEndpoint(srcPt496);
+ ConnEnd dstPt496(Point(1968.79, 2945.3), 8);
+ connRef496->setDestEndpoint(dstPt496);
+ connRef496->setRoutingType((ConnType)2);
+
+ ConnRef *connRef497 = new ConnRef(router, 497);
+ ConnEnd srcPt497(Point(2241.79, 2945.3), 15);
+ connRef497->setSourceEndpoint(srcPt497);
+ ConnEnd dstPt497(Point(2462.71, 2864.3), 4);
+ connRef497->setDestEndpoint(dstPt497);
+ connRef497->setRoutingType((ConnType)2);
+
+ ConnRef *connRef498 = new ConnRef(router, 498);
+ ConnEnd srcPt498(Point(2322.71, 2674.3), 15);
+ connRef498->setSourceEndpoint(srcPt498);
+ ConnEnd dstPt498(Point(2214.79, 2749.3), 4);
+ connRef498->setDestEndpoint(dstPt498);
+ connRef498->setRoutingType((ConnType)2);
+
+ ConnRef *connRef499 = new ConnRef(router, 499);
+ ConnEnd srcPt499(Point(2334.71, 2627.3), 2);
+ connRef499->setSourceEndpoint(srcPt499);
+ ConnEnd dstPt499(Point(2322.71, 2674.3), 15);
+ connRef499->setDestEndpoint(dstPt499);
+ connRef499->setRoutingType((ConnType)2);
+
+ ConnRef *connRef500 = new ConnRef(router, 500);
+ ConnEnd srcPt500(Point(2322.71, 2674.3), 15);
+ connRef500->setSourceEndpoint(srcPt500);
+ ConnEnd dstPt500(Point(2462.71, 2955.3), 4);
+ connRef500->setDestEndpoint(dstPt500);
+ connRef500->setRoutingType((ConnType)2);
+
+ ConnRef *connRef501 = new ConnRef(router, 501);
+ ConnEnd srcPt501(Point(2322.71, 2674.3), 15);
+ connRef501->setSourceEndpoint(srcPt501);
+ ConnEnd dstPt501(Point(2462.71, 2864.3), 4);
+ connRef501->setDestEndpoint(dstPt501);
+ connRef501->setRoutingType((ConnType)2);
+
+ ConnRef *connRef502 = new ConnRef(router, 502);
+ ConnEnd srcPt502(Point(2322.71, 2529.3), 15);
+ connRef502->setSourceEndpoint(srcPt502);
+ ConnEnd dstPt502(Point(2334.71, 2597.3), 1);
+ connRef502->setDestEndpoint(dstPt502);
+ connRef502->setRoutingType((ConnType)2);
+
+ ConnRef *connRef503 = new ConnRef(router, 503);
+ ConnEnd srcPt503(Point(876.358, 2529.3), 15);
+ connRef503->setSourceEndpoint(srcPt503);
+ ConnEnd dstPt503(Point(876.358, 2597.3), 1);
+ connRef503->setDestEndpoint(dstPt503);
+ connRef503->setRoutingType((ConnType)2);
+
+ ConnRef *connRef504 = new ConnRef(router, 504);
+ ConnEnd srcPt504(Point(876.358, 2674.3), 15);
+ connRef504->setSourceEndpoint(srcPt504);
+ ConnEnd dstPt504(Point(876.358, 2742.3), 1);
+ connRef504->setDestEndpoint(dstPt504);
+ connRef504->setRoutingType((ConnType)2);
+
+ ConnRef *connRef505 = new ConnRef(router, 505);
+ ConnEnd srcPt505(Point(876.358, 2945.3), 15);
+ connRef505->setSourceEndpoint(srcPt505);
+ ConnEnd dstPt505(Point(861.358, 3071.3), 4);
+ connRef505->setDestEndpoint(dstPt505);
+ connRef505->setRoutingType((ConnType)2);
+
+ ConnRef *connRef506 = new ConnRef(router, 506);
+ ConnEnd srcPt506(Point(3322.24, 2399.05), 15);
+ connRef506->setSourceEndpoint(srcPt506);
+ ConnEnd dstPt506(Point(3231.44, 2399.05), 8);
+ connRef506->setDestEndpoint(dstPt506);
+ connRef506->setRoutingType((ConnType)2);
+
+ ConnRef *connRef507 = new ConnRef(router, 507);
+ ConnEnd srcPt507(Point(3322.24, 2399.05), 15);
+ connRef507->setSourceEndpoint(srcPt507);
+ ConnEnd dstPt507(Point(3231.44, 2297.05), 8);
+ connRef507->setDestEndpoint(dstPt507);
+ connRef507->setRoutingType((ConnType)2);
+
+ ConnRef *connRef508 = new ConnRef(router, 508);
+ ConnEnd srcPt508(Point(3322.24, 2399.05), 15);
+ connRef508->setSourceEndpoint(srcPt508);
+ ConnEnd dstPt508(Point(3242.24, 2597.3), 1);
+ connRef508->setDestEndpoint(dstPt508);
+ connRef508->setRoutingType((ConnType)2);
+
+ ConnRef *connRef509 = new ConnRef(router, 509);
+ ConnEnd srcPt509(Point(3322.24, 2399.05), 15);
+ connRef509->setSourceEndpoint(srcPt509);
+ ConnEnd dstPt509(Point(3326.74, 3056.3), 1);
+ connRef509->setDestEndpoint(dstPt509);
+ connRef509->setRoutingType((ConnType)2);
+
+ ConnRef *connRef510 = new ConnRef(router, 510);
+ ConnEnd srcPt510(Point(2968.99, 2297.05), 15);
+ connRef510->setSourceEndpoint(srcPt510);
+ ConnEnd dstPt510(Point(2802.54, 2297.05), 8);
+ connRef510->setDestEndpoint(dstPt510);
+ connRef510->setRoutingType((ConnType)2);
+
+ ConnRef *connRef511 = new ConnRef(router, 511);
+ ConnEnd srcPt511(Point(3478.07, 1378.24), 15);
+ connRef511->setSourceEndpoint(srcPt511);
+ ConnEnd dstPt511(Point(3478.07, 1857.95), 1);
+ connRef511->setDestEndpoint(dstPt511);
+ connRef511->setRoutingType((ConnType)2);
+
+ ConnRef *connRef512 = new ConnRef(router, 512);
+ ConnEnd srcPt512(Point(3478.07, 2627.3), 2);
+ connRef512->setSourceEndpoint(srcPt512);
+ ConnEnd dstPt512(Point(3478.07, 3413.3), 15);
+ connRef512->setDestEndpoint(dstPt512);
+ connRef512->setRoutingType((ConnType)2);
+
+ ConnRef *connRef513 = new ConnRef(router, 513);
+ ConnEnd srcPt513(Point(2802.54, 3417.3), 8);
+ connRef513->setSourceEndpoint(srcPt513);
+ ConnEnd dstPt513(Point(3478.07, 3413.3), 15);
+ connRef513->setDestEndpoint(dstPt513);
+ connRef513->setRoutingType((ConnType)2);
+
+ ConnRef *connRef514 = new ConnRef(router, 514);
+ ConnEnd srcPt514(Point(3596.07, 2627.3), 2);
+ connRef514->setSourceEndpoint(srcPt514);
+ ConnEnd dstPt514(Point(3478.07, 3413.3), 15);
+ connRef514->setDestEndpoint(dstPt514);
+ connRef514->setRoutingType((ConnType)2);
+
+ ConnRef *connRef515 = new ConnRef(router, 515);
+ ConnEnd srcPt515(Point(220, 527.5), 2);
+ connRef515->setSourceEndpoint(srcPt515);
+ ConnEnd dstPt515(Point(323, 833.833), 15);
+ connRef515->setDestEndpoint(dstPt515);
+ connRef515->setRoutingType((ConnType)2);
+
+ ConnRef *connRef516 = new ConnRef(router, 516);
+ ConnEnd srcPt516(Point(131, 633.5), 1);
+ connRef516->setSourceEndpoint(srcPt516);
+ ConnEnd dstPt516(Point(323, 375.5), 15);
+ connRef516->setDestEndpoint(dstPt516);
+ connRef516->setRoutingType((ConnType)2);
+
+ ConnRef *connRef517 = new ConnRef(router, 517);
+ ConnEnd srcPt517(Point(1557.46, 291.5), 8);
+ connRef517->setSourceEndpoint(srcPt517);
+ ConnEnd dstPt517(Point(1762.79, 157.5), 15);
+ connRef517->setDestEndpoint(dstPt517);
+ connRef517->setRoutingType((ConnType)2);
+
+ ConnRef *connRef518 = new ConnRef(router, 518);
+ ConnEnd srcPt518(Point(1957.29, 291.5), 8);
+ connRef518->setSourceEndpoint(srcPt518);
+ ConnEnd dstPt518(Point(2041.79, 312.5), 15);
+ connRef518->setDestEndpoint(dstPt518);
+ connRef518->setRoutingType((ConnType)2);
+
+ ConnRef *connRef519 = new ConnRef(router, 519);
+ ConnEnd srcPt519(Point(2011.79, 777.5), 4);
+ connRef519->setSourceEndpoint(srcPt519);
+ ConnEnd dstPt519(Point(1958.29, 1041.64), 15);
+ connRef519->setDestEndpoint(dstPt519);
+ connRef519->setRoutingType((ConnType)2);
+
+ ConnRef *connRef520 = new ConnRef(router, 520);
+ ConnEnd srcPt520(Point(555.333, 1276.24), 8);
+ connRef520->setSourceEndpoint(srcPt520);
+ ConnEnd dstPt520(Point(610.333, 1276.24), 15);
+ connRef520->setDestEndpoint(dstPt520);
+ connRef520->setRoutingType((ConnType)2);
+
+ ConnRef *connRef521 = new ConnRef(router, 521);
+ ConnEnd srcPt521(Point(726.958, 1276.24), 8);
+ connRef521->setSourceEndpoint(srcPt521);
+ ConnEnd dstPt521(Point(876.358, 1276.24), 15);
+ connRef521->setDestEndpoint(dstPt521);
+ connRef521->setRoutingType((ConnType)2);
+
+ ConnRef *connRef522 = new ConnRef(router, 522);
+ ConnEnd srcPt522(Point(987.958, 1276.24), 8);
+ connRef522->setSourceEndpoint(srcPt522);
+ ConnEnd dstPt522(Point(1073.18, 1276.24), 15);
+ connRef522->setDestEndpoint(dstPt522);
+ connRef522->setRoutingType((ConnType)2);
+
+ ConnRef *connRef523 = new ConnRef(router, 523);
+ ConnEnd srcPt523(Point(1050.96, 1128.64), 1);
+ connRef523->setSourceEndpoint(srcPt523);
+ ConnEnd dstPt523(Point(1073.18, 978.5), 15);
+ connRef523->setDestEndpoint(dstPt523);
+ connRef523->setRoutingType((ConnType)2);
+
+ ConnRef *connRef524 = new ConnRef(router, 524);
+ ConnEnd srcPt524(Point(1646.79, 1291.24), 2);
+ connRef524->setSourceEndpoint(srcPt524);
+ ConnEnd dstPt524(Point(1782.79, 1378.24), 15);
+ connRef524->setDestEndpoint(dstPt524);
+ connRef524->setRoutingType((ConnType)2);
+
+ ConnRef *connRef525 = new ConnRef(router, 525);
+ ConnEnd srcPt525(Point(1919.87, 1601.64), 15);
+ connRef525->setSourceEndpoint(srcPt525);
+ ConnEnd dstPt525(Point(1782.79, 1569.64), 15);
+ connRef525->setDestEndpoint(dstPt525);
+ connRef525->setRoutingType((ConnType)2);
+
+ ConnRef *connRef526 = new ConnRef(router, 526);
+ ConnEnd srcPt526(Point(1911.79, 1653.64), 4);
+ connRef526->setSourceEndpoint(srcPt526);
+ ConnEnd dstPt526(Point(1782.79, 1569.64), 15);
+ connRef526->setDestEndpoint(dstPt526);
+ connRef526->setRoutingType((ConnType)2);
+
+ ConnRef *connRef527 = new ConnRef(router, 527);
+ ConnEnd srcPt527(Point(1942.29, 1378.24), 15);
+ connRef527->setSourceEndpoint(srcPt527);
+ ConnEnd dstPt527(Point(1958.29, 1425.24), 1);
+ connRef527->setDestEndpoint(dstPt527);
+ connRef527->setRoutingType((ConnType)2);
+
+ ConnRef *connRef528 = new ConnRef(router, 528);
+ ConnEnd srcPt528(Point(2028.87, 1507.64), 15);
+ connRef528->setSourceEndpoint(srcPt528);
+ ConnEnd dstPt528(Point(2241.79, 1378.24), 15);
+ connRef528->setDestEndpoint(dstPt528);
+ connRef528->setRoutingType((ConnType)2);
+
+ ConnRef *connRef529 = new ConnRef(router, 529);
+ ConnEnd srcPt529(Point(2492.71, 1509.44), 8);
+ connRef529->setSourceEndpoint(srcPt529);
+ ConnEnd dstPt529(Point(2547.71, 1569.64), 15);
+ connRef529->setDestEndpoint(dstPt529);
+ connRef529->setRoutingType((ConnType)2);
+
+ ConnRef *connRef530 = new ConnRef(router, 530);
+ ConnEnd srcPt530(Point(2492.71, 1581.64), 8);
+ connRef530->setSourceEndpoint(srcPt530);
+ ConnEnd dstPt530(Point(2547.71, 1569.64), 15);
+ connRef530->setDestEndpoint(dstPt530);
+ connRef530->setRoutingType((ConnType)2);
+ */
+
+ ConnRef *connRef531 = new ConnRef(router, 531);
+ ConnEnd srcPt531(Point(2186.79, 1872.95), 8);
+ connRef531->setSourceEndpoint(srcPt531);
+ ConnEnd dstPt531(Point(2241.79, 1872.95), 15);
+ connRef531->setDestEndpoint(dstPt531);
+ connRef531->setRoutingType((ConnType)2);
+
+ /*
+ ConnRef *connRef532 = new ConnRef(router, 532);
+ ConnEnd srcPt532(Point(2675.54, 1812.64), 8);
+ connRef532->setSourceEndpoint(srcPt532);
+ ConnEnd dstPt532(Point(2787.54, 1872.95), 15);
+ connRef532->setDestEndpoint(dstPt532);
+ connRef532->setRoutingType((ConnType)2);
+
+ ConnRef *connRef533 = new ConnRef(router, 533);
+ ConnEnd srcPt533(Point(2652.54, 1884.95), 8);
+ connRef533->setSourceEndpoint(srcPt533);
+ ConnEnd dstPt533(Point(2787.54, 1872.95), 15);
+ connRef533->setDestEndpoint(dstPt533);
+ connRef533->setRoutingType((ConnType)2);
+
+ ConnRef *connRef534 = new ConnRef(router, 534);
+ ConnEnd srcPt534(Point(2750.54, 1884.95), 8);
+ connRef534->setSourceEndpoint(srcPt534);
+ ConnEnd dstPt534(Point(2787.54, 1872.95), 15);
+ connRef534->setDestEndpoint(dstPt534);
+ connRef534->setRoutingType((ConnType)2);
+
+ ConnRef *connRef535 = new ConnRef(router, 535);
+ ConnEnd srcPt535(Point(2913.99, 1812.64), 8);
+ connRef535->setSourceEndpoint(srcPt535);
+ ConnEnd dstPt535(Point(3119.9, 1872.95), 15);
+ connRef535->setDestEndpoint(dstPt535);
+ connRef535->setRoutingType((ConnType)2);
+
+ ConnRef *connRef536 = new ConnRef(router, 536);
+ ConnEnd srcPt536(Point(2913.99, 1812.64), 8);
+ connRef536->setSourceEndpoint(srcPt536);
+ ConnEnd dstPt536(Point(2968.99, 1731.64), 15);
+ connRef536->setDestEndpoint(dstPt536);
+ connRef536->setRoutingType((ConnType)2);
+
+ ConnRef *connRef537 = new ConnRef(router, 537);
+ ConnEnd srcPt537(Point(2890.99, 1884.95), 8);
+ connRef537->setSourceEndpoint(srcPt537);
+ ConnEnd dstPt537(Point(3119.9, 1872.95), 15);
+ connRef537->setDestEndpoint(dstPt537);
+ connRef537->setRoutingType((ConnType)2);
+
+ ConnRef *connRef538 = new ConnRef(router, 538);
+ ConnEnd srcPt538(Point(2890.99, 1884.95), 8);
+ connRef538->setSourceEndpoint(srcPt538);
+ ConnEnd dstPt538(Point(2968.99, 1731.64), 15);
+ connRef538->setDestEndpoint(dstPt538);
+ connRef538->setRoutingType((ConnType)2);
+
+ ConnRef *connRef539 = new ConnRef(router, 539);
+ ConnEnd srcPt539(Point(2968.99, 1884.95), 8);
+ connRef539->setSourceEndpoint(srcPt539);
+ ConnEnd dstPt539(Point(3119.9, 1872.95), 15);
+ connRef539->setDestEndpoint(dstPt539);
+ connRef539->setRoutingType((ConnType)2);
+
+ ConnRef *connRef540 = new ConnRef(router, 540);
+ ConnEnd srcPt540(Point(2968.99, 1884.95), 8);
+ connRef540->setSourceEndpoint(srcPt540);
+ ConnEnd dstPt540(Point(2968.99, 1731.64), 15);
+ connRef540->setDestEndpoint(dstPt540);
+ connRef540->setRoutingType((ConnType)2);
+
+ ConnRef *connRef541 = new ConnRef(router, 541);
+ ConnEnd srcPt541(Point(2547.71, 723.5), 2);
+ connRef541->setSourceEndpoint(srcPt541);
+ ConnEnd dstPt541(Point(2547.71, 840.75), 15);
+ connRef541->setDestEndpoint(dstPt541);
+ connRef541->setRoutingType((ConnType)2);
+
+ ConnRef *connRef542 = new ConnRef(router, 542);
+ ConnEnd srcPt542(Point(2787.54, 723.5), 2);
+ connRef542->setSourceEndpoint(srcPt542);
+ ConnEnd dstPt542(Point(2787.54, 840.75), 15);
+ connRef542->setDestEndpoint(dstPt542);
+ connRef542->setRoutingType((ConnType)2);
+
+ ConnRef *connRef543 = new ConnRef(router, 543);
+ ConnEnd srcPt543(Point(2968.99, 723.5), 2);
+ connRef543->setSourceEndpoint(srcPt543);
+ ConnEnd dstPt543(Point(2968.99, 840.75), 15);
+ connRef543->setDestEndpoint(dstPt543);
+ connRef543->setRoutingType((ConnType)2);
+
+ ConnRef *connRef544 = new ConnRef(router, 544);
+ ConnEnd srcPt544(Point(2968.99, 929.5), 2);
+ connRef544->setSourceEndpoint(srcPt544);
+ ConnEnd dstPt544(Point(2968.99, 1041.64), 15);
+ connRef544->setDestEndpoint(dstPt544);
+ connRef544->setRoutingType((ConnType)2);
+
+ ConnRef *connRef545 = new ConnRef(router, 545);
+ ConnEnd srcPt545(Point(2492.71, 220.875), 8);
+ connRef545->setSourceEndpoint(srcPt545);
+ ConnEnd dstPt545(Point(2547.71, 220.875), 15);
+ connRef545->setDestEndpoint(dstPt545);
+ connRef545->setRoutingType((ConnType)2);
+
+ ConnRef *connRef546 = new ConnRef(router, 546);
+ ConnEnd srcPt546(Point(2547.71, 316.75), 2);
+ connRef546->setSourceEndpoint(srcPt546);
+ ConnEnd dstPt546(Point(2547.71, 437.7), 15);
+ connRef546->setDestEndpoint(dstPt546);
+ connRef546->setRoutingType((ConnType)2);
+
+ ConnRef *connRef547 = new ConnRef(router, 547);
+ ConnEnd srcPt547(Point(2547.71, 316.75), 2);
+ connRef547->setSourceEndpoint(srcPt547);
+ ConnEnd dstPt547(Point(2735.54, 362.5), 15);
+ connRef547->setDestEndpoint(dstPt547);
+ connRef547->setRoutingType((ConnType)2);
+
+ ConnRef *connRef548 = new ConnRef(router, 548);
+ ConnEnd srcPt548(Point(2680.54, 220.875), 8);
+ connRef548->setSourceEndpoint(srcPt548);
+ ConnEnd dstPt548(Point(2787.54, 220.875), 15);
+ connRef548->setDestEndpoint(dstPt548);
+ connRef548->setRoutingType((ConnType)2);
+
+ ConnRef *connRef549 = new ConnRef(router, 549);
+ ConnEnd srcPt549(Point(3493.07, 914.5), 8);
+ connRef549->setSourceEndpoint(srcPt549);
+ ConnEnd dstPt549(Point(3478.07, 1378.24), 15);
+ connRef549->setDestEndpoint(dstPt549);
+ connRef549->setRoutingType((ConnType)2);
+
+ ConnRef *connRef550 = new ConnRef(router, 550);
+ ConnEnd srcPt550(Point(3478.07, 1887.95), 2);
+ connRef550->setSourceEndpoint(srcPt550);
+ ConnEnd dstPt550(Point(3478.07, 2185.05), 15);
+ connRef550->setDestEndpoint(dstPt550);
+ connRef550->setRoutingType((ConnType)2);
+
+ ConnRef *connRef551 = new ConnRef(router, 551);
+ ConnEnd srcPt551(Point(2802.54, 3519.3), 8);
+ connRef551->setSourceEndpoint(srcPt551);
+ ConnEnd dstPt551(Point(3478.07, 3413.3), 15);
+ connRef551->setDestEndpoint(dstPt551);
+ connRef551->setRoutingType((ConnType)2);
+
+ ConnRef *connRef552 = new ConnRef(router, 552);
+ ConnEnd srcPt552(Point(3596.07, 929.5), 2);
+ connRef552->setSourceEndpoint(srcPt552);
+ ConnEnd dstPt552(Point(3596.07, 2185.05), 15);
+ connRef552->setDestEndpoint(dstPt552);
+ connRef552->setRoutingType((ConnType)2);
+
+ ConnRef *connRef553 = new ConnRef(router, 553);
+ ConnEnd srcPt553(Point(3326.74, 929.5), 2);
+ connRef553->setSourceEndpoint(srcPt553);
+ ConnEnd dstPt553(Point(3322.24, 2399.05), 15);
+ connRef553->setDestEndpoint(dstPt553);
+ connRef553->setRoutingType((ConnType)2);
+
+ ConnRef *connRef554 = new ConnRef(router, 554);
+ ConnEnd srcPt554(Point(3201.44, 2297.05), 4);
+ connRef554->setSourceEndpoint(srcPt554);
+ ConnEnd dstPt554(Point(2968.99, 2297.05), 15);
+ connRef554->setDestEndpoint(dstPt554);
+ connRef554->setRoutingType((ConnType)2);
+
+ ConnRef *connRef555 = new ConnRef(router, 555);
+ ConnEnd srcPt555(Point(3231.44, 914.5), 8);
+ connRef555->setSourceEndpoint(srcPt555);
+ ConnEnd dstPt555(Point(3216.44, 2185.05), 15);
+ connRef555->setDestEndpoint(dstPt555);
+ connRef555->setRoutingType((ConnType)2);
+
+ ConnRef *connRef556 = new ConnRef(router, 556);
+ ConnEnd srcPt556(Point(2384.71, 2185.05), 4);
+ connRef556->setSourceEndpoint(srcPt556);
+ ConnEnd dstPt556(Point(2041.79, 2185.05), 15);
+ connRef556->setDestEndpoint(dstPt556);
+ connRef556->setRoutingType((ConnType)2);
+
+ ConnRef *connRef557 = new ConnRef(router, 557);
+ ConnEnd srcPt557(Point(711.958, 1425.24), 1);
+ connRef557->setSourceEndpoint(srcPt557);
+ ConnEnd dstPt557(Point(1073.18, 1440.24), 15);
+ connRef557->setDestEndpoint(dstPt557);
+ connRef557->setRoutingType((ConnType)2);
+
+ ConnRef *connRef558 = new ConnRef(router, 558);
+ ConnEnd srcPt558(Point(1385.86, 1425.24), 1);
+ connRef558->setSourceEndpoint(srcPt558);
+ ConnEnd dstPt558(Point(1782.79, 1378.24), 15);
+ connRef558->setDestEndpoint(dstPt558);
+ connRef558->setRoutingType((ConnType)2);
+
+ ConnRef *connRef559 = new ConnRef(router, 559);
+ ConnEnd srcPt559(Point(595.333, 2477.3), 4);
+ connRef559->setSourceEndpoint(srcPt559);
+ ConnEnd dstPt559(Point(610.333, 2529.3), 15);
+ connRef559->setDestEndpoint(dstPt559);
+ connRef559->setRoutingType((ConnType)2);
+
+ ConnRef *connRef560 = new ConnRef(router, 560);
+ ConnEnd srcPt560(Point(610.333, 2627.3), 2);
+ connRef560->setSourceEndpoint(srcPt560);
+ ConnEnd dstPt560(Point(610.333, 2674.3), 15);
+ connRef560->setDestEndpoint(dstPt560);
+ connRef560->setRoutingType((ConnType)2);
+
+ ConnRef *connRef561 = new ConnRef(router, 561);
+ ConnEnd srcPt561(Point(1480.87, 2053.77), 15);
+ connRef561->setSourceEndpoint(srcPt561);
+ ConnEnd dstPt561(Point(610.333, 2945.3), 15);
+ connRef561->setDestEndpoint(dstPt561);
+ connRef561->setRoutingType((ConnType)2);
+
+ ConnRef *connRef562 = new ConnRef(router, 562);
+ ConnEnd srcPt562(Point(1197.96, 2627.3), 2);
+ connRef562->setSourceEndpoint(srcPt562);
+ ConnEnd dstPt562(Point(1563.6, 2945.3), 15);
+ connRef562->setDestEndpoint(dstPt562);
+ connRef562->setRoutingType((ConnType)2);
+
+ ConnRef *connRef563 = new ConnRef(router, 563);
+ ConnEnd srcPt563(Point(1315.96, 2627.3), 2);
+ connRef563->setSourceEndpoint(srcPt563);
+ ConnEnd dstPt563(Point(1563.6, 2945.3), 15);
+ connRef563->setDestEndpoint(dstPt563);
+ connRef563->setRoutingType((ConnType)2);
+
+ ConnRef *connRef564 = new ConnRef(router, 564);
+ ConnEnd srcPt564(Point(1646.79, 2772.3), 2);
+ connRef564->setSourceEndpoint(srcPt564);
+ ConnEnd dstPt564(Point(1563.6, 2945.3), 15);
+ connRef564->setDestEndpoint(dstPt564);
+ connRef564->setRoutingType((ConnType)2);
+
+ ConnRef *connRef565 = new ConnRef(router, 565);
+ ConnEnd srcPt565(Point(1563.6, 2703.3), 2);
+ connRef565->setSourceEndpoint(srcPt565);
+ ConnEnd dstPt565(Point(1563.6, 2945.3), 15);
+ connRef565->setDestEndpoint(dstPt565);
+ connRef565->setRoutingType((ConnType)2);
+
+ ConnRef *connRef566 = new ConnRef(router, 566);
+ ConnEnd srcPt566(Point(1538.46, 2772.3), 2);
+ connRef566->setSourceEndpoint(srcPt566);
+ ConnEnd dstPt566(Point(1563.6, 2945.3), 15);
+ connRef566->setDestEndpoint(dstPt566);
+ connRef566->setRoutingType((ConnType)2);
+
+ ConnRef *connRef567 = new ConnRef(router, 567);
+ ConnEnd srcPt567(Point(2492.71, 2955.3), 8);
+ connRef567->setSourceEndpoint(srcPt567);
+ ConnEnd dstPt567(Point(2547.71, 2945.3), 15);
+ connRef567->setDestEndpoint(dstPt567);
+ connRef567->setRoutingType((ConnType)2);
+
+ ConnRef *connRef568 = new ConnRef(router, 568);
+ ConnEnd srcPt568(Point(850.958, 2492.3), 2);
+ connRef568->setSourceEndpoint(srcPt568);
+ ConnEnd dstPt568(Point(876.358, 2529.3), 15);
+ connRef568->setDestEndpoint(dstPt568);
+ connRef568->setRoutingType((ConnType)2);
+
+ ConnRef *connRef569 = new ConnRef(router, 569);
+ ConnEnd srcPt569(Point(943.958, 2477.3), 4);
+ connRef569->setSourceEndpoint(srcPt569);
+ ConnEnd dstPt569(Point(876.358, 2529.3), 15);
+ connRef569->setDestEndpoint(dstPt569);
+ connRef569->setRoutingType((ConnType)2);
+
+ ConnRef *connRef570 = new ConnRef(router, 570);
+ ConnEnd srcPt570(Point(876.358, 2627.3), 2);
+ connRef570->setSourceEndpoint(srcPt570);
+ ConnEnd dstPt570(Point(876.358, 2674.3), 15);
+ connRef570->setDestEndpoint(dstPt570);
+ connRef570->setRoutingType((ConnType)2);
+
+ ConnRef *connRef571 = new ConnRef(router, 571);
+ ConnEnd srcPt571(Point(876.358, 2772.3), 2);
+ connRef571->setSourceEndpoint(srcPt571);
+ ConnEnd dstPt571(Point(876.358, 2945.3), 15);
+ connRef571->setDestEndpoint(dstPt571);
+ connRef571->setRoutingType((ConnType)2);
+
+ ConnRef *connRef572 = new ConnRef(router, 572);
+ ConnEnd srcPt572(Point(2186.79, 1041.64), 8);
+ connRef572->setSourceEndpoint(srcPt572);
+ ConnEnd dstPt572(Point(2241.79, 1041.64), 15);
+ connRef572->setDestEndpoint(dstPt572);
+ connRef572->setRoutingType((ConnType)2);
+
+ ConnRef *connRef573 = new ConnRef(router, 573);
+ ConnEnd srcPt573(Point(2492.71, 1041.64), 8);
+ connRef573->setSourceEndpoint(srcPt573);
+ ConnEnd dstPt573(Point(2547.71, 1041.64), 15);
+ connRef573->setDestEndpoint(dstPt573);
+ connRef573->setRoutingType((ConnType)2);
+
+ ConnRef *connRef574 = new ConnRef(router, 574);
+ ConnEnd srcPt574(Point(3478.07, 2185.05), 15);
+ connRef574->setSourceEndpoint(srcPt574);
+ ConnEnd dstPt574(Point(3478.07, 2597.3), 1);
+ connRef574->setDestEndpoint(dstPt574);
+ connRef574->setRoutingType((ConnType)2);
+
+ ConnRef *connRef575 = new ConnRef(router, 575);
+ ConnEnd srcPt575(Point(3596.07, 2185.05), 15);
+ connRef575->setSourceEndpoint(srcPt575);
+ ConnEnd dstPt575(Point(3596.07, 2597.3), 1);
+ connRef575->setDestEndpoint(dstPt575);
+ connRef575->setRoutingType((ConnType)2);
+
+ ConnRef *connRef576 = new ConnRef(router, 576);
+ ConnEnd srcPt576(Point(2041.79, 1291.24), 2);
+ connRef576->setSourceEndpoint(srcPt576);
+ ConnEnd dstPt576(Point(2041.79, 1569.64), 15);
+ connRef576->setDestEndpoint(dstPt576);
+ connRef576->setRoutingType((ConnType)2);
+
+ ConnRef *connRef577 = new ConnRef(router, 577);
+ ConnEnd srcPt577(Point(1797.79, 3401.3), 8);
+ connRef577->setSourceEndpoint(srcPt577);
+ ConnEnd dstPt577(Point(1861.79, 3209.3), 15);
+ connRef577->setDestEndpoint(dstPt577);
+ connRef577->setRoutingType((ConnType)2);
+
+ ConnRef *connRef578 = new ConnRef(router, 578);
+ ConnEnd srcPt578(Point(1797.79, 3197.3), 8);
+ connRef578->setSourceEndpoint(srcPt578);
+ ConnEnd dstPt578(Point(1861.79, 3209.3), 15);
+ connRef578->setDestEndpoint(dstPt578);
+ connRef578->setRoutingType((ConnType)2);
+
+ ConnRef *connRef579 = new ConnRef(router, 579);
+ ConnEnd srcPt579(Point(2760.54, 123.5), 4);
+ connRef579->setSourceEndpoint(srcPt579);
+ ConnEnd dstPt579(Point(2241.79, 220.875), 15);
+ connRef579->setDestEndpoint(dstPt579);
+ connRef579->setRoutingType((ConnType)2);
+
+ ConnRef *connRef580 = new ConnRef(router, 580);
+ ConnEnd srcPt580(Point(2760.54, 123.5), 4);
+ connRef580->setSourceEndpoint(srcPt580);
+ ConnEnd dstPt580(Point(2547.71, 220.875), 15);
+ connRef580->setDestEndpoint(dstPt580);
+ connRef580->setRoutingType((ConnType)2);
+
+ ConnRef *connRef581 = new ConnRef(router, 581);
+ ConnEnd srcPt581(Point(2156.79, 220.875), 4);
+ connRef581->setSourceEndpoint(srcPt581);
+ ConnEnd dstPt581(Point(2041.79, 220.875), 15);
+ connRef581->setDestEndpoint(dstPt581);
+ connRef581->setRoutingType((ConnType)2);
+
+ ConnRef *connRef582 = new ConnRef(router, 582);
+ ConnEnd srcPt582(Point(2041.79, 2185.05), 15);
+ connRef582->setSourceEndpoint(srcPt582);
+ ConnEnd dstPt582(Point(1941.79, 2185.05), 8);
+ connRef582->setDestEndpoint(dstPt582);
+ connRef582->setRoutingType((ConnType)2);
+
+ ConnRef *connRef583 = new ConnRef(router, 583);
+ ConnEnd srcPt583(Point(1775.79, 1872.95), 15);
+ connRef583->setSourceEndpoint(srcPt583);
+ ConnEnd dstPt583(Point(1479.46, 1872.95), 8);
+ connRef583->setDestEndpoint(dstPt583);
+ connRef583->setRoutingType((ConnType)2);
+
+ ConnRef *connRef584 = new ConnRef(router, 584);
+ ConnEnd srcPt584(Point(1911.79, 1872.95), 4);
+ connRef584->setSourceEndpoint(srcPt584);
+ ConnEnd dstPt584(Point(1775.79, 1872.95), 15);
+ connRef584->setDestEndpoint(dstPt584);
+ connRef584->setRoutingType((ConnType)2);
+
+ ConnRef *connRef585 = new ConnRef(router, 585);
+ ConnEnd srcPt585(Point(1449.46, 1872.95), 4);
+ connRef585->setSourceEndpoint(srcPt585);
+ ConnEnd dstPt585(Point(1073.18, 1872.95), 15);
+ connRef585->setDestEndpoint(dstPt585);
+ connRef585->setRoutingType((ConnType)2);
+
+ ConnRef *connRef586 = new ConnRef(router, 586);
+ ConnEnd srcPt586(Point(1073.18, 1872.95), 15);
+ connRef586->setSourceEndpoint(srcPt586);
+ ConnEnd dstPt586(Point(987.958, 1872.95), 8);
+ connRef586->setDestEndpoint(dstPt586);
+ connRef586->setRoutingType((ConnType)2);
+
+ ConnRef *connRef587 = new ConnRef(router, 587);
+ ConnEnd srcPt587(Point(957.958, 1872.95), 4);
+ connRef587->setSourceEndpoint(srcPt587);
+ ConnEnd dstPt587(Point(876.358, 1872.95), 15);
+ connRef587->setDestEndpoint(dstPt587);
+ connRef587->setRoutingType((ConnType)2);
+
+ ConnRef *connRef588 = new ConnRef(router, 588);
+ ConnEnd srcPt588(Point(3089.24, 316.75), 2);
+ connRef588->setSourceEndpoint(srcPt588);
+ ConnEnd dstPt588(Point(3114.24, 437.7), 15);
+ connRef588->setDestEndpoint(dstPt588);
+ connRef588->setRoutingType((ConnType)2);
+
+ ConnRef *connRef589 = new ConnRef(router, 589);
+ ConnEnd srcPt589(Point(2041.79, 2674.3), 15);
+ connRef589->setSourceEndpoint(srcPt589);
+ ConnEnd dstPt589(Point(2041.79, 2734.3), 1);
+ connRef589->setDestEndpoint(dstPt589);
+ connRef589->setRoutingType((ConnType)2);
+
+ ConnRef *connRef590 = new ConnRef(router, 590);
+ ConnEnd srcPt590(Point(2041.79, 2764.3), 2);
+ connRef590->setSourceEndpoint(srcPt590);
+ ConnEnd dstPt590(Point(2241.79, 2945.3), 15);
+ connRef590->setDestEndpoint(dstPt590);
+ connRef590->setRoutingType((ConnType)2);
+
+ ConnRef *connRef591 = new ConnRef(router, 591);
+ ConnEnd srcPt591(Point(1861.79, 2674.3), 15);
+ connRef591->setSourceEndpoint(srcPt591);
+ ConnEnd dstPt591(Point(1861.79, 2734.3), 1);
+ connRef591->setDestEndpoint(dstPt591);
+ connRef591->setRoutingType((ConnType)2);
+
+ ConnRef *connRef592 = new ConnRef(router, 592);
+ ConnEnd srcPt592(Point(1861.79, 2764.3), 2);
+ connRef592->setSourceEndpoint(srcPt592);
+ ConnEnd dstPt592(Point(1861.79, 2811.3), 15);
+ connRef592->setDestEndpoint(dstPt592);
+ connRef592->setRoutingType((ConnType)2);
+
+ ConnRef *connRef593 = new ConnRef(router, 593);
+ ConnEnd srcPt593(Point(1073.18, 569.7), 15);
+ connRef593->setSourceEndpoint(srcPt593);
+ ConnEnd dstPt593(Point(1214.46, 569.7), 4);
+ connRef593->setDestEndpoint(dstPt593);
+ connRef593->setRoutingType((ConnType)2);
+
+ ConnRef *connRef594 = new ConnRef(router, 594);
+ ConnEnd srcPt594(Point(1073.18, 693.5), 1);
+ connRef594->setSourceEndpoint(srcPt594);
+ ConnEnd dstPt594(Point(1073.18, 569.7), 15);
+ connRef594->setDestEndpoint(dstPt594);
+ connRef594->setRoutingType((ConnType)2);
+
+ ConnRef *connRef595 = new ConnRef(router, 595);
+ ConnEnd srcPt595(Point(876.358, 554.7), 1);
+ connRef595->setSourceEndpoint(srcPt595);
+ ConnEnd dstPt595(Point(876.358, 375.5), 15);
+ connRef595->setDestEndpoint(dstPt595);
+ connRef595->setRoutingType((ConnType)2);
+
+ ConnRef *connRef596 = new ConnRef(router, 596);
+ ConnEnd srcPt596(Point(781.958, 715.5), 15);
+ connRef596->setSourceEndpoint(srcPt596);
+ ConnEnd dstPt596(Point(876.358, 584.7), 2);
+ connRef596->setDestEndpoint(dstPt596);
+ connRef596->setRoutingType((ConnType)2);
+
+ ConnRef *connRef597 = new ConnRef(router, 597);
+ ConnEnd srcPt597(Point(404.333, 527.5), 2);
+ connRef597->setSourceEndpoint(srcPt597);
+ ConnEnd dstPt597(Point(323, 833.833), 15);
+ connRef597->setDestEndpoint(dstPt597);
+ connRef597->setRoutingType((ConnType)2);
+
+ ConnRef *connRef598 = new ConnRef(router, 598);
+ ConnEnd srcPt598(Point(2492.71, 2864.3), 8);
+ connRef598->setSourceEndpoint(srcPt598);
+ ConnEnd dstPt598(Point(2547.71, 2945.3), 15);
+ connRef598->setDestEndpoint(dstPt598);
+ connRef598->setRoutingType((ConnType)2);
+
+ ConnRef *connRef599 = new ConnRef(router, 599);
+ ConnEnd srcPt599(Point(3119.9, 2529.3), 15);
+ connRef599->setSourceEndpoint(srcPt599);
+ ConnEnd dstPt599(Point(2895.99, 2612.3), 4);
+ connRef599->setDestEndpoint(dstPt599);
+ connRef599->setRoutingType((ConnType)2);
+
+ ConnRef *connRef600 = new ConnRef(router, 600);
+ ConnEnd srcPt600(Point(3119.9, 2529.3), 15);
+ connRef600->setSourceEndpoint(srcPt600);
+ ConnEnd dstPt600(Point(3242.24, 2597.3), 1);
+ connRef600->setDestEndpoint(dstPt600);
+ connRef600->setRoutingType((ConnType)2);
+
+ ConnRef *connRef601 = new ConnRef(router, 601);
+ ConnEnd srcPt601(Point(2925.99, 2612.3), 8);
+ connRef601->setSourceEndpoint(srcPt601);
+ ConnEnd dstPt601(Point(2968.99, 2674.3), 15);
+ connRef601->setDestEndpoint(dstPt601);
+ connRef601->setRoutingType((ConnType)2);
+
+ ConnRef *connRef602 = new ConnRef(router, 602);
+ ConnEnd srcPt602(Point(3119.9, 2872.3), 15);
+ connRef602->setSourceEndpoint(srcPt602);
+ ConnEnd dstPt602(Point(2869.99, 3071.3), 4);
+ connRef602->setDestEndpoint(dstPt602);
+ connRef602->setRoutingType((ConnType)2);
+
+ ConnRef *connRef603 = new ConnRef(router, 603);
+ ConnEnd srcPt603(Point(3119.9, 2872.3), 15);
+ connRef603->setSourceEndpoint(srcPt603);
+ ConnEnd dstPt603(Point(3326.74, 3056.3), 1);
+ connRef603->setDestEndpoint(dstPt603);
+ connRef603->setRoutingType((ConnType)2);
+
+ ConnRef *connRef604 = new ConnRef(router, 604);
+ ConnEnd srcPt604(Point(3242.24, 2627.3), 2);
+ connRef604->setSourceEndpoint(srcPt604);
+ ConnEnd dstPt604(Point(3221.24, 2674.3), 15);
+ connRef604->setDestEndpoint(dstPt604);
+ connRef604->setRoutingType((ConnType)2);
+
+ ConnRef *connRef605 = new ConnRef(router, 605);
+ ConnEnd srcPt605(Point(2899.99, 3071.3), 8);
+ connRef605->setSourceEndpoint(srcPt605);
+ ConnEnd dstPt605(Point(2968.99, 3209.3), 15);
+ connRef605->setDestEndpoint(dstPt605);
+ connRef605->setRoutingType((ConnType)2);
+
+ ConnRef *connRef606 = new ConnRef(router, 606);
+ ConnEnd srcPt606(Point(3326.74, 3086.3), 2);
+ connRef606->setSourceEndpoint(srcPt606);
+ ConnEnd dstPt606(Point(3216.44, 3209.3), 15);
+ connRef606->setDestEndpoint(dstPt606);
+ connRef606->setRoutingType((ConnType)2);
+
+ ConnRef *connRef607 = new ConnRef(router, 607);
+ ConnEnd srcPt607(Point(1797.79, 3299.3), 8);
+ connRef607->setSourceEndpoint(srcPt607);
+ ConnEnd dstPt607(Point(1861.79, 3209.3), 15);
+ connRef607->setDestEndpoint(dstPt607);
+ connRef607->setRoutingType((ConnType)2);
+
+ ConnRef *connRef608 = new ConnRef(router, 608);
+ ConnEnd srcPt608(Point(162, 512.5), 8);
+ connRef608->setSourceEndpoint(srcPt608);
+ ConnEnd dstPt608(Point(220, 512.5), 4);
+ connRef608->setDestEndpoint(dstPt608);
+ connRef608->setRoutingType((ConnType)2);
+
+ ConnRef *connRef609 = new ConnRef(router, 609);
+ ConnEnd srcPt609(Point(73, 648.5), 8);
+ connRef609->setSourceEndpoint(srcPt609);
+ ConnEnd dstPt609(Point(131, 648.5), 4);
+ connRef609->setDestEndpoint(dstPt609);
+ connRef609->setRoutingType((ConnType)2);
+
+ ConnRef *connRef610 = new ConnRef(router, 610);
+ ConnEnd srcPt610(Point(540.333, 658.5), 2);
+ connRef610->setSourceEndpoint(srcPt610);
+ ConnEnd dstPt610(Point(540.333, 708.5), 1);
+ connRef610->setDestEndpoint(dstPt610);
+ connRef610->setRoutingType((ConnType)2);
+
+ ConnRef *connRef611 = new ConnRef(router, 611);
+ ConnEnd srcPt611(Point(540.333, 783.833), 2);
+ connRef611->setSourceEndpoint(srcPt611);
+ ConnEnd dstPt611(Point(540.333, 833.833), 1);
+ connRef611->setDestEndpoint(dstPt611);
+ connRef611->setRoutingType((ConnType)2);
+
+ ConnRef *connRef612 = new ConnRef(router, 612);
+ ConnEnd srcPt612(Point(1453.46, 708.5), 4);
+ connRef612->setSourceEndpoint(srcPt612);
+ ConnEnd dstPt612(Point(1395.46, 708.5), 8);
+ connRef612->setDestEndpoint(dstPt612);
+ connRef612->setRoutingType((ConnType)2);
+
+ ConnRef *connRef613 = new ConnRef(router, 613);
+ ConnEnd srcPt613(Point(1542.46, 241.5), 2);
+ connRef613->setSourceEndpoint(srcPt613);
+ ConnEnd dstPt613(Point(1542.46, 291.5), 1);
+ connRef613->setDestEndpoint(dstPt613);
+ connRef613->setRoutingType((ConnType)2);
+
+ ConnRef *connRef614 = new ConnRef(router, 614);
+ ConnEnd srcPt614(Point(1942.29, 241.5), 2);
+ connRef614->setSourceEndpoint(srcPt614);
+ ConnEnd dstPt614(Point(1942.29, 291.5), 1);
+ connRef614->setDestEndpoint(dstPt614);
+ connRef614->setRoutingType((ConnType)2);
+
+ ConnRef *connRef615 = new ConnRef(router, 615);
+ ConnEnd srcPt615(Point(2026.79, 727.5), 2);
+ connRef615->setSourceEndpoint(srcPt615);
+ ConnEnd dstPt615(Point(2026.79, 777.5), 1);
+ connRef615->setDestEndpoint(dstPt615);
+ connRef615->setRoutingType((ConnType)2);
+
+ ConnRef *connRef616 = new ConnRef(router, 616);
+ ConnEnd srcPt616(Point(540.333, 1226.24), 2);
+ connRef616->setSourceEndpoint(srcPt616);
+ ConnEnd dstPt616(Point(540.333, 1276.24), 1);
+ connRef616->setDestEndpoint(dstPt616);
+ connRef616->setRoutingType((ConnType)2);
+
+ ConnRef *connRef617 = new ConnRef(router, 617);
+ ConnEnd srcPt617(Point(711.958, 1226.24), 2);
+ connRef617->setSourceEndpoint(srcPt617);
+ ConnEnd dstPt617(Point(711.958, 1276.24), 1);
+ connRef617->setDestEndpoint(dstPt617);
+ connRef617->setRoutingType((ConnType)2);
+
+ ConnRef *connRef618 = new ConnRef(router, 618);
+ ConnEnd srcPt618(Point(972.958, 1226.24), 2);
+ connRef618->setSourceEndpoint(srcPt618);
+ ConnEnd dstPt618(Point(972.958, 1276.24), 1);
+ connRef618->setDestEndpoint(dstPt618);
+ connRef618->setRoutingType((ConnType)2);
+
+ ConnRef *connRef619 = new ConnRef(router, 619);
+ ConnEnd srcPt619(Point(992.958, 1143.64), 8);
+ connRef619->setSourceEndpoint(srcPt619);
+ ConnEnd dstPt619(Point(1050.96, 1143.64), 4);
+ connRef619->setDestEndpoint(dstPt619);
+ connRef619->setRoutingType((ConnType)2);
+
+ ConnRef *connRef620 = new ConnRef(router, 620);
+ ConnEnd srcPt620(Point(1385.86, 919.5), 2);
+ connRef620->setSourceEndpoint(srcPt620);
+ ConnEnd dstPt620(Point(1385.86, 969.5), 1);
+ connRef620->setDestEndpoint(dstPt620);
+ connRef620->setRoutingType((ConnType)2);
+
+ ConnRef *connRef621 = new ConnRef(router, 621);
+ ConnEnd srcPt621(Point(1385.86, 1091.64), 1);
+ connRef621->setSourceEndpoint(srcPt621);
+ ConnEnd dstPt621(Point(1385.86, 1041.64), 2);
+ connRef621->setDestEndpoint(dstPt621);
+ connRef621->setRoutingType((ConnType)2);
+
+ ConnRef *connRef622 = new ConnRef(router, 622);
+ ConnEnd srcPt622(Point(1385.86, 1193.64), 1);
+ connRef622->setSourceEndpoint(srcPt622);
+ ConnEnd dstPt622(Point(1385.86, 1143.64), 2);
+ connRef622->setDestEndpoint(dstPt622);
+ connRef622->setRoutingType((ConnType)2);
+
+ ConnRef *connRef623 = new ConnRef(router, 623);
+ ConnEnd srcPt623(Point(1704.79, 1276.24), 4);
+ connRef623->setSourceEndpoint(srcPt623);
+ ConnEnd dstPt623(Point(1646.79, 1276.24), 8);
+ connRef623->setDestEndpoint(dstPt623);
+ connRef623->setRoutingType((ConnType)2);
+
+ ConnRef *connRef624 = new ConnRef(router, 624);
+ ConnEnd srcPt624(Point(1926.79, 1703.64), 1);
+ connRef624->setSourceEndpoint(srcPt624);
+ ConnEnd dstPt624(Point(1926.79, 1653.64), 2);
+ connRef624->setDestEndpoint(dstPt624);
+ connRef624->setRoutingType((ConnType)2);
+
+ ConnRef *connRef625 = new ConnRef(router, 625);
+ ConnEnd srcPt625(Point(2016.29, 1440.24), 4);
+ connRef625->setSourceEndpoint(srcPt625);
+ ConnEnd dstPt625(Point(1958.29, 1440.24), 8);
+ connRef625->setDestEndpoint(dstPt625);
+ connRef625->setRoutingType((ConnType)2);
+
+ ConnRef *connRef626 = new ConnRef(router, 626);
+ ConnEnd srcPt626(Point(2099.79, 1722.64), 4);
+ connRef626->setSourceEndpoint(srcPt626);
+ ConnEnd dstPt626(Point(2041.79, 1722.64), 8);
+ connRef626->setDestEndpoint(dstPt626);
+ connRef626->setRoutingType((ConnType)2);
+
+ ConnRef *connRef627 = new ConnRef(router, 627);
+ ConnEnd srcPt627(Point(2171.79, 1519.64), 2);
+ connRef627->setSourceEndpoint(srcPt627);
+ ConnEnd dstPt627(Point(2171.79, 1569.64), 1);
+ connRef627->setDestEndpoint(dstPt627);
+ connRef627->setRoutingType((ConnType)2);
+
+ ConnRef *connRef628 = new ConnRef(router, 628);
+ ConnEnd srcPt628(Point(2299.79, 1440.24), 4);
+ connRef628->setSourceEndpoint(srcPt628);
+ ConnEnd dstPt628(Point(2241.79, 1440.24), 8);
+ connRef628->setDestEndpoint(dstPt628);
+ connRef628->setRoutingType((ConnType)2);
+
+ ConnRef *connRef629 = new ConnRef(router, 629);
+ ConnEnd srcPt629(Point(2477.71, 1459.44), 2);
+ connRef629->setSourceEndpoint(srcPt629);
+ ConnEnd dstPt629(Point(2477.71, 1509.44), 1);
+ connRef629->setDestEndpoint(dstPt629);
+ connRef629->setRoutingType((ConnType)2);
+
+ ConnRef *connRef630 = new ConnRef(router, 630);
+ ConnEnd srcPt630(Point(2477.71, 1631.64), 1);
+ connRef630->setSourceEndpoint(srcPt630);
+ ConnEnd dstPt630(Point(2477.71, 1581.64), 2);
+ connRef630->setDestEndpoint(dstPt630);
+ connRef630->setRoutingType((ConnType)2);
+
+ ConnRef *connRef631 = new ConnRef(router, 631);
+ ConnEnd srcPt631(Point(2171.79, 1822.95), 2);
+ connRef631->setSourceEndpoint(srcPt631);
+ ConnEnd dstPt631(Point(2171.79, 1872.95), 1);
+ connRef631->setDestEndpoint(dstPt631);
+ connRef631->setRoutingType((ConnType)2);
+
+ ConnRef *connRef632 = new ConnRef(router, 632);
+ ConnEnd srcPt632(Point(2477.71, 1963.95), 2);
+ connRef632->setSourceEndpoint(srcPt632);
+ ConnEnd dstPt632(Point(2477.71, 2013.95), 1);
+ connRef632->setDestEndpoint(dstPt632);
+ connRef632->setRoutingType((ConnType)2);
+
+ ConnRef *connRef633 = new ConnRef(router, 633);
+ ConnEnd srcPt633(Point(2477.71, 2105.95), 1);
+ connRef633->setSourceEndpoint(srcPt633);
+ ConnEnd dstPt633(Point(2477.71, 2055.95), 2);
+ connRef633->setDestEndpoint(dstPt633);
+ connRef633->setRoutingType((ConnType)2);
+
+ ConnRef *connRef634 = new ConnRef(router, 634);
+ ConnEnd srcPt634(Point(2660.54, 1762.64), 2);
+ connRef634->setSourceEndpoint(srcPt634);
+ ConnEnd dstPt634(Point(2660.54, 1812.64), 1);
+ connRef634->setDestEndpoint(dstPt634);
+ connRef634->setRoutingType((ConnType)2);
+
+ ConnRef *connRef635 = new ConnRef(router, 635);
+ ConnEnd srcPt635(Point(2637.54, 1934.95), 1);
+ connRef635->setSourceEndpoint(srcPt635);
+ ConnEnd dstPt635(Point(2637.54, 1884.95), 2);
+ connRef635->setDestEndpoint(dstPt635);
+ connRef635->setRoutingType((ConnType)2);
+
+ ConnRef *connRef636 = new ConnRef(router, 636);
+ ConnEnd srcPt636(Point(2735.54, 1934.95), 1);
+ connRef636->setSourceEndpoint(srcPt636);
+ ConnEnd dstPt636(Point(2735.54, 1884.95), 2);
+ connRef636->setDestEndpoint(dstPt636);
+ connRef636->setRoutingType((ConnType)2);
+
+ ConnRef *connRef637 = new ConnRef(router, 637);
+ ConnEnd srcPt637(Point(2898.99, 1762.64), 2);
+ connRef637->setSourceEndpoint(srcPt637);
+ ConnEnd dstPt637(Point(2898.99, 1812.64), 1);
+ connRef637->setDestEndpoint(dstPt637);
+ connRef637->setRoutingType((ConnType)2);
+
+ ConnRef *connRef638 = new ConnRef(router, 638);
+ ConnEnd srcPt638(Point(2875.99, 1934.95), 1);
+ connRef638->setSourceEndpoint(srcPt638);
+ ConnEnd dstPt638(Point(2875.99, 1884.95), 2);
+ connRef638->setDestEndpoint(dstPt638);
+ connRef638->setRoutingType((ConnType)2);
+
+ ConnRef *connRef639 = new ConnRef(router, 639);
+ ConnEnd srcPt639(Point(2953.99, 1934.95), 1);
+ connRef639->setSourceEndpoint(srcPt639);
+ ConnEnd dstPt639(Point(2953.99, 1884.95), 2);
+ connRef639->setDestEndpoint(dstPt639);
+ connRef639->setRoutingType((ConnType)2);
+
+ ConnRef *connRef640 = new ConnRef(router, 640);
+ ConnEnd srcPt640(Point(2299.79, 708.5), 4);
+ connRef640->setSourceEndpoint(srcPt640);
+ ConnEnd dstPt640(Point(2241.79, 708.5), 8);
+ connRef640->setDestEndpoint(dstPt640);
+ connRef640->setRoutingType((ConnType)2);
+
+ ConnRef *connRef641 = new ConnRef(router, 641);
+ ConnEnd srcPt641(Point(2605.71, 708.5), 4);
+ connRef641->setSourceEndpoint(srcPt641);
+ ConnEnd dstPt641(Point(2547.71, 708.5), 8);
+ connRef641->setDestEndpoint(dstPt641);
+ connRef641->setRoutingType((ConnType)2);
+
+ ConnRef *connRef642 = new ConnRef(router, 642);
+ ConnEnd srcPt642(Point(2845.54, 708.5), 4);
+ connRef642->setSourceEndpoint(srcPt642);
+ ConnEnd dstPt642(Point(2787.54, 708.5), 8);
+ connRef642->setDestEndpoint(dstPt642);
+ connRef642->setRoutingType((ConnType)2);
+
+ ConnRef *connRef643 = new ConnRef(router, 643);
+ ConnEnd srcPt643(Point(3026.99, 708.5), 4);
+ connRef643->setSourceEndpoint(srcPt643);
+ ConnEnd dstPt643(Point(2968.99, 708.5), 8);
+ connRef643->setDestEndpoint(dstPt643);
+ connRef643->setRoutingType((ConnType)2);
+
+ ConnRef *connRef644 = new ConnRef(router, 644);
+ ConnEnd srcPt644(Point(3026.99, 914.5), 4);
+ connRef644->setSourceEndpoint(srcPt644);
+ ConnEnd dstPt644(Point(2968.99, 914.5), 8);
+ connRef644->setDestEndpoint(dstPt644);
+ connRef644->setRoutingType((ConnType)2);
+
+ ConnRef *connRef645 = new ConnRef(router, 645);
+ ConnEnd srcPt645(Point(2299.79, 301.75), 4);
+ connRef645->setSourceEndpoint(srcPt645);
+ ConnEnd dstPt645(Point(2241.79, 301.75), 8);
+ connRef645->setDestEndpoint(dstPt645);
+ connRef645->setRoutingType((ConnType)2);
+
+ ConnRef *connRef646 = new ConnRef(router, 646);
+ ConnEnd srcPt646(Point(2477.71, 170.875), 2);
+ connRef646->setSourceEndpoint(srcPt646);
+ ConnEnd dstPt646(Point(2477.71, 220.875), 1);
+ connRef646->setDestEndpoint(dstPt646);
+ connRef646->setRoutingType((ConnType)2);
+
+ ConnRef *connRef647 = new ConnRef(router, 647);
+ ConnEnd srcPt647(Point(2605.71, 301.75), 4);
+ connRef647->setSourceEndpoint(srcPt647);
+ ConnEnd dstPt647(Point(2547.71, 301.75), 8);
+ connRef647->setDestEndpoint(dstPt647);
+ connRef647->setRoutingType((ConnType)2);
+
+ ConnRef *connRef648 = new ConnRef(router, 648);
+ ConnEnd srcPt648(Point(2665.54, 170.875), 2);
+ connRef648->setSourceEndpoint(srcPt648);
+ ConnEnd dstPt648(Point(2665.54, 220.875), 1);
+ connRef648->setDestEndpoint(dstPt648);
+ connRef648->setRoutingType((ConnType)2);
+
+ ConnRef *connRef649 = new ConnRef(router, 649);
+ ConnEnd srcPt649(Point(2665.54, 387.7), 2);
+ connRef649->setSourceEndpoint(srcPt649);
+ ConnEnd dstPt649(Point(2665.54, 437.7), 1);
+ connRef649->setDestEndpoint(dstPt649);
+ connRef649->setRoutingType((ConnType)2);
+
+ ConnRef *connRef650 = new ConnRef(router, 650);
+ ConnEnd srcPt650(Point(2919.99, 387.7), 2);
+ connRef650->setSourceEndpoint(srcPt650);
+ ConnEnd dstPt650(Point(2919.99, 437.7), 1);
+ connRef650->setDestEndpoint(dstPt650);
+ connRef650->setRoutingType((ConnType)2);
+
+ ConnRef *connRef651 = new ConnRef(router, 651);
+ ConnEnd srcPt651(Point(3197.24, 301.75), 4);
+ connRef651->setSourceEndpoint(srcPt651);
+ ConnEnd dstPt651(Point(3139.24, 301.75), 8);
+ connRef651->setDestEndpoint(dstPt651);
+ connRef651->setRoutingType((ConnType)2);
+
+ ConnRef *connRef652 = new ConnRef(router, 652);
+ ConnEnd srcPt652(Point(3478.07, 864.5), 2);
+ connRef652->setSourceEndpoint(srcPt652);
+ ConnEnd dstPt652(Point(3478.07, 914.5), 1);
+ connRef652->setDestEndpoint(dstPt652);
+ connRef652->setRoutingType((ConnType)2);
+
+ ConnRef *connRef653 = new ConnRef(router, 653);
+ ConnEnd srcPt653(Point(3536.07, 1872.95), 4);
+ connRef653->setSourceEndpoint(srcPt653);
+ ConnEnd dstPt653(Point(3478.07, 1872.95), 8);
+ connRef653->setDestEndpoint(dstPt653);
+ connRef653->setRoutingType((ConnType)2);
+
+ ConnRef *connRef654 = new ConnRef(router, 654);
+ ConnEnd srcPt654(Point(3536.07, 2612.3), 4);
+ connRef654->setSourceEndpoint(srcPt654);
+ ConnEnd dstPt654(Point(3478.07, 2612.3), 8);
+ connRef654->setDestEndpoint(dstPt654);
+ connRef654->setRoutingType((ConnType)2);
+
+ ConnRef *connRef655 = new ConnRef(router, 655);
+ ConnEnd srcPt655(Point(2787.54, 3467.3), 1);
+ connRef655->setSourceEndpoint(srcPt655);
+ ConnEnd dstPt655(Point(2787.54, 3417.3), 2);
+ connRef655->setDestEndpoint(dstPt655);
+ connRef655->setRoutingType((ConnType)2);
+
+ ConnRef *connRef656 = new ConnRef(router, 656);
+ ConnEnd srcPt656(Point(2787.54, 3569.3), 1);
+ connRef656->setSourceEndpoint(srcPt656);
+ ConnEnd dstPt656(Point(2787.54, 3519.3), 2);
+ connRef656->setDestEndpoint(dstPt656);
+ connRef656->setRoutingType((ConnType)2);
+
+ ConnRef *connRef657 = new ConnRef(router, 657);
+ ConnEnd srcPt657(Point(3654.07, 2612.3), 4);
+ connRef657->setSourceEndpoint(srcPt657);
+ ConnEnd dstPt657(Point(3596.07, 2612.3), 8);
+ connRef657->setDestEndpoint(dstPt657);
+ connRef657->setRoutingType((ConnType)2);
+
+ ConnRef *connRef658 = new ConnRef(router, 658);
+ ConnEnd srcPt658(Point(3654.07, 914.5), 4);
+ connRef658->setSourceEndpoint(srcPt658);
+ ConnEnd dstPt658(Point(3596.07, 914.5), 8);
+ connRef658->setDestEndpoint(dstPt658);
+ connRef658->setRoutingType((ConnType)2);
+
+ ConnRef *connRef659 = new ConnRef(router, 659);
+ ConnEnd srcPt659(Point(3384.74, 914.5), 4);
+ connRef659->setSourceEndpoint(srcPt659);
+ ConnEnd dstPt659(Point(3326.74, 914.5), 8);
+ connRef659->setDestEndpoint(dstPt659);
+ connRef659->setRoutingType((ConnType)2);
+
+ ConnRef *connRef660 = new ConnRef(router, 660);
+ ConnEnd srcPt660(Point(3216.44, 2349.05), 2);
+ connRef660->setSourceEndpoint(srcPt660);
+ ConnEnd dstPt660(Point(3216.44, 2399.05), 1);
+ connRef660->setDestEndpoint(dstPt660);
+ connRef660->setRoutingType((ConnType)2);
+
+ ConnRef *connRef661 = new ConnRef(router, 661);
+ ConnEnd srcPt661(Point(3216.44, 2247.05), 2);
+ connRef661->setSourceEndpoint(srcPt661);
+ ConnEnd dstPt661(Point(3216.44, 2297.05), 1);
+ connRef661->setDestEndpoint(dstPt661);
+ connRef661->setRoutingType((ConnType)2);
+
+ ConnRef *connRef662 = new ConnRef(router, 662);
+ ConnEnd srcPt662(Point(2787.54, 2247.05), 2);
+ connRef662->setSourceEndpoint(srcPt662);
+ ConnEnd dstPt662(Point(2787.54, 2297.05), 1);
+ connRef662->setDestEndpoint(dstPt662);
+ connRef662->setRoutingType((ConnType)2);
+
+ ConnRef *connRef663 = new ConnRef(router, 663);
+ ConnEnd srcPt663(Point(3216.44, 864.5), 2);
+ connRef663->setSourceEndpoint(srcPt663);
+ ConnEnd dstPt663(Point(3216.44, 914.5), 1);
+ connRef663->setDestEndpoint(dstPt663);
+ connRef663->setRoutingType((ConnType)2);
+
+ ConnRef *connRef664 = new ConnRef(router, 664);
+ ConnEnd srcPt664(Point(2787.54, 2135.05), 2);
+ connRef664->setSourceEndpoint(srcPt664);
+ ConnEnd dstPt664(Point(2787.54, 2185.05), 1);
+ connRef664->setDestEndpoint(dstPt664);
+ connRef664->setRoutingType((ConnType)2);
+
+ ConnRef *connRef665 = new ConnRef(router, 665);
+ ConnEnd srcPt665(Point(2399.71, 2135.05), 2);
+ connRef665->setSourceEndpoint(srcPt665);
+ ConnEnd dstPt665(Point(2399.71, 2185.05), 1);
+ connRef665->setDestEndpoint(dstPt665);
+ connRef665->setRoutingType((ConnType)2);
+
+ ConnRef *connRef666 = new ConnRef(router, 666);
+ ConnEnd srcPt666(Point(1926.79, 2135.05), 2);
+ connRef666->setSourceEndpoint(srcPt666);
+ ConnEnd dstPt666(Point(1926.79, 2185.05), 1);
+ connRef666->setDestEndpoint(dstPt666);
+ connRef666->setRoutingType((ConnType)2);
+
+ ConnRef *connRef667 = new ConnRef(router, 667);
+ ConnEnd srcPt667(Point(711.958, 2135.05), 2);
+ connRef667->setSourceEndpoint(srcPt667);
+ ConnEnd dstPt667(Point(711.958, 2185.05), 1);
+ connRef667->setDestEndpoint(dstPt667);
+ connRef667->setRoutingType((ConnType)2);
+
+ ConnRef *connRef668 = new ConnRef(router, 668);
+ ConnEnd srcPt668(Point(1621.6, 2023.95), 4);
+ connRef668->setSourceEndpoint(srcPt668);
+ ConnEnd dstPt668(Point(1563.6, 2023.95), 8);
+ connRef668->setDestEndpoint(dstPt668);
+ connRef668->setRoutingType((ConnType)2);
+
+ ConnRef *connRef669 = new ConnRef(router, 669);
+ ConnEnd srcPt669(Point(711.958, 1328.24), 2);
+ connRef669->setSourceEndpoint(srcPt669);
+ ConnEnd dstPt669(Point(711.958, 1378.24), 1);
+ connRef669->setDestEndpoint(dstPt669);
+ connRef669->setRoutingType((ConnType)2);
+
+ ConnRef *connRef670 = new ConnRef(router, 670);
+ ConnEnd srcPt670(Point(769.958, 1440.24), 4);
+ connRef670->setSourceEndpoint(srcPt670);
+ ConnEnd dstPt670(Point(711.958, 1440.24), 8);
+ connRef670->setDestEndpoint(dstPt670);
+ connRef670->setRoutingType((ConnType)2);
+
+ ConnRef *connRef671 = new ConnRef(router, 671);
+ ConnEnd srcPt671(Point(1327.86, 1440.24), 8);
+ connRef671->setSourceEndpoint(srcPt671);
+ ConnEnd dstPt671(Point(1385.86, 1440.24), 4);
+ connRef671->setDestEndpoint(dstPt671);
+ connRef671->setRoutingType((ConnType)2);
+
+ ConnRef *connRef672 = new ConnRef(router, 672);
+ ConnEnd srcPt672(Point(610.333, 2427.3), 2);
+ connRef672->setSourceEndpoint(srcPt672);
+ ConnEnd dstPt672(Point(610.333, 2477.3), 1);
+ connRef672->setDestEndpoint(dstPt672);
+ connRef672->setRoutingType((ConnType)2);
+
+ ConnRef *connRef673 = new ConnRef(router, 673);
+ ConnEnd srcPt673(Point(668.333, 2612.3), 4);
+ connRef673->setSourceEndpoint(srcPt673);
+ ConnEnd dstPt673(Point(610.333, 2612.3), 8);
+ connRef673->setDestEndpoint(dstPt673);
+ connRef673->setRoutingType((ConnType)2);
+
+ ConnRef *connRef674 = new ConnRef(router, 674);
+ ConnEnd srcPt674(Point(610.333, 3121.3), 1);
+ connRef674->setSourceEndpoint(srcPt674);
+ ConnEnd dstPt674(Point(610.333, 3071.3), 2);
+ connRef674->setDestEndpoint(dstPt674);
+ connRef674->setRoutingType((ConnType)2);
+
+ ConnRef *connRef675 = new ConnRef(router, 675);
+ ConnEnd srcPt675(Point(1139.96, 2612.3), 8);
+ connRef675->setSourceEndpoint(srcPt675);
+ ConnEnd dstPt675(Point(1197.96, 2612.3), 4);
+ connRef675->setDestEndpoint(dstPt675);
+ connRef675->setRoutingType((ConnType)2);
+
+ ConnRef *connRef676 = new ConnRef(router, 676);
+ ConnEnd srcPt676(Point(1257.96, 2612.3), 8);
+ connRef676->setSourceEndpoint(srcPt676);
+ ConnEnd dstPt676(Point(1315.96, 2612.3), 4);
+ connRef676->setDestEndpoint(dstPt676);
+ connRef676->setRoutingType((ConnType)2);
+
+ ConnRef *connRef677 = new ConnRef(router, 677);
+ ConnEnd srcPt677(Point(1704.79, 2757.3), 4);
+ connRef677->setSourceEndpoint(srcPt677);
+ ConnEnd dstPt677(Point(1646.79, 2757.3), 8);
+ connRef677->setDestEndpoint(dstPt677);
+ connRef677->setRoutingType((ConnType)2);
+
+ ConnRef *connRef678 = new ConnRef(router, 678);
+ ConnEnd srcPt678(Point(1621.6, 2688.3), 4);
+ connRef678->setSourceEndpoint(srcPt678);
+ ConnEnd dstPt678(Point(1563.6, 2688.3), 8);
+ connRef678->setDestEndpoint(dstPt678);
+ connRef678->setRoutingType((ConnType)2);
+
+ ConnRef *connRef679 = new ConnRef(router, 679);
+ ConnEnd srcPt679(Point(1480.46, 2757.3), 8);
+ connRef679->setSourceEndpoint(srcPt679);
+ ConnEnd dstPt679(Point(1538.46, 2757.3), 4);
+ connRef679->setDestEndpoint(dstPt679);
+ connRef679->setRoutingType((ConnType)2);
+
+ ConnRef *connRef680 = new ConnRef(router, 680);
+ ConnEnd srcPt680(Point(1704.79, 3140.3), 4);
+ connRef680->setSourceEndpoint(srcPt680);
+ ConnEnd dstPt680(Point(1646.79, 3140.3), 8);
+ connRef680->setDestEndpoint(dstPt680);
+ connRef680->setRoutingType((ConnType)2);
+
+ ConnRef *connRef681 = new ConnRef(router, 681);
+ ConnEnd srcPt681(Point(1480.46, 3140.3), 8);
+ connRef681->setSourceEndpoint(srcPt681);
+ ConnEnd dstPt681(Point(1538.46, 3140.3), 4);
+ connRef681->setDestEndpoint(dstPt681);
+ connRef681->setRoutingType((ConnType)2);
+
+ ConnRef *connRef682 = new ConnRef(router, 682);
+ ConnEnd srcPt682(Point(1621.6, 3071.3), 4);
+ connRef682->setSourceEndpoint(srcPt682);
+ ConnEnd dstPt682(Point(1563.6, 3071.3), 8);
+ connRef682->setDestEndpoint(dstPt682);
+ connRef682->setRoutingType((ConnType)2);
+
+ ConnRef *connRef683 = new ConnRef(router, 683);
+ ConnEnd srcPt683(Point(2229.79, 2699.3), 2);
+ connRef683->setSourceEndpoint(srcPt683);
+ ConnEnd dstPt683(Point(2229.79, 2749.3), 1);
+ connRef683->setDestEndpoint(dstPt683);
+ connRef683->setRoutingType((ConnType)2);
+
+ ConnRef *connRef684 = new ConnRef(router, 684);
+ ConnEnd srcPt684(Point(2392.71, 2612.3), 4);
+ connRef684->setSourceEndpoint(srcPt684);
+ ConnEnd dstPt684(Point(2334.71, 2612.3), 8);
+ connRef684->setDestEndpoint(dstPt684);
+ connRef684->setRoutingType((ConnType)2);
+
+ ConnRef *connRef685 = new ConnRef(router, 685);
+ ConnEnd srcPt685(Point(2477.71, 3005.3), 1);
+ connRef685->setSourceEndpoint(srcPt685);
+ ConnEnd dstPt685(Point(2477.71, 2955.3), 2);
+ connRef685->setDestEndpoint(dstPt685);
+ connRef685->setRoutingType((ConnType)2);
+
+ ConnRef *connRef686 = new ConnRef(router, 686);
+ ConnEnd srcPt686(Point(792.958, 2477.3), 8);
+ connRef686->setSourceEndpoint(srcPt686);
+ ConnEnd dstPt686(Point(850.958, 2477.3), 4);
+ connRef686->setDestEndpoint(dstPt686);
+ connRef686->setRoutingType((ConnType)2);
+
+ ConnRef *connRef687 = new ConnRef(router, 687);
+ ConnEnd srcPt687(Point(958.958, 2427.3), 2);
+ connRef687->setSourceEndpoint(srcPt687);
+ ConnEnd dstPt687(Point(958.958, 2477.3), 1);
+ connRef687->setDestEndpoint(dstPt687);
+ connRef687->setRoutingType((ConnType)2);
+
+ ConnRef *connRef688 = new ConnRef(router, 688);
+ ConnEnd srcPt688(Point(934.358, 2612.3), 4);
+ connRef688->setSourceEndpoint(srcPt688);
+ ConnEnd dstPt688(Point(876.358, 2612.3), 8);
+ connRef688->setDestEndpoint(dstPt688);
+ connRef688->setRoutingType((ConnType)2);
+
+ ConnRef *connRef689 = new ConnRef(router, 689);
+ ConnEnd srcPt689(Point(934.358, 2757.3), 4);
+ connRef689->setSourceEndpoint(srcPt689);
+ ConnEnd dstPt689(Point(876.358, 2757.3), 8);
+ connRef689->setDestEndpoint(dstPt689);
+ connRef689->setRoutingType((ConnType)2);
+
+ ConnRef *connRef690 = new ConnRef(router, 690);
+ ConnEnd srcPt690(Point(876.358, 3021.3), 2);
+ connRef690->setSourceEndpoint(srcPt690);
+ ConnEnd dstPt690(Point(876.358, 3071.3), 1);
+ connRef690->setDestEndpoint(dstPt690);
+ connRef690->setRoutingType((ConnType)2);
+
+ ConnRef *connRef691 = new ConnRef(router, 691);
+ ConnEnd srcPt691(Point(2171.79, 991.643), 2);
+ connRef691->setSourceEndpoint(srcPt691);
+ ConnEnd dstPt691(Point(2171.79, 1041.64), 1);
+ connRef691->setDestEndpoint(dstPt691);
+ connRef691->setRoutingType((ConnType)2);
+
+ ConnRef *connRef692 = new ConnRef(router, 692);
+ ConnEnd srcPt692(Point(2477.71, 991.643), 2);
+ connRef692->setSourceEndpoint(srcPt692);
+ ConnEnd dstPt692(Point(2477.71, 1041.64), 1);
+ connRef692->setDestEndpoint(dstPt692);
+ connRef692->setRoutingType((ConnType)2);
+
+ ConnRef *connRef693 = new ConnRef(router, 693);
+ ConnEnd srcPt693(Point(2241.79, 1193.64), 1);
+ connRef693->setSourceEndpoint(srcPt693);
+ ConnEnd dstPt693(Point(2241.79, 1143.64), 2);
+ connRef693->setDestEndpoint(dstPt693);
+ connRef693->setRoutingType((ConnType)2);
+
+ ConnRef *connRef694 = new ConnRef(router, 694);
+ ConnEnd srcPt694(Point(1769.79, 456.5), 2);
+ connRef694->setSourceEndpoint(srcPt694);
+ ConnEnd dstPt694(Point(1769.79, 506.5), 1);
+ connRef694->setDestEndpoint(dstPt694);
+ connRef694->setRoutingType((ConnType)2);
+
+ ConnRef *connRef695 = new ConnRef(router, 695);
+ ConnEnd srcPt695(Point(1769.79, 627.5), 1);
+ connRef695->setSourceEndpoint(srcPt695);
+ ConnEnd dstPt695(Point(1769.79, 577.5), 2);
+ connRef695->setDestEndpoint(dstPt695);
+ connRef695->setRoutingType((ConnType)2);
+
+ ConnRef *connRef696 = new ConnRef(router, 696);
+ ConnEnd srcPt696(Point(2099.79, 1276.24), 4);
+ connRef696->setSourceEndpoint(srcPt696);
+ ConnEnd dstPt696(Point(2041.79, 1276.24), 8);
+ connRef696->setDestEndpoint(dstPt696);
+ connRef696->setRoutingType((ConnType)2);
+
+ ConnRef *connRef697 = new ConnRef(router, 697);
+ ConnEnd srcPt697(Point(381, 1125.24), 4);
+ connRef697->setSourceEndpoint(srcPt697);
+ ConnEnd dstPt697(Point(323, 1125.24), 8);
+ connRef697->setDestEndpoint(dstPt697);
+ connRef697->setRoutingType((ConnType)2);
+
+ ConnRef *connRef698 = new ConnRef(router, 698);
+ ConnEnd srcPt698(Point(223, 1143.64), 8);
+ connRef698->setSourceEndpoint(srcPt698);
+ ConnEnd dstPt698(Point(281, 1143.64), 4);
+ connRef698->setDestEndpoint(dstPt698);
+ connRef698->setRoutingType((ConnType)2);
+
+ ConnRef *connRef699 = new ConnRef(router, 699);
+ ConnEnd srcPt699(Point(523.333, 1143.64), 4);
+ connRef699->setSourceEndpoint(srcPt699);
+ ConnEnd dstPt699(Point(465.333, 1143.64), 8);
+ connRef699->setDestEndpoint(dstPt699);
+ connRef699->setRoutingType((ConnType)2);
+
+ ConnRef *connRef700 = new ConnRef(router, 700);
+ ConnEnd srcPt700(Point(1782.79, 3351.3), 2);
+ connRef700->setSourceEndpoint(srcPt700);
+ ConnEnd dstPt700(Point(1782.79, 3401.3), 1);
+ connRef700->setDestEndpoint(dstPt700);
+ connRef700->setRoutingType((ConnType)2);
+
+ ConnRef *connRef701 = new ConnRef(router, 701);
+ ConnEnd srcPt701(Point(1782.79, 3147.3), 2);
+ connRef701->setSourceEndpoint(srcPt701);
+ ConnEnd dstPt701(Point(1782.79, 3197.3), 1);
+ connRef701->setDestEndpoint(dstPt701);
+ connRef701->setRoutingType((ConnType)2);
+
+ ConnRef *connRef702 = new ConnRef(router, 702);
+ ConnEnd srcPt702(Point(2775.54, 73.5), 2);
+ connRef702->setSourceEndpoint(srcPt702);
+ ConnEnd dstPt702(Point(2775.54, 123.5), 1);
+ connRef702->setDestEndpoint(dstPt702);
+ connRef702->setRoutingType((ConnType)2);
+
+ ConnRef *connRef703 = new ConnRef(router, 703);
+ ConnEnd srcPt703(Point(1953.79, 2895.3), 2);
+ connRef703->setSourceEndpoint(srcPt703);
+ ConnEnd dstPt703(Point(1953.79, 2945.3), 1);
+ connRef703->setDestEndpoint(dstPt703);
+ connRef703->setRoutingType((ConnType)2);
+
+ ConnRef *connRef704 = new ConnRef(router, 704);
+ ConnEnd srcPt704(Point(2171.79, 170.875), 2);
+ connRef704->setSourceEndpoint(srcPt704);
+ ConnEnd dstPt704(Point(2171.79, 220.875), 1);
+ connRef704->setDestEndpoint(dstPt704);
+ connRef704->setRoutingType((ConnType)2);
+
+ ConnRef *connRef705 = new ConnRef(router, 705);
+ ConnEnd srcPt705(Point(1926.79, 1822.95), 2);
+ connRef705->setSourceEndpoint(srcPt705);
+ ConnEnd dstPt705(Point(1926.79, 1872.95), 1);
+ connRef705->setDestEndpoint(dstPt705);
+ connRef705->setRoutingType((ConnType)2);
+
+ ConnRef *connRef706 = new ConnRef(router, 706);
+ ConnEnd srcPt706(Point(1464.46, 1822.95), 2);
+ connRef706->setSourceEndpoint(srcPt706);
+ ConnEnd dstPt706(Point(1464.46, 1872.95), 1);
+ connRef706->setDestEndpoint(dstPt706);
+ connRef706->setRoutingType((ConnType)2);
+
+ ConnRef *connRef707 = new ConnRef(router, 707);
+ ConnEnd srcPt707(Point(972.958, 1822.95), 2);
+ connRef707->setSourceEndpoint(srcPt707);
+ ConnEnd dstPt707(Point(972.958, 1872.95), 1);
+ connRef707->setDestEndpoint(dstPt707);
+ connRef707->setRoutingType((ConnType)2);
+
+ ConnRef *connRef708 = new ConnRef(router, 708);
+ ConnEnd srcPt708(Point(3031.24, 301.75), 8);
+ connRef708->setSourceEndpoint(srcPt708);
+ ConnEnd dstPt708(Point(3089.24, 301.75), 4);
+ connRef708->setDestEndpoint(dstPt708);
+ connRef708->setRoutingType((ConnType)2);
+
+ ConnRef *connRef709 = new ConnRef(router, 709);
+ ConnEnd srcPt709(Point(2099.79, 2749.3), 4);
+ connRef709->setSourceEndpoint(srcPt709);
+ ConnEnd dstPt709(Point(2041.79, 2749.3), 8);
+ connRef709->setDestEndpoint(dstPt709);
+ connRef709->setRoutingType((ConnType)2);
+
+ ConnRef *connRef710 = new ConnRef(router, 710);
+ ConnEnd srcPt710(Point(1919.79, 2749.3), 4);
+ connRef710->setSourceEndpoint(srcPt710);
+ ConnEnd dstPt710(Point(1861.79, 2749.3), 8);
+ connRef710->setDestEndpoint(dstPt710);
+ connRef710->setRoutingType((ConnType)2);
+
+ ConnRef *connRef711 = new ConnRef(router, 711);
+ ConnEnd srcPt711(Point(1131.18, 708.5), 4);
+ connRef711->setSourceEndpoint(srcPt711);
+ ConnEnd dstPt711(Point(1073.18, 708.5), 8);
+ connRef711->setDestEndpoint(dstPt711);
+ connRef711->setRoutingType((ConnType)2);
+
+ ConnRef *connRef712 = new ConnRef(router, 712);
+ ConnEnd srcPt712(Point(1229.46, 519.7), 2);
+ connRef712->setSourceEndpoint(srcPt712);
+ ConnEnd dstPt712(Point(1229.46, 569.7), 1);
+ connRef712->setDestEndpoint(dstPt712);
+ connRef712->setRoutingType((ConnType)2);
+
+ ConnRef *connRef713 = new ConnRef(router, 713);
+ ConnEnd srcPt713(Point(934.358, 569.7), 4);
+ connRef713->setSourceEndpoint(srcPt713);
+ ConnEnd dstPt713(Point(876.358, 569.7), 8);
+ connRef713->setDestEndpoint(dstPt713);
+ connRef713->setRoutingType((ConnType)2);
+
+ ConnRef *connRef714 = new ConnRef(router, 714);
+ ConnEnd srcPt714(Point(462.333, 512.5), 4);
+ connRef714->setSourceEndpoint(srcPt714);
+ ConnEnd dstPt714(Point(404.333, 512.5), 8);
+ connRef714->setDestEndpoint(dstPt714);
+ connRef714->setRoutingType((ConnType)2);
+
+ ConnRef *connRef715 = new ConnRef(router, 715);
+ ConnEnd srcPt715(Point(2477.71, 2814.3), 2);
+ connRef715->setSourceEndpoint(srcPt715);
+ ConnEnd dstPt715(Point(2477.71, 2864.3), 1);
+ connRef715->setDestEndpoint(dstPt715);
+ connRef715->setRoutingType((ConnType)2);
+
+ ConnRef *connRef716 = new ConnRef(router, 716);
+ ConnEnd srcPt716(Point(2910.99, 2562.3), 2);
+ connRef716->setSourceEndpoint(srcPt716);
+ ConnEnd dstPt716(Point(2910.99, 2612.3), 1);
+ connRef716->setDestEndpoint(dstPt716);
+ connRef716->setRoutingType((ConnType)2);
+
+ ConnRef *connRef717 = new ConnRef(router, 717);
+ ConnEnd srcPt717(Point(3300.24, 2612.3), 4);
+ connRef717->setSourceEndpoint(srcPt717);
+ ConnEnd dstPt717(Point(3242.24, 2612.3), 8);
+ connRef717->setDestEndpoint(dstPt717);
+ connRef717->setRoutingType((ConnType)2);
+
+ ConnRef *connRef718 = new ConnRef(router, 718);
+ ConnEnd srcPt718(Point(2884.99, 3021.3), 2);
+ connRef718->setSourceEndpoint(srcPt718);
+ ConnEnd dstPt718(Point(2884.99, 3071.3), 1);
+ connRef718->setDestEndpoint(dstPt718);
+ connRef718->setRoutingType((ConnType)2);
+
+ ConnRef *connRef719 = new ConnRef(router, 719);
+ ConnEnd srcPt719(Point(3384.74, 3071.3), 4);
+ connRef719->setSourceEndpoint(srcPt719);
+ ConnEnd dstPt719(Point(3326.74, 3071.3), 8);
+ connRef719->setDestEndpoint(dstPt719);
+ connRef719->setRoutingType((ConnType)2);
+
+ ConnRef *connRef720 = new ConnRef(router, 720);
+ ConnEnd srcPt720(Point(1782.79, 3249.3), 2);
+ connRef720->setSourceEndpoint(srcPt720);
+ ConnEnd dstPt720(Point(1782.79, 3299.3), 1);
+ connRef720->setDestEndpoint(dstPt720);
+ connRef720->setRoutingType((ConnType)2);
+
+ ConnRef *connRef721 = new ConnRef(router, 721);
+ ConnEnd srcPt721(Point(1563.6, 2399.05), 15);
+ connRef721->setSourceEndpoint(srcPt721);
+ ConnEnd dstPt721(Point(1197.96, 2597.3), 1);
+ connRef721->setDestEndpoint(dstPt721);
+ connRef721->setRoutingType((ConnType)2);
+
+ ConnRef *connRef722 = new ConnRef(router, 722);
+ ConnEnd srcPt722(Point(1563.6, 2399.05), 15);
+ connRef722->setSourceEndpoint(srcPt722);
+ ConnEnd dstPt722(Point(1315.96, 2597.3), 1);
+ connRef722->setDestEndpoint(dstPt722);
+ connRef722->setRoutingType((ConnType)2);
+
+ ConnRef *connRef723 = new ConnRef(router, 723);
+ ConnEnd srcPt723(Point(1563.6, 2399.05), 15);
+ connRef723->setSourceEndpoint(srcPt723);
+ ConnEnd dstPt723(Point(1563.6, 2673.3), 1);
+ connRef723->setDestEndpoint(dstPt723);
+ connRef723->setRoutingType((ConnType)2);
+
+ ConnRef *connRef724 = new ConnRef(router, 724);
+ ConnEnd srcPt724(Point(1563.6, 2399.05), 15);
+ connRef724->setSourceEndpoint(srcPt724);
+ ConnEnd dstPt724(Point(1538.46, 2742.3), 1);
+ connRef724->setDestEndpoint(dstPt724);
+ connRef724->setRoutingType((ConnType)2);
+
+ ConnRef *connRef725 = new ConnRef(router, 725);
+ ConnEnd srcPt725(Point(1523.87, 1631.77), 15);
+ connRef725->setSourceEndpoint(srcPt725);
+ ConnEnd dstPt725(Point(1782.79, 1569.64), 15);
+ connRef725->setDestEndpoint(dstPt725);
+ connRef725->setRoutingType((ConnType)2);
+ */
+
+ ConnRef *connRef726 = new ConnRef(router, 726);
+ ConnEnd srcPt726(Point(2111.79, 1884.95), 15);
+ connRef726->setSourceEndpoint(srcPt726);
+ ConnEnd dstPt726(Point(2241.79, 1872.95), 15);
+ connRef726->setDestEndpoint(dstPt726);
+ connRef726->setRoutingType((ConnType)2);
+
+ /*
+ ConnRef *connRef727 = new ConnRef(router, 727);
+ ConnEnd srcPt727(Point(2189.79, 1733.77), 15);
+ connRef727->setSourceEndpoint(srcPt727);
+ ConnEnd dstPt727(Point(2241.79, 1872.95), 15);
+ connRef727->setDestEndpoint(dstPt727);
+ connRef727->setRoutingType((ConnType)2);
+
+ ConnRef *connRef728 = new ConnRef(router, 728);
+ ConnEnd srcPt728(Point(1315.96, 312.5), 15);
+ connRef728->setSourceEndpoint(srcPt728);
+ ConnEnd dstPt728(Point(1426.46, 227), 2);
+ connRef728->setDestEndpoint(dstPt728);
+ connRef728->setRoutingType((ConnType)2);
+
+ ConnRef *connRef729 = new ConnRef(router, 729);
+ ConnEnd srcPt729(Point(2968.99, 1731.64), 15);
+ connRef729->setSourceEndpoint(srcPt729);
+ ConnEnd dstPt729(Point(3081.74, 1597.44), 2);
+ connRef729->setDestEndpoint(dstPt729);
+ connRef729->setRoutingType((ConnType)2);
+
+ ConnRef *connRef730 = new ConnRef(router, 730);
+ ConnEnd srcPt730(Point(3119.9, 1872.95), 15);
+ connRef730->setSourceEndpoint(srcPt730);
+ ConnEnd dstPt730(Point(3121.74, 1597.44), 2);
+ connRef730->setDestEndpoint(dstPt730);
+ connRef730->setRoutingType((ConnType)2);
+
+ ConnRef *connRef731 = new ConnRef(router, 731);
+ ConnEnd srcPt731(Point(2041.79, 312.5), 15);
+ connRef731->setSourceEndpoint(srcPt731);
+ ConnEnd dstPt731(Point(1907.3, 385), 4);
+ connRef731->setDestEndpoint(dstPt731);
+ connRef731->setRoutingType((ConnType)2);
+
+ ConnRef *connRef732 = new ConnRef(router, 732);
+ ConnEnd srcPt732(Point(1563.6, 978.5), 15);
+ connRef732->setSourceEndpoint(srcPt732);
+ ConnEnd dstPt732(Point(1671.79, 1204.74), 4);
+ connRef732->setDestEndpoint(dstPt732);
+ connRef732->setRoutingType((ConnType)2);
+
+ ConnRef *connRef733 = new ConnRef(router, 733);
+ ConnEnd srcPt733(Point(2041.79, 569.7), 15);
+ connRef733->setSourceEndpoint(srcPt733);
+ ConnEnd dstPt733(Point(1918.79, 1204.74), 8);
+ connRef733->setDestEndpoint(dstPt733);
+ connRef733->setRoutingType((ConnType)2);
+
+ ConnRef *connRef734 = new ConnRef(router, 734);
+ ConnEnd srcPt734(Point(1563.6, 3413.3), 15);
+ connRef734->setSourceEndpoint(srcPt734);
+ ConnEnd dstPt734(Point(1517.1, 2886.8), 8);
+ connRef734->setDestEndpoint(dstPt734);
+ connRef734->setRoutingType((ConnType)2);
+
+ ConnRef *connRef735 = new ConnRef(router, 735);
+ ConnEnd srcPt735(Point(390.333, 2399.05), 15);
+ connRef735->setSourceEndpoint(srcPt735);
+ ConnEnd dstPt735(Point(1375.6, 2804.8), 1);
+ connRef735->setDestEndpoint(dstPt735);
+ connRef735->setRoutingType((ConnType)2);
+
+ ConnRef *connRef736 = new ConnRef(router, 736);
+ ConnEnd srcPt736(Point(610.333, 833.833), 15);
+ connRef736->setSourceEndpoint(srcPt736);
+ ConnEnd dstPt736(Point(1233.46, 381), 2);
+ connRef736->setDestEndpoint(dstPt736);
+ connRef736->setRoutingType((ConnType)2);
+
+ ConnRef *connRef737 = new ConnRef(router, 737);
+ ConnEnd srcPt737(Point(610.333, 833.833), 15);
+ connRef737->setSourceEndpoint(srcPt737);
+ ConnEnd dstPt737(Point(1295.36, 908), 1);
+ connRef737->setDestEndpoint(dstPt737);
+ connRef737->setRoutingType((ConnType)2);
+
+ ConnRef *connRef738 = new ConnRef(router, 738);
+ ConnEnd srcPt738(Point(2547.71, 1569.64), 15);
+ connRef738->setSourceEndpoint(srcPt738);
+ ConnEnd dstPt738(Point(2712.49, 1519.94), 4);
+ connRef738->setDestEndpoint(dstPt738);
+ connRef738->setRoutingType((ConnType)2);
+
+ ConnRef *connRef739 = new ConnRef(router, 739);
+ ConnEnd srcPt739(Point(2547.71, 2945.3), 15);
+ connRef739->setSourceEndpoint(srcPt739);
+ ConnEnd dstPt739(Point(2607.04, 3118.8), 1);
+ connRef739->setDestEndpoint(dstPt739);
+ connRef739->setRoutingType((ConnType)2);
+
+ ConnRef *connRef740 = new ConnRef(router, 740);
+ ConnEnd srcPt740(Point(2547.71, 2945.3), 15);
+ connRef740->setSourceEndpoint(srcPt740);
+ ConnEnd dstPt740(Point(2630.04, 2873.8), 4);
+ connRef740->setDestEndpoint(dstPt740);
+ connRef740->setRoutingType((ConnType)2);
+
+ ConnRef *connRef741 = new ConnRef(router, 741);
+ ConnEnd srcPt741(Point(1563.6, 2399.05), 15);
+ connRef741->setSourceEndpoint(srcPt741);
+ ConnEnd dstPt741(Point(1818.33, 2300.88), 8);
+ connRef741->setDestEndpoint(dstPt741);
+ connRef741->setRoutingType((ConnType)2);
+ */
+
+ router->processTransaction();
+ router->outputDiagram("output/finalSegmentNudging1");
+
+ bool optimisedForConnectorType = true;
+ int crossings = router->existsCrossings(optimisedForConnectorType);
+
+ delete router;
+ return (crossings > 0) ? 1 : 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/finalSegmentNudging2.cpp b/src/3rdparty/adaptagrams/libavoid/tests/finalSegmentNudging2.cpp
new file mode 100644
index 0000000..712a0dd
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/finalSegmentNudging2.cpp
@@ -0,0 +1,397 @@
+// KEGG -> SBGN example #072
+//
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 0);
+ router->setRoutingPenalty((PenaltyType)5, 100);
+ router->setRoutingOption((RoutingOption)0, true);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, false);
+
+ /*
+ Polygon poly1(4);
+ poly1.ps[0] = Point(541.101, 45);
+ poly1.ps[1] = Point(541.101, 89);
+ poly1.ps[2] = Point(274.101, 89);
+ poly1.ps[3] = Point(274.101, 45);
+ new ShapeRef(router, poly1, 1);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(445.857, 111);
+ poly2.ps[1] = Point(445.857, 276);
+ poly2.ps[2] = Point(309.857, 276);
+ poly2.ps[3] = Point(309.857, 111);
+ new ShapeRef(router, poly2, 2);
+ */
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(328, 368);
+ poly3.ps[1] = Point(328, 400);
+ poly3.ps[2] = Point(308, 400);
+ poly3.ps[3] = Point(308, 368);
+ new ShapeRef(router, poly3, 3);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(328, 492);
+ poly4.ps[1] = Point(328, 524);
+ poly4.ps[2] = Point(308, 524);
+ poly4.ps[3] = Point(308, 492);
+ new ShapeRef(router, poly4, 4);
+
+ /*
+ Polygon poly5(4);
+ poly5.ps[0] = Point(328, 629);
+ poly5.ps[1] = Point(328, 661);
+ poly5.ps[2] = Point(308, 661);
+ poly5.ps[3] = Point(308, 629);
+ new ShapeRef(router, poly5, 5);
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(511.857, 308);
+ poly6.ps[1] = Point(511.857, 328);
+ poly6.ps[2] = Point(479.857, 328);
+ poly6.ps[3] = Point(479.857, 308);
+ new ShapeRef(router, poly6, 6);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(518.357, 629);
+ poly7.ps[1] = Point(518.357, 661);
+ poly7.ps[2] = Point(498.357, 661);
+ poly7.ps[3] = Point(498.357, 629);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(827.857, 210);
+ poly8.ps[1] = Point(827.857, 270);
+ poly8.ps[2] = Point(545.857, 270);
+ poly8.ps[3] = Point(545.857, 210);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(805.357, 409);
+ poly9.ps[1] = Point(805.357, 469);
+ poly9.ps[2] = Point(572.357, 469);
+ poly9.ps[3] = Point(572.357, 409);
+ new ShapeRef(router, poly9, 9);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(157.5, 426);
+ poly10.ps[1] = Point(157.5, 458);
+ poly10.ps[2] = Point(137.5, 458);
+ poly10.ps[3] = Point(137.5, 426);
+ new ShapeRef(router, poly10, 10);
+
+ Polygon poly11(4);
+ poly11.ps[0] = Point(276, 597.655);
+ poly11.ps[1] = Point(276, 657.655);
+ poly11.ps[2] = Point(45, 657.655);
+ poly11.ps[3] = Point(45, 597.655);
+ new ShapeRef(router, poly11, 11);
+
+ Polygon poly12(4);
+ poly12.ps[0] = Point(349, 287);
+ poly12.ps[1] = Point(349, 349);
+ poly12.ps[2] = Point(287, 349);
+ poly12.ps[3] = Point(287, 287);
+ new ShapeRef(router, poly12, 12);
+ */
+
+ Polygon poly13(4);
+ poly13.ps[0] = Point(349, 415);
+ poly13.ps[1] = Point(349, 477);
+ poly13.ps[2] = Point(287, 477);
+ poly13.ps[3] = Point(287, 415);
+ new ShapeRef(router, poly13, 13);
+
+ /*
+ Polygon poly14(4);
+ poly14.ps[0] = Point(349, 676);
+ poly14.ps[1] = Point(349, 738);
+ poly14.ps[2] = Point(287, 738);
+ poly14.ps[3] = Point(287, 676);
+ new ShapeRef(router, poly14, 14);
+
+ Polygon poly15(4);
+ poly15.ps[0] = Point(349, 552);
+ poly15.ps[1] = Point(349, 614);
+ poly15.ps[2] = Point(287, 614);
+ poly15.ps[3] = Point(287, 552);
+ new ShapeRef(router, poly15, 15);
+
+ Polygon poly16(4);
+ poly16.ps[0] = Point(539.357, 676);
+ poly16.ps[1] = Point(539.357, 738);
+ poly16.ps[2] = Point(477.357, 738);
+ poly16.ps[3] = Point(477.357, 676);
+ new ShapeRef(router, poly16, 16);
+ */
+
+ Polygon poly17(4);
+ poly17.ps[0] = Point(640.857, 336);
+ poly17.ps[1] = Point(640.857, 398);
+ poly17.ps[2] = Point(578.857, 398);
+ poly17.ps[3] = Point(578.857, 336);
+ new ShapeRef(router, poly17, 17);
+
+ Polygon poly18(4);
+ poly18.ps[0] = Point(404, 364);
+ poly18.ps[1] = Point(404, 404);
+ poly18.ps[2] = Point(328, 404);
+ poly18.ps[3] = Point(328, 364);
+ new ShapeRef(router, poly18, 18);
+
+ Polygon poly19(4);
+ poly19.ps[0] = Point(404, 488);
+ poly19.ps[1] = Point(404, 528);
+ poly19.ps[2] = Point(328, 528);
+ poly19.ps[3] = Point(328, 488);
+ new ShapeRef(router, poly19, 19);
+
+ /*
+ Polygon poly20(4);
+ poly20.ps[0] = Point(404, 625);
+ poly20.ps[1] = Point(404, 665);
+ poly20.ps[2] = Point(328, 665);
+ poly20.ps[3] = Point(328, 625);
+ new ShapeRef(router, poly20, 20);
+
+ Polygon poly21(4);
+ poly21.ps[0] = Point(523.857, 248);
+ poly21.ps[1] = Point(523.857, 308);
+ poly21.ps[2] = Point(467.857, 308);
+ poly21.ps[3] = Point(467.857, 248);
+ new ShapeRef(router, poly21, 21);
+
+ Polygon poly22(4);
+ poly22.ps[0] = Point(594.357, 625);
+ poly22.ps[1] = Point(594.357, 665);
+ poly22.ps[2] = Point(518.357, 665);
+ poly22.ps[3] = Point(518.357, 625);
+ new ShapeRef(router, poly22, 22);
+
+ Polygon poly23(4);
+ poly23.ps[0] = Point(137.5, 422);
+ poly23.ps[1] = Point(137.5, 462);
+ poly23.ps[2] = Point(61.5, 462);
+ poly23.ps[3] = Point(61.5, 422);
+ new ShapeRef(router, poly23, 23);
+
+ Polygon poly24(4);
+ poly24.ps[0] = Point(398.357, 216.5);
+ poly24.ps[1] = Point(398.357, 276.5);
+ poly24.ps[2] = Point(358.357, 276.5);
+ poly24.ps[3] = Point(358.357, 216.5);
+ new ShapeRef(router, poly24, 24);
+
+ Polygon poly25(4);
+ poly25.ps[0] = Point(606.357, 220.5);
+ poly25.ps[1] = Point(606.357, 260.5);
+ poly25.ps[2] = Point(546.357, 260.5);
+ poly25.ps[3] = Point(546.357, 220.5);
+ new ShapeRef(router, poly25, 25);
+ */
+
+ Polygon poly26(4);
+ poly26.ps[0] = Point(632.857, 419.5);
+ poly26.ps[1] = Point(632.857, 459.5);
+ poly26.ps[2] = Point(572.857, 459.5);
+ poly26.ps[3] = Point(572.857, 419.5);
+ new ShapeRef(router, poly26, 26);
+
+ /*
+ Polygon poly27(4);
+ poly27.ps[0] = Point(276.5, 608.155);
+ poly27.ps[1] = Point(276.5, 648.155);
+ poly27.ps[2] = Point(216.5, 648.155);
+ poly27.ps[3] = Point(216.5, 608.155);
+ new ShapeRef(router, poly27, 27);
+
+ ConnRef *connRef28 = new ConnRef(router, 28);
+ ConnEnd srcPt28(Point(318, 399), 2);
+ connRef28->setSourceEndpoint(srcPt28);
+ ConnEnd dstPt28(Point(318, 446), 15);
+ connRef28->setDestEndpoint(dstPt28);
+ connRef28->setRoutingType((ConnType)2);
+
+ ConnRef *connRef29 = new ConnRef(router, 29);
+ ConnEnd srcPt29(Point(318, 523), 2);
+ connRef29->setSourceEndpoint(srcPt29);
+ ConnEnd dstPt29(Point(318, 583), 15);
+ connRef29->setDestEndpoint(dstPt29);
+ connRef29->setRoutingType((ConnType)2);
+ */
+
+ ConnRef *connRef30 = new ConnRef(router, 30);
+ ConnEnd srcPt30(Point(318, 523), 2);
+ connRef30->setSourceEndpoint(srcPt30);
+ ConnEnd dstPt30(Point(609.857, 367), 15);
+ connRef30->setDestEndpoint(dstPt30);
+ connRef30->setRoutingType((ConnType)2);
+
+ /*
+ ConnRef *connRef31 = new ConnRef(router, 31);
+ ConnEnd srcPt31(Point(318, 660), 2);
+ connRef31->setSourceEndpoint(srcPt31);
+ ConnEnd dstPt31(Point(318, 707), 15);
+ connRef31->setDestEndpoint(dstPt31);
+ connRef31->setRoutingType((ConnType)2);
+
+ ConnRef *connRef32 = new ConnRef(router, 32);
+ ConnEnd srcPt32(Point(480.857, 318), 4);
+ connRef32->setSourceEndpoint(srcPt32);
+ ConnEnd dstPt32(Point(318, 318), 15);
+ connRef32->setDestEndpoint(dstPt32);
+ connRef32->setRoutingType((ConnType)2);
+
+ ConnRef *connRef33 = new ConnRef(router, 33);
+ ConnEnd srcPt33(Point(510.857, 318), 8);
+ connRef33->setSourceEndpoint(srcPt33);
+ ConnEnd dstPt33(Point(609.857, 367), 15);
+ connRef33->setDestEndpoint(dstPt33);
+ connRef33->setRoutingType((ConnType)2);
+
+ ConnRef *connRef34 = new ConnRef(router, 34);
+ ConnEnd srcPt34(Point(508.357, 630), 1);
+ connRef34->setSourceEndpoint(srcPt34);
+ ConnEnd dstPt34(Point(318, 583), 15);
+ connRef34->setDestEndpoint(dstPt34);
+ connRef34->setRoutingType((ConnType)2);
+
+ ConnRef *connRef35 = new ConnRef(router, 35);
+ ConnEnd srcPt35(Point(147.5, 427), 1);
+ connRef35->setSourceEndpoint(srcPt35);
+ ConnEnd dstPt35(Point(318, 318), 15);
+ connRef35->setDestEndpoint(dstPt35);
+ connRef35->setRoutingType((ConnType)2);
+
+ ConnRef *connRef36 = new ConnRef(router, 36);
+ ConnEnd srcPt36(Point(147.5, 457), 2);
+ connRef36->setSourceEndpoint(srcPt36);
+ ConnEnd dstPt36(Point(318, 583), 15);
+ connRef36->setDestEndpoint(dstPt36);
+ connRef36->setRoutingType((ConnType)2);
+
+ ConnRef *connRef37 = new ConnRef(router, 37);
+ ConnEnd srcPt37(Point(318, 446), 15);
+ connRef37->setSourceEndpoint(srcPt37);
+ ConnEnd dstPt37(Point(318, 493), 1);
+ connRef37->setDestEndpoint(dstPt37);
+ connRef37->setRoutingType((ConnType)2);
+
+ ConnRef *connRef38 = new ConnRef(router, 38);
+ ConnEnd srcPt38(Point(508.357, 660), 2);
+ connRef38->setSourceEndpoint(srcPt38);
+ ConnEnd dstPt38(Point(508.357, 707), 15);
+ connRef38->setDestEndpoint(dstPt38);
+ connRef38->setRoutingType((ConnType)2);
+
+ ConnRef *connRef39 = new ConnRef(router, 39);
+ ConnEnd srcPt39(Point(376, 384), 4);
+ connRef39->setSourceEndpoint(srcPt39);
+ ConnEnd dstPt39(Point(318, 384), 8);
+ connRef39->setDestEndpoint(dstPt39);
+ connRef39->setRoutingType((ConnType)2);
+
+ ConnRef *connRef40 = new ConnRef(router, 40);
+ ConnEnd srcPt40(Point(376, 508), 4);
+ connRef40->setSourceEndpoint(srcPt40);
+ ConnEnd dstPt40(Point(318, 508), 8);
+ connRef40->setDestEndpoint(dstPt40);
+ connRef40->setRoutingType((ConnType)2);
+
+ ConnRef *connRef41 = new ConnRef(router, 41);
+ ConnEnd srcPt41(Point(376, 645), 4);
+ connRef41->setSourceEndpoint(srcPt41);
+ ConnEnd dstPt41(Point(318, 645), 8);
+ connRef41->setDestEndpoint(dstPt41);
+ connRef41->setRoutingType((ConnType)2);
+
+ ConnRef *connRef42 = new ConnRef(router, 42);
+ ConnEnd srcPt42(Point(495.857, 268), 2);
+ connRef42->setSourceEndpoint(srcPt42);
+ ConnEnd dstPt42(Point(495.857, 318), 1);
+ connRef42->setDestEndpoint(dstPt42);
+ connRef42->setRoutingType((ConnType)2);
+
+ ConnRef *connRef43 = new ConnRef(router, 43);
+ ConnEnd srcPt43(Point(566.357, 645), 4);
+ connRef43->setSourceEndpoint(srcPt43);
+ ConnEnd dstPt43(Point(508.357, 645), 8);
+ connRef43->setDestEndpoint(dstPt43);
+ connRef43->setRoutingType((ConnType)2);
+
+ ConnRef *connRef44 = new ConnRef(router, 44);
+ ConnEnd srcPt44(Point(89.5, 442), 8);
+ connRef44->setSourceEndpoint(srcPt44);
+ ConnEnd dstPt44(Point(147.5, 442), 4);
+ connRef44->setDestEndpoint(dstPt44);
+ connRef44->setRoutingType((ConnType)2);
+
+ ConnRef *connRef45 = new ConnRef(router, 45);
+ ConnEnd srcPt45(Point(318, 318), 15);
+ connRef45->setSourceEndpoint(srcPt45);
+ ConnEnd dstPt45(Point(318, 369), 1);
+ connRef45->setDestEndpoint(dstPt45);
+ connRef45->setRoutingType((ConnType)2);
+ */
+
+ ConnRef *connRef46 = new ConnRef(router, 46);
+ ConnEnd srcPt46(Point(609.857, 367), 15);
+ connRef46->setSourceEndpoint(srcPt46);
+ ConnEnd dstPt46(Point(318, 369), 1);
+ connRef46->setDestEndpoint(dstPt46);
+ connRef46->setRoutingType((ConnType)2);
+
+ /*
+ ConnRef *connRef47 = new ConnRef(router, 47);
+ ConnEnd srcPt47(Point(318, 583), 15);
+ connRef47->setSourceEndpoint(srcPt47);
+ ConnEnd dstPt47(Point(318, 630), 1);
+ connRef47->setDestEndpoint(dstPt47);
+ connRef47->setRoutingType((ConnType)2);
+
+ ConnRef *connRef48 = new ConnRef(router, 48);
+ ConnEnd srcPt48(Point(318, 318), 15);
+ connRef48->setSourceEndpoint(srcPt48);
+ ConnEnd dstPt48(Point(378.357, 271.5), 2);
+ connRef48->setDestEndpoint(dstPt48);
+ connRef48->setRoutingType((ConnType)2);
+
+ ConnRef *connRef49 = new ConnRef(router, 49);
+ ConnEnd srcPt49(Point(318, 318), 15);
+ connRef49->setSourceEndpoint(srcPt49);
+ ConnEnd dstPt49(Point(551.357, 240.5), 4);
+ connRef49->setDestEndpoint(dstPt49);
+ connRef49->setRoutingType((ConnType)2);
+ */
+
+ ConnRef *connRef50 = new ConnRef(router, 50);
+ ConnEnd srcPt50(Point(609.857, 367), 15);
+ connRef50->setSourceEndpoint(srcPt50);
+ ConnEnd dstPt50(Point(577.857, 439.5), 4);
+ connRef50->setDestEndpoint(dstPt50);
+ connRef50->setRoutingType((ConnType)2);
+
+ /*
+ ConnRef *connRef51 = new ConnRef(router, 51);
+ ConnEnd srcPt51(Point(318, 583), 15);
+ connRef51->setSourceEndpoint(srcPt51);
+ ConnEnd dstPt51(Point(271.5, 628.155), 8);
+ connRef51->setDestEndpoint(dstPt51);
+ connRef51->setRoutingType((ConnType)2);
+ */
+
+ router->processTransaction();
+ router->outputDiagram("output/finalSegmentNudging2");
+ bool atEnds = true;
+ bool overlap = router->existsOrthogonalFixedSegmentOverlap(atEnds);
+ delete router;
+ return (overlap) ? 1 : 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/finalSegmentNudging3.cpp b/src/3rdparty/adaptagrams/libavoid/tests/finalSegmentNudging3.cpp
new file mode 100644
index 0000000..6cb0010
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/finalSegmentNudging3.cpp
@@ -0,0 +1,2658 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingParameter((RoutingParameter)0, 50);
+ router->setRoutingParameter((RoutingParameter)1, 0);
+ router->setRoutingParameter((RoutingParameter)2, 0);
+ router->setRoutingParameter((RoutingParameter)3, 4000);
+ router->setRoutingParameter((RoutingParameter)4, 0);
+ router->setRoutingParameter((RoutingParameter)5, 100);
+ router->setRoutingOption((RoutingOption)0, true);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, false);
+ router->setRoutingOption((RoutingOption)3, false);
+
+#ifdef ALL
+ Polygon poly1(4);
+ poly1.ps[0] = Point(1339.5, 943.25);
+ poly1.ps[1] = Point(1339.5, 975.25);
+ poly1.ps[2] = Point(1319.5, 975.25);
+ poly1.ps[3] = Point(1319.5, 943.25);
+ new ShapeRef(router, poly1, 1);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(661.5, 2238.92);
+ poly2.ps[1] = Point(661.5, 2258.92);
+ poly2.ps[2] = Point(629.5, 2258.92);
+ poly2.ps[3] = Point(629.5, 2238.92);
+ new ShapeRef(router, poly2, 2);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(282.5, 2053.92);
+ poly3.ps[1] = Point(282.5, 2085.92);
+ poly3.ps[2] = Point(262.5, 2085.92);
+ poly3.ps[3] = Point(262.5, 2053.92);
+ new ShapeRef(router, poly3, 3);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(661.5, 2280.92);
+ poly4.ps[1] = Point(661.5, 2300.92);
+ poly4.ps[2] = Point(629.5, 2300.92);
+ poly4.ps[3] = Point(629.5, 2280.92);
+ new ShapeRef(router, poly4, 4);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(282.5, 2238.92);
+ poly5.ps[1] = Point(282.5, 2300.92);
+ poly5.ps[2] = Point(220.5, 2300.92);
+ poly5.ps[3] = Point(220.5, 2238.92);
+ new ShapeRef(router, poly5, 5);
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(1771.5, 551.5);
+ poly6.ps[1] = Point(1771.5, 928.5);
+ poly6.ps[2] = Point(1549.5, 928.5);
+ poly6.ps[3] = Point(1549.5, 551.5);
+ new ShapeRef(router, poly6, 6);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(1449.5, 45);
+ poly7.ps[1] = Point(1449.5, 219);
+ poly7.ps[2] = Point(1329.5, 219);
+ poly7.ps[3] = Point(1329.5, 45);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(977.5, 2191.92);
+ poly8.ps[1] = Point(977.5, 2223.92);
+ poly8.ps[2] = Point(957.5, 2223.92);
+ poly8.ps[3] = Point(957.5, 2191.92);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(1297.5, 2163.92);
+ poly9.ps[1] = Point(1297.5, 2183.92);
+ poly9.ps[2] = Point(1265.5, 2183.92);
+ poly9.ps[3] = Point(1265.5, 2163.92);
+ new ShapeRef(router, poly9, 9);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(1297.5, 2238.92);
+ poly10.ps[1] = Point(1297.5, 2258.92);
+ poly10.ps[2] = Point(1265.5, 2258.92);
+ poly10.ps[3] = Point(1265.5, 2238.92);
+ new ShapeRef(router, poly10, 10);
+
+ Polygon poly11(4);
+ poly11.ps[0] = Point(1173.5, 2031.92);
+ poly11.ps[1] = Point(1173.5, 2051.92);
+ poly11.ps[2] = Point(1141.5, 2051.92);
+ poly11.ps[3] = Point(1141.5, 2031.92);
+ new ShapeRef(router, poly11, 11);
+
+ Polygon poly12(4);
+ poly12.ps[0] = Point(1167.5, 1909.92);
+ poly12.ps[1] = Point(1167.5, 1941.92);
+ poly12.ps[2] = Point(1147.5, 1941.92);
+ poly12.ps[3] = Point(1147.5, 1909.92);
+ new ShapeRef(router, poly12, 12);
+#endif
+
+ Polygon poly13(4);
+ poly13.ps[0] = Point(851.5, 1998.92);
+ poly13.ps[1] = Point(851.5, 2018.92);
+ poly13.ps[2] = Point(819.5, 2018.92);
+ poly13.ps[3] = Point(819.5, 1998.92);
+ new ShapeRef(router, poly13, 13);
+
+#ifdef ALL
+ Polygon poly14(4);
+ poly14.ps[0] = Point(426.5, 1998.92);
+ poly14.ps[1] = Point(426.5, 2018.92);
+ poly14.ps[2] = Point(394.5, 2018.92);
+ poly14.ps[3] = Point(394.5, 1998.92);
+ new ShapeRef(router, poly14, 14);
+
+ Polygon poly15(4);
+ poly15.ps[0] = Point(1514.5, 1998.92);
+ poly15.ps[1] = Point(1514.5, 2018.92);
+ poly15.ps[2] = Point(1482.5, 2018.92);
+ poly15.ps[3] = Point(1482.5, 1998.92);
+ new ShapeRef(router, poly15, 15);
+
+ Polygon poly16(4);
+ poly16.ps[0] = Point(1075.5, 1719.92);
+ poly16.ps[1] = Point(1075.5, 1763.92);
+ poly16.ps[2] = Point(987.5, 1763.92);
+ poly16.ps[3] = Point(987.5, 1719.92);
+ new ShapeRef(router, poly16, 16);
+
+ Polygon poly17(4);
+ poly17.ps[0] = Point(1339.5, 1760.92);
+ poly17.ps[1] = Point(1339.5, 1792.92);
+ poly17.ps[2] = Point(1319.5, 1792.92);
+ poly17.ps[3] = Point(1319.5, 1760.92);
+ new ShapeRef(router, poly17, 17);
+
+ Polygon poly18(4);
+ poly18.ps[0] = Point(252, 1782.92);
+ poly18.ps[1] = Point(252, 1946.92);
+ poly18.ps[2] = Point(45, 1946.92);
+ poly18.ps[3] = Point(45, 1782.92);
+ new ShapeRef(router, poly18, 18);
+
+ Polygon poly19(4);
+ poly19.ps[0] = Point(1339.5, 1636.92);
+ poly19.ps[1] = Point(1339.5, 1668.92);
+ poly19.ps[2] = Point(1319.5, 1668.92);
+ poly19.ps[3] = Point(1319.5, 1636.92);
+ new ShapeRef(router, poly19, 19);
+
+ Polygon poly20(4);
+ poly20.ps[0] = Point(1339.5, 1512.92);
+ poly20.ps[1] = Point(1339.5, 1544.92);
+ poly20.ps[2] = Point(1319.5, 1544.92);
+ poly20.ps[3] = Point(1319.5, 1512.92);
+ new ShapeRef(router, poly20, 20);
+
+ Polygon poly21(4);
+ poly21.ps[0] = Point(1318.5, 1098.92);
+ poly21.ps[1] = Point(1318.5, 1130.92);
+ poly21.ps[2] = Point(1298.5, 1130.92);
+ poly21.ps[3] = Point(1298.5, 1098.92);
+ new ShapeRef(router, poly21, 21);
+
+ Polygon poly22(4);
+ poly22.ps[0] = Point(867, 1443.92);
+ poly22.ps[1] = Point(867, 1503.92);
+ poly22.ps[2] = Point(554, 1503.92);
+ poly22.ps[3] = Point(554, 1443.92);
+ new ShapeRef(router, poly22, 22);
+
+ Polygon poly23(4);
+ poly23.ps[0] = Point(1140.5, 1043.92);
+ poly23.ps[1] = Point(1140.5, 1063.92);
+ poly23.ps[2] = Point(1108.5, 1063.92);
+ poly23.ps[3] = Point(1108.5, 1043.92);
+ new ShapeRef(router, poly23, 23);
+
+ Polygon poly24(4);
+ poly24.ps[0] = Point(1318.5, 761.25);
+ poly24.ps[1] = Point(1318.5, 793.25);
+ poly24.ps[2] = Point(1298.5, 793.25);
+ poly24.ps[3] = Point(1298.5, 761.25);
+ new ShapeRef(router, poly24, 24);
+
+ Polygon poly25(4);
+ poly25.ps[0] = Point(1451.5, 761.25);
+ poly25.ps[1] = Point(1451.5, 793.25);
+ poly25.ps[2] = Point(1431.5, 793.25);
+ poly25.ps[3] = Point(1431.5, 761.25);
+ new ShapeRef(router, poly25, 25);
+
+ Polygon poly26(4);
+ poly26.ps[0] = Point(1481.5, 461);
+ poly26.ps[1] = Point(1481.5, 481);
+ poly26.ps[2] = Point(1449.5, 481);
+ poly26.ps[3] = Point(1449.5, 461);
+ new ShapeRef(router, poly26, 26);
+
+ Polygon poly27(4);
+ poly27.ps[0] = Point(1339.5, 573.75);
+ poly27.ps[1] = Point(1339.5, 605.75);
+ poly27.ps[2] = Point(1319.5, 605.75);
+ poly27.ps[3] = Point(1319.5, 573.75);
+ new ShapeRef(router, poly27, 27);
+
+ Polygon poly28(4);
+ poly28.ps[0] = Point(1339.5, 372);
+ poly28.ps[1] = Point(1339.5, 404);
+ poly28.ps[2] = Point(1319.5, 404);
+ poly28.ps[3] = Point(1319.5, 372);
+ new ShapeRef(router, poly28, 28);
+
+ Polygon poly29(4);
+ poly29.ps[0] = Point(1074.5, 667.25);
+ poly29.ps[1] = Point(1074.5, 687.25);
+ poly29.ps[2] = Point(1042.5, 687.25);
+ poly29.ps[3] = Point(1042.5, 667.25);
+ new ShapeRef(router, poly29, 29);
+
+ Polygon poly30(4);
+ poly30.ps[0] = Point(529.5, 571.25);
+ poly30.ps[1] = Point(529.5, 591.25);
+ poly30.ps[2] = Point(497.5, 591.25);
+ poly30.ps[3] = Point(497.5, 571.25);
+ new ShapeRef(router, poly30, 30);
+
+ Polygon poly31(4);
+ poly31.ps[0] = Point(529.5, 646.25);
+ poly31.ps[1] = Point(529.5, 666.25);
+ poly31.ps[2] = Point(497.5, 666.25);
+ poly31.ps[3] = Point(497.5, 646.25);
+ new ShapeRef(router, poly31, 31);
+
+ Polygon poly32(4);
+ poly32.ps[0] = Point(950.5, 579.75);
+ poly32.ps[1] = Point(950.5, 599.75);
+ poly32.ps[2] = Point(918.5, 599.75);
+ poly32.ps[3] = Point(918.5, 579.75);
+ new ShapeRef(router, poly32, 32);
+
+ Polygon poly33(4);
+ poly33.ps[0] = Point(779.5, 573.75);
+ poly33.ps[1] = Point(779.5, 605.75);
+ poly33.ps[2] = Point(759.5, 605.75);
+ poly33.ps[3] = Point(759.5, 573.75);
+ new ShapeRef(router, poly33, 33);
+
+ Polygon poly34(4);
+ poly34.ps[0] = Point(296.5, 573.75);
+ poly34.ps[1] = Point(296.5, 605.75);
+ poly34.ps[2] = Point(276.5, 605.75);
+ poly34.ps[3] = Point(276.5, 573.75);
+ new ShapeRef(router, poly34, 34);
+
+ Polygon poly35(4);
+ poly35.ps[0] = Point(628.5, 323.5);
+ poly35.ps[1] = Point(628.5, 343.5);
+ poly35.ps[2] = Point(596.5, 343.5);
+ poly35.ps[3] = Point(596.5, 323.5);
+ new ShapeRef(router, poly35, 35);
+
+ Polygon poly36(4);
+ poly36.ps[0] = Point(628.5, 398.5);
+ poly36.ps[1] = Point(628.5, 418.5);
+ poly36.ps[2] = Point(596.5, 418.5);
+ poly36.ps[3] = Point(596.5, 398.5);
+ new ShapeRef(router, poly36, 36);
+
+ Polygon poly37(4);
+ poly37.ps[0] = Point(628.5, 590.5);
+ poly37.ps[1] = Point(628.5, 610.5);
+ poly37.ps[2] = Point(596.5, 610.5);
+ poly37.ps[3] = Point(596.5, 590.5);
+ new ShapeRef(router, poly37, 37);
+
+ Polygon poly38(4);
+ poly38.ps[0] = Point(917.5, 345);
+ poly38.ps[1] = Point(917.5, 365);
+ poly38.ps[2] = Point(885.5, 365);
+ poly38.ps[3] = Point(885.5, 345);
+ new ShapeRef(router, poly38, 38);
+
+ Polygon poly39(4);
+ poly39.ps[0] = Point(917.5, 229);
+ poly39.ps[1] = Point(917.5, 249);
+ poly39.ps[2] = Point(885.5, 249);
+ poly39.ps[3] = Point(885.5, 229);
+ new ShapeRef(router, poly39, 39);
+
+ Polygon poly40(4);
+ poly40.ps[0] = Point(402, 96.5);
+ poly40.ps[1] = Point(402, 131.5);
+ poly40.ps[2] = Point(141, 131.5);
+ poly40.ps[3] = Point(141, 96.5);
+ new ShapeRef(router, poly40, 40);
+
+ Polygon poly41(4);
+ poly41.ps[0] = Point(562.5, 2164.92);
+ poly41.ps[1] = Point(562.5, 2184.92);
+ poly41.ps[2] = Point(530.5, 2184.92);
+ poly41.ps[3] = Point(530.5, 2164.92);
+ new ShapeRef(router, poly41, 41);
+
+ Polygon poly42(4);
+ poly42.ps[0] = Point(1339.5, 1334.92);
+ poly42.ps[1] = Point(1339.5, 1366.92);
+ poly42.ps[2] = Point(1319.5, 1366.92);
+ poly42.ps[3] = Point(1319.5, 1334.92);
+ new ShapeRef(router, poly42, 42);
+
+ Polygon poly43(4);
+ poly43.ps[0] = Point(628.5, 473.5);
+ poly43.ps[1] = Point(628.5, 493.5);
+ poly43.ps[2] = Point(596.5, 493.5);
+ poly43.ps[3] = Point(596.5, 473.5);
+ new ShapeRef(router, poly43, 43);
+
+ Polygon poly44(4);
+ poly44.ps[0] = Point(529.5, 688.25);
+ poly44.ps[1] = Point(529.5, 708.25);
+ poly44.ps[2] = Point(497.5, 708.25);
+ poly44.ps[3] = Point(497.5, 688.25);
+ new ShapeRef(router, poly44, 44);
+
+ Polygon poly45(4);
+ poly45.ps[0] = Point(302.5, 800.25);
+ poly45.ps[1] = Point(302.5, 820.25);
+ poly45.ps[2] = Point(270.5, 820.25);
+ poly45.ps[3] = Point(270.5, 800.25);
+ new ShapeRef(router, poly45, 45);
+
+ Polygon poly46(4);
+ poly46.ps[0] = Point(302.5, 916.25);
+ poly46.ps[1] = Point(302.5, 936.25);
+ poly46.ps[2] = Point(270.5, 936.25);
+ poly46.ps[3] = Point(270.5, 916.25);
+ new ShapeRef(router, poly46, 46);
+
+ Polygon poly47(4);
+ poly47.ps[0] = Point(694.5, 800.25);
+ poly47.ps[1] = Point(694.5, 820.25);
+ poly47.ps[2] = Point(662.5, 820.25);
+ poly47.ps[3] = Point(662.5, 800.25);
+ new ShapeRef(router, poly47, 47);
+
+ Polygon poly48(4);
+ poly48.ps[0] = Point(694.5, 916.25);
+ poly48.ps[1] = Point(694.5, 936.25);
+ poly48.ps[2] = Point(662.5, 936.25);
+ poly48.ps[3] = Point(662.5, 916.25);
+ new ShapeRef(router, poly48, 48);
+
+ Polygon poly49(4);
+ poly49.ps[0] = Point(1572.5, 440);
+ poly49.ps[1] = Point(1572.5, 502);
+ poly49.ps[2] = Point(1510.5, 502);
+ poly49.ps[3] = Point(1510.5, 440);
+ new ShapeRef(router, poly49, 49);
+
+ Polygon poly50(4);
+ poly50.ps[0] = Point(1360.5, 241);
+ poly50.ps[1] = Point(1360.5, 303);
+ poly50.ps[2] = Point(1298.5, 303);
+ poly50.ps[3] = Point(1298.5, 241);
+ new ShapeRef(router, poly50, 50);
+
+ Polygon poly51(4);
+ poly51.ps[0] = Point(1360.5, 1559.92);
+ poly51.ps[1] = Point(1360.5, 1621.92);
+ poly51.ps[2] = Point(1298.5, 1621.92);
+ poly51.ps[3] = Point(1298.5, 1559.92);
+ new ShapeRef(router, poly51, 51);
+
+ Polygon poly52(4);
+ poly52.ps[0] = Point(317.5, 473.5);
+ poly52.ps[1] = Point(317.5, 535.5);
+ poly52.ps[2] = Point(255.5, 535.5);
+ poly52.ps[3] = Point(255.5, 473.5);
+ new ShapeRef(router, poly52, 52);
+
+ Polygon poly53(4);
+ poly53.ps[0] = Point(317.5, 646.25);
+ poly53.ps[1] = Point(317.5, 708.25);
+ poly53.ps[2] = Point(255.5, 708.25);
+ poly53.ps[3] = Point(255.5, 646.25);
+ new ShapeRef(router, poly53, 53);
+
+ Polygon poly54(4);
+ poly54.ps[0] = Point(899.5, 1022.92);
+ poly54.ps[1] = Point(899.5, 1084.92);
+ poly54.ps[2] = Point(837.5, 1084.92);
+ poly54.ps[3] = Point(837.5, 1022.92);
+ new ShapeRef(router, poly54, 54);
+
+ Polygon poly55(4);
+ poly55.ps[0] = Point(899.5, 646.25);
+ poly55.ps[1] = Point(899.5, 708.25);
+ poly55.ps[2] = Point(837.5, 708.25);
+ poly55.ps[3] = Point(837.5, 646.25);
+ new ShapeRef(router, poly55, 55);
+
+ Polygon poly56(4);
+ poly56.ps[0] = Point(1360.5, 473.5);
+ poly56.ps[1] = Point(1360.5, 535.5);
+ poly56.ps[2] = Point(1298.5, 535.5);
+ poly56.ps[3] = Point(1298.5, 473.5);
+ new ShapeRef(router, poly56, 56);
+
+ Polygon poly57(4);
+ poly57.ps[0] = Point(1360.5, 646.25);
+ poly57.ps[1] = Point(1360.5, 708.25);
+ poly57.ps[2] = Point(1298.5, 708.25);
+ poly57.ps[3] = Point(1298.5, 646.25);
+ new ShapeRef(router, poly57, 57);
+
+ Polygon poly58(4);
+ poly58.ps[0] = Point(1360.5, 1683.92);
+ poly58.ps[1] = Point(1360.5, 1745.92);
+ poly58.ps[2] = Point(1298.5, 1745.92);
+ poly58.ps[3] = Point(1298.5, 1683.92);
+ new ShapeRef(router, poly58, 58);
+
+ Polygon poly59(4);
+ poly59.ps[0] = Point(1360.5, 1435.92);
+ poly59.ps[1] = Point(1360.5, 1497.92);
+ poly59.ps[2] = Point(1298.5, 1497.92);
+ poly59.ps[3] = Point(1298.5, 1435.92);
+ new ShapeRef(router, poly59, 59);
+
+ Polygon poly60(4);
+ poly60.ps[0] = Point(1360.5, 1195.92);
+ poly60.ps[1] = Point(1360.5, 1257.92);
+ poly60.ps[2] = Point(1298.5, 1257.92);
+ poly60.ps[3] = Point(1298.5, 1195.92);
+ new ShapeRef(router, poly60, 60);
+
+ Polygon poly61(4);
+ poly61.ps[0] = Point(1605.5, 1977.92);
+ poly61.ps[1] = Point(1605.5, 2039.92);
+ poly61.ps[2] = Point(1543.5, 2039.92);
+ poly61.ps[3] = Point(1543.5, 1977.92);
+ new ShapeRef(router, poly61, 61);
+
+ Polygon poly62(4);
+ poly62.ps[0] = Point(833.5, 2143.92);
+ poly62.ps[1] = Point(833.5, 2205.92);
+ poly62.ps[2] = Point(771.5, 2205.92);
+ poly62.ps[3] = Point(771.5, 2143.92);
+ new ShapeRef(router, poly62, 62);
+
+ Polygon poly63(4);
+ poly63.ps[0] = Point(1496.5, 2238.92);
+ poly63.ps[1] = Point(1496.5, 2300.92);
+ poly63.ps[2] = Point(1434.5, 2300.92);
+ poly63.ps[3] = Point(1434.5, 2238.92);
+ new ShapeRef(router, poly63, 63);
+
+ Polygon poly64(4);
+ poly64.ps[0] = Point(1360.5, 1977.92);
+ poly64.ps[1] = Point(1360.5, 2039.92);
+ poly64.ps[2] = Point(1298.5, 2039.92);
+ poly64.ps[3] = Point(1298.5, 1977.92);
+ new ShapeRef(router, poly64, 64);
+#endif
+
+ Polygon poly65(4);
+ poly65.ps[0] = Point(998.5, 1977.92);
+ poly65.ps[1] = Point(998.5, 2039.92);
+ poly65.ps[2] = Point(936.5, 2039.92);
+ poly65.ps[3] = Point(936.5, 1977.92);
+ new ShapeRef(router, poly65, 65);
+
+#ifdef ALL
+ Polygon poly66(4);
+ poly66.ps[0] = Point(282.5, 1977.92);
+ poly66.ps[1] = Point(282.5, 2039.92);
+ poly66.ps[2] = Point(220.5, 2039.92);
+ poly66.ps[3] = Point(220.5, 1977.92);
+ new ShapeRef(router, poly66, 66);
+
+ Polygon poly67(4);
+ poly67.ps[0] = Point(998.5, 2238.92);
+ poly67.ps[1] = Point(998.5, 2300.92);
+ poly67.ps[2] = Point(936.5, 2300.92);
+ poly67.ps[3] = Point(936.5, 2238.92);
+ new ShapeRef(router, poly67, 67);
+#endif
+
+ Polygon poly68(4);
+ poly68.ps[0] = Point(610.5, 1977.92);
+ poly68.ps[1] = Point(610.5, 2039.92);
+ poly68.ps[2] = Point(548.5, 2039.92);
+ poly68.ps[3] = Point(548.5, 1977.92);
+ new ShapeRef(router, poly68, 68);
+
+#ifdef ALL
+ Polygon poly69(4);
+ poly69.ps[0] = Point(441.5, 2143.92);
+ poly69.ps[1] = Point(441.5, 2205.92);
+ poly69.ps[2] = Point(379.5, 2205.92);
+ poly69.ps[3] = Point(379.5, 2143.92);
+ new ShapeRef(router, poly69, 69);
+
+ Polygon poly70(4);
+ poly70.ps[0] = Point(1360.5, 812.25);
+ poly70.ps[1] = Point(1360.5, 874.25);
+ poly70.ps[2] = Point(1298.5, 874.25);
+ poly70.ps[3] = Point(1298.5, 812.25);
+ new ShapeRef(router, poly70, 70);
+
+ Polygon poly71(4);
+ poly71.ps[0] = Point(247.5, 779.25);
+ poly71.ps[1] = Point(247.5, 841.25);
+ poly71.ps[2] = Point(185.5, 841.25);
+ poly71.ps[3] = Point(185.5, 779.25);
+ new ShapeRef(router, poly71, 71);
+
+ Polygon poly72(4);
+ poly72.ps[0] = Point(474.5, 779.25);
+ poly72.ps[1] = Point(474.5, 841.25);
+ poly72.ps[2] = Point(412.5, 841.25);
+ poly72.ps[3] = Point(412.5, 779.25);
+ new ShapeRef(router, poly72, 72);
+
+ Polygon poly73(4);
+ poly73.ps[0] = Point(474.5, 895.25);
+ poly73.ps[1] = Point(474.5, 957.25);
+ poly73.ps[2] = Point(412.5, 957.25);
+ poly73.ps[3] = Point(412.5, 895.25);
+ new ShapeRef(router, poly73, 73);
+
+ Polygon poly74(4);
+ poly74.ps[0] = Point(247.5, 895.25);
+ poly74.ps[1] = Point(247.5, 957.25);
+ poly74.ps[2] = Point(185.5, 957.25);
+ poly74.ps[3] = Point(185.5, 895.25);
+ new ShapeRef(router, poly74, 74);
+
+ Polygon poly75(4);
+ poly75.ps[0] = Point(393.5, 1683.92);
+ poly75.ps[1] = Point(393.5, 1703.92);
+ poly75.ps[2] = Point(361.5, 1703.92);
+ poly75.ps[3] = Point(361.5, 1683.92);
+ new ShapeRef(router, poly75, 75);
+
+ Polygon poly76(4);
+ poly76.ps[0] = Point(282.5, 1683.92);
+ poly76.ps[1] = Point(282.5, 1745.92);
+ poly76.ps[2] = Point(220.5, 1745.92);
+ poly76.ps[3] = Point(220.5, 1683.92);
+ new ShapeRef(router, poly76, 76);
+
+ Polygon poly77(4);
+ poly77.ps[0] = Point(1297.5, 2280.92);
+ poly77.ps[1] = Point(1297.5, 2300.92);
+ poly77.ps[2] = Point(1265.5, 2300.92);
+ poly77.ps[3] = Point(1265.5, 2280.92);
+ new ShapeRef(router, poly77, 77);
+
+ Polygon poly78(4);
+ poly78.ps[0] = Point(393.5, 1725.92);
+ poly78.ps[1] = Point(393.5, 1745.92);
+ poly78.ps[2] = Point(361.5, 1745.92);
+ poly78.ps[3] = Point(361.5, 1725.92);
+ new ShapeRef(router, poly78, 78);
+
+ Polygon poly79(4);
+ poly79.ps[0] = Point(1645, 2133.42);
+ poly79.ps[1] = Point(1645, 2298.42);
+ poly79.ps[2] = Point(1508, 2298.42);
+ poly79.ps[3] = Point(1508, 2133.42);
+ new ShapeRef(router, poly79, 79);
+
+ Polygon poly80(4);
+ poly80.ps[0] = Point(1360.5, 1098.92);
+ poly80.ps[1] = Point(1360.5, 1130.92);
+ poly80.ps[2] = Point(1340.5, 1130.92);
+ poly80.ps[3] = Point(1340.5, 1098.92);
+ new ShapeRef(router, poly80, 80);
+
+ Polygon poly81(4);
+ poly81.ps[0] = Point(1446.5, 1272.92);
+ poly81.ps[1] = Point(1446.5, 1304.92);
+ poly81.ps[2] = Point(1426.5, 1304.92);
+ poly81.ps[3] = Point(1426.5, 1272.92);
+ new ShapeRef(router, poly81, 81);
+
+ Polygon poly82(4);
+ poly82.ps[0] = Point(1488.5, 1272.92);
+ poly82.ps[1] = Point(1488.5, 1304.92);
+ poly82.ps[2] = Point(1468.5, 1304.92);
+ poly82.ps[3] = Point(1468.5, 1272.92);
+ new ShapeRef(router, poly82, 82);
+
+ Polygon poly83(4);
+ poly83.ps[0] = Point(694.5, 1849.92);
+ poly83.ps[1] = Point(694.5, 1869.92);
+ poly83.ps[2] = Point(662.5, 1869.92);
+ poly83.ps[3] = Point(662.5, 1849.92);
+ new ShapeRef(router, poly83, 83);
+
+ Polygon poly84(4);
+ poly84.ps[0] = Point(1579.5, 1272.92);
+ poly84.ps[1] = Point(1579.5, 1304.92);
+ poly84.ps[2] = Point(1559.5, 1304.92);
+ poly84.ps[3] = Point(1559.5, 1272.92);
+ new ShapeRef(router, poly84, 84);
+
+ Polygon poly85(4);
+ poly85.ps[0] = Point(1122.5, 1319.92);
+ poly85.ps[1] = Point(1122.5, 1381.92);
+ poly85.ps[2] = Point(1060.5, 1381.92);
+ poly85.ps[3] = Point(1060.5, 1319.92);
+ new ShapeRef(router, poly85, 85);
+
+ Polygon poly86(4);
+ poly86.ps[0] = Point(1264.5, 1423.92);
+ poly86.ps[1] = Point(1264.5, 1443.92);
+ poly86.ps[2] = Point(1232.5, 1443.92);
+ poly86.ps[3] = Point(1232.5, 1423.92);
+ new ShapeRef(router, poly86, 86);
+
+ Polygon poly87(4);
+ poly87.ps[0] = Point(1264.5, 1216.92);
+ poly87.ps[1] = Point(1264.5, 1236.92);
+ poly87.ps[2] = Point(1232.5, 1236.92);
+ poly87.ps[3] = Point(1232.5, 1216.92);
+ new ShapeRef(router, poly87, 87);
+
+ Polygon poly88(4);
+ poly88.ps[0] = Point(1360.5, 1022.92);
+ poly88.ps[1] = Point(1360.5, 1084.92);
+ poly88.ps[2] = Point(1298.5, 1084.92);
+ poly88.ps[3] = Point(1298.5, 1022.92);
+ new ShapeRef(router, poly88, 88);
+
+ Polygon poly89(4);
+ poly89.ps[0] = Point(240.5, 2053.92);
+ poly89.ps[1] = Point(240.5, 2085.92);
+ poly89.ps[2] = Point(220.5, 2085.92);
+ poly89.ps[3] = Point(220.5, 2053.92);
+ new ShapeRef(router, poly89, 89);
+
+ Polygon poly90(4);
+ poly90.ps[0] = Point(1360.5, 761.25);
+ poly90.ps[1] = Point(1360.5, 793.25);
+ poly90.ps[2] = Point(1340.5, 793.25);
+ poly90.ps[3] = Point(1340.5, 761.25);
+ new ShapeRef(router, poly90, 90);
+
+ Polygon poly91(4);
+ poly91.ps[0] = Point(628.5, 515.5);
+ poly91.ps[1] = Point(628.5, 535.5);
+ poly91.ps[2] = Point(596.5, 535.5);
+ poly91.ps[3] = Point(596.5, 515.5);
+ new ShapeRef(router, poly91, 91);
+
+ Polygon poly92(4);
+ poly92.ps[0] = Point(529.5, 763.25);
+ poly92.ps[1] = Point(529.5, 783.25);
+ poly92.ps[2] = Point(497.5, 783.25);
+ poly92.ps[3] = Point(497.5, 763.25);
+ new ShapeRef(router, poly92, 92);
+
+ Polygon poly93(4);
+ poly93.ps[0] = Point(1297.5, 2355.92);
+ poly93.ps[1] = Point(1297.5, 2375.92);
+ poly93.ps[2] = Point(1265.5, 2375.92);
+ poly93.ps[3] = Point(1265.5, 2355.92);
+ new ShapeRef(router, poly93, 93);
+#endif
+
+ Polygon poly94(4);
+ poly94.ps[0] = Point(998.5, 1861.92);
+ poly94.ps[1] = Point(998.5, 1923.92);
+ poly94.ps[2] = Point(936.5, 1923.92);
+ poly94.ps[3] = Point(936.5, 1861.92);
+ new ShapeRef(router, poly94, 94);
+
+#ifdef ALL
+ Polygon poly95(4);
+ poly95.ps[0] = Point(1415.5, 939.25);
+ poly95.ps[1] = Point(1415.5, 979.25);
+ poly95.ps[2] = Point(1339.5, 979.25);
+ poly95.ps[3] = Point(1339.5, 939.25);
+ new ShapeRef(router, poly95, 95);
+
+ Polygon poly96(4);
+ poly96.ps[0] = Point(673.5, 2178.92);
+ poly96.ps[1] = Point(673.5, 2238.92);
+ poly96.ps[2] = Point(617.5, 2238.92);
+ poly96.ps[3] = Point(617.5, 2178.92);
+ new ShapeRef(router, poly96, 96);
+
+ Polygon poly97(4);
+ poly97.ps[0] = Point(358.5, 2049.92);
+ poly97.ps[1] = Point(358.5, 2089.92);
+ poly97.ps[2] = Point(282.5, 2089.92);
+ poly97.ps[3] = Point(282.5, 2049.92);
+ new ShapeRef(router, poly97, 97);
+
+ Polygon poly98(4);
+ poly98.ps[0] = Point(673.5, 2300.92);
+ poly98.ps[1] = Point(673.5, 2360.92);
+ poly98.ps[2] = Point(617.5, 2360.92);
+ poly98.ps[3] = Point(617.5, 2300.92);
+ new ShapeRef(router, poly98, 98);
+
+ Polygon poly99(4);
+ poly99.ps[0] = Point(1053.5, 2187.92);
+ poly99.ps[1] = Point(1053.5, 2227.92);
+ poly99.ps[2] = Point(977.5, 2227.92);
+ poly99.ps[3] = Point(977.5, 2187.92);
+ new ShapeRef(router, poly99, 99);
+
+ Polygon poly100(4);
+ poly100.ps[0] = Point(1309.5, 2103.92);
+ poly100.ps[1] = Point(1309.5, 2163.92);
+ poly100.ps[2] = Point(1253.5, 2163.92);
+ poly100.ps[3] = Point(1253.5, 2103.92);
+ new ShapeRef(router, poly100, 100);
+
+ Polygon poly101(4);
+ poly101.ps[0] = Point(1309.5, 2178.92);
+ poly101.ps[1] = Point(1309.5, 2238.92);
+ poly101.ps[2] = Point(1253.5, 2238.92);
+ poly101.ps[3] = Point(1253.5, 2178.92);
+ new ShapeRef(router, poly101, 101);
+
+ Polygon poly102(4);
+ poly102.ps[0] = Point(1185.5, 2051.92);
+ poly102.ps[1] = Point(1185.5, 2111.92);
+ poly102.ps[2] = Point(1129.5, 2111.92);
+ poly102.ps[3] = Point(1129.5, 2051.92);
+ new ShapeRef(router, poly102, 102);
+
+ Polygon poly103(4);
+ poly103.ps[0] = Point(1243.5, 1905.92);
+ poly103.ps[1] = Point(1243.5, 1945.92);
+ poly103.ps[2] = Point(1167.5, 1945.92);
+ poly103.ps[3] = Point(1167.5, 1905.92);
+ new ShapeRef(router, poly103, 103);
+#endif
+
+ Polygon poly104(4);
+ poly104.ps[0] = Point(863.5, 1938.92);
+ poly104.ps[1] = Point(863.5, 1998.92);
+ poly104.ps[2] = Point(807.5, 1998.92);
+ poly104.ps[3] = Point(807.5, 1938.92);
+ new ShapeRef(router, poly104, 104);
+
+#ifdef ALL
+ Polygon poly105(4);
+ poly105.ps[0] = Point(438.5, 1938.92);
+ poly105.ps[1] = Point(438.5, 1998.92);
+ poly105.ps[2] = Point(382.5, 1998.92);
+ poly105.ps[3] = Point(382.5, 1938.92);
+ new ShapeRef(router, poly105, 105);
+
+ Polygon poly106(4);
+ poly106.ps[0] = Point(1526.5, 1938.92);
+ poly106.ps[1] = Point(1526.5, 1998.92);
+ poly106.ps[2] = Point(1470.5, 1998.92);
+ poly106.ps[3] = Point(1470.5, 1938.92);
+ new ShapeRef(router, poly106, 106);
+
+ Polygon poly107(4);
+ poly107.ps[0] = Point(1415.5, 1756.92);
+ poly107.ps[1] = Point(1415.5, 1796.92);
+ poly107.ps[2] = Point(1339.5, 1796.92);
+ poly107.ps[3] = Point(1339.5, 1756.92);
+ new ShapeRef(router, poly107, 107);
+
+ Polygon poly108(4);
+ poly108.ps[0] = Point(1415.5, 1632.92);
+ poly108.ps[1] = Point(1415.5, 1672.92);
+ poly108.ps[2] = Point(1339.5, 1672.92);
+ poly108.ps[3] = Point(1339.5, 1632.92);
+ new ShapeRef(router, poly108, 108);
+
+ Polygon poly109(4);
+ poly109.ps[0] = Point(1415.5, 1508.92);
+ poly109.ps[1] = Point(1415.5, 1548.92);
+ poly109.ps[2] = Point(1339.5, 1548.92);
+ poly109.ps[3] = Point(1339.5, 1508.92);
+ new ShapeRef(router, poly109, 109);
+
+ Polygon poly110(4);
+ poly110.ps[0] = Point(1298.5, 1094.92);
+ poly110.ps[1] = Point(1298.5, 1134.92);
+ poly110.ps[2] = Point(1222.5, 1134.92);
+ poly110.ps[3] = Point(1222.5, 1094.92);
+ new ShapeRef(router, poly110, 110);
+
+ Polygon poly111(4);
+ poly111.ps[0] = Point(1152.5, 983.917);
+ poly111.ps[1] = Point(1152.5, 1043.92);
+ poly111.ps[2] = Point(1096.5, 1043.92);
+ poly111.ps[3] = Point(1096.5, 983.917);
+ new ShapeRef(router, poly111, 111);
+
+ Polygon poly112(4);
+ poly112.ps[0] = Point(1298.5, 757.25);
+ poly112.ps[1] = Point(1298.5, 797.25);
+ poly112.ps[2] = Point(1222.5, 797.25);
+ poly112.ps[3] = Point(1222.5, 757.25);
+ new ShapeRef(router, poly112, 112);
+
+ Polygon poly113(4);
+ poly113.ps[0] = Point(1527.5, 757.25);
+ poly113.ps[1] = Point(1527.5, 797.25);
+ poly113.ps[2] = Point(1451.5, 797.25);
+ poly113.ps[3] = Point(1451.5, 757.25);
+ new ShapeRef(router, poly113, 113);
+
+ Polygon poly114(4);
+ poly114.ps[0] = Point(1493.5, 401);
+ poly114.ps[1] = Point(1493.5, 461);
+ poly114.ps[2] = Point(1437.5, 461);
+ poly114.ps[3] = Point(1437.5, 401);
+ new ShapeRef(router, poly114, 114);
+
+ Polygon poly115(4);
+ poly115.ps[0] = Point(1415.5, 569.75);
+ poly115.ps[1] = Point(1415.5, 609.75);
+ poly115.ps[2] = Point(1339.5, 609.75);
+ poly115.ps[3] = Point(1339.5, 569.75);
+ new ShapeRef(router, poly115, 115);
+
+ Polygon poly116(4);
+ poly116.ps[0] = Point(1415.5, 368);
+ poly116.ps[1] = Point(1415.5, 408);
+ poly116.ps[2] = Point(1339.5, 408);
+ poly116.ps[3] = Point(1339.5, 368);
+ new ShapeRef(router, poly116, 116);
+
+ Polygon poly117(4);
+ poly117.ps[0] = Point(1086.5, 607.25);
+ poly117.ps[1] = Point(1086.5, 667.25);
+ poly117.ps[2] = Point(1030.5, 667.25);
+ poly117.ps[3] = Point(1030.5, 607.25);
+ new ShapeRef(router, poly117, 117);
+
+ Polygon poly118(4);
+ poly118.ps[0] = Point(541.5, 511.25);
+ poly118.ps[1] = Point(541.5, 571.25);
+ poly118.ps[2] = Point(485.5, 571.25);
+ poly118.ps[3] = Point(485.5, 511.25);
+ new ShapeRef(router, poly118, 118);
+
+ Polygon poly119(4);
+ poly119.ps[0] = Point(541.5, 586.25);
+ poly119.ps[1] = Point(541.5, 646.25);
+ poly119.ps[2] = Point(485.5, 646.25);
+ poly119.ps[3] = Point(485.5, 586.25);
+ new ShapeRef(router, poly119, 119);
+
+ Polygon poly120(4);
+ poly120.ps[0] = Point(962.5, 519.75);
+ poly120.ps[1] = Point(962.5, 579.75);
+ poly120.ps[2] = Point(906.5, 579.75);
+ poly120.ps[3] = Point(906.5, 519.75);
+ new ShapeRef(router, poly120, 120);
+
+ Polygon poly121(4);
+ poly121.ps[0] = Point(759.5, 569.75);
+ poly121.ps[1] = Point(759.5, 609.75);
+ poly121.ps[2] = Point(683.5, 609.75);
+ poly121.ps[3] = Point(683.5, 569.75);
+ new ShapeRef(router, poly121, 121);
+
+ Polygon poly122(4);
+ poly122.ps[0] = Point(372.5, 569.75);
+ poly122.ps[1] = Point(372.5, 609.75);
+ poly122.ps[2] = Point(296.5, 609.75);
+ poly122.ps[3] = Point(296.5, 569.75);
+ new ShapeRef(router, poly122, 122);
+
+ Polygon poly123(4);
+ poly123.ps[0] = Point(640.5, 263.5);
+ poly123.ps[1] = Point(640.5, 323.5);
+ poly123.ps[2] = Point(584.5, 323.5);
+ poly123.ps[3] = Point(584.5, 263.5);
+ new ShapeRef(router, poly123, 123);
+
+ Polygon poly124(4);
+ poly124.ps[0] = Point(640.5, 338.5);
+ poly124.ps[1] = Point(640.5, 398.5);
+ poly124.ps[2] = Point(584.5, 398.5);
+ poly124.ps[3] = Point(584.5, 338.5);
+ new ShapeRef(router, poly124, 124);
+
+ Polygon poly125(4);
+ poly125.ps[0] = Point(640.5, 610.5);
+ poly125.ps[1] = Point(640.5, 670.5);
+ poly125.ps[2] = Point(584.5, 670.5);
+ poly125.ps[3] = Point(584.5, 610.5);
+ new ShapeRef(router, poly125, 125);
+
+ Polygon poly126(4);
+ poly126.ps[0] = Point(929.5, 285);
+ poly126.ps[1] = Point(929.5, 345);
+ poly126.ps[2] = Point(873.5, 345);
+ poly126.ps[3] = Point(873.5, 285);
+ new ShapeRef(router, poly126, 126);
+
+ Polygon poly127(4);
+ poly127.ps[0] = Point(929.5, 169);
+ poly127.ps[1] = Point(929.5, 229);
+ poly127.ps[2] = Point(873.5, 229);
+ poly127.ps[3] = Point(873.5, 169);
+ new ShapeRef(router, poly127, 127);
+
+ Polygon poly128(4);
+ poly128.ps[0] = Point(574.5, 2104.92);
+ poly128.ps[1] = Point(574.5, 2164.92);
+ poly128.ps[2] = Point(518.5, 2164.92);
+ poly128.ps[3] = Point(518.5, 2104.92);
+ new ShapeRef(router, poly128, 128);
+
+ Polygon poly129(4);
+ poly129.ps[0] = Point(1415.5, 1330.92);
+ poly129.ps[1] = Point(1415.5, 1370.92);
+ poly129.ps[2] = Point(1339.5, 1370.92);
+ poly129.ps[3] = Point(1339.5, 1330.92);
+ new ShapeRef(router, poly129, 129);
+
+ Polygon poly130(4);
+ poly130.ps[0] = Point(640.5, 413.5);
+ poly130.ps[1] = Point(640.5, 473.5);
+ poly130.ps[2] = Point(584.5, 473.5);
+ poly130.ps[3] = Point(584.5, 413.5);
+ new ShapeRef(router, poly130, 130);
+
+ Polygon poly131(4);
+ poly131.ps[0] = Point(541.5, 708.25);
+ poly131.ps[1] = Point(541.5, 768.25);
+ poly131.ps[2] = Point(485.5, 768.25);
+ poly131.ps[3] = Point(485.5, 708.25);
+ new ShapeRef(router, poly131, 131);
+
+ Polygon poly132(4);
+ poly132.ps[0] = Point(314.5, 740.25);
+ poly132.ps[1] = Point(314.5, 800.25);
+ poly132.ps[2] = Point(258.5, 800.25);
+ poly132.ps[3] = Point(258.5, 740.25);
+ new ShapeRef(router, poly132, 132);
+
+ Polygon poly133(4);
+ poly133.ps[0] = Point(314.5, 856.25);
+ poly133.ps[1] = Point(314.5, 916.25);
+ poly133.ps[2] = Point(258.5, 916.25);
+ poly133.ps[3] = Point(258.5, 856.25);
+ new ShapeRef(router, poly133, 133);
+
+ Polygon poly134(4);
+ poly134.ps[0] = Point(706.5, 740.25);
+ poly134.ps[1] = Point(706.5, 800.25);
+ poly134.ps[2] = Point(650.5, 800.25);
+ poly134.ps[3] = Point(650.5, 740.25);
+ new ShapeRef(router, poly134, 134);
+
+ Polygon poly135(4);
+ poly135.ps[0] = Point(706.5, 856.25);
+ poly135.ps[1] = Point(706.5, 916.25);
+ poly135.ps[2] = Point(650.5, 916.25);
+ poly135.ps[3] = Point(650.5, 856.25);
+ new ShapeRef(router, poly135, 135);
+
+ Polygon poly136(4);
+ poly136.ps[0] = Point(405.5, 1623.92);
+ poly136.ps[1] = Point(405.5, 1683.92);
+ poly136.ps[2] = Point(349.5, 1683.92);
+ poly136.ps[3] = Point(349.5, 1623.92);
+ new ShapeRef(router, poly136, 136);
+
+ Polygon poly137(4);
+ poly137.ps[0] = Point(1309.5, 2300.92);
+ poly137.ps[1] = Point(1309.5, 2360.92);
+ poly137.ps[2] = Point(1253.5, 2360.92);
+ poly137.ps[3] = Point(1253.5, 2300.92);
+ new ShapeRef(router, poly137, 137);
+
+ Polygon poly138(4);
+ poly138.ps[0] = Point(405.5, 1745.92);
+ poly138.ps[1] = Point(405.5, 1805.92);
+ poly138.ps[2] = Point(349.5, 1805.92);
+ poly138.ps[3] = Point(349.5, 1745.92);
+ new ShapeRef(router, poly138, 138);
+
+ Polygon poly139(4);
+ poly139.ps[0] = Point(1436.5, 1094.92);
+ poly139.ps[1] = Point(1436.5, 1134.92);
+ poly139.ps[2] = Point(1360.5, 1134.92);
+ poly139.ps[3] = Point(1360.5, 1094.92);
+ new ShapeRef(router, poly139, 139);
+
+ Polygon poly140(4);
+ poly140.ps[0] = Point(1426.5, 1268.92);
+ poly140.ps[1] = Point(1426.5, 1308.92);
+ poly140.ps[2] = Point(1350.5, 1308.92);
+ poly140.ps[3] = Point(1350.5, 1268.92);
+ new ShapeRef(router, poly140, 140);
+
+ Polygon poly141(4);
+ poly141.ps[0] = Point(1564.5, 1268.92);
+ poly141.ps[1] = Point(1564.5, 1308.92);
+ poly141.ps[2] = Point(1488.5, 1308.92);
+ poly141.ps[3] = Point(1488.5, 1268.92);
+ new ShapeRef(router, poly141, 141);
+
+ Polygon poly142(4);
+ poly142.ps[0] = Point(706.5, 1789.92);
+ poly142.ps[1] = Point(706.5, 1849.92);
+ poly142.ps[2] = Point(650.5, 1849.92);
+ poly142.ps[3] = Point(650.5, 1789.92);
+ new ShapeRef(router, poly142, 142);
+
+ Polygon poly143(4);
+ poly143.ps[0] = Point(1655.5, 1268.92);
+ poly143.ps[1] = Point(1655.5, 1308.92);
+ poly143.ps[2] = Point(1579.5, 1308.92);
+ poly143.ps[3] = Point(1579.5, 1268.92);
+ new ShapeRef(router, poly143, 143);
+
+ Polygon poly144(4);
+ poly144.ps[0] = Point(1276.5, 1363.92);
+ poly144.ps[1] = Point(1276.5, 1423.92);
+ poly144.ps[2] = Point(1220.5, 1423.92);
+ poly144.ps[3] = Point(1220.5, 1363.92);
+ new ShapeRef(router, poly144, 144);
+
+ Polygon poly145(4);
+ poly145.ps[0] = Point(1276.5, 1156.92);
+ poly145.ps[1] = Point(1276.5, 1216.92);
+ poly145.ps[2] = Point(1220.5, 1216.92);
+ poly145.ps[3] = Point(1220.5, 1156.92);
+ new ShapeRef(router, poly145, 145);
+
+ Polygon poly146(4);
+ poly146.ps[0] = Point(220.5, 2049.92);
+ poly146.ps[1] = Point(220.5, 2089.92);
+ poly146.ps[2] = Point(144.5, 2089.92);
+ poly146.ps[3] = Point(144.5, 2049.92);
+ new ShapeRef(router, poly146, 146);
+
+ Polygon poly147(4);
+ poly147.ps[0] = Point(1436.5, 757.25);
+ poly147.ps[1] = Point(1436.5, 797.25);
+ poly147.ps[2] = Point(1360.5, 797.25);
+ poly147.ps[3] = Point(1360.5, 757.25);
+ new ShapeRef(router, poly147, 147);
+
+ Polygon poly148(4);
+ poly148.ps[0] = Point(640.5, 535.5);
+ poly148.ps[1] = Point(640.5, 595.5);
+ poly148.ps[2] = Point(584.5, 595.5);
+ poly148.ps[3] = Point(584.5, 535.5);
+ new ShapeRef(router, poly148, 148);
+
+ Polygon poly149(4);
+ poly149.ps[0] = Point(541.5, 783.25);
+ poly149.ps[1] = Point(541.5, 843.25);
+ poly149.ps[2] = Point(485.5, 843.25);
+ poly149.ps[3] = Point(485.5, 783.25);
+ new ShapeRef(router, poly149, 149);
+
+ Polygon poly150(4);
+ poly150.ps[0] = Point(1309.5, 2375.92);
+ poly150.ps[1] = Point(1309.5, 2435.92);
+ poly150.ps[2] = Point(1253.5, 2435.92);
+ poly150.ps[3] = Point(1253.5, 2375.92);
+ new ShapeRef(router, poly150, 150);
+
+ Polygon poly151(4);
+ poly151.ps[0] = Point(1610, 700.5);
+ poly151.ps[1] = Point(1610, 740.5);
+ poly151.ps[2] = Point(1550, 740.5);
+ poly151.ps[3] = Point(1550, 700.5);
+ new ShapeRef(router, poly151, 151);
+
+ Polygon poly152(4);
+ poly152.ps[0] = Point(1610, 740.5);
+ poly152.ps[1] = Point(1610, 780.5);
+ poly152.ps[2] = Point(1550, 780.5);
+ poly152.ps[3] = Point(1550, 740.5);
+ new ShapeRef(router, poly152, 152);
+
+ Polygon poly153(4);
+ poly153.ps[0] = Point(1661, 869);
+ poly153.ps[1] = Point(1661, 929);
+ poly153.ps[2] = Point(1621, 929);
+ poly153.ps[3] = Point(1621, 869);
+ new ShapeRef(router, poly153, 153);
+
+ Polygon poly154(4);
+ poly154.ps[0] = Point(1701, 869);
+ poly154.ps[1] = Point(1701, 929);
+ poly154.ps[2] = Point(1661, 929);
+ poly154.ps[3] = Point(1661, 869);
+ new ShapeRef(router, poly154, 154);
+
+ Polygon poly155(4);
+ poly155.ps[0] = Point(1410, 159.5);
+ poly155.ps[1] = Point(1410, 219.5);
+ poly155.ps[2] = Point(1370, 219.5);
+ poly155.ps[3] = Point(1370, 159.5);
+ new ShapeRef(router, poly155, 155);
+
+ Polygon poly156(4);
+ poly156.ps[0] = Point(252.5, 1825.42);
+ poly156.ps[1] = Point(252.5, 1865.42);
+ poly156.ps[2] = Point(192.5, 1865.42);
+ poly156.ps[3] = Point(192.5, 1825.42);
+ new ShapeRef(router, poly156, 156);
+
+ Polygon poly157(4);
+ poly157.ps[0] = Point(252.5, 1865.42);
+ poly157.ps[1] = Point(252.5, 1905.42);
+ poly157.ps[2] = Point(192.5, 1905.42);
+ poly157.ps[3] = Point(192.5, 1865.42);
+ new ShapeRef(router, poly157, 157);
+
+ Polygon poly158(4);
+ poly158.ps[0] = Point(867.5, 1454.42);
+ poly158.ps[1] = Point(867.5, 1494.42);
+ poly158.ps[2] = Point(807.5, 1494.42);
+ poly158.ps[3] = Point(807.5, 1454.42);
+ new ShapeRef(router, poly158, 158);
+
+ Polygon poly159(4);
+ poly159.ps[0] = Point(1597, 2133.92);
+ poly159.ps[1] = Point(1597, 2193.92);
+ poly159.ps[2] = Point(1557, 2193.92);
+ poly159.ps[3] = Point(1557, 2133.92);
+ new ShapeRef(router, poly159, 159);
+
+ Polygon poly160(4);
+ poly160.ps[0] = Point(675.5, 2248.92);
+ poly160.ps[1] = Point(675.5, 2290.92);
+ poly160.ps[2] = Point(607.5, 2290.92);
+ poly160.ps[3] = Point(607.5, 2248.92);
+ new ShapeRef(router, poly160, 160);
+
+ Polygon poly161(4);
+ poly161.ps[0] = Point(272.5, 2039.92);
+ poly161.ps[1] = Point(272.5, 2099.92);
+ poly161.ps[2] = Point(230.5, 2099.92);
+ poly161.ps[3] = Point(230.5, 2039.92);
+ new ShapeRef(router, poly161, 161);
+
+ Polygon poly162(4);
+ poly162.ps[0] = Point(642.5, 333.5);
+ poly162.ps[1] = Point(642.5, 600.5);
+ poly162.ps[2] = Point(574.5, 600.5);
+ poly162.ps[3] = Point(574.5, 333.5);
+ new ShapeRef(router, poly162, 162);
+
+ Polygon poly163(4);
+ poly163.ps[0] = Point(543.5, 581.25);
+ poly163.ps[1] = Point(543.5, 773.25);
+ poly163.ps[2] = Point(475.5, 773.25);
+ poly163.ps[3] = Point(475.5, 581.25);
+ new ShapeRef(router, poly163, 163);
+
+ Polygon poly164(4);
+ poly164.ps[0] = Point(1441.5, 747.25);
+ poly164.ps[1] = Point(1441.5, 807.25);
+ poly164.ps[2] = Point(1308.5, 807.25);
+ poly164.ps[3] = Point(1308.5, 747.25);
+ new ShapeRef(router, poly164, 164);
+
+ Polygon poly165(4);
+ poly165.ps[0] = Point(407.5, 1693.92);
+ poly165.ps[1] = Point(407.5, 1735.92);
+ poly165.ps[2] = Point(339.5, 1735.92);
+ poly165.ps[3] = Point(339.5, 1693.92);
+ new ShapeRef(router, poly165, 165);
+
+ Polygon poly166(4);
+ poly166.ps[0] = Point(1569.5, 1258.92);
+ poly166.ps[1] = Point(1569.5, 1318.92);
+ poly166.ps[2] = Point(1436.5, 1318.92);
+ poly166.ps[3] = Point(1436.5, 1258.92);
+ new ShapeRef(router, poly166, 166);
+
+ Polygon poly167(4);
+ poly167.ps[0] = Point(1350.5, 1084.92);
+ poly167.ps[1] = Point(1350.5, 1144.92);
+ poly167.ps[2] = Point(1308.5, 1144.92);
+ poly167.ps[3] = Point(1308.5, 1084.92);
+ new ShapeRef(router, poly167, 167);
+
+ Polygon poly168(4);
+ poly168.ps[0] = Point(1311.5, 2173.92);
+ poly168.ps[1] = Point(1311.5, 2365.92);
+ poly168.ps[2] = Point(1243.5, 2365.92);
+ poly168.ps[3] = Point(1243.5, 2173.92);
+ new ShapeRef(router, poly168, 168);
+
+ ConnRef *connRef169 = new ConnRef(router, 169);
+ ConnEnd srcPt169(Point(1329.5, 974.25), 2);
+ connRef169->setSourceEndpoint(srcPt169);
+ ConnEnd dstPt169(Point(868.5, 1053.92), 15);
+ connRef169->setDestEndpoint(dstPt169);
+ connRef169->setRoutingType((ConnType)2);
+
+ ConnRef *connRef170 = new ConnRef(router, 170);
+ ConnEnd srcPt170(Point(1329.5, 944.25), 1);
+ connRef170->setSourceEndpoint(srcPt170);
+ ConnEnd dstPt170(Point(1329.5, 843.25), 15);
+ connRef170->setDestEndpoint(dstPt170);
+ connRef170->setRoutingType((ConnType)2);
+
+ ConnRef *connRef171 = new ConnRef(router, 171);
+ ConnEnd srcPt171(Point(1329.5, 974.25), 2);
+ connRef171->setSourceEndpoint(srcPt171);
+ ConnEnd dstPt171(Point(1329.5, 1053.92), 15);
+ connRef171->setDestEndpoint(dstPt171);
+ connRef171->setRoutingType((ConnType)2);
+
+ ConnRef *connRef172 = new ConnRef(router, 172);
+ ConnEnd srcPt172(Point(630.5, 2248.92), 4);
+ connRef172->setSourceEndpoint(srcPt172);
+ ConnEnd dstPt172(Point(251.5, 2269.92), 15);
+ connRef172->setDestEndpoint(dstPt172);
+ connRef172->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints172(1);
+ checkpoints172[0] = Point(607.5, 2269.92);
+ connRef172->setRoutingCheckpoints(checkpoints172);
+
+ ConnRef *connRef173 = new ConnRef(router, 173);
+ ConnEnd srcPt173(Point(660.5, 2248.92), 8);
+ connRef173->setSourceEndpoint(srcPt173);
+ ConnEnd dstPt173(Point(967.5, 2269.92), 15);
+ connRef173->setDestEndpoint(dstPt173);
+ connRef173->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints173(1);
+ checkpoints173[0] = Point(683.5, 2269.92);
+ connRef173->setRoutingCheckpoints(checkpoints173);
+
+ ConnRef *connRef174 = new ConnRef(router, 174);
+ ConnEnd srcPt174(Point(272.5, 2084.92), 2);
+ connRef174->setSourceEndpoint(srcPt174);
+ ConnEnd dstPt174(Point(251.5, 2269.92), 15);
+ connRef174->setDestEndpoint(dstPt174);
+ connRef174->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints174(1);
+ checkpoints174[0] = Point(251.5, 2099.92);
+ connRef174->setRoutingCheckpoints(checkpoints174);
+
+ ConnRef *connRef175 = new ConnRef(router, 175);
+ ConnEnd srcPt175(Point(630.5, 2290.92), 4);
+ connRef175->setSourceEndpoint(srcPt175);
+ ConnEnd dstPt175(Point(251.5, 2269.92), 15);
+ connRef175->setDestEndpoint(dstPt175);
+ connRef175->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints175(1);
+ checkpoints175[0] = Point(607.5, 2269.92);
+ connRef175->setRoutingCheckpoints(checkpoints175);
+
+ ConnRef *connRef176 = new ConnRef(router, 176);
+ ConnEnd srcPt176(Point(660.5, 2290.92), 8);
+ connRef176->setSourceEndpoint(srcPt176);
+ ConnEnd dstPt176(Point(967.5, 2269.92), 15);
+ connRef176->setDestEndpoint(dstPt176);
+ connRef176->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints176(1);
+ checkpoints176[0] = Point(683.5, 2269.92);
+ connRef176->setRoutingCheckpoints(checkpoints176);
+
+ ConnRef *connRef177 = new ConnRef(router, 177);
+ ConnEnd srcPt177(Point(251.5, 2269.92), 15);
+ connRef177->setSourceEndpoint(srcPt177);
+ ConnEnd dstPt177(Point(230.5, 2084.92), 2);
+ connRef177->setDestEndpoint(dstPt177);
+ connRef177->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints177(1);
+ checkpoints177[0] = Point(251.5, 2099.92);
+ connRef177->setRoutingCheckpoints(checkpoints177);
+
+ ConnRef *connRef178 = new ConnRef(router, 178);
+ ConnEnd srcPt178(Point(967.5, 2222.92), 2);
+ connRef178->setSourceEndpoint(srcPt178);
+ ConnEnd dstPt178(Point(967.5, 2269.92), 15);
+ connRef178->setDestEndpoint(dstPt178);
+ connRef178->setRoutingType((ConnType)2);
+
+ ConnRef *connRef179 = new ConnRef(router, 179);
+ ConnEnd srcPt179(Point(1266.5, 2173.92), 4);
+ connRef179->setSourceEndpoint(srcPt179);
+ ConnEnd dstPt179(Point(967.5, 2269.92), 15);
+ connRef179->setDestEndpoint(dstPt179);
+ connRef179->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints179(1);
+ checkpoints179[0] = Point(1243.5, 2269.92);
+ connRef179->setRoutingCheckpoints(checkpoints179);
+
+ ConnRef *connRef180 = new ConnRef(router, 180);
+ ConnEnd srcPt180(Point(1266.5, 2248.92), 4);
+ connRef180->setSourceEndpoint(srcPt180);
+ ConnEnd dstPt180(Point(967.5, 2269.92), 15);
+ connRef180->setDestEndpoint(dstPt180);
+ connRef180->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints180(1);
+ checkpoints180[0] = Point(1243.5, 2269.92);
+ connRef180->setRoutingCheckpoints(checkpoints180);
+
+ ConnRef *connRef181 = new ConnRef(router, 181);
+ ConnEnd srcPt181(Point(1142.5, 2041.92), 4);
+ connRef181->setSourceEndpoint(srcPt181);
+ ConnEnd dstPt181(Point(967.5, 2008.92), 15);
+ connRef181->setDestEndpoint(dstPt181);
+ connRef181->setRoutingType((ConnType)2);
+
+ ConnRef *connRef182 = new ConnRef(router, 182);
+ ConnEnd srcPt182(Point(1157.5, 1940.92), 2);
+ connRef182->setSourceEndpoint(srcPt182);
+ ConnEnd dstPt182(Point(967.5, 2008.92), 15);
+ connRef182->setDestEndpoint(dstPt182);
+ connRef182->setRoutingType((ConnType)2);
+#endif
+
+ ConnRef *connRef183 = new ConnRef(router, 183);
+ ConnEnd srcPt183(Point(820.5, 2008.92), 4);
+ connRef183->setSourceEndpoint(srcPt183);
+ ConnEnd dstPt183(Point(579.5, 2008.92), 15);
+ connRef183->setDestEndpoint(dstPt183);
+ connRef183->setRoutingType((ConnType)2);
+
+ ConnRef *connRef184 = new ConnRef(router, 184);
+ ConnEnd srcPt184(Point(820.5, 2008.92), 4);
+ connRef184->setSourceEndpoint(srcPt184);
+ ConnEnd dstPt184(Point(967.5, 1892.92), 15);
+ connRef184->setDestEndpoint(dstPt184);
+ connRef184->setRoutingType((ConnType)2);
+
+#ifdef ALL
+ ConnRef *connRef185 = new ConnRef(router, 185);
+ ConnEnd srcPt185(Point(395.5, 2008.92), 4);
+ connRef185->setSourceEndpoint(srcPt185);
+ ConnEnd dstPt185(Point(251.5, 2008.92), 15);
+ connRef185->setDestEndpoint(dstPt185);
+ connRef185->setRoutingType((ConnType)2);
+
+ ConnRef *connRef186 = new ConnRef(router, 186);
+ ConnEnd srcPt186(Point(425.5, 2008.92), 8);
+ connRef186->setSourceEndpoint(srcPt186);
+ ConnEnd dstPt186(Point(579.5, 2008.92), 15);
+ connRef186->setDestEndpoint(dstPt186);
+ connRef186->setRoutingType((ConnType)2);
+
+ ConnRef *connRef187 = new ConnRef(router, 187);
+ ConnEnd srcPt187(Point(395.5, 2008.92), 4);
+ connRef187->setSourceEndpoint(srcPt187);
+ ConnEnd dstPt187(Point(410.5, 2174.92), 15);
+ connRef187->setDestEndpoint(dstPt187);
+ connRef187->setRoutingType((ConnType)2);
+
+ ConnRef *connRef188 = new ConnRef(router, 188);
+ ConnEnd srcPt188(Point(1513.5, 2008.92), 8);
+ connRef188->setSourceEndpoint(srcPt188);
+ ConnEnd dstPt188(Point(1574.5, 2008.92), 15);
+ connRef188->setDestEndpoint(dstPt188);
+ connRef188->setRoutingType((ConnType)2);
+
+ ConnRef *connRef189 = new ConnRef(router, 189);
+ ConnEnd srcPt189(Point(1483.5, 2008.92), 4);
+ connRef189->setSourceEndpoint(srcPt189);
+ ConnEnd dstPt189(Point(1329.5, 2008.92), 15);
+ connRef189->setDestEndpoint(dstPt189);
+ connRef189->setRoutingType((ConnType)2);
+
+ ConnRef *connRef190 = new ConnRef(router, 190);
+ ConnEnd srcPt190(Point(1329.5, 1791.92), 2);
+ connRef190->setSourceEndpoint(srcPt190);
+ ConnEnd dstPt190(Point(1329.5, 2008.92), 15);
+ connRef190->setDestEndpoint(dstPt190);
+ connRef190->setRoutingType((ConnType)2);
+
+ ConnRef *connRef191 = new ConnRef(router, 191);
+ ConnEnd srcPt191(Point(1329.5, 1637.92), 1);
+ connRef191->setSourceEndpoint(srcPt191);
+ ConnEnd dstPt191(Point(1329.5, 1590.92), 15);
+ connRef191->setDestEndpoint(dstPt191);
+ connRef191->setRoutingType((ConnType)2);
+
+ ConnRef *connRef192 = new ConnRef(router, 192);
+ ConnEnd srcPt192(Point(1329.5, 1667.92), 2);
+ connRef192->setSourceEndpoint(srcPt192);
+ ConnEnd dstPt192(Point(1329.5, 1714.92), 15);
+ connRef192->setDestEndpoint(dstPt192);
+ connRef192->setRoutingType((ConnType)2);
+
+ ConnRef *connRef193 = new ConnRef(router, 193);
+ ConnEnd srcPt193(Point(1329.5, 1543.92), 2);
+ connRef193->setSourceEndpoint(srcPt193);
+ ConnEnd dstPt193(Point(1329.5, 1590.92), 15);
+ connRef193->setDestEndpoint(dstPt193);
+ connRef193->setRoutingType((ConnType)2);
+
+ ConnRef *connRef194 = new ConnRef(router, 194);
+ ConnEnd srcPt194(Point(1329.5, 1513.92), 1);
+ connRef194->setSourceEndpoint(srcPt194);
+ ConnEnd dstPt194(Point(1329.5, 1466.92), 15);
+ connRef194->setDestEndpoint(dstPt194);
+ connRef194->setRoutingType((ConnType)2);
+
+ ConnRef *connRef195 = new ConnRef(router, 195);
+ ConnEnd srcPt195(Point(1308.5, 1129.92), 2);
+ connRef195->setSourceEndpoint(srcPt195);
+ ConnEnd dstPt195(Point(1329.5, 1226.92), 15);
+ connRef195->setDestEndpoint(dstPt195);
+ connRef195->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints195(1);
+ checkpoints195[0] = Point(1329.5, 1144.92);
+ connRef195->setRoutingCheckpoints(checkpoints195);
+
+ ConnRef *connRef196 = new ConnRef(router, 196);
+ ConnEnd srcPt196(Point(1308.5, 1099.92), 1);
+ connRef196->setSourceEndpoint(srcPt196);
+ ConnEnd dstPt196(Point(1329.5, 1053.92), 15);
+ connRef196->setDestEndpoint(dstPt196);
+ connRef196->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints196(1);
+ checkpoints196[0] = Point(1329.5, 1084.92);
+ connRef196->setRoutingCheckpoints(checkpoints196);
+
+ ConnRef *connRef197 = new ConnRef(router, 197);
+ ConnEnd srcPt197(Point(1109.5, 1053.92), 4);
+ connRef197->setSourceEndpoint(srcPt197);
+ ConnEnd dstPt197(Point(868.5, 1053.92), 15);
+ connRef197->setDestEndpoint(dstPt197);
+ connRef197->setRoutingType((ConnType)2);
+
+ ConnRef *connRef198 = new ConnRef(router, 198);
+ ConnEnd srcPt198(Point(1139.5, 1053.92), 8);
+ connRef198->setSourceEndpoint(srcPt198);
+ ConnEnd dstPt198(Point(1329.5, 1053.92), 15);
+ connRef198->setDestEndpoint(dstPt198);
+ connRef198->setRoutingType((ConnType)2);
+
+ ConnRef *connRef199 = new ConnRef(router, 199);
+ ConnEnd srcPt199(Point(1308.5, 792.25), 2);
+ connRef199->setSourceEndpoint(srcPt199);
+ ConnEnd dstPt199(Point(1329.5, 843.25), 15);
+ connRef199->setDestEndpoint(dstPt199);
+ connRef199->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints199(1);
+ checkpoints199[0] = Point(1329.5, 807.25);
+ connRef199->setRoutingCheckpoints(checkpoints199);
+
+ ConnRef *connRef200 = new ConnRef(router, 200);
+ ConnEnd srcPt200(Point(1441.5, 762.25), 1);
+ connRef200->setSourceEndpoint(srcPt200);
+ ConnEnd dstPt200(Point(1329.5, 677.25), 15);
+ connRef200->setDestEndpoint(dstPt200);
+ connRef200->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints200(1);
+ checkpoints200[0] = Point(1329.5, 747.25);
+ connRef200->setRoutingCheckpoints(checkpoints200);
+
+ ConnRef *connRef201 = new ConnRef(router, 201);
+ ConnEnd srcPt201(Point(1450.5, 471), 4);
+ connRef201->setSourceEndpoint(srcPt201);
+ ConnEnd dstPt201(Point(1329.5, 504.5), 15);
+ connRef201->setDestEndpoint(dstPt201);
+ connRef201->setRoutingType((ConnType)2);
+
+ ConnRef *connRef202 = new ConnRef(router, 202);
+ ConnEnd srcPt202(Point(1329.5, 574.75), 1);
+ connRef202->setSourceEndpoint(srcPt202);
+ ConnEnd dstPt202(Point(1329.5, 504.5), 15);
+ connRef202->setDestEndpoint(dstPt202);
+ connRef202->setRoutingType((ConnType)2);
+
+ ConnRef *connRef203 = new ConnRef(router, 203);
+ ConnEnd srcPt203(Point(1329.5, 604.75), 2);
+ connRef203->setSourceEndpoint(srcPt203);
+ ConnEnd dstPt203(Point(1329.5, 677.25), 15);
+ connRef203->setDestEndpoint(dstPt203);
+ connRef203->setRoutingType((ConnType)2);
+
+ ConnRef *connRef204 = new ConnRef(router, 204);
+ ConnEnd srcPt204(Point(1329.5, 373), 1);
+ connRef204->setSourceEndpoint(srcPt204);
+ ConnEnd dstPt204(Point(1329.5, 272), 15);
+ connRef204->setDestEndpoint(dstPt204);
+ connRef204->setRoutingType((ConnType)2);
+
+ ConnRef *connRef205 = new ConnRef(router, 205);
+ ConnEnd srcPt205(Point(1329.5, 403), 2);
+ connRef205->setSourceEndpoint(srcPt205);
+ ConnEnd dstPt205(Point(1329.5, 504.5), 15);
+ connRef205->setDestEndpoint(dstPt205);
+ connRef205->setRoutingType((ConnType)2);
+
+ ConnRef *connRef206 = new ConnRef(router, 206);
+ ConnEnd srcPt206(Point(1043.5, 677.25), 4);
+ connRef206->setSourceEndpoint(srcPt206);
+ ConnEnd dstPt206(Point(868.5, 677.25), 15);
+ connRef206->setDestEndpoint(dstPt206);
+ connRef206->setRoutingType((ConnType)2);
+
+ ConnRef *connRef207 = new ConnRef(router, 207);
+ ConnEnd srcPt207(Point(1073.5, 677.25), 8);
+ connRef207->setSourceEndpoint(srcPt207);
+ ConnEnd dstPt207(Point(1329.5, 677.25), 15);
+ connRef207->setDestEndpoint(dstPt207);
+ connRef207->setRoutingType((ConnType)2);
+
+ ConnRef *connRef208 = new ConnRef(router, 208);
+ ConnEnd srcPt208(Point(528.5, 581.25), 8);
+ connRef208->setSourceEndpoint(srcPt208);
+ ConnEnd dstPt208(Point(868.5, 677.25), 15);
+ connRef208->setDestEndpoint(dstPt208);
+ connRef208->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints208(1);
+ checkpoints208[0] = Point(551.5, 677.25);
+ connRef208->setRoutingCheckpoints(checkpoints208);
+
+ ConnRef *connRef209 = new ConnRef(router, 209);
+ ConnEnd srcPt209(Point(528.5, 656.25), 8);
+ connRef209->setSourceEndpoint(srcPt209);
+ ConnEnd dstPt209(Point(868.5, 677.25), 15);
+ connRef209->setDestEndpoint(dstPt209);
+ connRef209->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints209(1);
+ checkpoints209[0] = Point(551.5, 677.25);
+ connRef209->setRoutingCheckpoints(checkpoints209);
+
+ ConnRef *connRef210 = new ConnRef(router, 210);
+ ConnEnd srcPt210(Point(919.5, 589.75), 4);
+ connRef210->setSourceEndpoint(srcPt210);
+ ConnEnd dstPt210(Point(868.5, 677.25), 15);
+ connRef210->setDestEndpoint(dstPt210);
+ connRef210->setRoutingType((ConnType)2);
+
+ ConnRef *connRef211 = new ConnRef(router, 211);
+ ConnEnd srcPt211(Point(949.5, 589.75), 8);
+ connRef211->setSourceEndpoint(srcPt211);
+ ConnEnd dstPt211(Point(1329.5, 504.5), 15);
+ connRef211->setDestEndpoint(dstPt211);
+ connRef211->setRoutingType((ConnType)2);
+
+ ConnRef *connRef212 = new ConnRef(router, 212);
+ ConnEnd srcPt212(Point(769.5, 604.75), 2);
+ connRef212->setSourceEndpoint(srcPt212);
+ ConnEnd dstPt212(Point(868.5, 677.25), 15);
+ connRef212->setDestEndpoint(dstPt212);
+ connRef212->setRoutingType((ConnType)2);
+
+ ConnRef *connRef213 = new ConnRef(router, 213);
+ ConnEnd srcPt213(Point(769.5, 574.75), 1);
+ connRef213->setSourceEndpoint(srcPt213);
+ ConnEnd dstPt213(Point(1329.5, 504.5), 15);
+ connRef213->setDestEndpoint(dstPt213);
+ connRef213->setRoutingType((ConnType)2);
+
+ ConnRef *connRef214 = new ConnRef(router, 214);
+ ConnEnd srcPt214(Point(286.5, 574.75), 1);
+ connRef214->setSourceEndpoint(srcPt214);
+ ConnEnd dstPt214(Point(286.5, 504.5), 15);
+ connRef214->setDestEndpoint(dstPt214);
+ connRef214->setRoutingType((ConnType)2);
+
+ ConnRef *connRef215 = new ConnRef(router, 215);
+ ConnEnd srcPt215(Point(286.5, 604.75), 2);
+ connRef215->setSourceEndpoint(srcPt215);
+ ConnEnd dstPt215(Point(286.5, 677.25), 15);
+ connRef215->setDestEndpoint(dstPt215);
+ connRef215->setRoutingType((ConnType)2);
+
+ ConnRef *connRef216 = new ConnRef(router, 216);
+ ConnEnd srcPt216(Point(627.5, 333.5), 8);
+ connRef216->setSourceEndpoint(srcPt216);
+ ConnEnd dstPt216(Point(1329.5, 504.5), 15);
+ connRef216->setDestEndpoint(dstPt216);
+ connRef216->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints216(1);
+ checkpoints216[0] = Point(650.5, 504.5);
+ connRef216->setRoutingCheckpoints(checkpoints216);
+
+ ConnRef *connRef217 = new ConnRef(router, 217);
+ ConnEnd srcPt217(Point(627.5, 408.5), 8);
+ connRef217->setSourceEndpoint(srcPt217);
+ ConnEnd dstPt217(Point(1329.5, 504.5), 15);
+ connRef217->setDestEndpoint(dstPt217);
+ connRef217->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints217(1);
+ checkpoints217[0] = Point(650.5, 504.5);
+ connRef217->setRoutingCheckpoints(checkpoints217);
+
+ ConnRef *connRef218 = new ConnRef(router, 218);
+ ConnEnd srcPt218(Point(597.5, 600.5), 4);
+ connRef218->setSourceEndpoint(srcPt218);
+ ConnEnd dstPt218(Point(286.5, 504.5), 15);
+ connRef218->setDestEndpoint(dstPt218);
+ connRef218->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints218(1);
+ checkpoints218[0] = Point(574.5, 504.5);
+ connRef218->setRoutingCheckpoints(checkpoints218);
+
+ ConnRef *connRef219 = new ConnRef(router, 219);
+ ConnEnd srcPt219(Point(886.5, 355), 4);
+ connRef219->setSourceEndpoint(srcPt219);
+ ConnEnd dstPt219(Point(286.5, 504.5), 15);
+ connRef219->setDestEndpoint(dstPt219);
+ connRef219->setRoutingType((ConnType)2);
+
+ ConnRef *connRef220 = new ConnRef(router, 220);
+ ConnEnd srcPt220(Point(886.5, 239), 4);
+ connRef220->setSourceEndpoint(srcPt220);
+ ConnEnd dstPt220(Point(286.5, 504.5), 15);
+ connRef220->setDestEndpoint(dstPt220);
+ connRef220->setRoutingType((ConnType)2);
+
+ ConnRef *connRef221 = new ConnRef(router, 221);
+ ConnEnd srcPt221(Point(561.5, 2174.92), 8);
+ connRef221->setSourceEndpoint(srcPt221);
+ ConnEnd dstPt221(Point(802.5, 2174.92), 15);
+ connRef221->setDestEndpoint(dstPt221);
+ connRef221->setRoutingType((ConnType)2);
+
+ ConnRef *connRef222 = new ConnRef(router, 222);
+ ConnEnd srcPt222(Point(1329.5, 1365.92), 2);
+ connRef222->setSourceEndpoint(srcPt222);
+ ConnEnd dstPt222(Point(1329.5, 1466.92), 15);
+ connRef222->setDestEndpoint(dstPt222);
+ connRef222->setRoutingType((ConnType)2);
+
+ ConnRef *connRef223 = new ConnRef(router, 223);
+ ConnEnd srcPt223(Point(1329.5, 1335.92), 1);
+ connRef223->setSourceEndpoint(srcPt223);
+ ConnEnd dstPt223(Point(1329.5, 1226.92), 15);
+ connRef223->setDestEndpoint(dstPt223);
+ connRef223->setRoutingType((ConnType)2);
+
+ ConnRef *connRef224 = new ConnRef(router, 224);
+ ConnEnd srcPt224(Point(627.5, 483.5), 8);
+ connRef224->setSourceEndpoint(srcPt224);
+ ConnEnd dstPt224(Point(1329.5, 504.5), 15);
+ connRef224->setDestEndpoint(dstPt224);
+ connRef224->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints224(1);
+ checkpoints224[0] = Point(650.5, 504.5);
+ connRef224->setRoutingCheckpoints(checkpoints224);
+
+ ConnRef *connRef225 = new ConnRef(router, 225);
+ ConnEnd srcPt225(Point(528.5, 698.25), 8);
+ connRef225->setSourceEndpoint(srcPt225);
+ ConnEnd dstPt225(Point(868.5, 677.25), 15);
+ connRef225->setDestEndpoint(dstPt225);
+ connRef225->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints225(1);
+ checkpoints225[0] = Point(551.5, 677.25);
+ connRef225->setRoutingCheckpoints(checkpoints225);
+
+ ConnRef *connRef226 = new ConnRef(router, 226);
+ ConnEnd srcPt226(Point(301.5, 810.25), 8);
+ connRef226->setSourceEndpoint(srcPt226);
+ ConnEnd dstPt226(Point(443.5, 810.25), 15);
+ connRef226->setDestEndpoint(dstPt226);
+ connRef226->setRoutingType((ConnType)2);
+
+ ConnRef *connRef227 = new ConnRef(router, 227);
+ ConnEnd srcPt227(Point(301.5, 926.25), 8);
+ connRef227->setSourceEndpoint(srcPt227);
+ ConnEnd dstPt227(Point(443.5, 926.25), 15);
+ connRef227->setDestEndpoint(dstPt227);
+ connRef227->setRoutingType((ConnType)2);
+
+ ConnRef *connRef228 = new ConnRef(router, 228);
+ ConnEnd srcPt228(Point(693.5, 810.25), 8);
+ connRef228->setSourceEndpoint(srcPt228);
+ ConnEnd dstPt228(Point(868.5, 677.25), 15);
+ connRef228->setDestEndpoint(dstPt228);
+ connRef228->setRoutingType((ConnType)2);
+
+ ConnRef *connRef229 = new ConnRef(router, 229);
+ ConnEnd srcPt229(Point(693.5, 926.25), 8);
+ connRef229->setSourceEndpoint(srcPt229);
+ ConnEnd dstPt229(Point(868.5, 677.25), 15);
+ connRef229->setDestEndpoint(dstPt229);
+ connRef229->setRoutingType((ConnType)2);
+
+ ConnRef *connRef230 = new ConnRef(router, 230);
+ ConnEnd srcPt230(Point(1541.5, 471), 15);
+ connRef230->setSourceEndpoint(srcPt230);
+ ConnEnd dstPt230(Point(1480.5, 471), 8);
+ connRef230->setDestEndpoint(dstPt230);
+ connRef230->setRoutingType((ConnType)2);
+
+ ConnRef *connRef231 = new ConnRef(router, 231);
+ ConnEnd srcPt231(Point(286.5, 504.5), 15);
+ connRef231->setSourceEndpoint(srcPt231);
+ ConnEnd dstPt231(Point(597.5, 483.5), 4);
+ connRef231->setDestEndpoint(dstPt231);
+ connRef231->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints231(1);
+ checkpoints231[0] = Point(574.5, 504.5);
+ connRef231->setRoutingCheckpoints(checkpoints231);
+
+ ConnRef *connRef232 = new ConnRef(router, 232);
+ ConnEnd srcPt232(Point(286.5, 504.5), 15);
+ connRef232->setSourceEndpoint(srcPt232);
+ ConnEnd dstPt232(Point(597.5, 525.5), 4);
+ connRef232->setDestEndpoint(dstPt232);
+ connRef232->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints232(1);
+ checkpoints232[0] = Point(574.5, 504.5);
+ connRef232->setRoutingCheckpoints(checkpoints232);
+
+ ConnRef *connRef233 = new ConnRef(router, 233);
+ ConnEnd srcPt233(Point(286.5, 677.25), 15);
+ connRef233->setSourceEndpoint(srcPt233);
+ ConnEnd dstPt233(Point(498.5, 698.25), 4);
+ connRef233->setDestEndpoint(dstPt233);
+ connRef233->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints233(1);
+ checkpoints233[0] = Point(475.5, 677.25);
+ connRef233->setRoutingCheckpoints(checkpoints233);
+
+ ConnRef *connRef234 = new ConnRef(router, 234);
+ ConnEnd srcPt234(Point(498.5, 773.25), 4);
+ connRef234->setSourceEndpoint(srcPt234);
+ ConnEnd dstPt234(Point(286.5, 677.25), 15);
+ connRef234->setDestEndpoint(dstPt234);
+ connRef234->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints234(1);
+ checkpoints234[0] = Point(475.5, 677.25);
+ connRef234->setRoutingCheckpoints(checkpoints234);
+
+ ConnRef *connRef235 = new ConnRef(router, 235);
+ ConnEnd srcPt235(Point(528.5, 773.25), 8);
+ connRef235->setSourceEndpoint(srcPt235);
+ ConnEnd dstPt235(Point(868.5, 677.25), 15);
+ connRef235->setDestEndpoint(dstPt235);
+ connRef235->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints235(1);
+ checkpoints235[0] = Point(551.5, 677.25);
+ connRef235->setRoutingCheckpoints(checkpoints235);
+
+ ConnRef *connRef236 = new ConnRef(router, 236);
+ ConnEnd srcPt236(Point(1329.5, 677.25), 15);
+ connRef236->setSourceEndpoint(srcPt236);
+ ConnEnd dstPt236(Point(1350.5, 762.25), 1);
+ connRef236->setDestEndpoint(dstPt236);
+ connRef236->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints236(1);
+ checkpoints236[0] = Point(1329.5, 747.25);
+ connRef236->setRoutingCheckpoints(checkpoints236);
+
+ ConnRef *connRef237 = new ConnRef(router, 237);
+ ConnEnd srcPt237(Point(392.5, 1735.92), 8);
+ connRef237->setSourceEndpoint(srcPt237);
+ ConnEnd dstPt237(Point(1329.5, 1714.92), 15);
+ connRef237->setDestEndpoint(dstPt237);
+ connRef237->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints237(1);
+ checkpoints237[0] = Point(415.5, 1714.92);
+ connRef237->setRoutingCheckpoints(checkpoints237);
+
+ ConnRef *connRef238 = new ConnRef(router, 238);
+ ConnEnd srcPt238(Point(1436.5, 1303.92), 2);
+ connRef238->setSourceEndpoint(srcPt238);
+ ConnEnd dstPt238(Point(1329.5, 1466.92), 15);
+ connRef238->setDestEndpoint(dstPt238);
+ connRef238->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints238(1);
+ checkpoints238[0] = Point(1457.5, 1318.92);
+ connRef238->setRoutingCheckpoints(checkpoints238);
+
+ ConnRef *connRef239 = new ConnRef(router, 239);
+ ConnEnd srcPt239(Point(1478.5, 1303.92), 2);
+ connRef239->setSourceEndpoint(srcPt239);
+ ConnEnd dstPt239(Point(1329.5, 1466.92), 15);
+ connRef239->setDestEndpoint(dstPt239);
+ connRef239->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints239(1);
+ checkpoints239[0] = Point(1457.5, 1318.92);
+ connRef239->setRoutingCheckpoints(checkpoints239);
+
+ ConnRef *connRef240 = new ConnRef(router, 240);
+ ConnEnd srcPt240(Point(1569.5, 1303.92), 2);
+ connRef240->setSourceEndpoint(srcPt240);
+ ConnEnd dstPt240(Point(1329.5, 1466.92), 15);
+ connRef240->setDestEndpoint(dstPt240);
+ connRef240->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints240(1);
+ checkpoints240[0] = Point(1457.5, 1318.92);
+ connRef240->setRoutingCheckpoints(checkpoints240);
+
+ ConnRef *connRef241 = new ConnRef(router, 241);
+ ConnEnd srcPt241(Point(1350.5, 1129.92), 2);
+ connRef241->setSourceEndpoint(srcPt241);
+ ConnEnd dstPt241(Point(1329.5, 1226.92), 15);
+ connRef241->setDestEndpoint(dstPt241);
+ connRef241->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints241(1);
+ checkpoints241[0] = Point(1329.5, 1144.92);
+ connRef241->setRoutingCheckpoints(checkpoints241);
+
+ ConnRef *connRef242 = new ConnRef(router, 242);
+ ConnEnd srcPt242(Point(1263.5, 1226.92), 8);
+ connRef242->setSourceEndpoint(srcPt242);
+ ConnEnd dstPt242(Point(1329.5, 1226.92), 15);
+ connRef242->setDestEndpoint(dstPt242);
+ connRef242->setRoutingType((ConnType)2);
+
+ ConnRef *connRef243 = new ConnRef(router, 243);
+ ConnEnd srcPt243(Point(1296.5, 2173.92), 8);
+ connRef243->setSourceEndpoint(srcPt243);
+ ConnEnd dstPt243(Point(1465.5, 2269.92), 15);
+ connRef243->setDestEndpoint(dstPt243);
+ connRef243->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints243(1);
+ checkpoints243[0] = Point(1319.5, 2269.92);
+ connRef243->setRoutingCheckpoints(checkpoints243);
+
+ ConnRef *connRef244 = new ConnRef(router, 244);
+ ConnEnd srcPt244(Point(1296.5, 2248.92), 8);
+ connRef244->setSourceEndpoint(srcPt244);
+ ConnEnd dstPt244(Point(1465.5, 2269.92), 15);
+ connRef244->setDestEndpoint(dstPt244);
+ connRef244->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints244(1);
+ checkpoints244[0] = Point(1319.5, 2269.92);
+ connRef244->setRoutingCheckpoints(checkpoints244);
+
+ ConnRef *connRef245 = new ConnRef(router, 245);
+ ConnEnd srcPt245(Point(1296.5, 2290.92), 8);
+ connRef245->setSourceEndpoint(srcPt245);
+ ConnEnd dstPt245(Point(1465.5, 2269.92), 15);
+ connRef245->setDestEndpoint(dstPt245);
+ connRef245->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints245(1);
+ checkpoints245[0] = Point(1319.5, 2269.92);
+ connRef245->setRoutingCheckpoints(checkpoints245);
+
+ ConnRef *connRef246 = new ConnRef(router, 246);
+ ConnEnd srcPt246(Point(1296.5, 2365.92), 8);
+ connRef246->setSourceEndpoint(srcPt246);
+ ConnEnd dstPt246(Point(1465.5, 2269.92), 15);
+ connRef246->setDestEndpoint(dstPt246);
+ connRef246->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints246(1);
+ checkpoints246[0] = Point(1319.5, 2269.92);
+ connRef246->setRoutingCheckpoints(checkpoints246);
+
+ ConnRef *connRef247 = new ConnRef(router, 247);
+ ConnEnd srcPt247(Point(693.5, 1859.92), 8);
+ connRef247->setSourceEndpoint(srcPt247);
+ ConnEnd dstPt247(Point(1329.5, 2008.92), 15);
+ connRef247->setDestEndpoint(dstPt247);
+ connRef247->setRoutingType((ConnType)2);
+
+ ConnRef *connRef248 = new ConnRef(router, 248);
+ ConnEnd srcPt248(Point(967.5, 2008.92), 15);
+ connRef248->setSourceEndpoint(srcPt248);
+ ConnEnd dstPt248(Point(967.5, 2192.92), 1);
+ connRef248->setDestEndpoint(dstPt248);
+ connRef248->setRoutingType((ConnType)2);
+
+ ConnRef *connRef249 = new ConnRef(router, 249);
+ ConnEnd srcPt249(Point(663.5, 1859.92), 4);
+ connRef249->setSourceEndpoint(srcPt249);
+ ConnEnd dstPt249(Point(251.5, 2008.92), 15);
+ connRef249->setDestEndpoint(dstPt249);
+ connRef249->setRoutingType((ConnType)2);
+
+ ConnRef *connRef250 = new ConnRef(router, 250);
+ ConnEnd srcPt250(Point(1266.5, 2290.92), 4);
+ connRef250->setSourceEndpoint(srcPt250);
+ ConnEnd dstPt250(Point(967.5, 2269.92), 15);
+ connRef250->setDestEndpoint(dstPt250);
+ connRef250->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints250(1);
+ checkpoints250[0] = Point(1243.5, 2269.92);
+ connRef250->setRoutingCheckpoints(checkpoints250);
+
+ ConnRef *connRef251 = new ConnRef(router, 251);
+ ConnEnd srcPt251(Point(1266.5, 2365.92), 4);
+ connRef251->setSourceEndpoint(srcPt251);
+ ConnEnd dstPt251(Point(967.5, 2269.92), 15);
+ connRef251->setDestEndpoint(dstPt251);
+ connRef251->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints251(1);
+ checkpoints251[0] = Point(1243.5, 2269.92);
+ connRef251->setRoutingCheckpoints(checkpoints251);
+
+ ConnRef *connRef252 = new ConnRef(router, 252);
+ ConnEnd srcPt252(Point(531.5, 2174.92), 4);
+ connRef252->setSourceEndpoint(srcPt252);
+ ConnEnd dstPt252(Point(410.5, 2174.92), 15);
+ connRef252->setDestEndpoint(dstPt252);
+ connRef252->setRoutingType((ConnType)2);
+
+ ConnRef *connRef253 = new ConnRef(router, 253);
+ ConnEnd srcPt253(Point(1329.5, 843.25), 15);
+ connRef253->setSourceEndpoint(srcPt253);
+ ConnEnd dstPt253(Point(1441.5, 792.25), 2);
+ connRef253->setDestEndpoint(dstPt253);
+ connRef253->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints253(1);
+ checkpoints253[0] = Point(1329.5, 807.25);
+ connRef253->setRoutingCheckpoints(checkpoints253);
+
+ ConnRef *connRef254 = new ConnRef(router, 254);
+ ConnEnd srcPt254(Point(216.5, 810.25), 15);
+ connRef254->setSourceEndpoint(srcPt254);
+ ConnEnd dstPt254(Point(271.5, 810.25), 4);
+ connRef254->setDestEndpoint(dstPt254);
+ connRef254->setRoutingType((ConnType)2);
+
+ ConnRef *connRef255 = new ConnRef(router, 255);
+ ConnEnd srcPt255(Point(443.5, 810.25), 15);
+ connRef255->setSourceEndpoint(srcPt255);
+ ConnEnd dstPt255(Point(663.5, 810.25), 4);
+ connRef255->setDestEndpoint(dstPt255);
+ connRef255->setRoutingType((ConnType)2);
+
+ ConnRef *connRef256 = new ConnRef(router, 256);
+ ConnEnd srcPt256(Point(443.5, 926.25), 15);
+ connRef256->setSourceEndpoint(srcPt256);
+ ConnEnd dstPt256(Point(663.5, 926.25), 4);
+ connRef256->setDestEndpoint(dstPt256);
+ connRef256->setRoutingType((ConnType)2);
+
+ ConnRef *connRef257 = new ConnRef(router, 257);
+ ConnEnd srcPt257(Point(216.5, 926.25), 15);
+ connRef257->setSourceEndpoint(srcPt257);
+ ConnEnd dstPt257(Point(271.5, 926.25), 4);
+ connRef257->setDestEndpoint(dstPt257);
+ connRef257->setRoutingType((ConnType)2);
+
+ ConnRef *connRef258 = new ConnRef(router, 258);
+ ConnEnd srcPt258(Point(392.5, 1693.92), 8);
+ connRef258->setSourceEndpoint(srcPt258);
+ ConnEnd dstPt258(Point(1329.5, 1714.92), 15);
+ connRef258->setDestEndpoint(dstPt258);
+ connRef258->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints258(1);
+ checkpoints258[0] = Point(415.5, 1714.92);
+ connRef258->setRoutingCheckpoints(checkpoints258);
+
+ ConnRef *connRef259 = new ConnRef(router, 259);
+ ConnEnd srcPt259(Point(251.5, 1714.92), 15);
+ connRef259->setSourceEndpoint(srcPt259);
+ ConnEnd dstPt259(Point(362.5, 1693.92), 4);
+ connRef259->setDestEndpoint(dstPt259);
+ connRef259->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints259(1);
+ checkpoints259[0] = Point(339.5, 1714.92);
+ connRef259->setRoutingCheckpoints(checkpoints259);
+
+ ConnRef *connRef260 = new ConnRef(router, 260);
+ ConnEnd srcPt260(Point(251.5, 1714.92), 15);
+ connRef260->setSourceEndpoint(srcPt260);
+ ConnEnd dstPt260(Point(362.5, 1735.92), 4);
+ connRef260->setDestEndpoint(dstPt260);
+ connRef260->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints260(1);
+ checkpoints260[0] = Point(339.5, 1714.92);
+ connRef260->setRoutingCheckpoints(checkpoints260);
+
+ ConnRef *connRef261 = new ConnRef(router, 261);
+ ConnEnd srcPt261(Point(1350.5, 1099.92), 1);
+ connRef261->setSourceEndpoint(srcPt261);
+ ConnEnd dstPt261(Point(1329.5, 1053.92), 15);
+ connRef261->setDestEndpoint(dstPt261);
+ connRef261->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints261(1);
+ checkpoints261[0] = Point(1329.5, 1084.92);
+ connRef261->setRoutingCheckpoints(checkpoints261);
+
+ ConnRef *connRef262 = new ConnRef(router, 262);
+ ConnEnd srcPt262(Point(1233.5, 1433.92), 4);
+ connRef262->setSourceEndpoint(srcPt262);
+ ConnEnd dstPt262(Point(1091.5, 1350.92), 15);
+ connRef262->setDestEndpoint(dstPt262);
+ connRef262->setRoutingType((ConnType)2);
+
+ ConnRef *connRef263 = new ConnRef(router, 263);
+ ConnEnd srcPt263(Point(1263.5, 1433.92), 8);
+ connRef263->setSourceEndpoint(srcPt263);
+ ConnEnd dstPt263(Point(1329.5, 1466.92), 15);
+ connRef263->setDestEndpoint(dstPt263);
+ connRef263->setRoutingType((ConnType)2);
+
+ ConnRef *connRef264 = new ConnRef(router, 264);
+ ConnEnd srcPt264(Point(1233.5, 1226.92), 4);
+ connRef264->setSourceEndpoint(srcPt264);
+ ConnEnd dstPt264(Point(1091.5, 1350.92), 15);
+ connRef264->setDestEndpoint(dstPt264);
+ connRef264->setRoutingType((ConnType)2);
+
+ ConnRef *connRef265 = new ConnRef(router, 265);
+ ConnEnd srcPt265(Point(1329.5, 1053.92), 15);
+ connRef265->setSourceEndpoint(srcPt265);
+ ConnEnd dstPt265(Point(1436.5, 1273.92), 1);
+ connRef265->setDestEndpoint(dstPt265);
+ connRef265->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints265(1);
+ checkpoints265[0] = Point(1457.5, 1258.92);
+ connRef265->setRoutingCheckpoints(checkpoints265);
+
+ ConnRef *connRef266 = new ConnRef(router, 266);
+ ConnEnd srcPt266(Point(1329.5, 1053.92), 15);
+ connRef266->setSourceEndpoint(srcPt266);
+ ConnEnd dstPt266(Point(1478.5, 1273.92), 1);
+ connRef266->setDestEndpoint(dstPt266);
+ connRef266->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints266(1);
+ checkpoints266[0] = Point(1457.5, 1258.92);
+ connRef266->setRoutingCheckpoints(checkpoints266);
+
+ ConnRef *connRef267 = new ConnRef(router, 267);
+ ConnEnd srcPt267(Point(1329.5, 1053.92), 15);
+ connRef267->setSourceEndpoint(srcPt267);
+ ConnEnd dstPt267(Point(1569.5, 1273.92), 1);
+ connRef267->setDestEndpoint(dstPt267);
+ connRef267->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints267(1);
+ checkpoints267[0] = Point(1457.5, 1258.92);
+ connRef267->setRoutingCheckpoints(checkpoints267);
+
+ ConnRef *connRef268 = new ConnRef(router, 268);
+ ConnEnd srcPt268(Point(230.5, 2054.92), 1);
+ connRef268->setSourceEndpoint(srcPt268);
+ ConnEnd dstPt268(Point(251.5, 2008.92), 15);
+ connRef268->setDestEndpoint(dstPt268);
+ connRef268->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints268(1);
+ checkpoints268[0] = Point(251.5, 2039.92);
+ connRef268->setRoutingCheckpoints(checkpoints268);
+
+ ConnRef *connRef269 = new ConnRef(router, 269);
+ ConnEnd srcPt269(Point(1350.5, 792.25), 2);
+ connRef269->setSourceEndpoint(srcPt269);
+ ConnEnd dstPt269(Point(1329.5, 843.25), 15);
+ connRef269->setDestEndpoint(dstPt269);
+ connRef269->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints269(1);
+ checkpoints269[0] = Point(1329.5, 807.25);
+ connRef269->setRoutingCheckpoints(checkpoints269);
+
+ ConnRef *connRef270 = new ConnRef(router, 270);
+ ConnEnd srcPt270(Point(627.5, 525.5), 8);
+ connRef270->setSourceEndpoint(srcPt270);
+ ConnEnd dstPt270(Point(1329.5, 504.5), 15);
+ connRef270->setDestEndpoint(dstPt270);
+ connRef270->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints270(1);
+ checkpoints270[0] = Point(650.5, 504.5);
+ connRef270->setRoutingCheckpoints(checkpoints270);
+
+ ConnRef *connRef271 = new ConnRef(router, 271);
+ ConnEnd srcPt271(Point(967.5, 1892.92), 15);
+ connRef271->setSourceEndpoint(srcPt271);
+ ConnEnd dstPt271(Point(1172.5, 2041.92), 8);
+ connRef271->setDestEndpoint(dstPt271);
+ connRef271->setRoutingType((ConnType)2);
+
+ ConnRef *connRef272 = new ConnRef(router, 272);
+ ConnEnd srcPt272(Point(967.5, 1892.92), 15);
+ connRef272->setSourceEndpoint(srcPt272);
+ ConnEnd dstPt272(Point(1157.5, 1910.92), 1);
+ connRef272->setDestEndpoint(dstPt272);
+ connRef272->setRoutingType((ConnType)2);
+
+ ConnRef *connRef273 = new ConnRef(router, 273);
+ ConnEnd srcPt273(Point(1387.5, 959.25), 4);
+ connRef273->setSourceEndpoint(srcPt273);
+ ConnEnd dstPt273(Point(1329.5, 959.25), 8);
+ connRef273->setDestEndpoint(dstPt273);
+ connRef273->setRoutingType((ConnType)2);
+
+ ConnRef *connRef274 = new ConnRef(router, 274);
+ ConnEnd srcPt274(Point(645.5, 2198.92), 2);
+ connRef274->setSourceEndpoint(srcPt274);
+ ConnEnd dstPt274(Point(645.5, 2248.92), 1);
+ connRef274->setDestEndpoint(dstPt274);
+ connRef274->setRoutingType((ConnType)2);
+
+ ConnRef *connRef275 = new ConnRef(router, 275);
+ ConnEnd srcPt275(Point(330.5, 2069.92), 4);
+ connRef275->setSourceEndpoint(srcPt275);
+ ConnEnd dstPt275(Point(272.5, 2069.92), 8);
+ connRef275->setDestEndpoint(dstPt275);
+ connRef275->setRoutingType((ConnType)2);
+
+ ConnRef *connRef276 = new ConnRef(router, 276);
+ ConnEnd srcPt276(Point(645.5, 2340.92), 1);
+ connRef276->setSourceEndpoint(srcPt276);
+ ConnEnd dstPt276(Point(645.5, 2290.92), 2);
+ connRef276->setDestEndpoint(dstPt276);
+ connRef276->setRoutingType((ConnType)2);
+
+ ConnRef *connRef277 = new ConnRef(router, 277);
+ ConnEnd srcPt277(Point(1025.5, 2207.92), 4);
+ connRef277->setSourceEndpoint(srcPt277);
+ ConnEnd dstPt277(Point(967.5, 2207.92), 8);
+ connRef277->setDestEndpoint(dstPt277);
+ connRef277->setRoutingType((ConnType)2);
+
+ ConnRef *connRef278 = new ConnRef(router, 278);
+ ConnEnd srcPt278(Point(1281.5, 2123.92), 2);
+ connRef278->setSourceEndpoint(srcPt278);
+ ConnEnd dstPt278(Point(1281.5, 2173.92), 1);
+ connRef278->setDestEndpoint(dstPt278);
+ connRef278->setRoutingType((ConnType)2);
+
+ ConnRef *connRef279 = new ConnRef(router, 279);
+ ConnEnd srcPt279(Point(1281.5, 2198.92), 2);
+ connRef279->setSourceEndpoint(srcPt279);
+ ConnEnd dstPt279(Point(1281.5, 2248.92), 1);
+ connRef279->setDestEndpoint(dstPt279);
+ connRef279->setRoutingType((ConnType)2);
+
+ ConnRef *connRef280 = new ConnRef(router, 280);
+ ConnEnd srcPt280(Point(1157.5, 2091.92), 1);
+ connRef280->setSourceEndpoint(srcPt280);
+ ConnEnd dstPt280(Point(1157.5, 2041.92), 2);
+ connRef280->setDestEndpoint(dstPt280);
+ connRef280->setRoutingType((ConnType)2);
+
+ ConnRef *connRef281 = new ConnRef(router, 281);
+ ConnEnd srcPt281(Point(1215.5, 1925.92), 4);
+ connRef281->setSourceEndpoint(srcPt281);
+ ConnEnd dstPt281(Point(1157.5, 1925.92), 8);
+ connRef281->setDestEndpoint(dstPt281);
+ connRef281->setRoutingType((ConnType)2);
+
+ ConnRef *connRef282 = new ConnRef(router, 282);
+ ConnEnd srcPt282(Point(835.5, 1958.92), 2);
+ connRef282->setSourceEndpoint(srcPt282);
+ ConnEnd dstPt282(Point(835.5, 2008.92), 1);
+ connRef282->setDestEndpoint(dstPt282);
+ connRef282->setRoutingType((ConnType)2);
+
+ ConnRef *connRef283 = new ConnRef(router, 283);
+ ConnEnd srcPt283(Point(410.5, 1958.92), 2);
+ connRef283->setSourceEndpoint(srcPt283);
+ ConnEnd dstPt283(Point(410.5, 2008.92), 1);
+ connRef283->setDestEndpoint(dstPt283);
+ connRef283->setRoutingType((ConnType)2);
+
+ ConnRef *connRef284 = new ConnRef(router, 284);
+ ConnEnd srcPt284(Point(1498.5, 1958.92), 2);
+ connRef284->setSourceEndpoint(srcPt284);
+ ConnEnd dstPt284(Point(1498.5, 2008.92), 1);
+ connRef284->setDestEndpoint(dstPt284);
+ connRef284->setRoutingType((ConnType)2);
+
+ ConnRef *connRef285 = new ConnRef(router, 285);
+ ConnEnd srcPt285(Point(1387.5, 1776.92), 4);
+ connRef285->setSourceEndpoint(srcPt285);
+ ConnEnd dstPt285(Point(1329.5, 1776.92), 8);
+ connRef285->setDestEndpoint(dstPt285);
+ connRef285->setRoutingType((ConnType)2);
+
+ ConnRef *connRef286 = new ConnRef(router, 286);
+ ConnEnd srcPt286(Point(1387.5, 1652.92), 4);
+ connRef286->setSourceEndpoint(srcPt286);
+ ConnEnd dstPt286(Point(1329.5, 1652.92), 8);
+ connRef286->setDestEndpoint(dstPt286);
+ connRef286->setRoutingType((ConnType)2);
+
+ ConnRef *connRef287 = new ConnRef(router, 287);
+ ConnEnd srcPt287(Point(1387.5, 1528.92), 4);
+ connRef287->setSourceEndpoint(srcPt287);
+ ConnEnd dstPt287(Point(1329.5, 1528.92), 8);
+ connRef287->setDestEndpoint(dstPt287);
+ connRef287->setRoutingType((ConnType)2);
+
+ ConnRef *connRef288 = new ConnRef(router, 288);
+ ConnEnd srcPt288(Point(1250.5, 1114.92), 8);
+ connRef288->setSourceEndpoint(srcPt288);
+ ConnEnd dstPt288(Point(1308.5, 1114.92), 4);
+ connRef288->setDestEndpoint(dstPt288);
+ connRef288->setRoutingType((ConnType)2);
+
+ ConnRef *connRef289 = new ConnRef(router, 289);
+ ConnEnd srcPt289(Point(1124.5, 1003.92), 2);
+ connRef289->setSourceEndpoint(srcPt289);
+ ConnEnd dstPt289(Point(1124.5, 1053.92), 1);
+ connRef289->setDestEndpoint(dstPt289);
+ connRef289->setRoutingType((ConnType)2);
+
+ ConnRef *connRef290 = new ConnRef(router, 290);
+ ConnEnd srcPt290(Point(1250.5, 777.25), 8);
+ connRef290->setSourceEndpoint(srcPt290);
+ ConnEnd dstPt290(Point(1308.5, 777.25), 4);
+ connRef290->setDestEndpoint(dstPt290);
+ connRef290->setRoutingType((ConnType)2);
+
+ ConnRef *connRef291 = new ConnRef(router, 291);
+ ConnEnd srcPt291(Point(1499.5, 777.25), 4);
+ connRef291->setSourceEndpoint(srcPt291);
+ ConnEnd dstPt291(Point(1441.5, 777.25), 8);
+ connRef291->setDestEndpoint(dstPt291);
+ connRef291->setRoutingType((ConnType)2);
+
+ ConnRef *connRef292 = new ConnRef(router, 292);
+ ConnEnd srcPt292(Point(1465.5, 421), 2);
+ connRef292->setSourceEndpoint(srcPt292);
+ ConnEnd dstPt292(Point(1465.5, 471), 1);
+ connRef292->setDestEndpoint(dstPt292);
+ connRef292->setRoutingType((ConnType)2);
+
+ ConnRef *connRef293 = new ConnRef(router, 293);
+ ConnEnd srcPt293(Point(1387.5, 589.75), 4);
+ connRef293->setSourceEndpoint(srcPt293);
+ ConnEnd dstPt293(Point(1329.5, 589.75), 8);
+ connRef293->setDestEndpoint(dstPt293);
+ connRef293->setRoutingType((ConnType)2);
+
+ ConnRef *connRef294 = new ConnRef(router, 294);
+ ConnEnd srcPt294(Point(1387.5, 388), 4);
+ connRef294->setSourceEndpoint(srcPt294);
+ ConnEnd dstPt294(Point(1329.5, 388), 8);
+ connRef294->setDestEndpoint(dstPt294);
+ connRef294->setRoutingType((ConnType)2);
+
+ ConnRef *connRef295 = new ConnRef(router, 295);
+ ConnEnd srcPt295(Point(1058.5, 627.25), 2);
+ connRef295->setSourceEndpoint(srcPt295);
+ ConnEnd dstPt295(Point(1058.5, 677.25), 1);
+ connRef295->setDestEndpoint(dstPt295);
+ connRef295->setRoutingType((ConnType)2);
+
+ ConnRef *connRef296 = new ConnRef(router, 296);
+ ConnEnd srcPt296(Point(513.5, 531.25), 2);
+ connRef296->setSourceEndpoint(srcPt296);
+ ConnEnd dstPt296(Point(513.5, 581.25), 1);
+ connRef296->setDestEndpoint(dstPt296);
+ connRef296->setRoutingType((ConnType)2);
+
+ ConnRef *connRef297 = new ConnRef(router, 297);
+ ConnEnd srcPt297(Point(513.5, 606.25), 2);
+ connRef297->setSourceEndpoint(srcPt297);
+ ConnEnd dstPt297(Point(513.5, 656.25), 1);
+ connRef297->setDestEndpoint(dstPt297);
+ connRef297->setRoutingType((ConnType)2);
+
+ ConnRef *connRef298 = new ConnRef(router, 298);
+ ConnEnd srcPt298(Point(934.5, 539.75), 2);
+ connRef298->setSourceEndpoint(srcPt298);
+ ConnEnd dstPt298(Point(934.5, 589.75), 1);
+ connRef298->setDestEndpoint(dstPt298);
+ connRef298->setRoutingType((ConnType)2);
+
+ ConnRef *connRef299 = new ConnRef(router, 299);
+ ConnEnd srcPt299(Point(711.5, 589.75), 8);
+ connRef299->setSourceEndpoint(srcPt299);
+ ConnEnd dstPt299(Point(769.5, 589.75), 4);
+ connRef299->setDestEndpoint(dstPt299);
+ connRef299->setRoutingType((ConnType)2);
+
+ ConnRef *connRef300 = new ConnRef(router, 300);
+ ConnEnd srcPt300(Point(344.5, 589.75), 4);
+ connRef300->setSourceEndpoint(srcPt300);
+ ConnEnd dstPt300(Point(286.5, 589.75), 8);
+ connRef300->setDestEndpoint(dstPt300);
+ connRef300->setRoutingType((ConnType)2);
+
+ ConnRef *connRef301 = new ConnRef(router, 301);
+ ConnEnd srcPt301(Point(612.5, 283.5), 2);
+ connRef301->setSourceEndpoint(srcPt301);
+ ConnEnd dstPt301(Point(612.5, 333.5), 1);
+ connRef301->setDestEndpoint(dstPt301);
+ connRef301->setRoutingType((ConnType)2);
+
+ ConnRef *connRef302 = new ConnRef(router, 302);
+ ConnEnd srcPt302(Point(612.5, 358.5), 2);
+ connRef302->setSourceEndpoint(srcPt302);
+ ConnEnd dstPt302(Point(612.5, 408.5), 1);
+ connRef302->setDestEndpoint(dstPt302);
+ connRef302->setRoutingType((ConnType)2);
+
+ ConnRef *connRef303 = new ConnRef(router, 303);
+ ConnEnd srcPt303(Point(612.5, 650.5), 1);
+ connRef303->setSourceEndpoint(srcPt303);
+ ConnEnd dstPt303(Point(612.5, 600.5), 2);
+ connRef303->setDestEndpoint(dstPt303);
+ connRef303->setRoutingType((ConnType)2);
+
+ ConnRef *connRef304 = new ConnRef(router, 304);
+ ConnEnd srcPt304(Point(901.5, 305), 2);
+ connRef304->setSourceEndpoint(srcPt304);
+ ConnEnd dstPt304(Point(901.5, 355), 1);
+ connRef304->setDestEndpoint(dstPt304);
+ connRef304->setRoutingType((ConnType)2);
+
+ ConnRef *connRef305 = new ConnRef(router, 305);
+ ConnEnd srcPt305(Point(901.5, 189), 2);
+ connRef305->setSourceEndpoint(srcPt305);
+ ConnEnd dstPt305(Point(901.5, 239), 1);
+ connRef305->setDestEndpoint(dstPt305);
+ connRef305->setRoutingType((ConnType)2);
+
+ ConnRef *connRef306 = new ConnRef(router, 306);
+ ConnEnd srcPt306(Point(546.5, 2124.92), 2);
+ connRef306->setSourceEndpoint(srcPt306);
+ ConnEnd dstPt306(Point(546.5, 2174.92), 1);
+ connRef306->setDestEndpoint(dstPt306);
+ connRef306->setRoutingType((ConnType)2);
+
+ ConnRef *connRef307 = new ConnRef(router, 307);
+ ConnEnd srcPt307(Point(1387.5, 1350.92), 4);
+ connRef307->setSourceEndpoint(srcPt307);
+ ConnEnd dstPt307(Point(1329.5, 1350.92), 8);
+ connRef307->setDestEndpoint(dstPt307);
+ connRef307->setRoutingType((ConnType)2);
+
+ ConnRef *connRef308 = new ConnRef(router, 308);
+ ConnEnd srcPt308(Point(612.5, 433.5), 2);
+ connRef308->setSourceEndpoint(srcPt308);
+ ConnEnd dstPt308(Point(612.5, 483.5), 1);
+ connRef308->setDestEndpoint(dstPt308);
+ connRef308->setRoutingType((ConnType)2);
+
+ ConnRef *connRef309 = new ConnRef(router, 309);
+ ConnEnd srcPt309(Point(513.5, 748.25), 1);
+ connRef309->setSourceEndpoint(srcPt309);
+ ConnEnd dstPt309(Point(513.5, 698.25), 2);
+ connRef309->setDestEndpoint(dstPt309);
+ connRef309->setRoutingType((ConnType)2);
+
+ ConnRef *connRef310 = new ConnRef(router, 310);
+ ConnEnd srcPt310(Point(286.5, 760.25), 2);
+ connRef310->setSourceEndpoint(srcPt310);
+ ConnEnd dstPt310(Point(286.5, 810.25), 1);
+ connRef310->setDestEndpoint(dstPt310);
+ connRef310->setRoutingType((ConnType)2);
+
+ ConnRef *connRef311 = new ConnRef(router, 311);
+ ConnEnd srcPt311(Point(286.5, 876.25), 2);
+ connRef311->setSourceEndpoint(srcPt311);
+ ConnEnd dstPt311(Point(286.5, 926.25), 1);
+ connRef311->setDestEndpoint(dstPt311);
+ connRef311->setRoutingType((ConnType)2);
+
+ ConnRef *connRef312 = new ConnRef(router, 312);
+ ConnEnd srcPt312(Point(678.5, 760.25), 2);
+ connRef312->setSourceEndpoint(srcPt312);
+ ConnEnd dstPt312(Point(678.5, 810.25), 1);
+ connRef312->setDestEndpoint(dstPt312);
+ connRef312->setRoutingType((ConnType)2);
+
+ ConnRef *connRef313 = new ConnRef(router, 313);
+ ConnEnd srcPt313(Point(678.5, 876.25), 2);
+ connRef313->setSourceEndpoint(srcPt313);
+ ConnEnd dstPt313(Point(678.5, 926.25), 1);
+ connRef313->setDestEndpoint(dstPt313);
+ connRef313->setRoutingType((ConnType)2);
+
+ ConnRef *connRef314 = new ConnRef(router, 314);
+ ConnEnd srcPt314(Point(377.5, 1643.92), 2);
+ connRef314->setSourceEndpoint(srcPt314);
+ ConnEnd dstPt314(Point(377.5, 1693.92), 1);
+ connRef314->setDestEndpoint(dstPt314);
+ connRef314->setRoutingType((ConnType)2);
+
+ ConnRef *connRef315 = new ConnRef(router, 315);
+ ConnEnd srcPt315(Point(1281.5, 2340.92), 1);
+ connRef315->setSourceEndpoint(srcPt315);
+ ConnEnd dstPt315(Point(1281.5, 2290.92), 2);
+ connRef315->setDestEndpoint(dstPt315);
+ connRef315->setRoutingType((ConnType)2);
+
+ ConnRef *connRef316 = new ConnRef(router, 316);
+ ConnEnd srcPt316(Point(377.5, 1785.92), 1);
+ connRef316->setSourceEndpoint(srcPt316);
+ ConnEnd dstPt316(Point(377.5, 1735.92), 2);
+ connRef316->setDestEndpoint(dstPt316);
+ connRef316->setRoutingType((ConnType)2);
+
+ ConnRef *connRef317 = new ConnRef(router, 317);
+ ConnEnd srcPt317(Point(1408.5, 1114.92), 4);
+ connRef317->setSourceEndpoint(srcPt317);
+ ConnEnd dstPt317(Point(1350.5, 1114.92), 8);
+ connRef317->setDestEndpoint(dstPt317);
+ connRef317->setRoutingType((ConnType)2);
+
+ ConnRef *connRef318 = new ConnRef(router, 318);
+ ConnEnd srcPt318(Point(1378.5, 1288.92), 8);
+ connRef318->setSourceEndpoint(srcPt318);
+ ConnEnd dstPt318(Point(1436.5, 1288.92), 4);
+ connRef318->setDestEndpoint(dstPt318);
+ connRef318->setRoutingType((ConnType)2);
+
+ ConnRef *connRef319 = new ConnRef(router, 319);
+ ConnEnd srcPt319(Point(1536.5, 1288.92), 4);
+ connRef319->setSourceEndpoint(srcPt319);
+ ConnEnd dstPt319(Point(1478.5, 1288.92), 8);
+ connRef319->setDestEndpoint(dstPt319);
+ connRef319->setRoutingType((ConnType)2);
+
+ ConnRef *connRef320 = new ConnRef(router, 320);
+ ConnEnd srcPt320(Point(678.5, 1809.92), 2);
+ connRef320->setSourceEndpoint(srcPt320);
+ ConnEnd dstPt320(Point(678.5, 1859.92), 1);
+ connRef320->setDestEndpoint(dstPt320);
+ connRef320->setRoutingType((ConnType)2);
+
+ ConnRef *connRef321 = new ConnRef(router, 321);
+ ConnEnd srcPt321(Point(1627.5, 1288.92), 4);
+ connRef321->setSourceEndpoint(srcPt321);
+ ConnEnd dstPt321(Point(1569.5, 1288.92), 8);
+ connRef321->setDestEndpoint(dstPt321);
+ connRef321->setRoutingType((ConnType)2);
+
+ ConnRef *connRef322 = new ConnRef(router, 322);
+ ConnEnd srcPt322(Point(1248.5, 1383.92), 2);
+ connRef322->setSourceEndpoint(srcPt322);
+ ConnEnd dstPt322(Point(1248.5, 1433.92), 1);
+ connRef322->setDestEndpoint(dstPt322);
+ connRef322->setRoutingType((ConnType)2);
+
+ ConnRef *connRef323 = new ConnRef(router, 323);
+ ConnEnd srcPt323(Point(1248.5, 1176.92), 2);
+ connRef323->setSourceEndpoint(srcPt323);
+ ConnEnd dstPt323(Point(1248.5, 1226.92), 1);
+ connRef323->setDestEndpoint(dstPt323);
+ connRef323->setRoutingType((ConnType)2);
+
+ ConnRef *connRef324 = new ConnRef(router, 324);
+ ConnEnd srcPt324(Point(172.5, 2069.92), 8);
+ connRef324->setSourceEndpoint(srcPt324);
+ ConnEnd dstPt324(Point(230.5, 2069.92), 4);
+ connRef324->setDestEndpoint(dstPt324);
+ connRef324->setRoutingType((ConnType)2);
+
+ ConnRef *connRef325 = new ConnRef(router, 325);
+ ConnEnd srcPt325(Point(1408.5, 777.25), 4);
+ connRef325->setSourceEndpoint(srcPt325);
+ ConnEnd dstPt325(Point(1350.5, 777.25), 8);
+ connRef325->setDestEndpoint(dstPt325);
+ connRef325->setRoutingType((ConnType)2);
+
+ ConnRef *connRef326 = new ConnRef(router, 326);
+ ConnEnd srcPt326(Point(612.5, 575.5), 1);
+ connRef326->setSourceEndpoint(srcPt326);
+ ConnEnd dstPt326(Point(612.5, 525.5), 2);
+ connRef326->setDestEndpoint(dstPt326);
+ connRef326->setRoutingType((ConnType)2);
+
+ ConnRef *connRef327 = new ConnRef(router, 327);
+ ConnEnd srcPt327(Point(513.5, 823.25), 1);
+ connRef327->setSourceEndpoint(srcPt327);
+ ConnEnd dstPt327(Point(513.5, 773.25), 2);
+ connRef327->setDestEndpoint(dstPt327);
+ connRef327->setRoutingType((ConnType)2);
+
+ ConnRef *connRef328 = new ConnRef(router, 328);
+ ConnEnd srcPt328(Point(1281.5, 2415.92), 1);
+ connRef328->setSourceEndpoint(srcPt328);
+ ConnEnd dstPt328(Point(1281.5, 2365.92), 2);
+ connRef328->setDestEndpoint(dstPt328);
+ connRef328->setRoutingType((ConnType)2);
+
+ ConnRef *connRef329 = new ConnRef(router, 329);
+ ConnEnd srcPt329(Point(251.5, 2008.92), 15);
+ connRef329->setSourceEndpoint(srcPt329);
+ ConnEnd dstPt329(Point(272.5, 2054.92), 1);
+ connRef329->setDestEndpoint(dstPt329);
+ connRef329->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints329(1);
+ checkpoints329[0] = Point(251.5, 2039.92);
+ connRef329->setRoutingCheckpoints(checkpoints329);
+
+ ConnRef *connRef330 = new ConnRef(router, 330);
+ ConnEnd srcPt330(Point(1329.5, 2008.92), 15);
+ connRef330->setSourceEndpoint(srcPt330);
+ ConnEnd dstPt330(Point(1172.5, 2041.92), 8);
+ connRef330->setDestEndpoint(dstPt330);
+ connRef330->setRoutingType((ConnType)2);
+
+ ConnRef *connRef331 = new ConnRef(router, 331);
+ ConnEnd srcPt331(Point(1329.5, 2008.92), 15);
+ connRef331->setSourceEndpoint(srcPt331);
+ ConnEnd dstPt331(Point(1157.5, 1910.92), 1);
+ connRef331->setDestEndpoint(dstPt331);
+ connRef331->setRoutingType((ConnType)2);
+
+ ConnRef *connRef332 = new ConnRef(router, 332);
+ ConnEnd srcPt332(Point(802.5, 2174.92), 15);
+ connRef332->setSourceEndpoint(srcPt332);
+ ConnEnd dstPt332(Point(850.5, 2008.92), 8);
+ connRef332->setDestEndpoint(dstPt332);
+ connRef332->setRoutingType((ConnType)2);
+
+ ConnRef *connRef333 = new ConnRef(router, 333);
+ ConnEnd srcPt333(Point(967.5, 2008.92), 15);
+ connRef333->setSourceEndpoint(srcPt333);
+ ConnEnd dstPt333(Point(850.5, 2008.92), 8);
+ connRef333->setDestEndpoint(dstPt333);
+ connRef333->setRoutingType((ConnType)2);
+
+ ConnRef *connRef334 = new ConnRef(router, 334);
+ ConnEnd srcPt334(Point(1329.5, 1714.92), 15);
+ connRef334->setSourceEndpoint(srcPt334);
+ ConnEnd dstPt334(Point(1329.5, 1761.92), 1);
+ connRef334->setDestEndpoint(dstPt334);
+ connRef334->setRoutingType((ConnType)2);
+
+ ConnRef *connRef335 = new ConnRef(router, 335);
+ ConnEnd srcPt335(Point(1329.5, 677.25), 15);
+ connRef335->setSourceEndpoint(srcPt335);
+ ConnEnd dstPt335(Point(1308.5, 762.25), 1);
+ connRef335->setDestEndpoint(dstPt335);
+ connRef335->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints335(1);
+ checkpoints335[0] = Point(1329.5, 747.25);
+ connRef335->setRoutingCheckpoints(checkpoints335);
+
+ ConnRef *connRef336 = new ConnRef(router, 336);
+ ConnEnd srcPt336(Point(286.5, 677.25), 15);
+ connRef336->setSourceEndpoint(srcPt336);
+ ConnEnd dstPt336(Point(498.5, 581.25), 4);
+ connRef336->setDestEndpoint(dstPt336);
+ connRef336->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints336(1);
+ checkpoints336[0] = Point(475.5, 677.25);
+ connRef336->setRoutingCheckpoints(checkpoints336);
+
+ ConnRef *connRef337 = new ConnRef(router, 337);
+ ConnEnd srcPt337(Point(286.5, 677.25), 15);
+ connRef337->setSourceEndpoint(srcPt337);
+ ConnEnd dstPt337(Point(498.5, 656.25), 4);
+ connRef337->setDestEndpoint(dstPt337);
+ connRef337->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints337(1);
+ checkpoints337[0] = Point(475.5, 677.25);
+ connRef337->setRoutingCheckpoints(checkpoints337);
+
+ ConnRef *connRef338 = new ConnRef(router, 338);
+ ConnEnd srcPt338(Point(286.5, 504.5), 15);
+ connRef338->setSourceEndpoint(srcPt338);
+ ConnEnd dstPt338(Point(597.5, 333.5), 4);
+ connRef338->setDestEndpoint(dstPt338);
+ connRef338->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints338(1);
+ checkpoints338[0] = Point(574.5, 504.5);
+ connRef338->setRoutingCheckpoints(checkpoints338);
+
+ ConnRef *connRef339 = new ConnRef(router, 339);
+ ConnEnd srcPt339(Point(286.5, 504.5), 15);
+ connRef339->setSourceEndpoint(srcPt339);
+ ConnEnd dstPt339(Point(597.5, 408.5), 4);
+ connRef339->setDestEndpoint(dstPt339);
+ connRef339->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints339(1);
+ checkpoints339[0] = Point(574.5, 504.5);
+ connRef339->setRoutingCheckpoints(checkpoints339);
+
+ ConnRef *connRef340 = new ConnRef(router, 340);
+ ConnEnd srcPt340(Point(1329.5, 504.5), 15);
+ connRef340->setSourceEndpoint(srcPt340);
+ ConnEnd dstPt340(Point(627.5, 600.5), 8);
+ connRef340->setDestEndpoint(dstPt340);
+ connRef340->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints340(1);
+ checkpoints340[0] = Point(650.5, 504.5);
+ connRef340->setRoutingCheckpoints(checkpoints340);
+
+ ConnRef *connRef341 = new ConnRef(router, 341);
+ ConnEnd srcPt341(Point(1329.5, 272), 15);
+ connRef341->setSourceEndpoint(srcPt341);
+ ConnEnd dstPt341(Point(916.5, 355), 8);
+ connRef341->setDestEndpoint(dstPt341);
+ connRef341->setRoutingType((ConnType)2);
+
+ ConnRef *connRef342 = new ConnRef(router, 342);
+ ConnEnd srcPt342(Point(1329.5, 272), 15);
+ connRef342->setSourceEndpoint(srcPt342);
+ ConnEnd dstPt342(Point(916.5, 239), 8);
+ connRef342->setDestEndpoint(dstPt342);
+ connRef342->setRoutingType((ConnType)2);
+
+ ConnRef *connRef343 = new ConnRef(router, 343);
+ ConnEnd srcPt343(Point(1329.5, 504.5), 15);
+ connRef343->setSourceEndpoint(srcPt343);
+ ConnEnd dstPt343(Point(1555, 720.5), 4);
+ connRef343->setDestEndpoint(dstPt343);
+ connRef343->setRoutingType((ConnType)2);
+
+ ConnRef *connRef344 = new ConnRef(router, 344);
+ ConnEnd srcPt344(Point(1329.5, 1053.92), 15);
+ connRef344->setSourceEndpoint(srcPt344);
+ ConnEnd dstPt344(Point(1555, 760.5), 4);
+ connRef344->setDestEndpoint(dstPt344);
+ connRef344->setRoutingType((ConnType)2);
+
+ ConnRef *connRef345 = new ConnRef(router, 345);
+ ConnEnd srcPt345(Point(1329.5, 1590.92), 15);
+ connRef345->setSourceEndpoint(srcPt345);
+ ConnEnd dstPt345(Point(1641, 924), 2);
+ connRef345->setDestEndpoint(dstPt345);
+ connRef345->setRoutingType((ConnType)2);
+
+ ConnRef *connRef346 = new ConnRef(router, 346);
+ ConnEnd srcPt346(Point(1329.5, 2008.92), 15);
+ connRef346->setSourceEndpoint(srcPt346);
+ ConnEnd dstPt346(Point(1681, 924), 2);
+ connRef346->setDestEndpoint(dstPt346);
+ connRef346->setRoutingType((ConnType)2);
+
+ ConnRef *connRef347 = new ConnRef(router, 347);
+ ConnEnd srcPt347(Point(1329.5, 272), 15);
+ connRef347->setSourceEndpoint(srcPt347);
+ ConnEnd dstPt347(Point(1390, 214.5), 2);
+ connRef347->setDestEndpoint(dstPt347);
+ connRef347->setRoutingType((ConnType)2);
+
+ ConnRef *connRef348 = new ConnRef(router, 348);
+ ConnEnd srcPt348(Point(251.5, 1714.92), 15);
+ connRef348->setSourceEndpoint(srcPt348);
+ ConnEnd dstPt348(Point(247.5, 1845.42), 8);
+ connRef348->setDestEndpoint(dstPt348);
+ connRef348->setRoutingType((ConnType)2);
+
+ ConnRef *connRef349 = new ConnRef(router, 349);
+ ConnEnd srcPt349(Point(251.5, 2008.92), 15);
+ connRef349->setSourceEndpoint(srcPt349);
+ ConnEnd dstPt349(Point(247.5, 1885.42), 8);
+ connRef349->setDestEndpoint(dstPt349);
+ connRef349->setRoutingType((ConnType)2);
+
+ ConnRef *connRef350 = new ConnRef(router, 350);
+ ConnEnd srcPt350(Point(1329.5, 1466.92), 15);
+ connRef350->setSourceEndpoint(srcPt350);
+ ConnEnd dstPt350(Point(862.5, 1474.42), 8);
+ connRef350->setDestEndpoint(dstPt350);
+ connRef350->setRoutingType((ConnType)2);
+
+ ConnRef *connRef351 = new ConnRef(router, 351);
+ ConnEnd srcPt351(Point(1574.5, 2008.92), 15);
+ connRef351->setSourceEndpoint(srcPt351);
+ ConnEnd dstPt351(Point(1577, 2138.92), 1);
+ connRef351->setDestEndpoint(dstPt351);
+ connRef351->setRoutingType((ConnType)2);
+#endif
+
+ router->processTransaction();
+ router->outputDiagram("output/finalSegmentNudging3");
+
+ bool optimisedForConnectorType = false;
+ int crossings = router->existsCrossings(optimisedForConnectorType);
+
+ delete router;
+ return (crossings > 0) ? 1 : 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/forwardFlowingConnectors01.cpp b/src/3rdparty/adaptagrams/libavoid/tests/forwardFlowingConnectors01.cpp
new file mode 100644
index 0000000..b2fa17f
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/forwardFlowingConnectors01.cpp
@@ -0,0 +1,380 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingParameter((RoutingParameter)0, 10);
+ router->setRoutingParameter((RoutingParameter)1, 0);
+ router->setRoutingParameter((RoutingParameter)2, 1000);
+ router->setRoutingParameter((RoutingParameter)3, 4000);
+ router->setRoutingParameter((RoutingParameter)4, 0);
+ router->setRoutingParameter((RoutingParameter)5, 100);
+ router->setRoutingParameter((RoutingParameter)6, 1);
+ router->setRoutingParameter((RoutingParameter)7, 10);
+ router->setRoutingParameter(reverseDirectionPenalty, 500);
+ router->setRoutingOption((RoutingOption)0, false);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, false);
+ router->setRoutingOption((RoutingOption)3, false);
+ router->setRoutingOption((RoutingOption)4, true);
+ router->setRoutingOption((RoutingOption)5, true);
+ Polygon polygon;
+ ConnRef *connRef = nullptr;
+ ConnEnd srcPt;
+ ConnEnd dstPt;
+ PolyLine newRoute;
+ // shapeRef1
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(0, 0);
+ polygon.ps[1] = Point(0, 0);
+ polygon.ps[2] = Point(0, 0);
+ polygon.ps[3] = Point(0, 0);
+ new ShapeRef(router, polygon, 1);
+
+ // shapeRef2
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(0, 0);
+ polygon.ps[1] = Point(0, 0);
+ polygon.ps[2] = Point(0, 0);
+ polygon.ps[3] = Point(0, 0);
+ new ShapeRef(router, polygon, 2);
+
+ // shapeRef3
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(0, 0);
+ polygon.ps[1] = Point(0, 0);
+ polygon.ps[2] = Point(0, 0);
+ polygon.ps[3] = Point(0, 0);
+ new ShapeRef(router, polygon, 3);
+
+ // shapeRef4
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(0, 0);
+ polygon.ps[1] = Point(0, 0);
+ polygon.ps[2] = Point(0, 0);
+ polygon.ps[3] = Point(0, 0);
+ new ShapeRef(router, polygon, 4);
+
+ // shapeRef5
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(501, 345);
+ polygon.ps[1] = Point(501, 404);
+ polygon.ps[2] = Point(421, 404);
+ polygon.ps[3] = Point(421, 345);
+ ShapeRef *shapeRef5 = new ShapeRef(router, polygon, 5);
+ new ShapeConnectionPin(shapeRef5, 5, 1, 0.652542, true, 0, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef5, 6, 0, 0.79096, true, 0, (ConnDirFlags) 4);
+ new ShapeConnectionPin(shapeRef5, 7, 0, 0.514124, true, 0, (ConnDirFlags) 4);
+
+ // shapeRef6
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(94, 251.5);
+ polygon.ps[1] = Point(94, 315.5);
+ polygon.ps[2] = Point(12, 315.5);
+ polygon.ps[3] = Point(12, 251.5);
+ ShapeRef *shapeRef6 = new ShapeRef(router, polygon, 6);
+ new ShapeConnectionPin(shapeRef6, 8, 1, 0.640625, true, 0, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef6, 9, 0, 0.640625, true, 0, (ConnDirFlags) 4);
+
+ // shapeRef7
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(634.366, 262);
+ polygon.ps[1] = Point(634.366, 305);
+ polygon.ps[2] = Point(416.366, 305);
+ polygon.ps[3] = Point(416.366, 262);
+ ShapeRef *shapeRef7 = new ShapeRef(router, polygon, 7);
+ new ShapeConnectionPin(shapeRef7, 10, 1, 0.709302, true, 0, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef7, 11, 0, 0.709302, true, 0, (ConnDirFlags) 4);
+
+ // shapeRef8
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(324, 147.167);
+ polygon.ps[1] = Point(324, 206.167);
+ polygon.ps[2] = Point(236, 206.167);
+ polygon.ps[3] = Point(236, 147.167);
+ ShapeRef *shapeRef8 = new ShapeRef(router, polygon, 8);
+ new ShapeConnectionPin(shapeRef8, 12, 1, 0.652542, true, 0, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef8, 13, 0, 0.79096, true, 0, (ConnDirFlags) 4);
+ new ShapeConnectionPin(shapeRef8, 14, 0, 0.514124, true, 0, (ConnDirFlags) 4);
+
+ // shapeRef9
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(816, 353.167);
+ polygon.ps[1] = Point(816, 412.167);
+ polygon.ps[2] = Point(735, 412.167);
+ polygon.ps[3] = Point(735, 353.167);
+ ShapeRef *shapeRef9 = new ShapeRef(router, polygon, 9);
+ new ShapeConnectionPin(shapeRef9, 15, 1, 0.514124, true, 0, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef9, 16, 1, 0.79096, true, 0, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef9, 17, 0, 0.79096, true, 0, (ConnDirFlags) 4);
+ new ShapeConnectionPin(shapeRef9, 18, 0, 0.514124, true, 0, (ConnDirFlags) 4);
+
+ // shapeRef10
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(981, 263.833);
+ polygon.ps[1] = Point(981, 321.833);
+ polygon.ps[2] = Point(828, 321.833);
+ polygon.ps[3] = Point(828, 263.833);
+ ShapeRef *shapeRef10 = new ShapeRef(router, polygon, 10);
+ new ShapeConnectionPin(shapeRef10, 19, 0, 0.655172, true, 0, (ConnDirFlags) 4);
+
+ // shapeRef11
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1011.49, 361.833);
+ polygon.ps[1] = Point(1011.49, 419.833);
+ polygon.ps[2] = Point(834.489, 419.833);
+ polygon.ps[3] = Point(834.489, 361.833);
+ ShapeRef *shapeRef11 = new ShapeRef(router, polygon, 11);
+ new ShapeConnectionPin(shapeRef11, 20, 0, 0.655172, true, 0, (ConnDirFlags) 4);
+
+ // shapeRef12
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(511, 155.333);
+ polygon.ps[1] = Point(511, 214.333);
+ polygon.ps[2] = Point(422, 214.333);
+ polygon.ps[3] = Point(422, 155.333);
+ ShapeRef *shapeRef12 = new ShapeRef(router, polygon, 12);
+ new ShapeConnectionPin(shapeRef12, 21, 1, 0.514124, true, 0, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef12, 22, 1, 0.79096, true, 0, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef12, 23, 0, 0.79096, true, 0, (ConnDirFlags) 4);
+ new ShapeConnectionPin(shapeRef12, 24, 0, 0.514124, true, 0, (ConnDirFlags) 4);
+
+ // shapeRef13
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(690, 66);
+ polygon.ps[1] = Point(690, 124);
+ polygon.ps[2] = Point(523, 124);
+ polygon.ps[3] = Point(523, 66);
+ ShapeRef *shapeRef13 = new ShapeRef(router, polygon, 13);
+ new ShapeConnectionPin(shapeRef13, 25, 0, 0.655172, true, 0, (ConnDirFlags) 4);
+
+ // shapeRef14
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(720.212, 164);
+ polygon.ps[1] = Point(720.212, 222);
+ polygon.ps[2] = Point(529.212, 222);
+ polygon.ps[3] = Point(529.212, 164);
+ ShapeRef *shapeRef14 = new ShapeRef(router, polygon, 14);
+ new ShapeConnectionPin(shapeRef14, 26, 0, 0.655172, true, 0, (ConnDirFlags) 4);
+
+ // shapeRef15
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(217, 336.833);
+ polygon.ps[1] = Point(217, 395.833);
+ polygon.ps[2] = Point(98, 395.833);
+ polygon.ps[3] = Point(98, 336.833);
+ ShapeRef *shapeRef15 = new ShapeRef(router, polygon, 15);
+ new ShapeConnectionPin(shapeRef15, 27, 1, 0.652542, true, 0, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef15, 28, 0, 0.652542, true, 0, (ConnDirFlags) 4);
+
+ // shapeRef16
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(413, 147.167);
+ polygon.ps[1] = Point(413, 206.167);
+ polygon.ps[2] = Point(336, 206.167);
+ polygon.ps[3] = Point(336, 147.167);
+ ShapeRef *shapeRef16 = new ShapeRef(router, polygon, 16);
+ new ShapeConnectionPin(shapeRef16, 29, 1, 0.652542, true, 0, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef16, 30, 0, 0.652542, true, 0, (ConnDirFlags) 4);
+
+ // shapeRef17
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(306, 336.833);
+ polygon.ps[1] = Point(306, 395.833);
+ polygon.ps[2] = Point(229, 395.833);
+ polygon.ps[3] = Point(229, 336.833);
+ ShapeRef *shapeRef17 = new ShapeRef(router, polygon, 17);
+ new ShapeConnectionPin(shapeRef17, 31, 1, 0.652542, true, 0, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef17, 32, 0, 0.652542, true, 0, (ConnDirFlags) 4);
+
+ // shapeRef18
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(175, 139);
+ polygon.ps[1] = Point(175, 198);
+ polygon.ps[2] = Point(98, 198);
+ polygon.ps[3] = Point(98, 139);
+ ShapeRef *shapeRef18 = new ShapeRef(router, polygon, 18);
+ new ShapeConnectionPin(shapeRef18, 33, 1, 0.652542, true, 0, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef18, 34, 0, 0.652542, true, 0, (ConnDirFlags) 4);
+
+ // shapeRef19
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(409, 399.333);
+ polygon.ps[1] = Point(409, 458.333);
+ polygon.ps[2] = Point(298, 458.333);
+ polygon.ps[3] = Point(298, 399.333);
+ ShapeRef *shapeRef19 = new ShapeRef(router, polygon, 19);
+ new ShapeConnectionPin(shapeRef19, 35, 1, 0.652542, true, 0, (ConnDirFlags) 8);
+
+ // shapeRef20
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(224, 40);
+ polygon.ps[1] = Point(224, 99);
+ polygon.ps[2] = Point(106, 99);
+ polygon.ps[3] = Point(106, 40);
+ ShapeRef *shapeRef20 = new ShapeRef(router, polygon, 20);
+ new ShapeConnectionPin(shapeRef20, 36, 1, 0.652542, true, 0, (ConnDirFlags) 8);
+
+ // shapeRef21
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(604, 345);
+ polygon.ps[1] = Point(604, 404);
+ polygon.ps[2] = Point(513, 404);
+ polygon.ps[3] = Point(513, 345);
+ ShapeRef *shapeRef21 = new ShapeRef(router, polygon, 21);
+ new ShapeConnectionPin(shapeRef21, 37, 1, 0.652542, true, 0, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef21, 38, 0, 0.652542, true, 0, (ConnDirFlags) 4);
+
+ // connRef1
+ connRef = new ConnRef(router, 1);
+ srcPt = ConnEnd(shapeRef5, 5);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef21, 38);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2
+ connRef = new ConnRef(router, 2);
+ srcPt = ConnEnd(shapeRef6, 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef18, 34);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3
+ connRef = new ConnRef(router, 3);
+ srcPt = ConnEnd(shapeRef6, 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef15, 28);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef4
+ connRef = new ConnRef(router, 4);
+ srcPt = ConnEnd(shapeRef6, 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef12, 23);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef5
+ connRef = new ConnRef(router, 5);
+ srcPt = ConnEnd(shapeRef6, 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef7, 11);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef6
+ connRef = new ConnRef(router, 6);
+ srcPt = ConnEnd(shapeRef7, 10);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef9, 17);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ ConnRef *connector6 = connRef;
+
+ // connRef7
+ connRef = new ConnRef(router, 7);
+ srcPt = ConnEnd(shapeRef8, 12);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef16, 30);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef8
+ connRef = new ConnRef(router, 8);
+ srcPt = ConnEnd(shapeRef9, 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef10, 19);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef9
+ connRef = new ConnRef(router, 9);
+ srcPt = ConnEnd(shapeRef9, 16);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef11, 20);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef10
+ connRef = new ConnRef(router, 10);
+ srcPt = ConnEnd(shapeRef12, 21);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef13, 25);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef11
+ connRef = new ConnRef(router, 11);
+ srcPt = ConnEnd(shapeRef12, 22);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef14, 26);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef12
+ connRef = new ConnRef(router, 12);
+ srcPt = ConnEnd(shapeRef15, 27);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef17, 32);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef13
+ connRef = new ConnRef(router, 13);
+ srcPt = ConnEnd(shapeRef16, 29);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef12, 24);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef14
+ connRef = new ConnRef(router, 14);
+ srcPt = ConnEnd(shapeRef17, 31);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef5, 7);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef15
+ connRef = new ConnRef(router, 15);
+ srcPt = ConnEnd(shapeRef18, 33);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef8, 14);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef16
+ connRef = new ConnRef(router, 16);
+ srcPt = ConnEnd(shapeRef19, 35);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef5, 7);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef17
+ connRef = new ConnRef(router, 17);
+ srcPt = ConnEnd(shapeRef20, 36);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef8, 14);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef18
+ connRef = new ConnRef(router, 18);
+ srcPt = ConnEnd(shapeRef21, 37);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef9, 18);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ // Test that connector 6 has three segments and doesnt loop right
+ // around the shapes on the right due to the crossing penalty.
+ bool suceeds = (connector6->displayRoute().size() == 4);
+
+ //router->outputDiagram("output/forwardFlowingConnectors01");
+ delete router;
+ return (suceeds ? 0 : 1);
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/freeFloatingDirection01.cpp b/src/3rdparty/adaptagrams/libavoid/tests/freeFloatingDirection01.cpp
new file mode 100644
index 0000000..56e1773
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/freeFloatingDirection01.cpp
@@ -0,0 +1,3321 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 0);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(348, 1286.05);
+ poly2.ps[1] = Point(348, 1304.05);
+ poly2.ps[2] = Point(330, 1304.05);
+ poly2.ps[3] = Point(330, 1286.05);
+ new ShapeRef(router, poly2, 2);
+
+ Polygon poly153(4);
+ poly153.ps[0] = Point(495, 1032.05);
+ poly153.ps[1] = Point(495, 1070.05);
+ poly153.ps[2] = Point(440, 1070.05);
+ poly153.ps[3] = Point(440, 1032.05);
+ new ShapeRef(router, poly153, 153);
+
+ Polygon poly154(4);
+ poly154.ps[0] = Point(613, 959.545);
+ poly154.ps[1] = Point(613, 997.545);
+ poly154.ps[2] = Point(559, 997.545);
+ poly154.ps[3] = Point(559, 959.545);
+ new ShapeRef(router, poly154, 154);
+
+ Polygon poly155(4);
+ poly155.ps[0] = Point(596, 1134.05);
+ poly155.ps[1] = Point(596, 1172.05);
+ poly155.ps[2] = Point(542, 1172.05);
+ poly155.ps[3] = Point(542, 1134.05);
+ new ShapeRef(router, poly155, 155);
+
+ Polygon poly156(4);
+ poly156.ps[0] = Point(762, 377);
+ poly156.ps[1] = Point(762, 415);
+ poly156.ps[2] = Point(708, 415);
+ poly156.ps[3] = Point(708, 377);
+ new ShapeRef(router, poly156, 156);
+
+ Polygon poly157(4);
+ poly157.ps[0] = Point(888, 377);
+ poly157.ps[1] = Point(888, 415);
+ poly157.ps[2] = Point(834, 415);
+ poly157.ps[3] = Point(834, 377);
+ new ShapeRef(router, poly157, 157);
+
+ Polygon poly158(4);
+ poly158.ps[0] = Point(545, 515.545);
+ poly158.ps[1] = Point(545, 553.545);
+ poly158.ps[2] = Point(491, 553.545);
+ poly158.ps[3] = Point(491, 515.545);
+ new ShapeRef(router, poly158, 158);
+
+ Polygon poly159(4);
+ poly159.ps[0] = Point(819.5, 753.545);
+ poly159.ps[1] = Point(819.5, 791.545);
+ poly159.ps[2] = Point(765.5, 791.545);
+ poly159.ps[3] = Point(765.5, 753.545);
+ new ShapeRef(router, poly159, 159);
+
+ Polygon poly160(4);
+ poly160.ps[0] = Point(824, 959.545);
+ poly160.ps[1] = Point(824, 997.545);
+ poly160.ps[2] = Point(770, 997.545);
+ poly160.ps[3] = Point(770, 959.545);
+ new ShapeRef(router, poly160, 160);
+
+ Polygon poly161(4);
+ poly161.ps[0] = Point(868, 1104.55);
+ poly161.ps[1] = Point(868, 1142.55);
+ poly161.ps[2] = Point(814, 1142.55);
+ poly161.ps[3] = Point(814, 1104.55);
+ new ShapeRef(router, poly161, 161);
+
+ Polygon poly162(4);
+ poly162.ps[0] = Point(819.5, 617.545);
+ poly162.ps[1] = Point(819.5, 655.545);
+ poly162.ps[2] = Point(765.5, 655.545);
+ poly162.ps[3] = Point(765.5, 617.545);
+ new ShapeRef(router, poly162, 162);
+
+ Polygon poly163(4);
+ poly163.ps[0] = Point(826, 1156.55);
+ poly163.ps[1] = Point(826, 1194.55);
+ poly163.ps[2] = Point(772, 1194.55);
+ poly163.ps[3] = Point(772, 1156.55);
+ new ShapeRef(router, poly163, 163);
+
+ Polygon poly164(4);
+ poly164.ps[0] = Point(897, 1391.71);
+ poly164.ps[1] = Point(897, 1429.71);
+ poly164.ps[2] = Point(843, 1429.71);
+ poly164.ps[3] = Point(843, 1391.71);
+ new ShapeRef(router, poly164, 164);
+
+ Polygon poly165(4);
+ poly165.ps[0] = Point(781, 1524.71);
+ poly165.ps[1] = Point(781, 1562.71);
+ poly165.ps[2] = Point(727, 1562.71);
+ poly165.ps[3] = Point(727, 1524.71);
+ new ShapeRef(router, poly165, 165);
+
+ Polygon poly166(4);
+ poly166.ps[0] = Point(853, 1657.71);
+ poly166.ps[1] = Point(853, 1695.71);
+ poly166.ps[2] = Point(799, 1695.71);
+ poly166.ps[3] = Point(799, 1657.71);
+ new ShapeRef(router, poly166, 166);
+
+ Polygon poly167(4);
+ poly167.ps[0] = Point(1014, 241);
+ poly167.ps[1] = Point(1014, 279);
+ poly167.ps[2] = Point(960, 279);
+ poly167.ps[3] = Point(960, 241);
+ new ShapeRef(router, poly167, 167);
+
+ Polygon poly168(4);
+ poly168.ps[0] = Point(1014, 325);
+ poly168.ps[1] = Point(1014, 363);
+ poly168.ps[2] = Point(960, 363);
+ poly168.ps[3] = Point(960, 325);
+ new ShapeRef(router, poly168, 168);
+
+ Polygon poly169(4);
+ poly169.ps[0] = Point(1014, 660.045);
+ poly169.ps[1] = Point(1014, 698.045);
+ poly169.ps[2] = Point(960, 698.045);
+ poly169.ps[3] = Point(960, 660.045);
+ new ShapeRef(router, poly169, 169);
+
+ Polygon poly170(4);
+ poly170.ps[0] = Point(1014, 913.545);
+ poly170.ps[1] = Point(1014, 951.545);
+ poly170.ps[2] = Point(960, 951.545);
+ poly170.ps[3] = Point(960, 913.545);
+ new ShapeRef(router, poly170, 170);
+
+ Polygon poly171(4);
+ poly171.ps[0] = Point(1012, 46);
+ poly171.ps[1] = Point(1012, 84);
+ poly171.ps[2] = Point(958, 84);
+ poly171.ps[3] = Point(958, 46);
+ new ShapeRef(router, poly171, 171);
+
+ Polygon poly172(4);
+ poly172.ps[0] = Point(1017, 377);
+ poly172.ps[1] = Point(1017, 415);
+ poly172.ps[2] = Point(963, 415);
+ poly172.ps[3] = Point(963, 377);
+ new ShapeRef(router, poly172, 172);
+
+ Polygon poly173(4);
+ poly173.ps[0] = Point(1199, 377);
+ poly173.ps[1] = Point(1199, 415);
+ poly173.ps[2] = Point(1145, 415);
+ poly173.ps[3] = Point(1145, 377);
+ new ShapeRef(router, poly173, 173);
+
+ Polygon poly174(4);
+ poly174.ps[0] = Point(1179, 691.379);
+ poly174.ps[1] = Point(1179, 729.379);
+ poly174.ps[2] = Point(1125, 729.379);
+ poly174.ps[3] = Point(1125, 691.379);
+ new ShapeRef(router, poly174, 174);
+
+ Polygon poly130(4);
+ poly130.ps[0] = Point(119, 565.545);
+ poly130.ps[1] = Point(119, 603.545);
+ poly130.ps[2] = Point(81, 603.545);
+ poly130.ps[3] = Point(81, 565.545);
+ new ShapeRef(router, poly130, 130);
+
+ Polygon poly131(4);
+ poly131.ps[0] = Point(239, 565.545);
+ poly131.ps[1] = Point(239, 603.545);
+ poly131.ps[2] = Point(201, 603.545);
+ poly131.ps[3] = Point(201, 565.545);
+ new ShapeRef(router, poly131, 131);
+
+ Polygon poly132(4);
+ poly132.ps[0] = Point(1517.53, 1758.71);
+ poly132.ps[1] = Point(1517.53, 1796.71);
+ poly132.ps[2] = Point(1479.53, 1796.71);
+ poly132.ps[3] = Point(1479.53, 1758.71);
+ new ShapeRef(router, poly132, 132);
+
+ Polygon poly133(4);
+ poly133.ps[0] = Point(1627.2, 1758.71);
+ poly133.ps[1] = Point(1627.2, 1796.71);
+ poly133.ps[2] = Point(1589.2, 1796.71);
+ poly133.ps[3] = Point(1589.2, 1758.71);
+ new ShapeRef(router, poly133, 133);
+
+ Polygon poly134(4);
+ poly134.ps[0] = Point(1364, 1758.71);
+ poly134.ps[1] = Point(1364, 1796.71);
+ poly134.ps[2] = Point(1326, 1796.71);
+ poly134.ps[3] = Point(1326, 1758.71);
+ new ShapeRef(router, poly134, 134);
+
+ Polygon poly135(4);
+ poly135.ps[0] = Point(1238, 1758.71);
+ poly135.ps[1] = Point(1238, 1796.71);
+ poly135.ps[2] = Point(1200, 1796.71);
+ poly135.ps[3] = Point(1200, 1758.71);
+ new ShapeRef(router, poly135, 135);
+
+ Polygon poly136(4);
+ poly136.ps[0] = Point(1153, 1758.71);
+ poly136.ps[1] = Point(1153, 1796.71);
+ poly136.ps[2] = Point(1115, 1796.71);
+ poly136.ps[3] = Point(1115, 1758.71);
+ new ShapeRef(router, poly136, 136);
+
+ Polygon poly137(4);
+ poly137.ps[0] = Point(1563.49, 1033.05);
+ poly137.ps[1] = Point(1563.49, 1071.05);
+ poly137.ps[2] = Point(1525.49, 1071.05);
+ poly137.ps[3] = Point(1525.49, 1033.05);
+ new ShapeRef(router, poly137, 137);
+
+ Polygon poly138(4);
+ poly138.ps[0] = Point(1563.49, 1635.71);
+ poly138.ps[1] = Point(1563.49, 1673.71);
+ poly138.ps[2] = Point(1525.49, 1673.71);
+ poly138.ps[3] = Point(1525.49, 1635.71);
+ new ShapeRef(router, poly138, 138);
+
+ Polygon poly139(4);
+ poly139.ps[0] = Point(648, 565.545);
+ poly139.ps[1] = Point(648, 603.545);
+ poly139.ps[2] = Point(610, 603.545);
+ poly139.ps[3] = Point(610, 565.545);
+ new ShapeRef(router, poly139, 139);
+
+ Polygon poly140(4);
+ poly140.ps[0] = Point(665, 1208.55);
+ poly140.ps[1] = Point(665, 1246.55);
+ poly140.ps[2] = Point(627, 1246.55);
+ poly140.ps[3] = Point(627, 1208.55);
+ new ShapeRef(router, poly140, 140);
+
+ Polygon poly141(4);
+ poly141.ps[0] = Point(777, 1328.05);
+ poly141.ps[1] = Point(777, 1386.05);
+ poly141.ps[2] = Point(466, 1386.05);
+ poly141.ps[3] = Point(466, 1328.05);
+ new ShapeRef(router, poly141, 141);
+
+ Polygon poly142(4);
+ poly142.ps[0] = Point(892, 305);
+ poly142.ps[1] = Point(892, 363);
+ poly142.ps[2] = Point(581, 363);
+ poly142.ps[3] = Point(581, 305);
+ new ShapeRef(router, poly142, 142);
+
+ Polygon poly143(4);
+ poly143.ps[0] = Point(366, 1226.05);
+ poly143.ps[1] = Point(366, 1264.05);
+ poly143.ps[2] = Point(312, 1264.05);
+ poly143.ps[3] = Point(312, 1226.05);
+ new ShapeRef(router, poly143, 143);
+
+ Polygon poly144(4);
+ poly144.ps[0] = Point(366, 1134.05);
+ poly144.ps[1] = Point(366, 1172.05);
+ poly144.ps[2] = Point(312, 1172.05);
+ poly144.ps[3] = Point(312, 1134.05);
+ new ShapeRef(router, poly144, 144);
+
+ Polygon poly145(4);
+ poly145.ps[0] = Point(100, 1130.05);
+ poly145.ps[1] = Point(100, 1168.05);
+ poly145.ps[2] = Point(46, 1168.05);
+ poly145.ps[3] = Point(46, 1130.05);
+ new ShapeRef(router, poly145, 145);
+
+ Polygon poly146(4);
+ poly146.ps[0] = Point(1497.2, 669.545);
+ poly146.ps[1] = Point(1497.2, 707.545);
+ poly146.ps[2] = Point(1443.2, 707.545);
+ poly146.ps[3] = Point(1443.2, 669.545);
+ new ShapeRef(router, poly146, 146);
+
+ Polygon poly147(4);
+ poly147.ps[0] = Point(545, 377);
+ poly147.ps[1] = Point(545, 415);
+ poly147.ps[2] = Point(491, 415);
+ poly147.ps[3] = Point(491, 377);
+ new ShapeRef(router, poly147, 147);
+
+ Polygon poly148(4);
+ poly148.ps[0] = Point(361.2, 617.545);
+ poly148.ps[1] = Point(361.2, 655.545);
+ poly148.ps[2] = Point(307.2, 655.545);
+ poly148.ps[3] = Point(307.2, 617.545);
+ new ShapeRef(router, poly148, 148);
+
+ Polygon poly149(4);
+ poly149.ps[0] = Point(218, 1080.05);
+ poly149.ps[1] = Point(218, 1118.05);
+ poly149.ps[2] = Point(164, 1118.05);
+ poly149.ps[3] = Point(164, 1080.05);
+ new ShapeRef(router, poly149, 149);
+
+ Polygon poly150(4);
+ poly150.ps[0] = Point(423.2, 751.545);
+ poly150.ps[1] = Point(423.2, 789.545);
+ poly150.ps[2] = Point(369.2, 789.545);
+ poly150.ps[3] = Point(369.2, 751.545);
+ new ShapeRef(router, poly150, 150);
+
+ Polygon poly151(4);
+ poly151.ps[0] = Point(423.2, 803.545);
+ poly151.ps[1] = Point(423.2, 841.545);
+ poly151.ps[2] = Point(369.2, 841.545);
+ poly151.ps[3] = Point(369.2, 803.545);
+ new ShapeRef(router, poly151, 151);
+
+ Polygon poly152(4);
+ poly152.ps[0] = Point(423.2, 855.545);
+ poly152.ps[1] = Point(423.2, 893.545);
+ poly152.ps[2] = Point(369.2, 893.545);
+ poly152.ps[3] = Point(369.2, 855.545);
+ new ShapeRef(router, poly152, 152);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(348, 1194.05);
+ poly3.ps[1] = Point(348, 1212.05);
+ poly3.ps[2] = Point(330, 1212.05);
+ poly3.ps[3] = Point(330, 1194.05);
+ new ShapeRef(router, poly3, 3);
+
+ Polygon poly198(4);
+ poly198.ps[0] = Point(1291, 1134.05);
+ poly198.ps[1] = Point(1291, 1172.05);
+ poly198.ps[2] = Point(1237, 1172.05);
+ poly198.ps[3] = Point(1237, 1134.05);
+ new ShapeRef(router, poly198, 198);
+
+ Polygon poly199(4);
+ poly199.ps[0] = Point(1700.2, 1287.71);
+ poly199.ps[1] = Point(1700.2, 1325.71);
+ poly199.ps[2] = Point(1646.2, 1325.71);
+ poly199.ps[3] = Point(1646.2, 1287.71);
+ new ShapeRef(router, poly199, 199);
+
+ Polygon poly200(4);
+ poly200.ps[0] = Point(586.5, 855.545);
+ poly200.ps[1] = Point(586.5, 893.545);
+ poly200.ps[2] = Point(532.5, 893.545);
+ poly200.ps[3] = Point(532.5, 855.545);
+ new ShapeRef(router, poly200, 200);
+
+ Polygon poly201(4);
+ poly201.ps[0] = Point(787, 855.545);
+ poly201.ps[1] = Point(787, 893.545);
+ poly201.ps[2] = Point(733, 893.545);
+ poly201.ps[3] = Point(733, 855.545);
+ new ShapeRef(router, poly201, 201);
+
+ Polygon poly202(4);
+ poly202.ps[0] = Point(496, 907.545);
+ poly202.ps[1] = Point(496, 945.545);
+ poly202.ps[2] = Point(442, 945.545);
+ poly202.ps[3] = Point(442, 907.545);
+ new ShapeRef(router, poly202, 202);
+
+ Polygon poly203(4);
+ poly203.ps[0] = Point(1223, 1088.21);
+ poly203.ps[1] = Point(1223, 1126.21);
+ poly203.ps[2] = Point(1169, 1126.21);
+ poly203.ps[3] = Point(1169, 1088.21);
+ new ShapeRef(router, poly203, 203);
+
+ Polygon poly204(4);
+ poly204.ps[0] = Point(1841.2, 1593.71);
+ poly204.ps[1] = Point(1841.2, 1631.71);
+ poly204.ps[2] = Point(1787.2, 1631.71);
+ poly204.ps[3] = Point(1787.2, 1593.71);
+ new ShapeRef(router, poly204, 204);
+
+ Polygon poly205(4);
+ poly205.ps[0] = Point(658, 1260.55);
+ poly205.ps[1] = Point(658, 1298.55);
+ poly205.ps[2] = Point(604, 1298.55);
+ poly205.ps[3] = Point(604, 1260.55);
+ new ShapeRef(router, poly205, 205);
+
+ Polygon poly206(4);
+ poly206.ps[0] = Point(545, 980.045);
+ poly206.ps[1] = Point(545, 1018.05);
+ poly206.ps[2] = Point(491, 1018.05);
+ poly206.ps[3] = Point(491, 980.045);
+ new ShapeRef(router, poly206, 206);
+
+ Polygon poly207(4);
+ poly207.ps[0] = Point(357, 565.545);
+ poly207.ps[1] = Point(357, 603.545);
+ poly207.ps[2] = Point(303, 603.545);
+ poly207.ps[3] = Point(303, 565.545);
+ new ShapeRef(router, poly207, 207);
+
+ Polygon poly208(4);
+ poly208.ps[0] = Point(187, 515.545);
+ poly208.ps[1] = Point(187, 553.545);
+ poly208.ps[2] = Point(133, 553.545);
+ poly208.ps[3] = Point(133, 515.545);
+ new ShapeRef(router, poly208, 208);
+
+ Polygon poly209(4);
+ poly209.ps[0] = Point(1025.8, 976.045);
+ poly209.ps[1] = Point(1025.8, 1014.05);
+ poly209.ps[2] = Point(971.8, 1014.05);
+ poly209.ps[3] = Point(971.8, 976.045);
+ new ShapeRef(router, poly209, 209);
+
+ Polygon poly210(4);
+ poly210.ps[0] = Point(1654.2, 1339.71);
+ poly210.ps[1] = Point(1654.2, 1377.71);
+ poly210.ps[2] = Point(1600.2, 1377.71);
+ poly210.ps[3] = Point(1600.2, 1339.71);
+ new ShapeRef(router, poly210, 210);
+
+ Polygon poly211(4);
+ poly211.ps[0] = Point(1466.53, 1339.71);
+ poly211.ps[1] = Point(1466.53, 1377.71);
+ poly211.ps[2] = Point(1412.53, 1377.71);
+ poly211.ps[3] = Point(1412.53, 1339.71);
+ new ShapeRef(router, poly211, 211);
+
+ Polygon poly212(4);
+ poly212.ps[0] = Point(1633.49, 1593.71);
+ poly212.ps[1] = Point(1633.49, 1631.71);
+ poly212.ps[2] = Point(1579.49, 1631.71);
+ poly212.ps[3] = Point(1579.49, 1593.71);
+ new ShapeRef(router, poly212, 212);
+
+ Polygon poly213(4);
+ poly213.ps[0] = Point(1429.2, 840.545);
+ poly213.ps[1] = Point(1429.2, 878.545);
+ poly213.ps[2] = Point(1375.2, 878.545);
+ poly213.ps[3] = Point(1375.2, 840.545);
+ new ShapeRef(router, poly213, 213);
+
+ Polygon poly214(4);
+ poly214.ps[0] = Point(1633.49, 975.545);
+ poly214.ps[1] = Point(1633.49, 1013.55);
+ poly214.ps[2] = Point(1579.49, 1013.55);
+ poly214.ps[3] = Point(1579.49, 975.545);
+ new ShapeRef(router, poly214, 214);
+
+ Polygon poly215(4);
+ poly215.ps[0] = Point(1505.53, 925.545);
+ poly215.ps[1] = Point(1505.53, 963.545);
+ poly215.ps[2] = Point(1451.53, 963.545);
+ poly215.ps[3] = Point(1451.53, 925.545);
+ new ShapeRef(router, poly215, 215);
+
+ Polygon poly216(4);
+ poly216.ps[0] = Point(1099.8, 1595.71);
+ poly216.ps[1] = Point(1099.8, 1633.71);
+ poly216.ps[2] = Point(1041.8, 1633.71);
+ poly216.ps[3] = Point(1041.8, 1595.71);
+ new ShapeRef(router, poly216, 216);
+
+ Polygon poly217(4);
+ poly217.ps[0] = Point(1207, 325);
+ poly217.ps[1] = Point(1207, 363);
+ poly217.ps[2] = Point(1149, 363);
+ poly217.ps[3] = Point(1149, 325);
+ new ShapeRef(router, poly217, 217);
+
+ Polygon poly218(4);
+ poly218.ps[0] = Point(1259, 305);
+ poly218.ps[1] = Point(1259, 363);
+ poly218.ps[2] = Point(1221, 363);
+ poly218.ps[3] = Point(1221, 305);
+ new ShapeRef(router, poly218, 218);
+
+ Polygon poly219(4);
+ poly219.ps[0] = Point(342, 463.545);
+ poly219.ps[1] = Point(342, 501.545);
+ poly219.ps[2] = Point(284, 501.545);
+ poly219.ps[3] = Point(284, 463.545);
+ new ShapeRef(router, poly219, 219);
+
+ Polygon poly220(4);
+ poly220.ps[0] = Point(1066.83, 731.462);
+ poly220.ps[1] = Point(1066.83, 789.462);
+ poly220.ps[2] = Point(1028.83, 789.462);
+ poly220.ps[3] = Point(1028.83, 731.462);
+ new ShapeRef(router, poly220, 220);
+
+ Polygon poly221(4);
+ poly221.ps[0] = Point(777, 1328.05);
+ poly221.ps[1] = Point(777, 1366.05);
+ poly221.ps[2] = Point(719, 1366.05);
+ poly221.ps[3] = Point(719, 1328.05);
+ new ShapeRef(router, poly221, 221);
+
+ Polygon poly222(4);
+ poly222.ps[0] = Point(892, 325);
+ poly222.ps[1] = Point(892, 363);
+ poly222.ps[2] = Point(834, 363);
+ poly222.ps[3] = Point(834, 325);
+ new ShapeRef(router, poly222, 222);
+
+ Polygon poly63(4);
+ poly63.ps[0] = Point(1620.2, 1297.71);
+ poly63.ps[1] = Point(1620.2, 1315.71);
+ poly63.ps[2] = Point(1602.2, 1315.71);
+ poly63.ps[3] = Point(1602.2, 1297.71);
+ new ShapeRef(router, poly63, 63);
+
+ Polygon poly64(4);
+ poly64.ps[0] = Point(630.5, 865.545);
+ poly64.ps[1] = Point(630.5, 883.545);
+ poly64.ps[2] = Point(612.5, 883.545);
+ poly64.ps[3] = Point(612.5, 865.545);
+ new ShapeRef(router, poly64, 64);
+
+ Polygon poly65(4);
+ poly65.ps[0] = Point(707, 865.545);
+ poly65.ps[1] = Point(707, 883.545);
+ poly65.ps[2] = Point(689, 883.545);
+ poly65.ps[3] = Point(689, 865.545);
+ new ShapeRef(router, poly65, 65);
+
+ Polygon poly66(4);
+ poly66.ps[0] = Point(416, 917.545);
+ poly66.ps[1] = Point(416, 935.545);
+ poly66.ps[2] = Point(398, 935.545);
+ poly66.ps[3] = Point(398, 917.545);
+ new ShapeRef(router, poly66, 66);
+
+ Polygon poly67(4);
+ poly67.ps[0] = Point(1143, 1098.21);
+ poly67.ps[1] = Point(1143, 1116.21);
+ poly67.ps[2] = Point(1125, 1116.21);
+ poly67.ps[3] = Point(1125, 1098.21);
+ new ShapeRef(router, poly67, 67);
+
+ Polygon poly68(4);
+ poly68.ps[0] = Point(1761.2, 1603.71);
+ poly68.ps[1] = Point(1761.2, 1621.71);
+ poly68.ps[2] = Point(1743.2, 1621.71);
+ poly68.ps[3] = Point(1743.2, 1603.71);
+ new ShapeRef(router, poly68, 68);
+
+ Polygon poly69(4);
+ poly69.ps[0] = Point(578, 1270.55);
+ poly69.ps[1] = Point(578, 1288.55);
+ poly69.ps[2] = Point(560, 1288.55);
+ poly69.ps[3] = Point(560, 1270.55);
+ new ShapeRef(router, poly69, 69);
+
+ Polygon poly70(4);
+ poly70.ps[0] = Point(527, 1040.05);
+ poly70.ps[1] = Point(527, 1058.05);
+ poly70.ps[2] = Point(509, 1058.05);
+ poly70.ps[3] = Point(509, 1040.05);
+ new ShapeRef(router, poly70, 70);
+
+ Polygon poly71(4);
+ poly71.ps[0] = Point(277, 575.545);
+ poly71.ps[1] = Point(277, 593.545);
+ poly71.ps[2] = Point(259, 593.545);
+ poly71.ps[3] = Point(259, 575.545);
+ new ShapeRef(router, poly71, 71);
+
+ Polygon poly72(4);
+ poly72.ps[0] = Point(169, 575.545);
+ poly72.ps[1] = Point(169, 593.545);
+ poly72.ps[2] = Point(151, 593.545);
+ poly72.ps[3] = Point(151, 575.545);
+ new ShapeRef(router, poly72, 72);
+
+ Polygon poly73(4);
+ poly73.ps[0] = Point(1007.8, 1036.05);
+ poly73.ps[1] = Point(1007.8, 1054.05);
+ poly73.ps[2] = Point(989.8, 1054.05);
+ poly73.ps[3] = Point(989.8, 1036.05);
+ new ShapeRef(router, poly73, 73);
+
+ Polygon poly74(4);
+ poly74.ps[0] = Point(1574.2, 1349.71);
+ poly74.ps[1] = Point(1574.2, 1367.71);
+ poly74.ps[2] = Point(1556.2, 1367.71);
+ poly74.ps[3] = Point(1556.2, 1349.71);
+ new ShapeRef(router, poly74, 74);
+
+ Polygon poly75(4);
+ poly75.ps[0] = Point(1510.53, 1349.71);
+ poly75.ps[1] = Point(1510.53, 1367.71);
+ poly75.ps[2] = Point(1492.53, 1367.71);
+ poly75.ps[3] = Point(1492.53, 1349.71);
+ new ShapeRef(router, poly75, 75);
+
+ Polygon poly76(4);
+ poly76.ps[0] = Point(1553.49, 1603.71);
+ poly76.ps[1] = Point(1553.49, 1621.71);
+ poly76.ps[2] = Point(1535.49, 1621.71);
+ poly76.ps[3] = Point(1535.49, 1603.71);
+ new ShapeRef(router, poly76, 76);
+
+ Polygon poly77(4);
+ poly77.ps[0] = Point(1349.2, 850.545);
+ poly77.ps[1] = Point(1349.2, 868.545);
+ poly77.ps[2] = Point(1331.2, 868.545);
+ poly77.ps[3] = Point(1331.2, 850.545);
+ new ShapeRef(router, poly77, 77);
+
+ Polygon poly78(4);
+ poly78.ps[0] = Point(1553.49, 985.545);
+ poly78.ps[1] = Point(1553.49, 1003.55);
+ poly78.ps[2] = Point(1535.49, 1003.55);
+ poly78.ps[3] = Point(1535.49, 985.545);
+ new ShapeRef(router, poly78, 78);
+
+ Polygon poly79(4);
+ poly79.ps[0] = Point(1487.53, 985.545);
+ poly79.ps[1] = Point(1487.53, 1003.55);
+ poly79.ps[2] = Point(1469.53, 1003.55);
+ poly79.ps[3] = Point(1469.53, 985.545);
+ new ShapeRef(router, poly79, 79);
+
+ Polygon poly80(4);
+ poly80.ps[0] = Point(119, 667.545);
+ poly80.ps[1] = Point(119, 705.545);
+ poly80.ps[2] = Point(81, 705.545);
+ poly80.ps[3] = Point(81, 667.545);
+ new ShapeRef(router, poly80, 80);
+
+ Polygon poly81(4);
+ poly81.ps[0] = Point(179, 803.545);
+ poly81.ps[1] = Point(179, 841.545);
+ poly81.ps[2] = Point(141, 841.545);
+ poly81.ps[3] = Point(141, 803.545);
+ new ShapeRef(router, poly81, 81);
+
+ Polygon poly82(4);
+ poly82.ps[0] = Point(394, 427);
+ poly82.ps[1] = Point(394, 465);
+ poly82.ps[2] = Point(356, 465);
+ poly82.ps[3] = Point(356, 427);
+ new ShapeRef(router, poly82, 82);
+
+ Polygon poly83(4);
+ poly83.ps[0] = Point(658.5, 427);
+ poly83.ps[1] = Point(658.5, 465);
+ poly83.ps[2] = Point(620.5, 465);
+ poly83.ps[3] = Point(620.5, 427);
+ new ShapeRef(router, poly83, 83);
+
+ Polygon poly84(4);
+ poly84.ps[0] = Point(820, 427);
+ poly84.ps[1] = Point(820, 465);
+ poly84.ps[2] = Point(782, 465);
+ poly84.ps[3] = Point(782, 427);
+ new ShapeRef(router, poly84, 84);
+
+ Polygon poly22(4);
+ poly22.ps[0] = Point(801.5, 677.545);
+ poly22.ps[1] = Point(801.5, 695.545);
+ poly22.ps[2] = Point(783.5, 695.545);
+ poly22.ps[3] = Point(783.5, 677.545);
+ new ShapeRef(router, poly22, 22);
+
+ Polygon poly23(4);
+ poly23.ps[0] = Point(870, 1166.55);
+ poly23.ps[1] = Point(870, 1184.55);
+ poly23.ps[2] = Point(852, 1184.55);
+ poly23.ps[3] = Point(852, 1166.55);
+ new ShapeRef(router, poly23, 23);
+
+ Polygon poly24(4);
+ poly24.ps[0] = Point(879, 1451.71);
+ poly24.ps[1] = Point(879, 1469.71);
+ poly24.ps[2] = Point(861, 1469.71);
+ poly24.ps[3] = Point(861, 1451.71);
+ new ShapeRef(router, poly24, 24);
+
+ Polygon poly25(4);
+ poly25.ps[0] = Point(763, 1584.71);
+ poly25.ps[1] = Point(763, 1602.71);
+ poly25.ps[2] = Point(745, 1602.71);
+ poly25.ps[3] = Point(745, 1584.71);
+ new ShapeRef(router, poly25, 25);
+
+ Polygon poly26(4);
+ poly26.ps[0] = Point(835, 1617.71);
+ poly26.ps[1] = Point(835, 1635.71);
+ poly26.ps[2] = Point(817, 1635.71);
+ poly26.ps[3] = Point(817, 1617.71);
+ new ShapeRef(router, poly26, 26);
+
+ Polygon poly27(4);
+ poly27.ps[0] = Point(934, 251);
+ poly27.ps[1] = Point(934, 269);
+ poly27.ps[2] = Point(916, 269);
+ poly27.ps[3] = Point(916, 251);
+ new ShapeRef(router, poly27, 27);
+
+ Polygon poly28(4);
+ poly28.ps[0] = Point(934, 335);
+ poly28.ps[1] = Point(934, 353);
+ poly28.ps[2] = Point(916, 353);
+ poly28.ps[3] = Point(916, 335);
+ new ShapeRef(router, poly28, 28);
+
+ Polygon poly29(4);
+ poly29.ps[0] = Point(934, 670.045);
+ poly29.ps[1] = Point(934, 688.045);
+ poly29.ps[2] = Point(916, 688.045);
+ poly29.ps[3] = Point(916, 670.045);
+ new ShapeRef(router, poly29, 29);
+
+ Polygon poly30(4);
+ poly30.ps[0] = Point(934, 923.545);
+ poly30.ps[1] = Point(934, 941.545);
+ poly30.ps[2] = Point(916, 941.545);
+ poly30.ps[3] = Point(916, 923.545);
+ new ShapeRef(router, poly30, 30);
+
+ Polygon poly31(4);
+ poly31.ps[0] = Point(994, 106);
+ poly31.ps[1] = Point(994, 124);
+ poly31.ps[2] = Point(976, 124);
+ poly31.ps[3] = Point(976, 106);
+ new ShapeRef(router, poly31, 31);
+
+ Polygon poly32(4);
+ poly32.ps[0] = Point(999, 437);
+ poly32.ps[1] = Point(999, 455);
+ poly32.ps[2] = Point(981, 455);
+ poly32.ps[3] = Point(981, 437);
+ new ShapeRef(router, poly32, 32);
+
+ Polygon poly33(4);
+ poly33.ps[0] = Point(1181, 437);
+ poly33.ps[1] = Point(1181, 455);
+ poly33.ps[2] = Point(1163, 455);
+ poly33.ps[3] = Point(1163, 437);
+ new ShapeRef(router, poly33, 33);
+
+ Polygon poly34(4);
+ poly34.ps[0] = Point(1161, 751.379);
+ poly34.ps[1] = Point(1161, 769.379);
+ poly34.ps[2] = Point(1143, 769.379);
+ poly34.ps[3] = Point(1143, 751.379);
+ new ShapeRef(router, poly34, 34);
+
+ Polygon poly35(4);
+ poly35.ps[0] = Point(1107, 813.545);
+ poly35.ps[1] = Point(1107, 831.545);
+ poly35.ps[2] = Point(1089, 831.545);
+ poly35.ps[3] = Point(1089, 813.545);
+ new ShapeRef(router, poly35, 35);
+
+ Polygon poly36(4);
+ poly36.ps[0] = Point(979, 1098.21);
+ poly36.ps[1] = Point(979, 1116.21);
+ poly36.ps[2] = Point(961, 1116.21);
+ poly36.ps[3] = Point(961, 1098.21);
+ new ShapeRef(router, poly36, 36);
+
+ Polygon poly37(4);
+ poly37.ps[0] = Point(947.8, 1620.71);
+ poly37.ps[1] = Point(947.8, 1638.71);
+ poly37.ps[2] = Point(929.8, 1638.71);
+ poly37.ps[3] = Point(929.8, 1620.71);
+ new ShapeRef(router, poly37, 37);
+
+ Polygon poly38(4);
+ poly38.ps[0] = Point(1299.8, 1595.71);
+ poly38.ps[1] = Point(1299.8, 1653.71);
+ poly38.ps[2] = Point(1041.8, 1653.71);
+ poly38.ps[3] = Point(1041.8, 1595.71);
+ new ShapeRef(router, poly38, 38);
+
+ Polygon poly39(4);
+ poly39.ps[0] = Point(767, 1676.71);
+ poly39.ps[1] = Point(767, 1694.71);
+ poly39.ps[2] = Point(749, 1694.71);
+ poly39.ps[3] = Point(749, 1676.71);
+ new ShapeRef(router, poly39, 39);
+
+ Polygon poly40(4);
+ poly40.ps[0] = Point(767, 1768.71);
+ poly40.ps[1] = Point(767, 1786.71);
+ poly40.ps[2] = Point(749, 1786.71);
+ poly40.ps[3] = Point(749, 1768.71);
+ new ShapeRef(router, poly40, 40);
+
+ Polygon poly85(4);
+ poly85.ps[0] = Point(944, 96);
+ poly85.ps[1] = Point(944, 134);
+ poly85.ps[2] = Point(906, 134);
+ poly85.ps[3] = Point(906, 96);
+ new ShapeRef(router, poly85, 85);
+
+ Polygon poly86(4);
+ poly86.ps[0] = Point(1120, 96);
+ poly86.ps[1] = Point(1120, 134);
+ poly86.ps[2] = Point(1082, 134);
+ poly86.ps[3] = Point(1082, 96);
+ new ShapeRef(router, poly86, 86);
+
+ Polygon poly87(4);
+ poly87.ps[0] = Point(1120, 283);
+ poly87.ps[1] = Point(1120, 321);
+ poly87.ps[2] = Point(1082, 321);
+ poly87.ps[3] = Point(1082, 283);
+ new ShapeRef(router, poly87, 87);
+
+ Polygon poly88(4);
+ poly88.ps[0] = Point(944, 283);
+ poly88.ps[1] = Point(944, 321);
+ poly88.ps[2] = Point(906, 321);
+ poly88.ps[3] = Point(906, 283);
+ new ShapeRef(router, poly88, 88);
+
+ Polygon poly89(4);
+ poly89.ps[0] = Point(353.2, 709.545);
+ poly89.ps[1] = Point(353.2, 747.545);
+ poly89.ps[2] = Point(315.2, 747.545);
+ poly89.ps[3] = Point(315.2, 709.545);
+ new ShapeRef(router, poly89, 89);
+
+ Polygon poly90(4);
+ poly90.ps[0] = Point(665, 667.545);
+ poly90.ps[1] = Point(665, 705.545);
+ poly90.ps[2] = Point(627, 705.545);
+ poly90.ps[3] = Point(627, 667.545);
+ new ShapeRef(router, poly90, 90);
+
+ Polygon poly91(4);
+ poly91.ps[0] = Point(665, 803.545);
+ poly91.ps[1] = Point(665, 841.545);
+ poly91.ps[2] = Point(627, 841.545);
+ poly91.ps[3] = Point(627, 803.545);
+ new ShapeRef(router, poly91, 91);
+
+ Polygon poly92(4);
+ poly92.ps[0] = Point(944, 427);
+ poly92.ps[1] = Point(944, 465);
+ poly92.ps[2] = Point(906, 465);
+ poly92.ps[3] = Point(906, 427);
+ new ShapeRef(router, poly92, 92);
+
+ Polygon poly93(4);
+ poly93.ps[0] = Point(1131, 427);
+ poly93.ps[1] = Point(1131, 465);
+ poly93.ps[2] = Point(1093, 465);
+ poly93.ps[3] = Point(1093, 427);
+ new ShapeRef(router, poly93, 93);
+
+ Polygon poly94(4);
+ poly94.ps[0] = Point(1254, 427);
+ poly94.ps[1] = Point(1254, 465);
+ poly94.ps[2] = Point(1216, 465);
+ poly94.ps[3] = Point(1216, 427);
+ new ShapeRef(router, poly94, 94);
+
+ Polygon poly95(4);
+ poly95.ps[0] = Point(944, 803.545);
+ poly95.ps[1] = Point(944, 841.545);
+ poly95.ps[2] = Point(906, 841.545);
+ poly95.ps[3] = Point(906, 803.545);
+ new ShapeRef(router, poly95, 95);
+
+ Polygon poly96(4);
+ poly96.ps[0] = Point(270, 1082.05);
+ poly96.ps[1] = Point(270, 1120.05);
+ poly96.ps[2] = Point(232, 1120.05);
+ poly96.ps[3] = Point(232, 1082.05);
+ new ShapeRef(router, poly96, 96);
+
+ Polygon poly97(4);
+ poly97.ps[0] = Point(426, 1009.55);
+ poly97.ps[1] = Point(426, 1047.55);
+ poly97.ps[2] = Point(388, 1047.55);
+ poly97.ps[3] = Point(388, 1009.55);
+ new ShapeRef(router, poly97, 97);
+
+ Polygon poly98(4);
+ poly98.ps[0] = Point(262, 1276.05);
+ poly98.ps[1] = Point(262, 1314.05);
+ poly98.ps[2] = Point(224, 1314.05);
+ poly98.ps[3] = Point(224, 1276.05);
+ new ShapeRef(router, poly98, 98);
+
+ Polygon poly99(4);
+ poly99.ps[0] = Point(957.8, 1832.71);
+ poly99.ps[1] = Point(957.8, 1870.71);
+ poly99.ps[2] = Point(919.8, 1870.71);
+ poly99.ps[3] = Point(919.8, 1832.71);
+ new ShapeRef(router, poly99, 99);
+
+ Polygon poly100(4);
+ poly100.ps[0] = Point(957.8, 1666.71);
+ poly100.ps[1] = Point(957.8, 1704.71);
+ poly100.ps[2] = Point(919.8, 1704.71);
+ poly100.ps[3] = Point(919.8, 1666.71);
+ new ShapeRef(router, poly100, 100);
+
+ Polygon poly101(4);
+ poly101.ps[0] = Point(568, 1767.85);
+ poly101.ps[1] = Point(568, 1805.85);
+ poly101.ps[2] = Point(530, 1805.85);
+ poly101.ps[3] = Point(530, 1767.85);
+ new ShapeRef(router, poly101, 101);
+
+ Polygon poly102(4);
+ poly102.ps[0] = Point(717, 1596.71);
+ poly102.ps[1] = Point(717, 1634.71);
+ poly102.ps[2] = Point(679, 1634.71);
+ poly102.ps[3] = Point(679, 1596.71);
+ new ShapeRef(router, poly102, 102);
+
+ Polygon poly103(4);
+ poly103.ps[0] = Point(829, 1441.71);
+ poly103.ps[1] = Point(829, 1479.71);
+ poly103.ps[2] = Point(791, 1479.71);
+ poly103.ps[3] = Point(791, 1441.71);
+ new ShapeRef(router, poly103, 103);
+
+ Polygon poly104(4);
+ poly104.ps[0] = Point(949, 1208.55);
+ poly104.ps[1] = Point(949, 1246.55);
+ poly104.ps[2] = Point(911, 1246.55);
+ poly104.ps[3] = Point(911, 1208.55);
+ new ShapeRef(router, poly104, 104);
+
+ Polygon poly105(4);
+ poly105.ps[0] = Point(804, 1208.55);
+ poly105.ps[1] = Point(804, 1246.55);
+ poly105.ps[2] = Point(766, 1246.55);
+ poly105.ps[3] = Point(766, 1208.55);
+ new ShapeRef(router, poly105, 105);
+
+ Polygon poly106(4);
+ poly106.ps[0] = Point(717, 1009.55);
+ poly106.ps[1] = Point(717, 1047.55);
+ poly106.ps[2] = Point(679, 1047.55);
+ poly106.ps[3] = Point(679, 1009.55);
+ new ShapeRef(router, poly106, 106);
+
+ Polygon poly107(4);
+ poly107.ps[0] = Point(1111, 1088.21);
+ poly107.ps[1] = Point(1111, 1126.21);
+ poly107.ps[2] = Point(1073, 1126.21);
+ poly107.ps[3] = Point(1073, 1088.21);
+ new ShapeRef(router, poly107, 107);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(144, 1140.05);
+ poly4.ps[1] = Point(144, 1158.05);
+ poly4.ps[2] = Point(126, 1158.05);
+ poly4.ps[3] = Point(126, 1140.05);
+ new ShapeRef(router, poly4, 4);
+
+ Polygon poly1(4);
+ poly1.ps[0] = Point(1563.49, 741.379);
+ poly1.ps[1] = Point(1563.49, 779.379);
+ poly1.ps[2] = Point(1525.49, 779.379);
+ poly1.ps[3] = Point(1525.49, 741.379);
+ new ShapeRef(router, poly1, 1);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(527, 437);
+ poly7.ps[1] = Point(527, 455);
+ poly7.ps[2] = Point(509, 455);
+ poly7.ps[3] = Point(509, 437);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(343.2, 677.545);
+ poly8.ps[1] = Point(343.2, 695.545);
+ poly8.ps[2] = Point(325.2, 695.545);
+ poly8.ps[3] = Point(325.2, 677.545);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(200, 1140.05);
+ poly9.ps[1] = Point(200, 1158.05);
+ poly9.ps[2] = Point(182, 1158.05);
+ poly9.ps[3] = Point(182, 1140.05);
+ new ShapeRef(router, poly9, 9);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(343.2, 761.545);
+ poly10.ps[1] = Point(343.2, 779.545);
+ poly10.ps[2] = Point(325.2, 779.545);
+ poly10.ps[3] = Point(325.2, 761.545);
+ new ShapeRef(router, poly10, 10);
+
+ Polygon poly11(4);
+ poly11.ps[0] = Point(343.2, 813.545);
+ poly11.ps[1] = Point(343.2, 831.545);
+ poly11.ps[2] = Point(325.2, 831.545);
+ poly11.ps[3] = Point(325.2, 813.545);
+ new ShapeRef(router, poly11, 11);
+
+ Polygon poly12(4);
+ poly12.ps[0] = Point(343.2, 865.545);
+ poly12.ps[1] = Point(343.2, 883.545);
+ poly12.ps[2] = Point(325.2, 883.545);
+ poly12.ps[3] = Point(325.2, 865.545);
+ new ShapeRef(router, poly12, 12);
+
+ Polygon poly13(4);
+ poly13.ps[0] = Point(476.5, 1092.05);
+ poly13.ps[1] = Point(476.5, 1110.05);
+ poly13.ps[2] = Point(458.5, 1110.05);
+ poly13.ps[3] = Point(458.5, 1092.05);
+ new ShapeRef(router, poly13, 13);
+
+ Polygon poly14(4);
+ poly14.ps[0] = Point(595, 1019.55);
+ poly14.ps[1] = Point(595, 1037.55);
+ poly14.ps[2] = Point(577, 1037.55);
+ poly14.ps[3] = Point(577, 1019.55);
+ new ShapeRef(router, poly14, 14);
+
+ Polygon poly15(4);
+ poly15.ps[0] = Point(578, 1194.05);
+ poly15.ps[1] = Point(578, 1212.05);
+ poly15.ps[2] = Point(560, 1212.05);
+ poly15.ps[3] = Point(560, 1194.05);
+ new ShapeRef(router, poly15, 15);
+
+ Polygon poly16(4);
+ poly16.ps[0] = Point(744, 437);
+ poly16.ps[1] = Point(744, 455);
+ poly16.ps[2] = Point(726, 455);
+ poly16.ps[3] = Point(726, 437);
+ new ShapeRef(router, poly16, 16);
+
+ Polygon poly17(4);
+ poly17.ps[0] = Point(870, 437);
+ poly17.ps[1] = Point(870, 455);
+ poly17.ps[2] = Point(852, 455);
+ poly17.ps[3] = Point(852, 437);
+ new ShapeRef(router, poly17, 17);
+
+ Polygon poly18(4);
+ poly18.ps[0] = Point(527, 575.545);
+ poly18.ps[1] = Point(527, 593.545);
+ poly18.ps[2] = Point(509, 593.545);
+ poly18.ps[3] = Point(509, 575.545);
+ new ShapeRef(router, poly18, 18);
+
+ Polygon poly19(4);
+ poly19.ps[0] = Point(801.5, 813.545);
+ poly19.ps[1] = Point(801.5, 831.545);
+ poly19.ps[2] = Point(783.5, 831.545);
+ poly19.ps[3] = Point(783.5, 813.545);
+ new ShapeRef(router, poly19, 19);
+
+ Polygon poly20(4);
+ poly20.ps[0] = Point(806, 1019.55);
+ poly20.ps[1] = Point(806, 1037.55);
+ poly20.ps[2] = Point(788, 1037.55);
+ poly20.ps[3] = Point(788, 1019.55);
+ new ShapeRef(router, poly20, 20);
+
+ Polygon poly21(4);
+ poly21.ps[0] = Point(788, 1114.55);
+ poly21.ps[1] = Point(788, 1132.55);
+ poly21.ps[2] = Point(770, 1132.55);
+ poly21.ps[3] = Point(770, 1114.55);
+ new ShapeRef(router, poly21, 21);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(1479.2, 729.545);
+ poly5.ps[1] = Point(1479.2, 747.545);
+ poly5.ps[2] = Point(1461.2, 747.545);
+ poly5.ps[3] = Point(1461.2, 729.545);
+ new ShapeRef(router, poly5, 5);
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(687.327, 258);
+ poly6.ps[1] = Point(687.327, 291);
+ poly6.ps[2] = Point(393.327, 291);
+ poly6.ps[3] = Point(393.327, 258);
+ new ShapeRef(router, poly6, 6);
+
+ Polygon poly175(4);
+ poly175.ps[0] = Point(1187, 803.545);
+ poly175.ps[1] = Point(1187, 841.545);
+ poly175.ps[2] = Point(1133, 841.545);
+ poly175.ps[3] = Point(1133, 803.545);
+ new ShapeRef(router, poly175, 175);
+
+ Polygon poly176(4);
+ poly176.ps[0] = Point(1059, 1088.21);
+ poly176.ps[1] = Point(1059, 1126.21);
+ poly176.ps[2] = Point(1005, 1126.21);
+ poly176.ps[3] = Point(1005, 1088.21);
+ new ShapeRef(router, poly176, 176);
+
+ Polygon poly177(4);
+ poly177.ps[0] = Point(1027.8, 1610.71);
+ poly177.ps[1] = Point(1027.8, 1648.71);
+ poly177.ps[2] = Point(973.8, 1648.71);
+ poly177.ps[3] = Point(973.8, 1610.71);
+ new ShapeRef(router, poly177, 177);
+
+ Polygon poly178(4);
+ poly178.ps[0] = Point(785, 1616.71);
+ poly178.ps[1] = Point(785, 1654.71);
+ poly178.ps[2] = Point(731, 1654.71);
+ poly178.ps[3] = Point(731, 1616.71);
+ new ShapeRef(router, poly178, 178);
+
+ Polygon poly179(4);
+ poly179.ps[0] = Point(785, 1708.71);
+ poly179.ps[1] = Point(785, 1746.71);
+ poly179.ps[2] = Point(731, 1746.71);
+ poly179.ps[3] = Point(731, 1708.71);
+ new ShapeRef(router, poly179, 179);
+
+ Polygon poly180(4);
+ poly180.ps[0] = Point(785, 1840.71);
+ poly180.ps[1] = Point(785, 1878.71);
+ poly180.ps[2] = Point(731, 1878.71);
+ poly180.ps[3] = Point(731, 1840.71);
+ new ShapeRef(router, poly180, 180);
+
+ Polygon poly181(4);
+ poly181.ps[0] = Point(1027.8, 1790.71);
+ poly181.ps[1] = Point(1027.8, 1828.71);
+ poly181.ps[2] = Point(973.8, 1828.71);
+ poly181.ps[3] = Point(973.8, 1790.71);
+ new ShapeRef(router, poly181, 181);
+
+ Polygon poly182(4);
+ poly182.ps[0] = Point(1193, 1543.71);
+ poly182.ps[1] = Point(1193, 1581.71);
+ poly182.ps[2] = Point(1139, 1581.71);
+ poly182.ps[3] = Point(1139, 1543.71);
+ new ShapeRef(router, poly182, 182);
+
+ Polygon poly183(4);
+ poly183.ps[0] = Point(1255, 1491.71);
+ poly183.ps[1] = Point(1255, 1529.71);
+ poly183.ps[2] = Point(1201, 1529.71);
+ poly183.ps[3] = Point(1201, 1491.71);
+ new ShapeRef(router, poly183, 183);
+
+ Polygon poly184(4);
+ poly184.ps[0] = Point(1429.2, 663.045);
+ poly184.ps[1] = Point(1429.2, 701.045);
+ poly184.ps[2] = Point(1375.2, 701.045);
+ poly184.ps[3] = Point(1375.2, 663.045);
+ new ShapeRef(router, poly184, 184);
+
+ Polygon poly185(4);
+ poly185.ps[0] = Point(1444.33, 1082.05);
+ poly185.ps[1] = Point(1444.33, 1120.05);
+ poly185.ps[2] = Point(1390.33, 1120.05);
+ poly185.ps[3] = Point(1390.33, 1082.05);
+ new ShapeRef(router, poly185, 185);
+
+ Polygon poly186(4);
+ poly186.ps[0] = Point(1557.2, 383.545);
+ poly186.ps[1] = Point(1557.2, 421.545);
+ poly186.ps[2] = Point(1503.2, 421.545);
+ poly186.ps[3] = Point(1503.2, 383.545);
+ new ShapeRef(router, poly186, 186);
+
+ Polygon poly187(4);
+ poly187.ps[0] = Point(1557.2, 475.545);
+ poly187.ps[1] = Point(1557.2, 513.545);
+ poly187.ps[2] = Point(1503.2, 513.545);
+ poly187.ps[3] = Point(1503.2, 475.545);
+ new ShapeRef(router, poly187, 187);
+
+ Polygon poly188(4);
+ poly188.ps[0] = Point(1497.2, 801.545);
+ poly188.ps[1] = Point(1497.2, 839.545);
+ poly188.ps[2] = Point(1443.2, 839.545);
+ poly188.ps[3] = Point(1443.2, 801.545);
+ new ShapeRef(router, poly188, 188);
+
+ Polygon poly189(4);
+ poly189.ps[0] = Point(1557.2, 567.545);
+ poly189.ps[1] = Point(1557.2, 605.545);
+ poly189.ps[2] = Point(1503.2, 605.545);
+ poly189.ps[3] = Point(1503.2, 567.545);
+ new ShapeRef(router, poly189, 189);
+
+ Polygon poly190(4);
+ poly190.ps[0] = Point(1633.49, 840.545);
+ poly190.ps[1] = Point(1633.49, 878.545);
+ poly190.ps[2] = Point(1579.49, 878.545);
+ poly190.ps[3] = Point(1579.49, 840.545);
+ new ShapeRef(router, poly190, 190);
+
+ Polygon poly191(4);
+ poly191.ps[0] = Point(1745.49, 840.545);
+ poly191.ps[1] = Point(1745.49, 878.545);
+ poly191.ps[2] = Point(1691.49, 878.545);
+ poly191.ps[3] = Point(1691.49, 840.545);
+ new ShapeRef(router, poly191, 191);
+
+ Polygon poly192(4);
+ poly192.ps[0] = Point(1497.2, 1134.05);
+ poly192.ps[1] = Point(1497.2, 1172.05);
+ poly192.ps[2] = Point(1443.2, 1172.05);
+ poly192.ps[3] = Point(1443.2, 1134.05);
+ new ShapeRef(router, poly192, 192);
+
+ Polygon poly193(4);
+ poly193.ps[0] = Point(1497.2, 1230.21);
+ poly193.ps[1] = Point(1497.2, 1268.21);
+ poly193.ps[2] = Point(1443.2, 1268.21);
+ poly193.ps[3] = Point(1443.2, 1230.21);
+ new ShapeRef(router, poly193, 193);
+
+ Polygon poly194(4);
+ poly194.ps[0] = Point(1497.2, 1391.71);
+ poly194.ps[1] = Point(1497.2, 1429.71);
+ poly194.ps[2] = Point(1443.2, 1429.71);
+ poly194.ps[3] = Point(1443.2, 1391.71);
+ new ShapeRef(router, poly194, 194);
+
+ Polygon poly195(4);
+ poly195.ps[0] = Point(1812.2, 1287.71);
+ poly195.ps[1] = Point(1812.2, 1325.71);
+ poly195.ps[2] = Point(1758.2, 1325.71);
+ poly195.ps[3] = Point(1758.2, 1287.71);
+ new ShapeRef(router, poly195, 195);
+
+ Polygon poly196(4);
+ poly196.ps[0] = Point(1215, 148);
+ poly196.ps[1] = Point(1215, 186);
+ poly196.ps[2] = Point(1161, 186);
+ poly196.ps[3] = Point(1161, 148);
+ new ShapeRef(router, poly196, 196);
+
+ Polygon poly197(4);
+ poly197.ps[0] = Point(981.8, 148);
+ poly197.ps[1] = Point(981.8, 186);
+ poly197.ps[2] = Point(927.8, 186);
+ poly197.ps[3] = Point(927.8, 148);
+ new ShapeRef(router, poly197, 197);
+
+ Polygon poly41(4);
+ poly41.ps[0] = Point(767, 1800.71);
+ poly41.ps[1] = Point(767, 1818.71);
+ poly41.ps[2] = Point(749, 1818.71);
+ poly41.ps[3] = Point(749, 1800.71);
+ new ShapeRef(router, poly41, 41);
+
+ Polygon poly42(4);
+ poly42.ps[0] = Point(947.8, 1800.71);
+ poly42.ps[1] = Point(947.8, 1818.71);
+ poly42.ps[2] = Point(929.8, 1818.71);
+ poly42.ps[3] = Point(929.8, 1800.71);
+ new ShapeRef(router, poly42, 42);
+
+ Polygon poly43(4);
+ poly43.ps[0] = Point(1237, 1553.71);
+ poly43.ps[1] = Point(1237, 1571.71);
+ poly43.ps[2] = Point(1219, 1571.71);
+ poly43.ps[3] = Point(1219, 1553.71);
+ new ShapeRef(router, poly43, 43);
+
+ Polygon poly44(4);
+ poly44.ps[0] = Point(1237, 1451.71);
+ poly44.ps[1] = Point(1237, 1469.71);
+ poly44.ps[2] = Point(1219, 1469.71);
+ poly44.ps[3] = Point(1219, 1451.71);
+ new ShapeRef(router, poly44, 44);
+
+ Polygon poly45(4);
+ poly45.ps[0] = Point(1349.2, 673.045);
+ poly45.ps[1] = Point(1349.2, 691.045);
+ poly45.ps[2] = Point(1331.2, 691.045);
+ poly45.ps[3] = Point(1331.2, 673.045);
+ new ShapeRef(router, poly45, 45);
+
+ Polygon poly46(4);
+ poly46.ps[0] = Point(1364.33, 1092.05);
+ poly46.ps[1] = Point(1364.33, 1110.05);
+ poly46.ps[2] = Point(1346.33, 1110.05);
+ poly46.ps[3] = Point(1346.33, 1092.05);
+ new ShapeRef(router, poly46, 46);
+
+ Polygon poly47(4);
+ poly47.ps[0] = Point(1539.2, 443.545);
+ poly47.ps[1] = Point(1539.2, 461.545);
+ poly47.ps[2] = Point(1521.2, 461.545);
+ poly47.ps[3] = Point(1521.2, 443.545);
+ new ShapeRef(router, poly47, 47);
+
+ Polygon poly48(4);
+ poly48.ps[0] = Point(1539.2, 535.545);
+ poly48.ps[1] = Point(1539.2, 553.545);
+ poly48.ps[2] = Point(1521.2, 553.545);
+ poly48.ps[3] = Point(1521.2, 535.545);
+ new ShapeRef(router, poly48, 48);
+
+ Polygon poly49(4);
+ poly49.ps[0] = Point(1479.2, 761.545);
+ poly49.ps[1] = Point(1479.2, 779.545);
+ poly49.ps[2] = Point(1461.2, 779.545);
+ poly49.ps[3] = Point(1461.2, 761.545);
+ new ShapeRef(router, poly49, 49);
+
+ Polygon poly50(4);
+ poly50.ps[0] = Point(1539.2, 627.545);
+ poly50.ps[1] = Point(1539.2, 645.545);
+ poly50.ps[2] = Point(1521.2, 645.545);
+ poly50.ps[3] = Point(1521.2, 627.545);
+ new ShapeRef(router, poly50, 50);
+
+ Polygon poly51(4);
+ poly51.ps[0] = Point(1553.49, 850.545);
+ poly51.ps[1] = Point(1553.49, 868.545);
+ poly51.ps[2] = Point(1535.49, 868.545);
+ poly51.ps[3] = Point(1535.49, 850.545);
+ new ShapeRef(router, poly51, 51);
+
+ Polygon poly52(4);
+ poly52.ps[0] = Point(1665.49, 850.545);
+ poly52.ps[1] = Point(1665.49, 868.545);
+ poly52.ps[2] = Point(1647.49, 868.545);
+ poly52.ps[3] = Point(1647.49, 850.545);
+ new ShapeRef(router, poly52, 52);
+
+ Polygon poly53(4);
+ poly53.ps[0] = Point(1479.2, 1194.05);
+ poly53.ps[1] = Point(1479.2, 1212.05);
+ poly53.ps[2] = Point(1461.2, 1212.05);
+ poly53.ps[3] = Point(1461.2, 1194.05);
+ new ShapeRef(router, poly53, 53);
+
+ Polygon poly54(4);
+ poly54.ps[0] = Point(1479.2, 1290.21);
+ poly54.ps[1] = Point(1479.2, 1308.21);
+ poly54.ps[2] = Point(1461.2, 1308.21);
+ poly54.ps[3] = Point(1461.2, 1290.21);
+ new ShapeRef(router, poly54, 54);
+
+ Polygon poly55(4);
+ poly55.ps[0] = Point(1479.2, 1451.71);
+ poly55.ps[1] = Point(1479.2, 1469.71);
+ poly55.ps[2] = Point(1461.2, 1469.71);
+ poly55.ps[3] = Point(1461.2, 1451.71);
+ new ShapeRef(router, poly55, 55);
+
+ Polygon poly56(4);
+ poly56.ps[0] = Point(1732.2, 1297.71);
+ poly56.ps[1] = Point(1732.2, 1315.71);
+ poly56.ps[2] = Point(1714.2, 1315.71);
+ poly56.ps[3] = Point(1714.2, 1297.71);
+ new ShapeRef(router, poly56, 56);
+
+ Polygon poly57(4);
+ poly57.ps[0] = Point(1441, 200);
+ poly57.ps[1] = Point(1441, 363);
+ poly57.ps[2] = Point(1149, 363);
+ poly57.ps[3] = Point(1149, 200);
+ new ShapeRef(router, poly57, 57);
+
+ Polygon poly58(4);
+ poly58.ps[0] = Point(342, 443.545);
+ poly58.ps[1] = Point(342, 501.545);
+ poly58.ps[2] = Point(49, 501.545);
+ poly58.ps[3] = Point(49, 443.545);
+ new ShapeRef(router, poly58, 58);
+
+ Polygon poly59(4);
+ poly59.ps[0] = Point(1111, 617.545);
+ poly59.ps[1] = Point(1111, 789.545);
+ poly59.ps[2] = Point(1028, 789.545);
+ poly59.ps[3] = Point(1028, 617.545);
+ new ShapeRef(router, poly59, 59);
+
+ Polygon poly60(4);
+ poly60.ps[0] = Point(1135, 158);
+ poly60.ps[1] = Point(1135, 176);
+ poly60.ps[2] = Point(1117, 176);
+ poly60.ps[3] = Point(1117, 158);
+ new ShapeRef(router, poly60, 60);
+
+ Polygon poly61(4);
+ poly61.ps[0] = Point(1025.8, 158);
+ poly61.ps[1] = Point(1025.8, 176);
+ poly61.ps[2] = Point(1007.8, 176);
+ poly61.ps[3] = Point(1007.8, 158);
+ new ShapeRef(router, poly61, 61);
+
+ Polygon poly62(4);
+ poly62.ps[0] = Point(1273, 1194.05);
+ poly62.ps[1] = Point(1273, 1212.05);
+ poly62.ps[2] = Point(1255, 1212.05);
+ poly62.ps[3] = Point(1255, 1194.05);
+ new ShapeRef(router, poly62, 62);
+
+ Polygon poly108(4);
+ poly108.ps[0] = Point(1678.49, 1184.05);
+ poly108.ps[1] = Point(1678.49, 1222.05);
+ poly108.ps[2] = Point(1640.49, 1222.05);
+ poly108.ps[3] = Point(1640.49, 1184.05);
+ new ShapeRef(router, poly108, 108);
+
+ Polygon poly109(4);
+ poly109.ps[0] = Point(1559.2, 1280.21);
+ poly109.ps[1] = Point(1559.2, 1318.21);
+ poly109.ps[2] = Point(1521.2, 1318.21);
+ poly109.ps[3] = Point(1521.2, 1280.21);
+ new ShapeRef(router, poly109, 109);
+
+ Polygon poly110(4);
+ poly110.ps[0] = Point(1374.33, 1124.05);
+ poly110.ps[1] = Point(1374.33, 1162.05);
+ poly110.ps[2] = Point(1336.33, 1162.05);
+ poly110.ps[3] = Point(1336.33, 1124.05);
+ new ShapeRef(router, poly110, 110);
+
+ Polygon poly111(4);
+ poly111.ps[0] = Point(1374.33, 1026.05);
+ poly111.ps[1] = Point(1374.33, 1064.05);
+ poly111.ps[2] = Point(1336.33, 1064.05);
+ poly111.ps[3] = Point(1336.33, 1026.05);
+ new ShapeRef(router, poly111, 111);
+
+ Polygon poly112(4);
+ poly112.ps[0] = Point(1489.2, 617.545);
+ poly112.ps[1] = Point(1489.2, 655.545);
+ poly112.ps[2] = Point(1451.2, 655.545);
+ poly112.ps[3] = Point(1451.2, 617.545);
+ new ShapeRef(router, poly112, 112);
+
+ Polygon poly113(4);
+ poly113.ps[0] = Point(1359.2, 741.379);
+ poly113.ps[1] = Point(1359.2, 779.379);
+ poly113.ps[2] = Point(1321.2, 779.379);
+ poly113.ps[3] = Point(1321.2, 741.379);
+ new ShapeRef(router, poly113, 113);
+
+ Polygon poly114(4);
+ poly114.ps[0] = Point(1359.2, 525.545);
+ poly114.ps[1] = Point(1359.2, 563.545);
+ poly114.ps[2] = Point(1321.2, 563.545);
+ poly114.ps[3] = Point(1321.2, 525.545);
+ new ShapeRef(router, poly114, 114);
+
+ Polygon poly115(4);
+ poly115.ps[0] = Point(1609.2, 617.545);
+ poly115.ps[1] = Point(1609.2, 655.545);
+ poly115.ps[2] = Point(1571.2, 655.545);
+ poly115.ps[3] = Point(1571.2, 617.545);
+ new ShapeRef(router, poly115, 115);
+
+ Polygon poly116(4);
+ poly116.ps[0] = Point(1678.49, 525.545);
+ poly116.ps[1] = Point(1678.49, 563.545);
+ poly116.ps[2] = Point(1640.49, 563.545);
+ poly116.ps[3] = Point(1640.49, 525.545);
+ new ShapeRef(router, poly116, 116);
+
+ Polygon poly117(4);
+ poly117.ps[0] = Point(1563.49, 907.545);
+ poly117.ps[1] = Point(1563.49, 945.545);
+ poly117.ps[2] = Point(1525.49, 945.545);
+ poly117.ps[3] = Point(1525.49, 907.545);
+ new ShapeRef(router, poly117, 117);
+
+ Polygon poly118(4);
+ poly118.ps[0] = Point(409, 565.545);
+ poly118.ps[1] = Point(409, 603.545);
+ poly118.ps[2] = Point(371, 603.545);
+ poly118.ps[3] = Point(371, 565.545);
+ new ShapeRef(router, poly118, 118);
+
+ Polygon poly119(4);
+ poly119.ps[0] = Point(1359.2, 904.545);
+ poly119.ps[1] = Point(1359.2, 942.545);
+ poly119.ps[2] = Point(1321.2, 942.545);
+ poly119.ps[3] = Point(1321.2, 904.545);
+ new ShapeRef(router, poly119, 119);
+
+ Polygon poly120(4);
+ poly120.ps[0] = Point(648, 1082.05);
+ poly120.ps[1] = Point(648, 1120.05);
+ poly120.ps[2] = Point(610, 1120.05);
+ poly120.ps[3] = Point(610, 1082.05);
+ new ShapeRef(router, poly120, 120);
+
+ Polygon poly121(4);
+ poly121.ps[0] = Point(1196, 1297.71);
+ poly121.ps[1] = Point(1196, 1335.71);
+ poly121.ps[2] = Point(1158, 1335.71);
+ poly121.ps[3] = Point(1158, 1297.71);
+ new ShapeRef(router, poly121, 121);
+
+ Polygon poly122(4);
+ poly122.ps[0] = Point(1343, 1184.05);
+ poly122.ps[1] = Point(1343, 1222.05);
+ poly122.ps[2] = Point(1305, 1222.05);
+ poly122.ps[3] = Point(1305, 1184.05);
+ new ShapeRef(router, poly122, 122);
+
+ Polygon poly123(4);
+ poly123.ps[0] = Point(1559.2, 1441.71);
+ poly123.ps[1] = Point(1559.2, 1479.71);
+ poly123.ps[2] = Point(1521.2, 1479.71);
+ poly123.ps[3] = Point(1521.2, 1441.71);
+ new ShapeRef(router, poly123, 123);
+
+ Polygon poly124(4);
+ poly124.ps[0] = Point(1771.2, 1758.71);
+ poly124.ps[1] = Point(1771.2, 1796.71);
+ poly124.ps[2] = Point(1733.2, 1796.71);
+ poly124.ps[3] = Point(1733.2, 1758.71);
+ new ShapeRef(router, poly124, 124);
+
+ Polygon poly125(4);
+ poly125.ps[0] = Point(957.8, 965.545);
+ poly125.ps[1] = Point(957.8, 1003.55);
+ poly125.ps[2] = Point(919.8, 1003.55);
+ poly125.ps[3] = Point(919.8, 965.545);
+ new ShapeRef(router, poly125, 125);
+
+ Polygon poly126(4);
+ poly126.ps[0] = Point(1131, 1026.05);
+ poly126.ps[1] = Point(1131, 1064.05);
+ poly126.ps[2] = Point(1093, 1064.05);
+ poly126.ps[3] = Point(1093, 1026.05);
+ new ShapeRef(router, poly126, 126);
+
+ Polygon poly127(4);
+ poly127.ps[0] = Point(665, 939.925);
+ poly127.ps[1] = Point(665, 977.925);
+ poly127.ps[2] = Point(627, 977.925);
+ poly127.ps[3] = Point(627, 939.925);
+ new ShapeRef(router, poly127, 127);
+
+ Polygon poly128(4);
+ poly128.ps[0] = Point(418, 1184.05);
+ poly128.ps[1] = Point(418, 1222.05);
+ poly128.ps[2] = Point(380, 1222.05);
+ poly128.ps[3] = Point(380, 1184.05);
+ new ShapeRef(router, poly128, 128);
+
+ Polygon poly129(4);
+ poly129.ps[0] = Point(418, 1276.05);
+ poly129.ps[1] = Point(418, 1314.05);
+ poly129.ps[2] = Point(380, 1314.05);
+ poly129.ps[3] = Point(380, 1276.05);
+ new ShapeRef(router, poly129, 129);
+
+ ConnRef *connRef223 = new ConnRef(router, 223);
+ ConnEnd srcPt223(Point(1544.49, 849.545), 1);
+ connRef223->setSourceEndpoint(srcPt223);
+ ConnEnd dstPt223(Point(1544.49, 760.379), 15);
+ connRef223->setDestEndpoint(dstPt223);
+ connRef223->setRoutingType((ConnType)2);
+
+ ConnRef *connRef224 = new ConnRef(router, 224);
+ ConnEnd srcPt224(Point(329, 1295.05), 4);
+ connRef224->setSourceEndpoint(srcPt224);
+ ConnEnd dstPt224(Point(243, 1295.05), 15);
+ connRef224->setDestEndpoint(dstPt224);
+ connRef224->setRoutingType((ConnType)2);
+
+ ConnRef *connRef225 = new ConnRef(router, 225);
+ ConnEnd srcPt225(Point(329, 1203.05), 4);
+ connRef225->setSourceEndpoint(srcPt225);
+ ConnEnd dstPt225(Point(243, 1295.05), 15);
+ connRef225->setDestEndpoint(dstPt225);
+ connRef225->setRoutingType((ConnType)2);
+
+ ConnRef *connRef226 = new ConnRef(router, 226);
+ ConnEnd srcPt226(Point(135, 1159.05), 2);
+ connRef226->setSourceEndpoint(srcPt226);
+ ConnEnd dstPt226(Point(938.8, 1851.71), 15);
+ connRef226->setDestEndpoint(dstPt226);
+ connRef226->setRoutingType((ConnType)2);
+
+ ConnRef *connRef227 = new ConnRef(router, 227);
+ ConnEnd srcPt227(Point(1480.2, 738.545), 8);
+ connRef227->setSourceEndpoint(srcPt227);
+ ConnEnd dstPt227(Point(1544.49, 760.379), 15);
+ connRef227->setDestEndpoint(dstPt227);
+ connRef227->setRoutingType((ConnType)2);
+
+ ConnRef *connRef228 = new ConnRef(router, 228);
+ ConnEnd srcPt228(Point(508, 446), 4);
+ connRef228->setSourceEndpoint(srcPt228);
+ ConnEnd dstPt228(Point(375, 446), 15);
+ connRef228->setDestEndpoint(dstPt228);
+ connRef228->setRoutingType((ConnType)2);
+
+ ConnRef *connRef229 = new ConnRef(router, 229);
+ ConnEnd srcPt229(Point(324.2, 686.545), 4);
+ connRef229->setSourceEndpoint(srcPt229);
+ ConnEnd dstPt229(Point(100, 686.545), 15);
+ connRef229->setDestEndpoint(dstPt229);
+ connRef229->setRoutingType((ConnType)2);
+
+ ConnRef *connRef230 = new ConnRef(router, 230);
+ ConnEnd srcPt230(Point(324.2, 686.545), 4);
+ connRef230->setSourceEndpoint(srcPt230);
+ ConnEnd dstPt230(Point(160, 822.545), 15);
+ connRef230->setDestEndpoint(dstPt230);
+ connRef230->setRoutingType((ConnType)2);
+
+ ConnRef *connRef231 = new ConnRef(router, 231);
+ ConnEnd srcPt231(Point(324.2, 686.545), 4);
+ connRef231->setSourceEndpoint(srcPt231);
+ ConnEnd dstPt231(Point(646, 686.545), 15);
+ connRef231->setDestEndpoint(dstPt231);
+ connRef231->setRoutingType((ConnType)2);
+
+ ConnRef *connRef232 = new ConnRef(router, 232);
+ ConnEnd srcPt232(Point(201, 1149.05), 8);
+ connRef232->setSourceEndpoint(srcPt232);
+ ConnEnd dstPt232(Point(938.8, 1851.71), 15);
+ connRef232->setDestEndpoint(dstPt232);
+ connRef232->setRoutingType((ConnType)2);
+
+ ConnRef *connRef233 = new ConnRef(router, 233);
+ ConnEnd srcPt233(Point(334.2, 780.545), 2);
+ connRef233->setSourceEndpoint(srcPt233);
+ ConnEnd dstPt233(Point(160, 822.545), 15);
+ connRef233->setDestEndpoint(dstPt233);
+ connRef233->setRoutingType((ConnType)2);
+
+ ConnRef *connRef234 = new ConnRef(router, 234);
+ ConnEnd srcPt234(Point(334.2, 780.545), 2);
+ connRef234->setSourceEndpoint(srcPt234);
+ ConnEnd dstPt234(Point(646, 822.545), 15);
+ connRef234->setDestEndpoint(dstPt234);
+ connRef234->setRoutingType((ConnType)2);
+
+ ConnRef *connRef235 = new ConnRef(router, 235);
+ ConnEnd srcPt235(Point(334.2, 780.545), 2);
+ connRef235->setSourceEndpoint(srcPt235);
+ ConnEnd dstPt235(Point(251, 1101.05), 15);
+ connRef235->setDestEndpoint(dstPt235);
+ connRef235->setRoutingType((ConnType)2);
+
+ ConnRef *connRef236 = new ConnRef(router, 236);
+ ConnEnd srcPt236(Point(334.2, 832.545), 2);
+ connRef236->setSourceEndpoint(srcPt236);
+ ConnEnd dstPt236(Point(160, 822.545), 15);
+ connRef236->setDestEndpoint(dstPt236);
+ connRef236->setRoutingType((ConnType)2);
+
+ ConnRef *connRef237 = new ConnRef(router, 237);
+ ConnEnd srcPt237(Point(334.2, 832.545), 2);
+ connRef237->setSourceEndpoint(srcPt237);
+ ConnEnd dstPt237(Point(646, 822.545), 15);
+ connRef237->setDestEndpoint(dstPt237);
+ connRef237->setRoutingType((ConnType)2);
+
+ ConnRef *connRef238 = new ConnRef(router, 238);
+ ConnEnd srcPt238(Point(334.2, 832.545), 2);
+ connRef238->setSourceEndpoint(srcPt238);
+ ConnEnd dstPt238(Point(251, 1101.05), 15);
+ connRef238->setDestEndpoint(dstPt238);
+ connRef238->setRoutingType((ConnType)2);
+
+ ConnRef *connRef239 = new ConnRef(router, 239);
+ ConnEnd srcPt239(Point(334.2, 884.545), 2);
+ connRef239->setSourceEndpoint(srcPt239);
+ ConnEnd dstPt239(Point(160, 822.545), 15);
+ connRef239->setDestEndpoint(dstPt239);
+ connRef239->setRoutingType((ConnType)2);
+
+ ConnRef *connRef240 = new ConnRef(router, 240);
+ ConnEnd srcPt240(Point(334.2, 884.545), 2);
+ connRef240->setSourceEndpoint(srcPt240);
+ ConnEnd dstPt240(Point(646, 822.545), 15);
+ connRef240->setDestEndpoint(dstPt240);
+ connRef240->setRoutingType((ConnType)2);
+
+ ConnRef *connRef241 = new ConnRef(router, 241);
+ ConnEnd srcPt241(Point(334.2, 884.545), 2);
+ connRef241->setSourceEndpoint(srcPt241);
+ ConnEnd dstPt241(Point(251, 1101.05), 15);
+ connRef241->setDestEndpoint(dstPt241);
+ connRef241->setRoutingType((ConnType)2);
+
+ ConnRef *connRef242 = new ConnRef(router, 242);
+ ConnEnd srcPt242(Point(457.5, 1101.05), 4);
+ connRef242->setSourceEndpoint(srcPt242);
+ ConnEnd dstPt242(Point(251, 1101.05), 15);
+ connRef242->setDestEndpoint(dstPt242);
+ connRef242->setRoutingType((ConnType)2);
+
+ ConnRef *connRef243 = new ConnRef(router, 243);
+ ConnEnd srcPt243(Point(576, 1028.55), 4);
+ connRef243->setSourceEndpoint(srcPt243);
+ ConnEnd dstPt243(Point(407, 1028.55), 15);
+ connRef243->setDestEndpoint(dstPt243);
+ connRef243->setRoutingType((ConnType)2);
+
+ ConnRef *connRef244 = new ConnRef(router, 244);
+ ConnEnd srcPt244(Point(579, 1203.05), 8);
+ connRef244->setSourceEndpoint(srcPt244);
+ ConnEnd dstPt244(Point(399, 1203.05), 15);
+ connRef244->setDestEndpoint(dstPt244);
+ connRef244->setRoutingType((ConnType)2);
+
+ ConnRef *connRef245 = new ConnRef(router, 245);
+ ConnEnd srcPt245(Point(579, 1203.05), 8);
+ connRef245->setSourceEndpoint(srcPt245);
+ ConnEnd dstPt245(Point(646, 1227.55), 15);
+ connRef245->setDestEndpoint(dstPt245);
+ connRef245->setRoutingType((ConnType)2);
+
+ ConnRef *connRef246 = new ConnRef(router, 246);
+ ConnEnd srcPt246(Point(725, 446), 4);
+ connRef246->setSourceEndpoint(srcPt246);
+ ConnEnd dstPt246(Point(639.5, 446), 15);
+ connRef246->setDestEndpoint(dstPt246);
+ connRef246->setRoutingType((ConnType)2);
+
+ ConnRef *connRef247 = new ConnRef(router, 247);
+ ConnEnd srcPt247(Point(851, 446), 4);
+ connRef247->setSourceEndpoint(srcPt247);
+ ConnEnd dstPt247(Point(801, 446), 15);
+ connRef247->setDestEndpoint(dstPt247);
+ connRef247->setRoutingType((ConnType)2);
+
+ ConnRef *connRef248 = new ConnRef(router, 248);
+ ConnEnd srcPt248(Point(528, 584.545), 8);
+ connRef248->setSourceEndpoint(srcPt248);
+ ConnEnd dstPt248(Point(646, 686.545), 15);
+ connRef248->setDestEndpoint(dstPt248);
+ connRef248->setRoutingType((ConnType)2);
+
+ ConnRef *connRef249 = new ConnRef(router, 249);
+ ConnEnd srcPt249(Point(528, 584.545), 8);
+ connRef249->setSourceEndpoint(srcPt249);
+ ConnEnd dstPt249(Point(629, 584.545), 15);
+ connRef249->setDestEndpoint(dstPt249);
+ connRef249->setRoutingType((ConnType)2);
+
+ ConnRef *connRef250 = new ConnRef(router, 250);
+ ConnEnd srcPt250(Point(782.5, 822.545), 4);
+ connRef250->setSourceEndpoint(srcPt250);
+ ConnEnd dstPt250(Point(646, 822.545), 15);
+ connRef250->setDestEndpoint(dstPt250);
+ connRef250->setRoutingType((ConnType)2);
+
+ ConnRef *connRef251 = new ConnRef(router, 251);
+ ConnEnd srcPt251(Point(787, 1028.55), 4);
+ connRef251->setSourceEndpoint(srcPt251);
+ ConnEnd dstPt251(Point(698, 1028.55), 15);
+ connRef251->setDestEndpoint(dstPt251);
+ connRef251->setRoutingType((ConnType)2);
+
+ ConnRef *connRef252 = new ConnRef(router, 252);
+ ConnEnd srcPt252(Point(779, 1133.55), 2);
+ connRef252->setSourceEndpoint(srcPt252);
+ ConnEnd dstPt252(Point(646, 1227.55), 15);
+ connRef252->setDestEndpoint(dstPt252);
+ connRef252->setRoutingType((ConnType)2);
+
+ ConnRef *connRef253 = new ConnRef(router, 253);
+ ConnEnd srcPt253(Point(782.5, 686.545), 4);
+ connRef253->setSourceEndpoint(srcPt253);
+ ConnEnd dstPt253(Point(646, 686.545), 15);
+ connRef253->setDestEndpoint(dstPt253);
+ connRef253->setRoutingType((ConnType)2);
+
+ ConnRef *connRef254 = new ConnRef(router, 254);
+ ConnEnd srcPt254(Point(861, 1185.55), 2);
+ connRef254->setSourceEndpoint(srcPt254);
+ ConnEnd dstPt254(Point(930, 1227.55), 15);
+ connRef254->setDestEndpoint(dstPt254);
+ connRef254->setRoutingType((ConnType)2);
+
+ ConnRef *connRef255 = new ConnRef(router, 255);
+ ConnEnd srcPt255(Point(860, 1460.71), 4);
+ connRef255->setSourceEndpoint(srcPt255);
+ ConnEnd dstPt255(Point(810, 1460.71), 15);
+ connRef255->setDestEndpoint(dstPt255);
+ connRef255->setRoutingType((ConnType)2);
+
+ ConnRef *connRef256 = new ConnRef(router, 256);
+ ConnEnd srcPt256(Point(880, 1460.71), 8);
+ connRef256->setSourceEndpoint(srcPt256);
+ ConnEnd dstPt256(Point(930, 1227.55), 15);
+ connRef256->setDestEndpoint(dstPt256);
+ connRef256->setRoutingType((ConnType)2);
+
+ ConnRef *connRef257 = new ConnRef(router, 257);
+ ConnEnd srcPt257(Point(744, 1593.71), 4);
+ connRef257->setSourceEndpoint(srcPt257);
+ ConnEnd dstPt257(Point(549, 1786.85), 15);
+ connRef257->setDestEndpoint(dstPt257);
+ connRef257->setRoutingType((ConnType)2);
+
+ ConnRef *connRef258 = new ConnRef(router, 258);
+ ConnEnd srcPt258(Point(744, 1593.71), 4);
+ connRef258->setSourceEndpoint(srcPt258);
+ ConnEnd dstPt258(Point(698, 1615.71), 15);
+ connRef258->setDestEndpoint(dstPt258);
+ connRef258->setRoutingType((ConnType)2);
+
+ ConnRef *connRef259 = new ConnRef(router, 259);
+ ConnEnd srcPt259(Point(816, 1626.71), 4);
+ connRef259->setSourceEndpoint(srcPt259);
+ ConnEnd dstPt259(Point(698, 1615.71), 15);
+ connRef259->setDestEndpoint(dstPt259);
+ connRef259->setRoutingType((ConnType)2);
+
+ ConnRef *connRef260 = new ConnRef(router, 260);
+ ConnEnd srcPt260(Point(925, 250), 1);
+ connRef260->setSourceEndpoint(srcPt260);
+ ConnEnd dstPt260(Point(925, 115), 15);
+ connRef260->setDestEndpoint(dstPt260);
+ connRef260->setRoutingType((ConnType)2);
+
+ ConnRef *connRef261 = new ConnRef(router, 261);
+ ConnEnd srcPt261(Point(925, 334), 1);
+ connRef261->setSourceEndpoint(srcPt261);
+ ConnEnd dstPt261(Point(925, 302), 15);
+ connRef261->setDestEndpoint(dstPt261);
+ connRef261->setRoutingType((ConnType)2);
+
+ ConnRef *connRef262 = new ConnRef(router, 262);
+ ConnEnd srcPt262(Point(925, 354), 2);
+ connRef262->setSourceEndpoint(srcPt262);
+ ConnEnd dstPt262(Point(925, 446), 15);
+ connRef262->setDestEndpoint(dstPt262);
+ connRef262->setRoutingType((ConnType)2);
+
+ ConnRef *connRef263 = new ConnRef(router, 263);
+ ConnEnd srcPt263(Point(925, 669.045), 1);
+ connRef263->setSourceEndpoint(srcPt263);
+ ConnEnd dstPt263(Point(925, 446), 15);
+ connRef263->setDestEndpoint(dstPt263);
+ connRef263->setRoutingType((ConnType)2);
+
+ ConnRef *connRef264 = new ConnRef(router, 264);
+ ConnEnd srcPt264(Point(925, 922.545), 1);
+ connRef264->setSourceEndpoint(srcPt264);
+ ConnEnd dstPt264(Point(925, 822.545), 15);
+ connRef264->setDestEndpoint(dstPt264);
+ connRef264->setRoutingType((ConnType)2);
+
+ ConnRef *connRef265 = new ConnRef(router, 265);
+ ConnEnd srcPt265(Point(995, 115), 8);
+ connRef265->setSourceEndpoint(srcPt265);
+ ConnEnd dstPt265(Point(1101, 115), 15);
+ connRef265->setDestEndpoint(dstPt265);
+ connRef265->setRoutingType((ConnType)2);
+
+ ConnRef *connRef266 = new ConnRef(router, 266);
+ ConnEnd srcPt266(Point(1000, 446), 8);
+ connRef266->setSourceEndpoint(srcPt266);
+ ConnEnd dstPt266(Point(1112, 446), 15);
+ connRef266->setDestEndpoint(dstPt266);
+ connRef266->setRoutingType((ConnType)2);
+
+ ConnRef *connRef267 = new ConnRef(router, 267);
+ ConnEnd srcPt267(Point(1182, 446), 8);
+ connRef267->setSourceEndpoint(srcPt267);
+ ConnEnd dstPt267(Point(1235, 446), 15);
+ connRef267->setDestEndpoint(dstPt267);
+ connRef267->setRoutingType((ConnType)2);
+
+ ConnRef *connRef268 = new ConnRef(router, 268);
+ ConnEnd srcPt268(Point(1162, 760.379), 8);
+ connRef268->setSourceEndpoint(srcPt268);
+ ConnEnd dstPt268(Point(1340.2, 760.379), 15);
+ connRef268->setDestEndpoint(dstPt268);
+ connRef268->setRoutingType((ConnType)2);
+
+ ConnRef *connRef269 = new ConnRef(router, 269);
+ ConnEnd srcPt269(Point(1098, 832.545), 2);
+ connRef269->setSourceEndpoint(srcPt269);
+ ConnEnd dstPt269(Point(1177, 1316.71), 15);
+ connRef269->setDestEndpoint(dstPt269);
+ connRef269->setRoutingType((ConnType)2);
+
+ ConnRef *connRef270 = new ConnRef(router, 270);
+ ConnEnd srcPt270(Point(970, 1097.21), 1);
+ connRef270->setSourceEndpoint(srcPt270);
+ ConnEnd dstPt270(Point(1092, 1107.21), 15);
+ connRef270->setDestEndpoint(dstPt270);
+ connRef270->setRoutingType((ConnType)2);
+
+ ConnRef *connRef271 = new ConnRef(router, 271);
+ ConnEnd srcPt271(Point(938.8, 1639.71), 2);
+ connRef271->setSourceEndpoint(srcPt271);
+ ConnEnd dstPt271(Point(938.8, 1685.71), 15);
+ connRef271->setDestEndpoint(dstPt271);
+ connRef271->setRoutingType((ConnType)2);
+
+ ConnRef *connRef272 = new ConnRef(router, 272);
+ ConnEnd srcPt272(Point(938.8, 1619.71), 1);
+ connRef272->setSourceEndpoint(srcPt272);
+ ConnEnd dstPt272(Point(930, 1227.55), 15);
+ connRef272->setDestEndpoint(dstPt272);
+ connRef272->setRoutingType((ConnType)2);
+
+ ConnRef *connRef273 = new ConnRef(router, 273);
+ ConnEnd srcPt273(Point(768, 1685.71), 8);
+ connRef273->setSourceEndpoint(srcPt273);
+ ConnEnd dstPt273(Point(938.8, 1685.71), 15);
+ connRef273->setDestEndpoint(dstPt273);
+ connRef273->setRoutingType((ConnType)2);
+
+ ConnRef *connRef274 = new ConnRef(router, 274);
+ ConnEnd srcPt274(Point(748, 1685.71), 4);
+ connRef274->setSourceEndpoint(srcPt274);
+ ConnEnd dstPt274(Point(549, 1786.85), 15);
+ connRef274->setDestEndpoint(dstPt274);
+ connRef274->setRoutingType((ConnType)2);
+
+ ConnRef *connRef275 = new ConnRef(router, 275);
+ ConnEnd srcPt275(Point(768, 1777.71), 8);
+ connRef275->setSourceEndpoint(srcPt275);
+ ConnEnd dstPt275(Point(938.8, 1685.71), 15);
+ connRef275->setDestEndpoint(dstPt275);
+ connRef275->setRoutingType((ConnType)2);
+
+ ConnRef *connRef276 = new ConnRef(router, 276);
+ ConnEnd srcPt276(Point(768, 1809.71), 8);
+ connRef276->setSourceEndpoint(srcPt276);
+ ConnEnd dstPt276(Point(938.8, 1685.71), 15);
+ connRef276->setDestEndpoint(dstPt276);
+ connRef276->setRoutingType((ConnType)2);
+
+ ConnRef *connRef277 = new ConnRef(router, 277);
+ ConnEnd srcPt277(Point(938.8, 1819.71), 2);
+ connRef277->setSourceEndpoint(srcPt277);
+ ConnEnd dstPt277(Point(938.8, 1851.71), 15);
+ connRef277->setDestEndpoint(dstPt277);
+ connRef277->setRoutingType((ConnType)2);
+
+ ConnRef *connRef278 = new ConnRef(router, 278);
+ ConnEnd srcPt278(Point(1228, 1572.71), 2);
+ connRef278->setSourceEndpoint(srcPt278);
+ ConnEnd dstPt278(Point(1177, 1316.71), 15);
+ connRef278->setDestEndpoint(dstPt278);
+ connRef278->setRoutingType((ConnType)2);
+
+ ConnRef *connRef279 = new ConnRef(router, 279);
+ ConnEnd srcPt279(Point(1228, 1552.71), 1);
+ connRef279->setSourceEndpoint(srcPt279);
+ ConnEnd dstPt279(Point(1324, 1203.05), 15);
+ connRef279->setDestEndpoint(dstPt279);
+ connRef279->setRoutingType((ConnType)2);
+
+ ConnRef *connRef280 = new ConnRef(router, 280);
+ ConnEnd srcPt280(Point(1228, 1572.71), 2);
+ connRef280->setSourceEndpoint(srcPt280);
+ ConnEnd dstPt280(Point(1540.2, 1460.71), 15);
+ connRef280->setDestEndpoint(dstPt280);
+ connRef280->setRoutingType((ConnType)2);
+
+ ConnRef *connRef281 = new ConnRef(router, 281);
+ ConnEnd srcPt281(Point(1238, 1460.71), 8);
+ connRef281->setSourceEndpoint(srcPt281);
+ ConnEnd dstPt281(Point(1324, 1203.05), 15);
+ connRef281->setDestEndpoint(dstPt281);
+ connRef281->setRoutingType((ConnType)2);
+
+ ConnRef *connRef282 = new ConnRef(router, 282);
+ ConnEnd srcPt282(Point(1340.2, 672.045), 1);
+ connRef282->setSourceEndpoint(srcPt282);
+ ConnEnd dstPt282(Point(1340.2, 544.545), 15);
+ connRef282->setDestEndpoint(dstPt282);
+ connRef282->setRoutingType((ConnType)2);
+
+ ConnRef *connRef283 = new ConnRef(router, 283);
+ ConnEnd srcPt283(Point(1355.33, 1111.05), 2);
+ connRef283->setSourceEndpoint(srcPt283);
+ ConnEnd dstPt283(Point(1355.33, 1143.05), 15);
+ connRef283->setDestEndpoint(dstPt283);
+ connRef283->setRoutingType((ConnType)2);
+
+ ConnRef *connRef284 = new ConnRef(router, 284);
+ ConnEnd srcPt284(Point(1540.2, 452.545), 8);
+ connRef284->setSourceEndpoint(srcPt284);
+ ConnEnd dstPt284(Point(1659.49, 544.545), 15);
+ connRef284->setDestEndpoint(dstPt284);
+ connRef284->setRoutingType((ConnType)2);
+
+ ConnRef *connRef285 = new ConnRef(router, 285);
+ ConnEnd srcPt285(Point(1540.2, 544.545), 8);
+ connRef285->setSourceEndpoint(srcPt285);
+ ConnEnd dstPt285(Point(1590.2, 636.545), 15);
+ connRef285->setDestEndpoint(dstPt285);
+ connRef285->setRoutingType((ConnType)2);
+
+ ConnRef *connRef286 = new ConnRef(router, 286);
+ ConnEnd srcPt286(Point(1540.2, 544.545), 8);
+ connRef286->setSourceEndpoint(srcPt286);
+ ConnEnd dstPt286(Point(1659.49, 544.545), 15);
+ connRef286->setDestEndpoint(dstPt286);
+ connRef286->setRoutingType((ConnType)2);
+
+ ConnRef *connRef287 = new ConnRef(router, 287);
+ ConnEnd srcPt287(Point(1480.2, 770.545), 8);
+ connRef287->setSourceEndpoint(srcPt287);
+ ConnEnd dstPt287(Point(1544.49, 760.379), 15);
+ connRef287->setDestEndpoint(dstPt287);
+ connRef287->setRoutingType((ConnType)2);
+
+ ConnRef *connRef288 = new ConnRef(router, 288);
+ ConnEnd srcPt288(Point(1520.2, 636.545), 4);
+ connRef288->setSourceEndpoint(srcPt288);
+ ConnEnd dstPt288(Point(1470.2, 636.545), 15);
+ connRef288->setDestEndpoint(dstPt288);
+ connRef288->setRoutingType((ConnType)2);
+
+ ConnRef *connRef289 = new ConnRef(router, 289);
+ ConnEnd srcPt289(Point(1540.2, 636.545), 8);
+ connRef289->setSourceEndpoint(srcPt289);
+ ConnEnd dstPt289(Point(1590.2, 636.545), 15);
+ connRef289->setDestEndpoint(dstPt289);
+ connRef289->setRoutingType((ConnType)2);
+
+ ConnRef *connRef290 = new ConnRef(router, 290);
+ ConnEnd srcPt290(Point(1544.49, 869.545), 2);
+ connRef290->setSourceEndpoint(srcPt290);
+ ConnEnd dstPt290(Point(1544.49, 926.545), 15);
+ connRef290->setDestEndpoint(dstPt290);
+ connRef290->setRoutingType((ConnType)2);
+
+ ConnRef *connRef291 = new ConnRef(router, 291);
+ ConnEnd srcPt291(Point(1656.49, 849.545), 1);
+ connRef291->setSourceEndpoint(srcPt291);
+ ConnEnd dstPt291(Point(1659.49, 1203.05), 15);
+ connRef291->setDestEndpoint(dstPt291);
+ connRef291->setRoutingType((ConnType)2);
+
+ ConnRef *connRef292 = new ConnRef(router, 292);
+ ConnEnd srcPt292(Point(1656.49, 849.545), 1);
+ connRef292->setSourceEndpoint(srcPt292);
+ ConnEnd dstPt292(Point(1590.2, 636.545), 15);
+ connRef292->setDestEndpoint(dstPt292);
+ connRef292->setRoutingType((ConnType)2);
+
+ ConnRef *connRef293 = new ConnRef(router, 293);
+ ConnEnd srcPt293(Point(1656.49, 849.545), 1);
+ connRef293->setSourceEndpoint(srcPt293);
+ ConnEnd dstPt293(Point(1659.49, 544.545), 15);
+ connRef293->setDestEndpoint(dstPt293);
+ connRef293->setRoutingType((ConnType)2);
+
+ ConnRef *connRef294 = new ConnRef(router, 294);
+ ConnEnd srcPt294(Point(1480.2, 1203.05), 8);
+ connRef294->setSourceEndpoint(srcPt294);
+ ConnEnd dstPt294(Point(1659.49, 1203.05), 15);
+ connRef294->setDestEndpoint(dstPt294);
+ connRef294->setRoutingType((ConnType)2);
+
+ ConnRef *connRef295 = new ConnRef(router, 295);
+ ConnEnd srcPt295(Point(1480.2, 1203.05), 8);
+ connRef295->setSourceEndpoint(srcPt295);
+ ConnEnd dstPt295(Point(1355.33, 1143.05), 15);
+ connRef295->setDestEndpoint(dstPt295);
+ connRef295->setRoutingType((ConnType)2);
+
+ ConnRef *connRef296 = new ConnRef(router, 296);
+ ConnEnd srcPt296(Point(1480.2, 1203.05), 8);
+ connRef296->setSourceEndpoint(srcPt296);
+ ConnEnd dstPt296(Point(1544.49, 1052.05), 15);
+ connRef296->setDestEndpoint(dstPt296);
+ connRef296->setRoutingType((ConnType)2);
+
+ ConnRef *connRef297 = new ConnRef(router, 297);
+ ConnEnd srcPt297(Point(1480.2, 1299.21), 8);
+ connRef297->setSourceEndpoint(srcPt297);
+ ConnEnd dstPt297(Point(1540.2, 1299.21), 15);
+ connRef297->setDestEndpoint(dstPt297);
+ connRef297->setRoutingType((ConnType)2);
+
+ ConnRef *connRef298 = new ConnRef(router, 298);
+ ConnEnd srcPt298(Point(1480.2, 1460.71), 8);
+ connRef298->setSourceEndpoint(srcPt298);
+ ConnEnd dstPt298(Point(1540.2, 1460.71), 15);
+ connRef298->setDestEndpoint(dstPt298);
+ connRef298->setRoutingType((ConnType)2);
+
+ ConnRef *connRef299 = new ConnRef(router, 299);
+ ConnEnd srcPt299(Point(1723.2, 1316.71), 2);
+ connRef299->setSourceEndpoint(srcPt299);
+ ConnEnd dstPt299(Point(1540.2, 1460.71), 15);
+ connRef299->setDestEndpoint(dstPt299);
+ connRef299->setRoutingType((ConnType)2);
+
+ ConnRef *connRef300 = new ConnRef(router, 300);
+ ConnEnd srcPt300(Point(1126, 177), 2);
+ connRef300->setSourceEndpoint(srcPt300);
+ ConnEnd dstPt300(Point(1101, 302), 15);
+ connRef300->setDestEndpoint(dstPt300);
+ connRef300->setRoutingType((ConnType)2);
+
+ ConnRef *connRef301 = new ConnRef(router, 301);
+ ConnEnd srcPt301(Point(1016.8, 177), 2);
+ connRef301->setSourceEndpoint(srcPt301);
+ ConnEnd dstPt301(Point(1101, 302), 15);
+ connRef301->setDestEndpoint(dstPt301);
+ connRef301->setRoutingType((ConnType)2);
+
+ ConnRef *connRef302 = new ConnRef(router, 302);
+ ConnEnd srcPt302(Point(1254, 1203.05), 4);
+ connRef302->setSourceEndpoint(srcPt302);
+ ConnEnd dstPt302(Point(930, 1227.55), 15);
+ connRef302->setDestEndpoint(dstPt302);
+ connRef302->setRoutingType((ConnType)2);
+
+ ConnRef *connRef303 = new ConnRef(router, 303);
+ ConnEnd srcPt303(Point(1254, 1203.05), 4);
+ connRef303->setSourceEndpoint(srcPt303);
+ ConnEnd dstPt303(Point(1177, 1316.71), 15);
+ connRef303->setDestEndpoint(dstPt303);
+ connRef303->setRoutingType((ConnType)2);
+
+ ConnRef *connRef304 = new ConnRef(router, 304);
+ ConnEnd srcPt304(Point(1611.2, 1316.71), 2);
+ connRef304->setSourceEndpoint(srcPt304);
+ ConnEnd dstPt304(Point(1659.49, 1203.05), 15);
+ connRef304->setDestEndpoint(dstPt304);
+ connRef304->setRoutingType((ConnType)2);
+
+ ConnRef *connRef305 = new ConnRef(router, 305);
+ ConnEnd srcPt305(Point(1611.2, 1316.71), 2);
+ connRef305->setSourceEndpoint(srcPt305);
+ ConnEnd dstPt305(Point(1540.2, 1460.71), 15);
+ connRef305->setDestEndpoint(dstPt305);
+ connRef305->setRoutingType((ConnType)2);
+
+ ConnRef *connRef306 = new ConnRef(router, 306);
+ ConnEnd srcPt306(Point(621.5, 884.545), 2);
+ connRef306->setSourceEndpoint(srcPt306);
+ ConnEnd dstPt306(Point(646, 958.925), 15);
+ connRef306->setDestEndpoint(dstPt306);
+ connRef306->setRoutingType((ConnType)2);
+
+ ConnRef *connRef307 = new ConnRef(router, 307);
+ ConnEnd srcPt307(Point(698, 884.545), 2);
+ connRef307->setSourceEndpoint(srcPt307);
+ ConnEnd dstPt307(Point(646, 958.925), 15);
+ connRef307->setDestEndpoint(dstPt307);
+ connRef307->setRoutingType((ConnType)2);
+
+ ConnRef *connRef308 = new ConnRef(router, 308);
+ ConnEnd srcPt308(Point(407, 936.545), 2);
+ connRef308->setSourceEndpoint(srcPt308);
+ ConnEnd dstPt308(Point(646, 822.545), 15);
+ connRef308->setDestEndpoint(dstPt308);
+ connRef308->setRoutingType((ConnType)2);
+
+ ConnRef *connRef309 = new ConnRef(router, 309);
+ ConnEnd srcPt309(Point(407, 936.545), 2);
+ connRef309->setSourceEndpoint(srcPt309);
+ ConnEnd dstPt309(Point(407, 1028.55), 15);
+ connRef309->setDestEndpoint(dstPt309);
+ connRef309->setRoutingType((ConnType)2);
+
+ ConnRef *connRef310 = new ConnRef(router, 310);
+ ConnEnd srcPt310(Point(1134, 1117.21), 2);
+ connRef310->setSourceEndpoint(srcPt310);
+ ConnEnd dstPt310(Point(1177, 1316.71), 15);
+ connRef310->setDestEndpoint(dstPt310);
+ connRef310->setRoutingType((ConnType)2);
+
+ ConnRef *connRef311 = new ConnRef(router, 311);
+ ConnEnd srcPt311(Point(1752.2, 1602.71), 1);
+ connRef311->setSourceEndpoint(srcPt311);
+ ConnEnd dstPt311(Point(930, 1227.55), 15);
+ connRef311->setDestEndpoint(dstPt311);
+ connRef311->setRoutingType((ConnType)2);
+
+ ConnRef *connRef312 = new ConnRef(router, 312);
+ ConnEnd srcPt312(Point(1752.2, 1602.71), 1);
+ connRef312->setSourceEndpoint(srcPt312);
+ ConnEnd dstPt312(Point(1659.49, 544.545), 15);
+ connRef312->setDestEndpoint(dstPt312);
+ connRef312->setRoutingType((ConnType)2);
+
+ ConnRef *connRef313 = new ConnRef(router, 313);
+ ConnEnd srcPt313(Point(569, 1269.55), 1);
+ connRef313->setSourceEndpoint(srcPt313);
+ ConnEnd dstPt313(Point(399, 1203.05), 15);
+ connRef313->setDestEndpoint(dstPt313);
+ connRef313->setRoutingType((ConnType)2);
+
+ ConnRef *connRef314 = new ConnRef(router, 314);
+ ConnEnd srcPt314(Point(569, 1269.55), 1);
+ connRef314->setSourceEndpoint(srcPt314);
+ ConnEnd dstPt314(Point(646, 1227.55), 15);
+ connRef314->setDestEndpoint(dstPt314);
+ connRef314->setRoutingType((ConnType)2);
+
+ ConnRef *connRef315 = new ConnRef(router, 315);
+ ConnEnd srcPt315(Point(508, 1049.05), 4);
+ connRef315->setSourceEndpoint(srcPt315);
+ ConnEnd dstPt315(Point(251, 1101.05), 15);
+ connRef315->setDestEndpoint(dstPt315);
+ connRef315->setRoutingType((ConnType)2);
+
+ ConnRef *connRef316 = new ConnRef(router, 316);
+ ConnEnd srcPt316(Point(268, 594.545), 2);
+ connRef316->setSourceEndpoint(srcPt316);
+ ConnEnd dstPt316(Point(407, 1028.55), 15);
+ connRef316->setDestEndpoint(dstPt316);
+ connRef316->setRoutingType((ConnType)2);
+
+ ConnRef *connRef317 = new ConnRef(router, 317);
+ ConnEnd srcPt317(Point(268, 594.545), 2);
+ connRef317->setSourceEndpoint(srcPt317);
+ ConnEnd dstPt317(Point(390, 584.545), 15);
+ connRef317->setDestEndpoint(dstPt317);
+ connRef317->setRoutingType((ConnType)2);
+
+ ConnRef *connRef318 = new ConnRef(router, 318);
+ ConnEnd srcPt318(Point(268, 574.545), 1);
+ connRef318->setSourceEndpoint(srcPt318);
+ ConnEnd dstPt318(Point(220, 584.545), 15);
+ connRef318->setDestEndpoint(dstPt318);
+ connRef318->setRoutingType((ConnType)2);
+
+ ConnRef *connRef319 = new ConnRef(router, 319);
+ ConnEnd srcPt319(Point(150, 584.545), 4);
+ connRef319->setSourceEndpoint(srcPt319);
+ ConnEnd dstPt319(Point(100, 584.545), 15);
+ connRef319->setDestEndpoint(dstPt319);
+ connRef319->setRoutingType((ConnType)2);
+
+ ConnRef *connRef320 = new ConnRef(router, 320);
+ ConnEnd srcPt320(Point(988.8, 1045.05), 4);
+ connRef320->setSourceEndpoint(srcPt320);
+ ConnEnd dstPt320(Point(930, 1227.55), 15);
+ connRef320->setDestEndpoint(dstPt320);
+ connRef320->setRoutingType((ConnType)2);
+
+ ConnRef *connRef321 = new ConnRef(router, 321);
+ ConnEnd srcPt321(Point(988.8, 1045.05), 4);
+ connRef321->setSourceEndpoint(srcPt321);
+ ConnEnd dstPt321(Point(938.8, 984.545), 15);
+ connRef321->setDestEndpoint(dstPt321);
+ connRef321->setRoutingType((ConnType)2);
+
+ ConnRef *connRef322 = new ConnRef(router, 322);
+ ConnEnd srcPt322(Point(1565.2, 1368.71), 2);
+ connRef322->setSourceEndpoint(srcPt322);
+ ConnEnd dstPt322(Point(1540.2, 1460.71), 15);
+ connRef322->setDestEndpoint(dstPt322);
+ connRef322->setRoutingType((ConnType)2);
+
+ ConnRef *connRef323 = new ConnRef(router, 323);
+ ConnEnd srcPt323(Point(1501.53, 1368.71), 2);
+ connRef323->setSourceEndpoint(srcPt323);
+ ConnEnd dstPt323(Point(1540.2, 1460.71), 15);
+ connRef323->setDestEndpoint(dstPt323);
+ connRef323->setRoutingType((ConnType)2);
+
+ ConnRef *connRef324 = new ConnRef(router, 324);
+ ConnEnd srcPt324(Point(1544.49, 1602.71), 1);
+ connRef324->setSourceEndpoint(srcPt324);
+ ConnEnd dstPt324(Point(1540.2, 1460.71), 15);
+ connRef324->setDestEndpoint(dstPt324);
+ connRef324->setRoutingType((ConnType)2);
+
+ ConnRef *connRef325 = new ConnRef(router, 325);
+ ConnEnd srcPt325(Point(1340.2, 849.545), 1);
+ connRef325->setSourceEndpoint(srcPt325);
+ ConnEnd dstPt325(Point(1340.2, 760.379), 15);
+ connRef325->setDestEndpoint(dstPt325);
+ connRef325->setRoutingType((ConnType)2);
+
+ ConnRef *connRef326 = new ConnRef(router, 326);
+ ConnEnd srcPt326(Point(1544.49, 984.545), 1);
+ connRef326->setSourceEndpoint(srcPt326);
+ ConnEnd dstPt326(Point(1544.49, 926.545), 15);
+ connRef326->setDestEndpoint(dstPt326);
+ connRef326->setRoutingType((ConnType)2);
+
+ ConnRef *connRef327 = new ConnRef(router, 327);
+ ConnEnd srcPt327(Point(1468.53, 994.545), 4);
+ connRef327->setSourceEndpoint(srcPt327);
+ ConnEnd dstPt327(Point(1340.2, 923.545), 15);
+ connRef327->setDestEndpoint(dstPt327);
+ connRef327->setRoutingType((ConnType)2);
+
+ ConnRef *connRef328 = new ConnRef(router, 328);
+ ConnEnd srcPt328(Point(135, 1139.05), 1);
+ connRef328->setSourceEndpoint(srcPt328);
+ ConnEnd dstPt328(Point(160, 822.545), 15);
+ connRef328->setDestEndpoint(dstPt328);
+ connRef328->setRoutingType((ConnType)2);
+
+ ConnRef *connRef329 = new ConnRef(router, 329);
+ ConnEnd srcPt329(Point(181, 1149.05), 4);
+ connRef329->setSourceEndpoint(srcPt329);
+ ConnEnd dstPt329(Point(160, 822.545), 15);
+ connRef329->setDestEndpoint(dstPt329);
+ connRef329->setRoutingType((ConnType)2);
+
+ ConnRef *connRef330 = new ConnRef(router, 330);
+ ConnEnd srcPt330(Point(925, 115), 15);
+ connRef330->setSourceEndpoint(srcPt330);
+ ConnEnd dstPt330(Point(975, 115), 4);
+ connRef330->setDestEndpoint(dstPt330);
+ connRef330->setRoutingType((ConnType)2);
+
+ ConnRef *connRef331 = new ConnRef(router, 331);
+ ConnEnd srcPt331(Point(1101, 115), 15);
+ connRef331->setSourceEndpoint(srcPt331);
+ ConnEnd dstPt331(Point(1126, 157), 1);
+ connRef331->setDestEndpoint(dstPt331);
+ connRef331->setRoutingType((ConnType)2);
+
+ ConnRef *connRef332 = new ConnRef(router, 332);
+ ConnEnd srcPt332(Point(1101, 115), 15);
+ connRef332->setSourceEndpoint(srcPt332);
+ ConnEnd dstPt332(Point(1016.8, 157), 1);
+ connRef332->setDestEndpoint(dstPt332);
+ connRef332->setRoutingType((ConnType)2);
+
+ ConnRef *connRef333 = new ConnRef(router, 333);
+ ConnEnd srcPt333(Point(925, 446), 15);
+ connRef333->setSourceEndpoint(srcPt333);
+ ConnEnd dstPt333(Point(980, 446), 4);
+ connRef333->setDestEndpoint(dstPt333);
+ connRef333->setRoutingType((ConnType)2);
+
+ ConnRef *connRef411 = new ConnRef(router, 411);
+ ConnEnd srcPt411(Point(1470.2, 1249.21), 15);
+ connRef411->setSourceEndpoint(srcPt411);
+ ConnEnd dstPt411(Point(1470.2, 1299.21), 15);
+ connRef411->setDestEndpoint(dstPt411);
+ connRef411->setRoutingType((ConnType)2);
+
+ ConnRef *connRef412 = new ConnRef(router, 412);
+ ConnEnd srcPt412(Point(1470.2, 1410.71), 15);
+ connRef412->setSourceEndpoint(srcPt412);
+ ConnEnd dstPt412(Point(1470.2, 1460.71), 15);
+ connRef412->setDestEndpoint(dstPt412);
+ connRef412->setRoutingType((ConnType)2);
+
+ ConnRef *connRef413 = new ConnRef(router, 413);
+ ConnEnd srcPt413(Point(1785.2, 1306.71), 15);
+ connRef413->setSourceEndpoint(srcPt413);
+ ConnEnd dstPt413(Point(1723.2, 1306.71), 15);
+ connRef413->setDestEndpoint(dstPt413);
+ connRef413->setRoutingType((ConnType)2);
+
+ ConnRef *connRef414 = new ConnRef(router, 414);
+ ConnEnd srcPt414(Point(1188, 167), 15);
+ connRef414->setSourceEndpoint(srcPt414);
+ ConnEnd dstPt414(Point(1126, 167), 15);
+ connRef414->setDestEndpoint(dstPt414);
+ connRef414->setRoutingType((ConnType)2);
+
+ ConnRef *connRef415 = new ConnRef(router, 415);
+ ConnEnd srcPt415(Point(954.8, 167), 15);
+ connRef415->setSourceEndpoint(srcPt415);
+ ConnEnd dstPt415(Point(1016.8, 167), 15);
+ connRef415->setDestEndpoint(dstPt415);
+ connRef415->setRoutingType((ConnType)2);
+
+ ConnRef *connRef416 = new ConnRef(router, 416);
+ ConnEnd srcPt416(Point(1264, 1153.05), 15);
+ connRef416->setSourceEndpoint(srcPt416);
+ ConnEnd dstPt416(Point(1264, 1203.05), 15);
+ connRef416->setDestEndpoint(dstPt416);
+ connRef416->setRoutingType((ConnType)2);
+
+ ConnRef *connRef417 = new ConnRef(router, 417);
+ ConnEnd srcPt417(Point(1673.2, 1306.71), 15);
+ connRef417->setSourceEndpoint(srcPt417);
+ ConnEnd dstPt417(Point(1611.2, 1306.71), 15);
+ connRef417->setDestEndpoint(dstPt417);
+ connRef417->setRoutingType((ConnType)2);
+
+ ConnRef *connRef418 = new ConnRef(router, 418);
+ ConnEnd srcPt418(Point(559.5, 874.545), 15);
+ connRef418->setSourceEndpoint(srcPt418);
+ ConnEnd dstPt418(Point(621.5, 874.545), 15);
+ connRef418->setDestEndpoint(dstPt418);
+ connRef418->setRoutingType((ConnType)2);
+
+ ConnRef *connRef419 = new ConnRef(router, 419);
+ ConnEnd srcPt419(Point(760, 874.545), 15);
+ connRef419->setSourceEndpoint(srcPt419);
+ ConnEnd dstPt419(Point(698, 874.545), 15);
+ connRef419->setDestEndpoint(dstPt419);
+ connRef419->setRoutingType((ConnType)2);
+
+ ConnRef *connRef420 = new ConnRef(router, 420);
+ ConnEnd srcPt420(Point(469, 926.545), 15);
+ connRef420->setSourceEndpoint(srcPt420);
+ ConnEnd dstPt420(Point(407, 926.545), 15);
+ connRef420->setDestEndpoint(dstPt420);
+ connRef420->setRoutingType((ConnType)2);
+
+ ConnRef *connRef421 = new ConnRef(router, 421);
+ ConnEnd srcPt421(Point(1196, 1107.21), 15);
+ connRef421->setSourceEndpoint(srcPt421);
+ ConnEnd dstPt421(Point(1134, 1107.21), 15);
+ connRef421->setDestEndpoint(dstPt421);
+ connRef421->setRoutingType((ConnType)2);
+
+ ConnRef *connRef422 = new ConnRef(router, 422);
+ ConnEnd srcPt422(Point(1814.2, 1612.71), 15);
+ connRef422->setSourceEndpoint(srcPt422);
+ ConnEnd dstPt422(Point(1752.2, 1612.71), 15);
+ connRef422->setDestEndpoint(dstPt422);
+ connRef422->setRoutingType((ConnType)2);
+
+ ConnRef *connRef423 = new ConnRef(router, 423);
+ ConnEnd srcPt423(Point(631, 1279.55), 15);
+ connRef423->setSourceEndpoint(srcPt423);
+ ConnEnd dstPt423(Point(569, 1279.55), 15);
+ connRef423->setDestEndpoint(dstPt423);
+ connRef423->setRoutingType((ConnType)2);
+
+ ConnRef *connRef424 = new ConnRef(router, 424);
+ ConnEnd srcPt424(Point(518, 999.045), 15);
+ connRef424->setSourceEndpoint(srcPt424);
+ ConnEnd dstPt424(Point(518, 1049.05), 15);
+ connRef424->setDestEndpoint(dstPt424);
+ connRef424->setRoutingType((ConnType)2);
+
+ ConnRef *connRef425 = new ConnRef(router, 425);
+ ConnEnd srcPt425(Point(330, 584.545), 15);
+ connRef425->setSourceEndpoint(srcPt425);
+ ConnEnd dstPt425(Point(268, 584.545), 15);
+ connRef425->setDestEndpoint(dstPt425);
+ connRef425->setRoutingType((ConnType)2);
+
+ ConnRef *connRef426 = new ConnRef(router, 426);
+ ConnEnd srcPt426(Point(160, 534.545), 15);
+ connRef426->setSourceEndpoint(srcPt426);
+ ConnEnd dstPt426(Point(160, 584.545), 15);
+ connRef426->setDestEndpoint(dstPt426);
+ connRef426->setRoutingType((ConnType)2);
+
+ ConnRef *connRef427 = new ConnRef(router, 427);
+ ConnEnd srcPt427(Point(998.8, 995.045), 15);
+ connRef427->setSourceEndpoint(srcPt427);
+ ConnEnd dstPt427(Point(998.8, 1045.05), 15);
+ connRef427->setDestEndpoint(dstPt427);
+ connRef427->setRoutingType((ConnType)2);
+
+ ConnRef *connRef428 = new ConnRef(router, 428);
+ ConnEnd srcPt428(Point(1627.2, 1358.71), 15);
+ connRef428->setSourceEndpoint(srcPt428);
+ ConnEnd dstPt428(Point(1565.2, 1358.71), 15);
+ connRef428->setDestEndpoint(dstPt428);
+ connRef428->setRoutingType((ConnType)2);
+
+ ConnRef *connRef429 = new ConnRef(router, 429);
+ ConnEnd srcPt429(Point(1439.53, 1358.71), 15);
+ connRef429->setSourceEndpoint(srcPt429);
+ ConnEnd dstPt429(Point(1501.53, 1358.71), 15);
+ connRef429->setDestEndpoint(dstPt429);
+ connRef429->setRoutingType((ConnType)2);
+
+ ConnRef *connRef430 = new ConnRef(router, 430);
+ ConnEnd srcPt430(Point(1606.49, 1612.71), 15);
+ connRef430->setSourceEndpoint(srcPt430);
+ ConnEnd dstPt430(Point(1544.49, 1612.71), 15);
+ connRef430->setDestEndpoint(dstPt430);
+ connRef430->setRoutingType((ConnType)2);
+
+ ConnRef *connRef431 = new ConnRef(router, 431);
+ ConnEnd srcPt431(Point(1402.2, 859.545), 15);
+ connRef431->setSourceEndpoint(srcPt431);
+ ConnEnd dstPt431(Point(1340.2, 859.545), 15);
+ connRef431->setDestEndpoint(dstPt431);
+ connRef431->setRoutingType((ConnType)2);
+
+ ConnRef *connRef432 = new ConnRef(router, 432);
+ ConnEnd srcPt432(Point(1606.49, 994.545), 15);
+ connRef432->setSourceEndpoint(srcPt432);
+ ConnEnd dstPt432(Point(1544.49, 994.545), 15);
+ connRef432->setDestEndpoint(dstPt432);
+ connRef432->setRoutingType((ConnType)2);
+
+ ConnRef *connRef433 = new ConnRef(router, 433);
+ ConnEnd srcPt433(Point(1478.53, 944.545), 15);
+ connRef433->setSourceEndpoint(srcPt433);
+ ConnEnd dstPt433(Point(1478.53, 994.545), 15);
+ connRef433->setDestEndpoint(dstPt433);
+ connRef433->setRoutingType((ConnType)2);
+
+ ConnRef *connRef434 = new ConnRef(router, 434);
+ ConnEnd srcPt434(Point(399, 1295.05), 15);
+ connRef434->setSourceEndpoint(srcPt434);
+ ConnEnd dstPt434(Point(349, 1295.05), 8);
+ connRef434->setDestEndpoint(dstPt434);
+ connRef434->setRoutingType((ConnType)2);
+
+ ConnRef *connRef435 = new ConnRef(router, 435);
+ ConnEnd srcPt435(Point(399, 1203.05), 15);
+ connRef435->setSourceEndpoint(srcPt435);
+ ConnEnd dstPt435(Point(349, 1203.05), 8);
+ connRef435->setDestEndpoint(dstPt435);
+ connRef435->setRoutingType((ConnType)2);
+
+ ConnRef *connRef436 = new ConnRef(router, 436);
+ ConnEnd srcPt436(Point(1340.2, 760.379), 15);
+ connRef436->setSourceEndpoint(srcPt436);
+ ConnEnd dstPt436(Point(1460.2, 738.545), 4);
+ connRef436->setDestEndpoint(dstPt436);
+ connRef436->setRoutingType((ConnType)2);
+
+ ConnRef *connRef437 = new ConnRef(router, 437);
+ ConnEnd srcPt437(Point(639.5, 446), 15);
+ connRef437->setSourceEndpoint(srcPt437);
+ ConnEnd dstPt437(Point(528, 446), 8);
+ connRef437->setDestEndpoint(dstPt437);
+ connRef437->setRoutingType((ConnType)2);
+
+ ConnRef *connRef438 = new ConnRef(router, 438);
+ ConnEnd srcPt438(Point(698, 1028.55), 15);
+ connRef438->setSourceEndpoint(srcPt438);
+ ConnEnd dstPt438(Point(596, 1028.55), 8);
+ connRef438->setDestEndpoint(dstPt438);
+ connRef438->setRoutingType((ConnType)2);
+
+ ConnRef *connRef439 = new ConnRef(router, 439);
+ ConnEnd srcPt439(Point(801, 446), 15);
+ connRef439->setSourceEndpoint(srcPt439);
+ ConnEnd dstPt439(Point(745, 446), 8);
+ connRef439->setDestEndpoint(dstPt439);
+ connRef439->setRoutingType((ConnType)2);
+
+ ConnRef *connRef440 = new ConnRef(router, 440);
+ ConnEnd srcPt440(Point(925, 446), 15);
+ connRef440->setSourceEndpoint(srcPt440);
+ ConnEnd dstPt440(Point(871, 446), 8);
+ connRef440->setDestEndpoint(dstPt440);
+ connRef440->setRoutingType((ConnType)2);
+
+ ConnRef *connRef441 = new ConnRef(router, 441);
+ ConnEnd srcPt441(Point(390, 584.545), 15);
+ connRef441->setSourceEndpoint(srcPt441);
+ ConnEnd dstPt441(Point(508, 584.545), 4);
+ connRef441->setDestEndpoint(dstPt441);
+ connRef441->setRoutingType((ConnType)2);
+
+ ConnRef *connRef442 = new ConnRef(router, 442);
+ ConnEnd srcPt442(Point(925, 822.545), 15);
+ connRef442->setSourceEndpoint(srcPt442);
+ ConnEnd dstPt442(Point(802.5, 822.545), 8);
+ connRef442->setDestEndpoint(dstPt442);
+ connRef442->setRoutingType((ConnType)2);
+
+ ConnRef *connRef443 = new ConnRef(router, 443);
+ ConnEnd srcPt443(Point(925, 822.545), 15);
+ connRef443->setSourceEndpoint(srcPt443);
+ ConnEnd dstPt443(Point(807, 1028.55), 8);
+ connRef443->setDestEndpoint(dstPt443);
+ connRef443->setRoutingType((ConnType)2);
+
+ ConnRef *connRef444 = new ConnRef(router, 444);
+ ConnEnd srcPt444(Point(925, 822.545), 15);
+ connRef444->setSourceEndpoint(srcPt444);
+ ConnEnd dstPt444(Point(779, 1113.55), 1);
+ connRef444->setDestEndpoint(dstPt444);
+ connRef444->setRoutingType((ConnType)2);
+
+ ConnRef *connRef445 = new ConnRef(router, 445);
+ ConnEnd srcPt445(Point(925, 822.545), 15);
+ connRef445->setSourceEndpoint(srcPt445);
+ ConnEnd dstPt445(Point(802.5, 686.545), 8);
+ connRef445->setDestEndpoint(dstPt445);
+ connRef445->setRoutingType((ConnType)2);
+
+ ConnRef *connRef446 = new ConnRef(router, 446);
+ ConnEnd srcPt446(Point(925, 822.545), 15);
+ connRef446->setSourceEndpoint(srcPt446);
+ ConnEnd dstPt446(Point(861, 1165.55), 1);
+ connRef446->setDestEndpoint(dstPt446);
+ connRef446->setRoutingType((ConnType)2);
+
+ ConnRef *connRef447 = new ConnRef(router, 447);
+ ConnEnd srcPt447(Point(930, 1227.55), 15);
+ connRef447->setSourceEndpoint(srcPt447);
+ ConnEnd dstPt447(Point(764, 1593.71), 8);
+ connRef447->setDestEndpoint(dstPt447);
+ connRef447->setRoutingType((ConnType)2);
+
+ ConnRef *connRef448 = new ConnRef(router, 448);
+ ConnEnd srcPt448(Point(930, 1227.55), 15);
+ connRef448->setSourceEndpoint(srcPt448);
+ ConnEnd dstPt448(Point(836, 1626.71), 8);
+ connRef448->setDestEndpoint(dstPt448);
+ connRef448->setRoutingType((ConnType)2);
+
+ ConnRef *connRef449 = new ConnRef(router, 449);
+ ConnEnd srcPt449(Point(925, 302), 15);
+ connRef449->setSourceEndpoint(srcPt449);
+ ConnEnd dstPt449(Point(925, 270), 2);
+ connRef449->setDestEndpoint(dstPt449);
+ connRef449->setRoutingType((ConnType)2);
+
+ ConnRef *connRef450 = new ConnRef(router, 450);
+ ConnEnd srcPt450(Point(925, 822.545), 15);
+ connRef450->setSourceEndpoint(srcPt450);
+ ConnEnd dstPt450(Point(925, 689.045), 2);
+ connRef450->setDestEndpoint(dstPt450);
+ connRef450->setRoutingType((ConnType)2);
+
+ ConnRef *connRef451 = new ConnRef(router, 451);
+ ConnEnd srcPt451(Point(930, 1227.55), 15);
+ connRef451->setSourceEndpoint(srcPt451);
+ ConnEnd dstPt451(Point(925, 942.545), 2);
+ connRef451->setDestEndpoint(dstPt451);
+ connRef451->setRoutingType((ConnType)2);
+
+ ConnRef *connRef452 = new ConnRef(router, 452);
+ ConnEnd srcPt452(Point(1112, 446), 15);
+ connRef452->setSourceEndpoint(srcPt452);
+ ConnEnd dstPt452(Point(1162, 446), 4);
+ connRef452->setDestEndpoint(dstPt452);
+ connRef452->setRoutingType((ConnType)2);
+
+ ConnRef *connRef453 = new ConnRef(router, 453);
+ ConnEnd srcPt453(Point(925, 822.545), 15);
+ connRef453->setSourceEndpoint(srcPt453);
+ ConnEnd dstPt453(Point(1142, 760.379), 4);
+ connRef453->setDestEndpoint(dstPt453);
+ connRef453->setRoutingType((ConnType)2);
+
+ ConnRef *connRef454 = new ConnRef(router, 454);
+ ConnEnd srcPt454(Point(930, 1227.55), 15);
+ connRef454->setSourceEndpoint(srcPt454);
+ ConnEnd dstPt454(Point(970, 1117.21), 2);
+ connRef454->setDestEndpoint(dstPt454);
+ connRef454->setRoutingType((ConnType)2);
+
+ ConnRef *connRef455 = new ConnRef(router, 455);
+ ConnEnd srcPt455(Point(1177, 1316.71), 15);
+ connRef455->setSourceEndpoint(srcPt455);
+ ConnEnd dstPt455(Point(1218, 1460.71), 4);
+ connRef455->setDestEndpoint(dstPt455);
+ connRef455->setRoutingType((ConnType)2);
+
+ ConnRef *connRef456 = new ConnRef(router, 456);
+ ConnEnd srcPt456(Point(1340.2, 760.379), 15);
+ connRef456->setSourceEndpoint(srcPt456);
+ ConnEnd dstPt456(Point(1340.2, 692.045), 2);
+ connRef456->setDestEndpoint(dstPt456);
+ connRef456->setRoutingType((ConnType)2);
+
+ ConnRef *connRef457 = new ConnRef(router, 457);
+ ConnEnd srcPt457(Point(1340.2, 760.379), 15);
+ connRef457->setSourceEndpoint(srcPt457);
+ ConnEnd dstPt457(Point(1460.2, 770.545), 4);
+ connRef457->setDestEndpoint(dstPt457);
+ connRef457->setRoutingType((ConnType)2);
+
+ ConnRef *connRef458 = new ConnRef(router, 458);
+ ConnEnd srcPt458(Point(1324, 1203.05), 15);
+ connRef458->setSourceEndpoint(srcPt458);
+ ConnEnd dstPt458(Point(1460.2, 1203.05), 4);
+ connRef458->setDestEndpoint(dstPt458);
+ connRef458->setRoutingType((ConnType)2);
+
+ ConnRef *connRef459 = new ConnRef(router, 459);
+ ConnEnd srcPt459(Point(1324, 1203.05), 15);
+ connRef459->setSourceEndpoint(srcPt459);
+ ConnEnd dstPt459(Point(1460.2, 1299.21), 4);
+ connRef459->setDestEndpoint(dstPt459);
+ connRef459->setRoutingType((ConnType)2);
+
+ ConnRef *connRef460 = new ConnRef(router, 460);
+ ConnEnd srcPt460(Point(646, 822.545), 15);
+ connRef460->setSourceEndpoint(srcPt460);
+ ConnEnd dstPt460(Point(621.5, 864.545), 1);
+ connRef460->setDestEndpoint(dstPt460);
+ connRef460->setRoutingType((ConnType)2);
+
+ ConnRef *connRef461 = new ConnRef(router, 461);
+ ConnEnd srcPt461(Point(646, 822.545), 15);
+ connRef461->setSourceEndpoint(srcPt461);
+ ConnEnd dstPt461(Point(698, 864.545), 1);
+ connRef461->setDestEndpoint(dstPt461);
+ connRef461->setRoutingType((ConnType)2);
+
+ ConnRef *connRef462 = new ConnRef(router, 462);
+ ConnEnd srcPt462(Point(1340.2, 923.545), 15);
+ connRef462->setSourceEndpoint(srcPt462);
+ ConnEnd dstPt462(Point(1340.2, 869.545), 2);
+ connRef462->setDestEndpoint(dstPt462);
+ connRef462->setRoutingType((ConnType)2);
+
+ ConnRef *connRef463 = new ConnRef(router, 463);
+ ConnEnd srcPt463(Point(1544.49, 1052.05), 15);
+ connRef463->setSourceEndpoint(srcPt463);
+ ConnEnd dstPt463(Point(1544.49, 1004.55), 2);
+ connRef463->setDestEndpoint(dstPt463);
+ connRef463->setRoutingType((ConnType)2);
+
+ ConnRef *connRef464 = new ConnRef(router, 464);
+ ConnEnd srcPt464(Point(549, 1786.85), 15);
+ connRef464->setSourceEndpoint(srcPt464);
+ ConnEnd dstPt464(Point(748, 1777.71), 4);
+ connRef464->setDestEndpoint(dstPt464);
+ connRef464->setRoutingType((ConnType)2);
+
+ ConnRef *connRef465 = new ConnRef(router, 465);
+ ConnEnd srcPt465(Point(549, 1786.85), 15);
+ connRef465->setSourceEndpoint(srcPt465);
+ ConnEnd dstPt465(Point(748, 1809.71), 4);
+ connRef465->setDestEndpoint(dstPt465);
+ connRef465->setRoutingType((ConnType)2);
+
+ ConnRef *connRef466 = new ConnRef(router, 466);
+ ConnEnd srcPt466(Point(930, 1227.55), 15);
+ connRef466->setSourceEndpoint(srcPt466);
+ ConnEnd dstPt466(Point(1045.8, 1614.71), 4);
+ connRef466->setDestEndpoint(dstPt466);
+ connRef466->setRoutingType((ConnType)2);
+
+ ConnRef *connRef467 = new ConnRef(router, 467);
+ ConnEnd srcPt467(Point(1101, 302), 15);
+ connRef467->setSourceEndpoint(srcPt467);
+ ConnEnd dstPt467(Point(1153, 344), 4);
+ connRef467->setDestEndpoint(dstPt467);
+ connRef467->setRoutingType((ConnType)2);
+
+ ConnRef *connRef468 = new ConnRef(router, 468);
+ ConnEnd srcPt468(Point(1235, 446), 15);
+ connRef468->setSourceEndpoint(srcPt468);
+ ConnEnd dstPt468(Point(1240, 359), 2);
+ connRef468->setDestEndpoint(dstPt468);
+ connRef468->setRoutingType((ConnType)2);
+
+ ConnRef *connRef469 = new ConnRef(router, 469);
+ ConnEnd srcPt469(Point(375, 446), 15);
+ connRef469->setSourceEndpoint(srcPt469);
+ ConnEnd dstPt469(Point(338, 482.545), 8);
+ connRef469->setDestEndpoint(dstPt469);
+ connRef469->setRoutingType((ConnType)2);
+
+ ConnRef *connRef470 = new ConnRef(router, 470);
+ ConnEnd srcPt470(Point(1112, 446), 15);
+ connRef470->setSourceEndpoint(srcPt470);
+ ConnEnd dstPt470(Point(1047.83, 735.462), 1);
+ connRef470->setDestEndpoint(dstPt470);
+ connRef470->setRoutingType((ConnType)2);
+
+ ConnRef *connRef471 = new ConnRef(router, 471);
+ ConnEnd srcPt471(Point(810, 1460.71), 15);
+ connRef471->setSourceEndpoint(srcPt471);
+ ConnEnd dstPt471(Point(773, 1347.05), 8);
+ connRef471->setDestEndpoint(dstPt471);
+ connRef471->setRoutingType((ConnType)2);
+
+ ConnRef *connRef472 = new ConnRef(router, 472);
+ ConnEnd srcPt472(Point(925, 302), 15);
+ connRef472->setSourceEndpoint(srcPt472);
+ ConnEnd dstPt472(Point(888, 344), 8);
+ connRef472->setDestEndpoint(dstPt472);
+ connRef472->setRoutingType((ConnType)2);
+
+ ConnRef *connRef334 = new ConnRef(router, 334);
+ ConnEnd srcPt334(Point(925, 822.545), 15);
+ connRef334->setSourceEndpoint(srcPt334);
+ ConnEnd dstPt334(Point(1098, 812.545), 1);
+ connRef334->setDestEndpoint(dstPt334);
+ connRef334->setRoutingType((ConnType)2);
+
+ ConnRef *connRef335 = new ConnRef(router, 335);
+ ConnEnd srcPt335(Point(938.8, 1799.71), 1);
+ connRef335->setSourceEndpoint(srcPt335);
+ ConnEnd dstPt335(Point(938.8, 1685.71), 15);
+ connRef335->setDestEndpoint(dstPt335);
+ connRef335->setRoutingType((ConnType)2);
+
+ ConnRef *connRef336 = new ConnRef(router, 336);
+ ConnEnd srcPt336(Point(698, 1028.55), 15);
+ connRef336->setSourceEndpoint(srcPt336);
+ ConnEnd dstPt336(Point(528, 1049.05), 8);
+ connRef336->setDestEndpoint(dstPt336);
+ connRef336->setRoutingType((ConnType)2);
+
+ ConnRef *connRef337 = new ConnRef(router, 337);
+ ConnEnd srcPt337(Point(1092, 1107.21), 15);
+ connRef337->setSourceEndpoint(srcPt337);
+ ConnEnd dstPt337(Point(1134, 1097.21), 1);
+ connRef337->setDestEndpoint(dstPt337);
+ connRef337->setRoutingType((ConnType)2);
+
+ ConnRef *connRef338 = new ConnRef(router, 338);
+ ConnEnd srcPt338(Point(1659.49, 1203.05), 15);
+ connRef338->setSourceEndpoint(srcPt338);
+ ConnEnd dstPt338(Point(1723.2, 1296.71), 1);
+ connRef338->setDestEndpoint(dstPt338);
+ connRef338->setRoutingType((ConnType)2);
+
+ ConnRef *connRef339 = new ConnRef(router, 339);
+ ConnEnd srcPt339(Point(1540.2, 1299.21), 15);
+ connRef339->setSourceEndpoint(srcPt339);
+ ConnEnd dstPt339(Point(1565.2, 1348.71), 1);
+ connRef339->setDestEndpoint(dstPt339);
+ connRef339->setRoutingType((ConnType)2);
+
+ ConnRef *connRef340 = new ConnRef(router, 340);
+ ConnEnd srcPt340(Point(1540.2, 1299.21), 15);
+ connRef340->setSourceEndpoint(srcPt340);
+ ConnEnd dstPt340(Point(1501.53, 1348.71), 1);
+ connRef340->setDestEndpoint(dstPt340);
+ connRef340->setRoutingType((ConnType)2);
+
+ ConnRef *connRef341 = new ConnRef(router, 341);
+ ConnEnd srcPt341(Point(1355.33, 1045.05), 15);
+ connRef341->setSourceEndpoint(srcPt341);
+ ConnEnd dstPt341(Point(1355.33, 1091.05), 1);
+ connRef341->setDestEndpoint(dstPt341);
+ connRef341->setRoutingType((ConnType)2);
+
+ ConnRef *connRef342 = new ConnRef(router, 342);
+ ConnEnd srcPt342(Point(1340.2, 544.545), 15);
+ connRef342->setSourceEndpoint(srcPt342);
+ ConnEnd dstPt342(Point(1520.2, 452.545), 4);
+ connRef342->setDestEndpoint(dstPt342);
+ connRef342->setRoutingType((ConnType)2);
+
+ ConnRef *connRef343 = new ConnRef(router, 343);
+ ConnEnd srcPt343(Point(1340.2, 544.545), 15);
+ connRef343->setSourceEndpoint(srcPt343);
+ ConnEnd dstPt343(Point(1520.2, 544.545), 4);
+ connRef343->setDestEndpoint(dstPt343);
+ connRef343->setRoutingType((ConnType)2);
+
+ ConnRef *connRef344 = new ConnRef(router, 344);
+ ConnEnd srcPt344(Point(1659.49, 544.545), 15);
+ connRef344->setSourceEndpoint(srcPt344);
+ ConnEnd dstPt344(Point(1611.2, 1296.71), 1);
+ connRef344->setDestEndpoint(dstPt344);
+ connRef344->setRoutingType((ConnType)2);
+
+ ConnRef *connRef345 = new ConnRef(router, 345);
+ ConnEnd srcPt345(Point(390, 584.545), 15);
+ connRef345->setSourceEndpoint(srcPt345);
+ ConnEnd dstPt345(Point(334.2, 760.545), 1);
+ connRef345->setDestEndpoint(dstPt345);
+ connRef345->setRoutingType((ConnType)2);
+
+ ConnRef *connRef346 = new ConnRef(router, 346);
+ ConnEnd srcPt346(Point(390, 584.545), 15);
+ connRef346->setSourceEndpoint(srcPt346);
+ ConnEnd dstPt346(Point(334.2, 812.545), 1);
+ connRef346->setDestEndpoint(dstPt346);
+ connRef346->setRoutingType((ConnType)2);
+
+ ConnRef *connRef347 = new ConnRef(router, 347);
+ ConnEnd srcPt347(Point(390, 584.545), 15);
+ connRef347->setSourceEndpoint(srcPt347);
+ ConnEnd dstPt347(Point(334.2, 864.545), 1);
+ connRef347->setDestEndpoint(dstPt347);
+ connRef347->setRoutingType((ConnType)2);
+
+ ConnRef *connRef348 = new ConnRef(router, 348);
+ ConnEnd srcPt348(Point(629, 1101.05), 15);
+ connRef348->setSourceEndpoint(srcPt348);
+ ConnEnd dstPt348(Point(477.5, 1101.05), 8);
+ connRef348->setDestEndpoint(dstPt348);
+ connRef348->setRoutingType((ConnType)2);
+
+ ConnRef *connRef349 = new ConnRef(router, 349);
+ ConnEnd srcPt349(Point(1324, 1203.05), 15);
+ connRef349->setSourceEndpoint(srcPt349);
+ ConnEnd dstPt349(Point(1460.2, 1460.71), 4);
+ connRef349->setDestEndpoint(dstPt349);
+ connRef349->setRoutingType((ConnType)2);
+
+ ConnRef *connRef350 = new ConnRef(router, 350);
+ ConnEnd srcPt350(Point(1324, 1203.05), 15);
+ connRef350->setSourceEndpoint(srcPt350);
+ ConnEnd dstPt350(Point(1274, 1203.05), 8);
+ connRef350->setDestEndpoint(dstPt350);
+ connRef350->setRoutingType((ConnType)2);
+
+ ConnRef *connRef351 = new ConnRef(router, 351);
+ ConnEnd srcPt351(Point(1752.2, 1622.71), 2);
+ connRef351->setSourceEndpoint(srcPt351);
+ ConnEnd dstPt351(Point(1752.2, 1777.71), 15);
+ connRef351->setDestEndpoint(dstPt351);
+ connRef351->setRoutingType((ConnType)2);
+
+ ConnRef *connRef352 = new ConnRef(router, 352);
+ ConnEnd srcPt352(Point(1008.8, 1045.05), 8);
+ connRef352->setSourceEndpoint(srcPt352);
+ ConnEnd dstPt352(Point(1112, 1045.05), 15);
+ connRef352->setDestEndpoint(dstPt352);
+ connRef352->setRoutingType((ConnType)2);
+
+ ConnRef *connRef353 = new ConnRef(router, 353);
+ ConnEnd srcPt353(Point(399, 1295.05), 15);
+ connRef353->setSourceEndpoint(srcPt353);
+ ConnEnd dstPt353(Point(559, 1203.05), 4);
+ connRef353->setDestEndpoint(dstPt353);
+ connRef353->setRoutingType((ConnType)2);
+
+ ConnRef *connRef354 = new ConnRef(router, 354);
+ ConnEnd srcPt354(Point(399, 1295.05), 15);
+ connRef354->setSourceEndpoint(srcPt354);
+ ConnEnd dstPt354(Point(569, 1289.55), 2);
+ connRef354->setDestEndpoint(dstPt354);
+ connRef354->setRoutingType((ConnType)2);
+
+ ConnRef *connRef355 = new ConnRef(router, 355);
+ ConnEnd srcPt355(Point(407, 916.545), 1);
+ connRef355->setSourceEndpoint(srcPt355);
+ ConnEnd dstPt355(Point(220, 584.545), 15);
+ connRef355->setDestEndpoint(dstPt355);
+ connRef355->setRoutingType((ConnType)2);
+
+ ConnRef *connRef356 = new ConnRef(router, 356);
+ ConnEnd srcPt356(Point(220, 584.545), 15);
+ connRef356->setSourceEndpoint(srcPt356);
+ ConnEnd dstPt356(Point(170, 584.545), 8);
+ connRef356->setDestEndpoint(dstPt356);
+ connRef356->setRoutingType((ConnType)2);
+
+ ConnRef *connRef357 = new ConnRef(router, 357);
+ ConnEnd srcPt357(Point(1544.49, 1052.05), 15);
+ connRef357->setSourceEndpoint(srcPt357);
+ ConnEnd dstPt357(Point(1656.49, 869.545), 2);
+ connRef357->setDestEndpoint(dstPt357);
+ connRef357->setRoutingType((ConnType)2);
+
+ ConnRef *connRef358 = new ConnRef(router, 358);
+ ConnEnd srcPt358(Point(1488.53, 994.545), 8);
+ connRef358->setSourceEndpoint(srcPt358);
+ ConnEnd dstPt358(Point(1544.49, 1052.05), 15);
+ connRef358->setDestEndpoint(dstPt358);
+ connRef358->setRoutingType((ConnType)2);
+
+ ConnRef *connRef359 = new ConnRef(router, 359);
+ ConnEnd srcPt359(Point(1544.49, 1654.71), 15);
+ connRef359->setSourceEndpoint(srcPt359);
+ ConnEnd dstPt359(Point(1544.49, 1622.71), 2);
+ connRef359->setDestEndpoint(dstPt359);
+ connRef359->setRoutingType((ConnType)2);
+
+ ConnRef *connRef360 = new ConnRef(router, 360);
+ ConnEnd srcPt360(Point(344.2, 686.545), 8);
+ connRef360->setSourceEndpoint(srcPt360);
+ ConnEnd dstPt360(Point(629, 584.545), 15);
+ connRef360->setDestEndpoint(dstPt360);
+ connRef360->setRoutingType((ConnType)2);
+
+ ConnRef *connRef361 = new ConnRef(router, 361);
+ ConnEnd srcPt361(Point(339, 1245.05), 15);
+ connRef361->setSourceEndpoint(srcPt361);
+ ConnEnd dstPt361(Point(339, 1295.05), 15);
+ connRef361->setDestEndpoint(dstPt361);
+ connRef361->setRoutingType((ConnType)2);
+
+ ConnRef *connRef362 = new ConnRef(router, 362);
+ ConnEnd srcPt362(Point(339, 1153.05), 15);
+ connRef362->setSourceEndpoint(srcPt362);
+ ConnEnd dstPt362(Point(339, 1203.05), 15);
+ connRef362->setDestEndpoint(dstPt362);
+ connRef362->setRoutingType((ConnType)2);
+
+ ConnRef *connRef363 = new ConnRef(router, 363);
+ ConnEnd srcPt363(Point(73, 1149.05), 15);
+ connRef363->setSourceEndpoint(srcPt363);
+ ConnEnd dstPt363(Point(135, 1149.05), 15);
+ connRef363->setDestEndpoint(dstPt363);
+ connRef363->setRoutingType((ConnType)2);
+
+ ConnRef *connRef364 = new ConnRef(router, 364);
+ ConnEnd srcPt364(Point(1470.2, 688.545), 15);
+ connRef364->setSourceEndpoint(srcPt364);
+ ConnEnd dstPt364(Point(1470.2, 738.545), 15);
+ connRef364->setDestEndpoint(dstPt364);
+ connRef364->setRoutingType((ConnType)2);
+
+ ConnRef *connRef365 = new ConnRef(router, 365);
+ ConnEnd srcPt365(Point(518, 396), 15);
+ connRef365->setSourceEndpoint(srcPt365);
+ ConnEnd dstPt365(Point(518, 446), 15);
+ connRef365->setDestEndpoint(dstPt365);
+ connRef365->setRoutingType((ConnType)2);
+
+ ConnRef *connRef366 = new ConnRef(router, 366);
+ ConnEnd srcPt366(Point(334.2, 636.545), 15);
+ connRef366->setSourceEndpoint(srcPt366);
+ ConnEnd dstPt366(Point(334.2, 686.545), 15);
+ connRef366->setDestEndpoint(dstPt366);
+ connRef366->setRoutingType((ConnType)2);
+
+ ConnRef *connRef367 = new ConnRef(router, 367);
+ ConnEnd srcPt367(Point(191, 1099.05), 15);
+ connRef367->setSourceEndpoint(srcPt367);
+ ConnEnd dstPt367(Point(191, 1149.05), 15);
+ connRef367->setDestEndpoint(dstPt367);
+ connRef367->setRoutingType((ConnType)2);
+
+ ConnRef *connRef368 = new ConnRef(router, 368);
+ ConnEnd srcPt368(Point(396.2, 770.545), 15);
+ connRef368->setSourceEndpoint(srcPt368);
+ ConnEnd dstPt368(Point(334.2, 770.545), 15);
+ connRef368->setDestEndpoint(dstPt368);
+ connRef368->setRoutingType((ConnType)2);
+
+ ConnRef *connRef369 = new ConnRef(router, 369);
+ ConnEnd srcPt369(Point(396.2, 822.545), 15);
+ connRef369->setSourceEndpoint(srcPt369);
+ ConnEnd dstPt369(Point(334.2, 822.545), 15);
+ connRef369->setDestEndpoint(dstPt369);
+ connRef369->setRoutingType((ConnType)2);
+
+ ConnRef *connRef370 = new ConnRef(router, 370);
+ ConnEnd srcPt370(Point(396.2, 874.545), 15);
+ connRef370->setSourceEndpoint(srcPt370);
+ ConnEnd dstPt370(Point(334.2, 874.545), 15);
+ connRef370->setDestEndpoint(dstPt370);
+ connRef370->setRoutingType((ConnType)2);
+
+ ConnRef *connRef371 = new ConnRef(router, 371);
+ ConnEnd srcPt371(Point(467.5, 1051.05), 15);
+ connRef371->setSourceEndpoint(srcPt371);
+ ConnEnd dstPt371(Point(467.5, 1101.05), 15);
+ connRef371->setDestEndpoint(dstPt371);
+ connRef371->setRoutingType((ConnType)2);
+
+ ConnRef *connRef372 = new ConnRef(router, 372);
+ ConnEnd srcPt372(Point(586, 978.545), 15);
+ connRef372->setSourceEndpoint(srcPt372);
+ ConnEnd dstPt372(Point(586, 1028.55), 15);
+ connRef372->setDestEndpoint(dstPt372);
+ connRef372->setRoutingType((ConnType)2);
+
+ ConnRef *connRef373 = new ConnRef(router, 373);
+ ConnEnd srcPt373(Point(569, 1153.05), 15);
+ connRef373->setSourceEndpoint(srcPt373);
+ ConnEnd dstPt373(Point(569, 1203.05), 15);
+ connRef373->setDestEndpoint(dstPt373);
+ connRef373->setRoutingType((ConnType)2);
+
+ ConnRef *connRef374 = new ConnRef(router, 374);
+ ConnEnd srcPt374(Point(735, 396), 15);
+ connRef374->setSourceEndpoint(srcPt374);
+ ConnEnd dstPt374(Point(735, 446), 15);
+ connRef374->setDestEndpoint(dstPt374);
+ connRef374->setRoutingType((ConnType)2);
+
+ ConnRef *connRef375 = new ConnRef(router, 375);
+ ConnEnd srcPt375(Point(861, 396), 15);
+ connRef375->setSourceEndpoint(srcPt375);
+ ConnEnd dstPt375(Point(861, 446), 15);
+ connRef375->setDestEndpoint(dstPt375);
+ connRef375->setRoutingType((ConnType)2);
+
+ ConnRef *connRef376 = new ConnRef(router, 376);
+ ConnEnd srcPt376(Point(518, 534.545), 15);
+ connRef376->setSourceEndpoint(srcPt376);
+ ConnEnd dstPt376(Point(518, 584.545), 15);
+ connRef376->setDestEndpoint(dstPt376);
+ connRef376->setRoutingType((ConnType)2);
+
+ ConnRef *connRef377 = new ConnRef(router, 377);
+ ConnEnd srcPt377(Point(792.5, 772.545), 15);
+ connRef377->setSourceEndpoint(srcPt377);
+ ConnEnd dstPt377(Point(792.5, 822.545), 15);
+ connRef377->setDestEndpoint(dstPt377);
+ connRef377->setRoutingType((ConnType)2);
+
+ ConnRef *connRef378 = new ConnRef(router, 378);
+ ConnEnd srcPt378(Point(797, 978.545), 15);
+ connRef378->setSourceEndpoint(srcPt378);
+ ConnEnd dstPt378(Point(797, 1028.55), 15);
+ connRef378->setDestEndpoint(dstPt378);
+ connRef378->setRoutingType((ConnType)2);
+
+ ConnRef *connRef379 = new ConnRef(router, 379);
+ ConnEnd srcPt379(Point(841, 1123.55), 15);
+ connRef379->setSourceEndpoint(srcPt379);
+ ConnEnd dstPt379(Point(779, 1123.55), 15);
+ connRef379->setDestEndpoint(dstPt379);
+ connRef379->setRoutingType((ConnType)2);
+
+ ConnRef *connRef380 = new ConnRef(router, 380);
+ ConnEnd srcPt380(Point(792.5, 636.545), 15);
+ connRef380->setSourceEndpoint(srcPt380);
+ ConnEnd dstPt380(Point(792.5, 686.545), 15);
+ connRef380->setDestEndpoint(dstPt380);
+ connRef380->setRoutingType((ConnType)2);
+
+ ConnRef *connRef381 = new ConnRef(router, 381);
+ ConnEnd srcPt381(Point(799, 1175.55), 15);
+ connRef381->setSourceEndpoint(srcPt381);
+ ConnEnd dstPt381(Point(861, 1175.55), 15);
+ connRef381->setDestEndpoint(dstPt381);
+ connRef381->setRoutingType((ConnType)2);
+
+ ConnRef *connRef382 = new ConnRef(router, 382);
+ ConnEnd srcPt382(Point(870, 1410.71), 15);
+ connRef382->setSourceEndpoint(srcPt382);
+ ConnEnd dstPt382(Point(870, 1460.71), 15);
+ connRef382->setDestEndpoint(dstPt382);
+ connRef382->setRoutingType((ConnType)2);
+
+ ConnRef *connRef383 = new ConnRef(router, 383);
+ ConnEnd srcPt383(Point(754, 1543.71), 15);
+ connRef383->setSourceEndpoint(srcPt383);
+ ConnEnd dstPt383(Point(754, 1593.71), 15);
+ connRef383->setDestEndpoint(dstPt383);
+ connRef383->setRoutingType((ConnType)2);
+
+ ConnRef *connRef384 = new ConnRef(router, 384);
+ ConnEnd srcPt384(Point(826, 1676.71), 15);
+ connRef384->setSourceEndpoint(srcPt384);
+ ConnEnd dstPt384(Point(826, 1626.71), 15);
+ connRef384->setDestEndpoint(dstPt384);
+ connRef384->setRoutingType((ConnType)2);
+
+ ConnRef *connRef385 = new ConnRef(router, 385);
+ ConnEnd srcPt385(Point(987, 260), 15);
+ connRef385->setSourceEndpoint(srcPt385);
+ ConnEnd dstPt385(Point(925, 260), 15);
+ connRef385->setDestEndpoint(dstPt385);
+ connRef385->setRoutingType((ConnType)2);
+
+ ConnRef *connRef386 = new ConnRef(router, 386);
+ ConnEnd srcPt386(Point(987, 344), 15);
+ connRef386->setSourceEndpoint(srcPt386);
+ ConnEnd dstPt386(Point(925, 344), 15);
+ connRef386->setDestEndpoint(dstPt386);
+ connRef386->setRoutingType((ConnType)2);
+
+ ConnRef *connRef387 = new ConnRef(router, 387);
+ ConnEnd srcPt387(Point(987, 679.045), 15);
+ connRef387->setSourceEndpoint(srcPt387);
+ ConnEnd dstPt387(Point(925, 679.045), 15);
+ connRef387->setDestEndpoint(dstPt387);
+ connRef387->setRoutingType((ConnType)2);
+
+ ConnRef *connRef388 = new ConnRef(router, 388);
+ ConnEnd srcPt388(Point(987, 932.545), 15);
+ connRef388->setSourceEndpoint(srcPt388);
+ ConnEnd dstPt388(Point(925, 932.545), 15);
+ connRef388->setDestEndpoint(dstPt388);
+ connRef388->setRoutingType((ConnType)2);
+
+ ConnRef *connRef389 = new ConnRef(router, 389);
+ ConnEnd srcPt389(Point(985, 65), 15);
+ connRef389->setSourceEndpoint(srcPt389);
+ ConnEnd dstPt389(Point(985, 115), 15);
+ connRef389->setDestEndpoint(dstPt389);
+ connRef389->setRoutingType((ConnType)2);
+
+ ConnRef *connRef390 = new ConnRef(router, 390);
+ ConnEnd srcPt390(Point(990, 396), 15);
+ connRef390->setSourceEndpoint(srcPt390);
+ ConnEnd dstPt390(Point(990, 446), 15);
+ connRef390->setDestEndpoint(dstPt390);
+ connRef390->setRoutingType((ConnType)2);
+
+ ConnRef *connRef391 = new ConnRef(router, 391);
+ ConnEnd srcPt391(Point(1172, 396), 15);
+ connRef391->setSourceEndpoint(srcPt391);
+ ConnEnd dstPt391(Point(1172, 446), 15);
+ connRef391->setDestEndpoint(dstPt391);
+ connRef391->setRoutingType((ConnType)2);
+
+ ConnRef *connRef392 = new ConnRef(router, 392);
+ ConnEnd srcPt392(Point(1152, 710.379), 15);
+ connRef392->setSourceEndpoint(srcPt392);
+ ConnEnd dstPt392(Point(1152, 760.379), 15);
+ connRef392->setDestEndpoint(dstPt392);
+ connRef392->setRoutingType((ConnType)2);
+
+ ConnRef *connRef393 = new ConnRef(router, 393);
+ ConnEnd srcPt393(Point(1160, 822.545), 15);
+ connRef393->setSourceEndpoint(srcPt393);
+ ConnEnd dstPt393(Point(1098, 822.545), 15);
+ connRef393->setDestEndpoint(dstPt393);
+ connRef393->setRoutingType((ConnType)2);
+
+ ConnRef *connRef394 = new ConnRef(router, 394);
+ ConnEnd srcPt394(Point(1032, 1107.21), 15);
+ connRef394->setSourceEndpoint(srcPt394);
+ ConnEnd dstPt394(Point(970, 1107.21), 15);
+ connRef394->setDestEndpoint(dstPt394);
+ connRef394->setRoutingType((ConnType)2);
+
+ ConnRef *connRef395 = new ConnRef(router, 395);
+ ConnEnd srcPt395(Point(1000.8, 1629.71), 15);
+ connRef395->setSourceEndpoint(srcPt395);
+ ConnEnd dstPt395(Point(938.8, 1629.71), 15);
+ connRef395->setDestEndpoint(dstPt395);
+ connRef395->setRoutingType((ConnType)2);
+
+ ConnRef *connRef396 = new ConnRef(router, 396);
+ ConnEnd srcPt396(Point(758, 1635.71), 15);
+ connRef396->setSourceEndpoint(srcPt396);
+ ConnEnd dstPt396(Point(758, 1685.71), 15);
+ connRef396->setDestEndpoint(dstPt396);
+ connRef396->setRoutingType((ConnType)2);
+
+ ConnRef *connRef397 = new ConnRef(router, 397);
+ ConnEnd srcPt397(Point(758, 1727.71), 15);
+ connRef397->setSourceEndpoint(srcPt397);
+ ConnEnd dstPt397(Point(758, 1777.71), 15);
+ connRef397->setDestEndpoint(dstPt397);
+ connRef397->setRoutingType((ConnType)2);
+
+ ConnRef *connRef398 = new ConnRef(router, 398);
+ ConnEnd srcPt398(Point(758, 1859.71), 15);
+ connRef398->setSourceEndpoint(srcPt398);
+ ConnEnd dstPt398(Point(758, 1809.71), 15);
+ connRef398->setDestEndpoint(dstPt398);
+ connRef398->setRoutingType((ConnType)2);
+
+ ConnRef *connRef399 = new ConnRef(router, 399);
+ ConnEnd srcPt399(Point(1000.8, 1809.71), 15);
+ connRef399->setSourceEndpoint(srcPt399);
+ ConnEnd dstPt399(Point(938.8, 1809.71), 15);
+ connRef399->setDestEndpoint(dstPt399);
+ connRef399->setRoutingType((ConnType)2);
+
+ ConnRef *connRef400 = new ConnRef(router, 400);
+ ConnEnd srcPt400(Point(1166, 1562.71), 15);
+ connRef400->setSourceEndpoint(srcPt400);
+ ConnEnd dstPt400(Point(1228, 1562.71), 15);
+ connRef400->setDestEndpoint(dstPt400);
+ connRef400->setRoutingType((ConnType)2);
+
+ ConnRef *connRef401 = new ConnRef(router, 401);
+ ConnEnd srcPt401(Point(1228, 1510.71), 15);
+ connRef401->setSourceEndpoint(srcPt401);
+ ConnEnd dstPt401(Point(1228, 1460.71), 15);
+ connRef401->setDestEndpoint(dstPt401);
+ connRef401->setRoutingType((ConnType)2);
+
+ ConnRef *connRef402 = new ConnRef(router, 402);
+ ConnEnd srcPt402(Point(1402.2, 682.045), 15);
+ connRef402->setSourceEndpoint(srcPt402);
+ ConnEnd dstPt402(Point(1340.2, 682.045), 15);
+ connRef402->setDestEndpoint(dstPt402);
+ connRef402->setRoutingType((ConnType)2);
+
+ ConnRef *connRef403 = new ConnRef(router, 403);
+ ConnEnd srcPt403(Point(1417.33, 1101.05), 15);
+ connRef403->setSourceEndpoint(srcPt403);
+ ConnEnd dstPt403(Point(1355.33, 1101.05), 15);
+ connRef403->setDestEndpoint(dstPt403);
+ connRef403->setRoutingType((ConnType)2);
+
+ ConnRef *connRef404 = new ConnRef(router, 404);
+ ConnEnd srcPt404(Point(1530.2, 402.545), 15);
+ connRef404->setSourceEndpoint(srcPt404);
+ ConnEnd dstPt404(Point(1530.2, 452.545), 15);
+ connRef404->setDestEndpoint(dstPt404);
+ connRef404->setRoutingType((ConnType)2);
+
+ ConnRef *connRef405 = new ConnRef(router, 405);
+ ConnEnd srcPt405(Point(1530.2, 494.545), 15);
+ connRef405->setSourceEndpoint(srcPt405);
+ ConnEnd dstPt405(Point(1530.2, 544.545), 15);
+ connRef405->setDestEndpoint(dstPt405);
+ connRef405->setRoutingType((ConnType)2);
+
+ ConnRef *connRef406 = new ConnRef(router, 406);
+ ConnEnd srcPt406(Point(1470.2, 820.545), 15);
+ connRef406->setSourceEndpoint(srcPt406);
+ ConnEnd dstPt406(Point(1470.2, 770.545), 15);
+ connRef406->setDestEndpoint(dstPt406);
+ connRef406->setRoutingType((ConnType)2);
+
+ ConnRef *connRef407 = new ConnRef(router, 407);
+ ConnEnd srcPt407(Point(1530.2, 586.545), 15);
+ connRef407->setSourceEndpoint(srcPt407);
+ ConnEnd dstPt407(Point(1530.2, 636.545), 15);
+ connRef407->setDestEndpoint(dstPt407);
+ connRef407->setRoutingType((ConnType)2);
+
+ ConnRef *connRef408 = new ConnRef(router, 408);
+ ConnEnd srcPt408(Point(1606.49, 859.545), 15);
+ connRef408->setSourceEndpoint(srcPt408);
+ ConnEnd dstPt408(Point(1544.49, 859.545), 15);
+ connRef408->setDestEndpoint(dstPt408);
+ connRef408->setRoutingType((ConnType)2);
+
+ ConnRef *connRef409 = new ConnRef(router, 409);
+ ConnEnd srcPt409(Point(1718.49, 859.545), 15);
+ connRef409->setSourceEndpoint(srcPt409);
+ ConnEnd dstPt409(Point(1656.49, 859.545), 15);
+ connRef409->setDestEndpoint(dstPt409);
+ connRef409->setRoutingType((ConnType)2);
+
+ ConnRef *connRef410 = new ConnRef(router, 410);
+ ConnEnd srcPt410(Point(1470.2, 1153.05), 15);
+ connRef410->setSourceEndpoint(srcPt410);
+ ConnEnd dstPt410(Point(1470.2, 1203.05), 15);
+ connRef410->setDestEndpoint(dstPt410);
+ connRef410->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/freeFloatingDirection01");
+ assert(connRef239->displayRoute().size() == 4);
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/hola01.cpp b/src/3rdparty/adaptagrams/libavoid/tests/hola01.cpp
new file mode 100644
index 0000000..d3487bd
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/hola01.cpp
@@ -0,0 +1,1006 @@
+// Regression test exercises a problem with nudging that would result in the
+// following assertion if a sub-problem was unsatisfiable because the right
+// channel edge but not the left had moved.
+// Assertion failed: (unsatisfiedRanges.size() > 0)
+// Reported by Steve Kieffer and Tobias Czauderna.
+//
+// Problem happens if EDGE128 is defined.
+
+#include "libavoid/libavoid.h"
+
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingParameter((RoutingParameter)0, 30);
+ router->setRoutingParameter((RoutingParameter)1, 0);
+ router->setRoutingParameter((RoutingParameter)2, 120);
+ router->setRoutingParameter((RoutingParameter)3, 4000);
+ router->setRoutingParameter((RoutingParameter)4, 0);
+ router->setRoutingParameter((RoutingParameter)5, 0);
+ router->setRoutingParameter((RoutingParameter)6, 7.5);
+ router->setRoutingParameter((RoutingParameter)7, 4);
+ router->setRoutingParameter((RoutingParameter)8, 0);
+ router->setRoutingOption((RoutingOption)0, false);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, false);
+ router->setRoutingOption((RoutingOption)3, false);
+ router->setRoutingOption((RoutingOption)4, true);
+ router->setRoutingOption((RoutingOption)5, false);
+ router->setRoutingOption((RoutingOption)6, false);
+ Polygon polygon;
+ ConnRef *connRef = nullptr;
+ ConnEnd srcPt;
+ ConnEnd dstPt;
+ ConnEnd heConnPt;
+ PolyLine newRoute;
+ ShapeConnectionPin *connPin = nullptr;
+
+ // shapeRef1
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(274.03, 356.334);
+ polygon.ps[1] = Point(304.03, 356.334);
+ polygon.ps[2] = Point(304.03, 386.334);
+ polygon.ps[3] = Point(274.03, 386.334);
+ new ShapeRef(router, polygon, 1);
+
+ // shapeRef1
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(214.034, 356.334);
+ polygon.ps[1] = Point(244.034, 356.334);
+ polygon.ps[2] = Point(244.034, 386.334);
+ polygon.ps[3] = Point(214.034, 386.334);
+ new ShapeRef(router, polygon, 1);
+
+ // shapeRef2
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(214.034, 439.168);
+ polygon.ps[1] = Point(244.034, 439.168);
+ polygon.ps[2] = Point(244.034, 469.168);
+ polygon.ps[3] = Point(214.034, 469.168);
+ new ShapeRef(router, polygon, 2);
+
+ // shapeRef3
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(354.024, 416.334);
+ polygon.ps[1] = Point(384.024, 416.334);
+ polygon.ps[2] = Point(384.024, 446.334);
+ polygon.ps[3] = Point(354.024, 446.334);
+ new ShapeRef(router, polygon, 3);
+
+ // shapeRef4
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(274.03, 276.334);
+ polygon.ps[1] = Point(304.03, 276.334);
+ polygon.ps[2] = Point(304.03, 306.334);
+ polygon.ps[3] = Point(274.03, 306.334);
+ new ShapeRef(router, polygon, 4);
+
+ // shapeRef5
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(534.011, 276.334);
+ polygon.ps[1] = Point(564.011, 276.334);
+ polygon.ps[2] = Point(564.011, 306.334);
+ polygon.ps[3] = Point(534.011, 306.334);
+ new ShapeRef(router, polygon, 5);
+
+ // shapeRef6
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(414.023, 416.334);
+ polygon.ps[1] = Point(444.023, 416.334);
+ polygon.ps[2] = Point(444.023, 446.334);
+ polygon.ps[3] = Point(414.023, 446.334);
+ new ShapeRef(router, polygon, 6);
+
+ // shapeRef7
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(594.052, 276.334);
+ polygon.ps[1] = Point(624.052, 276.334);
+ polygon.ps[2] = Point(624.052, 306.334);
+ polygon.ps[3] = Point(594.052, 306.334);
+ new ShapeRef(router, polygon, 7);
+
+ // shapeRef8
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(254.052, 386.334);
+ polygon.ps[1] = Point(284.052, 386.334);
+ polygon.ps[2] = Point(284.052, 416.334);
+ polygon.ps[3] = Point(254.052, 416.334);
+ new ShapeRef(router, polygon, 8);
+
+ // shapeRef9
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(474.011, 416.334);
+ polygon.ps[1] = Point(504.011, 416.334);
+ polygon.ps[2] = Point(504.011, 446.334);
+ polygon.ps[3] = Point(474.011, 446.334);
+ new ShapeRef(router, polygon, 9);
+
+ // shapeRef10
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(274.03, 76.3341);
+ polygon.ps[1] = Point(304.03, 76.3341);
+ polygon.ps[2] = Point(304.03, 106.334);
+ polygon.ps[3] = Point(274.03, 106.334);
+ new ShapeRef(router, polygon, 10);
+
+ // shapeRef11
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(354.034, 536.334);
+ polygon.ps[1] = Point(384.034, 536.334);
+ polygon.ps[2] = Point(384.034, 566.334);
+ polygon.ps[3] = Point(354.034, 566.334);
+ new ShapeRef(router, polygon, 11);
+
+ // shapeRef12
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(414.023, 476.334);
+ polygon.ps[1] = Point(444.023, 476.334);
+ polygon.ps[2] = Point(444.023, 506.334);
+ polygon.ps[3] = Point(414.023, 506.334);
+ new ShapeRef(router, polygon, 12);
+
+ // shapeRef13
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(354.034, 596.334);
+ polygon.ps[1] = Point(384.034, 596.334);
+ polygon.ps[2] = Point(384.034, 626.334);
+ polygon.ps[3] = Point(354.034, 626.334);
+ new ShapeRef(router, polygon, 13);
+
+ // shapeRef14
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(274.03, 446.334);
+ polygon.ps[1] = Point(304.03, 446.334);
+ polygon.ps[2] = Point(304.03, 476.334);
+ polygon.ps[3] = Point(274.03, 476.334);
+ new ShapeRef(router, polygon, 14);
+
+ // shapeRef15
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(131.696, 276.334);
+ polygon.ps[1] = Point(161.696, 276.334);
+ polygon.ps[2] = Point(161.696, 306.334);
+ polygon.ps[3] = Point(131.696, 306.334);
+ new ShapeRef(router, polygon, 15);
+
+ // shapeRef16
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(564.023, 416.334);
+ polygon.ps[1] = Point(594.023, 416.334);
+ polygon.ps[2] = Point(594.023, 446.334);
+ polygon.ps[3] = Point(564.023, 446.334);
+ new ShapeRef(router, polygon, 16);
+
+ // shapeRef17
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8.56882, 276.334);
+ polygon.ps[1] = Point(38.5688, 276.334);
+ polygon.ps[2] = Point(38.5688, 306.334);
+ polygon.ps[3] = Point(8.56882, 306.334);
+ new ShapeRef(router, polygon, 17);
+
+ // shapeRef18
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(474.011, 216.334);
+ polygon.ps[1] = Point(504.011, 216.334);
+ polygon.ps[2] = Point(504.011, 246.334);
+ polygon.ps[3] = Point(474.011, 246.334);
+ new ShapeRef(router, polygon, 18);
+
+ // shapeRef19
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(474.011, 156.334);
+ polygon.ps[1] = Point(504.011, 156.334);
+ polygon.ps[2] = Point(504.011, 186.334);
+ polygon.ps[3] = Point(474.011, 186.334);
+ new ShapeRef(router, polygon, 19);
+
+ // shapeRef20
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(534.011, 216.334);
+ polygon.ps[1] = Point(564.011, 216.334);
+ polygon.ps[2] = Point(564.011, 246.334);
+ polygon.ps[3] = Point(534.011, 246.334);
+ new ShapeRef(router, polygon, 20);
+
+ // shapeRef21
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(474.011, 96.3341);
+ polygon.ps[1] = Point(504.011, 96.3341);
+ polygon.ps[2] = Point(504.011, 126.334);
+ polygon.ps[3] = Point(474.011, 126.334);
+ new ShapeRef(router, polygon, 21);
+
+ // shapeRef22
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(334.035, 356.334);
+ polygon.ps[1] = Point(364.035, 356.334);
+ polygon.ps[2] = Point(364.035, 386.334);
+ polygon.ps[3] = Point(334.035, 386.334);
+ new ShapeRef(router, polygon, 22);
+
+ // shapeRef23
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(414.023, 536.334);
+ polygon.ps[1] = Point(444.023, 536.334);
+ polygon.ps[2] = Point(444.023, 566.334);
+ polygon.ps[3] = Point(414.023, 566.334);
+ new ShapeRef(router, polygon, 23);
+
+ // shapeRef25
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(564.052, 180.582);
+ polygon.ps[1] = Point(594.052, 180.582);
+ polygon.ps[2] = Point(594.052, 210.582);
+ polygon.ps[3] = Point(564.052, 210.582);
+ new ShapeRef(router, polygon, 25);
+
+ // shapeRef26
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(154.041, 476.334);
+ polygon.ps[1] = Point(184.041, 476.334);
+ polygon.ps[2] = Point(184.041, 506.334);
+ polygon.ps[3] = Point(154.041, 506.334);
+ new ShapeRef(router, polygon, 26);
+
+ // shapeRef27
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(474.011, 300.457);
+ polygon.ps[1] = Point(504.011, 300.457);
+ polygon.ps[2] = Point(504.011, 330.457);
+ polygon.ps[3] = Point(474.011, 330.457);
+ new ShapeRef(router, polygon, 27);
+
+ // shapeRef28
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(134.045, 306.334);
+ polygon.ps[1] = Point(164.045, 306.334);
+ polygon.ps[2] = Point(164.045, 336.334);
+ polygon.ps[3] = Point(134.045, 336.334);
+ new ShapeRef(router, polygon, 28);
+
+ // shapeRef29
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(254.039, 216.334);
+ polygon.ps[1] = Point(284.039, 216.334);
+ polygon.ps[2] = Point(284.039, 246.334);
+ polygon.ps[3] = Point(254.039, 246.334);
+ new ShapeRef(router, polygon, 29);
+
+ // shapeRef30
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(134.045, 386.334);
+ polygon.ps[1] = Point(164.045, 386.334);
+ polygon.ps[2] = Point(164.045, 416.334);
+ polygon.ps[3] = Point(134.045, 416.334);
+ new ShapeRef(router, polygon, 30);
+
+ // shapeRef31
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(74.0462, 386.334);
+ polygon.ps[1] = Point(104.046, 386.334);
+ polygon.ps[2] = Point(104.046, 416.334);
+ polygon.ps[3] = Point(74.0462, 416.334);
+ new ShapeRef(router, polygon, 31);
+
+ // shapeRef32
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(594.052, 596.334);
+ polygon.ps[1] = Point(624.052, 596.334);
+ polygon.ps[2] = Point(624.052, 626.334);
+ polygon.ps[3] = Point(594.052, 626.334);
+ new ShapeRef(router, polygon, 32);
+
+ // shapeRef34
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(154.041, 356.334);
+ polygon.ps[1] = Point(184.041, 356.334);
+ polygon.ps[2] = Point(184.041, 386.334);
+ polygon.ps[3] = Point(154.041, 386.334);
+ new ShapeRef(router, polygon, 34);
+
+ // shapeRef35
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(474.011, 36.3341);
+ polygon.ps[1] = Point(504.011, 36.3341);
+ polygon.ps[2] = Point(504.011, 66.3341);
+ polygon.ps[3] = Point(474.011, 66.3341);
+ new ShapeRef(router, polygon, 35);
+
+ // shapeRef38
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(534.011, 386.334);
+ polygon.ps[1] = Point(564.011, 386.334);
+ polygon.ps[2] = Point(564.011, 416.334);
+ polygon.ps[3] = Point(534.011, 416.334);
+ new ShapeRef(router, polygon, 38);
+
+ // shapeRef39
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(564.023, 343.278);
+ polygon.ps[1] = Point(594.023, 343.278);
+ polygon.ps[2] = Point(594.023, 373.278);
+ polygon.ps[3] = Point(564.023, 373.278);
+ new ShapeRef(router, polygon, 39);
+
+ // shapeRef40
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(74.0462, 156.334);
+ polygon.ps[1] = Point(104.046, 156.334);
+ polygon.ps[2] = Point(104.046, 186.334);
+ polygon.ps[3] = Point(74.0462, 186.334);
+ new ShapeRef(router, polygon, 40);
+
+ // shapeRef41
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(214.034, 76.3341);
+ polygon.ps[1] = Point(244.034, 76.3341);
+ polygon.ps[2] = Point(244.034, 106.334);
+ polygon.ps[3] = Point(214.034, 106.334);
+ new ShapeRef(router, polygon, 41);
+
+ // shapeRef42
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(334.035, 136.334);
+ polygon.ps[1] = Point(364.035, 136.334);
+ polygon.ps[2] = Point(364.035, 166.334);
+ polygon.ps[3] = Point(334.035, 166.334);
+ new ShapeRef(router, polygon, 42);
+
+ // shapeRef45
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(354.024, 300.457);
+ polygon.ps[1] = Point(384.024, 300.457);
+ polygon.ps[2] = Point(384.024, 330.457);
+ polygon.ps[3] = Point(354.024, 330.457);
+ new ShapeRef(router, polygon, 45);
+
+ // shapeRef46
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(154.041, 416.334);
+ polygon.ps[1] = Point(184.041, 416.334);
+ polygon.ps[2] = Point(184.041, 446.334);
+ polygon.ps[3] = Point(154.041, 446.334);
+ new ShapeRef(router, polygon, 46);
+
+ // shapeRef47
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(214.034, 136.334);
+ polygon.ps[1] = Point(244.034, 136.334);
+ polygon.ps[2] = Point(244.034, 166.334);
+ polygon.ps[3] = Point(214.034, 166.334);
+ new ShapeRef(router, polygon, 47);
+
+ // shapeRef48
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(214.034, 296.334);
+ polygon.ps[1] = Point(244.034, 296.334);
+ polygon.ps[2] = Point(244.034, 326.334);
+ polygon.ps[3] = Point(214.034, 326.334);
+ new ShapeRef(router, polygon, 48);
+
+ // shapeRef50
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(74.0462, 296.334);
+ polygon.ps[1] = Point(104.046, 296.334);
+ polygon.ps[2] = Point(104.046, 326.334);
+ polygon.ps[3] = Point(74.0462, 326.334);
+ new ShapeRef(router, polygon, 50);
+
+ // shapeRef51
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(354.024, 36.3341);
+ polygon.ps[1] = Point(384.024, 36.3341);
+ polygon.ps[2] = Point(384.024, 66.3341);
+ polygon.ps[3] = Point(354.024, 66.3341);
+ new ShapeRef(router, polygon, 51);
+
+ // shapeRef53
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(354.024, 180.582);
+ polygon.ps[1] = Point(384.024, 180.582);
+ polygon.ps[2] = Point(384.024, 210.582);
+ polygon.ps[3] = Point(354.024, 210.582);
+ new ShapeRef(router, polygon, 53);
+
+ // shapeRef54
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(534.011, 596.334);
+ polygon.ps[1] = Point(564.011, 596.334);
+ polygon.ps[2] = Point(564.011, 626.334);
+ polygon.ps[3] = Point(534.011, 626.334);
+ new ShapeRef(router, polygon, 54);
+
+ // shapeRef55
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8.56882, 156.334);
+ polygon.ps[1] = Point(38.5688, 156.334);
+ polygon.ps[2] = Point(38.5688, 186.334);
+ polygon.ps[3] = Point(8.56882, 186.334);
+ new ShapeRef(router, polygon, 55);
+
+ // shapeRef57
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(281.314, 476.334);
+ polygon.ps[1] = Point(311.314, 476.334);
+ polygon.ps[2] = Point(311.314, 506.334);
+ polygon.ps[3] = Point(281.314, 506.334);
+ new ShapeRef(router, polygon, 57);
+
+ // shapeRef58
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(254.039, 312.99);
+ polygon.ps[1] = Point(284.039, 312.99);
+ polygon.ps[2] = Point(284.039, 342.99);
+ polygon.ps[3] = Point(254.039, 342.99);
+ new ShapeRef(router, polygon, 58);
+
+ // connRef59
+ connRef = new ConnRef(router, 59);
+ srcPt = ConnEnd(Point(229.034, 371.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(289.03, 371.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef60
+ connRef = new ConnRef(router, 60);
+ srcPt = ConnEnd(Point(169.041, 491.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(169.041, 431.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef61
+ connRef = new ConnRef(router, 61);
+ srcPt = ConnEnd(Point(369.024, 315.457), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(369.024, 431.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef62
+ connRef = new ConnRef(router, 62);
+ srcPt = ConnEnd(Point(23.5688, 291.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(23.5688, 171.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef63
+ connRef = new ConnRef(router, 63);
+ srcPt = ConnEnd(Point(429.023, 551.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(429.023, 491.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef64
+ connRef = new ConnRef(router, 64);
+ srcPt = ConnEnd(Point(549.011, 611.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(369.034, 611.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef65
+ connRef = new ConnRef(router, 65);
+ srcPt = ConnEnd(Point(369.024, 431.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(229.034, 454.168), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef66
+ connRef = new ConnRef(router, 66);
+ srcPt = ConnEnd(Point(429.023, 551.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(579.023, 431.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef67
+ connRef = new ConnRef(router, 67);
+ srcPt = ConnEnd(Point(489.011, 231.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(269.039, 231.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef68
+ connRef = new ConnRef(router, 68);
+ srcPt = ConnEnd(Point(369.034, 551.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(429.023, 551.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef69
+ connRef = new ConnRef(router, 69);
+ srcPt = ConnEnd(Point(169.041, 371.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(149.045, 401.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef70
+ connRef = new ConnRef(router, 70);
+ srcPt = ConnEnd(Point(169.041, 491.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(229.034, 371.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef71
+ connRef = new ConnRef(router, 71);
+ srcPt = ConnEnd(Point(149.045, 401.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(149.045, 321.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef72
+ connRef = new ConnRef(router, 72);
+ srcPt = ConnEnd(Point(489.011, 231.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(549.011, 291.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef73
+ connRef = new ConnRef(router, 73);
+ srcPt = ConnEnd(Point(229.034, 91.3341), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(289.03, 91.3341), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef74
+ connRef = new ConnRef(router, 74);
+ srcPt = ConnEnd(Point(369.024, 315.457), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(369.024, 195.582), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef75
+ connRef = new ConnRef(router, 75);
+ srcPt = ConnEnd(Point(489.011, 171.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.011, 231.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef76
+ connRef = new ConnRef(router, 76);
+ srcPt = ConnEnd(Point(146.696, 291.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(289.03, 291.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef77
+ connRef = new ConnRef(router, 77);
+ srcPt = ConnEnd(Point(23.5688, 291.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(146.696, 291.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef78
+ connRef = new ConnRef(router, 78);
+ srcPt = ConnEnd(Point(609.052, 611.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(289.03, 461.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef79
+ connRef = new ConnRef(router, 79);
+ srcPt = ConnEnd(Point(489.011, 431.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(429.023, 431.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef80
+ connRef = new ConnRef(router, 80);
+ srcPt = ConnEnd(Point(489.011, 315.457), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.011, 231.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef81
+ connRef = new ConnRef(router, 81);
+ srcPt = ConnEnd(Point(229.034, 371.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(169.041, 371.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef82
+ connRef = new ConnRef(router, 82);
+ srcPt = ConnEnd(Point(489.011, 431.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.011, 315.457), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef83
+ connRef = new ConnRef(router, 83);
+ srcPt = ConnEnd(Point(89.0462, 171.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.011, 171.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef84
+ connRef = new ConnRef(router, 84);
+ srcPt = ConnEnd(Point(229.034, 151.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(229.034, 91.3341), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef85
+ connRef = new ConnRef(router, 85);
+ srcPt = ConnEnd(Point(289.03, 91.3341), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(289.03, 291.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef86
+ connRef = new ConnRef(router, 86);
+ srcPt = ConnEnd(Point(89.0462, 311.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(89.0462, 171.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef87
+ connRef = new ConnRef(router, 87);
+ srcPt = ConnEnd(Point(149.045, 321.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.011, 171.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef88
+ connRef = new ConnRef(router, 88);
+ srcPt = ConnEnd(Point(489.011, 315.457), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(609.052, 291.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef89
+ connRef = new ConnRef(router, 89);
+ srcPt = ConnEnd(Point(369.024, 195.582), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(369.024, 51.3341), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef90
+ connRef = new ConnRef(router, 90);
+ srcPt = ConnEnd(Point(289.03, 461.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(289.03, 371.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef91
+ connRef = new ConnRef(router, 91);
+ srcPt = ConnEnd(Point(296.314, 491.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(429.023, 491.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef92
+ connRef = new ConnRef(router, 92);
+ srcPt = ConnEnd(Point(369.034, 611.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(369.034, 551.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef93
+ connRef = new ConnRef(router, 93);
+ srcPt = ConnEnd(Point(609.052, 291.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(549.011, 291.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef94
+ connRef = new ConnRef(router, 94);
+ srcPt = ConnEnd(Point(579.023, 431.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(579.023, 358.278), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef95
+ connRef = new ConnRef(router, 95);
+ srcPt = ConnEnd(Point(549.011, 231.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(549.011, 291.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef96
+ connRef = new ConnRef(router, 96);
+ srcPt = ConnEnd(Point(579.052, 195.582), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(549.011, 291.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef97
+ connRef = new ConnRef(router, 97);
+ srcPt = ConnEnd(Point(489.011, 231.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(549.011, 231.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef98
+ connRef = new ConnRef(router, 98);
+ srcPt = ConnEnd(Point(549.011, 291.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(289.03, 291.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef99
+ connRef = new ConnRef(router, 99);
+ srcPt = ConnEnd(Point(149.045, 401.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(269.052, 401.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef100
+ connRef = new ConnRef(router, 100);
+ srcPt = ConnEnd(Point(579.023, 431.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.011, 431.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef101
+ connRef = new ConnRef(router, 101);
+ srcPt = ConnEnd(Point(229.034, 454.168), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(229.034, 371.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef102
+ connRef = new ConnRef(router, 102);
+ srcPt = ConnEnd(Point(489.011, 111.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.011, 171.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef103
+ connRef = new ConnRef(router, 103);
+ srcPt = ConnEnd(Point(369.024, 315.457), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.011, 315.457), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef104
+ connRef = new ConnRef(router, 104);
+ srcPt = ConnEnd(Point(349.035, 371.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.011, 111.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef105
+ connRef = new ConnRef(router, 105);
+ srcPt = ConnEnd(Point(429.023, 431.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(289.03, 291.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef106
+ connRef = new ConnRef(router, 106);
+ srcPt = ConnEnd(Point(269.039, 231.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(349.035, 371.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef107
+ connRef = new ConnRef(router, 107);
+ srcPt = ConnEnd(Point(289.03, 371.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(349.035, 371.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef108
+ connRef = new ConnRef(router, 108);
+ srcPt = ConnEnd(Point(579.023, 358.278), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(549.011, 291.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef109
+ connRef = new ConnRef(router, 109);
+ srcPt = ConnEnd(Point(429.023, 431.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(369.024, 431.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef110
+ connRef = new ConnRef(router, 110);
+ srcPt = ConnEnd(Point(369.024, 51.3341), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.011, 51.3341), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef111
+ connRef = new ConnRef(router, 111);
+ srcPt = ConnEnd(Point(296.314, 491.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(169.041, 491.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef112
+ connRef = new ConnRef(router, 112);
+ srcPt = ConnEnd(Point(349.035, 151.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(349.035, 371.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef113
+ connRef = new ConnRef(router, 113);
+ srcPt = ConnEnd(Point(229.034, 311.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(229.034, 371.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef114
+ connRef = new ConnRef(router, 114);
+ srcPt = ConnEnd(Point(269.039, 327.99), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(169.041, 431.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef115
+ connRef = new ConnRef(router, 115);
+ srcPt = ConnEnd(Point(369.034, 551.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(229.034, 371.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef116
+ connRef = new ConnRef(router, 116);
+ srcPt = ConnEnd(Point(429.023, 491.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(429.023, 431.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef117
+ connRef = new ConnRef(router, 117);
+ srcPt = ConnEnd(Point(89.0462, 401.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(149.045, 401.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef118
+ connRef = new ConnRef(router, 118);
+ srcPt = ConnEnd(Point(349.035, 151.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(229.034, 151.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef119
+ connRef = new ConnRef(router, 119);
+ srcPt = ConnEnd(Point(549.011, 401.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(549.011, 611.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef120
+ connRef = new ConnRef(router, 120);
+ srcPt = ConnEnd(Point(369.024, 195.582), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(579.052, 195.582), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef121
+ connRef = new ConnRef(router, 121);
+ srcPt = ConnEnd(Point(269.039, 327.99), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(269.039, 231.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef122
+ connRef = new ConnRef(router, 122);
+ srcPt = ConnEnd(Point(169.041, 431.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(169.041, 371.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef123
+ connRef = new ConnRef(router, 123);
+ srcPt = ConnEnd(Point(369.024, 431.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(169.041, 431.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef124
+ connRef = new ConnRef(router, 124);
+ srcPt = ConnEnd(Point(229.034, 151.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(229.034, 311.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef125
+ connRef = new ConnRef(router, 125);
+ srcPt = ConnEnd(Point(549.011, 401.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(269.052, 401.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef126
+ connRef = new ConnRef(router, 126);
+ srcPt = ConnEnd(Point(549.011, 401.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(549.011, 291.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef127
+ connRef = new ConnRef(router, 127);
+ srcPt = ConnEnd(Point(269.052, 401.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(289.03, 291.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+#define EDGE128
+#ifdef EDGE128
+ // connRef128
+ connRef = new ConnRef(router, 128);
+ srcPt = ConnEnd(Point(289.03, 291.334), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(289.03, 371.334), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+#endif
+
+ router->processTransaction();
+ router->outputDiagram("output/hola01");
+ delete router;
+ return 0;
+};
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/hyperedge01.cpp b/src/3rdparty/adaptagrams/libavoid/tests/hyperedge01.cpp
new file mode 100644
index 0000000..2997088
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/hyperedge01.cpp
@@ -0,0 +1,285 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ //router->setRoutingPenalty((PenaltyType)2, 200);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ //router->setRoutingPenalty((PenaltyType)4, 110);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+ JunctionRef *shapeRef171026375 = new JunctionRef(router, Point(51075, 51225), 171026375);
+
+ Polygon poly878674(4);
+ poly878674.ps[0] = Point(51454, 51200);
+ poly878674.ps[1] = Point(51454, 51285);
+ poly878674.ps[2] = Point(51396, 51285);
+ poly878674.ps[3] = Point(51396, 51200);
+ new ShapeRef(router, poly878674, 878674);
+
+ Polygon poly286906544(4);
+ poly286906544.ps[0] = Point(50704, 51250);
+ poly286906544.ps[1] = Point(50704, 51335);
+ poly286906544.ps[2] = Point(50646, 51335);
+ poly286906544.ps[3] = Point(50646, 51250);
+ new ShapeRef(router, poly286906544, 286906544);
+
+ Polygon poly170813081(4);
+ poly170813081.ps[0] = Point(51104, 51090);
+ poly170813081.ps[1] = Point(51104, 51175);
+ poly170813081.ps[2] = Point(51046, 51175);
+ poly170813081.ps[3] = Point(51046, 51090);
+ new ShapeRef(router, poly170813081, 170813081);
+
+ Polygon poly342721632(4);
+ poly342721632.ps[0] = Point(51910, 50946);
+ poly342721632.ps[1] = Point(51910, 51004);
+ poly342721632.ps[2] = Point(51825, 51004);
+ poly342721632.ps[3] = Point(51825, 50946);
+ new ShapeRef(router, poly342721632, 342721632);
+
+ JunctionRef *shapeRef102578723 = new JunctionRef(router, Point(51275, 50725), 102578723);
+
+ JunctionRef *shapeRef17922268 = new JunctionRef(router, Point(50850, 50975), 17922268);
+
+ Polygon poly11057158(4);
+ poly11057158.ps[0] = Point(51679, 51200);
+ poly11057158.ps[1] = Point(51679, 51285);
+ poly11057158.ps[2] = Point(51621, 51285);
+ poly11057158.ps[3] = Point(51621, 51200);
+ new ShapeRef(router, poly11057158, 11057158);
+
+ Polygon poly322446045(4);
+ poly322446045.ps[0] = Point(50779, 51240);
+ poly322446045.ps[1] = Point(50779, 51335);
+ poly322446045.ps[2] = Point(50721, 51335);
+ poly322446045.ps[3] = Point(50721, 51240);
+ new ShapeRef(router, poly322446045, 322446045);
+
+ Polygon poly767565928(4);
+ poly767565928.ps[0] = Point(51004, 50741);
+ poly767565928.ps[1] = Point(51004, 50826);
+ poly767565928.ps[2] = Point(50946, 50826);
+ poly767565928.ps[3] = Point(50946, 50741);
+ new ShapeRef(router, poly767565928, 767565928);
+
+ Polygon poly280939374(4);
+ poly280939374.ps[0] = Point(51085, 50971);
+ poly280939374.ps[1] = Point(51085, 51029);
+ poly280939374.ps[2] = Point(51000, 51029);
+ poly280939374.ps[3] = Point(51000, 50971);
+ new ShapeRef(router, poly280939374, 280939374);
+
+ Polygon poly630623707(4);
+ poly630623707.ps[0] = Point(51279, 50925);
+ poly630623707.ps[1] = Point(51279, 51010);
+ poly630623707.ps[2] = Point(51221, 51010);
+ poly630623707.ps[3] = Point(51221, 50925);
+ new ShapeRef(router, poly630623707, 630623707);
+
+ Polygon poly28160455(4);
+ poly28160455.ps[0] = Point(50879, 51250);
+ poly28160455.ps[1] = Point(50879, 51335);
+ poly28160455.ps[2] = Point(50821, 51335);
+ poly28160455.ps[3] = Point(50821, 51250);
+ new ShapeRef(router, poly28160455, 28160455);
+
+ Polygon poly525890448(4);
+ poly525890448.ps[0] = Point(51174, 50721);
+ poly525890448.ps[1] = Point(51174, 50779);
+ poly525890448.ps[2] = Point(51089, 50779);
+ poly525890448.ps[3] = Point(51089, 50721);
+ new ShapeRef(router, poly525890448, 525890448);
+
+ Polygon poly157182552(4);
+ poly157182552.ps[0] = Point(51529, 51190);
+ poly157182552.ps[1] = Point(51529, 51285);
+ poly157182552.ps[2] = Point(51471, 51285);
+ poly157182552.ps[3] = Point(51471, 51190);
+ new ShapeRef(router, poly157182552, 157182552);
+
+ Polygon poly799637520(4);
+ poly799637520.ps[0] = Point(50625, 50896);
+ poly799637520.ps[1] = Point(50625, 50954);
+ poly799637520.ps[2] = Point(50540, 50954);
+ poly799637520.ps[3] = Point(50540, 50896);
+ new ShapeRef(router, poly799637520, 799637520);
+
+ Polygon poly60349320(4);
+ poly60349320.ps[0] = Point(50904, 51025);
+ poly60349320.ps[1] = Point(50904, 51110);
+ poly60349320.ps[2] = Point(50846, 51110);
+ poly60349320.ps[3] = Point(50846, 51025);
+ new ShapeRef(router, poly60349320, 60349320);
+
+ Polygon poly119851894(4);
+ poly119851894.ps[0] = Point(51179, 51225);
+ poly119851894.ps[1] = Point(51179, 51310);
+ poly119851894.ps[2] = Point(51121, 51310);
+ poly119851894.ps[3] = Point(51121, 51225);
+ new ShapeRef(router, poly119851894, 119851894);
+
+ Polygon poly233164275(4);
+ poly233164275.ps[0] = Point(51604, 51200);
+ poly233164275.ps[1] = Point(51604, 51285);
+ poly233164275.ps[2] = Point(51546, 51285);
+ poly233164275.ps[3] = Point(51546, 51200);
+ new ShapeRef(router, poly233164275, 233164275);
+
+ Polygon poly807558175(4);
+ poly807558175.ps[0] = Point(51604, 51000);
+ poly807558175.ps[1] = Point(51604, 51085);
+ poly807558175.ps[2] = Point(51546, 51085);
+ poly807558175.ps[3] = Point(51546, 51000);
+ new ShapeRef(router, poly807558175, 807558175);
+
+ JunctionRef *shapeRef265539540 = new JunctionRef(router, Point(51625, 50950), 265539540);
+
+ Polygon poly108859552(4);
+ poly108859552.ps[0] = Point(51560, 50721);
+ poly108859552.ps[1] = Point(51560, 50779);
+ poly108859552.ps[2] = Point(51475, 50779);
+ poly108859552.ps[3] = Point(51475, 50721);
+ new ShapeRef(router, poly108859552, 108859552);
+
+ Polygon poly404900496(4);
+ poly404900496.ps[0] = Point(51525, 50946);
+ poly404900496.ps[1] = Point(51525, 51004);
+ poly404900496.ps[2] = Point(51440, 51004);
+ poly404900496.ps[3] = Point(51440, 50946);
+ new ShapeRef(router, poly404900496, 404900496);
+
+ Polygon poly620445000(4);
+ poly620445000.ps[0] = Point(51029, 51225);
+ poly620445000.ps[1] = Point(51029, 51310);
+ poly620445000.ps[2] = Point(50971, 51310);
+ poly620445000.ps[3] = Point(50971, 51225);
+ new ShapeRef(router, poly620445000, 620445000);
+
+ ConnRef *connRef450684531 = new ConnRef(router, 450684531);
+ ConnEnd srcPt450684531(Point(51165, 50750), 8);
+ connRef450684531->setSourceEndpoint(srcPt450684531);
+ ConnEnd dstPt450684531(shapeRef102578723);
+ connRef450684531->setDestEndpoint(dstPt450684531);
+ connRef450684531->setRoutingType((ConnType)2);
+
+ ConnRef *connRef135371350 = new ConnRef(router, 135371350);
+ ConnEnd srcPt135371350(shapeRef102578723);
+ connRef135371350->setSourceEndpoint(srcPt135371350);
+ ConnEnd dstPt135371350(Point(51250, 50935), 1);
+ connRef135371350->setDestEndpoint(dstPt135371350);
+ connRef135371350->setRoutingType((ConnType)2);
+
+ ConnRef *connRef143333770 = new ConnRef(router, 143333770);
+ ConnEnd srcPt143333770(Point(51485, 50750), 4);
+ connRef143333770->setSourceEndpoint(srcPt143333770);
+ ConnEnd dstPt143333770(shapeRef102578723);
+ connRef143333770->setDestEndpoint(dstPt143333770);
+ connRef143333770->setRoutingType((ConnType)2);
+
+ ConnRef *connRef102966575 = new ConnRef(router, 102966575);
+ ConnEnd srcPt102966575(Point(50615, 50925), 8);
+ connRef102966575->setSourceEndpoint(srcPt102966575);
+ ConnEnd dstPt102966575(shapeRef17922268);
+ connRef102966575->setDestEndpoint(dstPt102966575);
+ connRef102966575->setRoutingType((ConnType)2);
+
+ ConnRef *connRef68998920 = new ConnRef(router, 68998920);
+ ConnEnd srcPt68998920(shapeRef17922268);
+ connRef68998920->setSourceEndpoint(srcPt68998920);
+ ConnEnd dstPt68998920(Point(50975, 50815), 2);
+ connRef68998920->setDestEndpoint(dstPt68998920);
+ connRef68998920->setRoutingType((ConnType)2);
+
+ ConnRef *connRef1625709 = new ConnRef(router, 1625709);
+ ConnEnd srcPt1625709(shapeRef17922268);
+ connRef1625709->setSourceEndpoint(srcPt1625709);
+ ConnEnd dstPt1625709(Point(50875, 51035), 1);
+ connRef1625709->setDestEndpoint(dstPt1625709);
+ connRef1625709->setRoutingType((ConnType)2);
+
+ ConnRef *connRef34178450 = new ConnRef(router, 34178450);
+ ConnEnd srcPt34178450(shapeRef17922268);
+ connRef34178450->setSourceEndpoint(srcPt34178450);
+ ConnEnd dstPt34178450(Point(51010, 51000), 4);
+ connRef34178450->setDestEndpoint(dstPt34178450);
+ connRef34178450->setRoutingType((ConnType)2);
+
+ ConnRef *connRef314512308 = new ConnRef(router, 314512308);
+ ConnEnd srcPt314512308(Point(51000, 51235), 1);
+ connRef314512308->setSourceEndpoint(srcPt314512308);
+ ConnEnd dstPt314512308(shapeRef171026375);
+ connRef314512308->setDestEndpoint(dstPt314512308);
+ connRef314512308->setRoutingType((ConnType)2);
+
+ ConnRef *connRef182776308 = new ConnRef(router, 182776308);
+ ConnEnd srcPt182776308(shapeRef171026375);
+ connRef182776308->setSourceEndpoint(srcPt182776308);
+ ConnEnd dstPt182776308(Point(51075, 51165), 2);
+ connRef182776308->setDestEndpoint(dstPt182776308);
+ connRef182776308->setRoutingType((ConnType)2);
+
+ ConnRef *connRef96504835 = new ConnRef(router, 96504835);
+ ConnEnd srcPt96504835(Point(51150, 51235), 1);
+ connRef96504835->setSourceEndpoint(srcPt96504835);
+ ConnEnd dstPt96504835(shapeRef171026375);
+ connRef96504835->setDestEndpoint(dstPt96504835);
+ connRef96504835->setRoutingType((ConnType)2);
+
+ ConnRef *connRef467016913 = new ConnRef(router, 467016913);
+ ConnEnd srcPt467016913(shapeRef265539540);
+ connRef467016913->setSourceEndpoint(srcPt467016913);
+ ConnEnd dstPt467016913(Point(51575, 51010), 1);
+ connRef467016913->setDestEndpoint(dstPt467016913);
+ connRef467016913->setRoutingType((ConnType)2);
+
+ ConnRef *connRef45740440 = new ConnRef(router, 45740440);
+ ConnEnd srcPt45740440(Point(51835, 50975), 4);
+ connRef45740440->setSourceEndpoint(srcPt45740440);
+ ConnEnd dstPt45740440(shapeRef265539540);
+ connRef45740440->setDestEndpoint(dstPt45740440);
+ connRef45740440->setRoutingType((ConnType)2);
+
+ ConnRef *connRef985644192 = new ConnRef(router, 985644192);
+ ConnEnd srcPt985644192(Point(51515, 50975), 8);
+ connRef985644192->setSourceEndpoint(srcPt985644192);
+ ConnEnd dstPt985644192(shapeRef265539540);
+ connRef985644192->setDestEndpoint(dstPt985644192);
+ connRef985644192->setRoutingType((ConnType)2);
+
+ ConnRef *connRef1 = new ConnRef(router, 1);
+ ConnEnd srcPt1(shapeRef102578723);
+ connRef1->setSourceEndpoint(srcPt1);
+ ConnEnd dstPt1(shapeRef171026375);
+ connRef1->setDestEndpoint(dstPt1);
+ connRef1->setRoutingType((ConnType)2);
+
+ ConnRef *connRef2 = new ConnRef(router, 2);
+ ConnEnd srcPt2(shapeRef102578723);
+ connRef2->setSourceEndpoint(srcPt2);
+ ConnEnd dstPt2(shapeRef17922268);
+ connRef2->setDestEndpoint(dstPt2);
+ connRef2->setRoutingType((ConnType)2);
+
+ ConnRef *connRef3 = new ConnRef(router, 3);
+ ConnEnd srcPt3(shapeRef102578723);
+ connRef3->setSourceEndpoint(srcPt3);
+ ConnEnd dstPt3(shapeRef265539540);
+ connRef3->setDestEndpoint(dstPt3);
+ connRef3->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/hyperedge01-1");
+
+ HyperedgeRerouter *hyperedgeRerouter = router->hyperedgeRerouter();
+ hyperedgeRerouter->registerHyperedgeForRerouting(shapeRef102578723);
+
+ router->processTransaction();
+ router->outputDiagram("output/hyperedge01-2");
+
+ delete router;
+ return 0;
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/hyperedge02.cpp b/src/3rdparty/adaptagrams/libavoid/tests/hyperedge02.cpp
new file mode 100644
index 0000000..46d4b76
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/hyperedge02.cpp
@@ -0,0 +1,99 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ ConnEndList hyperedgeTerminals;
+ Router *router = new Router(OrthogonalRouting);
+ /*
+ router->setRoutingPenalty((PenaltyType)0, 78.7234);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 0);
+ router->setRoutingPenalty((PenaltyType)4, 0);
+ router->setRoutingPenalty((PenaltyType)5, 100);
+ router->setRoutingOption((RoutingOption)0, true);
+ router->setOrthogonalNudgeDistance(4);
+ */
+
+ Polygon poly1(4);
+ poly1.ps[0] = Point(461.05, 1.66648);
+ poly1.ps[1] = Point(461.05, 65.6665);
+ poly1.ps[2] = Point(376.05, 65.6665);
+ poly1.ps[3] = Point(376.05, 1.66648);
+ ShapeRef *shapeRef1 = new ShapeRef(router, poly1, 1);
+ new ShapeConnectionPin(shapeRef1, 102, 0.5, 1, true, 10, (ConnDirFlags) 2);
+ hyperedgeTerminals.push_back(ConnEnd(shapeRef1, 102));
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(404, 166);
+ poly2.ps[1] = Point(404, 227);
+ poly2.ps[2] = Point(320, 227);
+ poly2.ps[3] = Point(320, 166);
+ ShapeRef *shapeRef2 = new ShapeRef(router, poly2, 2);
+ new ShapeConnectionPin(shapeRef2, 102, 0, 0.5, true, 10, (ConnDirFlags) 4);
+ hyperedgeTerminals.push_back(ConnEnd(shapeRef2, 102));
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(240.001, 185);
+ poly3.ps[1] = Point(240.001, 227);
+ poly3.ps[2] = Point(178.001, 227);
+ poly3.ps[3] = Point(178.001, 185);
+ ShapeRef *shapeRef3 = new ShapeRef(router, poly3, 3);
+ new ShapeConnectionPin(shapeRef3, 102, 1, 0.5, true, 10, (ConnDirFlags) 8);
+ hyperedgeTerminals.push_back(ConnEnd(shapeRef3, 102));
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(274.526, 132);
+ poly4.ps[1] = Point(274.526, 174);
+ poly4.ps[2] = Point(90.526, 174);
+ poly4.ps[3] = Point(90.526, 132);
+ new ShapeRef(router, poly4, 4);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(152.526, 1.66648);
+ poly5.ps[1] = Point(152.526, 40);
+ poly5.ps[2] = Point(90.526, 40);
+ poly5.ps[3] = Point(90.526, 1.66648);
+ ShapeRef *shapeRef5 = new ShapeRef(router, poly5, 5);
+ new ShapeConnectionPin(shapeRef5, 102, 0.5, 1, true, 10, (ConnDirFlags) 2);
+ hyperedgeTerminals.push_back(ConnEnd(shapeRef5, 102));
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(366.925, 1.66648);
+ poly6.ps[1] = Point(366.925, 92.6665);
+ poly6.ps[2] = Point(304.925, 92.6665);
+ poly6.ps[3] = Point(304.925, 1.66648);
+ new ShapeRef(router, poly6, 6);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(345, 115);
+ poly8.ps[1] = Point(345, 140);
+ poly8.ps[2] = Point(320, 140);
+ poly8.ps[3] = Point(320, 115);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(223.675, 1.66648);
+ poly7.ps[1] = Point(223.675, 50.3333);
+ poly7.ps[2] = Point(161.675, 50.3333);
+ poly7.ps[3] = Point(161.675, 1.66648);
+ ShapeRef *shapeRef7 = new ShapeRef(router, poly7, 7);
+ new ShapeConnectionPin(shapeRef7, 102, 0.5, 1, true, 10, (ConnDirFlags) 2);
+ hyperedgeTerminals.push_back(ConnEnd(shapeRef7, 102));
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(295.3, 1.66648);
+ poly10.ps[1] = Point(295.3, 40);
+ poly10.ps[2] = Point(233.3, 40);
+ poly10.ps[3] = Point(233.3, 1.66648);
+ ShapeRef *shapeRef10 = new ShapeRef(router, poly10, 10);
+ new ShapeConnectionPin(shapeRef10, 102, 0.5, 1, true, 10, (ConnDirFlags) 2);
+ hyperedgeTerminals.push_back(ConnEnd(shapeRef10, 102));
+
+ HyperedgeRerouter *hyperedgeRerouter = router->hyperedgeRerouter();
+ hyperedgeRerouter->registerHyperedgeForRerouting(hyperedgeTerminals);
+
+ router->processTransaction();
+ router->outputDiagram("output/hyperedge02");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/hyperedgeLoop1.cpp b/src/3rdparty/adaptagrams/libavoid/tests/hyperedgeLoop1.cpp
new file mode 100644
index 0000000..2ef5073
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/hyperedgeLoop1.cpp
@@ -0,0 +1,87 @@
+// THis is a regression test for an infinite loop in the hyperedge improvement.
+
+#include "libavoid/libavoid.h"
+#include <sstream>
+using namespace Avoid;
+
+void test()
+{
+ Avoid::ConnEnd end1;
+ Avoid::ConnEnd end2;
+ Avoid::Polygon poly;
+ Avoid::Router * router1 = new Avoid::Router(Avoid::OrthogonalRouting);
+ router1->setTransactionUse(true);
+ router1->setRoutingPenalty(Avoid::segmentPenalty);
+ router1->setRoutingPenalty(Avoid::crossingPenalty);
+ router1->setRoutingPenalty(Avoid::fixedSharedPathPenalty, 9000);
+ router1->setRoutingParameter(idealNudgingDistance, 25);
+
+ poly = Avoid::Polygon(4);
+ poly.setPoint(0, Avoid::Point(50760, 50620));
+ poly.setPoint(1, Avoid::Point(50760, 50680));
+ poly.setPoint(2, Avoid::Point(50590, 50680));
+ poly.setPoint(3, Avoid::Point(50590, 50620));
+ Avoid::ShapeRef * shape147006780 = new Avoid::ShapeRef(router1, poly, 147006780);
+ Avoid::ShapeConnectionPin * pin147006780_1 = new Avoid::ShapeConnectionPin(shape147006780, 2, 0.941176, 0.5, true, 10, 8);
+ pin147006780_1->setExclusive(true);
+
+ poly = Avoid::Polygon(4);
+ poly.setPoint(0, Avoid::Point(50585, 50765));
+ poly.setPoint(1, Avoid::Point(50585, 50935));
+ poly.setPoint(2, Avoid::Point(50365, 50935));
+ poly.setPoint(3, Avoid::Point(50365, 50765));
+ Avoid::ShapeRef * shape69758810 = new Avoid::ShapeRef(router1, poly, 69758810);
+ Avoid::ShapeConnectionPin * pin69758810_1 = new Avoid::ShapeConnectionPin(shape69758810, 2, 0.954545, 0.5, true, 10, 8);
+ pin69758810_1->setExclusive(true);
+
+ poly = Avoid::Polygon(4);
+ poly.setPoint(0, Avoid::Point(51060, 51020));
+ poly.setPoint(1, Avoid::Point(51060, 51080));
+ poly.setPoint(2, Avoid::Point(50890, 51080));
+ poly.setPoint(3, Avoid::Point(50890, 51020));
+ Avoid::ShapeRef * shape149922619 = new Avoid::ShapeRef(router1, poly, 149922619);
+ Avoid::ShapeConnectionPin * pin149922619_1 = new Avoid::ShapeConnectionPin(shape149922619, 2, 0.941176, 0.5, true, 10, 8);
+ pin149922619_1->setExclusive(true);
+
+ Avoid::JunctionRef * junction228834480 = new Avoid::JunctionRef(router1, Avoid::Point(51050, 51050), 228834480);
+ end1 = Avoid::ConnEnd(shape69758810, 2);
+ end2 = Avoid::ConnEnd(junction228834480);
+ Avoid::ConnRef * conn159270000 = new Avoid::ConnRef(router1, end1, end2);
+ conn159270000->makePathInvalid();
+ end1 = Avoid::ConnEnd(junction228834480);
+ end2 = Avoid::ConnEnd(shape149922619, 2);
+ Avoid::ConnRef * conn199495942 = new Avoid::ConnRef(router1, end1, end2);
+ router1->processTransaction();
+
+ router1->outputDiagram("output/hyperedgeLoop1-1");
+ end1 = Avoid::ConnEnd(shape147006780, 2);
+ end2 = Avoid::ConnEnd(junction228834480);
+ Avoid::ConnRef * conn8326760 = new Avoid::ConnRef(router1, end1, end2);
+ conn8326760->makePathInvalid();
+ router1->processTransaction(); // infinite
+
+ router1->outputDiagram("output/hyperedgeLoop1-2");
+ router1->deleteShape(shape147006780);
+ shape147006780 = nullptr;
+ router1->deleteShape(shape69758810);
+ shape69758810 = nullptr;
+ router1->deleteShape(shape149922619);
+ shape149922619 = nullptr;
+ router1->deleteJunction(junction228834480);
+ junction228834480 = nullptr;
+ router1->deleteConnector(conn159270000);
+ conn159270000 = nullptr;
+ router1->deleteConnector(conn199495942);
+ conn199495942 = nullptr;
+ router1->deleteConnector(conn8326760);
+ conn8326760 = nullptr;
+ router1->processTransaction();
+
+ delete router1;
+}
+
+extern "C" int main(void)
+{
+ test();
+ return 0;
+}
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/hyperedgeRerouting01.cpp b/src/3rdparty/adaptagrams/libavoid/tests/hyperedgeRerouting01.cpp
new file mode 100644
index 0000000..2aa81f2
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/hyperedgeRerouting01.cpp
@@ -0,0 +1,150 @@
+// Based on 33004heap_corruption.cpp
+//
+#include "libavoid/libavoid.h"
+#include <sstream>
+
+void outputDiagram(Avoid::Router * router)
+{
+ static int counter = 0;
+ std::ostringstream os;
+ os << (++counter);
+ //router->outputDiagram(os.str());
+}
+
+int test()
+{
+ // The contents of this function can be replaced by the automatically generated test code from the debug svg file
+ Avoid::ConnEnd end1_0;
+ Avoid::ConnEnd end2_0;
+ Avoid::Polygon poly0;
+ Avoid::Router * router0 = new Avoid::Router(Avoid::OrthogonalRouting);
+ Avoid::HyperedgeNewAndDeletedObjectLists newanddeletedobjects_0;
+ Avoid::ConnRefList::const_iterator connit_0;
+ Avoid::JunctionRefList::const_iterator junctionit_0;
+ router0->setTransactionUse(true);
+ router0->setRoutingPenalty(Avoid::segmentPenalty);
+ router0->setRoutingPenalty(Avoid::crossingPenalty);
+ router0->setRoutingPenalty(Avoid::fixedSharedPathPenalty, 9000);
+ router0->setRoutingOption(Avoid::penaliseOrthogonalSharedPathsAtConnEnds, true);
+ router0->setRoutingParameter(Avoid::idealNudgingDistance, 25);
+ router0->setRoutingOption(Avoid::improveHyperedgeRoutesMovingAddingAndDeletingJunctions, true);
+
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(27350, 26040));
+ poly0.setPoint(1, Avoid::Point(27350, 26450));
+ poly0.setPoint(2, Avoid::Point(26925, 26450));
+ poly0.setPoint(3, Avoid::Point(26925, 26040));
+ Avoid::ShapeRef * shape0_478041183 = new Avoid::ShapeRef(router0, poly0, 478041183);
+ Avoid::ShapeConnectionPin * pin0_478041183_0 = new Avoid::ShapeConnectionPin(shape0_478041183, 1, 0, 85, false, 10, 4);
+ pin0_478041183_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_478041183_1 = new Avoid::ShapeConnectionPin(shape0_478041183, 2, 100, -1, false, 10, 2);
+ pin0_478041183_1->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_478041183_2 = new Avoid::ShapeConnectionPin(shape0_478041183, 3, -1, 85, false, 10, 8);
+ pin0_478041183_2->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_478041183_3 = new Avoid::ShapeConnectionPin(shape0_478041183, 4, 250, -1, false, 10, 2);
+ pin0_478041183_3->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_478041183_4 = new Avoid::ShapeConnectionPin(shape0_478041183, 5, 0, 235, false, 10, 4);
+ pin0_478041183_4->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_478041183_5 = new Avoid::ShapeConnectionPin(shape0_478041183, 6, 0, 160, false, 10, 4);
+ pin0_478041183_5->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_478041183_6 = new Avoid::ShapeConnectionPin(shape0_478041183, 7, 175, -1, false, 10, 2);
+ pin0_478041183_6->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_478041183_7 = new Avoid::ShapeConnectionPin(shape0_478041183, 8, -1, 160, false, 10, 8);
+ pin0_478041183_7->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_478041183_8 = new Avoid::ShapeConnectionPin(shape0_478041183, 9, 325, -1, false, 10, 2);
+ pin0_478041183_8->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_478041183_9 = new Avoid::ShapeConnectionPin(shape0_478041183, 10, 0, 310, false, 10, 4);
+ pin0_478041183_9->setExclusive(true);
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(27030, 26900));
+ poly0.setPoint(1, Avoid::Point(27030, 27050));
+ poly0.setPoint(2, Avoid::Point(26970, 27050));
+ poly0.setPoint(3, Avoid::Point(26970, 26900));
+ Avoid::ShapeRef * shape0_646972128 = new Avoid::ShapeRef(router0, poly0, 646972128);
+ Avoid::ShapeConnectionPin * pin0_646972128_0 = new Avoid::ShapeConnectionPin(shape0_646972128, 1, 25, -1, false, 10, 2);
+ pin0_646972128_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_646972128_1 = new Avoid::ShapeConnectionPin(shape0_646972128, 2, 25, 0, false, 10, 1);
+ pin0_646972128_1->setExclusive(true);
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(26480, 26350));
+ poly0.setPoint(1, Avoid::Point(26480, 26500));
+ poly0.setPoint(2, Avoid::Point(26420, 26500));
+ poly0.setPoint(3, Avoid::Point(26420, 26350));
+ Avoid::ShapeRef * shape0_53041512 = new Avoid::ShapeRef(router0, poly0, 53041512);
+ Avoid::ShapeConnectionPin * pin0_53041512_0 = new Avoid::ShapeConnectionPin(shape0_53041512, 1, 30, 0, false, 10, 1);
+ pin0_53041512_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_53041512_1 = new Avoid::ShapeConnectionPin(shape0_53041512, 2, 30, -1, false, 10, 2);
+ pin0_53041512_1->setExclusive(true);
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(26860, 26900));
+ poly0.setPoint(1, Avoid::Point(26860, 27050));
+ poly0.setPoint(2, Avoid::Point(26790, 27050));
+ poly0.setPoint(3, Avoid::Point(26790, 26900));
+ Avoid::ShapeRef * shape0_241539284 = new Avoid::ShapeRef(router0, poly0, 241539284);
+ Avoid::ShapeConnectionPin * pin0_241539284_0 = new Avoid::ShapeConnectionPin(shape0_241539284, 1, 35, -1, false, 10, 2);
+ pin0_241539284_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_241539284_1 = new Avoid::ShapeConnectionPin(shape0_241539284, 2, 35, 0, false, 10, 1);
+ pin0_241539284_1->setExclusive(true);
+ Avoid::JunctionRef * junction0_16268769 = new Avoid::JunctionRef(router0, Avoid::Point(27000, 27075), 16268769);
+ junction0_16268769->setPositionFixed(true);
+ Avoid::JunctionRef * junction0_142222080 = new Avoid::JunctionRef(router0, Avoid::Point(27200, 26450), 142222080);
+ junction0_142222080->setPositionFixed(true);
+ Avoid::JunctionRef * junction0_471289251 = new Avoid::JunctionRef(router0, Avoid::Point(26350, 26325), 471289251);
+ junction0_471289251->setPositionFixed(true);
+
+
+ end1_0 = Avoid::ConnEnd(shape0_646972128, 1);
+ end2_0 = Avoid::ConnEnd(junction0_16268769);
+ Avoid::ConnRef * conn0_64950216 = new Avoid::ConnRef(router0, end1_0, end2_0, 64950216);
+ end1_0 = Avoid::ConnEnd(junction0_16268769);
+ end2_0 = Avoid::ConnEnd(shape0_478041183, 7);
+ Avoid::ConnRef * conn0_278089510 = new Avoid::ConnRef(router0, end1_0, end2_0, 278089510);
+ end1_0 = Avoid::ConnEnd(shape0_241539284, 1);
+ end2_0 = Avoid::ConnEnd(junction0_16268769);
+ Avoid::ConnRef * conn0_41268690 = new Avoid::ConnRef(router0, end1_0, end2_0, 41268690);
+
+ end1_0 = Avoid::ConnEnd(shape0_478041183, 9);
+ end2_0 = Avoid::ConnEnd(junction0_142222080);
+ Avoid::ConnRef * conn0_60256130 = new Avoid::ConnRef(router0, end1_0, end2_0, 60256130);
+ end1_0 = Avoid::ConnEnd(shape0_478041183, 3);
+ end2_0 = Avoid::ConnEnd(junction0_142222080);
+ Avoid::ConnRef * conn0_73835204 = new Avoid::ConnRef(router0, end1_0, end2_0, 73835204);
+ end1_0 = Avoid::ConnEnd(shape0_478041183, 4);
+ end2_0 = Avoid::ConnEnd(junction0_142222080);
+ Avoid::ConnRef * conn0_93872527 = new Avoid::ConnRef(router0, end1_0, end2_0, 93872527);
+
+ end1_0 = Avoid::ConnEnd(shape0_53041512, 1);
+ end2_0 = Avoid::ConnEnd(junction0_471289251);
+ Avoid::ConnRef * conn0_448284384 = new Avoid::ConnRef(router0, end1_0, end2_0, 448284384);
+ end1_0 = Avoid::ConnEnd(shape0_478041183, 1);
+ end2_0 = Avoid::ConnEnd(junction0_471289251);
+ Avoid::ConnRef * conn0_392836745 = new Avoid::ConnRef(router0, end1_0, end2_0, 392836745);
+ end1_0 = Avoid::ConnEnd(shape0_241539284, 2);
+ end2_0 = Avoid::ConnEnd(junction0_471289251);
+ Avoid::ConnRef * conn0_836242673 = new Avoid::ConnRef(router0, end1_0, end2_0, 836242673);
+
+ router0->processTransaction();
+
+ newanddeletedobjects_0 = router0->newAndDeletedObjectListsFromHyperedgeImprovement();
+ outputDiagram(router0);
+
+ junction0_16268769->setPositionFixed(false);
+ junction0_142222080->setPositionFixed(false);
+ junction0_471289251->setPositionFixed(false);
+
+ router0->hyperedgeRerouter()->registerHyperedgeForRerouting(junction0_16268769);
+ router0->hyperedgeRerouter()->registerHyperedgeForRerouting(junction0_142222080);
+ router0->hyperedgeRerouter()->registerHyperedgeForRerouting(junction0_471289251);
+
+ router0->processTransaction();
+ outputDiagram(router0);
+
+ int result = router0->existsInvalidOrthogonalPaths();
+ delete router0;
+ return result;
+}
+
+extern "C" int main(int argc, char* argv[])
+{
+ return test();
+}
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge01.cpp b/src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge01.cpp
new file mode 100644
index 0000000..092689c
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge01.cpp
@@ -0,0 +1,109 @@
+#include "libavoid/libavoid.h"
+#include <sstream>
+using namespace Avoid;
+
+int test()
+{
+ // The contents of this function can be replaced by the automatically generated test code from the debug svg file
+ Avoid::ConnEnd end1;
+ Avoid::ConnEnd end2;
+ Avoid::Polygon poly;
+ Avoid::Router * router = new Avoid::Router(Avoid::OrthogonalRouting);
+ router->setTransactionUse(true);
+ router->setRoutingPenalty(Avoid::segmentPenalty);
+ router->setRoutingPenalty(Avoid::crossingPenalty);
+ router->setRoutingPenalty(Avoid::fixedSharedPathPenalty);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+ router->setRoutingOption(Avoid::improveHyperedgeRoutesMovingJunctions, true);
+ poly = Avoid::Polygon(4);
+ poly.setPoint(0, Avoid::Point(51160, 50670));
+ poly.setPoint(1, Avoid::Point(51160, 50730));
+ poly.setPoint(2, Avoid::Point(50950, 50730));
+ poly.setPoint(3, Avoid::Point(50950, 50670));
+ Avoid::ShapeRef * shape341041314 = new Avoid::ShapeRef(router, poly, 341041314);
+ Avoid::ShapeConnectionPin * pin341041314_0 = new Avoid::ShapeConnectionPin(shape341041314, 1, 0.952381, 0.5, true, 10, 8);
+ pin341041314_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin341041314_1 = new Avoid::ShapeConnectionPin(shape341041314, 2, 0, 0.5, true, 10, 4);
+ pin341041314_1->setExclusive(true);
+ poly = Avoid::Polygon(4);
+ poly.setPoint(0, Avoid::Point(51160, 50395));
+ poly.setPoint(1, Avoid::Point(51160, 50455));
+ poly.setPoint(2, Avoid::Point(50950, 50455));
+ poly.setPoint(3, Avoid::Point(50950, 50395));
+ Avoid::ShapeRef * shape47540376 = new Avoid::ShapeRef(router, poly, 47540376);
+ Avoid::ShapeConnectionPin * pin47540376_0 = new Avoid::ShapeConnectionPin(shape47540376, 1, 0.952381, 0.5, true, 10, 8);
+ pin47540376_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin47540376_1 = new Avoid::ShapeConnectionPin(shape47540376, 2, 0, 0.5, true, 10, 4);
+ pin47540376_1->setExclusive(true);
+ poly = Avoid::Polygon(4);
+ poly.setPoint(0, Avoid::Point(50850, 50770));
+ poly.setPoint(1, Avoid::Point(50850, 50830));
+ poly.setPoint(2, Avoid::Point(50665, 50830));
+ poly.setPoint(3, Avoid::Point(50665, 50770));
+ Avoid::ShapeRef * shape81920772 = new Avoid::ShapeRef(router, poly, 81920772);
+ Avoid::ShapeConnectionPin * pin81920772_0 = new Avoid::ShapeConnectionPin(shape81920772, 1, 0.047619, 0.5, true, 10, 4);
+ pin81920772_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin81920772_1 = new Avoid::ShapeConnectionPin(shape81920772, 2, 1, 0.5, true, 10, 8);
+ pin81920772_1->setExclusive(true);
+ Avoid::JunctionRef * junction878282342 = new Avoid::JunctionRef(router, Avoid::Point(50875, 50700), 878282342);
+ junction878282342->setPositionFixed(false);
+ poly = Avoid::Polygon(4);
+ poly.setPoint(0, Avoid::Point(50850, 50470));
+ poly.setPoint(1, Avoid::Point(50850, 50530));
+ poly.setPoint(2, Avoid::Point(50665, 50530));
+ poly.setPoint(3, Avoid::Point(50665, 50470));
+ Avoid::ShapeRef * shape206564314 = new Avoid::ShapeRef(router, poly, 206564314);
+ Avoid::ShapeConnectionPin * pin206564314_0 = new Avoid::ShapeConnectionPin(shape206564314, 1, 0.047619, 0.5, true, 10, 4);
+ pin206564314_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin206564314_1 = new Avoid::ShapeConnectionPin(shape206564314, 2, 1, 0.5, true, 10, 8);
+ pin206564314_1->setExclusive(true);
+ Avoid::JunctionRef * junction213455341 = new Avoid::JunctionRef(router, Avoid::Point(50875, 50500), 213455341);
+ junction213455341->setPositionFixed(false);
+ end1 = Avoid::ConnEnd(junction878282342);
+ end2 = Avoid::ConnEnd(shape341041314, 2);
+ Avoid::ConnRef * conn290033688 = new Avoid::ConnRef(router, end1, end2);
+ conn290033688->makePathInvalid();
+ end1 = Avoid::ConnEnd(shape81920772, 2);
+ end2 = Avoid::ConnEnd(junction878282342);
+ Avoid::ConnRef * conn281807178 = new Avoid::ConnRef(router, end1, end2);
+ conn281807178->makePathInvalid();
+ end1 = Avoid::ConnEnd(shape47540376, 2);
+ end2 = Avoid::ConnEnd(junction213455341);
+ Avoid::ConnRef * conn762966660 = new Avoid::ConnRef(router, end1, end2);
+ conn762966660->makePathInvalid();
+ end1 = Avoid::ConnEnd(junction213455341);
+ end2 = Avoid::ConnEnd(junction878282342);
+ Avoid::ConnRef * conn46508714 = new Avoid::ConnRef(router, end1, end2);
+ conn46508714->makePathInvalid();
+ end1 = Avoid::ConnEnd(shape206564314, 2);
+ end2 = Avoid::ConnEnd(junction213455341);
+ Avoid::ConnRef * conn385831514 = new Avoid::ConnRef(router, end1, end2);
+ conn385831514->makePathInvalid();
+ router->processTransaction();
+
+ router->outputDiagram("output/improveHyperedge01-1");
+ poly = Avoid::Polygon(4);
+ poly.setPoint(0, Avoid::Point(51160, 50645));
+ poly.setPoint(1, Avoid::Point(51160, 50705));
+ poly.setPoint(2, Avoid::Point(50950, 50705));
+ poly.setPoint(3, Avoid::Point(50950, 50645));
+ router->moveShape(shape341041314, poly);
+ conn290033688->makePathInvalid();
+ conn281807178->makePathInvalid();
+ conn46508714->makePathInvalid();
+ conn762966660->makePathInvalid();
+ router->processTransaction();
+
+ router->outputDiagram("output/improveHyperedge01-2");
+ Avoid::Point junctionPos = junction878282342->recommendedPosition();
+
+ delete router;
+
+ // Regression test to check that a junction is correctly moved.
+ return (junctionPos.y == 50675) ? 0 : 1;
+}
+
+int main(void)
+{
+ return test();
+}
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge02.cpp b/src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge02.cpp
new file mode 100644
index 0000000..9eb1d2b
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge02.cpp
@@ -0,0 +1,90 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 200);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 9000);
+ router->setRoutingPenalty((PenaltyType)5, 100);
+ router->setRoutingOption((RoutingOption)0, false);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, true);
+ router->setRoutingOption(improveHyperedgeRoutesMovingAddingAndDeletingJunctions, true);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+ Polygon poly39761567(4);
+ poly39761567.ps[0] = Point(50754, 50975);
+ poly39761567.ps[1] = Point(50754, 51060);
+ poly39761567.ps[2] = Point(50696, 51060);
+ poly39761567.ps[3] = Point(50696, 50975);
+ ShapeRef *shapeRef39761567 = new ShapeRef(router, poly39761567, 39761567);
+ new ShapeConnectionPin(shapeRef39761567, 1, 0.5, 0, true, 10, (ConnDirFlags) 1);
+
+ Polygon poly115776716(4);
+ poly115776716.ps[0] = Point(51504, 50975);
+ poly115776716.ps[1] = Point(51504, 51060);
+ poly115776716.ps[2] = Point(51446, 51060);
+ poly115776716.ps[3] = Point(51446, 50975);
+ ShapeRef *shapeRef115776716 = new ShapeRef(router, poly115776716, 115776716);
+ new ShapeConnectionPin(shapeRef115776716, 1, 0.5, 0, true, 10, (ConnDirFlags) 1);
+
+ Polygon poly238475293(4);
+ poly238475293.ps[0] = Point(50554, 50975);
+ poly238475293.ps[1] = Point(50554, 51060);
+ poly238475293.ps[2] = Point(50496, 51060);
+ poly238475293.ps[3] = Point(50496, 50975);
+ ShapeRef *shapeRef238475293 = new ShapeRef(router, poly238475293, 238475293);
+ new ShapeConnectionPin(shapeRef238475293, 1, 0.5, 0, true, 10, (ConnDirFlags) 1);
+
+ Polygon poly430971008(4);
+ poly430971008.ps[0] = Point(51004, 50465);
+ poly430971008.ps[1] = Point(51004, 50550);
+ poly430971008.ps[2] = Point(50946, 50550);
+ poly430971008.ps[3] = Point(50946, 50465);
+ ShapeRef *shapeRef430971008 = new ShapeRef(router, poly430971008, 430971008);
+ new ShapeConnectionPin(shapeRef430971008, 1, 0.5, 1, true, 10, (ConnDirFlags) 2);
+
+ JunctionRef *junctionRef513246008 = new JunctionRef(router, Point(50925, 50725), 513246008);
+ /*
+ // This may be useful if junction pins are modified.
+ new ShapeConnectionPin(junctionRef513246008, 2147483646, (ConnDirFlags) 15);
+ */
+
+ ConnRef *connRef513246009 = new ConnRef(router, 513246009);
+ ConnEnd srcPt513246009(shapeRef39761567, 1);
+ connRef513246009->setSourceEndpoint(srcPt513246009);
+ ConnEnd dstPt513246009(junctionRef513246008);
+ connRef513246009->setDestEndpoint(dstPt513246009);
+ connRef513246009->setRoutingType((ConnType)2);
+
+ ConnRef *connRef513246010 = new ConnRef(router, 513246010);
+ ConnEnd srcPt513246010(junctionRef513246008);
+ connRef513246010->setSourceEndpoint(srcPt513246010);
+ ConnEnd dstPt513246010(shapeRef430971008, 1);
+ connRef513246010->setDestEndpoint(dstPt513246010);
+ connRef513246010->setRoutingType((ConnType)2);
+
+ ConnRef *connRef513246011 = new ConnRef(router, 513246011);
+ ConnEnd srcPt513246011(junctionRef513246008);
+ connRef513246011->setSourceEndpoint(srcPt513246011);
+ ConnEnd dstPt513246011(shapeRef238475293, 1);
+ connRef513246011->setDestEndpoint(dstPt513246011);
+ connRef513246011->setRoutingType((ConnType)2);
+
+ ConnRef *connRef513246012 = new ConnRef(router, 513246012);
+ ConnEnd srcPt513246012(shapeRef115776716, 1);
+ connRef513246012->setSourceEndpoint(srcPt513246012);
+ ConnEnd dstPt513246012(junctionRef513246008);
+ connRef513246012->setDestEndpoint(dstPt513246012);
+ connRef513246012->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/improveHyperedge02");
+
+ bool overlaps = router->existsOrthogonalSegmentOverlap(true);
+ delete router;
+ return (overlaps) ? 1 : 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge03.cpp b/src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge03.cpp
new file mode 100644
index 0000000..5dd6d2c
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge03.cpp
@@ -0,0 +1,90 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 200);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 9000);
+ router->setRoutingPenalty((PenaltyType)5, 100);
+ router->setRoutingOption((RoutingOption)0, false);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, true);
+ router->setRoutingOption(improveHyperedgeRoutesMovingAddingAndDeletingJunctions, true);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+ Polygon poly39761567(4);
+ poly39761567.ps[0] = Point(50754, 50975);
+ poly39761567.ps[1] = Point(50754, 51060);
+ poly39761567.ps[2] = Point(50696, 51060);
+ poly39761567.ps[3] = Point(50696, 50975);
+ ShapeRef *shapeRef39761567 = new ShapeRef(router, poly39761567, 39761567);
+ new ShapeConnectionPin(shapeRef39761567, 1, 0.5, 0, true, 10, (ConnDirFlags) 1);
+
+ Polygon poly115776716(4);
+ poly115776716.ps[0] = Point(51504, 50975);
+ poly115776716.ps[1] = Point(51504, 51060);
+ poly115776716.ps[2] = Point(51446, 51060);
+ poly115776716.ps[3] = Point(51446, 50975);
+ ShapeRef *shapeRef115776716 = new ShapeRef(router, poly115776716, 115776716);
+ new ShapeConnectionPin(shapeRef115776716, 1, 0.5, 0, true, 10, (ConnDirFlags) 1);
+
+ Polygon poly238475293(4);
+ poly238475293.ps[0] = Point(50554, 50975);
+ poly238475293.ps[1] = Point(50554, 51060);
+ poly238475293.ps[2] = Point(50496, 51060);
+ poly238475293.ps[3] = Point(50496, 50975);
+ ShapeRef *shapeRef238475293 = new ShapeRef(router, poly238475293, 238475293);
+ new ShapeConnectionPin(shapeRef238475293, 1, 0.5, 0, true, 10, (ConnDirFlags) 1);
+
+ Polygon poly430971008(4);
+ poly430971008.ps[0] = Point(51004, 50975);
+ poly430971008.ps[1] = Point(51004, 51060);
+ poly430971008.ps[2] = Point(50946, 51060);
+ poly430971008.ps[3] = Point(50946, 50975);
+ ShapeRef *shapeRef430971008 = new ShapeRef(router, poly430971008, 430971008);
+ new ShapeConnectionPin(shapeRef430971008, 1, 0.5, 0, true, 10, (ConnDirFlags) 1);
+
+ JunctionRef *junctionRef513246008 = new JunctionRef(router, Point(50925, 50725), 513246008);
+ /*
+ // This may be useful if junction pins are modified.
+ new ShapeConnectionPin(junctionRef513246008, 2147483646, (ConnDirFlags) 15);
+ */
+
+ ConnRef *connRef513246009 = new ConnRef(router, 513246009);
+ ConnEnd srcPt513246009(shapeRef39761567, 1);
+ connRef513246009->setSourceEndpoint(srcPt513246009);
+ ConnEnd dstPt513246009(junctionRef513246008);
+ connRef513246009->setDestEndpoint(dstPt513246009);
+ connRef513246009->setRoutingType((ConnType)2);
+
+ ConnRef *connRef513246010 = new ConnRef(router, 513246010);
+ ConnEnd srcPt513246010(junctionRef513246008);
+ connRef513246010->setSourceEndpoint(srcPt513246010);
+ ConnEnd dstPt513246010(shapeRef430971008, 1);
+ connRef513246010->setDestEndpoint(dstPt513246010);
+ connRef513246010->setRoutingType((ConnType)2);
+
+ ConnRef *connRef513246011 = new ConnRef(router, 513246011);
+ ConnEnd srcPt513246011(junctionRef513246008);
+ connRef513246011->setSourceEndpoint(srcPt513246011);
+ ConnEnd dstPt513246011(shapeRef238475293, 1);
+ connRef513246011->setDestEndpoint(dstPt513246011);
+ connRef513246011->setRoutingType((ConnType)2);
+
+ ConnRef *connRef513246012 = new ConnRef(router, 513246012);
+ ConnEnd srcPt513246012(shapeRef115776716, 1);
+ connRef513246012->setSourceEndpoint(srcPt513246012);
+ ConnEnd dstPt513246012(junctionRef513246008);
+ connRef513246012->setDestEndpoint(dstPt513246012);
+ connRef513246012->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/improveHyperedge03");
+
+ bool overlaps = router->existsOrthogonalSegmentOverlap(true);
+ delete router;
+ return (overlaps) ? 1 : 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge04.cpp b/src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge04.cpp
new file mode 100644
index 0000000..9ed66da
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge04.cpp
@@ -0,0 +1,113 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 200);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 9000);
+ router->setRoutingPenalty((PenaltyType)5, 100);
+ router->setRoutingOption((RoutingOption)0, false);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, true);
+ router->setRoutingOption(improveHyperedgeRoutesMovingJunctions, false);
+ router->setRoutingOption(improveHyperedgeRoutesMovingAddingAndDeletingJunctions, true);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(50354, 50975);
+ poly2.ps[1] = Point(50354, 51060);
+ poly2.ps[2] = Point(50296, 51060);
+ poly2.ps[3] = Point(50296, 50975);
+ ShapeRef *shapeRef2 = new ShapeRef(router, poly2, 2);
+ new ShapeConnectionPin(shapeRef2, 1, 0.5, 1, true, 10, (ConnDirFlags) 1);
+
+ Polygon poly39761567(4);
+ poly39761567.ps[0] = Point(50754, 50975);
+ poly39761567.ps[1] = Point(50754, 51060);
+ poly39761567.ps[2] = Point(50696, 51060);
+ poly39761567.ps[3] = Point(50696, 50975);
+ ShapeRef *shapeRef39761567 = new ShapeRef(router, poly39761567, 39761567);
+ new ShapeConnectionPin(shapeRef39761567, 1, 0.5, 0, true, 10, (ConnDirFlags) 1);
+
+ Polygon poly115776716(4);
+ poly115776716.ps[0] = Point(51504, 50975);
+ poly115776716.ps[1] = Point(51504, 51060);
+ poly115776716.ps[2] = Point(51446, 51060);
+ poly115776716.ps[3] = Point(51446, 50975);
+ ShapeRef *shapeRef115776716 = new ShapeRef(router, poly115776716, 115776716);
+ new ShapeConnectionPin(shapeRef115776716, 1, 0.5, 0, true, 10, (ConnDirFlags) 1);
+
+ Polygon poly238475293(4);
+ poly238475293.ps[0] = Point(50554, 50975);
+ poly238475293.ps[1] = Point(50554, 51060);
+ poly238475293.ps[2] = Point(50496, 51060);
+ poly238475293.ps[3] = Point(50496, 50975);
+ ShapeRef *shapeRef238475293 = new ShapeRef(router, poly238475293, 238475293);
+ new ShapeConnectionPin(shapeRef238475293, 1, 0.5, 0, true, 10, (ConnDirFlags) 1);
+
+ Polygon poly430971008(4);
+ poly430971008.ps[0] = Point(51004, 50975);
+ poly430971008.ps[1] = Point(51004, 51060);
+ poly430971008.ps[2] = Point(50946, 51060);
+ poly430971008.ps[3] = Point(50946, 50975);
+ ShapeRef *shapeRef430971008 = new ShapeRef(router, poly430971008, 430971008);
+ new ShapeConnectionPin(shapeRef430971008, 1, 0.5, 0, true, 10, (ConnDirFlags) 1);
+
+ JunctionRef *junctionRef513246008 = new JunctionRef(router, Point(50925, 50700), 513246008);
+ /*
+ // This may be useful if junction pins are modified.
+ new ShapeConnectionPin(junctionRef513246008, 2147483646, (ConnDirFlags) 15);
+ */
+ JunctionRef *junctionRef4 = new JunctionRef(router, Point(50725, 50725), 4);
+
+ ConnRef *connRef3 = new ConnRef(router, 3);
+ ConnEnd srcPt3(shapeRef2, 1);
+ connRef3->setSourceEndpoint(srcPt3);
+ ConnEnd dstPt3(junctionRef513246008);
+ connRef3->setDestEndpoint(dstPt3);
+ connRef3->setRoutingType((ConnType)2);
+
+ ConnRef *connRef5 = new ConnRef(router, 5);
+ ConnEnd srcPt5(junctionRef4);
+ connRef5->setSourceEndpoint(srcPt5);
+ ConnEnd dstPt5(junctionRef513246008);
+ connRef5->setDestEndpoint(dstPt5);
+ connRef5->setRoutingType((ConnType)2);
+
+ ConnRef *connRef513246009 = new ConnRef(router, 513246009);
+ ConnEnd srcPt513246009(shapeRef39761567, 1);
+ connRef513246009->setSourceEndpoint(srcPt513246009);
+ ConnEnd dstPt513246009(junctionRef4);
+ connRef513246009->setDestEndpoint(dstPt513246009);
+ connRef513246009->setRoutingType((ConnType)2);
+
+ ConnRef *connRef513246010 = new ConnRef(router, 513246010);
+ ConnEnd srcPt513246010(junctionRef513246008);
+ connRef513246010->setSourceEndpoint(srcPt513246010);
+ ConnEnd dstPt513246010(shapeRef430971008, 1);
+ connRef513246010->setDestEndpoint(dstPt513246010);
+ connRef513246010->setRoutingType((ConnType)2);
+
+ ConnRef *connRef513246011 = new ConnRef(router, 513246011);
+ ConnEnd srcPt513246011(junctionRef4);
+ connRef513246011->setSourceEndpoint(srcPt513246011);
+ ConnEnd dstPt513246011(shapeRef238475293, 1);
+ connRef513246011->setDestEndpoint(dstPt513246011);
+ connRef513246011->setRoutingType((ConnType)2);
+
+ ConnRef *connRef513246012 = new ConnRef(router, 513246012);
+ ConnEnd srcPt513246012(shapeRef115776716, 1);
+ connRef513246012->setSourceEndpoint(srcPt513246012);
+ ConnEnd dstPt513246012(junctionRef513246008);
+ connRef513246012->setDestEndpoint(dstPt513246012);
+ connRef513246012->setRoutingType((ConnType)2);
+ router->processTransaction();
+ router->outputDiagram("output/improveHyperedge04");
+
+ bool overlaps = router->existsOrthogonalSegmentOverlap(true);
+ delete router;
+ return (overlaps) ? 1 : 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge05.cpp b/src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge05.cpp
new file mode 100644
index 0000000..ff6ba17
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge05.cpp
@@ -0,0 +1,154 @@
+#include "libavoid/libavoid.h"
+#include <sstream>
+using namespace Avoid;
+
+void outputDiagram(Avoid::Router * router)
+{
+ static int counter = 0;
+ std::ostringstream os;
+ os << "output/improveHyperedge05-" << (++counter);
+ router->outputDiagram(os.str());
+}
+
+void test()
+{
+ // The contents of this function can be replaced by the automatically generated test code from the debug svg file
+ Avoid::ConnEnd end1_0;
+ Avoid::ConnEnd end2_0;
+ Avoid::Polygon poly0;
+ std::vector<Avoid::Checkpoint> checkpoints_0;
+ Avoid::Router * router0 = new Avoid::Router(Avoid::OrthogonalRouting);
+ Avoid::HyperedgeNewAndDeletedObjectLists newanddeletedobjects_0;
+ Avoid::ConnRefList::const_iterator connit_0;
+ Avoid::JunctionRefList::const_iterator junctionit_0;
+ router0->setTransactionUse(true);
+ router0->setRoutingPenalty(Avoid::segmentPenalty);
+ router0->setRoutingPenalty(Avoid::crossingPenalty);
+ router0->setRoutingPenalty(Avoid::fixedSharedPathPenalty, 9000);
+ router0->setRoutingOption(Avoid::penaliseOrthogonalSharedPathsAtConnEnds, true);
+ router0->setRoutingParameter(Avoid::idealNudgingDistance, 25);
+ router0->setRoutingOption(Avoid::improveHyperedgeRoutesMovingAddingAndDeletingJunctions, true);
+ router0->processTransaction();
+
+ newanddeletedobjects_0 = router0->newAndDeletedObjectListsFromHyperedgeImprovement();
+ outputDiagram(router0);
+
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(51885, 50715));
+ poly0.setPoint(1, Avoid::Point(51885, 50935));
+ poly0.setPoint(2, Avoid::Point(51700, 50935));
+ poly0.setPoint(3, Avoid::Point(51700, 50715));
+ Avoid::ShapeRef * shape0_68611488 = new Avoid::ShapeRef(router0, poly0, 68611488);
+ Avoid::ShapeConnectionPin * pin0_68611488_0 = new Avoid::ShapeConnectionPin(shape0_68611488, 1, 0.810810810811, 0.0454545454545, true, 10, 1);
+ pin0_68611488_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_68611488_1 = new Avoid::ShapeConnectionPin(shape0_68611488, 2, 0, 0.5, true, 10, 4);
+ pin0_68611488_1->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_68611488_2 = new Avoid::ShapeConnectionPin(shape0_68611488, 3, 0.810810810811, 0.954545454545, true, 10, 2);
+ pin0_68611488_2->setExclusive(true);
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(51600, 50795));
+ poly0.setPoint(1, Avoid::Point(51600, 50855));
+ poly0.setPoint(2, Avoid::Point(51440, 50855));
+ poly0.setPoint(3, Avoid::Point(51440, 50795));
+ Avoid::ShapeRef * shape0_84988680 = new Avoid::ShapeRef(router0, poly0, 84988680);
+ Avoid::ShapeConnectionPin * pin0_84988680_0 = new Avoid::ShapeConnectionPin(shape0_84988680, 1, 0.0625, 0.5, true, 10, 4);
+ pin0_84988680_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_84988680_1 = new Avoid::ShapeConnectionPin(shape0_84988680, 2, 1, 0.5, true, 10, 8);
+ pin0_84988680_1->setExclusive(true);
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(51705, 50640));
+ poly0.setPoint(1, Avoid::Point(51705, 50800));
+ poly0.setPoint(2, Avoid::Point(51645, 50800));
+ poly0.setPoint(3, Avoid::Point(51645, 50640));
+ Avoid::ShapeRef * shape0_170757006 = new Avoid::ShapeRef(router0, poly0, 170757006);
+ Avoid::ShapeConnectionPin * pin0_170757006_0 = new Avoid::ShapeConnectionPin(shape0_170757006, 1, 0.5, 1, true, 10, 2);
+ pin0_170757006_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_170757006_1 = new Avoid::ShapeConnectionPin(shape0_170757006, 2, 0.5, 0.0625, true, 10, 1);
+ pin0_170757006_1->setExclusive(true);
+ Avoid::JunctionRef * junction0_185122667 = new Avoid::JunctionRef(router0, Avoid::Point(51675, 50825), 185122667);
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(51705, 50925));
+ poly0.setPoint(1, Avoid::Point(51705, 51085));
+ poly0.setPoint(2, Avoid::Point(51645, 51085));
+ poly0.setPoint(3, Avoid::Point(51645, 50925));
+ Avoid::ShapeRef * shape0_300278382 = new Avoid::ShapeRef(router0, poly0, 300278382);
+ Avoid::ShapeConnectionPin * pin0_300278382_0 = new Avoid::ShapeConnectionPin(shape0_300278382, 1, 0.5, 0.9375, true, 10, 2);
+ pin0_300278382_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_300278382_1 = new Avoid::ShapeConnectionPin(shape0_300278382, 2, 0.5, 0, true, 10, 1);
+ pin0_300278382_1->setExclusive(true);
+ end1_0 = Avoid::ConnEnd(shape0_84988680, 2);
+ end2_0 = Avoid::ConnEnd(junction0_185122667);
+ new Avoid::ConnRef(router0, end1_0, end2_0, 70922320);
+ end1_0 = Avoid::ConnEnd(junction0_185122667);
+ end2_0 = Avoid::ConnEnd(shape0_68611488, 2);
+ new Avoid::ConnRef(router0, end1_0, end2_0, 141698060);
+ end1_0 = Avoid::ConnEnd(shape0_170757006, 1);
+ end2_0 = Avoid::ConnEnd(junction0_185122667);
+ new Avoid::ConnRef(router0, end1_0, end2_0, 27983869);
+ end1_0 = Avoid::ConnEnd(shape0_300278382, 2);
+ end2_0 = Avoid::ConnEnd(junction0_185122667);
+ new Avoid::ConnRef(router0, end1_0, end2_0, 197910572);
+ router0->processTransaction();
+ //printf("%d\n", junction0_185122667->attachedConnectors().size());
+ COLA_ASSERT(junction0_185122667->attachedConnectors().size() == 4);
+
+ newanddeletedobjects_0 = router0->newAndDeletedObjectListsFromHyperedgeImprovement();
+ outputDiagram(router0);
+ printf("\n\n\n");
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(51305, 50690));
+ poly0.setPoint(1, Avoid::Point(51305, 50850));
+ poly0.setPoint(2, Avoid::Point(51245, 50850));
+ poly0.setPoint(3, Avoid::Point(51245, 50690));
+ router0->moveShape(shape0_170757006, poly0);
+ router0->processTransaction();
+
+ newanddeletedobjects_0 = router0->newAndDeletedObjectListsFromHyperedgeImprovement();
+ junctionit_0 = newanddeletedobjects_0.newJunctionList.begin();
+ Avoid::JunctionRef * junction0_436653030 = *junctionit_0;
+ junction0_436653030->position();
+ //printf("%d %d\n", junction0_185122667->attachedConnectors().size(),
+ // junction0_436653030->attachedConnectors().size());
+ COLA_ASSERT(junction0_185122667->attachedConnectors().size() == 3);
+ COLA_ASSERT(junction0_436653030->attachedConnectors().size() == 3);
+
+ junction0_436653030->attachedConnectors();
+ junction0_436653030->setPositionFixed(true);
+ junctionit_0++;
+ COLA_ASSERT(junctionit_0 == newanddeletedobjects_0.newJunctionList.end());
+ connit_0 = newanddeletedobjects_0.newConnectorList.begin();
+ Avoid::ConnRef * conn0_400977693 = *connit_0;
+ conn0_400977693->endpointConnEnds();
+ connit_0++;
+ COLA_ASSERT(connit_0 == newanddeletedobjects_0.newConnectorList.end());
+ outputDiagram(router0);
+
+ conn0_400977693->makePathInvalid();
+ router0->processTransaction();
+
+ outputDiagram(router0);
+ return;
+/*
+ // INCORRECT
+ newanddeletedobjects_0 = router0->newAndDeletedObjectListsFromHyperedgeImprovement();
+ junctionit_0 = newanddeletedobjects_0.newJunctionList.begin();
+ Avoid::JunctionRef * junction0_112970070 = *junctionit_0;
+ junction0_112970070->position();
+ junction0_112970070->attachedConnectors();
+ junction0_112970070->setPositionFixed(true);
+ junctionit_0++;
+ COLA_ASSERT(junctionit_0 == newanddeletedobjects_0.newJunctionList.end());
+ connit_0 = newanddeletedobjects_0.newConnectorList.begin();
+ Avoid::ConnRef * conn0_152820633 = *connit_0;
+ conn0_152820633->endpointConnEnds();
+ connit_0++;
+ COLA_ASSERT(connit_0 == newanddeletedobjects_0.newConnectorList.end());
+ outputDiagram(router0);
+ */
+}
+
+extern "C" int main(void)
+{
+ test();
+ return 0;
+}
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge06.cpp b/src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge06.cpp
new file mode 100644
index 0000000..3322b98
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/improveHyperedge06.cpp
@@ -0,0 +1,92 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 200);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 9000);
+ router->setRoutingPenalty((PenaltyType)5, 100);
+ router->setRoutingOption((RoutingOption)0, false);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, true);
+ router->setRoutingOption(improveHyperedgeRoutesMovingAddingAndDeletingJunctions, true);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+ Polygon poly39761567(4);
+ poly39761567.ps[0] = Point(50754, 50975);
+ poly39761567.ps[1] = Point(50754, 51060);
+ poly39761567.ps[2] = Point(50696, 51060);
+ poly39761567.ps[3] = Point(50696, 50975);
+ ShapeRef *shapeRef39761567 = new ShapeRef(router, poly39761567, 39761567);
+ new ShapeConnectionPin(shapeRef39761567, 1, 0.5, 0, true, 10, (ConnDirFlags) 1);
+
+ Polygon poly115776716(4);
+ poly115776716.ps[0] = Point(51504, 50975);
+ poly115776716.ps[1] = Point(51504, 51060);
+ poly115776716.ps[2] = Point(51446, 51060);
+ poly115776716.ps[3] = Point(51446, 50975);
+ ShapeRef *shapeRef115776716 = new ShapeRef(router, poly115776716, 115776716);
+ new ShapeConnectionPin(shapeRef115776716, 1, 0.5, 0, true, 10, (ConnDirFlags) 1);
+
+ Polygon poly238475293(4);
+ poly238475293.ps[0] = Point(50554, 50975);
+ poly238475293.ps[1] = Point(50554, 51060);
+ poly238475293.ps[2] = Point(50496, 51060);
+ poly238475293.ps[3] = Point(50496, 50975);
+ ShapeRef *shapeRef238475293 = new ShapeRef(router, poly238475293, 238475293);
+ new ShapeConnectionPin(shapeRef238475293, 1, 0.5, 0, true, 10, (ConnDirFlags) 1);
+
+ Polygon poly430971008(4);
+ poly430971008.ps[0] = Point(51004, 50465);
+ poly430971008.ps[1] = Point(51004, 50550);
+ poly430971008.ps[2] = Point(50946, 50550);
+ poly430971008.ps[3] = Point(50946, 50465);
+ ShapeRef *shapeRef430971008 = new ShapeRef(router, poly430971008, 430971008);
+ new ShapeConnectionPin(shapeRef430971008, 1, 0.5, 1, true, 10, (ConnDirFlags) 2);
+
+ JunctionRef *junctionRef513246008 = new JunctionRef(router, Point(50925, 50725), 513246008);
+ junctionRef513246008->setPositionFixed(true);
+
+ /*
+ // This may be useful if junction pins are modified.
+ new ShapeConnectionPin(junctionRef513246008, 2147483646, (ConnDirFlags) 15);
+ */
+
+ ConnRef *connRef513246009 = new ConnRef(router, 513246009);
+ ConnEnd srcPt513246009(shapeRef39761567, 1);
+ connRef513246009->setSourceEndpoint(srcPt513246009);
+ ConnEnd dstPt513246009(junctionRef513246008);
+ connRef513246009->setDestEndpoint(dstPt513246009);
+ connRef513246009->setRoutingType((ConnType)2);
+
+ ConnRef *connRef513246010 = new ConnRef(router, 513246010);
+ ConnEnd srcPt513246010(junctionRef513246008);
+ connRef513246010->setSourceEndpoint(srcPt513246010);
+ ConnEnd dstPt513246010(shapeRef430971008, 1);
+ connRef513246010->setDestEndpoint(dstPt513246010);
+ connRef513246010->setRoutingType((ConnType)2);
+
+ ConnRef *connRef513246011 = new ConnRef(router, 513246011);
+ ConnEnd srcPt513246011(junctionRef513246008);
+ connRef513246011->setSourceEndpoint(srcPt513246011);
+ ConnEnd dstPt513246011(shapeRef238475293, 1);
+ connRef513246011->setDestEndpoint(dstPt513246011);
+ connRef513246011->setRoutingType((ConnType)2);
+
+ ConnRef *connRef513246012 = new ConnRef(router, 513246012);
+ ConnEnd srcPt513246012(shapeRef115776716, 1);
+ connRef513246012->setSourceEndpoint(srcPt513246012);
+ ConnEnd dstPt513246012(junctionRef513246008);
+ connRef513246012->setDestEndpoint(dstPt513246012);
+ connRef513246012->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/improveHyperedge06");
+
+ bool overlaps = router->existsOrthogonalSegmentOverlap(true);
+ delete router;
+ return (overlaps) ? 1 : 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/infinity.cpp b/src/3rdparty/adaptagrams/libavoid/tests/infinity.cpp
new file mode 100644
index 0000000..1fbf683
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/infinity.cpp
@@ -0,0 +1,26 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingPenalty(segmentPenalty, 50);
+ router->setRoutingParameter(idealNudgingDistance, 10);
+ Rectangle rect47(Point(51145, 50195), Point(51145+360, 50195+685));
+ new ShapeRef(router, rect47);
+ Rectangle rect46(Point(51920, 49770), Point(51920+360, 49770+310));
+ new ShapeRef(router, rect46);
+ Rectangle rect45(Point(51151, 49770), Point(51151+360, 49770+310));
+ new ShapeRef(router, rect45);
+ ConnEnd srcPt53(Point(51150,49850), 4);
+ ConnEnd dstPt53(Point(51500,50350), 8);
+ new ConnRef(router, srcPt53, dstPt53);
+ ConnEnd srcPt52(Point(52275,49850), 8);
+ ConnEnd dstPt52(Point(51150,49925), 4);
+ new ConnRef(router, srcPt52, dstPt52);
+ ConnEnd srcPt6(Point(51150,50500), 4);
+ ConnEnd dstPt6(Point(51925,50000), 4);
+ new ConnRef(router, srcPt6, dstPt6, 6);
+ router->processTransaction();
+ router->outputDiagram("output/infinity");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/inline.cpp b/src/3rdparty/adaptagrams/libavoid/tests/inline.cpp
new file mode 100644
index 0000000..ee10ce9
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/inline.cpp
@@ -0,0 +1,73 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ * Copyright (C) 2004-2007 Michael Wybrow <mjwybrow@users.sourceforge.net>
+ * Copyright (C) 2009 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow <mjwybrow@users.sourceforge.net>
+*/
+
+#include "libavoid/libavoid.h"
+
+using Avoid::ConnDirUp;
+using Avoid::ConnDirDown;
+using Avoid::ConnDirLeft;
+using Avoid::ConnDirRight;
+
+int main(void)
+{
+ Avoid::Router *router = new Avoid::Router(Avoid::OrthogonalRouting);
+
+ // Create the ShapeRef:
+ Avoid::Rectangle shapePoly(Avoid::Point(0, 0), Avoid::Point(100, 100));
+ new Avoid::ShapeRef(router, shapePoly);
+
+ Avoid::ConnEnd srcPt(Avoid::Point(200, 200));
+
+ Avoid::ConnEnd dstPt(Avoid::Point(95, 25),
+ ConnDirUp | ConnDirRight | ConnDirDown);
+ new Avoid::ConnRef(router, srcPt, dstPt);
+
+ dstPt = Avoid::ConnEnd(Avoid::Point(95, 75),
+ ConnDirUp | ConnDirRight | ConnDirDown);
+ new Avoid::ConnRef(router, srcPt, dstPt);
+
+ // Up goes towards negative coordinates.
+ dstPt = Avoid::ConnEnd(Avoid::Point(25, 5),
+ ConnDirLeft | ConnDirRight | ConnDirUp);
+ new Avoid::ConnRef(router, srcPt, dstPt);
+
+ dstPt = Avoid::ConnEnd(Avoid::Point(75, 5),
+ ConnDirLeft | ConnDirRight | ConnDirUp);
+ new Avoid::ConnRef(router, srcPt, dstPt);
+
+ dstPt = Avoid::ConnEnd(Avoid::Point(25, 95),
+ ConnDirLeft | ConnDirRight | ConnDirDown);
+ new Avoid::ConnRef(router, srcPt, dstPt);
+
+ dstPt = Avoid::ConnEnd(Avoid::Point(75, 95),
+ ConnDirLeft | ConnDirRight | ConnDirDown);
+ new Avoid::ConnRef(router, srcPt, dstPt);
+
+ router->processTransaction();
+ router->outputDiagram("output/inline");
+
+ delete router;
+ return 0;
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/inlineOverlap09.cpp b/src/3rdparty/adaptagrams/libavoid/tests/inlineOverlap09.cpp
new file mode 100644
index 0000000..1ab9c6d
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/inlineOverlap09.cpp
@@ -0,0 +1,401 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingParameter((RoutingParameter)0, 10);
+ router->setRoutingParameter((RoutingParameter)1, 0);
+ router->setRoutingParameter((RoutingParameter)2, 100);
+ router->setRoutingParameter((RoutingParameter)3, 4000);
+ router->setRoutingParameter((RoutingParameter)4, 1000);
+ router->setRoutingParameter((RoutingParameter)5, 100);
+ router->setRoutingParameter((RoutingParameter)6, 20);
+ router->setRoutingParameter((RoutingParameter)7, 40);
+ router->setRoutingOption((RoutingOption)0, false);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, false);
+ router->setRoutingOption((RoutingOption)3, false);
+ Polygon poly1(4);
+ poly1.ps[0] = Point(3.43711e+006, 6.73107e+006);
+ poly1.ps[1] = Point(3.43711e+006, 6.73108e+006);
+ poly1.ps[2] = Point(3.4371e+006, 6.73108e+006);
+ poly1.ps[3] = Point(3.4371e+006, 6.73107e+006);
+ new ShapeRef(router, poly1, 1);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(3.43536e+006, 6.73107e+006);
+ poly2.ps[1] = Point(3.43536e+006, 6.73108e+006);
+ poly2.ps[2] = Point(3.43535e+006, 6.73108e+006);
+ poly2.ps[3] = Point(3.43535e+006, 6.73107e+006);
+ new ShapeRef(router, poly2, 2);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(3.43786e+006, 6.73107e+006);
+ poly3.ps[1] = Point(3.43786e+006, 6.73108e+006);
+ poly3.ps[2] = Point(3.43785e+006, 6.73108e+006);
+ poly3.ps[3] = Point(3.43785e+006, 6.73107e+006);
+ new ShapeRef(router, poly3, 3);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(3.43736e+006, 6.73107e+006);
+ poly4.ps[1] = Point(3.43736e+006, 6.73108e+006);
+ poly4.ps[2] = Point(3.43735e+006, 6.73108e+006);
+ poly4.ps[3] = Point(3.43735e+006, 6.73107e+006);
+ new ShapeRef(router, poly4, 4);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(3.4349e+006, 6.73107e+006);
+ poly5.ps[1] = Point(3.4349e+006, 6.73108e+006);
+ poly5.ps[2] = Point(3.43489e+006, 6.73108e+006);
+ poly5.ps[3] = Point(3.43489e+006, 6.73107e+006);
+ new ShapeRef(router, poly5, 5);
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(3.43573e+006, 6.73052e+006);
+ poly6.ps[1] = Point(3.43573e+006, 6.73053e+006);
+ poly6.ps[2] = Point(3.43572e+006, 6.73053e+006);
+ poly6.ps[3] = Point(3.43572e+006, 6.73052e+006);
+ new ShapeRef(router, poly6, 6);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(3.43636e+006, 6.73107e+006);
+ poly7.ps[1] = Point(3.43636e+006, 6.73108e+006);
+ poly7.ps[2] = Point(3.43635e+006, 6.73108e+006);
+ poly7.ps[3] = Point(3.43635e+006, 6.73107e+006);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(3.43769e+006, 6.73107e+006);
+ poly8.ps[1] = Point(3.43769e+006, 6.73108e+006);
+ poly8.ps[2] = Point(3.43768e+006, 6.73108e+006);
+ poly8.ps[3] = Point(3.43768e+006, 6.73107e+006);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(3.43761e+006, 6.73107e+006);
+ poly9.ps[1] = Point(3.43761e+006, 6.73108e+006);
+ poly9.ps[2] = Point(3.4376e+006, 6.73108e+006);
+ poly9.ps[3] = Point(3.4376e+006, 6.73107e+006);
+ new ShapeRef(router, poly9, 9);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(3.43661e+006, 6.73107e+006);
+ poly10.ps[1] = Point(3.43661e+006, 6.73108e+006);
+ poly10.ps[2] = Point(3.4366e+006, 6.73108e+006);
+ poly10.ps[3] = Point(3.4366e+006, 6.73107e+006);
+ new ShapeRef(router, poly10, 10);
+
+ Polygon poly11(4);
+ poly11.ps[0] = Point(3.4369e+006, 6.73107e+006);
+ poly11.ps[1] = Point(3.4369e+006, 6.73108e+006);
+ poly11.ps[2] = Point(3.43689e+006, 6.73108e+006);
+ poly11.ps[3] = Point(3.43689e+006, 6.73107e+006);
+ new ShapeRef(router, poly11, 11);
+
+ Polygon poly12(4);
+ poly12.ps[0] = Point(3.43619e+006, 6.73107e+006);
+ poly12.ps[1] = Point(3.43619e+006, 6.73108e+006);
+ poly12.ps[2] = Point(3.43618e+006, 6.73108e+006);
+ poly12.ps[3] = Point(3.43618e+006, 6.73107e+006);
+ new ShapeRef(router, poly12, 12);
+
+ Polygon poly13(4);
+ poly13.ps[0] = Point(3.43611e+006, 6.73107e+006);
+ poly13.ps[1] = Point(3.43611e+006, 6.73108e+006);
+ poly13.ps[2] = Point(3.4361e+006, 6.73108e+006);
+ poly13.ps[3] = Point(3.4361e+006, 6.73107e+006);
+ new ShapeRef(router, poly13, 13);
+
+ Polygon poly14(4);
+ poly14.ps[0] = Point(3.43461e+006, 6.73107e+006);
+ poly14.ps[1] = Point(3.43461e+006, 6.73108e+006);
+ poly14.ps[2] = Point(3.4346e+006, 6.73108e+006);
+ poly14.ps[3] = Point(3.4346e+006, 6.73107e+006);
+ new ShapeRef(router, poly14, 14);
+
+ Polygon poly15(4);
+ poly15.ps[0] = Point(3.43476e+006, 6.73128e+006);
+ poly15.ps[1] = Point(3.43476e+006, 6.73148e+006);
+ poly15.ps[2] = Point(3.43456e+006, 6.73148e+006);
+ poly15.ps[3] = Point(3.43456e+006, 6.73128e+006);
+ new ShapeRef(router, poly15, 15);
+
+ Polygon poly16(4);
+ poly16.ps[0] = Point(3.43476e+006, 6.73013e+006);
+ poly16.ps[1] = Point(3.43476e+006, 6.73033e+006);
+ poly16.ps[2] = Point(3.43456e+006, 6.73033e+006);
+ poly16.ps[3] = Point(3.43456e+006, 6.73013e+006);
+ new ShapeRef(router, poly16, 16);
+
+ Polygon poly17(4);
+ poly17.ps[0] = Point(3.43501e+006, 6.73013e+006);
+ poly17.ps[1] = Point(3.43501e+006, 6.73033e+006);
+ poly17.ps[2] = Point(3.43481e+006, 6.73033e+006);
+ poly17.ps[3] = Point(3.43481e+006, 6.73013e+006);
+ new ShapeRef(router, poly17, 17);
+
+ Polygon poly18(4);
+ poly18.ps[0] = Point(3.43526e+006, 6.73013e+006);
+ poly18.ps[1] = Point(3.43526e+006, 6.73033e+006);
+ poly18.ps[2] = Point(3.43506e+006, 6.73033e+006);
+ poly18.ps[3] = Point(3.43506e+006, 6.73013e+006);
+ new ShapeRef(router, poly18, 18);
+
+ Polygon poly19(4);
+ poly19.ps[0] = Point(3.43551e+006, 6.73013e+006);
+ poly19.ps[1] = Point(3.43551e+006, 6.73033e+006);
+ poly19.ps[2] = Point(3.43531e+006, 6.73033e+006);
+ poly19.ps[3] = Point(3.43531e+006, 6.73013e+006);
+ new ShapeRef(router, poly19, 19);
+
+ Polygon poly20(4);
+ poly20.ps[0] = Point(3.43501e+006, 6.73128e+006);
+ poly20.ps[1] = Point(3.43501e+006, 6.73148e+006);
+ poly20.ps[2] = Point(3.43481e+006, 6.73148e+006);
+ poly20.ps[3] = Point(3.43481e+006, 6.73128e+006);
+ new ShapeRef(router, poly20, 20);
+
+ Polygon poly21(4);
+ poly21.ps[0] = Point(3.43526e+006, 6.73128e+006);
+ poly21.ps[1] = Point(3.43526e+006, 6.73148e+006);
+ poly21.ps[2] = Point(3.43506e+006, 6.73148e+006);
+ poly21.ps[3] = Point(3.43506e+006, 6.73128e+006);
+ new ShapeRef(router, poly21, 21);
+
+ Polygon poly22(4);
+ poly22.ps[0] = Point(3.43551e+006, 6.73128e+006);
+ poly22.ps[1] = Point(3.43551e+006, 6.73148e+006);
+ poly22.ps[2] = Point(3.43531e+006, 6.73148e+006);
+ poly22.ps[3] = Point(3.43531e+006, 6.73128e+006);
+ new ShapeRef(router, poly22, 22);
+
+ Polygon poly23(4);
+ poly23.ps[0] = Point(3.43576e+006, 6.73128e+006);
+ poly23.ps[1] = Point(3.43576e+006, 6.73148e+006);
+ poly23.ps[2] = Point(3.43556e+006, 6.73148e+006);
+ poly23.ps[3] = Point(3.43556e+006, 6.73128e+006);
+ new ShapeRef(router, poly23, 23);
+
+ Polygon poly24(4);
+ poly24.ps[0] = Point(3.43601e+006, 6.73128e+006);
+ poly24.ps[1] = Point(3.43601e+006, 6.73148e+006);
+ poly24.ps[2] = Point(3.43581e+006, 6.73148e+006);
+ poly24.ps[3] = Point(3.43581e+006, 6.73128e+006);
+ new ShapeRef(router, poly24, 24);
+
+ Polygon poly25(4);
+ poly25.ps[0] = Point(3.43626e+006, 6.73128e+006);
+ poly25.ps[1] = Point(3.43626e+006, 6.73148e+006);
+ poly25.ps[2] = Point(3.43606e+006, 6.73148e+006);
+ poly25.ps[3] = Point(3.43606e+006, 6.73128e+006);
+ new ShapeRef(router, poly25, 25);
+
+ Polygon poly26(4);
+ poly26.ps[0] = Point(3.43651e+006, 6.73128e+006);
+ poly26.ps[1] = Point(3.43651e+006, 6.73148e+006);
+ poly26.ps[2] = Point(3.43631e+006, 6.73148e+006);
+ poly26.ps[3] = Point(3.43631e+006, 6.73128e+006);
+ new ShapeRef(router, poly26, 26);
+
+ Polygon poly27(4);
+ poly27.ps[0] = Point(3.43676e+006, 6.73128e+006);
+ poly27.ps[1] = Point(3.43676e+006, 6.73148e+006);
+ poly27.ps[2] = Point(3.43656e+006, 6.73148e+006);
+ poly27.ps[3] = Point(3.43656e+006, 6.73128e+006);
+ new ShapeRef(router, poly27, 27);
+
+ Polygon poly28(4);
+ poly28.ps[0] = Point(3.43701e+006, 6.73128e+006);
+ poly28.ps[1] = Point(3.43701e+006, 6.73148e+006);
+ poly28.ps[2] = Point(3.43681e+006, 6.73148e+006);
+ poly28.ps[3] = Point(3.43681e+006, 6.73128e+006);
+ new ShapeRef(router, poly28, 28);
+
+ Polygon poly29(4);
+ poly29.ps[0] = Point(3.43726e+006, 6.73128e+006);
+ poly29.ps[1] = Point(3.43726e+006, 6.73148e+006);
+ poly29.ps[2] = Point(3.43706e+006, 6.73148e+006);
+ poly29.ps[3] = Point(3.43706e+006, 6.73128e+006);
+ new ShapeRef(router, poly29, 29);
+
+ Polygon poly30(4);
+ poly30.ps[0] = Point(3.43751e+006, 6.73128e+006);
+ poly30.ps[1] = Point(3.43751e+006, 6.73148e+006);
+ poly30.ps[2] = Point(3.43731e+006, 6.73148e+006);
+ poly30.ps[3] = Point(3.43731e+006, 6.73128e+006);
+ new ShapeRef(router, poly30, 30);
+
+ Polygon poly31(4);
+ poly31.ps[0] = Point(3.43776e+006, 6.73128e+006);
+ poly31.ps[1] = Point(3.43776e+006, 6.73148e+006);
+ poly31.ps[2] = Point(3.43756e+006, 6.73148e+006);
+ poly31.ps[3] = Point(3.43756e+006, 6.73128e+006);
+ new ShapeRef(router, poly31, 31);
+
+ Polygon poly32(4);
+ poly32.ps[0] = Point(3.43576e+006, 6.73013e+006);
+ poly32.ps[1] = Point(3.43576e+006, 6.73033e+006);
+ poly32.ps[2] = Point(3.43556e+006, 6.73033e+006);
+ poly32.ps[3] = Point(3.43556e+006, 6.73013e+006);
+ new ShapeRef(router, poly32, 32);
+
+ Polygon poly33(4);
+ poly33.ps[0] = Point(3.43801e+006, 6.73128e+006);
+ poly33.ps[1] = Point(3.43801e+006, 6.73148e+006);
+ poly33.ps[2] = Point(3.43781e+006, 6.73148e+006);
+ poly33.ps[3] = Point(3.43781e+006, 6.73128e+006);
+ new ShapeRef(router, poly33, 33);
+
+ ConnRef *connRef34 = new ConnRef(router, 34);
+ ConnEnd srcPt34(Point(3.4351e+006, 6.73033e+006), 2);
+ connRef34->setSourceEndpoint(srcPt34);
+ ConnEnd dstPt34(Point(3.4356e+006, 6.73128e+006), 1);
+ connRef34->setDestEndpoint(dstPt34);
+ connRef34->setRoutingType((ConnType)2);
+
+ ConnRef *connRef35 = new ConnRef(router, 35);
+ ConnEnd srcPt35(Point(3.43485e+006, 6.73033e+006), 2);
+ connRef35->setSourceEndpoint(srcPt35);
+ ConnEnd dstPt35(Point(3.4351e+006, 6.73128e+006), 1);
+ connRef35->setDestEndpoint(dstPt35);
+ connRef35->setRoutingType((ConnType)2);
+
+ ConnRef *connRef36 = new ConnRef(router, 36);
+ ConnEnd srcPt36(Point(3.4346e+006, 6.73033e+006), 2);
+ connRef36->setSourceEndpoint(srcPt36);
+ ConnEnd dstPt36(Point(3.43485e+006, 6.73128e+006), 1);
+ connRef36->setDestEndpoint(dstPt36);
+ connRef36->setRoutingType((ConnType)2);
+
+ ConnRef *connRef37 = new ConnRef(router, 37);
+ ConnEnd srcPt37(Point(3.4356e+006, 6.73033e+006), 2);
+ connRef37->setSourceEndpoint(srcPt37);
+ ConnEnd dstPt37(Point(3.43685e+006, 6.73128e+006), 1);
+ connRef37->setDestEndpoint(dstPt37);
+ connRef37->setRoutingType((ConnType)2);
+
+ ConnRef *connRef38 = new ConnRef(router, 38);
+ ConnEnd srcPt38(Point(3.43564e+006, 6.73033e+006), 2);
+ connRef38->setSourceEndpoint(srcPt38);
+ ConnEnd dstPt38(Point(3.43764e+006, 6.73128e+006), 1);
+ connRef38->setDestEndpoint(dstPt38);
+ connRef38->setRoutingType((ConnType)2);
+
+ ConnRef *connRef39 = new ConnRef(router, 39);
+ ConnEnd srcPt39(Point(3.43568e+006, 6.73033e+006), 2);
+ connRef39->setSourceEndpoint(srcPt39);
+ ConnEnd dstPt39(Point(3.43614e+006, 6.73128e+006), 1);
+ connRef39->setDestEndpoint(dstPt39);
+ connRef39->setRoutingType((ConnType)2);
+
+ ConnRef *connRef40 = new ConnRef(router, 40);
+ ConnEnd srcPt40(Point(3.43572e+006, 6.73033e+006), 2);
+ connRef40->setSourceEndpoint(srcPt40);
+ ConnEnd dstPt40(Point(3.43572e+006, 6.73052e+006), 1);
+ connRef40->setDestEndpoint(dstPt40);
+ connRef40->setRoutingType((ConnType)2);
+
+ ConnRef *connRef41 = new ConnRef(router, 41);
+ ConnEnd srcPt41(Point(3.43535e+006, 6.73033e+006), 2);
+ connRef41->setSourceEndpoint(srcPt41);
+ ConnEnd dstPt41(Point(3.43585e+006, 6.73128e+006), 1);
+ connRef41->setDestEndpoint(dstPt41);
+ connRef41->setRoutingType((ConnType)2);
+
+ ConnRef *connRef42 = new ConnRef(router, 42);
+ ConnEnd srcPt42(Point(3.43535e+006, 6.73128e+006), 1);
+ connRef42->setSourceEndpoint(srcPt42);
+ ConnEnd dstPt42(Point(3.43535e+006, 6.73108e+006), 2);
+ connRef42->setDestEndpoint(dstPt42);
+ connRef42->setRoutingType((ConnType)2);
+
+ ConnRef *connRef43 = new ConnRef(router, 43);
+ ConnEnd srcPt43(Point(3.4366e+006, 6.73128e+006), 1);
+ connRef43->setSourceEndpoint(srcPt43);
+ ConnEnd dstPt43(Point(3.4366e+006, 6.73108e+006), 2);
+ connRef43->setDestEndpoint(dstPt43);
+ connRef43->setRoutingType((ConnType)2);
+
+ ConnRef *connRef44 = new ConnRef(router, 44);
+ ConnEnd srcPt44(Point(3.43489e+006, 6.73128e+006), 1);
+ connRef44->setSourceEndpoint(srcPt44);
+ ConnEnd dstPt44(Point(3.43489e+006, 6.73108e+006), 2);
+ connRef44->setDestEndpoint(dstPt44);
+ connRef44->setRoutingType((ConnType)2);
+
+ ConnRef *connRef45 = new ConnRef(router, 45);
+ ConnEnd srcPt45(Point(3.43689e+006, 6.73128e+006), 1);
+ connRef45->setSourceEndpoint(srcPt45);
+ ConnEnd dstPt45(Point(3.43689e+006, 6.73108e+006), 2);
+ connRef45->setDestEndpoint(dstPt45);
+ connRef45->setRoutingType((ConnType)2);
+
+ ConnRef *connRef46 = new ConnRef(router, 46);
+ ConnEnd srcPt46(Point(3.4361e+006, 6.73128e+006), 1);
+ connRef46->setSourceEndpoint(srcPt46);
+ ConnEnd dstPt46(Point(3.4361e+006, 6.73108e+006), 2);
+ connRef46->setDestEndpoint(dstPt46);
+ connRef46->setRoutingType((ConnType)2);
+
+ ConnRef *connRef47 = new ConnRef(router, 47);
+ ConnEnd srcPt47(Point(3.43618e+006, 6.73128e+006), 1);
+ connRef47->setSourceEndpoint(srcPt47);
+ ConnEnd dstPt47(Point(3.43618e+006, 6.73108e+006), 2);
+ connRef47->setDestEndpoint(dstPt47);
+ connRef47->setRoutingType((ConnType)2);
+
+ ConnRef *connRef48 = new ConnRef(router, 48);
+ ConnEnd srcPt48(Point(3.4371e+006, 6.73128e+006), 1);
+ connRef48->setSourceEndpoint(srcPt48);
+ ConnEnd dstPt48(Point(3.4371e+006, 6.73108e+006), 2);
+ connRef48->setDestEndpoint(dstPt48);
+ connRef48->setRoutingType((ConnType)2);
+
+ ConnRef *connRef49 = new ConnRef(router, 49);
+ ConnEnd srcPt49(Point(3.43735e+006, 6.73128e+006), 1);
+ connRef49->setSourceEndpoint(srcPt49);
+ ConnEnd dstPt49(Point(3.43735e+006, 6.73108e+006), 2);
+ connRef49->setDestEndpoint(dstPt49);
+ connRef49->setRoutingType((ConnType)2);
+
+ ConnRef *connRef50 = new ConnRef(router, 50);
+ ConnEnd srcPt50(Point(3.4376e+006, 6.73128e+006), 1);
+ connRef50->setSourceEndpoint(srcPt50);
+ ConnEnd dstPt50(Point(3.4376e+006, 6.73108e+006), 2);
+ connRef50->setDestEndpoint(dstPt50);
+ connRef50->setRoutingType((ConnType)2);
+
+ ConnRef *connRef51 = new ConnRef(router, 51);
+ ConnEnd srcPt51(Point(3.43768e+006, 6.73128e+006), 1);
+ connRef51->setSourceEndpoint(srcPt51);
+ ConnEnd dstPt51(Point(3.43768e+006, 6.73108e+006), 2);
+ connRef51->setDestEndpoint(dstPt51);
+ connRef51->setRoutingType((ConnType)2);
+
+ ConnRef *connRef52 = new ConnRef(router, 52);
+ ConnEnd srcPt52(Point(3.4346e+006, 6.73128e+006), 1);
+ connRef52->setSourceEndpoint(srcPt52);
+ ConnEnd dstPt52(Point(3.4346e+006, 6.73108e+006), 2);
+ connRef52->setDestEndpoint(dstPt52);
+ connRef52->setRoutingType((ConnType)2);
+
+ ConnRef *connRef53 = new ConnRef(router, 53);
+ ConnEnd srcPt53(Point(3.43635e+006, 6.73128e+006), 1);
+ connRef53->setSourceEndpoint(srcPt53);
+ ConnEnd dstPt53(Point(3.43635e+006, 6.73108e+006), 2);
+ connRef53->setDestEndpoint(dstPt53);
+ connRef53->setRoutingType((ConnType)2);
+
+ ConnRef *connRef54 = new ConnRef(router, 54);
+ ConnEnd srcPt54(Point(3.43785e+006, 6.73128e+006), 1);
+ connRef54->setSourceEndpoint(srcPt54);
+ ConnEnd dstPt54(Point(3.43785e+006, 6.73108e+006), 2);
+ connRef54->setDestEndpoint(dstPt54);
+ connRef54->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/inlineOverlap09");
+ bool overlap = router->existsOrthogonalFixedSegmentOverlap();
+ delete router;
+ return (overlap) ? 1 : 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/inlineOverlap10.cpp b/src/3rdparty/adaptagrams/libavoid/tests/inlineOverlap10.cpp
new file mode 100644
index 0000000..648eed5
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/inlineOverlap10.cpp
@@ -0,0 +1,93 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingParameter((RoutingParameter)0, 50);
+ router->setRoutingParameter((RoutingParameter)1, 0);
+ router->setRoutingParameter((RoutingParameter)2, 200);
+ router->setRoutingParameter((RoutingParameter)3, 4000);
+ router->setRoutingParameter((RoutingParameter)4, 20000);
+ router->setRoutingParameter((RoutingParameter)5, 100);
+ router->setRoutingParameter((RoutingParameter)6, 0);
+ router->setRoutingParameter((RoutingParameter)7, 25);
+ router->setRoutingOption((RoutingOption)0, false);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, true);
+ router->setRoutingOption((RoutingOption)3, false);
+ router->setRoutingOption((RoutingOption)4, true);
+ router->setRoutingOption((RoutingOption)5, true);
+ Polygon polygon;
+ ConnRef *connRef = nullptr;
+ ConnEnd srcPt;
+ ConnEnd dstPt;
+ PolyLine newRoute;
+ // shapeRef320077872
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(51000, 50740);
+ polygon.ps[1] = Point(51000, 51135);
+ polygon.ps[2] = Point(50650, 51135);
+ polygon.ps[3] = Point(50650, 50740);
+ ShapeRef *shapeRef320077872 = new ShapeRef(router, polygon, 320077872);
+ new ShapeConnectionPin(shapeRef320077872, 1, 0, 0.21519, true, 10, (ConnDirFlags) 4);
+ new ShapeConnectionPin(shapeRef320077872, 2, 1, 0.21519, true, 10, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef320077872, 3, 0.0714286, 0.405063, true, 10, (ConnDirFlags) 4);
+ new ShapeConnectionPin(shapeRef320077872, 4, 1, 0.405063, true, 10, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef320077872, 5, 0.0714286, 0.594937, true, 10, (ConnDirFlags) 4);
+ new ShapeConnectionPin(shapeRef320077872, 6, 1, 0.594937, true, 10, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef320077872, 7, 0, 0.78481, true, 10, (ConnDirFlags) 4);
+ new ShapeConnectionPin(shapeRef320077872, 8, 1, 0.78481, true, 10, (ConnDirFlags) 8);
+
+ // shapeRef346216920
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(51650, 50740);
+ polygon.ps[1] = Point(51650, 51135);
+ polygon.ps[2] = Point(51300, 51135);
+ polygon.ps[3] = Point(51300, 50740);
+ ShapeRef *shapeRef346216920 = new ShapeRef(router, polygon, 346216920);
+ new ShapeConnectionPin(shapeRef346216920, 1, 0, 0.21519, true, 10, (ConnDirFlags) 4);
+ new ShapeConnectionPin(shapeRef346216920, 2, 1, 0.21519, true, 10, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef346216920, 3, 0, 0.405063, true, 10, (ConnDirFlags) 4);
+ new ShapeConnectionPin(shapeRef346216920, 4, 0.928571, 0.405063, true, 10, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef346216920, 5, 0, 0.594937, true, 10, (ConnDirFlags) 4);
+ new ShapeConnectionPin(shapeRef346216920, 6, 0.928571, 0.594937, true, 10, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef346216920, 7, 0, 0.78481, true, 10, (ConnDirFlags) 4);
+ new ShapeConnectionPin(shapeRef346216920, 8, 1, 0.78481, true, 10, (ConnDirFlags) 8);
+
+ // connRef13958908
+ connRef = new ConnRef(router, 13958908);
+ srcPt = ConnEnd(shapeRef346216920, 3);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef320077872, 6);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef81482716
+ connRef = new ConnRef(router, 81482716);
+ srcPt = ConnEnd(shapeRef320077872, 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef346216920, 7);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef180721992
+ connRef = new ConnRef(router, 180721992);
+ srcPt = ConnEnd(shapeRef320077872, 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef346216920, 5);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef273666240
+ connRef = new ConnRef(router, 273666240);
+ srcPt = ConnEnd(shapeRef320077872, 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef346216920, 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/inlineoverlap10");
+ bool overlap = router->existsOrthogonalFixedSegmentOverlap();
+ delete router;
+ return (overlap) ? 1 : 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/inlineOverlap11.cpp b/src/3rdparty/adaptagrams/libavoid/tests/inlineOverlap11.cpp
new file mode 100644
index 0000000..46cdd87
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/inlineOverlap11.cpp
@@ -0,0 +1,187 @@
+// From endpointOverlap.cpp
+#include "libavoid/libavoid.h"
+#include <sstream>
+
+extern "C" int main(void)
+{
+ // The contents of this function can be replaced by the automatically generated test code from the debug svg file
+ Avoid::ConnEnd end1_0;
+ Avoid::ConnEnd end2_0;
+ Avoid::Polygon poly0;
+ Avoid::Router * router0 = new Avoid::Router(Avoid::OrthogonalRouting);
+ Avoid::HyperedgeNewAndDeletedObjectLists newanddeletedobjects_0;
+ Avoid::ConnRefList::const_iterator connit_0;
+ Avoid::JunctionRefList::const_iterator junctionit_0;
+ router0->setTransactionUse(true);
+ router0->setRoutingPenalty(Avoid::segmentPenalty);
+ router0->setRoutingParameter(Avoid::portDirectionPenalty, 100);
+ router0->setRoutingParameter(Avoid::idealNudgingDistance, 25);
+ router0->setRoutingOption(Avoid::improveHyperedgeRoutesMovingAddingAndDeletingJunctions, true);
+ router0->setRoutingPenalty(Avoid::fixedSharedPathPenalty, 9000);
+ router0->setRoutingOption(Avoid::penaliseOrthogonalSharedPathsAtConnEnds, true);
+ router0->setRoutingParameter(Avoid::crossingPenalty);
+ router0->setRoutingOption(Avoid::performUnifyingNudgingPreprocessingStep, true);
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(50410, 50115));
+ poly0.setPoint(1, Avoid::Point(50410, 51860));
+ poly0.setPoint(2, Avoid::Point(50050, 51860));
+ poly0.setPoint(3, Avoid::Point(50050, 50115));
+ Avoid::ShapeRef * shape0_288069558 = new Avoid::ShapeRef(router0, poly0, 288069558);
+ Avoid::ShapeConnectionPin * pin0_288069558_0 = new Avoid::ShapeConnectionPin(shape0_288069558, 1, 0, 85, false, 10, 4);
+ pin0_288069558_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_1 = new Avoid::ShapeConnectionPin(shape0_288069558, 2, 0, 160, false, 10, 4);
+ pin0_288069558_1->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_2 = new Avoid::ShapeConnectionPin(shape0_288069558, 3, 0, 235, false, 10, 4);
+ pin0_288069558_2->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_3 = new Avoid::ShapeConnectionPin(shape0_288069558, 4, 0, 310, false, 10, 4);
+ pin0_288069558_3->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_4 = new Avoid::ShapeConnectionPin(shape0_288069558, 5, 0, 385, false, 10, 4);
+ pin0_288069558_4->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_5 = new Avoid::ShapeConnectionPin(shape0_288069558, 6, 0, 460, false, 10, 4);
+ pin0_288069558_5->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_6 = new Avoid::ShapeConnectionPin(shape0_288069558, 7, 0, 535, false, 10, 4);
+ pin0_288069558_6->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_7 = new Avoid::ShapeConnectionPin(shape0_288069558, 8, 0, 610, false, 10, 4);
+ pin0_288069558_7->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_8 = new Avoid::ShapeConnectionPin(shape0_288069558, 9, 0, 685, false, 10, 4);
+ pin0_288069558_8->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_9 = new Avoid::ShapeConnectionPin(shape0_288069558, 10, 0, 760, false, 10, 4);
+ pin0_288069558_9->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_10 = new Avoid::ShapeConnectionPin(shape0_288069558, 11, 0, 835, false, 10, 4);
+ pin0_288069558_10->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_11 = new Avoid::ShapeConnectionPin(shape0_288069558, 12, 0, 910, false, 10, 4);
+ pin0_288069558_11->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_12 = new Avoid::ShapeConnectionPin(shape0_288069558, 13, 0, 985, false, 10, 4);
+ pin0_288069558_12->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_13 = new Avoid::ShapeConnectionPin(shape0_288069558, 14, 0, 1060, false, 10, 4);
+ pin0_288069558_13->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_14 = new Avoid::ShapeConnectionPin(shape0_288069558, 15, 0, 1135, false, 10, 4);
+ pin0_288069558_14->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_15 = new Avoid::ShapeConnectionPin(shape0_288069558, 16, 0, 1210, false, 10, 4);
+ pin0_288069558_15->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_16 = new Avoid::ShapeConnectionPin(shape0_288069558, 17, 0, 1285, false, 10, 4);
+ pin0_288069558_16->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_17 = new Avoid::ShapeConnectionPin(shape0_288069558, 18, 0, 1360, false, 10, 4);
+ pin0_288069558_17->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_18 = new Avoid::ShapeConnectionPin(shape0_288069558, 19, 0, 1435, false, 10, 4);
+ pin0_288069558_18->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_19 = new Avoid::ShapeConnectionPin(shape0_288069558, 20, 0, 1510, false, 10, 4);
+ pin0_288069558_19->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_20 = new Avoid::ShapeConnectionPin(shape0_288069558, 21, 0, 1585, false, 10, 4);
+ pin0_288069558_20->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_21 = new Avoid::ShapeConnectionPin(shape0_288069558, 22, 0, 1660, false, 10, 4);
+ pin0_288069558_21->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_22 = new Avoid::ShapeConnectionPin(shape0_288069558, 23, 350, 85, false, 10, 8);
+ pin0_288069558_22->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_23 = new Avoid::ShapeConnectionPin(shape0_288069558, 24, 350, 160, false, 10, 8);
+ pin0_288069558_23->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_24 = new Avoid::ShapeConnectionPin(shape0_288069558, 25, 350, 235, false, 10, 8);
+ pin0_288069558_24->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_25 = new Avoid::ShapeConnectionPin(shape0_288069558, 26, 350, 310, false, 10, 8);
+ pin0_288069558_25->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_26 = new Avoid::ShapeConnectionPin(shape0_288069558, 27, 350, 385, false, 10, 8);
+ pin0_288069558_26->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_27 = new Avoid::ShapeConnectionPin(shape0_288069558, 28, 350, 460, false, 10, 8);
+ pin0_288069558_27->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_28 = new Avoid::ShapeConnectionPin(shape0_288069558, 29, 350, 535, false, 10, 8);
+ pin0_288069558_28->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_29 = new Avoid::ShapeConnectionPin(shape0_288069558, 30, 350, 610, false, 10, 8);
+ pin0_288069558_29->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_30 = new Avoid::ShapeConnectionPin(shape0_288069558, 31, 350, 685, false, 10, 8);
+ pin0_288069558_30->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_31 = new Avoid::ShapeConnectionPin(shape0_288069558, 32, 350, 760, false, 10, 8);
+ pin0_288069558_31->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_32 = new Avoid::ShapeConnectionPin(shape0_288069558, 33, 350, 835, false, 10, 8);
+ pin0_288069558_32->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_33 = new Avoid::ShapeConnectionPin(shape0_288069558, 34, 350, 910, false, 10, 8);
+ pin0_288069558_33->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_34 = new Avoid::ShapeConnectionPin(shape0_288069558, 35, 350, 985, false, 10, 8);
+ pin0_288069558_34->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_35 = new Avoid::ShapeConnectionPin(shape0_288069558, 36, 350, 1060, false, 10, 8);
+ pin0_288069558_35->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_36 = new Avoid::ShapeConnectionPin(shape0_288069558, 37, 350, 1135, false, 10, 8);
+ pin0_288069558_36->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_37 = new Avoid::ShapeConnectionPin(shape0_288069558, 38, 350, 1210, false, 10, 8);
+ pin0_288069558_37->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_38 = new Avoid::ShapeConnectionPin(shape0_288069558, 39, 350, 1285, false, 10, 8);
+ pin0_288069558_38->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_39 = new Avoid::ShapeConnectionPin(shape0_288069558, 40, 350, 1360, false, 10, 8);
+ pin0_288069558_39->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_40 = new Avoid::ShapeConnectionPin(shape0_288069558, 41, 350, 1435, false, 10, 8);
+ pin0_288069558_40->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_41 = new Avoid::ShapeConnectionPin(shape0_288069558, 42, 350, 1510, false, 10, 8);
+ pin0_288069558_41->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_288069558_42 = new Avoid::ShapeConnectionPin(shape0_288069558, 43, 350, 1585, false, 10, 8);
+ pin0_288069558_42->setExclusive(true);
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(49500, 50920));
+ poly0.setPoint(1, Avoid::Point(49500, 50980));
+ poly0.setPoint(2, Avoid::Point(49340, 50980));
+ poly0.setPoint(3, Avoid::Point(49340, 50920));
+ Avoid::ShapeRef * shape0_59726400 = new Avoid::ShapeRef(router0, poly0, 59726400);
+ Avoid::ShapeConnectionPin * pin0_59726400_0 = new Avoid::ShapeConnectionPin(shape0_59726400, 1, 10, 30, false, 10, 4);
+ pin0_59726400_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_59726400_1 = new Avoid::ShapeConnectionPin(shape0_59726400, 2, -1, 30, false, 10, 8);
+ pin0_59726400_1->setExclusive(true);
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(49500, 50845));
+ poly0.setPoint(1, Avoid::Point(49500, 50905));
+ poly0.setPoint(2, Avoid::Point(49340, 50905));
+ poly0.setPoint(3, Avoid::Point(49340, 50845));
+ Avoid::ShapeRef * shape0_574489840 = new Avoid::ShapeRef(router0, poly0, 574489840);
+ Avoid::ShapeConnectionPin * pin0_574489840_0 = new Avoid::ShapeConnectionPin(shape0_574489840, 1, 10, 30, false, 10, 4);
+ pin0_574489840_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_574489840_1 = new Avoid::ShapeConnectionPin(shape0_574489840, 2, -1, 30, false, 10, 8);
+ pin0_574489840_1->setExclusive(true);
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(49500, 50695));
+ poly0.setPoint(1, Avoid::Point(49500, 50755));
+ poly0.setPoint(2, Avoid::Point(49340, 50755));
+ poly0.setPoint(3, Avoid::Point(49340, 50695));
+ Avoid::ShapeRef * shape0_482418284 = new Avoid::ShapeRef(router0, poly0, 482418284);
+ Avoid::ShapeConnectionPin * pin0_482418284_0 = new Avoid::ShapeConnectionPin(shape0_482418284, 1, 10, 30, false, 10, 4);
+ pin0_482418284_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_482418284_1 = new Avoid::ShapeConnectionPin(shape0_482418284, 2, -1, 30, false, 10, 8);
+ pin0_482418284_1->setExclusive(true);
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(49500, 50770));
+ poly0.setPoint(1, Avoid::Point(49500, 50830));
+ poly0.setPoint(2, Avoid::Point(49340, 50830));
+ poly0.setPoint(3, Avoid::Point(49340, 50770));
+ Avoid::ShapeRef * shape0_100128936 = new Avoid::ShapeRef(router0, poly0, 100128936);
+ Avoid::ShapeConnectionPin * pin0_100128936_0 = new Avoid::ShapeConnectionPin(shape0_100128936, 1, 10, 30, false, 10, 4);
+ pin0_100128936_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_100128936_1 = new Avoid::ShapeConnectionPin(shape0_100128936, 2, -1, 30, false, 10, 8);
+ pin0_100128936_1->setExclusive(true);
+ end1_0 = Avoid::ConnEnd(shape0_100128936, 2);
+ end2_0 = Avoid::ConnEnd(shape0_288069558, 12);
+ new Avoid::ConnRef(router0, end1_0, end2_0, 105958336);
+ end1_0 = Avoid::ConnEnd(shape0_574489840, 2);
+ end2_0 = Avoid::ConnEnd(shape0_288069558, 13);
+ new Avoid::ConnRef(router0, end1_0, end2_0, 377294085);
+ end1_0 = Avoid::ConnEnd(shape0_59726400, 2);
+ end2_0 = Avoid::ConnEnd(shape0_288069558, 14);
+ new Avoid::ConnRef(router0, end1_0, end2_0, 870686312);
+ router0->processTransaction();
+
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(49518, 50707));
+ poly0.setPoint(1, Avoid::Point(49518, 50743));
+ poly0.setPoint(2, Avoid::Point(49482, 50743));
+ poly0.setPoint(3, Avoid::Point(49482, 50707));
+ Avoid::ShapeRef * shape0_91346832 = new Avoid::ShapeRef(router0, poly0, 91346832);
+ Avoid::ShapeConnectionPin * pin0_91346832_0 = new Avoid::ShapeConnectionPin(shape0_91346832, 2147483646, 18, 18, false, 0, 15);
+ pin0_91346832_0->setExclusive(false);
+ end1_0 = Avoid::ConnEnd(shape0_91346832, Avoid::CONNECTIONPIN_CENTRE);
+ end2_0 = Avoid::ConnEnd(shape0_288069558, 11);
+ new Avoid::ConnRef(router0, end1_0, end2_0, 214417907);
+ router0->processTransaction();
+
+ router0->outputDiagram("output/inlineOverlap11");
+
+ bool optimisedForConnectorType = false;
+ int crossings = router0->existsCrossings(optimisedForConnectorType);
+ delete router0;
+ return (crossings > 0) ? 1 : 0;
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/inlineShapes.cpp b/src/3rdparty/adaptagrams/libavoid/tests/inlineShapes.cpp
new file mode 100644
index 0000000..510c91c
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/inlineShapes.cpp
@@ -0,0 +1,97 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 0);
+
+ Polygon poly1(4);
+ poly1.ps[0] = Point(52, 188);
+ poly1.ps[1] = Point(52, 292);
+ poly1.ps[2] = Point(-52, 292);
+ poly1.ps[3] = Point(-52, 188);
+ ShapeRef *shapeRef1 = new ShapeRef(router, poly1, 1);
+ new ShapeConnectionPin(shapeRef1, 544, 0.5, 0.5, true, 10, (ConnDirFlags) 0);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(52, -52);
+ poly2.ps[1] = Point(52, 52);
+ poly2.ps[2] = Point(-52, 52);
+ poly2.ps[3] = Point(-52, -52);
+ ShapeRef *shapeRef2 = new ShapeRef(router, poly2, 2);
+ new ShapeConnectionPin(shapeRef2, 544, 0.5, 0.5, true, 10, (ConnDirFlags) 0);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(52, 428);
+ poly3.ps[1] = Point(52, 532);
+ poly3.ps[2] = Point(-52, 532);
+ poly3.ps[3] = Point(-52, 428);
+ ShapeRef *shapeRef3 = new ShapeRef(router, poly3, 3);
+ new ShapeConnectionPin(shapeRef3, 544, 0.5, 0.5, true, 10, (ConnDirFlags) 0);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(52, 68);
+ poly4.ps[1] = Point(52, 172);
+ poly4.ps[2] = Point(-52, 172);
+ poly4.ps[3] = Point(-52, 68);
+ ShapeRef *shapeRef4 = new ShapeRef(router, poly4, 4);
+ new ShapeConnectionPin(shapeRef4, 544, 0.5, 0.5, true, 10, (ConnDirFlags) 0);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(52, 308);
+ poly5.ps[1] = Point(52, 412);
+ poly5.ps[2] = Point(-52, 412);
+ poly5.ps[3] = Point(-52, 308);
+ ShapeRef *shapeRef5 = new ShapeRef(router, poly5, 5);
+ new ShapeConnectionPin(shapeRef5, 544, 0.5, 0.5, true, 10, (ConnDirFlags) 0);
+
+ ConnRef *connRef6 = new ConnRef(router, 6);
+ ConnEnd srcPt6(shapeRef2, 544);
+ connRef6->setSourceEndpoint(srcPt6);
+ ConnEnd dstPt6(shapeRef5, 544);
+ connRef6->setDestEndpoint(dstPt6);
+ connRef6->setRoutingType((ConnType)2);
+
+ ConnRef *connRef7 = new ConnRef(router, 7);
+ ConnEnd srcPt7(shapeRef5, 544);
+ connRef7->setSourceEndpoint(srcPt7);
+ ConnEnd dstPt7(shapeRef4, 544);
+ connRef7->setDestEndpoint(dstPt7);
+ connRef7->setRoutingType((ConnType)2);
+
+ ConnRef *connRef8 = new ConnRef(router, 8);
+ ConnEnd srcPt8(shapeRef1, 544);
+ connRef8->setSourceEndpoint(srcPt8);
+ ConnEnd dstPt8(shapeRef5, 544);
+ connRef8->setDestEndpoint(dstPt8);
+ connRef8->setRoutingType((ConnType)2);
+
+ ConnRef *connRef9 = new ConnRef(router, 9);
+ ConnEnd srcPt9(shapeRef2, 544);
+ connRef9->setSourceEndpoint(srcPt9);
+ ConnEnd dstPt9(shapeRef3, 544);
+ connRef9->setDestEndpoint(dstPt9);
+ connRef9->setRoutingType((ConnType)2);
+
+ ConnRef *connRef10 = new ConnRef(router, 10);
+ ConnEnd srcPt10(shapeRef3, 544);
+ connRef10->setSourceEndpoint(srcPt10);
+ ConnEnd dstPt10(shapeRef4, 544);
+ connRef10->setDestEndpoint(dstPt10);
+ connRef10->setRoutingType((ConnType)2);
+
+ ConnRef *connRef11 = new ConnRef(router, 11);
+ ConnEnd srcPt11(shapeRef1, 544);
+ connRef11->setSourceEndpoint(srcPt11);
+ ConnEnd dstPt11(shapeRef3, 544);
+ connRef11->setDestEndpoint(dstPt11);
+ connRef11->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/inlineShapes");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap01.cpp b/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap01.cpp
new file mode 100644
index 0000000..ff4a309
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap01.cpp
@@ -0,0 +1,25 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingPenalty(segmentPenalty);
+ router->setRoutingPenalty(fixedSharedPathPenalty);
+ router->setRoutingParameter(idealNudgingDistance, 20);
+ Rectangle rect335855988(Point(51140, 50190), Point(51510, 50885));
+ new ShapeRef(router, rect335855988, 335855988);
+ Rectangle rect548374163(Point(51915, 50415), Point(52285, 50885));
+ new ShapeRef(router, rect548374163, 548374163);
+ Rectangle rect942733064(Point(51771, 50790), Point(51829, 50885));
+ new ShapeRef(router, rect942733064, 942733064);
+ ConnEnd srcPt100850179(Point(51925, 50800), 4);
+ ConnEnd dstPt100850179(Point(51500, 50650), 8);
+ new ConnRef(router, srcPt100850179, dstPt100850179, 100850179);
+ ConnEnd srcPt240732432(Point(51925, 50650), 4);
+ ConnEnd dstPt240732432(Point(51800, 50800), 1);
+ new ConnRef(router, srcPt240732432, dstPt240732432, 240732432);
+ router->processTransaction();
+ router->outputDiagram("output/inlineoverlap01");
+ bool overlap = router->existsOrthogonalTouchingPaths();
+ delete router;
+ return (overlap) ? 1 : 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap02.cpp b/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap02.cpp
new file mode 100644
index 0000000..4e1c044
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap02.cpp
@@ -0,0 +1,62 @@
+// From p-overlap bug.
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 110);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+ Polygon poly548374163(4);
+ poly548374163.ps[0] = Point(52285, 50415);
+ poly548374163.ps[1] = Point(52285, 50885);
+ poly548374163.ps[2] = Point(51915, 50885);
+ poly548374163.ps[3] = Point(51915, 50415);
+ new ShapeRef(router, poly548374163, 548374163);
+
+ Polygon poly942733064(4);
+ poly942733064.ps[0] = Point(51829, 50800);
+ poly942733064.ps[1] = Point(51829, 50885);
+ poly942733064.ps[2] = Point(51771, 50885);
+ poly942733064.ps[3] = Point(51771, 50800);
+ new ShapeRef(router, poly942733064, 942733064);
+
+ Polygon poly335855988(4);
+ poly335855988.ps[0] = Point(51510, 50190);
+ poly335855988.ps[1] = Point(51510, 50885);
+ poly335855988.ps[2] = Point(51140, 50885);
+ poly335855988.ps[3] = Point(51140, 50190);
+ new ShapeRef(router, poly335855988, 335855988);
+
+ ConnRef *connRef240732432 = new ConnRef(router, 240732432);
+ ConnEnd srcPt240732432(Point(51935, 50650), 4);
+ connRef240732432->setSourceEndpoint(srcPt240732432);
+ ConnEnd dstPt240732432(Point(51800, 50810), 1);
+ connRef240732432->setDestEndpoint(dstPt240732432);
+ connRef240732432->setRoutingType((ConnType)2);
+
+ ConnRef *connRef148374725 = new ConnRef(router, 148374725);
+ ConnEnd srcPt148374725(Point(51935, 50500), 4);
+ connRef148374725->setSourceEndpoint(srcPt148374725);
+ ConnEnd dstPt148374725(Point(51490, 50800), 8);
+ connRef148374725->setDestEndpoint(dstPt148374725);
+ connRef148374725->setRoutingType((ConnType)2);
+
+ ConnRef *connRef100850179 = new ConnRef(router, 100850179);
+ ConnEnd srcPt100850179(Point(51935, 50800), 4);
+ connRef100850179->setSourceEndpoint(srcPt100850179);
+ ConnEnd dstPt100850179(Point(51490, 50650), 8);
+ connRef100850179->setDestEndpoint(dstPt100850179);
+ connRef100850179->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/inlineoverlap02");
+ bool overlap = router->existsOrthogonalFixedSegmentOverlap();
+ delete router;
+ return (overlap) ? 1 : 0;
+};
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap03.cpp b/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap03.cpp
new file mode 100644
index 0000000..945cd72
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap03.cpp
@@ -0,0 +1,55 @@
+// From diffport-pins-overlap-reduced_libavoid-debug_4 bug.
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 110);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+ Polygon poly421433292(4);
+ poly421433292.ps[0] = Point(51335, 50215);
+ poly421433292.ps[1] = Point(51335, 50385);
+ poly421433292.ps[2] = Point(51065, 50385);
+ poly421433292.ps[3] = Point(51065, 50215);
+ new ShapeRef(router, poly421433292, 421433292);
+
+ Polygon poly174734866(4);
+ poly174734866.ps[0] = Point(51335, 50490);
+ poly174734866.ps[1] = Point(51335, 50660);
+ poly174734866.ps[2] = Point(51065, 50660);
+ poly174734866.ps[3] = Point(51065, 50490);
+ new ShapeRef(router, poly174734866, 174734866);
+
+ Polygon poly564884274(4);
+ poly564884274.ps[0] = Point(50635, 50500);
+ poly564884274.ps[1] = Point(50635, 50583);
+ poly564884274.ps[2] = Point(50515, 50583);
+ poly564884274.ps[3] = Point(50515, 50500);
+ new ShapeRef(router, poly564884274, 564884274);
+
+ ConnRef *connRef103176525 = new ConnRef(router, 103176525);
+ ConnEnd srcPt103176525(Point(51085, 50550), 4);
+ connRef103176525->setSourceEndpoint(srcPt103176525);
+ ConnEnd dstPt103176525(Point(50575, 50510), 1);
+ connRef103176525->setDestEndpoint(dstPt103176525);
+ connRef103176525->setRoutingType((ConnType)2);
+
+ ConnRef *connRef223495632 = new ConnRef(router, 223495632);
+ ConnEnd srcPt223495632(Point(51085, 50325), 4);
+ connRef223495632->setSourceEndpoint(srcPt223495632);
+ ConnEnd dstPt223495632(Point(50575, 50550), 14);
+ connRef223495632->setDestEndpoint(dstPt223495632);
+ connRef223495632->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/inlineoverlap03");
+ bool overlap = router->existsOrthogonalFixedSegmentOverlap();
+ delete router;
+ return (overlap) ? 1 : 0;
+};
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap04.cpp b/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap04.cpp
new file mode 100644
index 0000000..70847bc
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap04.cpp
@@ -0,0 +1,62 @@
+// From Routing_2a_libavoid-debug.
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 110);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+ Polygon poly170253204(4);
+ poly170253204.ps[0] = Point(50450, 50190);
+ poly170253204.ps[1] = Point(50450, 50360);
+ poly170253204.ps[2] = Point(50265, 50360);
+ poly170253204.ps[3] = Point(50265, 50190);
+ new ShapeRef(router, poly170253204, 170253204);
+
+ Polygon poly914700248(4);
+ poly914700248.ps[0] = Point(50800, 50390);
+ poly914700248.ps[1] = Point(50800, 50560);
+ poly914700248.ps[2] = Point(50615, 50560);
+ poly914700248.ps[3] = Point(50615, 50390);
+ new ShapeRef(router, poly914700248, 914700248);
+
+ Polygon poly285103539(4);
+ poly285103539.ps[0] = Point(51385, 50390);
+ poly285103539.ps[1] = Point(51385, 50560);
+ poly285103539.ps[2] = Point(51200, 50560);
+ poly285103539.ps[3] = Point(51200, 50390);
+ new ShapeRef(router, poly285103539, 285103539);
+
+ Polygon poly252459412(4);
+ poly252459412.ps[0] = Point(51360, 50190);
+ poly252459412.ps[1] = Point(51360, 50360);
+ poly252459412.ps[2] = Point(51175, 50360);
+ poly252459412.ps[3] = Point(51175, 50190);
+ new ShapeRef(router, poly252459412, 252459412);
+
+ ConnRef *connRef573390636 = new ConnRef(router, 573390636);
+ ConnEnd srcPt573390636(Point(50790, 50475), 8);
+ connRef573390636->setSourceEndpoint(srcPt573390636);
+ ConnEnd dstPt573390636(Point(51185, 50275), 4);
+ connRef573390636->setDestEndpoint(dstPt573390636);
+ connRef573390636->setRoutingType((ConnType)2);
+
+ ConnRef *connRef214207623 = new ConnRef(router, 214207623);
+ ConnEnd srcPt214207623(Point(51210, 50475), 4);
+ connRef214207623->setSourceEndpoint(srcPt214207623);
+ ConnEnd dstPt214207623(Point(50440, 50275), 8);
+ connRef214207623->setDestEndpoint(dstPt214207623);
+ connRef214207623->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/inlineoverlap04");
+ bool overlap = router->existsOrthogonalFixedSegmentOverlap();
+ delete router;
+ return (overlap) ? 1 : 0;
+};
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap05.cpp b/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap05.cpp
new file mode 100644
index 0000000..1092679
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap05.cpp
@@ -0,0 +1,69 @@
+// From Diplexer-reduced2_libavoid-debug.
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 110);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+ Polygon poly231469760(4);
+ poly231469760.ps[0] = Point(6385, 9390);
+ poly231469760.ps[1] = Point(6385, 9560);
+ poly231469760.ps[2] = Point(6200, 9560);
+ poly231469760.ps[3] = Point(6200, 9390);
+ new ShapeRef(router, poly231469760, 231469760);
+
+ Polygon poly7136376(4);
+ poly7136376.ps[0] = Point(6560, 9290);
+ poly7136376.ps[1] = Point(6560, 9460);
+ poly7136376.ps[2] = Point(6375, 9460);
+ poly7136376.ps[3] = Point(6375, 9290);
+ new ShapeRef(router, poly7136376, 7136376);
+
+ Polygon poly215821749(4);
+ poly215821749.ps[0] = Point(6510, 9540);
+ poly215821749.ps[1] = Point(6510, 9710);
+ poly215821749.ps[2] = Point(6325, 9710);
+ poly215821749.ps[3] = Point(6325, 9540);
+ new ShapeRef(router, poly215821749, 215821749);
+
+ Polygon poly83086994(4);
+ poly83086994.ps[0] = Point(5925, 9240);
+ poly83086994.ps[1] = Point(5925, 10085);
+ poly83086994.ps[2] = Point(5575, 10085);
+ poly83086994.ps[3] = Point(5575, 9240);
+ new ShapeRef(router, poly83086994, 83086994);
+
+ ConnRef *connRef292408794 = new ConnRef(router, 292408794);
+ ConnEnd srcPt292408794(Point(5915, 9625), 8);
+ connRef292408794->setSourceEndpoint(srcPt292408794);
+ ConnEnd dstPt292408794(Point(6210, 9475), 4);
+ connRef292408794->setDestEndpoint(dstPt292408794);
+ connRef292408794->setRoutingType((ConnType)2);
+
+ ConnRef *connRef40917776 = new ConnRef(router, 40917776);
+ ConnEnd srcPt40917776(Point(5915, 9550), 8);
+ connRef40917776->setSourceEndpoint(srcPt40917776);
+ ConnEnd dstPt40917776(Point(6385, 9375), 4);
+ connRef40917776->setDestEndpoint(dstPt40917776);
+ connRef40917776->setRoutingType((ConnType)2);
+
+ ConnRef *connRef629564142 = new ConnRef(router, 629564142);
+ ConnEnd srcPt629564142(Point(5915, 9475), 8);
+ connRef629564142->setSourceEndpoint(srcPt629564142);
+ ConnEnd dstPt629564142(Point(6335, 9625), 4);
+ connRef629564142->setDestEndpoint(dstPt629564142);
+ connRef629564142->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/inlineoverlap05");
+ bool overlap = router->existsOrthogonalFixedSegmentOverlap();
+ delete router;
+ return (overlap) ? 1 : 0;
+};
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap06.cpp b/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap06.cpp
new file mode 100644
index 0000000..8319c29
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap06.cpp
@@ -0,0 +1,62 @@
+// From Routing_2a-broken_libavoid-debug.
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 210);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+ Polygon poly170253204(4);
+ poly170253204.ps[0] = Point(50450, 50190);
+ poly170253204.ps[1] = Point(50450, 50360);
+ poly170253204.ps[2] = Point(50265, 50360);
+ poly170253204.ps[3] = Point(50265, 50190);
+ new ShapeRef(router, poly170253204, 170253204);
+
+ Polygon poly285103539(4);
+ poly285103539.ps[0] = Point(51385, 50390);
+ poly285103539.ps[1] = Point(51385, 50560);
+ poly285103539.ps[2] = Point(51200, 50560);
+ poly285103539.ps[3] = Point(51200, 50390);
+ new ShapeRef(router, poly285103539, 285103539);
+
+ Polygon poly252459412(4);
+ poly252459412.ps[0] = Point(51360, 50190);
+ poly252459412.ps[1] = Point(51360, 50360);
+ poly252459412.ps[2] = Point(51175, 50360);
+ poly252459412.ps[3] = Point(51175, 50190);
+ new ShapeRef(router, poly252459412, 252459412);
+
+ Polygon poly914700248(4);
+ poly914700248.ps[0] = Point(50800, 50390);
+ poly914700248.ps[1] = Point(50800, 50560);
+ poly914700248.ps[2] = Point(50615, 50560);
+ poly914700248.ps[3] = Point(50615, 50390);
+ new ShapeRef(router, poly914700248, 914700248);
+
+ ConnRef *connRef214207623 = new ConnRef(router, 214207623);
+ ConnEnd srcPt214207623(Point(51210, 50475), 4);
+ connRef214207623->setSourceEndpoint(srcPt214207623);
+ ConnEnd dstPt214207623(Point(50440, 50275), 8);
+ connRef214207623->setDestEndpoint(dstPt214207623);
+ connRef214207623->setRoutingType((ConnType)2);
+
+ ConnRef *connRef573390636 = new ConnRef(router, 573390636);
+ ConnEnd srcPt573390636(Point(50790, 50475), 8);
+ connRef573390636->setSourceEndpoint(srcPt573390636);
+ ConnEnd dstPt573390636(Point(51185, 50275), 4);
+ connRef573390636->setDestEndpoint(dstPt573390636);
+ connRef573390636->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/inlineoverlap06");
+ bool overlap = router->existsOrthogonalFixedSegmentOverlap();
+ delete router;
+ return (overlap) ? 1 : 0;
+};
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap07.cpp b/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap07.cpp
new file mode 100644
index 0000000..cff0c19
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap07.cpp
@@ -0,0 +1,75 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 200);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 110);
+ router->setRoutingPenalty((PenaltyType)5, 100);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+ Polygon poly186982048(4);
+ poly186982048.ps[0] = Point(52660, 50490);
+ poly186982048.ps[1] = Point(52660, 50960);
+ poly186982048.ps[2] = Point(52100, 50960);
+ poly186982048.ps[3] = Point(52100, 50490);
+ new ShapeRef(router, poly186982048, 186982048);
+
+ Polygon poly193989760(4);
+ poly193989760.ps[0] = Point(51850, 50665);
+ poly193989760.ps[1] = Point(51850, 50835);
+ poly193989760.ps[2] = Point(51590, 50835);
+ poly193989760.ps[3] = Point(51590, 50665);
+ new ShapeRef(router, poly193989760, 193989760);
+
+ Polygon poly276825384(4);
+ poly276825384.ps[0] = Point(51825, 51040);
+ poly276825384.ps[1] = Point(51825, 51210);
+ poly276825384.ps[2] = Point(51565, 51210);
+ poly276825384.ps[3] = Point(51565, 51040);
+ new ShapeRef(router, poly276825384, 276825384);
+
+ Polygon poly190150804(4);
+ poly190150804.ps[0] = Point(50460, 51340);
+ poly190150804.ps[1] = Point(50460, 51510);
+ poly190150804.ps[2] = Point(50290, 51510);
+ poly190150804.ps[3] = Point(50290, 51340);
+ new ShapeRef(router, poly190150804, 190150804);
+
+ ConnRef *connRef562170592 = new ConnRef(router, 562170592);
+ ConnEnd srcPt562170592(Point(52110, 50800), 4);
+ connRef562170592->setSourceEndpoint(srcPt562170592);
+ ConnEnd dstPt562170592(Point(51815, 51100), 8);
+ connRef562170592->setDestEndpoint(dstPt562170592);
+ connRef562170592->setRoutingType((ConnType)2);
+
+ ConnRef *connRef171593006 = new ConnRef(router, 171593006);
+ ConnEnd srcPt171593006(Point(52110, 50750), 4);
+ connRef171593006->setSourceEndpoint(srcPt171593006);
+ ConnEnd dstPt171593006(Point(51840, 50725), 8);
+ connRef171593006->setDestEndpoint(dstPt171593006);
+ connRef171593006->setRoutingType((ConnType)2);
+
+ ConnRef *connRef172593160 = new ConnRef(router, 172593160);
+ ConnEnd srcPt172593160(Point(51815, 51150), 8);
+ connRef172593160->setSourceEndpoint(srcPt172593160);
+ ConnEnd dstPt172593160(Point(52110, 50900), 4);
+ connRef172593160->setDestEndpoint(dstPt172593160);
+ connRef172593160->setRoutingType((ConnType)2);
+
+ ConnRef *connRef116944564 = new ConnRef(router, 116944564);
+ ConnEnd srcPt116944564(Point(51840, 50775), 8);
+ connRef116944564->setSourceEndpoint(srcPt116944564);
+ ConnEnd dstPt116944564(Point(52110, 50850), 4);
+ connRef116944564->setDestEndpoint(dstPt116944564);
+ connRef116944564->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/inlineoverlap07");
+ delete router;
+ return 0;
+};
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap08.cpp b/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap08.cpp
new file mode 100644
index 0000000..cde44e0
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/inlineoverlap08.cpp
@@ -0,0 +1,120 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingParameter((RoutingParameter)0, 10);
+ router->setRoutingParameter((RoutingParameter)1, 0);
+ router->setRoutingParameter((RoutingParameter)2, 0);
+ router->setRoutingParameter((RoutingParameter)3, 4000);
+ router->setRoutingParameter((RoutingParameter)4, 400);
+ router->setRoutingParameter((RoutingParameter)5, 100);
+ router->setRoutingOption((RoutingOption)0, false);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, false);
+ router->setRoutingOption((RoutingOption)3, false);
+
+ Polygon poly1(4);
+ poly1.ps[0] = Point(99, -20);
+ poly1.ps[1] = Point(99, 0);
+ poly1.ps[2] = Point(55, 0);
+ poly1.ps[3] = Point(55, -20);
+ new ShapeRef(router, poly1, 1);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(20, -65);
+ poly2.ps[1] = Point(20, -45);
+ poly2.ps[2] = Point(0, -45);
+ poly2.ps[3] = Point(0, -65);
+ new ShapeRef(router, poly2, 2);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(20, -90);
+ poly3.ps[1] = Point(20, -70);
+ poly3.ps[2] = Point(0, -70);
+ poly3.ps[3] = Point(0, -90);
+ new ShapeRef(router, poly3, 3);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(20, -115);
+ poly4.ps[1] = Point(20, -95);
+ poly4.ps[2] = Point(0, -95);
+ poly4.ps[3] = Point(0, -115);
+ new ShapeRef(router, poly4, 4);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(20, -140);
+ poly5.ps[1] = Point(20, -120);
+ poly5.ps[2] = Point(0, -120);
+ poly5.ps[3] = Point(0, -140);
+ new ShapeRef(router, poly5, 5);
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(75, -185);
+ poly6.ps[1] = Point(75, -165);
+ poly6.ps[2] = Point(55, -165);
+ poly6.ps[3] = Point(55, -185);
+ new ShapeRef(router, poly6, 6);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(100, -185);
+ poly7.ps[1] = Point(100, -165);
+ poly7.ps[2] = Point(80, -165);
+ poly7.ps[3] = Point(80, -185);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(125, -185);
+ poly8.ps[1] = Point(125, -165);
+ poly8.ps[2] = Point(105, -165);
+ poly8.ps[3] = Point(105, -185);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(150, -185);
+ poly9.ps[1] = Point(150, -165);
+ poly9.ps[2] = Point(130, -165);
+ poly9.ps[3] = Point(130, -185);
+ new ShapeRef(router, poly9, 9);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(175, -185);
+ poly10.ps[1] = Point(175, -165);
+ poly10.ps[2] = Point(155, -165);
+ poly10.ps[3] = Point(155, -185);
+ new ShapeRef(router, poly10, 10);
+
+ ConnRef *connRef11 = new ConnRef(router, 11);
+ ConnEnd srcPt11(Point(20, -47), 15);
+ connRef11->setSourceEndpoint(srcPt11);
+ ConnEnd dstPt11(Point(57, -165), 15);
+ connRef11->setDestEndpoint(dstPt11);
+ connRef11->setRoutingType((ConnType)2);
+
+ ConnRef *connRef12 = new ConnRef(router, 12);
+ ConnEnd srcPt12(Point(61, -165), 15);
+ connRef12->setSourceEndpoint(srcPt12);
+ ConnEnd dstPt12(Point(57, -20), 15);
+ connRef12->setDestEndpoint(dstPt12);
+ connRef12->setRoutingType((ConnType)2);
+
+ ConnRef *connRef13 = new ConnRef(router, 13);
+ ConnEnd srcPt13(Point(15, -74), 15);
+ connRef13->setSourceEndpoint(srcPt13);
+ ConnEnd dstPt13(Point(65, -20), 15);
+ connRef13->setDestEndpoint(dstPt13);
+ connRef13->setRoutingType((ConnType)2);
+
+ ConnRef *connRef14 = new ConnRef(router, 14);
+ ConnEnd srcPt14(Point(61, -20), 15);
+ connRef14->setSourceEndpoint(srcPt14);
+ ConnEnd dstPt14(Point(61, -24), 15);
+ connRef14->setDestEndpoint(dstPt14);
+ connRef14->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/inlineoverlap08");
+ bool overlap = router->existsOrthogonalFixedSegmentOverlap();
+ delete router;
+ return (overlap) ? 1 : 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/junction01.cpp b/src/3rdparty/adaptagrams/libavoid/tests/junction01.cpp
new file mode 100644
index 0000000..24d4b5f
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/junction01.cpp
@@ -0,0 +1,55 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 105);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+ Rectangle rect478845150(Point(50695, 51070), Point(50705, 51080));
+ ShapeRef *shapeRef478845150 = new ShapeRef(router, rect478845150, 478845150);
+ ShapeConnectionPin *pin = new Avoid::ShapeConnectionPin(shapeRef478845150,
+ Avoid::CONNECTIONPIN_CENTRE, Avoid::ATTACH_POS_CENTRE,
+ Avoid::ATTACH_POS_CENTRE, true, 0.0, Avoid::ConnDirNone);
+ pin->setExclusive(false);
+
+ Rectangle rect92712048(Point(51246, 50475), Point(51304, 50585));
+ new ShapeRef(router, rect92712048, 92712048);
+ Rectangle rect23127921(Point(50365, 50766), Point(50485, 50834));
+ new ShapeRef(router, rect23127921, 23127921);
+ Rectangle rect159957148(Point(51740, 50891), Point(51860, 50959));
+ new ShapeRef(router, rect159957148, 159957148);
+ Rectangle rect1350214(Point(50375, 51015), Point(50625, 51135));
+ new ShapeRef(router, rect1350214, 1350214);
+ Rectangle rect247197258(Point(50265, 51046), Point(50375, 51104));
+ new ShapeRef(router, rect247197258, 247197258);
+ Rectangle rect281096654(Point(50700, 50390), Point(51000, 50610));
+ new ShapeRef(router, rect281096654, 281096654);
+ ConnEnd srcPt342420237(Point(50425, 50800), 15);
+ ConnEnd dstPt342420237(Point(50710, 50450), 4);
+ new ConnRef(router, srcPt342420237, dstPt342420237, 342420237);
+ ConnEnd srcPt352019675(Point(50990, 50500), 8);
+ ConnEnd dstPt352019675(shapeRef478845150, Avoid::CONNECTIONPIN_CENTRE);
+ //ConnEnd dstPt352019675(Point(50700, 51075), 15);
+ new ConnRef(router, srcPt352019675, dstPt352019675, 352019675);
+ ConnEnd srcPt42699400(shapeRef478845150, Avoid::CONNECTIONPIN_CENTRE);
+ //ConnEnd srcPt42699400(Point(50700, 51075), 15);
+ ConnEnd dstPt42699400(Point(50615, 51075), 8);
+ new ConnRef(router, srcPt42699400, dstPt42699400, 42699400);
+ ConnEnd srcPt94712625(Point(50710, 50550), 4);
+ ConnEnd dstPt94712625(shapeRef478845150, Avoid::CONNECTIONPIN_CENTRE);
+ //ConnEnd dstPt94712625(Point(50700, 51075), 15);
+ new ConnRef(router, srcPt94712625, dstPt94712625, 94712625);
+ ConnEnd srcPt92802970(Point(50990, 50450), 8);
+ ConnEnd dstPt92802970(Point(51275, 50485), 1);
+ new ConnRef(router, srcPt92802970, dstPt92802970, 92802970);
+ ConnEnd srcPt716502036(Point(50710, 50500), 4);
+ ConnEnd dstPt716502036(Point(51800, 50925), 15);
+ new ConnRef(router, srcPt716502036, dstPt716502036, 716502036);
+ router->processTransaction();
+ router->outputDiagram("output/junction01");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/junction02.cpp b/src/3rdparty/adaptagrams/libavoid/tests/junction02.cpp
new file mode 100644
index 0000000..51d9e94
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/junction02.cpp
@@ -0,0 +1,55 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 105);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+ JunctionRef *junction478845150 = new JunctionRef(router, Point(50700, 51075));
+
+ Rectangle rect92712048(Point(51246, 50475), Point(51304, 50585));
+ new ShapeRef(router, rect92712048, 92712048);
+ Rectangle rect23127921(Point(50365, 50766), Point(50485, 50834));
+ new ShapeRef(router, rect23127921, 23127921);
+ Rectangle rect159957148(Point(51740, 50891), Point(51860, 50959));
+ new ShapeRef(router, rect159957148, 159957148);
+ Rectangle rect1350214(Point(50375, 51015), Point(50625, 51135));
+ new ShapeRef(router, rect1350214, 1350214);
+ Rectangle rect247197258(Point(50265, 51046), Point(50375, 51104));
+ new ShapeRef(router, rect247197258, 247197258);
+ Rectangle rect281096654(Point(50700, 50390), Point(51000, 50610));
+ new ShapeRef(router, rect281096654, 281096654);
+ ConnEnd srcPt342420237(Point(50425, 50800), 15);
+ ConnEnd dstPt342420237(Point(50710, 50450), 4);
+ new ConnRef(router, srcPt342420237, dstPt342420237, 342420237);
+ ConnEnd srcPt352019675(Point(50990, 50500), 8);
+ ConnEnd dstPt352019675(junction478845150);
+ //ConnEnd dstPt352019675(Point(50700, 51075), 15);
+ new ConnRef(router, srcPt352019675, dstPt352019675, 352019675);
+ ConnEnd srcPt42699400(junction478845150);
+ //ConnEnd srcPt42699400(Point(50700, 51075), 15);
+ ConnEnd dstPt42699400(Point(50615, 51075), 8);
+ new ConnRef(router, srcPt42699400, dstPt42699400, 42699400);
+ ConnEnd srcPt94712625(Point(50710, 50550), 4);
+ ConnEnd dstPt94712625(junction478845150);
+ //ConnEnd dstPt94712625(Point(50700, 51075), 15);
+ new ConnRef(router, srcPt94712625, dstPt94712625, 94712625);
+ ConnEnd srcPt92802970(Point(50990, 50450), 8);
+ ConnEnd dstPt92802970(Point(51275, 50485), 1);
+ new ConnRef(router, srcPt92802970, dstPt92802970, 92802970);
+ ConnEnd srcPt716502036(Point(50710, 50500), 4);
+ ConnEnd dstPt716502036(Point(51800, 50925), 15);
+ new ConnRef(router, srcPt716502036, dstPt716502036, 716502036);
+ router->processTransaction();
+ router->outputDiagram("output/junction02-1");
+ router->moveJunction(junction478845150, 585, 0);
+ router->processTransaction();
+ router->outputDiagram("output/junction02-2");
+ delete router;
+ return 0;
+};
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/junction03.cpp b/src/3rdparty/adaptagrams/libavoid/tests/junction03.cpp
new file mode 100644
index 0000000..7eab3c0
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/junction03.cpp
@@ -0,0 +1,55 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 105);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+ Rectangle rect478845150(Point(50695, 51070), Point(50705, 51080));
+ JunctionRef *junctionRef478845150 = new JunctionRef(router,
+ Point(50700, 51075), 478845150);
+
+ Rectangle rect92712048(Point(51246, 50475), Point(51304, 50585));
+ new ShapeRef(router, rect92712048, 92712048);
+ Rectangle rect23127921(Point(50365, 50766), Point(50485, 50834));
+ new ShapeRef(router, rect23127921, 23127921);
+ Rectangle rect159957148(Point(51740, 50891), Point(51860, 50959));
+ new ShapeRef(router, rect159957148, 159957148);
+ Rectangle rect1350214(Point(50375, 51015), Point(50625, 51135));
+ new ShapeRef(router, rect1350214, 1350214);
+ Rectangle rect247197258(Point(50265, 51046), Point(50375, 51104));
+ new ShapeRef(router, rect247197258, 247197258);
+ Rectangle rect281096654(Point(50700, 50390), Point(51000, 50610));
+ new ShapeRef(router, rect281096654, 281096654);
+ ConnEnd srcPt342420237(Point(50425, 50800), 15);
+ ConnEnd dstPt342420237(Point(50710, 50450), 4);
+ new ConnRef(router, srcPt342420237, dstPt342420237, 342420237);
+ ConnEnd srcPt352019675(Point(50990, 50500), 8);
+ ConnEnd dstPt352019675(junctionRef478845150);
+ //ConnEnd dstPt352019675(Point(50700, 51075), 15);
+ new ConnRef(router, srcPt352019675, dstPt352019675, 352019675);
+ ConnEnd srcPt42699400(junctionRef478845150);
+ //ConnEnd srcPt42699400(Point(50700, 51075), 15);
+ ConnEnd dstPt42699400(Point(50615, 51075), 8);
+ new ConnRef(router, srcPt42699400, dstPt42699400, 42699400);
+ ConnEnd srcPt94712625(Point(50710, 50550), 4);
+ ConnEnd dstPt94712625(junctionRef478845150);
+ //ConnEnd dstPt94712625(Point(50700, 51075), 15);
+ new ConnRef(router, srcPt94712625, dstPt94712625, 94712625);
+ ConnEnd srcPt92802970(Point(50990, 50450), 8);
+ ConnEnd dstPt92802970(Point(51275, 50485), 1);
+ new ConnRef(router, srcPt92802970, dstPt92802970, 92802970);
+ ConnEnd srcPt716502036(Point(50710, 50500), 4);
+ ConnEnd dstPt716502036(Point(51800, 50925), 15);
+ new ConnRef(router, srcPt716502036, dstPt716502036, 716502036);
+ router->processTransaction();
+ router->outputDiagram("output/junction03-1");
+ router->moveJunction(junctionRef478845150, 585, 0);
+ router->processTransaction();
+ router->outputDiagram("output/junction03-2");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/junction04.cpp b/src/3rdparty/adaptagrams/libavoid/tests/junction04.cpp
new file mode 100644
index 0000000..9e75ff7
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/junction04.cpp
@@ -0,0 +1,100 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ * Copyright (C) 2010 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow <mjwybrow@users.sourceforge.net>
+*/
+
+#include "libavoid/libavoid.h"
+
+// Another testcase to check the functionality for connection pins.
+
+
+int main(void)
+{
+ Avoid::Router *router = new Avoid::Router(Avoid::OrthogonalRouting);
+ router->setRoutingPenalty((Avoid::PenaltyType)0, 50);
+
+ Avoid::Rectangle shapeRect1(Avoid::Point(0, 0), Avoid::Point(30, 20));
+ Avoid::ShapeRef *shapeRef1 = new Avoid::ShapeRef(router, shapeRect1);
+
+ Avoid::Rectangle shapeRect2(Avoid::Point(70, 7), Avoid::Point(100, 27));
+ new Avoid::ShapeRef(router, shapeRect2);
+
+ Avoid::Rectangle shapeRect3(Avoid::Point(50, 60), Avoid::Point(80, 155));
+ new Avoid::ShapeRef(router, shapeRect3);
+
+ Avoid::Rectangle shapeRect4(Avoid::Point(125, 60), Avoid::Point(155, 80));
+ new Avoid::ShapeRef(router, shapeRect4);
+
+ Avoid::Rectangle shapeRect5(Avoid::Point(15, 150), Avoid::Point(45, 170));
+ Avoid::ShapeRef *shapeRef5 = new Avoid::ShapeRef(router, shapeRect5);
+
+ Avoid::Rectangle shapeRect6(Avoid::Point(130, 130), Avoid::Point(160, 150));
+ Avoid::ShapeRef *shapeRef6 = new Avoid::ShapeRef(router, shapeRect6);
+
+ // Add a centre connection pin for the three shapes we'll be using.
+ new Avoid::ShapeConnectionPin(shapeRef1, Avoid::CONNECTIONPIN_CENTRE,
+ Avoid::ATTACH_POS_CENTRE, Avoid::ATTACH_POS_CENTRE, true, 0.0, Avoid::ConnDirNone);
+ new Avoid::ShapeConnectionPin(shapeRef5, Avoid::CONNECTIONPIN_CENTRE,
+ Avoid::ATTACH_POS_CENTRE, Avoid::ATTACH_POS_CENTRE, true, 0.0, Avoid::ConnDirNone);
+ new Avoid::ShapeConnectionPin(shapeRef6, Avoid::CONNECTIONPIN_CENTRE,
+ Avoid::ATTACH_POS_CENTRE, Avoid::ATTACH_POS_CENTRE, true, 0.0, Avoid::ConnDirNone);
+
+ Avoid::ConnEnd srcEnd(shapeRef1, Avoid::CONNECTIONPIN_CENTRE);
+ Avoid::ConnEnd dstEnd(shapeRef6, Avoid::CONNECTIONPIN_CENTRE);
+ Avoid::ConnRef *conn1= new Avoid::ConnRef(router, srcEnd, dstEnd);
+
+ router->processTransaction();
+ router->outputDiagram("output/junction04-1");
+
+ // Split the connector on its second segment and add a junction point.
+ std::pair<Avoid::JunctionRef *, Avoid::ConnRef *> newObjs =
+ conn1->splitAtSegment(2);
+
+ router->processTransaction();
+ router->outputDiagram("output/junction04-2");
+
+ // Create a connector from the centre of shape 5 that connects to
+ // the junction.
+ Avoid::ConnEnd srcEnd3(shapeRef5, Avoid::CONNECTIONPIN_CENTRE);
+ Avoid::ConnEnd dstEnd3(newObjs.first);
+ new Avoid::ConnRef(router, srcEnd3, dstEnd3);
+
+ router->processTransaction();
+ router->outputDiagram("output/junction04-3");
+
+ // Delete one half of the original connector, up to the junction.
+ router->deleteConnector(conn1);
+ conn1 = nullptr;
+
+ router->processTransaction();
+ router->outputDiagram("output/junction04-4");
+
+ // The junction just has two connector now, so merge these into one.
+ newObjs.first->removeJunctionAndMergeConnectors();
+ router->processTransaction();
+ router->outputDiagram("output/junction04-5");
+
+ router->processTransaction();
+
+ delete router;
+ return 0;
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/latesetup.cpp b/src/3rdparty/adaptagrams/libavoid/tests/latesetup.cpp
new file mode 100644
index 0000000..80b6cdd
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/latesetup.cpp
@@ -0,0 +1,94 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ * Copyright (C) 2004-2007 Michael Wybrow <mjwybrow@users.sourceforge.net>
+ * Copyright (C) 2009 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow <mjwybrow@users.sourceforge.net>
+*/
+
+#include "libavoid/libavoid.h"
+
+
+
+static void connCallback(void *ptr)
+{
+ Avoid::ConnRef *connRef = (Avoid::ConnRef *) ptr;
+
+ printf("Connector %u needs rerouting!\n", connRef->id());
+
+ const Avoid::PolyLine& route = connRef->route();
+ printf("New path: ");
+ for (size_t i = 0; i < route.ps.size(); ++i)
+ {
+ printf("%s(%f, %f)", (i > 0) ? "-" : "",
+ route.ps[i].x, route.ps[i].y);
+ }
+ printf("\n");
+}
+
+
+int main(void)
+{
+ Avoid::Router *router = new Avoid::Router(Avoid::PolyLineRouting);
+ router->setTransactionUse(false);
+
+ printf("\nCreate connector.\n");
+ Avoid::Point srcPt(1.2, 0.5);
+ Avoid::Point dstPt(1.5, 4);
+ Avoid::ConnRef *connRef = new Avoid::ConnRef(router);
+ connRef->setCallback(connCallback, connRef);
+ // Force inital callback:
+ router->processTransaction();
+
+ Avoid::ConnRef *connRef2 = new Avoid::ConnRef(router);
+ connRef2->setCallback(connCallback, connRef2);
+ router->processTransaction();
+
+ router->deleteConnector(connRef2);
+ connRef2 = nullptr;
+ router->processTransaction();
+
+ printf("\nAdd endpoints.\n");
+ connRef->setEndpoints(srcPt, dstPt);
+ router->processTransaction();
+
+ printf("\nAdding a shape.\n");
+ // Create the ShapeRef:
+ Avoid::Polygon shapePoly(3);
+ shapePoly.ps[0] = Avoid::Point(1, 1);
+ shapePoly.ps[1] = Avoid::Point(2.5, 1.5);
+ shapePoly.ps[2] = Avoid::Point(1.5, 2.5);
+ Avoid::ShapeRef *shapeRef = new Avoid::ShapeRef(router, shapePoly);
+ router->processTransaction();
+
+ printf("\nShifting endpoint.\n");
+ Avoid::Point dstPt2(6, 4.5);
+ connRef->setDestEndpoint(dstPt2);
+ // It's expected you know the connector needs rerouting, so the callback
+ // isn't called. You can force it to be called though, via:
+ router->processTransaction();
+
+ printf("\nMoving shape right by 0.5.\n");
+ router->moveShape(shapeRef, 0.5, 0);
+ router->processTransaction();
+
+ delete router;
+ return 0;
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash1.cpp b/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash1.cpp
new file mode 100644
index 0000000..0b504cf
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash1.cpp
@@ -0,0 +1,1884 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 0);
+
+ Polygon poly29(4);
+ poly29.ps[0] = Point(1038.92, 415.557);
+ poly29.ps[1] = Point(1038.92, 455.557);
+ poly29.ps[2] = Point(998.924, 455.557);
+ poly29.ps[3] = Point(998.924, 415.557);
+ new ShapeRef(router, poly29, 29);
+
+ Polygon poly23(4);
+ poly23.ps[0] = Point(337.924, 141.557);
+ poly23.ps[1] = Point(337.924, 181.557);
+ poly23.ps[2] = Point(297.924, 181.557);
+ poly23.ps[3] = Point(297.924, 141.557);
+ new ShapeRef(router, poly23, 23);
+
+ Polygon poly45(4);
+ poly45.ps[0] = Point(577.924, 34.8422);
+ poly45.ps[1] = Point(577.924, 74.8422);
+ poly45.ps[2] = Point(537.924, 74.8422);
+ poly45.ps[3] = Point(537.924, 34.8422);
+ new ShapeRef(router, poly45, 45);
+
+ Polygon poly18(4);
+ poly18.ps[0] = Point(217.924, 743.557);
+ poly18.ps[1] = Point(217.924, 783.557);
+ poly18.ps[2] = Point(177.924, 783.557);
+ poly18.ps[3] = Point(177.924, 743.557);
+ new ShapeRef(router, poly18, 18);
+
+ Polygon poly60(4);
+ poly60.ps[0] = Point(937.924, 1.84222);
+ poly60.ps[1] = Point(937.924, 41.8422);
+ poly60.ps[2] = Point(897.924, 41.8422);
+ poly60.ps[3] = Point(897.924, 1.84222);
+ new ShapeRef(router, poly60, 60);
+
+ Polygon poly61(4);
+ poly61.ps[0] = Point(577.924, -44.6578);
+ poly61.ps[1] = Point(577.924, -4.65778);
+ poly61.ps[2] = Point(537.924, -4.65778);
+ poly61.ps[3] = Point(537.924, -44.6578);
+ new ShapeRef(router, poly61, 61);
+
+ Polygon poly62(4);
+ poly62.ps[0] = Point(577.924, 629.557);
+ poly62.ps[1] = Point(577.924, 669.557);
+ poly62.ps[2] = Point(537.924, 669.557);
+ poly62.ps[3] = Point(537.924, 629.557);
+ new ShapeRef(router, poly62, 62);
+
+ Polygon poly63(4);
+ poly63.ps[0] = Point(457.924, 507.557);
+ poly63.ps[1] = Point(457.924, 547.557);
+ poly63.ps[2] = Point(417.924, 547.557);
+ poly63.ps[3] = Point(417.924, 507.557);
+ new ShapeRef(router, poly63, 63);
+
+ Polygon poly64(4);
+ poly64.ps[0] = Point(817.924, 554.057);
+ poly64.ps[1] = Point(817.924, 594.057);
+ poly64.ps[2] = Point(777.924, 594.057);
+ poly64.ps[3] = Point(777.924, 554.057);
+ new ShapeRef(router, poly64, 64);
+
+ Polygon poly65(4);
+ poly65.ps[0] = Point(97.9242, 599.557);
+ poly65.ps[1] = Point(97.9242, 639.557);
+ poly65.ps[2] = Point(57.9242, 639.557);
+ poly65.ps[3] = Point(57.9242, 599.557);
+ new ShapeRef(router, poly65, 65);
+
+ Polygon poly66(4);
+ poly66.ps[0] = Point(747.924, -70.6578);
+ poly66.ps[1] = Point(747.924, -50.6578);
+ poly66.ps[2] = Point(727.924, -50.6578);
+ poly66.ps[3] = Point(727.924, -70.6578);
+ new ShapeRef(router, poly66, 66);
+
+ Polygon poly67(4);
+ poly67.ps[0] = Point(147.924, 24.8422);
+ poly67.ps[1] = Point(147.924, 44.8422);
+ poly67.ps[2] = Point(127.924, 44.8422);
+ poly67.ps[3] = Point(127.924, 24.8422);
+ new ShapeRef(router, poly67, 67);
+
+ Polygon poly68(4);
+ poly68.ps[0] = Point(147.924, 151.557);
+ poly68.ps[1] = Point(147.924, 171.557);
+ poly68.ps[2] = Point(127.924, 171.557);
+ poly68.ps[3] = Point(127.924, 151.557);
+ new ShapeRef(router, poly68, 68);
+
+ Polygon poly69(4);
+ poly69.ps[0] = Point(267.924, 151.557);
+ poly69.ps[1] = Point(267.924, 171.557);
+ poly69.ps[2] = Point(247.924, 171.557);
+ poly69.ps[3] = Point(247.924, 151.557);
+ new ShapeRef(router, poly69, 69);
+
+ Polygon poly36(4);
+ poly36.ps[0] = Point(697.924, 507.557);
+ poly36.ps[1] = Point(697.924, 547.557);
+ poly36.ps[2] = Point(657.924, 547.557);
+ poly36.ps[3] = Point(657.924, 507.557);
+ new ShapeRef(router, poly36, 36);
+
+ Polygon poly12(4);
+ poly12.ps[0] = Point(1038.92, 260.557);
+ poly12.ps[1] = Point(1038.92, 300.557);
+ poly12.ps[2] = Point(998.924, 300.557);
+ poly12.ps[3] = Point(998.924, 260.557);
+ new ShapeRef(router, poly12, 12);
+
+ Polygon poly15(4);
+ poly15.ps[0] = Point(1158.92, 415.557);
+ poly15.ps[1] = Point(1158.92, 455.557);
+ poly15.ps[2] = Point(1118.92, 455.557);
+ poly15.ps[3] = Point(1118.92, 415.557);
+ new ShapeRef(router, poly15, 15);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(1278.92, -80.6578);
+ poly7.ps[1] = Point(1278.92, -40.6578);
+ poly7.ps[2] = Point(1238.92, -40.6578);
+ poly7.ps[3] = Point(1238.92, -80.6578);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly16(4);
+ poly16.ps[0] = Point(337.924, 743.557);
+ poly16.ps[1] = Point(337.924, 783.557);
+ poly16.ps[2] = Point(297.924, 783.557);
+ poly16.ps[3] = Point(297.924, 743.557);
+ new ShapeRef(router, poly16, 16);
+
+ Polygon poly19(4);
+ poly19.ps[0] = Point(217.924, 141.557);
+ poly19.ps[1] = Point(217.924, 181.557);
+ poly19.ps[2] = Point(177.924, 181.557);
+ poly19.ps[3] = Point(177.924, 141.557);
+ new ShapeRef(router, poly19, 19);
+
+ Polygon poly47(4);
+ poly47.ps[0] = Point(697.924, 271.557);
+ poly47.ps[1] = Point(697.924, 311.557);
+ poly47.ps[2] = Point(657.924, 311.557);
+ poly47.ps[3] = Point(657.924, 271.557);
+ new ShapeRef(router, poly47, 47);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(1158.92, -80.6578);
+ poly8.ps[1] = Point(1158.92, -40.6578);
+ poly8.ps[2] = Point(1118.92, -40.6578);
+ poly8.ps[3] = Point(1118.92, -80.6578);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly32(4);
+ poly32.ps[0] = Point(1038.92, 141.557);
+ poly32.ps[1] = Point(1038.92, 181.557);
+ poly32.ps[2] = Point(998.924, 181.557);
+ poly32.ps[3] = Point(998.924, 141.557);
+ new ShapeRef(router, poly32, 32);
+
+ Polygon poly51(4);
+ poly51.ps[0] = Point(1038.92, 323.557);
+ poly51.ps[1] = Point(1038.92, 363.557);
+ poly51.ps[2] = Point(998.924, 363.557);
+ poly51.ps[3] = Point(998.924, 323.557);
+ new ShapeRef(router, poly51, 51);
+
+ Polygon poly52(4);
+ poly52.ps[0] = Point(217.924, 295.557);
+ poly52.ps[1] = Point(217.924, 335.557);
+ poly52.ps[2] = Point(177.924, 335.557);
+ poly52.ps[3] = Point(177.924, 295.557);
+ new ShapeRef(router, poly52, 52);
+
+ Polygon poly53(4);
+ poly53.ps[0] = Point(577.924, 323.557);
+ poly53.ps[1] = Point(577.924, 363.557);
+ poly53.ps[2] = Point(537.924, 363.557);
+ poly53.ps[3] = Point(537.924, 323.557);
+ new ShapeRef(router, poly53, 53);
+
+ Polygon poly22(4);
+ poly22.ps[0] = Point(697.924, 34.8422);
+ poly22.ps[1] = Point(697.924, 74.8422);
+ poly22.ps[2] = Point(657.924, 74.8422);
+ poly22.ps[3] = Point(657.924, 34.8422);
+ new ShapeRef(router, poly22, 22);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(1371.92, 29.8422);
+ poly4.ps[1] = Point(1371.92, 69.8422);
+ poly4.ps[2] = Point(1331.92, 69.8422);
+ poly4.ps[3] = Point(1331.92, 29.8422);
+ new ShapeRef(router, poly4, 4);
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(1371.92, -80.6578);
+ poly6.ps[1] = Point(1371.92, -40.6578);
+ poly6.ps[2] = Point(1331.92, -40.6578);
+ poly6.ps[3] = Point(1331.92, -80.6578);
+ new ShapeRef(router, poly6, 6);
+
+ Polygon poly44(4);
+ poly44.ps[0] = Point(97.9242, 507.557);
+ poly44.ps[1] = Point(97.9242, 547.557);
+ poly44.ps[2] = Point(57.9242, 547.557);
+ poly44.ps[3] = Point(57.9242, 507.557);
+ new ShapeRef(router, poly44, 44);
+
+ Polygon poly54(4);
+ poly54.ps[0] = Point(697.924, 323.557);
+ poly54.ps[1] = Point(697.924, 363.557);
+ poly54.ps[2] = Point(657.924, 363.557);
+ poly54.ps[3] = Point(657.924, 323.557);
+ new ShapeRef(router, poly54, 54);
+
+ Polygon poly55(4);
+ poly55.ps[0] = Point(457.924, 7.34222);
+ poly55.ps[1] = Point(457.924, 47.3422);
+ poly55.ps[2] = Point(417.924, 47.3422);
+ poly55.ps[3] = Point(417.924, 7.34222);
+ new ShapeRef(router, poly55, 55);
+
+ Polygon poly56(4);
+ poly56.ps[0] = Point(457.924, -44.6578);
+ poly56.ps[1] = Point(457.924, -4.65778);
+ poly56.ps[2] = Point(417.924, -4.65778);
+ poly56.ps[3] = Point(417.924, -44.6578);
+ new ShapeRef(router, poly56, 56);
+
+ Polygon poly57(4);
+ poly57.ps[0] = Point(817.924, 141.557);
+ poly57.ps[1] = Point(817.924, 181.557);
+ poly57.ps[2] = Point(777.924, 181.557);
+ poly57.ps[3] = Point(777.924, 141.557);
+ new ShapeRef(router, poly57, 57);
+
+ Polygon poly58(4);
+ poly58.ps[0] = Point(97.9242, 14.8422);
+ poly58.ps[1] = Point(97.9242, 54.8422);
+ poly58.ps[2] = Point(57.9242, 54.8422);
+ poly58.ps[3] = Point(57.9242, 14.8422);
+ new ShapeRef(router, poly58, 58);
+
+ Polygon poly59(4);
+ poly59.ps[0] = Point(937.924, 323.557);
+ poly59.ps[1] = Point(937.924, 363.557);
+ poly59.ps[2] = Point(897.924, 363.557);
+ poly59.ps[3] = Point(897.924, 323.557);
+ new ShapeRef(router, poly59, 59);
+
+ Polygon poly25(4);
+ poly25.ps[0] = Point(697.924, 883.057);
+ poly25.ps[1] = Point(697.924, 923.057);
+ poly25.ps[2] = Point(657.924, 923.057);
+ poly25.ps[3] = Point(657.924, 883.057);
+ new ShapeRef(router, poly25, 25);
+
+ Polygon poly24(4);
+ poly24.ps[0] = Point(457.924, 743.557);
+ poly24.ps[1] = Point(457.924, 783.557);
+ poly24.ps[2] = Point(417.924, 783.557);
+ poly24.ps[3] = Point(417.924, 743.557);
+ new ShapeRef(router, poly24, 24);
+
+ Polygon poly39(4);
+ poly39.ps[0] = Point(457.924, 141.557);
+ poly39.ps[1] = Point(457.924, 181.557);
+ poly39.ps[2] = Point(417.924, 181.557);
+ poly39.ps[3] = Point(417.924, 141.557);
+ new ShapeRef(router, poly39, 39);
+
+ Polygon poly35(4);
+ poly35.ps[0] = Point(1158.92, 40.3422);
+ poly35.ps[1] = Point(1158.92, 80.3422);
+ poly35.ps[2] = Point(1118.92, 80.3422);
+ poly35.ps[3] = Point(1118.92, 40.3422);
+ new ShapeRef(router, poly35, 35);
+
+ Polygon poly34(4);
+ poly34.ps[0] = Point(1278.92, 323.557);
+ poly34.ps[1] = Point(1278.92, 363.557);
+ poly34.ps[2] = Point(1238.92, 363.557);
+ poly34.ps[3] = Point(1238.92, 323.557);
+ new ShapeRef(router, poly34, 34);
+
+ Polygon poly42(4);
+ poly42.ps[0] = Point(697.924, 415.557);
+ poly42.ps[1] = Point(697.924, 455.557);
+ poly42.ps[2] = Point(657.924, 455.557);
+ poly42.ps[3] = Point(657.924, 415.557);
+ new ShapeRef(router, poly42, 42);
+
+ Polygon poly40(4);
+ poly40.ps[0] = Point(97.9242, 141.557);
+ poly40.ps[1] = Point(97.9242, 181.557);
+ poly40.ps[2] = Point(57.9242, 181.557);
+ poly40.ps[3] = Point(57.9242, 141.557);
+ new ShapeRef(router, poly40, 40);
+
+ Polygon poly123(4);
+ poly123.ps[0] = Point(645.924, 833.057);
+ poly123.ps[1] = Point(645.924, 873.057);
+ poly123.ps[2] = Point(589.924, 873.057);
+ poly123.ps[3] = Point(589.924, 833.057);
+ new ShapeRef(router, poly123, 123);
+
+ Polygon poly124(4);
+ poly124.ps[0] = Point(405.924, 91.5565);
+ poly124.ps[1] = Point(405.924, 131.557);
+ poly124.ps[2] = Point(349.924, 131.557);
+ poly124.ps[3] = Point(349.924, 91.5565);
+ new ShapeRef(router, poly124, 124);
+
+ Polygon poly125(4);
+ poly125.ps[0] = Point(405.924, -42.6578);
+ poly125.ps[1] = Point(405.924, -2.65778);
+ poly125.ps[2] = Point(349.924, -2.65778);
+ poly125.ps[3] = Point(349.924, -42.6578);
+ new ShapeRef(router, poly125, 125);
+
+ Polygon poly126(4);
+ poly126.ps[0] = Point(525.924, -24.1578);
+ poly126.ps[1] = Point(525.924, 15.8422);
+ poly126.ps[2] = Point(469.924, 15.8422);
+ poly126.ps[3] = Point(469.924, -24.1578);
+ new ShapeRef(router, poly126, 126);
+
+ Polygon poly127(4);
+ poly127.ps[0] = Point(645.924, -24.1578);
+ poly127.ps[1] = Point(645.924, 15.8422);
+ poly127.ps[2] = Point(589.924, 15.8422);
+ poly127.ps[3] = Point(589.924, -24.1578);
+ new ShapeRef(router, poly127, 127);
+
+ Polygon poly128(4);
+ poly128.ps[0] = Point(765.924, 504.057);
+ poly128.ps[1] = Point(765.924, 544.057);
+ poly128.ps[2] = Point(709.924, 544.057);
+ poly128.ps[3] = Point(709.924, 504.057);
+ new ShapeRef(router, poly128, 128);
+
+ Polygon poly129(4);
+ poly129.ps[0] = Point(525.924, 457.557);
+ poly129.ps[1] = Point(525.924, 497.557);
+ poly129.ps[2] = Point(469.924, 497.557);
+ poly129.ps[3] = Point(469.924, 457.557);
+ new ShapeRef(router, poly129, 129);
+
+ Polygon poly130(4);
+ poly130.ps[0] = Point(525.924, 365.557);
+ poly130.ps[1] = Point(525.924, 405.557);
+ poly130.ps[2] = Point(469.924, 405.557);
+ poly130.ps[3] = Point(469.924, 365.557);
+ new ShapeRef(router, poly130, 130);
+
+ Polygon poly131(4);
+ poly131.ps[0] = Point(645.924, 457.557);
+ poly131.ps[1] = Point(645.924, 497.557);
+ poly131.ps[2] = Point(589.924, 497.557);
+ poly131.ps[3] = Point(589.924, 457.557);
+ new ShapeRef(router, poly131, 131);
+
+ Polygon poly132(4);
+ poly132.ps[0] = Point(645.924, 365.557);
+ poly132.ps[1] = Point(645.924, 405.557);
+ poly132.ps[2] = Point(589.924, 405.557);
+ poly132.ps[3] = Point(589.924, 365.557);
+ new ShapeRef(router, poly132, 132);
+
+ Polygon poly133(4);
+ poly133.ps[0] = Point(885.924, 273.557);
+ poly133.ps[1] = Point(885.924, 313.557);
+ poly133.ps[2] = Point(829.924, 313.557);
+ poly133.ps[3] = Point(829.924, 273.557);
+ new ShapeRef(router, poly133, 133);
+
+ Polygon poly134(4);
+ poly134.ps[0] = Point(885.924, 365.557);
+ poly134.ps[1] = Point(885.924, 405.557);
+ poly134.ps[2] = Point(829.924, 405.557);
+ poly134.ps[3] = Point(829.924, 365.557);
+ new ShapeRef(router, poly134, 134);
+
+ Polygon poly135(4);
+ poly135.ps[0] = Point(885.924, 91.5565);
+ poly135.ps[1] = Point(885.924, 131.557);
+ poly135.ps[2] = Point(829.924, 131.557);
+ poly135.ps[3] = Point(829.924, 91.5565);
+ new ShapeRef(router, poly135, 135);
+
+ Polygon poly136(4);
+ poly136.ps[0] = Point(765.924, 273.557);
+ poly136.ps[1] = Point(765.924, 313.557);
+ poly136.ps[2] = Point(709.924, 313.557);
+ poly136.ps[3] = Point(709.924, 273.557);
+ new ShapeRef(router, poly136, 136);
+
+ Polygon poly137(4);
+ poly137.ps[0] = Point(1106.92, 318.557);
+ poly137.ps[1] = Point(1106.92, 358.557);
+ poly137.ps[2] = Point(1050.92, 358.557);
+ poly137.ps[3] = Point(1050.92, 318.557);
+ new ShapeRef(router, poly137, 137);
+
+ Polygon poly138(4);
+ poly138.ps[0] = Point(1226.92, 318.557);
+ poly138.ps[1] = Point(1226.92, 358.557);
+ poly138.ps[2] = Point(1170.92, 358.557);
+ poly138.ps[3] = Point(1170.92, 318.557);
+ new ShapeRef(router, poly138, 138);
+
+ Polygon poly139(4);
+ poly139.ps[0] = Point(1106.92, 82.3422);
+ poly139.ps[1] = Point(1106.92, 122.342);
+ poly139.ps[2] = Point(1050.92, 122.342);
+ poly139.ps[3] = Point(1050.92, 82.3422);
+ new ShapeRef(router, poly139, 139);
+
+ Polygon poly140(4);
+ poly140.ps[0] = Point(1106.92, -9.65778);
+ poly140.ps[1] = Point(1106.92, 30.3422);
+ poly140.ps[2] = Point(1050.92, 30.3422);
+ poly140.ps[3] = Point(1050.92, -9.65778);
+ new ShapeRef(router, poly140, 140);
+
+ Polygon poly141(4);
+ poly141.ps[0] = Point(1226.92, 82.3422);
+ poly141.ps[1] = Point(1226.92, 122.342);
+ poly141.ps[2] = Point(1170.92, 122.342);
+ poly141.ps[3] = Point(1170.92, 82.3422);
+ new ShapeRef(router, poly141, 141);
+
+ Polygon poly142(4);
+ poly142.ps[0] = Point(1106.92, -130.658);
+ poly142.ps[1] = Point(1106.92, -90.6578);
+ poly142.ps[2] = Point(1050.92, -90.6578);
+ poly142.ps[3] = Point(1050.92, -130.658);
+ new ShapeRef(router, poly142, 142);
+
+ Polygon poly143(4);
+ poly143.ps[0] = Point(986.924, 210.557);
+ poly143.ps[1] = Point(986.924, 250.557);
+ poly143.ps[2] = Point(930.924, 250.557);
+ poly143.ps[3] = Point(930.924, 210.557);
+ new ShapeRef(router, poly143, 143);
+
+ Polygon poly144(4);
+ poly144.ps[0] = Point(765.924, 91.5565);
+ poly144.ps[1] = Point(765.924, 131.557);
+ poly144.ps[2] = Point(709.924, 131.557);
+ poly144.ps[3] = Point(709.924, 91.5565);
+ new ShapeRef(router, poly144, 144);
+
+ Polygon poly145(4);
+ poly145.ps[0] = Point(765.924, 790.057);
+ poly145.ps[1] = Point(765.924, 830.057);
+ poly145.ps[2] = Point(709.924, 830.057);
+ poly145.ps[3] = Point(709.924, 790.057);
+ new ShapeRef(router, poly145, 145);
+
+ Polygon poly146(4);
+ poly146.ps[0] = Point(45.9242, 232.5);
+ poly146.ps[1] = Point(45.9242, 272.5);
+ poly146.ps[2] = Point(-14.0758, 272.5);
+ poly146.ps[3] = Point(-14.0758, 232.5);
+ new ShapeRef(router, poly146, 146);
+
+ Polygon poly147(4);
+ poly147.ps[0] = Point(-26.0758, 274.75);
+ poly147.ps[1] = Point(-26.0758, 334.75);
+ poly147.ps[2] = Point(-66.0758, 334.75);
+ poly147.ps[3] = Point(-66.0758, 274.75);
+ new ShapeRef(router, poly147, 147);
+
+ Polygon poly70(4);
+ poly70.ps[0] = Point(207.924, 203.557);
+ poly70.ps[1] = Point(207.924, 223.557);
+ poly70.ps[2] = Point(187.924, 223.557);
+ poly70.ps[3] = Point(187.924, 203.557);
+ new ShapeRef(router, poly70, 70);
+
+ Polygon poly71(4);
+ poly71.ps[0] = Point(267.924, 305.557);
+ poly71.ps[1] = Point(267.924, 325.557);
+ poly71.ps[2] = Point(247.924, 325.557);
+ poly71.ps[3] = Point(247.924, 305.557);
+ new ShapeRef(router, poly71, 71);
+
+ Polygon poly72(4);
+ poly72.ps[0] = Point(87.9242, 357.557);
+ poly72.ps[1] = Point(87.9242, 377.557);
+ poly72.ps[2] = Point(67.9242, 377.557);
+ poly72.ps[3] = Point(67.9242, 357.557);
+ new ShapeRef(router, poly72, 72);
+
+ Polygon poly73(4);
+ poly73.ps[0] = Point(147.924, 517.557);
+ poly73.ps[1] = Point(147.924, 537.557);
+ poly73.ps[2] = Point(127.924, 537.557);
+ poly73.ps[3] = Point(127.924, 517.557);
+ new ShapeRef(router, poly73, 73);
+
+ Polygon poly74(4);
+ poly74.ps[0] = Point(147.924, 609.557);
+ poly74.ps[1] = Point(147.924, 629.557);
+ poly74.ps[2] = Point(127.924, 629.557);
+ poly74.ps[3] = Point(127.924, 609.557);
+ new ShapeRef(router, poly74, 74);
+
+ Polygon poly75(4);
+ poly75.ps[0] = Point(87.9242, 651.557);
+ poly75.ps[1] = Point(87.9242, 671.557);
+ poly75.ps[2] = Point(67.9242, 671.557);
+ poly75.ps[3] = Point(67.9242, 651.557);
+ new ShapeRef(router, poly75, 75);
+
+ Polygon poly76(4);
+ poly76.ps[0] = Point(147.924, 753.557);
+ poly76.ps[1] = Point(147.924, 773.557);
+ poly76.ps[2] = Point(127.924, 773.557);
+ poly76.ps[3] = Point(127.924, 753.557);
+ new ShapeRef(router, poly76, 76);
+
+ Polygon poly77(4);
+ poly77.ps[0] = Point(267.924, 753.557);
+ poly77.ps[1] = Point(267.924, 773.557);
+ poly77.ps[2] = Point(247.924, 773.557);
+ poly77.ps[3] = Point(247.924, 753.557);
+ new ShapeRef(router, poly77, 77);
+
+ Polygon poly78(4);
+ poly78.ps[0] = Point(387.924, 617.557);
+ poly78.ps[1] = Point(387.924, 637.557);
+ poly78.ps[2] = Point(367.924, 637.557);
+ poly78.ps[3] = Point(367.924, 617.557);
+ new ShapeRef(router, poly78, 78);
+
+ Polygon poly79(4);
+ poly79.ps[0] = Point(387.924, 753.557);
+ poly79.ps[1] = Point(387.924, 773.557);
+ poly79.ps[2] = Point(367.924, 773.557);
+ poly79.ps[3] = Point(367.924, 753.557);
+ new ShapeRef(router, poly79, 79);
+
+ Polygon poly80(4);
+ poly80.ps[0] = Point(507.924, 753.557);
+ poly80.ps[1] = Point(507.924, 773.557);
+ poly80.ps[2] = Point(487.924, 773.557);
+ poly80.ps[3] = Point(487.924, 753.557);
+ new ShapeRef(router, poly80, 80);
+
+ Polygon poly81(4);
+ poly81.ps[0] = Point(627.924, 753.557);
+ poly81.ps[1] = Point(627.924, 773.557);
+ poly81.ps[2] = Point(607.924, 773.557);
+ poly81.ps[3] = Point(607.924, 753.557);
+ new ShapeRef(router, poly81, 81);
+
+ Polygon poly82(4);
+ poly82.ps[0] = Point(507.924, 893.057);
+ poly82.ps[1] = Point(507.924, 913.057);
+ poly82.ps[2] = Point(487.924, 913.057);
+ poly82.ps[3] = Point(487.924, 893.057);
+ new ShapeRef(router, poly82, 82);
+
+ Polygon poly83(4);
+ poly83.ps[0] = Point(627.924, 893.057);
+ poly83.ps[1] = Point(627.924, 913.057);
+ poly83.ps[2] = Point(607.924, 913.057);
+ poly83.ps[3] = Point(607.924, 893.057);
+ new ShapeRef(router, poly83, 83);
+
+ Polygon poly84(4);
+ poly84.ps[0] = Point(387.924, 151.557);
+ poly84.ps[1] = Point(387.924, 171.557);
+ poly84.ps[2] = Point(367.924, 171.557);
+ poly84.ps[3] = Point(367.924, 151.557);
+ new ShapeRef(router, poly84, 84);
+
+ Polygon poly85(4);
+ poly85.ps[0] = Point(387.924, 17.3422);
+ poly85.ps[1] = Point(387.924, 37.3422);
+ poly85.ps[2] = Point(367.924, 37.3422);
+ poly85.ps[3] = Point(367.924, 17.3422);
+ new ShapeRef(router, poly85, 85);
+
+ Polygon poly86(4);
+ poly86.ps[0] = Point(507.924, 35.8422);
+ poly86.ps[1] = Point(507.924, 55.8422);
+ poly86.ps[2] = Point(487.924, 55.8422);
+ poly86.ps[3] = Point(487.924, 35.8422);
+ new ShapeRef(router, poly86, 86);
+
+ Polygon poly87(4);
+ poly87.ps[0] = Point(627.924, 35.8422);
+ poly87.ps[1] = Point(627.924, 55.8422);
+ poly87.ps[2] = Point(607.924, 55.8422);
+ poly87.ps[3] = Point(607.924, 35.8422);
+ new ShapeRef(router, poly87, 87);
+
+ Polygon poly88(4);
+ poly88.ps[0] = Point(747.924, 564.057);
+ poly88.ps[1] = Point(747.924, 584.057);
+ poly88.ps[2] = Point(727.924, 584.057);
+ poly88.ps[3] = Point(727.924, 564.057);
+ new ShapeRef(router, poly88, 88);
+
+ Polygon poly89(4);
+ poly89.ps[0] = Point(507.924, 517.557);
+ poly89.ps[1] = Point(507.924, 537.557);
+ poly89.ps[2] = Point(487.924, 537.557);
+ poly89.ps[3] = Point(487.924, 517.557);
+ new ShapeRef(router, poly89, 89);
+
+ Polygon poly90(4);
+ poly90.ps[0] = Point(507.924, 425.557);
+ poly90.ps[1] = Point(507.924, 445.557);
+ poly90.ps[2] = Point(487.924, 445.557);
+ poly90.ps[3] = Point(487.924, 425.557);
+ new ShapeRef(router, poly90, 90);
+
+ Polygon poly91(4);
+ poly91.ps[0] = Point(627.924, 517.557);
+ poly91.ps[1] = Point(627.924, 537.557);
+ poly91.ps[2] = Point(607.924, 537.557);
+ poly91.ps[3] = Point(607.924, 517.557);
+ new ShapeRef(router, poly91, 91);
+
+ Polygon poly92(4);
+ poly92.ps[0] = Point(627.924, 425.557);
+ poly92.ps[1] = Point(627.924, 445.557);
+ poly92.ps[2] = Point(607.924, 445.557);
+ poly92.ps[3] = Point(607.924, 425.557);
+ new ShapeRef(router, poly92, 92);
+
+ Polygon poly93(4);
+ poly93.ps[0] = Point(867.924, 333.557);
+ poly93.ps[1] = Point(867.924, 353.557);
+ poly93.ps[2] = Point(847.924, 353.557);
+ poly93.ps[3] = Point(847.924, 333.557);
+ new ShapeRef(router, poly93, 93);
+
+ Polygon poly94(4);
+ poly94.ps[0] = Point(867.924, 425.557);
+ poly94.ps[1] = Point(867.924, 445.557);
+ poly94.ps[2] = Point(847.924, 445.557);
+ poly94.ps[3] = Point(847.924, 425.557);
+ new ShapeRef(router, poly94, 94);
+
+ Polygon poly95(4);
+ poly95.ps[0] = Point(867.924, 151.557);
+ poly95.ps[1] = Point(867.924, 171.557);
+ poly95.ps[2] = Point(847.924, 171.557);
+ poly95.ps[3] = Point(847.924, 151.557);
+ new ShapeRef(router, poly95, 95);
+
+ Polygon poly96(4);
+ poly96.ps[0] = Point(747.924, 333.557);
+ poly96.ps[1] = Point(747.924, 353.557);
+ poly96.ps[2] = Point(727.924, 353.557);
+ poly96.ps[3] = Point(727.924, 333.557);
+ new ShapeRef(router, poly96, 96);
+
+ Polygon poly97(4);
+ poly97.ps[0] = Point(1088.92, 378.557);
+ poly97.ps[1] = Point(1088.92, 398.557);
+ poly97.ps[2] = Point(1068.92, 398.557);
+ poly97.ps[3] = Point(1068.92, 378.557);
+ new ShapeRef(router, poly97, 97);
+
+ Polygon poly98(4);
+ poly98.ps[0] = Point(1208.92, 378.557);
+ poly98.ps[1] = Point(1208.92, 398.557);
+ poly98.ps[2] = Point(1188.92, 398.557);
+ poly98.ps[3] = Point(1188.92, 378.557);
+ new ShapeRef(router, poly98, 98);
+
+ Polygon poly99(4);
+ poly99.ps[0] = Point(1088.92, 142.342);
+ poly99.ps[1] = Point(1088.92, 162.342);
+ poly99.ps[2] = Point(1068.92, 162.342);
+ poly99.ps[3] = Point(1068.92, 142.342);
+ new ShapeRef(router, poly99, 99);
+
+ Polygon poly100(4);
+ poly100.ps[0] = Point(1088.92, 50.3422);
+ poly100.ps[1] = Point(1088.92, 70.3422);
+ poly100.ps[2] = Point(1068.92, 70.3422);
+ poly100.ps[3] = Point(1068.92, 50.3422);
+ new ShapeRef(router, poly100, 100);
+
+ Polygon poly101(4);
+ poly101.ps[0] = Point(1208.92, 142.342);
+ poly101.ps[1] = Point(1208.92, 162.342);
+ poly101.ps[2] = Point(1188.92, 162.342);
+ poly101.ps[3] = Point(1188.92, 142.342);
+ new ShapeRef(router, poly101, 101);
+
+ Polygon poly102(4);
+ poly102.ps[0] = Point(1088.92, -70.6578);
+ poly102.ps[1] = Point(1088.92, -50.6578);
+ poly102.ps[2] = Point(1068.92, -50.6578);
+ poly102.ps[3] = Point(1068.92, -70.6578);
+ new ShapeRef(router, poly102, 102);
+
+ Polygon poly103(4);
+ poly103.ps[0] = Point(968.924, 270.557);
+ poly103.ps[1] = Point(968.924, 290.557);
+ poly103.ps[2] = Point(948.924, 290.557);
+ poly103.ps[3] = Point(948.924, 270.557);
+ new ShapeRef(router, poly103, 103);
+
+ Polygon poly11(4);
+ poly11.ps[0] = Point(817.924, -80.6578);
+ poly11.ps[1] = Point(817.924, -40.6578);
+ poly11.ps[2] = Point(777.924, -40.6578);
+ poly11.ps[3] = Point(777.924, -80.6578);
+ new ShapeRef(router, poly11, 11);
+
+ Polygon poly20(4);
+ poly20.ps[0] = Point(337.924, 507.557);
+ poly20.ps[1] = Point(337.924, 547.557);
+ poly20.ps[2] = Point(297.924, 547.557);
+ poly20.ps[3] = Point(297.924, 507.557);
+ new ShapeRef(router, poly20, 20);
+
+ Polygon poly33(4);
+ poly33.ps[0] = Point(937.924, 415.557);
+ poly33.ps[1] = Point(937.924, 455.557);
+ poly33.ps[2] = Point(897.924, 455.557);
+ poly33.ps[3] = Point(897.924, 415.557);
+ new ShapeRef(router, poly33, 33);
+
+ Polygon poly27(4);
+ poly27.ps[0] = Point(577.924, 507.557);
+ poly27.ps[1] = Point(577.924, 547.557);
+ poly27.ps[2] = Point(537.924, 547.557);
+ poly27.ps[3] = Point(537.924, 507.557);
+ new ShapeRef(router, poly27, 27);
+
+ Polygon poly1(4);
+ poly1.ps[0] = Point(817.924, 840.057);
+ poly1.ps[1] = Point(817.924, 880.057);
+ poly1.ps[2] = Point(777.924, 880.057);
+ poly1.ps[3] = Point(777.924, 840.057);
+ new ShapeRef(router, poly1, 1);
+
+ Polygon poly104(4);
+ poly104.ps[0] = Point(747.924, 151.557);
+ poly104.ps[1] = Point(747.924, 171.557);
+ poly104.ps[2] = Point(727.924, 171.557);
+ poly104.ps[3] = Point(727.924, 151.557);
+ new ShapeRef(router, poly104, 104);
+
+ Polygon poly105(4);
+ poly105.ps[0] = Point(747.924, 850.057);
+ poly105.ps[1] = Point(747.924, 870.057);
+ poly105.ps[2] = Point(727.924, 870.057);
+ poly105.ps[3] = Point(727.924, 850.057);
+ new ShapeRef(router, poly105, 105);
+
+ Polygon poly106(4);
+ poly106.ps[0] = Point(765.924, -130.658);
+ poly106.ps[1] = Point(765.924, -90.6578);
+ poly106.ps[2] = Point(709.924, -90.6578);
+ poly106.ps[3] = Point(709.924, -130.658);
+ new ShapeRef(router, poly106, 106);
+
+ Polygon poly107(4);
+ poly107.ps[0] = Point(165.924, -35.1578);
+ poly107.ps[1] = Point(165.924, 4.84222);
+ poly107.ps[2] = Point(109.924, 4.84222);
+ poly107.ps[3] = Point(109.924, -35.1578);
+ new ShapeRef(router, poly107, 107);
+
+ Polygon poly108(4);
+ poly108.ps[0] = Point(165.924, 91.5565);
+ poly108.ps[1] = Point(165.924, 131.557);
+ poly108.ps[2] = Point(109.924, 131.557);
+ poly108.ps[3] = Point(109.924, 91.5565);
+ new ShapeRef(router, poly108, 108);
+
+ Polygon poly109(4);
+ poly109.ps[0] = Point(285.924, 91.5565);
+ poly109.ps[1] = Point(285.924, 131.557);
+ poly109.ps[2] = Point(229.924, 131.557);
+ poly109.ps[3] = Point(229.924, 91.5565);
+ new ShapeRef(router, poly109, 109);
+
+ Polygon poly110(4);
+ poly110.ps[0] = Point(287.924, 193.557);
+ poly110.ps[1] = Point(287.924, 233.557);
+ poly110.ps[2] = Point(231.924, 233.557);
+ poly110.ps[3] = Point(231.924, 193.557);
+ new ShapeRef(router, poly110, 110);
+
+ Polygon poly111(4);
+ poly111.ps[0] = Point(285.924, 245.557);
+ poly111.ps[1] = Point(285.924, 285.557);
+ poly111.ps[2] = Point(229.924, 285.557);
+ poly111.ps[3] = Point(229.924, 245.557);
+ new ShapeRef(router, poly111, 111);
+
+ Polygon poly112(4);
+ poly112.ps[0] = Point(167.924, 347.557);
+ poly112.ps[1] = Point(167.924, 387.557);
+ poly112.ps[2] = Point(111.924, 387.557);
+ poly112.ps[3] = Point(111.924, 347.557);
+ new ShapeRef(router, poly112, 112);
+
+ Polygon poly113(4);
+ poly113.ps[0] = Point(165.924, 457.557);
+ poly113.ps[1] = Point(165.924, 497.557);
+ poly113.ps[2] = Point(109.924, 497.557);
+ poly113.ps[3] = Point(109.924, 457.557);
+ new ShapeRef(router, poly113, 113);
+
+ Polygon poly114(4);
+ poly114.ps[0] = Point(165.924, 549.557);
+ poly114.ps[1] = Point(165.924, 589.557);
+ poly114.ps[2] = Point(109.924, 589.557);
+ poly114.ps[3] = Point(109.924, 549.557);
+ new ShapeRef(router, poly114, 114);
+
+ Polygon poly115(4);
+ poly115.ps[0] = Point(167.924, 641.557);
+ poly115.ps[1] = Point(167.924, 681.557);
+ poly115.ps[2] = Point(111.924, 681.557);
+ poly115.ps[3] = Point(111.924, 641.557);
+ new ShapeRef(router, poly115, 115);
+
+ Polygon poly116(4);
+ poly116.ps[0] = Point(165.924, 693.557);
+ poly116.ps[1] = Point(165.924, 733.557);
+ poly116.ps[2] = Point(109.924, 733.557);
+ poly116.ps[3] = Point(109.924, 693.557);
+ new ShapeRef(router, poly116, 116);
+
+ Polygon poly117(4);
+ poly117.ps[0] = Point(285.924, 693.557);
+ poly117.ps[1] = Point(285.924, 733.557);
+ poly117.ps[2] = Point(229.924, 733.557);
+ poly117.ps[3] = Point(229.924, 693.557);
+ new ShapeRef(router, poly117, 117);
+
+ Polygon poly118(4);
+ poly118.ps[0] = Point(405.924, 557.557);
+ poly118.ps[1] = Point(405.924, 597.557);
+ poly118.ps[2] = Point(349.924, 597.557);
+ poly118.ps[3] = Point(349.924, 557.557);
+ new ShapeRef(router, poly118, 118);
+
+ Polygon poly119(4);
+ poly119.ps[0] = Point(405.924, 693.557);
+ poly119.ps[1] = Point(405.924, 733.557);
+ poly119.ps[2] = Point(349.924, 733.557);
+ poly119.ps[3] = Point(349.924, 693.557);
+ new ShapeRef(router, poly119, 119);
+
+ Polygon poly120(4);
+ poly120.ps[0] = Point(525.924, 693.557);
+ poly120.ps[1] = Point(525.924, 733.557);
+ poly120.ps[2] = Point(469.924, 733.557);
+ poly120.ps[3] = Point(469.924, 693.557);
+ new ShapeRef(router, poly120, 120);
+
+ Polygon poly121(4);
+ poly121.ps[0] = Point(645.924, 693.557);
+ poly121.ps[1] = Point(645.924, 733.557);
+ poly121.ps[2] = Point(589.924, 733.557);
+ poly121.ps[3] = Point(589.924, 693.557);
+ new ShapeRef(router, poly121, 121);
+
+ Polygon poly122(4);
+ poly122.ps[0] = Point(525.924, 833.057);
+ poly122.ps[1] = Point(525.924, 873.057);
+ poly122.ps[2] = Point(469.924, 873.057);
+ poly122.ps[3] = Point(469.924, 833.057);
+ new ShapeRef(router, poly122, 122);
+
+ Polygon poly13(4);
+ poly13.ps[0] = Point(1158.92, 323.557);
+ poly13.ps[1] = Point(1158.92, 363.557);
+ poly13.ps[2] = Point(1118.92, 363.557);
+ poly13.ps[3] = Point(1118.92, 323.557);
+ new ShapeRef(router, poly13, 13);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(1038.92, -80.6578);
+ poly9.ps[1] = Point(1038.92, -40.6578);
+ poly9.ps[2] = Point(998.924, -40.6578);
+ poly9.ps[3] = Point(998.924, -80.6578);
+ new ShapeRef(router, poly9, 9);
+
+ Polygon poly26(4);
+ poly26.ps[0] = Point(697.924, 743.557);
+ poly26.ps[1] = Point(697.924, 783.557);
+ poly26.ps[2] = Point(657.924, 783.557);
+ poly26.ps[3] = Point(657.924, 743.557);
+ new ShapeRef(router, poly26, 26);
+
+ Polygon poly37(4);
+ poly37.ps[0] = Point(457.924, 607.557);
+ poly37.ps[1] = Point(457.924, 647.557);
+ poly37.ps[2] = Point(417.924, 647.557);
+ poly37.ps[3] = Point(417.924, 607.557);
+ new ShapeRef(router, poly37, 37);
+
+ Polygon poly17(4);
+ poly17.ps[0] = Point(577.924, 883.057);
+ poly17.ps[1] = Point(577.924, 923.057);
+ poly17.ps[2] = Point(537.924, 923.057);
+ poly17.ps[3] = Point(537.924, 883.057);
+ new ShapeRef(router, poly17, 17);
+
+ Polygon poly38(4);
+ poly38.ps[0] = Point(217.924, 507.557);
+ poly38.ps[1] = Point(217.924, 547.557);
+ poly38.ps[2] = Point(177.924, 547.557);
+ poly38.ps[3] = Point(177.924, 507.557);
+ new ShapeRef(router, poly38, 38);
+
+ Polygon poly41(4);
+ poly41.ps[0] = Point(577.924, 743.557);
+ poly41.ps[1] = Point(577.924, 783.557);
+ poly41.ps[2] = Point(537.924, 783.557);
+ poly41.ps[3] = Point(537.924, 743.557);
+ new ShapeRef(router, poly41, 41);
+
+ Polygon poly28(4);
+ poly28.ps[0] = Point(817.924, 323.557);
+ poly28.ps[1] = Point(817.924, 363.557);
+ poly28.ps[2] = Point(777.924, 363.557);
+ poly28.ps[3] = Point(777.924, 323.557);
+ new ShapeRef(router, poly28, 28);
+
+ Polygon poly21(4);
+ poly21.ps[0] = Point(937.924, 141.557);
+ poly21.ps[1] = Point(937.924, 181.557);
+ poly21.ps[2] = Point(897.924, 181.557);
+ poly21.ps[3] = Point(897.924, 141.557);
+ new ShapeRef(router, poly21, 21);
+
+ Polygon poly48(4);
+ poly48.ps[0] = Point(97.9242, 743.557);
+ poly48.ps[1] = Point(97.9242, 783.557);
+ poly48.ps[2] = Point(57.9242, 783.557);
+ poly48.ps[3] = Point(57.9242, 743.557);
+ new ShapeRef(router, poly48, 48);
+
+ Polygon poly49(4);
+ poly49.ps[0] = Point(45.9242, 169.75);
+ poly49.ps[1] = Point(45.9242, 334.75);
+ poly49.ps[2] = Point(-242.076, 334.75);
+ poly49.ps[3] = Point(-242.076, 169.75);
+ new ShapeRef(router, poly49, 49);
+
+ Polygon poly50(4);
+ poly50.ps[0] = Point(272.5, -82.1578);
+ poly50.ps[1] = Point(272.5, -47.1578);
+ poly50.ps[2] = Point(35.5, -47.1578);
+ poly50.ps[3] = Point(35.5, -82.1578);
+ new ShapeRef(router, poly50, 50);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(1278.92, -22.1578);
+ poly3.ps[1] = Point(1278.92, 17.8422);
+ poly3.ps[2] = Point(1238.92, 17.8422);
+ poly3.ps[3] = Point(1238.92, -22.1578);
+ new ShapeRef(router, poly3, 3);
+
+ Polygon poly43(4);
+ poly43.ps[0] = Point(1038.92, 1.84222);
+ poly43.ps[1] = Point(1038.92, 41.8422);
+ poly43.ps[2] = Point(998.924, 41.8422);
+ poly43.ps[3] = Point(998.924, 1.84222);
+ new ShapeRef(router, poly43, 43);
+
+ Polygon poly30(4);
+ poly30.ps[0] = Point(1278.92, 415.557);
+ poly30.ps[1] = Point(1278.92, 455.557);
+ poly30.ps[2] = Point(1238.92, 455.557);
+ poly30.ps[3] = Point(1238.92, 415.557);
+ new ShapeRef(router, poly30, 30);
+
+ Polygon poly31(4);
+ poly31.ps[0] = Point(1278.92, 141.557);
+ poly31.ps[1] = Point(1278.92, 181.557);
+ poly31.ps[2] = Point(1238.92, 181.557);
+ poly31.ps[3] = Point(1238.92, 141.557);
+ new ShapeRef(router, poly31, 31);
+
+ Polygon poly46(4);
+ poly46.ps[0] = Point(577.924, 415.557);
+ poly46.ps[1] = Point(577.924, 455.557);
+ poly46.ps[2] = Point(537.924, 455.557);
+ poly46.ps[3] = Point(537.924, 415.557);
+ new ShapeRef(router, poly46, 46);
+
+ Polygon poly14(4);
+ poly14.ps[0] = Point(1158.92, 141.557);
+ poly14.ps[1] = Point(1158.92, 181.557);
+ poly14.ps[2] = Point(1118.92, 181.557);
+ poly14.ps[3] = Point(1118.92, 141.557);
+ new ShapeRef(router, poly14, 14);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(577.924, 795.557);
+ poly2.ps[1] = Point(577.924, 835.557);
+ poly2.ps[2] = Point(537.924, 835.557);
+ poly2.ps[3] = Point(537.924, 795.557);
+ new ShapeRef(router, poly2, 2);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(1371.92, -22.1578);
+ poly5.ps[1] = Point(1371.92, 17.8422);
+ poly5.ps[2] = Point(1331.92, 17.8422);
+ poly5.ps[3] = Point(1331.92, -22.1578);
+ new ShapeRef(router, poly5, 5);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(937.924, -80.6578);
+ poly10.ps[1] = Point(937.924, -40.6578);
+ poly10.ps[2] = Point(897.924, -40.6578);
+ poly10.ps[3] = Point(897.924, -80.6578);
+ new ShapeRef(router, poly10, 10);
+
+ ConnRef *connRef248 = new ConnRef(router, 248);
+ ConnEnd srcPt248(Point(737.924, 524.057), 15);
+ connRef248->setSourceEndpoint(srcPt248);
+ ConnEnd dstPt248(Point(737.924, 574.057), 15);
+ connRef248->setDestEndpoint(dstPt248);
+ connRef248->setRoutingType((ConnType)2);
+
+ ConnRef *connRef249 = new ConnRef(router, 249);
+ ConnEnd srcPt249(Point(497.924, 477.557), 15);
+ connRef249->setSourceEndpoint(srcPt249);
+ ConnEnd dstPt249(Point(497.924, 527.557), 15);
+ connRef249->setDestEndpoint(dstPt249);
+ connRef249->setRoutingType((ConnType)2);
+
+ ConnRef *connRef250 = new ConnRef(router, 250);
+ ConnEnd srcPt250(Point(497.924, 385.557), 15);
+ connRef250->setSourceEndpoint(srcPt250);
+ ConnEnd dstPt250(Point(497.924, 435.557), 15);
+ connRef250->setDestEndpoint(dstPt250);
+ connRef250->setRoutingType((ConnType)2);
+
+ ConnRef *connRef251 = new ConnRef(router, 251);
+ ConnEnd srcPt251(Point(617.924, 477.557), 15);
+ connRef251->setSourceEndpoint(srcPt251);
+ ConnEnd dstPt251(Point(617.924, 527.557), 15);
+ connRef251->setDestEndpoint(dstPt251);
+ connRef251->setRoutingType((ConnType)2);
+
+ ConnRef *connRef252 = new ConnRef(router, 252);
+ ConnEnd srcPt252(Point(617.924, 385.557), 15);
+ connRef252->setSourceEndpoint(srcPt252);
+ ConnEnd dstPt252(Point(617.924, 435.557), 15);
+ connRef252->setDestEndpoint(dstPt252);
+ connRef252->setRoutingType((ConnType)2);
+
+ ConnRef *connRef253 = new ConnRef(router, 253);
+ ConnEnd srcPt253(Point(857.924, 293.557), 15);
+ connRef253->setSourceEndpoint(srcPt253);
+ ConnEnd dstPt253(Point(857.924, 343.557), 15);
+ connRef253->setDestEndpoint(dstPt253);
+ connRef253->setRoutingType((ConnType)2);
+
+ ConnRef *connRef254 = new ConnRef(router, 254);
+ ConnEnd srcPt254(Point(857.924, 385.557), 15);
+ connRef254->setSourceEndpoint(srcPt254);
+ ConnEnd dstPt254(Point(857.924, 435.557), 15);
+ connRef254->setDestEndpoint(dstPt254);
+ connRef254->setRoutingType((ConnType)2);
+
+ ConnRef *connRef255 = new ConnRef(router, 255);
+ ConnEnd srcPt255(Point(857.924, 111.557), 15);
+ connRef255->setSourceEndpoint(srcPt255);
+ ConnEnd dstPt255(Point(857.924, 161.557), 15);
+ connRef255->setDestEndpoint(dstPt255);
+ connRef255->setRoutingType((ConnType)2);
+
+ ConnRef *connRef256 = new ConnRef(router, 256);
+ ConnEnd srcPt256(Point(737.924, 293.557), 15);
+ connRef256->setSourceEndpoint(srcPt256);
+ ConnEnd dstPt256(Point(737.924, 343.557), 15);
+ connRef256->setDestEndpoint(dstPt256);
+ connRef256->setRoutingType((ConnType)2);
+
+ ConnRef *connRef257 = new ConnRef(router, 257);
+ ConnEnd srcPt257(Point(1078.92, 338.557), 15);
+ connRef257->setSourceEndpoint(srcPt257);
+ ConnEnd dstPt257(Point(1078.92, 388.557), 15);
+ connRef257->setDestEndpoint(dstPt257);
+ connRef257->setRoutingType((ConnType)2);
+
+ ConnRef *connRef258 = new ConnRef(router, 258);
+ ConnEnd srcPt258(Point(1198.92, 338.557), 15);
+ connRef258->setSourceEndpoint(srcPt258);
+ ConnEnd dstPt258(Point(1198.92, 388.557), 15);
+ connRef258->setDestEndpoint(dstPt258);
+ connRef258->setRoutingType((ConnType)2);
+
+ ConnRef *connRef259 = new ConnRef(router, 259);
+ ConnEnd srcPt259(Point(1078.92, 102.342), 15);
+ connRef259->setSourceEndpoint(srcPt259);
+ ConnEnd dstPt259(Point(1078.92, 152.342), 15);
+ connRef259->setDestEndpoint(dstPt259);
+ connRef259->setRoutingType((ConnType)2);
+
+ ConnRef *connRef260 = new ConnRef(router, 260);
+ ConnEnd srcPt260(Point(1078.92, 10.3422), 15);
+ connRef260->setSourceEndpoint(srcPt260);
+ ConnEnd dstPt260(Point(1078.92, 60.3422), 15);
+ connRef260->setDestEndpoint(dstPt260);
+ connRef260->setRoutingType((ConnType)2);
+
+ ConnRef *connRef261 = new ConnRef(router, 261);
+ ConnEnd srcPt261(Point(1198.92, 102.342), 15);
+ connRef261->setSourceEndpoint(srcPt261);
+ ConnEnd dstPt261(Point(1198.92, 152.342), 15);
+ connRef261->setDestEndpoint(dstPt261);
+ connRef261->setRoutingType((ConnType)2);
+
+ ConnRef *connRef262 = new ConnRef(router, 262);
+ ConnEnd srcPt262(Point(1078.92, -110.658), 15);
+ connRef262->setSourceEndpoint(srcPt262);
+ ConnEnd dstPt262(Point(1078.92, -60.6578), 15);
+ connRef262->setDestEndpoint(dstPt262);
+ connRef262->setRoutingType((ConnType)2);
+
+ ConnRef *connRef263 = new ConnRef(router, 263);
+ ConnEnd srcPt263(Point(958.924, 230.557), 15);
+ connRef263->setSourceEndpoint(srcPt263);
+ ConnEnd dstPt263(Point(958.924, 280.557), 15);
+ connRef263->setDestEndpoint(dstPt263);
+ connRef263->setRoutingType((ConnType)2);
+
+ ConnRef *connRef264 = new ConnRef(router, 264);
+ ConnEnd srcPt264(Point(737.924, 111.557), 15);
+ connRef264->setSourceEndpoint(srcPt264);
+ ConnEnd dstPt264(Point(737.924, 161.557), 15);
+ connRef264->setDestEndpoint(dstPt264);
+ connRef264->setRoutingType((ConnType)2);
+
+ ConnRef *connRef265 = new ConnRef(router, 265);
+ ConnEnd srcPt265(Point(737.924, 810.057), 15);
+ connRef265->setSourceEndpoint(srcPt265);
+ ConnEnd dstPt265(Point(737.924, 860.057), 15);
+ connRef265->setDestEndpoint(dstPt265);
+ connRef265->setRoutingType((ConnType)2);
+
+ ConnRef *connRef266 = new ConnRef(router, 266);
+ ConnEnd srcPt266(Point(77.9242, 161.557), 15);
+ connRef266->setSourceEndpoint(srcPt266);
+ ConnEnd dstPt266(Point(40.9242, 252.5), 15);
+ connRef266->setDestEndpoint(dstPt266);
+ connRef266->setRoutingType((ConnType)2);
+
+ ConnRef *connRef267 = new ConnRef(router, 267);
+ ConnEnd srcPt267(Point(77.9242, 763.557), 15);
+ connRef267->setSourceEndpoint(srcPt267);
+ ConnEnd dstPt267(Point(-46.0758, 329.75), 15);
+ connRef267->setDestEndpoint(dstPt267);
+ connRef267->setRoutingType((ConnType)2);
+
+ ConnRef *connRef148 = new ConnRef(router, 148);
+ ConnEnd srcPt148(Point(1018.92, -60.6578), 15);
+ connRef148->setSourceEndpoint(srcPt148);
+ ConnEnd dstPt148(Point(1068.92, -60.6578), 15);
+ connRef148->setDestEndpoint(dstPt148);
+ connRef148->setRoutingType((ConnType)2);
+
+ ConnRef *connRef149 = new ConnRef(router, 149);
+ ConnEnd srcPt149(Point(1138.92, 161.557), 15);
+ connRef149->setSourceEndpoint(srcPt149);
+ ConnEnd dstPt149(Point(1188.92, 152.342), 15);
+ connRef149->setDestEndpoint(dstPt149);
+ connRef149->setRoutingType((ConnType)2);
+
+ ConnRef *connRef150 = new ConnRef(router, 150);
+ ConnEnd srcPt150(Point(1138.92, 435.557), 15);
+ connRef150->setSourceEndpoint(srcPt150);
+ ConnEnd dstPt150(Point(1188.92, 388.557), 15);
+ connRef150->setDestEndpoint(dstPt150);
+ connRef150->setRoutingType((ConnType)2);
+
+ ConnRef *connRef151 = new ConnRef(router, 151);
+ ConnEnd srcPt151(Point(317.924, 763.557), 15);
+ connRef151->setSourceEndpoint(srcPt151);
+ ConnEnd dstPt151(Point(367.924, 627.557), 15);
+ connRef151->setDestEndpoint(dstPt151);
+ connRef151->setRoutingType((ConnType)2);
+
+ ConnRef *connRef152 = new ConnRef(router, 152);
+ ConnEnd srcPt152(Point(317.924, 763.557), 15);
+ connRef152->setSourceEndpoint(srcPt152);
+ ConnEnd dstPt152(Point(367.924, 763.557), 15);
+ connRef152->setDestEndpoint(dstPt152);
+ connRef152->setRoutingType((ConnType)2);
+
+ ConnRef *connRef153 = new ConnRef(router, 153);
+ ConnEnd srcPt153(Point(317.924, 763.557), 15);
+ connRef153->setSourceEndpoint(srcPt153);
+ ConnEnd dstPt153(Point(487.924, 903.057), 15);
+ connRef153->setDestEndpoint(dstPt153);
+ connRef153->setRoutingType((ConnType)2);
+
+ ConnRef *connRef154 = new ConnRef(router, 154);
+ ConnEnd srcPt154(Point(317.924, 763.557), 15);
+ connRef154->setSourceEndpoint(srcPt154);
+ ConnEnd dstPt154(Point(727.924, 574.057), 15);
+ connRef154->setDestEndpoint(dstPt154);
+ connRef154->setRoutingType((ConnType)2);
+
+ ConnRef *connRef155 = new ConnRef(router, 155);
+ ConnEnd srcPt155(Point(557.924, 903.057), 15);
+ connRef155->setSourceEndpoint(srcPt155);
+ ConnEnd dstPt155(Point(607.924, 903.057), 15);
+ connRef155->setDestEndpoint(dstPt155);
+ connRef155->setRoutingType((ConnType)2);
+
+ ConnRef *connRef156 = new ConnRef(router, 156);
+ ConnEnd srcPt156(Point(197.924, 763.557), 15);
+ connRef156->setSourceEndpoint(srcPt156);
+ ConnEnd dstPt156(Point(247.924, 763.557), 15);
+ connRef156->setDestEndpoint(dstPt156);
+ connRef156->setRoutingType((ConnType)2);
+
+ ConnRef *connRef157 = new ConnRef(router, 157);
+ ConnEnd srcPt157(Point(147.924, 161.557), 15);
+ connRef157->setSourceEndpoint(srcPt157);
+ ConnEnd dstPt157(Point(197.924, 161.557), 15);
+ connRef157->setDestEndpoint(dstPt157);
+ connRef157->setRoutingType((ConnType)2);
+
+ ConnRef *connRef158 = new ConnRef(router, 158);
+ ConnEnd srcPt158(Point(197.924, 161.557), 15);
+ connRef158->setSourceEndpoint(srcPt158);
+ ConnEnd dstPt158(Point(247.924, 161.557), 15);
+ connRef158->setDestEndpoint(dstPt158);
+ connRef158->setRoutingType((ConnType)2);
+
+ ConnRef *connRef159 = new ConnRef(router, 159);
+ ConnEnd srcPt159(Point(197.924, 161.557), 15);
+ connRef159->setSourceEndpoint(srcPt159);
+ ConnEnd dstPt159(Point(197.924, 203.557), 15);
+ connRef159->setDestEndpoint(dstPt159);
+ connRef159->setRoutingType((ConnType)2);
+
+ ConnRef *connRef160 = new ConnRef(router, 160);
+ ConnEnd srcPt160(Point(317.924, 161.557), 15);
+ connRef160->setSourceEndpoint(srcPt160);
+ ConnEnd dstPt160(Point(727.924, -60.6578), 15);
+ connRef160->setDestEndpoint(dstPt160);
+ connRef160->setRoutingType((ConnType)2);
+
+ ConnRef *connRef161 = new ConnRef(router, 161);
+ ConnEnd srcPt161(Point(317.924, 161.557), 15);
+ connRef161->setSourceEndpoint(srcPt161);
+ ConnEnd dstPt161(Point(367.924, 161.557), 15);
+ connRef161->setDestEndpoint(dstPt161);
+ connRef161->setRoutingType((ConnType)2);
+
+ ConnRef *connRef162 = new ConnRef(router, 162);
+ ConnEnd srcPt162(Point(317.924, 161.557), 15);
+ connRef162->setSourceEndpoint(srcPt162);
+ ConnEnd dstPt162(Point(367.924, 27.3422), 15);
+ connRef162->setDestEndpoint(dstPt162);
+ connRef162->setRoutingType((ConnType)2);
+
+ ConnRef *connRef163 = new ConnRef(router, 163);
+ ConnEnd srcPt163(Point(317.924, 161.557), 15);
+ connRef163->setSourceEndpoint(srcPt163);
+ ConnEnd dstPt163(Point(487.924, 435.557), 15);
+ connRef163->setDestEndpoint(dstPt163);
+ connRef163->setRoutingType((ConnType)2);
+
+ ConnRef *connRef164 = new ConnRef(router, 164);
+ ConnEnd srcPt164(Point(437.924, 763.557), 15);
+ connRef164->setSourceEndpoint(srcPt164);
+ ConnEnd dstPt164(Point(487.924, 763.557), 15);
+ connRef164->setDestEndpoint(dstPt164);
+ connRef164->setRoutingType((ConnType)2);
+
+ ConnRef *connRef165 = new ConnRef(router, 165);
+ ConnEnd srcPt165(Point(437.924, 763.557), 15);
+ connRef165->setSourceEndpoint(srcPt165);
+ ConnEnd dstPt165(Point(727.924, 860.057), 15);
+ connRef165->setDestEndpoint(dstPt165);
+ connRef165->setRoutingType((ConnType)2);
+
+ ConnRef *connRef166 = new ConnRef(router, 166);
+ ConnEnd srcPt166(Point(557.924, 527.557), 15);
+ connRef166->setSourceEndpoint(srcPt166);
+ ConnEnd dstPt166(Point(607.924, 527.557), 15);
+ connRef166->setDestEndpoint(dstPt166);
+ connRef166->setRoutingType((ConnType)2);
+
+ ConnRef *connRef167 = new ConnRef(router, 167);
+ ConnEnd srcPt167(Point(797.924, 343.557), 15);
+ connRef167->setSourceEndpoint(srcPt167);
+ ConnEnd dstPt167(Point(847.924, 343.557), 15);
+ connRef167->setDestEndpoint(dstPt167);
+ connRef167->setRoutingType((ConnType)2);
+
+ ConnRef *connRef168 = new ConnRef(router, 168);
+ ConnEnd srcPt168(Point(797.924, 343.557), 15);
+ connRef168->setSourceEndpoint(srcPt168);
+ ConnEnd dstPt168(Point(847.924, 435.557), 15);
+ connRef168->setDestEndpoint(dstPt168);
+ connRef168->setRoutingType((ConnType)2);
+
+ ConnRef *connRef169 = new ConnRef(router, 169);
+ ConnEnd srcPt169(Point(1018.92, 435.557), 15);
+ connRef169->setSourceEndpoint(srcPt169);
+ ConnEnd dstPt169(Point(1068.92, 388.557), 15);
+ connRef169->setDestEndpoint(dstPt169);
+ connRef169->setRoutingType((ConnType)2);
+
+ ConnRef *connRef208 = new ConnRef(router, 208);
+ ConnEnd srcPt208(Point(627.924, 45.8422), 15);
+ connRef208->setSourceEndpoint(srcPt208);
+ ConnEnd dstPt208(Point(677.924, 54.8422), 15);
+ connRef208->setDestEndpoint(dstPt208);
+ connRef208->setRoutingType((ConnType)2);
+
+ ConnRef *connRef209 = new ConnRef(router, 209);
+ ConnEnd srcPt209(Point(747.924, 574.057), 15);
+ connRef209->setSourceEndpoint(srcPt209);
+ ConnEnd dstPt209(Point(797.924, 574.057), 15);
+ connRef209->setDestEndpoint(dstPt209);
+ connRef209->setRoutingType((ConnType)2);
+
+ ConnRef *connRef210 = new ConnRef(router, 210);
+ ConnEnd srcPt210(Point(507.924, 527.557), 15);
+ connRef210->setSourceEndpoint(srcPt210);
+ ConnEnd dstPt210(Point(557.924, 527.557), 15);
+ connRef210->setDestEndpoint(dstPt210);
+ connRef210->setRoutingType((ConnType)2);
+
+ ConnRef *connRef211 = new ConnRef(router, 211);
+ ConnEnd srcPt211(Point(507.924, 435.557), 15);
+ connRef211->setSourceEndpoint(srcPt211);
+ ConnEnd dstPt211(Point(557.924, 435.557), 15);
+ connRef211->setDestEndpoint(dstPt211);
+ connRef211->setRoutingType((ConnType)2);
+
+ ConnRef *connRef212 = new ConnRef(router, 212);
+ ConnEnd srcPt212(Point(627.924, 527.557), 15);
+ connRef212->setSourceEndpoint(srcPt212);
+ ConnEnd dstPt212(Point(677.924, 527.557), 15);
+ connRef212->setDestEndpoint(dstPt212);
+ connRef212->setRoutingType((ConnType)2);
+
+ ConnRef *connRef213 = new ConnRef(router, 213);
+ ConnEnd srcPt213(Point(627.924, 435.557), 15);
+ connRef213->setSourceEndpoint(srcPt213);
+ ConnEnd dstPt213(Point(677.924, 435.557), 15);
+ connRef213->setDestEndpoint(dstPt213);
+ connRef213->setRoutingType((ConnType)2);
+
+ ConnRef *connRef214 = new ConnRef(router, 214);
+ ConnEnd srcPt214(Point(867.924, 343.557), 15);
+ connRef214->setSourceEndpoint(srcPt214);
+ ConnEnd dstPt214(Point(917.924, 343.557), 15);
+ connRef214->setDestEndpoint(dstPt214);
+ connRef214->setRoutingType((ConnType)2);
+
+ ConnRef *connRef215 = new ConnRef(router, 215);
+ ConnEnd srcPt215(Point(867.924, 435.557), 15);
+ connRef215->setSourceEndpoint(srcPt215);
+ ConnEnd dstPt215(Point(917.924, 435.557), 15);
+ connRef215->setDestEndpoint(dstPt215);
+ connRef215->setRoutingType((ConnType)2);
+
+ ConnRef *connRef216 = new ConnRef(router, 216);
+ ConnEnd srcPt216(Point(867.924, 161.557), 15);
+ connRef216->setSourceEndpoint(srcPt216);
+ ConnEnd dstPt216(Point(917.924, 161.557), 15);
+ connRef216->setDestEndpoint(dstPt216);
+ connRef216->setRoutingType((ConnType)2);
+
+ ConnRef *connRef217 = new ConnRef(router, 217);
+ ConnEnd srcPt217(Point(747.924, 343.557), 15);
+ connRef217->setSourceEndpoint(srcPt217);
+ ConnEnd dstPt217(Point(797.924, 343.557), 15);
+ connRef217->setDestEndpoint(dstPt217);
+ connRef217->setRoutingType((ConnType)2);
+
+ ConnRef *connRef218 = new ConnRef(router, 218);
+ ConnEnd srcPt218(Point(1088.92, 388.557), 15);
+ connRef218->setSourceEndpoint(srcPt218);
+ ConnEnd dstPt218(Point(1138.92, 435.557), 15);
+ connRef218->setDestEndpoint(dstPt218);
+ connRef218->setRoutingType((ConnType)2);
+
+ ConnRef *connRef219 = new ConnRef(router, 219);
+ ConnEnd srcPt219(Point(1208.92, 388.557), 15);
+ connRef219->setSourceEndpoint(srcPt219);
+ ConnEnd dstPt219(Point(1258.92, 435.557), 15);
+ connRef219->setDestEndpoint(dstPt219);
+ connRef219->setRoutingType((ConnType)2);
+
+ ConnRef *connRef220 = new ConnRef(router, 220);
+ ConnEnd srcPt220(Point(1088.92, 152.342), 15);
+ connRef220->setSourceEndpoint(srcPt220);
+ ConnEnd dstPt220(Point(1138.92, 161.557), 15);
+ connRef220->setDestEndpoint(dstPt220);
+ connRef220->setRoutingType((ConnType)2);
+
+ ConnRef *connRef221 = new ConnRef(router, 221);
+ ConnEnd srcPt221(Point(1088.92, 60.3422), 15);
+ connRef221->setSourceEndpoint(srcPt221);
+ ConnEnd dstPt221(Point(1138.92, 60.3422), 15);
+ connRef221->setDestEndpoint(dstPt221);
+ connRef221->setRoutingType((ConnType)2);
+
+ ConnRef *connRef222 = new ConnRef(router, 222);
+ ConnEnd srcPt222(Point(1208.92, 152.342), 15);
+ connRef222->setSourceEndpoint(srcPt222);
+ ConnEnd dstPt222(Point(1258.92, 161.557), 15);
+ connRef222->setDestEndpoint(dstPt222);
+ connRef222->setRoutingType((ConnType)2);
+
+ ConnRef *connRef223 = new ConnRef(router, 223);
+ ConnEnd srcPt223(Point(1088.92, -60.6578), 15);
+ connRef223->setSourceEndpoint(srcPt223);
+ ConnEnd dstPt223(Point(1138.92, -60.6578), 15);
+ connRef223->setDestEndpoint(dstPt223);
+ connRef223->setRoutingType((ConnType)2);
+
+ ConnRef *connRef224 = new ConnRef(router, 224);
+ ConnEnd srcPt224(Point(747.924, 161.557), 15);
+ connRef224->setSourceEndpoint(srcPt224);
+ ConnEnd dstPt224(Point(797.924, 161.557), 15);
+ connRef224->setDestEndpoint(dstPt224);
+ connRef224->setRoutingType((ConnType)2);
+
+ ConnRef *connRef225 = new ConnRef(router, 225);
+ ConnEnd srcPt225(Point(747.924, 860.057), 15);
+ connRef225->setSourceEndpoint(srcPt225);
+ ConnEnd dstPt225(Point(797.924, 860.057), 15);
+ connRef225->setDestEndpoint(dstPt225);
+ connRef225->setRoutingType((ConnType)2);
+
+ ConnRef *connRef226 = new ConnRef(router, 226);
+ ConnEnd srcPt226(Point(737.924, -110.658), 15);
+ connRef226->setSourceEndpoint(srcPt226);
+ ConnEnd dstPt226(Point(737.924, -60.6578), 15);
+ connRef226->setDestEndpoint(dstPt226);
+ connRef226->setRoutingType((ConnType)2);
+
+ ConnRef *connRef227 = new ConnRef(router, 227);
+ ConnEnd srcPt227(Point(137.924, -15.1578), 15);
+ connRef227->setSourceEndpoint(srcPt227);
+ ConnEnd dstPt227(Point(137.924, 34.8422), 15);
+ connRef227->setDestEndpoint(dstPt227);
+ connRef227->setRoutingType((ConnType)2);
+
+ ConnRef *connRef228 = new ConnRef(router, 228);
+ ConnEnd srcPt228(Point(137.924, 111.557), 15);
+ connRef228->setSourceEndpoint(srcPt228);
+ ConnEnd dstPt228(Point(137.924, 161.557), 15);
+ connRef228->setDestEndpoint(dstPt228);
+ connRef228->setRoutingType((ConnType)2);
+
+ ConnRef *connRef229 = new ConnRef(router, 229);
+ ConnEnd srcPt229(Point(257.924, 111.557), 15);
+ connRef229->setSourceEndpoint(srcPt229);
+ ConnEnd dstPt229(Point(257.924, 161.557), 15);
+ connRef229->setDestEndpoint(dstPt229);
+ connRef229->setRoutingType((ConnType)2);
+
+ ConnRef *connRef230 = new ConnRef(router, 230);
+ ConnEnd srcPt230(Point(259.924, 213.557), 15);
+ connRef230->setSourceEndpoint(srcPt230);
+ ConnEnd dstPt230(Point(197.924, 213.557), 15);
+ connRef230->setDestEndpoint(dstPt230);
+ connRef230->setRoutingType((ConnType)2);
+
+ ConnRef *connRef231 = new ConnRef(router, 231);
+ ConnEnd srcPt231(Point(257.924, 265.557), 15);
+ connRef231->setSourceEndpoint(srcPt231);
+ ConnEnd dstPt231(Point(257.924, 315.557), 15);
+ connRef231->setDestEndpoint(dstPt231);
+ connRef231->setRoutingType((ConnType)2);
+
+ ConnRef *connRef232 = new ConnRef(router, 232);
+ ConnEnd srcPt232(Point(139.924, 367.557), 15);
+ connRef232->setSourceEndpoint(srcPt232);
+ ConnEnd dstPt232(Point(77.9242, 367.557), 15);
+ connRef232->setDestEndpoint(dstPt232);
+ connRef232->setRoutingType((ConnType)2);
+
+ ConnRef *connRef233 = new ConnRef(router, 233);
+ ConnEnd srcPt233(Point(137.924, 477.557), 15);
+ connRef233->setSourceEndpoint(srcPt233);
+ ConnEnd dstPt233(Point(137.924, 527.557), 15);
+ connRef233->setDestEndpoint(dstPt233);
+ connRef233->setRoutingType((ConnType)2);
+
+ ConnRef *connRef234 = new ConnRef(router, 234);
+ ConnEnd srcPt234(Point(137.924, 569.557), 15);
+ connRef234->setSourceEndpoint(srcPt234);
+ ConnEnd dstPt234(Point(137.924, 619.557), 15);
+ connRef234->setDestEndpoint(dstPt234);
+ connRef234->setRoutingType((ConnType)2);
+
+ ConnRef *connRef235 = new ConnRef(router, 235);
+ ConnEnd srcPt235(Point(139.924, 661.557), 15);
+ connRef235->setSourceEndpoint(srcPt235);
+ ConnEnd dstPt235(Point(77.9242, 661.557), 15);
+ connRef235->setDestEndpoint(dstPt235);
+ connRef235->setRoutingType((ConnType)2);
+
+ ConnRef *connRef236 = new ConnRef(router, 236);
+ ConnEnd srcPt236(Point(137.924, 713.557), 15);
+ connRef236->setSourceEndpoint(srcPt236);
+ ConnEnd dstPt236(Point(137.924, 763.557), 15);
+ connRef236->setDestEndpoint(dstPt236);
+ connRef236->setRoutingType((ConnType)2);
+
+ ConnRef *connRef237 = new ConnRef(router, 237);
+ ConnEnd srcPt237(Point(257.924, 713.557), 15);
+ connRef237->setSourceEndpoint(srcPt237);
+ ConnEnd dstPt237(Point(257.924, 763.557), 15);
+ connRef237->setDestEndpoint(dstPt237);
+ connRef237->setRoutingType((ConnType)2);
+
+ ConnRef *connRef238 = new ConnRef(router, 238);
+ ConnEnd srcPt238(Point(377.924, 577.557), 15);
+ connRef238->setSourceEndpoint(srcPt238);
+ ConnEnd dstPt238(Point(377.924, 627.557), 15);
+ connRef238->setDestEndpoint(dstPt238);
+ connRef238->setRoutingType((ConnType)2);
+
+ ConnRef *connRef239 = new ConnRef(router, 239);
+ ConnEnd srcPt239(Point(377.924, 713.557), 15);
+ connRef239->setSourceEndpoint(srcPt239);
+ ConnEnd dstPt239(Point(377.924, 763.557), 15);
+ connRef239->setDestEndpoint(dstPt239);
+ connRef239->setRoutingType((ConnType)2);
+
+ ConnRef *connRef240 = new ConnRef(router, 240);
+ ConnEnd srcPt240(Point(497.924, 713.557), 15);
+ connRef240->setSourceEndpoint(srcPt240);
+ ConnEnd dstPt240(Point(497.924, 763.557), 15);
+ connRef240->setDestEndpoint(dstPt240);
+ connRef240->setRoutingType((ConnType)2);
+
+ ConnRef *connRef241 = new ConnRef(router, 241);
+ ConnEnd srcPt241(Point(617.924, 713.557), 15);
+ connRef241->setSourceEndpoint(srcPt241);
+ ConnEnd dstPt241(Point(617.924, 763.557), 15);
+ connRef241->setDestEndpoint(dstPt241);
+ connRef241->setRoutingType((ConnType)2);
+
+ ConnRef *connRef242 = new ConnRef(router, 242);
+ ConnEnd srcPt242(Point(497.924, 853.057), 15);
+ connRef242->setSourceEndpoint(srcPt242);
+ ConnEnd dstPt242(Point(497.924, 903.057), 15);
+ connRef242->setDestEndpoint(dstPt242);
+ connRef242->setRoutingType((ConnType)2);
+
+ ConnRef *connRef243 = new ConnRef(router, 243);
+ ConnEnd srcPt243(Point(617.924, 853.057), 15);
+ connRef243->setSourceEndpoint(srcPt243);
+ ConnEnd dstPt243(Point(617.924, 903.057), 15);
+ connRef243->setDestEndpoint(dstPt243);
+ connRef243->setRoutingType((ConnType)2);
+
+ ConnRef *connRef244 = new ConnRef(router, 244);
+ ConnEnd srcPt244(Point(377.924, 111.557), 15);
+ connRef244->setSourceEndpoint(srcPt244);
+ ConnEnd dstPt244(Point(377.924, 161.557), 15);
+ connRef244->setDestEndpoint(dstPt244);
+ connRef244->setRoutingType((ConnType)2);
+
+ ConnRef *connRef245 = new ConnRef(router, 245);
+ ConnEnd srcPt245(Point(377.924, -22.6578), 15);
+ connRef245->setSourceEndpoint(srcPt245);
+ ConnEnd dstPt245(Point(377.924, 27.3422), 15);
+ connRef245->setDestEndpoint(dstPt245);
+ connRef245->setRoutingType((ConnType)2);
+
+ ConnRef *connRef246 = new ConnRef(router, 246);
+ ConnEnd srcPt246(Point(497.924, -4.15778), 15);
+ connRef246->setSourceEndpoint(srcPt246);
+ ConnEnd dstPt246(Point(497.924, 45.8422), 15);
+ connRef246->setDestEndpoint(dstPt246);
+ connRef246->setRoutingType((ConnType)2);
+
+ ConnRef *connRef247 = new ConnRef(router, 247);
+ ConnEnd srcPt247(Point(617.924, -4.15778), 15);
+ connRef247->setSourceEndpoint(srcPt247);
+ ConnEnd dstPt247(Point(617.924, 45.8422), 15);
+ connRef247->setDestEndpoint(dstPt247);
+ connRef247->setRoutingType((ConnType)2);
+
+ ConnRef *connRef170 = new ConnRef(router, 170);
+ ConnEnd srcPt170(Point(1018.92, 161.557), 15);
+ connRef170->setSourceEndpoint(srcPt170);
+ ConnEnd dstPt170(Point(1068.92, 152.342), 15);
+ connRef170->setDestEndpoint(dstPt170);
+ connRef170->setRoutingType((ConnType)2);
+
+ ConnRef *connRef171 = new ConnRef(router, 171);
+ ConnEnd srcPt171(Point(1018.92, 161.557), 15);
+ connRef171->setSourceEndpoint(srcPt171);
+ ConnEnd dstPt171(Point(1068.92, 60.3422), 15);
+ connRef171->setDestEndpoint(dstPt171);
+ connRef171->setRoutingType((ConnType)2);
+
+ ConnRef *connRef172 = new ConnRef(router, 172);
+ ConnEnd srcPt172(Point(267.924, 315.557), 15);
+ connRef172->setSourceEndpoint(srcPt172);
+ ConnEnd dstPt172(Point(437.924, 161.557), 15);
+ connRef172->setDestEndpoint(dstPt172);
+ connRef172->setRoutingType((ConnType)2);
+
+ ConnRef *connRef173 = new ConnRef(router, 173);
+ ConnEnd srcPt173(Point(437.924, 161.557), 15);
+ connRef173->setSourceEndpoint(srcPt173);
+ ConnEnd dstPt173(Point(487.924, 45.8422), 15);
+ connRef173->setDestEndpoint(dstPt173);
+ connRef173->setRoutingType((ConnType)2);
+
+ ConnRef *connRef174 = new ConnRef(router, 174);
+ ConnEnd srcPt174(Point(437.924, 161.557), 15);
+ connRef174->setSourceEndpoint(srcPt174);
+ ConnEnd dstPt174(Point(727.924, 161.557), 15);
+ connRef174->setDestEndpoint(dstPt174);
+ connRef174->setRoutingType((ConnType)2);
+
+ ConnRef *connRef175 = new ConnRef(router, 175);
+ ConnEnd srcPt175(Point(77.9242, 161.557), 15);
+ connRef175->setSourceEndpoint(srcPt175);
+ ConnEnd dstPt175(Point(127.924, 161.557), 15);
+ connRef175->setDestEndpoint(dstPt175);
+ connRef175->setRoutingType((ConnType)2);
+
+ ConnRef *connRef176 = new ConnRef(router, 176);
+ ConnEnd srcPt176(Point(77.9242, 161.557), 15);
+ connRef176->setSourceEndpoint(srcPt176);
+ ConnEnd dstPt176(Point(77.9242, 357.557), 15);
+ connRef176->setDestEndpoint(dstPt176);
+ connRef176->setRoutingType((ConnType)2);
+
+ ConnRef *connRef177 = new ConnRef(router, 177);
+ ConnEnd srcPt177(Point(557.924, 763.557), 15);
+ connRef177->setSourceEndpoint(srcPt177);
+ ConnEnd dstPt177(Point(607.924, 763.557), 15);
+ connRef177->setDestEndpoint(dstPt177);
+ connRef177->setRoutingType((ConnType)2);
+
+ ConnRef *connRef178 = new ConnRef(router, 178);
+ ConnEnd srcPt178(Point(77.9242, 527.557), 15);
+ connRef178->setSourceEndpoint(srcPt178);
+ ConnEnd dstPt178(Point(127.924, 527.557), 15);
+ connRef178->setDestEndpoint(dstPt178);
+ connRef178->setRoutingType((ConnType)2);
+
+ ConnRef *connRef179 = new ConnRef(router, 179);
+ ConnEnd srcPt179(Point(557.924, 54.8422), 15);
+ connRef179->setSourceEndpoint(srcPt179);
+ ConnEnd dstPt179(Point(607.924, 45.8422), 15);
+ connRef179->setDestEndpoint(dstPt179);
+ connRef179->setRoutingType((ConnType)2);
+
+ ConnRef *connRef180 = new ConnRef(router, 180);
+ ConnEnd srcPt180(Point(557.924, 435.557), 15);
+ connRef180->setSourceEndpoint(srcPt180);
+ ConnEnd dstPt180(Point(607.924, 435.557), 15);
+ connRef180->setDestEndpoint(dstPt180);
+ connRef180->setRoutingType((ConnType)2);
+
+ ConnRef *connRef181 = new ConnRef(router, 181);
+ ConnEnd srcPt181(Point(77.9242, 763.557), 15);
+ connRef181->setSourceEndpoint(srcPt181);
+ ConnEnd dstPt181(Point(77.9242, 671.557), 15);
+ connRef181->setDestEndpoint(dstPt181);
+ connRef181->setRoutingType((ConnType)2);
+
+ ConnRef *connRef182 = new ConnRef(router, 182);
+ ConnEnd srcPt182(Point(77.9242, 763.557), 15);
+ connRef182->setSourceEndpoint(srcPt182);
+ ConnEnd dstPt182(Point(127.924, 763.557), 15);
+ connRef182->setDestEndpoint(dstPt182);
+ connRef182->setRoutingType((ConnType)2);
+
+ ConnRef *connRef183 = new ConnRef(router, 183);
+ ConnEnd srcPt183(Point(197.924, 315.557), 15);
+ connRef183->setSourceEndpoint(srcPt183);
+ ConnEnd dstPt183(Point(247.924, 315.557), 15);
+ connRef183->setDestEndpoint(dstPt183);
+ connRef183->setRoutingType((ConnType)2);
+
+ ConnRef *connRef184 = new ConnRef(router, 184);
+ ConnEnd srcPt184(Point(677.924, 343.557), 15);
+ connRef184->setSourceEndpoint(srcPt184);
+ ConnEnd dstPt184(Point(727.924, 343.557), 15);
+ connRef184->setDestEndpoint(dstPt184);
+ connRef184->setRoutingType((ConnType)2);
+
+ ConnRef *connRef185 = new ConnRef(router, 185);
+ ConnEnd srcPt185(Point(797.924, 161.557), 15);
+ connRef185->setSourceEndpoint(srcPt185);
+ ConnEnd dstPt185(Point(847.924, 161.557), 15);
+ connRef185->setDestEndpoint(dstPt185);
+ connRef185->setRoutingType((ConnType)2);
+
+ ConnRef *connRef186 = new ConnRef(router, 186);
+ ConnEnd srcPt186(Point(77.9242, 34.8422), 15);
+ connRef186->setSourceEndpoint(srcPt186);
+ ConnEnd dstPt186(Point(127.924, 34.8422), 15);
+ connRef186->setDestEndpoint(dstPt186);
+ connRef186->setRoutingType((ConnType)2);
+
+ ConnRef *connRef187 = new ConnRef(router, 187);
+ ConnEnd srcPt187(Point(437.924, 527.557), 15);
+ connRef187->setSourceEndpoint(srcPt187);
+ ConnEnd dstPt187(Point(487.924, 527.557), 15);
+ connRef187->setDestEndpoint(dstPt187);
+ connRef187->setRoutingType((ConnType)2);
+
+ ConnRef *connRef188 = new ConnRef(router, 188);
+ ConnEnd srcPt188(Point(77.9242, 619.557), 15);
+ connRef188->setSourceEndpoint(srcPt188);
+ ConnEnd dstPt188(Point(127.924, 619.557), 15);
+ connRef188->setDestEndpoint(dstPt188);
+ connRef188->setRoutingType((ConnType)2);
+
+ ConnRef *connRef189 = new ConnRef(router, 189);
+ ConnEnd srcPt189(Point(747.924, -60.6578), 15);
+ connRef189->setSourceEndpoint(srcPt189);
+ ConnEnd dstPt189(Point(797.924, -60.6578), 15);
+ connRef189->setDestEndpoint(dstPt189);
+ connRef189->setRoutingType((ConnType)2);
+
+ ConnRef *connRef190 = new ConnRef(router, 190);
+ ConnEnd srcPt190(Point(147.924, 34.8422), 15);
+ connRef190->setSourceEndpoint(srcPt190);
+ ConnEnd dstPt190(Point(197.924, 161.557), 15);
+ connRef190->setDestEndpoint(dstPt190);
+ connRef190->setRoutingType((ConnType)2);
+
+ ConnRef *connRef191 = new ConnRef(router, 191);
+ ConnEnd srcPt191(Point(267.924, 161.557), 15);
+ connRef191->setSourceEndpoint(srcPt191);
+ ConnEnd dstPt191(Point(317.924, 161.557), 15);
+ connRef191->setDestEndpoint(dstPt191);
+ connRef191->setRoutingType((ConnType)2);
+
+ ConnRef *connRef192 = new ConnRef(router, 192);
+ ConnEnd srcPt192(Point(197.924, 223.557), 15);
+ connRef192->setSourceEndpoint(srcPt192);
+ ConnEnd dstPt192(Point(197.924, 315.557), 15);
+ connRef192->setDestEndpoint(dstPt192);
+ connRef192->setRoutingType((ConnType)2);
+
+ ConnRef *connRef193 = new ConnRef(router, 193);
+ ConnEnd srcPt193(Point(77.9242, 377.557), 15);
+ connRef193->setSourceEndpoint(srcPt193);
+ ConnEnd dstPt193(Point(77.9242, 527.557), 15);
+ connRef193->setDestEndpoint(dstPt193);
+ connRef193->setRoutingType((ConnType)2);
+
+ ConnRef *connRef194 = new ConnRef(router, 194);
+ ConnEnd srcPt194(Point(147.924, 527.557), 15);
+ connRef194->setSourceEndpoint(srcPt194);
+ ConnEnd dstPt194(Point(197.924, 527.557), 15);
+ connRef194->setDestEndpoint(dstPt194);
+ connRef194->setRoutingType((ConnType)2);
+
+ ConnRef *connRef195 = new ConnRef(router, 195);
+ ConnEnd srcPt195(Point(147.924, 619.557), 15);
+ connRef195->setSourceEndpoint(srcPt195);
+ ConnEnd dstPt195(Point(197.924, 763.557), 15);
+ connRef195->setDestEndpoint(dstPt195);
+ connRef195->setRoutingType((ConnType)2);
+
+ ConnRef *connRef196 = new ConnRef(router, 196);
+ ConnEnd srcPt196(Point(77.9242, 651.557), 15);
+ connRef196->setSourceEndpoint(srcPt196);
+ ConnEnd dstPt196(Point(77.9242, 619.557), 15);
+ connRef196->setDestEndpoint(dstPt196);
+ connRef196->setRoutingType((ConnType)2);
+
+ ConnRef *connRef197 = new ConnRef(router, 197);
+ ConnEnd srcPt197(Point(147.924, 763.557), 15);
+ connRef197->setSourceEndpoint(srcPt197);
+ ConnEnd dstPt197(Point(197.924, 763.557), 15);
+ connRef197->setDestEndpoint(dstPt197);
+ connRef197->setRoutingType((ConnType)2);
+
+ ConnRef *connRef198 = new ConnRef(router, 198);
+ ConnEnd srcPt198(Point(267.924, 763.557), 15);
+ connRef198->setSourceEndpoint(srcPt198);
+ ConnEnd dstPt198(Point(317.924, 763.557), 15);
+ connRef198->setDestEndpoint(dstPt198);
+ connRef198->setRoutingType((ConnType)2);
+
+ ConnRef *connRef199 = new ConnRef(router, 199);
+ ConnEnd srcPt199(Point(387.924, 627.557), 15);
+ connRef199->setSourceEndpoint(srcPt199);
+ ConnEnd dstPt199(Point(437.924, 627.557), 15);
+ connRef199->setDestEndpoint(dstPt199);
+ connRef199->setRoutingType((ConnType)2);
+
+ ConnRef *connRef200 = new ConnRef(router, 200);
+ ConnEnd srcPt200(Point(387.924, 763.557), 15);
+ connRef200->setSourceEndpoint(srcPt200);
+ ConnEnd dstPt200(Point(437.924, 763.557), 15);
+ connRef200->setDestEndpoint(dstPt200);
+ connRef200->setRoutingType((ConnType)2);
+
+ ConnRef *connRef201 = new ConnRef(router, 201);
+ ConnEnd srcPt201(Point(507.924, 763.557), 15);
+ connRef201->setSourceEndpoint(srcPt201);
+ ConnEnd dstPt201(Point(557.924, 763.557), 15);
+ connRef201->setDestEndpoint(dstPt201);
+ connRef201->setRoutingType((ConnType)2);
+
+ ConnRef *connRef202 = new ConnRef(router, 202);
+ ConnEnd srcPt202(Point(627.924, 763.557), 15);
+ connRef202->setSourceEndpoint(srcPt202);
+ ConnEnd dstPt202(Point(677.924, 763.557), 15);
+ connRef202->setDestEndpoint(dstPt202);
+ connRef202->setRoutingType((ConnType)2);
+
+ ConnRef *connRef203 = new ConnRef(router, 203);
+ ConnEnd srcPt203(Point(507.924, 903.057), 15);
+ connRef203->setSourceEndpoint(srcPt203);
+ ConnEnd dstPt203(Point(557.924, 903.057), 15);
+ connRef203->setDestEndpoint(dstPt203);
+ connRef203->setRoutingType((ConnType)2);
+
+ ConnRef *connRef204 = new ConnRef(router, 204);
+ ConnEnd srcPt204(Point(627.924, 903.057), 15);
+ connRef204->setSourceEndpoint(srcPt204);
+ ConnEnd dstPt204(Point(677.924, 903.057), 15);
+ connRef204->setDestEndpoint(dstPt204);
+ connRef204->setRoutingType((ConnType)2);
+
+ ConnRef *connRef205 = new ConnRef(router, 205);
+ ConnEnd srcPt205(Point(387.924, 161.557), 15);
+ connRef205->setSourceEndpoint(srcPt205);
+ ConnEnd dstPt205(Point(437.924, 161.557), 15);
+ connRef205->setDestEndpoint(dstPt205);
+ connRef205->setRoutingType((ConnType)2);
+
+ ConnRef *connRef206 = new ConnRef(router, 206);
+ ConnEnd srcPt206(Point(387.924, 27.3422), 15);
+ connRef206->setSourceEndpoint(srcPt206);
+ ConnEnd dstPt206(Point(437.924, 27.3422), 15);
+ connRef206->setDestEndpoint(dstPt206);
+ connRef206->setRoutingType((ConnType)2);
+
+ ConnRef *connRef207 = new ConnRef(router, 207);
+ ConnEnd srcPt207(Point(507.924, 45.8422), 15);
+ connRef207->setSourceEndpoint(srcPt207);
+ ConnEnd dstPt207(Point(557.924, 54.8422), 15);
+ connRef207->setDestEndpoint(dstPt207);
+ connRef207->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/lineSegWrapperCrash1");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash2.cpp b/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash2.cpp
new file mode 100644
index 0000000..f2ee8d4
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash2.cpp
@@ -0,0 +1,1884 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 0);
+
+ Polygon poly95(4);
+ poly95.ps[0] = Point(867.924, 151.557);
+ poly95.ps[1] = Point(867.924, 171.557);
+ poly95.ps[2] = Point(847.924, 171.557);
+ poly95.ps[3] = Point(847.924, 151.557);
+ new ShapeRef(router, poly95, 95);
+
+ Polygon poly96(4);
+ poly96.ps[0] = Point(747.924, 333.557);
+ poly96.ps[1] = Point(747.924, 353.557);
+ poly96.ps[2] = Point(727.924, 353.557);
+ poly96.ps[3] = Point(727.924, 333.557);
+ new ShapeRef(router, poly96, 96);
+
+ Polygon poly97(4);
+ poly97.ps[0] = Point(1088.92, 378.557);
+ poly97.ps[1] = Point(1088.92, 398.557);
+ poly97.ps[2] = Point(1068.92, 398.557);
+ poly97.ps[3] = Point(1068.92, 378.557);
+ new ShapeRef(router, poly97, 97);
+
+ Polygon poly98(4);
+ poly98.ps[0] = Point(1208.92, 378.557);
+ poly98.ps[1] = Point(1208.92, 398.557);
+ poly98.ps[2] = Point(1188.92, 398.557);
+ poly98.ps[3] = Point(1188.92, 378.557);
+ new ShapeRef(router, poly98, 98);
+
+ Polygon poly99(4);
+ poly99.ps[0] = Point(1088.92, 142.342);
+ poly99.ps[1] = Point(1088.92, 162.342);
+ poly99.ps[2] = Point(1068.92, 162.342);
+ poly99.ps[3] = Point(1068.92, 142.342);
+ new ShapeRef(router, poly99, 99);
+
+ Polygon poly100(4);
+ poly100.ps[0] = Point(1088.92, 50.3422);
+ poly100.ps[1] = Point(1088.92, 70.3422);
+ poly100.ps[2] = Point(1068.92, 70.3422);
+ poly100.ps[3] = Point(1068.92, 50.3422);
+ new ShapeRef(router, poly100, 100);
+
+ Polygon poly101(4);
+ poly101.ps[0] = Point(1208.92, 142.342);
+ poly101.ps[1] = Point(1208.92, 162.342);
+ poly101.ps[2] = Point(1188.92, 162.342);
+ poly101.ps[3] = Point(1188.92, 142.342);
+ new ShapeRef(router, poly101, 101);
+
+ Polygon poly73(4);
+ poly73.ps[0] = Point(147.924, 517.557);
+ poly73.ps[1] = Point(147.924, 537.557);
+ poly73.ps[2] = Point(127.924, 537.557);
+ poly73.ps[3] = Point(127.924, 517.557);
+ new ShapeRef(router, poly73, 73);
+
+ Polygon poly75(4);
+ poly75.ps[0] = Point(87.9242, 651.557);
+ poly75.ps[1] = Point(87.9242, 671.557);
+ poly75.ps[2] = Point(67.9242, 671.557);
+ poly75.ps[3] = Point(67.9242, 651.557);
+ new ShapeRef(router, poly75, 75);
+
+ Polygon poly85(4);
+ poly85.ps[0] = Point(387.924, 17.3422);
+ poly85.ps[1] = Point(387.924, 37.3422);
+ poly85.ps[2] = Point(367.924, 37.3422);
+ poly85.ps[3] = Point(367.924, 17.3422);
+ new ShapeRef(router, poly85, 85);
+
+ Polygon poly86(4);
+ poly86.ps[0] = Point(507.924, 35.8422);
+ poly86.ps[1] = Point(507.924, 55.8422);
+ poly86.ps[2] = Point(487.924, 55.8422);
+ poly86.ps[3] = Point(487.924, 35.8422);
+ new ShapeRef(router, poly86, 86);
+
+ Polygon poly87(4);
+ poly87.ps[0] = Point(627.924, 35.8422);
+ poly87.ps[1] = Point(627.924, 55.8422);
+ poly87.ps[2] = Point(607.924, 55.8422);
+ poly87.ps[3] = Point(607.924, 35.8422);
+ new ShapeRef(router, poly87, 87);
+
+ Polygon poly88(4);
+ poly88.ps[0] = Point(747.924, 564.057);
+ poly88.ps[1] = Point(747.924, 584.057);
+ poly88.ps[2] = Point(727.924, 584.057);
+ poly88.ps[3] = Point(727.924, 564.057);
+ new ShapeRef(router, poly88, 88);
+
+ Polygon poly24(4);
+ poly24.ps[0] = Point(457.924, 743.557);
+ poly24.ps[1] = Point(457.924, 783.557);
+ poly24.ps[2] = Point(417.924, 783.557);
+ poly24.ps[3] = Point(417.924, 743.557);
+ new ShapeRef(router, poly24, 24);
+
+ Polygon poly42(4);
+ poly42.ps[0] = Point(697.924, 415.557);
+ poly42.ps[1] = Point(697.924, 455.557);
+ poly42.ps[2] = Point(657.924, 455.557);
+ poly42.ps[3] = Point(657.924, 415.557);
+ new ShapeRef(router, poly42, 42);
+
+ Polygon poly23(4);
+ poly23.ps[0] = Point(337.924, 141.557);
+ poly23.ps[1] = Point(337.924, 181.557);
+ poly23.ps[2] = Point(297.924, 181.557);
+ poly23.ps[3] = Point(297.924, 141.557);
+ new ShapeRef(router, poly23, 23);
+
+ Polygon poly54(4);
+ poly54.ps[0] = Point(697.924, 323.557);
+ poly54.ps[1] = Point(697.924, 363.557);
+ poly54.ps[2] = Point(657.924, 363.557);
+ poly54.ps[3] = Point(657.924, 323.557);
+ new ShapeRef(router, poly54, 54);
+
+ Polygon poly19(4);
+ poly19.ps[0] = Point(217.924, 141.557);
+ poly19.ps[1] = Point(217.924, 181.557);
+ poly19.ps[2] = Point(177.924, 181.557);
+ poly19.ps[3] = Point(177.924, 141.557);
+ new ShapeRef(router, poly19, 19);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(1158.92, -80.6578);
+ poly8.ps[1] = Point(1158.92, -40.6578);
+ poly8.ps[2] = Point(1118.92, -40.6578);
+ poly8.ps[3] = Point(1118.92, -80.6578);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly25(4);
+ poly25.ps[0] = Point(697.924, 883.057);
+ poly25.ps[1] = Point(697.924, 923.057);
+ poly25.ps[2] = Point(657.924, 923.057);
+ poly25.ps[3] = Point(657.924, 883.057);
+ new ShapeRef(router, poly25, 25);
+
+ Polygon poly18(4);
+ poly18.ps[0] = Point(217.924, 743.557);
+ poly18.ps[1] = Point(217.924, 783.557);
+ poly18.ps[2] = Point(177.924, 783.557);
+ poly18.ps[3] = Point(177.924, 743.557);
+ new ShapeRef(router, poly18, 18);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(1278.92, -22.1578);
+ poly3.ps[1] = Point(1278.92, 17.8422);
+ poly3.ps[2] = Point(1238.92, 17.8422);
+ poly3.ps[3] = Point(1238.92, -22.1578);
+ new ShapeRef(router, poly3, 3);
+
+ Polygon poly30(4);
+ poly30.ps[0] = Point(1278.92, 415.557);
+ poly30.ps[1] = Point(1278.92, 455.557);
+ poly30.ps[2] = Point(1238.92, 455.557);
+ poly30.ps[3] = Point(1238.92, 415.557);
+ new ShapeRef(router, poly30, 30);
+
+ Polygon poly58(4);
+ poly58.ps[0] = Point(97.9242, 14.8422);
+ poly58.ps[1] = Point(97.9242, 54.8422);
+ poly58.ps[2] = Point(57.9242, 54.8422);
+ poly58.ps[3] = Point(57.9242, 14.8422);
+ new ShapeRef(router, poly58, 58);
+
+ Polygon poly47(4);
+ poly47.ps[0] = Point(697.924, 271.557);
+ poly47.ps[1] = Point(697.924, 311.557);
+ poly47.ps[2] = Point(657.924, 311.557);
+ poly47.ps[3] = Point(657.924, 271.557);
+ new ShapeRef(router, poly47, 47);
+
+ Polygon poly61(4);
+ poly61.ps[0] = Point(577.924, -44.6578);
+ poly61.ps[1] = Point(577.924, -4.65778);
+ poly61.ps[2] = Point(537.924, -4.65778);
+ poly61.ps[3] = Point(537.924, -44.6578);
+ new ShapeRef(router, poly61, 61);
+
+ Polygon poly49(4);
+ poly49.ps[0] = Point(45.9242, 169.75);
+ poly49.ps[1] = Point(45.9242, 334.75);
+ poly49.ps[2] = Point(-242.076, 334.75);
+ poly49.ps[3] = Point(-242.076, 169.75);
+ new ShapeRef(router, poly49, 49);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(577.924, 795.557);
+ poly2.ps[1] = Point(577.924, 835.557);
+ poly2.ps[2] = Point(537.924, 835.557);
+ poly2.ps[3] = Point(537.924, 795.557);
+ new ShapeRef(router, poly2, 2);
+
+ Polygon poly66(4);
+ poly66.ps[0] = Point(747.924, -70.6578);
+ poly66.ps[1] = Point(747.924, -50.6578);
+ poly66.ps[2] = Point(727.924, -50.6578);
+ poly66.ps[3] = Point(727.924, -70.6578);
+ new ShapeRef(router, poly66, 66);
+
+ Polygon poly1(4);
+ poly1.ps[0] = Point(817.924, 840.057);
+ poly1.ps[1] = Point(817.924, 880.057);
+ poly1.ps[2] = Point(777.924, 880.057);
+ poly1.ps[3] = Point(777.924, 840.057);
+ new ShapeRef(router, poly1, 1);
+
+ Polygon poly60(4);
+ poly60.ps[0] = Point(937.924, 1.84222);
+ poly60.ps[1] = Point(937.924, 41.8422);
+ poly60.ps[2] = Point(897.924, 41.8422);
+ poly60.ps[3] = Point(897.924, 1.84222);
+ new ShapeRef(router, poly60, 60);
+
+ Polygon poly89(4);
+ poly89.ps[0] = Point(507.924, 517.557);
+ poly89.ps[1] = Point(507.924, 537.557);
+ poly89.ps[2] = Point(487.924, 537.557);
+ poly89.ps[3] = Point(487.924, 517.557);
+ new ShapeRef(router, poly89, 89);
+
+ Polygon poly90(4);
+ poly90.ps[0] = Point(507.924, 425.557);
+ poly90.ps[1] = Point(507.924, 445.557);
+ poly90.ps[2] = Point(487.924, 445.557);
+ poly90.ps[3] = Point(487.924, 425.557);
+ new ShapeRef(router, poly90, 90);
+
+ Polygon poly91(4);
+ poly91.ps[0] = Point(627.924, 517.557);
+ poly91.ps[1] = Point(627.924, 537.557);
+ poly91.ps[2] = Point(607.924, 537.557);
+ poly91.ps[3] = Point(607.924, 517.557);
+ new ShapeRef(router, poly91, 91);
+
+ Polygon poly92(4);
+ poly92.ps[0] = Point(627.924, 425.557);
+ poly92.ps[1] = Point(627.924, 445.557);
+ poly92.ps[2] = Point(607.924, 445.557);
+ poly92.ps[3] = Point(607.924, 425.557);
+ new ShapeRef(router, poly92, 92);
+
+ Polygon poly93(4);
+ poly93.ps[0] = Point(867.924, 333.557);
+ poly93.ps[1] = Point(867.924, 353.557);
+ poly93.ps[2] = Point(847.924, 353.557);
+ poly93.ps[3] = Point(847.924, 333.557);
+ new ShapeRef(router, poly93, 93);
+
+ Polygon poly94(4);
+ poly94.ps[0] = Point(867.924, 425.557);
+ poly94.ps[1] = Point(867.924, 445.557);
+ poly94.ps[2] = Point(847.924, 445.557);
+ poly94.ps[3] = Point(847.924, 425.557);
+ new ShapeRef(router, poly94, 94);
+
+ Polygon poly59(4);
+ poly59.ps[0] = Point(937.924, 323.557);
+ poly59.ps[1] = Point(937.924, 363.557);
+ poly59.ps[2] = Point(897.924, 363.557);
+ poly59.ps[3] = Point(897.924, 323.557);
+ new ShapeRef(router, poly59, 59);
+
+ Polygon poly116(4);
+ poly116.ps[0] = Point(165.924, 693.557);
+ poly116.ps[1] = Point(165.924, 733.557);
+ poly116.ps[2] = Point(109.924, 733.557);
+ poly116.ps[3] = Point(109.924, 693.557);
+ new ShapeRef(router, poly116, 116);
+
+ Polygon poly117(4);
+ poly117.ps[0] = Point(285.924, 693.557);
+ poly117.ps[1] = Point(285.924, 733.557);
+ poly117.ps[2] = Point(229.924, 733.557);
+ poly117.ps[3] = Point(229.924, 693.557);
+ new ShapeRef(router, poly117, 117);
+
+ Polygon poly118(4);
+ poly118.ps[0] = Point(405.924, 557.557);
+ poly118.ps[1] = Point(405.924, 597.557);
+ poly118.ps[2] = Point(349.924, 597.557);
+ poly118.ps[3] = Point(349.924, 557.557);
+ new ShapeRef(router, poly118, 118);
+
+ Polygon poly119(4);
+ poly119.ps[0] = Point(405.924, 693.557);
+ poly119.ps[1] = Point(405.924, 733.557);
+ poly119.ps[2] = Point(349.924, 733.557);
+ poly119.ps[3] = Point(349.924, 693.557);
+ new ShapeRef(router, poly119, 119);
+
+ Polygon poly120(4);
+ poly120.ps[0] = Point(525.924, 693.557);
+ poly120.ps[1] = Point(525.924, 733.557);
+ poly120.ps[2] = Point(469.924, 733.557);
+ poly120.ps[3] = Point(469.924, 693.557);
+ new ShapeRef(router, poly120, 120);
+
+ Polygon poly121(4);
+ poly121.ps[0] = Point(645.924, 693.557);
+ poly121.ps[1] = Point(645.924, 733.557);
+ poly121.ps[2] = Point(589.924, 733.557);
+ poly121.ps[3] = Point(589.924, 693.557);
+ new ShapeRef(router, poly121, 121);
+
+ Polygon poly122(4);
+ poly122.ps[0] = Point(525.924, 833.057);
+ poly122.ps[1] = Point(525.924, 873.057);
+ poly122.ps[2] = Point(469.924, 873.057);
+ poly122.ps[3] = Point(469.924, 833.057);
+ new ShapeRef(router, poly122, 122);
+
+ Polygon poly123(4);
+ poly123.ps[0] = Point(645.924, 833.057);
+ poly123.ps[1] = Point(645.924, 873.057);
+ poly123.ps[2] = Point(589.924, 873.057);
+ poly123.ps[3] = Point(589.924, 833.057);
+ new ShapeRef(router, poly123, 123);
+
+ Polygon poly124(4);
+ poly124.ps[0] = Point(405.924, 91.5565);
+ poly124.ps[1] = Point(405.924, 131.557);
+ poly124.ps[2] = Point(349.924, 131.557);
+ poly124.ps[3] = Point(349.924, 91.5565);
+ new ShapeRef(router, poly124, 124);
+
+ Polygon poly125(4);
+ poly125.ps[0] = Point(405.924, -42.6578);
+ poly125.ps[1] = Point(405.924, -2.65778);
+ poly125.ps[2] = Point(349.924, -2.65778);
+ poly125.ps[3] = Point(349.924, -42.6578);
+ new ShapeRef(router, poly125, 125);
+
+ Polygon poly126(4);
+ poly126.ps[0] = Point(525.924, -24.1578);
+ poly126.ps[1] = Point(525.924, 15.8422);
+ poly126.ps[2] = Point(469.924, 15.8422);
+ poly126.ps[3] = Point(469.924, -24.1578);
+ new ShapeRef(router, poly126, 126);
+
+ Polygon poly127(4);
+ poly127.ps[0] = Point(645.924, -24.1578);
+ poly127.ps[1] = Point(645.924, 15.8422);
+ poly127.ps[2] = Point(589.924, 15.8422);
+ poly127.ps[3] = Point(589.924, -24.1578);
+ new ShapeRef(router, poly127, 127);
+
+ Polygon poly128(4);
+ poly128.ps[0] = Point(765.924, 504.057);
+ poly128.ps[1] = Point(765.924, 544.057);
+ poly128.ps[2] = Point(709.924, 544.057);
+ poly128.ps[3] = Point(709.924, 504.057);
+ new ShapeRef(router, poly128, 128);
+
+ Polygon poly129(4);
+ poly129.ps[0] = Point(525.924, 457.557);
+ poly129.ps[1] = Point(525.924, 497.557);
+ poly129.ps[2] = Point(469.924, 497.557);
+ poly129.ps[3] = Point(469.924, 457.557);
+ new ShapeRef(router, poly129, 129);
+
+ Polygon poly37(4);
+ poly37.ps[0] = Point(457.924, 607.557);
+ poly37.ps[1] = Point(457.924, 647.557);
+ poly37.ps[2] = Point(417.924, 647.557);
+ poly37.ps[3] = Point(417.924, 607.557);
+ new ShapeRef(router, poly37, 37);
+
+ Polygon poly36(4);
+ poly36.ps[0] = Point(697.924, 507.557);
+ poly36.ps[1] = Point(697.924, 547.557);
+ poly36.ps[2] = Point(657.924, 547.557);
+ poly36.ps[3] = Point(657.924, 507.557);
+ new ShapeRef(router, poly36, 36);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(1038.92, -80.6578);
+ poly9.ps[1] = Point(1038.92, -40.6578);
+ poly9.ps[2] = Point(998.924, -40.6578);
+ poly9.ps[3] = Point(998.924, -80.6578);
+ new ShapeRef(router, poly9, 9);
+
+ Polygon poly52(4);
+ poly52.ps[0] = Point(217.924, 295.557);
+ poly52.ps[1] = Point(217.924, 335.557);
+ poly52.ps[2] = Point(177.924, 335.557);
+ poly52.ps[3] = Point(177.924, 295.557);
+ new ShapeRef(router, poly52, 52);
+
+ Polygon poly82(4);
+ poly82.ps[0] = Point(507.924, 893.057);
+ poly82.ps[1] = Point(507.924, 913.057);
+ poly82.ps[2] = Point(487.924, 913.057);
+ poly82.ps[3] = Point(487.924, 893.057);
+ new ShapeRef(router, poly82, 82);
+
+ Polygon poly83(4);
+ poly83.ps[0] = Point(627.924, 893.057);
+ poly83.ps[1] = Point(627.924, 913.057);
+ poly83.ps[2] = Point(607.924, 913.057);
+ poly83.ps[3] = Point(607.924, 893.057);
+ new ShapeRef(router, poly83, 83);
+
+ Polygon poly84(4);
+ poly84.ps[0] = Point(387.924, 151.557);
+ poly84.ps[1] = Point(387.924, 171.557);
+ poly84.ps[2] = Point(367.924, 171.557);
+ poly84.ps[3] = Point(367.924, 151.557);
+ new ShapeRef(router, poly84, 84);
+
+ Polygon poly79(4);
+ poly79.ps[0] = Point(387.924, 753.557);
+ poly79.ps[1] = Point(387.924, 773.557);
+ poly79.ps[2] = Point(367.924, 773.557);
+ poly79.ps[3] = Point(367.924, 753.557);
+ new ShapeRef(router, poly79, 79);
+
+ Polygon poly80(4);
+ poly80.ps[0] = Point(507.924, 753.557);
+ poly80.ps[1] = Point(507.924, 773.557);
+ poly80.ps[2] = Point(487.924, 773.557);
+ poly80.ps[3] = Point(487.924, 753.557);
+ new ShapeRef(router, poly80, 80);
+
+ Polygon poly81(4);
+ poly81.ps[0] = Point(627.924, 753.557);
+ poly81.ps[1] = Point(627.924, 773.557);
+ poly81.ps[2] = Point(607.924, 773.557);
+ poly81.ps[3] = Point(607.924, 753.557);
+ new ShapeRef(router, poly81, 81);
+
+ Polygon poly21(4);
+ poly21.ps[0] = Point(937.924, 141.557);
+ poly21.ps[1] = Point(937.924, 181.557);
+ poly21.ps[2] = Point(897.924, 181.557);
+ poly21.ps[3] = Point(897.924, 141.557);
+ new ShapeRef(router, poly21, 21);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(1278.92, -80.6578);
+ poly7.ps[1] = Point(1278.92, -40.6578);
+ poly7.ps[2] = Point(1238.92, -40.6578);
+ poly7.ps[3] = Point(1238.92, -80.6578);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly45(4);
+ poly45.ps[0] = Point(577.924, 34.8422);
+ poly45.ps[1] = Point(577.924, 74.8422);
+ poly45.ps[2] = Point(537.924, 74.8422);
+ poly45.ps[3] = Point(537.924, 34.8422);
+ new ShapeRef(router, poly45, 45);
+
+ Polygon poly76(4);
+ poly76.ps[0] = Point(147.924, 753.557);
+ poly76.ps[1] = Point(147.924, 773.557);
+ poly76.ps[2] = Point(127.924, 773.557);
+ poly76.ps[3] = Point(127.924, 753.557);
+ new ShapeRef(router, poly76, 76);
+
+ Polygon poly77(4);
+ poly77.ps[0] = Point(267.924, 753.557);
+ poly77.ps[1] = Point(267.924, 773.557);
+ poly77.ps[2] = Point(247.924, 773.557);
+ poly77.ps[3] = Point(247.924, 753.557);
+ new ShapeRef(router, poly77, 77);
+
+ Polygon poly78(4);
+ poly78.ps[0] = Point(387.924, 617.557);
+ poly78.ps[1] = Point(387.924, 637.557);
+ poly78.ps[2] = Point(367.924, 637.557);
+ poly78.ps[3] = Point(367.924, 617.557);
+ new ShapeRef(router, poly78, 78);
+
+ Polygon poly130(4);
+ poly130.ps[0] = Point(525.924, 365.557);
+ poly130.ps[1] = Point(525.924, 405.557);
+ poly130.ps[2] = Point(469.924, 405.557);
+ poly130.ps[3] = Point(469.924, 365.557);
+ new ShapeRef(router, poly130, 130);
+
+ Polygon poly131(4);
+ poly131.ps[0] = Point(645.924, 457.557);
+ poly131.ps[1] = Point(645.924, 497.557);
+ poly131.ps[2] = Point(589.924, 497.557);
+ poly131.ps[3] = Point(589.924, 457.557);
+ new ShapeRef(router, poly131, 131);
+
+ Polygon poly132(4);
+ poly132.ps[0] = Point(645.924, 365.557);
+ poly132.ps[1] = Point(645.924, 405.557);
+ poly132.ps[2] = Point(589.924, 405.557);
+ poly132.ps[3] = Point(589.924, 365.557);
+ new ShapeRef(router, poly132, 132);
+
+ Polygon poly133(4);
+ poly133.ps[0] = Point(885.924, 273.557);
+ poly133.ps[1] = Point(885.924, 313.557);
+ poly133.ps[2] = Point(829.924, 313.557);
+ poly133.ps[3] = Point(829.924, 273.557);
+ new ShapeRef(router, poly133, 133);
+
+ Polygon poly134(4);
+ poly134.ps[0] = Point(885.924, 365.557);
+ poly134.ps[1] = Point(885.924, 405.557);
+ poly134.ps[2] = Point(829.924, 405.557);
+ poly134.ps[3] = Point(829.924, 365.557);
+ new ShapeRef(router, poly134, 134);
+
+ Polygon poly135(4);
+ poly135.ps[0] = Point(885.924, 91.5565);
+ poly135.ps[1] = Point(885.924, 131.557);
+ poly135.ps[2] = Point(829.924, 131.557);
+ poly135.ps[3] = Point(829.924, 91.5565);
+ new ShapeRef(router, poly135, 135);
+
+ Polygon poly136(4);
+ poly136.ps[0] = Point(765.924, 273.557);
+ poly136.ps[1] = Point(765.924, 313.557);
+ poly136.ps[2] = Point(709.924, 313.557);
+ poly136.ps[3] = Point(709.924, 273.557);
+ new ShapeRef(router, poly136, 136);
+
+ Polygon poly137(4);
+ poly137.ps[0] = Point(1106.92, 318.557);
+ poly137.ps[1] = Point(1106.92, 358.557);
+ poly137.ps[2] = Point(1050.92, 358.557);
+ poly137.ps[3] = Point(1050.92, 318.557);
+ new ShapeRef(router, poly137, 137);
+
+ Polygon poly138(4);
+ poly138.ps[0] = Point(1226.92, 318.557);
+ poly138.ps[1] = Point(1226.92, 358.557);
+ poly138.ps[2] = Point(1170.92, 358.557);
+ poly138.ps[3] = Point(1170.92, 318.557);
+ new ShapeRef(router, poly138, 138);
+
+ Polygon poly139(4);
+ poly139.ps[0] = Point(1106.92, 82.3422);
+ poly139.ps[1] = Point(1106.92, 122.342);
+ poly139.ps[2] = Point(1050.92, 122.342);
+ poly139.ps[3] = Point(1050.92, 82.3422);
+ new ShapeRef(router, poly139, 139);
+
+ Polygon poly140(4);
+ poly140.ps[0] = Point(1106.92, -9.65778);
+ poly140.ps[1] = Point(1106.92, 30.3422);
+ poly140.ps[2] = Point(1050.92, 30.3422);
+ poly140.ps[3] = Point(1050.92, -9.65778);
+ new ShapeRef(router, poly140, 140);
+
+ Polygon poly141(4);
+ poly141.ps[0] = Point(1226.92, 82.3422);
+ poly141.ps[1] = Point(1226.92, 122.342);
+ poly141.ps[2] = Point(1170.92, 122.342);
+ poly141.ps[3] = Point(1170.92, 82.3422);
+ new ShapeRef(router, poly141, 141);
+
+ Polygon poly142(4);
+ poly142.ps[0] = Point(1106.92, -130.658);
+ poly142.ps[1] = Point(1106.92, -90.6578);
+ poly142.ps[2] = Point(1050.92, -90.6578);
+ poly142.ps[3] = Point(1050.92, -130.658);
+ new ShapeRef(router, poly142, 142);
+
+ Polygon poly143(4);
+ poly143.ps[0] = Point(986.924, 210.557);
+ poly143.ps[1] = Point(986.924, 250.557);
+ poly143.ps[2] = Point(930.924, 250.557);
+ poly143.ps[3] = Point(930.924, 210.557);
+ new ShapeRef(router, poly143, 143);
+
+ Polygon poly144(4);
+ poly144.ps[0] = Point(765.924, 91.5565);
+ poly144.ps[1] = Point(765.924, 131.557);
+ poly144.ps[2] = Point(709.924, 131.557);
+ poly144.ps[3] = Point(709.924, 91.5565);
+ new ShapeRef(router, poly144, 144);
+
+ Polygon poly145(4);
+ poly145.ps[0] = Point(765.924, 790.057);
+ poly145.ps[1] = Point(765.924, 830.057);
+ poly145.ps[2] = Point(709.924, 830.057);
+ poly145.ps[3] = Point(709.924, 790.057);
+ new ShapeRef(router, poly145, 145);
+
+ Polygon poly146(4);
+ poly146.ps[0] = Point(45.9242, 232.5);
+ poly146.ps[1] = Point(45.9242, 272.5);
+ poly146.ps[2] = Point(-14.0758, 272.5);
+ poly146.ps[3] = Point(-14.0758, 232.5);
+ new ShapeRef(router, poly146, 146);
+
+ Polygon poly147(4);
+ poly147.ps[0] = Point(-26.0758, 274.75);
+ poly147.ps[1] = Point(-26.0758, 334.75);
+ poly147.ps[2] = Point(-66.0758, 334.75);
+ poly147.ps[3] = Point(-66.0758, 274.75);
+ new ShapeRef(router, poly147, 147);
+
+ Polygon poly69(4);
+ poly69.ps[0] = Point(267.924, 151.557);
+ poly69.ps[1] = Point(267.924, 171.557);
+ poly69.ps[2] = Point(247.924, 171.557);
+ poly69.ps[3] = Point(247.924, 151.557);
+ new ShapeRef(router, poly69, 69);
+
+ Polygon poly102(4);
+ poly102.ps[0] = Point(1088.92, -70.6578);
+ poly102.ps[1] = Point(1088.92, -50.6578);
+ poly102.ps[2] = Point(1068.92, -50.6578);
+ poly102.ps[3] = Point(1068.92, -70.6578);
+ new ShapeRef(router, poly102, 102);
+
+ Polygon poly103(4);
+ poly103.ps[0] = Point(968.924, 270.557);
+ poly103.ps[1] = Point(968.924, 290.557);
+ poly103.ps[2] = Point(948.924, 290.557);
+ poly103.ps[3] = Point(948.924, 270.557);
+ new ShapeRef(router, poly103, 103);
+
+ Polygon poly104(4);
+ poly104.ps[0] = Point(747.924, 151.557);
+ poly104.ps[1] = Point(747.924, 171.557);
+ poly104.ps[2] = Point(727.924, 171.557);
+ poly104.ps[3] = Point(727.924, 151.557);
+ new ShapeRef(router, poly104, 104);
+
+ Polygon poly105(4);
+ poly105.ps[0] = Point(747.924, 850.057);
+ poly105.ps[1] = Point(747.924, 870.057);
+ poly105.ps[2] = Point(727.924, 870.057);
+ poly105.ps[3] = Point(727.924, 850.057);
+ new ShapeRef(router, poly105, 105);
+
+ Polygon poly106(4);
+ poly106.ps[0] = Point(765.924, -130.658);
+ poly106.ps[1] = Point(765.924, -90.6578);
+ poly106.ps[2] = Point(709.924, -90.6578);
+ poly106.ps[3] = Point(709.924, -130.658);
+ new ShapeRef(router, poly106, 106);
+
+ Polygon poly107(4);
+ poly107.ps[0] = Point(165.924, -35.1578);
+ poly107.ps[1] = Point(165.924, 4.84222);
+ poly107.ps[2] = Point(109.924, 4.84222);
+ poly107.ps[3] = Point(109.924, -35.1578);
+ new ShapeRef(router, poly107, 107);
+
+ Polygon poly108(4);
+ poly108.ps[0] = Point(165.924, 91.5565);
+ poly108.ps[1] = Point(165.924, 131.557);
+ poly108.ps[2] = Point(109.924, 131.557);
+ poly108.ps[3] = Point(109.924, 91.5565);
+ new ShapeRef(router, poly108, 108);
+
+ Polygon poly109(4);
+ poly109.ps[0] = Point(285.924, 91.5565);
+ poly109.ps[1] = Point(285.924, 131.557);
+ poly109.ps[2] = Point(229.924, 131.557);
+ poly109.ps[3] = Point(229.924, 91.5565);
+ new ShapeRef(router, poly109, 109);
+
+ Polygon poly110(4);
+ poly110.ps[0] = Point(287.924, 193.557);
+ poly110.ps[1] = Point(287.924, 233.557);
+ poly110.ps[2] = Point(231.924, 233.557);
+ poly110.ps[3] = Point(231.924, 193.557);
+ new ShapeRef(router, poly110, 110);
+
+ Polygon poly111(4);
+ poly111.ps[0] = Point(285.924, 245.557);
+ poly111.ps[1] = Point(285.924, 285.557);
+ poly111.ps[2] = Point(229.924, 285.557);
+ poly111.ps[3] = Point(229.924, 245.557);
+ new ShapeRef(router, poly111, 111);
+
+ Polygon poly112(4);
+ poly112.ps[0] = Point(167.924, 347.557);
+ poly112.ps[1] = Point(167.924, 387.557);
+ poly112.ps[2] = Point(111.924, 387.557);
+ poly112.ps[3] = Point(111.924, 347.557);
+ new ShapeRef(router, poly112, 112);
+
+ Polygon poly113(4);
+ poly113.ps[0] = Point(165.924, 457.557);
+ poly113.ps[1] = Point(165.924, 497.557);
+ poly113.ps[2] = Point(109.924, 497.557);
+ poly113.ps[3] = Point(109.924, 457.557);
+ new ShapeRef(router, poly113, 113);
+
+ Polygon poly114(4);
+ poly114.ps[0] = Point(165.924, 549.557);
+ poly114.ps[1] = Point(165.924, 589.557);
+ poly114.ps[2] = Point(109.924, 589.557);
+ poly114.ps[3] = Point(109.924, 549.557);
+ new ShapeRef(router, poly114, 114);
+
+ Polygon poly115(4);
+ poly115.ps[0] = Point(167.924, 641.557);
+ poly115.ps[1] = Point(167.924, 681.557);
+ poly115.ps[2] = Point(111.924, 681.557);
+ poly115.ps[3] = Point(111.924, 641.557);
+ new ShapeRef(router, poly115, 115);
+
+ Polygon poly20(4);
+ poly20.ps[0] = Point(337.924, 507.557);
+ poly20.ps[1] = Point(337.924, 547.557);
+ poly20.ps[2] = Point(297.924, 547.557);
+ poly20.ps[3] = Point(297.924, 507.557);
+ new ShapeRef(router, poly20, 20);
+
+ Polygon poly44(4);
+ poly44.ps[0] = Point(97.9242, 507.557);
+ poly44.ps[1] = Point(97.9242, 547.557);
+ poly44.ps[2] = Point(57.9242, 547.557);
+ poly44.ps[3] = Point(57.9242, 507.557);
+ new ShapeRef(router, poly44, 44);
+
+ Polygon poly11(4);
+ poly11.ps[0] = Point(817.924, -80.6578);
+ poly11.ps[1] = Point(817.924, -40.6578);
+ poly11.ps[2] = Point(777.924, -40.6578);
+ poly11.ps[3] = Point(777.924, -80.6578);
+ new ShapeRef(router, poly11, 11);
+
+ Polygon poly16(4);
+ poly16.ps[0] = Point(337.924, 743.557);
+ poly16.ps[1] = Point(337.924, 783.557);
+ poly16.ps[2] = Point(297.924, 783.557);
+ poly16.ps[3] = Point(297.924, 743.557);
+ new ShapeRef(router, poly16, 16);
+
+ Polygon poly13(4);
+ poly13.ps[0] = Point(1158.92, 323.557);
+ poly13.ps[1] = Point(1158.92, 363.557);
+ poly13.ps[2] = Point(1118.92, 363.557);
+ poly13.ps[3] = Point(1118.92, 323.557);
+ new ShapeRef(router, poly13, 13);
+
+ Polygon poly74(4);
+ poly74.ps[0] = Point(147.924, 609.557);
+ poly74.ps[1] = Point(147.924, 629.557);
+ poly74.ps[2] = Point(127.924, 629.557);
+ poly74.ps[3] = Point(127.924, 609.557);
+ new ShapeRef(router, poly74, 74);
+
+ Polygon poly41(4);
+ poly41.ps[0] = Point(577.924, 743.557);
+ poly41.ps[1] = Point(577.924, 783.557);
+ poly41.ps[2] = Point(537.924, 783.557);
+ poly41.ps[3] = Point(537.924, 743.557);
+ new ShapeRef(router, poly41, 41);
+
+ Polygon poly72(4);
+ poly72.ps[0] = Point(87.9242, 357.557);
+ poly72.ps[1] = Point(87.9242, 377.557);
+ poly72.ps[2] = Point(67.9242, 377.557);
+ poly72.ps[3] = Point(67.9242, 357.557);
+ new ShapeRef(router, poly72, 72);
+
+ Polygon poly27(4);
+ poly27.ps[0] = Point(577.924, 507.557);
+ poly27.ps[1] = Point(577.924, 547.557);
+ poly27.ps[2] = Point(537.924, 547.557);
+ poly27.ps[3] = Point(537.924, 507.557);
+ new ShapeRef(router, poly27, 27);
+
+ Polygon poly28(4);
+ poly28.ps[0] = Point(817.924, 323.557);
+ poly28.ps[1] = Point(817.924, 363.557);
+ poly28.ps[2] = Point(777.924, 363.557);
+ poly28.ps[3] = Point(777.924, 323.557);
+ new ShapeRef(router, poly28, 28);
+
+ Polygon poly48(4);
+ poly48.ps[0] = Point(97.9242, 743.557);
+ poly48.ps[1] = Point(97.9242, 783.557);
+ poly48.ps[2] = Point(57.9242, 783.557);
+ poly48.ps[3] = Point(57.9242, 743.557);
+ new ShapeRef(router, poly48, 48);
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(1371.92, -80.6578);
+ poly6.ps[1] = Point(1371.92, -40.6578);
+ poly6.ps[2] = Point(1331.92, -40.6578);
+ poly6.ps[3] = Point(1331.92, -80.6578);
+ new ShapeRef(router, poly6, 6);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(937.924, -80.6578);
+ poly10.ps[1] = Point(937.924, -40.6578);
+ poly10.ps[2] = Point(897.924, -40.6578);
+ poly10.ps[3] = Point(897.924, -80.6578);
+ new ShapeRef(router, poly10, 10);
+
+ Polygon poly64(4);
+ poly64.ps[0] = Point(817.924, 554.057);
+ poly64.ps[1] = Point(817.924, 594.057);
+ poly64.ps[2] = Point(777.924, 594.057);
+ poly64.ps[3] = Point(777.924, 554.057);
+ new ShapeRef(router, poly64, 64);
+
+ Polygon poly46(4);
+ poly46.ps[0] = Point(577.924, 415.557);
+ poly46.ps[1] = Point(577.924, 455.557);
+ poly46.ps[2] = Point(537.924, 455.557);
+ poly46.ps[3] = Point(537.924, 415.557);
+ new ShapeRef(router, poly46, 46);
+
+ Polygon poly34(4);
+ poly34.ps[0] = Point(1278.92, 323.557);
+ poly34.ps[1] = Point(1278.92, 363.557);
+ poly34.ps[2] = Point(1238.92, 363.557);
+ poly34.ps[3] = Point(1238.92, 323.557);
+ new ShapeRef(router, poly34, 34);
+
+ Polygon poly40(4);
+ poly40.ps[0] = Point(97.9242, 141.557);
+ poly40.ps[1] = Point(97.9242, 181.557);
+ poly40.ps[2] = Point(57.9242, 181.557);
+ poly40.ps[3] = Point(57.9242, 141.557);
+ new ShapeRef(router, poly40, 40);
+
+ Polygon poly31(4);
+ poly31.ps[0] = Point(1278.92, 141.557);
+ poly31.ps[1] = Point(1278.92, 181.557);
+ poly31.ps[2] = Point(1238.92, 181.557);
+ poly31.ps[3] = Point(1238.92, 141.557);
+ new ShapeRef(router, poly31, 31);
+
+ Polygon poly56(4);
+ poly56.ps[0] = Point(457.924, -44.6578);
+ poly56.ps[1] = Point(457.924, -4.65778);
+ poly56.ps[2] = Point(417.924, -4.65778);
+ poly56.ps[3] = Point(417.924, -44.6578);
+ new ShapeRef(router, poly56, 56);
+
+ Polygon poly63(4);
+ poly63.ps[0] = Point(457.924, 507.557);
+ poly63.ps[1] = Point(457.924, 547.557);
+ poly63.ps[2] = Point(417.924, 547.557);
+ poly63.ps[3] = Point(417.924, 507.557);
+ new ShapeRef(router, poly63, 63);
+
+ Polygon poly14(4);
+ poly14.ps[0] = Point(1158.92, 141.557);
+ poly14.ps[1] = Point(1158.92, 181.557);
+ poly14.ps[2] = Point(1118.92, 181.557);
+ poly14.ps[3] = Point(1118.92, 141.557);
+ new ShapeRef(router, poly14, 14);
+
+ Polygon poly43(4);
+ poly43.ps[0] = Point(1038.92, 1.84222);
+ poly43.ps[1] = Point(1038.92, 41.8422);
+ poly43.ps[2] = Point(998.924, 41.8422);
+ poly43.ps[3] = Point(998.924, 1.84222);
+ new ShapeRef(router, poly43, 43);
+
+ Polygon poly32(4);
+ poly32.ps[0] = Point(1038.92, 141.557);
+ poly32.ps[1] = Point(1038.92, 181.557);
+ poly32.ps[2] = Point(998.924, 181.557);
+ poly32.ps[3] = Point(998.924, 141.557);
+ new ShapeRef(router, poly32, 32);
+
+ Polygon poly67(4);
+ poly67.ps[0] = Point(147.924, 24.8422);
+ poly67.ps[1] = Point(147.924, 44.8422);
+ poly67.ps[2] = Point(127.924, 44.8422);
+ poly67.ps[3] = Point(127.924, 24.8422);
+ new ShapeRef(router, poly67, 67);
+
+ Polygon poly68(4);
+ poly68.ps[0] = Point(147.924, 151.557);
+ poly68.ps[1] = Point(147.924, 171.557);
+ poly68.ps[2] = Point(127.924, 171.557);
+ poly68.ps[3] = Point(127.924, 151.557);
+ new ShapeRef(router, poly68, 68);
+
+ Polygon poly57(4);
+ poly57.ps[0] = Point(817.924, 141.557);
+ poly57.ps[1] = Point(817.924, 181.557);
+ poly57.ps[2] = Point(777.924, 181.557);
+ poly57.ps[3] = Point(777.924, 141.557);
+ new ShapeRef(router, poly57, 57);
+
+ Polygon poly71(4);
+ poly71.ps[0] = Point(267.924, 305.557);
+ poly71.ps[1] = Point(267.924, 325.557);
+ poly71.ps[2] = Point(247.924, 325.557);
+ poly71.ps[3] = Point(247.924, 305.557);
+ new ShapeRef(router, poly71, 71);
+
+ Polygon poly39(4);
+ poly39.ps[0] = Point(457.924, 141.557);
+ poly39.ps[1] = Point(457.924, 181.557);
+ poly39.ps[2] = Point(417.924, 181.557);
+ poly39.ps[3] = Point(417.924, 141.557);
+ new ShapeRef(router, poly39, 39);
+
+ Polygon poly38(4);
+ poly38.ps[0] = Point(217.924, 507.557);
+ poly38.ps[1] = Point(217.924, 547.557);
+ poly38.ps[2] = Point(177.924, 547.557);
+ poly38.ps[3] = Point(177.924, 507.557);
+ new ShapeRef(router, poly38, 38);
+
+ Polygon poly29(4);
+ poly29.ps[0] = Point(1038.92, 415.557);
+ poly29.ps[1] = Point(1038.92, 455.557);
+ poly29.ps[2] = Point(998.924, 455.557);
+ poly29.ps[3] = Point(998.924, 415.557);
+ new ShapeRef(router, poly29, 29);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(1371.92, -22.1578);
+ poly5.ps[1] = Point(1371.92, 17.8422);
+ poly5.ps[2] = Point(1331.92, 17.8422);
+ poly5.ps[3] = Point(1331.92, -22.1578);
+ new ShapeRef(router, poly5, 5);
+
+ Polygon poly65(4);
+ poly65.ps[0] = Point(97.9242, 599.557);
+ poly65.ps[1] = Point(97.9242, 639.557);
+ poly65.ps[2] = Point(57.9242, 639.557);
+ poly65.ps[3] = Point(57.9242, 599.557);
+ new ShapeRef(router, poly65, 65);
+
+ Polygon poly15(4);
+ poly15.ps[0] = Point(1158.92, 415.557);
+ poly15.ps[1] = Point(1158.92, 455.557);
+ poly15.ps[2] = Point(1118.92, 455.557);
+ poly15.ps[3] = Point(1118.92, 415.557);
+ new ShapeRef(router, poly15, 15);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(1371.92, 29.8422);
+ poly4.ps[1] = Point(1371.92, 69.8422);
+ poly4.ps[2] = Point(1331.92, 69.8422);
+ poly4.ps[3] = Point(1331.92, 29.8422);
+ new ShapeRef(router, poly4, 4);
+
+ Polygon poly55(4);
+ poly55.ps[0] = Point(457.924, 7.34222);
+ poly55.ps[1] = Point(457.924, 47.3422);
+ poly55.ps[2] = Point(417.924, 47.3422);
+ poly55.ps[3] = Point(417.924, 7.34222);
+ new ShapeRef(router, poly55, 55);
+
+ Polygon poly35(4);
+ poly35.ps[0] = Point(1158.92, 40.3422);
+ poly35.ps[1] = Point(1158.92, 80.3422);
+ poly35.ps[2] = Point(1118.92, 80.3422);
+ poly35.ps[3] = Point(1118.92, 40.3422);
+ new ShapeRef(router, poly35, 35);
+
+ Polygon poly70(4);
+ poly70.ps[0] = Point(207.924, 203.557);
+ poly70.ps[1] = Point(207.924, 223.557);
+ poly70.ps[2] = Point(187.924, 223.557);
+ poly70.ps[3] = Point(187.924, 203.557);
+ new ShapeRef(router, poly70, 70);
+
+ Polygon poly50(4);
+ poly50.ps[0] = Point(272.5, -82.1578);
+ poly50.ps[1] = Point(272.5, -47.1578);
+ poly50.ps[2] = Point(35.5, -47.1578);
+ poly50.ps[3] = Point(35.5, -82.1578);
+ new ShapeRef(router, poly50, 50);
+
+ Polygon poly33(4);
+ poly33.ps[0] = Point(937.924, 415.557);
+ poly33.ps[1] = Point(937.924, 455.557);
+ poly33.ps[2] = Point(897.924, 455.557);
+ poly33.ps[3] = Point(897.924, 415.557);
+ new ShapeRef(router, poly33, 33);
+
+ Polygon poly12(4);
+ poly12.ps[0] = Point(1038.92, 260.557);
+ poly12.ps[1] = Point(1038.92, 300.557);
+ poly12.ps[2] = Point(998.924, 300.557);
+ poly12.ps[3] = Point(998.924, 260.557);
+ new ShapeRef(router, poly12, 12);
+
+ Polygon poly51(4);
+ poly51.ps[0] = Point(1038.92, 323.557);
+ poly51.ps[1] = Point(1038.92, 363.557);
+ poly51.ps[2] = Point(998.924, 363.557);
+ poly51.ps[3] = Point(998.924, 323.557);
+ new ShapeRef(router, poly51, 51);
+
+ Polygon poly62(4);
+ poly62.ps[0] = Point(577.924, 629.557);
+ poly62.ps[1] = Point(577.924, 669.557);
+ poly62.ps[2] = Point(537.924, 669.557);
+ poly62.ps[3] = Point(537.924, 629.557);
+ new ShapeRef(router, poly62, 62);
+
+ Polygon poly53(4);
+ poly53.ps[0] = Point(577.924, 323.557);
+ poly53.ps[1] = Point(577.924, 363.557);
+ poly53.ps[2] = Point(537.924, 363.557);
+ poly53.ps[3] = Point(537.924, 323.557);
+ new ShapeRef(router, poly53, 53);
+
+ Polygon poly17(4);
+ poly17.ps[0] = Point(577.924, 883.057);
+ poly17.ps[1] = Point(577.924, 923.057);
+ poly17.ps[2] = Point(537.924, 923.057);
+ poly17.ps[3] = Point(537.924, 883.057);
+ new ShapeRef(router, poly17, 17);
+
+ Polygon poly22(4);
+ poly22.ps[0] = Point(697.924, 34.8422);
+ poly22.ps[1] = Point(697.924, 74.8422);
+ poly22.ps[2] = Point(657.924, 74.8422);
+ poly22.ps[3] = Point(657.924, 34.8422);
+ new ShapeRef(router, poly22, 22);
+
+ Polygon poly26(4);
+ poly26.ps[0] = Point(697.924, 743.557);
+ poly26.ps[1] = Point(697.924, 783.557);
+ poly26.ps[2] = Point(657.924, 783.557);
+ poly26.ps[3] = Point(657.924, 743.557);
+ new ShapeRef(router, poly26, 26);
+
+ ConnRef *connRef256 = new ConnRef(router, 256);
+ ConnEnd srcPt256(Point(737.924, 293.557), 15);
+ connRef256->setSourceEndpoint(srcPt256);
+ ConnEnd dstPt256(Point(737.924, 343.557), 15);
+ connRef256->setDestEndpoint(dstPt256);
+ connRef256->setRoutingType((ConnType)2);
+
+ ConnRef *connRef257 = new ConnRef(router, 257);
+ ConnEnd srcPt257(Point(1078.92, 338.557), 15);
+ connRef257->setSourceEndpoint(srcPt257);
+ ConnEnd dstPt257(Point(1078.92, 388.557), 15);
+ connRef257->setDestEndpoint(dstPt257);
+ connRef257->setRoutingType((ConnType)2);
+
+ ConnRef *connRef258 = new ConnRef(router, 258);
+ ConnEnd srcPt258(Point(1198.92, 338.557), 15);
+ connRef258->setSourceEndpoint(srcPt258);
+ ConnEnd dstPt258(Point(1198.92, 388.557), 15);
+ connRef258->setDestEndpoint(dstPt258);
+ connRef258->setRoutingType((ConnType)2);
+
+ ConnRef *connRef259 = new ConnRef(router, 259);
+ ConnEnd srcPt259(Point(1078.92, 102.342), 15);
+ connRef259->setSourceEndpoint(srcPt259);
+ ConnEnd dstPt259(Point(1078.92, 152.342), 15);
+ connRef259->setDestEndpoint(dstPt259);
+ connRef259->setRoutingType((ConnType)2);
+
+ ConnRef *connRef260 = new ConnRef(router, 260);
+ ConnEnd srcPt260(Point(1078.92, 10.3422), 15);
+ connRef260->setSourceEndpoint(srcPt260);
+ ConnEnd dstPt260(Point(1078.92, 60.3422), 15);
+ connRef260->setDestEndpoint(dstPt260);
+ connRef260->setRoutingType((ConnType)2);
+
+ ConnRef *connRef261 = new ConnRef(router, 261);
+ ConnEnd srcPt261(Point(1198.92, 102.342), 15);
+ connRef261->setSourceEndpoint(srcPt261);
+ ConnEnd dstPt261(Point(1198.92, 152.342), 15);
+ connRef261->setDestEndpoint(dstPt261);
+ connRef261->setRoutingType((ConnType)2);
+
+ ConnRef *connRef262 = new ConnRef(router, 262);
+ ConnEnd srcPt262(Point(1078.92, -110.658), 15);
+ connRef262->setSourceEndpoint(srcPt262);
+ ConnEnd dstPt262(Point(1078.92, -60.6578), 15);
+ connRef262->setDestEndpoint(dstPt262);
+ connRef262->setRoutingType((ConnType)2);
+
+ ConnRef *connRef263 = new ConnRef(router, 263);
+ ConnEnd srcPt263(Point(958.924, 230.557), 15);
+ connRef263->setSourceEndpoint(srcPt263);
+ ConnEnd dstPt263(Point(958.924, 280.557), 15);
+ connRef263->setDestEndpoint(dstPt263);
+ connRef263->setRoutingType((ConnType)2);
+
+ ConnRef *connRef264 = new ConnRef(router, 264);
+ ConnEnd srcPt264(Point(737.924, 111.557), 15);
+ connRef264->setSourceEndpoint(srcPt264);
+ ConnEnd dstPt264(Point(737.924, 161.557), 15);
+ connRef264->setDestEndpoint(dstPt264);
+ connRef264->setRoutingType((ConnType)2);
+
+ ConnRef *connRef265 = new ConnRef(router, 265);
+ ConnEnd srcPt265(Point(737.924, 810.057), 15);
+ connRef265->setSourceEndpoint(srcPt265);
+ ConnEnd dstPt265(Point(737.924, 860.057), 15);
+ connRef265->setDestEndpoint(dstPt265);
+ connRef265->setRoutingType((ConnType)2);
+
+ ConnRef *connRef266 = new ConnRef(router, 266);
+ ConnEnd srcPt266(Point(77.9242, 161.557), 15);
+ connRef266->setSourceEndpoint(srcPt266);
+ ConnEnd dstPt266(Point(40.9242, 252.5), 15);
+ connRef266->setDestEndpoint(dstPt266);
+ connRef266->setRoutingType((ConnType)2);
+
+ ConnRef *connRef267 = new ConnRef(router, 267);
+ ConnEnd srcPt267(Point(77.9242, 763.557), 15);
+ connRef267->setSourceEndpoint(srcPt267);
+ ConnEnd dstPt267(Point(-46.0758, 329.75), 15);
+ connRef267->setDestEndpoint(dstPt267);
+ connRef267->setRoutingType((ConnType)2);
+
+ ConnRef *connRef148 = new ConnRef(router, 148);
+ ConnEnd srcPt148(Point(1018.92, -60.6578), 15);
+ connRef148->setSourceEndpoint(srcPt148);
+ ConnEnd dstPt148(Point(1068.92, -60.6578), 15);
+ connRef148->setDestEndpoint(dstPt148);
+ connRef148->setRoutingType((ConnType)2);
+
+ ConnRef *connRef149 = new ConnRef(router, 149);
+ ConnEnd srcPt149(Point(1138.92, 161.557), 15);
+ connRef149->setSourceEndpoint(srcPt149);
+ ConnEnd dstPt149(Point(1188.92, 152.342), 15);
+ connRef149->setDestEndpoint(dstPt149);
+ connRef149->setRoutingType((ConnType)2);
+
+ ConnRef *connRef150 = new ConnRef(router, 150);
+ ConnEnd srcPt150(Point(1138.92, 435.557), 15);
+ connRef150->setSourceEndpoint(srcPt150);
+ ConnEnd dstPt150(Point(1188.92, 388.557), 15);
+ connRef150->setDestEndpoint(dstPt150);
+ connRef150->setRoutingType((ConnType)2);
+
+ ConnRef *connRef151 = new ConnRef(router, 151);
+ ConnEnd srcPt151(Point(317.924, 763.557), 15);
+ connRef151->setSourceEndpoint(srcPt151);
+ ConnEnd dstPt151(Point(367.924, 627.557), 15);
+ connRef151->setDestEndpoint(dstPt151);
+ connRef151->setRoutingType((ConnType)2);
+
+ ConnRef *connRef152 = new ConnRef(router, 152);
+ ConnEnd srcPt152(Point(317.924, 763.557), 15);
+ connRef152->setSourceEndpoint(srcPt152);
+ ConnEnd dstPt152(Point(367.924, 763.557), 15);
+ connRef152->setDestEndpoint(dstPt152);
+ connRef152->setRoutingType((ConnType)2);
+
+ ConnRef *connRef153 = new ConnRef(router, 153);
+ ConnEnd srcPt153(Point(317.924, 763.557), 15);
+ connRef153->setSourceEndpoint(srcPt153);
+ ConnEnd dstPt153(Point(487.924, 903.057), 15);
+ connRef153->setDestEndpoint(dstPt153);
+ connRef153->setRoutingType((ConnType)2);
+
+ ConnRef *connRef154 = new ConnRef(router, 154);
+ ConnEnd srcPt154(Point(317.924, 763.557), 15);
+ connRef154->setSourceEndpoint(srcPt154);
+ ConnEnd dstPt154(Point(727.924, 574.057), 15);
+ connRef154->setDestEndpoint(dstPt154);
+ connRef154->setRoutingType((ConnType)2);
+
+ ConnRef *connRef155 = new ConnRef(router, 155);
+ ConnEnd srcPt155(Point(557.924, 903.057), 15);
+ connRef155->setSourceEndpoint(srcPt155);
+ ConnEnd dstPt155(Point(607.924, 903.057), 15);
+ connRef155->setDestEndpoint(dstPt155);
+ connRef155->setRoutingType((ConnType)2);
+
+ ConnRef *connRef156 = new ConnRef(router, 156);
+ ConnEnd srcPt156(Point(197.924, 763.557), 15);
+ connRef156->setSourceEndpoint(srcPt156);
+ ConnEnd dstPt156(Point(247.924, 763.557), 15);
+ connRef156->setDestEndpoint(dstPt156);
+ connRef156->setRoutingType((ConnType)2);
+
+ ConnRef *connRef157 = new ConnRef(router, 157);
+ ConnEnd srcPt157(Point(147.924, 161.557), 15);
+ connRef157->setSourceEndpoint(srcPt157);
+ ConnEnd dstPt157(Point(197.924, 161.557), 15);
+ connRef157->setDestEndpoint(dstPt157);
+ connRef157->setRoutingType((ConnType)2);
+
+ ConnRef *connRef158 = new ConnRef(router, 158);
+ ConnEnd srcPt158(Point(197.924, 161.557), 15);
+ connRef158->setSourceEndpoint(srcPt158);
+ ConnEnd dstPt158(Point(247.924, 161.557), 15);
+ connRef158->setDestEndpoint(dstPt158);
+ connRef158->setRoutingType((ConnType)2);
+
+ ConnRef *connRef159 = new ConnRef(router, 159);
+ ConnEnd srcPt159(Point(197.924, 161.557), 15);
+ connRef159->setSourceEndpoint(srcPt159);
+ ConnEnd dstPt159(Point(197.924, 203.557), 15);
+ connRef159->setDestEndpoint(dstPt159);
+ connRef159->setRoutingType((ConnType)2);
+
+ ConnRef *connRef160 = new ConnRef(router, 160);
+ ConnEnd srcPt160(Point(317.924, 161.557), 15);
+ connRef160->setSourceEndpoint(srcPt160);
+ ConnEnd dstPt160(Point(727.924, -60.6578), 15);
+ connRef160->setDestEndpoint(dstPt160);
+ connRef160->setRoutingType((ConnType)2);
+
+ ConnRef *connRef161 = new ConnRef(router, 161);
+ ConnEnd srcPt161(Point(317.924, 161.557), 15);
+ connRef161->setSourceEndpoint(srcPt161);
+ ConnEnd dstPt161(Point(367.924, 161.557), 15);
+ connRef161->setDestEndpoint(dstPt161);
+ connRef161->setRoutingType((ConnType)2);
+
+ ConnRef *connRef162 = new ConnRef(router, 162);
+ ConnEnd srcPt162(Point(317.924, 161.557), 15);
+ connRef162->setSourceEndpoint(srcPt162);
+ ConnEnd dstPt162(Point(367.924, 27.3422), 15);
+ connRef162->setDestEndpoint(dstPt162);
+ connRef162->setRoutingType((ConnType)2);
+
+ ConnRef *connRef163 = new ConnRef(router, 163);
+ ConnEnd srcPt163(Point(317.924, 161.557), 15);
+ connRef163->setSourceEndpoint(srcPt163);
+ ConnEnd dstPt163(Point(487.924, 435.557), 15);
+ connRef163->setDestEndpoint(dstPt163);
+ connRef163->setRoutingType((ConnType)2);
+
+ ConnRef *connRef164 = new ConnRef(router, 164);
+ ConnEnd srcPt164(Point(437.924, 763.557), 15);
+ connRef164->setSourceEndpoint(srcPt164);
+ ConnEnd dstPt164(Point(487.924, 763.557), 15);
+ connRef164->setDestEndpoint(dstPt164);
+ connRef164->setRoutingType((ConnType)2);
+
+ ConnRef *connRef165 = new ConnRef(router, 165);
+ ConnEnd srcPt165(Point(437.924, 763.557), 15);
+ connRef165->setSourceEndpoint(srcPt165);
+ ConnEnd dstPt165(Point(727.924, 860.057), 15);
+ connRef165->setDestEndpoint(dstPt165);
+ connRef165->setRoutingType((ConnType)2);
+
+ ConnRef *connRef166 = new ConnRef(router, 166);
+ ConnEnd srcPt166(Point(557.924, 527.557), 15);
+ connRef166->setSourceEndpoint(srcPt166);
+ ConnEnd dstPt166(Point(607.924, 527.557), 15);
+ connRef166->setDestEndpoint(dstPt166);
+ connRef166->setRoutingType((ConnType)2);
+
+ ConnRef *connRef167 = new ConnRef(router, 167);
+ ConnEnd srcPt167(Point(797.924, 343.557), 15);
+ connRef167->setSourceEndpoint(srcPt167);
+ ConnEnd dstPt167(Point(847.924, 343.557), 15);
+ connRef167->setDestEndpoint(dstPt167);
+ connRef167->setRoutingType((ConnType)2);
+
+ ConnRef *connRef168 = new ConnRef(router, 168);
+ ConnEnd srcPt168(Point(797.924, 343.557), 15);
+ connRef168->setSourceEndpoint(srcPt168);
+ ConnEnd dstPt168(Point(847.924, 435.557), 15);
+ connRef168->setDestEndpoint(dstPt168);
+ connRef168->setRoutingType((ConnType)2);
+
+ ConnRef *connRef169 = new ConnRef(router, 169);
+ ConnEnd srcPt169(Point(1018.92, 435.557), 15);
+ connRef169->setSourceEndpoint(srcPt169);
+ ConnEnd dstPt169(Point(1068.92, 388.557), 15);
+ connRef169->setDestEndpoint(dstPt169);
+ connRef169->setRoutingType((ConnType)2);
+
+ ConnRef *connRef170 = new ConnRef(router, 170);
+ ConnEnd srcPt170(Point(1018.92, 161.557), 15);
+ connRef170->setSourceEndpoint(srcPt170);
+ ConnEnd dstPt170(Point(1068.92, 152.342), 15);
+ connRef170->setDestEndpoint(dstPt170);
+ connRef170->setRoutingType((ConnType)2);
+
+ ConnRef *connRef171 = new ConnRef(router, 171);
+ ConnEnd srcPt171(Point(1018.92, 161.557), 15);
+ connRef171->setSourceEndpoint(srcPt171);
+ ConnEnd dstPt171(Point(1068.92, 60.3422), 15);
+ connRef171->setDestEndpoint(dstPt171);
+ connRef171->setRoutingType((ConnType)2);
+
+ ConnRef *connRef172 = new ConnRef(router, 172);
+ ConnEnd srcPt172(Point(267.924, 315.557), 15);
+ connRef172->setSourceEndpoint(srcPt172);
+ ConnEnd dstPt172(Point(437.924, 161.557), 15);
+ connRef172->setDestEndpoint(dstPt172);
+ connRef172->setRoutingType((ConnType)2);
+
+ ConnRef *connRef173 = new ConnRef(router, 173);
+ ConnEnd srcPt173(Point(437.924, 161.557), 15);
+ connRef173->setSourceEndpoint(srcPt173);
+ ConnEnd dstPt173(Point(487.924, 45.8422), 15);
+ connRef173->setDestEndpoint(dstPt173);
+ connRef173->setRoutingType((ConnType)2);
+
+ ConnRef *connRef174 = new ConnRef(router, 174);
+ ConnEnd srcPt174(Point(437.924, 161.557), 15);
+ connRef174->setSourceEndpoint(srcPt174);
+ ConnEnd dstPt174(Point(727.924, 161.557), 15);
+ connRef174->setDestEndpoint(dstPt174);
+ connRef174->setRoutingType((ConnType)2);
+
+ ConnRef *connRef175 = new ConnRef(router, 175);
+ ConnEnd srcPt175(Point(77.9242, 161.557), 15);
+ connRef175->setSourceEndpoint(srcPt175);
+ ConnEnd dstPt175(Point(127.924, 161.557), 15);
+ connRef175->setDestEndpoint(dstPt175);
+ connRef175->setRoutingType((ConnType)2);
+
+ ConnRef *connRef176 = new ConnRef(router, 176);
+ ConnEnd srcPt176(Point(77.9242, 161.557), 15);
+ connRef176->setSourceEndpoint(srcPt176);
+ ConnEnd dstPt176(Point(77.9242, 357.557), 15);
+ connRef176->setDestEndpoint(dstPt176);
+ connRef176->setRoutingType((ConnType)2);
+
+ ConnRef *connRef177 = new ConnRef(router, 177);
+ ConnEnd srcPt177(Point(557.924, 763.557), 15);
+ connRef177->setSourceEndpoint(srcPt177);
+ ConnEnd dstPt177(Point(607.924, 763.557), 15);
+ connRef177->setDestEndpoint(dstPt177);
+ connRef177->setRoutingType((ConnType)2);
+
+ ConnRef *connRef178 = new ConnRef(router, 178);
+ ConnEnd srcPt178(Point(77.9242, 527.557), 15);
+ connRef178->setSourceEndpoint(srcPt178);
+ ConnEnd dstPt178(Point(127.924, 527.557), 15);
+ connRef178->setDestEndpoint(dstPt178);
+ connRef178->setRoutingType((ConnType)2);
+
+ ConnRef *connRef179 = new ConnRef(router, 179);
+ ConnEnd srcPt179(Point(557.924, 54.8422), 15);
+ connRef179->setSourceEndpoint(srcPt179);
+ ConnEnd dstPt179(Point(607.924, 45.8422), 15);
+ connRef179->setDestEndpoint(dstPt179);
+ connRef179->setRoutingType((ConnType)2);
+
+ ConnRef *connRef180 = new ConnRef(router, 180);
+ ConnEnd srcPt180(Point(557.924, 435.557), 15);
+ connRef180->setSourceEndpoint(srcPt180);
+ ConnEnd dstPt180(Point(607.924, 435.557), 15);
+ connRef180->setDestEndpoint(dstPt180);
+ connRef180->setRoutingType((ConnType)2);
+
+ ConnRef *connRef181 = new ConnRef(router, 181);
+ ConnEnd srcPt181(Point(77.9242, 763.557), 15);
+ connRef181->setSourceEndpoint(srcPt181);
+ ConnEnd dstPt181(Point(77.9242, 671.557), 15);
+ connRef181->setDestEndpoint(dstPt181);
+ connRef181->setRoutingType((ConnType)2);
+
+ ConnRef *connRef182 = new ConnRef(router, 182);
+ ConnEnd srcPt182(Point(77.9242, 763.557), 15);
+ connRef182->setSourceEndpoint(srcPt182);
+ ConnEnd dstPt182(Point(127.924, 763.557), 15);
+ connRef182->setDestEndpoint(dstPt182);
+ connRef182->setRoutingType((ConnType)2);
+
+ ConnRef *connRef183 = new ConnRef(router, 183);
+ ConnEnd srcPt183(Point(197.924, 315.557), 15);
+ connRef183->setSourceEndpoint(srcPt183);
+ ConnEnd dstPt183(Point(247.924, 315.557), 15);
+ connRef183->setDestEndpoint(dstPt183);
+ connRef183->setRoutingType((ConnType)2);
+
+ ConnRef *connRef184 = new ConnRef(router, 184);
+ ConnEnd srcPt184(Point(677.924, 343.557), 15);
+ connRef184->setSourceEndpoint(srcPt184);
+ ConnEnd dstPt184(Point(727.924, 343.557), 15);
+ connRef184->setDestEndpoint(dstPt184);
+ connRef184->setRoutingType((ConnType)2);
+
+ ConnRef *connRef185 = new ConnRef(router, 185);
+ ConnEnd srcPt185(Point(797.924, 161.557), 15);
+ connRef185->setSourceEndpoint(srcPt185);
+ ConnEnd dstPt185(Point(847.924, 161.557), 15);
+ connRef185->setDestEndpoint(dstPt185);
+ connRef185->setRoutingType((ConnType)2);
+
+ ConnRef *connRef186 = new ConnRef(router, 186);
+ ConnEnd srcPt186(Point(77.9242, 34.8422), 15);
+ connRef186->setSourceEndpoint(srcPt186);
+ ConnEnd dstPt186(Point(127.924, 34.8422), 15);
+ connRef186->setDestEndpoint(dstPt186);
+ connRef186->setRoutingType((ConnType)2);
+
+ ConnRef *connRef187 = new ConnRef(router, 187);
+ ConnEnd srcPt187(Point(437.924, 527.557), 15);
+ connRef187->setSourceEndpoint(srcPt187);
+ ConnEnd dstPt187(Point(487.924, 527.557), 15);
+ connRef187->setDestEndpoint(dstPt187);
+ connRef187->setRoutingType((ConnType)2);
+
+ ConnRef *connRef188 = new ConnRef(router, 188);
+ ConnEnd srcPt188(Point(77.9242, 619.557), 15);
+ connRef188->setSourceEndpoint(srcPt188);
+ ConnEnd dstPt188(Point(127.924, 619.557), 15);
+ connRef188->setDestEndpoint(dstPt188);
+ connRef188->setRoutingType((ConnType)2);
+
+ ConnRef *connRef189 = new ConnRef(router, 189);
+ ConnEnd srcPt189(Point(747.924, -60.6578), 15);
+ connRef189->setSourceEndpoint(srcPt189);
+ ConnEnd dstPt189(Point(797.924, -60.6578), 15);
+ connRef189->setDestEndpoint(dstPt189);
+ connRef189->setRoutingType((ConnType)2);
+
+ ConnRef *connRef190 = new ConnRef(router, 190);
+ ConnEnd srcPt190(Point(147.924, 34.8422), 15);
+ connRef190->setSourceEndpoint(srcPt190);
+ ConnEnd dstPt190(Point(197.924, 161.557), 15);
+ connRef190->setDestEndpoint(dstPt190);
+ connRef190->setRoutingType((ConnType)2);
+
+ ConnRef *connRef191 = new ConnRef(router, 191);
+ ConnEnd srcPt191(Point(267.924, 161.557), 15);
+ connRef191->setSourceEndpoint(srcPt191);
+ ConnEnd dstPt191(Point(317.924, 161.557), 15);
+ connRef191->setDestEndpoint(dstPt191);
+ connRef191->setRoutingType((ConnType)2);
+
+ ConnRef *connRef192 = new ConnRef(router, 192);
+ ConnEnd srcPt192(Point(197.924, 223.557), 15);
+ connRef192->setSourceEndpoint(srcPt192);
+ ConnEnd dstPt192(Point(197.924, 315.557), 15);
+ connRef192->setDestEndpoint(dstPt192);
+ connRef192->setRoutingType((ConnType)2);
+
+ ConnRef *connRef193 = new ConnRef(router, 193);
+ ConnEnd srcPt193(Point(77.9242, 377.557), 15);
+ connRef193->setSourceEndpoint(srcPt193);
+ ConnEnd dstPt193(Point(77.9242, 527.557), 15);
+ connRef193->setDestEndpoint(dstPt193);
+ connRef193->setRoutingType((ConnType)2);
+
+ ConnRef *connRef194 = new ConnRef(router, 194);
+ ConnEnd srcPt194(Point(147.924, 527.557), 15);
+ connRef194->setSourceEndpoint(srcPt194);
+ ConnEnd dstPt194(Point(197.924, 527.557), 15);
+ connRef194->setDestEndpoint(dstPt194);
+ connRef194->setRoutingType((ConnType)2);
+
+ ConnRef *connRef195 = new ConnRef(router, 195);
+ ConnEnd srcPt195(Point(147.924, 619.557), 15);
+ connRef195->setSourceEndpoint(srcPt195);
+ ConnEnd dstPt195(Point(197.924, 763.557), 15);
+ connRef195->setDestEndpoint(dstPt195);
+ connRef195->setRoutingType((ConnType)2);
+
+ ConnRef *connRef196 = new ConnRef(router, 196);
+ ConnEnd srcPt196(Point(77.9242, 651.557), 15);
+ connRef196->setSourceEndpoint(srcPt196);
+ ConnEnd dstPt196(Point(77.9242, 619.557), 15);
+ connRef196->setDestEndpoint(dstPt196);
+ connRef196->setRoutingType((ConnType)2);
+
+ ConnRef *connRef197 = new ConnRef(router, 197);
+ ConnEnd srcPt197(Point(147.924, 763.557), 15);
+ connRef197->setSourceEndpoint(srcPt197);
+ ConnEnd dstPt197(Point(197.924, 763.557), 15);
+ connRef197->setDestEndpoint(dstPt197);
+ connRef197->setRoutingType((ConnType)2);
+
+ ConnRef *connRef198 = new ConnRef(router, 198);
+ ConnEnd srcPt198(Point(267.924, 763.557), 15);
+ connRef198->setSourceEndpoint(srcPt198);
+ ConnEnd dstPt198(Point(317.924, 763.557), 15);
+ connRef198->setDestEndpoint(dstPt198);
+ connRef198->setRoutingType((ConnType)2);
+
+ ConnRef *connRef199 = new ConnRef(router, 199);
+ ConnEnd srcPt199(Point(387.924, 627.557), 15);
+ connRef199->setSourceEndpoint(srcPt199);
+ ConnEnd dstPt199(Point(437.924, 627.557), 15);
+ connRef199->setDestEndpoint(dstPt199);
+ connRef199->setRoutingType((ConnType)2);
+
+ ConnRef *connRef200 = new ConnRef(router, 200);
+ ConnEnd srcPt200(Point(387.924, 763.557), 15);
+ connRef200->setSourceEndpoint(srcPt200);
+ ConnEnd dstPt200(Point(437.924, 763.557), 15);
+ connRef200->setDestEndpoint(dstPt200);
+ connRef200->setRoutingType((ConnType)2);
+
+ ConnRef *connRef201 = new ConnRef(router, 201);
+ ConnEnd srcPt201(Point(507.924, 763.557), 15);
+ connRef201->setSourceEndpoint(srcPt201);
+ ConnEnd dstPt201(Point(557.924, 763.557), 15);
+ connRef201->setDestEndpoint(dstPt201);
+ connRef201->setRoutingType((ConnType)2);
+
+ ConnRef *connRef202 = new ConnRef(router, 202);
+ ConnEnd srcPt202(Point(627.924, 763.557), 15);
+ connRef202->setSourceEndpoint(srcPt202);
+ ConnEnd dstPt202(Point(677.924, 763.557), 15);
+ connRef202->setDestEndpoint(dstPt202);
+ connRef202->setRoutingType((ConnType)2);
+
+ ConnRef *connRef203 = new ConnRef(router, 203);
+ ConnEnd srcPt203(Point(507.924, 903.057), 15);
+ connRef203->setSourceEndpoint(srcPt203);
+ ConnEnd dstPt203(Point(557.924, 903.057), 15);
+ connRef203->setDestEndpoint(dstPt203);
+ connRef203->setRoutingType((ConnType)2);
+
+ ConnRef *connRef204 = new ConnRef(router, 204);
+ ConnEnd srcPt204(Point(627.924, 903.057), 15);
+ connRef204->setSourceEndpoint(srcPt204);
+ ConnEnd dstPt204(Point(677.924, 903.057), 15);
+ connRef204->setDestEndpoint(dstPt204);
+ connRef204->setRoutingType((ConnType)2);
+
+ ConnRef *connRef205 = new ConnRef(router, 205);
+ ConnEnd srcPt205(Point(387.924, 161.557), 15);
+ connRef205->setSourceEndpoint(srcPt205);
+ ConnEnd dstPt205(Point(437.924, 161.557), 15);
+ connRef205->setDestEndpoint(dstPt205);
+ connRef205->setRoutingType((ConnType)2);
+
+ ConnRef *connRef206 = new ConnRef(router, 206);
+ ConnEnd srcPt206(Point(387.924, 27.3422), 15);
+ connRef206->setSourceEndpoint(srcPt206);
+ ConnEnd dstPt206(Point(437.924, 27.3422), 15);
+ connRef206->setDestEndpoint(dstPt206);
+ connRef206->setRoutingType((ConnType)2);
+
+ ConnRef *connRef207 = new ConnRef(router, 207);
+ ConnEnd srcPt207(Point(507.924, 45.8422), 15);
+ connRef207->setSourceEndpoint(srcPt207);
+ ConnEnd dstPt207(Point(557.924, 54.8422), 15);
+ connRef207->setDestEndpoint(dstPt207);
+ connRef207->setRoutingType((ConnType)2);
+
+ ConnRef *connRef208 = new ConnRef(router, 208);
+ ConnEnd srcPt208(Point(627.924, 45.8422), 15);
+ connRef208->setSourceEndpoint(srcPt208);
+ ConnEnd dstPt208(Point(677.924, 54.8422), 15);
+ connRef208->setDestEndpoint(dstPt208);
+ connRef208->setRoutingType((ConnType)2);
+
+ ConnRef *connRef209 = new ConnRef(router, 209);
+ ConnEnd srcPt209(Point(747.924, 574.057), 15);
+ connRef209->setSourceEndpoint(srcPt209);
+ ConnEnd dstPt209(Point(797.924, 574.057), 15);
+ connRef209->setDestEndpoint(dstPt209);
+ connRef209->setRoutingType((ConnType)2);
+
+ ConnRef *connRef210 = new ConnRef(router, 210);
+ ConnEnd srcPt210(Point(507.924, 527.557), 15);
+ connRef210->setSourceEndpoint(srcPt210);
+ ConnEnd dstPt210(Point(557.924, 527.557), 15);
+ connRef210->setDestEndpoint(dstPt210);
+ connRef210->setRoutingType((ConnType)2);
+
+ ConnRef *connRef211 = new ConnRef(router, 211);
+ ConnEnd srcPt211(Point(507.924, 435.557), 15);
+ connRef211->setSourceEndpoint(srcPt211);
+ ConnEnd dstPt211(Point(557.924, 435.557), 15);
+ connRef211->setDestEndpoint(dstPt211);
+ connRef211->setRoutingType((ConnType)2);
+
+ ConnRef *connRef212 = new ConnRef(router, 212);
+ ConnEnd srcPt212(Point(627.924, 527.557), 15);
+ connRef212->setSourceEndpoint(srcPt212);
+ ConnEnd dstPt212(Point(677.924, 527.557), 15);
+ connRef212->setDestEndpoint(dstPt212);
+ connRef212->setRoutingType((ConnType)2);
+
+ ConnRef *connRef213 = new ConnRef(router, 213);
+ ConnEnd srcPt213(Point(627.924, 435.557), 15);
+ connRef213->setSourceEndpoint(srcPt213);
+ ConnEnd dstPt213(Point(677.924, 435.557), 15);
+ connRef213->setDestEndpoint(dstPt213);
+ connRef213->setRoutingType((ConnType)2);
+
+ ConnRef *connRef214 = new ConnRef(router, 214);
+ ConnEnd srcPt214(Point(867.924, 343.557), 15);
+ connRef214->setSourceEndpoint(srcPt214);
+ ConnEnd dstPt214(Point(917.924, 343.557), 15);
+ connRef214->setDestEndpoint(dstPt214);
+ connRef214->setRoutingType((ConnType)2);
+
+ ConnRef *connRef215 = new ConnRef(router, 215);
+ ConnEnd srcPt215(Point(867.924, 435.557), 15);
+ connRef215->setSourceEndpoint(srcPt215);
+ ConnEnd dstPt215(Point(917.924, 435.557), 15);
+ connRef215->setDestEndpoint(dstPt215);
+ connRef215->setRoutingType((ConnType)2);
+
+ ConnRef *connRef216 = new ConnRef(router, 216);
+ ConnEnd srcPt216(Point(867.924, 161.557), 15);
+ connRef216->setSourceEndpoint(srcPt216);
+ ConnEnd dstPt216(Point(917.924, 161.557), 15);
+ connRef216->setDestEndpoint(dstPt216);
+ connRef216->setRoutingType((ConnType)2);
+
+ ConnRef *connRef217 = new ConnRef(router, 217);
+ ConnEnd srcPt217(Point(747.924, 343.557), 15);
+ connRef217->setSourceEndpoint(srcPt217);
+ ConnEnd dstPt217(Point(797.924, 343.557), 15);
+ connRef217->setDestEndpoint(dstPt217);
+ connRef217->setRoutingType((ConnType)2);
+
+ ConnRef *connRef218 = new ConnRef(router, 218);
+ ConnEnd srcPt218(Point(1088.92, 388.557), 15);
+ connRef218->setSourceEndpoint(srcPt218);
+ ConnEnd dstPt218(Point(1138.92, 435.557), 15);
+ connRef218->setDestEndpoint(dstPt218);
+ connRef218->setRoutingType((ConnType)2);
+
+ ConnRef *connRef219 = new ConnRef(router, 219);
+ ConnEnd srcPt219(Point(1208.92, 388.557), 15);
+ connRef219->setSourceEndpoint(srcPt219);
+ ConnEnd dstPt219(Point(1258.92, 435.557), 15);
+ connRef219->setDestEndpoint(dstPt219);
+ connRef219->setRoutingType((ConnType)2);
+
+ ConnRef *connRef220 = new ConnRef(router, 220);
+ ConnEnd srcPt220(Point(1088.92, 152.342), 15);
+ connRef220->setSourceEndpoint(srcPt220);
+ ConnEnd dstPt220(Point(1138.92, 161.557), 15);
+ connRef220->setDestEndpoint(dstPt220);
+ connRef220->setRoutingType((ConnType)2);
+
+ ConnRef *connRef221 = new ConnRef(router, 221);
+ ConnEnd srcPt221(Point(1088.92, 60.3422), 15);
+ connRef221->setSourceEndpoint(srcPt221);
+ ConnEnd dstPt221(Point(1138.92, 60.3422), 15);
+ connRef221->setDestEndpoint(dstPt221);
+ connRef221->setRoutingType((ConnType)2);
+
+ ConnRef *connRef222 = new ConnRef(router, 222);
+ ConnEnd srcPt222(Point(1208.92, 152.342), 15);
+ connRef222->setSourceEndpoint(srcPt222);
+ ConnEnd dstPt222(Point(1258.92, 161.557), 15);
+ connRef222->setDestEndpoint(dstPt222);
+ connRef222->setRoutingType((ConnType)2);
+
+ ConnRef *connRef223 = new ConnRef(router, 223);
+ ConnEnd srcPt223(Point(1088.92, -60.6578), 15);
+ connRef223->setSourceEndpoint(srcPt223);
+ ConnEnd dstPt223(Point(1138.92, -60.6578), 15);
+ connRef223->setDestEndpoint(dstPt223);
+ connRef223->setRoutingType((ConnType)2);
+
+ ConnRef *connRef224 = new ConnRef(router, 224);
+ ConnEnd srcPt224(Point(747.924, 161.557), 15);
+ connRef224->setSourceEndpoint(srcPt224);
+ ConnEnd dstPt224(Point(797.924, 161.557), 15);
+ connRef224->setDestEndpoint(dstPt224);
+ connRef224->setRoutingType((ConnType)2);
+
+ ConnRef *connRef225 = new ConnRef(router, 225);
+ ConnEnd srcPt225(Point(747.924, 860.057), 15);
+ connRef225->setSourceEndpoint(srcPt225);
+ ConnEnd dstPt225(Point(797.924, 860.057), 15);
+ connRef225->setDestEndpoint(dstPt225);
+ connRef225->setRoutingType((ConnType)2);
+
+ ConnRef *connRef226 = new ConnRef(router, 226);
+ ConnEnd srcPt226(Point(737.924, -110.658), 15);
+ connRef226->setSourceEndpoint(srcPt226);
+ ConnEnd dstPt226(Point(737.924, -60.6578), 15);
+ connRef226->setDestEndpoint(dstPt226);
+ connRef226->setRoutingType((ConnType)2);
+
+ ConnRef *connRef227 = new ConnRef(router, 227);
+ ConnEnd srcPt227(Point(137.924, -15.1578), 15);
+ connRef227->setSourceEndpoint(srcPt227);
+ ConnEnd dstPt227(Point(137.924, 34.8422), 15);
+ connRef227->setDestEndpoint(dstPt227);
+ connRef227->setRoutingType((ConnType)2);
+
+ ConnRef *connRef228 = new ConnRef(router, 228);
+ ConnEnd srcPt228(Point(137.924, 111.557), 15);
+ connRef228->setSourceEndpoint(srcPt228);
+ ConnEnd dstPt228(Point(137.924, 161.557), 15);
+ connRef228->setDestEndpoint(dstPt228);
+ connRef228->setRoutingType((ConnType)2);
+
+ ConnRef *connRef229 = new ConnRef(router, 229);
+ ConnEnd srcPt229(Point(257.924, 111.557), 15);
+ connRef229->setSourceEndpoint(srcPt229);
+ ConnEnd dstPt229(Point(257.924, 161.557), 15);
+ connRef229->setDestEndpoint(dstPt229);
+ connRef229->setRoutingType((ConnType)2);
+
+ ConnRef *connRef230 = new ConnRef(router, 230);
+ ConnEnd srcPt230(Point(259.924, 213.557), 15);
+ connRef230->setSourceEndpoint(srcPt230);
+ ConnEnd dstPt230(Point(197.924, 213.557), 15);
+ connRef230->setDestEndpoint(dstPt230);
+ connRef230->setRoutingType((ConnType)2);
+
+ ConnRef *connRef231 = new ConnRef(router, 231);
+ ConnEnd srcPt231(Point(257.924, 265.557), 15);
+ connRef231->setSourceEndpoint(srcPt231);
+ ConnEnd dstPt231(Point(257.924, 315.557), 15);
+ connRef231->setDestEndpoint(dstPt231);
+ connRef231->setRoutingType((ConnType)2);
+
+ ConnRef *connRef232 = new ConnRef(router, 232);
+ ConnEnd srcPt232(Point(139.924, 367.557), 15);
+ connRef232->setSourceEndpoint(srcPt232);
+ ConnEnd dstPt232(Point(77.9242, 367.557), 15);
+ connRef232->setDestEndpoint(dstPt232);
+ connRef232->setRoutingType((ConnType)2);
+
+ ConnRef *connRef233 = new ConnRef(router, 233);
+ ConnEnd srcPt233(Point(137.924, 477.557), 15);
+ connRef233->setSourceEndpoint(srcPt233);
+ ConnEnd dstPt233(Point(137.924, 527.557), 15);
+ connRef233->setDestEndpoint(dstPt233);
+ connRef233->setRoutingType((ConnType)2);
+
+ ConnRef *connRef234 = new ConnRef(router, 234);
+ ConnEnd srcPt234(Point(137.924, 569.557), 15);
+ connRef234->setSourceEndpoint(srcPt234);
+ ConnEnd dstPt234(Point(137.924, 619.557), 15);
+ connRef234->setDestEndpoint(dstPt234);
+ connRef234->setRoutingType((ConnType)2);
+
+ ConnRef *connRef235 = new ConnRef(router, 235);
+ ConnEnd srcPt235(Point(139.924, 661.557), 15);
+ connRef235->setSourceEndpoint(srcPt235);
+ ConnEnd dstPt235(Point(77.9242, 661.557), 15);
+ connRef235->setDestEndpoint(dstPt235);
+ connRef235->setRoutingType((ConnType)2);
+
+ ConnRef *connRef236 = new ConnRef(router, 236);
+ ConnEnd srcPt236(Point(137.924, 713.557), 15);
+ connRef236->setSourceEndpoint(srcPt236);
+ ConnEnd dstPt236(Point(137.924, 763.557), 15);
+ connRef236->setDestEndpoint(dstPt236);
+ connRef236->setRoutingType((ConnType)2);
+
+ ConnRef *connRef237 = new ConnRef(router, 237);
+ ConnEnd srcPt237(Point(257.924, 713.557), 15);
+ connRef237->setSourceEndpoint(srcPt237);
+ ConnEnd dstPt237(Point(257.924, 763.557), 15);
+ connRef237->setDestEndpoint(dstPt237);
+ connRef237->setRoutingType((ConnType)2);
+
+ ConnRef *connRef238 = new ConnRef(router, 238);
+ ConnEnd srcPt238(Point(377.924, 577.557), 15);
+ connRef238->setSourceEndpoint(srcPt238);
+ ConnEnd dstPt238(Point(377.924, 627.557), 15);
+ connRef238->setDestEndpoint(dstPt238);
+ connRef238->setRoutingType((ConnType)2);
+
+ ConnRef *connRef239 = new ConnRef(router, 239);
+ ConnEnd srcPt239(Point(377.924, 713.557), 15);
+ connRef239->setSourceEndpoint(srcPt239);
+ ConnEnd dstPt239(Point(377.924, 763.557), 15);
+ connRef239->setDestEndpoint(dstPt239);
+ connRef239->setRoutingType((ConnType)2);
+
+ ConnRef *connRef240 = new ConnRef(router, 240);
+ ConnEnd srcPt240(Point(497.924, 713.557), 15);
+ connRef240->setSourceEndpoint(srcPt240);
+ ConnEnd dstPt240(Point(497.924, 763.557), 15);
+ connRef240->setDestEndpoint(dstPt240);
+ connRef240->setRoutingType((ConnType)2);
+
+ ConnRef *connRef241 = new ConnRef(router, 241);
+ ConnEnd srcPt241(Point(617.924, 713.557), 15);
+ connRef241->setSourceEndpoint(srcPt241);
+ ConnEnd dstPt241(Point(617.924, 763.557), 15);
+ connRef241->setDestEndpoint(dstPt241);
+ connRef241->setRoutingType((ConnType)2);
+
+ ConnRef *connRef242 = new ConnRef(router, 242);
+ ConnEnd srcPt242(Point(497.924, 853.057), 15);
+ connRef242->setSourceEndpoint(srcPt242);
+ ConnEnd dstPt242(Point(497.924, 903.057), 15);
+ connRef242->setDestEndpoint(dstPt242);
+ connRef242->setRoutingType((ConnType)2);
+
+ ConnRef *connRef243 = new ConnRef(router, 243);
+ ConnEnd srcPt243(Point(617.924, 853.057), 15);
+ connRef243->setSourceEndpoint(srcPt243);
+ ConnEnd dstPt243(Point(617.924, 903.057), 15);
+ connRef243->setDestEndpoint(dstPt243);
+ connRef243->setRoutingType((ConnType)2);
+
+ ConnRef *connRef244 = new ConnRef(router, 244);
+ ConnEnd srcPt244(Point(377.924, 111.557), 15);
+ connRef244->setSourceEndpoint(srcPt244);
+ ConnEnd dstPt244(Point(377.924, 161.557), 15);
+ connRef244->setDestEndpoint(dstPt244);
+ connRef244->setRoutingType((ConnType)2);
+
+ ConnRef *connRef245 = new ConnRef(router, 245);
+ ConnEnd srcPt245(Point(377.924, -22.6578), 15);
+ connRef245->setSourceEndpoint(srcPt245);
+ ConnEnd dstPt245(Point(377.924, 27.3422), 15);
+ connRef245->setDestEndpoint(dstPt245);
+ connRef245->setRoutingType((ConnType)2);
+
+ ConnRef *connRef246 = new ConnRef(router, 246);
+ ConnEnd srcPt246(Point(497.924, -4.15778), 15);
+ connRef246->setSourceEndpoint(srcPt246);
+ ConnEnd dstPt246(Point(497.924, 45.8422), 15);
+ connRef246->setDestEndpoint(dstPt246);
+ connRef246->setRoutingType((ConnType)2);
+
+ ConnRef *connRef247 = new ConnRef(router, 247);
+ ConnEnd srcPt247(Point(617.924, -4.15778), 15);
+ connRef247->setSourceEndpoint(srcPt247);
+ ConnEnd dstPt247(Point(617.924, 45.8422), 15);
+ connRef247->setDestEndpoint(dstPt247);
+ connRef247->setRoutingType((ConnType)2);
+
+ ConnRef *connRef248 = new ConnRef(router, 248);
+ ConnEnd srcPt248(Point(737.924, 524.057), 15);
+ connRef248->setSourceEndpoint(srcPt248);
+ ConnEnd dstPt248(Point(737.924, 574.057), 15);
+ connRef248->setDestEndpoint(dstPt248);
+ connRef248->setRoutingType((ConnType)2);
+
+ ConnRef *connRef249 = new ConnRef(router, 249);
+ ConnEnd srcPt249(Point(497.924, 477.557), 15);
+ connRef249->setSourceEndpoint(srcPt249);
+ ConnEnd dstPt249(Point(497.924, 527.557), 15);
+ connRef249->setDestEndpoint(dstPt249);
+ connRef249->setRoutingType((ConnType)2);
+
+ ConnRef *connRef250 = new ConnRef(router, 250);
+ ConnEnd srcPt250(Point(497.924, 385.557), 15);
+ connRef250->setSourceEndpoint(srcPt250);
+ ConnEnd dstPt250(Point(497.924, 435.557), 15);
+ connRef250->setDestEndpoint(dstPt250);
+ connRef250->setRoutingType((ConnType)2);
+
+ ConnRef *connRef251 = new ConnRef(router, 251);
+ ConnEnd srcPt251(Point(617.924, 477.557), 15);
+ connRef251->setSourceEndpoint(srcPt251);
+ ConnEnd dstPt251(Point(617.924, 527.557), 15);
+ connRef251->setDestEndpoint(dstPt251);
+ connRef251->setRoutingType((ConnType)2);
+
+ ConnRef *connRef252 = new ConnRef(router, 252);
+ ConnEnd srcPt252(Point(617.924, 385.557), 15);
+ connRef252->setSourceEndpoint(srcPt252);
+ ConnEnd dstPt252(Point(617.924, 435.557), 15);
+ connRef252->setDestEndpoint(dstPt252);
+ connRef252->setRoutingType((ConnType)2);
+
+ ConnRef *connRef253 = new ConnRef(router, 253);
+ ConnEnd srcPt253(Point(857.924, 293.557), 15);
+ connRef253->setSourceEndpoint(srcPt253);
+ ConnEnd dstPt253(Point(857.924, 343.557), 15);
+ connRef253->setDestEndpoint(dstPt253);
+ connRef253->setRoutingType((ConnType)2);
+
+ ConnRef *connRef254 = new ConnRef(router, 254);
+ ConnEnd srcPt254(Point(857.924, 385.557), 15);
+ connRef254->setSourceEndpoint(srcPt254);
+ ConnEnd dstPt254(Point(857.924, 435.557), 15);
+ connRef254->setDestEndpoint(dstPt254);
+ connRef254->setRoutingType((ConnType)2);
+
+ ConnRef *connRef255 = new ConnRef(router, 255);
+ ConnEnd srcPt255(Point(857.924, 111.557), 15);
+ connRef255->setSourceEndpoint(srcPt255);
+ ConnEnd dstPt255(Point(857.924, 161.557), 15);
+ connRef255->setDestEndpoint(dstPt255);
+ connRef255->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/lineSegWrapperCrash2");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash3.cpp b/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash3.cpp
new file mode 100644
index 0000000..36c8d04
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash3.cpp
@@ -0,0 +1,1884 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 0);
+
+ Polygon poly46(4);
+ poly46.ps[0] = Point(577.924, 415.557);
+ poly46.ps[1] = Point(577.924, 455.557);
+ poly46.ps[2] = Point(537.924, 455.557);
+ poly46.ps[3] = Point(537.924, 415.557);
+ new ShapeRef(router, poly46, 46);
+
+ Polygon poly69(4);
+ poly69.ps[0] = Point(267.924, 151.557);
+ poly69.ps[1] = Point(267.924, 171.557);
+ poly69.ps[2] = Point(247.924, 171.557);
+ poly69.ps[3] = Point(247.924, 151.557);
+ new ShapeRef(router, poly69, 69);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(1278.92, -22.1578);
+ poly3.ps[1] = Point(1278.92, 17.8422);
+ poly3.ps[2] = Point(1238.92, 17.8422);
+ poly3.ps[3] = Point(1238.92, -22.1578);
+ new ShapeRef(router, poly3, 3);
+
+ Polygon poly1(4);
+ poly1.ps[0] = Point(817.924, 840.057);
+ poly1.ps[1] = Point(817.924, 880.057);
+ poly1.ps[2] = Point(777.924, 880.057);
+ poly1.ps[3] = Point(777.924, 840.057);
+ new ShapeRef(router, poly1, 1);
+
+ Polygon poly117(4);
+ poly117.ps[0] = Point(285.924, 693.557);
+ poly117.ps[1] = Point(285.924, 733.557);
+ poly117.ps[2] = Point(229.924, 733.557);
+ poly117.ps[3] = Point(229.924, 693.557);
+ new ShapeRef(router, poly117, 117);
+
+ Polygon poly118(4);
+ poly118.ps[0] = Point(405.924, 557.557);
+ poly118.ps[1] = Point(405.924, 597.557);
+ poly118.ps[2] = Point(349.924, 597.557);
+ poly118.ps[3] = Point(349.924, 557.557);
+ new ShapeRef(router, poly118, 118);
+
+ Polygon poly119(4);
+ poly119.ps[0] = Point(405.924, 693.557);
+ poly119.ps[1] = Point(405.924, 733.557);
+ poly119.ps[2] = Point(349.924, 733.557);
+ poly119.ps[3] = Point(349.924, 693.557);
+ new ShapeRef(router, poly119, 119);
+
+ Polygon poly120(4);
+ poly120.ps[0] = Point(525.924, 693.557);
+ poly120.ps[1] = Point(525.924, 733.557);
+ poly120.ps[2] = Point(469.924, 733.557);
+ poly120.ps[3] = Point(469.924, 693.557);
+ new ShapeRef(router, poly120, 120);
+
+ Polygon poly121(4);
+ poly121.ps[0] = Point(645.924, 693.557);
+ poly121.ps[1] = Point(645.924, 733.557);
+ poly121.ps[2] = Point(589.924, 733.557);
+ poly121.ps[3] = Point(589.924, 693.557);
+ new ShapeRef(router, poly121, 121);
+
+ Polygon poly122(4);
+ poly122.ps[0] = Point(525.924, 833.057);
+ poly122.ps[1] = Point(525.924, 873.057);
+ poly122.ps[2] = Point(469.924, 873.057);
+ poly122.ps[3] = Point(469.924, 833.057);
+ new ShapeRef(router, poly122, 122);
+
+ Polygon poly123(4);
+ poly123.ps[0] = Point(645.924, 833.057);
+ poly123.ps[1] = Point(645.924, 873.057);
+ poly123.ps[2] = Point(589.924, 873.057);
+ poly123.ps[3] = Point(589.924, 833.057);
+ new ShapeRef(router, poly123, 123);
+
+ Polygon poly124(4);
+ poly124.ps[0] = Point(405.924, 91.5565);
+ poly124.ps[1] = Point(405.924, 131.557);
+ poly124.ps[2] = Point(349.924, 131.557);
+ poly124.ps[3] = Point(349.924, 91.5565);
+ new ShapeRef(router, poly124, 124);
+
+ Polygon poly125(4);
+ poly125.ps[0] = Point(405.924, -42.6578);
+ poly125.ps[1] = Point(405.924, -2.65778);
+ poly125.ps[2] = Point(349.924, -2.65778);
+ poly125.ps[3] = Point(349.924, -42.6578);
+ new ShapeRef(router, poly125, 125);
+
+ Polygon poly126(4);
+ poly126.ps[0] = Point(525.924, -24.1578);
+ poly126.ps[1] = Point(525.924, 15.8422);
+ poly126.ps[2] = Point(469.924, 15.8422);
+ poly126.ps[3] = Point(469.924, -24.1578);
+ new ShapeRef(router, poly126, 126);
+
+ Polygon poly127(4);
+ poly127.ps[0] = Point(645.924, -24.1578);
+ poly127.ps[1] = Point(645.924, 15.8422);
+ poly127.ps[2] = Point(589.924, 15.8422);
+ poly127.ps[3] = Point(589.924, -24.1578);
+ new ShapeRef(router, poly127, 127);
+
+ Polygon poly128(4);
+ poly128.ps[0] = Point(765.924, 504.057);
+ poly128.ps[1] = Point(765.924, 544.057);
+ poly128.ps[2] = Point(709.924, 544.057);
+ poly128.ps[3] = Point(709.924, 504.057);
+ new ShapeRef(router, poly128, 128);
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(1371.92, -80.6578);
+ poly6.ps[1] = Point(1371.92, -40.6578);
+ poly6.ps[2] = Point(1331.92, -40.6578);
+ poly6.ps[3] = Point(1331.92, -80.6578);
+ new ShapeRef(router, poly6, 6);
+
+ Polygon poly52(4);
+ poly52.ps[0] = Point(217.924, 295.557);
+ poly52.ps[1] = Point(217.924, 335.557);
+ poly52.ps[2] = Point(177.924, 335.557);
+ poly52.ps[3] = Point(177.924, 295.557);
+ new ShapeRef(router, poly52, 52);
+
+ Polygon poly65(4);
+ poly65.ps[0] = Point(97.9242, 599.557);
+ poly65.ps[1] = Point(97.9242, 639.557);
+ poly65.ps[2] = Point(57.9242, 639.557);
+ poly65.ps[3] = Point(57.9242, 599.557);
+ new ShapeRef(router, poly65, 65);
+
+ Polygon poly56(4);
+ poly56.ps[0] = Point(457.924, -44.6578);
+ poly56.ps[1] = Point(457.924, -4.65778);
+ poly56.ps[2] = Point(417.924, -4.65778);
+ poly56.ps[3] = Point(417.924, -44.6578);
+ new ShapeRef(router, poly56, 56);
+
+ Polygon poly96(4);
+ poly96.ps[0] = Point(747.924, 333.557);
+ poly96.ps[1] = Point(747.924, 353.557);
+ poly96.ps[2] = Point(727.924, 353.557);
+ poly96.ps[3] = Point(727.924, 333.557);
+ new ShapeRef(router, poly96, 96);
+
+ Polygon poly97(4);
+ poly97.ps[0] = Point(1088.92, 378.557);
+ poly97.ps[1] = Point(1088.92, 398.557);
+ poly97.ps[2] = Point(1068.92, 398.557);
+ poly97.ps[3] = Point(1068.92, 378.557);
+ new ShapeRef(router, poly97, 97);
+
+ Polygon poly98(4);
+ poly98.ps[0] = Point(1208.92, 378.557);
+ poly98.ps[1] = Point(1208.92, 398.557);
+ poly98.ps[2] = Point(1188.92, 398.557);
+ poly98.ps[3] = Point(1188.92, 378.557);
+ new ShapeRef(router, poly98, 98);
+
+ Polygon poly99(4);
+ poly99.ps[0] = Point(1088.92, 142.342);
+ poly99.ps[1] = Point(1088.92, 162.342);
+ poly99.ps[2] = Point(1068.92, 162.342);
+ poly99.ps[3] = Point(1068.92, 142.342);
+ new ShapeRef(router, poly99, 99);
+
+ Polygon poly100(4);
+ poly100.ps[0] = Point(1088.92, 50.3422);
+ poly100.ps[1] = Point(1088.92, 70.3422);
+ poly100.ps[2] = Point(1068.92, 70.3422);
+ poly100.ps[3] = Point(1068.92, 50.3422);
+ new ShapeRef(router, poly100, 100);
+
+ Polygon poly101(4);
+ poly101.ps[0] = Point(1208.92, 142.342);
+ poly101.ps[1] = Point(1208.92, 162.342);
+ poly101.ps[2] = Point(1188.92, 162.342);
+ poly101.ps[3] = Point(1188.92, 142.342);
+ new ShapeRef(router, poly101, 101);
+
+ Polygon poly102(4);
+ poly102.ps[0] = Point(1088.92, -70.6578);
+ poly102.ps[1] = Point(1088.92, -50.6578);
+ poly102.ps[2] = Point(1068.92, -50.6578);
+ poly102.ps[3] = Point(1068.92, -70.6578);
+ new ShapeRef(router, poly102, 102);
+
+ Polygon poly103(4);
+ poly103.ps[0] = Point(968.924, 270.557);
+ poly103.ps[1] = Point(968.924, 290.557);
+ poly103.ps[2] = Point(948.924, 290.557);
+ poly103.ps[3] = Point(948.924, 270.557);
+ new ShapeRef(router, poly103, 103);
+
+ Polygon poly104(4);
+ poly104.ps[0] = Point(747.924, 151.557);
+ poly104.ps[1] = Point(747.924, 171.557);
+ poly104.ps[2] = Point(727.924, 171.557);
+ poly104.ps[3] = Point(727.924, 151.557);
+ new ShapeRef(router, poly104, 104);
+
+ Polygon poly143(4);
+ poly143.ps[0] = Point(986.924, 210.557);
+ poly143.ps[1] = Point(986.924, 250.557);
+ poly143.ps[2] = Point(930.924, 250.557);
+ poly143.ps[3] = Point(930.924, 210.557);
+ new ShapeRef(router, poly143, 143);
+
+ Polygon poly144(4);
+ poly144.ps[0] = Point(765.924, 91.5565);
+ poly144.ps[1] = Point(765.924, 131.557);
+ poly144.ps[2] = Point(709.924, 131.557);
+ poly144.ps[3] = Point(709.924, 91.5565);
+ new ShapeRef(router, poly144, 144);
+
+ Polygon poly145(4);
+ poly145.ps[0] = Point(765.924, 790.057);
+ poly145.ps[1] = Point(765.924, 830.057);
+ poly145.ps[2] = Point(709.924, 830.057);
+ poly145.ps[3] = Point(709.924, 790.057);
+ new ShapeRef(router, poly145, 145);
+
+ Polygon poly146(4);
+ poly146.ps[0] = Point(45.9242, 232.5);
+ poly146.ps[1] = Point(45.9242, 272.5);
+ poly146.ps[2] = Point(-14.0758, 272.5);
+ poly146.ps[3] = Point(-14.0758, 232.5);
+ new ShapeRef(router, poly146, 146);
+
+ Polygon poly147(4);
+ poly147.ps[0] = Point(-26.0758, 274.75);
+ poly147.ps[1] = Point(-26.0758, 334.75);
+ poly147.ps[2] = Point(-66.0758, 334.75);
+ poly147.ps[3] = Point(-66.0758, 274.75);
+ new ShapeRef(router, poly147, 147);
+
+ Polygon poly60(4);
+ poly60.ps[0] = Point(937.924, 1.84222);
+ poly60.ps[1] = Point(937.924, 41.8422);
+ poly60.ps[2] = Point(897.924, 41.8422);
+ poly60.ps[3] = Point(897.924, 1.84222);
+ new ShapeRef(router, poly60, 60);
+
+ Polygon poly61(4);
+ poly61.ps[0] = Point(577.924, -44.6578);
+ poly61.ps[1] = Point(577.924, -4.65778);
+ poly61.ps[2] = Point(537.924, -4.65778);
+ poly61.ps[3] = Point(537.924, -44.6578);
+ new ShapeRef(router, poly61, 61);
+
+ Polygon poly26(4);
+ poly26.ps[0] = Point(697.924, 743.557);
+ poly26.ps[1] = Point(697.924, 783.557);
+ poly26.ps[2] = Point(657.924, 783.557);
+ poly26.ps[3] = Point(657.924, 743.557);
+ new ShapeRef(router, poly26, 26);
+
+ Polygon poly11(4);
+ poly11.ps[0] = Point(817.924, -80.6578);
+ poly11.ps[1] = Point(817.924, -40.6578);
+ poly11.ps[2] = Point(777.924, -40.6578);
+ poly11.ps[3] = Point(777.924, -80.6578);
+ new ShapeRef(router, poly11, 11);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(1371.92, -22.1578);
+ poly5.ps[1] = Point(1371.92, 17.8422);
+ poly5.ps[2] = Point(1331.92, 17.8422);
+ poly5.ps[3] = Point(1331.92, -22.1578);
+ new ShapeRef(router, poly5, 5);
+
+ Polygon poly13(4);
+ poly13.ps[0] = Point(1158.92, 323.557);
+ poly13.ps[1] = Point(1158.92, 363.557);
+ poly13.ps[2] = Point(1118.92, 363.557);
+ poly13.ps[3] = Point(1118.92, 323.557);
+ new ShapeRef(router, poly13, 13);
+
+ Polygon poly45(4);
+ poly45.ps[0] = Point(577.924, 34.8422);
+ poly45.ps[1] = Point(577.924, 74.8422);
+ poly45.ps[2] = Point(537.924, 74.8422);
+ poly45.ps[3] = Point(537.924, 34.8422);
+ new ShapeRef(router, poly45, 45);
+
+ Polygon poly55(4);
+ poly55.ps[0] = Point(457.924, 7.34222);
+ poly55.ps[1] = Point(457.924, 47.3422);
+ poly55.ps[2] = Point(417.924, 47.3422);
+ poly55.ps[3] = Point(417.924, 7.34222);
+ new ShapeRef(router, poly55, 55);
+
+ Polygon poly50(4);
+ poly50.ps[0] = Point(272.5, -82.1578);
+ poly50.ps[1] = Point(272.5, -47.1578);
+ poly50.ps[2] = Point(35.5, -47.1578);
+ poly50.ps[3] = Point(35.5, -82.1578);
+ new ShapeRef(router, poly50, 50);
+
+ Polygon poly70(4);
+ poly70.ps[0] = Point(207.924, 203.557);
+ poly70.ps[1] = Point(207.924, 223.557);
+ poly70.ps[2] = Point(187.924, 223.557);
+ poly70.ps[3] = Point(187.924, 203.557);
+ new ShapeRef(router, poly70, 70);
+
+ Polygon poly71(4);
+ poly71.ps[0] = Point(267.924, 305.557);
+ poly71.ps[1] = Point(267.924, 325.557);
+ poly71.ps[2] = Point(247.924, 325.557);
+ poly71.ps[3] = Point(247.924, 305.557);
+ new ShapeRef(router, poly71, 71);
+
+ Polygon poly75(4);
+ poly75.ps[0] = Point(87.9242, 651.557);
+ poly75.ps[1] = Point(87.9242, 671.557);
+ poly75.ps[2] = Point(67.9242, 671.557);
+ poly75.ps[3] = Point(67.9242, 651.557);
+ new ShapeRef(router, poly75, 75);
+
+ Polygon poly76(4);
+ poly76.ps[0] = Point(147.924, 753.557);
+ poly76.ps[1] = Point(147.924, 773.557);
+ poly76.ps[2] = Point(127.924, 773.557);
+ poly76.ps[3] = Point(127.924, 753.557);
+ new ShapeRef(router, poly76, 76);
+
+ Polygon poly77(4);
+ poly77.ps[0] = Point(267.924, 753.557);
+ poly77.ps[1] = Point(267.924, 773.557);
+ poly77.ps[2] = Point(247.924, 773.557);
+ poly77.ps[3] = Point(247.924, 753.557);
+ new ShapeRef(router, poly77, 77);
+
+ Polygon poly78(4);
+ poly78.ps[0] = Point(387.924, 617.557);
+ poly78.ps[1] = Point(387.924, 637.557);
+ poly78.ps[2] = Point(367.924, 637.557);
+ poly78.ps[3] = Point(367.924, 617.557);
+ new ShapeRef(router, poly78, 78);
+
+ Polygon poly79(4);
+ poly79.ps[0] = Point(387.924, 753.557);
+ poly79.ps[1] = Point(387.924, 773.557);
+ poly79.ps[2] = Point(367.924, 773.557);
+ poly79.ps[3] = Point(367.924, 753.557);
+ new ShapeRef(router, poly79, 79);
+
+ Polygon poly80(4);
+ poly80.ps[0] = Point(507.924, 753.557);
+ poly80.ps[1] = Point(507.924, 773.557);
+ poly80.ps[2] = Point(487.924, 773.557);
+ poly80.ps[3] = Point(487.924, 753.557);
+ new ShapeRef(router, poly80, 80);
+
+ Polygon poly81(4);
+ poly81.ps[0] = Point(627.924, 753.557);
+ poly81.ps[1] = Point(627.924, 773.557);
+ poly81.ps[2] = Point(607.924, 773.557);
+ poly81.ps[3] = Point(607.924, 753.557);
+ new ShapeRef(router, poly81, 81);
+
+ Polygon poly82(4);
+ poly82.ps[0] = Point(507.924, 893.057);
+ poly82.ps[1] = Point(507.924, 913.057);
+ poly82.ps[2] = Point(487.924, 913.057);
+ poly82.ps[3] = Point(487.924, 893.057);
+ new ShapeRef(router, poly82, 82);
+
+ Polygon poly83(4);
+ poly83.ps[0] = Point(627.924, 893.057);
+ poly83.ps[1] = Point(627.924, 913.057);
+ poly83.ps[2] = Point(607.924, 913.057);
+ poly83.ps[3] = Point(607.924, 893.057);
+ new ShapeRef(router, poly83, 83);
+
+ Polygon poly84(4);
+ poly84.ps[0] = Point(387.924, 151.557);
+ poly84.ps[1] = Point(387.924, 171.557);
+ poly84.ps[2] = Point(367.924, 171.557);
+ poly84.ps[3] = Point(367.924, 151.557);
+ new ShapeRef(router, poly84, 84);
+
+ Polygon poly85(4);
+ poly85.ps[0] = Point(387.924, 17.3422);
+ poly85.ps[1] = Point(387.924, 37.3422);
+ poly85.ps[2] = Point(367.924, 37.3422);
+ poly85.ps[3] = Point(367.924, 17.3422);
+ new ShapeRef(router, poly85, 85);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(577.924, 795.557);
+ poly2.ps[1] = Point(577.924, 835.557);
+ poly2.ps[2] = Point(537.924, 835.557);
+ poly2.ps[3] = Point(537.924, 795.557);
+ new ShapeRef(router, poly2, 2);
+
+ Polygon poly17(4);
+ poly17.ps[0] = Point(577.924, 883.057);
+ poly17.ps[1] = Point(577.924, 923.057);
+ poly17.ps[2] = Point(537.924, 923.057);
+ poly17.ps[3] = Point(537.924, 883.057);
+ new ShapeRef(router, poly17, 17);
+
+ Polygon poly25(4);
+ poly25.ps[0] = Point(697.924, 883.057);
+ poly25.ps[1] = Point(697.924, 923.057);
+ poly25.ps[2] = Point(657.924, 923.057);
+ poly25.ps[3] = Point(657.924, 883.057);
+ new ShapeRef(router, poly25, 25);
+
+ Polygon poly59(4);
+ poly59.ps[0] = Point(937.924, 323.557);
+ poly59.ps[1] = Point(937.924, 363.557);
+ poly59.ps[2] = Point(897.924, 363.557);
+ poly59.ps[3] = Point(897.924, 323.557);
+ new ShapeRef(router, poly59, 59);
+
+ Polygon poly42(4);
+ poly42.ps[0] = Point(697.924, 415.557);
+ poly42.ps[1] = Point(697.924, 455.557);
+ poly42.ps[2] = Point(657.924, 455.557);
+ poly42.ps[3] = Point(657.924, 415.557);
+ new ShapeRef(router, poly42, 42);
+
+ Polygon poly57(4);
+ poly57.ps[0] = Point(817.924, 141.557);
+ poly57.ps[1] = Point(817.924, 181.557);
+ poly57.ps[2] = Point(777.924, 181.557);
+ poly57.ps[3] = Point(777.924, 141.557);
+ new ShapeRef(router, poly57, 57);
+
+ Polygon poly62(4);
+ poly62.ps[0] = Point(577.924, 629.557);
+ poly62.ps[1] = Point(577.924, 669.557);
+ poly62.ps[2] = Point(537.924, 669.557);
+ poly62.ps[3] = Point(537.924, 629.557);
+ new ShapeRef(router, poly62, 62);
+
+ Polygon poly34(4);
+ poly34.ps[0] = Point(1278.92, 323.557);
+ poly34.ps[1] = Point(1278.92, 363.557);
+ poly34.ps[2] = Point(1238.92, 363.557);
+ poly34.ps[3] = Point(1238.92, 323.557);
+ new ShapeRef(router, poly34, 34);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(937.924, -80.6578);
+ poly10.ps[1] = Point(937.924, -40.6578);
+ poly10.ps[2] = Point(897.924, -40.6578);
+ poly10.ps[3] = Point(897.924, -80.6578);
+ new ShapeRef(router, poly10, 10);
+
+ Polygon poly18(4);
+ poly18.ps[0] = Point(217.924, 743.557);
+ poly18.ps[1] = Point(217.924, 783.557);
+ poly18.ps[2] = Point(177.924, 783.557);
+ poly18.ps[3] = Point(177.924, 743.557);
+ new ShapeRef(router, poly18, 18);
+
+ Polygon poly41(4);
+ poly41.ps[0] = Point(577.924, 743.557);
+ poly41.ps[1] = Point(577.924, 783.557);
+ poly41.ps[2] = Point(537.924, 783.557);
+ poly41.ps[3] = Point(537.924, 743.557);
+ new ShapeRef(router, poly41, 41);
+
+ Polygon poly30(4);
+ poly30.ps[0] = Point(1278.92, 415.557);
+ poly30.ps[1] = Point(1278.92, 455.557);
+ poly30.ps[2] = Point(1238.92, 455.557);
+ poly30.ps[3] = Point(1238.92, 415.557);
+ new ShapeRef(router, poly30, 30);
+
+ Polygon poly28(4);
+ poly28.ps[0] = Point(817.924, 323.557);
+ poly28.ps[1] = Point(817.924, 363.557);
+ poly28.ps[2] = Point(777.924, 363.557);
+ poly28.ps[3] = Point(777.924, 323.557);
+ new ShapeRef(router, poly28, 28);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(1278.92, -80.6578);
+ poly7.ps[1] = Point(1278.92, -40.6578);
+ poly7.ps[2] = Point(1238.92, -40.6578);
+ poly7.ps[3] = Point(1238.92, -80.6578);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly86(4);
+ poly86.ps[0] = Point(507.924, 35.8422);
+ poly86.ps[1] = Point(507.924, 55.8422);
+ poly86.ps[2] = Point(487.924, 55.8422);
+ poly86.ps[3] = Point(487.924, 35.8422);
+ new ShapeRef(router, poly86, 86);
+
+ Polygon poly87(4);
+ poly87.ps[0] = Point(627.924, 35.8422);
+ poly87.ps[1] = Point(627.924, 55.8422);
+ poly87.ps[2] = Point(607.924, 55.8422);
+ poly87.ps[3] = Point(607.924, 35.8422);
+ new ShapeRef(router, poly87, 87);
+
+ Polygon poly88(4);
+ poly88.ps[0] = Point(747.924, 564.057);
+ poly88.ps[1] = Point(747.924, 584.057);
+ poly88.ps[2] = Point(727.924, 584.057);
+ poly88.ps[3] = Point(727.924, 564.057);
+ new ShapeRef(router, poly88, 88);
+
+ Polygon poly89(4);
+ poly89.ps[0] = Point(507.924, 517.557);
+ poly89.ps[1] = Point(507.924, 537.557);
+ poly89.ps[2] = Point(487.924, 537.557);
+ poly89.ps[3] = Point(487.924, 517.557);
+ new ShapeRef(router, poly89, 89);
+
+ Polygon poly90(4);
+ poly90.ps[0] = Point(507.924, 425.557);
+ poly90.ps[1] = Point(507.924, 445.557);
+ poly90.ps[2] = Point(487.924, 445.557);
+ poly90.ps[3] = Point(487.924, 425.557);
+ new ShapeRef(router, poly90, 90);
+
+ Polygon poly91(4);
+ poly91.ps[0] = Point(627.924, 517.557);
+ poly91.ps[1] = Point(627.924, 537.557);
+ poly91.ps[2] = Point(607.924, 537.557);
+ poly91.ps[3] = Point(607.924, 517.557);
+ new ShapeRef(router, poly91, 91);
+
+ Polygon poly92(4);
+ poly92.ps[0] = Point(627.924, 425.557);
+ poly92.ps[1] = Point(627.924, 445.557);
+ poly92.ps[2] = Point(607.924, 445.557);
+ poly92.ps[3] = Point(607.924, 425.557);
+ new ShapeRef(router, poly92, 92);
+
+ Polygon poly93(4);
+ poly93.ps[0] = Point(867.924, 333.557);
+ poly93.ps[1] = Point(867.924, 353.557);
+ poly93.ps[2] = Point(847.924, 353.557);
+ poly93.ps[3] = Point(847.924, 333.557);
+ new ShapeRef(router, poly93, 93);
+
+ Polygon poly94(4);
+ poly94.ps[0] = Point(867.924, 425.557);
+ poly94.ps[1] = Point(867.924, 445.557);
+ poly94.ps[2] = Point(847.924, 445.557);
+ poly94.ps[3] = Point(847.924, 425.557);
+ new ShapeRef(router, poly94, 94);
+
+ Polygon poly95(4);
+ poly95.ps[0] = Point(867.924, 151.557);
+ poly95.ps[1] = Point(867.924, 171.557);
+ poly95.ps[2] = Point(847.924, 171.557);
+ poly95.ps[3] = Point(847.924, 151.557);
+ new ShapeRef(router, poly95, 95);
+
+ Polygon poly72(4);
+ poly72.ps[0] = Point(87.9242, 357.557);
+ poly72.ps[1] = Point(87.9242, 377.557);
+ poly72.ps[2] = Point(67.9242, 377.557);
+ poly72.ps[3] = Point(67.9242, 357.557);
+ new ShapeRef(router, poly72, 72);
+
+ Polygon poly73(4);
+ poly73.ps[0] = Point(147.924, 517.557);
+ poly73.ps[1] = Point(147.924, 537.557);
+ poly73.ps[2] = Point(127.924, 537.557);
+ poly73.ps[3] = Point(127.924, 517.557);
+ new ShapeRef(router, poly73, 73);
+
+ Polygon poly74(4);
+ poly74.ps[0] = Point(147.924, 609.557);
+ poly74.ps[1] = Point(147.924, 629.557);
+ poly74.ps[2] = Point(127.924, 629.557);
+ poly74.ps[3] = Point(127.924, 609.557);
+ new ShapeRef(router, poly74, 74);
+
+ Polygon poly36(4);
+ poly36.ps[0] = Point(697.924, 507.557);
+ poly36.ps[1] = Point(697.924, 547.557);
+ poly36.ps[2] = Point(657.924, 547.557);
+ poly36.ps[3] = Point(657.924, 507.557);
+ new ShapeRef(router, poly36, 36);
+
+ Polygon poly129(4);
+ poly129.ps[0] = Point(525.924, 457.557);
+ poly129.ps[1] = Point(525.924, 497.557);
+ poly129.ps[2] = Point(469.924, 497.557);
+ poly129.ps[3] = Point(469.924, 457.557);
+ new ShapeRef(router, poly129, 129);
+
+ Polygon poly130(4);
+ poly130.ps[0] = Point(525.924, 365.557);
+ poly130.ps[1] = Point(525.924, 405.557);
+ poly130.ps[2] = Point(469.924, 405.557);
+ poly130.ps[3] = Point(469.924, 365.557);
+ new ShapeRef(router, poly130, 130);
+
+ Polygon poly131(4);
+ poly131.ps[0] = Point(645.924, 457.557);
+ poly131.ps[1] = Point(645.924, 497.557);
+ poly131.ps[2] = Point(589.924, 497.557);
+ poly131.ps[3] = Point(589.924, 457.557);
+ new ShapeRef(router, poly131, 131);
+
+ Polygon poly132(4);
+ poly132.ps[0] = Point(645.924, 365.557);
+ poly132.ps[1] = Point(645.924, 405.557);
+ poly132.ps[2] = Point(589.924, 405.557);
+ poly132.ps[3] = Point(589.924, 365.557);
+ new ShapeRef(router, poly132, 132);
+
+ Polygon poly133(4);
+ poly133.ps[0] = Point(885.924, 273.557);
+ poly133.ps[1] = Point(885.924, 313.557);
+ poly133.ps[2] = Point(829.924, 313.557);
+ poly133.ps[3] = Point(829.924, 273.557);
+ new ShapeRef(router, poly133, 133);
+
+ Polygon poly134(4);
+ poly134.ps[0] = Point(885.924, 365.557);
+ poly134.ps[1] = Point(885.924, 405.557);
+ poly134.ps[2] = Point(829.924, 405.557);
+ poly134.ps[3] = Point(829.924, 365.557);
+ new ShapeRef(router, poly134, 134);
+
+ Polygon poly135(4);
+ poly135.ps[0] = Point(885.924, 91.5565);
+ poly135.ps[1] = Point(885.924, 131.557);
+ poly135.ps[2] = Point(829.924, 131.557);
+ poly135.ps[3] = Point(829.924, 91.5565);
+ new ShapeRef(router, poly135, 135);
+
+ Polygon poly136(4);
+ poly136.ps[0] = Point(765.924, 273.557);
+ poly136.ps[1] = Point(765.924, 313.557);
+ poly136.ps[2] = Point(709.924, 313.557);
+ poly136.ps[3] = Point(709.924, 273.557);
+ new ShapeRef(router, poly136, 136);
+
+ Polygon poly137(4);
+ poly137.ps[0] = Point(1106.92, 318.557);
+ poly137.ps[1] = Point(1106.92, 358.557);
+ poly137.ps[2] = Point(1050.92, 358.557);
+ poly137.ps[3] = Point(1050.92, 318.557);
+ new ShapeRef(router, poly137, 137);
+
+ Polygon poly138(4);
+ poly138.ps[0] = Point(1226.92, 318.557);
+ poly138.ps[1] = Point(1226.92, 358.557);
+ poly138.ps[2] = Point(1170.92, 358.557);
+ poly138.ps[3] = Point(1170.92, 318.557);
+ new ShapeRef(router, poly138, 138);
+
+ Polygon poly139(4);
+ poly139.ps[0] = Point(1106.92, 82.3422);
+ poly139.ps[1] = Point(1106.92, 122.342);
+ poly139.ps[2] = Point(1050.92, 122.342);
+ poly139.ps[3] = Point(1050.92, 82.3422);
+ new ShapeRef(router, poly139, 139);
+
+ Polygon poly140(4);
+ poly140.ps[0] = Point(1106.92, -9.65778);
+ poly140.ps[1] = Point(1106.92, 30.3422);
+ poly140.ps[2] = Point(1050.92, 30.3422);
+ poly140.ps[3] = Point(1050.92, -9.65778);
+ new ShapeRef(router, poly140, 140);
+
+ Polygon poly141(4);
+ poly141.ps[0] = Point(1226.92, 82.3422);
+ poly141.ps[1] = Point(1226.92, 122.342);
+ poly141.ps[2] = Point(1170.92, 122.342);
+ poly141.ps[3] = Point(1170.92, 82.3422);
+ new ShapeRef(router, poly141, 141);
+
+ Polygon poly142(4);
+ poly142.ps[0] = Point(1106.92, -130.658);
+ poly142.ps[1] = Point(1106.92, -90.6578);
+ poly142.ps[2] = Point(1050.92, -90.6578);
+ poly142.ps[3] = Point(1050.92, -130.658);
+ new ShapeRef(router, poly142, 142);
+
+ Polygon poly27(4);
+ poly27.ps[0] = Point(577.924, 507.557);
+ poly27.ps[1] = Point(577.924, 547.557);
+ poly27.ps[2] = Point(537.924, 547.557);
+ poly27.ps[3] = Point(537.924, 507.557);
+ new ShapeRef(router, poly27, 27);
+
+ Polygon poly47(4);
+ poly47.ps[0] = Point(697.924, 271.557);
+ poly47.ps[1] = Point(697.924, 311.557);
+ poly47.ps[2] = Point(657.924, 311.557);
+ poly47.ps[3] = Point(657.924, 271.557);
+ new ShapeRef(router, poly47, 47);
+
+ Polygon poly22(4);
+ poly22.ps[0] = Point(697.924, 34.8422);
+ poly22.ps[1] = Point(697.924, 74.8422);
+ poly22.ps[2] = Point(657.924, 74.8422);
+ poly22.ps[3] = Point(657.924, 34.8422);
+ new ShapeRef(router, poly22, 22);
+
+ Polygon poly66(4);
+ poly66.ps[0] = Point(747.924, -70.6578);
+ poly66.ps[1] = Point(747.924, -50.6578);
+ poly66.ps[2] = Point(727.924, -50.6578);
+ poly66.ps[3] = Point(727.924, -70.6578);
+ new ShapeRef(router, poly66, 66);
+
+ Polygon poly49(4);
+ poly49.ps[0] = Point(45.9242, 169.75);
+ poly49.ps[1] = Point(45.9242, 334.75);
+ poly49.ps[2] = Point(-242.076, 334.75);
+ poly49.ps[3] = Point(-242.076, 169.75);
+ new ShapeRef(router, poly49, 49);
+
+ Polygon poly32(4);
+ poly32.ps[0] = Point(1038.92, 141.557);
+ poly32.ps[1] = Point(1038.92, 181.557);
+ poly32.ps[2] = Point(998.924, 181.557);
+ poly32.ps[3] = Point(998.924, 141.557);
+ new ShapeRef(router, poly32, 32);
+
+ Polygon poly105(4);
+ poly105.ps[0] = Point(747.924, 850.057);
+ poly105.ps[1] = Point(747.924, 870.057);
+ poly105.ps[2] = Point(727.924, 870.057);
+ poly105.ps[3] = Point(727.924, 850.057);
+ new ShapeRef(router, poly105, 105);
+
+ Polygon poly106(4);
+ poly106.ps[0] = Point(765.924, -130.658);
+ poly106.ps[1] = Point(765.924, -90.6578);
+ poly106.ps[2] = Point(709.924, -90.6578);
+ poly106.ps[3] = Point(709.924, -130.658);
+ new ShapeRef(router, poly106, 106);
+
+ Polygon poly107(4);
+ poly107.ps[0] = Point(165.924, -35.1578);
+ poly107.ps[1] = Point(165.924, 4.84222);
+ poly107.ps[2] = Point(109.924, 4.84222);
+ poly107.ps[3] = Point(109.924, -35.1578);
+ new ShapeRef(router, poly107, 107);
+
+ Polygon poly108(4);
+ poly108.ps[0] = Point(165.924, 91.5565);
+ poly108.ps[1] = Point(165.924, 131.557);
+ poly108.ps[2] = Point(109.924, 131.557);
+ poly108.ps[3] = Point(109.924, 91.5565);
+ new ShapeRef(router, poly108, 108);
+
+ Polygon poly109(4);
+ poly109.ps[0] = Point(285.924, 91.5565);
+ poly109.ps[1] = Point(285.924, 131.557);
+ poly109.ps[2] = Point(229.924, 131.557);
+ poly109.ps[3] = Point(229.924, 91.5565);
+ new ShapeRef(router, poly109, 109);
+
+ Polygon poly110(4);
+ poly110.ps[0] = Point(287.924, 193.557);
+ poly110.ps[1] = Point(287.924, 233.557);
+ poly110.ps[2] = Point(231.924, 233.557);
+ poly110.ps[3] = Point(231.924, 193.557);
+ new ShapeRef(router, poly110, 110);
+
+ Polygon poly111(4);
+ poly111.ps[0] = Point(285.924, 245.557);
+ poly111.ps[1] = Point(285.924, 285.557);
+ poly111.ps[2] = Point(229.924, 285.557);
+ poly111.ps[3] = Point(229.924, 245.557);
+ new ShapeRef(router, poly111, 111);
+
+ Polygon poly112(4);
+ poly112.ps[0] = Point(167.924, 347.557);
+ poly112.ps[1] = Point(167.924, 387.557);
+ poly112.ps[2] = Point(111.924, 387.557);
+ poly112.ps[3] = Point(111.924, 347.557);
+ new ShapeRef(router, poly112, 112);
+
+ Polygon poly113(4);
+ poly113.ps[0] = Point(165.924, 457.557);
+ poly113.ps[1] = Point(165.924, 497.557);
+ poly113.ps[2] = Point(109.924, 497.557);
+ poly113.ps[3] = Point(109.924, 457.557);
+ new ShapeRef(router, poly113, 113);
+
+ Polygon poly114(4);
+ poly114.ps[0] = Point(165.924, 549.557);
+ poly114.ps[1] = Point(165.924, 589.557);
+ poly114.ps[2] = Point(109.924, 589.557);
+ poly114.ps[3] = Point(109.924, 549.557);
+ new ShapeRef(router, poly114, 114);
+
+ Polygon poly115(4);
+ poly115.ps[0] = Point(167.924, 641.557);
+ poly115.ps[1] = Point(167.924, 681.557);
+ poly115.ps[2] = Point(111.924, 681.557);
+ poly115.ps[3] = Point(111.924, 641.557);
+ new ShapeRef(router, poly115, 115);
+
+ Polygon poly116(4);
+ poly116.ps[0] = Point(165.924, 693.557);
+ poly116.ps[1] = Point(165.924, 733.557);
+ poly116.ps[2] = Point(109.924, 733.557);
+ poly116.ps[3] = Point(109.924, 693.557);
+ new ShapeRef(router, poly116, 116);
+
+ Polygon poly31(4);
+ poly31.ps[0] = Point(1278.92, 141.557);
+ poly31.ps[1] = Point(1278.92, 181.557);
+ poly31.ps[2] = Point(1238.92, 181.557);
+ poly31.ps[3] = Point(1238.92, 141.557);
+ new ShapeRef(router, poly31, 31);
+
+ Polygon poly23(4);
+ poly23.ps[0] = Point(337.924, 141.557);
+ poly23.ps[1] = Point(337.924, 181.557);
+ poly23.ps[2] = Point(297.924, 181.557);
+ poly23.ps[3] = Point(297.924, 141.557);
+ new ShapeRef(router, poly23, 23);
+
+ Polygon poly44(4);
+ poly44.ps[0] = Point(97.9242, 507.557);
+ poly44.ps[1] = Point(97.9242, 547.557);
+ poly44.ps[2] = Point(57.9242, 547.557);
+ poly44.ps[3] = Point(57.9242, 507.557);
+ new ShapeRef(router, poly44, 44);
+
+ Polygon poly40(4);
+ poly40.ps[0] = Point(97.9242, 141.557);
+ poly40.ps[1] = Point(97.9242, 181.557);
+ poly40.ps[2] = Point(57.9242, 181.557);
+ poly40.ps[3] = Point(57.9242, 141.557);
+ new ShapeRef(router, poly40, 40);
+
+ Polygon poly48(4);
+ poly48.ps[0] = Point(97.9242, 743.557);
+ poly48.ps[1] = Point(97.9242, 783.557);
+ poly48.ps[2] = Point(57.9242, 783.557);
+ poly48.ps[3] = Point(57.9242, 743.557);
+ new ShapeRef(router, poly48, 48);
+
+ Polygon poly64(4);
+ poly64.ps[0] = Point(817.924, 554.057);
+ poly64.ps[1] = Point(817.924, 594.057);
+ poly64.ps[2] = Point(777.924, 594.057);
+ poly64.ps[3] = Point(777.924, 554.057);
+ new ShapeRef(router, poly64, 64);
+
+ Polygon poly58(4);
+ poly58.ps[0] = Point(97.9242, 14.8422);
+ poly58.ps[1] = Point(97.9242, 54.8422);
+ poly58.ps[2] = Point(57.9242, 54.8422);
+ poly58.ps[3] = Point(57.9242, 14.8422);
+ new ShapeRef(router, poly58, 58);
+
+ Polygon poly39(4);
+ poly39.ps[0] = Point(457.924, 141.557);
+ poly39.ps[1] = Point(457.924, 181.557);
+ poly39.ps[2] = Point(417.924, 181.557);
+ poly39.ps[3] = Point(417.924, 141.557);
+ new ShapeRef(router, poly39, 39);
+
+ Polygon poly53(4);
+ poly53.ps[0] = Point(577.924, 323.557);
+ poly53.ps[1] = Point(577.924, 363.557);
+ poly53.ps[2] = Point(537.924, 363.557);
+ poly53.ps[3] = Point(537.924, 323.557);
+ new ShapeRef(router, poly53, 53);
+
+ Polygon poly16(4);
+ poly16.ps[0] = Point(337.924, 743.557);
+ poly16.ps[1] = Point(337.924, 783.557);
+ poly16.ps[2] = Point(297.924, 783.557);
+ poly16.ps[3] = Point(297.924, 743.557);
+ new ShapeRef(router, poly16, 16);
+
+ Polygon poly14(4);
+ poly14.ps[0] = Point(1158.92, 141.557);
+ poly14.ps[1] = Point(1158.92, 181.557);
+ poly14.ps[2] = Point(1118.92, 181.557);
+ poly14.ps[3] = Point(1118.92, 141.557);
+ new ShapeRef(router, poly14, 14);
+
+ Polygon poly19(4);
+ poly19.ps[0] = Point(217.924, 141.557);
+ poly19.ps[1] = Point(217.924, 181.557);
+ poly19.ps[2] = Point(177.924, 181.557);
+ poly19.ps[3] = Point(177.924, 141.557);
+ new ShapeRef(router, poly19, 19);
+
+ Polygon poly35(4);
+ poly35.ps[0] = Point(1158.92, 40.3422);
+ poly35.ps[1] = Point(1158.92, 80.3422);
+ poly35.ps[2] = Point(1118.92, 80.3422);
+ poly35.ps[3] = Point(1118.92, 40.3422);
+ new ShapeRef(router, poly35, 35);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(1158.92, -80.6578);
+ poly8.ps[1] = Point(1158.92, -40.6578);
+ poly8.ps[2] = Point(1118.92, -40.6578);
+ poly8.ps[3] = Point(1118.92, -80.6578);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(1371.92, 29.8422);
+ poly4.ps[1] = Point(1371.92, 69.8422);
+ poly4.ps[2] = Point(1331.92, 69.8422);
+ poly4.ps[3] = Point(1331.92, 29.8422);
+ new ShapeRef(router, poly4, 4);
+
+ Polygon poly15(4);
+ poly15.ps[0] = Point(1158.92, 415.557);
+ poly15.ps[1] = Point(1158.92, 455.557);
+ poly15.ps[2] = Point(1118.92, 455.557);
+ poly15.ps[3] = Point(1118.92, 415.557);
+ new ShapeRef(router, poly15, 15);
+
+ Polygon poly33(4);
+ poly33.ps[0] = Point(937.924, 415.557);
+ poly33.ps[1] = Point(937.924, 455.557);
+ poly33.ps[2] = Point(897.924, 455.557);
+ poly33.ps[3] = Point(897.924, 415.557);
+ new ShapeRef(router, poly33, 33);
+
+ Polygon poly51(4);
+ poly51.ps[0] = Point(1038.92, 323.557);
+ poly51.ps[1] = Point(1038.92, 363.557);
+ poly51.ps[2] = Point(998.924, 363.557);
+ poly51.ps[3] = Point(998.924, 323.557);
+ new ShapeRef(router, poly51, 51);
+
+ Polygon poly29(4);
+ poly29.ps[0] = Point(1038.92, 415.557);
+ poly29.ps[1] = Point(1038.92, 455.557);
+ poly29.ps[2] = Point(998.924, 455.557);
+ poly29.ps[3] = Point(998.924, 415.557);
+ new ShapeRef(router, poly29, 29);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(1038.92, -80.6578);
+ poly9.ps[1] = Point(1038.92, -40.6578);
+ poly9.ps[2] = Point(998.924, -40.6578);
+ poly9.ps[3] = Point(998.924, -80.6578);
+ new ShapeRef(router, poly9, 9);
+
+ Polygon poly20(4);
+ poly20.ps[0] = Point(337.924, 507.557);
+ poly20.ps[1] = Point(337.924, 547.557);
+ poly20.ps[2] = Point(297.924, 547.557);
+ poly20.ps[3] = Point(297.924, 507.557);
+ new ShapeRef(router, poly20, 20);
+
+ Polygon poly63(4);
+ poly63.ps[0] = Point(457.924, 507.557);
+ poly63.ps[1] = Point(457.924, 547.557);
+ poly63.ps[2] = Point(417.924, 547.557);
+ poly63.ps[3] = Point(417.924, 507.557);
+ new ShapeRef(router, poly63, 63);
+
+ Polygon poly21(4);
+ poly21.ps[0] = Point(937.924, 141.557);
+ poly21.ps[1] = Point(937.924, 181.557);
+ poly21.ps[2] = Point(897.924, 181.557);
+ poly21.ps[3] = Point(897.924, 141.557);
+ new ShapeRef(router, poly21, 21);
+
+ Polygon poly24(4);
+ poly24.ps[0] = Point(457.924, 743.557);
+ poly24.ps[1] = Point(457.924, 783.557);
+ poly24.ps[2] = Point(417.924, 783.557);
+ poly24.ps[3] = Point(417.924, 743.557);
+ new ShapeRef(router, poly24, 24);
+
+ Polygon poly43(4);
+ poly43.ps[0] = Point(1038.92, 1.84222);
+ poly43.ps[1] = Point(1038.92, 41.8422);
+ poly43.ps[2] = Point(998.924, 41.8422);
+ poly43.ps[3] = Point(998.924, 1.84222);
+ new ShapeRef(router, poly43, 43);
+
+ Polygon poly38(4);
+ poly38.ps[0] = Point(217.924, 507.557);
+ poly38.ps[1] = Point(217.924, 547.557);
+ poly38.ps[2] = Point(177.924, 547.557);
+ poly38.ps[3] = Point(177.924, 507.557);
+ new ShapeRef(router, poly38, 38);
+
+ Polygon poly12(4);
+ poly12.ps[0] = Point(1038.92, 260.557);
+ poly12.ps[1] = Point(1038.92, 300.557);
+ poly12.ps[2] = Point(998.924, 300.557);
+ poly12.ps[3] = Point(998.924, 260.557);
+ new ShapeRef(router, poly12, 12);
+
+ Polygon poly37(4);
+ poly37.ps[0] = Point(457.924, 607.557);
+ poly37.ps[1] = Point(457.924, 647.557);
+ poly37.ps[2] = Point(417.924, 647.557);
+ poly37.ps[3] = Point(417.924, 607.557);
+ new ShapeRef(router, poly37, 37);
+
+ Polygon poly54(4);
+ poly54.ps[0] = Point(697.924, 323.557);
+ poly54.ps[1] = Point(697.924, 363.557);
+ poly54.ps[2] = Point(657.924, 363.557);
+ poly54.ps[3] = Point(657.924, 323.557);
+ new ShapeRef(router, poly54, 54);
+
+ Polygon poly67(4);
+ poly67.ps[0] = Point(147.924, 24.8422);
+ poly67.ps[1] = Point(147.924, 44.8422);
+ poly67.ps[2] = Point(127.924, 44.8422);
+ poly67.ps[3] = Point(127.924, 24.8422);
+ new ShapeRef(router, poly67, 67);
+
+ Polygon poly68(4);
+ poly68.ps[0] = Point(147.924, 151.557);
+ poly68.ps[1] = Point(147.924, 171.557);
+ poly68.ps[2] = Point(127.924, 171.557);
+ poly68.ps[3] = Point(127.924, 151.557);
+ new ShapeRef(router, poly68, 68);
+
+ ConnRef *connRef148 = new ConnRef(router, 148);
+ ConnEnd srcPt148(Point(1018.92, -60.6578), 15);
+ connRef148->setSourceEndpoint(srcPt148);
+ ConnEnd dstPt148(Point(1068.92, -60.6578), 15);
+ connRef148->setDestEndpoint(dstPt148);
+ connRef148->setRoutingType((ConnType)2);
+
+ ConnRef *connRef149 = new ConnRef(router, 149);
+ ConnEnd srcPt149(Point(1138.92, 161.557), 15);
+ connRef149->setSourceEndpoint(srcPt149);
+ ConnEnd dstPt149(Point(1188.92, 152.342), 15);
+ connRef149->setDestEndpoint(dstPt149);
+ connRef149->setRoutingType((ConnType)2);
+
+ ConnRef *connRef150 = new ConnRef(router, 150);
+ ConnEnd srcPt150(Point(1138.92, 435.557), 15);
+ connRef150->setSourceEndpoint(srcPt150);
+ ConnEnd dstPt150(Point(1188.92, 388.557), 15);
+ connRef150->setDestEndpoint(dstPt150);
+ connRef150->setRoutingType((ConnType)2);
+
+ ConnRef *connRef151 = new ConnRef(router, 151);
+ ConnEnd srcPt151(Point(317.924, 763.557), 15);
+ connRef151->setSourceEndpoint(srcPt151);
+ ConnEnd dstPt151(Point(367.924, 627.557), 15);
+ connRef151->setDestEndpoint(dstPt151);
+ connRef151->setRoutingType((ConnType)2);
+
+ ConnRef *connRef152 = new ConnRef(router, 152);
+ ConnEnd srcPt152(Point(317.924, 763.557), 15);
+ connRef152->setSourceEndpoint(srcPt152);
+ ConnEnd dstPt152(Point(367.924, 763.557), 15);
+ connRef152->setDestEndpoint(dstPt152);
+ connRef152->setRoutingType((ConnType)2);
+
+ ConnRef *connRef153 = new ConnRef(router, 153);
+ ConnEnd srcPt153(Point(317.924, 763.557), 15);
+ connRef153->setSourceEndpoint(srcPt153);
+ ConnEnd dstPt153(Point(487.924, 903.057), 15);
+ connRef153->setDestEndpoint(dstPt153);
+ connRef153->setRoutingType((ConnType)2);
+
+ ConnRef *connRef154 = new ConnRef(router, 154);
+ ConnEnd srcPt154(Point(317.924, 763.557), 15);
+ connRef154->setSourceEndpoint(srcPt154);
+ ConnEnd dstPt154(Point(727.924, 574.057), 15);
+ connRef154->setDestEndpoint(dstPt154);
+ connRef154->setRoutingType((ConnType)2);
+
+ ConnRef *connRef155 = new ConnRef(router, 155);
+ ConnEnd srcPt155(Point(557.924, 903.057), 15);
+ connRef155->setSourceEndpoint(srcPt155);
+ ConnEnd dstPt155(Point(607.924, 903.057), 15);
+ connRef155->setDestEndpoint(dstPt155);
+ connRef155->setRoutingType((ConnType)2);
+
+ ConnRef *connRef156 = new ConnRef(router, 156);
+ ConnEnd srcPt156(Point(197.924, 763.557), 15);
+ connRef156->setSourceEndpoint(srcPt156);
+ ConnEnd dstPt156(Point(247.924, 763.557), 15);
+ connRef156->setDestEndpoint(dstPt156);
+ connRef156->setRoutingType((ConnType)2);
+
+ ConnRef *connRef157 = new ConnRef(router, 157);
+ ConnEnd srcPt157(Point(147.924, 161.557), 15);
+ connRef157->setSourceEndpoint(srcPt157);
+ ConnEnd dstPt157(Point(197.924, 161.557), 15);
+ connRef157->setDestEndpoint(dstPt157);
+ connRef157->setRoutingType((ConnType)2);
+
+ ConnRef *connRef158 = new ConnRef(router, 158);
+ ConnEnd srcPt158(Point(197.924, 161.557), 15);
+ connRef158->setSourceEndpoint(srcPt158);
+ ConnEnd dstPt158(Point(247.924, 161.557), 15);
+ connRef158->setDestEndpoint(dstPt158);
+ connRef158->setRoutingType((ConnType)2);
+
+ ConnRef *connRef159 = new ConnRef(router, 159);
+ ConnEnd srcPt159(Point(197.924, 161.557), 15);
+ connRef159->setSourceEndpoint(srcPt159);
+ ConnEnd dstPt159(Point(197.924, 203.557), 15);
+ connRef159->setDestEndpoint(dstPt159);
+ connRef159->setRoutingType((ConnType)2);
+
+ ConnRef *connRef160 = new ConnRef(router, 160);
+ ConnEnd srcPt160(Point(317.924, 161.557), 15);
+ connRef160->setSourceEndpoint(srcPt160);
+ ConnEnd dstPt160(Point(727.924, -60.6578), 15);
+ connRef160->setDestEndpoint(dstPt160);
+ connRef160->setRoutingType((ConnType)2);
+
+ ConnRef *connRef161 = new ConnRef(router, 161);
+ ConnEnd srcPt161(Point(317.924, 161.557), 15);
+ connRef161->setSourceEndpoint(srcPt161);
+ ConnEnd dstPt161(Point(367.924, 161.557), 15);
+ connRef161->setDestEndpoint(dstPt161);
+ connRef161->setRoutingType((ConnType)2);
+
+ ConnRef *connRef162 = new ConnRef(router, 162);
+ ConnEnd srcPt162(Point(317.924, 161.557), 15);
+ connRef162->setSourceEndpoint(srcPt162);
+ ConnEnd dstPt162(Point(367.924, 27.3422), 15);
+ connRef162->setDestEndpoint(dstPt162);
+ connRef162->setRoutingType((ConnType)2);
+
+ ConnRef *connRef163 = new ConnRef(router, 163);
+ ConnEnd srcPt163(Point(317.924, 161.557), 15);
+ connRef163->setSourceEndpoint(srcPt163);
+ ConnEnd dstPt163(Point(487.924, 435.557), 15);
+ connRef163->setDestEndpoint(dstPt163);
+ connRef163->setRoutingType((ConnType)2);
+
+ ConnRef *connRef164 = new ConnRef(router, 164);
+ ConnEnd srcPt164(Point(437.924, 763.557), 15);
+ connRef164->setSourceEndpoint(srcPt164);
+ ConnEnd dstPt164(Point(487.924, 763.557), 15);
+ connRef164->setDestEndpoint(dstPt164);
+ connRef164->setRoutingType((ConnType)2);
+
+ ConnRef *connRef165 = new ConnRef(router, 165);
+ ConnEnd srcPt165(Point(437.924, 763.557), 15);
+ connRef165->setSourceEndpoint(srcPt165);
+ ConnEnd dstPt165(Point(727.924, 860.057), 15);
+ connRef165->setDestEndpoint(dstPt165);
+ connRef165->setRoutingType((ConnType)2);
+
+ ConnRef *connRef166 = new ConnRef(router, 166);
+ ConnEnd srcPt166(Point(557.924, 527.557), 15);
+ connRef166->setSourceEndpoint(srcPt166);
+ ConnEnd dstPt166(Point(607.924, 527.557), 15);
+ connRef166->setDestEndpoint(dstPt166);
+ connRef166->setRoutingType((ConnType)2);
+
+ ConnRef *connRef167 = new ConnRef(router, 167);
+ ConnEnd srcPt167(Point(797.924, 343.557), 15);
+ connRef167->setSourceEndpoint(srcPt167);
+ ConnEnd dstPt167(Point(847.924, 343.557), 15);
+ connRef167->setDestEndpoint(dstPt167);
+ connRef167->setRoutingType((ConnType)2);
+
+ ConnRef *connRef168 = new ConnRef(router, 168);
+ ConnEnd srcPt168(Point(797.924, 343.557), 15);
+ connRef168->setSourceEndpoint(srcPt168);
+ ConnEnd dstPt168(Point(847.924, 435.557), 15);
+ connRef168->setDestEndpoint(dstPt168);
+ connRef168->setRoutingType((ConnType)2);
+
+ ConnRef *connRef169 = new ConnRef(router, 169);
+ ConnEnd srcPt169(Point(1018.92, 435.557), 15);
+ connRef169->setSourceEndpoint(srcPt169);
+ ConnEnd dstPt169(Point(1068.92, 388.557), 15);
+ connRef169->setDestEndpoint(dstPt169);
+ connRef169->setRoutingType((ConnType)2);
+
+ ConnRef *connRef198 = new ConnRef(router, 198);
+ ConnEnd srcPt198(Point(267.924, 763.557), 15);
+ connRef198->setSourceEndpoint(srcPt198);
+ ConnEnd dstPt198(Point(317.924, 763.557), 15);
+ connRef198->setDestEndpoint(dstPt198);
+ connRef198->setRoutingType((ConnType)2);
+
+ ConnRef *connRef199 = new ConnRef(router, 199);
+ ConnEnd srcPt199(Point(387.924, 627.557), 15);
+ connRef199->setSourceEndpoint(srcPt199);
+ ConnEnd dstPt199(Point(437.924, 627.557), 15);
+ connRef199->setDestEndpoint(dstPt199);
+ connRef199->setRoutingType((ConnType)2);
+
+ ConnRef *connRef200 = new ConnRef(router, 200);
+ ConnEnd srcPt200(Point(387.924, 763.557), 15);
+ connRef200->setSourceEndpoint(srcPt200);
+ ConnEnd dstPt200(Point(437.924, 763.557), 15);
+ connRef200->setDestEndpoint(dstPt200);
+ connRef200->setRoutingType((ConnType)2);
+
+ ConnRef *connRef201 = new ConnRef(router, 201);
+ ConnEnd srcPt201(Point(507.924, 763.557), 15);
+ connRef201->setSourceEndpoint(srcPt201);
+ ConnEnd dstPt201(Point(557.924, 763.557), 15);
+ connRef201->setDestEndpoint(dstPt201);
+ connRef201->setRoutingType((ConnType)2);
+
+ ConnRef *connRef202 = new ConnRef(router, 202);
+ ConnEnd srcPt202(Point(627.924, 763.557), 15);
+ connRef202->setSourceEndpoint(srcPt202);
+ ConnEnd dstPt202(Point(677.924, 763.557), 15);
+ connRef202->setDestEndpoint(dstPt202);
+ connRef202->setRoutingType((ConnType)2);
+
+ ConnRef *connRef203 = new ConnRef(router, 203);
+ ConnEnd srcPt203(Point(507.924, 903.057), 15);
+ connRef203->setSourceEndpoint(srcPt203);
+ ConnEnd dstPt203(Point(557.924, 903.057), 15);
+ connRef203->setDestEndpoint(dstPt203);
+ connRef203->setRoutingType((ConnType)2);
+
+ ConnRef *connRef204 = new ConnRef(router, 204);
+ ConnEnd srcPt204(Point(627.924, 903.057), 15);
+ connRef204->setSourceEndpoint(srcPt204);
+ ConnEnd dstPt204(Point(677.924, 903.057), 15);
+ connRef204->setDestEndpoint(dstPt204);
+ connRef204->setRoutingType((ConnType)2);
+
+ ConnRef *connRef205 = new ConnRef(router, 205);
+ ConnEnd srcPt205(Point(387.924, 161.557), 15);
+ connRef205->setSourceEndpoint(srcPt205);
+ ConnEnd dstPt205(Point(437.924, 161.557), 15);
+ connRef205->setDestEndpoint(dstPt205);
+ connRef205->setRoutingType((ConnType)2);
+
+ ConnRef *connRef206 = new ConnRef(router, 206);
+ ConnEnd srcPt206(Point(387.924, 27.3422), 15);
+ connRef206->setSourceEndpoint(srcPt206);
+ ConnEnd dstPt206(Point(437.924, 27.3422), 15);
+ connRef206->setDestEndpoint(dstPt206);
+ connRef206->setRoutingType((ConnType)2);
+
+ ConnRef *connRef207 = new ConnRef(router, 207);
+ ConnEnd srcPt207(Point(507.924, 45.8422), 15);
+ connRef207->setSourceEndpoint(srcPt207);
+ ConnEnd dstPt207(Point(557.924, 54.8422), 15);
+ connRef207->setDestEndpoint(dstPt207);
+ connRef207->setRoutingType((ConnType)2);
+
+ ConnRef *connRef208 = new ConnRef(router, 208);
+ ConnEnd srcPt208(Point(627.924, 45.8422), 15);
+ connRef208->setSourceEndpoint(srcPt208);
+ ConnEnd dstPt208(Point(677.924, 54.8422), 15);
+ connRef208->setDestEndpoint(dstPt208);
+ connRef208->setRoutingType((ConnType)2);
+
+ ConnRef *connRef209 = new ConnRef(router, 209);
+ ConnEnd srcPt209(Point(747.924, 574.057), 15);
+ connRef209->setSourceEndpoint(srcPt209);
+ ConnEnd dstPt209(Point(797.924, 574.057), 15);
+ connRef209->setDestEndpoint(dstPt209);
+ connRef209->setRoutingType((ConnType)2);
+
+ ConnRef *connRef210 = new ConnRef(router, 210);
+ ConnEnd srcPt210(Point(507.924, 527.557), 15);
+ connRef210->setSourceEndpoint(srcPt210);
+ ConnEnd dstPt210(Point(557.924, 527.557), 15);
+ connRef210->setDestEndpoint(dstPt210);
+ connRef210->setRoutingType((ConnType)2);
+
+ ConnRef *connRef211 = new ConnRef(router, 211);
+ ConnEnd srcPt211(Point(507.924, 435.557), 15);
+ connRef211->setSourceEndpoint(srcPt211);
+ ConnEnd dstPt211(Point(557.924, 435.557), 15);
+ connRef211->setDestEndpoint(dstPt211);
+ connRef211->setRoutingType((ConnType)2);
+
+ ConnRef *connRef212 = new ConnRef(router, 212);
+ ConnEnd srcPt212(Point(627.924, 527.557), 15);
+ connRef212->setSourceEndpoint(srcPt212);
+ ConnEnd dstPt212(Point(677.924, 527.557), 15);
+ connRef212->setDestEndpoint(dstPt212);
+ connRef212->setRoutingType((ConnType)2);
+
+ ConnRef *connRef213 = new ConnRef(router, 213);
+ ConnEnd srcPt213(Point(627.924, 435.557), 15);
+ connRef213->setSourceEndpoint(srcPt213);
+ ConnEnd dstPt213(Point(677.924, 435.557), 15);
+ connRef213->setDestEndpoint(dstPt213);
+ connRef213->setRoutingType((ConnType)2);
+
+ ConnRef *connRef214 = new ConnRef(router, 214);
+ ConnEnd srcPt214(Point(867.924, 343.557), 15);
+ connRef214->setSourceEndpoint(srcPt214);
+ ConnEnd dstPt214(Point(917.924, 343.557), 15);
+ connRef214->setDestEndpoint(dstPt214);
+ connRef214->setRoutingType((ConnType)2);
+
+ ConnRef *connRef215 = new ConnRef(router, 215);
+ ConnEnd srcPt215(Point(867.924, 435.557), 15);
+ connRef215->setSourceEndpoint(srcPt215);
+ ConnEnd dstPt215(Point(917.924, 435.557), 15);
+ connRef215->setDestEndpoint(dstPt215);
+ connRef215->setRoutingType((ConnType)2);
+
+ ConnRef *connRef216 = new ConnRef(router, 216);
+ ConnEnd srcPt216(Point(867.924, 161.557), 15);
+ connRef216->setSourceEndpoint(srcPt216);
+ ConnEnd dstPt216(Point(917.924, 161.557), 15);
+ connRef216->setDestEndpoint(dstPt216);
+ connRef216->setRoutingType((ConnType)2);
+
+ ConnRef *connRef217 = new ConnRef(router, 217);
+ ConnEnd srcPt217(Point(747.924, 343.557), 15);
+ connRef217->setSourceEndpoint(srcPt217);
+ ConnEnd dstPt217(Point(797.924, 343.557), 15);
+ connRef217->setDestEndpoint(dstPt217);
+ connRef217->setRoutingType((ConnType)2);
+
+ ConnRef *connRef218 = new ConnRef(router, 218);
+ ConnEnd srcPt218(Point(1088.92, 388.557), 15);
+ connRef218->setSourceEndpoint(srcPt218);
+ ConnEnd dstPt218(Point(1138.92, 435.557), 15);
+ connRef218->setDestEndpoint(dstPt218);
+ connRef218->setRoutingType((ConnType)2);
+
+ ConnRef *connRef219 = new ConnRef(router, 219);
+ ConnEnd srcPt219(Point(1208.92, 388.557), 15);
+ connRef219->setSourceEndpoint(srcPt219);
+ ConnEnd dstPt219(Point(1258.92, 435.557), 15);
+ connRef219->setDestEndpoint(dstPt219);
+ connRef219->setRoutingType((ConnType)2);
+
+ ConnRef *connRef220 = new ConnRef(router, 220);
+ ConnEnd srcPt220(Point(1088.92, 152.342), 15);
+ connRef220->setSourceEndpoint(srcPt220);
+ ConnEnd dstPt220(Point(1138.92, 161.557), 15);
+ connRef220->setDestEndpoint(dstPt220);
+ connRef220->setRoutingType((ConnType)2);
+
+ ConnRef *connRef221 = new ConnRef(router, 221);
+ ConnEnd srcPt221(Point(1088.92, 60.3422), 15);
+ connRef221->setSourceEndpoint(srcPt221);
+ ConnEnd dstPt221(Point(1138.92, 60.3422), 15);
+ connRef221->setDestEndpoint(dstPt221);
+ connRef221->setRoutingType((ConnType)2);
+
+ ConnRef *connRef222 = new ConnRef(router, 222);
+ ConnEnd srcPt222(Point(1208.92, 152.342), 15);
+ connRef222->setSourceEndpoint(srcPt222);
+ ConnEnd dstPt222(Point(1258.92, 161.557), 15);
+ connRef222->setDestEndpoint(dstPt222);
+ connRef222->setRoutingType((ConnType)2);
+
+ ConnRef *connRef223 = new ConnRef(router, 223);
+ ConnEnd srcPt223(Point(1088.92, -60.6578), 15);
+ connRef223->setSourceEndpoint(srcPt223);
+ ConnEnd dstPt223(Point(1138.92, -60.6578), 15);
+ connRef223->setDestEndpoint(dstPt223);
+ connRef223->setRoutingType((ConnType)2);
+
+ ConnRef *connRef224 = new ConnRef(router, 224);
+ ConnEnd srcPt224(Point(747.924, 161.557), 15);
+ connRef224->setSourceEndpoint(srcPt224);
+ ConnEnd dstPt224(Point(797.924, 161.557), 15);
+ connRef224->setDestEndpoint(dstPt224);
+ connRef224->setRoutingType((ConnType)2);
+
+ ConnRef *connRef225 = new ConnRef(router, 225);
+ ConnEnd srcPt225(Point(747.924, 860.057), 15);
+ connRef225->setSourceEndpoint(srcPt225);
+ ConnEnd dstPt225(Point(797.924, 860.057), 15);
+ connRef225->setDestEndpoint(dstPt225);
+ connRef225->setRoutingType((ConnType)2);
+
+ ConnRef *connRef254 = new ConnRef(router, 254);
+ ConnEnd srcPt254(Point(857.924, 385.557), 15);
+ connRef254->setSourceEndpoint(srcPt254);
+ ConnEnd dstPt254(Point(857.924, 435.557), 15);
+ connRef254->setDestEndpoint(dstPt254);
+ connRef254->setRoutingType((ConnType)2);
+
+ ConnRef *connRef255 = new ConnRef(router, 255);
+ ConnEnd srcPt255(Point(857.924, 111.557), 15);
+ connRef255->setSourceEndpoint(srcPt255);
+ ConnEnd dstPt255(Point(857.924, 161.557), 15);
+ connRef255->setDestEndpoint(dstPt255);
+ connRef255->setRoutingType((ConnType)2);
+
+ ConnRef *connRef256 = new ConnRef(router, 256);
+ ConnEnd srcPt256(Point(737.924, 293.557), 15);
+ connRef256->setSourceEndpoint(srcPt256);
+ ConnEnd dstPt256(Point(737.924, 343.557), 15);
+ connRef256->setDestEndpoint(dstPt256);
+ connRef256->setRoutingType((ConnType)2);
+
+ ConnRef *connRef257 = new ConnRef(router, 257);
+ ConnEnd srcPt257(Point(1078.92, 338.557), 15);
+ connRef257->setSourceEndpoint(srcPt257);
+ ConnEnd dstPt257(Point(1078.92, 388.557), 15);
+ connRef257->setDestEndpoint(dstPt257);
+ connRef257->setRoutingType((ConnType)2);
+
+ ConnRef *connRef258 = new ConnRef(router, 258);
+ ConnEnd srcPt258(Point(1198.92, 338.557), 15);
+ connRef258->setSourceEndpoint(srcPt258);
+ ConnEnd dstPt258(Point(1198.92, 388.557), 15);
+ connRef258->setDestEndpoint(dstPt258);
+ connRef258->setRoutingType((ConnType)2);
+
+ ConnRef *connRef259 = new ConnRef(router, 259);
+ ConnEnd srcPt259(Point(1078.92, 102.342), 15);
+ connRef259->setSourceEndpoint(srcPt259);
+ ConnEnd dstPt259(Point(1078.92, 152.342), 15);
+ connRef259->setDestEndpoint(dstPt259);
+ connRef259->setRoutingType((ConnType)2);
+
+ ConnRef *connRef260 = new ConnRef(router, 260);
+ ConnEnd srcPt260(Point(1078.92, 10.3422), 15);
+ connRef260->setSourceEndpoint(srcPt260);
+ ConnEnd dstPt260(Point(1078.92, 60.3422), 15);
+ connRef260->setDestEndpoint(dstPt260);
+ connRef260->setRoutingType((ConnType)2);
+
+ ConnRef *connRef261 = new ConnRef(router, 261);
+ ConnEnd srcPt261(Point(1198.92, 102.342), 15);
+ connRef261->setSourceEndpoint(srcPt261);
+ ConnEnd dstPt261(Point(1198.92, 152.342), 15);
+ connRef261->setDestEndpoint(dstPt261);
+ connRef261->setRoutingType((ConnType)2);
+
+ ConnRef *connRef262 = new ConnRef(router, 262);
+ ConnEnd srcPt262(Point(1078.92, -110.658), 15);
+ connRef262->setSourceEndpoint(srcPt262);
+ ConnEnd dstPt262(Point(1078.92, -60.6578), 15);
+ connRef262->setDestEndpoint(dstPt262);
+ connRef262->setRoutingType((ConnType)2);
+
+ ConnRef *connRef263 = new ConnRef(router, 263);
+ ConnEnd srcPt263(Point(958.924, 230.557), 15);
+ connRef263->setSourceEndpoint(srcPt263);
+ ConnEnd dstPt263(Point(958.924, 280.557), 15);
+ connRef263->setDestEndpoint(dstPt263);
+ connRef263->setRoutingType((ConnType)2);
+
+ ConnRef *connRef264 = new ConnRef(router, 264);
+ ConnEnd srcPt264(Point(737.924, 111.557), 15);
+ connRef264->setSourceEndpoint(srcPt264);
+ ConnEnd dstPt264(Point(737.924, 161.557), 15);
+ connRef264->setDestEndpoint(dstPt264);
+ connRef264->setRoutingType((ConnType)2);
+
+ ConnRef *connRef265 = new ConnRef(router, 265);
+ ConnEnd srcPt265(Point(737.924, 810.057), 15);
+ connRef265->setSourceEndpoint(srcPt265);
+ ConnEnd dstPt265(Point(737.924, 860.057), 15);
+ connRef265->setDestEndpoint(dstPt265);
+ connRef265->setRoutingType((ConnType)2);
+
+ ConnRef *connRef266 = new ConnRef(router, 266);
+ ConnEnd srcPt266(Point(77.9242, 161.557), 15);
+ connRef266->setSourceEndpoint(srcPt266);
+ ConnEnd dstPt266(Point(40.9242, 252.5), 15);
+ connRef266->setDestEndpoint(dstPt266);
+ connRef266->setRoutingType((ConnType)2);
+
+ ConnRef *connRef267 = new ConnRef(router, 267);
+ ConnEnd srcPt267(Point(77.9242, 763.557), 15);
+ connRef267->setSourceEndpoint(srcPt267);
+ ConnEnd dstPt267(Point(-46.0758, 329.75), 15);
+ connRef267->setDestEndpoint(dstPt267);
+ connRef267->setRoutingType((ConnType)2);
+
+ ConnRef *connRef226 = new ConnRef(router, 226);
+ ConnEnd srcPt226(Point(737.924, -110.658), 15);
+ connRef226->setSourceEndpoint(srcPt226);
+ ConnEnd dstPt226(Point(737.924, -60.6578), 15);
+ connRef226->setDestEndpoint(dstPt226);
+ connRef226->setRoutingType((ConnType)2);
+
+ ConnRef *connRef227 = new ConnRef(router, 227);
+ ConnEnd srcPt227(Point(137.924, -15.1578), 15);
+ connRef227->setSourceEndpoint(srcPt227);
+ ConnEnd dstPt227(Point(137.924, 34.8422), 15);
+ connRef227->setDestEndpoint(dstPt227);
+ connRef227->setRoutingType((ConnType)2);
+
+ ConnRef *connRef228 = new ConnRef(router, 228);
+ ConnEnd srcPt228(Point(137.924, 111.557), 15);
+ connRef228->setSourceEndpoint(srcPt228);
+ ConnEnd dstPt228(Point(137.924, 161.557), 15);
+ connRef228->setDestEndpoint(dstPt228);
+ connRef228->setRoutingType((ConnType)2);
+
+ ConnRef *connRef229 = new ConnRef(router, 229);
+ ConnEnd srcPt229(Point(257.924, 111.557), 15);
+ connRef229->setSourceEndpoint(srcPt229);
+ ConnEnd dstPt229(Point(257.924, 161.557), 15);
+ connRef229->setDestEndpoint(dstPt229);
+ connRef229->setRoutingType((ConnType)2);
+
+ ConnRef *connRef230 = new ConnRef(router, 230);
+ ConnEnd srcPt230(Point(259.924, 213.557), 15);
+ connRef230->setSourceEndpoint(srcPt230);
+ ConnEnd dstPt230(Point(197.924, 213.557), 15);
+ connRef230->setDestEndpoint(dstPt230);
+ connRef230->setRoutingType((ConnType)2);
+
+ ConnRef *connRef231 = new ConnRef(router, 231);
+ ConnEnd srcPt231(Point(257.924, 265.557), 15);
+ connRef231->setSourceEndpoint(srcPt231);
+ ConnEnd dstPt231(Point(257.924, 315.557), 15);
+ connRef231->setDestEndpoint(dstPt231);
+ connRef231->setRoutingType((ConnType)2);
+
+ ConnRef *connRef232 = new ConnRef(router, 232);
+ ConnEnd srcPt232(Point(139.924, 367.557), 15);
+ connRef232->setSourceEndpoint(srcPt232);
+ ConnEnd dstPt232(Point(77.9242, 367.557), 15);
+ connRef232->setDestEndpoint(dstPt232);
+ connRef232->setRoutingType((ConnType)2);
+
+ ConnRef *connRef233 = new ConnRef(router, 233);
+ ConnEnd srcPt233(Point(137.924, 477.557), 15);
+ connRef233->setSourceEndpoint(srcPt233);
+ ConnEnd dstPt233(Point(137.924, 527.557), 15);
+ connRef233->setDestEndpoint(dstPt233);
+ connRef233->setRoutingType((ConnType)2);
+
+ ConnRef *connRef234 = new ConnRef(router, 234);
+ ConnEnd srcPt234(Point(137.924, 569.557), 15);
+ connRef234->setSourceEndpoint(srcPt234);
+ ConnEnd dstPt234(Point(137.924, 619.557), 15);
+ connRef234->setDestEndpoint(dstPt234);
+ connRef234->setRoutingType((ConnType)2);
+
+ ConnRef *connRef235 = new ConnRef(router, 235);
+ ConnEnd srcPt235(Point(139.924, 661.557), 15);
+ connRef235->setSourceEndpoint(srcPt235);
+ ConnEnd dstPt235(Point(77.9242, 661.557), 15);
+ connRef235->setDestEndpoint(dstPt235);
+ connRef235->setRoutingType((ConnType)2);
+
+ ConnRef *connRef236 = new ConnRef(router, 236);
+ ConnEnd srcPt236(Point(137.924, 713.557), 15);
+ connRef236->setSourceEndpoint(srcPt236);
+ ConnEnd dstPt236(Point(137.924, 763.557), 15);
+ connRef236->setDestEndpoint(dstPt236);
+ connRef236->setRoutingType((ConnType)2);
+
+ ConnRef *connRef237 = new ConnRef(router, 237);
+ ConnEnd srcPt237(Point(257.924, 713.557), 15);
+ connRef237->setSourceEndpoint(srcPt237);
+ ConnEnd dstPt237(Point(257.924, 763.557), 15);
+ connRef237->setDestEndpoint(dstPt237);
+ connRef237->setRoutingType((ConnType)2);
+
+ ConnRef *connRef238 = new ConnRef(router, 238);
+ ConnEnd srcPt238(Point(377.924, 577.557), 15);
+ connRef238->setSourceEndpoint(srcPt238);
+ ConnEnd dstPt238(Point(377.924, 627.557), 15);
+ connRef238->setDestEndpoint(dstPt238);
+ connRef238->setRoutingType((ConnType)2);
+
+ ConnRef *connRef239 = new ConnRef(router, 239);
+ ConnEnd srcPt239(Point(377.924, 713.557), 15);
+ connRef239->setSourceEndpoint(srcPt239);
+ ConnEnd dstPt239(Point(377.924, 763.557), 15);
+ connRef239->setDestEndpoint(dstPt239);
+ connRef239->setRoutingType((ConnType)2);
+
+ ConnRef *connRef240 = new ConnRef(router, 240);
+ ConnEnd srcPt240(Point(497.924, 713.557), 15);
+ connRef240->setSourceEndpoint(srcPt240);
+ ConnEnd dstPt240(Point(497.924, 763.557), 15);
+ connRef240->setDestEndpoint(dstPt240);
+ connRef240->setRoutingType((ConnType)2);
+
+ ConnRef *connRef241 = new ConnRef(router, 241);
+ ConnEnd srcPt241(Point(617.924, 713.557), 15);
+ connRef241->setSourceEndpoint(srcPt241);
+ ConnEnd dstPt241(Point(617.924, 763.557), 15);
+ connRef241->setDestEndpoint(dstPt241);
+ connRef241->setRoutingType((ConnType)2);
+
+ ConnRef *connRef242 = new ConnRef(router, 242);
+ ConnEnd srcPt242(Point(497.924, 853.057), 15);
+ connRef242->setSourceEndpoint(srcPt242);
+ ConnEnd dstPt242(Point(497.924, 903.057), 15);
+ connRef242->setDestEndpoint(dstPt242);
+ connRef242->setRoutingType((ConnType)2);
+
+ ConnRef *connRef243 = new ConnRef(router, 243);
+ ConnEnd srcPt243(Point(617.924, 853.057), 15);
+ connRef243->setSourceEndpoint(srcPt243);
+ ConnEnd dstPt243(Point(617.924, 903.057), 15);
+ connRef243->setDestEndpoint(dstPt243);
+ connRef243->setRoutingType((ConnType)2);
+
+ ConnRef *connRef244 = new ConnRef(router, 244);
+ ConnEnd srcPt244(Point(377.924, 111.557), 15);
+ connRef244->setSourceEndpoint(srcPt244);
+ ConnEnd dstPt244(Point(377.924, 161.557), 15);
+ connRef244->setDestEndpoint(dstPt244);
+ connRef244->setRoutingType((ConnType)2);
+
+ ConnRef *connRef245 = new ConnRef(router, 245);
+ ConnEnd srcPt245(Point(377.924, -22.6578), 15);
+ connRef245->setSourceEndpoint(srcPt245);
+ ConnEnd dstPt245(Point(377.924, 27.3422), 15);
+ connRef245->setDestEndpoint(dstPt245);
+ connRef245->setRoutingType((ConnType)2);
+
+ ConnRef *connRef246 = new ConnRef(router, 246);
+ ConnEnd srcPt246(Point(497.924, -4.15778), 15);
+ connRef246->setSourceEndpoint(srcPt246);
+ ConnEnd dstPt246(Point(497.924, 45.8422), 15);
+ connRef246->setDestEndpoint(dstPt246);
+ connRef246->setRoutingType((ConnType)2);
+
+ ConnRef *connRef247 = new ConnRef(router, 247);
+ ConnEnd srcPt247(Point(617.924, -4.15778), 15);
+ connRef247->setSourceEndpoint(srcPt247);
+ ConnEnd dstPt247(Point(617.924, 45.8422), 15);
+ connRef247->setDestEndpoint(dstPt247);
+ connRef247->setRoutingType((ConnType)2);
+
+ ConnRef *connRef248 = new ConnRef(router, 248);
+ ConnEnd srcPt248(Point(737.924, 524.057), 15);
+ connRef248->setSourceEndpoint(srcPt248);
+ ConnEnd dstPt248(Point(737.924, 574.057), 15);
+ connRef248->setDestEndpoint(dstPt248);
+ connRef248->setRoutingType((ConnType)2);
+
+ ConnRef *connRef249 = new ConnRef(router, 249);
+ ConnEnd srcPt249(Point(497.924, 477.557), 15);
+ connRef249->setSourceEndpoint(srcPt249);
+ ConnEnd dstPt249(Point(497.924, 527.557), 15);
+ connRef249->setDestEndpoint(dstPt249);
+ connRef249->setRoutingType((ConnType)2);
+
+ ConnRef *connRef250 = new ConnRef(router, 250);
+ ConnEnd srcPt250(Point(497.924, 385.557), 15);
+ connRef250->setSourceEndpoint(srcPt250);
+ ConnEnd dstPt250(Point(497.924, 435.557), 15);
+ connRef250->setDestEndpoint(dstPt250);
+ connRef250->setRoutingType((ConnType)2);
+
+ ConnRef *connRef251 = new ConnRef(router, 251);
+ ConnEnd srcPt251(Point(617.924, 477.557), 15);
+ connRef251->setSourceEndpoint(srcPt251);
+ ConnEnd dstPt251(Point(617.924, 527.557), 15);
+ connRef251->setDestEndpoint(dstPt251);
+ connRef251->setRoutingType((ConnType)2);
+
+ ConnRef *connRef252 = new ConnRef(router, 252);
+ ConnEnd srcPt252(Point(617.924, 385.557), 15);
+ connRef252->setSourceEndpoint(srcPt252);
+ ConnEnd dstPt252(Point(617.924, 435.557), 15);
+ connRef252->setDestEndpoint(dstPt252);
+ connRef252->setRoutingType((ConnType)2);
+
+ ConnRef *connRef253 = new ConnRef(router, 253);
+ ConnEnd srcPt253(Point(857.924, 293.557), 15);
+ connRef253->setSourceEndpoint(srcPt253);
+ ConnEnd dstPt253(Point(857.924, 343.557), 15);
+ connRef253->setDestEndpoint(dstPt253);
+ connRef253->setRoutingType((ConnType)2);
+
+ ConnRef *connRef170 = new ConnRef(router, 170);
+ ConnEnd srcPt170(Point(1018.92, 161.557), 15);
+ connRef170->setSourceEndpoint(srcPt170);
+ ConnEnd dstPt170(Point(1068.92, 152.342), 15);
+ connRef170->setDestEndpoint(dstPt170);
+ connRef170->setRoutingType((ConnType)2);
+
+ ConnRef *connRef171 = new ConnRef(router, 171);
+ ConnEnd srcPt171(Point(1018.92, 161.557), 15);
+ connRef171->setSourceEndpoint(srcPt171);
+ ConnEnd dstPt171(Point(1068.92, 60.3422), 15);
+ connRef171->setDestEndpoint(dstPt171);
+ connRef171->setRoutingType((ConnType)2);
+
+ ConnRef *connRef172 = new ConnRef(router, 172);
+ ConnEnd srcPt172(Point(267.924, 315.557), 15);
+ connRef172->setSourceEndpoint(srcPt172);
+ ConnEnd dstPt172(Point(437.924, 161.557), 15);
+ connRef172->setDestEndpoint(dstPt172);
+ connRef172->setRoutingType((ConnType)2);
+
+ ConnRef *connRef173 = new ConnRef(router, 173);
+ ConnEnd srcPt173(Point(437.924, 161.557), 15);
+ connRef173->setSourceEndpoint(srcPt173);
+ ConnEnd dstPt173(Point(487.924, 45.8422), 15);
+ connRef173->setDestEndpoint(dstPt173);
+ connRef173->setRoutingType((ConnType)2);
+
+ ConnRef *connRef174 = new ConnRef(router, 174);
+ ConnEnd srcPt174(Point(437.924, 161.557), 15);
+ connRef174->setSourceEndpoint(srcPt174);
+ ConnEnd dstPt174(Point(727.924, 161.557), 15);
+ connRef174->setDestEndpoint(dstPt174);
+ connRef174->setRoutingType((ConnType)2);
+
+ ConnRef *connRef175 = new ConnRef(router, 175);
+ ConnEnd srcPt175(Point(77.9242, 161.557), 15);
+ connRef175->setSourceEndpoint(srcPt175);
+ ConnEnd dstPt175(Point(127.924, 161.557), 15);
+ connRef175->setDestEndpoint(dstPt175);
+ connRef175->setRoutingType((ConnType)2);
+
+ ConnRef *connRef176 = new ConnRef(router, 176);
+ ConnEnd srcPt176(Point(77.9242, 161.557), 15);
+ connRef176->setSourceEndpoint(srcPt176);
+ ConnEnd dstPt176(Point(77.9242, 357.557), 15);
+ connRef176->setDestEndpoint(dstPt176);
+ connRef176->setRoutingType((ConnType)2);
+
+ ConnRef *connRef177 = new ConnRef(router, 177);
+ ConnEnd srcPt177(Point(557.924, 763.557), 15);
+ connRef177->setSourceEndpoint(srcPt177);
+ ConnEnd dstPt177(Point(607.924, 763.557), 15);
+ connRef177->setDestEndpoint(dstPt177);
+ connRef177->setRoutingType((ConnType)2);
+
+ ConnRef *connRef178 = new ConnRef(router, 178);
+ ConnEnd srcPt178(Point(77.9242, 527.557), 15);
+ connRef178->setSourceEndpoint(srcPt178);
+ ConnEnd dstPt178(Point(127.924, 527.557), 15);
+ connRef178->setDestEndpoint(dstPt178);
+ connRef178->setRoutingType((ConnType)2);
+
+ ConnRef *connRef179 = new ConnRef(router, 179);
+ ConnEnd srcPt179(Point(557.924, 54.8422), 15);
+ connRef179->setSourceEndpoint(srcPt179);
+ ConnEnd dstPt179(Point(607.924, 45.8422), 15);
+ connRef179->setDestEndpoint(dstPt179);
+ connRef179->setRoutingType((ConnType)2);
+
+ ConnRef *connRef180 = new ConnRef(router, 180);
+ ConnEnd srcPt180(Point(557.924, 435.557), 15);
+ connRef180->setSourceEndpoint(srcPt180);
+ ConnEnd dstPt180(Point(607.924, 435.557), 15);
+ connRef180->setDestEndpoint(dstPt180);
+ connRef180->setRoutingType((ConnType)2);
+
+ ConnRef *connRef181 = new ConnRef(router, 181);
+ ConnEnd srcPt181(Point(77.9242, 763.557), 15);
+ connRef181->setSourceEndpoint(srcPt181);
+ ConnEnd dstPt181(Point(77.9242, 671.557), 15);
+ connRef181->setDestEndpoint(dstPt181);
+ connRef181->setRoutingType((ConnType)2);
+
+ ConnRef *connRef182 = new ConnRef(router, 182);
+ ConnEnd srcPt182(Point(77.9242, 763.557), 15);
+ connRef182->setSourceEndpoint(srcPt182);
+ ConnEnd dstPt182(Point(127.924, 763.557), 15);
+ connRef182->setDestEndpoint(dstPt182);
+ connRef182->setRoutingType((ConnType)2);
+
+ ConnRef *connRef183 = new ConnRef(router, 183);
+ ConnEnd srcPt183(Point(197.924, 315.557), 15);
+ connRef183->setSourceEndpoint(srcPt183);
+ ConnEnd dstPt183(Point(247.924, 315.557), 15);
+ connRef183->setDestEndpoint(dstPt183);
+ connRef183->setRoutingType((ConnType)2);
+
+ ConnRef *connRef184 = new ConnRef(router, 184);
+ ConnEnd srcPt184(Point(677.924, 343.557), 15);
+ connRef184->setSourceEndpoint(srcPt184);
+ ConnEnd dstPt184(Point(727.924, 343.557), 15);
+ connRef184->setDestEndpoint(dstPt184);
+ connRef184->setRoutingType((ConnType)2);
+
+ ConnRef *connRef185 = new ConnRef(router, 185);
+ ConnEnd srcPt185(Point(797.924, 161.557), 15);
+ connRef185->setSourceEndpoint(srcPt185);
+ ConnEnd dstPt185(Point(847.924, 161.557), 15);
+ connRef185->setDestEndpoint(dstPt185);
+ connRef185->setRoutingType((ConnType)2);
+
+ ConnRef *connRef186 = new ConnRef(router, 186);
+ ConnEnd srcPt186(Point(77.9242, 34.8422), 15);
+ connRef186->setSourceEndpoint(srcPt186);
+ ConnEnd dstPt186(Point(127.924, 34.8422), 15);
+ connRef186->setDestEndpoint(dstPt186);
+ connRef186->setRoutingType((ConnType)2);
+
+ ConnRef *connRef187 = new ConnRef(router, 187);
+ ConnEnd srcPt187(Point(437.924, 527.557), 15);
+ connRef187->setSourceEndpoint(srcPt187);
+ ConnEnd dstPt187(Point(487.924, 527.557), 15);
+ connRef187->setDestEndpoint(dstPt187);
+ connRef187->setRoutingType((ConnType)2);
+
+ ConnRef *connRef188 = new ConnRef(router, 188);
+ ConnEnd srcPt188(Point(77.9242, 619.557), 15);
+ connRef188->setSourceEndpoint(srcPt188);
+ ConnEnd dstPt188(Point(127.924, 619.557), 15);
+ connRef188->setDestEndpoint(dstPt188);
+ connRef188->setRoutingType((ConnType)2);
+
+ ConnRef *connRef189 = new ConnRef(router, 189);
+ ConnEnd srcPt189(Point(747.924, -60.6578), 15);
+ connRef189->setSourceEndpoint(srcPt189);
+ ConnEnd dstPt189(Point(797.924, -60.6578), 15);
+ connRef189->setDestEndpoint(dstPt189);
+ connRef189->setRoutingType((ConnType)2);
+
+ ConnRef *connRef190 = new ConnRef(router, 190);
+ ConnEnd srcPt190(Point(147.924, 34.8422), 15);
+ connRef190->setSourceEndpoint(srcPt190);
+ ConnEnd dstPt190(Point(197.924, 161.557), 15);
+ connRef190->setDestEndpoint(dstPt190);
+ connRef190->setRoutingType((ConnType)2);
+
+ ConnRef *connRef191 = new ConnRef(router, 191);
+ ConnEnd srcPt191(Point(267.924, 161.557), 15);
+ connRef191->setSourceEndpoint(srcPt191);
+ ConnEnd dstPt191(Point(317.924, 161.557), 15);
+ connRef191->setDestEndpoint(dstPt191);
+ connRef191->setRoutingType((ConnType)2);
+
+ ConnRef *connRef192 = new ConnRef(router, 192);
+ ConnEnd srcPt192(Point(197.924, 223.557), 15);
+ connRef192->setSourceEndpoint(srcPt192);
+ ConnEnd dstPt192(Point(197.924, 315.557), 15);
+ connRef192->setDestEndpoint(dstPt192);
+ connRef192->setRoutingType((ConnType)2);
+
+ ConnRef *connRef193 = new ConnRef(router, 193);
+ ConnEnd srcPt193(Point(77.9242, 377.557), 15);
+ connRef193->setSourceEndpoint(srcPt193);
+ ConnEnd dstPt193(Point(77.9242, 527.557), 15);
+ connRef193->setDestEndpoint(dstPt193);
+ connRef193->setRoutingType((ConnType)2);
+
+ ConnRef *connRef194 = new ConnRef(router, 194);
+ ConnEnd srcPt194(Point(147.924, 527.557), 15);
+ connRef194->setSourceEndpoint(srcPt194);
+ ConnEnd dstPt194(Point(197.924, 527.557), 15);
+ connRef194->setDestEndpoint(dstPt194);
+ connRef194->setRoutingType((ConnType)2);
+
+ ConnRef *connRef195 = new ConnRef(router, 195);
+ ConnEnd srcPt195(Point(147.924, 619.557), 15);
+ connRef195->setSourceEndpoint(srcPt195);
+ ConnEnd dstPt195(Point(197.924, 763.557), 15);
+ connRef195->setDestEndpoint(dstPt195);
+ connRef195->setRoutingType((ConnType)2);
+
+ ConnRef *connRef196 = new ConnRef(router, 196);
+ ConnEnd srcPt196(Point(77.9242, 651.557), 15);
+ connRef196->setSourceEndpoint(srcPt196);
+ ConnEnd dstPt196(Point(77.9242, 619.557), 15);
+ connRef196->setDestEndpoint(dstPt196);
+ connRef196->setRoutingType((ConnType)2);
+
+ ConnRef *connRef197 = new ConnRef(router, 197);
+ ConnEnd srcPt197(Point(147.924, 763.557), 15);
+ connRef197->setSourceEndpoint(srcPt197);
+ ConnEnd dstPt197(Point(197.924, 763.557), 15);
+ connRef197->setDestEndpoint(dstPt197);
+ connRef197->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/lineSegWrapperCrash3");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash4.cpp b/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash4.cpp
new file mode 100644
index 0000000..3b03533
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash4.cpp
@@ -0,0 +1,1884 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 0);
+
+ Polygon poly45(4);
+ poly45.ps[0] = Point(577.924, 34.8422);
+ poly45.ps[1] = Point(577.924, 74.8422);
+ poly45.ps[2] = Point(537.924, 74.8422);
+ poly45.ps[3] = Point(537.924, 34.8422);
+ new ShapeRef(router, poly45, 45);
+
+ Polygon poly137(4);
+ poly137.ps[0] = Point(1106.92, 318.557);
+ poly137.ps[1] = Point(1106.92, 358.557);
+ poly137.ps[2] = Point(1050.92, 358.557);
+ poly137.ps[3] = Point(1050.92, 318.557);
+ new ShapeRef(router, poly137, 137);
+
+ Polygon poly138(4);
+ poly138.ps[0] = Point(1226.92, 318.557);
+ poly138.ps[1] = Point(1226.92, 358.557);
+ poly138.ps[2] = Point(1170.92, 358.557);
+ poly138.ps[3] = Point(1170.92, 318.557);
+ new ShapeRef(router, poly138, 138);
+
+ Polygon poly139(4);
+ poly139.ps[0] = Point(1106.92, 82.3422);
+ poly139.ps[1] = Point(1106.92, 122.342);
+ poly139.ps[2] = Point(1050.92, 122.342);
+ poly139.ps[3] = Point(1050.92, 82.3422);
+ new ShapeRef(router, poly139, 139);
+
+ Polygon poly140(4);
+ poly140.ps[0] = Point(1106.92, -9.65778);
+ poly140.ps[1] = Point(1106.92, 30.3422);
+ poly140.ps[2] = Point(1050.92, 30.3422);
+ poly140.ps[3] = Point(1050.92, -9.65778);
+ new ShapeRef(router, poly140, 140);
+
+ Polygon poly141(4);
+ poly141.ps[0] = Point(1226.92, 82.3422);
+ poly141.ps[1] = Point(1226.92, 122.342);
+ poly141.ps[2] = Point(1170.92, 122.342);
+ poly141.ps[3] = Point(1170.92, 82.3422);
+ new ShapeRef(router, poly141, 141);
+
+ Polygon poly142(4);
+ poly142.ps[0] = Point(1106.92, -130.658);
+ poly142.ps[1] = Point(1106.92, -90.6578);
+ poly142.ps[2] = Point(1050.92, -90.6578);
+ poly142.ps[3] = Point(1050.92, -130.658);
+ new ShapeRef(router, poly142, 142);
+
+ Polygon poly143(4);
+ poly143.ps[0] = Point(986.924, 210.557);
+ poly143.ps[1] = Point(986.924, 250.557);
+ poly143.ps[2] = Point(930.924, 250.557);
+ poly143.ps[3] = Point(930.924, 210.557);
+ new ShapeRef(router, poly143, 143);
+
+ Polygon poly144(4);
+ poly144.ps[0] = Point(765.924, 91.5565);
+ poly144.ps[1] = Point(765.924, 131.557);
+ poly144.ps[2] = Point(709.924, 131.557);
+ poly144.ps[3] = Point(709.924, 91.5565);
+ new ShapeRef(router, poly144, 144);
+
+ Polygon poly145(4);
+ poly145.ps[0] = Point(765.924, 790.057);
+ poly145.ps[1] = Point(765.924, 830.057);
+ poly145.ps[2] = Point(709.924, 830.057);
+ poly145.ps[3] = Point(709.924, 790.057);
+ new ShapeRef(router, poly145, 145);
+
+ Polygon poly146(4);
+ poly146.ps[0] = Point(45.9242, 232.5);
+ poly146.ps[1] = Point(45.9242, 272.5);
+ poly146.ps[2] = Point(-14.0758, 272.5);
+ poly146.ps[3] = Point(-14.0758, 232.5);
+ new ShapeRef(router, poly146, 146);
+
+ Polygon poly147(4);
+ poly147.ps[0] = Point(-26.0758, 274.75);
+ poly147.ps[1] = Point(-26.0758, 334.75);
+ poly147.ps[2] = Point(-66.0758, 334.75);
+ poly147.ps[3] = Point(-66.0758, 274.75);
+ new ShapeRef(router, poly147, 147);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(937.924, -80.6578);
+ poly10.ps[1] = Point(937.924, -40.6578);
+ poly10.ps[2] = Point(897.924, -40.6578);
+ poly10.ps[3] = Point(897.924, -80.6578);
+ new ShapeRef(router, poly10, 10);
+
+ Polygon poly33(4);
+ poly33.ps[0] = Point(937.924, 415.557);
+ poly33.ps[1] = Point(937.924, 455.557);
+ poly33.ps[2] = Point(897.924, 455.557);
+ poly33.ps[3] = Point(897.924, 415.557);
+ new ShapeRef(router, poly33, 33);
+
+ Polygon poly114(4);
+ poly114.ps[0] = Point(165.924, 549.557);
+ poly114.ps[1] = Point(165.924, 589.557);
+ poly114.ps[2] = Point(109.924, 589.557);
+ poly114.ps[3] = Point(109.924, 549.557);
+ new ShapeRef(router, poly114, 114);
+
+ Polygon poly115(4);
+ poly115.ps[0] = Point(167.924, 641.557);
+ poly115.ps[1] = Point(167.924, 681.557);
+ poly115.ps[2] = Point(111.924, 681.557);
+ poly115.ps[3] = Point(111.924, 641.557);
+ new ShapeRef(router, poly115, 115);
+
+ Polygon poly116(4);
+ poly116.ps[0] = Point(165.924, 693.557);
+ poly116.ps[1] = Point(165.924, 733.557);
+ poly116.ps[2] = Point(109.924, 733.557);
+ poly116.ps[3] = Point(109.924, 693.557);
+ new ShapeRef(router, poly116, 116);
+
+ Polygon poly117(4);
+ poly117.ps[0] = Point(285.924, 693.557);
+ poly117.ps[1] = Point(285.924, 733.557);
+ poly117.ps[2] = Point(229.924, 733.557);
+ poly117.ps[3] = Point(229.924, 693.557);
+ new ShapeRef(router, poly117, 117);
+
+ Polygon poly118(4);
+ poly118.ps[0] = Point(405.924, 557.557);
+ poly118.ps[1] = Point(405.924, 597.557);
+ poly118.ps[2] = Point(349.924, 597.557);
+ poly118.ps[3] = Point(349.924, 557.557);
+ new ShapeRef(router, poly118, 118);
+
+ Polygon poly119(4);
+ poly119.ps[0] = Point(405.924, 693.557);
+ poly119.ps[1] = Point(405.924, 733.557);
+ poly119.ps[2] = Point(349.924, 733.557);
+ poly119.ps[3] = Point(349.924, 693.557);
+ new ShapeRef(router, poly119, 119);
+
+ Polygon poly120(4);
+ poly120.ps[0] = Point(525.924, 693.557);
+ poly120.ps[1] = Point(525.924, 733.557);
+ poly120.ps[2] = Point(469.924, 733.557);
+ poly120.ps[3] = Point(469.924, 693.557);
+ new ShapeRef(router, poly120, 120);
+
+ Polygon poly121(4);
+ poly121.ps[0] = Point(645.924, 693.557);
+ poly121.ps[1] = Point(645.924, 733.557);
+ poly121.ps[2] = Point(589.924, 733.557);
+ poly121.ps[3] = Point(589.924, 693.557);
+ new ShapeRef(router, poly121, 121);
+
+ Polygon poly122(4);
+ poly122.ps[0] = Point(525.924, 833.057);
+ poly122.ps[1] = Point(525.924, 873.057);
+ poly122.ps[2] = Point(469.924, 873.057);
+ poly122.ps[3] = Point(469.924, 833.057);
+ new ShapeRef(router, poly122, 122);
+
+ Polygon poly123(4);
+ poly123.ps[0] = Point(645.924, 833.057);
+ poly123.ps[1] = Point(645.924, 873.057);
+ poly123.ps[2] = Point(589.924, 873.057);
+ poly123.ps[3] = Point(589.924, 833.057);
+ new ShapeRef(router, poly123, 123);
+
+ Polygon poly124(4);
+ poly124.ps[0] = Point(405.924, 91.5565);
+ poly124.ps[1] = Point(405.924, 131.557);
+ poly124.ps[2] = Point(349.924, 131.557);
+ poly124.ps[3] = Point(349.924, 91.5565);
+ new ShapeRef(router, poly124, 124);
+
+ Polygon poly125(4);
+ poly125.ps[0] = Point(405.924, -42.6578);
+ poly125.ps[1] = Point(405.924, -2.65778);
+ poly125.ps[2] = Point(349.924, -2.65778);
+ poly125.ps[3] = Point(349.924, -42.6578);
+ new ShapeRef(router, poly125, 125);
+
+ Polygon poly126(4);
+ poly126.ps[0] = Point(525.924, -24.1578);
+ poly126.ps[1] = Point(525.924, 15.8422);
+ poly126.ps[2] = Point(469.924, 15.8422);
+ poly126.ps[3] = Point(469.924, -24.1578);
+ new ShapeRef(router, poly126, 126);
+
+ Polygon poly127(4);
+ poly127.ps[0] = Point(645.924, -24.1578);
+ poly127.ps[1] = Point(645.924, 15.8422);
+ poly127.ps[2] = Point(589.924, 15.8422);
+ poly127.ps[3] = Point(589.924, -24.1578);
+ new ShapeRef(router, poly127, 127);
+
+ Polygon poly128(4);
+ poly128.ps[0] = Point(765.924, 504.057);
+ poly128.ps[1] = Point(765.924, 544.057);
+ poly128.ps[2] = Point(709.924, 544.057);
+ poly128.ps[3] = Point(709.924, 504.057);
+ new ShapeRef(router, poly128, 128);
+
+ Polygon poly129(4);
+ poly129.ps[0] = Point(525.924, 457.557);
+ poly129.ps[1] = Point(525.924, 497.557);
+ poly129.ps[2] = Point(469.924, 497.557);
+ poly129.ps[3] = Point(469.924, 457.557);
+ new ShapeRef(router, poly129, 129);
+
+ Polygon poly130(4);
+ poly130.ps[0] = Point(525.924, 365.557);
+ poly130.ps[1] = Point(525.924, 405.557);
+ poly130.ps[2] = Point(469.924, 405.557);
+ poly130.ps[3] = Point(469.924, 365.557);
+ new ShapeRef(router, poly130, 130);
+
+ Polygon poly131(4);
+ poly131.ps[0] = Point(645.924, 457.557);
+ poly131.ps[1] = Point(645.924, 497.557);
+ poly131.ps[2] = Point(589.924, 497.557);
+ poly131.ps[3] = Point(589.924, 457.557);
+ new ShapeRef(router, poly131, 131);
+
+ Polygon poly132(4);
+ poly132.ps[0] = Point(645.924, 365.557);
+ poly132.ps[1] = Point(645.924, 405.557);
+ poly132.ps[2] = Point(589.924, 405.557);
+ poly132.ps[3] = Point(589.924, 365.557);
+ new ShapeRef(router, poly132, 132);
+
+ Polygon poly133(4);
+ poly133.ps[0] = Point(885.924, 273.557);
+ poly133.ps[1] = Point(885.924, 313.557);
+ poly133.ps[2] = Point(829.924, 313.557);
+ poly133.ps[3] = Point(829.924, 273.557);
+ new ShapeRef(router, poly133, 133);
+
+ Polygon poly134(4);
+ poly134.ps[0] = Point(885.924, 365.557);
+ poly134.ps[1] = Point(885.924, 405.557);
+ poly134.ps[2] = Point(829.924, 405.557);
+ poly134.ps[3] = Point(829.924, 365.557);
+ new ShapeRef(router, poly134, 134);
+
+ Polygon poly135(4);
+ poly135.ps[0] = Point(885.924, 91.5565);
+ poly135.ps[1] = Point(885.924, 131.557);
+ poly135.ps[2] = Point(829.924, 131.557);
+ poly135.ps[3] = Point(829.924, 91.5565);
+ new ShapeRef(router, poly135, 135);
+
+ Polygon poly136(4);
+ poly136.ps[0] = Point(765.924, 273.557);
+ poly136.ps[1] = Point(765.924, 313.557);
+ poly136.ps[2] = Point(709.924, 313.557);
+ poly136.ps[3] = Point(709.924, 273.557);
+ new ShapeRef(router, poly136, 136);
+
+ Polygon poly41(4);
+ poly41.ps[0] = Point(577.924, 743.557);
+ poly41.ps[1] = Point(577.924, 783.557);
+ poly41.ps[2] = Point(537.924, 783.557);
+ poly41.ps[3] = Point(537.924, 743.557);
+ new ShapeRef(router, poly41, 41);
+
+ Polygon poly35(4);
+ poly35.ps[0] = Point(1158.92, 40.3422);
+ poly35.ps[1] = Point(1158.92, 80.3422);
+ poly35.ps[2] = Point(1118.92, 80.3422);
+ poly35.ps[3] = Point(1118.92, 40.3422);
+ new ShapeRef(router, poly35, 35);
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(1371.92, -80.6578);
+ poly6.ps[1] = Point(1371.92, -40.6578);
+ poly6.ps[2] = Point(1331.92, -40.6578);
+ poly6.ps[3] = Point(1331.92, -80.6578);
+ new ShapeRef(router, poly6, 6);
+
+ Polygon poly43(4);
+ poly43.ps[0] = Point(1038.92, 1.84222);
+ poly43.ps[1] = Point(1038.92, 41.8422);
+ poly43.ps[2] = Point(998.924, 41.8422);
+ poly43.ps[3] = Point(998.924, 1.84222);
+ new ShapeRef(router, poly43, 43);
+
+ Polygon poly53(4);
+ poly53.ps[0] = Point(577.924, 323.557);
+ poly53.ps[1] = Point(577.924, 363.557);
+ poly53.ps[2] = Point(537.924, 363.557);
+ poly53.ps[3] = Point(537.924, 323.557);
+ new ShapeRef(router, poly53, 53);
+
+ Polygon poly31(4);
+ poly31.ps[0] = Point(1278.92, 141.557);
+ poly31.ps[1] = Point(1278.92, 181.557);
+ poly31.ps[2] = Point(1238.92, 181.557);
+ poly31.ps[3] = Point(1238.92, 141.557);
+ new ShapeRef(router, poly31, 31);
+
+ Polygon poly42(4);
+ poly42.ps[0] = Point(697.924, 415.557);
+ poly42.ps[1] = Point(697.924, 455.557);
+ poly42.ps[2] = Point(657.924, 455.557);
+ poly42.ps[3] = Point(657.924, 415.557);
+ new ShapeRef(router, poly42, 42);
+
+ Polygon poly28(4);
+ poly28.ps[0] = Point(817.924, 323.557);
+ poly28.ps[1] = Point(817.924, 363.557);
+ poly28.ps[2] = Point(777.924, 363.557);
+ poly28.ps[3] = Point(777.924, 323.557);
+ new ShapeRef(router, poly28, 28);
+
+ Polygon poly34(4);
+ poly34.ps[0] = Point(1278.92, 323.557);
+ poly34.ps[1] = Point(1278.92, 363.557);
+ poly34.ps[2] = Point(1238.92, 363.557);
+ poly34.ps[3] = Point(1238.92, 323.557);
+ new ShapeRef(router, poly34, 34);
+
+ Polygon poly36(4);
+ poly36.ps[0] = Point(697.924, 507.557);
+ poly36.ps[1] = Point(697.924, 547.557);
+ poly36.ps[2] = Point(657.924, 547.557);
+ poly36.ps[3] = Point(657.924, 507.557);
+ new ShapeRef(router, poly36, 36);
+
+ Polygon poly30(4);
+ poly30.ps[0] = Point(1278.92, 415.557);
+ poly30.ps[1] = Point(1278.92, 455.557);
+ poly30.ps[2] = Point(1238.92, 455.557);
+ poly30.ps[3] = Point(1238.92, 415.557);
+ new ShapeRef(router, poly30, 30);
+
+ Polygon poly77(4);
+ poly77.ps[0] = Point(267.924, 753.557);
+ poly77.ps[1] = Point(267.924, 773.557);
+ poly77.ps[2] = Point(247.924, 773.557);
+ poly77.ps[3] = Point(247.924, 753.557);
+ new ShapeRef(router, poly77, 77);
+
+ Polygon poly78(4);
+ poly78.ps[0] = Point(387.924, 617.557);
+ poly78.ps[1] = Point(387.924, 637.557);
+ poly78.ps[2] = Point(367.924, 637.557);
+ poly78.ps[3] = Point(367.924, 617.557);
+ new ShapeRef(router, poly78, 78);
+
+ Polygon poly79(4);
+ poly79.ps[0] = Point(387.924, 753.557);
+ poly79.ps[1] = Point(387.924, 773.557);
+ poly79.ps[2] = Point(367.924, 773.557);
+ poly79.ps[3] = Point(367.924, 753.557);
+ new ShapeRef(router, poly79, 79);
+
+ Polygon poly80(4);
+ poly80.ps[0] = Point(507.924, 753.557);
+ poly80.ps[1] = Point(507.924, 773.557);
+ poly80.ps[2] = Point(487.924, 773.557);
+ poly80.ps[3] = Point(487.924, 753.557);
+ new ShapeRef(router, poly80, 80);
+
+ Polygon poly81(4);
+ poly81.ps[0] = Point(627.924, 753.557);
+ poly81.ps[1] = Point(627.924, 773.557);
+ poly81.ps[2] = Point(607.924, 773.557);
+ poly81.ps[3] = Point(607.924, 753.557);
+ new ShapeRef(router, poly81, 81);
+
+ Polygon poly11(4);
+ poly11.ps[0] = Point(817.924, -80.6578);
+ poly11.ps[1] = Point(817.924, -40.6578);
+ poly11.ps[2] = Point(777.924, -40.6578);
+ poly11.ps[3] = Point(777.924, -80.6578);
+ new ShapeRef(router, poly11, 11);
+
+ Polygon poly25(4);
+ poly25.ps[0] = Point(697.924, 883.057);
+ poly25.ps[1] = Point(697.924, 923.057);
+ poly25.ps[2] = Point(657.924, 923.057);
+ poly25.ps[3] = Point(657.924, 883.057);
+ new ShapeRef(router, poly25, 25);
+
+ Polygon poly49(4);
+ poly49.ps[0] = Point(45.9242, 169.75);
+ poly49.ps[1] = Point(45.9242, 334.75);
+ poly49.ps[2] = Point(-242.076, 334.75);
+ poly49.ps[3] = Point(-242.076, 169.75);
+ new ShapeRef(router, poly49, 49);
+
+ Polygon poly52(4);
+ poly52.ps[0] = Point(217.924, 295.557);
+ poly52.ps[1] = Point(217.924, 335.557);
+ poly52.ps[2] = Point(177.924, 335.557);
+ poly52.ps[3] = Point(177.924, 295.557);
+ new ShapeRef(router, poly52, 52);
+
+ Polygon poly50(4);
+ poly50.ps[0] = Point(272.5, -82.1578);
+ poly50.ps[1] = Point(272.5, -47.1578);
+ poly50.ps[2] = Point(35.5, -47.1578);
+ poly50.ps[3] = Point(35.5, -82.1578);
+ new ShapeRef(router, poly50, 50);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(1158.92, -80.6578);
+ poly8.ps[1] = Point(1158.92, -40.6578);
+ poly8.ps[2] = Point(1118.92, -40.6578);
+ poly8.ps[3] = Point(1118.92, -80.6578);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly44(4);
+ poly44.ps[0] = Point(97.9242, 507.557);
+ poly44.ps[1] = Point(97.9242, 547.557);
+ poly44.ps[2] = Point(57.9242, 547.557);
+ poly44.ps[3] = Point(57.9242, 507.557);
+ new ShapeRef(router, poly44, 44);
+
+ Polygon poly18(4);
+ poly18.ps[0] = Point(217.924, 743.557);
+ poly18.ps[1] = Point(217.924, 783.557);
+ poly18.ps[2] = Point(177.924, 783.557);
+ poly18.ps[3] = Point(177.924, 743.557);
+ new ShapeRef(router, poly18, 18);
+
+ Polygon poly1(4);
+ poly1.ps[0] = Point(817.924, 840.057);
+ poly1.ps[1] = Point(817.924, 880.057);
+ poly1.ps[2] = Point(777.924, 880.057);
+ poly1.ps[3] = Point(777.924, 840.057);
+ new ShapeRef(router, poly1, 1);
+
+ Polygon poly21(4);
+ poly21.ps[0] = Point(937.924, 141.557);
+ poly21.ps[1] = Point(937.924, 181.557);
+ poly21.ps[2] = Point(897.924, 181.557);
+ poly21.ps[3] = Point(897.924, 141.557);
+ new ShapeRef(router, poly21, 21);
+
+ Polygon poly38(4);
+ poly38.ps[0] = Point(217.924, 507.557);
+ poly38.ps[1] = Point(217.924, 547.557);
+ poly38.ps[2] = Point(177.924, 547.557);
+ poly38.ps[3] = Point(177.924, 507.557);
+ new ShapeRef(router, poly38, 38);
+
+ Polygon poly24(4);
+ poly24.ps[0] = Point(457.924, 743.557);
+ poly24.ps[1] = Point(457.924, 783.557);
+ poly24.ps[2] = Point(417.924, 783.557);
+ poly24.ps[3] = Point(417.924, 743.557);
+ new ShapeRef(router, poly24, 24);
+
+ Polygon poly39(4);
+ poly39.ps[0] = Point(457.924, 141.557);
+ poly39.ps[1] = Point(457.924, 181.557);
+ poly39.ps[2] = Point(417.924, 181.557);
+ poly39.ps[3] = Point(417.924, 141.557);
+ new ShapeRef(router, poly39, 39);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(1278.92, -80.6578);
+ poly7.ps[1] = Point(1278.92, -40.6578);
+ poly7.ps[2] = Point(1238.92, -40.6578);
+ poly7.ps[3] = Point(1238.92, -80.6578);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly51(4);
+ poly51.ps[0] = Point(1038.92, 323.557);
+ poly51.ps[1] = Point(1038.92, 363.557);
+ poly51.ps[2] = Point(998.924, 363.557);
+ poly51.ps[3] = Point(998.924, 323.557);
+ new ShapeRef(router, poly51, 51);
+
+ Polygon poly27(4);
+ poly27.ps[0] = Point(577.924, 507.557);
+ poly27.ps[1] = Point(577.924, 547.557);
+ poly27.ps[2] = Point(537.924, 547.557);
+ poly27.ps[3] = Point(537.924, 507.557);
+ new ShapeRef(router, poly27, 27);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(1038.92, -80.6578);
+ poly9.ps[1] = Point(1038.92, -40.6578);
+ poly9.ps[2] = Point(998.924, -40.6578);
+ poly9.ps[3] = Point(998.924, -80.6578);
+ new ShapeRef(router, poly9, 9);
+
+ Polygon poly15(4);
+ poly15.ps[0] = Point(1158.92, 415.557);
+ poly15.ps[1] = Point(1158.92, 455.557);
+ poly15.ps[2] = Point(1118.92, 455.557);
+ poly15.ps[3] = Point(1118.92, 415.557);
+ new ShapeRef(router, poly15, 15);
+
+ Polygon poly19(4);
+ poly19.ps[0] = Point(217.924, 141.557);
+ poly19.ps[1] = Point(217.924, 181.557);
+ poly19.ps[2] = Point(177.924, 181.557);
+ poly19.ps[3] = Point(177.924, 141.557);
+ new ShapeRef(router, poly19, 19);
+
+ Polygon poly16(4);
+ poly16.ps[0] = Point(337.924, 743.557);
+ poly16.ps[1] = Point(337.924, 783.557);
+ poly16.ps[2] = Point(297.924, 783.557);
+ poly16.ps[3] = Point(297.924, 743.557);
+ new ShapeRef(router, poly16, 16);
+
+ Polygon poly54(4);
+ poly54.ps[0] = Point(697.924, 323.557);
+ poly54.ps[1] = Point(697.924, 363.557);
+ poly54.ps[2] = Point(657.924, 363.557);
+ poly54.ps[3] = Point(657.924, 323.557);
+ new ShapeRef(router, poly54, 54);
+
+ Polygon poly29(4);
+ poly29.ps[0] = Point(1038.92, 415.557);
+ poly29.ps[1] = Point(1038.92, 455.557);
+ poly29.ps[2] = Point(998.924, 455.557);
+ poly29.ps[3] = Point(998.924, 415.557);
+ new ShapeRef(router, poly29, 29);
+
+ Polygon poly40(4);
+ poly40.ps[0] = Point(97.9242, 141.557);
+ poly40.ps[1] = Point(97.9242, 181.557);
+ poly40.ps[2] = Point(57.9242, 181.557);
+ poly40.ps[3] = Point(57.9242, 141.557);
+ new ShapeRef(router, poly40, 40);
+
+ Polygon poly75(4);
+ poly75.ps[0] = Point(87.9242, 651.557);
+ poly75.ps[1] = Point(87.9242, 671.557);
+ poly75.ps[2] = Point(67.9242, 671.557);
+ poly75.ps[3] = Point(67.9242, 651.557);
+ new ShapeRef(router, poly75, 75);
+
+ Polygon poly76(4);
+ poly76.ps[0] = Point(147.924, 753.557);
+ poly76.ps[1] = Point(147.924, 773.557);
+ poly76.ps[2] = Point(127.924, 773.557);
+ poly76.ps[3] = Point(127.924, 753.557);
+ new ShapeRef(router, poly76, 76);
+
+ Polygon poly92(4);
+ poly92.ps[0] = Point(627.924, 425.557);
+ poly92.ps[1] = Point(627.924, 445.557);
+ poly92.ps[2] = Point(607.924, 445.557);
+ poly92.ps[3] = Point(607.924, 425.557);
+ new ShapeRef(router, poly92, 92);
+
+ Polygon poly93(4);
+ poly93.ps[0] = Point(867.924, 333.557);
+ poly93.ps[1] = Point(867.924, 353.557);
+ poly93.ps[2] = Point(847.924, 353.557);
+ poly93.ps[3] = Point(847.924, 333.557);
+ new ShapeRef(router, poly93, 93);
+
+ Polygon poly94(4);
+ poly94.ps[0] = Point(867.924, 425.557);
+ poly94.ps[1] = Point(867.924, 445.557);
+ poly94.ps[2] = Point(847.924, 445.557);
+ poly94.ps[3] = Point(847.924, 425.557);
+ new ShapeRef(router, poly94, 94);
+
+ Polygon poly95(4);
+ poly95.ps[0] = Point(867.924, 151.557);
+ poly95.ps[1] = Point(867.924, 171.557);
+ poly95.ps[2] = Point(847.924, 171.557);
+ poly95.ps[3] = Point(847.924, 151.557);
+ new ShapeRef(router, poly95, 95);
+
+ Polygon poly96(4);
+ poly96.ps[0] = Point(747.924, 333.557);
+ poly96.ps[1] = Point(747.924, 353.557);
+ poly96.ps[2] = Point(727.924, 353.557);
+ poly96.ps[3] = Point(727.924, 333.557);
+ new ShapeRef(router, poly96, 96);
+
+ Polygon poly97(4);
+ poly97.ps[0] = Point(1088.92, 378.557);
+ poly97.ps[1] = Point(1088.92, 398.557);
+ poly97.ps[2] = Point(1068.92, 398.557);
+ poly97.ps[3] = Point(1068.92, 378.557);
+ new ShapeRef(router, poly97, 97);
+
+ Polygon poly98(4);
+ poly98.ps[0] = Point(1208.92, 378.557);
+ poly98.ps[1] = Point(1208.92, 398.557);
+ poly98.ps[2] = Point(1188.92, 398.557);
+ poly98.ps[3] = Point(1188.92, 378.557);
+ new ShapeRef(router, poly98, 98);
+
+ Polygon poly99(4);
+ poly99.ps[0] = Point(1088.92, 142.342);
+ poly99.ps[1] = Point(1088.92, 162.342);
+ poly99.ps[2] = Point(1068.92, 162.342);
+ poly99.ps[3] = Point(1068.92, 142.342);
+ new ShapeRef(router, poly99, 99);
+
+ Polygon poly100(4);
+ poly100.ps[0] = Point(1088.92, 50.3422);
+ poly100.ps[1] = Point(1088.92, 70.3422);
+ poly100.ps[2] = Point(1068.92, 70.3422);
+ poly100.ps[3] = Point(1068.92, 50.3422);
+ new ShapeRef(router, poly100, 100);
+
+ Polygon poly101(4);
+ poly101.ps[0] = Point(1208.92, 142.342);
+ poly101.ps[1] = Point(1208.92, 162.342);
+ poly101.ps[2] = Point(1188.92, 162.342);
+ poly101.ps[3] = Point(1188.92, 142.342);
+ new ShapeRef(router, poly101, 101);
+
+ Polygon poly102(4);
+ poly102.ps[0] = Point(1088.92, -70.6578);
+ poly102.ps[1] = Point(1088.92, -50.6578);
+ poly102.ps[2] = Point(1068.92, -50.6578);
+ poly102.ps[3] = Point(1068.92, -70.6578);
+ new ShapeRef(router, poly102, 102);
+
+ Polygon poly103(4);
+ poly103.ps[0] = Point(968.924, 270.557);
+ poly103.ps[1] = Point(968.924, 290.557);
+ poly103.ps[2] = Point(948.924, 290.557);
+ poly103.ps[3] = Point(948.924, 270.557);
+ new ShapeRef(router, poly103, 103);
+
+ Polygon poly104(4);
+ poly104.ps[0] = Point(747.924, 151.557);
+ poly104.ps[1] = Point(747.924, 171.557);
+ poly104.ps[2] = Point(727.924, 171.557);
+ poly104.ps[3] = Point(727.924, 151.557);
+ new ShapeRef(router, poly104, 104);
+
+ Polygon poly105(4);
+ poly105.ps[0] = Point(747.924, 850.057);
+ poly105.ps[1] = Point(747.924, 870.057);
+ poly105.ps[2] = Point(727.924, 870.057);
+ poly105.ps[3] = Point(727.924, 850.057);
+ new ShapeRef(router, poly105, 105);
+
+ Polygon poly106(4);
+ poly106.ps[0] = Point(765.924, -130.658);
+ poly106.ps[1] = Point(765.924, -90.6578);
+ poly106.ps[2] = Point(709.924, -90.6578);
+ poly106.ps[3] = Point(709.924, -130.658);
+ new ShapeRef(router, poly106, 106);
+
+ Polygon poly107(4);
+ poly107.ps[0] = Point(165.924, -35.1578);
+ poly107.ps[1] = Point(165.924, 4.84222);
+ poly107.ps[2] = Point(109.924, 4.84222);
+ poly107.ps[3] = Point(109.924, -35.1578);
+ new ShapeRef(router, poly107, 107);
+
+ Polygon poly108(4);
+ poly108.ps[0] = Point(165.924, 91.5565);
+ poly108.ps[1] = Point(165.924, 131.557);
+ poly108.ps[2] = Point(109.924, 131.557);
+ poly108.ps[3] = Point(109.924, 91.5565);
+ new ShapeRef(router, poly108, 108);
+
+ Polygon poly109(4);
+ poly109.ps[0] = Point(285.924, 91.5565);
+ poly109.ps[1] = Point(285.924, 131.557);
+ poly109.ps[2] = Point(229.924, 131.557);
+ poly109.ps[3] = Point(229.924, 91.5565);
+ new ShapeRef(router, poly109, 109);
+
+ Polygon poly110(4);
+ poly110.ps[0] = Point(287.924, 193.557);
+ poly110.ps[1] = Point(287.924, 233.557);
+ poly110.ps[2] = Point(231.924, 233.557);
+ poly110.ps[3] = Point(231.924, 193.557);
+ new ShapeRef(router, poly110, 110);
+
+ Polygon poly111(4);
+ poly111.ps[0] = Point(285.924, 245.557);
+ poly111.ps[1] = Point(285.924, 285.557);
+ poly111.ps[2] = Point(229.924, 285.557);
+ poly111.ps[3] = Point(229.924, 245.557);
+ new ShapeRef(router, poly111, 111);
+
+ Polygon poly112(4);
+ poly112.ps[0] = Point(167.924, 347.557);
+ poly112.ps[1] = Point(167.924, 387.557);
+ poly112.ps[2] = Point(111.924, 387.557);
+ poly112.ps[3] = Point(111.924, 347.557);
+ new ShapeRef(router, poly112, 112);
+
+ Polygon poly113(4);
+ poly113.ps[0] = Point(165.924, 457.557);
+ poly113.ps[1] = Point(165.924, 497.557);
+ poly113.ps[2] = Point(109.924, 497.557);
+ poly113.ps[3] = Point(109.924, 457.557);
+ new ShapeRef(router, poly113, 113);
+
+ Polygon poly17(4);
+ poly17.ps[0] = Point(577.924, 883.057);
+ poly17.ps[1] = Point(577.924, 923.057);
+ poly17.ps[2] = Point(537.924, 923.057);
+ poly17.ps[3] = Point(537.924, 883.057);
+ new ShapeRef(router, poly17, 17);
+
+ Polygon poly32(4);
+ poly32.ps[0] = Point(1038.92, 141.557);
+ poly32.ps[1] = Point(1038.92, 181.557);
+ poly32.ps[2] = Point(998.924, 181.557);
+ poly32.ps[3] = Point(998.924, 141.557);
+ new ShapeRef(router, poly32, 32);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(577.924, 795.557);
+ poly2.ps[1] = Point(577.924, 835.557);
+ poly2.ps[2] = Point(537.924, 835.557);
+ poly2.ps[3] = Point(537.924, 795.557);
+ new ShapeRef(router, poly2, 2);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(1371.92, 29.8422);
+ poly4.ps[1] = Point(1371.92, 69.8422);
+ poly4.ps[2] = Point(1331.92, 69.8422);
+ poly4.ps[3] = Point(1331.92, 29.8422);
+ new ShapeRef(router, poly4, 4);
+
+ Polygon poly20(4);
+ poly20.ps[0] = Point(337.924, 507.557);
+ poly20.ps[1] = Point(337.924, 547.557);
+ poly20.ps[2] = Point(297.924, 547.557);
+ poly20.ps[3] = Point(297.924, 507.557);
+ new ShapeRef(router, poly20, 20);
+
+ Polygon poly48(4);
+ poly48.ps[0] = Point(97.9242, 743.557);
+ poly48.ps[1] = Point(97.9242, 783.557);
+ poly48.ps[2] = Point(57.9242, 783.557);
+ poly48.ps[3] = Point(57.9242, 743.557);
+ new ShapeRef(router, poly48, 48);
+
+ Polygon poly22(4);
+ poly22.ps[0] = Point(697.924, 34.8422);
+ poly22.ps[1] = Point(697.924, 74.8422);
+ poly22.ps[2] = Point(657.924, 74.8422);
+ poly22.ps[3] = Point(657.924, 34.8422);
+ new ShapeRef(router, poly22, 22);
+
+ Polygon poly23(4);
+ poly23.ps[0] = Point(337.924, 141.557);
+ poly23.ps[1] = Point(337.924, 181.557);
+ poly23.ps[2] = Point(297.924, 181.557);
+ poly23.ps[3] = Point(297.924, 141.557);
+ new ShapeRef(router, poly23, 23);
+
+ Polygon poly47(4);
+ poly47.ps[0] = Point(697.924, 271.557);
+ poly47.ps[1] = Point(697.924, 311.557);
+ poly47.ps[2] = Point(657.924, 311.557);
+ poly47.ps[3] = Point(657.924, 271.557);
+ new ShapeRef(router, poly47, 47);
+
+ Polygon poly13(4);
+ poly13.ps[0] = Point(1158.92, 323.557);
+ poly13.ps[1] = Point(1158.92, 363.557);
+ poly13.ps[2] = Point(1118.92, 363.557);
+ poly13.ps[3] = Point(1118.92, 323.557);
+ new ShapeRef(router, poly13, 13);
+
+ Polygon poly46(4);
+ poly46.ps[0] = Point(577.924, 415.557);
+ poly46.ps[1] = Point(577.924, 455.557);
+ poly46.ps[2] = Point(537.924, 455.557);
+ poly46.ps[3] = Point(537.924, 415.557);
+ new ShapeRef(router, poly46, 46);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(1371.92, -22.1578);
+ poly5.ps[1] = Point(1371.92, 17.8422);
+ poly5.ps[2] = Point(1331.92, 17.8422);
+ poly5.ps[3] = Point(1331.92, -22.1578);
+ new ShapeRef(router, poly5, 5);
+
+ Polygon poly56(4);
+ poly56.ps[0] = Point(457.924, -44.6578);
+ poly56.ps[1] = Point(457.924, -4.65778);
+ poly56.ps[2] = Point(417.924, -4.65778);
+ poly56.ps[3] = Point(417.924, -44.6578);
+ new ShapeRef(router, poly56, 56);
+
+ Polygon poly57(4);
+ poly57.ps[0] = Point(817.924, 141.557);
+ poly57.ps[1] = Point(817.924, 181.557);
+ poly57.ps[2] = Point(777.924, 181.557);
+ poly57.ps[3] = Point(777.924, 141.557);
+ new ShapeRef(router, poly57, 57);
+
+ Polygon poly58(4);
+ poly58.ps[0] = Point(97.9242, 14.8422);
+ poly58.ps[1] = Point(97.9242, 54.8422);
+ poly58.ps[2] = Point(57.9242, 54.8422);
+ poly58.ps[3] = Point(57.9242, 14.8422);
+ new ShapeRef(router, poly58, 58);
+
+ Polygon poly59(4);
+ poly59.ps[0] = Point(937.924, 323.557);
+ poly59.ps[1] = Point(937.924, 363.557);
+ poly59.ps[2] = Point(897.924, 363.557);
+ poly59.ps[3] = Point(897.924, 323.557);
+ new ShapeRef(router, poly59, 59);
+
+ Polygon poly69(4);
+ poly69.ps[0] = Point(267.924, 151.557);
+ poly69.ps[1] = Point(267.924, 171.557);
+ poly69.ps[2] = Point(247.924, 171.557);
+ poly69.ps[3] = Point(247.924, 151.557);
+ new ShapeRef(router, poly69, 69);
+
+ Polygon poly63(4);
+ poly63.ps[0] = Point(457.924, 507.557);
+ poly63.ps[1] = Point(457.924, 547.557);
+ poly63.ps[2] = Point(417.924, 547.557);
+ poly63.ps[3] = Point(417.924, 507.557);
+ new ShapeRef(router, poly63, 63);
+
+ Polygon poly70(4);
+ poly70.ps[0] = Point(207.924, 203.557);
+ poly70.ps[1] = Point(207.924, 223.557);
+ poly70.ps[2] = Point(187.924, 223.557);
+ poly70.ps[3] = Point(187.924, 203.557);
+ new ShapeRef(router, poly70, 70);
+
+ Polygon poly60(4);
+ poly60.ps[0] = Point(937.924, 1.84222);
+ poly60.ps[1] = Point(937.924, 41.8422);
+ poly60.ps[2] = Point(897.924, 41.8422);
+ poly60.ps[3] = Point(897.924, 1.84222);
+ new ShapeRef(router, poly60, 60);
+
+ Polygon poly61(4);
+ poly61.ps[0] = Point(577.924, -44.6578);
+ poly61.ps[1] = Point(577.924, -4.65778);
+ poly61.ps[2] = Point(537.924, -4.65778);
+ poly61.ps[3] = Point(537.924, -44.6578);
+ new ShapeRef(router, poly61, 61);
+
+ Polygon poly62(4);
+ poly62.ps[0] = Point(577.924, 629.557);
+ poly62.ps[1] = Point(577.924, 669.557);
+ poly62.ps[2] = Point(537.924, 669.557);
+ poly62.ps[3] = Point(537.924, 629.557);
+ new ShapeRef(router, poly62, 62);
+
+ Polygon poly66(4);
+ poly66.ps[0] = Point(747.924, -70.6578);
+ poly66.ps[1] = Point(747.924, -50.6578);
+ poly66.ps[2] = Point(727.924, -50.6578);
+ poly66.ps[3] = Point(727.924, -70.6578);
+ new ShapeRef(router, poly66, 66);
+
+ Polygon poly67(4);
+ poly67.ps[0] = Point(147.924, 24.8422);
+ poly67.ps[1] = Point(147.924, 44.8422);
+ poly67.ps[2] = Point(127.924, 44.8422);
+ poly67.ps[3] = Point(127.924, 24.8422);
+ new ShapeRef(router, poly67, 67);
+
+ Polygon poly68(4);
+ poly68.ps[0] = Point(147.924, 151.557);
+ poly68.ps[1] = Point(147.924, 171.557);
+ poly68.ps[2] = Point(127.924, 171.557);
+ poly68.ps[3] = Point(127.924, 151.557);
+ new ShapeRef(router, poly68, 68);
+
+ Polygon poly72(4);
+ poly72.ps[0] = Point(87.9242, 357.557);
+ poly72.ps[1] = Point(87.9242, 377.557);
+ poly72.ps[2] = Point(67.9242, 377.557);
+ poly72.ps[3] = Point(67.9242, 357.557);
+ new ShapeRef(router, poly72, 72);
+
+ Polygon poly65(4);
+ poly65.ps[0] = Point(97.9242, 599.557);
+ poly65.ps[1] = Point(97.9242, 639.557);
+ poly65.ps[2] = Point(57.9242, 639.557);
+ poly65.ps[3] = Point(57.9242, 599.557);
+ new ShapeRef(router, poly65, 65);
+
+ Polygon poly64(4);
+ poly64.ps[0] = Point(817.924, 554.057);
+ poly64.ps[1] = Point(817.924, 594.057);
+ poly64.ps[2] = Point(777.924, 594.057);
+ poly64.ps[3] = Point(777.924, 554.057);
+ new ShapeRef(router, poly64, 64);
+
+ Polygon poly14(4);
+ poly14.ps[0] = Point(1158.92, 141.557);
+ poly14.ps[1] = Point(1158.92, 181.557);
+ poly14.ps[2] = Point(1118.92, 181.557);
+ poly14.ps[3] = Point(1118.92, 141.557);
+ new ShapeRef(router, poly14, 14);
+
+ Polygon poly71(4);
+ poly71.ps[0] = Point(267.924, 305.557);
+ poly71.ps[1] = Point(267.924, 325.557);
+ poly71.ps[2] = Point(247.924, 325.557);
+ poly71.ps[3] = Point(247.924, 305.557);
+ new ShapeRef(router, poly71, 71);
+
+ Polygon poly73(4);
+ poly73.ps[0] = Point(147.924, 517.557);
+ poly73.ps[1] = Point(147.924, 537.557);
+ poly73.ps[2] = Point(127.924, 537.557);
+ poly73.ps[3] = Point(127.924, 517.557);
+ new ShapeRef(router, poly73, 73);
+
+ Polygon poly74(4);
+ poly74.ps[0] = Point(147.924, 609.557);
+ poly74.ps[1] = Point(147.924, 629.557);
+ poly74.ps[2] = Point(127.924, 629.557);
+ poly74.ps[3] = Point(127.924, 609.557);
+ new ShapeRef(router, poly74, 74);
+
+ Polygon poly37(4);
+ poly37.ps[0] = Point(457.924, 607.557);
+ poly37.ps[1] = Point(457.924, 647.557);
+ poly37.ps[2] = Point(417.924, 647.557);
+ poly37.ps[3] = Point(417.924, 607.557);
+ new ShapeRef(router, poly37, 37);
+
+ Polygon poly82(4);
+ poly82.ps[0] = Point(507.924, 893.057);
+ poly82.ps[1] = Point(507.924, 913.057);
+ poly82.ps[2] = Point(487.924, 913.057);
+ poly82.ps[3] = Point(487.924, 893.057);
+ new ShapeRef(router, poly82, 82);
+
+ Polygon poly83(4);
+ poly83.ps[0] = Point(627.924, 893.057);
+ poly83.ps[1] = Point(627.924, 913.057);
+ poly83.ps[2] = Point(607.924, 913.057);
+ poly83.ps[3] = Point(607.924, 893.057);
+ new ShapeRef(router, poly83, 83);
+
+ Polygon poly84(4);
+ poly84.ps[0] = Point(387.924, 151.557);
+ poly84.ps[1] = Point(387.924, 171.557);
+ poly84.ps[2] = Point(367.924, 171.557);
+ poly84.ps[3] = Point(367.924, 151.557);
+ new ShapeRef(router, poly84, 84);
+
+ Polygon poly85(4);
+ poly85.ps[0] = Point(387.924, 17.3422);
+ poly85.ps[1] = Point(387.924, 37.3422);
+ poly85.ps[2] = Point(367.924, 37.3422);
+ poly85.ps[3] = Point(367.924, 17.3422);
+ new ShapeRef(router, poly85, 85);
+
+ Polygon poly86(4);
+ poly86.ps[0] = Point(507.924, 35.8422);
+ poly86.ps[1] = Point(507.924, 55.8422);
+ poly86.ps[2] = Point(487.924, 55.8422);
+ poly86.ps[3] = Point(487.924, 35.8422);
+ new ShapeRef(router, poly86, 86);
+
+ Polygon poly87(4);
+ poly87.ps[0] = Point(627.924, 35.8422);
+ poly87.ps[1] = Point(627.924, 55.8422);
+ poly87.ps[2] = Point(607.924, 55.8422);
+ poly87.ps[3] = Point(607.924, 35.8422);
+ new ShapeRef(router, poly87, 87);
+
+ Polygon poly88(4);
+ poly88.ps[0] = Point(747.924, 564.057);
+ poly88.ps[1] = Point(747.924, 584.057);
+ poly88.ps[2] = Point(727.924, 584.057);
+ poly88.ps[3] = Point(727.924, 564.057);
+ new ShapeRef(router, poly88, 88);
+
+ Polygon poly89(4);
+ poly89.ps[0] = Point(507.924, 517.557);
+ poly89.ps[1] = Point(507.924, 537.557);
+ poly89.ps[2] = Point(487.924, 537.557);
+ poly89.ps[3] = Point(487.924, 517.557);
+ new ShapeRef(router, poly89, 89);
+
+ Polygon poly90(4);
+ poly90.ps[0] = Point(507.924, 425.557);
+ poly90.ps[1] = Point(507.924, 445.557);
+ poly90.ps[2] = Point(487.924, 445.557);
+ poly90.ps[3] = Point(487.924, 425.557);
+ new ShapeRef(router, poly90, 90);
+
+ Polygon poly91(4);
+ poly91.ps[0] = Point(627.924, 517.557);
+ poly91.ps[1] = Point(627.924, 537.557);
+ poly91.ps[2] = Point(607.924, 537.557);
+ poly91.ps[3] = Point(607.924, 517.557);
+ new ShapeRef(router, poly91, 91);
+
+ Polygon poly26(4);
+ poly26.ps[0] = Point(697.924, 743.557);
+ poly26.ps[1] = Point(697.924, 783.557);
+ poly26.ps[2] = Point(657.924, 783.557);
+ poly26.ps[3] = Point(657.924, 743.557);
+ new ShapeRef(router, poly26, 26);
+
+ Polygon poly12(4);
+ poly12.ps[0] = Point(1038.92, 260.557);
+ poly12.ps[1] = Point(1038.92, 300.557);
+ poly12.ps[2] = Point(998.924, 300.557);
+ poly12.ps[3] = Point(998.924, 260.557);
+ new ShapeRef(router, poly12, 12);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(1278.92, -22.1578);
+ poly3.ps[1] = Point(1278.92, 17.8422);
+ poly3.ps[2] = Point(1238.92, 17.8422);
+ poly3.ps[3] = Point(1238.92, -22.1578);
+ new ShapeRef(router, poly3, 3);
+
+ Polygon poly55(4);
+ poly55.ps[0] = Point(457.924, 7.34222);
+ poly55.ps[1] = Point(457.924, 47.3422);
+ poly55.ps[2] = Point(417.924, 47.3422);
+ poly55.ps[3] = Point(417.924, 7.34222);
+ new ShapeRef(router, poly55, 55);
+
+ ConnRef *connRef148 = new ConnRef(router, 148);
+ ConnEnd srcPt148(Point(1018.92, -60.6578), 15);
+ connRef148->setSourceEndpoint(srcPt148);
+ ConnEnd dstPt148(Point(1068.92, -60.6578), 15);
+ connRef148->setDestEndpoint(dstPt148);
+ connRef148->setRoutingType((ConnType)2);
+
+ ConnRef *connRef149 = new ConnRef(router, 149);
+ ConnEnd srcPt149(Point(1138.92, 161.557), 15);
+ connRef149->setSourceEndpoint(srcPt149);
+ ConnEnd dstPt149(Point(1188.92, 152.342), 15);
+ connRef149->setDestEndpoint(dstPt149);
+ connRef149->setRoutingType((ConnType)2);
+
+ ConnRef *connRef150 = new ConnRef(router, 150);
+ ConnEnd srcPt150(Point(1138.92, 435.557), 15);
+ connRef150->setSourceEndpoint(srcPt150);
+ ConnEnd dstPt150(Point(1188.92, 388.557), 15);
+ connRef150->setDestEndpoint(dstPt150);
+ connRef150->setRoutingType((ConnType)2);
+
+ ConnRef *connRef151 = new ConnRef(router, 151);
+ ConnEnd srcPt151(Point(317.924, 763.557), 15);
+ connRef151->setSourceEndpoint(srcPt151);
+ ConnEnd dstPt151(Point(367.924, 627.557), 15);
+ connRef151->setDestEndpoint(dstPt151);
+ connRef151->setRoutingType((ConnType)2);
+
+ ConnRef *connRef152 = new ConnRef(router, 152);
+ ConnEnd srcPt152(Point(317.924, 763.557), 15);
+ connRef152->setSourceEndpoint(srcPt152);
+ ConnEnd dstPt152(Point(367.924, 763.557), 15);
+ connRef152->setDestEndpoint(dstPt152);
+ connRef152->setRoutingType((ConnType)2);
+
+ ConnRef *connRef153 = new ConnRef(router, 153);
+ ConnEnd srcPt153(Point(317.924, 763.557), 15);
+ connRef153->setSourceEndpoint(srcPt153);
+ ConnEnd dstPt153(Point(487.924, 903.057), 15);
+ connRef153->setDestEndpoint(dstPt153);
+ connRef153->setRoutingType((ConnType)2);
+
+ ConnRef *connRef154 = new ConnRef(router, 154);
+ ConnEnd srcPt154(Point(317.924, 763.557), 15);
+ connRef154->setSourceEndpoint(srcPt154);
+ ConnEnd dstPt154(Point(727.924, 574.057), 15);
+ connRef154->setDestEndpoint(dstPt154);
+ connRef154->setRoutingType((ConnType)2);
+
+ ConnRef *connRef155 = new ConnRef(router, 155);
+ ConnEnd srcPt155(Point(557.924, 903.057), 15);
+ connRef155->setSourceEndpoint(srcPt155);
+ ConnEnd dstPt155(Point(607.924, 903.057), 15);
+ connRef155->setDestEndpoint(dstPt155);
+ connRef155->setRoutingType((ConnType)2);
+
+ ConnRef *connRef156 = new ConnRef(router, 156);
+ ConnEnd srcPt156(Point(197.924, 763.557), 15);
+ connRef156->setSourceEndpoint(srcPt156);
+ ConnEnd dstPt156(Point(247.924, 763.557), 15);
+ connRef156->setDestEndpoint(dstPt156);
+ connRef156->setRoutingType((ConnType)2);
+
+ ConnRef *connRef157 = new ConnRef(router, 157);
+ ConnEnd srcPt157(Point(147.924, 161.557), 15);
+ connRef157->setSourceEndpoint(srcPt157);
+ ConnEnd dstPt157(Point(197.924, 161.557), 15);
+ connRef157->setDestEndpoint(dstPt157);
+ connRef157->setRoutingType((ConnType)2);
+
+ ConnRef *connRef158 = new ConnRef(router, 158);
+ ConnEnd srcPt158(Point(197.924, 161.557), 15);
+ connRef158->setSourceEndpoint(srcPt158);
+ ConnEnd dstPt158(Point(247.924, 161.557), 15);
+ connRef158->setDestEndpoint(dstPt158);
+ connRef158->setRoutingType((ConnType)2);
+
+ ConnRef *connRef159 = new ConnRef(router, 159);
+ ConnEnd srcPt159(Point(197.924, 161.557), 15);
+ connRef159->setSourceEndpoint(srcPt159);
+ ConnEnd dstPt159(Point(197.924, 203.557), 15);
+ connRef159->setDestEndpoint(dstPt159);
+ connRef159->setRoutingType((ConnType)2);
+
+ ConnRef *connRef160 = new ConnRef(router, 160);
+ ConnEnd srcPt160(Point(317.924, 161.557), 15);
+ connRef160->setSourceEndpoint(srcPt160);
+ ConnEnd dstPt160(Point(727.924, -60.6578), 15);
+ connRef160->setDestEndpoint(dstPt160);
+ connRef160->setRoutingType((ConnType)2);
+
+ ConnRef *connRef161 = new ConnRef(router, 161);
+ ConnEnd srcPt161(Point(317.924, 161.557), 15);
+ connRef161->setSourceEndpoint(srcPt161);
+ ConnEnd dstPt161(Point(367.924, 161.557), 15);
+ connRef161->setDestEndpoint(dstPt161);
+ connRef161->setRoutingType((ConnType)2);
+
+ ConnRef *connRef162 = new ConnRef(router, 162);
+ ConnEnd srcPt162(Point(317.924, 161.557), 15);
+ connRef162->setSourceEndpoint(srcPt162);
+ ConnEnd dstPt162(Point(367.924, 27.3422), 15);
+ connRef162->setDestEndpoint(dstPt162);
+ connRef162->setRoutingType((ConnType)2);
+
+ ConnRef *connRef163 = new ConnRef(router, 163);
+ ConnEnd srcPt163(Point(317.924, 161.557), 15);
+ connRef163->setSourceEndpoint(srcPt163);
+ ConnEnd dstPt163(Point(487.924, 435.557), 15);
+ connRef163->setDestEndpoint(dstPt163);
+ connRef163->setRoutingType((ConnType)2);
+
+ ConnRef *connRef164 = new ConnRef(router, 164);
+ ConnEnd srcPt164(Point(437.924, 763.557), 15);
+ connRef164->setSourceEndpoint(srcPt164);
+ ConnEnd dstPt164(Point(487.924, 763.557), 15);
+ connRef164->setDestEndpoint(dstPt164);
+ connRef164->setRoutingType((ConnType)2);
+
+ ConnRef *connRef165 = new ConnRef(router, 165);
+ ConnEnd srcPt165(Point(437.924, 763.557), 15);
+ connRef165->setSourceEndpoint(srcPt165);
+ ConnEnd dstPt165(Point(727.924, 860.057), 15);
+ connRef165->setDestEndpoint(dstPt165);
+ connRef165->setRoutingType((ConnType)2);
+
+ ConnRef *connRef166 = new ConnRef(router, 166);
+ ConnEnd srcPt166(Point(557.924, 527.557), 15);
+ connRef166->setSourceEndpoint(srcPt166);
+ ConnEnd dstPt166(Point(607.924, 527.557), 15);
+ connRef166->setDestEndpoint(dstPt166);
+ connRef166->setRoutingType((ConnType)2);
+
+ ConnRef *connRef167 = new ConnRef(router, 167);
+ ConnEnd srcPt167(Point(797.924, 343.557), 15);
+ connRef167->setSourceEndpoint(srcPt167);
+ ConnEnd dstPt167(Point(847.924, 343.557), 15);
+ connRef167->setDestEndpoint(dstPt167);
+ connRef167->setRoutingType((ConnType)2);
+
+ ConnRef *connRef247 = new ConnRef(router, 247);
+ ConnEnd srcPt247(Point(617.924, -4.15778), 15);
+ connRef247->setSourceEndpoint(srcPt247);
+ ConnEnd dstPt247(Point(617.924, 45.8422), 15);
+ connRef247->setDestEndpoint(dstPt247);
+ connRef247->setRoutingType((ConnType)2);
+
+ ConnRef *connRef248 = new ConnRef(router, 248);
+ ConnEnd srcPt248(Point(737.924, 524.057), 15);
+ connRef248->setSourceEndpoint(srcPt248);
+ ConnEnd dstPt248(Point(737.924, 574.057), 15);
+ connRef248->setDestEndpoint(dstPt248);
+ connRef248->setRoutingType((ConnType)2);
+
+ ConnRef *connRef249 = new ConnRef(router, 249);
+ ConnEnd srcPt249(Point(497.924, 477.557), 15);
+ connRef249->setSourceEndpoint(srcPt249);
+ ConnEnd dstPt249(Point(497.924, 527.557), 15);
+ connRef249->setDestEndpoint(dstPt249);
+ connRef249->setRoutingType((ConnType)2);
+
+ ConnRef *connRef250 = new ConnRef(router, 250);
+ ConnEnd srcPt250(Point(497.924, 385.557), 15);
+ connRef250->setSourceEndpoint(srcPt250);
+ ConnEnd dstPt250(Point(497.924, 435.557), 15);
+ connRef250->setDestEndpoint(dstPt250);
+ connRef250->setRoutingType((ConnType)2);
+
+ ConnRef *connRef251 = new ConnRef(router, 251);
+ ConnEnd srcPt251(Point(617.924, 477.557), 15);
+ connRef251->setSourceEndpoint(srcPt251);
+ ConnEnd dstPt251(Point(617.924, 527.557), 15);
+ connRef251->setDestEndpoint(dstPt251);
+ connRef251->setRoutingType((ConnType)2);
+
+ ConnRef *connRef252 = new ConnRef(router, 252);
+ ConnEnd srcPt252(Point(617.924, 385.557), 15);
+ connRef252->setSourceEndpoint(srcPt252);
+ ConnEnd dstPt252(Point(617.924, 435.557), 15);
+ connRef252->setDestEndpoint(dstPt252);
+ connRef252->setRoutingType((ConnType)2);
+
+ ConnRef *connRef253 = new ConnRef(router, 253);
+ ConnEnd srcPt253(Point(857.924, 293.557), 15);
+ connRef253->setSourceEndpoint(srcPt253);
+ ConnEnd dstPt253(Point(857.924, 343.557), 15);
+ connRef253->setDestEndpoint(dstPt253);
+ connRef253->setRoutingType((ConnType)2);
+
+ ConnRef *connRef254 = new ConnRef(router, 254);
+ ConnEnd srcPt254(Point(857.924, 385.557), 15);
+ connRef254->setSourceEndpoint(srcPt254);
+ ConnEnd dstPt254(Point(857.924, 435.557), 15);
+ connRef254->setDestEndpoint(dstPt254);
+ connRef254->setRoutingType((ConnType)2);
+
+ ConnRef *connRef255 = new ConnRef(router, 255);
+ ConnEnd srcPt255(Point(857.924, 111.557), 15);
+ connRef255->setSourceEndpoint(srcPt255);
+ ConnEnd dstPt255(Point(857.924, 161.557), 15);
+ connRef255->setDestEndpoint(dstPt255);
+ connRef255->setRoutingType((ConnType)2);
+
+ ConnRef *connRef256 = new ConnRef(router, 256);
+ ConnEnd srcPt256(Point(737.924, 293.557), 15);
+ connRef256->setSourceEndpoint(srcPt256);
+ ConnEnd dstPt256(Point(737.924, 343.557), 15);
+ connRef256->setDestEndpoint(dstPt256);
+ connRef256->setRoutingType((ConnType)2);
+
+ ConnRef *connRef257 = new ConnRef(router, 257);
+ ConnEnd srcPt257(Point(1078.92, 338.557), 15);
+ connRef257->setSourceEndpoint(srcPt257);
+ ConnEnd dstPt257(Point(1078.92, 388.557), 15);
+ connRef257->setDestEndpoint(dstPt257);
+ connRef257->setRoutingType((ConnType)2);
+
+ ConnRef *connRef258 = new ConnRef(router, 258);
+ ConnEnd srcPt258(Point(1198.92, 338.557), 15);
+ connRef258->setSourceEndpoint(srcPt258);
+ ConnEnd dstPt258(Point(1198.92, 388.557), 15);
+ connRef258->setDestEndpoint(dstPt258);
+ connRef258->setRoutingType((ConnType)2);
+
+ ConnRef *connRef259 = new ConnRef(router, 259);
+ ConnEnd srcPt259(Point(1078.92, 102.342), 15);
+ connRef259->setSourceEndpoint(srcPt259);
+ ConnEnd dstPt259(Point(1078.92, 152.342), 15);
+ connRef259->setDestEndpoint(dstPt259);
+ connRef259->setRoutingType((ConnType)2);
+
+ ConnRef *connRef260 = new ConnRef(router, 260);
+ ConnEnd srcPt260(Point(1078.92, 10.3422), 15);
+ connRef260->setSourceEndpoint(srcPt260);
+ ConnEnd dstPt260(Point(1078.92, 60.3422), 15);
+ connRef260->setDestEndpoint(dstPt260);
+ connRef260->setRoutingType((ConnType)2);
+
+ ConnRef *connRef261 = new ConnRef(router, 261);
+ ConnEnd srcPt261(Point(1198.92, 102.342), 15);
+ connRef261->setSourceEndpoint(srcPt261);
+ ConnEnd dstPt261(Point(1198.92, 152.342), 15);
+ connRef261->setDestEndpoint(dstPt261);
+ connRef261->setRoutingType((ConnType)2);
+
+ ConnRef *connRef262 = new ConnRef(router, 262);
+ ConnEnd srcPt262(Point(1078.92, -110.658), 15);
+ connRef262->setSourceEndpoint(srcPt262);
+ ConnEnd dstPt262(Point(1078.92, -60.6578), 15);
+ connRef262->setDestEndpoint(dstPt262);
+ connRef262->setRoutingType((ConnType)2);
+
+ ConnRef *connRef263 = new ConnRef(router, 263);
+ ConnEnd srcPt263(Point(958.924, 230.557), 15);
+ connRef263->setSourceEndpoint(srcPt263);
+ ConnEnd dstPt263(Point(958.924, 280.557), 15);
+ connRef263->setDestEndpoint(dstPt263);
+ connRef263->setRoutingType((ConnType)2);
+
+ ConnRef *connRef264 = new ConnRef(router, 264);
+ ConnEnd srcPt264(Point(737.924, 111.557), 15);
+ connRef264->setSourceEndpoint(srcPt264);
+ ConnEnd dstPt264(Point(737.924, 161.557), 15);
+ connRef264->setDestEndpoint(dstPt264);
+ connRef264->setRoutingType((ConnType)2);
+
+ ConnRef *connRef265 = new ConnRef(router, 265);
+ ConnEnd srcPt265(Point(737.924, 810.057), 15);
+ connRef265->setSourceEndpoint(srcPt265);
+ ConnEnd dstPt265(Point(737.924, 860.057), 15);
+ connRef265->setDestEndpoint(dstPt265);
+ connRef265->setRoutingType((ConnType)2);
+
+ ConnRef *connRef266 = new ConnRef(router, 266);
+ ConnEnd srcPt266(Point(77.9242, 161.557), 15);
+ connRef266->setSourceEndpoint(srcPt266);
+ ConnEnd dstPt266(Point(40.9242, 252.5), 15);
+ connRef266->setDestEndpoint(dstPt266);
+ connRef266->setRoutingType((ConnType)2);
+
+ ConnRef *connRef267 = new ConnRef(router, 267);
+ ConnEnd srcPt267(Point(77.9242, 763.557), 15);
+ connRef267->setSourceEndpoint(srcPt267);
+ ConnEnd dstPt267(Point(-46.0758, 329.75), 15);
+ connRef267->setDestEndpoint(dstPt267);
+ connRef267->setRoutingType((ConnType)2);
+
+ ConnRef *connRef168 = new ConnRef(router, 168);
+ ConnEnd srcPt168(Point(797.924, 343.557), 15);
+ connRef168->setSourceEndpoint(srcPt168);
+ ConnEnd dstPt168(Point(847.924, 435.557), 15);
+ connRef168->setDestEndpoint(dstPt168);
+ connRef168->setRoutingType((ConnType)2);
+
+ ConnRef *connRef169 = new ConnRef(router, 169);
+ ConnEnd srcPt169(Point(1018.92, 435.557), 15);
+ connRef169->setSourceEndpoint(srcPt169);
+ ConnEnd dstPt169(Point(1068.92, 388.557), 15);
+ connRef169->setDestEndpoint(dstPt169);
+ connRef169->setRoutingType((ConnType)2);
+
+ ConnRef *connRef170 = new ConnRef(router, 170);
+ ConnEnd srcPt170(Point(1018.92, 161.557), 15);
+ connRef170->setSourceEndpoint(srcPt170);
+ ConnEnd dstPt170(Point(1068.92, 152.342), 15);
+ connRef170->setDestEndpoint(dstPt170);
+ connRef170->setRoutingType((ConnType)2);
+
+ ConnRef *connRef171 = new ConnRef(router, 171);
+ ConnEnd srcPt171(Point(1018.92, 161.557), 15);
+ connRef171->setSourceEndpoint(srcPt171);
+ ConnEnd dstPt171(Point(1068.92, 60.3422), 15);
+ connRef171->setDestEndpoint(dstPt171);
+ connRef171->setRoutingType((ConnType)2);
+
+ ConnRef *connRef172 = new ConnRef(router, 172);
+ ConnEnd srcPt172(Point(267.924, 315.557), 15);
+ connRef172->setSourceEndpoint(srcPt172);
+ ConnEnd dstPt172(Point(437.924, 161.557), 15);
+ connRef172->setDestEndpoint(dstPt172);
+ connRef172->setRoutingType((ConnType)2);
+
+ ConnRef *connRef173 = new ConnRef(router, 173);
+ ConnEnd srcPt173(Point(437.924, 161.557), 15);
+ connRef173->setSourceEndpoint(srcPt173);
+ ConnEnd dstPt173(Point(487.924, 45.8422), 15);
+ connRef173->setDestEndpoint(dstPt173);
+ connRef173->setRoutingType((ConnType)2);
+
+ ConnRef *connRef174 = new ConnRef(router, 174);
+ ConnEnd srcPt174(Point(437.924, 161.557), 15);
+ connRef174->setSourceEndpoint(srcPt174);
+ ConnEnd dstPt174(Point(727.924, 161.557), 15);
+ connRef174->setDestEndpoint(dstPt174);
+ connRef174->setRoutingType((ConnType)2);
+
+ ConnRef *connRef175 = new ConnRef(router, 175);
+ ConnEnd srcPt175(Point(77.9242, 161.557), 15);
+ connRef175->setSourceEndpoint(srcPt175);
+ ConnEnd dstPt175(Point(127.924, 161.557), 15);
+ connRef175->setDestEndpoint(dstPt175);
+ connRef175->setRoutingType((ConnType)2);
+
+ ConnRef *connRef176 = new ConnRef(router, 176);
+ ConnEnd srcPt176(Point(77.9242, 161.557), 15);
+ connRef176->setSourceEndpoint(srcPt176);
+ ConnEnd dstPt176(Point(77.9242, 357.557), 15);
+ connRef176->setDestEndpoint(dstPt176);
+ connRef176->setRoutingType((ConnType)2);
+
+ ConnRef *connRef177 = new ConnRef(router, 177);
+ ConnEnd srcPt177(Point(557.924, 763.557), 15);
+ connRef177->setSourceEndpoint(srcPt177);
+ ConnEnd dstPt177(Point(607.924, 763.557), 15);
+ connRef177->setDestEndpoint(dstPt177);
+ connRef177->setRoutingType((ConnType)2);
+
+ ConnRef *connRef178 = new ConnRef(router, 178);
+ ConnEnd srcPt178(Point(77.9242, 527.557), 15);
+ connRef178->setSourceEndpoint(srcPt178);
+ ConnEnd dstPt178(Point(127.924, 527.557), 15);
+ connRef178->setDestEndpoint(dstPt178);
+ connRef178->setRoutingType((ConnType)2);
+
+ ConnRef *connRef179 = new ConnRef(router, 179);
+ ConnEnd srcPt179(Point(557.924, 54.8422), 15);
+ connRef179->setSourceEndpoint(srcPt179);
+ ConnEnd dstPt179(Point(607.924, 45.8422), 15);
+ connRef179->setDestEndpoint(dstPt179);
+ connRef179->setRoutingType((ConnType)2);
+
+ ConnRef *connRef180 = new ConnRef(router, 180);
+ ConnEnd srcPt180(Point(557.924, 435.557), 15);
+ connRef180->setSourceEndpoint(srcPt180);
+ ConnEnd dstPt180(Point(607.924, 435.557), 15);
+ connRef180->setDestEndpoint(dstPt180);
+ connRef180->setRoutingType((ConnType)2);
+
+ ConnRef *connRef181 = new ConnRef(router, 181);
+ ConnEnd srcPt181(Point(77.9242, 763.557), 15);
+ connRef181->setSourceEndpoint(srcPt181);
+ ConnEnd dstPt181(Point(77.9242, 671.557), 15);
+ connRef181->setDestEndpoint(dstPt181);
+ connRef181->setRoutingType((ConnType)2);
+
+ ConnRef *connRef182 = new ConnRef(router, 182);
+ ConnEnd srcPt182(Point(77.9242, 763.557), 15);
+ connRef182->setSourceEndpoint(srcPt182);
+ ConnEnd dstPt182(Point(127.924, 763.557), 15);
+ connRef182->setDestEndpoint(dstPt182);
+ connRef182->setRoutingType((ConnType)2);
+
+ ConnRef *connRef183 = new ConnRef(router, 183);
+ ConnEnd srcPt183(Point(197.924, 315.557), 15);
+ connRef183->setSourceEndpoint(srcPt183);
+ ConnEnd dstPt183(Point(247.924, 315.557), 15);
+ connRef183->setDestEndpoint(dstPt183);
+ connRef183->setRoutingType((ConnType)2);
+
+ ConnRef *connRef184 = new ConnRef(router, 184);
+ ConnEnd srcPt184(Point(677.924, 343.557), 15);
+ connRef184->setSourceEndpoint(srcPt184);
+ ConnEnd dstPt184(Point(727.924, 343.557), 15);
+ connRef184->setDestEndpoint(dstPt184);
+ connRef184->setRoutingType((ConnType)2);
+
+ ConnRef *connRef185 = new ConnRef(router, 185);
+ ConnEnd srcPt185(Point(797.924, 161.557), 15);
+ connRef185->setSourceEndpoint(srcPt185);
+ ConnEnd dstPt185(Point(847.924, 161.557), 15);
+ connRef185->setDestEndpoint(dstPt185);
+ connRef185->setRoutingType((ConnType)2);
+
+ ConnRef *connRef186 = new ConnRef(router, 186);
+ ConnEnd srcPt186(Point(77.9242, 34.8422), 15);
+ connRef186->setSourceEndpoint(srcPt186);
+ ConnEnd dstPt186(Point(127.924, 34.8422), 15);
+ connRef186->setDestEndpoint(dstPt186);
+ connRef186->setRoutingType((ConnType)2);
+
+ ConnRef *connRef187 = new ConnRef(router, 187);
+ ConnEnd srcPt187(Point(437.924, 527.557), 15);
+ connRef187->setSourceEndpoint(srcPt187);
+ ConnEnd dstPt187(Point(487.924, 527.557), 15);
+ connRef187->setDestEndpoint(dstPt187);
+ connRef187->setRoutingType((ConnType)2);
+
+ ConnRef *connRef188 = new ConnRef(router, 188);
+ ConnEnd srcPt188(Point(77.9242, 619.557), 15);
+ connRef188->setSourceEndpoint(srcPt188);
+ ConnEnd dstPt188(Point(127.924, 619.557), 15);
+ connRef188->setDestEndpoint(dstPt188);
+ connRef188->setRoutingType((ConnType)2);
+
+ ConnRef *connRef189 = new ConnRef(router, 189);
+ ConnEnd srcPt189(Point(747.924, -60.6578), 15);
+ connRef189->setSourceEndpoint(srcPt189);
+ ConnEnd dstPt189(Point(797.924, -60.6578), 15);
+ connRef189->setDestEndpoint(dstPt189);
+ connRef189->setRoutingType((ConnType)2);
+
+ ConnRef *connRef190 = new ConnRef(router, 190);
+ ConnEnd srcPt190(Point(147.924, 34.8422), 15);
+ connRef190->setSourceEndpoint(srcPt190);
+ ConnEnd dstPt190(Point(197.924, 161.557), 15);
+ connRef190->setDestEndpoint(dstPt190);
+ connRef190->setRoutingType((ConnType)2);
+
+ ConnRef *connRef191 = new ConnRef(router, 191);
+ ConnEnd srcPt191(Point(267.924, 161.557), 15);
+ connRef191->setSourceEndpoint(srcPt191);
+ ConnEnd dstPt191(Point(317.924, 161.557), 15);
+ connRef191->setDestEndpoint(dstPt191);
+ connRef191->setRoutingType((ConnType)2);
+
+ ConnRef *connRef192 = new ConnRef(router, 192);
+ ConnEnd srcPt192(Point(197.924, 223.557), 15);
+ connRef192->setSourceEndpoint(srcPt192);
+ ConnEnd dstPt192(Point(197.924, 315.557), 15);
+ connRef192->setDestEndpoint(dstPt192);
+ connRef192->setRoutingType((ConnType)2);
+
+ ConnRef *connRef193 = new ConnRef(router, 193);
+ ConnEnd srcPt193(Point(77.9242, 377.557), 15);
+ connRef193->setSourceEndpoint(srcPt193);
+ ConnEnd dstPt193(Point(77.9242, 527.557), 15);
+ connRef193->setDestEndpoint(dstPt193);
+ connRef193->setRoutingType((ConnType)2);
+
+ ConnRef *connRef194 = new ConnRef(router, 194);
+ ConnEnd srcPt194(Point(147.924, 527.557), 15);
+ connRef194->setSourceEndpoint(srcPt194);
+ ConnEnd dstPt194(Point(197.924, 527.557), 15);
+ connRef194->setDestEndpoint(dstPt194);
+ connRef194->setRoutingType((ConnType)2);
+
+ ConnRef *connRef195 = new ConnRef(router, 195);
+ ConnEnd srcPt195(Point(147.924, 619.557), 15);
+ connRef195->setSourceEndpoint(srcPt195);
+ ConnEnd dstPt195(Point(197.924, 763.557), 15);
+ connRef195->setDestEndpoint(dstPt195);
+ connRef195->setRoutingType((ConnType)2);
+
+ ConnRef *connRef196 = new ConnRef(router, 196);
+ ConnEnd srcPt196(Point(77.9242, 651.557), 15);
+ connRef196->setSourceEndpoint(srcPt196);
+ ConnEnd dstPt196(Point(77.9242, 619.557), 15);
+ connRef196->setDestEndpoint(dstPt196);
+ connRef196->setRoutingType((ConnType)2);
+
+ ConnRef *connRef197 = new ConnRef(router, 197);
+ ConnEnd srcPt197(Point(147.924, 763.557), 15);
+ connRef197->setSourceEndpoint(srcPt197);
+ ConnEnd dstPt197(Point(197.924, 763.557), 15);
+ connRef197->setDestEndpoint(dstPt197);
+ connRef197->setRoutingType((ConnType)2);
+
+ ConnRef *connRef198 = new ConnRef(router, 198);
+ ConnEnd srcPt198(Point(267.924, 763.557), 15);
+ connRef198->setSourceEndpoint(srcPt198);
+ ConnEnd dstPt198(Point(317.924, 763.557), 15);
+ connRef198->setDestEndpoint(dstPt198);
+ connRef198->setRoutingType((ConnType)2);
+
+ ConnRef *connRef199 = new ConnRef(router, 199);
+ ConnEnd srcPt199(Point(387.924, 627.557), 15);
+ connRef199->setSourceEndpoint(srcPt199);
+ ConnEnd dstPt199(Point(437.924, 627.557), 15);
+ connRef199->setDestEndpoint(dstPt199);
+ connRef199->setRoutingType((ConnType)2);
+
+ ConnRef *connRef200 = new ConnRef(router, 200);
+ ConnEnd srcPt200(Point(387.924, 763.557), 15);
+ connRef200->setSourceEndpoint(srcPt200);
+ ConnEnd dstPt200(Point(437.924, 763.557), 15);
+ connRef200->setDestEndpoint(dstPt200);
+ connRef200->setRoutingType((ConnType)2);
+
+ ConnRef *connRef201 = new ConnRef(router, 201);
+ ConnEnd srcPt201(Point(507.924, 763.557), 15);
+ connRef201->setSourceEndpoint(srcPt201);
+ ConnEnd dstPt201(Point(557.924, 763.557), 15);
+ connRef201->setDestEndpoint(dstPt201);
+ connRef201->setRoutingType((ConnType)2);
+
+ ConnRef *connRef202 = new ConnRef(router, 202);
+ ConnEnd srcPt202(Point(627.924, 763.557), 15);
+ connRef202->setSourceEndpoint(srcPt202);
+ ConnEnd dstPt202(Point(677.924, 763.557), 15);
+ connRef202->setDestEndpoint(dstPt202);
+ connRef202->setRoutingType((ConnType)2);
+
+ ConnRef *connRef203 = new ConnRef(router, 203);
+ ConnEnd srcPt203(Point(507.924, 903.057), 15);
+ connRef203->setSourceEndpoint(srcPt203);
+ ConnEnd dstPt203(Point(557.924, 903.057), 15);
+ connRef203->setDestEndpoint(dstPt203);
+ connRef203->setRoutingType((ConnType)2);
+
+ ConnRef *connRef204 = new ConnRef(router, 204);
+ ConnEnd srcPt204(Point(627.924, 903.057), 15);
+ connRef204->setSourceEndpoint(srcPt204);
+ ConnEnd dstPt204(Point(677.924, 903.057), 15);
+ connRef204->setDestEndpoint(dstPt204);
+ connRef204->setRoutingType((ConnType)2);
+
+ ConnRef *connRef205 = new ConnRef(router, 205);
+ ConnEnd srcPt205(Point(387.924, 161.557), 15);
+ connRef205->setSourceEndpoint(srcPt205);
+ ConnEnd dstPt205(Point(437.924, 161.557), 15);
+ connRef205->setDestEndpoint(dstPt205);
+ connRef205->setRoutingType((ConnType)2);
+
+ ConnRef *connRef206 = new ConnRef(router, 206);
+ ConnEnd srcPt206(Point(387.924, 27.3422), 15);
+ connRef206->setSourceEndpoint(srcPt206);
+ ConnEnd dstPt206(Point(437.924, 27.3422), 15);
+ connRef206->setDestEndpoint(dstPt206);
+ connRef206->setRoutingType((ConnType)2);
+
+ ConnRef *connRef207 = new ConnRef(router, 207);
+ ConnEnd srcPt207(Point(507.924, 45.8422), 15);
+ connRef207->setSourceEndpoint(srcPt207);
+ ConnEnd dstPt207(Point(557.924, 54.8422), 15);
+ connRef207->setDestEndpoint(dstPt207);
+ connRef207->setRoutingType((ConnType)2);
+
+ ConnRef *connRef208 = new ConnRef(router, 208);
+ ConnEnd srcPt208(Point(627.924, 45.8422), 15);
+ connRef208->setSourceEndpoint(srcPt208);
+ ConnEnd dstPt208(Point(677.924, 54.8422), 15);
+ connRef208->setDestEndpoint(dstPt208);
+ connRef208->setRoutingType((ConnType)2);
+
+ ConnRef *connRef209 = new ConnRef(router, 209);
+ ConnEnd srcPt209(Point(747.924, 574.057), 15);
+ connRef209->setSourceEndpoint(srcPt209);
+ ConnEnd dstPt209(Point(797.924, 574.057), 15);
+ connRef209->setDestEndpoint(dstPt209);
+ connRef209->setRoutingType((ConnType)2);
+
+ ConnRef *connRef210 = new ConnRef(router, 210);
+ ConnEnd srcPt210(Point(507.924, 527.557), 15);
+ connRef210->setSourceEndpoint(srcPt210);
+ ConnEnd dstPt210(Point(557.924, 527.557), 15);
+ connRef210->setDestEndpoint(dstPt210);
+ connRef210->setRoutingType((ConnType)2);
+
+ ConnRef *connRef211 = new ConnRef(router, 211);
+ ConnEnd srcPt211(Point(507.924, 435.557), 15);
+ connRef211->setSourceEndpoint(srcPt211);
+ ConnEnd dstPt211(Point(557.924, 435.557), 15);
+ connRef211->setDestEndpoint(dstPt211);
+ connRef211->setRoutingType((ConnType)2);
+
+ ConnRef *connRef212 = new ConnRef(router, 212);
+ ConnEnd srcPt212(Point(627.924, 527.557), 15);
+ connRef212->setSourceEndpoint(srcPt212);
+ ConnEnd dstPt212(Point(677.924, 527.557), 15);
+ connRef212->setDestEndpoint(dstPt212);
+ connRef212->setRoutingType((ConnType)2);
+
+ ConnRef *connRef213 = new ConnRef(router, 213);
+ ConnEnd srcPt213(Point(627.924, 435.557), 15);
+ connRef213->setSourceEndpoint(srcPt213);
+ ConnEnd dstPt213(Point(677.924, 435.557), 15);
+ connRef213->setDestEndpoint(dstPt213);
+ connRef213->setRoutingType((ConnType)2);
+
+ ConnRef *connRef214 = new ConnRef(router, 214);
+ ConnEnd srcPt214(Point(867.924, 343.557), 15);
+ connRef214->setSourceEndpoint(srcPt214);
+ ConnEnd dstPt214(Point(917.924, 343.557), 15);
+ connRef214->setDestEndpoint(dstPt214);
+ connRef214->setRoutingType((ConnType)2);
+
+ ConnRef *connRef215 = new ConnRef(router, 215);
+ ConnEnd srcPt215(Point(867.924, 435.557), 15);
+ connRef215->setSourceEndpoint(srcPt215);
+ ConnEnd dstPt215(Point(917.924, 435.557), 15);
+ connRef215->setDestEndpoint(dstPt215);
+ connRef215->setRoutingType((ConnType)2);
+
+ ConnRef *connRef216 = new ConnRef(router, 216);
+ ConnEnd srcPt216(Point(867.924, 161.557), 15);
+ connRef216->setSourceEndpoint(srcPt216);
+ ConnEnd dstPt216(Point(917.924, 161.557), 15);
+ connRef216->setDestEndpoint(dstPt216);
+ connRef216->setRoutingType((ConnType)2);
+
+ ConnRef *connRef217 = new ConnRef(router, 217);
+ ConnEnd srcPt217(Point(747.924, 343.557), 15);
+ connRef217->setSourceEndpoint(srcPt217);
+ ConnEnd dstPt217(Point(797.924, 343.557), 15);
+ connRef217->setDestEndpoint(dstPt217);
+ connRef217->setRoutingType((ConnType)2);
+
+ ConnRef *connRef218 = new ConnRef(router, 218);
+ ConnEnd srcPt218(Point(1088.92, 388.557), 15);
+ connRef218->setSourceEndpoint(srcPt218);
+ ConnEnd dstPt218(Point(1138.92, 435.557), 15);
+ connRef218->setDestEndpoint(dstPt218);
+ connRef218->setRoutingType((ConnType)2);
+
+ ConnRef *connRef219 = new ConnRef(router, 219);
+ ConnEnd srcPt219(Point(1208.92, 388.557), 15);
+ connRef219->setSourceEndpoint(srcPt219);
+ ConnEnd dstPt219(Point(1258.92, 435.557), 15);
+ connRef219->setDestEndpoint(dstPt219);
+ connRef219->setRoutingType((ConnType)2);
+
+ ConnRef *connRef220 = new ConnRef(router, 220);
+ ConnEnd srcPt220(Point(1088.92, 152.342), 15);
+ connRef220->setSourceEndpoint(srcPt220);
+ ConnEnd dstPt220(Point(1138.92, 161.557), 15);
+ connRef220->setDestEndpoint(dstPt220);
+ connRef220->setRoutingType((ConnType)2);
+
+ ConnRef *connRef221 = new ConnRef(router, 221);
+ ConnEnd srcPt221(Point(1088.92, 60.3422), 15);
+ connRef221->setSourceEndpoint(srcPt221);
+ ConnEnd dstPt221(Point(1138.92, 60.3422), 15);
+ connRef221->setDestEndpoint(dstPt221);
+ connRef221->setRoutingType((ConnType)2);
+
+ ConnRef *connRef222 = new ConnRef(router, 222);
+ ConnEnd srcPt222(Point(1208.92, 152.342), 15);
+ connRef222->setSourceEndpoint(srcPt222);
+ ConnEnd dstPt222(Point(1258.92, 161.557), 15);
+ connRef222->setDestEndpoint(dstPt222);
+ connRef222->setRoutingType((ConnType)2);
+
+ ConnRef *connRef223 = new ConnRef(router, 223);
+ ConnEnd srcPt223(Point(1088.92, -60.6578), 15);
+ connRef223->setSourceEndpoint(srcPt223);
+ ConnEnd dstPt223(Point(1138.92, -60.6578), 15);
+ connRef223->setDestEndpoint(dstPt223);
+ connRef223->setRoutingType((ConnType)2);
+
+ ConnRef *connRef224 = new ConnRef(router, 224);
+ ConnEnd srcPt224(Point(747.924, 161.557), 15);
+ connRef224->setSourceEndpoint(srcPt224);
+ ConnEnd dstPt224(Point(797.924, 161.557), 15);
+ connRef224->setDestEndpoint(dstPt224);
+ connRef224->setRoutingType((ConnType)2);
+
+ ConnRef *connRef225 = new ConnRef(router, 225);
+ ConnEnd srcPt225(Point(747.924, 860.057), 15);
+ connRef225->setSourceEndpoint(srcPt225);
+ ConnEnd dstPt225(Point(797.924, 860.057), 15);
+ connRef225->setDestEndpoint(dstPt225);
+ connRef225->setRoutingType((ConnType)2);
+
+ ConnRef *connRef226 = new ConnRef(router, 226);
+ ConnEnd srcPt226(Point(737.924, -110.658), 15);
+ connRef226->setSourceEndpoint(srcPt226);
+ ConnEnd dstPt226(Point(737.924, -60.6578), 15);
+ connRef226->setDestEndpoint(dstPt226);
+ connRef226->setRoutingType((ConnType)2);
+
+ ConnRef *connRef227 = new ConnRef(router, 227);
+ ConnEnd srcPt227(Point(137.924, -15.1578), 15);
+ connRef227->setSourceEndpoint(srcPt227);
+ ConnEnd dstPt227(Point(137.924, 34.8422), 15);
+ connRef227->setDestEndpoint(dstPt227);
+ connRef227->setRoutingType((ConnType)2);
+
+ ConnRef *connRef228 = new ConnRef(router, 228);
+ ConnEnd srcPt228(Point(137.924, 111.557), 15);
+ connRef228->setSourceEndpoint(srcPt228);
+ ConnEnd dstPt228(Point(137.924, 161.557), 15);
+ connRef228->setDestEndpoint(dstPt228);
+ connRef228->setRoutingType((ConnType)2);
+
+ ConnRef *connRef229 = new ConnRef(router, 229);
+ ConnEnd srcPt229(Point(257.924, 111.557), 15);
+ connRef229->setSourceEndpoint(srcPt229);
+ ConnEnd dstPt229(Point(257.924, 161.557), 15);
+ connRef229->setDestEndpoint(dstPt229);
+ connRef229->setRoutingType((ConnType)2);
+
+ ConnRef *connRef230 = new ConnRef(router, 230);
+ ConnEnd srcPt230(Point(259.924, 213.557), 15);
+ connRef230->setSourceEndpoint(srcPt230);
+ ConnEnd dstPt230(Point(197.924, 213.557), 15);
+ connRef230->setDestEndpoint(dstPt230);
+ connRef230->setRoutingType((ConnType)2);
+
+ ConnRef *connRef231 = new ConnRef(router, 231);
+ ConnEnd srcPt231(Point(257.924, 265.557), 15);
+ connRef231->setSourceEndpoint(srcPt231);
+ ConnEnd dstPt231(Point(257.924, 315.557), 15);
+ connRef231->setDestEndpoint(dstPt231);
+ connRef231->setRoutingType((ConnType)2);
+
+ ConnRef *connRef232 = new ConnRef(router, 232);
+ ConnEnd srcPt232(Point(139.924, 367.557), 15);
+ connRef232->setSourceEndpoint(srcPt232);
+ ConnEnd dstPt232(Point(77.9242, 367.557), 15);
+ connRef232->setDestEndpoint(dstPt232);
+ connRef232->setRoutingType((ConnType)2);
+
+ ConnRef *connRef233 = new ConnRef(router, 233);
+ ConnEnd srcPt233(Point(137.924, 477.557), 15);
+ connRef233->setSourceEndpoint(srcPt233);
+ ConnEnd dstPt233(Point(137.924, 527.557), 15);
+ connRef233->setDestEndpoint(dstPt233);
+ connRef233->setRoutingType((ConnType)2);
+
+ ConnRef *connRef234 = new ConnRef(router, 234);
+ ConnEnd srcPt234(Point(137.924, 569.557), 15);
+ connRef234->setSourceEndpoint(srcPt234);
+ ConnEnd dstPt234(Point(137.924, 619.557), 15);
+ connRef234->setDestEndpoint(dstPt234);
+ connRef234->setRoutingType((ConnType)2);
+
+ ConnRef *connRef235 = new ConnRef(router, 235);
+ ConnEnd srcPt235(Point(139.924, 661.557), 15);
+ connRef235->setSourceEndpoint(srcPt235);
+ ConnEnd dstPt235(Point(77.9242, 661.557), 15);
+ connRef235->setDestEndpoint(dstPt235);
+ connRef235->setRoutingType((ConnType)2);
+
+ ConnRef *connRef236 = new ConnRef(router, 236);
+ ConnEnd srcPt236(Point(137.924, 713.557), 15);
+ connRef236->setSourceEndpoint(srcPt236);
+ ConnEnd dstPt236(Point(137.924, 763.557), 15);
+ connRef236->setDestEndpoint(dstPt236);
+ connRef236->setRoutingType((ConnType)2);
+
+ ConnRef *connRef237 = new ConnRef(router, 237);
+ ConnEnd srcPt237(Point(257.924, 713.557), 15);
+ connRef237->setSourceEndpoint(srcPt237);
+ ConnEnd dstPt237(Point(257.924, 763.557), 15);
+ connRef237->setDestEndpoint(dstPt237);
+ connRef237->setRoutingType((ConnType)2);
+
+ ConnRef *connRef238 = new ConnRef(router, 238);
+ ConnEnd srcPt238(Point(377.924, 577.557), 15);
+ connRef238->setSourceEndpoint(srcPt238);
+ ConnEnd dstPt238(Point(377.924, 627.557), 15);
+ connRef238->setDestEndpoint(dstPt238);
+ connRef238->setRoutingType((ConnType)2);
+
+ ConnRef *connRef239 = new ConnRef(router, 239);
+ ConnEnd srcPt239(Point(377.924, 713.557), 15);
+ connRef239->setSourceEndpoint(srcPt239);
+ ConnEnd dstPt239(Point(377.924, 763.557), 15);
+ connRef239->setDestEndpoint(dstPt239);
+ connRef239->setRoutingType((ConnType)2);
+
+ ConnRef *connRef240 = new ConnRef(router, 240);
+ ConnEnd srcPt240(Point(497.924, 713.557), 15);
+ connRef240->setSourceEndpoint(srcPt240);
+ ConnEnd dstPt240(Point(497.924, 763.557), 15);
+ connRef240->setDestEndpoint(dstPt240);
+ connRef240->setRoutingType((ConnType)2);
+
+ ConnRef *connRef241 = new ConnRef(router, 241);
+ ConnEnd srcPt241(Point(617.924, 713.557), 15);
+ connRef241->setSourceEndpoint(srcPt241);
+ ConnEnd dstPt241(Point(617.924, 763.557), 15);
+ connRef241->setDestEndpoint(dstPt241);
+ connRef241->setRoutingType((ConnType)2);
+
+ ConnRef *connRef242 = new ConnRef(router, 242);
+ ConnEnd srcPt242(Point(497.924, 853.057), 15);
+ connRef242->setSourceEndpoint(srcPt242);
+ ConnEnd dstPt242(Point(497.924, 903.057), 15);
+ connRef242->setDestEndpoint(dstPt242);
+ connRef242->setRoutingType((ConnType)2);
+
+ ConnRef *connRef243 = new ConnRef(router, 243);
+ ConnEnd srcPt243(Point(617.924, 853.057), 15);
+ connRef243->setSourceEndpoint(srcPt243);
+ ConnEnd dstPt243(Point(617.924, 903.057), 15);
+ connRef243->setDestEndpoint(dstPt243);
+ connRef243->setRoutingType((ConnType)2);
+
+ ConnRef *connRef244 = new ConnRef(router, 244);
+ ConnEnd srcPt244(Point(377.924, 111.557), 15);
+ connRef244->setSourceEndpoint(srcPt244);
+ ConnEnd dstPt244(Point(377.924, 161.557), 15);
+ connRef244->setDestEndpoint(dstPt244);
+ connRef244->setRoutingType((ConnType)2);
+
+ ConnRef *connRef245 = new ConnRef(router, 245);
+ ConnEnd srcPt245(Point(377.924, -22.6578), 15);
+ connRef245->setSourceEndpoint(srcPt245);
+ ConnEnd dstPt245(Point(377.924, 27.3422), 15);
+ connRef245->setDestEndpoint(dstPt245);
+ connRef245->setRoutingType((ConnType)2);
+
+ ConnRef *connRef246 = new ConnRef(router, 246);
+ ConnEnd srcPt246(Point(497.924, -4.15778), 15);
+ connRef246->setSourceEndpoint(srcPt246);
+ ConnEnd dstPt246(Point(497.924, 45.8422), 15);
+ connRef246->setDestEndpoint(dstPt246);
+ connRef246->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/lineSegWrapperCrash4");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash5.cpp b/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash5.cpp
new file mode 100644
index 0000000..cb49862
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash5.cpp
@@ -0,0 +1,1884 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 0);
+
+ Polygon poly134(4);
+ poly134.ps[0] = Point(885.924, 365.557);
+ poly134.ps[1] = Point(885.924, 405.557);
+ poly134.ps[2] = Point(829.924, 405.557);
+ poly134.ps[3] = Point(829.924, 365.557);
+ new ShapeRef(router, poly134, 134);
+
+ Polygon poly135(4);
+ poly135.ps[0] = Point(885.924, 91.5565);
+ poly135.ps[1] = Point(885.924, 131.557);
+ poly135.ps[2] = Point(829.924, 131.557);
+ poly135.ps[3] = Point(829.924, 91.5565);
+ new ShapeRef(router, poly135, 135);
+
+ Polygon poly136(4);
+ poly136.ps[0] = Point(765.924, 273.557);
+ poly136.ps[1] = Point(765.924, 313.557);
+ poly136.ps[2] = Point(709.924, 313.557);
+ poly136.ps[3] = Point(709.924, 273.557);
+ new ShapeRef(router, poly136, 136);
+
+ Polygon poly137(4);
+ poly137.ps[0] = Point(1106.92, 318.557);
+ poly137.ps[1] = Point(1106.92, 358.557);
+ poly137.ps[2] = Point(1050.92, 358.557);
+ poly137.ps[3] = Point(1050.92, 318.557);
+ new ShapeRef(router, poly137, 137);
+
+ Polygon poly138(4);
+ poly138.ps[0] = Point(1226.92, 318.557);
+ poly138.ps[1] = Point(1226.92, 358.557);
+ poly138.ps[2] = Point(1170.92, 358.557);
+ poly138.ps[3] = Point(1170.92, 318.557);
+ new ShapeRef(router, poly138, 138);
+
+ Polygon poly139(4);
+ poly139.ps[0] = Point(1106.92, 82.3422);
+ poly139.ps[1] = Point(1106.92, 122.342);
+ poly139.ps[2] = Point(1050.92, 122.342);
+ poly139.ps[3] = Point(1050.92, 82.3422);
+ new ShapeRef(router, poly139, 139);
+
+ Polygon poly140(4);
+ poly140.ps[0] = Point(1106.92, -9.65778);
+ poly140.ps[1] = Point(1106.92, 30.3422);
+ poly140.ps[2] = Point(1050.92, 30.3422);
+ poly140.ps[3] = Point(1050.92, -9.65778);
+ new ShapeRef(router, poly140, 140);
+
+ Polygon poly141(4);
+ poly141.ps[0] = Point(1226.92, 82.3422);
+ poly141.ps[1] = Point(1226.92, 122.342);
+ poly141.ps[2] = Point(1170.92, 122.342);
+ poly141.ps[3] = Point(1170.92, 82.3422);
+ new ShapeRef(router, poly141, 141);
+
+ Polygon poly142(4);
+ poly142.ps[0] = Point(1106.92, -130.658);
+ poly142.ps[1] = Point(1106.92, -90.6578);
+ poly142.ps[2] = Point(1050.92, -90.6578);
+ poly142.ps[3] = Point(1050.92, -130.658);
+ new ShapeRef(router, poly142, 142);
+
+ Polygon poly22(4);
+ poly22.ps[0] = Point(697.924, 34.8422);
+ poly22.ps[1] = Point(697.924, 74.8422);
+ poly22.ps[2] = Point(657.924, 74.8422);
+ poly22.ps[3] = Point(657.924, 34.8422);
+ new ShapeRef(router, poly22, 22);
+
+ Polygon poly21(4);
+ poly21.ps[0] = Point(937.924, 141.557);
+ poly21.ps[1] = Point(937.924, 181.557);
+ poly21.ps[2] = Point(897.924, 181.557);
+ poly21.ps[3] = Point(897.924, 141.557);
+ new ShapeRef(router, poly21, 21);
+
+ Polygon poly109(4);
+ poly109.ps[0] = Point(285.924, 91.5565);
+ poly109.ps[1] = Point(285.924, 131.557);
+ poly109.ps[2] = Point(229.924, 131.557);
+ poly109.ps[3] = Point(229.924, 91.5565);
+ new ShapeRef(router, poly109, 109);
+
+ Polygon poly42(4);
+ poly42.ps[0] = Point(697.924, 415.557);
+ poly42.ps[1] = Point(697.924, 455.557);
+ poly42.ps[2] = Point(657.924, 455.557);
+ poly42.ps[3] = Point(657.924, 415.557);
+ new ShapeRef(router, poly42, 42);
+
+ Polygon poly124(4);
+ poly124.ps[0] = Point(405.924, 91.5565);
+ poly124.ps[1] = Point(405.924, 131.557);
+ poly124.ps[2] = Point(349.924, 131.557);
+ poly124.ps[3] = Point(349.924, 91.5565);
+ new ShapeRef(router, poly124, 124);
+
+ Polygon poly125(4);
+ poly125.ps[0] = Point(405.924, -42.6578);
+ poly125.ps[1] = Point(405.924, -2.65778);
+ poly125.ps[2] = Point(349.924, -2.65778);
+ poly125.ps[3] = Point(349.924, -42.6578);
+ new ShapeRef(router, poly125, 125);
+
+ Polygon poly52(4);
+ poly52.ps[0] = Point(217.924, 295.557);
+ poly52.ps[1] = Point(217.924, 335.557);
+ poly52.ps[2] = Point(177.924, 335.557);
+ poly52.ps[3] = Point(177.924, 295.557);
+ new ShapeRef(router, poly52, 52);
+
+ Polygon poly51(4);
+ poly51.ps[0] = Point(1038.92, 323.557);
+ poly51.ps[1] = Point(1038.92, 363.557);
+ poly51.ps[2] = Point(998.924, 363.557);
+ poly51.ps[3] = Point(998.924, 323.557);
+ new ShapeRef(router, poly51, 51);
+
+ Polygon poly50(4);
+ poly50.ps[0] = Point(272.5, -82.1578);
+ poly50.ps[1] = Point(272.5, -47.1578);
+ poly50.ps[2] = Point(35.5, -47.1578);
+ poly50.ps[3] = Point(35.5, -82.1578);
+ new ShapeRef(router, poly50, 50);
+
+ Polygon poly49(4);
+ poly49.ps[0] = Point(45.9242, 169.75);
+ poly49.ps[1] = Point(45.9242, 334.75);
+ poly49.ps[2] = Point(-242.076, 334.75);
+ poly49.ps[3] = Point(-242.076, 169.75);
+ new ShapeRef(router, poly49, 49);
+
+ Polygon poly64(4);
+ poly64.ps[0] = Point(817.924, 554.057);
+ poly64.ps[1] = Point(817.924, 594.057);
+ poly64.ps[2] = Point(777.924, 594.057);
+ poly64.ps[3] = Point(777.924, 554.057);
+ new ShapeRef(router, poly64, 64);
+
+ Polygon poly70(4);
+ poly70.ps[0] = Point(207.924, 203.557);
+ poly70.ps[1] = Point(207.924, 223.557);
+ poly70.ps[2] = Point(187.924, 223.557);
+ poly70.ps[3] = Point(187.924, 203.557);
+ new ShapeRef(router, poly70, 70);
+
+ Polygon poly68(4);
+ poly68.ps[0] = Point(147.924, 151.557);
+ poly68.ps[1] = Point(147.924, 171.557);
+ poly68.ps[2] = Point(127.924, 171.557);
+ poly68.ps[3] = Point(127.924, 151.557);
+ new ShapeRef(router, poly68, 68);
+
+ Polygon poly40(4);
+ poly40.ps[0] = Point(97.9242, 141.557);
+ poly40.ps[1] = Point(97.9242, 181.557);
+ poly40.ps[2] = Point(57.9242, 181.557);
+ poly40.ps[3] = Point(57.9242, 141.557);
+ new ShapeRef(router, poly40, 40);
+
+ Polygon poly99(4);
+ poly99.ps[0] = Point(1088.92, 142.342);
+ poly99.ps[1] = Point(1088.92, 162.342);
+ poly99.ps[2] = Point(1068.92, 162.342);
+ poly99.ps[3] = Point(1068.92, 142.342);
+ new ShapeRef(router, poly99, 99);
+
+ Polygon poly67(4);
+ poly67.ps[0] = Point(147.924, 24.8422);
+ poly67.ps[1] = Point(147.924, 44.8422);
+ poly67.ps[2] = Point(127.924, 44.8422);
+ poly67.ps[3] = Point(127.924, 24.8422);
+ new ShapeRef(router, poly67, 67);
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(1371.92, -80.6578);
+ poly6.ps[1] = Point(1371.92, -40.6578);
+ poly6.ps[2] = Point(1331.92, -40.6578);
+ poly6.ps[3] = Point(1331.92, -80.6578);
+ new ShapeRef(router, poly6, 6);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(1278.92, -80.6578);
+ poly7.ps[1] = Point(1278.92, -40.6578);
+ poly7.ps[2] = Point(1238.92, -40.6578);
+ poly7.ps[3] = Point(1238.92, -80.6578);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly39(4);
+ poly39.ps[0] = Point(457.924, 141.557);
+ poly39.ps[1] = Point(457.924, 181.557);
+ poly39.ps[2] = Point(417.924, 181.557);
+ poly39.ps[3] = Point(417.924, 141.557);
+ new ShapeRef(router, poly39, 39);
+
+ Polygon poly88(4);
+ poly88.ps[0] = Point(747.924, 564.057);
+ poly88.ps[1] = Point(747.924, 584.057);
+ poly88.ps[2] = Point(727.924, 584.057);
+ poly88.ps[3] = Point(727.924, 564.057);
+ new ShapeRef(router, poly88, 88);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(577.924, 795.557);
+ poly2.ps[1] = Point(577.924, 835.557);
+ poly2.ps[2] = Point(537.924, 835.557);
+ poly2.ps[3] = Point(537.924, 795.557);
+ new ShapeRef(router, poly2, 2);
+
+ Polygon poly27(4);
+ poly27.ps[0] = Point(577.924, 507.557);
+ poly27.ps[1] = Point(577.924, 547.557);
+ poly27.ps[2] = Point(537.924, 547.557);
+ poly27.ps[3] = Point(537.924, 507.557);
+ new ShapeRef(router, poly27, 27);
+
+ Polygon poly45(4);
+ poly45.ps[0] = Point(577.924, 34.8422);
+ poly45.ps[1] = Point(577.924, 74.8422);
+ poly45.ps[2] = Point(537.924, 74.8422);
+ poly45.ps[3] = Point(537.924, 34.8422);
+ new ShapeRef(router, poly45, 45);
+
+ Polygon poly20(4);
+ poly20.ps[0] = Point(337.924, 507.557);
+ poly20.ps[1] = Point(337.924, 547.557);
+ poly20.ps[2] = Point(297.924, 547.557);
+ poly20.ps[3] = Point(297.924, 507.557);
+ new ShapeRef(router, poly20, 20);
+
+ Polygon poly19(4);
+ poly19.ps[0] = Point(217.924, 141.557);
+ poly19.ps[1] = Point(217.924, 181.557);
+ poly19.ps[2] = Point(177.924, 181.557);
+ poly19.ps[3] = Point(177.924, 141.557);
+ new ShapeRef(router, poly19, 19);
+
+ Polygon poly53(4);
+ poly53.ps[0] = Point(577.924, 323.557);
+ poly53.ps[1] = Point(577.924, 363.557);
+ poly53.ps[2] = Point(537.924, 363.557);
+ poly53.ps[3] = Point(537.924, 323.557);
+ new ShapeRef(router, poly53, 53);
+
+ Polygon poly38(4);
+ poly38.ps[0] = Point(217.924, 507.557);
+ poly38.ps[1] = Point(217.924, 547.557);
+ poly38.ps[2] = Point(177.924, 547.557);
+ poly38.ps[3] = Point(177.924, 507.557);
+ new ShapeRef(router, poly38, 38);
+
+ Polygon poly18(4);
+ poly18.ps[0] = Point(217.924, 743.557);
+ poly18.ps[1] = Point(217.924, 783.557);
+ poly18.ps[2] = Point(177.924, 783.557);
+ poly18.ps[3] = Point(177.924, 743.557);
+ new ShapeRef(router, poly18, 18);
+
+ Polygon poly17(4);
+ poly17.ps[0] = Point(577.924, 883.057);
+ poly17.ps[1] = Point(577.924, 923.057);
+ poly17.ps[2] = Point(537.924, 923.057);
+ poly17.ps[3] = Point(537.924, 883.057);
+ new ShapeRef(router, poly17, 17);
+
+ Polygon poly1(4);
+ poly1.ps[0] = Point(817.924, 840.057);
+ poly1.ps[1] = Point(817.924, 880.057);
+ poly1.ps[2] = Point(777.924, 880.057);
+ poly1.ps[3] = Point(777.924, 840.057);
+ new ShapeRef(router, poly1, 1);
+
+ Polygon poly16(4);
+ poly16.ps[0] = Point(337.924, 743.557);
+ poly16.ps[1] = Point(337.924, 783.557);
+ poly16.ps[2] = Point(297.924, 783.557);
+ poly16.ps[3] = Point(297.924, 743.557);
+ new ShapeRef(router, poly16, 16);
+
+ Polygon poly143(4);
+ poly143.ps[0] = Point(986.924, 210.557);
+ poly143.ps[1] = Point(986.924, 250.557);
+ poly143.ps[2] = Point(930.924, 250.557);
+ poly143.ps[3] = Point(930.924, 210.557);
+ new ShapeRef(router, poly143, 143);
+
+ Polygon poly144(4);
+ poly144.ps[0] = Point(765.924, 91.5565);
+ poly144.ps[1] = Point(765.924, 131.557);
+ poly144.ps[2] = Point(709.924, 131.557);
+ poly144.ps[3] = Point(709.924, 91.5565);
+ new ShapeRef(router, poly144, 144);
+
+ Polygon poly145(4);
+ poly145.ps[0] = Point(765.924, 790.057);
+ poly145.ps[1] = Point(765.924, 830.057);
+ poly145.ps[2] = Point(709.924, 830.057);
+ poly145.ps[3] = Point(709.924, 790.057);
+ new ShapeRef(router, poly145, 145);
+
+ Polygon poly146(4);
+ poly146.ps[0] = Point(45.9242, 232.5);
+ poly146.ps[1] = Point(45.9242, 272.5);
+ poly146.ps[2] = Point(-14.0758, 272.5);
+ poly146.ps[3] = Point(-14.0758, 232.5);
+ new ShapeRef(router, poly146, 146);
+
+ Polygon poly147(4);
+ poly147.ps[0] = Point(-26.0758, 274.75);
+ poly147.ps[1] = Point(-26.0758, 334.75);
+ poly147.ps[2] = Point(-66.0758, 334.75);
+ poly147.ps[3] = Point(-66.0758, 274.75);
+ new ShapeRef(router, poly147, 147);
+
+ Polygon poly47(4);
+ poly47.ps[0] = Point(697.924, 271.557);
+ poly47.ps[1] = Point(697.924, 311.557);
+ poly47.ps[2] = Point(657.924, 311.557);
+ poly47.ps[3] = Point(657.924, 271.557);
+ new ShapeRef(router, poly47, 47);
+
+ Polygon poly63(4);
+ poly63.ps[0] = Point(457.924, 507.557);
+ poly63.ps[1] = Point(457.924, 547.557);
+ poly63.ps[2] = Point(417.924, 547.557);
+ poly63.ps[3] = Point(417.924, 507.557);
+ new ShapeRef(router, poly63, 63);
+
+ Polygon poly43(4);
+ poly43.ps[0] = Point(1038.92, 1.84222);
+ poly43.ps[1] = Point(1038.92, 41.8422);
+ poly43.ps[2] = Point(998.924, 41.8422);
+ poly43.ps[3] = Point(998.924, 1.84222);
+ new ShapeRef(router, poly43, 43);
+
+ Polygon poly48(4);
+ poly48.ps[0] = Point(97.9242, 743.557);
+ poly48.ps[1] = Point(97.9242, 783.557);
+ poly48.ps[2] = Point(57.9242, 783.557);
+ poly48.ps[3] = Point(57.9242, 743.557);
+ new ShapeRef(router, poly48, 48);
+
+ Polygon poly87(4);
+ poly87.ps[0] = Point(627.924, 35.8422);
+ poly87.ps[1] = Point(627.924, 55.8422);
+ poly87.ps[2] = Point(607.924, 55.8422);
+ poly87.ps[3] = Point(607.924, 35.8422);
+ new ShapeRef(router, poly87, 87);
+
+ Polygon poly98(4);
+ poly98.ps[0] = Point(1208.92, 378.557);
+ poly98.ps[1] = Point(1208.92, 398.557);
+ poly98.ps[2] = Point(1188.92, 398.557);
+ poly98.ps[3] = Point(1188.92, 378.557);
+ new ShapeRef(router, poly98, 98);
+
+ Polygon poly66(4);
+ poly66.ps[0] = Point(747.924, -70.6578);
+ poly66.ps[1] = Point(747.924, -50.6578);
+ poly66.ps[2] = Point(727.924, -50.6578);
+ poly66.ps[3] = Point(727.924, -70.6578);
+ new ShapeRef(router, poly66, 66);
+
+ Polygon poly58(4);
+ poly58.ps[0] = Point(97.9242, 14.8422);
+ poly58.ps[1] = Point(97.9242, 54.8422);
+ poly58.ps[2] = Point(57.9242, 54.8422);
+ poly58.ps[3] = Point(57.9242, 14.8422);
+ new ShapeRef(router, poly58, 58);
+
+ Polygon poly128(4);
+ poly128.ps[0] = Point(765.924, 504.057);
+ poly128.ps[1] = Point(765.924, 544.057);
+ poly128.ps[2] = Point(709.924, 544.057);
+ poly128.ps[3] = Point(709.924, 504.057);
+ new ShapeRef(router, poly128, 128);
+
+ Polygon poly129(4);
+ poly129.ps[0] = Point(525.924, 457.557);
+ poly129.ps[1] = Point(525.924, 497.557);
+ poly129.ps[2] = Point(469.924, 497.557);
+ poly129.ps[3] = Point(469.924, 457.557);
+ new ShapeRef(router, poly129, 129);
+
+ Polygon poly54(4);
+ poly54.ps[0] = Point(697.924, 323.557);
+ poly54.ps[1] = Point(697.924, 363.557);
+ poly54.ps[2] = Point(657.924, 363.557);
+ poly54.ps[3] = Point(657.924, 323.557);
+ new ShapeRef(router, poly54, 54);
+
+ Polygon poly15(4);
+ poly15.ps[0] = Point(1158.92, 415.557);
+ poly15.ps[1] = Point(1158.92, 455.557);
+ poly15.ps[2] = Point(1118.92, 455.557);
+ poly15.ps[3] = Point(1118.92, 415.557);
+ new ShapeRef(router, poly15, 15);
+
+ Polygon poly117(4);
+ poly117.ps[0] = Point(285.924, 693.557);
+ poly117.ps[1] = Point(285.924, 733.557);
+ poly117.ps[2] = Point(229.924, 733.557);
+ poly117.ps[3] = Point(229.924, 693.557);
+ new ShapeRef(router, poly117, 117);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(1158.92, -80.6578);
+ poly8.ps[1] = Point(1158.92, -40.6578);
+ poly8.ps[2] = Point(1118.92, -40.6578);
+ poly8.ps[3] = Point(1118.92, -80.6578);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly57(4);
+ poly57.ps[0] = Point(817.924, 141.557);
+ poly57.ps[1] = Point(817.924, 181.557);
+ poly57.ps[2] = Point(777.924, 181.557);
+ poly57.ps[3] = Point(777.924, 141.557);
+ new ShapeRef(router, poly57, 57);
+
+ Polygon poly62(4);
+ poly62.ps[0] = Point(577.924, 629.557);
+ poly62.ps[1] = Point(577.924, 669.557);
+ poly62.ps[2] = Point(537.924, 669.557);
+ poly62.ps[3] = Point(537.924, 629.557);
+ new ShapeRef(router, poly62, 62);
+
+ Polygon poly24(4);
+ poly24.ps[0] = Point(457.924, 743.557);
+ poly24.ps[1] = Point(457.924, 783.557);
+ poly24.ps[2] = Point(417.924, 783.557);
+ poly24.ps[3] = Point(417.924, 743.557);
+ new ShapeRef(router, poly24, 24);
+
+ Polygon poly100(4);
+ poly100.ps[0] = Point(1088.92, 50.3422);
+ poly100.ps[1] = Point(1088.92, 70.3422);
+ poly100.ps[2] = Point(1068.92, 70.3422);
+ poly100.ps[3] = Point(1068.92, 50.3422);
+ new ShapeRef(router, poly100, 100);
+
+ Polygon poly28(4);
+ poly28.ps[0] = Point(817.924, 323.557);
+ poly28.ps[1] = Point(817.924, 363.557);
+ poly28.ps[2] = Point(777.924, 363.557);
+ poly28.ps[3] = Point(777.924, 323.557);
+ new ShapeRef(router, poly28, 28);
+
+ Polygon poly55(4);
+ poly55.ps[0] = Point(457.924, 7.34222);
+ poly55.ps[1] = Point(457.924, 47.3422);
+ poly55.ps[2] = Point(417.924, 47.3422);
+ poly55.ps[3] = Point(417.924, 7.34222);
+ new ShapeRef(router, poly55, 55);
+
+ Polygon poly60(4);
+ poly60.ps[0] = Point(937.924, 1.84222);
+ poly60.ps[1] = Point(937.924, 41.8422);
+ poly60.ps[2] = Point(897.924, 41.8422);
+ poly60.ps[3] = Point(897.924, 1.84222);
+ new ShapeRef(router, poly60, 60);
+
+ Polygon poly105(4);
+ poly105.ps[0] = Point(747.924, 850.057);
+ poly105.ps[1] = Point(747.924, 870.057);
+ poly105.ps[2] = Point(727.924, 870.057);
+ poly105.ps[3] = Point(727.924, 850.057);
+ new ShapeRef(router, poly105, 105);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(1371.92, -22.1578);
+ poly5.ps[1] = Point(1371.92, 17.8422);
+ poly5.ps[2] = Point(1331.92, 17.8422);
+ poly5.ps[3] = Point(1331.92, -22.1578);
+ new ShapeRef(router, poly5, 5);
+
+ Polygon poly84(4);
+ poly84.ps[0] = Point(387.924, 151.557);
+ poly84.ps[1] = Point(387.924, 171.557);
+ poly84.ps[2] = Point(367.924, 171.557);
+ poly84.ps[3] = Point(367.924, 151.557);
+ new ShapeRef(router, poly84, 84);
+
+ Polygon poly130(4);
+ poly130.ps[0] = Point(525.924, 365.557);
+ poly130.ps[1] = Point(525.924, 405.557);
+ poly130.ps[2] = Point(469.924, 405.557);
+ poly130.ps[3] = Point(469.924, 365.557);
+ new ShapeRef(router, poly130, 130);
+
+ Polygon poly131(4);
+ poly131.ps[0] = Point(645.924, 457.557);
+ poly131.ps[1] = Point(645.924, 497.557);
+ poly131.ps[2] = Point(589.924, 497.557);
+ poly131.ps[3] = Point(589.924, 457.557);
+ new ShapeRef(router, poly131, 131);
+
+ Polygon poly132(4);
+ poly132.ps[0] = Point(645.924, 365.557);
+ poly132.ps[1] = Point(645.924, 405.557);
+ poly132.ps[2] = Point(589.924, 405.557);
+ poly132.ps[3] = Point(589.924, 365.557);
+ new ShapeRef(router, poly132, 132);
+
+ Polygon poly133(4);
+ poly133.ps[0] = Point(885.924, 273.557);
+ poly133.ps[1] = Point(885.924, 313.557);
+ poly133.ps[2] = Point(829.924, 313.557);
+ poly133.ps[3] = Point(829.924, 273.557);
+ new ShapeRef(router, poly133, 133);
+
+ Polygon poly73(4);
+ poly73.ps[0] = Point(147.924, 517.557);
+ poly73.ps[1] = Point(147.924, 537.557);
+ poly73.ps[2] = Point(127.924, 537.557);
+ poly73.ps[3] = Point(127.924, 517.557);
+ new ShapeRef(router, poly73, 73);
+
+ Polygon poly86(4);
+ poly86.ps[0] = Point(507.924, 35.8422);
+ poly86.ps[1] = Point(507.924, 55.8422);
+ poly86.ps[2] = Point(487.924, 55.8422);
+ poly86.ps[3] = Point(487.924, 35.8422);
+ new ShapeRef(router, poly86, 86);
+
+ Polygon poly14(4);
+ poly14.ps[0] = Point(1158.92, 141.557);
+ poly14.ps[1] = Point(1158.92, 181.557);
+ poly14.ps[2] = Point(1118.92, 181.557);
+ poly14.ps[3] = Point(1118.92, 141.557);
+ new ShapeRef(router, poly14, 14);
+
+ Polygon poly13(4);
+ poly13.ps[0] = Point(1158.92, 323.557);
+ poly13.ps[1] = Point(1158.92, 363.557);
+ poly13.ps[2] = Point(1118.92, 363.557);
+ poly13.ps[3] = Point(1118.92, 323.557);
+ new ShapeRef(router, poly13, 13);
+
+ Polygon poly61(4);
+ poly61.ps[0] = Point(577.924, -44.6578);
+ poly61.ps[1] = Point(577.924, -4.65778);
+ poly61.ps[2] = Point(537.924, -4.65778);
+ poly61.ps[3] = Point(537.924, -44.6578);
+ new ShapeRef(router, poly61, 61);
+
+ Polygon poly101(4);
+ poly101.ps[0] = Point(1208.92, 142.342);
+ poly101.ps[1] = Point(1208.92, 162.342);
+ poly101.ps[2] = Point(1188.92, 162.342);
+ poly101.ps[3] = Point(1188.92, 142.342);
+ new ShapeRef(router, poly101, 101);
+
+ Polygon poly72(4);
+ poly72.ps[0] = Point(87.9242, 357.557);
+ poly72.ps[1] = Point(87.9242, 377.557);
+ poly72.ps[2] = Point(67.9242, 377.557);
+ poly72.ps[3] = Point(67.9242, 357.557);
+ new ShapeRef(router, poly72, 72);
+
+ Polygon poly41(4);
+ poly41.ps[0] = Point(577.924, 743.557);
+ poly41.ps[1] = Point(577.924, 783.557);
+ poly41.ps[2] = Point(537.924, 783.557);
+ poly41.ps[3] = Point(537.924, 743.557);
+ new ShapeRef(router, poly41, 41);
+
+ Polygon poly30(4);
+ poly30.ps[0] = Point(1278.92, 415.557);
+ poly30.ps[1] = Point(1278.92, 455.557);
+ poly30.ps[2] = Point(1238.92, 455.557);
+ poly30.ps[3] = Point(1238.92, 415.557);
+ new ShapeRef(router, poly30, 30);
+
+ Polygon poly65(4);
+ poly65.ps[0] = Point(97.9242, 599.557);
+ poly65.ps[1] = Point(97.9242, 639.557);
+ poly65.ps[2] = Point(57.9242, 639.557);
+ poly65.ps[3] = Point(57.9242, 599.557);
+ new ShapeRef(router, poly65, 65);
+
+ Polygon poly37(4);
+ poly37.ps[0] = Point(457.924, 607.557);
+ poly37.ps[1] = Point(457.924, 647.557);
+ poly37.ps[2] = Point(417.924, 647.557);
+ poly37.ps[3] = Point(417.924, 607.557);
+ new ShapeRef(router, poly37, 37);
+
+ Polygon poly35(4);
+ poly35.ps[0] = Point(1158.92, 40.3422);
+ poly35.ps[1] = Point(1158.92, 80.3422);
+ poly35.ps[2] = Point(1118.92, 80.3422);
+ poly35.ps[3] = Point(1118.92, 40.3422);
+ new ShapeRef(router, poly35, 35);
+
+ Polygon poly26(4);
+ poly26.ps[0] = Point(697.924, 743.557);
+ poly26.ps[1] = Point(697.924, 783.557);
+ poly26.ps[2] = Point(657.924, 783.557);
+ poly26.ps[3] = Point(657.924, 743.557);
+ new ShapeRef(router, poly26, 26);
+
+ Polygon poly80(4);
+ poly80.ps[0] = Point(507.924, 753.557);
+ poly80.ps[1] = Point(507.924, 773.557);
+ poly80.ps[2] = Point(487.924, 773.557);
+ poly80.ps[3] = Point(487.924, 753.557);
+ new ShapeRef(router, poly80, 80);
+
+ Polygon poly81(4);
+ poly81.ps[0] = Point(627.924, 753.557);
+ poly81.ps[1] = Point(627.924, 773.557);
+ poly81.ps[2] = Point(607.924, 773.557);
+ poly81.ps[3] = Point(607.924, 753.557);
+ new ShapeRef(router, poly81, 81);
+
+ Polygon poly79(4);
+ poly79.ps[0] = Point(387.924, 753.557);
+ poly79.ps[1] = Point(387.924, 773.557);
+ poly79.ps[2] = Point(367.924, 773.557);
+ poly79.ps[3] = Point(367.924, 753.557);
+ new ShapeRef(router, poly79, 79);
+
+ Polygon poly78(4);
+ poly78.ps[0] = Point(387.924, 617.557);
+ poly78.ps[1] = Point(387.924, 637.557);
+ poly78.ps[2] = Point(367.924, 637.557);
+ poly78.ps[3] = Point(367.924, 617.557);
+ new ShapeRef(router, poly78, 78);
+
+ Polygon poly77(4);
+ poly77.ps[0] = Point(267.924, 753.557);
+ poly77.ps[1] = Point(267.924, 773.557);
+ poly77.ps[2] = Point(247.924, 773.557);
+ poly77.ps[3] = Point(247.924, 753.557);
+ new ShapeRef(router, poly77, 77);
+
+ Polygon poly12(4);
+ poly12.ps[0] = Point(1038.92, 260.557);
+ poly12.ps[1] = Point(1038.92, 300.557);
+ poly12.ps[2] = Point(998.924, 300.557);
+ poly12.ps[3] = Point(998.924, 260.557);
+ new ShapeRef(router, poly12, 12);
+
+ Polygon poly76(4);
+ poly76.ps[0] = Point(147.924, 753.557);
+ poly76.ps[1] = Point(147.924, 773.557);
+ poly76.ps[2] = Point(127.924, 773.557);
+ poly76.ps[3] = Point(127.924, 753.557);
+ new ShapeRef(router, poly76, 76);
+
+ Polygon poly75(4);
+ poly75.ps[0] = Point(87.9242, 651.557);
+ poly75.ps[1] = Point(87.9242, 671.557);
+ poly75.ps[2] = Point(67.9242, 671.557);
+ poly75.ps[3] = Point(67.9242, 651.557);
+ new ShapeRef(router, poly75, 75);
+
+ Polygon poly32(4);
+ poly32.ps[0] = Point(1038.92, 141.557);
+ poly32.ps[1] = Point(1038.92, 181.557);
+ poly32.ps[2] = Point(998.924, 181.557);
+ poly32.ps[3] = Point(998.924, 141.557);
+ new ShapeRef(router, poly32, 32);
+
+ Polygon poly11(4);
+ poly11.ps[0] = Point(817.924, -80.6578);
+ poly11.ps[1] = Point(817.924, -40.6578);
+ poly11.ps[2] = Point(777.924, -40.6578);
+ poly11.ps[3] = Point(777.924, -80.6578);
+ new ShapeRef(router, poly11, 11);
+
+ Polygon poly36(4);
+ poly36.ps[0] = Point(697.924, 507.557);
+ poly36.ps[1] = Point(697.924, 547.557);
+ poly36.ps[2] = Point(657.924, 547.557);
+ poly36.ps[3] = Point(657.924, 507.557);
+ new ShapeRef(router, poly36, 36);
+
+ Polygon poly126(4);
+ poly126.ps[0] = Point(525.924, -24.1578);
+ poly126.ps[1] = Point(525.924, 15.8422);
+ poly126.ps[2] = Point(469.924, 15.8422);
+ poly126.ps[3] = Point(469.924, -24.1578);
+ new ShapeRef(router, poly126, 126);
+
+ Polygon poly127(4);
+ poly127.ps[0] = Point(645.924, -24.1578);
+ poly127.ps[1] = Point(645.924, 15.8422);
+ poly127.ps[2] = Point(589.924, 15.8422);
+ poly127.ps[3] = Point(589.924, -24.1578);
+ new ShapeRef(router, poly127, 127);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(1371.92, 29.8422);
+ poly4.ps[1] = Point(1371.92, 69.8422);
+ poly4.ps[2] = Point(1331.92, 69.8422);
+ poly4.ps[3] = Point(1331.92, 29.8422);
+ new ShapeRef(router, poly4, 4);
+
+ Polygon poly97(4);
+ poly97.ps[0] = Point(1088.92, 378.557);
+ poly97.ps[1] = Point(1088.92, 398.557);
+ poly97.ps[2] = Point(1068.92, 398.557);
+ poly97.ps[3] = Point(1068.92, 378.557);
+ new ShapeRef(router, poly97, 97);
+
+ Polygon poly103(4);
+ poly103.ps[0] = Point(968.924, 270.557);
+ poly103.ps[1] = Point(968.924, 290.557);
+ poly103.ps[2] = Point(948.924, 290.557);
+ poly103.ps[3] = Point(948.924, 270.557);
+ new ShapeRef(router, poly103, 103);
+
+ Polygon poly121(4);
+ poly121.ps[0] = Point(645.924, 693.557);
+ poly121.ps[1] = Point(645.924, 733.557);
+ poly121.ps[2] = Point(589.924, 733.557);
+ poly121.ps[3] = Point(589.924, 693.557);
+ new ShapeRef(router, poly121, 121);
+
+ Polygon poly104(4);
+ poly104.ps[0] = Point(747.924, 151.557);
+ poly104.ps[1] = Point(747.924, 171.557);
+ poly104.ps[2] = Point(727.924, 171.557);
+ poly104.ps[3] = Point(727.924, 151.557);
+ new ShapeRef(router, poly104, 104);
+
+ Polygon poly71(4);
+ poly71.ps[0] = Point(267.924, 305.557);
+ poly71.ps[1] = Point(267.924, 325.557);
+ poly71.ps[2] = Point(247.924, 325.557);
+ poly71.ps[3] = Point(247.924, 305.557);
+ new ShapeRef(router, poly71, 71);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(937.924, -80.6578);
+ poly10.ps[1] = Point(937.924, -40.6578);
+ poly10.ps[2] = Point(897.924, -40.6578);
+ poly10.ps[3] = Point(897.924, -80.6578);
+ new ShapeRef(router, poly10, 10);
+
+ Polygon poly116(4);
+ poly116.ps[0] = Point(165.924, 693.557);
+ poly116.ps[1] = Point(165.924, 733.557);
+ poly116.ps[2] = Point(109.924, 733.557);
+ poly116.ps[3] = Point(109.924, 693.557);
+ new ShapeRef(router, poly116, 116);
+
+ Polygon poly23(4);
+ poly23.ps[0] = Point(337.924, 141.557);
+ poly23.ps[1] = Point(337.924, 181.557);
+ poly23.ps[2] = Point(297.924, 181.557);
+ poly23.ps[3] = Point(297.924, 141.557);
+ new ShapeRef(router, poly23, 23);
+
+ Polygon poly115(4);
+ poly115.ps[0] = Point(167.924, 641.557);
+ poly115.ps[1] = Point(167.924, 681.557);
+ poly115.ps[2] = Point(111.924, 681.557);
+ poly115.ps[3] = Point(111.924, 641.557);
+ new ShapeRef(router, poly115, 115);
+
+ Polygon poly83(4);
+ poly83.ps[0] = Point(627.924, 893.057);
+ poly83.ps[1] = Point(627.924, 913.057);
+ poly83.ps[2] = Point(607.924, 913.057);
+ poly83.ps[3] = Point(607.924, 893.057);
+ new ShapeRef(router, poly83, 83);
+
+ Polygon poly94(4);
+ poly94.ps[0] = Point(867.924, 425.557);
+ poly94.ps[1] = Point(867.924, 445.557);
+ poly94.ps[2] = Point(847.924, 445.557);
+ poly94.ps[3] = Point(847.924, 425.557);
+ new ShapeRef(router, poly94, 94);
+
+ Polygon poly106(4);
+ poly106.ps[0] = Point(765.924, -130.658);
+ poly106.ps[1] = Point(765.924, -90.6578);
+ poly106.ps[2] = Point(709.924, -90.6578);
+ poly106.ps[3] = Point(709.924, -130.658);
+ new ShapeRef(router, poly106, 106);
+
+ Polygon poly113(4);
+ poly113.ps[0] = Point(165.924, 457.557);
+ poly113.ps[1] = Point(165.924, 497.557);
+ poly113.ps[2] = Point(109.924, 497.557);
+ poly113.ps[3] = Point(109.924, 457.557);
+ new ShapeRef(router, poly113, 113);
+
+ Polygon poly92(4);
+ poly92.ps[0] = Point(627.924, 425.557);
+ poly92.ps[1] = Point(627.924, 445.557);
+ poly92.ps[2] = Point(607.924, 445.557);
+ poly92.ps[3] = Point(607.924, 425.557);
+ new ShapeRef(router, poly92, 92);
+
+ Polygon poly46(4);
+ poly46.ps[0] = Point(577.924, 415.557);
+ poly46.ps[1] = Point(577.924, 455.557);
+ poly46.ps[2] = Point(537.924, 455.557);
+ poly46.ps[3] = Point(537.924, 415.557);
+ new ShapeRef(router, poly46, 46);
+
+ Polygon poly102(4);
+ poly102.ps[0] = Point(1088.92, -70.6578);
+ poly102.ps[1] = Point(1088.92, -50.6578);
+ poly102.ps[2] = Point(1068.92, -50.6578);
+ poly102.ps[3] = Point(1068.92, -70.6578);
+ new ShapeRef(router, poly102, 102);
+
+ Polygon poly122(4);
+ poly122.ps[0] = Point(525.924, 833.057);
+ poly122.ps[1] = Point(525.924, 873.057);
+ poly122.ps[2] = Point(469.924, 873.057);
+ poly122.ps[3] = Point(469.924, 833.057);
+ new ShapeRef(router, poly122, 122);
+
+ Polygon poly114(4);
+ poly114.ps[0] = Point(165.924, 549.557);
+ poly114.ps[1] = Point(165.924, 589.557);
+ poly114.ps[2] = Point(109.924, 589.557);
+ poly114.ps[3] = Point(109.924, 549.557);
+ new ShapeRef(router, poly114, 114);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(1038.92, -80.6578);
+ poly9.ps[1] = Point(1038.92, -40.6578);
+ poly9.ps[2] = Point(998.924, -40.6578);
+ poly9.ps[3] = Point(998.924, -80.6578);
+ new ShapeRef(router, poly9, 9);
+
+ Polygon poly123(4);
+ poly123.ps[0] = Point(645.924, 833.057);
+ poly123.ps[1] = Point(645.924, 873.057);
+ poly123.ps[2] = Point(589.924, 873.057);
+ poly123.ps[3] = Point(589.924, 833.057);
+ new ShapeRef(router, poly123, 123);
+
+ Polygon poly95(4);
+ poly95.ps[0] = Point(867.924, 151.557);
+ poly95.ps[1] = Point(867.924, 171.557);
+ poly95.ps[2] = Point(847.924, 171.557);
+ poly95.ps[3] = Point(847.924, 151.557);
+ new ShapeRef(router, poly95, 95);
+
+ Polygon poly82(4);
+ poly82.ps[0] = Point(507.924, 893.057);
+ poly82.ps[1] = Point(507.924, 913.057);
+ poly82.ps[2] = Point(487.924, 913.057);
+ poly82.ps[3] = Point(487.924, 893.057);
+ new ShapeRef(router, poly82, 82);
+
+ Polygon poly111(4);
+ poly111.ps[0] = Point(285.924, 245.557);
+ poly111.ps[1] = Point(285.924, 285.557);
+ poly111.ps[2] = Point(229.924, 285.557);
+ poly111.ps[3] = Point(229.924, 245.557);
+ new ShapeRef(router, poly111, 111);
+
+ Polygon poly85(4);
+ poly85.ps[0] = Point(387.924, 17.3422);
+ poly85.ps[1] = Point(387.924, 37.3422);
+ poly85.ps[2] = Point(367.924, 37.3422);
+ poly85.ps[3] = Point(367.924, 17.3422);
+ new ShapeRef(router, poly85, 85);
+
+ Polygon poly93(4);
+ poly93.ps[0] = Point(867.924, 333.557);
+ poly93.ps[1] = Point(867.924, 353.557);
+ poly93.ps[2] = Point(847.924, 353.557);
+ poly93.ps[3] = Point(847.924, 333.557);
+ new ShapeRef(router, poly93, 93);
+
+ Polygon poly119(4);
+ poly119.ps[0] = Point(405.924, 693.557);
+ poly119.ps[1] = Point(405.924, 733.557);
+ poly119.ps[2] = Point(349.924, 733.557);
+ poly119.ps[3] = Point(349.924, 693.557);
+ new ShapeRef(router, poly119, 119);
+
+ Polygon poly120(4);
+ poly120.ps[0] = Point(525.924, 693.557);
+ poly120.ps[1] = Point(525.924, 733.557);
+ poly120.ps[2] = Point(469.924, 733.557);
+ poly120.ps[3] = Point(469.924, 693.557);
+ new ShapeRef(router, poly120, 120);
+
+ Polygon poly118(4);
+ poly118.ps[0] = Point(405.924, 557.557);
+ poly118.ps[1] = Point(405.924, 597.557);
+ poly118.ps[2] = Point(349.924, 597.557);
+ poly118.ps[3] = Point(349.924, 557.557);
+ new ShapeRef(router, poly118, 118);
+
+ Polygon poly91(4);
+ poly91.ps[0] = Point(627.924, 517.557);
+ poly91.ps[1] = Point(627.924, 537.557);
+ poly91.ps[2] = Point(607.924, 537.557);
+ poly91.ps[3] = Point(607.924, 517.557);
+ new ShapeRef(router, poly91, 91);
+
+ Polygon poly112(4);
+ poly112.ps[0] = Point(167.924, 347.557);
+ poly112.ps[1] = Point(167.924, 387.557);
+ poly112.ps[2] = Point(111.924, 387.557);
+ poly112.ps[3] = Point(111.924, 347.557);
+ new ShapeRef(router, poly112, 112);
+
+ Polygon poly89(4);
+ poly89.ps[0] = Point(507.924, 517.557);
+ poly89.ps[1] = Point(507.924, 537.557);
+ poly89.ps[2] = Point(487.924, 537.557);
+ poly89.ps[3] = Point(487.924, 517.557);
+ new ShapeRef(router, poly89, 89);
+
+ Polygon poly110(4);
+ poly110.ps[0] = Point(287.924, 193.557);
+ poly110.ps[1] = Point(287.924, 233.557);
+ poly110.ps[2] = Point(231.924, 233.557);
+ poly110.ps[3] = Point(231.924, 193.557);
+ new ShapeRef(router, poly110, 110);
+
+ Polygon poly107(4);
+ poly107.ps[0] = Point(165.924, -35.1578);
+ poly107.ps[1] = Point(165.924, 4.84222);
+ poly107.ps[2] = Point(109.924, 4.84222);
+ poly107.ps[3] = Point(109.924, -35.1578);
+ new ShapeRef(router, poly107, 107);
+
+ Polygon poly31(4);
+ poly31.ps[0] = Point(1278.92, 141.557);
+ poly31.ps[1] = Point(1278.92, 181.557);
+ poly31.ps[2] = Point(1238.92, 181.557);
+ poly31.ps[3] = Point(1238.92, 141.557);
+ new ShapeRef(router, poly31, 31);
+
+ Polygon poly29(4);
+ poly29.ps[0] = Point(1038.92, 415.557);
+ poly29.ps[1] = Point(1038.92, 455.557);
+ poly29.ps[2] = Point(998.924, 455.557);
+ poly29.ps[3] = Point(998.924, 415.557);
+ new ShapeRef(router, poly29, 29);
+
+ Polygon poly34(4);
+ poly34.ps[0] = Point(1278.92, 323.557);
+ poly34.ps[1] = Point(1278.92, 363.557);
+ poly34.ps[2] = Point(1238.92, 363.557);
+ poly34.ps[3] = Point(1238.92, 323.557);
+ new ShapeRef(router, poly34, 34);
+
+ Polygon poly108(4);
+ poly108.ps[0] = Point(165.924, 91.5565);
+ poly108.ps[1] = Point(165.924, 131.557);
+ poly108.ps[2] = Point(109.924, 131.557);
+ poly108.ps[3] = Point(109.924, 91.5565);
+ new ShapeRef(router, poly108, 108);
+
+ Polygon poly74(4);
+ poly74.ps[0] = Point(147.924, 609.557);
+ poly74.ps[1] = Point(147.924, 629.557);
+ poly74.ps[2] = Point(127.924, 629.557);
+ poly74.ps[3] = Point(127.924, 609.557);
+ new ShapeRef(router, poly74, 74);
+
+ Polygon poly96(4);
+ poly96.ps[0] = Point(747.924, 333.557);
+ poly96.ps[1] = Point(747.924, 353.557);
+ poly96.ps[2] = Point(727.924, 353.557);
+ poly96.ps[3] = Point(727.924, 333.557);
+ new ShapeRef(router, poly96, 96);
+
+ Polygon poly69(4);
+ poly69.ps[0] = Point(267.924, 151.557);
+ poly69.ps[1] = Point(267.924, 171.557);
+ poly69.ps[2] = Point(247.924, 171.557);
+ poly69.ps[3] = Point(247.924, 151.557);
+ new ShapeRef(router, poly69, 69);
+
+ Polygon poly44(4);
+ poly44.ps[0] = Point(97.9242, 507.557);
+ poly44.ps[1] = Point(97.9242, 547.557);
+ poly44.ps[2] = Point(57.9242, 547.557);
+ poly44.ps[3] = Point(57.9242, 507.557);
+ new ShapeRef(router, poly44, 44);
+
+ Polygon poly90(4);
+ poly90.ps[0] = Point(507.924, 425.557);
+ poly90.ps[1] = Point(507.924, 445.557);
+ poly90.ps[2] = Point(487.924, 445.557);
+ poly90.ps[3] = Point(487.924, 425.557);
+ new ShapeRef(router, poly90, 90);
+
+ Polygon poly56(4);
+ poly56.ps[0] = Point(457.924, -44.6578);
+ poly56.ps[1] = Point(457.924, -4.65778);
+ poly56.ps[2] = Point(417.924, -4.65778);
+ poly56.ps[3] = Point(417.924, -44.6578);
+ new ShapeRef(router, poly56, 56);
+
+ Polygon poly25(4);
+ poly25.ps[0] = Point(697.924, 883.057);
+ poly25.ps[1] = Point(697.924, 923.057);
+ poly25.ps[2] = Point(657.924, 923.057);
+ poly25.ps[3] = Point(657.924, 883.057);
+ new ShapeRef(router, poly25, 25);
+
+ Polygon poly33(4);
+ poly33.ps[0] = Point(937.924, 415.557);
+ poly33.ps[1] = Point(937.924, 455.557);
+ poly33.ps[2] = Point(897.924, 455.557);
+ poly33.ps[3] = Point(897.924, 415.557);
+ new ShapeRef(router, poly33, 33);
+
+ Polygon poly59(4);
+ poly59.ps[0] = Point(937.924, 323.557);
+ poly59.ps[1] = Point(937.924, 363.557);
+ poly59.ps[2] = Point(897.924, 363.557);
+ poly59.ps[3] = Point(897.924, 323.557);
+ new ShapeRef(router, poly59, 59);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(1278.92, -22.1578);
+ poly3.ps[1] = Point(1278.92, 17.8422);
+ poly3.ps[2] = Point(1238.92, 17.8422);
+ poly3.ps[3] = Point(1238.92, -22.1578);
+ new ShapeRef(router, poly3, 3);
+
+ ConnRef *connRef211 = new ConnRef(router, 211);
+ ConnEnd srcPt211(Point(507.924, 435.557), 15);
+ connRef211->setSourceEndpoint(srcPt211);
+ ConnEnd dstPt211(Point(557.924, 435.557), 15);
+ connRef211->setDestEndpoint(dstPt211);
+ connRef211->setRoutingType((ConnType)2);
+
+ ConnRef *connRef212 = new ConnRef(router, 212);
+ ConnEnd srcPt212(Point(627.924, 527.557), 15);
+ connRef212->setSourceEndpoint(srcPt212);
+ ConnEnd dstPt212(Point(677.924, 527.557), 15);
+ connRef212->setDestEndpoint(dstPt212);
+ connRef212->setRoutingType((ConnType)2);
+
+ ConnRef *connRef213 = new ConnRef(router, 213);
+ ConnEnd srcPt213(Point(627.924, 435.557), 15);
+ connRef213->setSourceEndpoint(srcPt213);
+ ConnEnd dstPt213(Point(677.924, 435.557), 15);
+ connRef213->setDestEndpoint(dstPt213);
+ connRef213->setRoutingType((ConnType)2);
+
+ ConnRef *connRef214 = new ConnRef(router, 214);
+ ConnEnd srcPt214(Point(867.924, 343.557), 15);
+ connRef214->setSourceEndpoint(srcPt214);
+ ConnEnd dstPt214(Point(917.924, 343.557), 15);
+ connRef214->setDestEndpoint(dstPt214);
+ connRef214->setRoutingType((ConnType)2);
+
+ ConnRef *connRef215 = new ConnRef(router, 215);
+ ConnEnd srcPt215(Point(867.924, 435.557), 15);
+ connRef215->setSourceEndpoint(srcPt215);
+ ConnEnd dstPt215(Point(917.924, 435.557), 15);
+ connRef215->setDestEndpoint(dstPt215);
+ connRef215->setRoutingType((ConnType)2);
+
+ ConnRef *connRef216 = new ConnRef(router, 216);
+ ConnEnd srcPt216(Point(867.924, 161.557), 15);
+ connRef216->setSourceEndpoint(srcPt216);
+ ConnEnd dstPt216(Point(917.924, 161.557), 15);
+ connRef216->setDestEndpoint(dstPt216);
+ connRef216->setRoutingType((ConnType)2);
+
+ ConnRef *connRef217 = new ConnRef(router, 217);
+ ConnEnd srcPt217(Point(747.924, 343.557), 15);
+ connRef217->setSourceEndpoint(srcPt217);
+ ConnEnd dstPt217(Point(797.924, 343.557), 15);
+ connRef217->setDestEndpoint(dstPt217);
+ connRef217->setRoutingType((ConnType)2);
+
+ ConnRef *connRef218 = new ConnRef(router, 218);
+ ConnEnd srcPt218(Point(1088.92, 388.557), 15);
+ connRef218->setSourceEndpoint(srcPt218);
+ ConnEnd dstPt218(Point(1138.92, 435.557), 15);
+ connRef218->setDestEndpoint(dstPt218);
+ connRef218->setRoutingType((ConnType)2);
+
+ ConnRef *connRef219 = new ConnRef(router, 219);
+ ConnEnd srcPt219(Point(1208.92, 388.557), 15);
+ connRef219->setSourceEndpoint(srcPt219);
+ ConnEnd dstPt219(Point(1258.92, 435.557), 15);
+ connRef219->setDestEndpoint(dstPt219);
+ connRef219->setRoutingType((ConnType)2);
+
+ ConnRef *connRef220 = new ConnRef(router, 220);
+ ConnEnd srcPt220(Point(1088.92, 152.342), 15);
+ connRef220->setSourceEndpoint(srcPt220);
+ ConnEnd dstPt220(Point(1138.92, 161.557), 15);
+ connRef220->setDestEndpoint(dstPt220);
+ connRef220->setRoutingType((ConnType)2);
+
+ ConnRef *connRef221 = new ConnRef(router, 221);
+ ConnEnd srcPt221(Point(1088.92, 60.3422), 15);
+ connRef221->setSourceEndpoint(srcPt221);
+ ConnEnd dstPt221(Point(1138.92, 60.3422), 15);
+ connRef221->setDestEndpoint(dstPt221);
+ connRef221->setRoutingType((ConnType)2);
+
+ ConnRef *connRef222 = new ConnRef(router, 222);
+ ConnEnd srcPt222(Point(1208.92, 152.342), 15);
+ connRef222->setSourceEndpoint(srcPt222);
+ ConnEnd dstPt222(Point(1258.92, 161.557), 15);
+ connRef222->setDestEndpoint(dstPt222);
+ connRef222->setRoutingType((ConnType)2);
+
+ ConnRef *connRef223 = new ConnRef(router, 223);
+ ConnEnd srcPt223(Point(1088.92, -60.6578), 15);
+ connRef223->setSourceEndpoint(srcPt223);
+ ConnEnd dstPt223(Point(1138.92, -60.6578), 15);
+ connRef223->setDestEndpoint(dstPt223);
+ connRef223->setRoutingType((ConnType)2);
+
+ ConnRef *connRef224 = new ConnRef(router, 224);
+ ConnEnd srcPt224(Point(747.924, 161.557), 15);
+ connRef224->setSourceEndpoint(srcPt224);
+ ConnEnd dstPt224(Point(797.924, 161.557), 15);
+ connRef224->setDestEndpoint(dstPt224);
+ connRef224->setRoutingType((ConnType)2);
+
+ ConnRef *connRef225 = new ConnRef(router, 225);
+ ConnEnd srcPt225(Point(747.924, 860.057), 15);
+ connRef225->setSourceEndpoint(srcPt225);
+ ConnEnd dstPt225(Point(797.924, 860.057), 15);
+ connRef225->setDestEndpoint(dstPt225);
+ connRef225->setRoutingType((ConnType)2);
+
+ ConnRef *connRef226 = new ConnRef(router, 226);
+ ConnEnd srcPt226(Point(737.924, -110.658), 15);
+ connRef226->setSourceEndpoint(srcPt226);
+ ConnEnd dstPt226(Point(737.924, -60.6578), 15);
+ connRef226->setDestEndpoint(dstPt226);
+ connRef226->setRoutingType((ConnType)2);
+
+ ConnRef *connRef227 = new ConnRef(router, 227);
+ ConnEnd srcPt227(Point(137.924, -15.1578), 15);
+ connRef227->setSourceEndpoint(srcPt227);
+ ConnEnd dstPt227(Point(137.924, 34.8422), 15);
+ connRef227->setDestEndpoint(dstPt227);
+ connRef227->setRoutingType((ConnType)2);
+
+ ConnRef *connRef228 = new ConnRef(router, 228);
+ ConnEnd srcPt228(Point(137.924, 111.557), 15);
+ connRef228->setSourceEndpoint(srcPt228);
+ ConnEnd dstPt228(Point(137.924, 161.557), 15);
+ connRef228->setDestEndpoint(dstPt228);
+ connRef228->setRoutingType((ConnType)2);
+
+ ConnRef *connRef229 = new ConnRef(router, 229);
+ ConnEnd srcPt229(Point(257.924, 111.557), 15);
+ connRef229->setSourceEndpoint(srcPt229);
+ ConnEnd dstPt229(Point(257.924, 161.557), 15);
+ connRef229->setDestEndpoint(dstPt229);
+ connRef229->setRoutingType((ConnType)2);
+
+ ConnRef *connRef230 = new ConnRef(router, 230);
+ ConnEnd srcPt230(Point(259.924, 213.557), 15);
+ connRef230->setSourceEndpoint(srcPt230);
+ ConnEnd dstPt230(Point(197.924, 213.557), 15);
+ connRef230->setDestEndpoint(dstPt230);
+ connRef230->setRoutingType((ConnType)2);
+
+ ConnRef *connRef231 = new ConnRef(router, 231);
+ ConnEnd srcPt231(Point(257.924, 265.557), 15);
+ connRef231->setSourceEndpoint(srcPt231);
+ ConnEnd dstPt231(Point(257.924, 315.557), 15);
+ connRef231->setDestEndpoint(dstPt231);
+ connRef231->setRoutingType((ConnType)2);
+
+ ConnRef *connRef232 = new ConnRef(router, 232);
+ ConnEnd srcPt232(Point(139.924, 367.557), 15);
+ connRef232->setSourceEndpoint(srcPt232);
+ ConnEnd dstPt232(Point(77.9242, 367.557), 15);
+ connRef232->setDestEndpoint(dstPt232);
+ connRef232->setRoutingType((ConnType)2);
+
+ ConnRef *connRef233 = new ConnRef(router, 233);
+ ConnEnd srcPt233(Point(137.924, 477.557), 15);
+ connRef233->setSourceEndpoint(srcPt233);
+ ConnEnd dstPt233(Point(137.924, 527.557), 15);
+ connRef233->setDestEndpoint(dstPt233);
+ connRef233->setRoutingType((ConnType)2);
+
+ ConnRef *connRef234 = new ConnRef(router, 234);
+ ConnEnd srcPt234(Point(137.924, 569.557), 15);
+ connRef234->setSourceEndpoint(srcPt234);
+ ConnEnd dstPt234(Point(137.924, 619.557), 15);
+ connRef234->setDestEndpoint(dstPt234);
+ connRef234->setRoutingType((ConnType)2);
+
+ ConnRef *connRef235 = new ConnRef(router, 235);
+ ConnEnd srcPt235(Point(139.924, 661.557), 15);
+ connRef235->setSourceEndpoint(srcPt235);
+ ConnEnd dstPt235(Point(77.9242, 661.557), 15);
+ connRef235->setDestEndpoint(dstPt235);
+ connRef235->setRoutingType((ConnType)2);
+
+ ConnRef *connRef236 = new ConnRef(router, 236);
+ ConnEnd srcPt236(Point(137.924, 713.557), 15);
+ connRef236->setSourceEndpoint(srcPt236);
+ ConnEnd dstPt236(Point(137.924, 763.557), 15);
+ connRef236->setDestEndpoint(dstPt236);
+ connRef236->setRoutingType((ConnType)2);
+
+ ConnRef *connRef237 = new ConnRef(router, 237);
+ ConnEnd srcPt237(Point(257.924, 713.557), 15);
+ connRef237->setSourceEndpoint(srcPt237);
+ ConnEnd dstPt237(Point(257.924, 763.557), 15);
+ connRef237->setDestEndpoint(dstPt237);
+ connRef237->setRoutingType((ConnType)2);
+
+ ConnRef *connRef238 = new ConnRef(router, 238);
+ ConnEnd srcPt238(Point(377.924, 577.557), 15);
+ connRef238->setSourceEndpoint(srcPt238);
+ ConnEnd dstPt238(Point(377.924, 627.557), 15);
+ connRef238->setDestEndpoint(dstPt238);
+ connRef238->setRoutingType((ConnType)2);
+
+ ConnRef *connRef239 = new ConnRef(router, 239);
+ ConnEnd srcPt239(Point(377.924, 713.557), 15);
+ connRef239->setSourceEndpoint(srcPt239);
+ ConnEnd dstPt239(Point(377.924, 763.557), 15);
+ connRef239->setDestEndpoint(dstPt239);
+ connRef239->setRoutingType((ConnType)2);
+
+ ConnRef *connRef240 = new ConnRef(router, 240);
+ ConnEnd srcPt240(Point(497.924, 713.557), 15);
+ connRef240->setSourceEndpoint(srcPt240);
+ ConnEnd dstPt240(Point(497.924, 763.557), 15);
+ connRef240->setDestEndpoint(dstPt240);
+ connRef240->setRoutingType((ConnType)2);
+
+ ConnRef *connRef241 = new ConnRef(router, 241);
+ ConnEnd srcPt241(Point(617.924, 713.557), 15);
+ connRef241->setSourceEndpoint(srcPt241);
+ ConnEnd dstPt241(Point(617.924, 763.557), 15);
+ connRef241->setDestEndpoint(dstPt241);
+ connRef241->setRoutingType((ConnType)2);
+
+ ConnRef *connRef242 = new ConnRef(router, 242);
+ ConnEnd srcPt242(Point(497.924, 853.057), 15);
+ connRef242->setSourceEndpoint(srcPt242);
+ ConnEnd dstPt242(Point(497.924, 903.057), 15);
+ connRef242->setDestEndpoint(dstPt242);
+ connRef242->setRoutingType((ConnType)2);
+
+ ConnRef *connRef243 = new ConnRef(router, 243);
+ ConnEnd srcPt243(Point(617.924, 853.057), 15);
+ connRef243->setSourceEndpoint(srcPt243);
+ ConnEnd dstPt243(Point(617.924, 903.057), 15);
+ connRef243->setDestEndpoint(dstPt243);
+ connRef243->setRoutingType((ConnType)2);
+
+ ConnRef *connRef244 = new ConnRef(router, 244);
+ ConnEnd srcPt244(Point(377.924, 111.557), 15);
+ connRef244->setSourceEndpoint(srcPt244);
+ ConnEnd dstPt244(Point(377.924, 161.557), 15);
+ connRef244->setDestEndpoint(dstPt244);
+ connRef244->setRoutingType((ConnType)2);
+
+ ConnRef *connRef245 = new ConnRef(router, 245);
+ ConnEnd srcPt245(Point(377.924, -22.6578), 15);
+ connRef245->setSourceEndpoint(srcPt245);
+ ConnEnd dstPt245(Point(377.924, 27.3422), 15);
+ connRef245->setDestEndpoint(dstPt245);
+ connRef245->setRoutingType((ConnType)2);
+
+ ConnRef *connRef246 = new ConnRef(router, 246);
+ ConnEnd srcPt246(Point(497.924, -4.15778), 15);
+ connRef246->setSourceEndpoint(srcPt246);
+ ConnEnd dstPt246(Point(497.924, 45.8422), 15);
+ connRef246->setDestEndpoint(dstPt246);
+ connRef246->setRoutingType((ConnType)2);
+
+ ConnRef *connRef247 = new ConnRef(router, 247);
+ ConnEnd srcPt247(Point(617.924, -4.15778), 15);
+ connRef247->setSourceEndpoint(srcPt247);
+ ConnEnd dstPt247(Point(617.924, 45.8422), 15);
+ connRef247->setDestEndpoint(dstPt247);
+ connRef247->setRoutingType((ConnType)2);
+
+ ConnRef *connRef248 = new ConnRef(router, 248);
+ ConnEnd srcPt248(Point(737.924, 524.057), 15);
+ connRef248->setSourceEndpoint(srcPt248);
+ ConnEnd dstPt248(Point(737.924, 574.057), 15);
+ connRef248->setDestEndpoint(dstPt248);
+ connRef248->setRoutingType((ConnType)2);
+
+ ConnRef *connRef249 = new ConnRef(router, 249);
+ ConnEnd srcPt249(Point(497.924, 477.557), 15);
+ connRef249->setSourceEndpoint(srcPt249);
+ ConnEnd dstPt249(Point(497.924, 527.557), 15);
+ connRef249->setDestEndpoint(dstPt249);
+ connRef249->setRoutingType((ConnType)2);
+
+ ConnRef *connRef250 = new ConnRef(router, 250);
+ ConnEnd srcPt250(Point(497.924, 385.557), 15);
+ connRef250->setSourceEndpoint(srcPt250);
+ ConnEnd dstPt250(Point(497.924, 435.557), 15);
+ connRef250->setDestEndpoint(dstPt250);
+ connRef250->setRoutingType((ConnType)2);
+
+ ConnRef *connRef251 = new ConnRef(router, 251);
+ ConnEnd srcPt251(Point(617.924, 477.557), 15);
+ connRef251->setSourceEndpoint(srcPt251);
+ ConnEnd dstPt251(Point(617.924, 527.557), 15);
+ connRef251->setDestEndpoint(dstPt251);
+ connRef251->setRoutingType((ConnType)2);
+
+ ConnRef *connRef252 = new ConnRef(router, 252);
+ ConnEnd srcPt252(Point(617.924, 385.557), 15);
+ connRef252->setSourceEndpoint(srcPt252);
+ ConnEnd dstPt252(Point(617.924, 435.557), 15);
+ connRef252->setDestEndpoint(dstPt252);
+ connRef252->setRoutingType((ConnType)2);
+
+ ConnRef *connRef253 = new ConnRef(router, 253);
+ ConnEnd srcPt253(Point(857.924, 293.557), 15);
+ connRef253->setSourceEndpoint(srcPt253);
+ ConnEnd dstPt253(Point(857.924, 343.557), 15);
+ connRef253->setDestEndpoint(dstPt253);
+ connRef253->setRoutingType((ConnType)2);
+
+ ConnRef *connRef254 = new ConnRef(router, 254);
+ ConnEnd srcPt254(Point(857.924, 385.557), 15);
+ connRef254->setSourceEndpoint(srcPt254);
+ ConnEnd dstPt254(Point(857.924, 435.557), 15);
+ connRef254->setDestEndpoint(dstPt254);
+ connRef254->setRoutingType((ConnType)2);
+
+ ConnRef *connRef255 = new ConnRef(router, 255);
+ ConnEnd srcPt255(Point(857.924, 111.557), 15);
+ connRef255->setSourceEndpoint(srcPt255);
+ ConnEnd dstPt255(Point(857.924, 161.557), 15);
+ connRef255->setDestEndpoint(dstPt255);
+ connRef255->setRoutingType((ConnType)2);
+
+ ConnRef *connRef256 = new ConnRef(router, 256);
+ ConnEnd srcPt256(Point(737.924, 293.557), 15);
+ connRef256->setSourceEndpoint(srcPt256);
+ ConnEnd dstPt256(Point(737.924, 343.557), 15);
+ connRef256->setDestEndpoint(dstPt256);
+ connRef256->setRoutingType((ConnType)2);
+
+ ConnRef *connRef257 = new ConnRef(router, 257);
+ ConnEnd srcPt257(Point(1078.92, 338.557), 15);
+ connRef257->setSourceEndpoint(srcPt257);
+ ConnEnd dstPt257(Point(1078.92, 388.557), 15);
+ connRef257->setDestEndpoint(dstPt257);
+ connRef257->setRoutingType((ConnType)2);
+
+ ConnRef *connRef258 = new ConnRef(router, 258);
+ ConnEnd srcPt258(Point(1198.92, 338.557), 15);
+ connRef258->setSourceEndpoint(srcPt258);
+ ConnEnd dstPt258(Point(1198.92, 388.557), 15);
+ connRef258->setDestEndpoint(dstPt258);
+ connRef258->setRoutingType((ConnType)2);
+
+ ConnRef *connRef259 = new ConnRef(router, 259);
+ ConnEnd srcPt259(Point(1078.92, 102.342), 15);
+ connRef259->setSourceEndpoint(srcPt259);
+ ConnEnd dstPt259(Point(1078.92, 152.342), 15);
+ connRef259->setDestEndpoint(dstPt259);
+ connRef259->setRoutingType((ConnType)2);
+
+ ConnRef *connRef260 = new ConnRef(router, 260);
+ ConnEnd srcPt260(Point(1078.92, 10.3422), 15);
+ connRef260->setSourceEndpoint(srcPt260);
+ ConnEnd dstPt260(Point(1078.92, 60.3422), 15);
+ connRef260->setDestEndpoint(dstPt260);
+ connRef260->setRoutingType((ConnType)2);
+
+ ConnRef *connRef261 = new ConnRef(router, 261);
+ ConnEnd srcPt261(Point(1198.92, 102.342), 15);
+ connRef261->setSourceEndpoint(srcPt261);
+ ConnEnd dstPt261(Point(1198.92, 152.342), 15);
+ connRef261->setDestEndpoint(dstPt261);
+ connRef261->setRoutingType((ConnType)2);
+
+ ConnRef *connRef262 = new ConnRef(router, 262);
+ ConnEnd srcPt262(Point(1078.92, -110.658), 15);
+ connRef262->setSourceEndpoint(srcPt262);
+ ConnEnd dstPt262(Point(1078.92, -60.6578), 15);
+ connRef262->setDestEndpoint(dstPt262);
+ connRef262->setRoutingType((ConnType)2);
+
+ ConnRef *connRef263 = new ConnRef(router, 263);
+ ConnEnd srcPt263(Point(958.924, 230.557), 15);
+ connRef263->setSourceEndpoint(srcPt263);
+ ConnEnd dstPt263(Point(958.924, 280.557), 15);
+ connRef263->setDestEndpoint(dstPt263);
+ connRef263->setRoutingType((ConnType)2);
+
+ ConnRef *connRef264 = new ConnRef(router, 264);
+ ConnEnd srcPt264(Point(737.924, 111.557), 15);
+ connRef264->setSourceEndpoint(srcPt264);
+ ConnEnd dstPt264(Point(737.924, 161.557), 15);
+ connRef264->setDestEndpoint(dstPt264);
+ connRef264->setRoutingType((ConnType)2);
+
+ ConnRef *connRef265 = new ConnRef(router, 265);
+ ConnEnd srcPt265(Point(737.924, 810.057), 15);
+ connRef265->setSourceEndpoint(srcPt265);
+ ConnEnd dstPt265(Point(737.924, 860.057), 15);
+ connRef265->setDestEndpoint(dstPt265);
+ connRef265->setRoutingType((ConnType)2);
+
+ ConnRef *connRef266 = new ConnRef(router, 266);
+ ConnEnd srcPt266(Point(77.9242, 161.557), 15);
+ connRef266->setSourceEndpoint(srcPt266);
+ ConnEnd dstPt266(Point(40.9242, 252.5), 15);
+ connRef266->setDestEndpoint(dstPt266);
+ connRef266->setRoutingType((ConnType)2);
+
+ ConnRef *connRef267 = new ConnRef(router, 267);
+ ConnEnd srcPt267(Point(77.9242, 763.557), 15);
+ connRef267->setSourceEndpoint(srcPt267);
+ ConnEnd dstPt267(Point(-46.0758, 329.75), 15);
+ connRef267->setDestEndpoint(dstPt267);
+ connRef267->setRoutingType((ConnType)2);
+
+ ConnRef *connRef148 = new ConnRef(router, 148);
+ ConnEnd srcPt148(Point(1018.92, -60.6578), 15);
+ connRef148->setSourceEndpoint(srcPt148);
+ ConnEnd dstPt148(Point(1068.92, -60.6578), 15);
+ connRef148->setDestEndpoint(dstPt148);
+ connRef148->setRoutingType((ConnType)2);
+
+ ConnRef *connRef149 = new ConnRef(router, 149);
+ ConnEnd srcPt149(Point(1138.92, 161.557), 15);
+ connRef149->setSourceEndpoint(srcPt149);
+ ConnEnd dstPt149(Point(1188.92, 152.342), 15);
+ connRef149->setDestEndpoint(dstPt149);
+ connRef149->setRoutingType((ConnType)2);
+
+ ConnRef *connRef150 = new ConnRef(router, 150);
+ ConnEnd srcPt150(Point(1138.92, 435.557), 15);
+ connRef150->setSourceEndpoint(srcPt150);
+ ConnEnd dstPt150(Point(1188.92, 388.557), 15);
+ connRef150->setDestEndpoint(dstPt150);
+ connRef150->setRoutingType((ConnType)2);
+
+ ConnRef *connRef151 = new ConnRef(router, 151);
+ ConnEnd srcPt151(Point(317.924, 763.557), 15);
+ connRef151->setSourceEndpoint(srcPt151);
+ ConnEnd dstPt151(Point(367.924, 627.557), 15);
+ connRef151->setDestEndpoint(dstPt151);
+ connRef151->setRoutingType((ConnType)2);
+
+ ConnRef *connRef152 = new ConnRef(router, 152);
+ ConnEnd srcPt152(Point(317.924, 763.557), 15);
+ connRef152->setSourceEndpoint(srcPt152);
+ ConnEnd dstPt152(Point(367.924, 763.557), 15);
+ connRef152->setDestEndpoint(dstPt152);
+ connRef152->setRoutingType((ConnType)2);
+
+ ConnRef *connRef153 = new ConnRef(router, 153);
+ ConnEnd srcPt153(Point(317.924, 763.557), 15);
+ connRef153->setSourceEndpoint(srcPt153);
+ ConnEnd dstPt153(Point(487.924, 903.057), 15);
+ connRef153->setDestEndpoint(dstPt153);
+ connRef153->setRoutingType((ConnType)2);
+
+ ConnRef *connRef154 = new ConnRef(router, 154);
+ ConnEnd srcPt154(Point(317.924, 763.557), 15);
+ connRef154->setSourceEndpoint(srcPt154);
+ ConnEnd dstPt154(Point(727.924, 574.057), 15);
+ connRef154->setDestEndpoint(dstPt154);
+ connRef154->setRoutingType((ConnType)2);
+
+ ConnRef *connRef155 = new ConnRef(router, 155);
+ ConnEnd srcPt155(Point(557.924, 903.057), 15);
+ connRef155->setSourceEndpoint(srcPt155);
+ ConnEnd dstPt155(Point(607.924, 903.057), 15);
+ connRef155->setDestEndpoint(dstPt155);
+ connRef155->setRoutingType((ConnType)2);
+
+ ConnRef *connRef156 = new ConnRef(router, 156);
+ ConnEnd srcPt156(Point(197.924, 763.557), 15);
+ connRef156->setSourceEndpoint(srcPt156);
+ ConnEnd dstPt156(Point(247.924, 763.557), 15);
+ connRef156->setDestEndpoint(dstPt156);
+ connRef156->setRoutingType((ConnType)2);
+
+ ConnRef *connRef157 = new ConnRef(router, 157);
+ ConnEnd srcPt157(Point(147.924, 161.557), 15);
+ connRef157->setSourceEndpoint(srcPt157);
+ ConnEnd dstPt157(Point(197.924, 161.557), 15);
+ connRef157->setDestEndpoint(dstPt157);
+ connRef157->setRoutingType((ConnType)2);
+
+ ConnRef *connRef158 = new ConnRef(router, 158);
+ ConnEnd srcPt158(Point(197.924, 161.557), 15);
+ connRef158->setSourceEndpoint(srcPt158);
+ ConnEnd dstPt158(Point(247.924, 161.557), 15);
+ connRef158->setDestEndpoint(dstPt158);
+ connRef158->setRoutingType((ConnType)2);
+
+ ConnRef *connRef159 = new ConnRef(router, 159);
+ ConnEnd srcPt159(Point(197.924, 161.557), 15);
+ connRef159->setSourceEndpoint(srcPt159);
+ ConnEnd dstPt159(Point(197.924, 203.557), 15);
+ connRef159->setDestEndpoint(dstPt159);
+ connRef159->setRoutingType((ConnType)2);
+
+ ConnRef *connRef160 = new ConnRef(router, 160);
+ ConnEnd srcPt160(Point(317.924, 161.557), 15);
+ connRef160->setSourceEndpoint(srcPt160);
+ ConnEnd dstPt160(Point(727.924, -60.6578), 15);
+ connRef160->setDestEndpoint(dstPt160);
+ connRef160->setRoutingType((ConnType)2);
+
+ ConnRef *connRef161 = new ConnRef(router, 161);
+ ConnEnd srcPt161(Point(317.924, 161.557), 15);
+ connRef161->setSourceEndpoint(srcPt161);
+ ConnEnd dstPt161(Point(367.924, 161.557), 15);
+ connRef161->setDestEndpoint(dstPt161);
+ connRef161->setRoutingType((ConnType)2);
+
+ ConnRef *connRef162 = new ConnRef(router, 162);
+ ConnEnd srcPt162(Point(317.924, 161.557), 15);
+ connRef162->setSourceEndpoint(srcPt162);
+ ConnEnd dstPt162(Point(367.924, 27.3422), 15);
+ connRef162->setDestEndpoint(dstPt162);
+ connRef162->setRoutingType((ConnType)2);
+
+ ConnRef *connRef163 = new ConnRef(router, 163);
+ ConnEnd srcPt163(Point(317.924, 161.557), 15);
+ connRef163->setSourceEndpoint(srcPt163);
+ ConnEnd dstPt163(Point(487.924, 435.557), 15);
+ connRef163->setDestEndpoint(dstPt163);
+ connRef163->setRoutingType((ConnType)2);
+
+ ConnRef *connRef164 = new ConnRef(router, 164);
+ ConnEnd srcPt164(Point(437.924, 763.557), 15);
+ connRef164->setSourceEndpoint(srcPt164);
+ ConnEnd dstPt164(Point(487.924, 763.557), 15);
+ connRef164->setDestEndpoint(dstPt164);
+ connRef164->setRoutingType((ConnType)2);
+
+ ConnRef *connRef165 = new ConnRef(router, 165);
+ ConnEnd srcPt165(Point(437.924, 763.557), 15);
+ connRef165->setSourceEndpoint(srcPt165);
+ ConnEnd dstPt165(Point(727.924, 860.057), 15);
+ connRef165->setDestEndpoint(dstPt165);
+ connRef165->setRoutingType((ConnType)2);
+
+ ConnRef *connRef166 = new ConnRef(router, 166);
+ ConnEnd srcPt166(Point(557.924, 527.557), 15);
+ connRef166->setSourceEndpoint(srcPt166);
+ ConnEnd dstPt166(Point(607.924, 527.557), 15);
+ connRef166->setDestEndpoint(dstPt166);
+ connRef166->setRoutingType((ConnType)2);
+
+ ConnRef *connRef167 = new ConnRef(router, 167);
+ ConnEnd srcPt167(Point(797.924, 343.557), 15);
+ connRef167->setSourceEndpoint(srcPt167);
+ ConnEnd dstPt167(Point(847.924, 343.557), 15);
+ connRef167->setDestEndpoint(dstPt167);
+ connRef167->setRoutingType((ConnType)2);
+
+ ConnRef *connRef168 = new ConnRef(router, 168);
+ ConnEnd srcPt168(Point(797.924, 343.557), 15);
+ connRef168->setSourceEndpoint(srcPt168);
+ ConnEnd dstPt168(Point(847.924, 435.557), 15);
+ connRef168->setDestEndpoint(dstPt168);
+ connRef168->setRoutingType((ConnType)2);
+
+ ConnRef *connRef169 = new ConnRef(router, 169);
+ ConnEnd srcPt169(Point(1018.92, 435.557), 15);
+ connRef169->setSourceEndpoint(srcPt169);
+ ConnEnd dstPt169(Point(1068.92, 388.557), 15);
+ connRef169->setDestEndpoint(dstPt169);
+ connRef169->setRoutingType((ConnType)2);
+
+ ConnRef *connRef170 = new ConnRef(router, 170);
+ ConnEnd srcPt170(Point(1018.92, 161.557), 15);
+ connRef170->setSourceEndpoint(srcPt170);
+ ConnEnd dstPt170(Point(1068.92, 152.342), 15);
+ connRef170->setDestEndpoint(dstPt170);
+ connRef170->setRoutingType((ConnType)2);
+
+ ConnRef *connRef171 = new ConnRef(router, 171);
+ ConnEnd srcPt171(Point(1018.92, 161.557), 15);
+ connRef171->setSourceEndpoint(srcPt171);
+ ConnEnd dstPt171(Point(1068.92, 60.3422), 15);
+ connRef171->setDestEndpoint(dstPt171);
+ connRef171->setRoutingType((ConnType)2);
+
+ ConnRef *connRef172 = new ConnRef(router, 172);
+ ConnEnd srcPt172(Point(267.924, 315.557), 15);
+ connRef172->setSourceEndpoint(srcPt172);
+ ConnEnd dstPt172(Point(437.924, 161.557), 15);
+ connRef172->setDestEndpoint(dstPt172);
+ connRef172->setRoutingType((ConnType)2);
+
+ ConnRef *connRef173 = new ConnRef(router, 173);
+ ConnEnd srcPt173(Point(437.924, 161.557), 15);
+ connRef173->setSourceEndpoint(srcPt173);
+ ConnEnd dstPt173(Point(487.924, 45.8422), 15);
+ connRef173->setDestEndpoint(dstPt173);
+ connRef173->setRoutingType((ConnType)2);
+
+ ConnRef *connRef174 = new ConnRef(router, 174);
+ ConnEnd srcPt174(Point(437.924, 161.557), 15);
+ connRef174->setSourceEndpoint(srcPt174);
+ ConnEnd dstPt174(Point(727.924, 161.557), 15);
+ connRef174->setDestEndpoint(dstPt174);
+ connRef174->setRoutingType((ConnType)2);
+
+ ConnRef *connRef175 = new ConnRef(router, 175);
+ ConnEnd srcPt175(Point(77.9242, 161.557), 15);
+ connRef175->setSourceEndpoint(srcPt175);
+ ConnEnd dstPt175(Point(127.924, 161.557), 15);
+ connRef175->setDestEndpoint(dstPt175);
+ connRef175->setRoutingType((ConnType)2);
+
+ ConnRef *connRef176 = new ConnRef(router, 176);
+ ConnEnd srcPt176(Point(77.9242, 161.557), 15);
+ connRef176->setSourceEndpoint(srcPt176);
+ ConnEnd dstPt176(Point(77.9242, 357.557), 15);
+ connRef176->setDestEndpoint(dstPt176);
+ connRef176->setRoutingType((ConnType)2);
+
+ ConnRef *connRef177 = new ConnRef(router, 177);
+ ConnEnd srcPt177(Point(557.924, 763.557), 15);
+ connRef177->setSourceEndpoint(srcPt177);
+ ConnEnd dstPt177(Point(607.924, 763.557), 15);
+ connRef177->setDestEndpoint(dstPt177);
+ connRef177->setRoutingType((ConnType)2);
+
+ ConnRef *connRef178 = new ConnRef(router, 178);
+ ConnEnd srcPt178(Point(77.9242, 527.557), 15);
+ connRef178->setSourceEndpoint(srcPt178);
+ ConnEnd dstPt178(Point(127.924, 527.557), 15);
+ connRef178->setDestEndpoint(dstPt178);
+ connRef178->setRoutingType((ConnType)2);
+
+ ConnRef *connRef179 = new ConnRef(router, 179);
+ ConnEnd srcPt179(Point(557.924, 54.8422), 15);
+ connRef179->setSourceEndpoint(srcPt179);
+ ConnEnd dstPt179(Point(607.924, 45.8422), 15);
+ connRef179->setDestEndpoint(dstPt179);
+ connRef179->setRoutingType((ConnType)2);
+
+ ConnRef *connRef180 = new ConnRef(router, 180);
+ ConnEnd srcPt180(Point(557.924, 435.557), 15);
+ connRef180->setSourceEndpoint(srcPt180);
+ ConnEnd dstPt180(Point(607.924, 435.557), 15);
+ connRef180->setDestEndpoint(dstPt180);
+ connRef180->setRoutingType((ConnType)2);
+
+ ConnRef *connRef181 = new ConnRef(router, 181);
+ ConnEnd srcPt181(Point(77.9242, 763.557), 15);
+ connRef181->setSourceEndpoint(srcPt181);
+ ConnEnd dstPt181(Point(77.9242, 671.557), 15);
+ connRef181->setDestEndpoint(dstPt181);
+ connRef181->setRoutingType((ConnType)2);
+
+ ConnRef *connRef182 = new ConnRef(router, 182);
+ ConnEnd srcPt182(Point(77.9242, 763.557), 15);
+ connRef182->setSourceEndpoint(srcPt182);
+ ConnEnd dstPt182(Point(127.924, 763.557), 15);
+ connRef182->setDestEndpoint(dstPt182);
+ connRef182->setRoutingType((ConnType)2);
+
+ ConnRef *connRef183 = new ConnRef(router, 183);
+ ConnEnd srcPt183(Point(197.924, 315.557), 15);
+ connRef183->setSourceEndpoint(srcPt183);
+ ConnEnd dstPt183(Point(247.924, 315.557), 15);
+ connRef183->setDestEndpoint(dstPt183);
+ connRef183->setRoutingType((ConnType)2);
+
+ ConnRef *connRef184 = new ConnRef(router, 184);
+ ConnEnd srcPt184(Point(677.924, 343.557), 15);
+ connRef184->setSourceEndpoint(srcPt184);
+ ConnEnd dstPt184(Point(727.924, 343.557), 15);
+ connRef184->setDestEndpoint(dstPt184);
+ connRef184->setRoutingType((ConnType)2);
+
+ ConnRef *connRef185 = new ConnRef(router, 185);
+ ConnEnd srcPt185(Point(797.924, 161.557), 15);
+ connRef185->setSourceEndpoint(srcPt185);
+ ConnEnd dstPt185(Point(847.924, 161.557), 15);
+ connRef185->setDestEndpoint(dstPt185);
+ connRef185->setRoutingType((ConnType)2);
+
+ ConnRef *connRef186 = new ConnRef(router, 186);
+ ConnEnd srcPt186(Point(77.9242, 34.8422), 15);
+ connRef186->setSourceEndpoint(srcPt186);
+ ConnEnd dstPt186(Point(127.924, 34.8422), 15);
+ connRef186->setDestEndpoint(dstPt186);
+ connRef186->setRoutingType((ConnType)2);
+
+ ConnRef *connRef187 = new ConnRef(router, 187);
+ ConnEnd srcPt187(Point(437.924, 527.557), 15);
+ connRef187->setSourceEndpoint(srcPt187);
+ ConnEnd dstPt187(Point(487.924, 527.557), 15);
+ connRef187->setDestEndpoint(dstPt187);
+ connRef187->setRoutingType((ConnType)2);
+
+ ConnRef *connRef188 = new ConnRef(router, 188);
+ ConnEnd srcPt188(Point(77.9242, 619.557), 15);
+ connRef188->setSourceEndpoint(srcPt188);
+ ConnEnd dstPt188(Point(127.924, 619.557), 15);
+ connRef188->setDestEndpoint(dstPt188);
+ connRef188->setRoutingType((ConnType)2);
+
+ ConnRef *connRef189 = new ConnRef(router, 189);
+ ConnEnd srcPt189(Point(747.924, -60.6578), 15);
+ connRef189->setSourceEndpoint(srcPt189);
+ ConnEnd dstPt189(Point(797.924, -60.6578), 15);
+ connRef189->setDestEndpoint(dstPt189);
+ connRef189->setRoutingType((ConnType)2);
+
+ ConnRef *connRef190 = new ConnRef(router, 190);
+ ConnEnd srcPt190(Point(147.924, 34.8422), 15);
+ connRef190->setSourceEndpoint(srcPt190);
+ ConnEnd dstPt190(Point(197.924, 161.557), 15);
+ connRef190->setDestEndpoint(dstPt190);
+ connRef190->setRoutingType((ConnType)2);
+
+ ConnRef *connRef191 = new ConnRef(router, 191);
+ ConnEnd srcPt191(Point(267.924, 161.557), 15);
+ connRef191->setSourceEndpoint(srcPt191);
+ ConnEnd dstPt191(Point(317.924, 161.557), 15);
+ connRef191->setDestEndpoint(dstPt191);
+ connRef191->setRoutingType((ConnType)2);
+
+ ConnRef *connRef192 = new ConnRef(router, 192);
+ ConnEnd srcPt192(Point(197.924, 223.557), 15);
+ connRef192->setSourceEndpoint(srcPt192);
+ ConnEnd dstPt192(Point(197.924, 315.557), 15);
+ connRef192->setDestEndpoint(dstPt192);
+ connRef192->setRoutingType((ConnType)2);
+
+ ConnRef *connRef193 = new ConnRef(router, 193);
+ ConnEnd srcPt193(Point(77.9242, 377.557), 15);
+ connRef193->setSourceEndpoint(srcPt193);
+ ConnEnd dstPt193(Point(77.9242, 527.557), 15);
+ connRef193->setDestEndpoint(dstPt193);
+ connRef193->setRoutingType((ConnType)2);
+
+ ConnRef *connRef194 = new ConnRef(router, 194);
+ ConnEnd srcPt194(Point(147.924, 527.557), 15);
+ connRef194->setSourceEndpoint(srcPt194);
+ ConnEnd dstPt194(Point(197.924, 527.557), 15);
+ connRef194->setDestEndpoint(dstPt194);
+ connRef194->setRoutingType((ConnType)2);
+
+ ConnRef *connRef195 = new ConnRef(router, 195);
+ ConnEnd srcPt195(Point(147.924, 619.557), 15);
+ connRef195->setSourceEndpoint(srcPt195);
+ ConnEnd dstPt195(Point(197.924, 763.557), 15);
+ connRef195->setDestEndpoint(dstPt195);
+ connRef195->setRoutingType((ConnType)2);
+
+ ConnRef *connRef196 = new ConnRef(router, 196);
+ ConnEnd srcPt196(Point(77.9242, 651.557), 15);
+ connRef196->setSourceEndpoint(srcPt196);
+ ConnEnd dstPt196(Point(77.9242, 619.557), 15);
+ connRef196->setDestEndpoint(dstPt196);
+ connRef196->setRoutingType((ConnType)2);
+
+ ConnRef *connRef197 = new ConnRef(router, 197);
+ ConnEnd srcPt197(Point(147.924, 763.557), 15);
+ connRef197->setSourceEndpoint(srcPt197);
+ ConnEnd dstPt197(Point(197.924, 763.557), 15);
+ connRef197->setDestEndpoint(dstPt197);
+ connRef197->setRoutingType((ConnType)2);
+
+ ConnRef *connRef198 = new ConnRef(router, 198);
+ ConnEnd srcPt198(Point(267.924, 763.557), 15);
+ connRef198->setSourceEndpoint(srcPt198);
+ ConnEnd dstPt198(Point(317.924, 763.557), 15);
+ connRef198->setDestEndpoint(dstPt198);
+ connRef198->setRoutingType((ConnType)2);
+
+ ConnRef *connRef199 = new ConnRef(router, 199);
+ ConnEnd srcPt199(Point(387.924, 627.557), 15);
+ connRef199->setSourceEndpoint(srcPt199);
+ ConnEnd dstPt199(Point(437.924, 627.557), 15);
+ connRef199->setDestEndpoint(dstPt199);
+ connRef199->setRoutingType((ConnType)2);
+
+ ConnRef *connRef200 = new ConnRef(router, 200);
+ ConnEnd srcPt200(Point(387.924, 763.557), 15);
+ connRef200->setSourceEndpoint(srcPt200);
+ ConnEnd dstPt200(Point(437.924, 763.557), 15);
+ connRef200->setDestEndpoint(dstPt200);
+ connRef200->setRoutingType((ConnType)2);
+
+ ConnRef *connRef201 = new ConnRef(router, 201);
+ ConnEnd srcPt201(Point(507.924, 763.557), 15);
+ connRef201->setSourceEndpoint(srcPt201);
+ ConnEnd dstPt201(Point(557.924, 763.557), 15);
+ connRef201->setDestEndpoint(dstPt201);
+ connRef201->setRoutingType((ConnType)2);
+
+ ConnRef *connRef202 = new ConnRef(router, 202);
+ ConnEnd srcPt202(Point(627.924, 763.557), 15);
+ connRef202->setSourceEndpoint(srcPt202);
+ ConnEnd dstPt202(Point(677.924, 763.557), 15);
+ connRef202->setDestEndpoint(dstPt202);
+ connRef202->setRoutingType((ConnType)2);
+
+ ConnRef *connRef203 = new ConnRef(router, 203);
+ ConnEnd srcPt203(Point(507.924, 903.057), 15);
+ connRef203->setSourceEndpoint(srcPt203);
+ ConnEnd dstPt203(Point(557.924, 903.057), 15);
+ connRef203->setDestEndpoint(dstPt203);
+ connRef203->setRoutingType((ConnType)2);
+
+ ConnRef *connRef204 = new ConnRef(router, 204);
+ ConnEnd srcPt204(Point(627.924, 903.057), 15);
+ connRef204->setSourceEndpoint(srcPt204);
+ ConnEnd dstPt204(Point(677.924, 903.057), 15);
+ connRef204->setDestEndpoint(dstPt204);
+ connRef204->setRoutingType((ConnType)2);
+
+ ConnRef *connRef205 = new ConnRef(router, 205);
+ ConnEnd srcPt205(Point(387.924, 161.557), 15);
+ connRef205->setSourceEndpoint(srcPt205);
+ ConnEnd dstPt205(Point(437.924, 161.557), 15);
+ connRef205->setDestEndpoint(dstPt205);
+ connRef205->setRoutingType((ConnType)2);
+
+ ConnRef *connRef206 = new ConnRef(router, 206);
+ ConnEnd srcPt206(Point(387.924, 27.3422), 15);
+ connRef206->setSourceEndpoint(srcPt206);
+ ConnEnd dstPt206(Point(437.924, 27.3422), 15);
+ connRef206->setDestEndpoint(dstPt206);
+ connRef206->setRoutingType((ConnType)2);
+
+ ConnRef *connRef207 = new ConnRef(router, 207);
+ ConnEnd srcPt207(Point(507.924, 45.8422), 15);
+ connRef207->setSourceEndpoint(srcPt207);
+ ConnEnd dstPt207(Point(557.924, 54.8422), 15);
+ connRef207->setDestEndpoint(dstPt207);
+ connRef207->setRoutingType((ConnType)2);
+
+ ConnRef *connRef208 = new ConnRef(router, 208);
+ ConnEnd srcPt208(Point(627.924, 45.8422), 15);
+ connRef208->setSourceEndpoint(srcPt208);
+ ConnEnd dstPt208(Point(677.924, 54.8422), 15);
+ connRef208->setDestEndpoint(dstPt208);
+ connRef208->setRoutingType((ConnType)2);
+
+ ConnRef *connRef209 = new ConnRef(router, 209);
+ ConnEnd srcPt209(Point(747.924, 574.057), 15);
+ connRef209->setSourceEndpoint(srcPt209);
+ ConnEnd dstPt209(Point(797.924, 574.057), 15);
+ connRef209->setDestEndpoint(dstPt209);
+ connRef209->setRoutingType((ConnType)2);
+
+ ConnRef *connRef210 = new ConnRef(router, 210);
+ ConnEnd srcPt210(Point(507.924, 527.557), 15);
+ connRef210->setSourceEndpoint(srcPt210);
+ ConnEnd dstPt210(Point(557.924, 527.557), 15);
+ connRef210->setDestEndpoint(dstPt210);
+ connRef210->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/lineSegWrapperCrash5");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash6.cpp b/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash6.cpp
new file mode 100644
index 0000000..fb186b7
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash6.cpp
@@ -0,0 +1,1884 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 0);
+
+ Polygon poly121(4);
+ poly121.ps[0] = Point(645.924, 693.557);
+ poly121.ps[1] = Point(645.924, 733.557);
+ poly121.ps[2] = Point(589.924, 733.557);
+ poly121.ps[3] = Point(589.924, 693.557);
+ new ShapeRef(router, poly121, 121);
+
+ Polygon poly30(4);
+ poly30.ps[0] = Point(1278.92, 415.557);
+ poly30.ps[1] = Point(1278.92, 455.557);
+ poly30.ps[2] = Point(1238.92, 455.557);
+ poly30.ps[3] = Point(1238.92, 415.557);
+ new ShapeRef(router, poly30, 30);
+
+ Polygon poly29(4);
+ poly29.ps[0] = Point(1038.92, 415.557);
+ poly29.ps[1] = Point(1038.92, 455.557);
+ poly29.ps[2] = Point(998.924, 455.557);
+ poly29.ps[3] = Point(998.924, 415.557);
+ new ShapeRef(router, poly29, 29);
+
+ Polygon poly32(4);
+ poly32.ps[0] = Point(1038.92, 141.557);
+ poly32.ps[1] = Point(1038.92, 181.557);
+ poly32.ps[2] = Point(998.924, 181.557);
+ poly32.ps[3] = Point(998.924, 141.557);
+ new ShapeRef(router, poly32, 32);
+
+ Polygon poly34(4);
+ poly34.ps[0] = Point(1278.92, 323.557);
+ poly34.ps[1] = Point(1278.92, 363.557);
+ poly34.ps[2] = Point(1238.92, 363.557);
+ poly34.ps[3] = Point(1238.92, 323.557);
+ new ShapeRef(router, poly34, 34);
+
+ Polygon poly134(4);
+ poly134.ps[0] = Point(885.924, 365.557);
+ poly134.ps[1] = Point(885.924, 405.557);
+ poly134.ps[2] = Point(829.924, 405.557);
+ poly134.ps[3] = Point(829.924, 365.557);
+ new ShapeRef(router, poly134, 134);
+
+ Polygon poly51(4);
+ poly51.ps[0] = Point(1038.92, 323.557);
+ poly51.ps[1] = Point(1038.92, 363.557);
+ poly51.ps[2] = Point(998.924, 363.557);
+ poly51.ps[3] = Point(998.924, 323.557);
+ new ShapeRef(router, poly51, 51);
+
+ Polygon poly45(4);
+ poly45.ps[0] = Point(577.924, 34.8422);
+ poly45.ps[1] = Point(577.924, 74.8422);
+ poly45.ps[2] = Point(537.924, 74.8422);
+ poly45.ps[3] = Point(537.924, 34.8422);
+ new ShapeRef(router, poly45, 45);
+
+ Polygon poly141(4);
+ poly141.ps[0] = Point(1226.92, 82.3422);
+ poly141.ps[1] = Point(1226.92, 122.342);
+ poly141.ps[2] = Point(1170.92, 122.342);
+ poly141.ps[3] = Point(1170.92, 82.3422);
+ new ShapeRef(router, poly141, 141);
+
+ Polygon poly33(4);
+ poly33.ps[0] = Point(937.924, 415.557);
+ poly33.ps[1] = Point(937.924, 455.557);
+ poly33.ps[2] = Point(897.924, 455.557);
+ poly33.ps[3] = Point(897.924, 415.557);
+ new ShapeRef(router, poly33, 33);
+
+ Polygon poly46(4);
+ poly46.ps[0] = Point(577.924, 415.557);
+ poly46.ps[1] = Point(577.924, 455.557);
+ poly46.ps[2] = Point(537.924, 455.557);
+ poly46.ps[3] = Point(537.924, 415.557);
+ new ShapeRef(router, poly46, 46);
+
+ Polygon poly31(4);
+ poly31.ps[0] = Point(1278.92, 141.557);
+ poly31.ps[1] = Point(1278.92, 181.557);
+ poly31.ps[2] = Point(1238.92, 181.557);
+ poly31.ps[3] = Point(1238.92, 141.557);
+ new ShapeRef(router, poly31, 31);
+
+ Polygon poly100(4);
+ poly100.ps[0] = Point(1088.92, 50.3422);
+ poly100.ps[1] = Point(1088.92, 70.3422);
+ poly100.ps[2] = Point(1068.92, 70.3422);
+ poly100.ps[3] = Point(1068.92, 50.3422);
+ new ShapeRef(router, poly100, 100);
+
+ Polygon poly27(4);
+ poly27.ps[0] = Point(577.924, 507.557);
+ poly27.ps[1] = Point(577.924, 547.557);
+ poly27.ps[2] = Point(537.924, 547.557);
+ poly27.ps[3] = Point(537.924, 507.557);
+ new ShapeRef(router, poly27, 27);
+
+ Polygon poly21(4);
+ poly21.ps[0] = Point(937.924, 141.557);
+ poly21.ps[1] = Point(937.924, 181.557);
+ poly21.ps[2] = Point(897.924, 181.557);
+ poly21.ps[3] = Point(897.924, 141.557);
+ new ShapeRef(router, poly21, 21);
+
+ Polygon poly82(4);
+ poly82.ps[0] = Point(507.924, 893.057);
+ poly82.ps[1] = Point(507.924, 913.057);
+ poly82.ps[2] = Point(487.924, 913.057);
+ poly82.ps[3] = Point(487.924, 893.057);
+ new ShapeRef(router, poly82, 82);
+
+ Polygon poly123(4);
+ poly123.ps[0] = Point(645.924, 833.057);
+ poly123.ps[1] = Point(645.924, 873.057);
+ poly123.ps[2] = Point(589.924, 873.057);
+ poly123.ps[3] = Point(589.924, 833.057);
+ new ShapeRef(router, poly123, 123);
+
+ Polygon poly86(4);
+ poly86.ps[0] = Point(507.924, 35.8422);
+ poly86.ps[1] = Point(507.924, 55.8422);
+ poly86.ps[2] = Point(487.924, 55.8422);
+ poly86.ps[3] = Point(487.924, 35.8422);
+ new ShapeRef(router, poly86, 86);
+
+ Polygon poly23(4);
+ poly23.ps[0] = Point(337.924, 141.557);
+ poly23.ps[1] = Point(337.924, 181.557);
+ poly23.ps[2] = Point(297.924, 181.557);
+ poly23.ps[3] = Point(297.924, 141.557);
+ new ShapeRef(router, poly23, 23);
+
+ Polygon poly28(4);
+ poly28.ps[0] = Point(817.924, 323.557);
+ poly28.ps[1] = Point(817.924, 363.557);
+ poly28.ps[2] = Point(777.924, 363.557);
+ poly28.ps[3] = Point(777.924, 323.557);
+ new ShapeRef(router, poly28, 28);
+
+ Polygon poly20(4);
+ poly20.ps[0] = Point(337.924, 507.557);
+ poly20.ps[1] = Point(337.924, 547.557);
+ poly20.ps[2] = Point(297.924, 547.557);
+ poly20.ps[3] = Point(297.924, 507.557);
+ new ShapeRef(router, poly20, 20);
+
+ Polygon poly19(4);
+ poly19.ps[0] = Point(217.924, 141.557);
+ poly19.ps[1] = Point(217.924, 181.557);
+ poly19.ps[2] = Point(177.924, 181.557);
+ poly19.ps[3] = Point(177.924, 141.557);
+ new ShapeRef(router, poly19, 19);
+
+ Polygon poly59(4);
+ poly59.ps[0] = Point(937.924, 323.557);
+ poly59.ps[1] = Point(937.924, 363.557);
+ poly59.ps[2] = Point(897.924, 363.557);
+ poly59.ps[3] = Point(897.924, 323.557);
+ new ShapeRef(router, poly59, 59);
+
+ Polygon poly60(4);
+ poly60.ps[0] = Point(937.924, 1.84222);
+ poly60.ps[1] = Point(937.924, 41.8422);
+ poly60.ps[2] = Point(897.924, 41.8422);
+ poly60.ps[3] = Point(897.924, 1.84222);
+ new ShapeRef(router, poly60, 60);
+
+ Polygon poly18(4);
+ poly18.ps[0] = Point(217.924, 743.557);
+ poly18.ps[1] = Point(217.924, 783.557);
+ poly18.ps[2] = Point(177.924, 783.557);
+ poly18.ps[3] = Point(177.924, 743.557);
+ new ShapeRef(router, poly18, 18);
+
+ Polygon poly108(4);
+ poly108.ps[0] = Point(165.924, 91.5565);
+ poly108.ps[1] = Point(165.924, 131.557);
+ poly108.ps[2] = Point(109.924, 131.557);
+ poly108.ps[3] = Point(109.924, 91.5565);
+ new ShapeRef(router, poly108, 108);
+
+ Polygon poly38(4);
+ poly38.ps[0] = Point(217.924, 507.557);
+ poly38.ps[1] = Point(217.924, 547.557);
+ poly38.ps[2] = Point(177.924, 547.557);
+ poly38.ps[3] = Point(177.924, 507.557);
+ new ShapeRef(router, poly38, 38);
+
+ Polygon poly17(4);
+ poly17.ps[0] = Point(577.924, 883.057);
+ poly17.ps[1] = Point(577.924, 923.057);
+ poly17.ps[2] = Point(537.924, 923.057);
+ poly17.ps[3] = Point(537.924, 883.057);
+ new ShapeRef(router, poly17, 17);
+
+ Polygon poly129(4);
+ poly129.ps[0] = Point(525.924, 457.557);
+ poly129.ps[1] = Point(525.924, 497.557);
+ poly129.ps[2] = Point(469.924, 497.557);
+ poly129.ps[3] = Point(469.924, 457.557);
+ new ShapeRef(router, poly129, 129);
+
+ Polygon poly24(4);
+ poly24.ps[0] = Point(457.924, 743.557);
+ poly24.ps[1] = Point(457.924, 783.557);
+ poly24.ps[2] = Point(417.924, 783.557);
+ poly24.ps[3] = Point(417.924, 743.557);
+ new ShapeRef(router, poly24, 24);
+
+ Polygon poly94(4);
+ poly94.ps[0] = Point(867.924, 425.557);
+ poly94.ps[1] = Point(867.924, 445.557);
+ poly94.ps[2] = Point(847.924, 445.557);
+ poly94.ps[3] = Point(847.924, 425.557);
+ new ShapeRef(router, poly94, 94);
+
+ Polygon poly16(4);
+ poly16.ps[0] = Point(337.924, 743.557);
+ poly16.ps[1] = Point(337.924, 783.557);
+ poly16.ps[2] = Point(297.924, 783.557);
+ poly16.ps[3] = Point(297.924, 743.557);
+ new ShapeRef(router, poly16, 16);
+
+ Polygon poly15(4);
+ poly15.ps[0] = Point(1158.92, 415.557);
+ poly15.ps[1] = Point(1158.92, 455.557);
+ poly15.ps[2] = Point(1118.92, 455.557);
+ poly15.ps[3] = Point(1118.92, 415.557);
+ new ShapeRef(router, poly15, 15);
+
+ Polygon poly81(4);
+ poly81.ps[0] = Point(627.924, 753.557);
+ poly81.ps[1] = Point(627.924, 773.557);
+ poly81.ps[2] = Point(607.924, 773.557);
+ poly81.ps[3] = Point(607.924, 753.557);
+ new ShapeRef(router, poly81, 81);
+
+ Polygon poly44(4);
+ poly44.ps[0] = Point(97.9242, 507.557);
+ poly44.ps[1] = Point(97.9242, 547.557);
+ poly44.ps[2] = Point(57.9242, 547.557);
+ poly44.ps[3] = Point(57.9242, 507.557);
+ new ShapeRef(router, poly44, 44);
+
+ Polygon poly56(4);
+ poly56.ps[0] = Point(457.924, -44.6578);
+ poly56.ps[1] = Point(457.924, -4.65778);
+ poly56.ps[2] = Point(417.924, -4.65778);
+ poly56.ps[3] = Point(417.924, -44.6578);
+ new ShapeRef(router, poly56, 56);
+
+ Polygon poly90(4);
+ poly90.ps[0] = Point(507.924, 425.557);
+ poly90.ps[1] = Point(507.924, 445.557);
+ poly90.ps[2] = Point(487.924, 445.557);
+ poly90.ps[3] = Point(487.924, 425.557);
+ new ShapeRef(router, poly90, 90);
+
+ Polygon poly113(4);
+ poly113.ps[0] = Point(165.924, 457.557);
+ poly113.ps[1] = Point(165.924, 497.557);
+ poly113.ps[2] = Point(109.924, 497.557);
+ poly113.ps[3] = Point(109.924, 457.557);
+ new ShapeRef(router, poly113, 113);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(1371.92, 29.8422);
+ poly4.ps[1] = Point(1371.92, 69.8422);
+ poly4.ps[2] = Point(1331.92, 69.8422);
+ poly4.ps[3] = Point(1331.92, 29.8422);
+ new ShapeRef(router, poly4, 4);
+
+ Polygon poly83(4);
+ poly83.ps[0] = Point(627.924, 893.057);
+ poly83.ps[1] = Point(627.924, 913.057);
+ poly83.ps[2] = Point(607.924, 913.057);
+ poly83.ps[3] = Point(607.924, 893.057);
+ new ShapeRef(router, poly83, 83);
+
+ Polygon poly130(4);
+ poly130.ps[0] = Point(525.924, 365.557);
+ poly130.ps[1] = Point(525.924, 405.557);
+ poly130.ps[2] = Point(469.924, 405.557);
+ poly130.ps[3] = Point(469.924, 365.557);
+ new ShapeRef(router, poly130, 130);
+
+ Polygon poly133(4);
+ poly133.ps[0] = Point(885.924, 273.557);
+ poly133.ps[1] = Point(885.924, 313.557);
+ poly133.ps[2] = Point(829.924, 313.557);
+ poly133.ps[3] = Point(829.924, 273.557);
+ new ShapeRef(router, poly133, 133);
+
+ Polygon poly48(4);
+ poly48.ps[0] = Point(97.9242, 743.557);
+ poly48.ps[1] = Point(97.9242, 783.557);
+ poly48.ps[2] = Point(57.9242, 783.557);
+ poly48.ps[3] = Point(57.9242, 743.557);
+ new ShapeRef(router, poly48, 48);
+
+ Polygon poly115(4);
+ poly115.ps[0] = Point(167.924, 641.557);
+ poly115.ps[1] = Point(167.924, 681.557);
+ poly115.ps[2] = Point(111.924, 681.557);
+ poly115.ps[3] = Point(111.924, 641.557);
+ new ShapeRef(router, poly115, 115);
+
+ Polygon poly73(4);
+ poly73.ps[0] = Point(147.924, 517.557);
+ poly73.ps[1] = Point(147.924, 537.557);
+ poly73.ps[2] = Point(127.924, 537.557);
+ poly73.ps[3] = Point(127.924, 517.557);
+ new ShapeRef(router, poly73, 73);
+
+ Polygon poly119(4);
+ poly119.ps[0] = Point(405.924, 693.557);
+ poly119.ps[1] = Point(405.924, 733.557);
+ poly119.ps[2] = Point(349.924, 733.557);
+ poly119.ps[3] = Point(349.924, 693.557);
+ new ShapeRef(router, poly119, 119);
+
+ Polygon poly70(4);
+ poly70.ps[0] = Point(207.924, 203.557);
+ poly70.ps[1] = Point(207.924, 223.557);
+ poly70.ps[2] = Point(187.924, 223.557);
+ poly70.ps[3] = Point(187.924, 203.557);
+ new ShapeRef(router, poly70, 70);
+
+ Polygon poly116(4);
+ poly116.ps[0] = Point(165.924, 693.557);
+ poly116.ps[1] = Point(165.924, 733.557);
+ poly116.ps[2] = Point(109.924, 733.557);
+ poly116.ps[3] = Point(109.924, 693.557);
+ new ShapeRef(router, poly116, 116);
+
+ Polygon poly64(4);
+ poly64.ps[0] = Point(817.924, 554.057);
+ poly64.ps[1] = Point(817.924, 594.057);
+ poly64.ps[2] = Point(777.924, 594.057);
+ poly64.ps[3] = Point(777.924, 554.057);
+ new ShapeRef(router, poly64, 64);
+
+ Polygon poly61(4);
+ poly61.ps[0] = Point(577.924, -44.6578);
+ poly61.ps[1] = Point(577.924, -4.65778);
+ poly61.ps[2] = Point(537.924, -4.65778);
+ poly61.ps[3] = Point(537.924, -44.6578);
+ new ShapeRef(router, poly61, 61);
+
+ Polygon poly93(4);
+ poly93.ps[0] = Point(867.924, 333.557);
+ poly93.ps[1] = Point(867.924, 353.557);
+ poly93.ps[2] = Point(847.924, 353.557);
+ poly93.ps[3] = Point(847.924, 333.557);
+ new ShapeRef(router, poly93, 93);
+
+ Polygon poly67(4);
+ poly67.ps[0] = Point(147.924, 24.8422);
+ poly67.ps[1] = Point(147.924, 44.8422);
+ poly67.ps[2] = Point(127.924, 44.8422);
+ poly67.ps[3] = Point(127.924, 24.8422);
+ new ShapeRef(router, poly67, 67);
+
+ Polygon poly74(4);
+ poly74.ps[0] = Point(147.924, 609.557);
+ poly74.ps[1] = Point(147.924, 629.557);
+ poly74.ps[2] = Point(127.924, 629.557);
+ poly74.ps[3] = Point(127.924, 609.557);
+ new ShapeRef(router, poly74, 74);
+
+ Polygon poly35(4);
+ poly35.ps[0] = Point(1158.92, 40.3422);
+ poly35.ps[1] = Point(1158.92, 80.3422);
+ poly35.ps[2] = Point(1118.92, 80.3422);
+ poly35.ps[3] = Point(1118.92, 40.3422);
+ new ShapeRef(router, poly35, 35);
+
+ Polygon poly136(4);
+ poly136.ps[0] = Point(765.924, 273.557);
+ poly136.ps[1] = Point(765.924, 313.557);
+ poly136.ps[2] = Point(709.924, 313.557);
+ poly136.ps[3] = Point(709.924, 273.557);
+ new ShapeRef(router, poly136, 136);
+
+ Polygon poly120(4);
+ poly120.ps[0] = Point(525.924, 693.557);
+ poly120.ps[1] = Point(525.924, 733.557);
+ poly120.ps[2] = Point(469.924, 733.557);
+ poly120.ps[3] = Point(469.924, 693.557);
+ new ShapeRef(router, poly120, 120);
+
+ Polygon poly71(4);
+ poly71.ps[0] = Point(267.924, 305.557);
+ poly71.ps[1] = Point(267.924, 325.557);
+ poly71.ps[2] = Point(247.924, 325.557);
+ poly71.ps[3] = Point(247.924, 305.557);
+ new ShapeRef(router, poly71, 71);
+
+ Polygon poly79(4);
+ poly79.ps[0] = Point(387.924, 753.557);
+ poly79.ps[1] = Point(387.924, 773.557);
+ poly79.ps[2] = Point(367.924, 773.557);
+ poly79.ps[3] = Point(367.924, 753.557);
+ new ShapeRef(router, poly79, 79);
+
+ Polygon poly72(4);
+ poly72.ps[0] = Point(87.9242, 357.557);
+ poly72.ps[1] = Point(87.9242, 377.557);
+ poly72.ps[2] = Point(67.9242, 377.557);
+ poly72.ps[3] = Point(67.9242, 357.557);
+ new ShapeRef(router, poly72, 72);
+
+ Polygon poly66(4);
+ poly66.ps[0] = Point(747.924, -70.6578);
+ poly66.ps[1] = Point(747.924, -50.6578);
+ poly66.ps[2] = Point(727.924, -50.6578);
+ poly66.ps[3] = Point(727.924, -70.6578);
+ new ShapeRef(router, poly66, 66);
+
+ Polygon poly75(4);
+ poly75.ps[0] = Point(87.9242, 651.557);
+ poly75.ps[1] = Point(87.9242, 671.557);
+ poly75.ps[2] = Point(67.9242, 671.557);
+ poly75.ps[3] = Point(67.9242, 651.557);
+ new ShapeRef(router, poly75, 75);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(1278.92, -22.1578);
+ poly3.ps[1] = Point(1278.92, 17.8422);
+ poly3.ps[2] = Point(1238.92, 17.8422);
+ poly3.ps[3] = Point(1238.92, -22.1578);
+ new ShapeRef(router, poly3, 3);
+
+ Polygon poly117(4);
+ poly117.ps[0] = Point(285.924, 693.557);
+ poly117.ps[1] = Point(285.924, 733.557);
+ poly117.ps[2] = Point(229.924, 733.557);
+ poly117.ps[3] = Point(229.924, 693.557);
+ new ShapeRef(router, poly117, 117);
+
+ Polygon poly97(4);
+ poly97.ps[0] = Point(1088.92, 378.557);
+ poly97.ps[1] = Point(1088.92, 398.557);
+ poly97.ps[2] = Point(1068.92, 398.557);
+ poly97.ps[3] = Point(1068.92, 378.557);
+ new ShapeRef(router, poly97, 97);
+
+ Polygon poly41(4);
+ poly41.ps[0] = Point(577.924, 743.557);
+ poly41.ps[1] = Point(577.924, 783.557);
+ poly41.ps[2] = Point(537.924, 783.557);
+ poly41.ps[3] = Point(537.924, 743.557);
+ new ShapeRef(router, poly41, 41);
+
+ Polygon poly101(4);
+ poly101.ps[0] = Point(1208.92, 142.342);
+ poly101.ps[1] = Point(1208.92, 162.342);
+ poly101.ps[2] = Point(1188.92, 162.342);
+ poly101.ps[3] = Point(1188.92, 142.342);
+ new ShapeRef(router, poly101, 101);
+
+ Polygon poly77(4);
+ poly77.ps[0] = Point(267.924, 753.557);
+ poly77.ps[1] = Point(267.924, 773.557);
+ poly77.ps[2] = Point(247.924, 773.557);
+ poly77.ps[3] = Point(247.924, 753.557);
+ new ShapeRef(router, poly77, 77);
+
+ Polygon poly53(4);
+ poly53.ps[0] = Point(577.924, 323.557);
+ poly53.ps[1] = Point(577.924, 363.557);
+ poly53.ps[2] = Point(537.924, 363.557);
+ poly53.ps[3] = Point(537.924, 323.557);
+ new ShapeRef(router, poly53, 53);
+
+ Polygon poly106(4);
+ poly106.ps[0] = Point(765.924, -130.658);
+ poly106.ps[1] = Point(765.924, -90.6578);
+ poly106.ps[2] = Point(709.924, -90.6578);
+ poly106.ps[3] = Point(709.924, -130.658);
+ new ShapeRef(router, poly106, 106);
+
+ Polygon poly80(4);
+ poly80.ps[0] = Point(507.924, 753.557);
+ poly80.ps[1] = Point(507.924, 773.557);
+ poly80.ps[2] = Point(487.924, 773.557);
+ poly80.ps[3] = Point(487.924, 753.557);
+ new ShapeRef(router, poly80, 80);
+
+ Polygon poly88(4);
+ poly88.ps[0] = Point(747.924, 564.057);
+ poly88.ps[1] = Point(747.924, 584.057);
+ poly88.ps[2] = Point(727.924, 584.057);
+ poly88.ps[3] = Point(727.924, 564.057);
+ new ShapeRef(router, poly88, 88);
+
+ Polygon poly36(4);
+ poly36.ps[0] = Point(697.924, 507.557);
+ poly36.ps[1] = Point(697.924, 547.557);
+ poly36.ps[2] = Point(657.924, 547.557);
+ poly36.ps[3] = Point(657.924, 507.557);
+ new ShapeRef(router, poly36, 36);
+
+ Polygon poly98(4);
+ poly98.ps[0] = Point(1208.92, 378.557);
+ poly98.ps[1] = Point(1208.92, 398.557);
+ poly98.ps[2] = Point(1188.92, 398.557);
+ poly98.ps[3] = Point(1188.92, 378.557);
+ new ShapeRef(router, poly98, 98);
+
+ Polygon poly63(4);
+ poly63.ps[0] = Point(457.924, 507.557);
+ poly63.ps[1] = Point(457.924, 547.557);
+ poly63.ps[2] = Point(417.924, 547.557);
+ poly63.ps[3] = Point(417.924, 507.557);
+ new ShapeRef(router, poly63, 63);
+
+ Polygon poly111(4);
+ poly111.ps[0] = Point(285.924, 245.557);
+ poly111.ps[1] = Point(285.924, 285.557);
+ poly111.ps[2] = Point(229.924, 285.557);
+ poly111.ps[3] = Point(229.924, 245.557);
+ new ShapeRef(router, poly111, 111);
+
+ Polygon poly110(4);
+ poly110.ps[0] = Point(287.924, 193.557);
+ poly110.ps[1] = Point(287.924, 233.557);
+ poly110.ps[2] = Point(231.924, 233.557);
+ poly110.ps[3] = Point(231.924, 193.557);
+ new ShapeRef(router, poly110, 110);
+
+ Polygon poly69(4);
+ poly69.ps[0] = Point(267.924, 151.557);
+ poly69.ps[1] = Point(267.924, 171.557);
+ poly69.ps[2] = Point(247.924, 171.557);
+ poly69.ps[3] = Point(247.924, 151.557);
+ new ShapeRef(router, poly69, 69);
+
+ Polygon poly139(4);
+ poly139.ps[0] = Point(1106.92, 82.3422);
+ poly139.ps[1] = Point(1106.92, 122.342);
+ poly139.ps[2] = Point(1050.92, 122.342);
+ poly139.ps[3] = Point(1050.92, 82.3422);
+ new ShapeRef(router, poly139, 139);
+
+ Polygon poly22(4);
+ poly22.ps[0] = Point(697.924, 34.8422);
+ poly22.ps[1] = Point(697.924, 74.8422);
+ poly22.ps[2] = Point(657.924, 74.8422);
+ poly22.ps[3] = Point(657.924, 34.8422);
+ new ShapeRef(router, poly22, 22);
+
+ Polygon poly14(4);
+ poly14.ps[0] = Point(1158.92, 141.557);
+ poly14.ps[1] = Point(1158.92, 181.557);
+ poly14.ps[2] = Point(1118.92, 181.557);
+ poly14.ps[3] = Point(1118.92, 141.557);
+ new ShapeRef(router, poly14, 14);
+
+ Polygon poly13(4);
+ poly13.ps[0] = Point(1158.92, 323.557);
+ poly13.ps[1] = Point(1158.92, 363.557);
+ poly13.ps[2] = Point(1118.92, 363.557);
+ poly13.ps[3] = Point(1118.92, 323.557);
+ new ShapeRef(router, poly13, 13);
+
+ Polygon poly65(4);
+ poly65.ps[0] = Point(97.9242, 599.557);
+ poly65.ps[1] = Point(97.9242, 639.557);
+ poly65.ps[2] = Point(57.9242, 639.557);
+ poly65.ps[3] = Point(57.9242, 599.557);
+ new ShapeRef(router, poly65, 65);
+
+ Polygon poly131(4);
+ poly131.ps[0] = Point(645.924, 457.557);
+ poly131.ps[1] = Point(645.924, 497.557);
+ poly131.ps[2] = Point(589.924, 497.557);
+ poly131.ps[3] = Point(589.924, 457.557);
+ new ShapeRef(router, poly131, 131);
+
+ Polygon poly99(4);
+ poly99.ps[0] = Point(1088.92, 142.342);
+ poly99.ps[1] = Point(1088.92, 162.342);
+ poly99.ps[2] = Point(1068.92, 162.342);
+ poly99.ps[3] = Point(1068.92, 142.342);
+ new ShapeRef(router, poly99, 99);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(1371.92, -22.1578);
+ poly5.ps[1] = Point(1371.92, 17.8422);
+ poly5.ps[2] = Point(1331.92, 17.8422);
+ poly5.ps[3] = Point(1331.92, -22.1578);
+ new ShapeRef(router, poly5, 5);
+
+ Polygon poly87(4);
+ poly87.ps[0] = Point(627.924, 35.8422);
+ poly87.ps[1] = Point(627.924, 55.8422);
+ poly87.ps[2] = Point(607.924, 55.8422);
+ poly87.ps[3] = Point(607.924, 35.8422);
+ new ShapeRef(router, poly87, 87);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(577.924, 795.557);
+ poly2.ps[1] = Point(577.924, 835.557);
+ poly2.ps[2] = Point(537.924, 835.557);
+ poly2.ps[3] = Point(537.924, 795.557);
+ new ShapeRef(router, poly2, 2);
+
+ Polygon poly78(4);
+ poly78.ps[0] = Point(387.924, 617.557);
+ poly78.ps[1] = Point(387.924, 637.557);
+ poly78.ps[2] = Point(367.924, 637.557);
+ poly78.ps[3] = Point(367.924, 617.557);
+ new ShapeRef(router, poly78, 78);
+
+ Polygon poly137(4);
+ poly137.ps[0] = Point(1106.92, 318.557);
+ poly137.ps[1] = Point(1106.92, 358.557);
+ poly137.ps[2] = Point(1050.92, 358.557);
+ poly137.ps[3] = Point(1050.92, 318.557);
+ new ShapeRef(router, poly137, 137);
+
+ Polygon poly50(4);
+ poly50.ps[0] = Point(272.5, -82.1578);
+ poly50.ps[1] = Point(272.5, -47.1578);
+ poly50.ps[2] = Point(35.5, -47.1578);
+ poly50.ps[3] = Point(35.5, -82.1578);
+ new ShapeRef(router, poly50, 50);
+
+ Polygon poly144(4);
+ poly144.ps[0] = Point(765.924, 91.5565);
+ poly144.ps[1] = Point(765.924, 131.557);
+ poly144.ps[2] = Point(709.924, 131.557);
+ poly144.ps[3] = Point(709.924, 91.5565);
+ new ShapeRef(router, poly144, 144);
+
+ Polygon poly12(4);
+ poly12.ps[0] = Point(1038.92, 260.557);
+ poly12.ps[1] = Point(1038.92, 300.557);
+ poly12.ps[2] = Point(998.924, 300.557);
+ poly12.ps[3] = Point(998.924, 260.557);
+ new ShapeRef(router, poly12, 12);
+
+ Polygon poly102(4);
+ poly102.ps[0] = Point(1088.92, -70.6578);
+ poly102.ps[1] = Point(1088.92, -50.6578);
+ poly102.ps[2] = Point(1068.92, -50.6578);
+ poly102.ps[3] = Point(1068.92, -70.6578);
+ new ShapeRef(router, poly102, 102);
+
+ Polygon poly11(4);
+ poly11.ps[0] = Point(817.924, -80.6578);
+ poly11.ps[1] = Point(817.924, -40.6578);
+ poly11.ps[2] = Point(777.924, -40.6578);
+ poly11.ps[3] = Point(777.924, -80.6578);
+ new ShapeRef(router, poly11, 11);
+
+ Polygon poly96(4);
+ poly96.ps[0] = Point(747.924, 333.557);
+ poly96.ps[1] = Point(747.924, 353.557);
+ poly96.ps[2] = Point(727.924, 353.557);
+ poly96.ps[3] = Point(727.924, 333.557);
+ new ShapeRef(router, poly96, 96);
+
+ Polygon poly135(4);
+ poly135.ps[0] = Point(885.924, 91.5565);
+ poly135.ps[1] = Point(885.924, 131.557);
+ poly135.ps[2] = Point(829.924, 131.557);
+ poly135.ps[3] = Point(829.924, 91.5565);
+ new ShapeRef(router, poly135, 135);
+
+ Polygon poly1(4);
+ poly1.ps[0] = Point(817.924, 840.057);
+ poly1.ps[1] = Point(817.924, 880.057);
+ poly1.ps[2] = Point(777.924, 880.057);
+ poly1.ps[3] = Point(777.924, 840.057);
+ new ShapeRef(router, poly1, 1);
+
+ Polygon poly126(4);
+ poly126.ps[0] = Point(525.924, -24.1578);
+ poly126.ps[1] = Point(525.924, 15.8422);
+ poly126.ps[2] = Point(469.924, 15.8422);
+ poly126.ps[3] = Point(469.924, -24.1578);
+ new ShapeRef(router, poly126, 126);
+
+ Polygon poly54(4);
+ poly54.ps[0] = Point(697.924, 323.557);
+ poly54.ps[1] = Point(697.924, 363.557);
+ poly54.ps[2] = Point(657.924, 363.557);
+ poly54.ps[3] = Point(657.924, 323.557);
+ new ShapeRef(router, poly54, 54);
+
+ Polygon poly43(4);
+ poly43.ps[0] = Point(1038.92, 1.84222);
+ poly43.ps[1] = Point(1038.92, 41.8422);
+ poly43.ps[2] = Point(998.924, 41.8422);
+ poly43.ps[3] = Point(998.924, 1.84222);
+ new ShapeRef(router, poly43, 43);
+
+ Polygon poly85(4);
+ poly85.ps[0] = Point(387.924, 17.3422);
+ poly85.ps[1] = Point(387.924, 37.3422);
+ poly85.ps[2] = Point(367.924, 37.3422);
+ poly85.ps[3] = Point(367.924, 17.3422);
+ new ShapeRef(router, poly85, 85);
+
+ Polygon poly55(4);
+ poly55.ps[0] = Point(457.924, 7.34222);
+ poly55.ps[1] = Point(457.924, 47.3422);
+ poly55.ps[2] = Point(417.924, 47.3422);
+ poly55.ps[3] = Point(417.924, 7.34222);
+ new ShapeRef(router, poly55, 55);
+
+ Polygon poly127(4);
+ poly127.ps[0] = Point(645.924, -24.1578);
+ poly127.ps[1] = Point(645.924, 15.8422);
+ poly127.ps[2] = Point(589.924, 15.8422);
+ poly127.ps[3] = Point(589.924, -24.1578);
+ new ShapeRef(router, poly127, 127);
+
+ Polygon poly49(4);
+ poly49.ps[0] = Point(45.9242, 169.75);
+ poly49.ps[1] = Point(45.9242, 334.75);
+ poly49.ps[2] = Point(-242.076, 334.75);
+ poly49.ps[3] = Point(-242.076, 169.75);
+ new ShapeRef(router, poly49, 49);
+
+ Polygon poly57(4);
+ poly57.ps[0] = Point(817.924, 141.557);
+ poly57.ps[1] = Point(817.924, 181.557);
+ poly57.ps[2] = Point(777.924, 181.557);
+ poly57.ps[3] = Point(777.924, 141.557);
+ new ShapeRef(router, poly57, 57);
+
+ Polygon poly25(4);
+ poly25.ps[0] = Point(697.924, 883.057);
+ poly25.ps[1] = Point(697.924, 923.057);
+ poly25.ps[2] = Point(657.924, 923.057);
+ poly25.ps[3] = Point(657.924, 883.057);
+ new ShapeRef(router, poly25, 25);
+
+ Polygon poly37(4);
+ poly37.ps[0] = Point(457.924, 607.557);
+ poly37.ps[1] = Point(457.924, 647.557);
+ poly37.ps[2] = Point(417.924, 647.557);
+ poly37.ps[3] = Point(417.924, 607.557);
+ new ShapeRef(router, poly37, 37);
+
+ Polygon poly143(4);
+ poly143.ps[0] = Point(986.924, 210.557);
+ poly143.ps[1] = Point(986.924, 250.557);
+ poly143.ps[2] = Point(930.924, 250.557);
+ poly143.ps[3] = Point(930.924, 210.557);
+ new ShapeRef(router, poly143, 143);
+
+ Polygon poly138(4);
+ poly138.ps[0] = Point(1226.92, 318.557);
+ poly138.ps[1] = Point(1226.92, 358.557);
+ poly138.ps[2] = Point(1170.92, 358.557);
+ poly138.ps[3] = Point(1170.92, 318.557);
+ new ShapeRef(router, poly138, 138);
+
+ Polygon poly140(4);
+ poly140.ps[0] = Point(1106.92, -9.65778);
+ poly140.ps[1] = Point(1106.92, 30.3422);
+ poly140.ps[2] = Point(1050.92, 30.3422);
+ poly140.ps[3] = Point(1050.92, -9.65778);
+ new ShapeRef(router, poly140, 140);
+
+ Polygon poly147(4);
+ poly147.ps[0] = Point(-26.0758, 274.75);
+ poly147.ps[1] = Point(-26.0758, 334.75);
+ poly147.ps[2] = Point(-66.0758, 334.75);
+ poly147.ps[3] = Point(-66.0758, 274.75);
+ new ShapeRef(router, poly147, 147);
+
+ Polygon poly146(4);
+ poly146.ps[0] = Point(45.9242, 232.5);
+ poly146.ps[1] = Point(45.9242, 272.5);
+ poly146.ps[2] = Point(-14.0758, 272.5);
+ poly146.ps[3] = Point(-14.0758, 232.5);
+ new ShapeRef(router, poly146, 146);
+
+ Polygon poly103(4);
+ poly103.ps[0] = Point(968.924, 270.557);
+ poly103.ps[1] = Point(968.924, 290.557);
+ poly103.ps[2] = Point(948.924, 290.557);
+ poly103.ps[3] = Point(948.924, 270.557);
+ new ShapeRef(router, poly103, 103);
+
+ Polygon poly68(4);
+ poly68.ps[0] = Point(147.924, 151.557);
+ poly68.ps[1] = Point(147.924, 171.557);
+ poly68.ps[2] = Point(127.924, 171.557);
+ poly68.ps[3] = Point(127.924, 151.557);
+ new ShapeRef(router, poly68, 68);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(937.924, -80.6578);
+ poly10.ps[1] = Point(937.924, -40.6578);
+ poly10.ps[2] = Point(897.924, -40.6578);
+ poly10.ps[3] = Point(897.924, -80.6578);
+ new ShapeRef(router, poly10, 10);
+
+ Polygon poly118(4);
+ poly118.ps[0] = Point(405.924, 557.557);
+ poly118.ps[1] = Point(405.924, 597.557);
+ poly118.ps[2] = Point(349.924, 597.557);
+ poly118.ps[3] = Point(349.924, 557.557);
+ new ShapeRef(router, poly118, 118);
+
+ Polygon poly128(4);
+ poly128.ps[0] = Point(765.924, 504.057);
+ poly128.ps[1] = Point(765.924, 544.057);
+ poly128.ps[2] = Point(709.924, 544.057);
+ poly128.ps[3] = Point(709.924, 504.057);
+ new ShapeRef(router, poly128, 128);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(1038.92, -80.6578);
+ poly9.ps[1] = Point(1038.92, -40.6578);
+ poly9.ps[2] = Point(998.924, -40.6578);
+ poly9.ps[3] = Point(998.924, -80.6578);
+ new ShapeRef(router, poly9, 9);
+
+ Polygon poly91(4);
+ poly91.ps[0] = Point(627.924, 517.557);
+ poly91.ps[1] = Point(627.924, 537.557);
+ poly91.ps[2] = Point(607.924, 537.557);
+ poly91.ps[3] = Point(607.924, 517.557);
+ new ShapeRef(router, poly91, 91);
+
+ Polygon poly52(4);
+ poly52.ps[0] = Point(217.924, 295.557);
+ poly52.ps[1] = Point(217.924, 335.557);
+ poly52.ps[2] = Point(177.924, 335.557);
+ poly52.ps[3] = Point(177.924, 295.557);
+ new ShapeRef(router, poly52, 52);
+
+ Polygon poly39(4);
+ poly39.ps[0] = Point(457.924, 141.557);
+ poly39.ps[1] = Point(457.924, 181.557);
+ poly39.ps[2] = Point(417.924, 181.557);
+ poly39.ps[3] = Point(417.924, 141.557);
+ new ShapeRef(router, poly39, 39);
+
+ Polygon poly76(4);
+ poly76.ps[0] = Point(147.924, 753.557);
+ poly76.ps[1] = Point(147.924, 773.557);
+ poly76.ps[2] = Point(127.924, 773.557);
+ poly76.ps[3] = Point(127.924, 753.557);
+ new ShapeRef(router, poly76, 76);
+
+ Polygon poly62(4);
+ poly62.ps[0] = Point(577.924, 629.557);
+ poly62.ps[1] = Point(577.924, 669.557);
+ poly62.ps[2] = Point(537.924, 669.557);
+ poly62.ps[3] = Point(537.924, 629.557);
+ new ShapeRef(router, poly62, 62);
+
+ Polygon poly105(4);
+ poly105.ps[0] = Point(747.924, 850.057);
+ poly105.ps[1] = Point(747.924, 870.057);
+ poly105.ps[2] = Point(727.924, 870.057);
+ poly105.ps[3] = Point(727.924, 850.057);
+ new ShapeRef(router, poly105, 105);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(1158.92, -80.6578);
+ poly8.ps[1] = Point(1158.92, -40.6578);
+ poly8.ps[2] = Point(1118.92, -40.6578);
+ poly8.ps[3] = Point(1118.92, -80.6578);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly95(4);
+ poly95.ps[0] = Point(867.924, 151.557);
+ poly95.ps[1] = Point(867.924, 171.557);
+ poly95.ps[2] = Point(847.924, 171.557);
+ poly95.ps[3] = Point(847.924, 151.557);
+ new ShapeRef(router, poly95, 95);
+
+ Polygon poly125(4);
+ poly125.ps[0] = Point(405.924, -42.6578);
+ poly125.ps[1] = Point(405.924, -2.65778);
+ poly125.ps[2] = Point(349.924, -2.65778);
+ poly125.ps[3] = Point(349.924, -42.6578);
+ new ShapeRef(router, poly125, 125);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(1278.92, -80.6578);
+ poly7.ps[1] = Point(1278.92, -40.6578);
+ poly7.ps[2] = Point(1238.92, -40.6578);
+ poly7.ps[3] = Point(1238.92, -80.6578);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly114(4);
+ poly114.ps[0] = Point(165.924, 549.557);
+ poly114.ps[1] = Point(165.924, 589.557);
+ poly114.ps[2] = Point(109.924, 589.557);
+ poly114.ps[3] = Point(109.924, 549.557);
+ new ShapeRef(router, poly114, 114);
+
+ Polygon poly132(4);
+ poly132.ps[0] = Point(645.924, 365.557);
+ poly132.ps[1] = Point(645.924, 405.557);
+ poly132.ps[2] = Point(589.924, 405.557);
+ poly132.ps[3] = Point(589.924, 365.557);
+ new ShapeRef(router, poly132, 132);
+
+ Polygon poly112(4);
+ poly112.ps[0] = Point(167.924, 347.557);
+ poly112.ps[1] = Point(167.924, 387.557);
+ poly112.ps[2] = Point(111.924, 387.557);
+ poly112.ps[3] = Point(111.924, 347.557);
+ new ShapeRef(router, poly112, 112);
+
+ Polygon poly40(4);
+ poly40.ps[0] = Point(97.9242, 141.557);
+ poly40.ps[1] = Point(97.9242, 181.557);
+ poly40.ps[2] = Point(57.9242, 181.557);
+ poly40.ps[3] = Point(57.9242, 141.557);
+ new ShapeRef(router, poly40, 40);
+
+ Polygon poly92(4);
+ poly92.ps[0] = Point(627.924, 425.557);
+ poly92.ps[1] = Point(627.924, 445.557);
+ poly92.ps[2] = Point(607.924, 445.557);
+ poly92.ps[3] = Point(607.924, 425.557);
+ new ShapeRef(router, poly92, 92);
+
+ Polygon poly104(4);
+ poly104.ps[0] = Point(747.924, 151.557);
+ poly104.ps[1] = Point(747.924, 171.557);
+ poly104.ps[2] = Point(727.924, 171.557);
+ poly104.ps[3] = Point(727.924, 151.557);
+ new ShapeRef(router, poly104, 104);
+
+ Polygon poly89(4);
+ poly89.ps[0] = Point(507.924, 517.557);
+ poly89.ps[1] = Point(507.924, 537.557);
+ poly89.ps[2] = Point(487.924, 537.557);
+ poly89.ps[3] = Point(487.924, 517.557);
+ new ShapeRef(router, poly89, 89);
+
+ Polygon poly84(4);
+ poly84.ps[0] = Point(387.924, 151.557);
+ poly84.ps[1] = Point(387.924, 171.557);
+ poly84.ps[2] = Point(367.924, 171.557);
+ poly84.ps[3] = Point(367.924, 151.557);
+ new ShapeRef(router, poly84, 84);
+
+ Polygon poly26(4);
+ poly26.ps[0] = Point(697.924, 743.557);
+ poly26.ps[1] = Point(697.924, 783.557);
+ poly26.ps[2] = Point(657.924, 783.557);
+ poly26.ps[3] = Point(657.924, 743.557);
+ new ShapeRef(router, poly26, 26);
+
+ Polygon poly107(4);
+ poly107.ps[0] = Point(165.924, -35.1578);
+ poly107.ps[1] = Point(165.924, 4.84222);
+ poly107.ps[2] = Point(109.924, 4.84222);
+ poly107.ps[3] = Point(109.924, -35.1578);
+ new ShapeRef(router, poly107, 107);
+
+ Polygon poly142(4);
+ poly142.ps[0] = Point(1106.92, -130.658);
+ poly142.ps[1] = Point(1106.92, -90.6578);
+ poly142.ps[2] = Point(1050.92, -90.6578);
+ poly142.ps[3] = Point(1050.92, -130.658);
+ new ShapeRef(router, poly142, 142);
+
+ Polygon poly47(4);
+ poly47.ps[0] = Point(697.924, 271.557);
+ poly47.ps[1] = Point(697.924, 311.557);
+ poly47.ps[2] = Point(657.924, 311.557);
+ poly47.ps[3] = Point(657.924, 271.557);
+ new ShapeRef(router, poly47, 47);
+
+ Polygon poly109(4);
+ poly109.ps[0] = Point(285.924, 91.5565);
+ poly109.ps[1] = Point(285.924, 131.557);
+ poly109.ps[2] = Point(229.924, 131.557);
+ poly109.ps[3] = Point(229.924, 91.5565);
+ new ShapeRef(router, poly109, 109);
+
+ Polygon poly145(4);
+ poly145.ps[0] = Point(765.924, 790.057);
+ poly145.ps[1] = Point(765.924, 830.057);
+ poly145.ps[2] = Point(709.924, 830.057);
+ poly145.ps[3] = Point(709.924, 790.057);
+ new ShapeRef(router, poly145, 145);
+
+ Polygon poly122(4);
+ poly122.ps[0] = Point(525.924, 833.057);
+ poly122.ps[1] = Point(525.924, 873.057);
+ poly122.ps[2] = Point(469.924, 873.057);
+ poly122.ps[3] = Point(469.924, 833.057);
+ new ShapeRef(router, poly122, 122);
+
+ Polygon poly58(4);
+ poly58.ps[0] = Point(97.9242, 14.8422);
+ poly58.ps[1] = Point(97.9242, 54.8422);
+ poly58.ps[2] = Point(57.9242, 54.8422);
+ poly58.ps[3] = Point(57.9242, 14.8422);
+ new ShapeRef(router, poly58, 58);
+
+ Polygon poly124(4);
+ poly124.ps[0] = Point(405.924, 91.5565);
+ poly124.ps[1] = Point(405.924, 131.557);
+ poly124.ps[2] = Point(349.924, 131.557);
+ poly124.ps[3] = Point(349.924, 91.5565);
+ new ShapeRef(router, poly124, 124);
+
+ Polygon poly42(4);
+ poly42.ps[0] = Point(697.924, 415.557);
+ poly42.ps[1] = Point(697.924, 455.557);
+ poly42.ps[2] = Point(657.924, 455.557);
+ poly42.ps[3] = Point(657.924, 415.557);
+ new ShapeRef(router, poly42, 42);
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(1371.92, -80.6578);
+ poly6.ps[1] = Point(1371.92, -40.6578);
+ poly6.ps[2] = Point(1331.92, -40.6578);
+ poly6.ps[3] = Point(1331.92, -80.6578);
+ new ShapeRef(router, poly6, 6);
+
+ ConnRef *connRef162 = new ConnRef(router, 162);
+ ConnEnd srcPt162(Point(317.924, 161.557), 15);
+ connRef162->setSourceEndpoint(srcPt162);
+ ConnEnd dstPt162(Point(367.924, 27.3422), 15);
+ connRef162->setDestEndpoint(dstPt162);
+ connRef162->setRoutingType((ConnType)2);
+
+ ConnRef *connRef163 = new ConnRef(router, 163);
+ ConnEnd srcPt163(Point(317.924, 161.557), 15);
+ connRef163->setSourceEndpoint(srcPt163);
+ ConnEnd dstPt163(Point(487.924, 435.557), 15);
+ connRef163->setDestEndpoint(dstPt163);
+ connRef163->setRoutingType((ConnType)2);
+
+ ConnRef *connRef191 = new ConnRef(router, 191);
+ ConnEnd srcPt191(Point(267.924, 161.557), 15);
+ connRef191->setSourceEndpoint(srcPt191);
+ ConnEnd dstPt191(Point(317.924, 161.557), 15);
+ connRef191->setDestEndpoint(dstPt191);
+ connRef191->setRoutingType((ConnType)2);
+
+ ConnRef *connRef192 = new ConnRef(router, 192);
+ ConnEnd srcPt192(Point(197.924, 223.557), 15);
+ connRef192->setSourceEndpoint(srcPt192);
+ ConnEnd dstPt192(Point(197.924, 315.557), 15);
+ connRef192->setDestEndpoint(dstPt192);
+ connRef192->setRoutingType((ConnType)2);
+
+ ConnRef *connRef193 = new ConnRef(router, 193);
+ ConnEnd srcPt193(Point(77.9242, 377.557), 15);
+ connRef193->setSourceEndpoint(srcPt193);
+ ConnEnd dstPt193(Point(77.9242, 527.557), 15);
+ connRef193->setDestEndpoint(dstPt193);
+ connRef193->setRoutingType((ConnType)2);
+
+ ConnRef *connRef194 = new ConnRef(router, 194);
+ ConnEnd srcPt194(Point(147.924, 527.557), 15);
+ connRef194->setSourceEndpoint(srcPt194);
+ ConnEnd dstPt194(Point(197.924, 527.557), 15);
+ connRef194->setDestEndpoint(dstPt194);
+ connRef194->setRoutingType((ConnType)2);
+
+ ConnRef *connRef195 = new ConnRef(router, 195);
+ ConnEnd srcPt195(Point(147.924, 619.557), 15);
+ connRef195->setSourceEndpoint(srcPt195);
+ ConnEnd dstPt195(Point(197.924, 763.557), 15);
+ connRef195->setDestEndpoint(dstPt195);
+ connRef195->setRoutingType((ConnType)2);
+
+ ConnRef *connRef196 = new ConnRef(router, 196);
+ ConnEnd srcPt196(Point(77.9242, 651.557), 15);
+ connRef196->setSourceEndpoint(srcPt196);
+ ConnEnd dstPt196(Point(77.9242, 619.557), 15);
+ connRef196->setDestEndpoint(dstPt196);
+ connRef196->setRoutingType((ConnType)2);
+
+ ConnRef *connRef152 = new ConnRef(router, 152);
+ ConnEnd srcPt152(Point(317.924, 763.557), 15);
+ connRef152->setSourceEndpoint(srcPt152);
+ ConnEnd dstPt152(Point(367.924, 763.557), 15);
+ connRef152->setDestEndpoint(dstPt152);
+ connRef152->setRoutingType((ConnType)2);
+
+ ConnRef *connRef153 = new ConnRef(router, 153);
+ ConnEnd srcPt153(Point(317.924, 763.557), 15);
+ connRef153->setSourceEndpoint(srcPt153);
+ ConnEnd dstPt153(Point(487.924, 903.057), 15);
+ connRef153->setDestEndpoint(dstPt153);
+ connRef153->setRoutingType((ConnType)2);
+
+ ConnRef *connRef150 = new ConnRef(router, 150);
+ ConnEnd srcPt150(Point(1138.92, 435.557), 15);
+ connRef150->setSourceEndpoint(srcPt150);
+ ConnEnd dstPt150(Point(1188.92, 388.557), 15);
+ connRef150->setDestEndpoint(dstPt150);
+ connRef150->setRoutingType((ConnType)2);
+
+ ConnRef *connRef151 = new ConnRef(router, 151);
+ ConnEnd srcPt151(Point(317.924, 763.557), 15);
+ connRef151->setSourceEndpoint(srcPt151);
+ ConnEnd dstPt151(Point(367.924, 627.557), 15);
+ connRef151->setDestEndpoint(dstPt151);
+ connRef151->setRoutingType((ConnType)2);
+
+ ConnRef *connRef156 = new ConnRef(router, 156);
+ ConnEnd srcPt156(Point(197.924, 763.557), 15);
+ connRef156->setSourceEndpoint(srcPt156);
+ ConnEnd dstPt156(Point(247.924, 763.557), 15);
+ connRef156->setDestEndpoint(dstPt156);
+ connRef156->setRoutingType((ConnType)2);
+
+ ConnRef *connRef157 = new ConnRef(router, 157);
+ ConnEnd srcPt157(Point(147.924, 161.557), 15);
+ connRef157->setSourceEndpoint(srcPt157);
+ ConnEnd dstPt157(Point(197.924, 161.557), 15);
+ connRef157->setDestEndpoint(dstPt157);
+ connRef157->setRoutingType((ConnType)2);
+
+ ConnRef *connRef158 = new ConnRef(router, 158);
+ ConnEnd srcPt158(Point(197.924, 161.557), 15);
+ connRef158->setSourceEndpoint(srcPt158);
+ ConnEnd dstPt158(Point(247.924, 161.557), 15);
+ connRef158->setDestEndpoint(dstPt158);
+ connRef158->setRoutingType((ConnType)2);
+
+ ConnRef *connRef159 = new ConnRef(router, 159);
+ ConnEnd srcPt159(Point(197.924, 161.557), 15);
+ connRef159->setSourceEndpoint(srcPt159);
+ ConnEnd dstPt159(Point(197.924, 203.557), 15);
+ connRef159->setDestEndpoint(dstPt159);
+ connRef159->setRoutingType((ConnType)2);
+
+ ConnRef *connRef154 = new ConnRef(router, 154);
+ ConnEnd srcPt154(Point(317.924, 763.557), 15);
+ connRef154->setSourceEndpoint(srcPt154);
+ ConnEnd dstPt154(Point(727.924, 574.057), 15);
+ connRef154->setDestEndpoint(dstPt154);
+ connRef154->setRoutingType((ConnType)2);
+
+ ConnRef *connRef155 = new ConnRef(router, 155);
+ ConnEnd srcPt155(Point(557.924, 903.057), 15);
+ connRef155->setSourceEndpoint(srcPt155);
+ ConnEnd dstPt155(Point(607.924, 903.057), 15);
+ connRef155->setDestEndpoint(dstPt155);
+ connRef155->setRoutingType((ConnType)2);
+
+ ConnRef *connRef229 = new ConnRef(router, 229);
+ ConnEnd srcPt229(Point(257.924, 111.557), 15);
+ connRef229->setSourceEndpoint(srcPt229);
+ ConnEnd dstPt229(Point(257.924, 161.557), 15);
+ connRef229->setDestEndpoint(dstPt229);
+ connRef229->setRoutingType((ConnType)2);
+
+ ConnRef *connRef230 = new ConnRef(router, 230);
+ ConnEnd srcPt230(Point(259.924, 213.557), 15);
+ connRef230->setSourceEndpoint(srcPt230);
+ ConnEnd dstPt230(Point(197.924, 213.557), 15);
+ connRef230->setDestEndpoint(dstPt230);
+ connRef230->setRoutingType((ConnType)2);
+
+ ConnRef *connRef231 = new ConnRef(router, 231);
+ ConnEnd srcPt231(Point(257.924, 265.557), 15);
+ connRef231->setSourceEndpoint(srcPt231);
+ ConnEnd dstPt231(Point(257.924, 315.557), 15);
+ connRef231->setDestEndpoint(dstPt231);
+ connRef231->setRoutingType((ConnType)2);
+
+ ConnRef *connRef232 = new ConnRef(router, 232);
+ ConnEnd srcPt232(Point(139.924, 367.557), 15);
+ connRef232->setSourceEndpoint(srcPt232);
+ ConnEnd dstPt232(Point(77.9242, 367.557), 15);
+ connRef232->setDestEndpoint(dstPt232);
+ connRef232->setRoutingType((ConnType)2);
+
+ ConnRef *connRef233 = new ConnRef(router, 233);
+ ConnEnd srcPt233(Point(137.924, 477.557), 15);
+ connRef233->setSourceEndpoint(srcPt233);
+ ConnEnd dstPt233(Point(137.924, 527.557), 15);
+ connRef233->setDestEndpoint(dstPt233);
+ connRef233->setRoutingType((ConnType)2);
+
+ ConnRef *connRef234 = new ConnRef(router, 234);
+ ConnEnd srcPt234(Point(137.924, 569.557), 15);
+ connRef234->setSourceEndpoint(srcPt234);
+ ConnEnd dstPt234(Point(137.924, 619.557), 15);
+ connRef234->setDestEndpoint(dstPt234);
+ connRef234->setRoutingType((ConnType)2);
+
+ ConnRef *connRef235 = new ConnRef(router, 235);
+ ConnEnd srcPt235(Point(139.924, 661.557), 15);
+ connRef235->setSourceEndpoint(srcPt235);
+ ConnEnd dstPt235(Point(77.9242, 661.557), 15);
+ connRef235->setDestEndpoint(dstPt235);
+ connRef235->setRoutingType((ConnType)2);
+
+ ConnRef *connRef236 = new ConnRef(router, 236);
+ ConnEnd srcPt236(Point(137.924, 713.557), 15);
+ connRef236->setSourceEndpoint(srcPt236);
+ ConnEnd dstPt236(Point(137.924, 763.557), 15);
+ connRef236->setDestEndpoint(dstPt236);
+ connRef236->setRoutingType((ConnType)2);
+
+ ConnRef *connRef237 = new ConnRef(router, 237);
+ ConnEnd srcPt237(Point(257.924, 713.557), 15);
+ connRef237->setSourceEndpoint(srcPt237);
+ ConnEnd dstPt237(Point(257.924, 763.557), 15);
+ connRef237->setDestEndpoint(dstPt237);
+ connRef237->setRoutingType((ConnType)2);
+
+ ConnRef *connRef238 = new ConnRef(router, 238);
+ ConnEnd srcPt238(Point(377.924, 577.557), 15);
+ connRef238->setSourceEndpoint(srcPt238);
+ ConnEnd dstPt238(Point(377.924, 627.557), 15);
+ connRef238->setDestEndpoint(dstPt238);
+ connRef238->setRoutingType((ConnType)2);
+
+ ConnRef *connRef239 = new ConnRef(router, 239);
+ ConnEnd srcPt239(Point(377.924, 713.557), 15);
+ connRef239->setSourceEndpoint(srcPt239);
+ ConnEnd dstPt239(Point(377.924, 763.557), 15);
+ connRef239->setDestEndpoint(dstPt239);
+ connRef239->setRoutingType((ConnType)2);
+
+ ConnRef *connRef240 = new ConnRef(router, 240);
+ ConnEnd srcPt240(Point(497.924, 713.557), 15);
+ connRef240->setSourceEndpoint(srcPt240);
+ ConnEnd dstPt240(Point(497.924, 763.557), 15);
+ connRef240->setDestEndpoint(dstPt240);
+ connRef240->setRoutingType((ConnType)2);
+
+ ConnRef *connRef241 = new ConnRef(router, 241);
+ ConnEnd srcPt241(Point(617.924, 713.557), 15);
+ connRef241->setSourceEndpoint(srcPt241);
+ ConnEnd dstPt241(Point(617.924, 763.557), 15);
+ connRef241->setDestEndpoint(dstPt241);
+ connRef241->setRoutingType((ConnType)2);
+
+ ConnRef *connRef242 = new ConnRef(router, 242);
+ ConnEnd srcPt242(Point(497.924, 853.057), 15);
+ connRef242->setSourceEndpoint(srcPt242);
+ ConnEnd dstPt242(Point(497.924, 903.057), 15);
+ connRef242->setDestEndpoint(dstPt242);
+ connRef242->setRoutingType((ConnType)2);
+
+ ConnRef *connRef243 = new ConnRef(router, 243);
+ ConnEnd srcPt243(Point(617.924, 853.057), 15);
+ connRef243->setSourceEndpoint(srcPt243);
+ ConnEnd dstPt243(Point(617.924, 903.057), 15);
+ connRef243->setDestEndpoint(dstPt243);
+ connRef243->setRoutingType((ConnType)2);
+
+ ConnRef *connRef244 = new ConnRef(router, 244);
+ ConnEnd srcPt244(Point(377.924, 111.557), 15);
+ connRef244->setSourceEndpoint(srcPt244);
+ ConnEnd dstPt244(Point(377.924, 161.557), 15);
+ connRef244->setDestEndpoint(dstPt244);
+ connRef244->setRoutingType((ConnType)2);
+
+ ConnRef *connRef245 = new ConnRef(router, 245);
+ ConnEnd srcPt245(Point(377.924, -22.6578), 15);
+ connRef245->setSourceEndpoint(srcPt245);
+ ConnEnd dstPt245(Point(377.924, 27.3422), 15);
+ connRef245->setDestEndpoint(dstPt245);
+ connRef245->setRoutingType((ConnType)2);
+
+ ConnRef *connRef246 = new ConnRef(router, 246);
+ ConnEnd srcPt246(Point(497.924, -4.15778), 15);
+ connRef246->setSourceEndpoint(srcPt246);
+ ConnEnd dstPt246(Point(497.924, 45.8422), 15);
+ connRef246->setDestEndpoint(dstPt246);
+ connRef246->setRoutingType((ConnType)2);
+
+ ConnRef *connRef247 = new ConnRef(router, 247);
+ ConnEnd srcPt247(Point(617.924, -4.15778), 15);
+ connRef247->setSourceEndpoint(srcPt247);
+ ConnEnd dstPt247(Point(617.924, 45.8422), 15);
+ connRef247->setDestEndpoint(dstPt247);
+ connRef247->setRoutingType((ConnType)2);
+
+ ConnRef *connRef248 = new ConnRef(router, 248);
+ ConnEnd srcPt248(Point(737.924, 524.057), 15);
+ connRef248->setSourceEndpoint(srcPt248);
+ ConnEnd dstPt248(Point(737.924, 574.057), 15);
+ connRef248->setDestEndpoint(dstPt248);
+ connRef248->setRoutingType((ConnType)2);
+
+ ConnRef *connRef249 = new ConnRef(router, 249);
+ ConnEnd srcPt249(Point(497.924, 477.557), 15);
+ connRef249->setSourceEndpoint(srcPt249);
+ ConnEnd dstPt249(Point(497.924, 527.557), 15);
+ connRef249->setDestEndpoint(dstPt249);
+ connRef249->setRoutingType((ConnType)2);
+
+ ConnRef *connRef250 = new ConnRef(router, 250);
+ ConnEnd srcPt250(Point(497.924, 385.557), 15);
+ connRef250->setSourceEndpoint(srcPt250);
+ ConnEnd dstPt250(Point(497.924, 435.557), 15);
+ connRef250->setDestEndpoint(dstPt250);
+ connRef250->setRoutingType((ConnType)2);
+
+ ConnRef *connRef251 = new ConnRef(router, 251);
+ ConnEnd srcPt251(Point(617.924, 477.557), 15);
+ connRef251->setSourceEndpoint(srcPt251);
+ ConnEnd dstPt251(Point(617.924, 527.557), 15);
+ connRef251->setDestEndpoint(dstPt251);
+ connRef251->setRoutingType((ConnType)2);
+
+ ConnRef *connRef252 = new ConnRef(router, 252);
+ ConnEnd srcPt252(Point(617.924, 385.557), 15);
+ connRef252->setSourceEndpoint(srcPt252);
+ ConnEnd dstPt252(Point(617.924, 435.557), 15);
+ connRef252->setDestEndpoint(dstPt252);
+ connRef252->setRoutingType((ConnType)2);
+
+ ConnRef *connRef253 = new ConnRef(router, 253);
+ ConnEnd srcPt253(Point(857.924, 293.557), 15);
+ connRef253->setSourceEndpoint(srcPt253);
+ ConnEnd dstPt253(Point(857.924, 343.557), 15);
+ connRef253->setDestEndpoint(dstPt253);
+ connRef253->setRoutingType((ConnType)2);
+
+ ConnRef *connRef254 = new ConnRef(router, 254);
+ ConnEnd srcPt254(Point(857.924, 385.557), 15);
+ connRef254->setSourceEndpoint(srcPt254);
+ ConnEnd dstPt254(Point(857.924, 435.557), 15);
+ connRef254->setDestEndpoint(dstPt254);
+ connRef254->setRoutingType((ConnType)2);
+
+ ConnRef *connRef255 = new ConnRef(router, 255);
+ ConnEnd srcPt255(Point(857.924, 111.557), 15);
+ connRef255->setSourceEndpoint(srcPt255);
+ ConnEnd dstPt255(Point(857.924, 161.557), 15);
+ connRef255->setDestEndpoint(dstPt255);
+ connRef255->setRoutingType((ConnType)2);
+
+ ConnRef *connRef256 = new ConnRef(router, 256);
+ ConnEnd srcPt256(Point(737.924, 293.557), 15);
+ connRef256->setSourceEndpoint(srcPt256);
+ ConnEnd dstPt256(Point(737.924, 343.557), 15);
+ connRef256->setDestEndpoint(dstPt256);
+ connRef256->setRoutingType((ConnType)2);
+
+ ConnRef *connRef257 = new ConnRef(router, 257);
+ ConnEnd srcPt257(Point(1078.92, 338.557), 15);
+ connRef257->setSourceEndpoint(srcPt257);
+ ConnEnd dstPt257(Point(1078.92, 388.557), 15);
+ connRef257->setDestEndpoint(dstPt257);
+ connRef257->setRoutingType((ConnType)2);
+
+ ConnRef *connRef258 = new ConnRef(router, 258);
+ ConnEnd srcPt258(Point(1198.92, 338.557), 15);
+ connRef258->setSourceEndpoint(srcPt258);
+ ConnEnd dstPt258(Point(1198.92, 388.557), 15);
+ connRef258->setDestEndpoint(dstPt258);
+ connRef258->setRoutingType((ConnType)2);
+
+ ConnRef *connRef259 = new ConnRef(router, 259);
+ ConnEnd srcPt259(Point(1078.92, 102.342), 15);
+ connRef259->setSourceEndpoint(srcPt259);
+ ConnEnd dstPt259(Point(1078.92, 152.342), 15);
+ connRef259->setDestEndpoint(dstPt259);
+ connRef259->setRoutingType((ConnType)2);
+
+ ConnRef *connRef260 = new ConnRef(router, 260);
+ ConnEnd srcPt260(Point(1078.92, 10.3422), 15);
+ connRef260->setSourceEndpoint(srcPt260);
+ ConnEnd dstPt260(Point(1078.92, 60.3422), 15);
+ connRef260->setDestEndpoint(dstPt260);
+ connRef260->setRoutingType((ConnType)2);
+
+ ConnRef *connRef261 = new ConnRef(router, 261);
+ ConnEnd srcPt261(Point(1198.92, 102.342), 15);
+ connRef261->setSourceEndpoint(srcPt261);
+ ConnEnd dstPt261(Point(1198.92, 152.342), 15);
+ connRef261->setDestEndpoint(dstPt261);
+ connRef261->setRoutingType((ConnType)2);
+
+ ConnRef *connRef262 = new ConnRef(router, 262);
+ ConnEnd srcPt262(Point(1078.92, -110.658), 15);
+ connRef262->setSourceEndpoint(srcPt262);
+ ConnEnd dstPt262(Point(1078.92, -60.6578), 15);
+ connRef262->setDestEndpoint(dstPt262);
+ connRef262->setRoutingType((ConnType)2);
+
+ ConnRef *connRef263 = new ConnRef(router, 263);
+ ConnEnd srcPt263(Point(958.924, 230.557), 15);
+ connRef263->setSourceEndpoint(srcPt263);
+ ConnEnd dstPt263(Point(958.924, 280.557), 15);
+ connRef263->setDestEndpoint(dstPt263);
+ connRef263->setRoutingType((ConnType)2);
+
+ ConnRef *connRef264 = new ConnRef(router, 264);
+ ConnEnd srcPt264(Point(737.924, 111.557), 15);
+ connRef264->setSourceEndpoint(srcPt264);
+ ConnEnd dstPt264(Point(737.924, 161.557), 15);
+ connRef264->setDestEndpoint(dstPt264);
+ connRef264->setRoutingType((ConnType)2);
+
+ ConnRef *connRef265 = new ConnRef(router, 265);
+ ConnEnd srcPt265(Point(737.924, 810.057), 15);
+ connRef265->setSourceEndpoint(srcPt265);
+ ConnEnd dstPt265(Point(737.924, 860.057), 15);
+ connRef265->setDestEndpoint(dstPt265);
+ connRef265->setRoutingType((ConnType)2);
+
+ ConnRef *connRef266 = new ConnRef(router, 266);
+ ConnEnd srcPt266(Point(77.9242, 161.557), 15);
+ connRef266->setSourceEndpoint(srcPt266);
+ ConnEnd dstPt266(Point(40.9242, 252.5), 15);
+ connRef266->setDestEndpoint(dstPt266);
+ connRef266->setRoutingType((ConnType)2);
+
+ ConnRef *connRef267 = new ConnRef(router, 267);
+ ConnEnd srcPt267(Point(77.9242, 763.557), 15);
+ connRef267->setSourceEndpoint(srcPt267);
+ ConnEnd dstPt267(Point(-46.0758, 329.75), 15);
+ connRef267->setDestEndpoint(dstPt267);
+ connRef267->setRoutingType((ConnType)2);
+
+ ConnRef *connRef172 = new ConnRef(router, 172);
+ ConnEnd srcPt172(Point(267.924, 315.557), 15);
+ connRef172->setSourceEndpoint(srcPt172);
+ ConnEnd dstPt172(Point(437.924, 161.557), 15);
+ connRef172->setDestEndpoint(dstPt172);
+ connRef172->setRoutingType((ConnType)2);
+
+ ConnRef *connRef173 = new ConnRef(router, 173);
+ ConnEnd srcPt173(Point(437.924, 161.557), 15);
+ connRef173->setSourceEndpoint(srcPt173);
+ ConnEnd dstPt173(Point(487.924, 45.8422), 15);
+ connRef173->setDestEndpoint(dstPt173);
+ connRef173->setRoutingType((ConnType)2);
+
+ ConnRef *connRef178 = new ConnRef(router, 178);
+ ConnEnd srcPt178(Point(77.9242, 527.557), 15);
+ connRef178->setSourceEndpoint(srcPt178);
+ ConnEnd dstPt178(Point(127.924, 527.557), 15);
+ connRef178->setDestEndpoint(dstPt178);
+ connRef178->setRoutingType((ConnType)2);
+
+ ConnRef *connRef179 = new ConnRef(router, 179);
+ ConnEnd srcPt179(Point(557.924, 54.8422), 15);
+ connRef179->setSourceEndpoint(srcPt179);
+ ConnEnd dstPt179(Point(607.924, 45.8422), 15);
+ connRef179->setDestEndpoint(dstPt179);
+ connRef179->setRoutingType((ConnType)2);
+
+ ConnRef *connRef180 = new ConnRef(router, 180);
+ ConnEnd srcPt180(Point(557.924, 435.557), 15);
+ connRef180->setSourceEndpoint(srcPt180);
+ ConnEnd dstPt180(Point(607.924, 435.557), 15);
+ connRef180->setDestEndpoint(dstPt180);
+ connRef180->setRoutingType((ConnType)2);
+
+ ConnRef *connRef181 = new ConnRef(router, 181);
+ ConnEnd srcPt181(Point(77.9242, 763.557), 15);
+ connRef181->setSourceEndpoint(srcPt181);
+ ConnEnd dstPt181(Point(77.9242, 671.557), 15);
+ connRef181->setDestEndpoint(dstPt181);
+ connRef181->setRoutingType((ConnType)2);
+
+ ConnRef *connRef197 = new ConnRef(router, 197);
+ ConnEnd srcPt197(Point(147.924, 763.557), 15);
+ connRef197->setSourceEndpoint(srcPt197);
+ ConnEnd dstPt197(Point(197.924, 763.557), 15);
+ connRef197->setDestEndpoint(dstPt197);
+ connRef197->setRoutingType((ConnType)2);
+
+ ConnRef *connRef198 = new ConnRef(router, 198);
+ ConnEnd srcPt198(Point(267.924, 763.557), 15);
+ connRef198->setSourceEndpoint(srcPt198);
+ ConnEnd dstPt198(Point(317.924, 763.557), 15);
+ connRef198->setDestEndpoint(dstPt198);
+ connRef198->setRoutingType((ConnType)2);
+
+ ConnRef *connRef199 = new ConnRef(router, 199);
+ ConnEnd srcPt199(Point(387.924, 627.557), 15);
+ connRef199->setSourceEndpoint(srcPt199);
+ ConnEnd dstPt199(Point(437.924, 627.557), 15);
+ connRef199->setDestEndpoint(dstPt199);
+ connRef199->setRoutingType((ConnType)2);
+
+ ConnRef *connRef200 = new ConnRef(router, 200);
+ ConnEnd srcPt200(Point(387.924, 763.557), 15);
+ connRef200->setSourceEndpoint(srcPt200);
+ ConnEnd dstPt200(Point(437.924, 763.557), 15);
+ connRef200->setDestEndpoint(dstPt200);
+ connRef200->setRoutingType((ConnType)2);
+
+ ConnRef *connRef201 = new ConnRef(router, 201);
+ ConnEnd srcPt201(Point(507.924, 763.557), 15);
+ connRef201->setSourceEndpoint(srcPt201);
+ ConnEnd dstPt201(Point(557.924, 763.557), 15);
+ connRef201->setDestEndpoint(dstPt201);
+ connRef201->setRoutingType((ConnType)2);
+
+ ConnRef *connRef202 = new ConnRef(router, 202);
+ ConnEnd srcPt202(Point(627.924, 763.557), 15);
+ connRef202->setSourceEndpoint(srcPt202);
+ ConnEnd dstPt202(Point(677.924, 763.557), 15);
+ connRef202->setDestEndpoint(dstPt202);
+ connRef202->setRoutingType((ConnType)2);
+
+ ConnRef *connRef148 = new ConnRef(router, 148);
+ ConnEnd srcPt148(Point(1018.92, -60.6578), 15);
+ connRef148->setSourceEndpoint(srcPt148);
+ ConnEnd dstPt148(Point(1068.92, -60.6578), 15);
+ connRef148->setDestEndpoint(dstPt148);
+ connRef148->setRoutingType((ConnType)2);
+
+ ConnRef *connRef203 = new ConnRef(router, 203);
+ ConnEnd srcPt203(Point(507.924, 903.057), 15);
+ connRef203->setSourceEndpoint(srcPt203);
+ ConnEnd dstPt203(Point(557.924, 903.057), 15);
+ connRef203->setDestEndpoint(dstPt203);
+ connRef203->setRoutingType((ConnType)2);
+
+ ConnRef *connRef204 = new ConnRef(router, 204);
+ ConnEnd srcPt204(Point(627.924, 903.057), 15);
+ connRef204->setSourceEndpoint(srcPt204);
+ ConnEnd dstPt204(Point(677.924, 903.057), 15);
+ connRef204->setDestEndpoint(dstPt204);
+ connRef204->setRoutingType((ConnType)2);
+
+ ConnRef *connRef205 = new ConnRef(router, 205);
+ ConnEnd srcPt205(Point(387.924, 161.557), 15);
+ connRef205->setSourceEndpoint(srcPt205);
+ ConnEnd dstPt205(Point(437.924, 161.557), 15);
+ connRef205->setDestEndpoint(dstPt205);
+ connRef205->setRoutingType((ConnType)2);
+
+ ConnRef *connRef206 = new ConnRef(router, 206);
+ ConnEnd srcPt206(Point(387.924, 27.3422), 15);
+ connRef206->setSourceEndpoint(srcPt206);
+ ConnEnd dstPt206(Point(437.924, 27.3422), 15);
+ connRef206->setDestEndpoint(dstPt206);
+ connRef206->setRoutingType((ConnType)2);
+
+ ConnRef *connRef207 = new ConnRef(router, 207);
+ ConnEnd srcPt207(Point(507.924, 45.8422), 15);
+ connRef207->setSourceEndpoint(srcPt207);
+ ConnEnd dstPt207(Point(557.924, 54.8422), 15);
+ connRef207->setDestEndpoint(dstPt207);
+ connRef207->setRoutingType((ConnType)2);
+
+ ConnRef *connRef176 = new ConnRef(router, 176);
+ ConnEnd srcPt176(Point(77.9242, 161.557), 15);
+ connRef176->setSourceEndpoint(srcPt176);
+ ConnEnd dstPt176(Point(77.9242, 357.557), 15);
+ connRef176->setDestEndpoint(dstPt176);
+ connRef176->setRoutingType((ConnType)2);
+
+ ConnRef *connRef177 = new ConnRef(router, 177);
+ ConnEnd srcPt177(Point(557.924, 763.557), 15);
+ connRef177->setSourceEndpoint(srcPt177);
+ ConnEnd dstPt177(Point(607.924, 763.557), 15);
+ connRef177->setDestEndpoint(dstPt177);
+ connRef177->setRoutingType((ConnType)2);
+
+ ConnRef *connRef189 = new ConnRef(router, 189);
+ ConnEnd srcPt189(Point(747.924, -60.6578), 15);
+ connRef189->setSourceEndpoint(srcPt189);
+ ConnEnd dstPt189(Point(797.924, -60.6578), 15);
+ connRef189->setDestEndpoint(dstPt189);
+ connRef189->setRoutingType((ConnType)2);
+
+ ConnRef *connRef190 = new ConnRef(router, 190);
+ ConnEnd srcPt190(Point(147.924, 34.8422), 15);
+ connRef190->setSourceEndpoint(srcPt190);
+ ConnEnd dstPt190(Point(197.924, 161.557), 15);
+ connRef190->setDestEndpoint(dstPt190);
+ connRef190->setRoutingType((ConnType)2);
+
+ ConnRef *connRef174 = new ConnRef(router, 174);
+ ConnEnd srcPt174(Point(437.924, 161.557), 15);
+ connRef174->setSourceEndpoint(srcPt174);
+ ConnEnd dstPt174(Point(727.924, 161.557), 15);
+ connRef174->setDestEndpoint(dstPt174);
+ connRef174->setRoutingType((ConnType)2);
+
+ ConnRef *connRef175 = new ConnRef(router, 175);
+ ConnEnd srcPt175(Point(77.9242, 161.557), 15);
+ connRef175->setSourceEndpoint(srcPt175);
+ ConnEnd dstPt175(Point(127.924, 161.557), 15);
+ connRef175->setDestEndpoint(dstPt175);
+ connRef175->setRoutingType((ConnType)2);
+
+ ConnRef *connRef170 = new ConnRef(router, 170);
+ ConnEnd srcPt170(Point(1018.92, 161.557), 15);
+ connRef170->setSourceEndpoint(srcPt170);
+ ConnEnd dstPt170(Point(1068.92, 152.342), 15);
+ connRef170->setDestEndpoint(dstPt170);
+ connRef170->setRoutingType((ConnType)2);
+
+ ConnRef *connRef171 = new ConnRef(router, 171);
+ ConnEnd srcPt171(Point(1018.92, 161.557), 15);
+ connRef171->setSourceEndpoint(srcPt171);
+ ConnEnd dstPt171(Point(1068.92, 60.3422), 15);
+ connRef171->setDestEndpoint(dstPt171);
+ connRef171->setRoutingType((ConnType)2);
+
+ ConnRef *connRef166 = new ConnRef(router, 166);
+ ConnEnd srcPt166(Point(557.924, 527.557), 15);
+ connRef166->setSourceEndpoint(srcPt166);
+ ConnEnd dstPt166(Point(607.924, 527.557), 15);
+ connRef166->setDestEndpoint(dstPt166);
+ connRef166->setRoutingType((ConnType)2);
+
+ ConnRef *connRef167 = new ConnRef(router, 167);
+ ConnEnd srcPt167(Point(797.924, 343.557), 15);
+ connRef167->setSourceEndpoint(srcPt167);
+ ConnEnd dstPt167(Point(847.924, 343.557), 15);
+ connRef167->setDestEndpoint(dstPt167);
+ connRef167->setRoutingType((ConnType)2);
+
+ ConnRef *connRef168 = new ConnRef(router, 168);
+ ConnEnd srcPt168(Point(797.924, 343.557), 15);
+ connRef168->setSourceEndpoint(srcPt168);
+ ConnEnd dstPt168(Point(847.924, 435.557), 15);
+ connRef168->setDestEndpoint(dstPt168);
+ connRef168->setRoutingType((ConnType)2);
+
+ ConnRef *connRef169 = new ConnRef(router, 169);
+ ConnEnd srcPt169(Point(1018.92, 435.557), 15);
+ connRef169->setSourceEndpoint(srcPt169);
+ ConnEnd dstPt169(Point(1068.92, 388.557), 15);
+ connRef169->setDestEndpoint(dstPt169);
+ connRef169->setRoutingType((ConnType)2);
+
+ ConnRef *connRef160 = new ConnRef(router, 160);
+ ConnEnd srcPt160(Point(317.924, 161.557), 15);
+ connRef160->setSourceEndpoint(srcPt160);
+ ConnEnd dstPt160(Point(727.924, -60.6578), 15);
+ connRef160->setDestEndpoint(dstPt160);
+ connRef160->setRoutingType((ConnType)2);
+
+ ConnRef *connRef161 = new ConnRef(router, 161);
+ ConnEnd srcPt161(Point(317.924, 161.557), 15);
+ connRef161->setSourceEndpoint(srcPt161);
+ ConnEnd dstPt161(Point(367.924, 161.557), 15);
+ connRef161->setDestEndpoint(dstPt161);
+ connRef161->setRoutingType((ConnType)2);
+
+ ConnRef *connRef186 = new ConnRef(router, 186);
+ ConnEnd srcPt186(Point(77.9242, 34.8422), 15);
+ connRef186->setSourceEndpoint(srcPt186);
+ ConnEnd dstPt186(Point(127.924, 34.8422), 15);
+ connRef186->setDestEndpoint(dstPt186);
+ connRef186->setRoutingType((ConnType)2);
+
+ ConnRef *connRef187 = new ConnRef(router, 187);
+ ConnEnd srcPt187(Point(437.924, 527.557), 15);
+ connRef187->setSourceEndpoint(srcPt187);
+ ConnEnd dstPt187(Point(487.924, 527.557), 15);
+ connRef187->setDestEndpoint(dstPt187);
+ connRef187->setRoutingType((ConnType)2);
+
+ ConnRef *connRef188 = new ConnRef(router, 188);
+ ConnEnd srcPt188(Point(77.9242, 619.557), 15);
+ connRef188->setSourceEndpoint(srcPt188);
+ ConnEnd dstPt188(Point(127.924, 619.557), 15);
+ connRef188->setDestEndpoint(dstPt188);
+ connRef188->setRoutingType((ConnType)2);
+
+ ConnRef *connRef184 = new ConnRef(router, 184);
+ ConnEnd srcPt184(Point(677.924, 343.557), 15);
+ connRef184->setSourceEndpoint(srcPt184);
+ ConnEnd dstPt184(Point(727.924, 343.557), 15);
+ connRef184->setDestEndpoint(dstPt184);
+ connRef184->setRoutingType((ConnType)2);
+
+ ConnRef *connRef185 = new ConnRef(router, 185);
+ ConnEnd srcPt185(Point(797.924, 161.557), 15);
+ connRef185->setSourceEndpoint(srcPt185);
+ ConnEnd dstPt185(Point(847.924, 161.557), 15);
+ connRef185->setDestEndpoint(dstPt185);
+ connRef185->setRoutingType((ConnType)2);
+
+ ConnRef *connRef208 = new ConnRef(router, 208);
+ ConnEnd srcPt208(Point(627.924, 45.8422), 15);
+ connRef208->setSourceEndpoint(srcPt208);
+ ConnEnd dstPt208(Point(677.924, 54.8422), 15);
+ connRef208->setDestEndpoint(dstPt208);
+ connRef208->setRoutingType((ConnType)2);
+
+ ConnRef *connRef209 = new ConnRef(router, 209);
+ ConnEnd srcPt209(Point(747.924, 574.057), 15);
+ connRef209->setSourceEndpoint(srcPt209);
+ ConnEnd dstPt209(Point(797.924, 574.057), 15);
+ connRef209->setDestEndpoint(dstPt209);
+ connRef209->setRoutingType((ConnType)2);
+
+ ConnRef *connRef210 = new ConnRef(router, 210);
+ ConnEnd srcPt210(Point(507.924, 527.557), 15);
+ connRef210->setSourceEndpoint(srcPt210);
+ ConnEnd dstPt210(Point(557.924, 527.557), 15);
+ connRef210->setDestEndpoint(dstPt210);
+ connRef210->setRoutingType((ConnType)2);
+
+ ConnRef *connRef211 = new ConnRef(router, 211);
+ ConnEnd srcPt211(Point(507.924, 435.557), 15);
+ connRef211->setSourceEndpoint(srcPt211);
+ ConnEnd dstPt211(Point(557.924, 435.557), 15);
+ connRef211->setDestEndpoint(dstPt211);
+ connRef211->setRoutingType((ConnType)2);
+
+ ConnRef *connRef212 = new ConnRef(router, 212);
+ ConnEnd srcPt212(Point(627.924, 527.557), 15);
+ connRef212->setSourceEndpoint(srcPt212);
+ ConnEnd dstPt212(Point(677.924, 527.557), 15);
+ connRef212->setDestEndpoint(dstPt212);
+ connRef212->setRoutingType((ConnType)2);
+
+ ConnRef *connRef213 = new ConnRef(router, 213);
+ ConnEnd srcPt213(Point(627.924, 435.557), 15);
+ connRef213->setSourceEndpoint(srcPt213);
+ ConnEnd dstPt213(Point(677.924, 435.557), 15);
+ connRef213->setDestEndpoint(dstPt213);
+ connRef213->setRoutingType((ConnType)2);
+
+ ConnRef *connRef214 = new ConnRef(router, 214);
+ ConnEnd srcPt214(Point(867.924, 343.557), 15);
+ connRef214->setSourceEndpoint(srcPt214);
+ ConnEnd dstPt214(Point(917.924, 343.557), 15);
+ connRef214->setDestEndpoint(dstPt214);
+ connRef214->setRoutingType((ConnType)2);
+
+ ConnRef *connRef215 = new ConnRef(router, 215);
+ ConnEnd srcPt215(Point(867.924, 435.557), 15);
+ connRef215->setSourceEndpoint(srcPt215);
+ ConnEnd dstPt215(Point(917.924, 435.557), 15);
+ connRef215->setDestEndpoint(dstPt215);
+ connRef215->setRoutingType((ConnType)2);
+
+ ConnRef *connRef216 = new ConnRef(router, 216);
+ ConnEnd srcPt216(Point(867.924, 161.557), 15);
+ connRef216->setSourceEndpoint(srcPt216);
+ ConnEnd dstPt216(Point(917.924, 161.557), 15);
+ connRef216->setDestEndpoint(dstPt216);
+ connRef216->setRoutingType((ConnType)2);
+
+ ConnRef *connRef217 = new ConnRef(router, 217);
+ ConnEnd srcPt217(Point(747.924, 343.557), 15);
+ connRef217->setSourceEndpoint(srcPt217);
+ ConnEnd dstPt217(Point(797.924, 343.557), 15);
+ connRef217->setDestEndpoint(dstPt217);
+ connRef217->setRoutingType((ConnType)2);
+
+ ConnRef *connRef218 = new ConnRef(router, 218);
+ ConnEnd srcPt218(Point(1088.92, 388.557), 15);
+ connRef218->setSourceEndpoint(srcPt218);
+ ConnEnd dstPt218(Point(1138.92, 435.557), 15);
+ connRef218->setDestEndpoint(dstPt218);
+ connRef218->setRoutingType((ConnType)2);
+
+ ConnRef *connRef219 = new ConnRef(router, 219);
+ ConnEnd srcPt219(Point(1208.92, 388.557), 15);
+ connRef219->setSourceEndpoint(srcPt219);
+ ConnEnd dstPt219(Point(1258.92, 435.557), 15);
+ connRef219->setDestEndpoint(dstPt219);
+ connRef219->setRoutingType((ConnType)2);
+
+ ConnRef *connRef220 = new ConnRef(router, 220);
+ ConnEnd srcPt220(Point(1088.92, 152.342), 15);
+ connRef220->setSourceEndpoint(srcPt220);
+ ConnEnd dstPt220(Point(1138.92, 161.557), 15);
+ connRef220->setDestEndpoint(dstPt220);
+ connRef220->setRoutingType((ConnType)2);
+
+ ConnRef *connRef221 = new ConnRef(router, 221);
+ ConnEnd srcPt221(Point(1088.92, 60.3422), 15);
+ connRef221->setSourceEndpoint(srcPt221);
+ ConnEnd dstPt221(Point(1138.92, 60.3422), 15);
+ connRef221->setDestEndpoint(dstPt221);
+ connRef221->setRoutingType((ConnType)2);
+
+ ConnRef *connRef222 = new ConnRef(router, 222);
+ ConnEnd srcPt222(Point(1208.92, 152.342), 15);
+ connRef222->setSourceEndpoint(srcPt222);
+ ConnEnd dstPt222(Point(1258.92, 161.557), 15);
+ connRef222->setDestEndpoint(dstPt222);
+ connRef222->setRoutingType((ConnType)2);
+
+ ConnRef *connRef223 = new ConnRef(router, 223);
+ ConnEnd srcPt223(Point(1088.92, -60.6578), 15);
+ connRef223->setSourceEndpoint(srcPt223);
+ ConnEnd dstPt223(Point(1138.92, -60.6578), 15);
+ connRef223->setDestEndpoint(dstPt223);
+ connRef223->setRoutingType((ConnType)2);
+
+ ConnRef *connRef224 = new ConnRef(router, 224);
+ ConnEnd srcPt224(Point(747.924, 161.557), 15);
+ connRef224->setSourceEndpoint(srcPt224);
+ ConnEnd dstPt224(Point(797.924, 161.557), 15);
+ connRef224->setDestEndpoint(dstPt224);
+ connRef224->setRoutingType((ConnType)2);
+
+ ConnRef *connRef225 = new ConnRef(router, 225);
+ ConnEnd srcPt225(Point(747.924, 860.057), 15);
+ connRef225->setSourceEndpoint(srcPt225);
+ ConnEnd dstPt225(Point(797.924, 860.057), 15);
+ connRef225->setDestEndpoint(dstPt225);
+ connRef225->setRoutingType((ConnType)2);
+
+ ConnRef *connRef226 = new ConnRef(router, 226);
+ ConnEnd srcPt226(Point(737.924, -110.658), 15);
+ connRef226->setSourceEndpoint(srcPt226);
+ ConnEnd dstPt226(Point(737.924, -60.6578), 15);
+ connRef226->setDestEndpoint(dstPt226);
+ connRef226->setRoutingType((ConnType)2);
+
+ ConnRef *connRef227 = new ConnRef(router, 227);
+ ConnEnd srcPt227(Point(137.924, -15.1578), 15);
+ connRef227->setSourceEndpoint(srcPt227);
+ ConnEnd dstPt227(Point(137.924, 34.8422), 15);
+ connRef227->setDestEndpoint(dstPt227);
+ connRef227->setRoutingType((ConnType)2);
+
+ ConnRef *connRef228 = new ConnRef(router, 228);
+ ConnEnd srcPt228(Point(137.924, 111.557), 15);
+ connRef228->setSourceEndpoint(srcPt228);
+ ConnEnd dstPt228(Point(137.924, 161.557), 15);
+ connRef228->setDestEndpoint(dstPt228);
+ connRef228->setRoutingType((ConnType)2);
+
+ ConnRef *connRef149 = new ConnRef(router, 149);
+ ConnEnd srcPt149(Point(1138.92, 161.557), 15);
+ connRef149->setSourceEndpoint(srcPt149);
+ ConnEnd dstPt149(Point(1188.92, 152.342), 15);
+ connRef149->setDestEndpoint(dstPt149);
+ connRef149->setRoutingType((ConnType)2);
+
+ ConnRef *connRef164 = new ConnRef(router, 164);
+ ConnEnd srcPt164(Point(437.924, 763.557), 15);
+ connRef164->setSourceEndpoint(srcPt164);
+ ConnEnd dstPt164(Point(487.924, 763.557), 15);
+ connRef164->setDestEndpoint(dstPt164);
+ connRef164->setRoutingType((ConnType)2);
+
+ ConnRef *connRef165 = new ConnRef(router, 165);
+ ConnEnd srcPt165(Point(437.924, 763.557), 15);
+ connRef165->setSourceEndpoint(srcPt165);
+ ConnEnd dstPt165(Point(727.924, 860.057), 15);
+ connRef165->setDestEndpoint(dstPt165);
+ connRef165->setRoutingType((ConnType)2);
+
+ ConnRef *connRef182 = new ConnRef(router, 182);
+ ConnEnd srcPt182(Point(77.9242, 763.557), 15);
+ connRef182->setSourceEndpoint(srcPt182);
+ ConnEnd dstPt182(Point(127.924, 763.557), 15);
+ connRef182->setDestEndpoint(dstPt182);
+ connRef182->setRoutingType((ConnType)2);
+
+ ConnRef *connRef183 = new ConnRef(router, 183);
+ ConnEnd srcPt183(Point(197.924, 315.557), 15);
+ connRef183->setSourceEndpoint(srcPt183);
+ ConnEnd dstPt183(Point(247.924, 315.557), 15);
+ connRef183->setDestEndpoint(dstPt183);
+ connRef183->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/lineSegWrapperCrash6");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash7.cpp b/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash7.cpp
new file mode 100644
index 0000000..40f5d4a
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash7.cpp
@@ -0,0 +1,1884 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 0);
+
+ Polygon poly51(4);
+ poly51.ps[0] = Point(1038.92, 323.557);
+ poly51.ps[1] = Point(1038.92, 363.557);
+ poly51.ps[2] = Point(998.924, 363.557);
+ poly51.ps[3] = Point(998.924, 323.557);
+ new ShapeRef(router, poly51, 51);
+
+ Polygon poly50(4);
+ poly50.ps[0] = Point(272.5, -82.1578);
+ poly50.ps[1] = Point(272.5, -47.1578);
+ poly50.ps[2] = Point(35.5, -47.1578);
+ poly50.ps[3] = Point(35.5, -82.1578);
+ new ShapeRef(router, poly50, 50);
+
+ Polygon poly49(4);
+ poly49.ps[0] = Point(45.9242, 169.75);
+ poly49.ps[1] = Point(45.9242, 334.75);
+ poly49.ps[2] = Point(-242.076, 334.75);
+ poly49.ps[3] = Point(-242.076, 169.75);
+ new ShapeRef(router, poly49, 49);
+
+ Polygon poly48(4);
+ poly48.ps[0] = Point(97.9242, 743.557);
+ poly48.ps[1] = Point(97.9242, 783.557);
+ poly48.ps[2] = Point(57.9242, 783.557);
+ poly48.ps[3] = Point(57.9242, 743.557);
+ new ShapeRef(router, poly48, 48);
+
+ Polygon poly74(4);
+ poly74.ps[0] = Point(147.924, 609.557);
+ poly74.ps[1] = Point(147.924, 629.557);
+ poly74.ps[2] = Point(127.924, 629.557);
+ poly74.ps[3] = Point(127.924, 609.557);
+ new ShapeRef(router, poly74, 74);
+
+ Polygon poly47(4);
+ poly47.ps[0] = Point(697.924, 271.557);
+ poly47.ps[1] = Point(697.924, 311.557);
+ poly47.ps[2] = Point(657.924, 311.557);
+ poly47.ps[3] = Point(657.924, 271.557);
+ new ShapeRef(router, poly47, 47);
+
+ Polygon poly136(4);
+ poly136.ps[0] = Point(765.924, 273.557);
+ poly136.ps[1] = Point(765.924, 313.557);
+ poly136.ps[2] = Point(709.924, 313.557);
+ poly136.ps[3] = Point(709.924, 273.557);
+ new ShapeRef(router, poly136, 136);
+
+ Polygon poly46(4);
+ poly46.ps[0] = Point(577.924, 415.557);
+ poly46.ps[1] = Point(577.924, 455.557);
+ poly46.ps[2] = Point(537.924, 455.557);
+ poly46.ps[3] = Point(537.924, 415.557);
+ new ShapeRef(router, poly46, 46);
+
+ Polygon poly80(4);
+ poly80.ps[0] = Point(507.924, 753.557);
+ poly80.ps[1] = Point(507.924, 773.557);
+ poly80.ps[2] = Point(487.924, 773.557);
+ poly80.ps[3] = Point(487.924, 753.557);
+ new ShapeRef(router, poly80, 80);
+
+ Polygon poly45(4);
+ poly45.ps[0] = Point(577.924, 34.8422);
+ poly45.ps[1] = Point(577.924, 74.8422);
+ poly45.ps[2] = Point(537.924, 74.8422);
+ poly45.ps[3] = Point(537.924, 34.8422);
+ new ShapeRef(router, poly45, 45);
+
+ Polygon poly76(4);
+ poly76.ps[0] = Point(147.924, 753.557);
+ poly76.ps[1] = Point(147.924, 773.557);
+ poly76.ps[2] = Point(127.924, 773.557);
+ poly76.ps[3] = Point(127.924, 753.557);
+ new ShapeRef(router, poly76, 76);
+
+ Polygon poly105(4);
+ poly105.ps[0] = Point(747.924, 850.057);
+ poly105.ps[1] = Point(747.924, 870.057);
+ poly105.ps[2] = Point(727.924, 870.057);
+ poly105.ps[3] = Point(727.924, 850.057);
+ new ShapeRef(router, poly105, 105);
+
+ Polygon poly44(4);
+ poly44.ps[0] = Point(97.9242, 507.557);
+ poly44.ps[1] = Point(97.9242, 547.557);
+ poly44.ps[2] = Point(57.9242, 547.557);
+ poly44.ps[3] = Point(57.9242, 507.557);
+ new ShapeRef(router, poly44, 44);
+
+ Polygon poly43(4);
+ poly43.ps[0] = Point(1038.92, 1.84222);
+ poly43.ps[1] = Point(1038.92, 41.8422);
+ poly43.ps[2] = Point(998.924, 41.8422);
+ poly43.ps[3] = Point(998.924, 1.84222);
+ new ShapeRef(router, poly43, 43);
+
+ Polygon poly42(4);
+ poly42.ps[0] = Point(697.924, 415.557);
+ poly42.ps[1] = Point(697.924, 455.557);
+ poly42.ps[2] = Point(657.924, 455.557);
+ poly42.ps[3] = Point(657.924, 415.557);
+ new ShapeRef(router, poly42, 42);
+
+ Polygon poly41(4);
+ poly41.ps[0] = Point(577.924, 743.557);
+ poly41.ps[1] = Point(577.924, 783.557);
+ poly41.ps[2] = Point(537.924, 783.557);
+ poly41.ps[3] = Point(537.924, 743.557);
+ new ShapeRef(router, poly41, 41);
+
+ Polygon poly68(4);
+ poly68.ps[0] = Point(147.924, 151.557);
+ poly68.ps[1] = Point(147.924, 171.557);
+ poly68.ps[2] = Point(127.924, 171.557);
+ poly68.ps[3] = Point(127.924, 151.557);
+ new ShapeRef(router, poly68, 68);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(1278.92, -22.1578);
+ poly3.ps[1] = Point(1278.92, 17.8422);
+ poly3.ps[2] = Point(1238.92, 17.8422);
+ poly3.ps[3] = Point(1238.92, -22.1578);
+ new ShapeRef(router, poly3, 3);
+
+ Polygon poly71(4);
+ poly71.ps[0] = Point(267.924, 305.557);
+ poly71.ps[1] = Point(267.924, 325.557);
+ poly71.ps[2] = Point(247.924, 325.557);
+ poly71.ps[3] = Point(247.924, 305.557);
+ new ShapeRef(router, poly71, 71);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(1371.92, 29.8422);
+ poly4.ps[1] = Point(1371.92, 69.8422);
+ poly4.ps[2] = Point(1331.92, 69.8422);
+ poly4.ps[3] = Point(1331.92, 29.8422);
+ new ShapeRef(router, poly4, 4);
+
+ Polygon poly56(4);
+ poly56.ps[0] = Point(457.924, -44.6578);
+ poly56.ps[1] = Point(457.924, -4.65778);
+ poly56.ps[2] = Point(417.924, -4.65778);
+ poly56.ps[3] = Point(417.924, -44.6578);
+ new ShapeRef(router, poly56, 56);
+
+ Polygon poly40(4);
+ poly40.ps[0] = Point(97.9242, 141.557);
+ poly40.ps[1] = Point(97.9242, 181.557);
+ poly40.ps[2] = Point(57.9242, 181.557);
+ poly40.ps[3] = Point(57.9242, 141.557);
+ new ShapeRef(router, poly40, 40);
+
+ Polygon poly60(4);
+ poly60.ps[0] = Point(937.924, 1.84222);
+ poly60.ps[1] = Point(937.924, 41.8422);
+ poly60.ps[2] = Point(897.924, 41.8422);
+ poly60.ps[3] = Point(897.924, 1.84222);
+ new ShapeRef(router, poly60, 60);
+
+ Polygon poly39(4);
+ poly39.ps[0] = Point(457.924, 141.557);
+ poly39.ps[1] = Point(457.924, 181.557);
+ poly39.ps[2] = Point(417.924, 181.557);
+ poly39.ps[3] = Point(417.924, 141.557);
+ new ShapeRef(router, poly39, 39);
+
+ Polygon poly38(4);
+ poly38.ps[0] = Point(217.924, 507.557);
+ poly38.ps[1] = Point(217.924, 547.557);
+ poly38.ps[2] = Point(177.924, 547.557);
+ poly38.ps[3] = Point(177.924, 507.557);
+ new ShapeRef(router, poly38, 38);
+
+ Polygon poly77(4);
+ poly77.ps[0] = Point(267.924, 753.557);
+ poly77.ps[1] = Point(267.924, 773.557);
+ poly77.ps[2] = Point(247.924, 773.557);
+ poly77.ps[3] = Point(247.924, 753.557);
+ new ShapeRef(router, poly77, 77);
+
+ Polygon poly37(4);
+ poly37.ps[0] = Point(457.924, 607.557);
+ poly37.ps[1] = Point(457.924, 647.557);
+ poly37.ps[2] = Point(417.924, 647.557);
+ poly37.ps[3] = Point(417.924, 607.557);
+ new ShapeRef(router, poly37, 37);
+
+ Polygon poly116(4);
+ poly116.ps[0] = Point(165.924, 693.557);
+ poly116.ps[1] = Point(165.924, 733.557);
+ poly116.ps[2] = Point(109.924, 733.557);
+ poly116.ps[3] = Point(109.924, 693.557);
+ new ShapeRef(router, poly116, 116);
+
+ Polygon poly119(4);
+ poly119.ps[0] = Point(405.924, 693.557);
+ poly119.ps[1] = Point(405.924, 733.557);
+ poly119.ps[2] = Point(349.924, 733.557);
+ poly119.ps[3] = Point(349.924, 693.557);
+ new ShapeRef(router, poly119, 119);
+
+ Polygon poly117(4);
+ poly117.ps[0] = Point(285.924, 693.557);
+ poly117.ps[1] = Point(285.924, 733.557);
+ poly117.ps[2] = Point(229.924, 733.557);
+ poly117.ps[3] = Point(229.924, 693.557);
+ new ShapeRef(router, poly117, 117);
+
+ Polygon poly102(4);
+ poly102.ps[0] = Point(1088.92, -70.6578);
+ poly102.ps[1] = Point(1088.92, -50.6578);
+ poly102.ps[2] = Point(1068.92, -50.6578);
+ poly102.ps[3] = Point(1068.92, -70.6578);
+ new ShapeRef(router, poly102, 102);
+
+ Polygon poly118(4);
+ poly118.ps[0] = Point(405.924, 557.557);
+ poly118.ps[1] = Point(405.924, 597.557);
+ poly118.ps[2] = Point(349.924, 597.557);
+ poly118.ps[3] = Point(349.924, 557.557);
+ new ShapeRef(router, poly118, 118);
+
+ Polygon poly130(4);
+ poly130.ps[0] = Point(525.924, 365.557);
+ poly130.ps[1] = Point(525.924, 405.557);
+ poly130.ps[2] = Point(469.924, 405.557);
+ poly130.ps[3] = Point(469.924, 365.557);
+ new ShapeRef(router, poly130, 130);
+
+ Polygon poly122(4);
+ poly122.ps[0] = Point(525.924, 833.057);
+ poly122.ps[1] = Point(525.924, 873.057);
+ poly122.ps[2] = Point(469.924, 873.057);
+ poly122.ps[3] = Point(469.924, 833.057);
+ new ShapeRef(router, poly122, 122);
+
+ Polygon poly123(4);
+ poly123.ps[0] = Point(645.924, 833.057);
+ poly123.ps[1] = Point(645.924, 873.057);
+ poly123.ps[2] = Point(589.924, 873.057);
+ poly123.ps[3] = Point(589.924, 833.057);
+ new ShapeRef(router, poly123, 123);
+
+ Polygon poly124(4);
+ poly124.ps[0] = Point(405.924, 91.5565);
+ poly124.ps[1] = Point(405.924, 131.557);
+ poly124.ps[2] = Point(349.924, 131.557);
+ poly124.ps[3] = Point(349.924, 91.5565);
+ new ShapeRef(router, poly124, 124);
+
+ Polygon poly146(4);
+ poly146.ps[0] = Point(45.9242, 232.5);
+ poly146.ps[1] = Point(45.9242, 272.5);
+ poly146.ps[2] = Point(-14.0758, 272.5);
+ poly146.ps[3] = Point(-14.0758, 232.5);
+ new ShapeRef(router, poly146, 146);
+
+ Polygon poly134(4);
+ poly134.ps[0] = Point(885.924, 365.557);
+ poly134.ps[1] = Point(885.924, 405.557);
+ poly134.ps[2] = Point(829.924, 405.557);
+ poly134.ps[3] = Point(829.924, 365.557);
+ new ShapeRef(router, poly134, 134);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(1278.92, -80.6578);
+ poly7.ps[1] = Point(1278.92, -40.6578);
+ poly7.ps[2] = Point(1238.92, -40.6578);
+ poly7.ps[3] = Point(1238.92, -80.6578);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly98(4);
+ poly98.ps[0] = Point(1208.92, 378.557);
+ poly98.ps[1] = Point(1208.92, 398.557);
+ poly98.ps[2] = Point(1188.92, 398.557);
+ poly98.ps[3] = Point(1188.92, 378.557);
+ new ShapeRef(router, poly98, 98);
+
+ Polygon poly139(4);
+ poly139.ps[0] = Point(1106.92, 82.3422);
+ poly139.ps[1] = Point(1106.92, 122.342);
+ poly139.ps[2] = Point(1050.92, 122.342);
+ poly139.ps[3] = Point(1050.92, 82.3422);
+ new ShapeRef(router, poly139, 139);
+
+ Polygon poly140(4);
+ poly140.ps[0] = Point(1106.92, -9.65778);
+ poly140.ps[1] = Point(1106.92, 30.3422);
+ poly140.ps[2] = Point(1050.92, 30.3422);
+ poly140.ps[3] = Point(1050.92, -9.65778);
+ new ShapeRef(router, poly140, 140);
+
+ Polygon poly91(4);
+ poly91.ps[0] = Point(627.924, 517.557);
+ poly91.ps[1] = Point(627.924, 537.557);
+ poly91.ps[2] = Point(607.924, 537.557);
+ poly91.ps[3] = Point(607.924, 517.557);
+ new ShapeRef(router, poly91, 91);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(1158.92, -80.6578);
+ poly8.ps[1] = Point(1158.92, -40.6578);
+ poly8.ps[2] = Point(1118.92, -40.6578);
+ poly8.ps[3] = Point(1118.92, -80.6578);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly87(4);
+ poly87.ps[0] = Point(627.924, 35.8422);
+ poly87.ps[1] = Point(627.924, 55.8422);
+ poly87.ps[2] = Point(607.924, 55.8422);
+ poly87.ps[3] = Point(607.924, 35.8422);
+ new ShapeRef(router, poly87, 87);
+
+ Polygon poly72(4);
+ poly72.ps[0] = Point(87.9242, 357.557);
+ poly72.ps[1] = Point(87.9242, 377.557);
+ poly72.ps[2] = Point(67.9242, 377.557);
+ poly72.ps[3] = Point(67.9242, 357.557);
+ new ShapeRef(router, poly72, 72);
+
+ Polygon poly94(4);
+ poly94.ps[0] = Point(867.924, 425.557);
+ poly94.ps[1] = Point(867.924, 445.557);
+ poly94.ps[2] = Point(847.924, 445.557);
+ poly94.ps[3] = Point(847.924, 425.557);
+ new ShapeRef(router, poly94, 94);
+
+ Polygon poly92(4);
+ poly92.ps[0] = Point(627.924, 425.557);
+ poly92.ps[1] = Point(627.924, 445.557);
+ poly92.ps[2] = Point(607.924, 445.557);
+ poly92.ps[3] = Point(607.924, 425.557);
+ new ShapeRef(router, poly92, 92);
+
+ Polygon poly81(4);
+ poly81.ps[0] = Point(627.924, 753.557);
+ poly81.ps[1] = Point(627.924, 773.557);
+ poly81.ps[2] = Point(607.924, 773.557);
+ poly81.ps[3] = Point(607.924, 753.557);
+ new ShapeRef(router, poly81, 81);
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(1371.92, -80.6578);
+ poly6.ps[1] = Point(1371.92, -40.6578);
+ poly6.ps[2] = Point(1331.92, -40.6578);
+ poly6.ps[3] = Point(1331.92, -80.6578);
+ new ShapeRef(router, poly6, 6);
+
+ Polygon poly97(4);
+ poly97.ps[0] = Point(1088.92, 378.557);
+ poly97.ps[1] = Point(1088.92, 398.557);
+ poly97.ps[2] = Point(1068.92, 398.557);
+ poly97.ps[3] = Point(1068.92, 378.557);
+ new ShapeRef(router, poly97, 97);
+
+ Polygon poly36(4);
+ poly36.ps[0] = Point(697.924, 507.557);
+ poly36.ps[1] = Point(697.924, 547.557);
+ poly36.ps[2] = Point(657.924, 547.557);
+ poly36.ps[3] = Point(657.924, 507.557);
+ new ShapeRef(router, poly36, 36);
+
+ Polygon poly35(4);
+ poly35.ps[0] = Point(1158.92, 40.3422);
+ poly35.ps[1] = Point(1158.92, 80.3422);
+ poly35.ps[2] = Point(1118.92, 80.3422);
+ poly35.ps[3] = Point(1118.92, 40.3422);
+ new ShapeRef(router, poly35, 35);
+
+ Polygon poly125(4);
+ poly125.ps[0] = Point(405.924, -42.6578);
+ poly125.ps[1] = Point(405.924, -2.65778);
+ poly125.ps[2] = Point(349.924, -2.65778);
+ poly125.ps[3] = Point(349.924, -42.6578);
+ new ShapeRef(router, poly125, 125);
+
+ Polygon poly126(4);
+ poly126.ps[0] = Point(525.924, -24.1578);
+ poly126.ps[1] = Point(525.924, 15.8422);
+ poly126.ps[2] = Point(469.924, 15.8422);
+ poly126.ps[3] = Point(469.924, -24.1578);
+ new ShapeRef(router, poly126, 126);
+
+ Polygon poly127(4);
+ poly127.ps[0] = Point(645.924, -24.1578);
+ poly127.ps[1] = Point(645.924, 15.8422);
+ poly127.ps[2] = Point(589.924, 15.8422);
+ poly127.ps[3] = Point(589.924, -24.1578);
+ new ShapeRef(router, poly127, 127);
+
+ Polygon poly128(4);
+ poly128.ps[0] = Point(765.924, 504.057);
+ poly128.ps[1] = Point(765.924, 544.057);
+ poly128.ps[2] = Point(709.924, 544.057);
+ poly128.ps[3] = Point(709.924, 504.057);
+ new ShapeRef(router, poly128, 128);
+
+ Polygon poly129(4);
+ poly129.ps[0] = Point(525.924, 457.557);
+ poly129.ps[1] = Point(525.924, 497.557);
+ poly129.ps[2] = Point(469.924, 497.557);
+ poly129.ps[3] = Point(469.924, 457.557);
+ new ShapeRef(router, poly129, 129);
+
+ Polygon poly109(4);
+ poly109.ps[0] = Point(285.924, 91.5565);
+ poly109.ps[1] = Point(285.924, 131.557);
+ poly109.ps[2] = Point(229.924, 131.557);
+ poly109.ps[3] = Point(229.924, 91.5565);
+ new ShapeRef(router, poly109, 109);
+
+ Polygon poly103(4);
+ poly103.ps[0] = Point(968.924, 270.557);
+ poly103.ps[1] = Point(968.924, 290.557);
+ poly103.ps[2] = Point(948.924, 290.557);
+ poly103.ps[3] = Point(948.924, 270.557);
+ new ShapeRef(router, poly103, 103);
+
+ Polygon poly96(4);
+ poly96.ps[0] = Point(747.924, 333.557);
+ poly96.ps[1] = Point(747.924, 353.557);
+ poly96.ps[2] = Point(727.924, 353.557);
+ poly96.ps[3] = Point(727.924, 333.557);
+ new ShapeRef(router, poly96, 96);
+
+ Polygon poly143(4);
+ poly143.ps[0] = Point(986.924, 210.557);
+ poly143.ps[1] = Point(986.924, 250.557);
+ poly143.ps[2] = Point(930.924, 250.557);
+ poly143.ps[3] = Point(930.924, 210.557);
+ new ShapeRef(router, poly143, 143);
+
+ Polygon poly53(4);
+ poly53.ps[0] = Point(577.924, 323.557);
+ poly53.ps[1] = Point(577.924, 363.557);
+ poly53.ps[2] = Point(537.924, 363.557);
+ poly53.ps[3] = Point(537.924, 323.557);
+ new ShapeRef(router, poly53, 53);
+
+ Polygon poly75(4);
+ poly75.ps[0] = Point(87.9242, 651.557);
+ poly75.ps[1] = Point(87.9242, 671.557);
+ poly75.ps[2] = Point(67.9242, 671.557);
+ poly75.ps[3] = Point(67.9242, 651.557);
+ new ShapeRef(router, poly75, 75);
+
+ Polygon poly55(4);
+ poly55.ps[0] = Point(457.924, 7.34222);
+ poly55.ps[1] = Point(457.924, 47.3422);
+ poly55.ps[2] = Point(417.924, 47.3422);
+ poly55.ps[3] = Point(417.924, 7.34222);
+ new ShapeRef(router, poly55, 55);
+
+ Polygon poly34(4);
+ poly34.ps[0] = Point(1278.92, 323.557);
+ poly34.ps[1] = Point(1278.92, 363.557);
+ poly34.ps[2] = Point(1238.92, 363.557);
+ poly34.ps[3] = Point(1238.92, 323.557);
+ new ShapeRef(router, poly34, 34);
+
+ Polygon poly93(4);
+ poly93.ps[0] = Point(867.924, 333.557);
+ poly93.ps[1] = Point(867.924, 353.557);
+ poly93.ps[2] = Point(847.924, 353.557);
+ poly93.ps[3] = Point(847.924, 333.557);
+ new ShapeRef(router, poly93, 93);
+
+ Polygon poly100(4);
+ poly100.ps[0] = Point(1088.92, 50.3422);
+ poly100.ps[1] = Point(1088.92, 70.3422);
+ poly100.ps[2] = Point(1068.92, 70.3422);
+ poly100.ps[3] = Point(1068.92, 50.3422);
+ new ShapeRef(router, poly100, 100);
+
+ Polygon poly70(4);
+ poly70.ps[0] = Point(207.924, 203.557);
+ poly70.ps[1] = Point(207.924, 223.557);
+ poly70.ps[2] = Point(187.924, 223.557);
+ poly70.ps[3] = Point(187.924, 203.557);
+ new ShapeRef(router, poly70, 70);
+
+ Polygon poly110(4);
+ poly110.ps[0] = Point(287.924, 193.557);
+ poly110.ps[1] = Point(287.924, 233.557);
+ poly110.ps[2] = Point(231.924, 233.557);
+ poly110.ps[3] = Point(231.924, 193.557);
+ new ShapeRef(router, poly110, 110);
+
+ Polygon poly111(4);
+ poly111.ps[0] = Point(285.924, 245.557);
+ poly111.ps[1] = Point(285.924, 285.557);
+ poly111.ps[2] = Point(229.924, 285.557);
+ poly111.ps[3] = Point(229.924, 245.557);
+ new ShapeRef(router, poly111, 111);
+
+ Polygon poly135(4);
+ poly135.ps[0] = Point(885.924, 91.5565);
+ poly135.ps[1] = Point(885.924, 131.557);
+ poly135.ps[2] = Point(829.924, 131.557);
+ poly135.ps[3] = Point(829.924, 91.5565);
+ new ShapeRef(router, poly135, 135);
+
+ Polygon poly1(4);
+ poly1.ps[0] = Point(817.924, 840.057);
+ poly1.ps[1] = Point(817.924, 880.057);
+ poly1.ps[2] = Point(777.924, 880.057);
+ poly1.ps[3] = Point(777.924, 840.057);
+ new ShapeRef(router, poly1, 1);
+
+ Polygon poly67(4);
+ poly67.ps[0] = Point(147.924, 24.8422);
+ poly67.ps[1] = Point(147.924, 44.8422);
+ poly67.ps[2] = Point(127.924, 44.8422);
+ poly67.ps[3] = Point(127.924, 24.8422);
+ new ShapeRef(router, poly67, 67);
+
+ Polygon poly59(4);
+ poly59.ps[0] = Point(937.924, 323.557);
+ poly59.ps[1] = Point(937.924, 363.557);
+ poly59.ps[2] = Point(897.924, 363.557);
+ poly59.ps[3] = Point(897.924, 323.557);
+ new ShapeRef(router, poly59, 59);
+
+ Polygon poly89(4);
+ poly89.ps[0] = Point(507.924, 517.557);
+ poly89.ps[1] = Point(507.924, 537.557);
+ poly89.ps[2] = Point(487.924, 537.557);
+ poly89.ps[3] = Point(487.924, 517.557);
+ new ShapeRef(router, poly89, 89);
+
+ Polygon poly144(4);
+ poly144.ps[0] = Point(765.924, 91.5565);
+ poly144.ps[1] = Point(765.924, 131.557);
+ poly144.ps[2] = Point(709.924, 131.557);
+ poly144.ps[3] = Point(709.924, 91.5565);
+ new ShapeRef(router, poly144, 144);
+
+ Polygon poly33(4);
+ poly33.ps[0] = Point(937.924, 415.557);
+ poly33.ps[1] = Point(937.924, 455.557);
+ poly33.ps[2] = Point(897.924, 455.557);
+ poly33.ps[3] = Point(897.924, 415.557);
+ new ShapeRef(router, poly33, 33);
+
+ Polygon poly66(4);
+ poly66.ps[0] = Point(747.924, -70.6578);
+ poly66.ps[1] = Point(747.924, -50.6578);
+ poly66.ps[2] = Point(727.924, -50.6578);
+ poly66.ps[3] = Point(727.924, -70.6578);
+ new ShapeRef(router, poly66, 66);
+
+ Polygon poly145(4);
+ poly145.ps[0] = Point(765.924, 790.057);
+ poly145.ps[1] = Point(765.924, 830.057);
+ poly145.ps[2] = Point(709.924, 830.057);
+ poly145.ps[3] = Point(709.924, 790.057);
+ new ShapeRef(router, poly145, 145);
+
+ Polygon poly82(4);
+ poly82.ps[0] = Point(507.924, 893.057);
+ poly82.ps[1] = Point(507.924, 913.057);
+ poly82.ps[2] = Point(487.924, 913.057);
+ poly82.ps[3] = Point(487.924, 893.057);
+ new ShapeRef(router, poly82, 82);
+
+ Polygon poly32(4);
+ poly32.ps[0] = Point(1038.92, 141.557);
+ poly32.ps[1] = Point(1038.92, 181.557);
+ poly32.ps[2] = Point(998.924, 181.557);
+ poly32.ps[3] = Point(998.924, 141.557);
+ new ShapeRef(router, poly32, 32);
+
+ Polygon poly61(4);
+ poly61.ps[0] = Point(577.924, -44.6578);
+ poly61.ps[1] = Point(577.924, -4.65778);
+ poly61.ps[2] = Point(537.924, -4.65778);
+ poly61.ps[3] = Point(537.924, -44.6578);
+ new ShapeRef(router, poly61, 61);
+
+ Polygon poly138(4);
+ poly138.ps[0] = Point(1226.92, 318.557);
+ poly138.ps[1] = Point(1226.92, 358.557);
+ poly138.ps[2] = Point(1170.92, 358.557);
+ poly138.ps[3] = Point(1170.92, 318.557);
+ new ShapeRef(router, poly138, 138);
+
+ Polygon poly54(4);
+ poly54.ps[0] = Point(697.924, 323.557);
+ poly54.ps[1] = Point(697.924, 363.557);
+ poly54.ps[2] = Point(657.924, 363.557);
+ poly54.ps[3] = Point(657.924, 323.557);
+ new ShapeRef(router, poly54, 54);
+
+ Polygon poly142(4);
+ poly142.ps[0] = Point(1106.92, -130.658);
+ poly142.ps[1] = Point(1106.92, -90.6578);
+ poly142.ps[2] = Point(1050.92, -90.6578);
+ poly142.ps[3] = Point(1050.92, -130.658);
+ new ShapeRef(router, poly142, 142);
+
+ Polygon poly31(4);
+ poly31.ps[0] = Point(1278.92, 141.557);
+ poly31.ps[1] = Point(1278.92, 181.557);
+ poly31.ps[2] = Point(1238.92, 181.557);
+ poly31.ps[3] = Point(1238.92, 141.557);
+ new ShapeRef(router, poly31, 31);
+
+ Polygon poly78(4);
+ poly78.ps[0] = Point(387.924, 617.557);
+ poly78.ps[1] = Point(387.924, 637.557);
+ poly78.ps[2] = Point(367.924, 637.557);
+ poly78.ps[3] = Point(367.924, 617.557);
+ new ShapeRef(router, poly78, 78);
+
+ Polygon poly104(4);
+ poly104.ps[0] = Point(747.924, 151.557);
+ poly104.ps[1] = Point(747.924, 171.557);
+ poly104.ps[2] = Point(727.924, 171.557);
+ poly104.ps[3] = Point(727.924, 151.557);
+ new ShapeRef(router, poly104, 104);
+
+ Polygon poly58(4);
+ poly58.ps[0] = Point(97.9242, 14.8422);
+ poly58.ps[1] = Point(97.9242, 54.8422);
+ poly58.ps[2] = Point(57.9242, 54.8422);
+ poly58.ps[3] = Point(57.9242, 14.8422);
+ new ShapeRef(router, poly58, 58);
+
+ Polygon poly30(4);
+ poly30.ps[0] = Point(1278.92, 415.557);
+ poly30.ps[1] = Point(1278.92, 455.557);
+ poly30.ps[2] = Point(1238.92, 455.557);
+ poly30.ps[3] = Point(1238.92, 415.557);
+ new ShapeRef(router, poly30, 30);
+
+ Polygon poly64(4);
+ poly64.ps[0] = Point(817.924, 554.057);
+ poly64.ps[1] = Point(817.924, 594.057);
+ poly64.ps[2] = Point(777.924, 594.057);
+ poly64.ps[3] = Point(777.924, 554.057);
+ new ShapeRef(router, poly64, 64);
+
+ Polygon poly85(4);
+ poly85.ps[0] = Point(387.924, 17.3422);
+ poly85.ps[1] = Point(387.924, 37.3422);
+ poly85.ps[2] = Point(367.924, 37.3422);
+ poly85.ps[3] = Point(367.924, 17.3422);
+ new ShapeRef(router, poly85, 85);
+
+ Polygon poly83(4);
+ poly83.ps[0] = Point(627.924, 893.057);
+ poly83.ps[1] = Point(627.924, 913.057);
+ poly83.ps[2] = Point(607.924, 913.057);
+ poly83.ps[3] = Point(607.924, 893.057);
+ new ShapeRef(router, poly83, 83);
+
+ Polygon poly108(4);
+ poly108.ps[0] = Point(165.924, 91.5565);
+ poly108.ps[1] = Point(165.924, 131.557);
+ poly108.ps[2] = Point(109.924, 131.557);
+ poly108.ps[3] = Point(109.924, 91.5565);
+ new ShapeRef(router, poly108, 108);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(1371.92, -22.1578);
+ poly5.ps[1] = Point(1371.92, 17.8422);
+ poly5.ps[2] = Point(1331.92, 17.8422);
+ poly5.ps[3] = Point(1331.92, -22.1578);
+ new ShapeRef(router, poly5, 5);
+
+ Polygon poly131(4);
+ poly131.ps[0] = Point(645.924, 457.557);
+ poly131.ps[1] = Point(645.924, 497.557);
+ poly131.ps[2] = Point(589.924, 497.557);
+ poly131.ps[3] = Point(589.924, 457.557);
+ new ShapeRef(router, poly131, 131);
+
+ Polygon poly106(4);
+ poly106.ps[0] = Point(765.924, -130.658);
+ poly106.ps[1] = Point(765.924, -90.6578);
+ poly106.ps[2] = Point(709.924, -90.6578);
+ poly106.ps[3] = Point(709.924, -130.658);
+ new ShapeRef(router, poly106, 106);
+
+ Polygon poly86(4);
+ poly86.ps[0] = Point(507.924, 35.8422);
+ poly86.ps[1] = Point(507.924, 55.8422);
+ poly86.ps[2] = Point(487.924, 55.8422);
+ poly86.ps[3] = Point(487.924, 35.8422);
+ new ShapeRef(router, poly86, 86);
+
+ Polygon poly84(4);
+ poly84.ps[0] = Point(387.924, 151.557);
+ poly84.ps[1] = Point(387.924, 171.557);
+ poly84.ps[2] = Point(367.924, 171.557);
+ poly84.ps[3] = Point(367.924, 151.557);
+ new ShapeRef(router, poly84, 84);
+
+ Polygon poly88(4);
+ poly88.ps[0] = Point(747.924, 564.057);
+ poly88.ps[1] = Point(747.924, 584.057);
+ poly88.ps[2] = Point(727.924, 584.057);
+ poly88.ps[3] = Point(727.924, 564.057);
+ new ShapeRef(router, poly88, 88);
+
+ Polygon poly107(4);
+ poly107.ps[0] = Point(165.924, -35.1578);
+ poly107.ps[1] = Point(165.924, 4.84222);
+ poly107.ps[2] = Point(109.924, 4.84222);
+ poly107.ps[3] = Point(109.924, -35.1578);
+ new ShapeRef(router, poly107, 107);
+
+ Polygon poly29(4);
+ poly29.ps[0] = Point(1038.92, 415.557);
+ poly29.ps[1] = Point(1038.92, 455.557);
+ poly29.ps[2] = Point(998.924, 455.557);
+ poly29.ps[3] = Point(998.924, 415.557);
+ new ShapeRef(router, poly29, 29);
+
+ Polygon poly28(4);
+ poly28.ps[0] = Point(817.924, 323.557);
+ poly28.ps[1] = Point(817.924, 363.557);
+ poly28.ps[2] = Point(777.924, 363.557);
+ poly28.ps[3] = Point(777.924, 323.557);
+ new ShapeRef(router, poly28, 28);
+
+ Polygon poly27(4);
+ poly27.ps[0] = Point(577.924, 507.557);
+ poly27.ps[1] = Point(577.924, 547.557);
+ poly27.ps[2] = Point(537.924, 547.557);
+ poly27.ps[3] = Point(537.924, 507.557);
+ new ShapeRef(router, poly27, 27);
+
+ Polygon poly99(4);
+ poly99.ps[0] = Point(1088.92, 142.342);
+ poly99.ps[1] = Point(1088.92, 162.342);
+ poly99.ps[2] = Point(1068.92, 162.342);
+ poly99.ps[3] = Point(1068.92, 142.342);
+ new ShapeRef(router, poly99, 99);
+
+ Polygon poly57(4);
+ poly57.ps[0] = Point(817.924, 141.557);
+ poly57.ps[1] = Point(817.924, 181.557);
+ poly57.ps[2] = Point(777.924, 181.557);
+ poly57.ps[3] = Point(777.924, 141.557);
+ new ShapeRef(router, poly57, 57);
+
+ Polygon poly26(4);
+ poly26.ps[0] = Point(697.924, 743.557);
+ poly26.ps[1] = Point(697.924, 783.557);
+ poly26.ps[2] = Point(657.924, 783.557);
+ poly26.ps[3] = Point(657.924, 743.557);
+ new ShapeRef(router, poly26, 26);
+
+ Polygon poly133(4);
+ poly133.ps[0] = Point(885.924, 273.557);
+ poly133.ps[1] = Point(885.924, 313.557);
+ poly133.ps[2] = Point(829.924, 313.557);
+ poly133.ps[3] = Point(829.924, 273.557);
+ new ShapeRef(router, poly133, 133);
+
+ Polygon poly25(4);
+ poly25.ps[0] = Point(697.924, 883.057);
+ poly25.ps[1] = Point(697.924, 923.057);
+ poly25.ps[2] = Point(657.924, 923.057);
+ poly25.ps[3] = Point(657.924, 883.057);
+ new ShapeRef(router, poly25, 25);
+
+ Polygon poly69(4);
+ poly69.ps[0] = Point(267.924, 151.557);
+ poly69.ps[1] = Point(267.924, 171.557);
+ poly69.ps[2] = Point(247.924, 171.557);
+ poly69.ps[3] = Point(247.924, 151.557);
+ new ShapeRef(router, poly69, 69);
+
+ Polygon poly24(4);
+ poly24.ps[0] = Point(457.924, 743.557);
+ poly24.ps[1] = Point(457.924, 783.557);
+ poly24.ps[2] = Point(417.924, 783.557);
+ poly24.ps[3] = Point(417.924, 743.557);
+ new ShapeRef(router, poly24, 24);
+
+ Polygon poly141(4);
+ poly141.ps[0] = Point(1226.92, 82.3422);
+ poly141.ps[1] = Point(1226.92, 122.342);
+ poly141.ps[2] = Point(1170.92, 122.342);
+ poly141.ps[3] = Point(1170.92, 82.3422);
+ new ShapeRef(router, poly141, 141);
+
+ Polygon poly23(4);
+ poly23.ps[0] = Point(337.924, 141.557);
+ poly23.ps[1] = Point(337.924, 181.557);
+ poly23.ps[2] = Point(297.924, 181.557);
+ poly23.ps[3] = Point(297.924, 141.557);
+ new ShapeRef(router, poly23, 23);
+
+ Polygon poly137(4);
+ poly137.ps[0] = Point(1106.92, 318.557);
+ poly137.ps[1] = Point(1106.92, 358.557);
+ poly137.ps[2] = Point(1050.92, 358.557);
+ poly137.ps[3] = Point(1050.92, 318.557);
+ new ShapeRef(router, poly137, 137);
+
+ Polygon poly22(4);
+ poly22.ps[0] = Point(697.924, 34.8422);
+ poly22.ps[1] = Point(697.924, 74.8422);
+ poly22.ps[2] = Point(657.924, 74.8422);
+ poly22.ps[3] = Point(657.924, 34.8422);
+ new ShapeRef(router, poly22, 22);
+
+ Polygon poly121(4);
+ poly121.ps[0] = Point(645.924, 693.557);
+ poly121.ps[1] = Point(645.924, 733.557);
+ poly121.ps[2] = Point(589.924, 733.557);
+ poly121.ps[3] = Point(589.924, 693.557);
+ new ShapeRef(router, poly121, 121);
+
+ Polygon poly112(4);
+ poly112.ps[0] = Point(167.924, 347.557);
+ poly112.ps[1] = Point(167.924, 387.557);
+ poly112.ps[2] = Point(111.924, 387.557);
+ poly112.ps[3] = Point(111.924, 347.557);
+ new ShapeRef(router, poly112, 112);
+
+ Polygon poly113(4);
+ poly113.ps[0] = Point(165.924, 457.557);
+ poly113.ps[1] = Point(165.924, 497.557);
+ poly113.ps[2] = Point(109.924, 497.557);
+ poly113.ps[3] = Point(109.924, 457.557);
+ new ShapeRef(router, poly113, 113);
+
+ Polygon poly120(4);
+ poly120.ps[0] = Point(525.924, 693.557);
+ poly120.ps[1] = Point(525.924, 733.557);
+ poly120.ps[2] = Point(469.924, 733.557);
+ poly120.ps[3] = Point(469.924, 693.557);
+ new ShapeRef(router, poly120, 120);
+
+ Polygon poly114(4);
+ poly114.ps[0] = Point(165.924, 549.557);
+ poly114.ps[1] = Point(165.924, 589.557);
+ poly114.ps[2] = Point(109.924, 589.557);
+ poly114.ps[3] = Point(109.924, 549.557);
+ new ShapeRef(router, poly114, 114);
+
+ Polygon poly115(4);
+ poly115.ps[0] = Point(167.924, 641.557);
+ poly115.ps[1] = Point(167.924, 681.557);
+ poly115.ps[2] = Point(111.924, 681.557);
+ poly115.ps[3] = Point(111.924, 641.557);
+ new ShapeRef(router, poly115, 115);
+
+ Polygon poly101(4);
+ poly101.ps[0] = Point(1208.92, 142.342);
+ poly101.ps[1] = Point(1208.92, 162.342);
+ poly101.ps[2] = Point(1188.92, 162.342);
+ poly101.ps[3] = Point(1188.92, 142.342);
+ new ShapeRef(router, poly101, 101);
+
+ Polygon poly21(4);
+ poly21.ps[0] = Point(937.924, 141.557);
+ poly21.ps[1] = Point(937.924, 181.557);
+ poly21.ps[2] = Point(897.924, 181.557);
+ poly21.ps[3] = Point(897.924, 141.557);
+ new ShapeRef(router, poly21, 21);
+
+ Polygon poly20(4);
+ poly20.ps[0] = Point(337.924, 507.557);
+ poly20.ps[1] = Point(337.924, 547.557);
+ poly20.ps[2] = Point(297.924, 547.557);
+ poly20.ps[3] = Point(297.924, 507.557);
+ new ShapeRef(router, poly20, 20);
+
+ Polygon poly79(4);
+ poly79.ps[0] = Point(387.924, 753.557);
+ poly79.ps[1] = Point(387.924, 773.557);
+ poly79.ps[2] = Point(367.924, 773.557);
+ poly79.ps[3] = Point(367.924, 753.557);
+ new ShapeRef(router, poly79, 79);
+
+ Polygon poly62(4);
+ poly62.ps[0] = Point(577.924, 629.557);
+ poly62.ps[1] = Point(577.924, 669.557);
+ poly62.ps[2] = Point(537.924, 669.557);
+ poly62.ps[3] = Point(537.924, 629.557);
+ new ShapeRef(router, poly62, 62);
+
+ Polygon poly65(4);
+ poly65.ps[0] = Point(97.9242, 599.557);
+ poly65.ps[1] = Point(97.9242, 639.557);
+ poly65.ps[2] = Point(57.9242, 639.557);
+ poly65.ps[3] = Point(57.9242, 599.557);
+ new ShapeRef(router, poly65, 65);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(577.924, 795.557);
+ poly2.ps[1] = Point(577.924, 835.557);
+ poly2.ps[2] = Point(537.924, 835.557);
+ poly2.ps[3] = Point(537.924, 795.557);
+ new ShapeRef(router, poly2, 2);
+
+ Polygon poly19(4);
+ poly19.ps[0] = Point(217.924, 141.557);
+ poly19.ps[1] = Point(217.924, 181.557);
+ poly19.ps[2] = Point(177.924, 181.557);
+ poly19.ps[3] = Point(177.924, 141.557);
+ new ShapeRef(router, poly19, 19);
+
+ Polygon poly147(4);
+ poly147.ps[0] = Point(-26.0758, 274.75);
+ poly147.ps[1] = Point(-26.0758, 334.75);
+ poly147.ps[2] = Point(-66.0758, 334.75);
+ poly147.ps[3] = Point(-66.0758, 274.75);
+ new ShapeRef(router, poly147, 147);
+
+ Polygon poly18(4);
+ poly18.ps[0] = Point(217.924, 743.557);
+ poly18.ps[1] = Point(217.924, 783.557);
+ poly18.ps[2] = Point(177.924, 783.557);
+ poly18.ps[3] = Point(177.924, 743.557);
+ new ShapeRef(router, poly18, 18);
+
+ Polygon poly17(4);
+ poly17.ps[0] = Point(577.924, 883.057);
+ poly17.ps[1] = Point(577.924, 923.057);
+ poly17.ps[2] = Point(537.924, 923.057);
+ poly17.ps[3] = Point(537.924, 883.057);
+ new ShapeRef(router, poly17, 17);
+
+ Polygon poly95(4);
+ poly95.ps[0] = Point(867.924, 151.557);
+ poly95.ps[1] = Point(867.924, 171.557);
+ poly95.ps[2] = Point(847.924, 171.557);
+ poly95.ps[3] = Point(847.924, 151.557);
+ new ShapeRef(router, poly95, 95);
+
+ Polygon poly16(4);
+ poly16.ps[0] = Point(337.924, 743.557);
+ poly16.ps[1] = Point(337.924, 783.557);
+ poly16.ps[2] = Point(297.924, 783.557);
+ poly16.ps[3] = Point(297.924, 743.557);
+ new ShapeRef(router, poly16, 16);
+
+ Polygon poly15(4);
+ poly15.ps[0] = Point(1158.92, 415.557);
+ poly15.ps[1] = Point(1158.92, 455.557);
+ poly15.ps[2] = Point(1118.92, 455.557);
+ poly15.ps[3] = Point(1118.92, 415.557);
+ new ShapeRef(router, poly15, 15);
+
+ Polygon poly14(4);
+ poly14.ps[0] = Point(1158.92, 141.557);
+ poly14.ps[1] = Point(1158.92, 181.557);
+ poly14.ps[2] = Point(1118.92, 181.557);
+ poly14.ps[3] = Point(1118.92, 141.557);
+ new ShapeRef(router, poly14, 14);
+
+ Polygon poly63(4);
+ poly63.ps[0] = Point(457.924, 507.557);
+ poly63.ps[1] = Point(457.924, 547.557);
+ poly63.ps[2] = Point(417.924, 547.557);
+ poly63.ps[3] = Point(417.924, 507.557);
+ new ShapeRef(router, poly63, 63);
+
+ Polygon poly73(4);
+ poly73.ps[0] = Point(147.924, 517.557);
+ poly73.ps[1] = Point(147.924, 537.557);
+ poly73.ps[2] = Point(127.924, 537.557);
+ poly73.ps[3] = Point(127.924, 517.557);
+ new ShapeRef(router, poly73, 73);
+
+ Polygon poly13(4);
+ poly13.ps[0] = Point(1158.92, 323.557);
+ poly13.ps[1] = Point(1158.92, 363.557);
+ poly13.ps[2] = Point(1118.92, 363.557);
+ poly13.ps[3] = Point(1118.92, 323.557);
+ new ShapeRef(router, poly13, 13);
+
+ Polygon poly52(4);
+ poly52.ps[0] = Point(217.924, 295.557);
+ poly52.ps[1] = Point(217.924, 335.557);
+ poly52.ps[2] = Point(177.924, 335.557);
+ poly52.ps[3] = Point(177.924, 295.557);
+ new ShapeRef(router, poly52, 52);
+
+ Polygon poly132(4);
+ poly132.ps[0] = Point(645.924, 365.557);
+ poly132.ps[1] = Point(645.924, 405.557);
+ poly132.ps[2] = Point(589.924, 405.557);
+ poly132.ps[3] = Point(589.924, 365.557);
+ new ShapeRef(router, poly132, 132);
+
+ Polygon poly90(4);
+ poly90.ps[0] = Point(507.924, 425.557);
+ poly90.ps[1] = Point(507.924, 445.557);
+ poly90.ps[2] = Point(487.924, 445.557);
+ poly90.ps[3] = Point(487.924, 425.557);
+ new ShapeRef(router, poly90, 90);
+
+ Polygon poly12(4);
+ poly12.ps[0] = Point(1038.92, 260.557);
+ poly12.ps[1] = Point(1038.92, 300.557);
+ poly12.ps[2] = Point(998.924, 300.557);
+ poly12.ps[3] = Point(998.924, 260.557);
+ new ShapeRef(router, poly12, 12);
+
+ Polygon poly11(4);
+ poly11.ps[0] = Point(817.924, -80.6578);
+ poly11.ps[1] = Point(817.924, -40.6578);
+ poly11.ps[2] = Point(777.924, -40.6578);
+ poly11.ps[3] = Point(777.924, -80.6578);
+ new ShapeRef(router, poly11, 11);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(937.924, -80.6578);
+ poly10.ps[1] = Point(937.924, -40.6578);
+ poly10.ps[2] = Point(897.924, -40.6578);
+ poly10.ps[3] = Point(897.924, -80.6578);
+ new ShapeRef(router, poly10, 10);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(1038.92, -80.6578);
+ poly9.ps[1] = Point(1038.92, -40.6578);
+ poly9.ps[2] = Point(998.924, -40.6578);
+ poly9.ps[3] = Point(998.924, -80.6578);
+ new ShapeRef(router, poly9, 9);
+
+ ConnRef *connRef200 = new ConnRef(router, 200);
+ ConnEnd srcPt200(Point(387.924, 763.557), 15);
+ connRef200->setSourceEndpoint(srcPt200);
+ ConnEnd dstPt200(Point(437.924, 763.557), 15);
+ connRef200->setDestEndpoint(dstPt200);
+ connRef200->setRoutingType((ConnType)2);
+
+ ConnRef *connRef181 = new ConnRef(router, 181);
+ ConnEnd srcPt181(Point(77.9242, 763.557), 15);
+ connRef181->setSourceEndpoint(srcPt181);
+ ConnEnd dstPt181(Point(77.9242, 671.557), 15);
+ connRef181->setDestEndpoint(dstPt181);
+ connRef181->setRoutingType((ConnType)2);
+
+ ConnRef *connRef263 = new ConnRef(router, 263);
+ ConnEnd srcPt263(Point(958.924, 230.557), 15);
+ connRef263->setSourceEndpoint(srcPt263);
+ ConnEnd dstPt263(Point(958.924, 280.557), 15);
+ connRef263->setDestEndpoint(dstPt263);
+ connRef263->setRoutingType((ConnType)2);
+
+ ConnRef *connRef264 = new ConnRef(router, 264);
+ ConnEnd srcPt264(Point(737.924, 111.557), 15);
+ connRef264->setSourceEndpoint(srcPt264);
+ ConnEnd dstPt264(Point(737.924, 161.557), 15);
+ connRef264->setDestEndpoint(dstPt264);
+ connRef264->setRoutingType((ConnType)2);
+
+ ConnRef *connRef265 = new ConnRef(router, 265);
+ ConnEnd srcPt265(Point(737.924, 810.057), 15);
+ connRef265->setSourceEndpoint(srcPt265);
+ ConnEnd dstPt265(Point(737.924, 860.057), 15);
+ connRef265->setDestEndpoint(dstPt265);
+ connRef265->setRoutingType((ConnType)2);
+
+ ConnRef *connRef266 = new ConnRef(router, 266);
+ ConnEnd srcPt266(Point(77.9242, 161.557), 15);
+ connRef266->setSourceEndpoint(srcPt266);
+ ConnEnd dstPt266(Point(40.9242, 252.5), 15);
+ connRef266->setDestEndpoint(dstPt266);
+ connRef266->setRoutingType((ConnType)2);
+
+ ConnRef *connRef267 = new ConnRef(router, 267);
+ ConnEnd srcPt267(Point(77.9242, 763.557), 15);
+ connRef267->setSourceEndpoint(srcPt267);
+ ConnEnd dstPt267(Point(-46.0758, 329.75), 15);
+ connRef267->setDestEndpoint(dstPt267);
+ connRef267->setRoutingType((ConnType)2);
+
+ ConnRef *connRef202 = new ConnRef(router, 202);
+ ConnEnd srcPt202(Point(627.924, 763.557), 15);
+ connRef202->setSourceEndpoint(srcPt202);
+ ConnEnd dstPt202(Point(677.924, 763.557), 15);
+ connRef202->setDestEndpoint(dstPt202);
+ connRef202->setRoutingType((ConnType)2);
+
+ ConnRef *connRef161 = new ConnRef(router, 161);
+ ConnEnd srcPt161(Point(317.924, 161.557), 15);
+ connRef161->setSourceEndpoint(srcPt161);
+ ConnEnd dstPt161(Point(367.924, 161.557), 15);
+ connRef161->setDestEndpoint(dstPt161);
+ connRef161->setRoutingType((ConnType)2);
+
+ ConnRef *connRef162 = new ConnRef(router, 162);
+ ConnEnd srcPt162(Point(317.924, 161.557), 15);
+ connRef162->setSourceEndpoint(srcPt162);
+ ConnEnd dstPt162(Point(367.924, 27.3422), 15);
+ connRef162->setDestEndpoint(dstPt162);
+ connRef162->setRoutingType((ConnType)2);
+
+ ConnRef *connRef148 = new ConnRef(router, 148);
+ ConnEnd srcPt148(Point(1018.92, -60.6578), 15);
+ connRef148->setSourceEndpoint(srcPt148);
+ ConnEnd dstPt148(Point(1068.92, -60.6578), 15);
+ connRef148->setDestEndpoint(dstPt148);
+ connRef148->setRoutingType((ConnType)2);
+
+ ConnRef *connRef205 = new ConnRef(router, 205);
+ ConnEnd srcPt205(Point(387.924, 161.557), 15);
+ connRef205->setSourceEndpoint(srcPt205);
+ ConnEnd dstPt205(Point(437.924, 161.557), 15);
+ connRef205->setDestEndpoint(dstPt205);
+ connRef205->setRoutingType((ConnType)2);
+
+ ConnRef *connRef227 = new ConnRef(router, 227);
+ ConnEnd srcPt227(Point(137.924, -15.1578), 15);
+ connRef227->setSourceEndpoint(srcPt227);
+ ConnEnd dstPt227(Point(137.924, 34.8422), 15);
+ connRef227->setDestEndpoint(dstPt227);
+ connRef227->setRoutingType((ConnType)2);
+
+ ConnRef *connRef228 = new ConnRef(router, 228);
+ ConnEnd srcPt228(Point(137.924, 111.557), 15);
+ connRef228->setSourceEndpoint(srcPt228);
+ ConnEnd dstPt228(Point(137.924, 161.557), 15);
+ connRef228->setDestEndpoint(dstPt228);
+ connRef228->setRoutingType((ConnType)2);
+
+ ConnRef *connRef231 = new ConnRef(router, 231);
+ ConnEnd srcPt231(Point(257.924, 265.557), 15);
+ connRef231->setSourceEndpoint(srcPt231);
+ ConnEnd dstPt231(Point(257.924, 315.557), 15);
+ connRef231->setDestEndpoint(dstPt231);
+ connRef231->setRoutingType((ConnType)2);
+
+ ConnRef *connRef232 = new ConnRef(router, 232);
+ ConnEnd srcPt232(Point(139.924, 367.557), 15);
+ connRef232->setSourceEndpoint(srcPt232);
+ ConnEnd dstPt232(Point(77.9242, 367.557), 15);
+ connRef232->setDestEndpoint(dstPt232);
+ connRef232->setRoutingType((ConnType)2);
+
+ ConnRef *connRef225 = new ConnRef(router, 225);
+ ConnEnd srcPt225(Point(747.924, 860.057), 15);
+ connRef225->setSourceEndpoint(srcPt225);
+ ConnEnd dstPt225(Point(797.924, 860.057), 15);
+ connRef225->setDestEndpoint(dstPt225);
+ connRef225->setRoutingType((ConnType)2);
+
+ ConnRef *connRef226 = new ConnRef(router, 226);
+ ConnEnd srcPt226(Point(737.924, -110.658), 15);
+ connRef226->setSourceEndpoint(srcPt226);
+ ConnEnd dstPt226(Point(737.924, -60.6578), 15);
+ connRef226->setDestEndpoint(dstPt226);
+ connRef226->setRoutingType((ConnType)2);
+
+ ConnRef *connRef240 = new ConnRef(router, 240);
+ ConnEnd srcPt240(Point(497.924, 713.557), 15);
+ connRef240->setSourceEndpoint(srcPt240);
+ ConnEnd dstPt240(Point(497.924, 763.557), 15);
+ connRef240->setDestEndpoint(dstPt240);
+ connRef240->setRoutingType((ConnType)2);
+
+ ConnRef *connRef241 = new ConnRef(router, 241);
+ ConnEnd srcPt241(Point(617.924, 713.557), 15);
+ connRef241->setSourceEndpoint(srcPt241);
+ ConnEnd dstPt241(Point(617.924, 763.557), 15);
+ connRef241->setDestEndpoint(dstPt241);
+ connRef241->setRoutingType((ConnType)2);
+
+ ConnRef *connRef242 = new ConnRef(router, 242);
+ ConnEnd srcPt242(Point(497.924, 853.057), 15);
+ connRef242->setSourceEndpoint(srcPt242);
+ ConnEnd dstPt242(Point(497.924, 903.057), 15);
+ connRef242->setDestEndpoint(dstPt242);
+ connRef242->setRoutingType((ConnType)2);
+
+ ConnRef *connRef203 = new ConnRef(router, 203);
+ ConnEnd srcPt203(Point(507.924, 903.057), 15);
+ connRef203->setSourceEndpoint(srcPt203);
+ ConnEnd dstPt203(Point(557.924, 903.057), 15);
+ connRef203->setDestEndpoint(dstPt203);
+ connRef203->setRoutingType((ConnType)2);
+
+ ConnRef *connRef221 = new ConnRef(router, 221);
+ ConnEnd srcPt221(Point(1088.92, 60.3422), 15);
+ connRef221->setSourceEndpoint(srcPt221);
+ ConnEnd dstPt221(Point(1138.92, 60.3422), 15);
+ connRef221->setDestEndpoint(dstPt221);
+ connRef221->setRoutingType((ConnType)2);
+
+ ConnRef *connRef207 = new ConnRef(router, 207);
+ ConnEnd srcPt207(Point(507.924, 45.8422), 15);
+ connRef207->setSourceEndpoint(srcPt207);
+ ConnEnd dstPt207(Point(557.924, 54.8422), 15);
+ connRef207->setDestEndpoint(dstPt207);
+ connRef207->setRoutingType((ConnType)2);
+
+ ConnRef *connRef188 = new ConnRef(router, 188);
+ ConnEnd srcPt188(Point(77.9242, 619.557), 15);
+ connRef188->setSourceEndpoint(srcPt188);
+ ConnEnd dstPt188(Point(127.924, 619.557), 15);
+ connRef188->setDestEndpoint(dstPt188);
+ connRef188->setRoutingType((ConnType)2);
+
+ ConnRef *connRef209 = new ConnRef(router, 209);
+ ConnEnd srcPt209(Point(747.924, 574.057), 15);
+ connRef209->setSourceEndpoint(srcPt209);
+ ConnEnd dstPt209(Point(797.924, 574.057), 15);
+ connRef209->setDestEndpoint(dstPt209);
+ connRef209->setRoutingType((ConnType)2);
+
+ ConnRef *connRef210 = new ConnRef(router, 210);
+ ConnEnd srcPt210(Point(507.924, 527.557), 15);
+ connRef210->setSourceEndpoint(srcPt210);
+ ConnEnd dstPt210(Point(557.924, 527.557), 15);
+ connRef210->setDestEndpoint(dstPt210);
+ connRef210->setRoutingType((ConnType)2);
+
+ ConnRef *connRef155 = new ConnRef(router, 155);
+ ConnEnd srcPt155(Point(557.924, 903.057), 15);
+ connRef155->setSourceEndpoint(srcPt155);
+ ConnEnd dstPt155(Point(607.924, 903.057), 15);
+ connRef155->setDestEndpoint(dstPt155);
+ connRef155->setRoutingType((ConnType)2);
+
+ ConnRef *connRef222 = new ConnRef(router, 222);
+ ConnEnd srcPt222(Point(1208.92, 152.342), 15);
+ connRef222->setSourceEndpoint(srcPt222);
+ ConnEnd dstPt222(Point(1258.92, 161.557), 15);
+ connRef222->setDestEndpoint(dstPt222);
+ connRef222->setRoutingType((ConnType)2);
+
+ ConnRef *connRef223 = new ConnRef(router, 223);
+ ConnEnd srcPt223(Point(1088.92, -60.6578), 15);
+ connRef223->setSourceEndpoint(srcPt223);
+ ConnEnd dstPt223(Point(1138.92, -60.6578), 15);
+ connRef223->setDestEndpoint(dstPt223);
+ connRef223->setRoutingType((ConnType)2);
+
+ ConnRef *connRef215 = new ConnRef(router, 215);
+ ConnEnd srcPt215(Point(867.924, 435.557), 15);
+ connRef215->setSourceEndpoint(srcPt215);
+ ConnEnd dstPt215(Point(917.924, 435.557), 15);
+ connRef215->setDestEndpoint(dstPt215);
+ connRef215->setRoutingType((ConnType)2);
+
+ ConnRef *connRef216 = new ConnRef(router, 216);
+ ConnEnd srcPt216(Point(867.924, 161.557), 15);
+ connRef216->setSourceEndpoint(srcPt216);
+ ConnEnd dstPt216(Point(917.924, 161.557), 15);
+ connRef216->setDestEndpoint(dstPt216);
+ connRef216->setRoutingType((ConnType)2);
+
+ ConnRef *connRef213 = new ConnRef(router, 213);
+ ConnEnd srcPt213(Point(627.924, 435.557), 15);
+ connRef213->setSourceEndpoint(srcPt213);
+ ConnEnd dstPt213(Point(677.924, 435.557), 15);
+ connRef213->setDestEndpoint(dstPt213);
+ connRef213->setRoutingType((ConnType)2);
+
+ ConnRef *connRef214 = new ConnRef(router, 214);
+ ConnEnd srcPt214(Point(867.924, 343.557), 15);
+ connRef214->setSourceEndpoint(srcPt214);
+ ConnEnd dstPt214(Point(917.924, 343.557), 15);
+ connRef214->setDestEndpoint(dstPt214);
+ connRef214->setRoutingType((ConnType)2);
+
+ ConnRef *connRef171 = new ConnRef(router, 171);
+ ConnEnd srcPt171(Point(1018.92, 161.557), 15);
+ connRef171->setSourceEndpoint(srcPt171);
+ ConnEnd dstPt171(Point(1068.92, 60.3422), 15);
+ connRef171->setDestEndpoint(dstPt171);
+ connRef171->setRoutingType((ConnType)2);
+
+ ConnRef *connRef198 = new ConnRef(router, 198);
+ ConnEnd srcPt198(Point(267.924, 763.557), 15);
+ connRef198->setSourceEndpoint(srcPt198);
+ ConnEnd dstPt198(Point(317.924, 763.557), 15);
+ connRef198->setDestEndpoint(dstPt198);
+ connRef198->setRoutingType((ConnType)2);
+
+ ConnRef *connRef164 = new ConnRef(router, 164);
+ ConnEnd srcPt164(Point(437.924, 763.557), 15);
+ connRef164->setSourceEndpoint(srcPt164);
+ ConnEnd dstPt164(Point(487.924, 763.557), 15);
+ connRef164->setDestEndpoint(dstPt164);
+ connRef164->setRoutingType((ConnType)2);
+
+ ConnRef *connRef165 = new ConnRef(router, 165);
+ ConnEnd srcPt165(Point(437.924, 763.557), 15);
+ connRef165->setSourceEndpoint(srcPt165);
+ ConnEnd dstPt165(Point(727.924, 860.057), 15);
+ connRef165->setDestEndpoint(dstPt165);
+ connRef165->setRoutingType((ConnType)2);
+
+ ConnRef *connRef219 = new ConnRef(router, 219);
+ ConnEnd srcPt219(Point(1208.92, 388.557), 15);
+ connRef219->setSourceEndpoint(srcPt219);
+ ConnEnd dstPt219(Point(1258.92, 435.557), 15);
+ connRef219->setDestEndpoint(dstPt219);
+ connRef219->setRoutingType((ConnType)2);
+
+ ConnRef *connRef220 = new ConnRef(router, 220);
+ ConnEnd srcPt220(Point(1088.92, 152.342), 15);
+ connRef220->setSourceEndpoint(srcPt220);
+ ConnEnd dstPt220(Point(1138.92, 161.557), 15);
+ connRef220->setDestEndpoint(dstPt220);
+ connRef220->setRoutingType((ConnType)2);
+
+ ConnRef *connRef233 = new ConnRef(router, 233);
+ ConnEnd srcPt233(Point(137.924, 477.557), 15);
+ connRef233->setSourceEndpoint(srcPt233);
+ ConnEnd dstPt233(Point(137.924, 527.557), 15);
+ connRef233->setDestEndpoint(dstPt233);
+ connRef233->setRoutingType((ConnType)2);
+
+ ConnRef *connRef234 = new ConnRef(router, 234);
+ ConnEnd srcPt234(Point(137.924, 569.557), 15);
+ connRef234->setSourceEndpoint(srcPt234);
+ ConnEnd dstPt234(Point(137.924, 619.557), 15);
+ connRef234->setDestEndpoint(dstPt234);
+ connRef234->setRoutingType((ConnType)2);
+
+ ConnRef *connRef229 = new ConnRef(router, 229);
+ ConnEnd srcPt229(Point(257.924, 111.557), 15);
+ connRef229->setSourceEndpoint(srcPt229);
+ ConnEnd dstPt229(Point(257.924, 161.557), 15);
+ connRef229->setDestEndpoint(dstPt229);
+ connRef229->setRoutingType((ConnType)2);
+
+ ConnRef *connRef230 = new ConnRef(router, 230);
+ ConnEnd srcPt230(Point(259.924, 213.557), 15);
+ connRef230->setSourceEndpoint(srcPt230);
+ ConnEnd dstPt230(Point(197.924, 213.557), 15);
+ connRef230->setDestEndpoint(dstPt230);
+ connRef230->setRoutingType((ConnType)2);
+
+ ConnRef *connRef199 = new ConnRef(router, 199);
+ ConnEnd srcPt199(Point(387.924, 627.557), 15);
+ connRef199->setSourceEndpoint(srcPt199);
+ ConnEnd dstPt199(Point(437.924, 627.557), 15);
+ connRef199->setDestEndpoint(dstPt199);
+ connRef199->setRoutingType((ConnType)2);
+
+ ConnRef *connRef166 = new ConnRef(router, 166);
+ ConnEnd srcPt166(Point(557.924, 527.557), 15);
+ connRef166->setSourceEndpoint(srcPt166);
+ ConnEnd dstPt166(Point(607.924, 527.557), 15);
+ connRef166->setDestEndpoint(dstPt166);
+ connRef166->setRoutingType((ConnType)2);
+
+ ConnRef *connRef249 = new ConnRef(router, 249);
+ ConnEnd srcPt249(Point(497.924, 477.557), 15);
+ connRef249->setSourceEndpoint(srcPt249);
+ ConnEnd dstPt249(Point(497.924, 527.557), 15);
+ connRef249->setDestEndpoint(dstPt249);
+ connRef249->setRoutingType((ConnType)2);
+
+ ConnRef *connRef250 = new ConnRef(router, 250);
+ ConnEnd srcPt250(Point(497.924, 385.557), 15);
+ connRef250->setSourceEndpoint(srcPt250);
+ ConnEnd dstPt250(Point(497.924, 435.557), 15);
+ connRef250->setDestEndpoint(dstPt250);
+ connRef250->setRoutingType((ConnType)2);
+
+ ConnRef *connRef251 = new ConnRef(router, 251);
+ ConnEnd srcPt251(Point(617.924, 477.557), 15);
+ connRef251->setSourceEndpoint(srcPt251);
+ ConnEnd dstPt251(Point(617.924, 527.557), 15);
+ connRef251->setDestEndpoint(dstPt251);
+ connRef251->setRoutingType((ConnType)2);
+
+ ConnRef *connRef160 = new ConnRef(router, 160);
+ ConnEnd srcPt160(Point(317.924, 161.557), 15);
+ connRef160->setSourceEndpoint(srcPt160);
+ ConnEnd dstPt160(Point(727.924, -60.6578), 15);
+ connRef160->setDestEndpoint(dstPt160);
+ connRef160->setRoutingType((ConnType)2);
+
+ ConnRef *connRef149 = new ConnRef(router, 149);
+ ConnEnd srcPt149(Point(1138.92, 161.557), 15);
+ connRef149->setSourceEndpoint(srcPt149);
+ ConnEnd dstPt149(Point(1188.92, 152.342), 15);
+ connRef149->setDestEndpoint(dstPt149);
+ connRef149->setRoutingType((ConnType)2);
+
+ ConnRef *connRef246 = new ConnRef(router, 246);
+ ConnEnd srcPt246(Point(497.924, -4.15778), 15);
+ connRef246->setSourceEndpoint(srcPt246);
+ ConnEnd dstPt246(Point(497.924, 45.8422), 15);
+ connRef246->setDestEndpoint(dstPt246);
+ connRef246->setRoutingType((ConnType)2);
+
+ ConnRef *connRef247 = new ConnRef(router, 247);
+ ConnEnd srcPt247(Point(617.924, -4.15778), 15);
+ connRef247->setSourceEndpoint(srcPt247);
+ ConnEnd dstPt247(Point(617.924, 45.8422), 15);
+ connRef247->setDestEndpoint(dstPt247);
+ connRef247->setRoutingType((ConnType)2);
+
+ ConnRef *connRef248 = new ConnRef(router, 248);
+ ConnEnd srcPt248(Point(737.924, 524.057), 15);
+ connRef248->setSourceEndpoint(srcPt248);
+ ConnEnd dstPt248(Point(737.924, 574.057), 15);
+ connRef248->setDestEndpoint(dstPt248);
+ connRef248->setRoutingType((ConnType)2);
+
+ ConnRef *connRef201 = new ConnRef(router, 201);
+ ConnEnd srcPt201(Point(507.924, 763.557), 15);
+ connRef201->setSourceEndpoint(srcPt201);
+ ConnEnd dstPt201(Point(557.924, 763.557), 15);
+ connRef201->setDestEndpoint(dstPt201);
+ connRef201->setRoutingType((ConnType)2);
+
+ ConnRef *connRef152 = new ConnRef(router, 152);
+ ConnEnd srcPt152(Point(317.924, 763.557), 15);
+ connRef152->setSourceEndpoint(srcPt152);
+ ConnEnd dstPt152(Point(367.924, 763.557), 15);
+ connRef152->setDestEndpoint(dstPt152);
+ connRef152->setRoutingType((ConnType)2);
+
+ ConnRef *connRef185 = new ConnRef(router, 185);
+ ConnEnd srcPt185(Point(797.924, 161.557), 15);
+ connRef185->setSourceEndpoint(srcPt185);
+ ConnEnd dstPt185(Point(847.924, 161.557), 15);
+ connRef185->setDestEndpoint(dstPt185);
+ connRef185->setRoutingType((ConnType)2);
+
+ ConnRef *connRef178 = new ConnRef(router, 178);
+ ConnEnd srcPt178(Point(77.9242, 527.557), 15);
+ connRef178->setSourceEndpoint(srcPt178);
+ ConnEnd dstPt178(Point(127.924, 527.557), 15);
+ connRef178->setDestEndpoint(dstPt178);
+ connRef178->setRoutingType((ConnType)2);
+
+ ConnRef *connRef235 = new ConnRef(router, 235);
+ ConnEnd srcPt235(Point(139.924, 661.557), 15);
+ connRef235->setSourceEndpoint(srcPt235);
+ ConnEnd dstPt235(Point(77.9242, 661.557), 15);
+ connRef235->setDestEndpoint(dstPt235);
+ connRef235->setRoutingType((ConnType)2);
+
+ ConnRef *connRef236 = new ConnRef(router, 236);
+ ConnEnd srcPt236(Point(137.924, 713.557), 15);
+ connRef236->setSourceEndpoint(srcPt236);
+ ConnEnd dstPt236(Point(137.924, 763.557), 15);
+ connRef236->setDestEndpoint(dstPt236);
+ connRef236->setRoutingType((ConnType)2);
+
+ ConnRef *connRef237 = new ConnRef(router, 237);
+ ConnEnd srcPt237(Point(257.924, 713.557), 15);
+ connRef237->setSourceEndpoint(srcPt237);
+ ConnEnd dstPt237(Point(257.924, 763.557), 15);
+ connRef237->setDestEndpoint(dstPt237);
+ connRef237->setRoutingType((ConnType)2);
+
+ ConnRef *connRef217 = new ConnRef(router, 217);
+ ConnEnd srcPt217(Point(747.924, 343.557), 15);
+ connRef217->setSourceEndpoint(srcPt217);
+ ConnEnd dstPt217(Point(797.924, 343.557), 15);
+ connRef217->setDestEndpoint(dstPt217);
+ connRef217->setRoutingType((ConnType)2);
+
+ ConnRef *connRef218 = new ConnRef(router, 218);
+ ConnEnd srcPt218(Point(1088.92, 388.557), 15);
+ connRef218->setSourceEndpoint(srcPt218);
+ ConnEnd dstPt218(Point(1138.92, 435.557), 15);
+ connRef218->setDestEndpoint(dstPt218);
+ connRef218->setRoutingType((ConnType)2);
+
+ ConnRef *connRef189 = new ConnRef(router, 189);
+ ConnEnd srcPt189(Point(747.924, -60.6578), 15);
+ connRef189->setSourceEndpoint(srcPt189);
+ ConnEnd dstPt189(Point(797.924, -60.6578), 15);
+ connRef189->setDestEndpoint(dstPt189);
+ connRef189->setRoutingType((ConnType)2);
+
+ ConnRef *connRef252 = new ConnRef(router, 252);
+ ConnEnd srcPt252(Point(617.924, 385.557), 15);
+ connRef252->setSourceEndpoint(srcPt252);
+ ConnEnd dstPt252(Point(617.924, 435.557), 15);
+ connRef252->setDestEndpoint(dstPt252);
+ connRef252->setRoutingType((ConnType)2);
+
+ ConnRef *connRef253 = new ConnRef(router, 253);
+ ConnEnd srcPt253(Point(857.924, 293.557), 15);
+ connRef253->setSourceEndpoint(srcPt253);
+ ConnEnd dstPt253(Point(857.924, 343.557), 15);
+ connRef253->setDestEndpoint(dstPt253);
+ connRef253->setRoutingType((ConnType)2);
+
+ ConnRef *connRef254 = new ConnRef(router, 254);
+ ConnEnd srcPt254(Point(857.924, 385.557), 15);
+ connRef254->setSourceEndpoint(srcPt254);
+ ConnEnd dstPt254(Point(857.924, 435.557), 15);
+ connRef254->setDestEndpoint(dstPt254);
+ connRef254->setRoutingType((ConnType)2);
+
+ ConnRef *connRef255 = new ConnRef(router, 255);
+ ConnEnd srcPt255(Point(857.924, 111.557), 15);
+ connRef255->setSourceEndpoint(srcPt255);
+ ConnEnd dstPt255(Point(857.924, 161.557), 15);
+ connRef255->setDestEndpoint(dstPt255);
+ connRef255->setRoutingType((ConnType)2);
+
+ ConnRef *connRef256 = new ConnRef(router, 256);
+ ConnEnd srcPt256(Point(737.924, 293.557), 15);
+ connRef256->setSourceEndpoint(srcPt256);
+ ConnEnd dstPt256(Point(737.924, 343.557), 15);
+ connRef256->setDestEndpoint(dstPt256);
+ connRef256->setRoutingType((ConnType)2);
+
+ ConnRef *connRef257 = new ConnRef(router, 257);
+ ConnEnd srcPt257(Point(1078.92, 338.557), 15);
+ connRef257->setSourceEndpoint(srcPt257);
+ ConnEnd dstPt257(Point(1078.92, 388.557), 15);
+ connRef257->setDestEndpoint(dstPt257);
+ connRef257->setRoutingType((ConnType)2);
+
+ ConnRef *connRef258 = new ConnRef(router, 258);
+ ConnEnd srcPt258(Point(1198.92, 338.557), 15);
+ connRef258->setSourceEndpoint(srcPt258);
+ ConnEnd dstPt258(Point(1198.92, 388.557), 15);
+ connRef258->setDestEndpoint(dstPt258);
+ connRef258->setRoutingType((ConnType)2);
+
+ ConnRef *connRef259 = new ConnRef(router, 259);
+ ConnEnd srcPt259(Point(1078.92, 102.342), 15);
+ connRef259->setSourceEndpoint(srcPt259);
+ ConnEnd dstPt259(Point(1078.92, 152.342), 15);
+ connRef259->setDestEndpoint(dstPt259);
+ connRef259->setRoutingType((ConnType)2);
+
+ ConnRef *connRef260 = new ConnRef(router, 260);
+ ConnEnd srcPt260(Point(1078.92, 10.3422), 15);
+ connRef260->setSourceEndpoint(srcPt260);
+ ConnEnd dstPt260(Point(1078.92, 60.3422), 15);
+ connRef260->setDestEndpoint(dstPt260);
+ connRef260->setRoutingType((ConnType)2);
+
+ ConnRef *connRef261 = new ConnRef(router, 261);
+ ConnEnd srcPt261(Point(1198.92, 102.342), 15);
+ connRef261->setSourceEndpoint(srcPt261);
+ ConnEnd dstPt261(Point(1198.92, 152.342), 15);
+ connRef261->setDestEndpoint(dstPt261);
+ connRef261->setRoutingType((ConnType)2);
+
+ ConnRef *connRef262 = new ConnRef(router, 262);
+ ConnEnd srcPt262(Point(1078.92, -110.658), 15);
+ connRef262->setSourceEndpoint(srcPt262);
+ ConnEnd dstPt262(Point(1078.92, -60.6578), 15);
+ connRef262->setDestEndpoint(dstPt262);
+ connRef262->setRoutingType((ConnType)2);
+
+ ConnRef *connRef176 = new ConnRef(router, 176);
+ ConnEnd srcPt176(Point(77.9242, 161.557), 15);
+ connRef176->setSourceEndpoint(srcPt176);
+ ConnEnd dstPt176(Point(77.9242, 357.557), 15);
+ connRef176->setDestEndpoint(dstPt176);
+ connRef176->setRoutingType((ConnType)2);
+
+ ConnRef *connRef175 = new ConnRef(router, 175);
+ ConnEnd srcPt175(Point(77.9242, 161.557), 15);
+ connRef175->setSourceEndpoint(srcPt175);
+ ConnEnd dstPt175(Point(127.924, 161.557), 15);
+ connRef175->setDestEndpoint(dstPt175);
+ connRef175->setRoutingType((ConnType)2);
+
+ ConnRef *connRef183 = new ConnRef(router, 183);
+ ConnEnd srcPt183(Point(197.924, 315.557), 15);
+ connRef183->setSourceEndpoint(srcPt183);
+ ConnEnd dstPt183(Point(247.924, 315.557), 15);
+ connRef183->setDestEndpoint(dstPt183);
+ connRef183->setRoutingType((ConnType)2);
+
+ ConnRef *connRef184 = new ConnRef(router, 184);
+ ConnEnd srcPt184(Point(677.924, 343.557), 15);
+ connRef184->setSourceEndpoint(srcPt184);
+ ConnEnd dstPt184(Point(727.924, 343.557), 15);
+ connRef184->setDestEndpoint(dstPt184);
+ connRef184->setRoutingType((ConnType)2);
+
+ ConnRef *connRef156 = new ConnRef(router, 156);
+ ConnEnd srcPt156(Point(197.924, 763.557), 15);
+ connRef156->setSourceEndpoint(srcPt156);
+ ConnEnd dstPt156(Point(247.924, 763.557), 15);
+ connRef156->setDestEndpoint(dstPt156);
+ connRef156->setRoutingType((ConnType)2);
+
+ ConnRef *connRef169 = new ConnRef(router, 169);
+ ConnEnd srcPt169(Point(1018.92, 435.557), 15);
+ connRef169->setSourceEndpoint(srcPt169);
+ ConnEnd dstPt169(Point(1068.92, 388.557), 15);
+ connRef169->setDestEndpoint(dstPt169);
+ connRef169->setRoutingType((ConnType)2);
+
+ ConnRef *connRef192 = new ConnRef(router, 192);
+ ConnEnd srcPt192(Point(197.924, 223.557), 15);
+ connRef192->setSourceEndpoint(srcPt192);
+ ConnEnd dstPt192(Point(197.924, 315.557), 15);
+ connRef192->setDestEndpoint(dstPt192);
+ connRef192->setRoutingType((ConnType)2);
+
+ ConnRef *connRef224 = new ConnRef(router, 224);
+ ConnEnd srcPt224(Point(747.924, 161.557), 15);
+ connRef224->setSourceEndpoint(srcPt224);
+ ConnEnd dstPt224(Point(797.924, 161.557), 15);
+ connRef224->setDestEndpoint(dstPt224);
+ connRef224->setRoutingType((ConnType)2);
+
+ ConnRef *connRef170 = new ConnRef(router, 170);
+ ConnEnd srcPt170(Point(1018.92, 161.557), 15);
+ connRef170->setSourceEndpoint(srcPt170);
+ ConnEnd dstPt170(Point(1068.92, 152.342), 15);
+ connRef170->setDestEndpoint(dstPt170);
+ connRef170->setRoutingType((ConnType)2);
+
+ ConnRef *connRef211 = new ConnRef(router, 211);
+ ConnEnd srcPt211(Point(507.924, 435.557), 15);
+ connRef211->setSourceEndpoint(srcPt211);
+ ConnEnd dstPt211(Point(557.924, 435.557), 15);
+ connRef211->setDestEndpoint(dstPt211);
+ connRef211->setRoutingType((ConnType)2);
+
+ ConnRef *connRef212 = new ConnRef(router, 212);
+ ConnEnd srcPt212(Point(627.924, 527.557), 15);
+ connRef212->setSourceEndpoint(srcPt212);
+ ConnEnd dstPt212(Point(677.924, 527.557), 15);
+ connRef212->setDestEndpoint(dstPt212);
+ connRef212->setRoutingType((ConnType)2);
+
+ ConnRef *connRef243 = new ConnRef(router, 243);
+ ConnEnd srcPt243(Point(617.924, 853.057), 15);
+ connRef243->setSourceEndpoint(srcPt243);
+ ConnEnd dstPt243(Point(617.924, 903.057), 15);
+ connRef243->setDestEndpoint(dstPt243);
+ connRef243->setRoutingType((ConnType)2);
+
+ ConnRef *connRef244 = new ConnRef(router, 244);
+ ConnEnd srcPt244(Point(377.924, 111.557), 15);
+ connRef244->setSourceEndpoint(srcPt244);
+ ConnEnd dstPt244(Point(377.924, 161.557), 15);
+ connRef244->setDestEndpoint(dstPt244);
+ connRef244->setRoutingType((ConnType)2);
+
+ ConnRef *connRef245 = new ConnRef(router, 245);
+ ConnEnd srcPt245(Point(377.924, -22.6578), 15);
+ connRef245->setSourceEndpoint(srcPt245);
+ ConnEnd dstPt245(Point(377.924, 27.3422), 15);
+ connRef245->setDestEndpoint(dstPt245);
+ connRef245->setRoutingType((ConnType)2);
+
+ ConnRef *connRef154 = new ConnRef(router, 154);
+ ConnEnd srcPt154(Point(317.924, 763.557), 15);
+ connRef154->setSourceEndpoint(srcPt154);
+ ConnEnd dstPt154(Point(727.924, 574.057), 15);
+ connRef154->setDestEndpoint(dstPt154);
+ connRef154->setRoutingType((ConnType)2);
+
+ ConnRef *connRef208 = new ConnRef(router, 208);
+ ConnEnd srcPt208(Point(627.924, 45.8422), 15);
+ connRef208->setSourceEndpoint(srcPt208);
+ ConnEnd dstPt208(Point(677.924, 54.8422), 15);
+ connRef208->setDestEndpoint(dstPt208);
+ connRef208->setRoutingType((ConnType)2);
+
+ ConnRef *connRef238 = new ConnRef(router, 238);
+ ConnEnd srcPt238(Point(377.924, 577.557), 15);
+ connRef238->setSourceEndpoint(srcPt238);
+ ConnEnd dstPt238(Point(377.924, 627.557), 15);
+ connRef238->setDestEndpoint(dstPt238);
+ connRef238->setRoutingType((ConnType)2);
+
+ ConnRef *connRef239 = new ConnRef(router, 239);
+ ConnEnd srcPt239(Point(377.924, 713.557), 15);
+ connRef239->setSourceEndpoint(srcPt239);
+ ConnEnd dstPt239(Point(377.924, 763.557), 15);
+ connRef239->setDestEndpoint(dstPt239);
+ connRef239->setRoutingType((ConnType)2);
+
+ ConnRef *connRef187 = new ConnRef(router, 187);
+ ConnEnd srcPt187(Point(437.924, 527.557), 15);
+ connRef187->setSourceEndpoint(srcPt187);
+ ConnEnd dstPt187(Point(487.924, 527.557), 15);
+ connRef187->setDestEndpoint(dstPt187);
+ connRef187->setRoutingType((ConnType)2);
+
+ ConnRef *connRef194 = new ConnRef(router, 194);
+ ConnEnd srcPt194(Point(147.924, 527.557), 15);
+ connRef194->setSourceEndpoint(srcPt194);
+ ConnEnd dstPt194(Point(197.924, 527.557), 15);
+ connRef194->setDestEndpoint(dstPt194);
+ connRef194->setRoutingType((ConnType)2);
+
+ ConnRef *connRef195 = new ConnRef(router, 195);
+ ConnEnd srcPt195(Point(147.924, 619.557), 15);
+ connRef195->setSourceEndpoint(srcPt195);
+ ConnEnd dstPt195(Point(197.924, 763.557), 15);
+ connRef195->setDestEndpoint(dstPt195);
+ connRef195->setRoutingType((ConnType)2);
+
+ ConnRef *connRef177 = new ConnRef(router, 177);
+ ConnEnd srcPt177(Point(557.924, 763.557), 15);
+ connRef177->setSourceEndpoint(srcPt177);
+ ConnEnd dstPt177(Point(607.924, 763.557), 15);
+ connRef177->setDestEndpoint(dstPt177);
+ connRef177->setRoutingType((ConnType)2);
+
+ ConnRef *connRef179 = new ConnRef(router, 179);
+ ConnEnd srcPt179(Point(557.924, 54.8422), 15);
+ connRef179->setSourceEndpoint(srcPt179);
+ ConnEnd dstPt179(Point(607.924, 45.8422), 15);
+ connRef179->setDestEndpoint(dstPt179);
+ connRef179->setRoutingType((ConnType)2);
+
+ ConnRef *connRef191 = new ConnRef(router, 191);
+ ConnEnd srcPt191(Point(267.924, 161.557), 15);
+ connRef191->setSourceEndpoint(srcPt191);
+ ConnEnd dstPt191(Point(317.924, 161.557), 15);
+ connRef191->setDestEndpoint(dstPt191);
+ connRef191->setRoutingType((ConnType)2);
+
+ ConnRef *connRef174 = new ConnRef(router, 174);
+ ConnEnd srcPt174(Point(437.924, 161.557), 15);
+ connRef174->setSourceEndpoint(srcPt174);
+ ConnEnd dstPt174(Point(727.924, 161.557), 15);
+ connRef174->setDestEndpoint(dstPt174);
+ connRef174->setRoutingType((ConnType)2);
+
+ ConnRef *connRef158 = new ConnRef(router, 158);
+ ConnEnd srcPt158(Point(197.924, 161.557), 15);
+ connRef158->setSourceEndpoint(srcPt158);
+ ConnEnd dstPt158(Point(247.924, 161.557), 15);
+ connRef158->setDestEndpoint(dstPt158);
+ connRef158->setRoutingType((ConnType)2);
+
+ ConnRef *connRef151 = new ConnRef(router, 151);
+ ConnEnd srcPt151(Point(317.924, 763.557), 15);
+ connRef151->setSourceEndpoint(srcPt151);
+ ConnEnd dstPt151(Point(367.924, 627.557), 15);
+ connRef151->setDestEndpoint(dstPt151);
+ connRef151->setRoutingType((ConnType)2);
+
+ ConnRef *connRef206 = new ConnRef(router, 206);
+ ConnEnd srcPt206(Point(387.924, 27.3422), 15);
+ connRef206->setSourceEndpoint(srcPt206);
+ ConnEnd dstPt206(Point(437.924, 27.3422), 15);
+ connRef206->setDestEndpoint(dstPt206);
+ connRef206->setRoutingType((ConnType)2);
+
+ ConnRef *connRef168 = new ConnRef(router, 168);
+ ConnEnd srcPt168(Point(797.924, 343.557), 15);
+ connRef168->setSourceEndpoint(srcPt168);
+ ConnEnd dstPt168(Point(847.924, 435.557), 15);
+ connRef168->setDestEndpoint(dstPt168);
+ connRef168->setRoutingType((ConnType)2);
+
+ ConnRef *connRef193 = new ConnRef(router, 193);
+ ConnEnd srcPt193(Point(77.9242, 377.557), 15);
+ connRef193->setSourceEndpoint(srcPt193);
+ ConnEnd dstPt193(Point(77.9242, 527.557), 15);
+ connRef193->setDestEndpoint(dstPt193);
+ connRef193->setRoutingType((ConnType)2);
+
+ ConnRef *connRef197 = new ConnRef(router, 197);
+ ConnEnd srcPt197(Point(147.924, 763.557), 15);
+ connRef197->setSourceEndpoint(srcPt197);
+ ConnEnd dstPt197(Point(197.924, 763.557), 15);
+ connRef197->setDestEndpoint(dstPt197);
+ connRef197->setRoutingType((ConnType)2);
+
+ ConnRef *connRef182 = new ConnRef(router, 182);
+ ConnEnd srcPt182(Point(77.9242, 763.557), 15);
+ connRef182->setSourceEndpoint(srcPt182);
+ ConnEnd dstPt182(Point(127.924, 763.557), 15);
+ connRef182->setDestEndpoint(dstPt182);
+ connRef182->setRoutingType((ConnType)2);
+
+ ConnRef *connRef150 = new ConnRef(router, 150);
+ ConnEnd srcPt150(Point(1138.92, 435.557), 15);
+ connRef150->setSourceEndpoint(srcPt150);
+ ConnEnd dstPt150(Point(1188.92, 388.557), 15);
+ connRef150->setDestEndpoint(dstPt150);
+ connRef150->setRoutingType((ConnType)2);
+
+ ConnRef *connRef190 = new ConnRef(router, 190);
+ ConnEnd srcPt190(Point(147.924, 34.8422), 15);
+ connRef190->setSourceEndpoint(srcPt190);
+ ConnEnd dstPt190(Point(197.924, 161.557), 15);
+ connRef190->setDestEndpoint(dstPt190);
+ connRef190->setRoutingType((ConnType)2);
+
+ ConnRef *connRef196 = new ConnRef(router, 196);
+ ConnEnd srcPt196(Point(77.9242, 651.557), 15);
+ connRef196->setSourceEndpoint(srcPt196);
+ ConnEnd dstPt196(Point(77.9242, 619.557), 15);
+ connRef196->setDestEndpoint(dstPt196);
+ connRef196->setRoutingType((ConnType)2);
+
+ ConnRef *connRef157 = new ConnRef(router, 157);
+ ConnEnd srcPt157(Point(147.924, 161.557), 15);
+ connRef157->setSourceEndpoint(srcPt157);
+ ConnEnd dstPt157(Point(197.924, 161.557), 15);
+ connRef157->setDestEndpoint(dstPt157);
+ connRef157->setRoutingType((ConnType)2);
+
+ ConnRef *connRef173 = new ConnRef(router, 173);
+ ConnEnd srcPt173(Point(437.924, 161.557), 15);
+ connRef173->setSourceEndpoint(srcPt173);
+ ConnEnd dstPt173(Point(487.924, 45.8422), 15);
+ connRef173->setDestEndpoint(dstPt173);
+ connRef173->setRoutingType((ConnType)2);
+
+ ConnRef *connRef159 = new ConnRef(router, 159);
+ ConnEnd srcPt159(Point(197.924, 161.557), 15);
+ connRef159->setSourceEndpoint(srcPt159);
+ ConnEnd dstPt159(Point(197.924, 203.557), 15);
+ connRef159->setDestEndpoint(dstPt159);
+ connRef159->setRoutingType((ConnType)2);
+
+ ConnRef *connRef153 = new ConnRef(router, 153);
+ ConnEnd srcPt153(Point(317.924, 763.557), 15);
+ connRef153->setSourceEndpoint(srcPt153);
+ ConnEnd dstPt153(Point(487.924, 903.057), 15);
+ connRef153->setDestEndpoint(dstPt153);
+ connRef153->setRoutingType((ConnType)2);
+
+ ConnRef *connRef163 = new ConnRef(router, 163);
+ ConnEnd srcPt163(Point(317.924, 161.557), 15);
+ connRef163->setSourceEndpoint(srcPt163);
+ ConnEnd dstPt163(Point(487.924, 435.557), 15);
+ connRef163->setDestEndpoint(dstPt163);
+ connRef163->setRoutingType((ConnType)2);
+
+ ConnRef *connRef180 = new ConnRef(router, 180);
+ ConnEnd srcPt180(Point(557.924, 435.557), 15);
+ connRef180->setSourceEndpoint(srcPt180);
+ ConnEnd dstPt180(Point(607.924, 435.557), 15);
+ connRef180->setDestEndpoint(dstPt180);
+ connRef180->setRoutingType((ConnType)2);
+
+ ConnRef *connRef204 = new ConnRef(router, 204);
+ ConnEnd srcPt204(Point(627.924, 903.057), 15);
+ connRef204->setSourceEndpoint(srcPt204);
+ ConnEnd dstPt204(Point(677.924, 903.057), 15);
+ connRef204->setDestEndpoint(dstPt204);
+ connRef204->setRoutingType((ConnType)2);
+
+ ConnRef *connRef186 = new ConnRef(router, 186);
+ ConnEnd srcPt186(Point(77.9242, 34.8422), 15);
+ connRef186->setSourceEndpoint(srcPt186);
+ ConnEnd dstPt186(Point(127.924, 34.8422), 15);
+ connRef186->setDestEndpoint(dstPt186);
+ connRef186->setRoutingType((ConnType)2);
+
+ ConnRef *connRef167 = new ConnRef(router, 167);
+ ConnEnd srcPt167(Point(797.924, 343.557), 15);
+ connRef167->setSourceEndpoint(srcPt167);
+ ConnEnd dstPt167(Point(847.924, 343.557), 15);
+ connRef167->setDestEndpoint(dstPt167);
+ connRef167->setRoutingType((ConnType)2);
+
+ ConnRef *connRef172 = new ConnRef(router, 172);
+ ConnEnd srcPt172(Point(267.924, 315.557), 15);
+ connRef172->setSourceEndpoint(srcPt172);
+ ConnEnd dstPt172(Point(437.924, 161.557), 15);
+ connRef172->setDestEndpoint(dstPt172);
+ connRef172->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/lineSegWrapperCrash7");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash8.cpp b/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash8.cpp
new file mode 100644
index 0000000..696222a
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/lineSegWrapperCrash8.cpp
@@ -0,0 +1,1884 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 0);
+
+ Polygon poly79(4);
+ poly79.ps[0] = Point(387.924, 753.557);
+ poly79.ps[1] = Point(387.924, 773.557);
+ poly79.ps[2] = Point(367.924, 773.557);
+ poly79.ps[3] = Point(367.924, 753.557);
+ new ShapeRef(router, poly79, 79);
+
+ Polygon poly58(4);
+ poly58.ps[0] = Point(97.9242, 14.8422);
+ poly58.ps[1] = Point(97.9242, 54.8422);
+ poly58.ps[2] = Point(57.9242, 54.8422);
+ poly58.ps[3] = Point(57.9242, 14.8422);
+ new ShapeRef(router, poly58, 58);
+
+ Polygon poly62(4);
+ poly62.ps[0] = Point(577.924, 629.557);
+ poly62.ps[1] = Point(577.924, 669.557);
+ poly62.ps[2] = Point(537.924, 669.557);
+ poly62.ps[3] = Point(537.924, 629.557);
+ new ShapeRef(router, poly62, 62);
+
+ Polygon poly63(4);
+ poly63.ps[0] = Point(457.924, 507.557);
+ poly63.ps[1] = Point(457.924, 547.557);
+ poly63.ps[2] = Point(417.924, 547.557);
+ poly63.ps[3] = Point(417.924, 507.557);
+ new ShapeRef(router, poly63, 63);
+
+ Polygon poly19(4);
+ poly19.ps[0] = Point(217.924, 141.557);
+ poly19.ps[1] = Point(217.924, 181.557);
+ poly19.ps[2] = Point(177.924, 181.557);
+ poly19.ps[3] = Point(177.924, 141.557);
+ new ShapeRef(router, poly19, 19);
+
+ Polygon poly48(4);
+ poly48.ps[0] = Point(97.9242, 743.557);
+ poly48.ps[1] = Point(97.9242, 783.557);
+ poly48.ps[2] = Point(57.9242, 783.557);
+ poly48.ps[3] = Point(57.9242, 743.557);
+ new ShapeRef(router, poly48, 48);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(1158.92, -80.6578);
+ poly8.ps[1] = Point(1158.92, -40.6578);
+ poly8.ps[2] = Point(1118.92, -40.6578);
+ poly8.ps[3] = Point(1118.92, -80.6578);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly1(4);
+ poly1.ps[0] = Point(817.924, 840.057);
+ poly1.ps[1] = Point(817.924, 880.057);
+ poly1.ps[2] = Point(777.924, 880.057);
+ poly1.ps[3] = Point(777.924, 840.057);
+ new ShapeRef(router, poly1, 1);
+
+ Polygon poly24(4);
+ poly24.ps[0] = Point(457.924, 743.557);
+ poly24.ps[1] = Point(457.924, 783.557);
+ poly24.ps[2] = Point(417.924, 783.557);
+ poly24.ps[3] = Point(417.924, 743.557);
+ new ShapeRef(router, poly24, 24);
+
+ Polygon poly69(4);
+ poly69.ps[0] = Point(267.924, 151.557);
+ poly69.ps[1] = Point(267.924, 171.557);
+ poly69.ps[2] = Point(247.924, 171.557);
+ poly69.ps[3] = Point(247.924, 151.557);
+ new ShapeRef(router, poly69, 69);
+
+ Polygon poly125(4);
+ poly125.ps[0] = Point(405.924, -42.6578);
+ poly125.ps[1] = Point(405.924, -2.65778);
+ poly125.ps[2] = Point(349.924, -2.65778);
+ poly125.ps[3] = Point(349.924, -42.6578);
+ new ShapeRef(router, poly125, 125);
+
+ Polygon poly126(4);
+ poly126.ps[0] = Point(525.924, -24.1578);
+ poly126.ps[1] = Point(525.924, 15.8422);
+ poly126.ps[2] = Point(469.924, 15.8422);
+ poly126.ps[3] = Point(469.924, -24.1578);
+ new ShapeRef(router, poly126, 126);
+
+ Polygon poly127(4);
+ poly127.ps[0] = Point(645.924, -24.1578);
+ poly127.ps[1] = Point(645.924, 15.8422);
+ poly127.ps[2] = Point(589.924, 15.8422);
+ poly127.ps[3] = Point(589.924, -24.1578);
+ new ShapeRef(router, poly127, 127);
+
+ Polygon poly109(4);
+ poly109.ps[0] = Point(285.924, 91.5565);
+ poly109.ps[1] = Point(285.924, 131.557);
+ poly109.ps[2] = Point(229.924, 131.557);
+ poly109.ps[3] = Point(229.924, 91.5565);
+ new ShapeRef(router, poly109, 109);
+
+ Polygon poly80(4);
+ poly80.ps[0] = Point(507.924, 753.557);
+ poly80.ps[1] = Point(507.924, 773.557);
+ poly80.ps[2] = Point(487.924, 773.557);
+ poly80.ps[3] = Point(487.924, 753.557);
+ new ShapeRef(router, poly80, 80);
+
+ Polygon poly29(4);
+ poly29.ps[0] = Point(1038.92, 415.557);
+ poly29.ps[1] = Point(1038.92, 455.557);
+ poly29.ps[2] = Point(998.924, 455.557);
+ poly29.ps[3] = Point(998.924, 415.557);
+ new ShapeRef(router, poly29, 29);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(937.924, -80.6578);
+ poly10.ps[1] = Point(937.924, -40.6578);
+ poly10.ps[2] = Point(897.924, -40.6578);
+ poly10.ps[3] = Point(897.924, -80.6578);
+ new ShapeRef(router, poly10, 10);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(1371.92, 29.8422);
+ poly4.ps[1] = Point(1371.92, 69.8422);
+ poly4.ps[2] = Point(1331.92, 69.8422);
+ poly4.ps[3] = Point(1331.92, 29.8422);
+ new ShapeRef(router, poly4, 4);
+
+ Polygon poly12(4);
+ poly12.ps[0] = Point(1038.92, 260.557);
+ poly12.ps[1] = Point(1038.92, 300.557);
+ poly12.ps[2] = Point(998.924, 300.557);
+ poly12.ps[3] = Point(998.924, 260.557);
+ new ShapeRef(router, poly12, 12);
+
+ Polygon poly16(4);
+ poly16.ps[0] = Point(337.924, 743.557);
+ poly16.ps[1] = Point(337.924, 783.557);
+ poly16.ps[2] = Point(297.924, 783.557);
+ poly16.ps[3] = Point(297.924, 743.557);
+ new ShapeRef(router, poly16, 16);
+
+ Polygon poly91(4);
+ poly91.ps[0] = Point(627.924, 517.557);
+ poly91.ps[1] = Point(627.924, 537.557);
+ poly91.ps[2] = Point(607.924, 537.557);
+ poly91.ps[3] = Point(607.924, 517.557);
+ new ShapeRef(router, poly91, 91);
+
+ Polygon poly90(4);
+ poly90.ps[0] = Point(507.924, 425.557);
+ poly90.ps[1] = Point(507.924, 445.557);
+ poly90.ps[2] = Point(487.924, 445.557);
+ poly90.ps[3] = Point(487.924, 425.557);
+ new ShapeRef(router, poly90, 90);
+
+ Polygon poly119(4);
+ poly119.ps[0] = Point(405.924, 693.557);
+ poly119.ps[1] = Point(405.924, 733.557);
+ poly119.ps[2] = Point(349.924, 733.557);
+ poly119.ps[3] = Point(349.924, 693.557);
+ new ShapeRef(router, poly119, 119);
+
+ Polygon poly120(4);
+ poly120.ps[0] = Point(525.924, 693.557);
+ poly120.ps[1] = Point(525.924, 733.557);
+ poly120.ps[2] = Point(469.924, 733.557);
+ poly120.ps[3] = Point(469.924, 693.557);
+ new ShapeRef(router, poly120, 120);
+
+ Polygon poly89(4);
+ poly89.ps[0] = Point(507.924, 517.557);
+ poly89.ps[1] = Point(507.924, 537.557);
+ poly89.ps[2] = Point(487.924, 537.557);
+ poly89.ps[3] = Point(487.924, 517.557);
+ new ShapeRef(router, poly89, 89);
+
+ Polygon poly88(4);
+ poly88.ps[0] = Point(747.924, 564.057);
+ poly88.ps[1] = Point(747.924, 584.057);
+ poly88.ps[2] = Point(727.924, 584.057);
+ poly88.ps[3] = Point(727.924, 564.057);
+ new ShapeRef(router, poly88, 88);
+
+ Polygon poly87(4);
+ poly87.ps[0] = Point(627.924, 35.8422);
+ poly87.ps[1] = Point(627.924, 55.8422);
+ poly87.ps[2] = Point(607.924, 55.8422);
+ poly87.ps[3] = Point(607.924, 35.8422);
+ new ShapeRef(router, poly87, 87);
+
+ Polygon poly86(4);
+ poly86.ps[0] = Point(507.924, 35.8422);
+ poly86.ps[1] = Point(507.924, 55.8422);
+ poly86.ps[2] = Point(487.924, 55.8422);
+ poly86.ps[3] = Point(487.924, 35.8422);
+ new ShapeRef(router, poly86, 86);
+
+ Polygon poly85(4);
+ poly85.ps[0] = Point(387.924, 17.3422);
+ poly85.ps[1] = Point(387.924, 37.3422);
+ poly85.ps[2] = Point(367.924, 37.3422);
+ poly85.ps[3] = Point(367.924, 17.3422);
+ new ShapeRef(router, poly85, 85);
+
+ Polygon poly74(4);
+ poly74.ps[0] = Point(147.924, 609.557);
+ poly74.ps[1] = Point(147.924, 629.557);
+ poly74.ps[2] = Point(127.924, 629.557);
+ poly74.ps[3] = Point(127.924, 609.557);
+ new ShapeRef(router, poly74, 74);
+
+ Polygon poly28(4);
+ poly28.ps[0] = Point(817.924, 323.557);
+ poly28.ps[1] = Point(817.924, 363.557);
+ poly28.ps[2] = Point(777.924, 363.557);
+ poly28.ps[3] = Point(777.924, 323.557);
+ new ShapeRef(router, poly28, 28);
+
+ Polygon poly61(4);
+ poly61.ps[0] = Point(577.924, -44.6578);
+ poly61.ps[1] = Point(577.924, -4.65778);
+ poly61.ps[2] = Point(537.924, -4.65778);
+ poly61.ps[3] = Point(537.924, -44.6578);
+ new ShapeRef(router, poly61, 61);
+
+ Polygon poly15(4);
+ poly15.ps[0] = Point(1158.92, 415.557);
+ poly15.ps[1] = Point(1158.92, 455.557);
+ poly15.ps[2] = Point(1118.92, 455.557);
+ poly15.ps[3] = Point(1118.92, 415.557);
+ new ShapeRef(router, poly15, 15);
+
+ Polygon poly49(4);
+ poly49.ps[0] = Point(45.9242, 169.75);
+ poly49.ps[1] = Point(45.9242, 334.75);
+ poly49.ps[2] = Point(-242.076, 334.75);
+ poly49.ps[3] = Point(-242.076, 169.75);
+ new ShapeRef(router, poly49, 49);
+
+ Polygon poly20(4);
+ poly20.ps[0] = Point(337.924, 507.557);
+ poly20.ps[1] = Point(337.924, 547.557);
+ poly20.ps[2] = Point(297.924, 547.557);
+ poly20.ps[3] = Point(297.924, 507.557);
+ new ShapeRef(router, poly20, 20);
+
+ Polygon poly66(4);
+ poly66.ps[0] = Point(747.924, -70.6578);
+ poly66.ps[1] = Point(747.924, -50.6578);
+ poly66.ps[2] = Point(727.924, -50.6578);
+ poly66.ps[3] = Point(727.924, -70.6578);
+ new ShapeRef(router, poly66, 66);
+
+ Polygon poly21(4);
+ poly21.ps[0] = Point(937.924, 141.557);
+ poly21.ps[1] = Point(937.924, 181.557);
+ poly21.ps[2] = Point(897.924, 181.557);
+ poly21.ps[3] = Point(897.924, 141.557);
+ new ShapeRef(router, poly21, 21);
+
+ Polygon poly68(4);
+ poly68.ps[0] = Point(147.924, 151.557);
+ poly68.ps[1] = Point(147.924, 171.557);
+ poly68.ps[2] = Point(127.924, 171.557);
+ poly68.ps[3] = Point(127.924, 151.557);
+ new ShapeRef(router, poly68, 68);
+
+ Polygon poly70(4);
+ poly70.ps[0] = Point(207.924, 203.557);
+ poly70.ps[1] = Point(207.924, 223.557);
+ poly70.ps[2] = Point(187.924, 223.557);
+ poly70.ps[3] = Point(187.924, 203.557);
+ new ShapeRef(router, poly70, 70);
+
+ Polygon poly38(4);
+ poly38.ps[0] = Point(217.924, 507.557);
+ poly38.ps[1] = Point(217.924, 547.557);
+ poly38.ps[2] = Point(177.924, 547.557);
+ poly38.ps[3] = Point(177.924, 507.557);
+ new ShapeRef(router, poly38, 38);
+
+ Polygon poly51(4);
+ poly51.ps[0] = Point(1038.92, 323.557);
+ poly51.ps[1] = Point(1038.92, 363.557);
+ poly51.ps[2] = Point(998.924, 363.557);
+ poly51.ps[3] = Point(998.924, 323.557);
+ new ShapeRef(router, poly51, 51);
+
+ Polygon poly42(4);
+ poly42.ps[0] = Point(697.924, 415.557);
+ poly42.ps[1] = Point(697.924, 455.557);
+ poly42.ps[2] = Point(657.924, 455.557);
+ poly42.ps[3] = Point(657.924, 415.557);
+ new ShapeRef(router, poly42, 42);
+
+ Polygon poly59(4);
+ poly59.ps[0] = Point(937.924, 323.557);
+ poly59.ps[1] = Point(937.924, 363.557);
+ poly59.ps[2] = Point(897.924, 363.557);
+ poly59.ps[3] = Point(897.924, 323.557);
+ new ShapeRef(router, poly59, 59);
+
+ Polygon poly32(4);
+ poly32.ps[0] = Point(1038.92, 141.557);
+ poly32.ps[1] = Point(1038.92, 181.557);
+ poly32.ps[2] = Point(998.924, 181.557);
+ poly32.ps[3] = Point(998.924, 141.557);
+ new ShapeRef(router, poly32, 32);
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(1371.92, -80.6578);
+ poly6.ps[1] = Point(1371.92, -40.6578);
+ poly6.ps[2] = Point(1331.92, -40.6578);
+ poly6.ps[3] = Point(1331.92, -80.6578);
+ new ShapeRef(router, poly6, 6);
+
+ Polygon poly40(4);
+ poly40.ps[0] = Point(97.9242, 141.557);
+ poly40.ps[1] = Point(97.9242, 181.557);
+ poly40.ps[2] = Point(57.9242, 181.557);
+ poly40.ps[3] = Point(57.9242, 141.557);
+ new ShapeRef(router, poly40, 40);
+
+ Polygon poly43(4);
+ poly43.ps[0] = Point(1038.92, 1.84222);
+ poly43.ps[1] = Point(1038.92, 41.8422);
+ poly43.ps[2] = Point(998.924, 41.8422);
+ poly43.ps[3] = Point(998.924, 1.84222);
+ new ShapeRef(router, poly43, 43);
+
+ Polygon poly35(4);
+ poly35.ps[0] = Point(1158.92, 40.3422);
+ poly35.ps[1] = Point(1158.92, 80.3422);
+ poly35.ps[2] = Point(1118.92, 80.3422);
+ poly35.ps[3] = Point(1118.92, 40.3422);
+ new ShapeRef(router, poly35, 35);
+
+ Polygon poly81(4);
+ poly81.ps[0] = Point(627.924, 753.557);
+ poly81.ps[1] = Point(627.924, 773.557);
+ poly81.ps[2] = Point(607.924, 773.557);
+ poly81.ps[3] = Point(607.924, 753.557);
+ new ShapeRef(router, poly81, 81);
+
+ Polygon poly111(4);
+ poly111.ps[0] = Point(285.924, 245.557);
+ poly111.ps[1] = Point(285.924, 285.557);
+ poly111.ps[2] = Point(229.924, 285.557);
+ poly111.ps[3] = Point(229.924, 245.557);
+ new ShapeRef(router, poly111, 111);
+
+ Polygon poly128(4);
+ poly128.ps[0] = Point(765.924, 504.057);
+ poly128.ps[1] = Point(765.924, 544.057);
+ poly128.ps[2] = Point(709.924, 544.057);
+ poly128.ps[3] = Point(709.924, 504.057);
+ new ShapeRef(router, poly128, 128);
+
+ Polygon poly129(4);
+ poly129.ps[0] = Point(525.924, 457.557);
+ poly129.ps[1] = Point(525.924, 497.557);
+ poly129.ps[2] = Point(469.924, 497.557);
+ poly129.ps[3] = Point(469.924, 457.557);
+ new ShapeRef(router, poly129, 129);
+
+ Polygon poly130(4);
+ poly130.ps[0] = Point(525.924, 365.557);
+ poly130.ps[1] = Point(525.924, 405.557);
+ poly130.ps[2] = Point(469.924, 405.557);
+ poly130.ps[3] = Point(469.924, 365.557);
+ new ShapeRef(router, poly130, 130);
+
+ Polygon poly18(4);
+ poly18.ps[0] = Point(217.924, 743.557);
+ poly18.ps[1] = Point(217.924, 783.557);
+ poly18.ps[2] = Point(177.924, 783.557);
+ poly18.ps[3] = Point(177.924, 743.557);
+ new ShapeRef(router, poly18, 18);
+
+ Polygon poly34(4);
+ poly34.ps[0] = Point(1278.92, 323.557);
+ poly34.ps[1] = Point(1278.92, 363.557);
+ poly34.ps[2] = Point(1238.92, 363.557);
+ poly34.ps[3] = Point(1238.92, 323.557);
+ new ShapeRef(router, poly34, 34);
+
+ Polygon poly57(4);
+ poly57.ps[0] = Point(817.924, 141.557);
+ poly57.ps[1] = Point(817.924, 181.557);
+ poly57.ps[2] = Point(777.924, 181.557);
+ poly57.ps[3] = Point(777.924, 141.557);
+ new ShapeRef(router, poly57, 57);
+
+ Polygon poly83(4);
+ poly83.ps[0] = Point(627.924, 893.057);
+ poly83.ps[1] = Point(627.924, 913.057);
+ poly83.ps[2] = Point(607.924, 913.057);
+ poly83.ps[3] = Point(607.924, 893.057);
+ new ShapeRef(router, poly83, 83);
+
+ Polygon poly123(4);
+ poly123.ps[0] = Point(645.924, 833.057);
+ poly123.ps[1] = Point(645.924, 873.057);
+ poly123.ps[2] = Point(589.924, 873.057);
+ poly123.ps[3] = Point(589.924, 833.057);
+ new ShapeRef(router, poly123, 123);
+
+ Polygon poly124(4);
+ poly124.ps[0] = Point(405.924, 91.5565);
+ poly124.ps[1] = Point(405.924, 131.557);
+ poly124.ps[2] = Point(349.924, 131.557);
+ poly124.ps[3] = Point(349.924, 91.5565);
+ new ShapeRef(router, poly124, 124);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(1278.92, -80.6578);
+ poly7.ps[1] = Point(1278.92, -40.6578);
+ poly7.ps[2] = Point(1238.92, -40.6578);
+ poly7.ps[3] = Point(1238.92, -80.6578);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly44(4);
+ poly44.ps[0] = Point(97.9242, 507.557);
+ poly44.ps[1] = Point(97.9242, 547.557);
+ poly44.ps[2] = Point(57.9242, 547.557);
+ poly44.ps[3] = Point(57.9242, 507.557);
+ new ShapeRef(router, poly44, 44);
+
+ Polygon poly30(4);
+ poly30.ps[0] = Point(1278.92, 415.557);
+ poly30.ps[1] = Point(1278.92, 455.557);
+ poly30.ps[2] = Point(1238.92, 455.557);
+ poly30.ps[3] = Point(1238.92, 415.557);
+ new ShapeRef(router, poly30, 30);
+
+ Polygon poly71(4);
+ poly71.ps[0] = Point(267.924, 305.557);
+ poly71.ps[1] = Point(267.924, 325.557);
+ poly71.ps[2] = Point(247.924, 325.557);
+ poly71.ps[3] = Point(247.924, 305.557);
+ new ShapeRef(router, poly71, 71);
+
+ Polygon poly41(4);
+ poly41.ps[0] = Point(577.924, 743.557);
+ poly41.ps[1] = Point(577.924, 783.557);
+ poly41.ps[2] = Point(537.924, 783.557);
+ poly41.ps[3] = Point(537.924, 743.557);
+ new ShapeRef(router, poly41, 41);
+
+ Polygon poly39(4);
+ poly39.ps[0] = Point(457.924, 141.557);
+ poly39.ps[1] = Point(457.924, 181.557);
+ poly39.ps[2] = Point(417.924, 181.557);
+ poly39.ps[3] = Point(417.924, 141.557);
+ new ShapeRef(router, poly39, 39);
+
+ Polygon poly47(4);
+ poly47.ps[0] = Point(697.924, 271.557);
+ poly47.ps[1] = Point(697.924, 311.557);
+ poly47.ps[2] = Point(657.924, 311.557);
+ poly47.ps[3] = Point(657.924, 271.557);
+ new ShapeRef(router, poly47, 47);
+
+ Polygon poly73(4);
+ poly73.ps[0] = Point(147.924, 517.557);
+ poly73.ps[1] = Point(147.924, 537.557);
+ poly73.ps[2] = Point(127.924, 537.557);
+ poly73.ps[3] = Point(127.924, 517.557);
+ new ShapeRef(router, poly73, 73);
+
+ Polygon poly11(4);
+ poly11.ps[0] = Point(817.924, -80.6578);
+ poly11.ps[1] = Point(817.924, -40.6578);
+ poly11.ps[2] = Point(777.924, -40.6578);
+ poly11.ps[3] = Point(777.924, -80.6578);
+ new ShapeRef(router, poly11, 11);
+
+ Polygon poly75(4);
+ poly75.ps[0] = Point(87.9242, 651.557);
+ poly75.ps[1] = Point(87.9242, 671.557);
+ poly75.ps[2] = Point(67.9242, 671.557);
+ poly75.ps[3] = Point(67.9242, 651.557);
+ new ShapeRef(router, poly75, 75);
+
+ Polygon poly27(4);
+ poly27.ps[0] = Point(577.924, 507.557);
+ poly27.ps[1] = Point(577.924, 547.557);
+ poly27.ps[2] = Point(537.924, 547.557);
+ poly27.ps[3] = Point(537.924, 507.557);
+ new ShapeRef(router, poly27, 27);
+
+ Polygon poly31(4);
+ poly31.ps[0] = Point(1278.92, 141.557);
+ poly31.ps[1] = Point(1278.92, 181.557);
+ poly31.ps[2] = Point(1238.92, 181.557);
+ poly31.ps[3] = Point(1238.92, 141.557);
+ new ShapeRef(router, poly31, 31);
+
+ Polygon poly67(4);
+ poly67.ps[0] = Point(147.924, 24.8422);
+ poly67.ps[1] = Point(147.924, 44.8422);
+ poly67.ps[2] = Point(127.924, 44.8422);
+ poly67.ps[3] = Point(127.924, 24.8422);
+ new ShapeRef(router, poly67, 67);
+
+ Polygon poly50(4);
+ poly50.ps[0] = Point(272.5, -82.1578);
+ poly50.ps[1] = Point(272.5, -47.1578);
+ poly50.ps[2] = Point(35.5, -47.1578);
+ poly50.ps[3] = Point(35.5, -82.1578);
+ new ShapeRef(router, poly50, 50);
+
+ Polygon poly46(4);
+ poly46.ps[0] = Point(577.924, 415.557);
+ poly46.ps[1] = Point(577.924, 455.557);
+ poly46.ps[2] = Point(537.924, 455.557);
+ poly46.ps[3] = Point(537.924, 415.557);
+ new ShapeRef(router, poly46, 46);
+
+ Polygon poly64(4);
+ poly64.ps[0] = Point(817.924, 554.057);
+ poly64.ps[1] = Point(817.924, 594.057);
+ poly64.ps[2] = Point(777.924, 594.057);
+ poly64.ps[3] = Point(777.924, 554.057);
+ new ShapeRef(router, poly64, 64);
+
+ Polygon poly23(4);
+ poly23.ps[0] = Point(337.924, 141.557);
+ poly23.ps[1] = Point(337.924, 181.557);
+ poly23.ps[2] = Point(297.924, 181.557);
+ poly23.ps[3] = Point(297.924, 141.557);
+ new ShapeRef(router, poly23, 23);
+
+ Polygon poly72(4);
+ poly72.ps[0] = Point(87.9242, 357.557);
+ poly72.ps[1] = Point(87.9242, 377.557);
+ poly72.ps[2] = Point(67.9242, 377.557);
+ poly72.ps[3] = Point(67.9242, 357.557);
+ new ShapeRef(router, poly72, 72);
+
+ Polygon poly14(4);
+ poly14.ps[0] = Point(1158.92, 141.557);
+ poly14.ps[1] = Point(1158.92, 181.557);
+ poly14.ps[2] = Point(1118.92, 181.557);
+ poly14.ps[3] = Point(1118.92, 141.557);
+ new ShapeRef(router, poly14, 14);
+
+ Polygon poly45(4);
+ poly45.ps[0] = Point(577.924, 34.8422);
+ poly45.ps[1] = Point(577.924, 74.8422);
+ poly45.ps[2] = Point(537.924, 74.8422);
+ poly45.ps[3] = Point(537.924, 34.8422);
+ new ShapeRef(router, poly45, 45);
+
+ Polygon poly82(4);
+ poly82.ps[0] = Point(507.924, 893.057);
+ poly82.ps[1] = Point(507.924, 913.057);
+ poly82.ps[2] = Point(487.924, 913.057);
+ poly82.ps[3] = Point(487.924, 893.057);
+ new ShapeRef(router, poly82, 82);
+
+ Polygon poly56(4);
+ poly56.ps[0] = Point(457.924, -44.6578);
+ poly56.ps[1] = Point(457.924, -4.65778);
+ poly56.ps[2] = Point(417.924, -4.65778);
+ poly56.ps[3] = Point(417.924, -44.6578);
+ new ShapeRef(router, poly56, 56);
+
+ Polygon poly17(4);
+ poly17.ps[0] = Point(577.924, 883.057);
+ poly17.ps[1] = Point(577.924, 923.057);
+ poly17.ps[2] = Point(537.924, 923.057);
+ poly17.ps[3] = Point(537.924, 883.057);
+ new ShapeRef(router, poly17, 17);
+
+ Polygon poly33(4);
+ poly33.ps[0] = Point(937.924, 415.557);
+ poly33.ps[1] = Point(937.924, 455.557);
+ poly33.ps[2] = Point(897.924, 455.557);
+ poly33.ps[3] = Point(897.924, 415.557);
+ new ShapeRef(router, poly33, 33);
+
+ Polygon poly22(4);
+ poly22.ps[0] = Point(697.924, 34.8422);
+ poly22.ps[1] = Point(697.924, 74.8422);
+ poly22.ps[2] = Point(657.924, 74.8422);
+ poly22.ps[3] = Point(657.924, 34.8422);
+ new ShapeRef(router, poly22, 22);
+
+ Polygon poly13(4);
+ poly13.ps[0] = Point(1158.92, 323.557);
+ poly13.ps[1] = Point(1158.92, 363.557);
+ poly13.ps[2] = Point(1118.92, 363.557);
+ poly13.ps[3] = Point(1118.92, 323.557);
+ new ShapeRef(router, poly13, 13);
+
+ Polygon poly52(4);
+ poly52.ps[0] = Point(217.924, 295.557);
+ poly52.ps[1] = Point(217.924, 335.557);
+ poly52.ps[2] = Point(177.924, 335.557);
+ poly52.ps[3] = Point(177.924, 295.557);
+ new ShapeRef(router, poly52, 52);
+
+ Polygon poly84(4);
+ poly84.ps[0] = Point(387.924, 151.557);
+ poly84.ps[1] = Point(387.924, 171.557);
+ poly84.ps[2] = Point(367.924, 171.557);
+ poly84.ps[3] = Point(367.924, 151.557);
+ new ShapeRef(router, poly84, 84);
+
+ Polygon poly78(4);
+ poly78.ps[0] = Point(387.924, 617.557);
+ poly78.ps[1] = Point(387.924, 637.557);
+ poly78.ps[2] = Point(367.924, 637.557);
+ poly78.ps[3] = Point(367.924, 617.557);
+ new ShapeRef(router, poly78, 78);
+
+ Polygon poly114(4);
+ poly114.ps[0] = Point(165.924, 549.557);
+ poly114.ps[1] = Point(165.924, 589.557);
+ poly114.ps[2] = Point(109.924, 589.557);
+ poly114.ps[3] = Point(109.924, 549.557);
+ new ShapeRef(router, poly114, 114);
+
+ Polygon poly107(4);
+ poly107.ps[0] = Point(165.924, -35.1578);
+ poly107.ps[1] = Point(165.924, 4.84222);
+ poly107.ps[2] = Point(109.924, 4.84222);
+ poly107.ps[3] = Point(109.924, -35.1578);
+ new ShapeRef(router, poly107, 107);
+
+ Polygon poly106(4);
+ poly106.ps[0] = Point(765.924, -130.658);
+ poly106.ps[1] = Point(765.924, -90.6578);
+ poly106.ps[2] = Point(709.924, -90.6578);
+ poly106.ps[3] = Point(709.924, -130.658);
+ new ShapeRef(router, poly106, 106);
+
+ Polygon poly105(4);
+ poly105.ps[0] = Point(747.924, 850.057);
+ poly105.ps[1] = Point(747.924, 870.057);
+ poly105.ps[2] = Point(727.924, 870.057);
+ poly105.ps[3] = Point(727.924, 850.057);
+ new ShapeRef(router, poly105, 105);
+
+ Polygon poly104(4);
+ poly104.ps[0] = Point(747.924, 151.557);
+ poly104.ps[1] = Point(747.924, 171.557);
+ poly104.ps[2] = Point(727.924, 171.557);
+ poly104.ps[3] = Point(727.924, 151.557);
+ new ShapeRef(router, poly104, 104);
+
+ Polygon poly103(4);
+ poly103.ps[0] = Point(968.924, 270.557);
+ poly103.ps[1] = Point(968.924, 290.557);
+ poly103.ps[2] = Point(948.924, 290.557);
+ poly103.ps[3] = Point(948.924, 270.557);
+ new ShapeRef(router, poly103, 103);
+
+ Polygon poly102(4);
+ poly102.ps[0] = Point(1088.92, -70.6578);
+ poly102.ps[1] = Point(1088.92, -50.6578);
+ poly102.ps[2] = Point(1068.92, -50.6578);
+ poly102.ps[3] = Point(1068.92, -70.6578);
+ new ShapeRef(router, poly102, 102);
+
+ Polygon poly101(4);
+ poly101.ps[0] = Point(1208.92, 142.342);
+ poly101.ps[1] = Point(1208.92, 162.342);
+ poly101.ps[2] = Point(1188.92, 162.342);
+ poly101.ps[3] = Point(1188.92, 142.342);
+ new ShapeRef(router, poly101, 101);
+
+ Polygon poly100(4);
+ poly100.ps[0] = Point(1088.92, 50.3422);
+ poly100.ps[1] = Point(1088.92, 70.3422);
+ poly100.ps[2] = Point(1068.92, 70.3422);
+ poly100.ps[3] = Point(1068.92, 50.3422);
+ new ShapeRef(router, poly100, 100);
+
+ Polygon poly115(4);
+ poly115.ps[0] = Point(167.924, 641.557);
+ poly115.ps[1] = Point(167.924, 681.557);
+ poly115.ps[2] = Point(111.924, 681.557);
+ poly115.ps[3] = Point(111.924, 641.557);
+ new ShapeRef(router, poly115, 115);
+
+ Polygon poly116(4);
+ poly116.ps[0] = Point(165.924, 693.557);
+ poly116.ps[1] = Point(165.924, 733.557);
+ poly116.ps[2] = Point(109.924, 733.557);
+ poly116.ps[3] = Point(109.924, 693.557);
+ new ShapeRef(router, poly116, 116);
+
+ Polygon poly99(4);
+ poly99.ps[0] = Point(1088.92, 142.342);
+ poly99.ps[1] = Point(1088.92, 162.342);
+ poly99.ps[2] = Point(1068.92, 162.342);
+ poly99.ps[3] = Point(1068.92, 142.342);
+ new ShapeRef(router, poly99, 99);
+
+ Polygon poly98(4);
+ poly98.ps[0] = Point(1208.92, 378.557);
+ poly98.ps[1] = Point(1208.92, 398.557);
+ poly98.ps[2] = Point(1188.92, 398.557);
+ poly98.ps[3] = Point(1188.92, 378.557);
+ new ShapeRef(router, poly98, 98);
+
+ Polygon poly97(4);
+ poly97.ps[0] = Point(1088.92, 378.557);
+ poly97.ps[1] = Point(1088.92, 398.557);
+ poly97.ps[2] = Point(1068.92, 398.557);
+ poly97.ps[3] = Point(1068.92, 378.557);
+ new ShapeRef(router, poly97, 97);
+
+ Polygon poly96(4);
+ poly96.ps[0] = Point(747.924, 333.557);
+ poly96.ps[1] = Point(747.924, 353.557);
+ poly96.ps[2] = Point(727.924, 353.557);
+ poly96.ps[3] = Point(727.924, 333.557);
+ new ShapeRef(router, poly96, 96);
+
+ Polygon poly95(4);
+ poly95.ps[0] = Point(867.924, 151.557);
+ poly95.ps[1] = Point(867.924, 171.557);
+ poly95.ps[2] = Point(847.924, 171.557);
+ poly95.ps[3] = Point(847.924, 151.557);
+ new ShapeRef(router, poly95, 95);
+
+ Polygon poly94(4);
+ poly94.ps[0] = Point(867.924, 425.557);
+ poly94.ps[1] = Point(867.924, 445.557);
+ poly94.ps[2] = Point(847.924, 445.557);
+ poly94.ps[3] = Point(847.924, 425.557);
+ new ShapeRef(router, poly94, 94);
+
+ Polygon poly93(4);
+ poly93.ps[0] = Point(867.924, 333.557);
+ poly93.ps[1] = Point(867.924, 353.557);
+ poly93.ps[2] = Point(847.924, 353.557);
+ poly93.ps[3] = Point(847.924, 333.557);
+ new ShapeRef(router, poly93, 93);
+
+ Polygon poly92(4);
+ poly92.ps[0] = Point(627.924, 425.557);
+ poly92.ps[1] = Point(627.924, 445.557);
+ poly92.ps[2] = Point(607.924, 445.557);
+ poly92.ps[3] = Point(607.924, 425.557);
+ new ShapeRef(router, poly92, 92);
+
+ Polygon poly117(4);
+ poly117.ps[0] = Point(285.924, 693.557);
+ poly117.ps[1] = Point(285.924, 733.557);
+ poly117.ps[2] = Point(229.924, 733.557);
+ poly117.ps[3] = Point(229.924, 693.557);
+ new ShapeRef(router, poly117, 117);
+
+ Polygon poly118(4);
+ poly118.ps[0] = Point(405.924, 557.557);
+ poly118.ps[1] = Point(405.924, 597.557);
+ poly118.ps[2] = Point(349.924, 597.557);
+ poly118.ps[3] = Point(349.924, 557.557);
+ new ShapeRef(router, poly118, 118);
+
+ Polygon poly36(4);
+ poly36.ps[0] = Point(697.924, 507.557);
+ poly36.ps[1] = Point(697.924, 547.557);
+ poly36.ps[2] = Point(657.924, 547.557);
+ poly36.ps[3] = Point(657.924, 507.557);
+ new ShapeRef(router, poly36, 36);
+
+ Polygon poly55(4);
+ poly55.ps[0] = Point(457.924, 7.34222);
+ poly55.ps[1] = Point(457.924, 47.3422);
+ poly55.ps[2] = Point(417.924, 47.3422);
+ poly55.ps[3] = Point(417.924, 7.34222);
+ new ShapeRef(router, poly55, 55);
+
+ Polygon poly26(4);
+ poly26.ps[0] = Point(697.924, 743.557);
+ poly26.ps[1] = Point(697.924, 783.557);
+ poly26.ps[2] = Point(657.924, 783.557);
+ poly26.ps[3] = Point(657.924, 743.557);
+ new ShapeRef(router, poly26, 26);
+
+ Polygon poly37(4);
+ poly37.ps[0] = Point(457.924, 607.557);
+ poly37.ps[1] = Point(457.924, 647.557);
+ poly37.ps[2] = Point(417.924, 647.557);
+ poly37.ps[3] = Point(417.924, 607.557);
+ new ShapeRef(router, poly37, 37);
+
+ Polygon poly77(4);
+ poly77.ps[0] = Point(267.924, 753.557);
+ poly77.ps[1] = Point(267.924, 773.557);
+ poly77.ps[2] = Point(247.924, 773.557);
+ poly77.ps[3] = Point(247.924, 753.557);
+ new ShapeRef(router, poly77, 77);
+
+ Polygon poly60(4);
+ poly60.ps[0] = Point(937.924, 1.84222);
+ poly60.ps[1] = Point(937.924, 41.8422);
+ poly60.ps[2] = Point(897.924, 41.8422);
+ poly60.ps[3] = Point(897.924, 1.84222);
+ new ShapeRef(router, poly60, 60);
+
+ Polygon poly65(4);
+ poly65.ps[0] = Point(97.9242, 599.557);
+ poly65.ps[1] = Point(97.9242, 639.557);
+ poly65.ps[2] = Point(57.9242, 639.557);
+ poly65.ps[3] = Point(57.9242, 599.557);
+ new ShapeRef(router, poly65, 65);
+
+ Polygon poly108(4);
+ poly108.ps[0] = Point(165.924, 91.5565);
+ poly108.ps[1] = Point(165.924, 131.557);
+ poly108.ps[2] = Point(109.924, 131.557);
+ poly108.ps[3] = Point(109.924, 91.5565);
+ new ShapeRef(router, poly108, 108);
+
+ Polygon poly54(4);
+ poly54.ps[0] = Point(697.924, 323.557);
+ poly54.ps[1] = Point(697.924, 363.557);
+ poly54.ps[2] = Point(657.924, 363.557);
+ poly54.ps[3] = Point(657.924, 323.557);
+ new ShapeRef(router, poly54, 54);
+
+ Polygon poly112(4);
+ poly112.ps[0] = Point(167.924, 347.557);
+ poly112.ps[1] = Point(167.924, 387.557);
+ poly112.ps[2] = Point(111.924, 387.557);
+ poly112.ps[3] = Point(111.924, 347.557);
+ new ShapeRef(router, poly112, 112);
+
+ Polygon poly113(4);
+ poly113.ps[0] = Point(165.924, 457.557);
+ poly113.ps[1] = Point(165.924, 497.557);
+ poly113.ps[2] = Point(109.924, 497.557);
+ poly113.ps[3] = Point(109.924, 457.557);
+ new ShapeRef(router, poly113, 113);
+
+ Polygon poly110(4);
+ poly110.ps[0] = Point(287.924, 193.557);
+ poly110.ps[1] = Point(287.924, 233.557);
+ poly110.ps[2] = Point(231.924, 233.557);
+ poly110.ps[3] = Point(231.924, 193.557);
+ new ShapeRef(router, poly110, 110);
+
+ Polygon poly25(4);
+ poly25.ps[0] = Point(697.924, 883.057);
+ poly25.ps[1] = Point(697.924, 923.057);
+ poly25.ps[2] = Point(657.924, 923.057);
+ poly25.ps[3] = Point(657.924, 883.057);
+ new ShapeRef(router, poly25, 25);
+
+ Polygon poly53(4);
+ poly53.ps[0] = Point(577.924, 323.557);
+ poly53.ps[1] = Point(577.924, 363.557);
+ poly53.ps[2] = Point(537.924, 363.557);
+ poly53.ps[3] = Point(537.924, 323.557);
+ new ShapeRef(router, poly53, 53);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(1278.92, -22.1578);
+ poly3.ps[1] = Point(1278.92, 17.8422);
+ poly3.ps[2] = Point(1238.92, 17.8422);
+ poly3.ps[3] = Point(1238.92, -22.1578);
+ new ShapeRef(router, poly3, 3);
+
+ Polygon poly141(4);
+ poly141.ps[0] = Point(1226.92, 82.3422);
+ poly141.ps[1] = Point(1226.92, 122.342);
+ poly141.ps[2] = Point(1170.92, 122.342);
+ poly141.ps[3] = Point(1170.92, 82.3422);
+ new ShapeRef(router, poly141, 141);
+
+ Polygon poly142(4);
+ poly142.ps[0] = Point(1106.92, -130.658);
+ poly142.ps[1] = Point(1106.92, -90.6578);
+ poly142.ps[2] = Point(1050.92, -90.6578);
+ poly142.ps[3] = Point(1050.92, -130.658);
+ new ShapeRef(router, poly142, 142);
+
+ Polygon poly143(4);
+ poly143.ps[0] = Point(986.924, 210.557);
+ poly143.ps[1] = Point(986.924, 250.557);
+ poly143.ps[2] = Point(930.924, 250.557);
+ poly143.ps[3] = Point(930.924, 210.557);
+ new ShapeRef(router, poly143, 143);
+
+ Polygon poly144(4);
+ poly144.ps[0] = Point(765.924, 91.5565);
+ poly144.ps[1] = Point(765.924, 131.557);
+ poly144.ps[2] = Point(709.924, 131.557);
+ poly144.ps[3] = Point(709.924, 91.5565);
+ new ShapeRef(router, poly144, 144);
+
+ Polygon poly145(4);
+ poly145.ps[0] = Point(765.924, 790.057);
+ poly145.ps[1] = Point(765.924, 830.057);
+ poly145.ps[2] = Point(709.924, 830.057);
+ poly145.ps[3] = Point(709.924, 790.057);
+ new ShapeRef(router, poly145, 145);
+
+ Polygon poly146(4);
+ poly146.ps[0] = Point(45.9242, 232.5);
+ poly146.ps[1] = Point(45.9242, 272.5);
+ poly146.ps[2] = Point(-14.0758, 272.5);
+ poly146.ps[3] = Point(-14.0758, 232.5);
+ new ShapeRef(router, poly146, 146);
+
+ Polygon poly147(4);
+ poly147.ps[0] = Point(-26.0758, 274.75);
+ poly147.ps[1] = Point(-26.0758, 334.75);
+ poly147.ps[2] = Point(-66.0758, 334.75);
+ poly147.ps[3] = Point(-66.0758, 274.75);
+ new ShapeRef(router, poly147, 147);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(1371.92, -22.1578);
+ poly5.ps[1] = Point(1371.92, 17.8422);
+ poly5.ps[2] = Point(1331.92, 17.8422);
+ poly5.ps[3] = Point(1331.92, -22.1578);
+ new ShapeRef(router, poly5, 5);
+
+ Polygon poly131(4);
+ poly131.ps[0] = Point(645.924, 457.557);
+ poly131.ps[1] = Point(645.924, 497.557);
+ poly131.ps[2] = Point(589.924, 497.557);
+ poly131.ps[3] = Point(589.924, 457.557);
+ new ShapeRef(router, poly131, 131);
+
+ Polygon poly132(4);
+ poly132.ps[0] = Point(645.924, 365.557);
+ poly132.ps[1] = Point(645.924, 405.557);
+ poly132.ps[2] = Point(589.924, 405.557);
+ poly132.ps[3] = Point(589.924, 365.557);
+ new ShapeRef(router, poly132, 132);
+
+ Polygon poly133(4);
+ poly133.ps[0] = Point(885.924, 273.557);
+ poly133.ps[1] = Point(885.924, 313.557);
+ poly133.ps[2] = Point(829.924, 313.557);
+ poly133.ps[3] = Point(829.924, 273.557);
+ new ShapeRef(router, poly133, 133);
+
+ Polygon poly121(4);
+ poly121.ps[0] = Point(645.924, 693.557);
+ poly121.ps[1] = Point(645.924, 733.557);
+ poly121.ps[2] = Point(589.924, 733.557);
+ poly121.ps[3] = Point(589.924, 693.557);
+ new ShapeRef(router, poly121, 121);
+
+ Polygon poly122(4);
+ poly122.ps[0] = Point(525.924, 833.057);
+ poly122.ps[1] = Point(525.924, 873.057);
+ poly122.ps[2] = Point(469.924, 873.057);
+ poly122.ps[3] = Point(469.924, 833.057);
+ new ShapeRef(router, poly122, 122);
+
+ Polygon poly134(4);
+ poly134.ps[0] = Point(885.924, 365.557);
+ poly134.ps[1] = Point(885.924, 405.557);
+ poly134.ps[2] = Point(829.924, 405.557);
+ poly134.ps[3] = Point(829.924, 365.557);
+ new ShapeRef(router, poly134, 134);
+
+ Polygon poly135(4);
+ poly135.ps[0] = Point(885.924, 91.5565);
+ poly135.ps[1] = Point(885.924, 131.557);
+ poly135.ps[2] = Point(829.924, 131.557);
+ poly135.ps[3] = Point(829.924, 91.5565);
+ new ShapeRef(router, poly135, 135);
+
+ Polygon poly136(4);
+ poly136.ps[0] = Point(765.924, 273.557);
+ poly136.ps[1] = Point(765.924, 313.557);
+ poly136.ps[2] = Point(709.924, 313.557);
+ poly136.ps[3] = Point(709.924, 273.557);
+ new ShapeRef(router, poly136, 136);
+
+ Polygon poly137(4);
+ poly137.ps[0] = Point(1106.92, 318.557);
+ poly137.ps[1] = Point(1106.92, 358.557);
+ poly137.ps[2] = Point(1050.92, 358.557);
+ poly137.ps[3] = Point(1050.92, 318.557);
+ new ShapeRef(router, poly137, 137);
+
+ Polygon poly138(4);
+ poly138.ps[0] = Point(1226.92, 318.557);
+ poly138.ps[1] = Point(1226.92, 358.557);
+ poly138.ps[2] = Point(1170.92, 358.557);
+ poly138.ps[3] = Point(1170.92, 318.557);
+ new ShapeRef(router, poly138, 138);
+
+ Polygon poly139(4);
+ poly139.ps[0] = Point(1106.92, 82.3422);
+ poly139.ps[1] = Point(1106.92, 122.342);
+ poly139.ps[2] = Point(1050.92, 122.342);
+ poly139.ps[3] = Point(1050.92, 82.3422);
+ new ShapeRef(router, poly139, 139);
+
+ Polygon poly140(4);
+ poly140.ps[0] = Point(1106.92, -9.65778);
+ poly140.ps[1] = Point(1106.92, 30.3422);
+ poly140.ps[2] = Point(1050.92, 30.3422);
+ poly140.ps[3] = Point(1050.92, -9.65778);
+ new ShapeRef(router, poly140, 140);
+
+ Polygon poly76(4);
+ poly76.ps[0] = Point(147.924, 753.557);
+ poly76.ps[1] = Point(147.924, 773.557);
+ poly76.ps[2] = Point(127.924, 773.557);
+ poly76.ps[3] = Point(127.924, 753.557);
+ new ShapeRef(router, poly76, 76);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(1038.92, -80.6578);
+ poly9.ps[1] = Point(1038.92, -40.6578);
+ poly9.ps[2] = Point(998.924, -40.6578);
+ poly9.ps[3] = Point(998.924, -80.6578);
+ new ShapeRef(router, poly9, 9);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(577.924, 795.557);
+ poly2.ps[1] = Point(577.924, 835.557);
+ poly2.ps[2] = Point(537.924, 835.557);
+ poly2.ps[3] = Point(537.924, 795.557);
+ new ShapeRef(router, poly2, 2);
+
+ ConnRef *connRef207 = new ConnRef(router, 207);
+ ConnEnd srcPt207(Point(507.924, 45.8422), 15);
+ connRef207->setSourceEndpoint(srcPt207);
+ ConnEnd dstPt207(Point(557.924, 54.8422), 15);
+ connRef207->setDestEndpoint(dstPt207);
+ connRef207->setRoutingType((ConnType)2);
+
+ ConnRef *connRef208 = new ConnRef(router, 208);
+ ConnEnd srcPt208(Point(627.924, 45.8422), 15);
+ connRef208->setSourceEndpoint(srcPt208);
+ ConnEnd dstPt208(Point(677.924, 54.8422), 15);
+ connRef208->setDestEndpoint(dstPt208);
+ connRef208->setRoutingType((ConnType)2);
+
+ ConnRef *connRef209 = new ConnRef(router, 209);
+ ConnEnd srcPt209(Point(747.924, 574.057), 15);
+ connRef209->setSourceEndpoint(srcPt209);
+ ConnEnd dstPt209(Point(797.924, 574.057), 15);
+ connRef209->setDestEndpoint(dstPt209);
+ connRef209->setRoutingType((ConnType)2);
+
+ ConnRef *connRef210 = new ConnRef(router, 210);
+ ConnEnd srcPt210(Point(507.924, 527.557), 15);
+ connRef210->setSourceEndpoint(srcPt210);
+ ConnEnd dstPt210(Point(557.924, 527.557), 15);
+ connRef210->setDestEndpoint(dstPt210);
+ connRef210->setRoutingType((ConnType)2);
+
+ ConnRef *connRef211 = new ConnRef(router, 211);
+ ConnEnd srcPt211(Point(507.924, 435.557), 15);
+ connRef211->setSourceEndpoint(srcPt211);
+ ConnEnd dstPt211(Point(557.924, 435.557), 15);
+ connRef211->setDestEndpoint(dstPt211);
+ connRef211->setRoutingType((ConnType)2);
+
+ ConnRef *connRef212 = new ConnRef(router, 212);
+ ConnEnd srcPt212(Point(627.924, 527.557), 15);
+ connRef212->setSourceEndpoint(srcPt212);
+ ConnEnd dstPt212(Point(677.924, 527.557), 15);
+ connRef212->setDestEndpoint(dstPt212);
+ connRef212->setRoutingType((ConnType)2);
+
+ ConnRef *connRef213 = new ConnRef(router, 213);
+ ConnEnd srcPt213(Point(627.924, 435.557), 15);
+ connRef213->setSourceEndpoint(srcPt213);
+ ConnEnd dstPt213(Point(677.924, 435.557), 15);
+ connRef213->setDestEndpoint(dstPt213);
+ connRef213->setRoutingType((ConnType)2);
+
+ ConnRef *connRef214 = new ConnRef(router, 214);
+ ConnEnd srcPt214(Point(867.924, 343.557), 15);
+ connRef214->setSourceEndpoint(srcPt214);
+ ConnEnd dstPt214(Point(917.924, 343.557), 15);
+ connRef214->setDestEndpoint(dstPt214);
+ connRef214->setRoutingType((ConnType)2);
+
+ ConnRef *connRef215 = new ConnRef(router, 215);
+ ConnEnd srcPt215(Point(867.924, 435.557), 15);
+ connRef215->setSourceEndpoint(srcPt215);
+ ConnEnd dstPt215(Point(917.924, 435.557), 15);
+ connRef215->setDestEndpoint(dstPt215);
+ connRef215->setRoutingType((ConnType)2);
+
+ ConnRef *connRef216 = new ConnRef(router, 216);
+ ConnEnd srcPt216(Point(867.924, 161.557), 15);
+ connRef216->setSourceEndpoint(srcPt216);
+ ConnEnd dstPt216(Point(917.924, 161.557), 15);
+ connRef216->setDestEndpoint(dstPt216);
+ connRef216->setRoutingType((ConnType)2);
+
+ ConnRef *connRef217 = new ConnRef(router, 217);
+ ConnEnd srcPt217(Point(747.924, 343.557), 15);
+ connRef217->setSourceEndpoint(srcPt217);
+ ConnEnd dstPt217(Point(797.924, 343.557), 15);
+ connRef217->setDestEndpoint(dstPt217);
+ connRef217->setRoutingType((ConnType)2);
+
+ ConnRef *connRef218 = new ConnRef(router, 218);
+ ConnEnd srcPt218(Point(1088.92, 388.557), 15);
+ connRef218->setSourceEndpoint(srcPt218);
+ ConnEnd dstPt218(Point(1138.92, 435.557), 15);
+ connRef218->setDestEndpoint(dstPt218);
+ connRef218->setRoutingType((ConnType)2);
+
+ ConnRef *connRef219 = new ConnRef(router, 219);
+ ConnEnd srcPt219(Point(1208.92, 388.557), 15);
+ connRef219->setSourceEndpoint(srcPt219);
+ ConnEnd dstPt219(Point(1258.92, 435.557), 15);
+ connRef219->setDestEndpoint(dstPt219);
+ connRef219->setRoutingType((ConnType)2);
+
+ ConnRef *connRef220 = new ConnRef(router, 220);
+ ConnEnd srcPt220(Point(1088.92, 152.342), 15);
+ connRef220->setSourceEndpoint(srcPt220);
+ ConnEnd dstPt220(Point(1138.92, 161.557), 15);
+ connRef220->setDestEndpoint(dstPt220);
+ connRef220->setRoutingType((ConnType)2);
+
+ ConnRef *connRef221 = new ConnRef(router, 221);
+ ConnEnd srcPt221(Point(1088.92, 60.3422), 15);
+ connRef221->setSourceEndpoint(srcPt221);
+ ConnEnd dstPt221(Point(1138.92, 60.3422), 15);
+ connRef221->setDestEndpoint(dstPt221);
+ connRef221->setRoutingType((ConnType)2);
+
+ ConnRef *connRef222 = new ConnRef(router, 222);
+ ConnEnd srcPt222(Point(1208.92, 152.342), 15);
+ connRef222->setSourceEndpoint(srcPt222);
+ ConnEnd dstPt222(Point(1258.92, 161.557), 15);
+ connRef222->setDestEndpoint(dstPt222);
+ connRef222->setRoutingType((ConnType)2);
+
+ ConnRef *connRef223 = new ConnRef(router, 223);
+ ConnEnd srcPt223(Point(1088.92, -60.6578), 15);
+ connRef223->setSourceEndpoint(srcPt223);
+ ConnEnd dstPt223(Point(1138.92, -60.6578), 15);
+ connRef223->setDestEndpoint(dstPt223);
+ connRef223->setRoutingType((ConnType)2);
+
+ ConnRef *connRef224 = new ConnRef(router, 224);
+ ConnEnd srcPt224(Point(747.924, 161.557), 15);
+ connRef224->setSourceEndpoint(srcPt224);
+ ConnEnd dstPt224(Point(797.924, 161.557), 15);
+ connRef224->setDestEndpoint(dstPt224);
+ connRef224->setRoutingType((ConnType)2);
+
+ ConnRef *connRef225 = new ConnRef(router, 225);
+ ConnEnd srcPt225(Point(747.924, 860.057), 15);
+ connRef225->setSourceEndpoint(srcPt225);
+ ConnEnd dstPt225(Point(797.924, 860.057), 15);
+ connRef225->setDestEndpoint(dstPt225);
+ connRef225->setRoutingType((ConnType)2);
+
+ ConnRef *connRef226 = new ConnRef(router, 226);
+ ConnEnd srcPt226(Point(737.924, -110.658), 15);
+ connRef226->setSourceEndpoint(srcPt226);
+ ConnEnd dstPt226(Point(737.924, -60.6578), 15);
+ connRef226->setDestEndpoint(dstPt226);
+ connRef226->setRoutingType((ConnType)2);
+
+ ConnRef *connRef227 = new ConnRef(router, 227);
+ ConnEnd srcPt227(Point(137.924, -15.1578), 15);
+ connRef227->setSourceEndpoint(srcPt227);
+ ConnEnd dstPt227(Point(137.924, 34.8422), 15);
+ connRef227->setDestEndpoint(dstPt227);
+ connRef227->setRoutingType((ConnType)2);
+
+ ConnRef *connRef228 = new ConnRef(router, 228);
+ ConnEnd srcPt228(Point(137.924, 111.557), 15);
+ connRef228->setSourceEndpoint(srcPt228);
+ ConnEnd dstPt228(Point(137.924, 161.557), 15);
+ connRef228->setDestEndpoint(dstPt228);
+ connRef228->setRoutingType((ConnType)2);
+
+ ConnRef *connRef229 = new ConnRef(router, 229);
+ ConnEnd srcPt229(Point(257.924, 111.557), 15);
+ connRef229->setSourceEndpoint(srcPt229);
+ ConnEnd dstPt229(Point(257.924, 161.557), 15);
+ connRef229->setDestEndpoint(dstPt229);
+ connRef229->setRoutingType((ConnType)2);
+
+ ConnRef *connRef230 = new ConnRef(router, 230);
+ ConnEnd srcPt230(Point(259.924, 213.557), 15);
+ connRef230->setSourceEndpoint(srcPt230);
+ ConnEnd dstPt230(Point(197.924, 213.557), 15);
+ connRef230->setDestEndpoint(dstPt230);
+ connRef230->setRoutingType((ConnType)2);
+
+ ConnRef *connRef231 = new ConnRef(router, 231);
+ ConnEnd srcPt231(Point(257.924, 265.557), 15);
+ connRef231->setSourceEndpoint(srcPt231);
+ ConnEnd dstPt231(Point(257.924, 315.557), 15);
+ connRef231->setDestEndpoint(dstPt231);
+ connRef231->setRoutingType((ConnType)2);
+
+ ConnRef *connRef184 = new ConnRef(router, 184);
+ ConnEnd srcPt184(Point(677.924, 343.557), 15);
+ connRef184->setSourceEndpoint(srcPt184);
+ ConnEnd dstPt184(Point(727.924, 343.557), 15);
+ connRef184->setDestEndpoint(dstPt184);
+ connRef184->setRoutingType((ConnType)2);
+
+ ConnRef *connRef185 = new ConnRef(router, 185);
+ ConnEnd srcPt185(Point(797.924, 161.557), 15);
+ connRef185->setSourceEndpoint(srcPt185);
+ ConnEnd dstPt185(Point(847.924, 161.557), 15);
+ connRef185->setDestEndpoint(dstPt185);
+ connRef185->setRoutingType((ConnType)2);
+
+ ConnRef *connRef186 = new ConnRef(router, 186);
+ ConnEnd srcPt186(Point(77.9242, 34.8422), 15);
+ connRef186->setSourceEndpoint(srcPt186);
+ ConnEnd dstPt186(Point(127.924, 34.8422), 15);
+ connRef186->setDestEndpoint(dstPt186);
+ connRef186->setRoutingType((ConnType)2);
+
+ ConnRef *connRef187 = new ConnRef(router, 187);
+ ConnEnd srcPt187(Point(437.924, 527.557), 15);
+ connRef187->setSourceEndpoint(srcPt187);
+ ConnEnd dstPt187(Point(487.924, 527.557), 15);
+ connRef187->setDestEndpoint(dstPt187);
+ connRef187->setRoutingType((ConnType)2);
+
+ ConnRef *connRef188 = new ConnRef(router, 188);
+ ConnEnd srcPt188(Point(77.9242, 619.557), 15);
+ connRef188->setSourceEndpoint(srcPt188);
+ ConnEnd dstPt188(Point(127.924, 619.557), 15);
+ connRef188->setDestEndpoint(dstPt188);
+ connRef188->setRoutingType((ConnType)2);
+
+ ConnRef *connRef189 = new ConnRef(router, 189);
+ ConnEnd srcPt189(Point(747.924, -60.6578), 15);
+ connRef189->setSourceEndpoint(srcPt189);
+ ConnEnd dstPt189(Point(797.924, -60.6578), 15);
+ connRef189->setDestEndpoint(dstPt189);
+ connRef189->setRoutingType((ConnType)2);
+
+ ConnRef *connRef190 = new ConnRef(router, 190);
+ ConnEnd srcPt190(Point(147.924, 34.8422), 15);
+ connRef190->setSourceEndpoint(srcPt190);
+ ConnEnd dstPt190(Point(197.924, 161.557), 15);
+ connRef190->setDestEndpoint(dstPt190);
+ connRef190->setRoutingType((ConnType)2);
+
+ ConnRef *connRef191 = new ConnRef(router, 191);
+ ConnEnd srcPt191(Point(267.924, 161.557), 15);
+ connRef191->setSourceEndpoint(srcPt191);
+ ConnEnd dstPt191(Point(317.924, 161.557), 15);
+ connRef191->setDestEndpoint(dstPt191);
+ connRef191->setRoutingType((ConnType)2);
+
+ ConnRef *connRef192 = new ConnRef(router, 192);
+ ConnEnd srcPt192(Point(197.924, 223.557), 15);
+ connRef192->setSourceEndpoint(srcPt192);
+ ConnEnd dstPt192(Point(197.924, 315.557), 15);
+ connRef192->setDestEndpoint(dstPt192);
+ connRef192->setRoutingType((ConnType)2);
+
+ ConnRef *connRef193 = new ConnRef(router, 193);
+ ConnEnd srcPt193(Point(77.9242, 377.557), 15);
+ connRef193->setSourceEndpoint(srcPt193);
+ ConnEnd dstPt193(Point(77.9242, 527.557), 15);
+ connRef193->setDestEndpoint(dstPt193);
+ connRef193->setRoutingType((ConnType)2);
+
+ ConnRef *connRef194 = new ConnRef(router, 194);
+ ConnEnd srcPt194(Point(147.924, 527.557), 15);
+ connRef194->setSourceEndpoint(srcPt194);
+ ConnEnd dstPt194(Point(197.924, 527.557), 15);
+ connRef194->setDestEndpoint(dstPt194);
+ connRef194->setRoutingType((ConnType)2);
+
+ ConnRef *connRef195 = new ConnRef(router, 195);
+ ConnEnd srcPt195(Point(147.924, 619.557), 15);
+ connRef195->setSourceEndpoint(srcPt195);
+ ConnEnd dstPt195(Point(197.924, 763.557), 15);
+ connRef195->setDestEndpoint(dstPt195);
+ connRef195->setRoutingType((ConnType)2);
+
+ ConnRef *connRef196 = new ConnRef(router, 196);
+ ConnEnd srcPt196(Point(77.9242, 651.557), 15);
+ connRef196->setSourceEndpoint(srcPt196);
+ ConnEnd dstPt196(Point(77.9242, 619.557), 15);
+ connRef196->setDestEndpoint(dstPt196);
+ connRef196->setRoutingType((ConnType)2);
+
+ ConnRef *connRef197 = new ConnRef(router, 197);
+ ConnEnd srcPt197(Point(147.924, 763.557), 15);
+ connRef197->setSourceEndpoint(srcPt197);
+ ConnEnd dstPt197(Point(197.924, 763.557), 15);
+ connRef197->setDestEndpoint(dstPt197);
+ connRef197->setRoutingType((ConnType)2);
+
+ ConnRef *connRef198 = new ConnRef(router, 198);
+ ConnEnd srcPt198(Point(267.924, 763.557), 15);
+ connRef198->setSourceEndpoint(srcPt198);
+ ConnEnd dstPt198(Point(317.924, 763.557), 15);
+ connRef198->setDestEndpoint(dstPt198);
+ connRef198->setRoutingType((ConnType)2);
+
+ ConnRef *connRef199 = new ConnRef(router, 199);
+ ConnEnd srcPt199(Point(387.924, 627.557), 15);
+ connRef199->setSourceEndpoint(srcPt199);
+ ConnEnd dstPt199(Point(437.924, 627.557), 15);
+ connRef199->setDestEndpoint(dstPt199);
+ connRef199->setRoutingType((ConnType)2);
+
+ ConnRef *connRef200 = new ConnRef(router, 200);
+ ConnEnd srcPt200(Point(387.924, 763.557), 15);
+ connRef200->setSourceEndpoint(srcPt200);
+ ConnEnd dstPt200(Point(437.924, 763.557), 15);
+ connRef200->setDestEndpoint(dstPt200);
+ connRef200->setRoutingType((ConnType)2);
+
+ ConnRef *connRef201 = new ConnRef(router, 201);
+ ConnEnd srcPt201(Point(507.924, 763.557), 15);
+ connRef201->setSourceEndpoint(srcPt201);
+ ConnEnd dstPt201(Point(557.924, 763.557), 15);
+ connRef201->setDestEndpoint(dstPt201);
+ connRef201->setRoutingType((ConnType)2);
+
+ ConnRef *connRef202 = new ConnRef(router, 202);
+ ConnEnd srcPt202(Point(627.924, 763.557), 15);
+ connRef202->setSourceEndpoint(srcPt202);
+ ConnEnd dstPt202(Point(677.924, 763.557), 15);
+ connRef202->setDestEndpoint(dstPt202);
+ connRef202->setRoutingType((ConnType)2);
+
+ ConnRef *connRef203 = new ConnRef(router, 203);
+ ConnEnd srcPt203(Point(507.924, 903.057), 15);
+ connRef203->setSourceEndpoint(srcPt203);
+ ConnEnd dstPt203(Point(557.924, 903.057), 15);
+ connRef203->setDestEndpoint(dstPt203);
+ connRef203->setRoutingType((ConnType)2);
+
+ ConnRef *connRef204 = new ConnRef(router, 204);
+ ConnEnd srcPt204(Point(627.924, 903.057), 15);
+ connRef204->setSourceEndpoint(srcPt204);
+ ConnEnd dstPt204(Point(677.924, 903.057), 15);
+ connRef204->setDestEndpoint(dstPt204);
+ connRef204->setRoutingType((ConnType)2);
+
+ ConnRef *connRef205 = new ConnRef(router, 205);
+ ConnEnd srcPt205(Point(387.924, 161.557), 15);
+ connRef205->setSourceEndpoint(srcPt205);
+ ConnEnd dstPt205(Point(437.924, 161.557), 15);
+ connRef205->setDestEndpoint(dstPt205);
+ connRef205->setRoutingType((ConnType)2);
+
+ ConnRef *connRef206 = new ConnRef(router, 206);
+ ConnEnd srcPt206(Point(387.924, 27.3422), 15);
+ connRef206->setSourceEndpoint(srcPt206);
+ ConnEnd dstPt206(Point(437.924, 27.3422), 15);
+ connRef206->setDestEndpoint(dstPt206);
+ connRef206->setRoutingType((ConnType)2);
+
+ ConnRef *connRef232 = new ConnRef(router, 232);
+ ConnEnd srcPt232(Point(139.924, 367.557), 15);
+ connRef232->setSourceEndpoint(srcPt232);
+ ConnEnd dstPt232(Point(77.9242, 367.557), 15);
+ connRef232->setDestEndpoint(dstPt232);
+ connRef232->setRoutingType((ConnType)2);
+
+ ConnRef *connRef233 = new ConnRef(router, 233);
+ ConnEnd srcPt233(Point(137.924, 477.557), 15);
+ connRef233->setSourceEndpoint(srcPt233);
+ ConnEnd dstPt233(Point(137.924, 527.557), 15);
+ connRef233->setDestEndpoint(dstPt233);
+ connRef233->setRoutingType((ConnType)2);
+
+ ConnRef *connRef234 = new ConnRef(router, 234);
+ ConnEnd srcPt234(Point(137.924, 569.557), 15);
+ connRef234->setSourceEndpoint(srcPt234);
+ ConnEnd dstPt234(Point(137.924, 619.557), 15);
+ connRef234->setDestEndpoint(dstPt234);
+ connRef234->setRoutingType((ConnType)2);
+
+ ConnRef *connRef235 = new ConnRef(router, 235);
+ ConnEnd srcPt235(Point(139.924, 661.557), 15);
+ connRef235->setSourceEndpoint(srcPt235);
+ ConnEnd dstPt235(Point(77.9242, 661.557), 15);
+ connRef235->setDestEndpoint(dstPt235);
+ connRef235->setRoutingType((ConnType)2);
+
+ ConnRef *connRef236 = new ConnRef(router, 236);
+ ConnEnd srcPt236(Point(137.924, 713.557), 15);
+ connRef236->setSourceEndpoint(srcPt236);
+ ConnEnd dstPt236(Point(137.924, 763.557), 15);
+ connRef236->setDestEndpoint(dstPt236);
+ connRef236->setRoutingType((ConnType)2);
+
+ ConnRef *connRef237 = new ConnRef(router, 237);
+ ConnEnd srcPt237(Point(257.924, 713.557), 15);
+ connRef237->setSourceEndpoint(srcPt237);
+ ConnEnd dstPt237(Point(257.924, 763.557), 15);
+ connRef237->setDestEndpoint(dstPt237);
+ connRef237->setRoutingType((ConnType)2);
+
+ ConnRef *connRef238 = new ConnRef(router, 238);
+ ConnEnd srcPt238(Point(377.924, 577.557), 15);
+ connRef238->setSourceEndpoint(srcPt238);
+ ConnEnd dstPt238(Point(377.924, 627.557), 15);
+ connRef238->setDestEndpoint(dstPt238);
+ connRef238->setRoutingType((ConnType)2);
+
+ ConnRef *connRef239 = new ConnRef(router, 239);
+ ConnEnd srcPt239(Point(377.924, 713.557), 15);
+ connRef239->setSourceEndpoint(srcPt239);
+ ConnEnd dstPt239(Point(377.924, 763.557), 15);
+ connRef239->setDestEndpoint(dstPt239);
+ connRef239->setRoutingType((ConnType)2);
+
+ ConnRef *connRef240 = new ConnRef(router, 240);
+ ConnEnd srcPt240(Point(497.924, 713.557), 15);
+ connRef240->setSourceEndpoint(srcPt240);
+ ConnEnd dstPt240(Point(497.924, 763.557), 15);
+ connRef240->setDestEndpoint(dstPt240);
+ connRef240->setRoutingType((ConnType)2);
+
+ ConnRef *connRef241 = new ConnRef(router, 241);
+ ConnEnd srcPt241(Point(617.924, 713.557), 15);
+ connRef241->setSourceEndpoint(srcPt241);
+ ConnEnd dstPt241(Point(617.924, 763.557), 15);
+ connRef241->setDestEndpoint(dstPt241);
+ connRef241->setRoutingType((ConnType)2);
+
+ ConnRef *connRef242 = new ConnRef(router, 242);
+ ConnEnd srcPt242(Point(497.924, 853.057), 15);
+ connRef242->setSourceEndpoint(srcPt242);
+ ConnEnd dstPt242(Point(497.924, 903.057), 15);
+ connRef242->setDestEndpoint(dstPt242);
+ connRef242->setRoutingType((ConnType)2);
+
+ ConnRef *connRef243 = new ConnRef(router, 243);
+ ConnEnd srcPt243(Point(617.924, 853.057), 15);
+ connRef243->setSourceEndpoint(srcPt243);
+ ConnEnd dstPt243(Point(617.924, 903.057), 15);
+ connRef243->setDestEndpoint(dstPt243);
+ connRef243->setRoutingType((ConnType)2);
+
+ ConnRef *connRef244 = new ConnRef(router, 244);
+ ConnEnd srcPt244(Point(377.924, 111.557), 15);
+ connRef244->setSourceEndpoint(srcPt244);
+ ConnEnd dstPt244(Point(377.924, 161.557), 15);
+ connRef244->setDestEndpoint(dstPt244);
+ connRef244->setRoutingType((ConnType)2);
+
+ ConnRef *connRef245 = new ConnRef(router, 245);
+ ConnEnd srcPt245(Point(377.924, -22.6578), 15);
+ connRef245->setSourceEndpoint(srcPt245);
+ ConnEnd dstPt245(Point(377.924, 27.3422), 15);
+ connRef245->setDestEndpoint(dstPt245);
+ connRef245->setRoutingType((ConnType)2);
+
+ ConnRef *connRef246 = new ConnRef(router, 246);
+ ConnEnd srcPt246(Point(497.924, -4.15778), 15);
+ connRef246->setSourceEndpoint(srcPt246);
+ ConnEnd dstPt246(Point(497.924, 45.8422), 15);
+ connRef246->setDestEndpoint(dstPt246);
+ connRef246->setRoutingType((ConnType)2);
+
+ ConnRef *connRef247 = new ConnRef(router, 247);
+ ConnEnd srcPt247(Point(617.924, -4.15778), 15);
+ connRef247->setSourceEndpoint(srcPt247);
+ ConnEnd dstPt247(Point(617.924, 45.8422), 15);
+ connRef247->setDestEndpoint(dstPt247);
+ connRef247->setRoutingType((ConnType)2);
+
+ ConnRef *connRef248 = new ConnRef(router, 248);
+ ConnEnd srcPt248(Point(737.924, 524.057), 15);
+ connRef248->setSourceEndpoint(srcPt248);
+ ConnEnd dstPt248(Point(737.924, 574.057), 15);
+ connRef248->setDestEndpoint(dstPt248);
+ connRef248->setRoutingType((ConnType)2);
+
+ ConnRef *connRef249 = new ConnRef(router, 249);
+ ConnEnd srcPt249(Point(497.924, 477.557), 15);
+ connRef249->setSourceEndpoint(srcPt249);
+ ConnEnd dstPt249(Point(497.924, 527.557), 15);
+ connRef249->setDestEndpoint(dstPt249);
+ connRef249->setRoutingType((ConnType)2);
+
+ ConnRef *connRef250 = new ConnRef(router, 250);
+ ConnEnd srcPt250(Point(497.924, 385.557), 15);
+ connRef250->setSourceEndpoint(srcPt250);
+ ConnEnd dstPt250(Point(497.924, 435.557), 15);
+ connRef250->setDestEndpoint(dstPt250);
+ connRef250->setRoutingType((ConnType)2);
+
+ ConnRef *connRef251 = new ConnRef(router, 251);
+ ConnEnd srcPt251(Point(617.924, 477.557), 15);
+ connRef251->setSourceEndpoint(srcPt251);
+ ConnEnd dstPt251(Point(617.924, 527.557), 15);
+ connRef251->setDestEndpoint(dstPt251);
+ connRef251->setRoutingType((ConnType)2);
+
+ ConnRef *connRef252 = new ConnRef(router, 252);
+ ConnEnd srcPt252(Point(617.924, 385.557), 15);
+ connRef252->setSourceEndpoint(srcPt252);
+ ConnEnd dstPt252(Point(617.924, 435.557), 15);
+ connRef252->setDestEndpoint(dstPt252);
+ connRef252->setRoutingType((ConnType)2);
+
+ ConnRef *connRef253 = new ConnRef(router, 253);
+ ConnEnd srcPt253(Point(857.924, 293.557), 15);
+ connRef253->setSourceEndpoint(srcPt253);
+ ConnEnd dstPt253(Point(857.924, 343.557), 15);
+ connRef253->setDestEndpoint(dstPt253);
+ connRef253->setRoutingType((ConnType)2);
+
+ ConnRef *connRef254 = new ConnRef(router, 254);
+ ConnEnd srcPt254(Point(857.924, 385.557), 15);
+ connRef254->setSourceEndpoint(srcPt254);
+ ConnEnd dstPt254(Point(857.924, 435.557), 15);
+ connRef254->setDestEndpoint(dstPt254);
+ connRef254->setRoutingType((ConnType)2);
+
+ ConnRef *connRef255 = new ConnRef(router, 255);
+ ConnEnd srcPt255(Point(857.924, 111.557), 15);
+ connRef255->setSourceEndpoint(srcPt255);
+ ConnEnd dstPt255(Point(857.924, 161.557), 15);
+ connRef255->setDestEndpoint(dstPt255);
+ connRef255->setRoutingType((ConnType)2);
+
+ ConnRef *connRef256 = new ConnRef(router, 256);
+ ConnEnd srcPt256(Point(737.924, 293.557), 15);
+ connRef256->setSourceEndpoint(srcPt256);
+ ConnEnd dstPt256(Point(737.924, 343.557), 15);
+ connRef256->setDestEndpoint(dstPt256);
+ connRef256->setRoutingType((ConnType)2);
+
+ ConnRef *connRef257 = new ConnRef(router, 257);
+ ConnEnd srcPt257(Point(1078.92, 338.557), 15);
+ connRef257->setSourceEndpoint(srcPt257);
+ ConnEnd dstPt257(Point(1078.92, 388.557), 15);
+ connRef257->setDestEndpoint(dstPt257);
+ connRef257->setRoutingType((ConnType)2);
+
+ ConnRef *connRef258 = new ConnRef(router, 258);
+ ConnEnd srcPt258(Point(1198.92, 338.557), 15);
+ connRef258->setSourceEndpoint(srcPt258);
+ ConnEnd dstPt258(Point(1198.92, 388.557), 15);
+ connRef258->setDestEndpoint(dstPt258);
+ connRef258->setRoutingType((ConnType)2);
+
+ ConnRef *connRef259 = new ConnRef(router, 259);
+ ConnEnd srcPt259(Point(1078.92, 102.342), 15);
+ connRef259->setSourceEndpoint(srcPt259);
+ ConnEnd dstPt259(Point(1078.92, 152.342), 15);
+ connRef259->setDestEndpoint(dstPt259);
+ connRef259->setRoutingType((ConnType)2);
+
+ ConnRef *connRef260 = new ConnRef(router, 260);
+ ConnEnd srcPt260(Point(1078.92, 10.3422), 15);
+ connRef260->setSourceEndpoint(srcPt260);
+ ConnEnd dstPt260(Point(1078.92, 60.3422), 15);
+ connRef260->setDestEndpoint(dstPt260);
+ connRef260->setRoutingType((ConnType)2);
+
+ ConnRef *connRef261 = new ConnRef(router, 261);
+ ConnEnd srcPt261(Point(1198.92, 102.342), 15);
+ connRef261->setSourceEndpoint(srcPt261);
+ ConnEnd dstPt261(Point(1198.92, 152.342), 15);
+ connRef261->setDestEndpoint(dstPt261);
+ connRef261->setRoutingType((ConnType)2);
+
+ ConnRef *connRef262 = new ConnRef(router, 262);
+ ConnEnd srcPt262(Point(1078.92, -110.658), 15);
+ connRef262->setSourceEndpoint(srcPt262);
+ ConnEnd dstPt262(Point(1078.92, -60.6578), 15);
+ connRef262->setDestEndpoint(dstPt262);
+ connRef262->setRoutingType((ConnType)2);
+
+ ConnRef *connRef263 = new ConnRef(router, 263);
+ ConnEnd srcPt263(Point(958.924, 230.557), 15);
+ connRef263->setSourceEndpoint(srcPt263);
+ ConnEnd dstPt263(Point(958.924, 280.557), 15);
+ connRef263->setDestEndpoint(dstPt263);
+ connRef263->setRoutingType((ConnType)2);
+
+ ConnRef *connRef264 = new ConnRef(router, 264);
+ ConnEnd srcPt264(Point(737.924, 111.557), 15);
+ connRef264->setSourceEndpoint(srcPt264);
+ ConnEnd dstPt264(Point(737.924, 161.557), 15);
+ connRef264->setDestEndpoint(dstPt264);
+ connRef264->setRoutingType((ConnType)2);
+
+ ConnRef *connRef265 = new ConnRef(router, 265);
+ ConnEnd srcPt265(Point(737.924, 810.057), 15);
+ connRef265->setSourceEndpoint(srcPt265);
+ ConnEnd dstPt265(Point(737.924, 860.057), 15);
+ connRef265->setDestEndpoint(dstPt265);
+ connRef265->setRoutingType((ConnType)2);
+
+ ConnRef *connRef266 = new ConnRef(router, 266);
+ ConnEnd srcPt266(Point(77.9242, 161.557), 15);
+ connRef266->setSourceEndpoint(srcPt266);
+ ConnEnd dstPt266(Point(40.9242, 252.5), 15);
+ connRef266->setDestEndpoint(dstPt266);
+ connRef266->setRoutingType((ConnType)2);
+
+ ConnRef *connRef267 = new ConnRef(router, 267);
+ ConnEnd srcPt267(Point(77.9242, 763.557), 15);
+ connRef267->setSourceEndpoint(srcPt267);
+ ConnEnd dstPt267(Point(-46.0758, 329.75), 15);
+ connRef267->setDestEndpoint(dstPt267);
+ connRef267->setRoutingType((ConnType)2);
+
+ ConnRef *connRef168 = new ConnRef(router, 168);
+ ConnEnd srcPt168(Point(797.924, 343.557), 15);
+ connRef168->setSourceEndpoint(srcPt168);
+ ConnEnd dstPt168(Point(847.924, 435.557), 15);
+ connRef168->setDestEndpoint(dstPt168);
+ connRef168->setRoutingType((ConnType)2);
+
+ ConnRef *connRef169 = new ConnRef(router, 169);
+ ConnEnd srcPt169(Point(1018.92, 435.557), 15);
+ connRef169->setSourceEndpoint(srcPt169);
+ ConnEnd dstPt169(Point(1068.92, 388.557), 15);
+ connRef169->setDestEndpoint(dstPt169);
+ connRef169->setRoutingType((ConnType)2);
+
+ ConnRef *connRef170 = new ConnRef(router, 170);
+ ConnEnd srcPt170(Point(1018.92, 161.557), 15);
+ connRef170->setSourceEndpoint(srcPt170);
+ ConnEnd dstPt170(Point(1068.92, 152.342), 15);
+ connRef170->setDestEndpoint(dstPt170);
+ connRef170->setRoutingType((ConnType)2);
+
+ ConnRef *connRef171 = new ConnRef(router, 171);
+ ConnEnd srcPt171(Point(1018.92, 161.557), 15);
+ connRef171->setSourceEndpoint(srcPt171);
+ ConnEnd dstPt171(Point(1068.92, 60.3422), 15);
+ connRef171->setDestEndpoint(dstPt171);
+ connRef171->setRoutingType((ConnType)2);
+
+ ConnRef *connRef172 = new ConnRef(router, 172);
+ ConnEnd srcPt172(Point(267.924, 315.557), 15);
+ connRef172->setSourceEndpoint(srcPt172);
+ ConnEnd dstPt172(Point(437.924, 161.557), 15);
+ connRef172->setDestEndpoint(dstPt172);
+ connRef172->setRoutingType((ConnType)2);
+
+ ConnRef *connRef173 = new ConnRef(router, 173);
+ ConnEnd srcPt173(Point(437.924, 161.557), 15);
+ connRef173->setSourceEndpoint(srcPt173);
+ ConnEnd dstPt173(Point(487.924, 45.8422), 15);
+ connRef173->setDestEndpoint(dstPt173);
+ connRef173->setRoutingType((ConnType)2);
+
+ ConnRef *connRef174 = new ConnRef(router, 174);
+ ConnEnd srcPt174(Point(437.924, 161.557), 15);
+ connRef174->setSourceEndpoint(srcPt174);
+ ConnEnd dstPt174(Point(727.924, 161.557), 15);
+ connRef174->setDestEndpoint(dstPt174);
+ connRef174->setRoutingType((ConnType)2);
+
+ ConnRef *connRef175 = new ConnRef(router, 175);
+ ConnEnd srcPt175(Point(77.9242, 161.557), 15);
+ connRef175->setSourceEndpoint(srcPt175);
+ ConnEnd dstPt175(Point(127.924, 161.557), 15);
+ connRef175->setDestEndpoint(dstPt175);
+ connRef175->setRoutingType((ConnType)2);
+
+ ConnRef *connRef176 = new ConnRef(router, 176);
+ ConnEnd srcPt176(Point(77.9242, 161.557), 15);
+ connRef176->setSourceEndpoint(srcPt176);
+ ConnEnd dstPt176(Point(77.9242, 357.557), 15);
+ connRef176->setDestEndpoint(dstPt176);
+ connRef176->setRoutingType((ConnType)2);
+
+ ConnRef *connRef177 = new ConnRef(router, 177);
+ ConnEnd srcPt177(Point(557.924, 763.557), 15);
+ connRef177->setSourceEndpoint(srcPt177);
+ ConnEnd dstPt177(Point(607.924, 763.557), 15);
+ connRef177->setDestEndpoint(dstPt177);
+ connRef177->setRoutingType((ConnType)2);
+
+ ConnRef *connRef178 = new ConnRef(router, 178);
+ ConnEnd srcPt178(Point(77.9242, 527.557), 15);
+ connRef178->setSourceEndpoint(srcPt178);
+ ConnEnd dstPt178(Point(127.924, 527.557), 15);
+ connRef178->setDestEndpoint(dstPt178);
+ connRef178->setRoutingType((ConnType)2);
+
+ ConnRef *connRef179 = new ConnRef(router, 179);
+ ConnEnd srcPt179(Point(557.924, 54.8422), 15);
+ connRef179->setSourceEndpoint(srcPt179);
+ ConnEnd dstPt179(Point(607.924, 45.8422), 15);
+ connRef179->setDestEndpoint(dstPt179);
+ connRef179->setRoutingType((ConnType)2);
+
+ ConnRef *connRef180 = new ConnRef(router, 180);
+ ConnEnd srcPt180(Point(557.924, 435.557), 15);
+ connRef180->setSourceEndpoint(srcPt180);
+ ConnEnd dstPt180(Point(607.924, 435.557), 15);
+ connRef180->setDestEndpoint(dstPt180);
+ connRef180->setRoutingType((ConnType)2);
+
+ ConnRef *connRef181 = new ConnRef(router, 181);
+ ConnEnd srcPt181(Point(77.9242, 763.557), 15);
+ connRef181->setSourceEndpoint(srcPt181);
+ ConnEnd dstPt181(Point(77.9242, 671.557), 15);
+ connRef181->setDestEndpoint(dstPt181);
+ connRef181->setRoutingType((ConnType)2);
+
+ ConnRef *connRef182 = new ConnRef(router, 182);
+ ConnEnd srcPt182(Point(77.9242, 763.557), 15);
+ connRef182->setSourceEndpoint(srcPt182);
+ ConnEnd dstPt182(Point(127.924, 763.557), 15);
+ connRef182->setDestEndpoint(dstPt182);
+ connRef182->setRoutingType((ConnType)2);
+
+ ConnRef *connRef183 = new ConnRef(router, 183);
+ ConnEnd srcPt183(Point(197.924, 315.557), 15);
+ connRef183->setSourceEndpoint(srcPt183);
+ ConnEnd dstPt183(Point(247.924, 315.557), 15);
+ connRef183->setDestEndpoint(dstPt183);
+ connRef183->setRoutingType((ConnType)2);
+
+ ConnRef *connRef148 = new ConnRef(router, 148);
+ ConnEnd srcPt148(Point(1018.92, -60.6578), 15);
+ connRef148->setSourceEndpoint(srcPt148);
+ ConnEnd dstPt148(Point(1068.92, -60.6578), 15);
+ connRef148->setDestEndpoint(dstPt148);
+ connRef148->setRoutingType((ConnType)2);
+
+ ConnRef *connRef149 = new ConnRef(router, 149);
+ ConnEnd srcPt149(Point(1138.92, 161.557), 15);
+ connRef149->setSourceEndpoint(srcPt149);
+ ConnEnd dstPt149(Point(1188.92, 152.342), 15);
+ connRef149->setDestEndpoint(dstPt149);
+ connRef149->setRoutingType((ConnType)2);
+
+ ConnRef *connRef150 = new ConnRef(router, 150);
+ ConnEnd srcPt150(Point(1138.92, 435.557), 15);
+ connRef150->setSourceEndpoint(srcPt150);
+ ConnEnd dstPt150(Point(1188.92, 388.557), 15);
+ connRef150->setDestEndpoint(dstPt150);
+ connRef150->setRoutingType((ConnType)2);
+
+ ConnRef *connRef151 = new ConnRef(router, 151);
+ ConnEnd srcPt151(Point(317.924, 763.557), 15);
+ connRef151->setSourceEndpoint(srcPt151);
+ ConnEnd dstPt151(Point(367.924, 627.557), 15);
+ connRef151->setDestEndpoint(dstPt151);
+ connRef151->setRoutingType((ConnType)2);
+
+ ConnRef *connRef152 = new ConnRef(router, 152);
+ ConnEnd srcPt152(Point(317.924, 763.557), 15);
+ connRef152->setSourceEndpoint(srcPt152);
+ ConnEnd dstPt152(Point(367.924, 763.557), 15);
+ connRef152->setDestEndpoint(dstPt152);
+ connRef152->setRoutingType((ConnType)2);
+
+ ConnRef *connRef153 = new ConnRef(router, 153);
+ ConnEnd srcPt153(Point(317.924, 763.557), 15);
+ connRef153->setSourceEndpoint(srcPt153);
+ ConnEnd dstPt153(Point(487.924, 903.057), 15);
+ connRef153->setDestEndpoint(dstPt153);
+ connRef153->setRoutingType((ConnType)2);
+
+ ConnRef *connRef154 = new ConnRef(router, 154);
+ ConnEnd srcPt154(Point(317.924, 763.557), 15);
+ connRef154->setSourceEndpoint(srcPt154);
+ ConnEnd dstPt154(Point(727.924, 574.057), 15);
+ connRef154->setDestEndpoint(dstPt154);
+ connRef154->setRoutingType((ConnType)2);
+
+ ConnRef *connRef155 = new ConnRef(router, 155);
+ ConnEnd srcPt155(Point(557.924, 903.057), 15);
+ connRef155->setSourceEndpoint(srcPt155);
+ ConnEnd dstPt155(Point(607.924, 903.057), 15);
+ connRef155->setDestEndpoint(dstPt155);
+ connRef155->setRoutingType((ConnType)2);
+
+ ConnRef *connRef156 = new ConnRef(router, 156);
+ ConnEnd srcPt156(Point(197.924, 763.557), 15);
+ connRef156->setSourceEndpoint(srcPt156);
+ ConnEnd dstPt156(Point(247.924, 763.557), 15);
+ connRef156->setDestEndpoint(dstPt156);
+ connRef156->setRoutingType((ConnType)2);
+
+ ConnRef *connRef157 = new ConnRef(router, 157);
+ ConnEnd srcPt157(Point(147.924, 161.557), 15);
+ connRef157->setSourceEndpoint(srcPt157);
+ ConnEnd dstPt157(Point(197.924, 161.557), 15);
+ connRef157->setDestEndpoint(dstPt157);
+ connRef157->setRoutingType((ConnType)2);
+
+ ConnRef *connRef158 = new ConnRef(router, 158);
+ ConnEnd srcPt158(Point(197.924, 161.557), 15);
+ connRef158->setSourceEndpoint(srcPt158);
+ ConnEnd dstPt158(Point(247.924, 161.557), 15);
+ connRef158->setDestEndpoint(dstPt158);
+ connRef158->setRoutingType((ConnType)2);
+
+ ConnRef *connRef159 = new ConnRef(router, 159);
+ ConnEnd srcPt159(Point(197.924, 161.557), 15);
+ connRef159->setSourceEndpoint(srcPt159);
+ ConnEnd dstPt159(Point(197.924, 203.557), 15);
+ connRef159->setDestEndpoint(dstPt159);
+ connRef159->setRoutingType((ConnType)2);
+
+ ConnRef *connRef160 = new ConnRef(router, 160);
+ ConnEnd srcPt160(Point(317.924, 161.557), 15);
+ connRef160->setSourceEndpoint(srcPt160);
+ ConnEnd dstPt160(Point(727.924, -60.6578), 15);
+ connRef160->setDestEndpoint(dstPt160);
+ connRef160->setRoutingType((ConnType)2);
+
+ ConnRef *connRef161 = new ConnRef(router, 161);
+ ConnEnd srcPt161(Point(317.924, 161.557), 15);
+ connRef161->setSourceEndpoint(srcPt161);
+ ConnEnd dstPt161(Point(367.924, 161.557), 15);
+ connRef161->setDestEndpoint(dstPt161);
+ connRef161->setRoutingType((ConnType)2);
+
+ ConnRef *connRef162 = new ConnRef(router, 162);
+ ConnEnd srcPt162(Point(317.924, 161.557), 15);
+ connRef162->setSourceEndpoint(srcPt162);
+ ConnEnd dstPt162(Point(367.924, 27.3422), 15);
+ connRef162->setDestEndpoint(dstPt162);
+ connRef162->setRoutingType((ConnType)2);
+
+ ConnRef *connRef163 = new ConnRef(router, 163);
+ ConnEnd srcPt163(Point(317.924, 161.557), 15);
+ connRef163->setSourceEndpoint(srcPt163);
+ ConnEnd dstPt163(Point(487.924, 435.557), 15);
+ connRef163->setDestEndpoint(dstPt163);
+ connRef163->setRoutingType((ConnType)2);
+
+ ConnRef *connRef164 = new ConnRef(router, 164);
+ ConnEnd srcPt164(Point(437.924, 763.557), 15);
+ connRef164->setSourceEndpoint(srcPt164);
+ ConnEnd dstPt164(Point(487.924, 763.557), 15);
+ connRef164->setDestEndpoint(dstPt164);
+ connRef164->setRoutingType((ConnType)2);
+
+ ConnRef *connRef165 = new ConnRef(router, 165);
+ ConnEnd srcPt165(Point(437.924, 763.557), 15);
+ connRef165->setSourceEndpoint(srcPt165);
+ ConnEnd dstPt165(Point(727.924, 860.057), 15);
+ connRef165->setDestEndpoint(dstPt165);
+ connRef165->setRoutingType((ConnType)2);
+
+ ConnRef *connRef166 = new ConnRef(router, 166);
+ ConnEnd srcPt166(Point(557.924, 527.557), 15);
+ connRef166->setSourceEndpoint(srcPt166);
+ ConnEnd dstPt166(Point(607.924, 527.557), 15);
+ connRef166->setDestEndpoint(dstPt166);
+ connRef166->setRoutingType((ConnType)2);
+
+ ConnRef *connRef167 = new ConnRef(router, 167);
+ ConnEnd srcPt167(Point(797.924, 343.557), 15);
+ connRef167->setSourceEndpoint(srcPt167);
+ ConnEnd dstPt167(Point(847.924, 343.557), 15);
+ connRef167->setDestEndpoint(dstPt167);
+ connRef167->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/lineSegWrapperCrash8");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/msctests/2junctions.vcxproj b/src/3rdparty/adaptagrams/libavoid/tests/msctests/2junctions.vcxproj
new file mode 100755
index 0000000..9af2c2a
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/msctests/2junctions.vcxproj
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{4C07F666-EB74-44E9-811C-57CFCCC553C8}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>My2junctions</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\2junctions.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\libavoid.vcxproj">
+ <Project>{798c3d94-bf71-4c72-a29d-0e74c2eb296a}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/msctests/buildOrthogonalChannelInfo1.vcxproj b/src/3rdparty/adaptagrams/libavoid/tests/msctests/buildOrthogonalChannelInfo1.vcxproj
new file mode 100755
index 0000000..3caf3c9
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/msctests/buildOrthogonalChannelInfo1.vcxproj
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{022C18E8-4B2A-4CF0-8660-9B691473C20E}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>buildOrthogonalChannelInfo1</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\buildOrthogonalChannelInfo1.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\libavoid.vcxproj">
+ <Project>{798c3d94-bf71-4c72-a29d-0e74c2eb296a}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/msctests/checkpointNudging1.vcxproj b/src/3rdparty/adaptagrams/libavoid/tests/msctests/checkpointNudging1.vcxproj
new file mode 100755
index 0000000..d248fcf
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/msctests/checkpointNudging1.vcxproj
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{33240DD8-FDA7-4157-B022-C71E0B29467B}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>checkpointNudging1</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\checkpointNudging1.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\libavoid.vcxproj">
+ <Project>{798c3d94-bf71-4c72-a29d-0e74c2eb296a}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/msctests/checkpointNudging2.vcxproj b/src/3rdparty/adaptagrams/libavoid/tests/msctests/checkpointNudging2.vcxproj
new file mode 100755
index 0000000..04db55a
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/msctests/checkpointNudging2.vcxproj
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{97CCD32F-F345-4B41-BC79-50EE7644FCCD}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>checkpointNudging2</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\checkpointNudging2.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\libavoid.vcxproj">
+ <Project>{798c3d94-bf71-4c72-a29d-0e74c2eb296a}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/msctests/checkpoints01.vcxproj b/src/3rdparty/adaptagrams/libavoid/tests/msctests/checkpoints01.vcxproj
new file mode 100755
index 0000000..a919d2b
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/msctests/checkpoints01.vcxproj
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{6C2BA2FB-CD3A-409E-B87B-6A105C7CCA48}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>checkpoints01</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\checkpoints01.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\libavoid.vcxproj">
+ <Project>{798c3d94-bf71-4c72-a29d-0e74c2eb296a}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/msctests/connectionpin01.vcxproj b/src/3rdparty/adaptagrams/libavoid/tests/msctests/connectionpin01.vcxproj
new file mode 100755
index 0000000..43dfff4
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/msctests/connectionpin01.vcxproj
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{F77FA86C-07F5-468C-A162-479EEE7AEC45}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>connectionpin01</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\connectionpin01.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\libavoid.vcxproj">
+ <Project>{798c3d94-bf71-4c72-a29d-0e74c2eb296a}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/msctests/connectionpin02.vcxproj b/src/3rdparty/adaptagrams/libavoid/tests/msctests/connectionpin02.vcxproj
new file mode 100755
index 0000000..b2e82b9
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/msctests/connectionpin02.vcxproj
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{E570E7C6-CFF4-4639-855E-4C1E02F0DD85}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>connectionpin02</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\connectionpin02.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\libavoid.vcxproj">
+ <Project>{798c3d94-bf71-4c72-a29d-0e74c2eb296a}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/msctests/connectionpin03.vcxproj b/src/3rdparty/adaptagrams/libavoid/tests/msctests/connectionpin03.vcxproj
new file mode 100755
index 0000000..60a30b3
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/msctests/connectionpin03.vcxproj
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{69ED412A-63E6-4057-9517-D06A55DD99B0}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>connectionpin03</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\connectionpin03.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\libavoid.vcxproj">
+ <Project>{798c3d94-bf71-4c72-a29d-0e74c2eb296a}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/msctests/connendmove.vcxproj b/src/3rdparty/adaptagrams/libavoid/tests/msctests/connendmove.vcxproj
new file mode 100755
index 0000000..92dfc06
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/msctests/connendmove.vcxproj
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{980B4C23-428F-48A1-9111-40AA4777C246}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>connendmove</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\connendmove.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\libavoid.vcxproj">
+ <Project>{798c3d94-bf71-4c72-a29d-0e74c2eb296a}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/msctests/corneroverlap01.vcxproj b/src/3rdparty/adaptagrams/libavoid/tests/msctests/corneroverlap01.vcxproj
new file mode 100755
index 0000000..4814c41
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/msctests/corneroverlap01.vcxproj
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{8E4B6939-A58A-4DF0-B799-5662E25B7BAD}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>corneroverlap01</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\corneroverlap01.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\libavoid.vcxproj">
+ <Project>{798c3d94-bf71-4c72-a29d-0e74c2eb296a}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/msctests/example.vcxproj b/src/3rdparty/adaptagrams/libavoid/tests/msctests/example.vcxproj
new file mode 100755
index 0000000..f2d9ba7
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/msctests/example.vcxproj
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{6943E11D-22DE-4F6A-A30E-C7D23681B507}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>example</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\example.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\libavoid.vcxproj">
+ <Project>{798c3d94-bf71-4c72-a29d-0e74c2eb296a}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/msctests/finalSegmentNudging1.vcxproj b/src/3rdparty/adaptagrams/libavoid/tests/msctests/finalSegmentNudging1.vcxproj
new file mode 100755
index 0000000..bfc8a87
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/msctests/finalSegmentNudging1.vcxproj
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{DDD617A0-FFE1-4C05-8144-06F637FB1C7B}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>finalSegmentNudging1</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\finalSegmentNudging1.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\libavoid.vcxproj">
+ <Project>{798c3d94-bf71-4c72-a29d-0e74c2eb296a}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/msctests/finalSegmentNudging2.vcxproj b/src/3rdparty/adaptagrams/libavoid/tests/msctests/finalSegmentNudging2.vcxproj
new file mode 100755
index 0000000..d50324c
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/msctests/finalSegmentNudging2.vcxproj
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{A5A5A67A-A961-4AA1-A248-196D91406169}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>finalSegmentNudging2</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\finalSegmentNudging2.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\libavoid.vcxproj">
+ <Project>{798c3d94-bf71-4c72-a29d-0e74c2eb296a}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/msctests/finalSegmentNudging3.vcxproj b/src/3rdparty/adaptagrams/libavoid/tests/msctests/finalSegmentNudging3.vcxproj
new file mode 100755
index 0000000..7877e5e
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/msctests/finalSegmentNudging3.vcxproj
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{6C94F0E2-5A2C-4D6D-93FC-43B9A5A578AF}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>finalSegmentNudging3</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\finalSegmentNudging3.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\libavoid.vcxproj">
+ <Project>{798c3d94-bf71-4c72-a29d-0e74c2eb296a}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/msctests/freeFloatingDirection01.vcxproj b/src/3rdparty/adaptagrams/libavoid/tests/msctests/freeFloatingDirection01.vcxproj
new file mode 100755
index 0000000..f16bfeb
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/msctests/freeFloatingDirection01.vcxproj
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{8DB197B1-20B2-485D-B89E-D9A7674193BD}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>freeFloatingDirection01</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\freeFloatingDirection01.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\libavoid.vcxproj">
+ <Project>{798c3d94-bf71-4c72-a29d-0e74c2eb296a}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/msctests/junction01.vcxproj b/src/3rdparty/adaptagrams/libavoid/tests/msctests/junction01.vcxproj
new file mode 100755
index 0000000..02f37f9
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/msctests/junction01.vcxproj
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{35D83117-8DA7-495E-A045-DFDC555227C8}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>junction01</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>$(SolutionDir)..</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\junction01.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\libavoid.vcxproj">
+ <Project>{798c3d94-bf71-4c72-a29d-0e74c2eb296a}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/multiconnact.cpp b/src/3rdparty/adaptagrams/libavoid/tests/multiconnact.cpp
new file mode 100644
index 0000000..b5e360d
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/multiconnact.cpp
@@ -0,0 +1,75 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ * Copyright (C) 2004-2007 Michael Wybrow <mjwybrow@users.sourceforge.net>
+ * Copyright (C) 2009 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow <mjwybrow@users.sourceforge.net>
+*/
+
+#include "libavoid/libavoid.h"
+
+
+
+static void connCallback(void *ptr)
+{
+ Avoid::ConnRef *connRef = (Avoid::ConnRef *) ptr;
+
+ printf("Connector %u needs rerouting!\n", connRef->id());
+
+ const Avoid::PolyLine& route = connRef->displayRoute();
+ printf("New path: ");
+ for (size_t i = 0; i < route.ps.size(); ++i)
+ {
+ printf("%s(%f, %f)", (i > 0) ? "-" : "",
+ route.ps[i].x, route.ps[i].y);
+ }
+ printf("\n");
+}
+
+
+int main(void)
+{
+ Avoid::Router *router = new Avoid::Router(Avoid::OrthogonalRouting);
+
+ Avoid::Point srcPt(0,400);
+ Avoid::Point dstPt(775,400);
+ Avoid::ConnRef *connRef = new Avoid::ConnRef(router, srcPt, dstPt);
+ connRef->setCallback(connCallback, connRef);
+
+ Avoid::Point srcPt2(775,625);
+ Avoid::Point dstPt2(350,475);
+ Avoid::ConnRef *connRef2 = new Avoid::ConnRef(router, srcPt2, dstPt2);
+ connRef2->setCallback(connCallback, connRef2);
+
+ router->processTransaction();
+
+ printf("\nShifting endpoint.\n");
+ connRef->setEndpoints(Avoid::Point(0,375), Avoid::Point(775,400));
+ connRef2->setEndpoints(Avoid::Point(775,625), Avoid::Point(350,450));
+ router->processTransaction();
+
+ printf("\nShifting endpoint.\n");
+ connRef->setEndpoints(Avoid::Point(0,400), Avoid::Point(775,400));
+ connRef2->setEndpoints(Avoid::Point(775,625), Avoid::Point(350,475));
+ router->processTransaction();
+
+ delete router;
+ return 0;
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/node1.cpp b/src/3rdparty/adaptagrams/libavoid/tests/node1.cpp
new file mode 100644
index 0000000..1da1150
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/node1.cpp
@@ -0,0 +1,68 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 200);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ //router->setRoutingPenalty((PenaltyType)4, 110);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+ double buffer = 4;
+ Polygon poly342721632(4);
+ poly342721632.ps[0] = Point(51910, 50946);
+ poly342721632.ps[1] = Point(51910, 51004);
+ poly342721632.ps[2] = Point(51825, 51004);
+ poly342721632.ps[3] = Point(51825, 50946);
+ ShapeRef *shapeRef342721632 = new ShapeRef(router, poly342721632, 342721632);
+ new ShapeConnectionPin(shapeRef342721632, 1,
+ ATTACH_POS_LEFT, ATTACH_POS_CENTRE, true, buffer, ConnDirLeft);
+
+ Polygon poly807558175(4);
+ poly807558175.ps[0] = Point(51604, 51000);
+ poly807558175.ps[1] = Point(51604, 51085);
+ poly807558175.ps[2] = Point(51546, 51085);
+ poly807558175.ps[3] = Point(51546, 51000);
+ ShapeRef *shapeRef807558175 = new ShapeRef(router, poly807558175, 807558175);
+ new ShapeConnectionPin(shapeRef807558175, 1,
+ ATTACH_POS_CENTRE, ATTACH_POS_TOP, true, buffer, ConnDirNone);
+
+ Polygon poly404900496(4);
+ poly404900496.ps[0] = Point(51525, 50946);
+ poly404900496.ps[1] = Point(51525, 51004);
+ poly404900496.ps[2] = Point(51440, 51004);
+ poly404900496.ps[3] = Point(51440, 50946);
+ ShapeRef *shapeRef404900496 = new ShapeRef(router, poly404900496, 404900496);
+ new ShapeConnectionPin(shapeRef404900496, 1,
+ ATTACH_POS_RIGHT, ATTACH_POS_CENTRE, true, buffer, (ConnDirFlags) 8);
+
+ JunctionRef *junctionRef265539540 = new JunctionRef(router, Point(51625, 50950), 265539540);
+
+ ConnRef *connRef985644192 = new ConnRef(router, 985644192);
+ ConnEnd srcPt985644192(shapeRef404900496, 1);
+ connRef985644192->setSourceEndpoint(srcPt985644192);
+ ConnEnd dstPt985644192(junctionRef265539540);
+ connRef985644192->setDestEndpoint(dstPt985644192);
+ connRef985644192->setRoutingType((ConnType)2);
+
+ ConnRef *connRef467016913 = new ConnRef(router, 467016913);
+ ConnEnd srcPt467016913(junctionRef265539540);
+ connRef467016913->setSourceEndpoint(srcPt467016913);
+ ConnEnd dstPt467016913(shapeRef807558175, 1);
+ connRef467016913->setDestEndpoint(dstPt467016913);
+ connRef467016913->setRoutingType((ConnType)2);
+
+ ConnRef *connRef45740440 = new ConnRef(router, 45740440);
+ ConnEnd srcPt45740440(shapeRef342721632, 1);
+ connRef45740440->setSourceEndpoint(srcPt45740440);
+ ConnEnd dstPt45740440(junctionRef265539540);
+ connRef45740440->setDestEndpoint(dstPt45740440);
+ connRef45740440->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/node1");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/nudgeCrossing01.cpp b/src/3rdparty/adaptagrams/libavoid/tests/nudgeCrossing01.cpp
new file mode 100644
index 0000000..f5725e5
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/nudgeCrossing01.cpp
@@ -0,0 +1,2665 @@
+// #00010
+//
+// Regression test to catch a crossing that could be intriduced during
+// nudging when the centring step could previously change the ordering
+// of some segments. It now unifies them, rather than centring.
+//
+#include "libavoid/libavoid.h"
+#include "libcola/cola.h"
+using namespace cola;
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingParameter((RoutingParameter)0, 50);
+ router->setRoutingParameter((RoutingParameter)1, 0);
+ router->setRoutingParameter((RoutingParameter)2, 0);
+ router->setRoutingParameter((RoutingParameter)3, 4000);
+ router->setRoutingParameter((RoutingParameter)4, 0);
+ router->setRoutingParameter((RoutingParameter)5, 100);
+ router->setRoutingOption((RoutingOption)0, true);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, false);
+ router->setRoutingOption((RoutingOption)3, false);
+
+#if 0
+ Polygon poly1(4);
+ poly1.ps[0] = Point(1299.5, 855.5);
+ poly1.ps[1] = Point(1299.5, 887.5);
+ poly1.ps[2] = Point(1279.5, 887.5);
+ poly1.ps[3] = Point(1279.5, 855.5);
+ new ShapeRef(router, poly1, 1);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(647.5, 2048.54);
+ poly2.ps[1] = Point(647.5, 2068.54);
+ poly2.ps[2] = Point(615.5, 2068.54);
+ poly2.ps[3] = Point(615.5, 2048.54);
+ new ShapeRef(router, poly2, 2);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(282.5, 1914.17);
+ poly3.ps[1] = Point(282.5, 1946.17);
+ poly3.ps[2] = Point(262.5, 1946.17);
+ poly3.ps[3] = Point(262.5, 1914.17);
+ new ShapeRef(router, poly3, 3);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(647.5, 2090.54);
+ poly4.ps[1] = Point(647.5, 2110.54);
+ poly4.ps[2] = Point(615.5, 2110.54);
+ poly4.ps[3] = Point(615.5, 2090.54);
+ new ShapeRef(router, poly4, 4);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(282.5, 2048.54);
+ poly5.ps[1] = Point(282.5, 2110.54);
+ poly5.ps[2] = Point(220.5, 2110.54);
+ poly5.ps[3] = Point(220.5, 2048.54);
+ new ShapeRef(router, poly5, 5);
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(1731.5, 492);
+ poly6.ps[1] = Point(1731.5, 869);
+ poly6.ps[2] = Point(1509.5, 869);
+ poly6.ps[3] = Point(1509.5, 492);
+ new ShapeRef(router, poly6, 6);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(1409.5, 45);
+ poly7.ps[1] = Point(1409.5, 219);
+ poly7.ps[2] = Point(1289.5, 219);
+ poly7.ps[3] = Point(1289.5, 45);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(947.5, 2001.54);
+ poly8.ps[1] = Point(947.5, 2033.54);
+ poly8.ps[2] = Point(927.5, 2033.54);
+ poly8.ps[3] = Point(927.5, 2001.54);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(1255.5, 1973.54);
+ poly9.ps[1] = Point(1255.5, 1993.54);
+ poly9.ps[2] = Point(1223.5, 1993.54);
+ poly9.ps[3] = Point(1223.5, 1973.54);
+ new ShapeRef(router, poly9, 9);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(1255.5, 2048.54);
+ poly10.ps[1] = Point(1255.5, 2068.54);
+ poly10.ps[2] = Point(1223.5, 2068.54);
+ poly10.ps[3] = Point(1223.5, 2048.54);
+ new ShapeRef(router, poly10, 10);
+
+ Polygon poly11(4);
+ poly11.ps[0] = Point(1135.5, 1869.54);
+ poly11.ps[1] = Point(1135.5, 1889.54);
+ poly11.ps[2] = Point(1103.5, 1889.54);
+ poly11.ps[3] = Point(1103.5, 1869.54);
+ new ShapeRef(router, poly11, 11);
+
+ Polygon poly12(4);
+ poly12.ps[0] = Point(1129.5, 1782.17);
+ poly12.ps[1] = Point(1129.5, 1814.17);
+ poly12.ps[2] = Point(1109.5, 1814.17);
+ poly12.ps[3] = Point(1109.5, 1782.17);
+ new ShapeRef(router, poly12, 12);
+
+ Polygon poly13(4);
+ poly13.ps[0] = Point(829.5, 1859.17);
+ poly13.ps[1] = Point(829.5, 1879.17);
+ poly13.ps[2] = Point(797.5, 1879.17);
+ poly13.ps[3] = Point(797.5, 1859.17);
+ new ShapeRef(router, poly13, 13);
+
+ Polygon poly14(4);
+ poly14.ps[0] = Point(422.5, 1859.17);
+ poly14.ps[1] = Point(422.5, 1879.17);
+ poly14.ps[2] = Point(390.5, 1879.17);
+ poly14.ps[3] = Point(390.5, 1859.17);
+ new ShapeRef(router, poly14, 14);
+
+ Polygon poly15(4);
+ poly15.ps[0] = Point(1472.5, 1859.17);
+ poly15.ps[1] = Point(1472.5, 1879.17);
+ poly15.ps[2] = Point(1440.5, 1879.17);
+ poly15.ps[3] = Point(1440.5, 1859.17);
+ new ShapeRef(router, poly15, 15);
+
+ Polygon poly16(4);
+ poly16.ps[0] = Point(979.028, 1370.55);
+ poly16.ps[1] = Point(979.028, 1414.55);
+ poly16.ps[2] = Point(891.028, 1414.55);
+ poly16.ps[3] = Point(891.028, 1370.55);
+ new ShapeRef(router, poly16, 16);
+
+ Polygon poly17(4);
+ poly17.ps[0] = Point(1299.5, 1649.17);
+ poly17.ps[1] = Point(1299.5, 1681.17);
+ poly17.ps[2] = Point(1279.5, 1681.17);
+ poly17.ps[3] = Point(1279.5, 1649.17);
+ new ShapeRef(router, poly17, 17);
+
+ Polygon poly18(4);
+ poly18.ps[0] = Point(252, 1663.17);
+ poly18.ps[1] = Point(252, 1827.17);
+ poly18.ps[2] = Point(45, 1827.17);
+ poly18.ps[3] = Point(45, 1663.17);
+ new ShapeRef(router, poly18, 18);
+
+ Polygon poly19(4);
+ poly19.ps[0] = Point(1299.5, 1525.17);
+ poly19.ps[1] = Point(1299.5, 1557.17);
+ poly19.ps[2] = Point(1279.5, 1557.17);
+ poly19.ps[3] = Point(1279.5, 1525.17);
+ new ShapeRef(router, poly19, 19);
+
+ Polygon poly20(4);
+ poly20.ps[0] = Point(1299.5, 1401.17);
+ poly20.ps[1] = Point(1299.5, 1433.17);
+ poly20.ps[2] = Point(1279.5, 1433.17);
+ poly20.ps[3] = Point(1279.5, 1401.17);
+ new ShapeRef(router, poly20, 20);
+
+ Polygon poly21(4);
+ poly21.ps[0] = Point(1278.5, 1011.17);
+ poly21.ps[1] = Point(1278.5, 1043.17);
+ poly21.ps[2] = Point(1258.5, 1043.17);
+ poly21.ps[3] = Point(1258.5, 1011.17);
+ new ShapeRef(router, poly21, 21);
+
+ Polygon poly22(4);
+ poly22.ps[0] = Point(849, 1332.17);
+ poly22.ps[1] = Point(849, 1392.17);
+ poly22.ps[2] = Point(536, 1392.17);
+ poly22.ps[3] = Point(536, 1332.17);
+ new ShapeRef(router, poly22, 22);
+
+ Polygon poly23(4);
+ poly23.ps[0] = Point(1104.5, 956.167);
+ poly23.ps[1] = Point(1104.5, 976.167);
+ poly23.ps[2] = Point(1072.5, 976.167);
+ poly23.ps[3] = Point(1072.5, 956.167);
+ new ShapeRef(router, poly23, 23);
+
+ Polygon poly24(4);
+ poly24.ps[0] = Point(1278.5, 713.5);
+ poly24.ps[1] = Point(1278.5, 745.5);
+ poly24.ps[2] = Point(1258.5, 745.5);
+ poly24.ps[3] = Point(1258.5, 713.5);
+ new ShapeRef(router, poly24, 24);
+
+ Polygon poly25(4);
+ poly25.ps[0] = Point(1411.5, 713.5);
+ poly25.ps[1] = Point(1411.5, 745.5);
+ poly25.ps[2] = Point(1391.5, 745.5);
+ poly25.ps[3] = Point(1391.5, 713.5);
+ new ShapeRef(router, poly25, 25);
+
+ Polygon poly26(4);
+ poly26.ps[0] = Point(1441.5, 422.5);
+ poly26.ps[1] = Point(1441.5, 442.5);
+ poly26.ps[2] = Point(1409.5, 442.5);
+ poly26.ps[3] = Point(1409.5, 422.5);
+ new ShapeRef(router, poly26, 26);
+
+ Polygon poly27(4);
+ poly27.ps[0] = Point(1299.5, 535.25);
+ poly27.ps[1] = Point(1299.5, 567.25);
+ poly27.ps[2] = Point(1279.5, 567.25);
+ poly27.ps[3] = Point(1279.5, 535.25);
+ new ShapeRef(router, poly27, 27);
+
+ Polygon poly28(4);
+ poly28.ps[0] = Point(1299.5, 344);
+ poly28.ps[1] = Point(1299.5, 376);
+ poly28.ps[2] = Point(1279.5, 376);
+ poly28.ps[3] = Point(1279.5, 344);
+ new ShapeRef(router, poly28, 28);
+
+ Polygon poly29(4);
+ poly29.ps[0] = Point(1042.5, 628.75);
+ poly29.ps[1] = Point(1042.5, 648.75);
+ poly29.ps[2] = Point(1010.5, 648.75);
+ poly29.ps[3] = Point(1010.5, 628.75);
+ new ShapeRef(router, poly29, 29);
+
+ Polygon poly30(4);
+ poly30.ps[0] = Point(523.5, 532.75);
+ poly30.ps[1] = Point(523.5, 552.75);
+ poly30.ps[2] = Point(491.5, 552.75);
+ poly30.ps[3] = Point(491.5, 532.75);
+ new ShapeRef(router, poly30, 30);
+
+ Polygon poly31(4);
+ poly31.ps[0] = Point(523.5, 607.75);
+ poly31.ps[1] = Point(523.5, 627.75);
+ poly31.ps[2] = Point(491.5, 627.75);
+ poly31.ps[3] = Point(491.5, 607.75);
+ new ShapeRef(router, poly31, 31);
+
+ Polygon poly32(4);
+ poly32.ps[0] = Point(922.5, 541.25);
+ poly32.ps[1] = Point(922.5, 561.25);
+ poly32.ps[2] = Point(890.5, 561.25);
+ poly32.ps[3] = Point(890.5, 541.25);
+ new ShapeRef(router, poly32, 32);
+
+ Polygon poly33(4);
+ poly33.ps[0] = Point(761.5, 535.25);
+ poly33.ps[1] = Point(761.5, 567.25);
+ poly33.ps[2] = Point(741.5, 567.25);
+ poly33.ps[3] = Point(741.5, 535.25);
+ new ShapeRef(router, poly33, 33);
+
+ Polygon poly34(4);
+ poly34.ps[0] = Point(296.5, 535.25);
+ poly34.ps[1] = Point(296.5, 567.25);
+ poly34.ps[2] = Point(276.5, 567.25);
+ poly34.ps[3] = Point(276.5, 535.25);
+ new ShapeRef(router, poly34, 34);
+#endif
+
+ Polygon poly35(4);
+ poly35.ps[0] = Point(616.5, 285);
+ poly35.ps[1] = Point(616.5, 305);
+ poly35.ps[2] = Point(584.5, 305);
+ poly35.ps[3] = Point(584.5, 285);
+ new ShapeRef(router, poly35, 35);
+
+#if 0
+ Polygon poly36(4);
+ poly36.ps[0] = Point(616.5, 360);
+ poly36.ps[1] = Point(616.5, 380);
+ poly36.ps[2] = Point(584.5, 380);
+ poly36.ps[3] = Point(584.5, 360);
+ new ShapeRef(router, poly36, 36);
+
+ Polygon poly37(4);
+ poly37.ps[0] = Point(616.5, 552);
+ poly37.ps[1] = Point(616.5, 572);
+ poly37.ps[2] = Point(584.5, 572);
+ poly37.ps[3] = Point(584.5, 552);
+ new ShapeRef(router, poly37, 37);
+#endif
+
+ Polygon poly38(4);
+ poly38.ps[0] = Point(891.5, 331);
+ poly38.ps[1] = Point(891.5, 351);
+ poly38.ps[2] = Point(859.5, 351);
+ poly38.ps[3] = Point(859.5, 331);
+ new ShapeRef(router, poly38, 38);
+
+ Polygon poly39(4);
+ poly39.ps[0] = Point(891.5, 229);
+ poly39.ps[1] = Point(891.5, 249);
+ poly39.ps[2] = Point(859.5, 249);
+ poly39.ps[3] = Point(859.5, 229);
+ new ShapeRef(router, poly39, 39);
+
+#if 0
+ Polygon poly40(4);
+ poly40.ps[0] = Point(402, 96.5);
+ poly40.ps[1] = Point(402, 131.5);
+ poly40.ps[2] = Point(141, 131.5);
+ poly40.ps[3] = Point(141, 96.5);
+ new ShapeRef(router, poly40, 40);
+
+ Polygon poly41(4);
+ poly41.ps[0] = Point(554.5, 2002.21);
+ poly41.ps[1] = Point(554.5, 2022.21);
+ poly41.ps[2] = Point(522.5, 2022.21);
+ poly41.ps[3] = Point(522.5, 2002.21);
+ new ShapeRef(router, poly41, 41);
+
+ Polygon poly42(4);
+ poly42.ps[0] = Point(1299.5, 1247.17);
+ poly42.ps[1] = Point(1299.5, 1279.17);
+ poly42.ps[2] = Point(1279.5, 1279.17);
+ poly42.ps[3] = Point(1279.5, 1247.17);
+ new ShapeRef(router, poly42, 42);
+
+ Polygon poly43(4);
+ poly43.ps[0] = Point(616.5, 435);
+ poly43.ps[1] = Point(616.5, 455);
+ poly43.ps[2] = Point(584.5, 455);
+ poly43.ps[3] = Point(584.5, 435);
+ new ShapeRef(router, poly43, 43);
+
+ Polygon poly44(4);
+ poly44.ps[0] = Point(523.5, 649.75);
+ poly44.ps[1] = Point(523.5, 669.75);
+ poly44.ps[2] = Point(491.5, 669.75);
+ poly44.ps[3] = Point(491.5, 649.75);
+ new ShapeRef(router, poly44, 44);
+
+ Polygon poly45(4);
+ poly45.ps[0] = Point(302.5, 740.75);
+ poly45.ps[1] = Point(302.5, 760.75);
+ poly45.ps[2] = Point(270.5, 760.75);
+ poly45.ps[3] = Point(270.5, 740.75);
+ new ShapeRef(router, poly45, 45);
+
+ Polygon poly46(4);
+ poly46.ps[0] = Point(302.5, 842.75);
+ poly46.ps[1] = Point(302.5, 862.75);
+ poly46.ps[2] = Point(270.5, 862.75);
+ poly46.ps[3] = Point(270.5, 842.75);
+ new ShapeRef(router, poly46, 46);
+
+ Polygon poly47(4);
+ poly47.ps[0] = Point(678.5, 740.75);
+ poly47.ps[1] = Point(678.5, 760.75);
+ poly47.ps[2] = Point(646.5, 760.75);
+ poly47.ps[3] = Point(646.5, 740.75);
+ new ShapeRef(router, poly47, 47);
+
+ Polygon poly48(4);
+ poly48.ps[0] = Point(678.5, 842.75);
+ poly48.ps[1] = Point(678.5, 862.75);
+ poly48.ps[2] = Point(646.5, 862.75);
+ poly48.ps[3] = Point(646.5, 842.75);
+ new ShapeRef(router, poly48, 48);
+
+ Polygon poly49(4);
+ poly49.ps[0] = Point(1530.5, 401.5);
+ poly49.ps[1] = Point(1530.5, 463.5);
+ poly49.ps[2] = Point(1468.5, 463.5);
+ poly49.ps[3] = Point(1468.5, 401.5);
+ new ShapeRef(router, poly49, 49);
+
+ Polygon poly50(4);
+ poly50.ps[0] = Point(1320.5, 249);
+ poly50.ps[1] = Point(1320.5, 311);
+ poly50.ps[2] = Point(1258.5, 311);
+ poly50.ps[3] = Point(1258.5, 249);
+ new ShapeRef(router, poly50, 50);
+
+ Polygon poly51(4);
+ poly51.ps[0] = Point(1320.5, 1448.17);
+ poly51.ps[1] = Point(1320.5, 1510.17);
+ poly51.ps[2] = Point(1258.5, 1510.17);
+ poly51.ps[3] = Point(1258.5, 1448.17);
+ new ShapeRef(router, poly51, 51);
+#endif
+ Polygon poly52(4);
+ poly52.ps[0] = Point(317.5, 435);
+ poly52.ps[1] = Point(317.5, 497);
+ poly52.ps[2] = Point(255.5, 497);
+ poly52.ps[3] = Point(255.5, 435);
+ new ShapeRef(router, poly52, 52);
+#if 0
+ Polygon poly53(4);
+ poly53.ps[0] = Point(317.5, 607.75);
+ poly53.ps[1] = Point(317.5, 669.75);
+ poly53.ps[2] = Point(255.5, 669.75);
+ poly53.ps[3] = Point(255.5, 607.75);
+ new ShapeRef(router, poly53, 53);
+
+ Polygon poly54(4);
+ poly54.ps[0] = Point(875.5, 935.167);
+ poly54.ps[1] = Point(875.5, 997.167);
+ poly54.ps[2] = Point(813.5, 997.167);
+ poly54.ps[3] = Point(813.5, 935.167);
+ new ShapeRef(router, poly54, 54);
+
+ Polygon poly55(4);
+ poly55.ps[0] = Point(875.5, 607.75);
+ poly55.ps[1] = Point(875.5, 669.75);
+ poly55.ps[2] = Point(813.5, 669.75);
+ poly55.ps[3] = Point(813.5, 607.75);
+ new ShapeRef(router, poly55, 55);
+
+ Polygon poly56(4);
+ poly56.ps[0] = Point(1320.5, 435);
+ poly56.ps[1] = Point(1320.5, 497);
+ poly56.ps[2] = Point(1258.5, 497);
+ poly56.ps[3] = Point(1258.5, 435);
+ new ShapeRef(router, poly56, 56);
+
+ Polygon poly57(4);
+ poly57.ps[0] = Point(1320.5, 607.75);
+ poly57.ps[1] = Point(1320.5, 669.75);
+ poly57.ps[2] = Point(1258.5, 669.75);
+ poly57.ps[3] = Point(1258.5, 607.75);
+ new ShapeRef(router, poly57, 57);
+
+ Polygon poly58(4);
+ poly58.ps[0] = Point(1320.5, 1572.17);
+ poly58.ps[1] = Point(1320.5, 1634.17);
+ poly58.ps[2] = Point(1258.5, 1634.17);
+ poly58.ps[3] = Point(1258.5, 1572.17);
+ new ShapeRef(router, poly58, 58);
+
+ Polygon poly59(4);
+ poly59.ps[0] = Point(1320.5, 1324.17);
+ poly59.ps[1] = Point(1320.5, 1386.17);
+ poly59.ps[2] = Point(1258.5, 1386.17);
+ poly59.ps[3] = Point(1258.5, 1324.17);
+ new ShapeRef(router, poly59, 59);
+
+ Polygon poly60(4);
+ poly60.ps[0] = Point(1320.5, 1108.17);
+ poly60.ps[1] = Point(1320.5, 1170.17);
+ poly60.ps[2] = Point(1258.5, 1170.17);
+ poly60.ps[3] = Point(1258.5, 1108.17);
+ new ShapeRef(router, poly60, 60);
+
+ Polygon poly61(4);
+ poly61.ps[0] = Point(1561.5, 1838.17);
+ poly61.ps[1] = Point(1561.5, 1900.17);
+ poly61.ps[2] = Point(1499.5, 1900.17);
+ poly61.ps[3] = Point(1499.5, 1838.17);
+ new ShapeRef(router, poly61, 61);
+
+ Polygon poly62(4);
+ poly62.ps[0] = Point(813.5, 1981.21);
+ poly62.ps[1] = Point(813.5, 2043.21);
+ poly62.ps[2] = Point(751.5, 2043.21);
+ poly62.ps[3] = Point(751.5, 1981.21);
+ new ShapeRef(router, poly62, 62);
+
+ Polygon poly63(4);
+ poly63.ps[0] = Point(1456.5, 2048.54);
+ poly63.ps[1] = Point(1456.5, 2110.54);
+ poly63.ps[2] = Point(1394.5, 2110.54);
+ poly63.ps[3] = Point(1394.5, 2048.54);
+ new ShapeRef(router, poly63, 63);
+
+ Polygon poly64(4);
+ poly64.ps[0] = Point(1320.5, 1838.17);
+ poly64.ps[1] = Point(1320.5, 1900.17);
+ poly64.ps[2] = Point(1258.5, 1900.17);
+ poly64.ps[3] = Point(1258.5, 1838.17);
+ new ShapeRef(router, poly64, 64);
+
+ Polygon poly65(4);
+ poly65.ps[0] = Point(968.5, 1838.17);
+ poly65.ps[1] = Point(968.5, 1900.17);
+ poly65.ps[2] = Point(906.5, 1900.17);
+ poly65.ps[3] = Point(906.5, 1838.17);
+ new ShapeRef(router, poly65, 65);
+
+ Polygon poly66(4);
+ poly66.ps[0] = Point(282.5, 1838.17);
+ poly66.ps[1] = Point(282.5, 1900.17);
+ poly66.ps[2] = Point(220.5, 1900.17);
+ poly66.ps[3] = Point(220.5, 1838.17);
+ new ShapeRef(router, poly66, 66);
+
+ Polygon poly67(4);
+ poly67.ps[0] = Point(968.5, 2048.54);
+ poly67.ps[1] = Point(968.5, 2110.54);
+ poly67.ps[2] = Point(906.5, 2110.54);
+ poly67.ps[3] = Point(906.5, 2048.54);
+ new ShapeRef(router, poly67, 67);
+
+ Polygon poly68(4);
+ poly68.ps[0] = Point(600.5, 1838.17);
+ poly68.ps[1] = Point(600.5, 1900.17);
+ poly68.ps[2] = Point(538.5, 1900.17);
+ poly68.ps[3] = Point(538.5, 1838.17);
+ new ShapeRef(router, poly68, 68);
+
+ Polygon poly69(4);
+ poly69.ps[0] = Point(437.5, 1981.21);
+ poly69.ps[1] = Point(437.5, 2043.21);
+ poly69.ps[2] = Point(375.5, 2043.21);
+ poly69.ps[3] = Point(375.5, 1981.21);
+ new ShapeRef(router, poly69, 69);
+
+ Polygon poly70(4);
+ poly70.ps[0] = Point(1320.5, 759.5);
+ poly70.ps[1] = Point(1320.5, 821.5);
+ poly70.ps[2] = Point(1258.5, 821.5);
+ poly70.ps[3] = Point(1258.5, 759.5);
+ new ShapeRef(router, poly70, 70);
+
+ Polygon poly71(4);
+ poly71.ps[0] = Point(247.5, 719.75);
+ poly71.ps[1] = Point(247.5, 781.75);
+ poly71.ps[2] = Point(185.5, 781.75);
+ poly71.ps[3] = Point(185.5, 719.75);
+ new ShapeRef(router, poly71, 71);
+
+ Polygon poly72(4);
+ poly72.ps[0] = Point(468.5, 719.75);
+ poly72.ps[1] = Point(468.5, 781.75);
+ poly72.ps[2] = Point(406.5, 781.75);
+ poly72.ps[3] = Point(406.5, 719.75);
+ new ShapeRef(router, poly72, 72);
+
+ Polygon poly73(4);
+ poly73.ps[0] = Point(468.5, 821.75);
+ poly73.ps[1] = Point(468.5, 883.75);
+ poly73.ps[2] = Point(406.5, 883.75);
+ poly73.ps[3] = Point(406.5, 821.75);
+ new ShapeRef(router, poly73, 73);
+
+ Polygon poly74(4);
+ poly74.ps[0] = Point(247.5, 821.75);
+ poly74.ps[1] = Point(247.5, 883.75);
+ poly74.ps[2] = Point(185.5, 883.75);
+ poly74.ps[3] = Point(185.5, 821.75);
+ new ShapeRef(router, poly74, 74);
+
+ Polygon poly75(4);
+ poly75.ps[0] = Point(391.5, 1572.17);
+ poly75.ps[1] = Point(391.5, 1592.17);
+ poly75.ps[2] = Point(359.5, 1592.17);
+ poly75.ps[3] = Point(359.5, 1572.17);
+ new ShapeRef(router, poly75, 75);
+
+ Polygon poly76(4);
+ poly76.ps[0] = Point(282.5, 1572.17);
+ poly76.ps[1] = Point(282.5, 1634.17);
+ poly76.ps[2] = Point(220.5, 1634.17);
+ poly76.ps[3] = Point(220.5, 1572.17);
+ new ShapeRef(router, poly76, 76);
+
+ Polygon poly77(4);
+ poly77.ps[0] = Point(1255.5, 2090.54);
+ poly77.ps[1] = Point(1255.5, 2110.54);
+ poly77.ps[2] = Point(1223.5, 2110.54);
+ poly77.ps[3] = Point(1223.5, 2090.54);
+ new ShapeRef(router, poly77, 77);
+
+ Polygon poly78(4);
+ poly78.ps[0] = Point(391.5, 1614.17);
+ poly78.ps[1] = Point(391.5, 1634.17);
+ poly78.ps[2] = Point(359.5, 1634.17);
+ poly78.ps[3] = Point(359.5, 1614.17);
+ new ShapeRef(router, poly78, 78);
+
+ Polygon poly79(4);
+ poly79.ps[0] = Point(1604.5, 1943.04);
+ poly79.ps[1] = Point(1604.5, 2108.04);
+ poly79.ps[2] = Point(1467.5, 2108.04);
+ poly79.ps[3] = Point(1467.5, 1943.04);
+ new ShapeRef(router, poly79, 79);
+
+ Polygon poly80(4);
+ poly80.ps[0] = Point(1320.5, 1011.17);
+ poly80.ps[1] = Point(1320.5, 1043.17);
+ poly80.ps[2] = Point(1300.5, 1043.17);
+ poly80.ps[3] = Point(1300.5, 1011.17);
+ new ShapeRef(router, poly80, 80);
+
+ Polygon poly81(4);
+ poly81.ps[0] = Point(1406.5, 1185.17);
+ poly81.ps[1] = Point(1406.5, 1217.17);
+ poly81.ps[2] = Point(1386.5, 1217.17);
+ poly81.ps[3] = Point(1386.5, 1185.17);
+ new ShapeRef(router, poly81, 81);
+
+ Polygon poly82(4);
+ poly82.ps[0] = Point(1448.5, 1185.17);
+ poly82.ps[1] = Point(1448.5, 1217.17);
+ poly82.ps[2] = Point(1428.5, 1217.17);
+ poly82.ps[3] = Point(1428.5, 1185.17);
+ new ShapeRef(router, poly82, 82);
+
+ Polygon poly83(4);
+ poly83.ps[0] = Point(678.5, 1730.17);
+ poly83.ps[1] = Point(678.5, 1750.17);
+ poly83.ps[2] = Point(646.5, 1750.17);
+ poly83.ps[3] = Point(646.5, 1730.17);
+ new ShapeRef(router, poly83, 83);
+
+ Polygon poly84(4);
+ poly84.ps[0] = Point(1539.5, 1185.17);
+ poly84.ps[1] = Point(1539.5, 1217.17);
+ poly84.ps[2] = Point(1519.5, 1217.17);
+ poly84.ps[3] = Point(1519.5, 1185.17);
+ new ShapeRef(router, poly84, 84);
+
+ Polygon poly85(4);
+ poly85.ps[0] = Point(1088.5, 1232.17);
+ poly85.ps[1] = Point(1088.5, 1294.17);
+ poly85.ps[2] = Point(1026.5, 1294.17);
+ poly85.ps[3] = Point(1026.5, 1232.17);
+ new ShapeRef(router, poly85, 85);
+
+ Polygon poly86(4);
+ poly86.ps[0] = Point(1224.5, 1333.17);
+ poly86.ps[1] = Point(1224.5, 1353.17);
+ poly86.ps[2] = Point(1192.5, 1353.17);
+ poly86.ps[3] = Point(1192.5, 1333.17);
+ new ShapeRef(router, poly86, 86);
+
+ Polygon poly87(4);
+ poly87.ps[0] = Point(1224.5, 1129.17);
+ poly87.ps[1] = Point(1224.5, 1149.17);
+ poly87.ps[2] = Point(1192.5, 1149.17);
+ poly87.ps[3] = Point(1192.5, 1129.17);
+ new ShapeRef(router, poly87, 87);
+
+ Polygon poly88(4);
+ poly88.ps[0] = Point(1320.5, 935.167);
+ poly88.ps[1] = Point(1320.5, 997.167);
+ poly88.ps[2] = Point(1258.5, 997.167);
+ poly88.ps[3] = Point(1258.5, 935.167);
+ new ShapeRef(router, poly88, 88);
+
+ Polygon poly89(4);
+ poly89.ps[0] = Point(240.5, 1914.17);
+ poly89.ps[1] = Point(240.5, 1946.17);
+ poly89.ps[2] = Point(220.5, 1946.17);
+ poly89.ps[3] = Point(220.5, 1914.17);
+ new ShapeRef(router, poly89, 89);
+
+ Polygon poly90(4);
+ poly90.ps[0] = Point(1320.5, 713.5);
+ poly90.ps[1] = Point(1320.5, 745.5);
+ poly90.ps[2] = Point(1300.5, 745.5);
+ poly90.ps[3] = Point(1300.5, 713.5);
+ new ShapeRef(router, poly90, 90);
+
+ Polygon poly91(4);
+ poly91.ps[0] = Point(616.5, 477);
+ poly91.ps[1] = Point(616.5, 497);
+ poly91.ps[2] = Point(584.5, 497);
+ poly91.ps[3] = Point(584.5, 477);
+ new ShapeRef(router, poly91, 91);
+
+ Polygon poly92(4);
+ poly92.ps[0] = Point(523.5, 724.75);
+ poly92.ps[1] = Point(523.5, 744.75);
+ poly92.ps[2] = Point(491.5, 744.75);
+ poly92.ps[3] = Point(491.5, 724.75);
+ new ShapeRef(router, poly92, 92);
+
+ Polygon poly93(4);
+ poly93.ps[0] = Point(1255.5, 2165.54);
+ poly93.ps[1] = Point(1255.5, 2185.54);
+ poly93.ps[2] = Point(1223.5, 2185.54);
+ poly93.ps[3] = Point(1223.5, 2165.54);
+ new ShapeRef(router, poly93, 93);
+
+ Polygon poly94(4);
+ poly94.ps[0] = Point(968.5, 1734.17);
+ poly94.ps[1] = Point(968.5, 1796.17);
+ poly94.ps[2] = Point(906.5, 1796.17);
+ poly94.ps[3] = Point(906.5, 1734.17);
+ new ShapeRef(router, poly94, 94);
+
+ Polygon poly95(4);
+ poly95.ps[0] = Point(1375.5, 851.5);
+ poly95.ps[1] = Point(1375.5, 891.5);
+ poly95.ps[2] = Point(1299.5, 891.5);
+ poly95.ps[3] = Point(1299.5, 851.5);
+ new ShapeRef(router, poly95, 95);
+
+ Polygon poly96(4);
+ poly96.ps[0] = Point(659.5, 1988.54);
+ poly96.ps[1] = Point(659.5, 2048.54);
+ poly96.ps[2] = Point(603.5, 2048.54);
+ poly96.ps[3] = Point(603.5, 1988.54);
+ new ShapeRef(router, poly96, 96);
+
+ Polygon poly97(4);
+ poly97.ps[0] = Point(358.5, 1910.17);
+ poly97.ps[1] = Point(358.5, 1950.17);
+ poly97.ps[2] = Point(282.5, 1950.17);
+ poly97.ps[3] = Point(282.5, 1910.17);
+ new ShapeRef(router, poly97, 97);
+
+ Polygon poly98(4);
+ poly98.ps[0] = Point(659.5, 2110.54);
+ poly98.ps[1] = Point(659.5, 2170.54);
+ poly98.ps[2] = Point(603.5, 2170.54);
+ poly98.ps[3] = Point(603.5, 2110.54);
+ new ShapeRef(router, poly98, 98);
+
+ Polygon poly99(4);
+ poly99.ps[0] = Point(1023.5, 1997.54);
+ poly99.ps[1] = Point(1023.5, 2037.54);
+ poly99.ps[2] = Point(947.5, 2037.54);
+ poly99.ps[3] = Point(947.5, 1997.54);
+ new ShapeRef(router, poly99, 99);
+
+ Polygon poly100(4);
+ poly100.ps[0] = Point(1267.5, 1913.54);
+ poly100.ps[1] = Point(1267.5, 1973.54);
+ poly100.ps[2] = Point(1211.5, 1973.54);
+ poly100.ps[3] = Point(1211.5, 1913.54);
+ new ShapeRef(router, poly100, 100);
+
+ Polygon poly101(4);
+ poly101.ps[0] = Point(1267.5, 1988.54);
+ poly101.ps[1] = Point(1267.5, 2048.54);
+ poly101.ps[2] = Point(1211.5, 2048.54);
+ poly101.ps[3] = Point(1211.5, 1988.54);
+ new ShapeRef(router, poly101, 101);
+
+ Polygon poly102(4);
+ poly102.ps[0] = Point(1147.5, 1889.54);
+ poly102.ps[1] = Point(1147.5, 1949.54);
+ poly102.ps[2] = Point(1091.5, 1949.54);
+ poly102.ps[3] = Point(1091.5, 1889.54);
+ new ShapeRef(router, poly102, 102);
+
+ Polygon poly103(4);
+ poly103.ps[0] = Point(1205.5, 1778.17);
+ poly103.ps[1] = Point(1205.5, 1818.17);
+ poly103.ps[2] = Point(1129.5, 1818.17);
+ poly103.ps[3] = Point(1129.5, 1778.17);
+ new ShapeRef(router, poly103, 103);
+
+ Polygon poly104(4);
+ poly104.ps[0] = Point(841.5, 1799.17);
+ poly104.ps[1] = Point(841.5, 1859.17);
+ poly104.ps[2] = Point(785.5, 1859.17);
+ poly104.ps[3] = Point(785.5, 1799.17);
+ new ShapeRef(router, poly104, 104);
+
+ Polygon poly105(4);
+ poly105.ps[0] = Point(434.5, 1799.17);
+ poly105.ps[1] = Point(434.5, 1859.17);
+ poly105.ps[2] = Point(378.5, 1859.17);
+ poly105.ps[3] = Point(378.5, 1799.17);
+ new ShapeRef(router, poly105, 105);
+
+ Polygon poly106(4);
+ poly106.ps[0] = Point(1484.5, 1799.17);
+ poly106.ps[1] = Point(1484.5, 1859.17);
+ poly106.ps[2] = Point(1428.5, 1859.17);
+ poly106.ps[3] = Point(1428.5, 1799.17);
+ new ShapeRef(router, poly106, 106);
+
+ Polygon poly107(4);
+ poly107.ps[0] = Point(1375.5, 1645.17);
+ poly107.ps[1] = Point(1375.5, 1685.17);
+ poly107.ps[2] = Point(1299.5, 1685.17);
+ poly107.ps[3] = Point(1299.5, 1645.17);
+ new ShapeRef(router, poly107, 107);
+
+ Polygon poly108(4);
+ poly108.ps[0] = Point(1375.5, 1521.17);
+ poly108.ps[1] = Point(1375.5, 1561.17);
+ poly108.ps[2] = Point(1299.5, 1561.17);
+ poly108.ps[3] = Point(1299.5, 1521.17);
+ new ShapeRef(router, poly108, 108);
+
+ Polygon poly109(4);
+ poly109.ps[0] = Point(1375.5, 1397.17);
+ poly109.ps[1] = Point(1375.5, 1437.17);
+ poly109.ps[2] = Point(1299.5, 1437.17);
+ poly109.ps[3] = Point(1299.5, 1397.17);
+ new ShapeRef(router, poly109, 109);
+
+ Polygon poly110(4);
+ poly110.ps[0] = Point(1258.5, 1007.17);
+ poly110.ps[1] = Point(1258.5, 1047.17);
+ poly110.ps[2] = Point(1182.5, 1047.17);
+ poly110.ps[3] = Point(1182.5, 1007.17);
+ new ShapeRef(router, poly110, 110);
+
+ Polygon poly111(4);
+ poly111.ps[0] = Point(1116.5, 896.167);
+ poly111.ps[1] = Point(1116.5, 956.167);
+ poly111.ps[2] = Point(1060.5, 956.167);
+ poly111.ps[3] = Point(1060.5, 896.167);
+ new ShapeRef(router, poly111, 111);
+
+ Polygon poly112(4);
+ poly112.ps[0] = Point(1258.5, 709.5);
+ poly112.ps[1] = Point(1258.5, 749.5);
+ poly112.ps[2] = Point(1182.5, 749.5);
+ poly112.ps[3] = Point(1182.5, 709.5);
+ new ShapeRef(router, poly112, 112);
+
+ Polygon poly113(4);
+ poly113.ps[0] = Point(1487.5, 709.5);
+ poly113.ps[1] = Point(1487.5, 749.5);
+ poly113.ps[2] = Point(1411.5, 749.5);
+ poly113.ps[3] = Point(1411.5, 709.5);
+ new ShapeRef(router, poly113, 113);
+
+ Polygon poly114(4);
+ poly114.ps[0] = Point(1453.5, 362.5);
+ poly114.ps[1] = Point(1453.5, 422.5);
+ poly114.ps[2] = Point(1397.5, 422.5);
+ poly114.ps[3] = Point(1397.5, 362.5);
+ new ShapeRef(router, poly114, 114);
+
+ Polygon poly115(4);
+ poly115.ps[0] = Point(1375.5, 531.25);
+ poly115.ps[1] = Point(1375.5, 571.25);
+ poly115.ps[2] = Point(1299.5, 571.25);
+ poly115.ps[3] = Point(1299.5, 531.25);
+ new ShapeRef(router, poly115, 115);
+
+ Polygon poly116(4);
+ poly116.ps[0] = Point(1375.5, 340);
+ poly116.ps[1] = Point(1375.5, 380);
+ poly116.ps[2] = Point(1299.5, 380);
+ poly116.ps[3] = Point(1299.5, 340);
+ new ShapeRef(router, poly116, 116);
+
+ Polygon poly117(4);
+ poly117.ps[0] = Point(1054.5, 568.75);
+ poly117.ps[1] = Point(1054.5, 628.75);
+ poly117.ps[2] = Point(998.5, 628.75);
+ poly117.ps[3] = Point(998.5, 568.75);
+ new ShapeRef(router, poly117, 117);
+
+ Polygon poly118(4);
+ poly118.ps[0] = Point(535.5, 472.75);
+ poly118.ps[1] = Point(535.5, 532.75);
+ poly118.ps[2] = Point(479.5, 532.75);
+ poly118.ps[3] = Point(479.5, 472.75);
+ new ShapeRef(router, poly118, 118);
+
+ Polygon poly119(4);
+ poly119.ps[0] = Point(535.5, 547.75);
+ poly119.ps[1] = Point(535.5, 607.75);
+ poly119.ps[2] = Point(479.5, 607.75);
+ poly119.ps[3] = Point(479.5, 547.75);
+ new ShapeRef(router, poly119, 119);
+
+ Polygon poly120(4);
+ poly120.ps[0] = Point(934.5, 481.25);
+ poly120.ps[1] = Point(934.5, 541.25);
+ poly120.ps[2] = Point(878.5, 541.25);
+ poly120.ps[3] = Point(878.5, 481.25);
+ new ShapeRef(router, poly120, 120);
+
+ Polygon poly121(4);
+ poly121.ps[0] = Point(741.5, 531.25);
+ poly121.ps[1] = Point(741.5, 571.25);
+ poly121.ps[2] = Point(665.5, 571.25);
+ poly121.ps[3] = Point(665.5, 531.25);
+ new ShapeRef(router, poly121, 121);
+
+ Polygon poly122(4);
+ poly122.ps[0] = Point(372.5, 531.25);
+ poly122.ps[1] = Point(372.5, 571.25);
+ poly122.ps[2] = Point(296.5, 571.25);
+ poly122.ps[3] = Point(296.5, 531.25);
+ new ShapeRef(router, poly122, 122);
+#endif
+
+ Polygon poly123(4);
+ poly123.ps[0] = Point(628.5, 225);
+ poly123.ps[1] = Point(628.5, 285);
+ poly123.ps[2] = Point(572.5, 285);
+ poly123.ps[3] = Point(572.5, 225);
+ new ShapeRef(router, poly123, 123);
+
+#if 0
+ Polygon poly124(4);
+ poly124.ps[0] = Point(628.5, 300);
+ poly124.ps[1] = Point(628.5, 360);
+ poly124.ps[2] = Point(572.5, 360);
+ poly124.ps[3] = Point(572.5, 300);
+ new ShapeRef(router, poly124, 124);
+
+ Polygon poly125(4);
+ poly125.ps[0] = Point(628.5, 572);
+ poly125.ps[1] = Point(628.5, 632);
+ poly125.ps[2] = Point(572.5, 632);
+ poly125.ps[3] = Point(572.5, 572);
+ new ShapeRef(router, poly125, 125);
+
+ Polygon poly126(4);
+ poly126.ps[0] = Point(903.5, 271);
+ poly126.ps[1] = Point(903.5, 331);
+ poly126.ps[2] = Point(847.5, 331);
+ poly126.ps[3] = Point(847.5, 271);
+ new ShapeRef(router, poly126, 126);
+
+ Polygon poly127(4);
+ poly127.ps[0] = Point(903.5, 169);
+ poly127.ps[1] = Point(903.5, 229);
+ poly127.ps[2] = Point(847.5, 229);
+ poly127.ps[3] = Point(847.5, 169);
+ new ShapeRef(router, poly127, 127);
+
+ Polygon poly128(4);
+ poly128.ps[0] = Point(566.5, 1942.21);
+ poly128.ps[1] = Point(566.5, 2002.21);
+ poly128.ps[2] = Point(510.5, 2002.21);
+ poly128.ps[3] = Point(510.5, 1942.21);
+ new ShapeRef(router, poly128, 128);
+
+ Polygon poly129(4);
+ poly129.ps[0] = Point(1375.5, 1243.17);
+ poly129.ps[1] = Point(1375.5, 1283.17);
+ poly129.ps[2] = Point(1299.5, 1283.17);
+ poly129.ps[3] = Point(1299.5, 1243.17);
+ new ShapeRef(router, poly129, 129);
+
+ Polygon poly130(4);
+ poly130.ps[0] = Point(628.5, 375);
+ poly130.ps[1] = Point(628.5, 435);
+ poly130.ps[2] = Point(572.5, 435);
+ poly130.ps[3] = Point(572.5, 375);
+ new ShapeRef(router, poly130, 130);
+
+ Polygon poly131(4);
+ poly131.ps[0] = Point(535.5, 669.75);
+ poly131.ps[1] = Point(535.5, 729.75);
+ poly131.ps[2] = Point(479.5, 729.75);
+ poly131.ps[3] = Point(479.5, 669.75);
+ new ShapeRef(router, poly131, 131);
+
+ Polygon poly132(4);
+ poly132.ps[0] = Point(314.5, 680.75);
+ poly132.ps[1] = Point(314.5, 740.75);
+ poly132.ps[2] = Point(258.5, 740.75);
+ poly132.ps[3] = Point(258.5, 680.75);
+ new ShapeRef(router, poly132, 132);
+
+ Polygon poly133(4);
+ poly133.ps[0] = Point(314.5, 782.75);
+ poly133.ps[1] = Point(314.5, 842.75);
+ poly133.ps[2] = Point(258.5, 842.75);
+ poly133.ps[3] = Point(258.5, 782.75);
+ new ShapeRef(router, poly133, 133);
+
+ Polygon poly134(4);
+ poly134.ps[0] = Point(690.5, 680.75);
+ poly134.ps[1] = Point(690.5, 740.75);
+ poly134.ps[2] = Point(634.5, 740.75);
+ poly134.ps[3] = Point(634.5, 680.75);
+ new ShapeRef(router, poly134, 134);
+
+ Polygon poly135(4);
+ poly135.ps[0] = Point(690.5, 782.75);
+ poly135.ps[1] = Point(690.5, 842.75);
+ poly135.ps[2] = Point(634.5, 842.75);
+ poly135.ps[3] = Point(634.5, 782.75);
+ new ShapeRef(router, poly135, 135);
+
+ Polygon poly136(4);
+ poly136.ps[0] = Point(403.5, 1512.17);
+ poly136.ps[1] = Point(403.5, 1572.17);
+ poly136.ps[2] = Point(347.5, 1572.17);
+ poly136.ps[3] = Point(347.5, 1512.17);
+ new ShapeRef(router, poly136, 136);
+
+ Polygon poly137(4);
+ poly137.ps[0] = Point(1267.5, 2110.54);
+ poly137.ps[1] = Point(1267.5, 2170.54);
+ poly137.ps[2] = Point(1211.5, 2170.54);
+ poly137.ps[3] = Point(1211.5, 2110.54);
+ new ShapeRef(router, poly137, 137);
+
+ Polygon poly138(4);
+ poly138.ps[0] = Point(403.5, 1634.17);
+ poly138.ps[1] = Point(403.5, 1694.17);
+ poly138.ps[2] = Point(347.5, 1694.17);
+ poly138.ps[3] = Point(347.5, 1634.17);
+ new ShapeRef(router, poly138, 138);
+
+ Polygon poly139(4);
+ poly139.ps[0] = Point(1396.5, 1007.17);
+ poly139.ps[1] = Point(1396.5, 1047.17);
+ poly139.ps[2] = Point(1320.5, 1047.17);
+ poly139.ps[3] = Point(1320.5, 1007.17);
+ new ShapeRef(router, poly139, 139);
+
+ Polygon poly140(4);
+ poly140.ps[0] = Point(1386.5, 1181.17);
+ poly140.ps[1] = Point(1386.5, 1221.17);
+ poly140.ps[2] = Point(1310.5, 1221.17);
+ poly140.ps[3] = Point(1310.5, 1181.17);
+ new ShapeRef(router, poly140, 140);
+
+ Polygon poly141(4);
+ poly141.ps[0] = Point(1524.5, 1181.17);
+ poly141.ps[1] = Point(1524.5, 1221.17);
+ poly141.ps[2] = Point(1448.5, 1221.17);
+ poly141.ps[3] = Point(1448.5, 1181.17);
+ new ShapeRef(router, poly141, 141);
+
+ Polygon poly142(4);
+ poly142.ps[0] = Point(690.5, 1670.17);
+ poly142.ps[1] = Point(690.5, 1730.17);
+ poly142.ps[2] = Point(634.5, 1730.17);
+ poly142.ps[3] = Point(634.5, 1670.17);
+ new ShapeRef(router, poly142, 142);
+
+ Polygon poly143(4);
+ poly143.ps[0] = Point(1615.5, 1181.17);
+ poly143.ps[1] = Point(1615.5, 1221.17);
+ poly143.ps[2] = Point(1539.5, 1221.17);
+ poly143.ps[3] = Point(1539.5, 1181.17);
+ new ShapeRef(router, poly143, 143);
+
+ Polygon poly144(4);
+ poly144.ps[0] = Point(1236.5, 1273.17);
+ poly144.ps[1] = Point(1236.5, 1333.17);
+ poly144.ps[2] = Point(1180.5, 1333.17);
+ poly144.ps[3] = Point(1180.5, 1273.17);
+ new ShapeRef(router, poly144, 144);
+
+ Polygon poly145(4);
+ poly145.ps[0] = Point(1236.5, 1069.17);
+ poly145.ps[1] = Point(1236.5, 1129.17);
+ poly145.ps[2] = Point(1180.5, 1129.17);
+ poly145.ps[3] = Point(1180.5, 1069.17);
+ new ShapeRef(router, poly145, 145);
+
+ Polygon poly146(4);
+ poly146.ps[0] = Point(220.5, 1910.17);
+ poly146.ps[1] = Point(220.5, 1950.17);
+ poly146.ps[2] = Point(144.5, 1950.17);
+ poly146.ps[3] = Point(144.5, 1910.17);
+ new ShapeRef(router, poly146, 146);
+
+ Polygon poly147(4);
+ poly147.ps[0] = Point(1396.5, 709.5);
+ poly147.ps[1] = Point(1396.5, 749.5);
+ poly147.ps[2] = Point(1320.5, 749.5);
+ poly147.ps[3] = Point(1320.5, 709.5);
+ new ShapeRef(router, poly147, 147);
+
+ Polygon poly148(4);
+ poly148.ps[0] = Point(628.5, 497);
+ poly148.ps[1] = Point(628.5, 557);
+ poly148.ps[2] = Point(572.5, 557);
+ poly148.ps[3] = Point(572.5, 497);
+ new ShapeRef(router, poly148, 148);
+
+ Polygon poly149(4);
+ poly149.ps[0] = Point(535.5, 744.75);
+ poly149.ps[1] = Point(535.5, 804.75);
+ poly149.ps[2] = Point(479.5, 804.75);
+ poly149.ps[3] = Point(479.5, 744.75);
+ new ShapeRef(router, poly149, 149);
+
+ Polygon poly150(4);
+ poly150.ps[0] = Point(1267.5, 2185.54);
+ poly150.ps[1] = Point(1267.5, 2245.54);
+ poly150.ps[2] = Point(1211.5, 2245.54);
+ poly150.ps[3] = Point(1211.5, 2185.54);
+ new ShapeRef(router, poly150, 150);
+
+ Polygon poly151(4);
+ poly151.ps[0] = Point(1570, 641);
+ poly151.ps[1] = Point(1570, 681);
+ poly151.ps[2] = Point(1510, 681);
+ poly151.ps[3] = Point(1510, 641);
+ new ShapeRef(router, poly151, 151);
+
+ Polygon poly152(4);
+ poly152.ps[0] = Point(1570, 681);
+ poly152.ps[1] = Point(1570, 721);
+ poly152.ps[2] = Point(1510, 721);
+ poly152.ps[3] = Point(1510, 681);
+ new ShapeRef(router, poly152, 152);
+
+ Polygon poly153(4);
+ poly153.ps[0] = Point(1621, 809.5);
+ poly153.ps[1] = Point(1621, 869.5);
+ poly153.ps[2] = Point(1581, 869.5);
+ poly153.ps[3] = Point(1581, 809.5);
+ new ShapeRef(router, poly153, 153);
+
+ Polygon poly154(4);
+ poly154.ps[0] = Point(1661, 809.5);
+ poly154.ps[1] = Point(1661, 869.5);
+ poly154.ps[2] = Point(1621, 869.5);
+ poly154.ps[3] = Point(1621, 809.5);
+ new ShapeRef(router, poly154, 154);
+
+ Polygon poly155(4);
+ poly155.ps[0] = Point(1370, 159.5);
+ poly155.ps[1] = Point(1370, 219.5);
+ poly155.ps[2] = Point(1330, 219.5);
+ poly155.ps[3] = Point(1330, 159.5);
+ new ShapeRef(router, poly155, 155);
+
+ Polygon poly156(4);
+ poly156.ps[0] = Point(252.5, 1705.67);
+ poly156.ps[1] = Point(252.5, 1745.67);
+ poly156.ps[2] = Point(192.5, 1745.67);
+ poly156.ps[3] = Point(192.5, 1705.67);
+ new ShapeRef(router, poly156, 156);
+
+ Polygon poly157(4);
+ poly157.ps[0] = Point(252.5, 1745.67);
+ poly157.ps[1] = Point(252.5, 1785.67);
+ poly157.ps[2] = Point(192.5, 1785.67);
+ poly157.ps[3] = Point(192.5, 1745.67);
+ new ShapeRef(router, poly157, 157);
+
+ Polygon poly158(4);
+ poly158.ps[0] = Point(849.5, 1342.67);
+ poly158.ps[1] = Point(849.5, 1382.67);
+ poly158.ps[2] = Point(789.5, 1382.67);
+ poly158.ps[3] = Point(789.5, 1342.67);
+ new ShapeRef(router, poly158, 158);
+
+ Polygon poly159(4);
+ poly159.ps[0] = Point(1556.5, 1943.54);
+ poly159.ps[1] = Point(1556.5, 2003.54);
+ poly159.ps[2] = Point(1516.5, 2003.54);
+ poly159.ps[3] = Point(1516.5, 1943.54);
+ new ShapeRef(router, poly159, 159);
+
+ Polygon poly160(4);
+ poly160.ps[0] = Point(661.5, 2058.54);
+ poly160.ps[1] = Point(661.5, 2100.54);
+ poly160.ps[2] = Point(593.5, 2100.54);
+ poly160.ps[3] = Point(593.5, 2058.54);
+ new ShapeRef(router, poly160, 160);
+
+ Polygon poly161(4);
+ poly161.ps[0] = Point(272.5, 1900.17);
+ poly161.ps[1] = Point(272.5, 1960.17);
+ poly161.ps[2] = Point(230.5, 1960.17);
+ poly161.ps[3] = Point(230.5, 1900.17);
+ new ShapeRef(router, poly161, 161);
+#endif
+
+ Polygon poly162(4);
+ poly162.ps[0] = Point(630.5, 295);
+ poly162.ps[1] = Point(630.5, 562);
+ poly162.ps[2] = Point(562.5, 562);
+ poly162.ps[3] = Point(562.5, 295);
+ new ShapeRef(router, poly162, 162);
+
+ Polygon poly163(4);
+ poly163.ps[0] = Point(537.5, 542.75);
+ poly163.ps[1] = Point(537.5, 734.75);
+ poly163.ps[2] = Point(469.5, 734.75);
+ poly163.ps[3] = Point(469.5, 542.75);
+ new ShapeRef(router, poly163, 163);
+
+#if 0
+ Polygon poly164(4);
+ poly164.ps[0] = Point(1401.5, 699.5);
+ poly164.ps[1] = Point(1401.5, 759.5);
+ poly164.ps[2] = Point(1268.5, 759.5);
+ poly164.ps[3] = Point(1268.5, 699.5);
+ new ShapeRef(router, poly164, 164);
+
+ Polygon poly165(4);
+ poly165.ps[0] = Point(405.5, 1582.17);
+ poly165.ps[1] = Point(405.5, 1624.17);
+ poly165.ps[2] = Point(337.5, 1624.17);
+ poly165.ps[3] = Point(337.5, 1582.17);
+ new ShapeRef(router, poly165, 165);
+
+ Polygon poly166(4);
+ poly166.ps[0] = Point(1529.5, 1171.17);
+ poly166.ps[1] = Point(1529.5, 1231.17);
+ poly166.ps[2] = Point(1396.5, 1231.17);
+ poly166.ps[3] = Point(1396.5, 1171.17);
+ new ShapeRef(router, poly166, 166);
+
+ Polygon poly167(4);
+ poly167.ps[0] = Point(1310.5, 997.167);
+ poly167.ps[1] = Point(1310.5, 1057.17);
+ poly167.ps[2] = Point(1268.5, 1057.17);
+ poly167.ps[3] = Point(1268.5, 997.167);
+ new ShapeRef(router, poly167, 167);
+
+ Polygon poly168(4);
+ poly168.ps[0] = Point(1269.5, 1983.54);
+ poly168.ps[1] = Point(1269.5, 2175.54);
+ poly168.ps[2] = Point(1201.5, 2175.54);
+ poly168.ps[3] = Point(1201.5, 1983.54);
+ new ShapeRef(router, poly168, 168);
+
+ ConnRef *connRef169 = new ConnRef(router, 169);
+ ConnEnd srcPt169(Point(1289.5, 886.5), 2);
+ connRef169->setSourceEndpoint(srcPt169);
+ ConnEnd dstPt169(Point(844.5, 966.167), 15);
+ connRef169->setDestEndpoint(dstPt169);
+ connRef169->setRoutingType((ConnType)2);
+
+ ConnRef *connRef170 = new ConnRef(router, 170);
+ ConnEnd srcPt170(Point(1289.5, 856.5), 1);
+ connRef170->setSourceEndpoint(srcPt170);
+ ConnEnd dstPt170(Point(1289.5, 790.5), 15);
+ connRef170->setDestEndpoint(dstPt170);
+ connRef170->setRoutingType((ConnType)2);
+
+ ConnRef *connRef171 = new ConnRef(router, 171);
+ ConnEnd srcPt171(Point(1289.5, 886.5), 2);
+ connRef171->setSourceEndpoint(srcPt171);
+ ConnEnd dstPt171(Point(1289.5, 966.167), 15);
+ connRef171->setDestEndpoint(dstPt171);
+ connRef171->setRoutingType((ConnType)2);
+
+ ConnRef *connRef172 = new ConnRef(router, 172);
+ ConnEnd srcPt172(Point(616.5, 2058.54), 4);
+ connRef172->setSourceEndpoint(srcPt172);
+ ConnEnd dstPt172(Point(251.5, 2079.54), 15);
+ connRef172->setDestEndpoint(dstPt172);
+ connRef172->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints172(1);
+ checkpoints172[0] = Point(593.5, 2079.54);
+ connRef172->setRoutingCheckpoints(checkpoints172);
+
+ ConnRef *connRef173 = new ConnRef(router, 173);
+ ConnEnd srcPt173(Point(646.5, 2058.54), 8);
+ connRef173->setSourceEndpoint(srcPt173);
+ ConnEnd dstPt173(Point(937.5, 2079.54), 15);
+ connRef173->setDestEndpoint(dstPt173);
+ connRef173->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints173(1);
+ checkpoints173[0] = Point(669.5, 2079.54);
+ connRef173->setRoutingCheckpoints(checkpoints173);
+
+ ConnRef *connRef174 = new ConnRef(router, 174);
+ ConnEnd srcPt174(Point(272.5, 1945.17), 2);
+ connRef174->setSourceEndpoint(srcPt174);
+ ConnEnd dstPt174(Point(251.5, 2079.54), 15);
+ connRef174->setDestEndpoint(dstPt174);
+ connRef174->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints174(1);
+ checkpoints174[0] = Point(251.5, 1960.17);
+ connRef174->setRoutingCheckpoints(checkpoints174);
+
+ ConnRef *connRef175 = new ConnRef(router, 175);
+ ConnEnd srcPt175(Point(616.5, 2100.54), 4);
+ connRef175->setSourceEndpoint(srcPt175);
+ ConnEnd dstPt175(Point(251.5, 2079.54), 15);
+ connRef175->setDestEndpoint(dstPt175);
+ connRef175->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints175(1);
+ checkpoints175[0] = Point(593.5, 2079.54);
+ connRef175->setRoutingCheckpoints(checkpoints175);
+
+ ConnRef *connRef176 = new ConnRef(router, 176);
+ ConnEnd srcPt176(Point(646.5, 2100.54), 8);
+ connRef176->setSourceEndpoint(srcPt176);
+ ConnEnd dstPt176(Point(937.5, 2079.54), 15);
+ connRef176->setDestEndpoint(dstPt176);
+ connRef176->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints176(1);
+ checkpoints176[0] = Point(669.5, 2079.54);
+ connRef176->setRoutingCheckpoints(checkpoints176);
+
+ ConnRef *connRef177 = new ConnRef(router, 177);
+ ConnEnd srcPt177(Point(251.5, 2079.54), 15);
+ connRef177->setSourceEndpoint(srcPt177);
+ ConnEnd dstPt177(Point(230.5, 1945.17), 2);
+ connRef177->setDestEndpoint(dstPt177);
+ connRef177->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints177(1);
+ checkpoints177[0] = Point(251.5, 1960.17);
+ connRef177->setRoutingCheckpoints(checkpoints177);
+
+ ConnRef *connRef178 = new ConnRef(router, 178);
+ ConnEnd srcPt178(Point(937.5, 2032.54), 2);
+ connRef178->setSourceEndpoint(srcPt178);
+ ConnEnd dstPt178(Point(937.5, 2079.54), 15);
+ connRef178->setDestEndpoint(dstPt178);
+ connRef178->setRoutingType((ConnType)2);
+
+ ConnRef *connRef179 = new ConnRef(router, 179);
+ ConnEnd srcPt179(Point(1224.5, 1983.54), 4);
+ connRef179->setSourceEndpoint(srcPt179);
+ ConnEnd dstPt179(Point(937.5, 2079.54), 15);
+ connRef179->setDestEndpoint(dstPt179);
+ connRef179->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints179(1);
+ checkpoints179[0] = Point(1201.5, 2079.54);
+ connRef179->setRoutingCheckpoints(checkpoints179);
+
+ ConnRef *connRef180 = new ConnRef(router, 180);
+ ConnEnd srcPt180(Point(1224.5, 2058.54), 4);
+ connRef180->setSourceEndpoint(srcPt180);
+ ConnEnd dstPt180(Point(937.5, 2079.54), 15);
+ connRef180->setDestEndpoint(dstPt180);
+ connRef180->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints180(1);
+ checkpoints180[0] = Point(1201.5, 2079.54);
+ connRef180->setRoutingCheckpoints(checkpoints180);
+
+ ConnRef *connRef181 = new ConnRef(router, 181);
+ ConnEnd srcPt181(Point(1104.5, 1879.54), 4);
+ connRef181->setSourceEndpoint(srcPt181);
+ ConnEnd dstPt181(Point(937.5, 1869.17), 15);
+ connRef181->setDestEndpoint(dstPt181);
+ connRef181->setRoutingType((ConnType)2);
+
+ ConnRef *connRef182 = new ConnRef(router, 182);
+ ConnEnd srcPt182(Point(1119.5, 1813.17), 2);
+ connRef182->setSourceEndpoint(srcPt182);
+ ConnEnd dstPt182(Point(937.5, 1869.17), 15);
+ connRef182->setDestEndpoint(dstPt182);
+ connRef182->setRoutingType((ConnType)2);
+
+ ConnRef *connRef183 = new ConnRef(router, 183);
+ ConnEnd srcPt183(Point(798.5, 1869.17), 4);
+ connRef183->setSourceEndpoint(srcPt183);
+ ConnEnd dstPt183(Point(569.5, 1869.17), 15);
+ connRef183->setDestEndpoint(dstPt183);
+ connRef183->setRoutingType((ConnType)2);
+
+ ConnRef *connRef184 = new ConnRef(router, 184);
+ ConnEnd srcPt184(Point(798.5, 1869.17), 4);
+ connRef184->setSourceEndpoint(srcPt184);
+ ConnEnd dstPt184(Point(937.5, 1765.17), 15);
+ connRef184->setDestEndpoint(dstPt184);
+ connRef184->setRoutingType((ConnType)2);
+
+ ConnRef *connRef185 = new ConnRef(router, 185);
+ ConnEnd srcPt185(Point(391.5, 1869.17), 4);
+ connRef185->setSourceEndpoint(srcPt185);
+ ConnEnd dstPt185(Point(251.5, 1869.17), 15);
+ connRef185->setDestEndpoint(dstPt185);
+ connRef185->setRoutingType((ConnType)2);
+
+ ConnRef *connRef186 = new ConnRef(router, 186);
+ ConnEnd srcPt186(Point(421.5, 1869.17), 8);
+ connRef186->setSourceEndpoint(srcPt186);
+ ConnEnd dstPt186(Point(569.5, 1869.17), 15);
+ connRef186->setDestEndpoint(dstPt186);
+ connRef186->setRoutingType((ConnType)2);
+
+ ConnRef *connRef187 = new ConnRef(router, 187);
+ ConnEnd srcPt187(Point(391.5, 1869.17), 4);
+ connRef187->setSourceEndpoint(srcPt187);
+ ConnEnd dstPt187(Point(406.5, 2012.21), 15);
+ connRef187->setDestEndpoint(dstPt187);
+ connRef187->setRoutingType((ConnType)2);
+
+ ConnRef *connRef188 = new ConnRef(router, 188);
+ ConnEnd srcPt188(Point(1471.5, 1869.17), 8);
+ connRef188->setSourceEndpoint(srcPt188);
+ ConnEnd dstPt188(Point(1530.5, 1869.17), 15);
+ connRef188->setDestEndpoint(dstPt188);
+ connRef188->setRoutingType((ConnType)2);
+
+ ConnRef *connRef189 = new ConnRef(router, 189);
+ ConnEnd srcPt189(Point(1441.5, 1869.17), 4);
+ connRef189->setSourceEndpoint(srcPt189);
+ ConnEnd dstPt189(Point(1289.5, 1869.17), 15);
+ connRef189->setDestEndpoint(dstPt189);
+ connRef189->setRoutingType((ConnType)2);
+
+ ConnRef *connRef190 = new ConnRef(router, 190);
+ ConnEnd srcPt190(Point(1289.5, 1680.17), 2);
+ connRef190->setSourceEndpoint(srcPt190);
+ ConnEnd dstPt190(Point(1289.5, 1869.17), 15);
+ connRef190->setDestEndpoint(dstPt190);
+ connRef190->setRoutingType((ConnType)2);
+
+ ConnRef *connRef191 = new ConnRef(router, 191);
+ ConnEnd srcPt191(Point(1289.5, 1526.17), 1);
+ connRef191->setSourceEndpoint(srcPt191);
+ ConnEnd dstPt191(Point(1289.5, 1479.17), 15);
+ connRef191->setDestEndpoint(dstPt191);
+ connRef191->setRoutingType((ConnType)2);
+
+ ConnRef *connRef192 = new ConnRef(router, 192);
+ ConnEnd srcPt192(Point(1289.5, 1556.17), 2);
+ connRef192->setSourceEndpoint(srcPt192);
+ ConnEnd dstPt192(Point(1289.5, 1603.17), 15);
+ connRef192->setDestEndpoint(dstPt192);
+ connRef192->setRoutingType((ConnType)2);
+
+ ConnRef *connRef193 = new ConnRef(router, 193);
+ ConnEnd srcPt193(Point(1289.5, 1432.17), 2);
+ connRef193->setSourceEndpoint(srcPt193);
+ ConnEnd dstPt193(Point(1289.5, 1479.17), 15);
+ connRef193->setDestEndpoint(dstPt193);
+ connRef193->setRoutingType((ConnType)2);
+
+ ConnRef *connRef194 = new ConnRef(router, 194);
+ ConnEnd srcPt194(Point(1289.5, 1402.17), 1);
+ connRef194->setSourceEndpoint(srcPt194);
+ ConnEnd dstPt194(Point(1289.5, 1355.17), 15);
+ connRef194->setDestEndpoint(dstPt194);
+ connRef194->setRoutingType((ConnType)2);
+
+ ConnRef *connRef195 = new ConnRef(router, 195);
+ ConnEnd srcPt195(Point(1268.5, 1042.17), 2);
+ connRef195->setSourceEndpoint(srcPt195);
+ ConnEnd dstPt195(Point(1289.5, 1139.17), 15);
+ connRef195->setDestEndpoint(dstPt195);
+ connRef195->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints195(1);
+ checkpoints195[0] = Point(1289.5, 1057.17);
+ connRef195->setRoutingCheckpoints(checkpoints195);
+
+ ConnRef *connRef196 = new ConnRef(router, 196);
+ ConnEnd srcPt196(Point(1268.5, 1012.17), 1);
+ connRef196->setSourceEndpoint(srcPt196);
+ ConnEnd dstPt196(Point(1289.5, 966.167), 15);
+ connRef196->setDestEndpoint(dstPt196);
+ connRef196->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints196(1);
+ checkpoints196[0] = Point(1289.5, 997.167);
+ connRef196->setRoutingCheckpoints(checkpoints196);
+
+ ConnRef *connRef197 = new ConnRef(router, 197);
+ ConnEnd srcPt197(Point(1073.5, 966.167), 4);
+ connRef197->setSourceEndpoint(srcPt197);
+ ConnEnd dstPt197(Point(844.5, 966.167), 15);
+ connRef197->setDestEndpoint(dstPt197);
+ connRef197->setRoutingType((ConnType)2);
+
+ ConnRef *connRef198 = new ConnRef(router, 198);
+ ConnEnd srcPt198(Point(1103.5, 966.167), 8);
+ connRef198->setSourceEndpoint(srcPt198);
+ ConnEnd dstPt198(Point(1289.5, 966.167), 15);
+ connRef198->setDestEndpoint(dstPt198);
+ connRef198->setRoutingType((ConnType)2);
+
+ ConnRef *connRef199 = new ConnRef(router, 199);
+ ConnEnd srcPt199(Point(1268.5, 744.5), 2);
+ connRef199->setSourceEndpoint(srcPt199);
+ ConnEnd dstPt199(Point(1289.5, 790.5), 15);
+ connRef199->setDestEndpoint(dstPt199);
+ connRef199->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints199(1);
+ checkpoints199[0] = Point(1289.5, 759.5);
+ connRef199->setRoutingCheckpoints(checkpoints199);
+
+ ConnRef *connRef200 = new ConnRef(router, 200);
+ ConnEnd srcPt200(Point(1401.5, 714.5), 1);
+ connRef200->setSourceEndpoint(srcPt200);
+ ConnEnd dstPt200(Point(1289.5, 638.75), 15);
+ connRef200->setDestEndpoint(dstPt200);
+ connRef200->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints200(1);
+ checkpoints200[0] = Point(1289.5, 699.5);
+ connRef200->setRoutingCheckpoints(checkpoints200);
+
+ ConnRef *connRef201 = new ConnRef(router, 201);
+ ConnEnd srcPt201(Point(1410.5, 432.5), 4);
+ connRef201->setSourceEndpoint(srcPt201);
+ ConnEnd dstPt201(Point(1289.5, 466), 15);
+ connRef201->setDestEndpoint(dstPt201);
+ connRef201->setRoutingType((ConnType)2);
+
+ ConnRef *connRef202 = new ConnRef(router, 202);
+ ConnEnd srcPt202(Point(1289.5, 536.25), 1);
+ connRef202->setSourceEndpoint(srcPt202);
+ ConnEnd dstPt202(Point(1289.5, 466), 15);
+ connRef202->setDestEndpoint(dstPt202);
+ connRef202->setRoutingType((ConnType)2);
+
+ ConnRef *connRef203 = new ConnRef(router, 203);
+ ConnEnd srcPt203(Point(1289.5, 566.25), 2);
+ connRef203->setSourceEndpoint(srcPt203);
+ ConnEnd dstPt203(Point(1289.5, 638.75), 15);
+ connRef203->setDestEndpoint(dstPt203);
+ connRef203->setRoutingType((ConnType)2);
+
+ ConnRef *connRef204 = new ConnRef(router, 204);
+ ConnEnd srcPt204(Point(1289.5, 345), 1);
+ connRef204->setSourceEndpoint(srcPt204);
+ ConnEnd dstPt204(Point(1289.5, 280), 15);
+ connRef204->setDestEndpoint(dstPt204);
+ connRef204->setRoutingType((ConnType)2);
+
+ ConnRef *connRef205 = new ConnRef(router, 205);
+ ConnEnd srcPt205(Point(1289.5, 375), 2);
+ connRef205->setSourceEndpoint(srcPt205);
+ ConnEnd dstPt205(Point(1289.5, 466), 15);
+ connRef205->setDestEndpoint(dstPt205);
+ connRef205->setRoutingType((ConnType)2);
+
+ ConnRef *connRef206 = new ConnRef(router, 206);
+ ConnEnd srcPt206(Point(1011.5, 638.75), 4);
+ connRef206->setSourceEndpoint(srcPt206);
+ ConnEnd dstPt206(Point(844.5, 638.75), 15);
+ connRef206->setDestEndpoint(dstPt206);
+ connRef206->setRoutingType((ConnType)2);
+
+ ConnRef *connRef207 = new ConnRef(router, 207);
+ ConnEnd srcPt207(Point(1041.5, 638.75), 8);
+ connRef207->setSourceEndpoint(srcPt207);
+ ConnEnd dstPt207(Point(1289.5, 638.75), 15);
+ connRef207->setDestEndpoint(dstPt207);
+ connRef207->setRoutingType((ConnType)2);
+
+ ConnRef *connRef208 = new ConnRef(router, 208);
+ ConnEnd srcPt208(Point(522.5, 542.75), 8);
+ connRef208->setSourceEndpoint(srcPt208);
+ ConnEnd dstPt208(Point(844.5, 638.75), 15);
+ connRef208->setDestEndpoint(dstPt208);
+ connRef208->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints208(1);
+ checkpoints208[0] = Point(545.5, 638.75);
+ connRef208->setRoutingCheckpoints(checkpoints208);
+
+ ConnRef *connRef209 = new ConnRef(router, 209);
+ ConnEnd srcPt209(Point(522.5, 617.75), 8);
+ connRef209->setSourceEndpoint(srcPt209);
+ ConnEnd dstPt209(Point(844.5, 638.75), 15);
+ connRef209->setDestEndpoint(dstPt209);
+ connRef209->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints209(1);
+ checkpoints209[0] = Point(545.5, 638.75);
+ connRef209->setRoutingCheckpoints(checkpoints209);
+
+ ConnRef *connRef210 = new ConnRef(router, 210);
+ ConnEnd srcPt210(Point(891.5, 551.25), 4);
+ connRef210->setSourceEndpoint(srcPt210);
+ ConnEnd dstPt210(Point(844.5, 638.75), 15);
+ connRef210->setDestEndpoint(dstPt210);
+ connRef210->setRoutingType((ConnType)2);
+
+ ConnRef *connRef211 = new ConnRef(router, 211);
+ ConnEnd srcPt211(Point(921.5, 551.25), 8);
+ connRef211->setSourceEndpoint(srcPt211);
+ ConnEnd dstPt211(Point(1289.5, 466), 15);
+ connRef211->setDestEndpoint(dstPt211);
+ connRef211->setRoutingType((ConnType)2);
+
+ ConnRef *connRef212 = new ConnRef(router, 212);
+ ConnEnd srcPt212(Point(751.5, 566.25), 2);
+ connRef212->setSourceEndpoint(srcPt212);
+ ConnEnd dstPt212(Point(844.5, 638.75), 15);
+ connRef212->setDestEndpoint(dstPt212);
+ connRef212->setRoutingType((ConnType)2);
+
+ ConnRef *connRef213 = new ConnRef(router, 213);
+ ConnEnd srcPt213(Point(751.5, 536.25), 1);
+ connRef213->setSourceEndpoint(srcPt213);
+ ConnEnd dstPt213(Point(1289.5, 466), 15);
+ connRef213->setDestEndpoint(dstPt213);
+ connRef213->setRoutingType((ConnType)2);
+
+ ConnRef *connRef214 = new ConnRef(router, 214);
+ ConnEnd srcPt214(Point(286.5, 536.25), 1);
+ connRef214->setSourceEndpoint(srcPt214);
+ ConnEnd dstPt214(Point(286.5, 466), 15);
+ connRef214->setDestEndpoint(dstPt214);
+ connRef214->setRoutingType((ConnType)2);
+
+ ConnRef *connRef215 = new ConnRef(router, 215);
+ ConnEnd srcPt215(Point(286.5, 566.25), 2);
+ connRef215->setSourceEndpoint(srcPt215);
+ ConnEnd dstPt215(Point(286.5, 638.75), 15);
+ connRef215->setDestEndpoint(dstPt215);
+ connRef215->setRoutingType((ConnType)2);
+
+ ConnRef *connRef216 = new ConnRef(router, 216);
+ ConnEnd srcPt216(Point(615.5, 295), 8);
+ connRef216->setSourceEndpoint(srcPt216);
+ ConnEnd dstPt216(Point(1289.5, 466), 15);
+ connRef216->setDestEndpoint(dstPt216);
+ connRef216->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints216(1);
+ checkpoints216[0] = Point(638.5, 466);
+ connRef216->setRoutingCheckpoints(checkpoints216);
+
+ ConnRef *connRef217 = new ConnRef(router, 217);
+ ConnEnd srcPt217(Point(615.5, 370), 8);
+ connRef217->setSourceEndpoint(srcPt217);
+ ConnEnd dstPt217(Point(1289.5, 466), 15);
+ connRef217->setDestEndpoint(dstPt217);
+ connRef217->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints217(1);
+ checkpoints217[0] = Point(638.5, 466);
+ connRef217->setRoutingCheckpoints(checkpoints217);
+
+ ConnRef *connRef218 = new ConnRef(router, 218);
+ ConnEnd srcPt218(Point(585.5, 562), 4);
+ connRef218->setSourceEndpoint(srcPt218);
+ ConnEnd dstPt218(Point(286.5, 466), 15);
+ connRef218->setDestEndpoint(dstPt218);
+ connRef218->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints218(1);
+ checkpoints218[0] = Point(562.5, 466);
+ connRef218->setRoutingCheckpoints(checkpoints218);
+#endif
+
+ ConnRef *connRef219 = new ConnRef(router, 219);
+ ConnEnd srcPt219(Point(860.5, 341), 4);
+ connRef219->setSourceEndpoint(srcPt219);
+ ConnEnd dstPt219(Point(286.5, 466), 15);
+ connRef219->setDestEndpoint(dstPt219);
+ connRef219->setRoutingType((ConnType)2);
+
+ ConnRef *connRef220 = new ConnRef(router, 220);
+ ConnEnd srcPt220(Point(860.5, 239), 4);
+ connRef220->setSourceEndpoint(srcPt220);
+ ConnEnd dstPt220(Point(286.5, 466), 15);
+ connRef220->setDestEndpoint(dstPt220);
+ connRef220->setRoutingType((ConnType)2);
+
+#if 0
+ ConnRef *connRef221 = new ConnRef(router, 221);
+ ConnEnd srcPt221(Point(553.5, 2012.21), 8);
+ connRef221->setSourceEndpoint(srcPt221);
+ ConnEnd dstPt221(Point(782.5, 2012.21), 15);
+ connRef221->setDestEndpoint(dstPt221);
+ connRef221->setRoutingType((ConnType)2);
+
+ ConnRef *connRef222 = new ConnRef(router, 222);
+ ConnEnd srcPt222(Point(1289.5, 1278.17), 2);
+ connRef222->setSourceEndpoint(srcPt222);
+ ConnEnd dstPt222(Point(1289.5, 1355.17), 15);
+ connRef222->setDestEndpoint(dstPt222);
+ connRef222->setRoutingType((ConnType)2);
+
+ ConnRef *connRef223 = new ConnRef(router, 223);
+ ConnEnd srcPt223(Point(1289.5, 1248.17), 1);
+ connRef223->setSourceEndpoint(srcPt223);
+ ConnEnd dstPt223(Point(1289.5, 1139.17), 15);
+ connRef223->setDestEndpoint(dstPt223);
+ connRef223->setRoutingType((ConnType)2);
+
+ ConnRef *connRef224 = new ConnRef(router, 224);
+ ConnEnd srcPt224(Point(615.5, 445), 8);
+ connRef224->setSourceEndpoint(srcPt224);
+ ConnEnd dstPt224(Point(1289.5, 466), 15);
+ connRef224->setDestEndpoint(dstPt224);
+ connRef224->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints224(1);
+ checkpoints224[0] = Point(638.5, 466);
+ connRef224->setRoutingCheckpoints(checkpoints224);
+
+ ConnRef *connRef225 = new ConnRef(router, 225);
+ ConnEnd srcPt225(Point(522.5, 659.75), 8);
+ connRef225->setSourceEndpoint(srcPt225);
+ ConnEnd dstPt225(Point(844.5, 638.75), 15);
+ connRef225->setDestEndpoint(dstPt225);
+ connRef225->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints225(1);
+ checkpoints225[0] = Point(545.5, 638.75);
+ connRef225->setRoutingCheckpoints(checkpoints225);
+
+ ConnRef *connRef226 = new ConnRef(router, 226);
+ ConnEnd srcPt226(Point(301.5, 750.75), 8);
+ connRef226->setSourceEndpoint(srcPt226);
+ ConnEnd dstPt226(Point(437.5, 750.75), 15);
+ connRef226->setDestEndpoint(dstPt226);
+ connRef226->setRoutingType((ConnType)2);
+
+ ConnRef *connRef227 = new ConnRef(router, 227);
+ ConnEnd srcPt227(Point(301.5, 852.75), 8);
+ connRef227->setSourceEndpoint(srcPt227);
+ ConnEnd dstPt227(Point(437.5, 852.75), 15);
+ connRef227->setDestEndpoint(dstPt227);
+ connRef227->setRoutingType((ConnType)2);
+
+ ConnRef *connRef228 = new ConnRef(router, 228);
+ ConnEnd srcPt228(Point(677.5, 750.75), 8);
+ connRef228->setSourceEndpoint(srcPt228);
+ ConnEnd dstPt228(Point(844.5, 638.75), 15);
+ connRef228->setDestEndpoint(dstPt228);
+ connRef228->setRoutingType((ConnType)2);
+
+ ConnRef *connRef229 = new ConnRef(router, 229);
+ ConnEnd srcPt229(Point(677.5, 852.75), 8);
+ connRef229->setSourceEndpoint(srcPt229);
+ ConnEnd dstPt229(Point(844.5, 638.75), 15);
+ connRef229->setDestEndpoint(dstPt229);
+ connRef229->setRoutingType((ConnType)2);
+
+ ConnRef *connRef230 = new ConnRef(router, 230);
+ ConnEnd srcPt230(Point(1499.5, 432.5), 15);
+ connRef230->setSourceEndpoint(srcPt230);
+ ConnEnd dstPt230(Point(1440.5, 432.5), 8);
+ connRef230->setDestEndpoint(dstPt230);
+ connRef230->setRoutingType((ConnType)2);
+
+ ConnRef *connRef231 = new ConnRef(router, 231);
+ ConnEnd srcPt231(Point(286.5, 466), 15);
+ connRef231->setSourceEndpoint(srcPt231);
+ ConnEnd dstPt231(Point(585.5, 445), 4);
+ connRef231->setDestEndpoint(dstPt231);
+ connRef231->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints231(1);
+ checkpoints231[0] = Point(562.5, 466);
+ connRef231->setRoutingCheckpoints(checkpoints231);
+
+ ConnRef *connRef232 = new ConnRef(router, 232);
+ ConnEnd srcPt232(Point(286.5, 466), 15);
+ connRef232->setSourceEndpoint(srcPt232);
+ ConnEnd dstPt232(Point(585.5, 487), 4);
+ connRef232->setDestEndpoint(dstPt232);
+ connRef232->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints232(1);
+ checkpoints232[0] = Point(562.5, 466);
+ connRef232->setRoutingCheckpoints(checkpoints232);
+
+ ConnRef *connRef233 = new ConnRef(router, 233);
+ ConnEnd srcPt233(Point(286.5, 638.75), 15);
+ connRef233->setSourceEndpoint(srcPt233);
+ ConnEnd dstPt233(Point(492.5, 659.75), 4);
+ connRef233->setDestEndpoint(dstPt233);
+ connRef233->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints233(1);
+ checkpoints233[0] = Point(469.5, 638.75);
+ connRef233->setRoutingCheckpoints(checkpoints233);
+
+ ConnRef *connRef234 = new ConnRef(router, 234);
+ ConnEnd srcPt234(Point(492.5, 734.75), 4);
+ connRef234->setSourceEndpoint(srcPt234);
+ ConnEnd dstPt234(Point(286.5, 638.75), 15);
+ connRef234->setDestEndpoint(dstPt234);
+ connRef234->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints234(1);
+ checkpoints234[0] = Point(469.5, 638.75);
+ connRef234->setRoutingCheckpoints(checkpoints234);
+
+ ConnRef *connRef235 = new ConnRef(router, 235);
+ ConnEnd srcPt235(Point(522.5, 734.75), 8);
+ connRef235->setSourceEndpoint(srcPt235);
+ ConnEnd dstPt235(Point(844.5, 638.75), 15);
+ connRef235->setDestEndpoint(dstPt235);
+ connRef235->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints235(1);
+ checkpoints235[0] = Point(545.5, 638.75);
+ connRef235->setRoutingCheckpoints(checkpoints235);
+
+ ConnRef *connRef236 = new ConnRef(router, 236);
+ ConnEnd srcPt236(Point(1289.5, 638.75), 15);
+ connRef236->setSourceEndpoint(srcPt236);
+ ConnEnd dstPt236(Point(1310.5, 714.5), 1);
+ connRef236->setDestEndpoint(dstPt236);
+ connRef236->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints236(1);
+ checkpoints236[0] = Point(1289.5, 699.5);
+ connRef236->setRoutingCheckpoints(checkpoints236);
+
+ ConnRef *connRef237 = new ConnRef(router, 237);
+ ConnEnd srcPt237(Point(390.5, 1624.17), 8);
+ connRef237->setSourceEndpoint(srcPt237);
+ ConnEnd dstPt237(Point(1289.5, 1603.17), 15);
+ connRef237->setDestEndpoint(dstPt237);
+ connRef237->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints237(1);
+ checkpoints237[0] = Point(413.5, 1603.17);
+ connRef237->setRoutingCheckpoints(checkpoints237);
+
+ ConnRef *connRef238 = new ConnRef(router, 238);
+ ConnEnd srcPt238(Point(1396.5, 1216.17), 2);
+ connRef238->setSourceEndpoint(srcPt238);
+ ConnEnd dstPt238(Point(1289.5, 1355.17), 15);
+ connRef238->setDestEndpoint(dstPt238);
+ connRef238->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints238(1);
+ checkpoints238[0] = Point(1417.5, 1231.17);
+ connRef238->setRoutingCheckpoints(checkpoints238);
+
+ ConnRef *connRef239 = new ConnRef(router, 239);
+ ConnEnd srcPt239(Point(1438.5, 1216.17), 2);
+ connRef239->setSourceEndpoint(srcPt239);
+ ConnEnd dstPt239(Point(1289.5, 1355.17), 15);
+ connRef239->setDestEndpoint(dstPt239);
+ connRef239->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints239(1);
+ checkpoints239[0] = Point(1417.5, 1231.17);
+ connRef239->setRoutingCheckpoints(checkpoints239);
+
+ ConnRef *connRef240 = new ConnRef(router, 240);
+ ConnEnd srcPt240(Point(1529.5, 1216.17), 2);
+ connRef240->setSourceEndpoint(srcPt240);
+ ConnEnd dstPt240(Point(1289.5, 1355.17), 15);
+ connRef240->setDestEndpoint(dstPt240);
+ connRef240->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints240(1);
+ checkpoints240[0] = Point(1417.5, 1231.17);
+ connRef240->setRoutingCheckpoints(checkpoints240);
+
+ ConnRef *connRef241 = new ConnRef(router, 241);
+ ConnEnd srcPt241(Point(1310.5, 1042.17), 2);
+ connRef241->setSourceEndpoint(srcPt241);
+ ConnEnd dstPt241(Point(1289.5, 1139.17), 15);
+ connRef241->setDestEndpoint(dstPt241);
+ connRef241->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints241(1);
+ checkpoints241[0] = Point(1289.5, 1057.17);
+ connRef241->setRoutingCheckpoints(checkpoints241);
+
+ ConnRef *connRef242 = new ConnRef(router, 242);
+ ConnEnd srcPt242(Point(1223.5, 1139.17), 8);
+ connRef242->setSourceEndpoint(srcPt242);
+ ConnEnd dstPt242(Point(1289.5, 1139.17), 15);
+ connRef242->setDestEndpoint(dstPt242);
+ connRef242->setRoutingType((ConnType)2);
+
+ ConnRef *connRef243 = new ConnRef(router, 243);
+ ConnEnd srcPt243(Point(1254.5, 1983.54), 8);
+ connRef243->setSourceEndpoint(srcPt243);
+ ConnEnd dstPt243(Point(1425.5, 2079.54), 15);
+ connRef243->setDestEndpoint(dstPt243);
+ connRef243->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints243(1);
+ checkpoints243[0] = Point(1277.5, 2079.54);
+ connRef243->setRoutingCheckpoints(checkpoints243);
+
+ ConnRef *connRef244 = new ConnRef(router, 244);
+ ConnEnd srcPt244(Point(1254.5, 2058.54), 8);
+ connRef244->setSourceEndpoint(srcPt244);
+ ConnEnd dstPt244(Point(1425.5, 2079.54), 15);
+ connRef244->setDestEndpoint(dstPt244);
+ connRef244->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints244(1);
+ checkpoints244[0] = Point(1277.5, 2079.54);
+ connRef244->setRoutingCheckpoints(checkpoints244);
+
+ ConnRef *connRef245 = new ConnRef(router, 245);
+ ConnEnd srcPt245(Point(1254.5, 2100.54), 8);
+ connRef245->setSourceEndpoint(srcPt245);
+ ConnEnd dstPt245(Point(1425.5, 2079.54), 15);
+ connRef245->setDestEndpoint(dstPt245);
+ connRef245->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints245(1);
+ checkpoints245[0] = Point(1277.5, 2079.54);
+ connRef245->setRoutingCheckpoints(checkpoints245);
+
+ ConnRef *connRef246 = new ConnRef(router, 246);
+ ConnEnd srcPt246(Point(1254.5, 2175.54), 8);
+ connRef246->setSourceEndpoint(srcPt246);
+ ConnEnd dstPt246(Point(1425.5, 2079.54), 15);
+ connRef246->setDestEndpoint(dstPt246);
+ connRef246->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints246(1);
+ checkpoints246[0] = Point(1277.5, 2079.54);
+ connRef246->setRoutingCheckpoints(checkpoints246);
+
+ ConnRef *connRef247 = new ConnRef(router, 247);
+ ConnEnd srcPt247(Point(677.5, 1740.17), 8);
+ connRef247->setSourceEndpoint(srcPt247);
+ ConnEnd dstPt247(Point(1289.5, 1869.17), 15);
+ connRef247->setDestEndpoint(dstPt247);
+ connRef247->setRoutingType((ConnType)2);
+
+ ConnRef *connRef248 = new ConnRef(router, 248);
+ ConnEnd srcPt248(Point(937.5, 1869.17), 15);
+ connRef248->setSourceEndpoint(srcPt248);
+ ConnEnd dstPt248(Point(937.5, 2002.54), 1);
+ connRef248->setDestEndpoint(dstPt248);
+ connRef248->setRoutingType((ConnType)2);
+
+ ConnRef *connRef249 = new ConnRef(router, 249);
+ ConnEnd srcPt249(Point(647.5, 1740.17), 4);
+ connRef249->setSourceEndpoint(srcPt249);
+ ConnEnd dstPt249(Point(251.5, 1869.17), 15);
+ connRef249->setDestEndpoint(dstPt249);
+ connRef249->setRoutingType((ConnType)2);
+
+ ConnRef *connRef250 = new ConnRef(router, 250);
+ ConnEnd srcPt250(Point(1224.5, 2100.54), 4);
+ connRef250->setSourceEndpoint(srcPt250);
+ ConnEnd dstPt250(Point(937.5, 2079.54), 15);
+ connRef250->setDestEndpoint(dstPt250);
+ connRef250->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints250(1);
+ checkpoints250[0] = Point(1201.5, 2079.54);
+ connRef250->setRoutingCheckpoints(checkpoints250);
+
+ ConnRef *connRef251 = new ConnRef(router, 251);
+ ConnEnd srcPt251(Point(1224.5, 2175.54), 4);
+ connRef251->setSourceEndpoint(srcPt251);
+ ConnEnd dstPt251(Point(937.5, 2079.54), 15);
+ connRef251->setDestEndpoint(dstPt251);
+ connRef251->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints251(1);
+ checkpoints251[0] = Point(1201.5, 2079.54);
+ connRef251->setRoutingCheckpoints(checkpoints251);
+
+ ConnRef *connRef252 = new ConnRef(router, 252);
+ ConnEnd srcPt252(Point(523.5, 2012.21), 4);
+ connRef252->setSourceEndpoint(srcPt252);
+ ConnEnd dstPt252(Point(406.5, 2012.21), 15);
+ connRef252->setDestEndpoint(dstPt252);
+ connRef252->setRoutingType((ConnType)2);
+
+ ConnRef *connRef253 = new ConnRef(router, 253);
+ ConnEnd srcPt253(Point(1289.5, 790.5), 15);
+ connRef253->setSourceEndpoint(srcPt253);
+ ConnEnd dstPt253(Point(1401.5, 744.5), 2);
+ connRef253->setDestEndpoint(dstPt253);
+ connRef253->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints253(1);
+ checkpoints253[0] = Point(1289.5, 759.5);
+ connRef253->setRoutingCheckpoints(checkpoints253);
+
+ ConnRef *connRef254 = new ConnRef(router, 254);
+ ConnEnd srcPt254(Point(216.5, 750.75), 15);
+ connRef254->setSourceEndpoint(srcPt254);
+ ConnEnd dstPt254(Point(271.5, 750.75), 4);
+ connRef254->setDestEndpoint(dstPt254);
+ connRef254->setRoutingType((ConnType)2);
+
+ ConnRef *connRef255 = new ConnRef(router, 255);
+ ConnEnd srcPt255(Point(437.5, 750.75), 15);
+ connRef255->setSourceEndpoint(srcPt255);
+ ConnEnd dstPt255(Point(647.5, 750.75), 4);
+ connRef255->setDestEndpoint(dstPt255);
+ connRef255->setRoutingType((ConnType)2);
+
+ ConnRef *connRef256 = new ConnRef(router, 256);
+ ConnEnd srcPt256(Point(437.5, 852.75), 15);
+ connRef256->setSourceEndpoint(srcPt256);
+ ConnEnd dstPt256(Point(647.5, 852.75), 4);
+ connRef256->setDestEndpoint(dstPt256);
+ connRef256->setRoutingType((ConnType)2);
+
+ ConnRef *connRef257 = new ConnRef(router, 257);
+ ConnEnd srcPt257(Point(216.5, 852.75), 15);
+ connRef257->setSourceEndpoint(srcPt257);
+ ConnEnd dstPt257(Point(271.5, 852.75), 4);
+ connRef257->setDestEndpoint(dstPt257);
+ connRef257->setRoutingType((ConnType)2);
+
+ ConnRef *connRef258 = new ConnRef(router, 258);
+ ConnEnd srcPt258(Point(390.5, 1582.17), 8);
+ connRef258->setSourceEndpoint(srcPt258);
+ ConnEnd dstPt258(Point(1289.5, 1603.17), 15);
+ connRef258->setDestEndpoint(dstPt258);
+ connRef258->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints258(1);
+ checkpoints258[0] = Point(413.5, 1603.17);
+ connRef258->setRoutingCheckpoints(checkpoints258);
+
+ ConnRef *connRef259 = new ConnRef(router, 259);
+ ConnEnd srcPt259(Point(251.5, 1603.17), 15);
+ connRef259->setSourceEndpoint(srcPt259);
+ ConnEnd dstPt259(Point(360.5, 1582.17), 4);
+ connRef259->setDestEndpoint(dstPt259);
+ connRef259->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints259(1);
+ checkpoints259[0] = Point(337.5, 1603.17);
+ connRef259->setRoutingCheckpoints(checkpoints259);
+
+ ConnRef *connRef260 = new ConnRef(router, 260);
+ ConnEnd srcPt260(Point(251.5, 1603.17), 15);
+ connRef260->setSourceEndpoint(srcPt260);
+ ConnEnd dstPt260(Point(360.5, 1624.17), 4);
+ connRef260->setDestEndpoint(dstPt260);
+ connRef260->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints260(1);
+ checkpoints260[0] = Point(337.5, 1603.17);
+ connRef260->setRoutingCheckpoints(checkpoints260);
+
+ ConnRef *connRef261 = new ConnRef(router, 261);
+ ConnEnd srcPt261(Point(1310.5, 1012.17), 1);
+ connRef261->setSourceEndpoint(srcPt261);
+ ConnEnd dstPt261(Point(1289.5, 966.167), 15);
+ connRef261->setDestEndpoint(dstPt261);
+ connRef261->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints261(1);
+ checkpoints261[0] = Point(1289.5, 997.167);
+ connRef261->setRoutingCheckpoints(checkpoints261);
+
+ ConnRef *connRef262 = new ConnRef(router, 262);
+ ConnEnd srcPt262(Point(1193.5, 1343.17), 4);
+ connRef262->setSourceEndpoint(srcPt262);
+ ConnEnd dstPt262(Point(1057.5, 1263.17), 15);
+ connRef262->setDestEndpoint(dstPt262);
+ connRef262->setRoutingType((ConnType)2);
+
+ ConnRef *connRef263 = new ConnRef(router, 263);
+ ConnEnd srcPt263(Point(1223.5, 1343.17), 8);
+ connRef263->setSourceEndpoint(srcPt263);
+ ConnEnd dstPt263(Point(1289.5, 1355.17), 15);
+ connRef263->setDestEndpoint(dstPt263);
+ connRef263->setRoutingType((ConnType)2);
+
+ ConnRef *connRef264 = new ConnRef(router, 264);
+ ConnEnd srcPt264(Point(1193.5, 1139.17), 4);
+ connRef264->setSourceEndpoint(srcPt264);
+ ConnEnd dstPt264(Point(1057.5, 1263.17), 15);
+ connRef264->setDestEndpoint(dstPt264);
+ connRef264->setRoutingType((ConnType)2);
+
+ ConnRef *connRef265 = new ConnRef(router, 265);
+ ConnEnd srcPt265(Point(1289.5, 966.167), 15);
+ connRef265->setSourceEndpoint(srcPt265);
+ ConnEnd dstPt265(Point(1396.5, 1186.17), 1);
+ connRef265->setDestEndpoint(dstPt265);
+ connRef265->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints265(1);
+ checkpoints265[0] = Point(1417.5, 1171.17);
+ connRef265->setRoutingCheckpoints(checkpoints265);
+
+ ConnRef *connRef266 = new ConnRef(router, 266);
+ ConnEnd srcPt266(Point(1289.5, 966.167), 15);
+ connRef266->setSourceEndpoint(srcPt266);
+ ConnEnd dstPt266(Point(1438.5, 1186.17), 1);
+ connRef266->setDestEndpoint(dstPt266);
+ connRef266->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints266(1);
+ checkpoints266[0] = Point(1417.5, 1171.17);
+ connRef266->setRoutingCheckpoints(checkpoints266);
+
+ ConnRef *connRef267 = new ConnRef(router, 267);
+ ConnEnd srcPt267(Point(1289.5, 966.167), 15);
+ connRef267->setSourceEndpoint(srcPt267);
+ ConnEnd dstPt267(Point(1529.5, 1186.17), 1);
+ connRef267->setDestEndpoint(dstPt267);
+ connRef267->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints267(1);
+ checkpoints267[0] = Point(1417.5, 1171.17);
+ connRef267->setRoutingCheckpoints(checkpoints267);
+
+ ConnRef *connRef268 = new ConnRef(router, 268);
+ ConnEnd srcPt268(Point(230.5, 1915.17), 1);
+ connRef268->setSourceEndpoint(srcPt268);
+ ConnEnd dstPt268(Point(251.5, 1869.17), 15);
+ connRef268->setDestEndpoint(dstPt268);
+ connRef268->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints268(1);
+ checkpoints268[0] = Point(251.5, 1900.17);
+ connRef268->setRoutingCheckpoints(checkpoints268);
+
+ ConnRef *connRef269 = new ConnRef(router, 269);
+ ConnEnd srcPt269(Point(1310.5, 744.5), 2);
+ connRef269->setSourceEndpoint(srcPt269);
+ ConnEnd dstPt269(Point(1289.5, 790.5), 15);
+ connRef269->setDestEndpoint(dstPt269);
+ connRef269->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints269(1);
+ checkpoints269[0] = Point(1289.5, 759.5);
+ connRef269->setRoutingCheckpoints(checkpoints269);
+
+ ConnRef *connRef270 = new ConnRef(router, 270);
+ ConnEnd srcPt270(Point(615.5, 487), 8);
+ connRef270->setSourceEndpoint(srcPt270);
+ ConnEnd dstPt270(Point(1289.5, 466), 15);
+ connRef270->setDestEndpoint(dstPt270);
+ connRef270->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints270(1);
+ checkpoints270[0] = Point(638.5, 466);
+ connRef270->setRoutingCheckpoints(checkpoints270);
+
+ ConnRef *connRef271 = new ConnRef(router, 271);
+ ConnEnd srcPt271(Point(937.5, 1765.17), 15);
+ connRef271->setSourceEndpoint(srcPt271);
+ ConnEnd dstPt271(Point(1134.5, 1879.54), 8);
+ connRef271->setDestEndpoint(dstPt271);
+ connRef271->setRoutingType((ConnType)2);
+
+ ConnRef *connRef272 = new ConnRef(router, 272);
+ ConnEnd srcPt272(Point(937.5, 1765.17), 15);
+ connRef272->setSourceEndpoint(srcPt272);
+ ConnEnd dstPt272(Point(1119.5, 1783.17), 1);
+ connRef272->setDestEndpoint(dstPt272);
+ connRef272->setRoutingType((ConnType)2);
+
+ ConnRef *connRef273 = new ConnRef(router, 273);
+ ConnEnd srcPt273(Point(1347.5, 871.5), 4);
+ connRef273->setSourceEndpoint(srcPt273);
+ ConnEnd dstPt273(Point(1289.5, 871.5), 8);
+ connRef273->setDestEndpoint(dstPt273);
+ connRef273->setRoutingType((ConnType)2);
+
+ ConnRef *connRef274 = new ConnRef(router, 274);
+ ConnEnd srcPt274(Point(631.5, 2008.54), 2);
+ connRef274->setSourceEndpoint(srcPt274);
+ ConnEnd dstPt274(Point(631.5, 2058.54), 1);
+ connRef274->setDestEndpoint(dstPt274);
+ connRef274->setRoutingType((ConnType)2);
+
+ ConnRef *connRef275 = new ConnRef(router, 275);
+ ConnEnd srcPt275(Point(330.5, 1930.17), 4);
+ connRef275->setSourceEndpoint(srcPt275);
+ ConnEnd dstPt275(Point(272.5, 1930.17), 8);
+ connRef275->setDestEndpoint(dstPt275);
+ connRef275->setRoutingType((ConnType)2);
+
+ ConnRef *connRef276 = new ConnRef(router, 276);
+ ConnEnd srcPt276(Point(631.5, 2150.54), 1);
+ connRef276->setSourceEndpoint(srcPt276);
+ ConnEnd dstPt276(Point(631.5, 2100.54), 2);
+ connRef276->setDestEndpoint(dstPt276);
+ connRef276->setRoutingType((ConnType)2);
+
+ ConnRef *connRef277 = new ConnRef(router, 277);
+ ConnEnd srcPt277(Point(995.5, 2017.54), 4);
+ connRef277->setSourceEndpoint(srcPt277);
+ ConnEnd dstPt277(Point(937.5, 2017.54), 8);
+ connRef277->setDestEndpoint(dstPt277);
+ connRef277->setRoutingType((ConnType)2);
+
+ ConnRef *connRef278 = new ConnRef(router, 278);
+ ConnEnd srcPt278(Point(1239.5, 1933.54), 2);
+ connRef278->setSourceEndpoint(srcPt278);
+ ConnEnd dstPt278(Point(1239.5, 1983.54), 1);
+ connRef278->setDestEndpoint(dstPt278);
+ connRef278->setRoutingType((ConnType)2);
+
+ ConnRef *connRef279 = new ConnRef(router, 279);
+ ConnEnd srcPt279(Point(1239.5, 2008.54), 2);
+ connRef279->setSourceEndpoint(srcPt279);
+ ConnEnd dstPt279(Point(1239.5, 2058.54), 1);
+ connRef279->setDestEndpoint(dstPt279);
+ connRef279->setRoutingType((ConnType)2);
+
+ ConnRef *connRef280 = new ConnRef(router, 280);
+ ConnEnd srcPt280(Point(1119.5, 1929.54), 1);
+ connRef280->setSourceEndpoint(srcPt280);
+ ConnEnd dstPt280(Point(1119.5, 1879.54), 2);
+ connRef280->setDestEndpoint(dstPt280);
+ connRef280->setRoutingType((ConnType)2);
+
+ ConnRef *connRef281 = new ConnRef(router, 281);
+ ConnEnd srcPt281(Point(1177.5, 1798.17), 4);
+ connRef281->setSourceEndpoint(srcPt281);
+ ConnEnd dstPt281(Point(1119.5, 1798.17), 8);
+ connRef281->setDestEndpoint(dstPt281);
+ connRef281->setRoutingType((ConnType)2);
+
+ ConnRef *connRef282 = new ConnRef(router, 282);
+ ConnEnd srcPt282(Point(813.5, 1819.17), 2);
+ connRef282->setSourceEndpoint(srcPt282);
+ ConnEnd dstPt282(Point(813.5, 1869.17), 1);
+ connRef282->setDestEndpoint(dstPt282);
+ connRef282->setRoutingType((ConnType)2);
+
+ ConnRef *connRef283 = new ConnRef(router, 283);
+ ConnEnd srcPt283(Point(406.5, 1819.17), 2);
+ connRef283->setSourceEndpoint(srcPt283);
+ ConnEnd dstPt283(Point(406.5, 1869.17), 1);
+ connRef283->setDestEndpoint(dstPt283);
+ connRef283->setRoutingType((ConnType)2);
+
+ ConnRef *connRef284 = new ConnRef(router, 284);
+ ConnEnd srcPt284(Point(1456.5, 1819.17), 2);
+ connRef284->setSourceEndpoint(srcPt284);
+ ConnEnd dstPt284(Point(1456.5, 1869.17), 1);
+ connRef284->setDestEndpoint(dstPt284);
+ connRef284->setRoutingType((ConnType)2);
+
+ ConnRef *connRef285 = new ConnRef(router, 285);
+ ConnEnd srcPt285(Point(1347.5, 1665.17), 4);
+ connRef285->setSourceEndpoint(srcPt285);
+ ConnEnd dstPt285(Point(1289.5, 1665.17), 8);
+ connRef285->setDestEndpoint(dstPt285);
+ connRef285->setRoutingType((ConnType)2);
+
+ ConnRef *connRef286 = new ConnRef(router, 286);
+ ConnEnd srcPt286(Point(1347.5, 1541.17), 4);
+ connRef286->setSourceEndpoint(srcPt286);
+ ConnEnd dstPt286(Point(1289.5, 1541.17), 8);
+ connRef286->setDestEndpoint(dstPt286);
+ connRef286->setRoutingType((ConnType)2);
+
+ ConnRef *connRef287 = new ConnRef(router, 287);
+ ConnEnd srcPt287(Point(1347.5, 1417.17), 4);
+ connRef287->setSourceEndpoint(srcPt287);
+ ConnEnd dstPt287(Point(1289.5, 1417.17), 8);
+ connRef287->setDestEndpoint(dstPt287);
+ connRef287->setRoutingType((ConnType)2);
+
+ ConnRef *connRef288 = new ConnRef(router, 288);
+ ConnEnd srcPt288(Point(1210.5, 1027.17), 8);
+ connRef288->setSourceEndpoint(srcPt288);
+ ConnEnd dstPt288(Point(1268.5, 1027.17), 4);
+ connRef288->setDestEndpoint(dstPt288);
+ connRef288->setRoutingType((ConnType)2);
+
+ ConnRef *connRef289 = new ConnRef(router, 289);
+ ConnEnd srcPt289(Point(1088.5, 916.167), 2);
+ connRef289->setSourceEndpoint(srcPt289);
+ ConnEnd dstPt289(Point(1088.5, 966.167), 1);
+ connRef289->setDestEndpoint(dstPt289);
+ connRef289->setRoutingType((ConnType)2);
+
+ ConnRef *connRef290 = new ConnRef(router, 290);
+ ConnEnd srcPt290(Point(1210.5, 729.5), 8);
+ connRef290->setSourceEndpoint(srcPt290);
+ ConnEnd dstPt290(Point(1268.5, 729.5), 4);
+ connRef290->setDestEndpoint(dstPt290);
+ connRef290->setRoutingType((ConnType)2);
+
+ ConnRef *connRef291 = new ConnRef(router, 291);
+ ConnEnd srcPt291(Point(1459.5, 729.5), 4);
+ connRef291->setSourceEndpoint(srcPt291);
+ ConnEnd dstPt291(Point(1401.5, 729.5), 8);
+ connRef291->setDestEndpoint(dstPt291);
+ connRef291->setRoutingType((ConnType)2);
+
+ ConnRef *connRef292 = new ConnRef(router, 292);
+ ConnEnd srcPt292(Point(1425.5, 382.5), 2);
+ connRef292->setSourceEndpoint(srcPt292);
+ ConnEnd dstPt292(Point(1425.5, 432.5), 1);
+ connRef292->setDestEndpoint(dstPt292);
+ connRef292->setRoutingType((ConnType)2);
+
+ ConnRef *connRef293 = new ConnRef(router, 293);
+ ConnEnd srcPt293(Point(1347.5, 551.25), 4);
+ connRef293->setSourceEndpoint(srcPt293);
+ ConnEnd dstPt293(Point(1289.5, 551.25), 8);
+ connRef293->setDestEndpoint(dstPt293);
+ connRef293->setRoutingType((ConnType)2);
+
+ ConnRef *connRef294 = new ConnRef(router, 294);
+ ConnEnd srcPt294(Point(1347.5, 360), 4);
+ connRef294->setSourceEndpoint(srcPt294);
+ ConnEnd dstPt294(Point(1289.5, 360), 8);
+ connRef294->setDestEndpoint(dstPt294);
+ connRef294->setRoutingType((ConnType)2);
+
+ ConnRef *connRef295 = new ConnRef(router, 295);
+ ConnEnd srcPt295(Point(1026.5, 588.75), 2);
+ connRef295->setSourceEndpoint(srcPt295);
+ ConnEnd dstPt295(Point(1026.5, 638.75), 1);
+ connRef295->setDestEndpoint(dstPt295);
+ connRef295->setRoutingType((ConnType)2);
+
+ ConnRef *connRef296 = new ConnRef(router, 296);
+ ConnEnd srcPt296(Point(507.5, 492.75), 2);
+ connRef296->setSourceEndpoint(srcPt296);
+ ConnEnd dstPt296(Point(507.5, 542.75), 1);
+ connRef296->setDestEndpoint(dstPt296);
+ connRef296->setRoutingType((ConnType)2);
+
+ ConnRef *connRef297 = new ConnRef(router, 297);
+ ConnEnd srcPt297(Point(507.5, 567.75), 2);
+ connRef297->setSourceEndpoint(srcPt297);
+ ConnEnd dstPt297(Point(507.5, 617.75), 1);
+ connRef297->setDestEndpoint(dstPt297);
+ connRef297->setRoutingType((ConnType)2);
+
+ ConnRef *connRef298 = new ConnRef(router, 298);
+ ConnEnd srcPt298(Point(906.5, 501.25), 2);
+ connRef298->setSourceEndpoint(srcPt298);
+ ConnEnd dstPt298(Point(906.5, 551.25), 1);
+ connRef298->setDestEndpoint(dstPt298);
+ connRef298->setRoutingType((ConnType)2);
+
+ ConnRef *connRef299 = new ConnRef(router, 299);
+ ConnEnd srcPt299(Point(693.5, 551.25), 8);
+ connRef299->setSourceEndpoint(srcPt299);
+ ConnEnd dstPt299(Point(751.5, 551.25), 4);
+ connRef299->setDestEndpoint(dstPt299);
+ connRef299->setRoutingType((ConnType)2);
+
+ ConnRef *connRef300 = new ConnRef(router, 300);
+ ConnEnd srcPt300(Point(344.5, 551.25), 4);
+ connRef300->setSourceEndpoint(srcPt300);
+ ConnEnd dstPt300(Point(286.5, 551.25), 8);
+ connRef300->setDestEndpoint(dstPt300);
+ connRef300->setRoutingType((ConnType)2);
+
+ ConnRef *connRef301 = new ConnRef(router, 301);
+ ConnEnd srcPt301(Point(600.5, 245), 2);
+ connRef301->setSourceEndpoint(srcPt301);
+ ConnEnd dstPt301(Point(600.5, 295), 1);
+ connRef301->setDestEndpoint(dstPt301);
+ connRef301->setRoutingType((ConnType)2);
+
+ ConnRef *connRef302 = new ConnRef(router, 302);
+ ConnEnd srcPt302(Point(600.5, 320), 2);
+ connRef302->setSourceEndpoint(srcPt302);
+ ConnEnd dstPt302(Point(600.5, 370), 1);
+ connRef302->setDestEndpoint(dstPt302);
+ connRef302->setRoutingType((ConnType)2);
+
+ ConnRef *connRef303 = new ConnRef(router, 303);
+ ConnEnd srcPt303(Point(600.5, 612), 1);
+ connRef303->setSourceEndpoint(srcPt303);
+ ConnEnd dstPt303(Point(600.5, 562), 2);
+ connRef303->setDestEndpoint(dstPt303);
+ connRef303->setRoutingType((ConnType)2);
+
+ ConnRef *connRef304 = new ConnRef(router, 304);
+ ConnEnd srcPt304(Point(875.5, 291), 2);
+ connRef304->setSourceEndpoint(srcPt304);
+ ConnEnd dstPt304(Point(875.5, 341), 1);
+ connRef304->setDestEndpoint(dstPt304);
+ connRef304->setRoutingType((ConnType)2);
+
+ ConnRef *connRef305 = new ConnRef(router, 305);
+ ConnEnd srcPt305(Point(875.5, 189), 2);
+ connRef305->setSourceEndpoint(srcPt305);
+ ConnEnd dstPt305(Point(875.5, 239), 1);
+ connRef305->setDestEndpoint(dstPt305);
+ connRef305->setRoutingType((ConnType)2);
+
+ ConnRef *connRef306 = new ConnRef(router, 306);
+ ConnEnd srcPt306(Point(538.5, 1962.21), 2);
+ connRef306->setSourceEndpoint(srcPt306);
+ ConnEnd dstPt306(Point(538.5, 2012.21), 1);
+ connRef306->setDestEndpoint(dstPt306);
+ connRef306->setRoutingType((ConnType)2);
+
+ ConnRef *connRef307 = new ConnRef(router, 307);
+ ConnEnd srcPt307(Point(1347.5, 1263.17), 4);
+ connRef307->setSourceEndpoint(srcPt307);
+ ConnEnd dstPt307(Point(1289.5, 1263.17), 8);
+ connRef307->setDestEndpoint(dstPt307);
+ connRef307->setRoutingType((ConnType)2);
+
+ ConnRef *connRef308 = new ConnRef(router, 308);
+ ConnEnd srcPt308(Point(600.5, 395), 2);
+ connRef308->setSourceEndpoint(srcPt308);
+ ConnEnd dstPt308(Point(600.5, 445), 1);
+ connRef308->setDestEndpoint(dstPt308);
+ connRef308->setRoutingType((ConnType)2);
+
+ ConnRef *connRef309 = new ConnRef(router, 309);
+ ConnEnd srcPt309(Point(507.5, 709.75), 1);
+ connRef309->setSourceEndpoint(srcPt309);
+ ConnEnd dstPt309(Point(507.5, 659.75), 2);
+ connRef309->setDestEndpoint(dstPt309);
+ connRef309->setRoutingType((ConnType)2);
+
+ ConnRef *connRef310 = new ConnRef(router, 310);
+ ConnEnd srcPt310(Point(286.5, 700.75), 2);
+ connRef310->setSourceEndpoint(srcPt310);
+ ConnEnd dstPt310(Point(286.5, 750.75), 1);
+ connRef310->setDestEndpoint(dstPt310);
+ connRef310->setRoutingType((ConnType)2);
+
+ ConnRef *connRef311 = new ConnRef(router, 311);
+ ConnEnd srcPt311(Point(286.5, 802.75), 2);
+ connRef311->setSourceEndpoint(srcPt311);
+ ConnEnd dstPt311(Point(286.5, 852.75), 1);
+ connRef311->setDestEndpoint(dstPt311);
+ connRef311->setRoutingType((ConnType)2);
+
+ ConnRef *connRef312 = new ConnRef(router, 312);
+ ConnEnd srcPt312(Point(662.5, 700.75), 2);
+ connRef312->setSourceEndpoint(srcPt312);
+ ConnEnd dstPt312(Point(662.5, 750.75), 1);
+ connRef312->setDestEndpoint(dstPt312);
+ connRef312->setRoutingType((ConnType)2);
+
+ ConnRef *connRef313 = new ConnRef(router, 313);
+ ConnEnd srcPt313(Point(662.5, 802.75), 2);
+ connRef313->setSourceEndpoint(srcPt313);
+ ConnEnd dstPt313(Point(662.5, 852.75), 1);
+ connRef313->setDestEndpoint(dstPt313);
+ connRef313->setRoutingType((ConnType)2);
+
+ ConnRef *connRef314 = new ConnRef(router, 314);
+ ConnEnd srcPt314(Point(375.5, 1532.17), 2);
+ connRef314->setSourceEndpoint(srcPt314);
+ ConnEnd dstPt314(Point(375.5, 1582.17), 1);
+ connRef314->setDestEndpoint(dstPt314);
+ connRef314->setRoutingType((ConnType)2);
+
+ ConnRef *connRef315 = new ConnRef(router, 315);
+ ConnEnd srcPt315(Point(1239.5, 2150.54), 1);
+ connRef315->setSourceEndpoint(srcPt315);
+ ConnEnd dstPt315(Point(1239.5, 2100.54), 2);
+ connRef315->setDestEndpoint(dstPt315);
+ connRef315->setRoutingType((ConnType)2);
+
+ ConnRef *connRef316 = new ConnRef(router, 316);
+ ConnEnd srcPt316(Point(375.5, 1674.17), 1);
+ connRef316->setSourceEndpoint(srcPt316);
+ ConnEnd dstPt316(Point(375.5, 1624.17), 2);
+ connRef316->setDestEndpoint(dstPt316);
+ connRef316->setRoutingType((ConnType)2);
+
+ ConnRef *connRef317 = new ConnRef(router, 317);
+ ConnEnd srcPt317(Point(1368.5, 1027.17), 4);
+ connRef317->setSourceEndpoint(srcPt317);
+ ConnEnd dstPt317(Point(1310.5, 1027.17), 8);
+ connRef317->setDestEndpoint(dstPt317);
+ connRef317->setRoutingType((ConnType)2);
+
+ ConnRef *connRef318 = new ConnRef(router, 318);
+ ConnEnd srcPt318(Point(1338.5, 1201.17), 8);
+ connRef318->setSourceEndpoint(srcPt318);
+ ConnEnd dstPt318(Point(1396.5, 1201.17), 4);
+ connRef318->setDestEndpoint(dstPt318);
+ connRef318->setRoutingType((ConnType)2);
+
+ ConnRef *connRef319 = new ConnRef(router, 319);
+ ConnEnd srcPt319(Point(1496.5, 1201.17), 4);
+ connRef319->setSourceEndpoint(srcPt319);
+ ConnEnd dstPt319(Point(1438.5, 1201.17), 8);
+ connRef319->setDestEndpoint(dstPt319);
+ connRef319->setRoutingType((ConnType)2);
+
+ ConnRef *connRef320 = new ConnRef(router, 320);
+ ConnEnd srcPt320(Point(662.5, 1690.17), 2);
+ connRef320->setSourceEndpoint(srcPt320);
+ ConnEnd dstPt320(Point(662.5, 1740.17), 1);
+ connRef320->setDestEndpoint(dstPt320);
+ connRef320->setRoutingType((ConnType)2);
+
+ ConnRef *connRef321 = new ConnRef(router, 321);
+ ConnEnd srcPt321(Point(1587.5, 1201.17), 4);
+ connRef321->setSourceEndpoint(srcPt321);
+ ConnEnd dstPt321(Point(1529.5, 1201.17), 8);
+ connRef321->setDestEndpoint(dstPt321);
+ connRef321->setRoutingType((ConnType)2);
+
+ ConnRef *connRef322 = new ConnRef(router, 322);
+ ConnEnd srcPt322(Point(1208.5, 1293.17), 2);
+ connRef322->setSourceEndpoint(srcPt322);
+ ConnEnd dstPt322(Point(1208.5, 1343.17), 1);
+ connRef322->setDestEndpoint(dstPt322);
+ connRef322->setRoutingType((ConnType)2);
+
+ ConnRef *connRef323 = new ConnRef(router, 323);
+ ConnEnd srcPt323(Point(1208.5, 1089.17), 2);
+ connRef323->setSourceEndpoint(srcPt323);
+ ConnEnd dstPt323(Point(1208.5, 1139.17), 1);
+ connRef323->setDestEndpoint(dstPt323);
+ connRef323->setRoutingType((ConnType)2);
+
+ ConnRef *connRef324 = new ConnRef(router, 324);
+ ConnEnd srcPt324(Point(172.5, 1930.17), 8);
+ connRef324->setSourceEndpoint(srcPt324);
+ ConnEnd dstPt324(Point(230.5, 1930.17), 4);
+ connRef324->setDestEndpoint(dstPt324);
+ connRef324->setRoutingType((ConnType)2);
+
+ ConnRef *connRef325 = new ConnRef(router, 325);
+ ConnEnd srcPt325(Point(1368.5, 729.5), 4);
+ connRef325->setSourceEndpoint(srcPt325);
+ ConnEnd dstPt325(Point(1310.5, 729.5), 8);
+ connRef325->setDestEndpoint(dstPt325);
+ connRef325->setRoutingType((ConnType)2);
+
+ ConnRef *connRef326 = new ConnRef(router, 326);
+ ConnEnd srcPt326(Point(600.5, 537), 1);
+ connRef326->setSourceEndpoint(srcPt326);
+ ConnEnd dstPt326(Point(600.5, 487), 2);
+ connRef326->setDestEndpoint(dstPt326);
+ connRef326->setRoutingType((ConnType)2);
+
+ ConnRef *connRef327 = new ConnRef(router, 327);
+ ConnEnd srcPt327(Point(507.5, 784.75), 1);
+ connRef327->setSourceEndpoint(srcPt327);
+ ConnEnd dstPt327(Point(507.5, 734.75), 2);
+ connRef327->setDestEndpoint(dstPt327);
+ connRef327->setRoutingType((ConnType)2);
+
+ ConnRef *connRef328 = new ConnRef(router, 328);
+ ConnEnd srcPt328(Point(1239.5, 2225.54), 1);
+ connRef328->setSourceEndpoint(srcPt328);
+ ConnEnd dstPt328(Point(1239.5, 2175.54), 2);
+ connRef328->setDestEndpoint(dstPt328);
+ connRef328->setRoutingType((ConnType)2);
+
+ ConnRef *connRef329 = new ConnRef(router, 329);
+ ConnEnd srcPt329(Point(251.5, 1869.17), 15);
+ connRef329->setSourceEndpoint(srcPt329);
+ ConnEnd dstPt329(Point(272.5, 1915.17), 1);
+ connRef329->setDestEndpoint(dstPt329);
+ connRef329->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints329(1);
+ checkpoints329[0] = Point(251.5, 1900.17);
+ connRef329->setRoutingCheckpoints(checkpoints329);
+
+ ConnRef *connRef330 = new ConnRef(router, 330);
+ ConnEnd srcPt330(Point(1289.5, 1869.17), 15);
+ connRef330->setSourceEndpoint(srcPt330);
+ ConnEnd dstPt330(Point(1134.5, 1879.54), 8);
+ connRef330->setDestEndpoint(dstPt330);
+ connRef330->setRoutingType((ConnType)2);
+
+ ConnRef *connRef331 = new ConnRef(router, 331);
+ ConnEnd srcPt331(Point(1289.5, 1869.17), 15);
+ connRef331->setSourceEndpoint(srcPt331);
+ ConnEnd dstPt331(Point(1119.5, 1783.17), 1);
+ connRef331->setDestEndpoint(dstPt331);
+ connRef331->setRoutingType((ConnType)2);
+
+ ConnRef *connRef332 = new ConnRef(router, 332);
+ ConnEnd srcPt332(Point(782.5, 2012.21), 15);
+ connRef332->setSourceEndpoint(srcPt332);
+ ConnEnd dstPt332(Point(828.5, 1869.17), 8);
+ connRef332->setDestEndpoint(dstPt332);
+ connRef332->setRoutingType((ConnType)2);
+
+ ConnRef *connRef333 = new ConnRef(router, 333);
+ ConnEnd srcPt333(Point(937.5, 1869.17), 15);
+ connRef333->setSourceEndpoint(srcPt333);
+ ConnEnd dstPt333(Point(828.5, 1869.17), 8);
+ connRef333->setDestEndpoint(dstPt333);
+ connRef333->setRoutingType((ConnType)2);
+
+ ConnRef *connRef334 = new ConnRef(router, 334);
+ ConnEnd srcPt334(Point(1289.5, 1603.17), 15);
+ connRef334->setSourceEndpoint(srcPt334);
+ ConnEnd dstPt334(Point(1289.5, 1650.17), 1);
+ connRef334->setDestEndpoint(dstPt334);
+ connRef334->setRoutingType((ConnType)2);
+
+ ConnRef *connRef335 = new ConnRef(router, 335);
+ ConnEnd srcPt335(Point(1289.5, 638.75), 15);
+ connRef335->setSourceEndpoint(srcPt335);
+ ConnEnd dstPt335(Point(1268.5, 714.5), 1);
+ connRef335->setDestEndpoint(dstPt335);
+ connRef335->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints335(1);
+ checkpoints335[0] = Point(1289.5, 699.5);
+ connRef335->setRoutingCheckpoints(checkpoints335);
+
+ ConnRef *connRef336 = new ConnRef(router, 336);
+ ConnEnd srcPt336(Point(286.5, 638.75), 15);
+ connRef336->setSourceEndpoint(srcPt336);
+ ConnEnd dstPt336(Point(492.5, 542.75), 4);
+ connRef336->setDestEndpoint(dstPt336);
+ connRef336->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints336(1);
+ checkpoints336[0] = Point(469.5, 638.75);
+ connRef336->setRoutingCheckpoints(checkpoints336);
+
+ ConnRef *connRef337 = new ConnRef(router, 337);
+ ConnEnd srcPt337(Point(286.5, 638.75), 15);
+ connRef337->setSourceEndpoint(srcPt337);
+ ConnEnd dstPt337(Point(492.5, 617.75), 4);
+ connRef337->setDestEndpoint(dstPt337);
+ connRef337->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints337(1);
+ checkpoints337[0] = Point(469.5, 638.75);
+ connRef337->setRoutingCheckpoints(checkpoints337);
+
+ ConnRef *connRef338 = new ConnRef(router, 338);
+ ConnEnd srcPt338(Point(286.5, 466), 15);
+ connRef338->setSourceEndpoint(srcPt338);
+ ConnEnd dstPt338(Point(585.5, 295), 4);
+ connRef338->setDestEndpoint(dstPt338);
+ connRef338->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints338(1);
+ checkpoints338[0] = Point(562.5, 466);
+ connRef338->setRoutingCheckpoints(checkpoints338);
+
+ ConnRef *connRef339 = new ConnRef(router, 339);
+ ConnEnd srcPt339(Point(286.5, 466), 15);
+ connRef339->setSourceEndpoint(srcPt339);
+ ConnEnd dstPt339(Point(585.5, 370), 4);
+ connRef339->setDestEndpoint(dstPt339);
+ connRef339->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints339(1);
+ checkpoints339[0] = Point(562.5, 466);
+ connRef339->setRoutingCheckpoints(checkpoints339);
+
+ ConnRef *connRef340 = new ConnRef(router, 340);
+ ConnEnd srcPt340(Point(1289.5, 466), 15);
+ connRef340->setSourceEndpoint(srcPt340);
+ ConnEnd dstPt340(Point(615.5, 562), 8);
+ connRef340->setDestEndpoint(dstPt340);
+ connRef340->setRoutingType((ConnType)2);
+ std::vector<Point> checkpoints340(1);
+ checkpoints340[0] = Point(638.5, 466);
+ connRef340->setRoutingCheckpoints(checkpoints340);
+
+ ConnRef *connRef341 = new ConnRef(router, 341);
+ ConnEnd srcPt341(Point(1289.5, 280), 15);
+ connRef341->setSourceEndpoint(srcPt341);
+ ConnEnd dstPt341(Point(890.5, 341), 8);
+ connRef341->setDestEndpoint(dstPt341);
+ connRef341->setRoutingType((ConnType)2);
+
+ ConnRef *connRef342 = new ConnRef(router, 342);
+ ConnEnd srcPt342(Point(1289.5, 280), 15);
+ connRef342->setSourceEndpoint(srcPt342);
+ ConnEnd dstPt342(Point(890.5, 239), 8);
+ connRef342->setDestEndpoint(dstPt342);
+ connRef342->setRoutingType((ConnType)2);
+
+ ConnRef *connRef343 = new ConnRef(router, 343);
+ ConnEnd srcPt343(Point(1289.5, 466), 15);
+ connRef343->setSourceEndpoint(srcPt343);
+ ConnEnd dstPt343(Point(1515, 661), 4);
+ connRef343->setDestEndpoint(dstPt343);
+ connRef343->setRoutingType((ConnType)2);
+
+ ConnRef *connRef344 = new ConnRef(router, 344);
+ ConnEnd srcPt344(Point(1289.5, 966.167), 15);
+ connRef344->setSourceEndpoint(srcPt344);
+ ConnEnd dstPt344(Point(1515, 701), 4);
+ connRef344->setDestEndpoint(dstPt344);
+ connRef344->setRoutingType((ConnType)2);
+
+ ConnRef *connRef345 = new ConnRef(router, 345);
+ ConnEnd srcPt345(Point(1289.5, 1479.17), 15);
+ connRef345->setSourceEndpoint(srcPt345);
+ ConnEnd dstPt345(Point(1601, 864.5), 2);
+ connRef345->setDestEndpoint(dstPt345);
+ connRef345->setRoutingType((ConnType)2);
+
+ ConnRef *connRef346 = new ConnRef(router, 346);
+ ConnEnd srcPt346(Point(1289.5, 1869.17), 15);
+ connRef346->setSourceEndpoint(srcPt346);
+ ConnEnd dstPt346(Point(1641, 864.5), 2);
+ connRef346->setDestEndpoint(dstPt346);
+ connRef346->setRoutingType((ConnType)2);
+
+ ConnRef *connRef347 = new ConnRef(router, 347);
+ ConnEnd srcPt347(Point(1289.5, 280), 15);
+ connRef347->setSourceEndpoint(srcPt347);
+ ConnEnd dstPt347(Point(1350, 214.5), 2);
+ connRef347->setDestEndpoint(dstPt347);
+ connRef347->setRoutingType((ConnType)2);
+
+ ConnRef *connRef348 = new ConnRef(router, 348);
+ ConnEnd srcPt348(Point(251.5, 1603.17), 15);
+ connRef348->setSourceEndpoint(srcPt348);
+ ConnEnd dstPt348(Point(247.5, 1725.67), 8);
+ connRef348->setDestEndpoint(dstPt348);
+ connRef348->setRoutingType((ConnType)2);
+
+ ConnRef *connRef349 = new ConnRef(router, 349);
+ ConnEnd srcPt349(Point(251.5, 1869.17), 15);
+ connRef349->setSourceEndpoint(srcPt349);
+ ConnEnd dstPt349(Point(247.5, 1765.67), 8);
+ connRef349->setDestEndpoint(dstPt349);
+ connRef349->setRoutingType((ConnType)2);
+
+ ConnRef *connRef350 = new ConnRef(router, 350);
+ ConnEnd srcPt350(Point(1289.5, 1355.17), 15);
+ connRef350->setSourceEndpoint(srcPt350);
+ ConnEnd dstPt350(Point(844.5, 1362.67), 8);
+ connRef350->setDestEndpoint(dstPt350);
+ connRef350->setRoutingType((ConnType)2);
+
+ ConnRef *connRef351 = new ConnRef(router, 351);
+ ConnEnd srcPt351(Point(1530.5, 1869.17), 15);
+ connRef351->setSourceEndpoint(srcPt351);
+ ConnEnd dstPt351(Point(1536.5, 1948.54), 1);
+ connRef351->setDestEndpoint(dstPt351);
+ connRef351->setRoutingType((ConnType)2);
+#endif
+
+ router->processTransaction();
+ router->outputDiagram("output/nudgeCrossing01");
+
+ bool optimisedForConnectorType = false;
+ int crossings = router->existsCrossings(optimisedForConnectorType);
+
+ delete router;
+ return crossings;
+};
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/nudgeintobug.cpp b/src/3rdparty/adaptagrams/libavoid/tests/nudgeintobug.cpp
new file mode 100644
index 0000000..cf7f4e9
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/nudgeintobug.cpp
@@ -0,0 +1,40 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingPenalty((Avoid::PenaltyType)0, 50);
+ router->setRoutingPenalty((Avoid::PenaltyType)1, 0);
+ router->setRoutingPenalty((Avoid::PenaltyType)2, 200);
+ router->setRoutingPenalty((Avoid::PenaltyType)3, 4000);
+ router->setRoutingPenalty((Avoid::PenaltyType)4, 110);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+ Rectangle rect548374163(Point(51900, 50400), Point(52300, 50900));
+ new ShapeRef(router, rect548374163, 548374163);
+ Rectangle rect901116812(Point(51131, 49750), Point(51531, 50100));
+ new ShapeRef(router, rect901116812, 901116812);
+ Rectangle rect335855988(Point(51125, 50175), Point(51525, 50900));
+ new ShapeRef(router, rect335855988, 335855988);
+ Rectangle rect448725420(Point(52375, 50750), Point(52575, 50900));
+ new ShapeRef(router, rect448725420, 448725420);
+ Rectangle rect74263573(Point(51900, 49750), Point(52300, 50100));
+ new ShapeRef(router, rect74263573, 74263573);
+ ConnEnd srcPt463223880(Point(51500, 50275), 8);
+ ConnEnd dstPt463223880(Point(51150, 50275), 4);
+ ConnEnd srcPt144520410(Point(51150, 49850), 4);
+ ConnEnd dstPt144520410(Point(51500, 50350), 8);
+ ConnEnd srcPt45398340(Point(52400, 50825), 4);
+ ConnEnd dstPt45398340(Point(51500, 49925), 8);
+ ConnEnd srcPt29344262(Point(51150, 50500), 4);
+ ConnEnd dstPt29344262(Point(51925, 50000), 4);
+ new ConnRef(router, srcPt29344262, dstPt29344262, 29344262);
+ new ConnRef(router, srcPt45398340, dstPt45398340, 45398340);
+ new ConnRef(router, srcPt144520410, dstPt144520410, 144520410);
+ new ConnRef(router, srcPt463223880, dstPt463223880, 463223880);
+ router->processTransaction();
+ router->outputDiagram("output/nudgeintobug");
+ bool overlap = router->existsOrthogonalFixedSegmentOverlap();
+ bool touching = router->existsOrthogonalTouchingPaths();
+ delete router;
+ return (overlap || touching) ? 1 : 0;
+};
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/nudgeold.cpp b/src/3rdparty/adaptagrams/libavoid/tests/nudgeold.cpp
new file mode 100644
index 0000000..96bf237
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/nudgeold.cpp
@@ -0,0 +1,80 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 110);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+ Polygon poly426345871(4);
+ poly426345871.ps[0] = Point(7200, 5240);
+ poly426345871.ps[1] = Point(7200, 5660);
+ poly426345871.ps[2] = Point(6690, 5660);
+ poly426345871.ps[3] = Point(6690, 5240);
+ new ShapeRef(router, poly426345871, 426345871);
+
+ Polygon poly596896212(4);
+ poly596896212.ps[0] = Point(7200, 5740);
+ poly596896212.ps[1] = Point(7200, 6160);
+ poly596896212.ps[2] = Point(6690, 6160);
+ poly596896212.ps[3] = Point(6690, 5740);
+ new ShapeRef(router, poly596896212, 596896212);
+
+ ConnRef *connRef20026701 = new ConnRef(router, 20026701);
+ ConnEnd srcPt20026701(Point(7190, 5600), 8);
+ connRef20026701->setSourceEndpoint(srcPt20026701);
+ ConnEnd dstPt20026701(Point(7190, 5800), 8);
+ connRef20026701->setDestEndpoint(dstPt20026701);
+ connRef20026701->setRoutingType((ConnType)2);
+
+ ConnRef *connRef124776000 = new ConnRef(router, 124776000);
+ ConnEnd srcPt124776000(Point(7190, 5550), 8);
+ connRef124776000->setSourceEndpoint(srcPt124776000);
+ ConnEnd dstPt124776000(Point(7190, 5850), 8);
+ connRef124776000->setDestEndpoint(dstPt124776000);
+ connRef124776000->setRoutingType((ConnType)2);
+
+ ConnRef *connRef162425002 = new ConnRef(router, 162425002);
+ ConnEnd srcPt162425002(Point(7190, 5500), 8);
+ connRef162425002->setSourceEndpoint(srcPt162425002);
+ ConnEnd dstPt162425002(Point(7190, 5900), 8);
+ connRef162425002->setDestEndpoint(dstPt162425002);
+ connRef162425002->setRoutingType((ConnType)2);
+
+ ConnRef *connRef445102866 = new ConnRef(router, 445102866);
+ ConnEnd srcPt445102866(Point(7190, 5450), 8);
+ connRef445102866->setSourceEndpoint(srcPt445102866);
+ ConnEnd dstPt445102866(Point(7190, 5950), 8);
+ connRef445102866->setDestEndpoint(dstPt445102866);
+ connRef445102866->setRoutingType((ConnType)2);
+
+ ConnRef *connRef472520508 = new ConnRef(router, 472520508);
+ ConnEnd srcPt472520508(Point(7190, 5400), 8);
+ connRef472520508->setSourceEndpoint(srcPt472520508);
+ ConnEnd dstPt472520508(Point(7190, 6000), 8);
+ connRef472520508->setDestEndpoint(dstPt472520508);
+ connRef472520508->setRoutingType((ConnType)2);
+
+ ConnRef *connRef406587600 = new ConnRef(router, 406587600);
+ ConnEnd srcPt406587600(Point(7190, 5350), 8);
+ connRef406587600->setSourceEndpoint(srcPt406587600);
+ ConnEnd dstPt406587600(Point(7190, 6050), 8);
+ connRef406587600->setDestEndpoint(dstPt406587600);
+ connRef406587600->setRoutingType((ConnType)2);
+
+ ConnRef *connRef41657796 = new ConnRef(router, 41657796);
+ ConnEnd srcPt41657796(Point(7190, 5300), 8);
+ connRef41657796->setSourceEndpoint(srcPt41657796);
+ ConnEnd dstPt41657796(Point(7190, 6100), 8);
+ connRef41657796->setDestEndpoint(dstPt41657796);
+ connRef41657796->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/nudgeold");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/nudgingSkipsCheckpoint01.cpp b/src/3rdparty/adaptagrams/libavoid/tests/nudgingSkipsCheckpoint01.cpp
new file mode 100644
index 0000000..27c9d50
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/nudgingSkipsCheckpoint01.cpp
@@ -0,0 +1,1507 @@
+// Regression test to catch problem where orthogonal segments from the same
+// connector were being merged with others going through checkpoints and
+// being simplified so as not to pass the checkpoint anymore.
+// Based on ec00232.
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingParameter((RoutingParameter)0, 50);
+ router->setRoutingParameter((RoutingParameter)1, 0);
+ router->setRoutingParameter((RoutingParameter)2, 0);
+ router->setRoutingParameter((RoutingParameter)3, 4000);
+ router->setRoutingParameter((RoutingParameter)4, 0);
+ router->setRoutingParameter((RoutingParameter)5, 100);
+ router->setRoutingParameter((RoutingParameter)6, 0);
+ router->setRoutingParameter((RoutingParameter)7, 4);
+ router->setRoutingOption((RoutingOption)0, true);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, false);
+ router->setRoutingOption((RoutingOption)3, false);
+ Polygon polygon;
+ ConnRef *connRef = nullptr;
+ ConnEnd srcPt;
+ ConnEnd dstPt;
+#if ALL
+ // shapeRef1
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(-80.18071812011561, 825.315092940984);
+ polygon.ps[1] = Point(-80.18071812011561, 887.315092940984);
+ polygon.ps[2] = Point(-142.1807181201156, 887.315092940984);
+ polygon.ps[3] = Point(-142.1807181201156, 825.315092940984);
+ new ShapeRef(router, polygon, 1);
+#endif
+
+ // shapeRef2
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(620.1049961655988, -86.0182403953493);
+ polygon.ps[1] = Point(620.1049961655988, -24.0182403953493);
+ polygon.ps[2] = Point(558.1049961655988, -24.0182403953493);
+ polygon.ps[3] = Point(558.1049961655988, -86.0182403953493);
+ new ShapeRef(router, polygon, 2);
+
+#if ALL
+ // shapeRef3
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1044.504996167599, 719.315092940984);
+ polygon.ps[1] = Point(1044.504996167599, 781.315092940984);
+ polygon.ps[2] = Point(982.5049961675986, 781.315092940984);
+ polygon.ps[3] = Point(982.5049961675986, 719.315092940984);
+ new ShapeRef(router, polygon, 3);
+
+ // shapeRef4
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1153.104996167599, 759.315092940984);
+ polygon.ps[1] = Point(1153.104996167599, 821.315092940984);
+ polygon.ps[2] = Point(1091.104996167599, 821.315092940984);
+ polygon.ps[3] = Point(1091.104996167599, 759.315092940984);
+ new ShapeRef(router, polygon, 4);
+
+ // shapeRef5
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1044.504996167599, 495.9817596066507);
+ polygon.ps[1] = Point(1044.504996167599, 557.9817596066507);
+ polygon.ps[2] = Point(982.5049961675986, 557.9817596066507);
+ polygon.ps[3] = Point(982.5049961675986, 495.9817596066507);
+ new ShapeRef(router, polygon, 5);
+
+ // shapeRef6
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(968.1049961675988, 759.315092940984);
+ polygon.ps[1] = Point(968.1049961675988, 821.315092940984);
+ polygon.ps[2] = Point(906.1049961675988, 821.315092940984);
+ polygon.ps[3] = Point(906.1049961675988, 759.315092940984);
+ new ShapeRef(router, polygon, 6);
+
+ // shapeRef7
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1044.504996167599, 792.315092940984);
+ polygon.ps[1] = Point(1044.504996167599, 854.315092940984);
+ polygon.ps[2] = Point(982.5049961675986, 854.315092940984);
+ polygon.ps[3] = Point(982.5049961675986, 792.315092940984);
+ new ShapeRef(router, polygon, 7);
+
+ // shapeRef8
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(349.8192818798844, 1008.815092941984);
+ polygon.ps[1] = Point(349.8192818798844, 1070.815092941984);
+ polygon.ps[2] = Point(287.8192818798844, 1070.815092941984);
+ polygon.ps[3] = Point(287.8192818798844, 1008.815092941984);
+ new ShapeRef(router, polygon, 8);
+
+ // shapeRef9
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(349.8192818798844, 617.315092940984);
+ polygon.ps[1] = Point(349.8192818798844, 679.315092940984);
+ polygon.ps[2] = Point(287.8192818798844, 679.315092940984);
+ polygon.ps[3] = Point(287.8192818798844, 617.315092940984);
+ new ShapeRef(router, polygon, 9);
+
+ // shapeRef10
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(288.8192818798844, 371.9817596066507);
+ polygon.ps[1] = Point(288.8192818798844, 433.9817596066507);
+ polygon.ps[2] = Point(226.8192818798844, 433.9817596066507);
+ polygon.ps[3] = Point(226.8192818798844, 371.9817596066507);
+ new ShapeRef(router, polygon, 10);
+#endif
+
+ // shapeRef11
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(103.8192818798844, 975.8150929419839);
+ polygon.ps[1] = Point(103.8192818798844, 995.8150929419839);
+ polygon.ps[2] = Point(71.81928187988439, 995.8150929419839);
+ polygon.ps[3] = Point(71.81928187988439, 975.8150929419839);
+ new ShapeRef(router, polygon, 11);
+
+ // shapeRef12
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(103.8192818798844, 1017.815092941984);
+ polygon.ps[1] = Point(103.8192818798844, 1037.815092941984);
+ polygon.ps[2] = Point(71.81928187988439, 1037.815092941984);
+ polygon.ps[3] = Point(71.81928187988439, 1017.815092941984);
+ new ShapeRef(router, polygon, 12);
+
+#if ALL
+ // shapeRef13
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(328.8192818798844, 957.8150929419839);
+ polygon.ps[1] = Point(328.8192818798844, 989.8150929419839);
+ polygon.ps[2] = Point(308.8192818798844, 989.8150929419839);
+ polygon.ps[3] = Point(308.8192818798844, 957.8150929419839);
+ new ShapeRef(router, polygon, 13);
+
+ // shapeRef14
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12.81928187988439, 901.815092940984);
+ polygon.ps[1] = Point(12.81928187988439, 921.815092940984);
+ polygon.ps[2] = Point(-19.18071812011561, 921.815092940984);
+ polygon.ps[3] = Point(-19.18071812011561, 901.815092940984);
+ new ShapeRef(router, polygon, 14);
+
+ // shapeRef15
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(466.8192818798844, 840.315092940984);
+ polygon.ps[1] = Point(466.8192818798844, 872.315092940984);
+ polygon.ps[2] = Point(446.8192818798844, 872.315092940984);
+ polygon.ps[3] = Point(446.8192818798844, 840.315092940984);
+ new ShapeRef(router, polygon, 15);
+
+ // shapeRef16
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1023.504996167599, 572.9817596076507);
+ polygon.ps[1] = Point(1023.504996167599, 604.9817596076507);
+ polygon.ps[2] = Point(1003.504996167599, 604.9817596076507);
+ polygon.ps[3] = Point(1003.504996167599, 572.9817596076507);
+ new ShapeRef(router, polygon, 16);
+
+ // shapeRef17
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(887.1049961675988, 638.315092940984);
+ polygon.ps[1] = Point(887.1049961675988, 658.315092940984);
+ polygon.ps[2] = Point(855.1049961675988, 658.315092940984);
+ polygon.ps[3] = Point(855.1049961675988, 638.315092940984);
+ new ShapeRef(router, polygon, 17);
+
+ // shapeRef18
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(472.8192818798844, 671.315092940984);
+ polygon.ps[1] = Point(472.8192818798844, 691.315092940984);
+ polygon.ps[2] = Point(440.8192818798844, 691.315092940984);
+ polygon.ps[3] = Point(440.8192818798844, 671.315092940984);
+ new ShapeRef(router, polygon, 18);
+
+ // shapeRef19
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(142.8192818798844, 638.315092940984);
+ polygon.ps[1] = Point(142.8192818798844, 658.315092940984);
+ polygon.ps[2] = Point(110.8192818798844, 658.315092940984);
+ polygon.ps[3] = Point(110.8192818798844, 638.315092940984);
+ new ShapeRef(router, polygon, 19);
+
+ // shapeRef20
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(599.1049961655988, 419.9817596066507);
+ polygon.ps[1] = Point(599.1049961655988, 451.9817596066507);
+ polygon.ps[2] = Point(579.1049961655988, 451.9817596066507);
+ polygon.ps[3] = Point(579.1049961655988, 419.9817596066507);
+ new ShapeRef(router, polygon, 20);
+
+ // shapeRef21
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(472.8192818798844, 483.9817596066507);
+ polygon.ps[1] = Point(472.8192818798844, 503.9817596066507);
+ polygon.ps[2] = Point(440.8192818798844, 503.9817596066507);
+ polygon.ps[3] = Point(440.8192818798844, 483.9817596066507);
+ new ShapeRef(router, polygon, 21);
+
+ // shapeRef22
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(472.8192818798844, 134.9817596056507);
+ polygon.ps[1] = Point(472.8192818798844, 154.9817596056507);
+ polygon.ps[2] = Point(440.8192818798844, 154.9817596056507);
+ polygon.ps[3] = Point(440.8192818798844, 134.9817596056507);
+ new ShapeRef(router, polygon, 22);
+
+ // shapeRef23
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1023.504996167599, 419.9817596066507);
+ polygon.ps[1] = Point(1023.504996167599, 451.9817596066507);
+ polygon.ps[2] = Point(1003.504996167599, 451.9817596066507);
+ polygon.ps[3] = Point(1003.504996167599, 419.9817596066507);
+ new ShapeRef(router, polygon, 23);
+
+ // shapeRef24
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(751.1049961665988, 276.9817596056507);
+ polygon.ps[1] = Point(751.1049961665988, 296.9817596056507);
+ polygon.ps[2] = Point(719.1049961665988, 296.9817596056507);
+ polygon.ps[3] = Point(719.1049961665988, 276.9817596056507);
+ new ShapeRef(router, polygon, 24);
+
+ // shapeRef25
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(472.8192818798844, 209.9817596056507);
+ polygon.ps[1] = Point(472.8192818798844, 229.9817596056507);
+ polygon.ps[2] = Point(440.8192818798844, 229.9817596056507);
+ polygon.ps[3] = Point(440.8192818798844, 209.9817596056507);
+ new ShapeRef(router, polygon, 25);
+
+ // shapeRef26
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(751.1049961665988, 318.9817596056507);
+ polygon.ps[1] = Point(751.1049961665988, 338.9817596056507);
+ polygon.ps[2] = Point(719.1049961665988, 338.9817596056507);
+ polygon.ps[3] = Point(719.1049961665988, 318.9817596056507);
+ new ShapeRef(router, polygon, 26);
+
+ // shapeRef27
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(472.8192818798844, -181.0182403963493);
+ polygon.ps[1] = Point(472.8192818798844, -161.0182403963493);
+ polygon.ps[2] = Point(440.8192818798844, -161.0182403963493);
+ polygon.ps[3] = Point(440.8192818798844, -181.0182403963493);
+ new ShapeRef(router, polygon, 27);
+
+ // shapeRef28
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(599.1049961655988, -199.0182403963493);
+ polygon.ps[1] = Point(599.1049961655988, -167.0182403963493);
+ polygon.ps[2] = Point(579.1049961655988, -167.0182403963493);
+ polygon.ps[3] = Point(579.1049961655988, -199.0182403963493);
+ new ShapeRef(router, polygon, 28);
+
+ // shapeRef29
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(472.8192818798844, 251.9817596056507);
+ polygon.ps[1] = Point(472.8192818798844, 271.9817596056507);
+ polygon.ps[2] = Point(440.8192818798844, 271.9817596056507);
+ polygon.ps[3] = Point(440.8192818798844, 251.9817596056507);
+ new ShapeRef(router, polygon, 29);
+
+ // shapeRef30
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(142.8192818798844, -65.0182403953493);
+ polygon.ps[1] = Point(142.8192818798844, -45.0182403953493);
+ polygon.ps[2] = Point(110.8192818798844, -45.0182403953493);
+ polygon.ps[3] = Point(110.8192818798844, -65.0182403953493);
+ new ShapeRef(router, polygon, 30);
+
+ // shapeRef31
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(-20.18071812011561, -65.0182403953493);
+ polygon.ps[1] = Point(-20.18071812011561, -45.0182403953493);
+ polygon.ps[2] = Point(-52.18071812011561, -45.0182403953493);
+ polygon.ps[3] = Point(-52.18071812011561, -65.0182403953493);
+ new ShapeRef(router, polygon, 31);
+
+ // shapeRef32
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(267.8192818798844, 324.9817596056507);
+ polygon.ps[1] = Point(267.8192818798844, 356.9817596056507);
+ polygon.ps[2] = Point(247.8192818798844, 356.9817596056507);
+ polygon.ps[3] = Point(247.8192818798844, 324.9817596056507);
+ new ShapeRef(router, polygon, 32);
+
+ // shapeRef33
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(136.8192818798844, 258.9817596056507);
+ polygon.ps[1] = Point(136.8192818798844, 290.9817596056507);
+ polygon.ps[2] = Point(116.8192818798844, 290.9817596056507);
+ polygon.ps[3] = Point(116.8192818798844, 258.9817596056507);
+ new ShapeRef(router, polygon, 33);
+
+ // shapeRef34
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(472.8192818798844, -32.0182403953493);
+ polygon.ps[1] = Point(472.8192818798844, -12.0182403953493);
+ polygon.ps[2] = Point(440.8192818798844, -12.0182403953493);
+ polygon.ps[3] = Point(440.8192818798844, -32.0182403953493);
+ new ShapeRef(router, polygon, 34);
+
+ // shapeRef35
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1001.104996167599, 276.9817596056507);
+ polygon.ps[1] = Point(1001.104996167599, 338.9817596056507);
+ polygon.ps[2] = Point(939.1049961675988, 338.9817596056507);
+ polygon.ps[3] = Point(939.1049961675988, 276.9817596056507);
+ new ShapeRef(router, polygon, 35);
+
+ // shapeRef36
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(854.1049961675988, 144.9817596056507);
+ polygon.ps[1] = Point(854.1049961675988, 164.9817596056507);
+ polygon.ps[2] = Point(822.1049961675988, 164.9817596056507);
+ polygon.ps[3] = Point(822.1049961675988, 144.9817596056507);
+ new ShapeRef(router, polygon, 36);
+
+ // shapeRef37
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(854.1049961675988, 186.9817596056507);
+ polygon.ps[1] = Point(854.1049961675988, 206.9817596056507);
+ polygon.ps[2] = Point(822.1049961675988, 206.9817596056507);
+ polygon.ps[3] = Point(822.1049961675988, 186.9817596056507);
+ new ShapeRef(router, polygon, 37);
+
+ // shapeRef38
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(472.8192818798844, -139.0182403963493);
+ polygon.ps[1] = Point(472.8192818798844, -119.0182403963493);
+ polygon.ps[2] = Point(440.8192818798844, -119.0182403963493);
+ polygon.ps[3] = Point(440.8192818798844, -139.0182403963493);
+ new ShapeRef(router, polygon, 38);
+
+ // shapeRef39
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(854.1049961675988, 69.98175960565069);
+ polygon.ps[1] = Point(854.1049961675988, 89.98175960565069);
+ polygon.ps[2] = Point(822.1049961675988, 89.98175960565069);
+ polygon.ps[3] = Point(822.1049961675988, 69.98175960565069);
+ new ShapeRef(router, polygon, 39);
+
+ // shapeRef40
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(-51.68071812011561, 455.4817596066507);
+ polygon.ps[1] = Point(-51.68071812011561, 619.4817596066507);
+ polygon.ps[2] = Point(-170.6807181201156, 619.4817596066507);
+ polygon.ps[3] = Point(-170.6807181201156, 455.4817596066507);
+ new ShapeRef(router, polygon, 40);
+
+ // shapeRef41
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(31.81928187988439, -317.5182403973492);
+ polygon.ps[1] = Point(31.81928187988439, -282.5182403973492);
+ polygon.ps[2] = Point(-164.1807181201156, -282.5182403973492);
+ polygon.ps[3] = Point(-164.1807181201156, -317.5182403973492);
+ new ShapeRef(router, polygon, 41);
+
+ // shapeRef42
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(752.8192818798843, 768.315092940984);
+ polygon.ps[1] = Point(752.8192818798843, 812.315092940984);
+ polygon.ps[2] = Point(664.8192818798843, 812.315092940984);
+ polygon.ps[3] = Point(664.8192818798843, 768.315092940984);
+ new ShapeRef(router, polygon, 42);
+
+ // shapeRef43
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(349.8192818798844, 880.815092940984);
+ polygon.ps[1] = Point(349.8192818798844, 942.815092940984);
+ polygon.ps[2] = Point(287.8192818798844, 942.815092940984);
+ polygon.ps[3] = Point(287.8192818798844, 880.815092940984);
+ new ShapeRef(router, polygon, 43);
+
+ // shapeRef44
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(349.8192818798844, -181.0182403963493);
+ polygon.ps[1] = Point(349.8192818798844, -119.0182403963493);
+ polygon.ps[2] = Point(287.8192818798844, -119.0182403963493);
+ polygon.ps[3] = Point(287.8192818798844, -181.0182403963493);
+ new ShapeRef(router, polygon, 44);
+
+ // shapeRef45
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(935.1049961675988, -276.0182403973492);
+ polygon.ps[1] = Point(935.1049961675988, -214.0182403973492);
+ polygon.ps[2] = Point(873.1049961675988, -214.0182403973492);
+ polygon.ps[3] = Point(873.1049961675988, -276.0182403973492);
+ new ShapeRef(router, polygon, 45);
+
+ // shapeRef46
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(620.1049961655988, 276.9817596056507);
+ polygon.ps[1] = Point(620.1049961655988, 338.9817596056507);
+ polygon.ps[2] = Point(558.1049961655988, 338.9817596056507);
+ polygon.ps[3] = Point(558.1049961655988, 276.9817596056507);
+ new ShapeRef(router, polygon, 46);
+
+ // shapeRef47
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(620.1049961655988, 617.315092940984);
+ polygon.ps[1] = Point(620.1049961655988, 679.315092940984);
+ polygon.ps[2] = Point(558.1049961655988, 679.315092940984);
+ polygon.ps[3] = Point(558.1049961655988, 617.315092940984);
+ new ShapeRef(router, polygon, 47);
+#endif
+
+ // shapeRef48
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(78.81928187988439, -86.0182403953493);
+ polygon.ps[1] = Point(78.81928187988439, -24.0182403953493);
+ polygon.ps[2] = Point(16.81928187988439, -24.0182403953493);
+ polygon.ps[3] = Point(16.81928187988439, -86.0182403953493);
+ new ShapeRef(router, polygon, 48);
+
+#if ALL
+ // shapeRef49
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(-80.18071812011561, -86.0182403953493);
+ polygon.ps[1] = Point(-80.18071812011561, -24.0182403953493);
+ polygon.ps[2] = Point(-142.1807181201156, -24.0182403953493);
+ polygon.ps[3] = Point(-142.1807181201156, -86.0182403953493);
+ new ShapeRef(router, polygon, 49);
+
+ // shapeRef50
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(620.1049961655988, -276.0182403973492);
+ polygon.ps[1] = Point(620.1049961655988, -214.0182403973492);
+ polygon.ps[2] = Point(558.1049961655988, -214.0182403973492);
+ polygon.ps[3] = Point(558.1049961655988, -276.0182403973492);
+ new ShapeRef(router, polygon, 50);
+
+ // shapeRef51
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(349.8192818798844, -86.0182403953493);
+ polygon.ps[1] = Point(349.8192818798844, -24.0182403953493);
+ polygon.ps[2] = Point(287.8192818798844, -24.0182403953493);
+ polygon.ps[3] = Point(287.8192818798844, -86.0182403953493);
+ new ShapeRef(router, polygon, 51);
+
+ // shapeRef52
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(620.1049961655988, 495.9817596066507);
+ polygon.ps[1] = Point(620.1049961655988, 557.9817596066507);
+ polygon.ps[2] = Point(558.1049961655988, 557.9817596066507);
+ polygon.ps[3] = Point(558.1049961655988, 495.9817596066507);
+ new ShapeRef(router, polygon, 52);
+
+ // shapeRef53
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(115.8192818798844, 915.8150929419839);
+ polygon.ps[1] = Point(115.8192818798844, 975.8150929419839);
+ polygon.ps[2] = Point(59.81928187988439, 975.8150929419839);
+ polygon.ps[3] = Point(59.81928187988439, 915.8150929419839);
+ new ShapeRef(router, polygon, 53);
+
+ // shapeRef54
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(115.8192818798844, 1037.815092941984);
+ polygon.ps[1] = Point(115.8192818798844, 1097.815092941984);
+ polygon.ps[2] = Point(59.81928187988439, 1097.815092941984);
+ polygon.ps[3] = Point(59.81928187988439, 1037.815092941984);
+ new ShapeRef(router, polygon, 54);
+
+ // shapeRef55
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(404.8192818798844, 953.8150929419839);
+ polygon.ps[1] = Point(404.8192818798844, 993.8150929419839);
+ polygon.ps[2] = Point(328.8192818798844, 993.8150929419839);
+ polygon.ps[3] = Point(328.8192818798844, 953.8150929419839);
+ new ShapeRef(router, polygon, 55);
+#endif
+
+ // shapeRef56
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(24.81928187988439, 841.815092940984);
+ polygon.ps[1] = Point(24.81928187988439, 901.815092940984);
+ polygon.ps[2] = Point(-31.18071812011561, 901.815092940984);
+ polygon.ps[3] = Point(-31.18071812011561, 841.815092940984);
+ new ShapeRef(router, polygon, 56);
+
+#if ALL
+ // shapeRef57
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(542.8192818798843, 836.315092940984);
+ polygon.ps[1] = Point(542.8192818798843, 876.315092940984);
+ polygon.ps[2] = Point(466.8192818798844, 876.315092940984);
+ polygon.ps[3] = Point(466.8192818798844, 836.315092940984);
+ new ShapeRef(router, polygon, 57);
+
+ // shapeRef58
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1099.504996167599, 568.9817596076507);
+ polygon.ps[1] = Point(1099.504996167599, 608.9817596076507);
+ polygon.ps[2] = Point(1023.504996167599, 608.9817596076507);
+ polygon.ps[3] = Point(1023.504996167599, 568.9817596076507);
+ new ShapeRef(router, polygon, 58);
+
+ // shapeRef59
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(899.1049961675988, 578.315092940984);
+ polygon.ps[1] = Point(899.1049961675988, 638.315092940984);
+ polygon.ps[2] = Point(843.1049961675988, 638.315092940984);
+ polygon.ps[3] = Point(843.1049961675988, 578.315092940984);
+ new ShapeRef(router, polygon, 59);
+
+ // shapeRef60
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(484.8192818798844, 691.315092940984);
+ polygon.ps[1] = Point(484.8192818798844, 751.315092940984);
+ polygon.ps[2] = Point(428.8192818798844, 751.315092940984);
+ polygon.ps[3] = Point(428.8192818798844, 691.315092940984);
+ new ShapeRef(router, polygon, 60);
+
+ // shapeRef61
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(154.8192818798844, 578.315092940984);
+ polygon.ps[1] = Point(154.8192818798844, 638.315092940984);
+ polygon.ps[2] = Point(98.81928187988439, 638.315092940984);
+ polygon.ps[3] = Point(98.81928187988439, 578.315092940984);
+ new ShapeRef(router, polygon, 61);
+
+ // shapeRef62
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(675.1049961655988, 415.9817596066507);
+ polygon.ps[1] = Point(675.1049961655988, 455.9817596066507);
+ polygon.ps[2] = Point(599.1049961655988, 455.9817596066507);
+ polygon.ps[3] = Point(599.1049961655988, 415.9817596066507);
+ new ShapeRef(router, polygon, 62);
+
+ // shapeRef63
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(484.8192818798844, 423.9817596066507);
+ polygon.ps[1] = Point(484.8192818798844, 483.9817596066507);
+ polygon.ps[2] = Point(428.8192818798844, 483.9817596066507);
+ polygon.ps[3] = Point(428.8192818798844, 423.9817596066507);
+ new ShapeRef(router, polygon, 63);
+
+ // shapeRef64
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(484.8192818798844, 74.98175960565069);
+ polygon.ps[1] = Point(484.8192818798844, 134.9817596056507);
+ polygon.ps[2] = Point(428.8192818798844, 134.9817596056507);
+ polygon.ps[3] = Point(428.8192818798844, 74.98175960565069);
+ new ShapeRef(router, polygon, 64);
+
+ // shapeRef65
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1099.504996167599, 415.9817596066507);
+ polygon.ps[1] = Point(1099.504996167599, 455.9817596066507);
+ polygon.ps[2] = Point(1023.504996167599, 455.9817596066507);
+ polygon.ps[3] = Point(1023.504996167599, 415.9817596066507);
+ new ShapeRef(router, polygon, 65);
+
+ // shapeRef66
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(763.1049961665988, 216.9817596056507);
+ polygon.ps[1] = Point(763.1049961665988, 276.9817596056507);
+ polygon.ps[2] = Point(707.1049961665988, 276.9817596056507);
+ polygon.ps[3] = Point(707.1049961665988, 216.9817596056507);
+ new ShapeRef(router, polygon, 66);
+
+ // shapeRef67
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(484.8192818798844, 149.9817596056507);
+ polygon.ps[1] = Point(484.8192818798844, 209.9817596056507);
+ polygon.ps[2] = Point(428.8192818798844, 209.9817596056507);
+ polygon.ps[3] = Point(428.8192818798844, 149.9817596056507);
+ new ShapeRef(router, polygon, 67);
+
+ // shapeRef68
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(763.1049961665988, 338.9817596056507);
+ polygon.ps[1] = Point(763.1049961665988, 398.9817596056507);
+ polygon.ps[2] = Point(707.1049961665988, 398.9817596056507);
+ polygon.ps[3] = Point(707.1049961665988, 338.9817596056507);
+ new ShapeRef(router, polygon, 68);
+
+ // shapeRef69
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(484.8192818798844, -241.0182403963493);
+ polygon.ps[1] = Point(484.8192818798844, -181.0182403963493);
+ polygon.ps[2] = Point(428.8192818798844, -181.0182403963493);
+ polygon.ps[3] = Point(428.8192818798844, -241.0182403963493);
+ new ShapeRef(router, polygon, 69);
+
+ // shapeRef70
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(675.1049961655988, -203.0182403963493);
+ polygon.ps[1] = Point(675.1049961655988, -163.0182403963493);
+ polygon.ps[2] = Point(599.1049961655988, -163.0182403963493);
+ polygon.ps[3] = Point(599.1049961655988, -203.0182403963493);
+ new ShapeRef(router, polygon, 70);
+
+ // shapeRef71
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(484.8192818798844, 271.9817596056507);
+ polygon.ps[1] = Point(484.8192818798844, 331.9817596056507);
+ polygon.ps[2] = Point(428.8192818798844, 331.9817596056507);
+ polygon.ps[3] = Point(428.8192818798844, 271.9817596056507);
+ new ShapeRef(router, polygon, 71);
+
+ // shapeRef72
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(154.8192818798844, -125.0182403953493);
+ polygon.ps[1] = Point(154.8192818798844, -65.0182403953493);
+ polygon.ps[2] = Point(98.81928187988439, -65.0182403953493);
+ polygon.ps[3] = Point(98.81928187988439, -125.0182403953493);
+ new ShapeRef(router, polygon, 72);
+
+ // shapeRef73
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(-8.180718120115614, -125.0182403953493);
+ polygon.ps[1] = Point(-8.180718120115614, -65.0182403953493);
+ polygon.ps[2] = Point(-64.18071812011561, -65.0182403953493);
+ polygon.ps[3] = Point(-64.18071812011561, -125.0182403953493);
+ new ShapeRef(router, polygon, 73);
+
+ // shapeRef74
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(343.8192818798844, 320.9817596056507);
+ polygon.ps[1] = Point(343.8192818798844, 360.9817596056507);
+ polygon.ps[2] = Point(267.8192818798844, 360.9817596056507);
+ polygon.ps[3] = Point(267.8192818798844, 320.9817596056507);
+ new ShapeRef(router, polygon, 74);
+
+ // shapeRef75
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(212.8192818798844, 254.9817596056507);
+ polygon.ps[1] = Point(212.8192818798844, 294.9817596056507);
+ polygon.ps[2] = Point(136.8192818798844, 294.9817596056507);
+ polygon.ps[3] = Point(136.8192818798844, 254.9817596056507);
+ new ShapeRef(router, polygon, 75);
+
+ // shapeRef76
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(484.8192818798844, -12.0182403953493);
+ polygon.ps[1] = Point(484.8192818798844, 47.9817596046507);
+ polygon.ps[2] = Point(428.8192818798844, 47.9817596046507);
+ polygon.ps[3] = Point(428.8192818798844, -12.0182403953493);
+ new ShapeRef(router, polygon, 76);
+
+ // shapeRef77
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(866.1049961675988, 84.98175960565069);
+ polygon.ps[1] = Point(866.1049961675988, 144.9817596056507);
+ polygon.ps[2] = Point(810.1049961675988, 144.9817596056507);
+ polygon.ps[3] = Point(810.1049961675988, 84.98175960565069);
+ new ShapeRef(router, polygon, 77);
+
+ // shapeRef78
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(866.1049961675988, 206.9817596056507);
+ polygon.ps[1] = Point(866.1049961675988, 266.9817596056507);
+ polygon.ps[2] = Point(810.1049961675988, 266.9817596056507);
+ polygon.ps[3] = Point(810.1049961675988, 206.9817596056507);
+ new ShapeRef(router, polygon, 78);
+
+ // shapeRef79
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(484.8192818798844, -119.0182403963493);
+ polygon.ps[1] = Point(484.8192818798844, -59.01824039634928);
+ polygon.ps[2] = Point(428.8192818798844, -59.01824039634928);
+ polygon.ps[3] = Point(428.8192818798844, -119.0182403963493);
+ new ShapeRef(router, polygon, 79);
+
+ // shapeRef80
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(866.1049961675988, 9.981759605650694);
+ polygon.ps[1] = Point(866.1049961675988, 69.98175960565069);
+ polygon.ps[2] = Point(810.1049961675988, 69.98175960565069);
+ polygon.ps[3] = Point(810.1049961675988, 9.981759605650694);
+ new ShapeRef(router, polygon, 80);
+
+ // shapeRef81
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(-91.18071812011561, 455.9817596066507);
+ polygon.ps[1] = Point(-91.18071812011561, 515.9817596066507);
+ polygon.ps[2] = Point(-131.1807181201156, 515.9817596066507);
+ polygon.ps[3] = Point(-131.1807181201156, 455.9817596066507);
+ new ShapeRef(router, polygon, 81);
+
+ // shapeRef82
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(-91.18071812011561, 559.9817596066507);
+ polygon.ps[1] = Point(-91.18071812011561, 619.9817596066507);
+ polygon.ps[2] = Point(-131.1807181201156, 619.9817596066507);
+ polygon.ps[3] = Point(-131.1807181201156, 559.9817596066507);
+ new ShapeRef(router, polygon, 82);
+
+ // shapeRef83
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(876.0049961675987, 79.98175960565069);
+ polygon.ps[1] = Point(876.0049961675987, 196.9817596056507);
+ polygon.ps[2] = Point(800.2049961675988, 196.9817596056507);
+ polygon.ps[3] = Point(800.2049961675988, 79.98175960565069);
+ new ShapeRef(router, polygon, 83);
+#endif
+
+ // shapeRef84
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(125.7192818798844, 985.8150929419839);
+ polygon.ps[1] = Point(125.7192818798844, 1027.815092941984);
+ polygon.ps[2] = Point(49.91928187988439, 1027.815092941984);
+ polygon.ps[3] = Point(49.91928187988439, 985.8150929419839);
+ new ShapeRef(router, polygon, 84);
+
+#if ALL
+ // shapeRef85
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(494.7192818798844, -171.0182403963493);
+ polygon.ps[1] = Point(494.7192818798844, -129.0182403963493);
+ polygon.ps[2] = Point(418.9192818798844, -129.0182403963493);
+ polygon.ps[3] = Point(418.9192818798844, -171.0182403963493);
+ new ShapeRef(router, polygon, 85);
+
+ // shapeRef86
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(773.0049961665987, 286.9817596056507);
+ polygon.ps[1] = Point(773.0049961665987, 328.9817596056507);
+ polygon.ps[2] = Point(697.2049961665988, 328.9817596056507);
+ polygon.ps[3] = Point(697.2049961665988, 286.9817596056507);
+ new ShapeRef(router, polygon, 86);
+
+ // shapeRef87
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(494.7192818798844, 144.9817596056507);
+ polygon.ps[1] = Point(494.7192818798844, 261.9817596056507);
+ polygon.ps[2] = Point(418.9192818798844, 261.9817596056507);
+ polygon.ps[3] = Point(418.9192818798844, 144.9817596056507);
+ new ShapeRef(router, polygon, 87);
+
+ // connRef88
+ connRef = new ConnRef(router, 88);
+ srcPt = ConnEnd(Point(111.8192818798844, 648.315092940984), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(-111.1807181201156, 856.315092940984), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef89
+ connRef = new ConnRef(router, 89);
+ srcPt = ConnEnd(Point(126.8192818798844, 289.9817596056507), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(-111.1807181201156, 856.315092940984), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+#endif
+
+ // connRef90
+ connRef = new ConnRef(router, 90);
+ srcPt = ConnEnd(Point(72.81928187988439, 985.8150929419839), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(589.1049961655988, -55.0182403953493), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints90(1);
+ checkpoints90[0] = Checkpoint(Point(49.81928187988439, 1006.815092941984), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef->setRoutingCheckpoints(checkpoints90);
+ Avoid::ConnRef *connRef90 = connRef;
+
+ // connRef91
+ connRef = new ConnRef(router, 91);
+ srcPt = ConnEnd(Point(72.81928187988439, 1027.815092941984), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(589.1049961655988, -55.0182403953493), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints91(1);
+ checkpoints91[0] = Checkpoint(Point(49.81928187988439, 1006.815092941984), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef->setRoutingCheckpoints(checkpoints91);
+ Avoid::ConnRef *connRef91 = connRef;
+
+#if ALL
+ // connRef92
+ connRef = new ConnRef(router, 92);
+ srcPt = ConnEnd(Point(471.8192818798844, -171.0182403963493), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(589.1049961655988, -55.0182403953493), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints92(1);
+ checkpoints92[0] = Checkpoint(Point(494.8192818798844, -150.0182403963493), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef->setRoutingCheckpoints(checkpoints92);
+
+ // connRef93
+ connRef = new ConnRef(router, 93);
+ srcPt = ConnEnd(Point(589.1049961655988, -55.0182403953493), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(589.1049961655988, -168.0182403963493), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef94
+ connRef = new ConnRef(router, 94);
+ srcPt = ConnEnd(Point(589.1049961655988, -55.0182403953493), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(471.8192818798844, -22.0182403953493), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef95
+ connRef = new ConnRef(router, 95);
+ srcPt = ConnEnd(Point(823.1049961675988, 154.9817596056507), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(589.1049961655988, -55.0182403953493), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints95(1);
+ checkpoints95[0] = Checkpoint(Point(800.1049961675988, 175.9817596056507), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef->setRoutingCheckpoints(checkpoints95);
+
+ // connRef96
+ connRef = new ConnRef(router, 96);
+ srcPt = ConnEnd(Point(823.1049961675988, 196.9817596056507), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(589.1049961655988, -55.0182403953493), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints96(1);
+ checkpoints96[0] = Checkpoint(Point(800.1049961675988, 175.9817596056507), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef->setRoutingCheckpoints(checkpoints96);
+
+ // connRef97
+ connRef = new ConnRef(router, 97);
+ srcPt = ConnEnd(Point(471.8192818798844, -129.0182403963493), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(589.1049961655988, -55.0182403953493), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints97(1);
+ checkpoints97[0] = Checkpoint(Point(494.8192818798844, -150.0182403963493), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef->setRoutingCheckpoints(checkpoints97);
+
+ // connRef98
+ connRef = new ConnRef(router, 98);
+ srcPt = ConnEnd(Point(823.1049961675988, 79.98175960565069), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(589.1049961655988, -55.0182403953493), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints98(1);
+ checkpoints98[0] = Checkpoint(Point(800.1049961675988, 175.9817596056507), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef->setRoutingCheckpoints(checkpoints98);
+
+ // connRef99
+ connRef = new ConnRef(router, 99);
+ srcPt = ConnEnd(Point(1013.504996167599, 526.9817596066507), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1013.504996167599, 573.9817596076507), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef100
+ connRef = new ConnRef(router, 100);
+ srcPt = ConnEnd(Point(1013.504996167599, 450.9817596066507), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1013.504996167599, 526.9817596066507), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef101
+ connRef = new ConnRef(router, 101);
+ srcPt = ConnEnd(Point(318.8192818798844, 648.315092940984), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(141.8192818798844, 648.315092940984), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef102
+ connRef = new ConnRef(router, 102);
+ srcPt = ConnEnd(Point(441.8192818798844, 493.9817596066507), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(318.8192818798844, 648.315092940984), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef103
+ connRef = new ConnRef(router, 103);
+ srcPt = ConnEnd(Point(102.8192818798844, 985.8150929419839), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(318.8192818798844, 911.815092940984), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints103(1);
+ checkpoints103[0] = Checkpoint(Point(125.8192818798844, 1006.815092941984), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef->setRoutingCheckpoints(checkpoints103);
+
+ // connRef104
+ connRef = new ConnRef(router, 104);
+ srcPt = ConnEnd(Point(102.8192818798844, 1027.815092941984), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(318.8192818798844, 911.815092940984), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints104(1);
+ checkpoints104[0] = Checkpoint(Point(125.8192818798844, 1006.815092941984), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef->setRoutingCheckpoints(checkpoints104);
+
+ // connRef105
+ connRef = new ConnRef(router, 105);
+ srcPt = ConnEnd(Point(318.8192818798844, 988.8150929419839), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(318.8192818798844, 1039.815092941984), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef106
+ connRef = new ConnRef(router, 106);
+ srcPt = ConnEnd(Point(318.8192818798844, 911.815092940984), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(318.8192818798844, 958.8150929419839), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef107
+ connRef = new ConnRef(router, 107);
+ srcPt = ConnEnd(Point(-18.18071812011561, 911.815092940984), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(-111.1807181201156, 856.315092940984), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef108
+ connRef = new ConnRef(router, 108);
+ srcPt = ConnEnd(Point(318.8192818798844, 911.815092940984), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11.81928187988439, 911.815092940984), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef109
+ connRef = new ConnRef(router, 109);
+ srcPt = ConnEnd(Point(456.8192818798844, 871.315092940984), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(318.8192818798844, 911.815092940984), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef110
+ connRef = new ConnRef(router, 110);
+ srcPt = ConnEnd(Point(589.1049961655988, 648.315092940984), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(456.8192818798844, 841.315092940984), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef111
+ connRef = new ConnRef(router, 111);
+ srcPt = ConnEnd(Point(1013.504996167599, 603.9817596076507), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1013.504996167599, 750.315092940984), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef112
+ connRef = new ConnRef(router, 112);
+ srcPt = ConnEnd(Point(970.1049961675988, 307.9817596056507), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(886.1049961675988, 648.315092940984), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef113
+ connRef = new ConnRef(router, 113);
+ srcPt = ConnEnd(Point(856.1049961675988, 648.315092940984), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(589.1049961655988, 648.315092940984), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef114
+ connRef = new ConnRef(router, 114);
+ srcPt = ConnEnd(Point(441.8192818798844, 681.315092940984), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(318.8192818798844, 648.315092940984), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef115
+ connRef = new ConnRef(router, 115);
+ srcPt = ConnEnd(Point(589.1049961655988, 307.9817596056507), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(589.1049961655988, 420.9817596066507), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef116
+ connRef = new ConnRef(router, 116);
+ srcPt = ConnEnd(Point(589.1049961655988, 450.9817596066507), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(589.1049961655988, 526.9817596066507), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef117
+ connRef = new ConnRef(router, 117);
+ srcPt = ConnEnd(Point(589.1049961655988, 307.9817596056507), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(471.8192818798844, 493.9817596066507), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef118
+ connRef = new ConnRef(router, 118);
+ srcPt = ConnEnd(Point(471.8192818798844, 144.9817596056507), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(589.1049961655988, 307.9817596056507), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints118(1);
+ checkpoints118[0] = Checkpoint(Point(494.8192818798844, 240.9817596056507), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef->setRoutingCheckpoints(checkpoints118);
+
+ // connRef119
+ connRef = new ConnRef(router, 119);
+ srcPt = ConnEnd(Point(441.8192818798844, 144.9817596056507), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(318.8192818798844, -55.0182403953493), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints119(1);
+ checkpoints119[0] = Checkpoint(Point(418.8192818798844, 240.9817596056507), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef->setRoutingCheckpoints(checkpoints119);
+
+ // connRef120
+ connRef = new ConnRef(router, 120);
+ srcPt = ConnEnd(Point(970.1049961675988, 307.9817596056507), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1013.504996167599, 420.9817596066507), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef121
+ connRef = new ConnRef(router, 121);
+ srcPt = ConnEnd(Point(750.1049961665988, 286.9817596056507), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(970.1049961675988, 307.9817596056507), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints121(1);
+ checkpoints121[0] = Checkpoint(Point(773.1049961665988, 307.9817596056507), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef->setRoutingCheckpoints(checkpoints121);
+
+ // connRef122
+ connRef = new ConnRef(router, 122);
+ srcPt = ConnEnd(Point(720.1049961665988, 286.9817596056507), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(589.1049961655988, 307.9817596056507), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints122(1);
+ checkpoints122[0] = Checkpoint(Point(697.1049961665988, 307.9817596056507), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef->setRoutingCheckpoints(checkpoints122);
+
+ // connRef123
+ connRef = new ConnRef(router, 123);
+ srcPt = ConnEnd(Point(471.8192818798844, 219.9817596056507), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(589.1049961655988, 307.9817596056507), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints123(1);
+ checkpoints123[0] = Checkpoint(Point(494.8192818798844, 240.9817596056507), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef->setRoutingCheckpoints(checkpoints123);
+
+ // connRef124
+ connRef = new ConnRef(router, 124);
+ srcPt = ConnEnd(Point(441.8192818798844, 219.9817596056507), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(318.8192818798844, -55.0182403953493), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints124(1);
+ checkpoints124[0] = Checkpoint(Point(418.8192818798844, 240.9817596056507), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef->setRoutingCheckpoints(checkpoints124);
+
+ // connRef125
+ connRef = new ConnRef(router, 125);
+ srcPt = ConnEnd(Point(750.1049961665988, 328.9817596056507), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(970.1049961675988, 307.9817596056507), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints125(1);
+ checkpoints125[0] = Checkpoint(Point(773.1049961665988, 307.9817596056507), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef->setRoutingCheckpoints(checkpoints125);
+
+ // connRef126
+ connRef = new ConnRef(router, 126);
+ srcPt = ConnEnd(Point(441.8192818798844, -171.0182403963493), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(318.8192818798844, -150.0182403963493), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints126(1);
+ checkpoints126[0] = Checkpoint(Point(418.8192818798844, -150.0182403963493), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef->setRoutingCheckpoints(checkpoints126);
+
+ // connRef127
+ connRef = new ConnRef(router, 127);
+ srcPt = ConnEnd(Point(589.1049961655988, -198.0182403963493), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(589.1049961655988, -245.0182403973492), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef128
+ connRef = new ConnRef(router, 128);
+ srcPt = ConnEnd(Point(471.8192818798844, 261.9817596056507), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(589.1049961655988, 307.9817596056507), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints128(1);
+ checkpoints128[0] = Checkpoint(Point(494.8192818798844, 240.9817596056507), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef->setRoutingCheckpoints(checkpoints128);
+
+ // connRef129
+ connRef = new ConnRef(router, 129);
+ srcPt = ConnEnd(Point(441.8192818798844, 261.9817596056507), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(318.8192818798844, -55.0182403953493), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints129(1);
+ checkpoints129[0] = Checkpoint(Point(418.8192818798844, 240.9817596056507), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef->setRoutingCheckpoints(checkpoints129);
+#endif
+
+ // connRef130
+ connRef = new ConnRef(router, 130);
+ srcPt = ConnEnd(Point(47.81928187988439, -55.0182403953493), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(111.8192818798844, -55.0182403953493), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+#if ALL
+ // connRef131
+ connRef = new ConnRef(router, 131);
+ srcPt = ConnEnd(Point(141.8192818798844, -55.0182403953493), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(318.8192818798844, -55.0182403953493), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef132
+ connRef = new ConnRef(router, 132);
+ srcPt = ConnEnd(Point(-21.18071812011561, -55.0182403953493), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(47.81928187988439, -55.0182403953493), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef133
+ connRef = new ConnRef(router, 133);
+ srcPt = ConnEnd(Point(-111.1807181201156, -55.0182403953493), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(-51.18071812011561, -55.0182403953493), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef134
+ connRef = new ConnRef(router, 134);
+ srcPt = ConnEnd(Point(257.8192818798844, 355.9817596056507), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(257.8192818798844, 402.9817596066507), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef135
+ connRef = new ConnRef(router, 135);
+ srcPt = ConnEnd(Point(318.8192818798844, -55.0182403953493), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(257.8192818798844, 325.9817596056507), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef136
+ connRef = new ConnRef(router, 136);
+ srcPt = ConnEnd(Point(318.8192818798844, -55.0182403953493), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(126.8192818798844, 259.9817596056507), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef137
+ connRef = new ConnRef(router, 137);
+ srcPt = ConnEnd(Point(441.8192818798844, -22.0182403953493), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(318.8192818798844, -55.0182403953493), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef138
+ connRef = new ConnRef(router, 138);
+ srcPt = ConnEnd(Point(853.1049961675988, 154.9817596056507), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(970.1049961675988, 307.9817596056507), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints138(1);
+ checkpoints138[0] = Checkpoint(Point(876.1049961675988, 175.9817596056507), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef->setRoutingCheckpoints(checkpoints138);
+
+ // connRef139
+ connRef = new ConnRef(router, 139);
+ srcPt = ConnEnd(Point(853.1049961675988, 196.9817596056507), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(970.1049961675988, 307.9817596056507), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints139(1);
+ checkpoints139[0] = Checkpoint(Point(876.1049961675988, 175.9817596056507), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef->setRoutingCheckpoints(checkpoints139);
+
+ // connRef140
+ connRef = new ConnRef(router, 140);
+ srcPt = ConnEnd(Point(853.1049961675988, 79.98175960565069), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(970.1049961675988, 307.9817596056507), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints140(1);
+ checkpoints140[0] = Checkpoint(Point(876.1049961675988, 175.9817596056507), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef->setRoutingCheckpoints(checkpoints140);
+
+ // connRef141
+ connRef = new ConnRef(router, 141);
+ srcPt = ConnEnd(Point(441.8192818798844, -129.0182403963493), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(318.8192818798844, -150.0182403963493), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints141(1);
+ checkpoints141[0] = Checkpoint(Point(418.8192818798844, -150.0182403963493), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef->setRoutingCheckpoints(checkpoints141);
+
+ // connRef142
+ connRef = new ConnRef(router, 142);
+ srcPt = ConnEnd(Point(720.1049961665988, 328.9817596056507), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(589.1049961655988, 307.9817596056507), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints142(1);
+ checkpoints142[0] = Checkpoint(Point(697.1049961665988, 307.9817596056507), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef->setRoutingCheckpoints(checkpoints142);
+
+ // connRef143
+ connRef = new ConnRef(router, 143);
+ srcPt = ConnEnd(Point(589.1049961655988, 648.315092940984), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(471.8192818798844, 681.315092940984), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef144
+ connRef = new ConnRef(router, 144);
+ srcPt = ConnEnd(Point(87.81928187988439, 935.8150929419839), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(87.81928187988439, 985.8150929419839), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef145
+ connRef = new ConnRef(router, 145);
+ srcPt = ConnEnd(Point(87.81928187988439, 1077.815092941984), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(87.81928187988439, 1027.815092941984), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef146
+ connRef = new ConnRef(router, 146);
+ srcPt = ConnEnd(Point(376.8192818798844, 973.8150929419839), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(318.8192818798844, 973.8150929419839), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef147
+ connRef = new ConnRef(router, 147);
+ srcPt = ConnEnd(Point(-3.180718120115614, 861.815092940984), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(-3.180718120115614, 911.815092940984), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef148
+ connRef = new ConnRef(router, 148);
+ srcPt = ConnEnd(Point(514.8192818798843, 856.315092940984), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(456.8192818798844, 856.315092940984), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef149
+ connRef = new ConnRef(router, 149);
+ srcPt = ConnEnd(Point(1071.504996167599, 588.9817596076507), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1013.504996167599, 588.9817596076507), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef150
+ connRef = new ConnRef(router, 150);
+ srcPt = ConnEnd(Point(871.1049961675988, 598.315092940984), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(871.1049961675988, 648.315092940984), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef151
+ connRef = new ConnRef(router, 151);
+ srcPt = ConnEnd(Point(456.8192818798844, 731.315092940984), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(456.8192818798844, 681.315092940984), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef152
+ connRef = new ConnRef(router, 152);
+ srcPt = ConnEnd(Point(126.8192818798844, 598.315092940984), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(126.8192818798844, 648.315092940984), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef153
+ connRef = new ConnRef(router, 153);
+ srcPt = ConnEnd(Point(647.1049961655988, 435.9817596066507), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(589.1049961655988, 435.9817596066507), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef154
+ connRef = new ConnRef(router, 154);
+ srcPt = ConnEnd(Point(456.8192818798844, 443.9817596066507), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(456.8192818798844, 493.9817596066507), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef155
+ connRef = new ConnRef(router, 155);
+ srcPt = ConnEnd(Point(456.8192818798844, 94.98175960565069), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(456.8192818798844, 144.9817596056507), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef156
+ connRef = new ConnRef(router, 156);
+ srcPt = ConnEnd(Point(1071.504996167599, 435.9817596066507), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1013.504996167599, 435.9817596066507), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef157
+ connRef = new ConnRef(router, 157);
+ srcPt = ConnEnd(Point(735.1049961665988, 236.9817596056507), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(735.1049961665988, 286.9817596056507), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef158
+ connRef = new ConnRef(router, 158);
+ srcPt = ConnEnd(Point(456.8192818798844, 169.9817596056507), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(456.8192818798844, 219.9817596056507), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef159
+ connRef = new ConnRef(router, 159);
+ srcPt = ConnEnd(Point(735.1049961665988, 378.9817596056507), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(735.1049961665988, 328.9817596056507), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef160
+ connRef = new ConnRef(router, 160);
+ srcPt = ConnEnd(Point(456.8192818798844, -221.0182403963493), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(456.8192818798844, -171.0182403963493), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef161
+ connRef = new ConnRef(router, 161);
+ srcPt = ConnEnd(Point(647.1049961655988, -183.0182403963493), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(589.1049961655988, -183.0182403963493), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef162
+ connRef = new ConnRef(router, 162);
+ srcPt = ConnEnd(Point(456.8192818798844, 311.9817596056507), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(456.8192818798844, 261.9817596056507), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef163
+ connRef = new ConnRef(router, 163);
+ srcPt = ConnEnd(Point(126.8192818798844, -105.0182403953493), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(126.8192818798844, -55.0182403953493), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef164
+ connRef = new ConnRef(router, 164);
+ srcPt = ConnEnd(Point(-36.18071812011561, -105.0182403953493), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(-36.18071812011561, -55.0182403953493), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef165
+ connRef = new ConnRef(router, 165);
+ srcPt = ConnEnd(Point(315.8192818798844, 340.9817596056507), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(257.8192818798844, 340.9817596056507), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef166
+ connRef = new ConnRef(router, 166);
+ srcPt = ConnEnd(Point(184.8192818798844, 274.9817596056507), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(126.8192818798844, 274.9817596056507), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef167
+ connRef = new ConnRef(router, 167);
+ srcPt = ConnEnd(Point(456.8192818798844, 27.9817596046507), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(456.8192818798844, -22.0182403953493), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef168
+ connRef = new ConnRef(router, 168);
+ srcPt = ConnEnd(Point(838.1049961675988, 104.9817596056507), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(838.1049961675988, 154.9817596056507), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef169
+ connRef = new ConnRef(router, 169);
+ srcPt = ConnEnd(Point(838.1049961675988, 246.9817596056507), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(838.1049961675988, 196.9817596056507), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef170
+ connRef = new ConnRef(router, 170);
+ srcPt = ConnEnd(Point(456.8192818798844, -79.01824039634928), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(456.8192818798844, -129.0182403963493), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef171
+ connRef = new ConnRef(router, 171);
+ srcPt = ConnEnd(Point(838.1049961675988, 29.98175960565069), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(838.1049961675988, 79.98175960565069), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef172
+ connRef = new ConnRef(router, 172);
+ srcPt = ConnEnd(Point(-111.1807181201156, -55.0182403953493), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(-111.1807181201156, 460.9817596066507), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef173
+ connRef = new ConnRef(router, 173);
+ srcPt = ConnEnd(Point(-111.1807181201156, 856.315092940984), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(-111.1807181201156, 614.9817596066507), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+#endif
+
+ router->processTransaction();
+ router->outputDiagram("output/nudgingSkipsCheckpoint01");
+ Avoid::PolyLine route90 = connRef90->displayRoute();
+ Avoid::PolyLine route91 = connRef91->displayRoute();
+
+ delete router;
+ return (route90.size() == 7 && route91.size() == 7) ? 0 : 1;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/nudgingSkipsCheckpoint02.cpp b/src/3rdparty/adaptagrams/libavoid/tests/nudgingSkipsCheckpoint02.cpp
new file mode 100644
index 0000000..cb17c82
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/nudgingSkipsCheckpoint02.cpp
@@ -0,0 +1,3054 @@
+// Regression test to catch problem where orthogonal segments from the same
+// connector were being merged with others going through checkpoints and
+// being simplified so as not to pass the checkpoint anymore.
+// Based on ec00480.
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingParameter((RoutingParameter)0, 50);
+ router->setRoutingParameter((RoutingParameter)1, 0);
+ router->setRoutingParameter((RoutingParameter)2, 0);
+ router->setRoutingParameter((RoutingParameter)3, 4000);
+ router->setRoutingParameter((RoutingParameter)4, 0);
+ router->setRoutingParameter((RoutingParameter)5, 100);
+ router->setRoutingParameter((RoutingParameter)6, 0);
+ router->setRoutingParameter((RoutingParameter)7, 4);
+ router->setRoutingOption((RoutingOption)0, true);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, false);
+ router->setRoutingOption((RoutingOption)3, false);
+
+#ifdef ALL
+ Polygon poly1(4);
+ poly1.ps[0] = Point(1395.728847251115, 277.2282734381338);
+ poly1.ps[1] = Point(1395.728847251115, 339.2282734381338);
+ poly1.ps[2] = Point(1333.728847251115, 339.2282734381338);
+ poly1.ps[3] = Point(1333.728847251115, 277.2282734381338);
+ new ShapeRef(router, poly1, 1);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(-406.4508064345389, -754.3431551372947);
+ poly2.ps[1] = Point(-406.4508064345389, -719.3431551372947);
+ poly2.ps[2] = Point(-635.4508064345389, -719.3431551372947);
+ poly2.ps[3] = Point(-635.4508064345389, -754.3431551372947);
+ new ShapeRef(router, poly2, 2);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(887.7288472481148, -474.3431551372947);
+ poly3.ps[1] = Point(887.7288472481148, -310.3431551372947);
+ poly3.ps[2] = Point(803.7288472481148, -310.3431551372947);
+ poly3.ps[3] = Point(803.7288472481148, -474.3431551372947);
+ new ShapeRef(router, poly3, 3);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(723.2288472481148, -439.8431551372947);
+ poly4.ps[1] = Point(723.2288472481148, -384.8431551372947);
+ poly4.ps[2] = Point(515.2288472481148, -384.8431551372947);
+ poly4.ps[3] = Point(515.2288472481148, -439.8431551372947);
+ new ShapeRef(router, poly4, 4);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(543.4431329624006, -281.3431551362947);
+ poly5.ps[1] = Point(543.4431329624006, -231.3431551362947);
+ poly5.ps[2] = Point(301.4431329624006, -231.3431551362947);
+ poly5.ps[3] = Point(301.4431329624006, -281.3431551362947);
+ new ShapeRef(router, poly5, 5);
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(261.4431329624006, -444.8431551372947);
+ poly6.ps[1] = Point(261.4431329624006, -389.8431551372947);
+ poly6.ps[2] = Point(49.44313296240057, -389.8431551372947);
+ poly6.ps[3] = Point(49.44313296240057, -444.8431551372947);
+ new ShapeRef(router, poly6, 6);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(976.7288472491148, 236.2282734371338);
+ poly7.ps[1] = Point(976.7288472491148, 256.2282734371338);
+ poly7.ps[2] = Point(944.7288472491148, 256.2282734371338);
+ poly7.ps[3] = Point(944.7288472491148, 236.2282734371338);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(865.7288472481148, 364.561606771467);
+ poly8.ps[1] = Point(865.7288472481148, 384.561606771467);
+ poly8.ps[2] = Point(833.7288472481148, 384.561606771467);
+ poly8.ps[3] = Point(833.7288472481148, 364.561606771467);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(634.7288472481148, 424.9901782000385);
+ poly9.ps[1] = Point(634.7288472481148, 444.9901782000385);
+ poly9.ps[2] = Point(602.7288472481148, 444.9901782000385);
+ poly9.ps[3] = Point(602.7288472481148, 424.9901782000385);
+ new ShapeRef(router, poly9, 9);
+#endif
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(-264.9508064325389, 376.2282734371338);
+ poly10.ps[1] = Point(-264.9508064325389, 396.2282734371338);
+ poly10.ps[2] = Point(-296.9508064325389, 396.2282734371338);
+ poly10.ps[3] = Point(-296.9508064325389, 376.2282734371338);
+ new ShapeRef(router, poly10, 10);
+
+ Polygon poly11(4);
+ poly11.ps[0] = Point(-264.9508064325389, 451.2282734371338);
+ poly11.ps[1] = Point(-264.9508064325389, 471.2282734371338);
+ poly11.ps[2] = Point(-296.9508064325389, 471.2282734371338);
+ poly11.ps[3] = Point(-296.9508064325389, 451.2282734371338);
+ new ShapeRef(router, poly11, 11);
+
+ Polygon poly12(4);
+ poly12.ps[0] = Point(-264.9508064325389, 526.2282734371338);
+ poly12.ps[1] = Point(-264.9508064325389, 546.2282734371338);
+ poly12.ps[2] = Point(-296.9508064325389, 546.2282734371338);
+ poly12.ps[3] = Point(-296.9508064325389, 526.2282734371338);
+ new ShapeRef(router, poly12, 12);
+
+ Polygon poly13(4);
+ poly13.ps[0] = Point(-264.9508064325389, 601.2282734371338);
+ poly13.ps[1] = Point(-264.9508064325389, 621.2282734371338);
+ poly13.ps[2] = Point(-296.9508064325389, 621.2282734371338);
+ poly13.ps[3] = Point(-296.9508064325389, 601.2282734371338);
+ new ShapeRef(router, poly13, 13);
+
+ Polygon poly14(4);
+ poly14.ps[0] = Point(-264.9508064325389, 676.2282734371338);
+ poly14.ps[1] = Point(-264.9508064325389, 696.2282734371338);
+ poly14.ps[2] = Point(-296.9508064325389, 696.2282734371338);
+ poly14.ps[3] = Point(-296.9508064325389, 676.2282734371338);
+ new ShapeRef(router, poly14, 14);
+
+ Polygon poly15(4);
+ poly15.ps[0] = Point(-264.9508064325389, 943.2282734371338);
+ poly15.ps[1] = Point(-264.9508064325389, 963.2282734371338);
+ poly15.ps[2] = Point(-296.9508064325389, 963.2282734371338);
+ poly15.ps[3] = Point(-296.9508064325389, 943.2282734371338);
+ new ShapeRef(router, poly15, 15);
+
+ Polygon poly16(4);
+ poly16.ps[0] = Point(-264.9508064325389, 751.2282734371338);
+ poly16.ps[1] = Point(-264.9508064325389, 771.2282734371338);
+ poly16.ps[2] = Point(-296.9508064325389, 771.2282734371338);
+ poly16.ps[3] = Point(-296.9508064325389, 751.2282734371338);
+ new ShapeRef(router, poly16, 16);
+
+ Polygon poly17(4);
+ poly17.ps[0] = Point(-264.9508064325389, 793.2282734371338);
+ poly17.ps[1] = Point(-264.9508064325389, 813.2282734371338);
+ poly17.ps[2] = Point(-296.9508064325389, 813.2282734371338);
+ poly17.ps[3] = Point(-296.9508064325389, 793.2282734371338);
+ new ShapeRef(router, poly17, 17);
+
+ Polygon poly18(4);
+ poly18.ps[0] = Point(-264.9508064325389, 868.2282734371338);
+ poly18.ps[1] = Point(-264.9508064325389, 888.2282734371338);
+ poly18.ps[2] = Point(-296.9508064325389, 888.2282734371338);
+ poly18.ps[3] = Point(-296.9508064325389, 868.2282734371338);
+ new ShapeRef(router, poly18, 18);
+
+ Polygon poly19(4);
+ poly19.ps[0] = Point(-264.9508064325389, 1018.228273437134);
+ poly19.ps[1] = Point(-264.9508064325389, 1038.228273437134);
+ poly19.ps[2] = Point(-296.9508064325389, 1038.228273437134);
+ poly19.ps[3] = Point(-296.9508064325389, 1018.228273437134);
+ new ShapeRef(router, poly19, 19);
+
+#ifdef ALL
+ Polygon poly20(4);
+ poly20.ps[0] = Point(-392.9508064335388, 202.2282734381338);
+ poly20.ps[1] = Point(-392.9508064335388, 222.2282734381338);
+ poly20.ps[2] = Point(-424.9508064335388, 222.2282734381338);
+ poly20.ps[3] = Point(-424.9508064335388, 202.2282734381338);
+ new ShapeRef(router, poly20, 20);
+
+ Polygon poly21(4);
+ poly21.ps[0] = Point(-392.9508064335388, 277.2282734381338);
+ poly21.ps[1] = Point(-392.9508064335388, 297.2282734381338);
+ poly21.ps[2] = Point(-424.9508064335388, 297.2282734381338);
+ poly21.ps[3] = Point(-424.9508064335388, 277.2282734381338);
+ new ShapeRef(router, poly21, 21);
+
+ Polygon poly22(4);
+ poly22.ps[0] = Point(-392.9508064335388, 319.2282734381338);
+ poly22.ps[1] = Point(-392.9508064335388, 339.2282734381338);
+ poly22.ps[2] = Point(-424.9508064335388, 339.2282734381338);
+ poly22.ps[3] = Point(-424.9508064335388, 319.2282734381338);
+ new ShapeRef(router, poly22, 22);
+
+ Polygon poly23(4);
+ poly23.ps[0] = Point(601.7288472481148, 236.2282734371338);
+ poly23.ps[1] = Point(601.7288472481148, 256.2282734371338);
+ poly23.ps[2] = Point(569.7288472481148, 256.2282734371338);
+ poly23.ps[3] = Point(569.7288472481148, 236.2282734371338);
+ new ShapeRef(router, poly23, 23);
+
+ Polygon poly24(4);
+ poly24.ps[0] = Point(727.7288472481148, -284.3431551362947);
+ poly24.ps[1] = Point(727.7288472481148, -252.3431551362947);
+ poly24.ps[2] = Point(707.7288472481148, -252.3431551362947);
+ poly24.ps[3] = Point(707.7288472481148, -284.3431551362947);
+ new ShapeRef(router, poly24, 24);
+
+ Polygon poly25(4);
+ poly25.ps[0] = Point(168.7764662957339, 153.6568448657052);
+ poly25.ps[1] = Point(168.7764662957339, 185.6568448657052);
+ poly25.ps[2] = Point(148.7764662957339, 185.6568448657052);
+ poly25.ps[3] = Point(148.7764662957339, 153.6568448657052);
+ new ShapeRef(router, poly25, 25);
+
+ Polygon poly26(4);
+ poly26.ps[0] = Point(257.9431329624006, -143.3431551362948);
+ poly26.ps[1] = Point(257.9431329624006, -123.3431551362948);
+ poly26.ps[2] = Point(225.9431329624006, -123.3431551362948);
+ poly26.ps[3] = Point(225.9431329624006, -143.3431551362948);
+ new ShapeRef(router, poly26, 26);
+
+ Polygon poly27(4);
+ poly27.ps[0] = Point(354.4431329624006, -561.3431551372947);
+ poly27.ps[1] = Point(354.4431329624006, -541.3431551372947);
+ poly27.ps[2] = Point(322.4431329624006, -541.3431551372947);
+ poly27.ps[3] = Point(322.4431329624006, -561.3431551372947);
+ new ShapeRef(router, poly27, 27);
+
+ Polygon poly28(4);
+ poly28.ps[0] = Point(568.7288472481148, -651.8431551372947);
+ poly28.ps[1] = Point(568.7288472481148, -631.8431551372947);
+ poly28.ps[2] = Point(536.7288472481148, -631.8431551372947);
+ poly28.ps[3] = Point(536.7288472481148, -651.8431551372947);
+ new ShapeRef(router, poly28, 28);
+
+ Polygon poly29(4);
+ poly29.ps[0] = Point(-210.9735337052661, 120.6568448657052);
+ poly29.ps[1] = Point(-210.9735337052661, 152.6568448657052);
+ poly29.ps[2] = Point(-230.9735337052661, 152.6568448657052);
+ poly29.ps[3] = Point(-230.9735337052661, 120.6568448657052);
+ new ShapeRef(router, poly29, 29);
+
+ Polygon poly30(4);
+ poly30.ps[0] = Point(-210.9735337052661, -372.3431551372947);
+ poly30.ps[1] = Point(-210.9735337052661, -340.3431551372947);
+ poly30.ps[2] = Point(-230.9735337052661, -340.3431551372947);
+ poly30.ps[3] = Point(-230.9735337052661, -372.3431551372947);
+ new ShapeRef(router, poly30, 30);
+
+ Polygon poly31(4);
+ poly31.ps[0] = Point(1446.728847251115, 424.9901782000385);
+ poly31.ps[1] = Point(1446.728847251115, 444.9901782000385);
+ poly31.ps[2] = Point(1414.728847251115, 444.9901782000385);
+ poly31.ps[3] = Point(1414.728847251115, 424.9901782000385);
+ new ShapeRef(router, poly31, 31);
+
+ Polygon poly32(4);
+ poly32.ps[0] = Point(420.4431329624006, 424.9901782000385);
+ poly32.ps[1] = Point(420.4431329624006, 444.9901782000385);
+ poly32.ps[2] = Point(388.4431329624006, 444.9901782000385);
+ poly32.ps[3] = Point(388.4431329624006, 424.9901782000385);
+ new ShapeRef(router, poly32, 32);
+
+ Polygon poly33(4);
+ poly33.ps[0] = Point(447.4431329624006, 869.3235115333719);
+ poly33.ps[1] = Point(447.4431329624006, 901.3235115333719);
+ poly33.ps[2] = Point(427.4431329624006, 901.3235115333719);
+ poly33.ps[3] = Point(427.4431329624006, 869.3235115333719);
+ new ShapeRef(router, poly33, 33);
+
+ Polygon poly34(4);
+ poly34.ps[0] = Point(447.4431329624006, 578.9901782000385);
+ poly34.ps[1] = Point(447.4431329624006, 610.9901782000385);
+ poly34.ps[2] = Point(427.4431329624006, 610.9901782000385);
+ poly34.ps[3] = Point(427.4431329624006, 578.9901782000385);
+ new ShapeRef(router, poly34, 34);
+
+ Polygon poly35(4);
+ poly35.ps[0] = Point(-555.9508064345389, -439.3431551372947);
+ poly35.ps[1] = Point(-555.9508064345389, -377.3431551372947);
+ poly35.ps[2] = Point(-617.9508064345389, -377.3431551372947);
+ poly35.ps[3] = Point(-617.9508064345389, -439.3431551372947);
+ new ShapeRef(router, poly35, 35);
+
+ Polygon poly36(4);
+ poly36.ps[0] = Point(-189.9735337052661, -582.3431551372947);
+ poly36.ps[1] = Point(-189.9735337052661, -520.3431551372947);
+ poly36.ps[2] = Point(-251.9735337052661, -520.3431551372947);
+ poly36.ps[3] = Point(-251.9735337052661, -582.3431551372947);
+ new ShapeRef(router, poly36, 36);
+
+ Polygon poly37(4);
+ poly37.ps[0] = Point(468.4431329624006, -354.3431551372947);
+ poly37.ps[1] = Point(468.4431329624006, -292.3431551372947);
+ poly37.ps[2] = Point(406.4431329624006, -292.3431551372947);
+ poly37.ps[3] = Point(406.4431329624006, -354.3431551372947);
+ new ShapeRef(router, poly37, 37);
+
+ Polygon poly38(4);
+ poly38.ps[0] = Point(748.7288472481148, -549.3431551372947);
+ poly38.ps[1] = Point(748.7288472481148, -487.3431551372947);
+ poly38.ps[2] = Point(686.7288472481148, -487.3431551372947);
+ poly38.ps[3] = Point(686.7288472481148, -549.3431551372947);
+ new ShapeRef(router, poly38, 38);
+
+ Polygon poly39(4);
+ poly39.ps[0] = Point(649.7288472481148, -233.3431551362948);
+ poly39.ps[1] = Point(649.7288472481148, -171.3431551362948);
+ poly39.ps[2] = Point(587.7288472481148, -171.3431551362948);
+ poly39.ps[3] = Point(587.7288472481148, -233.3431551362948);
+ new ShapeRef(router, poly39, 39);
+
+ Polygon poly40(4);
+ poly40.ps[0] = Point(189.7764662957339, 72.65684486570521);
+ poly40.ps[1] = Point(189.7764662957339, 134.6568448657052);
+ poly40.ps[2] = Point(127.7764662957339, 134.6568448657052);
+ poly40.ps[3] = Point(127.7764662957339, 72.65684486570521);
+ new ShapeRef(router, poly40, 40);
+
+ Polygon poly41(4);
+ poly41.ps[0] = Point(-189.9735337052661, -266.3431551362947);
+ poly41.ps[1] = Point(-189.9735337052661, -204.3431551362947);
+ poly41.ps[2] = Point(-251.9735337052661, -204.3431551362947);
+ poly41.ps[3] = Point(-251.9735337052661, -266.3431551362947);
+ new ShapeRef(router, poly41, 41);
+#endif
+
+ Polygon poly42(4);
+ poly42.ps[0] = Point(189.7764662957339, 215.2282734371338);
+ poly42.ps[1] = Point(189.7764662957339, 277.2282734371338);
+ poly42.ps[2] = Point(127.7764662957339, 277.2282734371338);
+ poly42.ps[3] = Point(127.7764662957339, 215.2282734371338);
+ new ShapeRef(router, poly42, 42);
+
+#ifdef ALL
+ Polygon poly43(4);
+ poly43.ps[0] = Point(748.7288472481148, 215.2282734371338);
+ poly43.ps[1] = Point(748.7288472481148, 277.2282734371338);
+ poly43.ps[2] = Point(686.7288472481148, 277.2282734371338);
+ poly43.ps[3] = Point(686.7288472481148, 215.2282734371338);
+ new ShapeRef(router, poly43, 43);
+
+ Polygon poly44(4);
+ poly44.ps[0] = Point(1329.728847251115, 215.2282734371338);
+ poly44.ps[1] = Point(1329.728847251115, 277.2282734371338);
+ poly44.ps[2] = Point(1267.728847251115, 277.2282734371338);
+ poly44.ps[3] = Point(1267.728847251115, 215.2282734371338);
+ new ShapeRef(router, poly44, 44);
+
+ Polygon poly45(4);
+ poly45.ps[0] = Point(-594.9508064345389, 215.2282734371338);
+ poly45.ps[1] = Point(-594.9508064345389, 277.2282734371338);
+ poly45.ps[2] = Point(-656.9508064345389, 277.2282734371338);
+ poly45.ps[3] = Point(-656.9508064345389, 215.2282734371338);
+ new ShapeRef(router, poly45, 45);
+
+ Polygon poly46(4);
+ poly46.ps[0] = Point(-522.9508064345389, 277.2282734381338);
+ poly46.ps[1] = Point(-522.9508064345389, 339.2282734381338);
+ poly46.ps[2] = Point(-584.9508064345389, 339.2282734381338);
+ poly46.ps[3] = Point(-584.9508064345389, 277.2282734381338);
+ new ShapeRef(router, poly46, 46);
+
+ Polygon poly47(4);
+ poly47.ps[0] = Point(0.776466294733865, 277.2282734381338);
+ poly47.ps[1] = Point(0.776466294733865, 339.2282734381338);
+ poly47.ps[2] = Point(-61.22353370526614, 339.2282734381338);
+ poly47.ps[3] = Point(-61.22353370526614, 277.2282734381338);
+ new ShapeRef(router, poly47, 47);
+
+ Polygon poly48(4);
+ poly48.ps[0] = Point(272.9431329624006, 277.2282734381338);
+ poly48.ps[1] = Point(272.9431329624006, 339.2282734381338);
+ poly48.ps[2] = Point(210.9431329624006, 339.2282734381338);
+ poly48.ps[3] = Point(210.9431329624006, 277.2282734381338);
+ new ShapeRef(router, poly48, 48);
+
+ Polygon poly49(4);
+ poly49.ps[0] = Point(550.7288472481148, 403.9901782000385);
+ poly49.ps[1] = Point(550.7288472481148, 465.9901782000385);
+ poly49.ps[2] = Point(488.7288472481148, 465.9901782000385);
+ poly49.ps[3] = Point(488.7288472481148, 403.9901782000385);
+ new ShapeRef(router, poly49, 49);
+
+ Polygon poly50(4);
+ poly50.ps[0] = Point(682.7288472481148, 887.3235115333719);
+ poly50.ps[1] = Point(682.7288472481148, 949.3235115333719);
+ poly50.ps[2] = Point(620.7288472481148, 949.3235115333719);
+ poly50.ps[3] = Point(620.7288472481148, 887.3235115333719);
+ new ShapeRef(router, poly50, 50);
+
+ Polygon poly51(4);
+ poly51.ps[0] = Point(715.7288472481148, 277.2282734381338);
+ poly51.ps[1] = Point(715.7288472481148, 339.2282734381338);
+ poly51.ps[2] = Point(653.7288472481148, 339.2282734381338);
+ poly51.ps[3] = Point(653.7288472481148, 277.2282734381338);
+ new ShapeRef(router, poly51, 51);
+
+ Polygon poly52(4);
+ poly52.ps[0] = Point(812.7288472481148, 403.9901782000385);
+ poly52.ps[1] = Point(812.7288472481148, 465.9901782000385);
+ poly52.ps[2] = Point(750.7288472481148, 465.9901782000385);
+ poly52.ps[3] = Point(750.7288472481148, 403.9901782000385);
+ new ShapeRef(router, poly52, 52);
+
+ Polygon poly53(4);
+ poly53.ps[0] = Point(1160.728847250115, 277.2282734381338);
+ poly53.ps[1] = Point(1160.728847250115, 339.2282734381338);
+ poly53.ps[2] = Point(1098.728847250115, 339.2282734381338);
+ poly53.ps[3] = Point(1098.728847250115, 277.2282734381338);
+ new ShapeRef(router, poly53, 53);
+
+ Polygon poly54(4);
+ poly54.ps[0] = Point(1362.728847251115, 403.9901782000385);
+ poly54.ps[1] = Point(1362.728847251115, 465.9901782000385);
+ poly54.ps[2] = Point(1300.728847251115, 465.9901782000385);
+ poly54.ps[3] = Point(1300.728847251115, 403.9901782000385);
+ new ShapeRef(router, poly54, 54);
+
+ Polygon poly55(4);
+ poly55.ps[0] = Point(1542.728847251115, 403.9901782000385);
+ poly55.ps[1] = Point(1542.728847251115, 465.9901782000385);
+ poly55.ps[2] = Point(1480.728847251115, 465.9901782000385);
+ poly55.ps[3] = Point(1480.728847251115, 403.9901782000385);
+ new ShapeRef(router, poly55, 55);
+
+ Polygon poly56(4);
+ poly56.ps[0] = Point(-485.9508064345389, 236.2282734371338);
+ poly56.ps[1] = Point(-485.9508064345389, 256.2282734371338);
+ poly56.ps[2] = Point(-517.9508064345389, 256.2282734371338);
+ poly56.ps[3] = Point(-517.9508064345389, 236.2282734371338);
+ new ShapeRef(router, poly56, 56);
+#endif
+
+ Polygon poly57(4);
+ poly57.ps[0] = Point(-264.9508064325389, 1093.228273437134);
+ poly57.ps[1] = Point(-264.9508064325389, 1113.228273437134);
+ poly57.ps[2] = Point(-296.9508064325389, 1113.228273437134);
+ poly57.ps[3] = Point(-296.9508064325389, 1093.228273437134);
+ new ShapeRef(router, poly57, 57);
+
+#ifdef ALL
+ Polygon poly58(4);
+ poly58.ps[0] = Point(-119.8902003719328, 990.3235115333719);
+ poly58.ps[1] = Point(-119.8902003719328, 1052.323511533372);
+ poly58.ps[2] = Point(-181.8902003719328, 1052.323511533372);
+ poly58.ps[3] = Point(-181.8902003719328, 990.3235115333719);
+ new ShapeRef(router, poly58, 58);
+#endif
+
+ Polygon poly59(4);
+ poly59.ps[0] = Point(-119.8902003719328, 765.3235115333719);
+ poly59.ps[1] = Point(-119.8902003719328, 827.3235115333719);
+ poly59.ps[2] = Point(-181.8902003719328, 827.3235115333719);
+ poly59.ps[3] = Point(-181.8902003719328, 765.3235115333719);
+ new ShapeRef(router, poly59, 59);
+
+#ifdef ALL
+ Polygon poly60(4);
+ poly60.ps[0] = Point(402.4431329624006, 765.3235115333719);
+ poly60.ps[1] = Point(402.4431329624006, 827.3235115333719);
+ poly60.ps[2] = Point(340.4431329624006, 827.3235115333719);
+ poly60.ps[3] = Point(340.4431329624006, 765.3235115333719);
+ new ShapeRef(router, poly60, 60);
+
+ Polygon poly61(4);
+ poly61.ps[0] = Point(925.7288472491148, 887.3235115333719);
+ poly61.ps[1] = Point(925.7288472491148, 949.3235115333719);
+ poly61.ps[2] = Point(863.7288472491148, 949.3235115333719);
+ poly61.ps[3] = Point(863.7288472491148, 887.3235115333719);
+ new ShapeRef(router, poly61, 61);
+
+ Polygon poly62(4);
+ poly62.ps[0] = Point(1509.728847251115, 887.3235115333719);
+ poly62.ps[1] = Point(1509.728847251115, 949.3235115333719);
+ poly62.ps[2] = Point(1447.728847251115, 949.3235115333719);
+ poly62.ps[3] = Point(1447.728847251115, 887.3235115333719);
+ new ShapeRef(router, poly62, 62);
+
+ Polygon poly63(4);
+ poly63.ps[0] = Point(1428.728847251115, 530.9901782000385);
+ poly63.ps[1] = Point(1428.728847251115, 592.9901782000385);
+ poly63.ps[2] = Point(1366.728847251115, 592.9901782000385);
+ poly63.ps[3] = Point(1366.728847251115, 530.9901782000385);
+ new ShapeRef(router, poly63, 63);
+
+ Polygon poly64(4);
+ poly64.ps[0] = Point(1127.728847250115, 530.9901782000385);
+ poly64.ps[1] = Point(1127.728847250115, 592.9901782000385);
+ poly64.ps[2] = Point(1065.728847250115, 592.9901782000385);
+ poly64.ps[3] = Point(1065.728847250115, 530.9901782000385);
+ new ShapeRef(router, poly64, 64);
+
+ Polygon poly65(4);
+ poly65.ps[0] = Point(1024.728847249115, 821.3235115333719);
+ poly65.ps[1] = Point(1024.728847249115, 883.3235115333719);
+ poly65.ps[2] = Point(962.7288472491148, 883.3235115333719);
+ poly65.ps[3] = Point(962.7288472491148, 821.3235115333719);
+ new ShapeRef(router, poly65, 65);
+
+ Polygon poly66(4);
+ poly66.ps[0] = Point(1461.728847251115, 821.3235115333719);
+ poly66.ps[1] = Point(1461.728847251115, 883.3235115333719);
+ poly66.ps[2] = Point(1399.728847251115, 883.3235115333719);
+ poly66.ps[3] = Point(1399.728847251115, 821.3235115333719);
+ new ShapeRef(router, poly66, 66);
+
+ Polygon poly67(4);
+ poly67.ps[0] = Point(1024.728847249115, 1023.323511533372);
+ poly67.ps[1] = Point(1024.728847249115, 1085.323511533372);
+ poly67.ps[2] = Point(962.7288472491148, 1085.323511533372);
+ poly67.ps[3] = Point(962.7288472491148, 1023.323511533372);
+ new ShapeRef(router, poly67, 67);
+
+ Polygon poly68(4);
+ poly68.ps[0] = Point(1461.728847251115, 1023.323511533372);
+ poly68.ps[1] = Point(1461.728847251115, 1085.323511533372);
+ poly68.ps[2] = Point(1399.728847251115, 1085.323511533372);
+ poly68.ps[3] = Point(1399.728847251115, 1023.323511533372);
+ new ShapeRef(router, poly68, 68);
+
+ Polygon poly69(4);
+ poly69.ps[0] = Point(305.9431329624006, 1120.323511533372);
+ poly69.ps[1] = Point(305.9431329624006, 1182.323511533372);
+ poly69.ps[2] = Point(243.9431329624006, 1182.323511533372);
+ poly69.ps[3] = Point(243.9431329624006, 1120.323511533372);
+ new ShapeRef(router, poly69, 69);
+
+ Polygon poly70(4);
+ poly70.ps[0] = Point(682.7288472481148, 1293.723511533372);
+ poly70.ps[1] = Point(682.7288472481148, 1355.723511533372);
+ poly70.ps[2] = Point(620.7288472481148, 1355.723511533372);
+ poly70.ps[3] = Point(620.7288472481148, 1293.723511533372);
+ new ShapeRef(router, poly70, 70);
+
+ Polygon poly71(4);
+ poly71.ps[0] = Point(925.7288472491148, 1293.723511533372);
+ poly71.ps[1] = Point(925.7288472491148, 1355.723511533372);
+ poly71.ps[2] = Point(863.7288472491148, 1355.723511533372);
+ poly71.ps[3] = Point(863.7288472491148, 1293.723511533372);
+ new ShapeRef(router, poly71, 71);
+
+ Polygon poly72(4);
+ poly72.ps[0] = Point(1509.728847251115, 1293.723511533372);
+ poly72.ps[1] = Point(1509.728847251115, 1355.723511533372);
+ poly72.ps[2] = Point(1447.728847251115, 1355.723511533372);
+ poly72.ps[3] = Point(1447.728847251115, 1293.723511533372);
+ new ShapeRef(router, poly72, 72);
+
+ Polygon poly73(4);
+ poly73.ps[0] = Point(-410.9508064335388, 1449.609225819086);
+ poly73.ps[1] = Point(-410.9508064335388, 1511.609225819086);
+ poly73.ps[2] = Point(-472.9508064335388, 1511.609225819086);
+ poly73.ps[3] = Point(-472.9508064335388, 1449.609225819086);
+ new ShapeRef(router, poly73, 73);
+
+ Polygon poly74(4);
+ poly74.ps[0] = Point(66.77646629473389, 1449.609225819086);
+ poly74.ps[1] = Point(66.77646629473389, 1511.609225819086);
+ poly74.ps[2] = Point(4.776466294733893, 1511.609225819086);
+ poly74.ps[3] = Point(4.776466294733893, 1449.609225819086);
+ new ShapeRef(router, poly74, 74);
+
+ Polygon poly75(4);
+ poly75.ps[0] = Point(682.7288472481148, 1449.609225819086);
+ poly75.ps[1] = Point(682.7288472481148, 1511.609225819086);
+ poly75.ps[2] = Point(620.7288472481148, 1511.609225819086);
+ poly75.ps[3] = Point(620.7288472481148, 1449.609225819086);
+ new ShapeRef(router, poly75, 75);
+
+ Polygon poly76(4);
+ poly76.ps[0] = Point(925.7288472491148, 1449.609225819086);
+ poly76.ps[1] = Point(925.7288472491148, 1511.609225819086);
+ poly76.ps[2] = Point(863.7288472491148, 1511.609225819086);
+ poly76.ps[3] = Point(863.7288472491148, 1449.609225819086);
+ new ShapeRef(router, poly76, 76);
+
+ Polygon poly77(4);
+ poly77.ps[0] = Point(1509.728847251115, 1449.609225819086);
+ poly77.ps[1] = Point(1509.728847251115, 1511.609225819086);
+ poly77.ps[2] = Point(1447.728847251115, 1511.609225819086);
+ poly77.ps[3] = Point(1447.728847251115, 1449.609225819086);
+ new ShapeRef(router, poly77, 77);
+
+ Polygon poly78(4);
+ poly78.ps[0] = Point(-392.9508064335388, 394.2282734381338);
+ poly78.ps[1] = Point(-392.9508064335388, 414.2282734381338);
+ poly78.ps[2] = Point(-424.9508064335388, 414.2282734381338);
+ poly78.ps[3] = Point(-424.9508064335388, 394.2282734381338);
+ new ShapeRef(router, poly78, 78);
+
+ Polygon poly79(4);
+ poly79.ps[0] = Point(-140.8902003719328, 902.3235115333719);
+ poly79.ps[1] = Point(-140.8902003719328, 934.3235115333719);
+ poly79.ps[2] = Point(-160.8902003719328, 934.3235115333719);
+ poly79.ps[3] = Point(-160.8902003719328, 902.3235115333719);
+ new ShapeRef(router, poly79, 79);
+
+ Polygon poly80(4);
+ poly80.ps[0] = Point(18.77646629473389, 786.3235115333719);
+ poly80.ps[1] = Point(18.77646629473389, 806.3235115333719);
+ poly80.ps[2] = Point(-13.22353370526611, 806.3235115333719);
+ poly80.ps[3] = Point(-13.22353370526611, 786.3235115333719);
+ new ShapeRef(router, poly80, 80);
+
+ Polygon poly81(4);
+ poly81.ps[0] = Point(453.4431329624006, 705.9901782000385);
+ poly81.ps[1] = Point(453.4431329624006, 725.9901782000385);
+ poly81.ps[2] = Point(421.4431329624006, 725.9901782000385);
+ poly81.ps[3] = Point(421.4431329624006, 705.9901782000385);
+ new ShapeRef(router, poly81, 81);
+
+ Polygon poly82(4);
+ poly82.ps[0] = Point(453.4431329624006, 941.3235115333719);
+ poly82.ps[1] = Point(453.4431329624006, 961.3235115333719);
+ poly82.ps[2] = Point(421.4431329624006, 961.3235115333719);
+ poly82.ps[3] = Point(421.4431329624006, 941.3235115333719);
+ new ShapeRef(router, poly82, 82);
+
+ Polygon poly83(4);
+ poly83.ps[0] = Point(830.7288472481148, 929.3235115333719);
+ poly83.ps[1] = Point(830.7288472481148, 949.3235115333719);
+ poly83.ps[2] = Point(798.7288472481148, 949.3235115333719);
+ poly83.ps[3] = Point(798.7288472481148, 929.3235115333719);
+ new ShapeRef(router, poly83, 83);
+
+ Polygon poly84(4);
+ poly84.ps[0] = Point(830.7288472481148, 887.3235115333719);
+ poly84.ps[1] = Point(830.7288472481148, 907.3235115333719);
+ poly84.ps[2] = Point(798.7288472481148, 907.3235115333719);
+ poly84.ps[3] = Point(798.7288472481148, 887.3235115333719);
+ new ShapeRef(router, poly84, 84);
+
+ Polygon poly85(4);
+ poly85.ps[0] = Point(284.9431329624006, 1071.323511533372);
+ poly85.ps[1] = Point(284.9431329624006, 1103.323511533372);
+ poly85.ps[2] = Point(264.9431329624006, 1103.323511533372);
+ poly85.ps[3] = Point(264.9431329624006, 1071.323511533372);
+ new ShapeRef(router, poly85, 85);
+
+ Polygon poly86(4);
+ poly86.ps[0] = Point(453.4431329624006, 1314.723511533372);
+ poly86.ps[1] = Point(453.4431329624006, 1334.723511533372);
+ poly86.ps[2] = Point(421.4431329624006, 1334.723511533372);
+ poly86.ps[3] = Point(421.4431329624006, 1314.723511533372);
+ new ShapeRef(router, poly86, 86);
+
+ Polygon poly87(4);
+ poly87.ps[0] = Point(830.7288472481148, 1314.723511533372);
+ poly87.ps[1] = Point(830.7288472481148, 1334.723511533372);
+ poly87.ps[2] = Point(798.7288472481148, 1334.723511533372);
+ poly87.ps[3] = Point(798.7288472481148, 1314.723511533372);
+ new ShapeRef(router, poly87, 87);
+
+ Polygon poly88(4);
+ poly88.ps[0] = Point(-47.22353370526614, 1470.609225819086);
+ poly88.ps[1] = Point(-47.22353370526614, 1490.609225819086);
+ poly88.ps[2] = Point(-79.22353370526614, 1490.609225819086);
+ poly88.ps[3] = Point(-79.22353370526614, 1470.609225819086);
+ new ShapeRef(router, poly88, 88);
+
+ Polygon poly89(4);
+ poly89.ps[0] = Point(453.4431329624006, 1470.609225819086);
+ poly89.ps[1] = Point(453.4431329624006, 1490.609225819086);
+ poly89.ps[2] = Point(421.4431329624006, 1490.609225819086);
+ poly89.ps[3] = Point(421.4431329624006, 1470.609225819086);
+ new ShapeRef(router, poly89, 89);
+
+ Polygon poly90(4);
+ poly90.ps[0] = Point(830.7288472481148, 1449.609225819086);
+ poly90.ps[1] = Point(830.7288472481148, 1469.609225819086);
+ poly90.ps[2] = Point(798.7288472481148, 1469.609225819086);
+ poly90.ps[3] = Point(798.7288472481148, 1449.609225819086);
+ new ShapeRef(router, poly90, 90);
+
+ Polygon poly91(4);
+ poly91.ps[0] = Point(830.7288472481148, 1491.609225819086);
+ poly91.ps[1] = Point(830.7288472481148, 1511.609225819086);
+ poly91.ps[2] = Point(798.7288472481148, 1511.609225819086);
+ poly91.ps[3] = Point(798.7288472481148, 1491.609225819086);
+ new ShapeRef(router, poly91, 91);
+
+ Polygon poly92(4);
+ poly92.ps[0] = Point(1281.728847251115, 842.3235115333719);
+ poly92.ps[1] = Point(1281.728847251115, 862.3235115333719);
+ poly92.ps[2] = Point(1249.728847251115, 862.3235115333719);
+ poly92.ps[3] = Point(1249.728847251115, 842.3235115333719);
+ new ShapeRef(router, poly92, 92);
+
+ Polygon poly93(4);
+ poly93.ps[0] = Point(1281.728847251115, 645.9901782000385);
+ poly93.ps[1] = Point(1281.728847251115, 665.9901782000385);
+ poly93.ps[2] = Point(1249.728847251115, 665.9901782000385);
+ poly93.ps[3] = Point(1249.728847251115, 645.9901782000385);
+ new ShapeRef(router, poly93, 93);
+
+ Polygon poly94(4);
+ poly94.ps[0] = Point(1178.728847250115, 948.3235115333719);
+ poly94.ps[1] = Point(1178.728847250115, 968.3235115333719);
+ poly94.ps[2] = Point(1146.728847250115, 968.3235115333719);
+ poly94.ps[3] = Point(1146.728847250115, 948.3235115333719);
+ new ShapeRef(router, poly94, 94);
+
+ Polygon poly95(4);
+ poly95.ps[0] = Point(1178.728847250115, 1023.323511533372);
+ poly95.ps[1] = Point(1178.728847250115, 1043.323511533372);
+ poly95.ps[2] = Point(1146.728847250115, 1043.323511533372);
+ poly95.ps[3] = Point(1146.728847250115, 1023.323511533372);
+ new ShapeRef(router, poly95, 95);
+
+ Polygon poly96(4);
+ poly96.ps[0] = Point(1281.728847251115, 1043.323511533372);
+ poly96.ps[1] = Point(1281.728847251115, 1063.323511533372);
+ poly96.ps[2] = Point(1249.728847251115, 1063.323511533372);
+ poly96.ps[3] = Point(1249.728847251115, 1043.323511533372);
+ new ShapeRef(router, poly96, 96);
+
+ Polygon poly97(4);
+ poly97.ps[0] = Point(1281.728847251115, 1085.323511533372);
+ poly97.ps[1] = Point(1281.728847251115, 1105.323511533372);
+ poly97.ps[2] = Point(1249.728847251115, 1105.323511533372);
+ poly97.ps[3] = Point(1249.728847251115, 1085.323511533372);
+ new ShapeRef(router, poly97, 97);
+
+ Polygon poly98(4);
+ poly98.ps[0] = Point(1281.728847251115, 1257.323511533372);
+ poly98.ps[1] = Point(1281.728847251115, 1277.323511533372);
+ poly98.ps[2] = Point(1249.728847251115, 1277.323511533372);
+ poly98.ps[3] = Point(1249.728847251115, 1257.323511533372);
+ new ShapeRef(router, poly98, 98);
+
+ Polygon poly99(4);
+ poly99.ps[0] = Point(1281.728847251115, 1413.323511533372);
+ poly99.ps[1] = Point(1281.728847251115, 1433.323511533372);
+ poly99.ps[2] = Point(1249.728847251115, 1433.323511533372);
+ poly99.ps[3] = Point(1249.728847251115, 1413.323511533372);
+ new ShapeRef(router, poly99, 99);
+
+ Polygon poly100(4);
+ poly100.ps[0] = Point(-27.22353370526614, 1116.323511533372);
+ poly100.ps[1] = Point(-27.22353370526614, 1160.323511533372);
+ poly100.ps[2] = Point(-157.2235337052661, 1160.323511533372);
+ poly100.ps[3] = Point(-157.2235337052661, 1116.323511533372);
+ new ShapeRef(router, poly100, 100);
+
+ Polygon poly101(4);
+ poly101.ps[0] = Point(116.7764662947339, -149.3431551362948);
+ poly101.ps[1] = Point(116.7764662947339, -117.3431551362948);
+ poly101.ps[2] = Point(96.77646629473389, -117.3431551362948);
+ poly101.ps[3] = Point(96.77646629473389, -149.3431551362948);
+ new ShapeRef(router, poly101, 101);
+
+ Polygon poly102(4);
+ poly102.ps[0] = Point(865.7288472481148, 457.9901782000385);
+ poly102.ps[1] = Point(865.7288472481148, 477.9901782000385);
+ poly102.ps[2] = Point(833.7288472481148, 477.9901782000385);
+ poly102.ps[3] = Point(833.7288472481148, 457.9901782000385);
+ new ShapeRef(router, poly102, 102);
+
+ Polygon poly103(4);
+ poly103.ps[0] = Point(116.7764662947339, -47.34315513529478);
+ poly103.ps[1] = Point(116.7764662947339, -15.34315513529478);
+ poly103.ps[2] = Point(96.77646629473389, -15.34315513529478);
+ poly103.ps[3] = Point(96.77646629473389, -47.34315513529478);
+ new ShapeRef(router, poly103, 103);
+
+ Polygon poly104(4);
+ poly104.ps[0] = Point(943.7288472491148, 457.9901782000385);
+ poly104.ps[1] = Point(943.7288472491148, 477.9901782000385);
+ poly104.ps[2] = Point(911.7288472491148, 477.9901782000385);
+ poly104.ps[3] = Point(911.7288472491148, 457.9901782000385);
+ new ShapeRef(router, poly104, 104);
+
+ Polygon poly105(4);
+ poly105.ps[0] = Point(116.7764662947339, 54.65684486570521);
+ poly105.ps[1] = Point(116.7764662947339, 86.65684486570521);
+ poly105.ps[2] = Point(96.77646629473389, 86.65684486570521);
+ poly105.ps[3] = Point(96.77646629473389, 54.65684486570521);
+ new ShapeRef(router, poly105, 105);
+
+ Polygon poly106(4);
+ poly106.ps[0] = Point(1042.728847249115, 457.9901782000385);
+ poly106.ps[1] = Point(1042.728847249115, 477.9901782000385);
+ poly106.ps[2] = Point(1010.728847249115, 477.9901782000385);
+ poly106.ps[3] = Point(1010.728847249115, 457.9901782000385);
+ new ShapeRef(router, poly106, 106);
+
+ Polygon poly107(4);
+ poly107.ps[0] = Point(257.9431329624006, -41.34315513529478);
+ poly107.ps[1] = Point(257.9431329624006, -21.34315513529478);
+ poly107.ps[2] = Point(225.9431329624006, -21.34315513529478);
+ poly107.ps[3] = Point(225.9431329624006, -41.34315513529478);
+ new ShapeRef(router, poly107, 107);
+
+ Polygon poly108(4);
+ poly108.ps[0] = Point(943.7288472491148, 364.561606771467);
+ poly108.ps[1] = Point(943.7288472491148, 384.561606771467);
+ poly108.ps[2] = Point(911.7288472491148, 384.561606771467);
+ poly108.ps[3] = Point(911.7288472491148, 364.561606771467);
+ new ShapeRef(router, poly108, 108);
+
+ Polygon poly109(4);
+ poly109.ps[0] = Point(1178.728847250115, 1065.323511533372);
+ poly109.ps[1] = Point(1178.728847250115, 1085.323511533372);
+ poly109.ps[2] = Point(1146.728847250115, 1085.323511533372);
+ poly109.ps[3] = Point(1146.728847250115, 1065.323511533372);
+ new ShapeRef(router, poly109, 109);
+
+ Polygon poly110(4);
+ poly110.ps[0] = Point(257.9431329624006, 60.65684486570521);
+ poly110.ps[1] = Point(257.9431329624006, 80.65684486570521);
+ poly110.ps[2] = Point(225.9431329624006, 80.65684486570521);
+ poly110.ps[3] = Point(225.9431329624006, 60.65684486570521);
+ new ShapeRef(router, poly110, 110);
+
+ Polygon poly111(4);
+ poly111.ps[0] = Point(1042.728847249115, 364.561606771467);
+ poly111.ps[1] = Point(1042.728847249115, 384.561606771467);
+ poly111.ps[2] = Point(1010.728847249115, 384.561606771467);
+ poly111.ps[3] = Point(1010.728847249115, 364.561606771467);
+ new ShapeRef(router, poly111, 111);
+
+ Polygon poly112(4);
+ poly112.ps[0] = Point(988.7288472491148, 176.2282734371338);
+ poly112.ps[1] = Point(988.7288472491148, 236.2282734371338);
+ poly112.ps[2] = Point(932.7288472491148, 236.2282734371338);
+ poly112.ps[3] = Point(932.7288472491148, 176.2282734371338);
+ new ShapeRef(router, poly112, 112);
+
+ Polygon poly113(4);
+ poly113.ps[0] = Point(877.7288472481148, 304.561606771467);
+ poly113.ps[1] = Point(877.7288472481148, 364.561606771467);
+ poly113.ps[2] = Point(821.7288472481148, 364.561606771467);
+ poly113.ps[3] = Point(821.7288472481148, 304.561606771467);
+ new ShapeRef(router, poly113, 113);
+
+ Polygon poly114(4);
+ poly114.ps[0] = Point(646.7288472481148, 364.9901782000385);
+ poly114.ps[1] = Point(646.7288472481148, 424.9901782000385);
+ poly114.ps[2] = Point(590.7288472481148, 424.9901782000385);
+ poly114.ps[3] = Point(590.7288472481148, 364.9901782000385);
+ new ShapeRef(router, poly114, 114);
+
+ Polygon poly115(4);
+ poly115.ps[0] = Point(-252.9508064325389, 316.2282734371338);
+ poly115.ps[1] = Point(-252.9508064325389, 376.2282734371338);
+ poly115.ps[2] = Point(-308.9508064325389, 376.2282734371338);
+ poly115.ps[3] = Point(-308.9508064325389, 316.2282734371338);
+ new ShapeRef(router, poly115, 115);
+
+ Polygon poly116(4);
+ poly116.ps[0] = Point(-252.9508064325389, 391.2282734371338);
+ poly116.ps[1] = Point(-252.9508064325389, 451.2282734371338);
+ poly116.ps[2] = Point(-308.9508064325389, 451.2282734371338);
+ poly116.ps[3] = Point(-308.9508064325389, 391.2282734371338);
+ new ShapeRef(router, poly116, 116);
+
+ Polygon poly117(4);
+ poly117.ps[0] = Point(-252.9508064325389, 466.2282734371338);
+ poly117.ps[1] = Point(-252.9508064325389, 526.2282734371338);
+ poly117.ps[2] = Point(-308.9508064325389, 526.2282734371338);
+ poly117.ps[3] = Point(-308.9508064325389, 466.2282734371338);
+ new ShapeRef(router, poly117, 117);
+
+ Polygon poly118(4);
+ poly118.ps[0] = Point(-252.9508064325389, 541.2282734371338);
+ poly118.ps[1] = Point(-252.9508064325389, 601.2282734371338);
+ poly118.ps[2] = Point(-308.9508064325389, 601.2282734371338);
+ poly118.ps[3] = Point(-308.9508064325389, 541.2282734371338);
+ new ShapeRef(router, poly118, 118);
+
+ Polygon poly119(4);
+ poly119.ps[0] = Point(-252.9508064325389, 616.2282734371338);
+ poly119.ps[1] = Point(-252.9508064325389, 676.2282734371338);
+ poly119.ps[2] = Point(-308.9508064325389, 676.2282734371338);
+ poly119.ps[3] = Point(-308.9508064325389, 616.2282734371338);
+ new ShapeRef(router, poly119, 119);
+
+ Polygon poly120(4);
+ poly120.ps[0] = Point(-252.9508064325389, 963.2282734371338);
+ poly120.ps[1] = Point(-252.9508064325389, 1023.228273437134);
+ poly120.ps[2] = Point(-308.9508064325389, 1023.228273437134);
+ poly120.ps[3] = Point(-308.9508064325389, 963.2282734371338);
+ new ShapeRef(router, poly120, 120);
+
+ Polygon poly121(4);
+ poly121.ps[0] = Point(-252.9508064325389, 691.2282734371338);
+ poly121.ps[1] = Point(-252.9508064325389, 751.2282734371338);
+ poly121.ps[2] = Point(-308.9508064325389, 751.2282734371338);
+ poly121.ps[3] = Point(-308.9508064325389, 691.2282734371338);
+ new ShapeRef(router, poly121, 121);
+
+ Polygon poly122(4);
+ poly122.ps[0] = Point(-252.9508064325389, 813.2282734371338);
+ poly122.ps[1] = Point(-252.9508064325389, 873.2282734371338);
+ poly122.ps[2] = Point(-308.9508064325389, 873.2282734371338);
+ poly122.ps[3] = Point(-308.9508064325389, 813.2282734371338);
+ new ShapeRef(router, poly122, 122);
+
+ Polygon poly123(4);
+ poly123.ps[0] = Point(-252.9508064325389, 888.2282734371338);
+ poly123.ps[1] = Point(-252.9508064325389, 948.2282734371338);
+ poly123.ps[2] = Point(-308.9508064325389, 948.2282734371338);
+ poly123.ps[3] = Point(-308.9508064325389, 888.2282734371338);
+ new ShapeRef(router, poly123, 123);
+
+ Polygon poly124(4);
+ poly124.ps[0] = Point(-252.9508064325389, 1038.228273437134);
+ poly124.ps[1] = Point(-252.9508064325389, 1098.228273437134);
+ poly124.ps[2] = Point(-308.9508064325389, 1098.228273437134);
+ poly124.ps[3] = Point(-308.9508064325389, 1038.228273437134);
+ new ShapeRef(router, poly124, 124);
+
+ Polygon poly125(4);
+ poly125.ps[0] = Point(-380.9508064335388, 142.2282734381338);
+ poly125.ps[1] = Point(-380.9508064335388, 202.2282734381338);
+ poly125.ps[2] = Point(-436.9508064335388, 202.2282734381338);
+ poly125.ps[3] = Point(-436.9508064335388, 142.2282734381338);
+ new ShapeRef(router, poly125, 125);
+
+ Polygon poly126(4);
+ poly126.ps[0] = Point(-380.9508064335388, 217.2282734381338);
+ poly126.ps[1] = Point(-380.9508064335388, 277.2282734381338);
+ poly126.ps[2] = Point(-436.9508064335388, 277.2282734381338);
+ poly126.ps[3] = Point(-436.9508064335388, 217.2282734381338);
+ new ShapeRef(router, poly126, 126);
+
+ Polygon poly127(4);
+ poly127.ps[0] = Point(-380.9508064335388, 339.2282734381338);
+ poly127.ps[1] = Point(-380.9508064335388, 399.2282734381338);
+ poly127.ps[2] = Point(-436.9508064335388, 399.2282734381338);
+ poly127.ps[3] = Point(-436.9508064335388, 339.2282734381338);
+ new ShapeRef(router, poly127, 127);
+
+ Polygon poly128(4);
+ poly128.ps[0] = Point(613.7288472481148, 176.2282734371338);
+ poly128.ps[1] = Point(613.7288472481148, 236.2282734371338);
+ poly128.ps[2] = Point(557.7288472481148, 236.2282734371338);
+ poly128.ps[3] = Point(557.7288472481148, 176.2282734371338);
+ new ShapeRef(router, poly128, 128);
+
+ Polygon poly129(4);
+ poly129.ps[0] = Point(803.7288472481148, -288.3431551362947);
+ poly129.ps[1] = Point(803.7288472481148, -248.3431551362947);
+ poly129.ps[2] = Point(727.7288472481148, -248.3431551362947);
+ poly129.ps[3] = Point(727.7288472481148, -288.3431551362947);
+ new ShapeRef(router, poly129, 129);
+
+ Polygon poly130(4);
+ poly130.ps[0] = Point(244.7764662957339, 149.6568448657052);
+ poly130.ps[1] = Point(244.7764662957339, 189.6568448657052);
+ poly130.ps[2] = Point(168.7764662957339, 189.6568448657052);
+ poly130.ps[3] = Point(168.7764662957339, 149.6568448657052);
+ new ShapeRef(router, poly130, 130);
+
+ Polygon poly131(4);
+ poly131.ps[0] = Point(269.9431329624006, -203.3431551362948);
+ poly131.ps[1] = Point(269.9431329624006, -143.3431551362948);
+ poly131.ps[2] = Point(213.9431329624006, -143.3431551362948);
+ poly131.ps[3] = Point(213.9431329624006, -203.3431551362948);
+ new ShapeRef(router, poly131, 131);
+
+ Polygon poly132(4);
+ poly132.ps[0] = Point(366.4431329624006, -621.3431551372947);
+ poly132.ps[1] = Point(366.4431329624006, -561.3431551372947);
+ poly132.ps[2] = Point(310.4431329624006, -561.3431551372947);
+ poly132.ps[3] = Point(310.4431329624006, -621.3431551372947);
+ new ShapeRef(router, poly132, 132);
+
+ Polygon poly133(4);
+ poly133.ps[0] = Point(580.7288472481148, -711.8431551372947);
+ poly133.ps[1] = Point(580.7288472481148, -651.8431551372947);
+ poly133.ps[2] = Point(524.7288472481148, -651.8431551372947);
+ poly133.ps[3] = Point(524.7288472481148, -711.8431551372947);
+ new ShapeRef(router, poly133, 133);
+
+ Polygon poly134(4);
+ poly134.ps[0] = Point(-230.9735337052661, 116.6568448657052);
+ poly134.ps[1] = Point(-230.9735337052661, 156.6568448657052);
+ poly134.ps[2] = Point(-306.9735337052662, 156.6568448657052);
+ poly134.ps[3] = Point(-306.9735337052662, 116.6568448657052);
+ new ShapeRef(router, poly134, 134);
+
+ Polygon poly135(4);
+ poly135.ps[0] = Point(-134.9735337052661, -376.3431551372947);
+ poly135.ps[1] = Point(-134.9735337052661, -336.3431551372947);
+ poly135.ps[2] = Point(-210.9735337052661, -336.3431551372947);
+ poly135.ps[3] = Point(-210.9735337052661, -376.3431551372947);
+ new ShapeRef(router, poly135, 135);
+
+ Polygon poly136(4);
+ poly136.ps[0] = Point(1458.728847251115, 364.9901782000385);
+ poly136.ps[1] = Point(1458.728847251115, 424.9901782000385);
+ poly136.ps[2] = Point(1402.728847251115, 424.9901782000385);
+ poly136.ps[3] = Point(1402.728847251115, 364.9901782000385);
+ new ShapeRef(router, poly136, 136);
+
+ Polygon poly137(4);
+ poly137.ps[0] = Point(432.4431329624006, 364.9901782000385);
+ poly137.ps[1] = Point(432.4431329624006, 424.9901782000385);
+ poly137.ps[2] = Point(376.4431329624006, 424.9901782000385);
+ poly137.ps[3] = Point(376.4431329624006, 364.9901782000385);
+ new ShapeRef(router, poly137, 137);
+
+ Polygon poly138(4);
+ poly138.ps[0] = Point(523.4431329624006, 865.3235115333719);
+ poly138.ps[1] = Point(523.4431329624006, 905.3235115333719);
+ poly138.ps[2] = Point(447.4431329624006, 905.3235115333719);
+ poly138.ps[3] = Point(447.4431329624006, 865.3235115333719);
+ new ShapeRef(router, poly138, 138);
+
+ Polygon poly139(4);
+ poly139.ps[0] = Point(523.4431329624006, 574.9901782000385);
+ poly139.ps[1] = Point(523.4431329624006, 614.9901782000385);
+ poly139.ps[2] = Point(447.4431329624006, 614.9901782000385);
+ poly139.ps[3] = Point(447.4431329624006, 574.9901782000385);
+ new ShapeRef(router, poly139, 139);
+
+ Polygon poly140(4);
+ poly140.ps[0] = Point(-473.9508064345389, 176.2282734371338);
+ poly140.ps[1] = Point(-473.9508064345389, 236.2282734371338);
+ poly140.ps[2] = Point(-529.9508064345389, 236.2282734371338);
+ poly140.ps[3] = Point(-529.9508064345389, 176.2282734371338);
+ new ShapeRef(router, poly140, 140);
+
+ Polygon poly141(4);
+ poly141.ps[0] = Point(-252.9508064325389, 1113.228273437134);
+ poly141.ps[1] = Point(-252.9508064325389, 1173.228273437134);
+ poly141.ps[2] = Point(-308.9508064325389, 1173.228273437134);
+ poly141.ps[3] = Point(-308.9508064325389, 1113.228273437134);
+ new ShapeRef(router, poly141, 141);
+
+ Polygon poly142(4);
+ poly142.ps[0] = Point(-380.9508064335388, 414.2282734381338);
+ poly142.ps[1] = Point(-380.9508064335388, 474.2282734381338);
+ poly142.ps[2] = Point(-436.9508064335388, 474.2282734381338);
+ poly142.ps[3] = Point(-436.9508064335388, 414.2282734381338);
+ new ShapeRef(router, poly142, 142);
+
+ Polygon poly143(4);
+ poly143.ps[0] = Point(-64.89020037193279, 898.3235115333719);
+ poly143.ps[1] = Point(-64.89020037193279, 938.3235115333719);
+ poly143.ps[2] = Point(-140.8902003719328, 938.3235115333719);
+ poly143.ps[3] = Point(-140.8902003719328, 898.3235115333719);
+ new ShapeRef(router, poly143, 143);
+
+ Polygon poly144(4);
+ poly144.ps[0] = Point(30.77646629473389, 726.3235115333719);
+ poly144.ps[1] = Point(30.77646629473389, 786.3235115333719);
+ poly144.ps[2] = Point(-25.22353370526611, 786.3235115333719);
+ poly144.ps[3] = Point(-25.22353370526611, 726.3235115333719);
+ new ShapeRef(router, poly144, 144);
+
+ Polygon poly145(4);
+ poly145.ps[0] = Point(465.4431329624006, 645.9901782000385);
+ poly145.ps[1] = Point(465.4431329624006, 705.9901782000385);
+ poly145.ps[2] = Point(409.4431329624006, 705.9901782000385);
+ poly145.ps[3] = Point(409.4431329624006, 645.9901782000385);
+ new ShapeRef(router, poly145, 145);
+
+ Polygon poly146(4);
+ poly146.ps[0] = Point(465.4431329624006, 961.3235115333719);
+ poly146.ps[1] = Point(465.4431329624006, 1021.323511533372);
+ poly146.ps[2] = Point(409.4431329624006, 1021.323511533372);
+ poly146.ps[3] = Point(409.4431329624006, 961.3235115333719);
+ new ShapeRef(router, poly146, 146);
+
+ Polygon poly147(4);
+ poly147.ps[0] = Point(842.7288472481148, 949.3235115333719);
+ poly147.ps[1] = Point(842.7288472481148, 1009.323511533372);
+ poly147.ps[2] = Point(786.7288472481148, 1009.323511533372);
+ poly147.ps[3] = Point(786.7288472481148, 949.3235115333719);
+ new ShapeRef(router, poly147, 147);
+
+ Polygon poly148(4);
+ poly148.ps[0] = Point(842.7288472481148, 827.3235115333719);
+ poly148.ps[1] = Point(842.7288472481148, 887.3235115333719);
+ poly148.ps[2] = Point(786.7288472481148, 887.3235115333719);
+ poly148.ps[3] = Point(786.7288472481148, 827.3235115333719);
+ new ShapeRef(router, poly148, 148);
+
+ Polygon poly149(4);
+ poly149.ps[0] = Point(360.9431329624006, 1067.323511533372);
+ poly149.ps[1] = Point(360.9431329624006, 1107.323511533372);
+ poly149.ps[2] = Point(284.9431329624006, 1107.323511533372);
+ poly149.ps[3] = Point(284.9431329624006, 1067.323511533372);
+ new ShapeRef(router, poly149, 149);
+
+ Polygon poly150(4);
+ poly150.ps[0] = Point(465.4431329624006, 1254.723511533372);
+ poly150.ps[1] = Point(465.4431329624006, 1314.723511533372);
+ poly150.ps[2] = Point(409.4431329624006, 1314.723511533372);
+ poly150.ps[3] = Point(409.4431329624006, 1254.723511533372);
+ new ShapeRef(router, poly150, 150);
+
+ Polygon poly151(4);
+ poly151.ps[0] = Point(842.7288472481148, 1254.723511533372);
+ poly151.ps[1] = Point(842.7288472481148, 1314.723511533372);
+ poly151.ps[2] = Point(786.7288472481148, 1314.723511533372);
+ poly151.ps[3] = Point(786.7288472481148, 1254.723511533372);
+ new ShapeRef(router, poly151, 151);
+
+ Polygon poly152(4);
+ poly152.ps[0] = Point(-35.22353370526614, 1410.609225819086);
+ poly152.ps[1] = Point(-35.22353370526614, 1470.609225819086);
+ poly152.ps[2] = Point(-91.22353370526614, 1470.609225819086);
+ poly152.ps[3] = Point(-91.22353370526614, 1410.609225819086);
+ new ShapeRef(router, poly152, 152);
+
+ Polygon poly153(4);
+ poly153.ps[0] = Point(465.4431329624006, 1410.609225819086);
+ poly153.ps[1] = Point(465.4431329624006, 1470.609225819086);
+ poly153.ps[2] = Point(409.4431329624006, 1470.609225819086);
+ poly153.ps[3] = Point(409.4431329624006, 1410.609225819086);
+ new ShapeRef(router, poly153, 153);
+
+ Polygon poly154(4);
+ poly154.ps[0] = Point(842.7288472481148, 1389.609225819086);
+ poly154.ps[1] = Point(842.7288472481148, 1449.609225819086);
+ poly154.ps[2] = Point(786.7288472481148, 1449.609225819086);
+ poly154.ps[3] = Point(786.7288472481148, 1389.609225819086);
+ new ShapeRef(router, poly154, 154);
+
+ Polygon poly155(4);
+ poly155.ps[0] = Point(842.7288472481148, 1511.609225819086);
+ poly155.ps[1] = Point(842.7288472481148, 1571.609225819086);
+ poly155.ps[2] = Point(786.7288472481148, 1571.609225819086);
+ poly155.ps[3] = Point(786.7288472481148, 1511.609225819086);
+ new ShapeRef(router, poly155, 155);
+
+ Polygon poly156(4);
+ poly156.ps[0] = Point(1293.728847251115, 782.3235115333719);
+ poly156.ps[1] = Point(1293.728847251115, 842.3235115333719);
+ poly156.ps[2] = Point(1237.728847251115, 842.3235115333719);
+ poly156.ps[3] = Point(1237.728847251115, 782.3235115333719);
+ new ShapeRef(router, poly156, 156);
+
+ Polygon poly157(4);
+ poly157.ps[0] = Point(1293.728847251115, 585.9901782000385);
+ poly157.ps[1] = Point(1293.728847251115, 645.9901782000385);
+ poly157.ps[2] = Point(1237.728847251115, 645.9901782000385);
+ poly157.ps[3] = Point(1237.728847251115, 585.9901782000385);
+ new ShapeRef(router, poly157, 157);
+
+ Polygon poly158(4);
+ poly158.ps[0] = Point(1190.728847250115, 888.3235115333719);
+ poly158.ps[1] = Point(1190.728847250115, 948.3235115333719);
+ poly158.ps[2] = Point(1134.728847250115, 948.3235115333719);
+ poly158.ps[3] = Point(1134.728847250115, 888.3235115333719);
+ new ShapeRef(router, poly158, 158);
+
+ Polygon poly159(4);
+ poly159.ps[0] = Point(1190.728847250115, 963.3235115333719);
+ poly159.ps[1] = Point(1190.728847250115, 1023.323511533372);
+ poly159.ps[2] = Point(1134.728847250115, 1023.323511533372);
+ poly159.ps[3] = Point(1134.728847250115, 963.3235115333719);
+ new ShapeRef(router, poly159, 159);
+
+ Polygon poly160(4);
+ poly160.ps[0] = Point(1293.728847251115, 983.3235115333719);
+ poly160.ps[1] = Point(1293.728847251115, 1043.323511533372);
+ poly160.ps[2] = Point(1237.728847251115, 1043.323511533372);
+ poly160.ps[3] = Point(1237.728847251115, 983.3235115333719);
+ new ShapeRef(router, poly160, 160);
+
+ Polygon poly161(4);
+ poly161.ps[0] = Point(1293.728847251115, 1105.323511533372);
+ poly161.ps[1] = Point(1293.728847251115, 1165.323511533372);
+ poly161.ps[2] = Point(1237.728847251115, 1165.323511533372);
+ poly161.ps[3] = Point(1237.728847251115, 1105.323511533372);
+ new ShapeRef(router, poly161, 161);
+
+ Polygon poly162(4);
+ poly162.ps[0] = Point(1293.728847251115, 1197.323511533372);
+ poly162.ps[1] = Point(1293.728847251115, 1257.323511533372);
+ poly162.ps[2] = Point(1237.728847251115, 1257.323511533372);
+ poly162.ps[3] = Point(1237.728847251115, 1197.323511533372);
+ new ShapeRef(router, poly162, 162);
+
+ Polygon poly163(4);
+ poly163.ps[0] = Point(1293.728847251115, 1353.323511533372);
+ poly163.ps[1] = Point(1293.728847251115, 1413.323511533372);
+ poly163.ps[2] = Point(1237.728847251115, 1413.323511533372);
+ poly163.ps[3] = Point(1237.728847251115, 1353.323511533372);
+ new ShapeRef(router, poly163, 163);
+
+ Polygon poly164(4);
+ poly164.ps[0] = Point(96.77646629473389, -153.3431551362948);
+ poly164.ps[1] = Point(96.77646629473389, -113.3431551362948);
+ poly164.ps[2] = Point(20.77646629473389, -113.3431551362948);
+ poly164.ps[3] = Point(20.77646629473389, -153.3431551362948);
+ new ShapeRef(router, poly164, 164);
+
+ Polygon poly165(4);
+ poly165.ps[0] = Point(877.7288472481148, 477.9901782000385);
+ poly165.ps[1] = Point(877.7288472481148, 537.9901782000385);
+ poly165.ps[2] = Point(821.7288472481148, 537.9901782000385);
+ poly165.ps[3] = Point(821.7288472481148, 477.9901782000385);
+ new ShapeRef(router, poly165, 165);
+
+ Polygon poly166(4);
+ poly166.ps[0] = Point(96.77646629473389, -51.34315513529478);
+ poly166.ps[1] = Point(96.77646629473389, -11.34315513529478);
+ poly166.ps[2] = Point(20.77646629473389, -11.34315513529478);
+ poly166.ps[3] = Point(20.77646629473389, -51.34315513529478);
+ new ShapeRef(router, poly166, 166);
+
+ Polygon poly167(4);
+ poly167.ps[0] = Point(955.7288472491148, 477.9901782000385);
+ poly167.ps[1] = Point(955.7288472491148, 537.9901782000385);
+ poly167.ps[2] = Point(899.7288472491148, 537.9901782000385);
+ poly167.ps[3] = Point(899.7288472491148, 477.9901782000385);
+ new ShapeRef(router, poly167, 167);
+
+ Polygon poly168(4);
+ poly168.ps[0] = Point(96.77646629473389, 50.65684486570521);
+ poly168.ps[1] = Point(96.77646629473389, 90.65684486570521);
+ poly168.ps[2] = Point(20.77646629473389, 90.65684486570521);
+ poly168.ps[3] = Point(20.77646629473389, 50.65684486570521);
+ new ShapeRef(router, poly168, 168);
+
+ Polygon poly169(4);
+ poly169.ps[0] = Point(1054.728847249115, 477.9901782000385);
+ poly169.ps[1] = Point(1054.728847249115, 537.9901782000385);
+ poly169.ps[2] = Point(998.7288472491148, 537.9901782000385);
+ poly169.ps[3] = Point(998.7288472491148, 477.9901782000385);
+ new ShapeRef(router, poly169, 169);
+
+ Polygon poly170(4);
+ poly170.ps[0] = Point(269.9431329624006, -101.3431551352948);
+ poly170.ps[1] = Point(269.9431329624006, -41.34315513529478);
+ poly170.ps[2] = Point(213.9431329624006, -41.34315513529478);
+ poly170.ps[3] = Point(213.9431329624006, -101.3431551352948);
+ new ShapeRef(router, poly170, 170);
+
+ Polygon poly171(4);
+ poly171.ps[0] = Point(955.7288472491148, 304.561606771467);
+ poly171.ps[1] = Point(955.7288472491148, 364.561606771467);
+ poly171.ps[2] = Point(899.7288472491148, 364.561606771467);
+ poly171.ps[3] = Point(899.7288472491148, 304.561606771467);
+ new ShapeRef(router, poly171, 171);
+
+ Polygon poly172(4);
+ poly172.ps[0] = Point(1190.728847250115, 1085.323511533372);
+ poly172.ps[1] = Point(1190.728847250115, 1145.323511533372);
+ poly172.ps[2] = Point(1134.728847250115, 1145.323511533372);
+ poly172.ps[3] = Point(1134.728847250115, 1085.323511533372);
+ new ShapeRef(router, poly172, 172);
+
+ Polygon poly173(4);
+ poly173.ps[0] = Point(269.9431329624006, 0.6568448657052102);
+ poly173.ps[1] = Point(269.9431329624006, 60.65684486570521);
+ poly173.ps[2] = Point(213.9431329624006, 60.65684486570521);
+ poly173.ps[3] = Point(213.9431329624006, 0.6568448657052102);
+ new ShapeRef(router, poly173, 173);
+
+ Polygon poly174(4);
+ poly174.ps[0] = Point(1054.728847249115, 304.561606771467);
+ poly174.ps[1] = Point(1054.728847249115, 364.561606771467);
+ poly174.ps[2] = Point(998.7288472491148, 364.561606771467);
+ poly174.ps[3] = Point(998.7288472491148, 304.561606771467);
+ new ShapeRef(router, poly174, 174);
+
+ Polygon poly175(4);
+ poly175.ps[0] = Point(865.7288472481148, -473.8431551372947);
+ poly175.ps[1] = Point(865.7288472481148, -413.8431551372947);
+ poly175.ps[2] = Point(825.7288472481148, -413.8431551372947);
+ poly175.ps[3] = Point(825.7288472481148, -473.8431551372947);
+ new ShapeRef(router, poly175, 175);
+
+ Polygon poly176(4);
+ poly176.ps[0] = Point(575.7288472481148, -432.3431551372947);
+ poly176.ps[1] = Point(575.7288472481148, -392.3431551372947);
+ poly176.ps[2] = Point(515.7288472481148, -392.3431551372947);
+ poly176.ps[3] = Point(515.7288472481148, -432.3431551372947);
+ new ShapeRef(router, poly176, 176);
+
+ Polygon poly177(4);
+ poly177.ps[0] = Point(543.9431329624006, -276.3431551362947);
+ poly177.ps[1] = Point(543.9431329624006, -236.3431551362947);
+ poly177.ps[2] = Point(483.9431329624006, -236.3431551362947);
+ poly177.ps[3] = Point(483.9431329624006, -276.3431551362947);
+ new ShapeRef(router, poly177, 177);
+
+ Polygon poly178(4);
+ poly178.ps[0] = Point(261.9431329624006, -437.3431551372947);
+ poly178.ps[1] = Point(261.9431329624006, -397.3431551372947);
+ poly178.ps[2] = Point(201.9431329624006, -397.3431551372947);
+ poly178.ps[3] = Point(201.9431329624006, -437.3431551372947);
+ new ShapeRef(router, poly178, 178);
+
+ Polygon poly179(4);
+ poly179.ps[0] = Point(-243.0508064325388, 386.2282734371338);
+ poly179.ps[1] = Point(-243.0508064325388, 1103.228273437134);
+ poly179.ps[2] = Point(-318.8508064325388, 1103.228273437134);
+ poly179.ps[3] = Point(-318.8508064325388, 386.2282734371338);
+ new ShapeRef(router, poly179, 179);
+
+ Polygon poly180(4);
+ poly180.ps[0] = Point(-371.0508064335389, 212.2282734381338);
+ poly180.ps[1] = Point(-371.0508064335389, 404.2282734381338);
+ poly180.ps[2] = Point(-446.8508064335388, 404.2282734381338);
+ poly180.ps[3] = Point(-446.8508064335388, 212.2282734381338);
+ new ShapeRef(router, poly180, 180);
+
+ Polygon poly181(4);
+ poly181.ps[0] = Point(852.6288472481148, 897.3235115333719);
+ poly181.ps[1] = Point(852.6288472481148, 939.3235115333719);
+ poly181.ps[2] = Point(776.8288472481148, 939.3235115333719);
+ poly181.ps[3] = Point(776.8288472481148, 897.3235115333719);
+ new ShapeRef(router, poly181, 181);
+
+ Polygon poly182(4);
+ poly182.ps[0] = Point(1303.628847251115, 1053.323511533372);
+ poly182.ps[1] = Point(1303.628847251115, 1095.323511533372);
+ poly182.ps[2] = Point(1227.828847251115, 1095.323511533372);
+ poly182.ps[3] = Point(1227.828847251115, 1053.323511533372);
+ new ShapeRef(router, poly182, 182);
+
+ Polygon poly183(4);
+ poly183.ps[0] = Point(1200.628847250115, 958.3235115333719);
+ poly183.ps[1] = Point(1200.628847250115, 1075.323511533372);
+ poly183.ps[2] = Point(1124.828847250115, 1075.323511533372);
+ poly183.ps[3] = Point(1124.828847250115, 958.3235115333719);
+ new ShapeRef(router, poly183, 183);
+
+ Polygon poly184(4);
+ poly184.ps[0] = Point(852.6288472481148, 1459.609225819086);
+ poly184.ps[1] = Point(852.6288472481148, 1501.609225819086);
+ poly184.ps[2] = Point(776.8288472481148, 1501.609225819086);
+ poly184.ps[3] = Point(776.8288472481148, 1459.609225819086);
+ new ShapeRef(router, poly184, 184);
+
+ ConnRef *connRef185 = new ConnRef(router, 185);
+ ConnEnd srcPt185(Point(1364.728847251115, 308.2282734381338), 15);
+ connRef185->setSourceEndpoint(srcPt185);
+ ConnEnd dstPt185(Point(1415.728847251115, 434.9901782000385), 4);
+ connRef185->setDestEndpoint(dstPt185);
+ connRef185->setRoutingType((ConnType)2);
+
+ ConnRef *connRef186 = new ConnRef(router, 186);
+ ConnEnd srcPt186(Point(717.7288472481148, 246.2282734371338), 15);
+ connRef186->setSourceEndpoint(srcPt186);
+ ConnEnd dstPt186(Point(945.7288472491148, 246.2282734371338), 4);
+ connRef186->setDestEndpoint(dstPt186);
+ connRef186->setRoutingType((ConnType)2);
+
+ ConnRef *connRef187 = new ConnRef(router, 187);
+ ConnEnd srcPt187(Point(975.7288472491148, 246.2282734371338), 8);
+ connRef187->setSourceEndpoint(srcPt187);
+ ConnEnd dstPt187(Point(1298.728847251115, 246.2282734371338), 15);
+ connRef187->setDestEndpoint(dstPt187);
+ connRef187->setRoutingType((ConnType)2);
+
+ ConnRef *connRef188 = new ConnRef(router, 188);
+ ConnEnd srcPt188(Point(864.7288472481148, 374.561606771467), 8);
+ connRef188->setSourceEndpoint(srcPt188);
+ ConnEnd dstPt188(Point(1129.728847250115, 308.2282734381338), 15);
+ connRef188->setDestEndpoint(dstPt188);
+ connRef188->setRoutingType((ConnType)2);
+
+ ConnRef *connRef189 = new ConnRef(router, 189);
+ ConnEnd srcPt189(Point(864.7288472481148, 374.561606771467), 8);
+ connRef189->setSourceEndpoint(srcPt189);
+ ConnEnd dstPt189(Point(1331.728847251115, 434.9901782000385), 15);
+ connRef189->setDestEndpoint(dstPt189);
+ connRef189->setRoutingType((ConnType)2);
+
+ ConnRef *connRef190 = new ConnRef(router, 190);
+ ConnEnd srcPt190(Point(633.7288472481148, 434.9901782000385), 8);
+ connRef190->setSourceEndpoint(srcPt190);
+ ConnEnd dstPt190(Point(684.7288472481148, 308.2282734381338), 15);
+ connRef190->setDestEndpoint(dstPt190);
+ connRef190->setRoutingType((ConnType)2);
+
+ ConnRef *connRef191 = new ConnRef(router, 191);
+ ConnEnd srcPt191(Point(633.7288472481148, 434.9901782000385), 8);
+ connRef191->setSourceEndpoint(srcPt191);
+ ConnEnd dstPt191(Point(781.7288472481148, 434.9901782000385), 15);
+ connRef191->setDestEndpoint(dstPt191);
+ connRef191->setRoutingType((ConnType)2);
+
+ ConnRef *connRef192 = new ConnRef(router, 192);
+ ConnEnd srcPt192(Point(-295.9508064325389, 386.2282734371338), 4);
+ connRef192->setSourceEndpoint(srcPt192);
+ ConnEnd dstPt192(Point(-625.9508064345389, 246.2282734371338), 15);
+ connRef192->setDestEndpoint(dstPt192);
+ connRef192->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints192(1);
+ checkpoints192[0] = Checkpoint(Point(-318.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef192->setRoutingCheckpoints(checkpoints192);
+
+ ConnRef *connRef193 = new ConnRef(router, 193);
+ ConnEnd srcPt193(Point(-295.9508064325389, 461.2282734371338), 4);
+ connRef193->setSourceEndpoint(srcPt193);
+ ConnEnd dstPt193(Point(-625.9508064345389, 246.2282734371338), 15);
+ connRef193->setDestEndpoint(dstPt193);
+ connRef193->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints193(1);
+ checkpoints193[0] = Checkpoint(Point(-318.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef193->setRoutingCheckpoints(checkpoints193);
+
+ ConnRef *connRef194 = new ConnRef(router, 194);
+ ConnEnd srcPt194(Point(-295.9508064325389, 536.2282734371338), 4);
+ connRef194->setSourceEndpoint(srcPt194);
+ ConnEnd dstPt194(Point(-625.9508064345389, 246.2282734371338), 15);
+ connRef194->setDestEndpoint(dstPt194);
+ connRef194->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints194(1);
+ checkpoints194[0] = Checkpoint(Point(-318.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef194->setRoutingCheckpoints(checkpoints194);
+
+ ConnRef *connRef195 = new ConnRef(router, 195);
+ ConnEnd srcPt195(Point(-295.9508064325389, 611.2282734371338), 4);
+ connRef195->setSourceEndpoint(srcPt195);
+ ConnEnd dstPt195(Point(-625.9508064345389, 246.2282734371338), 15);
+ connRef195->setDestEndpoint(dstPt195);
+ connRef195->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints195(1);
+ checkpoints195[0] = Checkpoint(Point(-318.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef195->setRoutingCheckpoints(checkpoints195);
+
+ ConnRef *connRef196 = new ConnRef(router, 196);
+ ConnEnd srcPt196(Point(-295.9508064325389, 686.2282734371338), 4);
+ connRef196->setSourceEndpoint(srcPt196);
+ ConnEnd dstPt196(Point(-625.9508064345389, 246.2282734371338), 15);
+ connRef196->setDestEndpoint(dstPt196);
+ connRef196->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints196(1);
+ checkpoints196[0] = Checkpoint(Point(-318.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef196->setRoutingCheckpoints(checkpoints196);
+#endif
+
+ ConnRef *connRef197 = new ConnRef(router, 197);
+ ConnEnd srcPt197(Point(-265.9508064325389, 953.2282734371338), 8);
+ connRef197->setSourceEndpoint(srcPt197);
+ ConnEnd dstPt197(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef197->setDestEndpoint(dstPt197);
+ connRef197->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints197(1);
+ checkpoints197[0] = Checkpoint(Point(-242.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef197->setRoutingCheckpoints(checkpoints197);
+
+#ifdef ALL
+ ConnRef *connRef198 = new ConnRef(router, 198);
+ ConnEnd srcPt198(Point(-295.9508064325389, 761.2282734371338), 4);
+ connRef198->setSourceEndpoint(srcPt198);
+ ConnEnd dstPt198(Point(-625.9508064345389, 246.2282734371338), 15);
+ connRef198->setDestEndpoint(dstPt198);
+ connRef198->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints198(1);
+ checkpoints198[0] = Checkpoint(Point(-318.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef198->setRoutingCheckpoints(checkpoints198);
+
+ ConnRef *connRef199 = new ConnRef(router, 199);
+ ConnEnd srcPt199(Point(-295.9508064325389, 803.2282734371338), 4);
+ connRef199->setSourceEndpoint(srcPt199);
+ ConnEnd dstPt199(Point(-625.9508064345389, 246.2282734371338), 15);
+ connRef199->setDestEndpoint(dstPt199);
+ connRef199->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints199(1);
+ checkpoints199[0] = Checkpoint(Point(-318.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef199->setRoutingCheckpoints(checkpoints199);
+
+ ConnRef *connRef200 = new ConnRef(router, 200);
+ ConnEnd srcPt200(Point(-295.9508064325389, 878.2282734371338), 4);
+ connRef200->setSourceEndpoint(srcPt200);
+ ConnEnd dstPt200(Point(-625.9508064345389, 246.2282734371338), 15);
+ connRef200->setDestEndpoint(dstPt200);
+ connRef200->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints200(1);
+ checkpoints200[0] = Checkpoint(Point(-318.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef200->setRoutingCheckpoints(checkpoints200);
+#endif
+
+ ConnRef *connRef201 = new ConnRef(router, 201);
+ ConnEnd srcPt201(Point(-265.9508064325389, 1028.228273437134), 8);
+ connRef201->setSourceEndpoint(srcPt201);
+ ConnEnd dstPt201(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef201->setDestEndpoint(dstPt201);
+ connRef201->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints201(1);
+ checkpoints201[0] = Checkpoint(Point(-242.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef201->setRoutingCheckpoints(checkpoints201);
+
+#ifdef ALL
+ ConnRef *connRef202 = new ConnRef(router, 202);
+ ConnEnd srcPt202(Point(-423.9508064335388, 212.2282734381338), 4);
+ connRef202->setSourceEndpoint(srcPt202);
+ ConnEnd dstPt202(Point(-553.9508064345389, 308.2282734381338), 15);
+ connRef202->setDestEndpoint(dstPt202);
+ connRef202->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints202(1);
+ checkpoints202[0] = Checkpoint(Point(-446.9508064335388, 308.2282734381338), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef202->setRoutingCheckpoints(checkpoints202);
+
+ ConnRef *connRef203 = new ConnRef(router, 203);
+ ConnEnd srcPt203(Point(-423.9508064335388, 287.2282734381338), 4);
+ connRef203->setSourceEndpoint(srcPt203);
+ ConnEnd dstPt203(Point(-553.9508064345389, 308.2282734381338), 15);
+ connRef203->setDestEndpoint(dstPt203);
+ connRef203->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints203(1);
+ checkpoints203[0] = Checkpoint(Point(-446.9508064335388, 308.2282734381338), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef203->setRoutingCheckpoints(checkpoints203);
+
+ ConnRef *connRef204 = new ConnRef(router, 204);
+ ConnEnd srcPt204(Point(-423.9508064335388, 329.2282734381338), 4);
+ connRef204->setSourceEndpoint(srcPt204);
+ ConnEnd dstPt204(Point(-553.9508064345389, 308.2282734381338), 15);
+ connRef204->setDestEndpoint(dstPt204);
+ connRef204->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints204(1);
+ checkpoints204[0] = Checkpoint(Point(-446.9508064335388, 308.2282734381338), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef204->setRoutingCheckpoints(checkpoints204);
+
+ ConnRef *connRef205 = new ConnRef(router, 205);
+ ConnEnd srcPt205(Point(618.7288472481148, -202.3431551362948), 15);
+ connRef205->setSourceEndpoint(srcPt205);
+ ConnEnd dstPt205(Point(600.7288472481148, 246.2282734371338), 8);
+ connRef205->setDestEndpoint(dstPt205);
+ connRef205->setRoutingType((ConnType)2);
+
+ ConnRef *connRef206 = new ConnRef(router, 206);
+ ConnEnd srcPt206(Point(570.7288472481148, 246.2282734371338), 4);
+ connRef206->setSourceEndpoint(srcPt206);
+ ConnEnd dstPt206(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef206->setDestEndpoint(dstPt206);
+ connRef206->setRoutingType((ConnType)2);
+
+ ConnRef *connRef207 = new ConnRef(router, 207);
+ ConnEnd srcPt207(Point(717.7288472481148, 246.2282734371338), 15);
+ connRef207->setSourceEndpoint(srcPt207);
+ ConnEnd dstPt207(Point(600.7288472481148, 246.2282734371338), 8);
+ connRef207->setDestEndpoint(dstPt207);
+ connRef207->setRoutingType((ConnType)2);
+
+ ConnRef *connRef208 = new ConnRef(router, 208);
+ ConnEnd srcPt208(Point(437.4431329624006, -323.3431551372947), 15);
+ connRef208->setSourceEndpoint(srcPt208);
+ ConnEnd dstPt208(Point(717.7288472481148, -283.3431551362947), 1);
+ connRef208->setDestEndpoint(dstPt208);
+ connRef208->setRoutingType((ConnType)2);
+
+ ConnRef *connRef209 = new ConnRef(router, 209);
+ ConnEnd srcPt209(Point(717.7288472481148, -518.3431551372947), 15);
+ connRef209->setSourceEndpoint(srcPt209);
+ ConnEnd dstPt209(Point(717.7288472481148, -283.3431551362947), 1);
+ connRef209->setDestEndpoint(dstPt209);
+ connRef209->setRoutingType((ConnType)2);
+
+ ConnRef *connRef210 = new ConnRef(router, 210);
+ ConnEnd srcPt210(Point(717.7288472481148, -253.3431551362947), 2);
+ connRef210->setSourceEndpoint(srcPt210);
+ ConnEnd dstPt210(Point(717.7288472481148, 246.2282734371338), 15);
+ connRef210->setDestEndpoint(dstPt210);
+ connRef210->setRoutingType((ConnType)2);
+
+ ConnRef *connRef211 = new ConnRef(router, 211);
+ ConnEnd srcPt211(Point(158.7764662957339, 154.6568448657052), 1);
+ connRef211->setSourceEndpoint(srcPt211);
+ ConnEnd dstPt211(Point(717.7288472481148, -518.3431551372947), 15);
+ connRef211->setDestEndpoint(dstPt211);
+ connRef211->setRoutingType((ConnType)2);
+
+ ConnRef *connRef212 = new ConnRef(router, 212);
+ ConnEnd srcPt212(Point(158.7764662957339, 154.6568448657052), 1);
+ connRef212->setSourceEndpoint(srcPt212);
+ ConnEnd dstPt212(Point(158.7764662957339, 103.6568448657052), 15);
+ connRef212->setDestEndpoint(dstPt212);
+ connRef212->setRoutingType((ConnType)2);
+
+ ConnRef *connRef213 = new ConnRef(router, 213);
+ ConnEnd srcPt213(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef213->setSourceEndpoint(srcPt213);
+ ConnEnd dstPt213(Point(158.7764662957339, 184.6568448657052), 2);
+ connRef213->setDestEndpoint(dstPt213);
+ connRef213->setRoutingType((ConnType)2);
+
+ ConnRef *connRef214 = new ConnRef(router, 214);
+ ConnEnd srcPt214(Point(256.9431329624006, -133.3431551362948), 8);
+ connRef214->setSourceEndpoint(srcPt214);
+ ConnEnd dstPt214(Point(437.4431329624006, -323.3431551372947), 15);
+ connRef214->setDestEndpoint(dstPt214);
+ connRef214->setRoutingType((ConnType)2);
+
+ ConnRef *connRef215 = new ConnRef(router, 215);
+ ConnEnd srcPt215(Point(256.9431329624006, -133.3431551362948), 8);
+ connRef215->setSourceEndpoint(srcPt215);
+ ConnEnd dstPt215(Point(618.7288472481148, -202.3431551362948), 15);
+ connRef215->setDestEndpoint(dstPt215);
+ connRef215->setRoutingType((ConnType)2);
+
+ ConnRef *connRef216 = new ConnRef(router, 216);
+ ConnEnd srcPt216(Point(158.7764662957339, 103.6568448657052), 15);
+ connRef216->setSourceEndpoint(srcPt216);
+ ConnEnd dstPt216(Point(226.9431329624006, -133.3431551362948), 4);
+ connRef216->setDestEndpoint(dstPt216);
+ connRef216->setRoutingType((ConnType)2);
+
+ ConnRef *connRef217 = new ConnRef(router, 217);
+ ConnEnd srcPt217(Point(-220.9735337052661, -551.3431551372947), 15);
+ connRef217->setSourceEndpoint(srcPt217);
+ ConnEnd dstPt217(Point(323.4431329624006, -551.3431551372947), 4);
+ connRef217->setDestEndpoint(dstPt217);
+ connRef217->setRoutingType((ConnType)2);
+
+ ConnRef *connRef218 = new ConnRef(router, 218);
+ ConnEnd srcPt218(Point(353.4431329624006, -551.3431551372947), 8);
+ connRef218->setSourceEndpoint(srcPt218);
+ ConnEnd dstPt218(Point(717.7288472481148, -518.3431551372947), 15);
+ connRef218->setDestEndpoint(dstPt218);
+ connRef218->setRoutingType((ConnType)2);
+
+ ConnRef *connRef219 = new ConnRef(router, 219);
+ ConnEnd srcPt219(Point(537.7288472481148, -641.8431551372947), 4);
+ connRef219->setSourceEndpoint(srcPt219);
+ ConnEnd dstPt219(Point(-220.9735337052661, -551.3431551372947), 15);
+ connRef219->setDestEndpoint(dstPt219);
+ connRef219->setRoutingType((ConnType)2);
+
+ ConnRef *connRef220 = new ConnRef(router, 220);
+ ConnEnd srcPt220(Point(537.7288472481148, -641.8431551372947), 4);
+ connRef220->setSourceEndpoint(srcPt220);
+ ConnEnd dstPt220(Point(437.4431329624006, -323.3431551372947), 15);
+ connRef220->setDestEndpoint(dstPt220);
+ connRef220->setRoutingType((ConnType)2);
+
+ ConnRef *connRef221 = new ConnRef(router, 221);
+ ConnEnd srcPt221(Point(-220.9735337052661, 121.6568448657052), 1);
+ connRef221->setSourceEndpoint(srcPt221);
+ ConnEnd dstPt221(Point(158.7764662957339, 103.6568448657052), 15);
+ connRef221->setDestEndpoint(dstPt221);
+ connRef221->setRoutingType((ConnType)2);
+
+ ConnRef *connRef222 = new ConnRef(router, 222);
+ ConnEnd srcPt222(Point(-220.9735337052661, 121.6568448657052), 1);
+ connRef222->setSourceEndpoint(srcPt222);
+ ConnEnd dstPt222(Point(-220.9735337052661, -235.3431551362947), 15);
+ connRef222->setDestEndpoint(dstPt222);
+ connRef222->setRoutingType((ConnType)2);
+
+ ConnRef *connRef223 = new ConnRef(router, 223);
+ ConnEnd srcPt223(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef223->setSourceEndpoint(srcPt223);
+ ConnEnd dstPt223(Point(-220.9735337052661, 151.6568448657052), 2);
+ connRef223->setDestEndpoint(dstPt223);
+ connRef223->setRoutingType((ConnType)2);
+
+ ConnRef *connRef224 = new ConnRef(router, 224);
+ ConnEnd srcPt224(Point(-220.9735337052661, -371.3431551372947), 1);
+ connRef224->setSourceEndpoint(srcPt224);
+ ConnEnd dstPt224(Point(-586.9508064345389, -408.3431551372947), 15);
+ connRef224->setDestEndpoint(dstPt224);
+ connRef224->setRoutingType((ConnType)2);
+
+ ConnRef *connRef225 = new ConnRef(router, 225);
+ ConnEnd srcPt225(Point(-220.9735337052661, -371.3431551372947), 1);
+ connRef225->setSourceEndpoint(srcPt225);
+ ConnEnd dstPt225(Point(-220.9735337052661, -551.3431551372947), 15);
+ connRef225->setDestEndpoint(dstPt225);
+ connRef225->setRoutingType((ConnType)2);
+
+ ConnRef *connRef226 = new ConnRef(router, 226);
+ ConnEnd srcPt226(Point(-220.9735337052661, -235.3431551362947), 15);
+ connRef226->setSourceEndpoint(srcPt226);
+ ConnEnd dstPt226(Point(-220.9735337052661, -341.3431551372947), 2);
+ connRef226->setDestEndpoint(dstPt226);
+ connRef226->setRoutingType((ConnType)2);
+
+ ConnRef *connRef227 = new ConnRef(router, 227);
+ ConnEnd srcPt227(Point(1331.728847251115, 434.9901782000385), 15);
+ connRef227->setSourceEndpoint(srcPt227);
+ ConnEnd dstPt227(Point(1415.728847251115, 434.9901782000385), 4);
+ connRef227->setDestEndpoint(dstPt227);
+ connRef227->setRoutingType((ConnType)2);
+
+ ConnRef *connRef228 = new ConnRef(router, 228);
+ ConnEnd srcPt228(Point(1445.728847251115, 434.9901782000385), 8);
+ connRef228->setSourceEndpoint(srcPt228);
+ ConnEnd dstPt228(Point(1511.728847251115, 434.9901782000385), 15);
+ connRef228->setDestEndpoint(dstPt228);
+ connRef228->setRoutingType((ConnType)2);
+
+ ConnRef *connRef229 = new ConnRef(router, 229);
+ ConnEnd srcPt229(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef229->setSourceEndpoint(srcPt229);
+ ConnEnd dstPt229(Point(389.4431329624006, 434.9901782000385), 4);
+ connRef229->setDestEndpoint(dstPt229);
+ connRef229->setRoutingType((ConnType)2);
+
+ ConnRef *connRef230 = new ConnRef(router, 230);
+ ConnEnd srcPt230(Point(419.4431329624006, 434.9901782000385), 8);
+ connRef230->setSourceEndpoint(srcPt230);
+ ConnEnd dstPt230(Point(519.7288472481148, 434.9901782000385), 15);
+ connRef230->setDestEndpoint(dstPt230);
+ connRef230->setRoutingType((ConnType)2);
+
+ ConnRef *connRef231 = new ConnRef(router, 231);
+ ConnEnd srcPt231(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef231->setSourceEndpoint(srcPt231);
+ ConnEnd dstPt231(Point(437.4431329624006, 870.3235115333719), 1);
+ connRef231->setDestEndpoint(dstPt231);
+ connRef231->setRoutingType((ConnType)2);
+
+ ConnRef *connRef232 = new ConnRef(router, 232);
+ ConnEnd srcPt232(Point(437.4431329624006, 900.3235115333719), 2);
+ connRef232->setSourceEndpoint(srcPt232);
+ ConnEnd dstPt232(Point(651.7288472481148, 918.3235115333719), 15);
+ connRef232->setDestEndpoint(dstPt232);
+ connRef232->setRoutingType((ConnType)2);
+
+ ConnRef *connRef233 = new ConnRef(router, 233);
+ ConnEnd srcPt233(Point(371.4431329624006, 796.3235115333719), 15);
+ connRef233->setSourceEndpoint(srcPt233);
+ ConnEnd dstPt233(Point(437.4431329624006, 870.3235115333719), 1);
+ connRef233->setDestEndpoint(dstPt233);
+ connRef233->setRoutingType((ConnType)2);
+
+ ConnRef *connRef234 = new ConnRef(router, 234);
+ ConnEnd srcPt234(Point(437.4431329624006, 579.9901782000385), 1);
+ connRef234->setSourceEndpoint(srcPt234);
+ ConnEnd dstPt234(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef234->setDestEndpoint(dstPt234);
+ connRef234->setRoutingType((ConnType)2);
+
+ ConnRef *connRef235 = new ConnRef(router, 235);
+ ConnEnd srcPt235(Point(651.7288472481148, 918.3235115333719), 15);
+ connRef235->setSourceEndpoint(srcPt235);
+ ConnEnd dstPt235(Point(437.4431329624006, 609.9901782000385), 2);
+ connRef235->setDestEndpoint(dstPt235);
+ connRef235->setRoutingType((ConnType)2);
+
+ ConnRef *connRef236 = new ConnRef(router, 236);
+ ConnEnd srcPt236(Point(437.4431329624006, 579.9901782000385), 1);
+ connRef236->setSourceEndpoint(srcPt236);
+ ConnEnd dstPt236(Point(371.4431329624006, 796.3235115333719), 15);
+ connRef236->setDestEndpoint(dstPt236);
+ connRef236->setRoutingType((ConnType)2);
+
+ ConnRef *connRef237 = new ConnRef(router, 237);
+ ConnEnd srcPt237(Point(-586.9508064345389, -408.3431551372947), 15);
+ connRef237->setSourceEndpoint(srcPt237);
+ ConnEnd dstPt237(Point(-220.9735337052661, 151.6568448657052), 2);
+ connRef237->setDestEndpoint(dstPt237);
+ connRef237->setRoutingType((ConnType)2);
+
+ ConnRef *connRef238 = new ConnRef(router, 238);
+ ConnEnd srcPt238(Point(256.9431329624006, 70.65684486570521), 8);
+ connRef238->setSourceEndpoint(srcPt238);
+ ConnEnd dstPt238(Point(437.4431329624006, -323.3431551372947), 15);
+ connRef238->setDestEndpoint(dstPt238);
+ connRef238->setRoutingType((ConnType)2);
+
+ ConnRef *connRef239 = new ConnRef(router, 239);
+ ConnEnd srcPt239(Point(106.7764662947339, -148.3431551362948), 1);
+ connRef239->setSourceEndpoint(srcPt239);
+ ConnEnd dstPt239(Point(618.7288472481148, -202.3431551362948), 15);
+ connRef239->setDestEndpoint(dstPt239);
+ connRef239->setRoutingType((ConnType)2);
+
+ ConnRef *connRef240 = new ConnRef(router, 240);
+ ConnEnd srcPt240(Point(106.7764662947339, -46.34315513529478), 1);
+ connRef240->setSourceEndpoint(srcPt240);
+ ConnEnd dstPt240(Point(618.7288472481148, -202.3431551362948), 15);
+ connRef240->setDestEndpoint(dstPt240);
+ connRef240->setRoutingType((ConnType)2);
+
+ ConnRef *connRef241 = new ConnRef(router, 241);
+ ConnEnd srcPt241(Point(106.7764662947339, 55.65684486570521), 1);
+ connRef241->setSourceEndpoint(srcPt241);
+ ConnEnd dstPt241(Point(618.7288472481148, -202.3431551362948), 15);
+ connRef241->setDestEndpoint(dstPt241);
+ connRef241->setRoutingType((ConnType)2);
+
+ ConnRef *connRef242 = new ConnRef(router, 242);
+ ConnEnd srcPt242(Point(256.9431329624006, -31.34315513529478), 8);
+ connRef242->setSourceEndpoint(srcPt242);
+ ConnEnd dstPt242(Point(618.7288472481148, -202.3431551362948), 15);
+ connRef242->setDestEndpoint(dstPt242);
+ connRef242->setRoutingType((ConnType)2);
+
+ ConnRef *connRef243 = new ConnRef(router, 243);
+ ConnEnd srcPt243(Point(256.9431329624006, 70.65684486570521), 8);
+ connRef243->setSourceEndpoint(srcPt243);
+ ConnEnd dstPt243(Point(618.7288472481148, -202.3431551362948), 15);
+ connRef243->setDestEndpoint(dstPt243);
+ connRef243->setRoutingType((ConnType)2);
+
+ ConnRef *connRef244 = new ConnRef(router, 244);
+ ConnEnd srcPt244(Point(158.7764662957339, 103.6568448657052), 15);
+ connRef244->setSourceEndpoint(srcPt244);
+ ConnEnd dstPt244(Point(106.7764662947339, -118.3431551362948), 2);
+ connRef244->setDestEndpoint(dstPt244);
+ connRef244->setRoutingType((ConnType)2);
+
+ ConnRef *connRef245 = new ConnRef(router, 245);
+ ConnEnd srcPt245(Point(158.7764662957339, 103.6568448657052), 15);
+ connRef245->setSourceEndpoint(srcPt245);
+ ConnEnd dstPt245(Point(106.7764662947339, -16.34315513529478), 2);
+ connRef245->setDestEndpoint(dstPt245);
+ connRef245->setRoutingType((ConnType)2);
+
+ ConnRef *connRef246 = new ConnRef(router, 246);
+ ConnEnd srcPt246(Point(158.7764662957339, 103.6568448657052), 15);
+ connRef246->setSourceEndpoint(srcPt246);
+ ConnEnd dstPt246(Point(106.7764662947339, 85.65684486570521), 2);
+ connRef246->setDestEndpoint(dstPt246);
+ connRef246->setRoutingType((ConnType)2);
+
+ ConnRef *connRef247 = new ConnRef(router, 247);
+ ConnEnd srcPt247(Point(158.7764662957339, 103.6568448657052), 15);
+ connRef247->setSourceEndpoint(srcPt247);
+ ConnEnd dstPt247(Point(226.9431329624006, -31.34315513529478), 4);
+ connRef247->setDestEndpoint(dstPt247);
+ connRef247->setRoutingType((ConnType)2);
+
+ ConnRef *connRef248 = new ConnRef(router, 248);
+ ConnEnd srcPt248(Point(158.7764662957339, 103.6568448657052), 15);
+ connRef248->setSourceEndpoint(srcPt248);
+ ConnEnd dstPt248(Point(226.9431329624006, 70.65684486570521), 4);
+ connRef248->setDestEndpoint(dstPt248);
+ connRef248->setRoutingType((ConnType)2);
+#endif
+
+ ConnRef *connRef249 = new ConnRef(router, 249);
+ ConnEnd srcPt249(Point(-265.9508064325389, 386.2282734371338), 8);
+ connRef249->setSourceEndpoint(srcPt249);
+ ConnEnd dstPt249(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef249->setDestEndpoint(dstPt249);
+ connRef249->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints249(1);
+ checkpoints249[0] = Checkpoint(Point(-242.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef249->setRoutingCheckpoints(checkpoints249);
+
+ ConnRef *connRef250 = new ConnRef(router, 250);
+ ConnEnd srcPt250(Point(-265.9508064325389, 461.2282734371338), 8);
+ connRef250->setSourceEndpoint(srcPt250);
+ ConnEnd dstPt250(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef250->setDestEndpoint(dstPt250);
+ connRef250->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints250(1);
+ checkpoints250[0] = Checkpoint(Point(-242.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef250->setRoutingCheckpoints(checkpoints250);
+
+ ConnRef *connRef251 = new ConnRef(router, 251);
+ ConnEnd srcPt251(Point(-265.9508064325389, 536.2282734371338), 8);
+ connRef251->setSourceEndpoint(srcPt251);
+ ConnEnd dstPt251(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef251->setDestEndpoint(dstPt251);
+ connRef251->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints251(1);
+ checkpoints251[0] = Checkpoint(Point(-242.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef251->setRoutingCheckpoints(checkpoints251);
+
+ ConnRef *connRef252 = new ConnRef(router, 252);
+ ConnEnd srcPt252(Point(-265.9508064325389, 611.2282734371338), 8);
+ connRef252->setSourceEndpoint(srcPt252);
+ ConnEnd dstPt252(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef252->setDestEndpoint(dstPt252);
+ connRef252->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints252(1);
+ checkpoints252[0] = Checkpoint(Point(-242.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef252->setRoutingCheckpoints(checkpoints252);
+
+ ConnRef *connRef253 = new ConnRef(router, 253);
+ ConnEnd srcPt253(Point(-265.9508064325389, 686.2282734371338), 8);
+ connRef253->setSourceEndpoint(srcPt253);
+ ConnEnd dstPt253(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef253->setDestEndpoint(dstPt253);
+ connRef253->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints253(1);
+ checkpoints253[0] = Checkpoint(Point(-242.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef253->setRoutingCheckpoints(checkpoints253);
+
+ ConnRef *connRef254 = new ConnRef(router, 254);
+ ConnEnd srcPt254(Point(-265.9508064325389, 761.2282734371338), 8);
+ connRef254->setSourceEndpoint(srcPt254);
+ ConnEnd dstPt254(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef254->setDestEndpoint(dstPt254);
+ connRef254->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints254(1);
+ checkpoints254[0] = Checkpoint(Point(-242.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef254->setRoutingCheckpoints(checkpoints254);
+
+ ConnRef *connRef255 = new ConnRef(router, 255);
+ ConnEnd srcPt255(Point(-265.9508064325389, 803.2282734371338), 8);
+ connRef255->setSourceEndpoint(srcPt255);
+ ConnEnd dstPt255(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef255->setDestEndpoint(dstPt255);
+ connRef255->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints255(1);
+ checkpoints255[0] = Checkpoint(Point(-242.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef255->setRoutingCheckpoints(checkpoints255);
+
+ ConnRef *connRef256 = new ConnRef(router, 256);
+ ConnEnd srcPt256(Point(-265.9508064325389, 878.2282734371338), 8);
+ connRef256->setSourceEndpoint(srcPt256);
+ ConnEnd dstPt256(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef256->setDestEndpoint(dstPt256);
+ connRef256->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints256(1);
+ checkpoints256[0] = Checkpoint(Point(-242.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef256->setRoutingCheckpoints(checkpoints256);
+
+#ifdef ALL
+ ConnRef *connRef257 = new ConnRef(router, 257);
+ ConnEnd srcPt257(Point(-486.9508064345389, 246.2282734371338), 8);
+ connRef257->setSourceEndpoint(srcPt257);
+ ConnEnd dstPt257(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef257->setDestEndpoint(dstPt257);
+ connRef257->setRoutingType((ConnType)2);
+#endif
+
+ ConnRef *connRef258 = new ConnRef(router, 258);
+ ConnEnd srcPt258(Point(-265.9508064325389, 1103.228273437134), 8);
+ connRef258->setSourceEndpoint(srcPt258);
+ ConnEnd dstPt258(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef258->setDestEndpoint(dstPt258);
+ connRef258->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints258(1);
+ checkpoints258[0] = Checkpoint(Point(-242.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef258->setRoutingCheckpoints(checkpoints258);
+
+#ifdef ALL
+ ConnRef *connRef259 = new ConnRef(router, 259);
+ ConnEnd srcPt259(Point(422.4431329624006, 715.9901782000385), 4);
+ connRef259->setSourceEndpoint(srcPt259);
+ ConnEnd dstPt259(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef259->setDestEndpoint(dstPt259);
+ connRef259->setRoutingType((ConnType)2);
+
+ ConnRef *connRef260 = new ConnRef(router, 260);
+ ConnEnd srcPt260(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef260->setSourceEndpoint(srcPt260);
+ ConnEnd dstPt260(Point(422.4431329624006, 951.3235115333719), 4);
+ connRef260->setDestEndpoint(dstPt260);
+ connRef260->setRoutingType((ConnType)2);
+
+ ConnRef *connRef261 = new ConnRef(router, 261);
+ ConnEnd srcPt261(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef261->setSourceEndpoint(srcPt261);
+ ConnEnd dstPt261(Point(422.4431329624006, 1324.723511533372), 4);
+ connRef261->setDestEndpoint(dstPt261);
+ connRef261->setRoutingType((ConnType)2);
+
+ ConnRef *connRef262 = new ConnRef(router, 262);
+ ConnEnd srcPt262(Point(158.7764662957339, 246.2282734371338), 15);
+ connRef262->setSourceEndpoint(srcPt262);
+ ConnEnd dstPt262(Point(422.4431329624006, 1480.609225819086), 4);
+ connRef262->setDestEndpoint(dstPt262);
+ connRef262->setRoutingType((ConnType)2);
+
+ ConnRef *connRef263 = new ConnRef(router, 263);
+ ConnEnd srcPt263(Point(717.7288472481148, 246.2282734371338), 15);
+ connRef263->setSourceEndpoint(srcPt263);
+ ConnEnd dstPt263(Point(567.7288472481148, -641.8431551372947), 8);
+ connRef263->setDestEndpoint(dstPt263);
+ connRef263->setRoutingType((ConnType)2);
+
+ ConnRef *connRef264 = new ConnRef(router, 264);
+ ConnEnd srcPt264(Point(-295.9508064325389, 953.2282734371338), 4);
+ connRef264->setSourceEndpoint(srcPt264);
+ ConnEnd dstPt264(Point(-625.9508064345389, 246.2282734371338), 15);
+ connRef264->setDestEndpoint(dstPt264);
+ connRef264->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints264(1);
+ checkpoints264[0] = Checkpoint(Point(-318.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef264->setRoutingCheckpoints(checkpoints264);
+
+ ConnRef *connRef265 = new ConnRef(router, 265);
+ ConnEnd srcPt265(Point(-295.9508064325389, 1028.228273437134), 4);
+ connRef265->setSourceEndpoint(srcPt265);
+ ConnEnd dstPt265(Point(-625.9508064345389, 246.2282734371338), 15);
+ connRef265->setDestEndpoint(dstPt265);
+ connRef265->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints265(1);
+ checkpoints265[0] = Checkpoint(Point(-318.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef265->setRoutingCheckpoints(checkpoints265);
+
+ ConnRef *connRef266 = new ConnRef(router, 266);
+ ConnEnd srcPt266(Point(-625.9508064345389, 246.2282734371338), 15);
+ connRef266->setSourceEndpoint(srcPt266);
+ ConnEnd dstPt266(Point(-516.9508064345389, 246.2282734371338), 4);
+ connRef266->setDestEndpoint(dstPt266);
+ connRef266->setRoutingType((ConnType)2);
+
+ ConnRef *connRef267 = new ConnRef(router, 267);
+ ConnEnd srcPt267(Point(-295.9508064325389, 1103.228273437134), 4);
+ connRef267->setSourceEndpoint(srcPt267);
+ ConnEnd dstPt267(Point(-625.9508064345389, 246.2282734371338), 15);
+ connRef267->setDestEndpoint(dstPt267);
+ connRef267->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints267(1);
+ checkpoints267[0] = Checkpoint(Point(-318.9508064325389, 782.2282734371338), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef267->setRoutingCheckpoints(checkpoints267);
+
+ ConnRef *connRef268 = new ConnRef(router, 268);
+ ConnEnd srcPt268(Point(-553.9508064345389, 308.2282734381338), 15);
+ connRef268->setSourceEndpoint(srcPt268);
+ ConnEnd dstPt268(Point(-516.9508064345389, 246.2282734371338), 4);
+ connRef268->setDestEndpoint(dstPt268);
+ connRef268->setRoutingType((ConnType)2);
+
+ ConnRef *connRef269 = new ConnRef(router, 269);
+ ConnEnd srcPt269(Point(-393.9508064335388, 212.2282734381338), 8);
+ connRef269->setSourceEndpoint(srcPt269);
+ ConnEnd dstPt269(Point(-30.22353370526614, 308.2282734381338), 15);
+ connRef269->setDestEndpoint(dstPt269);
+ connRef269->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints269(1);
+ checkpoints269[0] = Checkpoint(Point(-370.9508064335388, 308.2282734381338), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef269->setRoutingCheckpoints(checkpoints269);
+
+ ConnRef *connRef270 = new ConnRef(router, 270);
+ ConnEnd srcPt270(Point(-393.9508064335388, 287.2282734381338), 8);
+ connRef270->setSourceEndpoint(srcPt270);
+ ConnEnd dstPt270(Point(-30.22353370526614, 308.2282734381338), 15);
+ connRef270->setDestEndpoint(dstPt270);
+ connRef270->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints270(1);
+ checkpoints270[0] = Checkpoint(Point(-370.9508064335388, 308.2282734381338), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef270->setRoutingCheckpoints(checkpoints270);
+
+ ConnRef *connRef271 = new ConnRef(router, 271);
+ ConnEnd srcPt271(Point(-393.9508064335388, 329.2282734381338), 8);
+ connRef271->setSourceEndpoint(srcPt271);
+ ConnEnd dstPt271(Point(-30.22353370526614, 308.2282734381338), 15);
+ connRef271->setDestEndpoint(dstPt271);
+ connRef271->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints271(1);
+ checkpoints271[0] = Checkpoint(Point(-370.9508064335388, 308.2282734381338), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef271->setRoutingCheckpoints(checkpoints271);
+
+ ConnRef *connRef272 = new ConnRef(router, 272);
+ ConnEnd srcPt272(Point(-393.9508064335388, 404.2282734381338), 8);
+ connRef272->setSourceEndpoint(srcPt272);
+ ConnEnd dstPt272(Point(-30.22353370526614, 308.2282734381338), 15);
+ connRef272->setDestEndpoint(dstPt272);
+ connRef272->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints272(1);
+ checkpoints272[0] = Checkpoint(Point(-370.9508064335388, 308.2282734381338), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef272->setRoutingCheckpoints(checkpoints272);
+
+ ConnRef *connRef273 = new ConnRef(router, 273);
+ ConnEnd srcPt273(Point(241.9431329624006, 308.2282734381338), 15);
+ connRef273->setSourceEndpoint(srcPt273);
+ ConnEnd dstPt273(Point(389.4431329624006, 434.9901782000385), 4);
+ connRef273->setDestEndpoint(dstPt273);
+ connRef273->setRoutingType((ConnType)2);
+
+ ConnRef *connRef274 = new ConnRef(router, 274);
+ ConnEnd srcPt274(Point(519.7288472481148, 434.9901782000385), 15);
+ connRef274->setSourceEndpoint(srcPt274);
+ ConnEnd dstPt274(Point(603.7288472481148, 434.9901782000385), 4);
+ connRef274->setDestEndpoint(dstPt274);
+ connRef274->setRoutingType((ConnType)2);
+
+ ConnRef *connRef275 = new ConnRef(router, 275);
+ ConnEnd srcPt275(Point(651.7288472481148, 918.3235115333719), 15);
+ connRef275->setSourceEndpoint(srcPt275);
+ ConnEnd dstPt275(Point(452.4431329624006, 715.9901782000385), 8);
+ connRef275->setDestEndpoint(dstPt275);
+ connRef275->setRoutingType((ConnType)2);
+
+ ConnRef *connRef276 = new ConnRef(router, 276);
+ ConnEnd srcPt276(Point(799.7288472481148, 939.3235115333719), 4);
+ connRef276->setSourceEndpoint(srcPt276);
+ ConnEnd dstPt276(Point(651.7288472481148, 918.3235115333719), 15);
+ connRef276->setDestEndpoint(dstPt276);
+ connRef276->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints276(1);
+ checkpoints276[0] = Checkpoint(Point(776.7288472481148, 918.3235115333719), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef276->setRoutingCheckpoints(checkpoints276);
+
+ ConnRef *connRef277 = new ConnRef(router, 277);
+ ConnEnd srcPt277(Point(799.7288472481148, 897.3235115333719), 4);
+ connRef277->setSourceEndpoint(srcPt277);
+ ConnEnd dstPt277(Point(651.7288472481148, 918.3235115333719), 15);
+ connRef277->setDestEndpoint(dstPt277);
+ connRef277->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints277(1);
+ checkpoints277[0] = Checkpoint(Point(776.7288472481148, 918.3235115333719), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef277->setRoutingCheckpoints(checkpoints277);
+
+ ConnRef *connRef278 = new ConnRef(router, 278);
+ ConnEnd srcPt278(Point(781.7288472481148, 434.9901782000385), 15);
+ connRef278->setSourceEndpoint(srcPt278);
+ ConnEnd dstPt278(Point(834.7288472481148, 374.561606771467), 4);
+ connRef278->setDestEndpoint(dstPt278);
+ connRef278->setRoutingType((ConnType)2);
+
+ ConnRef *connRef279 = new ConnRef(router, 279);
+ ConnEnd srcPt279(Point(781.7288472481148, 434.9901782000385), 15);
+ connRef279->setSourceEndpoint(srcPt279);
+ ConnEnd dstPt279(Point(834.7288472481148, 467.9901782000385), 4);
+ connRef279->setDestEndpoint(dstPt279);
+ connRef279->setRoutingType((ConnType)2);
+
+ ConnRef *connRef280 = new ConnRef(router, 280);
+ ConnEnd srcPt280(Point(781.7288472481148, 434.9901782000385), 15);
+ connRef280->setSourceEndpoint(srcPt280);
+ ConnEnd dstPt280(Point(912.7288472491148, 467.9901782000385), 4);
+ connRef280->setDestEndpoint(dstPt280);
+ connRef280->setRoutingType((ConnType)2);
+
+ ConnRef *connRef281 = new ConnRef(router, 281);
+ ConnEnd srcPt281(Point(781.7288472481148, 434.9901782000385), 15);
+ connRef281->setSourceEndpoint(srcPt281);
+ ConnEnd dstPt281(Point(1011.728847249115, 467.9901782000385), 4);
+ connRef281->setDestEndpoint(dstPt281);
+ connRef281->setRoutingType((ConnType)2);
+
+ ConnRef *connRef282 = new ConnRef(router, 282);
+ ConnEnd srcPt282(Point(781.7288472481148, 434.9901782000385), 15);
+ connRef282->setSourceEndpoint(srcPt282);
+ ConnEnd dstPt282(Point(912.7288472491148, 374.561606771467), 4);
+ connRef282->setDestEndpoint(dstPt282);
+ connRef282->setRoutingType((ConnType)2);
+
+ ConnRef *connRef283 = new ConnRef(router, 283);
+ ConnEnd srcPt283(Point(781.7288472481148, 434.9901782000385), 15);
+ connRef283->setSourceEndpoint(srcPt283);
+ ConnEnd dstPt283(Point(1011.728847249115, 374.561606771467), 4);
+ connRef283->setDestEndpoint(dstPt283);
+ connRef283->setRoutingType((ConnType)2);
+
+ ConnRef *connRef284 = new ConnRef(router, 284);
+ ConnEnd srcPt284(Point(864.7288472481148, 467.9901782000385), 8);
+ connRef284->setSourceEndpoint(srcPt284);
+ ConnEnd dstPt284(Point(1331.728847251115, 434.9901782000385), 15);
+ connRef284->setDestEndpoint(dstPt284);
+ connRef284->setRoutingType((ConnType)2);
+
+ ConnRef *connRef285 = new ConnRef(router, 285);
+ ConnEnd srcPt285(Point(942.7288472491148, 467.9901782000385), 8);
+ connRef285->setSourceEndpoint(srcPt285);
+ ConnEnd dstPt285(Point(1331.728847251115, 434.9901782000385), 15);
+ connRef285->setDestEndpoint(dstPt285);
+ connRef285->setRoutingType((ConnType)2);
+
+ ConnRef *connRef286 = new ConnRef(router, 286);
+ ConnEnd srcPt286(Point(1041.728847249115, 467.9901782000385), 8);
+ connRef286->setSourceEndpoint(srcPt286);
+ ConnEnd dstPt286(Point(1331.728847251115, 434.9901782000385), 15);
+ connRef286->setDestEndpoint(dstPt286);
+ connRef286->setRoutingType((ConnType)2);
+
+ ConnRef *connRef287 = new ConnRef(router, 287);
+ ConnEnd srcPt287(Point(942.7288472491148, 374.561606771467), 8);
+ connRef287->setSourceEndpoint(srcPt287);
+ ConnEnd dstPt287(Point(1331.728847251115, 434.9901782000385), 15);
+ connRef287->setDestEndpoint(dstPt287);
+ connRef287->setRoutingType((ConnType)2);
+
+ ConnRef *connRef288 = new ConnRef(router, 288);
+ ConnEnd srcPt288(Point(-486.9508064345389, 246.2282734371338), 8);
+ connRef288->setSourceEndpoint(srcPt288);
+ ConnEnd dstPt288(Point(-30.22353370526614, 308.2282734381338), 15);
+ connRef288->setDestEndpoint(dstPt288);
+ connRef288->setRoutingType((ConnType)2);
+
+ ConnRef *connRef289 = new ConnRef(router, 289);
+ ConnEnd srcPt289(Point(-150.8902003719328, 1021.323511533372), 15);
+ connRef289->setSourceEndpoint(srcPt289);
+ ConnEnd dstPt289(Point(-150.8902003719328, 933.3235115333719), 2);
+ connRef289->setDestEndpoint(dstPt289);
+ connRef289->setRoutingType((ConnType)2);
+
+ ConnRef *connRef290 = new ConnRef(router, 290);
+ ConnEnd srcPt290(Point(-150.8902003719328, 796.3235115333719), 15);
+ connRef290->setSourceEndpoint(srcPt290);
+ ConnEnd dstPt290(Point(-12.22353370526611, 796.3235115333719), 4);
+ connRef290->setDestEndpoint(dstPt290);
+ connRef290->setRoutingType((ConnType)2);
+
+ ConnRef *connRef291 = new ConnRef(router, 291);
+ ConnEnd srcPt291(Point(17.77646629473389, 796.3235115333719), 8);
+ connRef291->setSourceEndpoint(srcPt291);
+ ConnEnd dstPt291(Point(371.4431329624006, 796.3235115333719), 15);
+ connRef291->setDestEndpoint(dstPt291);
+ connRef291->setRoutingType((ConnType)2);
+
+ ConnRef *connRef292 = new ConnRef(router, 292);
+ ConnEnd srcPt292(Point(371.4431329624006, 796.3235115333719), 15);
+ connRef292->setSourceEndpoint(srcPt292);
+ ConnEnd dstPt292(Point(422.4431329624006, 951.3235115333719), 4);
+ connRef292->setDestEndpoint(dstPt292);
+ connRef292->setRoutingType((ConnType)2);
+
+ ConnRef *connRef293 = new ConnRef(router, 293);
+ ConnEnd srcPt293(Point(371.4431329624006, 796.3235115333719), 15);
+ connRef293->setSourceEndpoint(srcPt293);
+ ConnEnd dstPt293(Point(274.9431329624006, 1072.323511533372), 1);
+ connRef293->setDestEndpoint(dstPt293);
+ connRef293->setRoutingType((ConnType)2);
+
+ ConnRef *connRef294 = new ConnRef(router, 294);
+ ConnEnd srcPt294(Point(829.7288472481148, 939.3235115333719), 8);
+ connRef294->setSourceEndpoint(srcPt294);
+ ConnEnd dstPt294(Point(894.7288472491148, 918.3235115333719), 15);
+ connRef294->setDestEndpoint(dstPt294);
+ connRef294->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints294(1);
+ checkpoints294[0] = Checkpoint(Point(852.7288472481148, 918.3235115333719), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef294->setRoutingCheckpoints(checkpoints294);
+
+ ConnRef *connRef295 = new ConnRef(router, 295);
+ ConnEnd srcPt295(Point(1250.728847251115, 655.9901782000385), 4);
+ connRef295->setSourceEndpoint(srcPt295);
+ ConnEnd dstPt295(Point(894.7288472491148, 918.3235115333719), 15);
+ connRef295->setDestEndpoint(dstPt295);
+ connRef295->setRoutingType((ConnType)2);
+
+ ConnRef *connRef296 = new ConnRef(router, 296);
+ ConnEnd srcPt296(Point(1250.728847251115, 1053.323511533372), 4);
+ connRef296->setSourceEndpoint(srcPt296);
+ ConnEnd dstPt296(Point(894.7288472491148, 918.3235115333719), 15);
+ connRef296->setDestEndpoint(dstPt296);
+ connRef296->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints296(1);
+ checkpoints296[0] = Checkpoint(Point(1227.728847251115, 1074.323511533372), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef296->setRoutingCheckpoints(checkpoints296);
+
+ ConnRef *connRef297 = new ConnRef(router, 297);
+ ConnEnd srcPt297(Point(1250.728847251115, 1095.323511533372), 4);
+ connRef297->setSourceEndpoint(srcPt297);
+ ConnEnd dstPt297(Point(894.7288472491148, 918.3235115333719), 15);
+ connRef297->setDestEndpoint(dstPt297);
+ connRef297->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints297(1);
+ checkpoints297[0] = Checkpoint(Point(1227.728847251115, 1074.323511533372), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef297->setRoutingCheckpoints(checkpoints297);
+
+ ConnRef *connRef298 = new ConnRef(router, 298);
+ ConnEnd srcPt298(Point(1478.728847251115, 918.3235115333719), 15);
+ connRef298->setSourceEndpoint(srcPt298);
+ ConnEnd dstPt298(Point(1280.728847251115, 655.9901782000385), 8);
+ connRef298->setDestEndpoint(dstPt298);
+ connRef298->setRoutingType((ConnType)2);
+
+ ConnRef *connRef299 = new ConnRef(router, 299);
+ ConnEnd srcPt299(Point(1397.728847251115, 561.9901782000385), 15);
+ connRef299->setSourceEndpoint(srcPt299);
+ ConnEnd dstPt299(Point(1280.728847251115, 655.9901782000385), 8);
+ connRef299->setDestEndpoint(dstPt299);
+ connRef299->setRoutingType((ConnType)2);
+
+ ConnRef *connRef300 = new ConnRef(router, 300);
+ ConnEnd srcPt300(Point(1430.728847251115, 852.3235115333719), 15);
+ connRef300->setSourceEndpoint(srcPt300);
+ ConnEnd dstPt300(Point(1280.728847251115, 852.3235115333719), 8);
+ connRef300->setDestEndpoint(dstPt300);
+ connRef300->setRoutingType((ConnType)2);
+
+ ConnRef *connRef301 = new ConnRef(router, 301);
+ ConnEnd srcPt301(Point(1177.728847250115, 958.3235115333719), 8);
+ connRef301->setSourceEndpoint(srcPt301);
+ ConnEnd dstPt301(Point(1430.728847251115, 1054.323511533372), 15);
+ connRef301->setDestEndpoint(dstPt301);
+ connRef301->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints301(1);
+ checkpoints301[0] = Checkpoint(Point(1200.728847250115, 1054.323511533372), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef301->setRoutingCheckpoints(checkpoints301);
+
+ ConnRef *connRef302 = new ConnRef(router, 302);
+ ConnEnd srcPt302(Point(1177.728847250115, 1033.323511533372), 8);
+ connRef302->setSourceEndpoint(srcPt302);
+ ConnEnd dstPt302(Point(1430.728847251115, 1054.323511533372), 15);
+ connRef302->setDestEndpoint(dstPt302);
+ connRef302->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints302(1);
+ checkpoints302[0] = Checkpoint(Point(1200.728847250115, 1054.323511533372), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef302->setRoutingCheckpoints(checkpoints302);
+
+ ConnRef *connRef303 = new ConnRef(router, 303);
+ ConnEnd srcPt303(Point(1177.728847250115, 1075.323511533372), 8);
+ connRef303->setSourceEndpoint(srcPt303);
+ ConnEnd dstPt303(Point(1430.728847251115, 1054.323511533372), 15);
+ connRef303->setDestEndpoint(dstPt303);
+ connRef303->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints303(1);
+ checkpoints303[0] = Checkpoint(Point(1200.728847250115, 1054.323511533372), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef303->setRoutingCheckpoints(checkpoints303);
+
+ ConnRef *connRef304 = new ConnRef(router, 304);
+ ConnEnd srcPt304(Point(274.9431329624006, 1151.323511533372), 15);
+ connRef304->setSourceEndpoint(srcPt304);
+ ConnEnd dstPt304(Point(422.4431329624006, 1324.723511533372), 4);
+ connRef304->setDestEndpoint(dstPt304);
+ connRef304->setRoutingType((ConnType)2);
+
+ ConnRef *connRef305 = new ConnRef(router, 305);
+ ConnEnd srcPt305(Point(651.7288472481148, 1324.723511533372), 15);
+ connRef305->setSourceEndpoint(srcPt305);
+ ConnEnd dstPt305(Point(799.7288472481148, 1324.723511533372), 4);
+ connRef305->setDestEndpoint(dstPt305);
+ connRef305->setRoutingType((ConnType)2);
+
+ ConnRef *connRef306 = new ConnRef(router, 306);
+ ConnEnd srcPt306(Point(1250.728847251115, 1267.323511533372), 4);
+ connRef306->setSourceEndpoint(srcPt306);
+ ConnEnd dstPt306(Point(894.7288472491148, 1324.723511533372), 15);
+ connRef306->setDestEndpoint(dstPt306);
+ connRef306->setRoutingType((ConnType)2);
+
+ ConnRef *connRef307 = new ConnRef(router, 307);
+ ConnEnd srcPt307(Point(1478.728847251115, 1324.723511533372), 15);
+ connRef307->setSourceEndpoint(srcPt307);
+ ConnEnd dstPt307(Point(1280.728847251115, 1267.323511533372), 8);
+ connRef307->setDestEndpoint(dstPt307);
+ connRef307->setRoutingType((ConnType)2);
+
+ ConnRef *connRef308 = new ConnRef(router, 308);
+ ConnEnd srcPt308(Point(-441.9508064335388, 1480.609225819086), 15);
+ connRef308->setSourceEndpoint(srcPt308);
+ ConnEnd dstPt308(Point(-78.22353370526614, 1480.609225819086), 4);
+ connRef308->setDestEndpoint(dstPt308);
+ connRef308->setRoutingType((ConnType)2);
+
+ ConnRef *connRef309 = new ConnRef(router, 309);
+ ConnEnd srcPt309(Point(35.77646629473389, 1480.609225819086), 15);
+ connRef309->setSourceEndpoint(srcPt309);
+ ConnEnd dstPt309(Point(422.4431329624006, 1480.609225819086), 4);
+ connRef309->setDestEndpoint(dstPt309);
+ connRef309->setRoutingType((ConnType)2);
+
+ ConnRef *connRef310 = new ConnRef(router, 310);
+ ConnEnd srcPt310(Point(799.7288472481148, 1459.609225819086), 4);
+ connRef310->setSourceEndpoint(srcPt310);
+ ConnEnd dstPt310(Point(651.7288472481148, 1480.609225819086), 15);
+ connRef310->setDestEndpoint(dstPt310);
+ connRef310->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints310(1);
+ checkpoints310[0] = Checkpoint(Point(776.7288472481148, 1480.609225819086), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef310->setRoutingCheckpoints(checkpoints310);
+
+ ConnRef *connRef311 = new ConnRef(router, 311);
+ ConnEnd srcPt311(Point(829.7288472481148, 1501.609225819086), 8);
+ connRef311->setSourceEndpoint(srcPt311);
+ ConnEnd dstPt311(Point(894.7288472491148, 1480.609225819086), 15);
+ connRef311->setDestEndpoint(dstPt311);
+ connRef311->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints311(1);
+ checkpoints311[0] = Checkpoint(Point(852.7288472481148, 1480.609225819086), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef311->setRoutingCheckpoints(checkpoints311);
+
+ ConnRef *connRef312 = new ConnRef(router, 312);
+ ConnEnd srcPt312(Point(1250.728847251115, 1423.323511533372), 4);
+ connRef312->setSourceEndpoint(srcPt312);
+ ConnEnd dstPt312(Point(894.7288472491148, 1480.609225819086), 15);
+ connRef312->setDestEndpoint(dstPt312);
+ connRef312->setRoutingType((ConnType)2);
+
+ ConnRef *connRef313 = new ConnRef(router, 313);
+ ConnEnd srcPt313(Point(1478.728847251115, 1480.609225819086), 15);
+ connRef313->setSourceEndpoint(srcPt313);
+ ConnEnd dstPt313(Point(1280.728847251115, 1423.323511533372), 8);
+ connRef313->setDestEndpoint(dstPt313);
+ connRef313->setRoutingType((ConnType)2);
+
+ ConnRef *connRef314 = new ConnRef(router, 314);
+ ConnEnd srcPt314(Point(-423.9508064335388, 404.2282734381338), 4);
+ connRef314->setSourceEndpoint(srcPt314);
+ ConnEnd dstPt314(Point(-553.9508064345389, 308.2282734381338), 15);
+ connRef314->setDestEndpoint(dstPt314);
+ connRef314->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints314(1);
+ checkpoints314[0] = Checkpoint(Point(-446.9508064335388, 308.2282734381338), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef314->setRoutingCheckpoints(checkpoints314);
+
+ ConnRef *connRef315 = new ConnRef(router, 315);
+ ConnEnd srcPt315(Point(-150.8902003719328, 903.3235115333719), 1);
+ connRef315->setSourceEndpoint(srcPt315);
+ ConnEnd dstPt315(Point(-150.8902003719328, 796.3235115333719), 15);
+ connRef315->setDestEndpoint(dstPt315);
+ connRef315->setRoutingType((ConnType)2);
+
+ ConnRef *connRef316 = new ConnRef(router, 316);
+ ConnEnd srcPt316(Point(422.4431329624006, 715.9901782000385), 4);
+ connRef316->setSourceEndpoint(srcPt316);
+ ConnEnd dstPt316(Point(371.4431329624006, 796.3235115333719), 15);
+ connRef316->setDestEndpoint(dstPt316);
+ connRef316->setRoutingType((ConnType)2);
+
+ ConnRef *connRef317 = new ConnRef(router, 317);
+ ConnEnd srcPt317(Point(452.4431329624006, 951.3235115333719), 8);
+ connRef317->setSourceEndpoint(srcPt317);
+ ConnEnd dstPt317(Point(651.7288472481148, 918.3235115333719), 15);
+ connRef317->setDestEndpoint(dstPt317);
+ connRef317->setRoutingType((ConnType)2);
+
+ ConnRef *connRef318 = new ConnRef(router, 318);
+ ConnEnd srcPt318(Point(829.7288472481148, 897.3235115333719), 8);
+ connRef318->setSourceEndpoint(srcPt318);
+ ConnEnd dstPt318(Point(894.7288472491148, 918.3235115333719), 15);
+ connRef318->setDestEndpoint(dstPt318);
+ connRef318->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints318(1);
+ checkpoints318[0] = Checkpoint(Point(852.7288472481148, 918.3235115333719), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef318->setRoutingCheckpoints(checkpoints318);
+
+ ConnRef *connRef319 = new ConnRef(router, 319);
+ ConnEnd srcPt319(Point(274.9431329624006, 1102.323511533372), 2);
+ connRef319->setSourceEndpoint(srcPt319);
+ ConnEnd dstPt319(Point(274.9431329624006, 1151.323511533372), 15);
+ connRef319->setDestEndpoint(dstPt319);
+ connRef319->setRoutingType((ConnType)2);
+
+ ConnRef *connRef320 = new ConnRef(router, 320);
+ ConnEnd srcPt320(Point(452.4431329624006, 1324.723511533372), 8);
+ connRef320->setSourceEndpoint(srcPt320);
+ ConnEnd dstPt320(Point(651.7288472481148, 1324.723511533372), 15);
+ connRef320->setDestEndpoint(dstPt320);
+ connRef320->setRoutingType((ConnType)2);
+
+ ConnRef *connRef321 = new ConnRef(router, 321);
+ ConnEnd srcPt321(Point(829.7288472481148, 1324.723511533372), 8);
+ connRef321->setSourceEndpoint(srcPt321);
+ ConnEnd dstPt321(Point(894.7288472491148, 1324.723511533372), 15);
+ connRef321->setDestEndpoint(dstPt321);
+ connRef321->setRoutingType((ConnType)2);
+
+ ConnRef *connRef322 = new ConnRef(router, 322);
+ ConnEnd srcPt322(Point(-48.22353370526614, 1480.609225819086), 8);
+ connRef322->setSourceEndpoint(srcPt322);
+ ConnEnd dstPt322(Point(35.77646629473389, 1480.609225819086), 15);
+ connRef322->setDestEndpoint(dstPt322);
+ connRef322->setRoutingType((ConnType)2);
+
+ ConnRef *connRef323 = new ConnRef(router, 323);
+ ConnEnd srcPt323(Point(452.4431329624006, 1480.609225819086), 8);
+ connRef323->setSourceEndpoint(srcPt323);
+ ConnEnd dstPt323(Point(651.7288472481148, 1480.609225819086), 15);
+ connRef323->setDestEndpoint(dstPt323);
+ connRef323->setRoutingType((ConnType)2);
+
+ ConnRef *connRef324 = new ConnRef(router, 324);
+ ConnEnd srcPt324(Point(829.7288472481148, 1459.609225819086), 8);
+ connRef324->setSourceEndpoint(srcPt324);
+ ConnEnd dstPt324(Point(894.7288472491148, 1480.609225819086), 15);
+ connRef324->setDestEndpoint(dstPt324);
+ connRef324->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints324(1);
+ checkpoints324[0] = Checkpoint(Point(852.7288472481148, 1480.609225819086), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef324->setRoutingCheckpoints(checkpoints324);
+
+ ConnRef *connRef325 = new ConnRef(router, 325);
+ ConnEnd srcPt325(Point(799.7288472481148, 1501.609225819086), 4);
+ connRef325->setSourceEndpoint(srcPt325);
+ ConnEnd dstPt325(Point(651.7288472481148, 1480.609225819086), 15);
+ connRef325->setDestEndpoint(dstPt325);
+ connRef325->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints325(1);
+ checkpoints325[0] = Checkpoint(Point(776.7288472481148, 1480.609225819086), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef325->setRoutingCheckpoints(checkpoints325);
+
+ ConnRef *connRef326 = new ConnRef(router, 326);
+ ConnEnd srcPt326(Point(1250.728847251115, 852.3235115333719), 4);
+ connRef326->setSourceEndpoint(srcPt326);
+ ConnEnd dstPt326(Point(993.7288472491148, 852.3235115333719), 15);
+ connRef326->setDestEndpoint(dstPt326);
+ connRef326->setRoutingType((ConnType)2);
+
+ ConnRef *connRef327 = new ConnRef(router, 327);
+ ConnEnd srcPt327(Point(1250.728847251115, 655.9901782000385), 4);
+ connRef327->setSourceEndpoint(srcPt327);
+ ConnEnd dstPt327(Point(1096.728847250115, 561.9901782000385), 15);
+ connRef327->setDestEndpoint(dstPt327);
+ connRef327->setRoutingType((ConnType)2);
+
+ ConnRef *connRef328 = new ConnRef(router, 328);
+ ConnEnd srcPt328(Point(1147.728847250115, 958.3235115333719), 4);
+ connRef328->setSourceEndpoint(srcPt328);
+ ConnEnd dstPt328(Point(993.7288472491148, 1054.323511533372), 15);
+ connRef328->setDestEndpoint(dstPt328);
+ connRef328->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints328(1);
+ checkpoints328[0] = Checkpoint(Point(1124.728847250115, 1054.323511533372), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef328->setRoutingCheckpoints(checkpoints328);
+
+ ConnRef *connRef329 = new ConnRef(router, 329);
+ ConnEnd srcPt329(Point(1147.728847250115, 1033.323511533372), 4);
+ connRef329->setSourceEndpoint(srcPt329);
+ ConnEnd dstPt329(Point(993.7288472491148, 1054.323511533372), 15);
+ connRef329->setDestEndpoint(dstPt329);
+ connRef329->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints329(1);
+ checkpoints329[0] = Checkpoint(Point(1124.728847250115, 1054.323511533372), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef329->setRoutingCheckpoints(checkpoints329);
+
+ ConnRef *connRef330 = new ConnRef(router, 330);
+ ConnEnd srcPt330(Point(1280.728847251115, 1053.323511533372), 8);
+ connRef330->setSourceEndpoint(srcPt330);
+ ConnEnd dstPt330(Point(1478.728847251115, 918.3235115333719), 15);
+ connRef330->setDestEndpoint(dstPt330);
+ connRef330->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints330(1);
+ checkpoints330[0] = Checkpoint(Point(1303.728847251115, 1074.323511533372), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef330->setRoutingCheckpoints(checkpoints330);
+
+ ConnRef *connRef331 = new ConnRef(router, 331);
+ ConnEnd srcPt331(Point(1280.728847251115, 1095.323511533372), 8);
+ connRef331->setSourceEndpoint(srcPt331);
+ ConnEnd dstPt331(Point(1478.728847251115, 918.3235115333719), 15);
+ connRef331->setDestEndpoint(dstPt331);
+ connRef331->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints331(1);
+ checkpoints331[0] = Checkpoint(Point(1303.728847251115, 1074.323511533372), (ConnDirFlags) 15, (ConnDirFlags) 8);
+ connRef331->setRoutingCheckpoints(checkpoints331);
+
+ ConnRef *connRef332 = new ConnRef(router, 332);
+ ConnEnd srcPt332(Point(106.7764662947339, -148.3431551362948), 1);
+ connRef332->setSourceEndpoint(srcPt332);
+ ConnEnd dstPt332(Point(437.4431329624006, -323.3431551372947), 15);
+ connRef332->setDestEndpoint(dstPt332);
+ connRef332->setRoutingType((ConnType)2);
+
+ ConnRef *connRef333 = new ConnRef(router, 333);
+ ConnEnd srcPt333(Point(864.7288472481148, 467.9901782000385), 8);
+ connRef333->setSourceEndpoint(srcPt333);
+ ConnEnd dstPt333(Point(1129.728847250115, 308.2282734381338), 15);
+ connRef333->setDestEndpoint(dstPt333);
+ connRef333->setRoutingType((ConnType)2);
+
+ ConnRef *connRef334 = new ConnRef(router, 334);
+ ConnEnd srcPt334(Point(106.7764662947339, -46.34315513529478), 1);
+ connRef334->setSourceEndpoint(srcPt334);
+ ConnEnd dstPt334(Point(437.4431329624006, -323.3431551372947), 15);
+ connRef334->setDestEndpoint(dstPt334);
+ connRef334->setRoutingType((ConnType)2);
+
+ ConnRef *connRef335 = new ConnRef(router, 335);
+ ConnEnd srcPt335(Point(942.7288472491148, 467.9901782000385), 8);
+ connRef335->setSourceEndpoint(srcPt335);
+ ConnEnd dstPt335(Point(1129.728847250115, 308.2282734381338), 15);
+ connRef335->setDestEndpoint(dstPt335);
+ connRef335->setRoutingType((ConnType)2);
+
+ ConnRef *connRef336 = new ConnRef(router, 336);
+ ConnEnd srcPt336(Point(106.7764662947339, 55.65684486570521), 1);
+ connRef336->setSourceEndpoint(srcPt336);
+ ConnEnd dstPt336(Point(437.4431329624006, -323.3431551372947), 15);
+ connRef336->setDestEndpoint(dstPt336);
+ connRef336->setRoutingType((ConnType)2);
+
+ ConnRef *connRef337 = new ConnRef(router, 337);
+ ConnEnd srcPt337(Point(1041.728847249115, 467.9901782000385), 8);
+ connRef337->setSourceEndpoint(srcPt337);
+ ConnEnd dstPt337(Point(1129.728847250115, 308.2282734381338), 15);
+ connRef337->setDestEndpoint(dstPt337);
+ connRef337->setRoutingType((ConnType)2);
+
+ ConnRef *connRef338 = new ConnRef(router, 338);
+ ConnEnd srcPt338(Point(256.9431329624006, -31.34315513529478), 8);
+ connRef338->setSourceEndpoint(srcPt338);
+ ConnEnd dstPt338(Point(437.4431329624006, -323.3431551372947), 15);
+ connRef338->setDestEndpoint(dstPt338);
+ connRef338->setRoutingType((ConnType)2);
+
+ ConnRef *connRef339 = new ConnRef(router, 339);
+ ConnEnd srcPt339(Point(942.7288472491148, 374.561606771467), 8);
+ connRef339->setSourceEndpoint(srcPt339);
+ ConnEnd dstPt339(Point(1129.728847250115, 308.2282734381338), 15);
+ connRef339->setDestEndpoint(dstPt339);
+ connRef339->setRoutingType((ConnType)2);
+
+ ConnRef *connRef340 = new ConnRef(router, 340);
+ ConnEnd srcPt340(Point(1147.728847250115, 1075.323511533372), 4);
+ connRef340->setSourceEndpoint(srcPt340);
+ ConnEnd dstPt340(Point(993.7288472491148, 1054.323511533372), 15);
+ connRef340->setDestEndpoint(dstPt340);
+ connRef340->setRoutingType((ConnType)2);
+ std::vector<Checkpoint> checkpoints340(1);
+ checkpoints340[0] = Checkpoint(Point(1124.728847250115, 1054.323511533372), (ConnDirFlags) 15, (ConnDirFlags) 4);
+ connRef340->setRoutingCheckpoints(checkpoints340);
+
+ ConnRef *connRef341 = new ConnRef(router, 341);
+ ConnEnd srcPt341(Point(1041.728847249115, 374.561606771467), 8);
+ connRef341->setSourceEndpoint(srcPt341);
+ ConnEnd dstPt341(Point(1129.728847250115, 308.2282734381338), 15);
+ connRef341->setDestEndpoint(dstPt341);
+ connRef341->setRoutingType((ConnType)2);
+
+ ConnRef *connRef342 = new ConnRef(router, 342);
+ ConnEnd srcPt342(Point(1041.728847249115, 374.561606771467), 8);
+ connRef342->setSourceEndpoint(srcPt342);
+ ConnEnd dstPt342(Point(1331.728847251115, 434.9901782000385), 15);
+ connRef342->setDestEndpoint(dstPt342);
+ connRef342->setRoutingType((ConnType)2);
+
+ ConnRef *connRef343 = new ConnRef(router, 343);
+ ConnEnd srcPt343(Point(960.7288472491148, 196.2282734371338), 2);
+ connRef343->setSourceEndpoint(srcPt343);
+ ConnEnd dstPt343(Point(960.7288472491148, 246.2282734371338), 1);
+ connRef343->setDestEndpoint(dstPt343);
+ connRef343->setRoutingType((ConnType)2);
+
+ ConnRef *connRef344 = new ConnRef(router, 344);
+ ConnEnd srcPt344(Point(849.7288472481148, 324.561606771467), 2);
+ connRef344->setSourceEndpoint(srcPt344);
+ ConnEnd dstPt344(Point(849.7288472481148, 374.561606771467), 1);
+ connRef344->setDestEndpoint(dstPt344);
+ connRef344->setRoutingType((ConnType)2);
+
+ ConnRef *connRef345 = new ConnRef(router, 345);
+ ConnEnd srcPt345(Point(618.7288472481148, 384.9901782000385), 2);
+ connRef345->setSourceEndpoint(srcPt345);
+ ConnEnd dstPt345(Point(618.7288472481148, 434.9901782000385), 1);
+ connRef345->setDestEndpoint(dstPt345);
+ connRef345->setRoutingType((ConnType)2);
+
+ ConnRef *connRef346 = new ConnRef(router, 346);
+ ConnEnd srcPt346(Point(-280.9508064325389, 336.2282734371338), 2);
+ connRef346->setSourceEndpoint(srcPt346);
+ ConnEnd dstPt346(Point(-280.9508064325389, 386.2282734371338), 1);
+ connRef346->setDestEndpoint(dstPt346);
+ connRef346->setRoutingType((ConnType)2);
+
+ ConnRef *connRef347 = new ConnRef(router, 347);
+ ConnEnd srcPt347(Point(-280.9508064325389, 411.2282734371338), 2);
+ connRef347->setSourceEndpoint(srcPt347);
+ ConnEnd dstPt347(Point(-280.9508064325389, 461.2282734371338), 1);
+ connRef347->setDestEndpoint(dstPt347);
+ connRef347->setRoutingType((ConnType)2);
+
+ ConnRef *connRef348 = new ConnRef(router, 348);
+ ConnEnd srcPt348(Point(-280.9508064325389, 486.2282734371338), 2);
+ connRef348->setSourceEndpoint(srcPt348);
+ ConnEnd dstPt348(Point(-280.9508064325389, 536.2282734371338), 1);
+ connRef348->setDestEndpoint(dstPt348);
+ connRef348->setRoutingType((ConnType)2);
+
+ ConnRef *connRef349 = new ConnRef(router, 349);
+ ConnEnd srcPt349(Point(-280.9508064325389, 561.2282734371338), 2);
+ connRef349->setSourceEndpoint(srcPt349);
+ ConnEnd dstPt349(Point(-280.9508064325389, 611.2282734371338), 1);
+ connRef349->setDestEndpoint(dstPt349);
+ connRef349->setRoutingType((ConnType)2);
+
+ ConnRef *connRef350 = new ConnRef(router, 350);
+ ConnEnd srcPt350(Point(-280.9508064325389, 636.2282734371338), 2);
+ connRef350->setSourceEndpoint(srcPt350);
+ ConnEnd dstPt350(Point(-280.9508064325389, 686.2282734371338), 1);
+ connRef350->setDestEndpoint(dstPt350);
+ connRef350->setRoutingType((ConnType)2);
+
+ ConnRef *connRef351 = new ConnRef(router, 351);
+ ConnEnd srcPt351(Point(-280.9508064325389, 1003.228273437134), 1);
+ connRef351->setSourceEndpoint(srcPt351);
+ ConnEnd dstPt351(Point(-280.9508064325389, 953.2282734371338), 2);
+ connRef351->setDestEndpoint(dstPt351);
+ connRef351->setRoutingType((ConnType)2);
+
+ ConnRef *connRef352 = new ConnRef(router, 352);
+ ConnEnd srcPt352(Point(-280.9508064325389, 711.2282734371338), 2);
+ connRef352->setSourceEndpoint(srcPt352);
+ ConnEnd dstPt352(Point(-280.9508064325389, 761.2282734371338), 1);
+ connRef352->setDestEndpoint(dstPt352);
+ connRef352->setRoutingType((ConnType)2);
+
+ ConnRef *connRef353 = new ConnRef(router, 353);
+ ConnEnd srcPt353(Point(-280.9508064325389, 853.2282734371338), 1);
+ connRef353->setSourceEndpoint(srcPt353);
+ ConnEnd dstPt353(Point(-280.9508064325389, 803.2282734371338), 2);
+ connRef353->setDestEndpoint(dstPt353);
+ connRef353->setRoutingType((ConnType)2);
+
+ ConnRef *connRef354 = new ConnRef(router, 354);
+ ConnEnd srcPt354(Point(-280.9508064325389, 928.2282734371338), 1);
+ connRef354->setSourceEndpoint(srcPt354);
+ ConnEnd dstPt354(Point(-280.9508064325389, 878.2282734371338), 2);
+ connRef354->setDestEndpoint(dstPt354);
+ connRef354->setRoutingType((ConnType)2);
+
+ ConnRef *connRef355 = new ConnRef(router, 355);
+ ConnEnd srcPt355(Point(-280.9508064325389, 1078.228273437134), 1);
+ connRef355->setSourceEndpoint(srcPt355);
+ ConnEnd dstPt355(Point(-280.9508064325389, 1028.228273437134), 2);
+ connRef355->setDestEndpoint(dstPt355);
+ connRef355->setRoutingType((ConnType)2);
+
+ ConnRef *connRef356 = new ConnRef(router, 356);
+ ConnEnd srcPt356(Point(-408.9508064335388, 162.2282734381338), 2);
+ connRef356->setSourceEndpoint(srcPt356);
+ ConnEnd dstPt356(Point(-408.9508064335388, 212.2282734381338), 1);
+ connRef356->setDestEndpoint(dstPt356);
+ connRef356->setRoutingType((ConnType)2);
+
+ ConnRef *connRef357 = new ConnRef(router, 357);
+ ConnEnd srcPt357(Point(-408.9508064335388, 237.2282734381338), 2);
+ connRef357->setSourceEndpoint(srcPt357);
+ ConnEnd dstPt357(Point(-408.9508064335388, 287.2282734381338), 1);
+ connRef357->setDestEndpoint(dstPt357);
+ connRef357->setRoutingType((ConnType)2);
+
+ ConnRef *connRef358 = new ConnRef(router, 358);
+ ConnEnd srcPt358(Point(-408.9508064335388, 379.2282734381338), 1);
+ connRef358->setSourceEndpoint(srcPt358);
+ ConnEnd dstPt358(Point(-408.9508064335388, 329.2282734381338), 2);
+ connRef358->setDestEndpoint(dstPt358);
+ connRef358->setRoutingType((ConnType)2);
+
+ ConnRef *connRef359 = new ConnRef(router, 359);
+ ConnEnd srcPt359(Point(585.7288472481148, 196.2282734371338), 2);
+ connRef359->setSourceEndpoint(srcPt359);
+ ConnEnd dstPt359(Point(585.7288472481148, 246.2282734371338), 1);
+ connRef359->setDestEndpoint(dstPt359);
+ connRef359->setRoutingType((ConnType)2);
+
+ ConnRef *connRef360 = new ConnRef(router, 360);
+ ConnEnd srcPt360(Point(775.7288472481148, -268.3431551362947), 4);
+ connRef360->setSourceEndpoint(srcPt360);
+ ConnEnd dstPt360(Point(717.7288472481148, -268.3431551362947), 8);
+ connRef360->setDestEndpoint(dstPt360);
+ connRef360->setRoutingType((ConnType)2);
+
+ ConnRef *connRef361 = new ConnRef(router, 361);
+ ConnEnd srcPt361(Point(216.7764662957339, 169.6568448657052), 4);
+ connRef361->setSourceEndpoint(srcPt361);
+ ConnEnd dstPt361(Point(158.7764662957339, 169.6568448657052), 8);
+ connRef361->setDestEndpoint(dstPt361);
+ connRef361->setRoutingType((ConnType)2);
+
+ ConnRef *connRef362 = new ConnRef(router, 362);
+ ConnEnd srcPt362(Point(241.9431329624006, -183.3431551362948), 2);
+ connRef362->setSourceEndpoint(srcPt362);
+ ConnEnd dstPt362(Point(241.9431329624006, -133.3431551362948), 1);
+ connRef362->setDestEndpoint(dstPt362);
+ connRef362->setRoutingType((ConnType)2);
+
+ ConnRef *connRef363 = new ConnRef(router, 363);
+ ConnEnd srcPt363(Point(338.4431329624006, -601.3431551372947), 2);
+ connRef363->setSourceEndpoint(srcPt363);
+ ConnEnd dstPt363(Point(338.4431329624006, -551.3431551372947), 1);
+ connRef363->setDestEndpoint(dstPt363);
+ connRef363->setRoutingType((ConnType)2);
+
+ ConnRef *connRef364 = new ConnRef(router, 364);
+ ConnEnd srcPt364(Point(552.7288472481148, -691.8431551372947), 2);
+ connRef364->setSourceEndpoint(srcPt364);
+ ConnEnd dstPt364(Point(552.7288472481148, -641.8431551372947), 1);
+ connRef364->setDestEndpoint(dstPt364);
+ connRef364->setRoutingType((ConnType)2);
+
+ ConnRef *connRef365 = new ConnRef(router, 365);
+ ConnEnd srcPt365(Point(-278.9735337052662, 136.6568448657052), 8);
+ connRef365->setSourceEndpoint(srcPt365);
+ ConnEnd dstPt365(Point(-220.9735337052661, 136.6568448657052), 4);
+ connRef365->setDestEndpoint(dstPt365);
+ connRef365->setRoutingType((ConnType)2);
+
+ ConnRef *connRef366 = new ConnRef(router, 366);
+ ConnEnd srcPt366(Point(-162.9735337052661, -356.3431551372947), 4);
+ connRef366->setSourceEndpoint(srcPt366);
+ ConnEnd dstPt366(Point(-220.9735337052661, -356.3431551372947), 8);
+ connRef366->setDestEndpoint(dstPt366);
+ connRef366->setRoutingType((ConnType)2);
+
+ ConnRef *connRef367 = new ConnRef(router, 367);
+ ConnEnd srcPt367(Point(1430.728847251115, 384.9901782000385), 2);
+ connRef367->setSourceEndpoint(srcPt367);
+ ConnEnd dstPt367(Point(1430.728847251115, 434.9901782000385), 1);
+ connRef367->setDestEndpoint(dstPt367);
+ connRef367->setRoutingType((ConnType)2);
+
+ ConnRef *connRef368 = new ConnRef(router, 368);
+ ConnEnd srcPt368(Point(404.4431329624006, 384.9901782000385), 2);
+ connRef368->setSourceEndpoint(srcPt368);
+ ConnEnd dstPt368(Point(404.4431329624006, 434.9901782000385), 1);
+ connRef368->setDestEndpoint(dstPt368);
+ connRef368->setRoutingType((ConnType)2);
+
+ ConnRef *connRef369 = new ConnRef(router, 369);
+ ConnEnd srcPt369(Point(495.4431329624006, 885.3235115333719), 4);
+ connRef369->setSourceEndpoint(srcPt369);
+ ConnEnd dstPt369(Point(437.4431329624006, 885.3235115333719), 8);
+ connRef369->setDestEndpoint(dstPt369);
+ connRef369->setRoutingType((ConnType)2);
+
+ ConnRef *connRef370 = new ConnRef(router, 370);
+ ConnEnd srcPt370(Point(495.4431329624006, 594.9901782000385), 4);
+ connRef370->setSourceEndpoint(srcPt370);
+ ConnEnd dstPt370(Point(437.4431329624006, 594.9901782000385), 8);
+ connRef370->setDestEndpoint(dstPt370);
+ connRef370->setRoutingType((ConnType)2);
+
+ ConnRef *connRef371 = new ConnRef(router, 371);
+ ConnEnd srcPt371(Point(-501.9508064345389, 196.2282734371338), 2);
+ connRef371->setSourceEndpoint(srcPt371);
+ ConnEnd dstPt371(Point(-501.9508064345389, 246.2282734371338), 1);
+ connRef371->setDestEndpoint(dstPt371);
+ connRef371->setRoutingType((ConnType)2);
+
+ ConnRef *connRef372 = new ConnRef(router, 372);
+ ConnEnd srcPt372(Point(-280.9508064325389, 1153.228273437134), 1);
+ connRef372->setSourceEndpoint(srcPt372);
+ ConnEnd dstPt372(Point(-280.9508064325389, 1103.228273437134), 2);
+ connRef372->setDestEndpoint(dstPt372);
+ connRef372->setRoutingType((ConnType)2);
+
+ ConnRef *connRef373 = new ConnRef(router, 373);
+ ConnEnd srcPt373(Point(-408.9508064335388, 454.2282734381338), 1);
+ connRef373->setSourceEndpoint(srcPt373);
+ ConnEnd dstPt373(Point(-408.9508064335388, 404.2282734381338), 2);
+ connRef373->setDestEndpoint(dstPt373);
+ connRef373->setRoutingType((ConnType)2);
+
+ ConnRef *connRef374 = new ConnRef(router, 374);
+ ConnEnd srcPt374(Point(-92.89020037193279, 918.3235115333719), 4);
+ connRef374->setSourceEndpoint(srcPt374);
+ ConnEnd dstPt374(Point(-150.8902003719328, 918.3235115333719), 8);
+ connRef374->setDestEndpoint(dstPt374);
+ connRef374->setRoutingType((ConnType)2);
+
+ ConnRef *connRef375 = new ConnRef(router, 375);
+ ConnEnd srcPt375(Point(2.776466294733893, 746.3235115333719), 2);
+ connRef375->setSourceEndpoint(srcPt375);
+ ConnEnd dstPt375(Point(2.776466294733893, 796.3235115333719), 1);
+ connRef375->setDestEndpoint(dstPt375);
+ connRef375->setRoutingType((ConnType)2);
+
+ ConnRef *connRef376 = new ConnRef(router, 376);
+ ConnEnd srcPt376(Point(437.4431329624006, 665.9901782000385), 2);
+ connRef376->setSourceEndpoint(srcPt376);
+ ConnEnd dstPt376(Point(437.4431329624006, 715.9901782000385), 1);
+ connRef376->setDestEndpoint(dstPt376);
+ connRef376->setRoutingType((ConnType)2);
+
+ ConnRef *connRef377 = new ConnRef(router, 377);
+ ConnEnd srcPt377(Point(437.4431329624006, 1001.323511533372), 1);
+ connRef377->setSourceEndpoint(srcPt377);
+ ConnEnd dstPt377(Point(437.4431329624006, 951.3235115333719), 2);
+ connRef377->setDestEndpoint(dstPt377);
+ connRef377->setRoutingType((ConnType)2);
+
+ ConnRef *connRef378 = new ConnRef(router, 378);
+ ConnEnd srcPt378(Point(814.7288472481148, 989.3235115333719), 1);
+ connRef378->setSourceEndpoint(srcPt378);
+ ConnEnd dstPt378(Point(814.7288472481148, 939.3235115333719), 2);
+ connRef378->setDestEndpoint(dstPt378);
+ connRef378->setRoutingType((ConnType)2);
+
+ ConnRef *connRef379 = new ConnRef(router, 379);
+ ConnEnd srcPt379(Point(814.7288472481148, 847.3235115333719), 2);
+ connRef379->setSourceEndpoint(srcPt379);
+ ConnEnd dstPt379(Point(814.7288472481148, 897.3235115333719), 1);
+ connRef379->setDestEndpoint(dstPt379);
+ connRef379->setRoutingType((ConnType)2);
+
+ ConnRef *connRef380 = new ConnRef(router, 380);
+ ConnEnd srcPt380(Point(332.9431329624006, 1087.323511533372), 4);
+ connRef380->setSourceEndpoint(srcPt380);
+ ConnEnd dstPt380(Point(274.9431329624006, 1087.323511533372), 8);
+ connRef380->setDestEndpoint(dstPt380);
+ connRef380->setRoutingType((ConnType)2);
+
+ ConnRef *connRef381 = new ConnRef(router, 381);
+ ConnEnd srcPt381(Point(437.4431329624006, 1274.723511533372), 2);
+ connRef381->setSourceEndpoint(srcPt381);
+ ConnEnd dstPt381(Point(437.4431329624006, 1324.723511533372), 1);
+ connRef381->setDestEndpoint(dstPt381);
+ connRef381->setRoutingType((ConnType)2);
+
+ ConnRef *connRef382 = new ConnRef(router, 382);
+ ConnEnd srcPt382(Point(814.7288472481148, 1274.723511533372), 2);
+ connRef382->setSourceEndpoint(srcPt382);
+ ConnEnd dstPt382(Point(814.7288472481148, 1324.723511533372), 1);
+ connRef382->setDestEndpoint(dstPt382);
+ connRef382->setRoutingType((ConnType)2);
+
+ ConnRef *connRef383 = new ConnRef(router, 383);
+ ConnEnd srcPt383(Point(-63.22353370526614, 1430.609225819086), 2);
+ connRef383->setSourceEndpoint(srcPt383);
+ ConnEnd dstPt383(Point(-63.22353370526614, 1480.609225819086), 1);
+ connRef383->setDestEndpoint(dstPt383);
+ connRef383->setRoutingType((ConnType)2);
+
+ ConnRef *connRef384 = new ConnRef(router, 384);
+ ConnEnd srcPt384(Point(437.4431329624006, 1430.609225819086), 2);
+ connRef384->setSourceEndpoint(srcPt384);
+ ConnEnd dstPt384(Point(437.4431329624006, 1480.609225819086), 1);
+ connRef384->setDestEndpoint(dstPt384);
+ connRef384->setRoutingType((ConnType)2);
+
+ ConnRef *connRef385 = new ConnRef(router, 385);
+ ConnEnd srcPt385(Point(814.7288472481148, 1409.609225819086), 2);
+ connRef385->setSourceEndpoint(srcPt385);
+ ConnEnd dstPt385(Point(814.7288472481148, 1459.609225819086), 1);
+ connRef385->setDestEndpoint(dstPt385);
+ connRef385->setRoutingType((ConnType)2);
+
+ ConnRef *connRef386 = new ConnRef(router, 386);
+ ConnEnd srcPt386(Point(814.7288472481148, 1551.609225819086), 1);
+ connRef386->setSourceEndpoint(srcPt386);
+ ConnEnd dstPt386(Point(814.7288472481148, 1501.609225819086), 2);
+ connRef386->setDestEndpoint(dstPt386);
+ connRef386->setRoutingType((ConnType)2);
+
+ ConnRef *connRef387 = new ConnRef(router, 387);
+ ConnEnd srcPt387(Point(1265.728847251115, 802.3235115333719), 2);
+ connRef387->setSourceEndpoint(srcPt387);
+ ConnEnd dstPt387(Point(1265.728847251115, 852.3235115333719), 1);
+ connRef387->setDestEndpoint(dstPt387);
+ connRef387->setRoutingType((ConnType)2);
+
+ ConnRef *connRef388 = new ConnRef(router, 388);
+ ConnEnd srcPt388(Point(1265.728847251115, 605.9901782000385), 2);
+ connRef388->setSourceEndpoint(srcPt388);
+ ConnEnd dstPt388(Point(1265.728847251115, 655.9901782000385), 1);
+ connRef388->setDestEndpoint(dstPt388);
+ connRef388->setRoutingType((ConnType)2);
+
+ ConnRef *connRef389 = new ConnRef(router, 389);
+ ConnEnd srcPt389(Point(1162.728847250115, 908.3235115333719), 2);
+ connRef389->setSourceEndpoint(srcPt389);
+ ConnEnd dstPt389(Point(1162.728847250115, 958.3235115333719), 1);
+ connRef389->setDestEndpoint(dstPt389);
+ connRef389->setRoutingType((ConnType)2);
+
+ ConnRef *connRef390 = new ConnRef(router, 390);
+ ConnEnd srcPt390(Point(1162.728847250115, 983.3235115333719), 2);
+ connRef390->setSourceEndpoint(srcPt390);
+ ConnEnd dstPt390(Point(1162.728847250115, 1033.323511533372), 1);
+ connRef390->setDestEndpoint(dstPt390);
+ connRef390->setRoutingType((ConnType)2);
+
+ ConnRef *connRef391 = new ConnRef(router, 391);
+ ConnEnd srcPt391(Point(1265.728847251115, 1003.323511533372), 2);
+ connRef391->setSourceEndpoint(srcPt391);
+ ConnEnd dstPt391(Point(1265.728847251115, 1053.323511533372), 1);
+ connRef391->setDestEndpoint(dstPt391);
+ connRef391->setRoutingType((ConnType)2);
+
+ ConnRef *connRef392 = new ConnRef(router, 392);
+ ConnEnd srcPt392(Point(1265.728847251115, 1145.323511533372), 1);
+ connRef392->setSourceEndpoint(srcPt392);
+ ConnEnd dstPt392(Point(1265.728847251115, 1095.323511533372), 2);
+ connRef392->setDestEndpoint(dstPt392);
+ connRef392->setRoutingType((ConnType)2);
+
+ ConnRef *connRef393 = new ConnRef(router, 393);
+ ConnEnd srcPt393(Point(1265.728847251115, 1217.323511533372), 2);
+ connRef393->setSourceEndpoint(srcPt393);
+ ConnEnd dstPt393(Point(1265.728847251115, 1267.323511533372), 1);
+ connRef393->setDestEndpoint(dstPt393);
+ connRef393->setRoutingType((ConnType)2);
+
+ ConnRef *connRef394 = new ConnRef(router, 394);
+ ConnEnd srcPt394(Point(1265.728847251115, 1373.323511533372), 2);
+ connRef394->setSourceEndpoint(srcPt394);
+ ConnEnd dstPt394(Point(1265.728847251115, 1423.323511533372), 1);
+ connRef394->setDestEndpoint(dstPt394);
+ connRef394->setRoutingType((ConnType)2);
+
+ ConnRef *connRef395 = new ConnRef(router, 395);
+ ConnEnd srcPt395(Point(48.77646629473389, -133.3431551362948), 8);
+ connRef395->setSourceEndpoint(srcPt395);
+ ConnEnd dstPt395(Point(106.7764662947339, -133.3431551362948), 4);
+ connRef395->setDestEndpoint(dstPt395);
+ connRef395->setRoutingType((ConnType)2);
+
+ ConnRef *connRef396 = new ConnRef(router, 396);
+ ConnEnd srcPt396(Point(849.7288472481148, 517.9901782000385), 1);
+ connRef396->setSourceEndpoint(srcPt396);
+ ConnEnd dstPt396(Point(849.7288472481148, 467.9901782000385), 2);
+ connRef396->setDestEndpoint(dstPt396);
+ connRef396->setRoutingType((ConnType)2);
+
+ ConnRef *connRef397 = new ConnRef(router, 397);
+ ConnEnd srcPt397(Point(48.77646629473389, -31.34315513529478), 8);
+ connRef397->setSourceEndpoint(srcPt397);
+ ConnEnd dstPt397(Point(106.7764662947339, -31.34315513529478), 4);
+ connRef397->setDestEndpoint(dstPt397);
+ connRef397->setRoutingType((ConnType)2);
+
+ ConnRef *connRef398 = new ConnRef(router, 398);
+ ConnEnd srcPt398(Point(927.7288472491148, 517.9901782000385), 1);
+ connRef398->setSourceEndpoint(srcPt398);
+ ConnEnd dstPt398(Point(927.7288472491148, 467.9901782000385), 2);
+ connRef398->setDestEndpoint(dstPt398);
+ connRef398->setRoutingType((ConnType)2);
+
+ ConnRef *connRef399 = new ConnRef(router, 399);
+ ConnEnd srcPt399(Point(48.77646629473389, 70.65684486570521), 8);
+ connRef399->setSourceEndpoint(srcPt399);
+ ConnEnd dstPt399(Point(106.7764662947339, 70.65684486570521), 4);
+ connRef399->setDestEndpoint(dstPt399);
+ connRef399->setRoutingType((ConnType)2);
+
+ ConnRef *connRef400 = new ConnRef(router, 400);
+ ConnEnd srcPt400(Point(1026.728847249115, 517.9901782000385), 1);
+ connRef400->setSourceEndpoint(srcPt400);
+ ConnEnd dstPt400(Point(1026.728847249115, 467.9901782000385), 2);
+ connRef400->setDestEndpoint(dstPt400);
+ connRef400->setRoutingType((ConnType)2);
+
+ ConnRef *connRef401 = new ConnRef(router, 401);
+ ConnEnd srcPt401(Point(241.9431329624006, -81.34315513529478), 2);
+ connRef401->setSourceEndpoint(srcPt401);
+ ConnEnd dstPt401(Point(241.9431329624006, -31.34315513529478), 1);
+ connRef401->setDestEndpoint(dstPt401);
+ connRef401->setRoutingType((ConnType)2);
+
+ ConnRef *connRef402 = new ConnRef(router, 402);
+ ConnEnd srcPt402(Point(927.7288472491148, 324.561606771467), 2);
+ connRef402->setSourceEndpoint(srcPt402);
+ ConnEnd dstPt402(Point(927.7288472491148, 374.561606771467), 1);
+ connRef402->setDestEndpoint(dstPt402);
+ connRef402->setRoutingType((ConnType)2);
+
+ ConnRef *connRef403 = new ConnRef(router, 403);
+ ConnEnd srcPt403(Point(1162.728847250115, 1125.323511533372), 1);
+ connRef403->setSourceEndpoint(srcPt403);
+ ConnEnd dstPt403(Point(1162.728847250115, 1075.323511533372), 2);
+ connRef403->setDestEndpoint(dstPt403);
+ connRef403->setRoutingType((ConnType)2);
+
+ ConnRef *connRef404 = new ConnRef(router, 404);
+ ConnEnd srcPt404(Point(241.9431329624006, 20.65684486570521), 2);
+ connRef404->setSourceEndpoint(srcPt404);
+ ConnEnd dstPt404(Point(241.9431329624006, 70.65684486570521), 1);
+ connRef404->setDestEndpoint(dstPt404);
+ connRef404->setRoutingType((ConnType)2);
+
+ ConnRef *connRef405 = new ConnRef(router, 405);
+ ConnEnd srcPt405(Point(1026.728847249115, 324.561606771467), 2);
+ connRef405->setSourceEndpoint(srcPt405);
+ ConnEnd dstPt405(Point(1026.728847249115, 374.561606771467), 1);
+ connRef405->setDestEndpoint(dstPt405);
+ connRef405->setRoutingType((ConnType)2);
+
+ ConnRef *connRef406 = new ConnRef(router, 406);
+ ConnEnd srcPt406(Point(717.7288472481148, -518.3431551372947), 15);
+ connRef406->setSourceEndpoint(srcPt406);
+ ConnEnd dstPt406(Point(845.7288472481148, -468.8431551372947), 1);
+ connRef406->setDestEndpoint(dstPt406);
+ connRef406->setRoutingType((ConnType)2);
+
+ ConnRef *connRef407 = new ConnRef(router, 407);
+ ConnEnd srcPt407(Point(437.4431329624006, -323.3431551372947), 15);
+ connRef407->setSourceEndpoint(srcPt407);
+ ConnEnd dstPt407(Point(520.7288472481148, -412.3431551372947), 4);
+ connRef407->setDestEndpoint(dstPt407);
+ connRef407->setRoutingType((ConnType)2);
+
+ ConnRef *connRef408 = new ConnRef(router, 408);
+ ConnEnd srcPt408(Point(618.7288472481148, -202.3431551362948), 15);
+ connRef408->setSourceEndpoint(srcPt408);
+ ConnEnd dstPt408(Point(538.9431329624006, -256.3431551362947), 8);
+ connRef408->setDestEndpoint(dstPt408);
+ connRef408->setRoutingType((ConnType)2);
+
+ ConnRef *connRef409 = new ConnRef(router, 409);
+ ConnEnd srcPt409(Point(437.4431329624006, -323.3431551372947), 15);
+ connRef409->setSourceEndpoint(srcPt409);
+ ConnEnd dstPt409(Point(256.9431329624006, -417.3431551372947), 8);
+ connRef409->setDestEndpoint(dstPt409);
+ connRef409->setRoutingType((ConnType)2);
+#endif
+
+ router->processTransaction();
+ router->outputDiagram("output/nudgingSkipsCheckpoint02");
+ Avoid::PolyLine route249 = connRef249->displayRoute();
+
+ delete router;
+ return (route249.size() == 6) ? 0 : 1;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/orderassertion.cpp b/src/3rdparty/adaptagrams/libavoid/tests/orderassertion.cpp
new file mode 100644
index 0000000..ad2a5c3
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/orderassertion.cpp
@@ -0,0 +1,1720 @@
+// Test case that triggers the orderSwapped after a second call
+// to the PtOrder::addPoints method.
+
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 0);
+
+ Polygon poly73(4);
+ poly73.ps[0] = Point(232, 362);
+ poly73.ps[1] = Point(232, 402);
+ poly73.ps[2] = Point(192, 402);
+ poly73.ps[3] = Point(192, 362);
+ new ShapeRef(router, poly73, 73);
+
+ Polygon poly74(4);
+ poly74.ps[0] = Point(125, 362);
+ poly74.ps[1] = Point(125, 402);
+ poly74.ps[2] = Point(85, 402);
+ poly74.ps[3] = Point(85, 362);
+ new ShapeRef(router, poly74, 74);
+
+ Polygon poly75(4);
+ poly75.ps[0] = Point(77.5, 716);
+ poly75.ps[1] = Point(77.5, 880);
+ poly75.ps[2] = Point(20.5, 880);
+ poly75.ps[3] = Point(20.5, 716);
+ new ShapeRef(router, poly75, 75);
+
+ Polygon poly76(4);
+ poly76.ps[0] = Point(187, 713);
+ poly76.ps[1] = Point(187, 733);
+ poly76.ps[2] = Point(167, 733);
+ poly76.ps[3] = Point(167, 713);
+ new ShapeRef(router, poly76, 76);
+
+ Polygon poly77(4);
+ poly77.ps[0] = Point(139, 714);
+ poly77.ps[1] = Point(139, 754);
+ poly77.ps[2] = Point(99, 754);
+ poly77.ps[3] = Point(99, 714);
+ new ShapeRef(router, poly77, 77);
+
+ Polygon poly78(4);
+ poly78.ps[0] = Point(422, 951);
+ poly78.ps[1] = Point(422, 971);
+ poly78.ps[2] = Point(402, 971);
+ poly78.ps[3] = Point(402, 951);
+ new ShapeRef(router, poly78, 78);
+
+ Polygon poly79(4);
+ poly79.ps[0] = Point(187, 734);
+ poly79.ps[1] = Point(187, 754);
+ poly79.ps[2] = Point(167, 754);
+ poly79.ps[3] = Point(167, 734);
+ new ShapeRef(router, poly79, 79);
+
+ Polygon poly80(4);
+ poly80.ps[0] = Point(470, 951);
+ poly80.ps[1] = Point(470, 971);
+ poly80.ps[2] = Point(450, 971);
+ poly80.ps[3] = Point(450, 951);
+ new ShapeRef(router, poly80, 80);
+
+ Polygon poly81(4);
+ poly81.ps[0] = Point(669.5, 899.5);
+ poly81.ps[1] = Point(669.5, 934.5);
+ poly81.ps[2] = Point(532.5, 934.5);
+ poly81.ps[3] = Point(532.5, 899.5);
+ new ShapeRef(router, poly81, 81);
+
+ Polygon poly82(4);
+ poly82.ps[0] = Point(491, 471);
+ poly82.ps[1] = Point(491, 491);
+ poly82.ps[2] = Point(471, 491);
+ poly82.ps[3] = Point(471, 471);
+ new ShapeRef(router, poly82, 82);
+
+ Polygon poly83(4);
+ poly83.ps[0] = Point(565, 512);
+ poly83.ps[1] = Point(565, 532);
+ poly83.ps[2] = Point(545, 532);
+ poly83.ps[3] = Point(545, 512);
+ new ShapeRef(router, poly83, 83);
+
+ Polygon poly84(4);
+ poly84.ps[0] = Point(538, 531);
+ poly84.ps[1] = Point(538, 551);
+ poly84.ps[2] = Point(518, 551);
+ poly84.ps[3] = Point(518, 531);
+ new ShapeRef(router, poly84, 84);
+
+ Polygon poly85(4);
+ poly85.ps[0] = Point(272, 782);
+ poly85.ps[1] = Point(272, 802);
+ poly85.ps[2] = Point(252, 802);
+ poly85.ps[3] = Point(252, 782);
+ new ShapeRef(router, poly85, 85);
+
+ Polygon poly86(4);
+ poly86.ps[0] = Point(515, 512);
+ poly86.ps[1] = Point(515, 532);
+ poly86.ps[2] = Point(495, 532);
+ poly86.ps[3] = Point(495, 512);
+ new ShapeRef(router, poly86, 86);
+
+ Polygon poly87(4);
+ poly87.ps[0] = Point(391, 534);
+ poly87.ps[1] = Point(391, 574);
+ poly87.ps[2] = Point(351, 574);
+ poly87.ps[3] = Point(351, 534);
+ new ShapeRef(router, poly87, 87);
+
+ Polygon poly88(4);
+ poly88.ps[0] = Point(420, 573);
+ poly88.ps[1] = Point(420, 593);
+ poly88.ps[2] = Point(400, 593);
+ poly88.ps[3] = Point(400, 573);
+ new ShapeRef(router, poly88, 88);
+
+ Polygon poly89(4);
+ poly89.ps[0] = Point(421, 509);
+ poly89.ps[1] = Point(421, 529);
+ poly89.ps[2] = Point(401, 529);
+ poly89.ps[3] = Point(401, 509);
+ new ShapeRef(router, poly89, 89);
+
+ Polygon poly90(4);
+ poly90.ps[0] = Point(476, 426);
+ poly90.ps[1] = Point(476, 466);
+ poly90.ps[2] = Point(436, 466);
+ poly90.ps[3] = Point(436, 426);
+ new ShapeRef(router, poly90, 90);
+
+ Polygon poly91(4);
+ poly91.ps[0] = Point(290, 970);
+ poly91.ps[1] = Point(290, 1010);
+ poly91.ps[2] = Point(234, 1010);
+ poly91.ps[3] = Point(234, 970);
+ new ShapeRef(router, poly91, 91);
+
+ Polygon poly92(4);
+ poly92.ps[0] = Point(77, 888);
+ poly92.ps[1] = Point(77, 928);
+ poly92.ps[2] = Point(21, 928);
+ poly92.ps[3] = Point(21, 888);
+ new ShapeRef(router, poly92, 92);
+
+ Polygon poly93(4);
+ poly93.ps[0] = Point(360, 991);
+ poly93.ps[1] = Point(360, 1031);
+ poly93.ps[2] = Point(304, 1031);
+ poly93.ps[3] = Point(304, 991);
+ new ShapeRef(router, poly93, 93);
+
+ Polygon poly94(4);
+ poly94.ps[0] = Point(449, 889);
+ poly94.ps[1] = Point(449, 929);
+ poly94.ps[2] = Point(393, 929);
+ poly94.ps[3] = Point(393, 889);
+ new ShapeRef(router, poly94, 94);
+
+ Polygon poly95(4);
+ poly95.ps[0] = Point(488, 970);
+ poly95.ps[1] = Point(488, 1010);
+ poly95.ps[2] = Point(432, 1010);
+ poly95.ps[3] = Point(432, 970);
+ new ShapeRef(router, poly95, 95);
+
+ Polygon poly96(4);
+ poly96.ps[0] = Point(440, 970);
+ poly96.ps[1] = Point(440, 1010);
+ poly96.ps[2] = Point(384, 1010);
+ poly96.ps[3] = Point(384, 970);
+ new ShapeRef(router, poly96, 96);
+
+ Polygon poly97(4);
+ poly97.ps[0] = Point(432, 801);
+ poly97.ps[1] = Point(432, 841);
+ poly97.ps[2] = Point(376, 841);
+ poly97.ps[3] = Point(376, 801);
+ new ShapeRef(router, poly97, 97);
+
+ Polygon poly98(4);
+ poly98.ps[0] = Point(502, 780);
+ poly98.ps[1] = Point(502, 820);
+ poly98.ps[2] = Point(446, 820);
+ poly98.ps[3] = Point(446, 780);
+ new ShapeRef(router, poly98, 98);
+
+ Polygon poly99(4);
+ poly99.ps[0] = Point(320, 792);
+ poly99.ps[1] = Point(320, 832);
+ poly99.ps[2] = Point(264, 832);
+ poly99.ps[3] = Point(264, 792);
+ new ShapeRef(router, poly99, 99);
+
+ Polygon poly100(4);
+ poly100.ps[0] = Point(211, 792);
+ poly100.ps[1] = Point(211, 832);
+ poly100.ps[2] = Point(155, 832);
+ poly100.ps[3] = Point(155, 792);
+ new ShapeRef(router, poly100, 100);
+
+ Polygon poly101(4);
+ poly101.ps[0] = Point(559, 791);
+ poly101.ps[1] = Point(559, 831);
+ poly101.ps[2] = Point(503, 831);
+ poly101.ps[3] = Point(503, 791);
+ new ShapeRef(router, poly101, 101);
+
+ Polygon poly102(4);
+ poly102.ps[0] = Point(554, 747);
+ poly102.ps[1] = Point(554, 787);
+ poly102.ps[2] = Point(498, 787);
+ poly102.ps[3] = Point(498, 747);
+ new ShapeRef(router, poly102, 102);
+
+ Polygon poly103(4);
+ poly103.ps[0] = Point(554, 678);
+ poly103.ps[1] = Point(554, 718);
+ poly103.ps[2] = Point(498, 718);
+ poly103.ps[3] = Point(498, 678);
+ new ShapeRef(router, poly103, 103);
+
+ Polygon poly104(4);
+ poly104.ps[0] = Point(555, 606);
+ poly104.ps[1] = Point(555, 646);
+ poly104.ps[2] = Point(499, 646);
+ poly104.ps[3] = Point(499, 606);
+ new ShapeRef(router, poly104, 104);
+
+ Polygon poly105(4);
+ poly105.ps[0] = Point(389, 461);
+ poly105.ps[1] = Point(389, 501);
+ poly105.ps[2] = Point(333, 501);
+ poly105.ps[3] = Point(333, 461);
+ new ShapeRef(router, poly105, 105);
+
+ Polygon poly106(4);
+ poly106.ps[0] = Point(404, 377);
+ poly106.ps[1] = Point(404, 417);
+ poly106.ps[2] = Point(348, 417);
+ poly106.ps[3] = Point(348, 377);
+ new ShapeRef(router, poly106, 106);
+
+ Polygon poly107(4);
+ poly107.ps[0] = Point(554, 381);
+ poly107.ps[1] = Point(554, 421);
+ poly107.ps[2] = Point(498, 421);
+ poly107.ps[3] = Point(498, 381);
+ new ShapeRef(router, poly107, 107);
+
+ Polygon poly108(4);
+ poly108.ps[0] = Point(554, 315);
+ poly108.ps[1] = Point(554, 355);
+ poly108.ps[2] = Point(498, 355);
+ poly108.ps[3] = Point(498, 315);
+ new ShapeRef(router, poly108, 108);
+
+ Polygon poly109(4);
+ poly109.ps[0] = Point(431, 265);
+ poly109.ps[1] = Point(431, 305);
+ poly109.ps[2] = Point(375, 305);
+ poly109.ps[3] = Point(375, 265);
+ new ShapeRef(router, poly109, 109);
+
+ Polygon poly110(4);
+ poly110.ps[0] = Point(553, 122);
+ poly110.ps[1] = Point(553, 162);
+ poly110.ps[2] = Point(497, 162);
+ poly110.ps[3] = Point(497, 122);
+ new ShapeRef(router, poly110, 110);
+
+ Polygon poly111(4);
+ poly111.ps[0] = Point(554, 245);
+ poly111.ps[1] = Point(554, 285);
+ poly111.ps[2] = Point(498, 285);
+ poly111.ps[3] = Point(498, 245);
+ new ShapeRef(router, poly111, 111);
+
+ Polygon poly112(4);
+ poly112.ps[0] = Point(414, 150);
+ poly112.ps[1] = Point(414, 190);
+ poly112.ps[2] = Point(358, 190);
+ poly112.ps[3] = Point(358, 150);
+ new ShapeRef(router, poly112, 112);
+
+ Polygon poly113(4);
+ poly113.ps[0] = Point(404, 229);
+ poly113.ps[1] = Point(404, 269);
+ poly113.ps[2] = Point(348, 269);
+ poly113.ps[3] = Point(348, 229);
+ new ShapeRef(router, poly113, 113);
+
+ Polygon poly114(4);
+ poly114.ps[0] = Point(319, 310);
+ poly114.ps[1] = Point(319, 350);
+ poly114.ps[2] = Point(263, 350);
+ poly114.ps[3] = Point(263, 310);
+ new ShapeRef(router, poly114, 114);
+
+ Polygon poly115(4);
+ poly115.ps[0] = Point(249, 229);
+ poly115.ps[1] = Point(249, 269);
+ poly115.ps[2] = Point(193, 269);
+ poly115.ps[3] = Point(193, 229);
+ new ShapeRef(router, poly115, 115);
+
+ Polygon poly116(4);
+ poly116.ps[0] = Point(358, 196);
+ poly116.ps[1] = Point(358, 236);
+ poly116.ps[2] = Point(302, 236);
+ poly116.ps[3] = Point(302, 196);
+ new ShapeRef(router, poly116, 116);
+
+ Polygon poly117(4);
+ poly117.ps[0] = Point(308, 196);
+ poly117.ps[1] = Point(308, 236);
+ poly117.ps[2] = Point(252, 236);
+ poly117.ps[3] = Point(252, 196);
+ new ShapeRef(router, poly117, 117);
+
+ Polygon poly118(4);
+ poly118.ps[0] = Point(112, 241);
+ poly118.ps[1] = Point(112, 281);
+ poly118.ps[2] = Point(56, 281);
+ poly118.ps[3] = Point(56, 241);
+ new ShapeRef(router, poly118, 118);
+
+ Polygon poly119(4);
+ poly119.ps[0] = Point(249, 154);
+ poly119.ps[1] = Point(249, 194);
+ poly119.ps[2] = Point(193, 194);
+ poly119.ps[3] = Point(193, 154);
+ new ShapeRef(router, poly119, 119);
+
+ Polygon poly120(4);
+ poly120.ps[0] = Point(249, 135);
+ poly120.ps[1] = Point(249, 175);
+ poly120.ps[2] = Point(193, 175);
+ poly120.ps[3] = Point(193, 135);
+ new ShapeRef(router, poly120, 120);
+
+ Polygon poly121(4);
+ poly121.ps[0] = Point(317, 113);
+ poly121.ps[1] = Point(317, 153);
+ poly121.ps[2] = Point(261, 153);
+ poly121.ps[3] = Point(261, 113);
+ new ShapeRef(router, poly121, 121);
+
+ Polygon poly122(4);
+ poly122.ps[0] = Point(344, 81);
+ poly122.ps[1] = Point(344, 121);
+ poly122.ps[2] = Point(288, 121);
+ poly122.ps[3] = Point(288, 81);
+ new ShapeRef(router, poly122, 122);
+
+ Polygon poly123(4);
+ poly123.ps[0] = Point(344, 160);
+ poly123.ps[1] = Point(344, 200);
+ poly123.ps[2] = Point(288, 200);
+ poly123.ps[3] = Point(288, 160);
+ new ShapeRef(router, poly123, 123);
+
+ Polygon poly124(4);
+ poly124.ps[0] = Point(263, 835);
+ poly124.ps[1] = Point(263, 875);
+ poly124.ps[2] = Point(207, 875);
+ poly124.ps[3] = Point(207, 835);
+ new ShapeRef(router, poly124, 124);
+
+ Polygon poly125(4);
+ poly125.ps[0] = Point(554, 533);
+ poly125.ps[1] = Point(554, 573);
+ poly125.ps[2] = Point(498, 573);
+ poly125.ps[3] = Point(498, 533);
+ new ShapeRef(router, poly125, 125);
+
+ Polygon poly126(4);
+ poly126.ps[0] = Point(249, 173);
+ poly126.ps[1] = Point(249, 213);
+ poly126.ps[2] = Point(193, 213);
+ poly126.ps[3] = Point(193, 173);
+ new ShapeRef(router, poly126, 126);
+
+ Polygon poly127(4);
+ poly127.ps[0] = Point(319, 248);
+ poly127.ps[1] = Point(319, 288);
+ poly127.ps[2] = Point(263, 288);
+ poly127.ps[3] = Point(263, 248);
+ new ShapeRef(router, poly127, 127);
+
+ Polygon poly128(4);
+ poly128.ps[0] = Point(182, 287);
+ poly128.ps[1] = Point(182, 327);
+ poly128.ps[2] = Point(126, 327);
+ poly128.ps[3] = Point(126, 287);
+ new ShapeRef(router, poly128, 128);
+
+ Polygon poly129(4);
+ poly129.ps[0] = Point(182, 413);
+ poly129.ps[1] = Point(182, 453);
+ poly129.ps[2] = Point(126, 453);
+ poly129.ps[3] = Point(126, 413);
+ new ShapeRef(router, poly129, 129);
+
+ Polygon poly130(4);
+ poly130.ps[0] = Point(292, 286);
+ poly130.ps[1] = Point(292, 326);
+ poly130.ps[2] = Point(236, 326);
+ poly130.ps[3] = Point(236, 286);
+ new ShapeRef(router, poly130, 130);
+
+ Polygon poly131(4);
+ poly131.ps[0] = Point(292, 412);
+ poly131.ps[1] = Point(292, 452);
+ poly131.ps[2] = Point(236, 452);
+ poly131.ps[3] = Point(236, 412);
+ new ShapeRef(router, poly131, 131);
+
+ Polygon poly132(4);
+ poly132.ps[0] = Point(205, 653);
+ poly132.ps[1] = Point(205, 693);
+ poly132.ps[2] = Point(149, 693);
+ poly132.ps[3] = Point(149, 653);
+ new ShapeRef(router, poly132, 132);
+
+ Polygon poly133(4);
+ poly133.ps[0] = Point(510, 891);
+ poly133.ps[1] = Point(510, 931);
+ poly133.ps[2] = Point(454, 931);
+ poly133.ps[3] = Point(454, 891);
+ new ShapeRef(router, poly133, 133);
+
+ Polygon poly134(4);
+ poly134.ps[0] = Point(275, 674);
+ poly134.ps[1] = Point(275, 714);
+ poly134.ps[2] = Point(219, 714);
+ poly134.ps[3] = Point(219, 674);
+ new ShapeRef(router, poly134, 134);
+
+ Polygon poly135(4);
+ poly135.ps[0] = Point(488, 891);
+ poly135.ps[1] = Point(488, 931);
+ poly135.ps[2] = Point(432, 931);
+ poly135.ps[3] = Point(432, 891);
+ new ShapeRef(router, poly135, 135);
+
+ Polygon poly136(4);
+ poly136.ps[0] = Point(579, 461);
+ poly136.ps[1] = Point(579, 501);
+ poly136.ps[2] = Point(523, 501);
+ poly136.ps[3] = Point(523, 461);
+ new ShapeRef(router, poly136, 136);
+
+ Polygon poly137(4);
+ poly137.ps[0] = Point(583, 452);
+ poly137.ps[1] = Point(583, 492);
+ poly137.ps[2] = Point(527, 492);
+ poly137.ps[3] = Point(527, 452);
+ new ShapeRef(router, poly137, 137);
+
+ Polygon poly138(4);
+ poly138.ps[0] = Point(556, 571);
+ poly138.ps[1] = Point(556, 611);
+ poly138.ps[2] = Point(500, 611);
+ poly138.ps[3] = Point(500, 571);
+ new ShapeRef(router, poly138, 138);
+
+ Polygon poly139(4);
+ poly139.ps[0] = Point(290, 722);
+ poly139.ps[1] = Point(290, 762);
+ poly139.ps[2] = Point(234, 762);
+ poly139.ps[3] = Point(234, 722);
+ new ShapeRef(router, poly139, 139);
+
+ Polygon poly140(4);
+ poly140.ps[0] = Point(603, 502);
+ poly140.ps[1] = Point(603, 542);
+ poly140.ps[2] = Point(547, 542);
+ poly140.ps[3] = Point(547, 502);
+ new ShapeRef(router, poly140, 140);
+
+ Polygon poly141(4);
+ poly141.ps[0] = Point(438, 613);
+ poly141.ps[1] = Point(438, 653);
+ poly141.ps[2] = Point(382, 653);
+ poly141.ps[3] = Point(382, 613);
+ new ShapeRef(router, poly141, 141);
+
+ Polygon poly142(4);
+ poly142.ps[0] = Point(439, 449);
+ poly142.ps[1] = Point(439, 489);
+ poly142.ps[2] = Point(383, 489);
+ poly142.ps[3] = Point(383, 449);
+ new ShapeRef(router, poly142, 142);
+
+ ConnRef *connRef143 = new ConnRef(router, 143);
+ ConnEnd srcPt143(Point(262, 940), 15);
+ connRef143->setSourceEndpoint(srcPt143);
+ ConnEnd dstPt143(Point(119, 951), 15);
+ connRef143->setDestEndpoint(dstPt143);
+ connRef143->setRoutingType((ConnType)2);
+
+ ConnRef *connRef144 = new ConnRef(router, 144);
+ ConnEnd srcPt144(Point(262, 940), 15);
+ connRef144->setSourceEndpoint(srcPt144);
+ ConnEnd dstPt144(Point(351, 951), 15);
+ connRef144->setDestEndpoint(dstPt144);
+ connRef144->setRoutingType((ConnType)2);
+
+ ConnRef *connRef145 = new ConnRef(router, 145);
+ ConnEnd srcPt145(Point(119, 908), 15);
+ connRef145->setSourceEndpoint(srcPt145);
+ ConnEnd dstPt145(Point(119, 951), 15);
+ connRef145->setDestEndpoint(dstPt145);
+ connRef145->setRoutingType((ConnType)2);
+
+ ConnRef *connRef146 = new ConnRef(router, 146);
+ ConnEnd srcPt146(Point(119, 908), 15);
+ connRef146->setSourceEndpoint(srcPt146);
+ ConnEnd dstPt146(Point(119, 861), 15);
+ connRef146->setDestEndpoint(dstPt146);
+ connRef146->setRoutingType((ConnType)2);
+
+ ConnRef *connRef147 = new ConnRef(router, 147);
+ ConnEnd srcPt147(Point(262, 961), 15);
+ connRef147->setSourceEndpoint(srcPt147);
+ ConnEnd dstPt147(Point(119, 951), 15);
+ connRef147->setDestEndpoint(dstPt147);
+ connRef147->setRoutingType((ConnType)2);
+
+ ConnRef *connRef148 = new ConnRef(router, 148);
+ ConnEnd srcPt148(Point(262, 961), 15);
+ connRef148->setSourceEndpoint(srcPt148);
+ ConnEnd dstPt148(Point(351, 951), 15);
+ connRef148->setDestEndpoint(dstPt148);
+ connRef148->setRoutingType((ConnType)2);
+
+ ConnRef *connRef149 = new ConnRef(router, 149);
+ ConnEnd srcPt149(Point(629, 336), 15);
+ connRef149->setSourceEndpoint(srcPt149);
+ ConnEnd dstPt149(Point(456, 446), 15);
+ connRef149->setDestEndpoint(dstPt149);
+ connRef149->setRoutingType((ConnType)2);
+
+ ConnRef *connRef150 = new ConnRef(router, 150);
+ ConnEnd srcPt150(Point(351, 909), 15);
+ connRef150->setSourceEndpoint(srcPt150);
+ ConnEnd dstPt150(Point(351, 951), 15);
+ connRef150->setDestEndpoint(dstPt150);
+ connRef150->setRoutingType((ConnType)2);
+
+ ConnRef *connRef151 = new ConnRef(router, 151);
+ ConnEnd srcPt151(Point(460, 940), 15);
+ connRef151->setSourceEndpoint(srcPt151);
+ ConnEnd dstPt151(Point(351, 951), 15);
+ connRef151->setDestEndpoint(dstPt151);
+ connRef151->setRoutingType((ConnType)2);
+
+ ConnRef *connRef152 = new ConnRef(router, 152);
+ ConnEnd srcPt152(Point(412, 940), 15);
+ connRef152->setSourceEndpoint(srcPt152);
+ ConnEnd dstPt152(Point(351, 951), 15);
+ connRef152->setDestEndpoint(dstPt152);
+ connRef152->setRoutingType((ConnType)2);
+
+ ConnRef *connRef153 = new ConnRef(router, 153);
+ ConnEnd srcPt153(Point(404, 871), 15);
+ connRef153->setSourceEndpoint(srcPt153);
+ ConnEnd dstPt153(Point(456, 861), 15);
+ connRef153->setDestEndpoint(dstPt153);
+ connRef153->setRoutingType((ConnType)2);
+
+ ConnRef *connRef154 = new ConnRef(router, 154);
+ ConnEnd srcPt154(Point(404, 871), 15);
+ connRef154->setSourceEndpoint(srcPt154);
+ ConnEnd dstPt154(Point(351, 861), 15);
+ connRef154->setDestEndpoint(dstPt154);
+ connRef154->setRoutingType((ConnType)2);
+
+ ConnRef *connRef155 = new ConnRef(router, 155);
+ ConnEnd srcPt155(Point(404, 850), 15);
+ connRef155->setSourceEndpoint(srcPt155);
+ ConnEnd dstPt155(Point(456, 861), 15);
+ connRef155->setDestEndpoint(dstPt155);
+ connRef155->setRoutingType((ConnType)2);
+
+ ConnRef *connRef156 = new ConnRef(router, 156);
+ ConnEnd srcPt156(Point(404, 850), 15);
+ connRef156->setSourceEndpoint(srcPt156);
+ ConnEnd dstPt156(Point(351, 861), 15);
+ connRef156->setDestEndpoint(dstPt156);
+ connRef156->setRoutingType((ConnType)2);
+
+ ConnRef *connRef157 = new ConnRef(router, 157);
+ ConnEnd srcPt157(Point(292, 862), 15);
+ connRef157->setSourceEndpoint(srcPt157);
+ ConnEnd dstPt157(Point(287, 904), 15);
+ connRef157->setDestEndpoint(dstPt157);
+ connRef157->setRoutingType((ConnType)2);
+
+ ConnRef *connRef158 = new ConnRef(router, 158);
+ ConnEnd srcPt158(Point(292, 862), 15);
+ connRef158->setSourceEndpoint(srcPt158);
+ ConnEnd dstPt158(Point(351, 861), 15);
+ connRef158->setDestEndpoint(dstPt158);
+ connRef158->setRoutingType((ConnType)2);
+
+ ConnRef *connRef159 = new ConnRef(router, 159);
+ ConnEnd srcPt159(Point(292, 862), 15);
+ connRef159->setSourceEndpoint(srcPt159);
+ ConnEnd dstPt159(Point(351, 818), 15);
+ connRef159->setDestEndpoint(dstPt159);
+ connRef159->setRoutingType((ConnType)2);
+
+ ConnRef *connRef160 = new ConnRef(router, 160);
+ ConnEnd srcPt160(Point(292, 862), 15);
+ connRef160->setSourceEndpoint(srcPt160);
+ ConnEnd dstPt160(Point(238, 861), 15);
+ connRef160->setDestEndpoint(dstPt160);
+ connRef160->setRoutingType((ConnType)2);
+
+ ConnRef *connRef161 = new ConnRef(router, 161);
+ ConnEnd srcPt161(Point(183, 862), 15);
+ connRef161->setSourceEndpoint(srcPt161);
+ ConnEnd dstPt161(Point(119, 861), 15);
+ connRef161->setDestEndpoint(dstPt161);
+ connRef161->setRoutingType((ConnType)2);
+
+ ConnRef *connRef162 = new ConnRef(router, 162);
+ ConnEnd srcPt162(Point(183, 862), 15);
+ connRef162->setSourceEndpoint(srcPt162);
+ ConnEnd dstPt162(Point(238, 861), 15);
+ connRef162->setDestEndpoint(dstPt162);
+ connRef162->setRoutingType((ConnType)2);
+
+ ConnRef *connRef163 = new ConnRef(router, 163);
+ ConnEnd srcPt163(Point(183, 862), 15);
+ connRef163->setSourceEndpoint(srcPt163);
+ ConnEnd dstPt163(Point(185, 904), 15);
+ connRef163->setDestEndpoint(dstPt163);
+ connRef163->setRoutingType((ConnType)2);
+
+ ConnRef *connRef164 = new ConnRef(router, 164);
+ ConnEnd srcPt164(Point(531, 861), 15);
+ connRef164->setSourceEndpoint(srcPt164);
+ ConnEnd dstPt164(Point(600, 861), 15);
+ connRef164->setDestEndpoint(dstPt164);
+ connRef164->setRoutingType((ConnType)2);
+
+ ConnRef *connRef165 = new ConnRef(router, 165);
+ ConnEnd srcPt165(Point(531, 861), 15);
+ connRef165->setSourceEndpoint(srcPt165);
+ ConnEnd dstPt165(Point(456, 861), 15);
+ connRef165->setDestEndpoint(dstPt165);
+ connRef165->setRoutingType((ConnType)2);
+
+ ConnRef *connRef166 = new ConnRef(router, 166);
+ ConnEnd srcPt166(Point(456, 767), 15);
+ connRef166->setSourceEndpoint(srcPt166);
+ ConnEnd dstPt166(Point(456, 734), 15);
+ connRef166->setDestEndpoint(dstPt166);
+ connRef166->setRoutingType((ConnType)2);
+
+ ConnRef *connRef167 = new ConnRef(router, 167);
+ ConnEnd srcPt167(Point(456, 767), 15);
+ connRef167->setSourceEndpoint(srcPt167);
+ ConnEnd dstPt167(Point(456, 861), 15);
+ connRef167->setDestEndpoint(dstPt167);
+ connRef167->setRoutingType((ConnType)2);
+
+ ConnRef *connRef168 = new ConnRef(router, 168);
+ ConnEnd srcPt168(Point(456, 698), 15);
+ connRef168->setSourceEndpoint(srcPt168);
+ ConnEnd dstPt168(Point(456, 662), 15);
+ connRef168->setDestEndpoint(dstPt168);
+ connRef168->setRoutingType((ConnType)2);
+
+ ConnRef *connRef169 = new ConnRef(router, 169);
+ ConnEnd srcPt169(Point(456, 698), 15);
+ connRef169->setSourceEndpoint(srcPt169);
+ ConnEnd dstPt169(Point(456, 734), 15);
+ connRef169->setDestEndpoint(dstPt169);
+ connRef169->setRoutingType((ConnType)2);
+
+ ConnRef *connRef170 = new ConnRef(router, 170);
+ ConnEnd srcPt170(Point(457, 626), 15);
+ connRef170->setSourceEndpoint(srcPt170);
+ ConnEnd dstPt170(Point(456, 662), 15);
+ connRef170->setDestEndpoint(dstPt170);
+ connRef170->setRoutingType((ConnType)2);
+
+ ConnRef *connRef171 = new ConnRef(router, 171);
+ ConnEnd srcPt171(Point(457, 626), 15);
+ connRef171->setSourceEndpoint(srcPt171);
+ ConnEnd dstPt171(Point(456, 590), 15);
+ connRef171->setDestEndpoint(dstPt171);
+ connRef171->setRoutingType((ConnType)2);
+
+ ConnRef *connRef172 = new ConnRef(router, 172);
+ ConnEnd srcPt172(Point(431, 481), 15);
+ connRef172->setSourceEndpoint(srcPt172);
+ ConnEnd dstPt172(Point(456, 518), 15);
+ connRef172->setDestEndpoint(dstPt172);
+ connRef172->setRoutingType((ConnType)2);
+
+ ConnRef *connRef173 = new ConnRef(router, 173);
+ ConnEnd srcPt173(Point(431, 481), 15);
+ connRef173->setSourceEndpoint(srcPt173);
+ ConnEnd dstPt173(Point(456, 446), 15);
+ connRef173->setDestEndpoint(dstPt173);
+ connRef173->setRoutingType((ConnType)2);
+
+ ConnRef *connRef174 = new ConnRef(router, 174);
+ ConnEnd srcPt174(Point(376, 447), 15);
+ connRef174->setSourceEndpoint(srcPt174);
+ ConnEnd dstPt174(Point(305, 446), 15);
+ connRef174->setDestEndpoint(dstPt174);
+ connRef174->setRoutingType((ConnType)2);
+
+ ConnRef *connRef175 = new ConnRef(router, 175);
+ ConnEnd srcPt175(Point(376, 447), 15);
+ connRef175->setSourceEndpoint(srcPt175);
+ ConnEnd dstPt175(Point(456, 446), 15);
+ connRef175->setDestEndpoint(dstPt175);
+ connRef175->setRoutingType((ConnType)2);
+
+ ConnRef *connRef176 = new ConnRef(router, 176);
+ ConnEnd srcPt176(Point(456, 401), 15);
+ connRef176->setSourceEndpoint(srcPt176);
+ ConnEnd dstPt176(Point(305, 446), 15);
+ connRef176->setDestEndpoint(dstPt176);
+ connRef176->setRoutingType((ConnType)2);
+
+ ConnRef *connRef177 = new ConnRef(router, 177);
+ ConnEnd srcPt177(Point(456, 401), 15);
+ connRef177->setSourceEndpoint(srcPt177);
+ ConnEnd dstPt177(Point(456, 371), 15);
+ connRef177->setDestEndpoint(dstPt177);
+ connRef177->setRoutingType((ConnType)2);
+
+ ConnRef *connRef178 = new ConnRef(router, 178);
+ ConnEnd srcPt178(Point(456, 401), 15);
+ connRef178->setSourceEndpoint(srcPt178);
+ ConnEnd dstPt178(Point(456, 446), 15);
+ connRef178->setDestEndpoint(dstPt178);
+ connRef178->setRoutingType((ConnType)2);
+
+ ConnRef *connRef179 = new ConnRef(router, 179);
+ ConnEnd srcPt179(Point(456, 335), 15);
+ connRef179->setSourceEndpoint(srcPt179);
+ ConnEnd dstPt179(Point(456, 301), 15);
+ connRef179->setDestEndpoint(dstPt179);
+ connRef179->setRoutingType((ConnType)2);
+
+ ConnRef *connRef180 = new ConnRef(router, 180);
+ ConnEnd srcPt180(Point(456, 335), 15);
+ connRef180->setSourceEndpoint(srcPt180);
+ ConnEnd dstPt180(Point(456, 371), 15);
+ connRef180->setDestEndpoint(dstPt180);
+ connRef180->setRoutingType((ConnType)2);
+
+ ConnRef *connRef181 = new ConnRef(router, 181);
+ ConnEnd srcPt181(Point(403, 335), 15);
+ connRef181->setSourceEndpoint(srcPt181);
+ ConnEnd dstPt181(Point(456, 301), 15);
+ connRef181->setDestEndpoint(dstPt181);
+ connRef181->setRoutingType((ConnType)2);
+
+ ConnRef *connRef182 = new ConnRef(router, 182);
+ ConnEnd srcPt182(Point(525, 192), 15);
+ connRef182->setSourceEndpoint(srcPt182);
+ ConnEnd dstPt182(Point(456, 228), 15);
+ connRef182->setDestEndpoint(dstPt182);
+ connRef182->setRoutingType((ConnType)2);
+
+ ConnRef *connRef183 = new ConnRef(router, 183);
+ ConnEnd srcPt183(Point(456, 265), 15);
+ connRef183->setSourceEndpoint(srcPt183);
+ ConnEnd dstPt183(Point(456, 228), 15);
+ connRef183->setDestEndpoint(dstPt183);
+ connRef183->setRoutingType((ConnType)2);
+
+ ConnRef *connRef184 = new ConnRef(router, 184);
+ ConnEnd srcPt184(Point(456, 265), 15);
+ connRef184->setSourceEndpoint(srcPt184);
+ ConnEnd dstPt184(Point(456, 301), 15);
+ connRef184->setDestEndpoint(dstPt184);
+ connRef184->setRoutingType((ConnType)2);
+
+ ConnRef *connRef185 = new ConnRef(router, 185);
+ ConnEnd srcPt185(Point(456, 170), 15);
+ connRef185->setSourceEndpoint(srcPt185);
+ ConnEnd dstPt185(Point(456, 141), 15);
+ connRef185->setDestEndpoint(dstPt185);
+ connRef185->setRoutingType((ConnType)2);
+
+ ConnRef *connRef186 = new ConnRef(router, 186);
+ ConnEnd srcPt186(Point(456, 170), 15);
+ connRef186->setSourceEndpoint(srcPt186);
+ ConnEnd dstPt186(Point(456, 228), 15);
+ connRef186->setDestEndpoint(dstPt186);
+ connRef186->setRoutingType((ConnType)2);
+
+ ConnRef *connRef187 = new ConnRef(router, 187);
+ ConnEnd srcPt187(Point(376, 299), 15);
+ connRef187->setSourceEndpoint(srcPt187);
+ ConnEnd dstPt187(Point(305, 299), 15);
+ connRef187->setDestEndpoint(dstPt187);
+ connRef187->setRoutingType((ConnType)2);
+
+ ConnRef *connRef188 = new ConnRef(router, 188);
+ ConnEnd srcPt188(Point(376, 299), 15);
+ connRef188->setSourceEndpoint(srcPt188);
+ ConnEnd dstPt188(Point(456, 301), 15);
+ connRef188->setDestEndpoint(dstPt188);
+ connRef188->setRoutingType((ConnType)2);
+
+ ConnRef *connRef189 = new ConnRef(router, 189);
+ ConnEnd srcPt189(Point(221, 280), 15);
+ connRef189->setSourceEndpoint(srcPt189);
+ ConnEnd dstPt189(Point(154, 299), 15);
+ connRef189->setDestEndpoint(dstPt189);
+ connRef189->setRoutingType((ConnType)2);
+
+ ConnRef *connRef190 = new ConnRef(router, 190);
+ ConnEnd srcPt190(Point(221, 280), 15);
+ connRef190->setSourceEndpoint(srcPt190);
+ ConnEnd dstPt190(Point(305, 299), 15);
+ connRef190->setDestEndpoint(dstPt190);
+ connRef190->setRoutingType((ConnType)2);
+
+ ConnRef *connRef191 = new ConnRef(router, 191);
+ ConnEnd srcPt191(Point(221, 299), 15);
+ connRef191->setSourceEndpoint(srcPt191);
+ ConnEnd dstPt191(Point(154, 299), 15);
+ connRef191->setDestEndpoint(dstPt191);
+ connRef191->setRoutingType((ConnType)2);
+
+ ConnRef *connRef192 = new ConnRef(router, 192);
+ ConnEnd srcPt192(Point(221, 299), 15);
+ connRef192->setSourceEndpoint(srcPt192);
+ ConnEnd dstPt192(Point(305, 299), 15);
+ connRef192->setDestEndpoint(dstPt192);
+ connRef192->setRoutingType((ConnType)2);
+
+ ConnRef *connRef193 = new ConnRef(router, 193);
+ ConnEnd srcPt193(Point(330, 266), 15);
+ connRef193->setSourceEndpoint(srcPt193);
+ ConnEnd dstPt193(Point(305, 299), 15);
+ connRef193->setDestEndpoint(dstPt193);
+ connRef193->setRoutingType((ConnType)2);
+
+ ConnRef *connRef194 = new ConnRef(router, 194);
+ ConnEnd srcPt194(Point(330, 266), 15);
+ connRef194->setSourceEndpoint(srcPt194);
+ ConnEnd dstPt194(Point(456, 228), 15);
+ connRef194->setDestEndpoint(dstPt194);
+ connRef194->setRoutingType((ConnType)2);
+
+ ConnRef *connRef195 = new ConnRef(router, 195);
+ ConnEnd srcPt195(Point(280, 266), 15);
+ connRef195->setSourceEndpoint(srcPt195);
+ ConnEnd dstPt195(Point(305, 299), 15);
+ connRef195->setDestEndpoint(dstPt195);
+ connRef195->setRoutingType((ConnType)2);
+
+ ConnRef *connRef196 = new ConnRef(router, 196);
+ ConnEnd srcPt196(Point(280, 266), 15);
+ connRef196->setSourceEndpoint(srcPt196);
+ ConnEnd dstPt196(Point(456, 228), 15);
+ connRef196->setDestEndpoint(dstPt196);
+ connRef196->setRoutingType((ConnType)2);
+
+ ConnRef *connRef197 = new ConnRef(router, 197);
+ ConnEnd srcPt197(Point(154, 261), 15);
+ connRef197->setSourceEndpoint(srcPt197);
+ ConnEnd dstPt197(Point(154, 226), 15);
+ connRef197->setDestEndpoint(dstPt197);
+ connRef197->setRoutingType((ConnType)2);
+
+ ConnRef *connRef198 = new ConnRef(router, 198);
+ ConnEnd srcPt198(Point(154, 261), 15);
+ connRef198->setSourceEndpoint(srcPt198);
+ ConnEnd dstPt198(Point(154, 299), 15);
+ connRef198->setDestEndpoint(dstPt198);
+ connRef198->setRoutingType((ConnType)2);
+
+ ConnRef *connRef199 = new ConnRef(router, 199);
+ ConnEnd srcPt199(Point(221, 224), 15);
+ connRef199->setSourceEndpoint(srcPt199);
+ ConnEnd dstPt199(Point(154, 226), 15);
+ connRef199->setDestEndpoint(dstPt199);
+ connRef199->setRoutingType((ConnType)2);
+
+ ConnRef *connRef200 = new ConnRef(router, 200);
+ ConnEnd srcPt200(Point(221, 224), 15);
+ connRef200->setSourceEndpoint(srcPt200);
+ ConnEnd dstPt200(Point(456, 228), 15);
+ connRef200->setDestEndpoint(dstPt200);
+ connRef200->setRoutingType((ConnType)2);
+
+ ConnRef *connRef201 = new ConnRef(router, 201);
+ ConnEnd srcPt201(Point(221, 205), 15);
+ connRef201->setSourceEndpoint(srcPt201);
+ ConnEnd dstPt201(Point(154, 226), 15);
+ connRef201->setDestEndpoint(dstPt201);
+ connRef201->setRoutingType((ConnType)2);
+
+ ConnRef *connRef202 = new ConnRef(router, 202);
+ ConnEnd srcPt202(Point(221, 205), 15);
+ connRef202->setSourceEndpoint(srcPt202);
+ ConnEnd dstPt202(Point(456, 228), 15);
+ connRef202->setDestEndpoint(dstPt202);
+ connRef202->setRoutingType((ConnType)2);
+
+ ConnRef *connRef203 = new ConnRef(router, 203);
+ ConnEnd srcPt203(Point(289, 183), 15);
+ connRef203->setSourceEndpoint(srcPt203);
+ ConnEnd dstPt203(Point(154, 226), 15);
+ connRef203->setDestEndpoint(dstPt203);
+ connRef203->setRoutingType((ConnType)2);
+
+ ConnRef *connRef204 = new ConnRef(router, 204);
+ ConnEnd srcPt204(Point(289, 183), 15);
+ connRef204->setSourceEndpoint(srcPt204);
+ ConnEnd dstPt204(Point(456, 228), 15);
+ connRef204->setDestEndpoint(dstPt204);
+ connRef204->setRoutingType((ConnType)2);
+
+ ConnRef *connRef205 = new ConnRef(router, 205);
+ ConnEnd srcPt205(Point(316, 151), 15);
+ connRef205->setSourceEndpoint(srcPt205);
+ ConnEnd dstPt205(Point(456, 141), 15);
+ connRef205->setDestEndpoint(dstPt205);
+ connRef205->setRoutingType((ConnType)2);
+
+ ConnRef *connRef206 = new ConnRef(router, 206);
+ ConnEnd srcPt206(Point(316, 151), 15);
+ connRef206->setSourceEndpoint(srcPt206);
+ ConnEnd dstPt206(Point(154, 226), 15);
+ connRef206->setDestEndpoint(dstPt206);
+ connRef206->setRoutingType((ConnType)2);
+
+ ConnRef *connRef207 = new ConnRef(router, 207);
+ ConnEnd srcPt207(Point(316, 130), 15);
+ connRef207->setSourceEndpoint(srcPt207);
+ ConnEnd dstPt207(Point(456, 141), 15);
+ connRef207->setDestEndpoint(dstPt207);
+ connRef207->setRoutingType((ConnType)2);
+
+ ConnRef *connRef208 = new ConnRef(router, 208);
+ ConnEnd srcPt208(Point(316, 130), 15);
+ connRef208->setSourceEndpoint(srcPt208);
+ ConnEnd dstPt208(Point(154, 226), 15);
+ connRef208->setDestEndpoint(dstPt208);
+ connRef208->setRoutingType((ConnType)2);
+
+ ConnRef *connRef209 = new ConnRef(router, 209);
+ ConnEnd srcPt209(Point(235, 905), 15);
+ connRef209->setSourceEndpoint(srcPt209);
+ ConnEnd dstPt209(Point(287, 904), 15);
+ connRef209->setDestEndpoint(dstPt209);
+ connRef209->setRoutingType((ConnType)2);
+
+ ConnRef *connRef210 = new ConnRef(router, 210);
+ ConnEnd srcPt210(Point(456, 553), 15);
+ connRef210->setSourceEndpoint(srcPt210);
+ ConnEnd dstPt210(Point(456, 590), 15);
+ connRef210->setDestEndpoint(dstPt210);
+ connRef210->setRoutingType((ConnType)2);
+
+ ConnRef *connRef211 = new ConnRef(router, 211);
+ ConnEnd srcPt211(Point(456, 553), 15);
+ connRef211->setSourceEndpoint(srcPt211);
+ ConnEnd dstPt211(Point(456, 518), 15);
+ connRef211->setDestEndpoint(dstPt211);
+ connRef211->setRoutingType((ConnType)2);
+
+ ConnRef *connRef212 = new ConnRef(router, 212);
+ ConnEnd srcPt212(Point(221, 243), 15);
+ connRef212->setSourceEndpoint(srcPt212);
+ ConnEnd dstPt212(Point(456, 228), 15);
+ connRef212->setDestEndpoint(dstPt212);
+ connRef212->setRoutingType((ConnType)2);
+
+ ConnRef *connRef213 = new ConnRef(router, 213);
+ ConnEnd srcPt213(Point(221, 318), 15);
+ connRef213->setSourceEndpoint(srcPt213);
+ ConnEnd dstPt213(Point(305, 299), 15);
+ connRef213->setDestEndpoint(dstPt213);
+ connRef213->setRoutingType((ConnType)2);
+
+ ConnRef *connRef214 = new ConnRef(router, 214);
+ ConnEnd srcPt214(Point(154, 357), 15);
+ connRef214->setSourceEndpoint(srcPt214);
+ ConnEnd dstPt214(Point(212, 356), 15);
+ connRef214->setDestEndpoint(dstPt214);
+ connRef214->setRoutingType((ConnType)2);
+
+ ConnRef *connRef215 = new ConnRef(router, 215);
+ ConnEnd srcPt215(Point(154, 383), 15);
+ connRef215->setSourceEndpoint(srcPt215);
+ ConnEnd dstPt215(Point(212, 382), 15);
+ connRef215->setDestEndpoint(dstPt215);
+ connRef215->setRoutingType((ConnType)2);
+
+ ConnRef *connRef216 = new ConnRef(router, 216);
+ ConnEnd srcPt216(Point(264, 356), 15);
+ connRef216->setSourceEndpoint(srcPt216);
+ ConnEnd dstPt216(Point(305, 299), 15);
+ connRef216->setDestEndpoint(dstPt216);
+ connRef216->setRoutingType((ConnType)2);
+
+ ConnRef *connRef217 = new ConnRef(router, 217);
+ ConnEnd srcPt217(Point(264, 382), 15);
+ connRef217->setSourceEndpoint(srcPt217);
+ ConnEnd dstPt217(Point(305, 299), 15);
+ connRef217->setDestEndpoint(dstPt217);
+ connRef217->setRoutingType((ConnType)2);
+
+ ConnRef *connRef218 = new ConnRef(router, 218);
+ ConnEnd srcPt218(Point(574, 193), 15);
+ connRef218->setSourceEndpoint(srcPt218);
+ ConnEnd dstPt218(Point(525, 192), 15);
+ connRef218->setDestEndpoint(dstPt218);
+ connRef218->setRoutingType((ConnType)2);
+
+ ConnRef *connRef219 = new ConnRef(router, 219);
+ ConnEnd srcPt219(Point(456, 141), 15);
+ connRef219->setSourceEndpoint(srcPt219);
+ ConnEnd dstPt219(Point(458, 74), 15);
+ connRef219->setDestEndpoint(dstPt219);
+ connRef219->setRoutingType((ConnType)2);
+
+ ConnRef *connRef220 = new ConnRef(router, 220);
+ ConnEnd srcPt220(Point(456, 662), 15);
+ connRef220->setSourceEndpoint(srcPt220);
+ ConnEnd dstPt220(Point(629, 336), 15);
+ connRef220->setDestEndpoint(dstPt220);
+ connRef220->setRoutingType((ConnType)2);
+
+ ConnRef *connRef221 = new ConnRef(router, 221);
+ ConnEnd srcPt221(Point(154, 226), 15);
+ connRef221->setSourceEndpoint(srcPt221);
+ ConnEnd dstPt221(Point(221, 243), 15);
+ connRef221->setDestEndpoint(dstPt221);
+ connRef221->setRoutingType((ConnType)2);
+
+ ConnRef *connRef222 = new ConnRef(router, 222);
+ ConnEnd srcPt222(Point(221, 318), 15);
+ connRef222->setSourceEndpoint(srcPt222);
+ ConnEnd dstPt222(Point(154, 299), 15);
+ connRef222->setDestEndpoint(dstPt222);
+ connRef222->setRoutingType((ConnType)2);
+
+ ConnRef *connRef223 = new ConnRef(router, 223);
+ ConnEnd srcPt223(Point(456, 228), 15);
+ connRef223->setSourceEndpoint(srcPt223);
+ ConnEnd dstPt223(Point(629, 336), 15);
+ connRef223->setDestEndpoint(dstPt223);
+ connRef223->setRoutingType((ConnType)2);
+
+ ConnRef *connRef224 = new ConnRef(router, 224);
+ ConnEnd srcPt224(Point(456, 734), 15);
+ connRef224->setSourceEndpoint(srcPt224);
+ ConnEnd dstPt224(Point(49, 798), 15);
+ connRef224->setDestEndpoint(dstPt224);
+ connRef224->setRoutingType((ConnType)2);
+
+ ConnRef *connRef225 = new ConnRef(router, 225);
+ ConnEnd srcPt225(Point(177, 744), 15);
+ connRef225->setSourceEndpoint(srcPt225);
+ ConnEnd dstPt225(Point(456, 734), 15);
+ connRef225->setDestEndpoint(dstPt225);
+ connRef225->setRoutingType((ConnType)2);
+
+ ConnRef *connRef226 = new ConnRef(router, 226);
+ ConnEnd srcPt226(Point(456, 590), 15);
+ connRef226->setSourceEndpoint(srcPt226);
+ ConnEnd dstPt226(Point(278, 597), 15);
+ connRef226->setDestEndpoint(dstPt226);
+ connRef226->setRoutingType((ConnType)2);
+
+ ConnRef *connRef227 = new ConnRef(router, 227);
+ ConnEnd srcPt227(Point(555, 522), 15);
+ connRef227->setSourceEndpoint(srcPt227);
+ ConnEnd dstPt227(Point(456, 590), 15);
+ connRef227->setDestEndpoint(dstPt227);
+ connRef227->setRoutingType((ConnType)2);
+
+ ConnRef *connRef228 = new ConnRef(router, 228);
+ ConnEnd srcPt228(Point(528, 541), 15);
+ connRef228->setSourceEndpoint(srcPt228);
+ ConnEnd dstPt228(Point(456, 590), 15);
+ connRef228->setDestEndpoint(dstPt228);
+ connRef228->setRoutingType((ConnType)2);
+
+ ConnRef *connRef229 = new ConnRef(router, 229);
+ ConnEnd srcPt229(Point(505, 522), 15);
+ connRef229->setSourceEndpoint(srcPt229);
+ ConnEnd dstPt229(Point(456, 590), 15);
+ connRef229->setDestEndpoint(dstPt229);
+ connRef229->setRoutingType((ConnType)2);
+
+ ConnRef *connRef230 = new ConnRef(router, 230);
+ ConnEnd srcPt230(Point(481, 481), 15);
+ connRef230->setSourceEndpoint(srcPt230);
+ ConnEnd dstPt230(Point(456, 518), 15);
+ connRef230->setDestEndpoint(dstPt230);
+ connRef230->setRoutingType((ConnType)2);
+
+ ConnRef *connRef231 = new ConnRef(router, 231);
+ ConnEnd srcPt231(Point(411, 519), 15);
+ connRef231->setSourceEndpoint(srcPt231);
+ ConnEnd dstPt231(Point(456, 518), 15);
+ connRef231->setDestEndpoint(dstPt231);
+ connRef231->setRoutingType((ConnType)2);
+
+ ConnRef *connRef232 = new ConnRef(router, 232);
+ ConnEnd srcPt232(Point(600, 861), 15);
+ connRef232->setSourceEndpoint(srcPt232);
+ ConnEnd dstPt232(Point(601, 917), 15);
+ connRef232->setDestEndpoint(dstPt232);
+ connRef232->setRoutingType((ConnType)2);
+
+ ConnRef *connRef233 = new ConnRef(router, 233);
+ ConnEnd srcPt233(Point(460, 940), 15);
+ connRef233->setSourceEndpoint(srcPt233);
+ ConnEnd dstPt233(Point(523, 951), 15);
+ connRef233->setDestEndpoint(dstPt233);
+ connRef233->setRoutingType((ConnType)2);
+
+ ConnRef *connRef234 = new ConnRef(router, 234);
+ ConnEnd srcPt234(Point(412, 940), 15);
+ connRef234->setSourceEndpoint(srcPt234);
+ ConnEnd dstPt234(Point(523, 951), 15);
+ connRef234->setDestEndpoint(dstPt234);
+ connRef234->setRoutingType((ConnType)2);
+
+ ConnRef *connRef235 = new ConnRef(router, 235);
+ ConnEnd srcPt235(Point(523, 951), 15);
+ connRef235->setSourceEndpoint(srcPt235);
+ ConnEnd dstPt235(Point(412, 961), 15);
+ connRef235->setDestEndpoint(dstPt235);
+ connRef235->setRoutingType((ConnType)2);
+
+ ConnRef *connRef236 = new ConnRef(router, 236);
+ ConnEnd srcPt236(Point(460, 961), 15);
+ connRef236->setSourceEndpoint(srcPt236);
+ ConnEnd dstPt236(Point(523, 951), 15);
+ connRef236->setDestEndpoint(dstPt236);
+ connRef236->setRoutingType((ConnType)2);
+
+ ConnRef *connRef237 = new ConnRef(router, 237);
+ ConnEnd srcPt237(Point(456, 861), 15);
+ connRef237->setSourceEndpoint(srcPt237);
+ ConnEnd dstPt237(Point(629, 336), 15);
+ connRef237->setDestEndpoint(dstPt237);
+ connRef237->setRoutingType((ConnType)2);
+
+ ConnRef *connRef238 = new ConnRef(router, 238);
+ ConnEnd srcPt238(Point(456, 861), 15);
+ connRef238->setSourceEndpoint(srcPt238);
+ ConnEnd dstPt238(Point(49, 798), 15);
+ connRef238->setDestEndpoint(dstPt238);
+ connRef238->setRoutingType((ConnType)2);
+
+ ConnRef *connRef239 = new ConnRef(router, 239);
+ ConnEnd srcPt239(Point(262, 792), 15);
+ connRef239->setSourceEndpoint(srcPt239);
+ ConnEnd dstPt239(Point(456, 861), 15);
+ connRef239->setDestEndpoint(dstPt239);
+ connRef239->setRoutingType((ConnType)2);
+
+ ConnRef *connRef240 = new ConnRef(router, 240);
+ ConnEnd srcPt240(Point(351, 861), 15);
+ connRef240->setSourceEndpoint(srcPt240);
+ ConnEnd dstPt240(Point(351, 909), 15);
+ connRef240->setDestEndpoint(dstPt240);
+ connRef240->setRoutingType((ConnType)2);
+
+ ConnRef *connRef241 = new ConnRef(router, 241);
+ ConnEnd srcPt241(Point(351, 818), 15);
+ connRef241->setSourceEndpoint(srcPt241);
+ ConnEnd dstPt241(Point(404, 871), 15);
+ connRef241->setDestEndpoint(dstPt241);
+ connRef241->setRoutingType((ConnType)2);
+
+ ConnRef *connRef242 = new ConnRef(router, 242);
+ ConnEnd srcPt242(Point(351, 818), 15);
+ connRef242->setSourceEndpoint(srcPt242);
+ ConnEnd dstPt242(Point(404, 850), 15);
+ connRef242->setDestEndpoint(dstPt242);
+ connRef242->setRoutingType((ConnType)2);
+
+ ConnRef *connRef243 = new ConnRef(router, 243);
+ ConnEnd srcPt243(Point(119, 861), 15);
+ connRef243->setSourceEndpoint(srcPt243);
+ ConnEnd dstPt243(Point(49, 798), 15);
+ connRef243->setDestEndpoint(dstPt243);
+ connRef243->setRoutingType((ConnType)2);
+
+ ConnRef *connRef244 = new ConnRef(router, 244);
+ ConnEnd srcPt244(Point(262, 792), 15);
+ connRef244->setSourceEndpoint(srcPt244);
+ ConnEnd dstPt244(Point(119, 861), 15);
+ connRef244->setDestEndpoint(dstPt244);
+ connRef244->setRoutingType((ConnType)2);
+
+ ConnRef *connRef245 = new ConnRef(router, 245);
+ ConnEnd srcPt245(Point(412, 961), 15);
+ connRef245->setSourceEndpoint(srcPt245);
+ ConnEnd dstPt245(Point(351, 951), 15);
+ connRef245->setDestEndpoint(dstPt245);
+ connRef245->setRoutingType((ConnType)2);
+
+ ConnRef *connRef246 = new ConnRef(router, 246);
+ ConnEnd srcPt246(Point(460, 961), 15);
+ connRef246->setSourceEndpoint(srcPt246);
+ ConnEnd dstPt246(Point(351, 951), 15);
+ connRef246->setDestEndpoint(dstPt246);
+ connRef246->setRoutingType((ConnType)2);
+
+ ConnRef *connRef247 = new ConnRef(router, 247);
+ ConnEnd srcPt247(Point(235, 905), 15);
+ connRef247->setSourceEndpoint(srcPt247);
+ ConnEnd dstPt247(Point(185, 904), 15);
+ connRef247->setDestEndpoint(dstPt247);
+ connRef247->setRoutingType((ConnType)2);
+
+ ConnRef *connRef248 = new ConnRef(router, 248);
+ ConnEnd srcPt248(Point(456, 371), 15);
+ connRef248->setSourceEndpoint(srcPt248);
+ ConnEnd dstPt248(Point(403, 335), 15);
+ connRef248->setDestEndpoint(dstPt248);
+ connRef248->setRoutingType((ConnType)2);
+
+ ConnRef *connRef249 = new ConnRef(router, 249);
+ ConnEnd srcPt249(Point(105, 356), 15);
+ connRef249->setSourceEndpoint(srcPt249);
+ ConnEnd dstPt249(Point(154, 357), 15);
+ connRef249->setDestEndpoint(dstPt249);
+ connRef249->setRoutingType((ConnType)2);
+
+ ConnRef *connRef250 = new ConnRef(router, 250);
+ ConnEnd srcPt250(Point(212, 356), 15);
+ connRef250->setSourceEndpoint(srcPt250);
+ ConnEnd dstPt250(Point(264, 356), 15);
+ connRef250->setDestEndpoint(dstPt250);
+ connRef250->setRoutingType((ConnType)2);
+
+ ConnRef *connRef251 = new ConnRef(router, 251);
+ ConnEnd srcPt251(Point(212, 382), 15);
+ connRef251->setSourceEndpoint(srcPt251);
+ ConnEnd dstPt251(Point(264, 382), 15);
+ connRef251->setDestEndpoint(dstPt251);
+ connRef251->setRoutingType((ConnType)2);
+
+ ConnRef *connRef252 = new ConnRef(router, 252);
+ ConnEnd srcPt252(Point(105, 382), 15);
+ connRef252->setSourceEndpoint(srcPt252);
+ ConnEnd dstPt252(Point(154, 383), 15);
+ connRef252->setDestEndpoint(dstPt252);
+ connRef252->setRoutingType((ConnType)2);
+
+ ConnRef *connRef253 = new ConnRef(router, 253);
+ ConnEnd srcPt253(Point(49, 798), 15);
+ connRef253->setSourceEndpoint(srcPt253);
+ ConnEnd dstPt253(Point(119, 734), 15);
+ connRef253->setDestEndpoint(dstPt253);
+ connRef253->setRoutingType((ConnType)2);
+
+ ConnRef *connRef254 = new ConnRef(router, 254);
+ ConnEnd srcPt254(Point(177, 723), 15);
+ connRef254->setSourceEndpoint(srcPt254);
+ ConnEnd dstPt254(Point(456, 734), 15);
+ connRef254->setDestEndpoint(dstPt254);
+ connRef254->setRoutingType((ConnType)2);
+
+ ConnRef *connRef255 = new ConnRef(router, 255);
+ ConnEnd srcPt255(Point(119, 734), 15);
+ connRef255->setSourceEndpoint(srcPt255);
+ ConnEnd dstPt255(Point(177, 723), 15);
+ connRef255->setDestEndpoint(dstPt255);
+ connRef255->setRoutingType((ConnType)2);
+
+ ConnRef *connRef256 = new ConnRef(router, 256);
+ ConnEnd srcPt256(Point(119, 734), 15);
+ connRef256->setSourceEndpoint(srcPt256);
+ ConnEnd dstPt256(Point(177, 744), 15);
+ connRef256->setDestEndpoint(dstPt256);
+ connRef256->setRoutingType((ConnType)2);
+
+ ConnRef *connRef257 = new ConnRef(router, 257);
+ ConnEnd srcPt257(Point(481, 481), 15);
+ connRef257->setSourceEndpoint(srcPt257);
+ ConnEnd dstPt257(Point(456, 446), 15);
+ connRef257->setDestEndpoint(dstPt257);
+ connRef257->setRoutingType((ConnType)2);
+
+ ConnRef *connRef258 = new ConnRef(router, 258);
+ ConnEnd srcPt258(Point(410, 583), 15);
+ connRef258->setSourceEndpoint(srcPt258);
+ ConnEnd dstPt258(Point(371, 554), 15);
+ connRef258->setDestEndpoint(dstPt258);
+ connRef258->setRoutingType((ConnType)2);
+
+ ConnRef *connRef259 = new ConnRef(router, 259);
+ ConnEnd srcPt259(Point(410, 583), 15);
+ connRef259->setSourceEndpoint(srcPt259);
+ ConnEnd dstPt259(Point(456, 590), 15);
+ connRef259->setDestEndpoint(dstPt259);
+ connRef259->setRoutingType((ConnType)2);
+
+ ConnRef *connRef260 = new ConnRef(router, 260);
+ ConnEnd srcPt260(Point(411, 519), 15);
+ connRef260->setSourceEndpoint(srcPt260);
+ ConnEnd dstPt260(Point(371, 554), 15);
+ connRef260->setDestEndpoint(dstPt260);
+ connRef260->setRoutingType((ConnType)2);
+
+ ConnRef *connRef261 = new ConnRef(router, 261);
+ ConnEnd srcPt261(Point(456, 446), 15);
+ connRef261->setSourceEndpoint(srcPt261);
+ ConnEnd dstPt261(Point(555, 522), 15);
+ connRef261->setDestEndpoint(dstPt261);
+ connRef261->setRoutingType((ConnType)2);
+
+ ConnRef *connRef262 = new ConnRef(router, 262);
+ ConnEnd srcPt262(Point(456, 446), 15);
+ connRef262->setSourceEndpoint(srcPt262);
+ ConnEnd dstPt262(Point(528, 541), 15);
+ connRef262->setDestEndpoint(dstPt262);
+ connRef262->setRoutingType((ConnType)2);
+
+ ConnRef *connRef263 = new ConnRef(router, 263);
+ ConnEnd srcPt263(Point(456, 446), 15);
+ connRef263->setSourceEndpoint(srcPt263);
+ ConnEnd dstPt263(Point(505, 522), 15);
+ connRef263->setDestEndpoint(dstPt263);
+ connRef263->setRoutingType((ConnType)2);
+
+ ConnRef *connRef264 = new ConnRef(router, 264);
+ ConnEnd srcPt264(Point(262, 990), 15);
+ connRef264->setSourceEndpoint(srcPt264);
+ ConnEnd dstPt264(Point(262, 940), 15);
+ connRef264->setDestEndpoint(dstPt264);
+ connRef264->setRoutingType((ConnType)2);
+
+ ConnRef *connRef265 = new ConnRef(router, 265);
+ ConnEnd srcPt265(Point(49, 908), 15);
+ connRef265->setSourceEndpoint(srcPt265);
+ ConnEnd dstPt265(Point(119, 908), 15);
+ connRef265->setDestEndpoint(dstPt265);
+ connRef265->setRoutingType((ConnType)2);
+
+ ConnRef *connRef266 = new ConnRef(router, 266);
+ ConnEnd srcPt266(Point(332, 1011), 15);
+ connRef266->setSourceEndpoint(srcPt266);
+ ConnEnd dstPt266(Point(262, 961), 15);
+ connRef266->setDestEndpoint(dstPt266);
+ connRef266->setRoutingType((ConnType)2);
+
+ ConnRef *connRef267 = new ConnRef(router, 267);
+ ConnEnd srcPt267(Point(421, 909), 15);
+ connRef267->setSourceEndpoint(srcPt267);
+ ConnEnd dstPt267(Point(351, 909), 15);
+ connRef267->setDestEndpoint(dstPt267);
+ connRef267->setRoutingType((ConnType)2);
+
+ ConnRef *connRef268 = new ConnRef(router, 268);
+ ConnEnd srcPt268(Point(460, 990), 15);
+ connRef268->setSourceEndpoint(srcPt268);
+ ConnEnd dstPt268(Point(460, 940), 15);
+ connRef268->setDestEndpoint(dstPt268);
+ connRef268->setRoutingType((ConnType)2);
+
+ ConnRef *connRef269 = new ConnRef(router, 269);
+ ConnEnd srcPt269(Point(412, 990), 15);
+ connRef269->setSourceEndpoint(srcPt269);
+ ConnEnd dstPt269(Point(412, 940), 15);
+ connRef269->setDestEndpoint(dstPt269);
+ connRef269->setRoutingType((ConnType)2);
+
+ ConnRef *connRef270 = new ConnRef(router, 270);
+ ConnEnd srcPt270(Point(404, 821), 15);
+ connRef270->setSourceEndpoint(srcPt270);
+ ConnEnd dstPt270(Point(404, 871), 15);
+ connRef270->setDestEndpoint(dstPt270);
+ connRef270->setRoutingType((ConnType)2);
+
+ ConnRef *connRef271 = new ConnRef(router, 271);
+ ConnEnd srcPt271(Point(474, 800), 15);
+ connRef271->setSourceEndpoint(srcPt271);
+ ConnEnd dstPt271(Point(404, 850), 15);
+ connRef271->setDestEndpoint(dstPt271);
+ connRef271->setRoutingType((ConnType)2);
+
+ ConnRef *connRef272 = new ConnRef(router, 272);
+ ConnEnd srcPt272(Point(292, 812), 15);
+ connRef272->setSourceEndpoint(srcPt272);
+ ConnEnd dstPt272(Point(292, 862), 15);
+ connRef272->setDestEndpoint(dstPt272);
+ connRef272->setRoutingType((ConnType)2);
+
+ ConnRef *connRef273 = new ConnRef(router, 273);
+ ConnEnd srcPt273(Point(183, 812), 15);
+ connRef273->setSourceEndpoint(srcPt273);
+ ConnEnd dstPt273(Point(183, 862), 15);
+ connRef273->setDestEndpoint(dstPt273);
+ connRef273->setRoutingType((ConnType)2);
+
+ ConnRef *connRef274 = new ConnRef(router, 274);
+ ConnEnd srcPt274(Point(531, 811), 15);
+ connRef274->setSourceEndpoint(srcPt274);
+ ConnEnd dstPt274(Point(531, 861), 15);
+ connRef274->setDestEndpoint(dstPt274);
+ connRef274->setRoutingType((ConnType)2);
+
+ ConnRef *connRef275 = new ConnRef(router, 275);
+ ConnEnd srcPt275(Point(526, 767), 15);
+ connRef275->setSourceEndpoint(srcPt275);
+ ConnEnd dstPt275(Point(456, 767), 15);
+ connRef275->setDestEndpoint(dstPt275);
+ connRef275->setRoutingType((ConnType)2);
+
+ ConnRef *connRef276 = new ConnRef(router, 276);
+ ConnEnd srcPt276(Point(526, 698), 15);
+ connRef276->setSourceEndpoint(srcPt276);
+ ConnEnd dstPt276(Point(456, 698), 15);
+ connRef276->setDestEndpoint(dstPt276);
+ connRef276->setRoutingType((ConnType)2);
+
+ ConnRef *connRef277 = new ConnRef(router, 277);
+ ConnEnd srcPt277(Point(527, 626), 15);
+ connRef277->setSourceEndpoint(srcPt277);
+ ConnEnd dstPt277(Point(457, 626), 15);
+ connRef277->setDestEndpoint(dstPt277);
+ connRef277->setRoutingType((ConnType)2);
+
+ ConnRef *connRef278 = new ConnRef(router, 278);
+ ConnEnd srcPt278(Point(361, 481), 15);
+ connRef278->setSourceEndpoint(srcPt278);
+ ConnEnd dstPt278(Point(431, 481), 15);
+ connRef278->setDestEndpoint(dstPt278);
+ connRef278->setRoutingType((ConnType)2);
+
+ ConnRef *connRef279 = new ConnRef(router, 279);
+ ConnEnd srcPt279(Point(376, 397), 15);
+ connRef279->setSourceEndpoint(srcPt279);
+ ConnEnd dstPt279(Point(376, 447), 15);
+ connRef279->setDestEndpoint(dstPt279);
+ connRef279->setRoutingType((ConnType)2);
+
+ ConnRef *connRef280 = new ConnRef(router, 280);
+ ConnEnd srcPt280(Point(526, 401), 15);
+ connRef280->setSourceEndpoint(srcPt280);
+ ConnEnd dstPt280(Point(456, 401), 15);
+ connRef280->setDestEndpoint(dstPt280);
+ connRef280->setRoutingType((ConnType)2);
+
+ ConnRef *connRef281 = new ConnRef(router, 281);
+ ConnEnd srcPt281(Point(526, 335), 15);
+ connRef281->setSourceEndpoint(srcPt281);
+ ConnEnd dstPt281(Point(456, 335), 15);
+ connRef281->setDestEndpoint(dstPt281);
+ connRef281->setRoutingType((ConnType)2);
+
+ ConnRef *connRef282 = new ConnRef(router, 282);
+ ConnEnd srcPt282(Point(403, 285), 15);
+ connRef282->setSourceEndpoint(srcPt282);
+ ConnEnd dstPt282(Point(403, 335), 15);
+ connRef282->setDestEndpoint(dstPt282);
+ connRef282->setRoutingType((ConnType)2);
+
+ ConnRef *connRef283 = new ConnRef(router, 283);
+ ConnEnd srcPt283(Point(525, 142), 15);
+ connRef283->setSourceEndpoint(srcPt283);
+ ConnEnd dstPt283(Point(525, 192), 15);
+ connRef283->setDestEndpoint(dstPt283);
+ connRef283->setRoutingType((ConnType)2);
+
+ ConnRef *connRef284 = new ConnRef(router, 284);
+ ConnEnd srcPt284(Point(526, 265), 15);
+ connRef284->setSourceEndpoint(srcPt284);
+ ConnEnd dstPt284(Point(456, 265), 15);
+ connRef284->setDestEndpoint(dstPt284);
+ connRef284->setRoutingType((ConnType)2);
+
+ ConnRef *connRef285 = new ConnRef(router, 285);
+ ConnEnd srcPt285(Point(386, 170), 15);
+ connRef285->setSourceEndpoint(srcPt285);
+ ConnEnd dstPt285(Point(456, 170), 15);
+ connRef285->setDestEndpoint(dstPt285);
+ connRef285->setRoutingType((ConnType)2);
+
+ ConnRef *connRef286 = new ConnRef(router, 286);
+ ConnEnd srcPt286(Point(376, 249), 15);
+ connRef286->setSourceEndpoint(srcPt286);
+ ConnEnd dstPt286(Point(376, 299), 15);
+ connRef286->setDestEndpoint(dstPt286);
+ connRef286->setRoutingType((ConnType)2);
+
+ ConnRef *connRef287 = new ConnRef(router, 287);
+ ConnEnd srcPt287(Point(291, 330), 15);
+ connRef287->setSourceEndpoint(srcPt287);
+ ConnEnd dstPt287(Point(221, 280), 15);
+ connRef287->setDestEndpoint(dstPt287);
+ connRef287->setRoutingType((ConnType)2);
+
+ ConnRef *connRef288 = new ConnRef(router, 288);
+ ConnEnd srcPt288(Point(221, 249), 15);
+ connRef288->setSourceEndpoint(srcPt288);
+ ConnEnd dstPt288(Point(221, 299), 15);
+ connRef288->setDestEndpoint(dstPt288);
+ connRef288->setRoutingType((ConnType)2);
+
+ ConnRef *connRef289 = new ConnRef(router, 289);
+ ConnEnd srcPt289(Point(330, 216), 15);
+ connRef289->setSourceEndpoint(srcPt289);
+ ConnEnd dstPt289(Point(330, 266), 15);
+ connRef289->setDestEndpoint(dstPt289);
+ connRef289->setRoutingType((ConnType)2);
+
+ ConnRef *connRef290 = new ConnRef(router, 290);
+ ConnEnd srcPt290(Point(280, 216), 15);
+ connRef290->setSourceEndpoint(srcPt290);
+ ConnEnd dstPt290(Point(280, 266), 15);
+ connRef290->setDestEndpoint(dstPt290);
+ connRef290->setRoutingType((ConnType)2);
+
+ ConnRef *connRef291 = new ConnRef(router, 291);
+ ConnEnd srcPt291(Point(84, 261), 15);
+ connRef291->setSourceEndpoint(srcPt291);
+ ConnEnd dstPt291(Point(154, 261), 15);
+ connRef291->setDestEndpoint(dstPt291);
+ connRef291->setRoutingType((ConnType)2);
+
+ ConnRef *connRef292 = new ConnRef(router, 292);
+ ConnEnd srcPt292(Point(221, 174), 15);
+ connRef292->setSourceEndpoint(srcPt292);
+ ConnEnd dstPt292(Point(221, 224), 15);
+ connRef292->setDestEndpoint(dstPt292);
+ connRef292->setRoutingType((ConnType)2);
+
+ ConnRef *connRef293 = new ConnRef(router, 293);
+ ConnEnd srcPt293(Point(221, 155), 15);
+ connRef293->setSourceEndpoint(srcPt293);
+ ConnEnd dstPt293(Point(221, 205), 15);
+ connRef293->setDestEndpoint(dstPt293);
+ connRef293->setRoutingType((ConnType)2);
+
+ ConnRef *connRef294 = new ConnRef(router, 294);
+ ConnEnd srcPt294(Point(289, 133), 15);
+ connRef294->setSourceEndpoint(srcPt294);
+ ConnEnd dstPt294(Point(289, 183), 15);
+ connRef294->setDestEndpoint(dstPt294);
+ connRef294->setRoutingType((ConnType)2);
+
+ ConnRef *connRef295 = new ConnRef(router, 295);
+ ConnEnd srcPt295(Point(316, 101), 15);
+ connRef295->setSourceEndpoint(srcPt295);
+ ConnEnd dstPt295(Point(316, 151), 15);
+ connRef295->setDestEndpoint(dstPt295);
+ connRef295->setRoutingType((ConnType)2);
+
+ ConnRef *connRef296 = new ConnRef(router, 296);
+ ConnEnd srcPt296(Point(316, 180), 15);
+ connRef296->setSourceEndpoint(srcPt296);
+ ConnEnd dstPt296(Point(316, 130), 15);
+ connRef296->setDestEndpoint(dstPt296);
+ connRef296->setRoutingType((ConnType)2);
+
+ ConnRef *connRef297 = new ConnRef(router, 297);
+ ConnEnd srcPt297(Point(235, 855), 15);
+ connRef297->setSourceEndpoint(srcPt297);
+ ConnEnd dstPt297(Point(235, 905), 15);
+ connRef297->setDestEndpoint(dstPt297);
+ connRef297->setRoutingType((ConnType)2);
+
+ ConnRef *connRef298 = new ConnRef(router, 298);
+ ConnEnd srcPt298(Point(526, 553), 15);
+ connRef298->setSourceEndpoint(srcPt298);
+ ConnEnd dstPt298(Point(456, 553), 15);
+ connRef298->setDestEndpoint(dstPt298);
+ connRef298->setRoutingType((ConnType)2);
+
+ ConnRef *connRef299 = new ConnRef(router, 299);
+ ConnEnd srcPt299(Point(221, 193), 15);
+ connRef299->setSourceEndpoint(srcPt299);
+ ConnEnd dstPt299(Point(221, 243), 15);
+ connRef299->setDestEndpoint(dstPt299);
+ connRef299->setRoutingType((ConnType)2);
+
+ ConnRef *connRef300 = new ConnRef(router, 300);
+ ConnEnd srcPt300(Point(291, 268), 15);
+ connRef300->setSourceEndpoint(srcPt300);
+ ConnEnd dstPt300(Point(221, 318), 15);
+ connRef300->setDestEndpoint(dstPt300);
+ connRef300->setRoutingType((ConnType)2);
+
+ ConnRef *connRef301 = new ConnRef(router, 301);
+ ConnEnd srcPt301(Point(154, 307), 15);
+ connRef301->setSourceEndpoint(srcPt301);
+ ConnEnd dstPt301(Point(154, 357), 15);
+ connRef301->setDestEndpoint(dstPt301);
+ connRef301->setRoutingType((ConnType)2);
+
+ ConnRef *connRef302 = new ConnRef(router, 302);
+ ConnEnd srcPt302(Point(154, 433), 15);
+ connRef302->setSourceEndpoint(srcPt302);
+ ConnEnd dstPt302(Point(154, 383), 15);
+ connRef302->setDestEndpoint(dstPt302);
+ connRef302->setRoutingType((ConnType)2);
+
+ ConnRef *connRef303 = new ConnRef(router, 303);
+ ConnEnd srcPt303(Point(264, 306), 15);
+ connRef303->setSourceEndpoint(srcPt303);
+ ConnEnd dstPt303(Point(264, 356), 15);
+ connRef303->setDestEndpoint(dstPt303);
+ connRef303->setRoutingType((ConnType)2);
+
+ ConnRef *connRef304 = new ConnRef(router, 304);
+ ConnEnd srcPt304(Point(264, 432), 15);
+ connRef304->setSourceEndpoint(srcPt304);
+ ConnEnd dstPt304(Point(264, 382), 15);
+ connRef304->setDestEndpoint(dstPt304);
+ connRef304->setRoutingType((ConnType)2);
+
+ ConnRef *connRef305 = new ConnRef(router, 305);
+ ConnEnd srcPt305(Point(177, 673), 15);
+ connRef305->setSourceEndpoint(srcPt305);
+ ConnEnd dstPt305(Point(177, 723), 15);
+ connRef305->setDestEndpoint(dstPt305);
+ connRef305->setRoutingType((ConnType)2);
+
+ ConnRef *connRef306 = new ConnRef(router, 306);
+ ConnEnd srcPt306(Point(482, 911), 15);
+ connRef306->setSourceEndpoint(srcPt306);
+ ConnEnd dstPt306(Point(412, 961), 15);
+ connRef306->setDestEndpoint(dstPt306);
+ connRef306->setRoutingType((ConnType)2);
+
+ ConnRef *connRef307 = new ConnRef(router, 307);
+ ConnEnd srcPt307(Point(247, 694), 15);
+ connRef307->setSourceEndpoint(srcPt307);
+ ConnEnd dstPt307(Point(177, 744), 15);
+ connRef307->setDestEndpoint(dstPt307);
+ connRef307->setRoutingType((ConnType)2);
+
+ ConnRef *connRef308 = new ConnRef(router, 308);
+ ConnEnd srcPt308(Point(460, 911), 15);
+ connRef308->setSourceEndpoint(srcPt308);
+ ConnEnd dstPt308(Point(460, 961), 15);
+ connRef308->setDestEndpoint(dstPt308);
+ connRef308->setRoutingType((ConnType)2);
+
+ ConnRef *connRef309 = new ConnRef(router, 309);
+ ConnEnd srcPt309(Point(551, 481), 15);
+ connRef309->setSourceEndpoint(srcPt309);
+ ConnEnd dstPt309(Point(481, 481), 15);
+ connRef309->setDestEndpoint(dstPt309);
+ connRef309->setRoutingType((ConnType)2);
+
+ ConnRef *connRef310 = new ConnRef(router, 310);
+ ConnEnd srcPt310(Point(555, 472), 15);
+ connRef310->setSourceEndpoint(srcPt310);
+ ConnEnd dstPt310(Point(555, 522), 15);
+ connRef310->setDestEndpoint(dstPt310);
+ connRef310->setRoutingType((ConnType)2);
+
+ ConnRef *connRef311 = new ConnRef(router, 311);
+ ConnEnd srcPt311(Point(528, 591), 15);
+ connRef311->setSourceEndpoint(srcPt311);
+ ConnEnd dstPt311(Point(528, 541), 15);
+ connRef311->setDestEndpoint(dstPt311);
+ connRef311->setRoutingType((ConnType)2);
+
+ ConnRef *connRef312 = new ConnRef(router, 312);
+ ConnEnd srcPt312(Point(262, 742), 15);
+ connRef312->setSourceEndpoint(srcPt312);
+ ConnEnd dstPt312(Point(262, 792), 15);
+ connRef312->setDestEndpoint(dstPt312);
+ connRef312->setRoutingType((ConnType)2);
+
+ ConnRef *connRef313 = new ConnRef(router, 313);
+ ConnEnd srcPt313(Point(575, 522), 15);
+ connRef313->setSourceEndpoint(srcPt313);
+ ConnEnd dstPt313(Point(505, 522), 15);
+ connRef313->setDestEndpoint(dstPt313);
+ connRef313->setRoutingType((ConnType)2);
+
+ ConnRef *connRef314 = new ConnRef(router, 314);
+ ConnEnd srcPt314(Point(410, 633), 15);
+ connRef314->setSourceEndpoint(srcPt314);
+ ConnEnd dstPt314(Point(410, 583), 15);
+ connRef314->setDestEndpoint(dstPt314);
+ connRef314->setRoutingType((ConnType)2);
+
+ ConnRef *connRef315 = new ConnRef(router, 315);
+ ConnEnd srcPt315(Point(411, 469), 15);
+ connRef315->setSourceEndpoint(srcPt315);
+ ConnEnd dstPt315(Point(411, 519), 15);
+ connRef315->setDestEndpoint(dstPt315);
+ connRef315->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/orderassertion");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/orthordering01.cpp b/src/3rdparty/adaptagrams/libavoid/tests/orthordering01.cpp
new file mode 100644
index 0000000..30317e6
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/orthordering01.cpp
@@ -0,0 +1,92 @@
+// From bandgap_1_nooverlap_reduced_libavoid-debug.
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 400);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 110);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+ Polygon poly143407352(4);
+ poly143407352.ps[0] = Point(5810, 4340);
+ poly143407352.ps[1] = Point(5810, 5035);
+ poly143407352.ps[2] = Point(5450, 5035);
+ poly143407352.ps[3] = Point(5450, 4340);
+ new ShapeRef(router, poly143407352, 143407352);
+
+ Polygon poly124950386(4);
+ poly124950386.ps[0] = Point(4900, 4090);
+ poly124950386.ps[1] = Point(4900, 4785);
+ poly124950386.ps[2] = Point(4540, 4785);
+ poly124950386.ps[3] = Point(4540, 4090);
+ new ShapeRef(router, poly124950386, 124950386);
+
+ ConnRef *connRef373967044 = new ConnRef(router, 373967044);
+ ConnEnd srcPt373967044(Point(4890, 4250), 8);
+ connRef373967044->setSourceEndpoint(srcPt373967044);
+ ConnEnd dstPt373967044(Point(5460, 4500), 4);
+ connRef373967044->setDestEndpoint(dstPt373967044);
+ connRef373967044->setRoutingType((ConnType)2);
+
+ ConnRef *connRef681881486 = new ConnRef(router, 681881486);
+ ConnEnd srcPt681881486(Point(4890, 4325), 8);
+ connRef681881486->setSourceEndpoint(srcPt681881486);
+ ConnEnd dstPt681881486(Point(5460, 4575), 4);
+ connRef681881486->setDestEndpoint(dstPt681881486);
+ connRef681881486->setRoutingType((ConnType)2);
+
+ ConnRef *connRef829752 = new ConnRef(router, 829752);
+ ConnEnd srcPt829752(Point(4890, 4400), 8);
+ connRef829752->setSourceEndpoint(srcPt829752);
+ ConnEnd dstPt829752(Point(5460, 4650), 4);
+ connRef829752->setDestEndpoint(dstPt829752);
+ connRef829752->setRoutingType((ConnType)2);
+
+ ConnRef *connRef17625739 = new ConnRef(router, 17625739);
+ ConnEnd srcPt17625739(Point(4890, 4475), 8);
+ connRef17625739->setSourceEndpoint(srcPt17625739);
+ ConnEnd dstPt17625739(Point(5460, 4725), 4);
+ connRef17625739->setDestEndpoint(dstPt17625739);
+ connRef17625739->setRoutingType((ConnType)2);
+
+ ConnRef *connRef223864175 = new ConnRef(router, 223864175);
+ ConnEnd srcPt223864175(Point(4890, 4550), 8);
+ connRef223864175->setSourceEndpoint(srcPt223864175);
+ ConnEnd dstPt223864175(Point(5460, 4800), 4);
+ connRef223864175->setDestEndpoint(dstPt223864175);
+ connRef223864175->setRoutingType((ConnType)2);
+
+ ConnRef *connRef98144280 = new ConnRef(router, 98144280);
+ ConnEnd srcPt98144280(Point(4890, 4625), 8);
+ connRef98144280->setSourceEndpoint(srcPt98144280);
+ ConnEnd dstPt98144280(Point(5460, 4875), 4);
+ connRef98144280->setDestEndpoint(dstPt98144280);
+ connRef98144280->setRoutingType((ConnType)2);
+
+ ConnRef *connRef283100856 = new ConnRef(router, 283100856);
+ ConnEnd srcPt283100856(Point(4890, 4700), 8);
+ connRef283100856->setSourceEndpoint(srcPt283100856);
+ ConnEnd dstPt283100856(Point(5460, 4950), 4);
+ connRef283100856->setDestEndpoint(dstPt283100856);
+ connRef283100856->setRoutingType((ConnType)2);
+
+ ConnRef *connRef387080925 = new ConnRef(router, 387080925);
+ ConnEnd srcPt387080925(Point(5460, 4425), 4);
+ connRef387080925->setSourceEndpoint(srcPt387080925);
+ ConnEnd dstPt387080925(Point(4890, 4175), 8);
+ connRef387080925->setDestEndpoint(dstPt387080925);
+ connRef387080925->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/orthordering-01");
+
+ int crossings = router->existsCrossings();
+
+ delete router;
+ return (crossings > 0) ? 1 : 0;
+};
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/orthordering02.cpp b/src/3rdparty/adaptagrams/libavoid/tests/orthordering02.cpp
new file mode 100644
index 0000000..1fec6fa
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/orthordering02.cpp
@@ -0,0 +1,92 @@
+// From bandgap_1_overlap_reduced_libavoid-debug.svg.
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 50);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 110);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+ Polygon poly143407352(4);
+ poly143407352.ps[0] = Point(6035, 4390);
+ poly143407352.ps[1] = Point(6035, 5085);
+ poly143407352.ps[2] = Point(5675, 5085);
+ poly143407352.ps[3] = Point(5675, 4390);
+ new ShapeRef(router, poly143407352, 143407352);
+
+ Polygon poly124950386(4);
+ poly124950386.ps[0] = Point(4900, 4090);
+ poly124950386.ps[1] = Point(4900, 4785);
+ poly124950386.ps[2] = Point(4540, 4785);
+ poly124950386.ps[3] = Point(4540, 4090);
+ new ShapeRef(router, poly124950386, 124950386);
+
+ ConnRef *connRef373967044 = new ConnRef(router, 373967044);
+ ConnEnd srcPt373967044(Point(4890, 4250), 8);
+ connRef373967044->setSourceEndpoint(srcPt373967044);
+ ConnEnd dstPt373967044(Point(5685, 4550), 4);
+ connRef373967044->setDestEndpoint(dstPt373967044);
+ connRef373967044->setRoutingType((ConnType)2);
+
+ ConnRef *connRef681881486 = new ConnRef(router, 681881486);
+ ConnEnd srcPt681881486(Point(4890, 4325), 8);
+ connRef681881486->setSourceEndpoint(srcPt681881486);
+ ConnEnd dstPt681881486(Point(5685, 4625), 4);
+ connRef681881486->setDestEndpoint(dstPt681881486);
+ connRef681881486->setRoutingType((ConnType)2);
+
+ ConnRef *connRef829752 = new ConnRef(router, 829752);
+ ConnEnd srcPt829752(Point(4890, 4400), 8);
+ connRef829752->setSourceEndpoint(srcPt829752);
+ ConnEnd dstPt829752(Point(5685, 4700), 4);
+ connRef829752->setDestEndpoint(dstPt829752);
+ connRef829752->setRoutingType((ConnType)2);
+
+ ConnRef *connRef17625739 = new ConnRef(router, 17625739);
+ ConnEnd srcPt17625739(Point(4890, 4475), 8);
+ connRef17625739->setSourceEndpoint(srcPt17625739);
+ ConnEnd dstPt17625739(Point(5685, 4775), 4);
+ connRef17625739->setDestEndpoint(dstPt17625739);
+ connRef17625739->setRoutingType((ConnType)2);
+
+ ConnRef *connRef223864175 = new ConnRef(router, 223864175);
+ ConnEnd srcPt223864175(Point(4890, 4550), 8);
+ connRef223864175->setSourceEndpoint(srcPt223864175);
+ ConnEnd dstPt223864175(Point(5685, 4850), 4);
+ connRef223864175->setDestEndpoint(dstPt223864175);
+ connRef223864175->setRoutingType((ConnType)2);
+
+ ConnRef *connRef98144280 = new ConnRef(router, 98144280);
+ ConnEnd srcPt98144280(Point(4890, 4625), 8);
+ connRef98144280->setSourceEndpoint(srcPt98144280);
+ ConnEnd dstPt98144280(Point(5685, 4925), 4);
+ connRef98144280->setDestEndpoint(dstPt98144280);
+ connRef98144280->setRoutingType((ConnType)2);
+
+ ConnRef *connRef283100856 = new ConnRef(router, 283100856);
+ ConnEnd srcPt283100856(Point(4890, 4700), 8);
+ connRef283100856->setSourceEndpoint(srcPt283100856);
+ ConnEnd dstPt283100856(Point(5685, 5000), 4);
+ connRef283100856->setDestEndpoint(dstPt283100856);
+ connRef283100856->setRoutingType((ConnType)2);
+
+ ConnRef *connRef387080925 = new ConnRef(router, 387080925);
+ ConnEnd srcPt387080925(Point(5685, 4475), 4);
+ connRef387080925->setSourceEndpoint(srcPt387080925);
+ ConnEnd dstPt387080925(Point(4890, 4175), 8);
+ connRef387080925->setDestEndpoint(dstPt387080925);
+ connRef387080925->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/orthordering-02");
+
+ int crossings = router->existsCrossings();
+
+ delete router;
+ return (crossings > 0) ? 1 : 0;
+};
+
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/output/README.txt b/src/3rdparty/adaptagrams/libavoid/tests/output/README.txt
new file mode 100644
index 0000000..1524fa2
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/output/README.txt
@@ -0,0 +1 @@
+This directory is used to for output debug svg files from the testcases.
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/overlappingRects.cpp b/src/3rdparty/adaptagrams/libavoid/tests/overlappingRects.cpp
new file mode 100644
index 0000000..f286285
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/overlappingRects.cpp
@@ -0,0 +1,2327 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 0);
+ router->setRoutingOption(nudgeOrthogonalSegmentsConnectedToShapes, true);
+
+ Polygon poly57(4);
+ poly57.ps[0] = Point(-66.016, 38.6079);
+ poly57.ps[1] = Point(-66.016, 58.6079);
+ poly57.ps[2] = Point(-86.016, 58.6079);
+ poly57.ps[3] = Point(-86.016, 38.6079);
+ new ShapeRef(router, poly57, 57);
+
+ Polygon poly114(4);
+ poly114.ps[0] = Point(886.746, 359.608);
+ poly114.ps[1] = Point(886.746, 399.608);
+ poly114.ps[2] = Point(830.746, 399.608);
+ poly114.ps[3] = Point(830.746, 359.608);
+ new ShapeRef(router, poly114, 114);
+
+ Polygon poly126(4);
+ poly126.ps[0] = Point(510.984, 767.608);
+ poly126.ps[1] = Point(510.984, 807.608);
+ poly126.ps[2] = Point(454.984, 807.608);
+ poly126.ps[3] = Point(454.984, 767.608);
+ new ShapeRef(router, poly126, 126);
+
+ Polygon poly142(4);
+ poly142.ps[0] = Point(149.984, 62.6079);
+ poly142.ps[1] = Point(149.984, 102.608);
+ poly142.ps[2] = Point(93.984, 102.608);
+ poly142.ps[3] = Point(93.984, 62.6079);
+ new ShapeRef(router, poly142, 142);
+
+ Polygon poly115(4);
+ poly115.ps[0] = Point(539.534, 166.608);
+ poly115.ps[1] = Point(539.534, 206.608);
+ poly115.ps[2] = Point(483.534, 206.608);
+ poly115.ps[3] = Point(483.534, 166.608);
+ new ShapeRef(router, poly115, 115);
+
+ Polygon poly107(4);
+ poly107.ps[0] = Point(484.984, 500.608);
+ poly107.ps[1] = Point(484.984, 540.608);
+ poly107.ps[2] = Point(444.984, 540.608);
+ poly107.ps[3] = Point(444.984, 500.608);
+ new ShapeRef(router, poly107, 107);
+
+ Polygon poly164(4);
+ poly164.ps[0] = Point(388.984, 1086.01);
+ poly164.ps[1] = Point(388.984, 1126.01);
+ poly164.ps[2] = Point(328.984, 1126.01);
+ poly164.ps[3] = Point(328.984, 1086.01);
+ new ShapeRef(router, poly164, 164);
+
+ Polygon poly40(4);
+ poly40.ps[0] = Point(131.984, -13.3921);
+ poly40.ps[1] = Point(131.984, 6.60786);
+ poly40.ps[2] = Point(111.984, 6.60786);
+ poly40.ps[3] = Point(111.984, -13.3921);
+ new ShapeRef(router, poly40, 40);
+
+ Polygon poly161(4);
+ poly161.ps[0] = Point(785.5, 24.6079);
+ poly161.ps[1] = Point(785.5, 64.6079);
+ poly161.ps[2] = Point(725.5, 64.6079);
+ poly161.ps[3] = Point(725.5, 24.6079);
+ new ShapeRef(router, poly161, 161);
+
+ Polygon poly82(4);
+ poly82.ps[0] = Point(813.984, 1031.01);
+ poly82.ps[1] = Point(813.984, 1071.01);
+ poly82.ps[2] = Point(773.984, 1071.01);
+ poly82.ps[3] = Point(773.984, 1031.01);
+ new ShapeRef(router, poly82, 82);
+
+ Polygon poly146(4);
+ poly146.ps[0] = Point(530.584, -65.3921);
+ poly146.ps[1] = Point(530.584, -25.3921);
+ poly146.ps[2] = Point(474.584, -25.3921);
+ poly146.ps[3] = Point(474.584, -65.3921);
+ new ShapeRef(router, poly146, 146);
+
+ Polygon poly151(4);
+ poly151.ps[0] = Point(97.984, -229.392);
+ poly151.ps[1] = Point(97.984, -189.392);
+ poly151.ps[2] = Point(41.984, -189.392);
+ poly151.ps[3] = Point(41.984, -229.392);
+ new ShapeRef(router, poly151, 151);
+
+ Polygon poly23(4);
+ poly23.ps[0] = Point(691.984, 725.608);
+ poly23.ps[1] = Point(691.984, 745.608);
+ poly23.ps[2] = Point(671.984, 745.608);
+ poly23.ps[3] = Point(671.984, 725.608);
+ new ShapeRef(router, poly23, 23);
+
+ Polygon poly121(4);
+ poly121.ps[0] = Point(709.984, 1063.01);
+ poly121.ps[1] = Point(709.984, 1103.01);
+ poly121.ps[2] = Point(653.984, 1103.01);
+ poly121.ps[3] = Point(653.984, 1063.01);
+ new ShapeRef(router, poly121, 121);
+
+ Polygon poly68(4);
+ poly68.ps[0] = Point(460.584, 164.608);
+ poly68.ps[1] = Point(460.584, 204.608);
+ poly68.ps[2] = Point(420.584, 204.608);
+ poly68.ps[3] = Point(420.584, 164.608);
+ new ShapeRef(router, poly68, 68);
+
+ Polygon poly53(4);
+ poly53.ps[0] = Point(450.584, -424.392);
+ poly53.ps[1] = Point(450.584, -404.392);
+ poly53.ps[2] = Point(430.584, -404.392);
+ poly53.ps[3] = Point(430.584, -424.392);
+ new ShapeRef(router, poly53, 53);
+
+ Polygon poly29(4);
+ poly29.ps[0] = Point(808.746, 229.608);
+ poly29.ps[1] = Point(808.746, 249.608);
+ poly29.ps[2] = Point(788.746, 249.608);
+ poly29.ps[3] = Point(788.746, 229.608);
+ new ShapeRef(router, poly29, 29);
+
+ Polygon poly88(4);
+ poly88.ps[0] = Point(1085.98, 883.608);
+ poly88.ps[1] = Point(1085.98, 923.608);
+ poly88.ps[2] = Point(1045.98, 923.608);
+ poly88.ps[3] = Point(1045.98, 883.608);
+ new ShapeRef(router, poly88, 88);
+
+ Polygon poly141(4);
+ poly141.ps[0] = Point(390.984, 62.6079);
+ poly141.ps[1] = Point(390.984, 102.608);
+ poly141.ps[2] = Point(334.984, 102.608);
+ poly141.ps[3] = Point(334.984, 62.6079);
+ new ShapeRef(router, poly141, 141);
+
+ Polygon poly118(4);
+ poly118.ps[0] = Point(1155.98, 739.608);
+ poly118.ps[1] = Point(1155.98, 779.608);
+ poly118.ps[2] = Point(1099.98, 779.608);
+ poly118.ps[3] = Point(1099.98, 739.608);
+ new ShapeRef(router, poly118, 118);
+
+ Polygon poly31(4);
+ poly31.ps[0] = Point(1.98401, 363.608);
+ poly31.ps[1] = Point(1.98401, 383.608);
+ poly31.ps[2] = Point(-18.016, 383.608);
+ poly31.ps[3] = Point(-18.016, 363.608);
+ new ShapeRef(router, poly31, 31);
+
+ Polygon poly137(4);
+ poly137.ps[0] = Point(408.584, 166.608);
+ poly137.ps[1] = Point(408.584, 206.608);
+ poly137.ps[2] = Point(352.584, 206.608);
+ poly137.ps[3] = Point(352.584, 166.608);
+ new ShapeRef(router, poly137, 137);
+
+ Polygon poly159(4);
+ poly159.ps[0] = Point(622.984, 330.5);
+ poly159.ps[1] = Point(622.984, 390.5);
+ poly159.ps[2] = Point(582.984, 390.5);
+ poly159.ps[3] = Point(582.984, 330.5);
+ new ShapeRef(router, poly159, 159);
+
+ Polygon poly169(4);
+ poly169.ps[0] = Point(1089.98, 243.608);
+ poly169.ps[1] = Point(1089.98, 303.608);
+ poly169.ps[2] = Point(1049.98, 303.608);
+ poly169.ps[3] = Point(1049.98, 243.608);
+ new ShapeRef(router, poly169, 169);
+
+ Polygon poly13(4);
+ poly13.ps[0] = Point(763.984, 1145.01);
+ poly13.ps[1] = Point(763.984, 1165.01);
+ poly13.ps[2] = Point(743.984, 1165.01);
+ poly13.ps[3] = Point(743.984, 1145.01);
+ new ShapeRef(router, poly13, 13);
+
+ Polygon poly33(4);
+ poly33.ps[0] = Point(327.084, 309.608);
+ poly33.ps[1] = Point(327.084, 329.608);
+ poly33.ps[2] = Point(307.084, 329.608);
+ poly33.ps[3] = Point(307.084, 309.608);
+ new ShapeRef(router, poly33, 33);
+
+ Polygon poly60(4);
+ poly60.ps[0] = Point(11.984, -23.3921);
+ poly60.ps[1] = Point(11.984, 16.6079);
+ poly60.ps[2] = Point(-28.016, 16.6079);
+ poly60.ps[3] = Point(-28.016, -23.3921);
+ new ShapeRef(router, poly60, 60);
+
+ Polygon poly145(4);
+ poly145.ps[0] = Point(149.984, -73.3921);
+ poly145.ps[1] = Point(149.984, -33.3921);
+ poly145.ps[2] = Point(93.984, -33.3921);
+ poly145.ps[3] = Point(93.984, -73.3921);
+ new ShapeRef(router, poly145, 145);
+
+ Polygon poly134(4);
+ poly134.ps[0] = Point(888.746, 219.608);
+ poly134.ps[1] = Point(888.746, 259.608);
+ poly134.ps[2] = Point(832.746, 259.608);
+ poly134.ps[3] = Point(832.746, 219.608);
+ new ShapeRef(router, poly134, 134);
+
+ Polygon poly160(4);
+ poly160.ps[0] = Point(785.5, -27.3921);
+ poly160.ps[1] = Point(785.5, 12.6079);
+ poly160.ps[2] = Point(725.5, 12.6079);
+ poly160.ps[3] = Point(725.5, -27.3921);
+ new ShapeRef(router, poly160, 160);
+
+ Polygon poly117(4);
+ poly117.ps[0] = Point(646.484, 1203.01);
+ poly117.ps[1] = Point(646.484, 1243.01);
+ poly117.ps[2] = Point(590.484, 1243.01);
+ poly117.ps[3] = Point(590.484, 1203.01);
+ new ShapeRef(router, poly117, 117);
+
+ Polygon poly170(4);
+ poly170.ps[0] = Point(322.984, 536.5);
+ poly170.ps[1] = Point(322.984, 596.5);
+ poly170.ps[2] = Point(282.984, 596.5);
+ poly170.ps[3] = Point(282.984, 536.5);
+ new ShapeRef(router, poly170, 170);
+
+ Polygon poly36(4);
+ poly36.ps[0] = Point(372.984, 122.608);
+ poly36.ps[1] = Point(372.984, 142.608);
+ poly36.ps[2] = Point(352.984, 142.608);
+ poly36.ps[3] = Point(352.984, 122.608);
+ new ShapeRef(router, poly36, 36);
+
+ Polygon poly19(4);
+ poly19.ps[0] = Point(803.984, 869.608);
+ poly19.ps[1] = Point(803.984, 889.608);
+ poly19.ps[2] = Point(783.984, 889.608);
+ poly19.ps[3] = Point(783.984, 869.608);
+ new ShapeRef(router, poly19, 19);
+
+ Polygon poly116(4);
+ poly116.ps[0] = Point(456.984, 1213.01);
+ poly116.ps[1] = Point(456.984, 1253.01);
+ poly116.ps[2] = Point(400.984, 1253.01);
+ poly116.ps[3] = Point(400.984, 1213.01);
+ new ShapeRef(router, poly116, 116);
+
+ Polygon poly52(4);
+ poly52.ps[0] = Point(450.584, -271.392);
+ poly52.ps[1] = Point(450.584, -251.392);
+ poly52.ps[2] = Point(430.584, -251.392);
+ poly52.ps[3] = Point(430.584, -271.392);
+ new ShapeRef(router, poly52, 52);
+
+ Polygon poly99(4);
+ poly99.ps[0] = Point(307.984, -334.392);
+ poly99.ps[1] = Point(307.984, -294.392);
+ poly99.ps[2] = Point(267.984, -294.392);
+ poly99.ps[3] = Point(267.984, -334.392);
+ new ShapeRef(router, poly99, 99);
+
+ Polygon poly154(4);
+ poly154.ps[0] = Point(570.984, 450.608);
+ poly154.ps[1] = Point(570.984, 490.608);
+ poly154.ps[2] = Point(514.984, 490.608);
+ poly154.ps[3] = Point(514.984, 450.608);
+ new ShapeRef(router, poly154, 154);
+
+ Polygon poly150(4);
+ poly150.ps[0] = Point(377.984, -281.392);
+ poly150.ps[1] = Point(377.984, -241.392);
+ poly150.ps[2] = Point(321.984, -241.392);
+ poly150.ps[3] = Point(321.984, -281.392);
+ new ShapeRef(router, poly150, 150);
+
+ Polygon poly153(4);
+ poly153.ps[0] = Point(767.984, 450.608);
+ poly153.ps[1] = Point(767.984, 490.608);
+ poly153.ps[2] = Point(711.984, 490.608);
+ poly153.ps[3] = Point(711.984, 450.608);
+ new ShapeRef(router, poly153, 153);
+
+ Polygon poly104(4);
+ poly104.ps[0] = Point(965.984, 164.608);
+ poly104.ps[1] = Point(965.984, 204.608);
+ poly104.ps[2] = Point(925.984, 204.608);
+ poly104.ps[3] = Point(925.984, 164.608);
+ new ShapeRef(router, poly104, 104);
+
+ Polygon poly75(4);
+ poly75.ps[0] = Point(442.984, 663.608);
+ poly75.ps[1] = Point(442.984, 703.608);
+ poly75.ps[2] = Point(402.984, 703.608);
+ poly75.ps[3] = Point(402.984, 663.608);
+ new ShapeRef(router, poly75, 75);
+
+ Polygon poly51(4);
+ poly51.ps[0] = Point(450.584, -55.3921);
+ poly51.ps[1] = Point(450.584, -35.3921);
+ poly51.ps[2] = Point(430.584, -35.3921);
+ poly51.ps[3] = Point(430.584, -55.3921);
+ new ShapeRef(router, poly51, 51);
+
+ Polygon poly112(4);
+ poly112.ps[0] = Point(539.534, -229.392);
+ poly112.ps[1] = Point(539.534, -189.392);
+ poly112.ps[2] = Point(483.534, -189.392);
+ poly112.ps[3] = Point(483.534, -229.392);
+ new ShapeRef(router, poly112, 112);
+
+ Polygon poly61(4);
+ poly61.ps[0] = Point(337.084, 425.608);
+ poly61.ps[1] = Point(337.084, 465.608);
+ poly61.ps[2] = Point(297.084, 465.608);
+ poly61.ps[3] = Point(297.084, 425.608);
+ new ShapeRef(router, poly61, 61);
+
+ Polygon poly158(4);
+ poly158.ps[0] = Point(285.084, 425.608);
+ poly158.ps[1] = Point(285.084, 465.608);
+ poly158.ps[2] = Point(225.084, 465.608);
+ poly158.ps[3] = Point(225.084, 425.608);
+ new ShapeRef(router, poly158, 158);
+
+ Polygon poly162(4);
+ poly162.ps[0] = Point(785.5, 76.6079);
+ poly162.ps[1] = Point(785.5, 116.608);
+ poly162.ps[2] = Point(725.5, 116.608);
+ poly162.ps[3] = Point(725.5, 76.6079);
+ new ShapeRef(router, poly162, 162);
+
+ Polygon poly103(4);
+ poly103.ps[0] = Point(965.984, 315.608);
+ poly103.ps[1] = Point(965.984, 355.608);
+ poly103.ps[2] = Point(925.984, 355.608);
+ poly103.ps[3] = Point(925.984, 315.608);
+ new ShapeRef(router, poly103, 103);
+
+ Polygon poly90(4);
+ poly90.ps[0] = Point(813.984, 817.608);
+ poly90.ps[1] = Point(813.984, 857.608);
+ poly90.ps[2] = Point(773.984, 857.608);
+ poly90.ps[3] = Point(773.984, 817.608);
+ new ShapeRef(router, poly90, 90);
+
+ Polygon poly70(4);
+ poly70.ps[0] = Point(340.584, 164.608);
+ poly70.ps[1] = Point(340.584, 204.608);
+ poly70.ps[2] = Point(300.584, 204.608);
+ poly70.ps[3] = Point(300.584, 164.608);
+ new ShapeRef(router, poly70, 70);
+
+ Polygon poly50(4);
+ poly50.ps[0] = Point(886.746, 307.608);
+ poly50.ps[1] = Point(886.746, 347.608);
+ poly50.ps[2] = Point(830.746, 347.608);
+ poly50.ps[3] = Point(830.746, 307.608);
+ new ShapeRef(router, poly50, 50);
+
+ Polygon poly49(4);
+ poly49.ps[0] = Point(1115.98, 1187.01);
+ poly49.ps[1] = Point(1115.98, 1247.01);
+ poly49.ps[2] = Point(825.984, 1247.01);
+ poly49.ps[3] = Point(825.984, 1187.01);
+ new ShapeRef(router, poly49, 49);
+
+ Polygon poly37(4);
+ poly37.ps[0] = Point(131.984, 122.608);
+ poly37.ps[1] = Point(131.984, 142.608);
+ poly37.ps[2] = Point(111.984, 142.608);
+ poly37.ps[3] = Point(111.984, 122.608);
+ new ShapeRef(router, poly37, 37);
+
+ Polygon poly120(4);
+ poly120.ps[0] = Point(843.984, 1135.01);
+ poly120.ps[1] = Point(843.984, 1175.01);
+ poly120.ps[2] = Point(787.984, 1175.01);
+ poly120.ps[3] = Point(787.984, 1135.01);
+ new ShapeRef(router, poly120, 120);
+
+ Polygon poly28(4);
+ poly28.ps[0] = Point(372.984, 673.608);
+ poly28.ps[1] = Point(372.984, 693.608);
+ poly28.ps[2] = Point(352.984, 693.608);
+ poly28.ps[3] = Point(352.984, 673.608);
+ new ShapeRef(router, poly28, 28);
+
+ Polygon poly136(4);
+ poly136.ps[0] = Point(81.984, 353.608);
+ poly136.ps[1] = Point(81.984, 393.608);
+ poly136.ps[2] = Point(25.984, 393.608);
+ poly136.ps[3] = Point(25.984, 353.608);
+ new ShapeRef(router, poly136, 136);
+
+ Polygon poly12(4);
+ poly12.ps[0] = Point(933.984, 939.008);
+ poly12.ps[1] = Point(933.984, 959.008);
+ poly12.ps[2] = Point(913.984, 959.008);
+ poly12.ps[3] = Point(913.984, 939.008);
+ new ShapeRef(router, poly12, 12);
+
+ Polygon poly131(4);
+ poly131.ps[0] = Point(390.984, 715.608);
+ poly131.ps[1] = Point(390.984, 755.608);
+ poly131.ps[2] = Point(334.984, 755.608);
+ poly131.ps[3] = Point(334.984, 715.608);
+ new ShapeRef(router, poly131, 131);
+
+ Polygon poly78(4);
+ poly78.ps[0] = Point(302.984, 1031.01);
+ poly78.ps[1] = Point(302.984, 1071.01);
+ poly78.ps[2] = Point(262.984, 1071.01);
+ poly78.ps[3] = Point(262.984, 1031.01);
+ new ShapeRef(router, poly78, 78);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(944.984, 516.108);
+ poly3.ps[1] = Point(944.984, 536.108);
+ poly3.ps[2] = Point(924.984, 536.108);
+ poly3.ps[3] = Point(924.984, 516.108);
+ new ShapeRef(router, poly3, 3);
+
+ Polygon poly17(4);
+ poly17.ps[0] = Point(691.984, 939.008);
+ poly17.ps[1] = Point(691.984, 959.008);
+ poly17.ps[2] = Point(671.984, 959.008);
+ poly17.ps[3] = Point(671.984, 939.008);
+ new ShapeRef(router, poly17, 17);
+
+ Polygon poly66(4);
+ poly66.ps[0] = Point(11.984, 229.608);
+ poly66.ps[1] = Point(11.984, 269.608);
+ poly66.ps[2] = Point(-28.016, 269.608);
+ poly66.ps[3] = Point(-28.016, 229.608);
+ new ShapeRef(router, poly66, 66);
+
+ Polygon poly15(4);
+ poly15.ps[0] = Point(691.984, 1031.01);
+ poly15.ps[1] = Point(691.984, 1051.01);
+ poly15.ps[2] = Point(671.984, 1051.01);
+ poly15.ps[3] = Point(671.984, 1031.01);
+ new ShapeRef(router, poly15, 15);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(868.746, 419.608);
+ poly4.ps[1] = Point(868.746, 439.608);
+ poly4.ps[2] = Point(848.746, 439.608);
+ poly4.ps[3] = Point(848.746, 419.608);
+ new ShapeRef(router, poly4, 4);
+
+ Polygon poly22(4);
+ poly22.ps[0] = Point(803.984, 725.608);
+ poly22.ps[1] = Point(803.984, 745.608);
+ poly22.ps[2] = Point(783.984, 745.608);
+ poly22.ps[3] = Point(783.984, 725.608);
+ new ShapeRef(router, poly22, 22);
+
+ Polygon poly119(4);
+ poly119.ps[0] = Point(951.984, 879.008);
+ poly119.ps[1] = Point(951.984, 919.008);
+ poly119.ps[2] = Point(895.984, 919.008);
+ poly119.ps[3] = Point(895.984, 879.008);
+ new ShapeRef(router, poly119, 119);
+
+ Polygon poly130(4);
+ poly130.ps[0] = Point(512.984, 715.608);
+ poly130.ps[1] = Point(512.984, 755.608);
+ poly130.ps[2] = Point(456.984, 755.608);
+ poly130.ps[3] = Point(456.984, 715.608);
+ new ShapeRef(router, poly130, 130);
+
+ Polygon poly138(4);
+ poly138.ps[0] = Point(407.084, 299.608);
+ poly138.ps[1] = Point(407.084, 339.608);
+ poly138.ps[2] = Point(351.084, 339.608);
+ poly138.ps[3] = Point(351.084, 299.608);
+ new ShapeRef(router, poly138, 138);
+
+ Polygon poly97(4);
+ poly97.ps[0] = Point(460.584, -334.392);
+ poly97.ps[1] = Point(460.584, -294.392);
+ poly97.ps[2] = Point(420.584, -294.392);
+ poly97.ps[3] = Point(420.584, -334.392);
+ new ShapeRef(router, poly97, 97);
+
+ Polygon poly156(4);
+ poly156.ps[0] = Point(190.984, 624.465);
+ poly156.ps[1] = Point(190.984, 664.465);
+ poly156.ps[2] = Point(134.984, 664.465);
+ poly156.ps[3] = Point(134.984, 624.465);
+ new ShapeRef(router, poly156, 156);
+
+ Polygon poly11(4);
+ poly11.ps[0] = Point(1075.98, 749.608);
+ poly11.ps[1] = Point(1075.98, 769.608);
+ poly11.ps[2] = Point(1055.98, 769.608);
+ poly11.ps[3] = Point(1055.98, 749.608);
+ new ShapeRef(router, poly11, 11);
+
+ Polygon poly152(4);
+ poly152.ps[0] = Point(13.984, 28.6079);
+ poly152.ps[1] = Point(13.984, 68.6079);
+ poly152.ps[2] = Point(-42.016, 68.6079);
+ poly152.ps[3] = Point(-42.016, 28.6079);
+ new ShapeRef(router, poly152, 152);
+
+ Polygon poly81(4);
+ poly81.ps[0] = Point(122.984, 817.608);
+ poly81.ps[1] = Point(122.984, 857.608);
+ poly81.ps[2] = Point(82.984, 857.608);
+ poly81.ps[3] = Point(82.984, 817.608);
+ new ShapeRef(router, poly81, 81);
+
+ Polygon poly109(4);
+ poly109.ps[0] = Point(372.984, -313.392);
+ poly109.ps[1] = Point(372.984, -293.392);
+ poly109.ps[2] = Point(352.984, -293.392);
+ poly109.ps[3] = Point(352.984, -313.392);
+ new ShapeRef(router, poly109, 109);
+
+ Polygon poly101(4);
+ poly101.ps[0] = Point(-81.016, -179.392);
+ poly101.ps[1] = Point(-81.016, -139.392);
+ poly101.ps[2] = Point(-121.016, -139.392);
+ poly101.ps[3] = Point(-121.016, -179.392);
+ new ShapeRef(router, poly101, 101);
+
+ Polygon poly64(4);
+ poly64.ps[0] = Point(307.984, 112.608);
+ poly64.ps[1] = Point(307.984, 152.608);
+ poly64.ps[2] = Point(267.984, 152.608);
+ poly64.ps[3] = Point(267.984, 112.608);
+ new ShapeRef(router, poly64, 64);
+
+ Polygon poly92(4);
+ poly92.ps[0] = Point(813.984, 929.008);
+ poly92.ps[1] = Point(813.984, 969.008);
+ poly92.ps[2] = Point(773.984, 969.008);
+ poly92.ps[3] = Point(773.984, 929.008);
+ new ShapeRef(router, poly92, 92);
+
+ Polygon poly27(4);
+ poly27.ps[0] = Point(542.984, 680.465);
+ poly27.ps[1] = Point(542.984, 700.465);
+ poly27.ps[2] = Point(522.984, 700.465);
+ poly27.ps[3] = Point(522.984, 680.465);
+ new ShapeRef(router, poly27, 27);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(438.984, 1273.01);
+ poly9.ps[1] = Point(438.984, 1293.01);
+ poly9.ps[2] = Point(418.984, 1293.01);
+ poly9.ps[3] = Point(418.984, 1273.01);
+ new ShapeRef(router, poly9, 9);
+
+ Polygon poly171(4);
+ poly171.ps[0] = Point(885.984, 1187.01);
+ poly171.ps[1] = Point(885.984, 1227.01);
+ poly171.ps[2] = Point(825.984, 1227.01);
+ poly171.ps[3] = Point(825.984, 1187.01);
+ new ShapeRef(router, poly171, 171);
+
+ Polygon poly26(4);
+ poly26.ps[0] = Point(852, 549);
+ poly26.ps[1] = Point(852, 589);
+ poly26.ps[2] = Point(796, 589);
+ poly26.ps[3] = Point(796, 549);
+ new ShapeRef(router, poly26, 26);
+
+ Polygon poly95(4);
+ poly95.ps[0] = Point(818.746, 315.608);
+ poly95.ps[1] = Point(818.746, 355.608);
+ poly95.ps[2] = Point(778.746, 355.608);
+ poly95.ps[3] = Point(778.746, 315.608);
+ new ShapeRef(router, poly95, 95);
+
+ Polygon poly72(4);
+ poly72.ps[0] = Point(813.984, 663.608);
+ poly72.ps[1] = Point(813.984, 703.608);
+ poly72.ps[2] = Point(773.984, 703.608);
+ poly72.ps[3] = Point(773.984, 663.608);
+ new ShapeRef(router, poly72, 72);
+
+ Polygon poly16(4);
+ poly16.ps[0] = Point(561.984, 981.008);
+ poly16.ps[1] = Point(561.984, 1001.01);
+ poly16.ps[2] = Point(541.984, 1001.01);
+ poly16.ps[3] = Point(541.984, 981.008);
+ new ShapeRef(router, poly16, 16);
+
+ Polygon poly35(4);
+ poly35.ps[0] = Point(521.534, 122.608);
+ poly35.ps[1] = Point(521.534, 142.608);
+ poly35.ps[2] = Point(501.534, 142.608);
+ poly35.ps[3] = Point(501.534, 122.608);
+ new ShapeRef(router, poly35, 35);
+
+ Polygon poly34(4);
+ poly34.ps[0] = Point(1.98401, 197.608);
+ poly34.ps[1] = Point(1.98401, 217.608);
+ poly34.ps[2] = Point(-18.016, 217.608);
+ poly34.ps[3] = Point(-18.016, 197.608);
+ new ShapeRef(router, poly34, 34);
+
+ Polygon poly86(4);
+ poly86.ps[0] = Point(571.984, 1031.01);
+ poly86.ps[1] = Point(571.984, 1071.01);
+ poly86.ps[2] = Point(531.984, 1071.01);
+ poly86.ps[3] = Point(531.984, 1031.01);
+ new ShapeRef(router, poly86, 86);
+
+ Polygon poly140(4);
+ poly140.ps[0] = Point(539.534, 62.6079);
+ poly140.ps[1] = Point(539.534, 102.608);
+ poly140.ps[2] = Point(483.534, 102.608);
+ poly140.ps[3] = Point(483.534, 62.6079);
+ new ShapeRef(router, poly140, 140);
+
+ Polygon poly69(4);
+ poly69.ps[0] = Point(591.534, 164.608);
+ poly69.ps[1] = Point(591.534, 204.608);
+ poly69.ps[2] = Point(551.534, 204.608);
+ poly69.ps[3] = Point(551.534, 164.608);
+ new ShapeRef(router, poly69, 69);
+
+ Polygon poly48(4);
+ poly48.ps[0] = Point(322.984, 477.608);
+ poly48.ps[1] = Point(322.984, 651.608);
+ poly48.ps[2] = Point(202.984, 651.608);
+ poly48.ps[3] = Point(202.984, 477.608);
+ new ShapeRef(router, poly48, 48);
+
+ Polygon poly100(4);
+ poly100.ps[0] = Point(307.984, -179.392);
+ poly100.ps[1] = Point(307.984, -139.392);
+ poly100.ps[2] = Point(267.984, -139.392);
+ poly100.ps[3] = Point(267.984, -179.392);
+ new ShapeRef(router, poly100, 100);
+
+ Polygon poly54(4);
+ poly54.ps[0] = Point(372.984, -405.392);
+ poly54.ps[1] = Point(372.984, -385.392);
+ poly54.ps[2] = Point(352.984, -385.392);
+ poly54.ps[3] = Point(352.984, -405.392);
+ new ShapeRef(router, poly54, 54);
+
+ Polygon poly113(4);
+ poly113.ps[0] = Point(1024.98, 506.108);
+ poly113.ps[1] = Point(1024.98, 546.108);
+ poly113.ps[2] = Point(968.984, 546.108);
+ poly113.ps[3] = Point(968.984, 506.108);
+ new ShapeRef(router, poly113, 113);
+
+ Polygon poly155(4);
+ poly155.ps[0] = Point(390.984, -373.392);
+ poly155.ps[1] = Point(390.984, -333.392);
+ poly155.ps[2] = Point(334.984, -333.392);
+ poly155.ps[3] = Point(334.984, -373.392);
+ new ShapeRef(router, poly155, 155);
+
+ Polygon poly87(4);
+ poly87.ps[0] = Point(376.184, 939.758);
+ poly87.ps[1] = Point(376.184, 979.758);
+ poly87.ps[2] = Point(336.184, 979.758);
+ poly87.ps[3] = Point(336.184, 939.758);
+ new ShapeRef(router, poly87, 87);
+
+ Polygon poly63(4);
+ poly63.ps[0] = Point(460.584, 112.608);
+ poly63.ps[1] = Point(460.584, 152.608);
+ poly63.ps[2] = Point(420.584, 152.608);
+ poly63.ps[3] = Point(420.584, 112.608);
+ new ShapeRef(router, poly63, 63);
+
+ Polygon poly129(4);
+ poly129.ps[0] = Point(771.984, 715.608);
+ poly129.ps[1] = Point(771.984, 755.608);
+ poly129.ps[2] = Point(715.984, 755.608);
+ poly129.ps[3] = Point(715.984, 715.608);
+ new ShapeRef(router, poly129, 129);
+
+ Polygon poly76(4);
+ poly76.ps[0] = Point(320.984, 663.608);
+ poly76.ps[1] = Point(320.984, 703.608);
+ poly76.ps[2] = Point(280.984, 703.608);
+ poly76.ps[3] = Point(280.984, 663.608);
+ new ShapeRef(router, poly76, 76);
+
+ Polygon poly93(4);
+ poly93.ps[0] = Point(1085.98, 663.608);
+ poly93.ps[1] = Point(1085.98, 703.608);
+ poly93.ps[2] = Point(1045.98, 703.608);
+ poly93.ps[3] = Point(1045.98, 663.608);
+ new ShapeRef(router, poly93, 93);
+
+ Polygon poly157(4);
+ poly157.ps[0] = Point(213, 425.608);
+ poly157.ps[1] = Point(213, 465.608);
+ poly157.ps[2] = Point(153, 465.608);
+ poly157.ps[3] = Point(153, 425.608);
+ new ShapeRef(router, poly157, 157);
+
+ Polygon poly147(4);
+ poly147.ps[0] = Point(530.584, -281.392);
+ poly147.ps[1] = Point(530.584, -241.392);
+ poly147.ps[2] = Point(474.584, -241.392);
+ poly147.ps[3] = Point(474.584, -281.392);
+ new ShapeRef(router, poly147, 147);
+
+ Polygon poly80(4);
+ poly80.ps[0] = Point(122.984, 933.758);
+ poly80.ps[1] = Point(122.984, 973.758);
+ poly80.ps[2] = Point(82.984, 973.758);
+ poly80.ps[3] = Point(82.984, 933.758);
+ new ShapeRef(router, poly80, 80);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(326.584, 1263.01);
+ poly7.ps[1] = Point(326.584, 1303.01);
+ poly7.ps[2] = Point(286.584, 1303.01);
+ poly7.ps[3] = Point(286.584, 1263.01);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(460.584, 216.608);
+ poly5.ps[1] = Point(460.584, 256.608);
+ poly5.ps[2] = Point(420.584, 256.608);
+ poly5.ps[3] = Point(420.584, 216.608);
+ new ShapeRef(router, poly5, 5);
+
+ Polygon poly148(4);
+ poly148.ps[0] = Point(530.584, -434.392);
+ poly148.ps[1] = Point(530.584, -394.392);
+ poly148.ps[2] = Point(474.584, -394.392);
+ poly148.ps[3] = Point(474.584, -434.392);
+ new ShapeRef(router, poly148, 148);
+
+ Polygon poly166(4);
+ poly166.ps[0] = Point(316.984, 1158.01);
+ poly166.ps[1] = Point(316.984, 1218.01);
+ poly166.ps[2] = Point(276.984, 1218.01);
+ poly166.ps[3] = Point(276.984, 1158.01);
+ new ShapeRef(router, poly166, 166);
+
+ Polygon poly139(4);
+ poly139.ps[0] = Point(81.984, 187.608);
+ poly139.ps[1] = Point(81.984, 227.608);
+ poly139.ps[2] = Point(25.984, 227.608);
+ poly139.ps[3] = Point(25.984, 187.608);
+ new ShapeRef(router, poly139, 139);
+
+ Polygon poly91(4);
+ poly91.ps[0] = Point(701.984, 827.008);
+ poly91.ps[1] = Point(701.984, 867.008);
+ poly91.ps[2] = Point(661.984, 867.008);
+ poly91.ps[3] = Point(661.984, 827.008);
+ new ShapeRef(router, poly91, 91);
+
+ Polygon poly122(4);
+ poly122.ps[0] = Point(709.984, 971.008);
+ poly122.ps[1] = Point(709.984, 1011.01);
+ poly122.ps[2] = Point(653.984, 1011.01);
+ poly122.ps[3] = Point(653.984, 971.008);
+ new ShapeRef(router, poly122, 122);
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(521.534, 226.608);
+ poly6.ps[1] = Point(521.534, 246.608);
+ poly6.ps[2] = Point(501.534, 246.608);
+ poly6.ps[3] = Point(501.534, 226.608);
+ new ShapeRef(router, poly6, 6);
+
+ Polygon poly18(4);
+ poly18.ps[0] = Point(517, 916.608);
+ poly18.ps[1] = Point(517, 956.608);
+ poly18.ps[2] = Point(461, 956.608);
+ poly18.ps[3] = Point(461, 916.608);
+ new ShapeRef(router, poly18, 18);
+
+ Polygon poly39(4);
+ poly39.ps[0] = Point(372.984, -13.3921);
+ poly39.ps[1] = Point(372.984, 6.60786);
+ poly39.ps[2] = Point(352.984, 6.60786);
+ poly39.ps[3] = Point(352.984, -13.3921);
+ new ShapeRef(router, poly39, 39);
+
+ Polygon poly25(4);
+ poly25.ps[0] = Point(310.984, 725.608);
+ poly25.ps[1] = Point(310.984, 745.608);
+ poly25.ps[2] = Point(290.984, 745.608);
+ poly25.ps[3] = Point(290.984, 725.608);
+ new ShapeRef(router, poly25, 25);
+
+ Polygon poly56(4);
+ poly56.ps[0] = Point(79.984, -169.392);
+ poly56.ps[1] = Point(79.984, -149.392);
+ poly56.ps[2] = Point(59.984, -149.392);
+ poly56.ps[3] = Point(59.984, -169.392);
+ new ShapeRef(router, poly56, 56);
+
+ Polygon poly21(4);
+ poly21.ps[0] = Point(432.984, 874.608);
+ poly21.ps[1] = Point(432.984, 894.608);
+ poly21.ps[2] = Point(412.984, 894.608);
+ poly21.ps[3] = Point(412.984, 874.608);
+ new ShapeRef(router, poly21, 21);
+
+ Polygon poly47(4);
+ poly47.ps[0] = Point(1291.98, 128.608);
+ poly47.ps[1] = Point(1291.98, 303.608);
+ poly47.ps[2] = Point(977.984, 303.608);
+ poly47.ps[3] = Point(977.984, 128.608);
+ new ShapeRef(router, poly47, 47);
+
+ Polygon poly62(4);
+ poly62.ps[0] = Point(460.584, -23.3921);
+ poly62.ps[1] = Point(460.584, 16.6079);
+ poly62.ps[2] = Point(420.584, 16.6079);
+ poly62.ps[3] = Point(420.584, -23.3921);
+ new ShapeRef(router, poly62, 62);
+
+ Polygon poly74(4);
+ poly74.ps[0] = Point(11.984, 425.608);
+ poly74.ps[1] = Point(11.984, 465.608);
+ poly74.ps[2] = Point(-28.016, 465.608);
+ poly74.ps[3] = Point(-28.016, 425.608);
+ new ShapeRef(router, poly74, 74);
+
+ Polygon poly89(4);
+ poly89.ps[0] = Point(979.984, 663.608);
+ poly89.ps[1] = Point(979.984, 703.608);
+ poly89.ps[2] = Point(939.984, 703.608);
+ poly89.ps[3] = Point(939.984, 663.608);
+ new ShapeRef(router, poly89, 89);
+
+ Polygon poly143(4);
+ poly143.ps[0] = Point(81.984, 70.6079);
+ poly143.ps[1] = Point(81.984, 110.608);
+ poly143.ps[2] = Point(25.984, 110.608);
+ poly143.ps[3] = Point(25.984, 70.6079);
+ new ShapeRef(router, poly143, 143);
+
+ Polygon poly135(4);
+ poly135.ps[0] = Point(407.084, 383.608);
+ poly135.ps[1] = Point(407.084, 423.608);
+ poly135.ps[2] = Point(351.084, 423.608);
+ poly135.ps[3] = Point(351.084, 383.608);
+ new ShapeRef(router, poly135, 135);
+
+ Polygon poly46(4);
+ poly46.ps[0] = Point(285.084, 281.608);
+ poly46.ps[1] = Point(285.084, 341.608);
+ poly46.ps[2] = Point(49.084, 341.608);
+ poly46.ps[3] = Point(49.084, 281.608);
+ new ShapeRef(router, poly46, 46);
+
+ Polygon poly144(4);
+ poly144.ps[0] = Point(390.984, -73.3921);
+ poly144.ps[1] = Point(390.984, -33.3921);
+ poly144.ps[2] = Point(334.984, -33.3921);
+ poly144.ps[3] = Point(334.984, -73.3921);
+ new ShapeRef(router, poly144, 144);
+
+ Polygon poly128(4);
+ poly128.ps[0] = Point(883.984, 715.608);
+ poly128.ps[1] = Point(883.984, 755.608);
+ poly128.ps[2] = Point(827.984, 755.608);
+ poly128.ps[3] = Point(827.984, 715.608);
+ new ShapeRef(router, poly128, 128);
+
+ Polygon poly111(4);
+ poly111.ps[0] = Point(172.984, 684.465);
+ poly111.ps[1] = Point(172.984, 704.465);
+ poly111.ps[2] = Point(152.984, 704.465);
+ poly111.ps[3] = Point(152.984, 684.465);
+ new ShapeRef(router, poly111, 111);
+
+ Polygon poly45(4);
+ poly45.ps[0] = Point(388.984, 1086.01);
+ poly45.ps[1] = Point(388.984, 1251.01);
+ poly45.ps[2] = Point(73.984, 1251.01);
+ poly45.ps[3] = Point(73.984, 1086.01);
+ new ShapeRef(router, poly45, 45);
+
+ Polygon poly172(4);
+ poly172.ps[0] = Point(532.584, -117.392);
+ poly172.ps[1] = Point(532.584, -77.3921);
+ poly172.ps[2] = Point(472.584, -77.3921);
+ poly172.ps[3] = Point(472.584, -117.392);
+ new ShapeRef(router, poly172, 172);
+
+ Polygon poly83(4);
+ poly83.ps[0] = Point(813.984, 1187.01);
+ poly83.ps[1] = Point(813.984, 1227.01);
+ poly83.ps[2] = Point(773.984, 1227.01);
+ poly83.ps[3] = Point(773.984, 1187.01);
+ new ShapeRef(router, poly83, 83);
+
+ Polygon poly58(4);
+ poly58.ps[0] = Point(749.984, 510.608);
+ poly58.ps[1] = Point(749.984, 530.608);
+ poly58.ps[2] = Point(729.984, 530.608);
+ poly58.ps[3] = Point(729.984, 510.608);
+ new ShapeRef(router, poly58, 58);
+
+ Polygon poly106(4);
+ poly106.ps[0] = Point(502.984, 448.608);
+ poly106.ps[1] = Point(502.984, 488.608);
+ poly106.ps[2] = Point(462.984, 488.608);
+ poly106.ps[3] = Point(462.984, 448.608);
+ new ShapeRef(router, poly106, 106);
+
+ Polygon poly41(4);
+ poly41.ps[0] = Point(285.084, 405.608);
+ poly41.ps[1] = Point(285.084, 465.608);
+ poly41.ps[2] = Point(52.084, 465.608);
+ poly41.ps[3] = Point(52.084, 405.608);
+ new ShapeRef(router, poly41, 41);
+
+ Polygon poly132(4);
+ poly132.ps[0] = Point(560.984, 620.465);
+ poly132.ps[1] = Point(560.984, 660.465);
+ poly132.ps[2] = Point(504.984, 660.465);
+ poly132.ps[3] = Point(504.984, 620.465);
+ new ShapeRef(router, poly132, 132);
+
+ Polygon poly127(4);
+ poly127.ps[0] = Point(512.984, 864.608);
+ poly127.ps[1] = Point(512.984, 904.608);
+ poly127.ps[2] = Point(456.984, 904.608);
+ poly127.ps[3] = Point(456.984, 864.608);
+ new ShapeRef(router, poly127, 127);
+
+ Polygon poly124(4);
+ poly124.ps[0] = Point(709.984, 879.008);
+ poly124.ps[1] = Point(709.984, 919.008);
+ poly124.ps[2] = Point(653.984, 919.008);
+ poly124.ps[3] = Point(653.984, 879.008);
+ new ShapeRef(router, poly124, 124);
+
+ Polygon poly168(4);
+ poly168.ps[0] = Point(1037.98, 263.5);
+ poly168.ps[1] = Point(1037.98, 303.5);
+ poly168.ps[2] = Point(977.984, 303.5);
+ poly168.ps[3] = Point(977.984, 263.5);
+ new ShapeRef(router, poly168, 168);
+
+ Polygon poly85(4);
+ poly85.ps[0] = Point(442.984, 817.608);
+ poly85.ps[1] = Point(442.984, 857.608);
+ poly85.ps[2] = Point(402.984, 857.608);
+ poly85.ps[3] = Point(402.984, 817.608);
+ new ShapeRef(router, poly85, 85);
+
+ Polygon poly149(4);
+ poly149.ps[0] = Point(390.984, -465.392);
+ poly149.ps[1] = Point(390.984, -425.392);
+ poly149.ps[2] = Point(334.984, -425.392);
+ poly149.ps[3] = Point(334.984, -465.392);
+ new ShapeRef(router, poly149, 149);
+
+ Polygon poly79(4);
+ poly79.ps[0] = Point(122.984, 1034.01);
+ poly79.ps[1] = Point(122.984, 1074.01);
+ poly79.ps[2] = Point(82.984, 1074.01);
+ poly79.ps[3] = Point(82.984, 1034.01);
+ new ShapeRef(router, poly79, 79);
+
+ Polygon poly133(4);
+ poly133.ps[0] = Point(390.984, 613.608);
+ poly133.ps[1] = Point(390.984, 653.608);
+ poly133.ps[2] = Point(334.984, 653.608);
+ poly133.ps[3] = Point(334.984, 613.608);
+ new ShapeRef(router, poly133, 133);
+
+ Polygon poly14(4);
+ poly14.ps[0] = Point(691.984, 1123.01);
+ poly14.ps[1] = Point(691.984, 1143.01);
+ poly14.ps[2] = Point(671.984, 1143.01);
+ poly14.ps[3] = Point(671.984, 1123.01);
+ new ShapeRef(router, poly14, 14);
+
+ Polygon poly30(4);
+ poly30.ps[0] = Point(327.084, 393.608);
+ poly30.ps[1] = Point(327.084, 413.608);
+ poly30.ps[2] = Point(307.084, 413.608);
+ poly30.ps[3] = Point(307.084, 393.608);
+ new ShapeRef(router, poly30, 30);
+
+ Polygon poly20(4);
+ poly20.ps[0] = Point(492.984, 827.608);
+ poly20.ps[1] = Point(492.984, 847.608);
+ poly20.ps[2] = Point(472.984, 847.608);
+ poly20.ps[3] = Point(472.984, 827.608);
+ new ShapeRef(router, poly20, 20);
+
+ Polygon poly38(4);
+ poly38.ps[0] = Point(1.98401, 80.6079);
+ poly38.ps[1] = Point(1.98401, 100.608);
+ poly38.ps[2] = Point(-18.016, 100.608);
+ poly38.ps[3] = Point(-18.016, 80.6079);
+ new ShapeRef(router, poly38, 38);
+
+ Polygon poly44(4);
+ poly44.ps[0] = Point(408.584, -512.392);
+ poly44.ps[1] = Point(408.584, -477.392);
+ poly44.ps[2] = Point(20.584, -477.392);
+ poly44.ps[3] = Point(20.584, -512.392);
+ new ShapeRef(router, poly44, 44);
+
+ Polygon poly94(4);
+ poly94.ps[0] = Point(585.984, 817.608);
+ poly94.ps[1] = Point(585.984, 857.608);
+ poly94.ps[2] = Point(545.984, 857.608);
+ poly94.ps[3] = Point(545.984, 817.608);
+ new ShapeRef(router, poly94, 94);
+
+ Polygon poly32(4);
+ poly32.ps[0] = Point(390.584, 226.608);
+ poly32.ps[1] = Point(390.584, 246.608);
+ poly32.ps[2] = Point(370.584, 246.608);
+ poly32.ps[3] = Point(370.584, 226.608);
+ new ShapeRef(router, poly32, 32);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(576.484, 1263.01);
+ poly8.ps[1] = Point(576.484, 1303.01);
+ poly8.ps[2] = Point(536.484, 1303.01);
+ poly8.ps[3] = Point(536.484, 1263.01);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly59(4);
+ poly59.ps[0] = Point(552.984, 510.608);
+ poly59.ps[1] = Point(552.984, 530.608);
+ poly59.ps[2] = Point(532.984, 530.608);
+ poly59.ps[3] = Point(532.984, 510.608);
+ new ShapeRef(router, poly59, 59);
+
+ Polygon poly102(4);
+ poly102.ps[0] = Point(1047.98, 315.608);
+ poly102.ps[1] = Point(1047.98, 355.608);
+ poly102.ps[2] = Point(1007.98, 355.608);
+ poly102.ps[3] = Point(1007.98, 315.608);
+ new ShapeRef(router, poly102, 102);
+
+ Polygon poly67(4);
+ poly67.ps[0] = Point(818.746, 164.608);
+ poly67.ps[1] = Point(818.746, 204.608);
+ poly67.ps[2] = Point(778.746, 204.608);
+ poly67.ps[3] = Point(778.746, 164.608);
+ new ShapeRef(router, poly67, 67);
+
+ Polygon poly77(4);
+ poly77.ps[0] = Point(429.484, 1031.01);
+ poly77.ps[1] = Point(429.484, 1071.01);
+ poly77.ps[2] = Point(389.484, 1071.01);
+ poly77.ps[3] = Point(389.484, 1031.01);
+ new ShapeRef(router, poly77, 77);
+
+ Polygon poly163(4);
+ poly163.ps[0] = Point(886.5, 56.6079);
+ poly163.ps[1] = Point(886.5, 116.608);
+ poly163.ps[2] = Point(846.5, 116.608);
+ poly163.ps[3] = Point(846.5, 56.6079);
+ new ShapeRef(router, poly163, 163);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(954.984, 442.608);
+ poly2.ps[1] = Point(954.984, 482.608);
+ poly2.ps[2] = Point(914.984, 482.608);
+ poly2.ps[3] = Point(914.984, 442.608);
+ new ShapeRef(router, poly2, 2);
+
+ Polygon poly73(4);
+ poly73.ps[0] = Point(122.984, 663.608);
+ poly73.ps[1] = Point(122.984, 703.608);
+ poly73.ps[2] = Point(82.984, 703.608);
+ poly73.ps[3] = Point(82.984, 663.608);
+ new ShapeRef(router, poly73, 73);
+
+ Polygon poly65(4);
+ poly65.ps[0] = Point(307.984, -23.3921);
+ poly65.ps[1] = Point(307.984, 16.6079);
+ poly65.ps[2] = Point(267.984, 16.6079);
+ poly65.ps[3] = Point(267.984, -23.3921);
+ new ShapeRef(router, poly65, 65);
+
+ Polygon poly71(4);
+ poly71.ps[0] = Point(337.084, 341.608);
+ poly71.ps[1] = Point(337.084, 381.608);
+ poly71.ps[2] = Point(297.084, 381.608);
+ poly71.ps[3] = Point(297.084, 341.608);
+ new ShapeRef(router, poly71, 71);
+
+ Polygon poly110(4);
+ poly110.ps[0] = Point(786.584, -137.392);
+ poly110.ps[1] = Point(786.584, -77.3921);
+ poly110.ps[2] = Point(472.584, -77.3921);
+ poly110.ps[3] = Point(472.584, -137.392);
+ new ShapeRef(router, poly110, 110);
+
+ Polygon poly84(4);
+ poly84.ps[0] = Point(571.984, 929.008);
+ poly84.ps[1] = Point(571.984, 969.008);
+ poly84.ps[2] = Point(531.984, 969.008);
+ poly84.ps[3] = Point(531.984, 929.008);
+ new ShapeRef(router, poly84, 84);
+
+ Polygon poly125(4);
+ poly125.ps[0] = Point(883.984, 859.608);
+ poly125.ps[1] = Point(883.984, 899.608);
+ poly125.ps[2] = Point(827.984, 899.608);
+ poly125.ps[3] = Point(827.984, 859.608);
+ new ShapeRef(router, poly125, 125);
+
+ Polygon poly96(4);
+ poly96.ps[0] = Point(460.584, -476.392);
+ poly96.ps[1] = Point(460.584, -436.392);
+ poly96.ps[2] = Point(420.584, -436.392);
+ poly96.ps[3] = Point(420.584, -476.392);
+ new ShapeRef(router, poly96, 96);
+
+ Polygon poly167(4);
+ poly167.ps[0] = Point(285.084, 301.608);
+ poly167.ps[1] = Point(285.084, 341.608);
+ poly167.ps[2] = Point(225.084, 341.608);
+ poly167.ps[3] = Point(225.084, 301.608);
+ new ShapeRef(router, poly167, 167);
+
+ Polygon poly43(4);
+ poly43.ps[0] = Point(1007, -57.3921);
+ poly43.ps[1] = Point(1007, 116.608);
+ poly43.ps[2] = Point(725, 116.608);
+ poly43.ps[3] = Point(725, -57.3921);
+ new ShapeRef(router, poly43, 43);
+
+ Polygon poly55(4);
+ poly55.ps[0] = Point(297.984, -271.392);
+ poly55.ps[1] = Point(297.984, -251.392);
+ poly55.ps[2] = Point(277.984, -251.392);
+ poly55.ps[3] = Point(277.984, -271.392);
+ new ShapeRef(router, poly55, 55);
+
+ Polygon poly98(4);
+ poly98.ps[0] = Point(460.584, -179.392);
+ poly98.ps[1] = Point(460.584, -139.392);
+ poly98.ps[2] = Point(420.584, -139.392);
+ poly98.ps[3] = Point(420.584, -179.392);
+ new ShapeRef(router, poly98, 98);
+
+ Polygon poly42(4);
+ poly42.ps[0] = Point(699.984, 314.608);
+ poly42.ps[1] = Point(699.984, 488.608);
+ poly42.ps[2] = Point(582.984, 488.608);
+ poly42.ps[3] = Point(582.984, 314.608);
+ new ShapeRef(router, poly42, 42);
+
+ Polygon poly105(4);
+ poly105.ps[0] = Point(622.984, 500.608);
+ poly105.ps[1] = Point(622.984, 540.608);
+ poly105.ps[2] = Point(582.984, 540.608);
+ poly105.ps[3] = Point(582.984, 500.608);
+ new ShapeRef(router, poly105, 105);
+
+ Polygon poly1(4);
+ poly1.ps[0] = Point(521.534, -169.392);
+ poly1.ps[1] = Point(521.534, -149.392);
+ poly1.ps[2] = Point(501.534, -149.392);
+ poly1.ps[3] = Point(501.534, -169.392);
+ new ShapeRef(router, poly1, 1);
+
+ Polygon poly165(4);
+ poly165.ps[0] = Point(316.984, 1086.01);
+ poly165.ps[1] = Point(316.984, 1146.01);
+ poly165.ps[2] = Point(276.984, 1146.01);
+ poly165.ps[3] = Point(276.984, 1086.01);
+ new ShapeRef(router, poly165, 165);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(566.484, 1213.01);
+ poly10.ps[1] = Point(566.484, 1233.01);
+ poly10.ps[2] = Point(546.484, 1233.01);
+ poly10.ps[3] = Point(546.484, 1213.01);
+ new ShapeRef(router, poly10, 10);
+
+ Polygon poly24(4);
+ poly24.ps[0] = Point(432.984, 725.608);
+ poly24.ps[1] = Point(432.984, 745.608);
+ poly24.ps[2] = Point(412.984, 745.608);
+ poly24.ps[3] = Point(412.984, 725.608);
+ new ShapeRef(router, poly24, 24);
+
+ Polygon poly108(4);
+ poly108.ps[0] = Point(11.984, 112.608);
+ poly108.ps[1] = Point(11.984, 152.608);
+ poly108.ps[2] = Point(-28.016, 152.608);
+ poly108.ps[3] = Point(-28.016, 112.608);
+ new ShapeRef(router, poly108, 108);
+
+ Polygon poly123(4);
+ poly123.ps[0] = Point(641.984, 971.008);
+ poly123.ps[1] = Point(641.984, 1011.01);
+ poly123.ps[2] = Point(585.984, 1011.01);
+ poly123.ps[3] = Point(585.984, 971.008);
+ new ShapeRef(router, poly123, 123);
+
+ ConnRef *connRef279 = new ConnRef(router, 279);
+ ConnEnd srcPt279(Point(743.984, 735.608), 15);
+ connRef279->setSourceEndpoint(srcPt279);
+ ConnEnd dstPt279(Point(681.984, 735.608), 15);
+ connRef279->setDestEndpoint(dstPt279);
+ connRef279->setRoutingType((ConnType)2);
+
+ ConnRef *connRef280 = new ConnRef(router, 280);
+ ConnEnd srcPt280(Point(484.984, 735.608), 15);
+ connRef280->setSourceEndpoint(srcPt280);
+ ConnEnd dstPt280(Point(422.984, 735.608), 15);
+ connRef280->setDestEndpoint(dstPt280);
+ connRef280->setRoutingType((ConnType)2);
+
+ ConnRef *connRef327 = new ConnRef(router, 327);
+ ConnEnd srcPt327(Point(1065.98, 683.608), 15);
+ connRef327->setSourceEndpoint(srcPt327);
+ ConnEnd dstPt327(Point(1069.98, 298.608), 2);
+ connRef327->setDestEndpoint(dstPt327);
+ connRef327->setRoutingType((ConnType)2);
+
+ ConnRef *connRef330 = new ConnRef(router, 330);
+ ConnEnd srcPt330(Point(440.584, -3.39214), 15);
+ connRef330->setSourceEndpoint(srcPt330);
+ ConnEnd dstPt330(Point(477.584, -97.3921), 4);
+ connRef330->setDestEndpoint(dstPt330);
+ connRef330->setRoutingType((ConnType)2);
+
+ ConnRef *connRef176 = new ConnRef(router, 176);
+ ConnEnd srcPt176(Point(934.984, 536.108), 15);
+ connRef176->setSourceEndpoint(srcPt176);
+ ConnEnd dstPt176(Point(793.984, 837.608), 15);
+ connRef176->setDestEndpoint(dstPt176);
+ connRef176->setRoutingType((ConnType)2);
+
+ ConnRef *connRef177 = new ConnRef(router, 177);
+ ConnEnd srcPt177(Point(440.584, 236.608), 15);
+ connRef177->setSourceEndpoint(srcPt177);
+ ConnEnd dstPt177(Point(501.534, 236.608), 15);
+ connRef177->setDestEndpoint(dstPt177);
+ connRef177->setRoutingType((ConnType)2);
+
+ ConnRef *connRef312 = new ConnRef(router, 312);
+ ConnEnd srcPt312(Point(440.584, -159.392), 15);
+ connRef312->setSourceEndpoint(srcPt312);
+ ConnEnd dstPt312(Point(440.584, -55.3921), 15);
+ connRef312->setDestEndpoint(dstPt312);
+ connRef312->setRoutingType((ConnType)2);
+
+ ConnRef *connRef306 = new ConnRef(router, 306);
+ ConnEnd srcPt306(Point(162.984, 644.465), 15);
+ connRef306->setSourceEndpoint(srcPt306);
+ ConnEnd dstPt306(Point(162.984, 694.465), 15);
+ connRef306->setDestEndpoint(dstPt306);
+ connRef306->setRoutingType((ConnType)2);
+
+ ConnRef *connRef198 = new ConnRef(router, 198);
+ ConnEnd srcPt198(Point(422.984, 894.608), 15);
+ connRef198->setSourceEndpoint(srcPt198);
+ ConnEnd dstPt198(Point(551.984, 949.008), 15);
+ connRef198->setDestEndpoint(dstPt198);
+ connRef198->setRoutingType((ConnType)2);
+
+ ConnRef *connRef199 = new ConnRef(router, 199);
+ ConnEnd srcPt199(Point(422.984, 874.608), 15);
+ connRef199->setSourceEndpoint(srcPt199);
+ ConnEnd dstPt199(Point(422.984, 837.608), 15);
+ connRef199->setDestEndpoint(dstPt199);
+ connRef199->setRoutingType((ConnType)2);
+
+ ConnRef *connRef282 = new ConnRef(router, 282);
+ ConnEnd srcPt282(Point(532.984, 640.465), 15);
+ connRef282->setSourceEndpoint(srcPt282);
+ ConnEnd dstPt282(Point(532.984, 690.465), 15);
+ connRef282->setDestEndpoint(dstPt282);
+ connRef282->setRoutingType((ConnType)2);
+
+ ConnRef *connRef283 = new ConnRef(router, 283);
+ ConnEnd srcPt283(Point(362.984, 633.608), 15);
+ connRef283->setSourceEndpoint(srcPt283);
+ ConnEnd dstPt283(Point(362.984, 683.608), 15);
+ connRef283->setDestEndpoint(dstPt283);
+ connRef283->setRoutingType((ConnType)2);
+
+ ConnRef *connRef186 = new ConnRef(router, 186);
+ ConnEnd srcPt186(Point(913.984, 949.008), 15);
+ connRef186->setSourceEndpoint(srcPt186);
+ ConnEnd dstPt186(Point(793.984, 949.008), 15);
+ connRef186->setDestEndpoint(dstPt186);
+ connRef186->setRoutingType((ConnType)2);
+
+ ConnRef *connRef187 = new ConnRef(router, 187);
+ ConnEnd srcPt187(Point(753.984, 1145.01), 15);
+ connRef187->setSourceEndpoint(srcPt187);
+ ConnEnd dstPt187(Point(793.984, 1051.01), 15);
+ connRef187->setDestEndpoint(dstPt187);
+ connRef187->setRoutingType((ConnType)2);
+
+ ConnRef *connRef222 = new ConnRef(router, 222);
+ ConnEnd srcPt222(Point(501.534, 132.608), 15);
+ connRef222->setSourceEndpoint(srcPt222);
+ ConnEnd dstPt222(Point(440.584, 132.608), 15);
+ connRef222->setDestEndpoint(dstPt222);
+ connRef222->setRoutingType((ConnType)2);
+
+ ConnRef *connRef223 = new ConnRef(router, 223);
+ ConnEnd srcPt223(Point(521.534, 132.608), 15);
+ connRef223->setSourceEndpoint(srcPt223);
+ ConnEnd dstPt223(Point(571.534, 184.608), 15);
+ connRef223->setDestEndpoint(dstPt223);
+ connRef223->setRoutingType((ConnType)2);
+
+ ConnRef *connRef284 = new ConnRef(router, 284);
+ ConnEnd srcPt284(Point(860.746, 239.608), 15);
+ connRef284->setSourceEndpoint(srcPt284);
+ ConnEnd dstPt284(Point(798.746, 239.608), 15);
+ connRef284->setDestEndpoint(dstPt284);
+ connRef284->setRoutingType((ConnType)2);
+
+ ConnRef *connRef174 = new ConnRef(router, 174);
+ ConnEnd srcPt174(Point(934.984, 462.608), 15);
+ connRef174->setSourceEndpoint(srcPt174);
+ ConnEnd dstPt174(Point(934.984, 516.108), 15);
+ connRef174->setDestEndpoint(dstPt174);
+ connRef174->setRoutingType((ConnType)2);
+
+ ConnRef *connRef175 = new ConnRef(router, 175);
+ ConnEnd srcPt175(Point(868.746, 429.608), 15);
+ connRef175->setSourceEndpoint(srcPt175);
+ ConnEnd dstPt175(Point(934.984, 462.608), 15);
+ connRef175->setDestEndpoint(dstPt175);
+ connRef175->setRoutingType((ConnType)2);
+
+ ConnRef *connRef188 = new ConnRef(router, 188);
+ ConnEnd srcPt188(Point(753.984, 1165.01), 15);
+ connRef188->setSourceEndpoint(srcPt188);
+ ConnEnd dstPt188(Point(793.984, 1207.01), 15);
+ connRef188->setDestEndpoint(dstPt188);
+ connRef188->setRoutingType((ConnType)2);
+
+ ConnRef *connRef189 = new ConnRef(router, 189);
+ ConnEnd srcPt189(Point(671.984, 1133.01), 15);
+ connRef189->setSourceEndpoint(srcPt189);
+ ConnEnd dstPt189(Point(551.984, 1051.01), 15);
+ connRef189->setDestEndpoint(dstPt189);
+ connRef189->setRoutingType((ConnType)2);
+
+ ConnRef *connRef252 = new ConnRef(router, 252);
+ ConnEnd srcPt252(Point(492.984, 837.608), 15);
+ connRef252->setSourceEndpoint(srcPt252);
+ ConnEnd dstPt252(Point(565.984, 837.608), 15);
+ connRef252->setDestEndpoint(dstPt252);
+ connRef252->setRoutingType((ConnType)2);
+
+ ConnRef *connRef253 = new ConnRef(router, 253);
+ ConnEnd srcPt253(Point(798.746, 335.608), 15);
+ connRef253->setSourceEndpoint(srcPt253);
+ ConnEnd dstPt253(Point(858.746, 327.608), 15);
+ connRef253->setDestEndpoint(dstPt253);
+ connRef253->setRoutingType((ConnType)2);
+
+ ConnRef *connRef315 = new ConnRef(router, 315);
+ ConnEnd srcPt315(Point(-8.01599, 445.608), 15);
+ connRef315->setSourceEndpoint(srcPt315);
+ ConnEnd dstPt315(Point(158, 445.608), 4);
+ connRef315->setDestEndpoint(dstPt315);
+ connRef315->setRoutingType((ConnType)2);
+
+ ConnRef *connRef321 = new ConnRef(router, 321);
+ ConnEnd srcPt321(Point(1065.98, 683.608), 15);
+ connRef321->setSourceEndpoint(srcPt321);
+ ConnEnd dstPt321(Point(866.5, 111.608), 2);
+ connRef321->setDestEndpoint(dstPt321);
+ connRef321->setRoutingType((ConnType)2);
+
+ ConnRef *connRef180 = new ConnRef(router, 180);
+ ConnEnd srcPt180(Point(438.984, 1283.01), 15);
+ connRef180->setSourceEndpoint(srcPt180);
+ ConnEnd dstPt180(Point(556.484, 1283.01), 15);
+ connRef180->setDestEndpoint(dstPt180);
+ connRef180->setRoutingType((ConnType)2);
+
+ ConnRef *connRef181 = new ConnRef(router, 181);
+ ConnEnd srcPt181(Point(556.484, 1233.01), 15);
+ connRef181->setSourceEndpoint(srcPt181);
+ ConnEnd dstPt181(Point(556.484, 1283.01), 15);
+ connRef181->setDestEndpoint(dstPt181);
+ connRef181->setRoutingType((ConnType)2);
+
+ ConnRef *connRef288 = new ConnRef(router, 288);
+ ConnEnd srcPt288(Point(379.084, 319.608), 15);
+ connRef288->setSourceEndpoint(srcPt288);
+ ConnEnd dstPt288(Point(317.084, 319.608), 15);
+ connRef288->setDestEndpoint(dstPt288);
+ connRef288->setRoutingType((ConnType)2);
+
+ ConnRef *connRef289 = new ConnRef(router, 289);
+ ConnEnd srcPt289(Point(53.984, 207.608), 15);
+ connRef289->setSourceEndpoint(srcPt289);
+ ConnEnd dstPt289(Point(-8.01599, 207.608), 15);
+ connRef289->setDestEndpoint(dstPt289);
+ connRef289->setRoutingType((ConnType)2);
+
+ ConnRef *connRef328 = new ConnRef(router, 328);
+ ConnEnd srcPt328(Point(300.984, 683.608), 15);
+ connRef328->setSourceEndpoint(srcPt328);
+ ConnEnd dstPt328(Point(302.984, 591.5), 2);
+ connRef328->setDestEndpoint(dstPt328);
+ connRef328->setRoutingType((ConnType)2);
+
+ ConnRef *connRef329 = new ConnRef(router, 329);
+ ConnEnd srcPt329(Point(793.984, 1207.01), 15);
+ connRef329->setSourceEndpoint(srcPt329);
+ ConnEnd dstPt329(Point(830.984, 1207.01), 4);
+ connRef329->setDestEndpoint(dstPt329);
+ connRef329->setRoutingType((ConnType)2);
+
+ ConnRef *connRef192 = new ConnRef(router, 192);
+ ConnEnd srcPt192(Point(551.984, 1001.01), 15);
+ connRef192->setSourceEndpoint(srcPt192);
+ ConnEnd dstPt192(Point(551.984, 1051.01), 15);
+ connRef192->setDestEndpoint(dstPt192);
+ connRef192->setRoutingType((ConnType)2);
+
+ ConnRef *connRef193 = new ConnRef(router, 193);
+ ConnEnd srcPt193(Point(671.984, 949.008), 15);
+ connRef193->setSourceEndpoint(srcPt193);
+ ConnEnd dstPt193(Point(551.984, 949.008), 15);
+ connRef193->setDestEndpoint(dstPt193);
+ connRef193->setRoutingType((ConnType)2);
+
+ ConnRef *connRef215 = new ConnRef(router, 215);
+ ConnEnd srcPt215(Point(-8.01599, 363.608), 15);
+ connRef215->setSourceEndpoint(srcPt215);
+ ConnEnd dstPt215(Point(-8.01599, 249.608), 15);
+ connRef215->setDestEndpoint(dstPt215);
+ connRef215->setRoutingType((ConnType)2);
+
+ ConnRef *connRef276 = new ConnRef(router, 276);
+ ConnEnd srcPt276(Point(482.984, 787.608), 15);
+ connRef276->setSourceEndpoint(srcPt276);
+ ConnEnd dstPt276(Point(482.984, 837.608), 15);
+ connRef276->setDestEndpoint(dstPt276);
+ connRef276->setRoutingType((ConnType)2);
+
+ ConnRef *connRef277 = new ConnRef(router, 277);
+ ConnEnd srcPt277(Point(484.984, 884.608), 15);
+ connRef277->setSourceEndpoint(srcPt277);
+ ConnEnd dstPt277(Point(422.984, 884.608), 15);
+ connRef277->setDestEndpoint(dstPt277);
+ connRef277->setRoutingType((ConnType)2);
+
+ ConnRef *connRef273 = new ConnRef(router, 273);
+ ConnEnd srcPt273(Point(613.984, 991.008), 15);
+ connRef273->setSourceEndpoint(srcPt273);
+ ConnEnd dstPt273(Point(551.984, 991.008), 15);
+ connRef273->setDestEndpoint(dstPt273);
+ connRef273->setRoutingType((ConnType)2);
+
+ ConnRef *connRef274 = new ConnRef(router, 274);
+ ConnEnd srcPt274(Point(681.984, 899.008), 15);
+ connRef274->setSourceEndpoint(srcPt274);
+ ConnEnd dstPt274(Point(681.984, 949.008), 15);
+ connRef274->setDestEndpoint(dstPt274);
+ connRef274->setRoutingType((ConnType)2);
+
+ ConnRef *connRef313 = new ConnRef(router, 313);
+ ConnEnd srcPt313(Point(440.584, -314.392), 15);
+ connRef313->setSourceEndpoint(srcPt313);
+ ConnEnd dstPt313(Point(440.584, -271.392), 15);
+ connRef313->setDestEndpoint(dstPt313);
+ connRef313->setRoutingType((ConnType)2);
+
+ ConnRef *connRef314 = new ConnRef(router, 314);
+ ConnEnd srcPt314(Point(287.984, -314.392), 15);
+ connRef314->setSourceEndpoint(srcPt314);
+ ConnEnd dstPt314(Point(287.984, -271.392), 15);
+ connRef314->setDestEndpoint(dstPt314);
+ connRef314->setRoutingType((ConnType)2);
+
+ ConnRef *connRef248 = new ConnRef(router, 248);
+ ConnEnd srcPt248(Point(691.984, 1041.01), 15);
+ connRef248->setSourceEndpoint(srcPt248);
+ ConnEnd dstPt248(Point(793.984, 1051.01), 15);
+ connRef248->setDestEndpoint(dstPt248);
+ connRef248->setRoutingType((ConnType)2);
+
+ ConnRef *connRef309 = new ConnRef(router, 309);
+ ConnEnd srcPt309(Point(317.084, 445.608), 15);
+ connRef309->setSourceEndpoint(srcPt309);
+ ConnEnd dstPt309(Point(317.084, 413.608), 15);
+ connRef309->setDestEndpoint(dstPt309);
+ connRef309->setRoutingType((ConnType)2);
+
+ ConnRef *connRef203 = new ConnRef(router, 203);
+ ConnEnd srcPt203(Point(681.984, 745.608), 15);
+ connRef203->setSourceEndpoint(srcPt203);
+ ConnEnd dstPt203(Point(681.984, 847.008), 15);
+ connRef203->setDestEndpoint(dstPt203);
+ connRef203->setRoutingType((ConnType)2);
+
+ ConnRef *connRef239 = new ConnRef(router, 239);
+ ConnEnd srcPt239(Point(532.984, 520.608), 15);
+ connRef239->setSourceEndpoint(srcPt239);
+ ConnEnd dstPt239(Point(482.984, 468.608), 15);
+ connRef239->setDestEndpoint(dstPt239);
+ connRef239->setRoutingType((ConnType)2);
+
+ ConnRef *connRef316 = new ConnRef(router, 316);
+ ConnEnd srcPt316(Point(317.084, 445.608), 15);
+ connRef316->setSourceEndpoint(srcPt316);
+ ConnEnd dstPt316(Point(280.084, 445.608), 8);
+ connRef316->setDestEndpoint(dstPt316);
+ connRef316->setRoutingType((ConnType)2);
+
+ ConnRef *connRef317 = new ConnRef(router, 317);
+ ConnEnd srcPt317(Point(571.534, 184.608), 15);
+ connRef317->setSourceEndpoint(srcPt317);
+ ConnEnd dstPt317(Point(602.984, 335.5), 1);
+ connRef317->setDestEndpoint(dstPt317);
+ connRef317->setRoutingType((ConnType)2);
+
+ ConnRef *connRef234 = new ConnRef(router, 234);
+ ConnEnd srcPt234(Point(287.984, -251.392), 15);
+ connRef234->setSourceEndpoint(srcPt234);
+ ConnEnd dstPt234(Point(287.984, -159.392), 15);
+ connRef234->setDestEndpoint(dstPt234);
+ connRef234->setRoutingType((ConnType)2);
+
+ ConnRef *connRef235 = new ConnRef(router, 235);
+ ConnEnd srcPt235(Point(59.984, -159.392), 15);
+ connRef235->setSourceEndpoint(srcPt235);
+ ConnEnd dstPt235(Point(-101.016, -159.392), 15);
+ connRef235->setDestEndpoint(dstPt235);
+ connRef235->setRoutingType((ConnType)2);
+
+ ConnRef *connRef322 = new ConnRef(router, 322);
+ ConnEnd srcPt322(Point(551.984, 1051.01), 15);
+ connRef322->setSourceEndpoint(srcPt322);
+ ConnEnd dstPt322(Point(383.984, 1106.01), 8);
+ connRef322->setDestEndpoint(dstPt322);
+ connRef322->setRoutingType((ConnType)2);
+
+ ConnRef *connRef323 = new ConnRef(router, 323);
+ ConnEnd srcPt323(Point(-8.01599, 132.608), 15);
+ connRef323->setSourceEndpoint(srcPt323);
+ ConnEnd dstPt323(Point(296.984, 1091.01), 1);
+ connRef323->setDestEndpoint(dstPt323);
+ connRef323->setRoutingType((ConnType)2);
+
+ ConnRef *connRef213 = new ConnRef(router, 213);
+ ConnEnd srcPt213(Point(798.746, 249.608), 15);
+ connRef213->setSourceEndpoint(srcPt213);
+ ConnEnd dstPt213(Point(798.746, 335.608), 15);
+ connRef213->setDestEndpoint(dstPt213);
+ connRef213->setRoutingType((ConnType)2);
+
+ ConnRef *connRef214 = new ConnRef(router, 214);
+ ConnEnd srcPt214(Point(317.084, 393.608), 15);
+ connRef214->setSourceEndpoint(srcPt214);
+ ConnEnd dstPt214(Point(317.084, 361.608), 15);
+ connRef214->setDestEndpoint(dstPt214);
+ connRef214->setRoutingType((ConnType)2);
+
+ ConnRef *connRef243 = new ConnRef(router, 243);
+ ConnEnd srcPt243(Point(749.984, 520.608), 15);
+ connRef243->setSourceEndpoint(srcPt243);
+ ConnEnd dstPt243(Point(793.984, 683.608), 15);
+ connRef243->setDestEndpoint(dstPt243);
+ connRef243->setRoutingType((ConnType)2);
+
+ ConnRef *connRef244 = new ConnRef(router, 244);
+ ConnEnd srcPt244(Point(372.984, 683.608), 15);
+ connRef244->setSourceEndpoint(srcPt244);
+ ConnEnd dstPt244(Point(422.984, 683.608), 15);
+ connRef244->setDestEndpoint(dstPt244);
+ connRef244->setRoutingType((ConnType)2);
+
+ ConnRef *connRef272 = new ConnRef(router, 272);
+ ConnEnd srcPt272(Point(681.984, 991.008), 15);
+ connRef272->setSourceEndpoint(srcPt272);
+ ConnEnd dstPt272(Point(681.984, 1041.01), 15);
+ connRef272->setDestEndpoint(dstPt272);
+ connRef272->setRoutingType((ConnType)2);
+
+ ConnRef *connRef210 = new ConnRef(router, 210);
+ ConnEnd srcPt210(Point(522.984, 690.465), 15);
+ connRef210->setSourceEndpoint(srcPt210);
+ ConnEnd dstPt210(Point(422.984, 683.608), 15);
+ connRef210->setDestEndpoint(dstPt210);
+ connRef210->setRoutingType((ConnType)2);
+
+ ConnRef *connRef211 = new ConnRef(router, 211);
+ ConnEnd srcPt211(Point(352.984, 683.608), 15);
+ connRef211->setSourceEndpoint(srcPt211);
+ ConnEnd dstPt211(Point(300.984, 683.608), 15);
+ connRef211->setDestEndpoint(dstPt211);
+ connRef211->setRoutingType((ConnType)2);
+
+ ConnRef *connRef245 = new ConnRef(router, 245);
+ ConnEnd srcPt245(Point(300.984, 683.608), 15);
+ connRef245->setSourceEndpoint(srcPt245);
+ ConnEnd dstPt245(Point(172.984, 694.465), 15);
+ connRef245->setDestEndpoint(dstPt245);
+ connRef245->setRoutingType((ConnType)2);
+
+ ConnRef *connRef178 = new ConnRef(router, 178);
+ ConnEnd srcPt178(Point(390.584, 236.608), 15);
+ connRef178->setSourceEndpoint(srcPt178);
+ ConnEnd dstPt178(Point(440.584, 236.608), 15);
+ connRef178->setDestEndpoint(dstPt178);
+ connRef178->setRoutingType((ConnType)2);
+
+ ConnRef *connRef179 = new ConnRef(router, 179);
+ ConnEnd srcPt179(Point(521.534, 236.608), 15);
+ connRef179->setSourceEndpoint(srcPt179);
+ ConnEnd dstPt179(Point(571.534, 184.608), 15);
+ connRef179->setDestEndpoint(dstPt179);
+ connRef179->setRoutingType((ConnType)2);
+
+ ConnRef *connRef194 = new ConnRef(router, 194);
+ ConnEnd srcPt194(Point(691.984, 949.008), 15);
+ connRef194->setSourceEndpoint(srcPt194);
+ ConnEnd dstPt194(Point(793.984, 949.008), 15);
+ connRef194->setDestEndpoint(dstPt194);
+ connRef194->setRoutingType((ConnType)2);
+
+ ConnRef *connRef296 = new ConnRef(router, 296);
+ ConnEnd srcPt296(Point(502.584, -45.3921), 15);
+ connRef296->setSourceEndpoint(srcPt296);
+ ConnEnd dstPt296(Point(440.584, -45.3921), 15);
+ connRef296->setDestEndpoint(dstPt296);
+ connRef296->setRoutingType((ConnType)2);
+
+ ConnRef *connRef230 = new ConnRef(router, 230);
+ ConnEnd srcPt230(Point(440.584, -35.3921), 15);
+ connRef230->setSourceEndpoint(srcPt230);
+ ConnEnd dstPt230(Point(440.584, -3.39214), 15);
+ connRef230->setDestEndpoint(dstPt230);
+ connRef230->setRoutingType((ConnType)2);
+
+ ConnRef *connRef246 = new ConnRef(router, 246);
+ ConnEnd srcPt246(Point(409.484, 1051.01), 15);
+ connRef246->setSourceEndpoint(srcPt246);
+ ConnEnd dstPt246(Point(551.984, 1051.01), 15);
+ connRef246->setDestEndpoint(dstPt246);
+ connRef246->setRoutingType((ConnType)2);
+
+ ConnRef *connRef247 = new ConnRef(router, 247);
+ ConnEnd srcPt247(Point(691.984, 1133.01), 15);
+ connRef247->setSourceEndpoint(srcPt247);
+ ConnEnd dstPt247(Point(793.984, 1051.01), 15);
+ connRef247->setDestEndpoint(dstPt247);
+ connRef247->setRoutingType((ConnType)2);
+
+ ConnRef *connRef269 = new ConnRef(router, 269);
+ ConnEnd srcPt269(Point(923.984, 899.008), 15);
+ connRef269->setSourceEndpoint(srcPt269);
+ ConnEnd dstPt269(Point(923.984, 949.008), 15);
+ connRef269->setDestEndpoint(dstPt269);
+ connRef269->setRoutingType((ConnType)2);
+
+ ConnRef *connRef240 = new ConnRef(router, 240);
+ ConnEnd srcPt240(Point(532.984, 520.608), 15);
+ connRef240->setSourceEndpoint(srcPt240);
+ ConnEnd dstPt240(Point(464.984, 520.608), 15);
+ connRef240->setDestEndpoint(dstPt240);
+ connRef240->setRoutingType((ConnType)2);
+
+ ConnRef *connRef241 = new ConnRef(router, 241);
+ ConnEnd srcPt241(Point(131.984, 132.608), 15);
+ connRef241->setSourceEndpoint(srcPt241);
+ ConnEnd dstPt241(Point(287.984, 132.608), 15);
+ connRef241->setDestEndpoint(dstPt241);
+ connRef241->setRoutingType((ConnType)2);
+
+ ConnRef *connRef201 = new ConnRef(router, 201);
+ ConnEnd srcPt201(Point(793.984, 745.608), 15);
+ connRef201->setSourceEndpoint(srcPt201);
+ ConnEnd dstPt201(Point(793.984, 837.608), 15);
+ connRef201->setDestEndpoint(dstPt201);
+ connRef201->setRoutingType((ConnType)2);
+
+ ConnRef *connRef202 = new ConnRef(router, 202);
+ ConnEnd srcPt202(Point(681.984, 725.608), 15);
+ connRef202->setSourceEndpoint(srcPt202);
+ ConnEnd dstPt202(Point(793.984, 683.608), 15);
+ connRef202->setDestEndpoint(dstPt202);
+ connRef202->setRoutingType((ConnType)2);
+
+ ConnRef *connRef324 = new ConnRef(router, 324);
+ ConnEnd srcPt324(Point(306.584, 1283.01), 15);
+ connRef324->setSourceEndpoint(srcPt324);
+ ConnEnd dstPt324(Point(296.984, 1213.01), 2);
+ connRef324->setDestEndpoint(dstPt324);
+ connRef324->setRoutingType((ConnType)2);
+
+ ConnRef *connRef182 = new ConnRef(router, 182);
+ ConnEnd srcPt182(Point(418.984, 1283.01), 15);
+ connRef182->setSourceEndpoint(srcPt182);
+ ConnEnd dstPt182(Point(306.584, 1283.01), 15);
+ connRef182->setDestEndpoint(dstPt182);
+ connRef182->setRoutingType((ConnType)2);
+
+ ConnRef *connRef183 = new ConnRef(router, 183);
+ ConnEnd srcPt183(Point(556.484, 1213.01), 15);
+ connRef183->setSourceEndpoint(srcPt183);
+ ConnEnd dstPt183(Point(551.984, 1051.01), 15);
+ connRef183->setDestEndpoint(dstPt183);
+ connRef183->setRoutingType((ConnType)2);
+
+ ConnRef *connRef190 = new ConnRef(router, 190);
+ ConnEnd srcPt190(Point(671.984, 1041.01), 15);
+ connRef190->setSourceEndpoint(srcPt190);
+ ConnEnd dstPt190(Point(551.984, 1051.01), 15);
+ connRef190->setDestEndpoint(dstPt190);
+ connRef190->setRoutingType((ConnType)2);
+
+ ConnRef *connRef191 = new ConnRef(router, 191);
+ ConnEnd srcPt191(Point(551.984, 981.008), 15);
+ connRef191->setSourceEndpoint(srcPt191);
+ ConnEnd dstPt191(Point(551.984, 949.008), 15);
+ connRef191->setDestEndpoint(dstPt191);
+ connRef191->setRoutingType((ConnType)2);
+
+ ConnRef *connRef285 = new ConnRef(router, 285);
+ ConnEnd srcPt285(Point(379.084, 403.608), 15);
+ connRef285->setSourceEndpoint(srcPt285);
+ ConnEnd dstPt285(Point(317.084, 403.608), 15);
+ connRef285->setDestEndpoint(dstPt285);
+ connRef285->setRoutingType((ConnType)2);
+
+ ConnRef *connRef286 = new ConnRef(router, 286);
+ ConnEnd srcPt286(Point(53.984, 373.608), 15);
+ connRef286->setSourceEndpoint(srcPt286);
+ ConnEnd dstPt286(Point(-8.01599, 373.608), 15);
+ connRef286->setDestEndpoint(dstPt286);
+ connRef286->setRoutingType((ConnType)2);
+
+ ConnRef *connRef291 = new ConnRef(router, 291);
+ ConnEnd srcPt291(Point(362.984, 82.6079), 15);
+ connRef291->setSourceEndpoint(srcPt291);
+ ConnEnd dstPt291(Point(362.984, 132.608), 15);
+ connRef291->setDestEndpoint(dstPt291);
+ connRef291->setRoutingType((ConnType)2);
+
+ ConnRef *connRef292 = new ConnRef(router, 292);
+ ConnEnd srcPt292(Point(121.984, 82.6079), 15);
+ connRef292->setSourceEndpoint(srcPt292);
+ ConnEnd dstPt292(Point(121.984, 132.608), 15);
+ connRef292->setDestEndpoint(dstPt292);
+ connRef292->setRoutingType((ConnType)2);
+
+ ConnRef *connRef325 = new ConnRef(router, 325);
+ ConnEnd srcPt325(Point(317.084, 361.608), 15);
+ connRef325->setSourceEndpoint(srcPt325);
+ ConnEnd dstPt325(Point(280.084, 321.608), 8);
+ connRef325->setDestEndpoint(dstPt325);
+ connRef325->setRoutingType((ConnType)2);
+
+ ConnRef *connRef326 = new ConnRef(router, 326);
+ ConnEnd srcPt326(Point(571.534, 184.608), 15);
+ connRef326->setSourceEndpoint(srcPt326);
+ ConnEnd dstPt326(Point(982.984, 283.5), 4);
+ connRef326->setDestEndpoint(dstPt326);
+ connRef326->setRoutingType((ConnType)2);
+
+ ConnRef *connRef219 = new ConnRef(router, 219);
+ ConnEnd srcPt219(Point(317.084, 329.608), 15);
+ connRef219->setSourceEndpoint(srcPt219);
+ ConnEnd dstPt219(Point(317.084, 361.608), 15);
+ connRef219->setDestEndpoint(dstPt219);
+ connRef219->setRoutingType((ConnType)2);
+
+ ConnRef *connRef220 = new ConnRef(router, 220);
+ ConnEnd srcPt220(Point(-8.01599, 217.608), 15);
+ connRef220->setSourceEndpoint(srcPt220);
+ ConnEnd dstPt220(Point(-8.01599, 249.608), 15);
+ connRef220->setDestEndpoint(dstPt220);
+ connRef220->setRoutingType((ConnType)2);
+
+ ConnRef *connRef224 = new ConnRef(router, 224);
+ ConnEnd srcPt224(Point(372.984, 132.608), 15);
+ connRef224->setSourceEndpoint(srcPt224);
+ ConnEnd dstPt224(Point(440.584, 132.608), 15);
+ connRef224->setDestEndpoint(dstPt224);
+ connRef224->setRoutingType((ConnType)2);
+
+ ConnRef *connRef173 = new ConnRef(router, 173);
+ ConnEnd srcPt173(Point(511.534, -149.392), 15);
+ connRef173->setSourceEndpoint(srcPt173);
+ ConnEnd dstPt173(Point(440.584, -3.39214), 15);
+ connRef173->setDestEndpoint(dstPt173);
+ connRef173->setRoutingType((ConnType)2);
+
+ ConnRef *connRef260 = new ConnRef(router, 260);
+ ConnEnd srcPt260(Point(552.984, 520.608), 15);
+ connRef260->setSourceEndpoint(srcPt260);
+ ConnEnd dstPt260(Point(602.984, 520.608), 15);
+ connRef260->setDestEndpoint(dstPt260);
+ connRef260->setRoutingType((ConnType)2);
+
+ ConnRef *connRef197 = new ConnRef(router, 197);
+ ConnEnd srcPt197(Point(472.984, 837.608), 15);
+ connRef197->setSourceEndpoint(srcPt197);
+ ConnEnd dstPt197(Point(422.984, 837.608), 15);
+ connRef197->setDestEndpoint(dstPt197);
+ connRef197->setRoutingType((ConnType)2);
+
+ ConnRef *connRef206 = new ConnRef(router, 206);
+ ConnEnd srcPt206(Point(300.984, 725.608), 15);
+ connRef206->setSourceEndpoint(srcPt206);
+ ConnEnd dstPt206(Point(300.984, 683.608), 15);
+ connRef206->setDestEndpoint(dstPt206);
+ connRef206->setRoutingType((ConnType)2);
+
+ ConnRef *connRef255 = new ConnRef(router, 255);
+ ConnEnd srcPt255(Point(440.584, -456.392), 15);
+ connRef255->setSourceEndpoint(srcPt255);
+ ConnEnd dstPt255(Point(440.584, -424.392), 15);
+ connRef255->setDestEndpoint(dstPt255);
+ connRef255->setRoutingType((ConnType)2);
+
+ ConnRef *connRef256 = new ConnRef(router, 256);
+ ConnEnd srcPt256(Point(440.584, -314.392), 15);
+ connRef256->setSourceEndpoint(srcPt256);
+ ConnEnd dstPt256(Point(362.984, -405.392), 15);
+ connRef256->setDestEndpoint(dstPt256);
+ connRef256->setRoutingType((ConnType)2);
+
+ ConnRef *connRef225 = new ConnRef(router, 225);
+ ConnEnd srcPt225(Point(352.984, 132.608), 15);
+ connRef225->setSourceEndpoint(srcPt225);
+ ConnEnd dstPt225(Point(287.984, 132.608), 15);
+ connRef225->setDestEndpoint(dstPt225);
+ connRef225->setRoutingType((ConnType)2);
+
+ ConnRef *connRef226 = new ConnRef(router, 226);
+ ConnEnd srcPt226(Point(111.984, 132.608), 15);
+ connRef226->setSourceEndpoint(srcPt226);
+ ConnEnd dstPt226(Point(-8.01599, 132.608), 15);
+ connRef226->setDestEndpoint(dstPt226);
+ connRef226->setRoutingType((ConnType)2);
+
+ ConnRef *connRef236 = new ConnRef(router, 236);
+ ConnEnd srcPt236(Point(-76.016, 38.6079), 15);
+ connRef236->setSourceEndpoint(srcPt236);
+ ConnEnd dstPt236(Point(-101.016, -159.392), 15);
+ connRef236->setDestEndpoint(dstPt236);
+ connRef236->setRoutingType((ConnType)2);
+
+ ConnRef *connRef184 = new ConnRef(router, 184);
+ ConnEnd srcPt184(Point(1065.98, 769.608), 15);
+ connRef184->setSourceEndpoint(srcPt184);
+ ConnEnd dstPt184(Point(1065.98, 903.608), 15);
+ connRef184->setDestEndpoint(dstPt184);
+ connRef184->setRoutingType((ConnType)2);
+
+ ConnRef *connRef185 = new ConnRef(router, 185);
+ ConnEnd srcPt185(Point(1065.98, 749.608), 15);
+ connRef185->setSourceEndpoint(srcPt185);
+ ConnEnd dstPt185(Point(1065.98, 683.608), 15);
+ connRef185->setDestEndpoint(dstPt185);
+ connRef185->setRoutingType((ConnType)2);
+
+ ConnRef *connRef212 = new ConnRef(router, 212);
+ ConnEnd srcPt212(Point(798.746, 229.608), 15);
+ connRef212->setSourceEndpoint(srcPt212);
+ ConnEnd dstPt212(Point(798.746, 184.608), 15);
+ connRef212->setDestEndpoint(dstPt212);
+ connRef212->setRoutingType((ConnType)2);
+
+ ConnRef *connRef195 = new ConnRef(router, 195);
+ ConnEnd srcPt195(Point(489, 936.608), 15);
+ connRef195->setSourceEndpoint(srcPt195);
+ ConnEnd dstPt195(Point(551.984, 1051.01), 15);
+ connRef195->setDestEndpoint(dstPt195);
+ connRef195->setRoutingType((ConnType)2);
+
+ ConnRef *connRef196 = new ConnRef(router, 196);
+ ConnEnd srcPt196(Point(793.984, 869.608), 15);
+ connRef196->setSourceEndpoint(srcPt196);
+ ConnEnd dstPt196(Point(793.984, 837.608), 15);
+ connRef196->setDestEndpoint(dstPt196);
+ connRef196->setRoutingType((ConnType)2);
+
+ ConnRef *connRef294 = new ConnRef(router, 294);
+ ConnEnd srcPt294(Point(362.984, -53.3921), 15);
+ connRef294->setSourceEndpoint(srcPt294);
+ ConnEnd dstPt294(Point(362.984, -3.39214), 15);
+ connRef294->setDestEndpoint(dstPt294);
+ connRef294->setRoutingType((ConnType)2);
+
+ ConnRef *connRef295 = new ConnRef(router, 295);
+ ConnEnd srcPt295(Point(121.984, -53.3921), 15);
+ connRef295->setSourceEndpoint(srcPt295);
+ ConnEnd dstPt295(Point(121.984, -3.39214), 15);
+ connRef295->setDestEndpoint(dstPt295);
+ connRef295->setRoutingType((ConnType)2);
+
+ ConnRef *connRef254 = new ConnRef(router, 254);
+ ConnEnd srcPt254(Point(798.746, 335.608), 15);
+ connRef254->setSourceEndpoint(srcPt254);
+ ConnEnd dstPt254(Point(945.984, 335.608), 15);
+ connRef254->setDestEndpoint(dstPt254);
+ connRef254->setRoutingType((ConnType)2);
+
+ ConnRef *connRef264 = new ConnRef(router, 264);
+ ConnEnd srcPt264(Point(858.746, 379.608), 15);
+ connRef264->setSourceEndpoint(srcPt264);
+ ConnEnd dstPt264(Point(858.746, 429.608), 15);
+ connRef264->setDestEndpoint(dstPt264);
+ connRef264->setRoutingType((ConnType)2);
+
+ ConnRef *connRef265 = new ConnRef(router, 265);
+ ConnEnd srcPt265(Point(511.534, 186.608), 15);
+ connRef265->setSourceEndpoint(srcPt265);
+ ConnEnd dstPt265(Point(511.534, 236.608), 15);
+ connRef265->setDestEndpoint(dstPt265);
+ connRef265->setRoutingType((ConnType)2);
+
+ ConnRef *connRef266 = new ConnRef(router, 266);
+ ConnEnd srcPt266(Point(428.984, 1233.01), 15);
+ connRef266->setSourceEndpoint(srcPt266);
+ ConnEnd dstPt266(Point(428.984, 1283.01), 15);
+ connRef266->setDestEndpoint(dstPt266);
+ connRef266->setRoutingType((ConnType)2);
+
+ ConnRef *connRef290 = new ConnRef(router, 290);
+ ConnEnd srcPt290(Point(511.534, 82.6079), 15);
+ connRef290->setSourceEndpoint(srcPt290);
+ ConnEnd dstPt290(Point(511.534, 132.608), 15);
+ connRef290->setDestEndpoint(dstPt290);
+ connRef290->setRoutingType((ConnType)2);
+
+ ConnRef *connRef270 = new ConnRef(router, 270);
+ ConnEnd srcPt270(Point(815.984, 1155.01), 15);
+ connRef270->setSourceEndpoint(srcPt270);
+ ConnEnd dstPt270(Point(753.984, 1155.01), 15);
+ connRef270->setDestEndpoint(dstPt270);
+ connRef270->setRoutingType((ConnType)2);
+
+ ConnRef *connRef271 = new ConnRef(router, 271);
+ ConnEnd srcPt271(Point(681.984, 1083.01), 15);
+ connRef271->setSourceEndpoint(srcPt271);
+ ConnEnd dstPt271(Point(681.984, 1133.01), 15);
+ connRef271->setDestEndpoint(dstPt271);
+ connRef271->setRoutingType((ConnType)2);
+
+ ConnRef *connRef301 = new ConnRef(router, 301);
+ ConnEnd srcPt301(Point(69.984, -209.392), 15);
+ connRef301->setSourceEndpoint(srcPt301);
+ ConnEnd dstPt301(Point(69.984, -159.392), 15);
+ connRef301->setDestEndpoint(dstPt301);
+ connRef301->setRoutingType((ConnType)2);
+
+ ConnRef *connRef228 = new ConnRef(router, 228);
+ ConnEnd srcPt228(Point(352.984, -3.39214), 15);
+ connRef228->setSourceEndpoint(srcPt228);
+ ConnEnd dstPt228(Point(287.984, -3.39214), 15);
+ connRef228->setDestEndpoint(dstPt228);
+ connRef228->setRoutingType((ConnType)2);
+
+ ConnRef *connRef229 = new ConnRef(router, 229);
+ ConnEnd srcPt229(Point(111.984, -3.39214), 15);
+ connRef229->setSourceEndpoint(srcPt229);
+ ConnEnd dstPt229(Point(-8.01599, -3.39214), 15);
+ connRef229->setDestEndpoint(dstPt229);
+ connRef229->setRoutingType((ConnType)2);
+
+ ConnRef *connRef237 = new ConnRef(router, 237);
+ ConnEnd srcPt237(Point(-76.016, 58.6079), 15);
+ connRef237->setSourceEndpoint(srcPt237);
+ ConnEnd dstPt237(Point(-8.01599, 132.608), 15);
+ connRef237->setDestEndpoint(dstPt237);
+ connRef237->setRoutingType((ConnType)2);
+
+ ConnRef *connRef238 = new ConnRef(router, 238);
+ ConnEnd srcPt238(Point(729.984, 520.608), 15);
+ connRef238->setSourceEndpoint(srcPt238);
+ ConnEnd dstPt238(Point(602.984, 520.608), 15);
+ connRef238->setDestEndpoint(dstPt238);
+ connRef238->setRoutingType((ConnType)2);
+
+ ConnRef *connRef227 = new ConnRef(router, 227);
+ ConnEnd srcPt227(Point(-8.01599, 100.608), 15);
+ connRef227->setSourceEndpoint(srcPt227);
+ ConnEnd dstPt227(Point(-8.01599, 132.608), 15);
+ connRef227->setDestEndpoint(dstPt227);
+ connRef227->setRoutingType((ConnType)2);
+
+ ConnRef *connRef281 = new ConnRef(router, 281);
+ ConnEnd srcPt281(Point(362.984, 735.608), 15);
+ connRef281->setSourceEndpoint(srcPt281);
+ ConnEnd dstPt281(Point(300.984, 735.608), 15);
+ connRef281->setDestEndpoint(dstPt281);
+ connRef281->setRoutingType((ConnType)2);
+
+ ConnRef *connRef221 = new ConnRef(router, 221);
+ ConnEnd srcPt221(Point(-8.01599, 197.608), 15);
+ connRef221->setSourceEndpoint(srcPt221);
+ ConnEnd dstPt221(Point(-8.01599, 132.608), 15);
+ connRef221->setDestEndpoint(dstPt221);
+ connRef221->setRoutingType((ConnType)2);
+
+ ConnRef *connRef304 = new ConnRef(router, 304);
+ ConnEnd srcPt304(Point(542.984, 470.608), 15);
+ connRef304->setSourceEndpoint(srcPt304);
+ ConnEnd dstPt304(Point(542.984, 520.608), 15);
+ connRef304->setDestEndpoint(dstPt304);
+ connRef304->setRoutingType((ConnType)2);
+
+ ConnRef *connRef305 = new ConnRef(router, 305);
+ ConnEnd srcPt305(Point(362.984, -353.392), 15);
+ connRef305->setSourceEndpoint(srcPt305);
+ ConnEnd dstPt305(Point(362.984, -303.392), 15);
+ connRef305->setDestEndpoint(dstPt305);
+ connRef305->setRoutingType((ConnType)2);
+
+ ConnRef *connRef319 = new ConnRef(router, 319);
+ ConnEnd srcPt319(Point(571.534, 184.608), 15);
+ connRef319->setSourceEndpoint(srcPt319);
+ ConnEnd dstPt319(Point(730.5, 44.6079), 4);
+ connRef319->setDestEndpoint(dstPt319);
+ connRef319->setRoutingType((ConnType)2);
+
+ ConnRef *connRef320 = new ConnRef(router, 320);
+ ConnEnd srcPt320(Point(798.746, 184.608), 15);
+ connRef320->setSourceEndpoint(srcPt320);
+ ConnEnd dstPt320(Point(730.5, 96.6079), 4);
+ connRef320->setDestEndpoint(dstPt320);
+ connRef320->setRoutingType((ConnType)2);
+
+ ConnRef *connRef251 = new ConnRef(router, 251);
+ ConnEnd srcPt251(Point(793.984, 889.608), 15);
+ connRef251->setSourceEndpoint(srcPt251);
+ ConnEnd dstPt251(Point(793.984, 949.008), 15);
+ connRef251->setDestEndpoint(dstPt251);
+ connRef251->setRoutingType((ConnType)2);
+
+ ConnRef *connRef261 = new ConnRef(router, 261);
+ ConnEnd srcPt261(Point(152.984, 694.465), 15);
+ connRef261->setSourceEndpoint(srcPt261);
+ ConnEnd dstPt261(Point(102.984, 683.608), 15);
+ connRef261->setDestEndpoint(dstPt261);
+ connRef261->setRoutingType((ConnType)2);
+
+ ConnRef *connRef262 = new ConnRef(router, 262);
+ ConnEnd srcPt262(Point(511.534, -209.392), 15);
+ connRef262->setSourceEndpoint(srcPt262);
+ ConnEnd dstPt262(Point(511.534, -159.392), 15);
+ connRef262->setDestEndpoint(dstPt262);
+ connRef262->setRoutingType((ConnType)2);
+
+ ConnRef *connRef257 = new ConnRef(router, 257);
+ ConnEnd srcPt257(Point(440.584, -314.392), 15);
+ connRef257->setSourceEndpoint(srcPt257);
+ ConnEnd dstPt257(Point(372.984, -303.392), 15);
+ connRef257->setDestEndpoint(dstPt257);
+ connRef257->setRoutingType((ConnType)2);
+
+ ConnRef *connRef233 = new ConnRef(router, 233);
+ ConnEnd srcPt233(Point(362.984, -385.392), 15);
+ connRef233->setSourceEndpoint(srcPt233);
+ ConnEnd dstPt233(Point(287.984, -314.392), 15);
+ connRef233->setDestEndpoint(dstPt233);
+ connRef233->setRoutingType((ConnType)2);
+
+ ConnRef *connRef263 = new ConnRef(router, 263);
+ ConnEnd srcPt263(Point(996.984, 526.108), 15);
+ connRef263->setSourceEndpoint(srcPt263);
+ ConnEnd dstPt263(Point(934.984, 526.108), 15);
+ connRef263->setDestEndpoint(dstPt263);
+ connRef263->setRoutingType((ConnType)2);
+
+ ConnRef *connRef287 = new ConnRef(router, 287);
+ ConnEnd srcPt287(Point(380.584, 186.608), 15);
+ connRef287->setSourceEndpoint(srcPt287);
+ ConnEnd dstPt287(Point(380.584, 236.608), 15);
+ connRef287->setDestEndpoint(dstPt287);
+ connRef287->setRoutingType((ConnType)2);
+
+ ConnRef *connRef218 = new ConnRef(router, 218);
+ ConnEnd srcPt218(Point(317.084, 309.608), 15);
+ connRef218->setSourceEndpoint(srcPt218);
+ ConnEnd dstPt218(Point(320.584, 184.608), 15);
+ connRef218->setDestEndpoint(dstPt218);
+ connRef218->setRoutingType((ConnType)2);
+
+ ConnRef *connRef267 = new ConnRef(router, 267);
+ ConnEnd srcPt267(Point(618.484, 1223.01), 15);
+ connRef267->setSourceEndpoint(srcPt267);
+ ConnEnd dstPt267(Point(556.484, 1223.01), 15);
+ connRef267->setDestEndpoint(dstPt267);
+ connRef267->setRoutingType((ConnType)2);
+
+ ConnRef *connRef268 = new ConnRef(router, 268);
+ ConnEnd srcPt268(Point(1127.98, 759.608), 15);
+ connRef268->setSourceEndpoint(srcPt268);
+ ConnEnd dstPt268(Point(1065.98, 759.608), 15);
+ connRef268->setDestEndpoint(dstPt268);
+ connRef268->setRoutingType((ConnType)2);
+
+ ConnRef *connRef278 = new ConnRef(router, 278);
+ ConnEnd srcPt278(Point(855.984, 735.608), 15);
+ connRef278->setSourceEndpoint(srcPt278);
+ ConnEnd dstPt278(Point(793.984, 735.608), 15);
+ connRef278->setDestEndpoint(dstPt278);
+ connRef278->setRoutingType((ConnType)2);
+
+ ConnRef *connRef299 = new ConnRef(router, 299);
+ ConnEnd srcPt299(Point(362.984, -445.392), 15);
+ connRef299->setSourceEndpoint(srcPt299);
+ ConnEnd dstPt299(Point(362.984, -395.392), 15);
+ connRef299->setDestEndpoint(dstPt299);
+ connRef299->setRoutingType((ConnType)2);
+
+ ConnRef *connRef300 = new ConnRef(router, 300);
+ ConnEnd srcPt300(Point(349.984, -261.392), 15);
+ connRef300->setSourceEndpoint(srcPt300);
+ ConnEnd dstPt300(Point(287.984, -261.392), 15);
+ connRef300->setDestEndpoint(dstPt300);
+ connRef300->setRoutingType((ConnType)2);
+
+ ConnRef *connRef302 = new ConnRef(router, 302);
+ ConnEnd srcPt302(Point(-14.016, 48.6079), 15);
+ connRef302->setSourceEndpoint(srcPt302);
+ ConnEnd dstPt302(Point(-76.016, 48.6079), 15);
+ connRef302->setDestEndpoint(dstPt302);
+ connRef302->setRoutingType((ConnType)2);
+
+ ConnRef *connRef303 = new ConnRef(router, 303);
+ ConnEnd srcPt303(Point(739.984, 470.608), 15);
+ connRef303->setSourceEndpoint(srcPt303);
+ ConnEnd dstPt303(Point(739.984, 520.608), 15);
+ connRef303->setDestEndpoint(dstPt303);
+ connRef303->setRoutingType((ConnType)2);
+
+ ConnRef *connRef204 = new ConnRef(router, 204);
+ ConnEnd srcPt204(Point(422.984, 725.608), 15);
+ connRef204->setSourceEndpoint(srcPt204);
+ ConnEnd dstPt204(Point(422.984, 683.608), 15);
+ connRef204->setDestEndpoint(dstPt204);
+ connRef204->setRoutingType((ConnType)2);
+
+ ConnRef *connRef205 = new ConnRef(router, 205);
+ ConnEnd srcPt205(Point(422.984, 745.608), 15);
+ connRef205->setSourceEndpoint(srcPt205);
+ ConnEnd dstPt205(Point(422.984, 837.608), 15);
+ connRef205->setDestEndpoint(dstPt205);
+ connRef205->setRoutingType((ConnType)2);
+
+ ConnRef *connRef207 = new ConnRef(router, 207);
+ ConnEnd srcPt207(Point(300.984, 745.608), 15);
+ connRef207->setSourceEndpoint(srcPt207);
+ ConnEnd dstPt207(Point(422.984, 837.608), 15);
+ connRef207->setDestEndpoint(dstPt207);
+ connRef207->setRoutingType((ConnType)2);
+
+ ConnRef *connRef208 = new ConnRef(router, 208);
+ ConnEnd srcPt208(Point(824, 569), 15);
+ connRef208->setSourceEndpoint(srcPt208);
+ ConnEnd dstPt208(Point(1065.98, 683.608), 15);
+ connRef208->setDestEndpoint(dstPt208);
+ connRef208->setRoutingType((ConnType)2);
+
+ ConnRef *connRef258 = new ConnRef(router, 258);
+ ConnEnd srcPt258(Point(352.984, -303.392), 15);
+ connRef258->setSourceEndpoint(srcPt258);
+ ConnEnd dstPt258(Point(287.984, -314.392), 15);
+ connRef258->setDestEndpoint(dstPt258);
+ connRef258->setRoutingType((ConnType)2);
+
+ ConnRef *connRef259 = new ConnRef(router, 259);
+ ConnEnd srcPt259(Point(79.984, -159.392), 15);
+ connRef259->setSourceEndpoint(srcPt259);
+ ConnEnd dstPt259(Point(287.984, -159.392), 15);
+ connRef259->setDestEndpoint(dstPt259);
+ connRef259->setRoutingType((ConnType)2);
+
+ ConnRef *connRef200 = new ConnRef(router, 200);
+ ConnEnd srcPt200(Point(793.984, 725.608), 15);
+ connRef200->setSourceEndpoint(srcPt200);
+ ConnEnd dstPt200(Point(793.984, 683.608), 15);
+ connRef200->setDestEndpoint(dstPt200);
+ connRef200->setRoutingType((ConnType)2);
+
+ ConnRef *connRef231 = new ConnRef(router, 231);
+ ConnEnd srcPt231(Point(440.584, -251.392), 15);
+ connRef231->setSourceEndpoint(srcPt231);
+ ConnEnd dstPt231(Point(440.584, -159.392), 15);
+ connRef231->setDestEndpoint(dstPt231);
+ connRef231->setRoutingType((ConnType)2);
+
+ ConnRef *connRef232 = new ConnRef(router, 232);
+ ConnEnd srcPt232(Point(440.584, -404.392), 15);
+ connRef232->setSourceEndpoint(srcPt232);
+ ConnEnd dstPt232(Point(440.584, -314.392), 15);
+ connRef232->setDestEndpoint(dstPt232);
+ connRef232->setRoutingType((ConnType)2);
+
+ ConnRef *connRef318 = new ConnRef(router, 318);
+ ConnEnd srcPt318(Point(440.584, -3.39214), 15);
+ connRef318->setSourceEndpoint(srcPt318);
+ ConnEnd dstPt318(Point(730.5, -7.39214), 4);
+ connRef318->setDestEndpoint(dstPt318);
+ connRef318->setRoutingType((ConnType)2);
+
+ ConnRef *connRef293 = new ConnRef(router, 293);
+ ConnEnd srcPt293(Point(53.984, 90.6079), 15);
+ connRef293->setSourceEndpoint(srcPt293);
+ ConnEnd dstPt293(Point(-8.01599, 90.6079), 15);
+ connRef293->setDestEndpoint(dstPt293);
+ connRef293->setRoutingType((ConnType)2);
+
+ ConnRef *connRef310 = new ConnRef(router, 310);
+ ConnEnd srcPt310(Point(-8.01599, -3.39214), 15);
+ connRef310->setSourceEndpoint(srcPt310);
+ ConnEnd dstPt310(Point(-8.01599, 80.6079), 15);
+ connRef310->setDestEndpoint(dstPt310);
+ connRef310->setRoutingType((ConnType)2);
+
+ ConnRef *connRef311 = new ConnRef(router, 311);
+ ConnEnd srcPt311(Point(440.584, -3.39214), 15);
+ connRef311->setSourceEndpoint(srcPt311);
+ ConnEnd dstPt311(Point(372.984, -3.39214), 15);
+ connRef311->setDestEndpoint(dstPt311);
+ connRef311->setRoutingType((ConnType)2);
+
+ ConnRef *connRef249 = new ConnRef(router, 249);
+ ConnEnd srcPt249(Point(933.984, 949.008), 15);
+ connRef249->setSourceEndpoint(srcPt249);
+ ConnEnd dstPt249(Point(1065.98, 903.608), 15);
+ connRef249->setDestEndpoint(dstPt249);
+ connRef249->setRoutingType((ConnType)2);
+
+ ConnRef *connRef250 = new ConnRef(router, 250);
+ ConnEnd srcPt250(Point(959.984, 683.608), 15);
+ connRef250->setSourceEndpoint(srcPt250);
+ ConnEnd dstPt250(Point(1065.98, 683.608), 15);
+ connRef250->setDestEndpoint(dstPt250);
+ connRef250->setRoutingType((ConnType)2);
+
+ ConnRef *connRef242 = new ConnRef(router, 242);
+ ConnEnd srcPt242(Point(287.984, -3.39214), 15);
+ connRef242->setSourceEndpoint(srcPt242);
+ ConnEnd dstPt242(Point(131.984, -3.39214), 15);
+ connRef242->setDestEndpoint(dstPt242);
+ connRef242->setRoutingType((ConnType)2);
+
+ ConnRef *connRef275 = new ConnRef(router, 275);
+ ConnEnd srcPt275(Point(855.984, 879.608), 15);
+ connRef275->setSourceEndpoint(srcPt275);
+ ConnEnd dstPt275(Point(793.984, 879.608), 15);
+ connRef275->setDestEndpoint(dstPt275);
+ connRef275->setRoutingType((ConnType)2);
+
+ ConnRef *connRef307 = new ConnRef(router, 307);
+ ConnEnd srcPt307(Point(440.584, -314.392), 15);
+ connRef307->setSourceEndpoint(srcPt307);
+ ConnEnd dstPt307(Point(511.534, -169.392), 15);
+ connRef307->setDestEndpoint(dstPt307);
+ connRef307->setRoutingType((ConnType)2);
+
+ ConnRef *connRef308 = new ConnRef(router, 308);
+ ConnEnd srcPt308(Point(798.746, 335.608), 15);
+ connRef308->setSourceEndpoint(srcPt308);
+ ConnEnd dstPt308(Point(848.746, 429.608), 15);
+ connRef308->setDestEndpoint(dstPt308);
+ connRef308->setRoutingType((ConnType)2);
+
+ ConnRef *connRef297 = new ConnRef(router, 297);
+ ConnEnd srcPt297(Point(502.584, -261.392), 15);
+ connRef297->setSourceEndpoint(srcPt297);
+ ConnEnd dstPt297(Point(440.584, -261.392), 15);
+ connRef297->setDestEndpoint(dstPt297);
+ connRef297->setRoutingType((ConnType)2);
+
+ ConnRef *connRef298 = new ConnRef(router, 298);
+ ConnEnd srcPt298(Point(502.584, -414.392), 15);
+ connRef298->setSourceEndpoint(srcPt298);
+ ConnEnd dstPt298(Point(440.584, -414.392), 15);
+ connRef298->setDestEndpoint(dstPt298);
+ connRef298->setRoutingType((ConnType)2);
+
+ ConnRef *connRef216 = new ConnRef(router, 216);
+ ConnEnd srcPt216(Point(-8.01599, 383.608), 15);
+ connRef216->setSourceEndpoint(srcPt216);
+ ConnEnd dstPt216(Point(-8.01599, 445.608), 15);
+ connRef216->setDestEndpoint(dstPt216);
+ connRef216->setRoutingType((ConnType)2);
+
+ ConnRef *connRef217 = new ConnRef(router, 217);
+ ConnEnd srcPt217(Point(370.584, 236.608), 15);
+ connRef217->setSourceEndpoint(srcPt217);
+ ConnEnd dstPt217(Point(320.584, 184.608), 15);
+ connRef217->setDestEndpoint(dstPt217);
+ connRef217->setRoutingType((ConnType)2);
+
+ ConnRef *connRef209 = new ConnRef(router, 209);
+ ConnEnd srcPt209(Point(542.984, 690.465), 15);
+ connRef209->setSourceEndpoint(srcPt209);
+ ConnEnd dstPt209(Point(793.984, 683.608), 15);
+ connRef209->setDestEndpoint(dstPt209);
+ connRef209->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/overlappingRects");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/penaltyRerouting01.cpp b/src/3rdparty/adaptagrams/libavoid/tests/penaltyRerouting01.cpp
new file mode 100644
index 0000000..5dabad7
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/penaltyRerouting01.cpp
@@ -0,0 +1,369 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingParameter((RoutingParameter)0, 10);
+ router->setRoutingParameter((RoutingParameter)1, 0);
+ router->setRoutingParameter((RoutingParameter)2, 1e+09);
+ router->setRoutingParameter((RoutingParameter)3, 4000);
+ router->setRoutingParameter((RoutingParameter)4, 0);
+ router->setRoutingParameter((RoutingParameter)5, 0);
+ router->setRoutingParameter((RoutingParameter)6, 0);
+ router->setRoutingParameter((RoutingParameter)7, 4);
+ router->setRoutingParameter((RoutingParameter)8, 0);
+ router->setRoutingOption((RoutingOption)0, false);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, false);
+ router->setRoutingOption((RoutingOption)3, false);
+ router->setRoutingOption((RoutingOption)4, true);
+ router->setRoutingOption((RoutingOption)5, false);
+ router->setRoutingOption((RoutingOption)6, true);
+ Polygon polygon;
+ ConnRef *connRef = nullptr;
+ ConnEnd srcPt;
+ ConnEnd dstPt;
+ ConnEnd heConnPt;
+ PolyLine newRoute;
+
+ // shapeRef1
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(449, 491);
+ polygon.ps[1] = Point(479, 491);
+ polygon.ps[2] = Point(479, 521);
+ polygon.ps[3] = Point(449, 521);
+ new ShapeRef(router, polygon, 1);
+
+ // shapeRef1
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(449, 583);
+ polygon.ps[1] = Point(479, 583);
+ polygon.ps[2] = Point(479, 613);
+ polygon.ps[3] = Point(449, 613);
+ new ShapeRef(router, polygon, 1);
+
+ // shapeRef2
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(354, 583);
+ polygon.ps[1] = Point(384, 583);
+ polygon.ps[2] = Point(384, 613);
+ polygon.ps[3] = Point(354, 613);
+ new ShapeRef(router, polygon, 2);
+
+ // shapeRef3
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(354, 354);
+ polygon.ps[1] = Point(384, 354);
+ polygon.ps[2] = Point(384, 384);
+ polygon.ps[3] = Point(354, 384);
+ new ShapeRef(router, polygon, 3);
+
+ // shapeRef4
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(252.5, 354);
+ polygon.ps[1] = Point(282.5, 354);
+ polygon.ps[2] = Point(282.5, 384);
+ polygon.ps[3] = Point(252.5, 384);
+ new ShapeRef(router, polygon, 4);
+
+ // shapeRef5
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(252.5, 583);
+ polygon.ps[1] = Point(282.5, 583);
+ polygon.ps[2] = Point(282.5, 613);
+ polygon.ps[3] = Point(252.5, 613);
+ new ShapeRef(router, polygon, 5);
+
+ // shapeRef6
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(151, 583);
+ polygon.ps[1] = Point(181, 583);
+ polygon.ps[2] = Point(181, 613);
+ polygon.ps[3] = Point(151, 613);
+ new ShapeRef(router, polygon, 6);
+
+ // shapeRef7
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(151, 130);
+ polygon.ps[1] = Point(181, 130);
+ polygon.ps[2] = Point(181, 160);
+ polygon.ps[3] = Point(151, 160);
+ new ShapeRef(router, polygon, 7);
+
+ // shapeRef8
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(520, 491);
+ polygon.ps[1] = Point(550, 491);
+ polygon.ps[2] = Point(550, 521);
+ polygon.ps[3] = Point(520, 521);
+ new ShapeRef(router, polygon, 8);
+
+ // shapeRef9
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(520, 354);
+ polygon.ps[1] = Point(550, 354);
+ polygon.ps[2] = Point(550, 384);
+ polygon.ps[3] = Point(520, 384);
+ new ShapeRef(router, polygon, 9);
+
+ // shapeRef10
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(633, 354);
+ polygon.ps[1] = Point(663, 354);
+ polygon.ps[2] = Point(663, 384);
+ polygon.ps[3] = Point(633, 384);
+ new ShapeRef(router, polygon, 10);
+
+ // shapeRef11
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(633, 583);
+ polygon.ps[1] = Point(663, 583);
+ polygon.ps[2] = Point(663, 613);
+ polygon.ps[3] = Point(633, 613);
+ new ShapeRef(router, polygon, 11);
+
+ // shapeRef12
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(741, 583);
+ polygon.ps[1] = Point(771, 583);
+ polygon.ps[2] = Point(771, 613);
+ polygon.ps[3] = Point(741, 613);
+ new ShapeRef(router, polygon, 12);
+
+ // shapeRef13
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(741, 130);
+ polygon.ps[1] = Point(771, 130);
+ polygon.ps[2] = Point(771, 160);
+ polygon.ps[3] = Point(741, 160);
+ new ShapeRef(router, polygon, 13);
+
+ // shapeRef14
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(459.495, 481.99);
+ polygon.ps[1] = Point(468.505, 481.99);
+ polygon.ps[2] = Point(468.505, 491);
+ polygon.ps[3] = Point(459.495, 491);
+ new ShapeRef(router, polygon, 14);
+
+ // shapeRef15
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(212.495, 481.99);
+ polygon.ps[1] = Point(221.505, 481.99);
+ polygon.ps[2] = Point(221.505, 491);
+ polygon.ps[3] = Point(212.495, 491);
+ new ShapeRef(router, polygon, 15);
+
+ // shapeRef16
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(701.99, 481.99);
+ polygon.ps[1] = Point(711, 481.99);
+ polygon.ps[2] = Point(711, 491);
+ polygon.ps[3] = Point(701.99, 491);
+ new ShapeRef(router, polygon, 16);
+
+ // connRef17
+ connRef = new ConnRef(router, 17);
+ srcPt = ConnEnd(Point(464, 598), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(369, 598), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ newRoute._id = 17;
+ newRoute.ps.resize(2);
+ newRoute.ps[0] = Point(464, 598);
+ newRoute.ps[1] = Point(369, 598);
+ connRef->setFixedRoute(newRoute);
+
+ // connRef18
+ connRef = new ConnRef(router, 18);
+ srcPt = ConnEnd(Point(267.5, 598), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(166, 598), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ newRoute._id = 18;
+ newRoute.ps.resize(2);
+ newRoute.ps[0] = Point(267.5, 598);
+ newRoute.ps[1] = Point(166, 598);
+ connRef->setFixedRoute(newRoute);
+
+ // connRef19
+ connRef = new ConnRef(router, 19);
+ srcPt = ConnEnd(Point(369, 598), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(369, 369), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ newRoute._id = 19;
+ newRoute.ps.resize(2);
+ newRoute.ps[0] = Point(369, 598);
+ newRoute.ps[1] = Point(369, 369);
+ connRef->setFixedRoute(newRoute);
+
+ // connRef20
+ connRef = new ConnRef(router, 20);
+ srcPt = ConnEnd(Point(464, 506), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(464, 598), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ newRoute._id = 20;
+ newRoute.ps.resize(2);
+ newRoute.ps[0] = Point(464, 506);
+ newRoute.ps[1] = Point(464, 598);
+ connRef->setFixedRoute(newRoute);
+
+ // connRef21
+ connRef = new ConnRef(router, 21);
+ srcPt = ConnEnd(Point(756, 598), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(756, 145), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ newRoute._id = 21;
+ newRoute.ps.resize(2);
+ newRoute.ps[0] = Point(756, 598);
+ newRoute.ps[1] = Point(756, 145);
+ connRef->setFixedRoute(newRoute);
+
+ // connRef22
+ connRef = new ConnRef(router, 22);
+ srcPt = ConnEnd(Point(369, 369), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(267.5, 369), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ newRoute._id = 22;
+ newRoute.ps.resize(2);
+ newRoute.ps[0] = Point(369, 369);
+ newRoute.ps[1] = Point(267.5, 369);
+ connRef->setFixedRoute(newRoute);
+
+ // connRef23
+ connRef = new ConnRef(router, 23);
+ srcPt = ConnEnd(Point(166, 145), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(756, 145), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ newRoute._id = 23;
+ newRoute.ps.resize(2);
+ newRoute.ps[0] = Point(166, 145);
+ newRoute.ps[1] = Point(756, 145);
+ connRef->setFixedRoute(newRoute);
+
+ // connRef24
+ connRef = new ConnRef(router, 24);
+ srcPt = ConnEnd(Point(464, 486.495), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(706.495, 486.495), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef25
+ connRef = new ConnRef(router, 25);
+ srcPt = ConnEnd(Point(535, 369), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(535, 506), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ newRoute._id = 25;
+ newRoute.ps.resize(2);
+ newRoute.ps[0] = Point(535, 369);
+ newRoute.ps[1] = Point(535, 506);
+ connRef->setFixedRoute(newRoute);
+
+ // connRef26
+ connRef = new ConnRef(router, 26);
+ srcPt = ConnEnd(Point(648, 598), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(648, 369), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ newRoute._id = 26;
+ newRoute.ps.resize(2);
+ newRoute.ps[0] = Point(648, 598);
+ newRoute.ps[1] = Point(648, 369);
+ connRef->setFixedRoute(newRoute);
+
+ // connRef27
+ connRef = new ConnRef(router, 27);
+ srcPt = ConnEnd(Point(464, 486.495), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(217, 486.495), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef28
+ connRef = new ConnRef(router, 28);
+ srcPt = ConnEnd(Point(648, 598), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(756, 598), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ newRoute._id = 28;
+ newRoute.ps.resize(2);
+ newRoute.ps[0] = Point(648, 598);
+ newRoute.ps[1] = Point(756, 598);
+ connRef->setFixedRoute(newRoute);
+
+ // connRef29
+ connRef = new ConnRef(router, 29);
+ srcPt = ConnEnd(Point(166, 598), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(166, 145), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ newRoute._id = 29;
+ newRoute.ps.resize(2);
+ newRoute.ps[0] = Point(166, 598);
+ newRoute.ps[1] = Point(166, 145);
+ connRef->setFixedRoute(newRoute);
+
+ // connRef30
+ connRef = new ConnRef(router, 30);
+ srcPt = ConnEnd(Point(648, 369), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(535, 369), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ newRoute._id = 30;
+ newRoute.ps.resize(2);
+ newRoute.ps[0] = Point(648, 369);
+ newRoute.ps[1] = Point(535, 369);
+ connRef->setFixedRoute(newRoute);
+
+ // connRef31
+ connRef = new ConnRef(router, 31);
+ srcPt = ConnEnd(Point(267.5, 369), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(267.5, 598), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ newRoute._id = 31;
+ newRoute.ps.resize(2);
+ newRoute.ps[0] = Point(267.5, 369);
+ newRoute.ps[1] = Point(267.5, 598);
+ connRef->setFixedRoute(newRoute);
+
+ // connRef32
+ connRef = new ConnRef(router, 32);
+ srcPt = ConnEnd(Point(535, 506), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(464, 506), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+ newRoute._id = 32;
+ newRoute.ps.resize(2);
+ newRoute.ps[0] = Point(535, 506);
+ newRoute.ps[1] = Point(464, 506);
+ connRef->setFixedRoute(newRoute);
+
+ router->processTransaction();
+ router->outputDiagram("output/penaltyRerouting01");
+
+ int crossings = router->existsCrossings();
+
+ delete router;
+ return (crossings > 0) ? 1 : 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/performance01.cpp b/src/3rdparty/adaptagrams/libavoid/tests/performance01.cpp
new file mode 100644
index 0000000..df22037
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/performance01.cpp
@@ -0,0 +1,7665 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingParameter((RoutingParameter)0, 50);
+ router->setRoutingParameter((RoutingParameter)1, 0);
+ router->setRoutingParameter((RoutingParameter)2, 0);
+ router->setRoutingParameter((RoutingParameter)3, 4000);
+ router->setRoutingParameter((RoutingParameter)4, 0);
+ router->setRoutingParameter((RoutingParameter)5, 100);
+ router->setRoutingParameter((RoutingParameter)6, 0);
+ router->setRoutingParameter((RoutingParameter)7, 4);
+ router->setRoutingOption((RoutingOption)0, false);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, false);
+ router->setRoutingOption((RoutingOption)3, false);
+ Polygon polygon;
+ ConnRef *connRef = nullptr;
+ ConnEnd srcPt;
+ ConnEnd dstPt;
+ // shapeRef1
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1015.25, 612.918);
+ polygon.ps[1] = Point(1015.25, 632.918);
+ polygon.ps[2] = Point(995.246, 632.918);
+ polygon.ps[3] = Point(995.246, 612.918);
+ new ShapeRef(router, polygon, 1);
+
+ // shapeRef2
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(859.246, 612.918);
+ polygon.ps[1] = Point(859.246, 632.918);
+ polygon.ps[2] = Point(839.246, 632.918);
+ polygon.ps[3] = Point(839.246, 612.918);
+ new ShapeRef(router, polygon, 2);
+
+ // shapeRef3
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(703.246, 612.918);
+ polygon.ps[1] = Point(703.246, 632.918);
+ polygon.ps[2] = Point(683.246, 632.918);
+ polygon.ps[3] = Point(683.246, 612.918);
+ new ShapeRef(router, polygon, 3);
+
+ // shapeRef4
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(547.246, 612.918);
+ polygon.ps[1] = Point(547.246, 632.918);
+ polygon.ps[2] = Point(527.246, 632.918);
+ polygon.ps[3] = Point(527.246, 612.918);
+ new ShapeRef(router, polygon, 4);
+
+ // shapeRef5
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(391.246, 612.918);
+ polygon.ps[1] = Point(391.246, 632.918);
+ polygon.ps[2] = Point(371.246, 632.918);
+ polygon.ps[3] = Point(371.246, 612.918);
+ new ShapeRef(router, polygon, 5);
+
+ // shapeRef6
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(235.246, 612.918);
+ polygon.ps[1] = Point(235.246, 632.918);
+ polygon.ps[2] = Point(215.246, 632.918);
+ polygon.ps[3] = Point(215.246, 612.918);
+ new ShapeRef(router, polygon, 6);
+
+ // shapeRef7
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(77.2456, 644.918);
+ polygon.ps[1] = Point(77.2456, 664.918);
+ polygon.ps[2] = Point(57.2456, 664.918);
+ polygon.ps[3] = Point(57.2456, 644.918);
+ new ShapeRef(router, polygon, 7);
+
+ // shapeRef8
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1223.25, 656.918);
+ polygon.ps[1] = Point(1223.25, 696.918);
+ polygon.ps[2] = Point(1183.25, 696.918);
+ polygon.ps[3] = Point(1183.25, 656.918);
+ new ShapeRef(router, polygon, 8);
+
+ // shapeRef9
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1223.25, 538.918);
+ polygon.ps[1] = Point(1223.25, 578.918);
+ polygon.ps[2] = Point(1183.25, 578.918);
+ polygon.ps[3] = Point(1183.25, 538.918);
+ new ShapeRef(router, polygon, 9);
+
+ // shapeRef10
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1223.25, 427.955);
+ polygon.ps[1] = Point(1223.25, 467.955);
+ polygon.ps[2] = Point(1183.25, 467.955);
+ polygon.ps[3] = Point(1183.25, 427.955);
+ new ShapeRef(router, polygon, 10);
+
+ // shapeRef11
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1223.25, 312.918);
+ polygon.ps[1] = Point(1223.25, 352.918);
+ polygon.ps[2] = Point(1183.25, 352.918);
+ polygon.ps[3] = Point(1183.25, 312.918);
+ new ShapeRef(router, polygon, 11);
+
+ // shapeRef12
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1469.25, 730.918);
+ polygon.ps[1] = Point(1469.25, 770.918);
+ polygon.ps[2] = Point(1429.25, 770.918);
+ polygon.ps[3] = Point(1429.25, 730.918);
+ new ShapeRef(router, polygon, 12);
+
+ // shapeRef13
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1223.25, 730.918);
+ polygon.ps[1] = Point(1223.25, 770.918);
+ polygon.ps[2] = Point(1183.25, 770.918);
+ polygon.ps[3] = Point(1183.25, 730.918);
+ new ShapeRef(router, polygon, 13);
+
+ // shapeRef14
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1191.25, 730.918);
+ polygon.ps[1] = Point(1191.25, 770.918);
+ polygon.ps[2] = Point(1151.25, 770.918);
+ polygon.ps[3] = Point(1151.25, 730.918);
+ new ShapeRef(router, polygon, 14);
+
+ // shapeRef15
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1469.25, 656.918);
+ polygon.ps[1] = Point(1469.25, 696.918);
+ polygon.ps[2] = Point(1429.25, 696.918);
+ polygon.ps[3] = Point(1429.25, 656.918);
+ new ShapeRef(router, polygon, 15);
+
+ // shapeRef16
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1191.25, 656.918);
+ polygon.ps[1] = Point(1191.25, 696.918);
+ polygon.ps[2] = Point(1151.25, 696.918);
+ polygon.ps[3] = Point(1151.25, 656.918);
+ new ShapeRef(router, polygon, 16);
+
+ // shapeRef17
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(843.246, 730.918);
+ polygon.ps[1] = Point(843.246, 770.918);
+ polygon.ps[2] = Point(803.246, 770.918);
+ polygon.ps[3] = Point(803.246, 730.918);
+ new ShapeRef(router, polygon, 17);
+
+ // shapeRef18
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(693.933, 730.918);
+ polygon.ps[1] = Point(693.933, 770.918);
+ polygon.ps[2] = Point(653.933, 770.918);
+ polygon.ps[3] = Point(653.933, 730.918);
+ new ShapeRef(router, polygon, 18);
+
+ // shapeRef19
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(547.246, 730.918);
+ polygon.ps[1] = Point(547.246, 770.918);
+ polygon.ps[2] = Point(507.246, 770.918);
+ polygon.ps[3] = Point(507.246, 730.918);
+ new ShapeRef(router, polygon, 19);
+
+ // shapeRef20
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(391.246, 730.918);
+ polygon.ps[1] = Point(391.246, 770.918);
+ polygon.ps[2] = Point(351.246, 770.918);
+ polygon.ps[3] = Point(351.246, 730.918);
+ new ShapeRef(router, polygon, 20);
+
+ // shapeRef21
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(811.246, 708.918);
+ polygon.ps[1] = Point(811.246, 728.918);
+ polygon.ps[2] = Point(791.246, 728.918);
+ polygon.ps[3] = Point(791.246, 708.918);
+ new ShapeRef(router, polygon, 21);
+
+ // shapeRef22
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1171.25, 708.918);
+ polygon.ps[1] = Point(1171.25, 728.918);
+ polygon.ps[2] = Point(1151.25, 728.918);
+ polygon.ps[3] = Point(1151.25, 708.918);
+ new ShapeRef(router, polygon, 22);
+
+ // shapeRef23
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1183.25, 708.918);
+ polygon.ps[1] = Point(1183.25, 728.918);
+ polygon.ps[2] = Point(1163.25, 728.918);
+ polygon.ps[3] = Point(1163.25, 708.918);
+ new ShapeRef(router, polygon, 23);
+
+ // shapeRef24
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(537.246, 708.918);
+ polygon.ps[1] = Point(537.246, 728.918);
+ polygon.ps[2] = Point(517.246, 728.918);
+ polygon.ps[3] = Point(517.246, 708.918);
+ new ShapeRef(router, polygon, 24);
+
+ // shapeRef25
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(381.246, 708.918);
+ polygon.ps[1] = Point(381.246, 728.918);
+ polygon.ps[2] = Point(361.246, 728.918);
+ polygon.ps[3] = Point(361.246, 708.918);
+ new ShapeRef(router, polygon, 25);
+
+ // shapeRef26
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1381.25, 666.918);
+ polygon.ps[1] = Point(1381.25, 686.918);
+ polygon.ps[2] = Point(1361.25, 686.918);
+ polygon.ps[3] = Point(1361.25, 666.918);
+ new ShapeRef(router, polygon, 26);
+
+ // shapeRef27
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1303.25, 565.942);
+ polygon.ps[1] = Point(1303.25, 585.942);
+ polygon.ps[2] = Point(1283.25, 585.942);
+ polygon.ps[3] = Point(1283.25, 565.942);
+ new ShapeRef(router, polygon, 27);
+
+ // shapeRef28
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1015.25, 644.918);
+ polygon.ps[1] = Point(1015.25, 664.918);
+ polygon.ps[2] = Point(995.246, 664.918);
+ polygon.ps[3] = Point(995.246, 644.918);
+ new ShapeRef(router, polygon, 28);
+
+ // shapeRef29
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(859.246, 644.918);
+ polygon.ps[1] = Point(859.246, 664.918);
+ polygon.ps[2] = Point(839.246, 664.918);
+ polygon.ps[3] = Point(839.246, 644.918);
+ new ShapeRef(router, polygon, 29);
+
+ // shapeRef30
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(703.246, 644.918);
+ polygon.ps[1] = Point(703.246, 664.918);
+ polygon.ps[2] = Point(683.246, 664.918);
+ polygon.ps[3] = Point(683.246, 644.918);
+ new ShapeRef(router, polygon, 30);
+
+ // shapeRef31
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(547.246, 644.918);
+ polygon.ps[1] = Point(547.246, 664.918);
+ polygon.ps[2] = Point(527.246, 664.918);
+ polygon.ps[3] = Point(527.246, 644.918);
+ new ShapeRef(router, polygon, 31);
+
+ // shapeRef32
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(391.246, 644.918);
+ polygon.ps[1] = Point(391.246, 664.918);
+ polygon.ps[2] = Point(371.246, 664.918);
+ polygon.ps[3] = Point(371.246, 644.918);
+ new ShapeRef(router, polygon, 32);
+
+ // shapeRef33
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(235.246, 644.918);
+ polygon.ps[1] = Point(235.246, 664.918);
+ polygon.ps[2] = Point(215.246, 664.918);
+ polygon.ps[3] = Point(215.246, 644.918);
+ new ShapeRef(router, polygon, 33);
+
+ // shapeRef34
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(77.2456, 612.918);
+ polygon.ps[1] = Point(77.2456, 632.918);
+ polygon.ps[2] = Point(57.2456, 632.918);
+ polygon.ps[3] = Point(57.2456, 612.918);
+ new ShapeRef(router, polygon, 34);
+
+ // shapeRef35
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1303.25, 504.918);
+ polygon.ps[1] = Point(1303.25, 524.918);
+ polygon.ps[2] = Point(1283.25, 524.918);
+ polygon.ps[3] = Point(1283.25, 504.918);
+ new ShapeRef(router, polygon, 35);
+
+ // shapeRef36
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1015.25, 526.918);
+ polygon.ps[1] = Point(1015.25, 546.918);
+ polygon.ps[2] = Point(995.246, 546.918);
+ polygon.ps[3] = Point(995.246, 526.918);
+ new ShapeRef(router, polygon, 36);
+
+ // shapeRef37
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(859.246, 526.918);
+ polygon.ps[1] = Point(859.246, 546.918);
+ polygon.ps[2] = Point(839.246, 546.918);
+ polygon.ps[3] = Point(839.246, 526.918);
+ new ShapeRef(router, polygon, 37);
+
+ // shapeRef38
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(703.246, 526.918);
+ polygon.ps[1] = Point(703.246, 546.918);
+ polygon.ps[2] = Point(683.246, 546.918);
+ polygon.ps[3] = Point(683.246, 526.918);
+ new ShapeRef(router, polygon, 38);
+
+ // shapeRef39
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(547.246, 526.918);
+ polygon.ps[1] = Point(547.246, 546.918);
+ polygon.ps[2] = Point(527.246, 546.918);
+ polygon.ps[3] = Point(527.246, 526.918);
+ new ShapeRef(router, polygon, 39);
+
+ // shapeRef40
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(391.246, 526.918);
+ polygon.ps[1] = Point(391.246, 546.918);
+ polygon.ps[2] = Point(371.246, 546.918);
+ polygon.ps[3] = Point(371.246, 526.918);
+ new ShapeRef(router, polygon, 40);
+
+ // shapeRef41
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(235.246, 526.918);
+ polygon.ps[1] = Point(235.246, 546.918);
+ polygon.ps[2] = Point(215.246, 546.918);
+ polygon.ps[3] = Point(215.246, 526.918);
+ new ShapeRef(router, polygon, 41);
+
+ // shapeRef42
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(77.2456, 526.918);
+ polygon.ps[1] = Point(77.2456, 546.918);
+ polygon.ps[2] = Point(57.2456, 546.918);
+ polygon.ps[3] = Point(57.2456, 526.918);
+ new ShapeRef(router, polygon, 42);
+
+ // shapeRef43
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1303.25, 278.918);
+ polygon.ps[1] = Point(1303.25, 298.918);
+ polygon.ps[2] = Point(1283.25, 298.918);
+ polygon.ps[3] = Point(1283.25, 278.918);
+ new ShapeRef(router, polygon, 43);
+
+ // shapeRef44
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1093.25, 666.918);
+ polygon.ps[1] = Point(1093.25, 686.918);
+ polygon.ps[2] = Point(1073.25, 686.918);
+ polygon.ps[3] = Point(1073.25, 666.918);
+ new ShapeRef(router, polygon, 44);
+
+ // shapeRef45
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1303.25, 408.918);
+ polygon.ps[1] = Point(1303.25, 428.918);
+ polygon.ps[2] = Point(1283.25, 428.918);
+ polygon.ps[3] = Point(1283.25, 408.918);
+ new ShapeRef(router, polygon, 45);
+
+ // shapeRef46
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1303.25, 708.918);
+ polygon.ps[1] = Point(1303.25, 728.918);
+ polygon.ps[2] = Point(1283.25, 728.918);
+ polygon.ps[3] = Point(1283.25, 708.918);
+ new ShapeRef(router, polygon, 46);
+
+ // shapeRef47
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1459.25, 708.918);
+ polygon.ps[1] = Point(1459.25, 728.918);
+ polygon.ps[2] = Point(1439.25, 728.918);
+ polygon.ps[3] = Point(1439.25, 708.918);
+ new ShapeRef(router, polygon, 47);
+
+ // shapeRef48
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(655.246, 708.918);
+ polygon.ps[1] = Point(655.246, 728.918);
+ polygon.ps[2] = Point(635.246, 728.918);
+ polygon.ps[3] = Point(635.246, 708.918);
+ new ShapeRef(router, polygon, 48);
+
+ // shapeRef49
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(859.246, 708.918);
+ polygon.ps[1] = Point(859.246, 728.918);
+ polygon.ps[2] = Point(839.246, 728.918);
+ polygon.ps[3] = Point(839.246, 708.918);
+ new ShapeRef(router, polygon, 49);
+
+ // shapeRef50
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(77.2456, 22.9179);
+ polygon.ps[1] = Point(77.2456, 42.9179);
+ polygon.ps[2] = Point(57.2456, 42.9179);
+ polygon.ps[3] = Point(57.2456, 22.9179);
+ new ShapeRef(router, polygon, 50);
+
+ // shapeRef51
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(77.2456, 300.918);
+ polygon.ps[1] = Point(77.2456, 320.918);
+ polygon.ps[2] = Point(57.2456, 320.918);
+ polygon.ps[3] = Point(57.2456, 300.918);
+ new ShapeRef(router, polygon, 51);
+
+ // shapeRef52
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1015.25, 278.918);
+ polygon.ps[1] = Point(1015.25, 298.918);
+ polygon.ps[2] = Point(995.246, 298.918);
+ polygon.ps[3] = Point(995.246, 278.918);
+ new ShapeRef(router, polygon, 52);
+
+ // shapeRef53
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(859.246, 278.918);
+ polygon.ps[1] = Point(859.246, 298.918);
+ polygon.ps[2] = Point(839.246, 298.918);
+ polygon.ps[3] = Point(839.246, 278.918);
+ new ShapeRef(router, polygon, 53);
+
+ // shapeRef54
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(703.246, 278.918);
+ polygon.ps[1] = Point(703.246, 298.918);
+ polygon.ps[2] = Point(683.246, 298.918);
+ polygon.ps[3] = Point(683.246, 278.918);
+ new ShapeRef(router, polygon, 54);
+
+ // shapeRef55
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(547.246, 278.918);
+ polygon.ps[1] = Point(547.246, 298.918);
+ polygon.ps[2] = Point(527.246, 298.918);
+ polygon.ps[3] = Point(527.246, 278.918);
+ new ShapeRef(router, polygon, 55);
+
+ // shapeRef56
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(391.246, 278.918);
+ polygon.ps[1] = Point(391.246, 298.918);
+ polygon.ps[2] = Point(371.246, 298.918);
+ polygon.ps[3] = Point(371.246, 278.918);
+ new ShapeRef(router, polygon, 56);
+
+ // shapeRef57
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(235.246, 278.918);
+ polygon.ps[1] = Point(235.246, 298.918);
+ polygon.ps[2] = Point(215.246, 298.918);
+ polygon.ps[3] = Point(215.246, 278.918);
+ new ShapeRef(router, polygon, 57);
+
+ // shapeRef58
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1047.75, 767.422);
+ polygon.ps[1] = Point(1047.75, 802.422);
+ polygon.ps[2] = Point(910.746, 802.422);
+ polygon.ps[3] = Point(910.746, 767.422);
+ new ShapeRef(router, polygon, 58);
+
+ // shapeRef59
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(207.246, -128.082);
+ polygon.ps[1] = Point(207.246, -93.0821);
+ polygon.ps[2] = Point(-12.7544, -93.0821);
+ polygon.ps[3] = Point(-12.7544, -128.082);
+ new ShapeRef(router, polygon, 59);
+
+ // shapeRef60
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(590.455, 4.91795);
+ polygon.ps[1] = Point(590.455, 64.9179);
+ polygon.ps[2] = Point(312.455, 64.9179);
+ polygon.ps[3] = Point(312.455, 4.91795);
+ new ShapeRef(router, polygon, 60);
+
+ // shapeRef61
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(222.246, -101.082);
+ polygon.ps[1] = Point(222.246, -41.0821);
+ polygon.ps[2] = Point(-12.7544, -41.0821);
+ polygon.ps[3] = Point(-12.7544, -101.082);
+ new ShapeRef(router, polygon, 61);
+
+ // shapeRef62
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1015.25, 708.918);
+ polygon.ps[1] = Point(1015.25, 728.918);
+ polygon.ps[2] = Point(995.246, 728.918);
+ polygon.ps[3] = Point(995.246, 708.918);
+ new ShapeRef(router, polygon, 62);
+
+ // shapeRef63
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(967.246, 676.918);
+ polygon.ps[1] = Point(967.246, 696.918);
+ polygon.ps[2] = Point(947.246, 696.918);
+ polygon.ps[3] = Point(947.246, 676.918);
+ new ShapeRef(router, polygon, 63);
+
+ // shapeRef64
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1015.25, 580.918);
+ polygon.ps[1] = Point(1015.25, 600.918);
+ polygon.ps[2] = Point(995.246, 600.918);
+ polygon.ps[3] = Point(995.246, 580.918);
+ new ShapeRef(router, polygon, 64);
+
+ // shapeRef65
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(967.246, 612.918);
+ polygon.ps[1] = Point(967.246, 632.918);
+ polygon.ps[2] = Point(947.246, 632.918);
+ polygon.ps[3] = Point(947.246, 612.918);
+ new ShapeRef(router, polygon, 65);
+
+ // shapeRef66
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(967.246, 580.918);
+ polygon.ps[1] = Point(967.246, 600.918);
+ polygon.ps[2] = Point(947.246, 600.918);
+ polygon.ps[3] = Point(947.246, 580.918);
+ new ShapeRef(router, polygon, 66);
+
+ // shapeRef67
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(967.246, 504.918);
+ polygon.ps[1] = Point(967.246, 524.918);
+ polygon.ps[2] = Point(947.246, 524.918);
+ polygon.ps[3] = Point(947.246, 504.918);
+ new ShapeRef(router, polygon, 67);
+
+ // shapeRef68
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(967.246, 472.918);
+ polygon.ps[1] = Point(967.246, 492.918);
+ polygon.ps[2] = Point(947.246, 492.918);
+ polygon.ps[3] = Point(947.246, 472.918);
+ new ShapeRef(router, polygon, 68);
+
+ // shapeRef69
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1015.25, 408.918);
+ polygon.ps[1] = Point(1015.25, 428.918);
+ polygon.ps[2] = Point(995.246, 428.918);
+ polygon.ps[3] = Point(995.246, 408.918);
+ new ShapeRef(router, polygon, 69);
+
+ // shapeRef70
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(967.246, 408.918);
+ polygon.ps[1] = Point(967.246, 428.918);
+ polygon.ps[2] = Point(947.246, 428.918);
+ polygon.ps[3] = Point(947.246, 408.918);
+ new ShapeRef(router, polygon, 70);
+
+ // shapeRef71
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(967.246, 376.918);
+ polygon.ps[1] = Point(967.246, 396.918);
+ polygon.ps[2] = Point(947.246, 396.918);
+ polygon.ps[3] = Point(947.246, 376.918);
+ new ShapeRef(router, polygon, 71);
+
+ // shapeRef72
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1015.25, 246.918);
+ polygon.ps[1] = Point(1015.25, 266.918);
+ polygon.ps[2] = Point(995.246, 266.918);
+ polygon.ps[3] = Point(995.246, 246.918);
+ new ShapeRef(router, polygon, 72);
+
+ // shapeRef73
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(967.246, 268.918);
+ polygon.ps[1] = Point(967.246, 288.918);
+ polygon.ps[2] = Point(947.246, 288.918);
+ polygon.ps[3] = Point(947.246, 268.918);
+ new ShapeRef(router, polygon, 73);
+
+ // shapeRef74
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(967.246, 236.918);
+ polygon.ps[1] = Point(967.246, 256.918);
+ polygon.ps[2] = Point(947.246, 256.918);
+ polygon.ps[3] = Point(947.246, 236.918);
+ new ShapeRef(router, polygon, 74);
+
+ // shapeRef75
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(859.246, 580.918);
+ polygon.ps[1] = Point(859.246, 600.918);
+ polygon.ps[2] = Point(839.246, 600.918);
+ polygon.ps[3] = Point(839.246, 580.918);
+ new ShapeRef(router, polygon, 75);
+
+ // shapeRef76
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(811.246, 612.918);
+ polygon.ps[1] = Point(811.246, 632.918);
+ polygon.ps[2] = Point(791.246, 632.918);
+ polygon.ps[3] = Point(791.246, 612.918);
+ new ShapeRef(router, polygon, 76);
+
+ // shapeRef77
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(811.246, 580.918);
+ polygon.ps[1] = Point(811.246, 600.918);
+ polygon.ps[2] = Point(791.246, 600.918);
+ polygon.ps[3] = Point(791.246, 580.918);
+ new ShapeRef(router, polygon, 77);
+
+ // shapeRef78
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(811.246, 504.918);
+ polygon.ps[1] = Point(811.246, 524.918);
+ polygon.ps[2] = Point(791.246, 524.918);
+ polygon.ps[3] = Point(791.246, 504.918);
+ new ShapeRef(router, polygon, 78);
+
+ // shapeRef79
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(811.246, 472.918);
+ polygon.ps[1] = Point(811.246, 492.918);
+ polygon.ps[2] = Point(791.246, 492.918);
+ polygon.ps[3] = Point(791.246, 472.918);
+ new ShapeRef(router, polygon, 79);
+
+ // shapeRef80
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(859.246, 408.918);
+ polygon.ps[1] = Point(859.246, 428.918);
+ polygon.ps[2] = Point(839.246, 428.918);
+ polygon.ps[3] = Point(839.246, 408.918);
+ new ShapeRef(router, polygon, 80);
+
+ // shapeRef81
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(811.246, 408.918);
+ polygon.ps[1] = Point(811.246, 428.918);
+ polygon.ps[2] = Point(791.246, 428.918);
+ polygon.ps[3] = Point(791.246, 408.918);
+ new ShapeRef(router, polygon, 81);
+
+ // shapeRef82
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(811.246, 376.918);
+ polygon.ps[1] = Point(811.246, 396.918);
+ polygon.ps[2] = Point(791.246, 396.918);
+ polygon.ps[3] = Point(791.246, 376.918);
+ new ShapeRef(router, polygon, 82);
+
+ // shapeRef83
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(859.246, 246.918);
+ polygon.ps[1] = Point(859.246, 266.918);
+ polygon.ps[2] = Point(839.246, 266.918);
+ polygon.ps[3] = Point(839.246, 246.918);
+ new ShapeRef(router, polygon, 83);
+
+ // shapeRef84
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(811.246, 268.918);
+ polygon.ps[1] = Point(811.246, 288.918);
+ polygon.ps[2] = Point(791.246, 288.918);
+ polygon.ps[3] = Point(791.246, 268.918);
+ new ShapeRef(router, polygon, 84);
+
+ // shapeRef85
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(811.246, 236.918);
+ polygon.ps[1] = Point(811.246, 256.918);
+ polygon.ps[2] = Point(791.246, 256.918);
+ polygon.ps[3] = Point(791.246, 236.918);
+ new ShapeRef(router, polygon, 85);
+
+ // shapeRef86
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(703.246, 580.918);
+ polygon.ps[1] = Point(703.246, 600.918);
+ polygon.ps[2] = Point(683.246, 600.918);
+ polygon.ps[3] = Point(683.246, 580.918);
+ new ShapeRef(router, polygon, 86);
+
+ // shapeRef87
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(655.246, 612.918);
+ polygon.ps[1] = Point(655.246, 632.918);
+ polygon.ps[2] = Point(635.246, 632.918);
+ polygon.ps[3] = Point(635.246, 612.918);
+ new ShapeRef(router, polygon, 87);
+
+ // shapeRef88
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(655.246, 580.918);
+ polygon.ps[1] = Point(655.246, 600.918);
+ polygon.ps[2] = Point(635.246, 600.918);
+ polygon.ps[3] = Point(635.246, 580.918);
+ new ShapeRef(router, polygon, 88);
+
+ // shapeRef89
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(655.246, 504.918);
+ polygon.ps[1] = Point(655.246, 524.918);
+ polygon.ps[2] = Point(635.246, 524.918);
+ polygon.ps[3] = Point(635.246, 504.918);
+ new ShapeRef(router, polygon, 89);
+
+ // shapeRef90
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(655.246, 472.918);
+ polygon.ps[1] = Point(655.246, 492.918);
+ polygon.ps[2] = Point(635.246, 492.918);
+ polygon.ps[3] = Point(635.246, 472.918);
+ new ShapeRef(router, polygon, 90);
+
+ // shapeRef91
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(703.246, 408.918);
+ polygon.ps[1] = Point(703.246, 428.918);
+ polygon.ps[2] = Point(683.246, 428.918);
+ polygon.ps[3] = Point(683.246, 408.918);
+ new ShapeRef(router, polygon, 91);
+
+ // shapeRef92
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(655.246, 408.918);
+ polygon.ps[1] = Point(655.246, 428.918);
+ polygon.ps[2] = Point(635.246, 428.918);
+ polygon.ps[3] = Point(635.246, 408.918);
+ new ShapeRef(router, polygon, 92);
+
+ // shapeRef93
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(655.246, 376.918);
+ polygon.ps[1] = Point(655.246, 396.918);
+ polygon.ps[2] = Point(635.246, 396.918);
+ polygon.ps[3] = Point(635.246, 376.918);
+ new ShapeRef(router, polygon, 93);
+
+ // shapeRef94
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(703.246, 246.918);
+ polygon.ps[1] = Point(703.246, 266.918);
+ polygon.ps[2] = Point(683.246, 266.918);
+ polygon.ps[3] = Point(683.246, 246.918);
+ new ShapeRef(router, polygon, 94);
+
+ // shapeRef95
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(655.246, 268.918);
+ polygon.ps[1] = Point(655.246, 288.918);
+ polygon.ps[2] = Point(635.246, 288.918);
+ polygon.ps[3] = Point(635.246, 268.918);
+ new ShapeRef(router, polygon, 95);
+
+ // shapeRef96
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(655.246, 236.918);
+ polygon.ps[1] = Point(655.246, 256.918);
+ polygon.ps[2] = Point(635.246, 256.918);
+ polygon.ps[3] = Point(635.246, 236.918);
+ new ShapeRef(router, polygon, 96);
+
+ // shapeRef97
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(547.246, 580.918);
+ polygon.ps[1] = Point(547.246, 600.918);
+ polygon.ps[2] = Point(527.246, 600.918);
+ polygon.ps[3] = Point(527.246, 580.918);
+ new ShapeRef(router, polygon, 97);
+
+ // shapeRef98
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(499.246, 612.918);
+ polygon.ps[1] = Point(499.246, 632.918);
+ polygon.ps[2] = Point(479.246, 632.918);
+ polygon.ps[3] = Point(479.246, 612.918);
+ new ShapeRef(router, polygon, 98);
+
+ // shapeRef99
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(499.246, 580.918);
+ polygon.ps[1] = Point(499.246, 600.918);
+ polygon.ps[2] = Point(479.246, 600.918);
+ polygon.ps[3] = Point(479.246, 580.918);
+ new ShapeRef(router, polygon, 99);
+
+ // shapeRef100
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(547.246, 476.951);
+ polygon.ps[1] = Point(547.246, 496.951);
+ polygon.ps[2] = Point(527.246, 496.951);
+ polygon.ps[3] = Point(527.246, 476.951);
+ new ShapeRef(router, polygon, 100);
+
+ // shapeRef101
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(499.246, 504.918);
+ polygon.ps[1] = Point(499.246, 524.918);
+ polygon.ps[2] = Point(479.246, 524.918);
+ polygon.ps[3] = Point(479.246, 504.918);
+ new ShapeRef(router, polygon, 101);
+
+ // shapeRef102
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(499.246, 472.918);
+ polygon.ps[1] = Point(499.246, 492.918);
+ polygon.ps[2] = Point(479.246, 492.918);
+ polygon.ps[3] = Point(479.246, 472.918);
+ new ShapeRef(router, polygon, 102);
+
+ // shapeRef103
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(547.246, 408.918);
+ polygon.ps[1] = Point(547.246, 428.918);
+ polygon.ps[2] = Point(527.246, 428.918);
+ polygon.ps[3] = Point(527.246, 408.918);
+ new ShapeRef(router, polygon, 103);
+
+ // shapeRef104
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(499.246, 408.918);
+ polygon.ps[1] = Point(499.246, 428.918);
+ polygon.ps[2] = Point(479.246, 428.918);
+ polygon.ps[3] = Point(479.246, 408.918);
+ new ShapeRef(router, polygon, 104);
+
+ // shapeRef105
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(499.246, 376.918);
+ polygon.ps[1] = Point(499.246, 396.918);
+ polygon.ps[2] = Point(479.246, 396.918);
+ polygon.ps[3] = Point(479.246, 376.918);
+ new ShapeRef(router, polygon, 105);
+
+ // shapeRef106
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(547.246, 246.918);
+ polygon.ps[1] = Point(547.246, 266.918);
+ polygon.ps[2] = Point(527.246, 266.918);
+ polygon.ps[3] = Point(527.246, 246.918);
+ new ShapeRef(router, polygon, 106);
+
+ // shapeRef107
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(499.246, 268.918);
+ polygon.ps[1] = Point(499.246, 288.918);
+ polygon.ps[2] = Point(479.246, 288.918);
+ polygon.ps[3] = Point(479.246, 268.918);
+ new ShapeRef(router, polygon, 107);
+
+ // shapeRef108
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(499.246, 236.918);
+ polygon.ps[1] = Point(499.246, 256.918);
+ polygon.ps[2] = Point(479.246, 256.918);
+ polygon.ps[3] = Point(479.246, 236.918);
+ new ShapeRef(router, polygon, 108);
+
+ // shapeRef109
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(391.246, 580.918);
+ polygon.ps[1] = Point(391.246, 600.918);
+ polygon.ps[2] = Point(371.246, 600.918);
+ polygon.ps[3] = Point(371.246, 580.918);
+ new ShapeRef(router, polygon, 109);
+
+ // shapeRef110
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(343.246, 612.918);
+ polygon.ps[1] = Point(343.246, 632.918);
+ polygon.ps[2] = Point(323.246, 632.918);
+ polygon.ps[3] = Point(323.246, 612.918);
+ new ShapeRef(router, polygon, 110);
+
+ // shapeRef111
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(343.246, 580.918);
+ polygon.ps[1] = Point(343.246, 600.918);
+ polygon.ps[2] = Point(323.246, 600.918);
+ polygon.ps[3] = Point(323.246, 580.918);
+ new ShapeRef(router, polygon, 111);
+
+ // shapeRef112
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(343.246, 504.918);
+ polygon.ps[1] = Point(343.246, 524.918);
+ polygon.ps[2] = Point(323.246, 524.918);
+ polygon.ps[3] = Point(323.246, 504.918);
+ new ShapeRef(router, polygon, 112);
+
+ // shapeRef113
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(343.246, 472.918);
+ polygon.ps[1] = Point(343.246, 492.918);
+ polygon.ps[2] = Point(323.246, 492.918);
+ polygon.ps[3] = Point(323.246, 472.918);
+ new ShapeRef(router, polygon, 113);
+
+ // shapeRef114
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(391.246, 408.918);
+ polygon.ps[1] = Point(391.246, 428.918);
+ polygon.ps[2] = Point(371.246, 428.918);
+ polygon.ps[3] = Point(371.246, 408.918);
+ new ShapeRef(router, polygon, 114);
+
+ // shapeRef115
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(343.246, 408.918);
+ polygon.ps[1] = Point(343.246, 428.918);
+ polygon.ps[2] = Point(323.246, 428.918);
+ polygon.ps[3] = Point(323.246, 408.918);
+ new ShapeRef(router, polygon, 115);
+
+ // shapeRef116
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(343.246, 376.918);
+ polygon.ps[1] = Point(343.246, 396.918);
+ polygon.ps[2] = Point(323.246, 396.918);
+ polygon.ps[3] = Point(323.246, 376.918);
+ new ShapeRef(router, polygon, 116);
+
+ // shapeRef117
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(391.246, 246.918);
+ polygon.ps[1] = Point(391.246, 266.918);
+ polygon.ps[2] = Point(371.246, 266.918);
+ polygon.ps[3] = Point(371.246, 246.918);
+ new ShapeRef(router, polygon, 117);
+
+ // shapeRef118
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(343.246, 268.918);
+ polygon.ps[1] = Point(343.246, 288.918);
+ polygon.ps[2] = Point(323.246, 288.918);
+ polygon.ps[3] = Point(323.246, 268.918);
+ new ShapeRef(router, polygon, 118);
+
+ // shapeRef119
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(343.246, 236.918);
+ polygon.ps[1] = Point(343.246, 256.918);
+ polygon.ps[2] = Point(323.246, 256.918);
+ polygon.ps[3] = Point(323.246, 236.918);
+ new ShapeRef(router, polygon, 119);
+
+ // shapeRef120
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(235.246, 580.918);
+ polygon.ps[1] = Point(235.246, 600.918);
+ polygon.ps[2] = Point(215.246, 600.918);
+ polygon.ps[3] = Point(215.246, 580.918);
+ new ShapeRef(router, polygon, 120);
+
+ // shapeRef121
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(203.246, 612.918);
+ polygon.ps[1] = Point(203.246, 632.918);
+ polygon.ps[2] = Point(183.246, 632.918);
+ polygon.ps[3] = Point(183.246, 612.918);
+ new ShapeRef(router, polygon, 121);
+
+ // shapeRef122
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(203.246, 580.918);
+ polygon.ps[1] = Point(203.246, 600.918);
+ polygon.ps[2] = Point(183.246, 600.918);
+ polygon.ps[3] = Point(183.246, 580.918);
+ new ShapeRef(router, polygon, 122);
+
+ // shapeRef123
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(203.246, 504.918);
+ polygon.ps[1] = Point(203.246, 524.918);
+ polygon.ps[2] = Point(183.246, 524.918);
+ polygon.ps[3] = Point(183.246, 504.918);
+ new ShapeRef(router, polygon, 123);
+
+ // shapeRef124
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(203.246, 472.918);
+ polygon.ps[1] = Point(203.246, 492.918);
+ polygon.ps[2] = Point(183.246, 492.918);
+ polygon.ps[3] = Point(183.246, 472.918);
+ new ShapeRef(router, polygon, 124);
+
+ // shapeRef125
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(235.246, 408.918);
+ polygon.ps[1] = Point(235.246, 428.918);
+ polygon.ps[2] = Point(215.246, 428.918);
+ polygon.ps[3] = Point(215.246, 408.918);
+ new ShapeRef(router, polygon, 125);
+
+ // shapeRef126
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(203.246, 408.918);
+ polygon.ps[1] = Point(203.246, 428.918);
+ polygon.ps[2] = Point(183.246, 428.918);
+ polygon.ps[3] = Point(183.246, 408.918);
+ new ShapeRef(router, polygon, 126);
+
+ // shapeRef127
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(203.246, 376.918);
+ polygon.ps[1] = Point(203.246, 396.918);
+ polygon.ps[2] = Point(183.246, 396.918);
+ polygon.ps[3] = Point(183.246, 376.918);
+ new ShapeRef(router, polygon, 127);
+
+ // shapeRef128
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(235.246, 246.918);
+ polygon.ps[1] = Point(235.246, 266.918);
+ polygon.ps[2] = Point(215.246, 266.918);
+ polygon.ps[3] = Point(215.246, 246.918);
+ new ShapeRef(router, polygon, 128);
+
+ // shapeRef129
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(203.246, 236.918);
+ polygon.ps[1] = Point(203.246, 256.918);
+ polygon.ps[2] = Point(183.246, 256.918);
+ polygon.ps[3] = Point(183.246, 236.918);
+ new ShapeRef(router, polygon, 129);
+
+ // shapeRef130
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(203.246, 268.918);
+ polygon.ps[1] = Point(203.246, 288.918);
+ polygon.ps[2] = Point(183.246, 288.918);
+ polygon.ps[3] = Point(183.246, 268.918);
+ new ShapeRef(router, polygon, 130);
+
+ // shapeRef131
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(77.2456, 580.918);
+ polygon.ps[1] = Point(77.2456, 600.918);
+ polygon.ps[2] = Point(57.2456, 600.918);
+ polygon.ps[3] = Point(57.2456, 580.918);
+ new ShapeRef(router, polygon, 131);
+
+ // shapeRef132
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(27.2456, 612.918);
+ polygon.ps[1] = Point(27.2456, 632.918);
+ polygon.ps[2] = Point(7.24557, 632.918);
+ polygon.ps[3] = Point(7.24557, 612.918);
+ new ShapeRef(router, polygon, 132);
+
+ // shapeRef133
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(27.2456, 580.918);
+ polygon.ps[1] = Point(27.2456, 600.918);
+ polygon.ps[2] = Point(7.24557, 600.918);
+ polygon.ps[3] = Point(7.24557, 580.918);
+ new ShapeRef(router, polygon, 133);
+
+ // shapeRef134
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(27.2456, 504.918);
+ polygon.ps[1] = Point(27.2456, 524.918);
+ polygon.ps[2] = Point(7.24557, 524.918);
+ polygon.ps[3] = Point(7.24557, 504.918);
+ new ShapeRef(router, polygon, 134);
+
+ // shapeRef135
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(27.2456, 472.918);
+ polygon.ps[1] = Point(27.2456, 492.918);
+ polygon.ps[2] = Point(7.24557, 492.918);
+ polygon.ps[3] = Point(7.24557, 472.918);
+ new ShapeRef(router, polygon, 135);
+
+ // shapeRef136
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(77.2456, 408.918);
+ polygon.ps[1] = Point(77.2456, 428.918);
+ polygon.ps[2] = Point(57.2456, 428.918);
+ polygon.ps[3] = Point(57.2456, 408.918);
+ new ShapeRef(router, polygon, 136);
+
+ // shapeRef137
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(27.2456, 408.918);
+ polygon.ps[1] = Point(27.2456, 428.918);
+ polygon.ps[2] = Point(7.24557, 428.918);
+ polygon.ps[3] = Point(7.24557, 408.918);
+ new ShapeRef(router, polygon, 137);
+
+ // shapeRef138
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(27.2456, 376.918);
+ polygon.ps[1] = Point(27.2456, 396.918);
+ polygon.ps[2] = Point(7.24557, 396.918);
+ polygon.ps[3] = Point(7.24557, 376.918);
+ new ShapeRef(router, polygon, 138);
+
+ // shapeRef139
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(27.2456, 268.918);
+ polygon.ps[1] = Point(27.2456, 288.918);
+ polygon.ps[2] = Point(7.24557, 288.918);
+ polygon.ps[3] = Point(7.24557, 268.918);
+ new ShapeRef(router, polygon, 139);
+
+ // shapeRef140
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(27.2456, 236.918);
+ polygon.ps[1] = Point(27.2456, 256.918);
+ polygon.ps[2] = Point(7.24557, 256.918);
+ polygon.ps[3] = Point(7.24557, 236.918);
+ new ShapeRef(router, polygon, 140);
+
+ // shapeRef141
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(254.976, 160.918);
+ polygon.ps[1] = Point(254.976, 180.918);
+ polygon.ps[2] = Point(234.976, 180.918);
+ polygon.ps[3] = Point(234.976, 160.918);
+ new ShapeRef(router, polygon, 141);
+
+ // shapeRef142
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(155.246, 76.9179);
+ polygon.ps[1] = Point(155.246, 96.9179);
+ polygon.ps[2] = Point(135.246, 96.9179);
+ polygon.ps[3] = Point(135.246, 76.9179);
+ new ShapeRef(router, polygon, 142);
+
+ // shapeRef143
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(155.246, 44.9179);
+ polygon.ps[1] = Point(155.246, 64.9179);
+ polygon.ps[2] = Point(135.246, 64.9179);
+ polygon.ps[3] = Point(135.246, 44.9179);
+ new ShapeRef(router, polygon, 143);
+
+ // shapeRef144
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(27.2456, 160.918);
+ polygon.ps[1] = Point(27.2456, 180.918);
+ polygon.ps[2] = Point(7.24557, 180.918);
+ polygon.ps[3] = Point(7.24557, 160.918);
+ new ShapeRef(router, polygon, 144);
+
+ // shapeRef145
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(27.2456, 22.9179);
+ polygon.ps[1] = Point(27.2456, 42.9179);
+ polygon.ps[2] = Point(7.24557, 42.9179);
+ polygon.ps[3] = Point(7.24557, 22.9179);
+ new ShapeRef(router, polygon, 145);
+
+ // shapeRef146
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(27.2456, -9.08205);
+ polygon.ps[1] = Point(27.2456, 10.9179);
+ polygon.ps[2] = Point(7.24557, 10.9179);
+ polygon.ps[3] = Point(7.24557, -9.08205);
+ new ShapeRef(router, polygon, 146);
+
+ // shapeRef147
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(329.219, -39.0821);
+ polygon.ps[1] = Point(329.219, -19.0821);
+ polygon.ps[2] = Point(309.219, -19.0821);
+ polygon.ps[3] = Point(309.219, -39.0821);
+ new ShapeRef(router, polygon, 147);
+
+ // shapeRef148
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(207.246, -39.0821);
+ polygon.ps[1] = Point(207.246, -19.0821);
+ polygon.ps[2] = Point(187.246, -19.0821);
+ polygon.ps[3] = Point(187.246, -39.0821);
+ new ShapeRef(router, polygon, 148);
+
+ // shapeRef149
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(601.954, 56.9179);
+ polygon.ps[1] = Point(601.954, 116.918);
+ polygon.ps[2] = Point(311.954, 116.918);
+ polygon.ps[3] = Point(311.954, 56.9179);
+ new ShapeRef(router, polygon, 149);
+
+ // shapeRef150
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(77.2456, 105.987);
+ polygon.ps[1] = Point(77.2456, 145.987);
+ polygon.ps[2] = Point(37.2456, 145.987);
+ polygon.ps[3] = Point(37.2456, 105.987);
+ new ShapeRef(router, polygon, 150);
+
+ // shapeRef151
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(339.219, -71.0821);
+ polygon.ps[1] = Point(339.219, -31.0821);
+ polygon.ps[2] = Point(299.219, -31.0821);
+ polygon.ps[3] = Point(299.219, -71.0821);
+ new ShapeRef(router, polygon, 151);
+
+ // shapeRef152
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(339.219, -27.0821);
+ polygon.ps[1] = Point(339.219, 12.9179);
+ polygon.ps[2] = Point(299.219, 12.9179);
+ polygon.ps[3] = Point(299.219, -27.0821);
+ new ShapeRef(router, polygon, 152);
+
+ // shapeRef153
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(217.246, 76.9179);
+ polygon.ps[1] = Point(217.246, 116.918);
+ polygon.ps[2] = Point(177.246, 116.918);
+ polygon.ps[3] = Point(177.246, 76.9179);
+ new ShapeRef(router, polygon, 153);
+
+ // shapeRef154
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(217.246, 140.918);
+ polygon.ps[1] = Point(217.246, 180.918);
+ polygon.ps[2] = Point(177.246, 180.918);
+ polygon.ps[3] = Point(177.246, 140.918);
+ new ShapeRef(router, polygon, 154);
+
+ // shapeRef155
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(77.2456, 140.918);
+ polygon.ps[1] = Point(77.2456, 180.918);
+ polygon.ps[2] = Point(37.2456, 180.918);
+ polygon.ps[3] = Point(37.2456, 140.918);
+ new ShapeRef(router, polygon, 155);
+
+ // shapeRef156
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(77.2456, 312.918);
+ polygon.ps[1] = Point(77.2456, 352.918);
+ polygon.ps[2] = Point(37.2456, 352.918);
+ polygon.ps[3] = Point(37.2456, 312.918);
+ new ShapeRef(router, polygon, 156);
+
+ // shapeRef157
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(77.2456, 427.955);
+ polygon.ps[1] = Point(77.2456, 467.955);
+ polygon.ps[2] = Point(37.2456, 467.955);
+ polygon.ps[3] = Point(37.2456, 427.955);
+ new ShapeRef(router, polygon, 157);
+
+ // shapeRef158
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(77.2456, 538.918);
+ polygon.ps[1] = Point(77.2456, 578.918);
+ polygon.ps[2] = Point(37.2456, 578.918);
+ polygon.ps[3] = Point(37.2456, 538.918);
+ new ShapeRef(router, polygon, 158);
+
+ // shapeRef159
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(77.2456, 656.918);
+ polygon.ps[1] = Point(77.2456, 696.918);
+ polygon.ps[2] = Point(37.2456, 696.918);
+ polygon.ps[3] = Point(37.2456, 656.918);
+ new ShapeRef(router, polygon, 159);
+
+ // shapeRef160
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(45.2456, 76.9179);
+ polygon.ps[1] = Point(45.2456, 116.918);
+ polygon.ps[2] = Point(5.24557, 116.918);
+ polygon.ps[3] = Point(5.24557, 76.9179);
+ new ShapeRef(router, polygon, 160);
+
+ // shapeRef161
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(235.246, 312.918);
+ polygon.ps[1] = Point(235.246, 352.918);
+ polygon.ps[2] = Point(195.246, 352.918);
+ polygon.ps[3] = Point(195.246, 312.918);
+ new ShapeRef(router, polygon, 161);
+
+ // shapeRef162
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(235.246, 427.955);
+ polygon.ps[1] = Point(235.246, 467.955);
+ polygon.ps[2] = Point(195.246, 467.955);
+ polygon.ps[3] = Point(195.246, 427.955);
+ new ShapeRef(router, polygon, 162);
+
+ // shapeRef163
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(235.246, 538.918);
+ polygon.ps[1] = Point(235.246, 578.918);
+ polygon.ps[2] = Point(195.246, 578.918);
+ polygon.ps[3] = Point(195.246, 538.918);
+ new ShapeRef(router, polygon, 163);
+
+ // shapeRef164
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(235.246, 656.918);
+ polygon.ps[1] = Point(235.246, 696.918);
+ polygon.ps[2] = Point(195.246, 696.918);
+ polygon.ps[3] = Point(195.246, 656.918);
+ new ShapeRef(router, polygon, 164);
+
+ // shapeRef165
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(391.246, 656.918);
+ polygon.ps[1] = Point(391.246, 696.918);
+ polygon.ps[2] = Point(351.246, 696.918);
+ polygon.ps[3] = Point(351.246, 656.918);
+ new ShapeRef(router, polygon, 165);
+
+ // shapeRef166
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(391.246, 538.918);
+ polygon.ps[1] = Point(391.246, 578.918);
+ polygon.ps[2] = Point(351.246, 578.918);
+ polygon.ps[3] = Point(351.246, 538.918);
+ new ShapeRef(router, polygon, 166);
+
+ // shapeRef167
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(391.246, 427.955);
+ polygon.ps[1] = Point(391.246, 467.955);
+ polygon.ps[2] = Point(351.246, 467.955);
+ polygon.ps[3] = Point(351.246, 427.955);
+ new ShapeRef(router, polygon, 167);
+
+ // shapeRef168
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(391.246, 312.918);
+ polygon.ps[1] = Point(391.246, 352.918);
+ polygon.ps[2] = Point(351.246, 352.918);
+ polygon.ps[3] = Point(351.246, 312.918);
+ new ShapeRef(router, polygon, 168);
+
+ // shapeRef169
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(547.246, 312.918);
+ polygon.ps[1] = Point(547.246, 352.918);
+ polygon.ps[2] = Point(507.246, 352.918);
+ polygon.ps[3] = Point(507.246, 312.918);
+ new ShapeRef(router, polygon, 169);
+
+ // shapeRef170
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(547.246, 427.955);
+ polygon.ps[1] = Point(547.246, 467.955);
+ polygon.ps[2] = Point(507.246, 467.955);
+ polygon.ps[3] = Point(507.246, 427.955);
+ new ShapeRef(router, polygon, 170);
+
+ // shapeRef171
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(547.246, 538.918);
+ polygon.ps[1] = Point(547.246, 578.918);
+ polygon.ps[2] = Point(507.246, 578.918);
+ polygon.ps[3] = Point(507.246, 538.918);
+ new ShapeRef(router, polygon, 171);
+
+ // shapeRef172
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(547.246, 656.918);
+ polygon.ps[1] = Point(547.246, 696.918);
+ polygon.ps[2] = Point(507.246, 696.918);
+ polygon.ps[3] = Point(507.246, 656.918);
+ new ShapeRef(router, polygon, 172);
+
+ // shapeRef173
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(693.933, 656.918);
+ polygon.ps[1] = Point(693.933, 696.918);
+ polygon.ps[2] = Point(653.933, 696.918);
+ polygon.ps[3] = Point(653.933, 656.918);
+ new ShapeRef(router, polygon, 173);
+
+ // shapeRef174
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(693.933, 538.918);
+ polygon.ps[1] = Point(693.933, 578.918);
+ polygon.ps[2] = Point(653.933, 578.918);
+ polygon.ps[3] = Point(653.933, 538.918);
+ new ShapeRef(router, polygon, 174);
+
+ // shapeRef175
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(693.933, 427.955);
+ polygon.ps[1] = Point(693.933, 467.955);
+ polygon.ps[2] = Point(653.933, 467.955);
+ polygon.ps[3] = Point(653.933, 427.955);
+ new ShapeRef(router, polygon, 175);
+
+ // shapeRef176
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(693.933, 312.918);
+ polygon.ps[1] = Point(693.933, 352.918);
+ polygon.ps[2] = Point(653.933, 352.918);
+ polygon.ps[3] = Point(653.933, 312.918);
+ new ShapeRef(router, polygon, 176);
+
+ // shapeRef177
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(843.246, 312.918);
+ polygon.ps[1] = Point(843.246, 352.918);
+ polygon.ps[2] = Point(803.246, 352.918);
+ polygon.ps[3] = Point(803.246, 312.918);
+ new ShapeRef(router, polygon, 177);
+
+ // shapeRef178
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(843.246, 427.955);
+ polygon.ps[1] = Point(843.246, 467.955);
+ polygon.ps[2] = Point(803.246, 467.955);
+ polygon.ps[3] = Point(803.246, 427.955);
+ new ShapeRef(router, polygon, 178);
+
+ // shapeRef179
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(843.246, 538.918);
+ polygon.ps[1] = Point(843.246, 578.918);
+ polygon.ps[2] = Point(803.246, 578.918);
+ polygon.ps[3] = Point(803.246, 538.918);
+ new ShapeRef(router, polygon, 179);
+
+ // shapeRef180
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(843.246, 656.918);
+ polygon.ps[1] = Point(843.246, 696.918);
+ polygon.ps[2] = Point(803.246, 696.918);
+ polygon.ps[3] = Point(803.246, 656.918);
+ new ShapeRef(router, polygon, 180);
+
+ // shapeRef181
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(999.246, 730.918);
+ polygon.ps[1] = Point(999.246, 770.918);
+ polygon.ps[2] = Point(959.246, 770.918);
+ polygon.ps[3] = Point(959.246, 730.918);
+ new ShapeRef(router, polygon, 181);
+
+ // shapeRef182
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(999.246, 656.918);
+ polygon.ps[1] = Point(999.246, 696.918);
+ polygon.ps[2] = Point(959.246, 696.918);
+ polygon.ps[3] = Point(959.246, 656.918);
+ new ShapeRef(router, polygon, 182);
+
+ // shapeRef183
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(999.246, 538.918);
+ polygon.ps[1] = Point(999.246, 578.918);
+ polygon.ps[2] = Point(959.246, 578.918);
+ polygon.ps[3] = Point(959.246, 538.918);
+ new ShapeRef(router, polygon, 183);
+
+ // shapeRef184
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(999.246, 427.955);
+ polygon.ps[1] = Point(999.246, 467.955);
+ polygon.ps[2] = Point(959.246, 467.955);
+ polygon.ps[3] = Point(959.246, 427.955);
+ new ShapeRef(router, polygon, 184);
+
+ // shapeRef185
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(999.246, 312.918);
+ polygon.ps[1] = Point(999.246, 352.918);
+ polygon.ps[2] = Point(959.246, 352.918);
+ polygon.ps[3] = Point(959.246, 312.918);
+ new ShapeRef(router, polygon, 185);
+
+ // shapeRef186
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(27.2456, 300.918);
+ polygon.ps[1] = Point(27.2456, 320.918);
+ polygon.ps[2] = Point(7.24557, 320.918);
+ polygon.ps[3] = Point(7.24557, 300.918);
+ new ShapeRef(router, polygon, 186);
+
+ // shapeRef187
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(203.246, 300.918);
+ polygon.ps[1] = Point(203.246, 320.918);
+ polygon.ps[2] = Point(183.246, 320.918);
+ polygon.ps[3] = Point(183.246, 300.918);
+ new ShapeRef(router, polygon, 187);
+
+ // shapeRef188
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(343.246, 300.918);
+ polygon.ps[1] = Point(343.246, 320.918);
+ polygon.ps[2] = Point(323.246, 320.918);
+ polygon.ps[3] = Point(323.246, 300.918);
+ new ShapeRef(router, polygon, 188);
+
+ // shapeRef189
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(499.246, 300.918);
+ polygon.ps[1] = Point(499.246, 320.918);
+ polygon.ps[2] = Point(479.246, 320.918);
+ polygon.ps[3] = Point(479.246, 300.918);
+ new ShapeRef(router, polygon, 189);
+
+ // shapeRef190
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(655.246, 300.918);
+ polygon.ps[1] = Point(655.246, 320.918);
+ polygon.ps[2] = Point(635.246, 320.918);
+ polygon.ps[3] = Point(635.246, 300.918);
+ new ShapeRef(router, polygon, 190);
+
+ // shapeRef191
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(811.246, 300.918);
+ polygon.ps[1] = Point(811.246, 320.918);
+ polygon.ps[2] = Point(791.246, 320.918);
+ polygon.ps[3] = Point(791.246, 300.918);
+ new ShapeRef(router, polygon, 191);
+
+ // shapeRef192
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(967.246, 300.918);
+ polygon.ps[1] = Point(967.246, 320.918);
+ polygon.ps[2] = Point(947.246, 320.918);
+ polygon.ps[3] = Point(947.246, 300.918);
+ new ShapeRef(router, polygon, 192);
+
+ // shapeRef193
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(27.2456, 440.918);
+ polygon.ps[1] = Point(27.2456, 460.918);
+ polygon.ps[2] = Point(7.24557, 460.918);
+ polygon.ps[3] = Point(7.24557, 440.918);
+ new ShapeRef(router, polygon, 193);
+
+ // shapeRef194
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(203.246, 440.918);
+ polygon.ps[1] = Point(203.246, 460.918);
+ polygon.ps[2] = Point(183.246, 460.918);
+ polygon.ps[3] = Point(183.246, 440.918);
+ new ShapeRef(router, polygon, 194);
+
+ // shapeRef195
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(343.246, 440.918);
+ polygon.ps[1] = Point(343.246, 460.918);
+ polygon.ps[2] = Point(323.246, 460.918);
+ polygon.ps[3] = Point(323.246, 440.918);
+ new ShapeRef(router, polygon, 195);
+
+ // shapeRef196
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(499.246, 440.918);
+ polygon.ps[1] = Point(499.246, 460.918);
+ polygon.ps[2] = Point(479.246, 460.918);
+ polygon.ps[3] = Point(479.246, 440.918);
+ new ShapeRef(router, polygon, 196);
+
+ // shapeRef197
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(811.246, 440.918);
+ polygon.ps[1] = Point(811.246, 460.918);
+ polygon.ps[2] = Point(791.246, 460.918);
+ polygon.ps[3] = Point(791.246, 440.918);
+ new ShapeRef(router, polygon, 197);
+
+ // shapeRef198
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(967.246, 440.918);
+ polygon.ps[1] = Point(967.246, 460.918);
+ polygon.ps[2] = Point(947.246, 460.918);
+ polygon.ps[3] = Point(947.246, 440.918);
+ new ShapeRef(router, polygon, 198);
+
+ // shapeRef199
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(655.246, 440.918);
+ polygon.ps[1] = Point(655.246, 460.918);
+ polygon.ps[2] = Point(635.246, 460.918);
+ polygon.ps[3] = Point(635.246, 440.918);
+ new ShapeRef(router, polygon, 199);
+
+ // shapeRef200
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(27.2456, 548.918);
+ polygon.ps[1] = Point(27.2456, 568.918);
+ polygon.ps[2] = Point(7.24557, 568.918);
+ polygon.ps[3] = Point(7.24557, 548.918);
+ new ShapeRef(router, polygon, 200);
+
+ // shapeRef201
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(203.246, 548.918);
+ polygon.ps[1] = Point(203.246, 568.918);
+ polygon.ps[2] = Point(183.246, 568.918);
+ polygon.ps[3] = Point(183.246, 548.918);
+ new ShapeRef(router, polygon, 201);
+
+ // shapeRef202
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(343.246, 548.918);
+ polygon.ps[1] = Point(343.246, 568.918);
+ polygon.ps[2] = Point(323.246, 568.918);
+ polygon.ps[3] = Point(323.246, 548.918);
+ new ShapeRef(router, polygon, 202);
+
+ // shapeRef203
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(499.246, 548.918);
+ polygon.ps[1] = Point(499.246, 568.918);
+ polygon.ps[2] = Point(479.246, 568.918);
+ polygon.ps[3] = Point(479.246, 548.918);
+ new ShapeRef(router, polygon, 203);
+
+ // shapeRef204
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(655.246, 548.918);
+ polygon.ps[1] = Point(655.246, 568.918);
+ polygon.ps[2] = Point(635.246, 568.918);
+ polygon.ps[3] = Point(635.246, 548.918);
+ new ShapeRef(router, polygon, 204);
+
+ // shapeRef205
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(811.246, 548.918);
+ polygon.ps[1] = Point(811.246, 568.918);
+ polygon.ps[2] = Point(791.246, 568.918);
+ polygon.ps[3] = Point(791.246, 548.918);
+ new ShapeRef(router, polygon, 205);
+
+ // shapeRef206
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(967.246, 548.918);
+ polygon.ps[1] = Point(967.246, 568.918);
+ polygon.ps[2] = Point(947.246, 568.918);
+ polygon.ps[3] = Point(947.246, 548.918);
+ new ShapeRef(router, polygon, 206);
+
+ // shapeRef207
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(27.2456, 644.918);
+ polygon.ps[1] = Point(27.2456, 664.918);
+ polygon.ps[2] = Point(7.24557, 664.918);
+ polygon.ps[3] = Point(7.24557, 644.918);
+ new ShapeRef(router, polygon, 207);
+
+ // shapeRef208
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(203.246, 644.918);
+ polygon.ps[1] = Point(203.246, 664.918);
+ polygon.ps[2] = Point(183.246, 664.918);
+ polygon.ps[3] = Point(183.246, 644.918);
+ new ShapeRef(router, polygon, 208);
+
+ // shapeRef209
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(343.246, 644.918);
+ polygon.ps[1] = Point(343.246, 664.918);
+ polygon.ps[2] = Point(323.246, 664.918);
+ polygon.ps[3] = Point(323.246, 644.918);
+ new ShapeRef(router, polygon, 209);
+
+ // shapeRef210
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(499.246, 644.918);
+ polygon.ps[1] = Point(499.246, 664.918);
+ polygon.ps[2] = Point(479.246, 664.918);
+ polygon.ps[3] = Point(479.246, 644.918);
+ new ShapeRef(router, polygon, 210);
+
+ // shapeRef211
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(655.246, 644.918);
+ polygon.ps[1] = Point(655.246, 664.918);
+ polygon.ps[2] = Point(635.246, 664.918);
+ polygon.ps[3] = Point(635.246, 644.918);
+ new ShapeRef(router, polygon, 211);
+
+ // shapeRef212
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(811.246, 644.918);
+ polygon.ps[1] = Point(811.246, 664.918);
+ polygon.ps[2] = Point(791.246, 664.918);
+ polygon.ps[3] = Point(791.246, 644.918);
+ new ShapeRef(router, polygon, 212);
+
+ // shapeRef213
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(967.246, 644.918);
+ polygon.ps[1] = Point(967.246, 664.918);
+ polygon.ps[2] = Point(947.246, 664.918);
+ polygon.ps[3] = Point(947.246, 644.918);
+ new ShapeRef(router, polygon, 213);
+
+ // shapeRef214
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1243.25, 268.918);
+ polygon.ps[1] = Point(1243.25, 288.918);
+ polygon.ps[2] = Point(1223.25, 288.918);
+ polygon.ps[3] = Point(1223.25, 268.918);
+ new ShapeRef(router, polygon, 214);
+
+ // shapeRef215
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1243.25, 408.918);
+ polygon.ps[1] = Point(1243.25, 428.918);
+ polygon.ps[2] = Point(1223.25, 428.918);
+ polygon.ps[3] = Point(1223.25, 408.918);
+ new ShapeRef(router, polygon, 215);
+
+ // shapeRef216
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1243.25, 504.918);
+ polygon.ps[1] = Point(1243.25, 524.918);
+ polygon.ps[2] = Point(1223.25, 524.918);
+ polygon.ps[3] = Point(1223.25, 504.918);
+ new ShapeRef(router, polygon, 216);
+
+ // shapeRef217
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1243.25, 612.918);
+ polygon.ps[1] = Point(1243.25, 632.918);
+ polygon.ps[2] = Point(1223.25, 632.918);
+ polygon.ps[3] = Point(1223.25, 612.918);
+ new ShapeRef(router, polygon, 217);
+
+ // shapeRef218
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(967.246, 708.918);
+ polygon.ps[1] = Point(967.246, 728.918);
+ polygon.ps[2] = Point(947.246, 728.918);
+ polygon.ps[3] = Point(947.246, 708.918);
+ new ShapeRef(router, polygon, 218);
+
+ // shapeRef219
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(967.246, 740.918);
+ polygon.ps[1] = Point(967.246, 760.918);
+ polygon.ps[2] = Point(947.246, 760.918);
+ polygon.ps[3] = Point(947.246, 740.918);
+ new ShapeRef(router, polygon, 219);
+
+ // shapeRef220
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1243.25, 708.918);
+ polygon.ps[1] = Point(1243.25, 728.918);
+ polygon.ps[2] = Point(1223.25, 728.918);
+ polygon.ps[3] = Point(1223.25, 708.918);
+ new ShapeRef(router, polygon, 220);
+
+ // shapeRef221
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1303.25, 246.918);
+ polygon.ps[1] = Point(1303.25, 266.918);
+ polygon.ps[2] = Point(1283.25, 266.918);
+ polygon.ps[3] = Point(1283.25, 246.918);
+ new ShapeRef(router, polygon, 221);
+
+ // shapeRef222
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1303.25, 634.918);
+ polygon.ps[1] = Point(1303.25, 654.918);
+ polygon.ps[2] = Point(1283.25, 654.918);
+ polygon.ps[3] = Point(1283.25, 634.918);
+ new ShapeRef(router, polygon, 222);
+
+ // shapeRef223
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(77.2456, 236.918);
+ polygon.ps[1] = Point(77.2456, 256.918);
+ polygon.ps[2] = Point(57.2456, 256.918);
+ polygon.ps[3] = Point(57.2456, 236.918);
+ new ShapeRef(router, polygon, 223);
+
+ // shapeRef224
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(77.2456, 268.918);
+ polygon.ps[1] = Point(77.2456, 288.918);
+ polygon.ps[2] = Point(57.2456, 288.918);
+ polygon.ps[3] = Point(57.2456, 268.918);
+ new ShapeRef(router, polygon, 224);
+
+ // shapeRef225
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1159.25, 602.918);
+ polygon.ps[1] = Point(1159.25, 642.918);
+ polygon.ps[2] = Point(1103.25, 642.918);
+ polygon.ps[3] = Point(1103.25, 602.918);
+ new ShapeRef(router, polygon, 225);
+
+ // shapeRef226
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(955.246, 602.918);
+ polygon.ps[1] = Point(955.246, 642.918);
+ polygon.ps[2] = Point(899.246, 642.918);
+ polygon.ps[3] = Point(899.246, 602.918);
+ new ShapeRef(router, polygon, 226);
+
+ // shapeRef227
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(799.246, 602.918);
+ polygon.ps[1] = Point(799.246, 642.918);
+ polygon.ps[2] = Point(743.246, 642.918);
+ polygon.ps[3] = Point(743.246, 602.918);
+ new ShapeRef(router, polygon, 227);
+
+ // shapeRef228
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(643.246, 602.918);
+ polygon.ps[1] = Point(643.246, 642.918);
+ polygon.ps[2] = Point(587.246, 642.918);
+ polygon.ps[3] = Point(587.246, 602.918);
+ new ShapeRef(router, polygon, 228);
+
+ // shapeRef229
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(487.246, 602.918);
+ polygon.ps[1] = Point(487.246, 642.918);
+ polygon.ps[2] = Point(431.246, 642.918);
+ polygon.ps[3] = Point(431.246, 602.918);
+ new ShapeRef(router, polygon, 229);
+
+ // shapeRef230
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(331.246, 602.918);
+ polygon.ps[1] = Point(331.246, 642.918);
+ polygon.ps[2] = Point(275.246, 642.918);
+ polygon.ps[3] = Point(275.246, 602.918);
+ new ShapeRef(router, polygon, 230);
+
+ // shapeRef231
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(173.246, 634.918);
+ polygon.ps[1] = Point(173.246, 674.918);
+ polygon.ps[2] = Point(117.246, 674.918);
+ polygon.ps[3] = Point(117.246, 634.918);
+ new ShapeRef(router, polygon, 231);
+
+ // shapeRef232
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(907.246, 698.918);
+ polygon.ps[1] = Point(907.246, 738.918);
+ polygon.ps[2] = Point(851.246, 738.918);
+ polygon.ps[3] = Point(851.246, 698.918);
+ new ShapeRef(router, polygon, 232);
+
+ // shapeRef233
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1231.25, 698.918);
+ polygon.ps[1] = Point(1231.25, 738.918);
+ polygon.ps[2] = Point(1175.25, 738.918);
+ polygon.ps[3] = Point(1175.25, 698.918);
+ new ShapeRef(router, polygon, 233);
+
+ // shapeRef234
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1291.25, 698.918);
+ polygon.ps[1] = Point(1291.25, 738.918);
+ polygon.ps[2] = Point(1235.25, 738.918);
+ polygon.ps[3] = Point(1235.25, 698.918);
+ new ShapeRef(router, polygon, 234);
+
+ // shapeRef235
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(622.941, 698.918);
+ polygon.ps[1] = Point(622.941, 738.918);
+ polygon.ps[2] = Point(566.941, 738.918);
+ polygon.ps[3] = Point(566.941, 698.918);
+ new ShapeRef(router, polygon, 235);
+
+ // shapeRef236
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(479.455, 698.918);
+ polygon.ps[1] = Point(479.455, 738.918);
+ polygon.ps[2] = Point(423.455, 738.918);
+ polygon.ps[3] = Point(423.455, 698.918);
+ new ShapeRef(router, polygon, 236);
+
+ // shapeRef237
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1399.25, 602.918);
+ polygon.ps[1] = Point(1399.25, 642.918);
+ polygon.ps[2] = Point(1343.25, 642.918);
+ polygon.ps[3] = Point(1343.25, 602.918);
+ new ShapeRef(router, polygon, 237);
+
+ // shapeRef238
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1447.25, 555.942);
+ polygon.ps[1] = Point(1447.25, 595.942);
+ polygon.ps[2] = Point(1391.25, 595.942);
+ polygon.ps[3] = Point(1391.25, 555.942);
+ new ShapeRef(router, polygon, 238);
+
+ // shapeRef239
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1159.25, 634.918);
+ polygon.ps[1] = Point(1159.25, 674.918);
+ polygon.ps[2] = Point(1103.25, 674.918);
+ polygon.ps[3] = Point(1103.25, 634.918);
+ new ShapeRef(router, polygon, 239);
+
+ // shapeRef240
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(955.246, 634.918);
+ polygon.ps[1] = Point(955.246, 674.918);
+ polygon.ps[2] = Point(899.246, 674.918);
+ polygon.ps[3] = Point(899.246, 634.918);
+ new ShapeRef(router, polygon, 240);
+
+ // shapeRef241
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(799.246, 634.918);
+ polygon.ps[1] = Point(799.246, 674.918);
+ polygon.ps[2] = Point(743.246, 674.918);
+ polygon.ps[3] = Point(743.246, 634.918);
+ new ShapeRef(router, polygon, 241);
+
+ // shapeRef242
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(643.246, 634.918);
+ polygon.ps[1] = Point(643.246, 674.918);
+ polygon.ps[2] = Point(587.246, 674.918);
+ polygon.ps[3] = Point(587.246, 634.918);
+ new ShapeRef(router, polygon, 242);
+
+ // shapeRef243
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(487.246, 634.918);
+ polygon.ps[1] = Point(487.246, 674.918);
+ polygon.ps[2] = Point(431.246, 674.918);
+ polygon.ps[3] = Point(431.246, 634.918);
+ new ShapeRef(router, polygon, 243);
+
+ // shapeRef244
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(331.246, 634.918);
+ polygon.ps[1] = Point(331.246, 674.918);
+ polygon.ps[2] = Point(275.246, 674.918);
+ polygon.ps[3] = Point(275.246, 634.918);
+ new ShapeRef(router, polygon, 244);
+
+ // shapeRef245
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(173.246, 602.918);
+ polygon.ps[1] = Point(173.246, 642.918);
+ polygon.ps[2] = Point(117.246, 642.918);
+ polygon.ps[3] = Point(117.246, 602.918);
+ new ShapeRef(router, polygon, 245);
+
+ // shapeRef246
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1447.25, 494.918);
+ polygon.ps[1] = Point(1447.25, 534.918);
+ polygon.ps[2] = Point(1391.25, 534.918);
+ polygon.ps[3] = Point(1391.25, 494.918);
+ new ShapeRef(router, polygon, 246);
+
+ // shapeRef247
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1159.25, 516.918);
+ polygon.ps[1] = Point(1159.25, 556.918);
+ polygon.ps[2] = Point(1103.25, 556.918);
+ polygon.ps[3] = Point(1103.25, 516.918);
+ new ShapeRef(router, polygon, 247);
+
+ // shapeRef248
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(955.246, 516.918);
+ polygon.ps[1] = Point(955.246, 556.918);
+ polygon.ps[2] = Point(899.246, 556.918);
+ polygon.ps[3] = Point(899.246, 516.918);
+ new ShapeRef(router, polygon, 248);
+
+ // shapeRef249
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(799.246, 516.918);
+ polygon.ps[1] = Point(799.246, 556.918);
+ polygon.ps[2] = Point(743.246, 556.918);
+ polygon.ps[3] = Point(743.246, 516.918);
+ new ShapeRef(router, polygon, 249);
+
+ // shapeRef250
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(643.246, 516.918);
+ polygon.ps[1] = Point(643.246, 556.918);
+ polygon.ps[2] = Point(587.246, 556.918);
+ polygon.ps[3] = Point(587.246, 516.918);
+ new ShapeRef(router, polygon, 250);
+
+ // shapeRef251
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(487.246, 516.918);
+ polygon.ps[1] = Point(487.246, 556.918);
+ polygon.ps[2] = Point(431.246, 556.918);
+ polygon.ps[3] = Point(431.246, 516.918);
+ new ShapeRef(router, polygon, 251);
+
+ // shapeRef252
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(331.246, 516.918);
+ polygon.ps[1] = Point(331.246, 556.918);
+ polygon.ps[2] = Point(275.246, 556.918);
+ polygon.ps[3] = Point(275.246, 516.918);
+ new ShapeRef(router, polygon, 252);
+
+ // shapeRef253
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(173.246, 516.918);
+ polygon.ps[1] = Point(173.246, 556.918);
+ polygon.ps[2] = Point(117.246, 556.918);
+ polygon.ps[3] = Point(117.246, 516.918);
+ new ShapeRef(router, polygon, 253);
+
+ // shapeRef254
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1321.25, 214.918);
+ polygon.ps[1] = Point(1321.25, 254.918);
+ polygon.ps[2] = Point(1265.25, 254.918);
+ polygon.ps[3] = Point(1265.25, 214.918);
+ new ShapeRef(router, polygon, 254);
+
+ // shapeRef255
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1111.25, 602.918);
+ polygon.ps[1] = Point(1111.25, 642.918);
+ polygon.ps[2] = Point(1055.25, 642.918);
+ polygon.ps[3] = Point(1055.25, 602.918);
+ new ShapeRef(router, polygon, 255);
+
+ // shapeRef256
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1447.25, 398.918);
+ polygon.ps[1] = Point(1447.25, 438.918);
+ polygon.ps[2] = Point(1391.25, 438.918);
+ polygon.ps[3] = Point(1391.25, 398.918);
+ new ShapeRef(router, polygon, 256);
+
+ // shapeRef257
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1447.25, 698.918);
+ polygon.ps[1] = Point(1447.25, 738.918);
+ polygon.ps[2] = Point(1391.25, 738.918);
+ polygon.ps[3] = Point(1391.25, 698.918);
+ new ShapeRef(router, polygon, 257);
+
+ // shapeRef258
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1507.25, 698.918);
+ polygon.ps[1] = Point(1507.25, 738.918);
+ polygon.ps[2] = Point(1451.25, 738.918);
+ polygon.ps[3] = Point(1451.25, 698.918);
+ new ShapeRef(router, polygon, 258);
+
+ // shapeRef259
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(751.246, 698.918);
+ polygon.ps[1] = Point(751.246, 738.918);
+ polygon.ps[2] = Point(695.246, 738.918);
+ polygon.ps[3] = Point(695.246, 698.918);
+ new ShapeRef(router, polygon, 259);
+
+ // shapeRef260
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(955.246, 698.918);
+ polygon.ps[1] = Point(955.246, 738.918);
+ polygon.ps[2] = Point(899.246, 738.918);
+ polygon.ps[3] = Point(899.246, 698.918);
+ new ShapeRef(router, polygon, 260);
+
+ // shapeRef261
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(173.246, 12.9179);
+ polygon.ps[1] = Point(173.246, 52.9179);
+ polygon.ps[2] = Point(117.246, 52.9179);
+ polygon.ps[3] = Point(117.246, 12.9179);
+ new ShapeRef(router, polygon, 261);
+
+ // shapeRef262
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(173.246, 290.918);
+ polygon.ps[1] = Point(173.246, 330.918);
+ polygon.ps[2] = Point(117.246, 330.918);
+ polygon.ps[3] = Point(117.246, 290.918);
+ new ShapeRef(router, polygon, 262);
+
+ // shapeRef263
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1033.25, 214.918);
+ polygon.ps[1] = Point(1033.25, 254.918);
+ polygon.ps[2] = Point(977.246, 254.918);
+ polygon.ps[3] = Point(977.246, 214.918);
+ new ShapeRef(router, polygon, 263);
+
+ // shapeRef264
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(877.246, 214.918);
+ polygon.ps[1] = Point(877.246, 254.918);
+ polygon.ps[2] = Point(821.246, 254.918);
+ polygon.ps[3] = Point(821.246, 214.918);
+ new ShapeRef(router, polygon, 264);
+
+ // shapeRef265
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(721.246, 214.918);
+ polygon.ps[1] = Point(721.246, 254.918);
+ polygon.ps[2] = Point(665.246, 254.918);
+ polygon.ps[3] = Point(665.246, 214.918);
+ new ShapeRef(router, polygon, 265);
+
+ // shapeRef266
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(565.246, 214.918);
+ polygon.ps[1] = Point(565.246, 254.918);
+ polygon.ps[2] = Point(509.246, 254.918);
+ polygon.ps[3] = Point(509.246, 214.918);
+ new ShapeRef(router, polygon, 266);
+
+ // shapeRef267
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(409.246, 214.918);
+ polygon.ps[1] = Point(409.246, 254.918);
+ polygon.ps[2] = Point(353.246, 254.918);
+ polygon.ps[3] = Point(353.246, 214.918);
+ new ShapeRef(router, polygon, 267);
+
+ // shapeRef268
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(331.246, 268.918);
+ polygon.ps[1] = Point(331.246, 308.918);
+ polygon.ps[2] = Point(275.246, 308.918);
+ polygon.ps[3] = Point(275.246, 268.918);
+ new ShapeRef(router, polygon, 268);
+
+ // shapeRef269
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1159.25, 698.918);
+ polygon.ps[1] = Point(1159.25, 738.918);
+ polygon.ps[2] = Point(1103.25, 738.918);
+ polygon.ps[3] = Point(1103.25, 698.918);
+ new ShapeRef(router, polygon, 269);
+
+ // shapeRef270
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1063.25, 666.918);
+ polygon.ps[1] = Point(1063.25, 706.918);
+ polygon.ps[2] = Point(1007.25, 706.918);
+ polygon.ps[3] = Point(1007.25, 666.918);
+ new ShapeRef(router, polygon, 270);
+
+ // shapeRef271
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1159.25, 570.918);
+ polygon.ps[1] = Point(1159.25, 610.918);
+ polygon.ps[2] = Point(1103.25, 610.918);
+ polygon.ps[3] = Point(1103.25, 570.918);
+ new ShapeRef(router, polygon, 271);
+
+ // shapeRef272
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1063.25, 602.918);
+ polygon.ps[1] = Point(1063.25, 642.918);
+ polygon.ps[2] = Point(1007.25, 642.918);
+ polygon.ps[3] = Point(1007.25, 602.918);
+ new ShapeRef(router, polygon, 272);
+
+ // shapeRef273
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1063.25, 570.918);
+ polygon.ps[1] = Point(1063.25, 610.918);
+ polygon.ps[2] = Point(1007.25, 610.918);
+ polygon.ps[3] = Point(1007.25, 570.918);
+ new ShapeRef(router, polygon, 273);
+
+ // shapeRef274
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1063.25, 494.918);
+ polygon.ps[1] = Point(1063.25, 534.918);
+ polygon.ps[2] = Point(1007.25, 534.918);
+ polygon.ps[3] = Point(1007.25, 494.918);
+ new ShapeRef(router, polygon, 274);
+
+ // shapeRef275
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1063.25, 462.918);
+ polygon.ps[1] = Point(1063.25, 502.918);
+ polygon.ps[2] = Point(1007.25, 502.918);
+ polygon.ps[3] = Point(1007.25, 462.918);
+ new ShapeRef(router, polygon, 275);
+
+ // shapeRef276
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1159.25, 398.918);
+ polygon.ps[1] = Point(1159.25, 438.918);
+ polygon.ps[2] = Point(1103.25, 438.918);
+ polygon.ps[3] = Point(1103.25, 398.918);
+ new ShapeRef(router, polygon, 276);
+
+ // shapeRef277
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1063.25, 398.918);
+ polygon.ps[1] = Point(1063.25, 438.918);
+ polygon.ps[2] = Point(1007.25, 438.918);
+ polygon.ps[3] = Point(1007.25, 398.918);
+ new ShapeRef(router, polygon, 277);
+
+ // shapeRef278
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1063.25, 366.918);
+ polygon.ps[1] = Point(1063.25, 406.918);
+ polygon.ps[2] = Point(1007.25, 406.918);
+ polygon.ps[3] = Point(1007.25, 366.918);
+ new ShapeRef(router, polygon, 278);
+
+ // shapeRef279
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1033.25, 182.918);
+ polygon.ps[1] = Point(1033.25, 222.918);
+ polygon.ps[2] = Point(977.246, 222.918);
+ polygon.ps[3] = Point(977.246, 182.918);
+ new ShapeRef(router, polygon, 279);
+
+ // shapeRef280
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(985.246, 172.918);
+ polygon.ps[1] = Point(985.246, 212.918);
+ polygon.ps[2] = Point(929.246, 212.918);
+ polygon.ps[3] = Point(929.246, 172.918);
+ new ShapeRef(router, polygon, 280);
+
+ // shapeRef281
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(985.246, 108.918);
+ polygon.ps[1] = Point(985.246, 148.918);
+ polygon.ps[2] = Point(929.246, 148.918);
+ polygon.ps[3] = Point(929.246, 108.918);
+ new ShapeRef(router, polygon, 281);
+
+ // shapeRef282
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(955.246, 570.918);
+ polygon.ps[1] = Point(955.246, 610.918);
+ polygon.ps[2] = Point(899.246, 610.918);
+ polygon.ps[3] = Point(899.246, 570.918);
+ new ShapeRef(router, polygon, 282);
+
+ // shapeRef283
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(907.246, 602.918);
+ polygon.ps[1] = Point(907.246, 642.918);
+ polygon.ps[2] = Point(851.246, 642.918);
+ polygon.ps[3] = Point(851.246, 602.918);
+ new ShapeRef(router, polygon, 283);
+
+ // shapeRef284
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(907.246, 570.918);
+ polygon.ps[1] = Point(907.246, 610.918);
+ polygon.ps[2] = Point(851.246, 610.918);
+ polygon.ps[3] = Point(851.246, 570.918);
+ new ShapeRef(router, polygon, 284);
+
+ // shapeRef285
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(907.246, 494.918);
+ polygon.ps[1] = Point(907.246, 534.918);
+ polygon.ps[2] = Point(851.246, 534.918);
+ polygon.ps[3] = Point(851.246, 494.918);
+ new ShapeRef(router, polygon, 285);
+
+ // shapeRef286
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(907.246, 462.918);
+ polygon.ps[1] = Point(907.246, 502.918);
+ polygon.ps[2] = Point(851.246, 502.918);
+ polygon.ps[3] = Point(851.246, 462.918);
+ new ShapeRef(router, polygon, 286);
+
+ // shapeRef287
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(955.246, 398.918);
+ polygon.ps[1] = Point(955.246, 438.918);
+ polygon.ps[2] = Point(899.246, 438.918);
+ polygon.ps[3] = Point(899.246, 398.918);
+ new ShapeRef(router, polygon, 287);
+
+ // shapeRef288
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(907.246, 398.918);
+ polygon.ps[1] = Point(907.246, 438.918);
+ polygon.ps[2] = Point(851.246, 438.918);
+ polygon.ps[3] = Point(851.246, 398.918);
+ new ShapeRef(router, polygon, 288);
+
+ // shapeRef289
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(907.246, 366.918);
+ polygon.ps[1] = Point(907.246, 406.918);
+ polygon.ps[2] = Point(851.246, 406.918);
+ polygon.ps[3] = Point(851.246, 366.918);
+ new ShapeRef(router, polygon, 289);
+
+ // shapeRef290
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(877.246, 182.918);
+ polygon.ps[1] = Point(877.246, 222.918);
+ polygon.ps[2] = Point(821.246, 222.918);
+ polygon.ps[3] = Point(821.246, 182.918);
+ new ShapeRef(router, polygon, 290);
+
+ // shapeRef291
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(829.246, 172.918);
+ polygon.ps[1] = Point(829.246, 212.918);
+ polygon.ps[2] = Point(773.246, 212.918);
+ polygon.ps[3] = Point(773.246, 172.918);
+ new ShapeRef(router, polygon, 291);
+
+ // shapeRef292
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(829.246, 108.918);
+ polygon.ps[1] = Point(829.246, 148.918);
+ polygon.ps[2] = Point(773.246, 148.918);
+ polygon.ps[3] = Point(773.246, 108.918);
+ new ShapeRef(router, polygon, 292);
+
+ // shapeRef293
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(799.246, 570.918);
+ polygon.ps[1] = Point(799.246, 610.918);
+ polygon.ps[2] = Point(743.246, 610.918);
+ polygon.ps[3] = Point(743.246, 570.918);
+ new ShapeRef(router, polygon, 293);
+
+ // shapeRef294
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(751.246, 602.918);
+ polygon.ps[1] = Point(751.246, 642.918);
+ polygon.ps[2] = Point(695.246, 642.918);
+ polygon.ps[3] = Point(695.246, 602.918);
+ new ShapeRef(router, polygon, 294);
+
+ // shapeRef295
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(751.246, 570.918);
+ polygon.ps[1] = Point(751.246, 610.918);
+ polygon.ps[2] = Point(695.246, 610.918);
+ polygon.ps[3] = Point(695.246, 570.918);
+ new ShapeRef(router, polygon, 295);
+
+ // shapeRef296
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(751.246, 494.918);
+ polygon.ps[1] = Point(751.246, 534.918);
+ polygon.ps[2] = Point(695.246, 534.918);
+ polygon.ps[3] = Point(695.246, 494.918);
+ new ShapeRef(router, polygon, 296);
+
+ // shapeRef297
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(751.246, 462.918);
+ polygon.ps[1] = Point(751.246, 502.918);
+ polygon.ps[2] = Point(695.246, 502.918);
+ polygon.ps[3] = Point(695.246, 462.918);
+ new ShapeRef(router, polygon, 297);
+
+ // shapeRef298
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(799.246, 398.918);
+ polygon.ps[1] = Point(799.246, 438.918);
+ polygon.ps[2] = Point(743.246, 438.918);
+ polygon.ps[3] = Point(743.246, 398.918);
+ new ShapeRef(router, polygon, 298);
+
+ // shapeRef299
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(751.246, 398.918);
+ polygon.ps[1] = Point(751.246, 438.918);
+ polygon.ps[2] = Point(695.246, 438.918);
+ polygon.ps[3] = Point(695.246, 398.918);
+ new ShapeRef(router, polygon, 299);
+
+ // shapeRef300
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(751.246, 366.918);
+ polygon.ps[1] = Point(751.246, 406.918);
+ polygon.ps[2] = Point(695.246, 406.918);
+ polygon.ps[3] = Point(695.246, 366.918);
+ new ShapeRef(router, polygon, 300);
+
+ // shapeRef301
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(721.246, 182.918);
+ polygon.ps[1] = Point(721.246, 222.918);
+ polygon.ps[2] = Point(665.246, 222.918);
+ polygon.ps[3] = Point(665.246, 182.918);
+ new ShapeRef(router, polygon, 301);
+
+ // shapeRef302
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(673.246, 172.918);
+ polygon.ps[1] = Point(673.246, 212.918);
+ polygon.ps[2] = Point(617.246, 212.918);
+ polygon.ps[3] = Point(617.246, 172.918);
+ new ShapeRef(router, polygon, 302);
+
+ // shapeRef303
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(673.246, 108.918);
+ polygon.ps[1] = Point(673.246, 148.918);
+ polygon.ps[2] = Point(617.246, 148.918);
+ polygon.ps[3] = Point(617.246, 108.918);
+ new ShapeRef(router, polygon, 303);
+
+ // shapeRef304
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(643.246, 570.918);
+ polygon.ps[1] = Point(643.246, 610.918);
+ polygon.ps[2] = Point(587.246, 610.918);
+ polygon.ps[3] = Point(587.246, 570.918);
+ new ShapeRef(router, polygon, 304);
+
+ // shapeRef305
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(595.246, 602.918);
+ polygon.ps[1] = Point(595.246, 642.918);
+ polygon.ps[2] = Point(539.246, 642.918);
+ polygon.ps[3] = Point(539.246, 602.918);
+ new ShapeRef(router, polygon, 305);
+
+ // shapeRef306
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(595.246, 570.918);
+ polygon.ps[1] = Point(595.246, 610.918);
+ polygon.ps[2] = Point(539.246, 610.918);
+ polygon.ps[3] = Point(539.246, 570.918);
+ new ShapeRef(router, polygon, 306);
+
+ // shapeRef307
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(643.246, 466.951);
+ polygon.ps[1] = Point(643.246, 506.951);
+ polygon.ps[2] = Point(587.246, 506.951);
+ polygon.ps[3] = Point(587.246, 466.951);
+ new ShapeRef(router, polygon, 307);
+
+ // shapeRef308
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(595.246, 494.918);
+ polygon.ps[1] = Point(595.246, 534.918);
+ polygon.ps[2] = Point(539.246, 534.918);
+ polygon.ps[3] = Point(539.246, 494.918);
+ new ShapeRef(router, polygon, 308);
+
+ // shapeRef309
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(595.246, 462.918);
+ polygon.ps[1] = Point(595.246, 502.918);
+ polygon.ps[2] = Point(539.246, 502.918);
+ polygon.ps[3] = Point(539.246, 462.918);
+ new ShapeRef(router, polygon, 309);
+
+ // shapeRef310
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(643.246, 398.918);
+ polygon.ps[1] = Point(643.246, 438.918);
+ polygon.ps[2] = Point(587.246, 438.918);
+ polygon.ps[3] = Point(587.246, 398.918);
+ new ShapeRef(router, polygon, 310);
+
+ // shapeRef311
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(595.246, 398.918);
+ polygon.ps[1] = Point(595.246, 438.918);
+ polygon.ps[2] = Point(539.246, 438.918);
+ polygon.ps[3] = Point(539.246, 398.918);
+ new ShapeRef(router, polygon, 311);
+
+ // shapeRef312
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(595.246, 366.918);
+ polygon.ps[1] = Point(595.246, 406.918);
+ polygon.ps[2] = Point(539.246, 406.918);
+ polygon.ps[3] = Point(539.246, 366.918);
+ new ShapeRef(router, polygon, 312);
+
+ // shapeRef313
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(565.246, 182.918);
+ polygon.ps[1] = Point(565.246, 222.918);
+ polygon.ps[2] = Point(509.246, 222.918);
+ polygon.ps[3] = Point(509.246, 182.918);
+ new ShapeRef(router, polygon, 313);
+
+ // shapeRef314
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(517.246, 172.918);
+ polygon.ps[1] = Point(517.246, 212.918);
+ polygon.ps[2] = Point(461.246, 212.918);
+ polygon.ps[3] = Point(461.246, 172.918);
+ new ShapeRef(router, polygon, 314);
+
+ // shapeRef315
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(517.246, 108.918);
+ polygon.ps[1] = Point(517.246, 148.918);
+ polygon.ps[2] = Point(461.246, 148.918);
+ polygon.ps[3] = Point(461.246, 108.918);
+ new ShapeRef(router, polygon, 315);
+
+ // shapeRef316
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(487.246, 570.918);
+ polygon.ps[1] = Point(487.246, 610.918);
+ polygon.ps[2] = Point(431.246, 610.918);
+ polygon.ps[3] = Point(431.246, 570.918);
+ new ShapeRef(router, polygon, 316);
+
+ // shapeRef317
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(439.246, 602.918);
+ polygon.ps[1] = Point(439.246, 642.918);
+ polygon.ps[2] = Point(383.246, 642.918);
+ polygon.ps[3] = Point(383.246, 602.918);
+ new ShapeRef(router, polygon, 317);
+
+ // shapeRef318
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(439.246, 570.918);
+ polygon.ps[1] = Point(439.246, 610.918);
+ polygon.ps[2] = Point(383.246, 610.918);
+ polygon.ps[3] = Point(383.246, 570.918);
+ new ShapeRef(router, polygon, 318);
+
+ // shapeRef319
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(439.246, 494.918);
+ polygon.ps[1] = Point(439.246, 534.918);
+ polygon.ps[2] = Point(383.246, 534.918);
+ polygon.ps[3] = Point(383.246, 494.918);
+ new ShapeRef(router, polygon, 319);
+
+ // shapeRef320
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(439.246, 462.918);
+ polygon.ps[1] = Point(439.246, 502.918);
+ polygon.ps[2] = Point(383.246, 502.918);
+ polygon.ps[3] = Point(383.246, 462.918);
+ new ShapeRef(router, polygon, 320);
+
+ // shapeRef321
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(487.246, 398.918);
+ polygon.ps[1] = Point(487.246, 438.918);
+ polygon.ps[2] = Point(431.246, 438.918);
+ polygon.ps[3] = Point(431.246, 398.918);
+ new ShapeRef(router, polygon, 321);
+
+ // shapeRef322
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(439.246, 398.918);
+ polygon.ps[1] = Point(439.246, 438.918);
+ polygon.ps[2] = Point(383.246, 438.918);
+ polygon.ps[3] = Point(383.246, 398.918);
+ new ShapeRef(router, polygon, 322);
+
+ // shapeRef323
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(439.246, 366.918);
+ polygon.ps[1] = Point(439.246, 406.918);
+ polygon.ps[2] = Point(383.246, 406.918);
+ polygon.ps[3] = Point(383.246, 366.918);
+ new ShapeRef(router, polygon, 323);
+
+ // shapeRef324
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(409.246, 182.918);
+ polygon.ps[1] = Point(409.246, 222.918);
+ polygon.ps[2] = Point(353.246, 222.918);
+ polygon.ps[3] = Point(353.246, 182.918);
+ new ShapeRef(router, polygon, 324);
+
+ // shapeRef325
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(361.246, 172.918);
+ polygon.ps[1] = Point(361.246, 212.918);
+ polygon.ps[2] = Point(305.246, 212.918);
+ polygon.ps[3] = Point(305.246, 172.918);
+ new ShapeRef(router, polygon, 325);
+
+ // shapeRef326
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(361.246, 108.918);
+ polygon.ps[1] = Point(361.246, 148.918);
+ polygon.ps[2] = Point(305.246, 148.918);
+ polygon.ps[3] = Point(305.246, 108.918);
+ new ShapeRef(router, polygon, 326);
+
+ // shapeRef327
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(331.246, 570.918);
+ polygon.ps[1] = Point(331.246, 610.918);
+ polygon.ps[2] = Point(275.246, 610.918);
+ polygon.ps[3] = Point(275.246, 570.918);
+ new ShapeRef(router, polygon, 327);
+
+ // shapeRef328
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(283.246, 602.918);
+ polygon.ps[1] = Point(283.246, 642.918);
+ polygon.ps[2] = Point(227.246, 642.918);
+ polygon.ps[3] = Point(227.246, 602.918);
+ new ShapeRef(router, polygon, 328);
+
+ // shapeRef329
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(283.246, 570.918);
+ polygon.ps[1] = Point(283.246, 610.918);
+ polygon.ps[2] = Point(227.246, 610.918);
+ polygon.ps[3] = Point(227.246, 570.918);
+ new ShapeRef(router, polygon, 329);
+
+ // shapeRef330
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(283.246, 494.918);
+ polygon.ps[1] = Point(283.246, 534.918);
+ polygon.ps[2] = Point(227.246, 534.918);
+ polygon.ps[3] = Point(227.246, 494.918);
+ new ShapeRef(router, polygon, 330);
+
+ // shapeRef331
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(283.246, 462.918);
+ polygon.ps[1] = Point(283.246, 502.918);
+ polygon.ps[2] = Point(227.246, 502.918);
+ polygon.ps[3] = Point(227.246, 462.918);
+ new ShapeRef(router, polygon, 331);
+
+ // shapeRef332
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(331.246, 398.918);
+ polygon.ps[1] = Point(331.246, 438.918);
+ polygon.ps[2] = Point(275.246, 438.918);
+ polygon.ps[3] = Point(275.246, 398.918);
+ new ShapeRef(router, polygon, 332);
+
+ // shapeRef333
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(283.246, 398.918);
+ polygon.ps[1] = Point(283.246, 438.918);
+ polygon.ps[2] = Point(227.246, 438.918);
+ polygon.ps[3] = Point(227.246, 398.918);
+ new ShapeRef(router, polygon, 333);
+
+ // shapeRef334
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(283.246, 366.918);
+ polygon.ps[1] = Point(283.246, 406.918);
+ polygon.ps[2] = Point(227.246, 406.918);
+ polygon.ps[3] = Point(227.246, 366.918);
+ new ShapeRef(router, polygon, 334);
+
+ // shapeRef335
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(331.246, 236.918);
+ polygon.ps[1] = Point(331.246, 276.918);
+ polygon.ps[2] = Point(275.246, 276.918);
+ polygon.ps[3] = Point(275.246, 236.918);
+ new ShapeRef(router, polygon, 335);
+
+ // shapeRef336
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(221.246, 108.918);
+ polygon.ps[1] = Point(221.246, 148.918);
+ polygon.ps[2] = Point(165.246, 148.918);
+ polygon.ps[3] = Point(165.246, 108.918);
+ new ShapeRef(router, polygon, 336);
+
+ // shapeRef337
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(221.246, 172.918);
+ polygon.ps[1] = Point(221.246, 212.918);
+ polygon.ps[2] = Point(165.246, 212.918);
+ polygon.ps[3] = Point(165.246, 172.918);
+ new ShapeRef(router, polygon, 337);
+
+ // shapeRef338
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(173.246, 570.918);
+ polygon.ps[1] = Point(173.246, 610.918);
+ polygon.ps[2] = Point(117.246, 610.918);
+ polygon.ps[3] = Point(117.246, 570.918);
+ new ShapeRef(router, polygon, 338);
+
+ // shapeRef339
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(125.246, 602.918);
+ polygon.ps[1] = Point(125.246, 642.918);
+ polygon.ps[2] = Point(69.2456, 642.918);
+ polygon.ps[3] = Point(69.2456, 602.918);
+ new ShapeRef(router, polygon, 339);
+
+ // shapeRef340
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(125.246, 570.918);
+ polygon.ps[1] = Point(125.246, 610.918);
+ polygon.ps[2] = Point(69.2456, 610.918);
+ polygon.ps[3] = Point(69.2456, 570.918);
+ new ShapeRef(router, polygon, 340);
+
+ // shapeRef341
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(125.246, 494.918);
+ polygon.ps[1] = Point(125.246, 534.918);
+ polygon.ps[2] = Point(69.2456, 534.918);
+ polygon.ps[3] = Point(69.2456, 494.918);
+ new ShapeRef(router, polygon, 341);
+
+ // shapeRef342
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(125.246, 462.918);
+ polygon.ps[1] = Point(125.246, 502.918);
+ polygon.ps[2] = Point(69.2456, 502.918);
+ polygon.ps[3] = Point(69.2456, 462.918);
+ new ShapeRef(router, polygon, 342);
+
+ // shapeRef343
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(173.246, 398.918);
+ polygon.ps[1] = Point(173.246, 438.918);
+ polygon.ps[2] = Point(117.246, 438.918);
+ polygon.ps[3] = Point(117.246, 398.918);
+ new ShapeRef(router, polygon, 343);
+
+ // shapeRef344
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(125.246, 398.918);
+ polygon.ps[1] = Point(125.246, 438.918);
+ polygon.ps[2] = Point(69.2456, 438.918);
+ polygon.ps[3] = Point(69.2456, 398.918);
+ new ShapeRef(router, polygon, 344);
+
+ // shapeRef345
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(125.246, 366.918);
+ polygon.ps[1] = Point(125.246, 406.918);
+ polygon.ps[2] = Point(69.2456, 406.918);
+ polygon.ps[3] = Point(69.2456, 366.918);
+ new ShapeRef(router, polygon, 345);
+
+ // shapeRef346
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(45.2456, 172.918);
+ polygon.ps[1] = Point(45.2456, 212.918);
+ polygon.ps[2] = Point(-10.7544, 212.918);
+ polygon.ps[3] = Point(-10.7544, 172.918);
+ new ShapeRef(router, polygon, 346);
+
+ // shapeRef347
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(45.2456, 108.918);
+ polygon.ps[1] = Point(45.2456, 148.918);
+ polygon.ps[2] = Point(-10.7544, 148.918);
+ polygon.ps[3] = Point(-10.7544, 108.918);
+ new ShapeRef(router, polygon, 347);
+
+ // shapeRef348
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(313.246, 150.918);
+ polygon.ps[1] = Point(313.246, 190.918);
+ polygon.ps[2] = Point(257.246, 190.918);
+ polygon.ps[3] = Point(257.246, 150.918);
+ new ShapeRef(router, polygon, 348);
+
+ // shapeRef349
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(265.246, 66.9179);
+ polygon.ps[1] = Point(265.246, 106.918);
+ polygon.ps[2] = Point(209.246, 106.918);
+ polygon.ps[3] = Point(209.246, 66.9179);
+ new ShapeRef(router, polygon, 349);
+
+ // shapeRef350
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(265.246, 34.9179);
+ polygon.ps[1] = Point(265.246, 74.9179);
+ polygon.ps[2] = Point(209.246, 74.9179);
+ polygon.ps[3] = Point(209.246, 34.9179);
+ new ShapeRef(router, polygon, 350);
+
+ // shapeRef351
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(125.246, 150.918);
+ polygon.ps[1] = Point(125.246, 190.918);
+ polygon.ps[2] = Point(69.2456, 190.918);
+ polygon.ps[3] = Point(69.2456, 150.918);
+ new ShapeRef(router, polygon, 351);
+
+ // shapeRef352
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(125.246, 12.9179);
+ polygon.ps[1] = Point(125.246, 52.9179);
+ polygon.ps[2] = Point(69.2456, 52.9179);
+ polygon.ps[3] = Point(69.2456, 12.9179);
+ new ShapeRef(router, polygon, 352);
+
+ // shapeRef353
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(125.246, -19.0821);
+ polygon.ps[1] = Point(125.246, 20.9179);
+ polygon.ps[2] = Point(69.2456, 20.9179);
+ polygon.ps[3] = Point(69.2456, -19.0821);
+ new ShapeRef(router, polygon, 353);
+
+ // shapeRef354
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(408.962, -49.0821);
+ polygon.ps[1] = Point(408.962, -9.08205);
+ polygon.ps[2] = Point(352.962, -9.08205);
+ polygon.ps[3] = Point(352.962, -49.0821);
+ new ShapeRef(router, polygon, 354);
+
+ // shapeRef355
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(307.219, -49.0821);
+ polygon.ps[1] = Point(307.219, -9.08205);
+ polygon.ps[2] = Point(251.219, -9.08205);
+ polygon.ps[3] = Point(251.219, -49.0821);
+ new ShapeRef(router, polygon, 355);
+
+ // shapeRef356
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(125.246, 290.918);
+ polygon.ps[1] = Point(125.246, 330.918);
+ polygon.ps[2] = Point(69.2456, 330.918);
+ polygon.ps[3] = Point(69.2456, 290.918);
+ new ShapeRef(router, polygon, 356);
+
+ // shapeRef357
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(221.246, 204.918);
+ polygon.ps[1] = Point(221.246, 244.918);
+ polygon.ps[2] = Point(165.246, 244.918);
+ polygon.ps[3] = Point(165.246, 204.918);
+ new ShapeRef(router, polygon, 357);
+
+ // shapeRef358
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(361.246, 204.918);
+ polygon.ps[1] = Point(361.246, 244.918);
+ polygon.ps[2] = Point(305.246, 244.918);
+ polygon.ps[3] = Point(305.246, 204.918);
+ new ShapeRef(router, polygon, 358);
+
+ // shapeRef359
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(517.246, 204.918);
+ polygon.ps[1] = Point(517.246, 244.918);
+ polygon.ps[2] = Point(461.246, 244.918);
+ polygon.ps[3] = Point(461.246, 204.918);
+ new ShapeRef(router, polygon, 359);
+
+ // shapeRef360
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(673.246, 204.918);
+ polygon.ps[1] = Point(673.246, 244.918);
+ polygon.ps[2] = Point(617.246, 244.918);
+ polygon.ps[3] = Point(617.246, 204.918);
+ new ShapeRef(router, polygon, 360);
+
+ // shapeRef361
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(829.246, 204.918);
+ polygon.ps[1] = Point(829.246, 244.918);
+ polygon.ps[2] = Point(773.246, 244.918);
+ polygon.ps[3] = Point(773.246, 204.918);
+ new ShapeRef(router, polygon, 361);
+
+ // shapeRef362
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(985.246, 204.918);
+ polygon.ps[1] = Point(985.246, 244.918);
+ polygon.ps[2] = Point(929.246, 244.918);
+ polygon.ps[3] = Point(929.246, 204.918);
+ new ShapeRef(router, polygon, 362);
+
+ // shapeRef363
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(45.2456, 344.918);
+ polygon.ps[1] = Point(45.2456, 384.918);
+ polygon.ps[2] = Point(-10.7544, 384.918);
+ polygon.ps[3] = Point(-10.7544, 344.918);
+ new ShapeRef(router, polygon, 363);
+
+ // shapeRef364
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(283.246, 430.918);
+ polygon.ps[1] = Point(283.246, 470.918);
+ polygon.ps[2] = Point(227.246, 470.918);
+ polygon.ps[3] = Point(227.246, 430.918);
+ new ShapeRef(router, polygon, 364);
+
+ // shapeRef365
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(439.246, 430.918);
+ polygon.ps[1] = Point(439.246, 470.918);
+ polygon.ps[2] = Point(383.246, 470.918);
+ polygon.ps[3] = Point(383.246, 430.918);
+ new ShapeRef(router, polygon, 365);
+
+ // shapeRef366
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(595.246, 430.918);
+ polygon.ps[1] = Point(595.246, 470.918);
+ polygon.ps[2] = Point(539.246, 470.918);
+ polygon.ps[3] = Point(539.246, 430.918);
+ new ShapeRef(router, polygon, 366);
+
+ // shapeRef367
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(907.246, 430.918);
+ polygon.ps[1] = Point(907.246, 470.918);
+ polygon.ps[2] = Point(851.246, 470.918);
+ polygon.ps[3] = Point(851.246, 430.918);
+ new ShapeRef(router, polygon, 367);
+
+ // shapeRef368
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1063.25, 430.918);
+ polygon.ps[1] = Point(1063.25, 470.918);
+ polygon.ps[2] = Point(1007.25, 470.918);
+ polygon.ps[3] = Point(1007.25, 430.918);
+ new ShapeRef(router, polygon, 368);
+
+ // shapeRef369
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(751.246, 430.918);
+ polygon.ps[1] = Point(751.246, 470.918);
+ polygon.ps[2] = Point(695.246, 470.918);
+ polygon.ps[3] = Point(695.246, 430.918);
+ new ShapeRef(router, polygon, 369);
+
+ // shapeRef370
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(125.246, 538.918);
+ polygon.ps[1] = Point(125.246, 578.918);
+ polygon.ps[2] = Point(69.2456, 578.918);
+ polygon.ps[3] = Point(69.2456, 538.918);
+ new ShapeRef(router, polygon, 370);
+
+ // shapeRef371
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(283.246, 538.918);
+ polygon.ps[1] = Point(283.246, 578.918);
+ polygon.ps[2] = Point(227.246, 578.918);
+ polygon.ps[3] = Point(227.246, 538.918);
+ new ShapeRef(router, polygon, 371);
+
+ // shapeRef372
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(439.246, 538.918);
+ polygon.ps[1] = Point(439.246, 578.918);
+ polygon.ps[2] = Point(383.246, 578.918);
+ polygon.ps[3] = Point(383.246, 538.918);
+ new ShapeRef(router, polygon, 372);
+
+ // shapeRef373
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(595.246, 538.918);
+ polygon.ps[1] = Point(595.246, 578.918);
+ polygon.ps[2] = Point(539.246, 578.918);
+ polygon.ps[3] = Point(539.246, 538.918);
+ new ShapeRef(router, polygon, 373);
+
+ // shapeRef374
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(751.246, 538.918);
+ polygon.ps[1] = Point(751.246, 578.918);
+ polygon.ps[2] = Point(695.246, 578.918);
+ polygon.ps[3] = Point(695.246, 538.918);
+ new ShapeRef(router, polygon, 374);
+
+ // shapeRef375
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(907.246, 538.918);
+ polygon.ps[1] = Point(907.246, 578.918);
+ polygon.ps[2] = Point(851.246, 578.918);
+ polygon.ps[3] = Point(851.246, 538.918);
+ new ShapeRef(router, polygon, 375);
+
+ // shapeRef376
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1063.25, 538.918);
+ polygon.ps[1] = Point(1063.25, 578.918);
+ polygon.ps[2] = Point(1007.25, 578.918);
+ polygon.ps[3] = Point(1007.25, 538.918);
+ new ShapeRef(router, polygon, 376);
+
+ // shapeRef377
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(125.246, 634.918);
+ polygon.ps[1] = Point(125.246, 674.918);
+ polygon.ps[2] = Point(69.2456, 674.918);
+ polygon.ps[3] = Point(69.2456, 634.918);
+ new ShapeRef(router, polygon, 377);
+
+ // shapeRef378
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(283.246, 634.918);
+ polygon.ps[1] = Point(283.246, 674.918);
+ polygon.ps[2] = Point(227.246, 674.918);
+ polygon.ps[3] = Point(227.246, 634.918);
+ new ShapeRef(router, polygon, 378);
+
+ // shapeRef379
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(439.246, 634.918);
+ polygon.ps[1] = Point(439.246, 674.918);
+ polygon.ps[2] = Point(383.246, 674.918);
+ polygon.ps[3] = Point(383.246, 634.918);
+ new ShapeRef(router, polygon, 379);
+
+ // shapeRef380
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(595.246, 634.918);
+ polygon.ps[1] = Point(595.246, 674.918);
+ polygon.ps[2] = Point(539.246, 674.918);
+ polygon.ps[3] = Point(539.246, 634.918);
+ new ShapeRef(router, polygon, 380);
+
+ // shapeRef381
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(751.246, 634.918);
+ polygon.ps[1] = Point(751.246, 674.918);
+ polygon.ps[2] = Point(695.246, 674.918);
+ polygon.ps[3] = Point(695.246, 634.918);
+ new ShapeRef(router, polygon, 381);
+
+ // shapeRef382
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(907.246, 634.918);
+ polygon.ps[1] = Point(907.246, 674.918);
+ polygon.ps[2] = Point(851.246, 674.918);
+ polygon.ps[3] = Point(851.246, 634.918);
+ new ShapeRef(router, polygon, 382);
+
+ // shapeRef383
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1063.25, 634.918);
+ polygon.ps[1] = Point(1063.25, 674.918);
+ polygon.ps[2] = Point(1007.25, 674.918);
+ polygon.ps[3] = Point(1007.25, 634.918);
+ new ShapeRef(router, polygon, 383);
+
+ // shapeRef384
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1261.25, 172.918);
+ polygon.ps[1] = Point(1261.25, 212.918);
+ polygon.ps[2] = Point(1205.25, 212.918);
+ polygon.ps[3] = Point(1205.25, 172.918);
+ new ShapeRef(router, polygon, 384);
+
+ // shapeRef385
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1351.25, 398.918);
+ polygon.ps[1] = Point(1351.25, 438.918);
+ polygon.ps[2] = Point(1295.25, 438.918);
+ polygon.ps[3] = Point(1295.25, 398.918);
+ new ShapeRef(router, polygon, 385);
+
+ // shapeRef386
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1351.25, 494.918);
+ polygon.ps[1] = Point(1351.25, 534.918);
+ polygon.ps[2] = Point(1295.25, 534.918);
+ polygon.ps[3] = Point(1295.25, 494.918);
+ new ShapeRef(router, polygon, 386);
+
+ // shapeRef387
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1351.25, 602.918);
+ polygon.ps[1] = Point(1351.25, 642.918);
+ polygon.ps[2] = Point(1295.25, 642.918);
+ polygon.ps[3] = Point(1295.25, 602.918);
+ new ShapeRef(router, polygon, 387);
+
+ // shapeRef388
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1063.25, 698.918);
+ polygon.ps[1] = Point(1063.25, 738.918);
+ polygon.ps[2] = Point(1007.25, 738.918);
+ polygon.ps[3] = Point(1007.25, 698.918);
+ new ShapeRef(router, polygon, 388);
+
+ // shapeRef389
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1063.25, 730.918);
+ polygon.ps[1] = Point(1063.25, 770.918);
+ polygon.ps[2] = Point(1007.25, 770.918);
+ polygon.ps[3] = Point(1007.25, 730.918);
+ new ShapeRef(router, polygon, 389);
+
+ // shapeRef390
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1351.25, 698.918);
+ polygon.ps[1] = Point(1351.25, 738.918);
+ polygon.ps[2] = Point(1295.25, 738.918);
+ polygon.ps[3] = Point(1295.25, 698.918);
+ new ShapeRef(router, polygon, 390);
+
+ // shapeRef391
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1321.25, 182.918);
+ polygon.ps[1] = Point(1321.25, 222.918);
+ polygon.ps[2] = Point(1265.25, 222.918);
+ polygon.ps[3] = Point(1265.25, 182.918);
+ new ShapeRef(router, polygon, 391);
+
+ // shapeRef392
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1447.25, 624.918);
+ polygon.ps[1] = Point(1447.25, 664.918);
+ polygon.ps[2] = Point(1391.25, 664.918);
+ polygon.ps[3] = Point(1391.25, 624.918);
+ new ShapeRef(router, polygon, 392);
+
+ // shapeRef393
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(173.246, 226.918);
+ polygon.ps[1] = Point(173.246, 266.918);
+ polygon.ps[2] = Point(117.246, 266.918);
+ polygon.ps[3] = Point(117.246, 226.918);
+ new ShapeRef(router, polygon, 393);
+
+ // shapeRef394
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(173.246, 258.918);
+ polygon.ps[1] = Point(173.246, 298.918);
+ polygon.ps[2] = Point(117.246, 298.918);
+ polygon.ps[3] = Point(117.246, 258.918);
+ new ShapeRef(router, polygon, 394);
+
+ // shapeRef395
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(372.466, 14.9179);
+ polygon.ps[1] = Point(372.466, 54.9179);
+ polygon.ps[2] = Point(312.466, 54.9179);
+ polygon.ps[3] = Point(312.466, 14.9179);
+ new ShapeRef(router, polygon, 395);
+
+ // shapeRef396
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(47.2456, -91.0821);
+ polygon.ps[1] = Point(47.2456, -51.0821);
+ polygon.ps[2] = Point(-12.7544, -51.0821);
+ polygon.ps[3] = Point(-12.7544, -91.0821);
+ new ShapeRef(router, polygon, 396);
+
+ // shapeRef397
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(372.466, 66.9179);
+ polygon.ps[1] = Point(372.466, 106.918);
+ polygon.ps[2] = Point(312.466, 106.918);
+ polygon.ps[3] = Point(312.466, 66.9179);
+ new ShapeRef(router, polygon, 397);
+
+ // connRef398
+ connRef = new ConnRef(router, 398);
+ srcPt = ConnEnd(Point(982, 596), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef399
+ connRef = new ConnRef(router, 399);
+ srcPt = ConnEnd(Point(840, 596), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef400
+ connRef = new ConnRef(router, 400);
+ srcPt = ConnEnd(Point(699, 596), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef401
+ connRef = new ConnRef(router, 401);
+ srcPt = ConnEnd(Point(557, 596), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef402
+ connRef = new ConnRef(router, 402);
+ srcPt = ConnEnd(Point(415, 596), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef403
+ connRef = new ConnRef(router, 403);
+ srcPt = ConnEnd(Point(273, 596), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef404
+ connRef = new ConnRef(router, 404);
+ srcPt = ConnEnd(Point(132, 615), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef405
+ connRef = new ConnRef(router, 405);
+ srcPt = ConnEnd(Point(1203.25, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1227, 632), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef406
+ connRef = new ConnRef(router, 406);
+ srcPt = ConnEnd(Point(1209, 586), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1203.25, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef407
+ connRef = new ConnRef(router, 407);
+ srcPt = ConnEnd(Point(1203.25, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1209, 667), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef408
+ connRef = new ConnRef(router, 408);
+ srcPt = ConnEnd(Point(1203.25, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1159, 667), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef409
+ connRef = new ConnRef(router, 409);
+ srcPt = ConnEnd(Point(1209, 566), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1203.25, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef410
+ connRef = new ConnRef(router, 410);
+ srcPt = ConnEnd(Point(1209, 505), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1203.25, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef411
+ connRef = new ConnRef(router, 411);
+ srcPt = ConnEnd(Point(1159, 575), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1203.25, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef412
+ connRef = new ConnRef(router, 412);
+ srcPt = ConnEnd(Point(1209, 585), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1203.25, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef413
+ connRef = new ConnRef(router, 413);
+ srcPt = ConnEnd(Point(1209, 485), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1203.25, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef414
+ connRef = new ConnRef(router, 414);
+ srcPt = ConnEnd(Point(1209, 414), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1203.25, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef415
+ connRef = new ConnRef(router, 415);
+ srcPt = ConnEnd(Point(1159, 485), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1203.25, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef416
+ connRef = new ConnRef(router, 416);
+ srcPt = ConnEnd(Point(1209, 394), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1203.25, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef417
+ connRef = new ConnRef(router, 417);
+ srcPt = ConnEnd(Point(1159, 394), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1203.25, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef418
+ connRef = new ConnRef(router, 418);
+ srcPt = ConnEnd(Point(1449.25, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1299, 667), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef419
+ connRef = new ConnRef(router, 419);
+ srcPt = ConnEnd(Point(1171.25, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1059, 667), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef420
+ connRef = new ConnRef(router, 420);
+ srcPt = ConnEnd(Point(1171.25, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1109, 667), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef421
+ connRef = new ConnRef(router, 421);
+ srcPt = ConnEnd(Point(1050, 634), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1171.25, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef422
+ connRef = new ConnRef(router, 422);
+ srcPt = ConnEnd(Point(790, 687), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 750.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef423
+ connRef = new ConnRef(router, 423);
+ srcPt = ConnEnd(Point(1059, 687), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1171.25, 750.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef424
+ connRef = new ConnRef(router, 424);
+ srcPt = ConnEnd(Point(1109, 687), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1171.25, 750.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef425
+ connRef = new ConnRef(router, 425);
+ srcPt = ConnEnd(Point(533, 687), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 750.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef426
+ connRef = new ConnRef(router, 426);
+ srcPt = ConnEnd(Point(390, 687), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 750.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef427
+ connRef = new ConnRef(router, 427);
+ srcPt = ConnEnd(Point(1247, 632), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1449.25, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef428
+ connRef = new ConnRef(router, 428);
+ srcPt = ConnEnd(Point(982, 615), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef429
+ connRef = new ConnRef(router, 429);
+ srcPt = ConnEnd(Point(840, 615), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef430
+ connRef = new ConnRef(router, 430);
+ srcPt = ConnEnd(Point(699, 615), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef431
+ connRef = new ConnRef(router, 431);
+ srcPt = ConnEnd(Point(557, 615), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef432
+ connRef = new ConnRef(router, 432);
+ srcPt = ConnEnd(Point(415, 615), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef433
+ connRef = new ConnRef(router, 433);
+ srcPt = ConnEnd(Point(273, 615), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef434
+ connRef = new ConnRef(router, 434);
+ srcPt = ConnEnd(Point(132, 596), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef435
+ connRef = new ConnRef(router, 435);
+ srcPt = ConnEnd(Point(982, 516), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef436
+ connRef = new ConnRef(router, 436);
+ srcPt = ConnEnd(Point(982, 496), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef437
+ connRef = new ConnRef(router, 437);
+ srcPt = ConnEnd(Point(840, 496), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef438
+ connRef = new ConnRef(router, 438);
+ srcPt = ConnEnd(Point(840, 516), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef439
+ connRef = new ConnRef(router, 439);
+ srcPt = ConnEnd(Point(699, 516), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef440
+ connRef = new ConnRef(router, 440);
+ srcPt = ConnEnd(Point(699, 496), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef441
+ connRef = new ConnRef(router, 441);
+ srcPt = ConnEnd(Point(557, 496), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef442
+ connRef = new ConnRef(router, 442);
+ srcPt = ConnEnd(Point(557, 516), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef443
+ connRef = new ConnRef(router, 443);
+ srcPt = ConnEnd(Point(415, 516), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef444
+ connRef = new ConnRef(router, 444);
+ srcPt = ConnEnd(Point(415, 496), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef445
+ connRef = new ConnRef(router, 445);
+ srcPt = ConnEnd(Point(273, 496), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef446
+ connRef = new ConnRef(router, 446);
+ srcPt = ConnEnd(Point(273, 516), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef447
+ connRef = new ConnRef(router, 447);
+ srcPt = ConnEnd(Point(132, 496), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef448
+ connRef = new ConnRef(router, 448);
+ srcPt = ConnEnd(Point(132, 516), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef449
+ connRef = new ConnRef(router, 449);
+ srcPt = ConnEnd(Point(1219, 319), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1203.25, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef450
+ connRef = new ConnRef(router, 450);
+ srcPt = ConnEnd(Point(1199, 319), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef451
+ connRef = new ConnRef(router, 451);
+ srcPt = ConnEnd(Point(1199, 319), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef452
+ connRef = new ConnRef(router, 452);
+ srcPt = ConnEnd(Point(1209, 687), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1203.25, 750.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef453
+ connRef = new ConnRef(router, 453);
+ srcPt = ConnEnd(Point(1299, 687), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1449.25, 750.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef454
+ connRef = new ConnRef(router, 454);
+ srcPt = ConnEnd(Point(649, 687), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 750.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef455
+ connRef = new ConnRef(router, 455);
+ srcPt = ConnEnd(Point(840, 687), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 750.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef456
+ connRef = new ConnRef(router, 456);
+ srcPt = ConnEnd(Point(132, 195), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 160.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef457
+ connRef = new ConnRef(router, 457);
+ srcPt = ConnEnd(Point(132, 338), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef458
+ connRef = new ConnRef(router, 458);
+ srcPt = ConnEnd(Point(992, 319), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef459
+ connRef = new ConnRef(router, 459);
+ srcPt = ConnEnd(Point(850, 319), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef460
+ connRef = new ConnRef(router, 460);
+ srcPt = ConnEnd(Point(709, 319), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef461
+ connRef = new ConnRef(router, 461);
+ srcPt = ConnEnd(Point(567, 319), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef462
+ connRef = new ConnRef(router, 462);
+ srcPt = ConnEnd(Point(425, 319), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef463
+ connRef = new ConnRef(router, 463);
+ srcPt = ConnEnd(Point(273, 309), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef464
+ connRef = new ConnRef(router, 464);
+ srcPt = ConnEnd(Point(982, 687), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 750.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef465
+ connRef = new ConnRef(router, 465);
+ srcPt = ConnEnd(Point(932, 668), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 750.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef466
+ connRef = new ConnRef(router, 466);
+ srcPt = ConnEnd(Point(982, 577), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef467
+ connRef = new ConnRef(router, 467);
+ srcPt = ConnEnd(Point(982, 557), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef468
+ connRef = new ConnRef(router, 468);
+ srcPt = ConnEnd(Point(932, 596), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef469
+ connRef = new ConnRef(router, 469);
+ srcPt = ConnEnd(Point(932, 576), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef470
+ connRef = new ConnRef(router, 470);
+ srcPt = ConnEnd(Point(932, 577), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef471
+ connRef = new ConnRef(router, 471);
+ srcPt = ConnEnd(Point(932, 557), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef472
+ connRef = new ConnRef(router, 472);
+ srcPt = ConnEnd(Point(932, 505), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef473
+ connRef = new ConnRef(router, 473);
+ srcPt = ConnEnd(Point(932, 485), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef474
+ connRef = new ConnRef(router, 474);
+ srcPt = ConnEnd(Point(932, 486), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef475
+ connRef = new ConnRef(router, 475);
+ srcPt = ConnEnd(Point(932, 466), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef476
+ connRef = new ConnRef(router, 476);
+ srcPt = ConnEnd(Point(982, 414), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef477
+ connRef = new ConnRef(router, 477);
+ srcPt = ConnEnd(Point(982, 394), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef478
+ connRef = new ConnRef(router, 478);
+ srcPt = ConnEnd(Point(932, 414), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef479
+ connRef = new ConnRef(router, 479);
+ srcPt = ConnEnd(Point(932, 394), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef480
+ connRef = new ConnRef(router, 480);
+ srcPt = ConnEnd(Point(932, 395), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef481
+ connRef = new ConnRef(router, 481);
+ srcPt = ConnEnd(Point(932, 375), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef482
+ connRef = new ConnRef(router, 482);
+ srcPt = ConnEnd(Point(992, 300), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef483
+ connRef = new ConnRef(router, 483);
+ srcPt = ConnEnd(Point(942, 309), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef484
+ connRef = new ConnRef(router, 484);
+ srcPt = ConnEnd(Point(942, 290), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef485
+ connRef = new ConnRef(router, 485);
+ srcPt = ConnEnd(Point(840, 557), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef486
+ connRef = new ConnRef(router, 486);
+ srcPt = ConnEnd(Point(840, 577), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef487
+ connRef = new ConnRef(router, 487);
+ srcPt = ConnEnd(Point(790, 576), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef488
+ connRef = new ConnRef(router, 488);
+ srcPt = ConnEnd(Point(790, 596), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef489
+ connRef = new ConnRef(router, 489);
+ srcPt = ConnEnd(Point(790, 557), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef490
+ connRef = new ConnRef(router, 490);
+ srcPt = ConnEnd(Point(790, 577), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef491
+ connRef = new ConnRef(router, 491);
+ srcPt = ConnEnd(Point(790, 485), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef492
+ connRef = new ConnRef(router, 492);
+ srcPt = ConnEnd(Point(790, 505), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef493
+ connRef = new ConnRef(router, 493);
+ srcPt = ConnEnd(Point(790, 466), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef494
+ connRef = new ConnRef(router, 494);
+ srcPt = ConnEnd(Point(790, 486), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef495
+ connRef = new ConnRef(router, 495);
+ srcPt = ConnEnd(Point(840, 394), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef496
+ connRef = new ConnRef(router, 496);
+ srcPt = ConnEnd(Point(840, 414), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef497
+ connRef = new ConnRef(router, 497);
+ srcPt = ConnEnd(Point(790, 394), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef498
+ connRef = new ConnRef(router, 498);
+ srcPt = ConnEnd(Point(790, 414), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef499
+ connRef = new ConnRef(router, 499);
+ srcPt = ConnEnd(Point(790, 375), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef500
+ connRef = new ConnRef(router, 500);
+ srcPt = ConnEnd(Point(790, 395), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef501
+ connRef = new ConnRef(router, 501);
+ srcPt = ConnEnd(Point(850, 300), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef502
+ connRef = new ConnRef(router, 502);
+ srcPt = ConnEnd(Point(800, 309), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef503
+ connRef = new ConnRef(router, 503);
+ srcPt = ConnEnd(Point(800, 290), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef504
+ connRef = new ConnRef(router, 504);
+ srcPt = ConnEnd(Point(699, 577), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef505
+ connRef = new ConnRef(router, 505);
+ srcPt = ConnEnd(Point(699, 557), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef506
+ connRef = new ConnRef(router, 506);
+ srcPt = ConnEnd(Point(649, 596), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef507
+ connRef = new ConnRef(router, 507);
+ srcPt = ConnEnd(Point(649, 576), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef508
+ connRef = new ConnRef(router, 508);
+ srcPt = ConnEnd(Point(649, 577), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef509
+ connRef = new ConnRef(router, 509);
+ srcPt = ConnEnd(Point(649, 557), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef510
+ connRef = new ConnRef(router, 510);
+ srcPt = ConnEnd(Point(649, 505), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef511
+ connRef = new ConnRef(router, 511);
+ srcPt = ConnEnd(Point(649, 485), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef512
+ connRef = new ConnRef(router, 512);
+ srcPt = ConnEnd(Point(649, 486), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef513
+ connRef = new ConnRef(router, 513);
+ srcPt = ConnEnd(Point(649, 466), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef514
+ connRef = new ConnRef(router, 514);
+ srcPt = ConnEnd(Point(699, 414), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef515
+ connRef = new ConnRef(router, 515);
+ srcPt = ConnEnd(Point(699, 394), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef516
+ connRef = new ConnRef(router, 516);
+ srcPt = ConnEnd(Point(649, 414), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef517
+ connRef = new ConnRef(router, 517);
+ srcPt = ConnEnd(Point(649, 394), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef518
+ connRef = new ConnRef(router, 518);
+ srcPt = ConnEnd(Point(649, 395), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef519
+ connRef = new ConnRef(router, 519);
+ srcPt = ConnEnd(Point(649, 375), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef520
+ connRef = new ConnRef(router, 520);
+ srcPt = ConnEnd(Point(709, 300), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef521
+ connRef = new ConnRef(router, 521);
+ srcPt = ConnEnd(Point(659, 309), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef522
+ connRef = new ConnRef(router, 522);
+ srcPt = ConnEnd(Point(659, 290), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef523
+ connRef = new ConnRef(router, 523);
+ srcPt = ConnEnd(Point(557, 557), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef524
+ connRef = new ConnRef(router, 524);
+ srcPt = ConnEnd(Point(557, 577), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef525
+ connRef = new ConnRef(router, 525);
+ srcPt = ConnEnd(Point(507, 576), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef526
+ connRef = new ConnRef(router, 526);
+ srcPt = ConnEnd(Point(507, 596), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef527
+ connRef = new ConnRef(router, 527);
+ srcPt = ConnEnd(Point(507, 557), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef528
+ connRef = new ConnRef(router, 528);
+ srcPt = ConnEnd(Point(507, 577), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef529
+ connRef = new ConnRef(router, 529);
+ srcPt = ConnEnd(Point(557, 477), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef530
+ connRef = new ConnRef(router, 530);
+ srcPt = ConnEnd(Point(557, 497), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef531
+ connRef = new ConnRef(router, 531);
+ srcPt = ConnEnd(Point(507, 485), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef532
+ connRef = new ConnRef(router, 532);
+ srcPt = ConnEnd(Point(507, 505), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef533
+ connRef = new ConnRef(router, 533);
+ srcPt = ConnEnd(Point(507, 466), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef534
+ connRef = new ConnRef(router, 534);
+ srcPt = ConnEnd(Point(507, 486), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef535
+ connRef = new ConnRef(router, 535);
+ srcPt = ConnEnd(Point(557, 394), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef536
+ connRef = new ConnRef(router, 536);
+ srcPt = ConnEnd(Point(557, 414), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef537
+ connRef = new ConnRef(router, 537);
+ srcPt = ConnEnd(Point(507, 394), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef538
+ connRef = new ConnRef(router, 538);
+ srcPt = ConnEnd(Point(507, 414), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef539
+ connRef = new ConnRef(router, 539);
+ srcPt = ConnEnd(Point(507, 375), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef540
+ connRef = new ConnRef(router, 540);
+ srcPt = ConnEnd(Point(507, 395), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef541
+ connRef = new ConnRef(router, 541);
+ srcPt = ConnEnd(Point(567, 300), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef542
+ connRef = new ConnRef(router, 542);
+ srcPt = ConnEnd(Point(517, 309), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef543
+ connRef = new ConnRef(router, 543);
+ srcPt = ConnEnd(Point(517, 290), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef544
+ connRef = new ConnRef(router, 544);
+ srcPt = ConnEnd(Point(415, 577), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef545
+ connRef = new ConnRef(router, 545);
+ srcPt = ConnEnd(Point(415, 557), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef546
+ connRef = new ConnRef(router, 546);
+ srcPt = ConnEnd(Point(365, 596), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef547
+ connRef = new ConnRef(router, 547);
+ srcPt = ConnEnd(Point(365, 576), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef548
+ connRef = new ConnRef(router, 548);
+ srcPt = ConnEnd(Point(365, 577), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef549
+ connRef = new ConnRef(router, 549);
+ srcPt = ConnEnd(Point(365, 557), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef550
+ connRef = new ConnRef(router, 550);
+ srcPt = ConnEnd(Point(365, 505), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef551
+ connRef = new ConnRef(router, 551);
+ srcPt = ConnEnd(Point(365, 485), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef552
+ connRef = new ConnRef(router, 552);
+ srcPt = ConnEnd(Point(365, 486), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef553
+ connRef = new ConnRef(router, 553);
+ srcPt = ConnEnd(Point(365, 466), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef554
+ connRef = new ConnRef(router, 554);
+ srcPt = ConnEnd(Point(415, 414), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef555
+ connRef = new ConnRef(router, 555);
+ srcPt = ConnEnd(Point(415, 394), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef556
+ connRef = new ConnRef(router, 556);
+ srcPt = ConnEnd(Point(365, 414), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef557
+ connRef = new ConnRef(router, 557);
+ srcPt = ConnEnd(Point(365, 394), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef558
+ connRef = new ConnRef(router, 558);
+ srcPt = ConnEnd(Point(365, 395), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef559
+ connRef = new ConnRef(router, 559);
+ srcPt = ConnEnd(Point(365, 375), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef560
+ connRef = new ConnRef(router, 560);
+ srcPt = ConnEnd(Point(425, 300), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef561
+ connRef = new ConnRef(router, 561);
+ srcPt = ConnEnd(Point(375, 309), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef562
+ connRef = new ConnRef(router, 562);
+ srcPt = ConnEnd(Point(375, 290), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef563
+ connRef = new ConnRef(router, 563);
+ srcPt = ConnEnd(Point(273, 557), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef564
+ connRef = new ConnRef(router, 564);
+ srcPt = ConnEnd(Point(273, 577), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef565
+ connRef = new ConnRef(router, 565);
+ srcPt = ConnEnd(Point(223, 576), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef566
+ connRef = new ConnRef(router, 566);
+ srcPt = ConnEnd(Point(223, 596), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef567
+ connRef = new ConnRef(router, 567);
+ srcPt = ConnEnd(Point(223, 557), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef568
+ connRef = new ConnRef(router, 568);
+ srcPt = ConnEnd(Point(223, 577), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef569
+ connRef = new ConnRef(router, 569);
+ srcPt = ConnEnd(Point(223, 485), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef570
+ connRef = new ConnRef(router, 570);
+ srcPt = ConnEnd(Point(223, 505), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef571
+ connRef = new ConnRef(router, 571);
+ srcPt = ConnEnd(Point(223, 466), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef572
+ connRef = new ConnRef(router, 572);
+ srcPt = ConnEnd(Point(223, 486), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef573
+ connRef = new ConnRef(router, 573);
+ srcPt = ConnEnd(Point(273, 394), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef574
+ connRef = new ConnRef(router, 574);
+ srcPt = ConnEnd(Point(273, 414), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef575
+ connRef = new ConnRef(router, 575);
+ srcPt = ConnEnd(Point(223, 394), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef576
+ connRef = new ConnRef(router, 576);
+ srcPt = ConnEnd(Point(223, 414), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef577
+ connRef = new ConnRef(router, 577);
+ srcPt = ConnEnd(Point(223, 375), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef578
+ connRef = new ConnRef(router, 578);
+ srcPt = ConnEnd(Point(223, 395), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef579
+ connRef = new ConnRef(router, 579);
+ srcPt = ConnEnd(Point(273, 290), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef580
+ connRef = new ConnRef(router, 580);
+ srcPt = ConnEnd(Point(233, 290), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef581
+ connRef = new ConnRef(router, 581);
+ srcPt = ConnEnd(Point(233, 309), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef582
+ connRef = new ConnRef(router, 582);
+ srcPt = ConnEnd(Point(132, 557), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef583
+ connRef = new ConnRef(router, 583);
+ srcPt = ConnEnd(Point(132, 577), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef584
+ connRef = new ConnRef(router, 584);
+ srcPt = ConnEnd(Point(82, 576), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef585
+ connRef = new ConnRef(router, 585);
+ srcPt = ConnEnd(Point(82, 596), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef586
+ connRef = new ConnRef(router, 586);
+ srcPt = ConnEnd(Point(82, 557), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef587
+ connRef = new ConnRef(router, 587);
+ srcPt = ConnEnd(Point(82, 577), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef588
+ connRef = new ConnRef(router, 588);
+ srcPt = ConnEnd(Point(82, 485), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef589
+ connRef = new ConnRef(router, 589);
+ srcPt = ConnEnd(Point(82, 505), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef590
+ connRef = new ConnRef(router, 590);
+ srcPt = ConnEnd(Point(82, 466), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef591
+ connRef = new ConnRef(router, 591);
+ srcPt = ConnEnd(Point(82, 486), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef592
+ connRef = new ConnRef(router, 592);
+ srcPt = ConnEnd(Point(132, 394), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef593
+ connRef = new ConnRef(router, 593);
+ srcPt = ConnEnd(Point(132, 414), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef594
+ connRef = new ConnRef(router, 594);
+ srcPt = ConnEnd(Point(82, 394), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef595
+ connRef = new ConnRef(router, 595);
+ srcPt = ConnEnd(Point(82, 414), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef596
+ connRef = new ConnRef(router, 596);
+ srcPt = ConnEnd(Point(82, 375), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef597
+ connRef = new ConnRef(router, 597);
+ srcPt = ConnEnd(Point(82, 395), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef598
+ connRef = new ConnRef(router, 598);
+ srcPt = ConnEnd(Point(72, 309), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef599
+ connRef = new ConnRef(router, 599);
+ srcPt = ConnEnd(Point(72, 290), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef600
+ connRef = new ConnRef(router, 600);
+ srcPt = ConnEnd(Point(245, 207), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(197.246, 96.9179), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef601
+ connRef = new ConnRef(router, 601);
+ srcPt = ConnEnd(Point(245, 227), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef602
+ connRef = new ConnRef(router, 602);
+ srcPt = ConnEnd(Point(195, 217), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(197.246, 96.9179), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef603
+ connRef = new ConnRef(router, 603);
+ srcPt = ConnEnd(Point(195, 237), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef604
+ connRef = new ConnRef(router, 604);
+ srcPt = ConnEnd(Point(195, 198), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(197.246, 96.9179), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef605
+ connRef = new ConnRef(router, 605);
+ srcPt = ConnEnd(Point(195, 218), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef606
+ connRef = new ConnRef(router, 606);
+ srcPt = ConnEnd(Point(82, 214), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 160.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef607
+ connRef = new ConnRef(router, 607);
+ srcPt = ConnEnd(Point(82, 195), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 160.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef608
+ connRef = new ConnRef(router, 608);
+ srcPt = ConnEnd(Point(82, 176), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 160.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef609
+ connRef = new ConnRef(router, 609);
+ srcPt = ConnEnd(Point(319, 135), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(319.219, -51.0821), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef610
+ connRef = new ConnRef(router, 610);
+ srcPt = ConnEnd(Point(220, 135), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 125.987), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef611
+ connRef = new ConnRef(router, 611);
+ srcPt = ConnEnd(Point(220, 155), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(319.219, -7.08205), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef612
+ connRef = new ConnRef(router, 612);
+ srcPt = ConnEnd(Point(220, 155), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(197.246, 96.9179), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef613
+ connRef = new ConnRef(router, 613);
+ srcPt = ConnEnd(Point(220, 135), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(319.219, -51.0821), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef614
+ connRef = new ConnRef(router, 614);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(82, 318), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef615
+ connRef = new ConnRef(router, 615);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(213, 328), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef616
+ connRef = new ConnRef(router, 616);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(355, 328), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef617
+ connRef = new ConnRef(router, 617);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(497, 328), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef618
+ connRef = new ConnRef(router, 618);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(639, 328), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef619
+ connRef = new ConnRef(router, 619);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(780, 328), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef620
+ connRef = new ConnRef(router, 620);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(922, 328), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef621
+ connRef = new ConnRef(router, 621);
+ srcPt = ConnEnd(Point(1149, 309), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef622
+ connRef = new ConnRef(router, 622);
+ srcPt = ConnEnd(Point(1199, 300), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef623
+ connRef = new ConnRef(router, 623);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(132, 280), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef624
+ connRef = new ConnRef(router, 624);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(132, 299), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef625
+ connRef = new ConnRef(router, 625);
+ srcPt = ConnEnd(Point(57.2456, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(82, 318), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef626
+ connRef = new ConnRef(router, 626);
+ srcPt = ConnEnd(Point(57.2456, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(132, 280), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef627
+ connRef = new ConnRef(router, 627);
+ srcPt = ConnEnd(Point(57.2456, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(132, 299), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef628
+ connRef = new ConnRef(router, 628);
+ srcPt = ConnEnd(Point(72, 423), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef629
+ connRef = new ConnRef(router, 629);
+ srcPt = ConnEnd(Point(92, 423), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef630
+ connRef = new ConnRef(router, 630);
+ srcPt = ConnEnd(Point(82, 504), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef631
+ connRef = new ConnRef(router, 631);
+ srcPt = ConnEnd(Point(132, 595), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef632
+ connRef = new ConnRef(router, 632);
+ srcPt = ConnEnd(Point(132, 576), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef633
+ connRef = new ConnRef(router, 633);
+ srcPt = ConnEnd(Point(82, 595), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef634
+ connRef = new ConnRef(router, 634);
+ srcPt = ConnEnd(Point(57.2456, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(213, 328), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef635
+ connRef = new ConnRef(router, 635);
+ srcPt = ConnEnd(Point(25.2456, 96.9179), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(132, 175), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef636
+ connRef = new ConnRef(router, 636);
+ srcPt = ConnEnd(Point(25.2456, 96.9179), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(82, 194), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef637
+ connRef = new ConnRef(router, 637);
+ srcPt = ConnEnd(Point(25.2456, 96.9179), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(82, 175), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef638
+ connRef = new ConnRef(router, 638);
+ srcPt = ConnEnd(Point(25.2456, 96.9179), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(82, 156), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef639
+ connRef = new ConnRef(router, 639);
+ srcPt = ConnEnd(Point(223, 413), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef640
+ connRef = new ConnRef(router, 640);
+ srcPt = ConnEnd(Point(223, 504), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef641
+ connRef = new ConnRef(router, 641);
+ srcPt = ConnEnd(Point(273, 576), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef642
+ connRef = new ConnRef(router, 642);
+ srcPt = ConnEnd(Point(273, 595), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef643
+ connRef = new ConnRef(router, 643);
+ srcPt = ConnEnd(Point(223, 595), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef644
+ connRef = new ConnRef(router, 644);
+ srcPt = ConnEnd(Point(215.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(355, 328), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef645
+ connRef = new ConnRef(router, 645);
+ srcPt = ConnEnd(Point(371.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(497, 328), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef646
+ connRef = new ConnRef(router, 646);
+ srcPt = ConnEnd(Point(415, 576), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef647
+ connRef = new ConnRef(router, 647);
+ srcPt = ConnEnd(Point(415, 595), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef648
+ connRef = new ConnRef(router, 648);
+ srcPt = ConnEnd(Point(365, 595), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef649
+ connRef = new ConnRef(router, 649);
+ srcPt = ConnEnd(Point(365, 504), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef650
+ connRef = new ConnRef(router, 650);
+ srcPt = ConnEnd(Point(365, 413), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef651
+ connRef = new ConnRef(router, 651);
+ srcPt = ConnEnd(Point(507, 413), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef652
+ connRef = new ConnRef(router, 652);
+ srcPt = ConnEnd(Point(507, 504), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef653
+ connRef = new ConnRef(router, 653);
+ srcPt = ConnEnd(Point(557, 576), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef654
+ connRef = new ConnRef(router, 654);
+ srcPt = ConnEnd(Point(557, 595), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef655
+ connRef = new ConnRef(router, 655);
+ srcPt = ConnEnd(Point(507, 595), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef656
+ connRef = new ConnRef(router, 656);
+ srcPt = ConnEnd(Point(527.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(639, 328), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef657
+ connRef = new ConnRef(router, 657);
+ srcPt = ConnEnd(Point(673.933, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(780, 328), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef658
+ connRef = new ConnRef(router, 658);
+ srcPt = ConnEnd(Point(699, 576), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef659
+ connRef = new ConnRef(router, 659);
+ srcPt = ConnEnd(Point(699, 595), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef660
+ connRef = new ConnRef(router, 660);
+ srcPt = ConnEnd(Point(649, 595), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef661
+ connRef = new ConnRef(router, 661);
+ srcPt = ConnEnd(Point(649, 504), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef662
+ connRef = new ConnRef(router, 662);
+ srcPt = ConnEnd(Point(649, 413), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef663
+ connRef = new ConnRef(router, 663);
+ srcPt = ConnEnd(Point(790, 413), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef664
+ connRef = new ConnRef(router, 664);
+ srcPt = ConnEnd(Point(790, 504), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef665
+ connRef = new ConnRef(router, 665);
+ srcPt = ConnEnd(Point(840, 576), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef666
+ connRef = new ConnRef(router, 666);
+ srcPt = ConnEnd(Point(840, 595), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef667
+ connRef = new ConnRef(router, 667);
+ srcPt = ConnEnd(Point(790, 595), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef668
+ connRef = new ConnRef(router, 668);
+ srcPt = ConnEnd(Point(823.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(922, 328), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef669
+ connRef = new ConnRef(router, 669);
+ srcPt = ConnEnd(Point(1149, 309), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef670
+ connRef = new ConnRef(router, 670);
+ srcPt = ConnEnd(Point(979.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(932, 667), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef671
+ connRef = new ConnRef(router, 671);
+ srcPt = ConnEnd(Point(979.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(932, 686), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef672
+ connRef = new ConnRef(router, 672);
+ srcPt = ConnEnd(Point(1199, 300), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef673
+ connRef = new ConnRef(router, 673);
+ srcPt = ConnEnd(Point(982, 576), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef674
+ connRef = new ConnRef(router, 674);
+ srcPt = ConnEnd(Point(982, 595), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef675
+ connRef = new ConnRef(router, 675);
+ srcPt = ConnEnd(Point(932, 595), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef676
+ connRef = new ConnRef(router, 676);
+ srcPt = ConnEnd(Point(932, 504), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef677
+ connRef = new ConnRef(router, 677);
+ srcPt = ConnEnd(Point(932, 413), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef678
+ connRef = new ConnRef(router, 678);
+ srcPt = ConnEnd(Point(82, 338), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef679
+ connRef = new ConnRef(router, 679);
+ srcPt = ConnEnd(Point(233, 328), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef680
+ connRef = new ConnRef(router, 680);
+ srcPt = ConnEnd(Point(375, 328), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef681
+ connRef = new ConnRef(router, 681);
+ srcPt = ConnEnd(Point(517, 328), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef682
+ connRef = new ConnRef(router, 682);
+ srcPt = ConnEnd(Point(659, 328), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef683
+ connRef = new ConnRef(router, 683);
+ srcPt = ConnEnd(Point(800, 328), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef684
+ connRef = new ConnRef(router, 684);
+ srcPt = ConnEnd(Point(942, 328), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef685
+ connRef = new ConnRef(router, 685);
+ srcPt = ConnEnd(Point(223, 433), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef686
+ connRef = new ConnRef(router, 686);
+ srcPt = ConnEnd(Point(365, 433), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef687
+ connRef = new ConnRef(router, 687);
+ srcPt = ConnEnd(Point(507, 433), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef688
+ connRef = new ConnRef(router, 688);
+ srcPt = ConnEnd(Point(790, 433), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef689
+ connRef = new ConnRef(router, 689);
+ srcPt = ConnEnd(Point(932, 433), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef690
+ connRef = new ConnRef(router, 690);
+ srcPt = ConnEnd(Point(649, 433), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef691
+ connRef = new ConnRef(router, 691);
+ srcPt = ConnEnd(Point(82, 524), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef692
+ connRef = new ConnRef(router, 692);
+ srcPt = ConnEnd(Point(223, 524), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef693
+ connRef = new ConnRef(router, 693);
+ srcPt = ConnEnd(Point(365, 524), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef694
+ connRef = new ConnRef(router, 694);
+ srcPt = ConnEnd(Point(507, 524), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef695
+ connRef = new ConnRef(router, 695);
+ srcPt = ConnEnd(Point(649, 524), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef696
+ connRef = new ConnRef(router, 696);
+ srcPt = ConnEnd(Point(790, 524), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef697
+ connRef = new ConnRef(router, 697);
+ srcPt = ConnEnd(Point(932, 524), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef698
+ connRef = new ConnRef(router, 698);
+ srcPt = ConnEnd(Point(82, 615), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef699
+ connRef = new ConnRef(router, 699);
+ srcPt = ConnEnd(Point(223, 615), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(215.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef700
+ connRef = new ConnRef(router, 700);
+ srcPt = ConnEnd(Point(365, 615), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef701
+ connRef = new ConnRef(router, 701);
+ srcPt = ConnEnd(Point(507, 615), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef702
+ connRef = new ConnRef(router, 702);
+ srcPt = ConnEnd(Point(649, 615), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(673.933, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef703
+ connRef = new ConnRef(router, 703);
+ srcPt = ConnEnd(Point(790, 615), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(823.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef704
+ connRef = new ConnRef(router, 704);
+ srcPt = ConnEnd(Point(932, 615), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef705
+ connRef = new ConnRef(router, 705);
+ srcPt = ConnEnd(Point(1169, 309), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1203.25, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef706
+ connRef = new ConnRef(router, 706);
+ srcPt = ConnEnd(Point(1159, 414), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1203.25, 447.955), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef707
+ connRef = new ConnRef(router, 707);
+ srcPt = ConnEnd(Point(1159, 505), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1203.25, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef708
+ connRef = new ConnRef(router, 708);
+ srcPt = ConnEnd(Point(1159, 595), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1203.25, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef709
+ connRef = new ConnRef(router, 709);
+ srcPt = ConnEnd(Point(932, 687), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 750.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef710
+ connRef = new ConnRef(router, 710);
+ srcPt = ConnEnd(Point(932, 706), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(979.246, 750.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef711
+ connRef = new ConnRef(router, 711);
+ srcPt = ConnEnd(Point(1159, 687), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1203.25, 750.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef712
+ connRef = new ConnRef(router, 712);
+ srcPt = ConnEnd(Point(1219, 300), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1203.25, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef713
+ connRef = new ConnRef(router, 713);
+ srcPt = ConnEnd(Point(1209, 605), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1203.25, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef714
+ connRef = new ConnRef(router, 714);
+ srcPt = ConnEnd(Point(132, 300), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef715
+ connRef = new ConnRef(router, 715);
+ srcPt = ConnEnd(Point(132, 319), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(57.2456, 332.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef716
+ connRef = new ConnRef(router, 716);
+ srcPt = ConnEnd(Point(1131.25, 622.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1005.25, 622.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef717
+ connRef = new ConnRef(router, 717);
+ srcPt = ConnEnd(Point(927.246, 622.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(849.246, 622.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef718
+ connRef = new ConnRef(router, 718);
+ srcPt = ConnEnd(Point(771.246, 622.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(693.246, 622.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef719
+ connRef = new ConnRef(router, 719);
+ srcPt = ConnEnd(Point(615.246, 622.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(537.246, 622.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef720
+ connRef = new ConnRef(router, 720);
+ srcPt = ConnEnd(Point(459.246, 622.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(381.246, 622.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef721
+ connRef = new ConnRef(router, 721);
+ srcPt = ConnEnd(Point(303.246, 622.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(225.246, 622.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef722
+ connRef = new ConnRef(router, 722);
+ srcPt = ConnEnd(Point(145.246, 654.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(67.2456, 654.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef723
+ connRef = new ConnRef(router, 723);
+ srcPt = ConnEnd(Point(879.246, 718.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(801.246, 718.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef724
+ connRef = new ConnRef(router, 724);
+ srcPt = ConnEnd(Point(1203.25, 718.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1161.25, 718.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef725
+ connRef = new ConnRef(router, 725);
+ srcPt = ConnEnd(Point(1263.25, 718.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1173.25, 718.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef726
+ connRef = new ConnRef(router, 726);
+ srcPt = ConnEnd(Point(594.941, 718.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(527.246, 718.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef727
+ connRef = new ConnRef(router, 727);
+ srcPt = ConnEnd(Point(451.455, 718.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(371.246, 718.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef728
+ connRef = new ConnRef(router, 728);
+ srcPt = ConnEnd(Point(1371.25, 622.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1371.25, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef729
+ connRef = new ConnRef(router, 729);
+ srcPt = ConnEnd(Point(1419.25, 575.942), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1293.25, 575.942), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef730
+ connRef = new ConnRef(router, 730);
+ srcPt = ConnEnd(Point(1131.25, 654.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1005.25, 654.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef731
+ connRef = new ConnRef(router, 731);
+ srcPt = ConnEnd(Point(927.246, 654.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(849.246, 654.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef732
+ connRef = new ConnRef(router, 732);
+ srcPt = ConnEnd(Point(771.246, 654.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(693.246, 654.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef733
+ connRef = new ConnRef(router, 733);
+ srcPt = ConnEnd(Point(615.246, 654.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(537.246, 654.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef734
+ connRef = new ConnRef(router, 734);
+ srcPt = ConnEnd(Point(459.246, 654.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(381.246, 654.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef735
+ connRef = new ConnRef(router, 735);
+ srcPt = ConnEnd(Point(303.246, 654.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(225.246, 654.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef736
+ connRef = new ConnRef(router, 736);
+ srcPt = ConnEnd(Point(145.246, 622.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(67.2456, 622.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef737
+ connRef = new ConnRef(router, 737);
+ srcPt = ConnEnd(Point(1419.25, 514.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1293.25, 514.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef738
+ connRef = new ConnRef(router, 738);
+ srcPt = ConnEnd(Point(1131.25, 536.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1005.25, 536.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef739
+ connRef = new ConnRef(router, 739);
+ srcPt = ConnEnd(Point(927.246, 536.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(849.246, 536.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef740
+ connRef = new ConnRef(router, 740);
+ srcPt = ConnEnd(Point(771.246, 536.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(693.246, 536.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef741
+ connRef = new ConnRef(router, 741);
+ srcPt = ConnEnd(Point(615.246, 536.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(537.246, 536.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef742
+ connRef = new ConnRef(router, 742);
+ srcPt = ConnEnd(Point(459.246, 536.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(381.246, 536.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef743
+ connRef = new ConnRef(router, 743);
+ srcPt = ConnEnd(Point(303.246, 536.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(225.246, 536.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef744
+ connRef = new ConnRef(router, 744);
+ srcPt = ConnEnd(Point(145.246, 536.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(67.2456, 536.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef745
+ connRef = new ConnRef(router, 745);
+ srcPt = ConnEnd(Point(1293.25, 234.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1293.25, 288.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef746
+ connRef = new ConnRef(router, 746);
+ srcPt = ConnEnd(Point(1083.25, 622.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1083.25, 676.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef747
+ connRef = new ConnRef(router, 747);
+ srcPt = ConnEnd(Point(1419.25, 418.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1293.25, 418.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef748
+ connRef = new ConnRef(router, 748);
+ srcPt = ConnEnd(Point(1419.25, 718.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1293.25, 718.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef749
+ connRef = new ConnRef(router, 749);
+ srcPt = ConnEnd(Point(1479.25, 718.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1449.25, 718.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef750
+ connRef = new ConnRef(router, 750);
+ srcPt = ConnEnd(Point(723.246, 718.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(645.246, 718.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef751
+ connRef = new ConnRef(router, 751);
+ srcPt = ConnEnd(Point(927.246, 718.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(849.246, 718.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef752
+ connRef = new ConnRef(router, 752);
+ srcPt = ConnEnd(Point(145.246, 32.9179), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(67.2456, 32.9179), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef753
+ connRef = new ConnRef(router, 753);
+ srcPt = ConnEnd(Point(145.246, 310.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(67.2456, 310.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef754
+ connRef = new ConnRef(router, 754);
+ srcPt = ConnEnd(Point(1005.25, 234.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1005.25, 288.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef755
+ connRef = new ConnRef(router, 755);
+ srcPt = ConnEnd(Point(849.246, 234.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(849.246, 288.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef756
+ connRef = new ConnRef(router, 756);
+ srcPt = ConnEnd(Point(693.246, 234.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(693.246, 288.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef757
+ connRef = new ConnRef(router, 757);
+ srcPt = ConnEnd(Point(537.246, 234.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(537.246, 288.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef758
+ connRef = new ConnRef(router, 758);
+ srcPt = ConnEnd(Point(381.246, 234.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(381.246, 288.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef759
+ connRef = new ConnRef(router, 759);
+ srcPt = ConnEnd(Point(303.246, 288.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(225.246, 288.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef760
+ connRef = new ConnRef(router, 760);
+ srcPt = ConnEnd(Point(1131.25, 718.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1005.25, 718.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef761
+ connRef = new ConnRef(router, 761);
+ srcPt = ConnEnd(Point(1035.25, 686.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(957.246, 686.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef762
+ connRef = new ConnRef(router, 762);
+ srcPt = ConnEnd(Point(1131.25, 590.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1005.25, 590.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef763
+ connRef = new ConnRef(router, 763);
+ srcPt = ConnEnd(Point(1035.25, 622.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(957.246, 622.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef764
+ connRef = new ConnRef(router, 764);
+ srcPt = ConnEnd(Point(1035.25, 590.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(957.246, 590.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef765
+ connRef = new ConnRef(router, 765);
+ srcPt = ConnEnd(Point(1035.25, 514.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(957.246, 514.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef766
+ connRef = new ConnRef(router, 766);
+ srcPt = ConnEnd(Point(1035.25, 482.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(957.246, 482.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef767
+ connRef = new ConnRef(router, 767);
+ srcPt = ConnEnd(Point(1131.25, 418.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1005.25, 418.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef768
+ connRef = new ConnRef(router, 768);
+ srcPt = ConnEnd(Point(1035.25, 418.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(957.246, 418.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef769
+ connRef = new ConnRef(router, 769);
+ srcPt = ConnEnd(Point(1035.25, 386.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(957.246, 386.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef770
+ connRef = new ConnRef(router, 770);
+ srcPt = ConnEnd(Point(1005.25, 202.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1005.25, 256.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef771
+ connRef = new ConnRef(router, 771);
+ srcPt = ConnEnd(Point(957.246, 192.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(957.246, 278.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef772
+ connRef = new ConnRef(router, 772);
+ srcPt = ConnEnd(Point(957.246, 128.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(957.246, 246.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef773
+ connRef = new ConnRef(router, 773);
+ srcPt = ConnEnd(Point(927.246, 590.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(849.246, 590.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef774
+ connRef = new ConnRef(router, 774);
+ srcPt = ConnEnd(Point(879.246, 622.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(801.246, 622.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef775
+ connRef = new ConnRef(router, 775);
+ srcPt = ConnEnd(Point(879.246, 590.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(801.246, 590.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef776
+ connRef = new ConnRef(router, 776);
+ srcPt = ConnEnd(Point(879.246, 514.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(801.246, 514.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef777
+ connRef = new ConnRef(router, 777);
+ srcPt = ConnEnd(Point(879.246, 482.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(801.246, 482.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef778
+ connRef = new ConnRef(router, 778);
+ srcPt = ConnEnd(Point(927.246, 418.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(849.246, 418.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef779
+ connRef = new ConnRef(router, 779);
+ srcPt = ConnEnd(Point(879.246, 418.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(801.246, 418.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef780
+ connRef = new ConnRef(router, 780);
+ srcPt = ConnEnd(Point(879.246, 386.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(801.246, 386.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef781
+ connRef = new ConnRef(router, 781);
+ srcPt = ConnEnd(Point(849.246, 202.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(849.246, 256.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef782
+ connRef = new ConnRef(router, 782);
+ srcPt = ConnEnd(Point(801.246, 192.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(801.246, 278.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef783
+ connRef = new ConnRef(router, 783);
+ srcPt = ConnEnd(Point(801.246, 128.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(801.246, 246.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef784
+ connRef = new ConnRef(router, 784);
+ srcPt = ConnEnd(Point(771.246, 590.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(693.246, 590.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef785
+ connRef = new ConnRef(router, 785);
+ srcPt = ConnEnd(Point(723.246, 622.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(645.246, 622.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef786
+ connRef = new ConnRef(router, 786);
+ srcPt = ConnEnd(Point(723.246, 590.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(645.246, 590.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef787
+ connRef = new ConnRef(router, 787);
+ srcPt = ConnEnd(Point(723.246, 514.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(645.246, 514.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef788
+ connRef = new ConnRef(router, 788);
+ srcPt = ConnEnd(Point(723.246, 482.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(645.246, 482.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef789
+ connRef = new ConnRef(router, 789);
+ srcPt = ConnEnd(Point(771.246, 418.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(693.246, 418.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef790
+ connRef = new ConnRef(router, 790);
+ srcPt = ConnEnd(Point(723.246, 418.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(645.246, 418.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef791
+ connRef = new ConnRef(router, 791);
+ srcPt = ConnEnd(Point(723.246, 386.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(645.246, 386.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef792
+ connRef = new ConnRef(router, 792);
+ srcPt = ConnEnd(Point(693.246, 202.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(693.246, 256.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef793
+ connRef = new ConnRef(router, 793);
+ srcPt = ConnEnd(Point(645.246, 192.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(645.246, 278.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef794
+ connRef = new ConnRef(router, 794);
+ srcPt = ConnEnd(Point(645.246, 128.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(645.246, 246.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef795
+ connRef = new ConnRef(router, 795);
+ srcPt = ConnEnd(Point(615.246, 590.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(537.246, 590.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef796
+ connRef = new ConnRef(router, 796);
+ srcPt = ConnEnd(Point(567.246, 622.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.246, 622.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef797
+ connRef = new ConnRef(router, 797);
+ srcPt = ConnEnd(Point(567.246, 590.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.246, 590.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef798
+ connRef = new ConnRef(router, 798);
+ srcPt = ConnEnd(Point(615.246, 486.951), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(537.246, 486.951), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef799
+ connRef = new ConnRef(router, 799);
+ srcPt = ConnEnd(Point(567.246, 514.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.246, 514.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef800
+ connRef = new ConnRef(router, 800);
+ srcPt = ConnEnd(Point(567.246, 482.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.246, 482.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef801
+ connRef = new ConnRef(router, 801);
+ srcPt = ConnEnd(Point(615.246, 418.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(537.246, 418.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef802
+ connRef = new ConnRef(router, 802);
+ srcPt = ConnEnd(Point(567.246, 418.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.246, 418.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef803
+ connRef = new ConnRef(router, 803);
+ srcPt = ConnEnd(Point(567.246, 386.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.246, 386.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef804
+ connRef = new ConnRef(router, 804);
+ srcPt = ConnEnd(Point(537.246, 202.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(537.246, 256.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef805
+ connRef = new ConnRef(router, 805);
+ srcPt = ConnEnd(Point(489.246, 192.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.246, 278.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef806
+ connRef = new ConnRef(router, 806);
+ srcPt = ConnEnd(Point(489.246, 128.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.246, 246.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef807
+ connRef = new ConnRef(router, 807);
+ srcPt = ConnEnd(Point(459.246, 590.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(381.246, 590.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef808
+ connRef = new ConnRef(router, 808);
+ srcPt = ConnEnd(Point(411.246, 622.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(333.246, 622.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef809
+ connRef = new ConnRef(router, 809);
+ srcPt = ConnEnd(Point(411.246, 590.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(333.246, 590.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef810
+ connRef = new ConnRef(router, 810);
+ srcPt = ConnEnd(Point(411.246, 514.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(333.246, 514.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef811
+ connRef = new ConnRef(router, 811);
+ srcPt = ConnEnd(Point(411.246, 482.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(333.246, 482.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef812
+ connRef = new ConnRef(router, 812);
+ srcPt = ConnEnd(Point(459.246, 418.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(381.246, 418.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef813
+ connRef = new ConnRef(router, 813);
+ srcPt = ConnEnd(Point(411.246, 418.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(333.246, 418.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef814
+ connRef = new ConnRef(router, 814);
+ srcPt = ConnEnd(Point(411.246, 386.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(333.246, 386.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef815
+ connRef = new ConnRef(router, 815);
+ srcPt = ConnEnd(Point(381.246, 202.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(381.246, 256.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef816
+ connRef = new ConnRef(router, 816);
+ srcPt = ConnEnd(Point(333.246, 192.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(333.246, 278.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef817
+ connRef = new ConnRef(router, 817);
+ srcPt = ConnEnd(Point(333.246, 128.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(333.246, 246.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef818
+ connRef = new ConnRef(router, 818);
+ srcPt = ConnEnd(Point(303.246, 590.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(225.246, 590.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef819
+ connRef = new ConnRef(router, 819);
+ srcPt = ConnEnd(Point(255.246, 622.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(193.246, 622.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef820
+ connRef = new ConnRef(router, 820);
+ srcPt = ConnEnd(Point(255.246, 590.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(193.246, 590.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef821
+ connRef = new ConnRef(router, 821);
+ srcPt = ConnEnd(Point(255.246, 514.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(193.246, 514.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef822
+ connRef = new ConnRef(router, 822);
+ srcPt = ConnEnd(Point(255.246, 482.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(193.246, 482.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef823
+ connRef = new ConnRef(router, 823);
+ srcPt = ConnEnd(Point(303.246, 418.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(225.246, 418.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef824
+ connRef = new ConnRef(router, 824);
+ srcPt = ConnEnd(Point(255.246, 418.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(193.246, 418.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef825
+ connRef = new ConnRef(router, 825);
+ srcPt = ConnEnd(Point(255.246, 386.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(193.246, 386.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef826
+ connRef = new ConnRef(router, 826);
+ srcPt = ConnEnd(Point(303.246, 256.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(225.246, 256.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef827
+ connRef = new ConnRef(router, 827);
+ srcPt = ConnEnd(Point(193.246, 128.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(193.246, 246.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef828
+ connRef = new ConnRef(router, 828);
+ srcPt = ConnEnd(Point(193.246, 192.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(193.246, 278.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef829
+ connRef = new ConnRef(router, 829);
+ srcPt = ConnEnd(Point(145.246, 590.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(67.2456, 590.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef830
+ connRef = new ConnRef(router, 830);
+ srcPt = ConnEnd(Point(97.2456, 622.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17.2456, 622.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef831
+ connRef = new ConnRef(router, 831);
+ srcPt = ConnEnd(Point(97.2456, 590.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17.2456, 590.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef832
+ connRef = new ConnRef(router, 832);
+ srcPt = ConnEnd(Point(97.2456, 514.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17.2456, 514.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef833
+ connRef = new ConnRef(router, 833);
+ srcPt = ConnEnd(Point(97.2456, 482.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17.2456, 482.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef834
+ connRef = new ConnRef(router, 834);
+ srcPt = ConnEnd(Point(145.246, 418.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(67.2456, 418.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef835
+ connRef = new ConnRef(router, 835);
+ srcPt = ConnEnd(Point(97.2456, 418.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17.2456, 418.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef836
+ connRef = new ConnRef(router, 836);
+ srcPt = ConnEnd(Point(97.2456, 386.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17.2456, 386.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef837
+ connRef = new ConnRef(router, 837);
+ srcPt = ConnEnd(Point(17.2456, 192.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17.2456, 278.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef838
+ connRef = new ConnRef(router, 838);
+ srcPt = ConnEnd(Point(17.2456, 128.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17.2456, 246.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef839
+ connRef = new ConnRef(router, 839);
+ srcPt = ConnEnd(Point(285.246, 170.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(244.976, 170.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef840
+ connRef = new ConnRef(router, 840);
+ srcPt = ConnEnd(Point(237.246, 86.9179), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(145.246, 86.9179), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef841
+ connRef = new ConnRef(router, 841);
+ srcPt = ConnEnd(Point(237.246, 54.9179), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(145.246, 54.9179), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef842
+ connRef = new ConnRef(router, 842);
+ srcPt = ConnEnd(Point(97.2456, 170.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17.2456, 170.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef843
+ connRef = new ConnRef(router, 843);
+ srcPt = ConnEnd(Point(97.2456, 32.9179), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17.2456, 32.9179), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef844
+ connRef = new ConnRef(router, 844);
+ srcPt = ConnEnd(Point(97.2456, 0.917947), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17.2456, 0.917947), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef845
+ connRef = new ConnRef(router, 845);
+ srcPt = ConnEnd(Point(380.962, -29.0821), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(319.219, -29.0821), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef846
+ connRef = new ConnRef(router, 846);
+ srcPt = ConnEnd(Point(279.219, -29.0821), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(197.246, -29.0821), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef847
+ connRef = new ConnRef(router, 847);
+ srcPt = ConnEnd(Point(97.2456, 310.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17.2456, 310.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef848
+ connRef = new ConnRef(router, 848);
+ srcPt = ConnEnd(Point(193.246, 224.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(193.246, 310.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef849
+ connRef = new ConnRef(router, 849);
+ srcPt = ConnEnd(Point(333.246, 224.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(333.246, 310.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef850
+ connRef = new ConnRef(router, 850);
+ srcPt = ConnEnd(Point(489.246, 224.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.246, 310.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef851
+ connRef = new ConnRef(router, 851);
+ srcPt = ConnEnd(Point(645.246, 224.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(645.246, 310.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef852
+ connRef = new ConnRef(router, 852);
+ srcPt = ConnEnd(Point(801.246, 224.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(801.246, 310.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef853
+ connRef = new ConnRef(router, 853);
+ srcPt = ConnEnd(Point(957.246, 224.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(957.246, 310.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef854
+ connRef = new ConnRef(router, 854);
+ srcPt = ConnEnd(Point(17.2456, 364.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17.2456, 450.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef855
+ connRef = new ConnRef(router, 855);
+ srcPt = ConnEnd(Point(255.246, 450.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(193.246, 450.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef856
+ connRef = new ConnRef(router, 856);
+ srcPt = ConnEnd(Point(411.246, 450.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(333.246, 450.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef857
+ connRef = new ConnRef(router, 857);
+ srcPt = ConnEnd(Point(567.246, 450.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.246, 450.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef858
+ connRef = new ConnRef(router, 858);
+ srcPt = ConnEnd(Point(879.246, 450.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(801.246, 450.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef859
+ connRef = new ConnRef(router, 859);
+ srcPt = ConnEnd(Point(1035.25, 450.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(957.246, 450.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef860
+ connRef = new ConnRef(router, 860);
+ srcPt = ConnEnd(Point(723.246, 450.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(645.246, 450.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef861
+ connRef = new ConnRef(router, 861);
+ srcPt = ConnEnd(Point(97.2456, 558.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17.2456, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef862
+ connRef = new ConnRef(router, 862);
+ srcPt = ConnEnd(Point(255.246, 558.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(193.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef863
+ connRef = new ConnRef(router, 863);
+ srcPt = ConnEnd(Point(411.246, 558.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(333.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef864
+ connRef = new ConnRef(router, 864);
+ srcPt = ConnEnd(Point(567.246, 558.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef865
+ connRef = new ConnRef(router, 865);
+ srcPt = ConnEnd(Point(723.246, 558.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(645.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef866
+ connRef = new ConnRef(router, 866);
+ srcPt = ConnEnd(Point(879.246, 558.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(801.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef867
+ connRef = new ConnRef(router, 867);
+ srcPt = ConnEnd(Point(1035.25, 558.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(957.246, 558.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef868
+ connRef = new ConnRef(router, 868);
+ srcPt = ConnEnd(Point(97.2456, 654.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17.2456, 654.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef869
+ connRef = new ConnRef(router, 869);
+ srcPt = ConnEnd(Point(255.246, 654.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(193.246, 654.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef870
+ connRef = new ConnRef(router, 870);
+ srcPt = ConnEnd(Point(411.246, 654.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(333.246, 654.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef871
+ connRef = new ConnRef(router, 871);
+ srcPt = ConnEnd(Point(567.246, 654.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(489.246, 654.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef872
+ connRef = new ConnRef(router, 872);
+ srcPt = ConnEnd(Point(723.246, 654.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(645.246, 654.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef873
+ connRef = new ConnRef(router, 873);
+ srcPt = ConnEnd(Point(879.246, 654.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(801.246, 654.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef874
+ connRef = new ConnRef(router, 874);
+ srcPt = ConnEnd(Point(1035.25, 654.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(957.246, 654.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef875
+ connRef = new ConnRef(router, 875);
+ srcPt = ConnEnd(Point(1233.25, 192.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1233.25, 278.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef876
+ connRef = new ConnRef(router, 876);
+ srcPt = ConnEnd(Point(1323.25, 418.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1233.25, 418.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef877
+ connRef = new ConnRef(router, 877);
+ srcPt = ConnEnd(Point(1323.25, 514.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1233.25, 514.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef878
+ connRef = new ConnRef(router, 878);
+ srcPt = ConnEnd(Point(1323.25, 622.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1233.25, 622.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef879
+ connRef = new ConnRef(router, 879);
+ srcPt = ConnEnd(Point(1035.25, 718.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(957.246, 718.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef880
+ connRef = new ConnRef(router, 880);
+ srcPt = ConnEnd(Point(1035.25, 750.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(957.246, 750.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef881
+ connRef = new ConnRef(router, 881);
+ srcPt = ConnEnd(Point(1323.25, 718.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1233.25, 718.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef882
+ connRef = new ConnRef(router, 882);
+ srcPt = ConnEnd(Point(1293.25, 202.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1293.25, 256.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef883
+ connRef = new ConnRef(router, 883);
+ srcPt = ConnEnd(Point(1419.25, 644.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1293.25, 644.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef884
+ connRef = new ConnRef(router, 884);
+ srcPt = ConnEnd(Point(145.246, 246.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(67.2456, 246.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef885
+ connRef = new ConnRef(router, 885);
+ srcPt = ConnEnd(Point(145.246, 278.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(67.2456, 278.918), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef886
+ connRef = new ConnRef(router, 886);
+ srcPt = ConnEnd(Point(823.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(790, 667), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef887
+ connRef = new ConnRef(router, 887);
+ srcPt = ConnEnd(Point(527.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(533, 667), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef888
+ connRef = new ConnRef(router, 888);
+ srcPt = ConnEnd(Point(371.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(390, 667), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef889
+ connRef = new ConnRef(router, 889);
+ srcPt = ConnEnd(Point(979.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1030, 634), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef890
+ connRef = new ConnRef(router, 890);
+ srcPt = ConnEnd(Point(673.933, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(649, 667), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef891
+ connRef = new ConnRef(router, 891);
+ srcPt = ConnEnd(Point(823.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(840, 667), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef892
+ connRef = new ConnRef(router, 892);
+ srcPt = ConnEnd(Point(57.2456, 125.987), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(132, 175), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef893
+ connRef = new ConnRef(router, 893);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(132, 318), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef894
+ connRef = new ConnRef(router, 894);
+ srcPt = ConnEnd(Point(57.2456, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(132, 318), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef895
+ connRef = new ConnRef(router, 895);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(972, 319), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef896
+ connRef = new ConnRef(router, 896);
+ srcPt = ConnEnd(Point(823.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(972, 319), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef897
+ connRef = new ConnRef(router, 897);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(830, 319), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef898
+ connRef = new ConnRef(router, 898);
+ srcPt = ConnEnd(Point(673.933, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(830, 319), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef899
+ connRef = new ConnRef(router, 899);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(689, 319), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef900
+ connRef = new ConnRef(router, 900);
+ srcPt = ConnEnd(Point(527.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(689, 319), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef901
+ connRef = new ConnRef(router, 901);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(547, 319), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef902
+ connRef = new ConnRef(router, 902);
+ srcPt = ConnEnd(Point(371.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(547, 319), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef903
+ connRef = new ConnRef(router, 903);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(405, 319), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef904
+ connRef = new ConnRef(router, 904);
+ srcPt = ConnEnd(Point(215.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(405, 319), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef905
+ connRef = new ConnRef(router, 905);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(273, 329), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef906
+ connRef = new ConnRef(router, 906);
+ srcPt = ConnEnd(Point(57.2456, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(273, 329), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef907
+ connRef = new ConnRef(router, 907);
+ srcPt = ConnEnd(Point(979.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(982, 667), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef908
+ connRef = new ConnRef(router, 908);
+ srcPt = ConnEnd(Point(979.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(932, 648), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef909
+ connRef = new ConnRef(router, 909);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(972, 300), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef910
+ connRef = new ConnRef(router, 910);
+ srcPt = ConnEnd(Point(823.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(972, 300), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef911
+ connRef = new ConnRef(router, 911);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(922, 309), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef912
+ connRef = new ConnRef(router, 912);
+ srcPt = ConnEnd(Point(823.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(922, 309), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef913
+ connRef = new ConnRef(router, 913);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(922, 290), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef914
+ connRef = new ConnRef(router, 914);
+ srcPt = ConnEnd(Point(823.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(922, 290), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef915
+ connRef = new ConnRef(router, 915);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(830, 300), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef916
+ connRef = new ConnRef(router, 916);
+ srcPt = ConnEnd(Point(673.933, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(830, 300), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef917
+ connRef = new ConnRef(router, 917);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(780, 309), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef918
+ connRef = new ConnRef(router, 918);
+ srcPt = ConnEnd(Point(673.933, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(780, 309), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef919
+ connRef = new ConnRef(router, 919);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(780, 290), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef920
+ connRef = new ConnRef(router, 920);
+ srcPt = ConnEnd(Point(673.933, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(780, 290), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef921
+ connRef = new ConnRef(router, 921);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(689, 300), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef922
+ connRef = new ConnRef(router, 922);
+ srcPt = ConnEnd(Point(527.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(689, 300), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef923
+ connRef = new ConnRef(router, 923);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(639, 309), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef924
+ connRef = new ConnRef(router, 924);
+ srcPt = ConnEnd(Point(527.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(639, 309), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef925
+ connRef = new ConnRef(router, 925);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(639, 290), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef926
+ connRef = new ConnRef(router, 926);
+ srcPt = ConnEnd(Point(527.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(639, 290), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef927
+ connRef = new ConnRef(router, 927);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(547, 300), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef928
+ connRef = new ConnRef(router, 928);
+ srcPt = ConnEnd(Point(371.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(547, 300), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef929
+ connRef = new ConnRef(router, 929);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(497, 309), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef930
+ connRef = new ConnRef(router, 930);
+ srcPt = ConnEnd(Point(371.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(497, 309), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef931
+ connRef = new ConnRef(router, 931);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(497, 290), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef932
+ connRef = new ConnRef(router, 932);
+ srcPt = ConnEnd(Point(371.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(497, 290), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef933
+ connRef = new ConnRef(router, 933);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(405, 300), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef934
+ connRef = new ConnRef(router, 934);
+ srcPt = ConnEnd(Point(215.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(405, 300), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef935
+ connRef = new ConnRef(router, 935);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(355, 309), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef936
+ connRef = new ConnRef(router, 936);
+ srcPt = ConnEnd(Point(215.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(355, 309), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef937
+ connRef = new ConnRef(router, 937);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(355, 290), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef938
+ connRef = new ConnRef(router, 938);
+ srcPt = ConnEnd(Point(215.246, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(355, 290), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef939
+ connRef = new ConnRef(router, 939);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(273, 310), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef940
+ connRef = new ConnRef(router, 940);
+ srcPt = ConnEnd(Point(57.2456, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(273, 310), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef941
+ connRef = new ConnRef(router, 941);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(213, 290), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef942
+ connRef = new ConnRef(router, 942);
+ srcPt = ConnEnd(Point(57.2456, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(213, 290), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef943
+ connRef = new ConnRef(router, 943);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(213, 309), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef944
+ connRef = new ConnRef(router, 944);
+ srcPt = ConnEnd(Point(57.2456, 676.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(213, 309), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef945
+ connRef = new ConnRef(router, 945);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(92, 309), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef946
+ connRef = new ConnRef(router, 946);
+ srcPt = ConnEnd(Point(57.2456, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(92, 309), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef947
+ connRef = new ConnRef(router, 947);
+ srcPt = ConnEnd(Point(197.246, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(92, 290), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef948
+ connRef = new ConnRef(router, 948);
+ srcPt = ConnEnd(Point(57.2456, 160.918), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(92, 290), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef949
+ connRef = new ConnRef(router, 949);
+ srcPt = ConnEnd(Point(57.2456, 125.987), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(82, 194), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef950
+ connRef = new ConnRef(router, 950);
+ srcPt = ConnEnd(Point(57.2456, 125.987), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(82, 175), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef951
+ connRef = new ConnRef(router, 951);
+ srcPt = ConnEnd(Point(57.2456, 125.987), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(82, 156), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef952
+ connRef = new ConnRef(router, 952);
+ srcPt = ConnEnd(Point(319.219, -7.08205), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(319, 155), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef953
+ connRef = new ConnRef(router, 953);
+ srcPt = ConnEnd(Point(197.246, 96.9179), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(317.466, 34.9179), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef954
+ connRef = new ConnRef(router, 954);
+ srcPt = ConnEnd(Point(57.2456, 125.987), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(-7.75443, -71.0821), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef955
+ connRef = new ConnRef(router, 955);
+ srcPt = ConnEnd(Point(197.246, 96.9179), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(317.466, 86.9179), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/performance01");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/reallyslowrouting.cpp b/src/3rdparty/adaptagrams/libavoid/tests/reallyslowrouting.cpp
new file mode 100644
index 0000000..26785d7
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/reallyslowrouting.cpp
@@ -0,0 +1,7099 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 0);
+ router->setOrthogonalNudgeDistance(4);
+
+ Polygon poly91(4);
+ poly91.ps[0] = Point(703.246, 408.918);
+ poly91.ps[1] = Point(703.246, 428.918);
+ poly91.ps[2] = Point(683.246, 428.918);
+ poly91.ps[3] = Point(683.246, 408.918);
+ ShapeRef *shapeRef91 = new ShapeRef(router, poly91, 91);
+ router->addShape(shapeRef91);
+
+ Polygon poly84(4);
+ poly84.ps[0] = Point(811.246, 268.918);
+ poly84.ps[1] = Point(811.246, 288.918);
+ poly84.ps[2] = Point(791.246, 288.918);
+ poly84.ps[3] = Point(791.246, 268.918);
+ ShapeRef *shapeRef84 = new ShapeRef(router, poly84, 84);
+ router->addShape(shapeRef84);
+
+ Polygon poly75(4);
+ poly75.ps[0] = Point(859.246, 580.918);
+ poly75.ps[1] = Point(859.246, 600.918);
+ poly75.ps[2] = Point(839.246, 600.918);
+ poly75.ps[3] = Point(839.246, 580.918);
+ ShapeRef *shapeRef75 = new ShapeRef(router, poly75, 75);
+ router->addShape(shapeRef75);
+
+ Polygon poly120(4);
+ poly120.ps[0] = Point(235.246, 580.918);
+ poly120.ps[1] = Point(235.246, 600.918);
+ poly120.ps[2] = Point(215.246, 600.918);
+ poly120.ps[3] = Point(215.246, 580.918);
+ ShapeRef *shapeRef120 = new ShapeRef(router, poly120, 120);
+ router->addShape(shapeRef120);
+
+ Polygon poly157(4);
+ poly157.ps[0] = Point(77.2456, 427.955);
+ poly157.ps[1] = Point(77.2456, 467.955);
+ poly157.ps[2] = Point(37.2456, 467.955);
+ poly157.ps[3] = Point(37.2456, 427.955);
+ ShapeRef *shapeRef157 = new ShapeRef(router, poly157, 157);
+ router->addShape(shapeRef157);
+
+ Polygon poly138(4);
+ poly138.ps[0] = Point(27.2456, 376.918);
+ poly138.ps[1] = Point(27.2456, 396.918);
+ poly138.ps[2] = Point(7.24557, 396.918);
+ poly138.ps[3] = Point(7.24557, 376.918);
+ ShapeRef *shapeRef138 = new ShapeRef(router, poly138, 138);
+ router->addShape(shapeRef138);
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(235.246, 612.918);
+ poly6.ps[1] = Point(235.246, 632.918);
+ poly6.ps[2] = Point(215.246, 632.918);
+ poly6.ps[3] = Point(215.246, 612.918);
+ ShapeRef *shapeRef6 = new ShapeRef(router, poly6, 6);
+ router->addShape(shapeRef6);
+
+ Polygon poly117(4);
+ poly117.ps[0] = Point(391.246, 246.918);
+ poly117.ps[1] = Point(391.246, 266.918);
+ poly117.ps[2] = Point(371.246, 266.918);
+ poly117.ps[3] = Point(371.246, 246.918);
+ ShapeRef *shapeRef117 = new ShapeRef(router, poly117, 117);
+ router->addShape(shapeRef117);
+
+ Polygon poly177(4);
+ poly177.ps[0] = Point(843.246, 312.918);
+ poly177.ps[1] = Point(843.246, 352.918);
+ poly177.ps[2] = Point(803.246, 352.918);
+ poly177.ps[3] = Point(803.246, 312.918);
+ ShapeRef *shapeRef177 = new ShapeRef(router, poly177, 177);
+ router->addShape(shapeRef177);
+
+ Polygon poly178(4);
+ poly178.ps[0] = Point(843.246, 427.955);
+ poly178.ps[1] = Point(843.246, 467.955);
+ poly178.ps[2] = Point(803.246, 467.955);
+ poly178.ps[3] = Point(803.246, 427.955);
+ ShapeRef *shapeRef178 = new ShapeRef(router, poly178, 178);
+ router->addShape(shapeRef178);
+
+ Polygon poly31(4);
+ poly31.ps[0] = Point(547.246, 644.918);
+ poly31.ps[1] = Point(547.246, 664.918);
+ poly31.ps[2] = Point(527.246, 664.918);
+ poly31.ps[3] = Point(527.246, 644.918);
+ ShapeRef *shapeRef31 = new ShapeRef(router, poly31, 31);
+ router->addShape(shapeRef31);
+
+ Polygon poly124(4);
+ poly124.ps[0] = Point(203.246, 472.918);
+ poly124.ps[1] = Point(203.246, 492.918);
+ poly124.ps[2] = Point(183.246, 492.918);
+ poly124.ps[3] = Point(183.246, 472.918);
+ ShapeRef *shapeRef124 = new ShapeRef(router, poly124, 124);
+ router->addShape(shapeRef124);
+
+ Polygon poly38(4);
+ poly38.ps[0] = Point(703.246, 526.918);
+ poly38.ps[1] = Point(703.246, 546.918);
+ poly38.ps[2] = Point(683.246, 546.918);
+ poly38.ps[3] = Point(683.246, 526.918);
+ ShapeRef *shapeRef38 = new ShapeRef(router, poly38, 38);
+ router->addShape(shapeRef38);
+
+ Polygon poly73(4);
+ poly73.ps[0] = Point(967.246, 268.918);
+ poly73.ps[1] = Point(967.246, 288.918);
+ poly73.ps[2] = Point(947.246, 288.918);
+ poly73.ps[3] = Point(947.246, 268.918);
+ ShapeRef *shapeRef73 = new ShapeRef(router, poly73, 73);
+ router->addShape(shapeRef73);
+
+ Polygon poly165(4);
+ poly165.ps[0] = Point(391.246, 656.918);
+ poly165.ps[1] = Point(391.246, 696.918);
+ poly165.ps[2] = Point(351.246, 696.918);
+ poly165.ps[3] = Point(351.246, 656.918);
+ ShapeRef *shapeRef165 = new ShapeRef(router, poly165, 165);
+ router->addShape(shapeRef165);
+
+ Polygon poly166(4);
+ poly166.ps[0] = Point(391.246, 538.918);
+ poly166.ps[1] = Point(391.246, 578.918);
+ poly166.ps[2] = Point(351.246, 578.918);
+ poly166.ps[3] = Point(351.246, 538.918);
+ ShapeRef *shapeRef166 = new ShapeRef(router, poly166, 166);
+ router->addShape(shapeRef166);
+
+ Polygon poly153(4);
+ poly153.ps[0] = Point(217.246, 76.9179);
+ poly153.ps[1] = Point(217.246, 116.918);
+ poly153.ps[2] = Point(177.246, 116.918);
+ poly153.ps[3] = Point(177.246, 76.9179);
+ ShapeRef *shapeRef153 = new ShapeRef(router, poly153, 153);
+ router->addShape(shapeRef153);
+
+ Polygon poly17(4);
+ poly17.ps[0] = Point(843.246, 730.918);
+ poly17.ps[1] = Point(843.246, 770.918);
+ poly17.ps[2] = Point(803.246, 770.918);
+ poly17.ps[3] = Point(803.246, 730.918);
+ ShapeRef *shapeRef17 = new ShapeRef(router, poly17, 17);
+ router->addShape(shapeRef17);
+
+ Polygon poly48(4);
+ poly48.ps[0] = Point(655.246, 708.918);
+ poly48.ps[1] = Point(655.246, 728.918);
+ poly48.ps[2] = Point(635.246, 728.918);
+ poly48.ps[3] = Point(635.246, 708.918);
+ ShapeRef *shapeRef48 = new ShapeRef(router, poly48, 48);
+ router->addShape(shapeRef48);
+
+ Polygon poly290(4);
+ poly290.ps[0] = Point(877.246, 182.918);
+ poly290.ps[1] = Point(877.246, 222.918);
+ poly290.ps[2] = Point(821.246, 222.918);
+ poly290.ps[3] = Point(821.246, 182.918);
+ ShapeRef *shapeRef290 = new ShapeRef(router, poly290, 290);
+ router->addShape(shapeRef290);
+
+ Polygon poly291(4);
+ poly291.ps[0] = Point(829.246, 172.918);
+ poly291.ps[1] = Point(829.246, 212.918);
+ poly291.ps[2] = Point(773.246, 212.918);
+ poly291.ps[3] = Point(773.246, 172.918);
+ ShapeRef *shapeRef291 = new ShapeRef(router, poly291, 291);
+ router->addShape(shapeRef291);
+
+ Polygon poly292(4);
+ poly292.ps[0] = Point(829.246, 108.918);
+ poly292.ps[1] = Point(829.246, 148.918);
+ poly292.ps[2] = Point(773.246, 148.918);
+ poly292.ps[3] = Point(773.246, 108.918);
+ ShapeRef *shapeRef292 = new ShapeRef(router, poly292, 292);
+ router->addShape(shapeRef292);
+
+ Polygon poly293(4);
+ poly293.ps[0] = Point(799.246, 570.918);
+ poly293.ps[1] = Point(799.246, 610.918);
+ poly293.ps[2] = Point(743.246, 610.918);
+ poly293.ps[3] = Point(743.246, 570.918);
+ ShapeRef *shapeRef293 = new ShapeRef(router, poly293, 293);
+ router->addShape(shapeRef293);
+
+ Polygon poly294(4);
+ poly294.ps[0] = Point(751.246, 602.918);
+ poly294.ps[1] = Point(751.246, 642.918);
+ poly294.ps[2] = Point(695.246, 642.918);
+ poly294.ps[3] = Point(695.246, 602.918);
+ ShapeRef *shapeRef294 = new ShapeRef(router, poly294, 294);
+ router->addShape(shapeRef294);
+
+ Polygon poly295(4);
+ poly295.ps[0] = Point(751.246, 570.918);
+ poly295.ps[1] = Point(751.246, 610.918);
+ poly295.ps[2] = Point(695.246, 610.918);
+ poly295.ps[3] = Point(695.246, 570.918);
+ ShapeRef *shapeRef295 = new ShapeRef(router, poly295, 295);
+ router->addShape(shapeRef295);
+
+ Polygon poly296(4);
+ poly296.ps[0] = Point(751.246, 494.918);
+ poly296.ps[1] = Point(751.246, 534.918);
+ poly296.ps[2] = Point(695.246, 534.918);
+ poly296.ps[3] = Point(695.246, 494.918);
+ ShapeRef *shapeRef296 = new ShapeRef(router, poly296, 296);
+ router->addShape(shapeRef296);
+
+ Polygon poly297(4);
+ poly297.ps[0] = Point(751.246, 462.918);
+ poly297.ps[1] = Point(751.246, 502.918);
+ poly297.ps[2] = Point(695.246, 502.918);
+ poly297.ps[3] = Point(695.246, 462.918);
+ ShapeRef *shapeRef297 = new ShapeRef(router, poly297, 297);
+ router->addShape(shapeRef297);
+
+ Polygon poly298(4);
+ poly298.ps[0] = Point(799.246, 398.918);
+ poly298.ps[1] = Point(799.246, 438.918);
+ poly298.ps[2] = Point(743.246, 438.918);
+ poly298.ps[3] = Point(743.246, 398.918);
+ ShapeRef *shapeRef298 = new ShapeRef(router, poly298, 298);
+ router->addShape(shapeRef298);
+
+ Polygon poly99(4);
+ poly99.ps[0] = Point(499.246, 580.918);
+ poly99.ps[1] = Point(499.246, 600.918);
+ poly99.ps[2] = Point(479.246, 600.918);
+ poly99.ps[3] = Point(479.246, 580.918);
+ ShapeRef *shapeRef99 = new ShapeRef(router, poly99, 99);
+ router->addShape(shapeRef99);
+
+ Polygon poly85(4);
+ poly85.ps[0] = Point(811.246, 236.918);
+ poly85.ps[1] = Point(811.246, 256.918);
+ poly85.ps[2] = Point(791.246, 256.918);
+ poly85.ps[3] = Point(791.246, 236.918);
+ ShapeRef *shapeRef85 = new ShapeRef(router, poly85, 85);
+ router->addShape(shapeRef85);
+
+ Polygon poly24(4);
+ poly24.ps[0] = Point(537.246, 708.918);
+ poly24.ps[1] = Point(537.246, 728.918);
+ poly24.ps[2] = Point(517.246, 728.918);
+ poly24.ps[3] = Point(517.246, 708.918);
+ ShapeRef *shapeRef24 = new ShapeRef(router, poly24, 24);
+ router->addShape(shapeRef24);
+
+ Polygon poly72(4);
+ poly72.ps[0] = Point(1015.25, 246.918);
+ poly72.ps[1] = Point(1015.25, 266.918);
+ poly72.ps[2] = Point(995.246, 266.918);
+ poly72.ps[3] = Point(995.246, 246.918);
+ ShapeRef *shapeRef72 = new ShapeRef(router, poly72, 72);
+ router->addShape(shapeRef72);
+
+ Polygon poly20(4);
+ poly20.ps[0] = Point(391.246, 730.918);
+ poly20.ps[1] = Point(391.246, 770.918);
+ poly20.ps[2] = Point(351.246, 770.918);
+ poly20.ps[3] = Point(351.246, 730.918);
+ ShapeRef *shapeRef20 = new ShapeRef(router, poly20, 20);
+ router->addShape(shapeRef20);
+
+ Polygon poly254(4);
+ poly254.ps[0] = Point(1321.25, 214.918);
+ poly254.ps[1] = Point(1321.25, 254.918);
+ poly254.ps[2] = Point(1265.25, 254.918);
+ poly254.ps[3] = Point(1265.25, 214.918);
+ ShapeRef *shapeRef254 = new ShapeRef(router, poly254, 254);
+ router->addShape(shapeRef254);
+
+ Polygon poly255(4);
+ poly255.ps[0] = Point(1111.25, 602.918);
+ poly255.ps[1] = Point(1111.25, 642.918);
+ poly255.ps[2] = Point(1055.25, 642.918);
+ poly255.ps[3] = Point(1055.25, 602.918);
+ ShapeRef *shapeRef255 = new ShapeRef(router, poly255, 255);
+ router->addShape(shapeRef255);
+
+ Polygon poly256(4);
+ poly256.ps[0] = Point(1447.25, 398.918);
+ poly256.ps[1] = Point(1447.25, 438.918);
+ poly256.ps[2] = Point(1391.25, 438.918);
+ poly256.ps[3] = Point(1391.25, 398.918);
+ ShapeRef *shapeRef256 = new ShapeRef(router, poly256, 256);
+ router->addShape(shapeRef256);
+
+ Polygon poly257(4);
+ poly257.ps[0] = Point(1447.25, 698.918);
+ poly257.ps[1] = Point(1447.25, 738.918);
+ poly257.ps[2] = Point(1391.25, 738.918);
+ poly257.ps[3] = Point(1391.25, 698.918);
+ ShapeRef *shapeRef257 = new ShapeRef(router, poly257, 257);
+ router->addShape(shapeRef257);
+
+ Polygon poly258(4);
+ poly258.ps[0] = Point(1507.25, 698.918);
+ poly258.ps[1] = Point(1507.25, 738.918);
+ poly258.ps[2] = Point(1451.25, 738.918);
+ poly258.ps[3] = Point(1451.25, 698.918);
+ ShapeRef *shapeRef258 = new ShapeRef(router, poly258, 258);
+ router->addShape(shapeRef258);
+
+ Polygon poly259(4);
+ poly259.ps[0] = Point(751.246, 698.918);
+ poly259.ps[1] = Point(751.246, 738.918);
+ poly259.ps[2] = Point(695.246, 738.918);
+ poly259.ps[3] = Point(695.246, 698.918);
+ ShapeRef *shapeRef259 = new ShapeRef(router, poly259, 259);
+ router->addShape(shapeRef259);
+
+ Polygon poly87(4);
+ poly87.ps[0] = Point(655.246, 612.918);
+ poly87.ps[1] = Point(655.246, 632.918);
+ poly87.ps[2] = Point(635.246, 632.918);
+ poly87.ps[3] = Point(635.246, 612.918);
+ ShapeRef *shapeRef87 = new ShapeRef(router, poly87, 87);
+ router->addShape(shapeRef87);
+
+ Polygon poly134(4);
+ poly134.ps[0] = Point(27.2456, 504.918);
+ poly134.ps[1] = Point(27.2456, 524.918);
+ poly134.ps[2] = Point(7.24557, 524.918);
+ poly134.ps[3] = Point(7.24557, 504.918);
+ ShapeRef *shapeRef134 = new ShapeRef(router, poly134, 134);
+ router->addShape(shapeRef134);
+
+ Polygon poly201(4);
+ poly201.ps[0] = Point(203.246, 548.918);
+ poly201.ps[1] = Point(203.246, 568.918);
+ poly201.ps[2] = Point(183.246, 568.918);
+ poly201.ps[3] = Point(183.246, 548.918);
+ ShapeRef *shapeRef201 = new ShapeRef(router, poly201, 201);
+ router->addShape(shapeRef201);
+
+ Polygon poly202(4);
+ poly202.ps[0] = Point(343.246, 548.918);
+ poly202.ps[1] = Point(343.246, 568.918);
+ poly202.ps[2] = Point(323.246, 568.918);
+ poly202.ps[3] = Point(323.246, 548.918);
+ ShapeRef *shapeRef202 = new ShapeRef(router, poly202, 202);
+ router->addShape(shapeRef202);
+
+ Polygon poly203(4);
+ poly203.ps[0] = Point(499.246, 548.918);
+ poly203.ps[1] = Point(499.246, 568.918);
+ poly203.ps[2] = Point(479.246, 568.918);
+ poly203.ps[3] = Point(479.246, 548.918);
+ ShapeRef *shapeRef203 = new ShapeRef(router, poly203, 203);
+ router->addShape(shapeRef203);
+
+ Polygon poly32(4);
+ poly32.ps[0] = Point(391.246, 644.918);
+ poly32.ps[1] = Point(391.246, 664.918);
+ poly32.ps[2] = Point(371.246, 664.918);
+ poly32.ps[3] = Point(371.246, 644.918);
+ ShapeRef *shapeRef32 = new ShapeRef(router, poly32, 32);
+ router->addShape(shapeRef32);
+
+ Polygon poly25(4);
+ poly25.ps[0] = Point(381.246, 708.918);
+ poly25.ps[1] = Point(381.246, 728.918);
+ poly25.ps[2] = Point(361.246, 728.918);
+ poly25.ps[3] = Point(361.246, 708.918);
+ ShapeRef *shapeRef25 = new ShapeRef(router, poly25, 25);
+ router->addShape(shapeRef25);
+
+ Polygon poly210(4);
+ poly210.ps[0] = Point(499.246, 644.918);
+ poly210.ps[1] = Point(499.246, 664.918);
+ poly210.ps[2] = Point(479.246, 664.918);
+ poly210.ps[3] = Point(479.246, 644.918);
+ ShapeRef *shapeRef210 = new ShapeRef(router, poly210, 210);
+ router->addShape(shapeRef210);
+
+ Polygon poly211(4);
+ poly211.ps[0] = Point(655.246, 644.918);
+ poly211.ps[1] = Point(655.246, 664.918);
+ poly211.ps[2] = Point(635.246, 664.918);
+ poly211.ps[3] = Point(635.246, 644.918);
+ ShapeRef *shapeRef211 = new ShapeRef(router, poly211, 211);
+ router->addShape(shapeRef211);
+
+ Polygon poly212(4);
+ poly212.ps[0] = Point(811.246, 644.918);
+ poly212.ps[1] = Point(811.246, 664.918);
+ poly212.ps[2] = Point(791.246, 664.918);
+ poly212.ps[3] = Point(791.246, 644.918);
+ ShapeRef *shapeRef212 = new ShapeRef(router, poly212, 212);
+ router->addShape(shapeRef212);
+
+ Polygon poly98(4);
+ poly98.ps[0] = Point(499.246, 612.918);
+ poly98.ps[1] = Point(499.246, 632.918);
+ poly98.ps[2] = Point(479.246, 632.918);
+ poly98.ps[3] = Point(479.246, 612.918);
+ ShapeRef *shapeRef98 = new ShapeRef(router, poly98, 98);
+ router->addShape(shapeRef98);
+
+ Polygon poly310(4);
+ poly310.ps[0] = Point(643.246, 398.918);
+ poly310.ps[1] = Point(643.246, 438.918);
+ poly310.ps[2] = Point(587.246, 438.918);
+ poly310.ps[3] = Point(587.246, 398.918);
+ ShapeRef *shapeRef310 = new ShapeRef(router, poly310, 310);
+ router->addShape(shapeRef310);
+
+ Polygon poly311(4);
+ poly311.ps[0] = Point(595.246, 398.918);
+ poly311.ps[1] = Point(595.246, 438.918);
+ poly311.ps[2] = Point(539.246, 438.918);
+ poly311.ps[3] = Point(539.246, 398.918);
+ ShapeRef *shapeRef311 = new ShapeRef(router, poly311, 311);
+ router->addShape(shapeRef311);
+
+ Polygon poly312(4);
+ poly312.ps[0] = Point(595.246, 366.918);
+ poly312.ps[1] = Point(595.246, 406.918);
+ poly312.ps[2] = Point(539.246, 406.918);
+ poly312.ps[3] = Point(539.246, 366.918);
+ ShapeRef *shapeRef312 = new ShapeRef(router, poly312, 312);
+ router->addShape(shapeRef312);
+
+ Polygon poly313(4);
+ poly313.ps[0] = Point(565.246, 182.918);
+ poly313.ps[1] = Point(565.246, 222.918);
+ poly313.ps[2] = Point(509.246, 222.918);
+ poly313.ps[3] = Point(509.246, 182.918);
+ ShapeRef *shapeRef313 = new ShapeRef(router, poly313, 313);
+ router->addShape(shapeRef313);
+
+ Polygon poly314(4);
+ poly314.ps[0] = Point(517.246, 172.918);
+ poly314.ps[1] = Point(517.246, 212.918);
+ poly314.ps[2] = Point(461.246, 212.918);
+ poly314.ps[3] = Point(461.246, 172.918);
+ ShapeRef *shapeRef314 = new ShapeRef(router, poly314, 314);
+ router->addShape(shapeRef314);
+
+ Polygon poly315(4);
+ poly315.ps[0] = Point(517.246, 108.918);
+ poly315.ps[1] = Point(517.246, 148.918);
+ poly315.ps[2] = Point(461.246, 148.918);
+ poly315.ps[3] = Point(461.246, 108.918);
+ ShapeRef *shapeRef315 = new ShapeRef(router, poly315, 315);
+ router->addShape(shapeRef315);
+
+ Polygon poly316(4);
+ poly316.ps[0] = Point(487.246, 570.918);
+ poly316.ps[1] = Point(487.246, 610.918);
+ poly316.ps[2] = Point(431.246, 610.918);
+ poly316.ps[3] = Point(431.246, 570.918);
+ ShapeRef *shapeRef316 = new ShapeRef(router, poly316, 316);
+ router->addShape(shapeRef316);
+
+ Polygon poly317(4);
+ poly317.ps[0] = Point(439.246, 602.918);
+ poly317.ps[1] = Point(439.246, 642.918);
+ poly317.ps[2] = Point(383.246, 642.918);
+ poly317.ps[3] = Point(383.246, 602.918);
+ ShapeRef *shapeRef317 = new ShapeRef(router, poly317, 317);
+ router->addShape(shapeRef317);
+
+ Polygon poly318(4);
+ poly318.ps[0] = Point(439.246, 570.918);
+ poly318.ps[1] = Point(439.246, 610.918);
+ poly318.ps[2] = Point(383.246, 610.918);
+ poly318.ps[3] = Point(383.246, 570.918);
+ ShapeRef *shapeRef318 = new ShapeRef(router, poly318, 318);
+ router->addShape(shapeRef318);
+
+ Polygon poly319(4);
+ poly319.ps[0] = Point(439.246, 494.918);
+ poly319.ps[1] = Point(439.246, 534.918);
+ poly319.ps[2] = Point(383.246, 534.918);
+ poly319.ps[3] = Point(383.246, 494.918);
+ ShapeRef *shapeRef319 = new ShapeRef(router, poly319, 319);
+ router->addShape(shapeRef319);
+
+ Polygon poly320(4);
+ poly320.ps[0] = Point(439.246, 462.918);
+ poly320.ps[1] = Point(439.246, 502.918);
+ poly320.ps[2] = Point(383.246, 502.918);
+ poly320.ps[3] = Point(383.246, 462.918);
+ ShapeRef *shapeRef320 = new ShapeRef(router, poly320, 320);
+ router->addShape(shapeRef320);
+
+ Polygon poly321(4);
+ poly321.ps[0] = Point(487.246, 398.918);
+ poly321.ps[1] = Point(487.246, 438.918);
+ poly321.ps[2] = Point(431.246, 438.918);
+ poly321.ps[3] = Point(431.246, 398.918);
+ ShapeRef *shapeRef321 = new ShapeRef(router, poly321, 321);
+ router->addShape(shapeRef321);
+
+ Polygon poly322(4);
+ poly322.ps[0] = Point(439.246, 398.918);
+ poly322.ps[1] = Point(439.246, 438.918);
+ poly322.ps[2] = Point(383.246, 438.918);
+ poly322.ps[3] = Point(383.246, 398.918);
+ ShapeRef *shapeRef322 = new ShapeRef(router, poly322, 322);
+ router->addShape(shapeRef322);
+
+ Polygon poly323(4);
+ poly323.ps[0] = Point(439.246, 366.918);
+ poly323.ps[1] = Point(439.246, 406.918);
+ poly323.ps[2] = Point(383.246, 406.918);
+ poly323.ps[3] = Point(383.246, 366.918);
+ ShapeRef *shapeRef323 = new ShapeRef(router, poly323, 323);
+ router->addShape(shapeRef323);
+
+ Polygon poly324(4);
+ poly324.ps[0] = Point(409.246, 182.918);
+ poly324.ps[1] = Point(409.246, 222.918);
+ poly324.ps[2] = Point(353.246, 222.918);
+ poly324.ps[3] = Point(353.246, 182.918);
+ ShapeRef *shapeRef324 = new ShapeRef(router, poly324, 324);
+ router->addShape(shapeRef324);
+
+ Polygon poly325(4);
+ poly325.ps[0] = Point(361.246, 172.918);
+ poly325.ps[1] = Point(361.246, 212.918);
+ poly325.ps[2] = Point(305.246, 212.918);
+ poly325.ps[3] = Point(305.246, 172.918);
+ ShapeRef *shapeRef325 = new ShapeRef(router, poly325, 325);
+ router->addShape(shapeRef325);
+
+ Polygon poly96(4);
+ poly96.ps[0] = Point(655.246, 236.918);
+ poly96.ps[1] = Point(655.246, 256.918);
+ poly96.ps[2] = Point(635.246, 256.918);
+ poly96.ps[3] = Point(635.246, 236.918);
+ ShapeRef *shapeRef96 = new ShapeRef(router, poly96, 96);
+ router->addShape(shapeRef96);
+
+ Polygon poly144(4);
+ poly144.ps[0] = Point(27.2456, 160.918);
+ poly144.ps[1] = Point(27.2456, 180.918);
+ poly144.ps[2] = Point(7.24557, 180.918);
+ poly144.ps[3] = Point(7.24557, 160.918);
+ ShapeRef *shapeRef144 = new ShapeRef(router, poly144, 144);
+ router->addShape(shapeRef144);
+
+ Polygon poly192(4);
+ poly192.ps[0] = Point(967.246, 300.918);
+ poly192.ps[1] = Point(967.246, 320.918);
+ poly192.ps[2] = Point(947.246, 320.918);
+ poly192.ps[3] = Point(947.246, 300.918);
+ ShapeRef *shapeRef192 = new ShapeRef(router, poly192, 192);
+ router->addShape(shapeRef192);
+
+ Polygon poly193(4);
+ poly193.ps[0] = Point(27.2456, 440.918);
+ poly193.ps[1] = Point(27.2456, 460.918);
+ poly193.ps[2] = Point(7.24557, 460.918);
+ poly193.ps[3] = Point(7.24557, 440.918);
+ ShapeRef *shapeRef193 = new ShapeRef(router, poly193, 193);
+ router->addShape(shapeRef193);
+
+ Polygon poly173(4);
+ poly173.ps[0] = Point(693.933, 656.918);
+ poly173.ps[1] = Point(693.933, 696.918);
+ poly173.ps[2] = Point(653.933, 696.918);
+ poly173.ps[3] = Point(653.933, 656.918);
+ ShapeRef *shapeRef173 = new ShapeRef(router, poly173, 173);
+ router->addShape(shapeRef173);
+
+ Polygon poly174(4);
+ poly174.ps[0] = Point(693.933, 538.918);
+ poly174.ps[1] = Point(693.933, 578.918);
+ poly174.ps[2] = Point(653.933, 578.918);
+ poly174.ps[3] = Point(653.933, 538.918);
+ ShapeRef *shapeRef174 = new ShapeRef(router, poly174, 174);
+ router->addShape(shapeRef174);
+
+ Polygon poly118(4);
+ poly118.ps[0] = Point(343.246, 268.918);
+ poly118.ps[1] = Point(343.246, 288.918);
+ poly118.ps[2] = Point(323.246, 288.918);
+ poly118.ps[3] = Point(323.246, 268.918);
+ ShapeRef *shapeRef118 = new ShapeRef(router, poly118, 118);
+ router->addShape(shapeRef118);
+
+ Polygon poly183(4);
+ poly183.ps[0] = Point(999.246, 538.918);
+ poly183.ps[1] = Point(999.246, 578.918);
+ poly183.ps[2] = Point(959.246, 578.918);
+ poly183.ps[3] = Point(959.246, 538.918);
+ ShapeRef *shapeRef183 = new ShapeRef(router, poly183, 183);
+ router->addShape(shapeRef183);
+
+ Polygon poly184(4);
+ poly184.ps[0] = Point(999.246, 427.955);
+ poly184.ps[1] = Point(999.246, 467.955);
+ poly184.ps[2] = Point(959.246, 467.955);
+ poly184.ps[3] = Point(959.246, 427.955);
+ ShapeRef *shapeRef184 = new ShapeRef(router, poly184, 184);
+ router->addShape(shapeRef184);
+
+ Polygon poly125(4);
+ poly125.ps[0] = Point(235.246, 408.918);
+ poly125.ps[1] = Point(235.246, 428.918);
+ poly125.ps[2] = Point(215.246, 428.918);
+ poly125.ps[3] = Point(215.246, 408.918);
+ ShapeRef *shapeRef125 = new ShapeRef(router, poly125, 125);
+ router->addShape(shapeRef125);
+
+ Polygon poly101(4);
+ poly101.ps[0] = Point(499.246, 504.918);
+ poly101.ps[1] = Point(499.246, 524.918);
+ poly101.ps[2] = Point(479.246, 524.918);
+ poly101.ps[3] = Point(479.246, 504.918);
+ ShapeRef *shapeRef101 = new ShapeRef(router, poly101, 101);
+ router->addShape(shapeRef101);
+
+ Polygon poly139(4);
+ poly139.ps[0] = Point(27.2456, 268.918);
+ poly139.ps[1] = Point(27.2456, 288.918);
+ poly139.ps[2] = Point(7.24557, 288.918);
+ poly139.ps[3] = Point(7.24557, 268.918);
+ ShapeRef *shapeRef139 = new ShapeRef(router, poly139, 139);
+ router->addShape(shapeRef139);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(859.246, 612.918);
+ poly2.ps[1] = Point(859.246, 632.918);
+ poly2.ps[2] = Point(839.246, 632.918);
+ poly2.ps[3] = Point(839.246, 612.918);
+ ShapeRef *shapeRef2 = new ShapeRef(router, poly2, 2);
+ router->addShape(shapeRef2);
+
+ Polygon poly1(4);
+ poly1.ps[0] = Point(1015.25, 612.918);
+ poly1.ps[1] = Point(1015.25, 632.918);
+ poly1.ps[2] = Point(995.246, 632.918);
+ poly1.ps[3] = Point(995.246, 612.918);
+ ShapeRef *shapeRef1 = new ShapeRef(router, poly1, 1);
+ router->addShape(shapeRef1);
+
+ Polygon poly105(4);
+ poly105.ps[0] = Point(499.246, 376.918);
+ poly105.ps[1] = Point(499.246, 396.918);
+ poly105.ps[2] = Point(479.246, 396.918);
+ poly105.ps[3] = Point(479.246, 376.918);
+ ShapeRef *shapeRef105 = new ShapeRef(router, poly105, 105);
+ router->addShape(shapeRef105);
+
+ Polygon poly29(4);
+ poly29.ps[0] = Point(859.246, 644.918);
+ poly29.ps[1] = Point(859.246, 664.918);
+ poly29.ps[2] = Point(839.246, 664.918);
+ poly29.ps[3] = Point(839.246, 644.918);
+ ShapeRef *shapeRef29 = new ShapeRef(router, poly29, 29);
+ router->addShape(shapeRef29);
+
+ Polygon poly128(4);
+ poly128.ps[0] = Point(235.246, 246.918);
+ poly128.ps[1] = Point(235.246, 266.918);
+ poly128.ps[2] = Point(215.246, 266.918);
+ poly128.ps[3] = Point(215.246, 246.918);
+ ShapeRef *shapeRef128 = new ShapeRef(router, poly128, 128);
+ router->addShape(shapeRef128);
+
+ Polygon poly45(4);
+ poly45.ps[0] = Point(1303.25, 408.918);
+ poly45.ps[1] = Point(1303.25, 428.918);
+ poly45.ps[2] = Point(1283.25, 428.918);
+ poly45.ps[3] = Point(1283.25, 408.918);
+ ShapeRef *shapeRef45 = new ShapeRef(router, poly45, 45);
+ router->addShape(shapeRef45);
+
+ Polygon poly16(4);
+ poly16.ps[0] = Point(1191.25, 656.918);
+ poly16.ps[1] = Point(1191.25, 696.918);
+ poly16.ps[2] = Point(1151.25, 696.918);
+ poly16.ps[3] = Point(1151.25, 656.918);
+ ShapeRef *shapeRef16 = new ShapeRef(router, poly16, 16);
+ router->addShape(shapeRef16);
+
+ Polygon poly88(4);
+ poly88.ps[0] = Point(655.246, 580.918);
+ poly88.ps[1] = Point(655.246, 600.918);
+ poly88.ps[2] = Point(635.246, 600.918);
+ poly88.ps[3] = Point(635.246, 580.918);
+ ShapeRef *shapeRef88 = new ShapeRef(router, poly88, 88);
+ router->addShape(shapeRef88);
+
+ Polygon poly129(4);
+ poly129.ps[0] = Point(203.246, 236.918);
+ poly129.ps[1] = Point(203.246, 256.918);
+ poly129.ps[2] = Point(183.246, 256.918);
+ poly129.ps[3] = Point(183.246, 236.918);
+ ShapeRef *shapeRef129 = new ShapeRef(router, poly129, 129);
+ router->addShape(shapeRef129);
+
+ Polygon poly107(4);
+ poly107.ps[0] = Point(499.246, 268.918);
+ poly107.ps[1] = Point(499.246, 288.918);
+ poly107.ps[2] = Point(479.246, 288.918);
+ poly107.ps[3] = Point(479.246, 268.918);
+ ShapeRef *shapeRef107 = new ShapeRef(router, poly107, 107);
+ router->addShape(shapeRef107);
+
+ Polygon poly160(4);
+ poly160.ps[0] = Point(45.2456, 76.9179);
+ poly160.ps[1] = Point(45.2456, 116.918);
+ poly160.ps[2] = Point(5.24557, 116.918);
+ poly160.ps[3] = Point(5.24557, 76.9179);
+ ShapeRef *shapeRef160 = new ShapeRef(router, poly160, 160);
+ router->addShape(shapeRef160);
+
+ Polygon poly116(4);
+ poly116.ps[0] = Point(343.246, 376.918);
+ poly116.ps[1] = Point(343.246, 396.918);
+ poly116.ps[2] = Point(323.246, 396.918);
+ poly116.ps[3] = Point(323.246, 376.918);
+ ShapeRef *shapeRef116 = new ShapeRef(router, poly116, 116);
+ router->addShape(shapeRef116);
+
+ Polygon poly127(4);
+ poly127.ps[0] = Point(203.246, 376.918);
+ poly127.ps[1] = Point(203.246, 396.918);
+ poly127.ps[2] = Point(183.246, 396.918);
+ poly127.ps[3] = Point(183.246, 376.918);
+ ShapeRef *shapeRef127 = new ShapeRef(router, poly127, 127);
+ router->addShape(shapeRef127);
+
+ Polygon poly57(4);
+ poly57.ps[0] = Point(235.246, 278.918);
+ poly57.ps[1] = Point(235.246, 298.918);
+ poly57.ps[2] = Point(215.246, 298.918);
+ poly57.ps[3] = Point(215.246, 278.918);
+ ShapeRef *shapeRef57 = new ShapeRef(router, poly57, 57);
+ router->addShape(shapeRef57);
+
+ Polygon poly37(4);
+ poly37.ps[0] = Point(859.246, 526.918);
+ poly37.ps[1] = Point(859.246, 546.918);
+ poly37.ps[2] = Point(839.246, 546.918);
+ poly37.ps[3] = Point(839.246, 526.918);
+ ShapeRef *shapeRef37 = new ShapeRef(router, poly37, 37);
+ router->addShape(shapeRef37);
+
+ Polygon poly167(4);
+ poly167.ps[0] = Point(391.246, 427.955);
+ poly167.ps[1] = Point(391.246, 467.955);
+ poly167.ps[2] = Point(351.246, 467.955);
+ poly167.ps[3] = Point(351.246, 427.955);
+ ShapeRef *shapeRef167 = new ShapeRef(router, poly167, 167);
+ router->addShape(shapeRef167);
+
+ Polygon poly77(4);
+ poly77.ps[0] = Point(811.246, 580.918);
+ poly77.ps[1] = Point(811.246, 600.918);
+ poly77.ps[2] = Point(791.246, 600.918);
+ poly77.ps[3] = Point(791.246, 580.918);
+ ShapeRef *shapeRef77 = new ShapeRef(router, poly77, 77);
+ router->addShape(shapeRef77);
+
+ Polygon poly115(4);
+ poly115.ps[0] = Point(343.246, 408.918);
+ poly115.ps[1] = Point(343.246, 428.918);
+ poly115.ps[2] = Point(323.246, 428.918);
+ poly115.ps[3] = Point(323.246, 408.918);
+ ShapeRef *shapeRef115 = new ShapeRef(router, poly115, 115);
+ router->addShape(shapeRef115);
+
+ Polygon poly97(4);
+ poly97.ps[0] = Point(547.246, 580.918);
+ poly97.ps[1] = Point(547.246, 600.918);
+ poly97.ps[2] = Point(527.246, 600.918);
+ poly97.ps[3] = Point(527.246, 580.918);
+ ShapeRef *shapeRef97 = new ShapeRef(router, poly97, 97);
+ router->addShape(shapeRef97);
+
+ Polygon poly28(4);
+ poly28.ps[0] = Point(1015.25, 644.918);
+ poly28.ps[1] = Point(1015.25, 664.918);
+ poly28.ps[2] = Point(995.246, 664.918);
+ poly28.ps[3] = Point(995.246, 644.918);
+ ShapeRef *shapeRef28 = new ShapeRef(router, poly28, 28);
+ router->addShape(shapeRef28);
+
+ Polygon poly126(4);
+ poly126.ps[0] = Point(203.246, 408.918);
+ poly126.ps[1] = Point(203.246, 428.918);
+ poly126.ps[2] = Point(183.246, 428.918);
+ poly126.ps[3] = Point(183.246, 408.918);
+ ShapeRef *shapeRef126 = new ShapeRef(router, poly126, 126);
+ router->addShape(shapeRef126);
+
+ Polygon poly108(4);
+ poly108.ps[0] = Point(499.246, 236.918);
+ poly108.ps[1] = Point(499.246, 256.918);
+ poly108.ps[2] = Point(479.246, 256.918);
+ poly108.ps[3] = Point(479.246, 236.918);
+ ShapeRef *shapeRef108 = new ShapeRef(router, poly108, 108);
+ router->addShape(shapeRef108);
+
+ Polygon poly161(4);
+ poly161.ps[0] = Point(235.246, 312.918);
+ poly161.ps[1] = Point(235.246, 352.918);
+ poly161.ps[2] = Point(195.246, 352.918);
+ poly161.ps[3] = Point(195.246, 312.918);
+ ShapeRef *shapeRef161 = new ShapeRef(router, poly161, 161);
+ router->addShape(shapeRef161);
+
+ Polygon poly146(4);
+ poly146.ps[0] = Point(27.2456, -9.08205);
+ poly146.ps[1] = Point(27.2456, 10.9179);
+ poly146.ps[2] = Point(7.24557, 10.9179);
+ poly146.ps[3] = Point(7.24557, -9.08205);
+ ShapeRef *shapeRef146 = new ShapeRef(router, poly146, 146);
+ router->addShape(shapeRef146);
+
+ Polygon poly114(4);
+ poly114.ps[0] = Point(391.246, 408.918);
+ poly114.ps[1] = Point(391.246, 428.918);
+ poly114.ps[2] = Point(371.246, 428.918);
+ poly114.ps[3] = Point(371.246, 408.918);
+ ShapeRef *shapeRef114 = new ShapeRef(router, poly114, 114);
+ router->addShape(shapeRef114);
+
+ Polygon poly64(4);
+ poly64.ps[0] = Point(1015.25, 580.918);
+ poly64.ps[1] = Point(1015.25, 600.918);
+ poly64.ps[2] = Point(995.246, 600.918);
+ poly64.ps[3] = Point(995.246, 580.918);
+ ShapeRef *shapeRef64 = new ShapeRef(router, poly64, 64);
+ router->addShape(shapeRef64);
+
+ Polygon poly11(4);
+ poly11.ps[0] = Point(1223.25, 312.918);
+ poly11.ps[1] = Point(1223.25, 352.918);
+ poly11.ps[2] = Point(1183.25, 352.918);
+ poly11.ps[3] = Point(1183.25, 312.918);
+ ShapeRef *shapeRef11 = new ShapeRef(router, poly11, 11);
+ router->addShape(shapeRef11);
+
+ Polygon poly67(4);
+ poly67.ps[0] = Point(967.246, 504.918);
+ poly67.ps[1] = Point(967.246, 524.918);
+ poly67.ps[2] = Point(947.246, 524.918);
+ poly67.ps[3] = Point(947.246, 504.918);
+ ShapeRef *shapeRef67 = new ShapeRef(router, poly67, 67);
+ router->addShape(shapeRef67);
+
+ Polygon poly158(4);
+ poly158.ps[0] = Point(77.2456, 538.918);
+ poly158.ps[1] = Point(77.2456, 578.918);
+ poly158.ps[2] = Point(37.2456, 578.918);
+ poly158.ps[3] = Point(37.2456, 538.918);
+ ShapeRef *shapeRef158 = new ShapeRef(router, poly158, 158);
+ router->addShape(shapeRef158);
+
+ Polygon poly159(4);
+ poly159.ps[0] = Point(77.2456, 656.918);
+ poly159.ps[1] = Point(77.2456, 696.918);
+ poly159.ps[2] = Point(37.2456, 696.918);
+ poly159.ps[3] = Point(37.2456, 656.918);
+ ShapeRef *shapeRef159 = new ShapeRef(router, poly159, 159);
+ router->addShape(shapeRef159);
+
+ Polygon poly94(4);
+ poly94.ps[0] = Point(703.246, 246.918);
+ poly94.ps[1] = Point(703.246, 266.918);
+ poly94.ps[2] = Point(683.246, 266.918);
+ poly94.ps[3] = Point(683.246, 246.918);
+ ShapeRef *shapeRef94 = new ShapeRef(router, poly94, 94);
+ router->addShape(shapeRef94);
+
+ Polygon poly102(4);
+ poly102.ps[0] = Point(499.246, 472.918);
+ poly102.ps[1] = Point(499.246, 492.918);
+ poly102.ps[2] = Point(479.246, 492.918);
+ poly102.ps[3] = Point(479.246, 472.918);
+ ShapeRef *shapeRef102 = new ShapeRef(router, poly102, 102);
+ router->addShape(shapeRef102);
+
+ Polygon poly42(4);
+ poly42.ps[0] = Point(77.2456, 526.918);
+ poly42.ps[1] = Point(77.2456, 546.918);
+ poly42.ps[2] = Point(57.2456, 546.918);
+ poly42.ps[3] = Point(57.2456, 526.918);
+ ShapeRef *shapeRef42 = new ShapeRef(router, poly42, 42);
+ router->addShape(shapeRef42);
+
+ Polygon poly131(4);
+ poly131.ps[0] = Point(77.2456, 580.918);
+ poly131.ps[1] = Point(77.2456, 600.918);
+ poly131.ps[2] = Point(57.2456, 600.918);
+ poly131.ps[3] = Point(57.2456, 580.918);
+ ShapeRef *shapeRef131 = new ShapeRef(router, poly131, 131);
+ router->addShape(shapeRef131);
+
+ Polygon poly149(4);
+ poly149.ps[0] = Point(601.954, 56.9179);
+ poly149.ps[1] = Point(601.954, 116.918);
+ poly149.ps[2] = Point(311.954, 116.918);
+ poly149.ps[3] = Point(311.954, 56.9179);
+ ShapeRef *shapeRef149 = new ShapeRef(router, poly149, 149);
+ router->addShape(shapeRef149);
+
+ Polygon poly150(4);
+ poly150.ps[0] = Point(77.2456, 105.987);
+ poly150.ps[1] = Point(77.2456, 145.987);
+ poly150.ps[2] = Point(37.2456, 145.987);
+ poly150.ps[3] = Point(37.2456, 105.987);
+ ShapeRef *shapeRef150 = new ShapeRef(router, poly150, 150);
+ router->addShape(shapeRef150);
+
+ Polygon poly74(4);
+ poly74.ps[0] = Point(967.246, 236.918);
+ poly74.ps[1] = Point(967.246, 256.918);
+ poly74.ps[2] = Point(947.246, 256.918);
+ poly74.ps[3] = Point(947.246, 236.918);
+ ShapeRef *shapeRef74 = new ShapeRef(router, poly74, 74);
+ router->addShape(shapeRef74);
+
+ Polygon poly34(4);
+ poly34.ps[0] = Point(77.2456, 612.918);
+ poly34.ps[1] = Point(77.2456, 632.918);
+ poly34.ps[2] = Point(57.2456, 632.918);
+ poly34.ps[3] = Point(57.2456, 612.918);
+ ShapeRef *shapeRef34 = new ShapeRef(router, poly34, 34);
+ router->addShape(shapeRef34);
+
+ Polygon poly35(4);
+ poly35.ps[0] = Point(1303.25, 504.918);
+ poly35.ps[1] = Point(1303.25, 524.918);
+ poly35.ps[2] = Point(1283.25, 524.918);
+ poly35.ps[3] = Point(1283.25, 504.918);
+ ShapeRef *shapeRef35 = new ShapeRef(router, poly35, 35);
+ router->addShape(shapeRef35);
+
+ Polygon poly26(4);
+ poly26.ps[0] = Point(1381.25, 666.918);
+ poly26.ps[1] = Point(1381.25, 686.918);
+ poly26.ps[2] = Point(1361.25, 686.918);
+ poly26.ps[3] = Point(1361.25, 666.918);
+ ShapeRef *shapeRef26 = new ShapeRef(router, poly26, 26);
+ router->addShape(shapeRef26);
+
+ Polygon poly36(4);
+ poly36.ps[0] = Point(1015.25, 526.918);
+ poly36.ps[1] = Point(1015.25, 546.918);
+ poly36.ps[2] = Point(995.246, 546.918);
+ poly36.ps[3] = Point(995.246, 526.918);
+ ShapeRef *shapeRef36 = new ShapeRef(router, poly36, 36);
+ router->addShape(shapeRef36);
+
+ Polygon poly110(4);
+ poly110.ps[0] = Point(343.246, 612.918);
+ poly110.ps[1] = Point(343.246, 632.918);
+ poly110.ps[2] = Point(323.246, 632.918);
+ poly110.ps[3] = Point(323.246, 612.918);
+ ShapeRef *shapeRef110 = new ShapeRef(router, poly110, 110);
+ router->addShape(shapeRef110);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(703.246, 612.918);
+ poly3.ps[1] = Point(703.246, 632.918);
+ poly3.ps[2] = Point(683.246, 632.918);
+ poly3.ps[3] = Point(683.246, 612.918);
+ ShapeRef *shapeRef3 = new ShapeRef(router, poly3, 3);
+ router->addShape(shapeRef3);
+
+ Polygon poly113(4);
+ poly113.ps[0] = Point(343.246, 472.918);
+ poly113.ps[1] = Point(343.246, 492.918);
+ poly113.ps[2] = Point(323.246, 492.918);
+ poly113.ps[3] = Point(323.246, 472.918);
+ ShapeRef *shapeRef113 = new ShapeRef(router, poly113, 113);
+ router->addShape(shapeRef113);
+
+ Polygon poly137(4);
+ poly137.ps[0] = Point(27.2456, 408.918);
+ poly137.ps[1] = Point(27.2456, 428.918);
+ poly137.ps[2] = Point(7.24557, 428.918);
+ poly137.ps[3] = Point(7.24557, 408.918);
+ ShapeRef *shapeRef137 = new ShapeRef(router, poly137, 137);
+ router->addShape(shapeRef137);
+
+ Polygon poly46(4);
+ poly46.ps[0] = Point(1303.25, 708.918);
+ poly46.ps[1] = Point(1303.25, 728.918);
+ poly46.ps[2] = Point(1283.25, 728.918);
+ poly46.ps[3] = Point(1283.25, 708.918);
+ ShapeRef *shapeRef46 = new ShapeRef(router, poly46, 46);
+ router->addShape(shapeRef46);
+
+ Polygon poly164(4);
+ poly164.ps[0] = Point(235.246, 656.918);
+ poly164.ps[1] = Point(235.246, 696.918);
+ poly164.ps[2] = Point(195.246, 696.918);
+ poly164.ps[3] = Point(195.246, 656.918);
+ ShapeRef *shapeRef164 = new ShapeRef(router, poly164, 164);
+ router->addShape(shapeRef164);
+
+ Polygon poly68(4);
+ poly68.ps[0] = Point(967.246, 472.918);
+ poly68.ps[1] = Point(967.246, 492.918);
+ poly68.ps[2] = Point(947.246, 492.918);
+ poly68.ps[3] = Point(947.246, 472.918);
+ ShapeRef *shapeRef68 = new ShapeRef(router, poly68, 68);
+ router->addShape(shapeRef68);
+
+ Polygon poly22(4);
+ poly22.ps[0] = Point(1171.25, 708.918);
+ poly22.ps[1] = Point(1171.25, 728.918);
+ poly22.ps[2] = Point(1151.25, 728.918);
+ poly22.ps[3] = Point(1151.25, 708.918);
+ ShapeRef *shapeRef22 = new ShapeRef(router, poly22, 22);
+ router->addShape(shapeRef22);
+
+ Polygon poly21(4);
+ poly21.ps[0] = Point(811.246, 708.918);
+ poly21.ps[1] = Point(811.246, 728.918);
+ poly21.ps[2] = Point(791.246, 728.918);
+ poly21.ps[3] = Point(791.246, 708.918);
+ ShapeRef *shapeRef21 = new ShapeRef(router, poly21, 21);
+ router->addShape(shapeRef21);
+
+ Polygon poly162(4);
+ poly162.ps[0] = Point(235.246, 427.955);
+ poly162.ps[1] = Point(235.246, 467.955);
+ poly162.ps[2] = Point(195.246, 467.955);
+ poly162.ps[3] = Point(195.246, 427.955);
+ ShapeRef *shapeRef162 = new ShapeRef(router, poly162, 162);
+ router->addShape(shapeRef162);
+
+ Polygon poly163(4);
+ poly163.ps[0] = Point(235.246, 538.918);
+ poly163.ps[1] = Point(235.246, 578.918);
+ poly163.ps[2] = Point(195.246, 578.918);
+ poly163.ps[3] = Point(195.246, 538.918);
+ ShapeRef *shapeRef163 = new ShapeRef(router, poly163, 163);
+ router->addShape(shapeRef163);
+
+ Polygon poly135(4);
+ poly135.ps[0] = Point(27.2456, 472.918);
+ poly135.ps[1] = Point(27.2456, 492.918);
+ poly135.ps[2] = Point(7.24557, 492.918);
+ poly135.ps[3] = Point(7.24557, 472.918);
+ ShapeRef *shapeRef135 = new ShapeRef(router, poly135, 135);
+ router->addShape(shapeRef135);
+
+ Polygon poly13(4);
+ poly13.ps[0] = Point(1223.25, 730.918);
+ poly13.ps[1] = Point(1223.25, 770.918);
+ poly13.ps[2] = Point(1183.25, 770.918);
+ poly13.ps[3] = Point(1183.25, 730.918);
+ ShapeRef *shapeRef13 = new ShapeRef(router, poly13, 13);
+ router->addShape(shapeRef13);
+
+ Polygon poly93(4);
+ poly93.ps[0] = Point(655.246, 376.918);
+ poly93.ps[1] = Point(655.246, 396.918);
+ poly93.ps[2] = Point(635.246, 396.918);
+ poly93.ps[3] = Point(635.246, 376.918);
+ ShapeRef *shapeRef93 = new ShapeRef(router, poly93, 93);
+ router->addShape(shapeRef93);
+
+ Polygon poly80(4);
+ poly80.ps[0] = Point(859.246, 408.918);
+ poly80.ps[1] = Point(859.246, 428.918);
+ poly80.ps[2] = Point(839.246, 428.918);
+ poly80.ps[3] = Point(839.246, 408.918);
+ ShapeRef *shapeRef80 = new ShapeRef(router, poly80, 80);
+ router->addShape(shapeRef80);
+
+ Polygon poly92(4);
+ poly92.ps[0] = Point(655.246, 408.918);
+ poly92.ps[1] = Point(655.246, 428.918);
+ poly92.ps[2] = Point(635.246, 428.918);
+ poly92.ps[3] = Point(635.246, 408.918);
+ ShapeRef *shapeRef92 = new ShapeRef(router, poly92, 92);
+ router->addShape(shapeRef92);
+
+ Polygon poly59(4);
+ poly59.ps[0] = Point(207.246, -128.082);
+ poly59.ps[1] = Point(207.246, -93.0821);
+ poly59.ps[2] = Point(-12.7544, -93.0821);
+ poly59.ps[3] = Point(-12.7544, -128.082);
+ ShapeRef *shapeRef59 = new ShapeRef(router, poly59, 59);
+ router->addShape(shapeRef59);
+
+ Polygon poly43(4);
+ poly43.ps[0] = Point(1303.25, 278.918);
+ poly43.ps[1] = Point(1303.25, 298.918);
+ poly43.ps[2] = Point(1283.25, 298.918);
+ poly43.ps[3] = Point(1283.25, 278.918);
+ ShapeRef *shapeRef43 = new ShapeRef(router, poly43, 43);
+ router->addShape(shapeRef43);
+
+ Polygon poly106(4);
+ poly106.ps[0] = Point(547.246, 246.918);
+ poly106.ps[1] = Point(547.246, 266.918);
+ poly106.ps[2] = Point(527.246, 266.918);
+ poly106.ps[3] = Point(527.246, 246.918);
+ ShapeRef *shapeRef106 = new ShapeRef(router, poly106, 106);
+ router->addShape(shapeRef106);
+
+ Polygon poly79(4);
+ poly79.ps[0] = Point(811.246, 472.918);
+ poly79.ps[1] = Point(811.246, 492.918);
+ poly79.ps[2] = Point(791.246, 492.918);
+ poly79.ps[3] = Point(791.246, 472.918);
+ ShapeRef *shapeRef79 = new ShapeRef(router, poly79, 79);
+ router->addShape(shapeRef79);
+
+ Polygon poly86(4);
+ poly86.ps[0] = Point(703.246, 580.918);
+ poly86.ps[1] = Point(703.246, 600.918);
+ poly86.ps[2] = Point(683.246, 600.918);
+ poly86.ps[3] = Point(683.246, 580.918);
+ ShapeRef *shapeRef86 = new ShapeRef(router, poly86, 86);
+ router->addShape(shapeRef86);
+
+ Polygon poly112(4);
+ poly112.ps[0] = Point(343.246, 504.918);
+ poly112.ps[1] = Point(343.246, 524.918);
+ poly112.ps[2] = Point(323.246, 524.918);
+ poly112.ps[3] = Point(323.246, 504.918);
+ ShapeRef *shapeRef112 = new ShapeRef(router, poly112, 112);
+ router->addShape(shapeRef112);
+
+ Polygon poly82(4);
+ poly82.ps[0] = Point(811.246, 376.918);
+ poly82.ps[1] = Point(811.246, 396.918);
+ poly82.ps[2] = Point(791.246, 396.918);
+ poly82.ps[3] = Point(791.246, 376.918);
+ ShapeRef *shapeRef82 = new ShapeRef(router, poly82, 82);
+ router->addShape(shapeRef82);
+
+ Polygon poly141(4);
+ poly141.ps[0] = Point(254.976, 160.918);
+ poly141.ps[1] = Point(254.976, 180.918);
+ poly141.ps[2] = Point(234.976, 180.918);
+ poly141.ps[3] = Point(234.976, 160.918);
+ ShapeRef *shapeRef141 = new ShapeRef(router, poly141, 141);
+ router->addShape(shapeRef141);
+
+ Polygon poly15(4);
+ poly15.ps[0] = Point(1469.25, 656.918);
+ poly15.ps[1] = Point(1469.25, 696.918);
+ poly15.ps[2] = Point(1429.25, 696.918);
+ poly15.ps[3] = Point(1429.25, 656.918);
+ ShapeRef *shapeRef15 = new ShapeRef(router, poly15, 15);
+ router->addShape(shapeRef15);
+
+ Polygon poly152(4);
+ poly152.ps[0] = Point(339.219, -27.0821);
+ poly152.ps[1] = Point(339.219, 12.9179);
+ poly152.ps[2] = Point(299.219, 12.9179);
+ poly152.ps[3] = Point(299.219, -27.0821);
+ ShapeRef *shapeRef152 = new ShapeRef(router, poly152, 152);
+ router->addShape(shapeRef152);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(1223.25, 538.918);
+ poly9.ps[1] = Point(1223.25, 578.918);
+ poly9.ps[2] = Point(1183.25, 578.918);
+ poly9.ps[3] = Point(1183.25, 538.918);
+ ShapeRef *shapeRef9 = new ShapeRef(router, poly9, 9);
+ router->addShape(shapeRef9);
+
+ Polygon poly148(4);
+ poly148.ps[0] = Point(207.246, -39.0821);
+ poly148.ps[1] = Point(207.246, -19.0821);
+ poly148.ps[2] = Point(187.246, -19.0821);
+ poly148.ps[3] = Point(187.246, -39.0821);
+ ShapeRef *shapeRef148 = new ShapeRef(router, poly148, 148);
+ router->addShape(shapeRef148);
+
+ Polygon poly140(4);
+ poly140.ps[0] = Point(27.2456, 236.918);
+ poly140.ps[1] = Point(27.2456, 256.918);
+ poly140.ps[2] = Point(7.24557, 256.918);
+ poly140.ps[3] = Point(7.24557, 236.918);
+ ShapeRef *shapeRef140 = new ShapeRef(router, poly140, 140);
+ router->addShape(shapeRef140);
+
+ Polygon poly18(4);
+ poly18.ps[0] = Point(693.933, 730.918);
+ poly18.ps[1] = Point(693.933, 770.918);
+ poly18.ps[2] = Point(653.933, 770.918);
+ poly18.ps[3] = Point(653.933, 730.918);
+ ShapeRef *shapeRef18 = new ShapeRef(router, poly18, 18);
+ router->addShape(shapeRef18);
+
+ Polygon poly40(4);
+ poly40.ps[0] = Point(391.246, 526.918);
+ poly40.ps[1] = Point(391.246, 546.918);
+ poly40.ps[2] = Point(371.246, 546.918);
+ poly40.ps[3] = Point(371.246, 526.918);
+ ShapeRef *shapeRef40 = new ShapeRef(router, poly40, 40);
+ router->addShape(shapeRef40);
+
+ Polygon poly122(4);
+ poly122.ps[0] = Point(203.246, 580.918);
+ poly122.ps[1] = Point(203.246, 600.918);
+ poly122.ps[2] = Point(183.246, 600.918);
+ poly122.ps[3] = Point(183.246, 580.918);
+ ShapeRef *shapeRef122 = new ShapeRef(router, poly122, 122);
+ router->addShape(shapeRef122);
+
+ Polygon poly175(4);
+ poly175.ps[0] = Point(693.933, 427.955);
+ poly175.ps[1] = Point(693.933, 467.955);
+ poly175.ps[2] = Point(653.933, 467.955);
+ poly175.ps[3] = Point(653.933, 427.955);
+ ShapeRef *shapeRef175 = new ShapeRef(router, poly175, 175);
+ router->addShape(shapeRef175);
+
+ Polygon poly176(4);
+ poly176.ps[0] = Point(693.933, 312.918);
+ poly176.ps[1] = Point(693.933, 352.918);
+ poly176.ps[2] = Point(653.933, 352.918);
+ poly176.ps[3] = Point(653.933, 312.918);
+ ShapeRef *shapeRef176 = new ShapeRef(router, poly176, 176);
+ router->addShape(shapeRef176);
+
+ Polygon poly132(4);
+ poly132.ps[0] = Point(27.2456, 612.918);
+ poly132.ps[1] = Point(27.2456, 632.918);
+ poly132.ps[2] = Point(7.24557, 632.918);
+ poly132.ps[3] = Point(7.24557, 612.918);
+ ShapeRef *shapeRef132 = new ShapeRef(router, poly132, 132);
+ router->addShape(shapeRef132);
+
+ Polygon poly44(4);
+ poly44.ps[0] = Point(1093.25, 666.918);
+ poly44.ps[1] = Point(1093.25, 686.918);
+ poly44.ps[2] = Point(1073.25, 686.918);
+ poly44.ps[3] = Point(1073.25, 666.918);
+ ShapeRef *shapeRef44 = new ShapeRef(router, poly44, 44);
+ router->addShape(shapeRef44);
+
+ Polygon poly62(4);
+ poly62.ps[0] = Point(1015.25, 708.918);
+ poly62.ps[1] = Point(1015.25, 728.918);
+ poly62.ps[2] = Point(995.246, 728.918);
+ poly62.ps[3] = Point(995.246, 708.918);
+ ShapeRef *shapeRef62 = new ShapeRef(router, poly62, 62);
+ router->addShape(shapeRef62);
+
+ Polygon poly151(4);
+ poly151.ps[0] = Point(339.219, -71.0821);
+ poly151.ps[1] = Point(339.219, -31.0821);
+ poly151.ps[2] = Point(299.219, -31.0821);
+ poly151.ps[3] = Point(299.219, -71.0821);
+ ShapeRef *shapeRef151 = new ShapeRef(router, poly151, 151);
+ router->addShape(shapeRef151);
+
+ Polygon poly70(4);
+ poly70.ps[0] = Point(967.246, 408.918);
+ poly70.ps[1] = Point(967.246, 428.918);
+ poly70.ps[2] = Point(947.246, 428.918);
+ poly70.ps[3] = Point(947.246, 408.918);
+ ShapeRef *shapeRef70 = new ShapeRef(router, poly70, 70);
+ router->addShape(shapeRef70);
+
+ Polygon poly168(4);
+ poly168.ps[0] = Point(391.246, 312.918);
+ poly168.ps[1] = Point(391.246, 352.918);
+ poly168.ps[2] = Point(351.246, 352.918);
+ poly168.ps[3] = Point(351.246, 312.918);
+ ShapeRef *shapeRef168 = new ShapeRef(router, poly168, 168);
+ router->addShape(shapeRef168);
+
+ Polygon poly169(4);
+ poly169.ps[0] = Point(547.246, 312.918);
+ poly169.ps[1] = Point(547.246, 352.918);
+ poly169.ps[2] = Point(507.246, 352.918);
+ poly169.ps[3] = Point(507.246, 312.918);
+ ShapeRef *shapeRef169 = new ShapeRef(router, poly169, 169);
+ router->addShape(shapeRef169);
+
+ Polygon poly189(4);
+ poly189.ps[0] = Point(499.246, 300.918);
+ poly189.ps[1] = Point(499.246, 320.918);
+ poly189.ps[2] = Point(479.246, 320.918);
+ poly189.ps[3] = Point(479.246, 300.918);
+ ShapeRef *shapeRef189 = new ShapeRef(router, poly189, 189);
+ router->addShape(shapeRef189);
+
+ Polygon poly190(4);
+ poly190.ps[0] = Point(655.246, 300.918);
+ poly190.ps[1] = Point(655.246, 320.918);
+ poly190.ps[2] = Point(635.246, 320.918);
+ poly190.ps[3] = Point(635.246, 300.918);
+ ShapeRef *shapeRef190 = new ShapeRef(router, poly190, 190);
+ router->addShape(shapeRef190);
+
+ Polygon poly191(4);
+ poly191.ps[0] = Point(811.246, 300.918);
+ poly191.ps[1] = Point(811.246, 320.918);
+ poly191.ps[2] = Point(791.246, 320.918);
+ poly191.ps[3] = Point(791.246, 300.918);
+ ShapeRef *shapeRef191 = new ShapeRef(router, poly191, 191);
+ router->addShape(shapeRef191);
+
+ Polygon poly207(4);
+ poly207.ps[0] = Point(27.2456, 644.918);
+ poly207.ps[1] = Point(27.2456, 664.918);
+ poly207.ps[2] = Point(7.24557, 664.918);
+ poly207.ps[3] = Point(7.24557, 644.918);
+ ShapeRef *shapeRef207 = new ShapeRef(router, poly207, 207);
+ router->addShape(shapeRef207);
+
+ Polygon poly208(4);
+ poly208.ps[0] = Point(203.246, 644.918);
+ poly208.ps[1] = Point(203.246, 664.918);
+ poly208.ps[2] = Point(183.246, 664.918);
+ poly208.ps[3] = Point(183.246, 644.918);
+ ShapeRef *shapeRef208 = new ShapeRef(router, poly208, 208);
+ router->addShape(shapeRef208);
+
+ Polygon poly209(4);
+ poly209.ps[0] = Point(343.246, 644.918);
+ poly209.ps[1] = Point(343.246, 664.918);
+ poly209.ps[2] = Point(323.246, 664.918);
+ poly209.ps[3] = Point(323.246, 644.918);
+ ShapeRef *shapeRef209 = new ShapeRef(router, poly209, 209);
+ router->addShape(shapeRef209);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(1223.25, 427.955);
+ poly10.ps[1] = Point(1223.25, 467.955);
+ poly10.ps[2] = Point(1183.25, 467.955);
+ poly10.ps[3] = Point(1183.25, 427.955);
+ ShapeRef *shapeRef10 = new ShapeRef(router, poly10, 10);
+ router->addShape(shapeRef10);
+
+ Polygon poly30(4);
+ poly30.ps[0] = Point(703.246, 644.918);
+ poly30.ps[1] = Point(703.246, 664.918);
+ poly30.ps[2] = Point(683.246, 664.918);
+ poly30.ps[3] = Point(683.246, 644.918);
+ ShapeRef *shapeRef30 = new ShapeRef(router, poly30, 30);
+ router->addShape(shapeRef30);
+
+ Polygon poly119(4);
+ poly119.ps[0] = Point(343.246, 236.918);
+ poly119.ps[1] = Point(343.246, 256.918);
+ poly119.ps[2] = Point(323.246, 256.918);
+ poly119.ps[3] = Point(323.246, 236.918);
+ ShapeRef *shapeRef119 = new ShapeRef(router, poly119, 119);
+ router->addShape(shapeRef119);
+
+ Polygon poly12(4);
+ poly12.ps[0] = Point(1469.25, 730.918);
+ poly12.ps[1] = Point(1469.25, 770.918);
+ poly12.ps[2] = Point(1429.25, 770.918);
+ poly12.ps[3] = Point(1429.25, 730.918);
+ ShapeRef *shapeRef12 = new ShapeRef(router, poly12, 12);
+ router->addShape(shapeRef12);
+
+ Polygon poly154(4);
+ poly154.ps[0] = Point(217.246, 140.918);
+ poly154.ps[1] = Point(217.246, 180.918);
+ poly154.ps[2] = Point(177.246, 180.918);
+ poly154.ps[3] = Point(177.246, 140.918);
+ ShapeRef *shapeRef154 = new ShapeRef(router, poly154, 154);
+ router->addShape(shapeRef154);
+
+ Polygon poly155(4);
+ poly155.ps[0] = Point(77.2456, 140.918);
+ poly155.ps[1] = Point(77.2456, 180.918);
+ poly155.ps[2] = Point(37.2456, 180.918);
+ poly155.ps[3] = Point(37.2456, 140.918);
+ ShapeRef *shapeRef155 = new ShapeRef(router, poly155, 155);
+ router->addShape(shapeRef155);
+
+ Polygon poly39(4);
+ poly39.ps[0] = Point(547.246, 526.918);
+ poly39.ps[1] = Point(547.246, 546.918);
+ poly39.ps[2] = Point(527.246, 546.918);
+ poly39.ps[3] = Point(527.246, 526.918);
+ ShapeRef *shapeRef39 = new ShapeRef(router, poly39, 39);
+ router->addShape(shapeRef39);
+
+ Polygon poly142(4);
+ poly142.ps[0] = Point(155.246, 76.9179);
+ poly142.ps[1] = Point(155.246, 96.9179);
+ poly142.ps[2] = Point(135.246, 96.9179);
+ poly142.ps[3] = Point(135.246, 76.9179);
+ ShapeRef *shapeRef142 = new ShapeRef(router, poly142, 142);
+ router->addShape(shapeRef142);
+
+ Polygon poly143(4);
+ poly143.ps[0] = Point(155.246, 44.9179);
+ poly143.ps[1] = Point(155.246, 64.9179);
+ poly143.ps[2] = Point(135.246, 64.9179);
+ poly143.ps[3] = Point(135.246, 44.9179);
+ ShapeRef *shapeRef143 = new ShapeRef(router, poly143, 143);
+ router->addShape(shapeRef143);
+
+ Polygon poly76(4);
+ poly76.ps[0] = Point(811.246, 612.918);
+ poly76.ps[1] = Point(811.246, 632.918);
+ poly76.ps[2] = Point(791.246, 632.918);
+ poly76.ps[3] = Point(791.246, 612.918);
+ ShapeRef *shapeRef76 = new ShapeRef(router, poly76, 76);
+ router->addShape(shapeRef76);
+
+ Polygon poly55(4);
+ poly55.ps[0] = Point(547.246, 278.918);
+ poly55.ps[1] = Point(547.246, 298.918);
+ poly55.ps[2] = Point(527.246, 298.918);
+ poly55.ps[3] = Point(527.246, 278.918);
+ ShapeRef *shapeRef55 = new ShapeRef(router, poly55, 55);
+ router->addShape(shapeRef55);
+
+ Polygon poly133(4);
+ poly133.ps[0] = Point(27.2456, 580.918);
+ poly133.ps[1] = Point(27.2456, 600.918);
+ poly133.ps[2] = Point(7.24557, 600.918);
+ poly133.ps[3] = Point(7.24557, 580.918);
+ ShapeRef *shapeRef133 = new ShapeRef(router, poly133, 133);
+ router->addShape(shapeRef133);
+
+ Polygon poly123(4);
+ poly123.ps[0] = Point(203.246, 504.918);
+ poly123.ps[1] = Point(203.246, 524.918);
+ poly123.ps[2] = Point(183.246, 524.918);
+ poly123.ps[3] = Point(183.246, 504.918);
+ ShapeRef *shapeRef123 = new ShapeRef(router, poly123, 123);
+ router->addShape(shapeRef123);
+
+ Polygon poly81(4);
+ poly81.ps[0] = Point(811.246, 408.918);
+ poly81.ps[1] = Point(811.246, 428.918);
+ poly81.ps[2] = Point(791.246, 428.918);
+ poly81.ps[3] = Point(791.246, 408.918);
+ ShapeRef *shapeRef81 = new ShapeRef(router, poly81, 81);
+ router->addShape(shapeRef81);
+
+ Polygon poly170(4);
+ poly170.ps[0] = Point(547.246, 427.955);
+ poly170.ps[1] = Point(547.246, 467.955);
+ poly170.ps[2] = Point(507.246, 467.955);
+ poly170.ps[3] = Point(507.246, 427.955);
+ ShapeRef *shapeRef170 = new ShapeRef(router, poly170, 170);
+ router->addShape(shapeRef170);
+
+ Polygon poly145(4);
+ poly145.ps[0] = Point(27.2456, 22.9179);
+ poly145.ps[1] = Point(27.2456, 42.9179);
+ poly145.ps[2] = Point(7.24557, 42.9179);
+ poly145.ps[3] = Point(7.24557, 22.9179);
+ ShapeRef *shapeRef145 = new ShapeRef(router, poly145, 145);
+ router->addShape(shapeRef145);
+
+ Polygon poly14(4);
+ poly14.ps[0] = Point(1191.25, 730.918);
+ poly14.ps[1] = Point(1191.25, 770.918);
+ poly14.ps[2] = Point(1151.25, 770.918);
+ poly14.ps[3] = Point(1151.25, 730.918);
+ ShapeRef *shapeRef14 = new ShapeRef(router, poly14, 14);
+ router->addShape(shapeRef14);
+
+ Polygon poly111(4);
+ poly111.ps[0] = Point(343.246, 580.918);
+ poly111.ps[1] = Point(343.246, 600.918);
+ poly111.ps[2] = Point(323.246, 600.918);
+ poly111.ps[3] = Point(323.246, 580.918);
+ ShapeRef *shapeRef111 = new ShapeRef(router, poly111, 111);
+ router->addShape(shapeRef111);
+
+ Polygon poly299(4);
+ poly299.ps[0] = Point(751.246, 398.918);
+ poly299.ps[1] = Point(751.246, 438.918);
+ poly299.ps[2] = Point(695.246, 438.918);
+ poly299.ps[3] = Point(695.246, 398.918);
+ ShapeRef *shapeRef299 = new ShapeRef(router, poly299, 299);
+ router->addShape(shapeRef299);
+
+ Polygon poly300(4);
+ poly300.ps[0] = Point(751.246, 366.918);
+ poly300.ps[1] = Point(751.246, 406.918);
+ poly300.ps[2] = Point(695.246, 406.918);
+ poly300.ps[3] = Point(695.246, 366.918);
+ ShapeRef *shapeRef300 = new ShapeRef(router, poly300, 300);
+ router->addShape(shapeRef300);
+
+ Polygon poly301(4);
+ poly301.ps[0] = Point(721.246, 182.918);
+ poly301.ps[1] = Point(721.246, 222.918);
+ poly301.ps[2] = Point(665.246, 222.918);
+ poly301.ps[3] = Point(665.246, 182.918);
+ ShapeRef *shapeRef301 = new ShapeRef(router, poly301, 301);
+ router->addShape(shapeRef301);
+
+ Polygon poly302(4);
+ poly302.ps[0] = Point(673.246, 172.918);
+ poly302.ps[1] = Point(673.246, 212.918);
+ poly302.ps[2] = Point(617.246, 212.918);
+ poly302.ps[3] = Point(617.246, 172.918);
+ ShapeRef *shapeRef302 = new ShapeRef(router, poly302, 302);
+ router->addShape(shapeRef302);
+
+ Polygon poly303(4);
+ poly303.ps[0] = Point(673.246, 108.918);
+ poly303.ps[1] = Point(673.246, 148.918);
+ poly303.ps[2] = Point(617.246, 148.918);
+ poly303.ps[3] = Point(617.246, 108.918);
+ ShapeRef *shapeRef303 = new ShapeRef(router, poly303, 303);
+ router->addShape(shapeRef303);
+
+ Polygon poly304(4);
+ poly304.ps[0] = Point(643.246, 570.918);
+ poly304.ps[1] = Point(643.246, 610.918);
+ poly304.ps[2] = Point(587.246, 610.918);
+ poly304.ps[3] = Point(587.246, 570.918);
+ ShapeRef *shapeRef304 = new ShapeRef(router, poly304, 304);
+ router->addShape(shapeRef304);
+
+ Polygon poly305(4);
+ poly305.ps[0] = Point(595.246, 602.918);
+ poly305.ps[1] = Point(595.246, 642.918);
+ poly305.ps[2] = Point(539.246, 642.918);
+ poly305.ps[3] = Point(539.246, 602.918);
+ ShapeRef *shapeRef305 = new ShapeRef(router, poly305, 305);
+ router->addShape(shapeRef305);
+
+ Polygon poly306(4);
+ poly306.ps[0] = Point(595.246, 570.918);
+ poly306.ps[1] = Point(595.246, 610.918);
+ poly306.ps[2] = Point(539.246, 610.918);
+ poly306.ps[3] = Point(539.246, 570.918);
+ ShapeRef *shapeRef306 = new ShapeRef(router, poly306, 306);
+ router->addShape(shapeRef306);
+
+ Polygon poly307(4);
+ poly307.ps[0] = Point(643.246, 466.951);
+ poly307.ps[1] = Point(643.246, 506.951);
+ poly307.ps[2] = Point(587.246, 506.951);
+ poly307.ps[3] = Point(587.246, 466.951);
+ ShapeRef *shapeRef307 = new ShapeRef(router, poly307, 307);
+ router->addShape(shapeRef307);
+
+ Polygon poly308(4);
+ poly308.ps[0] = Point(595.246, 494.918);
+ poly308.ps[1] = Point(595.246, 534.918);
+ poly308.ps[2] = Point(539.246, 534.918);
+ poly308.ps[3] = Point(539.246, 494.918);
+ ShapeRef *shapeRef308 = new ShapeRef(router, poly308, 308);
+ router->addShape(shapeRef308);
+
+ Polygon poly309(4);
+ poly309.ps[0] = Point(595.246, 462.918);
+ poly309.ps[1] = Point(595.246, 502.918);
+ poly309.ps[2] = Point(539.246, 502.918);
+ poly309.ps[3] = Point(539.246, 462.918);
+ ShapeRef *shapeRef309 = new ShapeRef(router, poly309, 309);
+ router->addShape(shapeRef309);
+
+ Polygon poly51(4);
+ poly51.ps[0] = Point(77.2456, 300.918);
+ poly51.ps[1] = Point(77.2456, 320.918);
+ poly51.ps[2] = Point(57.2456, 320.918);
+ poly51.ps[3] = Point(57.2456, 300.918);
+ ShapeRef *shapeRef51 = new ShapeRef(router, poly51, 51);
+ router->addShape(shapeRef51);
+
+ Polygon poly49(4);
+ poly49.ps[0] = Point(859.246, 708.918);
+ poly49.ps[1] = Point(859.246, 728.918);
+ poly49.ps[2] = Point(839.246, 728.918);
+ poly49.ps[3] = Point(839.246, 708.918);
+ ShapeRef *shapeRef49 = new ShapeRef(router, poly49, 49);
+ router->addShape(shapeRef49);
+
+ Polygon poly267(4);
+ poly267.ps[0] = Point(409.246, 214.918);
+ poly267.ps[1] = Point(409.246, 254.918);
+ poly267.ps[2] = Point(353.246, 254.918);
+ poly267.ps[3] = Point(353.246, 214.918);
+ ShapeRef *shapeRef267 = new ShapeRef(router, poly267, 267);
+ router->addShape(shapeRef267);
+
+ Polygon poly268(4);
+ poly268.ps[0] = Point(331.246, 268.918);
+ poly268.ps[1] = Point(331.246, 308.918);
+ poly268.ps[2] = Point(275.246, 308.918);
+ poly268.ps[3] = Point(275.246, 268.918);
+ ShapeRef *shapeRef268 = new ShapeRef(router, poly268, 268);
+ router->addShape(shapeRef268);
+
+ Polygon poly269(4);
+ poly269.ps[0] = Point(1159.25, 698.918);
+ poly269.ps[1] = Point(1159.25, 738.918);
+ poly269.ps[2] = Point(1103.25, 738.918);
+ poly269.ps[3] = Point(1103.25, 698.918);
+ ShapeRef *shapeRef269 = new ShapeRef(router, poly269, 269);
+ router->addShape(shapeRef269);
+
+ Polygon poly270(4);
+ poly270.ps[0] = Point(1063.25, 666.918);
+ poly270.ps[1] = Point(1063.25, 706.918);
+ poly270.ps[2] = Point(1007.25, 706.918);
+ poly270.ps[3] = Point(1007.25, 666.918);
+ ShapeRef *shapeRef270 = new ShapeRef(router, poly270, 270);
+ router->addShape(shapeRef270);
+
+ Polygon poly271(4);
+ poly271.ps[0] = Point(1159.25, 570.918);
+ poly271.ps[1] = Point(1159.25, 610.918);
+ poly271.ps[2] = Point(1103.25, 610.918);
+ poly271.ps[3] = Point(1103.25, 570.918);
+ ShapeRef *shapeRef271 = new ShapeRef(router, poly271, 271);
+ router->addShape(shapeRef271);
+
+ Polygon poly272(4);
+ poly272.ps[0] = Point(1063.25, 602.918);
+ poly272.ps[1] = Point(1063.25, 642.918);
+ poly272.ps[2] = Point(1007.25, 642.918);
+ poly272.ps[3] = Point(1007.25, 602.918);
+ ShapeRef *shapeRef272 = new ShapeRef(router, poly272, 272);
+ router->addShape(shapeRef272);
+
+ Polygon poly273(4);
+ poly273.ps[0] = Point(1063.25, 570.918);
+ poly273.ps[1] = Point(1063.25, 610.918);
+ poly273.ps[2] = Point(1007.25, 610.918);
+ poly273.ps[3] = Point(1007.25, 570.918);
+ ShapeRef *shapeRef273 = new ShapeRef(router, poly273, 273);
+ router->addShape(shapeRef273);
+
+ Polygon poly199(4);
+ poly199.ps[0] = Point(655.246, 440.918);
+ poly199.ps[1] = Point(655.246, 460.918);
+ poly199.ps[2] = Point(635.246, 460.918);
+ poly199.ps[3] = Point(635.246, 440.918);
+ ShapeRef *shapeRef199 = new ShapeRef(router, poly199, 199);
+ router->addShape(shapeRef199);
+
+ Polygon poly200(4);
+ poly200.ps[0] = Point(27.2456, 548.918);
+ poly200.ps[1] = Point(27.2456, 568.918);
+ poly200.ps[2] = Point(7.24557, 568.918);
+ poly200.ps[3] = Point(7.24557, 548.918);
+ ShapeRef *shapeRef200 = new ShapeRef(router, poly200, 200);
+ router->addShape(shapeRef200);
+
+ Polygon poly227(4);
+ poly227.ps[0] = Point(799.246, 602.918);
+ poly227.ps[1] = Point(799.246, 642.918);
+ poly227.ps[2] = Point(743.246, 642.918);
+ poly227.ps[3] = Point(743.246, 602.918);
+ ShapeRef *shapeRef227 = new ShapeRef(router, poly227, 227);
+ router->addShape(shapeRef227);
+
+ Polygon poly228(4);
+ poly228.ps[0] = Point(643.246, 602.918);
+ poly228.ps[1] = Point(643.246, 642.918);
+ poly228.ps[2] = Point(587.246, 642.918);
+ poly228.ps[3] = Point(587.246, 602.918);
+ ShapeRef *shapeRef228 = new ShapeRef(router, poly228, 228);
+ router->addShape(shapeRef228);
+
+ Polygon poly229(4);
+ poly229.ps[0] = Point(487.246, 602.918);
+ poly229.ps[1] = Point(487.246, 642.918);
+ poly229.ps[2] = Point(431.246, 642.918);
+ poly229.ps[3] = Point(431.246, 602.918);
+ ShapeRef *shapeRef229 = new ShapeRef(router, poly229, 229);
+ router->addShape(shapeRef229);
+
+ Polygon poly230(4);
+ poly230.ps[0] = Point(331.246, 602.918);
+ poly230.ps[1] = Point(331.246, 642.918);
+ poly230.ps[2] = Point(275.246, 642.918);
+ poly230.ps[3] = Point(275.246, 602.918);
+ ShapeRef *shapeRef230 = new ShapeRef(router, poly230, 230);
+ router->addShape(shapeRef230);
+
+ Polygon poly185(4);
+ poly185.ps[0] = Point(999.246, 312.918);
+ poly185.ps[1] = Point(999.246, 352.918);
+ poly185.ps[2] = Point(959.246, 352.918);
+ poly185.ps[3] = Point(959.246, 312.918);
+ ShapeRef *shapeRef185 = new ShapeRef(router, poly185, 185);
+ router->addShape(shapeRef185);
+
+ Polygon poly186(4);
+ poly186.ps[0] = Point(27.2456, 300.918);
+ poly186.ps[1] = Point(27.2456, 320.918);
+ poly186.ps[2] = Point(7.24557, 320.918);
+ poly186.ps[3] = Point(7.24557, 300.918);
+ ShapeRef *shapeRef186 = new ShapeRef(router, poly186, 186);
+ router->addShape(shapeRef186);
+
+ Polygon poly204(4);
+ poly204.ps[0] = Point(655.246, 548.918);
+ poly204.ps[1] = Point(655.246, 568.918);
+ poly204.ps[2] = Point(635.246, 568.918);
+ poly204.ps[3] = Point(635.246, 548.918);
+ ShapeRef *shapeRef204 = new ShapeRef(router, poly204, 204);
+ router->addShape(shapeRef204);
+
+ Polygon poly205(4);
+ poly205.ps[0] = Point(811.246, 548.918);
+ poly205.ps[1] = Point(811.246, 568.918);
+ poly205.ps[2] = Point(791.246, 568.918);
+ poly205.ps[3] = Point(791.246, 548.918);
+ ShapeRef *shapeRef205 = new ShapeRef(router, poly205, 205);
+ router->addShape(shapeRef205);
+
+ Polygon poly206(4);
+ poly206.ps[0] = Point(967.246, 548.918);
+ poly206.ps[1] = Point(967.246, 568.918);
+ poly206.ps[2] = Point(947.246, 568.918);
+ poly206.ps[3] = Point(947.246, 548.918);
+ ShapeRef *shapeRef206 = new ShapeRef(router, poly206, 206);
+ router->addShape(shapeRef206);
+
+ Polygon poly237(4);
+ poly237.ps[0] = Point(1399.25, 602.918);
+ poly237.ps[1] = Point(1399.25, 642.918);
+ poly237.ps[2] = Point(1343.25, 642.918);
+ poly237.ps[3] = Point(1343.25, 602.918);
+ ShapeRef *shapeRef237 = new ShapeRef(router, poly237, 237);
+ router->addShape(shapeRef237);
+
+ Polygon poly238(4);
+ poly238.ps[0] = Point(1447.25, 555.942);
+ poly238.ps[1] = Point(1447.25, 595.942);
+ poly238.ps[2] = Point(1391.25, 595.942);
+ poly238.ps[3] = Point(1391.25, 555.942);
+ ShapeRef *shapeRef238 = new ShapeRef(router, poly238, 238);
+ router->addShape(shapeRef238);
+
+ Polygon poly239(4);
+ poly239.ps[0] = Point(1159.25, 634.918);
+ poly239.ps[1] = Point(1159.25, 674.918);
+ poly239.ps[2] = Point(1103.25, 674.918);
+ poly239.ps[3] = Point(1103.25, 634.918);
+ ShapeRef *shapeRef239 = new ShapeRef(router, poly239, 239);
+ router->addShape(shapeRef239);
+
+ Polygon poly240(4);
+ poly240.ps[0] = Point(955.246, 634.918);
+ poly240.ps[1] = Point(955.246, 674.918);
+ poly240.ps[2] = Point(899.246, 674.918);
+ poly240.ps[3] = Point(899.246, 634.918);
+ ShapeRef *shapeRef240 = new ShapeRef(router, poly240, 240);
+ router->addShape(shapeRef240);
+
+ Polygon poly241(4);
+ poly241.ps[0] = Point(799.246, 634.918);
+ poly241.ps[1] = Point(799.246, 674.918);
+ poly241.ps[2] = Point(743.246, 674.918);
+ poly241.ps[3] = Point(743.246, 634.918);
+ ShapeRef *shapeRef241 = new ShapeRef(router, poly241, 241);
+ router->addShape(shapeRef241);
+
+ Polygon poly71(4);
+ poly71.ps[0] = Point(967.246, 376.918);
+ poly71.ps[1] = Point(967.246, 396.918);
+ poly71.ps[2] = Point(947.246, 396.918);
+ poly71.ps[3] = Point(947.246, 376.918);
+ ShapeRef *shapeRef71 = new ShapeRef(router, poly71, 71);
+ router->addShape(shapeRef71);
+
+ Polygon poly50(4);
+ poly50.ps[0] = Point(77.2456, 22.9179);
+ poly50.ps[1] = Point(77.2456, 42.9179);
+ poly50.ps[2] = Point(57.2456, 42.9179);
+ poly50.ps[3] = Point(57.2456, 22.9179);
+ ShapeRef *shapeRef50 = new ShapeRef(router, poly50, 50);
+ router->addShape(shapeRef50);
+
+ Polygon poly358(4);
+ poly358.ps[0] = Point(361.246, 204.918);
+ poly358.ps[1] = Point(361.246, 244.918);
+ poly358.ps[2] = Point(305.246, 244.918);
+ poly358.ps[3] = Point(305.246, 204.918);
+ ShapeRef *shapeRef358 = new ShapeRef(router, poly358, 358);
+ router->addShape(shapeRef358);
+
+ Polygon poly359(4);
+ poly359.ps[0] = Point(517.246, 204.918);
+ poly359.ps[1] = Point(517.246, 244.918);
+ poly359.ps[2] = Point(461.246, 244.918);
+ poly359.ps[3] = Point(461.246, 204.918);
+ ShapeRef *shapeRef359 = new ShapeRef(router, poly359, 359);
+ router->addShape(shapeRef359);
+
+ Polygon poly360(4);
+ poly360.ps[0] = Point(673.246, 204.918);
+ poly360.ps[1] = Point(673.246, 244.918);
+ poly360.ps[2] = Point(617.246, 244.918);
+ poly360.ps[3] = Point(617.246, 204.918);
+ ShapeRef *shapeRef360 = new ShapeRef(router, poly360, 360);
+ router->addShape(shapeRef360);
+
+ Polygon poly361(4);
+ poly361.ps[0] = Point(829.246, 204.918);
+ poly361.ps[1] = Point(829.246, 244.918);
+ poly361.ps[2] = Point(773.246, 244.918);
+ poly361.ps[3] = Point(773.246, 204.918);
+ ShapeRef *shapeRef361 = new ShapeRef(router, poly361, 361);
+ router->addShape(shapeRef361);
+
+ Polygon poly362(4);
+ poly362.ps[0] = Point(985.246, 204.918);
+ poly362.ps[1] = Point(985.246, 244.918);
+ poly362.ps[2] = Point(929.246, 244.918);
+ poly362.ps[3] = Point(929.246, 204.918);
+ ShapeRef *shapeRef362 = new ShapeRef(router, poly362, 362);
+ router->addShape(shapeRef362);
+
+ Polygon poly363(4);
+ poly363.ps[0] = Point(45.2456, 344.918);
+ poly363.ps[1] = Point(45.2456, 384.918);
+ poly363.ps[2] = Point(-10.7544, 384.918);
+ poly363.ps[3] = Point(-10.7544, 344.918);
+ ShapeRef *shapeRef363 = new ShapeRef(router, poly363, 363);
+ router->addShape(shapeRef363);
+
+ Polygon poly364(4);
+ poly364.ps[0] = Point(283.246, 430.918);
+ poly364.ps[1] = Point(283.246, 470.918);
+ poly364.ps[2] = Point(227.246, 470.918);
+ poly364.ps[3] = Point(227.246, 430.918);
+ ShapeRef *shapeRef364 = new ShapeRef(router, poly364, 364);
+ router->addShape(shapeRef364);
+
+ Polygon poly365(4);
+ poly365.ps[0] = Point(439.246, 430.918);
+ poly365.ps[1] = Point(439.246, 470.918);
+ poly365.ps[2] = Point(383.246, 470.918);
+ poly365.ps[3] = Point(383.246, 430.918);
+ ShapeRef *shapeRef365 = new ShapeRef(router, poly365, 365);
+ router->addShape(shapeRef365);
+
+ Polygon poly366(4);
+ poly366.ps[0] = Point(595.246, 430.918);
+ poly366.ps[1] = Point(595.246, 470.918);
+ poly366.ps[2] = Point(539.246, 470.918);
+ poly366.ps[3] = Point(539.246, 430.918);
+ ShapeRef *shapeRef366 = new ShapeRef(router, poly366, 366);
+ router->addShape(shapeRef366);
+
+ Polygon poly367(4);
+ poly367.ps[0] = Point(907.246, 430.918);
+ poly367.ps[1] = Point(907.246, 470.918);
+ poly367.ps[2] = Point(851.246, 470.918);
+ poly367.ps[3] = Point(851.246, 430.918);
+ ShapeRef *shapeRef367 = new ShapeRef(router, poly367, 367);
+ router->addShape(shapeRef367);
+
+ Polygon poly368(4);
+ poly368.ps[0] = Point(1063.25, 430.918);
+ poly368.ps[1] = Point(1063.25, 470.918);
+ poly368.ps[2] = Point(1007.25, 470.918);
+ poly368.ps[3] = Point(1007.25, 430.918);
+ ShapeRef *shapeRef368 = new ShapeRef(router, poly368, 368);
+ router->addShape(shapeRef368);
+
+ Polygon poly369(4);
+ poly369.ps[0] = Point(751.246, 430.918);
+ poly369.ps[1] = Point(751.246, 470.918);
+ poly369.ps[2] = Point(695.246, 470.918);
+ poly369.ps[3] = Point(695.246, 430.918);
+ ShapeRef *shapeRef369 = new ShapeRef(router, poly369, 369);
+ router->addShape(shapeRef369);
+
+ Polygon poly370(4);
+ poly370.ps[0] = Point(125.246, 538.918);
+ poly370.ps[1] = Point(125.246, 578.918);
+ poly370.ps[2] = Point(69.2456, 578.918);
+ poly370.ps[3] = Point(69.2456, 538.918);
+ ShapeRef *shapeRef370 = new ShapeRef(router, poly370, 370);
+ router->addShape(shapeRef370);
+
+ Polygon poly371(4);
+ poly371.ps[0] = Point(283.246, 538.918);
+ poly371.ps[1] = Point(283.246, 578.918);
+ poly371.ps[2] = Point(227.246, 578.918);
+ poly371.ps[3] = Point(227.246, 538.918);
+ ShapeRef *shapeRef371 = new ShapeRef(router, poly371, 371);
+ router->addShape(shapeRef371);
+
+ Polygon poly372(4);
+ poly372.ps[0] = Point(439.246, 538.918);
+ poly372.ps[1] = Point(439.246, 578.918);
+ poly372.ps[2] = Point(383.246, 578.918);
+ poly372.ps[3] = Point(383.246, 538.918);
+ ShapeRef *shapeRef372 = new ShapeRef(router, poly372, 372);
+ router->addShape(shapeRef372);
+
+ Polygon poly373(4);
+ poly373.ps[0] = Point(595.246, 538.918);
+ poly373.ps[1] = Point(595.246, 578.918);
+ poly373.ps[2] = Point(539.246, 578.918);
+ poly373.ps[3] = Point(539.246, 538.918);
+ ShapeRef *shapeRef373 = new ShapeRef(router, poly373, 373);
+ router->addShape(shapeRef373);
+
+ Polygon poly374(4);
+ poly374.ps[0] = Point(751.246, 538.918);
+ poly374.ps[1] = Point(751.246, 578.918);
+ poly374.ps[2] = Point(695.246, 578.918);
+ poly374.ps[3] = Point(695.246, 538.918);
+ ShapeRef *shapeRef374 = new ShapeRef(router, poly374, 374);
+ router->addShape(shapeRef374);
+
+ Polygon poly375(4);
+ poly375.ps[0] = Point(907.246, 538.918);
+ poly375.ps[1] = Point(907.246, 578.918);
+ poly375.ps[2] = Point(851.246, 578.918);
+ poly375.ps[3] = Point(851.246, 538.918);
+ ShapeRef *shapeRef375 = new ShapeRef(router, poly375, 375);
+ router->addShape(shapeRef375);
+
+ Polygon poly376(4);
+ poly376.ps[0] = Point(1063.25, 538.918);
+ poly376.ps[1] = Point(1063.25, 578.918);
+ poly376.ps[2] = Point(1007.25, 578.918);
+ poly376.ps[3] = Point(1007.25, 538.918);
+ ShapeRef *shapeRef376 = new ShapeRef(router, poly376, 376);
+ router->addShape(shapeRef376);
+
+ Polygon poly377(4);
+ poly377.ps[0] = Point(125.246, 634.918);
+ poly377.ps[1] = Point(125.246, 674.918);
+ poly377.ps[2] = Point(69.2456, 674.918);
+ poly377.ps[3] = Point(69.2456, 634.918);
+ ShapeRef *shapeRef377 = new ShapeRef(router, poly377, 377);
+ router->addShape(shapeRef377);
+
+ Polygon poly378(4);
+ poly378.ps[0] = Point(283.246, 634.918);
+ poly378.ps[1] = Point(283.246, 674.918);
+ poly378.ps[2] = Point(227.246, 674.918);
+ poly378.ps[3] = Point(227.246, 634.918);
+ ShapeRef *shapeRef378 = new ShapeRef(router, poly378, 378);
+ router->addShape(shapeRef378);
+
+ Polygon poly379(4);
+ poly379.ps[0] = Point(439.246, 634.918);
+ poly379.ps[1] = Point(439.246, 674.918);
+ poly379.ps[2] = Point(383.246, 674.918);
+ poly379.ps[3] = Point(383.246, 634.918);
+ ShapeRef *shapeRef379 = new ShapeRef(router, poly379, 379);
+ router->addShape(shapeRef379);
+
+ Polygon poly52(4);
+ poly52.ps[0] = Point(1015.25, 278.918);
+ poly52.ps[1] = Point(1015.25, 298.918);
+ poly52.ps[2] = Point(995.246, 298.918);
+ poly52.ps[3] = Point(995.246, 278.918);
+ ShapeRef *shapeRef52 = new ShapeRef(router, poly52, 52);
+ router->addShape(shapeRef52);
+
+ Polygon poly19(4);
+ poly19.ps[0] = Point(547.246, 730.918);
+ poly19.ps[1] = Point(547.246, 770.918);
+ poly19.ps[2] = Point(507.246, 770.918);
+ poly19.ps[3] = Point(507.246, 730.918);
+ ShapeRef *shapeRef19 = new ShapeRef(router, poly19, 19);
+ router->addShape(shapeRef19);
+
+ Polygon poly89(4);
+ poly89.ps[0] = Point(655.246, 504.918);
+ poly89.ps[1] = Point(655.246, 524.918);
+ poly89.ps[2] = Point(635.246, 524.918);
+ poly89.ps[3] = Point(635.246, 504.918);
+ ShapeRef *shapeRef89 = new ShapeRef(router, poly89, 89);
+ router->addShape(shapeRef89);
+
+ Polygon poly194(4);
+ poly194.ps[0] = Point(203.246, 440.918);
+ poly194.ps[1] = Point(203.246, 460.918);
+ poly194.ps[2] = Point(183.246, 460.918);
+ poly194.ps[3] = Point(183.246, 440.918);
+ ShapeRef *shapeRef194 = new ShapeRef(router, poly194, 194);
+ router->addShape(shapeRef194);
+
+ Polygon poly195(4);
+ poly195.ps[0] = Point(343.246, 440.918);
+ poly195.ps[1] = Point(343.246, 460.918);
+ poly195.ps[2] = Point(323.246, 460.918);
+ poly195.ps[3] = Point(323.246, 440.918);
+ ShapeRef *shapeRef195 = new ShapeRef(router, poly195, 195);
+ router->addShape(shapeRef195);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(391.246, 612.918);
+ poly5.ps[1] = Point(391.246, 632.918);
+ poly5.ps[2] = Point(371.246, 632.918);
+ poly5.ps[3] = Point(371.246, 612.918);
+ ShapeRef *shapeRef5 = new ShapeRef(router, poly5, 5);
+ router->addShape(shapeRef5);
+
+ Polygon poly27(4);
+ poly27.ps[0] = Point(1303.25, 565.942);
+ poly27.ps[1] = Point(1303.25, 585.942);
+ poly27.ps[2] = Point(1283.25, 585.942);
+ poly27.ps[3] = Point(1283.25, 565.942);
+ ShapeRef *shapeRef27 = new ShapeRef(router, poly27, 27);
+ router->addShape(shapeRef27);
+
+ Polygon poly147(4);
+ poly147.ps[0] = Point(329.219, -39.0821);
+ poly147.ps[1] = Point(329.219, -19.0821);
+ poly147.ps[2] = Point(309.219, -19.0821);
+ poly147.ps[3] = Point(309.219, -39.0821);
+ ShapeRef *shapeRef147 = new ShapeRef(router, poly147, 147);
+ router->addShape(shapeRef147);
+
+ Polygon poly130(4);
+ poly130.ps[0] = Point(203.246, 268.918);
+ poly130.ps[1] = Point(203.246, 288.918);
+ poly130.ps[2] = Point(183.246, 288.918);
+ poly130.ps[3] = Point(183.246, 268.918);
+ ShapeRef *shapeRef130 = new ShapeRef(router, poly130, 130);
+ router->addShape(shapeRef130);
+
+ Polygon poly216(4);
+ poly216.ps[0] = Point(1243.25, 504.918);
+ poly216.ps[1] = Point(1243.25, 524.918);
+ poly216.ps[2] = Point(1223.25, 524.918);
+ poly216.ps[3] = Point(1223.25, 504.918);
+ ShapeRef *shapeRef216 = new ShapeRef(router, poly216, 216);
+ router->addShape(shapeRef216);
+
+ Polygon poly217(4);
+ poly217.ps[0] = Point(1243.25, 612.918);
+ poly217.ps[1] = Point(1243.25, 632.918);
+ poly217.ps[2] = Point(1223.25, 632.918);
+ poly217.ps[3] = Point(1223.25, 612.918);
+ ShapeRef *shapeRef217 = new ShapeRef(router, poly217, 217);
+ router->addShape(shapeRef217);
+
+ Polygon poly218(4);
+ poly218.ps[0] = Point(967.246, 708.918);
+ poly218.ps[1] = Point(967.246, 728.918);
+ poly218.ps[2] = Point(947.246, 728.918);
+ poly218.ps[3] = Point(947.246, 708.918);
+ ShapeRef *shapeRef218 = new ShapeRef(router, poly218, 218);
+ router->addShape(shapeRef218);
+
+ Polygon poly219(4);
+ poly219.ps[0] = Point(967.246, 740.918);
+ poly219.ps[1] = Point(967.246, 760.918);
+ poly219.ps[2] = Point(947.246, 760.918);
+ poly219.ps[3] = Point(947.246, 740.918);
+ ShapeRef *shapeRef219 = new ShapeRef(router, poly219, 219);
+ router->addShape(shapeRef219);
+
+ Polygon poly41(4);
+ poly41.ps[0] = Point(235.246, 526.918);
+ poly41.ps[1] = Point(235.246, 546.918);
+ poly41.ps[2] = Point(215.246, 546.918);
+ poly41.ps[3] = Point(215.246, 526.918);
+ ShapeRef *shapeRef41 = new ShapeRef(router, poly41, 41);
+ router->addShape(shapeRef41);
+
+ Polygon poly109(4);
+ poly109.ps[0] = Point(391.246, 580.918);
+ poly109.ps[1] = Point(391.246, 600.918);
+ poly109.ps[2] = Point(371.246, 600.918);
+ poly109.ps[3] = Point(371.246, 580.918);
+ ShapeRef *shapeRef109 = new ShapeRef(router, poly109, 109);
+ router->addShape(shapeRef109);
+
+ Polygon poly213(4);
+ poly213.ps[0] = Point(967.246, 644.918);
+ poly213.ps[1] = Point(967.246, 664.918);
+ poly213.ps[2] = Point(947.246, 664.918);
+ poly213.ps[3] = Point(947.246, 644.918);
+ ShapeRef *shapeRef213 = new ShapeRef(router, poly213, 213);
+ router->addShape(shapeRef213);
+
+ Polygon poly214(4);
+ poly214.ps[0] = Point(1243.25, 268.918);
+ poly214.ps[1] = Point(1243.25, 288.918);
+ poly214.ps[2] = Point(1223.25, 288.918);
+ poly214.ps[3] = Point(1223.25, 268.918);
+ ShapeRef *shapeRef214 = new ShapeRef(router, poly214, 214);
+ router->addShape(shapeRef214);
+
+ Polygon poly215(4);
+ poly215.ps[0] = Point(1243.25, 408.918);
+ poly215.ps[1] = Point(1243.25, 428.918);
+ poly215.ps[2] = Point(1223.25, 428.918);
+ poly215.ps[3] = Point(1223.25, 408.918);
+ ShapeRef *shapeRef215 = new ShapeRef(router, poly215, 215);
+ router->addShape(shapeRef215);
+
+ Polygon poly196(4);
+ poly196.ps[0] = Point(499.246, 440.918);
+ poly196.ps[1] = Point(499.246, 460.918);
+ poly196.ps[2] = Point(479.246, 460.918);
+ poly196.ps[3] = Point(479.246, 440.918);
+ ShapeRef *shapeRef196 = new ShapeRef(router, poly196, 196);
+ router->addShape(shapeRef196);
+
+ Polygon poly197(4);
+ poly197.ps[0] = Point(811.246, 440.918);
+ poly197.ps[1] = Point(811.246, 460.918);
+ poly197.ps[2] = Point(791.246, 460.918);
+ poly197.ps[3] = Point(791.246, 440.918);
+ ShapeRef *shapeRef197 = new ShapeRef(router, poly197, 197);
+ router->addShape(shapeRef197);
+
+ Polygon poly198(4);
+ poly198.ps[0] = Point(967.246, 440.918);
+ poly198.ps[1] = Point(967.246, 460.918);
+ poly198.ps[2] = Point(947.246, 460.918);
+ poly198.ps[3] = Point(947.246, 440.918);
+ ShapeRef *shapeRef198 = new ShapeRef(router, poly198, 198);
+ router->addShape(shapeRef198);
+
+ Polygon poly181(4);
+ poly181.ps[0] = Point(999.246, 730.918);
+ poly181.ps[1] = Point(999.246, 770.918);
+ poly181.ps[2] = Point(959.246, 770.918);
+ poly181.ps[3] = Point(959.246, 730.918);
+ ShapeRef *shapeRef181 = new ShapeRef(router, poly181, 181);
+ router->addShape(shapeRef181);
+
+ Polygon poly182(4);
+ poly182.ps[0] = Point(999.246, 656.918);
+ poly182.ps[1] = Point(999.246, 696.918);
+ poly182.ps[2] = Point(959.246, 696.918);
+ poly182.ps[3] = Point(959.246, 656.918);
+ ShapeRef *shapeRef182 = new ShapeRef(router, poly182, 182);
+ router->addShape(shapeRef182);
+
+ Polygon poly223(4);
+ poly223.ps[0] = Point(77.2456, 236.918);
+ poly223.ps[1] = Point(77.2456, 256.918);
+ poly223.ps[2] = Point(57.2456, 256.918);
+ poly223.ps[3] = Point(57.2456, 236.918);
+ ShapeRef *shapeRef223 = new ShapeRef(router, poly223, 223);
+ router->addShape(shapeRef223);
+
+ Polygon poly224(4);
+ poly224.ps[0] = Point(77.2456, 268.918);
+ poly224.ps[1] = Point(77.2456, 288.918);
+ poly224.ps[2] = Point(57.2456, 288.918);
+ poly224.ps[3] = Point(57.2456, 268.918);
+ ShapeRef *shapeRef224 = new ShapeRef(router, poly224, 224);
+ router->addShape(shapeRef224);
+
+ Polygon poly225(4);
+ poly225.ps[0] = Point(1159.25, 602.918);
+ poly225.ps[1] = Point(1159.25, 642.918);
+ poly225.ps[2] = Point(1103.25, 642.918);
+ poly225.ps[3] = Point(1103.25, 602.918);
+ ShapeRef *shapeRef225 = new ShapeRef(router, poly225, 225);
+ router->addShape(shapeRef225);
+
+ Polygon poly226(4);
+ poly226.ps[0] = Point(955.246, 602.918);
+ poly226.ps[1] = Point(955.246, 642.918);
+ poly226.ps[2] = Point(899.246, 642.918);
+ poly226.ps[3] = Point(899.246, 602.918);
+ ShapeRef *shapeRef226 = new ShapeRef(router, poly226, 226);
+ router->addShape(shapeRef226);
+
+ Polygon poly326(4);
+ poly326.ps[0] = Point(361.246, 108.918);
+ poly326.ps[1] = Point(361.246, 148.918);
+ poly326.ps[2] = Point(305.246, 148.918);
+ poly326.ps[3] = Point(305.246, 108.918);
+ ShapeRef *shapeRef326 = new ShapeRef(router, poly326, 326);
+ router->addShape(shapeRef326);
+
+ Polygon poly327(4);
+ poly327.ps[0] = Point(331.246, 570.918);
+ poly327.ps[1] = Point(331.246, 610.918);
+ poly327.ps[2] = Point(275.246, 610.918);
+ poly327.ps[3] = Point(275.246, 570.918);
+ ShapeRef *shapeRef327 = new ShapeRef(router, poly327, 327);
+ router->addShape(shapeRef327);
+
+ Polygon poly328(4);
+ poly328.ps[0] = Point(283.246, 602.918);
+ poly328.ps[1] = Point(283.246, 642.918);
+ poly328.ps[2] = Point(227.246, 642.918);
+ poly328.ps[3] = Point(227.246, 602.918);
+ ShapeRef *shapeRef328 = new ShapeRef(router, poly328, 328);
+ router->addShape(shapeRef328);
+
+ Polygon poly329(4);
+ poly329.ps[0] = Point(283.246, 570.918);
+ poly329.ps[1] = Point(283.246, 610.918);
+ poly329.ps[2] = Point(227.246, 610.918);
+ poly329.ps[3] = Point(227.246, 570.918);
+ ShapeRef *shapeRef329 = new ShapeRef(router, poly329, 329);
+ router->addShape(shapeRef329);
+
+ Polygon poly330(4);
+ poly330.ps[0] = Point(283.246, 494.918);
+ poly330.ps[1] = Point(283.246, 534.918);
+ poly330.ps[2] = Point(227.246, 534.918);
+ poly330.ps[3] = Point(227.246, 494.918);
+ ShapeRef *shapeRef330 = new ShapeRef(router, poly330, 330);
+ router->addShape(shapeRef330);
+
+ Polygon poly331(4);
+ poly331.ps[0] = Point(283.246, 462.918);
+ poly331.ps[1] = Point(283.246, 502.918);
+ poly331.ps[2] = Point(227.246, 502.918);
+ poly331.ps[3] = Point(227.246, 462.918);
+ ShapeRef *shapeRef331 = new ShapeRef(router, poly331, 331);
+ router->addShape(shapeRef331);
+
+ Polygon poly332(4);
+ poly332.ps[0] = Point(331.246, 398.918);
+ poly332.ps[1] = Point(331.246, 438.918);
+ poly332.ps[2] = Point(275.246, 438.918);
+ poly332.ps[3] = Point(275.246, 398.918);
+ ShapeRef *shapeRef332 = new ShapeRef(router, poly332, 332);
+ router->addShape(shapeRef332);
+
+ Polygon poly333(4);
+ poly333.ps[0] = Point(283.246, 398.918);
+ poly333.ps[1] = Point(283.246, 438.918);
+ poly333.ps[2] = Point(227.246, 438.918);
+ poly333.ps[3] = Point(227.246, 398.918);
+ ShapeRef *shapeRef333 = new ShapeRef(router, poly333, 333);
+ router->addShape(shapeRef333);
+
+ Polygon poly334(4);
+ poly334.ps[0] = Point(283.246, 366.918);
+ poly334.ps[1] = Point(283.246, 406.918);
+ poly334.ps[2] = Point(227.246, 406.918);
+ poly334.ps[3] = Point(227.246, 366.918);
+ ShapeRef *shapeRef334 = new ShapeRef(router, poly334, 334);
+ router->addShape(shapeRef334);
+
+ Polygon poly335(4);
+ poly335.ps[0] = Point(331.246, 236.918);
+ poly335.ps[1] = Point(331.246, 276.918);
+ poly335.ps[2] = Point(275.246, 276.918);
+ poly335.ps[3] = Point(275.246, 236.918);
+ ShapeRef *shapeRef335 = new ShapeRef(router, poly335, 335);
+ router->addShape(shapeRef335);
+
+ Polygon poly336(4);
+ poly336.ps[0] = Point(221.246, 108.918);
+ poly336.ps[1] = Point(221.246, 148.918);
+ poly336.ps[2] = Point(165.246, 148.918);
+ poly336.ps[3] = Point(165.246, 108.918);
+ ShapeRef *shapeRef336 = new ShapeRef(router, poly336, 336);
+ router->addShape(shapeRef336);
+
+ Polygon poly337(4);
+ poly337.ps[0] = Point(221.246, 172.918);
+ poly337.ps[1] = Point(221.246, 212.918);
+ poly337.ps[2] = Point(165.246, 212.918);
+ poly337.ps[3] = Point(165.246, 172.918);
+ ShapeRef *shapeRef337 = new ShapeRef(router, poly337, 337);
+ router->addShape(shapeRef337);
+
+ Polygon poly338(4);
+ poly338.ps[0] = Point(173.246, 570.918);
+ poly338.ps[1] = Point(173.246, 610.918);
+ poly338.ps[2] = Point(117.246, 610.918);
+ poly338.ps[3] = Point(117.246, 570.918);
+ ShapeRef *shapeRef338 = new ShapeRef(router, poly338, 338);
+ router->addShape(shapeRef338);
+
+ Polygon poly339(4);
+ poly339.ps[0] = Point(125.246, 602.918);
+ poly339.ps[1] = Point(125.246, 642.918);
+ poly339.ps[2] = Point(69.2456, 642.918);
+ poly339.ps[3] = Point(69.2456, 602.918);
+ ShapeRef *shapeRef339 = new ShapeRef(router, poly339, 339);
+ router->addShape(shapeRef339);
+
+ Polygon poly340(4);
+ poly340.ps[0] = Point(125.246, 570.918);
+ poly340.ps[1] = Point(125.246, 610.918);
+ poly340.ps[2] = Point(69.2456, 610.918);
+ poly340.ps[3] = Point(69.2456, 570.918);
+ ShapeRef *shapeRef340 = new ShapeRef(router, poly340, 340);
+ router->addShape(shapeRef340);
+
+ Polygon poly341(4);
+ poly341.ps[0] = Point(125.246, 494.918);
+ poly341.ps[1] = Point(125.246, 534.918);
+ poly341.ps[2] = Point(69.2456, 534.918);
+ poly341.ps[3] = Point(69.2456, 494.918);
+ ShapeRef *shapeRef341 = new ShapeRef(router, poly341, 341);
+ router->addShape(shapeRef341);
+
+ Polygon poly47(4);
+ poly47.ps[0] = Point(1459.25, 708.918);
+ poly47.ps[1] = Point(1459.25, 728.918);
+ poly47.ps[2] = Point(1439.25, 728.918);
+ poly47.ps[3] = Point(1439.25, 708.918);
+ ShapeRef *shapeRef47 = new ShapeRef(router, poly47, 47);
+ router->addShape(shapeRef47);
+
+ Polygon poly342(4);
+ poly342.ps[0] = Point(125.246, 462.918);
+ poly342.ps[1] = Point(125.246, 502.918);
+ poly342.ps[2] = Point(69.2456, 502.918);
+ poly342.ps[3] = Point(69.2456, 462.918);
+ ShapeRef *shapeRef342 = new ShapeRef(router, poly342, 342);
+ router->addShape(shapeRef342);
+
+ Polygon poly343(4);
+ poly343.ps[0] = Point(173.246, 398.918);
+ poly343.ps[1] = Point(173.246, 438.918);
+ poly343.ps[2] = Point(117.246, 438.918);
+ poly343.ps[3] = Point(117.246, 398.918);
+ ShapeRef *shapeRef343 = new ShapeRef(router, poly343, 343);
+ router->addShape(shapeRef343);
+
+ Polygon poly344(4);
+ poly344.ps[0] = Point(125.246, 398.918);
+ poly344.ps[1] = Point(125.246, 438.918);
+ poly344.ps[2] = Point(69.2456, 438.918);
+ poly344.ps[3] = Point(69.2456, 398.918);
+ ShapeRef *shapeRef344 = new ShapeRef(router, poly344, 344);
+ router->addShape(shapeRef344);
+
+ Polygon poly345(4);
+ poly345.ps[0] = Point(125.246, 366.918);
+ poly345.ps[1] = Point(125.246, 406.918);
+ poly345.ps[2] = Point(69.2456, 406.918);
+ poly345.ps[3] = Point(69.2456, 366.918);
+ ShapeRef *shapeRef345 = new ShapeRef(router, poly345, 345);
+ router->addShape(shapeRef345);
+
+ Polygon poly346(4);
+ poly346.ps[0] = Point(45.2456, 172.918);
+ poly346.ps[1] = Point(45.2456, 212.918);
+ poly346.ps[2] = Point(-10.7544, 212.918);
+ poly346.ps[3] = Point(-10.7544, 172.918);
+ ShapeRef *shapeRef346 = new ShapeRef(router, poly346, 346);
+ router->addShape(shapeRef346);
+
+ Polygon poly347(4);
+ poly347.ps[0] = Point(45.2456, 108.918);
+ poly347.ps[1] = Point(45.2456, 148.918);
+ poly347.ps[2] = Point(-10.7544, 148.918);
+ poly347.ps[3] = Point(-10.7544, 108.918);
+ ShapeRef *shapeRef347 = new ShapeRef(router, poly347, 347);
+ router->addShape(shapeRef347);
+
+ Polygon poly348(4);
+ poly348.ps[0] = Point(313.246, 150.918);
+ poly348.ps[1] = Point(313.246, 190.918);
+ poly348.ps[2] = Point(257.246, 190.918);
+ poly348.ps[3] = Point(257.246, 150.918);
+ ShapeRef *shapeRef348 = new ShapeRef(router, poly348, 348);
+ router->addShape(shapeRef348);
+
+ Polygon poly349(4);
+ poly349.ps[0] = Point(265.246, 66.9179);
+ poly349.ps[1] = Point(265.246, 106.918);
+ poly349.ps[2] = Point(209.246, 106.918);
+ poly349.ps[3] = Point(209.246, 66.9179);
+ ShapeRef *shapeRef349 = new ShapeRef(router, poly349, 349);
+ router->addShape(shapeRef349);
+
+ Polygon poly350(4);
+ poly350.ps[0] = Point(265.246, 34.9179);
+ poly350.ps[1] = Point(265.246, 74.9179);
+ poly350.ps[2] = Point(209.246, 74.9179);
+ poly350.ps[3] = Point(209.246, 34.9179);
+ ShapeRef *shapeRef350 = new ShapeRef(router, poly350, 350);
+ router->addShape(shapeRef350);
+
+ Polygon poly351(4);
+ poly351.ps[0] = Point(125.246, 150.918);
+ poly351.ps[1] = Point(125.246, 190.918);
+ poly351.ps[2] = Point(69.2456, 190.918);
+ poly351.ps[3] = Point(69.2456, 150.918);
+ ShapeRef *shapeRef351 = new ShapeRef(router, poly351, 351);
+ router->addShape(shapeRef351);
+
+ Polygon poly352(4);
+ poly352.ps[0] = Point(125.246, 12.9179);
+ poly352.ps[1] = Point(125.246, 52.9179);
+ poly352.ps[2] = Point(69.2456, 52.9179);
+ poly352.ps[3] = Point(69.2456, 12.9179);
+ ShapeRef *shapeRef352 = new ShapeRef(router, poly352, 352);
+ router->addShape(shapeRef352);
+
+ Polygon poly353(4);
+ poly353.ps[0] = Point(125.246, -19.0821);
+ poly353.ps[1] = Point(125.246, 20.9179);
+ poly353.ps[2] = Point(69.2456, 20.9179);
+ poly353.ps[3] = Point(69.2456, -19.0821);
+ ShapeRef *shapeRef353 = new ShapeRef(router, poly353, 353);
+ router->addShape(shapeRef353);
+
+ Polygon poly354(4);
+ poly354.ps[0] = Point(408.962, -49.0821);
+ poly354.ps[1] = Point(408.962, -9.08205);
+ poly354.ps[2] = Point(352.962, -9.08205);
+ poly354.ps[3] = Point(352.962, -49.0821);
+ ShapeRef *shapeRef354 = new ShapeRef(router, poly354, 354);
+ router->addShape(shapeRef354);
+
+ Polygon poly355(4);
+ poly355.ps[0] = Point(307.219, -49.0821);
+ poly355.ps[1] = Point(307.219, -9.08205);
+ poly355.ps[2] = Point(251.219, -9.08205);
+ poly355.ps[3] = Point(251.219, -49.0821);
+ ShapeRef *shapeRef355 = new ShapeRef(router, poly355, 355);
+ router->addShape(shapeRef355);
+
+ Polygon poly356(4);
+ poly356.ps[0] = Point(125.246, 290.918);
+ poly356.ps[1] = Point(125.246, 330.918);
+ poly356.ps[2] = Point(69.2456, 330.918);
+ poly356.ps[3] = Point(69.2456, 290.918);
+ ShapeRef *shapeRef356 = new ShapeRef(router, poly356, 356);
+ router->addShape(shapeRef356);
+
+ Polygon poly357(4);
+ poly357.ps[0] = Point(221.246, 204.918);
+ poly357.ps[1] = Point(221.246, 244.918);
+ poly357.ps[2] = Point(165.246, 244.918);
+ poly357.ps[3] = Point(165.246, 204.918);
+ ShapeRef *shapeRef357 = new ShapeRef(router, poly357, 357);
+ router->addShape(shapeRef357);
+
+ Polygon poly260(4);
+ poly260.ps[0] = Point(955.246, 698.918);
+ poly260.ps[1] = Point(955.246, 738.918);
+ poly260.ps[2] = Point(899.246, 738.918);
+ poly260.ps[3] = Point(899.246, 698.918);
+ ShapeRef *shapeRef260 = new ShapeRef(router, poly260, 260);
+ router->addShape(shapeRef260);
+
+ Polygon poly261(4);
+ poly261.ps[0] = Point(173.246, 12.9179);
+ poly261.ps[1] = Point(173.246, 52.9179);
+ poly261.ps[2] = Point(117.246, 52.9179);
+ poly261.ps[3] = Point(117.246, 12.9179);
+ ShapeRef *shapeRef261 = new ShapeRef(router, poly261, 261);
+ router->addShape(shapeRef261);
+
+ Polygon poly262(4);
+ poly262.ps[0] = Point(173.246, 290.918);
+ poly262.ps[1] = Point(173.246, 330.918);
+ poly262.ps[2] = Point(117.246, 330.918);
+ poly262.ps[3] = Point(117.246, 290.918);
+ ShapeRef *shapeRef262 = new ShapeRef(router, poly262, 262);
+ router->addShape(shapeRef262);
+
+ Polygon poly263(4);
+ poly263.ps[0] = Point(1033.25, 214.918);
+ poly263.ps[1] = Point(1033.25, 254.918);
+ poly263.ps[2] = Point(977.246, 254.918);
+ poly263.ps[3] = Point(977.246, 214.918);
+ ShapeRef *shapeRef263 = new ShapeRef(router, poly263, 263);
+ router->addShape(shapeRef263);
+
+ Polygon poly264(4);
+ poly264.ps[0] = Point(877.246, 214.918);
+ poly264.ps[1] = Point(877.246, 254.918);
+ poly264.ps[2] = Point(821.246, 254.918);
+ poly264.ps[3] = Point(821.246, 214.918);
+ ShapeRef *shapeRef264 = new ShapeRef(router, poly264, 264);
+ router->addShape(shapeRef264);
+
+ Polygon poly265(4);
+ poly265.ps[0] = Point(721.246, 214.918);
+ poly265.ps[1] = Point(721.246, 254.918);
+ poly265.ps[2] = Point(665.246, 254.918);
+ poly265.ps[3] = Point(665.246, 214.918);
+ ShapeRef *shapeRef265 = new ShapeRef(router, poly265, 265);
+ router->addShape(shapeRef265);
+
+ Polygon poly266(4);
+ poly266.ps[0] = Point(565.246, 214.918);
+ poly266.ps[1] = Point(565.246, 254.918);
+ poly266.ps[2] = Point(509.246, 254.918);
+ poly266.ps[3] = Point(509.246, 214.918);
+ ShapeRef *shapeRef266 = new ShapeRef(router, poly266, 266);
+ router->addShape(shapeRef266);
+
+ Polygon poly179(4);
+ poly179.ps[0] = Point(843.246, 538.918);
+ poly179.ps[1] = Point(843.246, 578.918);
+ poly179.ps[2] = Point(803.246, 578.918);
+ poly179.ps[3] = Point(803.246, 538.918);
+ ShapeRef *shapeRef179 = new ShapeRef(router, poly179, 179);
+ router->addShape(shapeRef179);
+
+ Polygon poly180(4);
+ poly180.ps[0] = Point(843.246, 656.918);
+ poly180.ps[1] = Point(843.246, 696.918);
+ poly180.ps[2] = Point(803.246, 696.918);
+ poly180.ps[3] = Point(803.246, 656.918);
+ ShapeRef *shapeRef180 = new ShapeRef(router, poly180, 180);
+ router->addShape(shapeRef180);
+
+ Polygon poly274(4);
+ poly274.ps[0] = Point(1063.25, 494.918);
+ poly274.ps[1] = Point(1063.25, 534.918);
+ poly274.ps[2] = Point(1007.25, 534.918);
+ poly274.ps[3] = Point(1007.25, 494.918);
+ ShapeRef *shapeRef274 = new ShapeRef(router, poly274, 274);
+ router->addShape(shapeRef274);
+
+ Polygon poly275(4);
+ poly275.ps[0] = Point(1063.25, 462.918);
+ poly275.ps[1] = Point(1063.25, 502.918);
+ poly275.ps[2] = Point(1007.25, 502.918);
+ poly275.ps[3] = Point(1007.25, 462.918);
+ ShapeRef *shapeRef275 = new ShapeRef(router, poly275, 275);
+ router->addShape(shapeRef275);
+
+ Polygon poly276(4);
+ poly276.ps[0] = Point(1159.25, 398.918);
+ poly276.ps[1] = Point(1159.25, 438.918);
+ poly276.ps[2] = Point(1103.25, 438.918);
+ poly276.ps[3] = Point(1103.25, 398.918);
+ ShapeRef *shapeRef276 = new ShapeRef(router, poly276, 276);
+ router->addShape(shapeRef276);
+
+ Polygon poly277(4);
+ poly277.ps[0] = Point(1063.25, 398.918);
+ poly277.ps[1] = Point(1063.25, 438.918);
+ poly277.ps[2] = Point(1007.25, 438.918);
+ poly277.ps[3] = Point(1007.25, 398.918);
+ ShapeRef *shapeRef277 = new ShapeRef(router, poly277, 277);
+ router->addShape(shapeRef277);
+
+ Polygon poly278(4);
+ poly278.ps[0] = Point(1063.25, 366.918);
+ poly278.ps[1] = Point(1063.25, 406.918);
+ poly278.ps[2] = Point(1007.25, 406.918);
+ poly278.ps[3] = Point(1007.25, 366.918);
+ ShapeRef *shapeRef278 = new ShapeRef(router, poly278, 278);
+ router->addShape(shapeRef278);
+
+ Polygon poly279(4);
+ poly279.ps[0] = Point(1033.25, 182.918);
+ poly279.ps[1] = Point(1033.25, 222.918);
+ poly279.ps[2] = Point(977.246, 222.918);
+ poly279.ps[3] = Point(977.246, 182.918);
+ ShapeRef *shapeRef279 = new ShapeRef(router, poly279, 279);
+ router->addShape(shapeRef279);
+
+ Polygon poly280(4);
+ poly280.ps[0] = Point(985.246, 172.918);
+ poly280.ps[1] = Point(985.246, 212.918);
+ poly280.ps[2] = Point(929.246, 212.918);
+ poly280.ps[3] = Point(929.246, 172.918);
+ ShapeRef *shapeRef280 = new ShapeRef(router, poly280, 280);
+ router->addShape(shapeRef280);
+
+ Polygon poly281(4);
+ poly281.ps[0] = Point(985.246, 108.918);
+ poly281.ps[1] = Point(985.246, 148.918);
+ poly281.ps[2] = Point(929.246, 148.918);
+ poly281.ps[3] = Point(929.246, 108.918);
+ ShapeRef *shapeRef281 = new ShapeRef(router, poly281, 281);
+ router->addShape(shapeRef281);
+
+ Polygon poly65(4);
+ poly65.ps[0] = Point(967.246, 612.918);
+ poly65.ps[1] = Point(967.246, 632.918);
+ poly65.ps[2] = Point(947.246, 632.918);
+ poly65.ps[3] = Point(947.246, 612.918);
+ ShapeRef *shapeRef65 = new ShapeRef(router, poly65, 65);
+ router->addShape(shapeRef65);
+
+ Polygon poly53(4);
+ poly53.ps[0] = Point(859.246, 278.918);
+ poly53.ps[1] = Point(859.246, 298.918);
+ poly53.ps[2] = Point(839.246, 298.918);
+ poly53.ps[3] = Point(839.246, 278.918);
+ ShapeRef *shapeRef53 = new ShapeRef(router, poly53, 53);
+ router->addShape(shapeRef53);
+
+ Polygon poly66(4);
+ poly66.ps[0] = Point(967.246, 580.918);
+ poly66.ps[1] = Point(967.246, 600.918);
+ poly66.ps[2] = Point(947.246, 600.918);
+ poly66.ps[3] = Point(947.246, 580.918);
+ ShapeRef *shapeRef66 = new ShapeRef(router, poly66, 66);
+ router->addShape(shapeRef66);
+
+ Polygon poly54(4);
+ poly54.ps[0] = Point(703.246, 278.918);
+ poly54.ps[1] = Point(703.246, 298.918);
+ poly54.ps[2] = Point(683.246, 298.918);
+ poly54.ps[3] = Point(683.246, 278.918);
+ ShapeRef *shapeRef54 = new ShapeRef(router, poly54, 54);
+ router->addShape(shapeRef54);
+
+ Polygon poly171(4);
+ poly171.ps[0] = Point(547.246, 538.918);
+ poly171.ps[1] = Point(547.246, 578.918);
+ poly171.ps[2] = Point(507.246, 578.918);
+ poly171.ps[3] = Point(507.246, 538.918);
+ ShapeRef *shapeRef171 = new ShapeRef(router, poly171, 171);
+ router->addShape(shapeRef171);
+
+ Polygon poly172(4);
+ poly172.ps[0] = Point(547.246, 656.918);
+ poly172.ps[1] = Point(547.246, 696.918);
+ poly172.ps[2] = Point(507.246, 696.918);
+ poly172.ps[3] = Point(507.246, 656.918);
+ ShapeRef *shapeRef172 = new ShapeRef(router, poly172, 172);
+ router->addShape(shapeRef172);
+
+ Polygon poly78(4);
+ poly78.ps[0] = Point(811.246, 504.918);
+ poly78.ps[1] = Point(811.246, 524.918);
+ poly78.ps[2] = Point(791.246, 524.918);
+ poly78.ps[3] = Point(791.246, 504.918);
+ ShapeRef *shapeRef78 = new ShapeRef(router, poly78, 78);
+ router->addShape(shapeRef78);
+
+ Polygon poly95(4);
+ poly95.ps[0] = Point(655.246, 268.918);
+ poly95.ps[1] = Point(655.246, 288.918);
+ poly95.ps[2] = Point(635.246, 288.918);
+ poly95.ps[3] = Point(635.246, 268.918);
+ ShapeRef *shapeRef95 = new ShapeRef(router, poly95, 95);
+ router->addShape(shapeRef95);
+
+ Polygon poly156(4);
+ poly156.ps[0] = Point(77.2456, 312.918);
+ poly156.ps[1] = Point(77.2456, 352.918);
+ poly156.ps[2] = Point(37.2456, 352.918);
+ poly156.ps[3] = Point(37.2456, 312.918);
+ ShapeRef *shapeRef156 = new ShapeRef(router, poly156, 156);
+ router->addShape(shapeRef156);
+
+ Polygon poly187(4);
+ poly187.ps[0] = Point(203.246, 300.918);
+ poly187.ps[1] = Point(203.246, 320.918);
+ poly187.ps[2] = Point(183.246, 320.918);
+ poly187.ps[3] = Point(183.246, 300.918);
+ ShapeRef *shapeRef187 = new ShapeRef(router, poly187, 187);
+ router->addShape(shapeRef187);
+
+ Polygon poly188(4);
+ poly188.ps[0] = Point(343.246, 300.918);
+ poly188.ps[1] = Point(343.246, 320.918);
+ poly188.ps[2] = Point(323.246, 320.918);
+ poly188.ps[3] = Point(323.246, 300.918);
+ ShapeRef *shapeRef188 = new ShapeRef(router, poly188, 188);
+ router->addShape(shapeRef188);
+
+ Polygon poly100(4);
+ poly100.ps[0] = Point(547.246, 476.951);
+ poly100.ps[1] = Point(547.246, 496.951);
+ poly100.ps[2] = Point(527.246, 496.951);
+ poly100.ps[3] = Point(527.246, 476.951);
+ ShapeRef *shapeRef100 = new ShapeRef(router, poly100, 100);
+ router->addShape(shapeRef100);
+
+ Polygon poly56(4);
+ poly56.ps[0] = Point(391.246, 278.918);
+ poly56.ps[1] = Point(391.246, 298.918);
+ poly56.ps[2] = Point(371.246, 298.918);
+ poly56.ps[3] = Point(371.246, 278.918);
+ ShapeRef *shapeRef56 = new ShapeRef(router, poly56, 56);
+ router->addShape(shapeRef56);
+
+ Polygon poly220(4);
+ poly220.ps[0] = Point(1243.25, 708.918);
+ poly220.ps[1] = Point(1243.25, 728.918);
+ poly220.ps[2] = Point(1223.25, 728.918);
+ poly220.ps[3] = Point(1223.25, 708.918);
+ ShapeRef *shapeRef220 = new ShapeRef(router, poly220, 220);
+ router->addShape(shapeRef220);
+
+ Polygon poly221(4);
+ poly221.ps[0] = Point(1303.25, 246.918);
+ poly221.ps[1] = Point(1303.25, 266.918);
+ poly221.ps[2] = Point(1283.25, 266.918);
+ poly221.ps[3] = Point(1283.25, 246.918);
+ ShapeRef *shapeRef221 = new ShapeRef(router, poly221, 221);
+ router->addShape(shapeRef221);
+
+ Polygon poly222(4);
+ poly222.ps[0] = Point(1303.25, 634.918);
+ poly222.ps[1] = Point(1303.25, 654.918);
+ poly222.ps[2] = Point(1283.25, 654.918);
+ poly222.ps[3] = Point(1283.25, 634.918);
+ ShapeRef *shapeRef222 = new ShapeRef(router, poly222, 222);
+ router->addShape(shapeRef222);
+
+ Polygon poly83(4);
+ poly83.ps[0] = Point(859.246, 246.918);
+ poly83.ps[1] = Point(859.246, 266.918);
+ poly83.ps[2] = Point(839.246, 266.918);
+ poly83.ps[3] = Point(839.246, 246.918);
+ ShapeRef *shapeRef83 = new ShapeRef(router, poly83, 83);
+ router->addShape(shapeRef83);
+
+ Polygon poly136(4);
+ poly136.ps[0] = Point(77.2456, 408.918);
+ poly136.ps[1] = Point(77.2456, 428.918);
+ poly136.ps[2] = Point(57.2456, 428.918);
+ poly136.ps[3] = Point(57.2456, 408.918);
+ ShapeRef *shapeRef136 = new ShapeRef(router, poly136, 136);
+ router->addShape(shapeRef136);
+
+ Polygon poly60(4);
+ poly60.ps[0] = Point(590.455, 4.91795);
+ poly60.ps[1] = Point(590.455, 64.9179);
+ poly60.ps[2] = Point(312.455, 64.9179);
+ poly60.ps[3] = Point(312.455, 4.91795);
+ ShapeRef *shapeRef60 = new ShapeRef(router, poly60, 60);
+ router->addShape(shapeRef60);
+
+ Polygon poly104(4);
+ poly104.ps[0] = Point(499.246, 408.918);
+ poly104.ps[1] = Point(499.246, 428.918);
+ poly104.ps[2] = Point(479.246, 428.918);
+ poly104.ps[3] = Point(479.246, 408.918);
+ ShapeRef *shapeRef104 = new ShapeRef(router, poly104, 104);
+ router->addShape(shapeRef104);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(1223.25, 656.918);
+ poly8.ps[1] = Point(1223.25, 696.918);
+ poly8.ps[2] = Point(1183.25, 696.918);
+ poly8.ps[3] = Point(1183.25, 656.918);
+ ShapeRef *shapeRef8 = new ShapeRef(router, poly8, 8);
+ router->addShape(shapeRef8);
+
+ Polygon poly121(4);
+ poly121.ps[0] = Point(203.246, 612.918);
+ poly121.ps[1] = Point(203.246, 632.918);
+ poly121.ps[2] = Point(183.246, 632.918);
+ poly121.ps[3] = Point(183.246, 612.918);
+ ShapeRef *shapeRef121 = new ShapeRef(router, poly121, 121);
+ router->addShape(shapeRef121);
+
+ Polygon poly61(4);
+ poly61.ps[0] = Point(222.246, -101.082);
+ poly61.ps[1] = Point(222.246, -41.0821);
+ poly61.ps[2] = Point(-12.7544, -41.0821);
+ poly61.ps[3] = Point(-12.7544, -101.082);
+ ShapeRef *shapeRef61 = new ShapeRef(router, poly61, 61);
+ router->addShape(shapeRef61);
+
+ Polygon poly58(4);
+ poly58.ps[0] = Point(1047.75, 767.422);
+ poly58.ps[1] = Point(1047.75, 802.422);
+ poly58.ps[2] = Point(910.746, 802.422);
+ poly58.ps[3] = Point(910.746, 767.422);
+ ShapeRef *shapeRef58 = new ShapeRef(router, poly58, 58);
+ router->addShape(shapeRef58);
+
+ Polygon poly248(4);
+ poly248.ps[0] = Point(955.246, 516.918);
+ poly248.ps[1] = Point(955.246, 556.918);
+ poly248.ps[2] = Point(899.246, 556.918);
+ poly248.ps[3] = Point(899.246, 516.918);
+ ShapeRef *shapeRef248 = new ShapeRef(router, poly248, 248);
+ router->addShape(shapeRef248);
+
+ Polygon poly249(4);
+ poly249.ps[0] = Point(799.246, 516.918);
+ poly249.ps[1] = Point(799.246, 556.918);
+ poly249.ps[2] = Point(743.246, 556.918);
+ poly249.ps[3] = Point(743.246, 516.918);
+ ShapeRef *shapeRef249 = new ShapeRef(router, poly249, 249);
+ router->addShape(shapeRef249);
+
+ Polygon poly250(4);
+ poly250.ps[0] = Point(643.246, 516.918);
+ poly250.ps[1] = Point(643.246, 556.918);
+ poly250.ps[2] = Point(587.246, 556.918);
+ poly250.ps[3] = Point(587.246, 516.918);
+ ShapeRef *shapeRef250 = new ShapeRef(router, poly250, 250);
+ router->addShape(shapeRef250);
+
+ Polygon poly251(4);
+ poly251.ps[0] = Point(487.246, 516.918);
+ poly251.ps[1] = Point(487.246, 556.918);
+ poly251.ps[2] = Point(431.246, 556.918);
+ poly251.ps[3] = Point(431.246, 516.918);
+ ShapeRef *shapeRef251 = new ShapeRef(router, poly251, 251);
+ router->addShape(shapeRef251);
+
+ Polygon poly252(4);
+ poly252.ps[0] = Point(331.246, 516.918);
+ poly252.ps[1] = Point(331.246, 556.918);
+ poly252.ps[2] = Point(275.246, 556.918);
+ poly252.ps[3] = Point(275.246, 516.918);
+ ShapeRef *shapeRef252 = new ShapeRef(router, poly252, 252);
+ router->addShape(shapeRef252);
+
+ Polygon poly253(4);
+ poly253.ps[0] = Point(173.246, 516.918);
+ poly253.ps[1] = Point(173.246, 556.918);
+ poly253.ps[2] = Point(117.246, 556.918);
+ poly253.ps[3] = Point(117.246, 516.918);
+ ShapeRef *shapeRef253 = new ShapeRef(router, poly253, 253);
+ router->addShape(shapeRef253);
+
+ Polygon poly231(4);
+ poly231.ps[0] = Point(173.246, 634.918);
+ poly231.ps[1] = Point(173.246, 674.918);
+ poly231.ps[2] = Point(117.246, 674.918);
+ poly231.ps[3] = Point(117.246, 634.918);
+ ShapeRef *shapeRef231 = new ShapeRef(router, poly231, 231);
+ router->addShape(shapeRef231);
+
+ Polygon poly232(4);
+ poly232.ps[0] = Point(907.246, 698.918);
+ poly232.ps[1] = Point(907.246, 738.918);
+ poly232.ps[2] = Point(851.246, 738.918);
+ poly232.ps[3] = Point(851.246, 698.918);
+ ShapeRef *shapeRef232 = new ShapeRef(router, poly232, 232);
+ router->addShape(shapeRef232);
+
+ Polygon poly233(4);
+ poly233.ps[0] = Point(1231.25, 698.918);
+ poly233.ps[1] = Point(1231.25, 738.918);
+ poly233.ps[2] = Point(1175.25, 738.918);
+ poly233.ps[3] = Point(1175.25, 698.918);
+ ShapeRef *shapeRef233 = new ShapeRef(router, poly233, 233);
+ router->addShape(shapeRef233);
+
+ Polygon poly234(4);
+ poly234.ps[0] = Point(1291.25, 698.918);
+ poly234.ps[1] = Point(1291.25, 738.918);
+ poly234.ps[2] = Point(1235.25, 738.918);
+ poly234.ps[3] = Point(1235.25, 698.918);
+ ShapeRef *shapeRef234 = new ShapeRef(router, poly234, 234);
+ router->addShape(shapeRef234);
+
+ Polygon poly235(4);
+ poly235.ps[0] = Point(622.941, 698.918);
+ poly235.ps[1] = Point(622.941, 738.918);
+ poly235.ps[2] = Point(566.941, 738.918);
+ poly235.ps[3] = Point(566.941, 698.918);
+ ShapeRef *shapeRef235 = new ShapeRef(router, poly235, 235);
+ router->addShape(shapeRef235);
+
+ Polygon poly236(4);
+ poly236.ps[0] = Point(479.455, 698.918);
+ poly236.ps[1] = Point(479.455, 738.918);
+ poly236.ps[2] = Point(423.455, 738.918);
+ poly236.ps[3] = Point(423.455, 698.918);
+ ShapeRef *shapeRef236 = new ShapeRef(router, poly236, 236);
+ router->addShape(shapeRef236);
+
+ Polygon poly103(4);
+ poly103.ps[0] = Point(547.246, 408.918);
+ poly103.ps[1] = Point(547.246, 428.918);
+ poly103.ps[2] = Point(527.246, 428.918);
+ poly103.ps[3] = Point(527.246, 408.918);
+ ShapeRef *shapeRef103 = new ShapeRef(router, poly103, 103);
+ router->addShape(shapeRef103);
+
+ Polygon poly69(4);
+ poly69.ps[0] = Point(1015.25, 408.918);
+ poly69.ps[1] = Point(1015.25, 428.918);
+ poly69.ps[2] = Point(995.246, 428.918);
+ poly69.ps[3] = Point(995.246, 408.918);
+ ShapeRef *shapeRef69 = new ShapeRef(router, poly69, 69);
+ router->addShape(shapeRef69);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(547.246, 612.918);
+ poly4.ps[1] = Point(547.246, 632.918);
+ poly4.ps[2] = Point(527.246, 632.918);
+ poly4.ps[3] = Point(527.246, 612.918);
+ ShapeRef *shapeRef4 = new ShapeRef(router, poly4, 4);
+ router->addShape(shapeRef4);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(77.2456, 644.918);
+ poly7.ps[1] = Point(77.2456, 664.918);
+ poly7.ps[2] = Point(57.2456, 664.918);
+ poly7.ps[3] = Point(57.2456, 644.918);
+ ShapeRef *shapeRef7 = new ShapeRef(router, poly7, 7);
+ router->addShape(shapeRef7);
+
+ Polygon poly33(4);
+ poly33.ps[0] = Point(235.246, 644.918);
+ poly33.ps[1] = Point(235.246, 664.918);
+ poly33.ps[2] = Point(215.246, 664.918);
+ poly33.ps[3] = Point(215.246, 644.918);
+ ShapeRef *shapeRef33 = new ShapeRef(router, poly33, 33);
+ router->addShape(shapeRef33);
+
+ Polygon poly380(4);
+ poly380.ps[0] = Point(595.246, 634.918);
+ poly380.ps[1] = Point(595.246, 674.918);
+ poly380.ps[2] = Point(539.246, 674.918);
+ poly380.ps[3] = Point(539.246, 634.918);
+ ShapeRef *shapeRef380 = new ShapeRef(router, poly380, 380);
+ router->addShape(shapeRef380);
+
+ Polygon poly381(4);
+ poly381.ps[0] = Point(751.246, 634.918);
+ poly381.ps[1] = Point(751.246, 674.918);
+ poly381.ps[2] = Point(695.246, 674.918);
+ poly381.ps[3] = Point(695.246, 634.918);
+ ShapeRef *shapeRef381 = new ShapeRef(router, poly381, 381);
+ router->addShape(shapeRef381);
+
+ Polygon poly382(4);
+ poly382.ps[0] = Point(907.246, 634.918);
+ poly382.ps[1] = Point(907.246, 674.918);
+ poly382.ps[2] = Point(851.246, 674.918);
+ poly382.ps[3] = Point(851.246, 634.918);
+ ShapeRef *shapeRef382 = new ShapeRef(router, poly382, 382);
+ router->addShape(shapeRef382);
+
+ Polygon poly383(4);
+ poly383.ps[0] = Point(1063.25, 634.918);
+ poly383.ps[1] = Point(1063.25, 674.918);
+ poly383.ps[2] = Point(1007.25, 674.918);
+ poly383.ps[3] = Point(1007.25, 634.918);
+ ShapeRef *shapeRef383 = new ShapeRef(router, poly383, 383);
+ router->addShape(shapeRef383);
+
+ Polygon poly384(4);
+ poly384.ps[0] = Point(1261.25, 172.918);
+ poly384.ps[1] = Point(1261.25, 212.918);
+ poly384.ps[2] = Point(1205.25, 212.918);
+ poly384.ps[3] = Point(1205.25, 172.918);
+ ShapeRef *shapeRef384 = new ShapeRef(router, poly384, 384);
+ router->addShape(shapeRef384);
+
+ Polygon poly385(4);
+ poly385.ps[0] = Point(1351.25, 398.918);
+ poly385.ps[1] = Point(1351.25, 438.918);
+ poly385.ps[2] = Point(1295.25, 438.918);
+ poly385.ps[3] = Point(1295.25, 398.918);
+ ShapeRef *shapeRef385 = new ShapeRef(router, poly385, 385);
+ router->addShape(shapeRef385);
+
+ Polygon poly386(4);
+ poly386.ps[0] = Point(1351.25, 494.918);
+ poly386.ps[1] = Point(1351.25, 534.918);
+ poly386.ps[2] = Point(1295.25, 534.918);
+ poly386.ps[3] = Point(1295.25, 494.918);
+ ShapeRef *shapeRef386 = new ShapeRef(router, poly386, 386);
+ router->addShape(shapeRef386);
+
+ Polygon poly387(4);
+ poly387.ps[0] = Point(1351.25, 602.918);
+ poly387.ps[1] = Point(1351.25, 642.918);
+ poly387.ps[2] = Point(1295.25, 642.918);
+ poly387.ps[3] = Point(1295.25, 602.918);
+ ShapeRef *shapeRef387 = new ShapeRef(router, poly387, 387);
+ router->addShape(shapeRef387);
+
+ Polygon poly388(4);
+ poly388.ps[0] = Point(1063.25, 698.918);
+ poly388.ps[1] = Point(1063.25, 738.918);
+ poly388.ps[2] = Point(1007.25, 738.918);
+ poly388.ps[3] = Point(1007.25, 698.918);
+ ShapeRef *shapeRef388 = new ShapeRef(router, poly388, 388);
+ router->addShape(shapeRef388);
+
+ Polygon poly389(4);
+ poly389.ps[0] = Point(1063.25, 730.918);
+ poly389.ps[1] = Point(1063.25, 770.918);
+ poly389.ps[2] = Point(1007.25, 770.918);
+ poly389.ps[3] = Point(1007.25, 730.918);
+ ShapeRef *shapeRef389 = new ShapeRef(router, poly389, 389);
+ router->addShape(shapeRef389);
+
+ Polygon poly390(4);
+ poly390.ps[0] = Point(1351.25, 698.918);
+ poly390.ps[1] = Point(1351.25, 738.918);
+ poly390.ps[2] = Point(1295.25, 738.918);
+ poly390.ps[3] = Point(1295.25, 698.918);
+ ShapeRef *shapeRef390 = new ShapeRef(router, poly390, 390);
+ router->addShape(shapeRef390);
+
+ Polygon poly391(4);
+ poly391.ps[0] = Point(1321.25, 182.918);
+ poly391.ps[1] = Point(1321.25, 222.918);
+ poly391.ps[2] = Point(1265.25, 222.918);
+ poly391.ps[3] = Point(1265.25, 182.918);
+ ShapeRef *shapeRef391 = new ShapeRef(router, poly391, 391);
+ router->addShape(shapeRef391);
+
+ Polygon poly392(4);
+ poly392.ps[0] = Point(1447.25, 624.918);
+ poly392.ps[1] = Point(1447.25, 664.918);
+ poly392.ps[2] = Point(1391.25, 664.918);
+ poly392.ps[3] = Point(1391.25, 624.918);
+ ShapeRef *shapeRef392 = new ShapeRef(router, poly392, 392);
+ router->addShape(shapeRef392);
+
+ Polygon poly393(4);
+ poly393.ps[0] = Point(173.246, 226.918);
+ poly393.ps[1] = Point(173.246, 266.918);
+ poly393.ps[2] = Point(117.246, 266.918);
+ poly393.ps[3] = Point(117.246, 226.918);
+ ShapeRef *shapeRef393 = new ShapeRef(router, poly393, 393);
+ router->addShape(shapeRef393);
+
+ Polygon poly394(4);
+ poly394.ps[0] = Point(173.246, 258.918);
+ poly394.ps[1] = Point(173.246, 298.918);
+ poly394.ps[2] = Point(117.246, 298.918);
+ poly394.ps[3] = Point(117.246, 258.918);
+ ShapeRef *shapeRef394 = new ShapeRef(router, poly394, 394);
+ router->addShape(shapeRef394);
+
+ Polygon poly395(4);
+ poly395.ps[0] = Point(372.466, 14.9179);
+ poly395.ps[1] = Point(372.466, 54.9179);
+ poly395.ps[2] = Point(312.466, 54.9179);
+ poly395.ps[3] = Point(312.466, 14.9179);
+ ShapeRef *shapeRef395 = new ShapeRef(router, poly395, 395);
+ router->addShape(shapeRef395);
+
+ Polygon poly396(4);
+ poly396.ps[0] = Point(47.2456, -91.0821);
+ poly396.ps[1] = Point(47.2456, -51.0821);
+ poly396.ps[2] = Point(-12.7544, -51.0821);
+ poly396.ps[3] = Point(-12.7544, -91.0821);
+ ShapeRef *shapeRef396 = new ShapeRef(router, poly396, 396);
+ router->addShape(shapeRef396);
+
+ Polygon poly397(4);
+ poly397.ps[0] = Point(372.466, 66.9179);
+ poly397.ps[1] = Point(372.466, 106.918);
+ poly397.ps[2] = Point(312.466, 106.918);
+ poly397.ps[3] = Point(312.466, 66.9179);
+ ShapeRef *shapeRef397 = new ShapeRef(router, poly397, 397);
+ router->addShape(shapeRef397);
+
+ Polygon poly63(4);
+ poly63.ps[0] = Point(967.246, 676.918);
+ poly63.ps[1] = Point(967.246, 696.918);
+ poly63.ps[2] = Point(947.246, 696.918);
+ poly63.ps[3] = Point(947.246, 676.918);
+ ShapeRef *shapeRef63 = new ShapeRef(router, poly63, 63);
+ router->addShape(shapeRef63);
+
+ Polygon poly90(4);
+ poly90.ps[0] = Point(655.246, 472.918);
+ poly90.ps[1] = Point(655.246, 492.918);
+ poly90.ps[2] = Point(635.246, 492.918);
+ poly90.ps[3] = Point(635.246, 472.918);
+ ShapeRef *shapeRef90 = new ShapeRef(router, poly90, 90);
+ router->addShape(shapeRef90);
+
+ Polygon poly282(4);
+ poly282.ps[0] = Point(955.246, 570.918);
+ poly282.ps[1] = Point(955.246, 610.918);
+ poly282.ps[2] = Point(899.246, 610.918);
+ poly282.ps[3] = Point(899.246, 570.918);
+ ShapeRef *shapeRef282 = new ShapeRef(router, poly282, 282);
+ router->addShape(shapeRef282);
+
+ Polygon poly283(4);
+ poly283.ps[0] = Point(907.246, 602.918);
+ poly283.ps[1] = Point(907.246, 642.918);
+ poly283.ps[2] = Point(851.246, 642.918);
+ poly283.ps[3] = Point(851.246, 602.918);
+ ShapeRef *shapeRef283 = new ShapeRef(router, poly283, 283);
+ router->addShape(shapeRef283);
+
+ Polygon poly284(4);
+ poly284.ps[0] = Point(907.246, 570.918);
+ poly284.ps[1] = Point(907.246, 610.918);
+ poly284.ps[2] = Point(851.246, 610.918);
+ poly284.ps[3] = Point(851.246, 570.918);
+ ShapeRef *shapeRef284 = new ShapeRef(router, poly284, 284);
+ router->addShape(shapeRef284);
+
+ Polygon poly285(4);
+ poly285.ps[0] = Point(907.246, 494.918);
+ poly285.ps[1] = Point(907.246, 534.918);
+ poly285.ps[2] = Point(851.246, 534.918);
+ poly285.ps[3] = Point(851.246, 494.918);
+ ShapeRef *shapeRef285 = new ShapeRef(router, poly285, 285);
+ router->addShape(shapeRef285);
+
+ Polygon poly286(4);
+ poly286.ps[0] = Point(907.246, 462.918);
+ poly286.ps[1] = Point(907.246, 502.918);
+ poly286.ps[2] = Point(851.246, 502.918);
+ poly286.ps[3] = Point(851.246, 462.918);
+ ShapeRef *shapeRef286 = new ShapeRef(router, poly286, 286);
+ router->addShape(shapeRef286);
+
+ Polygon poly287(4);
+ poly287.ps[0] = Point(955.246, 398.918);
+ poly287.ps[1] = Point(955.246, 438.918);
+ poly287.ps[2] = Point(899.246, 438.918);
+ poly287.ps[3] = Point(899.246, 398.918);
+ ShapeRef *shapeRef287 = new ShapeRef(router, poly287, 287);
+ router->addShape(shapeRef287);
+
+ Polygon poly288(4);
+ poly288.ps[0] = Point(907.246, 398.918);
+ poly288.ps[1] = Point(907.246, 438.918);
+ poly288.ps[2] = Point(851.246, 438.918);
+ poly288.ps[3] = Point(851.246, 398.918);
+ ShapeRef *shapeRef288 = new ShapeRef(router, poly288, 288);
+ router->addShape(shapeRef288);
+
+ Polygon poly289(4);
+ poly289.ps[0] = Point(907.246, 366.918);
+ poly289.ps[1] = Point(907.246, 406.918);
+ poly289.ps[2] = Point(851.246, 406.918);
+ poly289.ps[3] = Point(851.246, 366.918);
+ ShapeRef *shapeRef289 = new ShapeRef(router, poly289, 289);
+ router->addShape(shapeRef289);
+
+ Polygon poly242(4);
+ poly242.ps[0] = Point(643.246, 634.918);
+ poly242.ps[1] = Point(643.246, 674.918);
+ poly242.ps[2] = Point(587.246, 674.918);
+ poly242.ps[3] = Point(587.246, 634.918);
+ ShapeRef *shapeRef242 = new ShapeRef(router, poly242, 242);
+ router->addShape(shapeRef242);
+
+ Polygon poly243(4);
+ poly243.ps[0] = Point(487.246, 634.918);
+ poly243.ps[1] = Point(487.246, 674.918);
+ poly243.ps[2] = Point(431.246, 674.918);
+ poly243.ps[3] = Point(431.246, 634.918);
+ ShapeRef *shapeRef243 = new ShapeRef(router, poly243, 243);
+ router->addShape(shapeRef243);
+
+ Polygon poly244(4);
+ poly244.ps[0] = Point(331.246, 634.918);
+ poly244.ps[1] = Point(331.246, 674.918);
+ poly244.ps[2] = Point(275.246, 674.918);
+ poly244.ps[3] = Point(275.246, 634.918);
+ ShapeRef *shapeRef244 = new ShapeRef(router, poly244, 244);
+ router->addShape(shapeRef244);
+
+ Polygon poly245(4);
+ poly245.ps[0] = Point(173.246, 602.918);
+ poly245.ps[1] = Point(173.246, 642.918);
+ poly245.ps[2] = Point(117.246, 642.918);
+ poly245.ps[3] = Point(117.246, 602.918);
+ ShapeRef *shapeRef245 = new ShapeRef(router, poly245, 245);
+ router->addShape(shapeRef245);
+
+ Polygon poly246(4);
+ poly246.ps[0] = Point(1447.25, 494.918);
+ poly246.ps[1] = Point(1447.25, 534.918);
+ poly246.ps[2] = Point(1391.25, 534.918);
+ poly246.ps[3] = Point(1391.25, 494.918);
+ ShapeRef *shapeRef246 = new ShapeRef(router, poly246, 246);
+ router->addShape(shapeRef246);
+
+ Polygon poly247(4);
+ poly247.ps[0] = Point(1159.25, 516.918);
+ poly247.ps[1] = Point(1159.25, 556.918);
+ poly247.ps[2] = Point(1103.25, 556.918);
+ poly247.ps[3] = Point(1103.25, 516.918);
+ ShapeRef *shapeRef247 = new ShapeRef(router, poly247, 247);
+ router->addShape(shapeRef247);
+
+ Polygon poly23(4);
+ poly23.ps[0] = Point(1183.25, 708.918);
+ poly23.ps[1] = Point(1183.25, 728.918);
+ poly23.ps[2] = Point(1163.25, 728.918);
+ poly23.ps[3] = Point(1163.25, 708.918);
+ ShapeRef *shapeRef23 = new ShapeRef(router, poly23, 23);
+ router->addShape(shapeRef23);
+
+ ConnRef *connRef715 = new ConnRef(router, 715);
+ ConnEnd srcPt715(Point(132, 319), 15);
+ connRef715->setSourceEndpoint(srcPt715);
+ ConnEnd dstPt715(Point(57.2456, 332.918), 15);
+ connRef715->setDestEndpoint(dstPt715);
+ connRef715->setRoutingType((ConnType)2);
+
+ ConnRef *connRef716 = new ConnRef(router, 716);
+ ConnEnd srcPt716(Point(1131.25, 622.918), 15);
+ connRef716->setSourceEndpoint(srcPt716);
+ ConnEnd dstPt716(Point(1005.25, 622.918), 15);
+ connRef716->setDestEndpoint(dstPt716);
+ connRef716->setRoutingType((ConnType)2);
+
+ ConnRef *connRef717 = new ConnRef(router, 717);
+ ConnEnd srcPt717(Point(927.246, 622.918), 15);
+ connRef717->setSourceEndpoint(srcPt717);
+ ConnEnd dstPt717(Point(849.246, 622.918), 15);
+ connRef717->setDestEndpoint(dstPt717);
+ connRef717->setRoutingType((ConnType)2);
+
+ ConnRef *connRef718 = new ConnRef(router, 718);
+ ConnEnd srcPt718(Point(771.246, 622.918), 15);
+ connRef718->setSourceEndpoint(srcPt718);
+ ConnEnd dstPt718(Point(693.246, 622.918), 15);
+ connRef718->setDestEndpoint(dstPt718);
+ connRef718->setRoutingType((ConnType)2);
+
+ ConnRef *connRef719 = new ConnRef(router, 719);
+ ConnEnd srcPt719(Point(615.246, 622.918), 15);
+ connRef719->setSourceEndpoint(srcPt719);
+ ConnEnd dstPt719(Point(537.246, 622.918), 15);
+ connRef719->setDestEndpoint(dstPt719);
+ connRef719->setRoutingType((ConnType)2);
+
+ ConnRef *connRef720 = new ConnRef(router, 720);
+ ConnEnd srcPt720(Point(459.246, 622.918), 15);
+ connRef720->setSourceEndpoint(srcPt720);
+ ConnEnd dstPt720(Point(381.246, 622.918), 15);
+ connRef720->setDestEndpoint(dstPt720);
+ connRef720->setRoutingType((ConnType)2);
+
+ ConnRef *connRef721 = new ConnRef(router, 721);
+ ConnEnd srcPt721(Point(303.246, 622.918), 15);
+ connRef721->setSourceEndpoint(srcPt721);
+ ConnEnd dstPt721(Point(225.246, 622.918), 15);
+ connRef721->setDestEndpoint(dstPt721);
+ connRef721->setRoutingType((ConnType)2);
+
+ ConnRef *connRef722 = new ConnRef(router, 722);
+ ConnEnd srcPt722(Point(145.246, 654.918), 15);
+ connRef722->setSourceEndpoint(srcPt722);
+ ConnEnd dstPt722(Point(67.2456, 654.918), 15);
+ connRef722->setDestEndpoint(dstPt722);
+ connRef722->setRoutingType((ConnType)2);
+
+ ConnRef *connRef723 = new ConnRef(router, 723);
+ ConnEnd srcPt723(Point(879.246, 718.918), 15);
+ connRef723->setSourceEndpoint(srcPt723);
+ ConnEnd dstPt723(Point(801.246, 718.918), 15);
+ connRef723->setDestEndpoint(dstPt723);
+ connRef723->setRoutingType((ConnType)2);
+
+ ConnRef *connRef724 = new ConnRef(router, 724);
+ ConnEnd srcPt724(Point(1203.25, 718.918), 15);
+ connRef724->setSourceEndpoint(srcPt724);
+ ConnEnd dstPt724(Point(1161.25, 718.918), 15);
+ connRef724->setDestEndpoint(dstPt724);
+ connRef724->setRoutingType((ConnType)2);
+
+ ConnRef *connRef725 = new ConnRef(router, 725);
+ ConnEnd srcPt725(Point(1263.25, 718.918), 15);
+ connRef725->setSourceEndpoint(srcPt725);
+ ConnEnd dstPt725(Point(1173.25, 718.918), 15);
+ connRef725->setDestEndpoint(dstPt725);
+ connRef725->setRoutingType((ConnType)2);
+
+ ConnRef *connRef726 = new ConnRef(router, 726);
+ ConnEnd srcPt726(Point(594.941, 718.918), 15);
+ connRef726->setSourceEndpoint(srcPt726);
+ ConnEnd dstPt726(Point(527.246, 718.918), 15);
+ connRef726->setDestEndpoint(dstPt726);
+ connRef726->setRoutingType((ConnType)2);
+
+ ConnRef *connRef727 = new ConnRef(router, 727);
+ ConnEnd srcPt727(Point(451.455, 718.918), 15);
+ connRef727->setSourceEndpoint(srcPt727);
+ ConnEnd dstPt727(Point(371.246, 718.918), 15);
+ connRef727->setDestEndpoint(dstPt727);
+ connRef727->setRoutingType((ConnType)2);
+
+ ConnRef *connRef728 = new ConnRef(router, 728);
+ ConnEnd srcPt728(Point(1371.25, 622.918), 15);
+ connRef728->setSourceEndpoint(srcPt728);
+ ConnEnd dstPt728(Point(1371.25, 676.918), 15);
+ connRef728->setDestEndpoint(dstPt728);
+ connRef728->setRoutingType((ConnType)2);
+
+ ConnRef *connRef729 = new ConnRef(router, 729);
+ ConnEnd srcPt729(Point(1419.25, 575.942), 15);
+ connRef729->setSourceEndpoint(srcPt729);
+ ConnEnd dstPt729(Point(1293.25, 575.942), 15);
+ connRef729->setDestEndpoint(dstPt729);
+ connRef729->setRoutingType((ConnType)2);
+
+ ConnRef *connRef730 = new ConnRef(router, 730);
+ ConnEnd srcPt730(Point(1131.25, 654.918), 15);
+ connRef730->setSourceEndpoint(srcPt730);
+ ConnEnd dstPt730(Point(1005.25, 654.918), 15);
+ connRef730->setDestEndpoint(dstPt730);
+ connRef730->setRoutingType((ConnType)2);
+
+ ConnRef *connRef731 = new ConnRef(router, 731);
+ ConnEnd srcPt731(Point(927.246, 654.918), 15);
+ connRef731->setSourceEndpoint(srcPt731);
+ ConnEnd dstPt731(Point(849.246, 654.918), 15);
+ connRef731->setDestEndpoint(dstPt731);
+ connRef731->setRoutingType((ConnType)2);
+
+ ConnRef *connRef732 = new ConnRef(router, 732);
+ ConnEnd srcPt732(Point(771.246, 654.918), 15);
+ connRef732->setSourceEndpoint(srcPt732);
+ ConnEnd dstPt732(Point(693.246, 654.918), 15);
+ connRef732->setDestEndpoint(dstPt732);
+ connRef732->setRoutingType((ConnType)2);
+
+ ConnRef *connRef733 = new ConnRef(router, 733);
+ ConnEnd srcPt733(Point(615.246, 654.918), 15);
+ connRef733->setSourceEndpoint(srcPt733);
+ ConnEnd dstPt733(Point(537.246, 654.918), 15);
+ connRef733->setDestEndpoint(dstPt733);
+ connRef733->setRoutingType((ConnType)2);
+
+ ConnRef *connRef734 = new ConnRef(router, 734);
+ ConnEnd srcPt734(Point(459.246, 654.918), 15);
+ connRef734->setSourceEndpoint(srcPt734);
+ ConnEnd dstPt734(Point(381.246, 654.918), 15);
+ connRef734->setDestEndpoint(dstPt734);
+ connRef734->setRoutingType((ConnType)2);
+
+ ConnRef *connRef735 = new ConnRef(router, 735);
+ ConnEnd srcPt735(Point(303.246, 654.918), 15);
+ connRef735->setSourceEndpoint(srcPt735);
+ ConnEnd dstPt735(Point(225.246, 654.918), 15);
+ connRef735->setDestEndpoint(dstPt735);
+ connRef735->setRoutingType((ConnType)2);
+
+ ConnRef *connRef736 = new ConnRef(router, 736);
+ ConnEnd srcPt736(Point(145.246, 622.918), 15);
+ connRef736->setSourceEndpoint(srcPt736);
+ ConnEnd dstPt736(Point(67.2456, 622.918), 15);
+ connRef736->setDestEndpoint(dstPt736);
+ connRef736->setRoutingType((ConnType)2);
+
+ ConnRef *connRef737 = new ConnRef(router, 737);
+ ConnEnd srcPt737(Point(1419.25, 514.918), 15);
+ connRef737->setSourceEndpoint(srcPt737);
+ ConnEnd dstPt737(Point(1293.25, 514.918), 15);
+ connRef737->setDestEndpoint(dstPt737);
+ connRef737->setRoutingType((ConnType)2);
+
+ ConnRef *connRef738 = new ConnRef(router, 738);
+ ConnEnd srcPt738(Point(1131.25, 536.918), 15);
+ connRef738->setSourceEndpoint(srcPt738);
+ ConnEnd dstPt738(Point(1005.25, 536.918), 15);
+ connRef738->setDestEndpoint(dstPt738);
+ connRef738->setRoutingType((ConnType)2);
+
+ ConnRef *connRef739 = new ConnRef(router, 739);
+ ConnEnd srcPt739(Point(927.246, 536.918), 15);
+ connRef739->setSourceEndpoint(srcPt739);
+ ConnEnd dstPt739(Point(849.246, 536.918), 15);
+ connRef739->setDestEndpoint(dstPt739);
+ connRef739->setRoutingType((ConnType)2);
+
+ ConnRef *connRef740 = new ConnRef(router, 740);
+ ConnEnd srcPt740(Point(771.246, 536.918), 15);
+ connRef740->setSourceEndpoint(srcPt740);
+ ConnEnd dstPt740(Point(693.246, 536.918), 15);
+ connRef740->setDestEndpoint(dstPt740);
+ connRef740->setRoutingType((ConnType)2);
+
+ ConnRef *connRef741 = new ConnRef(router, 741);
+ ConnEnd srcPt741(Point(615.246, 536.918), 15);
+ connRef741->setSourceEndpoint(srcPt741);
+ ConnEnd dstPt741(Point(537.246, 536.918), 15);
+ connRef741->setDestEndpoint(dstPt741);
+ connRef741->setRoutingType((ConnType)2);
+
+ ConnRef *connRef742 = new ConnRef(router, 742);
+ ConnEnd srcPt742(Point(459.246, 536.918), 15);
+ connRef742->setSourceEndpoint(srcPt742);
+ ConnEnd dstPt742(Point(381.246, 536.918), 15);
+ connRef742->setDestEndpoint(dstPt742);
+ connRef742->setRoutingType((ConnType)2);
+
+ ConnRef *connRef743 = new ConnRef(router, 743);
+ ConnEnd srcPt743(Point(303.246, 536.918), 15);
+ connRef743->setSourceEndpoint(srcPt743);
+ ConnEnd dstPt743(Point(225.246, 536.918), 15);
+ connRef743->setDestEndpoint(dstPt743);
+ connRef743->setRoutingType((ConnType)2);
+
+ ConnRef *connRef744 = new ConnRef(router, 744);
+ ConnEnd srcPt744(Point(145.246, 536.918), 15);
+ connRef744->setSourceEndpoint(srcPt744);
+ ConnEnd dstPt744(Point(67.2456, 536.918), 15);
+ connRef744->setDestEndpoint(dstPt744);
+ connRef744->setRoutingType((ConnType)2);
+
+ ConnRef *connRef745 = new ConnRef(router, 745);
+ ConnEnd srcPt745(Point(1293.25, 234.918), 15);
+ connRef745->setSourceEndpoint(srcPt745);
+ ConnEnd dstPt745(Point(1293.25, 288.918), 15);
+ connRef745->setDestEndpoint(dstPt745);
+ connRef745->setRoutingType((ConnType)2);
+
+ ConnRef *connRef746 = new ConnRef(router, 746);
+ ConnEnd srcPt746(Point(1083.25, 622.918), 15);
+ connRef746->setSourceEndpoint(srcPt746);
+ ConnEnd dstPt746(Point(1083.25, 676.918), 15);
+ connRef746->setDestEndpoint(dstPt746);
+ connRef746->setRoutingType((ConnType)2);
+
+ ConnRef *connRef747 = new ConnRef(router, 747);
+ ConnEnd srcPt747(Point(1419.25, 418.918), 15);
+ connRef747->setSourceEndpoint(srcPt747);
+ ConnEnd dstPt747(Point(1293.25, 418.918), 15);
+ connRef747->setDestEndpoint(dstPt747);
+ connRef747->setRoutingType((ConnType)2);
+
+ ConnRef *connRef748 = new ConnRef(router, 748);
+ ConnEnd srcPt748(Point(1419.25, 718.918), 15);
+ connRef748->setSourceEndpoint(srcPt748);
+ ConnEnd dstPt748(Point(1293.25, 718.918), 15);
+ connRef748->setDestEndpoint(dstPt748);
+ connRef748->setRoutingType((ConnType)2);
+
+ ConnRef *connRef749 = new ConnRef(router, 749);
+ ConnEnd srcPt749(Point(1479.25, 718.918), 15);
+ connRef749->setSourceEndpoint(srcPt749);
+ ConnEnd dstPt749(Point(1449.25, 718.918), 15);
+ connRef749->setDestEndpoint(dstPt749);
+ connRef749->setRoutingType((ConnType)2);
+
+ ConnRef *connRef750 = new ConnRef(router, 750);
+ ConnEnd srcPt750(Point(723.246, 718.918), 15);
+ connRef750->setSourceEndpoint(srcPt750);
+ ConnEnd dstPt750(Point(645.246, 718.918), 15);
+ connRef750->setDestEndpoint(dstPt750);
+ connRef750->setRoutingType((ConnType)2);
+
+ ConnRef *connRef751 = new ConnRef(router, 751);
+ ConnEnd srcPt751(Point(927.246, 718.918), 15);
+ connRef751->setSourceEndpoint(srcPt751);
+ ConnEnd dstPt751(Point(849.246, 718.918), 15);
+ connRef751->setDestEndpoint(dstPt751);
+ connRef751->setRoutingType((ConnType)2);
+
+ ConnRef *connRef752 = new ConnRef(router, 752);
+ ConnEnd srcPt752(Point(145.246, 32.9179), 15);
+ connRef752->setSourceEndpoint(srcPt752);
+ ConnEnd dstPt752(Point(67.2456, 32.9179), 15);
+ connRef752->setDestEndpoint(dstPt752);
+ connRef752->setRoutingType((ConnType)2);
+
+ ConnRef *connRef753 = new ConnRef(router, 753);
+ ConnEnd srcPt753(Point(145.246, 310.918), 15);
+ connRef753->setSourceEndpoint(srcPt753);
+ ConnEnd dstPt753(Point(67.2456, 310.918), 15);
+ connRef753->setDestEndpoint(dstPt753);
+ connRef753->setRoutingType((ConnType)2);
+
+ ConnRef *connRef754 = new ConnRef(router, 754);
+ ConnEnd srcPt754(Point(1005.25, 234.918), 15);
+ connRef754->setSourceEndpoint(srcPt754);
+ ConnEnd dstPt754(Point(1005.25, 288.918), 15);
+ connRef754->setDestEndpoint(dstPt754);
+ connRef754->setRoutingType((ConnType)2);
+
+ ConnRef *connRef755 = new ConnRef(router, 755);
+ ConnEnd srcPt755(Point(849.246, 234.918), 15);
+ connRef755->setSourceEndpoint(srcPt755);
+ ConnEnd dstPt755(Point(849.246, 288.918), 15);
+ connRef755->setDestEndpoint(dstPt755);
+ connRef755->setRoutingType((ConnType)2);
+
+ ConnRef *connRef756 = new ConnRef(router, 756);
+ ConnEnd srcPt756(Point(693.246, 234.918), 15);
+ connRef756->setSourceEndpoint(srcPt756);
+ ConnEnd dstPt756(Point(693.246, 288.918), 15);
+ connRef756->setDestEndpoint(dstPt756);
+ connRef756->setRoutingType((ConnType)2);
+
+ ConnRef *connRef757 = new ConnRef(router, 757);
+ ConnEnd srcPt757(Point(537.246, 234.918), 15);
+ connRef757->setSourceEndpoint(srcPt757);
+ ConnEnd dstPt757(Point(537.246, 288.918), 15);
+ connRef757->setDestEndpoint(dstPt757);
+ connRef757->setRoutingType((ConnType)2);
+
+ ConnRef *connRef758 = new ConnRef(router, 758);
+ ConnEnd srcPt758(Point(381.246, 234.918), 15);
+ connRef758->setSourceEndpoint(srcPt758);
+ ConnEnd dstPt758(Point(381.246, 288.918), 15);
+ connRef758->setDestEndpoint(dstPt758);
+ connRef758->setRoutingType((ConnType)2);
+
+ ConnRef *connRef759 = new ConnRef(router, 759);
+ ConnEnd srcPt759(Point(303.246, 288.918), 15);
+ connRef759->setSourceEndpoint(srcPt759);
+ ConnEnd dstPt759(Point(225.246, 288.918), 15);
+ connRef759->setDestEndpoint(dstPt759);
+ connRef759->setRoutingType((ConnType)2);
+
+ ConnRef *connRef760 = new ConnRef(router, 760);
+ ConnEnd srcPt760(Point(1131.25, 718.918), 15);
+ connRef760->setSourceEndpoint(srcPt760);
+ ConnEnd dstPt760(Point(1005.25, 718.918), 15);
+ connRef760->setDestEndpoint(dstPt760);
+ connRef760->setRoutingType((ConnType)2);
+
+ ConnRef *connRef761 = new ConnRef(router, 761);
+ ConnEnd srcPt761(Point(1035.25, 686.918), 15);
+ connRef761->setSourceEndpoint(srcPt761);
+ ConnEnd dstPt761(Point(957.246, 686.918), 15);
+ connRef761->setDestEndpoint(dstPt761);
+ connRef761->setRoutingType((ConnType)2);
+
+ ConnRef *connRef762 = new ConnRef(router, 762);
+ ConnEnd srcPt762(Point(1131.25, 590.918), 15);
+ connRef762->setSourceEndpoint(srcPt762);
+ ConnEnd dstPt762(Point(1005.25, 590.918), 15);
+ connRef762->setDestEndpoint(dstPt762);
+ connRef762->setRoutingType((ConnType)2);
+
+ ConnRef *connRef763 = new ConnRef(router, 763);
+ ConnEnd srcPt763(Point(1035.25, 622.918), 15);
+ connRef763->setSourceEndpoint(srcPt763);
+ ConnEnd dstPt763(Point(957.246, 622.918), 15);
+ connRef763->setDestEndpoint(dstPt763);
+ connRef763->setRoutingType((ConnType)2);
+
+ ConnRef *connRef764 = new ConnRef(router, 764);
+ ConnEnd srcPt764(Point(1035.25, 590.918), 15);
+ connRef764->setSourceEndpoint(srcPt764);
+ ConnEnd dstPt764(Point(957.246, 590.918), 15);
+ connRef764->setDestEndpoint(dstPt764);
+ connRef764->setRoutingType((ConnType)2);
+
+ ConnRef *connRef765 = new ConnRef(router, 765);
+ ConnEnd srcPt765(Point(1035.25, 514.918), 15);
+ connRef765->setSourceEndpoint(srcPt765);
+ ConnEnd dstPt765(Point(957.246, 514.918), 15);
+ connRef765->setDestEndpoint(dstPt765);
+ connRef765->setRoutingType((ConnType)2);
+
+ ConnRef *connRef766 = new ConnRef(router, 766);
+ ConnEnd srcPt766(Point(1035.25, 482.918), 15);
+ connRef766->setSourceEndpoint(srcPt766);
+ ConnEnd dstPt766(Point(957.246, 482.918), 15);
+ connRef766->setDestEndpoint(dstPt766);
+ connRef766->setRoutingType((ConnType)2);
+
+ ConnRef *connRef767 = new ConnRef(router, 767);
+ ConnEnd srcPt767(Point(1131.25, 418.918), 15);
+ connRef767->setSourceEndpoint(srcPt767);
+ ConnEnd dstPt767(Point(1005.25, 418.918), 15);
+ connRef767->setDestEndpoint(dstPt767);
+ connRef767->setRoutingType((ConnType)2);
+
+ ConnRef *connRef768 = new ConnRef(router, 768);
+ ConnEnd srcPt768(Point(1035.25, 418.918), 15);
+ connRef768->setSourceEndpoint(srcPt768);
+ ConnEnd dstPt768(Point(957.246, 418.918), 15);
+ connRef768->setDestEndpoint(dstPt768);
+ connRef768->setRoutingType((ConnType)2);
+
+ ConnRef *connRef769 = new ConnRef(router, 769);
+ ConnEnd srcPt769(Point(1035.25, 386.918), 15);
+ connRef769->setSourceEndpoint(srcPt769);
+ ConnEnd dstPt769(Point(957.246, 386.918), 15);
+ connRef769->setDestEndpoint(dstPt769);
+ connRef769->setRoutingType((ConnType)2);
+
+ ConnRef *connRef770 = new ConnRef(router, 770);
+ ConnEnd srcPt770(Point(1005.25, 202.918), 15);
+ connRef770->setSourceEndpoint(srcPt770);
+ ConnEnd dstPt770(Point(1005.25, 256.918), 15);
+ connRef770->setDestEndpoint(dstPt770);
+ connRef770->setRoutingType((ConnType)2);
+
+ ConnRef *connRef771 = new ConnRef(router, 771);
+ ConnEnd srcPt771(Point(957.246, 192.918), 15);
+ connRef771->setSourceEndpoint(srcPt771);
+ ConnEnd dstPt771(Point(957.246, 278.918), 15);
+ connRef771->setDestEndpoint(dstPt771);
+ connRef771->setRoutingType((ConnType)2);
+
+ ConnRef *connRef772 = new ConnRef(router, 772);
+ ConnEnd srcPt772(Point(957.246, 128.918), 15);
+ connRef772->setSourceEndpoint(srcPt772);
+ ConnEnd dstPt772(Point(957.246, 246.918), 15);
+ connRef772->setDestEndpoint(dstPt772);
+ connRef772->setRoutingType((ConnType)2);
+
+ ConnRef *connRef773 = new ConnRef(router, 773);
+ ConnEnd srcPt773(Point(927.246, 590.918), 15);
+ connRef773->setSourceEndpoint(srcPt773);
+ ConnEnd dstPt773(Point(849.246, 590.918), 15);
+ connRef773->setDestEndpoint(dstPt773);
+ connRef773->setRoutingType((ConnType)2);
+
+ ConnRef *connRef774 = new ConnRef(router, 774);
+ ConnEnd srcPt774(Point(879.246, 622.918), 15);
+ connRef774->setSourceEndpoint(srcPt774);
+ ConnEnd dstPt774(Point(801.246, 622.918), 15);
+ connRef774->setDestEndpoint(dstPt774);
+ connRef774->setRoutingType((ConnType)2);
+
+ ConnRef *connRef775 = new ConnRef(router, 775);
+ ConnEnd srcPt775(Point(879.246, 590.918), 15);
+ connRef775->setSourceEndpoint(srcPt775);
+ ConnEnd dstPt775(Point(801.246, 590.918), 15);
+ connRef775->setDestEndpoint(dstPt775);
+ connRef775->setRoutingType((ConnType)2);
+
+ ConnRef *connRef776 = new ConnRef(router, 776);
+ ConnEnd srcPt776(Point(879.246, 514.918), 15);
+ connRef776->setSourceEndpoint(srcPt776);
+ ConnEnd dstPt776(Point(801.246, 514.918), 15);
+ connRef776->setDestEndpoint(dstPt776);
+ connRef776->setRoutingType((ConnType)2);
+
+ ConnRef *connRef777 = new ConnRef(router, 777);
+ ConnEnd srcPt777(Point(879.246, 482.918), 15);
+ connRef777->setSourceEndpoint(srcPt777);
+ ConnEnd dstPt777(Point(801.246, 482.918), 15);
+ connRef777->setDestEndpoint(dstPt777);
+ connRef777->setRoutingType((ConnType)2);
+
+ ConnRef *connRef778 = new ConnRef(router, 778);
+ ConnEnd srcPt778(Point(927.246, 418.918), 15);
+ connRef778->setSourceEndpoint(srcPt778);
+ ConnEnd dstPt778(Point(849.246, 418.918), 15);
+ connRef778->setDestEndpoint(dstPt778);
+ connRef778->setRoutingType((ConnType)2);
+
+ ConnRef *connRef779 = new ConnRef(router, 779);
+ ConnEnd srcPt779(Point(879.246, 418.918), 15);
+ connRef779->setSourceEndpoint(srcPt779);
+ ConnEnd dstPt779(Point(801.246, 418.918), 15);
+ connRef779->setDestEndpoint(dstPt779);
+ connRef779->setRoutingType((ConnType)2);
+
+ ConnRef *connRef780 = new ConnRef(router, 780);
+ ConnEnd srcPt780(Point(879.246, 386.918), 15);
+ connRef780->setSourceEndpoint(srcPt780);
+ ConnEnd dstPt780(Point(801.246, 386.918), 15);
+ connRef780->setDestEndpoint(dstPt780);
+ connRef780->setRoutingType((ConnType)2);
+
+ ConnRef *connRef781 = new ConnRef(router, 781);
+ ConnEnd srcPt781(Point(849.246, 202.918), 15);
+ connRef781->setSourceEndpoint(srcPt781);
+ ConnEnd dstPt781(Point(849.246, 256.918), 15);
+ connRef781->setDestEndpoint(dstPt781);
+ connRef781->setRoutingType((ConnType)2);
+
+ ConnRef *connRef782 = new ConnRef(router, 782);
+ ConnEnd srcPt782(Point(801.246, 192.918), 15);
+ connRef782->setSourceEndpoint(srcPt782);
+ ConnEnd dstPt782(Point(801.246, 278.918), 15);
+ connRef782->setDestEndpoint(dstPt782);
+ connRef782->setRoutingType((ConnType)2);
+
+ ConnRef *connRef783 = new ConnRef(router, 783);
+ ConnEnd srcPt783(Point(801.246, 128.918), 15);
+ connRef783->setSourceEndpoint(srcPt783);
+ ConnEnd dstPt783(Point(801.246, 246.918), 15);
+ connRef783->setDestEndpoint(dstPt783);
+ connRef783->setRoutingType((ConnType)2);
+
+ ConnRef *connRef784 = new ConnRef(router, 784);
+ ConnEnd srcPt784(Point(771.246, 590.918), 15);
+ connRef784->setSourceEndpoint(srcPt784);
+ ConnEnd dstPt784(Point(693.246, 590.918), 15);
+ connRef784->setDestEndpoint(dstPt784);
+ connRef784->setRoutingType((ConnType)2);
+
+ ConnRef *connRef785 = new ConnRef(router, 785);
+ ConnEnd srcPt785(Point(723.246, 622.918), 15);
+ connRef785->setSourceEndpoint(srcPt785);
+ ConnEnd dstPt785(Point(645.246, 622.918), 15);
+ connRef785->setDestEndpoint(dstPt785);
+ connRef785->setRoutingType((ConnType)2);
+
+ ConnRef *connRef786 = new ConnRef(router, 786);
+ ConnEnd srcPt786(Point(723.246, 590.918), 15);
+ connRef786->setSourceEndpoint(srcPt786);
+ ConnEnd dstPt786(Point(645.246, 590.918), 15);
+ connRef786->setDestEndpoint(dstPt786);
+ connRef786->setRoutingType((ConnType)2);
+
+ ConnRef *connRef787 = new ConnRef(router, 787);
+ ConnEnd srcPt787(Point(723.246, 514.918), 15);
+ connRef787->setSourceEndpoint(srcPt787);
+ ConnEnd dstPt787(Point(645.246, 514.918), 15);
+ connRef787->setDestEndpoint(dstPt787);
+ connRef787->setRoutingType((ConnType)2);
+
+ ConnRef *connRef788 = new ConnRef(router, 788);
+ ConnEnd srcPt788(Point(723.246, 482.918), 15);
+ connRef788->setSourceEndpoint(srcPt788);
+ ConnEnd dstPt788(Point(645.246, 482.918), 15);
+ connRef788->setDestEndpoint(dstPt788);
+ connRef788->setRoutingType((ConnType)2);
+
+ ConnRef *connRef789 = new ConnRef(router, 789);
+ ConnEnd srcPt789(Point(771.246, 418.918), 15);
+ connRef789->setSourceEndpoint(srcPt789);
+ ConnEnd dstPt789(Point(693.246, 418.918), 15);
+ connRef789->setDestEndpoint(dstPt789);
+ connRef789->setRoutingType((ConnType)2);
+
+ ConnRef *connRef790 = new ConnRef(router, 790);
+ ConnEnd srcPt790(Point(723.246, 418.918), 15);
+ connRef790->setSourceEndpoint(srcPt790);
+ ConnEnd dstPt790(Point(645.246, 418.918), 15);
+ connRef790->setDestEndpoint(dstPt790);
+ connRef790->setRoutingType((ConnType)2);
+
+ ConnRef *connRef791 = new ConnRef(router, 791);
+ ConnEnd srcPt791(Point(723.246, 386.918), 15);
+ connRef791->setSourceEndpoint(srcPt791);
+ ConnEnd dstPt791(Point(645.246, 386.918), 15);
+ connRef791->setDestEndpoint(dstPt791);
+ connRef791->setRoutingType((ConnType)2);
+
+ ConnRef *connRef792 = new ConnRef(router, 792);
+ ConnEnd srcPt792(Point(693.246, 202.918), 15);
+ connRef792->setSourceEndpoint(srcPt792);
+ ConnEnd dstPt792(Point(693.246, 256.918), 15);
+ connRef792->setDestEndpoint(dstPt792);
+ connRef792->setRoutingType((ConnType)2);
+
+ ConnRef *connRef793 = new ConnRef(router, 793);
+ ConnEnd srcPt793(Point(645.246, 192.918), 15);
+ connRef793->setSourceEndpoint(srcPt793);
+ ConnEnd dstPt793(Point(645.246, 278.918), 15);
+ connRef793->setDestEndpoint(dstPt793);
+ connRef793->setRoutingType((ConnType)2);
+
+ ConnRef *connRef794 = new ConnRef(router, 794);
+ ConnEnd srcPt794(Point(645.246, 128.918), 15);
+ connRef794->setSourceEndpoint(srcPt794);
+ ConnEnd dstPt794(Point(645.246, 246.918), 15);
+ connRef794->setDestEndpoint(dstPt794);
+ connRef794->setRoutingType((ConnType)2);
+
+ ConnRef *connRef795 = new ConnRef(router, 795);
+ ConnEnd srcPt795(Point(615.246, 590.918), 15);
+ connRef795->setSourceEndpoint(srcPt795);
+ ConnEnd dstPt795(Point(537.246, 590.918), 15);
+ connRef795->setDestEndpoint(dstPt795);
+ connRef795->setRoutingType((ConnType)2);
+
+ ConnRef *connRef796 = new ConnRef(router, 796);
+ ConnEnd srcPt796(Point(567.246, 622.918), 15);
+ connRef796->setSourceEndpoint(srcPt796);
+ ConnEnd dstPt796(Point(489.246, 622.918), 15);
+ connRef796->setDestEndpoint(dstPt796);
+ connRef796->setRoutingType((ConnType)2);
+
+ ConnRef *connRef797 = new ConnRef(router, 797);
+ ConnEnd srcPt797(Point(567.246, 590.918), 15);
+ connRef797->setSourceEndpoint(srcPt797);
+ ConnEnd dstPt797(Point(489.246, 590.918), 15);
+ connRef797->setDestEndpoint(dstPt797);
+ connRef797->setRoutingType((ConnType)2);
+
+ ConnRef *connRef798 = new ConnRef(router, 798);
+ ConnEnd srcPt798(Point(615.246, 486.951), 15);
+ connRef798->setSourceEndpoint(srcPt798);
+ ConnEnd dstPt798(Point(537.246, 486.951), 15);
+ connRef798->setDestEndpoint(dstPt798);
+ connRef798->setRoutingType((ConnType)2);
+
+ ConnRef *connRef799 = new ConnRef(router, 799);
+ ConnEnd srcPt799(Point(567.246, 514.918), 15);
+ connRef799->setSourceEndpoint(srcPt799);
+ ConnEnd dstPt799(Point(489.246, 514.918), 15);
+ connRef799->setDestEndpoint(dstPt799);
+ connRef799->setRoutingType((ConnType)2);
+
+ ConnRef *connRef800 = new ConnRef(router, 800);
+ ConnEnd srcPt800(Point(567.246, 482.918), 15);
+ connRef800->setSourceEndpoint(srcPt800);
+ ConnEnd dstPt800(Point(489.246, 482.918), 15);
+ connRef800->setDestEndpoint(dstPt800);
+ connRef800->setRoutingType((ConnType)2);
+
+ ConnRef *connRef801 = new ConnRef(router, 801);
+ ConnEnd srcPt801(Point(615.246, 418.918), 15);
+ connRef801->setSourceEndpoint(srcPt801);
+ ConnEnd dstPt801(Point(537.246, 418.918), 15);
+ connRef801->setDestEndpoint(dstPt801);
+ connRef801->setRoutingType((ConnType)2);
+
+ ConnRef *connRef802 = new ConnRef(router, 802);
+ ConnEnd srcPt802(Point(567.246, 418.918), 15);
+ connRef802->setSourceEndpoint(srcPt802);
+ ConnEnd dstPt802(Point(489.246, 418.918), 15);
+ connRef802->setDestEndpoint(dstPt802);
+ connRef802->setRoutingType((ConnType)2);
+
+ ConnRef *connRef803 = new ConnRef(router, 803);
+ ConnEnd srcPt803(Point(567.246, 386.918), 15);
+ connRef803->setSourceEndpoint(srcPt803);
+ ConnEnd dstPt803(Point(489.246, 386.918), 15);
+ connRef803->setDestEndpoint(dstPt803);
+ connRef803->setRoutingType((ConnType)2);
+
+ ConnRef *connRef804 = new ConnRef(router, 804);
+ ConnEnd srcPt804(Point(537.246, 202.918), 15);
+ connRef804->setSourceEndpoint(srcPt804);
+ ConnEnd dstPt804(Point(537.246, 256.918), 15);
+ connRef804->setDestEndpoint(dstPt804);
+ connRef804->setRoutingType((ConnType)2);
+
+ ConnRef *connRef805 = new ConnRef(router, 805);
+ ConnEnd srcPt805(Point(489.246, 192.918), 15);
+ connRef805->setSourceEndpoint(srcPt805);
+ ConnEnd dstPt805(Point(489.246, 278.918), 15);
+ connRef805->setDestEndpoint(dstPt805);
+ connRef805->setRoutingType((ConnType)2);
+
+ ConnRef *connRef806 = new ConnRef(router, 806);
+ ConnEnd srcPt806(Point(489.246, 128.918), 15);
+ connRef806->setSourceEndpoint(srcPt806);
+ ConnEnd dstPt806(Point(489.246, 246.918), 15);
+ connRef806->setDestEndpoint(dstPt806);
+ connRef806->setRoutingType((ConnType)2);
+
+ ConnRef *connRef807 = new ConnRef(router, 807);
+ ConnEnd srcPt807(Point(459.246, 590.918), 15);
+ connRef807->setSourceEndpoint(srcPt807);
+ ConnEnd dstPt807(Point(381.246, 590.918), 15);
+ connRef807->setDestEndpoint(dstPt807);
+ connRef807->setRoutingType((ConnType)2);
+
+ ConnRef *connRef808 = new ConnRef(router, 808);
+ ConnEnd srcPt808(Point(411.246, 622.918), 15);
+ connRef808->setSourceEndpoint(srcPt808);
+ ConnEnd dstPt808(Point(333.246, 622.918), 15);
+ connRef808->setDestEndpoint(dstPt808);
+ connRef808->setRoutingType((ConnType)2);
+
+ ConnRef *connRef809 = new ConnRef(router, 809);
+ ConnEnd srcPt809(Point(411.246, 590.918), 15);
+ connRef809->setSourceEndpoint(srcPt809);
+ ConnEnd dstPt809(Point(333.246, 590.918), 15);
+ connRef809->setDestEndpoint(dstPt809);
+ connRef809->setRoutingType((ConnType)2);
+
+ ConnRef *connRef810 = new ConnRef(router, 810);
+ ConnEnd srcPt810(Point(411.246, 514.918), 15);
+ connRef810->setSourceEndpoint(srcPt810);
+ ConnEnd dstPt810(Point(333.246, 514.918), 15);
+ connRef810->setDestEndpoint(dstPt810);
+ connRef810->setRoutingType((ConnType)2);
+
+ ConnRef *connRef811 = new ConnRef(router, 811);
+ ConnEnd srcPt811(Point(411.246, 482.918), 15);
+ connRef811->setSourceEndpoint(srcPt811);
+ ConnEnd dstPt811(Point(333.246, 482.918), 15);
+ connRef811->setDestEndpoint(dstPt811);
+ connRef811->setRoutingType((ConnType)2);
+
+ ConnRef *connRef812 = new ConnRef(router, 812);
+ ConnEnd srcPt812(Point(459.246, 418.918), 15);
+ connRef812->setSourceEndpoint(srcPt812);
+ ConnEnd dstPt812(Point(381.246, 418.918), 15);
+ connRef812->setDestEndpoint(dstPt812);
+ connRef812->setRoutingType((ConnType)2);
+
+ ConnRef *connRef813 = new ConnRef(router, 813);
+ ConnEnd srcPt813(Point(411.246, 418.918), 15);
+ connRef813->setSourceEndpoint(srcPt813);
+ ConnEnd dstPt813(Point(333.246, 418.918), 15);
+ connRef813->setDestEndpoint(dstPt813);
+ connRef813->setRoutingType((ConnType)2);
+
+ ConnRef *connRef814 = new ConnRef(router, 814);
+ ConnEnd srcPt814(Point(411.246, 386.918), 15);
+ connRef814->setSourceEndpoint(srcPt814);
+ ConnEnd dstPt814(Point(333.246, 386.918), 15);
+ connRef814->setDestEndpoint(dstPt814);
+ connRef814->setRoutingType((ConnType)2);
+
+ ConnRef *connRef815 = new ConnRef(router, 815);
+ ConnEnd srcPt815(Point(381.246, 202.918), 15);
+ connRef815->setSourceEndpoint(srcPt815);
+ ConnEnd dstPt815(Point(381.246, 256.918), 15);
+ connRef815->setDestEndpoint(dstPt815);
+ connRef815->setRoutingType((ConnType)2);
+
+ ConnRef *connRef816 = new ConnRef(router, 816);
+ ConnEnd srcPt816(Point(333.246, 192.918), 15);
+ connRef816->setSourceEndpoint(srcPt816);
+ ConnEnd dstPt816(Point(333.246, 278.918), 15);
+ connRef816->setDestEndpoint(dstPt816);
+ connRef816->setRoutingType((ConnType)2);
+
+ ConnRef *connRef817 = new ConnRef(router, 817);
+ ConnEnd srcPt817(Point(333.246, 128.918), 15);
+ connRef817->setSourceEndpoint(srcPt817);
+ ConnEnd dstPt817(Point(333.246, 246.918), 15);
+ connRef817->setDestEndpoint(dstPt817);
+ connRef817->setRoutingType((ConnType)2);
+
+ ConnRef *connRef818 = new ConnRef(router, 818);
+ ConnEnd srcPt818(Point(303.246, 590.918), 15);
+ connRef818->setSourceEndpoint(srcPt818);
+ ConnEnd dstPt818(Point(225.246, 590.918), 15);
+ connRef818->setDestEndpoint(dstPt818);
+ connRef818->setRoutingType((ConnType)2);
+
+ ConnRef *connRef819 = new ConnRef(router, 819);
+ ConnEnd srcPt819(Point(255.246, 622.918), 15);
+ connRef819->setSourceEndpoint(srcPt819);
+ ConnEnd dstPt819(Point(193.246, 622.918), 15);
+ connRef819->setDestEndpoint(dstPt819);
+ connRef819->setRoutingType((ConnType)2);
+
+ ConnRef *connRef820 = new ConnRef(router, 820);
+ ConnEnd srcPt820(Point(255.246, 590.918), 15);
+ connRef820->setSourceEndpoint(srcPt820);
+ ConnEnd dstPt820(Point(193.246, 590.918), 15);
+ connRef820->setDestEndpoint(dstPt820);
+ connRef820->setRoutingType((ConnType)2);
+
+ ConnRef *connRef821 = new ConnRef(router, 821);
+ ConnEnd srcPt821(Point(255.246, 514.918), 15);
+ connRef821->setSourceEndpoint(srcPt821);
+ ConnEnd dstPt821(Point(193.246, 514.918), 15);
+ connRef821->setDestEndpoint(dstPt821);
+ connRef821->setRoutingType((ConnType)2);
+
+ ConnRef *connRef822 = new ConnRef(router, 822);
+ ConnEnd srcPt822(Point(255.246, 482.918), 15);
+ connRef822->setSourceEndpoint(srcPt822);
+ ConnEnd dstPt822(Point(193.246, 482.918), 15);
+ connRef822->setDestEndpoint(dstPt822);
+ connRef822->setRoutingType((ConnType)2);
+
+ ConnRef *connRef823 = new ConnRef(router, 823);
+ ConnEnd srcPt823(Point(303.246, 418.918), 15);
+ connRef823->setSourceEndpoint(srcPt823);
+ ConnEnd dstPt823(Point(225.246, 418.918), 15);
+ connRef823->setDestEndpoint(dstPt823);
+ connRef823->setRoutingType((ConnType)2);
+
+ ConnRef *connRef824 = new ConnRef(router, 824);
+ ConnEnd srcPt824(Point(255.246, 418.918), 15);
+ connRef824->setSourceEndpoint(srcPt824);
+ ConnEnd dstPt824(Point(193.246, 418.918), 15);
+ connRef824->setDestEndpoint(dstPt824);
+ connRef824->setRoutingType((ConnType)2);
+
+ ConnRef *connRef825 = new ConnRef(router, 825);
+ ConnEnd srcPt825(Point(255.246, 386.918), 15);
+ connRef825->setSourceEndpoint(srcPt825);
+ ConnEnd dstPt825(Point(193.246, 386.918), 15);
+ connRef825->setDestEndpoint(dstPt825);
+ connRef825->setRoutingType((ConnType)2);
+
+ ConnRef *connRef826 = new ConnRef(router, 826);
+ ConnEnd srcPt826(Point(303.246, 256.918), 15);
+ connRef826->setSourceEndpoint(srcPt826);
+ ConnEnd dstPt826(Point(225.246, 256.918), 15);
+ connRef826->setDestEndpoint(dstPt826);
+ connRef826->setRoutingType((ConnType)2);
+
+ ConnRef *connRef827 = new ConnRef(router, 827);
+ ConnEnd srcPt827(Point(193.246, 128.918), 15);
+ connRef827->setSourceEndpoint(srcPt827);
+ ConnEnd dstPt827(Point(193.246, 246.918), 15);
+ connRef827->setDestEndpoint(dstPt827);
+ connRef827->setRoutingType((ConnType)2);
+
+ ConnRef *connRef828 = new ConnRef(router, 828);
+ ConnEnd srcPt828(Point(193.246, 192.918), 15);
+ connRef828->setSourceEndpoint(srcPt828);
+ ConnEnd dstPt828(Point(193.246, 278.918), 15);
+ connRef828->setDestEndpoint(dstPt828);
+ connRef828->setRoutingType((ConnType)2);
+
+ ConnRef *connRef829 = new ConnRef(router, 829);
+ ConnEnd srcPt829(Point(145.246, 590.918), 15);
+ connRef829->setSourceEndpoint(srcPt829);
+ ConnEnd dstPt829(Point(67.2456, 590.918), 15);
+ connRef829->setDestEndpoint(dstPt829);
+ connRef829->setRoutingType((ConnType)2);
+
+ ConnRef *connRef830 = new ConnRef(router, 830);
+ ConnEnd srcPt830(Point(97.2456, 622.918), 15);
+ connRef830->setSourceEndpoint(srcPt830);
+ ConnEnd dstPt830(Point(17.2456, 622.918), 15);
+ connRef830->setDestEndpoint(dstPt830);
+ connRef830->setRoutingType((ConnType)2);
+
+ ConnRef *connRef831 = new ConnRef(router, 831);
+ ConnEnd srcPt831(Point(97.2456, 590.918), 15);
+ connRef831->setSourceEndpoint(srcPt831);
+ ConnEnd dstPt831(Point(17.2456, 590.918), 15);
+ connRef831->setDestEndpoint(dstPt831);
+ connRef831->setRoutingType((ConnType)2);
+
+ ConnRef *connRef832 = new ConnRef(router, 832);
+ ConnEnd srcPt832(Point(97.2456, 514.918), 15);
+ connRef832->setSourceEndpoint(srcPt832);
+ ConnEnd dstPt832(Point(17.2456, 514.918), 15);
+ connRef832->setDestEndpoint(dstPt832);
+ connRef832->setRoutingType((ConnType)2);
+
+ ConnRef *connRef833 = new ConnRef(router, 833);
+ ConnEnd srcPt833(Point(97.2456, 482.918), 15);
+ connRef833->setSourceEndpoint(srcPt833);
+ ConnEnd dstPt833(Point(17.2456, 482.918), 15);
+ connRef833->setDestEndpoint(dstPt833);
+ connRef833->setRoutingType((ConnType)2);
+
+ ConnRef *connRef834 = new ConnRef(router, 834);
+ ConnEnd srcPt834(Point(145.246, 418.918), 15);
+ connRef834->setSourceEndpoint(srcPt834);
+ ConnEnd dstPt834(Point(67.2456, 418.918), 15);
+ connRef834->setDestEndpoint(dstPt834);
+ connRef834->setRoutingType((ConnType)2);
+
+ ConnRef *connRef835 = new ConnRef(router, 835);
+ ConnEnd srcPt835(Point(97.2456, 418.918), 15);
+ connRef835->setSourceEndpoint(srcPt835);
+ ConnEnd dstPt835(Point(17.2456, 418.918), 15);
+ connRef835->setDestEndpoint(dstPt835);
+ connRef835->setRoutingType((ConnType)2);
+
+ ConnRef *connRef836 = new ConnRef(router, 836);
+ ConnEnd srcPt836(Point(97.2456, 386.918), 15);
+ connRef836->setSourceEndpoint(srcPt836);
+ ConnEnd dstPt836(Point(17.2456, 386.918), 15);
+ connRef836->setDestEndpoint(dstPt836);
+ connRef836->setRoutingType((ConnType)2);
+
+ ConnRef *connRef837 = new ConnRef(router, 837);
+ ConnEnd srcPt837(Point(17.2456, 192.918), 15);
+ connRef837->setSourceEndpoint(srcPt837);
+ ConnEnd dstPt837(Point(17.2456, 278.918), 15);
+ connRef837->setDestEndpoint(dstPt837);
+ connRef837->setRoutingType((ConnType)2);
+
+ ConnRef *connRef838 = new ConnRef(router, 838);
+ ConnEnd srcPt838(Point(17.2456, 128.918), 15);
+ connRef838->setSourceEndpoint(srcPt838);
+ ConnEnd dstPt838(Point(17.2456, 246.918), 15);
+ connRef838->setDestEndpoint(dstPt838);
+ connRef838->setRoutingType((ConnType)2);
+
+ ConnRef *connRef839 = new ConnRef(router, 839);
+ ConnEnd srcPt839(Point(285.246, 170.918), 15);
+ connRef839->setSourceEndpoint(srcPt839);
+ ConnEnd dstPt839(Point(244.976, 170.918), 15);
+ connRef839->setDestEndpoint(dstPt839);
+ connRef839->setRoutingType((ConnType)2);
+
+ ConnRef *connRef840 = new ConnRef(router, 840);
+ ConnEnd srcPt840(Point(237.246, 86.9179), 15);
+ connRef840->setSourceEndpoint(srcPt840);
+ ConnEnd dstPt840(Point(145.246, 86.9179), 15);
+ connRef840->setDestEndpoint(dstPt840);
+ connRef840->setRoutingType((ConnType)2);
+
+ ConnRef *connRef841 = new ConnRef(router, 841);
+ ConnEnd srcPt841(Point(237.246, 54.9179), 15);
+ connRef841->setSourceEndpoint(srcPt841);
+ ConnEnd dstPt841(Point(145.246, 54.9179), 15);
+ connRef841->setDestEndpoint(dstPt841);
+ connRef841->setRoutingType((ConnType)2);
+
+ ConnRef *connRef842 = new ConnRef(router, 842);
+ ConnEnd srcPt842(Point(97.2456, 170.918), 15);
+ connRef842->setSourceEndpoint(srcPt842);
+ ConnEnd dstPt842(Point(17.2456, 170.918), 15);
+ connRef842->setDestEndpoint(dstPt842);
+ connRef842->setRoutingType((ConnType)2);
+
+ ConnRef *connRef843 = new ConnRef(router, 843);
+ ConnEnd srcPt843(Point(97.2456, 32.9179), 15);
+ connRef843->setSourceEndpoint(srcPt843);
+ ConnEnd dstPt843(Point(17.2456, 32.9179), 15);
+ connRef843->setDestEndpoint(dstPt843);
+ connRef843->setRoutingType((ConnType)2);
+
+ ConnRef *connRef844 = new ConnRef(router, 844);
+ ConnEnd srcPt844(Point(97.2456, 0.917947), 15);
+ connRef844->setSourceEndpoint(srcPt844);
+ ConnEnd dstPt844(Point(17.2456, 0.917947), 15);
+ connRef844->setDestEndpoint(dstPt844);
+ connRef844->setRoutingType((ConnType)2);
+
+ ConnRef *connRef845 = new ConnRef(router, 845);
+ ConnEnd srcPt845(Point(380.962, -29.0821), 15);
+ connRef845->setSourceEndpoint(srcPt845);
+ ConnEnd dstPt845(Point(319.219, -29.0821), 15);
+ connRef845->setDestEndpoint(dstPt845);
+ connRef845->setRoutingType((ConnType)2);
+
+ ConnRef *connRef846 = new ConnRef(router, 846);
+ ConnEnd srcPt846(Point(279.219, -29.0821), 15);
+ connRef846->setSourceEndpoint(srcPt846);
+ ConnEnd dstPt846(Point(197.246, -29.0821), 15);
+ connRef846->setDestEndpoint(dstPt846);
+ connRef846->setRoutingType((ConnType)2);
+
+ ConnRef *connRef847 = new ConnRef(router, 847);
+ ConnEnd srcPt847(Point(97.2456, 310.918), 15);
+ connRef847->setSourceEndpoint(srcPt847);
+ ConnEnd dstPt847(Point(17.2456, 310.918), 15);
+ connRef847->setDestEndpoint(dstPt847);
+ connRef847->setRoutingType((ConnType)2);
+
+ ConnRef *connRef848 = new ConnRef(router, 848);
+ ConnEnd srcPt848(Point(193.246, 224.918), 15);
+ connRef848->setSourceEndpoint(srcPt848);
+ ConnEnd dstPt848(Point(193.246, 310.918), 15);
+ connRef848->setDestEndpoint(dstPt848);
+ connRef848->setRoutingType((ConnType)2);
+
+ ConnRef *connRef849 = new ConnRef(router, 849);
+ ConnEnd srcPt849(Point(333.246, 224.918), 15);
+ connRef849->setSourceEndpoint(srcPt849);
+ ConnEnd dstPt849(Point(333.246, 310.918), 15);
+ connRef849->setDestEndpoint(dstPt849);
+ connRef849->setRoutingType((ConnType)2);
+
+ ConnRef *connRef850 = new ConnRef(router, 850);
+ ConnEnd srcPt850(Point(489.246, 224.918), 15);
+ connRef850->setSourceEndpoint(srcPt850);
+ ConnEnd dstPt850(Point(489.246, 310.918), 15);
+ connRef850->setDestEndpoint(dstPt850);
+ connRef850->setRoutingType((ConnType)2);
+
+ ConnRef *connRef851 = new ConnRef(router, 851);
+ ConnEnd srcPt851(Point(645.246, 224.918), 15);
+ connRef851->setSourceEndpoint(srcPt851);
+ ConnEnd dstPt851(Point(645.246, 310.918), 15);
+ connRef851->setDestEndpoint(dstPt851);
+ connRef851->setRoutingType((ConnType)2);
+
+ ConnRef *connRef852 = new ConnRef(router, 852);
+ ConnEnd srcPt852(Point(801.246, 224.918), 15);
+ connRef852->setSourceEndpoint(srcPt852);
+ ConnEnd dstPt852(Point(801.246, 310.918), 15);
+ connRef852->setDestEndpoint(dstPt852);
+ connRef852->setRoutingType((ConnType)2);
+
+ ConnRef *connRef853 = new ConnRef(router, 853);
+ ConnEnd srcPt853(Point(957.246, 224.918), 15);
+ connRef853->setSourceEndpoint(srcPt853);
+ ConnEnd dstPt853(Point(957.246, 310.918), 15);
+ connRef853->setDestEndpoint(dstPt853);
+ connRef853->setRoutingType((ConnType)2);
+
+ ConnRef *connRef854 = new ConnRef(router, 854);
+ ConnEnd srcPt854(Point(17.2456, 364.918), 15);
+ connRef854->setSourceEndpoint(srcPt854);
+ ConnEnd dstPt854(Point(17.2456, 450.918), 15);
+ connRef854->setDestEndpoint(dstPt854);
+ connRef854->setRoutingType((ConnType)2);
+
+ ConnRef *connRef855 = new ConnRef(router, 855);
+ ConnEnd srcPt855(Point(255.246, 450.918), 15);
+ connRef855->setSourceEndpoint(srcPt855);
+ ConnEnd dstPt855(Point(193.246, 450.918), 15);
+ connRef855->setDestEndpoint(dstPt855);
+ connRef855->setRoutingType((ConnType)2);
+
+ ConnRef *connRef856 = new ConnRef(router, 856);
+ ConnEnd srcPt856(Point(411.246, 450.918), 15);
+ connRef856->setSourceEndpoint(srcPt856);
+ ConnEnd dstPt856(Point(333.246, 450.918), 15);
+ connRef856->setDestEndpoint(dstPt856);
+ connRef856->setRoutingType((ConnType)2);
+
+ ConnRef *connRef857 = new ConnRef(router, 857);
+ ConnEnd srcPt857(Point(567.246, 450.918), 15);
+ connRef857->setSourceEndpoint(srcPt857);
+ ConnEnd dstPt857(Point(489.246, 450.918), 15);
+ connRef857->setDestEndpoint(dstPt857);
+ connRef857->setRoutingType((ConnType)2);
+
+ ConnRef *connRef858 = new ConnRef(router, 858);
+ ConnEnd srcPt858(Point(879.246, 450.918), 15);
+ connRef858->setSourceEndpoint(srcPt858);
+ ConnEnd dstPt858(Point(801.246, 450.918), 15);
+ connRef858->setDestEndpoint(dstPt858);
+ connRef858->setRoutingType((ConnType)2);
+
+ ConnRef *connRef859 = new ConnRef(router, 859);
+ ConnEnd srcPt859(Point(1035.25, 450.918), 15);
+ connRef859->setSourceEndpoint(srcPt859);
+ ConnEnd dstPt859(Point(957.246, 450.918), 15);
+ connRef859->setDestEndpoint(dstPt859);
+ connRef859->setRoutingType((ConnType)2);
+
+ ConnRef *connRef860 = new ConnRef(router, 860);
+ ConnEnd srcPt860(Point(723.246, 450.918), 15);
+ connRef860->setSourceEndpoint(srcPt860);
+ ConnEnd dstPt860(Point(645.246, 450.918), 15);
+ connRef860->setDestEndpoint(dstPt860);
+ connRef860->setRoutingType((ConnType)2);
+
+ ConnRef *connRef861 = new ConnRef(router, 861);
+ ConnEnd srcPt861(Point(97.2456, 558.918), 15);
+ connRef861->setSourceEndpoint(srcPt861);
+ ConnEnd dstPt861(Point(17.2456, 558.918), 15);
+ connRef861->setDestEndpoint(dstPt861);
+ connRef861->setRoutingType((ConnType)2);
+
+ ConnRef *connRef862 = new ConnRef(router, 862);
+ ConnEnd srcPt862(Point(255.246, 558.918), 15);
+ connRef862->setSourceEndpoint(srcPt862);
+ ConnEnd dstPt862(Point(193.246, 558.918), 15);
+ connRef862->setDestEndpoint(dstPt862);
+ connRef862->setRoutingType((ConnType)2);
+
+ ConnRef *connRef863 = new ConnRef(router, 863);
+ ConnEnd srcPt863(Point(411.246, 558.918), 15);
+ connRef863->setSourceEndpoint(srcPt863);
+ ConnEnd dstPt863(Point(333.246, 558.918), 15);
+ connRef863->setDestEndpoint(dstPt863);
+ connRef863->setRoutingType((ConnType)2);
+
+ ConnRef *connRef864 = new ConnRef(router, 864);
+ ConnEnd srcPt864(Point(567.246, 558.918), 15);
+ connRef864->setSourceEndpoint(srcPt864);
+ ConnEnd dstPt864(Point(489.246, 558.918), 15);
+ connRef864->setDestEndpoint(dstPt864);
+ connRef864->setRoutingType((ConnType)2);
+
+ ConnRef *connRef865 = new ConnRef(router, 865);
+ ConnEnd srcPt865(Point(723.246, 558.918), 15);
+ connRef865->setSourceEndpoint(srcPt865);
+ ConnEnd dstPt865(Point(645.246, 558.918), 15);
+ connRef865->setDestEndpoint(dstPt865);
+ connRef865->setRoutingType((ConnType)2);
+
+ ConnRef *connRef866 = new ConnRef(router, 866);
+ ConnEnd srcPt866(Point(879.246, 558.918), 15);
+ connRef866->setSourceEndpoint(srcPt866);
+ ConnEnd dstPt866(Point(801.246, 558.918), 15);
+ connRef866->setDestEndpoint(dstPt866);
+ connRef866->setRoutingType((ConnType)2);
+
+ ConnRef *connRef867 = new ConnRef(router, 867);
+ ConnEnd srcPt867(Point(1035.25, 558.918), 15);
+ connRef867->setSourceEndpoint(srcPt867);
+ ConnEnd dstPt867(Point(957.246, 558.918), 15);
+ connRef867->setDestEndpoint(dstPt867);
+ connRef867->setRoutingType((ConnType)2);
+
+ ConnRef *connRef868 = new ConnRef(router, 868);
+ ConnEnd srcPt868(Point(97.2456, 654.918), 15);
+ connRef868->setSourceEndpoint(srcPt868);
+ ConnEnd dstPt868(Point(17.2456, 654.918), 15);
+ connRef868->setDestEndpoint(dstPt868);
+ connRef868->setRoutingType((ConnType)2);
+
+ ConnRef *connRef869 = new ConnRef(router, 869);
+ ConnEnd srcPt869(Point(255.246, 654.918), 15);
+ connRef869->setSourceEndpoint(srcPt869);
+ ConnEnd dstPt869(Point(193.246, 654.918), 15);
+ connRef869->setDestEndpoint(dstPt869);
+ connRef869->setRoutingType((ConnType)2);
+
+ ConnRef *connRef870 = new ConnRef(router, 870);
+ ConnEnd srcPt870(Point(411.246, 654.918), 15);
+ connRef870->setSourceEndpoint(srcPt870);
+ ConnEnd dstPt870(Point(333.246, 654.918), 15);
+ connRef870->setDestEndpoint(dstPt870);
+ connRef870->setRoutingType((ConnType)2);
+
+ ConnRef *connRef871 = new ConnRef(router, 871);
+ ConnEnd srcPt871(Point(567.246, 654.918), 15);
+ connRef871->setSourceEndpoint(srcPt871);
+ ConnEnd dstPt871(Point(489.246, 654.918), 15);
+ connRef871->setDestEndpoint(dstPt871);
+ connRef871->setRoutingType((ConnType)2);
+
+ ConnRef *connRef872 = new ConnRef(router, 872);
+ ConnEnd srcPt872(Point(723.246, 654.918), 15);
+ connRef872->setSourceEndpoint(srcPt872);
+ ConnEnd dstPt872(Point(645.246, 654.918), 15);
+ connRef872->setDestEndpoint(dstPt872);
+ connRef872->setRoutingType((ConnType)2);
+
+ ConnRef *connRef873 = new ConnRef(router, 873);
+ ConnEnd srcPt873(Point(879.246, 654.918), 15);
+ connRef873->setSourceEndpoint(srcPt873);
+ ConnEnd dstPt873(Point(801.246, 654.918), 15);
+ connRef873->setDestEndpoint(dstPt873);
+ connRef873->setRoutingType((ConnType)2);
+
+ ConnRef *connRef874 = new ConnRef(router, 874);
+ ConnEnd srcPt874(Point(1035.25, 654.918), 15);
+ connRef874->setSourceEndpoint(srcPt874);
+ ConnEnd dstPt874(Point(957.246, 654.918), 15);
+ connRef874->setDestEndpoint(dstPt874);
+ connRef874->setRoutingType((ConnType)2);
+
+ ConnRef *connRef875 = new ConnRef(router, 875);
+ ConnEnd srcPt875(Point(1233.25, 192.918), 15);
+ connRef875->setSourceEndpoint(srcPt875);
+ ConnEnd dstPt875(Point(1233.25, 278.918), 15);
+ connRef875->setDestEndpoint(dstPt875);
+ connRef875->setRoutingType((ConnType)2);
+
+ ConnRef *connRef876 = new ConnRef(router, 876);
+ ConnEnd srcPt876(Point(1323.25, 418.918), 15);
+ connRef876->setSourceEndpoint(srcPt876);
+ ConnEnd dstPt876(Point(1233.25, 418.918), 15);
+ connRef876->setDestEndpoint(dstPt876);
+ connRef876->setRoutingType((ConnType)2);
+
+ ConnRef *connRef877 = new ConnRef(router, 877);
+ ConnEnd srcPt877(Point(1323.25, 514.918), 15);
+ connRef877->setSourceEndpoint(srcPt877);
+ ConnEnd dstPt877(Point(1233.25, 514.918), 15);
+ connRef877->setDestEndpoint(dstPt877);
+ connRef877->setRoutingType((ConnType)2);
+
+ ConnRef *connRef878 = new ConnRef(router, 878);
+ ConnEnd srcPt878(Point(1323.25, 622.918), 15);
+ connRef878->setSourceEndpoint(srcPt878);
+ ConnEnd dstPt878(Point(1233.25, 622.918), 15);
+ connRef878->setDestEndpoint(dstPt878);
+ connRef878->setRoutingType((ConnType)2);
+
+ ConnRef *connRef879 = new ConnRef(router, 879);
+ ConnEnd srcPt879(Point(1035.25, 718.918), 15);
+ connRef879->setSourceEndpoint(srcPt879);
+ ConnEnd dstPt879(Point(957.246, 718.918), 15);
+ connRef879->setDestEndpoint(dstPt879);
+ connRef879->setRoutingType((ConnType)2);
+
+ ConnRef *connRef880 = new ConnRef(router, 880);
+ ConnEnd srcPt880(Point(1035.25, 750.918), 15);
+ connRef880->setSourceEndpoint(srcPt880);
+ ConnEnd dstPt880(Point(957.246, 750.918), 15);
+ connRef880->setDestEndpoint(dstPt880);
+ connRef880->setRoutingType((ConnType)2);
+
+ ConnRef *connRef881 = new ConnRef(router, 881);
+ ConnEnd srcPt881(Point(1323.25, 718.918), 15);
+ connRef881->setSourceEndpoint(srcPt881);
+ ConnEnd dstPt881(Point(1233.25, 718.918), 15);
+ connRef881->setDestEndpoint(dstPt881);
+ connRef881->setRoutingType((ConnType)2);
+
+ ConnRef *connRef882 = new ConnRef(router, 882);
+ ConnEnd srcPt882(Point(1293.25, 202.918), 15);
+ connRef882->setSourceEndpoint(srcPt882);
+ ConnEnd dstPt882(Point(1293.25, 256.918), 15);
+ connRef882->setDestEndpoint(dstPt882);
+ connRef882->setRoutingType((ConnType)2);
+
+ ConnRef *connRef883 = new ConnRef(router, 883);
+ ConnEnd srcPt883(Point(1419.25, 644.918), 15);
+ connRef883->setSourceEndpoint(srcPt883);
+ ConnEnd dstPt883(Point(1293.25, 644.918), 15);
+ connRef883->setDestEndpoint(dstPt883);
+ connRef883->setRoutingType((ConnType)2);
+
+ ConnRef *connRef884 = new ConnRef(router, 884);
+ ConnEnd srcPt884(Point(145.246, 246.918), 15);
+ connRef884->setSourceEndpoint(srcPt884);
+ ConnEnd dstPt884(Point(67.2456, 246.918), 15);
+ connRef884->setDestEndpoint(dstPt884);
+ connRef884->setRoutingType((ConnType)2);
+
+ ConnRef *connRef885 = new ConnRef(router, 885);
+ ConnEnd srcPt885(Point(145.246, 278.918), 15);
+ connRef885->setSourceEndpoint(srcPt885);
+ ConnEnd dstPt885(Point(67.2456, 278.918), 15);
+ connRef885->setDestEndpoint(dstPt885);
+ connRef885->setRoutingType((ConnType)2);
+
+ ConnRef *connRef886 = new ConnRef(router, 886);
+ ConnEnd srcPt886(Point(823.246, 676.918), 15);
+ connRef886->setSourceEndpoint(srcPt886);
+ ConnEnd dstPt886(Point(790, 667), 15);
+ connRef886->setDestEndpoint(dstPt886);
+ connRef886->setRoutingType((ConnType)2);
+
+ ConnRef *connRef887 = new ConnRef(router, 887);
+ ConnEnd srcPt887(Point(527.246, 676.918), 15);
+ connRef887->setSourceEndpoint(srcPt887);
+ ConnEnd dstPt887(Point(533, 667), 15);
+ connRef887->setDestEndpoint(dstPt887);
+ connRef887->setRoutingType((ConnType)2);
+
+ ConnRef *connRef888 = new ConnRef(router, 888);
+ ConnEnd srcPt888(Point(371.246, 676.918), 15);
+ connRef888->setSourceEndpoint(srcPt888);
+ ConnEnd dstPt888(Point(390, 667), 15);
+ connRef888->setDestEndpoint(dstPt888);
+ connRef888->setRoutingType((ConnType)2);
+
+ ConnRef *connRef889 = new ConnRef(router, 889);
+ ConnEnd srcPt889(Point(979.246, 676.918), 15);
+ connRef889->setSourceEndpoint(srcPt889);
+ ConnEnd dstPt889(Point(1030, 634), 15);
+ connRef889->setDestEndpoint(dstPt889);
+ connRef889->setRoutingType((ConnType)2);
+
+ ConnRef *connRef890 = new ConnRef(router, 890);
+ ConnEnd srcPt890(Point(673.933, 676.918), 15);
+ connRef890->setSourceEndpoint(srcPt890);
+ ConnEnd dstPt890(Point(649, 667), 15);
+ connRef890->setDestEndpoint(dstPt890);
+ connRef890->setRoutingType((ConnType)2);
+
+ ConnRef *connRef891 = new ConnRef(router, 891);
+ ConnEnd srcPt891(Point(823.246, 676.918), 15);
+ connRef891->setSourceEndpoint(srcPt891);
+ ConnEnd dstPt891(Point(840, 667), 15);
+ connRef891->setDestEndpoint(dstPt891);
+ connRef891->setRoutingType((ConnType)2);
+
+ ConnRef *connRef892 = new ConnRef(router, 892);
+ ConnEnd srcPt892(Point(57.2456, 125.987), 15);
+ connRef892->setSourceEndpoint(srcPt892);
+ ConnEnd dstPt892(Point(132, 175), 15);
+ connRef892->setDestEndpoint(dstPt892);
+ connRef892->setRoutingType((ConnType)2);
+
+ ConnRef *connRef893 = new ConnRef(router, 893);
+ ConnEnd srcPt893(Point(197.246, 160.918), 15);
+ connRef893->setSourceEndpoint(srcPt893);
+ ConnEnd dstPt893(Point(132, 318), 15);
+ connRef893->setDestEndpoint(dstPt893);
+ connRef893->setRoutingType((ConnType)2);
+
+ ConnRef *connRef894 = new ConnRef(router, 894);
+ ConnEnd srcPt894(Point(57.2456, 160.918), 15);
+ connRef894->setSourceEndpoint(srcPt894);
+ ConnEnd dstPt894(Point(132, 318), 15);
+ connRef894->setDestEndpoint(dstPt894);
+ connRef894->setRoutingType((ConnType)2);
+
+ ConnRef *connRef895 = new ConnRef(router, 895);
+ ConnEnd srcPt895(Point(197.246, 160.918), 15);
+ connRef895->setSourceEndpoint(srcPt895);
+ ConnEnd dstPt895(Point(972, 319), 15);
+ connRef895->setDestEndpoint(dstPt895);
+ connRef895->setRoutingType((ConnType)2);
+
+ ConnRef *connRef896 = new ConnRef(router, 896);
+ ConnEnd srcPt896(Point(823.246, 676.918), 15);
+ connRef896->setSourceEndpoint(srcPt896);
+ ConnEnd dstPt896(Point(972, 319), 15);
+ connRef896->setDestEndpoint(dstPt896);
+ connRef896->setRoutingType((ConnType)2);
+
+ ConnRef *connRef897 = new ConnRef(router, 897);
+ ConnEnd srcPt897(Point(197.246, 160.918), 15);
+ connRef897->setSourceEndpoint(srcPt897);
+ ConnEnd dstPt897(Point(830, 319), 15);
+ connRef897->setDestEndpoint(dstPt897);
+ connRef897->setRoutingType((ConnType)2);
+
+ ConnRef *connRef898 = new ConnRef(router, 898);
+ ConnEnd srcPt898(Point(673.933, 676.918), 15);
+ connRef898->setSourceEndpoint(srcPt898);
+ ConnEnd dstPt898(Point(830, 319), 15);
+ connRef898->setDestEndpoint(dstPt898);
+ connRef898->setRoutingType((ConnType)2);
+
+ ConnRef *connRef899 = new ConnRef(router, 899);
+ ConnEnd srcPt899(Point(197.246, 160.918), 15);
+ connRef899->setSourceEndpoint(srcPt899);
+ ConnEnd dstPt899(Point(689, 319), 15);
+ connRef899->setDestEndpoint(dstPt899);
+ connRef899->setRoutingType((ConnType)2);
+
+ ConnRef *connRef900 = new ConnRef(router, 900);
+ ConnEnd srcPt900(Point(527.246, 676.918), 15);
+ connRef900->setSourceEndpoint(srcPt900);
+ ConnEnd dstPt900(Point(689, 319), 15);
+ connRef900->setDestEndpoint(dstPt900);
+ connRef900->setRoutingType((ConnType)2);
+
+ ConnRef *connRef901 = new ConnRef(router, 901);
+ ConnEnd srcPt901(Point(197.246, 160.918), 15);
+ connRef901->setSourceEndpoint(srcPt901);
+ ConnEnd dstPt901(Point(547, 319), 15);
+ connRef901->setDestEndpoint(dstPt901);
+ connRef901->setRoutingType((ConnType)2);
+
+ ConnRef *connRef902 = new ConnRef(router, 902);
+ ConnEnd srcPt902(Point(371.246, 676.918), 15);
+ connRef902->setSourceEndpoint(srcPt902);
+ ConnEnd dstPt902(Point(547, 319), 15);
+ connRef902->setDestEndpoint(dstPt902);
+ connRef902->setRoutingType((ConnType)2);
+
+ ConnRef *connRef903 = new ConnRef(router, 903);
+ ConnEnd srcPt903(Point(197.246, 160.918), 15);
+ connRef903->setSourceEndpoint(srcPt903);
+ ConnEnd dstPt903(Point(405, 319), 15);
+ connRef903->setDestEndpoint(dstPt903);
+ connRef903->setRoutingType((ConnType)2);
+
+ ConnRef *connRef904 = new ConnRef(router, 904);
+ ConnEnd srcPt904(Point(215.246, 676.918), 15);
+ connRef904->setSourceEndpoint(srcPt904);
+ ConnEnd dstPt904(Point(405, 319), 15);
+ connRef904->setDestEndpoint(dstPt904);
+ connRef904->setRoutingType((ConnType)2);
+
+ ConnRef *connRef905 = new ConnRef(router, 905);
+ ConnEnd srcPt905(Point(197.246, 160.918), 15);
+ connRef905->setSourceEndpoint(srcPt905);
+ ConnEnd dstPt905(Point(273, 329), 15);
+ connRef905->setDestEndpoint(dstPt905);
+ connRef905->setRoutingType((ConnType)2);
+
+ ConnRef *connRef906 = new ConnRef(router, 906);
+ ConnEnd srcPt906(Point(57.2456, 676.918), 15);
+ connRef906->setSourceEndpoint(srcPt906);
+ ConnEnd dstPt906(Point(273, 329), 15);
+ connRef906->setDestEndpoint(dstPt906);
+ connRef906->setRoutingType((ConnType)2);
+
+ ConnRef *connRef907 = new ConnRef(router, 907);
+ ConnEnd srcPt907(Point(979.246, 676.918), 15);
+ connRef907->setSourceEndpoint(srcPt907);
+ ConnEnd dstPt907(Point(982, 667), 15);
+ connRef907->setDestEndpoint(dstPt907);
+ connRef907->setRoutingType((ConnType)2);
+
+ ConnRef *connRef908 = new ConnRef(router, 908);
+ ConnEnd srcPt908(Point(979.246, 676.918), 15);
+ connRef908->setSourceEndpoint(srcPt908);
+ ConnEnd dstPt908(Point(932, 648), 15);
+ connRef908->setDestEndpoint(dstPt908);
+ connRef908->setRoutingType((ConnType)2);
+
+ ConnRef *connRef909 = new ConnRef(router, 909);
+ ConnEnd srcPt909(Point(197.246, 160.918), 15);
+ connRef909->setSourceEndpoint(srcPt909);
+ ConnEnd dstPt909(Point(972, 300), 15);
+ connRef909->setDestEndpoint(dstPt909);
+ connRef909->setRoutingType((ConnType)2);
+
+ ConnRef *connRef910 = new ConnRef(router, 910);
+ ConnEnd srcPt910(Point(823.246, 676.918), 15);
+ connRef910->setSourceEndpoint(srcPt910);
+ ConnEnd dstPt910(Point(972, 300), 15);
+ connRef910->setDestEndpoint(dstPt910);
+ connRef910->setRoutingType((ConnType)2);
+
+ ConnRef *connRef911 = new ConnRef(router, 911);
+ ConnEnd srcPt911(Point(197.246, 160.918), 15);
+ connRef911->setSourceEndpoint(srcPt911);
+ ConnEnd dstPt911(Point(922, 309), 15);
+ connRef911->setDestEndpoint(dstPt911);
+ connRef911->setRoutingType((ConnType)2);
+
+ ConnRef *connRef912 = new ConnRef(router, 912);
+ ConnEnd srcPt912(Point(823.246, 676.918), 15);
+ connRef912->setSourceEndpoint(srcPt912);
+ ConnEnd dstPt912(Point(922, 309), 15);
+ connRef912->setDestEndpoint(dstPt912);
+ connRef912->setRoutingType((ConnType)2);
+
+ ConnRef *connRef913 = new ConnRef(router, 913);
+ ConnEnd srcPt913(Point(197.246, 160.918), 15);
+ connRef913->setSourceEndpoint(srcPt913);
+ ConnEnd dstPt913(Point(922, 290), 15);
+ connRef913->setDestEndpoint(dstPt913);
+ connRef913->setRoutingType((ConnType)2);
+
+ ConnRef *connRef914 = new ConnRef(router, 914);
+ ConnEnd srcPt914(Point(823.246, 676.918), 15);
+ connRef914->setSourceEndpoint(srcPt914);
+ ConnEnd dstPt914(Point(922, 290), 15);
+ connRef914->setDestEndpoint(dstPt914);
+ connRef914->setRoutingType((ConnType)2);
+
+ ConnRef *connRef915 = new ConnRef(router, 915);
+ ConnEnd srcPt915(Point(197.246, 160.918), 15);
+ connRef915->setSourceEndpoint(srcPt915);
+ ConnEnd dstPt915(Point(830, 300), 15);
+ connRef915->setDestEndpoint(dstPt915);
+ connRef915->setRoutingType((ConnType)2);
+
+ ConnRef *connRef916 = new ConnRef(router, 916);
+ ConnEnd srcPt916(Point(673.933, 676.918), 15);
+ connRef916->setSourceEndpoint(srcPt916);
+ ConnEnd dstPt916(Point(830, 300), 15);
+ connRef916->setDestEndpoint(dstPt916);
+ connRef916->setRoutingType((ConnType)2);
+
+ ConnRef *connRef917 = new ConnRef(router, 917);
+ ConnEnd srcPt917(Point(197.246, 160.918), 15);
+ connRef917->setSourceEndpoint(srcPt917);
+ ConnEnd dstPt917(Point(780, 309), 15);
+ connRef917->setDestEndpoint(dstPt917);
+ connRef917->setRoutingType((ConnType)2);
+
+ ConnRef *connRef918 = new ConnRef(router, 918);
+ ConnEnd srcPt918(Point(673.933, 676.918), 15);
+ connRef918->setSourceEndpoint(srcPt918);
+ ConnEnd dstPt918(Point(780, 309), 15);
+ connRef918->setDestEndpoint(dstPt918);
+ connRef918->setRoutingType((ConnType)2);
+
+ ConnRef *connRef919 = new ConnRef(router, 919);
+ ConnEnd srcPt919(Point(197.246, 160.918), 15);
+ connRef919->setSourceEndpoint(srcPt919);
+ ConnEnd dstPt919(Point(780, 290), 15);
+ connRef919->setDestEndpoint(dstPt919);
+ connRef919->setRoutingType((ConnType)2);
+
+ ConnRef *connRef920 = new ConnRef(router, 920);
+ ConnEnd srcPt920(Point(673.933, 676.918), 15);
+ connRef920->setSourceEndpoint(srcPt920);
+ ConnEnd dstPt920(Point(780, 290), 15);
+ connRef920->setDestEndpoint(dstPt920);
+ connRef920->setRoutingType((ConnType)2);
+
+ ConnRef *connRef921 = new ConnRef(router, 921);
+ ConnEnd srcPt921(Point(197.246, 160.918), 15);
+ connRef921->setSourceEndpoint(srcPt921);
+ ConnEnd dstPt921(Point(689, 300), 15);
+ connRef921->setDestEndpoint(dstPt921);
+ connRef921->setRoutingType((ConnType)2);
+
+ ConnRef *connRef922 = new ConnRef(router, 922);
+ ConnEnd srcPt922(Point(527.246, 676.918), 15);
+ connRef922->setSourceEndpoint(srcPt922);
+ ConnEnd dstPt922(Point(689, 300), 15);
+ connRef922->setDestEndpoint(dstPt922);
+ connRef922->setRoutingType((ConnType)2);
+
+ ConnRef *connRef923 = new ConnRef(router, 923);
+ ConnEnd srcPt923(Point(197.246, 160.918), 15);
+ connRef923->setSourceEndpoint(srcPt923);
+ ConnEnd dstPt923(Point(639, 309), 15);
+ connRef923->setDestEndpoint(dstPt923);
+ connRef923->setRoutingType((ConnType)2);
+
+ ConnRef *connRef924 = new ConnRef(router, 924);
+ ConnEnd srcPt924(Point(527.246, 676.918), 15);
+ connRef924->setSourceEndpoint(srcPt924);
+ ConnEnd dstPt924(Point(639, 309), 15);
+ connRef924->setDestEndpoint(dstPt924);
+ connRef924->setRoutingType((ConnType)2);
+
+ ConnRef *connRef925 = new ConnRef(router, 925);
+ ConnEnd srcPt925(Point(197.246, 160.918), 15);
+ connRef925->setSourceEndpoint(srcPt925);
+ ConnEnd dstPt925(Point(639, 290), 15);
+ connRef925->setDestEndpoint(dstPt925);
+ connRef925->setRoutingType((ConnType)2);
+
+ ConnRef *connRef926 = new ConnRef(router, 926);
+ ConnEnd srcPt926(Point(527.246, 676.918), 15);
+ connRef926->setSourceEndpoint(srcPt926);
+ ConnEnd dstPt926(Point(639, 290), 15);
+ connRef926->setDestEndpoint(dstPt926);
+ connRef926->setRoutingType((ConnType)2);
+
+ ConnRef *connRef927 = new ConnRef(router, 927);
+ ConnEnd srcPt927(Point(197.246, 160.918), 15);
+ connRef927->setSourceEndpoint(srcPt927);
+ ConnEnd dstPt927(Point(547, 300), 15);
+ connRef927->setDestEndpoint(dstPt927);
+ connRef927->setRoutingType((ConnType)2);
+
+ ConnRef *connRef928 = new ConnRef(router, 928);
+ ConnEnd srcPt928(Point(371.246, 676.918), 15);
+ connRef928->setSourceEndpoint(srcPt928);
+ ConnEnd dstPt928(Point(547, 300), 15);
+ connRef928->setDestEndpoint(dstPt928);
+ connRef928->setRoutingType((ConnType)2);
+
+ ConnRef *connRef929 = new ConnRef(router, 929);
+ ConnEnd srcPt929(Point(197.246, 160.918), 15);
+ connRef929->setSourceEndpoint(srcPt929);
+ ConnEnd dstPt929(Point(497, 309), 15);
+ connRef929->setDestEndpoint(dstPt929);
+ connRef929->setRoutingType((ConnType)2);
+
+ ConnRef *connRef930 = new ConnRef(router, 930);
+ ConnEnd srcPt930(Point(371.246, 676.918), 15);
+ connRef930->setSourceEndpoint(srcPt930);
+ ConnEnd dstPt930(Point(497, 309), 15);
+ connRef930->setDestEndpoint(dstPt930);
+ connRef930->setRoutingType((ConnType)2);
+
+ ConnRef *connRef931 = new ConnRef(router, 931);
+ ConnEnd srcPt931(Point(197.246, 160.918), 15);
+ connRef931->setSourceEndpoint(srcPt931);
+ ConnEnd dstPt931(Point(497, 290), 15);
+ connRef931->setDestEndpoint(dstPt931);
+ connRef931->setRoutingType((ConnType)2);
+
+ ConnRef *connRef932 = new ConnRef(router, 932);
+ ConnEnd srcPt932(Point(371.246, 676.918), 15);
+ connRef932->setSourceEndpoint(srcPt932);
+ ConnEnd dstPt932(Point(497, 290), 15);
+ connRef932->setDestEndpoint(dstPt932);
+ connRef932->setRoutingType((ConnType)2);
+
+ ConnRef *connRef933 = new ConnRef(router, 933);
+ ConnEnd srcPt933(Point(197.246, 160.918), 15);
+ connRef933->setSourceEndpoint(srcPt933);
+ ConnEnd dstPt933(Point(405, 300), 15);
+ connRef933->setDestEndpoint(dstPt933);
+ connRef933->setRoutingType((ConnType)2);
+
+ ConnRef *connRef934 = new ConnRef(router, 934);
+ ConnEnd srcPt934(Point(215.246, 676.918), 15);
+ connRef934->setSourceEndpoint(srcPt934);
+ ConnEnd dstPt934(Point(405, 300), 15);
+ connRef934->setDestEndpoint(dstPt934);
+ connRef934->setRoutingType((ConnType)2);
+
+ ConnRef *connRef935 = new ConnRef(router, 935);
+ ConnEnd srcPt935(Point(197.246, 160.918), 15);
+ connRef935->setSourceEndpoint(srcPt935);
+ ConnEnd dstPt935(Point(355, 309), 15);
+ connRef935->setDestEndpoint(dstPt935);
+ connRef935->setRoutingType((ConnType)2);
+
+ ConnRef *connRef936 = new ConnRef(router, 936);
+ ConnEnd srcPt936(Point(215.246, 676.918), 15);
+ connRef936->setSourceEndpoint(srcPt936);
+ ConnEnd dstPt936(Point(355, 309), 15);
+ connRef936->setDestEndpoint(dstPt936);
+ connRef936->setRoutingType((ConnType)2);
+
+ ConnRef *connRef937 = new ConnRef(router, 937);
+ ConnEnd srcPt937(Point(197.246, 160.918), 15);
+ connRef937->setSourceEndpoint(srcPt937);
+ ConnEnd dstPt937(Point(355, 290), 15);
+ connRef937->setDestEndpoint(dstPt937);
+ connRef937->setRoutingType((ConnType)2);
+
+ ConnRef *connRef938 = new ConnRef(router, 938);
+ ConnEnd srcPt938(Point(215.246, 676.918), 15);
+ connRef938->setSourceEndpoint(srcPt938);
+ ConnEnd dstPt938(Point(355, 290), 15);
+ connRef938->setDestEndpoint(dstPt938);
+ connRef938->setRoutingType((ConnType)2);
+
+ ConnRef *connRef939 = new ConnRef(router, 939);
+ ConnEnd srcPt939(Point(197.246, 160.918), 15);
+ connRef939->setSourceEndpoint(srcPt939);
+ ConnEnd dstPt939(Point(273, 310), 15);
+ connRef939->setDestEndpoint(dstPt939);
+ connRef939->setRoutingType((ConnType)2);
+
+ ConnRef *connRef940 = new ConnRef(router, 940);
+ ConnEnd srcPt940(Point(57.2456, 676.918), 15);
+ connRef940->setSourceEndpoint(srcPt940);
+ ConnEnd dstPt940(Point(273, 310), 15);
+ connRef940->setDestEndpoint(dstPt940);
+ connRef940->setRoutingType((ConnType)2);
+
+ ConnRef *connRef941 = new ConnRef(router, 941);
+ ConnEnd srcPt941(Point(197.246, 160.918), 15);
+ connRef941->setSourceEndpoint(srcPt941);
+ ConnEnd dstPt941(Point(213, 290), 15);
+ connRef941->setDestEndpoint(dstPt941);
+ connRef941->setRoutingType((ConnType)2);
+
+ ConnRef *connRef942 = new ConnRef(router, 942);
+ ConnEnd srcPt942(Point(57.2456, 676.918), 15);
+ connRef942->setSourceEndpoint(srcPt942);
+ ConnEnd dstPt942(Point(213, 290), 15);
+ connRef942->setDestEndpoint(dstPt942);
+ connRef942->setRoutingType((ConnType)2);
+
+ ConnRef *connRef943 = new ConnRef(router, 943);
+ ConnEnd srcPt943(Point(197.246, 160.918), 15);
+ connRef943->setSourceEndpoint(srcPt943);
+ ConnEnd dstPt943(Point(213, 309), 15);
+ connRef943->setDestEndpoint(dstPt943);
+ connRef943->setRoutingType((ConnType)2);
+
+ ConnRef *connRef944 = new ConnRef(router, 944);
+ ConnEnd srcPt944(Point(57.2456, 676.918), 15);
+ connRef944->setSourceEndpoint(srcPt944);
+ ConnEnd dstPt944(Point(213, 309), 15);
+ connRef944->setDestEndpoint(dstPt944);
+ connRef944->setRoutingType((ConnType)2);
+
+ ConnRef *connRef945 = new ConnRef(router, 945);
+ ConnEnd srcPt945(Point(197.246, 160.918), 15);
+ connRef945->setSourceEndpoint(srcPt945);
+ ConnEnd dstPt945(Point(92, 309), 15);
+ connRef945->setDestEndpoint(dstPt945);
+ connRef945->setRoutingType((ConnType)2);
+
+ ConnRef *connRef946 = new ConnRef(router, 946);
+ ConnEnd srcPt946(Point(57.2456, 160.918), 15);
+ connRef946->setSourceEndpoint(srcPt946);
+ ConnEnd dstPt946(Point(92, 309), 15);
+ connRef946->setDestEndpoint(dstPt946);
+ connRef946->setRoutingType((ConnType)2);
+
+ ConnRef *connRef947 = new ConnRef(router, 947);
+ ConnEnd srcPt947(Point(197.246, 160.918), 15);
+ connRef947->setSourceEndpoint(srcPt947);
+ ConnEnd dstPt947(Point(92, 290), 15);
+ connRef947->setDestEndpoint(dstPt947);
+ connRef947->setRoutingType((ConnType)2);
+
+ ConnRef *connRef948 = new ConnRef(router, 948);
+ ConnEnd srcPt948(Point(57.2456, 160.918), 15);
+ connRef948->setSourceEndpoint(srcPt948);
+ ConnEnd dstPt948(Point(92, 290), 15);
+ connRef948->setDestEndpoint(dstPt948);
+ connRef948->setRoutingType((ConnType)2);
+
+ ConnRef *connRef949 = new ConnRef(router, 949);
+ ConnEnd srcPt949(Point(57.2456, 125.987), 15);
+ connRef949->setSourceEndpoint(srcPt949);
+ ConnEnd dstPt949(Point(82, 194), 15);
+ connRef949->setDestEndpoint(dstPt949);
+ connRef949->setRoutingType((ConnType)2);
+
+ ConnRef *connRef950 = new ConnRef(router, 950);
+ ConnEnd srcPt950(Point(57.2456, 125.987), 15);
+ connRef950->setSourceEndpoint(srcPt950);
+ ConnEnd dstPt950(Point(82, 175), 15);
+ connRef950->setDestEndpoint(dstPt950);
+ connRef950->setRoutingType((ConnType)2);
+
+ ConnRef *connRef951 = new ConnRef(router, 951);
+ ConnEnd srcPt951(Point(57.2456, 125.987), 15);
+ connRef951->setSourceEndpoint(srcPt951);
+ ConnEnd dstPt951(Point(82, 156), 15);
+ connRef951->setDestEndpoint(dstPt951);
+ connRef951->setRoutingType((ConnType)2);
+
+ ConnRef *connRef952 = new ConnRef(router, 952);
+ ConnEnd srcPt952(Point(319.219, -7.08205), 15);
+ connRef952->setSourceEndpoint(srcPt952);
+ ConnEnd dstPt952(Point(319, 155), 15);
+ connRef952->setDestEndpoint(dstPt952);
+ connRef952->setRoutingType((ConnType)2);
+
+ ConnRef *connRef953 = new ConnRef(router, 953);
+ ConnEnd srcPt953(Point(197.246, 96.9179), 15);
+ connRef953->setSourceEndpoint(srcPt953);
+ ConnEnd dstPt953(Point(317.466, 34.9179), 15);
+ connRef953->setDestEndpoint(dstPt953);
+ connRef953->setRoutingType((ConnType)2);
+
+ ConnRef *connRef954 = new ConnRef(router, 954);
+ ConnEnd srcPt954(Point(57.2456, 125.987), 15);
+ connRef954->setSourceEndpoint(srcPt954);
+ ConnEnd dstPt954(Point(-7.75443, -71.0821), 15);
+ connRef954->setDestEndpoint(dstPt954);
+ connRef954->setRoutingType((ConnType)2);
+
+ ConnRef *connRef955 = new ConnRef(router, 955);
+ ConnEnd srcPt955(Point(197.246, 96.9179), 15);
+ connRef955->setSourceEndpoint(srcPt955);
+ ConnEnd dstPt955(Point(317.466, 86.9179), 15);
+ connRef955->setDestEndpoint(dstPt955);
+ connRef955->setRoutingType((ConnType)2);
+
+ ConnRef *connRef398 = new ConnRef(router, 398);
+ ConnEnd srcPt398(Point(982, 596), 15);
+ connRef398->setSourceEndpoint(srcPt398);
+ ConnEnd dstPt398(Point(979.246, 676.918), 15);
+ connRef398->setDestEndpoint(dstPt398);
+ connRef398->setRoutingType((ConnType)2);
+
+ ConnRef *connRef399 = new ConnRef(router, 399);
+ ConnEnd srcPt399(Point(840, 596), 15);
+ connRef399->setSourceEndpoint(srcPt399);
+ ConnEnd dstPt399(Point(823.246, 676.918), 15);
+ connRef399->setDestEndpoint(dstPt399);
+ connRef399->setRoutingType((ConnType)2);
+
+ ConnRef *connRef400 = new ConnRef(router, 400);
+ ConnEnd srcPt400(Point(699, 596), 15);
+ connRef400->setSourceEndpoint(srcPt400);
+ ConnEnd dstPt400(Point(673.933, 676.918), 15);
+ connRef400->setDestEndpoint(dstPt400);
+ connRef400->setRoutingType((ConnType)2);
+
+ ConnRef *connRef401 = new ConnRef(router, 401);
+ ConnEnd srcPt401(Point(557, 596), 15);
+ connRef401->setSourceEndpoint(srcPt401);
+ ConnEnd dstPt401(Point(527.246, 676.918), 15);
+ connRef401->setDestEndpoint(dstPt401);
+ connRef401->setRoutingType((ConnType)2);
+
+ ConnRef *connRef402 = new ConnRef(router, 402);
+ ConnEnd srcPt402(Point(415, 596), 15);
+ connRef402->setSourceEndpoint(srcPt402);
+ ConnEnd dstPt402(Point(371.246, 676.918), 15);
+ connRef402->setDestEndpoint(dstPt402);
+ connRef402->setRoutingType((ConnType)2);
+
+ ConnRef *connRef403 = new ConnRef(router, 403);
+ ConnEnd srcPt403(Point(273, 596), 15);
+ connRef403->setSourceEndpoint(srcPt403);
+ ConnEnd dstPt403(Point(215.246, 676.918), 15);
+ connRef403->setDestEndpoint(dstPt403);
+ connRef403->setRoutingType((ConnType)2);
+
+ ConnRef *connRef404 = new ConnRef(router, 404);
+ ConnEnd srcPt404(Point(132, 615), 15);
+ connRef404->setSourceEndpoint(srcPt404);
+ ConnEnd dstPt404(Point(57.2456, 676.918), 15);
+ connRef404->setDestEndpoint(dstPt404);
+ connRef404->setRoutingType((ConnType)2);
+
+ ConnRef *connRef405 = new ConnRef(router, 405);
+ ConnEnd srcPt405(Point(1203.25, 676.918), 15);
+ connRef405->setSourceEndpoint(srcPt405);
+ ConnEnd dstPt405(Point(1227, 632), 15);
+ connRef405->setDestEndpoint(dstPt405);
+ connRef405->setRoutingType((ConnType)2);
+
+ ConnRef *connRef406 = new ConnRef(router, 406);
+ ConnEnd srcPt406(Point(1209, 586), 15);
+ connRef406->setSourceEndpoint(srcPt406);
+ ConnEnd dstPt406(Point(1203.25, 676.918), 15);
+ connRef406->setDestEndpoint(dstPt406);
+ connRef406->setRoutingType((ConnType)2);
+
+ ConnRef *connRef407 = new ConnRef(router, 407);
+ ConnEnd srcPt407(Point(1203.25, 676.918), 15);
+ connRef407->setSourceEndpoint(srcPt407);
+ ConnEnd dstPt407(Point(1209, 667), 15);
+ connRef407->setDestEndpoint(dstPt407);
+ connRef407->setRoutingType((ConnType)2);
+
+ ConnRef *connRef408 = new ConnRef(router, 408);
+ ConnEnd srcPt408(Point(1203.25, 676.918), 15);
+ connRef408->setSourceEndpoint(srcPt408);
+ ConnEnd dstPt408(Point(1159, 667), 15);
+ connRef408->setDestEndpoint(dstPt408);
+ connRef408->setRoutingType((ConnType)2);
+
+ ConnRef *connRef409 = new ConnRef(router, 409);
+ ConnEnd srcPt409(Point(1209, 566), 15);
+ connRef409->setSourceEndpoint(srcPt409);
+ ConnEnd dstPt409(Point(1203.25, 558.918), 15);
+ connRef409->setDestEndpoint(dstPt409);
+ connRef409->setRoutingType((ConnType)2);
+
+ ConnRef *connRef410 = new ConnRef(router, 410);
+ ConnEnd srcPt410(Point(1209, 505), 15);
+ connRef410->setSourceEndpoint(srcPt410);
+ ConnEnd dstPt410(Point(1203.25, 558.918), 15);
+ connRef410->setDestEndpoint(dstPt410);
+ connRef410->setRoutingType((ConnType)2);
+
+ ConnRef *connRef411 = new ConnRef(router, 411);
+ ConnEnd srcPt411(Point(1159, 575), 15);
+ connRef411->setSourceEndpoint(srcPt411);
+ ConnEnd dstPt411(Point(1203.25, 558.918), 15);
+ connRef411->setDestEndpoint(dstPt411);
+ connRef411->setRoutingType((ConnType)2);
+
+ ConnRef *connRef412 = new ConnRef(router, 412);
+ ConnEnd srcPt412(Point(1209, 585), 15);
+ connRef412->setSourceEndpoint(srcPt412);
+ ConnEnd dstPt412(Point(1203.25, 558.918), 15);
+ connRef412->setDestEndpoint(dstPt412);
+ connRef412->setRoutingType((ConnType)2);
+
+ ConnRef *connRef413 = new ConnRef(router, 413);
+ ConnEnd srcPt413(Point(1209, 485), 15);
+ connRef413->setSourceEndpoint(srcPt413);
+ ConnEnd dstPt413(Point(1203.25, 447.955), 15);
+ connRef413->setDestEndpoint(dstPt413);
+ connRef413->setRoutingType((ConnType)2);
+
+ ConnRef *connRef414 = new ConnRef(router, 414);
+ ConnEnd srcPt414(Point(1209, 414), 15);
+ connRef414->setSourceEndpoint(srcPt414);
+ ConnEnd dstPt414(Point(1203.25, 447.955), 15);
+ connRef414->setDestEndpoint(dstPt414);
+ connRef414->setRoutingType((ConnType)2);
+
+ ConnRef *connRef415 = new ConnRef(router, 415);
+ ConnEnd srcPt415(Point(1159, 485), 15);
+ connRef415->setSourceEndpoint(srcPt415);
+ ConnEnd dstPt415(Point(1203.25, 447.955), 15);
+ connRef415->setDestEndpoint(dstPt415);
+ connRef415->setRoutingType((ConnType)2);
+
+ ConnRef *connRef416 = new ConnRef(router, 416);
+ ConnEnd srcPt416(Point(1209, 394), 15);
+ connRef416->setSourceEndpoint(srcPt416);
+ ConnEnd dstPt416(Point(1203.25, 332.918), 15);
+ connRef416->setDestEndpoint(dstPt416);
+ connRef416->setRoutingType((ConnType)2);
+
+ ConnRef *connRef417 = new ConnRef(router, 417);
+ ConnEnd srcPt417(Point(1159, 394), 15);
+ connRef417->setSourceEndpoint(srcPt417);
+ ConnEnd dstPt417(Point(1203.25, 332.918), 15);
+ connRef417->setDestEndpoint(dstPt417);
+ connRef417->setRoutingType((ConnType)2);
+
+ ConnRef *connRef418 = new ConnRef(router, 418);
+ ConnEnd srcPt418(Point(1449.25, 676.918), 15);
+ connRef418->setSourceEndpoint(srcPt418);
+ ConnEnd dstPt418(Point(1299, 667), 15);
+ connRef418->setDestEndpoint(dstPt418);
+ connRef418->setRoutingType((ConnType)2);
+
+ ConnRef *connRef419 = new ConnRef(router, 419);
+ ConnEnd srcPt419(Point(1171.25, 676.918), 15);
+ connRef419->setSourceEndpoint(srcPt419);
+ ConnEnd dstPt419(Point(1059, 667), 15);
+ connRef419->setDestEndpoint(dstPt419);
+ connRef419->setRoutingType((ConnType)2);
+
+ ConnRef *connRef420 = new ConnRef(router, 420);
+ ConnEnd srcPt420(Point(1171.25, 676.918), 15);
+ connRef420->setSourceEndpoint(srcPt420);
+ ConnEnd dstPt420(Point(1109, 667), 15);
+ connRef420->setDestEndpoint(dstPt420);
+ connRef420->setRoutingType((ConnType)2);
+
+ ConnRef *connRef421 = new ConnRef(router, 421);
+ ConnEnd srcPt421(Point(1050, 634), 15);
+ connRef421->setSourceEndpoint(srcPt421);
+ ConnEnd dstPt421(Point(1171.25, 676.918), 15);
+ connRef421->setDestEndpoint(dstPt421);
+ connRef421->setRoutingType((ConnType)2);
+
+ ConnRef *connRef422 = new ConnRef(router, 422);
+ ConnEnd srcPt422(Point(790, 687), 15);
+ connRef422->setSourceEndpoint(srcPt422);
+ ConnEnd dstPt422(Point(823.246, 750.918), 15);
+ connRef422->setDestEndpoint(dstPt422);
+ connRef422->setRoutingType((ConnType)2);
+
+ ConnRef *connRef423 = new ConnRef(router, 423);
+ ConnEnd srcPt423(Point(1059, 687), 15);
+ connRef423->setSourceEndpoint(srcPt423);
+ ConnEnd dstPt423(Point(1171.25, 750.918), 15);
+ connRef423->setDestEndpoint(dstPt423);
+ connRef423->setRoutingType((ConnType)2);
+
+ ConnRef *connRef424 = new ConnRef(router, 424);
+ ConnEnd srcPt424(Point(1109, 687), 15);
+ connRef424->setSourceEndpoint(srcPt424);
+ ConnEnd dstPt424(Point(1171.25, 750.918), 15);
+ connRef424->setDestEndpoint(dstPt424);
+ connRef424->setRoutingType((ConnType)2);
+
+ ConnRef *connRef425 = new ConnRef(router, 425);
+ ConnEnd srcPt425(Point(533, 687), 15);
+ connRef425->setSourceEndpoint(srcPt425);
+ ConnEnd dstPt425(Point(527.246, 750.918), 15);
+ connRef425->setDestEndpoint(dstPt425);
+ connRef425->setRoutingType((ConnType)2);
+
+ ConnRef *connRef426 = new ConnRef(router, 426);
+ ConnEnd srcPt426(Point(390, 687), 15);
+ connRef426->setSourceEndpoint(srcPt426);
+ ConnEnd dstPt426(Point(371.246, 750.918), 15);
+ connRef426->setDestEndpoint(dstPt426);
+ connRef426->setRoutingType((ConnType)2);
+
+ ConnRef *connRef427 = new ConnRef(router, 427);
+ ConnEnd srcPt427(Point(1247, 632), 15);
+ connRef427->setSourceEndpoint(srcPt427);
+ ConnEnd dstPt427(Point(1449.25, 676.918), 15);
+ connRef427->setDestEndpoint(dstPt427);
+ connRef427->setRoutingType((ConnType)2);
+
+ ConnRef *connRef428 = new ConnRef(router, 428);
+ ConnEnd srcPt428(Point(982, 615), 15);
+ connRef428->setSourceEndpoint(srcPt428);
+ ConnEnd dstPt428(Point(979.246, 676.918), 15);
+ connRef428->setDestEndpoint(dstPt428);
+ connRef428->setRoutingType((ConnType)2);
+
+ ConnRef *connRef429 = new ConnRef(router, 429);
+ ConnEnd srcPt429(Point(840, 615), 15);
+ connRef429->setSourceEndpoint(srcPt429);
+ ConnEnd dstPt429(Point(823.246, 676.918), 15);
+ connRef429->setDestEndpoint(dstPt429);
+ connRef429->setRoutingType((ConnType)2);
+
+ ConnRef *connRef430 = new ConnRef(router, 430);
+ ConnEnd srcPt430(Point(699, 615), 15);
+ connRef430->setSourceEndpoint(srcPt430);
+ ConnEnd dstPt430(Point(673.933, 676.918), 15);
+ connRef430->setDestEndpoint(dstPt430);
+ connRef430->setRoutingType((ConnType)2);
+
+ ConnRef *connRef431 = new ConnRef(router, 431);
+ ConnEnd srcPt431(Point(557, 615), 15);
+ connRef431->setSourceEndpoint(srcPt431);
+ ConnEnd dstPt431(Point(527.246, 676.918), 15);
+ connRef431->setDestEndpoint(dstPt431);
+ connRef431->setRoutingType((ConnType)2);
+
+ ConnRef *connRef432 = new ConnRef(router, 432);
+ ConnEnd srcPt432(Point(415, 615), 15);
+ connRef432->setSourceEndpoint(srcPt432);
+ ConnEnd dstPt432(Point(371.246, 676.918), 15);
+ connRef432->setDestEndpoint(dstPt432);
+ connRef432->setRoutingType((ConnType)2);
+
+ ConnRef *connRef433 = new ConnRef(router, 433);
+ ConnEnd srcPt433(Point(273, 615), 15);
+ connRef433->setSourceEndpoint(srcPt433);
+ ConnEnd dstPt433(Point(215.246, 676.918), 15);
+ connRef433->setDestEndpoint(dstPt433);
+ connRef433->setRoutingType((ConnType)2);
+
+ ConnRef *connRef434 = new ConnRef(router, 434);
+ ConnEnd srcPt434(Point(132, 596), 15);
+ connRef434->setSourceEndpoint(srcPt434);
+ ConnEnd dstPt434(Point(57.2456, 676.918), 15);
+ connRef434->setDestEndpoint(dstPt434);
+ connRef434->setRoutingType((ConnType)2);
+
+ ConnRef *connRef435 = new ConnRef(router, 435);
+ ConnEnd srcPt435(Point(982, 516), 15);
+ connRef435->setSourceEndpoint(srcPt435);
+ ConnEnd dstPt435(Point(979.246, 558.918), 15);
+ connRef435->setDestEndpoint(dstPt435);
+ connRef435->setRoutingType((ConnType)2);
+
+ ConnRef *connRef436 = new ConnRef(router, 436);
+ ConnEnd srcPt436(Point(982, 496), 15);
+ connRef436->setSourceEndpoint(srcPt436);
+ ConnEnd dstPt436(Point(979.246, 447.955), 15);
+ connRef436->setDestEndpoint(dstPt436);
+ connRef436->setRoutingType((ConnType)2);
+
+ ConnRef *connRef437 = new ConnRef(router, 437);
+ ConnEnd srcPt437(Point(840, 496), 15);
+ connRef437->setSourceEndpoint(srcPt437);
+ ConnEnd dstPt437(Point(823.246, 447.955), 15);
+ connRef437->setDestEndpoint(dstPt437);
+ connRef437->setRoutingType((ConnType)2);
+
+ ConnRef *connRef438 = new ConnRef(router, 438);
+ ConnEnd srcPt438(Point(840, 516), 15);
+ connRef438->setSourceEndpoint(srcPt438);
+ ConnEnd dstPt438(Point(823.246, 558.918), 15);
+ connRef438->setDestEndpoint(dstPt438);
+ connRef438->setRoutingType((ConnType)2);
+
+ ConnRef *connRef439 = new ConnRef(router, 439);
+ ConnEnd srcPt439(Point(699, 516), 15);
+ connRef439->setSourceEndpoint(srcPt439);
+ ConnEnd dstPt439(Point(673.933, 558.918), 15);
+ connRef439->setDestEndpoint(dstPt439);
+ connRef439->setRoutingType((ConnType)2);
+
+ ConnRef *connRef440 = new ConnRef(router, 440);
+ ConnEnd srcPt440(Point(699, 496), 15);
+ connRef440->setSourceEndpoint(srcPt440);
+ ConnEnd dstPt440(Point(673.933, 447.955), 15);
+ connRef440->setDestEndpoint(dstPt440);
+ connRef440->setRoutingType((ConnType)2);
+
+ ConnRef *connRef441 = new ConnRef(router, 441);
+ ConnEnd srcPt441(Point(557, 496), 15);
+ connRef441->setSourceEndpoint(srcPt441);
+ ConnEnd dstPt441(Point(527.246, 447.955), 15);
+ connRef441->setDestEndpoint(dstPt441);
+ connRef441->setRoutingType((ConnType)2);
+
+ ConnRef *connRef442 = new ConnRef(router, 442);
+ ConnEnd srcPt442(Point(557, 516), 15);
+ connRef442->setSourceEndpoint(srcPt442);
+ ConnEnd dstPt442(Point(527.246, 558.918), 15);
+ connRef442->setDestEndpoint(dstPt442);
+ connRef442->setRoutingType((ConnType)2);
+
+ ConnRef *connRef443 = new ConnRef(router, 443);
+ ConnEnd srcPt443(Point(415, 516), 15);
+ connRef443->setSourceEndpoint(srcPt443);
+ ConnEnd dstPt443(Point(371.246, 558.918), 15);
+ connRef443->setDestEndpoint(dstPt443);
+ connRef443->setRoutingType((ConnType)2);
+
+ ConnRef *connRef444 = new ConnRef(router, 444);
+ ConnEnd srcPt444(Point(415, 496), 15);
+ connRef444->setSourceEndpoint(srcPt444);
+ ConnEnd dstPt444(Point(371.246, 447.955), 15);
+ connRef444->setDestEndpoint(dstPt444);
+ connRef444->setRoutingType((ConnType)2);
+
+ ConnRef *connRef445 = new ConnRef(router, 445);
+ ConnEnd srcPt445(Point(273, 496), 15);
+ connRef445->setSourceEndpoint(srcPt445);
+ ConnEnd dstPt445(Point(215.246, 447.955), 15);
+ connRef445->setDestEndpoint(dstPt445);
+ connRef445->setRoutingType((ConnType)2);
+
+ ConnRef *connRef446 = new ConnRef(router, 446);
+ ConnEnd srcPt446(Point(273, 516), 15);
+ connRef446->setSourceEndpoint(srcPt446);
+ ConnEnd dstPt446(Point(215.246, 558.918), 15);
+ connRef446->setDestEndpoint(dstPt446);
+ connRef446->setRoutingType((ConnType)2);
+
+ ConnRef *connRef447 = new ConnRef(router, 447);
+ ConnEnd srcPt447(Point(132, 496), 15);
+ connRef447->setSourceEndpoint(srcPt447);
+ ConnEnd dstPt447(Point(57.2456, 447.955), 15);
+ connRef447->setDestEndpoint(dstPt447);
+ connRef447->setRoutingType((ConnType)2);
+
+ ConnRef *connRef448 = new ConnRef(router, 448);
+ ConnEnd srcPt448(Point(132, 516), 15);
+ connRef448->setSourceEndpoint(srcPt448);
+ ConnEnd dstPt448(Point(57.2456, 558.918), 15);
+ connRef448->setDestEndpoint(dstPt448);
+ connRef448->setRoutingType((ConnType)2);
+
+ ConnRef *connRef449 = new ConnRef(router, 449);
+ ConnEnd srcPt449(Point(1219, 319), 15);
+ connRef449->setSourceEndpoint(srcPt449);
+ ConnEnd dstPt449(Point(1203.25, 332.918), 15);
+ connRef449->setDestEndpoint(dstPt449);
+ connRef449->setRoutingType((ConnType)2);
+
+ ConnRef *connRef450 = new ConnRef(router, 450);
+ ConnEnd srcPt450(Point(1199, 319), 15);
+ connRef450->setSourceEndpoint(srcPt450);
+ ConnEnd dstPt450(Point(197.246, 160.918), 15);
+ connRef450->setDestEndpoint(dstPt450);
+ connRef450->setRoutingType((ConnType)2);
+
+ ConnRef *connRef451 = new ConnRef(router, 451);
+ ConnEnd srcPt451(Point(1199, 319), 15);
+ connRef451->setSourceEndpoint(srcPt451);
+ ConnEnd dstPt451(Point(979.246, 676.918), 15);
+ connRef451->setDestEndpoint(dstPt451);
+ connRef451->setRoutingType((ConnType)2);
+
+ ConnRef *connRef452 = new ConnRef(router, 452);
+ ConnEnd srcPt452(Point(1209, 687), 15);
+ connRef452->setSourceEndpoint(srcPt452);
+ ConnEnd dstPt452(Point(1203.25, 750.918), 15);
+ connRef452->setDestEndpoint(dstPt452);
+ connRef452->setRoutingType((ConnType)2);
+
+ ConnRef *connRef453 = new ConnRef(router, 453);
+ ConnEnd srcPt453(Point(1299, 687), 15);
+ connRef453->setSourceEndpoint(srcPt453);
+ ConnEnd dstPt453(Point(1449.25, 750.918), 15);
+ connRef453->setDestEndpoint(dstPt453);
+ connRef453->setRoutingType((ConnType)2);
+
+ ConnRef *connRef454 = new ConnRef(router, 454);
+ ConnEnd srcPt454(Point(649, 687), 15);
+ connRef454->setSourceEndpoint(srcPt454);
+ ConnEnd dstPt454(Point(673.933, 750.918), 15);
+ connRef454->setDestEndpoint(dstPt454);
+ connRef454->setRoutingType((ConnType)2);
+
+ ConnRef *connRef455 = new ConnRef(router, 455);
+ ConnEnd srcPt455(Point(840, 687), 15);
+ connRef455->setSourceEndpoint(srcPt455);
+ ConnEnd dstPt455(Point(823.246, 750.918), 15);
+ connRef455->setDestEndpoint(dstPt455);
+ connRef455->setRoutingType((ConnType)2);
+
+ ConnRef *connRef456 = new ConnRef(router, 456);
+ ConnEnd srcPt456(Point(132, 195), 15);
+ connRef456->setSourceEndpoint(srcPt456);
+ ConnEnd dstPt456(Point(57.2456, 160.918), 15);
+ connRef456->setDestEndpoint(dstPt456);
+ connRef456->setRoutingType((ConnType)2);
+
+ ConnRef *connRef457 = new ConnRef(router, 457);
+ ConnEnd srcPt457(Point(132, 338), 15);
+ connRef457->setSourceEndpoint(srcPt457);
+ ConnEnd dstPt457(Point(57.2456, 332.918), 15);
+ connRef457->setDestEndpoint(dstPt457);
+ connRef457->setRoutingType((ConnType)2);
+
+ ConnRef *connRef458 = new ConnRef(router, 458);
+ ConnEnd srcPt458(Point(992, 319), 15);
+ connRef458->setSourceEndpoint(srcPt458);
+ ConnEnd dstPt458(Point(979.246, 332.918), 15);
+ connRef458->setDestEndpoint(dstPt458);
+ connRef458->setRoutingType((ConnType)2);
+
+ ConnRef *connRef459 = new ConnRef(router, 459);
+ ConnEnd srcPt459(Point(850, 319), 15);
+ connRef459->setSourceEndpoint(srcPt459);
+ ConnEnd dstPt459(Point(823.246, 332.918), 15);
+ connRef459->setDestEndpoint(dstPt459);
+ connRef459->setRoutingType((ConnType)2);
+
+ ConnRef *connRef460 = new ConnRef(router, 460);
+ ConnEnd srcPt460(Point(709, 319), 15);
+ connRef460->setSourceEndpoint(srcPt460);
+ ConnEnd dstPt460(Point(673.933, 332.918), 15);
+ connRef460->setDestEndpoint(dstPt460);
+ connRef460->setRoutingType((ConnType)2);
+
+ ConnRef *connRef461 = new ConnRef(router, 461);
+ ConnEnd srcPt461(Point(567, 319), 15);
+ connRef461->setSourceEndpoint(srcPt461);
+ ConnEnd dstPt461(Point(527.246, 332.918), 15);
+ connRef461->setDestEndpoint(dstPt461);
+ connRef461->setRoutingType((ConnType)2);
+
+ ConnRef *connRef462 = new ConnRef(router, 462);
+ ConnEnd srcPt462(Point(425, 319), 15);
+ connRef462->setSourceEndpoint(srcPt462);
+ ConnEnd dstPt462(Point(371.246, 332.918), 15);
+ connRef462->setDestEndpoint(dstPt462);
+ connRef462->setRoutingType((ConnType)2);
+
+ ConnRef *connRef463 = new ConnRef(router, 463);
+ ConnEnd srcPt463(Point(273, 309), 15);
+ connRef463->setSourceEndpoint(srcPt463);
+ ConnEnd dstPt463(Point(215.246, 332.918), 15);
+ connRef463->setDestEndpoint(dstPt463);
+ connRef463->setRoutingType((ConnType)2);
+
+ ConnRef *connRef464 = new ConnRef(router, 464);
+ ConnEnd srcPt464(Point(982, 687), 15);
+ connRef464->setSourceEndpoint(srcPt464);
+ ConnEnd dstPt464(Point(979.246, 750.918), 15);
+ connRef464->setDestEndpoint(dstPt464);
+ connRef464->setRoutingType((ConnType)2);
+
+ ConnRef *connRef465 = new ConnRef(router, 465);
+ ConnEnd srcPt465(Point(932, 668), 15);
+ connRef465->setSourceEndpoint(srcPt465);
+ ConnEnd dstPt465(Point(979.246, 750.918), 15);
+ connRef465->setDestEndpoint(dstPt465);
+ connRef465->setRoutingType((ConnType)2);
+
+ ConnRef *connRef466 = new ConnRef(router, 466);
+ ConnEnd srcPt466(Point(982, 577), 15);
+ connRef466->setSourceEndpoint(srcPt466);
+ ConnEnd dstPt466(Point(979.246, 676.918), 15);
+ connRef466->setDestEndpoint(dstPt466);
+ connRef466->setRoutingType((ConnType)2);
+
+ ConnRef *connRef467 = new ConnRef(router, 467);
+ ConnEnd srcPt467(Point(982, 557), 15);
+ connRef467->setSourceEndpoint(srcPt467);
+ ConnEnd dstPt467(Point(979.246, 558.918), 15);
+ connRef467->setDestEndpoint(dstPt467);
+ connRef467->setRoutingType((ConnType)2);
+
+ ConnRef *connRef468 = new ConnRef(router, 468);
+ ConnEnd srcPt468(Point(932, 596), 15);
+ connRef468->setSourceEndpoint(srcPt468);
+ ConnEnd dstPt468(Point(979.246, 676.918), 15);
+ connRef468->setDestEndpoint(dstPt468);
+ connRef468->setRoutingType((ConnType)2);
+
+ ConnRef *connRef469 = new ConnRef(router, 469);
+ ConnEnd srcPt469(Point(932, 576), 15);
+ connRef469->setSourceEndpoint(srcPt469);
+ ConnEnd dstPt469(Point(979.246, 558.918), 15);
+ connRef469->setDestEndpoint(dstPt469);
+ connRef469->setRoutingType((ConnType)2);
+
+ ConnRef *connRef470 = new ConnRef(router, 470);
+ ConnEnd srcPt470(Point(932, 577), 15);
+ connRef470->setSourceEndpoint(srcPt470);
+ ConnEnd dstPt470(Point(979.246, 676.918), 15);
+ connRef470->setDestEndpoint(dstPt470);
+ connRef470->setRoutingType((ConnType)2);
+
+ ConnRef *connRef471 = new ConnRef(router, 471);
+ ConnEnd srcPt471(Point(932, 557), 15);
+ connRef471->setSourceEndpoint(srcPt471);
+ ConnEnd dstPt471(Point(979.246, 558.918), 15);
+ connRef471->setDestEndpoint(dstPt471);
+ connRef471->setRoutingType((ConnType)2);
+
+ ConnRef *connRef472 = new ConnRef(router, 472);
+ ConnEnd srcPt472(Point(932, 505), 15);
+ connRef472->setSourceEndpoint(srcPt472);
+ ConnEnd dstPt472(Point(979.246, 558.918), 15);
+ connRef472->setDestEndpoint(dstPt472);
+ connRef472->setRoutingType((ConnType)2);
+
+ ConnRef *connRef473 = new ConnRef(router, 473);
+ ConnEnd srcPt473(Point(932, 485), 15);
+ connRef473->setSourceEndpoint(srcPt473);
+ ConnEnd dstPt473(Point(979.246, 447.955), 15);
+ connRef473->setDestEndpoint(dstPt473);
+ connRef473->setRoutingType((ConnType)2);
+
+ ConnRef *connRef474 = new ConnRef(router, 474);
+ ConnEnd srcPt474(Point(932, 486), 15);
+ connRef474->setSourceEndpoint(srcPt474);
+ ConnEnd dstPt474(Point(979.246, 558.918), 15);
+ connRef474->setDestEndpoint(dstPt474);
+ connRef474->setRoutingType((ConnType)2);
+
+ ConnRef *connRef475 = new ConnRef(router, 475);
+ ConnEnd srcPt475(Point(932, 466), 15);
+ connRef475->setSourceEndpoint(srcPt475);
+ ConnEnd dstPt475(Point(979.246, 447.955), 15);
+ connRef475->setDestEndpoint(dstPt475);
+ connRef475->setRoutingType((ConnType)2);
+
+ ConnRef *connRef476 = new ConnRef(router, 476);
+ ConnEnd srcPt476(Point(982, 414), 15);
+ connRef476->setSourceEndpoint(srcPt476);
+ ConnEnd dstPt476(Point(979.246, 447.955), 15);
+ connRef476->setDestEndpoint(dstPt476);
+ connRef476->setRoutingType((ConnType)2);
+
+ ConnRef *connRef477 = new ConnRef(router, 477);
+ ConnEnd srcPt477(Point(982, 394), 15);
+ connRef477->setSourceEndpoint(srcPt477);
+ ConnEnd dstPt477(Point(979.246, 332.918), 15);
+ connRef477->setDestEndpoint(dstPt477);
+ connRef477->setRoutingType((ConnType)2);
+
+ ConnRef *connRef478 = new ConnRef(router, 478);
+ ConnEnd srcPt478(Point(932, 414), 15);
+ connRef478->setSourceEndpoint(srcPt478);
+ ConnEnd dstPt478(Point(979.246, 447.955), 15);
+ connRef478->setDestEndpoint(dstPt478);
+ connRef478->setRoutingType((ConnType)2);
+
+ ConnRef *connRef479 = new ConnRef(router, 479);
+ ConnEnd srcPt479(Point(932, 394), 15);
+ connRef479->setSourceEndpoint(srcPt479);
+ ConnEnd dstPt479(Point(979.246, 332.918), 15);
+ connRef479->setDestEndpoint(dstPt479);
+ connRef479->setRoutingType((ConnType)2);
+
+ ConnRef *connRef480 = new ConnRef(router, 480);
+ ConnEnd srcPt480(Point(932, 395), 15);
+ connRef480->setSourceEndpoint(srcPt480);
+ ConnEnd dstPt480(Point(979.246, 447.955), 15);
+ connRef480->setDestEndpoint(dstPt480);
+ connRef480->setRoutingType((ConnType)2);
+
+ ConnRef *connRef481 = new ConnRef(router, 481);
+ ConnEnd srcPt481(Point(932, 375), 15);
+ connRef481->setSourceEndpoint(srcPt481);
+ ConnEnd dstPt481(Point(979.246, 332.918), 15);
+ connRef481->setDestEndpoint(dstPt481);
+ connRef481->setRoutingType((ConnType)2);
+
+ ConnRef *connRef482 = new ConnRef(router, 482);
+ ConnEnd srcPt482(Point(992, 300), 15);
+ connRef482->setSourceEndpoint(srcPt482);
+ ConnEnd dstPt482(Point(979.246, 332.918), 15);
+ connRef482->setDestEndpoint(dstPt482);
+ connRef482->setRoutingType((ConnType)2);
+
+ ConnRef *connRef483 = new ConnRef(router, 483);
+ ConnEnd srcPt483(Point(942, 309), 15);
+ connRef483->setSourceEndpoint(srcPt483);
+ ConnEnd dstPt483(Point(979.246, 332.918), 15);
+ connRef483->setDestEndpoint(dstPt483);
+ connRef483->setRoutingType((ConnType)2);
+
+ ConnRef *connRef484 = new ConnRef(router, 484);
+ ConnEnd srcPt484(Point(942, 290), 15);
+ connRef484->setSourceEndpoint(srcPt484);
+ ConnEnd dstPt484(Point(979.246, 332.918), 15);
+ connRef484->setDestEndpoint(dstPt484);
+ connRef484->setRoutingType((ConnType)2);
+
+ ConnRef *connRef485 = new ConnRef(router, 485);
+ ConnEnd srcPt485(Point(840, 557), 15);
+ connRef485->setSourceEndpoint(srcPt485);
+ ConnEnd dstPt485(Point(823.246, 558.918), 15);
+ connRef485->setDestEndpoint(dstPt485);
+ connRef485->setRoutingType((ConnType)2);
+
+ ConnRef *connRef486 = new ConnRef(router, 486);
+ ConnEnd srcPt486(Point(840, 577), 15);
+ connRef486->setSourceEndpoint(srcPt486);
+ ConnEnd dstPt486(Point(823.246, 676.918), 15);
+ connRef486->setDestEndpoint(dstPt486);
+ connRef486->setRoutingType((ConnType)2);
+
+ ConnRef *connRef487 = new ConnRef(router, 487);
+ ConnEnd srcPt487(Point(790, 576), 15);
+ connRef487->setSourceEndpoint(srcPt487);
+ ConnEnd dstPt487(Point(823.246, 558.918), 15);
+ connRef487->setDestEndpoint(dstPt487);
+ connRef487->setRoutingType((ConnType)2);
+
+ ConnRef *connRef488 = new ConnRef(router, 488);
+ ConnEnd srcPt488(Point(790, 596), 15);
+ connRef488->setSourceEndpoint(srcPt488);
+ ConnEnd dstPt488(Point(823.246, 676.918), 15);
+ connRef488->setDestEndpoint(dstPt488);
+ connRef488->setRoutingType((ConnType)2);
+
+ ConnRef *connRef489 = new ConnRef(router, 489);
+ ConnEnd srcPt489(Point(790, 557), 15);
+ connRef489->setSourceEndpoint(srcPt489);
+ ConnEnd dstPt489(Point(823.246, 558.918), 15);
+ connRef489->setDestEndpoint(dstPt489);
+ connRef489->setRoutingType((ConnType)2);
+
+ ConnRef *connRef490 = new ConnRef(router, 490);
+ ConnEnd srcPt490(Point(790, 577), 15);
+ connRef490->setSourceEndpoint(srcPt490);
+ ConnEnd dstPt490(Point(823.246, 676.918), 15);
+ connRef490->setDestEndpoint(dstPt490);
+ connRef490->setRoutingType((ConnType)2);
+
+ ConnRef *connRef491 = new ConnRef(router, 491);
+ ConnEnd srcPt491(Point(790, 485), 15);
+ connRef491->setSourceEndpoint(srcPt491);
+ ConnEnd dstPt491(Point(823.246, 447.955), 15);
+ connRef491->setDestEndpoint(dstPt491);
+ connRef491->setRoutingType((ConnType)2);
+
+ ConnRef *connRef492 = new ConnRef(router, 492);
+ ConnEnd srcPt492(Point(790, 505), 15);
+ connRef492->setSourceEndpoint(srcPt492);
+ ConnEnd dstPt492(Point(823.246, 558.918), 15);
+ connRef492->setDestEndpoint(dstPt492);
+ connRef492->setRoutingType((ConnType)2);
+
+ ConnRef *connRef493 = new ConnRef(router, 493);
+ ConnEnd srcPt493(Point(790, 466), 15);
+ connRef493->setSourceEndpoint(srcPt493);
+ ConnEnd dstPt493(Point(823.246, 447.955), 15);
+ connRef493->setDestEndpoint(dstPt493);
+ connRef493->setRoutingType((ConnType)2);
+
+ ConnRef *connRef494 = new ConnRef(router, 494);
+ ConnEnd srcPt494(Point(790, 486), 15);
+ connRef494->setSourceEndpoint(srcPt494);
+ ConnEnd dstPt494(Point(823.246, 558.918), 15);
+ connRef494->setDestEndpoint(dstPt494);
+ connRef494->setRoutingType((ConnType)2);
+
+ ConnRef *connRef495 = new ConnRef(router, 495);
+ ConnEnd srcPt495(Point(840, 394), 15);
+ connRef495->setSourceEndpoint(srcPt495);
+ ConnEnd dstPt495(Point(823.246, 332.918), 15);
+ connRef495->setDestEndpoint(dstPt495);
+ connRef495->setRoutingType((ConnType)2);
+
+ ConnRef *connRef496 = new ConnRef(router, 496);
+ ConnEnd srcPt496(Point(840, 414), 15);
+ connRef496->setSourceEndpoint(srcPt496);
+ ConnEnd dstPt496(Point(823.246, 447.955), 15);
+ connRef496->setDestEndpoint(dstPt496);
+ connRef496->setRoutingType((ConnType)2);
+
+ ConnRef *connRef497 = new ConnRef(router, 497);
+ ConnEnd srcPt497(Point(790, 394), 15);
+ connRef497->setSourceEndpoint(srcPt497);
+ ConnEnd dstPt497(Point(823.246, 332.918), 15);
+ connRef497->setDestEndpoint(dstPt497);
+ connRef497->setRoutingType((ConnType)2);
+
+ ConnRef *connRef498 = new ConnRef(router, 498);
+ ConnEnd srcPt498(Point(790, 414), 15);
+ connRef498->setSourceEndpoint(srcPt498);
+ ConnEnd dstPt498(Point(823.246, 447.955), 15);
+ connRef498->setDestEndpoint(dstPt498);
+ connRef498->setRoutingType((ConnType)2);
+
+ ConnRef *connRef499 = new ConnRef(router, 499);
+ ConnEnd srcPt499(Point(790, 375), 15);
+ connRef499->setSourceEndpoint(srcPt499);
+ ConnEnd dstPt499(Point(823.246, 332.918), 15);
+ connRef499->setDestEndpoint(dstPt499);
+ connRef499->setRoutingType((ConnType)2);
+
+ ConnRef *connRef500 = new ConnRef(router, 500);
+ ConnEnd srcPt500(Point(790, 395), 15);
+ connRef500->setSourceEndpoint(srcPt500);
+ ConnEnd dstPt500(Point(823.246, 447.955), 15);
+ connRef500->setDestEndpoint(dstPt500);
+ connRef500->setRoutingType((ConnType)2);
+
+ ConnRef *connRef501 = new ConnRef(router, 501);
+ ConnEnd srcPt501(Point(850, 300), 15);
+ connRef501->setSourceEndpoint(srcPt501);
+ ConnEnd dstPt501(Point(823.246, 332.918), 15);
+ connRef501->setDestEndpoint(dstPt501);
+ connRef501->setRoutingType((ConnType)2);
+
+ ConnRef *connRef502 = new ConnRef(router, 502);
+ ConnEnd srcPt502(Point(800, 309), 15);
+ connRef502->setSourceEndpoint(srcPt502);
+ ConnEnd dstPt502(Point(823.246, 332.918), 15);
+ connRef502->setDestEndpoint(dstPt502);
+ connRef502->setRoutingType((ConnType)2);
+
+ ConnRef *connRef503 = new ConnRef(router, 503);
+ ConnEnd srcPt503(Point(800, 290), 15);
+ connRef503->setSourceEndpoint(srcPt503);
+ ConnEnd dstPt503(Point(823.246, 332.918), 15);
+ connRef503->setDestEndpoint(dstPt503);
+ connRef503->setRoutingType((ConnType)2);
+
+ ConnRef *connRef504 = new ConnRef(router, 504);
+ ConnEnd srcPt504(Point(699, 577), 15);
+ connRef504->setSourceEndpoint(srcPt504);
+ ConnEnd dstPt504(Point(673.933, 676.918), 15);
+ connRef504->setDestEndpoint(dstPt504);
+ connRef504->setRoutingType((ConnType)2);
+
+ ConnRef *connRef505 = new ConnRef(router, 505);
+ ConnEnd srcPt505(Point(699, 557), 15);
+ connRef505->setSourceEndpoint(srcPt505);
+ ConnEnd dstPt505(Point(673.933, 558.918), 15);
+ connRef505->setDestEndpoint(dstPt505);
+ connRef505->setRoutingType((ConnType)2);
+
+ ConnRef *connRef506 = new ConnRef(router, 506);
+ ConnEnd srcPt506(Point(649, 596), 15);
+ connRef506->setSourceEndpoint(srcPt506);
+ ConnEnd dstPt506(Point(673.933, 676.918), 15);
+ connRef506->setDestEndpoint(dstPt506);
+ connRef506->setRoutingType((ConnType)2);
+
+ ConnRef *connRef507 = new ConnRef(router, 507);
+ ConnEnd srcPt507(Point(649, 576), 15);
+ connRef507->setSourceEndpoint(srcPt507);
+ ConnEnd dstPt507(Point(673.933, 558.918), 15);
+ connRef507->setDestEndpoint(dstPt507);
+ connRef507->setRoutingType((ConnType)2);
+
+ ConnRef *connRef508 = new ConnRef(router, 508);
+ ConnEnd srcPt508(Point(649, 577), 15);
+ connRef508->setSourceEndpoint(srcPt508);
+ ConnEnd dstPt508(Point(673.933, 676.918), 15);
+ connRef508->setDestEndpoint(dstPt508);
+ connRef508->setRoutingType((ConnType)2);
+
+ ConnRef *connRef509 = new ConnRef(router, 509);
+ ConnEnd srcPt509(Point(649, 557), 15);
+ connRef509->setSourceEndpoint(srcPt509);
+ ConnEnd dstPt509(Point(673.933, 558.918), 15);
+ connRef509->setDestEndpoint(dstPt509);
+ connRef509->setRoutingType((ConnType)2);
+
+ ConnRef *connRef510 = new ConnRef(router, 510);
+ ConnEnd srcPt510(Point(649, 505), 15);
+ connRef510->setSourceEndpoint(srcPt510);
+ ConnEnd dstPt510(Point(673.933, 558.918), 15);
+ connRef510->setDestEndpoint(dstPt510);
+ connRef510->setRoutingType((ConnType)2);
+
+ ConnRef *connRef511 = new ConnRef(router, 511);
+ ConnEnd srcPt511(Point(649, 485), 15);
+ connRef511->setSourceEndpoint(srcPt511);
+ ConnEnd dstPt511(Point(673.933, 447.955), 15);
+ connRef511->setDestEndpoint(dstPt511);
+ connRef511->setRoutingType((ConnType)2);
+
+ ConnRef *connRef512 = new ConnRef(router, 512);
+ ConnEnd srcPt512(Point(649, 486), 15);
+ connRef512->setSourceEndpoint(srcPt512);
+ ConnEnd dstPt512(Point(673.933, 558.918), 15);
+ connRef512->setDestEndpoint(dstPt512);
+ connRef512->setRoutingType((ConnType)2);
+
+ ConnRef *connRef513 = new ConnRef(router, 513);
+ ConnEnd srcPt513(Point(649, 466), 15);
+ connRef513->setSourceEndpoint(srcPt513);
+ ConnEnd dstPt513(Point(673.933, 447.955), 15);
+ connRef513->setDestEndpoint(dstPt513);
+ connRef513->setRoutingType((ConnType)2);
+
+ ConnRef *connRef514 = new ConnRef(router, 514);
+ ConnEnd srcPt514(Point(699, 414), 15);
+ connRef514->setSourceEndpoint(srcPt514);
+ ConnEnd dstPt514(Point(673.933, 447.955), 15);
+ connRef514->setDestEndpoint(dstPt514);
+ connRef514->setRoutingType((ConnType)2);
+
+ ConnRef *connRef515 = new ConnRef(router, 515);
+ ConnEnd srcPt515(Point(699, 394), 15);
+ connRef515->setSourceEndpoint(srcPt515);
+ ConnEnd dstPt515(Point(673.933, 332.918), 15);
+ connRef515->setDestEndpoint(dstPt515);
+ connRef515->setRoutingType((ConnType)2);
+
+ ConnRef *connRef516 = new ConnRef(router, 516);
+ ConnEnd srcPt516(Point(649, 414), 15);
+ connRef516->setSourceEndpoint(srcPt516);
+ ConnEnd dstPt516(Point(673.933, 447.955), 15);
+ connRef516->setDestEndpoint(dstPt516);
+ connRef516->setRoutingType((ConnType)2);
+
+ ConnRef *connRef517 = new ConnRef(router, 517);
+ ConnEnd srcPt517(Point(649, 394), 15);
+ connRef517->setSourceEndpoint(srcPt517);
+ ConnEnd dstPt517(Point(673.933, 332.918), 15);
+ connRef517->setDestEndpoint(dstPt517);
+ connRef517->setRoutingType((ConnType)2);
+
+ ConnRef *connRef518 = new ConnRef(router, 518);
+ ConnEnd srcPt518(Point(649, 395), 15);
+ connRef518->setSourceEndpoint(srcPt518);
+ ConnEnd dstPt518(Point(673.933, 447.955), 15);
+ connRef518->setDestEndpoint(dstPt518);
+ connRef518->setRoutingType((ConnType)2);
+
+ ConnRef *connRef519 = new ConnRef(router, 519);
+ ConnEnd srcPt519(Point(649, 375), 15);
+ connRef519->setSourceEndpoint(srcPt519);
+ ConnEnd dstPt519(Point(673.933, 332.918), 15);
+ connRef519->setDestEndpoint(dstPt519);
+ connRef519->setRoutingType((ConnType)2);
+
+ ConnRef *connRef520 = new ConnRef(router, 520);
+ ConnEnd srcPt520(Point(709, 300), 15);
+ connRef520->setSourceEndpoint(srcPt520);
+ ConnEnd dstPt520(Point(673.933, 332.918), 15);
+ connRef520->setDestEndpoint(dstPt520);
+ connRef520->setRoutingType((ConnType)2);
+
+ ConnRef *connRef521 = new ConnRef(router, 521);
+ ConnEnd srcPt521(Point(659, 309), 15);
+ connRef521->setSourceEndpoint(srcPt521);
+ ConnEnd dstPt521(Point(673.933, 332.918), 15);
+ connRef521->setDestEndpoint(dstPt521);
+ connRef521->setRoutingType((ConnType)2);
+
+ ConnRef *connRef522 = new ConnRef(router, 522);
+ ConnEnd srcPt522(Point(659, 290), 15);
+ connRef522->setSourceEndpoint(srcPt522);
+ ConnEnd dstPt522(Point(673.933, 332.918), 15);
+ connRef522->setDestEndpoint(dstPt522);
+ connRef522->setRoutingType((ConnType)2);
+
+ ConnRef *connRef523 = new ConnRef(router, 523);
+ ConnEnd srcPt523(Point(557, 557), 15);
+ connRef523->setSourceEndpoint(srcPt523);
+ ConnEnd dstPt523(Point(527.246, 558.918), 15);
+ connRef523->setDestEndpoint(dstPt523);
+ connRef523->setRoutingType((ConnType)2);
+
+ ConnRef *connRef524 = new ConnRef(router, 524);
+ ConnEnd srcPt524(Point(557, 577), 15);
+ connRef524->setSourceEndpoint(srcPt524);
+ ConnEnd dstPt524(Point(527.246, 676.918), 15);
+ connRef524->setDestEndpoint(dstPt524);
+ connRef524->setRoutingType((ConnType)2);
+
+ ConnRef *connRef525 = new ConnRef(router, 525);
+ ConnEnd srcPt525(Point(507, 576), 15);
+ connRef525->setSourceEndpoint(srcPt525);
+ ConnEnd dstPt525(Point(527.246, 558.918), 15);
+ connRef525->setDestEndpoint(dstPt525);
+ connRef525->setRoutingType((ConnType)2);
+
+ ConnRef *connRef526 = new ConnRef(router, 526);
+ ConnEnd srcPt526(Point(507, 596), 15);
+ connRef526->setSourceEndpoint(srcPt526);
+ ConnEnd dstPt526(Point(527.246, 676.918), 15);
+ connRef526->setDestEndpoint(dstPt526);
+ connRef526->setRoutingType((ConnType)2);
+
+ ConnRef *connRef527 = new ConnRef(router, 527);
+ ConnEnd srcPt527(Point(507, 557), 15);
+ connRef527->setSourceEndpoint(srcPt527);
+ ConnEnd dstPt527(Point(527.246, 558.918), 15);
+ connRef527->setDestEndpoint(dstPt527);
+ connRef527->setRoutingType((ConnType)2);
+
+ ConnRef *connRef528 = new ConnRef(router, 528);
+ ConnEnd srcPt528(Point(507, 577), 15);
+ connRef528->setSourceEndpoint(srcPt528);
+ ConnEnd dstPt528(Point(527.246, 676.918), 15);
+ connRef528->setDestEndpoint(dstPt528);
+ connRef528->setRoutingType((ConnType)2);
+
+ ConnRef *connRef529 = new ConnRef(router, 529);
+ ConnEnd srcPt529(Point(557, 477), 15);
+ connRef529->setSourceEndpoint(srcPt529);
+ ConnEnd dstPt529(Point(527.246, 447.955), 15);
+ connRef529->setDestEndpoint(dstPt529);
+ connRef529->setRoutingType((ConnType)2);
+
+ ConnRef *connRef530 = new ConnRef(router, 530);
+ ConnEnd srcPt530(Point(557, 497), 15);
+ connRef530->setSourceEndpoint(srcPt530);
+ ConnEnd dstPt530(Point(527.246, 558.918), 15);
+ connRef530->setDestEndpoint(dstPt530);
+ connRef530->setRoutingType((ConnType)2);
+
+ ConnRef *connRef531 = new ConnRef(router, 531);
+ ConnEnd srcPt531(Point(507, 485), 15);
+ connRef531->setSourceEndpoint(srcPt531);
+ ConnEnd dstPt531(Point(527.246, 447.955), 15);
+ connRef531->setDestEndpoint(dstPt531);
+ connRef531->setRoutingType((ConnType)2);
+
+ ConnRef *connRef532 = new ConnRef(router, 532);
+ ConnEnd srcPt532(Point(507, 505), 15);
+ connRef532->setSourceEndpoint(srcPt532);
+ ConnEnd dstPt532(Point(527.246, 558.918), 15);
+ connRef532->setDestEndpoint(dstPt532);
+ connRef532->setRoutingType((ConnType)2);
+
+ ConnRef *connRef533 = new ConnRef(router, 533);
+ ConnEnd srcPt533(Point(507, 466), 15);
+ connRef533->setSourceEndpoint(srcPt533);
+ ConnEnd dstPt533(Point(527.246, 447.955), 15);
+ connRef533->setDestEndpoint(dstPt533);
+ connRef533->setRoutingType((ConnType)2);
+
+ ConnRef *connRef534 = new ConnRef(router, 534);
+ ConnEnd srcPt534(Point(507, 486), 15);
+ connRef534->setSourceEndpoint(srcPt534);
+ ConnEnd dstPt534(Point(527.246, 558.918), 15);
+ connRef534->setDestEndpoint(dstPt534);
+ connRef534->setRoutingType((ConnType)2);
+
+ ConnRef *connRef535 = new ConnRef(router, 535);
+ ConnEnd srcPt535(Point(557, 394), 15);
+ connRef535->setSourceEndpoint(srcPt535);
+ ConnEnd dstPt535(Point(527.246, 332.918), 15);
+ connRef535->setDestEndpoint(dstPt535);
+ connRef535->setRoutingType((ConnType)2);
+
+ ConnRef *connRef536 = new ConnRef(router, 536);
+ ConnEnd srcPt536(Point(557, 414), 15);
+ connRef536->setSourceEndpoint(srcPt536);
+ ConnEnd dstPt536(Point(527.246, 447.955), 15);
+ connRef536->setDestEndpoint(dstPt536);
+ connRef536->setRoutingType((ConnType)2);
+
+ ConnRef *connRef537 = new ConnRef(router, 537);
+ ConnEnd srcPt537(Point(507, 394), 15);
+ connRef537->setSourceEndpoint(srcPt537);
+ ConnEnd dstPt537(Point(527.246, 332.918), 15);
+ connRef537->setDestEndpoint(dstPt537);
+ connRef537->setRoutingType((ConnType)2);
+
+ ConnRef *connRef538 = new ConnRef(router, 538);
+ ConnEnd srcPt538(Point(507, 414), 15);
+ connRef538->setSourceEndpoint(srcPt538);
+ ConnEnd dstPt538(Point(527.246, 447.955), 15);
+ connRef538->setDestEndpoint(dstPt538);
+ connRef538->setRoutingType((ConnType)2);
+
+ ConnRef *connRef539 = new ConnRef(router, 539);
+ ConnEnd srcPt539(Point(507, 375), 15);
+ connRef539->setSourceEndpoint(srcPt539);
+ ConnEnd dstPt539(Point(527.246, 332.918), 15);
+ connRef539->setDestEndpoint(dstPt539);
+ connRef539->setRoutingType((ConnType)2);
+
+ ConnRef *connRef540 = new ConnRef(router, 540);
+ ConnEnd srcPt540(Point(507, 395), 15);
+ connRef540->setSourceEndpoint(srcPt540);
+ ConnEnd dstPt540(Point(527.246, 447.955), 15);
+ connRef540->setDestEndpoint(dstPt540);
+ connRef540->setRoutingType((ConnType)2);
+
+ ConnRef *connRef541 = new ConnRef(router, 541);
+ ConnEnd srcPt541(Point(567, 300), 15);
+ connRef541->setSourceEndpoint(srcPt541);
+ ConnEnd dstPt541(Point(527.246, 332.918), 15);
+ connRef541->setDestEndpoint(dstPt541);
+ connRef541->setRoutingType((ConnType)2);
+
+ ConnRef *connRef542 = new ConnRef(router, 542);
+ ConnEnd srcPt542(Point(517, 309), 15);
+ connRef542->setSourceEndpoint(srcPt542);
+ ConnEnd dstPt542(Point(527.246, 332.918), 15);
+ connRef542->setDestEndpoint(dstPt542);
+ connRef542->setRoutingType((ConnType)2);
+
+ ConnRef *connRef543 = new ConnRef(router, 543);
+ ConnEnd srcPt543(Point(517, 290), 15);
+ connRef543->setSourceEndpoint(srcPt543);
+ ConnEnd dstPt543(Point(527.246, 332.918), 15);
+ connRef543->setDestEndpoint(dstPt543);
+ connRef543->setRoutingType((ConnType)2);
+
+ ConnRef *connRef544 = new ConnRef(router, 544);
+ ConnEnd srcPt544(Point(415, 577), 15);
+ connRef544->setSourceEndpoint(srcPt544);
+ ConnEnd dstPt544(Point(371.246, 676.918), 15);
+ connRef544->setDestEndpoint(dstPt544);
+ connRef544->setRoutingType((ConnType)2);
+
+ ConnRef *connRef545 = new ConnRef(router, 545);
+ ConnEnd srcPt545(Point(415, 557), 15);
+ connRef545->setSourceEndpoint(srcPt545);
+ ConnEnd dstPt545(Point(371.246, 558.918), 15);
+ connRef545->setDestEndpoint(dstPt545);
+ connRef545->setRoutingType((ConnType)2);
+
+ ConnRef *connRef546 = new ConnRef(router, 546);
+ ConnEnd srcPt546(Point(365, 596), 15);
+ connRef546->setSourceEndpoint(srcPt546);
+ ConnEnd dstPt546(Point(371.246, 676.918), 15);
+ connRef546->setDestEndpoint(dstPt546);
+ connRef546->setRoutingType((ConnType)2);
+
+ ConnRef *connRef547 = new ConnRef(router, 547);
+ ConnEnd srcPt547(Point(365, 576), 15);
+ connRef547->setSourceEndpoint(srcPt547);
+ ConnEnd dstPt547(Point(371.246, 558.918), 15);
+ connRef547->setDestEndpoint(dstPt547);
+ connRef547->setRoutingType((ConnType)2);
+
+ ConnRef *connRef548 = new ConnRef(router, 548);
+ ConnEnd srcPt548(Point(365, 577), 15);
+ connRef548->setSourceEndpoint(srcPt548);
+ ConnEnd dstPt548(Point(371.246, 676.918), 15);
+ connRef548->setDestEndpoint(dstPt548);
+ connRef548->setRoutingType((ConnType)2);
+
+ ConnRef *connRef549 = new ConnRef(router, 549);
+ ConnEnd srcPt549(Point(365, 557), 15);
+ connRef549->setSourceEndpoint(srcPt549);
+ ConnEnd dstPt549(Point(371.246, 558.918), 15);
+ connRef549->setDestEndpoint(dstPt549);
+ connRef549->setRoutingType((ConnType)2);
+
+ ConnRef *connRef550 = new ConnRef(router, 550);
+ ConnEnd srcPt550(Point(365, 505), 15);
+ connRef550->setSourceEndpoint(srcPt550);
+ ConnEnd dstPt550(Point(371.246, 558.918), 15);
+ connRef550->setDestEndpoint(dstPt550);
+ connRef550->setRoutingType((ConnType)2);
+
+ ConnRef *connRef551 = new ConnRef(router, 551);
+ ConnEnd srcPt551(Point(365, 485), 15);
+ connRef551->setSourceEndpoint(srcPt551);
+ ConnEnd dstPt551(Point(371.246, 447.955), 15);
+ connRef551->setDestEndpoint(dstPt551);
+ connRef551->setRoutingType((ConnType)2);
+
+ ConnRef *connRef552 = new ConnRef(router, 552);
+ ConnEnd srcPt552(Point(365, 486), 15);
+ connRef552->setSourceEndpoint(srcPt552);
+ ConnEnd dstPt552(Point(371.246, 558.918), 15);
+ connRef552->setDestEndpoint(dstPt552);
+ connRef552->setRoutingType((ConnType)2);
+
+ ConnRef *connRef553 = new ConnRef(router, 553);
+ ConnEnd srcPt553(Point(365, 466), 15);
+ connRef553->setSourceEndpoint(srcPt553);
+ ConnEnd dstPt553(Point(371.246, 447.955), 15);
+ connRef553->setDestEndpoint(dstPt553);
+ connRef553->setRoutingType((ConnType)2);
+
+ ConnRef *connRef554 = new ConnRef(router, 554);
+ ConnEnd srcPt554(Point(415, 414), 15);
+ connRef554->setSourceEndpoint(srcPt554);
+ ConnEnd dstPt554(Point(371.246, 447.955), 15);
+ connRef554->setDestEndpoint(dstPt554);
+ connRef554->setRoutingType((ConnType)2);
+
+ ConnRef *connRef555 = new ConnRef(router, 555);
+ ConnEnd srcPt555(Point(415, 394), 15);
+ connRef555->setSourceEndpoint(srcPt555);
+ ConnEnd dstPt555(Point(371.246, 332.918), 15);
+ connRef555->setDestEndpoint(dstPt555);
+ connRef555->setRoutingType((ConnType)2);
+
+ ConnRef *connRef556 = new ConnRef(router, 556);
+ ConnEnd srcPt556(Point(365, 414), 15);
+ connRef556->setSourceEndpoint(srcPt556);
+ ConnEnd dstPt556(Point(371.246, 447.955), 15);
+ connRef556->setDestEndpoint(dstPt556);
+ connRef556->setRoutingType((ConnType)2);
+
+ ConnRef *connRef557 = new ConnRef(router, 557);
+ ConnEnd srcPt557(Point(365, 394), 15);
+ connRef557->setSourceEndpoint(srcPt557);
+ ConnEnd dstPt557(Point(371.246, 332.918), 15);
+ connRef557->setDestEndpoint(dstPt557);
+ connRef557->setRoutingType((ConnType)2);
+
+ ConnRef *connRef558 = new ConnRef(router, 558);
+ ConnEnd srcPt558(Point(365, 395), 15);
+ connRef558->setSourceEndpoint(srcPt558);
+ ConnEnd dstPt558(Point(371.246, 447.955), 15);
+ connRef558->setDestEndpoint(dstPt558);
+ connRef558->setRoutingType((ConnType)2);
+
+ ConnRef *connRef559 = new ConnRef(router, 559);
+ ConnEnd srcPt559(Point(365, 375), 15);
+ connRef559->setSourceEndpoint(srcPt559);
+ ConnEnd dstPt559(Point(371.246, 332.918), 15);
+ connRef559->setDestEndpoint(dstPt559);
+ connRef559->setRoutingType((ConnType)2);
+
+ ConnRef *connRef560 = new ConnRef(router, 560);
+ ConnEnd srcPt560(Point(425, 300), 15);
+ connRef560->setSourceEndpoint(srcPt560);
+ ConnEnd dstPt560(Point(371.246, 332.918), 15);
+ connRef560->setDestEndpoint(dstPt560);
+ connRef560->setRoutingType((ConnType)2);
+
+ ConnRef *connRef561 = new ConnRef(router, 561);
+ ConnEnd srcPt561(Point(375, 309), 15);
+ connRef561->setSourceEndpoint(srcPt561);
+ ConnEnd dstPt561(Point(371.246, 332.918), 15);
+ connRef561->setDestEndpoint(dstPt561);
+ connRef561->setRoutingType((ConnType)2);
+
+ ConnRef *connRef562 = new ConnRef(router, 562);
+ ConnEnd srcPt562(Point(375, 290), 15);
+ connRef562->setSourceEndpoint(srcPt562);
+ ConnEnd dstPt562(Point(371.246, 332.918), 15);
+ connRef562->setDestEndpoint(dstPt562);
+ connRef562->setRoutingType((ConnType)2);
+
+ ConnRef *connRef563 = new ConnRef(router, 563);
+ ConnEnd srcPt563(Point(273, 557), 15);
+ connRef563->setSourceEndpoint(srcPt563);
+ ConnEnd dstPt563(Point(215.246, 558.918), 15);
+ connRef563->setDestEndpoint(dstPt563);
+ connRef563->setRoutingType((ConnType)2);
+
+ ConnRef *connRef564 = new ConnRef(router, 564);
+ ConnEnd srcPt564(Point(273, 577), 15);
+ connRef564->setSourceEndpoint(srcPt564);
+ ConnEnd dstPt564(Point(215.246, 676.918), 15);
+ connRef564->setDestEndpoint(dstPt564);
+ connRef564->setRoutingType((ConnType)2);
+
+ ConnRef *connRef565 = new ConnRef(router, 565);
+ ConnEnd srcPt565(Point(223, 576), 15);
+ connRef565->setSourceEndpoint(srcPt565);
+ ConnEnd dstPt565(Point(215.246, 558.918), 15);
+ connRef565->setDestEndpoint(dstPt565);
+ connRef565->setRoutingType((ConnType)2);
+
+ ConnRef *connRef566 = new ConnRef(router, 566);
+ ConnEnd srcPt566(Point(223, 596), 15);
+ connRef566->setSourceEndpoint(srcPt566);
+ ConnEnd dstPt566(Point(215.246, 676.918), 15);
+ connRef566->setDestEndpoint(dstPt566);
+ connRef566->setRoutingType((ConnType)2);
+
+ ConnRef *connRef567 = new ConnRef(router, 567);
+ ConnEnd srcPt567(Point(223, 557), 15);
+ connRef567->setSourceEndpoint(srcPt567);
+ ConnEnd dstPt567(Point(215.246, 558.918), 15);
+ connRef567->setDestEndpoint(dstPt567);
+ connRef567->setRoutingType((ConnType)2);
+
+ ConnRef *connRef568 = new ConnRef(router, 568);
+ ConnEnd srcPt568(Point(223, 577), 15);
+ connRef568->setSourceEndpoint(srcPt568);
+ ConnEnd dstPt568(Point(215.246, 676.918), 15);
+ connRef568->setDestEndpoint(dstPt568);
+ connRef568->setRoutingType((ConnType)2);
+
+ ConnRef *connRef569 = new ConnRef(router, 569);
+ ConnEnd srcPt569(Point(223, 485), 15);
+ connRef569->setSourceEndpoint(srcPt569);
+ ConnEnd dstPt569(Point(215.246, 447.955), 15);
+ connRef569->setDestEndpoint(dstPt569);
+ connRef569->setRoutingType((ConnType)2);
+
+ ConnRef *connRef570 = new ConnRef(router, 570);
+ ConnEnd srcPt570(Point(223, 505), 15);
+ connRef570->setSourceEndpoint(srcPt570);
+ ConnEnd dstPt570(Point(215.246, 558.918), 15);
+ connRef570->setDestEndpoint(dstPt570);
+ connRef570->setRoutingType((ConnType)2);
+
+ ConnRef *connRef571 = new ConnRef(router, 571);
+ ConnEnd srcPt571(Point(223, 466), 15);
+ connRef571->setSourceEndpoint(srcPt571);
+ ConnEnd dstPt571(Point(215.246, 447.955), 15);
+ connRef571->setDestEndpoint(dstPt571);
+ connRef571->setRoutingType((ConnType)2);
+
+ ConnRef *connRef572 = new ConnRef(router, 572);
+ ConnEnd srcPt572(Point(223, 486), 15);
+ connRef572->setSourceEndpoint(srcPt572);
+ ConnEnd dstPt572(Point(215.246, 558.918), 15);
+ connRef572->setDestEndpoint(dstPt572);
+ connRef572->setRoutingType((ConnType)2);
+
+ ConnRef *connRef573 = new ConnRef(router, 573);
+ ConnEnd srcPt573(Point(273, 394), 15);
+ connRef573->setSourceEndpoint(srcPt573);
+ ConnEnd dstPt573(Point(215.246, 332.918), 15);
+ connRef573->setDestEndpoint(dstPt573);
+ connRef573->setRoutingType((ConnType)2);
+
+ ConnRef *connRef574 = new ConnRef(router, 574);
+ ConnEnd srcPt574(Point(273, 414), 15);
+ connRef574->setSourceEndpoint(srcPt574);
+ ConnEnd dstPt574(Point(215.246, 447.955), 15);
+ connRef574->setDestEndpoint(dstPt574);
+ connRef574->setRoutingType((ConnType)2);
+
+ ConnRef *connRef575 = new ConnRef(router, 575);
+ ConnEnd srcPt575(Point(223, 394), 15);
+ connRef575->setSourceEndpoint(srcPt575);
+ ConnEnd dstPt575(Point(215.246, 332.918), 15);
+ connRef575->setDestEndpoint(dstPt575);
+ connRef575->setRoutingType((ConnType)2);
+
+ ConnRef *connRef576 = new ConnRef(router, 576);
+ ConnEnd srcPt576(Point(223, 414), 15);
+ connRef576->setSourceEndpoint(srcPt576);
+ ConnEnd dstPt576(Point(215.246, 447.955), 15);
+ connRef576->setDestEndpoint(dstPt576);
+ connRef576->setRoutingType((ConnType)2);
+
+ ConnRef *connRef577 = new ConnRef(router, 577);
+ ConnEnd srcPt577(Point(223, 375), 15);
+ connRef577->setSourceEndpoint(srcPt577);
+ ConnEnd dstPt577(Point(215.246, 332.918), 15);
+ connRef577->setDestEndpoint(dstPt577);
+ connRef577->setRoutingType((ConnType)2);
+
+ ConnRef *connRef578 = new ConnRef(router, 578);
+ ConnEnd srcPt578(Point(223, 395), 15);
+ connRef578->setSourceEndpoint(srcPt578);
+ ConnEnd dstPt578(Point(215.246, 447.955), 15);
+ connRef578->setDestEndpoint(dstPt578);
+ connRef578->setRoutingType((ConnType)2);
+
+ ConnRef *connRef579 = new ConnRef(router, 579);
+ ConnEnd srcPt579(Point(273, 290), 15);
+ connRef579->setSourceEndpoint(srcPt579);
+ ConnEnd dstPt579(Point(215.246, 332.918), 15);
+ connRef579->setDestEndpoint(dstPt579);
+ connRef579->setRoutingType((ConnType)2);
+
+ ConnRef *connRef580 = new ConnRef(router, 580);
+ ConnEnd srcPt580(Point(233, 290), 15);
+ connRef580->setSourceEndpoint(srcPt580);
+ ConnEnd dstPt580(Point(215.246, 332.918), 15);
+ connRef580->setDestEndpoint(dstPt580);
+ connRef580->setRoutingType((ConnType)2);
+
+ ConnRef *connRef581 = new ConnRef(router, 581);
+ ConnEnd srcPt581(Point(233, 309), 15);
+ connRef581->setSourceEndpoint(srcPt581);
+ ConnEnd dstPt581(Point(215.246, 332.918), 15);
+ connRef581->setDestEndpoint(dstPt581);
+ connRef581->setRoutingType((ConnType)2);
+
+ ConnRef *connRef582 = new ConnRef(router, 582);
+ ConnEnd srcPt582(Point(132, 557), 15);
+ connRef582->setSourceEndpoint(srcPt582);
+ ConnEnd dstPt582(Point(57.2456, 558.918), 15);
+ connRef582->setDestEndpoint(dstPt582);
+ connRef582->setRoutingType((ConnType)2);
+
+ ConnRef *connRef583 = new ConnRef(router, 583);
+ ConnEnd srcPt583(Point(132, 577), 15);
+ connRef583->setSourceEndpoint(srcPt583);
+ ConnEnd dstPt583(Point(57.2456, 676.918), 15);
+ connRef583->setDestEndpoint(dstPt583);
+ connRef583->setRoutingType((ConnType)2);
+
+ ConnRef *connRef584 = new ConnRef(router, 584);
+ ConnEnd srcPt584(Point(82, 576), 15);
+ connRef584->setSourceEndpoint(srcPt584);
+ ConnEnd dstPt584(Point(57.2456, 558.918), 15);
+ connRef584->setDestEndpoint(dstPt584);
+ connRef584->setRoutingType((ConnType)2);
+
+ ConnRef *connRef585 = new ConnRef(router, 585);
+ ConnEnd srcPt585(Point(82, 596), 15);
+ connRef585->setSourceEndpoint(srcPt585);
+ ConnEnd dstPt585(Point(57.2456, 676.918), 15);
+ connRef585->setDestEndpoint(dstPt585);
+ connRef585->setRoutingType((ConnType)2);
+
+ ConnRef *connRef586 = new ConnRef(router, 586);
+ ConnEnd srcPt586(Point(82, 557), 15);
+ connRef586->setSourceEndpoint(srcPt586);
+ ConnEnd dstPt586(Point(57.2456, 558.918), 15);
+ connRef586->setDestEndpoint(dstPt586);
+ connRef586->setRoutingType((ConnType)2);
+
+ ConnRef *connRef587 = new ConnRef(router, 587);
+ ConnEnd srcPt587(Point(82, 577), 15);
+ connRef587->setSourceEndpoint(srcPt587);
+ ConnEnd dstPt587(Point(57.2456, 676.918), 15);
+ connRef587->setDestEndpoint(dstPt587);
+ connRef587->setRoutingType((ConnType)2);
+
+ ConnRef *connRef588 = new ConnRef(router, 588);
+ ConnEnd srcPt588(Point(82, 485), 15);
+ connRef588->setSourceEndpoint(srcPt588);
+ ConnEnd dstPt588(Point(57.2456, 447.955), 15);
+ connRef588->setDestEndpoint(dstPt588);
+ connRef588->setRoutingType((ConnType)2);
+
+ ConnRef *connRef589 = new ConnRef(router, 589);
+ ConnEnd srcPt589(Point(82, 505), 15);
+ connRef589->setSourceEndpoint(srcPt589);
+ ConnEnd dstPt589(Point(57.2456, 558.918), 15);
+ connRef589->setDestEndpoint(dstPt589);
+ connRef589->setRoutingType((ConnType)2);
+
+ ConnRef *connRef590 = new ConnRef(router, 590);
+ ConnEnd srcPt590(Point(82, 466), 15);
+ connRef590->setSourceEndpoint(srcPt590);
+ ConnEnd dstPt590(Point(57.2456, 447.955), 15);
+ connRef590->setDestEndpoint(dstPt590);
+ connRef590->setRoutingType((ConnType)2);
+
+ ConnRef *connRef591 = new ConnRef(router, 591);
+ ConnEnd srcPt591(Point(82, 486), 15);
+ connRef591->setSourceEndpoint(srcPt591);
+ ConnEnd dstPt591(Point(57.2456, 558.918), 15);
+ connRef591->setDestEndpoint(dstPt591);
+ connRef591->setRoutingType((ConnType)2);
+
+ ConnRef *connRef592 = new ConnRef(router, 592);
+ ConnEnd srcPt592(Point(132, 394), 15);
+ connRef592->setSourceEndpoint(srcPt592);
+ ConnEnd dstPt592(Point(57.2456, 332.918), 15);
+ connRef592->setDestEndpoint(dstPt592);
+ connRef592->setRoutingType((ConnType)2);
+
+ ConnRef *connRef593 = new ConnRef(router, 593);
+ ConnEnd srcPt593(Point(132, 414), 15);
+ connRef593->setSourceEndpoint(srcPt593);
+ ConnEnd dstPt593(Point(57.2456, 447.955), 15);
+ connRef593->setDestEndpoint(dstPt593);
+ connRef593->setRoutingType((ConnType)2);
+
+ ConnRef *connRef594 = new ConnRef(router, 594);
+ ConnEnd srcPt594(Point(82, 394), 15);
+ connRef594->setSourceEndpoint(srcPt594);
+ ConnEnd dstPt594(Point(57.2456, 332.918), 15);
+ connRef594->setDestEndpoint(dstPt594);
+ connRef594->setRoutingType((ConnType)2);
+
+ ConnRef *connRef595 = new ConnRef(router, 595);
+ ConnEnd srcPt595(Point(82, 414), 15);
+ connRef595->setSourceEndpoint(srcPt595);
+ ConnEnd dstPt595(Point(57.2456, 447.955), 15);
+ connRef595->setDestEndpoint(dstPt595);
+ connRef595->setRoutingType((ConnType)2);
+
+ ConnRef *connRef596 = new ConnRef(router, 596);
+ ConnEnd srcPt596(Point(82, 375), 15);
+ connRef596->setSourceEndpoint(srcPt596);
+ ConnEnd dstPt596(Point(57.2456, 332.918), 15);
+ connRef596->setDestEndpoint(dstPt596);
+ connRef596->setRoutingType((ConnType)2);
+
+ ConnRef *connRef597 = new ConnRef(router, 597);
+ ConnEnd srcPt597(Point(82, 395), 15);
+ connRef597->setSourceEndpoint(srcPt597);
+ ConnEnd dstPt597(Point(57.2456, 447.955), 15);
+ connRef597->setDestEndpoint(dstPt597);
+ connRef597->setRoutingType((ConnType)2);
+
+ ConnRef *connRef598 = new ConnRef(router, 598);
+ ConnEnd srcPt598(Point(72, 309), 15);
+ connRef598->setSourceEndpoint(srcPt598);
+ ConnEnd dstPt598(Point(57.2456, 332.918), 15);
+ connRef598->setDestEndpoint(dstPt598);
+ connRef598->setRoutingType((ConnType)2);
+
+ ConnRef *connRef599 = new ConnRef(router, 599);
+ ConnEnd srcPt599(Point(72, 290), 15);
+ connRef599->setSourceEndpoint(srcPt599);
+ ConnEnd dstPt599(Point(57.2456, 332.918), 15);
+ connRef599->setDestEndpoint(dstPt599);
+ connRef599->setRoutingType((ConnType)2);
+
+ ConnRef *connRef600 = new ConnRef(router, 600);
+ ConnEnd srcPt600(Point(245, 207), 15);
+ connRef600->setSourceEndpoint(srcPt600);
+ ConnEnd dstPt600(Point(197.246, 96.9179), 15);
+ connRef600->setDestEndpoint(dstPt600);
+ connRef600->setRoutingType((ConnType)2);
+
+ ConnRef *connRef601 = new ConnRef(router, 601);
+ ConnEnd srcPt601(Point(245, 227), 15);
+ connRef601->setSourceEndpoint(srcPt601);
+ ConnEnd dstPt601(Point(197.246, 160.918), 15);
+ connRef601->setDestEndpoint(dstPt601);
+ connRef601->setRoutingType((ConnType)2);
+
+ ConnRef *connRef602 = new ConnRef(router, 602);
+ ConnEnd srcPt602(Point(195, 217), 15);
+ connRef602->setSourceEndpoint(srcPt602);
+ ConnEnd dstPt602(Point(197.246, 96.9179), 15);
+ connRef602->setDestEndpoint(dstPt602);
+ connRef602->setRoutingType((ConnType)2);
+
+ ConnRef *connRef603 = new ConnRef(router, 603);
+ ConnEnd srcPt603(Point(195, 237), 15);
+ connRef603->setSourceEndpoint(srcPt603);
+ ConnEnd dstPt603(Point(197.246, 160.918), 15);
+ connRef603->setDestEndpoint(dstPt603);
+ connRef603->setRoutingType((ConnType)2);
+
+ ConnRef *connRef604 = new ConnRef(router, 604);
+ ConnEnd srcPt604(Point(195, 198), 15);
+ connRef604->setSourceEndpoint(srcPt604);
+ ConnEnd dstPt604(Point(197.246, 96.9179), 15);
+ connRef604->setDestEndpoint(dstPt604);
+ connRef604->setRoutingType((ConnType)2);
+
+ ConnRef *connRef605 = new ConnRef(router, 605);
+ ConnEnd srcPt605(Point(195, 218), 15);
+ connRef605->setSourceEndpoint(srcPt605);
+ ConnEnd dstPt605(Point(197.246, 160.918), 15);
+ connRef605->setDestEndpoint(dstPt605);
+ connRef605->setRoutingType((ConnType)2);
+
+ ConnRef *connRef606 = new ConnRef(router, 606);
+ ConnEnd srcPt606(Point(82, 214), 15);
+ connRef606->setSourceEndpoint(srcPt606);
+ ConnEnd dstPt606(Point(57.2456, 160.918), 15);
+ connRef606->setDestEndpoint(dstPt606);
+ connRef606->setRoutingType((ConnType)2);
+
+ ConnRef *connRef607 = new ConnRef(router, 607);
+ ConnEnd srcPt607(Point(82, 195), 15);
+ connRef607->setSourceEndpoint(srcPt607);
+ ConnEnd dstPt607(Point(57.2456, 160.918), 15);
+ connRef607->setDestEndpoint(dstPt607);
+ connRef607->setRoutingType((ConnType)2);
+
+ ConnRef *connRef608 = new ConnRef(router, 608);
+ ConnEnd srcPt608(Point(82, 176), 15);
+ connRef608->setSourceEndpoint(srcPt608);
+ ConnEnd dstPt608(Point(57.2456, 160.918), 15);
+ connRef608->setDestEndpoint(dstPt608);
+ connRef608->setRoutingType((ConnType)2);
+
+ ConnRef *connRef609 = new ConnRef(router, 609);
+ ConnEnd srcPt609(Point(319, 135), 15);
+ connRef609->setSourceEndpoint(srcPt609);
+ ConnEnd dstPt609(Point(319.219, -51.0821), 15);
+ connRef609->setDestEndpoint(dstPt609);
+ connRef609->setRoutingType((ConnType)2);
+
+ ConnRef *connRef610 = new ConnRef(router, 610);
+ ConnEnd srcPt610(Point(220, 135), 15);
+ connRef610->setSourceEndpoint(srcPt610);
+ ConnEnd dstPt610(Point(57.2456, 125.987), 15);
+ connRef610->setDestEndpoint(dstPt610);
+ connRef610->setRoutingType((ConnType)2);
+
+ ConnRef *connRef611 = new ConnRef(router, 611);
+ ConnEnd srcPt611(Point(220, 155), 15);
+ connRef611->setSourceEndpoint(srcPt611);
+ ConnEnd dstPt611(Point(319.219, -7.08205), 15);
+ connRef611->setDestEndpoint(dstPt611);
+ connRef611->setRoutingType((ConnType)2);
+
+ ConnRef *connRef612 = new ConnRef(router, 612);
+ ConnEnd srcPt612(Point(220, 155), 15);
+ connRef612->setSourceEndpoint(srcPt612);
+ ConnEnd dstPt612(Point(197.246, 96.9179), 15);
+ connRef612->setDestEndpoint(dstPt612);
+ connRef612->setRoutingType((ConnType)2);
+
+ ConnRef *connRef613 = new ConnRef(router, 613);
+ ConnEnd srcPt613(Point(220, 135), 15);
+ connRef613->setSourceEndpoint(srcPt613);
+ ConnEnd dstPt613(Point(319.219, -51.0821), 15);
+ connRef613->setDestEndpoint(dstPt613);
+ connRef613->setRoutingType((ConnType)2);
+
+ ConnRef *connRef614 = new ConnRef(router, 614);
+ ConnEnd srcPt614(Point(197.246, 160.918), 15);
+ connRef614->setSourceEndpoint(srcPt614);
+ ConnEnd dstPt614(Point(82, 318), 15);
+ connRef614->setDestEndpoint(dstPt614);
+ connRef614->setRoutingType((ConnType)2);
+
+ ConnRef *connRef615 = new ConnRef(router, 615);
+ ConnEnd srcPt615(Point(197.246, 160.918), 15);
+ connRef615->setSourceEndpoint(srcPt615);
+ ConnEnd dstPt615(Point(213, 328), 15);
+ connRef615->setDestEndpoint(dstPt615);
+ connRef615->setRoutingType((ConnType)2);
+
+ ConnRef *connRef616 = new ConnRef(router, 616);
+ ConnEnd srcPt616(Point(197.246, 160.918), 15);
+ connRef616->setSourceEndpoint(srcPt616);
+ ConnEnd dstPt616(Point(355, 328), 15);
+ connRef616->setDestEndpoint(dstPt616);
+ connRef616->setRoutingType((ConnType)2);
+
+ ConnRef *connRef617 = new ConnRef(router, 617);
+ ConnEnd srcPt617(Point(197.246, 160.918), 15);
+ connRef617->setSourceEndpoint(srcPt617);
+ ConnEnd dstPt617(Point(497, 328), 15);
+ connRef617->setDestEndpoint(dstPt617);
+ connRef617->setRoutingType((ConnType)2);
+
+ ConnRef *connRef618 = new ConnRef(router, 618);
+ ConnEnd srcPt618(Point(197.246, 160.918), 15);
+ connRef618->setSourceEndpoint(srcPt618);
+ ConnEnd dstPt618(Point(639, 328), 15);
+ connRef618->setDestEndpoint(dstPt618);
+ connRef618->setRoutingType((ConnType)2);
+
+ ConnRef *connRef619 = new ConnRef(router, 619);
+ ConnEnd srcPt619(Point(197.246, 160.918), 15);
+ connRef619->setSourceEndpoint(srcPt619);
+ ConnEnd dstPt619(Point(780, 328), 15);
+ connRef619->setDestEndpoint(dstPt619);
+ connRef619->setRoutingType((ConnType)2);
+
+ ConnRef *connRef620 = new ConnRef(router, 620);
+ ConnEnd srcPt620(Point(197.246, 160.918), 15);
+ connRef620->setSourceEndpoint(srcPt620);
+ ConnEnd dstPt620(Point(922, 328), 15);
+ connRef620->setDestEndpoint(dstPt620);
+ connRef620->setRoutingType((ConnType)2);
+
+ ConnRef *connRef621 = new ConnRef(router, 621);
+ ConnEnd srcPt621(Point(1149, 309), 15);
+ connRef621->setSourceEndpoint(srcPt621);
+ ConnEnd dstPt621(Point(197.246, 160.918), 15);
+ connRef621->setDestEndpoint(dstPt621);
+ connRef621->setRoutingType((ConnType)2);
+
+ ConnRef *connRef622 = new ConnRef(router, 622);
+ ConnEnd srcPt622(Point(1199, 300), 15);
+ connRef622->setSourceEndpoint(srcPt622);
+ ConnEnd dstPt622(Point(197.246, 160.918), 15);
+ connRef622->setDestEndpoint(dstPt622);
+ connRef622->setRoutingType((ConnType)2);
+
+ ConnRef *connRef623 = new ConnRef(router, 623);
+ ConnEnd srcPt623(Point(197.246, 160.918), 15);
+ connRef623->setSourceEndpoint(srcPt623);
+ ConnEnd dstPt623(Point(132, 280), 15);
+ connRef623->setDestEndpoint(dstPt623);
+ connRef623->setRoutingType((ConnType)2);
+
+ ConnRef *connRef624 = new ConnRef(router, 624);
+ ConnEnd srcPt624(Point(197.246, 160.918), 15);
+ connRef624->setSourceEndpoint(srcPt624);
+ ConnEnd dstPt624(Point(132, 299), 15);
+ connRef624->setDestEndpoint(dstPt624);
+ connRef624->setRoutingType((ConnType)2);
+
+ ConnRef *connRef625 = new ConnRef(router, 625);
+ ConnEnd srcPt625(Point(57.2456, 160.918), 15);
+ connRef625->setSourceEndpoint(srcPt625);
+ ConnEnd dstPt625(Point(82, 318), 15);
+ connRef625->setDestEndpoint(dstPt625);
+ connRef625->setRoutingType((ConnType)2);
+
+ ConnRef *connRef626 = new ConnRef(router, 626);
+ ConnEnd srcPt626(Point(57.2456, 160.918), 15);
+ connRef626->setSourceEndpoint(srcPt626);
+ ConnEnd dstPt626(Point(132, 280), 15);
+ connRef626->setDestEndpoint(dstPt626);
+ connRef626->setRoutingType((ConnType)2);
+
+ ConnRef *connRef627 = new ConnRef(router, 627);
+ ConnEnd srcPt627(Point(57.2456, 160.918), 15);
+ connRef627->setSourceEndpoint(srcPt627);
+ ConnEnd dstPt627(Point(132, 299), 15);
+ connRef627->setDestEndpoint(dstPt627);
+ connRef627->setRoutingType((ConnType)2);
+
+ ConnRef *connRef628 = new ConnRef(router, 628);
+ ConnEnd srcPt628(Point(72, 423), 15);
+ connRef628->setSourceEndpoint(srcPt628);
+ ConnEnd dstPt628(Point(57.2456, 332.918), 15);
+ connRef628->setDestEndpoint(dstPt628);
+ connRef628->setRoutingType((ConnType)2);
+
+ ConnRef *connRef629 = new ConnRef(router, 629);
+ ConnEnd srcPt629(Point(92, 423), 15);
+ connRef629->setSourceEndpoint(srcPt629);
+ ConnEnd dstPt629(Point(57.2456, 447.955), 15);
+ connRef629->setDestEndpoint(dstPt629);
+ connRef629->setRoutingType((ConnType)2);
+
+ ConnRef *connRef630 = new ConnRef(router, 630);
+ ConnEnd srcPt630(Point(82, 504), 15);
+ connRef630->setSourceEndpoint(srcPt630);
+ ConnEnd dstPt630(Point(57.2456, 447.955), 15);
+ connRef630->setDestEndpoint(dstPt630);
+ connRef630->setRoutingType((ConnType)2);
+
+ ConnRef *connRef631 = new ConnRef(router, 631);
+ ConnEnd srcPt631(Point(132, 595), 15);
+ connRef631->setSourceEndpoint(srcPt631);
+ ConnEnd dstPt631(Point(57.2456, 558.918), 15);
+ connRef631->setDestEndpoint(dstPt631);
+ connRef631->setRoutingType((ConnType)2);
+
+ ConnRef *connRef632 = new ConnRef(router, 632);
+ ConnEnd srcPt632(Point(132, 576), 15);
+ connRef632->setSourceEndpoint(srcPt632);
+ ConnEnd dstPt632(Point(57.2456, 558.918), 15);
+ connRef632->setDestEndpoint(dstPt632);
+ connRef632->setRoutingType((ConnType)2);
+
+ ConnRef *connRef633 = new ConnRef(router, 633);
+ ConnEnd srcPt633(Point(82, 595), 15);
+ connRef633->setSourceEndpoint(srcPt633);
+ ConnEnd dstPt633(Point(57.2456, 558.918), 15);
+ connRef633->setDestEndpoint(dstPt633);
+ connRef633->setRoutingType((ConnType)2);
+
+ ConnRef *connRef634 = new ConnRef(router, 634);
+ ConnEnd srcPt634(Point(57.2456, 676.918), 15);
+ connRef634->setSourceEndpoint(srcPt634);
+ ConnEnd dstPt634(Point(213, 328), 15);
+ connRef634->setDestEndpoint(dstPt634);
+ connRef634->setRoutingType((ConnType)2);
+
+ ConnRef *connRef635 = new ConnRef(router, 635);
+ ConnEnd srcPt635(Point(25.2456, 96.9179), 15);
+ connRef635->setSourceEndpoint(srcPt635);
+ ConnEnd dstPt635(Point(132, 175), 15);
+ connRef635->setDestEndpoint(dstPt635);
+ connRef635->setRoutingType((ConnType)2);
+
+ ConnRef *connRef636 = new ConnRef(router, 636);
+ ConnEnd srcPt636(Point(25.2456, 96.9179), 15);
+ connRef636->setSourceEndpoint(srcPt636);
+ ConnEnd dstPt636(Point(82, 194), 15);
+ connRef636->setDestEndpoint(dstPt636);
+ connRef636->setRoutingType((ConnType)2);
+
+ ConnRef *connRef637 = new ConnRef(router, 637);
+ ConnEnd srcPt637(Point(25.2456, 96.9179), 15);
+ connRef637->setSourceEndpoint(srcPt637);
+ ConnEnd dstPt637(Point(82, 175), 15);
+ connRef637->setDestEndpoint(dstPt637);
+ connRef637->setRoutingType((ConnType)2);
+
+ ConnRef *connRef638 = new ConnRef(router, 638);
+ ConnEnd srcPt638(Point(25.2456, 96.9179), 15);
+ connRef638->setSourceEndpoint(srcPt638);
+ ConnEnd dstPt638(Point(82, 156), 15);
+ connRef638->setDestEndpoint(dstPt638);
+ connRef638->setRoutingType((ConnType)2);
+
+ ConnRef *connRef639 = new ConnRef(router, 639);
+ ConnEnd srcPt639(Point(223, 413), 15);
+ connRef639->setSourceEndpoint(srcPt639);
+ ConnEnd dstPt639(Point(215.246, 332.918), 15);
+ connRef639->setDestEndpoint(dstPt639);
+ connRef639->setRoutingType((ConnType)2);
+
+ ConnRef *connRef640 = new ConnRef(router, 640);
+ ConnEnd srcPt640(Point(223, 504), 15);
+ connRef640->setSourceEndpoint(srcPt640);
+ ConnEnd dstPt640(Point(215.246, 447.955), 15);
+ connRef640->setDestEndpoint(dstPt640);
+ connRef640->setRoutingType((ConnType)2);
+
+ ConnRef *connRef641 = new ConnRef(router, 641);
+ ConnEnd srcPt641(Point(273, 576), 15);
+ connRef641->setSourceEndpoint(srcPt641);
+ ConnEnd dstPt641(Point(215.246, 558.918), 15);
+ connRef641->setDestEndpoint(dstPt641);
+ connRef641->setRoutingType((ConnType)2);
+
+ ConnRef *connRef642 = new ConnRef(router, 642);
+ ConnEnd srcPt642(Point(273, 595), 15);
+ connRef642->setSourceEndpoint(srcPt642);
+ ConnEnd dstPt642(Point(215.246, 558.918), 15);
+ connRef642->setDestEndpoint(dstPt642);
+ connRef642->setRoutingType((ConnType)2);
+
+ ConnRef *connRef643 = new ConnRef(router, 643);
+ ConnEnd srcPt643(Point(223, 595), 15);
+ connRef643->setSourceEndpoint(srcPt643);
+ ConnEnd dstPt643(Point(215.246, 558.918), 15);
+ connRef643->setDestEndpoint(dstPt643);
+ connRef643->setRoutingType((ConnType)2);
+
+ ConnRef *connRef644 = new ConnRef(router, 644);
+ ConnEnd srcPt644(Point(215.246, 676.918), 15);
+ connRef644->setSourceEndpoint(srcPt644);
+ ConnEnd dstPt644(Point(355, 328), 15);
+ connRef644->setDestEndpoint(dstPt644);
+ connRef644->setRoutingType((ConnType)2);
+
+ ConnRef *connRef645 = new ConnRef(router, 645);
+ ConnEnd srcPt645(Point(371.246, 676.918), 15);
+ connRef645->setSourceEndpoint(srcPt645);
+ ConnEnd dstPt645(Point(497, 328), 15);
+ connRef645->setDestEndpoint(dstPt645);
+ connRef645->setRoutingType((ConnType)2);
+
+ ConnRef *connRef646 = new ConnRef(router, 646);
+ ConnEnd srcPt646(Point(415, 576), 15);
+ connRef646->setSourceEndpoint(srcPt646);
+ ConnEnd dstPt646(Point(371.246, 558.918), 15);
+ connRef646->setDestEndpoint(dstPt646);
+ connRef646->setRoutingType((ConnType)2);
+
+ ConnRef *connRef647 = new ConnRef(router, 647);
+ ConnEnd srcPt647(Point(415, 595), 15);
+ connRef647->setSourceEndpoint(srcPt647);
+ ConnEnd dstPt647(Point(371.246, 558.918), 15);
+ connRef647->setDestEndpoint(dstPt647);
+ connRef647->setRoutingType((ConnType)2);
+
+ ConnRef *connRef648 = new ConnRef(router, 648);
+ ConnEnd srcPt648(Point(365, 595), 15);
+ connRef648->setSourceEndpoint(srcPt648);
+ ConnEnd dstPt648(Point(371.246, 558.918), 15);
+ connRef648->setDestEndpoint(dstPt648);
+ connRef648->setRoutingType((ConnType)2);
+
+ ConnRef *connRef649 = new ConnRef(router, 649);
+ ConnEnd srcPt649(Point(365, 504), 15);
+ connRef649->setSourceEndpoint(srcPt649);
+ ConnEnd dstPt649(Point(371.246, 447.955), 15);
+ connRef649->setDestEndpoint(dstPt649);
+ connRef649->setRoutingType((ConnType)2);
+
+ ConnRef *connRef650 = new ConnRef(router, 650);
+ ConnEnd srcPt650(Point(365, 413), 15);
+ connRef650->setSourceEndpoint(srcPt650);
+ ConnEnd dstPt650(Point(371.246, 332.918), 15);
+ connRef650->setDestEndpoint(dstPt650);
+ connRef650->setRoutingType((ConnType)2);
+
+ ConnRef *connRef651 = new ConnRef(router, 651);
+ ConnEnd srcPt651(Point(507, 413), 15);
+ connRef651->setSourceEndpoint(srcPt651);
+ ConnEnd dstPt651(Point(527.246, 332.918), 15);
+ connRef651->setDestEndpoint(dstPt651);
+ connRef651->setRoutingType((ConnType)2);
+
+ ConnRef *connRef652 = new ConnRef(router, 652);
+ ConnEnd srcPt652(Point(507, 504), 15);
+ connRef652->setSourceEndpoint(srcPt652);
+ ConnEnd dstPt652(Point(527.246, 447.955), 15);
+ connRef652->setDestEndpoint(dstPt652);
+ connRef652->setRoutingType((ConnType)2);
+
+ ConnRef *connRef653 = new ConnRef(router, 653);
+ ConnEnd srcPt653(Point(557, 576), 15);
+ connRef653->setSourceEndpoint(srcPt653);
+ ConnEnd dstPt653(Point(527.246, 558.918), 15);
+ connRef653->setDestEndpoint(dstPt653);
+ connRef653->setRoutingType((ConnType)2);
+
+ ConnRef *connRef654 = new ConnRef(router, 654);
+ ConnEnd srcPt654(Point(557, 595), 15);
+ connRef654->setSourceEndpoint(srcPt654);
+ ConnEnd dstPt654(Point(527.246, 558.918), 15);
+ connRef654->setDestEndpoint(dstPt654);
+ connRef654->setRoutingType((ConnType)2);
+
+ ConnRef *connRef655 = new ConnRef(router, 655);
+ ConnEnd srcPt655(Point(507, 595), 15);
+ connRef655->setSourceEndpoint(srcPt655);
+ ConnEnd dstPt655(Point(527.246, 558.918), 15);
+ connRef655->setDestEndpoint(dstPt655);
+ connRef655->setRoutingType((ConnType)2);
+
+ ConnRef *connRef656 = new ConnRef(router, 656);
+ ConnEnd srcPt656(Point(527.246, 676.918), 15);
+ connRef656->setSourceEndpoint(srcPt656);
+ ConnEnd dstPt656(Point(639, 328), 15);
+ connRef656->setDestEndpoint(dstPt656);
+ connRef656->setRoutingType((ConnType)2);
+
+ ConnRef *connRef657 = new ConnRef(router, 657);
+ ConnEnd srcPt657(Point(673.933, 676.918), 15);
+ connRef657->setSourceEndpoint(srcPt657);
+ ConnEnd dstPt657(Point(780, 328), 15);
+ connRef657->setDestEndpoint(dstPt657);
+ connRef657->setRoutingType((ConnType)2);
+
+ ConnRef *connRef658 = new ConnRef(router, 658);
+ ConnEnd srcPt658(Point(699, 576), 15);
+ connRef658->setSourceEndpoint(srcPt658);
+ ConnEnd dstPt658(Point(673.933, 558.918), 15);
+ connRef658->setDestEndpoint(dstPt658);
+ connRef658->setRoutingType((ConnType)2);
+
+ ConnRef *connRef659 = new ConnRef(router, 659);
+ ConnEnd srcPt659(Point(699, 595), 15);
+ connRef659->setSourceEndpoint(srcPt659);
+ ConnEnd dstPt659(Point(673.933, 558.918), 15);
+ connRef659->setDestEndpoint(dstPt659);
+ connRef659->setRoutingType((ConnType)2);
+
+ ConnRef *connRef660 = new ConnRef(router, 660);
+ ConnEnd srcPt660(Point(649, 595), 15);
+ connRef660->setSourceEndpoint(srcPt660);
+ ConnEnd dstPt660(Point(673.933, 558.918), 15);
+ connRef660->setDestEndpoint(dstPt660);
+ connRef660->setRoutingType((ConnType)2);
+
+ ConnRef *connRef661 = new ConnRef(router, 661);
+ ConnEnd srcPt661(Point(649, 504), 15);
+ connRef661->setSourceEndpoint(srcPt661);
+ ConnEnd dstPt661(Point(673.933, 447.955), 15);
+ connRef661->setDestEndpoint(dstPt661);
+ connRef661->setRoutingType((ConnType)2);
+
+ ConnRef *connRef662 = new ConnRef(router, 662);
+ ConnEnd srcPt662(Point(649, 413), 15);
+ connRef662->setSourceEndpoint(srcPt662);
+ ConnEnd dstPt662(Point(673.933, 332.918), 15);
+ connRef662->setDestEndpoint(dstPt662);
+ connRef662->setRoutingType((ConnType)2);
+
+ ConnRef *connRef663 = new ConnRef(router, 663);
+ ConnEnd srcPt663(Point(790, 413), 15);
+ connRef663->setSourceEndpoint(srcPt663);
+ ConnEnd dstPt663(Point(823.246, 332.918), 15);
+ connRef663->setDestEndpoint(dstPt663);
+ connRef663->setRoutingType((ConnType)2);
+
+ ConnRef *connRef664 = new ConnRef(router, 664);
+ ConnEnd srcPt664(Point(790, 504), 15);
+ connRef664->setSourceEndpoint(srcPt664);
+ ConnEnd dstPt664(Point(823.246, 447.955), 15);
+ connRef664->setDestEndpoint(dstPt664);
+ connRef664->setRoutingType((ConnType)2);
+
+ ConnRef *connRef665 = new ConnRef(router, 665);
+ ConnEnd srcPt665(Point(840, 576), 15);
+ connRef665->setSourceEndpoint(srcPt665);
+ ConnEnd dstPt665(Point(823.246, 558.918), 15);
+ connRef665->setDestEndpoint(dstPt665);
+ connRef665->setRoutingType((ConnType)2);
+
+ ConnRef *connRef666 = new ConnRef(router, 666);
+ ConnEnd srcPt666(Point(840, 595), 15);
+ connRef666->setSourceEndpoint(srcPt666);
+ ConnEnd dstPt666(Point(823.246, 558.918), 15);
+ connRef666->setDestEndpoint(dstPt666);
+ connRef666->setRoutingType((ConnType)2);
+
+ ConnRef *connRef667 = new ConnRef(router, 667);
+ ConnEnd srcPt667(Point(790, 595), 15);
+ connRef667->setSourceEndpoint(srcPt667);
+ ConnEnd dstPt667(Point(823.246, 558.918), 15);
+ connRef667->setDestEndpoint(dstPt667);
+ connRef667->setRoutingType((ConnType)2);
+
+ ConnRef *connRef668 = new ConnRef(router, 668);
+ ConnEnd srcPt668(Point(823.246, 676.918), 15);
+ connRef668->setSourceEndpoint(srcPt668);
+ ConnEnd dstPt668(Point(922, 328), 15);
+ connRef668->setDestEndpoint(dstPt668);
+ connRef668->setRoutingType((ConnType)2);
+
+ ConnRef *connRef669 = new ConnRef(router, 669);
+ ConnEnd srcPt669(Point(1149, 309), 15);
+ connRef669->setSourceEndpoint(srcPt669);
+ ConnEnd dstPt669(Point(979.246, 676.918), 15);
+ connRef669->setDestEndpoint(dstPt669);
+ connRef669->setRoutingType((ConnType)2);
+
+ ConnRef *connRef670 = new ConnRef(router, 670);
+ ConnEnd srcPt670(Point(979.246, 676.918), 15);
+ connRef670->setSourceEndpoint(srcPt670);
+ ConnEnd dstPt670(Point(932, 667), 15);
+ connRef670->setDestEndpoint(dstPt670);
+ connRef670->setRoutingType((ConnType)2);
+
+ ConnRef *connRef671 = new ConnRef(router, 671);
+ ConnEnd srcPt671(Point(979.246, 676.918), 15);
+ connRef671->setSourceEndpoint(srcPt671);
+ ConnEnd dstPt671(Point(932, 686), 15);
+ connRef671->setDestEndpoint(dstPt671);
+ connRef671->setRoutingType((ConnType)2);
+
+ ConnRef *connRef672 = new ConnRef(router, 672);
+ ConnEnd srcPt672(Point(1199, 300), 15);
+ connRef672->setSourceEndpoint(srcPt672);
+ ConnEnd dstPt672(Point(979.246, 676.918), 15);
+ connRef672->setDestEndpoint(dstPt672);
+ connRef672->setRoutingType((ConnType)2);
+
+ ConnRef *connRef673 = new ConnRef(router, 673);
+ ConnEnd srcPt673(Point(982, 576), 15);
+ connRef673->setSourceEndpoint(srcPt673);
+ ConnEnd dstPt673(Point(979.246, 558.918), 15);
+ connRef673->setDestEndpoint(dstPt673);
+ connRef673->setRoutingType((ConnType)2);
+
+ ConnRef *connRef674 = new ConnRef(router, 674);
+ ConnEnd srcPt674(Point(982, 595), 15);
+ connRef674->setSourceEndpoint(srcPt674);
+ ConnEnd dstPt674(Point(979.246, 558.918), 15);
+ connRef674->setDestEndpoint(dstPt674);
+ connRef674->setRoutingType((ConnType)2);
+
+ ConnRef *connRef675 = new ConnRef(router, 675);
+ ConnEnd srcPt675(Point(932, 595), 15);
+ connRef675->setSourceEndpoint(srcPt675);
+ ConnEnd dstPt675(Point(979.246, 558.918), 15);
+ connRef675->setDestEndpoint(dstPt675);
+ connRef675->setRoutingType((ConnType)2);
+
+ ConnRef *connRef676 = new ConnRef(router, 676);
+ ConnEnd srcPt676(Point(932, 504), 15);
+ connRef676->setSourceEndpoint(srcPt676);
+ ConnEnd dstPt676(Point(979.246, 447.955), 15);
+ connRef676->setDestEndpoint(dstPt676);
+ connRef676->setRoutingType((ConnType)2);
+
+ ConnRef *connRef677 = new ConnRef(router, 677);
+ ConnEnd srcPt677(Point(932, 413), 15);
+ connRef677->setSourceEndpoint(srcPt677);
+ ConnEnd dstPt677(Point(979.246, 332.918), 15);
+ connRef677->setDestEndpoint(dstPt677);
+ connRef677->setRoutingType((ConnType)2);
+
+ ConnRef *connRef678 = new ConnRef(router, 678);
+ ConnEnd srcPt678(Point(82, 338), 15);
+ connRef678->setSourceEndpoint(srcPt678);
+ ConnEnd dstPt678(Point(57.2456, 332.918), 15);
+ connRef678->setDestEndpoint(dstPt678);
+ connRef678->setRoutingType((ConnType)2);
+
+ ConnRef *connRef679 = new ConnRef(router, 679);
+ ConnEnd srcPt679(Point(233, 328), 15);
+ connRef679->setSourceEndpoint(srcPt679);
+ ConnEnd dstPt679(Point(215.246, 332.918), 15);
+ connRef679->setDestEndpoint(dstPt679);
+ connRef679->setRoutingType((ConnType)2);
+
+ ConnRef *connRef680 = new ConnRef(router, 680);
+ ConnEnd srcPt680(Point(375, 328), 15);
+ connRef680->setSourceEndpoint(srcPt680);
+ ConnEnd dstPt680(Point(371.246, 332.918), 15);
+ connRef680->setDestEndpoint(dstPt680);
+ connRef680->setRoutingType((ConnType)2);
+
+ ConnRef *connRef681 = new ConnRef(router, 681);
+ ConnEnd srcPt681(Point(517, 328), 15);
+ connRef681->setSourceEndpoint(srcPt681);
+ ConnEnd dstPt681(Point(527.246, 332.918), 15);
+ connRef681->setDestEndpoint(dstPt681);
+ connRef681->setRoutingType((ConnType)2);
+
+ ConnRef *connRef682 = new ConnRef(router, 682);
+ ConnEnd srcPt682(Point(659, 328), 15);
+ connRef682->setSourceEndpoint(srcPt682);
+ ConnEnd dstPt682(Point(673.933, 332.918), 15);
+ connRef682->setDestEndpoint(dstPt682);
+ connRef682->setRoutingType((ConnType)2);
+
+ ConnRef *connRef683 = new ConnRef(router, 683);
+ ConnEnd srcPt683(Point(800, 328), 15);
+ connRef683->setSourceEndpoint(srcPt683);
+ ConnEnd dstPt683(Point(823.246, 332.918), 15);
+ connRef683->setDestEndpoint(dstPt683);
+ connRef683->setRoutingType((ConnType)2);
+
+ ConnRef *connRef684 = new ConnRef(router, 684);
+ ConnEnd srcPt684(Point(942, 328), 15);
+ connRef684->setSourceEndpoint(srcPt684);
+ ConnEnd dstPt684(Point(979.246, 332.918), 15);
+ connRef684->setDestEndpoint(dstPt684);
+ connRef684->setRoutingType((ConnType)2);
+
+ ConnRef *connRef685 = new ConnRef(router, 685);
+ ConnEnd srcPt685(Point(223, 433), 15);
+ connRef685->setSourceEndpoint(srcPt685);
+ ConnEnd dstPt685(Point(215.246, 447.955), 15);
+ connRef685->setDestEndpoint(dstPt685);
+ connRef685->setRoutingType((ConnType)2);
+
+ ConnRef *connRef686 = new ConnRef(router, 686);
+ ConnEnd srcPt686(Point(365, 433), 15);
+ connRef686->setSourceEndpoint(srcPt686);
+ ConnEnd dstPt686(Point(371.246, 447.955), 15);
+ connRef686->setDestEndpoint(dstPt686);
+ connRef686->setRoutingType((ConnType)2);
+
+ ConnRef *connRef687 = new ConnRef(router, 687);
+ ConnEnd srcPt687(Point(507, 433), 15);
+ connRef687->setSourceEndpoint(srcPt687);
+ ConnEnd dstPt687(Point(527.246, 447.955), 15);
+ connRef687->setDestEndpoint(dstPt687);
+ connRef687->setRoutingType((ConnType)2);
+
+ ConnRef *connRef688 = new ConnRef(router, 688);
+ ConnEnd srcPt688(Point(790, 433), 15);
+ connRef688->setSourceEndpoint(srcPt688);
+ ConnEnd dstPt688(Point(823.246, 447.955), 15);
+ connRef688->setDestEndpoint(dstPt688);
+ connRef688->setRoutingType((ConnType)2);
+
+ ConnRef *connRef689 = new ConnRef(router, 689);
+ ConnEnd srcPt689(Point(932, 433), 15);
+ connRef689->setSourceEndpoint(srcPt689);
+ ConnEnd dstPt689(Point(979.246, 447.955), 15);
+ connRef689->setDestEndpoint(dstPt689);
+ connRef689->setRoutingType((ConnType)2);
+
+ ConnRef *connRef690 = new ConnRef(router, 690);
+ ConnEnd srcPt690(Point(649, 433), 15);
+ connRef690->setSourceEndpoint(srcPt690);
+ ConnEnd dstPt690(Point(673.933, 447.955), 15);
+ connRef690->setDestEndpoint(dstPt690);
+ connRef690->setRoutingType((ConnType)2);
+
+ ConnRef *connRef691 = new ConnRef(router, 691);
+ ConnEnd srcPt691(Point(82, 524), 15);
+ connRef691->setSourceEndpoint(srcPt691);
+ ConnEnd dstPt691(Point(57.2456, 558.918), 15);
+ connRef691->setDestEndpoint(dstPt691);
+ connRef691->setRoutingType((ConnType)2);
+
+ ConnRef *connRef692 = new ConnRef(router, 692);
+ ConnEnd srcPt692(Point(223, 524), 15);
+ connRef692->setSourceEndpoint(srcPt692);
+ ConnEnd dstPt692(Point(215.246, 558.918), 15);
+ connRef692->setDestEndpoint(dstPt692);
+ connRef692->setRoutingType((ConnType)2);
+
+ ConnRef *connRef693 = new ConnRef(router, 693);
+ ConnEnd srcPt693(Point(365, 524), 15);
+ connRef693->setSourceEndpoint(srcPt693);
+ ConnEnd dstPt693(Point(371.246, 558.918), 15);
+ connRef693->setDestEndpoint(dstPt693);
+ connRef693->setRoutingType((ConnType)2);
+
+ ConnRef *connRef694 = new ConnRef(router, 694);
+ ConnEnd srcPt694(Point(507, 524), 15);
+ connRef694->setSourceEndpoint(srcPt694);
+ ConnEnd dstPt694(Point(527.246, 558.918), 15);
+ connRef694->setDestEndpoint(dstPt694);
+ connRef694->setRoutingType((ConnType)2);
+
+ ConnRef *connRef695 = new ConnRef(router, 695);
+ ConnEnd srcPt695(Point(649, 524), 15);
+ connRef695->setSourceEndpoint(srcPt695);
+ ConnEnd dstPt695(Point(673.933, 558.918), 15);
+ connRef695->setDestEndpoint(dstPt695);
+ connRef695->setRoutingType((ConnType)2);
+
+ ConnRef *connRef696 = new ConnRef(router, 696);
+ ConnEnd srcPt696(Point(790, 524), 15);
+ connRef696->setSourceEndpoint(srcPt696);
+ ConnEnd dstPt696(Point(823.246, 558.918), 15);
+ connRef696->setDestEndpoint(dstPt696);
+ connRef696->setRoutingType((ConnType)2);
+
+ ConnRef *connRef697 = new ConnRef(router, 697);
+ ConnEnd srcPt697(Point(932, 524), 15);
+ connRef697->setSourceEndpoint(srcPt697);
+ ConnEnd dstPt697(Point(979.246, 558.918), 15);
+ connRef697->setDestEndpoint(dstPt697);
+ connRef697->setRoutingType((ConnType)2);
+
+ ConnRef *connRef698 = new ConnRef(router, 698);
+ ConnEnd srcPt698(Point(82, 615), 15);
+ connRef698->setSourceEndpoint(srcPt698);
+ ConnEnd dstPt698(Point(57.2456, 676.918), 15);
+ connRef698->setDestEndpoint(dstPt698);
+ connRef698->setRoutingType((ConnType)2);
+
+ ConnRef *connRef699 = new ConnRef(router, 699);
+ ConnEnd srcPt699(Point(223, 615), 15);
+ connRef699->setSourceEndpoint(srcPt699);
+ ConnEnd dstPt699(Point(215.246, 676.918), 15);
+ connRef699->setDestEndpoint(dstPt699);
+ connRef699->setRoutingType((ConnType)2);
+
+ ConnRef *connRef700 = new ConnRef(router, 700);
+ ConnEnd srcPt700(Point(365, 615), 15);
+ connRef700->setSourceEndpoint(srcPt700);
+ ConnEnd dstPt700(Point(371.246, 676.918), 15);
+ connRef700->setDestEndpoint(dstPt700);
+ connRef700->setRoutingType((ConnType)2);
+
+ ConnRef *connRef701 = new ConnRef(router, 701);
+ ConnEnd srcPt701(Point(507, 615), 15);
+ connRef701->setSourceEndpoint(srcPt701);
+ ConnEnd dstPt701(Point(527.246, 676.918), 15);
+ connRef701->setDestEndpoint(dstPt701);
+ connRef701->setRoutingType((ConnType)2);
+
+ ConnRef *connRef702 = new ConnRef(router, 702);
+ ConnEnd srcPt702(Point(649, 615), 15);
+ connRef702->setSourceEndpoint(srcPt702);
+ ConnEnd dstPt702(Point(673.933, 676.918), 15);
+ connRef702->setDestEndpoint(dstPt702);
+ connRef702->setRoutingType((ConnType)2);
+
+ ConnRef *connRef703 = new ConnRef(router, 703);
+ ConnEnd srcPt703(Point(790, 615), 15);
+ connRef703->setSourceEndpoint(srcPt703);
+ ConnEnd dstPt703(Point(823.246, 676.918), 15);
+ connRef703->setDestEndpoint(dstPt703);
+ connRef703->setRoutingType((ConnType)2);
+
+ ConnRef *connRef704 = new ConnRef(router, 704);
+ ConnEnd srcPt704(Point(932, 615), 15);
+ connRef704->setSourceEndpoint(srcPt704);
+ ConnEnd dstPt704(Point(979.246, 676.918), 15);
+ connRef704->setDestEndpoint(dstPt704);
+ connRef704->setRoutingType((ConnType)2);
+
+ ConnRef *connRef705 = new ConnRef(router, 705);
+ ConnEnd srcPt705(Point(1169, 309), 15);
+ connRef705->setSourceEndpoint(srcPt705);
+ ConnEnd dstPt705(Point(1203.25, 332.918), 15);
+ connRef705->setDestEndpoint(dstPt705);
+ connRef705->setRoutingType((ConnType)2);
+
+ ConnRef *connRef706 = new ConnRef(router, 706);
+ ConnEnd srcPt706(Point(1159, 414), 15);
+ connRef706->setSourceEndpoint(srcPt706);
+ ConnEnd dstPt706(Point(1203.25, 447.955), 15);
+ connRef706->setDestEndpoint(dstPt706);
+ connRef706->setRoutingType((ConnType)2);
+
+ ConnRef *connRef707 = new ConnRef(router, 707);
+ ConnEnd srcPt707(Point(1159, 505), 15);
+ connRef707->setSourceEndpoint(srcPt707);
+ ConnEnd dstPt707(Point(1203.25, 558.918), 15);
+ connRef707->setDestEndpoint(dstPt707);
+ connRef707->setRoutingType((ConnType)2);
+
+ ConnRef *connRef708 = new ConnRef(router, 708);
+ ConnEnd srcPt708(Point(1159, 595), 15);
+ connRef708->setSourceEndpoint(srcPt708);
+ ConnEnd dstPt708(Point(1203.25, 676.918), 15);
+ connRef708->setDestEndpoint(dstPt708);
+ connRef708->setRoutingType((ConnType)2);
+
+ ConnRef *connRef709 = new ConnRef(router, 709);
+ ConnEnd srcPt709(Point(932, 687), 15);
+ connRef709->setSourceEndpoint(srcPt709);
+ ConnEnd dstPt709(Point(979.246, 750.918), 15);
+ connRef709->setDestEndpoint(dstPt709);
+ connRef709->setRoutingType((ConnType)2);
+
+ ConnRef *connRef710 = new ConnRef(router, 710);
+ ConnEnd srcPt710(Point(932, 706), 15);
+ connRef710->setSourceEndpoint(srcPt710);
+ ConnEnd dstPt710(Point(979.246, 750.918), 15);
+ connRef710->setDestEndpoint(dstPt710);
+ connRef710->setRoutingType((ConnType)2);
+
+ ConnRef *connRef711 = new ConnRef(router, 711);
+ ConnEnd srcPt711(Point(1159, 687), 15);
+ connRef711->setSourceEndpoint(srcPt711);
+ ConnEnd dstPt711(Point(1203.25, 750.918), 15);
+ connRef711->setDestEndpoint(dstPt711);
+ connRef711->setRoutingType((ConnType)2);
+
+ ConnRef *connRef712 = new ConnRef(router, 712);
+ ConnEnd srcPt712(Point(1219, 300), 15);
+ connRef712->setSourceEndpoint(srcPt712);
+ ConnEnd dstPt712(Point(1203.25, 332.918), 15);
+ connRef712->setDestEndpoint(dstPt712);
+ connRef712->setRoutingType((ConnType)2);
+
+ ConnRef *connRef713 = new ConnRef(router, 713);
+ ConnEnd srcPt713(Point(1209, 605), 15);
+ connRef713->setSourceEndpoint(srcPt713);
+ ConnEnd dstPt713(Point(1203.25, 676.918), 15);
+ connRef713->setDestEndpoint(dstPt713);
+ connRef713->setRoutingType((ConnType)2);
+
+ ConnRef *connRef714 = new ConnRef(router, 714);
+ ConnEnd srcPt714(Point(132, 300), 15);
+ connRef714->setSourceEndpoint(srcPt714);
+ ConnEnd dstPt714(Point(57.2456, 332.918), 15);
+ connRef714->setDestEndpoint(dstPt714);
+ connRef714->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/reallyslowrouting");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/removeJunctions01.cpp b/src/3rdparty/adaptagrams/libavoid/tests/removeJunctions01.cpp
new file mode 100644
index 0000000..3dc09c0
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/removeJunctions01.cpp
@@ -0,0 +1,103 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingParameter((RoutingParameter)0, 2);
+ router->setRoutingParameter((RoutingParameter)1, 0);
+ router->setRoutingParameter((RoutingParameter)2, 0);
+ router->setRoutingParameter((RoutingParameter)3, 4000);
+ router->setRoutingParameter((RoutingParameter)4, 9000);
+ router->setRoutingParameter((RoutingParameter)5, 0);
+ router->setRoutingParameter((RoutingParameter)6, 0);
+ router->setRoutingParameter((RoutingParameter)7, 16);
+ router->setRoutingParameter((RoutingParameter)8, 0);
+ router->setRoutingOption((RoutingOption)0, false);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, false);
+ router->setRoutingOption((RoutingOption)3, false);
+ router->setRoutingOption((RoutingOption)4, true);
+ router->setRoutingOption((RoutingOption)5, false);
+ router->setRoutingOption((RoutingOption)6, true);
+ Polygon polygon;
+ ConnEnd srcPt;
+ ConnEnd dstPt;
+ ConnEnd heConnPt;
+ PolyLine newRoute;
+ ShapeConnectionPin *connPin = nullptr;
+
+ // shapeRef1
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(450, 330);
+ polygon.ps[1] = Point(490, 330);
+ polygon.ps[2] = Point(490, 450);
+ polygon.ps[3] = Point(450, 450);
+ ShapeRef *shapeRef1 = new ShapeRef(router, polygon, 1);
+ connPin = new ShapeConnectionPin(shapeRef1, 1, 0, 0.333333, true, 10, (ConnDirFlags) 0);
+ connPin->setExclusive(false);
+ connPin = new ShapeConnectionPin(shapeRef1, 2, 0, 0.666667, true, 10, (ConnDirFlags) 0);
+ connPin->setExclusive(false);
+ connPin = new ShapeConnectionPin(shapeRef1, 3, 1, 0.5, true, 10, (ConnDirFlags) 0);
+ connPin->setExclusive(false);
+ connPin = new ShapeConnectionPin(shapeRef1, 4, 0.5, 0, true, 10, (ConnDirFlags) 0);
+ connPin->setExclusive(false);
+
+ // shapeRef8
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(502, 237.5);
+ polygon.ps[1] = Point(502, 262.5);
+ polygon.ps[2] = Point(438, 262.5);
+ polygon.ps[3] = Point(438, 237.5);
+ ShapeRef *shapeRef8 = new ShapeRef(router, polygon, 8);
+ connPin = new ShapeConnectionPin(shapeRef8, 1, 0, 0.5, true, 1, (ConnDirFlags) 0);
+ connPin = new ShapeConnectionPin(shapeRef8, 2, 1, 0.5, true, 1, (ConnDirFlags) 0);
+ connPin = new ShapeConnectionPin(shapeRef8, 3, 0.5, 1, true, 1, (ConnDirFlags) 0);
+ connPin = new ShapeConnectionPin(shapeRef8, 4, 0.5, 0, true, 1, (ConnDirFlags) 0);
+
+ JunctionRef *junctionRef6 = new JunctionRef(router, Point(470, 300), 6);
+ /*
+ // This may be useful if junction pins are modified.
+ connPin = new ShapeConnectionPin(junctionRef6, 2147483646, (ConnDirFlags) 15);
+ */
+
+ // connRef9
+ ConnRef *connRef9 = new ConnRef(router, 9);
+ srcPt = ConnEnd(junctionRef6);
+ connRef9->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef8, 3);
+ connRef9->setDestEndpoint(dstPt);
+ connRef9->setRoutingType((ConnType)2);
+
+#if 1
+ // connRef10 - WITH BUG
+ ConnRef *connRef10 = new ConnRef(router, 10);
+ srcPt = ConnEnd(junctionRef6);
+ connRef10->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(shapeRef1, 4);
+ connRef10->setDestEndpoint(dstPt);
+ connRef10->setRoutingType((ConnType)2);
+#else
+ // connRef10 - WITHOUT BUG
+ ConnRef *connRef10 = new ConnRef(router, 10);
+ srcPt = ConnEnd(shapeRef1, 4);
+ connRef10->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(junctionRef6);
+ connRef10->setDestEndpoint(dstPt);
+ connRef10->setRoutingType((ConnType)2);
+#endif
+
+ // router->deleteConnector(connRef5);
+ router->processTransaction();
+
+ ConnRef *mergedConn = junctionRef6->removeJunctionAndMergeConnectors();
+ router->processTransaction();
+ router->outputDiagram("output/removeJunctions01");
+
+ std::pair<ConnEnd, ConnEnd> ends = mergedConn->endpointConnEnds();
+
+ // Expected result: output images should be virtually identical.
+ // Result: An endpoint seems to be disconnected from shapeRef8.
+ bool isConnected = (ends.first.shape() == shapeRef8) || (ends.second.shape() == shapeRef8);
+
+ delete router;
+ return isConnected ? 0 : 1;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/restrictedNudging.cpp b/src/3rdparty/adaptagrams/libavoid/tests/restrictedNudging.cpp
new file mode 100644
index 0000000..77f8960
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/restrictedNudging.cpp
@@ -0,0 +1,68 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 200);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 110);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+ Polygon poly282634758(4);
+ poly282634758.ps[0] = Point(51360, 50215);
+ poly282634758.ps[1] = Point(51360, 50460);
+ poly282634758.ps[2] = Point(51075, 50460);
+ poly282634758.ps[3] = Point(51075, 50215);
+ new ShapeRef(router, poly282634758, 282634758);
+
+ Polygon poly69386928(4);
+ poly69386928.ps[0] = Point(51050, 50415);
+ poly69386928.ps[1] = Point(51050, 50735);
+ poly69386928.ps[2] = Point(50690, 50735);
+ poly69386928.ps[3] = Point(50690, 50415);
+ new ShapeRef(router, poly69386928, 69386928);
+
+ Polygon poly11958280(4);
+ poly11958280.ps[0] = Point(50460, 50490);
+ poly11958280.ps[1] = Point(50460, 50660);
+ poly11958280.ps[2] = Point(50290, 50660);
+ poly11958280.ps[3] = Point(50290, 50490);
+ new ShapeRef(router, poly11958280, 11958280);
+
+ Polygon poly50591298(4);
+ poly50591298.ps[0] = Point(51260, 50015);
+ poly50591298.ps[1] = Point(51260, 50185);
+ poly50591298.ps[2] = Point(51075, 50185);
+ poly50591298.ps[3] = Point(51075, 50015);
+ new ShapeRef(router, poly50591298, 50591298);
+
+ ConnRef *connRef355676284 = new ConnRef(router, 355676284);
+ ConnEnd srcPt355676284(Point(51040, 50575), 8);
+ connRef355676284->setSourceEndpoint(srcPt355676284);
+ ConnEnd dstPt355676284(Point(51085, 50300), 4);
+ connRef355676284->setDestEndpoint(dstPt355676284);
+ connRef355676284->setRoutingType((ConnType)2);
+
+ ConnRef *connRef33653259 = new ConnRef(router, 33653259);
+ ConnEnd srcPt33653259(Point(51040, 50650), 8);
+ connRef33653259->setSourceEndpoint(srcPt33653259);
+ ConnEnd dstPt33653259(Point(51085, 50375), 4);
+ connRef33653259->setDestEndpoint(dstPt33653259);
+ connRef33653259->setRoutingType((ConnType)2);
+
+ ConnRef *connRef421608980 = new ConnRef(router, 421608980);
+ ConnEnd srcPt421608980(Point(51040, 50500), 8);
+ connRef421608980->setSourceEndpoint(srcPt421608980);
+ ConnEnd dstPt421608980(Point(51085, 50100), 4);
+ connRef421608980->setDestEndpoint(dstPt421608980);
+ connRef421608980->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/restrictedNudging");
+
+ bool overlap = router->existsOrthogonalTouchingPaths();
+ delete router;
+ return (overlap) ? 1 : 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/slowrouting.cpp b/src/3rdparty/adaptagrams/libavoid/tests/slowrouting.cpp
new file mode 100644
index 0000000..5a9bf83
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/slowrouting.cpp
@@ -0,0 +1,1459 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 0);
+ router->setRoutingPenalty((PenaltyType)4, 110);
+ router->setRoutingPenalty((PenaltyType)5, 100);
+ router->setRoutingOption((RoutingOption)0, false);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+JunctionRef *junctionRef1634752 = new JunctionRef(router, Point(24800, 27000), 1634752);
+
+ Polygon poly2807970(4);
+ poly2807970.ps[0] = Point(26175, 26940);
+ poly2807970.ps[1] = Point(26175, 28610);
+ poly2807970.ps[2] = Point(25825, 28610);
+ poly2807970.ps[3] = Point(25825, 26940);
+ new ShapeRef(router, poly2807970, 2807970);
+
+JunctionRef *junctionRef5416208 = new JunctionRef(router, Point(24300, 28050), 5416208);
+
+ Polygon poly8864520(4);
+ poly8864520.ps[0] = Point(24900, 28815);
+ poly8864520.ps[1] = Point(24900, 29135);
+ poly8864520.ps[2] = Point(24550, 29135);
+ poly8864520.ps[3] = Point(24550, 28815);
+ new ShapeRef(router, poly8864520, 8864520);
+
+JunctionRef *junctionRef9420650 = new JunctionRef(router, Point(26675, 28125), 9420650);
+
+ Polygon poly11441468(4);
+ poly11441468.ps[0] = Point(27754, 28275);
+ poly11441468.ps[1] = Point(27754, 28360);
+ poly11441468.ps[2] = Point(27696, 28360);
+ poly11441468.ps[3] = Point(27696, 28275);
+ new ShapeRef(router, poly11441468, 11441468);
+
+JunctionRef *junctionRef12650756 = new JunctionRef(router, Point(24250, 26575), 12650756);
+
+ Polygon poly13550052(4);
+ poly13550052.ps[0] = Point(24304, 29500);
+ poly13550052.ps[1] = Point(24304, 29585);
+ poly13550052.ps[2] = Point(24246, 29585);
+ poly13550052.ps[3] = Point(24246, 29500);
+ new ShapeRef(router, poly13550052, 13550052);
+
+JunctionRef *junctionRef16613420 = new JunctionRef(router, Point(27625, 28750), 16613420);
+
+ Polygon poly16932600(4);
+ poly16932600.ps[0] = Point(27425, 26715);
+ poly16932600.ps[1] = Point(27425, 27035);
+ poly16932600.ps[2] = Point(27075, 27035);
+ poly16932600.ps[3] = Point(27075, 26715);
+ new ShapeRef(router, poly16932600, 16932600);
+
+ Polygon poly17785779(4);
+ poly17785779.ps[0] = Point(25129, 27950);
+ poly17785779.ps[1] = Point(25129, 28035);
+ poly17785779.ps[2] = Point(25071, 28035);
+ poly17785779.ps[3] = Point(25071, 27950);
+ new ShapeRef(router, poly17785779, 17785779);
+
+JunctionRef *junctionRef23132835 = new JunctionRef(router, Point(24450, 26900), 23132835);
+
+JunctionRef *junctionRef26572870 = new JunctionRef(router, Point(23158, 26550), 26572870);
+
+ Polygon poly27045198(4);
+ poly27045198.ps[0] = Point(24279, 27925);
+ poly27045198.ps[1] = Point(24279, 28010);
+ poly27045198.ps[2] = Point(24221, 28010);
+ poly27045198.ps[3] = Point(24221, 27925);
+ new ShapeRef(router, poly27045198, 27045198);
+
+ Polygon poly28607408(4);
+ poly28607408.ps[0] = Point(27500, 28190);
+ poly28607408.ps[1] = Point(27500, 28510);
+ poly28607408.ps[2] = Point(27150, 28510);
+ poly28607408.ps[3] = Point(27150, 28190);
+ new ShapeRef(router, poly28607408, 28607408);
+
+ Polygon poly28892384(4);
+ poly28892384.ps[0] = Point(24950, 29440);
+ poly28892384.ps[1] = Point(24950, 29760);
+ poly28892384.ps[2] = Point(24600, 29760);
+ poly28892384.ps[3] = Point(24600, 29440);
+ new ShapeRef(router, poly28892384, 28892384);
+
+JunctionRef *junctionRef34620300 = new JunctionRef(router, Point(24400, 26200), 34620300);
+
+JunctionRef *junctionRef36814260 = new JunctionRef(router, Point(24994, 28975), 36814260);
+
+JunctionRef *junctionRef39695669 = new JunctionRef(router, Point(24000, 29000), 39695669);
+
+ Polygon poly39757638(4);
+ poly39757638.ps[0] = Point(26135, 26516);
+ poly39757638.ps[1] = Point(26135, 26584);
+ poly39757638.ps[2] = Point(26015, 26584);
+ poly39757638.ps[3] = Point(26015, 26516);
+ new ShapeRef(router, poly39757638, 39757638);
+
+JunctionRef *junctionRef41941580 = new JunctionRef(router, Point(23275, 26700), 41941580);
+
+ Polygon poly44086980(4);
+ poly44086980.ps[0] = Point(23950, 27840);
+ poly44086980.ps[1] = Point(23950, 28160);
+ poly44086980.ps[2] = Point(23600, 28160);
+ poly44086980.ps[3] = Point(23600, 27840);
+ new ShapeRef(router, poly44086980, 44086980);
+
+ Polygon poly45299820(4);
+ poly45299820.ps[0] = Point(25054, 26225);
+ poly45299820.ps[1] = Point(25054, 26310);
+ poly45299820.ps[2] = Point(24996, 26310);
+ poly45299820.ps[3] = Point(24996, 26225);
+ new ShapeRef(router, poly45299820, 45299820);
+
+ Polygon poly45389694(4);
+ poly45389694.ps[0] = Point(24825, 27265);
+ poly45389694.ps[1] = Point(24825, 27585);
+ poly45389694.ps[2] = Point(24475, 27585);
+ poly45389694.ps[3] = Point(24475, 27265);
+ new ShapeRef(router, poly45389694, 45389694);
+
+ Polygon poly53329545(4);
+ poly53329545.ps[0] = Point(22900, 29265);
+ poly53329545.ps[1] = Point(22900, 29385);
+ poly53329545.ps[2] = Point(22750, 29385);
+ poly53329545.ps[3] = Point(22750, 29265);
+ new ShapeRef(router, poly53329545, 53329545);
+
+JunctionRef *junctionRef58465624 = new JunctionRef(router, Point(23200, 28550), 58465624);
+
+ Polygon poly59167974(4);
+ poly59167974.ps[0] = Point(23925, 26465);
+ poly59167974.ps[1] = Point(23925, 26785);
+ poly59167974.ps[2] = Point(23575, 26785);
+ poly59167974.ps[3] = Point(23575, 26465);
+ new ShapeRef(router, poly59167974, 59167974);
+
+ Polygon poly66193481(4);
+ poly66193481.ps[0] = Point(27779, 29625);
+ poly66193481.ps[1] = Point(27779, 29710);
+ poly66193481.ps[2] = Point(27721, 29710);
+ poly66193481.ps[3] = Point(27721, 29625);
+ new ShapeRef(router, poly66193481, 66193481);
+
+ Polygon poly70299198(4);
+ poly70299198.ps[0] = Point(27754, 29100);
+ poly70299198.ps[1] = Point(27754, 29185);
+ poly70299198.ps[2] = Point(27696, 29185);
+ poly70299198.ps[3] = Point(27696, 29100);
+ new ShapeRef(router, poly70299198, 70299198);
+
+ Polygon poly71509898(4);
+ poly71509898.ps[0] = Point(27754, 28675);
+ poly71509898.ps[1] = Point(27754, 28760);
+ poly71509898.ps[2] = Point(27696, 28760);
+ poly71509898.ps[3] = Point(27696, 28675);
+ new ShapeRef(router, poly71509898, 71509898);
+
+ Polygon poly92664994(4);
+ poly92664994.ps[0] = Point(27754, 27175);
+ poly92664994.ps[1] = Point(27754, 27260);
+ poly92664994.ps[2] = Point(27696, 27260);
+ poly92664994.ps[3] = Point(27696, 27175);
+ new ShapeRef(router, poly92664994, 92664994);
+
+ Polygon poly106612990(4);
+ poly106612990.ps[0] = Point(23950, 27265);
+ poly106612990.ps[1] = Point(23950, 27585);
+ poly106612990.ps[2] = Point(23600, 27585);
+ poly106612990.ps[3] = Point(23600, 27265);
+ new ShapeRef(router, poly106612990, 106612990);
+
+ Polygon poly115549720(4);
+ poly115549720.ps[0] = Point(24050, 29415);
+ poly115549720.ps[1] = Point(24050, 29735);
+ poly115549720.ps[2] = Point(23700, 29735);
+ poly115549720.ps[3] = Point(23700, 29415);
+ new ShapeRef(router, poly115549720, 115549720);
+
+JunctionRef *junctionRef117582414 = new JunctionRef(router, Point(24225, 26700), 117582414);
+
+ Polygon poly129015449(4);
+ poly129015449.ps[0] = Point(24254, 28425);
+ poly129015449.ps[1] = Point(24254, 28510);
+ poly129015449.ps[2] = Point(24196, 28510);
+ poly129015449.ps[3] = Point(24196, 28425);
+ new ShapeRef(router, poly129015449, 129015449);
+
+JunctionRef *junctionRef131744632 = new JunctionRef(router, Point(24870, 26650), 131744632);
+
+ Polygon poly132843360(4);
+ poly132843360.ps[0] = Point(27425, 27090);
+ poly132843360.ps[1] = Point(27425, 27410);
+ poly132843360.ps[2] = Point(27075, 27410);
+ poly132843360.ps[3] = Point(27075, 27090);
+ new ShapeRef(router, poly132843360, 132843360);
+
+JunctionRef *junctionRef137263932 = new JunctionRef(router, Point(24250, 27125), 137263932);
+
+JunctionRef *junctionRef137883060 = new JunctionRef(router, Point(25000, 28650), 137883060);
+
+JunctionRef *junctionRef144791664 = new JunctionRef(router, Point(24300, 29050), 144791664);
+
+JunctionRef *junctionRef147481188 = new JunctionRef(router, Point(23208, 28075), 147481188);
+
+ Polygon poly156912624(4);
+ poly156912624.ps[0] = Point(24279, 28925);
+ poly156912624.ps[1] = Point(24279, 29010);
+ poly156912624.ps[2] = Point(24221, 29010);
+ poly156912624.ps[3] = Point(24221, 28925);
+ new ShapeRef(router, poly156912624, 156912624);
+
+ Polygon poly163577296(4);
+ poly163577296.ps[0] = Point(23950, 26115);
+ poly163577296.ps[1] = Point(23950, 26435);
+ poly163577296.ps[2] = Point(23600, 26435);
+ poly163577296.ps[3] = Point(23600, 26115);
+ new ShapeRef(router, poly163577296, 163577296);
+
+ Polygon poly165702672(4);
+ poly165702672.ps[0] = Point(25179, 29500);
+ poly165702672.ps[1] = Point(25179, 29585);
+ poly165702672.ps[2] = Point(25121, 29585);
+ poly165702672.ps[3] = Point(25121, 29500);
+ new ShapeRef(router, poly165702672, 165702672);
+
+ Polygon poly165841098(4);
+ poly165841098.ps[0] = Point(25029, 26575);
+ poly165841098.ps[1] = Point(25029, 26660);
+ poly165841098.ps[2] = Point(24971, 26660);
+ poly165841098.ps[3] = Point(24971, 26575);
+ new ShapeRef(router, poly165841098, 165841098);
+
+ Polygon poly170549060(4);
+ poly170549060.ps[0] = Point(23975, 28340);
+ poly170549060.ps[1] = Point(23975, 28660);
+ poly170549060.ps[2] = Point(23625, 28660);
+ poly170549060.ps[3] = Point(23625, 28340);
+ new ShapeRef(router, poly170549060, 170549060);
+
+ Polygon poly188773123(4);
+ poly188773123.ps[0] = Point(25029, 26975);
+ poly188773123.ps[1] = Point(25029, 27060);
+ poly188773123.ps[2] = Point(24971, 27060);
+ poly188773123.ps[3] = Point(24971, 26975);
+ new ShapeRef(router, poly188773123, 188773123);
+
+ Polygon poly190710960(4);
+ poly190710960.ps[0] = Point(27550, 29540);
+ poly190710960.ps[1] = Point(27550, 29860);
+ poly190710960.ps[2] = Point(27200, 29860);
+ poly190710960.ps[3] = Point(27200, 29540);
+ new ShapeRef(router, poly190710960, 190710960);
+
+JunctionRef *junctionRef195377532 = new JunctionRef(router, Point(27425, 27650), 195377532);
+
+JunctionRef *junctionRef200348672 = new JunctionRef(router, Point(27564, 28000), 200348672);
+
+ Polygon poly200595752(4);
+ poly200595752.ps[0] = Point(24900, 27865);
+ poly200595752.ps[1] = Point(24900, 28185);
+ poly200595752.ps[2] = Point(24550, 28185);
+ poly200595752.ps[3] = Point(24550, 27865);
+ new ShapeRef(router, poly200595752, 200595752);
+
+ Polygon poly208373760(4);
+ poly208373760.ps[0] = Point(24800, 26140);
+ poly208373760.ps[1] = Point(24800, 26460);
+ poly208373760.ps[2] = Point(24450, 26460);
+ poly208373760.ps[3] = Point(24450, 26140);
+ new ShapeRef(router, poly208373760, 208373760);
+
+ Polygon poly208442016(4);
+ poly208442016.ps[0] = Point(27525, 28590);
+ poly208442016.ps[1] = Point(27525, 28910);
+ poly208442016.ps[2] = Point(27175, 28910);
+ poly208442016.ps[3] = Point(27175, 28590);
+ new ShapeRef(router, poly208442016, 208442016);
+
+ Polygon poly214671138(4);
+ poly214671138.ps[0] = Point(24154, 26550);
+ poly214671138.ps[1] = Point(24154, 26635);
+ poly214671138.ps[2] = Point(24096, 26635);
+ poly214671138.ps[3] = Point(24096, 26550);
+ new ShapeRef(router, poly214671138, 214671138);
+
+ Polygon poly215949184(4);
+ poly215949184.ps[0] = Point(24800, 26890);
+ poly215949184.ps[1] = Point(24800, 27210);
+ poly215949184.ps[2] = Point(24450, 27210);
+ poly215949184.ps[3] = Point(24450, 26890);
+ new ShapeRef(router, poly215949184, 215949184);
+
+JunctionRef *junctionRef221746560 = new JunctionRef(router, Point(26702, 28825), 221746560);
+
+ Polygon poly221761830(4);
+ poly221761830.ps[0] = Point(27704, 26800);
+ poly221761830.ps[1] = Point(27704, 26885);
+ poly221761830.ps[2] = Point(27646, 26885);
+ poly221761830.ps[3] = Point(27646, 26800);
+ new ShapeRef(router, poly221761830, 221761830);
+
+ Polygon poly226135532(4);
+ poly226135532.ps[0] = Point(24750, 26490);
+ poly226135532.ps[1] = Point(24750, 26810);
+ poly226135532.ps[2] = Point(24400, 26810);
+ poly226135532.ps[3] = Point(24400, 26490);
+ new ShapeRef(router, poly226135532, 226135532);
+
+JunctionRef *junctionRef228740625 = new JunctionRef(router, Point(24350, 29300), 228740625);
+
+ Polygon poly251291208(4);
+ poly251291208.ps[0] = Point(27425, 27490);
+ poly251291208.ps[1] = Point(27425, 27810);
+ poly251291208.ps[2] = Point(27075, 27810);
+ poly251291208.ps[3] = Point(27075, 27490);
+ new ShapeRef(router, poly251291208, 251291208);
+
+JunctionRef *junctionRef255105144 = new JunctionRef(router, Point(26700, 28425), 255105144);
+
+JunctionRef *junctionRef275948952 = new JunctionRef(router, Point(23281, 27100), 275948952);
+
+ Polygon poly292681455(4);
+ poly292681455.ps[0] = Point(27475, 27840);
+ poly292681455.ps[1] = Point(27475, 28160);
+ poly292681455.ps[2] = Point(27125, 28160);
+ poly292681455.ps[3] = Point(27125, 27840);
+ new ShapeRef(router, poly292681455, 292681455);
+
+JunctionRef *junctionRef295885488 = new JunctionRef(router, Point(23925, 26625), 295885488);
+
+JunctionRef *junctionRef299817832 = new JunctionRef(router, Point(24300, 27500), 299817832);
+
+JunctionRef *junctionRef309723792 = new JunctionRef(router, Point(23575, 26100), 309723792);
+
+ Polygon poly312169746(4);
+ poly312169746.ps[0] = Point(23900, 26865);
+ poly312169746.ps[1] = Point(23900, 27185);
+ poly312169746.ps[2] = Point(23550, 27185);
+ poly312169746.ps[3] = Point(23550, 26865);
+ new ShapeRef(router, poly312169746, 312169746);
+
+ Polygon poly324370200(4);
+ poly324370200.ps[0] = Point(27550, 29015);
+ poly324370200.ps[1] = Point(27550, 29335);
+ poly324370200.ps[2] = Point(27200, 29335);
+ poly324370200.ps[3] = Point(27200, 29015);
+ new ShapeRef(router, poly324370200, 324370200);
+
+ Polygon poly330285180(4);
+ poly330285180.ps[0] = Point(22604, 29350);
+ poly330285180.ps[1] = Point(22604, 29435);
+ poly330285180.ps[2] = Point(22546, 29435);
+ poly330285180.ps[3] = Point(22546, 29350);
+ new ShapeRef(router, poly330285180, 330285180);
+
+ Polygon poly343901696(4);
+ poly343901696.ps[0] = Point(24204, 26200);
+ poly343901696.ps[1] = Point(24204, 26285);
+ poly343901696.ps[2] = Point(24146, 26285);
+ poly343901696.ps[3] = Point(24146, 26200);
+ new ShapeRef(router, poly343901696, 343901696);
+
+JunctionRef *junctionRef350832579 = new JunctionRef(router, Point(25000, 28450), 350832579);
+
+ Polygon poly351751345(4);
+ poly351751345.ps[0] = Point(24000, 28840);
+ poly351751345.ps[1] = Point(24000, 29160);
+ poly351751345.ps[2] = Point(23650, 29160);
+ poly351751345.ps[3] = Point(23650, 28840);
+ new ShapeRef(router, poly351751345, 351751345);
+
+JunctionRef *junctionRef358449734 = new JunctionRef(router, Point(27616, 29175), 358449734);
+
+JunctionRef *junctionRef373450980 = new JunctionRef(router, Point(27525, 27250), 373450980);
+
+JunctionRef *junctionRef391945245 = new JunctionRef(router, Point(27500, 28350), 391945245);
+
+JunctionRef *junctionRef394539723 = new JunctionRef(router, Point(23550, 26350), 394539723);
+
+ Polygon poly396658490(4);
+ poly396658490.ps[0] = Point(27754, 27925);
+ poly396658490.ps[1] = Point(27754, 28010);
+ poly396658490.ps[2] = Point(27696, 28010);
+ poly396658490.ps[3] = Point(27696, 27925);
+ new ShapeRef(router, poly396658490, 396658490);
+
+ Polygon poly408762900(4);
+ poly408762900.ps[0] = Point(24979, 27350);
+ poly408762900.ps[1] = Point(24979, 27435);
+ poly408762900.ps[2] = Point(24921, 27435);
+ poly408762900.ps[3] = Point(24921, 27350);
+ new ShapeRef(router, poly408762900, 408762900);
+
+JunctionRef *junctionRef414982287 = new JunctionRef(router, Point(24406, 26100), 414982287);
+
+ Polygon poly486383940(4);
+ poly486383940.ps[0] = Point(24154, 26950);
+ poly486383940.ps[1] = Point(24154, 27035);
+ poly486383940.ps[2] = Point(24096, 27035);
+ poly486383940.ps[3] = Point(24096, 26950);
+ new ShapeRef(router, poly486383940, 486383940);
+
+JunctionRef *junctionRef495386613 = new JunctionRef(router, Point(23200, 29075), 495386613);
+
+JunctionRef *junctionRef504671094 = new JunctionRef(router, Point(24836, 27425), 504671094);
+
+JunctionRef *junctionRef557043721 = new JunctionRef(router, Point(26702, 29250), 557043721);
+
+JunctionRef *junctionRef619528800 = new JunctionRef(router, Point(24168, 28425), 619528800);
+
+ Polygon poly627663896(4);
+ poly627663896.ps[0] = Point(24179, 27350);
+ poly627663896.ps[1] = Point(24179, 27435);
+ poly627663896.ps[2] = Point(24121, 27435);
+ poly627663896.ps[3] = Point(24121, 27350);
+ new ShapeRef(router, poly627663896, 627663896);
+
+JunctionRef *junctionRef639333280 = new JunctionRef(router, Point(24000, 26450), 639333280);
+
+JunctionRef *junctionRef706194558 = new JunctionRef(router, Point(24300, 28550), 706194558);
+
+ Polygon poly735238470(4);
+ poly735238470.ps[0] = Point(25179, 28400);
+ poly735238470.ps[1] = Point(25179, 28485);
+ poly735238470.ps[2] = Point(25121, 28485);
+ poly735238470.ps[3] = Point(25121, 28400);
+ new ShapeRef(router, poly735238470, 735238470);
+
+JunctionRef *junctionRef736226792 = new JunctionRef(router, Point(23150, 29350), 736226792);
+
+ Polygon poly736682544(4);
+ poly736682544.ps[0] = Point(25229, 28900);
+ poly736682544.ps[1] = Point(25229, 28985);
+ poly736682544.ps[2] = Point(25171, 28985);
+ poly736682544.ps[3] = Point(25171, 28900);
+ new ShapeRef(router, poly736682544, 736682544);
+
+ Polygon poly760051248(4);
+ poly760051248.ps[0] = Point(24875, 28315);
+ poly760051248.ps[1] = Point(24875, 28635);
+ poly760051248.ps[2] = Point(24525, 28635);
+ poly760051248.ps[3] = Point(24525, 28315);
+ new ShapeRef(router, poly760051248, 760051248);
+
+JunctionRef *junctionRef790438915 = new JunctionRef(router, Point(24075, 28500), 790438915);
+
+JunctionRef *junctionRef881601350 = new JunctionRef(router, Point(27692, 29100), 881601350);
+
+ Polygon poly900057885(4);
+ poly900057885.ps[0] = Point(27704, 27575);
+ poly900057885.ps[1] = Point(27704, 27660);
+ poly900057885.ps[2] = Point(27646, 27660);
+ poly900057885.ps[3] = Point(27646, 27575);
+ new ShapeRef(router, poly900057885, 900057885);
+
+JunctionRef *junctionRef990913310 = new JunctionRef(router, Point(24000, 27025), 990913310);
+
+ ConnRef *connRef2650284 = new ConnRef(router, 2650284);
+ ConnEnd srcPt2650284(junctionRef295885488);
+ connRef2650284->setSourceEndpoint(srcPt2650284);
+ ConnEnd dstPt2650284(junctionRef639333280);
+ connRef2650284->setDestEndpoint(dstPt2650284);
+ connRef2650284->setRoutingType((ConnType)2);
+
+ ConnRef *connRef2833330 = new ConnRef(router, 2833330);
+ ConnEnd srcPt2833330(junctionRef221746560);
+ connRef2833330->setSourceEndpoint(srcPt2833330);
+ ConnEnd dstPt2833330(junctionRef255105144);
+ connRef2833330->setDestEndpoint(dstPt2833330);
+ connRef2833330->setRoutingType((ConnType)2);
+
+ ConnRef *connRef4043718 = new ConnRef(router, 4043718);
+ ConnEnd srcPt4043718(Point(27515, 28750), 8);
+ connRef4043718->setSourceEndpoint(srcPt4043718);
+ ConnEnd dstPt4043718(junctionRef16613420);
+ connRef4043718->setDestEndpoint(dstPt4043718);
+ connRef4043718->setRoutingType((ConnType)2);
+
+ ConnRef *connRef9745060 = new ConnRef(router, 9745060);
+ ConnEnd srcPt9745060(Point(23610, 28075), 4);
+ connRef9745060->setSourceEndpoint(srcPt9745060);
+ ConnEnd dstPt9745060(junctionRef147481188);
+ connRef9745060->setDestEndpoint(dstPt9745060);
+ connRef9745060->setRoutingType((ConnType)2);
+
+ ConnRef *connRef10983140 = new ConnRef(router, 10983140);
+ ConnEnd srcPt10983140(Point(23890, 26950), 8);
+ connRef10983140->setSourceEndpoint(srcPt10983140);
+ ConnEnd dstPt10983140(Point(24125, 26960), 1);
+ connRef10983140->setDestEndpoint(dstPt10983140);
+ connRef10983140->setRoutingType((ConnType)2);
+
+ ConnRef *connRef11588500 = new ConnRef(router, 11588500);
+ ConnEnd srcPt11588500(Point(23610, 27425), 4);
+ connRef11588500->setSourceEndpoint(srcPt11588500);
+ ConnEnd dstPt11588500(Point(25835, 27250), 4);
+ connRef11588500->setDestEndpoint(dstPt11588500);
+ connRef11588500->setRoutingType((ConnType)2);
+
+ ConnRef *connRef11844992 = new ConnRef(router, 11844992);
+ ConnEnd srcPt11844992(junctionRef137263932);
+ connRef11844992->setSourceEndpoint(srcPt11844992);
+ ConnEnd dstPt11844992(junctionRef117582414);
+ connRef11844992->setDestEndpoint(dstPt11844992);
+ connRef11844992->setRoutingType((ConnType)2);
+
+ ConnRef *connRef14786845 = new ConnRef(router, 14786845);
+ ConnEnd srcPt14786845(junctionRef736226792);
+ connRef14786845->setSourceEndpoint(srcPt14786845);
+ ConnEnd dstPt14786845(junctionRef495386613);
+ connRef14786845->setDestEndpoint(dstPt14786845);
+ connRef14786845->setRoutingType((ConnType)2);
+
+ ConnRef *connRef16261480 = new ConnRef(router, 16261480);
+ ConnEnd srcPt16261480(junctionRef5416208);
+ connRef16261480->setSourceEndpoint(srcPt16261480);
+ ConnEnd dstPt16261480(junctionRef299817832);
+ connRef16261480->setDestEndpoint(dstPt16261480);
+ connRef16261480->setRoutingType((ConnType)2);
+
+ ConnRef *connRef16390046 = new ConnRef(router, 16390046);
+ ConnEnd srcPt16390046(Point(24040, 29575), 8);
+ connRef16390046->setSourceEndpoint(srcPt16390046);
+ ConnEnd dstPt16390046(junctionRef39695669);
+ connRef16390046->setDestEndpoint(dstPt16390046);
+ connRef16390046->setRoutingType((ConnType)2);
+
+ ConnRef *connRef17931396 = new ConnRef(router, 17931396);
+ ConnEnd srcPt17931396(Point(27210, 29250), 4);
+ connRef17931396->setSourceEndpoint(srcPt17931396);
+ ConnEnd dstPt17931396(junctionRef557043721);
+ connRef17931396->setDestEndpoint(dstPt17931396);
+ connRef17931396->setRoutingType((ConnType)2);
+
+ ConnRef *connRef22109256 = new ConnRef(router, 22109256);
+ ConnEnd srcPt22109256(Point(27210, 29775), 4);
+ connRef22109256->setSourceEndpoint(srcPt22109256);
+ ConnEnd dstPt22109256(junctionRef557043721);
+ connRef22109256->setDestEndpoint(dstPt22109256);
+ connRef22109256->setRoutingType((ConnType)2);
+
+ ConnRef *connRef22594350 = new ConnRef(router, 22594350);
+ ConnEnd srcPt22594350(junctionRef414982287);
+ connRef22594350->setSourceEndpoint(srcPt22594350);
+ ConnEnd dstPt22594350(junctionRef34620300);
+ connRef22594350->setDestEndpoint(dstPt22594350);
+ connRef22594350->setRoutingType((ConnType)2);
+
+ ConnRef *connRef22914582 = new ConnRef(router, 22914582);
+ ConnEnd srcPt22914582(junctionRef350832579);
+ connRef22914582->setSourceEndpoint(srcPt22914582);
+ ConnEnd dstPt22914582(Point(24865, 28475), 8);
+ connRef22914582->setDestEndpoint(dstPt22914582);
+ connRef22914582->setRoutingType((ConnType)2);
+
+ ConnRef *connRef23169708 = new ConnRef(router, 23169708);
+ ConnEnd srcPt23169708(junctionRef358449734);
+ connRef23169708->setSourceEndpoint(srcPt23169708);
+ ConnEnd dstPt23169708(junctionRef881601350);
+ connRef23169708->setDestEndpoint(dstPt23169708);
+ connRef23169708->setRoutingType((ConnType)2);
+
+ ConnRef *connRef23586424 = new ConnRef(router, 23586424);
+ ConnEnd srcPt23586424(Point(23610, 27350), 4);
+ connRef23586424->setSourceEndpoint(srcPt23586424);
+ ConnEnd dstPt23586424(junctionRef26572870);
+ connRef23586424->setDestEndpoint(dstPt23586424);
+ connRef23586424->setRoutingType((ConnType)2);
+
+ ConnRef *connRef24487272 = new ConnRef(router, 24487272);
+ ConnEnd srcPt24487272(junctionRef299817832);
+ connRef24487272->setSourceEndpoint(srcPt24487272);
+ ConnEnd dstPt24487272(junctionRef137263932);
+ connRef24487272->setDestEndpoint(dstPt24487272);
+ connRef24487272->setRoutingType((ConnType)2);
+
+ ConnRef *connRef26971490 = new ConnRef(router, 26971490);
+ ConnEnd srcPt26971490(junctionRef275948952);
+ connRef26971490->setSourceEndpoint(srcPt26971490);
+ ConnEnd dstPt26971490(Point(23610, 27500), 4);
+ connRef26971490->setDestEndpoint(dstPt26971490);
+ connRef26971490->setRoutingType((ConnType)2);
+
+ ConnRef *connRef27342336 = new ConnRef(router, 27342336);
+ ConnEnd srcPt27342336(junctionRef34620300);
+ connRef27342336->setSourceEndpoint(srcPt27342336);
+ ConnEnd dstPt27342336(Point(24460, 26225), 4);
+ connRef27342336->setDestEndpoint(dstPt27342336);
+ connRef27342336->setRoutingType((ConnType)2);
+
+ ConnRef *connRef29036799 = new ConnRef(router, 29036799);
+ ConnEnd srcPt29036799(Point(23890, 27025), 8);
+ connRef29036799->setSourceEndpoint(srcPt29036799);
+ ConnEnd dstPt29036799(junctionRef990913310);
+ connRef29036799->setDestEndpoint(dstPt29036799);
+ connRef29036799->setRoutingType((ConnType)2);
+
+ ConnRef *connRef29965772 = new ConnRef(router, 29965772);
+ ConnEnd srcPt29965772(Point(27675, 26810), 1);
+ connRef29965772->setSourceEndpoint(srcPt29965772);
+ ConnEnd dstPt29965772(Point(27415, 26800), 8);
+ connRef29965772->setDestEndpoint(dstPt29965772);
+ connRef29965772->setRoutingType((ConnType)2);
+
+ ConnRef *connRef31188915 = new ConnRef(router, 31188915);
+ ConnEnd srcPt31188915(Point(24410, 26650), 4);
+ connRef31188915->setSourceEndpoint(srcPt31188915);
+ ConnEnd dstPt31188915(Point(25835, 27400), 4);
+ connRef31188915->setDestEndpoint(dstPt31188915);
+ connRef31188915->setRoutingType((ConnType)2);
+
+ ConnRef *connRef32390545 = new ConnRef(router, 32390545);
+ ConnEnd srcPt32390545(Point(27540, 29175), 8);
+ connRef32390545->setSourceEndpoint(srcPt32390545);
+ ConnEnd dstPt32390545(junctionRef358449734);
+ connRef32390545->setDestEndpoint(dstPt32390545);
+ connRef32390545->setRoutingType((ConnType)2);
+
+ ConnRef *connRef33457066 = new ConnRef(router, 33457066);
+ ConnEnd srcPt33457066(Point(27185, 28825), 4);
+ connRef33457066->setSourceEndpoint(srcPt33457066);
+ ConnEnd dstPt33457066(junctionRef221746560);
+ connRef33457066->setDestEndpoint(dstPt33457066);
+ connRef33457066->setRoutingType((ConnType)2);
+
+ ConnRef *connRef34908836 = new ConnRef(router, 34908836);
+ ConnEnd srcPt34908836(junctionRef9420650);
+ connRef34908836->setSourceEndpoint(srcPt34908836);
+ ConnEnd dstPt34908836(Point(27135, 28075), 4);
+ connRef34908836->setDestEndpoint(dstPt34908836);
+ connRef34908836->setRoutingType((ConnType)2);
+
+ ConnRef *connRef37638287 = new ConnRef(router, 37638287);
+ ConnEnd srcPt37638287(junctionRef790438915);
+ connRef37638287->setSourceEndpoint(srcPt37638287);
+ ConnEnd dstPt37638287(Point(23965, 28500), 8);
+ connRef37638287->setDestEndpoint(dstPt37638287);
+ connRef37638287->setRoutingType((ConnType)2);
+
+ ConnRef *connRef40448457 = new ConnRef(router, 40448457);
+ ConnEnd srcPt40448457(Point(24790, 26975), 8);
+ connRef40448457->setSourceEndpoint(srcPt40448457);
+ ConnEnd dstPt40448457(Point(25000, 26985), 1);
+ connRef40448457->setDestEndpoint(dstPt40448457);
+ connRef40448457->setRoutingType((ConnType)2);
+
+ ConnRef *connRef40882634 = new ConnRef(router, 40882634);
+ ConnEnd srcPt40882634(Point(23560, 26950), 4);
+ connRef40882634->setSourceEndpoint(srcPt40882634);
+ ConnEnd dstPt40882634(junctionRef26572870);
+ connRef40882634->setDestEndpoint(dstPt40882634);
+ connRef40882634->setRoutingType((ConnType)2);
+
+ ConnRef *connRef47717100 = new ConnRef(router, 47717100);
+ ConnEnd srcPt47717100(Point(25200, 28910), 1);
+ connRef47717100->setSourceEndpoint(srcPt47717100);
+ ConnEnd dstPt47717100(Point(24890, 28900), 8);
+ connRef47717100->setDestEndpoint(dstPt47717100);
+ connRef47717100->setRoutingType((ConnType)2);
+
+ ConnRef *connRef56597370 = new ConnRef(router, 56597370);
+ ConnEnd srcPt56597370(Point(27675, 27585), 1);
+ connRef56597370->setSourceEndpoint(srcPt56597370);
+ ConnEnd dstPt56597370(Point(27415, 27575), 8);
+ connRef56597370->setDestEndpoint(dstPt56597370);
+ connRef56597370->setRoutingType((ConnType)2);
+
+ ConnRef *connRef59354933 = new ConnRef(router, 59354933);
+ ConnEnd srcPt59354933(junctionRef309723792);
+ connRef59354933->setSourceEndpoint(srcPt59354933);
+ ConnEnd dstPt59354933(junctionRef414982287);
+ connRef59354933->setDestEndpoint(dstPt59354933);
+ connRef59354933->setRoutingType((ConnType)2);
+
+ ConnRef *connRef77227284 = new ConnRef(router, 77227284);
+ ConnEnd srcPt77227284(Point(24740, 26650), 8);
+ connRef77227284->setSourceEndpoint(srcPt77227284);
+ ConnEnd dstPt77227284(junctionRef131744632);
+ connRef77227284->setDestEndpoint(dstPt77227284);
+ connRef77227284->setRoutingType((ConnType)2);
+
+ ConnRef *connRef79612408 = new ConnRef(router, 79612408);
+ ConnEnd srcPt79612408(Point(23585, 26625), 4);
+ connRef79612408->setSourceEndpoint(srcPt79612408);
+ ConnEnd dstPt79612408(Point(25835, 27100), 4);
+ connRef79612408->setDestEndpoint(dstPt79612408);
+ connRef79612408->setRoutingType((ConnType)2);
+
+ ConnRef *connRef82780868 = new ConnRef(router, 82780868);
+ ConnEnd srcPt82780868(Point(27185, 28750), 4);
+ connRef82780868->setSourceEndpoint(srcPt82780868);
+ ConnEnd dstPt82780868(Point(25835, 28375), 4);
+ connRef82780868->setDestEndpoint(dstPt82780868);
+ connRef82780868->setRoutingType((ConnType)2);
+
+ ConnRef *connRef83092945 = new ConnRef(router, 83092945);
+ ConnEnd srcPt83092945(Point(27085, 27650), 4);
+ connRef83092945->setSourceEndpoint(srcPt83092945);
+ ConnEnd dstPt83092945(Point(26165, 27175), 8);
+ connRef83092945->setDestEndpoint(dstPt83092945);
+ connRef83092945->setRoutingType((ConnType)2);
+
+ ConnRef *connRef88266240 = new ConnRef(router, 88266240);
+ ConnEnd srcPt88266240(junctionRef790438915);
+ connRef88266240->setSourceEndpoint(srcPt88266240);
+ ConnEnd dstPt88266240(junctionRef137883060);
+ connRef88266240->setDestEndpoint(dstPt88266240);
+ connRef88266240->setRoutingType((ConnType)2);
+
+ ConnRef *connRef90460104 = new ConnRef(router, 90460104);
+ ConnEnd srcPt90460104(junctionRef39695669);
+ connRef90460104->setSourceEndpoint(srcPt90460104);
+ ConnEnd dstPt90460104(junctionRef790438915);
+ connRef90460104->setDestEndpoint(dstPt90460104);
+ connRef90460104->setRoutingType((ConnType)2);
+
+ ConnRef *connRef91952388 = new ConnRef(router, 91952388);
+ ConnEnd srcPt91952388(Point(25835, 27475), 4);
+ connRef91952388->setSourceEndpoint(srcPt91952388);
+ ConnEnd dstPt91952388(Point(24460, 27050), 4);
+ connRef91952388->setDestEndpoint(dstPt91952388);
+ connRef91952388->setRoutingType((ConnType)2);
+
+ ConnRef *connRef92256651 = new ConnRef(router, 92256651);
+ ConnEnd srcPt92256651(Point(27135, 28000), 4);
+ connRef92256651->setSourceEndpoint(srcPt92256651);
+ ConnEnd dstPt92256651(Point(25835, 28525), 4);
+ connRef92256651->setDestEndpoint(dstPt92256651);
+ connRef92256651->setRoutingType((ConnType)2);
+
+ ConnRef *connRef95273991 = new ConnRef(router, 95273991);
+ ConnEnd srcPt95273991(Point(27750, 29635), 1);
+ connRef95273991->setSourceEndpoint(srcPt95273991);
+ ConnEnd dstPt95273991(Point(27540, 29625), 8);
+ connRef95273991->setDestEndpoint(dstPt95273991);
+ connRef95273991->setRoutingType((ConnType)2);
+
+ ConnRef *connRef98351958 = new ConnRef(router, 98351958);
+ ConnEnd srcPt98351958(junctionRef41941580);
+ connRef98351958->setSourceEndpoint(srcPt98351958);
+ ConnEnd dstPt98351958(Point(23585, 26700), 4);
+ connRef98351958->setDestEndpoint(dstPt98351958);
+ connRef98351958->setRoutingType((ConnType)2);
+
+ ConnRef *connRef101848175 = new ConnRef(router, 101848175);
+ ConnEnd srcPt101848175(Point(24485, 27350), 4);
+ connRef101848175->setSourceEndpoint(srcPt101848175);
+ ConnEnd dstPt101848175(junctionRef23132835);
+ connRef101848175->setDestEndpoint(dstPt101848175);
+ connRef101848175->setRoutingType((ConnType)2);
+
+ ConnRef *connRef107055166 = new ConnRef(router, 107055166);
+ ConnEnd srcPt107055166(junctionRef200348672);
+ connRef107055166->setSourceEndpoint(srcPt107055166);
+ ConnEnd dstPt107055166(junctionRef195377532);
+ connRef107055166->setDestEndpoint(dstPt107055166);
+ connRef107055166->setRoutingType((ConnType)2);
+
+ ConnRef *connRef126287880 = new ConnRef(router, 126287880);
+ ConnEnd srcPt126287880(junctionRef881601350);
+ connRef126287880->setSourceEndpoint(srcPt126287880);
+ ConnEnd dstPt126287880(Point(27540, 29100), 8);
+ connRef126287880->setDestEndpoint(dstPt126287880);
+ connRef126287880->setRoutingType((ConnType)2);
+
+ ConnRef *connRef149791360 = new ConnRef(router, 149791360);
+ ConnEnd srcPt149791360(Point(24940, 29600), 8);
+ connRef149791360->setSourceEndpoint(srcPt149791360);
+ ConnEnd dstPt149791360(junctionRef36814260);
+ connRef149791360->setDestEndpoint(dstPt149791360);
+ connRef149791360->setRoutingType((ConnType)2);
+
+ ConnRef *connRef152838249 = new ConnRef(router, 152838249);
+ ConnEnd srcPt152838249(Point(24275, 29510), 1);
+ connRef152838249->setSourceEndpoint(srcPt152838249);
+ ConnEnd dstPt152838249(Point(24040, 29500), 8);
+ connRef152838249->setDestEndpoint(dstPt152838249);
+ connRef152838249->setRoutingType((ConnType)2);
+
+ ConnRef *connRef156657228 = new ConnRef(router, 156657228);
+ ConnEnd srcPt156657228(junctionRef619528800);
+ connRef156657228->setSourceEndpoint(srcPt156657228);
+ ConnEnd dstPt156657228(Point(23965, 28425), 8);
+ connRef156657228->setDestEndpoint(dstPt156657228);
+ connRef156657228->setRoutingType((ConnType)2);
+
+ ConnRef *connRef157276356 = new ConnRef(router, 157276356);
+ ConnEnd srcPt157276356(Point(24890, 28025), 8);
+ connRef157276356->setSourceEndpoint(srcPt157276356);
+ ConnEnd dstPt157276356(junctionRef350832579);
+ connRef157276356->setDestEndpoint(dstPt157276356);
+ connRef157276356->setRoutingType((ConnType)2);
+
+ ConnRef *connRef162858434 = new ConnRef(router, 162858434);
+ ConnEnd srcPt162858434(Point(24150, 27360), 1);
+ connRef162858434->setSourceEndpoint(srcPt162858434);
+ ConnEnd dstPt162858434(Point(23940, 27350), 8);
+ connRef162858434->setDestEndpoint(dstPt162858434);
+ connRef162858434->setRoutingType((ConnType)2);
+
+ ConnRef *connRef170639469 = new ConnRef(router, 170639469);
+ ConnEnd srcPt170639469(junctionRef131744632);
+ connRef170639469->setSourceEndpoint(srcPt170639469);
+ ConnEnd dstPt170639469(Point(24790, 26300), 8);
+ connRef170639469->setDestEndpoint(dstPt170639469);
+ connRef170639469->setRoutingType((ConnType)2);
+
+ ConnRef *connRef171917628 = new ConnRef(router, 171917628);
+ ConnEnd srcPt171917628(Point(24790, 27050), 8);
+ connRef171917628->setSourceEndpoint(srcPt171917628);
+ ConnEnd dstPt171917628(junctionRef1634752);
+ connRef171917628->setDestEndpoint(dstPt171917628);
+ connRef171917628->setRoutingType((ConnType)2);
+
+ ConnRef *connRef175703112 = new ConnRef(router, 175703112);
+ ConnEnd srcPt175703112(Point(22760, 29325), 4);
+ connRef175703112->setSourceEndpoint(srcPt175703112);
+ ConnEnd dstPt175703112(Point(22575, 29360), 1);
+ connRef175703112->setDestEndpoint(dstPt175703112);
+ connRef175703112->setRoutingType((ConnType)2);
+
+ ConnRef *connRef175774395 = new ConnRef(router, 175774395);
+ ConnEnd srcPt175774395(junctionRef358449734);
+ connRef175774395->setSourceEndpoint(srcPt175774395);
+ ConnEnd dstPt175774395(junctionRef16613420);
+ connRef175774395->setDestEndpoint(dstPt175774395);
+ connRef175774395->setRoutingType((ConnType)2);
+
+ ConnRef *connRef177387840 = new ConnRef(router, 177387840);
+ ConnEnd srcPt177387840(Point(27725, 27935), 1);
+ connRef177387840->setSourceEndpoint(srcPt177387840);
+ ConnEnd dstPt177387840(Point(27465, 27925), 8);
+ connRef177387840->setDestEndpoint(dstPt177387840);
+ connRef177387840->setRoutingType((ConnType)2);
+
+ ConnRef *connRef179014612 = new ConnRef(router, 179014612);
+ ConnEnd srcPt179014612(Point(24790, 26225), 8);
+ connRef179014612->setSourceEndpoint(srcPt179014612);
+ ConnEnd dstPt179014612(Point(25025, 26235), 1);
+ connRef179014612->setDestEndpoint(dstPt179014612);
+ connRef179014612->setRoutingType((ConnType)2);
+
+ ConnRef *connRef181436988 = new ConnRef(router, 181436988);
+ ConnEnd srcPt181436988(junctionRef275948952);
+ connRef181436988->setSourceEndpoint(srcPt181436988);
+ ConnEnd dstPt181436988(junctionRef41941580);
+ connRef181436988->setDestEndpoint(dstPt181436988);
+ connRef181436988->setRoutingType((ConnType)2);
+
+ ConnRef *connRef186910820 = new ConnRef(router, 186910820);
+ ConnEnd srcPt186910820(Point(25100, 27960), 1);
+ connRef186910820->setSourceEndpoint(srcPt186910820);
+ ConnEnd dstPt186910820(Point(24890, 27950), 8);
+ connRef186910820->setDestEndpoint(dstPt186910820);
+ connRef186910820->setRoutingType((ConnType)2);
+
+ ConnRef *connRef187785156 = new ConnRef(router, 187785156);
+ ConnEnd srcPt187785156(junctionRef495386613);
+ connRef187785156->setSourceEndpoint(srcPt187785156);
+ ConnEnd dstPt187785156(junctionRef58465624);
+ connRef187785156->setDestEndpoint(dstPt187785156);
+ connRef187785156->setRoutingType((ConnType)2);
+
+ ConnRef *connRef189722660 = new ConnRef(router, 189722660);
+ ConnEnd srcPt189722660(junctionRef23132835);
+ connRef189722660->setSourceEndpoint(srcPt189722660);
+ ConnEnd dstPt189722660(junctionRef12650756);
+ connRef189722660->setDestEndpoint(dstPt189722660);
+ connRef189722660->setRoutingType((ConnType)2);
+
+ ConnRef *connRef192744750 = new ConnRef(router, 192744750);
+ ConnEnd srcPt192744750(junctionRef36814260);
+ connRef192744750->setSourceEndpoint(srcPt192744750);
+ ConnEnd dstPt192744750(junctionRef137883060);
+ connRef192744750->setDestEndpoint(dstPt192744750);
+ connRef192744750->setRoutingType((ConnType)2);
+
+ ConnRef *connRef197632590 = new ConnRef(router, 197632590);
+ ConnEnd srcPt197632590(Point(25150, 29510), 1);
+ connRef197632590->setSourceEndpoint(srcPt197632590);
+ ConnEnd dstPt197632590(Point(24940, 29525), 8);
+ connRef197632590->setDestEndpoint(dstPt197632590);
+ connRef197632590->setRoutingType((ConnType)2);
+
+ ConnRef *connRef199761771 = new ConnRef(router, 199761771);
+ ConnEnd srcPt199761771(Point(25150, 28410), 1);
+ connRef199761771->setSourceEndpoint(srcPt199761771);
+ ConnEnd dstPt199761771(Point(24865, 28400), 8);
+ connRef199761771->setDestEndpoint(dstPt199761771);
+ connRef199761771->setRoutingType((ConnType)2);
+
+ ConnRef *connRef200371408 = new ConnRef(router, 200371408);
+ ConnEnd srcPt200371408(Point(23710, 29575), 4);
+ connRef200371408->setSourceEndpoint(srcPt200371408);
+ ConnEnd dstPt200371408(Point(25835, 27700), 4);
+ connRef200371408->setDestEndpoint(dstPt200371408);
+ connRef200371408->setRoutingType((ConnType)2);
+
+ ConnRef *connRef202197435 = new ConnRef(router, 202197435);
+ ConnEnd srcPt202197435(Point(23610, 26275), 4);
+ connRef202197435->setSourceEndpoint(srcPt202197435);
+ ConnEnd dstPt202197435(Point(25835, 27025), 4);
+ connRef202197435->setDestEndpoint(dstPt202197435);
+ connRef202197435->setRoutingType((ConnType)2);
+
+ ConnRef *connRef223350000 = new ConnRef(router, 223350000);
+ ConnEnd srcPt223350000(junctionRef790438915);
+ connRef223350000->setSourceEndpoint(srcPt223350000);
+ ConnEnd dstPt223350000(junctionRef619528800);
+ connRef223350000->setDestEndpoint(dstPt223350000);
+ connRef223350000->setRoutingType((ConnType)2);
+
+ ConnRef *connRef225755952 = new ConnRef(router, 225755952);
+ ConnEnd srcPt225755952(Point(26075, 26550), 15);
+ connRef225755952->setSourceEndpoint(srcPt225755952);
+ ConnEnd dstPt225755952(junctionRef414982287);
+ connRef225755952->setDestEndpoint(dstPt225755952);
+ connRef225755952->setRoutingType((ConnType)2);
+
+ ConnRef *connRef231794598 = new ConnRef(router, 231794598);
+ ConnEnd srcPt231794598(Point(24740, 26575), 8);
+ connRef231794598->setSourceEndpoint(srcPt231794598);
+ ConnEnd dstPt231794598(Point(25000, 26585), 1);
+ connRef231794598->setDestEndpoint(dstPt231794598);
+ connRef231794598->setRoutingType((ConnType)2);
+
+ ConnRef *connRef235948750 = new ConnRef(router, 235948750);
+ ConnEnd srcPt235948750(Point(24485, 27500), 4);
+ connRef235948750->setSourceEndpoint(srcPt235948750);
+ ConnEnd dstPt235948750(junctionRef299817832);
+ connRef235948750->setDestEndpoint(dstPt235948750);
+ connRef235948750->setRoutingType((ConnType)2);
+
+ ConnRef *connRef237307070 = new ConnRef(router, 237307070);
+ ConnEnd srcPt237307070(Point(24610, 29675), 4);
+ connRef237307070->setSourceEndpoint(srcPt237307070);
+ ConnEnd dstPt237307070(junctionRef228740625);
+ connRef237307070->setDestEndpoint(dstPt237307070);
+ connRef237307070->setRoutingType((ConnType)2);
+
+ ConnRef *connRef243434688 = new ConnRef(router, 243434688);
+ ConnEnd srcPt243434688(Point(23560, 27100), 4);
+ connRef243434688->setSourceEndpoint(srcPt243434688);
+ ConnEnd dstPt243434688(junctionRef275948952);
+ connRef243434688->setDestEndpoint(dstPt243434688);
+ connRef243434688->setRoutingType((ConnType)2);
+
+ ConnRef *connRef257379648 = new ConnRef(router, 257379648);
+ ConnEnd srcPt257379648(Point(24460, 27125), 4);
+ connRef257379648->setSourceEndpoint(srcPt257379648);
+ ConnEnd dstPt257379648(junctionRef137263932);
+ connRef257379648->setDestEndpoint(dstPt257379648);
+ connRef257379648->setRoutingType((ConnType)2);
+
+ ConnRef *connRef257846316 = new ConnRef(router, 257846316);
+ ConnEnd srcPt257846316(junctionRef557043721);
+ connRef257846316->setSourceEndpoint(srcPt257846316);
+ ConnEnd dstPt257846316(junctionRef228740625);
+ connRef257846316->setDestEndpoint(dstPt257846316);
+ connRef257846316->setRoutingType((ConnType)2);
+
+ ConnRef *connRef258773320 = new ConnRef(router, 258773320);
+ ConnEnd srcPt258773320(Point(27210, 29175), 4);
+ connRef258773320->setSourceEndpoint(srcPt258773320);
+ ConnEnd dstPt258773320(Point(25835, 28300), 4);
+ connRef258773320->setDestEndpoint(dstPt258773320);
+ connRef258773320->setRoutingType((ConnType)2);
+
+ ConnRef *connRef260211707 = new ConnRef(router, 260211707);
+ ConnEnd srcPt260211707(Point(23940, 27425), 8);
+ connRef260211707->setSourceEndpoint(srcPt260211707);
+ ConnEnd dstPt260211707(junctionRef990913310);
+ connRef260211707->setDestEndpoint(dstPt260211707);
+ connRef260211707->setRoutingType((ConnType)2);
+
+ ConnRef *connRef273011160 = new ConnRef(router, 273011160);
+ ConnEnd srcPt273011160(Point(23660, 29000), 4);
+ connRef273011160->setSourceEndpoint(srcPt273011160);
+ ConnEnd dstPt273011160(Point(25835, 28150), 4);
+ connRef273011160->setDestEndpoint(dstPt273011160);
+ connRef273011160->setRoutingType((ConnType)2);
+
+ ConnRef *connRef274013534 = new ConnRef(router, 274013534);
+ ConnEnd srcPt274013534(Point(24890, 28975), 8);
+ connRef274013534->setSourceEndpoint(srcPt274013534);
+ ConnEnd dstPt274013534(junctionRef36814260);
+ connRef274013534->setDestEndpoint(dstPt274013534);
+ connRef274013534->setRoutingType((ConnType)2);
+
+ ConnRef *connRef279737601 = new ConnRef(router, 279737601);
+ ConnEnd srcPt279737601(junctionRef26572870);
+ connRef279737601->setSourceEndpoint(srcPt279737601);
+ ConnEnd dstPt279737601(junctionRef309723792);
+ connRef279737601->setDestEndpoint(dstPt279737601);
+ connRef279737601->setRoutingType((ConnType)2);
+
+ ConnRef *connRef281388594 = new ConnRef(router, 281388594);
+ ConnEnd srcPt281388594(Point(27725, 28685), 1);
+ connRef281388594->setSourceEndpoint(srcPt281388594);
+ ConnEnd dstPt281388594(Point(27515, 28675), 8);
+ connRef281388594->setDestEndpoint(dstPt281388594);
+ connRef281388594->setRoutingType((ConnType)2);
+
+ ConnRef *connRef285908400 = new ConnRef(router, 285908400);
+ ConnEnd srcPt285908400(Point(23560, 27025), 4);
+ connRef285908400->setSourceEndpoint(srcPt285908400);
+ ConnEnd dstPt285908400(Point(25835, 27175), 4);
+ connRef285908400->setDestEndpoint(dstPt285908400);
+ connRef285908400->setRoutingType((ConnType)2);
+
+ ConnRef *connRef287034425 = new ConnRef(router, 287034425);
+ ConnEnd srcPt287034425(junctionRef391945245);
+ connRef287034425->setSourceEndpoint(srcPt287034425);
+ ConnEnd dstPt287034425(junctionRef200348672);
+ connRef287034425->setDestEndpoint(dstPt287034425);
+ connRef287034425->setRoutingType((ConnType)2);
+
+ ConnRef *connRef288108606 = new ConnRef(router, 288108606);
+ ConnEnd srcPt288108606(Point(23610, 26350), 4);
+ connRef288108606->setSourceEndpoint(srcPt288108606);
+ ConnEnd dstPt288108606(junctionRef394539723);
+ connRef288108606->setDestEndpoint(dstPt288108606);
+ connRef288108606->setRoutingType((ConnType)2);
+
+ ConnRef *connRef290380424 = new ConnRef(router, 290380424);
+ ConnEnd srcPt290380424(Point(24560, 29050), 4);
+ connRef290380424->setSourceEndpoint(srcPt290380424);
+ ConnEnd dstPt290380424(junctionRef144791664);
+ connRef290380424->setDestEndpoint(dstPt290380424);
+ connRef290380424->setRoutingType((ConnType)2);
+
+ ConnRef *connRef294588780 = new ConnRef(router, 294588780);
+ ConnEnd srcPt294588780(Point(27085, 27725), 4);
+ connRef294588780->setSourceEndpoint(srcPt294588780);
+ ConnEnd dstPt294588780(junctionRef9420650);
+ connRef294588780->setDestEndpoint(dstPt294588780);
+ connRef294588780->setRoutingType((ConnType)2);
+
+ ConnRef *connRef295795481 = new ConnRef(router, 295795481);
+ ConnEnd srcPt295795481(Point(24460, 26375), 4);
+ connRef295795481->setSourceEndpoint(srcPt295795481);
+ ConnEnd dstPt295795481(junctionRef117582414);
+ connRef295795481->setDestEndpoint(dstPt295795481);
+ connRef295795481->setRoutingType((ConnType)2);
+
+ ConnRef *connRef297813338 = new ConnRef(router, 297813338);
+ ConnEnd srcPt297813338(Point(24560, 28100), 4);
+ connRef297813338->setSourceEndpoint(srcPt297813338);
+ ConnEnd dstPt297813338(junctionRef5416208);
+ connRef297813338->setDestEndpoint(dstPt297813338);
+ connRef297813338->setRoutingType((ConnType)2);
+
+ ConnRef *connRef297831780 = new ConnRef(router, 297831780);
+ ConnEnd srcPt297831780(Point(27725, 29110), 1);
+ connRef297831780->setSourceEndpoint(srcPt297831780);
+ ConnEnd dstPt297831780(junctionRef881601350);
+ connRef297831780->setDestEndpoint(dstPt297831780);
+ connRef297831780->setRoutingType((ConnType)2);
+
+ ConnRef *connRef305590064 = new ConnRef(router, 305590064);
+ ConnEnd srcPt305590064(Point(24560, 28025), 4);
+ connRef305590064->setSourceEndpoint(srcPt305590064);
+ ConnEnd dstPt305590064(Point(25835, 27625), 4);
+ connRef305590064->setDestEndpoint(dstPt305590064);
+ connRef305590064->setRoutingType((ConnType)2);
+
+ ConnRef *connRef311241725 = new ConnRef(router, 311241725);
+ ConnEnd srcPt311241725(Point(27725, 28285), 1);
+ connRef311241725->setSourceEndpoint(srcPt311241725);
+ ConnEnd dstPt311241725(Point(27490, 28275), 8);
+ connRef311241725->setDestEndpoint(dstPt311241725);
+ connRef311241725->setRoutingType((ConnType)2);
+
+ ConnRef *connRef322174720 = new ConnRef(router, 322174720);
+ ConnEnd srcPt322174720(Point(24250, 27935), 1);
+ connRef322174720->setSourceEndpoint(srcPt322174720);
+ ConnEnd dstPt322174720(Point(23940, 27925), 8);
+ connRef322174720->setDestEndpoint(dstPt322174720);
+ connRef322174720->setRoutingType((ConnType)2);
+
+ ConnRef *connRef322291528 = new ConnRef(router, 322291528);
+ ConnEnd srcPt322291528(Point(23585, 26550), 4);
+ connRef322291528->setSourceEndpoint(srcPt322291528);
+ ConnEnd dstPt322291528(junctionRef26572870);
+ connRef322291528->setDestEndpoint(dstPt322291528);
+ connRef322291528->setRoutingType((ConnType)2);
+
+ ConnRef *connRef328813520 = new ConnRef(router, 328813520);
+ ConnEnd srcPt328813520(junctionRef1634752);
+ connRef328813520->setSourceEndpoint(srcPt328813520);
+ ConnEnd dstPt328813520(junctionRef131744632);
+ connRef328813520->setDestEndpoint(dstPt328813520);
+ connRef328813520->setRoutingType((ConnType)2);
+
+ ConnRef *connRef342417330 = new ConnRef(router, 342417330);
+ ConnEnd srcPt342417330(Point(24225, 28435), 1);
+ connRef342417330->setSourceEndpoint(srcPt342417330);
+ ConnEnd dstPt342417330(junctionRef619528800);
+ connRef342417330->setDestEndpoint(dstPt342417330);
+ connRef342417330->setRoutingType((ConnType)2);
+
+ ConnRef *connRef351151744 = new ConnRef(router, 351151744);
+ ConnEnd srcPt351151744(Point(25835, 27550), 4);
+ connRef351151744->setSourceEndpoint(srcPt351151744);
+ ConnEnd dstPt351151744(Point(24485, 27425), 4);
+ connRef351151744->setDestEndpoint(dstPt351151744);
+ connRef351151744->setRoutingType((ConnType)2);
+
+ ConnRef *connRef353764215 = new ConnRef(router, 353764215);
+ ConnEnd srcPt353764215(junctionRef706194558);
+ connRef353764215->setSourceEndpoint(srcPt353764215);
+ ConnEnd dstPt353764215(junctionRef5416208);
+ connRef353764215->setDestEndpoint(dstPt353764215);
+ connRef353764215->setRoutingType((ConnType)2);
+
+ ConnRef *connRef360051452 = new ConnRef(router, 360051452);
+ //ConnEnd srcPt360051452(Point(24350, 29300), 15);
+ ConnEnd srcPt360051452(junctionRef228740625);
+ connRef360051452->setSourceEndpoint(srcPt360051452);
+ ConnEnd dstPt360051452(junctionRef144791664);
+ connRef360051452->setDestEndpoint(dstPt360051452);
+ connRef360051452->setRoutingType((ConnType)2);
+
+ ConnRef *connRef370001467 = new ConnRef(router, 370001467);
+ ConnEnd srcPt370001467(Point(24535, 28550), 4);
+ connRef370001467->setSourceEndpoint(srcPt370001467);
+ ConnEnd dstPt370001467(junctionRef706194558);
+ connRef370001467->setDestEndpoint(dstPt370001467);
+ connRef370001467->setRoutingType((ConnType)2);
+
+ ConnRef *connRef374482680 = new ConnRef(router, 374482680);
+ ConnEnd srcPt374482680(junctionRef255105144);
+ connRef374482680->setSourceEndpoint(srcPt374482680);
+ ConnEnd dstPt374482680(junctionRef9420650);
+ connRef374482680->setDestEndpoint(dstPt374482680);
+ connRef374482680->setRoutingType((ConnType)2);
+
+ ConnRef *connRef384565632 = new ConnRef(router, 384565632);
+ ConnEnd srcPt384565632(Point(27160, 28350), 4);
+ connRef384565632->setSourceEndpoint(srcPt384565632);
+ ConnEnd dstPt384565632(Point(25835, 28450), 4);
+ connRef384565632->setDestEndpoint(dstPt384565632);
+ connRef384565632->setRoutingType((ConnType)2);
+
+ ConnRef *connRef385394335 = new ConnRef(router, 385394335);
+ ConnEnd srcPt385394335(junctionRef12650756);
+ connRef385394335->setSourceEndpoint(srcPt385394335);
+ ConnEnd dstPt385394335(junctionRef34620300);
+ connRef385394335->setDestEndpoint(dstPt385394335);
+ connRef385394335->setRoutingType((ConnType)2);
+
+ ConnRef *connRef394841184 = new ConnRef(router, 394841184);
+ ConnEnd srcPt394841184(junctionRef373450980);
+ connRef394841184->setSourceEndpoint(srcPt394841184);
+ ConnEnd dstPt394841184(Point(27415, 27250), 8);
+ connRef394841184->setDestEndpoint(dstPt394841184);
+ connRef394841184->setRoutingType((ConnType)2);
+
+ ConnRef *connRef395684456 = new ConnRef(router, 395684456);
+ ConnEnd srcPt395684456(junctionRef990913310);
+ connRef395684456->setSourceEndpoint(srcPt395684456);
+ ConnEnd dstPt395684456(junctionRef504671094);
+ connRef395684456->setDestEndpoint(dstPt395684456);
+ connRef395684456->setRoutingType((ConnType)2);
+
+ ConnRef *connRef399195680 = new ConnRef(router, 399195680);
+ ConnEnd srcPt399195680(Point(24460, 26300), 4);
+ connRef399195680->setSourceEndpoint(srcPt399195680);
+ ConnEnd dstPt399195680(Point(25835, 27325), 4);
+ connRef399195680->setDestEndpoint(dstPt399195680);
+ connRef399195680->setRoutingType((ConnType)2);
+
+ ConnRef *connRef430804024 = new ConnRef(router, 430804024);
+ ConnEnd srcPt430804024(Point(24410, 26575), 4);
+ connRef430804024->setSourceEndpoint(srcPt430804024);
+ ConnEnd dstPt430804024(junctionRef12650756);
+ connRef430804024->setDestEndpoint(dstPt430804024);
+ connRef430804024->setRoutingType((ConnType)2);
+
+ ConnRef *connRef441263950 = new ConnRef(router, 441263950);
+ ConnEnd srcPt441263950(junctionRef117582414);
+ connRef441263950->setSourceEndpoint(srcPt441263950);
+ ConnEnd dstPt441263950(Point(24410, 26725), 4);
+ connRef441263950->setDestEndpoint(dstPt441263950);
+ connRef441263950->setRoutingType((ConnType)2);
+
+ ConnRef *connRef449028114 = new ConnRef(router, 449028114);
+ ConnEnd srcPt449028114(junctionRef147481188);
+ connRef449028114->setSourceEndpoint(srcPt449028114);
+ ConnEnd dstPt449028114(junctionRef58465624);
+ connRef449028114->setDestEndpoint(dstPt449028114);
+ connRef449028114->setRoutingType((ConnType)2);
+
+ ConnRef *connRef456315054 = new ConnRef(router, 456315054);
+ ConnEnd srcPt456315054(junctionRef195377532);
+ connRef456315054->setSourceEndpoint(srcPt456315054);
+ ConnEnd dstPt456315054(junctionRef373450980);
+ connRef456315054->setDestEndpoint(dstPt456315054);
+ connRef456315054->setRoutingType((ConnType)2);
+
+ ConnRef *connRef463648203 = new ConnRef(router, 463648203);
+ ConnEnd srcPt463648203(Point(24535, 28475), 4);
+ connRef463648203->setSourceEndpoint(srcPt463648203);
+ ConnEnd dstPt463648203(Point(25835, 27775), 4);
+ connRef463648203->setDestEndpoint(dstPt463648203);
+ connRef463648203->setRoutingType((ConnType)2);
+
+ ConnRef *connRef466988995 = new ConnRef(router, 466988995);
+ ConnEnd srcPt466988995(Point(27465, 28000), 8);
+ connRef466988995->setSourceEndpoint(srcPt466988995);
+ ConnEnd dstPt466988995(junctionRef200348672);
+ connRef466988995->setDestEndpoint(dstPt466988995);
+ connRef466988995->setRoutingType((ConnType)2);
+
+ ConnRef *connRef470918448 = new ConnRef(router, 470918448);
+ ConnEnd srcPt470918448(Point(23710, 29650), 4);
+ connRef470918448->setSourceEndpoint(srcPt470918448);
+ ConnEnd dstPt470918448(junctionRef736226792);
+ connRef470918448->setDestEndpoint(dstPt470918448);
+ connRef470918448->setRoutingType((ConnType)2);
+
+ ConnRef *connRef473830263 = new ConnRef(router, 473830263);
+ ConnEnd srcPt473830263(junctionRef394539723);
+ connRef473830263->setSourceEndpoint(srcPt473830263);
+ ConnEnd dstPt473830263(junctionRef41941580);
+ connRef473830263->setDestEndpoint(dstPt473830263);
+ connRef473830263->setRoutingType((ConnType)2);
+
+ ConnRef *connRef475132644 = new ConnRef(router, 475132644);
+ ConnEnd srcPt475132644(Point(27725, 27185), 1);
+ connRef475132644->setSourceEndpoint(srcPt475132644);
+ ConnEnd dstPt475132644(Point(27415, 27175), 8);
+ connRef475132644->setDestEndpoint(dstPt475132644);
+ connRef475132644->setRoutingType((ConnType)2);
+
+ ConnRef *connRef482803577 = new ConnRef(router, 482803577);
+ ConnEnd srcPt482803577(Point(24560, 28975), 4);
+ connRef482803577->setSourceEndpoint(srcPt482803577);
+ ConnEnd dstPt482803577(Point(25835, 27850), 4);
+ connRef482803577->setDestEndpoint(dstPt482803577);
+ connRef482803577->setRoutingType((ConnType)2);
+
+ ConnRef *connRef485259659 = new ConnRef(router, 485259659);
+ ConnEnd srcPt485259659(Point(27085, 26875), 4);
+ connRef485259659->setSourceEndpoint(srcPt485259659);
+ ConnEnd dstPt485259659(Point(26165, 27025), 8);
+ connRef485259659->setDestEndpoint(dstPt485259659);
+ connRef485259659->setRoutingType((ConnType)2);
+
+ ConnRef *connRef489175830 = new ConnRef(router, 489175830);
+ ConnEnd srcPt489175830(Point(24610, 29600), 4);
+ connRef489175830->setSourceEndpoint(srcPt489175830);
+ ConnEnd dstPt489175830(Point(25835, 27925), 4);
+ connRef489175830->setDestEndpoint(dstPt489175830);
+ connRef489175830->setRoutingType((ConnType)2);
+
+ ConnRef *connRef491853546 = new ConnRef(router, 491853546);
+ ConnEnd srcPt491853546(Point(23940, 28000), 8);
+ connRef491853546->setSourceEndpoint(srcPt491853546);
+ ConnEnd dstPt491853546(junctionRef790438915);
+ connRef491853546->setDestEndpoint(dstPt491853546);
+ connRef491853546->setRoutingType((ConnType)2);
+
+ ConnRef *connRef493768530 = new ConnRef(router, 493768530);
+ ConnEnd srcPt493768530(Point(24460, 26975), 4);
+ connRef493768530->setSourceEndpoint(srcPt493768530);
+ ConnEnd dstPt493768530(junctionRef23132835);
+ connRef493768530->setDestEndpoint(dstPt493768530);
+ connRef493768530->setRoutingType((ConnType)2);
+
+ ConnRef *connRef545608051 = new ConnRef(router, 545608051);
+ ConnEnd srcPt545608051(Point(23915, 26550), 8);
+ connRef545608051->setSourceEndpoint(srcPt545608051);
+ ConnEnd dstPt545608051(Point(24125, 26560), 1);
+ connRef545608051->setDestEndpoint(dstPt545608051);
+ connRef545608051->setRoutingType((ConnType)2);
+
+ ConnRef *connRef553412832 = new ConnRef(router, 553412832);
+ ConnEnd srcPt553412832(Point(24815, 27350), 8);
+ connRef553412832->setSourceEndpoint(srcPt553412832);
+ ConnEnd dstPt553412832(Point(24950, 27360), 1);
+ connRef553412832->setDestEndpoint(dstPt553412832);
+ connRef553412832->setRoutingType((ConnType)2);
+
+ ConnRef *connRef561568812 = new ConnRef(router, 561568812);
+ ConnEnd srcPt561568812(Point(27085, 27250), 4);
+ connRef561568812->setSourceEndpoint(srcPt561568812);
+ ConnEnd dstPt561568812(Point(26165, 27100), 8);
+ connRef561568812->setDestEndpoint(dstPt561568812);
+ connRef561568812->setRoutingType((ConnType)2);
+
+ ConnRef *connRef567114946 = new ConnRef(router, 567114946);
+ ConnEnd srcPt567114946(junctionRef16613420);
+ connRef567114946->setSourceEndpoint(srcPt567114946);
+ ConnEnd dstPt567114946(junctionRef391945245);
+ connRef567114946->setDestEndpoint(dstPt567114946);
+ connRef567114946->setRoutingType((ConnType)2);
+
+ ConnRef *connRef568675195 = new ConnRef(router, 568675195);
+ ConnEnd srcPt568675195(Point(27540, 29700), 8);
+ connRef568675195->setSourceEndpoint(srcPt568675195);
+ ConnEnd dstPt568675195(junctionRef358449734);
+ connRef568675195->setDestEndpoint(dstPt568675195);
+ connRef568675195->setRoutingType((ConnType)2);
+
+ ConnRef *connRef578029290 = new ConnRef(router, 578029290);
+ ConnEnd srcPt578029290(junctionRef137883060);
+ connRef578029290->setSourceEndpoint(srcPt578029290);
+ ConnEnd dstPt578029290(junctionRef350832579);
+ connRef578029290->setDestEndpoint(dstPt578029290);
+ connRef578029290->setRoutingType((ConnType)2);
+
+ ConnRef *connRef580228904 = new ConnRef(router, 580228904);
+ ConnEnd srcPt580228904(Point(23660, 29075), 4);
+ connRef580228904->setSourceEndpoint(srcPt580228904);
+ ConnEnd dstPt580228904(junctionRef495386613);
+ connRef580228904->setDestEndpoint(dstPt580228904);
+ connRef580228904->setRoutingType((ConnType)2);
+
+ ConnRef *connRef591782037 = new ConnRef(router, 591782037);
+ ConnEnd srcPt591782037(Point(27210, 29700), 4);
+ connRef591782037->setSourceEndpoint(srcPt591782037);
+ ConnEnd dstPt591782037(Point(25835, 28225), 4);
+ connRef591782037->setDestEndpoint(dstPt591782037);
+ connRef591782037->setRoutingType((ConnType)2);
+
+ ConnRef *connRef592807451 = new ConnRef(router, 592807451);
+ ConnEnd srcPt592807451(junctionRef144791664);
+ connRef592807451->setSourceEndpoint(srcPt592807451);
+ ConnEnd dstPt592807451(junctionRef706194558);
+ connRef592807451->setDestEndpoint(dstPt592807451);
+ connRef592807451->setRoutingType((ConnType)2);
+
+ ConnRef *connRef594396814 = new ConnRef(router, 594396814);
+ ConnEnd srcPt594396814(junctionRef58465624);
+ connRef594396814->setSourceEndpoint(srcPt594396814);
+ ConnEnd dstPt594396814(Point(23635, 28575), 4);
+ connRef594396814->setDestEndpoint(dstPt594396814);
+ connRef594396814->setRoutingType((ConnType)2);
+
+ ConnRef *connRef599540824 = new ConnRef(router, 599540824);
+ ConnEnd srcPt599540824(Point(22890, 29325), 8);
+ connRef599540824->setSourceEndpoint(srcPt599540824);
+ ConnEnd dstPt599540824(junctionRef736226792);
+ connRef599540824->setDestEndpoint(dstPt599540824);
+ connRef599540824->setRoutingType((ConnType)2);
+
+ ConnRef *connRef603411683 = new ConnRef(router, 603411683);
+ ConnEnd srcPt603411683(Point(23610, 28000), 4);
+ connRef603411683->setSourceEndpoint(srcPt603411683);
+ ConnEnd dstPt603411683(Point(25835, 28000), 4);
+ connRef603411683->setDestEndpoint(dstPt603411683);
+ connRef603411683->setRoutingType((ConnType)2);
+
+ ConnRef *connRef605752708 = new ConnRef(router, 605752708);
+ ConnEnd srcPt605752708(Point(23610, 26200), 4);
+ connRef605752708->setSourceEndpoint(srcPt605752708);
+ ConnEnd dstPt605752708(junctionRef309723792);
+ connRef605752708->setDestEndpoint(dstPt605752708);
+ connRef605752708->setRoutingType((ConnType)2);
+
+ ConnRef *connRef606705960 = new ConnRef(router, 606705960);
+ ConnEnd srcPt606705960(junctionRef557043721);
+ connRef606705960->setSourceEndpoint(srcPt606705960);
+ ConnEnd dstPt606705960(junctionRef221746560);
+ connRef606705960->setDestEndpoint(dstPt606705960);
+ connRef606705960->setRoutingType((ConnType)2);
+
+ ConnRef *connRef609832117 = new ConnRef(router, 609832117);
+ ConnEnd srcPt609832117(junctionRef990913310);
+ connRef609832117->setSourceEndpoint(srcPt609832117);
+ ConnEnd dstPt609832117(junctionRef295885488);
+ connRef609832117->setDestEndpoint(dstPt609832117);
+ connRef609832117->setRoutingType((ConnType)2);
+
+ ConnRef *connRef621742890 = new ConnRef(router, 621742890);
+ ConnEnd srcPt621742890(junctionRef639333280);
+ connRef621742890->setSourceEndpoint(srcPt621742890);
+ ConnEnd dstPt621742890(junctionRef394539723);
+ connRef621742890->setDestEndpoint(dstPt621742890);
+ connRef621742890->setRoutingType((ConnType)2);
+
+ ConnRef *connRef636523650 = new ConnRef(router, 636523650);
+ ConnEnd srcPt636523650(Point(23940, 26275), 8);
+ connRef636523650->setSourceEndpoint(srcPt636523650);
+ ConnEnd dstPt636523650(junctionRef639333280);
+ connRef636523650->setDestEndpoint(dstPt636523650);
+ connRef636523650->setRoutingType((ConnType)2);
+
+ ConnRef *connRef642950671 = new ConnRef(router, 642950671);
+ ConnEnd srcPt642950671(Point(23940, 26200), 8);
+ connRef642950671->setSourceEndpoint(srcPt642950671);
+ ConnEnd dstPt642950671(Point(24175, 26210), 1);
+ connRef642950671->setDestEndpoint(dstPt642950671);
+ connRef642950671->setRoutingType((ConnType)2);
+
+ ConnRef *connRef651115920 = new ConnRef(router, 651115920);
+ ConnEnd srcPt651115920(Point(27160, 28425), 4);
+ connRef651115920->setSourceEndpoint(srcPt651115920);
+ ConnEnd dstPt651115920(junctionRef255105144);
+ connRef651115920->setDestEndpoint(dstPt651115920);
+ connRef651115920->setRoutingType((ConnType)2);
+
+ ConnRef *connRef671449520 = new ConnRef(router, 671449520);
+ ConnEnd srcPt671449520(Point(24250, 28935), 1);
+ connRef671449520->setSourceEndpoint(srcPt671449520);
+ ConnEnd dstPt671449520(Point(23990, 28925), 8);
+ connRef671449520->setDestEndpoint(dstPt671449520);
+ connRef671449520->setRoutingType((ConnType)2);
+
+ ConnRef *connRef683989950 = new ConnRef(router, 683989950);
+ ConnEnd srcPt683989950(Point(27415, 26875), 8);
+ connRef683989950->setSourceEndpoint(srcPt683989950);
+ ConnEnd dstPt683989950(junctionRef373450980);
+ connRef683989950->setDestEndpoint(dstPt683989950);
+ connRef683989950->setRoutingType((ConnType)2);
+
+ ConnRef *connRef906470916 = new ConnRef(router, 906470916);
+ ConnEnd srcPt906470916(junctionRef275948952);
+ connRef906470916->setSourceEndpoint(srcPt906470916);
+ ConnEnd dstPt906470916(junctionRef147481188);
+ connRef906470916->setDestEndpoint(dstPt906470916);
+ connRef906470916->setRoutingType((ConnType)2);
+
+ ConnRef *connRef952154604 = new ConnRef(router, 952154604);
+ ConnEnd srcPt952154604(junctionRef504671094);
+ connRef952154604->setSourceEndpoint(srcPt952154604);
+ ConnEnd dstPt952154604(junctionRef1634752);
+ connRef952154604->setDestEndpoint(dstPt952154604);
+ connRef952154604->setRoutingType((ConnType)2);
+
+ ConnRef *connRef952588978 = new ConnRef(router, 952588978);
+ ConnEnd srcPt952588978(Point(23635, 28500), 4);
+ connRef952588978->setSourceEndpoint(srcPt952588978);
+ ConnEnd dstPt952588978(Point(25835, 28075), 4);
+ connRef952588978->setDestEndpoint(dstPt952588978);
+ connRef952588978->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/slowrouting");
+
+ /*
+ for (int i = 0; i < 1; ++i)
+ {
+ router->moveShape(shapeRef396658490, 0.1, 0.1);
+ router->processTransaction();
+ }
+ */
+
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/tjunct.cpp b/src/3rdparty/adaptagrams/libavoid/tests/tjunct.cpp
new file mode 100644
index 0000000..656d0de
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/tjunct.cpp
@@ -0,0 +1,48 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 200);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 105);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+ JunctionRef *jRef1 = new JunctionRef(router, Point(50700, 51075));
+
+ Rectangle rect92712048(Point(51246, 50475), Point(51304, 50585));
+ new ShapeRef(router, rect92712048, 92712048);
+ Rectangle rect23127921(Point(50365, 50766), Point(50485, 50834));
+ new ShapeRef(router, rect23127921, 23127921);
+ Rectangle rect159957148(Point(51740, 50891), Point(51860, 50959));
+ new ShapeRef(router, rect159957148, 159957148);
+ Rectangle rect1350214(Point(50375, 51015), Point(50625, 51135));
+ new ShapeRef(router, rect1350214, 1350214);
+ Rectangle rect247197258(Point(50265, 51046), Point(50375, 51104));
+ new ShapeRef(router, rect247197258, 247197258);
+ Rectangle rect281096654(Point(50700, 50390), Point(51000, 50610));
+ new ShapeRef(router, rect281096654, 281096654);
+ ConnEnd srcPt342420237(Point(50425, 50800), 15);
+ ConnEnd dstPt342420237(Point(50710, 50450), 4);
+ new ConnRef(router, srcPt342420237, dstPt342420237, 342420237);
+ ConnEnd srcPt352019675(Point(50990, 50500), 8);
+ ConnEnd dstPt352019675(jRef1);
+ new ConnRef(router, srcPt352019675, dstPt352019675, 352019675);
+ ConnEnd srcPt42699400(jRef1);
+ ConnEnd dstPt42699400(Point(50615, 51075), 8);
+ new ConnRef(router, srcPt42699400, dstPt42699400, 42699400);
+ ConnEnd srcPt94712625(Point(50710, 50550), 4);
+ ConnEnd dstPt94712625(jRef1);
+ new ConnRef(router, srcPt94712625, dstPt94712625, 94712625);
+ ConnEnd srcPt92802970(Point(50990, 50450), 8);
+ ConnEnd dstPt92802970(Point(51275, 50485), 1);
+ new ConnRef(router, srcPt92802970, dstPt92802970, 92802970);
+ ConnEnd srcPt716502036(Point(50710, 50500), 4);
+ ConnEnd dstPt716502036(Point(51800, 50925), 15);
+ new ConnRef(router, srcPt716502036, dstPt716502036, 716502036);
+ router->processTransaction();
+ router->outputDiagram("output/tjunct");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/treeRootCrash01.cpp b/src/3rdparty/adaptagrams/libavoid/tests/treeRootCrash01.cpp
new file mode 100644
index 0000000..fc1f0a4
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/treeRootCrash01.cpp
@@ -0,0 +1,140 @@
+#include "libavoid/libavoid.h"
+#include <sstream>
+
+void test()
+{
+ Avoid::ConnEnd end1_0;
+ Avoid::ConnEnd end2_0;
+ Avoid::Polygon poly0;
+ Avoid::Router * router0 = new Avoid::Router(Avoid::OrthogonalRouting);
+ Avoid::HyperedgeNewAndDeletedObjectLists newanddeletedobjects_0;
+ Avoid::ConnRefList::const_iterator connit_0;
+ Avoid::JunctionRefList::const_iterator junctionit_0;
+ router0->setTransactionUse(true);
+ router0->setRoutingPenalty(Avoid::segmentPenalty);
+ router0->setRoutingParameter(Avoid::portDirectionPenalty, 100);
+ router0->setRoutingParameter(Avoid::idealNudgingDistance, 25);
+ router0->setRoutingOption(Avoid::improveHyperedgeRoutesMovingAddingAndDeletingJunctions, true);
+ router0->setRoutingPenalty(Avoid::fixedSharedPathPenalty, 9000);
+ router0->setRoutingOption(Avoid::penaliseOrthogonalSharedPathsAtConnEnds, true);
+ router0->setRoutingParameter(Avoid::crossingPenalty);
+ router0->setRoutingOption(Avoid::performUnifyingNudgingPreprocessingStep, true);
+ router0->setRoutingPenalty(Avoid::fixedSharedPathPenalty, 9000);
+ router0->setRoutingOption(Avoid::penaliseOrthogonalSharedPathsAtConnEnds, true);
+ router0->setRoutingParameter(Avoid::crossingPenalty);
+ router0->setRoutingOption(Avoid::performUnifyingNudgingPreprocessingStep, true);
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(50410, 49965));
+ poly0.setPoint(1, Avoid::Point(50410, 50710));
+ poly0.setPoint(2, Avoid::Point(49975, 50710));
+ poly0.setPoint(3, Avoid::Point(49975, 49965));
+ Avoid::ShapeRef * shape0_1023802233 = new Avoid::ShapeRef(router0, poly0, 1023802233);
+ Avoid::ShapeConnectionPin * pin0_1023802233_2 = new Avoid::ShapeConnectionPin(shape0_1023802233, 3, 0, 560, false, 10, 4);
+ pin0_1023802233_2->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_1023802233_12 = new Avoid::ShapeConnectionPin(shape0_1023802233, 13, 0, 635, false, 10, 4);
+ pin0_1023802233_12->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_1023802233_19 = new Avoid::ShapeConnectionPin(shape0_1023802233, 20, 0, 485, false, 10, 4);
+ pin0_1023802233_19->setExclusive(true);
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(49504, 50775));
+ poly0.setPoint(1, Avoid::Point(49504, 50860));
+ poly0.setPoint(2, Avoid::Point(49446, 50860));
+ poly0.setPoint(3, Avoid::Point(49446, 50775));
+ Avoid::ShapeRef * shape0_368159034 = new Avoid::ShapeRef(router0, poly0, 368159034);
+ Avoid::ShapeConnectionPin * pin0_368159034_0 = new Avoid::ShapeConnectionPin(shape0_368159034, 1, 29, 0, false, 10, 1);
+ pin0_368159034_0->setExclusive(true);
+
+ Avoid::JunctionRef * junction0_526491597 = new Avoid::JunctionRef(router0, Avoid::Point(49600, 50525), 526491597);
+ junction0_526491597->setPositionFixed(false);
+
+ Avoid::JunctionRef * junction0_30828132 = new Avoid::JunctionRef(router0, Avoid::Point(49600, 50650), 30828132);
+ junction0_30828132->setPositionFixed(false);
+
+ // Right, top - to top junction
+ end1_0 = Avoid::ConnEnd(shape0_1023802233, 20);
+ end2_0 = Avoid::ConnEnd(junction0_526491597);
+ Avoid::ConnRef * conn0_117136925 = new Avoid::ConnRef(router0, end1_0, end2_0, 117136925);
+ poly0 = Avoid::PolyLine(3);
+ poly0.setPoint(0, Avoid::Point(49975, 50450));
+ poly0.setPoint(1, Avoid::Point(49600, 50450));
+ poly0.setPoint(2, Avoid::Point(49600, 50525));
+ conn0_117136925->setFixedRoute(poly0);
+ conn0_117136925->setSourceEndpoint(end1_0);
+ conn0_117136925->setDestEndpoint(end2_0);
+
+ // Right, middle - to top junction.
+ end1_0 = Avoid::ConnEnd(shape0_1023802233, 3);
+ end2_0 = Avoid::ConnEnd(junction0_526491597);
+ Avoid::ConnRef * conn0_224626788 = new Avoid::ConnRef(router0, end1_0, end2_0, 224626788);
+
+ // Middle vertical from top junction point to lower junction.
+#ifdef CORRECTED
+ end1_0 = Avoid::ConnEnd(junction0_526491597);
+#else
+ end1_0 = Avoid::ConnEnd(Avoid::Point(49600, 50525), 15);
+#endif
+ end2_0 = Avoid::ConnEnd(junction0_30828132);
+ Avoid::ConnRef * conn0_446423927 = new Avoid::ConnRef(router0, end1_0, end2_0, 446423927);
+ poly0 = Avoid::PolyLine(3);
+ poly0.setPoint(0, Avoid::Point(49600, 50525));
+ poly0.setPoint(1, Avoid::Point(49600, 50587));
+ poly0.setPoint(2, Avoid::Point(49600, 50650));
+ conn0_446423927->setFixedRoute(poly0);
+ conn0_446423927->setSourceEndpoint(end1_0);
+ conn0_446423927->setDestEndpoint(end2_0);
+
+ // Bottom, right - to lower junction point.
+ end1_0 = Avoid::ConnEnd(shape0_1023802233, 13);
+#ifdef CORRECTED
+ end2_0 = Avoid::ConnEnd(junction0_30828132);
+#else
+ end2_0 = Avoid::ConnEnd(Avoid::Point(49600, 50650), 15);
+#endif
+ Avoid::ConnRef * conn0_11189244 = new Avoid::ConnRef(router0, end1_0, end2_0, 11189244);
+ poly0 = Avoid::PolyLine(3);
+ poly0.setPoint(0, Avoid::Point(49975, 50600));
+ poly0.setPoint(1, Avoid::Point(49600, 50600));
+ poly0.setPoint(2, Avoid::Point(49600, 50650));
+ conn0_11189244->setFixedRoute(poly0);
+ conn0_11189244->setSourceEndpoint(end1_0);
+ conn0_11189244->setDestEndpoint(end2_0);
+
+ // Left bottom - to lower junction.
+ end1_0 = Avoid::ConnEnd(shape0_368159034, 1);
+ end2_0 = Avoid::ConnEnd(junction0_30828132);
+ Avoid::ConnRef * conn0_280909026 = new Avoid::ConnRef(router0, end1_0, end2_0, 280909026);
+
+ router0->processTransaction();
+
+ newanddeletedobjects_0 = router0->newAndDeletedObjectListsFromHyperedgeImprovement();
+ router0->outputDiagram("output/treeRootCrash01-1");
+
+ conn0_117136925->clearFixedRoute();
+ conn0_224626788->makePathInvalid();
+ conn0_446423927->clearFixedRoute();
+ conn0_11189244->clearFixedRoute();
+ conn0_280909026->makePathInvalid();
+ junction0_526491597->setPositionFixed(false);
+ junction0_30828132->setPositionFixed(false);
+ router0->processTransaction();
+
+ newanddeletedobjects_0 = router0->newAndDeletedObjectListsFromHyperedgeImprovement();
+ router0->outputDiagram("output/treeRootCrash01-2");
+ router0->processTransaction();
+
+ newanddeletedobjects_0 = router0->newAndDeletedObjectListsFromHyperedgeImprovement();
+ router0->outputDiagram("output/treeRootCrash01-3");
+
+ router0->hyperedgeRerouter()->registerHyperedgeForRerouting(junction0_526491597);
+ router0->processTransaction();
+ router0->outputDiagram("output/treeRootCrash01-4");
+
+ delete router0;
+}
+
+
+extern "C" int main(int argc, char* argv[])
+{
+ test();
+ return 0;
+}
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/treeRootCrash02.cpp b/src/3rdparty/adaptagrams/libavoid/tests/treeRootCrash02.cpp
new file mode 100644
index 0000000..5f26b3e
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/treeRootCrash02.cpp
@@ -0,0 +1,243 @@
+// Based on constructInterleavedCrash bug report.
+//
+#include "libavoid/libavoid.h"
+#include <sstream>
+
+void test()
+{
+ Avoid::ConnEnd end1_0;
+ Avoid::ConnEnd end2_0;
+ Avoid::Polygon poly0;
+ Avoid::Router * router0 = new Avoid::Router(Avoid::OrthogonalRouting);
+ Avoid::HyperedgeNewAndDeletedObjectLists newanddeletedobjects_0;
+ Avoid::ConnRefList::const_iterator connit_0;
+ Avoid::JunctionRefList::const_iterator junctionit_0;
+ router0->setTransactionUse(true);
+ router0->setRoutingPenalty(Avoid::segmentPenalty);
+ router0->setRoutingParameter(Avoid::portDirectionPenalty, 100);
+ router0->setRoutingParameter(Avoid::idealNudgingDistance, 25);
+ router0->setRoutingOption(Avoid::improveHyperedgeRoutesMovingAddingAndDeletingJunctions, true);
+ router0->setRoutingPenalty(Avoid::fixedSharedPathPenalty, 9000);
+ router0->setRoutingOption(Avoid::penaliseOrthogonalSharedPathsAtConnEnds, true);
+ router0->setRoutingParameter(Avoid::crossingPenalty);
+ router0->setRoutingOption(Avoid::performUnifyingNudgingPreprocessingStep, true);
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(50410, 49975));
+ poly0.setPoint(1, Avoid::Point(50410, 50710));
+ poly0.setPoint(2, Avoid::Point(49975, 50710));
+ poly0.setPoint(3, Avoid::Point(49975, 49975));
+ Avoid::ShapeRef * shape0_1023802233 = new Avoid::ShapeRef(router0, poly0, 1023802233);
+ Avoid::ShapeConnectionPin * pin0_1023802233_0 = new Avoid::ShapeConnectionPin(shape0_1023802233, 1, 0, 100, false, 10, 4);
+ pin0_1023802233_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_1023802233_1 = new Avoid::ShapeConnectionPin(shape0_1023802233, 2, 0, 250, false, 10, 4);
+ pin0_1023802233_1->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_1023802233_2 = new Avoid::ShapeConnectionPin(shape0_1023802233, 3, 0, 550, false, 10, 4);
+ pin0_1023802233_2->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_1023802233_3 = new Avoid::ShapeConnectionPin(shape0_1023802233, 4, 425, 100, false, 10, 8);
+ pin0_1023802233_3->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_1023802233_4 = new Avoid::ShapeConnectionPin(shape0_1023802233, 5, 250, 0, false, 10, 1);
+ pin0_1023802233_4->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_1023802233_5 = new Avoid::ShapeConnectionPin(shape0_1023802233, 6, 425, 250, false, 10, 8);
+ pin0_1023802233_5->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_1023802233_6 = new Avoid::ShapeConnectionPin(shape0_1023802233, 7, 250, 725, false, 10, 2);
+ pin0_1023802233_6->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_1023802233_7 = new Avoid::ShapeConnectionPin(shape0_1023802233, 8, 100, 725, false, 10, 2);
+ pin0_1023802233_7->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_1023802233_8 = new Avoid::ShapeConnectionPin(shape0_1023802233, 9, 100, 0, false, 10, 1);
+ pin0_1023802233_8->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_1023802233_9 = new Avoid::ShapeConnectionPin(shape0_1023802233, 10, 0, 400, false, 10, 4);
+ pin0_1023802233_9->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_1023802233_10 = new Avoid::ShapeConnectionPin(shape0_1023802233, 11, 0, 175, false, 10, 4);
+ pin0_1023802233_10->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_1023802233_11 = new Avoid::ShapeConnectionPin(shape0_1023802233, 12, 0, 325, false, 10, 4);
+ pin0_1023802233_11->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_1023802233_12 = new Avoid::ShapeConnectionPin(shape0_1023802233, 13, 0, 625, false, 10, 4);
+ pin0_1023802233_12->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_1023802233_13 = new Avoid::ShapeConnectionPin(shape0_1023802233, 14, 425, 175, false, 10, 8);
+ pin0_1023802233_13->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_1023802233_14 = new Avoid::ShapeConnectionPin(shape0_1023802233, 15, 325, 0, false, 10, 1);
+ pin0_1023802233_14->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_1023802233_15 = new Avoid::ShapeConnectionPin(shape0_1023802233, 16, 425, 325, false, 10, 8);
+ pin0_1023802233_15->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_1023802233_16 = new Avoid::ShapeConnectionPin(shape0_1023802233, 17, 325, 725, false, 10, 2);
+ pin0_1023802233_16->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_1023802233_17 = new Avoid::ShapeConnectionPin(shape0_1023802233, 18, 175, 725, false, 10, 2);
+ pin0_1023802233_17->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_1023802233_18 = new Avoid::ShapeConnectionPin(shape0_1023802233, 19, 175, 0, false, 10, 1);
+ pin0_1023802233_18->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_1023802233_19 = new Avoid::ShapeConnectionPin(shape0_1023802233, 20, 0, 475, false, 10, 4);
+ pin0_1023802233_19->setExclusive(true);
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(49535, 50540));
+ poly0.setPoint(1, Avoid::Point(49535, 50650));
+ poly0.setPoint(2, Avoid::Point(49415, 50650));
+ poly0.setPoint(3, Avoid::Point(49415, 50540));
+ Avoid::ShapeRef * shape0_145706592 = new Avoid::ShapeRef(router0, poly0, 145706592);
+ Avoid::ShapeConnectionPin * pin0_145706592_0 = new Avoid::ShapeConnectionPin(shape0_145706592, 1, 60, 10, false, 10, 1);
+ pin0_145706592_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_145706592_1 = new Avoid::ShapeConnectionPin(shape0_145706592, 2, 60, -1, false, 10, 2);
+ pin0_145706592_1->setExclusive(true);
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(49504, 50775));
+ poly0.setPoint(1, Avoid::Point(49504, 50860));
+ poly0.setPoint(2, Avoid::Point(49446, 50860));
+ poly0.setPoint(3, Avoid::Point(49446, 50775));
+ Avoid::ShapeRef * shape0_368159034 = new Avoid::ShapeRef(router0, poly0, 368159034);
+ Avoid::ShapeConnectionPin * pin0_368159034_0 = new Avoid::ShapeConnectionPin(shape0_368159034, 1, 29, 0, false, 10, 1);
+ pin0_368159034_0->setExclusive(true);
+ Avoid::JunctionRef * junction0_144230940 = new Avoid::JunctionRef(router0, Avoid::Point(49475, 50725), 144230940);
+ junction0_144230940->setPositionFixed(true);
+ Avoid::JunctionRef * junction0_526491597 = new Avoid::JunctionRef(router0, Avoid::Point(49600, 50525), 526491597);
+ junction0_526491597->setPositionFixed(true);
+ Avoid::JunctionRef * junction0_30828132 = new Avoid::JunctionRef(router0, Avoid::Point(49600, 50650), 30828132);
+ junction0_30828132->setPositionFixed(true);
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(50485, 49265));
+ poly0.setPoint(1, Avoid::Point(50485, 49550));
+ poly0.setPoint(2, Avoid::Point(50190, 49550));
+ poly0.setPoint(3, Avoid::Point(50190, 49265));
+ Avoid::ShapeRef * shape0_59732242 = new Avoid::ShapeRef(router0, poly0, 59732242);
+ Avoid::ShapeConnectionPin * pin0_59732242_0 = new Avoid::ShapeConnectionPin(shape0_59732242, 1, 110, 10, false, 10, 1);
+ pin0_59732242_0->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_59732242_1 = new Avoid::ShapeConnectionPin(shape0_59732242, 2, 10, 110, false, 10, 4);
+ pin0_59732242_1->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_59732242_2 = new Avoid::ShapeConnectionPin(shape0_59732242, 3, 110, -1, false, 10, 2);
+ pin0_59732242_2->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_59732242_3 = new Avoid::ShapeConnectionPin(shape0_59732242, 4, 285, 110, false, 10, 8);
+ pin0_59732242_3->setExclusive(true);
+ Avoid::ShapeConnectionPin * pin0_59732242_4 = new Avoid::ShapeConnectionPin(shape0_59732242, 5, 285, 185, false, 10, 8);
+ pin0_59732242_4->setExclusive(true);
+ poly0 = Avoid::Polygon(4);
+ poly0.setPoint(0, Avoid::Point(50610, 49646));
+ poly0.setPoint(1, Avoid::Point(50610, 49704));
+ poly0.setPoint(2, Avoid::Point(50525, 49704));
+ poly0.setPoint(3, Avoid::Point(50525, 49646));
+ Avoid::ShapeRef * shape0_152071508 = new Avoid::ShapeRef(router0, poly0, 152071508);
+ Avoid::ShapeConnectionPin * pin0_152071508_0 = new Avoid::ShapeConnectionPin(shape0_152071508, 1, 0, 29, false, 10, 4);
+ pin0_152071508_0->setExclusive(true);
+ Avoid::JunctionRef * junction0_24560921 = new Avoid::JunctionRef(router0, Avoid::Point(50300, 49675), 24560921);
+ junction0_24560921->setPositionFixed(true);
+ end1_0 = Avoid::ConnEnd(shape0_145706592, 2);
+ end2_0 = Avoid::ConnEnd(junction0_144230940);
+ Avoid::ConnRef * conn0_61425638 = new Avoid::ConnRef(router0, end1_0, end2_0, 61425638);
+ end1_0 = Avoid::ConnEnd(junction0_144230940);
+ end2_0 = Avoid::ConnEnd(shape0_368159034, 1);
+ Avoid::ConnRef * conn0_378385232 = new Avoid::ConnRef(router0, end1_0, end2_0, 378385232);
+ end1_0 = Avoid::ConnEnd(Avoid::Point(49975, 50450), 15);
+ end2_0 = Avoid::ConnEnd(Avoid::Point(49600, 50525), 15);
+ Avoid::ConnRef * conn0_117136925 = new Avoid::ConnRef(router0, end1_0, end2_0, 117136925);
+ poly0 = Avoid::PolyLine(3);
+ poly0.setPoint(0, Avoid::Point(49975, 50450));
+ poly0.setPoint(1, Avoid::Point(49600, 50450));
+ poly0.setPoint(2, Avoid::Point(49600, 50525));
+ conn0_117136925->setFixedRoute(poly0);
+ conn0_117136925->setSourceEndpoint(end1_0);
+ conn0_117136925->setDestEndpoint(end2_0);
+ end1_0 = Avoid::ConnEnd(shape0_1023802233, 3);
+ end2_0 = Avoid::ConnEnd(junction0_526491597);
+ Avoid::ConnRef * conn0_224626788 = new Avoid::ConnRef(router0, end1_0, end2_0, 224626788);
+ end1_0 = Avoid::ConnEnd(Avoid::Point(49600, 50525), 15);
+ end2_0 = Avoid::ConnEnd(Avoid::Point(49600, 50650), 15);
+ Avoid::ConnRef * conn0_446423927 = new Avoid::ConnRef(router0, end1_0, end2_0, 446423927);
+ poly0 = Avoid::PolyLine(3);
+ poly0.setPoint(0, Avoid::Point(49600, 50525));
+ poly0.setPoint(1, Avoid::Point(49600, 50587));
+ poly0.setPoint(2, Avoid::Point(49600, 50650));
+ conn0_446423927->setFixedRoute(poly0);
+ conn0_446423927->setSourceEndpoint(end1_0);
+ conn0_446423927->setDestEndpoint(end2_0);
+ end1_0 = Avoid::ConnEnd(Avoid::Point(49600, 50650), 15);
+ end2_0 = Avoid::ConnEnd(Avoid::Point(49475, 50725), 15);
+ Avoid::ConnRef * conn0_880789055 = new Avoid::ConnRef(router0, end1_0, end2_0, 880789055);
+ poly0 = Avoid::PolyLine(3);
+ poly0.setPoint(0, Avoid::Point(49600, 50650));
+ poly0.setPoint(1, Avoid::Point(49600, 50725));
+ poly0.setPoint(2, Avoid::Point(49475, 50725));
+ conn0_880789055->setFixedRoute(poly0);
+ conn0_880789055->setSourceEndpoint(end1_0);
+ conn0_880789055->setDestEndpoint(end2_0);
+ end1_0 = Avoid::ConnEnd(Avoid::Point(49975, 50600), 15);
+ end2_0 = Avoid::ConnEnd(Avoid::Point(49600, 50650), 15);
+ Avoid::ConnRef * conn0_11189244 = new Avoid::ConnRef(router0, end1_0, end2_0, 11189244);
+ poly0 = Avoid::PolyLine(3);
+ poly0.setPoint(0, Avoid::Point(49975, 50600));
+ poly0.setPoint(1, Avoid::Point(49600, 50600));
+ poly0.setPoint(2, Avoid::Point(49600, 50650));
+ conn0_11189244->setFixedRoute(poly0);
+ conn0_11189244->setSourceEndpoint(end1_0);
+ conn0_11189244->setDestEndpoint(end2_0);
+ end1_0 = Avoid::ConnEnd(shape0_59732242, 3);
+ end2_0 = Avoid::ConnEnd(junction0_24560921);
+ Avoid::ConnRef * conn0_605306624 = new Avoid::ConnRef(router0, end1_0, end2_0, 605306624);
+ end1_0 = Avoid::ConnEnd(junction0_24560921);
+ end2_0 = Avoid::ConnEnd(shape0_1023802233, 15);
+ Avoid::ConnRef * conn0_61198110 = new Avoid::ConnRef(router0, end1_0, end2_0, 61198110);
+ end1_0 = Avoid::ConnEnd(shape0_1023802233, 19);
+ end2_0 = Avoid::ConnEnd(junction0_24560921);
+ Avoid::ConnRef * conn0_323306544 = new Avoid::ConnRef(router0, end1_0, end2_0, 323306544);
+ end1_0 = Avoid::ConnEnd(shape0_152071508, 1);
+ end2_0 = Avoid::ConnEnd(junction0_24560921);
+ Avoid::ConnRef * conn0_2415000 = new Avoid::ConnRef(router0, end1_0, end2_0, 2415000);
+ router0->processTransaction();
+
+ newanddeletedobjects_0 = router0->newAndDeletedObjectListsFromHyperedgeImprovement();
+ router0->outputDiagram("output/treeRootCrash02-1");
+ end2_0 = Avoid::ConnEnd(junction0_144230940);
+ conn0_61425638->setDestEndpoint(end2_0);
+ conn0_61425638->makePathInvalid();
+ conn0_378385232->makePathInvalid();
+ end1_0 = Avoid::ConnEnd(shape0_1023802233, 20);
+ end2_0 = Avoid::ConnEnd(junction0_526491597);
+ conn0_117136925->setSourceEndpoint(end1_0);
+ conn0_117136925->setDestEndpoint(end2_0);
+ conn0_117136925->clearFixedRoute();
+ conn0_224626788->makePathInvalid();
+ end2_0 = Avoid::ConnEnd(junction0_30828132);
+ conn0_446423927->setDestEndpoint(end2_0);
+ conn0_446423927->clearFixedRoute();
+ conn0_880789055->clearFixedRoute();
+ end1_0 = Avoid::ConnEnd(shape0_1023802233, 13);
+ conn0_11189244->setSourceEndpoint(end1_0);
+ conn0_11189244->clearFixedRoute();
+ conn0_605306624->makePathInvalid();
+ conn0_61198110->makePathInvalid();
+ conn0_323306544->makePathInvalid();
+ conn0_2415000->makePathInvalid();
+ junction0_144230940->setPositionFixed(false);
+ junction0_30828132->setPositionFixed(false);
+ junction0_526491597->setPositionFixed(false);
+ end2_0 = Avoid::ConnEnd(junction0_144230940);
+ conn0_61425638->setDestEndpoint(end2_0);
+ conn0_61425638->makePathInvalid();
+ conn0_378385232->makePathInvalid();
+ end2_0 = Avoid::ConnEnd(junction0_526491597);
+ conn0_117136925->setDestEndpoint(end2_0);
+ conn0_117136925->makePathInvalid();
+ conn0_224626788->makePathInvalid();
+ end2_0 = Avoid::ConnEnd(junction0_30828132);
+ conn0_446423927->setDestEndpoint(end2_0);
+ conn0_446423927->makePathInvalid();
+ conn0_880789055->makePathInvalid();
+ conn0_11189244->makePathInvalid();
+ junction0_24560921->setPositionFixed(false);
+ end2_0 = Avoid::ConnEnd(junction0_24560921);
+ conn0_605306624->setDestEndpoint(end2_0);
+ conn0_605306624->makePathInvalid();
+ conn0_61198110->makePathInvalid();
+ conn0_323306544->makePathInvalid();
+ conn0_2415000->makePathInvalid();
+ router0->hyperedgeRerouter()->registerHyperedgeForRerouting(junction0_24560921);
+ router0->hyperedgeRerouter()->registerHyperedgeForRerouting(junction0_526491597);
+ router0->processTransaction();
+
+ newanddeletedobjects_0 = router0->newAndDeletedObjectListsFromHyperedgeImprovement();
+ router0->outputDiagram("output/treeRootCrash02-2");
+
+ delete router0;
+}
+
+extern "C" int main(int argc, char* argv[])
+{
+ test();
+ return 0;
+}
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/unsatisfiableRangeAssertion.cpp b/src/3rdparty/adaptagrams/libavoid/tests/unsatisfiableRangeAssertion.cpp
new file mode 100644
index 0000000..323c098
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/unsatisfiableRangeAssertion.cpp
@@ -0,0 +1,25789 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(OrthogonalRouting);
+ router->setRoutingParameter((RoutingParameter)0, 50);
+ router->setRoutingParameter((RoutingParameter)1, 0);
+ router->setRoutingParameter((RoutingParameter)2, 0);
+ router->setRoutingParameter((RoutingParameter)3, 4000);
+ router->setRoutingParameter((RoutingParameter)4, 0);
+ router->setRoutingParameter((RoutingParameter)5, 0);
+ router->setRoutingParameter((RoutingParameter)6, 0);
+ router->setRoutingParameter((RoutingParameter)7, 4);
+ router->setRoutingOption((RoutingOption)0, true);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingOption((RoutingOption)2, false);
+ router->setRoutingOption((RoutingOption)3, false);
+ router->setRoutingOption((RoutingOption)4, false);
+ router->setRoutingOption((RoutingOption)5, false);
+ Polygon polygon;
+ ConnRef *connRef = nullptr;
+ ConnEnd srcPt;
+ ConnEnd dstPt;
+ PolyLine newRoute;
+ // shapeRef1
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4056, 12427.7);
+ polygon.ps[1] = Point(4056, 12489.7);
+ polygon.ps[2] = Point(3994, 12489.7);
+ polygon.ps[3] = Point(3994, 12427.7);
+ new ShapeRef(router, polygon, 1);
+
+ // shapeRef2
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1911, 12427.7);
+ polygon.ps[1] = Point(1911, 12489.7);
+ polygon.ps[2] = Point(1849, 12489.7);
+ polygon.ps[3] = Point(1849, 12427.7);
+ new ShapeRef(router, polygon, 2);
+
+ // shapeRef3
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1449, 2119.29);
+ polygon.ps[1] = Point(1449, 2181.29);
+ polygon.ps[2] = Point(1387, 2181.29);
+ polygon.ps[3] = Point(1387, 2119.29);
+ new ShapeRef(router, polygon, 3);
+
+ // shapeRef4
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1449, 2317.29);
+ polygon.ps[1] = Point(1449, 2379.29);
+ polygon.ps[2] = Point(1387, 2379.29);
+ polygon.ps[3] = Point(1387, 2317.29);
+ new ShapeRef(router, polygon, 4);
+
+ // shapeRef5
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3561, 328.265);
+ polygon.ps[1] = Point(3561, 390.265);
+ polygon.ps[2] = Point(3499, 390.265);
+ polygon.ps[3] = Point(3499, 328.265);
+ new ShapeRef(router, polygon, 5);
+
+ // shapeRef6
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(360, 2119.29);
+ polygon.ps[1] = Point(360, 2181.29);
+ polygon.ps[2] = Point(298, 2181.29);
+ polygon.ps[3] = Point(298, 2119.29);
+ new ShapeRef(router, polygon, 6);
+
+ // shapeRef7
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1383, 678.091);
+ polygon.ps[1] = Point(1383, 740.091);
+ polygon.ps[2] = Point(1321, 740.091);
+ polygon.ps[3] = Point(1321, 678.091);
+ new ShapeRef(router, polygon, 7);
+
+ // shapeRef8
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(921, 678.091);
+ polygon.ps[1] = Point(921, 740.091);
+ polygon.ps[2] = Point(859, 740.091);
+ polygon.ps[3] = Point(859, 678.091);
+ new ShapeRef(router, polygon, 8);
+
+ // shapeRef9
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2670, 678.091);
+ polygon.ps[1] = Point(2670, 740.091);
+ polygon.ps[2] = Point(2608, 740.091);
+ polygon.ps[3] = Point(2608, 678.091);
+ new ShapeRef(router, polygon, 9);
+
+ // shapeRef10
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5758.1, 1480.29);
+ polygon.ps[1] = Point(5758.1, 1542.29);
+ polygon.ps[2] = Point(5696.1, 1542.29);
+ polygon.ps[3] = Point(5696.1, 1480.29);
+ new ShapeRef(router, polygon, 10);
+
+ // shapeRef11
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5310, 1480.29);
+ polygon.ps[1] = Point(5310, 1542.29);
+ polygon.ps[2] = Point(5248, 1542.29);
+ polygon.ps[3] = Point(5248, 1480.29);
+ new ShapeRef(router, polygon, 11);
+
+ // shapeRef12
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4881, 12427.7);
+ polygon.ps[1] = Point(4881, 12489.7);
+ polygon.ps[2] = Point(4819, 12489.7);
+ polygon.ps[3] = Point(4819, 12427.7);
+ new ShapeRef(router, polygon, 12);
+
+ // shapeRef13
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4881, 12129.3);
+ polygon.ps[1] = Point(4881, 12191.3);
+ polygon.ps[2] = Point(4819, 12191.3);
+ polygon.ps[3] = Point(4819, 12129.3);
+ new ShapeRef(router, polygon, 13);
+
+ // shapeRef14
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3330, 6252.51);
+ polygon.ps[1] = Point(3330, 6314.51);
+ polygon.ps[2] = Point(3268, 6314.51);
+ polygon.ps[3] = Point(3268, 6252.51);
+ new ShapeRef(router, polygon, 14);
+
+ // shapeRef15
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1416, 7647.79);
+ polygon.ps[1] = Point(1416, 7709.79);
+ polygon.ps[2] = Point(1354, 7709.79);
+ polygon.ps[3] = Point(1354, 7647.79);
+ new ShapeRef(router, polygon, 15);
+
+ // shapeRef16
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1416, 8109.79);
+ polygon.ps[1] = Point(1416, 8171.79);
+ polygon.ps[2] = Point(1354, 8171.79);
+ polygon.ps[3] = Point(1354, 8109.79);
+ new ShapeRef(router, polygon, 16);
+
+ // shapeRef17
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4650, 7097.4);
+ polygon.ps[1] = Point(4650, 7159.4);
+ polygon.ps[2] = Point(4588, 7159.4);
+ polygon.ps[3] = Point(4588, 7097.4);
+ new ShapeRef(router, polygon, 17);
+
+ // shapeRef18
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1284, 8482.99);
+ polygon.ps[1] = Point(1284, 8544.99);
+ polygon.ps[2] = Point(1222, 8544.99);
+ polygon.ps[3] = Point(1222, 8482.99);
+ new ShapeRef(router, polygon, 18);
+
+ // shapeRef19
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1647, 8109.79);
+ polygon.ps[1] = Point(1647, 8171.79);
+ polygon.ps[2] = Point(1585, 8171.79);
+ polygon.ps[3] = Point(1585, 8109.79);
+ new ShapeRef(router, polygon, 19);
+
+ // shapeRef20
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1647, 7163.4);
+ polygon.ps[1] = Point(1647, 7225.4);
+ polygon.ps[2] = Point(1585, 7225.4);
+ polygon.ps[3] = Point(1585, 7163.4);
+ new ShapeRef(router, polygon, 20);
+
+ // shapeRef21
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 4997.89);
+ polygon.ps[1] = Point(9289.03, 5037.89);
+ polygon.ps[2] = Point(9234.03, 5037.89);
+ polygon.ps[3] = Point(9234.03, 4997.89);
+ new ShapeRef(router, polygon, 21);
+
+ // shapeRef22
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 4997.89);
+ polygon.ps[1] = Point(9389.03, 5037.89);
+ polygon.ps[2] = Point(9334.03, 5037.89);
+ polygon.ps[3] = Point(9334.03, 4997.89);
+ new ShapeRef(router, polygon, 22);
+
+ // shapeRef23
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 5097.89);
+ polygon.ps[1] = Point(8389.03, 5137.89);
+ polygon.ps[2] = Point(8334.03, 5137.89);
+ polygon.ps[3] = Point(8334.03, 5097.89);
+ new ShapeRef(router, polygon, 23);
+
+ // shapeRef24
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4056, 5039.4);
+ polygon.ps[1] = Point(4056, 5101.4);
+ polygon.ps[2] = Point(3994, 5101.4);
+ polygon.ps[3] = Point(3994, 5039.4);
+ new ShapeRef(router, polygon, 24);
+
+ // shapeRef25
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4452, 5039.4);
+ polygon.ps[1] = Point(4452, 5101.4);
+ polygon.ps[2] = Point(4390, 5101.4);
+ polygon.ps[3] = Point(4390, 5039.4);
+ new ShapeRef(router, polygon, 25);
+
+ // shapeRef26
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 5097.89);
+ polygon.ps[1] = Point(8689.03, 5137.89);
+ polygon.ps[2] = Point(8634.03, 5137.89);
+ polygon.ps[3] = Point(8634.03, 5097.89);
+ new ShapeRef(router, polygon, 26);
+
+ // shapeRef27
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 5097.89);
+ polygon.ps[1] = Point(8789.03, 5137.89);
+ polygon.ps[2] = Point(8734.03, 5137.89);
+ polygon.ps[3] = Point(8734.03, 5097.89);
+ new ShapeRef(router, polygon, 27);
+
+ // shapeRef28
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16753.8, 10750.3);
+ polygon.ps[1] = Point(16753.8, 10812.3);
+ polygon.ps[2] = Point(16691.8, 10812.3);
+ polygon.ps[3] = Point(16691.8, 10750.3);
+ new ShapeRef(router, polygon, 28);
+
+ // shapeRef29
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16493.6, 10750.3);
+ polygon.ps[1] = Point(16493.6, 10812.3);
+ polygon.ps[2] = Point(16431.6, 10812.3);
+ polygon.ps[3] = Point(16431.6, 10750.3);
+ new ShapeRef(router, polygon, 29);
+
+ // shapeRef30
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1086, 5481.67);
+ polygon.ps[1] = Point(1086, 5543.67);
+ polygon.ps[2] = Point(1024, 5543.67);
+ polygon.ps[3] = Point(1024, 5481.67);
+ new ShapeRef(router, polygon, 30);
+
+ // shapeRef31
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(591, 6582.51);
+ polygon.ps[1] = Point(591, 6644.51);
+ polygon.ps[2] = Point(529, 6644.51);
+ polygon.ps[3] = Point(529, 6582.51);
+ new ShapeRef(router, polygon, 31);
+
+ // shapeRef32
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(591, 7064.4);
+ polygon.ps[1] = Point(591, 7126.4);
+ polygon.ps[2] = Point(529, 7126.4);
+ polygon.ps[3] = Point(529, 7064.4);
+ new ShapeRef(router, polygon, 32);
+
+ // shapeRef33
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(591, 7394.4);
+ polygon.ps[1] = Point(591, 7456.4);
+ polygon.ps[2] = Point(529, 7456.4);
+ polygon.ps[3] = Point(529, 7394.4);
+ new ShapeRef(router, polygon, 33);
+
+ // shapeRef34
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(591, 7713.79);
+ polygon.ps[1] = Point(591, 7775.79);
+ polygon.ps[2] = Point(529, 7775.79);
+ polygon.ps[3] = Point(529, 7713.79);
+ new ShapeRef(router, polygon, 34);
+
+ // shapeRef35
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(591, 6285.51);
+ polygon.ps[1] = Point(591, 6347.51);
+ polygon.ps[2] = Point(529, 6347.51);
+ polygon.ps[3] = Point(529, 6285.51);
+ new ShapeRef(router, polygon, 35);
+
+ // shapeRef36
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(591, 5659.9);
+ polygon.ps[1] = Point(591, 5721.9);
+ polygon.ps[2] = Point(529, 5721.9);
+ polygon.ps[3] = Point(529, 5659.9);
+ new ShapeRef(router, polygon, 36);
+
+ // shapeRef37
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(591, 5966.59);
+ polygon.ps[1] = Point(591, 6028.59);
+ polygon.ps[2] = Point(529, 6028.59);
+ polygon.ps[3] = Point(529, 5966.59);
+ new ShapeRef(router, polygon, 37);
+
+ // shapeRef38
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 5197.89);
+ polygon.ps[1] = Point(8789.03, 5237.89);
+ polygon.ps[2] = Point(8734.03, 5237.89);
+ polygon.ps[3] = Point(8734.03, 5197.89);
+ new ShapeRef(router, polygon, 38);
+
+ // shapeRef39
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 5197.89);
+ polygon.ps[1] = Point(8889.03, 5237.89);
+ polygon.ps[2] = Point(8834.03, 5237.89);
+ polygon.ps[3] = Point(8834.03, 5197.89);
+ new ShapeRef(router, polygon, 39);
+
+ // shapeRef40
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 5197.89);
+ polygon.ps[1] = Point(8989.03, 5237.89);
+ polygon.ps[2] = Point(8934.03, 5237.89);
+ polygon.ps[3] = Point(8934.03, 5197.89);
+ new ShapeRef(router, polygon, 40);
+
+ // shapeRef41
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 5197.89);
+ polygon.ps[1] = Point(9089.03, 5237.89);
+ polygon.ps[2] = Point(9034.03, 5237.89);
+ polygon.ps[3] = Point(9034.03, 5197.89);
+ new ShapeRef(router, polygon, 41);
+
+ // shapeRef42
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(855, 7097.4);
+ polygon.ps[1] = Point(855, 7159.4);
+ polygon.ps[2] = Point(793, 7159.4);
+ polygon.ps[3] = Point(793, 7097.4);
+ new ShapeRef(router, polygon, 42);
+
+ // shapeRef43
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5178, 1150.29);
+ polygon.ps[1] = Point(5178, 1212.29);
+ polygon.ps[2] = Point(5116, 1212.29);
+ polygon.ps[3] = Point(5116, 1150.29);
+ new ShapeRef(router, polygon, 43);
+
+ // shapeRef44
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4716, 1051.29);
+ polygon.ps[1] = Point(4716, 1113.29);
+ polygon.ps[2] = Point(4654, 1113.29);
+ polygon.ps[3] = Point(4654, 1051.29);
+ new ShapeRef(router, polygon, 44);
+
+ // shapeRef45
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4419, 1645.29);
+ polygon.ps[1] = Point(4419, 1707.29);
+ polygon.ps[2] = Point(4357, 1707.29);
+ polygon.ps[3] = Point(4357, 1645.29);
+ new ShapeRef(router, polygon, 45);
+
+ // shapeRef46
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4716, 1645.29);
+ polygon.ps[1] = Point(4716, 1707.29);
+ polygon.ps[2] = Point(4654, 1707.29);
+ polygon.ps[3] = Point(4654, 1645.29);
+ new ShapeRef(router, polygon, 46);
+
+ // shapeRef47
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4419, 853.285);
+ polygon.ps[1] = Point(4419, 915.285);
+ polygon.ps[2] = Point(4357, 915.285);
+ polygon.ps[3] = Point(4357, 853.285);
+ new ShapeRef(router, polygon, 47);
+
+ // shapeRef48
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4419, 1183.29);
+ polygon.ps[1] = Point(4419, 1245.29);
+ polygon.ps[2] = Point(4357, 1245.29);
+ polygon.ps[3] = Point(4357, 1183.29);
+ new ShapeRef(router, polygon, 48);
+
+ // shapeRef49
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4716, 1183.29);
+ polygon.ps[1] = Point(4716, 1245.29);
+ polygon.ps[2] = Point(4654, 1245.29);
+ polygon.ps[3] = Point(4654, 1183.29);
+ new ShapeRef(router, polygon, 49);
+
+ // shapeRef50
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4716, 1381.29);
+ polygon.ps[1] = Point(4716, 1443.29);
+ polygon.ps[2] = Point(4654, 1443.29);
+ polygon.ps[3] = Point(4654, 1381.29);
+ new ShapeRef(router, polygon, 50);
+
+ // shapeRef51
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4419, 1381.29);
+ polygon.ps[1] = Point(4419, 1443.29);
+ polygon.ps[2] = Point(4357, 1443.29);
+ polygon.ps[3] = Point(4357, 1381.29);
+ new ShapeRef(router, polygon, 51);
+
+ // shapeRef52
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6385.1, 744.091);
+ polygon.ps[1] = Point(6385.1, 806.091);
+ polygon.ps[2] = Point(6323.1, 806.091);
+ polygon.ps[3] = Point(6323.1, 744.091);
+ new ShapeRef(router, polygon, 52);
+
+ // shapeRef53
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6715.1, 744.091);
+ polygon.ps[1] = Point(6715.1, 806.091);
+ polygon.ps[2] = Point(6653.1, 806.091);
+ polygon.ps[3] = Point(6653.1, 744.091);
+ new ShapeRef(router, polygon, 53);
+
+ // shapeRef54
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6715.1, 1117.29);
+ polygon.ps[1] = Point(6715.1, 1179.29);
+ polygon.ps[2] = Point(6653.1, 1179.29);
+ polygon.ps[3] = Point(6653.1, 1117.29);
+ new ShapeRef(router, polygon, 54);
+
+ // shapeRef55
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6715.1, 1414.29);
+ polygon.ps[1] = Point(6715.1, 1476.29);
+ polygon.ps[2] = Point(6653.1, 1476.29);
+ polygon.ps[3] = Point(6653.1, 1414.29);
+ new ShapeRef(router, polygon, 55);
+
+ // shapeRef56
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6418.1, 1414.29);
+ polygon.ps[1] = Point(6418.1, 1476.29);
+ polygon.ps[2] = Point(6356.1, 1476.29);
+ polygon.ps[3] = Point(6356.1, 1414.29);
+ new ShapeRef(router, polygon, 56);
+
+ // shapeRef57
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5046, 1480.29);
+ polygon.ps[1] = Point(5046, 1542.29);
+ polygon.ps[2] = Point(4984, 1542.29);
+ polygon.ps[3] = Point(4984, 1480.29);
+ new ShapeRef(router, polygon, 57);
+
+ // shapeRef58
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6715.1, 1645.29);
+ polygon.ps[1] = Point(6715.1, 1707.29);
+ polygon.ps[2] = Point(6653.1, 1707.29);
+ polygon.ps[3] = Point(6653.1, 1645.29);
+ new ShapeRef(router, polygon, 58);
+
+ // shapeRef59
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5310, 1645.29);
+ polygon.ps[1] = Point(5310, 1707.29);
+ polygon.ps[2] = Point(5248, 1707.29);
+ polygon.ps[3] = Point(5248, 1645.29);
+ new ShapeRef(router, polygon, 59);
+
+ // shapeRef60
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5758.1, 1645.29);
+ polygon.ps[1] = Point(5758.1, 1707.29);
+ polygon.ps[2] = Point(5696.1, 1707.29);
+ polygon.ps[3] = Point(5696.1, 1645.29);
+ new ShapeRef(router, polygon, 60);
+
+ // shapeRef61
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6121.1, 1645.29);
+ polygon.ps[1] = Point(6121.1, 1707.29);
+ polygon.ps[2] = Point(6059.1, 1707.29);
+ polygon.ps[3] = Point(6059.1, 1645.29);
+ new ShapeRef(router, polygon, 61);
+
+ // shapeRef62
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6418.1, 1645.29);
+ polygon.ps[1] = Point(6418.1, 1707.29);
+ polygon.ps[2] = Point(6356.1, 1707.29);
+ polygon.ps[3] = Point(6356.1, 1645.29);
+ new ShapeRef(router, polygon, 62);
+
+ // shapeRef63
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5046, 1813.29);
+ polygon.ps[1] = Point(5046, 1875.29);
+ polygon.ps[2] = Point(4984, 1875.29);
+ polygon.ps[3] = Point(4984, 1813.29);
+ new ShapeRef(router, polygon, 63);
+
+ // shapeRef64
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6715.1, 1813.29);
+ polygon.ps[1] = Point(6715.1, 1875.29);
+ polygon.ps[2] = Point(6653.1, 1875.29);
+ polygon.ps[3] = Point(6653.1, 1813.29);
+ new ShapeRef(router, polygon, 64);
+
+ // shapeRef65
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6418.1, 1813.29);
+ polygon.ps[1] = Point(6418.1, 1875.29);
+ polygon.ps[2] = Point(6356.1, 1875.29);
+ polygon.ps[3] = Point(6356.1, 1813.29);
+ new ShapeRef(router, polygon, 65);
+
+ // shapeRef66
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6121.1, 1813.29);
+ polygon.ps[1] = Point(6121.1, 1875.29);
+ polygon.ps[2] = Point(6059.1, 1875.29);
+ polygon.ps[3] = Point(6059.1, 1813.29);
+ new ShapeRef(router, polygon, 66);
+
+ // shapeRef67
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5758.1, 1813.29);
+ polygon.ps[1] = Point(5758.1, 1875.29);
+ polygon.ps[2] = Point(5696.1, 1875.29);
+ polygon.ps[3] = Point(5696.1, 1813.29);
+ new ShapeRef(router, polygon, 67);
+
+ // shapeRef68
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5310, 1813.29);
+ polygon.ps[1] = Point(5310, 1875.29);
+ polygon.ps[2] = Point(5248, 1875.29);
+ polygon.ps[3] = Point(5248, 1813.29);
+ new ShapeRef(router, polygon, 68);
+
+ // shapeRef69
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4650, 1813.29);
+ polygon.ps[1] = Point(4650, 1875.29);
+ polygon.ps[2] = Point(4588, 1875.29);
+ polygon.ps[3] = Point(4588, 1813.29);
+ new ShapeRef(router, polygon, 69);
+
+ // shapeRef70
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5923.1, 1150.29);
+ polygon.ps[1] = Point(5923.1, 1212.29);
+ polygon.ps[2] = Point(5861.1, 1212.29);
+ polygon.ps[3] = Point(5861.1, 1150.29);
+ new ShapeRef(router, polygon, 70);
+
+ // shapeRef71
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5626.1, 1150.29);
+ polygon.ps[1] = Point(5626.1, 1212.29);
+ polygon.ps[2] = Point(5564.1, 1212.29);
+ polygon.ps[3] = Point(5564.1, 1150.29);
+ new ShapeRef(router, polygon, 71);
+
+ // shapeRef72
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5923.1, 919.285);
+ polygon.ps[1] = Point(5923.1, 981.285);
+ polygon.ps[2] = Point(5861.1, 981.285);
+ polygon.ps[3] = Point(5861.1, 919.285);
+ new ShapeRef(router, polygon, 72);
+
+ // shapeRef73
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5626.1, 919.285);
+ polygon.ps[1] = Point(5626.1, 981.285);
+ polygon.ps[2] = Point(5564.1, 981.285);
+ polygon.ps[3] = Point(5564.1, 919.285);
+ new ShapeRef(router, polygon, 73);
+
+ // shapeRef74
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5626.1, 678.091);
+ polygon.ps[1] = Point(5626.1, 740.091);
+ polygon.ps[2] = Point(5564.1, 740.091);
+ polygon.ps[3] = Point(5564.1, 678.091);
+ new ShapeRef(router, polygon, 74);
+
+ // shapeRef75
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4914, 678.091);
+ polygon.ps[1] = Point(4914, 740.091);
+ polygon.ps[2] = Point(4852, 740.091);
+ polygon.ps[3] = Point(4852, 678.091);
+ new ShapeRef(router, polygon, 75);
+
+ // shapeRef76
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5923.1, 678.091);
+ polygon.ps[1] = Point(5923.1, 740.091);
+ polygon.ps[2] = Point(5861.1, 740.091);
+ polygon.ps[3] = Point(5861.1, 678.091);
+ new ShapeRef(router, polygon, 76);
+
+ // shapeRef77
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5178, 678.091);
+ polygon.ps[1] = Point(5178, 740.091);
+ polygon.ps[2] = Point(5116, 740.091);
+ polygon.ps[3] = Point(5116, 678.091);
+ new ShapeRef(router, polygon, 77);
+
+ // shapeRef78
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5079, 513.091);
+ polygon.ps[1] = Point(5079, 575.091);
+ polygon.ps[2] = Point(5017, 575.091);
+ polygon.ps[3] = Point(5017, 513.091);
+ new ShapeRef(router, polygon, 78);
+
+ // shapeRef79
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4617, 513.091);
+ polygon.ps[1] = Point(4617, 575.091);
+ polygon.ps[2] = Point(4555, 575.091);
+ polygon.ps[3] = Point(4555, 513.091);
+ new ShapeRef(router, polygon, 79);
+
+ // shapeRef80
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4254, 513.091);
+ polygon.ps[1] = Point(4254, 575.091);
+ polygon.ps[2] = Point(4192, 575.091);
+ polygon.ps[3] = Point(4192, 513.091);
+ new ShapeRef(router, polygon, 80);
+
+ // shapeRef81
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3792, 513.091);
+ polygon.ps[1] = Point(3792, 575.091);
+ polygon.ps[2] = Point(3730, 575.091);
+ polygon.ps[3] = Point(3730, 513.091);
+ new ShapeRef(router, polygon, 81);
+
+ // shapeRef82
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4749, 328.265);
+ polygon.ps[1] = Point(4749, 390.265);
+ polygon.ps[2] = Point(4687, 390.265);
+ polygon.ps[3] = Point(4687, 328.265);
+ new ShapeRef(router, polygon, 82);
+
+ // shapeRef83
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3561, 249.265);
+ polygon.ps[1] = Point(3561, 311.265);
+ polygon.ps[2] = Point(3499, 311.265);
+ polygon.ps[3] = Point(3499, 249.265);
+ new ShapeRef(router, polygon, 83);
+
+ // shapeRef84
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3627, 361.265);
+ polygon.ps[1] = Point(3627, 423.265);
+ polygon.ps[2] = Point(3565, 423.265);
+ polygon.ps[3] = Point(3565, 361.265);
+ new ShapeRef(router, polygon, 84);
+
+ // shapeRef85
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3198, 361.265);
+ polygon.ps[1] = Point(3198, 423.265);
+ polygon.ps[2] = Point(3136, 423.265);
+ polygon.ps[3] = Point(3136, 361.265);
+ new ShapeRef(router, polygon, 85);
+
+ // shapeRef86
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2670, 328.265);
+ polygon.ps[1] = Point(2670, 390.265);
+ polygon.ps[2] = Point(2608, 390.265);
+ polygon.ps[3] = Point(2608, 328.265);
+ new ShapeRef(router, polygon, 86);
+
+ // shapeRef87
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2274, 513.091);
+ polygon.ps[1] = Point(2274, 575.091);
+ polygon.ps[2] = Point(2212, 575.091);
+ polygon.ps[3] = Point(2212, 513.091);
+ new ShapeRef(router, polygon, 87);
+
+ // shapeRef88
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2670, 513.091);
+ polygon.ps[1] = Point(2670, 575.091);
+ polygon.ps[2] = Point(2608, 575.091);
+ polygon.ps[3] = Point(2608, 513.091);
+ new ShapeRef(router, polygon, 88);
+
+ // shapeRef89
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2241, 678.091);
+ polygon.ps[1] = Point(2241, 740.091);
+ polygon.ps[2] = Point(2179, 740.091);
+ polygon.ps[3] = Point(2179, 678.091);
+ new ShapeRef(router, polygon, 89);
+
+ // shapeRef90
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3198, 678.091);
+ polygon.ps[1] = Point(3198, 740.091);
+ polygon.ps[2] = Point(3136, 740.091);
+ polygon.ps[3] = Point(3136, 678.091);
+ new ShapeRef(router, polygon, 90);
+
+ // shapeRef91
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3198, 513.091);
+ polygon.ps[1] = Point(3198, 575.091);
+ polygon.ps[2] = Point(3136, 575.091);
+ polygon.ps[3] = Point(3136, 513.091);
+ new ShapeRef(router, polygon, 91);
+
+ // shapeRef92
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1779, 678.091);
+ polygon.ps[1] = Point(1779, 740.091);
+ polygon.ps[2] = Point(1717, 740.091);
+ polygon.ps[3] = Point(1717, 678.091);
+ new ShapeRef(router, polygon, 92);
+
+ // shapeRef93
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2340, 1282.29);
+ polygon.ps[1] = Point(2340, 1344.29);
+ polygon.ps[2] = Point(2278, 1344.29);
+ polygon.ps[3] = Point(2278, 1282.29);
+ new ShapeRef(router, polygon, 93);
+
+ // shapeRef94
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1152, 1282.29);
+ polygon.ps[1] = Point(1152, 1344.29);
+ polygon.ps[2] = Point(1090, 1344.29);
+ polygon.ps[3] = Point(1090, 1282.29);
+ new ShapeRef(router, polygon, 94);
+
+ // shapeRef95
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1515, 1282.29);
+ polygon.ps[1] = Point(1515, 1344.29);
+ polygon.ps[2] = Point(1453, 1344.29);
+ polygon.ps[3] = Point(1453, 1282.29);
+ new ShapeRef(router, polygon, 95);
+
+ // shapeRef96
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(789, 1018.29);
+ polygon.ps[1] = Point(789, 1080.29);
+ polygon.ps[2] = Point(727, 1080.29);
+ polygon.ps[3] = Point(727, 1018.29);
+ new ShapeRef(router, polygon, 96);
+
+ // shapeRef97
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1152, 1018.29);
+ polygon.ps[1] = Point(1152, 1080.29);
+ polygon.ps[2] = Point(1090, 1080.29);
+ polygon.ps[3] = Point(1090, 1018.29);
+ new ShapeRef(router, polygon, 97);
+
+ // shapeRef98
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1878, 1018.29);
+ polygon.ps[1] = Point(1878, 1080.29);
+ polygon.ps[2] = Point(1816, 1080.29);
+ polygon.ps[3] = Point(1816, 1018.29);
+ new ShapeRef(router, polygon, 98);
+
+ // shapeRef99
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2340, 1018.29);
+ polygon.ps[1] = Point(2340, 1080.29);
+ polygon.ps[2] = Point(2278, 1080.29);
+ polygon.ps[3] = Point(2278, 1018.29);
+ new ShapeRef(router, polygon, 99);
+
+ // shapeRef100
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2703, 1018.29);
+ polygon.ps[1] = Point(2703, 1080.29);
+ polygon.ps[2] = Point(2641, 1080.29);
+ polygon.ps[3] = Point(2641, 1018.29);
+ new ShapeRef(router, polygon, 100);
+
+ // shapeRef101
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3660, 1018.29);
+ polygon.ps[1] = Point(3660, 1080.29);
+ polygon.ps[2] = Point(3598, 1080.29);
+ polygon.ps[3] = Point(3598, 1018.29);
+ new ShapeRef(router, polygon, 101);
+
+ // shapeRef102
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1515, 1018.29);
+ polygon.ps[1] = Point(1515, 1080.29);
+ polygon.ps[2] = Point(1453, 1080.29);
+ polygon.ps[3] = Point(1453, 1018.29);
+ new ShapeRef(router, polygon, 102);
+
+ // shapeRef103
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(492, 1018.29);
+ polygon.ps[1] = Point(492, 1080.29);
+ polygon.ps[2] = Point(430, 1080.29);
+ polygon.ps[3] = Point(430, 1018.29);
+ new ShapeRef(router, polygon, 103);
+
+ // shapeRef104
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4023, 1018.29);
+ polygon.ps[1] = Point(4023, 1080.29);
+ polygon.ps[2] = Point(3961, 1080.29);
+ polygon.ps[3] = Point(3961, 1018.29);
+ new ShapeRef(router, polygon, 104);
+
+ // shapeRef105
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(195, 1747.29);
+ polygon.ps[1] = Point(195, 1809.29);
+ polygon.ps[2] = Point(133, 1809.29);
+ polygon.ps[3] = Point(133, 1747.29);
+ new ShapeRef(router, polygon, 105);
+
+ // shapeRef106
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(195, 1480.29);
+ polygon.ps[1] = Point(195, 1542.29);
+ polygon.ps[2] = Point(133, 1542.29);
+ polygon.ps[3] = Point(133, 1480.29);
+ new ShapeRef(router, polygon, 106);
+
+ // shapeRef107
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(426, 1480.29);
+ polygon.ps[1] = Point(426, 1542.29);
+ polygon.ps[2] = Point(364, 1542.29);
+ polygon.ps[3] = Point(364, 1480.29);
+ new ShapeRef(router, polygon, 107);
+
+ // shapeRef108
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(690, 1480.29);
+ polygon.ps[1] = Point(690, 1542.29);
+ polygon.ps[2] = Point(628, 1542.29);
+ polygon.ps[3] = Point(628, 1480.29);
+ new ShapeRef(router, polygon, 108);
+
+ // shapeRef109
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1086, 1480.29);
+ polygon.ps[1] = Point(1086, 1542.29);
+ polygon.ps[2] = Point(1024, 1542.29);
+ polygon.ps[3] = Point(1024, 1480.29);
+ new ShapeRef(router, polygon, 109);
+
+ // shapeRef110
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1449, 1480.29);
+ polygon.ps[1] = Point(1449, 1542.29);
+ polygon.ps[2] = Point(1387, 1542.29);
+ polygon.ps[3] = Point(1387, 1480.29);
+ new ShapeRef(router, polygon, 110);
+
+ // shapeRef111
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1845, 1480.29);
+ polygon.ps[1] = Point(1845, 1542.29);
+ polygon.ps[2] = Point(1783, 1542.29);
+ polygon.ps[3] = Point(1783, 1480.29);
+ new ShapeRef(router, polygon, 111);
+
+ // shapeRef112
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2637, 1480.29);
+ polygon.ps[1] = Point(2637, 1542.29);
+ polygon.ps[2] = Point(2575, 1542.29);
+ polygon.ps[3] = Point(2575, 1480.29);
+ new ShapeRef(router, polygon, 112);
+
+ // shapeRef113
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3132, 1480.29);
+ polygon.ps[1] = Point(3132, 1542.29);
+ polygon.ps[2] = Point(3070, 1542.29);
+ polygon.ps[3] = Point(3070, 1480.29);
+ new ShapeRef(router, polygon, 113);
+
+ // shapeRef114
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3660, 1480.29);
+ polygon.ps[1] = Point(3660, 1542.29);
+ polygon.ps[2] = Point(3598, 1542.29);
+ polygon.ps[3] = Point(3598, 1480.29);
+ new ShapeRef(router, polygon, 114);
+
+ // shapeRef115
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4023, 1480.29);
+ polygon.ps[1] = Point(4023, 1542.29);
+ polygon.ps[2] = Point(3961, 1542.29);
+ polygon.ps[3] = Point(3961, 1480.29);
+ new ShapeRef(router, polygon, 115);
+
+ // shapeRef116
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2274, 1480.29);
+ polygon.ps[1] = Point(2274, 1542.29);
+ polygon.ps[2] = Point(2212, 1542.29);
+ polygon.ps[3] = Point(2212, 1480.29);
+ new ShapeRef(router, polygon, 116);
+
+ // shapeRef117
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1449, 1645.29);
+ polygon.ps[1] = Point(1449, 1707.29);
+ polygon.ps[2] = Point(1387, 1707.29);
+ polygon.ps[3] = Point(1387, 1645.29);
+ new ShapeRef(router, polygon, 117);
+
+ // shapeRef118
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1845, 1645.29);
+ polygon.ps[1] = Point(1845, 1707.29);
+ polygon.ps[2] = Point(1783, 1707.29);
+ polygon.ps[3] = Point(1783, 1645.29);
+ new ShapeRef(router, polygon, 118);
+
+ // shapeRef119
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2274, 1645.29);
+ polygon.ps[1] = Point(2274, 1707.29);
+ polygon.ps[2] = Point(2212, 1707.29);
+ polygon.ps[3] = Point(2212, 1645.29);
+ new ShapeRef(router, polygon, 119);
+
+ // shapeRef120
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1086, 1813.29);
+ polygon.ps[1] = Point(1086, 1875.29);
+ polygon.ps[2] = Point(1024, 1875.29);
+ polygon.ps[3] = Point(1024, 1813.29);
+ new ShapeRef(router, polygon, 120);
+
+ // shapeRef121
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1449, 1813.29);
+ polygon.ps[1] = Point(1449, 1875.29);
+ polygon.ps[2] = Point(1387, 1875.29);
+ polygon.ps[3] = Point(1387, 1813.29);
+ new ShapeRef(router, polygon, 121);
+
+ // shapeRef122
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1845, 1813.29);
+ polygon.ps[1] = Point(1845, 1875.29);
+ polygon.ps[2] = Point(1783, 1875.29);
+ polygon.ps[3] = Point(1783, 1813.29);
+ new ShapeRef(router, polygon, 122);
+
+ // shapeRef123
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2274, 1813.29);
+ polygon.ps[1] = Point(2274, 1875.29);
+ polygon.ps[2] = Point(2212, 1875.29);
+ polygon.ps[3] = Point(2212, 1813.29);
+ new ShapeRef(router, polygon, 123);
+
+ // shapeRef124
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2637, 1813.29);
+ polygon.ps[1] = Point(2637, 1875.29);
+ polygon.ps[2] = Point(2575, 1875.29);
+ polygon.ps[3] = Point(2575, 1813.29);
+ new ShapeRef(router, polygon, 124);
+
+ // shapeRef125
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3132, 1813.29);
+ polygon.ps[1] = Point(3132, 1875.29);
+ polygon.ps[2] = Point(3070, 1875.29);
+ polygon.ps[3] = Point(3070, 1813.29);
+ new ShapeRef(router, polygon, 125);
+
+ // shapeRef126
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3660, 1813.29);
+ polygon.ps[1] = Point(3660, 1875.29);
+ polygon.ps[2] = Point(3598, 1875.29);
+ polygon.ps[3] = Point(3598, 1813.29);
+ new ShapeRef(router, polygon, 126);
+
+ // shapeRef127
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4023, 1813.29);
+ polygon.ps[1] = Point(4023, 1875.29);
+ polygon.ps[2] = Point(3961, 1875.29);
+ polygon.ps[3] = Point(3961, 1813.29);
+ new ShapeRef(router, polygon, 127);
+
+ // shapeRef128
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4353, 1813.29);
+ polygon.ps[1] = Point(4353, 1875.29);
+ polygon.ps[2] = Point(4291, 1875.29);
+ polygon.ps[3] = Point(4291, 1813.29);
+ new ShapeRef(router, polygon, 128);
+
+ // shapeRef129
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(360, 1813.29);
+ polygon.ps[1] = Point(360, 1875.29);
+ polygon.ps[2] = Point(298, 1875.29);
+ polygon.ps[3] = Point(298, 1813.29);
+ new ShapeRef(router, polygon, 129);
+
+ // shapeRef130
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(360, 2317.29);
+ polygon.ps[1] = Point(360, 2379.29);
+ polygon.ps[2] = Point(298, 2379.29);
+ polygon.ps[3] = Point(298, 2317.29);
+ new ShapeRef(router, polygon, 130);
+
+ // shapeRef131
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(624, 2317.29);
+ polygon.ps[1] = Point(624, 2379.29);
+ polygon.ps[2] = Point(562, 2379.29);
+ polygon.ps[3] = Point(562, 2317.29);
+ new ShapeRef(router, polygon, 131);
+
+ // shapeRef132
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1086, 2317.29);
+ polygon.ps[1] = Point(1086, 2379.29);
+ polygon.ps[2] = Point(1024, 2379.29);
+ polygon.ps[3] = Point(1024, 2317.29);
+ new ShapeRef(router, polygon, 132);
+
+ // shapeRef133
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1845, 2317.29);
+ polygon.ps[1] = Point(1845, 2379.29);
+ polygon.ps[2] = Point(1783, 2379.29);
+ polygon.ps[3] = Point(1783, 2317.29);
+ new ShapeRef(router, polygon, 133);
+
+ // shapeRef134
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(162, 2581.29);
+ polygon.ps[1] = Point(162, 2643.29);
+ polygon.ps[2] = Point(100, 2643.29);
+ polygon.ps[3] = Point(100, 2581.29);
+ new ShapeRef(router, polygon, 134);
+
+ // shapeRef135
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(162, 2383.29);
+ polygon.ps[1] = Point(162, 2445.29);
+ polygon.ps[2] = Point(100, 2445.29);
+ polygon.ps[3] = Point(100, 2383.29);
+ new ShapeRef(router, polygon, 135);
+
+ // shapeRef136
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(162, 2119.29);
+ polygon.ps[1] = Point(162, 2181.29);
+ polygon.ps[2] = Point(100, 2181.29);
+ polygon.ps[3] = Point(100, 2119.29);
+ new ShapeRef(router, polygon, 136);
+
+ // shapeRef137
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(624, 2119.29);
+ polygon.ps[1] = Point(624, 2181.29);
+ polygon.ps[2] = Point(562, 2181.29);
+ polygon.ps[3] = Point(562, 2119.29);
+ new ShapeRef(router, polygon, 137);
+
+ // shapeRef138
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1845, 2119.29);
+ polygon.ps[1] = Point(1845, 2181.29);
+ polygon.ps[2] = Point(1783, 2181.29);
+ polygon.ps[3] = Point(1783, 2119.29);
+ new ShapeRef(router, polygon, 138);
+
+ // shapeRef139
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1086, 2119.29);
+ polygon.ps[1] = Point(1086, 2181.29);
+ polygon.ps[2] = Point(1024, 2181.29);
+ polygon.ps[3] = Point(1024, 2119.29);
+ new ShapeRef(router, polygon, 139);
+
+ // shapeRef140
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2274, 2119.29);
+ polygon.ps[1] = Point(2274, 2181.29);
+ polygon.ps[2] = Point(2212, 2181.29);
+ polygon.ps[3] = Point(2212, 2119.29);
+ new ShapeRef(router, polygon, 140);
+
+ // shapeRef141
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2637, 2119.29);
+ polygon.ps[1] = Point(2637, 2181.29);
+ polygon.ps[2] = Point(2575, 2181.29);
+ polygon.ps[3] = Point(2575, 2119.29);
+ new ShapeRef(router, polygon, 141);
+
+ // shapeRef142
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3132, 2119.29);
+ polygon.ps[1] = Point(3132, 2181.29);
+ polygon.ps[2] = Point(3070, 2181.29);
+ polygon.ps[3] = Point(3070, 2119.29);
+ new ShapeRef(router, polygon, 142);
+
+ // shapeRef143
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4023, 2119.29);
+ polygon.ps[1] = Point(4023, 2181.29);
+ polygon.ps[2] = Point(3961, 2181.29);
+ polygon.ps[3] = Point(3961, 2119.29);
+ new ShapeRef(router, polygon, 143);
+
+ // shapeRef144
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3660, 2119.29);
+ polygon.ps[1] = Point(3660, 2181.29);
+ polygon.ps[2] = Point(3598, 2181.29);
+ polygon.ps[3] = Point(3598, 2119.29);
+ new ShapeRef(router, polygon, 144);
+
+ // shapeRef145
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5923.1, 1348.29);
+ polygon.ps[1] = Point(5923.1, 1410.29);
+ polygon.ps[2] = Point(5861.1, 1410.29);
+ polygon.ps[3] = Point(5861.1, 1348.29);
+ new ShapeRef(router, polygon, 145);
+
+ // shapeRef146
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6616.1, 1150.29);
+ polygon.ps[1] = Point(6616.1, 1212.29);
+ polygon.ps[2] = Point(6554.1, 1212.29);
+ polygon.ps[3] = Point(6554.1, 1150.29);
+ new ShapeRef(router, polygon, 146);
+
+ // shapeRef147
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6220.1, 1150.29);
+ polygon.ps[1] = Point(6220.1, 1212.29);
+ polygon.ps[2] = Point(6158.1, 1212.29);
+ polygon.ps[3] = Point(6158.1, 1150.29);
+ new ShapeRef(router, polygon, 147);
+
+ // shapeRef148
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5593.1, 513.091);
+ polygon.ps[1] = Point(5593.1, 575.091);
+ polygon.ps[2] = Point(5531.1, 575.091);
+ polygon.ps[3] = Point(5531.1, 513.091);
+ new ShapeRef(router, polygon, 148);
+
+ // shapeRef149
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4254, 328.265);
+ polygon.ps[1] = Point(4254, 390.265);
+ polygon.ps[2] = Point(4192, 390.265);
+ polygon.ps[3] = Point(4192, 328.265);
+ new ShapeRef(router, polygon, 149);
+
+ // shapeRef150
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(525, 678.091);
+ polygon.ps[1] = Point(525, 740.091);
+ polygon.ps[2] = Point(463, 740.091);
+ polygon.ps[3] = Point(463, 678.091);
+ new ShapeRef(router, polygon, 150);
+
+ // shapeRef151
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3198, 1018.29);
+ polygon.ps[1] = Point(3198, 1080.29);
+ polygon.ps[2] = Point(3136, 1080.29);
+ polygon.ps[3] = Point(3136, 1018.29);
+ new ShapeRef(router, polygon, 151);
+
+ // shapeRef152
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8986.36, 6197.89);
+ polygon.ps[1] = Point(8986.36, 6237.89);
+ polygon.ps[2] = Point(8931.36, 6237.89);
+ polygon.ps[3] = Point(8931.36, 6197.89);
+ new ShapeRef(router, polygon, 152);
+
+ // shapeRef153
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9063.36, 6197.89);
+ polygon.ps[1] = Point(9063.36, 6237.89);
+ polygon.ps[2] = Point(9008.36, 6237.89);
+ polygon.ps[3] = Point(9008.36, 6197.89);
+ new ShapeRef(router, polygon, 153);
+
+ // shapeRef154
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 6197.89);
+ polygon.ps[1] = Point(9389.03, 6237.89);
+ polygon.ps[2] = Point(9334.03, 6237.89);
+ polygon.ps[3] = Point(9334.03, 6197.89);
+ new ShapeRef(router, polygon, 154);
+
+ // shapeRef155
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 6297.89);
+ polygon.ps[1] = Point(8389.03, 6337.89);
+ polygon.ps[2] = Point(8334.03, 6337.89);
+ polygon.ps[3] = Point(8334.03, 6297.89);
+ new ShapeRef(router, polygon, 155);
+
+ // shapeRef156
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 6297.89);
+ polygon.ps[1] = Point(8589.03, 6337.89);
+ polygon.ps[2] = Point(8534.03, 6337.89);
+ polygon.ps[3] = Point(8534.03, 6297.89);
+ new ShapeRef(router, polygon, 156);
+
+ // shapeRef157
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 6297.89);
+ polygon.ps[1] = Point(8689.03, 6337.89);
+ polygon.ps[2] = Point(8634.03, 6337.89);
+ polygon.ps[3] = Point(8634.03, 6297.89);
+ new ShapeRef(router, polygon, 157);
+
+ // shapeRef158
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 6297.89);
+ polygon.ps[1] = Point(8789.03, 6337.89);
+ polygon.ps[2] = Point(8734.03, 6337.89);
+ polygon.ps[3] = Point(8734.03, 6297.89);
+ new ShapeRef(router, polygon, 158);
+
+ // shapeRef159
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 6297.89);
+ polygon.ps[1] = Point(8889.03, 6337.89);
+ polygon.ps[2] = Point(8834.03, 6337.89);
+ polygon.ps[3] = Point(8834.03, 6297.89);
+ new ShapeRef(router, polygon, 159);
+
+ // shapeRef160
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 6297.89);
+ polygon.ps[1] = Point(8989.03, 6337.89);
+ polygon.ps[2] = Point(8934.03, 6337.89);
+ polygon.ps[3] = Point(8934.03, 6297.89);
+ new ShapeRef(router, polygon, 160);
+
+ // shapeRef161
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 6297.89);
+ polygon.ps[1] = Point(9089.03, 6337.89);
+ polygon.ps[2] = Point(9034.03, 6337.89);
+ polygon.ps[3] = Point(9034.03, 6297.89);
+ new ShapeRef(router, polygon, 161);
+
+ // shapeRef162
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4881, 11796.9);
+ polygon.ps[1] = Point(4881, 11858.9);
+ polygon.ps[2] = Point(4819, 11858.9);
+ polygon.ps[3] = Point(4819, 11796.9);
+ new ShapeRef(router, polygon, 162);
+
+ // shapeRef163
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2538, 10275);
+ polygon.ps[1] = Point(2538, 10337);
+ polygon.ps[2] = Point(2476, 10337);
+ polygon.ps[3] = Point(2476, 10275);
+ new ShapeRef(router, polygon, 163);
+
+ // shapeRef164
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3231, 10275);
+ polygon.ps[1] = Point(3231, 10337);
+ polygon.ps[2] = Point(3169, 10337);
+ polygon.ps[3] = Point(3169, 10275);
+ new ShapeRef(router, polygon, 164);
+
+ // shapeRef165
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3231, 10982.6);
+ polygon.ps[1] = Point(3231, 11044.6);
+ polygon.ps[2] = Point(3169, 11044.6);
+ polygon.ps[3] = Point(3169, 10982.6);
+ new ShapeRef(router, polygon, 165);
+
+ // shapeRef166
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11137.2, 2011.29);
+ polygon.ps[1] = Point(11137.2, 2073.29);
+ polygon.ps[2] = Point(11075.2, 2073.29);
+ polygon.ps[3] = Point(11075.2, 2011.29);
+ new ShapeRef(router, polygon, 166);
+
+ // shapeRef167
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11460.1, 2011.29);
+ polygon.ps[1] = Point(11460.1, 2073.29);
+ polygon.ps[2] = Point(11398.1, 2073.29);
+ polygon.ps[3] = Point(11398.1, 2011.29);
+ new ShapeRef(router, polygon, 167);
+
+ // shapeRef168
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 6397.89);
+ polygon.ps[1] = Point(8689.03, 6437.89);
+ polygon.ps[2] = Point(8634.03, 6437.89);
+ polygon.ps[3] = Point(8634.03, 6397.89);
+ new ShapeRef(router, polygon, 168);
+
+ // shapeRef169
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10939.2, 2011.29);
+ polygon.ps[1] = Point(10939.2, 2073.29);
+ polygon.ps[2] = Point(10877.2, 2073.29);
+ polygon.ps[3] = Point(10877.2, 2011.29);
+ new ShapeRef(router, polygon, 169);
+
+ // shapeRef170
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11460.1, 1711.29);
+ polygon.ps[1] = Point(11460.1, 1773.29);
+ polygon.ps[2] = Point(11398.1, 1773.29);
+ polygon.ps[3] = Point(11398.1, 1711.29);
+ new ShapeRef(router, polygon, 170);
+
+ // shapeRef171
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11856.1, 1711.29);
+ polygon.ps[1] = Point(11856.1, 1773.29);
+ polygon.ps[2] = Point(11794.1, 1773.29);
+ polygon.ps[3] = Point(11794.1, 1711.29);
+ new ShapeRef(router, polygon, 171);
+
+ // shapeRef172
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13705, 4808.4);
+ polygon.ps[1] = Point(13705, 4870.4);
+ polygon.ps[2] = Point(13643, 4870.4);
+ polygon.ps[3] = Point(13643, 4808.4);
+ new ShapeRef(router, polygon, 172);
+
+ // shapeRef173
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12986.5, 4808.4);
+ polygon.ps[1] = Point(12986.5, 4870.4);
+ polygon.ps[2] = Point(12924.5, 4870.4);
+ polygon.ps[3] = Point(12924.5, 4808.4);
+ new ShapeRef(router, polygon, 173);
+
+ // shapeRef174
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12986.5, 4330.11);
+ polygon.ps[1] = Point(12986.5, 4392.11);
+ polygon.ps[2] = Point(12924.5, 4392.11);
+ polygon.ps[3] = Point(12924.5, 4330.11);
+ new ShapeRef(router, polygon, 174);
+
+ // shapeRef175
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12986.5, 3996.51);
+ polygon.ps[1] = Point(12986.5, 4058.51);
+ polygon.ps[2] = Point(12924.5, 4058.51);
+ polygon.ps[3] = Point(12924.5, 3996.51);
+ new ShapeRef(router, polygon, 175);
+
+ // shapeRef176
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12986.5, 3732.51);
+ polygon.ps[1] = Point(12986.5, 3794.51);
+ polygon.ps[2] = Point(12924.5, 3794.51);
+ polygon.ps[3] = Point(12924.5, 3732.51);
+ new ShapeRef(router, polygon, 176);
+
+ // shapeRef177
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8422.29, 6497.89);
+ polygon.ps[1] = Point(8422.29, 6537.89);
+ polygon.ps[2] = Point(8367.29, 6537.89);
+ polygon.ps[3] = Point(8367.29, 6497.89);
+ new ShapeRef(router, polygon, 177);
+
+ // shapeRef178
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8499.29, 6497.89);
+ polygon.ps[1] = Point(8499.29, 6537.89);
+ polygon.ps[2] = Point(8444.29, 6537.89);
+ polygon.ps[3] = Point(8444.29, 6497.89);
+ new ShapeRef(router, polygon, 178);
+
+ // shapeRef179
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8576.29, 6497.89);
+ polygon.ps[1] = Point(8576.29, 6537.89);
+ polygon.ps[2] = Point(8521.29, 6537.89);
+ polygon.ps[3] = Point(8521.29, 6497.89);
+ new ShapeRef(router, polygon, 179);
+
+ // shapeRef180
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11203.2, 2548.29);
+ polygon.ps[1] = Point(11203.2, 2610.29);
+ polygon.ps[2] = Point(11141.2, 2610.29);
+ polygon.ps[3] = Point(11141.2, 2548.29);
+ new ShapeRef(router, polygon, 180);
+
+ // shapeRef181
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10906.2, 2548.29);
+ polygon.ps[1] = Point(10906.2, 2610.29);
+ polygon.ps[2] = Point(10844.2, 2610.29);
+ polygon.ps[3] = Point(10844.2, 2548.29);
+ new ShapeRef(router, polygon, 181);
+
+ // shapeRef182
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11203.2, 2911.29);
+ polygon.ps[1] = Point(11203.2, 2973.29);
+ polygon.ps[2] = Point(11141.2, 2973.29);
+ polygon.ps[3] = Point(11141.2, 2911.29);
+ new ShapeRef(router, polygon, 182);
+
+ // shapeRef183
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10906.2, 2911.29);
+ polygon.ps[1] = Point(10906.2, 2973.29);
+ polygon.ps[2] = Point(10844.2, 2973.29);
+ polygon.ps[3] = Point(10844.2, 2911.29);
+ new ShapeRef(router, polygon, 183);
+
+ // shapeRef184
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10421.9, 2548.29);
+ polygon.ps[1] = Point(10421.9, 2610.29);
+ polygon.ps[2] = Point(10359.9, 2610.29);
+ polygon.ps[3] = Point(10359.9, 2548.29);
+ new ShapeRef(router, polygon, 184);
+
+ // shapeRef185
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10421.9, 2911.29);
+ polygon.ps[1] = Point(10421.9, 2973.29);
+ polygon.ps[2] = Point(10359.9, 2973.29);
+ polygon.ps[3] = Point(10359.9, 2911.29);
+ new ShapeRef(router, polygon, 185);
+
+ // shapeRef186
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10421.9, 3274.29);
+ polygon.ps[1] = Point(10421.9, 3336.29);
+ polygon.ps[2] = Point(10359.9, 3336.29);
+ polygon.ps[3] = Point(10359.9, 3274.29);
+ new ShapeRef(router, polygon, 186);
+
+ // shapeRef187
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10421.9, 3633.51);
+ polygon.ps[1] = Point(10421.9, 3695.51);
+ polygon.ps[2] = Point(10359.9, 3695.51);
+ polygon.ps[3] = Point(10359.9, 3633.51);
+ new ShapeRef(router, polygon, 187);
+
+ // shapeRef188
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9532.59, 3633.51);
+ polygon.ps[1] = Point(9532.59, 3695.51);
+ polygon.ps[2] = Point(9470.59, 3695.51);
+ polygon.ps[3] = Point(9470.59, 3633.51);
+ new ShapeRef(router, polygon, 188);
+
+ // shapeRef189
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9532.59, 3402.51);
+ polygon.ps[1] = Point(9532.59, 3464.51);
+ polygon.ps[2] = Point(9470.59, 3464.51);
+ polygon.ps[3] = Point(9470.59, 3402.51);
+ new ShapeRef(router, polygon, 189);
+
+ // shapeRef190
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9532.59, 3142.29);
+ polygon.ps[1] = Point(9532.59, 3204.29);
+ polygon.ps[2] = Point(9470.59, 3204.29);
+ polygon.ps[3] = Point(9470.59, 3142.29);
+ new ShapeRef(router, polygon, 190);
+
+ // shapeRef191
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9532.59, 2911.29);
+ polygon.ps[1] = Point(9532.59, 2973.29);
+ polygon.ps[2] = Point(9470.59, 2973.29);
+ polygon.ps[3] = Point(9470.59, 2911.29);
+ new ShapeRef(router, polygon, 191);
+
+ // shapeRef192
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9532.59, 2548.29);
+ polygon.ps[1] = Point(9532.59, 2610.29);
+ polygon.ps[2] = Point(9470.59, 2610.29);
+ polygon.ps[3] = Point(9470.59, 2548.29);
+ new ShapeRef(router, polygon, 192);
+
+ // shapeRef193
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9202.59, 2548.29);
+ polygon.ps[1] = Point(9202.59, 2610.29);
+ polygon.ps[2] = Point(9140.59, 2610.29);
+ polygon.ps[3] = Point(9140.59, 2548.29);
+ new ShapeRef(router, polygon, 193);
+
+ // shapeRef194
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9202.59, 2911.29);
+ polygon.ps[1] = Point(9202.59, 2973.29);
+ polygon.ps[2] = Point(9140.59, 2973.29);
+ polygon.ps[3] = Point(9140.59, 2911.29);
+ new ShapeRef(router, polygon, 194);
+
+ // shapeRef195
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9202.59, 3142.29);
+ polygon.ps[1] = Point(9202.59, 3204.29);
+ polygon.ps[2] = Point(9140.59, 3204.29);
+ polygon.ps[3] = Point(9140.59, 3142.29);
+ new ShapeRef(router, polygon, 195);
+
+ // shapeRef196
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9202.59, 3402.51);
+ polygon.ps[1] = Point(9202.59, 3464.51);
+ polygon.ps[2] = Point(9140.59, 3464.51);
+ polygon.ps[3] = Point(9140.59, 3402.51);
+ new ShapeRef(router, polygon, 196);
+
+ // shapeRef197
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9202.59, 3633.51);
+ polygon.ps[1] = Point(9202.59, 3695.51);
+ polygon.ps[2] = Point(9140.59, 3695.51);
+ polygon.ps[3] = Point(9140.59, 3633.51);
+ new ShapeRef(router, polygon, 197);
+
+ // shapeRef198
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9202.59, 3963.51);
+ polygon.ps[1] = Point(9202.59, 4025.51);
+ polygon.ps[2] = Point(9140.59, 4025.51);
+ polygon.ps[3] = Point(9140.59, 3963.51);
+ new ShapeRef(router, polygon, 198);
+
+ // shapeRef199
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3396, 2515.29);
+ polygon.ps[1] = Point(3396, 2577.29);
+ polygon.ps[2] = Point(3334, 2577.29);
+ polygon.ps[3] = Point(3334, 2515.29);
+ new ShapeRef(router, polygon, 199);
+
+ // shapeRef200
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2571, 3666.51);
+ polygon.ps[1] = Point(2571, 3728.51);
+ polygon.ps[2] = Point(2509, 3728.51);
+ polygon.ps[3] = Point(2509, 3666.51);
+ new ShapeRef(router, polygon, 200);
+
+ // shapeRef201
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3726, 2779.29);
+ polygon.ps[1] = Point(3726, 2841.29);
+ polygon.ps[2] = Point(3664, 2841.29);
+ polygon.ps[3] = Point(3664, 2779.29);
+ new ShapeRef(router, polygon, 201);
+
+ // shapeRef202
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7928.29, 952.285);
+ polygon.ps[1] = Point(7928.29, 1014.29);
+ polygon.ps[2] = Point(7866.29, 1014.29);
+ polygon.ps[3] = Point(7866.29, 952.285);
+ new ShapeRef(router, polygon, 202);
+
+ // shapeRef203
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4551, 3666.51);
+ polygon.ps[1] = Point(4551, 3728.51);
+ polygon.ps[2] = Point(4489, 3728.51);
+ polygon.ps[3] = Point(4489, 3666.51);
+ new ShapeRef(router, polygon, 203);
+
+ // shapeRef204
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3561, 4297.11);
+ polygon.ps[1] = Point(3561, 4359.11);
+ polygon.ps[2] = Point(3499, 4359.11);
+ polygon.ps[3] = Point(3499, 4297.11);
+ new ShapeRef(router, polygon, 204);
+
+ // shapeRef205
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3759, 3930.51);
+ polygon.ps[1] = Point(3759, 3992.51);
+ polygon.ps[2] = Point(3697, 3992.51);
+ polygon.ps[3] = Point(3697, 3930.51);
+ new ShapeRef(router, polygon, 205);
+
+ // shapeRef206
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4353, 2119.29);
+ polygon.ps[1] = Point(4353, 2181.29);
+ polygon.ps[2] = Point(4291, 2181.29);
+ polygon.ps[3] = Point(4291, 2119.29);
+ new ShapeRef(router, polygon, 206);
+
+ // shapeRef207
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3990, 3666.51);
+ polygon.ps[1] = Point(3990, 3728.51);
+ polygon.ps[2] = Point(3928, 3728.51);
+ polygon.ps[3] = Point(3928, 3666.51);
+ new ShapeRef(router, polygon, 207);
+
+ // shapeRef208
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3396, 3109.29);
+ polygon.ps[1] = Point(3396, 3171.29);
+ polygon.ps[2] = Point(3334, 3171.29);
+ polygon.ps[3] = Point(3334, 3109.29);
+ new ShapeRef(router, polygon, 208);
+
+ // shapeRef209
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 6697.89);
+ polygon.ps[1] = Point(9289.03, 6737.89);
+ polygon.ps[2] = Point(9234.03, 6737.89);
+ polygon.ps[3] = Point(9234.03, 6697.89);
+ new ShapeRef(router, polygon, 209);
+
+ // shapeRef210
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4815, 5481.67);
+ polygon.ps[1] = Point(4815, 5543.67);
+ polygon.ps[2] = Point(4753, 5543.67);
+ polygon.ps[3] = Point(4753, 5481.67);
+ new ShapeRef(router, polygon, 210);
+
+ // shapeRef211
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16328.6, 5072.4);
+ polygon.ps[1] = Point(16328.6, 5134.4);
+ polygon.ps[2] = Point(16266.6, 5134.4);
+ polygon.ps[3] = Point(16266.6, 5072.4);
+ new ShapeRef(router, polygon, 211);
+
+ // shapeRef212
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15932.6, 5072.4);
+ polygon.ps[1] = Point(15932.6, 5134.4);
+ polygon.ps[2] = Point(15870.6, 5134.4);
+ polygon.ps[3] = Point(15870.6, 5072.4);
+ new ShapeRef(router, polygon, 212);
+
+ // shapeRef213
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15438.5, 4676.4);
+ polygon.ps[1] = Point(15438.5, 4738.4);
+ polygon.ps[2] = Point(15376.5, 4738.4);
+ polygon.ps[3] = Point(15376.5, 4676.4);
+ new ShapeRef(router, polygon, 213);
+
+ // shapeRef214
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15438.5, 5448.67);
+ polygon.ps[1] = Point(15438.5, 5510.67);
+ polygon.ps[2] = Point(15376.5, 5510.67);
+ polygon.ps[3] = Point(15376.5, 5448.67);
+ new ShapeRef(router, polygon, 214);
+
+ // shapeRef215
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15438.5, 6186.51);
+ polygon.ps[1] = Point(15438.5, 6248.51);
+ polygon.ps[2] = Point(15376.5, 6248.51);
+ polygon.ps[3] = Point(15376.5, 6186.51);
+ new ShapeRef(router, polygon, 215);
+
+ // shapeRef216
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15438.5, 6549.51);
+ polygon.ps[1] = Point(15438.5, 6611.51);
+ polygon.ps[2] = Point(15376.5, 6611.51);
+ polygon.ps[3] = Point(15376.5, 6549.51);
+ new ShapeRef(router, polygon, 216);
+
+ // shapeRef217
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4650, 8908.22);
+ polygon.ps[1] = Point(4650, 8970.22);
+ polygon.ps[2] = Point(4588, 8970.22);
+ polygon.ps[3] = Point(4588, 8908.22);
+ new ShapeRef(router, polygon, 217);
+
+ // shapeRef218
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4287, 8677.22);
+ polygon.ps[1] = Point(4287, 8739.22);
+ polygon.ps[2] = Point(4225, 8739.22);
+ polygon.ps[3] = Point(4225, 8677.22);
+ new ShapeRef(router, polygon, 218);
+
+ // shapeRef219
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4287, 8383.99);
+ polygon.ps[1] = Point(4287, 8445.99);
+ polygon.ps[2] = Point(4225, 8445.99);
+ polygon.ps[3] = Point(4225, 8383.99);
+ new ShapeRef(router, polygon, 219);
+
+ // shapeRef220
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 6797.89);
+ polygon.ps[1] = Point(9289.03, 6837.89);
+ polygon.ps[2] = Point(9234.03, 6837.89);
+ polygon.ps[3] = Point(9234.03, 6797.89);
+ new ShapeRef(router, polygon, 220);
+
+ // shapeRef221
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 6797.89);
+ polygon.ps[1] = Point(9389.03, 6837.89);
+ polygon.ps[2] = Point(9334.03, 6837.89);
+ polygon.ps[3] = Point(9334.03, 6797.89);
+ new ShapeRef(router, polygon, 221);
+
+ // shapeRef222
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 6897.89);
+ polygon.ps[1] = Point(8389.03, 6937.89);
+ polygon.ps[2] = Point(8334.03, 6937.89);
+ polygon.ps[3] = Point(8334.03, 6897.89);
+ new ShapeRef(router, polygon, 222);
+
+ // shapeRef223
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4848, 8076.79);
+ polygon.ps[1] = Point(4848, 8138.79);
+ polygon.ps[2] = Point(4786, 8138.79);
+ polygon.ps[3] = Point(4786, 8076.79);
+ new ShapeRef(router, polygon, 223);
+
+ // shapeRef224
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4848, 7548.79);
+ polygon.ps[1] = Point(4848, 7610.79);
+ polygon.ps[2] = Point(4786, 7610.79);
+ polygon.ps[3] = Point(4786, 7548.79);
+ new ShapeRef(router, polygon, 224);
+
+ // shapeRef225
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3924, 6965.4);
+ polygon.ps[1] = Point(3924, 7027.4);
+ polygon.ps[2] = Point(3862, 7027.4);
+ polygon.ps[3] = Point(3862, 6965.4);
+ new ShapeRef(router, polygon, 225);
+
+ // shapeRef226
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4188, 6965.4);
+ polygon.ps[1] = Point(4188, 7027.4);
+ polygon.ps[2] = Point(4126, 7027.4);
+ polygon.ps[3] = Point(4126, 6965.4);
+ new ShapeRef(router, polygon, 226);
+
+ // shapeRef227
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4452, 6965.4);
+ polygon.ps[1] = Point(4452, 7027.4);
+ polygon.ps[2] = Point(4390, 7027.4);
+ polygon.ps[3] = Point(4390, 6965.4);
+ new ShapeRef(router, polygon, 227);
+
+ // shapeRef228
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2967, 6582.51);
+ polygon.ps[1] = Point(2967, 6644.51);
+ polygon.ps[2] = Point(2905, 6644.51);
+ polygon.ps[3] = Point(2905, 6582.51);
+ new ShapeRef(router, polygon, 228);
+
+ // shapeRef229
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3759, 7097.4);
+ polygon.ps[1] = Point(3759, 7159.4);
+ polygon.ps[2] = Point(3697, 7159.4);
+ polygon.ps[3] = Point(3697, 7097.4);
+ new ShapeRef(router, polygon, 229);
+
+ // shapeRef230
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3495, 7097.4);
+ polygon.ps[1] = Point(3495, 7159.4);
+ polygon.ps[2] = Point(3433, 7159.4);
+ polygon.ps[3] = Point(3433, 7097.4);
+ new ShapeRef(router, polygon, 230);
+
+ // shapeRef231
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 6897.89);
+ polygon.ps[1] = Point(9289.03, 6937.89);
+ polygon.ps[2] = Point(9234.03, 6937.89);
+ polygon.ps[3] = Point(9234.03, 6897.89);
+ new ShapeRef(router, polygon, 231);
+
+ // shapeRef232
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 6897.89);
+ polygon.ps[1] = Point(9389.03, 6937.89);
+ polygon.ps[2] = Point(9334.03, 6937.89);
+ polygon.ps[3] = Point(9334.03, 6897.89);
+ new ShapeRef(router, polygon, 232);
+
+ // shapeRef233
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 6997.89);
+ polygon.ps[1] = Point(8389.03, 7037.89);
+ polygon.ps[2] = Point(8334.03, 7037.89);
+ polygon.ps[3] = Point(8334.03, 6997.89);
+ new ShapeRef(router, polygon, 233);
+
+ // shapeRef234
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 6997.89);
+ polygon.ps[1] = Point(8489.03, 7037.89);
+ polygon.ps[2] = Point(8434.03, 7037.89);
+ polygon.ps[3] = Point(8434.03, 6997.89);
+ new ShapeRef(router, polygon, 234);
+
+ // shapeRef235
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5494.1, 8515.99);
+ polygon.ps[1] = Point(5494.1, 8577.99);
+ polygon.ps[2] = Point(5432.1, 8577.99);
+ polygon.ps[3] = Point(5432.1, 8515.99);
+ new ShapeRef(router, polygon, 235);
+
+ // shapeRef236
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5494.1, 8076.79);
+ polygon.ps[1] = Point(5494.1, 8138.79);
+ polygon.ps[2] = Point(5432.1, 8138.79);
+ polygon.ps[3] = Point(5432.1, 8076.79);
+ new ShapeRef(router, polygon, 236);
+
+ // shapeRef237
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5112, 8076.79);
+ polygon.ps[1] = Point(5112, 8138.79);
+ polygon.ps[2] = Point(5050, 8138.79);
+ polygon.ps[3] = Point(5050, 8076.79);
+ new ShapeRef(router, polygon, 237);
+
+ // shapeRef238
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5244, 6153.51);
+ polygon.ps[1] = Point(5244, 6215.51);
+ polygon.ps[2] = Point(5182, 6215.51);
+ polygon.ps[3] = Point(5182, 6153.51);
+ new ShapeRef(router, polygon, 238);
+
+ // shapeRef239
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5244, 8908.22);
+ polygon.ps[1] = Point(5244, 8970.22);
+ polygon.ps[2] = Point(5182, 8970.22);
+ polygon.ps[3] = Point(5182, 8908.22);
+ new ShapeRef(router, polygon, 239);
+
+ // shapeRef240
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5244, 8515.99);
+ polygon.ps[1] = Point(5244, 8577.99);
+ polygon.ps[2] = Point(5182, 8577.99);
+ polygon.ps[3] = Point(5182, 8515.99);
+ new ShapeRef(router, polygon, 240);
+
+ // shapeRef241
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5244, 8076.79);
+ polygon.ps[1] = Point(5244, 8138.79);
+ polygon.ps[2] = Point(5182, 8138.79);
+ polygon.ps[3] = Point(5182, 8076.79);
+ new ShapeRef(router, polygon, 241);
+
+ // shapeRef242
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5244, 7548.79);
+ polygon.ps[1] = Point(5244, 7610.79);
+ polygon.ps[2] = Point(5182, 7610.79);
+ polygon.ps[3] = Point(5182, 7548.79);
+ new ShapeRef(router, polygon, 242);
+
+ // shapeRef243
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 6997.89);
+ polygon.ps[1] = Point(9389.03, 7037.89);
+ polygon.ps[2] = Point(9334.03, 7037.89);
+ polygon.ps[3] = Point(9334.03, 6997.89);
+ new ShapeRef(router, polygon, 243);
+
+ // shapeRef244
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 7097.89);
+ polygon.ps[1] = Point(8389.03, 7137.89);
+ polygon.ps[2] = Point(8334.03, 7137.89);
+ polygon.ps[3] = Point(8334.03, 7097.89);
+ new ShapeRef(router, polygon, 244);
+
+ // shapeRef245
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 7097.89);
+ polygon.ps[1] = Point(8489.03, 7137.89);
+ polygon.ps[2] = Point(8434.03, 7137.89);
+ polygon.ps[3] = Point(8434.03, 7097.89);
+ new ShapeRef(router, polygon, 245);
+
+ // shapeRef246
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 7097.89);
+ polygon.ps[1] = Point(8589.03, 7137.89);
+ polygon.ps[2] = Point(8534.03, 7137.89);
+ polygon.ps[3] = Point(8534.03, 7097.89);
+ new ShapeRef(router, polygon, 246);
+
+ // shapeRef247
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 7097.89);
+ polygon.ps[1] = Point(8789.03, 7137.89);
+ polygon.ps[2] = Point(8734.03, 7137.89);
+ polygon.ps[3] = Point(8734.03, 7097.89);
+ new ShapeRef(router, polygon, 247);
+
+ // shapeRef248
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 7097.89);
+ polygon.ps[1] = Point(8889.03, 7137.89);
+ polygon.ps[2] = Point(8834.03, 7137.89);
+ polygon.ps[3] = Point(8834.03, 7097.89);
+ new ShapeRef(router, polygon, 248);
+
+ // shapeRef249
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2109, 7097.4);
+ polygon.ps[1] = Point(2109, 7159.4);
+ polygon.ps[2] = Point(2047, 7159.4);
+ polygon.ps[3] = Point(2047, 7097.4);
+ new ShapeRef(router, polygon, 249);
+
+ // shapeRef250
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2406, 6998.4);
+ polygon.ps[1] = Point(2406, 7060.4);
+ polygon.ps[2] = Point(2344, 7060.4);
+ polygon.ps[3] = Point(2344, 6998.4);
+ new ShapeRef(router, polygon, 250);
+
+ // shapeRef251
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1911, 6998.4);
+ polygon.ps[1] = Point(1911, 7060.4);
+ polygon.ps[2] = Point(1849, 7060.4);
+ polygon.ps[3] = Point(1849, 6998.4);
+ new ShapeRef(router, polygon, 251);
+
+ // shapeRef252
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 7097.89);
+ polygon.ps[1] = Point(9289.03, 7137.89);
+ polygon.ps[2] = Point(9234.03, 7137.89);
+ polygon.ps[3] = Point(9234.03, 7097.89);
+ new ShapeRef(router, polygon, 252);
+
+ // shapeRef253
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 7097.89);
+ polygon.ps[1] = Point(9389.03, 7137.89);
+ polygon.ps[2] = Point(9334.03, 7137.89);
+ polygon.ps[3] = Point(9334.03, 7097.89);
+ new ShapeRef(router, polygon, 253);
+
+ // shapeRef254
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2406, 7097.4);
+ polygon.ps[1] = Point(2406, 7159.4);
+ polygon.ps[2] = Point(2344, 7159.4);
+ polygon.ps[3] = Point(2344, 7097.4);
+ new ShapeRef(router, polygon, 254);
+
+ // shapeRef255
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1779, 7614.79);
+ polygon.ps[1] = Point(1779, 7676.79);
+ polygon.ps[2] = Point(1717, 7676.79);
+ polygon.ps[3] = Point(1717, 7614.79);
+ new ShapeRef(router, polygon, 255);
+
+ // shapeRef256
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1779, 7097.4);
+ polygon.ps[1] = Point(1779, 7159.4);
+ polygon.ps[2] = Point(1717, 7159.4);
+ polygon.ps[3] = Point(1717, 7097.4);
+ new ShapeRef(router, polygon, 256);
+
+ // shapeRef257
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1779, 8142.79);
+ polygon.ps[1] = Point(1779, 8204.79);
+ polygon.ps[2] = Point(1717, 8204.79);
+ polygon.ps[3] = Point(1717, 8142.79);
+ new ShapeRef(router, polygon, 257);
+
+ // shapeRef258
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1779, 6582.51);
+ polygon.ps[1] = Point(1779, 6644.51);
+ polygon.ps[2] = Point(1717, 6644.51);
+ polygon.ps[3] = Point(1717, 6582.51);
+ new ShapeRef(router, polygon, 258);
+
+ // shapeRef259
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2109, 8142.79);
+ polygon.ps[1] = Point(2109, 8204.79);
+ polygon.ps[2] = Point(2047, 8204.79);
+ polygon.ps[3] = Point(2047, 8142.79);
+ new ShapeRef(router, polygon, 259);
+
+ // shapeRef260
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2109, 7614.79);
+ polygon.ps[1] = Point(2109, 7676.79);
+ polygon.ps[2] = Point(2047, 7676.79);
+ polygon.ps[3] = Point(2047, 7614.79);
+ new ShapeRef(router, polygon, 260);
+
+ // shapeRef261
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2109, 8548.99);
+ polygon.ps[1] = Point(2109, 8610.99);
+ polygon.ps[2] = Point(2047, 8610.99);
+ polygon.ps[3] = Point(2047, 8548.99);
+ new ShapeRef(router, polygon, 261);
+
+ // shapeRef262
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2406, 8142.79);
+ polygon.ps[1] = Point(2406, 8204.79);
+ polygon.ps[2] = Point(2344, 8204.79);
+ polygon.ps[3] = Point(2344, 8142.79);
+ new ShapeRef(router, polygon, 262);
+
+ // shapeRef263
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2406, 7614.79);
+ polygon.ps[1] = Point(2406, 7676.79);
+ polygon.ps[2] = Point(2344, 7676.79);
+ polygon.ps[3] = Point(2344, 7614.79);
+ new ShapeRef(router, polygon, 263);
+
+ // shapeRef264
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2406, 8548.99);
+ polygon.ps[1] = Point(2406, 8610.99);
+ polygon.ps[2] = Point(2344, 8610.99);
+ polygon.ps[3] = Point(2344, 8548.99);
+ new ShapeRef(router, polygon, 264);
+
+ // shapeRef265
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2604, 8548.99);
+ polygon.ps[1] = Point(2604, 8610.99);
+ polygon.ps[2] = Point(2542, 8610.99);
+ polygon.ps[3] = Point(2542, 8548.99);
+ new ShapeRef(router, polygon, 265);
+
+ // shapeRef266
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2604, 8142.79);
+ polygon.ps[1] = Point(2604, 8204.79);
+ polygon.ps[2] = Point(2542, 8204.79);
+ polygon.ps[3] = Point(2542, 8142.79);
+ new ShapeRef(router, polygon, 266);
+
+ // shapeRef267
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2604, 9017.42);
+ polygon.ps[1] = Point(2604, 9079.42);
+ polygon.ps[2] = Point(2542, 9079.42);
+ polygon.ps[3] = Point(2542, 9017.42);
+ new ShapeRef(router, polygon, 267);
+
+ // shapeRef268
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2604, 7614.79);
+ polygon.ps[1] = Point(2604, 7676.79);
+ polygon.ps[2] = Point(2542, 7676.79);
+ polygon.ps[3] = Point(2542, 7614.79);
+ new ShapeRef(router, polygon, 268);
+
+ // shapeRef269
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4155, 5481.67);
+ polygon.ps[1] = Point(4155, 5543.67);
+ polygon.ps[2] = Point(4093, 5543.67);
+ polygon.ps[3] = Point(4093, 5481.67);
+ new ShapeRef(router, polygon, 269);
+
+ // shapeRef270
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 7297.89);
+ polygon.ps[1] = Point(8889.03, 7337.89);
+ polygon.ps[2] = Point(8834.03, 7337.89);
+ polygon.ps[3] = Point(8834.03, 7297.89);
+ new ShapeRef(router, polygon, 270);
+
+ // shapeRef271
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3825, 5481.67);
+ polygon.ps[1] = Point(3825, 5543.67);
+ polygon.ps[2] = Point(3763, 5543.67);
+ polygon.ps[3] = Point(3763, 5481.67);
+ new ShapeRef(router, polygon, 271);
+
+ // shapeRef272
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3462, 5481.67);
+ polygon.ps[1] = Point(3462, 5543.67);
+ polygon.ps[2] = Point(3400, 5543.67);
+ polygon.ps[3] = Point(3400, 5481.67);
+ new ShapeRef(router, polygon, 272);
+
+ // shapeRef273
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3033, 5481.67);
+ polygon.ps[1] = Point(3033, 5543.67);
+ polygon.ps[2] = Point(2971, 5543.67);
+ polygon.ps[3] = Point(2971, 5481.67);
+ new ShapeRef(router, polygon, 273);
+
+ // shapeRef274
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2538, 5481.67);
+ polygon.ps[1] = Point(2538, 5543.67);
+ polygon.ps[2] = Point(2476, 5543.67);
+ polygon.ps[3] = Point(2476, 5481.67);
+ new ShapeRef(router, polygon, 274);
+
+ // shapeRef275
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 7297.89);
+ polygon.ps[1] = Point(9389.03, 7337.89);
+ polygon.ps[2] = Point(9334.03, 7337.89);
+ polygon.ps[3] = Point(9334.03, 7297.89);
+ new ShapeRef(router, polygon, 275);
+
+ // shapeRef276
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(129, 5758.9);
+ polygon.ps[1] = Point(129, 5820.9);
+ polygon.ps[2] = Point(67, 5820.9);
+ polygon.ps[3] = Point(67, 5758.9);
+ new ShapeRef(router, polygon, 276);
+
+ // shapeRef277
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(129, 6318.51);
+ polygon.ps[1] = Point(129, 6380.51);
+ polygon.ps[2] = Point(67, 6380.51);
+ polygon.ps[3] = Point(67, 6318.51);
+ new ShapeRef(router, polygon, 277);
+
+ // shapeRef278
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(393, 7614.79);
+ polygon.ps[1] = Point(393, 7676.79);
+ polygon.ps[2] = Point(331, 7676.79);
+ polygon.ps[3] = Point(331, 7614.79);
+ new ShapeRef(router, polygon, 278);
+
+ // shapeRef279
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(393, 7163.4);
+ polygon.ps[1] = Point(393, 7225.4);
+ polygon.ps[2] = Point(331, 7225.4);
+ polygon.ps[3] = Point(331, 7163.4);
+ new ShapeRef(router, polygon, 279);
+
+ // shapeRef280
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(393, 6648.51);
+ polygon.ps[1] = Point(393, 6710.51);
+ polygon.ps[2] = Point(331, 6710.51);
+ polygon.ps[3] = Point(331, 6648.51);
+ new ShapeRef(router, polygon, 280);
+
+ // shapeRef281
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(393, 6318.51);
+ polygon.ps[1] = Point(393, 6380.51);
+ polygon.ps[2] = Point(331, 6380.51);
+ polygon.ps[3] = Point(331, 6318.51);
+ new ShapeRef(router, polygon, 281);
+
+ // shapeRef282
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(855, 7977.79);
+ polygon.ps[1] = Point(855, 8039.79);
+ polygon.ps[2] = Point(793, 8039.79);
+ polygon.ps[3] = Point(793, 7977.79);
+ new ShapeRef(router, polygon, 282);
+
+ // shapeRef283
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(855, 7581.79);
+ polygon.ps[1] = Point(855, 7643.79);
+ polygon.ps[2] = Point(793, 7643.79);
+ polygon.ps[3] = Point(793, 7581.79);
+ new ShapeRef(router, polygon, 283);
+
+ // shapeRef284
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(855, 6582.51);
+ polygon.ps[1] = Point(855, 6644.51);
+ polygon.ps[2] = Point(793, 6644.51);
+ polygon.ps[3] = Point(793, 6582.51);
+ new ShapeRef(router, polygon, 284);
+
+ // shapeRef285
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(855, 6219.51);
+ polygon.ps[1] = Point(855, 6281.51);
+ polygon.ps[2] = Point(793, 6281.51);
+ polygon.ps[3] = Point(793, 6219.51);
+ new ShapeRef(router, polygon, 285);
+
+ // shapeRef286
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(855, 5758.9);
+ polygon.ps[1] = Point(855, 5820.9);
+ polygon.ps[2] = Point(793, 5820.9);
+ polygon.ps[3] = Point(793, 5758.9);
+ new ShapeRef(router, polygon, 286);
+
+ // shapeRef287
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1086, 8515.99);
+ polygon.ps[1] = Point(1086, 8577.99);
+ polygon.ps[2] = Point(1024, 8577.99);
+ polygon.ps[3] = Point(1024, 8515.99);
+ new ShapeRef(router, polygon, 287);
+
+ // shapeRef288
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1086, 8142.79);
+ polygon.ps[1] = Point(1086, 8204.79);
+ polygon.ps[2] = Point(1024, 8204.79);
+ polygon.ps[3] = Point(1024, 8142.79);
+ new ShapeRef(router, polygon, 288);
+
+ // shapeRef289
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1086, 7680.79);
+ polygon.ps[1] = Point(1086, 7742.79);
+ polygon.ps[2] = Point(1024, 7742.79);
+ polygon.ps[3] = Point(1024, 7680.79);
+ new ShapeRef(router, polygon, 289);
+
+ // shapeRef290
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1086, 7229.4);
+ polygon.ps[1] = Point(1086, 7291.4);
+ polygon.ps[2] = Point(1024, 7291.4);
+ polygon.ps[3] = Point(1024, 7229.4);
+ new ShapeRef(router, polygon, 290);
+
+ // shapeRef291
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1086, 6790.21);
+ polygon.ps[1] = Point(1086, 6852.21);
+ polygon.ps[2] = Point(1024, 6852.21);
+ polygon.ps[3] = Point(1024, 6790.21);
+ new ShapeRef(router, polygon, 291);
+
+ // shapeRef292
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1086, 6384.51);
+ polygon.ps[1] = Point(1086, 6446.51);
+ polygon.ps[2] = Point(1024, 6446.51);
+ polygon.ps[3] = Point(1024, 6384.51);
+ new ShapeRef(router, polygon, 292);
+
+ // shapeRef293
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1086, 5966.59);
+ polygon.ps[1] = Point(1086, 6028.59);
+ polygon.ps[2] = Point(1024, 6028.59);
+ polygon.ps[3] = Point(1024, 5966.59);
+ new ShapeRef(router, polygon, 293);
+
+ // shapeRef294
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1416, 5481.67);
+ polygon.ps[1] = Point(1416, 5543.67);
+ polygon.ps[2] = Point(1354, 5543.67);
+ polygon.ps[3] = Point(1354, 5481.67);
+ new ShapeRef(router, polygon, 294);
+
+ // shapeRef295
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 7497.89);
+ polygon.ps[1] = Point(9189.03, 7537.89);
+ polygon.ps[2] = Point(9134.03, 7537.89);
+ polygon.ps[3] = Point(9134.03, 7497.89);
+ new ShapeRef(router, polygon, 295);
+
+ // shapeRef296
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 7497.89);
+ polygon.ps[1] = Point(9289.03, 7537.89);
+ polygon.ps[2] = Point(9234.03, 7537.89);
+ polygon.ps[3] = Point(9234.03, 7497.89);
+ new ShapeRef(router, polygon, 296);
+
+ // shapeRef297
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 7497.89);
+ polygon.ps[1] = Point(9389.03, 7537.89);
+ polygon.ps[2] = Point(9334.03, 7537.89);
+ polygon.ps[3] = Point(9334.03, 7497.89);
+ new ShapeRef(router, polygon, 297);
+
+ // shapeRef298
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 7597.89);
+ polygon.ps[1] = Point(8389.03, 7637.89);
+ polygon.ps[2] = Point(8334.03, 7637.89);
+ polygon.ps[3] = Point(8334.03, 7597.89);
+ new ShapeRef(router, polygon, 298);
+
+ // shapeRef299
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 7597.89);
+ polygon.ps[1] = Point(8489.03, 7637.89);
+ polygon.ps[2] = Point(8434.03, 7637.89);
+ polygon.ps[3] = Point(8434.03, 7597.89);
+ new ShapeRef(router, polygon, 299);
+
+ // shapeRef300
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 7597.89);
+ polygon.ps[1] = Point(8589.03, 7637.89);
+ polygon.ps[2] = Point(8534.03, 7637.89);
+ polygon.ps[3] = Point(8534.03, 7597.89);
+ new ShapeRef(router, polygon, 300);
+
+ // shapeRef301
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 7597.89);
+ polygon.ps[1] = Point(8689.03, 7637.89);
+ polygon.ps[2] = Point(8634.03, 7637.89);
+ polygon.ps[3] = Point(8634.03, 7597.89);
+ new ShapeRef(router, polygon, 301);
+
+ // shapeRef302
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 7597.89);
+ polygon.ps[1] = Point(8789.03, 7637.89);
+ polygon.ps[2] = Point(8734.03, 7637.89);
+ polygon.ps[3] = Point(8734.03, 7597.89);
+ new ShapeRef(router, polygon, 302);
+
+ // shapeRef303
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(954, 5039.4);
+ polygon.ps[1] = Point(954, 5101.4);
+ polygon.ps[2] = Point(892, 5101.4);
+ polygon.ps[3] = Point(892, 5039.4);
+ new ShapeRef(router, polygon, 303);
+
+ // shapeRef304
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1416, 5039.4);
+ polygon.ps[1] = Point(1416, 5101.4);
+ polygon.ps[2] = Point(1354, 5101.4);
+ polygon.ps[3] = Point(1354, 5039.4);
+ new ShapeRef(router, polygon, 304);
+
+ // shapeRef305
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(492, 5316.67);
+ polygon.ps[1] = Point(492, 5378.67);
+ polygon.ps[2] = Point(430, 5378.67);
+ polygon.ps[3] = Point(430, 5316.67);
+ new ShapeRef(router, polygon, 305);
+
+ // shapeRef306
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(492, 5217.67);
+ polygon.ps[1] = Point(492, 5279.67);
+ polygon.ps[2] = Point(430, 5279.67);
+ polygon.ps[3] = Point(430, 5217.67);
+ new ShapeRef(router, polygon, 306);
+
+ // shapeRef307
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(228, 5217.67);
+ polygon.ps[1] = Point(228, 5279.67);
+ polygon.ps[2] = Point(166, 5279.67);
+ polygon.ps[3] = Point(166, 5217.67);
+ new ShapeRef(router, polygon, 307);
+
+ // shapeRef308
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2472, 4742.4);
+ polygon.ps[1] = Point(2472, 4804.4);
+ polygon.ps[2] = Point(2410, 4804.4);
+ polygon.ps[3] = Point(2410, 4742.4);
+ new ShapeRef(router, polygon, 308);
+
+ // shapeRef309
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(492, 5039.4);
+ polygon.ps[1] = Point(492, 5101.4);
+ polygon.ps[2] = Point(430, 5101.4);
+ polygon.ps[3] = Point(430, 5039.4);
+ new ShapeRef(router, polygon, 309);
+
+ // shapeRef310
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2142, 4742.4);
+ polygon.ps[1] = Point(2142, 4804.4);
+ polygon.ps[2] = Point(2080, 4804.4);
+ polygon.ps[3] = Point(2080, 4742.4);
+ new ShapeRef(router, polygon, 310);
+
+ // shapeRef311
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1086, 4742.4);
+ polygon.ps[1] = Point(1086, 4804.4);
+ polygon.ps[2] = Point(1024, 4804.4);
+ polygon.ps[3] = Point(1024, 4742.4);
+ new ShapeRef(router, polygon, 311);
+
+ // shapeRef312
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(228, 4742.4);
+ polygon.ps[1] = Point(228, 4804.4);
+ polygon.ps[2] = Point(166, 4804.4);
+ polygon.ps[3] = Point(166, 4742.4);
+ new ShapeRef(router, polygon, 312);
+
+ // shapeRef313
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(756, 4742.4);
+ polygon.ps[1] = Point(756, 4804.4);
+ polygon.ps[2] = Point(694, 4804.4);
+ polygon.ps[3] = Point(694, 4742.4);
+ new ShapeRef(router, polygon, 313);
+
+ // shapeRef314
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2901, 5039.4);
+ polygon.ps[1] = Point(2901, 5101.4);
+ polygon.ps[2] = Point(2839, 5101.4);
+ polygon.ps[3] = Point(2839, 5039.4);
+ new ShapeRef(router, polygon, 314);
+
+ // shapeRef315
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1944, 5039.4);
+ polygon.ps[1] = Point(1944, 5101.4);
+ polygon.ps[2] = Point(1882, 5101.4);
+ polygon.ps[3] = Point(1882, 5039.4);
+ new ShapeRef(router, polygon, 315);
+
+ // shapeRef316
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 7697.89);
+ polygon.ps[1] = Point(9189.03, 7737.89);
+ polygon.ps[2] = Point(9134.03, 7737.89);
+ polygon.ps[3] = Point(9134.03, 7697.89);
+ new ShapeRef(router, polygon, 316);
+
+ // shapeRef317
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 7697.89);
+ polygon.ps[1] = Point(9289.03, 7737.89);
+ polygon.ps[2] = Point(9234.03, 7737.89);
+ polygon.ps[3] = Point(9234.03, 7697.89);
+ new ShapeRef(router, polygon, 317);
+
+ // shapeRef318
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 7697.89);
+ polygon.ps[1] = Point(9389.03, 7737.89);
+ polygon.ps[2] = Point(9334.03, 7737.89);
+ polygon.ps[3] = Point(9334.03, 7697.89);
+ new ShapeRef(router, polygon, 318);
+
+ // shapeRef319
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 7797.89);
+ polygon.ps[1] = Point(8389.03, 7837.89);
+ polygon.ps[2] = Point(8334.03, 7837.89);
+ polygon.ps[3] = Point(8334.03, 7797.89);
+ new ShapeRef(router, polygon, 319);
+
+ // shapeRef320
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 7797.89);
+ polygon.ps[1] = Point(8489.03, 7837.89);
+ polygon.ps[2] = Point(8434.03, 7837.89);
+ polygon.ps[3] = Point(8434.03, 7797.89);
+ new ShapeRef(router, polygon, 320);
+
+ // shapeRef321
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 7797.89);
+ polygon.ps[1] = Point(8589.03, 7837.89);
+ polygon.ps[2] = Point(8534.03, 7837.89);
+ polygon.ps[3] = Point(8534.03, 7797.89);
+ new ShapeRef(router, polygon, 321);
+
+ // shapeRef322
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 7797.89);
+ polygon.ps[1] = Point(8789.03, 7837.89);
+ polygon.ps[2] = Point(8734.03, 7837.89);
+ polygon.ps[3] = Point(8734.03, 7797.89);
+ new ShapeRef(router, polygon, 322);
+
+ // shapeRef323
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 7797.89);
+ polygon.ps[1] = Point(8889.03, 7837.89);
+ polygon.ps[2] = Point(8834.03, 7837.89);
+ polygon.ps[3] = Point(8834.03, 7797.89);
+ new ShapeRef(router, polygon, 323);
+
+ // shapeRef324
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 7797.89);
+ polygon.ps[1] = Point(9089.03, 7837.89);
+ polygon.ps[2] = Point(9034.03, 7837.89);
+ polygon.ps[3] = Point(9034.03, 7797.89);
+ new ShapeRef(router, polygon, 324);
+
+ // shapeRef325
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18366.5, 3534.51);
+ polygon.ps[1] = Point(18366.5, 3596.51);
+ polygon.ps[2] = Point(18304.5, 3596.51);
+ polygon.ps[3] = Point(18304.5, 3534.51);
+ new ShapeRef(router, polygon, 325);
+
+ // shapeRef326
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18580, 3534.51);
+ polygon.ps[1] = Point(18580, 3596.51);
+ polygon.ps[2] = Point(18518, 3596.51);
+ polygon.ps[3] = Point(18518, 3534.51);
+ new ShapeRef(router, polygon, 326);
+
+ // shapeRef327
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18580, 3307.29);
+ polygon.ps[1] = Point(18580, 3369.29);
+ polygon.ps[2] = Point(18518, 3369.29);
+ polygon.ps[3] = Point(18518, 3307.29);
+ new ShapeRef(router, polygon, 327);
+
+ // shapeRef328
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18797.5, 3307.29);
+ polygon.ps[1] = Point(18797.5, 3369.29);
+ polygon.ps[2] = Point(18735.5, 3369.29);
+ polygon.ps[3] = Point(18735.5, 3307.29);
+ new ShapeRef(router, polygon, 328);
+
+ // shapeRef329
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18797.5, 3534.51);
+ polygon.ps[1] = Point(18797.5, 3596.51);
+ polygon.ps[2] = Point(18735.5, 3596.51);
+ polygon.ps[3] = Point(18735.5, 3534.51);
+ new ShapeRef(router, polygon, 329);
+
+ // shapeRef330
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18797.5, 3798.51);
+ polygon.ps[1] = Point(18797.5, 3860.51);
+ polygon.ps[2] = Point(18735.5, 3860.51);
+ polygon.ps[3] = Point(18735.5, 3798.51);
+ new ShapeRef(router, polygon, 330);
+
+ // shapeRef331
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16031.6, 9248.42);
+ polygon.ps[1] = Point(16031.6, 9310.42);
+ polygon.ps[2] = Point(15969.6, 9310.42);
+ polygon.ps[3] = Point(15969.6, 9248.42);
+ new ShapeRef(router, polygon, 331);
+
+ // shapeRef332
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 7897.89);
+ polygon.ps[1] = Point(8889.03, 7937.89);
+ polygon.ps[2] = Point(8834.03, 7937.89);
+ polygon.ps[3] = Point(8834.03, 7897.89);
+ new ShapeRef(router, polygon, 332);
+
+ // shapeRef333
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7639.1, 3435.51);
+ polygon.ps[1] = Point(7639.1, 3497.51);
+ polygon.ps[2] = Point(7577.1, 3497.51);
+ polygon.ps[3] = Point(7577.1, 3435.51);
+ new ShapeRef(router, polygon, 333);
+
+ // shapeRef334
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7639.1, 2482.29);
+ polygon.ps[1] = Point(7639.1, 2544.29);
+ polygon.ps[2] = Point(7577.1, 2544.29);
+ polygon.ps[3] = Point(7577.1, 2482.29);
+ new ShapeRef(router, polygon, 334);
+
+ // shapeRef335
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7639.1, 1945.29);
+ polygon.ps[1] = Point(7639.1, 2007.29);
+ polygon.ps[2] = Point(7577.1, 2007.29);
+ polygon.ps[3] = Point(7577.1, 1945.29);
+ new ShapeRef(router, polygon, 335);
+
+ // shapeRef336
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 7897.89);
+ polygon.ps[1] = Point(9289.03, 7937.89);
+ polygon.ps[2] = Point(9234.03, 7937.89);
+ polygon.ps[3] = Point(9234.03, 7897.89);
+ new ShapeRef(router, polygon, 336);
+
+ // shapeRef337
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 7897.89);
+ polygon.ps[1] = Point(9389.03, 7937.89);
+ polygon.ps[2] = Point(9334.03, 7937.89);
+ polygon.ps[3] = Point(9334.03, 7897.89);
+ new ShapeRef(router, polygon, 337);
+
+ // shapeRef338
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6088.1, 8548.99);
+ polygon.ps[1] = Point(6088.1, 8610.99);
+ polygon.ps[2] = Point(6026.1, 8610.99);
+ polygon.ps[3] = Point(6026.1, 8548.99);
+ new ShapeRef(router, polygon, 338);
+
+ // shapeRef339
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6088.1, 8251.99);
+ polygon.ps[1] = Point(6088.1, 8313.99);
+ polygon.ps[2] = Point(6026.1, 8313.99);
+ polygon.ps[3] = Point(6026.1, 8251.99);
+ new ShapeRef(router, polygon, 339);
+
+ // shapeRef340
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5791.1, 8875.22);
+ polygon.ps[1] = Point(5791.1, 8937.22);
+ polygon.ps[2] = Point(5729.1, 8937.22);
+ polygon.ps[3] = Point(5729.1, 8875.22);
+ new ShapeRef(router, polygon, 340);
+
+ // shapeRef341
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5791.1, 8548.99);
+ polygon.ps[1] = Point(5791.1, 8610.99);
+ polygon.ps[2] = Point(5729.1, 8610.99);
+ polygon.ps[3] = Point(5729.1, 8548.99);
+ new ShapeRef(router, polygon, 341);
+
+ // shapeRef342
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5791.1, 8251.99);
+ polygon.ps[1] = Point(5791.1, 8313.99);
+ polygon.ps[2] = Point(5729.1, 8313.99);
+ polygon.ps[3] = Point(5729.1, 8251.99);
+ new ShapeRef(router, polygon, 342);
+
+ // shapeRef343
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5791.1, 7812.79);
+ polygon.ps[1] = Point(5791.1, 7874.79);
+ polygon.ps[2] = Point(5729.1, 7874.79);
+ polygon.ps[3] = Point(5729.1, 7812.79);
+ new ShapeRef(router, polygon, 343);
+
+ // shapeRef344
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 7997.89);
+ polygon.ps[1] = Point(8989.03, 8037.89);
+ polygon.ps[2] = Point(8934.03, 8037.89);
+ polygon.ps[3] = Point(8934.03, 7997.89);
+ new ShapeRef(router, polygon, 344);
+
+ // shapeRef345
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 7997.89);
+ polygon.ps[1] = Point(9089.03, 8037.89);
+ polygon.ps[2] = Point(9034.03, 8037.89);
+ polygon.ps[3] = Point(9034.03, 7997.89);
+ new ShapeRef(router, polygon, 345);
+
+ // shapeRef346
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 7997.89);
+ polygon.ps[1] = Point(9189.03, 8037.89);
+ polygon.ps[2] = Point(9134.03, 8037.89);
+ polygon.ps[3] = Point(9134.03, 7997.89);
+ new ShapeRef(router, polygon, 346);
+
+ // shapeRef347
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 7997.89);
+ polygon.ps[1] = Point(9289.03, 8037.89);
+ polygon.ps[2] = Point(9234.03, 8037.89);
+ polygon.ps[3] = Point(9234.03, 7997.89);
+ new ShapeRef(router, polygon, 347);
+
+ // shapeRef348
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1911, 10585.3);
+ polygon.ps[1] = Point(1911, 10647.3);
+ polygon.ps[2] = Point(1849, 10647.3);
+ polygon.ps[3] = Point(1849, 10585.3);
+ new ShapeRef(router, polygon, 348);
+
+ // shapeRef349
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1911, 10982.6);
+ polygon.ps[1] = Point(1911, 11044.6);
+ polygon.ps[2] = Point(1849, 11044.6);
+ polygon.ps[3] = Point(1849, 10982.6);
+ new ShapeRef(router, polygon, 349);
+
+ // shapeRef350
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18003.5, 8743.22);
+ polygon.ps[1] = Point(18003.5, 8805.22);
+ polygon.ps[2] = Point(17941.5, 8805.22);
+ polygon.ps[3] = Point(17941.5, 8743.22);
+ new ShapeRef(router, polygon, 350);
+
+ // shapeRef351
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17772.5, 8743.22);
+ polygon.ps[1] = Point(17772.5, 8805.22);
+ polygon.ps[2] = Point(17710.5, 8805.22);
+ polygon.ps[3] = Point(17710.5, 8743.22);
+ new ShapeRef(router, polygon, 351);
+
+ // shapeRef352
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1581, 183.265);
+ polygon.ps[1] = Point(1581, 245.265);
+ polygon.ps[2] = Point(1519, 245.265);
+ polygon.ps[3] = Point(1519, 183.265);
+ new ShapeRef(router, polygon, 352);
+
+ // shapeRef353
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4221, 11114.6);
+ polygon.ps[1] = Point(4221, 11176.6);
+ polygon.ps[2] = Point(4159, 11176.6);
+ polygon.ps[3] = Point(4159, 11114.6);
+ new ShapeRef(router, polygon, 353);
+
+ // shapeRef354
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3726, 11114.6);
+ polygon.ps[1] = Point(3726, 11176.6);
+ polygon.ps[2] = Point(3664, 11176.6);
+ polygon.ps[3] = Point(3664, 11114.6);
+ new ShapeRef(router, polygon, 354);
+
+ // shapeRef355
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 8097.89);
+ polygon.ps[1] = Point(8989.03, 8137.89);
+ polygon.ps[2] = Point(8934.03, 8137.89);
+ polygon.ps[3] = Point(8934.03, 8097.89);
+ new ShapeRef(router, polygon, 355);
+
+ // shapeRef356
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4584, 9083.42);
+ polygon.ps[1] = Point(4584, 9145.42);
+ polygon.ps[2] = Point(4522, 9145.42);
+ polygon.ps[3] = Point(4522, 9083.42);
+ new ShapeRef(router, polygon, 356);
+
+ // shapeRef357
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4584, 7361.4);
+ polygon.ps[1] = Point(4584, 7423.4);
+ polygon.ps[2] = Point(4522, 7423.4);
+ polygon.ps[3] = Point(4522, 7361.4);
+ new ShapeRef(router, polygon, 357);
+
+ // shapeRef358
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10013.7, 4874.4);
+ polygon.ps[1] = Point(10013.7, 4936.4);
+ polygon.ps[2] = Point(9951.69, 4936.4);
+ polygon.ps[3] = Point(9951.69, 4874.4);
+ new ShapeRef(router, polygon, 358);
+
+ // shapeRef359
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10013.7, 5283.67);
+ polygon.ps[1] = Point(10013.7, 5345.67);
+ polygon.ps[2] = Point(9951.69, 5345.67);
+ polygon.ps[3] = Point(9951.69, 5283.67);
+ new ShapeRef(router, polygon, 359);
+
+ // shapeRef360
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11988.1, 3996.51);
+ polygon.ps[1] = Point(11988.1, 4058.51);
+ polygon.ps[2] = Point(11926.1, 4058.51);
+ polygon.ps[3] = Point(11926.1, 3996.51);
+ new ShapeRef(router, polygon, 360);
+
+ // shapeRef361
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11658.1, 3765.51);
+ polygon.ps[1] = Point(11658.1, 3827.51);
+ polygon.ps[2] = Point(11596.1, 3827.51);
+ polygon.ps[3] = Point(11596.1, 3765.51);
+ new ShapeRef(router, polygon, 361);
+
+ // shapeRef362
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11658.1, 4128.51);
+ polygon.ps[1] = Point(11658.1, 4190.51);
+ polygon.ps[2] = Point(11596.1, 4190.51);
+ polygon.ps[3] = Point(11596.1, 4128.51);
+ new ShapeRef(router, polygon, 362);
+
+ // shapeRef363
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12219.1, 3732.51);
+ polygon.ps[1] = Point(12219.1, 3794.51);
+ polygon.ps[2] = Point(12157.1, 3794.51);
+ polygon.ps[3] = Point(12157.1, 3732.51);
+ new ShapeRef(router, polygon, 363);
+
+ // shapeRef364
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4584, 12129.3);
+ polygon.ps[1] = Point(4584, 12191.3);
+ polygon.ps[2] = Point(4522, 12191.3);
+ polygon.ps[3] = Point(4522, 12129.3);
+ new ShapeRef(router, polygon, 364);
+
+ // shapeRef365
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4584, 11147.6);
+ polygon.ps[1] = Point(4584, 11209.6);
+ polygon.ps[2] = Point(4522, 11209.6);
+ polygon.ps[3] = Point(4522, 11147.6);
+ new ShapeRef(router, polygon, 365);
+
+ // shapeRef366
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4584, 11796.9);
+ polygon.ps[1] = Point(4584, 11858.9);
+ polygon.ps[2] = Point(4522, 11858.9);
+ polygon.ps[3] = Point(4522, 11796.9);
+ new ShapeRef(router, polygon, 366);
+
+ // shapeRef367
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 8197.89);
+ polygon.ps[1] = Point(9089.03, 8237.89);
+ polygon.ps[2] = Point(9034.03, 8237.89);
+ polygon.ps[3] = Point(9034.03, 8197.89);
+ new ShapeRef(router, polygon, 367);
+
+ // shapeRef368
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 8424.22);
+ polygon.ps[1] = Point(9189.03, 8464.22);
+ polygon.ps[2] = Point(9134.03, 8464.22);
+ polygon.ps[3] = Point(9134.03, 8424.22);
+ new ShapeRef(router, polygon, 368);
+
+ // shapeRef369
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2967, 9017.42);
+ polygon.ps[1] = Point(2967, 9079.42);
+ polygon.ps[2] = Point(2905, 9079.42);
+ polygon.ps[3] = Point(2905, 9017.42);
+ new ShapeRef(router, polygon, 369);
+
+ // shapeRef370
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2967, 8548.99);
+ polygon.ps[1] = Point(2967, 8610.99);
+ polygon.ps[2] = Point(2905, 8610.99);
+ polygon.ps[3] = Point(2905, 8548.99);
+ new ShapeRef(router, polygon, 370);
+
+ // shapeRef371
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2967, 9380.42);
+ polygon.ps[1] = Point(2967, 9442.42);
+ polygon.ps[2] = Point(2905, 9442.42);
+ polygon.ps[3] = Point(2905, 9380.42);
+ new ShapeRef(router, polygon, 371);
+
+ // shapeRef372
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2967, 8142.79);
+ polygon.ps[1] = Point(2967, 8204.79);
+ polygon.ps[2] = Point(2905, 8204.79);
+ polygon.ps[3] = Point(2905, 8142.79);
+ new ShapeRef(router, polygon, 372);
+
+ // shapeRef373
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4056, 12195.3);
+ polygon.ps[1] = Point(4056, 12257.3);
+ polygon.ps[2] = Point(3994, 12257.3);
+ polygon.ps[3] = Point(3994, 12195.3);
+ new ShapeRef(router, polygon, 373);
+
+ // shapeRef374
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 8297.89);
+ polygon.ps[1] = Point(8689.03, 8337.89);
+ polygon.ps[2] = Point(8634.03, 8337.89);
+ polygon.ps[3] = Point(8634.03, 8297.89);
+ new ShapeRef(router, polygon, 374);
+
+ // shapeRef375
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1911, 12195.3);
+ polygon.ps[1] = Point(1911, 12257.3);
+ polygon.ps[2] = Point(1849, 12257.3);
+ polygon.ps[3] = Point(1849, 12195.3);
+ new ShapeRef(router, polygon, 375);
+
+ // shapeRef376
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12021.1, 10651.3);
+ polygon.ps[1] = Point(12021.1, 10713.3);
+ polygon.ps[2] = Point(11959.1, 10713.3);
+ polygon.ps[3] = Point(11959.1, 10651.3);
+ new ShapeRef(router, polygon, 376);
+
+ // shapeRef377
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12021.1, 11048.6);
+ polygon.ps[1] = Point(12021.1, 11110.6);
+ polygon.ps[2] = Point(11959.1, 11110.6);
+ polygon.ps[3] = Point(11959.1, 11048.6);
+ new ShapeRef(router, polygon, 377);
+
+ // shapeRef378
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11724.1, 1813.29);
+ polygon.ps[1] = Point(11724.1, 1875.29);
+ polygon.ps[2] = Point(11662.1, 1875.29);
+ polygon.ps[3] = Point(11662.1, 1813.29);
+ new ShapeRef(router, polygon, 378);
+
+ // shapeRef379
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11889.1, 9677.42);
+ polygon.ps[1] = Point(11889.1, 9739.42);
+ polygon.ps[2] = Point(11827.1, 9739.42);
+ polygon.ps[3] = Point(11827.1, 9677.42);
+ new ShapeRef(router, polygon, 379);
+
+ // shapeRef380
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11460.1, 9677.42);
+ polygon.ps[1] = Point(11460.1, 9739.42);
+ polygon.ps[2] = Point(11398.1, 9739.42);
+ polygon.ps[3] = Point(11398.1, 9677.42);
+ new ShapeRef(router, polygon, 380);
+
+ // shapeRef381
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12562.5, 9644.42);
+ polygon.ps[1] = Point(12562.5, 9706.42);
+ polygon.ps[2] = Point(12500.5, 9706.42);
+ polygon.ps[3] = Point(12500.5, 9644.42);
+ new ShapeRef(router, polygon, 381);
+
+ // shapeRef382
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12318.1, 9347.42);
+ polygon.ps[1] = Point(12318.1, 9409.42);
+ polygon.ps[2] = Point(12256.1, 9409.42);
+ polygon.ps[3] = Point(12256.1, 9347.42);
+ new ShapeRef(router, polygon, 382);
+
+ // shapeRef383
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12054.1, 7581.79);
+ polygon.ps[1] = Point(12054.1, 7643.79);
+ polygon.ps[2] = Point(11992.1, 7643.79);
+ polygon.ps[3] = Point(11992.1, 7581.79);
+ new ShapeRef(router, polygon, 383);
+
+ // shapeRef384
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(228, 8809.22);
+ polygon.ps[1] = Point(228, 8871.22);
+ polygon.ps[2] = Point(166, 8871.22);
+ polygon.ps[3] = Point(166, 8809.22);
+ new ShapeRef(router, polygon, 384);
+
+ // shapeRef385
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(228, 5316.67);
+ polygon.ps[1] = Point(228, 5378.67);
+ polygon.ps[2] = Point(166, 5378.67);
+ polygon.ps[3] = Point(166, 5316.67);
+ new ShapeRef(router, polygon, 385);
+
+ // shapeRef386
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(492, 5791.9);
+ polygon.ps[1] = Point(492, 5853.9);
+ polygon.ps[2] = Point(430, 5853.9);
+ polygon.ps[3] = Point(430, 5791.9);
+ new ShapeRef(router, polygon, 386);
+
+ // shapeRef387
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13019.5, 12261.3);
+ polygon.ps[1] = Point(13019.5, 12323.3);
+ polygon.ps[2] = Point(12957.5, 12323.3);
+ polygon.ps[3] = Point(12957.5, 12261.3);
+ new ShapeRef(router, polygon, 387);
+
+ // shapeRef388
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13573, 12261.3);
+ polygon.ps[1] = Point(13573, 12323.3);
+ polygon.ps[2] = Point(13511, 12323.3);
+ polygon.ps[3] = Point(13511, 12261.3);
+ new ShapeRef(router, polygon, 388);
+
+ // shapeRef389
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13264, 11951.3);
+ polygon.ps[1] = Point(13264, 12013.3);
+ polygon.ps[2] = Point(13202, 12013.3);
+ polygon.ps[3] = Point(13202, 11951.3);
+ new ShapeRef(router, polygon, 389);
+
+ // shapeRef390
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13936, 12096.3);
+ polygon.ps[1] = Point(13936, 12158.3);
+ polygon.ps[2] = Point(13874, 12158.3);
+ polygon.ps[3] = Point(13874, 12096.3);
+ new ShapeRef(router, polygon, 390);
+
+ // shapeRef391
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14827, 8611.22);
+ polygon.ps[1] = Point(14827, 8673.22);
+ polygon.ps[2] = Point(14765, 8673.22);
+ polygon.ps[3] = Point(14765, 8611.22);
+ new ShapeRef(router, polygon, 391);
+
+ // shapeRef392
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14464, 8611.22);
+ polygon.ps[1] = Point(14464, 8673.22);
+ polygon.ps[2] = Point(14402, 8673.22);
+ polygon.ps[3] = Point(14402, 8611.22);
+ new ShapeRef(router, polygon, 392);
+
+ // shapeRef393
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14827, 9182.42);
+ polygon.ps[1] = Point(14827, 9244.42);
+ polygon.ps[2] = Point(14765, 9244.42);
+ polygon.ps[3] = Point(14765, 9182.42);
+ new ShapeRef(router, polygon, 393);
+
+ // shapeRef394
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15899.6, 9116.42);
+ polygon.ps[1] = Point(15899.6, 9178.42);
+ polygon.ps[2] = Point(15837.6, 9178.42);
+ polygon.ps[3] = Point(15837.6, 9116.42);
+ new ShapeRef(router, polygon, 394);
+
+ // shapeRef395
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16295.6, 9116.42);
+ polygon.ps[1] = Point(16295.6, 9178.42);
+ polygon.ps[2] = Point(16233.6, 9178.42);
+ polygon.ps[3] = Point(16233.6, 9116.42);
+ new ShapeRef(router, polygon, 395);
+
+ // shapeRef396
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16130.6, 9978.02);
+ polygon.ps[1] = Point(16130.6, 10040);
+ polygon.ps[2] = Point(16068.6, 10040);
+ polygon.ps[3] = Point(16068.6, 9978.02);
+ new ShapeRef(router, polygon, 396);
+
+ // shapeRef397
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16493.6, 9978.02);
+ polygon.ps[1] = Point(16493.6, 10040);
+ polygon.ps[2] = Point(16431.6, 10040);
+ polygon.ps[3] = Point(16431.6, 9978.02);
+ new ShapeRef(router, polygon, 397);
+
+ // shapeRef398
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16753.8, 10275);
+ polygon.ps[1] = Point(16753.8, 10337);
+ polygon.ps[2] = Point(16691.8, 10337);
+ polygon.ps[3] = Point(16691.8, 10275);
+ new ShapeRef(router, polygon, 398);
+
+ // shapeRef399
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17871.5, 7031.4);
+ polygon.ps[1] = Point(17871.5, 7093.4);
+ polygon.ps[2] = Point(17809.5, 7093.4);
+ polygon.ps[3] = Point(17809.5, 7031.4);
+ new ShapeRef(router, polygon, 399);
+
+ // shapeRef400
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18036.5, 7911.79);
+ polygon.ps[1] = Point(18036.5, 7973.79);
+ polygon.ps[2] = Point(17974.5, 7973.79);
+ polygon.ps[3] = Point(17974.5, 7911.79);
+ new ShapeRef(router, polygon, 400);
+
+ // shapeRef401
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18234.5, 8743.22);
+ polygon.ps[1] = Point(18234.5, 8805.22);
+ polygon.ps[2] = Point(18172.5, 8805.22);
+ polygon.ps[3] = Point(18172.5, 8743.22);
+ new ShapeRef(router, polygon, 401);
+
+ // shapeRef402
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11724.1, 2449.29);
+ polygon.ps[1] = Point(11724.1, 2511.29);
+ polygon.ps[2] = Point(11662.1, 2511.29);
+ polygon.ps[3] = Point(11662.1, 2449.29);
+ new ShapeRef(router, polygon, 402);
+
+ // shapeRef403
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16361.6, 11015.6);
+ polygon.ps[1] = Point(16361.6, 11077.6);
+ polygon.ps[2] = Point(16299.6, 11077.6);
+ polygon.ps[3] = Point(16299.6, 11015.6);
+ new ShapeRef(router, polygon, 403);
+
+ // shapeRef404
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16361.6, 10473);
+ polygon.ps[1] = Point(16361.6, 10535);
+ polygon.ps[2] = Point(16299.6, 10535);
+ polygon.ps[3] = Point(16299.6, 10473);
+ new ShapeRef(router, polygon, 404);
+
+ // shapeRef405
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16361.6, 9644.42);
+ polygon.ps[1] = Point(16361.6, 9706.42);
+ polygon.ps[2] = Point(16299.6, 9706.42);
+ polygon.ps[3] = Point(16299.6, 9644.42);
+ new ShapeRef(router, polygon, 405);
+
+ // shapeRef406
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11104.2, 4643.4);
+ polygon.ps[1] = Point(11104.2, 4705.4);
+ polygon.ps[2] = Point(11042.2, 4705.4);
+ polygon.ps[3] = Point(11042.2, 4643.4);
+ new ShapeRef(router, polygon, 406);
+
+ // shapeRef407
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5013, 4907.4);
+ polygon.ps[1] = Point(5013, 4969.4);
+ polygon.ps[2] = Point(4951, 4969.4);
+ polygon.ps[3] = Point(4951, 4907.4);
+ new ShapeRef(router, polygon, 407);
+
+ // shapeRef408
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3330, 6790.21);
+ polygon.ps[1] = Point(3330, 6852.21);
+ polygon.ps[2] = Point(3268, 6852.21);
+ polygon.ps[3] = Point(3268, 6790.21);
+ new ShapeRef(router, polygon, 408);
+
+ // shapeRef409
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3990, 5626.9);
+ polygon.ps[1] = Point(3990, 5688.9);
+ polygon.ps[2] = Point(3928, 5688.9);
+ polygon.ps[3] = Point(3928, 5626.9);
+ new ShapeRef(router, polygon, 409);
+
+ // shapeRef410
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3165, 5626.9);
+ polygon.ps[1] = Point(3165, 5688.9);
+ polygon.ps[2] = Point(3103, 5688.9);
+ polygon.ps[3] = Point(3103, 5626.9);
+ new ShapeRef(router, polygon, 410);
+
+ // shapeRef411
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3660, 5626.9);
+ polygon.ps[1] = Point(3660, 5688.9);
+ polygon.ps[2] = Point(3598, 5688.9);
+ polygon.ps[3] = Point(3598, 5626.9);
+ new ShapeRef(router, polygon, 411);
+
+ // shapeRef412
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5659.1, 7581.79);
+ polygon.ps[1] = Point(5659.1, 7643.79);
+ polygon.ps[2] = Point(5597.1, 7643.79);
+ polygon.ps[3] = Point(5597.1, 7581.79);
+ new ShapeRef(router, polygon, 412);
+
+ // shapeRef413
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5659.1, 6965.4);
+ polygon.ps[1] = Point(5659.1, 7027.4);
+ polygon.ps[2] = Point(5597.1, 7027.4);
+ polygon.ps[3] = Point(5597.1, 6965.4);
+ new ShapeRef(router, polygon, 413);
+
+ // shapeRef414
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1911, 6153.51);
+ polygon.ps[1] = Point(1911, 6215.51);
+ polygon.ps[2] = Point(1849, 6215.51);
+ polygon.ps[3] = Point(1849, 6153.51);
+ new ShapeRef(router, polygon, 414);
+
+ // shapeRef415
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1911, 7196.4);
+ polygon.ps[1] = Point(1911, 7258.4);
+ polygon.ps[2] = Point(1849, 7258.4);
+ polygon.ps[3] = Point(1849, 7196.4);
+ new ShapeRef(router, polygon, 415);
+
+ // shapeRef416
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12285.1, 2449.29);
+ polygon.ps[1] = Point(12285.1, 2511.29);
+ polygon.ps[2] = Point(12223.1, 2511.29);
+ polygon.ps[3] = Point(12223.1, 2449.29);
+ new ShapeRef(router, polygon, 416);
+
+ // shapeRef417
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11724.1, 2185.29);
+ polygon.ps[1] = Point(11724.1, 2247.29);
+ polygon.ps[2] = Point(11662.1, 2247.29);
+ polygon.ps[3] = Point(11662.1, 2185.29);
+ new ShapeRef(router, polygon, 417);
+
+ // shapeRef418
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17508.5, 3600.51);
+ polygon.ps[1] = Point(17508.5, 3662.51);
+ polygon.ps[2] = Point(17446.5, 3662.51);
+ polygon.ps[3] = Point(17446.5, 3600.51);
+ new ShapeRef(router, polygon, 418);
+
+ // shapeRef419
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12186.1, 2185.29);
+ polygon.ps[1] = Point(12186.1, 2247.29);
+ polygon.ps[2] = Point(12124.1, 2247.29);
+ polygon.ps[3] = Point(12124.1, 2185.29);
+ new ShapeRef(router, polygon, 419);
+
+ // shapeRef420
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12854.5, 1846.29);
+ polygon.ps[1] = Point(12854.5, 1908.29);
+ polygon.ps[2] = Point(12792.5, 1908.29);
+ polygon.ps[3] = Point(12792.5, 1846.29);
+ new ShapeRef(router, polygon, 420);
+
+ // shapeRef421
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13507, 2185.29);
+ polygon.ps[1] = Point(13507, 2247.29);
+ polygon.ps[2] = Point(13445, 2247.29);
+ polygon.ps[3] = Point(13445, 2185.29);
+ new ShapeRef(router, polygon, 421);
+
+ // shapeRef422
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12854.5, 2185.29);
+ polygon.ps[1] = Point(12854.5, 2247.29);
+ polygon.ps[2] = Point(12792.5, 2247.29);
+ polygon.ps[3] = Point(12792.5, 2185.29);
+ new ShapeRef(router, polygon, 422);
+
+ // shapeRef423
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12854.5, 2515.29);
+ polygon.ps[1] = Point(12854.5, 2577.29);
+ polygon.ps[2] = Point(12792.5, 2577.29);
+ polygon.ps[3] = Point(12792.5, 2515.29);
+ new ShapeRef(router, polygon, 423);
+
+ // shapeRef424
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12854.5, 2944.29);
+ polygon.ps[1] = Point(12854.5, 3006.29);
+ polygon.ps[2] = Point(12792.5, 3006.29);
+ polygon.ps[3] = Point(12792.5, 2944.29);
+ new ShapeRef(router, polygon, 424);
+
+ // shapeRef425
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11658.1, 6516.51);
+ polygon.ps[1] = Point(11658.1, 6578.51);
+ polygon.ps[2] = Point(11596.1, 6578.51);
+ polygon.ps[3] = Point(11596.1, 6516.51);
+ new ShapeRef(router, polygon, 425);
+
+ // shapeRef426
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17083.8, 6186.51);
+ polygon.ps[1] = Point(17083.8, 6248.51);
+ polygon.ps[2] = Point(17021.8, 6248.51);
+ polygon.ps[3] = Point(17021.8, 6186.51);
+ new ShapeRef(router, polygon, 426);
+
+ // shapeRef427
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17083.8, 6516.51);
+ polygon.ps[1] = Point(17083.8, 6578.51);
+ polygon.ps[2] = Point(17021.8, 6578.51);
+ polygon.ps[3] = Point(17021.8, 6516.51);
+ new ShapeRef(router, polygon, 427);
+
+ // shapeRef428
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 8797.89);
+ polygon.ps[1] = Point(8589.03, 8837.89);
+ polygon.ps[2] = Point(8534.03, 8837.89);
+ polygon.ps[3] = Point(8534.03, 8797.89);
+ new ShapeRef(router, polygon, 428);
+
+ // shapeRef429
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 8797.89);
+ polygon.ps[1] = Point(8689.03, 8837.89);
+ polygon.ps[2] = Point(8634.03, 8837.89);
+ polygon.ps[3] = Point(8634.03, 8797.89);
+ new ShapeRef(router, polygon, 429);
+
+ // shapeRef430
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1911, 12017.3);
+ polygon.ps[1] = Point(1911, 12079.3);
+ polygon.ps[2] = Point(1849, 12079.3);
+ polygon.ps[3] = Point(1849, 12017.3);
+ new ShapeRef(router, polygon, 430);
+
+ // shapeRef431
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1911, 11549.7);
+ polygon.ps[1] = Point(1911, 11611.7);
+ polygon.ps[2] = Point(1849, 11611.7);
+ polygon.ps[3] = Point(1849, 11549.7);
+ new ShapeRef(router, polygon, 431);
+
+ // shapeRef432
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1350, 10585.3);
+ polygon.ps[1] = Point(1350, 10647.3);
+ polygon.ps[2] = Point(1288, 10647.3);
+ polygon.ps[3] = Point(1288, 10585.3);
+ new ShapeRef(router, polygon, 432);
+
+ // shapeRef433
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1350, 10275);
+ polygon.ps[1] = Point(1350, 10337);
+ polygon.ps[2] = Point(1288, 10337);
+ polygon.ps[3] = Point(1288, 10275);
+ new ShapeRef(router, polygon, 433);
+
+ // shapeRef434
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1350, 9945.02);
+ polygon.ps[1] = Point(1350, 10007);
+ polygon.ps[2] = Point(1288, 10007);
+ polygon.ps[3] = Point(1288, 9945.02);
+ new ShapeRef(router, polygon, 434);
+
+ // shapeRef435
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1350, 9479.42);
+ polygon.ps[1] = Point(1350, 9541.42);
+ polygon.ps[2] = Point(1288, 9541.42);
+ polygon.ps[3] = Point(1288, 9479.42);
+ new ShapeRef(router, polygon, 435);
+
+ // shapeRef436
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1350, 9116.42);
+ polygon.ps[1] = Point(1350, 9178.42);
+ polygon.ps[2] = Point(1288, 9178.42);
+ polygon.ps[3] = Point(1288, 9116.42);
+ new ShapeRef(router, polygon, 436);
+
+ // shapeRef437
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1911, 10275);
+ polygon.ps[1] = Point(1911, 10337);
+ polygon.ps[2] = Point(1849, 10337);
+ polygon.ps[3] = Point(1849, 10275);
+ new ShapeRef(router, polygon, 437);
+
+ // shapeRef438
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1911, 9945.02);
+ polygon.ps[1] = Point(1911, 10007);
+ polygon.ps[2] = Point(1849, 10007);
+ polygon.ps[3] = Point(1849, 9945.02);
+ new ShapeRef(router, polygon, 438);
+
+ // shapeRef439
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1911, 9479.42);
+ polygon.ps[1] = Point(1911, 9541.42);
+ polygon.ps[2] = Point(1849, 9541.42);
+ polygon.ps[3] = Point(1849, 9479.42);
+ new ShapeRef(router, polygon, 439);
+
+ // shapeRef440
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1911, 9116.42);
+ polygon.ps[1] = Point(1911, 9178.42);
+ polygon.ps[2] = Point(1849, 9178.42);
+ polygon.ps[3] = Point(1849, 9116.42);
+ new ShapeRef(router, polygon, 440);
+
+ // shapeRef441
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 8897.89);
+ polygon.ps[1] = Point(8789.03, 8937.89);
+ polygon.ps[2] = Point(8734.03, 8937.89);
+ polygon.ps[3] = Point(8734.03, 8897.89);
+ new ShapeRef(router, polygon, 441);
+
+ // shapeRef442
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 8897.89);
+ polygon.ps[1] = Point(8889.03, 8937.89);
+ polygon.ps[2] = Point(8834.03, 8937.89);
+ polygon.ps[3] = Point(8834.03, 8897.89);
+ new ShapeRef(router, polygon, 442);
+
+ // shapeRef443
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 8897.89);
+ polygon.ps[1] = Point(8989.03, 8937.89);
+ polygon.ps[2] = Point(8934.03, 8937.89);
+ polygon.ps[3] = Point(8934.03, 8897.89);
+ new ShapeRef(router, polygon, 443);
+
+ // shapeRef444
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 8897.89);
+ polygon.ps[1] = Point(9089.03, 8937.89);
+ polygon.ps[2] = Point(9034.03, 8937.89);
+ polygon.ps[3] = Point(9034.03, 8897.89);
+ new ShapeRef(router, polygon, 444);
+
+ // shapeRef445
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 8897.89);
+ polygon.ps[1] = Point(9189.03, 8937.89);
+ polygon.ps[2] = Point(9134.03, 8937.89);
+ polygon.ps[3] = Point(9134.03, 8897.89);
+ new ShapeRef(router, polygon, 445);
+
+ // shapeRef446
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2043, 2779.29);
+ polygon.ps[1] = Point(2043, 2841.29);
+ polygon.ps[2] = Point(1981, 2841.29);
+ polygon.ps[3] = Point(1981, 2779.29);
+ new ShapeRef(router, polygon, 446);
+
+ // shapeRef447
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4980, 4029.51);
+ polygon.ps[1] = Point(4980, 4091.51);
+ polygon.ps[2] = Point(4918, 4091.51);
+ polygon.ps[3] = Point(4918, 4029.51);
+ new ShapeRef(router, polygon, 447);
+
+ // shapeRef448
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1779, 3307.29);
+ polygon.ps[1] = Point(1779, 3369.29);
+ polygon.ps[2] = Point(1717, 3369.29);
+ polygon.ps[3] = Point(1717, 3307.29);
+ new ShapeRef(router, polygon, 448);
+
+ // shapeRef449
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1053, 3435.51);
+ polygon.ps[1] = Point(1053, 3497.51);
+ polygon.ps[2] = Point(991, 3497.51);
+ polygon.ps[3] = Point(991, 3435.51);
+ new ShapeRef(router, polygon, 449);
+
+ // shapeRef450
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1449, 3567.51);
+ polygon.ps[1] = Point(1449, 3629.51);
+ polygon.ps[2] = Point(1387, 3629.51);
+ polygon.ps[3] = Point(1387, 3567.51);
+ new ShapeRef(router, polygon, 450);
+
+ // shapeRef451
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2307, 3897.51);
+ polygon.ps[1] = Point(2307, 3959.51);
+ polygon.ps[2] = Point(2245, 3959.51);
+ polygon.ps[3] = Point(2245, 3897.51);
+ new ShapeRef(router, polygon, 451);
+
+ // shapeRef452
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(327, 3666.51);
+ polygon.ps[1] = Point(327, 3728.51);
+ polygon.ps[2] = Point(265, 3728.51);
+ polygon.ps[3] = Point(265, 3666.51);
+ new ShapeRef(router, polygon, 452);
+
+ // shapeRef453
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(558, 3666.51);
+ polygon.ps[1] = Point(558, 3728.51);
+ polygon.ps[2] = Point(496, 3728.51);
+ polygon.ps[3] = Point(496, 3666.51);
+ new ShapeRef(router, polygon, 453);
+
+ // shapeRef454
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(888, 3666.51);
+ polygon.ps[1] = Point(888, 3728.51);
+ polygon.ps[2] = Point(826, 3728.51);
+ polygon.ps[3] = Point(826, 3666.51);
+ new ShapeRef(router, polygon, 454);
+
+ // shapeRef455
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1284, 3666.51);
+ polygon.ps[1] = Point(1284, 3728.51);
+ polygon.ps[2] = Point(1222, 3728.51);
+ polygon.ps[3] = Point(1222, 3666.51);
+ new ShapeRef(router, polygon, 455);
+
+ // shapeRef456
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1713, 3666.51);
+ polygon.ps[1] = Point(1713, 3728.51);
+ polygon.ps[2] = Point(1651, 3728.51);
+ polygon.ps[3] = Point(1651, 3666.51);
+ new ShapeRef(router, polygon, 456);
+
+ // shapeRef457
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2043, 3666.51);
+ polygon.ps[1] = Point(2043, 3728.51);
+ polygon.ps[2] = Point(1981, 3728.51);
+ polygon.ps[3] = Point(1981, 3666.51);
+ new ShapeRef(router, polygon, 457);
+
+ // shapeRef458
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(228, 3109.29);
+ polygon.ps[1] = Point(228, 3171.29);
+ polygon.ps[2] = Point(166, 3171.29);
+ polygon.ps[3] = Point(166, 3109.29);
+ new ShapeRef(router, polygon, 458);
+
+ // shapeRef459
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1119, 2614.29);
+ polygon.ps[1] = Point(1119, 2676.29);
+ polygon.ps[2] = Point(1057, 2676.29);
+ polygon.ps[3] = Point(1057, 2614.29);
+ new ShapeRef(router, polygon, 459);
+
+ // shapeRef460
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(459, 2614.29);
+ polygon.ps[1] = Point(459, 2676.29);
+ polygon.ps[2] = Point(397, 2676.29);
+ polygon.ps[3] = Point(397, 2614.29);
+ new ShapeRef(router, polygon, 460);
+
+ // shapeRef461
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(723, 1813.29);
+ polygon.ps[1] = Point(723, 1875.29);
+ polygon.ps[2] = Point(661, 1875.29);
+ polygon.ps[3] = Point(661, 1813.29);
+ new ShapeRef(router, polygon, 461);
+
+ // shapeRef462
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(723, 2614.29);
+ polygon.ps[1] = Point(723, 2676.29);
+ polygon.ps[2] = Point(661, 2676.29);
+ polygon.ps[3] = Point(661, 2614.29);
+ new ShapeRef(router, polygon, 462);
+
+ // shapeRef463
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(723, 2911.29);
+ polygon.ps[1] = Point(723, 2973.29);
+ polygon.ps[2] = Point(661, 2973.29);
+ polygon.ps[3] = Point(661, 2911.29);
+ new ShapeRef(router, polygon, 463);
+
+ // shapeRef464
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(459, 3109.29);
+ polygon.ps[1] = Point(459, 3171.29);
+ polygon.ps[2] = Point(397, 3171.29);
+ polygon.ps[3] = Point(397, 3109.29);
+ new ShapeRef(router, polygon, 464);
+
+ // shapeRef465
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(723, 3241.29);
+ polygon.ps[1] = Point(723, 3303.29);
+ polygon.ps[2] = Point(661, 3303.29);
+ polygon.ps[3] = Point(661, 3241.29);
+ new ShapeRef(router, polygon, 465);
+
+ // shapeRef466
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1086, 3109.29);
+ polygon.ps[1] = Point(1086, 3171.29);
+ polygon.ps[2] = Point(1024, 3171.29);
+ polygon.ps[3] = Point(1024, 3109.29);
+ new ShapeRef(router, polygon, 466);
+
+ // shapeRef467
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2043, 3109.29);
+ polygon.ps[1] = Point(2043, 3171.29);
+ polygon.ps[2] = Point(1981, 3171.29);
+ polygon.ps[3] = Point(1981, 3109.29);
+ new ShapeRef(router, polygon, 467);
+
+ // shapeRef468
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2637, 3109.29);
+ polygon.ps[1] = Point(2637, 3171.29);
+ polygon.ps[2] = Point(2575, 3171.29);
+ polygon.ps[3] = Point(2575, 3109.29);
+ new ShapeRef(router, polygon, 468);
+
+ // shapeRef469
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(987, 4297.11);
+ polygon.ps[1] = Point(987, 4359.11);
+ polygon.ps[2] = Point(925, 4359.11);
+ polygon.ps[3] = Point(925, 4297.11);
+ new ShapeRef(router, polygon, 469);
+
+ // shapeRef470
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1482, 4297.11);
+ polygon.ps[1] = Point(1482, 4359.11);
+ polygon.ps[2] = Point(1420, 4359.11);
+ polygon.ps[3] = Point(1420, 4297.11);
+ new ShapeRef(router, polygon, 470);
+
+ // shapeRef471
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6055.1, 3666.51);
+ polygon.ps[1] = Point(6055.1, 3728.51);
+ polygon.ps[2] = Point(5993.1, 3728.51);
+ polygon.ps[3] = Point(5993.1, 3666.51);
+ new ShapeRef(router, polygon, 471);
+
+ // shapeRef472
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5560.1, 3666.51);
+ polygon.ps[1] = Point(5560.1, 3728.51);
+ polygon.ps[2] = Point(5498.1, 3728.51);
+ polygon.ps[3] = Point(5498.1, 3666.51);
+ new ShapeRef(router, polygon, 472);
+
+ // shapeRef473
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5178, 3666.51);
+ polygon.ps[1] = Point(5178, 3728.51);
+ polygon.ps[2] = Point(5116, 3728.51);
+ polygon.ps[3] = Point(5116, 3666.51);
+ new ShapeRef(router, polygon, 473);
+
+ // shapeRef474
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4914, 3666.51);
+ polygon.ps[1] = Point(4914, 3728.51);
+ polygon.ps[2] = Point(4852, 3728.51);
+ polygon.ps[3] = Point(4852, 3666.51);
+ new ShapeRef(router, polygon, 474);
+
+ // shapeRef475
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1779, 2515.29);
+ polygon.ps[1] = Point(1779, 2577.29);
+ polygon.ps[2] = Point(1717, 2577.29);
+ polygon.ps[3] = Point(1717, 2515.29);
+ new ShapeRef(router, polygon, 475);
+
+ // shapeRef476
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2208, 2515.29);
+ polygon.ps[1] = Point(2208, 2577.29);
+ polygon.ps[2] = Point(2146, 2577.29);
+ polygon.ps[3] = Point(2146, 2515.29);
+ new ShapeRef(router, polygon, 476);
+
+ // shapeRef477
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2538, 2515.29);
+ polygon.ps[1] = Point(2538, 2577.29);
+ polygon.ps[2] = Point(2476, 2577.29);
+ polygon.ps[3] = Point(2476, 2515.29);
+ new ShapeRef(router, polygon, 477);
+
+ // shapeRef478
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3000, 2515.29);
+ polygon.ps[1] = Point(3000, 2577.29);
+ polygon.ps[2] = Point(2938, 2577.29);
+ polygon.ps[3] = Point(2938, 2515.29);
+ new ShapeRef(router, polygon, 478);
+
+ // shapeRef479
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3858, 2284.29);
+ polygon.ps[1] = Point(3858, 2346.29);
+ polygon.ps[2] = Point(3796, 2346.29);
+ polygon.ps[3] = Point(3796, 2284.29);
+ new ShapeRef(router, polygon, 479);
+
+ // shapeRef480
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7045.1, 3798.51);
+ polygon.ps[1] = Point(7045.1, 3860.51);
+ polygon.ps[2] = Point(6983.1, 3860.51);
+ polygon.ps[3] = Point(6983.1, 3798.51);
+ new ShapeRef(router, polygon, 480);
+
+ // shapeRef481
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6451.1, 2482.29);
+ polygon.ps[1] = Point(6451.1, 2544.29);
+ polygon.ps[2] = Point(6389.1, 2544.29);
+ polygon.ps[3] = Point(6389.1, 2482.29);
+ new ShapeRef(router, polygon, 481);
+
+ // shapeRef482
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6847.1, 2482.29);
+ polygon.ps[1] = Point(6847.1, 2544.29);
+ polygon.ps[2] = Point(6785.1, 2544.29);
+ polygon.ps[3] = Point(6785.1, 2482.29);
+ new ShapeRef(router, polygon, 482);
+
+ // shapeRef483
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6451.1, 2746.29);
+ polygon.ps[1] = Point(6451.1, 2808.29);
+ polygon.ps[2] = Point(6389.1, 2808.29);
+ polygon.ps[3] = Point(6389.1, 2746.29);
+ new ShapeRef(router, polygon, 483);
+
+ // shapeRef484
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7375.1, 3043.29);
+ polygon.ps[1] = Point(7375.1, 3105.29);
+ polygon.ps[2] = Point(7313.1, 3105.29);
+ polygon.ps[3] = Point(7313.1, 3043.29);
+ new ShapeRef(router, polygon, 484);
+
+ // shapeRef485
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8060.29, 3043.29);
+ polygon.ps[1] = Point(8060.29, 3105.29);
+ polygon.ps[2] = Point(7998.29, 3105.29);
+ polygon.ps[3] = Point(7998.29, 3043.29);
+ new ShapeRef(router, polygon, 485);
+
+ // shapeRef486
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6286.1, 3043.29);
+ polygon.ps[1] = Point(6286.1, 3105.29);
+ polygon.ps[2] = Point(6224.1, 3105.29);
+ polygon.ps[3] = Point(6224.1, 3043.29);
+ new ShapeRef(router, polygon, 486);
+
+ // shapeRef487
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5857.1, 3043.29);
+ polygon.ps[1] = Point(5857.1, 3105.29);
+ polygon.ps[2] = Point(5795.1, 3105.29);
+ polygon.ps[3] = Point(5795.1, 3043.29);
+ new ShapeRef(router, polygon, 487);
+
+ // shapeRef488
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7375.1, 2746.29);
+ polygon.ps[1] = Point(7375.1, 2808.29);
+ polygon.ps[2] = Point(7313.1, 2808.29);
+ polygon.ps[3] = Point(7313.1, 2746.29);
+ new ShapeRef(router, polygon, 488);
+
+ // shapeRef489
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7375.1, 2482.29);
+ polygon.ps[1] = Point(7375.1, 2544.29);
+ polygon.ps[2] = Point(7313.1, 2544.29);
+ polygon.ps[3] = Point(7313.1, 2482.29);
+ new ShapeRef(router, polygon, 489);
+
+ // shapeRef490
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7375.1, 1945.29);
+ polygon.ps[1] = Point(7375.1, 2007.29);
+ polygon.ps[2] = Point(7313.1, 2007.29);
+ polygon.ps[3] = Point(7313.1, 1945.29);
+ new ShapeRef(router, polygon, 490);
+
+ // shapeRef491
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7375.1, 1579.29);
+ polygon.ps[1] = Point(7375.1, 1641.29);
+ polygon.ps[2] = Point(7313.1, 1641.29);
+ polygon.ps[3] = Point(7313.1, 1579.29);
+ new ShapeRef(router, polygon, 491);
+
+ // shapeRef492
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7375.1, 1249.29);
+ polygon.ps[1] = Point(7375.1, 1311.29);
+ polygon.ps[2] = Point(7313.1, 1311.29);
+ polygon.ps[3] = Point(7313.1, 1249.29);
+ new ShapeRef(router, polygon, 492);
+
+ // shapeRef493
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(822, 216.265);
+ polygon.ps[1] = Point(822, 278.265);
+ polygon.ps[2] = Point(760, 278.265);
+ polygon.ps[3] = Point(760, 216.265);
+ new ShapeRef(router, polygon, 493);
+
+ // shapeRef494
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(822, 84.2652);
+ polygon.ps[1] = Point(822, 146.265);
+ polygon.ps[2] = Point(760, 146.265);
+ polygon.ps[3] = Point(760, 84.2652);
+ new ShapeRef(router, polygon, 494);
+
+ // shapeRef495
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1218, 183.265);
+ polygon.ps[1] = Point(1218, 245.265);
+ polygon.ps[2] = Point(1156, 245.265);
+ polygon.ps[3] = Point(1156, 183.265);
+ new ShapeRef(router, polygon, 495);
+
+ // shapeRef496
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1977, 183.265);
+ polygon.ps[1] = Point(1977, 245.265);
+ polygon.ps[2] = Point(1915, 245.265);
+ polygon.ps[3] = Point(1915, 183.265);
+ new ShapeRef(router, polygon, 496);
+
+ // shapeRef497
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2439, 183.265);
+ polygon.ps[1] = Point(2439, 245.265);
+ polygon.ps[2] = Point(2377, 245.265);
+ polygon.ps[3] = Point(2377, 183.265);
+ new ShapeRef(router, polygon, 497);
+
+ // shapeRef498
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2835, 216.265);
+ polygon.ps[1] = Point(2835, 278.265);
+ polygon.ps[2] = Point(2773, 278.265);
+ polygon.ps[3] = Point(2773, 216.265);
+ new ShapeRef(router, polygon, 498);
+
+ // shapeRef499
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2835, 84.2652);
+ polygon.ps[1] = Point(2835, 146.265);
+ polygon.ps[2] = Point(2773, 146.265);
+ polygon.ps[3] = Point(2773, 84.2652);
+ new ShapeRef(router, polygon, 499);
+
+ // shapeRef500
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3363, 183.265);
+ polygon.ps[1] = Point(3363, 245.265);
+ polygon.ps[2] = Point(3301, 245.265);
+ polygon.ps[3] = Point(3301, 183.265);
+ new ShapeRef(router, polygon, 500);
+
+ // shapeRef501
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3792, 183.265);
+ polygon.ps[1] = Point(3792, 245.265);
+ polygon.ps[2] = Point(3730, 245.265);
+ polygon.ps[3] = Point(3730, 183.265);
+ new ShapeRef(router, polygon, 501);
+
+ // shapeRef502
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4518, 183.265);
+ polygon.ps[1] = Point(4518, 245.265);
+ polygon.ps[2] = Point(4456, 245.265);
+ polygon.ps[3] = Point(4456, 183.265);
+ new ShapeRef(router, polygon, 502);
+
+ // shapeRef503
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4914, 183.265);
+ polygon.ps[1] = Point(4914, 245.265);
+ polygon.ps[2] = Point(4852, 245.265);
+ polygon.ps[3] = Point(4852, 183.265);
+ new ShapeRef(router, polygon, 503);
+
+ // shapeRef504
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5211, 183.265);
+ polygon.ps[1] = Point(5211, 245.265);
+ polygon.ps[2] = Point(5149, 245.265);
+ polygon.ps[3] = Point(5149, 183.265);
+ new ShapeRef(router, polygon, 504);
+
+ // shapeRef505
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5659.1, 183.265);
+ polygon.ps[1] = Point(5659.1, 245.265);
+ polygon.ps[2] = Point(5597.1, 245.265);
+ polygon.ps[3] = Point(5597.1, 183.265);
+ new ShapeRef(router, polygon, 505);
+
+ // shapeRef506
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6616.1, 183.265);
+ polygon.ps[1] = Point(6616.1, 245.265);
+ polygon.ps[2] = Point(6554.1, 245.265);
+ polygon.ps[3] = Point(6554.1, 183.265);
+ new ShapeRef(router, polygon, 506);
+
+ // shapeRef507
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6913.1, 183.265);
+ polygon.ps[1] = Point(6913.1, 245.265);
+ polygon.ps[2] = Point(6851.1, 245.265);
+ polygon.ps[3] = Point(6851.1, 183.265);
+ new ShapeRef(router, polygon, 507);
+
+ // shapeRef508
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7309.1, 183.265);
+ polygon.ps[1] = Point(7309.1, 245.265);
+ polygon.ps[2] = Point(7247.1, 245.265);
+ polygon.ps[3] = Point(7247.1, 183.265);
+ new ShapeRef(router, polygon, 508);
+
+ // shapeRef509
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7796.29, 183.265);
+ polygon.ps[1] = Point(7796.29, 245.265);
+ polygon.ps[2] = Point(7734.29, 245.265);
+ polygon.ps[3] = Point(7734.29, 183.265);
+ new ShapeRef(router, polygon, 509);
+
+ // shapeRef510
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5343, 9248.42);
+ polygon.ps[1] = Point(5343, 9310.42);
+ polygon.ps[2] = Point(5281, 9310.42);
+ polygon.ps[3] = Point(5281, 9248.42);
+ new ShapeRef(router, polygon, 510);
+
+ // shapeRef511
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5343, 9677.42);
+ polygon.ps[1] = Point(5343, 9739.42);
+ polygon.ps[2] = Point(5281, 9739.42);
+ polygon.ps[3] = Point(5281, 9677.42);
+ new ShapeRef(router, polygon, 511);
+
+ // shapeRef512
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5824.1, 9248.42);
+ polygon.ps[1] = Point(5824.1, 9310.42);
+ polygon.ps[2] = Point(5762.1, 9310.42);
+ polygon.ps[3] = Point(5762.1, 9248.42);
+ new ShapeRef(router, polygon, 512);
+
+ // shapeRef513
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5824.1, 9677.42);
+ polygon.ps[1] = Point(5824.1, 9739.42);
+ polygon.ps[2] = Point(5762.1, 9739.42);
+ polygon.ps[3] = Point(5762.1, 9677.42);
+ new ShapeRef(router, polygon, 513);
+
+ // shapeRef514
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5626.1, 10407);
+ polygon.ps[1] = Point(5626.1, 10469);
+ polygon.ps[2] = Point(5564.1, 10469);
+ polygon.ps[3] = Point(5564.1, 10407);
+ new ShapeRef(router, polygon, 514);
+
+ // shapeRef515
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5626.1, 10143);
+ polygon.ps[1] = Point(5626.1, 10205);
+ polygon.ps[2] = Point(5564.1, 10205);
+ polygon.ps[3] = Point(5564.1, 10143);
+ new ShapeRef(router, polygon, 515);
+
+ // shapeRef516
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5145, 10143);
+ polygon.ps[1] = Point(5145, 10205);
+ polygon.ps[2] = Point(5083, 10205);
+ polygon.ps[3] = Point(5083, 10143);
+ new ShapeRef(router, polygon, 516);
+
+ // shapeRef517
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5145, 10407);
+ polygon.ps[1] = Point(5145, 10469);
+ polygon.ps[2] = Point(5083, 10469);
+ polygon.ps[3] = Point(5083, 10407);
+ new ShapeRef(router, polygon, 517);
+
+ // shapeRef518
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5145, 10684.3);
+ polygon.ps[1] = Point(5145, 10746.3);
+ polygon.ps[2] = Point(5083, 10746.3);
+ polygon.ps[3] = Point(5083, 10684.3);
+ new ShapeRef(router, polygon, 518);
+
+ // shapeRef519
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7796.29, 11984.3);
+ polygon.ps[1] = Point(7796.29, 12046.3);
+ polygon.ps[2] = Point(7734.29, 12046.3);
+ polygon.ps[3] = Point(7734.29, 11984.3);
+ new ShapeRef(router, polygon, 519);
+
+ // shapeRef520
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8225.29, 11984.3);
+ polygon.ps[1] = Point(8225.29, 12046.3);
+ polygon.ps[2] = Point(8163.29, 12046.3);
+ polygon.ps[3] = Point(8163.29, 11984.3);
+ new ShapeRef(router, polygon, 520);
+
+ // shapeRef521
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5626.1, 11180.6);
+ polygon.ps[1] = Point(5626.1, 11242.6);
+ polygon.ps[2] = Point(5564.1, 11242.6);
+ polygon.ps[3] = Point(5564.1, 11180.6);
+ new ShapeRef(router, polygon, 521);
+
+ // shapeRef522
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5626.1, 10684.3);
+ polygon.ps[1] = Point(5626.1, 10746.3);
+ polygon.ps[2] = Point(5564.1, 10746.3);
+ polygon.ps[3] = Point(5564.1, 10684.3);
+ new ShapeRef(router, polygon, 522);
+
+ // shapeRef523
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5989.1, 10684.3);
+ polygon.ps[1] = Point(5989.1, 10746.3);
+ polygon.ps[2] = Point(5927.1, 10746.3);
+ polygon.ps[3] = Point(5927.1, 10684.3);
+ new ShapeRef(router, polygon, 523);
+
+ // shapeRef524
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5989.1, 11180.6);
+ polygon.ps[1] = Point(5989.1, 11242.6);
+ polygon.ps[2] = Point(5927.1, 11242.6);
+ polygon.ps[3] = Point(5927.1, 11180.6);
+ new ShapeRef(router, polygon, 524);
+
+ // shapeRef525
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6253.1, 11180.6);
+ polygon.ps[1] = Point(6253.1, 11242.6);
+ polygon.ps[2] = Point(6191.1, 11242.6);
+ polygon.ps[3] = Point(6191.1, 11180.6);
+ new ShapeRef(router, polygon, 525);
+
+ // shapeRef526
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6649.1, 11180.6);
+ polygon.ps[1] = Point(6649.1, 11242.6);
+ polygon.ps[2] = Point(6587.1, 11242.6);
+ polygon.ps[3] = Point(6587.1, 11180.6);
+ new ShapeRef(router, polygon, 526);
+
+ // shapeRef527
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7078.1, 11180.6);
+ polygon.ps[1] = Point(7078.1, 11242.6);
+ polygon.ps[2] = Point(7016.1, 11242.6);
+ polygon.ps[3] = Point(7016.1, 11180.6);
+ new ShapeRef(router, polygon, 527);
+
+ // shapeRef528
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7573.1, 11180.6);
+ polygon.ps[1] = Point(7573.1, 11242.6);
+ polygon.ps[2] = Point(7511.1, 11242.6);
+ polygon.ps[3] = Point(7511.1, 11180.6);
+ new ShapeRef(router, polygon, 528);
+
+ // shapeRef529
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 10150.2);
+ polygon.ps[1] = Point(8789.03, 10190.2);
+ polygon.ps[2] = Point(8734.03, 10190.2);
+ polygon.ps[3] = Point(8734.03, 10150.2);
+ new ShapeRef(router, polygon, 529);
+
+ // shapeRef530
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 9697.89);
+ polygon.ps[1] = Point(8889.03, 9737.89);
+ polygon.ps[2] = Point(8834.03, 9737.89);
+ polygon.ps[3] = Point(8834.03, 9697.89);
+ new ShapeRef(router, polygon, 530);
+
+ // shapeRef531
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 9697.89);
+ polygon.ps[1] = Point(8989.03, 9737.89);
+ polygon.ps[2] = Point(8934.03, 9737.89);
+ polygon.ps[3] = Point(8934.03, 9697.89);
+ new ShapeRef(router, polygon, 531);
+
+ // shapeRef532
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 9697.89);
+ polygon.ps[1] = Point(9089.03, 9737.89);
+ polygon.ps[2] = Point(9034.03, 9737.89);
+ polygon.ps[3] = Point(9034.03, 9697.89);
+ new ShapeRef(router, polygon, 532);
+
+ // shapeRef533
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 9697.89);
+ polygon.ps[1] = Point(9189.03, 9737.89);
+ polygon.ps[2] = Point(9134.03, 9737.89);
+ polygon.ps[3] = Point(9134.03, 9697.89);
+ new ShapeRef(router, polygon, 533);
+
+ // shapeRef534
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 9765.77);
+ polygon.ps[1] = Point(9289.03, 9805.77);
+ polygon.ps[2] = Point(9234.03, 9805.77);
+ polygon.ps[3] = Point(9234.03, 9765.77);
+ new ShapeRef(router, polygon, 534);
+
+ // shapeRef535
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 9942.61);
+ polygon.ps[1] = Point(8389.03, 9982.61);
+ polygon.ps[2] = Point(8334.03, 9982.61);
+ polygon.ps[3] = Point(8334.03, 9942.61);
+ new ShapeRef(router, polygon, 535);
+
+ // shapeRef536
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 9942.61);
+ polygon.ps[1] = Point(8489.03, 9982.61);
+ polygon.ps[2] = Point(8434.03, 9982.61);
+ polygon.ps[3] = Point(8434.03, 9942.61);
+ new ShapeRef(router, polygon, 536);
+
+ // shapeRef537
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 9942.61);
+ polygon.ps[1] = Point(8589.03, 9982.61);
+ polygon.ps[2] = Point(8534.03, 9982.61);
+ polygon.ps[3] = Point(8534.03, 9942.61);
+ new ShapeRef(router, polygon, 537);
+
+ // shapeRef538
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 9797.89);
+ polygon.ps[1] = Point(8689.03, 9837.89);
+ polygon.ps[2] = Point(8634.03, 9837.89);
+ polygon.ps[3] = Point(8634.03, 9797.89);
+ new ShapeRef(router, polygon, 538);
+
+ // shapeRef539
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 9797.89);
+ polygon.ps[1] = Point(8789.03, 9837.89);
+ polygon.ps[2] = Point(8734.03, 9837.89);
+ polygon.ps[3] = Point(8734.03, 9797.89);
+ new ShapeRef(router, polygon, 539);
+
+ // shapeRef540
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 10150.2);
+ polygon.ps[1] = Point(8889.03, 10190.2);
+ polygon.ps[2] = Point(8834.03, 10190.2);
+ polygon.ps[3] = Point(8834.03, 10150.2);
+ new ShapeRef(router, polygon, 540);
+
+ // shapeRef541
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 10150.2);
+ polygon.ps[1] = Point(8989.03, 10190.2);
+ polygon.ps[2] = Point(8934.03, 10190.2);
+ polygon.ps[3] = Point(8934.03, 10150.2);
+ new ShapeRef(router, polygon, 541);
+
+ // shapeRef542
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 10150.2);
+ polygon.ps[1] = Point(9089.03, 10190.2);
+ polygon.ps[2] = Point(9034.03, 10190.2);
+ polygon.ps[3] = Point(9034.03, 10150.2);
+ new ShapeRef(router, polygon, 542);
+
+ // shapeRef543
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 9797.89);
+ polygon.ps[1] = Point(9189.03, 9837.89);
+ polygon.ps[2] = Point(9134.03, 9837.89);
+ polygon.ps[3] = Point(9134.03, 9797.89);
+ new ShapeRef(router, polygon, 543);
+
+ // shapeRef544
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11856.1, 150.265);
+ polygon.ps[1] = Point(11856.1, 212.265);
+ polygon.ps[2] = Point(11794.1, 212.265);
+ polygon.ps[3] = Point(11794.1, 150.265);
+ new ShapeRef(router, polygon, 544);
+
+ // shapeRef545
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11302.2, 150.265);
+ polygon.ps[1] = Point(11302.2, 212.265);
+ polygon.ps[2] = Point(11240.2, 212.265);
+ polygon.ps[3] = Point(11240.2, 150.265);
+ new ShapeRef(router, polygon, 545);
+
+ // shapeRef546
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10807.2, 150.265);
+ polygon.ps[1] = Point(10807.2, 212.265);
+ polygon.ps[2] = Point(10745.2, 212.265);
+ polygon.ps[3] = Point(10745.2, 150.265);
+ new ShapeRef(router, polygon, 546);
+
+ // shapeRef547
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9947.69, 150.265);
+ polygon.ps[1] = Point(9947.69, 212.265);
+ polygon.ps[2] = Point(9885.69, 212.265);
+ polygon.ps[3] = Point(9885.69, 150.265);
+ new ShapeRef(router, polygon, 547);
+
+ // shapeRef548
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9268.59, 150.265);
+ polygon.ps[1] = Point(9268.59, 212.265);
+ polygon.ps[2] = Point(9206.59, 212.265);
+ polygon.ps[3] = Point(9206.59, 150.265);
+ new ShapeRef(router, polygon, 548);
+
+ // shapeRef549
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14365, 282.265);
+ polygon.ps[1] = Point(14365, 344.265);
+ polygon.ps[2] = Point(14303, 344.265);
+ polygon.ps[3] = Point(14303, 282.265);
+ new ShapeRef(router, polygon, 549);
+
+ // shapeRef550
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14002, 282.265);
+ polygon.ps[1] = Point(14002, 344.265);
+ polygon.ps[2] = Point(13940, 344.265);
+ polygon.ps[3] = Point(13940, 282.265);
+ new ShapeRef(router, polygon, 550);
+
+ // shapeRef551
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13672, 282.265);
+ polygon.ps[1] = Point(13672, 344.265);
+ polygon.ps[2] = Point(13610, 344.265);
+ polygon.ps[3] = Point(13610, 282.265);
+ new ShapeRef(router, polygon, 551);
+
+ // shapeRef552
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13231, 282.265);
+ polygon.ps[1] = Point(13231, 344.265);
+ polygon.ps[2] = Point(13169, 344.265);
+ polygon.ps[3] = Point(13169, 282.265);
+ new ShapeRef(router, polygon, 552);
+
+ // shapeRef553
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12821.5, 282.265);
+ polygon.ps[1] = Point(12821.5, 344.265);
+ polygon.ps[2] = Point(12759.5, 344.265);
+ polygon.ps[3] = Point(12759.5, 282.265);
+ new ShapeRef(router, polygon, 553);
+
+ // shapeRef554
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14398, 150.265);
+ polygon.ps[1] = Point(14398, 212.265);
+ polygon.ps[2] = Point(14336, 212.265);
+ polygon.ps[3] = Point(14336, 150.265);
+ new ShapeRef(router, polygon, 554);
+
+ // shapeRef555
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13804, 150.265);
+ polygon.ps[1] = Point(13804, 212.265);
+ polygon.ps[2] = Point(13742, 212.265);
+ polygon.ps[3] = Point(13742, 150.265);
+ new ShapeRef(router, polygon, 555);
+
+ // shapeRef556
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12953.5, 150.265);
+ polygon.ps[1] = Point(12953.5, 212.265);
+ polygon.ps[2] = Point(12891.5, 212.265);
+ polygon.ps[3] = Point(12891.5, 150.265);
+ new ShapeRef(router, polygon, 556);
+
+ // shapeRef557
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12318.1, 282.265);
+ polygon.ps[1] = Point(12318.1, 344.265);
+ polygon.ps[2] = Point(12256.1, 344.265);
+ polygon.ps[3] = Point(12256.1, 282.265);
+ new ShapeRef(router, polygon, 557);
+
+ // shapeRef558
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12054.1, 282.265);
+ polygon.ps[1] = Point(12054.1, 344.265);
+ polygon.ps[2] = Point(11992.1, 344.265);
+ polygon.ps[3] = Point(11992.1, 282.265);
+ new ShapeRef(router, polygon, 558);
+
+ // shapeRef559
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11856.1, 282.265);
+ polygon.ps[1] = Point(11856.1, 344.265);
+ polygon.ps[2] = Point(11794.1, 344.265);
+ polygon.ps[3] = Point(11794.1, 282.265);
+ new ShapeRef(router, polygon, 559);
+
+ // shapeRef560
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11592.1, 282.265);
+ polygon.ps[1] = Point(11592.1, 344.265);
+ polygon.ps[2] = Point(11530.1, 344.265);
+ polygon.ps[3] = Point(11530.1, 282.265);
+ new ShapeRef(router, polygon, 560);
+
+ // shapeRef561
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11302.2, 282.265);
+ polygon.ps[1] = Point(11302.2, 344.265);
+ polygon.ps[2] = Point(11240.2, 344.265);
+ polygon.ps[3] = Point(11240.2, 282.265);
+ new ShapeRef(router, polygon, 561);
+
+ // shapeRef562
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11005.2, 282.265);
+ polygon.ps[1] = Point(11005.2, 344.265);
+ polygon.ps[2] = Point(10943.2, 344.265);
+ polygon.ps[3] = Point(10943.2, 282.265);
+ new ShapeRef(router, polygon, 562);
+
+ // shapeRef563
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10807.2, 282.265);
+ polygon.ps[1] = Point(10807.2, 344.265);
+ polygon.ps[2] = Point(10745.2, 344.265);
+ polygon.ps[3] = Point(10745.2, 282.265);
+ new ShapeRef(router, polygon, 563);
+
+ // shapeRef564
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10487.9, 282.265);
+ polygon.ps[1] = Point(10487.9, 344.265);
+ polygon.ps[2] = Point(10425.9, 344.265);
+ polygon.ps[3] = Point(10425.9, 282.265);
+ new ShapeRef(router, polygon, 564);
+
+ // shapeRef565
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9947.69, 282.265);
+ polygon.ps[1] = Point(9947.69, 344.265);
+ polygon.ps[2] = Point(9885.69, 344.265);
+ polygon.ps[3] = Point(9885.69, 282.265);
+ new ShapeRef(router, polygon, 565);
+
+ // shapeRef566
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9499.59, 282.265);
+ polygon.ps[1] = Point(9499.59, 344.265);
+ polygon.ps[2] = Point(9437.59, 344.265);
+ polygon.ps[3] = Point(9437.59, 282.265);
+ new ShapeRef(router, polygon, 566);
+
+ // shapeRef567
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16786.8, 5900.59);
+ polygon.ps[1] = Point(16786.8, 5962.59);
+ polygon.ps[2] = Point(16724.8, 5962.59);
+ polygon.ps[3] = Point(16724.8, 5900.59);
+ new ShapeRef(router, polygon, 567);
+
+ // shapeRef568
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3330, 7328.4);
+ polygon.ps[1] = Point(3330, 7390.4);
+ polygon.ps[2] = Point(3268, 7390.4);
+ polygon.ps[3] = Point(3268, 7328.4);
+ new ShapeRef(router, polygon, 568);
+
+ // shapeRef569
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12562.5, 8449.99);
+ polygon.ps[1] = Point(12562.5, 8511.99);
+ polygon.ps[2] = Point(12500.5, 8511.99);
+ polygon.ps[3] = Point(12500.5, 8449.99);
+ new ShapeRef(router, polygon, 569);
+
+ // shapeRef570
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12054.1, 7031.4);
+ polygon.ps[1] = Point(12054.1, 7093.4);
+ polygon.ps[2] = Point(11992.1, 7093.4);
+ polygon.ps[3] = Point(11992.1, 7031.4);
+ new ShapeRef(router, polygon, 570);
+
+ // shapeRef571
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(129, 8383.99);
+ polygon.ps[1] = Point(129, 8445.99);
+ polygon.ps[2] = Point(67, 8445.99);
+ polygon.ps[3] = Point(67, 8383.99);
+ new ShapeRef(router, polygon, 571);
+
+ // shapeRef572
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(129, 7911.79);
+ polygon.ps[1] = Point(129, 7973.79);
+ polygon.ps[2] = Point(67, 7973.79);
+ polygon.ps[3] = Point(67, 7911.79);
+ new ShapeRef(router, polygon, 572);
+
+ // shapeRef573
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(129, 7394.4);
+ polygon.ps[1] = Point(129, 7456.4);
+ polygon.ps[2] = Point(67, 7456.4);
+ polygon.ps[3] = Point(67, 7394.4);
+ new ShapeRef(router, polygon, 573);
+
+ // shapeRef574
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15270.5, 12096.3);
+ polygon.ps[1] = Point(15270.5, 12158.3);
+ polygon.ps[2] = Point(15208.5, 12158.3);
+ polygon.ps[3] = Point(15208.5, 12096.3);
+ new ShapeRef(router, polygon, 574);
+
+ // shapeRef575
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14431, 12096.3);
+ polygon.ps[1] = Point(14431, 12158.3);
+ polygon.ps[2] = Point(14369, 12158.3);
+ polygon.ps[3] = Point(14369, 12096.3);
+ new ShapeRef(router, polygon, 575);
+
+ // shapeRef576
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16753.8, 11601.9);
+ polygon.ps[1] = Point(16753.8, 11663.9);
+ polygon.ps[2] = Point(16691.8, 11663.9);
+ polygon.ps[3] = Point(16691.8, 11601.9);
+ new ShapeRef(router, polygon, 576);
+
+ // shapeRef577
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16493.6, 11601.9);
+ polygon.ps[1] = Point(16493.6, 11663.9);
+ polygon.ps[2] = Point(16431.6, 11663.9);
+ polygon.ps[3] = Point(16431.6, 11601.9);
+ new ShapeRef(router, polygon, 577);
+
+ // shapeRef578
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13870, 3864.51);
+ polygon.ps[1] = Point(13870, 3926.51);
+ polygon.ps[2] = Point(13808, 3926.51);
+ polygon.ps[3] = Point(13808, 3864.51);
+ new ShapeRef(router, polygon, 578);
+
+ // shapeRef579
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16621.8, 9578.42);
+ polygon.ps[1] = Point(16621.8, 9640.42);
+ polygon.ps[2] = Point(16559.8, 9640.42);
+ polygon.ps[3] = Point(16559.8, 9578.42);
+ new ShapeRef(router, polygon, 579);
+
+ // shapeRef580
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17838.5, 11634.9);
+ polygon.ps[1] = Point(17838.5, 11696.9);
+ polygon.ps[2] = Point(17776.5, 11696.9);
+ polygon.ps[3] = Point(17776.5, 11634.9);
+ new ShapeRef(router, polygon, 580);
+
+ // shapeRef581
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17083.8, 11634.9);
+ polygon.ps[1] = Point(17083.8, 11696.9);
+ polygon.ps[2] = Point(17021.8, 11696.9);
+ polygon.ps[3] = Point(17021.8, 11634.9);
+ new ShapeRef(router, polygon, 581);
+
+ // shapeRef582
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17838.5, 11081.6);
+ polygon.ps[1] = Point(17838.5, 11143.6);
+ polygon.ps[2] = Point(17776.5, 11143.6);
+ polygon.ps[3] = Point(17776.5, 11081.6);
+ new ShapeRef(router, polygon, 582);
+
+ // shapeRef583
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17083.8, 11081.6);
+ polygon.ps[1] = Point(17083.8, 11143.6);
+ polygon.ps[2] = Point(17021.8, 11143.6);
+ polygon.ps[3] = Point(17021.8, 11081.6);
+ new ShapeRef(router, polygon, 583);
+
+ // shapeRef584
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17838.5, 10717.3);
+ polygon.ps[1] = Point(17838.5, 10779.3);
+ polygon.ps[2] = Point(17776.5, 10779.3);
+ polygon.ps[3] = Point(17776.5, 10717.3);
+ new ShapeRef(router, polygon, 584);
+
+ // shapeRef585
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17083.8, 10717.3);
+ polygon.ps[1] = Point(17083.8, 10779.3);
+ polygon.ps[2] = Point(17021.8, 10779.3);
+ polygon.ps[3] = Point(17021.8, 10717.3);
+ new ShapeRef(router, polygon, 585);
+
+ // shapeRef586
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17838.5, 10440);
+ polygon.ps[1] = Point(17838.5, 10502);
+ polygon.ps[2] = Point(17776.5, 10502);
+ polygon.ps[3] = Point(17776.5, 10440);
+ new ShapeRef(router, polygon, 586);
+
+ // shapeRef587
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17083.8, 10440);
+ polygon.ps[1] = Point(17083.8, 10502);
+ polygon.ps[2] = Point(17021.8, 10502);
+ polygon.ps[3] = Point(17021.8, 10440);
+ new ShapeRef(router, polygon, 587);
+
+ // shapeRef588
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17838.5, 10209);
+ polygon.ps[1] = Point(17838.5, 10271);
+ polygon.ps[2] = Point(17776.5, 10271);
+ polygon.ps[3] = Point(17776.5, 10209);
+ new ShapeRef(router, polygon, 588);
+
+ // shapeRef589
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17083.8, 10209);
+ polygon.ps[1] = Point(17083.8, 10271);
+ polygon.ps[2] = Point(17021.8, 10271);
+ polygon.ps[3] = Point(17021.8, 10209);
+ new ShapeRef(router, polygon, 589);
+
+ // shapeRef590
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16885.8, 10209);
+ polygon.ps[1] = Point(16885.8, 10271);
+ polygon.ps[2] = Point(16823.8, 10271);
+ polygon.ps[3] = Point(16823.8, 10209);
+ new ShapeRef(router, polygon, 590);
+
+ // shapeRef591
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16885.8, 9578.42);
+ polygon.ps[1] = Point(16885.8, 9640.42);
+ polygon.ps[2] = Point(16823.8, 9640.42);
+ polygon.ps[3] = Point(16823.8, 9578.42);
+ new ShapeRef(router, polygon, 591);
+
+ // shapeRef592
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16885.8, 9083.42);
+ polygon.ps[1] = Point(16885.8, 9145.42);
+ polygon.ps[2] = Point(16823.8, 9145.42);
+ polygon.ps[3] = Point(16823.8, 9083.42);
+ new ShapeRef(router, polygon, 592);
+
+ // shapeRef593
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16885.8, 8449.99);
+ polygon.ps[1] = Point(16885.8, 8511.99);
+ polygon.ps[2] = Point(16823.8, 8511.99);
+ polygon.ps[3] = Point(16823.8, 8449.99);
+ new ShapeRef(router, polygon, 593);
+
+ // shapeRef594
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16885.8, 7878.79);
+ polygon.ps[1] = Point(16885.8, 7940.79);
+ polygon.ps[2] = Point(16823.8, 7940.79);
+ polygon.ps[3] = Point(16823.8, 7878.79);
+ new ShapeRef(router, polygon, 594);
+
+ // shapeRef595
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7796.29, 6219.51);
+ polygon.ps[1] = Point(7796.29, 6281.51);
+ polygon.ps[2] = Point(7734.29, 6281.51);
+ polygon.ps[3] = Point(7734.29, 6219.51);
+ new ShapeRef(router, polygon, 595);
+
+ // shapeRef596
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8159.29, 6219.51);
+ polygon.ps[1] = Point(8159.29, 6281.51);
+ polygon.ps[2] = Point(8097.29, 6281.51);
+ polygon.ps[3] = Point(8097.29, 6219.51);
+ new ShapeRef(router, polygon, 596);
+
+ // shapeRef597
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8649.29, 6219.51);
+ polygon.ps[1] = Point(8649.29, 6281.51);
+ polygon.ps[2] = Point(8587.29, 6281.51);
+ polygon.ps[3] = Point(8587.29, 6219.51);
+ new ShapeRef(router, polygon, 597);
+
+ // shapeRef598
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9301.59, 6219.51);
+ polygon.ps[1] = Point(9301.59, 6281.51);
+ polygon.ps[2] = Point(9239.59, 6281.51);
+ polygon.ps[3] = Point(9239.59, 6219.51);
+ new ShapeRef(router, polygon, 598);
+
+ // shapeRef599
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9815.69, 6219.51);
+ polygon.ps[1] = Point(9815.69, 6281.51);
+ polygon.ps[2] = Point(9753.69, 6281.51);
+ polygon.ps[3] = Point(9753.69, 6219.51);
+ new ShapeRef(router, polygon, 599);
+
+ // shapeRef600
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6814.1, 8644.22);
+ polygon.ps[1] = Point(6814.1, 8706.22);
+ polygon.ps[2] = Point(6752.1, 8706.22);
+ polygon.ps[3] = Point(6752.1, 8644.22);
+ new ShapeRef(router, polygon, 600);
+
+ // shapeRef601
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6814.1, 8284.99);
+ polygon.ps[1] = Point(6814.1, 8346.99);
+ polygon.ps[2] = Point(6752.1, 8346.99);
+ polygon.ps[3] = Point(6752.1, 8284.99);
+ new ShapeRef(router, polygon, 601);
+
+ // shapeRef602
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6583.1, 10684.3);
+ polygon.ps[1] = Point(6583.1, 10746.3);
+ polygon.ps[2] = Point(6521.1, 10746.3);
+ polygon.ps[3] = Point(6521.1, 10684.3);
+ new ShapeRef(router, polygon, 602);
+
+ // shapeRef603
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6583.1, 10374);
+ polygon.ps[1] = Point(6583.1, 10436);
+ polygon.ps[2] = Point(6521.1, 10436);
+ polygon.ps[3] = Point(6521.1, 10374);
+ new ShapeRef(router, polygon, 603);
+
+ // shapeRef604
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6583.1, 9116.42);
+ polygon.ps[1] = Point(6583.1, 9178.42);
+ polygon.ps[2] = Point(6521.1, 9178.42);
+ polygon.ps[3] = Point(6521.1, 9116.42);
+ new ShapeRef(router, polygon, 604);
+
+ // shapeRef605
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6583.1, 8644.22);
+ polygon.ps[1] = Point(6583.1, 8706.22);
+ polygon.ps[2] = Point(6521.1, 8706.22);
+ polygon.ps[3] = Point(6521.1, 8644.22);
+ new ShapeRef(router, polygon, 605);
+
+ // shapeRef606
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7012.1, 7614.79);
+ polygon.ps[1] = Point(7012.1, 7676.79);
+ polygon.ps[2] = Point(6950.1, 7676.79);
+ polygon.ps[3] = Point(6950.1, 7614.79);
+ new ShapeRef(router, polygon, 606);
+
+ // shapeRef607
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7243.1, 10275);
+ polygon.ps[1] = Point(7243.1, 10337);
+ polygon.ps[2] = Point(7181.1, 10337);
+ polygon.ps[3] = Point(7181.1, 10275);
+ new ShapeRef(router, polygon, 607);
+
+ // shapeRef608
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7243.1, 9912.02);
+ polygon.ps[1] = Point(7243.1, 9974.02);
+ polygon.ps[2] = Point(7181.1, 9974.02);
+ polygon.ps[3] = Point(7181.1, 9912.02);
+ new ShapeRef(router, polygon, 608);
+
+ // shapeRef609
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7243.1, 8548.99);
+ polygon.ps[1] = Point(7243.1, 8610.99);
+ polygon.ps[2] = Point(7181.1, 8610.99);
+ polygon.ps[3] = Point(7181.1, 8548.99);
+ new ShapeRef(router, polygon, 609);
+
+ // shapeRef610
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7243.1, 8142.79);
+ polygon.ps[1] = Point(7243.1, 8204.79);
+ polygon.ps[2] = Point(7181.1, 8204.79);
+ polygon.ps[3] = Point(7181.1, 8142.79);
+ new ShapeRef(router, polygon, 610);
+
+ // shapeRef611
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6253.1, 10684.3);
+ polygon.ps[1] = Point(6253.1, 10746.3);
+ polygon.ps[2] = Point(6191.1, 10746.3);
+ polygon.ps[3] = Point(6191.1, 10684.3);
+ new ShapeRef(router, polygon, 611);
+
+ // shapeRef612
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6253.1, 10374);
+ polygon.ps[1] = Point(6253.1, 10436);
+ polygon.ps[2] = Point(6191.1, 10436);
+ polygon.ps[3] = Point(6191.1, 10374);
+ new ShapeRef(router, polygon, 612);
+
+ // shapeRef613
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6253.1, 10077);
+ polygon.ps[1] = Point(6253.1, 10139);
+ polygon.ps[2] = Point(6191.1, 10139);
+ polygon.ps[3] = Point(6191.1, 10077);
+ new ShapeRef(router, polygon, 613);
+
+ // shapeRef614
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6253.1, 9512.42);
+ polygon.ps[1] = Point(6253.1, 9574.42);
+ polygon.ps[2] = Point(6191.1, 9574.42);
+ polygon.ps[3] = Point(6191.1, 9512.42);
+ new ShapeRef(router, polygon, 614);
+
+ // shapeRef615
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6253.1, 9116.42);
+ polygon.ps[1] = Point(6253.1, 9178.42);
+ polygon.ps[2] = Point(6191.1, 9178.42);
+ polygon.ps[3] = Point(6191.1, 9116.42);
+ new ShapeRef(router, polygon, 615);
+
+ // shapeRef616
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6253.1, 8644.22);
+ polygon.ps[1] = Point(6253.1, 8706.22);
+ polygon.ps[2] = Point(6191.1, 8706.22);
+ polygon.ps[3] = Point(6191.1, 8644.22);
+ new ShapeRef(router, polygon, 616);
+
+ // shapeRef617
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6253.1, 8284.99);
+ polygon.ps[1] = Point(6253.1, 8346.99);
+ polygon.ps[2] = Point(6191.1, 8346.99);
+ polygon.ps[3] = Point(6191.1, 8284.99);
+ new ShapeRef(router, polygon, 617);
+
+ // shapeRef618
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6253.1, 7779.79);
+ polygon.ps[1] = Point(6253.1, 7841.79);
+ polygon.ps[2] = Point(6191.1, 7841.79);
+ polygon.ps[3] = Point(6191.1, 7779.79);
+ new ShapeRef(router, polygon, 618);
+
+ // shapeRef619
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 10497.9);
+ polygon.ps[1] = Point(9089.03, 10537.9);
+ polygon.ps[2] = Point(9034.03, 10537.9);
+ polygon.ps[3] = Point(9034.03, 10497.9);
+ new ShapeRef(router, polygon, 619);
+
+ // shapeRef620
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 10497.9);
+ polygon.ps[1] = Point(9189.03, 10537.9);
+ polygon.ps[2] = Point(9134.03, 10537.9);
+ polygon.ps[3] = Point(9134.03, 10497.9);
+ new ShapeRef(router, polygon, 620);
+
+ // shapeRef621
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 10497.9);
+ polygon.ps[1] = Point(9289.03, 10537.9);
+ polygon.ps[2] = Point(9234.03, 10537.9);
+ polygon.ps[3] = Point(9234.03, 10497.9);
+ new ShapeRef(router, polygon, 621);
+
+ // shapeRef622
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 10497.9);
+ polygon.ps[1] = Point(9389.03, 10537.9);
+ polygon.ps[2] = Point(9334.03, 10537.9);
+ polygon.ps[3] = Point(9334.03, 10497.9);
+ new ShapeRef(router, polygon, 622);
+
+ // shapeRef623
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8456.29, 5316.67);
+ polygon.ps[1] = Point(8456.29, 5378.67);
+ polygon.ps[2] = Point(8394.29, 5378.67);
+ polygon.ps[3] = Point(8394.29, 5316.67);
+ new ShapeRef(router, polygon, 623);
+
+ // shapeRef624
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8126.29, 5316.67);
+ polygon.ps[1] = Point(8126.29, 5378.67);
+ polygon.ps[2] = Point(8064.29, 5378.67);
+ polygon.ps[3] = Point(8064.29, 5316.67);
+ new ShapeRef(router, polygon, 624);
+
+ // shapeRef625
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7796.29, 5316.67);
+ polygon.ps[1] = Point(7796.29, 5378.67);
+ polygon.ps[2] = Point(7734.29, 5378.67);
+ polygon.ps[3] = Point(7734.29, 5316.67);
+ new ShapeRef(router, polygon, 625);
+
+ // shapeRef626
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7342.1, 5316.67);
+ polygon.ps[1] = Point(7342.1, 5378.67);
+ polygon.ps[2] = Point(7280.1, 5378.67);
+ polygon.ps[3] = Point(7280.1, 5316.67);
+ new ShapeRef(router, polygon, 626);
+
+ // shapeRef627
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6946.1, 5316.67);
+ polygon.ps[1] = Point(6946.1, 5378.67);
+ polygon.ps[2] = Point(6884.1, 5378.67);
+ polygon.ps[3] = Point(6884.1, 5316.67);
+ new ShapeRef(router, polygon, 627);
+
+ // shapeRef628
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7507.1, 4095.51);
+ polygon.ps[1] = Point(7507.1, 4157.51);
+ polygon.ps[2] = Point(7445.1, 4157.51);
+ polygon.ps[3] = Point(7445.1, 4095.51);
+ new ShapeRef(router, polygon, 628);
+
+ // shapeRef629
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7012.1, 4095.51);
+ polygon.ps[1] = Point(7012.1, 4157.51);
+ polygon.ps[2] = Point(6950.1, 4157.51);
+ polygon.ps[3] = Point(6950.1, 4095.51);
+ new ShapeRef(router, polygon, 629);
+
+ // shapeRef630
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6484.1, 4095.51);
+ polygon.ps[1] = Point(6484.1, 4157.51);
+ polygon.ps[2] = Point(6422.1, 4157.51);
+ polygon.ps[3] = Point(6422.1, 4095.51);
+ new ShapeRef(router, polygon, 630);
+
+ // shapeRef631
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6187.1, 4095.51);
+ polygon.ps[1] = Point(6187.1, 4157.51);
+ polygon.ps[2] = Point(6125.1, 4157.51);
+ polygon.ps[3] = Point(6125.1, 4095.51);
+ new ShapeRef(router, polygon, 631);
+
+ // shapeRef632
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11889.1, 10506);
+ polygon.ps[1] = Point(11889.1, 10568);
+ polygon.ps[2] = Point(11827.1, 10568);
+ polygon.ps[3] = Point(11827.1, 10506);
+ new ShapeRef(router, polygon, 632);
+
+ // shapeRef633
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14266, 1945.29);
+ polygon.ps[1] = Point(14266, 2007.29);
+ polygon.ps[2] = Point(14204, 2007.29);
+ polygon.ps[3] = Point(14204, 1945.29);
+ new ShapeRef(router, polygon, 633);
+
+ // shapeRef634
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13771, 1945.29);
+ polygon.ps[1] = Point(13771, 2007.29);
+ polygon.ps[2] = Point(13709, 2007.29);
+ polygon.ps[3] = Point(13709, 1945.29);
+ new ShapeRef(router, polygon, 634);
+
+ // shapeRef635
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14695, 1780.29);
+ polygon.ps[1] = Point(14695, 1842.29);
+ polygon.ps[2] = Point(14633, 1842.29);
+ polygon.ps[3] = Point(14633, 1780.29);
+ new ShapeRef(router, polygon, 635);
+
+ // shapeRef636
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14497, 1579.29);
+ polygon.ps[1] = Point(14497, 1641.29);
+ polygon.ps[2] = Point(14435, 1641.29);
+ polygon.ps[3] = Point(14435, 1579.29);
+ new ShapeRef(router, polygon, 636);
+
+ // shapeRef637
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13771, 1579.29);
+ polygon.ps[1] = Point(13771, 1641.29);
+ polygon.ps[2] = Point(13709, 1641.29);
+ polygon.ps[3] = Point(13709, 1579.29);
+ new ShapeRef(router, polygon, 637);
+
+ // shapeRef638
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14167, 1579.29);
+ polygon.ps[1] = Point(14167, 1641.29);
+ polygon.ps[2] = Point(14105, 1641.29);
+ polygon.ps[3] = Point(14105, 1579.29);
+ new ShapeRef(router, polygon, 638);
+
+ // shapeRef639
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13771, 1780.29);
+ polygon.ps[1] = Point(13771, 1842.29);
+ polygon.ps[2] = Point(13709, 1842.29);
+ polygon.ps[3] = Point(13709, 1780.29);
+ new ShapeRef(router, polygon, 639);
+
+ // shapeRef640
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12285.1, 3402.51);
+ polygon.ps[1] = Point(12285.1, 3464.51);
+ polygon.ps[2] = Point(12223.1, 3464.51);
+ polygon.ps[3] = Point(12223.1, 3402.51);
+ new ShapeRef(router, polygon, 640);
+
+ // shapeRef641
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11493.1, 2812.29);
+ polygon.ps[1] = Point(11493.1, 2874.29);
+ polygon.ps[2] = Point(11431.1, 2874.29);
+ polygon.ps[3] = Point(11431.1, 2812.29);
+ new ShapeRef(router, polygon, 641);
+
+ // shapeRef642
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11823.1, 2812.29);
+ polygon.ps[1] = Point(11823.1, 2874.29);
+ polygon.ps[2] = Point(11761.1, 2874.29);
+ polygon.ps[3] = Point(11761.1, 2812.29);
+ new ShapeRef(router, polygon, 642);
+
+ // shapeRef643
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11493.1, 3402.51);
+ polygon.ps[1] = Point(11493.1, 3464.51);
+ polygon.ps[2] = Point(11431.1, 3464.51);
+ polygon.ps[3] = Point(11431.1, 3402.51);
+ new ShapeRef(router, polygon, 643);
+
+ // shapeRef644
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11823.1, 3402.51);
+ polygon.ps[1] = Point(11823.1, 3464.51);
+ polygon.ps[2] = Point(11761.1, 3464.51);
+ polygon.ps[3] = Point(11761.1, 3402.51);
+ new ShapeRef(router, polygon, 644);
+
+ // shapeRef645
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12021.1, 3402.51);
+ polygon.ps[1] = Point(12021.1, 3464.51);
+ polygon.ps[2] = Point(11959.1, 3464.51);
+ polygon.ps[3] = Point(11959.1, 3402.51);
+ new ShapeRef(router, polygon, 645);
+
+ // shapeRef646
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10675.2, 1912.29);
+ polygon.ps[1] = Point(10675.2, 1974.29);
+ polygon.ps[2] = Point(10613.2, 1974.29);
+ polygon.ps[3] = Point(10613.2, 1912.29);
+ new ShapeRef(router, polygon, 646);
+
+ // shapeRef647
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10675.2, 2152.29);
+ polygon.ps[1] = Point(10675.2, 2214.29);
+ polygon.ps[2] = Point(10613.2, 2214.29);
+ polygon.ps[3] = Point(10613.2, 2152.29);
+ new ShapeRef(router, polygon, 647);
+
+ // shapeRef648
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10675.2, 2416.29);
+ polygon.ps[1] = Point(10675.2, 2478.29);
+ polygon.ps[2] = Point(10613.2, 2478.29);
+ polygon.ps[3] = Point(10613.2, 2416.29);
+ new ShapeRef(router, polygon, 648);
+
+ // shapeRef649
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10675.2, 2680.29);
+ polygon.ps[1] = Point(10675.2, 2742.29);
+ polygon.ps[2] = Point(10613.2, 2742.29);
+ polygon.ps[3] = Point(10613.2, 2680.29);
+ new ShapeRef(router, polygon, 649);
+
+ // shapeRef650
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10675.2, 3274.29);
+ polygon.ps[1] = Point(10675.2, 3336.29);
+ polygon.ps[2] = Point(10613.2, 3336.29);
+ polygon.ps[3] = Point(10613.2, 3274.29);
+ new ShapeRef(router, polygon, 650);
+
+ // shapeRef651
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10972.2, 3274.29);
+ polygon.ps[1] = Point(10972.2, 3336.29);
+ polygon.ps[2] = Point(10910.2, 3336.29);
+ polygon.ps[3] = Point(10910.2, 3274.29);
+ new ShapeRef(router, polygon, 651);
+
+ // shapeRef652
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11203.2, 3274.29);
+ polygon.ps[1] = Point(11203.2, 3336.29);
+ polygon.ps[2] = Point(11141.2, 3336.29);
+ polygon.ps[3] = Point(11141.2, 3274.29);
+ new ShapeRef(router, polygon, 652);
+
+ // shapeRef653
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10046.7, 3076.29);
+ polygon.ps[1] = Point(10046.7, 3138.29);
+ polygon.ps[2] = Point(9984.69, 3138.29);
+ polygon.ps[3] = Point(9984.69, 3076.29);
+ new ShapeRef(router, polygon, 653);
+
+ // shapeRef654
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10675.2, 3076.29);
+ polygon.ps[1] = Point(10675.2, 3138.29);
+ polygon.ps[2] = Point(10613.2, 3138.29);
+ polygon.ps[3] = Point(10613.2, 3076.29);
+ new ShapeRef(router, polygon, 654);
+
+ // shapeRef655
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10972.2, 3076.29);
+ polygon.ps[1] = Point(10972.2, 3138.29);
+ polygon.ps[2] = Point(10910.2, 3138.29);
+ polygon.ps[3] = Point(10910.2, 3076.29);
+ new ShapeRef(router, polygon, 655);
+
+ // shapeRef656
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11203.2, 3076.29);
+ polygon.ps[1] = Point(11203.2, 3138.29);
+ polygon.ps[2] = Point(11141.2, 3138.29);
+ polygon.ps[3] = Point(11141.2, 3076.29);
+ new ShapeRef(router, polygon, 656);
+
+ // shapeRef657
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11493.1, 3076.29);
+ polygon.ps[1] = Point(11493.1, 3138.29);
+ polygon.ps[2] = Point(11431.1, 3138.29);
+ polygon.ps[3] = Point(11431.1, 3076.29);
+ new ShapeRef(router, polygon, 657);
+
+ // shapeRef658
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14101, 1216.29);
+ polygon.ps[1] = Point(14101, 1278.29);
+ polygon.ps[2] = Point(14039, 1278.29);
+ polygon.ps[3] = Point(14039, 1216.29);
+ new ShapeRef(router, polygon, 658);
+
+ // shapeRef659
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13738, 1216.29);
+ polygon.ps[1] = Point(13738, 1278.29);
+ polygon.ps[2] = Point(13676, 1278.29);
+ polygon.ps[3] = Point(13676, 1216.29);
+ new ShapeRef(router, polygon, 659);
+
+ // shapeRef660
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13231, 1216.29);
+ polygon.ps[1] = Point(13231, 1278.29);
+ polygon.ps[2] = Point(13169, 1278.29);
+ polygon.ps[3] = Point(13169, 1216.29);
+ new ShapeRef(router, polygon, 660);
+
+ // shapeRef661
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13231, 1480.29);
+ polygon.ps[1] = Point(13231, 1542.29);
+ polygon.ps[2] = Point(13169, 1542.29);
+ polygon.ps[3] = Point(13169, 1480.29);
+ new ShapeRef(router, polygon, 661);
+
+ // shapeRef662
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13231, 1780.29);
+ polygon.ps[1] = Point(13231, 1842.29);
+ polygon.ps[2] = Point(13169, 1842.29);
+ polygon.ps[3] = Point(13169, 1780.29);
+ new ShapeRef(router, polygon, 662);
+
+ // shapeRef663
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11823.1, 3076.29);
+ polygon.ps[1] = Point(11823.1, 3138.29);
+ polygon.ps[2] = Point(11761.1, 3138.29);
+ polygon.ps[3] = Point(11761.1, 3076.29);
+ new ShapeRef(router, polygon, 663);
+
+ // shapeRef664
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12021.1, 3076.29);
+ polygon.ps[1] = Point(12021.1, 3138.29);
+ polygon.ps[2] = Point(11959.1, 3138.29);
+ polygon.ps[3] = Point(11959.1, 3076.29);
+ new ShapeRef(router, polygon, 664);
+
+ // shapeRef665
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12021.1, 2614.29);
+ polygon.ps[1] = Point(12021.1, 2676.29);
+ polygon.ps[2] = Point(11959.1, 2676.29);
+ polygon.ps[3] = Point(11959.1, 2614.29);
+ new ShapeRef(router, polygon, 665);
+
+ // shapeRef666
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12021.1, 2449.29);
+ polygon.ps[1] = Point(12021.1, 2511.29);
+ polygon.ps[2] = Point(11959.1, 2511.29);
+ polygon.ps[3] = Point(11959.1, 2449.29);
+ new ShapeRef(router, polygon, 666);
+
+ // shapeRef667
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12021.1, 2185.29);
+ polygon.ps[1] = Point(12021.1, 2247.29);
+ polygon.ps[2] = Point(11959.1, 2247.29);
+ polygon.ps[3] = Point(11959.1, 2185.29);
+ new ShapeRef(router, polygon, 667);
+
+ // shapeRef668
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(294, 10717.3);
+ polygon.ps[1] = Point(294, 10779.3);
+ polygon.ps[2] = Point(232, 10779.3);
+ polygon.ps[3] = Point(232, 10717.3);
+ new ShapeRef(router, polygon, 668);
+
+ // shapeRef669
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(657, 10717.3);
+ polygon.ps[1] = Point(657, 10779.3);
+ polygon.ps[2] = Point(595, 10779.3);
+ polygon.ps[3] = Point(595, 10717.3);
+ new ShapeRef(router, polygon, 669);
+
+ // shapeRef670
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1449, 10717.3);
+ polygon.ps[1] = Point(1449, 10779.3);
+ polygon.ps[2] = Point(1387, 10779.3);
+ polygon.ps[3] = Point(1387, 10717.3);
+ new ShapeRef(router, polygon, 670);
+
+ // shapeRef671
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2076, 10717.3);
+ polygon.ps[1] = Point(2076, 10779.3);
+ polygon.ps[2] = Point(2014, 10779.3);
+ polygon.ps[3] = Point(2014, 10717.3);
+ new ShapeRef(router, polygon, 671);
+
+ // shapeRef672
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(294, 11667.9);
+ polygon.ps[1] = Point(294, 11729.9);
+ polygon.ps[2] = Point(232, 11729.9);
+ polygon.ps[3] = Point(232, 11667.9);
+ new ShapeRef(router, polygon, 672);
+
+ // shapeRef673
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(657, 11667.9);
+ polygon.ps[1] = Point(657, 11729.9);
+ polygon.ps[2] = Point(595, 11729.9);
+ polygon.ps[3] = Point(595, 11667.9);
+ new ShapeRef(router, polygon, 673);
+
+ // shapeRef674
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(294, 11114.6);
+ polygon.ps[1] = Point(294, 11176.6);
+ polygon.ps[2] = Point(232, 11176.6);
+ polygon.ps[3] = Point(232, 11114.6);
+ new ShapeRef(router, polygon, 674);
+
+ // shapeRef675
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(657, 11114.6);
+ polygon.ps[1] = Point(657, 11176.6);
+ polygon.ps[2] = Point(595, 11176.6);
+ polygon.ps[3] = Point(595, 11114.6);
+ new ShapeRef(router, polygon, 675);
+
+ // shapeRef676
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1251, 11114.6);
+ polygon.ps[1] = Point(1251, 11176.6);
+ polygon.ps[2] = Point(1189, 11176.6);
+ polygon.ps[3] = Point(1189, 11114.6);
+ new ShapeRef(router, polygon, 676);
+
+ // shapeRef677
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1779, 11114.6);
+ polygon.ps[1] = Point(1779, 11176.6);
+ polygon.ps[2] = Point(1717, 11176.6);
+ polygon.ps[3] = Point(1717, 11114.6);
+ new ShapeRef(router, polygon, 677);
+
+ // shapeRef678
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2439, 11114.6);
+ polygon.ps[1] = Point(2439, 11176.6);
+ polygon.ps[2] = Point(2377, 11176.6);
+ polygon.ps[3] = Point(2377, 11114.6);
+ new ShapeRef(router, polygon, 678);
+
+ // shapeRef679
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3066, 11114.6);
+ polygon.ps[1] = Point(3066, 11176.6);
+ polygon.ps[2] = Point(3004, 11176.6);
+ polygon.ps[3] = Point(3004, 11114.6);
+ new ShapeRef(router, polygon, 679);
+
+ // shapeRef680
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1020, 9677.42);
+ polygon.ps[1] = Point(1020, 9739.42);
+ polygon.ps[2] = Point(958, 9739.42);
+ polygon.ps[3] = Point(958, 9677.42);
+ new ShapeRef(router, polygon, 680);
+
+ // shapeRef681
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2142, 9677.42);
+ polygon.ps[1] = Point(2142, 9739.42);
+ polygon.ps[2] = Point(2080, 9739.42);
+ polygon.ps[3] = Point(2080, 9677.42);
+ new ShapeRef(router, polygon, 681);
+
+ // shapeRef682
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1020, 10308);
+ polygon.ps[1] = Point(1020, 10370);
+ polygon.ps[2] = Point(958, 10370);
+ polygon.ps[3] = Point(958, 10308);
+ new ShapeRef(router, polygon, 682);
+
+ // shapeRef683
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(492, 10176);
+ polygon.ps[1] = Point(492, 10238);
+ polygon.ps[2] = Point(430, 10238);
+ polygon.ps[3] = Point(430, 10176);
+ new ShapeRef(router, polygon, 683);
+
+ // shapeRef684
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1020, 10176);
+ polygon.ps[1] = Point(1020, 10238);
+ polygon.ps[2] = Point(958, 10238);
+ polygon.ps[3] = Point(958, 10176);
+ new ShapeRef(router, polygon, 684);
+
+ // shapeRef685
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1548, 10176);
+ polygon.ps[1] = Point(1548, 10238);
+ polygon.ps[2] = Point(1486, 10238);
+ polygon.ps[3] = Point(1486, 10176);
+ new ShapeRef(router, polygon, 685);
+
+ // shapeRef686
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2142, 10176);
+ polygon.ps[1] = Point(2142, 10238);
+ polygon.ps[2] = Point(2080, 10238);
+ polygon.ps[3] = Point(2080, 10176);
+ new ShapeRef(router, polygon, 686);
+
+ // shapeRef687
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10972.2, 6384.51);
+ polygon.ps[1] = Point(10972.2, 6446.51);
+ polygon.ps[2] = Point(10910.2, 6446.51);
+ polygon.ps[3] = Point(10910.2, 6384.51);
+ new ShapeRef(router, polygon, 687);
+
+ // shapeRef688
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10972.2, 5725.9);
+ polygon.ps[1] = Point(10972.2, 5787.9);
+ polygon.ps[2] = Point(10910.2, 5787.9);
+ polygon.ps[3] = Point(10910.2, 5725.9);
+ new ShapeRef(router, polygon, 688);
+
+ // shapeRef689
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10972.2, 5382.67);
+ polygon.ps[1] = Point(10972.2, 5444.67);
+ polygon.ps[2] = Point(10910.2, 5444.67);
+ polygon.ps[3] = Point(10910.2, 5382.67);
+ new ShapeRef(router, polygon, 689);
+
+ // shapeRef690
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10972.2, 5138.4);
+ polygon.ps[1] = Point(10972.2, 5200.4);
+ polygon.ps[2] = Point(10910.2, 5200.4);
+ polygon.ps[3] = Point(10910.2, 5138.4);
+ new ShapeRef(router, polygon, 690);
+
+ // shapeRef691
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10972.2, 4643.4);
+ polygon.ps[1] = Point(10972.2, 4705.4);
+ polygon.ps[2] = Point(10910.2, 4705.4);
+ polygon.ps[3] = Point(10910.2, 4643.4);
+ new ShapeRef(router, polygon, 691);
+
+ // shapeRef692
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11236.2, 5966.59);
+ polygon.ps[1] = Point(11236.2, 6028.59);
+ polygon.ps[2] = Point(11174.2, 6028.59);
+ polygon.ps[3] = Point(11174.2, 5966.59);
+ new ShapeRef(router, polygon, 692);
+
+ // shapeRef693
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11236.2, 6384.51);
+ polygon.ps[1] = Point(11236.2, 6446.51);
+ polygon.ps[2] = Point(11174.2, 6446.51);
+ polygon.ps[3] = Point(11174.2, 6384.51);
+ new ShapeRef(router, polygon, 693);
+
+ // shapeRef694
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11658.1, 6757.21);
+ polygon.ps[1] = Point(11658.1, 6819.21);
+ polygon.ps[2] = Point(11596.1, 6819.21);
+ polygon.ps[3] = Point(11596.1, 6757.21);
+ new ShapeRef(router, polygon, 694);
+
+ // shapeRef695
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10013.7, 6417.51);
+ polygon.ps[1] = Point(10013.7, 6479.51);
+ polygon.ps[2] = Point(9951.69, 6479.51);
+ polygon.ps[3] = Point(9951.69, 6417.51);
+ new ShapeRef(router, polygon, 695);
+
+ // shapeRef696
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10013.7, 6058.29);
+ polygon.ps[1] = Point(10013.7, 6120.29);
+ polygon.ps[2] = Point(9951.69, 6120.29);
+ polygon.ps[3] = Point(9951.69, 6058.29);
+ new ShapeRef(router, polygon, 696);
+
+ // shapeRef697
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10013.7, 4478.4);
+ polygon.ps[1] = Point(10013.7, 4540.4);
+ polygon.ps[2] = Point(9951.69, 4540.4);
+ polygon.ps[3] = Point(9951.69, 4478.4);
+ new ShapeRef(router, polygon, 697);
+
+ // shapeRef698
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10013.7, 3534.51);
+ polygon.ps[1] = Point(10013.7, 3596.51);
+ polygon.ps[2] = Point(9951.69, 3596.51);
+ polygon.ps[3] = Point(9951.69, 3534.51);
+ new ShapeRef(router, polygon, 698);
+
+ // shapeRef699
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11658.1, 6384.51);
+ polygon.ps[1] = Point(11658.1, 6446.51);
+ polygon.ps[2] = Point(11596.1, 6446.51);
+ polygon.ps[3] = Point(11596.1, 6384.51);
+ new ShapeRef(router, polygon, 699);
+
+ // shapeRef700
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11658.1, 5725.9);
+ polygon.ps[1] = Point(11658.1, 5787.9);
+ polygon.ps[2] = Point(11596.1, 5787.9);
+ polygon.ps[3] = Point(11596.1, 5725.9);
+ new ShapeRef(router, polygon, 700);
+
+ // shapeRef701
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11658.1, 5382.67);
+ polygon.ps[1] = Point(11658.1, 5444.67);
+ polygon.ps[2] = Point(11596.1, 5444.67);
+ polygon.ps[3] = Point(11596.1, 5382.67);
+ new ShapeRef(router, polygon, 701);
+
+ // shapeRef702
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11658.1, 5138.4);
+ polygon.ps[1] = Point(11658.1, 5200.4);
+ polygon.ps[2] = Point(11596.1, 5200.4);
+ polygon.ps[3] = Point(11596.1, 5138.4);
+ new ShapeRef(router, polygon, 702);
+
+ // shapeRef703
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11658.1, 4577.4);
+ polygon.ps[1] = Point(11658.1, 4639.4);
+ polygon.ps[2] = Point(11596.1, 4639.4);
+ polygon.ps[3] = Point(11596.1, 4577.4);
+ new ShapeRef(router, polygon, 703);
+
+ // shapeRef704
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11658.1, 3534.51);
+ polygon.ps[1] = Point(11658.1, 3596.51);
+ polygon.ps[2] = Point(11596.1, 3596.51);
+ polygon.ps[3] = Point(11596.1, 3534.51);
+ new ShapeRef(router, polygon, 704);
+
+ // shapeRef705
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11988.1, 5006.4);
+ polygon.ps[1] = Point(11988.1, 5068.4);
+ polygon.ps[2] = Point(11926.1, 5068.4);
+ polygon.ps[3] = Point(11926.1, 5006.4);
+ new ShapeRef(router, polygon, 705);
+
+ // shapeRef706
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12219.1, 3996.51);
+ polygon.ps[1] = Point(12219.1, 4058.51);
+ polygon.ps[2] = Point(12157.1, 4058.51);
+ polygon.ps[3] = Point(12157.1, 3996.51);
+ new ShapeRef(router, polygon, 706);
+
+ // shapeRef707
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12219.1, 5006.4);
+ polygon.ps[1] = Point(12219.1, 5068.4);
+ polygon.ps[2] = Point(12157.1, 5068.4);
+ polygon.ps[3] = Point(12157.1, 5006.4);
+ new ShapeRef(router, polygon, 707);
+
+ // shapeRef708
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12219.1, 3534.51);
+ polygon.ps[1] = Point(12219.1, 3596.51);
+ polygon.ps[2] = Point(12157.1, 3596.51);
+ polygon.ps[3] = Point(12157.1, 3534.51);
+ new ShapeRef(router, polygon, 708);
+
+ // shapeRef709
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12986.5, 3534.51);
+ polygon.ps[1] = Point(12986.5, 3596.51);
+ polygon.ps[2] = Point(12924.5, 3596.51);
+ polygon.ps[3] = Point(12924.5, 3534.51);
+ new ShapeRef(router, polygon, 709);
+
+ // shapeRef710
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17871.5, 2044.29);
+ polygon.ps[1] = Point(17871.5, 2106.29);
+ polygon.ps[2] = Point(17809.5, 2106.29);
+ polygon.ps[3] = Point(17809.5, 2044.29);
+ new ShapeRef(router, polygon, 710);
+
+ // shapeRef711
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17640.5, 2044.29);
+ polygon.ps[1] = Point(17640.5, 2106.29);
+ polygon.ps[2] = Point(17578.5, 2106.29);
+ polygon.ps[3] = Point(17578.5, 2044.29);
+ new ShapeRef(router, polygon, 711);
+
+ // shapeRef712
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17376.5, 2044.29);
+ polygon.ps[1] = Point(17376.5, 2106.29);
+ polygon.ps[2] = Point(17314.5, 2106.29);
+ polygon.ps[3] = Point(17314.5, 2044.29);
+ new ShapeRef(router, polygon, 712);
+
+ // shapeRef713
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17017.8, 2044.29);
+ polygon.ps[1] = Point(17017.8, 2106.29);
+ polygon.ps[2] = Point(16955.8, 2106.29);
+ polygon.ps[3] = Point(16955.8, 2044.29);
+ new ShapeRef(router, polygon, 713);
+
+ // shapeRef714
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16753.8, 2044.29);
+ polygon.ps[1] = Point(16753.8, 2106.29);
+ polygon.ps[2] = Point(16691.8, 2106.29);
+ polygon.ps[3] = Point(16691.8, 2044.29);
+ new ShapeRef(router, polygon, 714);
+
+ // shapeRef715
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16588.8, 2044.29);
+ polygon.ps[1] = Point(16588.8, 2106.29);
+ polygon.ps[2] = Point(16526.8, 2106.29);
+ polygon.ps[3] = Point(16526.8, 2044.29);
+ new ShapeRef(router, polygon, 715);
+
+ // shapeRef716
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16262.6, 2044.29);
+ polygon.ps[1] = Point(16262.6, 2106.29);
+ polygon.ps[2] = Point(16200.6, 2106.29);
+ polygon.ps[3] = Point(16200.6, 2044.29);
+ new ShapeRef(router, polygon, 716);
+
+ // shapeRef717
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15932.6, 2044.29);
+ polygon.ps[1] = Point(15932.6, 2106.29);
+ polygon.ps[2] = Point(15870.6, 2106.29);
+ polygon.ps[3] = Point(15870.6, 2044.29);
+ new ShapeRef(router, polygon, 717);
+
+ // shapeRef718
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15270.5, 2044.29);
+ polygon.ps[1] = Point(15270.5, 2106.29);
+ polygon.ps[2] = Point(15208.5, 2106.29);
+ polygon.ps[3] = Point(15208.5, 2044.29);
+ new ShapeRef(router, polygon, 718);
+
+ // shapeRef719
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15270.5, 1780.29);
+ polygon.ps[1] = Point(15270.5, 1842.29);
+ polygon.ps[2] = Point(15208.5, 1842.29);
+ polygon.ps[3] = Point(15208.5, 1780.29);
+ new ShapeRef(router, polygon, 719);
+
+ // shapeRef720
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18756.5, 10651.3);
+ polygon.ps[1] = Point(18756.5, 10713.3);
+ polygon.ps[2] = Point(18694.5, 10713.3);
+ polygon.ps[3] = Point(18694.5, 10651.3);
+ new ShapeRef(router, polygon, 720);
+
+ // shapeRef721
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18756.5, 10242);
+ polygon.ps[1] = Point(18756.5, 10304);
+ polygon.ps[2] = Point(18694.5, 10304);
+ polygon.ps[3] = Point(18694.5, 10242);
+ new ShapeRef(router, polygon, 721);
+
+ // shapeRef722
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18756.5, 9644.42);
+ polygon.ps[1] = Point(18756.5, 9706.42);
+ polygon.ps[2] = Point(18694.5, 9706.42);
+ polygon.ps[3] = Point(18694.5, 9644.42);
+ new ShapeRef(router, polygon, 722);
+
+ // shapeRef723
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18756.5, 9149.42);
+ polygon.ps[1] = Point(18756.5, 9211.42);
+ polygon.ps[2] = Point(18694.5, 9211.42);
+ polygon.ps[3] = Point(18694.5, 9149.42);
+ new ShapeRef(router, polygon, 723);
+
+ // shapeRef724
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18756.5, 8611.22);
+ polygon.ps[1] = Point(18756.5, 8673.22);
+ polygon.ps[2] = Point(18694.5, 8673.22);
+ polygon.ps[3] = Point(18694.5, 8611.22);
+ new ShapeRef(router, polygon, 724);
+
+ // shapeRef725
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18756.5, 8218.99);
+ polygon.ps[1] = Point(18756.5, 8280.99);
+ polygon.ps[2] = Point(18694.5, 8280.99);
+ polygon.ps[3] = Point(18694.5, 8218.99);
+ new ShapeRef(router, polygon, 725);
+
+ // shapeRef726
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18756.5, 7581.79);
+ polygon.ps[1] = Point(18756.5, 7643.79);
+ polygon.ps[2] = Point(18694.5, 7643.79);
+ polygon.ps[3] = Point(18694.5, 7581.79);
+ new ShapeRef(router, polygon, 726);
+
+ // shapeRef727
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18756.5, 6757.21);
+ polygon.ps[1] = Point(18756.5, 6819.21);
+ polygon.ps[2] = Point(18694.5, 6819.21);
+ polygon.ps[3] = Point(18694.5, 6757.21);
+ new ShapeRef(router, polygon, 727);
+
+ // shapeRef728
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3957, 394.265);
+ polygon.ps[1] = Point(3957, 456.265);
+ polygon.ps[2] = Point(3895, 456.265);
+ polygon.ps[3] = Point(3895, 394.265);
+ new ShapeRef(router, polygon, 728);
+
+ // shapeRef729
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4254, 394.265);
+ polygon.ps[1] = Point(4254, 456.265);
+ polygon.ps[2] = Point(4192, 456.265);
+ polygon.ps[3] = Point(4192, 394.265);
+ new ShapeRef(router, polygon, 729);
+
+ // shapeRef730
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4584, 394.265);
+ polygon.ps[1] = Point(4584, 456.265);
+ polygon.ps[2] = Point(4522, 456.265);
+ polygon.ps[3] = Point(4522, 394.265);
+ new ShapeRef(router, polygon, 730);
+
+ // shapeRef731
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4947, 394.265);
+ polygon.ps[1] = Point(4947, 456.265);
+ polygon.ps[2] = Point(4885, 456.265);
+ polygon.ps[3] = Point(4885, 394.265);
+ new ShapeRef(router, polygon, 731);
+
+ // shapeRef732
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5659.1, 394.265);
+ polygon.ps[1] = Point(5659.1, 456.265);
+ polygon.ps[2] = Point(5597.1, 456.265);
+ polygon.ps[3] = Point(5597.1, 394.265);
+ new ShapeRef(router, polygon, 732);
+
+ // shapeRef733
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5277, 282.265);
+ polygon.ps[1] = Point(5277, 344.265);
+ polygon.ps[2] = Point(5215, 344.265);
+ polygon.ps[3] = Point(5215, 282.265);
+ new ShapeRef(router, polygon, 733);
+
+ // shapeRef734
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5659.1, 282.265);
+ polygon.ps[1] = Point(5659.1, 344.265);
+ polygon.ps[2] = Point(5597.1, 344.265);
+ polygon.ps[3] = Point(5597.1, 282.265);
+ new ShapeRef(router, polygon, 734);
+
+ // shapeRef735
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5857.1, 282.265);
+ polygon.ps[1] = Point(5857.1, 344.265);
+ polygon.ps[2] = Point(5795.1, 344.265);
+ polygon.ps[3] = Point(5795.1, 282.265);
+ new ShapeRef(router, polygon, 735);
+
+ // shapeRef736
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6121.1, 282.265);
+ polygon.ps[1] = Point(6121.1, 344.265);
+ polygon.ps[2] = Point(6059.1, 344.265);
+ polygon.ps[3] = Point(6059.1, 282.265);
+ new ShapeRef(router, polygon, 736);
+
+ // shapeRef737
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6319.1, 282.265);
+ polygon.ps[1] = Point(6319.1, 344.265);
+ polygon.ps[2] = Point(6257.1, 344.265);
+ polygon.ps[3] = Point(6257.1, 282.265);
+ new ShapeRef(router, polygon, 737);
+
+ // shapeRef738
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6616.1, 282.265);
+ polygon.ps[1] = Point(6616.1, 344.265);
+ polygon.ps[2] = Point(6554.1, 344.265);
+ polygon.ps[3] = Point(6554.1, 282.265);
+ new ShapeRef(router, polygon, 738);
+
+ // shapeRef739
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6880.1, 282.265);
+ polygon.ps[1] = Point(6880.1, 344.265);
+ polygon.ps[2] = Point(6818.1, 344.265);
+ polygon.ps[3] = Point(6818.1, 282.265);
+ new ShapeRef(router, polygon, 739);
+
+ // shapeRef740
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7210.1, 282.265);
+ polygon.ps[1] = Point(7210.1, 344.265);
+ polygon.ps[2] = Point(7148.1, 344.265);
+ polygon.ps[3] = Point(7148.1, 282.265);
+ new ShapeRef(router, polygon, 740);
+
+ // shapeRef741
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7573.1, 282.265);
+ polygon.ps[1] = Point(7573.1, 344.265);
+ polygon.ps[2] = Point(7511.1, 344.265);
+ polygon.ps[3] = Point(7511.1, 282.265);
+ new ShapeRef(router, polygon, 741);
+
+ // shapeRef742
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12186.1, 11984.3);
+ polygon.ps[1] = Point(12186.1, 12046.3);
+ polygon.ps[2] = Point(12124.1, 12046.3);
+ polygon.ps[3] = Point(12124.1, 11984.3);
+ new ShapeRef(router, polygon, 742);
+
+ // shapeRef743
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11889.1, 11984.3);
+ polygon.ps[1] = Point(11889.1, 12046.3);
+ polygon.ps[2] = Point(11827.1, 12046.3);
+ polygon.ps[3] = Point(11827.1, 11984.3);
+ new ShapeRef(router, polygon, 743);
+
+ // shapeRef744
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11889.1, 11355.8);
+ polygon.ps[1] = Point(11889.1, 11417.8);
+ polygon.ps[2] = Point(11827.1, 11417.8);
+ polygon.ps[3] = Point(11827.1, 11355.8);
+ new ShapeRef(router, polygon, 744);
+
+ // shapeRef745
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11460.1, 11984.3);
+ polygon.ps[1] = Point(11460.1, 12046.3);
+ polygon.ps[2] = Point(11398.1, 12046.3);
+ polygon.ps[3] = Point(11398.1, 11984.3);
+ new ShapeRef(router, polygon, 745);
+
+ // shapeRef746
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11460.1, 11355.8);
+ polygon.ps[1] = Point(11460.1, 11417.8);
+ polygon.ps[2] = Point(11398.1, 11417.8);
+ polygon.ps[3] = Point(11398.1, 11355.8);
+ new ShapeRef(router, polygon, 746);
+
+ // shapeRef747
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11460.1, 10916.6);
+ polygon.ps[1] = Point(11460.1, 10978.6);
+ polygon.ps[2] = Point(11398.1, 10978.6);
+ polygon.ps[3] = Point(11398.1, 10916.6);
+ new ShapeRef(router, polygon, 747);
+
+ // shapeRef748
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11460.1, 10506);
+ polygon.ps[1] = Point(11460.1, 10568);
+ polygon.ps[2] = Point(11398.1, 10568);
+ polygon.ps[3] = Point(11398.1, 10506);
+ new ShapeRef(router, polygon, 748);
+
+ // shapeRef749
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11889.1, 10209);
+ polygon.ps[1] = Point(11889.1, 10271);
+ polygon.ps[2] = Point(11827.1, 10271);
+ polygon.ps[3] = Point(11827.1, 10209);
+ new ShapeRef(router, polygon, 749);
+
+ // shapeRef750
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11460.1, 10209);
+ polygon.ps[1] = Point(11460.1, 10271);
+ polygon.ps[2] = Point(11398.1, 10271);
+ polygon.ps[3] = Point(11398.1, 10209);
+ new ShapeRef(router, polygon, 750);
+
+ // shapeRef751
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11460.1, 9182.42);
+ polygon.ps[1] = Point(11460.1, 9244.42);
+ polygon.ps[2] = Point(11398.1, 9244.42);
+ polygon.ps[3] = Point(11398.1, 9182.42);
+ new ShapeRef(router, polygon, 751);
+
+ // shapeRef752
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12920.5, 9182.42);
+ polygon.ps[1] = Point(12920.5, 9244.42);
+ polygon.ps[2] = Point(12858.5, 9244.42);
+ polygon.ps[3] = Point(12858.5, 9182.42);
+ new ShapeRef(router, polygon, 752);
+
+ // shapeRef753
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4683, 4511.4);
+ polygon.ps[1] = Point(4683, 4573.4);
+ polygon.ps[2] = Point(4621, 4573.4);
+ polygon.ps[3] = Point(4621, 4511.4);
+ new ShapeRef(router, polygon, 753);
+
+ // shapeRef754
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17706.5, 11829.9);
+ polygon.ps[1] = Point(17706.5, 11891.9);
+ polygon.ps[2] = Point(17644.5, 11891.9);
+ polygon.ps[3] = Point(17644.5, 11829.9);
+ new ShapeRef(router, polygon, 754);
+
+ // shapeRef755
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17409.5, 11829.9);
+ polygon.ps[1] = Point(17409.5, 11891.9);
+ polygon.ps[2] = Point(17347.5, 11891.9);
+ polygon.ps[3] = Point(17347.5, 11829.9);
+ new ShapeRef(router, polygon, 755);
+
+ // shapeRef756
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16984.8, 11829.9);
+ polygon.ps[1] = Point(16984.8, 11891.9);
+ polygon.ps[2] = Point(16922.8, 11891.9);
+ polygon.ps[3] = Point(16922.8, 11829.9);
+ new ShapeRef(router, polygon, 756);
+
+ // shapeRef757
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16295.6, 2548.29);
+ polygon.ps[1] = Point(16295.6, 2610.29);
+ polygon.ps[2] = Point(16233.6, 2610.29);
+ polygon.ps[3] = Point(16233.6, 2548.29);
+ new ShapeRef(router, polygon, 757);
+
+ // shapeRef758
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15965.6, 2548.29);
+ polygon.ps[1] = Point(15965.6, 2610.29);
+ polygon.ps[2] = Point(15903.6, 2610.29);
+ polygon.ps[3] = Point(15903.6, 2548.29);
+ new ShapeRef(router, polygon, 758);
+
+ // shapeRef759
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15270.5, 2548.29);
+ polygon.ps[1] = Point(15270.5, 2610.29);
+ polygon.ps[2] = Point(15208.5, 2610.29);
+ polygon.ps[3] = Point(15208.5, 2548.29);
+ new ShapeRef(router, polygon, 759);
+
+ // shapeRef760
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14629, 2548.29);
+ polygon.ps[1] = Point(14629, 2610.29);
+ polygon.ps[2] = Point(14567, 2610.29);
+ polygon.ps[3] = Point(14567, 2548.29);
+ new ShapeRef(router, polygon, 760);
+
+ // shapeRef761
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13837, 2845.29);
+ polygon.ps[1] = Point(13837, 2907.29);
+ polygon.ps[2] = Point(13775, 2907.29);
+ polygon.ps[3] = Point(13775, 2845.29);
+ new ShapeRef(router, polygon, 761);
+
+ // shapeRef762
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14200, 2548.29);
+ polygon.ps[1] = Point(14200, 2610.29);
+ polygon.ps[2] = Point(14138, 2610.29);
+ polygon.ps[3] = Point(14138, 2548.29);
+ new ShapeRef(router, polygon, 762);
+
+ // shapeRef763
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18498.5, 9644.42);
+ polygon.ps[1] = Point(18498.5, 9706.42);
+ polygon.ps[2] = Point(18436.5, 9706.42);
+ polygon.ps[3] = Point(18436.5, 9644.42);
+ new ShapeRef(router, polygon, 763);
+
+ // shapeRef764
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18300.5, 9644.42);
+ polygon.ps[1] = Point(18300.5, 9706.42);
+ polygon.ps[2] = Point(18238.5, 9706.42);
+ polygon.ps[3] = Point(18238.5, 9644.42);
+ new ShapeRef(router, polygon, 764);
+
+ // shapeRef765
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18069.5, 9644.42);
+ polygon.ps[1] = Point(18069.5, 9706.42);
+ polygon.ps[2] = Point(18007.5, 9706.42);
+ polygon.ps[3] = Point(18007.5, 9644.42);
+ new ShapeRef(router, polygon, 765);
+
+ // shapeRef766
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17838.5, 9644.42);
+ polygon.ps[1] = Point(17838.5, 9706.42);
+ polygon.ps[2] = Point(17776.5, 9706.42);
+ polygon.ps[3] = Point(17776.5, 9644.42);
+ new ShapeRef(router, polygon, 766);
+
+ // shapeRef767
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17673.5, 9644.42);
+ polygon.ps[1] = Point(17673.5, 9706.42);
+ polygon.ps[2] = Point(17611.5, 9706.42);
+ polygon.ps[3] = Point(17611.5, 9644.42);
+ new ShapeRef(router, polygon, 767);
+
+ // shapeRef768
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17442.5, 9644.42);
+ polygon.ps[1] = Point(17442.5, 9706.42);
+ polygon.ps[2] = Point(17380.5, 9706.42);
+ polygon.ps[3] = Point(17380.5, 9644.42);
+ new ShapeRef(router, polygon, 768);
+
+ // shapeRef769
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17083.8, 9644.42);
+ polygon.ps[1] = Point(17083.8, 9706.42);
+ polygon.ps[2] = Point(17021.8, 9706.42);
+ polygon.ps[3] = Point(17021.8, 9644.42);
+ new ShapeRef(router, polygon, 769);
+
+ // shapeRef770
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17083.8, 9083.42);
+ polygon.ps[1] = Point(17083.8, 9145.42);
+ polygon.ps[2] = Point(17021.8, 9145.42);
+ polygon.ps[3] = Point(17021.8, 9083.42);
+ new ShapeRef(router, polygon, 770);
+
+ // shapeRef771
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17083.8, 8449.99);
+ polygon.ps[1] = Point(17083.8, 8511.99);
+ polygon.ps[2] = Point(17021.8, 8511.99);
+ polygon.ps[3] = Point(17021.8, 8449.99);
+ new ShapeRef(router, polygon, 771);
+
+ // shapeRef772
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17083.8, 7878.79);
+ polygon.ps[1] = Point(17083.8, 7940.79);
+ polygon.ps[2] = Point(17021.8, 7940.79);
+ polygon.ps[3] = Point(17021.8, 7878.79);
+ new ShapeRef(router, polygon, 772);
+
+ // shapeRef773
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17310.5, 1879.29);
+ polygon.ps[1] = Point(17310.5, 1941.29);
+ polygon.ps[2] = Point(17248.5, 1941.29);
+ polygon.ps[3] = Point(17248.5, 1879.29);
+ new ShapeRef(router, polygon, 773);
+
+ // shapeRef774
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17574.5, 1513.29);
+ polygon.ps[1] = Point(17574.5, 1575.29);
+ polygon.ps[2] = Point(17512.5, 1575.29);
+ polygon.ps[3] = Point(17512.5, 1513.29);
+ new ShapeRef(router, polygon, 774);
+
+ // shapeRef775
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17310.5, 1513.29);
+ polygon.ps[1] = Point(17310.5, 1575.29);
+ polygon.ps[2] = Point(17248.5, 1575.29);
+ polygon.ps[3] = Point(17248.5, 1513.29);
+ new ShapeRef(router, polygon, 775);
+
+ // shapeRef776
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16687.8, 1513.29);
+ polygon.ps[1] = Point(16687.8, 1575.29);
+ polygon.ps[2] = Point(16625.8, 1575.29);
+ polygon.ps[3] = Point(16625.8, 1513.29);
+ new ShapeRef(router, polygon, 776);
+
+ // shapeRef777
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16687.8, 1249.29);
+ polygon.ps[1] = Point(16687.8, 1311.29);
+ polygon.ps[2] = Point(16625.8, 1311.29);
+ polygon.ps[3] = Point(16625.8, 1249.29);
+ new ShapeRef(router, polygon, 777);
+
+ // shapeRef778
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16918.8, 1249.29);
+ polygon.ps[1] = Point(16918.8, 1311.29);
+ polygon.ps[2] = Point(16856.8, 1311.29);
+ polygon.ps[3] = Point(16856.8, 1249.29);
+ new ShapeRef(router, polygon, 778);
+
+ // shapeRef779
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17310.5, 1018.29);
+ polygon.ps[1] = Point(17310.5, 1080.29);
+ polygon.ps[2] = Point(17248.5, 1080.29);
+ polygon.ps[3] = Point(17248.5, 1018.29);
+ new ShapeRef(router, polygon, 779);
+
+ // shapeRef780
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17310.5, 645.091);
+ polygon.ps[1] = Point(17310.5, 707.091);
+ polygon.ps[2] = Point(17248.5, 707.091);
+ polygon.ps[3] = Point(17248.5, 645.091);
+ new ShapeRef(router, polygon, 780);
+
+ // shapeRef781
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16918.8, 427.265);
+ polygon.ps[1] = Point(16918.8, 489.265);
+ polygon.ps[2] = Point(16856.8, 489.265);
+ polygon.ps[3] = Point(16856.8, 427.265);
+ new ShapeRef(router, polygon, 781);
+
+ // shapeRef782
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16687.8, 427.265);
+ polygon.ps[1] = Point(16687.8, 489.265);
+ polygon.ps[2] = Point(16625.8, 489.265);
+ polygon.ps[3] = Point(16625.8, 427.265);
+ new ShapeRef(router, polygon, 782);
+
+ // shapeRef783
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5890.1, 12427.7);
+ polygon.ps[1] = Point(5890.1, 12489.7);
+ polygon.ps[2] = Point(5828.1, 12489.7);
+ polygon.ps[3] = Point(5828.1, 12427.7);
+ new ShapeRef(router, polygon, 783);
+
+ // shapeRef784
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5593.1, 12427.7);
+ polygon.ps[1] = Point(5593.1, 12489.7);
+ polygon.ps[2] = Point(5531.1, 12489.7);
+ polygon.ps[3] = Point(5531.1, 12427.7);
+ new ShapeRef(router, polygon, 784);
+
+ // shapeRef785
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5178, 12427.7);
+ polygon.ps[1] = Point(5178, 12489.7);
+ polygon.ps[2] = Point(5116, 12489.7);
+ polygon.ps[3] = Point(5116, 12427.7);
+ new ShapeRef(router, polygon, 785);
+
+ // shapeRef786
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4980, 11796.9);
+ polygon.ps[1] = Point(4980, 11858.9);
+ polygon.ps[2] = Point(4918, 11858.9);
+ polygon.ps[3] = Point(4918, 11796.9);
+ new ShapeRef(router, polygon, 786);
+
+ // shapeRef787
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4980, 11147.6);
+ polygon.ps[1] = Point(4980, 11209.6);
+ polygon.ps[2] = Point(4918, 11209.6);
+ polygon.ps[3] = Point(4918, 11147.6);
+ new ShapeRef(router, polygon, 787);
+
+ // shapeRef788
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4980, 10717.3);
+ polygon.ps[1] = Point(4980, 10779.3);
+ polygon.ps[2] = Point(4918, 10779.3);
+ polygon.ps[3] = Point(4918, 10717.3);
+ new ShapeRef(router, polygon, 788);
+
+ // shapeRef789
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4980, 10110);
+ polygon.ps[1] = Point(4980, 10172);
+ polygon.ps[2] = Point(4918, 10172);
+ polygon.ps[3] = Point(4918, 10110);
+ new ShapeRef(router, polygon, 789);
+
+ // shapeRef790
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4617, 10110);
+ polygon.ps[1] = Point(4617, 10172);
+ polygon.ps[2] = Point(4555, 10172);
+ polygon.ps[3] = Point(4555, 10110);
+ new ShapeRef(router, polygon, 790);
+
+ // shapeRef791
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4320, 10341);
+ polygon.ps[1] = Point(4320, 10403);
+ polygon.ps[2] = Point(4258, 10403);
+ polygon.ps[3] = Point(4258, 10341);
+ new ShapeRef(router, polygon, 791);
+
+ // shapeRef792
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4617, 9545.42);
+ polygon.ps[1] = Point(4617, 9607.42);
+ polygon.ps[2] = Point(4555, 9607.42);
+ polygon.ps[3] = Point(4555, 9545.42);
+ new ShapeRef(router, polygon, 792);
+
+ // shapeRef793
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3429, 10618.3);
+ polygon.ps[1] = Point(3429, 10680.3);
+ polygon.ps[2] = Point(3367, 10680.3);
+ polygon.ps[3] = Point(3367, 10618.3);
+ new ShapeRef(router, polygon, 793);
+
+ // shapeRef794
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4056, 10618.3);
+ polygon.ps[1] = Point(4056, 10680.3);
+ polygon.ps[2] = Point(3994, 10680.3);
+ polygon.ps[3] = Point(3994, 10618.3);
+ new ShapeRef(router, polygon, 794);
+
+ // shapeRef795
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3429, 10275);
+ polygon.ps[1] = Point(3429, 10337);
+ polygon.ps[2] = Point(3367, 10337);
+ polygon.ps[3] = Point(3367, 10275);
+ new ShapeRef(router, polygon, 795);
+
+ // shapeRef796
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3429, 9879.02);
+ polygon.ps[1] = Point(3429, 9941.02);
+ polygon.ps[2] = Point(3367, 9941.02);
+ polygon.ps[3] = Point(3367, 9879.02);
+ new ShapeRef(router, polygon, 796);
+
+ // shapeRef797
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3429, 9380.42);
+ polygon.ps[1] = Point(3429, 9442.42);
+ polygon.ps[2] = Point(3367, 9442.42);
+ polygon.ps[3] = Point(3367, 9380.42);
+ new ShapeRef(router, polygon, 797);
+
+ // shapeRef798
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3429, 9017.42);
+ polygon.ps[1] = Point(3429, 9079.42);
+ polygon.ps[2] = Point(3367, 9079.42);
+ polygon.ps[3] = Point(3367, 9017.42);
+ new ShapeRef(router, polygon, 798);
+
+ // shapeRef799
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4056, 10275);
+ polygon.ps[1] = Point(4056, 10337);
+ polygon.ps[2] = Point(3994, 10337);
+ polygon.ps[3] = Point(3994, 10275);
+ new ShapeRef(router, polygon, 799);
+
+ // shapeRef800
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4056, 9879.02);
+ polygon.ps[1] = Point(4056, 9941.02);
+ polygon.ps[2] = Point(3994, 9941.02);
+ polygon.ps[3] = Point(3994, 9879.02);
+ new ShapeRef(router, polygon, 800);
+
+ // shapeRef801
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4056, 9380.42);
+ polygon.ps[1] = Point(4056, 9442.42);
+ polygon.ps[2] = Point(3994, 9442.42);
+ polygon.ps[3] = Point(3994, 9380.42);
+ new ShapeRef(router, polygon, 801);
+
+ // shapeRef802
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4056, 9017.42);
+ polygon.ps[1] = Point(4056, 9079.42);
+ polygon.ps[2] = Point(3994, 9079.42);
+ polygon.ps[3] = Point(3994, 9017.42);
+ new ShapeRef(router, polygon, 802);
+
+ // shapeRef803
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4056, 8548.99);
+ polygon.ps[1] = Point(4056, 8610.99);
+ polygon.ps[2] = Point(3994, 8610.99);
+ polygon.ps[3] = Point(3994, 8548.99);
+ new ShapeRef(router, polygon, 803);
+
+ // shapeRef804
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4056, 8142.79);
+ polygon.ps[1] = Point(4056, 8204.79);
+ polygon.ps[2] = Point(3994, 8204.79);
+ polygon.ps[3] = Point(3994, 8142.79);
+ new ShapeRef(router, polygon, 804);
+
+ // shapeRef805
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4485, 8142.79);
+ polygon.ps[1] = Point(4485, 8204.79);
+ polygon.ps[2] = Point(4423, 8204.79);
+ polygon.ps[3] = Point(4423, 8142.79);
+ new ShapeRef(router, polygon, 805);
+
+ // shapeRef806
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4485, 7614.79);
+ polygon.ps[1] = Point(4485, 7676.79);
+ polygon.ps[2] = Point(4423, 7676.79);
+ polygon.ps[3] = Point(4423, 7614.79);
+ new ShapeRef(router, polygon, 806);
+
+ // shapeRef807
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4056, 7614.79);
+ polygon.ps[1] = Point(4056, 7676.79);
+ polygon.ps[2] = Point(3994, 7676.79);
+ polygon.ps[3] = Point(3994, 7614.79);
+ new ShapeRef(router, polygon, 807);
+
+ // shapeRef808
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3099, 9380.42);
+ polygon.ps[1] = Point(3099, 9442.42);
+ polygon.ps[2] = Point(3037, 9442.42);
+ polygon.ps[3] = Point(3037, 9380.42);
+ new ShapeRef(router, polygon, 808);
+
+ // shapeRef809
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3099, 9017.42);
+ polygon.ps[1] = Point(3099, 9079.42);
+ polygon.ps[2] = Point(3037, 9079.42);
+ polygon.ps[3] = Point(3037, 9017.42);
+ new ShapeRef(router, polygon, 809);
+
+ // shapeRef810
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3099, 8548.99);
+ polygon.ps[1] = Point(3099, 8610.99);
+ polygon.ps[2] = Point(3037, 8610.99);
+ polygon.ps[3] = Point(3037, 8548.99);
+ new ShapeRef(router, polygon, 810);
+
+ // shapeRef811
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3759, 8548.99);
+ polygon.ps[1] = Point(3759, 8610.99);
+ polygon.ps[2] = Point(3697, 8610.99);
+ polygon.ps[3] = Point(3697, 8548.99);
+ new ShapeRef(router, polygon, 811);
+
+ // shapeRef812
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3759, 8142.79);
+ polygon.ps[1] = Point(3759, 8204.79);
+ polygon.ps[2] = Point(3697, 8204.79);
+ polygon.ps[3] = Point(3697, 8142.79);
+ new ShapeRef(router, polygon, 812);
+
+ // shapeRef813
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3099, 8142.79);
+ polygon.ps[1] = Point(3099, 8204.79);
+ polygon.ps[2] = Point(3037, 8204.79);
+ polygon.ps[3] = Point(3037, 8142.79);
+ new ShapeRef(router, polygon, 813);
+
+ // shapeRef814
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3099, 7614.79);
+ polygon.ps[1] = Point(3099, 7676.79);
+ polygon.ps[2] = Point(3037, 7676.79);
+ polygon.ps[3] = Point(3037, 7614.79);
+ new ShapeRef(router, polygon, 814);
+
+ // shapeRef815
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3759, 7614.79);
+ polygon.ps[1] = Point(3759, 7676.79);
+ polygon.ps[2] = Point(3697, 7676.79);
+ polygon.ps[3] = Point(3697, 7614.79);
+ new ShapeRef(router, polygon, 815);
+
+ // shapeRef816
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1614, 5933.59);
+ polygon.ps[1] = Point(1614, 5995.59);
+ polygon.ps[2] = Point(1552, 5995.59);
+ polygon.ps[3] = Point(1552, 5933.59);
+ new ShapeRef(router, polygon, 816);
+
+ // shapeRef817
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1812, 6252.51);
+ polygon.ps[1] = Point(1812, 6314.51);
+ polygon.ps[2] = Point(1750, 6314.51);
+ polygon.ps[3] = Point(1750, 6252.51);
+ new ShapeRef(router, polygon, 817);
+
+ // shapeRef818
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2175, 6252.51);
+ polygon.ps[1] = Point(2175, 6314.51);
+ polygon.ps[2] = Point(2113, 6314.51);
+ polygon.ps[3] = Point(2113, 6252.51);
+ new ShapeRef(router, polygon, 818);
+
+ // shapeRef819
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2505, 6252.51);
+ polygon.ps[1] = Point(2505, 6314.51);
+ polygon.ps[2] = Point(2443, 6314.51);
+ polygon.ps[3] = Point(2443, 6252.51);
+ new ShapeRef(router, polygon, 819);
+
+ // shapeRef820
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2934, 6252.51);
+ polygon.ps[1] = Point(2934, 6314.51);
+ polygon.ps[2] = Point(2872, 6314.51);
+ polygon.ps[3] = Point(2872, 6252.51);
+ new ShapeRef(router, polygon, 820);
+
+ // shapeRef821
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3726, 6252.51);
+ polygon.ps[1] = Point(3726, 6314.51);
+ polygon.ps[2] = Point(3664, 6314.51);
+ polygon.ps[3] = Point(3664, 6252.51);
+ new ShapeRef(router, polygon, 821);
+
+ // shapeRef822
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4287, 6252.51);
+ polygon.ps[1] = Point(4287, 6314.51);
+ polygon.ps[2] = Point(4225, 6314.51);
+ polygon.ps[3] = Point(4225, 6252.51);
+ new ShapeRef(router, polygon, 822);
+
+ // shapeRef823
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(228, 8383.99);
+ polygon.ps[1] = Point(228, 8445.99);
+ polygon.ps[2] = Point(166, 8445.99);
+ polygon.ps[3] = Point(166, 8383.99);
+ new ShapeRef(router, polygon, 823);
+
+ // shapeRef824
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(228, 7911.79);
+ polygon.ps[1] = Point(228, 7973.79);
+ polygon.ps[2] = Point(166, 7973.79);
+ polygon.ps[3] = Point(166, 7911.79);
+ new ShapeRef(router, polygon, 824);
+
+ // shapeRef825
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(228, 7394.4);
+ polygon.ps[1] = Point(228, 7456.4);
+ polygon.ps[2] = Point(166, 7456.4);
+ polygon.ps[3] = Point(166, 7394.4);
+ new ShapeRef(router, polygon, 825);
+
+ // shapeRef826
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(228, 6965.4);
+ polygon.ps[1] = Point(228, 7027.4);
+ polygon.ps[2] = Point(166, 7027.4);
+ polygon.ps[3] = Point(166, 6965.4);
+ new ShapeRef(router, polygon, 826);
+
+ // shapeRef827
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(228, 6417.51);
+ polygon.ps[1] = Point(228, 6479.51);
+ polygon.ps[2] = Point(166, 6479.51);
+ polygon.ps[3] = Point(166, 6417.51);
+ new ShapeRef(router, polygon, 827);
+
+ // shapeRef828
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(228, 6025.29);
+ polygon.ps[1] = Point(228, 6087.29);
+ polygon.ps[2] = Point(166, 6087.29);
+ polygon.ps[3] = Point(166, 6025.29);
+ new ShapeRef(router, polygon, 828);
+
+ // shapeRef829
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(228, 5626.9);
+ polygon.ps[1] = Point(228, 5688.9);
+ polygon.ps[2] = Point(166, 5688.9);
+ polygon.ps[3] = Point(166, 5626.9);
+ new ShapeRef(router, polygon, 829);
+
+ // shapeRef830
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1416, 8482.99);
+ polygon.ps[1] = Point(1416, 8544.99);
+ polygon.ps[2] = Point(1354, 8544.99);
+ polygon.ps[3] = Point(1354, 8482.99);
+ new ShapeRef(router, polygon, 830);
+
+ // shapeRef831
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1416, 6648.51);
+ polygon.ps[1] = Point(1416, 6710.51);
+ polygon.ps[2] = Point(1354, 6710.51);
+ polygon.ps[3] = Point(1354, 6648.51);
+ new ShapeRef(router, polygon, 831);
+
+ // shapeRef832
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1416, 6252.51);
+ polygon.ps[1] = Point(1416, 6314.51);
+ polygon.ps[2] = Point(1354, 6314.51);
+ polygon.ps[3] = Point(1354, 6252.51);
+ new ShapeRef(router, polygon, 832);
+
+ // shapeRef833
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4386, 12427.7);
+ polygon.ps[1] = Point(4386, 12489.7);
+ polygon.ps[2] = Point(4324, 12489.7);
+ polygon.ps[3] = Point(4324, 12427.7);
+ new ShapeRef(router, polygon, 833);
+
+ // shapeRef834
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3693, 12427.7);
+ polygon.ps[1] = Point(3693, 12489.7);
+ polygon.ps[2] = Point(3631, 12489.7);
+ polygon.ps[3] = Point(3631, 12427.7);
+ new ShapeRef(router, polygon, 834);
+
+ // shapeRef835
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3231, 12427.7);
+ polygon.ps[1] = Point(3231, 12489.7);
+ polygon.ps[2] = Point(3169, 12489.7);
+ polygon.ps[3] = Point(3169, 12427.7);
+ new ShapeRef(router, polygon, 835);
+
+ // shapeRef836
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2736, 12427.7);
+ polygon.ps[1] = Point(2736, 12489.7);
+ polygon.ps[2] = Point(2674, 12489.7);
+ polygon.ps[3] = Point(2674, 12427.7);
+ new ShapeRef(router, polygon, 836);
+
+ // shapeRef837
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2373, 12427.7);
+ polygon.ps[1] = Point(2373, 12489.7);
+ polygon.ps[2] = Point(2311, 12489.7);
+ polygon.ps[3] = Point(2311, 12427.7);
+ new ShapeRef(router, polygon, 837);
+
+ // shapeRef838
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4056, 12017.3);
+ polygon.ps[1] = Point(4056, 12079.3);
+ polygon.ps[2] = Point(3994, 12079.3);
+ polygon.ps[3] = Point(3994, 12017.3);
+ new ShapeRef(router, polygon, 838);
+
+ // shapeRef839
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3693, 12017.3);
+ polygon.ps[1] = Point(3693, 12079.3);
+ polygon.ps[2] = Point(3631, 12079.3);
+ polygon.ps[3] = Point(3631, 12017.3);
+ new ShapeRef(router, polygon, 839);
+
+ // shapeRef840
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3231, 12017.3);
+ polygon.ps[1] = Point(3231, 12079.3);
+ polygon.ps[2] = Point(3169, 12079.3);
+ polygon.ps[3] = Point(3169, 12017.3);
+ new ShapeRef(router, polygon, 840);
+
+ // shapeRef841
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2736, 12017.3);
+ polygon.ps[1] = Point(2736, 12079.3);
+ polygon.ps[2] = Point(2674, 12079.3);
+ polygon.ps[3] = Point(2674, 12017.3);
+ new ShapeRef(router, polygon, 841);
+
+ // shapeRef842
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2373, 12017.3);
+ polygon.ps[1] = Point(2373, 12079.3);
+ polygon.ps[2] = Point(2311, 12079.3);
+ polygon.ps[3] = Point(2311, 12017.3);
+ new ShapeRef(router, polygon, 842);
+
+ // shapeRef843
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1350, 8677.22);
+ polygon.ps[1] = Point(1350, 8739.22);
+ polygon.ps[2] = Point(1288, 8739.22);
+ polygon.ps[3] = Point(1288, 8677.22);
+ new ShapeRef(router, polygon, 843);
+
+ // shapeRef844
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1911, 8677.22);
+ polygon.ps[1] = Point(1911, 8739.22);
+ polygon.ps[2] = Point(1849, 8739.22);
+ polygon.ps[3] = Point(1849, 8677.22);
+ new ShapeRef(router, polygon, 844);
+
+ // shapeRef845
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1911, 8350.99);
+ polygon.ps[1] = Point(1911, 8412.99);
+ polygon.ps[2] = Point(1849, 8412.99);
+ polygon.ps[3] = Point(1849, 8350.99);
+ new ShapeRef(router, polygon, 845);
+
+ // shapeRef846
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1350, 7845.79);
+ polygon.ps[1] = Point(1350, 7907.79);
+ polygon.ps[2] = Point(1288, 7907.79);
+ polygon.ps[3] = Point(1288, 7845.79);
+ new ShapeRef(router, polygon, 846);
+
+ // shapeRef847
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1911, 7845.79);
+ polygon.ps[1] = Point(1911, 7907.79);
+ polygon.ps[2] = Point(1849, 7907.79);
+ polygon.ps[3] = Point(1849, 7845.79);
+ new ShapeRef(router, polygon, 847);
+
+ // shapeRef848
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1911, 7394.4);
+ polygon.ps[1] = Point(1911, 7456.4);
+ polygon.ps[2] = Point(1849, 7456.4);
+ polygon.ps[3] = Point(1849, 7394.4);
+ new ShapeRef(router, polygon, 848);
+
+ // shapeRef849
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1350, 7394.4);
+ polygon.ps[1] = Point(1350, 7456.4);
+ polygon.ps[2] = Point(1288, 7456.4);
+ polygon.ps[3] = Point(1288, 7394.4);
+ new ShapeRef(router, polygon, 849);
+
+ // shapeRef850
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1350, 6998.4);
+ polygon.ps[1] = Point(1350, 7060.4);
+ polygon.ps[2] = Point(1288, 7060.4);
+ polygon.ps[3] = Point(1288, 6998.4);
+ new ShapeRef(router, polygon, 850);
+
+ // shapeRef851
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1680, 6417.51);
+ polygon.ps[1] = Point(1680, 6479.51);
+ polygon.ps[2] = Point(1618, 6479.51);
+ polygon.ps[3] = Point(1618, 6417.51);
+ new ShapeRef(router, polygon, 851);
+
+ // shapeRef852
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1911, 6417.51);
+ polygon.ps[1] = Point(1911, 6479.51);
+ polygon.ps[2] = Point(1849, 6479.51);
+ polygon.ps[3] = Point(1849, 6417.51);
+ new ShapeRef(router, polygon, 852);
+
+ // shapeRef853
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3528, 6417.51);
+ polygon.ps[1] = Point(3528, 6479.51);
+ polygon.ps[2] = Point(3466, 6479.51);
+ polygon.ps[3] = Point(3466, 6417.51);
+ new ShapeRef(router, polygon, 853);
+
+ // shapeRef854
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8159.29, 4907.4);
+ polygon.ps[1] = Point(8159.29, 4969.4);
+ polygon.ps[2] = Point(8097.29, 4969.4);
+ polygon.ps[3] = Point(8097.29, 4907.4);
+ new ShapeRef(router, polygon, 854);
+
+ // shapeRef855
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7862.29, 4907.4);
+ polygon.ps[1] = Point(7862.29, 4969.4);
+ polygon.ps[2] = Point(7800.29, 4969.4);
+ polygon.ps[3] = Point(7800.29, 4907.4);
+ new ShapeRef(router, polygon, 855);
+
+ // shapeRef856
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7507.1, 4907.4);
+ polygon.ps[1] = Point(7507.1, 4969.4);
+ polygon.ps[2] = Point(7445.1, 4969.4);
+ polygon.ps[3] = Point(7445.1, 4907.4);
+ new ShapeRef(router, polygon, 856);
+
+ // shapeRef857
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7111.1, 4907.4);
+ polygon.ps[1] = Point(7111.1, 4969.4);
+ polygon.ps[2] = Point(7049.1, 4969.4);
+ polygon.ps[3] = Point(7049.1, 4907.4);
+ new ShapeRef(router, polygon, 857);
+
+ // shapeRef858
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6748.1, 4907.4);
+ polygon.ps[1] = Point(6748.1, 4969.4);
+ polygon.ps[2] = Point(6686.1, 4969.4);
+ polygon.ps[3] = Point(6686.1, 4907.4);
+ new ShapeRef(router, polygon, 858);
+
+ // shapeRef859
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6517.1, 4907.4);
+ polygon.ps[1] = Point(6517.1, 4969.4);
+ polygon.ps[2] = Point(6455.1, 4969.4);
+ polygon.ps[3] = Point(6455.1, 4907.4);
+ new ShapeRef(router, polygon, 859);
+
+ // shapeRef860
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6220.1, 4907.4);
+ polygon.ps[1] = Point(6220.1, 4969.4);
+ polygon.ps[2] = Point(6158.1, 4969.4);
+ polygon.ps[3] = Point(6158.1, 4907.4);
+ new ShapeRef(router, polygon, 860);
+
+ // shapeRef861
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6055.1, 4907.4);
+ polygon.ps[1] = Point(6055.1, 4969.4);
+ polygon.ps[2] = Point(5993.1, 4969.4);
+ polygon.ps[3] = Point(5993.1, 4907.4);
+ new ShapeRef(router, polygon, 861);
+
+ // shapeRef862
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7012.1, 7097.4);
+ polygon.ps[1] = Point(7012.1, 7159.4);
+ polygon.ps[2] = Point(6950.1, 7159.4);
+ polygon.ps[3] = Point(6950.1, 7097.4);
+ new ShapeRef(router, polygon, 862);
+
+ // shapeRef863
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4584, 5250.67);
+ polygon.ps[1] = Point(4584, 5312.67);
+ polygon.ps[2] = Point(4522, 5312.67);
+ polygon.ps[3] = Point(4522, 5250.67);
+ new ShapeRef(router, polygon, 863);
+
+ // shapeRef864
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6253.1, 6582.51);
+ polygon.ps[1] = Point(6253.1, 6644.51);
+ polygon.ps[2] = Point(6191.1, 6644.51);
+ polygon.ps[3] = Point(6191.1, 6582.51);
+ new ShapeRef(router, polygon, 864);
+
+ // shapeRef865
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6121.1, 5933.59);
+ polygon.ps[1] = Point(6121.1, 5995.59);
+ polygon.ps[2] = Point(6059.1, 5995.59);
+ polygon.ps[3] = Point(6059.1, 5933.59);
+ new ShapeRef(router, polygon, 865);
+
+ // shapeRef866
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6484.1, 5933.59);
+ polygon.ps[1] = Point(6484.1, 5995.59);
+ polygon.ps[2] = Point(6422.1, 5995.59);
+ polygon.ps[3] = Point(6422.1, 5933.59);
+ new ShapeRef(router, polygon, 866);
+
+ // shapeRef867
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7144.1, 5933.59);
+ polygon.ps[1] = Point(7144.1, 5995.59);
+ polygon.ps[2] = Point(7082.1, 5995.59);
+ polygon.ps[3] = Point(7082.1, 5933.59);
+ new ShapeRef(router, polygon, 867);
+
+ // shapeRef868
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7796.29, 5933.59);
+ polygon.ps[1] = Point(7796.29, 5995.59);
+ polygon.ps[2] = Point(7734.29, 5995.59);
+ polygon.ps[3] = Point(7734.29, 5933.59);
+ new ShapeRef(router, polygon, 868);
+
+ // shapeRef869
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13672, 985.285);
+ polygon.ps[1] = Point(13672, 1047.29);
+ polygon.ps[2] = Point(13610, 1047.29);
+ polygon.ps[3] = Point(13610, 985.285);
+ new ShapeRef(router, polygon, 869);
+
+ // shapeRef870
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13165, 985.285);
+ polygon.ps[1] = Point(13165, 1047.29);
+ polygon.ps[2] = Point(13103, 1047.29);
+ polygon.ps[3] = Point(13103, 985.285);
+ new ShapeRef(router, polygon, 870);
+
+ // shapeRef871
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12562.5, 985.285);
+ polygon.ps[1] = Point(12562.5, 1047.29);
+ polygon.ps[2] = Point(12500.5, 1047.29);
+ polygon.ps[3] = Point(12500.5, 985.285);
+ new ShapeRef(router, polygon, 871);
+
+ // shapeRef872
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12021.1, 985.285);
+ polygon.ps[1] = Point(12021.1, 1047.29);
+ polygon.ps[2] = Point(11959.1, 1047.29);
+ polygon.ps[3] = Point(11959.1, 985.285);
+ new ShapeRef(router, polygon, 872);
+
+ // shapeRef873
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16753.8, 9978.02);
+ polygon.ps[1] = Point(16753.8, 10040);
+ polygon.ps[2] = Point(16691.8, 10040);
+ polygon.ps[3] = Point(16691.8, 9978.02);
+ new ShapeRef(router, polygon, 873);
+
+ // shapeRef874
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16130.6, 8842.22);
+ polygon.ps[1] = Point(16130.6, 8904.22);
+ polygon.ps[2] = Point(16068.6, 8904.22);
+ polygon.ps[3] = Point(16068.6, 8842.22);
+ new ShapeRef(router, polygon, 874);
+
+ // shapeRef875
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14464, 8842.22);
+ polygon.ps[1] = Point(14464, 8904.22);
+ polygon.ps[2] = Point(14402, 8904.22);
+ polygon.ps[3] = Point(14402, 8842.22);
+ new ShapeRef(router, polygon, 875);
+
+ // shapeRef876
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17541.5, 9248.42);
+ polygon.ps[1] = Point(17541.5, 9310.42);
+ polygon.ps[2] = Point(17479.5, 9310.42);
+ polygon.ps[3] = Point(17479.5, 9248.42);
+ new ShapeRef(router, polygon, 876);
+
+ // shapeRef877
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17541.5, 8743.22);
+ polygon.ps[1] = Point(17541.5, 8805.22);
+ polygon.ps[2] = Point(17479.5, 8805.22);
+ polygon.ps[3] = Point(17479.5, 8743.22);
+ new ShapeRef(router, polygon, 877);
+
+ // shapeRef878
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17475.5, 7581.79);
+ polygon.ps[1] = Point(17475.5, 7643.79);
+ polygon.ps[2] = Point(17413.5, 7643.79);
+ polygon.ps[3] = Point(17413.5, 7581.79);
+ new ShapeRef(router, polygon, 878);
+
+ // shapeRef879
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18333.5, 9446.42);
+ polygon.ps[1] = Point(18333.5, 9508.42);
+ polygon.ps[2] = Point(18271.5, 9508.42);
+ polygon.ps[3] = Point(18271.5, 9446.42);
+ new ShapeRef(router, polygon, 879);
+
+ // shapeRef880
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18333.5, 9050.42);
+ polygon.ps[1] = Point(18333.5, 9112.42);
+ polygon.ps[2] = Point(18271.5, 9112.42);
+ polygon.ps[3] = Point(18271.5, 9050.42);
+ new ShapeRef(router, polygon, 880);
+
+ // shapeRef881
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18333.5, 8611.22);
+ polygon.ps[1] = Point(18333.5, 8673.22);
+ polygon.ps[2] = Point(18271.5, 8673.22);
+ polygon.ps[3] = Point(18271.5, 8611.22);
+ new ShapeRef(router, polygon, 881);
+
+ // shapeRef882
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18333.5, 8218.99);
+ polygon.ps[1] = Point(18333.5, 8280.99);
+ polygon.ps[2] = Point(18271.5, 8280.99);
+ polygon.ps[3] = Point(18271.5, 8218.99);
+ new ShapeRef(router, polygon, 882);
+
+ // shapeRef883
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18694.5, 9149.42);
+ polygon.ps[1] = Point(18694.5, 9211.42);
+ polygon.ps[2] = Point(18632.5, 9211.42);
+ polygon.ps[3] = Point(18632.5, 9149.42);
+ new ShapeRef(router, polygon, 883);
+
+ // shapeRef884
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18465.5, 9149.42);
+ polygon.ps[1] = Point(18465.5, 9211.42);
+ polygon.ps[2] = Point(18403.5, 9211.42);
+ polygon.ps[3] = Point(18403.5, 9149.42);
+ new ShapeRef(router, polygon, 884);
+
+ // shapeRef885
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17904.5, 9347.42);
+ polygon.ps[1] = Point(17904.5, 9409.42);
+ polygon.ps[2] = Point(17842.5, 9409.42);
+ polygon.ps[3] = Point(17842.5, 9347.42);
+ new ShapeRef(router, polygon, 885);
+
+ // shapeRef886
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17739.5, 9149.42);
+ polygon.ps[1] = Point(17739.5, 9211.42);
+ polygon.ps[2] = Point(17677.5, 9211.42);
+ polygon.ps[3] = Point(17677.5, 9149.42);
+ new ShapeRef(router, polygon, 886);
+
+ // shapeRef887
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17739.5, 8611.22);
+ polygon.ps[1] = Point(17739.5, 8673.22);
+ polygon.ps[2] = Point(17677.5, 8673.22);
+ polygon.ps[3] = Point(17677.5, 8611.22);
+ new ShapeRef(router, polygon, 887);
+
+ // shapeRef888
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17739.5, 8218.99);
+ polygon.ps[1] = Point(17739.5, 8280.99);
+ polygon.ps[2] = Point(17677.5, 8280.99);
+ polygon.ps[3] = Point(17677.5, 8218.99);
+ new ShapeRef(router, polygon, 888);
+
+ // shapeRef889
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16130.6, 5900.59);
+ polygon.ps[1] = Point(16130.6, 5962.59);
+ polygon.ps[2] = Point(16068.6, 5962.59);
+ polygon.ps[3] = Point(16068.6, 5900.59);
+ new ShapeRef(router, polygon, 889);
+
+ // shapeRef890
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17739.5, 7581.79);
+ polygon.ps[1] = Point(17739.5, 7643.79);
+ polygon.ps[2] = Point(17677.5, 7643.79);
+ polygon.ps[3] = Point(17677.5, 7581.79);
+ new ShapeRef(router, polygon, 890);
+
+ // shapeRef891
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18036.5, 7581.79);
+ polygon.ps[1] = Point(18036.5, 7643.79);
+ polygon.ps[2] = Point(17974.5, 7643.79);
+ polygon.ps[3] = Point(17974.5, 7581.79);
+ new ShapeRef(router, polygon, 891);
+
+ // shapeRef892
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18333.5, 7581.79);
+ polygon.ps[1] = Point(18333.5, 7643.79);
+ polygon.ps[2] = Point(18271.5, 7643.79);
+ polygon.ps[3] = Point(18271.5, 7581.79);
+ new ShapeRef(router, polygon, 892);
+
+ // shapeRef893
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15763.9, 5692.9);
+ polygon.ps[1] = Point(15763.9, 5754.9);
+ polygon.ps[2] = Point(15701.9, 5754.9);
+ polygon.ps[3] = Point(15701.9, 5692.9);
+ new ShapeRef(router, polygon, 893);
+
+ // shapeRef894
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14794, 5692.9);
+ polygon.ps[1] = Point(14794, 5754.9);
+ polygon.ps[2] = Point(14732, 5754.9);
+ polygon.ps[3] = Point(14732, 5692.9);
+ new ShapeRef(router, polygon, 894);
+
+ // shapeRef895
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14266, 5692.9);
+ polygon.ps[1] = Point(14266, 5754.9);
+ polygon.ps[2] = Point(14204, 5754.9);
+ polygon.ps[3] = Point(14204, 5692.9);
+ new ShapeRef(router, polygon, 895);
+
+ // shapeRef896
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13705, 5692.9);
+ polygon.ps[1] = Point(13705, 5754.9);
+ polygon.ps[2] = Point(13643, 5754.9);
+ polygon.ps[3] = Point(13643, 5692.9);
+ new ShapeRef(router, polygon, 896);
+
+ // shapeRef897
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14266, 5415.67);
+ polygon.ps[1] = Point(14266, 5477.67);
+ polygon.ps[2] = Point(14204, 5477.67);
+ polygon.ps[3] = Point(14204, 5415.67);
+ new ShapeRef(router, polygon, 897);
+
+ // shapeRef898
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13705, 5415.67);
+ polygon.ps[1] = Point(13705, 5477.67);
+ polygon.ps[2] = Point(13643, 5477.67);
+ polygon.ps[3] = Point(13643, 5415.67);
+ new ShapeRef(router, polygon, 898);
+
+ // shapeRef899
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15763.9, 4841.4);
+ polygon.ps[1] = Point(15763.9, 4903.4);
+ polygon.ps[2] = Point(15701.9, 4903.4);
+ polygon.ps[3] = Point(15701.9, 4841.4);
+ new ShapeRef(router, polygon, 899);
+
+ // shapeRef900
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14794, 4841.4);
+ polygon.ps[1] = Point(14794, 4903.4);
+ polygon.ps[2] = Point(14732, 4903.4);
+ polygon.ps[3] = Point(14732, 4841.4);
+ new ShapeRef(router, polygon, 900);
+
+ // shapeRef901
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13705, 4511.4);
+ polygon.ps[1] = Point(13705, 4573.4);
+ polygon.ps[2] = Point(13643, 4573.4);
+ polygon.ps[3] = Point(13643, 4511.4);
+ new ShapeRef(router, polygon, 901);
+
+ // shapeRef902
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17277.5, 4511.4);
+ polygon.ps[1] = Point(17277.5, 4573.4);
+ polygon.ps[2] = Point(17215.5, 4573.4);
+ polygon.ps[3] = Point(17215.5, 4511.4);
+ new ShapeRef(router, polygon, 902);
+
+ // shapeRef903
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16852.8, 4511.4);
+ polygon.ps[1] = Point(16852.8, 4573.4);
+ polygon.ps[2] = Point(16790.8, 4573.4);
+ polygon.ps[3] = Point(16790.8, 4511.4);
+ new ShapeRef(router, polygon, 903);
+
+ // shapeRef904
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16654.8, 4511.4);
+ polygon.ps[1] = Point(16654.8, 4573.4);
+ polygon.ps[2] = Point(16592.8, 4573.4);
+ polygon.ps[3] = Point(16592.8, 4511.4);
+ new ShapeRef(router, polygon, 904);
+
+ // shapeRef905
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16262.6, 4511.4);
+ polygon.ps[1] = Point(16262.6, 4573.4);
+ polygon.ps[2] = Point(16200.6, 4573.4);
+ polygon.ps[3] = Point(16200.6, 4511.4);
+ new ShapeRef(router, polygon, 905);
+
+ // shapeRef906
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15763.9, 4511.4);
+ polygon.ps[1] = Point(15763.9, 4573.4);
+ polygon.ps[2] = Point(15701.9, 4573.4);
+ polygon.ps[3] = Point(15701.9, 4511.4);
+ new ShapeRef(router, polygon, 906);
+
+ // shapeRef907
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14794, 4511.4);
+ polygon.ps[1] = Point(14794, 4573.4);
+ polygon.ps[2] = Point(14732, 4573.4);
+ polygon.ps[3] = Point(14732, 4511.4);
+ new ShapeRef(router, polygon, 907);
+
+ // shapeRef908
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14266, 4511.4);
+ polygon.ps[1] = Point(14266, 4573.4);
+ polygon.ps[2] = Point(14204, 4573.4);
+ polygon.ps[3] = Point(14204, 4511.4);
+ new ShapeRef(router, polygon, 908);
+
+ // shapeRef909
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16654.8, 5217.67);
+ polygon.ps[1] = Point(16654.8, 5279.67);
+ polygon.ps[2] = Point(16592.8, 5279.67);
+ polygon.ps[3] = Point(16592.8, 5217.67);
+ new ShapeRef(router, polygon, 909);
+
+ // shapeRef910
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16262.6, 5217.67);
+ polygon.ps[1] = Point(16262.6, 5279.67);
+ polygon.ps[2] = Point(16200.6, 5279.67);
+ polygon.ps[3] = Point(16200.6, 5217.67);
+ new ShapeRef(router, polygon, 910);
+
+ // shapeRef911
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15763.9, 5217.67);
+ polygon.ps[1] = Point(15763.9, 5279.67);
+ polygon.ps[2] = Point(15701.9, 5279.67);
+ polygon.ps[3] = Point(15701.9, 5217.67);
+ new ShapeRef(router, polygon, 911);
+
+ // shapeRef912
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14794, 5217.67);
+ polygon.ps[1] = Point(14794, 5279.67);
+ polygon.ps[2] = Point(14732, 5279.67);
+ polygon.ps[3] = Point(14732, 5217.67);
+ new ShapeRef(router, polygon, 912);
+
+ // shapeRef913
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14266, 5217.67);
+ polygon.ps[1] = Point(14266, 5279.67);
+ polygon.ps[2] = Point(14204, 5279.67);
+ polygon.ps[3] = Point(14204, 5217.67);
+ new ShapeRef(router, polygon, 913);
+
+ // shapeRef914
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13705, 5217.67);
+ polygon.ps[1] = Point(13705, 5279.67);
+ polygon.ps[2] = Point(13643, 5279.67);
+ polygon.ps[3] = Point(13643, 5217.67);
+ new ShapeRef(router, polygon, 914);
+
+ // shapeRef915
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12953.5, 5217.67);
+ polygon.ps[1] = Point(12953.5, 5279.67);
+ polygon.ps[2] = Point(12891.5, 5279.67);
+ polygon.ps[3] = Point(12891.5, 5217.67);
+ new ShapeRef(router, polygon, 915);
+
+ // shapeRef916
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12562.5, 10506);
+ polygon.ps[1] = Point(12562.5, 10568);
+ polygon.ps[2] = Point(12500.5, 10568);
+ polygon.ps[3] = Point(12500.5, 10506);
+ new ShapeRef(router, polygon, 916);
+
+ // shapeRef917
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12562.5, 10209);
+ polygon.ps[1] = Point(12562.5, 10271);
+ polygon.ps[2] = Point(12500.5, 10271);
+ polygon.ps[3] = Point(12500.5, 10209);
+ new ShapeRef(router, polygon, 917);
+
+ // shapeRef918
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14827, 10011);
+ polygon.ps[1] = Point(14827, 10073);
+ polygon.ps[2] = Point(14765, 10073);
+ polygon.ps[3] = Point(14765, 10011);
+ new ShapeRef(router, polygon, 918);
+
+ // shapeRef919
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15471.5, 10275);
+ polygon.ps[1] = Point(15471.5, 10337);
+ polygon.ps[2] = Point(15409.5, 10337);
+ polygon.ps[3] = Point(15409.5, 10275);
+ new ShapeRef(router, polygon, 919);
+
+ // shapeRef920
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14728, 10275);
+ polygon.ps[1] = Point(14728, 10337);
+ polygon.ps[2] = Point(14666, 10337);
+ polygon.ps[3] = Point(14666, 10275);
+ new ShapeRef(router, polygon, 920);
+
+ // shapeRef921
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17805.5, 3468.51);
+ polygon.ps[1] = Point(17805.5, 3530.51);
+ polygon.ps[2] = Point(17743.5, 3530.51);
+ polygon.ps[3] = Point(17743.5, 3468.51);
+ new ShapeRef(router, polygon, 921);
+
+ // shapeRef922
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17508.5, 3468.51);
+ polygon.ps[1] = Point(17508.5, 3530.51);
+ polygon.ps[2] = Point(17446.5, 3530.51);
+ polygon.ps[3] = Point(17446.5, 3468.51);
+ new ShapeRef(router, polygon, 922);
+
+ // shapeRef923
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17050.8, 3468.51);
+ polygon.ps[1] = Point(17050.8, 3530.51);
+ polygon.ps[2] = Point(16988.8, 3530.51);
+ polygon.ps[3] = Point(16988.8, 3468.51);
+ new ShapeRef(router, polygon, 923);
+
+ // shapeRef924
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18797.5, 4709.4);
+ polygon.ps[1] = Point(18797.5, 4771.4);
+ polygon.ps[2] = Point(18735.5, 4771.4);
+ polygon.ps[3] = Point(18735.5, 4709.4);
+ new ShapeRef(router, polygon, 924);
+
+ // shapeRef925
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18797.5, 4478.4);
+ polygon.ps[1] = Point(18797.5, 4540.4);
+ polygon.ps[2] = Point(18735.5, 4540.4);
+ polygon.ps[3] = Point(18735.5, 4478.4);
+ new ShapeRef(router, polygon, 925);
+
+ // shapeRef926
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18797.5, 4095.51);
+ polygon.ps[1] = Point(18797.5, 4157.51);
+ polygon.ps[2] = Point(18735.5, 4157.51);
+ polygon.ps[3] = Point(18735.5, 4095.51);
+ new ShapeRef(router, polygon, 926);
+
+ // shapeRef927
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18580, 3798.51);
+ polygon.ps[1] = Point(18580, 3860.51);
+ polygon.ps[2] = Point(18518, 3860.51);
+ polygon.ps[3] = Point(18518, 3798.51);
+ new ShapeRef(router, polygon, 927);
+
+ // shapeRef928
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18366.5, 3798.51);
+ polygon.ps[1] = Point(18366.5, 3860.51);
+ polygon.ps[2] = Point(18304.5, 3860.51);
+ polygon.ps[3] = Point(18304.5, 3798.51);
+ new ShapeRef(router, polygon, 928);
+
+ // shapeRef929
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18135.5, 3798.51);
+ polygon.ps[1] = Point(18135.5, 3860.51);
+ polygon.ps[2] = Point(18073.5, 3860.51);
+ polygon.ps[3] = Point(18073.5, 3798.51);
+ new ShapeRef(router, polygon, 929);
+
+ // shapeRef930
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17805.5, 3798.51);
+ polygon.ps[1] = Point(17805.5, 3860.51);
+ polygon.ps[2] = Point(17743.5, 3860.51);
+ polygon.ps[3] = Point(17743.5, 3798.51);
+ new ShapeRef(router, polygon, 930);
+
+ // shapeRef931
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17508.5, 3798.51);
+ polygon.ps[1] = Point(17508.5, 3860.51);
+ polygon.ps[2] = Point(17446.5, 3860.51);
+ polygon.ps[3] = Point(17446.5, 3798.51);
+ new ShapeRef(router, polygon, 931);
+
+ // shapeRef932
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17050.8, 3798.51);
+ polygon.ps[1] = Point(17050.8, 3860.51);
+ polygon.ps[2] = Point(16988.8, 3860.51);
+ polygon.ps[3] = Point(16988.8, 3798.51);
+ new ShapeRef(router, polygon, 932);
+
+ // shapeRef933
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18580, 5006.4);
+ polygon.ps[1] = Point(18580, 5068.4);
+ polygon.ps[2] = Point(18518, 5068.4);
+ polygon.ps[3] = Point(18518, 5006.4);
+ new ShapeRef(router, polygon, 933);
+
+ // shapeRef934
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18580, 4709.4);
+ polygon.ps[1] = Point(18580, 4771.4);
+ polygon.ps[2] = Point(18518, 4771.4);
+ polygon.ps[3] = Point(18518, 4709.4);
+ new ShapeRef(router, polygon, 934);
+
+ // shapeRef935
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18580, 4478.4);
+ polygon.ps[1] = Point(18580, 4540.4);
+ polygon.ps[2] = Point(18518, 4540.4);
+ polygon.ps[3] = Point(18518, 4478.4);
+ new ShapeRef(router, polygon, 935);
+
+ // shapeRef936
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18580, 4095.51);
+ polygon.ps[1] = Point(18580, 4157.51);
+ polygon.ps[2] = Point(18518, 4157.51);
+ polygon.ps[3] = Point(18518, 4095.51);
+ new ShapeRef(router, polygon, 936);
+
+ // shapeRef937
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18366.5, 4095.51);
+ polygon.ps[1] = Point(18366.5, 4157.51);
+ polygon.ps[2] = Point(18304.5, 4157.51);
+ polygon.ps[3] = Point(18304.5, 4095.51);
+ new ShapeRef(router, polygon, 937);
+
+ // shapeRef938
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18135.5, 4095.51);
+ polygon.ps[1] = Point(18135.5, 4157.51);
+ polygon.ps[2] = Point(18073.5, 4157.51);
+ polygon.ps[3] = Point(18073.5, 4095.51);
+ new ShapeRef(router, polygon, 938);
+
+ // shapeRef939
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17050.8, 4095.51);
+ polygon.ps[1] = Point(17050.8, 4157.51);
+ polygon.ps[2] = Point(16988.8, 4157.51);
+ polygon.ps[3] = Point(16988.8, 4095.51);
+ new ShapeRef(router, polygon, 939);
+
+ // shapeRef940
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18102.5, 3307.29);
+ polygon.ps[1] = Point(18102.5, 3369.29);
+ polygon.ps[2] = Point(18040.5, 3369.29);
+ polygon.ps[3] = Point(18040.5, 3307.29);
+ new ShapeRef(router, polygon, 940);
+
+ // shapeRef941
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17739.5, 3307.29);
+ polygon.ps[1] = Point(17739.5, 3369.29);
+ polygon.ps[2] = Point(17677.5, 3369.29);
+ polygon.ps[3] = Point(17677.5, 3307.29);
+ new ShapeRef(router, polygon, 941);
+
+ // shapeRef942
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17343.5, 3307.29);
+ polygon.ps[1] = Point(17343.5, 3369.29);
+ polygon.ps[2] = Point(17281.5, 3369.29);
+ polygon.ps[3] = Point(17281.5, 3307.29);
+ new ShapeRef(router, polygon, 942);
+
+ // shapeRef943
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16885.8, 3307.29);
+ polygon.ps[1] = Point(16885.8, 3369.29);
+ polygon.ps[2] = Point(16823.8, 3369.29);
+ polygon.ps[3] = Point(16823.8, 3307.29);
+ new ShapeRef(router, polygon, 943);
+
+ // shapeRef944
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16588.8, 3307.29);
+ polygon.ps[1] = Point(16588.8, 3369.29);
+ polygon.ps[2] = Point(16526.8, 3369.29);
+ polygon.ps[3] = Point(16526.8, 3307.29);
+ new ShapeRef(router, polygon, 944);
+
+ // shapeRef945
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16064.6, 3307.29);
+ polygon.ps[1] = Point(16064.6, 3369.29);
+ polygon.ps[2] = Point(16002.6, 3369.29);
+ polygon.ps[3] = Point(16002.6, 3307.29);
+ new ShapeRef(router, polygon, 945);
+
+ // shapeRef946
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15146.3, 3307.29);
+ polygon.ps[1] = Point(15146.3, 3369.29);
+ polygon.ps[2] = Point(15084.3, 3369.29);
+ polygon.ps[3] = Point(15084.3, 3307.29);
+ new ShapeRef(router, polygon, 946);
+
+ // shapeRef947
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17050.8, 4775.4);
+ polygon.ps[1] = Point(17050.8, 4837.4);
+ polygon.ps[2] = Point(16988.8, 4837.4);
+ polygon.ps[3] = Point(16988.8, 4775.4);
+ new ShapeRef(router, polygon, 947);
+
+ // shapeRef948
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16786.8, 4775.4);
+ polygon.ps[1] = Point(16786.8, 4837.4);
+ polygon.ps[2] = Point(16724.8, 4837.4);
+ polygon.ps[3] = Point(16724.8, 4775.4);
+ new ShapeRef(router, polygon, 948);
+
+ // shapeRef949
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16427.6, 3864.51);
+ polygon.ps[1] = Point(16427.6, 3926.51);
+ polygon.ps[2] = Point(16365.6, 3926.51);
+ polygon.ps[3] = Point(16365.6, 3864.51);
+ new ShapeRef(router, polygon, 949);
+
+ // shapeRef950
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15998.6, 3864.51);
+ polygon.ps[1] = Point(15998.6, 3926.51);
+ polygon.ps[2] = Point(15936.6, 3926.51);
+ polygon.ps[3] = Point(15936.6, 3864.51);
+ new ShapeRef(router, polygon, 950);
+
+ // shapeRef951
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15146.3, 3864.51);
+ polygon.ps[1] = Point(15146.3, 3926.51);
+ polygon.ps[2] = Point(15084.3, 3926.51);
+ polygon.ps[3] = Point(15084.3, 3864.51);
+ new ShapeRef(router, polygon, 951);
+
+ // shapeRef952
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16786.8, 3600.51);
+ polygon.ps[1] = Point(16786.8, 3662.51);
+ polygon.ps[2] = Point(16724.8, 3662.51);
+ polygon.ps[3] = Point(16724.8, 3600.51);
+ new ShapeRef(router, polygon, 952);
+
+ // shapeRef953
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16361.6, 3600.51);
+ polygon.ps[1] = Point(16361.6, 3662.51);
+ polygon.ps[2] = Point(16299.6, 3662.51);
+ polygon.ps[3] = Point(16299.6, 3600.51);
+ new ShapeRef(router, polygon, 953);
+
+ // shapeRef954
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15541.3, 3600.51);
+ polygon.ps[1] = Point(15541.3, 3662.51);
+ polygon.ps[2] = Point(15479.3, 3662.51);
+ polygon.ps[3] = Point(15479.3, 3600.51);
+ new ShapeRef(router, polygon, 954);
+
+ // shapeRef955
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16786.8, 4095.51);
+ polygon.ps[1] = Point(16786.8, 4157.51);
+ polygon.ps[2] = Point(16724.8, 4157.51);
+ polygon.ps[3] = Point(16724.8, 4095.51);
+ new ShapeRef(router, polygon, 955);
+
+ // shapeRef956
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16588.8, 4095.51);
+ polygon.ps[1] = Point(16588.8, 4157.51);
+ polygon.ps[2] = Point(16526.8, 4157.51);
+ polygon.ps[3] = Point(16526.8, 4095.51);
+ new ShapeRef(router, polygon, 956);
+
+ // shapeRef957
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16163.6, 4095.51);
+ polygon.ps[1] = Point(16163.6, 4157.51);
+ polygon.ps[2] = Point(16101.6, 4157.51);
+ polygon.ps[3] = Point(16101.6, 4095.51);
+ new ShapeRef(router, polygon, 957);
+
+ // shapeRef958
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15541.3, 4095.51);
+ polygon.ps[1] = Point(15541.3, 4157.51);
+ polygon.ps[2] = Point(15479.3, 4157.51);
+ polygon.ps[3] = Point(15479.3, 4095.51);
+ new ShapeRef(router, polygon, 958);
+
+ // shapeRef959
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15635.3, 2713.29);
+ polygon.ps[1] = Point(15635.3, 2775.29);
+ polygon.ps[2] = Point(15573.3, 2775.29);
+ polygon.ps[3] = Point(15573.3, 2713.29);
+ new ShapeRef(router, polygon, 959);
+
+ // shapeRef960
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14662, 3208.29);
+ polygon.ps[1] = Point(14662, 3270.29);
+ polygon.ps[2] = Point(14600, 3270.29);
+ polygon.ps[3] = Point(14600, 3208.29);
+ new ShapeRef(router, polygon, 960);
+
+ // shapeRef961
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16720.8, 2944.29);
+ polygon.ps[1] = Point(16720.8, 3006.29);
+ polygon.ps[2] = Point(16658.8, 3006.29);
+ polygon.ps[3] = Point(16658.8, 2944.29);
+ new ShapeRef(router, polygon, 961);
+
+ // shapeRef962
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16295.6, 2944.29);
+ polygon.ps[1] = Point(16295.6, 3006.29);
+ polygon.ps[2] = Point(16233.6, 3006.29);
+ polygon.ps[3] = Point(16233.6, 2944.29);
+ new ShapeRef(router, polygon, 962);
+
+ // shapeRef963
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15635.3, 2944.29);
+ polygon.ps[1] = Point(15635.3, 3006.29);
+ polygon.ps[2] = Point(15573.3, 3006.29);
+ polygon.ps[3] = Point(15573.3, 2944.29);
+ new ShapeRef(router, polygon, 963);
+
+ // shapeRef964
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14662, 2944.29);
+ polygon.ps[1] = Point(14662, 3006.29);
+ polygon.ps[2] = Point(14600, 3006.29);
+ polygon.ps[3] = Point(14600, 2944.29);
+ new ShapeRef(router, polygon, 964);
+
+ // shapeRef965
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13969, 2944.29);
+ polygon.ps[1] = Point(13969, 3006.29);
+ polygon.ps[2] = Point(13907, 3006.29);
+ polygon.ps[3] = Point(13907, 2944.29);
+ new ShapeRef(router, polygon, 965);
+
+ // shapeRef966
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13969, 3307.29);
+ polygon.ps[1] = Point(13969, 3369.29);
+ polygon.ps[2] = Point(13907, 3369.29);
+ polygon.ps[3] = Point(13907, 3307.29);
+ new ShapeRef(router, polygon, 966);
+
+ // shapeRef967
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13969, 3600.51);
+ polygon.ps[1] = Point(13969, 3662.51);
+ polygon.ps[2] = Point(13907, 3662.51);
+ polygon.ps[3] = Point(13907, 3600.51);
+ new ShapeRef(router, polygon, 967);
+
+ // shapeRef968
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14728, 4095.51);
+ polygon.ps[1] = Point(14728, 4157.51);
+ polygon.ps[2] = Point(14666, 4157.51);
+ polygon.ps[3] = Point(14666, 4095.51);
+ new ShapeRef(router, polygon, 968);
+
+ // shapeRef969
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13969, 4095.51);
+ polygon.ps[1] = Point(13969, 4157.51);
+ polygon.ps[2] = Point(13907, 4157.51);
+ polygon.ps[3] = Point(13907, 4095.51);
+ new ShapeRef(router, polygon, 969);
+
+ // shapeRef970
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16130.6, 6549.51);
+ polygon.ps[1] = Point(16130.6, 6611.51);
+ polygon.ps[2] = Point(16068.6, 6611.51);
+ polygon.ps[3] = Point(16068.6, 6549.51);
+ new ShapeRef(router, polygon, 970);
+
+ // shapeRef971
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13540, 6549.51);
+ polygon.ps[1] = Point(13540, 6611.51);
+ polygon.ps[2] = Point(13478, 6611.51);
+ polygon.ps[3] = Point(13478, 6549.51);
+ new ShapeRef(router, polygon, 971);
+
+ // shapeRef972
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16031.6, 11015.6);
+ polygon.ps[1] = Point(16031.6, 11077.6);
+ polygon.ps[2] = Point(15969.6, 11077.6);
+ polygon.ps[3] = Point(15969.6, 11015.6);
+ new ShapeRef(router, polygon, 972);
+
+ // shapeRef973
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16031.6, 10473);
+ polygon.ps[1] = Point(16031.6, 10535);
+ polygon.ps[2] = Point(15969.6, 10535);
+ polygon.ps[3] = Point(15969.6, 10473);
+ new ShapeRef(router, polygon, 973);
+
+ // shapeRef974
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16031.6, 9644.42);
+ polygon.ps[1] = Point(16031.6, 9706.42);
+ polygon.ps[2] = Point(15969.6, 9706.42);
+ polygon.ps[3] = Point(15969.6, 9644.42);
+ new ShapeRef(router, polygon, 974);
+
+ // shapeRef975
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15471.5, 10684.3);
+ polygon.ps[1] = Point(15471.5, 10746.3);
+ polygon.ps[2] = Point(15409.5, 10746.3);
+ polygon.ps[3] = Point(15409.5, 10684.3);
+ new ShapeRef(router, polygon, 975);
+
+ // shapeRef976
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15471.5, 10044);
+ polygon.ps[1] = Point(15471.5, 10106);
+ polygon.ps[2] = Point(15409.5, 10106);
+ polygon.ps[3] = Point(15409.5, 10044);
+ new ShapeRef(router, polygon, 976);
+
+ // shapeRef977
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15471.5, 11015.6);
+ polygon.ps[1] = Point(15471.5, 11077.6);
+ polygon.ps[2] = Point(15409.5, 11077.6);
+ polygon.ps[3] = Point(15409.5, 11015.6);
+ new ShapeRef(router, polygon, 977);
+
+ // shapeRef978
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15471.5, 10473);
+ polygon.ps[1] = Point(15471.5, 10535);
+ polygon.ps[2] = Point(15409.5, 10535);
+ polygon.ps[3] = Point(15409.5, 10473);
+ new ShapeRef(router, polygon, 978);
+
+ // shapeRef979
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15471.5, 9644.42);
+ polygon.ps[1] = Point(15471.5, 9706.42);
+ polygon.ps[2] = Point(15409.5, 9706.42);
+ polygon.ps[3] = Point(15409.5, 9644.42);
+ new ShapeRef(router, polygon, 979);
+
+ // shapeRef980
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14299, 10275);
+ polygon.ps[1] = Point(14299, 10337);
+ polygon.ps[2] = Point(14237, 10337);
+ polygon.ps[3] = Point(14237, 10275);
+ new ShapeRef(router, polygon, 980);
+
+ // shapeRef981
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14299, 10011);
+ polygon.ps[1] = Point(14299, 10073);
+ polygon.ps[2] = Point(14237, 10073);
+ polygon.ps[3] = Point(14237, 10011);
+ new ShapeRef(router, polygon, 981);
+
+ // shapeRef982
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13507, 10275);
+ polygon.ps[1] = Point(13507, 10337);
+ polygon.ps[2] = Point(13445, 10337);
+ polygon.ps[3] = Point(13445, 10275);
+ new ShapeRef(router, polygon, 982);
+
+ // shapeRef983
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13507, 10011);
+ polygon.ps[1] = Point(13507, 10073);
+ polygon.ps[2] = Point(13445, 10073);
+ polygon.ps[3] = Point(13445, 10011);
+ new ShapeRef(router, polygon, 983);
+
+ // shapeRef984
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13969, 11015.6);
+ polygon.ps[1] = Point(13969, 11077.6);
+ polygon.ps[2] = Point(13907, 11077.6);
+ polygon.ps[3] = Point(13907, 11015.6);
+ new ShapeRef(router, polygon, 984);
+
+ // shapeRef985
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13969, 10473);
+ polygon.ps[1] = Point(13969, 10535);
+ polygon.ps[2] = Point(13907, 10535);
+ polygon.ps[3] = Point(13907, 10473);
+ new ShapeRef(router, polygon, 985);
+
+ // shapeRef986
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13969, 9644.42);
+ polygon.ps[1] = Point(13969, 9706.42);
+ polygon.ps[2] = Point(13907, 9706.42);
+ polygon.ps[3] = Point(13907, 9644.42);
+ new ShapeRef(router, polygon, 986);
+
+ // shapeRef987
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13198, 11015.6);
+ polygon.ps[1] = Point(13198, 11077.6);
+ polygon.ps[2] = Point(13136, 11077.6);
+ polygon.ps[3] = Point(13136, 11015.6);
+ new ShapeRef(router, polygon, 987);
+
+ // shapeRef988
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13198, 10473);
+ polygon.ps[1] = Point(13198, 10535);
+ polygon.ps[2] = Point(13136, 10535);
+ polygon.ps[3] = Point(13136, 10473);
+ new ShapeRef(router, polygon, 988);
+
+ // shapeRef989
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13198, 9644.42);
+ polygon.ps[1] = Point(13198, 9706.42);
+ polygon.ps[2] = Point(13136, 9706.42);
+ polygon.ps[3] = Point(13136, 9644.42);
+ new ShapeRef(router, polygon, 989);
+
+ // shapeRef990
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16753.8, 7581.79);
+ polygon.ps[1] = Point(16753.8, 7643.79);
+ polygon.ps[2] = Point(16691.8, 7643.79);
+ polygon.ps[3] = Point(16691.8, 7581.79);
+ new ShapeRef(router, polygon, 990);
+
+ // shapeRef991
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16753.8, 7031.4);
+ polygon.ps[1] = Point(16753.8, 7093.4);
+ polygon.ps[2] = Point(16691.8, 7093.4);
+ polygon.ps[3] = Point(16691.8, 7031.4);
+ new ShapeRef(router, polygon, 991);
+
+ // shapeRef992
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16753.8, 6384.51);
+ polygon.ps[1] = Point(16753.8, 6446.51);
+ polygon.ps[2] = Point(16691.8, 6446.51);
+ polygon.ps[3] = Point(16691.8, 6384.51);
+ new ShapeRef(router, polygon, 992);
+
+ // shapeRef993
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16460.6, 8218.99);
+ polygon.ps[1] = Point(16460.6, 8280.99);
+ polygon.ps[2] = Point(16398.6, 8280.99);
+ polygon.ps[3] = Point(16398.6, 8218.99);
+ new ShapeRef(router, polygon, 993);
+
+ // shapeRef994
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16460.6, 7581.79);
+ polygon.ps[1] = Point(16460.6, 7643.79);
+ polygon.ps[2] = Point(16398.6, 7643.79);
+ polygon.ps[3] = Point(16398.6, 7581.79);
+ new ShapeRef(router, polygon, 994);
+
+ // shapeRef995
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16460.6, 7031.4);
+ polygon.ps[1] = Point(16460.6, 7093.4);
+ polygon.ps[2] = Point(16398.6, 7093.4);
+ polygon.ps[3] = Point(16398.6, 7031.4);
+ new ShapeRef(router, polygon, 995);
+
+ // shapeRef996
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16460.6, 6384.51);
+ polygon.ps[1] = Point(16460.6, 6446.51);
+ polygon.ps[2] = Point(16398.6, 6446.51);
+ polygon.ps[3] = Point(16398.6, 6384.51);
+ new ShapeRef(router, polygon, 996);
+
+ // shapeRef997
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15899.6, 7581.79);
+ polygon.ps[1] = Point(15899.6, 7643.79);
+ polygon.ps[2] = Point(15837.6, 7643.79);
+ polygon.ps[3] = Point(15837.6, 7581.79);
+ new ShapeRef(router, polygon, 997);
+
+ // shapeRef998
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15899.6, 7031.4);
+ polygon.ps[1] = Point(15899.6, 7093.4);
+ polygon.ps[2] = Point(15837.6, 7093.4);
+ polygon.ps[3] = Point(15837.6, 7031.4);
+ new ShapeRef(router, polygon, 998);
+
+ // shapeRef999
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15899.6, 6384.51);
+ polygon.ps[1] = Point(15899.6, 6446.51);
+ polygon.ps[2] = Point(15837.6, 6446.51);
+ polygon.ps[3] = Point(15837.6, 6384.51);
+ new ShapeRef(router, polygon, 999);
+
+ // shapeRef1000
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14530, 7262.4);
+ polygon.ps[1] = Point(14530, 7324.4);
+ polygon.ps[2] = Point(14468, 7324.4);
+ polygon.ps[3] = Point(14468, 7262.4);
+ new ShapeRef(router, polygon, 1000);
+
+ // shapeRef1001
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14134, 7262.4);
+ polygon.ps[1] = Point(14134, 7324.4);
+ polygon.ps[2] = Point(14072, 7324.4);
+ polygon.ps[3] = Point(14072, 7262.4);
+ new ShapeRef(router, polygon, 1001);
+
+ // shapeRef1002
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14530, 6615.51);
+ polygon.ps[1] = Point(14530, 6677.51);
+ polygon.ps[2] = Point(14468, 6677.51);
+ polygon.ps[3] = Point(14468, 6615.51);
+ new ShapeRef(router, polygon, 1002);
+
+ // shapeRef1003
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14134, 6615.51);
+ polygon.ps[1] = Point(14134, 6677.51);
+ polygon.ps[2] = Point(14072, 6677.51);
+ polygon.ps[3] = Point(14072, 6615.51);
+ new ShapeRef(router, polygon, 1003);
+
+ // shapeRef1004
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14827, 8218.99);
+ polygon.ps[1] = Point(14827, 8280.99);
+ polygon.ps[2] = Point(14765, 8280.99);
+ polygon.ps[3] = Point(14765, 8218.99);
+ new ShapeRef(router, polygon, 1004);
+
+ // shapeRef1005
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14827, 7581.79);
+ polygon.ps[1] = Point(14827, 7643.79);
+ polygon.ps[2] = Point(14765, 7643.79);
+ polygon.ps[3] = Point(14765, 7581.79);
+ new ShapeRef(router, polygon, 1005);
+
+ // shapeRef1006
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14827, 7031.4);
+ polygon.ps[1] = Point(14827, 7093.4);
+ polygon.ps[2] = Point(14765, 7093.4);
+ polygon.ps[3] = Point(14765, 7031.4);
+ new ShapeRef(router, polygon, 1006);
+
+ // shapeRef1007
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14827, 6384.51);
+ polygon.ps[1] = Point(14827, 6446.51);
+ polygon.ps[2] = Point(14765, 6446.51);
+ polygon.ps[3] = Point(14765, 6384.51);
+ new ShapeRef(router, polygon, 1007);
+
+ // shapeRef1008
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11955.1, 8710.22);
+ polygon.ps[1] = Point(11955.1, 8772.22);
+ polygon.ps[2] = Point(11893.1, 8772.22);
+ polygon.ps[3] = Point(11893.1, 8710.22);
+ new ShapeRef(router, polygon, 1008);
+
+ // shapeRef1009
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11955.1, 7031.4);
+ polygon.ps[1] = Point(11955.1, 7093.4);
+ polygon.ps[2] = Point(11893.1, 7093.4);
+ polygon.ps[3] = Point(11893.1, 7031.4);
+ new ShapeRef(router, polygon, 1009);
+
+ // shapeRef1010
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11955.1, 6384.51);
+ polygon.ps[1] = Point(11955.1, 6446.51);
+ polygon.ps[2] = Point(11893.1, 6446.51);
+ polygon.ps[3] = Point(11893.1, 6384.51);
+ new ShapeRef(router, polygon, 1010);
+
+ // shapeRef1011
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13903, 7581.79);
+ polygon.ps[1] = Point(13903, 7643.79);
+ polygon.ps[2] = Point(13841, 7643.79);
+ polygon.ps[3] = Point(13841, 7581.79);
+ new ShapeRef(router, polygon, 1011);
+
+ // shapeRef1012
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12562.5, 7581.79);
+ polygon.ps[1] = Point(12562.5, 7643.79);
+ polygon.ps[2] = Point(12500.5, 7643.79);
+ polygon.ps[3] = Point(12500.5, 7581.79);
+ new ShapeRef(router, polygon, 1012);
+
+ // shapeRef1013
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12562.5, 7031.4);
+ polygon.ps[1] = Point(12562.5, 7093.4);
+ polygon.ps[2] = Point(12500.5, 7093.4);
+ polygon.ps[3] = Point(12500.5, 7031.4);
+ new ShapeRef(router, polygon, 1013);
+
+ // shapeRef1014
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12562.5, 6384.51);
+ polygon.ps[1] = Point(12562.5, 6446.51);
+ polygon.ps[2] = Point(12500.5, 6446.51);
+ polygon.ps[3] = Point(12500.5, 6384.51);
+ new ShapeRef(router, polygon, 1014);
+
+ // shapeRef1015
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11203.2, 5481.67);
+ polygon.ps[1] = Point(11203.2, 5543.67);
+ polygon.ps[2] = Point(11141.2, 5543.67);
+ polygon.ps[3] = Point(11141.2, 5481.67);
+ new ShapeRef(router, polygon, 1015);
+
+ // shapeRef1016
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10675.2, 5481.67);
+ polygon.ps[1] = Point(10675.2, 5543.67);
+ polygon.ps[2] = Point(10613.2, 5543.67);
+ polygon.ps[3] = Point(10613.2, 5481.67);
+ new ShapeRef(router, polygon, 1016);
+
+ // shapeRef1017
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9815.69, 4973.4);
+ polygon.ps[1] = Point(9815.69, 5035.4);
+ polygon.ps[2] = Point(9753.69, 5035.4);
+ polygon.ps[3] = Point(9753.69, 4973.4);
+ new ShapeRef(router, polygon, 1017);
+
+ // shapeRef1018
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15471.5, 11355.8);
+ polygon.ps[1] = Point(15471.5, 11417.8);
+ polygon.ps[2] = Point(15409.5, 11417.8);
+ polygon.ps[3] = Point(15409.5, 11355.8);
+ new ShapeRef(router, polygon, 1018);
+
+ // shapeRef1019
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14662, 7878.79);
+ polygon.ps[1] = Point(14662, 7940.79);
+ polygon.ps[2] = Point(14600, 7940.79);
+ polygon.ps[3] = Point(14600, 7878.79);
+ new ShapeRef(router, polygon, 1019);
+
+ // shapeRef1020
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16130.6, 8449.99);
+ polygon.ps[1] = Point(16130.6, 8511.99);
+ polygon.ps[2] = Point(16068.6, 8511.99);
+ polygon.ps[3] = Point(16068.6, 8449.99);
+ new ShapeRef(router, polygon, 1020);
+
+ // shapeRef1021
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16130.6, 7878.79);
+ polygon.ps[1] = Point(16130.6, 7940.79);
+ polygon.ps[2] = Point(16068.6, 7940.79);
+ polygon.ps[3] = Point(16068.6, 7878.79);
+ new ShapeRef(router, polygon, 1021);
+
+ // shapeRef1022
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14662, 8449.99);
+ polygon.ps[1] = Point(14662, 8511.99);
+ polygon.ps[2] = Point(14600, 8511.99);
+ polygon.ps[3] = Point(14600, 8449.99);
+ new ShapeRef(router, polygon, 1022);
+
+ // shapeRef1023
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13540, 8449.99);
+ polygon.ps[1] = Point(13540, 8511.99);
+ polygon.ps[2] = Point(13478, 8511.99);
+ polygon.ps[3] = Point(13478, 8449.99);
+ new ShapeRef(router, polygon, 1023);
+
+ // shapeRef1024
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13540, 7878.79);
+ polygon.ps[1] = Point(13540, 7940.79);
+ polygon.ps[2] = Point(13478, 7940.79);
+ polygon.ps[3] = Point(13478, 7878.79);
+ new ShapeRef(router, polygon, 1024);
+
+ // shapeRef1025
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16130.6, 6058.29);
+ polygon.ps[1] = Point(16130.6, 6120.29);
+ polygon.ps[2] = Point(16068.6, 6120.29);
+ polygon.ps[3] = Point(16068.6, 6058.29);
+ new ShapeRef(router, polygon, 1025);
+
+ // shapeRef1026
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14662, 6058.29);
+ polygon.ps[1] = Point(14662, 6120.29);
+ polygon.ps[2] = Point(14600, 6120.29);
+ polygon.ps[3] = Point(14600, 6058.29);
+ new ShapeRef(router, polygon, 1026);
+
+ // shapeRef1027
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13540, 6058.29);
+ polygon.ps[1] = Point(13540, 6120.29);
+ polygon.ps[2] = Point(13478, 6120.29);
+ polygon.ps[3] = Point(13478, 6058.29);
+ new ShapeRef(router, polygon, 1027);
+
+ // shapeRef1028
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16588.8, 3468.51);
+ polygon.ps[1] = Point(16588.8, 3530.51);
+ polygon.ps[2] = Point(16526.8, 3530.51);
+ polygon.ps[3] = Point(16526.8, 3468.51);
+ new ShapeRef(router, polygon, 1028);
+
+ // shapeRef1029
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16064.6, 3468.51);
+ polygon.ps[1] = Point(16064.6, 3530.51);
+ polygon.ps[2] = Point(16002.6, 3530.51);
+ polygon.ps[3] = Point(16002.6, 3468.51);
+ new ShapeRef(router, polygon, 1029);
+
+ // shapeRef1030
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15146.3, 3468.51);
+ polygon.ps[1] = Point(15146.3, 3530.51);
+ polygon.ps[2] = Point(15084.3, 3530.51);
+ polygon.ps[3] = Point(15084.3, 3468.51);
+ new ShapeRef(router, polygon, 1030);
+
+ // shapeRef1031
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17805.5, 4095.51);
+ polygon.ps[1] = Point(17805.5, 4157.51);
+ polygon.ps[2] = Point(17743.5, 4157.51);
+ polygon.ps[3] = Point(17743.5, 4095.51);
+ new ShapeRef(router, polygon, 1031);
+
+ // shapeRef1032
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17508.5, 4095.51);
+ polygon.ps[1] = Point(17508.5, 4157.51);
+ polygon.ps[2] = Point(17446.5, 4157.51);
+ polygon.ps[3] = Point(17446.5, 4095.51);
+ new ShapeRef(router, polygon, 1032);
+
+ // shapeRef1033
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14662, 9479.42);
+ polygon.ps[1] = Point(14662, 9541.42);
+ polygon.ps[2] = Point(14600, 9541.42);
+ polygon.ps[3] = Point(14600, 9479.42);
+ new ShapeRef(router, polygon, 1033);
+
+ // shapeRef1034
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16753.8, 8842.22);
+ polygon.ps[1] = Point(16753.8, 8904.22);
+ polygon.ps[2] = Point(16691.8, 8904.22);
+ polygon.ps[3] = Point(16691.8, 8842.22);
+ new ShapeRef(router, polygon, 1034);
+
+ // shapeRef1035
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12953.5, 6058.29);
+ polygon.ps[1] = Point(12953.5, 6120.29);
+ polygon.ps[2] = Point(12891.5, 6120.29);
+ polygon.ps[3] = Point(12891.5, 6058.29);
+ new ShapeRef(router, polygon, 1035);
+
+ // shapeRef1036
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12953.5, 5692.9);
+ polygon.ps[1] = Point(12953.5, 5754.9);
+ polygon.ps[2] = Point(12891.5, 5754.9);
+ polygon.ps[3] = Point(12891.5, 5692.9);
+ new ShapeRef(router, polygon, 1036);
+
+ // shapeRef1037
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1416, 7163.4);
+ polygon.ps[1] = Point(1416, 7225.4);
+ polygon.ps[2] = Point(1354, 7225.4);
+ polygon.ps[3] = Point(1354, 7163.4);
+ new ShapeRef(router, polygon, 1037);
+
+ // shapeRef1038
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4023, 6252.51);
+ polygon.ps[1] = Point(4023, 6314.51);
+ polygon.ps[2] = Point(3961, 6314.51);
+ polygon.ps[3] = Point(3961, 6252.51);
+ new ShapeRef(router, polygon, 1038);
+
+ // shapeRef1039
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13969, 3864.51);
+ polygon.ps[1] = Point(13969, 3926.51);
+ polygon.ps[2] = Point(13907, 3926.51);
+ polygon.ps[3] = Point(13907, 3864.51);
+ new ShapeRef(router, polygon, 1039);
+
+ // shapeRef1040
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14497, 3600.51);
+ polygon.ps[1] = Point(14497, 3662.51);
+ polygon.ps[2] = Point(14435, 3662.51);
+ polygon.ps[3] = Point(14435, 3600.51);
+ new ShapeRef(router, polygon, 1040);
+
+ // shapeRef1041
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17607.5, 6757.21);
+ polygon.ps[1] = Point(17607.5, 6819.21);
+ polygon.ps[2] = Point(17545.5, 6819.21);
+ polygon.ps[3] = Point(17545.5, 6757.21);
+ new ShapeRef(router, polygon, 1041);
+
+ // shapeRef1042
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12054.1, 6757.21);
+ polygon.ps[1] = Point(12054.1, 6819.21);
+ polygon.ps[2] = Point(11992.1, 6819.21);
+ polygon.ps[3] = Point(11992.1, 6757.21);
+ new ShapeRef(router, polygon, 1042);
+
+ // shapeRef1043
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10013.7, 5626.9);
+ polygon.ps[1] = Point(10013.7, 5688.9);
+ polygon.ps[2] = Point(9951.69, 5688.9);
+ polygon.ps[3] = Point(9951.69, 5626.9);
+ new ShapeRef(router, polygon, 1043);
+
+ // shapeRef1044
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2769, 10176);
+ polygon.ps[1] = Point(2769, 10238);
+ polygon.ps[2] = Point(2707, 10238);
+ polygon.ps[3] = Point(2707, 10176);
+ new ShapeRef(router, polygon, 1044);
+
+ // shapeRef1045
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5758.1, 5184.67);
+ polygon.ps[1] = Point(5758.1, 5246.67);
+ polygon.ps[2] = Point(5696.1, 5246.67);
+ polygon.ps[3] = Point(5696.1, 5184.67);
+ new ShapeRef(router, polygon, 1045);
+
+ // shapeRef1046
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15270.5, 1480.29);
+ polygon.ps[1] = Point(15270.5, 1542.29);
+ polygon.ps[2] = Point(15208.5, 1542.29);
+ polygon.ps[3] = Point(15208.5, 1480.29);
+ new ShapeRef(router, polygon, 1046);
+
+ // shapeRef1047
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13903, 6384.51);
+ polygon.ps[1] = Point(13903, 6446.51);
+ polygon.ps[2] = Point(13841, 6446.51);
+ polygon.ps[3] = Point(13841, 6384.51);
+ new ShapeRef(router, polygon, 1047);
+
+ // shapeRef1048
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13297, 5105.4);
+ polygon.ps[1] = Point(13297, 5167.4);
+ polygon.ps[2] = Point(13235, 5167.4);
+ polygon.ps[3] = Point(13235, 5105.4);
+ new ShapeRef(router, polygon, 1048);
+
+ // shapeRef1049
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11427.1, 7262.4);
+ polygon.ps[1] = Point(11427.1, 7324.4);
+ polygon.ps[2] = Point(11365.1, 7324.4);
+ polygon.ps[3] = Point(11365.1, 7262.4);
+ new ShapeRef(router, polygon, 1049);
+
+ // shapeRef1050
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17937.5, 11829.9);
+ polygon.ps[1] = Point(17937.5, 11891.9);
+ polygon.ps[2] = Point(17875.5, 11891.9);
+ polygon.ps[3] = Point(17875.5, 11829.9);
+ new ShapeRef(router, polygon, 1050);
+
+ // shapeRef1051
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18201.5, 11829.9);
+ polygon.ps[1] = Point(18201.5, 11891.9);
+ polygon.ps[2] = Point(18139.5, 11891.9);
+ polygon.ps[3] = Point(18139.5, 11829.9);
+ new ShapeRef(router, polygon, 1051);
+
+ // shapeRef1052
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16621.8, 8743.22);
+ polygon.ps[1] = Point(16621.8, 8805.22);
+ polygon.ps[2] = Point(16559.8, 8805.22);
+ polygon.ps[3] = Point(16559.8, 8743.22);
+ new ShapeRef(router, polygon, 1052);
+
+ // shapeRef1053
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13198, 5382.67);
+ polygon.ps[1] = Point(13198, 5444.67);
+ polygon.ps[2] = Point(13136, 5444.67);
+ polygon.ps[3] = Point(13136, 5382.67);
+ new ShapeRef(router, polygon, 1053);
+
+ // shapeRef1054
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11922.1, 5382.67);
+ polygon.ps[1] = Point(11922.1, 5444.67);
+ polygon.ps[2] = Point(11860.1, 5444.67);
+ polygon.ps[3] = Point(11860.1, 5382.67);
+ new ShapeRef(router, polygon, 1054);
+
+ // shapeRef1055
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11922.1, 5725.9);
+ polygon.ps[1] = Point(11922.1, 5787.9);
+ polygon.ps[2] = Point(11860.1, 5787.9);
+ polygon.ps[3] = Point(11860.1, 5725.9);
+ new ShapeRef(router, polygon, 1055);
+
+ // shapeRef1056
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12219.1, 5382.67);
+ polygon.ps[1] = Point(12219.1, 5444.67);
+ polygon.ps[2] = Point(12157.1, 5444.67);
+ polygon.ps[3] = Point(12157.1, 5382.67);
+ new ShapeRef(router, polygon, 1056);
+
+ // shapeRef1057
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11922.1, 6186.51);
+ polygon.ps[1] = Point(11922.1, 6248.51);
+ polygon.ps[2] = Point(11860.1, 6248.51);
+ polygon.ps[3] = Point(11860.1, 6186.51);
+ new ShapeRef(router, polygon, 1057);
+
+ // shapeRef1058
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12219.1, 6186.51);
+ polygon.ps[1] = Point(12219.1, 6248.51);
+ polygon.ps[2] = Point(12157.1, 6248.51);
+ polygon.ps[3] = Point(12157.1, 6186.51);
+ new ShapeRef(router, polygon, 1058);
+
+ // shapeRef1059
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12562.5, 7746.79);
+ polygon.ps[1] = Point(12562.5, 7808.79);
+ polygon.ps[2] = Point(12500.5, 7808.79);
+ polygon.ps[3] = Point(12500.5, 7746.79);
+ new ShapeRef(router, polygon, 1059);
+
+ // shapeRef1060
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16295.6, 8449.99);
+ polygon.ps[1] = Point(16295.6, 8511.99);
+ polygon.ps[2] = Point(16233.6, 8511.99);
+ polygon.ps[3] = Point(16233.6, 8449.99);
+ new ShapeRef(router, polygon, 1060);
+
+ // shapeRef1061
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16295.6, 8743.22);
+ polygon.ps[1] = Point(16295.6, 8805.22);
+ polygon.ps[2] = Point(16233.6, 8805.22);
+ polygon.ps[3] = Point(16233.6, 8743.22);
+ new ShapeRef(router, polygon, 1061);
+
+ // shapeRef1062
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16588.8, 8449.99);
+ polygon.ps[1] = Point(16588.8, 8511.99);
+ polygon.ps[2] = Point(16526.8, 8511.99);
+ polygon.ps[3] = Point(16526.8, 8449.99);
+ new ShapeRef(router, polygon, 1062);
+
+ // shapeRef1063
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2175, 5481.67);
+ polygon.ps[1] = Point(2175, 5543.67);
+ polygon.ps[2] = Point(2113, 5543.67);
+ polygon.ps[3] = Point(2113, 5481.67);
+ new ShapeRef(router, polygon, 1063);
+
+ // shapeRef1064
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1779, 5481.67);
+ polygon.ps[1] = Point(1779, 5543.67);
+ polygon.ps[2] = Point(1717, 5543.67);
+ polygon.ps[3] = Point(1717, 5481.67);
+ new ShapeRef(router, polygon, 1064);
+
+ // shapeRef1065
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(723, 5481.67);
+ polygon.ps[1] = Point(723, 5543.67);
+ polygon.ps[2] = Point(661, 5543.67);
+ polygon.ps[3] = Point(661, 5481.67);
+ new ShapeRef(router, polygon, 1065);
+
+ // shapeRef1066
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5013, 5039.4);
+ polygon.ps[1] = Point(5013, 5101.4);
+ polygon.ps[2] = Point(4951, 5101.4);
+ polygon.ps[3] = Point(4951, 5039.4);
+ new ShapeRef(router, polygon, 1066);
+
+ // shapeRef1067
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3594, 5039.4);
+ polygon.ps[1] = Point(3594, 5101.4);
+ polygon.ps[2] = Point(3532, 5101.4);
+ polygon.ps[3] = Point(3532, 5039.4);
+ new ShapeRef(router, polygon, 1067);
+
+ // shapeRef1068
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3891, 7911.79);
+ polygon.ps[1] = Point(3891, 7973.79);
+ polygon.ps[2] = Point(3829, 7973.79);
+ polygon.ps[3] = Point(3829, 7911.79);
+ new ShapeRef(router, polygon, 1068);
+
+ // shapeRef1069
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4056, 7097.4);
+ polygon.ps[1] = Point(4056, 7159.4);
+ polygon.ps[2] = Point(3994, 7159.4);
+ polygon.ps[3] = Point(3994, 7097.4);
+ new ShapeRef(router, polygon, 1069);
+
+ // shapeRef1070
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17970.5, 9149.42);
+ polygon.ps[1] = Point(17970.5, 9211.42);
+ polygon.ps[2] = Point(17908.5, 9211.42);
+ polygon.ps[3] = Point(17908.5, 9149.42);
+ new ShapeRef(router, polygon, 1070);
+
+ // shapeRef1071
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18234.5, 9149.42);
+ polygon.ps[1] = Point(18234.5, 9211.42);
+ polygon.ps[2] = Point(18172.5, 9211.42);
+ polygon.ps[3] = Point(18172.5, 9149.42);
+ new ShapeRef(router, polygon, 1071);
+
+ // shapeRef1072
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12021.1, 9677.42);
+ polygon.ps[1] = Point(12021.1, 9739.42);
+ polygon.ps[2] = Point(11959.1, 9739.42);
+ polygon.ps[3] = Point(11959.1, 9677.42);
+ new ShapeRef(router, polygon, 1072);
+
+ // shapeRef1073
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12021.1, 10308);
+ polygon.ps[1] = Point(12021.1, 10370);
+ polygon.ps[2] = Point(11959.1, 10370);
+ polygon.ps[3] = Point(11959.1, 10308);
+ new ShapeRef(router, polygon, 1073);
+
+ // shapeRef1074
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12021.1, 9182.42);
+ polygon.ps[1] = Point(12021.1, 9244.42);
+ polygon.ps[2] = Point(11959.1, 9244.42);
+ polygon.ps[3] = Point(11959.1, 9182.42);
+ new ShapeRef(router, polygon, 1074);
+
+ // shapeRef1075
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4518, 51.2652);
+ polygon.ps[1] = Point(4518, 113.265);
+ polygon.ps[2] = Point(4456, 113.265);
+ polygon.ps[3] = Point(4456, 51.2652);
+ new ShapeRef(router, polygon, 1075);
+
+ // shapeRef1076
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4122, 183.265);
+ polygon.ps[1] = Point(4122, 245.265);
+ polygon.ps[2] = Point(4060, 245.265);
+ polygon.ps[3] = Point(4060, 183.265);
+ new ShapeRef(router, polygon, 1076);
+
+ // shapeRef1077
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8060.29, 4095.51);
+ polygon.ps[1] = Point(8060.29, 4157.51);
+ polygon.ps[2] = Point(7998.29, 4157.51);
+ polygon.ps[3] = Point(7998.29, 4095.51);
+ new ShapeRef(router, polygon, 1077);
+
+ // shapeRef1078
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5277, 3043.29);
+ polygon.ps[1] = Point(5277, 3105.29);
+ polygon.ps[2] = Point(5215, 3105.29);
+ polygon.ps[3] = Point(5215, 3043.29);
+ new ShapeRef(router, polygon, 1078);
+
+ // shapeRef1079
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10741.2, 6998.4);
+ polygon.ps[1] = Point(10741.2, 7060.4);
+ polygon.ps[2] = Point(10679.2, 7060.4);
+ polygon.ps[3] = Point(10679.2, 6998.4);
+ new ShapeRef(router, polygon, 1079);
+
+ // shapeRef1080
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9914.69, 6516.51);
+ polygon.ps[1] = Point(9914.69, 6578.51);
+ polygon.ps[2] = Point(9852.69, 6578.51);
+ polygon.ps[3] = Point(9852.69, 6516.51);
+ new ShapeRef(router, polygon, 1080);
+
+ // shapeRef1081
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10454.9, 6998.4);
+ polygon.ps[1] = Point(10454.9, 7060.4);
+ polygon.ps[2] = Point(10392.9, 7060.4);
+ polygon.ps[3] = Point(10392.9, 6998.4);
+ new ShapeRef(router, polygon, 1081);
+
+ // shapeRef1082
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7408.1, 3600.51);
+ polygon.ps[1] = Point(7408.1, 3662.51);
+ polygon.ps[2] = Point(7346.1, 3662.51);
+ polygon.ps[3] = Point(7346.1, 3600.51);
+ new ShapeRef(router, polygon, 1082);
+
+ // shapeRef1083
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7408.1, 3996.51);
+ polygon.ps[1] = Point(7408.1, 4058.51);
+ polygon.ps[2] = Point(7346.1, 4058.51);
+ polygon.ps[3] = Point(7346.1, 3996.51);
+ new ShapeRef(router, polygon, 1083);
+
+ // shapeRef1084
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7408.1, 3798.51);
+ polygon.ps[1] = Point(7408.1, 3860.51);
+ polygon.ps[2] = Point(7346.1, 3860.51);
+ polygon.ps[3] = Point(7346.1, 3798.51);
+ new ShapeRef(router, polygon, 1084);
+
+ // shapeRef1085
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7829.29, 3798.51);
+ polygon.ps[1] = Point(7829.29, 3860.51);
+ polygon.ps[2] = Point(7767.29, 3860.51);
+ polygon.ps[3] = Point(7767.29, 3798.51);
+ new ShapeRef(router, polygon, 1085);
+
+ // shapeRef1086
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7928.29, 11763.9);
+ polygon.ps[1] = Point(7928.29, 11825.9);
+ polygon.ps[2] = Point(7866.29, 11825.9);
+ polygon.ps[3] = Point(7866.29, 11763.9);
+ new ShapeRef(router, polygon, 1086);
+
+ // shapeRef1087
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12562.5, 11763.9);
+ polygon.ps[1] = Point(12562.5, 11825.9);
+ polygon.ps[2] = Point(12500.5, 11825.9);
+ polygon.ps[3] = Point(12500.5, 11763.9);
+ new ShapeRef(router, polygon, 1087);
+
+ // shapeRef1088
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1317, 2515.29);
+ polygon.ps[1] = Point(1317, 2577.29);
+ polygon.ps[2] = Point(1255, 2577.29);
+ polygon.ps[3] = Point(1255, 2515.29);
+ new ShapeRef(router, polygon, 1088);
+
+ // shapeRef1089
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 14797.9);
+ polygon.ps[1] = Point(8689.03, 14837.9);
+ polygon.ps[2] = Point(8634.03, 14837.9);
+ polygon.ps[3] = Point(8634.03, 14797.9);
+ new ShapeRef(router, polygon, 1089);
+
+ // shapeRef1090
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 14797.9);
+ polygon.ps[1] = Point(8789.03, 14837.9);
+ polygon.ps[2] = Point(8734.03, 14837.9);
+ polygon.ps[3] = Point(8734.03, 14797.9);
+ new ShapeRef(router, polygon, 1090);
+
+ // shapeRef1091
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 14797.9);
+ polygon.ps[1] = Point(8889.03, 14837.9);
+ polygon.ps[2] = Point(8834.03, 14837.9);
+ polygon.ps[3] = Point(8834.03, 14797.9);
+ new ShapeRef(router, polygon, 1091);
+
+ // shapeRef1092
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 14797.9);
+ polygon.ps[1] = Point(8989.03, 14837.9);
+ polygon.ps[2] = Point(8934.03, 14837.9);
+ polygon.ps[3] = Point(8934.03, 14797.9);
+ new ShapeRef(router, polygon, 1092);
+
+ // shapeRef1093
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 14797.9);
+ polygon.ps[1] = Point(9089.03, 14837.9);
+ polygon.ps[2] = Point(9034.03, 14837.9);
+ polygon.ps[3] = Point(9034.03, 14797.9);
+ new ShapeRef(router, polygon, 1093);
+
+ // shapeRef1094
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 14797.9);
+ polygon.ps[1] = Point(9189.03, 14837.9);
+ polygon.ps[2] = Point(9134.03, 14837.9);
+ polygon.ps[3] = Point(9134.03, 14797.9);
+ new ShapeRef(router, polygon, 1094);
+
+ // shapeRef1095
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 14797.9);
+ polygon.ps[1] = Point(9289.03, 14837.9);
+ polygon.ps[2] = Point(9234.03, 14837.9);
+ polygon.ps[3] = Point(9234.03, 14797.9);
+ new ShapeRef(router, polygon, 1095);
+
+ // shapeRef1096
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 14797.9);
+ polygon.ps[1] = Point(9389.03, 14837.9);
+ polygon.ps[2] = Point(9334.03, 14837.9);
+ polygon.ps[3] = Point(9334.03, 14797.9);
+ new ShapeRef(router, polygon, 1096);
+
+ // shapeRef1097
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 14897.9);
+ polygon.ps[1] = Point(8389.03, 14937.9);
+ polygon.ps[2] = Point(8334.03, 14937.9);
+ polygon.ps[3] = Point(8334.03, 14897.9);
+ new ShapeRef(router, polygon, 1097);
+
+ // shapeRef1098
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 14897.9);
+ polygon.ps[1] = Point(8489.03, 14937.9);
+ polygon.ps[2] = Point(8434.03, 14937.9);
+ polygon.ps[3] = Point(8434.03, 14897.9);
+ new ShapeRef(router, polygon, 1098);
+
+ // shapeRef1099
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 14897.9);
+ polygon.ps[1] = Point(8589.03, 14937.9);
+ polygon.ps[2] = Point(8534.03, 14937.9);
+ polygon.ps[3] = Point(8534.03, 14897.9);
+ new ShapeRef(router, polygon, 1099);
+
+ // shapeRef1100
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 14897.9);
+ polygon.ps[1] = Point(8689.03, 14937.9);
+ polygon.ps[2] = Point(8634.03, 14937.9);
+ polygon.ps[3] = Point(8634.03, 14897.9);
+ new ShapeRef(router, polygon, 1100);
+
+ // shapeRef1101
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 14897.9);
+ polygon.ps[1] = Point(8789.03, 14937.9);
+ polygon.ps[2] = Point(8734.03, 14937.9);
+ polygon.ps[3] = Point(8734.03, 14897.9);
+ new ShapeRef(router, polygon, 1101);
+
+ // shapeRef1102
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 14897.9);
+ polygon.ps[1] = Point(8889.03, 14937.9);
+ polygon.ps[2] = Point(8834.03, 14937.9);
+ polygon.ps[3] = Point(8834.03, 14897.9);
+ new ShapeRef(router, polygon, 1102);
+
+ // shapeRef1103
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 14897.9);
+ polygon.ps[1] = Point(8989.03, 14937.9);
+ polygon.ps[2] = Point(8934.03, 14937.9);
+ polygon.ps[3] = Point(8934.03, 14897.9);
+ new ShapeRef(router, polygon, 1103);
+
+ // shapeRef1104
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 14897.9);
+ polygon.ps[1] = Point(9089.03, 14937.9);
+ polygon.ps[2] = Point(9034.03, 14937.9);
+ polygon.ps[3] = Point(9034.03, 14897.9);
+ new ShapeRef(router, polygon, 1104);
+
+ // shapeRef1105
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 14897.9);
+ polygon.ps[1] = Point(9189.03, 14937.9);
+ polygon.ps[2] = Point(9134.03, 14937.9);
+ polygon.ps[3] = Point(9134.03, 14897.9);
+ new ShapeRef(router, polygon, 1105);
+
+ // shapeRef1106
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 14897.9);
+ polygon.ps[1] = Point(9289.03, 14937.9);
+ polygon.ps[2] = Point(9234.03, 14937.9);
+ polygon.ps[3] = Point(9234.03, 14897.9);
+ new ShapeRef(router, polygon, 1106);
+
+ // shapeRef1107
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 14897.9);
+ polygon.ps[1] = Point(9389.03, 14937.9);
+ polygon.ps[2] = Point(9334.03, 14937.9);
+ polygon.ps[3] = Point(9334.03, 14897.9);
+ new ShapeRef(router, polygon, 1107);
+
+ // shapeRef1108
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 14997.9);
+ polygon.ps[1] = Point(8389.03, 15037.9);
+ polygon.ps[2] = Point(8334.03, 15037.9);
+ polygon.ps[3] = Point(8334.03, 14997.9);
+ new ShapeRef(router, polygon, 1108);
+
+ // shapeRef1109
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 14997.9);
+ polygon.ps[1] = Point(8489.03, 15037.9);
+ polygon.ps[2] = Point(8434.03, 15037.9);
+ polygon.ps[3] = Point(8434.03, 14997.9);
+ new ShapeRef(router, polygon, 1109);
+
+ // shapeRef1110
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 14997.9);
+ polygon.ps[1] = Point(8589.03, 15037.9);
+ polygon.ps[2] = Point(8534.03, 15037.9);
+ polygon.ps[3] = Point(8534.03, 14997.9);
+ new ShapeRef(router, polygon, 1110);
+
+ // shapeRef1111
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 14997.9);
+ polygon.ps[1] = Point(8689.03, 15037.9);
+ polygon.ps[2] = Point(8634.03, 15037.9);
+ polygon.ps[3] = Point(8634.03, 14997.9);
+ new ShapeRef(router, polygon, 1111);
+
+ // shapeRef1112
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 14997.9);
+ polygon.ps[1] = Point(8789.03, 15037.9);
+ polygon.ps[2] = Point(8734.03, 15037.9);
+ polygon.ps[3] = Point(8734.03, 14997.9);
+ new ShapeRef(router, polygon, 1112);
+
+ // shapeRef1113
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 14997.9);
+ polygon.ps[1] = Point(8889.03, 15037.9);
+ polygon.ps[2] = Point(8834.03, 15037.9);
+ polygon.ps[3] = Point(8834.03, 14997.9);
+ new ShapeRef(router, polygon, 1113);
+
+ // shapeRef1114
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 14997.9);
+ polygon.ps[1] = Point(8989.03, 15037.9);
+ polygon.ps[2] = Point(8934.03, 15037.9);
+ polygon.ps[3] = Point(8934.03, 14997.9);
+ new ShapeRef(router, polygon, 1114);
+
+ // shapeRef1115
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 14997.9);
+ polygon.ps[1] = Point(9089.03, 15037.9);
+ polygon.ps[2] = Point(9034.03, 15037.9);
+ polygon.ps[3] = Point(9034.03, 14997.9);
+ new ShapeRef(router, polygon, 1115);
+
+ // shapeRef1116
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 14997.9);
+ polygon.ps[1] = Point(9189.03, 15037.9);
+ polygon.ps[2] = Point(9134.03, 15037.9);
+ polygon.ps[3] = Point(9134.03, 14997.9);
+ new ShapeRef(router, polygon, 1116);
+
+ // shapeRef1117
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 14997.9);
+ polygon.ps[1] = Point(9289.03, 15037.9);
+ polygon.ps[2] = Point(9234.03, 15037.9);
+ polygon.ps[3] = Point(9234.03, 14997.9);
+ new ShapeRef(router, polygon, 1117);
+
+ // shapeRef1118
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 14997.9);
+ polygon.ps[1] = Point(9389.03, 15037.9);
+ polygon.ps[2] = Point(9334.03, 15037.9);
+ polygon.ps[3] = Point(9334.03, 14997.9);
+ new ShapeRef(router, polygon, 1118);
+
+ // shapeRef1119
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 15097.9);
+ polygon.ps[1] = Point(8389.03, 15137.9);
+ polygon.ps[2] = Point(8334.03, 15137.9);
+ polygon.ps[3] = Point(8334.03, 15097.9);
+ new ShapeRef(router, polygon, 1119);
+
+ // shapeRef1120
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 15097.9);
+ polygon.ps[1] = Point(8489.03, 15137.9);
+ polygon.ps[2] = Point(8434.03, 15137.9);
+ polygon.ps[3] = Point(8434.03, 15097.9);
+ new ShapeRef(router, polygon, 1120);
+
+ // shapeRef1121
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 15097.9);
+ polygon.ps[1] = Point(8589.03, 15137.9);
+ polygon.ps[2] = Point(8534.03, 15137.9);
+ polygon.ps[3] = Point(8534.03, 15097.9);
+ new ShapeRef(router, polygon, 1121);
+
+ // shapeRef1122
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 15097.9);
+ polygon.ps[1] = Point(8789.03, 15137.9);
+ polygon.ps[2] = Point(8734.03, 15137.9);
+ polygon.ps[3] = Point(8734.03, 15097.9);
+ new ShapeRef(router, polygon, 1122);
+
+ // shapeRef1123
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 15097.9);
+ polygon.ps[1] = Point(8889.03, 15137.9);
+ polygon.ps[2] = Point(8834.03, 15137.9);
+ polygon.ps[3] = Point(8834.03, 15097.9);
+ new ShapeRef(router, polygon, 1123);
+
+ // shapeRef1124
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 15097.9);
+ polygon.ps[1] = Point(8989.03, 15137.9);
+ polygon.ps[2] = Point(8934.03, 15137.9);
+ polygon.ps[3] = Point(8934.03, 15097.9);
+ new ShapeRef(router, polygon, 1124);
+
+ // shapeRef1125
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 15097.9);
+ polygon.ps[1] = Point(9089.03, 15137.9);
+ polygon.ps[2] = Point(9034.03, 15137.9);
+ polygon.ps[3] = Point(9034.03, 15097.9);
+ new ShapeRef(router, polygon, 1125);
+
+ // shapeRef1126
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 15097.9);
+ polygon.ps[1] = Point(9189.03, 15137.9);
+ polygon.ps[2] = Point(9134.03, 15137.9);
+ polygon.ps[3] = Point(9134.03, 15097.9);
+ new ShapeRef(router, polygon, 1126);
+
+ // shapeRef1127
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 15097.9);
+ polygon.ps[1] = Point(9289.03, 15137.9);
+ polygon.ps[2] = Point(9234.03, 15137.9);
+ polygon.ps[3] = Point(9234.03, 15097.9);
+ new ShapeRef(router, polygon, 1127);
+
+ // shapeRef1128
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 15097.9);
+ polygon.ps[1] = Point(9389.03, 15137.9);
+ polygon.ps[2] = Point(9334.03, 15137.9);
+ polygon.ps[3] = Point(9334.03, 15097.9);
+ new ShapeRef(router, polygon, 1128);
+
+ // shapeRef1129
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 15197.9);
+ polygon.ps[1] = Point(8389.03, 15237.9);
+ polygon.ps[2] = Point(8334.03, 15237.9);
+ polygon.ps[3] = Point(8334.03, 15197.9);
+ new ShapeRef(router, polygon, 1129);
+
+ // shapeRef1130
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 15197.9);
+ polygon.ps[1] = Point(8489.03, 15237.9);
+ polygon.ps[2] = Point(8434.03, 15237.9);
+ polygon.ps[3] = Point(8434.03, 15197.9);
+ new ShapeRef(router, polygon, 1130);
+
+ // shapeRef1131
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 15197.9);
+ polygon.ps[1] = Point(8789.03, 15237.9);
+ polygon.ps[2] = Point(8734.03, 15237.9);
+ polygon.ps[3] = Point(8734.03, 15197.9);
+ new ShapeRef(router, polygon, 1131);
+
+ // shapeRef1132
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 15197.9);
+ polygon.ps[1] = Point(8889.03, 15237.9);
+ polygon.ps[2] = Point(8834.03, 15237.9);
+ polygon.ps[3] = Point(8834.03, 15197.9);
+ new ShapeRef(router, polygon, 1132);
+
+ // shapeRef1133
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 15197.9);
+ polygon.ps[1] = Point(8989.03, 15237.9);
+ polygon.ps[2] = Point(8934.03, 15237.9);
+ polygon.ps[3] = Point(8934.03, 15197.9);
+ new ShapeRef(router, polygon, 1133);
+
+ // shapeRef1134
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 15197.9);
+ polygon.ps[1] = Point(9089.03, 15237.9);
+ polygon.ps[2] = Point(9034.03, 15237.9);
+ polygon.ps[3] = Point(9034.03, 15197.9);
+ new ShapeRef(router, polygon, 1134);
+
+ // shapeRef1135
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 15197.9);
+ polygon.ps[1] = Point(9289.03, 15237.9);
+ polygon.ps[2] = Point(9234.03, 15237.9);
+ polygon.ps[3] = Point(9234.03, 15197.9);
+ new ShapeRef(router, polygon, 1135);
+
+ // shapeRef1136
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 15197.9);
+ polygon.ps[1] = Point(9389.03, 15237.9);
+ polygon.ps[2] = Point(9334.03, 15237.9);
+ polygon.ps[3] = Point(9334.03, 15197.9);
+ new ShapeRef(router, polygon, 1136);
+
+ // shapeRef1137
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 15297.9);
+ polygon.ps[1] = Point(8389.03, 15337.9);
+ polygon.ps[2] = Point(8334.03, 15337.9);
+ polygon.ps[3] = Point(8334.03, 15297.9);
+ new ShapeRef(router, polygon, 1137);
+
+ // shapeRef1138
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 15297.9);
+ polygon.ps[1] = Point(8489.03, 15337.9);
+ polygon.ps[2] = Point(8434.03, 15337.9);
+ polygon.ps[3] = Point(8434.03, 15297.9);
+ new ShapeRef(router, polygon, 1138);
+
+ // shapeRef1139
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 15297.9);
+ polygon.ps[1] = Point(8589.03, 15337.9);
+ polygon.ps[2] = Point(8534.03, 15337.9);
+ polygon.ps[3] = Point(8534.03, 15297.9);
+ new ShapeRef(router, polygon, 1139);
+
+ // shapeRef1140
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 15297.9);
+ polygon.ps[1] = Point(8689.03, 15337.9);
+ polygon.ps[2] = Point(8634.03, 15337.9);
+ polygon.ps[3] = Point(8634.03, 15297.9);
+ new ShapeRef(router, polygon, 1140);
+
+ // shapeRef1141
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 15297.9);
+ polygon.ps[1] = Point(8789.03, 15337.9);
+ polygon.ps[2] = Point(8734.03, 15337.9);
+ polygon.ps[3] = Point(8734.03, 15297.9);
+ new ShapeRef(router, polygon, 1141);
+
+ // shapeRef1142
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 15297.9);
+ polygon.ps[1] = Point(8889.03, 15337.9);
+ polygon.ps[2] = Point(8834.03, 15337.9);
+ polygon.ps[3] = Point(8834.03, 15297.9);
+ new ShapeRef(router, polygon, 1142);
+
+ // shapeRef1143
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 15297.9);
+ polygon.ps[1] = Point(8989.03, 15337.9);
+ polygon.ps[2] = Point(8934.03, 15337.9);
+ polygon.ps[3] = Point(8934.03, 15297.9);
+ new ShapeRef(router, polygon, 1143);
+
+ // shapeRef1144
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 15297.9);
+ polygon.ps[1] = Point(9089.03, 15337.9);
+ polygon.ps[2] = Point(9034.03, 15337.9);
+ polygon.ps[3] = Point(9034.03, 15297.9);
+ new ShapeRef(router, polygon, 1144);
+
+ // shapeRef1145
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 15297.9);
+ polygon.ps[1] = Point(9189.03, 15337.9);
+ polygon.ps[2] = Point(9134.03, 15337.9);
+ polygon.ps[3] = Point(9134.03, 15297.9);
+ new ShapeRef(router, polygon, 1145);
+
+ // shapeRef1146
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 15297.9);
+ polygon.ps[1] = Point(9289.03, 15337.9);
+ polygon.ps[2] = Point(9234.03, 15337.9);
+ polygon.ps[3] = Point(9234.03, 15297.9);
+ new ShapeRef(router, polygon, 1146);
+
+ // shapeRef1147
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 15297.9);
+ polygon.ps[1] = Point(9389.03, 15337.9);
+ polygon.ps[2] = Point(9334.03, 15337.9);
+ polygon.ps[3] = Point(9334.03, 15297.9);
+ new ShapeRef(router, polygon, 1147);
+
+ // shapeRef1148
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 15397.9);
+ polygon.ps[1] = Point(8389.03, 15437.9);
+ polygon.ps[2] = Point(8334.03, 15437.9);
+ polygon.ps[3] = Point(8334.03, 15397.9);
+ new ShapeRef(router, polygon, 1148);
+
+ // shapeRef1149
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 15397.9);
+ polygon.ps[1] = Point(8489.03, 15437.9);
+ polygon.ps[2] = Point(8434.03, 15437.9);
+ polygon.ps[3] = Point(8434.03, 15397.9);
+ new ShapeRef(router, polygon, 1149);
+
+ // shapeRef1150
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 15397.9);
+ polygon.ps[1] = Point(8589.03, 15437.9);
+ polygon.ps[2] = Point(8534.03, 15437.9);
+ polygon.ps[3] = Point(8534.03, 15397.9);
+ new ShapeRef(router, polygon, 1150);
+
+ // shapeRef1151
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 15397.9);
+ polygon.ps[1] = Point(8689.03, 15437.9);
+ polygon.ps[2] = Point(8634.03, 15437.9);
+ polygon.ps[3] = Point(8634.03, 15397.9);
+ new ShapeRef(router, polygon, 1151);
+
+ // shapeRef1152
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 15397.9);
+ polygon.ps[1] = Point(8789.03, 15437.9);
+ polygon.ps[2] = Point(8734.03, 15437.9);
+ polygon.ps[3] = Point(8734.03, 15397.9);
+ new ShapeRef(router, polygon, 1152);
+
+ // shapeRef1153
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 15397.9);
+ polygon.ps[1] = Point(8889.03, 15437.9);
+ polygon.ps[2] = Point(8834.03, 15437.9);
+ polygon.ps[3] = Point(8834.03, 15397.9);
+ new ShapeRef(router, polygon, 1153);
+
+ // shapeRef1154
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 15397.9);
+ polygon.ps[1] = Point(8989.03, 15437.9);
+ polygon.ps[2] = Point(8934.03, 15437.9);
+ polygon.ps[3] = Point(8934.03, 15397.9);
+ new ShapeRef(router, polygon, 1154);
+
+ // shapeRef1155
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 15397.9);
+ polygon.ps[1] = Point(9089.03, 15437.9);
+ polygon.ps[2] = Point(9034.03, 15437.9);
+ polygon.ps[3] = Point(9034.03, 15397.9);
+ new ShapeRef(router, polygon, 1155);
+
+ // shapeRef1156
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 15397.9);
+ polygon.ps[1] = Point(9189.03, 15437.9);
+ polygon.ps[2] = Point(9134.03, 15437.9);
+ polygon.ps[3] = Point(9134.03, 15397.9);
+ new ShapeRef(router, polygon, 1156);
+
+ // shapeRef1157
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 15397.9);
+ polygon.ps[1] = Point(9289.03, 15437.9);
+ polygon.ps[2] = Point(9234.03, 15437.9);
+ polygon.ps[3] = Point(9234.03, 15397.9);
+ new ShapeRef(router, polygon, 1157);
+
+ // shapeRef1158
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 15397.9);
+ polygon.ps[1] = Point(9389.03, 15437.9);
+ polygon.ps[2] = Point(9334.03, 15437.9);
+ polygon.ps[3] = Point(9334.03, 15397.9);
+ new ShapeRef(router, polygon, 1158);
+
+ // shapeRef1159
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 15497.9);
+ polygon.ps[1] = Point(8489.03, 15537.9);
+ polygon.ps[2] = Point(8434.03, 15537.9);
+ polygon.ps[3] = Point(8434.03, 15497.9);
+ new ShapeRef(router, polygon, 1159);
+
+ // shapeRef1160
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 15497.9);
+ polygon.ps[1] = Point(8589.03, 15537.9);
+ polygon.ps[2] = Point(8534.03, 15537.9);
+ polygon.ps[3] = Point(8534.03, 15497.9);
+ new ShapeRef(router, polygon, 1160);
+
+ // shapeRef1161
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 15497.9);
+ polygon.ps[1] = Point(8689.03, 15537.9);
+ polygon.ps[2] = Point(8634.03, 15537.9);
+ polygon.ps[3] = Point(8634.03, 15497.9);
+ new ShapeRef(router, polygon, 1161);
+
+ // shapeRef1162
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 15497.9);
+ polygon.ps[1] = Point(8789.03, 15537.9);
+ polygon.ps[2] = Point(8734.03, 15537.9);
+ polygon.ps[3] = Point(8734.03, 15497.9);
+ new ShapeRef(router, polygon, 1162);
+
+ // shapeRef1163
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 15497.9);
+ polygon.ps[1] = Point(8889.03, 15537.9);
+ polygon.ps[2] = Point(8834.03, 15537.9);
+ polygon.ps[3] = Point(8834.03, 15497.9);
+ new ShapeRef(router, polygon, 1163);
+
+ // shapeRef1164
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 15497.9);
+ polygon.ps[1] = Point(8989.03, 15537.9);
+ polygon.ps[2] = Point(8934.03, 15537.9);
+ polygon.ps[3] = Point(8934.03, 15497.9);
+ new ShapeRef(router, polygon, 1164);
+
+ // shapeRef1165
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 15497.9);
+ polygon.ps[1] = Point(9089.03, 15537.9);
+ polygon.ps[2] = Point(9034.03, 15537.9);
+ polygon.ps[3] = Point(9034.03, 15497.9);
+ new ShapeRef(router, polygon, 1165);
+
+ // shapeRef1166
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 15497.9);
+ polygon.ps[1] = Point(9189.03, 15537.9);
+ polygon.ps[2] = Point(9134.03, 15537.9);
+ polygon.ps[3] = Point(9134.03, 15497.9);
+ new ShapeRef(router, polygon, 1166);
+
+ // shapeRef1167
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 15497.9);
+ polygon.ps[1] = Point(9289.03, 15537.9);
+ polygon.ps[2] = Point(9234.03, 15537.9);
+ polygon.ps[3] = Point(9234.03, 15497.9);
+ new ShapeRef(router, polygon, 1167);
+
+ // shapeRef1168
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 15497.9);
+ polygon.ps[1] = Point(9389.03, 15537.9);
+ polygon.ps[2] = Point(9334.03, 15537.9);
+ polygon.ps[3] = Point(9334.03, 15497.9);
+ new ShapeRef(router, polygon, 1168);
+
+ // shapeRef1169
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 15597.9);
+ polygon.ps[1] = Point(8389.03, 15637.9);
+ polygon.ps[2] = Point(8334.03, 15637.9);
+ polygon.ps[3] = Point(8334.03, 15597.9);
+ new ShapeRef(router, polygon, 1169);
+
+ // shapeRef1170
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 15597.9);
+ polygon.ps[1] = Point(8489.03, 15637.9);
+ polygon.ps[2] = Point(8434.03, 15637.9);
+ polygon.ps[3] = Point(8434.03, 15597.9);
+ new ShapeRef(router, polygon, 1170);
+
+ // shapeRef1171
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 15597.9);
+ polygon.ps[1] = Point(8589.03, 15637.9);
+ polygon.ps[2] = Point(8534.03, 15637.9);
+ polygon.ps[3] = Point(8534.03, 15597.9);
+ new ShapeRef(router, polygon, 1171);
+
+ // shapeRef1172
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 15597.9);
+ polygon.ps[1] = Point(8689.03, 15637.9);
+ polygon.ps[2] = Point(8634.03, 15637.9);
+ polygon.ps[3] = Point(8634.03, 15597.9);
+ new ShapeRef(router, polygon, 1172);
+
+ // shapeRef1173
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 15597.9);
+ polygon.ps[1] = Point(8789.03, 15637.9);
+ polygon.ps[2] = Point(8734.03, 15637.9);
+ polygon.ps[3] = Point(8734.03, 15597.9);
+ new ShapeRef(router, polygon, 1173);
+
+ // shapeRef1174
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 15597.9);
+ polygon.ps[1] = Point(8889.03, 15637.9);
+ polygon.ps[2] = Point(8834.03, 15637.9);
+ polygon.ps[3] = Point(8834.03, 15597.9);
+ new ShapeRef(router, polygon, 1174);
+
+ // shapeRef1175
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 15597.9);
+ polygon.ps[1] = Point(8989.03, 15637.9);
+ polygon.ps[2] = Point(8934.03, 15637.9);
+ polygon.ps[3] = Point(8934.03, 15597.9);
+ new ShapeRef(router, polygon, 1175);
+
+ // shapeRef1176
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 15597.9);
+ polygon.ps[1] = Point(9089.03, 15637.9);
+ polygon.ps[2] = Point(9034.03, 15637.9);
+ polygon.ps[3] = Point(9034.03, 15597.9);
+ new ShapeRef(router, polygon, 1176);
+
+ // shapeRef1177
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 15597.9);
+ polygon.ps[1] = Point(9189.03, 15637.9);
+ polygon.ps[2] = Point(9134.03, 15637.9);
+ polygon.ps[3] = Point(9134.03, 15597.9);
+ new ShapeRef(router, polygon, 1177);
+
+ // shapeRef1178
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 15597.9);
+ polygon.ps[1] = Point(9289.03, 15637.9);
+ polygon.ps[2] = Point(9234.03, 15637.9);
+ polygon.ps[3] = Point(9234.03, 15597.9);
+ new ShapeRef(router, polygon, 1178);
+
+ // shapeRef1179
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 15597.9);
+ polygon.ps[1] = Point(9389.03, 15637.9);
+ polygon.ps[2] = Point(9334.03, 15637.9);
+ polygon.ps[3] = Point(9334.03, 15597.9);
+ new ShapeRef(router, polygon, 1179);
+
+ // shapeRef1180
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 15697.9);
+ polygon.ps[1] = Point(8389.03, 15737.9);
+ polygon.ps[2] = Point(8334.03, 15737.9);
+ polygon.ps[3] = Point(8334.03, 15697.9);
+ new ShapeRef(router, polygon, 1180);
+
+ // shapeRef1181
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 15697.9);
+ polygon.ps[1] = Point(8489.03, 15737.9);
+ polygon.ps[2] = Point(8434.03, 15737.9);
+ polygon.ps[3] = Point(8434.03, 15697.9);
+ new ShapeRef(router, polygon, 1181);
+
+ // shapeRef1182
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 15697.9);
+ polygon.ps[1] = Point(8589.03, 15737.9);
+ polygon.ps[2] = Point(8534.03, 15737.9);
+ polygon.ps[3] = Point(8534.03, 15697.9);
+ new ShapeRef(router, polygon, 1182);
+
+ // shapeRef1183
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 15697.9);
+ polygon.ps[1] = Point(8689.03, 15737.9);
+ polygon.ps[2] = Point(8634.03, 15737.9);
+ polygon.ps[3] = Point(8634.03, 15697.9);
+ new ShapeRef(router, polygon, 1183);
+
+ // shapeRef1184
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 15697.9);
+ polygon.ps[1] = Point(8789.03, 15737.9);
+ polygon.ps[2] = Point(8734.03, 15737.9);
+ polygon.ps[3] = Point(8734.03, 15697.9);
+ new ShapeRef(router, polygon, 1184);
+
+ // shapeRef1185
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 15697.9);
+ polygon.ps[1] = Point(8889.03, 15737.9);
+ polygon.ps[2] = Point(8834.03, 15737.9);
+ polygon.ps[3] = Point(8834.03, 15697.9);
+ new ShapeRef(router, polygon, 1185);
+
+ // shapeRef1186
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 15697.9);
+ polygon.ps[1] = Point(8989.03, 15737.9);
+ polygon.ps[2] = Point(8934.03, 15737.9);
+ polygon.ps[3] = Point(8934.03, 15697.9);
+ new ShapeRef(router, polygon, 1186);
+
+ // shapeRef1187
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 15697.9);
+ polygon.ps[1] = Point(9089.03, 15737.9);
+ polygon.ps[2] = Point(9034.03, 15737.9);
+ polygon.ps[3] = Point(9034.03, 15697.9);
+ new ShapeRef(router, polygon, 1187);
+
+ // shapeRef1188
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 15697.9);
+ polygon.ps[1] = Point(9189.03, 15737.9);
+ polygon.ps[2] = Point(9134.03, 15737.9);
+ polygon.ps[3] = Point(9134.03, 15697.9);
+ new ShapeRef(router, polygon, 1188);
+
+ // shapeRef1189
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 15697.9);
+ polygon.ps[1] = Point(9289.03, 15737.9);
+ polygon.ps[2] = Point(9234.03, 15737.9);
+ polygon.ps[3] = Point(9234.03, 15697.9);
+ new ShapeRef(router, polygon, 1189);
+
+ // shapeRef1190
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 15697.9);
+ polygon.ps[1] = Point(9389.03, 15737.9);
+ polygon.ps[2] = Point(9334.03, 15737.9);
+ polygon.ps[3] = Point(9334.03, 15697.9);
+ new ShapeRef(router, polygon, 1190);
+
+ // shapeRef1191
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 15797.9);
+ polygon.ps[1] = Point(8389.03, 15837.9);
+ polygon.ps[2] = Point(8334.03, 15837.9);
+ polygon.ps[3] = Point(8334.03, 15797.9);
+ new ShapeRef(router, polygon, 1191);
+
+ // shapeRef1192
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 15797.9);
+ polygon.ps[1] = Point(8489.03, 15837.9);
+ polygon.ps[2] = Point(8434.03, 15837.9);
+ polygon.ps[3] = Point(8434.03, 15797.9);
+ new ShapeRef(router, polygon, 1192);
+
+ // shapeRef1193
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 15797.9);
+ polygon.ps[1] = Point(8589.03, 15837.9);
+ polygon.ps[2] = Point(8534.03, 15837.9);
+ polygon.ps[3] = Point(8534.03, 15797.9);
+ new ShapeRef(router, polygon, 1193);
+
+ // shapeRef1194
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 15797.9);
+ polygon.ps[1] = Point(8689.03, 15837.9);
+ polygon.ps[2] = Point(8634.03, 15837.9);
+ polygon.ps[3] = Point(8634.03, 15797.9);
+ new ShapeRef(router, polygon, 1194);
+
+ // shapeRef1195
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 15797.9);
+ polygon.ps[1] = Point(8789.03, 15837.9);
+ polygon.ps[2] = Point(8734.03, 15837.9);
+ polygon.ps[3] = Point(8734.03, 15797.9);
+ new ShapeRef(router, polygon, 1195);
+
+ // shapeRef1196
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 15797.9);
+ polygon.ps[1] = Point(8889.03, 15837.9);
+ polygon.ps[2] = Point(8834.03, 15837.9);
+ polygon.ps[3] = Point(8834.03, 15797.9);
+ new ShapeRef(router, polygon, 1196);
+
+ // shapeRef1197
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 15797.9);
+ polygon.ps[1] = Point(8989.03, 15837.9);
+ polygon.ps[2] = Point(8934.03, 15837.9);
+ polygon.ps[3] = Point(8934.03, 15797.9);
+ new ShapeRef(router, polygon, 1197);
+
+ // shapeRef1198
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 15797.9);
+ polygon.ps[1] = Point(9089.03, 15837.9);
+ polygon.ps[2] = Point(9034.03, 15837.9);
+ polygon.ps[3] = Point(9034.03, 15797.9);
+ new ShapeRef(router, polygon, 1198);
+
+ // shapeRef1199
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 15797.9);
+ polygon.ps[1] = Point(9189.03, 15837.9);
+ polygon.ps[2] = Point(9134.03, 15837.9);
+ polygon.ps[3] = Point(9134.03, 15797.9);
+ new ShapeRef(router, polygon, 1199);
+
+ // shapeRef1200
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 15797.9);
+ polygon.ps[1] = Point(9289.03, 15837.9);
+ polygon.ps[2] = Point(9234.03, 15837.9);
+ polygon.ps[3] = Point(9234.03, 15797.9);
+ new ShapeRef(router, polygon, 1200);
+
+ // shapeRef1201
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 15797.9);
+ polygon.ps[1] = Point(9389.03, 15837.9);
+ polygon.ps[2] = Point(9334.03, 15837.9);
+ polygon.ps[3] = Point(9334.03, 15797.9);
+ new ShapeRef(router, polygon, 1201);
+
+ // shapeRef1202
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 15897.9);
+ polygon.ps[1] = Point(8389.03, 15937.9);
+ polygon.ps[2] = Point(8334.03, 15937.9);
+ polygon.ps[3] = Point(8334.03, 15897.9);
+ new ShapeRef(router, polygon, 1202);
+
+ // shapeRef1203
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 15897.9);
+ polygon.ps[1] = Point(8489.03, 15937.9);
+ polygon.ps[2] = Point(8434.03, 15937.9);
+ polygon.ps[3] = Point(8434.03, 15897.9);
+ new ShapeRef(router, polygon, 1203);
+
+ // shapeRef1204
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 15897.9);
+ polygon.ps[1] = Point(8589.03, 15937.9);
+ polygon.ps[2] = Point(8534.03, 15937.9);
+ polygon.ps[3] = Point(8534.03, 15897.9);
+ new ShapeRef(router, polygon, 1204);
+
+ // shapeRef1205
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 15897.9);
+ polygon.ps[1] = Point(8689.03, 15937.9);
+ polygon.ps[2] = Point(8634.03, 15937.9);
+ polygon.ps[3] = Point(8634.03, 15897.9);
+ new ShapeRef(router, polygon, 1205);
+
+ // shapeRef1206
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 15897.9);
+ polygon.ps[1] = Point(8789.03, 15937.9);
+ polygon.ps[2] = Point(8734.03, 15937.9);
+ polygon.ps[3] = Point(8734.03, 15897.9);
+ new ShapeRef(router, polygon, 1206);
+
+ // shapeRef1207
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 15897.9);
+ polygon.ps[1] = Point(8889.03, 15937.9);
+ polygon.ps[2] = Point(8834.03, 15937.9);
+ polygon.ps[3] = Point(8834.03, 15897.9);
+ new ShapeRef(router, polygon, 1207);
+
+ // shapeRef1208
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 15897.9);
+ polygon.ps[1] = Point(8989.03, 15937.9);
+ polygon.ps[2] = Point(8934.03, 15937.9);
+ polygon.ps[3] = Point(8934.03, 15897.9);
+ new ShapeRef(router, polygon, 1208);
+
+ // shapeRef1209
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 15897.9);
+ polygon.ps[1] = Point(9089.03, 15937.9);
+ polygon.ps[2] = Point(9034.03, 15937.9);
+ polygon.ps[3] = Point(9034.03, 15897.9);
+ new ShapeRef(router, polygon, 1209);
+
+ // shapeRef1210
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 15897.9);
+ polygon.ps[1] = Point(9189.03, 15937.9);
+ polygon.ps[2] = Point(9134.03, 15937.9);
+ polygon.ps[3] = Point(9134.03, 15897.9);
+ new ShapeRef(router, polygon, 1210);
+
+ // shapeRef1211
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 15897.9);
+ polygon.ps[1] = Point(9289.03, 15937.9);
+ polygon.ps[2] = Point(9234.03, 15937.9);
+ polygon.ps[3] = Point(9234.03, 15897.9);
+ new ShapeRef(router, polygon, 1211);
+
+ // shapeRef1212
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 15897.9);
+ polygon.ps[1] = Point(9389.03, 15937.9);
+ polygon.ps[2] = Point(9334.03, 15937.9);
+ polygon.ps[3] = Point(9334.03, 15897.9);
+ new ShapeRef(router, polygon, 1212);
+
+ // shapeRef1213
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 15997.9);
+ polygon.ps[1] = Point(8389.03, 16037.9);
+ polygon.ps[2] = Point(8334.03, 16037.9);
+ polygon.ps[3] = Point(8334.03, 15997.9);
+ new ShapeRef(router, polygon, 1213);
+
+ // shapeRef1214
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 15997.9);
+ polygon.ps[1] = Point(8489.03, 16037.9);
+ polygon.ps[2] = Point(8434.03, 16037.9);
+ polygon.ps[3] = Point(8434.03, 15997.9);
+ new ShapeRef(router, polygon, 1214);
+
+ // shapeRef1215
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 15997.9);
+ polygon.ps[1] = Point(8589.03, 16037.9);
+ polygon.ps[2] = Point(8534.03, 16037.9);
+ polygon.ps[3] = Point(8534.03, 15997.9);
+ new ShapeRef(router, polygon, 1215);
+
+ // shapeRef1216
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 15997.9);
+ polygon.ps[1] = Point(8689.03, 16037.9);
+ polygon.ps[2] = Point(8634.03, 16037.9);
+ polygon.ps[3] = Point(8634.03, 15997.9);
+ new ShapeRef(router, polygon, 1216);
+
+ // shapeRef1217
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 15997.9);
+ polygon.ps[1] = Point(8789.03, 16037.9);
+ polygon.ps[2] = Point(8734.03, 16037.9);
+ polygon.ps[3] = Point(8734.03, 15997.9);
+ new ShapeRef(router, polygon, 1217);
+
+ // shapeRef1218
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 15997.9);
+ polygon.ps[1] = Point(8889.03, 16037.9);
+ polygon.ps[2] = Point(8834.03, 16037.9);
+ polygon.ps[3] = Point(8834.03, 15997.9);
+ new ShapeRef(router, polygon, 1218);
+
+ // shapeRef1219
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 15997.9);
+ polygon.ps[1] = Point(8989.03, 16037.9);
+ polygon.ps[2] = Point(8934.03, 16037.9);
+ polygon.ps[3] = Point(8934.03, 15997.9);
+ new ShapeRef(router, polygon, 1219);
+
+ // shapeRef1220
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 15997.9);
+ polygon.ps[1] = Point(9089.03, 16037.9);
+ polygon.ps[2] = Point(9034.03, 16037.9);
+ polygon.ps[3] = Point(9034.03, 15997.9);
+ new ShapeRef(router, polygon, 1220);
+
+ // shapeRef1221
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 15997.9);
+ polygon.ps[1] = Point(9189.03, 16037.9);
+ polygon.ps[2] = Point(9134.03, 16037.9);
+ polygon.ps[3] = Point(9134.03, 15997.9);
+ new ShapeRef(router, polygon, 1221);
+
+ // shapeRef1222
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 15997.9);
+ polygon.ps[1] = Point(9289.03, 16037.9);
+ polygon.ps[2] = Point(9234.03, 16037.9);
+ polygon.ps[3] = Point(9234.03, 15997.9);
+ new ShapeRef(router, polygon, 1222);
+
+ // shapeRef1223
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 15997.9);
+ polygon.ps[1] = Point(9389.03, 16037.9);
+ polygon.ps[2] = Point(9334.03, 16037.9);
+ polygon.ps[3] = Point(9334.03, 15997.9);
+ new ShapeRef(router, polygon, 1223);
+
+ // shapeRef1224
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 16097.9);
+ polygon.ps[1] = Point(8389.03, 16137.9);
+ polygon.ps[2] = Point(8334.03, 16137.9);
+ polygon.ps[3] = Point(8334.03, 16097.9);
+ new ShapeRef(router, polygon, 1224);
+
+ // shapeRef1225
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 16097.9);
+ polygon.ps[1] = Point(8489.03, 16137.9);
+ polygon.ps[2] = Point(8434.03, 16137.9);
+ polygon.ps[3] = Point(8434.03, 16097.9);
+ new ShapeRef(router, polygon, 1225);
+
+ // shapeRef1226
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 16097.9);
+ polygon.ps[1] = Point(8589.03, 16137.9);
+ polygon.ps[2] = Point(8534.03, 16137.9);
+ polygon.ps[3] = Point(8534.03, 16097.9);
+ new ShapeRef(router, polygon, 1226);
+
+ // shapeRef1227
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 16097.9);
+ polygon.ps[1] = Point(8689.03, 16137.9);
+ polygon.ps[2] = Point(8634.03, 16137.9);
+ polygon.ps[3] = Point(8634.03, 16097.9);
+ new ShapeRef(router, polygon, 1227);
+
+ // shapeRef1228
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 16097.9);
+ polygon.ps[1] = Point(8789.03, 16137.9);
+ polygon.ps[2] = Point(8734.03, 16137.9);
+ polygon.ps[3] = Point(8734.03, 16097.9);
+ new ShapeRef(router, polygon, 1228);
+
+ // shapeRef1229
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 16097.9);
+ polygon.ps[1] = Point(8889.03, 16137.9);
+ polygon.ps[2] = Point(8834.03, 16137.9);
+ polygon.ps[3] = Point(8834.03, 16097.9);
+ new ShapeRef(router, polygon, 1229);
+
+ // shapeRef1230
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 16097.9);
+ polygon.ps[1] = Point(8989.03, 16137.9);
+ polygon.ps[2] = Point(8934.03, 16137.9);
+ polygon.ps[3] = Point(8934.03, 16097.9);
+ new ShapeRef(router, polygon, 1230);
+
+ // shapeRef1231
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 16097.9);
+ polygon.ps[1] = Point(9089.03, 16137.9);
+ polygon.ps[2] = Point(9034.03, 16137.9);
+ polygon.ps[3] = Point(9034.03, 16097.9);
+ new ShapeRef(router, polygon, 1231);
+
+ // shapeRef1232
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 16097.9);
+ polygon.ps[1] = Point(9189.03, 16137.9);
+ polygon.ps[2] = Point(9134.03, 16137.9);
+ polygon.ps[3] = Point(9134.03, 16097.9);
+ new ShapeRef(router, polygon, 1232);
+
+ // shapeRef1233
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 16097.9);
+ polygon.ps[1] = Point(9289.03, 16137.9);
+ polygon.ps[2] = Point(9234.03, 16137.9);
+ polygon.ps[3] = Point(9234.03, 16097.9);
+ new ShapeRef(router, polygon, 1233);
+
+ // shapeRef1234
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 16097.9);
+ polygon.ps[1] = Point(9389.03, 16137.9);
+ polygon.ps[2] = Point(9334.03, 16137.9);
+ polygon.ps[3] = Point(9334.03, 16097.9);
+ new ShapeRef(router, polygon, 1234);
+
+ // shapeRef1235
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 16197.9);
+ polygon.ps[1] = Point(8389.03, 16237.9);
+ polygon.ps[2] = Point(8334.03, 16237.9);
+ polygon.ps[3] = Point(8334.03, 16197.9);
+ new ShapeRef(router, polygon, 1235);
+
+ // shapeRef1236
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 16197.9);
+ polygon.ps[1] = Point(8489.03, 16237.9);
+ polygon.ps[2] = Point(8434.03, 16237.9);
+ polygon.ps[3] = Point(8434.03, 16197.9);
+ new ShapeRef(router, polygon, 1236);
+
+ // shapeRef1237
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 16197.9);
+ polygon.ps[1] = Point(8589.03, 16237.9);
+ polygon.ps[2] = Point(8534.03, 16237.9);
+ polygon.ps[3] = Point(8534.03, 16197.9);
+ new ShapeRef(router, polygon, 1237);
+
+ // shapeRef1238
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 16197.9);
+ polygon.ps[1] = Point(8689.03, 16237.9);
+ polygon.ps[2] = Point(8634.03, 16237.9);
+ polygon.ps[3] = Point(8634.03, 16197.9);
+ new ShapeRef(router, polygon, 1238);
+
+ // shapeRef1239
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 16197.9);
+ polygon.ps[1] = Point(8789.03, 16237.9);
+ polygon.ps[2] = Point(8734.03, 16237.9);
+ polygon.ps[3] = Point(8734.03, 16197.9);
+ new ShapeRef(router, polygon, 1239);
+
+ // shapeRef1240
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 16197.9);
+ polygon.ps[1] = Point(8889.03, 16237.9);
+ polygon.ps[2] = Point(8834.03, 16237.9);
+ polygon.ps[3] = Point(8834.03, 16197.9);
+ new ShapeRef(router, polygon, 1240);
+
+ // shapeRef1241
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 16197.9);
+ polygon.ps[1] = Point(8989.03, 16237.9);
+ polygon.ps[2] = Point(8934.03, 16237.9);
+ polygon.ps[3] = Point(8934.03, 16197.9);
+ new ShapeRef(router, polygon, 1241);
+
+ // shapeRef1242
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 16197.9);
+ polygon.ps[1] = Point(9089.03, 16237.9);
+ polygon.ps[2] = Point(9034.03, 16237.9);
+ polygon.ps[3] = Point(9034.03, 16197.9);
+ new ShapeRef(router, polygon, 1242);
+
+ // shapeRef1243
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 16197.9);
+ polygon.ps[1] = Point(9189.03, 16237.9);
+ polygon.ps[2] = Point(9134.03, 16237.9);
+ polygon.ps[3] = Point(9134.03, 16197.9);
+ new ShapeRef(router, polygon, 1243);
+
+ // shapeRef1244
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 16197.9);
+ polygon.ps[1] = Point(9289.03, 16237.9);
+ polygon.ps[2] = Point(9234.03, 16237.9);
+ polygon.ps[3] = Point(9234.03, 16197.9);
+ new ShapeRef(router, polygon, 1244);
+
+ // shapeRef1245
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 16197.9);
+ polygon.ps[1] = Point(9389.03, 16237.9);
+ polygon.ps[2] = Point(9334.03, 16237.9);
+ polygon.ps[3] = Point(9334.03, 16197.9);
+ new ShapeRef(router, polygon, 1245);
+
+ // shapeRef1246
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 16297.9);
+ polygon.ps[1] = Point(8389.03, 16337.9);
+ polygon.ps[2] = Point(8334.03, 16337.9);
+ polygon.ps[3] = Point(8334.03, 16297.9);
+ new ShapeRef(router, polygon, 1246);
+
+ // shapeRef1247
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 16297.9);
+ polygon.ps[1] = Point(8489.03, 16337.9);
+ polygon.ps[2] = Point(8434.03, 16337.9);
+ polygon.ps[3] = Point(8434.03, 16297.9);
+ new ShapeRef(router, polygon, 1247);
+
+ // shapeRef1248
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 16297.9);
+ polygon.ps[1] = Point(8589.03, 16337.9);
+ polygon.ps[2] = Point(8534.03, 16337.9);
+ polygon.ps[3] = Point(8534.03, 16297.9);
+ new ShapeRef(router, polygon, 1248);
+
+ // shapeRef1249
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 16297.9);
+ polygon.ps[1] = Point(8689.03, 16337.9);
+ polygon.ps[2] = Point(8634.03, 16337.9);
+ polygon.ps[3] = Point(8634.03, 16297.9);
+ new ShapeRef(router, polygon, 1249);
+
+ // shapeRef1250
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 16297.9);
+ polygon.ps[1] = Point(8789.03, 16337.9);
+ polygon.ps[2] = Point(8734.03, 16337.9);
+ polygon.ps[3] = Point(8734.03, 16297.9);
+ new ShapeRef(router, polygon, 1250);
+
+ // shapeRef1251
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 16297.9);
+ polygon.ps[1] = Point(8889.03, 16337.9);
+ polygon.ps[2] = Point(8834.03, 16337.9);
+ polygon.ps[3] = Point(8834.03, 16297.9);
+ new ShapeRef(router, polygon, 1251);
+
+ // shapeRef1252
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 16297.9);
+ polygon.ps[1] = Point(8989.03, 16337.9);
+ polygon.ps[2] = Point(8934.03, 16337.9);
+ polygon.ps[3] = Point(8934.03, 16297.9);
+ new ShapeRef(router, polygon, 1252);
+
+ // shapeRef1253
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 16297.9);
+ polygon.ps[1] = Point(9089.03, 16337.9);
+ polygon.ps[2] = Point(9034.03, 16337.9);
+ polygon.ps[3] = Point(9034.03, 16297.9);
+ new ShapeRef(router, polygon, 1253);
+
+ // shapeRef1254
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 16297.9);
+ polygon.ps[1] = Point(9189.03, 16337.9);
+ polygon.ps[2] = Point(9134.03, 16337.9);
+ polygon.ps[3] = Point(9134.03, 16297.9);
+ new ShapeRef(router, polygon, 1254);
+
+ // shapeRef1255
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 16297.9);
+ polygon.ps[1] = Point(9289.03, 16337.9);
+ polygon.ps[2] = Point(9234.03, 16337.9);
+ polygon.ps[3] = Point(9234.03, 16297.9);
+ new ShapeRef(router, polygon, 1255);
+
+ // shapeRef1256
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 16297.9);
+ polygon.ps[1] = Point(9389.03, 16337.9);
+ polygon.ps[2] = Point(9334.03, 16337.9);
+ polygon.ps[3] = Point(9334.03, 16297.9);
+ new ShapeRef(router, polygon, 1256);
+
+ // shapeRef1257
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 16397.9);
+ polygon.ps[1] = Point(8389.03, 16437.9);
+ polygon.ps[2] = Point(8334.03, 16437.9);
+ polygon.ps[3] = Point(8334.03, 16397.9);
+ new ShapeRef(router, polygon, 1257);
+
+ // shapeRef1258
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 16397.9);
+ polygon.ps[1] = Point(8489.03, 16437.9);
+ polygon.ps[2] = Point(8434.03, 16437.9);
+ polygon.ps[3] = Point(8434.03, 16397.9);
+ new ShapeRef(router, polygon, 1258);
+
+ // shapeRef1259
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 16397.9);
+ polygon.ps[1] = Point(8589.03, 16437.9);
+ polygon.ps[2] = Point(8534.03, 16437.9);
+ polygon.ps[3] = Point(8534.03, 16397.9);
+ new ShapeRef(router, polygon, 1259);
+
+ // shapeRef1260
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 16397.9);
+ polygon.ps[1] = Point(8689.03, 16437.9);
+ polygon.ps[2] = Point(8634.03, 16437.9);
+ polygon.ps[3] = Point(8634.03, 16397.9);
+ new ShapeRef(router, polygon, 1260);
+
+ // shapeRef1261
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 16397.9);
+ polygon.ps[1] = Point(8789.03, 16437.9);
+ polygon.ps[2] = Point(8734.03, 16437.9);
+ polygon.ps[3] = Point(8734.03, 16397.9);
+ new ShapeRef(router, polygon, 1261);
+
+ // shapeRef1262
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 16397.9);
+ polygon.ps[1] = Point(8889.03, 16437.9);
+ polygon.ps[2] = Point(8834.03, 16437.9);
+ polygon.ps[3] = Point(8834.03, 16397.9);
+ new ShapeRef(router, polygon, 1262);
+
+ // shapeRef1263
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 16397.9);
+ polygon.ps[1] = Point(8989.03, 16437.9);
+ polygon.ps[2] = Point(8934.03, 16437.9);
+ polygon.ps[3] = Point(8934.03, 16397.9);
+ new ShapeRef(router, polygon, 1263);
+
+ // shapeRef1264
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 16397.9);
+ polygon.ps[1] = Point(9089.03, 16437.9);
+ polygon.ps[2] = Point(9034.03, 16437.9);
+ polygon.ps[3] = Point(9034.03, 16397.9);
+ new ShapeRef(router, polygon, 1264);
+
+ // shapeRef1265
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 16397.9);
+ polygon.ps[1] = Point(9189.03, 16437.9);
+ polygon.ps[2] = Point(9134.03, 16437.9);
+ polygon.ps[3] = Point(9134.03, 16397.9);
+ new ShapeRef(router, polygon, 1265);
+
+ // shapeRef1266
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 16397.9);
+ polygon.ps[1] = Point(9289.03, 16437.9);
+ polygon.ps[2] = Point(9234.03, 16437.9);
+ polygon.ps[3] = Point(9234.03, 16397.9);
+ new ShapeRef(router, polygon, 1266);
+
+ // shapeRef1267
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 16397.9);
+ polygon.ps[1] = Point(9389.03, 16437.9);
+ polygon.ps[2] = Point(9334.03, 16437.9);
+ polygon.ps[3] = Point(9334.03, 16397.9);
+ new ShapeRef(router, polygon, 1267);
+
+ // shapeRef1268
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 16497.9);
+ polygon.ps[1] = Point(8389.03, 16537.9);
+ polygon.ps[2] = Point(8334.03, 16537.9);
+ polygon.ps[3] = Point(8334.03, 16497.9);
+ new ShapeRef(router, polygon, 1268);
+
+ // shapeRef1269
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 16497.9);
+ polygon.ps[1] = Point(8489.03, 16537.9);
+ polygon.ps[2] = Point(8434.03, 16537.9);
+ polygon.ps[3] = Point(8434.03, 16497.9);
+ new ShapeRef(router, polygon, 1269);
+
+ // shapeRef1270
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 16497.9);
+ polygon.ps[1] = Point(8589.03, 16537.9);
+ polygon.ps[2] = Point(8534.03, 16537.9);
+ polygon.ps[3] = Point(8534.03, 16497.9);
+ new ShapeRef(router, polygon, 1270);
+
+ // shapeRef1271
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 16497.9);
+ polygon.ps[1] = Point(8689.03, 16537.9);
+ polygon.ps[2] = Point(8634.03, 16537.9);
+ polygon.ps[3] = Point(8634.03, 16497.9);
+ new ShapeRef(router, polygon, 1271);
+
+ // shapeRef1272
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 16497.9);
+ polygon.ps[1] = Point(8789.03, 16537.9);
+ polygon.ps[2] = Point(8734.03, 16537.9);
+ polygon.ps[3] = Point(8734.03, 16497.9);
+ new ShapeRef(router, polygon, 1272);
+
+ // shapeRef1273
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 16497.9);
+ polygon.ps[1] = Point(8889.03, 16537.9);
+ polygon.ps[2] = Point(8834.03, 16537.9);
+ polygon.ps[3] = Point(8834.03, 16497.9);
+ new ShapeRef(router, polygon, 1273);
+
+ // shapeRef1274
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 16497.9);
+ polygon.ps[1] = Point(8989.03, 16537.9);
+ polygon.ps[2] = Point(8934.03, 16537.9);
+ polygon.ps[3] = Point(8934.03, 16497.9);
+ new ShapeRef(router, polygon, 1274);
+
+ // shapeRef1275
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 16497.9);
+ polygon.ps[1] = Point(9089.03, 16537.9);
+ polygon.ps[2] = Point(9034.03, 16537.9);
+ polygon.ps[3] = Point(9034.03, 16497.9);
+ new ShapeRef(router, polygon, 1275);
+
+ // shapeRef1276
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 16497.9);
+ polygon.ps[1] = Point(9189.03, 16537.9);
+ polygon.ps[2] = Point(9134.03, 16537.9);
+ polygon.ps[3] = Point(9134.03, 16497.9);
+ new ShapeRef(router, polygon, 1276);
+
+ // shapeRef1277
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 16497.9);
+ polygon.ps[1] = Point(9289.03, 16537.9);
+ polygon.ps[2] = Point(9234.03, 16537.9);
+ polygon.ps[3] = Point(9234.03, 16497.9);
+ new ShapeRef(router, polygon, 1277);
+
+ // shapeRef1278
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 16497.9);
+ polygon.ps[1] = Point(9389.03, 16537.9);
+ polygon.ps[2] = Point(9334.03, 16537.9);
+ polygon.ps[3] = Point(9334.03, 16497.9);
+ new ShapeRef(router, polygon, 1278);
+
+ // shapeRef1279
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 16597.9);
+ polygon.ps[1] = Point(8389.03, 16637.9);
+ polygon.ps[2] = Point(8334.03, 16637.9);
+ polygon.ps[3] = Point(8334.03, 16597.9);
+ new ShapeRef(router, polygon, 1279);
+
+ // shapeRef1280
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 16597.9);
+ polygon.ps[1] = Point(8489.03, 16637.9);
+ polygon.ps[2] = Point(8434.03, 16637.9);
+ polygon.ps[3] = Point(8434.03, 16597.9);
+ new ShapeRef(router, polygon, 1280);
+
+ // shapeRef1281
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 16597.9);
+ polygon.ps[1] = Point(8589.03, 16637.9);
+ polygon.ps[2] = Point(8534.03, 16637.9);
+ polygon.ps[3] = Point(8534.03, 16597.9);
+ new ShapeRef(router, polygon, 1281);
+
+ // shapeRef1282
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 16597.9);
+ polygon.ps[1] = Point(8689.03, 16637.9);
+ polygon.ps[2] = Point(8634.03, 16637.9);
+ polygon.ps[3] = Point(8634.03, 16597.9);
+ new ShapeRef(router, polygon, 1282);
+
+ // shapeRef1283
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 16597.9);
+ polygon.ps[1] = Point(8789.03, 16637.9);
+ polygon.ps[2] = Point(8734.03, 16637.9);
+ polygon.ps[3] = Point(8734.03, 16597.9);
+ new ShapeRef(router, polygon, 1283);
+
+ // shapeRef1284
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 16597.9);
+ polygon.ps[1] = Point(8889.03, 16637.9);
+ polygon.ps[2] = Point(8834.03, 16637.9);
+ polygon.ps[3] = Point(8834.03, 16597.9);
+ new ShapeRef(router, polygon, 1284);
+
+ // shapeRef1285
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 16597.9);
+ polygon.ps[1] = Point(8989.03, 16637.9);
+ polygon.ps[2] = Point(8934.03, 16637.9);
+ polygon.ps[3] = Point(8934.03, 16597.9);
+ new ShapeRef(router, polygon, 1285);
+
+ // shapeRef1286
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 16597.9);
+ polygon.ps[1] = Point(9089.03, 16637.9);
+ polygon.ps[2] = Point(9034.03, 16637.9);
+ polygon.ps[3] = Point(9034.03, 16597.9);
+ new ShapeRef(router, polygon, 1286);
+
+ // shapeRef1287
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 16597.9);
+ polygon.ps[1] = Point(9189.03, 16637.9);
+ polygon.ps[2] = Point(9134.03, 16637.9);
+ polygon.ps[3] = Point(9134.03, 16597.9);
+ new ShapeRef(router, polygon, 1287);
+
+ // shapeRef1288
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 16597.9);
+ polygon.ps[1] = Point(9289.03, 16637.9);
+ polygon.ps[2] = Point(9234.03, 16637.9);
+ polygon.ps[3] = Point(9234.03, 16597.9);
+ new ShapeRef(router, polygon, 1288);
+
+ // shapeRef1289
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 16597.9);
+ polygon.ps[1] = Point(9389.03, 16637.9);
+ polygon.ps[2] = Point(9334.03, 16637.9);
+ polygon.ps[3] = Point(9334.03, 16597.9);
+ new ShapeRef(router, polygon, 1289);
+
+ // shapeRef1290
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 16697.9);
+ polygon.ps[1] = Point(8389.03, 16737.9);
+ polygon.ps[2] = Point(8334.03, 16737.9);
+ polygon.ps[3] = Point(8334.03, 16697.9);
+ new ShapeRef(router, polygon, 1290);
+
+ // shapeRef1291
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 16697.9);
+ polygon.ps[1] = Point(8489.03, 16737.9);
+ polygon.ps[2] = Point(8434.03, 16737.9);
+ polygon.ps[3] = Point(8434.03, 16697.9);
+ new ShapeRef(router, polygon, 1291);
+
+ // shapeRef1292
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 16697.9);
+ polygon.ps[1] = Point(8589.03, 16737.9);
+ polygon.ps[2] = Point(8534.03, 16737.9);
+ polygon.ps[3] = Point(8534.03, 16697.9);
+ new ShapeRef(router, polygon, 1292);
+
+ // shapeRef1293
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 16697.9);
+ polygon.ps[1] = Point(8689.03, 16737.9);
+ polygon.ps[2] = Point(8634.03, 16737.9);
+ polygon.ps[3] = Point(8634.03, 16697.9);
+ new ShapeRef(router, polygon, 1293);
+
+ // shapeRef1294
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 16697.9);
+ polygon.ps[1] = Point(8789.03, 16737.9);
+ polygon.ps[2] = Point(8734.03, 16737.9);
+ polygon.ps[3] = Point(8734.03, 16697.9);
+ new ShapeRef(router, polygon, 1294);
+
+ // shapeRef1295
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 16697.9);
+ polygon.ps[1] = Point(8889.03, 16737.9);
+ polygon.ps[2] = Point(8834.03, 16737.9);
+ polygon.ps[3] = Point(8834.03, 16697.9);
+ new ShapeRef(router, polygon, 1295);
+
+ // shapeRef1296
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 16697.9);
+ polygon.ps[1] = Point(8989.03, 16737.9);
+ polygon.ps[2] = Point(8934.03, 16737.9);
+ polygon.ps[3] = Point(8934.03, 16697.9);
+ new ShapeRef(router, polygon, 1296);
+
+ // shapeRef1297
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 16697.9);
+ polygon.ps[1] = Point(9089.03, 16737.9);
+ polygon.ps[2] = Point(9034.03, 16737.9);
+ polygon.ps[3] = Point(9034.03, 16697.9);
+ new ShapeRef(router, polygon, 1297);
+
+ // shapeRef1298
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 16697.9);
+ polygon.ps[1] = Point(9189.03, 16737.9);
+ polygon.ps[2] = Point(9134.03, 16737.9);
+ polygon.ps[3] = Point(9134.03, 16697.9);
+ new ShapeRef(router, polygon, 1298);
+
+ // shapeRef1299
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 16697.9);
+ polygon.ps[1] = Point(9289.03, 16737.9);
+ polygon.ps[2] = Point(9234.03, 16737.9);
+ polygon.ps[3] = Point(9234.03, 16697.9);
+ new ShapeRef(router, polygon, 1299);
+
+ // shapeRef1300
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 16697.9);
+ polygon.ps[1] = Point(9389.03, 16737.9);
+ polygon.ps[2] = Point(9334.03, 16737.9);
+ polygon.ps[3] = Point(9334.03, 16697.9);
+ new ShapeRef(router, polygon, 1300);
+
+ // shapeRef1301
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 16797.9);
+ polygon.ps[1] = Point(8389.03, 16837.9);
+ polygon.ps[2] = Point(8334.03, 16837.9);
+ polygon.ps[3] = Point(8334.03, 16797.9);
+ new ShapeRef(router, polygon, 1301);
+
+ // shapeRef1302
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 16797.9);
+ polygon.ps[1] = Point(8489.03, 16837.9);
+ polygon.ps[2] = Point(8434.03, 16837.9);
+ polygon.ps[3] = Point(8434.03, 16797.9);
+ new ShapeRef(router, polygon, 1302);
+
+ // shapeRef1303
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 16797.9);
+ polygon.ps[1] = Point(8589.03, 16837.9);
+ polygon.ps[2] = Point(8534.03, 16837.9);
+ polygon.ps[3] = Point(8534.03, 16797.9);
+ new ShapeRef(router, polygon, 1303);
+
+ // shapeRef1304
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 16797.9);
+ polygon.ps[1] = Point(8689.03, 16837.9);
+ polygon.ps[2] = Point(8634.03, 16837.9);
+ polygon.ps[3] = Point(8634.03, 16797.9);
+ new ShapeRef(router, polygon, 1304);
+
+ // shapeRef1305
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 16797.9);
+ polygon.ps[1] = Point(8789.03, 16837.9);
+ polygon.ps[2] = Point(8734.03, 16837.9);
+ polygon.ps[3] = Point(8734.03, 16797.9);
+ new ShapeRef(router, polygon, 1305);
+
+ // shapeRef1306
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 16797.9);
+ polygon.ps[1] = Point(8889.03, 16837.9);
+ polygon.ps[2] = Point(8834.03, 16837.9);
+ polygon.ps[3] = Point(8834.03, 16797.9);
+ new ShapeRef(router, polygon, 1306);
+
+ // shapeRef1307
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 16797.9);
+ polygon.ps[1] = Point(8989.03, 16837.9);
+ polygon.ps[2] = Point(8934.03, 16837.9);
+ polygon.ps[3] = Point(8934.03, 16797.9);
+ new ShapeRef(router, polygon, 1307);
+
+ // shapeRef1308
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 16797.9);
+ polygon.ps[1] = Point(9089.03, 16837.9);
+ polygon.ps[2] = Point(9034.03, 16837.9);
+ polygon.ps[3] = Point(9034.03, 16797.9);
+ new ShapeRef(router, polygon, 1308);
+
+ // shapeRef1309
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 16797.9);
+ polygon.ps[1] = Point(9189.03, 16837.9);
+ polygon.ps[2] = Point(9134.03, 16837.9);
+ polygon.ps[3] = Point(9134.03, 16797.9);
+ new ShapeRef(router, polygon, 1309);
+
+ // shapeRef1310
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 16797.9);
+ polygon.ps[1] = Point(9289.03, 16837.9);
+ polygon.ps[2] = Point(9234.03, 16837.9);
+ polygon.ps[3] = Point(9234.03, 16797.9);
+ new ShapeRef(router, polygon, 1310);
+
+ // shapeRef1311
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 16897.9);
+ polygon.ps[1] = Point(8389.03, 16937.9);
+ polygon.ps[2] = Point(8334.03, 16937.9);
+ polygon.ps[3] = Point(8334.03, 16897.9);
+ new ShapeRef(router, polygon, 1311);
+
+ // shapeRef1312
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 16897.9);
+ polygon.ps[1] = Point(8489.03, 16937.9);
+ polygon.ps[2] = Point(8434.03, 16937.9);
+ polygon.ps[3] = Point(8434.03, 16897.9);
+ new ShapeRef(router, polygon, 1312);
+
+ // shapeRef1313
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 16897.9);
+ polygon.ps[1] = Point(8589.03, 16937.9);
+ polygon.ps[2] = Point(8534.03, 16937.9);
+ polygon.ps[3] = Point(8534.03, 16897.9);
+ new ShapeRef(router, polygon, 1313);
+
+ // shapeRef1314
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 16897.9);
+ polygon.ps[1] = Point(8689.03, 16937.9);
+ polygon.ps[2] = Point(8634.03, 16937.9);
+ polygon.ps[3] = Point(8634.03, 16897.9);
+ new ShapeRef(router, polygon, 1314);
+
+ // shapeRef1315
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 16897.9);
+ polygon.ps[1] = Point(8789.03, 16937.9);
+ polygon.ps[2] = Point(8734.03, 16937.9);
+ polygon.ps[3] = Point(8734.03, 16897.9);
+ new ShapeRef(router, polygon, 1315);
+
+ // shapeRef1316
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 16897.9);
+ polygon.ps[1] = Point(8889.03, 16937.9);
+ polygon.ps[2] = Point(8834.03, 16937.9);
+ polygon.ps[3] = Point(8834.03, 16897.9);
+ new ShapeRef(router, polygon, 1316);
+
+ // shapeRef1317
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 16897.9);
+ polygon.ps[1] = Point(8989.03, 16937.9);
+ polygon.ps[2] = Point(8934.03, 16937.9);
+ polygon.ps[3] = Point(8934.03, 16897.9);
+ new ShapeRef(router, polygon, 1317);
+
+ // shapeRef1318
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 16897.9);
+ polygon.ps[1] = Point(9189.03, 16937.9);
+ polygon.ps[2] = Point(9134.03, 16937.9);
+ polygon.ps[3] = Point(9134.03, 16897.9);
+ new ShapeRef(router, polygon, 1318);
+
+ // shapeRef1319
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 16897.9);
+ polygon.ps[1] = Point(9289.03, 16937.9);
+ polygon.ps[2] = Point(9234.03, 16937.9);
+ polygon.ps[3] = Point(9234.03, 16897.9);
+ new ShapeRef(router, polygon, 1319);
+
+ // shapeRef1320
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 16897.9);
+ polygon.ps[1] = Point(9389.03, 16937.9);
+ polygon.ps[2] = Point(9334.03, 16937.9);
+ polygon.ps[3] = Point(9334.03, 16897.9);
+ new ShapeRef(router, polygon, 1320);
+
+ // shapeRef1321
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 16997.9);
+ polygon.ps[1] = Point(8389.03, 17037.9);
+ polygon.ps[2] = Point(8334.03, 17037.9);
+ polygon.ps[3] = Point(8334.03, 16997.9);
+ new ShapeRef(router, polygon, 1321);
+
+ // shapeRef1322
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 16997.9);
+ polygon.ps[1] = Point(8489.03, 17037.9);
+ polygon.ps[2] = Point(8434.03, 17037.9);
+ polygon.ps[3] = Point(8434.03, 16997.9);
+ new ShapeRef(router, polygon, 1322);
+
+ // shapeRef1323
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 16997.9);
+ polygon.ps[1] = Point(8589.03, 17037.9);
+ polygon.ps[2] = Point(8534.03, 17037.9);
+ polygon.ps[3] = Point(8534.03, 16997.9);
+ new ShapeRef(router, polygon, 1323);
+
+ // shapeRef1324
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 16997.9);
+ polygon.ps[1] = Point(8789.03, 17037.9);
+ polygon.ps[2] = Point(8734.03, 17037.9);
+ polygon.ps[3] = Point(8734.03, 16997.9);
+ new ShapeRef(router, polygon, 1324);
+
+ // shapeRef1325
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 16997.9);
+ polygon.ps[1] = Point(8889.03, 17037.9);
+ polygon.ps[2] = Point(8834.03, 17037.9);
+ polygon.ps[3] = Point(8834.03, 16997.9);
+ new ShapeRef(router, polygon, 1325);
+
+ // shapeRef1326
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 16997.9);
+ polygon.ps[1] = Point(8989.03, 17037.9);
+ polygon.ps[2] = Point(8934.03, 17037.9);
+ polygon.ps[3] = Point(8934.03, 16997.9);
+ new ShapeRef(router, polygon, 1326);
+
+ // shapeRef1327
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 16997.9);
+ polygon.ps[1] = Point(9089.03, 17037.9);
+ polygon.ps[2] = Point(9034.03, 17037.9);
+ polygon.ps[3] = Point(9034.03, 16997.9);
+ new ShapeRef(router, polygon, 1327);
+
+ // shapeRef1328
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 16997.9);
+ polygon.ps[1] = Point(9189.03, 17037.9);
+ polygon.ps[2] = Point(9134.03, 17037.9);
+ polygon.ps[3] = Point(9134.03, 16997.9);
+ new ShapeRef(router, polygon, 1328);
+
+ // shapeRef1329
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 16997.9);
+ polygon.ps[1] = Point(9289.03, 17037.9);
+ polygon.ps[2] = Point(9234.03, 17037.9);
+ polygon.ps[3] = Point(9234.03, 16997.9);
+ new ShapeRef(router, polygon, 1329);
+
+ // shapeRef1330
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 16997.9);
+ polygon.ps[1] = Point(9389.03, 17037.9);
+ polygon.ps[2] = Point(9334.03, 17037.9);
+ polygon.ps[3] = Point(9334.03, 16997.9);
+ new ShapeRef(router, polygon, 1330);
+
+ // shapeRef1331
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 17097.9);
+ polygon.ps[1] = Point(8389.03, 17137.9);
+ polygon.ps[2] = Point(8334.03, 17137.9);
+ polygon.ps[3] = Point(8334.03, 17097.9);
+ new ShapeRef(router, polygon, 1331);
+
+ // shapeRef1332
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 17097.9);
+ polygon.ps[1] = Point(8489.03, 17137.9);
+ polygon.ps[2] = Point(8434.03, 17137.9);
+ polygon.ps[3] = Point(8434.03, 17097.9);
+ new ShapeRef(router, polygon, 1332);
+
+ // shapeRef1333
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 17097.9);
+ polygon.ps[1] = Point(8589.03, 17137.9);
+ polygon.ps[2] = Point(8534.03, 17137.9);
+ polygon.ps[3] = Point(8534.03, 17097.9);
+ new ShapeRef(router, polygon, 1333);
+
+ // shapeRef1334
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 17097.9);
+ polygon.ps[1] = Point(8689.03, 17137.9);
+ polygon.ps[2] = Point(8634.03, 17137.9);
+ polygon.ps[3] = Point(8634.03, 17097.9);
+ new ShapeRef(router, polygon, 1334);
+
+ // shapeRef1335
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 17097.9);
+ polygon.ps[1] = Point(8789.03, 17137.9);
+ polygon.ps[2] = Point(8734.03, 17137.9);
+ polygon.ps[3] = Point(8734.03, 17097.9);
+ new ShapeRef(router, polygon, 1335);
+
+ // shapeRef1336
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 17097.9);
+ polygon.ps[1] = Point(8889.03, 17137.9);
+ polygon.ps[2] = Point(8834.03, 17137.9);
+ polygon.ps[3] = Point(8834.03, 17097.9);
+ new ShapeRef(router, polygon, 1336);
+
+ // shapeRef1337
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 17097.9);
+ polygon.ps[1] = Point(8989.03, 17137.9);
+ polygon.ps[2] = Point(8934.03, 17137.9);
+ polygon.ps[3] = Point(8934.03, 17097.9);
+ new ShapeRef(router, polygon, 1337);
+
+ // shapeRef1338
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 17097.9);
+ polygon.ps[1] = Point(9089.03, 17137.9);
+ polygon.ps[2] = Point(9034.03, 17137.9);
+ polygon.ps[3] = Point(9034.03, 17097.9);
+ new ShapeRef(router, polygon, 1338);
+
+ // shapeRef1339
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 17097.9);
+ polygon.ps[1] = Point(9289.03, 17137.9);
+ polygon.ps[2] = Point(9234.03, 17137.9);
+ polygon.ps[3] = Point(9234.03, 17097.9);
+ new ShapeRef(router, polygon, 1339);
+
+ // shapeRef1340
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 17097.9);
+ polygon.ps[1] = Point(9389.03, 17137.9);
+ polygon.ps[2] = Point(9334.03, 17137.9);
+ polygon.ps[3] = Point(9334.03, 17097.9);
+ new ShapeRef(router, polygon, 1340);
+
+ // shapeRef1341
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 17197.9);
+ polygon.ps[1] = Point(8389.03, 17237.9);
+ polygon.ps[2] = Point(8334.03, 17237.9);
+ polygon.ps[3] = Point(8334.03, 17197.9);
+ new ShapeRef(router, polygon, 1341);
+
+ // shapeRef1342
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 17197.9);
+ polygon.ps[1] = Point(8489.03, 17237.9);
+ polygon.ps[2] = Point(8434.03, 17237.9);
+ polygon.ps[3] = Point(8434.03, 17197.9);
+ new ShapeRef(router, polygon, 1342);
+
+ // shapeRef1343
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 17197.9);
+ polygon.ps[1] = Point(8589.03, 17237.9);
+ polygon.ps[2] = Point(8534.03, 17237.9);
+ polygon.ps[3] = Point(8534.03, 17197.9);
+ new ShapeRef(router, polygon, 1343);
+
+ // shapeRef1344
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 17197.9);
+ polygon.ps[1] = Point(8789.03, 17237.9);
+ polygon.ps[2] = Point(8734.03, 17237.9);
+ polygon.ps[3] = Point(8734.03, 17197.9);
+ new ShapeRef(router, polygon, 1344);
+
+ // shapeRef1345
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 17197.9);
+ polygon.ps[1] = Point(8889.03, 17237.9);
+ polygon.ps[2] = Point(8834.03, 17237.9);
+ polygon.ps[3] = Point(8834.03, 17197.9);
+ new ShapeRef(router, polygon, 1345);
+
+ // shapeRef1346
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 17197.9);
+ polygon.ps[1] = Point(8989.03, 17237.9);
+ polygon.ps[2] = Point(8934.03, 17237.9);
+ polygon.ps[3] = Point(8934.03, 17197.9);
+ new ShapeRef(router, polygon, 1346);
+
+ // shapeRef1347
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 17197.9);
+ polygon.ps[1] = Point(9089.03, 17237.9);
+ polygon.ps[2] = Point(9034.03, 17237.9);
+ polygon.ps[3] = Point(9034.03, 17197.9);
+ new ShapeRef(router, polygon, 1347);
+
+ // shapeRef1348
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 17197.9);
+ polygon.ps[1] = Point(9189.03, 17237.9);
+ polygon.ps[2] = Point(9134.03, 17237.9);
+ polygon.ps[3] = Point(9134.03, 17197.9);
+ new ShapeRef(router, polygon, 1348);
+
+ // shapeRef1349
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 17197.9);
+ polygon.ps[1] = Point(9289.03, 17237.9);
+ polygon.ps[2] = Point(9234.03, 17237.9);
+ polygon.ps[3] = Point(9234.03, 17197.9);
+ new ShapeRef(router, polygon, 1349);
+
+ // shapeRef1350
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 17197.9);
+ polygon.ps[1] = Point(9389.03, 17237.9);
+ polygon.ps[2] = Point(9334.03, 17237.9);
+ polygon.ps[3] = Point(9334.03, 17197.9);
+ new ShapeRef(router, polygon, 1350);
+
+ // shapeRef1351
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 17297.9);
+ polygon.ps[1] = Point(8389.03, 17337.9);
+ polygon.ps[2] = Point(8334.03, 17337.9);
+ polygon.ps[3] = Point(8334.03, 17297.9);
+ new ShapeRef(router, polygon, 1351);
+
+ // shapeRef1352
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 17297.9);
+ polygon.ps[1] = Point(8489.03, 17337.9);
+ polygon.ps[2] = Point(8434.03, 17337.9);
+ polygon.ps[3] = Point(8434.03, 17297.9);
+ new ShapeRef(router, polygon, 1352);
+
+ // shapeRef1353
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 17297.9);
+ polygon.ps[1] = Point(8589.03, 17337.9);
+ polygon.ps[2] = Point(8534.03, 17337.9);
+ polygon.ps[3] = Point(8534.03, 17297.9);
+ new ShapeRef(router, polygon, 1353);
+
+ // shapeRef1354
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 17297.9);
+ polygon.ps[1] = Point(8689.03, 17337.9);
+ polygon.ps[2] = Point(8634.03, 17337.9);
+ polygon.ps[3] = Point(8634.03, 17297.9);
+ new ShapeRef(router, polygon, 1354);
+
+ // shapeRef1355
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 17297.9);
+ polygon.ps[1] = Point(8789.03, 17337.9);
+ polygon.ps[2] = Point(8734.03, 17337.9);
+ polygon.ps[3] = Point(8734.03, 17297.9);
+ new ShapeRef(router, polygon, 1355);
+
+ // shapeRef1356
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 17297.9);
+ polygon.ps[1] = Point(8889.03, 17337.9);
+ polygon.ps[2] = Point(8834.03, 17337.9);
+ polygon.ps[3] = Point(8834.03, 17297.9);
+ new ShapeRef(router, polygon, 1356);
+
+ // shapeRef1357
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 17297.9);
+ polygon.ps[1] = Point(8989.03, 17337.9);
+ polygon.ps[2] = Point(8934.03, 17337.9);
+ polygon.ps[3] = Point(8934.03, 17297.9);
+ new ShapeRef(router, polygon, 1357);
+
+ // shapeRef1358
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 17297.9);
+ polygon.ps[1] = Point(9189.03, 17337.9);
+ polygon.ps[2] = Point(9134.03, 17337.9);
+ polygon.ps[3] = Point(9134.03, 17297.9);
+ new ShapeRef(router, polygon, 1358);
+
+ // shapeRef1359
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 17297.9);
+ polygon.ps[1] = Point(9289.03, 17337.9);
+ polygon.ps[2] = Point(9234.03, 17337.9);
+ polygon.ps[3] = Point(9234.03, 17297.9);
+ new ShapeRef(router, polygon, 1359);
+
+ // shapeRef1360
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 17297.9);
+ polygon.ps[1] = Point(9389.03, 17337.9);
+ polygon.ps[2] = Point(9334.03, 17337.9);
+ polygon.ps[3] = Point(9334.03, 17297.9);
+ new ShapeRef(router, polygon, 1360);
+
+ // shapeRef1361
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 17397.9);
+ polygon.ps[1] = Point(8389.03, 17437.9);
+ polygon.ps[2] = Point(8334.03, 17437.9);
+ polygon.ps[3] = Point(8334.03, 17397.9);
+ new ShapeRef(router, polygon, 1361);
+
+ // shapeRef1362
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 17397.9);
+ polygon.ps[1] = Point(8489.03, 17437.9);
+ polygon.ps[2] = Point(8434.03, 17437.9);
+ polygon.ps[3] = Point(8434.03, 17397.9);
+ new ShapeRef(router, polygon, 1362);
+
+ // shapeRef1363
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 17397.9);
+ polygon.ps[1] = Point(8589.03, 17437.9);
+ polygon.ps[2] = Point(8534.03, 17437.9);
+ polygon.ps[3] = Point(8534.03, 17397.9);
+ new ShapeRef(router, polygon, 1363);
+
+ // shapeRef1364
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 17397.9);
+ polygon.ps[1] = Point(8689.03, 17437.9);
+ polygon.ps[2] = Point(8634.03, 17437.9);
+ polygon.ps[3] = Point(8634.03, 17397.9);
+ new ShapeRef(router, polygon, 1364);
+
+ // shapeRef1365
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 17397.9);
+ polygon.ps[1] = Point(8789.03, 17437.9);
+ polygon.ps[2] = Point(8734.03, 17437.9);
+ polygon.ps[3] = Point(8734.03, 17397.9);
+ new ShapeRef(router, polygon, 1365);
+
+ // shapeRef1366
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 17397.9);
+ polygon.ps[1] = Point(8889.03, 17437.9);
+ polygon.ps[2] = Point(8834.03, 17437.9);
+ polygon.ps[3] = Point(8834.03, 17397.9);
+ new ShapeRef(router, polygon, 1366);
+
+ // shapeRef1367
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 17397.9);
+ polygon.ps[1] = Point(8989.03, 17437.9);
+ polygon.ps[2] = Point(8934.03, 17437.9);
+ polygon.ps[3] = Point(8934.03, 17397.9);
+ new ShapeRef(router, polygon, 1367);
+
+ // shapeRef1368
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 17397.9);
+ polygon.ps[1] = Point(9189.03, 17437.9);
+ polygon.ps[2] = Point(9134.03, 17437.9);
+ polygon.ps[3] = Point(9134.03, 17397.9);
+ new ShapeRef(router, polygon, 1368);
+
+ // shapeRef1369
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 17397.9);
+ polygon.ps[1] = Point(9289.03, 17437.9);
+ polygon.ps[2] = Point(9234.03, 17437.9);
+ polygon.ps[3] = Point(9234.03, 17397.9);
+ new ShapeRef(router, polygon, 1369);
+
+ // shapeRef1370
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 17397.9);
+ polygon.ps[1] = Point(9389.03, 17437.9);
+ polygon.ps[2] = Point(9334.03, 17437.9);
+ polygon.ps[3] = Point(9334.03, 17397.9);
+ new ShapeRef(router, polygon, 1370);
+
+ // shapeRef1371
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 17497.9);
+ polygon.ps[1] = Point(8389.03, 17537.9);
+ polygon.ps[2] = Point(8334.03, 17537.9);
+ polygon.ps[3] = Point(8334.03, 17497.9);
+ new ShapeRef(router, polygon, 1371);
+
+ // shapeRef1372
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 17497.9);
+ polygon.ps[1] = Point(8489.03, 17537.9);
+ polygon.ps[2] = Point(8434.03, 17537.9);
+ polygon.ps[3] = Point(8434.03, 17497.9);
+ new ShapeRef(router, polygon, 1372);
+
+ // shapeRef1373
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 17497.9);
+ polygon.ps[1] = Point(8589.03, 17537.9);
+ polygon.ps[2] = Point(8534.03, 17537.9);
+ polygon.ps[3] = Point(8534.03, 17497.9);
+ new ShapeRef(router, polygon, 1373);
+
+ // shapeRef1374
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 17497.9);
+ polygon.ps[1] = Point(8689.03, 17537.9);
+ polygon.ps[2] = Point(8634.03, 17537.9);
+ polygon.ps[3] = Point(8634.03, 17497.9);
+ new ShapeRef(router, polygon, 1374);
+
+ // shapeRef1375
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 17497.9);
+ polygon.ps[1] = Point(8789.03, 17537.9);
+ polygon.ps[2] = Point(8734.03, 17537.9);
+ polygon.ps[3] = Point(8734.03, 17497.9);
+ new ShapeRef(router, polygon, 1375);
+
+ // shapeRef1376
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 17497.9);
+ polygon.ps[1] = Point(8989.03, 17537.9);
+ polygon.ps[2] = Point(8934.03, 17537.9);
+ polygon.ps[3] = Point(8934.03, 17497.9);
+ new ShapeRef(router, polygon, 1376);
+
+ // shapeRef1377
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 17497.9);
+ polygon.ps[1] = Point(9089.03, 17537.9);
+ polygon.ps[2] = Point(9034.03, 17537.9);
+ polygon.ps[3] = Point(9034.03, 17497.9);
+ new ShapeRef(router, polygon, 1377);
+
+ // shapeRef1378
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 17497.9);
+ polygon.ps[1] = Point(9189.03, 17537.9);
+ polygon.ps[2] = Point(9134.03, 17537.9);
+ polygon.ps[3] = Point(9134.03, 17497.9);
+ new ShapeRef(router, polygon, 1378);
+
+ // shapeRef1379
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 17497.9);
+ polygon.ps[1] = Point(9289.03, 17537.9);
+ polygon.ps[2] = Point(9234.03, 17537.9);
+ polygon.ps[3] = Point(9234.03, 17497.9);
+ new ShapeRef(router, polygon, 1379);
+
+ // shapeRef1380
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 17497.9);
+ polygon.ps[1] = Point(9389.03, 17537.9);
+ polygon.ps[2] = Point(9334.03, 17537.9);
+ polygon.ps[3] = Point(9334.03, 17497.9);
+ new ShapeRef(router, polygon, 1380);
+
+ // shapeRef1381
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 17597.9);
+ polygon.ps[1] = Point(8389.03, 17637.9);
+ polygon.ps[2] = Point(8334.03, 17637.9);
+ polygon.ps[3] = Point(8334.03, 17597.9);
+ new ShapeRef(router, polygon, 1381);
+
+ // shapeRef1382
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(492, 4062.51);
+ polygon.ps[1] = Point(492, 4124.51);
+ polygon.ps[2] = Point(430, 4124.51);
+ polygon.ps[3] = Point(430, 4062.51);
+ new ShapeRef(router, polygon, 1382);
+
+ // shapeRef1383
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(261, 4511.4);
+ polygon.ps[1] = Point(261, 4573.4);
+ polygon.ps[2] = Point(199, 4573.4);
+ polygon.ps[3] = Point(199, 4511.4);
+ new ShapeRef(router, polygon, 1383);
+
+ // shapeRef1384
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(261, 4062.51);
+ polygon.ps[1] = Point(261, 4124.51);
+ polygon.ps[2] = Point(199, 4124.51);
+ polygon.ps[3] = Point(199, 4062.51);
+ new ShapeRef(router, polygon, 1384);
+
+ // shapeRef1385
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(96, 4511.4);
+ polygon.ps[1] = Point(96, 4573.4);
+ polygon.ps[2] = Point(34, 4573.4);
+ polygon.ps[3] = Point(34, 4511.4);
+ new ShapeRef(router, polygon, 1385);
+
+ // shapeRef1386
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(492, 4511.4);
+ polygon.ps[1] = Point(492, 4573.4);
+ polygon.ps[2] = Point(430, 4573.4);
+ polygon.ps[3] = Point(430, 4511.4);
+ new ShapeRef(router, polygon, 1386);
+
+ // shapeRef1387
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2439, 4062.51);
+ polygon.ps[1] = Point(2439, 4124.51);
+ polygon.ps[2] = Point(2377, 4124.51);
+ polygon.ps[3] = Point(2377, 4062.51);
+ new ShapeRef(router, polygon, 1387);
+
+ // shapeRef1388
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2010, 4062.51);
+ polygon.ps[1] = Point(2010, 4124.51);
+ polygon.ps[2] = Point(1948, 4124.51);
+ polygon.ps[3] = Point(1948, 4062.51);
+ new ShapeRef(router, polygon, 1388);
+
+ // shapeRef1389
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1614, 4062.51);
+ polygon.ps[1] = Point(1614, 4124.51);
+ polygon.ps[2] = Point(1552, 4124.51);
+ polygon.ps[3] = Point(1552, 4062.51);
+ new ShapeRef(router, polygon, 1389);
+
+ // shapeRef1390
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2439, 4511.4);
+ polygon.ps[1] = Point(2439, 4573.4);
+ polygon.ps[2] = Point(2377, 4573.4);
+ polygon.ps[3] = Point(2377, 4511.4);
+ new ShapeRef(router, polygon, 1390);
+
+ // shapeRef1391
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2802, 4511.4);
+ polygon.ps[1] = Point(2802, 4573.4);
+ polygon.ps[2] = Point(2740, 4573.4);
+ polygon.ps[3] = Point(2740, 4511.4);
+ new ShapeRef(router, polygon, 1391);
+
+ // shapeRef1392
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3297, 4511.4);
+ polygon.ps[1] = Point(3297, 4573.4);
+ polygon.ps[2] = Point(3235, 4573.4);
+ polygon.ps[3] = Point(3235, 4511.4);
+ new ShapeRef(router, polygon, 1392);
+
+ // shapeRef1393
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3759, 4511.4);
+ polygon.ps[1] = Point(3759, 4573.4);
+ polygon.ps[2] = Point(3697, 4573.4);
+ polygon.ps[3] = Point(3697, 4511.4);
+ new ShapeRef(router, polygon, 1393);
+
+ // shapeRef1394
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4089, 4511.4);
+ polygon.ps[1] = Point(4089, 4573.4);
+ polygon.ps[2] = Point(4027, 4573.4);
+ polygon.ps[3] = Point(4027, 4511.4);
+ new ShapeRef(router, polygon, 1394);
+
+ // shapeRef1395
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2802, 4062.51);
+ polygon.ps[1] = Point(2802, 4124.51);
+ polygon.ps[2] = Point(2740, 4124.51);
+ polygon.ps[3] = Point(2740, 4062.51);
+ new ShapeRef(router, polygon, 1395);
+
+ // shapeRef1396
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1185, 4062.51);
+ polygon.ps[1] = Point(1185, 4124.51);
+ polygon.ps[2] = Point(1123, 4124.51);
+ polygon.ps[3] = Point(1123, 4062.51);
+ new ShapeRef(router, polygon, 1396);
+
+ // shapeRef1397
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1614, 4511.4);
+ polygon.ps[1] = Point(1614, 4573.4);
+ polygon.ps[2] = Point(1552, 4573.4);
+ polygon.ps[3] = Point(1552, 4511.4);
+ new ShapeRef(router, polygon, 1397);
+
+ // shapeRef1398
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2010, 4511.4);
+ polygon.ps[1] = Point(2010, 4573.4);
+ polygon.ps[2] = Point(1948, 4573.4);
+ polygon.ps[3] = Point(1948, 4511.4);
+ new ShapeRef(router, polygon, 1398);
+
+ // shapeRef1399
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1185, 4511.4);
+ polygon.ps[1] = Point(1185, 4573.4);
+ polygon.ps[2] = Point(1123, 4573.4);
+ polygon.ps[3] = Point(1123, 4511.4);
+ new ShapeRef(router, polygon, 1399);
+
+ // shapeRef1400
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(822, 4511.4);
+ polygon.ps[1] = Point(822, 4573.4);
+ polygon.ps[2] = Point(760, 4573.4);
+ polygon.ps[3] = Point(760, 4511.4);
+ new ShapeRef(router, polygon, 1400);
+
+ // shapeRef1401
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 17697.9);
+ polygon.ps[1] = Point(9289.03, 17737.9);
+ polygon.ps[2] = Point(9234.03, 17737.9);
+ polygon.ps[3] = Point(9234.03, 17697.9);
+ new ShapeRef(router, polygon, 1401);
+
+ // shapeRef1402
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 17697.9);
+ polygon.ps[1] = Point(9389.03, 17737.9);
+ polygon.ps[2] = Point(9334.03, 17737.9);
+ polygon.ps[3] = Point(9334.03, 17697.9);
+ new ShapeRef(router, polygon, 1402);
+
+ // shapeRef1403
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 17797.9);
+ polygon.ps[1] = Point(8389.03, 17837.9);
+ polygon.ps[2] = Point(8334.03, 17837.9);
+ polygon.ps[3] = Point(8334.03, 17797.9);
+ new ShapeRef(router, polygon, 1403);
+
+ // shapeRef1404
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 17797.9);
+ polygon.ps[1] = Point(8489.03, 17837.9);
+ polygon.ps[2] = Point(8434.03, 17837.9);
+ polygon.ps[3] = Point(8434.03, 17797.9);
+ new ShapeRef(router, polygon, 1404);
+
+ // shapeRef1405
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 17797.9);
+ polygon.ps[1] = Point(8589.03, 17837.9);
+ polygon.ps[2] = Point(8534.03, 17837.9);
+ polygon.ps[3] = Point(8534.03, 17797.9);
+ new ShapeRef(router, polygon, 1405);
+
+ // shapeRef1406
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 17797.9);
+ polygon.ps[1] = Point(8689.03, 17837.9);
+ polygon.ps[2] = Point(8634.03, 17837.9);
+ polygon.ps[3] = Point(8634.03, 17797.9);
+ new ShapeRef(router, polygon, 1406);
+
+ // shapeRef1407
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 17797.9);
+ polygon.ps[1] = Point(8789.03, 17837.9);
+ polygon.ps[2] = Point(8734.03, 17837.9);
+ polygon.ps[3] = Point(8734.03, 17797.9);
+ new ShapeRef(router, polygon, 1407);
+
+ // shapeRef1408
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 17797.9);
+ polygon.ps[1] = Point(8889.03, 17837.9);
+ polygon.ps[2] = Point(8834.03, 17837.9);
+ polygon.ps[3] = Point(8834.03, 17797.9);
+ new ShapeRef(router, polygon, 1408);
+
+ // shapeRef1409
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 17797.9);
+ polygon.ps[1] = Point(8989.03, 17837.9);
+ polygon.ps[2] = Point(8934.03, 17837.9);
+ polygon.ps[3] = Point(8934.03, 17797.9);
+ new ShapeRef(router, polygon, 1409);
+
+ // shapeRef1410
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 17797.9);
+ polygon.ps[1] = Point(9089.03, 17837.9);
+ polygon.ps[2] = Point(9034.03, 17837.9);
+ polygon.ps[3] = Point(9034.03, 17797.9);
+ new ShapeRef(router, polygon, 1410);
+
+ // shapeRef1411
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 17797.9);
+ polygon.ps[1] = Point(9189.03, 17837.9);
+ polygon.ps[2] = Point(9134.03, 17837.9);
+ polygon.ps[3] = Point(9134.03, 17797.9);
+ new ShapeRef(router, polygon, 1411);
+
+ // shapeRef1412
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 17797.9);
+ polygon.ps[1] = Point(9289.03, 17837.9);
+ polygon.ps[2] = Point(9234.03, 17837.9);
+ polygon.ps[3] = Point(9234.03, 17797.9);
+ new ShapeRef(router, polygon, 1412);
+
+ // shapeRef1413
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 17797.9);
+ polygon.ps[1] = Point(9389.03, 17837.9);
+ polygon.ps[2] = Point(9334.03, 17837.9);
+ polygon.ps[3] = Point(9334.03, 17797.9);
+ new ShapeRef(router, polygon, 1413);
+
+ // shapeRef1414
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 17897.9);
+ polygon.ps[1] = Point(8389.03, 17937.9);
+ polygon.ps[2] = Point(8334.03, 17937.9);
+ polygon.ps[3] = Point(8334.03, 17897.9);
+ new ShapeRef(router, polygon, 1414);
+
+ // shapeRef1415
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 17897.9);
+ polygon.ps[1] = Point(8489.03, 17937.9);
+ polygon.ps[2] = Point(8434.03, 17937.9);
+ polygon.ps[3] = Point(8434.03, 17897.9);
+ new ShapeRef(router, polygon, 1415);
+
+ // shapeRef1416
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 17897.9);
+ polygon.ps[1] = Point(8589.03, 17937.9);
+ polygon.ps[2] = Point(8534.03, 17937.9);
+ polygon.ps[3] = Point(8534.03, 17897.9);
+ new ShapeRef(router, polygon, 1416);
+
+ // shapeRef1417
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 17897.9);
+ polygon.ps[1] = Point(8689.03, 17937.9);
+ polygon.ps[2] = Point(8634.03, 17937.9);
+ polygon.ps[3] = Point(8634.03, 17897.9);
+ new ShapeRef(router, polygon, 1417);
+
+ // shapeRef1418
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 17897.9);
+ polygon.ps[1] = Point(8789.03, 17937.9);
+ polygon.ps[2] = Point(8734.03, 17937.9);
+ polygon.ps[3] = Point(8734.03, 17897.9);
+ new ShapeRef(router, polygon, 1418);
+
+ // shapeRef1419
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 17897.9);
+ polygon.ps[1] = Point(8889.03, 17937.9);
+ polygon.ps[2] = Point(8834.03, 17937.9);
+ polygon.ps[3] = Point(8834.03, 17897.9);
+ new ShapeRef(router, polygon, 1419);
+
+ // shapeRef1420
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 17897.9);
+ polygon.ps[1] = Point(8989.03, 17937.9);
+ polygon.ps[2] = Point(8934.03, 17937.9);
+ polygon.ps[3] = Point(8934.03, 17897.9);
+ new ShapeRef(router, polygon, 1420);
+
+ // shapeRef1421
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 17897.9);
+ polygon.ps[1] = Point(9089.03, 17937.9);
+ polygon.ps[2] = Point(9034.03, 17937.9);
+ polygon.ps[3] = Point(9034.03, 17897.9);
+ new ShapeRef(router, polygon, 1421);
+
+ // shapeRef1422
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 17897.9);
+ polygon.ps[1] = Point(9189.03, 17937.9);
+ polygon.ps[2] = Point(9134.03, 17937.9);
+ polygon.ps[3] = Point(9134.03, 17897.9);
+ new ShapeRef(router, polygon, 1422);
+
+ // shapeRef1423
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 17897.9);
+ polygon.ps[1] = Point(9289.03, 17937.9);
+ polygon.ps[2] = Point(9234.03, 17937.9);
+ polygon.ps[3] = Point(9234.03, 17897.9);
+ new ShapeRef(router, polygon, 1423);
+
+ // shapeRef1424
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9389.03, 17897.9);
+ polygon.ps[1] = Point(9389.03, 17937.9);
+ polygon.ps[2] = Point(9334.03, 17937.9);
+ polygon.ps[3] = Point(9334.03, 17897.9);
+ new ShapeRef(router, polygon, 1424);
+
+ // shapeRef1425
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8389.03, 17997.9);
+ polygon.ps[1] = Point(8389.03, 18037.9);
+ polygon.ps[2] = Point(8334.03, 18037.9);
+ polygon.ps[3] = Point(8334.03, 17997.9);
+ new ShapeRef(router, polygon, 1425);
+
+ // shapeRef1426
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.03, 17997.9);
+ polygon.ps[1] = Point(8489.03, 18037.9);
+ polygon.ps[2] = Point(8434.03, 18037.9);
+ polygon.ps[3] = Point(8434.03, 17997.9);
+ new ShapeRef(router, polygon, 1426);
+
+ // shapeRef1427
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8589.03, 17997.9);
+ polygon.ps[1] = Point(8589.03, 18037.9);
+ polygon.ps[2] = Point(8534.03, 18037.9);
+ polygon.ps[3] = Point(8534.03, 17997.9);
+ new ShapeRef(router, polygon, 1427);
+
+ // shapeRef1428
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8689.03, 17997.9);
+ polygon.ps[1] = Point(8689.03, 18037.9);
+ polygon.ps[2] = Point(8634.03, 18037.9);
+ polygon.ps[3] = Point(8634.03, 17997.9);
+ new ShapeRef(router, polygon, 1428);
+
+ // shapeRef1429
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8789.03, 17997.9);
+ polygon.ps[1] = Point(8789.03, 18037.9);
+ polygon.ps[2] = Point(8734.03, 18037.9);
+ polygon.ps[3] = Point(8734.03, 17997.9);
+ new ShapeRef(router, polygon, 1429);
+
+ // shapeRef1430
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8889.03, 17997.9);
+ polygon.ps[1] = Point(8889.03, 18037.9);
+ polygon.ps[2] = Point(8834.03, 18037.9);
+ polygon.ps[3] = Point(8834.03, 17997.9);
+ new ShapeRef(router, polygon, 1430);
+
+ // shapeRef1431
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.03, 17997.9);
+ polygon.ps[1] = Point(8989.03, 18037.9);
+ polygon.ps[2] = Point(8934.03, 18037.9);
+ polygon.ps[3] = Point(8934.03, 17997.9);
+ new ShapeRef(router, polygon, 1431);
+
+ // shapeRef1432
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9089.03, 17997.9);
+ polygon.ps[1] = Point(9089.03, 18037.9);
+ polygon.ps[2] = Point(9034.03, 18037.9);
+ polygon.ps[3] = Point(9034.03, 17997.9);
+ new ShapeRef(router, polygon, 1432);
+
+ // shapeRef1433
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9189.03, 17997.9);
+ polygon.ps[1] = Point(9189.03, 18037.9);
+ polygon.ps[2] = Point(9134.03, 18037.9);
+ polygon.ps[3] = Point(9134.03, 17997.9);
+ new ShapeRef(router, polygon, 1433);
+
+ // shapeRef1434
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9289.03, 17997.9);
+ polygon.ps[1] = Point(9289.03, 18037.9);
+ polygon.ps[2] = Point(9234.03, 18037.9);
+ polygon.ps[3] = Point(9234.03, 17997.9);
+ new ShapeRef(router, polygon, 1434);
+
+ // shapeRef1435
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4976.5, 5752.9);
+ polygon.ps[1] = Point(4976.5, 5812.9);
+ polygon.ps[2] = Point(4921.5, 5812.9);
+ polygon.ps[3] = Point(4921.5, 5752.9);
+ new ShapeRef(router, polygon, 1435);
+
+ // shapeRef1436
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5034.5, 6131.51);
+ polygon.ps[1] = Point(5034.5, 6171.51);
+ polygon.ps[2] = Point(4959, 6171.51);
+ polygon.ps[3] = Point(4959, 6131.51);
+ new ShapeRef(router, polygon, 1436);
+
+ // shapeRef1437
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7693.6, 2970.79);
+ polygon.ps[1] = Point(7693.6, 3010.79);
+ polygon.ps[2] = Point(7618.1, 3010.79);
+ polygon.ps[3] = Point(7618.1, 2970.79);
+ new ShapeRef(router, polygon, 1437);
+
+ // shapeRef1438
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10035.2, 9973.52);
+ polygon.ps[1] = Point(10035.2, 10013.5);
+ polygon.ps[2] = Point(9959.69, 10013.5);
+ polygon.ps[3] = Point(9959.69, 9973.52);
+ new ShapeRef(router, polygon, 1438);
+
+ // shapeRef1439
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16094.1, 11724.9);
+ polygon.ps[1] = Point(16094.1, 11784.9);
+ polygon.ps[2] = Point(16039.1, 11784.9);
+ polygon.ps[3] = Point(16039.1, 11724.9);
+ new ShapeRef(router, polygon, 1439);
+
+ // shapeRef1440
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8386.79, 1210.29);
+ polygon.ps[1] = Point(8386.79, 1270.29);
+ polygon.ps[2] = Point(8331.79, 1270.29);
+ polygon.ps[3] = Point(8331.79, 1210.29);
+ new ShapeRef(router, polygon, 1440);
+
+ // shapeRef1441
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9364.09, 5522.67);
+ polygon.ps[1] = Point(9364.09, 5582.67);
+ polygon.ps[2] = Point(9309.09, 5582.67);
+ polygon.ps[3] = Point(9309.09, 5522.67);
+ new ShapeRef(router, polygon, 1441);
+
+ // shapeRef1442
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5746.6, 4555.4);
+ polygon.ps[1] = Point(5746.6, 4595.4);
+ polygon.ps[2] = Point(5671.1, 4595.4);
+ polygon.ps[3] = Point(5671.1, 4555.4);
+ new ShapeRef(router, polygon, 1442);
+
+ // shapeRef1443
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13598, 6659.51);
+ polygon.ps[1] = Point(13598, 6699.51);
+ polygon.ps[2] = Point(13522.5, 6699.51);
+ polygon.ps[3] = Point(13522.5, 6659.51);
+ new ShapeRef(router, polygon, 1443);
+
+ // shapeRef1444
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11448.6, 2229.29);
+ polygon.ps[1] = Point(11448.6, 2269.29);
+ polygon.ps[2] = Point(11373.1, 2269.29);
+ polygon.ps[3] = Point(11373.1, 2229.29);
+ new ShapeRef(router, polygon, 1444);
+
+ // shapeRef1445
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11448.6, 3318.29);
+ polygon.ps[1] = Point(11448.6, 3358.29);
+ polygon.ps[2] = Point(11373.1, 3358.29);
+ polygon.ps[3] = Point(11373.1, 3318.29);
+ new ShapeRef(router, polygon, 1445);
+
+ // shapeRef1446
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11448.6, 4456.4);
+ polygon.ps[1] = Point(11448.6, 4496.4);
+ polygon.ps[2] = Point(11373.1, 4496.4);
+ polygon.ps[3] = Point(11373.1, 4456.4);
+ new ShapeRef(router, polygon, 1446);
+
+ // shapeRef1447
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11448.6, 5360.67);
+ polygon.ps[1] = Point(11448.6, 5400.67);
+ polygon.ps[2] = Point(11373.1, 5400.67);
+ polygon.ps[3] = Point(11373.1, 5360.67);
+ new ShapeRef(router, polygon, 1447);
+
+ // shapeRef1448
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11448.6, 6560.51);
+ polygon.ps[1] = Point(11448.6, 6600.51);
+ polygon.ps[2] = Point(11373.1, 6600.51);
+ polygon.ps[3] = Point(11373.1, 6560.51);
+ new ShapeRef(router, polygon, 1448);
+
+ // shapeRef1449
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11448.6, 8394.99);
+ polygon.ps[1] = Point(11448.6, 8434.99);
+ polygon.ps[2] = Point(11373.1, 8434.99);
+ polygon.ps[3] = Point(11373.1, 8394.99);
+ new ShapeRef(router, polygon, 1449);
+
+ // shapeRef1450
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11448.6, 11158.6);
+ polygon.ps[1] = Point(11448.6, 11198.6);
+ polygon.ps[2] = Point(11373.1, 11198.6);
+ polygon.ps[3] = Point(11373.1, 11158.6);
+ new ShapeRef(router, polygon, 1450);
+
+ // shapeRef1451
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11448.6, 9956.02);
+ polygon.ps[1] = Point(11448.6, 9996.02);
+ polygon.ps[2] = Point(11373.1, 9996.02);
+ polygon.ps[3] = Point(11373.1, 9956.02);
+ new ShapeRef(router, polygon, 1451);
+
+ // shapeRef1452
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11951.6, 12057.3);
+ polygon.ps[1] = Point(11951.6, 12117.3);
+ polygon.ps[2] = Point(11896.6, 12117.3);
+ polygon.ps[3] = Point(11896.6, 12057.3);
+ new ShapeRef(router, polygon, 1452);
+
+ // shapeRef1453
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12950, 12057.3);
+ polygon.ps[1] = Point(12950, 12117.3);
+ polygon.ps[2] = Point(12895, 12117.3);
+ polygon.ps[3] = Point(12895, 12057.3);
+ new ShapeRef(router, polygon, 1453);
+
+ // shapeRef1454
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7982.79, 4440.9);
+ polygon.ps[1] = Point(7982.79, 4480.9);
+ polygon.ps[2] = Point(7907.29, 4480.9);
+ polygon.ps[3] = Point(7907.29, 4440.9);
+ new ShapeRef(router, polygon, 1454);
+
+ // shapeRef1455
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1610.5, 4703.4);
+ polygon.ps[1] = Point(1610.5, 4763.4);
+ polygon.ps[2] = Point(1555.5, 4763.4);
+ polygon.ps[3] = Point(1555.5, 4703.4);
+ new ShapeRef(router, polygon, 1455);
+
+ // shapeRef1456
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3062.5, 4703.4);
+ polygon.ps[1] = Point(3062.5, 4763.4);
+ polygon.ps[2] = Point(3007.5, 4763.4);
+ polygon.ps[3] = Point(3007.5, 4703.4);
+ new ShapeRef(router, polygon, 1456);
+
+ // shapeRef1457
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15793.4, 10711.3);
+ polygon.ps[1] = Point(15793.4, 10771.3);
+ polygon.ps[2] = Point(15738.4, 10771.3);
+ polygon.ps[3] = Point(15738.4, 10711.3);
+ new ShapeRef(router, polygon, 1457);
+
+ // shapeRef1458
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14229.5, 12222.3);
+ polygon.ps[1] = Point(14229.5, 12282.3);
+ polygon.ps[2] = Point(14174.5, 12282.3);
+ polygon.ps[3] = Point(14174.5, 12222.3);
+ new ShapeRef(router, polygon, 1458);
+
+ // shapeRef1459
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16119.1, 11642.9);
+ polygon.ps[1] = Point(16119.1, 11702.9);
+ polygon.ps[2] = Point(16064.1, 11702.9);
+ polygon.ps[3] = Point(16064.1, 11642.9);
+ new ShapeRef(router, polygon, 1459);
+
+ // shapeRef1460
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15233.8, 10877.1);
+ polygon.ps[1] = Point(15233.8, 10917.1);
+ polygon.ps[2] = Point(15158.3, 10917.1);
+ polygon.ps[3] = Point(15158.3, 10877.1);
+ new ShapeRef(router, polygon, 1460);
+
+ // shapeRef1461
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10509.4, 6395.51);
+ polygon.ps[1] = Point(10509.4, 6435.51);
+ polygon.ps[2] = Point(10433.9, 6435.51);
+ polygon.ps[3] = Point(10433.9, 6395.51);
+ new ShapeRef(router, polygon, 1461);
+
+ // shapeRef1462
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10385.4, 10711.3);
+ polygon.ps[1] = Point(10385.4, 10771.3);
+ polygon.ps[2] = Point(10330.4, 10771.3);
+ polygon.ps[3] = Point(10330.4, 10711.3);
+ new ShapeRef(router, polygon, 1462);
+
+ // shapeRef1463
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9944.19, 11562.9);
+ polygon.ps[1] = Point(9944.19, 11622.9);
+ polygon.ps[2] = Point(9889.19, 11622.9);
+ polygon.ps[3] = Point(9889.19, 11562.9);
+ new ShapeRef(router, polygon, 1463);
+
+ // shapeRef1464
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9356.09, 5637.9);
+ polygon.ps[1] = Point(9356.09, 5677.9);
+ polygon.ps[2] = Point(9280.59, 5677.9);
+ polygon.ps[3] = Point(9280.59, 5637.9);
+ new ShapeRef(router, polygon, 1464);
+
+ // shapeRef1465
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9587.09, 7356.9);
+ polygon.ps[1] = Point(9587.09, 7396.9);
+ polygon.ps[2] = Point(9511.59, 7396.9);
+ polygon.ps[3] = Point(9511.59, 7356.9);
+ new ShapeRef(router, polygon, 1465);
+
+ // shapeRef1466
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9587.09, 10352);
+ polygon.ps[1] = Point(9587.09, 10392);
+ polygon.ps[2] = Point(9511.59, 10392);
+ polygon.ps[3] = Point(9511.59, 10352);
+ new ShapeRef(router, polygon, 1466);
+
+ // shapeRef1467
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11712.6, 10711.3);
+ polygon.ps[1] = Point(11712.6, 10771.3);
+ polygon.ps[2] = Point(11657.6, 10771.3);
+ polygon.ps[3] = Point(11657.6, 10711.3);
+ new ShapeRef(router, polygon, 1467);
+
+ // shapeRef1468
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13128.5, 10711.3);
+ polygon.ps[1] = Point(13128.5, 10771.3);
+ polygon.ps[2] = Point(13073.5, 10771.3);
+ polygon.ps[3] = Point(13073.5, 10711.3);
+ new ShapeRef(router, polygon, 1468);
+
+ // shapeRef1469
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11481.6, 11562.9);
+ polygon.ps[1] = Point(11481.6, 11622.9);
+ polygon.ps[2] = Point(11426.6, 11622.9);
+ polygon.ps[3] = Point(11426.6, 11562.9);
+ new ShapeRef(router, polygon, 1469);
+
+ // shapeRef1470
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12785, 11562.9);
+ polygon.ps[1] = Point(12785, 11622.9);
+ polygon.ps[2] = Point(12730, 11622.9);
+ polygon.ps[3] = Point(12730, 11562.9);
+ new ShapeRef(router, polygon, 1470);
+
+ // shapeRef1471
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14328.5, 10711.3);
+ polygon.ps[1] = Point(14328.5, 10771.3);
+ polygon.ps[2] = Point(14273.5, 10771.3);
+ polygon.ps[3] = Point(14273.5, 10711.3);
+ new ShapeRef(router, polygon, 1471);
+
+ // shapeRef1472
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14559.5, 11562.9);
+ polygon.ps[1] = Point(14559.5, 11622.9);
+ polygon.ps[2] = Point(14504.5, 11622.9);
+ polygon.ps[3] = Point(14504.5, 11562.9);
+ new ShapeRef(router, polygon, 1472);
+
+ // shapeRef1473
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15954.1, 12173.3);
+ polygon.ps[1] = Point(15954.1, 12213.3);
+ polygon.ps[2] = Point(15878.6, 12213.3);
+ polygon.ps[3] = Point(15878.6, 12173.3);
+ new ShapeRef(router, polygon, 1473);
+
+ // shapeRef1474
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15631.8, 12222.3);
+ polygon.ps[1] = Point(15631.8, 12282.3);
+ polygon.ps[2] = Point(15576.8, 12282.3);
+ polygon.ps[3] = Point(15576.8, 12222.3);
+ new ShapeRef(router, polygon, 1474);
+
+ // shapeRef1475
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9138.49, 8308.99);
+ polygon.ps[1] = Point(9138.49, 8348.99);
+ polygon.ps[2] = Point(9062.99, 8348.99);
+ polygon.ps[3] = Point(9062.99, 8308.99);
+ new ShapeRef(router, polygon, 1475);
+
+ // shapeRef1476
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18322, 8544.49);
+ polygon.ps[1] = Point(18322, 8584.49);
+ polygon.ps[2] = Point(18246.5, 8584.49);
+ polygon.ps[3] = Point(18246.5, 8544.49);
+ new ShapeRef(router, polygon, 1476);
+
+ // shapeRef1477
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17637, 10104);
+ polygon.ps[1] = Point(17637, 10164);
+ polygon.ps[2] = Point(17582, 10164);
+ polygon.ps[3] = Point(17582, 10104);
+ new ShapeRef(router, polygon, 1477);
+
+ // shapeRef1478
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16585.3, 10104);
+ polygon.ps[1] = Point(16585.3, 10164);
+ polygon.ps[2] = Point(16530.3, 10164);
+ polygon.ps[3] = Point(16530.3, 10104);
+ new ShapeRef(router, polygon, 1478);
+
+ // shapeRef1479
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13965.5, 10184);
+ polygon.ps[1] = Point(13965.5, 10244);
+ polygon.ps[2] = Point(13910.5, 10244);
+ polygon.ps[3] = Point(13910.5, 10184);
+ new ShapeRef(router, polygon, 1479);
+
+ // shapeRef1480
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10410.4, 9688.42);
+ polygon.ps[1] = Point(10410.4, 9728.42);
+ polygon.ps[2] = Point(10334.9, 9728.42);
+ polygon.ps[3] = Point(10334.9, 9688.42);
+ new ShapeRef(router, polygon, 1480);
+
+ // shapeRef1481
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14625.5, 6718.21);
+ polygon.ps[1] = Point(14625.5, 6778.21);
+ polygon.ps[2] = Point(14570.5, 6778.21);
+ polygon.ps[3] = Point(14570.5, 6718.21);
+ new ShapeRef(router, polygon, 1481);
+
+ // shapeRef1482
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11580.6, 7724.79);
+ polygon.ps[1] = Point(11580.6, 7764.79);
+ polygon.ps[2] = Point(11505.1, 7764.79);
+ polygon.ps[3] = Point(11505.1, 7724.79);
+ new ShapeRef(router, polygon, 1482);
+
+ // shapeRef1483
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12050.6, 7355.4);
+ polygon.ps[1] = Point(12050.6, 7415.4);
+ polygon.ps[2] = Point(11995.6, 7415.4);
+ polygon.ps[3] = Point(11995.6, 7355.4);
+ new ShapeRef(router, polygon, 1483);
+
+ // shapeRef1484
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17138.3, 7191.9);
+ polygon.ps[1] = Point(17138.3, 7231.9);
+ polygon.ps[2] = Point(17062.8, 7231.9);
+ polygon.ps[3] = Point(17062.8, 7191.9);
+ new ShapeRef(router, polygon, 1484);
+
+ // shapeRef1485
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5034.5, 6036.29);
+ polygon.ps[1] = Point(5034.5, 6076.29);
+ polygon.ps[2] = Point(4959, 6076.29);
+ polygon.ps[3] = Point(4959, 6036.29);
+ new ShapeRef(router, polygon, 1485);
+
+ // shapeRef1486
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4976.5, 5894.59);
+ polygon.ps[1] = Point(4976.5, 5954.59);
+ polygon.ps[2] = Point(4921.5, 5954.59);
+ polygon.ps[3] = Point(4921.5, 5894.59);
+ new ShapeRef(router, polygon, 1486);
+
+ // shapeRef1487
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5523.6, 5277.67);
+ polygon.ps[1] = Point(5523.6, 5337.67);
+ polygon.ps[2] = Point(5468.6, 5337.67);
+ polygon.ps[3] = Point(5468.6, 5277.67);
+ new ShapeRef(router, polygon, 1487);
+
+ // shapeRef1488
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9141.09, 6081.51);
+ polygon.ps[1] = Point(9141.09, 6141.51);
+ polygon.ps[2] = Point(9086.09, 6141.51);
+ polygon.ps[3] = Point(9086.09, 6081.51);
+ new ShapeRef(router, polygon, 1488);
+
+ // shapeRef1489
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9820.19, 7091.4);
+ polygon.ps[1] = Point(9820.19, 7151.4);
+ polygon.ps[2] = Point(9765.19, 7151.4);
+ polygon.ps[3] = Point(9765.19, 7091.4);
+ new ShapeRef(router, polygon, 1489);
+
+ // shapeRef1490
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10542.4, 7856.79);
+ polygon.ps[1] = Point(10542.4, 7896.79);
+ polygon.ps[2] = Point(10466.9, 7896.79);
+ polygon.ps[3] = Point(10466.9, 7856.79);
+ new ShapeRef(router, polygon, 1490);
+
+ // shapeRef1491
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7660.6, 9061.42);
+ polygon.ps[1] = Point(7660.6, 9101.42);
+ polygon.ps[2] = Point(7585.1, 9101.42);
+ polygon.ps[3] = Point(7585.1, 9061.42);
+ new ShapeRef(router, polygon, 1491);
+
+ // shapeRef1492
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15325, 1326.29);
+ polygon.ps[1] = Point(15325, 1366.29);
+ polygon.ps[2] = Point(15249.5, 1366.29);
+ polygon.ps[3] = Point(15249.5, 1326.29);
+ new ShapeRef(router, polygon, 1492);
+
+ // shapeRef1493
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9397.09, 9572.42);
+ polygon.ps[1] = Point(9397.09, 9632.42);
+ polygon.ps[2] = Point(9342.09, 9632.42);
+ polygon.ps[3] = Point(9342.09, 9572.42);
+ new ShapeRef(router, polygon, 1493);
+
+ // shapeRef1494
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7594.6, 7988.79);
+ polygon.ps[1] = Point(7594.6, 8028.79);
+ polygon.ps[2] = Point(7519.1, 8028.79);
+ polygon.ps[3] = Point(7519.1, 7988.79);
+ new ShapeRef(router, polygon, 1494);
+
+ // shapeRef1495
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10762.7, 8559.99);
+ polygon.ps[1] = Point(10762.7, 8599.99);
+ polygon.ps[2] = Point(10687.2, 8599.99);
+ polygon.ps[3] = Point(10687.2, 8559.99);
+ new ShapeRef(router, polygon, 1495);
+
+ // shapeRef1496
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10597.7, 9127.42);
+ polygon.ps[1] = Point(10597.7, 9167.42);
+ polygon.ps[2] = Point(10522.2, 9167.42);
+ polygon.ps[3] = Point(10522.2, 9127.42);
+ new ShapeRef(router, polygon, 1496);
+
+ // shapeRef1497
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9188.49, 8328.99);
+ polygon.ps[1] = Point(9188.49, 8368.99);
+ polygon.ps[2] = Point(9062.99, 8368.99);
+ polygon.ps[3] = Point(9062.99, 8328.99);
+ new ShapeRef(router, polygon, 1497);
+
+ // shapeRef1498
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8825.89, 4638.9);
+ polygon.ps[1] = Point(8825.89, 4678.9);
+ polygon.ps[2] = Point(8750.39, 4678.9);
+ polygon.ps[3] = Point(8750.39, 4638.9);
+ new ShapeRef(router, polygon, 1498);
+
+ // shapeRef1499
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8921.39, 3941.51);
+ polygon.ps[1] = Point(8921.39, 3981.51);
+ polygon.ps[2] = Point(8845.89, 3981.51);
+ polygon.ps[3] = Point(8845.89, 3941.51);
+ new ShapeRef(router, polygon, 1499);
+
+ // shapeRef1500
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8921.39, 3413.51);
+ polygon.ps[1] = Point(8921.39, 3453.51);
+ polygon.ps[2] = Point(8845.89, 3453.51);
+ polygon.ps[3] = Point(8845.89, 3413.51);
+ new ShapeRef(router, polygon, 1500);
+
+ // shapeRef1501
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8825.89, 2889.29);
+ polygon.ps[1] = Point(8825.89, 2929.29);
+ polygon.ps[2] = Point(8750.39, 2929.29);
+ polygon.ps[3] = Point(8750.39, 2889.29);
+ new ShapeRef(router, polygon, 1501);
+
+ // shapeRef1502
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8921.39, 2343.79);
+ polygon.ps[1] = Point(8921.39, 2383.79);
+ polygon.ps[2] = Point(8845.89, 2383.79);
+ polygon.ps[3] = Point(8845.89, 2343.79);
+ new ShapeRef(router, polygon, 1502);
+
+ // shapeRef1503
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8452.79, 2160.29);
+ polygon.ps[1] = Point(8452.79, 2220.29);
+ polygon.ps[2] = Point(8397.79, 2220.29);
+ polygon.ps[3] = Point(8397.79, 2160.29);
+ new ShapeRef(router, polygon, 1503);
+
+ // shapeRef1504
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15402, 1276.29);
+ polygon.ps[1] = Point(15402, 1336.29);
+ polygon.ps[2] = Point(15347, 1336.29);
+ polygon.ps[3] = Point(15347, 1276.29);
+ new ShapeRef(router, polygon, 1504);
+
+ // shapeRef1505
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8543.79, 1095.29);
+ polygon.ps[1] = Point(8543.79, 1135.29);
+ polygon.ps[2] = Point(8468.29, 1135.29);
+ polygon.ps[3] = Point(8468.29, 1095.29);
+ new ShapeRef(router, polygon, 1505);
+
+ // shapeRef1506
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8989.49, 738.091);
+ polygon.ps[1] = Point(8989.49, 798.091);
+ polygon.ps[2] = Point(8934.49, 798.091);
+ polygon.ps[3] = Point(8934.49, 738.091);
+ new ShapeRef(router, polygon, 1506);
+
+ // shapeRef1507
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9014.49, 1045.29);
+ polygon.ps[1] = Point(9014.49, 1105.29);
+ polygon.ps[2] = Point(8959.49, 1105.29);
+ polygon.ps[3] = Point(8959.49, 1045.29);
+ new ShapeRef(router, polygon, 1507);
+
+ // shapeRef1508
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15167.8, 1356.29);
+ polygon.ps[1] = Point(15167.8, 1416.29);
+ polygon.ps[2] = Point(15112.8, 1416.29);
+ polygon.ps[3] = Point(15112.8, 1356.29);
+ new ShapeRef(router, polygon, 1508);
+
+ // shapeRef1509
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15529.8, 1356.29);
+ polygon.ps[1] = Point(15529.8, 1416.29);
+ polygon.ps[2] = Point(15474.8, 1416.29);
+ polygon.ps[3] = Point(15474.8, 1356.29);
+ new ShapeRef(router, polygon, 1509);
+
+ // shapeRef1510
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8081.79, 963.285);
+ polygon.ps[1] = Point(8081.79, 1003.29);
+ polygon.ps[2] = Point(8006.29, 1003.29);
+ polygon.ps[3] = Point(8006.29, 963.285);
+ new ShapeRef(router, polygon, 1510);
+
+ // shapeRef1511
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9779.19, 738.091);
+ polygon.ps[1] = Point(9779.19, 798.091);
+ polygon.ps[2] = Point(9724.19, 798.091);
+ polygon.ps[3] = Point(9724.19, 738.091);
+ new ShapeRef(router, polygon, 1511);
+
+ // shapeRef1512
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10803.7, 738.091);
+ polygon.ps[1] = Point(10803.7, 798.091);
+ polygon.ps[2] = Point(10748.7, 798.091);
+ polygon.ps[3] = Point(10748.7, 738.091);
+ new ShapeRef(router, polygon, 1512);
+
+ // shapeRef1513
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11059.7, 1095.29);
+ polygon.ps[1] = Point(11059.7, 1135.29);
+ polygon.ps[2] = Point(10984.2, 1135.29);
+ polygon.ps[3] = Point(10984.2, 1095.29);
+ new ShapeRef(router, polygon, 1513);
+
+ // shapeRef1514
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10803.7, 1210.29);
+ polygon.ps[1] = Point(10803.7, 1270.29);
+ polygon.ps[2] = Point(10748.7, 1270.29);
+ polygon.ps[3] = Point(10748.7, 1210.29);
+ new ShapeRef(router, polygon, 1514);
+
+ // shapeRef1515
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9397.09, 1210.29);
+ polygon.ps[1] = Point(9397.09, 1270.29);
+ polygon.ps[2] = Point(9342.09, 1270.29);
+ polygon.ps[3] = Point(9342.09, 1210.29);
+ new ShapeRef(router, polygon, 1515);
+
+ // shapeRef1516
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9331.09, 1939.29);
+ polygon.ps[1] = Point(9331.09, 1999.29);
+ polygon.ps[2] = Point(9276.09, 1999.29);
+ polygon.ps[3] = Point(9276.09, 1939.29);
+ new ShapeRef(router, polygon, 1516);
+
+ // shapeRef1517
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6117.6, 144.265);
+ polygon.ps[1] = Point(6117.6, 204.265);
+ polygon.ps[2] = Point(6062.6, 204.265);
+ polygon.ps[3] = Point(6062.6, 144.265);
+ new ShapeRef(router, polygon, 1517);
+
+ // shapeRef1518
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9738.19, 1689.29);
+ polygon.ps[1] = Point(9738.19, 1729.29);
+ polygon.ps[2] = Point(9662.69, 1729.29);
+ polygon.ps[3] = Point(9662.69, 1689.29);
+ new ShapeRef(router, polygon, 1518);
+
+ // shapeRef1519
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11059.7, 1458.29);
+ polygon.ps[1] = Point(11059.7, 1498.29);
+ polygon.ps[2] = Point(10984.2, 1498.29);
+ polygon.ps[3] = Point(10984.2, 1458.29);
+ new ShapeRef(router, polygon, 1519);
+
+ // shapeRef1520
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11166.7, 1653.29);
+ polygon.ps[1] = Point(11166.7, 1713.29);
+ polygon.ps[2] = Point(11111.7, 1713.29);
+ polygon.ps[3] = Point(11111.7, 1653.29);
+ new ShapeRef(router, polygon, 1520);
+
+ // shapeRef1521
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10964.2, 590.091);
+ polygon.ps[1] = Point(10964.2, 630.091);
+ polygon.ps[2] = Point(10888.7, 630.091);
+ polygon.ps[3] = Point(10888.7, 590.091);
+ new ShapeRef(router, polygon, 1521);
+
+ // shapeRef1522
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10572.7, 4291.11);
+ polygon.ps[1] = Point(10572.7, 4351.11);
+ polygon.ps[2] = Point(10517.7, 4351.11);
+ polygon.ps[3] = Point(10517.7, 4291.11);
+ new ShapeRef(router, polygon, 1522);
+
+ // shapeRef1523
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10968.7, 4291.11);
+ polygon.ps[1] = Point(10968.7, 4351.11);
+ polygon.ps[2] = Point(10913.7, 4351.11);
+ polygon.ps[3] = Point(10913.7, 4291.11);
+ new ShapeRef(router, polygon, 1523);
+
+ // shapeRef1524
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11290.7, 4291.11);
+ polygon.ps[1] = Point(11290.7, 4351.11);
+ polygon.ps[2] = Point(11235.7, 4351.11);
+ polygon.ps[3] = Point(11235.7, 4291.11);
+ new ShapeRef(router, polygon, 1524);
+
+ // shapeRef1525
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11621.6, 4371.11);
+ polygon.ps[1] = Point(11621.6, 4431.11);
+ polygon.ps[2] = Point(11566.6, 4431.11);
+ polygon.ps[3] = Point(11566.6, 4371.11);
+ new ShapeRef(router, polygon, 1525);
+
+ // shapeRef1526
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10638.7, 4519.4);
+ polygon.ps[1] = Point(10638.7, 4579.4);
+ polygon.ps[2] = Point(10583.7, 4579.4);
+ polygon.ps[3] = Point(10583.7, 4519.4);
+ new ShapeRef(router, polygon, 1526);
+
+ // shapeRef1527
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12248.6, 4291.11);
+ polygon.ps[1] = Point(12248.6, 4351.11);
+ polygon.ps[2] = Point(12193.6, 4351.11);
+ polygon.ps[3] = Point(12193.6, 4291.11);
+ new ShapeRef(router, polygon, 1527);
+
+ // shapeRef1528
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12617, 4555.4);
+ polygon.ps[1] = Point(12617, 4595.4);
+ polygon.ps[2] = Point(12541.5, 4595.4);
+ polygon.ps[3] = Point(12541.5, 4555.4);
+ new ShapeRef(router, polygon, 1528);
+
+ // shapeRef1529
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12617, 4933.9);
+ polygon.ps[1] = Point(12617, 4973.9);
+ polygon.ps[2] = Point(12541.5, 4973.9);
+ polygon.ps[3] = Point(12541.5, 4933.9);
+ new ShapeRef(router, polygon, 1529);
+
+ // shapeRef1530
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12617, 5312.17);
+ polygon.ps[1] = Point(12617, 5352.17);
+ polygon.ps[2] = Point(12541.5, 5352.17);
+ polygon.ps[3] = Point(12541.5, 5312.17);
+ new ShapeRef(router, polygon, 1530);
+
+ // shapeRef1531
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13351.5, 3822.51);
+ polygon.ps[1] = Point(13351.5, 3862.51);
+ polygon.ps[2] = Point(13276, 3862.51);
+ polygon.ps[3] = Point(13276, 3822.51);
+ new ShapeRef(router, polygon, 1531);
+
+ // shapeRef1532
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12975, 4439.4);
+ polygon.ps[1] = Point(12975, 4499.4);
+ polygon.ps[2] = Point(12920, 4499.4);
+ polygon.ps[3] = Point(12920, 4439.4);
+ new ShapeRef(router, polygon, 1532);
+
+ // shapeRef1533
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12617, 3974.51);
+ polygon.ps[1] = Point(12617, 4014.51);
+ polygon.ps[2] = Point(12541.5, 4014.51);
+ polygon.ps[3] = Point(12541.5, 3974.51);
+ new ShapeRef(router, polygon, 1533);
+
+ // shapeRef1534
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12617, 3512.51);
+ polygon.ps[1] = Point(12617, 3552.51);
+ polygon.ps[2] = Point(12541.5, 3552.51);
+ polygon.ps[3] = Point(12541.5, 3512.51);
+ new ShapeRef(router, polygon, 1534);
+
+ // shapeRef1535
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12617, 3021.29);
+ polygon.ps[1] = Point(12617, 3061.29);
+ polygon.ps[2] = Point(12541.5, 3061.29);
+ polygon.ps[3] = Point(12541.5, 3021.29);
+ new ShapeRef(router, polygon, 1535);
+
+ // shapeRef1536
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12617, 2262.29);
+ polygon.ps[1] = Point(12617, 2302.29);
+ polygon.ps[2] = Point(12541.5, 2302.29);
+ polygon.ps[3] = Point(12541.5, 2262.29);
+ new ShapeRef(router, polygon, 1536);
+
+ // shapeRef1537
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12182.6, 1774.29);
+ polygon.ps[1] = Point(12182.6, 1834.29);
+ polygon.ps[2] = Point(12127.6, 1834.29);
+ polygon.ps[3] = Point(12127.6, 1774.29);
+ new ShapeRef(router, polygon, 1537);
+
+ // shapeRef1538
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12075.6, 1704.79);
+ polygon.ps[1] = Point(12075.6, 1744.79);
+ polygon.ps[2] = Point(12000.1, 1744.79);
+ polygon.ps[3] = Point(12000.1, 1704.79);
+ new ShapeRef(router, polygon, 1538);
+
+ // shapeRef1539
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12207.6, 1672.29);
+ polygon.ps[1] = Point(12207.6, 1732.29);
+ polygon.ps[2] = Point(12152.6, 1732.29);
+ polygon.ps[3] = Point(12152.6, 1672.29);
+ new ShapeRef(router, polygon, 1539);
+
+ // shapeRef1540
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13957.5, 8445.49);
+ polygon.ps[1] = Point(13957.5, 8485.49);
+ polygon.ps[2] = Point(13882, 8485.49);
+ polygon.ps[3] = Point(13882, 8445.49);
+ new ShapeRef(router, polygon, 1540);
+
+ // shapeRef1541
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15954.1, 8445.49);
+ polygon.ps[1] = Point(15954.1, 8485.49);
+ polygon.ps[2] = Point(15878.6, 8485.49);
+ polygon.ps[3] = Point(15878.6, 8445.49);
+ new ShapeRef(router, polygon, 1541);
+
+ // shapeRef1542
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16808.3, 8377.49);
+ polygon.ps[1] = Point(16808.3, 8417.49);
+ polygon.ps[2] = Point(16732.8, 8417.49);
+ polygon.ps[3] = Point(16732.8, 8377.49);
+ new ShapeRef(router, polygon, 1542);
+
+ // shapeRef1543
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12009.6, 7823.79);
+ polygon.ps[1] = Point(12009.6, 7863.79);
+ polygon.ps[2] = Point(11934.1, 7863.79);
+ polygon.ps[3] = Point(11934.1, 7823.79);
+ new ShapeRef(router, polygon, 1543);
+
+ // shapeRef1544
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18588.5, 11790.9);
+ polygon.ps[1] = Point(18588.5, 11850.9);
+ polygon.ps[2] = Point(18533.5, 11850.9);
+ polygon.ps[3] = Point(18533.5, 11790.9);
+ new ShapeRef(router, polygon, 1544);
+
+ // shapeRef1545
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8653.79, 4122.51);
+ polygon.ps[1] = Point(8653.79, 4182.51);
+ polygon.ps[2] = Point(8598.79, 4182.51);
+ polygon.ps[3] = Point(8598.79, 4122.51);
+ new ShapeRef(router, polygon, 1545);
+
+ // shapeRef1546
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10201.5, 9688.42);
+ polygon.ps[1] = Point(10201.5, 9728.42);
+ polygon.ps[2] = Point(10126, 9728.42);
+ polygon.ps[3] = Point(10126, 9688.42);
+ new ShapeRef(router, polygon, 1546);
+
+ // shapeRef1547
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15402, 1111.29);
+ polygon.ps[1] = Point(15402, 1171.29);
+ polygon.ps[2] = Point(15347, 1171.29);
+ polygon.ps[3] = Point(15347, 1111.29);
+ new ShapeRef(router, polygon, 1547);
+
+ // shapeRef1548
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10799.2, 7306.4);
+ polygon.ps[1] = Point(10799.2, 7346.4);
+ polygon.ps[2] = Point(10723.7, 7346.4);
+ polygon.ps[3] = Point(10723.7, 7306.4);
+ new ShapeRef(router, polygon, 1548);
+
+ // shapeRef1549
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10894.7, 7790.79);
+ polygon.ps[1] = Point(10894.7, 7830.79);
+ polygon.ps[2] = Point(10819.2, 7830.79);
+ polygon.ps[3] = Point(10819.2, 7790.79);
+ new ShapeRef(router, polygon, 1549);
+
+ // shapeRef1550
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9936.19, 6395.51);
+ polygon.ps[1] = Point(9936.19, 6435.51);
+ polygon.ps[2] = Point(9860.69, 6435.51);
+ polygon.ps[3] = Point(9860.69, 6395.51);
+ new ShapeRef(router, polygon, 1550);
+
+ // shapeRef1551
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11265.7, 8803.22);
+ polygon.ps[1] = Point(11265.7, 8863.22);
+ polygon.ps[2] = Point(11210.7, 8863.22);
+ polygon.ps[3] = Point(11210.7, 8803.22);
+ new ShapeRef(router, polygon, 1551);
+
+ // shapeRef1552
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12347.6, 8803.22);
+ polygon.ps[1] = Point(12347.6, 8863.22);
+ polygon.ps[2] = Point(12292.6, 8863.22);
+ polygon.ps[3] = Point(12292.6, 8803.22);
+ new ShapeRef(router, polygon, 1552);
+
+ // shapeRef1553
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13293.5, 8803.22);
+ polygon.ps[1] = Point(13293.5, 8863.22);
+ polygon.ps[2] = Point(13238.5, 8863.22);
+ polygon.ps[3] = Point(13238.5, 8803.22);
+ new ShapeRef(router, polygon, 1553);
+
+ // shapeRef1554
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9047.49, 3363.51);
+ polygon.ps[1] = Point(9047.49, 3423.51);
+ polygon.ps[2] = Point(8992.49, 3423.51);
+ polygon.ps[3] = Point(8992.49, 3363.51);
+ new ShapeRef(router, polygon, 1554);
+
+ // shapeRef1555
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7503.6, 3495.51);
+ polygon.ps[1] = Point(7503.6, 3555.51);
+ polygon.ps[2] = Point(7448.6, 3555.51);
+ polygon.ps[3] = Point(7448.6, 3495.51);
+ new ShapeRef(router, polygon, 1555);
+
+ // shapeRef1556
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6810.6, 3495.51);
+ polygon.ps[1] = Point(6810.6, 3555.51);
+ polygon.ps[2] = Point(6755.6, 3555.51);
+ polygon.ps[3] = Point(6755.6, 3495.51);
+ new ShapeRef(router, polygon, 1556);
+
+ // shapeRef1557
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6216.6, 3575.51);
+ polygon.ps[1] = Point(6216.6, 3635.51);
+ polygon.ps[2] = Point(6161.6, 3635.51);
+ polygon.ps[3] = Point(6161.6, 3575.51);
+ new ShapeRef(router, polygon, 1557);
+
+ // shapeRef1558
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5721.6, 3495.51);
+ polygon.ps[1] = Point(5721.6, 3555.51);
+ polygon.ps[2] = Point(5666.6, 3555.51);
+ polygon.ps[3] = Point(5666.6, 3495.51);
+ new ShapeRef(router, polygon, 1558);
+
+ // shapeRef1559
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5397.5, 3809.51);
+ polygon.ps[1] = Point(5397.5, 3849.51);
+ polygon.ps[2] = Point(5322, 3849.51);
+ polygon.ps[3] = Point(5322, 3809.51);
+ new ShapeRef(router, polygon, 1559);
+
+ // shapeRef1560
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5397.5, 5327.67);
+ polygon.ps[1] = Point(5397.5, 5367.67);
+ polygon.ps[2] = Point(5322, 5367.67);
+ polygon.ps[3] = Point(5322, 5327.67);
+ new ShapeRef(router, polygon, 1560);
+
+ // shapeRef1561
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5034.5, 7808.29);
+ polygon.ps[1] = Point(5034.5, 7848.29);
+ polygon.ps[2] = Point(4959, 7848.29);
+ polygon.ps[3] = Point(4959, 7808.29);
+ new ShapeRef(router, polygon, 1561);
+
+ // shapeRef1562
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5034.5, 8341.99);
+ polygon.ps[1] = Point(5034.5, 8381.99);
+ polygon.ps[2] = Point(4959, 8381.99);
+ polygon.ps[3] = Point(4959, 8341.99);
+ new ShapeRef(router, polygon, 1562);
+
+ // shapeRef1563
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5034.5, 8807.22);
+ polygon.ps[1] = Point(5034.5, 8847.22);
+ polygon.ps[2] = Point(4959, 8847.22);
+ polygon.ps[3] = Point(4959, 8807.22);
+ new ShapeRef(router, polygon, 1563);
+
+ // shapeRef1564
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5034.5, 9312.42);
+ polygon.ps[1] = Point(5034.5, 9352.42);
+ polygon.ps[2] = Point(4959, 9352.42);
+ polygon.ps[3] = Point(4959, 9312.42);
+ new ShapeRef(router, polygon, 1564);
+
+ // shapeRef1565
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4374.5, 9857.02);
+ polygon.ps[1] = Point(4374.5, 9897.02);
+ polygon.ps[2] = Point(4299, 9897.02);
+ polygon.ps[3] = Point(4299, 9857.02);
+ new ShapeRef(router, polygon, 1565);
+
+ // shapeRef1566
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4778.5, 10368);
+ polygon.ps[1] = Point(4778.5, 10428);
+ polygon.ps[2] = Point(4723.5, 10428);
+ polygon.ps[3] = Point(4723.5, 10368);
+ new ShapeRef(router, polygon, 1566);
+
+ // shapeRef1567
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4638.5, 10563.3);
+ polygon.ps[1] = Point(4638.5, 10603.3);
+ polygon.ps[2] = Point(4563, 10603.3);
+ polygon.ps[3] = Point(4563, 10563.3);
+ new ShapeRef(router, polygon, 1567);
+
+ // shapeRef1568
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11448.6, 1458.29);
+ polygon.ps[1] = Point(11448.6, 1498.29);
+ polygon.ps[2] = Point(11373.1, 1498.29);
+ polygon.ps[3] = Point(11373.1, 1458.29);
+ new ShapeRef(router, polygon, 1568);
+
+ // shapeRef1569
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11353.1, 1095.29);
+ polygon.ps[1] = Point(11353.1, 1135.29);
+ polygon.ps[2] = Point(11277.6, 1135.29);
+ polygon.ps[3] = Point(11277.6, 1095.29);
+ new ShapeRef(router, polygon, 1569);
+
+ // shapeRef1570
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11448.6, 590.091);
+ polygon.ps[1] = Point(11448.6, 630.091);
+ polygon.ps[2] = Point(11373.1, 630.091);
+ polygon.ps[3] = Point(11373.1, 590.091);
+ new ShapeRef(router, polygon, 1570);
+
+ // shapeRef1571
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11555.6, 388.265);
+ polygon.ps[1] = Point(11555.6, 448.265);
+ polygon.ps[2] = Point(11500.6, 448.265);
+ polygon.ps[3] = Point(11500.6, 388.265);
+ new ShapeRef(router, polygon, 1571);
+
+ // shapeRef1572
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11984.6, 388.265);
+ polygon.ps[1] = Point(11984.6, 448.265);
+ polygon.ps[2] = Point(11929.6, 448.265);
+ polygon.ps[3] = Point(11929.6, 388.265);
+ new ShapeRef(router, polygon, 1572);
+
+ // shapeRef1573
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15014.4, 1356.29);
+ polygon.ps[1] = Point(15014.4, 1416.29);
+ polygon.ps[2] = Point(14959.4, 1416.29);
+ polygon.ps[3] = Point(14959.4, 1356.29);
+ new ShapeRef(router, polygon, 1573);
+
+ // shapeRef1574
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12752, 507.091);
+ polygon.ps[1] = Point(12752, 567.091);
+ polygon.ps[2] = Point(12697, 567.091);
+ polygon.ps[3] = Point(12697, 507.091);
+ new ShapeRef(router, polygon, 1574);
+
+ // shapeRef1575
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13227.5, 388.265);
+ polygon.ps[1] = Point(13227.5, 448.265);
+ polygon.ps[2] = Point(13172.5, 448.265);
+ polygon.ps[3] = Point(13172.5, 388.265);
+ new ShapeRef(router, polygon, 1575);
+
+ // shapeRef1576
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13899.5, 388.265);
+ polygon.ps[1] = Point(13899.5, 448.265);
+ polygon.ps[2] = Point(13844.5, 448.265);
+ polygon.ps[3] = Point(13844.5, 388.265);
+ new ShapeRef(router, polygon, 1576);
+
+ // shapeRef1577
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14361.5, 388.265);
+ polygon.ps[1] = Point(14361.5, 448.265);
+ polygon.ps[2] = Point(14306.5, 448.265);
+ polygon.ps[3] = Point(14306.5, 388.265);
+ new ShapeRef(router, polygon, 1577);
+
+ // shapeRef1578
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14823.5, 388.265);
+ polygon.ps[1] = Point(14823.5, 448.265);
+ polygon.ps[2] = Point(14768.5, 448.265);
+ polygon.ps[3] = Point(14768.5, 388.265);
+ new ShapeRef(router, polygon, 1578);
+
+ // shapeRef1579
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15664.8, 388.265);
+ polygon.ps[1] = Point(15664.8, 448.265);
+ polygon.ps[2] = Point(15609.8, 448.265);
+ polygon.ps[3] = Point(15609.8, 388.265);
+ new ShapeRef(router, polygon, 1579);
+
+ // shapeRef1580
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16193.1, 388.265);
+ polygon.ps[1] = Point(16193.1, 448.265);
+ polygon.ps[2] = Point(16138.1, 448.265);
+ polygon.ps[3] = Point(16138.1, 388.265);
+ new ShapeRef(router, polygon, 1580);
+
+ // shapeRef1581
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16449.1, 805.591);
+ polygon.ps[1] = Point(16449.1, 845.591);
+ polygon.ps[2] = Point(16373.6, 845.591);
+ polygon.ps[3] = Point(16373.6, 805.591);
+ new ShapeRef(router, polygon, 1581);
+
+ // shapeRef1582
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16251.1, 805.591);
+ polygon.ps[1] = Point(16251.1, 845.591);
+ polygon.ps[2] = Point(16175.6, 845.591);
+ polygon.ps[3] = Point(16175.6, 805.591);
+ new ShapeRef(router, polygon, 1582);
+
+ // shapeRef1583
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11133.7, 8004.79);
+ polygon.ps[1] = Point(11133.7, 8064.79);
+ polygon.ps[2] = Point(11078.7, 8064.79);
+ polygon.ps[3] = Point(11078.7, 8004.79);
+ new ShapeRef(router, polygon, 1583);
+
+ // shapeRef1584
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10803.7, 388.265);
+ polygon.ps[1] = Point(10803.7, 448.265);
+ polygon.ps[2] = Point(10748.7, 448.265);
+ polygon.ps[3] = Point(10748.7, 388.265);
+ new ShapeRef(router, polygon, 1584);
+
+ // shapeRef1585
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15606.8, 1356.29);
+ polygon.ps[1] = Point(15606.8, 1416.29);
+ polygon.ps[2] = Point(15551.8, 1416.29);
+ polygon.ps[3] = Point(15551.8, 1356.29);
+ new ShapeRef(router, polygon, 1585);
+
+ // shapeRef1586
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8056.79, 243.265);
+ polygon.ps[1] = Point(8056.79, 303.265);
+ polygon.ps[2] = Point(8001.79, 303.265);
+ polygon.ps[3] = Point(8001.79, 243.265);
+ new ShapeRef(router, polygon, 1586);
+
+ // shapeRef1587
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8320.79, 355.265);
+ polygon.ps[1] = Point(8320.79, 415.265);
+ polygon.ps[2] = Point(8265.79, 415.265);
+ polygon.ps[3] = Point(8265.79, 355.265);
+ new ShapeRef(router, polygon, 1587);
+
+ // shapeRef1588
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7792.79, 355.265);
+ polygon.ps[1] = Point(7792.79, 415.265);
+ polygon.ps[2] = Point(7737.79, 415.265);
+ polygon.ps[3] = Point(7737.79, 355.265);
+ new ShapeRef(router, polygon, 1588);
+
+ // shapeRef1589
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6975.6, 355.265);
+ polygon.ps[1] = Point(6975.6, 415.265);
+ polygon.ps[2] = Point(6920.6, 415.265);
+ polygon.ps[3] = Point(6920.6, 355.265);
+ new ShapeRef(router, polygon, 1589);
+
+ // shapeRef1590
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6348.6, 355.265);
+ polygon.ps[1] = Point(6348.6, 415.265);
+ polygon.ps[2] = Point(6293.6, 415.265);
+ polygon.ps[3] = Point(6293.6, 355.265);
+ new ShapeRef(router, polygon, 1590);
+
+ // shapeRef1591
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15142.8, 1111.29);
+ polygon.ps[1] = Point(15142.8, 1171.29);
+ polygon.ps[2] = Point(15087.8, 1171.29);
+ polygon.ps[3] = Point(15087.8, 1111.29);
+ new ShapeRef(router, polygon, 1591);
+
+ // shapeRef1592
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15504.8, 1111.29);
+ polygon.ps[1] = Point(15504.8, 1171.29);
+ polygon.ps[2] = Point(15449.8, 1171.29);
+ polygon.ps[3] = Point(15449.8, 1111.29);
+ new ShapeRef(router, polygon, 1592);
+
+ // shapeRef1593
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8825.89, 4603.9);
+ polygon.ps[1] = Point(8825.89, 4643.9);
+ polygon.ps[2] = Point(8750.39, 4643.9);
+ polygon.ps[3] = Point(8750.39, 4603.9);
+ new ShapeRef(router, polygon, 1593);
+
+ // shapeRef1594
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5397.5, 4555.4);
+ polygon.ps[1] = Point(5397.5, 4595.4);
+ polygon.ps[2] = Point(5322, 4595.4);
+ polygon.ps[3] = Point(5322, 4555.4);
+ new ShapeRef(router, polygon, 1594);
+
+ // shapeRef1595
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5397.5, 5149.4);
+ polygon.ps[1] = Point(5397.5, 5189.4);
+ polygon.ps[2] = Point(5322, 5189.4);
+ polygon.ps[3] = Point(5322, 5149.4);
+ new ShapeRef(router, polygon, 1595);
+
+ // shapeRef1596
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10106, 10369.5);
+ polygon.ps[1] = Point(10106, 10409.5);
+ polygon.ps[2] = Point(10030.5, 10409.5);
+ polygon.ps[3] = Point(10030.5, 10369.5);
+ new ShapeRef(router, polygon, 1596);
+
+ // shapeRef1597
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10539.7, 10612.3);
+ polygon.ps[1] = Point(10539.7, 10672.3);
+ polygon.ps[2] = Point(10484.7, 10672.3);
+ polygon.ps[3] = Point(10484.7, 10612.3);
+ new ShapeRef(router, polygon, 1597);
+
+ // shapeRef1598
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10935.7, 10612.3);
+ polygon.ps[1] = Point(10935.7, 10672.3);
+ polygon.ps[2] = Point(10880.7, 10672.3);
+ polygon.ps[3] = Point(10880.7, 10612.3);
+ new ShapeRef(router, polygon, 1598);
+
+ // shapeRef1599
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10927.7, 10960.6);
+ polygon.ps[1] = Point(10927.7, 11000.6);
+ polygon.ps[2] = Point(10852.2, 11000.6);
+ polygon.ps[3] = Point(10852.2, 10960.6);
+ new ShapeRef(router, polygon, 1599);
+
+ // shapeRef1600
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6678.6, 6926.4);
+ polygon.ps[1] = Point(6678.6, 6986.4);
+ polygon.ps[2] = Point(6623.6, 6986.4);
+ polygon.ps[3] = Point(6623.6, 6926.4);
+ new ShapeRef(router, polygon, 1600);
+
+ // shapeRef1601
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6637.6, 7542.29);
+ polygon.ps[1] = Point(6637.6, 7582.29);
+ polygon.ps[2] = Point(6562.1, 7582.29);
+ polygon.ps[3] = Point(6562.1, 7542.29);
+ new ShapeRef(router, polygon, 1601);
+
+ // shapeRef1602
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7297.6, 7273.4);
+ polygon.ps[1] = Point(7297.6, 7313.4);
+ polygon.ps[2] = Point(7222.1, 7313.4);
+ polygon.ps[3] = Point(7222.1, 7273.4);
+ new ShapeRef(router, polygon, 1602);
+
+ // shapeRef1603
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6637.6, 8021.79);
+ polygon.ps[1] = Point(6637.6, 8061.79);
+ polygon.ps[2] = Point(6562.1, 8061.79);
+ polygon.ps[3] = Point(6562.1, 8021.79);
+ new ShapeRef(router, polygon, 1603);
+
+ // shapeRef1604
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7297.6, 9193.42);
+ polygon.ps[1] = Point(7297.6, 9233.42);
+ polygon.ps[2] = Point(7222.1, 9233.42);
+ polygon.ps[3] = Point(7222.1, 9193.42);
+ new ShapeRef(router, polygon, 1604);
+
+ // shapeRef1605
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6637.6, 9857.02);
+ polygon.ps[1] = Point(6637.6, 9897.02);
+ polygon.ps[2] = Point(6562.1, 9897.02);
+ polygon.ps[3] = Point(6562.1, 9857.02);
+ new ShapeRef(router, polygon, 1605);
+
+ // shapeRef1606
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8188.79, 6444.51);
+ polygon.ps[1] = Point(8188.79, 6504.51);
+ polygon.ps[2] = Point(8133.79, 6504.51);
+ polygon.ps[3] = Point(8133.79, 6444.51);
+ new ShapeRef(router, polygon, 1606);
+
+ // shapeRef1607
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6208.6, 7955.79);
+ polygon.ps[1] = Point(6208.6, 7995.79);
+ polygon.ps[2] = Point(6133.1, 7995.79);
+ polygon.ps[3] = Point(6133.1, 7955.79);
+ new ShapeRef(router, polygon, 1607);
+
+ // shapeRef1608
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7272.6, 6444.51);
+ polygon.ps[1] = Point(7272.6, 6504.51);
+ polygon.ps[2] = Point(7217.6, 6504.51);
+ polygon.ps[3] = Point(7217.6, 6444.51);
+ new ShapeRef(router, polygon, 1608);
+
+ // shapeRef1609
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6414.6, 6718.21);
+ polygon.ps[1] = Point(6414.6, 6778.21);
+ polygon.ps[2] = Point(6359.6, 6778.21);
+ polygon.ps[3] = Point(6359.6, 6718.21);
+ new ShapeRef(router, polygon, 1609);
+
+ // shapeRef1610
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15954.1, 11873.9);
+ polygon.ps[1] = Point(15954.1, 11913.9);
+ polygon.ps[2] = Point(15878.6, 11913.9);
+ polygon.ps[3] = Point(15878.6, 11873.9);
+ new ShapeRef(router, polygon, 1610);
+
+ // shapeRef1611
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15014.4, 12222.3);
+ polygon.ps[1] = Point(15014.4, 12282.3);
+ polygon.ps[2] = Point(14959.4, 12282.3);
+ polygon.ps[3] = Point(14959.4, 12222.3);
+ new ShapeRef(router, polygon, 1611);
+
+ // shapeRef1612
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14885.9, 1276.29);
+ polygon.ps[1] = Point(14885.9, 1336.29);
+ polygon.ps[2] = Point(14830.9, 1336.29);
+ polygon.ps[3] = Point(14830.9, 1276.29);
+ new ShapeRef(router, polygon, 1612);
+
+ // shapeRef1613
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7850.79, 831.285);
+ polygon.ps[1] = Point(7850.79, 871.285);
+ polygon.ps[2] = Point(7775.29, 871.285);
+ polygon.ps[3] = Point(7775.29, 831.285);
+ new ShapeRef(router, polygon, 1613);
+
+ // shapeRef1614
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7928.29, 8908.22);
+ polygon.ps[1] = Point(7928.29, 8970.22);
+ polygon.ps[2] = Point(7866.29, 8970.22);
+ polygon.ps[3] = Point(7866.29, 8908.22);
+ new ShapeRef(router, polygon, 1614);
+
+ // shapeRef1615
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16229.6, 10750.3);
+ polygon.ps[1] = Point(16229.6, 10812.3);
+ polygon.ps[2] = Point(16167.6, 10812.3);
+ polygon.ps[3] = Point(16167.6, 10750.3);
+ new ShapeRef(router, polygon, 1615);
+
+ // shapeRef1616
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15050.9, 10750.3);
+ polygon.ps[1] = Point(15050.9, 10812.3);
+ polygon.ps[2] = Point(14988.9, 10812.3);
+ polygon.ps[3] = Point(14988.9, 10750.3);
+ new ShapeRef(router, polygon, 1616);
+
+ // shapeRef1617
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15050.9, 11763.9);
+ polygon.ps[1] = Point(15050.9, 11825.9);
+ polygon.ps[2] = Point(14988.9, 11825.9);
+ polygon.ps[3] = Point(14988.9, 11763.9);
+ new ShapeRef(router, polygon, 1617);
+
+ // shapeRef1618
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10454.9, 6219.51);
+ polygon.ps[1] = Point(10454.9, 6281.51);
+ polygon.ps[2] = Point(10392.9, 6281.51);
+ polygon.ps[3] = Point(10392.9, 6219.51);
+ new ShapeRef(router, polygon, 1618);
+
+ // shapeRef1619
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12562.5, 4330.11);
+ polygon.ps[1] = Point(12562.5, 4392.11);
+ polygon.ps[2] = Point(12500.5, 4392.11);
+ polygon.ps[3] = Point(12500.5, 4330.11);
+ new ShapeRef(router, polygon, 1619);
+
+ // shapeRef1620
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13297, 4095.51);
+ polygon.ps[1] = Point(13297, 4157.51);
+ polygon.ps[2] = Point(13235, 4157.51);
+ polygon.ps[3] = Point(13235, 4095.51);
+ new ShapeRef(router, polygon, 1620);
+
+ // shapeRef1621
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7796.29, 579.091);
+ polygon.ps[1] = Point(7796.29, 641.091);
+ polygon.ps[2] = Point(7734.29, 641.091);
+ polygon.ps[3] = Point(7734.29, 579.091);
+ new ShapeRef(router, polygon, 1621);
+
+ // shapeRef1622
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10147, 10143);
+ polygon.ps[1] = Point(10147, 10205);
+ polygon.ps[2] = Point(10085, 10205);
+ polygon.ps[3] = Point(10085, 10143);
+ new ShapeRef(router, polygon, 1622);
+
+ // shapeRef1623
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10906.2, 10750.3);
+ polygon.ps[1] = Point(10906.2, 10812.3);
+ polygon.ps[2] = Point(10844.2, 10812.3);
+ polygon.ps[3] = Point(10844.2, 10750.3);
+ new ShapeRef(router, polygon, 1623);
+
+ // shapeRef1624
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9532.59, 10750.3);
+ polygon.ps[1] = Point(9532.59, 10812.3);
+ polygon.ps[2] = Point(9470.59, 10812.3);
+ polygon.ps[3] = Point(9470.59, 10750.3);
+ new ShapeRef(router, polygon, 1624);
+
+ // shapeRef1625
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9532.59, 6450.51);
+ polygon.ps[1] = Point(9532.59, 6512.51);
+ polygon.ps[2] = Point(9470.59, 6512.51);
+ polygon.ps[3] = Point(9470.59, 6450.51);
+ new ShapeRef(router, polygon, 1625);
+
+ // shapeRef1626
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13606, 10750.3);
+ polygon.ps[1] = Point(13606, 10812.3);
+ polygon.ps[2] = Point(13544, 10812.3);
+ polygon.ps[3] = Point(13544, 10750.3);
+ new ShapeRef(router, polygon, 1626);
+
+ // shapeRef1627
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12562.5, 10750.3);
+ polygon.ps[1] = Point(12562.5, 10812.3);
+ polygon.ps[2] = Point(12500.5, 10812.3);
+ polygon.ps[3] = Point(12500.5, 10750.3);
+ new ShapeRef(router, polygon, 1627);
+
+ // shapeRef1628
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9532.59, 9945.02);
+ polygon.ps[1] = Point(9532.59, 10007);
+ polygon.ps[2] = Point(9470.59, 10007);
+ polygon.ps[3] = Point(9470.59, 9945.02);
+ new ShapeRef(router, polygon, 1628);
+
+ // shapeRef1629
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9532.59, 8218.99);
+ polygon.ps[1] = Point(9532.59, 8280.99);
+ polygon.ps[2] = Point(9470.59, 8280.99);
+ polygon.ps[3] = Point(9470.59, 8218.99);
+ new ShapeRef(router, polygon, 1629);
+
+ // shapeRef1630
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8866.89, 4973.4);
+ polygon.ps[1] = Point(8866.89, 5035.4);
+ polygon.ps[2] = Point(8804.89, 5035.4);
+ polygon.ps[3] = Point(8804.89, 4973.4);
+ new ShapeRef(router, polygon, 1630);
+
+ // shapeRef1631
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15899.6, 12050.3);
+ polygon.ps[1] = Point(15899.6, 12112.3);
+ polygon.ps[2] = Point(15837.6, 12112.3);
+ polygon.ps[3] = Point(15837.6, 12050.3);
+ new ShapeRef(router, polygon, 1631);
+
+ // shapeRef1632
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15899.6, 12261.3);
+ polygon.ps[1] = Point(15899.6, 12323.3);
+ polygon.ps[2] = Point(15837.6, 12323.3);
+ polygon.ps[3] = Point(15837.6, 12261.3);
+ new ShapeRef(router, polygon, 1632);
+
+ // shapeRef1633
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15303.5, 12261.3);
+ polygon.ps[1] = Point(15303.5, 12323.3);
+ polygon.ps[2] = Point(15241.5, 12323.3);
+ polygon.ps[3] = Point(15241.5, 12261.3);
+ new ShapeRef(router, polygon, 1633);
+
+ // shapeRef1634
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9116.99, 11601.9);
+ polygon.ps[1] = Point(9116.99, 11663.9);
+ polygon.ps[2] = Point(9054.99, 11663.9);
+ polygon.ps[3] = Point(9054.99, 11601.9);
+ new ShapeRef(router, polygon, 1634);
+
+ // shapeRef1635
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10906.2, 11601.9);
+ polygon.ps[1] = Point(10906.2, 11663.9);
+ polygon.ps[2] = Point(10844.2, 11663.9);
+ polygon.ps[3] = Point(10844.2, 11601.9);
+ new ShapeRef(router, polygon, 1635);
+
+ // shapeRef1636
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12021.1, 11601.9);
+ polygon.ps[1] = Point(12021.1, 11663.9);
+ polygon.ps[2] = Point(11959.1, 11663.9);
+ polygon.ps[3] = Point(11959.1, 11601.9);
+ new ShapeRef(router, polygon, 1636);
+
+ // shapeRef1637
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13606, 11601.9);
+ polygon.ps[1] = Point(13606, 11663.9);
+ polygon.ps[2] = Point(13544, 11663.9);
+ polygon.ps[3] = Point(13544, 11601.9);
+ new ShapeRef(router, polygon, 1637);
+
+ // shapeRef1638
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13903, 7031.4);
+ polygon.ps[1] = Point(13903, 7093.4);
+ polygon.ps[2] = Point(13841, 7093.4);
+ polygon.ps[3] = Point(13841, 7031.4);
+ new ShapeRef(router, polygon, 1638);
+
+ // shapeRef1639
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10147, 9314.42);
+ polygon.ps[1] = Point(10147, 9376.42);
+ polygon.ps[2] = Point(10085, 9376.42);
+ polygon.ps[3] = Point(10085, 9314.42);
+ new ShapeRef(router, polygon, 1639);
+
+ // shapeRef1640
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12153.1, 10143);
+ polygon.ps[1] = Point(12153.1, 10205);
+ polygon.ps[2] = Point(12091.1, 10205);
+ polygon.ps[3] = Point(12091.1, 10143);
+ new ShapeRef(router, polygon, 1640);
+
+ // shapeRef1641
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15899.6, 10143);
+ polygon.ps[1] = Point(15899.6, 10205);
+ polygon.ps[2] = Point(15837.6, 10205);
+ polygon.ps[3] = Point(15837.6, 10143);
+ new ShapeRef(router, polygon, 1641);
+
+ // shapeRef1642
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16951.8, 10143);
+ polygon.ps[1] = Point(16951.8, 10205);
+ polygon.ps[2] = Point(16889.8, 10205);
+ polygon.ps[3] = Point(16889.8, 10143);
+ new ShapeRef(router, polygon, 1642);
+
+ // shapeRef1643
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18168.5, 10143);
+ polygon.ps[1] = Point(18168.5, 10205);
+ polygon.ps[2] = Point(18106.5, 10205);
+ polygon.ps[3] = Point(18106.5, 10143);
+ new ShapeRef(router, polygon, 1643);
+
+ // shapeRef1644
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18333.5, 6757.21);
+ polygon.ps[1] = Point(18333.5, 6819.21);
+ polygon.ps[2] = Point(18271.5, 6819.21);
+ polygon.ps[3] = Point(18271.5, 6757.21);
+ new ShapeRef(router, polygon, 1644);
+
+ // shapeRef1645
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13231, 6757.21);
+ polygon.ps[1] = Point(13231, 6819.21);
+ polygon.ps[2] = Point(13169, 6819.21);
+ polygon.ps[3] = Point(13169, 6757.21);
+ new ShapeRef(router, polygon, 1645);
+
+ // shapeRef1646
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16262.6, 6757.21);
+ polygon.ps[1] = Point(16262.6, 6819.21);
+ polygon.ps[2] = Point(16200.6, 6819.21);
+ polygon.ps[3] = Point(16200.6, 6757.21);
+ new ShapeRef(router, polygon, 1646);
+
+ // shapeRef1647
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10840.2, 8043.79);
+ polygon.ps[1] = Point(10840.2, 8105.79);
+ polygon.ps[2] = Point(10778.2, 8105.79);
+ polygon.ps[3] = Point(10778.2, 8043.79);
+ new ShapeRef(router, polygon, 1647);
+
+ // shapeRef1648
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11526.1, 8043.79);
+ polygon.ps[1] = Point(11526.1, 8105.79);
+ polygon.ps[2] = Point(11464.1, 8105.79);
+ polygon.ps[3] = Point(11464.1, 8043.79);
+ new ShapeRef(router, polygon, 1648);
+
+ // shapeRef1649
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11526.1, 7394.4);
+ polygon.ps[1] = Point(11526.1, 7456.4);
+ polygon.ps[2] = Point(11464.1, 7456.4);
+ polygon.ps[3] = Point(11464.1, 7394.4);
+ new ShapeRef(router, polygon, 1649);
+
+ // shapeRef1650
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12887.5, 7394.4);
+ polygon.ps[1] = Point(12887.5, 7456.4);
+ polygon.ps[2] = Point(12825.5, 7456.4);
+ polygon.ps[3] = Point(12825.5, 7394.4);
+ new ShapeRef(router, polygon, 1650);
+
+ // shapeRef1651
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15438.5, 7394.4);
+ polygon.ps[1] = Point(15438.5, 7456.4);
+ polygon.ps[2] = Point(15376.5, 7456.4);
+ polygon.ps[3] = Point(15376.5, 7394.4);
+ new ShapeRef(router, polygon, 1651);
+
+ // shapeRef1652
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7829.29, 3534.51);
+ polygon.ps[1] = Point(7829.29, 3596.51);
+ polygon.ps[2] = Point(7767.29, 3596.51);
+ polygon.ps[3] = Point(7767.29, 3534.51);
+ new ShapeRef(router, polygon, 1652);
+
+ // shapeRef1653
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11005.2, 1612.29);
+ polygon.ps[1] = Point(11005.2, 1674.29);
+ polygon.ps[2] = Point(10943.2, 1674.29);
+ polygon.ps[3] = Point(10943.2, 1612.29);
+ new ShapeRef(router, polygon, 1653);
+
+ // shapeRef1654
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9466.59, 6932.4);
+ polygon.ps[1] = Point(9466.59, 6994.4);
+ polygon.ps[2] = Point(9404.59, 6994.4);
+ polygon.ps[3] = Point(9404.59, 6932.4);
+ new ShapeRef(router, polygon, 1654);
+
+ // shapeRef1655
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10180, 7427.4);
+ polygon.ps[1] = Point(10180, 7489.4);
+ polygon.ps[2] = Point(10118, 7489.4);
+ polygon.ps[3] = Point(10118, 7427.4);
+ new ShapeRef(router, polygon, 1655);
+
+ // shapeRef1656
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10642.2, 8251.99);
+ polygon.ps[1] = Point(10642.2, 8313.99);
+ polygon.ps[2] = Point(10580.2, 8313.99);
+ polygon.ps[3] = Point(10580.2, 8251.99);
+ new ShapeRef(router, polygon, 1656);
+
+ // shapeRef1657
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10741.2, 8842.22);
+ polygon.ps[1] = Point(10741.2, 8904.22);
+ polygon.ps[2] = Point(10679.2, 8904.22);
+ polygon.ps[3] = Point(10679.2, 8842.22);
+ new ShapeRef(router, polygon, 1657);
+
+ // shapeRef1658
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8715.29, 9945.02);
+ polygon.ps[1] = Point(8715.29, 10007);
+ polygon.ps[2] = Point(8653.29, 10007);
+ polygon.ps[3] = Point(8653.29, 9945.02);
+ new ShapeRef(router, polygon, 1658);
+
+ // shapeRef1659
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7862.29, 9446.42);
+ polygon.ps[1] = Point(7862.29, 9508.42);
+ polygon.ps[2] = Point(7800.29, 9508.42);
+ polygon.ps[3] = Point(7800.29, 9446.42);
+ new ShapeRef(router, polygon, 1659);
+
+ // shapeRef1660
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7441.1, 8548.99);
+ polygon.ps[1] = Point(7441.1, 8610.99);
+ polygon.ps[2] = Point(7379.1, 8610.99);
+ polygon.ps[3] = Point(7379.1, 8548.99);
+ new ShapeRef(router, polygon, 1660);
+
+ // shapeRef1661
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8866.89, 4330.11);
+ polygon.ps[1] = Point(8866.89, 4392.11);
+ polygon.ps[2] = Point(8804.89, 4392.11);
+ polygon.ps[3] = Point(8804.89, 4330.11);
+ new ShapeRef(router, polygon, 1661);
+
+ // shapeRef1662
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8866.89, 3633.51);
+ polygon.ps[1] = Point(8866.89, 3695.51);
+ polygon.ps[2] = Point(8804.89, 3695.51);
+ polygon.ps[3] = Point(8804.89, 3633.51);
+ new ShapeRef(router, polygon, 1662);
+
+ // shapeRef1663
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9815.69, 5481.67);
+ polygon.ps[1] = Point(9815.69, 5543.67);
+ polygon.ps[2] = Point(9753.69, 5543.67);
+ polygon.ps[3] = Point(9753.69, 5481.67);
+ new ShapeRef(router, polygon, 1663);
+
+ // shapeRef1664
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8866.89, 3142.29);
+ polygon.ps[1] = Point(8866.89, 3204.29);
+ polygon.ps[2] = Point(8804.89, 3204.29);
+ polygon.ps[3] = Point(8804.89, 3142.29);
+ new ShapeRef(router, polygon, 1664);
+
+ // shapeRef1665
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8866.89, 2548.29);
+ polygon.ps[1] = Point(8866.89, 2610.29);
+ polygon.ps[2] = Point(8804.89, 2610.29);
+ polygon.ps[3] = Point(8804.89, 2548.29);
+ new ShapeRef(router, polygon, 1665);
+
+ // shapeRef1666
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.29, 1645.29);
+ polygon.ps[1] = Point(8489.29, 1707.29);
+ polygon.ps[2] = Point(8427.29, 1707.29);
+ polygon.ps[3] = Point(8427.29, 1645.29);
+ new ShapeRef(router, polygon, 1666);
+
+ // shapeRef1667
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.29, 1249.29);
+ polygon.ps[1] = Point(8489.29, 1311.29);
+ polygon.ps[2] = Point(8427.29, 1311.29);
+ polygon.ps[3] = Point(8427.29, 1249.29);
+ new ShapeRef(router, polygon, 1667);
+
+ // shapeRef1668
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.29, 777.091);
+ polygon.ps[1] = Point(8489.29, 839.091);
+ polygon.ps[2] = Point(8427.29, 839.091);
+ polygon.ps[3] = Point(8427.29, 777.091);
+ new ShapeRef(router, polygon, 1668);
+
+ // shapeRef1669
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.29, 394.265);
+ polygon.ps[1] = Point(8489.29, 456.265);
+ polygon.ps[2] = Point(8427.29, 456.265);
+ polygon.ps[3] = Point(8427.29, 394.265);
+ new ShapeRef(router, polygon, 1669);
+
+ // shapeRef1670
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8027.29, 777.091);
+ polygon.ps[1] = Point(8027.29, 839.091);
+ polygon.ps[2] = Point(7965.29, 839.091);
+ polygon.ps[3] = Point(7965.29, 777.091);
+ new ShapeRef(router, polygon, 1670);
+
+ // shapeRef1671
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9301.59, 777.091);
+ polygon.ps[1] = Point(9301.59, 839.091);
+ polygon.ps[2] = Point(9239.59, 839.091);
+ polygon.ps[3] = Point(9239.59, 777.091);
+ new ShapeRef(router, polygon, 1671);
+
+ // shapeRef1672
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8027.29, 1117.29);
+ polygon.ps[1] = Point(8027.29, 1179.29);
+ polygon.ps[2] = Point(7965.29, 1179.29);
+ polygon.ps[3] = Point(7965.29, 1117.29);
+ new ShapeRef(router, polygon, 1672);
+
+ // shapeRef1673
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10487.9, 777.091);
+ polygon.ps[1] = Point(10487.9, 839.091);
+ polygon.ps[2] = Point(10425.9, 839.091);
+ polygon.ps[3] = Point(10425.9, 777.091);
+ new ShapeRef(router, polygon, 1673);
+
+ // shapeRef1674
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11005.2, 777.091);
+ polygon.ps[1] = Point(11005.2, 839.091);
+ polygon.ps[2] = Point(10943.2, 839.091);
+ polygon.ps[3] = Point(10943.2, 777.091);
+ new ShapeRef(router, polygon, 1674);
+
+ // shapeRef1675
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11005.2, 1249.29);
+ polygon.ps[1] = Point(11005.2, 1311.29);
+ polygon.ps[2] = Point(10943.2, 1311.29);
+ polygon.ps[3] = Point(10943.2, 1249.29);
+ new ShapeRef(router, polygon, 1675);
+
+ // shapeRef1676
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10487.9, 1249.29);
+ polygon.ps[1] = Point(10487.9, 1311.29);
+ polygon.ps[2] = Point(10425.9, 1311.29);
+ polygon.ps[3] = Point(10425.9, 1249.29);
+ new ShapeRef(router, polygon, 1676);
+
+ // shapeRef1677
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9683.69, 1414.29);
+ polygon.ps[1] = Point(9683.69, 1476.29);
+ polygon.ps[2] = Point(9621.69, 1476.29);
+ polygon.ps[3] = Point(9621.69, 1414.29);
+ new ShapeRef(router, polygon, 1677);
+
+ // shapeRef1678
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9683.69, 1912.29);
+ polygon.ps[1] = Point(9683.69, 1974.29);
+ polygon.ps[2] = Point(9621.69, 1974.29);
+ polygon.ps[3] = Point(9621.69, 1912.29);
+ new ShapeRef(router, polygon, 1678);
+
+ // shapeRef1679
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11394.1, 1612.29);
+ polygon.ps[1] = Point(11394.1, 1674.29);
+ polygon.ps[2] = Point(11332.1, 1674.29);
+ polygon.ps[3] = Point(11332.1, 1612.29);
+ new ShapeRef(router, polygon, 1679);
+
+ // shapeRef1680
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11005.2, 427.265);
+ polygon.ps[1] = Point(11005.2, 489.265);
+ polygon.ps[2] = Point(10943.2, 489.265);
+ polygon.ps[3] = Point(10943.2, 427.265);
+ new ShapeRef(router, polygon, 1680);
+
+ // shapeRef1681
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10180, 4330.11);
+ polygon.ps[1] = Point(10180, 4392.11);
+ polygon.ps[2] = Point(10118, 4392.11);
+ polygon.ps[3] = Point(10118, 4330.11);
+ new ShapeRef(router, polygon, 1681);
+
+ // shapeRef1682
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10774.2, 4330.11);
+ polygon.ps[1] = Point(10774.2, 4392.11);
+ polygon.ps[2] = Point(10712.2, 4392.11);
+ polygon.ps[3] = Point(10712.2, 4330.11);
+ new ShapeRef(router, polygon, 1682);
+
+ // shapeRef1683
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11104.2, 4330.11);
+ polygon.ps[1] = Point(11104.2, 4392.11);
+ polygon.ps[2] = Point(11042.2, 4392.11);
+ polygon.ps[3] = Point(11042.2, 4330.11);
+ new ShapeRef(router, polygon, 1683);
+
+ // shapeRef1684
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11427.1, 4330.11);
+ polygon.ps[1] = Point(11427.1, 4392.11);
+ polygon.ps[2] = Point(11365.1, 4392.11);
+ polygon.ps[3] = Point(11365.1, 4330.11);
+ new ShapeRef(router, polygon, 1684);
+
+ // shapeRef1685
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11790.1, 4330.11);
+ polygon.ps[1] = Point(11790.1, 4392.11);
+ polygon.ps[2] = Point(11728.1, 4392.11);
+ polygon.ps[3] = Point(11728.1, 4330.11);
+ new ShapeRef(router, polygon, 1685);
+
+ // shapeRef1686
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12087.1, 4330.11);
+ polygon.ps[1] = Point(12087.1, 4392.11);
+ polygon.ps[2] = Point(12025.1, 4392.11);
+ polygon.ps[3] = Point(12025.1, 4330.11);
+ new ShapeRef(router, polygon, 1686);
+
+ // shapeRef1687
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12562.5, 4709.4);
+ polygon.ps[1] = Point(12562.5, 4771.4);
+ polygon.ps[2] = Point(12500.5, 4771.4);
+ polygon.ps[3] = Point(12500.5, 4709.4);
+ new ShapeRef(router, polygon, 1687);
+
+ // shapeRef1688
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12562.5, 5138.4);
+ polygon.ps[1] = Point(12562.5, 5200.4);
+ polygon.ps[2] = Point(12500.5, 5200.4);
+ polygon.ps[3] = Point(12500.5, 5138.4);
+ new ShapeRef(router, polygon, 1688);
+
+ // shapeRef1689
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12562.5, 5481.67);
+ polygon.ps[1] = Point(12562.5, 5543.67);
+ polygon.ps[2] = Point(12500.5, 5543.67);
+ polygon.ps[3] = Point(12500.5, 5481.67);
+ new ShapeRef(router, polygon, 1689);
+
+ // shapeRef1690
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12562.5, 3699.51);
+ polygon.ps[1] = Point(12562.5, 3761.51);
+ polygon.ps[2] = Point(12500.5, 3761.51);
+ polygon.ps[3] = Point(12500.5, 3699.51);
+ new ShapeRef(router, polygon, 1690);
+
+ // shapeRef1691
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12562.5, 3307.29);
+ polygon.ps[1] = Point(12562.5, 3369.29);
+ polygon.ps[2] = Point(12500.5, 3369.29);
+ polygon.ps[3] = Point(12500.5, 3307.29);
+ new ShapeRef(router, polygon, 1691);
+
+ // shapeRef1692
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12562.5, 2647.29);
+ polygon.ps[1] = Point(12562.5, 2709.29);
+ polygon.ps[2] = Point(12500.5, 2709.29);
+ polygon.ps[3] = Point(12500.5, 2647.29);
+ new ShapeRef(router, polygon, 1692);
+
+ // shapeRef1693
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12562.5, 1813.29);
+ polygon.ps[1] = Point(12562.5, 1875.29);
+ polygon.ps[2] = Point(12500.5, 1875.29);
+ polygon.ps[3] = Point(12500.5, 1813.29);
+ new ShapeRef(router, polygon, 1693);
+
+ // shapeRef1694
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12021.1, 1813.29);
+ polygon.ps[1] = Point(12021.1, 1875.29);
+ polygon.ps[2] = Point(11959.1, 1875.29);
+ polygon.ps[3] = Point(11959.1, 1813.29);
+ new ShapeRef(router, polygon, 1694);
+
+ // shapeRef1695
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12021.1, 1546.29);
+ polygon.ps[1] = Point(12021.1, 1608.29);
+ polygon.ps[2] = Point(11959.1, 1608.29);
+ polygon.ps[3] = Point(11959.1, 1546.29);
+ new ShapeRef(router, polygon, 1695);
+
+ // shapeRef1696
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13903, 8218.99);
+ polygon.ps[1] = Point(13903, 8280.99);
+ polygon.ps[2] = Point(13841, 8280.99);
+ polygon.ps[3] = Point(13841, 8218.99);
+ new ShapeRef(router, polygon, 1696);
+
+ // shapeRef1697
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13903, 8677.22);
+ polygon.ps[1] = Point(13903, 8739.22);
+ polygon.ps[2] = Point(13841, 8739.22);
+ polygon.ps[3] = Point(13841, 8677.22);
+ new ShapeRef(router, polygon, 1697);
+
+ // shapeRef1698
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11955.1, 7581.79);
+ polygon.ps[1] = Point(11955.1, 7643.79);
+ polygon.ps[2] = Point(11893.1, 7643.79);
+ polygon.ps[3] = Point(11893.1, 7581.79);
+ new ShapeRef(router, polygon, 1698);
+
+ // shapeRef1699
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11955.1, 8043.79);
+ polygon.ps[1] = Point(11955.1, 8105.79);
+ polygon.ps[2] = Point(11893.1, 8105.79);
+ polygon.ps[3] = Point(11893.1, 8043.79);
+ new ShapeRef(router, polygon, 1699);
+
+ // shapeRef1700
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15899.6, 8218.99);
+ polygon.ps[1] = Point(15899.6, 8280.99);
+ polygon.ps[2] = Point(15837.6, 8280.99);
+ polygon.ps[3] = Point(15837.6, 8218.99);
+ new ShapeRef(router, polygon, 1700);
+
+ // shapeRef1701
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15899.6, 8677.22);
+ polygon.ps[1] = Point(15899.6, 8739.22);
+ polygon.ps[2] = Point(15837.6, 8739.22);
+ polygon.ps[3] = Point(15837.6, 8677.22);
+ new ShapeRef(router, polygon, 1701);
+
+ // shapeRef1702
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16753.8, 8218.99);
+ polygon.ps[1] = Point(16753.8, 8280.99);
+ polygon.ps[2] = Point(16691.8, 8280.99);
+ polygon.ps[3] = Point(16691.8, 8218.99);
+ new ShapeRef(router, polygon, 1702);
+
+ // shapeRef1703
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16753.8, 8611.22);
+ polygon.ps[1] = Point(16753.8, 8673.22);
+ polygon.ps[2] = Point(16691.8, 8673.22);
+ polygon.ps[3] = Point(16691.8, 8611.22);
+ new ShapeRef(router, polygon, 1703);
+
+ // shapeRef1704
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13198, 8218.99);
+ polygon.ps[1] = Point(13198, 8280.99);
+ polygon.ps[2] = Point(13136, 8280.99);
+ polygon.ps[3] = Point(13136, 8218.99);
+ new ShapeRef(router, polygon, 1704);
+
+ // shapeRef1705
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10840.2, 7097.4);
+ polygon.ps[1] = Point(10840.2, 7159.4);
+ polygon.ps[2] = Point(10778.2, 7159.4);
+ polygon.ps[3] = Point(10778.2, 7097.4);
+ new ShapeRef(router, polygon, 1705);
+
+ // shapeRef1706
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18399.5, 5039.4);
+ polygon.ps[1] = Point(18399.5, 5101.4);
+ polygon.ps[2] = Point(18337.5, 5101.4);
+ polygon.ps[3] = Point(18337.5, 5039.4);
+ new ShapeRef(router, polygon, 1706);
+
+ // shapeRef1707
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18756.5, 5791.9);
+ polygon.ps[1] = Point(18756.5, 5853.9);
+ polygon.ps[2] = Point(18694.5, 5853.9);
+ polygon.ps[3] = Point(18694.5, 5791.9);
+ new ShapeRef(router, polygon, 1707);
+
+ // shapeRef1708
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17772.5, 5791.9);
+ polygon.ps[1] = Point(17772.5, 5853.9);
+ polygon.ps[2] = Point(17710.5, 5853.9);
+ polygon.ps[3] = Point(17710.5, 5791.9);
+ new ShapeRef(router, polygon, 1708);
+
+ // shapeRef1709
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10840.2, 7548.79);
+ polygon.ps[1] = Point(10840.2, 7610.79);
+ polygon.ps[2] = Point(10778.2, 7610.79);
+ polygon.ps[3] = Point(10778.2, 7548.79);
+ new ShapeRef(router, polygon, 1709);
+
+ // shapeRef1710
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11071.2, 8842.22);
+ polygon.ps[1] = Point(11071.2, 8904.22);
+ polygon.ps[2] = Point(11009.2, 8904.22);
+ polygon.ps[3] = Point(11009.2, 8842.22);
+ new ShapeRef(router, polygon, 1710);
+
+ // shapeRef1711
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11460.1, 8842.22);
+ polygon.ps[1] = Point(11460.1, 8904.22);
+ polygon.ps[2] = Point(11398.1, 8904.22);
+ polygon.ps[3] = Point(11398.1, 8842.22);
+ new ShapeRef(router, polygon, 1711);
+
+ // shapeRef1712
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12021.1, 8842.22);
+ polygon.ps[1] = Point(12021.1, 8904.22);
+ polygon.ps[2] = Point(11959.1, 8904.22);
+ polygon.ps[3] = Point(11959.1, 8842.22);
+ new ShapeRef(router, polygon, 1712);
+
+ // shapeRef1713
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12920.5, 8842.22);
+ polygon.ps[1] = Point(12920.5, 8904.22);
+ polygon.ps[2] = Point(12858.5, 8904.22);
+ polygon.ps[3] = Point(12858.5, 8842.22);
+ new ShapeRef(router, polygon, 1713);
+
+ // shapeRef1714
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13903, 8842.22);
+ polygon.ps[1] = Point(13903, 8904.22);
+ polygon.ps[2] = Point(13841, 8904.22);
+ polygon.ps[3] = Point(13841, 8842.22);
+ new ShapeRef(router, polygon, 1714);
+
+ // shapeRef1715
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7177.1, 3534.51);
+ polygon.ps[1] = Point(7177.1, 3596.51);
+ polygon.ps[2] = Point(7115.1, 3596.51);
+ polygon.ps[3] = Point(7115.1, 3534.51);
+ new ShapeRef(router, polygon, 1715);
+
+ // shapeRef1716
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6550.1, 3534.51);
+ polygon.ps[1] = Point(6550.1, 3596.51);
+ polygon.ps[2] = Point(6488.1, 3596.51);
+ polygon.ps[3] = Point(6488.1, 3534.51);
+ new ShapeRef(router, polygon, 1716);
+
+ // shapeRef1717
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6055.1, 3534.51);
+ polygon.ps[1] = Point(6055.1, 3596.51);
+ polygon.ps[2] = Point(5993.1, 3596.51);
+ polygon.ps[3] = Point(5993.1, 3534.51);
+ new ShapeRef(router, polygon, 1717);
+
+ // shapeRef1718
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5343, 3534.51);
+ polygon.ps[1] = Point(5343, 3596.51);
+ polygon.ps[2] = Point(5281, 3596.51);
+ polygon.ps[3] = Point(5281, 3534.51);
+ new ShapeRef(router, polygon, 1718);
+
+ // shapeRef1719
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6781.1, 6483.51);
+ polygon.ps[1] = Point(6781.1, 6545.51);
+ polygon.ps[2] = Point(6719.1, 6545.51);
+ polygon.ps[3] = Point(6719.1, 6483.51);
+ new ShapeRef(router, polygon, 1719);
+
+ // shapeRef1720
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4980, 7548.79);
+ polygon.ps[1] = Point(4980, 7610.79);
+ polygon.ps[2] = Point(4918, 7610.79);
+ polygon.ps[3] = Point(4918, 7548.79);
+ new ShapeRef(router, polygon, 1720);
+
+ // shapeRef1721
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4980, 8076.79);
+ polygon.ps[1] = Point(4980, 8138.79);
+ polygon.ps[2] = Point(4918, 8138.79);
+ polygon.ps[3] = Point(4918, 8076.79);
+ new ShapeRef(router, polygon, 1721);
+
+ // shapeRef1722
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4980, 8548.99);
+ polygon.ps[1] = Point(4980, 8610.99);
+ polygon.ps[2] = Point(4918, 8610.99);
+ polygon.ps[3] = Point(4918, 8548.99);
+ new ShapeRef(router, polygon, 1722);
+
+ // shapeRef1723
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4980, 9083.42);
+ polygon.ps[1] = Point(4980, 9145.42);
+ polygon.ps[2] = Point(4918, 9145.42);
+ polygon.ps[3] = Point(4918, 9083.42);
+ new ShapeRef(router, polygon, 1723);
+
+ // shapeRef1724
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4980, 9545.42);
+ polygon.ps[1] = Point(4980, 9607.42);
+ polygon.ps[2] = Point(4918, 9607.42);
+ polygon.ps[3] = Point(4918, 9545.42);
+ new ShapeRef(router, polygon, 1724);
+
+ // shapeRef1725
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4320, 9545.42);
+ polygon.ps[1] = Point(4320, 9607.42);
+ polygon.ps[2] = Point(4258, 9607.42);
+ polygon.ps[3] = Point(4258, 9545.42);
+ new ShapeRef(router, polygon, 1725);
+
+ // shapeRef1726
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4320, 10044);
+ polygon.ps[1] = Point(4320, 10106);
+ polygon.ps[2] = Point(4258, 10106);
+ polygon.ps[3] = Point(4258, 10044);
+ new ShapeRef(router, polygon, 1726);
+
+ // shapeRef1727
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4980, 10407);
+ polygon.ps[1] = Point(4980, 10469);
+ polygon.ps[2] = Point(4918, 10469);
+ polygon.ps[3] = Point(4918, 10407);
+ new ShapeRef(router, polygon, 1727);
+
+ // shapeRef1728
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4584, 10407);
+ polygon.ps[1] = Point(4584, 10469);
+ polygon.ps[2] = Point(4522, 10469);
+ polygon.ps[3] = Point(4522, 10407);
+ new ShapeRef(router, polygon, 1728);
+
+ // shapeRef1729
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11394.1, 1249.29);
+ polygon.ps[1] = Point(11394.1, 1311.29);
+ polygon.ps[2] = Point(11332.1, 1311.29);
+ polygon.ps[3] = Point(11332.1, 1249.29);
+ new ShapeRef(router, polygon, 1729);
+
+ // shapeRef1730
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11394.1, 777.091);
+ polygon.ps[1] = Point(11394.1, 839.091);
+ polygon.ps[2] = Point(11332.1, 839.091);
+ polygon.ps[3] = Point(11332.1, 777.091);
+ new ShapeRef(router, polygon, 1730);
+
+ // shapeRef1731
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11394.1, 427.265);
+ polygon.ps[1] = Point(11394.1, 489.265);
+ polygon.ps[2] = Point(11332.1, 489.265);
+ polygon.ps[3] = Point(11332.1, 427.265);
+ new ShapeRef(router, polygon, 1731);
+
+ // shapeRef1732
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11757.1, 427.265);
+ polygon.ps[1] = Point(11757.1, 489.265);
+ polygon.ps[2] = Point(11695.1, 489.265);
+ polygon.ps[3] = Point(11695.1, 427.265);
+ new ShapeRef(router, polygon, 1732);
+
+ // shapeRef1733
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12120.1, 427.265);
+ polygon.ps[1] = Point(12120.1, 489.265);
+ polygon.ps[2] = Point(12058.1, 489.265);
+ polygon.ps[3] = Point(12058.1, 427.265);
+ new ShapeRef(router, polygon, 1733);
+
+ // shapeRef1734
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12887.5, 427.265);
+ polygon.ps[1] = Point(12887.5, 489.265);
+ polygon.ps[2] = Point(12825.5, 489.265);
+ polygon.ps[3] = Point(12825.5, 427.265);
+ new ShapeRef(router, polygon, 1734);
+
+ // shapeRef1735
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12384.1, 612.091);
+ polygon.ps[1] = Point(12384.1, 674.091);
+ polygon.ps[2] = Point(12322.1, 674.091);
+ polygon.ps[3] = Point(12322.1, 612.091);
+ new ShapeRef(router, polygon, 1735);
+
+ // shapeRef1736
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13540, 427.265);
+ polygon.ps[1] = Point(13540, 489.265);
+ polygon.ps[2] = Point(13478, 489.265);
+ polygon.ps[3] = Point(13478, 427.265);
+ new ShapeRef(router, polygon, 1736);
+
+ // shapeRef1737
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14068, 427.265);
+ polygon.ps[1] = Point(14068, 489.265);
+ polygon.ps[2] = Point(14006, 489.265);
+ polygon.ps[3] = Point(14006, 427.265);
+ new ShapeRef(router, polygon, 1737);
+
+ // shapeRef1738
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14596, 427.265);
+ polygon.ps[1] = Point(14596, 489.265);
+ polygon.ps[2] = Point(14534, 489.265);
+ polygon.ps[3] = Point(14534, 427.265);
+ new ShapeRef(router, polygon, 1738);
+
+ // shapeRef1739
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15270.5, 427.265);
+ polygon.ps[1] = Point(15270.5, 489.265);
+ polygon.ps[2] = Point(15208.5, 489.265);
+ polygon.ps[3] = Point(15208.5, 427.265);
+ new ShapeRef(router, polygon, 1739);
+
+ // shapeRef1740
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15998.6, 427.265);
+ polygon.ps[1] = Point(15998.6, 489.265);
+ polygon.ps[2] = Point(15936.6, 489.265);
+ polygon.ps[3] = Point(15936.6, 427.265);
+ new ShapeRef(router, polygon, 1740);
+
+ // shapeRef1741
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16394.6, 427.265);
+ polygon.ps[1] = Point(16394.6, 489.265);
+ polygon.ps[2] = Point(16332.6, 489.265);
+ polygon.ps[3] = Point(16332.6, 427.265);
+ new ShapeRef(router, polygon, 1741);
+
+ // shapeRef1742
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16394.6, 1249.29);
+ polygon.ps[1] = Point(16394.6, 1311.29);
+ polygon.ps[2] = Point(16332.6, 1311.29);
+ polygon.ps[3] = Point(16332.6, 1249.29);
+ new ShapeRef(router, polygon, 1742);
+
+ // shapeRef1743
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18432.5, 11829.9);
+ polygon.ps[1] = Point(18432.5, 11891.9);
+ polygon.ps[2] = Point(18370.5, 11891.9);
+ polygon.ps[3] = Point(18370.5, 11829.9);
+ new ShapeRef(router, polygon, 1743);
+
+ // shapeRef1744
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18661.5, 11829.9);
+ polygon.ps[1] = Point(18661.5, 11891.9);
+ polygon.ps[2] = Point(18599.5, 11891.9);
+ polygon.ps[3] = Point(18599.5, 11829.9);
+ new ShapeRef(router, polygon, 1744);
+
+ // shapeRef1745
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10487.9, 427.265);
+ polygon.ps[1] = Point(10487.9, 489.265);
+ polygon.ps[2] = Point(10425.9, 489.265);
+ polygon.ps[3] = Point(10425.9, 427.265);
+ new ShapeRef(router, polygon, 1745);
+
+ // shapeRef1746
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9202.59, 427.265);
+ polygon.ps[1] = Point(9202.59, 489.265);
+ polygon.ps[2] = Point(9140.59, 489.265);
+ polygon.ps[3] = Point(9140.59, 427.265);
+ new ShapeRef(router, polygon, 1746);
+
+ // shapeRef1747
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8489.29, 282.265);
+ polygon.ps[1] = Point(8489.29, 344.265);
+ polygon.ps[2] = Point(8427.29, 344.265);
+ polygon.ps[3] = Point(8427.29, 282.265);
+ new ShapeRef(router, polygon, 1747);
+
+ // shapeRef1748
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8225.29, 282.265);
+ polygon.ps[1] = Point(8225.29, 344.265);
+ polygon.ps[2] = Point(8163.29, 344.265);
+ polygon.ps[3] = Point(8163.29, 282.265);
+ new ShapeRef(router, polygon, 1748);
+
+ // shapeRef1749
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7895.29, 282.265);
+ polygon.ps[1] = Point(7895.29, 344.265);
+ polygon.ps[2] = Point(7833.29, 344.265);
+ polygon.ps[3] = Point(7833.29, 282.265);
+ new ShapeRef(router, polygon, 1749);
+
+ // shapeRef1750
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8093.29, 394.265);
+ polygon.ps[1] = Point(8093.29, 456.265);
+ polygon.ps[2] = Point(8031.29, 456.265);
+ polygon.ps[3] = Point(8031.29, 394.265);
+ new ShapeRef(router, polygon, 1750);
+
+ // shapeRef1751
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7375.1, 394.265);
+ polygon.ps[1] = Point(7375.1, 456.265);
+ polygon.ps[2] = Point(7313.1, 456.265);
+ polygon.ps[3] = Point(7313.1, 394.265);
+ new ShapeRef(router, polygon, 1751);
+
+ // shapeRef1752
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6649.1, 394.265);
+ polygon.ps[1] = Point(6649.1, 456.265);
+ polygon.ps[2] = Point(6587.1, 456.265);
+ polygon.ps[3] = Point(6587.1, 394.265);
+ new ShapeRef(router, polygon, 1752);
+
+ // shapeRef1753
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6154.1, 394.265);
+ polygon.ps[1] = Point(6154.1, 456.265);
+ polygon.ps[2] = Point(6092.1, 456.265);
+ polygon.ps[3] = Point(6092.1, 394.265);
+ new ShapeRef(router, polygon, 1753);
+
+ // shapeRef1754
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10840.2, 4511.4);
+ polygon.ps[1] = Point(10840.2, 4573.4);
+ polygon.ps[2] = Point(10778.2, 4573.4);
+ polygon.ps[3] = Point(10778.2, 4511.4);
+ new ShapeRef(router, polygon, 1754);
+
+ // shapeRef1755
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15270.5, 711.091);
+ polygon.ps[1] = Point(15270.5, 773.091);
+ polygon.ps[2] = Point(15208.5, 773.091);
+ polygon.ps[3] = Point(15208.5, 711.091);
+ new ShapeRef(router, polygon, 1755);
+
+ // shapeRef1756
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15270.5, 1150.29);
+ polygon.ps[1] = Point(15270.5, 1212.29);
+ polygon.ps[2] = Point(15208.5, 1212.29);
+ polygon.ps[3] = Point(15208.5, 1150.29);
+ new ShapeRef(router, polygon, 1756);
+
+ // shapeRef1757
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5824.1, 4095.51);
+ polygon.ps[1] = Point(5824.1, 4157.51);
+ polygon.ps[2] = Point(5762.1, 4157.51);
+ polygon.ps[3] = Point(5762.1, 4095.51);
+ new ShapeRef(router, polygon, 1757);
+
+ // shapeRef1758
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5343, 5933.59);
+ polygon.ps[1] = Point(5343, 5995.59);
+ polygon.ps[2] = Point(5281, 5995.59);
+ polygon.ps[3] = Point(5281, 5933.59);
+ new ShapeRef(router, polygon, 1758);
+
+ // shapeRef1759
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5343, 4907.4);
+ polygon.ps[1] = Point(5343, 4969.4);
+ polygon.ps[2] = Point(5281, 4969.4);
+ polygon.ps[3] = Point(5281, 4907.4);
+ new ShapeRef(router, polygon, 1759);
+
+ // shapeRef1760
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5343, 4095.51);
+ polygon.ps[1] = Point(5343, 4157.51);
+ polygon.ps[2] = Point(5281, 4157.51);
+ polygon.ps[3] = Point(5281, 4095.51);
+ new ShapeRef(router, polygon, 1760);
+
+ // shapeRef1761
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10147, 10651.3);
+ polygon.ps[1] = Point(10147, 10713.3);
+ polygon.ps[2] = Point(10085, 10713.3);
+ polygon.ps[3] = Point(10085, 10651.3);
+ new ShapeRef(router, polygon, 1761);
+
+ // shapeRef1762
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10741.2, 10651.3);
+ polygon.ps[1] = Point(10741.2, 10713.3);
+ polygon.ps[2] = Point(10679.2, 10713.3);
+ polygon.ps[3] = Point(10679.2, 10651.3);
+ new ShapeRef(router, polygon, 1762);
+
+ // shapeRef1763
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11038.2, 10651.3);
+ polygon.ps[1] = Point(11038.2, 10713.3);
+ polygon.ps[2] = Point(10976.2, 10713.3);
+ polygon.ps[3] = Point(10976.2, 10651.3);
+ new ShapeRef(router, polygon, 1763);
+
+ // shapeRef1764
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6583.1, 7262.4);
+ polygon.ps[1] = Point(6583.1, 7324.4);
+ polygon.ps[2] = Point(6521.1, 7324.4);
+ polygon.ps[3] = Point(6521.1, 7262.4);
+ new ShapeRef(router, polygon, 1764);
+
+ // shapeRef1765
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7243.1, 6998.4);
+ polygon.ps[1] = Point(7243.1, 7060.4);
+ polygon.ps[2] = Point(7181.1, 7060.4);
+ polygon.ps[3] = Point(7181.1, 6998.4);
+ new ShapeRef(router, polygon, 1765);
+
+ // shapeRef1766
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7243.1, 7614.79);
+ polygon.ps[1] = Point(7243.1, 7676.79);
+ polygon.ps[2] = Point(7181.1, 7676.79);
+ polygon.ps[3] = Point(7181.1, 7614.79);
+ new ShapeRef(router, polygon, 1766);
+
+ // shapeRef1767
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7243.1, 9017.42);
+ polygon.ps[1] = Point(7243.1, 9079.42);
+ polygon.ps[2] = Point(7181.1, 9079.42);
+ polygon.ps[3] = Point(7181.1, 9017.42);
+ new ShapeRef(router, polygon, 1767);
+
+ // shapeRef1768
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7243.1, 9380.42);
+ polygon.ps[1] = Point(7243.1, 9442.42);
+ polygon.ps[2] = Point(7181.1, 9442.42);
+ polygon.ps[3] = Point(7181.1, 9380.42);
+ new ShapeRef(router, polygon, 1768);
+
+ // shapeRef1769
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6583.1, 7779.79);
+ polygon.ps[1] = Point(6583.1, 7841.79);
+ polygon.ps[2] = Point(6521.1, 7841.79);
+ polygon.ps[3] = Point(6521.1, 7779.79);
+ new ShapeRef(router, polygon, 1769);
+
+ // shapeRef1770
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6583.1, 8284.99);
+ polygon.ps[1] = Point(6583.1, 8346.99);
+ polygon.ps[2] = Point(6521.1, 8346.99);
+ polygon.ps[3] = Point(6521.1, 8284.99);
+ new ShapeRef(router, polygon, 1770);
+
+ // shapeRef1771
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6583.1, 9512.42);
+ polygon.ps[1] = Point(6583.1, 9574.42);
+ polygon.ps[2] = Point(6521.1, 9574.42);
+ polygon.ps[3] = Point(6521.1, 9512.42);
+ new ShapeRef(router, polygon, 1771);
+
+ // shapeRef1772
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6583.1, 10077);
+ polygon.ps[1] = Point(6583.1, 10139);
+ polygon.ps[2] = Point(6521.1, 10139);
+ polygon.ps[3] = Point(6521.1, 10077);
+ new ShapeRef(router, polygon, 1772);
+
+ // shapeRef1773
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6814.1, 7515.79);
+ polygon.ps[1] = Point(6814.1, 7577.79);
+ polygon.ps[2] = Point(6752.1, 7577.79);
+ polygon.ps[3] = Point(6752.1, 7515.79);
+ new ShapeRef(router, polygon, 1773);
+
+ // shapeRef1774
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7177.1, 6219.51);
+ polygon.ps[1] = Point(7177.1, 6281.51);
+ polygon.ps[2] = Point(7115.1, 6281.51);
+ polygon.ps[3] = Point(7115.1, 6219.51);
+ new ShapeRef(router, polygon, 1774);
+
+ // shapeRef1775
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7796.29, 6483.51);
+ polygon.ps[1] = Point(7796.29, 6545.51);
+ polygon.ps[2] = Point(7734.29, 6545.51);
+ polygon.ps[3] = Point(7734.29, 6483.51);
+ new ShapeRef(router, polygon, 1775);
+
+ // shapeRef1776
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8649.29, 6483.51);
+ polygon.ps[1] = Point(8649.29, 6545.51);
+ polygon.ps[2] = Point(8587.29, 6545.51);
+ polygon.ps[3] = Point(8587.29, 6483.51);
+ new ShapeRef(router, polygon, 1776);
+
+ // shapeRef1777
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6154.1, 7713.79);
+ polygon.ps[1] = Point(6154.1, 7775.79);
+ polygon.ps[2] = Point(6092.1, 7775.79);
+ polygon.ps[3] = Point(6092.1, 7713.79);
+ new ShapeRef(router, polygon, 1777);
+
+ // shapeRef1778
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6154.1, 8251.99);
+ polygon.ps[1] = Point(6154.1, 8313.99);
+ polygon.ps[2] = Point(6092.1, 8313.99);
+ polygon.ps[3] = Point(6092.1, 8251.99);
+ new ShapeRef(router, polygon, 1778);
+
+ // shapeRef1779
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14728, 12261.3);
+ polygon.ps[1] = Point(14728, 12323.3);
+ polygon.ps[2] = Point(14666, 12323.3);
+ polygon.ps[3] = Point(14666, 12261.3);
+ new ShapeRef(router, polygon, 1779);
+
+ // shapeRef1780
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14431, 12261.3);
+ polygon.ps[1] = Point(14431, 12323.3);
+ polygon.ps[2] = Point(14369, 12323.3);
+ polygon.ps[3] = Point(14369, 12261.3);
+ new ShapeRef(router, polygon, 1780);
+
+ // shapeRef1781
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9265.09, 11141.6);
+ polygon.ps[1] = Point(9265.09, 11201.6);
+ polygon.ps[2] = Point(9210.09, 11201.6);
+ polygon.ps[3] = Point(9210.09, 11141.6);
+ new ShapeRef(router, polygon, 1781);
+
+ // shapeRef1782
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8711.79, 11141.6);
+ polygon.ps[1] = Point(8711.79, 11201.6);
+ polygon.ps[2] = Point(8656.79, 11201.6);
+ polygon.ps[3] = Point(8656.79, 11141.6);
+ new ShapeRef(router, polygon, 1782);
+
+ // shapeRef1783
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8048.79, 10993.6);
+ polygon.ps[1] = Point(8048.79, 11033.6);
+ polygon.ps[2] = Point(7973.29, 11033.6);
+ polygon.ps[3] = Point(7973.29, 10993.6);
+ new ShapeRef(router, polygon, 1783);
+
+ // shapeRef1784
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8254.79, 10645.3);
+ polygon.ps[1] = Point(8254.79, 10705.3);
+ polygon.ps[2] = Point(8199.79, 10705.3);
+ polygon.ps[3] = Point(8199.79, 10645.3);
+ new ShapeRef(router, polygon, 1784);
+
+ // shapeRef1785
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8711.79, 10645.3);
+ polygon.ps[1] = Point(8711.79, 10705.3);
+ polygon.ps[2] = Point(8656.79, 10705.3);
+ polygon.ps[3] = Point(8656.79, 10645.3);
+ new ShapeRef(router, polygon, 1785);
+
+ // shapeRef1786
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13326.5, 9176.42);
+ polygon.ps[1] = Point(13326.5, 9236.42);
+ polygon.ps[2] = Point(13271.5, 9236.42);
+ polygon.ps[3] = Point(13271.5, 9176.42);
+ new ShapeRef(router, polygon, 1786);
+
+ // shapeRef1787
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9746.19, 11141.6);
+ polygon.ps[1] = Point(9746.19, 11201.6);
+ polygon.ps[2] = Point(9691.19, 11201.6);
+ polygon.ps[3] = Point(9691.19, 11141.6);
+ new ShapeRef(router, polygon, 1787);
+
+ // shapeRef1788
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10609.2, 11180.6);
+ polygon.ps[1] = Point(10609.2, 11242.6);
+ polygon.ps[2] = Point(10547.2, 11242.6);
+ polygon.ps[3] = Point(10547.2, 11180.6);
+ new ShapeRef(router, polygon, 1788);
+
+ // shapeRef1789
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9980.69, 11180.6);
+ polygon.ps[1] = Point(9980.69, 11242.6);
+ polygon.ps[2] = Point(9918.69, 11242.6);
+ polygon.ps[3] = Point(9918.69, 11180.6);
+ new ShapeRef(router, polygon, 1789);
+
+ // shapeRef1790
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9433.59, 11180.6);
+ polygon.ps[1] = Point(9433.59, 11242.6);
+ polygon.ps[2] = Point(9371.59, 11242.6);
+ polygon.ps[3] = Point(9371.59, 11180.6);
+ new ShapeRef(router, polygon, 1790);
+
+ // shapeRef1791
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9050.99, 11180.6);
+ polygon.ps[1] = Point(9050.99, 11242.6);
+ polygon.ps[2] = Point(8988.99, 11242.6);
+ polygon.ps[3] = Point(8988.99, 11180.6);
+ new ShapeRef(router, polygon, 1791);
+
+ // shapeRef1792
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8423.29, 11180.6);
+ polygon.ps[1] = Point(8423.29, 11242.6);
+ polygon.ps[2] = Point(8361.29, 11242.6);
+ polygon.ps[3] = Point(8361.29, 11180.6);
+ new ShapeRef(router, polygon, 1792);
+
+ // shapeRef1793
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7994.29, 11180.6);
+ polygon.ps[1] = Point(7994.29, 11242.6);
+ polygon.ps[2] = Point(7932.29, 11242.6);
+ polygon.ps[3] = Point(7932.29, 11180.6);
+ new ShapeRef(router, polygon, 1793);
+
+ // shapeRef1794
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7994.29, 10684.3);
+ polygon.ps[1] = Point(7994.29, 10746.3);
+ polygon.ps[2] = Point(7932.29, 10746.3);
+ polygon.ps[3] = Point(7932.29, 10684.3);
+ new ShapeRef(router, polygon, 1794);
+
+ // shapeRef1795
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8423.29, 10684.3);
+ polygon.ps[1] = Point(8423.29, 10746.3);
+ polygon.ps[2] = Point(8361.29, 10746.3);
+ polygon.ps[3] = Point(8361.29, 10684.3);
+ new ShapeRef(router, polygon, 1795);
+
+ // shapeRef1796
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9050.99, 10684.3);
+ polygon.ps[1] = Point(9050.99, 10746.3);
+ polygon.ps[2] = Point(8988.99, 10746.3);
+ polygon.ps[3] = Point(8988.99, 10684.3);
+ new ShapeRef(router, polygon, 1796);
+
+ // shapeRef1797
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8800.89, 11984.3);
+ polygon.ps[1] = Point(8800.89, 12046.3);
+ polygon.ps[2] = Point(8738.89, 12046.3);
+ polygon.ps[3] = Point(8738.89, 11984.3);
+ new ShapeRef(router, polygon, 1797);
+
+ // shapeRef1798
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6220.1, 183.265);
+ polygon.ps[1] = Point(6220.1, 245.265);
+ polygon.ps[2] = Point(6158.1, 245.265);
+ polygon.ps[3] = Point(6158.1, 183.265);
+ new ShapeRef(router, polygon, 1798);
+
+ // shapeRef1799
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5956.1, 183.265);
+ polygon.ps[1] = Point(5956.1, 245.265);
+ polygon.ps[2] = Point(5894.1, 245.265);
+ polygon.ps[3] = Point(5894.1, 183.265);
+ new ShapeRef(router, polygon, 1799);
+
+ // shapeRef1800
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7796.29, 1117.29);
+ polygon.ps[1] = Point(7796.29, 1179.29);
+ polygon.ps[2] = Point(7734.29, 1179.29);
+ polygon.ps[3] = Point(7734.29, 1117.29);
+ new ShapeRef(router, polygon, 1800);
+
+ // shapeRef1801
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8419.79, 5442.67);
+ polygon.ps[1] = Point(8419.79, 5502.67);
+ polygon.ps[2] = Point(8364.79, 5502.67);
+ polygon.ps[3] = Point(8364.79, 5442.67);
+ new ShapeRef(router, polygon, 1801);
+
+ // shapeRef1802
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8866.89, 5481.67);
+ polygon.ps[1] = Point(8866.89, 5543.67);
+ polygon.ps[2] = Point(8804.89, 5543.67);
+ polygon.ps[3] = Point(8804.89, 5481.67);
+ new ShapeRef(router, polygon, 1802);
+
+ // shapeRef1803
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8126.29, 5481.67);
+ polygon.ps[1] = Point(8126.29, 5543.67);
+ polygon.ps[2] = Point(8064.29, 5543.67);
+ polygon.ps[3] = Point(8064.29, 5481.67);
+ new ShapeRef(router, polygon, 1803);
+
+ // shapeRef1804
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17241, 7204.4);
+ polygon.ps[1] = Point(17241, 7264.4);
+ polygon.ps[2] = Point(17186, 7264.4);
+ polygon.ps[3] = Point(17186, 7204.4);
+ new ShapeRef(router, polygon, 1804);
+
+ // shapeRef1805
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17083.8, 7394.4);
+ polygon.ps[1] = Point(17083.8, 7456.4);
+ polygon.ps[2] = Point(17021.8, 7456.4);
+ polygon.ps[3] = Point(17021.8, 7394.4);
+ new ShapeRef(router, polygon, 1805);
+
+ // shapeRef1806
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17083.8, 7031.4);
+ polygon.ps[1] = Point(17083.8, 7093.4);
+ polygon.ps[2] = Point(17021.8, 7093.4);
+ polygon.ps[3] = Point(17021.8, 7031.4);
+ new ShapeRef(router, polygon, 1806);
+
+ // shapeRef1807
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10454.9, 6516.51);
+ polygon.ps[1] = Point(10454.9, 6578.51);
+ polygon.ps[2] = Point(10392.9, 6578.51);
+ polygon.ps[3] = Point(10392.9, 6516.51);
+ new ShapeRef(router, polygon, 1807);
+
+ // shapeRef1808
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4584, 5933.59);
+ polygon.ps[1] = Point(4584, 5995.59);
+ polygon.ps[2] = Point(4522, 5995.59);
+ polygon.ps[3] = Point(4522, 5933.59);
+ new ShapeRef(router, polygon, 1808);
+
+ // shapeRef1809
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11394.1, 2812.29);
+ polygon.ps[1] = Point(11394.1, 2874.29);
+ polygon.ps[2] = Point(11332.1, 2874.29);
+ polygon.ps[3] = Point(11332.1, 2812.29);
+ new ShapeRef(router, polygon, 1809);
+
+ // shapeRef1810
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11394.1, 3666.51);
+ polygon.ps[1] = Point(11394.1, 3728.51);
+ polygon.ps[2] = Point(11332.1, 3728.51);
+ polygon.ps[3] = Point(11332.1, 3666.51);
+ new ShapeRef(router, polygon, 1810);
+
+ // shapeRef1811
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11394.1, 5138.4);
+ polygon.ps[1] = Point(11394.1, 5200.4);
+ polygon.ps[2] = Point(11332.1, 5200.4);
+ polygon.ps[3] = Point(11332.1, 5138.4);
+ new ShapeRef(router, polygon, 1811);
+
+ // shapeRef1812
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11394.1, 5725.9);
+ polygon.ps[1] = Point(11394.1, 5787.9);
+ polygon.ps[2] = Point(11332.1, 5787.9);
+ polygon.ps[3] = Point(11332.1, 5725.9);
+ new ShapeRef(router, polygon, 1812);
+
+ // shapeRef1813
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11394.1, 7548.79);
+ polygon.ps[1] = Point(11394.1, 7610.79);
+ polygon.ps[2] = Point(11332.1, 7610.79);
+ polygon.ps[3] = Point(11332.1, 7548.79);
+ new ShapeRef(router, polygon, 1813);
+
+ // shapeRef1814
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11394.1, 9182.42);
+ polygon.ps[1] = Point(11394.1, 9244.42);
+ polygon.ps[2] = Point(11332.1, 9244.42);
+ polygon.ps[3] = Point(11332.1, 9182.42);
+ new ShapeRef(router, polygon, 1814);
+
+ // shapeRef1815
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11394.1, 10506);
+ polygon.ps[1] = Point(11394.1, 10568);
+ polygon.ps[2] = Point(11332.1, 10568);
+ polygon.ps[3] = Point(11332.1, 10506);
+ new ShapeRef(router, polygon, 1815);
+
+ // shapeRef1816
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11394.1, 12096.3);
+ polygon.ps[1] = Point(11394.1, 12158.3);
+ polygon.ps[2] = Point(11332.1, 12158.3);
+ polygon.ps[3] = Point(11332.1, 12096.3);
+ new ShapeRef(router, polygon, 1816);
+
+ // shapeRef1817
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12562.5, 12096.3);
+ polygon.ps[1] = Point(12562.5, 12158.3);
+ polygon.ps[2] = Point(12500.5, 12158.3);
+ polygon.ps[3] = Point(12500.5, 12096.3);
+ new ShapeRef(router, polygon, 1817);
+
+ // shapeRef1818
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13264, 12096.3);
+ polygon.ps[1] = Point(13264, 12158.3);
+ polygon.ps[2] = Point(13202, 12158.3);
+ polygon.ps[3] = Point(13202, 12096.3);
+ new ShapeRef(router, polygon, 1818);
+
+ // shapeRef1819
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14035, 12261.3);
+ polygon.ps[1] = Point(14035, 12323.3);
+ polygon.ps[2] = Point(13973, 12323.3);
+ polygon.ps[3] = Point(13973, 12261.3);
+ new ShapeRef(router, polygon, 1819);
+
+ // shapeRef1820
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4584, 10717.3);
+ polygon.ps[1] = Point(4584, 10779.3);
+ polygon.ps[2] = Point(4522, 10779.3);
+ polygon.ps[3] = Point(4522, 10717.3);
+ new ShapeRef(router, polygon, 1820);
+
+ // shapeRef1821
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7924.79, 1210.29);
+ polygon.ps[1] = Point(7924.79, 1270.29);
+ polygon.ps[2] = Point(7869.79, 1270.29);
+ polygon.ps[3] = Point(7869.79, 1210.29);
+ new ShapeRef(router, polygon, 1821);
+
+ // shapeRef1822
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7693.6, 1392.29);
+ polygon.ps[1] = Point(7693.6, 1432.29);
+ polygon.ps[2] = Point(7618.1, 1432.29);
+ polygon.ps[3] = Point(7618.1, 1392.29);
+ new ShapeRef(router, polygon, 1822);
+
+ // shapeRef1823
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8192.29, 1249.29);
+ polygon.ps[1] = Point(8192.29, 1311.29);
+ polygon.ps[2] = Point(8130.29, 1311.29);
+ polygon.ps[3] = Point(8130.29, 1249.29);
+ new ShapeRef(router, polygon, 1823);
+
+ // shapeRef1824
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7639.1, 1249.29);
+ polygon.ps[1] = Point(7639.1, 1311.29);
+ polygon.ps[2] = Point(7577.1, 1311.29);
+ polygon.ps[3] = Point(7577.1, 1249.29);
+ new ShapeRef(router, polygon, 1824);
+
+ // shapeRef1825
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7639.1, 1579.29);
+ polygon.ps[1] = Point(7639.1, 1641.29);
+ polygon.ps[2] = Point(7577.1, 1641.29);
+ polygon.ps[3] = Point(7577.1, 1579.29);
+ new ShapeRef(router, polygon, 1825);
+
+ // shapeRef1826
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7639.1, 2746.29);
+ polygon.ps[1] = Point(7639.1, 2808.29);
+ polygon.ps[2] = Point(7577.1, 2808.29);
+ polygon.ps[3] = Point(7577.1, 2746.29);
+ new ShapeRef(router, polygon, 1826);
+
+ // shapeRef1827
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7639.1, 3175.29);
+ polygon.ps[1] = Point(7639.1, 3237.29);
+ polygon.ps[2] = Point(7577.1, 3237.29);
+ polygon.ps[3] = Point(7577.1, 3175.29);
+ new ShapeRef(router, polygon, 1827);
+
+ // shapeRef1828
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15014.4, 1111.29);
+ polygon.ps[1] = Point(15014.4, 1171.29);
+ polygon.ps[2] = Point(14959.4, 1171.29);
+ polygon.ps[3] = Point(14959.4, 1111.29);
+ new ShapeRef(router, polygon, 1828);
+
+ // shapeRef1829
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16229.6, 11601.9);
+ polygon.ps[1] = Point(16229.6, 11663.9);
+ polygon.ps[2] = Point(16167.6, 11663.9);
+ polygon.ps[3] = Point(16167.6, 11601.9);
+ new ShapeRef(router, polygon, 1829);
+
+ // shapeRef1830
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15899.6, 11601.9);
+ polygon.ps[1] = Point(15899.6, 11663.9);
+ polygon.ps[2] = Point(15837.6, 11663.9);
+ polygon.ps[3] = Point(15837.6, 11601.9);
+ new ShapeRef(router, polygon, 1830);
+
+ // shapeRef1831
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9268.59, 12427.7);
+ polygon.ps[1] = Point(9268.59, 12489.7);
+ polygon.ps[2] = Point(9206.59, 12489.7);
+ polygon.ps[3] = Point(9206.59, 12427.7);
+ new ShapeRef(router, polygon, 1831);
+
+ // shapeRef1832
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16229.6, 11951.3);
+ polygon.ps[1] = Point(16229.6, 12013.3);
+ polygon.ps[2] = Point(16167.6, 12013.3);
+ polygon.ps[3] = Point(16167.6, 11951.3);
+ new ShapeRef(router, polygon, 1832);
+
+ // shapeRef1833
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16588.8, 11951.3);
+ polygon.ps[1] = Point(16588.8, 12013.3);
+ polygon.ps[2] = Point(16526.8, 12013.3);
+ polygon.ps[3] = Point(16526.8, 11951.3);
+ new ShapeRef(router, polygon, 1833);
+
+ // shapeRef1834
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16819.8, 12427.7);
+ polygon.ps[1] = Point(16819.8, 12489.7);
+ polygon.ps[2] = Point(16757.8, 12489.7);
+ polygon.ps[3] = Point(16757.8, 12427.7);
+ new ShapeRef(router, polygon, 1834);
+
+ // shapeRef1835
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1746, 4742.4);
+ polygon.ps[1] = Point(1746, 4804.4);
+ polygon.ps[2] = Point(1684, 4804.4);
+ polygon.ps[3] = Point(1684, 4742.4);
+ new ShapeRef(router, polygon, 1835);
+
+ // shapeRef1836
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(2868, 4742.4);
+ polygon.ps[1] = Point(2868, 4804.4);
+ polygon.ps[2] = Point(2806, 4804.4);
+ polygon.ps[3] = Point(2806, 4742.4);
+ new ShapeRef(router, polygon, 1836);
+
+ // shapeRef1837
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3264, 4742.4);
+ polygon.ps[1] = Point(3264, 4804.4);
+ polygon.ps[2] = Point(3202, 4804.4);
+ polygon.ps[3] = Point(3202, 4742.4);
+ new ShapeRef(router, polygon, 1837);
+
+ // shapeRef1838
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1416, 4742.4);
+ polygon.ps[1] = Point(1416, 4804.4);
+ polygon.ps[2] = Point(1354, 4804.4);
+ polygon.ps[3] = Point(1354, 4742.4);
+ new ShapeRef(router, polygon, 1838);
+
+ // shapeRef1839
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4980, 6582.51);
+ polygon.ps[1] = Point(4980, 6644.51);
+ polygon.ps[2] = Point(4918, 6644.51);
+ polygon.ps[3] = Point(4918, 6582.51);
+ new ShapeRef(router, polygon, 1839);
+
+ // shapeRef1840
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6022.1, 6351.51);
+ polygon.ps[1] = Point(6022.1, 6413.51);
+ polygon.ps[2] = Point(5960.1, 6413.51);
+ polygon.ps[3] = Point(5960.1, 6351.51);
+ new ShapeRef(router, polygon, 1840);
+
+ // shapeRef1841
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7982.79, 7058.4);
+ polygon.ps[1] = Point(7982.79, 7118.4);
+ polygon.ps[2] = Point(7927.79, 7118.4);
+ polygon.ps[3] = Point(7927.79, 7058.4);
+ new ShapeRef(router, polygon, 1841);
+
+ // shapeRef1842
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7796.29, 7394.4);
+ polygon.ps[1] = Point(7796.29, 7456.4);
+ polygon.ps[2] = Point(7734.29, 7456.4);
+ polygon.ps[3] = Point(7734.29, 7394.4);
+ new ShapeRef(router, polygon, 1842);
+
+ // shapeRef1843
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8324.29, 6823.21);
+ polygon.ps[1] = Point(8324.29, 6885.21);
+ polygon.ps[2] = Point(8262.29, 6885.21);
+ polygon.ps[3] = Point(8262.29, 6823.21);
+ new ShapeRef(router, polygon, 1843);
+
+ // shapeRef1844
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13297, 3600.51);
+ polygon.ps[1] = Point(13297, 3662.51);
+ polygon.ps[2] = Point(13235, 3662.51);
+ polygon.ps[3] = Point(13235, 3600.51);
+ new ShapeRef(router, polygon, 1844);
+
+ // shapeRef1845
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8452.79, 2038.29);
+ polygon.ps[1] = Point(8452.79, 2098.29);
+ polygon.ps[2] = Point(8397.79, 2098.29);
+ polygon.ps[3] = Point(8397.79, 2038.29);
+ new ShapeRef(router, polygon, 1845);
+
+ // shapeRef1846
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8866.89, 2077.29);
+ polygon.ps[1] = Point(8866.89, 2139.29);
+ polygon.ps[2] = Point(8804.89, 2139.29);
+ polygon.ps[3] = Point(8804.89, 2077.29);
+ new ShapeRef(router, polygon, 1846);
+
+ // shapeRef1847
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8192.29, 2077.29);
+ polygon.ps[1] = Point(8192.29, 2139.29);
+ polygon.ps[2] = Point(8130.29, 2139.29);
+ polygon.ps[3] = Point(8130.29, 2077.29);
+ new ShapeRef(router, polygon, 1847);
+
+ // shapeRef1848
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5013, 5316.67);
+ polygon.ps[1] = Point(5013, 5378.67);
+ polygon.ps[2] = Point(4951, 5378.67);
+ polygon.ps[3] = Point(4951, 5316.67);
+ new ShapeRef(router, polygon, 1848);
+
+ // shapeRef1849
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5791.1, 7295.4);
+ polygon.ps[1] = Point(5791.1, 7357.4);
+ polygon.ps[2] = Point(5729.1, 7357.4);
+ polygon.ps[3] = Point(5729.1, 7295.4);
+ new ShapeRef(router, polygon, 1849);
+
+ // shapeRef1850
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(686.5, 1689.29);
+ polygon.ps[1] = Point(686.5, 1729.29);
+ polygon.ps[2] = Point(631.5, 1729.29);
+ polygon.ps[3] = Point(631.5, 1689.29);
+ new ShapeRef(router, polygon, 1850);
+
+ // shapeRef1851
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7470.6, 12239.3);
+ polygon.ps[1] = Point(7470.6, 12279.3);
+ polygon.ps[2] = Point(7415.6, 12279.3);
+ polygon.ps[3] = Point(7415.6, 12239.3);
+ new ShapeRef(router, polygon, 1851);
+
+ // shapeRef1852
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4279, 9877.02);
+ polygon.ps[1] = Point(4279, 9961.11);
+ polygon.ps[2] = Point(4232.77, 9961.11);
+ polygon.ps[3] = Point(4232.77, 9877.02);
+ new ShapeRef(router, polygon, 1852);
+
+ // shapeRef1853
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8014.39, 7138.4);
+ polygon.ps[1] = Point(8014.39, 7184.64);
+ polygon.ps[2] = Point(7930.29, 7184.64);
+ polygon.ps[3] = Point(7930.29, 7138.4);
+ new ShapeRef(router, polygon, 1853);
+
+ // shapeRef1854
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7990.86, 7138.4);
+ polygon.ps[1] = Point(7990.86, 7210);
+ polygon.ps[2] = Point(7930.29, 7210);
+ polygon.ps[3] = Point(7930.29, 7138.4);
+ new ShapeRef(router, polygon, 1854);
+
+ // shapeRef1855
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7932.79, 7058.4);
+ polygon.ps[1] = Point(7932.79, 7118.4);
+ polygon.ps[2] = Point(7877.79, 7118.4);
+ polygon.ps[3] = Point(7877.79, 7058.4);
+ new ShapeRef(router, polygon, 1855);
+
+ // shapeRef1856
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8735.39, 4202.51);
+ polygon.ps[1] = Point(8735.39, 4248.75);
+ polygon.ps[2] = Point(8651.29, 4248.75);
+ polygon.ps[3] = Point(8651.29, 4202.51);
+ new ShapeRef(router, polygon, 1856);
+
+ // shapeRef1857
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9138.59, 6161.51);
+ polygon.ps[1] = Point(9138.59, 6206.21);
+ polygon.ps[2] = Point(9080.36, 6206.21);
+ polygon.ps[3] = Point(9080.36, 6161.51);
+ new ShapeRef(router, polygon, 1857);
+
+ // shapeRef1858
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9191.09, 6081.51);
+ polygon.ps[1] = Point(9191.09, 6141.51);
+ polygon.ps[2] = Point(9136.09, 6141.51);
+ polygon.ps[3] = Point(9136.09, 6081.51);
+ new ShapeRef(router, polygon, 1858);
+
+ // shapeRef1859
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15229.5, 1288.06);
+ polygon.ps[1] = Point(15229.5, 1346.29);
+ polygon.ps[2] = Point(15184.8, 1346.29);
+ polygon.ps[3] = Point(15184.8, 1288.06);
+ new ShapeRef(router, polygon, 1859);
+
+ // shapeRef1860
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14782.5, 1276.29);
+ polygon.ps[1] = Point(14782.5, 1336.29);
+ polygon.ps[2] = Point(14727.5, 1336.29);
+ polygon.ps[3] = Point(14727.5, 1276.29);
+ new ShapeRef(router, polygon, 1860);
+
+ // shapeRef1861
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9655.19, 6114.51);
+ polygon.ps[1] = Point(9655.19, 6174.51);
+ polygon.ps[2] = Point(9600.19, 6174.51);
+ polygon.ps[3] = Point(9600.19, 6114.51);
+ new ShapeRef(router, polygon, 1861);
+
+ // shapeRef1862
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9870.19, 7091.4);
+ polygon.ps[1] = Point(9870.19, 7151.4);
+ polygon.ps[2] = Point(9815.19, 7151.4);
+ polygon.ps[3] = Point(9815.19, 7091.4);
+ new ShapeRef(router, polygon, 1862);
+
+ // shapeRef1863
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4939, 8807.22);
+ polygon.ps[1] = Point(4939, 8867.78);
+ polygon.ps[2] = Point(4867.4, 8867.78);
+ polygon.ps[3] = Point(4867.4, 8807.22);
+ new ShapeRef(router, polygon, 1863);
+
+ // shapeRef1864
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7565.1, 9023.19);
+ polygon.ps[1] = Point(7565.1, 9081.42);
+ polygon.ps[2] = Point(7520.4, 9081.42);
+ polygon.ps[3] = Point(7520.4, 9023.19);
+ new ShapeRef(router, polygon, 1864);
+
+ // shapeRef1865
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7171.33, 10250);
+ polygon.ps[1] = Point(7171.33, 10294.7);
+ polygon.ps[2] = Point(7113.1, 10294.7);
+ polygon.ps[3] = Point(7113.1, 10250);
+ new ShapeRef(router, polygon, 1865);
+
+ // shapeRef1866
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8227.29, 9685.42);
+ polygon.ps[1] = Point(8227.29, 9731.65);
+ polygon.ps[2] = Point(8143.2, 9731.65);
+ polygon.ps[3] = Point(8143.2, 9685.42);
+ new ShapeRef(router, polygon, 1866);
+
+ // shapeRef1867
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8311.39, 9685.42);
+ polygon.ps[1] = Point(8311.39, 9731.65);
+ polygon.ps[2] = Point(8227.29, 9731.65);
+ polygon.ps[3] = Point(8227.29, 9685.42);
+ new ShapeRef(router, polygon, 1867);
+
+ // shapeRef1868
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8279.79, 9605.42);
+ polygon.ps[1] = Point(8279.79, 9665.42);
+ polygon.ps[2] = Point(8224.79, 9665.42);
+ polygon.ps[3] = Point(8224.79, 9605.42);
+ new ShapeRef(router, polygon, 1868);
+
+ // shapeRef1869
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8326.29, 9854.02);
+ polygon.ps[1] = Point(8326.29, 9900.25);
+ polygon.ps[2] = Point(8242.2, 9900.25);
+ polygon.ps[3] = Point(8242.2, 9854.02);
+ new ShapeRef(router, polygon, 1869);
+
+ // shapeRef1870
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8410.39, 9854.02);
+ polygon.ps[1] = Point(8410.39, 9900.25);
+ polygon.ps[2] = Point(8326.29, 9900.25);
+ polygon.ps[3] = Point(8326.29, 9854.02);
+ new ShapeRef(router, polygon, 1870);
+
+ // shapeRef1871
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9369.59, 9652.42);
+ polygon.ps[1] = Point(9369.59, 9699.2);
+ polygon.ps[2] = Point(9261.33, 9699.2);
+ polygon.ps[3] = Point(9261.33, 9652.42);
+ new ShapeRef(router, polygon, 1871);
+
+ // shapeRef1872
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(253, 40);
+ polygon.ps[1] = Point(253, 148.265);
+ polygon.ps[2] = Point(206.215, 148.265);
+ polygon.ps[3] = Point(206.215, 40);
+ new ShapeRef(router, polygon, 1872);
+
+ // shapeRef1873
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10314.9, 9360.32);
+ polygon.ps[1] = Point(10314.9, 9444.42);
+ polygon.ps[2] = Point(10268.7, 9444.42);
+ polygon.ps[3] = Point(10268.7, 9360.32);
+ new ShapeRef(router, polygon, 1873);
+
+ // shapeRef1874
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8792.89, 10075);
+ polygon.ps[1] = Point(8792.89, 10133.2);
+ polygon.ps[2] = Point(8748.2, 10133.2);
+ polygon.ps[3] = Point(8748.2, 10075);
+ new ShapeRef(router, polygon, 1874);
+
+ // shapeRef1875
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5302, 5169.4);
+ polygon.ps[1] = Point(5302, 5253.5);
+ polygon.ps[2] = Point(5255.77, 5253.5);
+ polygon.ps[3] = Point(5255.77, 5169.4);
+ new ShapeRef(router, polygon, 1875);
+
+ // shapeRef1876
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10667.2, 8579.99);
+ polygon.ps[1] = Point(10667.2, 8664.09);
+ polygon.ps[2] = Point(10621, 8664.09);
+ polygon.ps[3] = Point(10621, 8579.99);
+ new ShapeRef(router, polygon, 1876);
+
+ // shapeRef1877
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10416.1, 10791.3);
+ polygon.ps[1] = Point(10416.1, 10836);
+ polygon.ps[2] = Point(10357.9, 10836);
+ polygon.ps[3] = Point(10357.9, 10791.3);
+ new ShapeRef(router, polygon, 1877);
+
+ // shapeRef1878
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9138.49, 8348.99);
+ polygon.ps[1] = Point(9138.49, 8388.99);
+ polygon.ps[2] = Point(9062.99, 8388.99);
+ polygon.ps[3] = Point(9062.99, 8348.99);
+ new ShapeRef(router, polygon, 1878);
+
+ // shapeRef1879
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9194.59, 11614.8);
+ polygon.ps[1] = Point(9194.59, 11698.9);
+ polygon.ps[2] = Point(9148.36, 11698.9);
+ polygon.ps[3] = Point(9148.36, 11614.8);
+ new ShapeRef(router, polygon, 1879);
+
+ // shapeRef1880
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9336.59, 5457.98);
+ polygon.ps[1] = Point(9336.59, 5502.67);
+ polygon.ps[2] = Point(9278.36, 5502.67);
+ polygon.ps[3] = Point(9278.36, 5457.98);
+ new ShapeRef(router, polygon, 1880);
+
+ // shapeRef1881
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8921.39, 2378.79);
+ polygon.ps[1] = Point(8921.39, 2418.79);
+ polygon.ps[2] = Point(8845.89, 2418.79);
+ polygon.ps[3] = Point(8845.89, 2378.79);
+ new ShapeRef(router, polygon, 1881);
+
+ // shapeRef1882
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9155.49, 2361.29);
+ polygon.ps[1] = Point(9155.49, 2401.29);
+ polygon.ps[2] = Point(9029.99, 2401.29);
+ polygon.ps[3] = Point(9029.99, 2361.29);
+ new ShapeRef(router, polygon, 1882);
+
+ // shapeRef1883
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8670.79, 1488.29);
+ polygon.ps[1] = Point(8670.79, 1548.29);
+ polygon.ps[2] = Point(8615.79, 1548.29);
+ polygon.ps[3] = Point(8615.79, 1488.29);
+ new ShapeRef(router, polygon, 1883);
+
+ // shapeRef1884
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15117.8, 1356.29);
+ polygon.ps[1] = Point(15117.8, 1416.29);
+ polygon.ps[2] = Point(15062.8, 1416.29);
+ polygon.ps[3] = Point(15062.8, 1356.29);
+ new ShapeRef(router, polygon, 1884);
+
+ // shapeRef1885
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8318.52, 818.091);
+ polygon.ps[1] = Point(8318.52, 862.785);
+ polygon.ps[2] = Point(8260.29, 862.785);
+ polygon.ps[3] = Point(8260.29, 818.091);
+ new ShapeRef(router, polygon, 1885);
+
+ // shapeRef1886
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8250.29, 914.785);
+ polygon.ps[1] = Point(8250.29, 954.785);
+ polygon.ps[2] = Point(8174.79, 954.785);
+ polygon.ps[3] = Point(8174.79, 914.785);
+ new ShapeRef(router, polygon, 1886);
+
+ // shapeRef1887
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9039.49, 738.091);
+ polygon.ps[1] = Point(9039.49, 798.091);
+ polygon.ps[2] = Point(8984.49, 798.091);
+ polygon.ps[3] = Point(8984.49, 738.091);
+ new ShapeRef(router, polygon, 1887);
+
+ // shapeRef1888
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12617, 4968.9);
+ polygon.ps[1] = Point(12617, 5008.9);
+ polygon.ps[2] = Point(12541.5, 5008.9);
+ polygon.ps[3] = Point(12541.5, 4968.9);
+ new ShapeRef(router, polygon, 1888);
+
+ // shapeRef1889
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12521.5, 5206.4);
+ polygon.ps[1] = Point(12521.5, 5314.67);
+ polygon.ps[2] = Point(12474.7, 5314.67);
+ polygon.ps[3] = Point(12474.7, 5206.4);
+ new ShapeRef(router, polygon, 1889);
+
+ // shapeRef1890
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12617, 5277.17);
+ polygon.ps[1] = Point(12617, 5317.17);
+ polygon.ps[2] = Point(12541.5, 5317.17);
+ polygon.ps[3] = Point(12541.5, 5277.17);
+ new ShapeRef(router, polygon, 1890);
+
+ // shapeRef1891
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12749.7, 5259.98);
+ polygon.ps[1] = Point(12749.7, 5304.67);
+ polygon.ps[2] = Point(12691.5, 5304.67);
+ polygon.ps[3] = Point(12691.5, 5259.98);
+ new ShapeRef(router, polygon, 1891);
+
+ // shapeRef1892
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12694, 5324.67);
+ polygon.ps[1] = Point(12694, 5384.67);
+ polygon.ps[2] = Point(12639, 5384.67);
+ polygon.ps[3] = Point(12639, 5324.67);
+ new ShapeRef(router, polygon, 1892);
+
+ // shapeRef1893
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13401.5, 3842.51);
+ polygon.ps[1] = Point(13401.5, 3882.51);
+ polygon.ps[2] = Point(13276, 3882.51);
+ polygon.ps[3] = Point(13276, 3842.51);
+ new ShapeRef(router, polygon, 1893);
+
+ // shapeRef1894
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13351.5, 3862.51);
+ polygon.ps[1] = Point(13351.5, 3902.51);
+ polygon.ps[2] = Point(13276, 3902.51);
+ polygon.ps[3] = Point(13276, 3862.51);
+ new ShapeRef(router, polygon, 1894);
+
+ // shapeRef1895
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12925, 4439.4);
+ polygon.ps[1] = Point(12925, 4499.4);
+ polygon.ps[2] = Point(12870, 4499.4);
+ polygon.ps[3] = Point(12870, 4439.4);
+ new ShapeRef(router, polygon, 1895);
+
+ // shapeRef1896
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11353.1, 1478.29);
+ polygon.ps[1] = Point(11353.1, 1562.38);
+ polygon.ps[2] = Point(11306.9, 1562.38);
+ polygon.ps[3] = Point(11306.9, 1478.29);
+ new ShapeRef(router, polygon, 1896);
+
+ // shapeRef1897
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12075.6, 1739.79);
+ polygon.ps[1] = Point(12075.6, 1779.79);
+ polygon.ps[2] = Point(12000.1, 1779.79);
+ polygon.ps[3] = Point(12000.1, 1739.79);
+ new ShapeRef(router, polygon, 1897);
+
+ // shapeRef1898
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12157.6, 1672.29);
+ polygon.ps[1] = Point(12157.6, 1732.29);
+ polygon.ps[2] = Point(12102.6, 1732.29);
+ polygon.ps[3] = Point(12102.6, 1672.29);
+ new ShapeRef(router, polygon, 1898);
+
+ // shapeRef1899
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13957.5, 8410.49);
+ polygon.ps[1] = Point(13957.5, 8450.49);
+ polygon.ps[2] = Point(13882, 8450.49);
+ polygon.ps[3] = Point(13882, 8410.49);
+ new ShapeRef(router, polygon, 1899);
+
+ // shapeRef1900
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8703.79, 4122.51);
+ polygon.ps[1] = Point(8703.79, 4182.51);
+ polygon.ps[2] = Point(8648.79, 4182.51);
+ polygon.ps[3] = Point(8648.79, 4122.51);
+ new ShapeRef(router, polygon, 1900);
+
+ // shapeRef1901
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6841.33, 3575.51);
+ polygon.ps[1] = Point(6841.33, 3620.21);
+ polygon.ps[2] = Point(6783.1, 3620.21);
+ polygon.ps[3] = Point(6783.1, 3575.51);
+ new ShapeRef(router, polygon, 1901);
+
+ // shapeRef1902
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5694.1, 3575.51);
+ polygon.ps[1] = Point(5694.1, 3620.21);
+ polygon.ps[2] = Point(5635.87, 3620.21);
+ polygon.ps[3] = Point(5635.87, 3575.51);
+ new ShapeRef(router, polygon, 1902);
+
+ // shapeRef1903
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5302, 3771.29);
+ polygon.ps[1] = Point(5302, 3829.51);
+ polygon.ps[2] = Point(5257.31, 3829.51);
+ polygon.ps[3] = Point(5257.31, 3771.29);
+ new ShapeRef(router, polygon, 1903);
+
+ // shapeRef1904
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5302, 3829.51);
+ polygon.ps[1] = Point(5302, 3890.07);
+ polygon.ps[2] = Point(5230.4, 3890.07);
+ polygon.ps[3] = Point(5230.4, 3829.51);
+ new ShapeRef(router, polygon, 1904);
+
+ // shapeRef1905
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5034.5, 7773.29);
+ polygon.ps[1] = Point(5034.5, 7813.29);
+ polygon.ps[2] = Point(4959, 7813.29);
+ polygon.ps[3] = Point(4959, 7773.29);
+ new ShapeRef(router, polygon, 1905);
+
+ // shapeRef1906
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5034.5, 8381.99);
+ polygon.ps[1] = Point(5034.5, 8421.99);
+ polygon.ps[2] = Point(4959, 8421.99);
+ polygon.ps[3] = Point(4959, 8381.99);
+ new ShapeRef(router, polygon, 1906);
+
+ // shapeRef1907
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4939, 8746.66);
+ polygon.ps[1] = Point(4939, 8807.22);
+ polygon.ps[2] = Point(4867.4, 8807.22);
+ polygon.ps[3] = Point(4867.4, 8746.66);
+ new ShapeRef(router, polygon, 1907);
+
+ // shapeRef1908
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5084.5, 8787.22);
+ polygon.ps[1] = Point(5084.5, 8827.22);
+ polygon.ps[2] = Point(4959, 8827.22);
+ polygon.ps[3] = Point(4959, 8787.22);
+ new ShapeRef(router, polygon, 1908);
+
+ // shapeRef1909
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11353.1, 610.091);
+ polygon.ps[1] = Point(11353.1, 668.318);
+ polygon.ps[2] = Point(11308.4, 668.318);
+ polygon.ps[3] = Point(11308.4, 610.091);
+ new ShapeRef(router, polygon, 1909);
+
+ // shapeRef1910
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11353.1, 551.864);
+ polygon.ps[1] = Point(11353.1, 610.091);
+ polygon.ps[2] = Point(11308.4, 610.091);
+ polygon.ps[3] = Point(11308.4, 551.864);
+ new ShapeRef(router, polygon, 1910);
+
+ // shapeRef1911
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14986.9, 1291.59);
+ polygon.ps[1] = Point(14986.9, 1336.29);
+ polygon.ps[2] = Point(14928.7, 1336.29);
+ polygon.ps[3] = Point(14928.7, 1291.59);
+ new ShapeRef(router, polygon, 1911);
+
+ // shapeRef1912
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15835.6, 1291.59);
+ polygon.ps[1] = Point(15835.6, 1336.29);
+ polygon.ps[2] = Point(15777.4, 1336.29);
+ polygon.ps[3] = Point(15777.4, 1291.59);
+ new ShapeRef(router, polygon, 1912);
+
+ // shapeRef1913
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15838.1, 1356.29);
+ polygon.ps[1] = Point(15838.1, 1416.29);
+ polygon.ps[2] = Point(15783.1, 1416.29);
+ polygon.ps[3] = Point(15783.1, 1356.29);
+ new ShapeRef(router, polygon, 1913);
+
+ // shapeRef1914
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16353.6, 808.091);
+ polygon.ps[1] = Point(16353.6, 866.318);
+ polygon.ps[2] = Point(16308.9, 866.318);
+ polygon.ps[3] = Point(16308.9, 808.091);
+ new ShapeRef(router, polygon, 1914);
+
+ // shapeRef1915
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16449.1, 770.591);
+ polygon.ps[1] = Point(16449.1, 810.591);
+ polygon.ps[2] = Point(16373.6, 810.591);
+ polygon.ps[3] = Point(16373.6, 770.591);
+ new ShapeRef(router, polygon, 1915);
+
+ // shapeRef1916
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16251.1, 770.591);
+ polygon.ps[1] = Point(16251.1, 810.591);
+ polygon.ps[2] = Point(16175.6, 810.591);
+ polygon.ps[3] = Point(16175.6, 770.591);
+ new ShapeRef(router, polygon, 1916);
+
+ // shapeRef1917
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12023.1, 7435.4);
+ polygon.ps[1] = Point(12023.1, 7480.1);
+ polygon.ps[2] = Point(11964.9, 7480.1);
+ polygon.ps[3] = Point(11964.9, 7435.4);
+ new ShapeRef(router, polygon, 1917);
+
+ // shapeRef1918
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17042.8, 7194.4);
+ polygon.ps[1] = Point(17042.8, 7252.63);
+ polygon.ps[2] = Point(16998.1, 7252.63);
+ polygon.ps[3] = Point(16998.1, 7194.4);
+ new ShapeRef(router, polygon, 1918);
+
+ // shapeRef1919
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17138.3, 7156.9);
+ polygon.ps[1] = Point(17138.3, 7196.9);
+ polygon.ps[2] = Point(17062.8, 7196.9);
+ polygon.ps[3] = Point(17062.8, 7156.9);
+ new ShapeRef(router, polygon, 1919);
+
+ // shapeRef1920
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16524.8, 7435.4);
+ polygon.ps[1] = Point(16524.8, 7480.1);
+ polygon.ps[2] = Point(16466.6, 7480.1);
+ polygon.ps[3] = Point(16466.6, 7435.4);
+ new ShapeRef(router, polygon, 1920);
+
+ // shapeRef1921
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16524.8, 7492.1);
+ polygon.ps[1] = Point(16524.8, 7536.79);
+ polygon.ps[2] = Point(16466.6, 7536.79);
+ polygon.ps[3] = Point(16466.6, 7492.1);
+ new ShapeRef(router, polygon, 1921);
+
+ // shapeRef1922
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16583, 7492.1);
+ polygon.ps[1] = Point(16583, 7536.79);
+ polygon.ps[2] = Point(16524.8, 7536.79);
+ polygon.ps[3] = Point(16524.8, 7492.1);
+ new ShapeRef(router, polygon, 1922);
+
+ // shapeRef1923
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18574.3, 11870.9);
+ polygon.ps[1] = Point(18574.3, 11915.6);
+ polygon.ps[2] = Point(18516, 11915.6);
+ polygon.ps[3] = Point(18516, 11870.9);
+ new ShapeRef(router, polygon, 1923);
+
+ // shapeRef1924
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18498.5, 11790.9);
+ polygon.ps[1] = Point(18498.5, 11850.9);
+ polygon.ps[2] = Point(18443.5, 11850.9);
+ polygon.ps[3] = Point(18443.5, 11790.9);
+ new ShapeRef(router, polygon, 1924);
+
+ // shapeRef1925
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18568.5, 11755.9);
+ polygon.ps[1] = Point(18568.5, 11850.9);
+ polygon.ps[2] = Point(18513.5, 11850.9);
+ polygon.ps[3] = Point(18513.5, 11755.9);
+ new ShapeRef(router, polygon, 1925);
+
+ // shapeRef1926
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18518.5, 11755.9);
+ polygon.ps[1] = Point(18518.5, 11850.9);
+ polygon.ps[2] = Point(18463.5, 11850.9);
+ polygon.ps[3] = Point(18463.5, 11755.9);
+ new ShapeRef(router, polygon, 1926);
+
+ // shapeRef1927
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8351.52, 435.265);
+ polygon.ps[1] = Point(8351.52, 479.96);
+ polygon.ps[2] = Point(8293.29, 479.96);
+ polygon.ps[3] = Point(8293.29, 435.265);
+ new ShapeRef(router, polygon, 1927);
+
+ // shapeRef1928
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10894.7, 5620.4);
+ polygon.ps[1] = Point(10894.7, 5660.4);
+ polygon.ps[2] = Point(10819.2, 5660.4);
+ polygon.ps[3] = Point(10819.2, 5620.4);
+ new ShapeRef(router, polygon, 1928);
+
+ // shapeRef1929
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11240.7, 4291.11);
+ polygon.ps[1] = Point(11240.7, 4351.11);
+ polygon.ps[2] = Point(11185.7, 4351.11);
+ polygon.ps[3] = Point(11185.7, 4291.11);
+ new ShapeRef(router, polygon, 1929);
+
+ // shapeRef1930
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11296.4, 4454.71);
+ polygon.ps[1] = Point(11296.4, 4499.4);
+ polygon.ps[2] = Point(11238.2, 4499.4);
+ polygon.ps[3] = Point(11238.2, 4454.71);
+ new ShapeRef(router, polygon, 1930);
+
+ // shapeRef1931
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11238.2, 4454.71);
+ polygon.ps[1] = Point(11238.2, 4499.4);
+ polygon.ps[2] = Point(11180, 4499.4);
+ polygon.ps[3] = Point(11180, 4454.71);
+ new ShapeRef(router, polygon, 1931);
+
+ // shapeRef1932
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11240.7, 4519.4);
+ polygon.ps[1] = Point(11240.7, 4579.4);
+ polygon.ps[2] = Point(11185.7, 4579.4);
+ polygon.ps[3] = Point(11185.7, 4519.4);
+ new ShapeRef(router, polygon, 1932);
+
+ // shapeRef1933
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14650.5, 6576.51);
+ polygon.ps[1] = Point(14650.5, 6636.51);
+ polygon.ps[2] = Point(14595.5, 6636.51);
+ polygon.ps[3] = Point(14595.5, 6576.51);
+ new ShapeRef(router, polygon, 1933);
+
+ // shapeRef1934
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5651.1, 4575.4);
+ polygon.ps[1] = Point(5651.1, 4633.63);
+ polygon.ps[2] = Point(5606.4, 4633.63);
+ polygon.ps[3] = Point(5606.4, 4575.4);
+ new ShapeRef(router, polygon, 1934);
+
+ // shapeRef1935
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18322, 8509.49);
+ polygon.ps[1] = Point(18322, 8549.49);
+ polygon.ps[2] = Point(18246.5, 8549.49);
+ polygon.ps[3] = Point(18246.5, 8509.49);
+ new ShapeRef(router, polygon, 1935);
+
+ // shapeRef1936
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10596.3, 10692.3);
+ polygon.ps[1] = Point(10596.3, 10738.5);
+ polygon.ps[2] = Point(10512.2, 10738.5);
+ polygon.ps[3] = Point(10512.2, 10692.3);
+ new ShapeRef(router, polygon, 1936);
+
+ // shapeRef1937
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10106, 10334.5);
+ polygon.ps[1] = Point(10106, 10374.5);
+ polygon.ps[2] = Point(10030.5, 10374.5);
+ polygon.ps[3] = Point(10030.5, 10334.5);
+ new ShapeRef(router, polygon, 1937);
+
+ // shapeRef1938
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8684.29, 11305.2);
+ polygon.ps[1] = Point(8684.29, 11376.8);
+ polygon.ps[2] = Point(8623.73, 11376.8);
+ polygon.ps[3] = Point(8623.73, 11305.2);
+ new ShapeRef(router, polygon, 1938);
+
+ // shapeRef1939
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7953.29, 11013.6);
+ polygon.ps[1] = Point(7953.29, 11071.9);
+ polygon.ps[2] = Point(7908.6, 11071.9);
+ polygon.ps[3] = Point(7908.6, 11013.6);
+ new ShapeRef(router, polygon, 1939);
+
+ // shapeRef1940
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6637.6, 7577.29);
+ polygon.ps[1] = Point(6637.6, 7617.29);
+ polygon.ps[2] = Point(6562.1, 7617.29);
+ polygon.ps[3] = Point(6562.1, 7577.29);
+ new ShapeRef(router, polygon, 1940);
+
+ // shapeRef1941
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11431.6, 11562.9);
+ polygon.ps[1] = Point(11431.6, 11622.9);
+ polygon.ps[2] = Point(11376.6, 11622.9);
+ polygon.ps[3] = Point(11376.6, 11562.9);
+ new ShapeRef(router, polygon, 1941);
+
+ // shapeRef1942
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16069.1, 11642.9);
+ polygon.ps[1] = Point(16069.1, 11702.9);
+ polygon.ps[2] = Point(16014.1, 11702.9);
+ polygon.ps[3] = Point(16014.1, 11642.9);
+ new ShapeRef(router, polygon, 1942);
+
+ // shapeRef1943
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16152.1, 11510.2);
+ polygon.ps[1] = Point(16152.1, 11550.2);
+ polygon.ps[2] = Point(16076.6, 11550.2);
+ polygon.ps[3] = Point(16076.6, 11510.2);
+ new ShapeRef(router, polygon, 1943);
+
+ // shapeRef1944
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14202, 12435.7);
+ polygon.ps[1] = Point(14202, 12495.7);
+ polygon.ps[2] = Point(14147, 12495.7);
+ polygon.ps[3] = Point(14147, 12435.7);
+ new ShapeRef(router, polygon, 1944);
+
+ // shapeRef1945
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9491.59, 7301.18);
+ polygon.ps[1] = Point(9491.59, 7359.4);
+ polygon.ps[2] = Point(9446.9, 7359.4);
+ polygon.ps[3] = Point(9446.9, 7301.18);
+ new ShapeRef(router, polygon, 1945);
+
+ // shapeRef1946
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9491.59, 7359.4);
+ polygon.ps[1] = Point(9491.59, 7417.63);
+ polygon.ps[2] = Point(9446.9, 7417.63);
+ polygon.ps[3] = Point(9446.9, 7359.4);
+ new ShapeRef(router, polygon, 1946);
+
+ // shapeRef1947
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9587.09, 7321.9);
+ polygon.ps[1] = Point(9587.09, 7361.9);
+ polygon.ps[2] = Point(9511.59, 7361.9);
+ polygon.ps[3] = Point(9511.59, 7321.9);
+ new ShapeRef(router, polygon, 1947);
+
+ // shapeRef1948
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16066.6, 11804.9);
+ polygon.ps[1] = Point(16066.6, 11851.1);
+ polygon.ps[2] = Point(15982.5, 11851.1);
+ polygon.ps[3] = Point(15982.5, 11804.9);
+ new ShapeRef(router, polygon, 1948);
+
+ // shapeRef1949
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15138.3, 10830.5);
+ polygon.ps[1] = Point(15138.3, 10914.6);
+ polygon.ps[2] = Point(15092.1, 10914.6);
+ polygon.ps[3] = Point(15092.1, 10830.5);
+ new ShapeRef(router, polygon, 1949);
+
+ // shapeRef1950
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15233.8, 10912.1);
+ polygon.ps[1] = Point(15233.8, 10952.1);
+ polygon.ps[2] = Point(15158.3, 10952.1);
+ polygon.ps[3] = Point(15158.3, 10912.1);
+ new ShapeRef(router, polygon, 1950);
+
+ // shapeRef1951
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(649, 64.1679);
+ polygon.ps[1] = Point(649, 148.265);
+ polygon.ps[2] = Point(602.765, 148.265);
+ polygon.ps[3] = Point(602.765, 64.1679);
+ new ShapeRef(router, polygon, 1951);
+
+ // shapeRef1952
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15233.8, 11856.4);
+ polygon.ps[1] = Point(15233.8, 11896.4);
+ polygon.ps[2] = Point(15158.3, 11896.4);
+ polygon.ps[3] = Point(15158.3, 11856.4);
+ new ShapeRef(router, polygon, 1952);
+
+ // shapeRef1953
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7982.79, 4405.9);
+ polygon.ps[1] = Point(7982.79, 4445.9);
+ polygon.ps[2] = Point(7907.29, 4445.9);
+ polygon.ps[3] = Point(7907.29, 4405.9);
+ new ShapeRef(router, polygon, 1953);
+
+ // shapeRef1954
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7693.6, 3005.79);
+ polygon.ps[1] = Point(7693.6, 3045.79);
+ polygon.ps[2] = Point(7618.1, 3045.79);
+ polygon.ps[3] = Point(7618.1, 3005.79);
+ new ShapeRef(router, polygon, 1954);
+
+ // shapeRef1955
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10035.2, 9938.52);
+ polygon.ps[1] = Point(10035.2, 9978.52);
+ polygon.ps[2] = Point(9959.69, 9978.52);
+ polygon.ps[3] = Point(9959.69, 9938.52);
+ new ShapeRef(router, polygon, 1955);
+
+ // shapeRef1956
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12975, 12388.7);
+ polygon.ps[1] = Point(12975, 12448.7);
+ polygon.ps[2] = Point(12920, 12448.7);
+ polygon.ps[3] = Point(12920, 12388.7);
+ new ShapeRef(router, polygon, 1956);
+
+ // shapeRef1957
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7946.29, 7118.4);
+ polygon.ps[1] = Point(7946.29, 7138.4);
+ polygon.ps[2] = Point(7914.29, 7138.4);
+ polygon.ps[3] = Point(7914.29, 7118.4);
+ new ShapeRef(router, polygon, 1957);
+
+ // shapeRef1958
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9154.59, 6141.51);
+ polygon.ps[1] = Point(9154.59, 6161.51);
+ polygon.ps[2] = Point(9122.59, 6161.51);
+ polygon.ps[3] = Point(9122.59, 6141.51);
+ new ShapeRef(router, polygon, 1958);
+
+ // shapeRef1959
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9833.69, 7151.4);
+ polygon.ps[1] = Point(9833.69, 7171.4);
+ polygon.ps[2] = Point(9801.69, 7171.4);
+ polygon.ps[3] = Point(9801.69, 7151.4);
+ new ShapeRef(router, polygon, 1959);
+
+ // shapeRef1960
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10466.9, 7860.79);
+ polygon.ps[1] = Point(10466.9, 7892.79);
+ polygon.ps[2] = Point(10446.9, 7892.79);
+ polygon.ps[3] = Point(10446.9, 7860.79);
+ new ShapeRef(router, polygon, 1960);
+
+ // shapeRef1961
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7585.1, 9065.42);
+ polygon.ps[1] = Point(7585.1, 9097.42);
+ polygon.ps[2] = Point(7565.1, 9097.42);
+ polygon.ps[3] = Point(7565.1, 9065.42);
+ new ShapeRef(router, polygon, 1961);
+
+ // shapeRef1962
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15249.5, 1330.29);
+ polygon.ps[1] = Point(15249.5, 1362.29);
+ polygon.ps[2] = Point(15229.5, 1362.29);
+ polygon.ps[3] = Point(15229.5, 1330.29);
+ new ShapeRef(router, polygon, 1962);
+
+ // shapeRef1963
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9385.59, 9632.42);
+ polygon.ps[1] = Point(9385.59, 9652.42);
+ polygon.ps[2] = Point(9353.59, 9652.42);
+ polygon.ps[3] = Point(9353.59, 9632.42);
+ new ShapeRef(router, polygon, 1963);
+
+ // shapeRef1964
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7519.1, 7992.79);
+ polygon.ps[1] = Point(7519.1, 8024.79);
+ polygon.ps[2] = Point(7499.1, 8024.79);
+ polygon.ps[3] = Point(7499.1, 7992.79);
+ new ShapeRef(router, polygon, 1964);
+
+ // shapeRef1965
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10687.2, 8563.99);
+ polygon.ps[1] = Point(10687.2, 8595.99);
+ polygon.ps[2] = Point(10667.2, 8595.99);
+ polygon.ps[3] = Point(10667.2, 8563.99);
+ new ShapeRef(router, polygon, 1965);
+
+ // shapeRef1966
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10522.2, 9131.42);
+ polygon.ps[1] = Point(10522.2, 9163.42);
+ polygon.ps[2] = Point(10502.2, 9163.42);
+ polygon.ps[3] = Point(10502.2, 9131.42);
+ new ShapeRef(router, polygon, 1966);
+
+ // shapeRef1967
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9062.99, 8332.99);
+ polygon.ps[1] = Point(9062.99, 8364.99);
+ polygon.ps[2] = Point(9042.99, 8364.99);
+ polygon.ps[3] = Point(9042.99, 8332.99);
+ new ShapeRef(router, polygon, 1967);
+
+ // shapeRef1968
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8845.89, 4625.4);
+ polygon.ps[1] = Point(8845.89, 4657.4);
+ polygon.ps[2] = Point(8825.89, 4657.4);
+ polygon.ps[3] = Point(8825.89, 4625.4);
+ new ShapeRef(router, polygon, 1968);
+
+ // shapeRef1969
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8845.89, 3945.51);
+ polygon.ps[1] = Point(8845.89, 3977.51);
+ polygon.ps[2] = Point(8825.89, 3977.51);
+ polygon.ps[3] = Point(8825.89, 3945.51);
+ new ShapeRef(router, polygon, 1969);
+
+ // shapeRef1970
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9352.59, 5502.67);
+ polygon.ps[1] = Point(9352.59, 5522.67);
+ polygon.ps[2] = Point(9320.59, 5522.67);
+ polygon.ps[3] = Point(9320.59, 5502.67);
+ new ShapeRef(router, polygon, 1970);
+
+ // shapeRef1971
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8845.89, 3417.51);
+ polygon.ps[1] = Point(8845.89, 3449.51);
+ polygon.ps[2] = Point(8825.89, 3449.51);
+ polygon.ps[3] = Point(8825.89, 3417.51);
+ new ShapeRef(router, polygon, 1971);
+
+ // shapeRef1972
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8845.89, 2893.29);
+ polygon.ps[1] = Point(8845.89, 2925.29);
+ polygon.ps[2] = Point(8825.89, 2925.29);
+ polygon.ps[3] = Point(8825.89, 2893.29);
+ new ShapeRef(router, polygon, 1972);
+
+ // shapeRef1973
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8845.89, 2365.29);
+ polygon.ps[1] = Point(8845.89, 2397.29);
+ polygon.ps[2] = Point(8825.89, 2397.29);
+ polygon.ps[3] = Point(8825.89, 2365.29);
+ new ShapeRef(router, polygon, 1973);
+
+ // shapeRef1974
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8441.29, 2098.29);
+ polygon.ps[1] = Point(8441.29, 2118.29);
+ polygon.ps[2] = Point(8409.29, 2118.29);
+ polygon.ps[3] = Point(8409.29, 2098.29);
+ new ShapeRef(router, polygon, 1974);
+
+ // shapeRef1975
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8441.29, 2140.29);
+ polygon.ps[1] = Point(8441.29, 2160.29);
+ polygon.ps[2] = Point(8409.29, 2160.29);
+ polygon.ps[3] = Point(8409.29, 2140.29);
+ new ShapeRef(router, polygon, 1975);
+
+ // shapeRef1976
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15390.5, 1336.29);
+ polygon.ps[1] = Point(15390.5, 1356.29);
+ polygon.ps[2] = Point(15358.5, 1356.29);
+ polygon.ps[3] = Point(15358.5, 1336.29);
+ new ShapeRef(router, polygon, 1976);
+
+ // shapeRef1977
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8468.29, 1099.29);
+ polygon.ps[1] = Point(8468.29, 1131.29);
+ polygon.ps[2] = Point(8448.29, 1131.29);
+ polygon.ps[3] = Point(8448.29, 1099.29);
+ new ShapeRef(router, polygon, 1977);
+
+ // shapeRef1978
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15131.3, 1336.29);
+ polygon.ps[1] = Point(15131.3, 1356.29);
+ polygon.ps[2] = Point(15099.3, 1356.29);
+ polygon.ps[3] = Point(15099.3, 1336.29);
+ new ShapeRef(router, polygon, 1978);
+
+ // shapeRef1979
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9002.99, 798.091);
+ polygon.ps[1] = Point(9002.99, 818.091);
+ polygon.ps[2] = Point(8970.99, 818.091);
+ polygon.ps[3] = Point(8970.99, 798.091);
+ new ShapeRef(router, polygon, 1979);
+
+ // shapeRef1980
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9002.99, 1105.29);
+ polygon.ps[1] = Point(9002.99, 1125.29);
+ polygon.ps[2] = Point(8970.99, 1125.29);
+ polygon.ps[3] = Point(8970.99, 1105.29);
+ new ShapeRef(router, polygon, 1980);
+
+ // shapeRef1981
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8006.29, 967.285);
+ polygon.ps[1] = Point(8006.29, 999.285);
+ polygon.ps[2] = Point(7986.29, 999.285);
+ polygon.ps[3] = Point(7986.29, 967.285);
+ new ShapeRef(router, polygon, 1981);
+
+ // shapeRef1982
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15493.3, 1336.29);
+ polygon.ps[1] = Point(15493.3, 1356.29);
+ polygon.ps[2] = Point(15461.3, 1356.29);
+ polygon.ps[3] = Point(15461.3, 1336.29);
+ new ShapeRef(router, polygon, 1982);
+
+ // shapeRef1983
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9767.69, 798.091);
+ polygon.ps[1] = Point(9767.69, 818.091);
+ polygon.ps[2] = Point(9735.69, 818.091);
+ polygon.ps[3] = Point(9735.69, 798.091);
+ new ShapeRef(router, polygon, 1983);
+
+ // shapeRef1984
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10792.2, 798.091);
+ polygon.ps[1] = Point(10792.2, 818.091);
+ polygon.ps[2] = Point(10760.2, 818.091);
+ polygon.ps[3] = Point(10760.2, 798.091);
+ new ShapeRef(router, polygon, 1984);
+
+ // shapeRef1985
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10984.2, 1099.29);
+ polygon.ps[1] = Point(10984.2, 1131.29);
+ polygon.ps[2] = Point(10964.2, 1131.29);
+ polygon.ps[3] = Point(10964.2, 1099.29);
+ new ShapeRef(router, polygon, 1985);
+
+ // shapeRef1986
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10792.2, 1270.29);
+ polygon.ps[1] = Point(10792.2, 1290.29);
+ polygon.ps[2] = Point(10760.2, 1290.29);
+ polygon.ps[3] = Point(10760.2, 1270.29);
+ new ShapeRef(router, polygon, 1986);
+
+ // shapeRef1987
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9385.59, 1270.29);
+ polygon.ps[1] = Point(9385.59, 1290.29);
+ polygon.ps[2] = Point(9353.59, 1290.29);
+ polygon.ps[3] = Point(9353.59, 1270.29);
+ new ShapeRef(router, polygon, 1987);
+
+ // shapeRef1988
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9662.69, 1693.29);
+ polygon.ps[1] = Point(9662.69, 1725.29);
+ polygon.ps[2] = Point(9642.69, 1725.29);
+ polygon.ps[3] = Point(9642.69, 1693.29);
+ new ShapeRef(router, polygon, 1988);
+
+ // shapeRef1989
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9319.59, 1999.29);
+ polygon.ps[1] = Point(9319.59, 2019.29);
+ polygon.ps[2] = Point(9287.59, 2019.29);
+ polygon.ps[3] = Point(9287.59, 1999.29);
+ new ShapeRef(router, polygon, 1989);
+
+ // shapeRef1990
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10984.2, 1462.29);
+ polygon.ps[1] = Point(10984.2, 1494.29);
+ polygon.ps[2] = Point(10964.2, 1494.29);
+ polygon.ps[3] = Point(10964.2, 1462.29);
+ new ShapeRef(router, polygon, 1990);
+
+ // shapeRef1991
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11155.2, 1633.29);
+ polygon.ps[1] = Point(11155.2, 1653.29);
+ polygon.ps[2] = Point(11123.2, 1653.29);
+ polygon.ps[3] = Point(11123.2, 1633.29);
+ new ShapeRef(router, polygon, 1991);
+
+ // shapeRef1992
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10984.2, 594.091);
+ polygon.ps[1] = Point(10984.2, 626.091);
+ polygon.ps[2] = Point(10964.2, 626.091);
+ polygon.ps[3] = Point(10964.2, 594.091);
+ new ShapeRef(router, polygon, 1992);
+
+ // shapeRef1993
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10561.2, 4351.11);
+ polygon.ps[1] = Point(10561.2, 4371.11);
+ polygon.ps[2] = Point(10529.2, 4371.11);
+ polygon.ps[3] = Point(10529.2, 4351.11);
+ new ShapeRef(router, polygon, 1993);
+
+ // shapeRef1994
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10957.2, 4351.11);
+ polygon.ps[1] = Point(10957.2, 4371.11);
+ polygon.ps[2] = Point(10925.2, 4371.11);
+ polygon.ps[3] = Point(10925.2, 4351.11);
+ new ShapeRef(router, polygon, 1994);
+
+ // shapeRef1995
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11610.1, 4351.11);
+ polygon.ps[1] = Point(11610.1, 4371.11);
+ polygon.ps[2] = Point(11578.1, 4371.11);
+ polygon.ps[3] = Point(11578.1, 4351.11);
+ new ShapeRef(router, polygon, 1995);
+
+ // shapeRef1996
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10627.2, 4499.4);
+ polygon.ps[1] = Point(10627.2, 4519.4);
+ polygon.ps[2] = Point(10595.2, 4519.4);
+ polygon.ps[3] = Point(10595.2, 4499.4);
+ new ShapeRef(router, polygon, 1996);
+
+ // shapeRef1997
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12237.1, 4351.11);
+ polygon.ps[1] = Point(12237.1, 4371.11);
+ polygon.ps[2] = Point(12205.1, 4371.11);
+ polygon.ps[3] = Point(12205.1, 4351.11);
+ new ShapeRef(router, polygon, 1997);
+
+ // shapeRef1998
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12541.5, 4559.4);
+ polygon.ps[1] = Point(12541.5, 4591.4);
+ polygon.ps[2] = Point(12521.5, 4591.4);
+ polygon.ps[3] = Point(12521.5, 4559.4);
+ new ShapeRef(router, polygon, 1998);
+
+ // shapeRef1999
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12541.5, 4955.4);
+ polygon.ps[1] = Point(12541.5, 4987.4);
+ polygon.ps[2] = Point(12521.5, 4987.4);
+ polygon.ps[3] = Point(12521.5, 4955.4);
+ new ShapeRef(router, polygon, 1999);
+
+ // shapeRef2000
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12541.5, 5298.67);
+ polygon.ps[1] = Point(12541.5, 5330.67);
+ polygon.ps[2] = Point(12521.5, 5330.67);
+ polygon.ps[3] = Point(12521.5, 5298.67);
+ new ShapeRef(router, polygon, 2000);
+
+ // shapeRef2001
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12938.5, 4499.4);
+ polygon.ps[1] = Point(12938.5, 4519.4);
+ polygon.ps[2] = Point(12906.5, 4519.4);
+ polygon.ps[3] = Point(12906.5, 4499.4);
+ new ShapeRef(router, polygon, 2001);
+
+ // shapeRef2002
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13276, 3846.51);
+ polygon.ps[1] = Point(13276, 3878.51);
+ polygon.ps[2] = Point(13256, 3878.51);
+ polygon.ps[3] = Point(13256, 3846.51);
+ new ShapeRef(router, polygon, 2002);
+
+ // shapeRef2003
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12541.5, 3978.51);
+ polygon.ps[1] = Point(12541.5, 4010.51);
+ polygon.ps[2] = Point(12521.5, 4010.51);
+ polygon.ps[3] = Point(12521.5, 3978.51);
+ new ShapeRef(router, polygon, 2003);
+
+ // shapeRef2004
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12541.5, 3516.51);
+ polygon.ps[1] = Point(12541.5, 3548.51);
+ polygon.ps[2] = Point(12521.5, 3548.51);
+ polygon.ps[3] = Point(12521.5, 3516.51);
+ new ShapeRef(router, polygon, 2004);
+
+ // shapeRef2005
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12541.5, 3025.29);
+ polygon.ps[1] = Point(12541.5, 3057.29);
+ polygon.ps[2] = Point(12521.5, 3057.29);
+ polygon.ps[3] = Point(12521.5, 3025.29);
+ new ShapeRef(router, polygon, 2005);
+
+ // shapeRef2006
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12541.5, 2266.29);
+ polygon.ps[1] = Point(12541.5, 2298.29);
+ polygon.ps[2] = Point(12521.5, 2298.29);
+ polygon.ps[3] = Point(12521.5, 2266.29);
+ new ShapeRef(router, polygon, 2006);
+
+ // shapeRef2007
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12171.1, 1834.29);
+ polygon.ps[1] = Point(12171.1, 1854.29);
+ polygon.ps[2] = Point(12139.1, 1854.29);
+ polygon.ps[3] = Point(12139.1, 1834.29);
+ new ShapeRef(router, polygon, 2007);
+
+ // shapeRef2008
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12000.1, 1726.29);
+ polygon.ps[1] = Point(12000.1, 1758.29);
+ polygon.ps[2] = Point(11980.1, 1758.29);
+ polygon.ps[3] = Point(11980.1, 1726.29);
+ new ShapeRef(router, polygon, 2008);
+
+ // shapeRef2009
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12171.1, 1732.29);
+ polygon.ps[1] = Point(12171.1, 1752.29);
+ polygon.ps[2] = Point(12139.1, 1752.29);
+ polygon.ps[3] = Point(12139.1, 1732.29);
+ new ShapeRef(router, polygon, 2009);
+
+ // shapeRef2010
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13882, 8431.99);
+ polygon.ps[1] = Point(13882, 8463.99);
+ polygon.ps[2] = Point(13862, 8463.99);
+ polygon.ps[3] = Point(13862, 8431.99);
+ new ShapeRef(router, polygon, 2010);
+
+ // shapeRef2011
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11934.1, 7827.79);
+ polygon.ps[1] = Point(11934.1, 7859.79);
+ polygon.ps[2] = Point(11914.1, 7859.79);
+ polygon.ps[3] = Point(11914.1, 7827.79);
+ new ShapeRef(router, polygon, 2011);
+
+ // shapeRef2012
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15878.6, 8431.99);
+ polygon.ps[1] = Point(15878.6, 8463.99);
+ polygon.ps[2] = Point(15858.6, 8463.99);
+ polygon.ps[3] = Point(15858.6, 8431.99);
+ new ShapeRef(router, polygon, 2012);
+
+ // shapeRef2013
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16732.8, 8398.99);
+ polygon.ps[1] = Point(16732.8, 8430.99);
+ polygon.ps[2] = Point(16712.8, 8430.99);
+ polygon.ps[3] = Point(16712.8, 8398.99);
+ new ShapeRef(router, polygon, 2013);
+
+ // shapeRef2014
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8667.29, 4182.51);
+ polygon.ps[1] = Point(8667.29, 4202.51);
+ polygon.ps[2] = Point(8635.29, 4202.51);
+ polygon.ps[3] = Point(8635.29, 4182.51);
+ new ShapeRef(router, polygon, 2014);
+
+ // shapeRef2015
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10126, 9692.42);
+ polygon.ps[1] = Point(10126, 9724.42);
+ polygon.ps[2] = Point(10106, 9724.42);
+ polygon.ps[3] = Point(10106, 9692.42);
+ new ShapeRef(router, polygon, 2015);
+
+ // shapeRef2016
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15390.5, 1171.29);
+ polygon.ps[1] = Point(15390.5, 1191.29);
+ polygon.ps[2] = Point(15358.5, 1191.29);
+ polygon.ps[3] = Point(15358.5, 1171.29);
+ new ShapeRef(router, polygon, 2016);
+
+ // shapeRef2017
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13618, 6663.51);
+ polygon.ps[1] = Point(13618, 6695.51);
+ polygon.ps[2] = Point(13598, 6695.51);
+ polygon.ps[3] = Point(13598, 6663.51);
+ new ShapeRef(router, polygon, 2017);
+
+ // shapeRef2018
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10819.2, 7310.4);
+ polygon.ps[1] = Point(10819.2, 7342.4);
+ polygon.ps[2] = Point(10799.2, 7342.4);
+ polygon.ps[3] = Point(10799.2, 7310.4);
+ new ShapeRef(router, polygon, 2018);
+
+ // shapeRef2019
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10819.2, 7794.79);
+ polygon.ps[1] = Point(10819.2, 7826.79);
+ polygon.ps[2] = Point(10799.2, 7826.79);
+ polygon.ps[3] = Point(10799.2, 7794.79);
+ new ShapeRef(router, polygon, 2019);
+
+ // shapeRef2020
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9860.69, 6399.51);
+ polygon.ps[1] = Point(9860.69, 6431.51);
+ polygon.ps[2] = Point(9840.69, 6431.51);
+ polygon.ps[3] = Point(9840.69, 6399.51);
+ new ShapeRef(router, polygon, 2020);
+
+ // shapeRef2021
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11254.2, 8863.22);
+ polygon.ps[1] = Point(11254.2, 8883.22);
+ polygon.ps[2] = Point(11222.2, 8883.22);
+ polygon.ps[3] = Point(11222.2, 8863.22);
+ new ShapeRef(router, polygon, 2021);
+
+ // shapeRef2022
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12336.1, 8863.22);
+ polygon.ps[1] = Point(12336.1, 8883.22);
+ polygon.ps[2] = Point(12304.1, 8883.22);
+ polygon.ps[3] = Point(12304.1, 8863.22);
+ new ShapeRef(router, polygon, 2022);
+
+ // shapeRef2023
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9035.99, 3423.51);
+ polygon.ps[1] = Point(9035.99, 3443.51);
+ polygon.ps[2] = Point(9003.99, 3443.51);
+ polygon.ps[3] = Point(9003.99, 3423.51);
+ new ShapeRef(router, polygon, 2023);
+
+ // shapeRef2024
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7492.1, 3555.51);
+ polygon.ps[1] = Point(7492.1, 3575.51);
+ polygon.ps[2] = Point(7460.1, 3575.51);
+ polygon.ps[3] = Point(7460.1, 3555.51);
+ new ShapeRef(router, polygon, 2024);
+
+ // shapeRef2025
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6799.1, 3555.51);
+ polygon.ps[1] = Point(6799.1, 3575.51);
+ polygon.ps[2] = Point(6767.1, 3575.51);
+ polygon.ps[3] = Point(6767.1, 3555.51);
+ new ShapeRef(router, polygon, 2025);
+
+ // shapeRef2026
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6205.1, 3555.51);
+ polygon.ps[1] = Point(6205.1, 3575.51);
+ polygon.ps[2] = Point(6173.1, 3575.51);
+ polygon.ps[3] = Point(6173.1, 3555.51);
+ new ShapeRef(router, polygon, 2026);
+
+ // shapeRef2027
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5710.1, 3555.51);
+ polygon.ps[1] = Point(5710.1, 3575.51);
+ polygon.ps[2] = Point(5678.1, 3575.51);
+ polygon.ps[3] = Point(5678.1, 3555.51);
+ new ShapeRef(router, polygon, 2027);
+
+ // shapeRef2028
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5322, 3813.51);
+ polygon.ps[1] = Point(5322, 3845.51);
+ polygon.ps[2] = Point(5302, 3845.51);
+ polygon.ps[3] = Point(5302, 3813.51);
+ new ShapeRef(router, polygon, 2028);
+
+ // shapeRef2029
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5322, 4559.4);
+ polygon.ps[1] = Point(5322, 4591.4);
+ polygon.ps[2] = Point(5302, 4591.4);
+ polygon.ps[3] = Point(5302, 4559.4);
+ new ShapeRef(router, polygon, 2029);
+
+ // shapeRef2030
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5322, 5331.67);
+ polygon.ps[1] = Point(5322, 5363.67);
+ polygon.ps[2] = Point(5302, 5363.67);
+ polygon.ps[3] = Point(5302, 5331.67);
+ new ShapeRef(router, polygon, 2030);
+
+ // shapeRef2031
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5322, 5153.4);
+ polygon.ps[1] = Point(5322, 5185.4);
+ polygon.ps[2] = Point(5302, 5185.4);
+ polygon.ps[3] = Point(5302, 5153.4);
+ new ShapeRef(router, polygon, 2031);
+
+ // shapeRef2032
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8408.29, 5502.67);
+ polygon.ps[1] = Point(8408.29, 5522.67);
+ polygon.ps[2] = Point(8376.29, 5522.67);
+ polygon.ps[3] = Point(8376.29, 5502.67);
+ new ShapeRef(router, polygon, 2032);
+
+ // shapeRef2033
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5512.1, 5337.67);
+ polygon.ps[1] = Point(5512.1, 5357.67);
+ polygon.ps[2] = Point(5480.1, 5357.67);
+ polygon.ps[3] = Point(5480.1, 5337.67);
+ new ShapeRef(router, polygon, 2033);
+
+ // shapeRef2034
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4965, 5954.59);
+ polygon.ps[1] = Point(4965, 5974.59);
+ polygon.ps[2] = Point(4933, 5974.59);
+ polygon.ps[3] = Point(4933, 5954.59);
+ new ShapeRef(router, polygon, 2034);
+
+ // shapeRef2035
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4959, 6040.29);
+ polygon.ps[1] = Point(4959, 6072.29);
+ polygon.ps[2] = Point(4939, 6072.29);
+ polygon.ps[3] = Point(4939, 6040.29);
+ new ShapeRef(router, polygon, 2035);
+
+ // shapeRef2036
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4959, 7794.79);
+ polygon.ps[1] = Point(4959, 7826.79);
+ polygon.ps[2] = Point(4939, 7826.79);
+ polygon.ps[3] = Point(4939, 7794.79);
+ new ShapeRef(router, polygon, 2036);
+
+ // shapeRef2037
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4959, 8365.99);
+ polygon.ps[1] = Point(4959, 8397.99);
+ polygon.ps[2] = Point(4939, 8397.99);
+ polygon.ps[3] = Point(4939, 8365.99);
+ new ShapeRef(router, polygon, 2037);
+
+ // shapeRef2038
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4959, 8791.22);
+ polygon.ps[1] = Point(4959, 8823.22);
+ polygon.ps[2] = Point(4939, 8823.22);
+ polygon.ps[3] = Point(4939, 8791.22);
+ new ShapeRef(router, polygon, 2038);
+
+ // shapeRef2039
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4959, 9296.42);
+ polygon.ps[1] = Point(4959, 9328.42);
+ polygon.ps[2] = Point(4939, 9328.42);
+ polygon.ps[3] = Point(4939, 9296.42);
+ new ShapeRef(router, polygon, 2039);
+
+ // shapeRef2040
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4299, 9861.02);
+ polygon.ps[1] = Point(4299, 9893.02);
+ polygon.ps[2] = Point(4279, 9893.02);
+ polygon.ps[3] = Point(4279, 9861.02);
+ new ShapeRef(router, polygon, 2040);
+
+ // shapeRef2041
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4767, 10428);
+ polygon.ps[1] = Point(4767, 10448);
+ polygon.ps[2] = Point(4735, 10448);
+ polygon.ps[3] = Point(4735, 10428);
+ new ShapeRef(router, polygon, 2041);
+
+ // shapeRef2042
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4563, 10567.3);
+ polygon.ps[1] = Point(4563, 10599.3);
+ polygon.ps[2] = Point(4543, 10599.3);
+ polygon.ps[3] = Point(4543, 10567.3);
+ new ShapeRef(router, polygon, 2042);
+
+ // shapeRef2043
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11373.1, 1462.29);
+ polygon.ps[1] = Point(11373.1, 1494.29);
+ polygon.ps[2] = Point(11353.1, 1494.29);
+ polygon.ps[3] = Point(11353.1, 1462.29);
+ new ShapeRef(router, polygon, 2043);
+
+ // shapeRef2044
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11373.1, 1099.29);
+ polygon.ps[1] = Point(11373.1, 1131.29);
+ polygon.ps[2] = Point(11353.1, 1131.29);
+ polygon.ps[3] = Point(11353.1, 1099.29);
+ new ShapeRef(router, polygon, 2044);
+
+ // shapeRef2045
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11373.1, 594.091);
+ polygon.ps[1] = Point(11373.1, 626.091);
+ polygon.ps[2] = Point(11353.1, 626.091);
+ polygon.ps[3] = Point(11353.1, 594.091);
+ new ShapeRef(router, polygon, 2045);
+
+ // shapeRef2046
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11544.1, 448.265);
+ polygon.ps[1] = Point(11544.1, 468.265);
+ polygon.ps[2] = Point(11512.1, 468.265);
+ polygon.ps[3] = Point(11512.1, 448.265);
+ new ShapeRef(router, polygon, 2046);
+
+ // shapeRef2047
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11973.1, 448.265);
+ polygon.ps[1] = Point(11973.1, 468.265);
+ polygon.ps[2] = Point(11941.1, 468.265);
+ polygon.ps[3] = Point(11941.1, 448.265);
+ new ShapeRef(router, polygon, 2047);
+
+ // shapeRef2048
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15002.9, 1336.29);
+ polygon.ps[1] = Point(15002.9, 1356.29);
+ polygon.ps[2] = Point(14970.9, 1356.29);
+ polygon.ps[3] = Point(14970.9, 1336.29);
+ new ShapeRef(router, polygon, 2048);
+
+ // shapeRef2049
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12740.5, 567.091);
+ polygon.ps[1] = Point(12740.5, 587.091);
+ polygon.ps[2] = Point(12708.5, 587.091);
+ polygon.ps[3] = Point(12708.5, 567.091);
+ new ShapeRef(router, polygon, 2049);
+
+ // shapeRef2050
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13216, 448.265);
+ polygon.ps[1] = Point(13216, 468.265);
+ polygon.ps[2] = Point(13184, 468.265);
+ polygon.ps[3] = Point(13184, 448.265);
+ new ShapeRef(router, polygon, 2050);
+
+ // shapeRef2051
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13888, 448.265);
+ polygon.ps[1] = Point(13888, 468.265);
+ polygon.ps[2] = Point(13856, 468.265);
+ polygon.ps[3] = Point(13856, 448.265);
+ new ShapeRef(router, polygon, 2051);
+
+ // shapeRef2052
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14350, 448.265);
+ polygon.ps[1] = Point(14350, 468.265);
+ polygon.ps[2] = Point(14318, 468.265);
+ polygon.ps[3] = Point(14318, 448.265);
+ new ShapeRef(router, polygon, 2052);
+
+ // shapeRef2053
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14812, 448.265);
+ polygon.ps[1] = Point(14812, 468.265);
+ polygon.ps[2] = Point(14780, 468.265);
+ polygon.ps[3] = Point(14780, 448.265);
+ new ShapeRef(router, polygon, 2053);
+
+ // shapeRef2054
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15653.3, 448.265);
+ polygon.ps[1] = Point(15653.3, 468.265);
+ polygon.ps[2] = Point(15621.3, 468.265);
+ polygon.ps[3] = Point(15621.3, 448.265);
+ new ShapeRef(router, polygon, 2054);
+
+ // shapeRef2055
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16181.6, 448.265);
+ polygon.ps[1] = Point(16181.6, 468.265);
+ polygon.ps[2] = Point(16149.6, 468.265);
+ polygon.ps[3] = Point(16149.6, 448.265);
+ new ShapeRef(router, polygon, 2055);
+
+ // shapeRef2056
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16373.6, 792.091);
+ polygon.ps[1] = Point(16373.6, 824.091);
+ polygon.ps[2] = Point(16353.6, 824.091);
+ polygon.ps[3] = Point(16353.6, 792.091);
+ new ShapeRef(router, polygon, 2056);
+
+ // shapeRef2057
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16175.6, 792.091);
+ polygon.ps[1] = Point(16175.6, 824.091);
+ polygon.ps[2] = Point(16155.6, 824.091);
+ polygon.ps[3] = Point(16155.6, 792.091);
+ new ShapeRef(router, polygon, 2057);
+
+ // shapeRef2058
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11122.2, 8064.79);
+ polygon.ps[1] = Point(11122.2, 8084.79);
+ polygon.ps[2] = Point(11090.2, 8084.79);
+ polygon.ps[3] = Point(11090.2, 8064.79);
+ new ShapeRef(router, polygon, 2058);
+
+ // shapeRef2059
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11505.1, 7728.79);
+ polygon.ps[1] = Point(11505.1, 7760.79);
+ polygon.ps[2] = Point(11485.1, 7760.79);
+ polygon.ps[3] = Point(11485.1, 7728.79);
+ new ShapeRef(router, polygon, 2059);
+
+ // shapeRef2060
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12039.1, 7415.4);
+ polygon.ps[1] = Point(12039.1, 7435.4);
+ polygon.ps[2] = Point(12007.1, 7435.4);
+ polygon.ps[3] = Point(12007.1, 7415.4);
+ new ShapeRef(router, polygon, 2060);
+
+ // shapeRef2061
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17062.8, 7178.4);
+ polygon.ps[1] = Point(17062.8, 7210.4);
+ polygon.ps[2] = Point(17042.8, 7210.4);
+ polygon.ps[3] = Point(17042.8, 7178.4);
+ new ShapeRef(router, polygon, 2061);
+
+ // shapeRef2062
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18532, 11850.9);
+ polygon.ps[1] = Point(18532, 11870.9);
+ polygon.ps[2] = Point(18500, 11870.9);
+ polygon.ps[3] = Point(18500, 11850.9);
+ new ShapeRef(router, polygon, 2062);
+
+ // shapeRef2063
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13282, 8863.22);
+ polygon.ps[1] = Point(13282, 8883.22);
+ polygon.ps[2] = Point(13250, 8883.22);
+ polygon.ps[3] = Point(13250, 8863.22);
+ new ShapeRef(router, polygon, 2063);
+
+ // shapeRef2064
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10792.2, 448.265);
+ polygon.ps[1] = Point(10792.2, 468.265);
+ polygon.ps[2] = Point(10760.2, 468.265);
+ polygon.ps[3] = Point(10760.2, 448.265);
+ new ShapeRef(router, polygon, 2064);
+
+ // shapeRef2065
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15620.3, 1336.29);
+ polygon.ps[1] = Point(15620.3, 1356.29);
+ polygon.ps[2] = Point(15588.3, 1356.29);
+ polygon.ps[3] = Point(15588.3, 1336.29);
+ new ShapeRef(router, polygon, 2065);
+
+ // shapeRef2066
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8045.29, 303.265);
+ polygon.ps[1] = Point(8045.29, 323.265);
+ polygon.ps[2] = Point(8013.29, 323.265);
+ polygon.ps[3] = Point(8013.29, 303.265);
+ new ShapeRef(router, polygon, 2066);
+
+ // shapeRef2067
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8309.29, 415.265);
+ polygon.ps[1] = Point(8309.29, 435.265);
+ polygon.ps[2] = Point(8277.29, 435.265);
+ polygon.ps[3] = Point(8277.29, 415.265);
+ new ShapeRef(router, polygon, 2067);
+
+ // shapeRef2068
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7781.29, 415.265);
+ polygon.ps[1] = Point(7781.29, 435.265);
+ polygon.ps[2] = Point(7749.29, 435.265);
+ polygon.ps[3] = Point(7749.29, 415.265);
+ new ShapeRef(router, polygon, 2068);
+
+ // shapeRef2069
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6964.1, 415.265);
+ polygon.ps[1] = Point(6964.1, 435.265);
+ polygon.ps[2] = Point(6932.1, 435.265);
+ polygon.ps[3] = Point(6932.1, 415.265);
+ new ShapeRef(router, polygon, 2069);
+
+ // shapeRef2070
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6337.1, 415.265);
+ polygon.ps[1] = Point(6337.1, 435.265);
+ polygon.ps[2] = Point(6305.1, 435.265);
+ polygon.ps[3] = Point(6305.1, 415.265);
+ new ShapeRef(router, polygon, 2070);
+
+ // shapeRef2071
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15131.3, 1171.29);
+ polygon.ps[1] = Point(15131.3, 1191.29);
+ polygon.ps[2] = Point(15099.3, 1191.29);
+ polygon.ps[3] = Point(15099.3, 1171.29);
+ new ShapeRef(router, polygon, 2071);
+
+ // shapeRef2072
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14874.4, 1336.29);
+ polygon.ps[1] = Point(14874.4, 1356.29);
+ polygon.ps[2] = Point(14842.4, 1356.29);
+ polygon.ps[3] = Point(14842.4, 1336.29);
+ new ShapeRef(router, polygon, 2072);
+
+ // shapeRef2073
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15493.3, 1171.29);
+ polygon.ps[1] = Point(15493.3, 1191.29);
+ polygon.ps[2] = Point(15461.3, 1191.29);
+ polygon.ps[3] = Point(15461.3, 1171.29);
+ new ShapeRef(router, polygon, 2073);
+
+ // shapeRef2074
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15748.9, 1336.29);
+ polygon.ps[1] = Point(15748.9, 1356.29);
+ polygon.ps[2] = Point(15716.9, 1356.29);
+ polygon.ps[3] = Point(15716.9, 1336.29);
+ new ShapeRef(router, polygon, 2074);
+
+ // shapeRef2075
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11254.2, 4351.11);
+ polygon.ps[1] = Point(11254.2, 4371.11);
+ polygon.ps[2] = Point(11222.2, 4371.11);
+ polygon.ps[3] = Point(11222.2, 4351.11);
+ new ShapeRef(router, polygon, 2075);
+
+ // shapeRef2076
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14614, 6778.21);
+ polygon.ps[1] = Point(14614, 6798.21);
+ polygon.ps[2] = Point(14582, 6798.21);
+ polygon.ps[3] = Point(14582, 6778.21);
+ new ShapeRef(router, polygon, 2076);
+
+ // shapeRef2077
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5671.1, 4559.4);
+ polygon.ps[1] = Point(5671.1, 4591.4);
+ polygon.ps[2] = Point(5651.1, 4591.4);
+ polygon.ps[3] = Point(5651.1, 4559.4);
+ new ShapeRef(router, polygon, 2077);
+
+ // shapeRef2078
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18246.5, 8530.99);
+ polygon.ps[1] = Point(18246.5, 8562.99);
+ polygon.ps[2] = Point(18226.5, 8562.99);
+ polygon.ps[3] = Point(18226.5, 8530.99);
+ new ShapeRef(router, polygon, 2078);
+
+ // shapeRef2079
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17625.5, 10164);
+ polygon.ps[1] = Point(17625.5, 10184);
+ polygon.ps[2] = Point(17593.5, 10184);
+ polygon.ps[3] = Point(17593.5, 10164);
+ new ShapeRef(router, polygon, 2079);
+
+ // shapeRef2080
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16573.8, 10164);
+ polygon.ps[1] = Point(16573.8, 10184);
+ polygon.ps[2] = Point(16541.8, 10184);
+ polygon.ps[3] = Point(16541.8, 10164);
+ new ShapeRef(router, polygon, 2080);
+
+ // shapeRef2081
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13954, 10164);
+ polygon.ps[1] = Point(13954, 10184);
+ polygon.ps[2] = Point(13922, 10184);
+ polygon.ps[3] = Point(13922, 10164);
+ new ShapeRef(router, polygon, 2081);
+
+ // shapeRef2082
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10334.9, 9692.42);
+ polygon.ps[1] = Point(10334.9, 9724.42);
+ polygon.ps[2] = Point(10314.9, 9724.42);
+ polygon.ps[3] = Point(10314.9, 9692.42);
+ new ShapeRef(router, polygon, 2082);
+
+ // shapeRef2083
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10126, 10356);
+ polygon.ps[1] = Point(10126, 10388);
+ polygon.ps[2] = Point(10106, 10388);
+ polygon.ps[3] = Point(10106, 10356);
+ new ShapeRef(router, polygon, 2083);
+
+ // shapeRef2084
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10528.2, 10672.3);
+ polygon.ps[1] = Point(10528.2, 10692.3);
+ polygon.ps[2] = Point(10496.2, 10692.3);
+ polygon.ps[3] = Point(10496.2, 10672.3);
+ new ShapeRef(router, polygon, 2084);
+
+ // shapeRef2085
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10924.2, 10672.3);
+ polygon.ps[1] = Point(10924.2, 10692.3);
+ polygon.ps[2] = Point(10892.2, 10692.3);
+ polygon.ps[3] = Point(10892.2, 10672.3);
+ new ShapeRef(router, polygon, 2085);
+
+ // shapeRef2086
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10852.2, 10964.6);
+ polygon.ps[1] = Point(10852.2, 10996.6);
+ polygon.ps[2] = Point(10832.2, 10996.6);
+ polygon.ps[3] = Point(10832.2, 10964.6);
+ new ShapeRef(router, polygon, 2086);
+
+ // shapeRef2087
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9734.69, 11201.6);
+ polygon.ps[1] = Point(9734.69, 11221.6);
+ polygon.ps[2] = Point(9702.69, 11221.6);
+ polygon.ps[3] = Point(9702.69, 11201.6);
+ new ShapeRef(router, polygon, 2087);
+
+ // shapeRef2088
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9253.59, 11201.6);
+ polygon.ps[1] = Point(9253.59, 11221.6);
+ polygon.ps[2] = Point(9221.59, 11221.6);
+ polygon.ps[3] = Point(9221.59, 11201.6);
+ new ShapeRef(router, polygon, 2088);
+
+ // shapeRef2089
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8700.29, 11201.6);
+ polygon.ps[1] = Point(8700.29, 11221.6);
+ polygon.ps[2] = Point(8668.29, 11221.6);
+ polygon.ps[3] = Point(8668.29, 11201.6);
+ new ShapeRef(router, polygon, 2089);
+
+ // shapeRef2090
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7973.29, 10997.6);
+ polygon.ps[1] = Point(7973.29, 11029.6);
+ polygon.ps[2] = Point(7953.29, 11029.6);
+ polygon.ps[3] = Point(7953.29, 10997.6);
+ new ShapeRef(router, polygon, 2090);
+
+ // shapeRef2091
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8243.29, 10705.3);
+ polygon.ps[1] = Point(8243.29, 10725.3);
+ polygon.ps[2] = Point(8211.29, 10725.3);
+ polygon.ps[3] = Point(8211.29, 10705.3);
+ new ShapeRef(router, polygon, 2091);
+
+ // shapeRef2092
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8700.29, 10705.3);
+ polygon.ps[1] = Point(8700.29, 10725.3);
+ polygon.ps[2] = Point(8668.29, 10725.3);
+ polygon.ps[3] = Point(8668.29, 10705.3);
+ new ShapeRef(router, polygon, 2092);
+
+ // shapeRef2093
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13315, 9236.42);
+ polygon.ps[1] = Point(13315, 9256.42);
+ polygon.ps[2] = Point(13283, 9256.42);
+ polygon.ps[3] = Point(13283, 9236.42);
+ new ShapeRef(router, polygon, 2093);
+
+ // shapeRef2094
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6667.1, 6986.4);
+ polygon.ps[1] = Point(6667.1, 7006.4);
+ polygon.ps[2] = Point(6635.1, 7006.4);
+ polygon.ps[3] = Point(6635.1, 6986.4);
+ new ShapeRef(router, polygon, 2094);
+
+ // shapeRef2095
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7222.1, 7277.4);
+ polygon.ps[1] = Point(7222.1, 7309.4);
+ polygon.ps[2] = Point(7202.1, 7309.4);
+ polygon.ps[3] = Point(7202.1, 7277.4);
+ new ShapeRef(router, polygon, 2095);
+
+ // shapeRef2096
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7222.1, 9197.42);
+ polygon.ps[1] = Point(7222.1, 9229.42);
+ polygon.ps[2] = Point(7202.1, 9229.42);
+ polygon.ps[3] = Point(7202.1, 9197.42);
+ new ShapeRef(router, polygon, 2096);
+
+ // shapeRef2097
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6562.1, 8025.79);
+ polygon.ps[1] = Point(6562.1, 8057.79);
+ polygon.ps[2] = Point(6542.1, 8057.79);
+ polygon.ps[3] = Point(6542.1, 8025.79);
+ new ShapeRef(router, polygon, 2097);
+
+ // shapeRef2098
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6562.1, 9861.02);
+ polygon.ps[1] = Point(6562.1, 9893.02);
+ polygon.ps[2] = Point(6542.1, 9893.02);
+ polygon.ps[3] = Point(6542.1, 9861.02);
+ new ShapeRef(router, polygon, 2098);
+
+ // shapeRef2099
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6562.1, 7563.79);
+ polygon.ps[1] = Point(6562.1, 7595.79);
+ polygon.ps[2] = Point(6542.1, 7595.79);
+ polygon.ps[3] = Point(6542.1, 7563.79);
+ new ShapeRef(router, polygon, 2099);
+
+ // shapeRef2100
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7261.1, 6504.51);
+ polygon.ps[1] = Point(7261.1, 6524.51);
+ polygon.ps[2] = Point(7229.1, 6524.51);
+ polygon.ps[3] = Point(7229.1, 6504.51);
+ new ShapeRef(router, polygon, 2100);
+
+ // shapeRef2101
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8177.29, 6504.51);
+ polygon.ps[1] = Point(8177.29, 6524.51);
+ polygon.ps[2] = Point(8145.29, 6524.51);
+ polygon.ps[3] = Point(8145.29, 6504.51);
+ new ShapeRef(router, polygon, 2101);
+
+ // shapeRef2102
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6403.1, 6778.21);
+ polygon.ps[1] = Point(6403.1, 6798.21);
+ polygon.ps[2] = Point(6371.1, 6798.21);
+ polygon.ps[3] = Point(6371.1, 6778.21);
+ new ShapeRef(router, polygon, 2102);
+
+ // shapeRef2103
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6133.1, 7959.79);
+ polygon.ps[1] = Point(6133.1, 7991.79);
+ polygon.ps[2] = Point(6113.1, 7991.79);
+ polygon.ps[3] = Point(6113.1, 7959.79);
+ new ShapeRef(router, polygon, 2103);
+
+ // shapeRef2104
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9932.69, 11622.9);
+ polygon.ps[1] = Point(9932.69, 11642.9);
+ polygon.ps[2] = Point(9900.69, 11642.9);
+ polygon.ps[3] = Point(9900.69, 11622.9);
+ new ShapeRef(router, polygon, 2104);
+
+ // shapeRef2105
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11445.1, 11622.9);
+ polygon.ps[1] = Point(11445.1, 11642.9);
+ polygon.ps[2] = Point(11413.1, 11642.9);
+ polygon.ps[3] = Point(11413.1, 11622.9);
+ new ShapeRef(router, polygon, 2105);
+
+ // shapeRef2106
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12773.5, 11622.9);
+ polygon.ps[1] = Point(12773.5, 11642.9);
+ polygon.ps[2] = Point(12741.5, 11642.9);
+ polygon.ps[3] = Point(12741.5, 11622.9);
+ new ShapeRef(router, polygon, 2106);
+
+ // shapeRef2107
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14548, 11622.9);
+ polygon.ps[1] = Point(14548, 11642.9);
+ polygon.ps[2] = Point(14516, 11642.9);
+ polygon.ps[3] = Point(14516, 11622.9);
+ new ShapeRef(router, polygon, 2107);
+
+ // shapeRef2108
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16082.6, 11622.9);
+ polygon.ps[1] = Point(16082.6, 11642.9);
+ polygon.ps[2] = Point(16050.6, 11642.9);
+ polygon.ps[3] = Point(16050.6, 11622.9);
+ new ShapeRef(router, polygon, 2108);
+
+ // shapeRef2109
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15878.6, 11877.9);
+ polygon.ps[1] = Point(15878.6, 11909.9);
+ polygon.ps[2] = Point(15858.6, 11909.9);
+ polygon.ps[3] = Point(15858.6, 11877.9);
+ new ShapeRef(router, polygon, 2109);
+
+ // shapeRef2110
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15878.6, 12177.3);
+ polygon.ps[1] = Point(15878.6, 12209.3);
+ polygon.ps[2] = Point(15858.6, 12209.3);
+ polygon.ps[3] = Point(15858.6, 12177.3);
+ new ShapeRef(router, polygon, 2110);
+
+ // shapeRef2111
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15620.3, 12282.3);
+ polygon.ps[1] = Point(15620.3, 12302.3);
+ polygon.ps[2] = Point(15588.3, 12302.3);
+ polygon.ps[3] = Point(15588.3, 12282.3);
+ new ShapeRef(router, polygon, 2111);
+
+ // shapeRef2112
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15002.9, 12282.3);
+ polygon.ps[1] = Point(15002.9, 12302.3);
+ polygon.ps[2] = Point(14970.9, 12302.3);
+ polygon.ps[3] = Point(14970.9, 12282.3);
+ new ShapeRef(router, polygon, 2112);
+
+ // shapeRef2113
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14218, 12282.3);
+ polygon.ps[1] = Point(14218, 12302.3);
+ polygon.ps[2] = Point(14186, 12302.3);
+ polygon.ps[3] = Point(14186, 12282.3);
+ new ShapeRef(router, polygon, 2113);
+
+ // shapeRef2114
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9280.59, 5641.9);
+ polygon.ps[1] = Point(9280.59, 5673.9);
+ polygon.ps[2] = Point(9260.59, 5673.9);
+ polygon.ps[3] = Point(9260.59, 5641.9);
+ new ShapeRef(router, polygon, 2114);
+
+ // shapeRef2115
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9511.59, 7343.4);
+ polygon.ps[1] = Point(9511.59, 7375.4);
+ polygon.ps[2] = Point(9491.59, 7375.4);
+ polygon.ps[3] = Point(9491.59, 7343.4);
+ new ShapeRef(router, polygon, 2115);
+
+ // shapeRef2116
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9511.59, 10356);
+ polygon.ps[1] = Point(9511.59, 10388);
+ polygon.ps[2] = Point(9491.59, 10388);
+ polygon.ps[3] = Point(9491.59, 10356);
+ new ShapeRef(router, polygon, 2116);
+
+ // shapeRef2117
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10373.9, 10771.3);
+ polygon.ps[1] = Point(10373.9, 10791.3);
+ polygon.ps[2] = Point(10341.9, 10791.3);
+ polygon.ps[3] = Point(10341.9, 10771.3);
+ new ShapeRef(router, polygon, 2117);
+
+ // shapeRef2118
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11676.1, 10771.3);
+ polygon.ps[1] = Point(11676.1, 10791.3);
+ polygon.ps[2] = Point(11644.1, 10791.3);
+ polygon.ps[3] = Point(11644.1, 10771.3);
+ new ShapeRef(router, polygon, 2118);
+
+ // shapeRef2119
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13117, 10771.3);
+ polygon.ps[1] = Point(13117, 10791.3);
+ polygon.ps[2] = Point(13085, 10791.3);
+ polygon.ps[3] = Point(13085, 10771.3);
+ new ShapeRef(router, polygon, 2119);
+
+ // shapeRef2120
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14317, 10771.3);
+ polygon.ps[1] = Point(14317, 10791.3);
+ polygon.ps[2] = Point(14285, 10791.3);
+ polygon.ps[3] = Point(14285, 10771.3);
+ new ShapeRef(router, polygon, 2120);
+
+ // shapeRef2121
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15781.9, 10771.3);
+ polygon.ps[1] = Point(15781.9, 10791.3);
+ polygon.ps[2] = Point(15749.9, 10791.3);
+ polygon.ps[3] = Point(15749.9, 10771.3);
+ new ShapeRef(router, polygon, 2121);
+
+ // shapeRef2122
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6106.1, 204.265);
+ polygon.ps[1] = Point(6106.1, 224.265);
+ polygon.ps[2] = Point(6074.1, 224.265);
+ polygon.ps[3] = Point(6074.1, 204.265);
+ new ShapeRef(router, polygon, 2122);
+
+ // shapeRef2123
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7775.29, 835.285);
+ polygon.ps[1] = Point(7775.29, 867.285);
+ polygon.ps[2] = Point(7755.29, 867.285);
+ polygon.ps[3] = Point(7755.29, 835.285);
+ new ShapeRef(router, polygon, 2123);
+
+ // shapeRef2124
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10433.9, 6399.51);
+ polygon.ps[1] = Point(10433.9, 6431.51);
+ polygon.ps[2] = Point(10413.9, 6431.51);
+ polygon.ps[3] = Point(10413.9, 6399.51);
+ new ShapeRef(router, polygon, 2124);
+
+ // shapeRef2125
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15158.3, 10898.6);
+ polygon.ps[1] = Point(15158.3, 10930.6);
+ polygon.ps[2] = Point(15138.3, 10930.6);
+ polygon.ps[3] = Point(15138.3, 10898.6);
+ new ShapeRef(router, polygon, 2125);
+
+ // shapeRef2126
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7907.29, 4427.4);
+ polygon.ps[1] = Point(7907.29, 4459.4);
+ polygon.ps[2] = Point(7887.29, 4459.4);
+ polygon.ps[3] = Point(7887.29, 4427.4);
+ new ShapeRef(router, polygon, 2126);
+
+ // shapeRef2127
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17229.5, 7184.4);
+ polygon.ps[1] = Point(17229.5, 7204.4);
+ polygon.ps[2] = Point(17197.5, 7204.4);
+ polygon.ps[3] = Point(17197.5, 7184.4);
+ new ShapeRef(router, polygon, 2127);
+
+ // shapeRef2128
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4965, 5812.9);
+ polygon.ps[1] = Point(4965, 5832.9);
+ polygon.ps[2] = Point(4933, 5832.9);
+ polygon.ps[3] = Point(4933, 5812.9);
+ new ShapeRef(router, polygon, 2128);
+
+ // shapeRef2129
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11373.1, 2233.29);
+ polygon.ps[1] = Point(11373.1, 2265.29);
+ polygon.ps[2] = Point(11353.1, 2265.29);
+ polygon.ps[3] = Point(11353.1, 2233.29);
+ new ShapeRef(router, polygon, 2129);
+
+ // shapeRef2130
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11373.1, 3322.29);
+ polygon.ps[1] = Point(11373.1, 3354.29);
+ polygon.ps[2] = Point(11353.1, 3354.29);
+ polygon.ps[3] = Point(11353.1, 3322.29);
+ new ShapeRef(router, polygon, 2130);
+
+ // shapeRef2131
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11373.1, 4460.4);
+ polygon.ps[1] = Point(11373.1, 4492.4);
+ polygon.ps[2] = Point(11353.1, 4492.4);
+ polygon.ps[3] = Point(11353.1, 4460.4);
+ new ShapeRef(router, polygon, 2131);
+
+ // shapeRef2132
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11373.1, 5364.67);
+ polygon.ps[1] = Point(11373.1, 5396.67);
+ polygon.ps[2] = Point(11353.1, 5396.67);
+ polygon.ps[3] = Point(11353.1, 5364.67);
+ new ShapeRef(router, polygon, 2132);
+
+ // shapeRef2133
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11373.1, 6564.51);
+ polygon.ps[1] = Point(11373.1, 6596.51);
+ polygon.ps[2] = Point(11353.1, 6596.51);
+ polygon.ps[3] = Point(11353.1, 6564.51);
+ new ShapeRef(router, polygon, 2133);
+
+ // shapeRef2134
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11373.1, 8398.99);
+ polygon.ps[1] = Point(11373.1, 8430.99);
+ polygon.ps[2] = Point(11353.1, 8430.99);
+ polygon.ps[3] = Point(11353.1, 8398.99);
+ new ShapeRef(router, polygon, 2134);
+
+ // shapeRef2135
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11373.1, 9960.02);
+ polygon.ps[1] = Point(11373.1, 9992.02);
+ polygon.ps[2] = Point(11353.1, 9992.02);
+ polygon.ps[3] = Point(11353.1, 9960.02);
+ new ShapeRef(router, polygon, 2135);
+
+ // shapeRef2136
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11373.1, 11162.6);
+ polygon.ps[1] = Point(11373.1, 11194.6);
+ polygon.ps[2] = Point(11353.1, 11194.6);
+ polygon.ps[3] = Point(11353.1, 11162.6);
+ new ShapeRef(router, polygon, 2136);
+
+ // shapeRef2137
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11940.1, 12117.3);
+ polygon.ps[1] = Point(11940.1, 12137.3);
+ polygon.ps[2] = Point(11908.1, 12137.3);
+ polygon.ps[3] = Point(11908.1, 12117.3);
+ new ShapeRef(router, polygon, 2137);
+
+ // shapeRef2138
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12938.5, 12117.3);
+ polygon.ps[1] = Point(12938.5, 12137.3);
+ polygon.ps[2] = Point(12906.5, 12137.3);
+ polygon.ps[3] = Point(12906.5, 12117.3);
+ new ShapeRef(router, polygon, 2138);
+
+ // shapeRef2139
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8375.29, 1270.29);
+ polygon.ps[1] = Point(8375.29, 1290.29);
+ polygon.ps[2] = Point(8343.29, 1290.29);
+ polygon.ps[3] = Point(8343.29, 1270.29);
+ new ShapeRef(router, polygon, 2139);
+
+ // shapeRef2140
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7913.29, 1270.29);
+ polygon.ps[1] = Point(7913.29, 1290.29);
+ polygon.ps[2] = Point(7881.29, 1290.29);
+ polygon.ps[3] = Point(7881.29, 1270.29);
+ new ShapeRef(router, polygon, 2140);
+
+ // shapeRef2141
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7618.1, 1396.29);
+ polygon.ps[1] = Point(7618.1, 1428.29);
+ polygon.ps[2] = Point(7598.1, 1428.29);
+ polygon.ps[3] = Point(7598.1, 1396.29);
+ new ShapeRef(router, polygon, 2141);
+
+ // shapeRef2142
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7618.1, 2992.29);
+ polygon.ps[1] = Point(7618.1, 3024.29);
+ polygon.ps[2] = Point(7598.1, 3024.29);
+ polygon.ps[3] = Point(7598.1, 2992.29);
+ new ShapeRef(router, polygon, 2142);
+
+ // shapeRef2143
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9959.69, 9960.02);
+ polygon.ps[1] = Point(9959.69, 9992.02);
+ polygon.ps[2] = Point(9939.69, 9992.02);
+ polygon.ps[3] = Point(9939.69, 9960.02);
+ new ShapeRef(router, polygon, 2143);
+
+ // shapeRef2144
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15002.9, 1171.29);
+ polygon.ps[1] = Point(15002.9, 1191.29);
+ polygon.ps[2] = Point(14970.9, 1191.29);
+ polygon.ps[3] = Point(14970.9, 1171.29);
+ new ShapeRef(router, polygon, 2144);
+
+ // shapeRef2145
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16082.6, 11784.9);
+ polygon.ps[1] = Point(16082.6, 11804.9);
+ polygon.ps[2] = Point(16050.6, 11804.9);
+ polygon.ps[3] = Point(16050.6, 11784.9);
+ new ShapeRef(router, polygon, 2145);
+
+ // shapeRef2146
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1599, 4763.4);
+ polygon.ps[1] = Point(1599, 4783.4);
+ polygon.ps[2] = Point(1567, 4783.4);
+ polygon.ps[3] = Point(1567, 4763.4);
+ new ShapeRef(router, polygon, 2146);
+
+ // shapeRef2147
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3051, 4763.4);
+ polygon.ps[1] = Point(3051, 4783.4);
+ polygon.ps[2] = Point(3019, 4783.4);
+ polygon.ps[3] = Point(3019, 4763.4);
+ new ShapeRef(router, polygon, 2147);
+
+ // shapeRef2148
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4959, 6135.51);
+ polygon.ps[1] = Point(4959, 6167.51);
+ polygon.ps[2] = Point(4939, 6167.51);
+ polygon.ps[3] = Point(4939, 6135.51);
+ new ShapeRef(router, polygon, 2148);
+
+ // shapeRef2149
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14746, 1336.29);
+ polygon.ps[1] = Point(14746, 1356.29);
+ polygon.ps[2] = Point(14714, 1356.29);
+ polygon.ps[3] = Point(14714, 1336.29);
+ new ShapeRef(router, polygon, 2149);
+
+ // shapeRef2150
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9668.69, 6174.51);
+ polygon.ps[1] = Point(9668.69, 6194.51);
+ polygon.ps[2] = Point(9636.69, 6194.51);
+ polygon.ps[3] = Point(9636.69, 6174.51);
+ new ShapeRef(router, polygon, 2150);
+
+ // shapeRef2151
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7129.1, 10230);
+ polygon.ps[1] = Point(7129.1, 10250);
+ polygon.ps[2] = Point(7097.1, 10250);
+ polygon.ps[3] = Point(7097.1, 10230);
+ new ShapeRef(router, polygon, 2151);
+
+ // shapeRef2152
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8243.29, 9665.42);
+ polygon.ps[1] = Point(8243.29, 9685.42);
+ polygon.ps[2] = Point(8211.29, 9685.42);
+ polygon.ps[3] = Point(8211.29, 9665.42);
+ new ShapeRef(router, polygon, 2152);
+
+ // shapeRef2153
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8342.29, 9834.02);
+ polygon.ps[1] = Point(8342.29, 9854.02);
+ polygon.ps[2] = Point(8310.29, 9854.02);
+ polygon.ps[3] = Point(8310.29, 9834.02);
+ new ShapeRef(router, polygon, 2153);
+
+ // shapeRef2154
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10334.9, 9428.42);
+ polygon.ps[1] = Point(10334.9, 9460.42);
+ polygon.ps[2] = Point(10314.9, 9460.42);
+ polygon.ps[3] = Point(10314.9, 9428.42);
+ new ShapeRef(router, polygon, 2154);
+
+ // shapeRef2155
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8812.89, 10059);
+ polygon.ps[1] = Point(8812.89, 10091);
+ polygon.ps[2] = Point(8792.89, 10091);
+ polygon.ps[3] = Point(8792.89, 10059);
+ new ShapeRef(router, polygon, 2155);
+
+ // shapeRef2156
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(273, 132.265);
+ polygon.ps[1] = Point(273, 164.265);
+ polygon.ps[2] = Point(253, 164.265);
+ polygon.ps[3] = Point(253, 132.265);
+ new ShapeRef(router, polygon, 2156);
+
+ // shapeRef2157
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9214.59, 11682.9);
+ polygon.ps[1] = Point(9214.59, 11714.9);
+ polygon.ps[2] = Point(9194.59, 11714.9);
+ polygon.ps[3] = Point(9194.59, 11682.9);
+ new ShapeRef(router, polygon, 2157);
+
+ // shapeRef2158
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9029.99, 5641.9);
+ polygon.ps[1] = Point(9029.99, 5673.9);
+ polygon.ps[2] = Point(9009.99, 5673.9);
+ polygon.ps[3] = Point(9009.99, 5641.9);
+ new ShapeRef(router, polygon, 2158);
+
+ // shapeRef2159
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9029.99, 2365.29);
+ polygon.ps[1] = Point(9029.99, 2397.29);
+ polygon.ps[2] = Point(9009.99, 2397.29);
+ polygon.ps[3] = Point(9009.99, 2365.29);
+ new ShapeRef(router, polygon, 2159);
+
+ // shapeRef2160
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8468.29, 1462.29);
+ polygon.ps[1] = Point(8468.29, 1494.29);
+ polygon.ps[2] = Point(8448.29, 1494.29);
+ polygon.ps[3] = Point(8448.29, 1462.29);
+ new ShapeRef(router, polygon, 2160);
+
+ // shapeRef2161
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8634.29, 1468.29);
+ polygon.ps[1] = Point(8634.29, 1488.29);
+ polygon.ps[2] = Point(8602.29, 1488.29);
+ polygon.ps[3] = Point(8602.29, 1468.29);
+ new ShapeRef(router, polygon, 2161);
+
+ // shapeRef2162
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8276.29, 798.091);
+ polygon.ps[1] = Point(8276.29, 818.091);
+ polygon.ps[2] = Point(8244.29, 818.091);
+ polygon.ps[3] = Point(8244.29, 798.091);
+ new ShapeRef(router, polygon, 2162);
+
+ // shapeRef2163
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8270.29, 901.285);
+ polygon.ps[1] = Point(8270.29, 933.285);
+ polygon.ps[2] = Point(8250.29, 933.285);
+ polygon.ps[3] = Point(8250.29, 901.285);
+ new ShapeRef(router, polygon, 2163);
+
+ // shapeRef2164
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8634.29, 973.285);
+ polygon.ps[1] = Point(8634.29, 993.285);
+ polygon.ps[2] = Point(8602.29, 993.285);
+ polygon.ps[3] = Point(8602.29, 973.285);
+ new ShapeRef(router, polygon, 2164);
+
+ // shapeRef2165
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15249.5, 967.285);
+ polygon.ps[1] = Point(15249.5, 999.285);
+ polygon.ps[2] = Point(15229.5, 999.285);
+ polygon.ps[3] = Point(15229.5, 967.285);
+ new ShapeRef(router, polygon, 2165);
+
+ // shapeRef2166
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12707.5, 5304.67);
+ polygon.ps[1] = Point(12707.5, 5324.67);
+ polygon.ps[2] = Point(12675.5, 5324.67);
+ polygon.ps[3] = Point(12675.5, 5304.67);
+ new ShapeRef(router, polygon, 2166);
+
+ // shapeRef2167
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12369.1, 5304.67);
+ polygon.ps[1] = Point(12369.1, 5324.67);
+ polygon.ps[2] = Point(12337.1, 5324.67);
+ polygon.ps[3] = Point(12337.1, 5304.67);
+ new ShapeRef(router, polygon, 2167);
+
+ // shapeRef2168
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13117, 4532.4);
+ polygon.ps[1] = Point(13117, 4552.4);
+ polygon.ps[2] = Point(13085, 4552.4);
+ polygon.ps[3] = Point(13085, 4532.4);
+ new ShapeRef(router, polygon, 2168);
+
+ // shapeRef2169
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13492, 3852.51);
+ polygon.ps[1] = Point(13492, 3872.51);
+ polygon.ps[2] = Point(13460, 3872.51);
+ polygon.ps[3] = Point(13460, 3852.51);
+ new ShapeRef(router, polygon, 2169);
+
+ // shapeRef2170
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12707.5, 3984.51);
+ polygon.ps[1] = Point(12707.5, 4004.51);
+ polygon.ps[2] = Point(12675.5, 4004.51);
+ polygon.ps[3] = Point(12675.5, 3984.51);
+ new ShapeRef(router, polygon, 2170);
+
+ // shapeRef2171
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11254.2, 9038.42);
+ polygon.ps[1] = Point(11254.2, 9058.42);
+ polygon.ps[2] = Point(11222.2, 9058.42);
+ polygon.ps[3] = Point(11222.2, 9038.42);
+ new ShapeRef(router, polygon, 2171);
+
+ // shapeRef2172
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5506.1, 4559.4);
+ polygon.ps[1] = Point(5506.1, 4591.4);
+ polygon.ps[2] = Point(5486.1, 4591.4);
+ polygon.ps[3] = Point(5486.1, 4559.4);
+ new ShapeRef(router, polygon, 2172);
+
+ // shapeRef2173
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5506.1, 5153.4);
+ polygon.ps[1] = Point(5506.1, 5185.4);
+ polygon.ps[2] = Point(5486.1, 5185.4);
+ polygon.ps[3] = Point(5486.1, 5153.4);
+ new ShapeRef(router, polygon, 2173);
+
+ // shapeRef2174
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15851.6, 1336.29);
+ polygon.ps[1] = Point(15851.6, 1356.29);
+ polygon.ps[2] = Point(15819.6, 1356.29);
+ polygon.ps[3] = Point(15819.6, 1336.29);
+ new ShapeRef(router, polygon, 2174);
+
+ // shapeRef2175
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11122.2, 8239.99);
+ polygon.ps[1] = Point(11122.2, 8259.99);
+ polygon.ps[2] = Point(11090.2, 8259.99);
+ polygon.ps[3] = Point(11090.2, 8239.99);
+ new ShapeRef(router, polygon, 2175);
+
+ // shapeRef2176
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16540.8, 7415.4);
+ polygon.ps[1] = Point(16540.8, 7435.4);
+ polygon.ps[2] = Point(16508.8, 7435.4);
+ polygon.ps[3] = Point(16508.8, 7415.4);
+ new ShapeRef(router, polygon, 2176);
+
+ // shapeRef2177
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16540.8, 7536.79);
+ polygon.ps[1] = Point(16540.8, 7556.79);
+ polygon.ps[2] = Point(16508.8, 7556.79);
+ polygon.ps[3] = Point(16508.8, 7536.79);
+ new ShapeRef(router, polygon, 2177);
+
+ // shapeRef2178
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18532, 11972.3);
+ polygon.ps[1] = Point(18532, 11992.3);
+ polygon.ps[2] = Point(18500, 11992.3);
+ polygon.ps[3] = Point(18500, 11972.3);
+ new ShapeRef(router, polygon, 2178);
+
+ // shapeRef2179
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10819.2, 5641.9);
+ polygon.ps[1] = Point(10819.2, 5673.9);
+ polygon.ps[2] = Point(10799.2, 5673.9);
+ polygon.ps[3] = Point(10799.2, 5641.9);
+ new ShapeRef(router, polygon, 2179);
+
+ // shapeRef2180
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15620.3, 1171.29);
+ polygon.ps[1] = Point(15620.3, 1191.29);
+ polygon.ps[2] = Point(15588.3, 1191.29);
+ polygon.ps[3] = Point(15588.3, 1171.29);
+ new ShapeRef(router, polygon, 2180);
+
+ // shapeRef2181
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11254.2, 4499.4);
+ polygon.ps[1] = Point(11254.2, 4519.4);
+ polygon.ps[2] = Point(11222.2, 4519.4);
+ polygon.ps[3] = Point(11222.2, 4499.4);
+ new ShapeRef(router, polygon, 2181);
+
+ // shapeRef2182
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11254.2, 4182.51);
+ polygon.ps[1] = Point(11254.2, 4202.51);
+ polygon.ps[2] = Point(11222.2, 4202.51);
+ polygon.ps[3] = Point(11222.2, 4182.51);
+ new ShapeRef(router, polygon, 2182);
+
+ // shapeRef2183
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14614, 6953.4);
+ polygon.ps[1] = Point(14614, 6973.4);
+ polygon.ps[2] = Point(14582, 6973.4);
+ polygon.ps[3] = Point(14582, 6953.4);
+ new ShapeRef(router, polygon, 2183);
+
+ // shapeRef2184
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14614, 6636.51);
+ polygon.ps[1] = Point(14614, 6656.51);
+ polygon.ps[2] = Point(14582, 6656.51);
+ polygon.ps[3] = Point(14582, 6636.51);
+ new ShapeRef(router, polygon, 2184);
+
+ // shapeRef2185
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9992.69, 9692.42);
+ polygon.ps[1] = Point(9992.69, 9724.42);
+ polygon.ps[2] = Point(9972.69, 9724.42);
+ polygon.ps[3] = Point(9972.69, 9692.42);
+ new ShapeRef(router, polygon, 2185);
+
+ // shapeRef2186
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8700.29, 11376.8);
+ polygon.ps[1] = Point(8700.29, 11396.8);
+ polygon.ps[2] = Point(8668.29, 11396.8);
+ polygon.ps[3] = Point(8668.29, 11376.8);
+ new ShapeRef(router, polygon, 2186);
+
+ // shapeRef2187
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16076.6, 11531.7);
+ polygon.ps[1] = Point(16076.6, 11563.7);
+ polygon.ps[2] = Point(16056.6, 11563.7);
+ polygon.ps[3] = Point(16056.6, 11531.7);
+ new ShapeRef(router, polygon, 2187);
+
+ // shapeRef2188
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16082.6, 11376.8);
+ polygon.ps[1] = Point(16082.6, 11396.8);
+ polygon.ps[2] = Point(16050.6, 11396.8);
+ polygon.ps[3] = Point(16050.6, 11376.8);
+ new ShapeRef(router, polygon, 2188);
+
+ // shapeRef2189
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14218, 12415.7);
+ polygon.ps[1] = Point(14218, 12435.7);
+ polygon.ps[2] = Point(14186, 12435.7);
+ polygon.ps[3] = Point(14186, 12415.7);
+ new ShapeRef(router, polygon, 2189);
+
+ // shapeRef2190
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9695.69, 7343.4);
+ polygon.ps[1] = Point(9695.69, 7375.4);
+ polygon.ps[2] = Point(9675.69, 7375.4);
+ polygon.ps[3] = Point(9675.69, 7343.4);
+ new ShapeRef(router, polygon, 2190);
+
+ // shapeRef2191
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15781.9, 10904.6);
+ polygon.ps[1] = Point(15781.9, 10924.6);
+ polygon.ps[2] = Point(15749.9, 10924.6);
+ polygon.ps[3] = Point(15749.9, 10904.6);
+ new ShapeRef(router, polygon, 2191);
+
+ // shapeRef2192
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(669, 132.265);
+ polygon.ps[1] = Point(669, 164.265);
+ polygon.ps[2] = Point(649, 164.265);
+ polygon.ps[3] = Point(649, 132.265);
+ new ShapeRef(router, polygon, 2192);
+
+ // shapeRef2193
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15158.3, 11877.9);
+ polygon.ps[1] = Point(15158.3, 11909.9);
+ polygon.ps[2] = Point(15138.3, 11909.9);
+ polygon.ps[3] = Point(15138.3, 11877.9);
+ new ShapeRef(router, polygon, 2193);
+
+ // shapeRef2194
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7775.29, 1396.29);
+ polygon.ps[1] = Point(7775.29, 1428.29);
+ polygon.ps[2] = Point(7755.29, 1428.29);
+ polygon.ps[3] = Point(7755.29, 1396.29);
+ new ShapeRef(router, polygon, 2194);
+
+ // shapeRef2195
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12938.5, 12448.7);
+ polygon.ps[1] = Point(12938.5, 12468.7);
+ polygon.ps[2] = Point(12906.5, 12468.7);
+ polygon.ps[3] = Point(12906.5, 12448.7);
+ new ShapeRef(router, polygon, 2195);
+
+ // shapeRef2196
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15793.4, 10924.6);
+ polygon.ps[1] = Point(15793.4, 10984.6);
+ polygon.ps[2] = Point(15738.4, 10984.6);
+ polygon.ps[3] = Point(15738.4, 10924.6);
+ new ShapeRef(router, polygon, 2196);
+
+ // shapeRef2197
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14257, 12435.7);
+ polygon.ps[1] = Point(14257, 12495.7);
+ polygon.ps[2] = Point(14202, 12495.7);
+ polygon.ps[3] = Point(14202, 12435.7);
+ new ShapeRef(router, polygon, 2197);
+
+ // shapeRef2198
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16152.1, 11545.2);
+ polygon.ps[1] = Point(16152.1, 11585.2);
+ polygon.ps[2] = Point(16076.6, 11585.2);
+ polygon.ps[3] = Point(16076.6, 11545.2);
+ new ShapeRef(router, polygon, 2198);
+
+ // shapeRef2199
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16094.1, 11316.8);
+ polygon.ps[1] = Point(16094.1, 11376.8);
+ polygon.ps[2] = Point(16039.1, 11376.8);
+ polygon.ps[3] = Point(16039.1, 11316.8);
+ new ShapeRef(router, polygon, 2199);
+
+ // shapeRef2200
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(348.5, 148.265);
+ polygon.ps[1] = Point(348.5, 188.265);
+ polygon.ps[2] = Point(273, 188.265);
+ polygon.ps[3] = Point(273, 148.265);
+ new ShapeRef(router, polygon, 2200);
+
+ // shapeRef2201
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(744.5, 110.765);
+ polygon.ps[1] = Point(744.5, 150.765);
+ polygon.ps[2] = Point(669, 150.765);
+ polygon.ps[3] = Point(669, 110.765);
+ new ShapeRef(router, polygon, 2201);
+
+ // shapeRef2202
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15233.8, 11891.4);
+ polygon.ps[1] = Point(15233.8, 11931.4);
+ polygon.ps[2] = Point(15158.3, 11931.4);
+ polygon.ps[3] = Point(15158.3, 11891.4);
+ new ShapeRef(router, polygon, 2202);
+
+ // shapeRef2203
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9771.19, 7339.4);
+ polygon.ps[1] = Point(9771.19, 7379.4);
+ polygon.ps[2] = Point(9695.69, 7379.4);
+ polygon.ps[3] = Point(9695.69, 7339.4);
+ new ShapeRef(router, polygon, 2203);
+
+ // shapeRef2204
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9972.69, 9688.42);
+ polygon.ps[1] = Point(9972.69, 9728.42);
+ polygon.ps[2] = Point(9897.19, 9728.42);
+ polygon.ps[3] = Point(9897.19, 9688.42);
+ new ShapeRef(router, polygon, 2204);
+
+ // shapeRef2205
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14625.5, 6973.4);
+ polygon.ps[1] = Point(14625.5, 7033.4);
+ polygon.ps[2] = Point(14570.5, 7033.4);
+ polygon.ps[3] = Point(14570.5, 6973.4);
+ new ShapeRef(router, polygon, 2205);
+
+ // shapeRef2206
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14600.5, 6576.51);
+ polygon.ps[1] = Point(14600.5, 6636.51);
+ polygon.ps[2] = Point(14545.5, 6636.51);
+ polygon.ps[3] = Point(14545.5, 6576.51);
+ new ShapeRef(router, polygon, 2206);
+
+ // shapeRef2207
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16552.3, 7355.4);
+ polygon.ps[1] = Point(16552.3, 7415.4);
+ polygon.ps[2] = Point(16497.3, 7415.4);
+ polygon.ps[3] = Point(16497.3, 7355.4);
+ new ShapeRef(router, polygon, 2207);
+
+ // shapeRef2208
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16552.3, 7556.79);
+ polygon.ps[1] = Point(16552.3, 7616.79);
+ polygon.ps[2] = Point(16497.3, 7616.79);
+ polygon.ps[3] = Point(16497.3, 7556.79);
+ new ShapeRef(router, polygon, 2208);
+
+ // shapeRef2209
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14732.5, 1276.29);
+ polygon.ps[1] = Point(14732.5, 1336.29);
+ polygon.ps[2] = Point(14677.5, 1336.29);
+ polygon.ps[3] = Point(14677.5, 1276.29);
+ new ShapeRef(router, polygon, 2209);
+
+ // shapeRef2210
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9705.19, 6114.51);
+ polygon.ps[1] = Point(9705.19, 6174.51);
+ polygon.ps[2] = Point(9650.19, 6174.51);
+ polygon.ps[3] = Point(9650.19, 6114.51);
+ new ShapeRef(router, polygon, 2210);
+
+ // shapeRef2211
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7140.6, 10170);
+ polygon.ps[1] = Point(7140.6, 10230);
+ polygon.ps[2] = Point(7085.6, 10230);
+ polygon.ps[3] = Point(7085.6, 10170);
+ new ShapeRef(router, polygon, 2211);
+
+ // shapeRef2212
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8229.79, 9605.42);
+ polygon.ps[1] = Point(8229.79, 9665.42);
+ polygon.ps[2] = Point(8174.79, 9665.42);
+ polygon.ps[3] = Point(8174.79, 9605.42);
+ new ShapeRef(router, polygon, 2212);
+
+ // shapeRef2213
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8378.79, 9774.02);
+ polygon.ps[1] = Point(8378.79, 9834.02);
+ polygon.ps[2] = Point(8323.79, 9834.02);
+ polygon.ps[3] = Point(8323.79, 9774.02);
+ new ShapeRef(router, polygon, 2213);
+
+ // shapeRef2214
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10410.4, 9424.42);
+ polygon.ps[1] = Point(10410.4, 9464.42);
+ polygon.ps[2] = Point(10334.9, 9464.42);
+ polygon.ps[3] = Point(10334.9, 9424.42);
+ new ShapeRef(router, polygon, 2214);
+
+ // shapeRef2215
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8888.39, 10055);
+ polygon.ps[1] = Point(8888.39, 10095);
+ polygon.ps[2] = Point(8812.89, 10095);
+ polygon.ps[3] = Point(8812.89, 10055);
+ new ShapeRef(router, polygon, 2215);
+
+ // shapeRef2216
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(348.5, 108.265);
+ polygon.ps[1] = Point(348.5, 148.265);
+ polygon.ps[2] = Point(273, 148.265);
+ polygon.ps[3] = Point(273, 108.265);
+ new ShapeRef(router, polygon, 2216);
+
+ // shapeRef2217
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(398.5, 128.265);
+ polygon.ps[1] = Point(398.5, 168.265);
+ polygon.ps[2] = Point(273, 168.265);
+ polygon.ps[3] = Point(273, 128.265);
+ new ShapeRef(router, polygon, 2217);
+
+ // shapeRef2218
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9290.09, 11678.9);
+ polygon.ps[1] = Point(9290.09, 11718.9);
+ polygon.ps[2] = Point(9214.59, 11718.9);
+ polygon.ps[3] = Point(9214.59, 11678.9);
+ new ShapeRef(router, polygon, 2218);
+
+ // shapeRef2219
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9105.49, 5637.9);
+ polygon.ps[1] = Point(9105.49, 5677.9);
+ polygon.ps[2] = Point(9029.99, 5677.9);
+ polygon.ps[3] = Point(9029.99, 5637.9);
+ new ShapeRef(router, polygon, 2219);
+
+ // shapeRef2220
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9105.49, 2381.29);
+ polygon.ps[1] = Point(9105.49, 2421.29);
+ polygon.ps[2] = Point(9029.99, 2421.29);
+ polygon.ps[3] = Point(9029.99, 2381.29);
+ new ShapeRef(router, polygon, 2220);
+
+ // shapeRef2221
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8543.79, 1458.29);
+ polygon.ps[1] = Point(8543.79, 1498.29);
+ polygon.ps[2] = Point(8468.29, 1498.29);
+ polygon.ps[3] = Point(8468.29, 1458.29);
+ new ShapeRef(router, polygon, 2221);
+
+ // shapeRef2222
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8620.79, 1488.29);
+ polygon.ps[1] = Point(8620.79, 1548.29);
+ polygon.ps[2] = Point(8565.79, 1548.29);
+ polygon.ps[3] = Point(8565.79, 1488.29);
+ new ShapeRef(router, polygon, 2222);
+
+ // shapeRef2223
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8287.79, 738.091);
+ polygon.ps[1] = Point(8287.79, 798.091);
+ polygon.ps[2] = Point(8232.79, 798.091);
+ polygon.ps[3] = Point(8232.79, 738.091);
+ new ShapeRef(router, polygon, 2223);
+
+ // shapeRef2224
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8250.29, 879.785);
+ polygon.ps[1] = Point(8250.29, 919.785);
+ polygon.ps[2] = Point(8174.79, 919.785);
+ polygon.ps[3] = Point(8174.79, 879.785);
+ new ShapeRef(router, polygon, 2224);
+
+ // shapeRef2225
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8645.79, 913.285);
+ polygon.ps[1] = Point(8645.79, 973.285);
+ polygon.ps[2] = Point(8590.79, 973.285);
+ polygon.ps[3] = Point(8590.79, 913.285);
+ new ShapeRef(router, polygon, 2225);
+
+ // shapeRef2226
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15325, 980.785);
+ polygon.ps[1] = Point(15325, 1020.79);
+ polygon.ps[2] = Point(15249.5, 1020.79);
+ polygon.ps[3] = Point(15249.5, 980.785);
+ new ShapeRef(router, polygon, 2226);
+
+ // shapeRef2227
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11290.7, 4519.4);
+ polygon.ps[1] = Point(11290.7, 4579.4);
+ polygon.ps[2] = Point(11235.7, 4579.4);
+ polygon.ps[3] = Point(11235.7, 4519.4);
+ new ShapeRef(router, polygon, 2227);
+
+ // shapeRef2228
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11290.7, 4122.51);
+ polygon.ps[1] = Point(11290.7, 4182.51);
+ polygon.ps[2] = Point(11235.7, 4182.51);
+ polygon.ps[3] = Point(11235.7, 4122.51);
+ new ShapeRef(router, polygon, 2228);
+
+ // shapeRef2229
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12744, 5324.67);
+ polygon.ps[1] = Point(12744, 5384.67);
+ polygon.ps[2] = Point(12689, 5384.67);
+ polygon.ps[3] = Point(12689, 5324.67);
+ new ShapeRef(router, polygon, 2229);
+
+ // shapeRef2230
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12408.1, 5244.67);
+ polygon.ps[1] = Point(12408.1, 5304.67);
+ polygon.ps[2] = Point(12353.1, 5304.67);
+ polygon.ps[3] = Point(12353.1, 5244.67);
+ new ShapeRef(router, polygon, 2230);
+
+ // shapeRef2231
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13528.5, 3792.51);
+ polygon.ps[1] = Point(13528.5, 3852.51);
+ polygon.ps[2] = Point(13473.5, 3852.51);
+ polygon.ps[3] = Point(13473.5, 3792.51);
+ new ShapeRef(router, polygon, 2231);
+
+ // shapeRef2232
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13128.5, 4472.4);
+ polygon.ps[1] = Point(13128.5, 4532.4);
+ polygon.ps[2] = Point(13073.5, 4532.4);
+ polygon.ps[3] = Point(13073.5, 4472.4);
+ new ShapeRef(router, polygon, 2232);
+
+ // shapeRef2233
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12719, 3924.51);
+ polygon.ps[1] = Point(12719, 3984.51);
+ polygon.ps[2] = Point(12664, 3984.51);
+ polygon.ps[3] = Point(12664, 3924.51);
+ new ShapeRef(router, polygon, 2233);
+
+ // shapeRef2234
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18543.5, 11992.3);
+ polygon.ps[1] = Point(18543.5, 12052.3);
+ polygon.ps[2] = Point(18488.5, 12052.3);
+ polygon.ps[3] = Point(18488.5, 11992.3);
+ new ShapeRef(router, polygon, 2234);
+
+ // shapeRef2235
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11265.7, 9058.42);
+ polygon.ps[1] = Point(11265.7, 9118.42);
+ polygon.ps[2] = Point(11210.7, 9118.42);
+ polygon.ps[3] = Point(11210.7, 9058.42);
+ new ShapeRef(router, polygon, 2235);
+
+ // shapeRef2236
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15888.1, 1356.29);
+ polygon.ps[1] = Point(15888.1, 1416.29);
+ polygon.ps[2] = Point(15833.1, 1416.29);
+ polygon.ps[3] = Point(15833.1, 1356.29);
+ new ShapeRef(router, polygon, 2236);
+
+ // shapeRef2237
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11133.7, 8259.99);
+ polygon.ps[1] = Point(11133.7, 8319.99);
+ polygon.ps[2] = Point(11078.7, 8319.99);
+ polygon.ps[3] = Point(11078.7, 8259.99);
+ new ShapeRef(router, polygon, 2237);
+
+ // shapeRef2238
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10894.7, 5655.4);
+ polygon.ps[1] = Point(10894.7, 5695.4);
+ polygon.ps[2] = Point(10819.2, 5695.4);
+ polygon.ps[3] = Point(10819.2, 5655.4);
+ new ShapeRef(router, polygon, 2238);
+
+ // shapeRef2239
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15631.8, 1111.29);
+ polygon.ps[1] = Point(15631.8, 1171.29);
+ polygon.ps[2] = Point(15576.8, 1171.29);
+ polygon.ps[3] = Point(15576.8, 1111.29);
+ new ShapeRef(router, polygon, 2239);
+
+ // shapeRef2240
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15760.4, 1276.29);
+ polygon.ps[1] = Point(15760.4, 1336.29);
+ polygon.ps[2] = Point(15705.4, 1336.29);
+ polygon.ps[3] = Point(15705.4, 1276.29);
+ new ShapeRef(router, polygon, 2240);
+
+ // shapeRef2241
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5581.6, 4555.4);
+ polygon.ps[1] = Point(5581.6, 4595.4);
+ polygon.ps[2] = Point(5506.1, 4595.4);
+ polygon.ps[3] = Point(5506.1, 4555.4);
+ new ShapeRef(router, polygon, 2241);
+
+ // shapeRef2242
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5581.6, 5149.4);
+ polygon.ps[1] = Point(5581.6, 5189.4);
+ polygon.ps[2] = Point(5506.1, 5189.4);
+ polygon.ps[3] = Point(5506.1, 5149.4);
+ new ShapeRef(router, polygon, 2242);
+
+ // shapeRef2243
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8711.79, 11396.8);
+ polygon.ps[1] = Point(8711.79, 11456.8);
+ polygon.ps[2] = Point(8656.79, 11456.8);
+ polygon.ps[3] = Point(8656.79, 11396.8);
+ new ShapeRef(router, polygon, 2243);
+
+ // shapeRef2244
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7850.79, 1392.29);
+ polygon.ps[1] = Point(7850.79, 1432.29);
+ polygon.ps[2] = Point(7775.29, 1432.29);
+ polygon.ps[3] = Point(7775.29, 1392.29);
+ new ShapeRef(router, polygon, 2244);
+
+ // shapeRef2245
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12925, 12388.7);
+ polygon.ps[1] = Point(12925, 12448.7);
+ polygon.ps[2] = Point(12870, 12448.7);
+ polygon.ps[3] = Point(12870, 12388.7);
+ new ShapeRef(router, polygon, 2245);
+
+ // shapeRef2246
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4751, 10448);
+ polygon.ps[1] = Point(4751, 10494.2);
+ polygon.ps[2] = Point(4666.9, 10494.2);
+ polygon.ps[3] = Point(4666.9, 10448);
+ new ShapeRef(router, polygon, 2246);
+
+ // shapeRef2247
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4543, 10583.3);
+ polygon.ps[1] = Point(4543, 10667.4);
+ polygon.ps[2] = Point(4496.77, 10667.4);
+ polygon.ps[3] = Point(4496.77, 10583.3);
+ new ShapeRef(router, polygon, 2247);
+
+ // shapeRef2248
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7930.29, 7138.4);
+ polygon.ps[1] = Point(7930.29, 7183.1);
+ polygon.ps[2] = Point(7872.07, 7183.1);
+ polygon.ps[3] = Point(7872.07, 7138.4);
+ new ShapeRef(router, polygon, 2248);
+
+ // shapeRef2249
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9430.15, 9652.42);
+ polygon.ps[1] = Point(9430.15, 9724.02);
+ polygon.ps[2] = Point(9369.59, 9724.02);
+ polygon.ps[3] = Point(9369.59, 9652.42);
+ new ShapeRef(router, polygon, 2249);
+
+ // shapeRef2250
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8825.89, 2320.72);
+ polygon.ps[1] = Point(8825.89, 2381.29);
+ polygon.ps[2] = Point(8754.29, 2381.29);
+ polygon.ps[3] = Point(8754.29, 2320.72);
+ new ShapeRef(router, polygon, 2250);
+
+ // shapeRef2251
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12521.5, 5314.67);
+ polygon.ps[1] = Point(12521.5, 5375.23);
+ polygon.ps[2] = Point(12449.9, 5375.23);
+ polygon.ps[3] = Point(12449.9, 5314.67);
+ new ShapeRef(router, polygon, 2251);
+
+ // shapeRef2252
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12922.5, 4519.4);
+ polygon.ps[1] = Point(12922.5, 4564.1);
+ polygon.ps[2] = Point(12864.3, 4564.1);
+ polygon.ps[3] = Point(12864.3, 4519.4);
+ new ShapeRef(router, polygon, 2252);
+
+ // shapeRef2253
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11296.4, 8883.22);
+ polygon.ps[1] = Point(11296.4, 8927.91);
+ polygon.ps[2] = Point(11238.2, 8927.91);
+ polygon.ps[3] = Point(11238.2, 8883.22);
+ new ShapeRef(router, polygon, 2253);
+
+ // shapeRef2254
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15637.3, 468.265);
+ polygon.ps[1] = Point(15637.3, 514.5);
+ polygon.ps[2] = Point(15553.2, 514.5);
+ polygon.ps[3] = Point(15553.2, 468.265);
+ new ShapeRef(router, polygon, 2254);
+
+ // shapeRef2255
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11164.4, 8084.79);
+ polygon.ps[1] = Point(11164.4, 8129.49);
+ polygon.ps[2] = Point(11106.2, 8129.49);
+ polygon.ps[3] = Point(11106.2, 8084.79);
+ new ShapeRef(router, polygon, 2255);
+
+ // shapeRef2256
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14598, 6798.21);
+ polygon.ps[1] = Point(14598, 6842.9);
+ polygon.ps[2] = Point(14539.8, 6842.9);
+ polygon.ps[3] = Point(14539.8, 6798.21);
+ new ShapeRef(router, polygon, 2256);
+
+ // shapeRef2257
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10314.9, 9708.42);
+ polygon.ps[1] = Point(10314.9, 9766.64);
+ polygon.ps[2] = Point(10270.2, 9766.64);
+ polygon.ps[3] = Point(10270.2, 9708.42);
+ new ShapeRef(router, polygon, 2257);
+
+ // shapeRef2258
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15045.1, 12302.3);
+ polygon.ps[1] = Point(15045.1, 12347);
+ polygon.ps[2] = Point(14986.9, 12347);
+ polygon.ps[3] = Point(14986.9, 12302.3);
+ new ShapeRef(router, polygon, 2258);
+
+ // shapeRef2259
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14202, 12302.3);
+ polygon.ps[1] = Point(14202, 12373.9);
+ polygon.ps[2] = Point(14141.4, 12373.9);
+ polygon.ps[3] = Point(14141.4, 12302.3);
+ new ShapeRef(router, polygon, 2259);
+
+ // shapeRef2260
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15850, 10791.3);
+ polygon.ps[1] = Point(15850, 10837.5);
+ polygon.ps[2] = Point(15765.9, 10837.5);
+ polygon.ps[3] = Point(15765.9, 10791.3);
+ new ShapeRef(router, polygon, 2260);
+
+ // shapeRef2261
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7755.29, 790.723);
+ polygon.ps[1] = Point(7755.29, 851.285);
+ polygon.ps[2] = Point(7683.69, 851.285);
+ polygon.ps[3] = Point(7683.69, 790.723);
+ new ShapeRef(router, polygon, 2261);
+
+ // shapeRef2262
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11924.1, 12137.3);
+ polygon.ps[1] = Point(11924.1, 12182);
+ polygon.ps[2] = Point(11865.9, 12182);
+ polygon.ps[3] = Point(11865.9, 12137.3);
+ new ShapeRef(router, polygon, 2262);
+
+ // shapeRef2263
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12922.5, 12137.3);
+ polygon.ps[1] = Point(12922.5, 12208.9);
+ polygon.ps[2] = Point(12861.9, 12208.9);
+ polygon.ps[3] = Point(12861.9, 12137.3);
+ new ShapeRef(router, polygon, 2263);
+
+ // shapeRef2264
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7598.1, 2950.06);
+ polygon.ps[1] = Point(7598.1, 3008.29);
+ polygon.ps[2] = Point(7553.4, 3008.29);
+ polygon.ps[3] = Point(7553.4, 2950.06);
+ new ShapeRef(router, polygon, 2264);
+
+ // shapeRef2265
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(253, 148.265);
+ polygon.ps[1] = Point(253, 208.827);
+ polygon.ps[2] = Point(181.401, 208.827);
+ polygon.ps[3] = Point(181.401, 148.265);
+ new ShapeRef(router, polygon, 2265);
+
+ // shapeRef2266
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5486.1, 4575.4);
+ polygon.ps[1] = Point(5486.1, 4659.5);
+ polygon.ps[2] = Point(5439.86, 4659.5);
+ polygon.ps[3] = Point(5439.86, 4575.4);
+ new ShapeRef(router, polygon, 2266);
+
+ // shapeRef2267
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5486.1, 5169.4);
+ polygon.ps[1] = Point(5486.1, 5253.5);
+ polygon.ps[2] = Point(5439.86, 5253.5);
+ polygon.ps[3] = Point(5439.86, 5169.4);
+ new ShapeRef(router, polygon, 2267);
+
+ // shapeRef2268
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11296.4, 4202.51);
+ polygon.ps[1] = Point(11296.4, 4247.21);
+ polygon.ps[2] = Point(11238.2, 4247.21);
+ polygon.ps[3] = Point(11238.2, 4202.51);
+ new ShapeRef(router, polygon, 2268);
+
+ // shapeRef2269
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16127.2, 11396.8);
+ polygon.ps[1] = Point(16127.2, 11468.4);
+ polygon.ps[2] = Point(16066.6, 11468.4);
+ polygon.ps[3] = Point(16066.6, 11396.8);
+ new ShapeRef(router, polygon, 2269);
+
+ // shapeRef2270
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9369.59, 9652.42);
+ polygon.ps[1] = Point(9369.59, 9728.65);
+ polygon.ps[2] = Point(9279.83, 9728.65);
+ polygon.ps[3] = Point(9279.83, 9652.42);
+ new ShapeRef(router, polygon, 2270);
+
+ // shapeRef2271
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8825.89, 2381.29);
+ polygon.ps[1] = Point(8825.89, 2465.38);
+ polygon.ps[2] = Point(8779.66, 2465.38);
+ polygon.ps[3] = Point(8779.66, 2381.29);
+ new ShapeRef(router, polygon, 2271);
+
+ // shapeRef2272
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12521.5, 5224.91);
+ polygon.ps[1] = Point(12521.5, 5314.67);
+ polygon.ps[2] = Point(12445.3, 5314.67);
+ polygon.ps[3] = Point(12445.3, 5224.91);
+ new ShapeRef(router, polygon, 2272);
+
+ // shapeRef2273
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13012.3, 4519.4);
+ polygon.ps[1] = Point(13012.3, 4595.63);
+ polygon.ps[2] = Point(12922.5, 4595.63);
+ polygon.ps[3] = Point(12922.5, 4519.4);
+ new ShapeRef(router, polygon, 2273);
+
+ // shapeRef2274
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11238.2, 8883.22);
+ polygon.ps[1] = Point(11238.2, 8929.45);
+ polygon.ps[2] = Point(11154.1, 8929.45);
+ polygon.ps[3] = Point(11154.1, 8883.22);
+ new ShapeRef(router, polygon, 2274);
+
+ // shapeRef2275
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15721.4, 468.265);
+ polygon.ps[1] = Point(15721.4, 514.5);
+ polygon.ps[2] = Point(15637.3, 514.5);
+ polygon.ps[3] = Point(15637.3, 468.265);
+ new ShapeRef(router, polygon, 2275);
+
+ // shapeRef2276
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11106.2, 8084.79);
+ polygon.ps[1] = Point(11106.2, 8131.03);
+ polygon.ps[2] = Point(11022.1, 8131.03);
+ polygon.ps[3] = Point(11022.1, 8084.79);
+ new ShapeRef(router, polygon, 2276);
+
+ // shapeRef2277
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14682.1, 6798.21);
+ polygon.ps[1] = Point(14682.1, 6844.44);
+ polygon.ps[2] = Point(14598, 6844.44);
+ polygon.ps[3] = Point(14598, 6798.21);
+ new ShapeRef(router, polygon, 2277);
+
+ // shapeRef2278
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10314.9, 9618.65);
+ polygon.ps[1] = Point(10314.9, 9708.42);
+ polygon.ps[2] = Point(10238.7, 9708.42);
+ polygon.ps[3] = Point(10238.7, 9618.65);
+ new ShapeRef(router, polygon, 2278);
+
+ // shapeRef2279
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14986.9, 12302.3);
+ polygon.ps[1] = Point(14986.9, 12348.5);
+ polygon.ps[2] = Point(14902.8, 12348.5);
+ polygon.ps[3] = Point(14902.8, 12302.3);
+ new ShapeRef(router, polygon, 2279);
+
+ // shapeRef2280
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14291.7, 12302.3);
+ polygon.ps[1] = Point(14291.7, 12378.5);
+ polygon.ps[2] = Point(14202, 12378.5);
+ polygon.ps[3] = Point(14202, 12302.3);
+ new ShapeRef(router, polygon, 2280);
+
+ // shapeRef2281
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15765.9, 10791.3);
+ polygon.ps[1] = Point(15765.9, 10867.5);
+ polygon.ps[2] = Point(15676.1, 10867.5);
+ polygon.ps[3] = Point(15676.1, 10791.3);
+ new ShapeRef(router, polygon, 2281);
+
+ // shapeRef2282
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7755.29, 851.285);
+ polygon.ps[1] = Point(7755.29, 935.383);
+ polygon.ps[2] = Point(7709.06, 935.383);
+ polygon.ps[3] = Point(7709.06, 851.285);
+ new ShapeRef(router, polygon, 2282);
+
+ // shapeRef2283
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12008.2, 12137.3);
+ polygon.ps[1] = Point(12008.2, 12183.5);
+ polygon.ps[2] = Point(11924.1, 12183.5);
+ polygon.ps[3] = Point(11924.1, 12137.3);
+ new ShapeRef(router, polygon, 2283);
+
+ // shapeRef2284
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13006.6, 12137.3);
+ polygon.ps[1] = Point(13006.6, 12183.5);
+ polygon.ps[2] = Point(12922.5, 12183.5);
+ polygon.ps[3] = Point(12922.5, 12137.3);
+ new ShapeRef(router, polygon, 2284);
+
+ // shapeRef2285
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7598.1, 3008.29);
+ polygon.ps[1] = Point(7598.1, 3092.38);
+ polygon.ps[2] = Point(7551.86, 3092.38);
+ polygon.ps[3] = Point(7551.86, 3008.29);
+ new ShapeRef(router, polygon, 2285);
+
+ // shapeRef2286
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(253, 58.5019);
+ polygon.ps[1] = Point(253, 148.265);
+ polygon.ps[2] = Point(176.77, 148.265);
+ polygon.ps[3] = Point(176.77, 58.5019);
+ new ShapeRef(router, polygon, 2286);
+
+ // shapeRef2287
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5486.1, 4491.31);
+ polygon.ps[1] = Point(5486.1, 4575.4);
+ polygon.ps[2] = Point(5439.86, 4575.4);
+ polygon.ps[3] = Point(5439.86, 4491.31);
+ new ShapeRef(router, polygon, 2287);
+
+ // shapeRef2288
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5486.1, 5085.31);
+ polygon.ps[1] = Point(5486.1, 5169.4);
+ polygon.ps[2] = Point(5439.86, 5169.4);
+ polygon.ps[3] = Point(5439.86, 5085.31);
+ new ShapeRef(router, polygon, 2288);
+
+ // shapeRef2289
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11238.2, 4202.51);
+ polygon.ps[1] = Point(11238.2, 4248.75);
+ polygon.ps[2] = Point(11154.1, 4248.75);
+ polygon.ps[3] = Point(11154.1, 4202.51);
+ new ShapeRef(router, polygon, 2289);
+
+ // shapeRef2290
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16066.6, 11396.8);
+ polygon.ps[1] = Point(16066.6, 11473.1);
+ polygon.ps[2] = Point(15976.8, 11473.1);
+ polygon.ps[3] = Point(15976.8, 11396.8);
+ new ShapeRef(router, polygon, 2290);
+
+ // shapeRef2291
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4279, 9768.75);
+ polygon.ps[1] = Point(4279, 9877.02);
+ polygon.ps[2] = Point(4232.22, 9877.02);
+ polygon.ps[3] = Point(4232.22, 9768.75);
+ new ShapeRef(router, polygon, 2291);
+
+ // shapeRef2292
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4859.27, 10448);
+ polygon.ps[1] = Point(4859.27, 10494.8);
+ polygon.ps[2] = Point(4751, 10494.8);
+ polygon.ps[3] = Point(4751, 10448);
+ new ShapeRef(router, polygon, 2292);
+
+ // shapeRef2293
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4543, 10475);
+ polygon.ps[1] = Point(4543, 10583.3);
+ polygon.ps[2] = Point(4496.22, 10583.3);
+ polygon.ps[3] = Point(4496.22, 10475);
+ new ShapeRef(router, polygon, 2293);
+
+ // shapeRef2294
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9369.59, 9652.42);
+ polygon.ps[1] = Point(9369.59, 9748.77);
+ polygon.ps[2] = Point(9308.19, 9748.77);
+ polygon.ps[3] = Point(9308.19, 9652.42);
+ new ShapeRef(router, polygon, 2294);
+
+ // shapeRef2295
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10667.2, 8579.99);
+ polygon.ps[1] = Point(10667.2, 8640.55);
+ polygon.ps[2] = Point(10595.6, 8640.55);
+ polygon.ps[3] = Point(10595.6, 8579.99);
+ new ShapeRef(router, polygon, 2295);
+
+ // shapeRef2296
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8825.89, 2381.29);
+ polygon.ps[1] = Point(8825.89, 2441.85);
+ polygon.ps[2] = Point(8754.29, 2441.85);
+ polygon.ps[3] = Point(8754.29, 2381.29);
+ new ShapeRef(router, polygon, 2296);
+
+ // shapeRef2297
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9812.25, 818.091);
+ polygon.ps[1] = Point(9812.25, 889.69);
+ polygon.ps[2] = Point(9751.69, 889.69);
+ polygon.ps[3] = Point(9751.69, 818.091);
+ new ShapeRef(router, polygon, 2297);
+
+ // shapeRef2298
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10964.2, 1115.29);
+ polygon.ps[1] = Point(10964.2, 1176.69);
+ polygon.ps[2] = Point(10867.9, 1176.69);
+ polygon.ps[3] = Point(10867.9, 1115.29);
+ new ShapeRef(router, polygon, 2298);
+
+ // shapeRef2299
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12521.5, 5253.27);
+ polygon.ps[1] = Point(12521.5, 5314.67);
+ polygon.ps[2] = Point(12425.1, 5314.67);
+ polygon.ps[3] = Point(12425.1, 5253.27);
+ new ShapeRef(router, polygon, 2299);
+
+ // shapeRef2300
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12983.9, 4519.4);
+ polygon.ps[1] = Point(12983.9, 4615.76);
+ polygon.ps[2] = Point(12922.5, 4615.76);
+ polygon.ps[3] = Point(12922.5, 4519.4);
+ new ShapeRef(router, polygon, 2300);
+
+ // shapeRef2301
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10799.2, 7750.23);
+ polygon.ps[1] = Point(10799.2, 7810.79);
+ polygon.ps[2] = Point(10727.6, 7810.79);
+ polygon.ps[3] = Point(10727.6, 7750.23);
+ new ShapeRef(router, polygon, 2301);
+
+ // shapeRef2302
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11238.2, 8883.22);
+ polygon.ps[1] = Point(11238.2, 8954.82);
+ polygon.ps[2] = Point(11177.7, 8954.82);
+ polygon.ps[3] = Point(11177.7, 8883.22);
+ new ShapeRef(router, polygon, 2302);
+
+ // shapeRef2303
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7536.66, 3575.51);
+ polygon.ps[1] = Point(7536.66, 3647.11);
+ polygon.ps[2] = Point(7476.1, 3647.11);
+ polygon.ps[3] = Point(7476.1, 3575.51);
+ new ShapeRef(router, polygon, 2303);
+
+ // shapeRef2304
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5302, 4514.84);
+ polygon.ps[1] = Point(5302, 4575.4);
+ polygon.ps[2] = Point(5230.4, 4575.4);
+ polygon.ps[3] = Point(5230.4, 4514.84);
+ new ShapeRef(router, polygon, 2304);
+
+ // shapeRef2305
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15697.8, 468.265);
+ polygon.ps[1] = Point(15697.8, 539.864);
+ polygon.ps[2] = Point(15637.3, 539.864);
+ polygon.ps[3] = Point(15637.3, 468.265);
+ new ShapeRef(router, polygon, 2305);
+
+ // shapeRef2306
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11106.2, 8084.79);
+ polygon.ps[1] = Point(11106.2, 8156.39);
+ polygon.ps[2] = Point(11045.7, 8156.39);
+ polygon.ps[3] = Point(11045.7, 8084.79);
+ new ShapeRef(router, polygon, 2306);
+
+ // shapeRef2307
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6381.66, 435.265);
+ polygon.ps[1] = Point(6381.66, 506.864);
+ polygon.ps[2] = Point(6321.1, 506.864);
+ polygon.ps[3] = Point(6321.1, 435.265);
+ new ShapeRef(router, polygon, 2307);
+
+ // shapeRef2308
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11238.2, 4371.11);
+ polygon.ps[1] = Point(11238.2, 4442.71);
+ polygon.ps[2] = Point(11177.7, 4442.71);
+ polygon.ps[3] = Point(11177.7, 4371.11);
+ new ShapeRef(router, polygon, 2308);
+
+ // shapeRef2309
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14658.5, 6798.21);
+ polygon.ps[1] = Point(14658.5, 6869.81);
+ polygon.ps[2] = Point(14598, 6869.81);
+ polygon.ps[3] = Point(14598, 6798.21);
+ new ShapeRef(router, polygon, 2309);
+
+ // shapeRef2310
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16557.8, 10184);
+ polygon.ps[1] = Point(16557.8, 10255.6);
+ polygon.ps[2] = Point(16497.3, 10255.6);
+ polygon.ps[3] = Point(16497.3, 10184);
+ new ShapeRef(router, polygon, 2310);
+
+ // shapeRef2311
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10314.9, 9647.01);
+ polygon.ps[1] = Point(10314.9, 9708.42);
+ polygon.ps[2] = Point(10218.5, 9708.42);
+ polygon.ps[3] = Point(10218.5, 9647.01);
+ new ShapeRef(router, polygon, 2311);
+
+ // shapeRef2312
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7953.29, 10955.4);
+ polygon.ps[1] = Point(7953.29, 11013.6);
+ polygon.ps[2] = Point(7908.6, 11013.6);
+ polygon.ps[3] = Point(7908.6, 10955.4);
+ new ShapeRef(router, polygon, 2312);
+
+ // shapeRef2313
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12757.5, 11642.9);
+ polygon.ps[1] = Point(12757.5, 11714.5);
+ polygon.ps[2] = Point(12696.9, 11714.5);
+ polygon.ps[3] = Point(12696.9, 11642.9);
+ new ShapeRef(router, polygon, 2313);
+
+ // shapeRef2314
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14986.9, 12302.3);
+ polygon.ps[1] = Point(14986.9, 12373.9);
+ polygon.ps[2] = Point(14926.3, 12373.9);
+ polygon.ps[3] = Point(14926.3, 12302.3);
+ new ShapeRef(router, polygon, 2314);
+
+ // shapeRef2315
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14263.4, 12302.3);
+ polygon.ps[1] = Point(14263.4, 12398.7);
+ polygon.ps[2] = Point(14202, 12398.7);
+ polygon.ps[3] = Point(14202, 12302.3);
+ new ShapeRef(router, polygon, 2315);
+
+ // shapeRef2316
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13101, 10791.3);
+ polygon.ps[1] = Point(13101, 10862.9);
+ polygon.ps[2] = Point(13040.4, 10862.9);
+ polygon.ps[3] = Point(13040.4, 10791.3);
+ new ShapeRef(router, polygon, 2316);
+
+ // shapeRef2317
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15765.9, 10791.3);
+ polygon.ps[1] = Point(15765.9, 10887.6);
+ polygon.ps[2] = Point(15704.5, 10887.6);
+ polygon.ps[3] = Point(15704.5, 10791.3);
+ new ShapeRef(router, polygon, 2317);
+
+ // shapeRef2318
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7755.29, 851.285);
+ polygon.ps[1] = Point(7755.29, 911.847);
+ polygon.ps[2] = Point(7683.69, 911.847);
+ polygon.ps[3] = Point(7683.69, 851.285);
+ new ShapeRef(router, polygon, 2318);
+
+ // shapeRef2319
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11984.7, 12137.3);
+ polygon.ps[1] = Point(11984.7, 12208.9);
+ polygon.ps[2] = Point(11924.1, 12208.9);
+ polygon.ps[3] = Point(11924.1, 12137.3);
+ new ShapeRef(router, polygon, 2319);
+
+ // shapeRef2320
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12983.1, 12137.3);
+ polygon.ps[1] = Point(12983.1, 12208.9);
+ polygon.ps[2] = Point(12922.5, 12208.9);
+ polygon.ps[3] = Point(12922.5, 12137.3);
+ new ShapeRef(router, polygon, 2320);
+
+ // shapeRef2321
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7598.1, 3008.29);
+ polygon.ps[1] = Point(7598.1, 3068.85);
+ polygon.ps[2] = Point(7526.5, 3068.85);
+ polygon.ps[3] = Point(7526.5, 3008.29);
+ new ShapeRef(router, polygon, 2321);
+
+ // shapeRef2322
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(253, 86.8638);
+ polygon.ps[1] = Point(253, 148.265);
+ polygon.ps[2] = Point(156.647, 148.265);
+ polygon.ps[3] = Point(156.647, 86.8638);
+ new ShapeRef(router, polygon, 2322);
+
+ // shapeRef2323
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9009.99, 2381.29);
+ polygon.ps[1] = Point(9009.99, 2441.85);
+ polygon.ps[2] = Point(8938.39, 2441.85);
+ polygon.ps[3] = Point(8938.39, 2381.29);
+ new ShapeRef(router, polygon, 2323);
+
+ // shapeRef2324
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13162.4, 4552.4);
+ polygon.ps[1] = Point(13162.4, 4648.76);
+ polygon.ps[2] = Point(13101, 4648.76);
+ polygon.ps[3] = Point(13101, 4552.4);
+ new ShapeRef(router, polygon, 2324);
+
+ // shapeRef2325
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11238.2, 8966.82);
+ polygon.ps[1] = Point(11238.2, 9038.42);
+ polygon.ps[2] = Point(11177.7, 9038.42);
+ polygon.ps[3] = Point(11177.7, 8966.82);
+ new ShapeRef(router, polygon, 2325);
+
+ // shapeRef2326
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5486.1, 4514.84);
+ polygon.ps[1] = Point(5486.1, 4575.4);
+ polygon.ps[2] = Point(5414.5, 4575.4);
+ polygon.ps[3] = Point(5414.5, 4514.84);
+ new ShapeRef(router, polygon, 2326);
+
+ // shapeRef2327
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5486.1, 5108.84);
+ polygon.ps[1] = Point(5486.1, 5169.4);
+ polygon.ps[2] = Point(5414.5, 5169.4);
+ polygon.ps[3] = Point(5414.5, 5108.84);
+ new ShapeRef(router, polygon, 2327);
+
+ // shapeRef2328
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11106.2, 8168.39);
+ polygon.ps[1] = Point(11106.2, 8239.99);
+ polygon.ps[2] = Point(11045.7, 8239.99);
+ polygon.ps[3] = Point(11045.7, 8168.39);
+ new ShapeRef(router, polygon, 2328);
+
+ // shapeRef2329
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11238.2, 4202.51);
+ polygon.ps[1] = Point(11238.2, 4274.11);
+ polygon.ps[2] = Point(11177.7, 4274.11);
+ polygon.ps[3] = Point(11177.7, 4202.51);
+ new ShapeRef(router, polygon, 2329);
+
+ // shapeRef2330
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14658.5, 6881.81);
+ polygon.ps[1] = Point(14658.5, 6953.4);
+ polygon.ps[2] = Point(14598, 6953.4);
+ polygon.ps[3] = Point(14598, 6881.81);
+ new ShapeRef(router, polygon, 2330);
+
+ // shapeRef2331
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10089, 9647.01);
+ polygon.ps[1] = Point(10089, 9708.42);
+ polygon.ps[2] = Point(9992.69, 9708.42);
+ polygon.ps[3] = Point(9992.69, 9647.01);
+ new ShapeRef(router, polygon, 2331);
+
+ // shapeRef2332
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16066.6, 11396.8);
+ polygon.ps[1] = Point(16066.6, 11493.2);
+ polygon.ps[2] = Point(16005.2, 11493.2);
+ polygon.ps[3] = Point(16005.2, 11396.8);
+ new ShapeRef(router, polygon, 2332);
+
+ // shapeRef2333
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5302, 5108.84);
+ polygon.ps[1] = Point(5302, 5169.4);
+ polygon.ps[2] = Point(5230.4, 5169.4);
+ polygon.ps[3] = Point(5230.4, 5108.84);
+ new ShapeRef(router, polygon, 2333);
+
+ // shapeRef2334
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4279, 9787.25);
+ polygon.ps[1] = Point(4279, 9877.02);
+ polygon.ps[2] = Point(4202.77, 9877.02);
+ polygon.ps[3] = Point(4202.77, 9787.25);
+ new ShapeRef(router, polygon, 2334);
+
+ // shapeRef2335
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4840.76, 10448);
+ polygon.ps[1] = Point(4840.76, 10524.2);
+ polygon.ps[2] = Point(4751, 10524.2);
+ polygon.ps[3] = Point(4751, 10448);
+ new ShapeRef(router, polygon, 2335);
+
+ // shapeRef2336
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4543, 10493.5);
+ polygon.ps[1] = Point(4543, 10583.3);
+ polygon.ps[2] = Point(4466.77, 10583.3);
+ polygon.ps[3] = Point(4466.77, 10493.5);
+ new ShapeRef(router, polygon, 2336);
+
+ // shapeRef2337
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10512.2, 10692.3);
+ polygon.ps[1] = Point(10512.2, 10763.9);
+ polygon.ps[2] = Point(10451.7, 10763.9);
+ polygon.ps[3] = Point(10451.7, 10692.3);
+ new ShapeRef(router, polygon, 2337);
+
+ // shapeRef2338
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8392.29, 5522.67);
+ polygon.ps[1] = Point(8392.29, 5567.36);
+ polygon.ps[2] = Point(8334.07, 5567.36);
+ polygon.ps[3] = Point(8334.07, 5522.67);
+ new ShapeRef(router, polygon, 2338);
+
+ // shapeRef2339
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11485.1, 7686.57);
+ polygon.ps[1] = Point(11485.1, 7744.79);
+ polygon.ps[2] = Point(11440.4, 7744.79);
+ polygon.ps[3] = Point(11440.4, 7686.57);
+ new ShapeRef(router, polygon, 2339);
+
+ // shapeRef2340
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7887.29, 4443.4);
+ polygon.ps[1] = Point(7887.29, 4501.63);
+ polygon.ps[2] = Point(7842.6, 4501.63);
+ polygon.ps[3] = Point(7842.6, 4443.4);
+ new ShapeRef(router, polygon, 2340);
+
+ // shapeRef2341
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8792.89, 9990.92);
+ polygon.ps[1] = Point(8792.89, 10075);
+ polygon.ps[2] = Point(8746.66, 10075);
+ polygon.ps[3] = Point(8746.66, 9990.92);
+ new ShapeRef(router, polygon, 2341);
+
+ // shapeRef2342
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9009.99, 5573.8);
+ polygon.ps[1] = Point(9009.99, 5657.9);
+ polygon.ps[2] = Point(8963.76, 5657.9);
+ polygon.ps[3] = Point(8963.76, 5573.8);
+ new ShapeRef(router, polygon, 2342);
+
+ // shapeRef2343
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15138.3, 11809.8);
+ polygon.ps[1] = Point(15138.3, 11893.9);
+ polygon.ps[2] = Point(15092.1, 11893.9);
+ polygon.ps[3] = Point(15092.1, 11809.8);
+ new ShapeRef(router, polygon, 2343);
+
+ // shapeRef2344
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9196.82, 6161.51);
+ polygon.ps[1] = Point(9196.82, 6206.21);
+ polygon.ps[2] = Point(9138.59, 6206.21);
+ polygon.ps[3] = Point(9138.59, 6161.51);
+ new ShapeRef(router, polygon, 2344);
+
+ // shapeRef2345
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15229.5, 1346.29);
+ polygon.ps[1] = Point(15229.5, 1404.51);
+ polygon.ps[2] = Point(15184.8, 1404.51);
+ polygon.ps[3] = Point(15184.8, 1346.29);
+ new ShapeRef(router, polygon, 2345);
+
+ // shapeRef2346
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9453.69, 9652.42);
+ polygon.ps[1] = Point(9453.69, 9698.65);
+ polygon.ps[2] = Point(9369.59, 9698.65);
+ polygon.ps[3] = Point(9369.59, 9652.42);
+ new ShapeRef(router, polygon, 2346);
+
+ // shapeRef2347
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9394.82, 5457.98);
+ polygon.ps[1] = Point(9394.82, 5502.67);
+ polygon.ps[2] = Point(9336.59, 5502.67);
+ polygon.ps[3] = Point(9336.59, 5457.98);
+ new ShapeRef(router, polygon, 2347);
+
+ // shapeRef2348
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15858.6, 11893.9);
+ polygon.ps[1] = Point(15858.6, 11952.1);
+ polygon.ps[2] = Point(15813.9, 11952.1);
+ polygon.ps[3] = Point(15813.9, 11893.9);
+ new ShapeRef(router, polygon, 2348);
+
+ // shapeRef2349
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(1583, 4783.4);
+ polygon.ps[1] = Point(1583, 4828.1);
+ polygon.ps[2] = Point(1524.77, 4828.1);
+ polygon.ps[3] = Point(1524.77, 4783.4);
+ new ShapeRef(router, polygon, 2349);
+
+ // shapeRef2350
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(3035, 4783.4);
+ polygon.ps[1] = Point(3035, 4828.1);
+ polygon.ps[2] = Point(2976.77, 4828.1);
+ polygon.ps[3] = Point(2976.77, 4783.4);
+ new ShapeRef(router, polygon, 2350);
+
+ // shapeRef2351
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14788.2, 1356.29);
+ polygon.ps[1] = Point(14788.2, 1400.98);
+ polygon.ps[2] = Point(14730, 1400.98);
+ polygon.ps[3] = Point(14730, 1356.29);
+ new ShapeRef(router, polygon, 2351);
+
+ // shapeRef2352
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8227.29, 9685.42);
+ polygon.ps[1] = Point(8227.29, 9757.02);
+ polygon.ps[2] = Point(8166.73, 9757.02);
+ polygon.ps[3] = Point(8166.73, 9685.42);
+ new ShapeRef(router, polygon, 2352);
+
+ // shapeRef2353
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8326.29, 9854.02);
+ polygon.ps[1] = Point(8326.29, 9925.61);
+ polygon.ps[2] = Point(8265.73, 9925.61);
+ polygon.ps[3] = Point(8265.73, 9854.02);
+ new ShapeRef(router, polygon, 2353);
+
+ // shapeRef2354
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9875.92, 7171.4);
+ polygon.ps[1] = Point(9875.92, 7216.1);
+ polygon.ps[2] = Point(9817.69, 7216.1);
+ polygon.ps[3] = Point(9817.69, 7171.4);
+ new ShapeRef(router, polygon, 2354);
+
+ // shapeRef2355
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10446.9, 7818.57);
+ polygon.ps[1] = Point(10446.9, 7876.79);
+ polygon.ps[2] = Point(10402.2, 7876.79);
+ polygon.ps[3] = Point(10402.2, 7818.57);
+ new ShapeRef(router, polygon, 2355);
+
+ // shapeRef2356
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7499.1, 8008.79);
+ polygon.ps[1] = Point(7499.1, 8067.02);
+ polygon.ps[2] = Point(7454.4, 8067.02);
+ polygon.ps[3] = Point(7454.4, 8008.79);
+ new ShapeRef(router, polygon, 2356);
+
+ // shapeRef2357
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8825.89, 3961.51);
+ polygon.ps[1] = Point(8825.89, 4019.74);
+ polygon.ps[2] = Point(8781.2, 4019.74);
+ polygon.ps[3] = Point(8781.2, 3961.51);
+ new ShapeRef(router, polygon, 2357);
+
+ // shapeRef2358
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10999.4, 4371.11);
+ polygon.ps[1] = Point(10999.4, 4415.81);
+ polygon.ps[2] = Point(10941.2, 4415.81);
+ polygon.ps[3] = Point(10941.2, 4371.11);
+ new ShapeRef(router, polygon, 2358);
+
+ // shapeRef2359
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12521.5, 4971.4);
+ polygon.ps[1] = Point(12521.5, 5055.5);
+ polygon.ps[2] = Point(12475.3, 5055.5);
+ polygon.ps[3] = Point(12475.3, 4971.4);
+ new ShapeRef(router, polygon, 2359);
+
+ // shapeRef2360
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12521.5, 3936.29);
+ polygon.ps[1] = Point(12521.5, 3994.51);
+ polygon.ps[2] = Point(12476.8, 3994.51);
+ polygon.ps[3] = Point(12476.8, 3936.29);
+ new ShapeRef(router, polygon, 2360);
+
+ // shapeRef2361
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12521.5, 2221.72);
+ polygon.ps[1] = Point(12521.5, 2282.29);
+ polygon.ps[2] = Point(12449.9, 2282.29);
+ polygon.ps[3] = Point(12449.9, 2221.72);
+ new ShapeRef(router, polygon, 2361);
+
+ // shapeRef2362
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12155.1, 1854.29);
+ polygon.ps[1] = Point(12155.1, 1898.98);
+ polygon.ps[2] = Point(12096.9, 1898.98);
+ polygon.ps[3] = Point(12096.9, 1854.29);
+ new ShapeRef(router, polygon, 2362);
+
+ // shapeRef2363
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11980.1, 1742.29);
+ polygon.ps[1] = Point(11980.1, 1800.51);
+ polygon.ps[2] = Point(11935.4, 1800.51);
+ polygon.ps[3] = Point(11935.4, 1742.29);
+ new ShapeRef(router, polygon, 2363);
+
+ // shapeRef2364
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9840.69, 6415.51);
+ polygon.ps[1] = Point(9840.69, 6473.74);
+ polygon.ps[2] = Point(9795.99, 6473.74);
+ polygon.ps[3] = Point(9795.99, 6415.51);
+ new ShapeRef(router, polygon, 2364);
+
+ // shapeRef2365
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5302, 3829.51);
+ polygon.ps[1] = Point(5302, 3913.61);
+ polygon.ps[2] = Point(5255.77, 3913.61);
+ polygon.ps[3] = Point(5255.77, 3829.51);
+ new ShapeRef(router, polygon, 2365);
+
+ // shapeRef2366
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5302, 5169.4);
+ polygon.ps[1] = Point(5302, 5229.97);
+ polygon.ps[2] = Point(5230.4, 5229.97);
+ polygon.ps[3] = Point(5230.4, 5169.4);
+ new ShapeRef(router, polygon, 2366);
+
+ // shapeRef2367
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4939, 8807.22);
+ polygon.ps[1] = Point(4939, 8891.32);
+ polygon.ps[2] = Point(4892.77, 8891.32);
+ polygon.ps[3] = Point(4892.77, 8807.22);
+ new ShapeRef(router, polygon, 2367);
+
+ // shapeRef2368
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4939, 9312.42);
+ polygon.ps[1] = Point(4939, 9372.98);
+ polygon.ps[2] = Point(4867.4, 9372.98);
+ polygon.ps[3] = Point(4867.4, 9312.42);
+ new ShapeRef(router, polygon, 2368);
+
+ // shapeRef2369
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4279, 9877.02);
+ polygon.ps[1] = Point(4279, 9937.58);
+ polygon.ps[2] = Point(4207.4, 9937.58);
+ polygon.ps[3] = Point(4207.4, 9877.02);
+ new ShapeRef(router, polygon, 2369);
+
+ // shapeRef2370
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4751, 10448);
+ polygon.ps[1] = Point(4751, 10519.6);
+ polygon.ps[2] = Point(4690.44, 10519.6);
+ polygon.ps[3] = Point(4690.44, 10448);
+ new ShapeRef(router, polygon, 2370);
+
+ // shapeRef2371
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4543, 10583.3);
+ polygon.ps[1] = Point(4543, 10643.8);
+ polygon.ps[2] = Point(4471.4, 10643.8);
+ polygon.ps[3] = Point(4471.4, 10583.3);
+ new ShapeRef(router, polygon, 2371);
+
+ // shapeRef2372
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11353.1, 1478.29);
+ polygon.ps[1] = Point(11353.1, 1538.85);
+ polygon.ps[2] = Point(11281.5, 1538.85);
+ polygon.ps[3] = Point(11281.5, 1478.29);
+ new ShapeRef(router, polygon, 2372);
+
+ // shapeRef2373
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7765.29, 435.265);
+ polygon.ps[1] = Point(7765.29, 479.96);
+ polygon.ps[2] = Point(7707.07, 479.96);
+ polygon.ps[3] = Point(7707.07, 435.265);
+ new ShapeRef(router, polygon, 2373);
+
+ // shapeRef2374
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10832.2, 10980.6);
+ polygon.ps[1] = Point(10832.2, 11038.9);
+ polygon.ps[2] = Point(10787.5, 11038.9);
+ polygon.ps[3] = Point(10787.5, 10980.6);
+ new ShapeRef(router, polygon, 2374);
+
+ // shapeRef2375
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9718.69, 11221.6);
+ polygon.ps[1] = Point(9718.69, 11266.3);
+ polygon.ps[2] = Point(9660.46, 11266.3);
+ polygon.ps[3] = Point(9660.46, 11221.6);
+ new ShapeRef(router, polygon, 2375);
+
+ // shapeRef2376
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8684.29, 11221.6);
+ polygon.ps[1] = Point(8684.29, 11293.2);
+ polygon.ps[2] = Point(8623.73, 11293.2);
+ polygon.ps[3] = Point(8623.73, 11221.6);
+ new ShapeRef(router, polygon, 2376);
+
+ // shapeRef2377
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14590.2, 11642.9);
+ polygon.ps[1] = Point(14590.2, 11687.6);
+ polygon.ps[2] = Point(14532, 11687.6);
+ polygon.ps[3] = Point(14532, 11642.9);
+ new ShapeRef(router, polygon, 2377);
+
+ // shapeRef2378
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15858.6, 11835.7);
+ polygon.ps[1] = Point(15858.6, 11893.9);
+ polygon.ps[2] = Point(15813.9, 11893.9);
+ polygon.ps[3] = Point(15813.9, 11835.7);
+ new ShapeRef(router, polygon, 2378);
+
+ // shapeRef2379
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15858.6, 12193.3);
+ polygon.ps[1] = Point(15858.6, 12251.5);
+ polygon.ps[2] = Point(15813.9, 12251.5);
+ polygon.ps[3] = Point(15813.9, 12193.3);
+ new ShapeRef(router, polygon, 2379);
+
+ // shapeRef2380
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15662.5, 12302.3);
+ polygon.ps[1] = Point(15662.5, 12347);
+ polygon.ps[2] = Point(15604.3, 12347);
+ polygon.ps[3] = Point(15604.3, 12302.3);
+ new ShapeRef(router, polygon, 2380);
+
+ // shapeRef2381
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14359.2, 10791.3);
+ polygon.ps[1] = Point(14359.2, 10836);
+ polygon.ps[2] = Point(14301, 10836);
+ polygon.ps[3] = Point(14301, 10791.3);
+ new ShapeRef(router, polygon, 2381);
+
+ // shapeRef2382
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17213.5, 7139.71);
+ polygon.ps[1] = Point(17213.5, 7184.4);
+ polygon.ps[2] = Point(17155.3, 7184.4);
+ polygon.ps[3] = Point(17155.3, 7139.71);
+ new ShapeRef(router, polygon, 2382);
+
+ // shapeRef2383
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11353.1, 8414.99);
+ polygon.ps[1] = Point(11353.1, 8473.22);
+ polygon.ps[2] = Point(11308.4, 8473.22);
+ polygon.ps[3] = Point(11308.4, 8414.99);
+ new ShapeRef(router, polygon, 2383);
+
+ // shapeRef2384
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10776.2, 818.091);
+ polygon.ps[1] = Point(10776.2, 862.785);
+ polygon.ps[2] = Point(10718, 862.785);
+ polygon.ps[3] = Point(10718, 818.091);
+ new ShapeRef(router, polygon, 2384);
+
+ // shapeRef2385
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12521.5, 5314.67);
+ polygon.ps[1] = Point(12521.5, 5398.77);
+ polygon.ps[2] = Point(12475.3, 5398.77);
+ polygon.ps[3] = Point(12475.3, 5314.67);
+ new ShapeRef(router, polygon, 2385);
+
+ // shapeRef2386
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11914.1, 7785.57);
+ polygon.ps[1] = Point(11914.1, 7843.79);
+ polygon.ps[2] = Point(11869.4, 7843.79);
+ polygon.ps[3] = Point(11869.4, 7785.57);
+ new ShapeRef(router, polygon, 2386);
+
+ // shapeRef2387
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5302, 4575.4);
+ polygon.ps[1] = Point(5302, 4635.97);
+ polygon.ps[2] = Point(5230.4, 4635.97);
+ polygon.ps[3] = Point(5230.4, 4575.4);
+ new ShapeRef(router, polygon, 2387);
+
+ // shapeRef2388
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11528.1, 468.265);
+ polygon.ps[1] = Point(11528.1, 539.864);
+ polygon.ps[2] = Point(11467.6, 539.864);
+ polygon.ps[3] = Point(11467.6, 468.265);
+ new ShapeRef(router, polygon, 2388);
+
+ // shapeRef2389
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14854.2, 468.265);
+ polygon.ps[1] = Point(14854.2, 512.96);
+ polygon.ps[2] = Point(14796, 512.96);
+ polygon.ps[3] = Point(14796, 468.265);
+ new ShapeRef(router, polygon, 2389);
+
+ // shapeRef2390
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15637.3, 468.265);
+ polygon.ps[1] = Point(15637.3, 539.864);
+ polygon.ps[2] = Point(15576.7, 539.864);
+ polygon.ps[3] = Point(15576.7, 468.265);
+ new ShapeRef(router, polygon, 2390);
+
+ // shapeRef2391
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16165.6, 468.265);
+ polygon.ps[1] = Point(16165.6, 512.96);
+ polygon.ps[2] = Point(16107.4, 512.96);
+ polygon.ps[3] = Point(16107.4, 468.265);
+ new ShapeRef(router, polygon, 2391);
+
+ // shapeRef2392
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10776.2, 468.265);
+ polygon.ps[1] = Point(10776.2, 512.96);
+ polygon.ps[2] = Point(10718, 512.96);
+ polygon.ps[3] = Point(10718, 468.265);
+ new ShapeRef(router, polygon, 2392);
+
+ // shapeRef2393
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8087.52, 323.265);
+ polygon.ps[1] = Point(8087.52, 367.96);
+ polygon.ps[2] = Point(8029.29, 367.96);
+ polygon.ps[3] = Point(8029.29, 323.265);
+ new ShapeRef(router, polygon, 2393);
+
+ // shapeRef2394
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18226.5, 8546.99);
+ polygon.ps[1] = Point(18226.5, 8605.22);
+ polygon.ps[2] = Point(18181.9, 8605.22);
+ polygon.ps[3] = Point(18181.9, 8546.99);
+ new ShapeRef(router, polygon, 2394);
+
+ // shapeRef2395
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8227.29, 10725.3);
+ polygon.ps[1] = Point(8227.29, 10770);
+ polygon.ps[2] = Point(8169.07, 10770);
+ polygon.ps[3] = Point(8169.07, 10725.3);
+ new ShapeRef(router, polygon, 2395);
+
+ // shapeRef2396
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14202, 12302.3);
+ polygon.ps[1] = Point(14202, 12348.5);
+ polygon.ps[2] = Point(14117.9, 12348.5);
+ polygon.ps[3] = Point(14117.9, 12302.3);
+ new ShapeRef(router, polygon, 2396);
+
+ // shapeRef2397
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15826.4, 10791.3);
+ polygon.ps[1] = Point(15826.4, 10862.9);
+ polygon.ps[2] = Point(15765.9, 10862.9);
+ polygon.ps[3] = Point(15765.9, 10791.3);
+ new ShapeRef(router, polygon, 2397);
+
+ // shapeRef2398
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7755.29, 767.188);
+ polygon.ps[1] = Point(7755.29, 851.285);
+ polygon.ps[2] = Point(7709.06, 851.285);
+ polygon.ps[3] = Point(7709.06, 767.188);
+ new ShapeRef(router, polygon, 2398);
+
+ // shapeRef2399
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11353.1, 3280.06);
+ polygon.ps[1] = Point(11353.1, 3338.29);
+ polygon.ps[2] = Point(11308.4, 3338.29);
+ polygon.ps[3] = Point(11308.4, 3280.06);
+ new ShapeRef(router, polygon, 2399);
+
+ // shapeRef2400
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11353.1, 4418.18);
+ polygon.ps[1] = Point(11353.1, 4476.4);
+ polygon.ps[2] = Point(11308.4, 4476.4);
+ polygon.ps[3] = Point(11308.4, 4418.18);
+ new ShapeRef(router, polygon, 2400);
+
+ // shapeRef2401
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11353.1, 11120.4);
+ polygon.ps[1] = Point(11353.1, 11178.6);
+ polygon.ps[2] = Point(11308.4, 11178.6);
+ polygon.ps[3] = Point(11308.4, 11120.4);
+ new ShapeRef(router, polygon, 2401);
+
+ // shapeRef2402
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12922.5, 12137.3);
+ polygon.ps[1] = Point(12922.5, 12183.5);
+ polygon.ps[2] = Point(12838.4, 12183.5);
+ polygon.ps[3] = Point(12838.4, 12137.3);
+ new ShapeRef(router, polygon, 2402);
+
+ // shapeRef2403
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16066.6, 11804.9);
+ polygon.ps[1] = Point(16066.6, 11876.5);
+ polygon.ps[2] = Point(16006, 11876.5);
+ polygon.ps[3] = Point(16006, 11804.9);
+ new ShapeRef(router, polygon, 2403);
+
+ // shapeRef2404
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8448.29, 1478.29);
+ polygon.ps[1] = Point(8448.29, 1536.51);
+ polygon.ps[2] = Point(8403.6, 1536.51);
+ polygon.ps[3] = Point(8403.6, 1478.29);
+ new ShapeRef(router, polygon, 2404);
+
+ // shapeRef2405
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5486.1, 4575.4);
+ polygon.ps[1] = Point(5486.1, 4635.97);
+ polygon.ps[2] = Point(5414.5, 4635.97);
+ polygon.ps[3] = Point(5414.5, 4575.4);
+ new ShapeRef(router, polygon, 2405);
+
+ // shapeRef2406
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5486.1, 5169.4);
+ polygon.ps[1] = Point(5486.1, 5229.97);
+ polygon.ps[2] = Point(5414.5, 5229.97);
+ polygon.ps[3] = Point(5414.5, 5169.4);
+ new ShapeRef(router, polygon, 2406);
+
+ // shapeRef2407
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(18574.3, 11927.6);
+ polygon.ps[1] = Point(18574.3, 11972.3);
+ polygon.ps[2] = Point(18516, 11972.3);
+ polygon.ps[3] = Point(18516, 11927.6);
+ new ShapeRef(router, polygon, 2407);
+
+ // shapeRef2408
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10799.2, 5599.67);
+ polygon.ps[1] = Point(10799.2, 5657.9);
+ polygon.ps[2] = Point(10754.5, 5657.9);
+ polygon.ps[3] = Point(10754.5, 5599.67);
+ new ShapeRef(router, polygon, 2408);
+
+ // shapeRef2409
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15664.8, 1191.29);
+ polygon.ps[1] = Point(15664.8, 1262.88);
+ polygon.ps[2] = Point(15604.3, 1262.88);
+ polygon.ps[3] = Point(15604.3, 1191.29);
+ new ShapeRef(router, polygon, 2409);
+
+ // shapeRef2410
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16150.7, 11396.8);
+ polygon.ps[1] = Point(16150.7, 11443.1);
+ polygon.ps[2] = Point(16066.6, 11443.1);
+ polygon.ps[3] = Point(16066.6, 11396.8);
+ new ShapeRef(router, polygon, 2410);
+
+ // shapeRef2411
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9675.69, 7359.4);
+ polygon.ps[1] = Point(9675.69, 7419.97);
+ polygon.ps[2] = Point(9604.09, 7419.97);
+ polygon.ps[3] = Point(9604.09, 7359.4);
+ new ShapeRef(router, polygon, 2411);
+
+ // shapeRef2412
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12980.7, 12468.7);
+ polygon.ps[1] = Point(12980.7, 12513.3);
+ polygon.ps[2] = Point(12922.5, 12513.3);
+ polygon.ps[3] = Point(12922.5, 12468.7);
+ new ShapeRef(router, polygon, 2412);
+
+ // shapeRef2413
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10603.4, 4371.11);
+ polygon.ps[1] = Point(10603.4, 4415.81);
+ polygon.ps[2] = Point(10545.2, 4415.81);
+ polygon.ps[3] = Point(10545.2, 4371.11);
+ new ShapeRef(router, polygon, 2413);
+
+ // shapeRef2414
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10669.4, 4454.71);
+ polygon.ps[1] = Point(10669.4, 4499.4);
+ polygon.ps[2] = Point(10611.2, 4499.4);
+ polygon.ps[3] = Point(10611.2, 4454.71);
+ new ShapeRef(router, polygon, 2414);
+
+ // shapeRef2415
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12279.4, 4371.11);
+ polygon.ps[1] = Point(12279.4, 4415.81);
+ polygon.ps[2] = Point(12221.1, 4415.81);
+ polygon.ps[3] = Point(12221.1, 4371.11);
+ new ShapeRef(router, polygon, 2415);
+
+ // shapeRef2416
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11417.8, 1057.06);
+ polygon.ps[1] = Point(11417.8, 1115.29);
+ polygon.ps[2] = Point(11373.1, 1115.29);
+ polygon.ps[3] = Point(11373.1, 1057.06);
+ new ShapeRef(router, polygon, 2416);
+
+ // shapeRef2417
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11586.4, 468.265);
+ polygon.ps[1] = Point(11586.4, 512.96);
+ polygon.ps[2] = Point(11528.1, 512.96);
+ polygon.ps[3] = Point(11528.1, 468.265);
+ new ShapeRef(router, polygon, 2417);
+
+ // shapeRef2418
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12015.4, 468.265);
+ polygon.ps[1] = Point(12015.4, 512.96);
+ polygon.ps[2] = Point(11957.1, 512.96);
+ polygon.ps[3] = Point(11957.1, 468.265);
+ new ShapeRef(router, polygon, 2418);
+
+ // shapeRef2419
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15045.1, 1291.59);
+ polygon.ps[1] = Point(15045.1, 1336.29);
+ polygon.ps[2] = Point(14986.9, 1336.29);
+ polygon.ps[3] = Point(14986.9, 1291.59);
+ new ShapeRef(router, polygon, 2419);
+
+ // shapeRef2420
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13258.2, 468.265);
+ polygon.ps[1] = Point(13258.2, 512.96);
+ polygon.ps[2] = Point(13200, 512.96);
+ polygon.ps[3] = Point(13200, 468.265);
+ new ShapeRef(router, polygon, 2420);
+
+ // shapeRef2421
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16223.8, 468.265);
+ polygon.ps[1] = Point(16223.8, 512.96);
+ polygon.ps[2] = Point(16165.6, 512.96);
+ polygon.ps[3] = Point(16165.6, 468.265);
+ new ShapeRef(router, polygon, 2421);
+
+ // shapeRef2422
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8029.29, 323.265);
+ polygon.ps[1] = Point(8029.29, 367.96);
+ polygon.ps[2] = Point(7971.07, 367.96);
+ polygon.ps[3] = Point(7971.07, 323.265);
+ new ShapeRef(router, polygon, 2422);
+
+ // shapeRef2423
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14858.4, 1356.29);
+ polygon.ps[1] = Point(14858.4, 1400.98);
+ polygon.ps[2] = Point(14800.2, 1400.98);
+ polygon.ps[3] = Point(14800.2, 1356.29);
+ new ShapeRef(router, polygon, 2423);
+
+ // shapeRef2424
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11353.1, 11178.6);
+ polygon.ps[1] = Point(11353.1, 11236.9);
+ polygon.ps[2] = Point(11308.4, 11236.9);
+ polygon.ps[3] = Point(11308.4, 11178.6);
+ new ShapeRef(router, polygon, 2424);
+
+ // shapeRef2425
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7598.1, 1412.29);
+ polygon.ps[1] = Point(7598.1, 1470.51);
+ polygon.ps[2] = Point(7553.4, 1470.51);
+ polygon.ps[3] = Point(7553.4, 1412.29);
+ new ShapeRef(router, polygon, 2425);
+
+ // shapeRef2426
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14730, 1356.29);
+ polygon.ps[1] = Point(14730, 1400.98);
+ polygon.ps[2] = Point(14671.8, 1400.98);
+ polygon.ps[3] = Point(14671.8, 1356.29);
+ new ShapeRef(router, polygon, 2426);
+
+ // shapeRef2427
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8287.86, 9685.42);
+ polygon.ps[1] = Point(8287.86, 9757.02);
+ polygon.ps[2] = Point(8227.29, 9757.02);
+ polygon.ps[3] = Point(8227.29, 9685.42);
+ new ShapeRef(router, polygon, 2427);
+
+ // shapeRef2428
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8386.86, 9854.02);
+ polygon.ps[1] = Point(8386.86, 9925.61);
+ polygon.ps[2] = Point(8326.29, 9925.61);
+ polygon.ps[3] = Point(8326.29, 9854.02);
+ new ShapeRef(router, polygon, 2428);
+
+ // shapeRef2429
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8448.29, 1420.06);
+ polygon.ps[1] = Point(8448.29, 1478.29);
+ polygon.ps[2] = Point(8403.6, 1478.29);
+ polygon.ps[3] = Point(8403.6, 1420.06);
+ new ShapeRef(router, polygon, 2429);
+
+ // shapeRef2430
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15893.8, 1291.59);
+ polygon.ps[1] = Point(15893.8, 1336.29);
+ polygon.ps[2] = Point(15835.6, 1336.29);
+ polygon.ps[3] = Point(15835.6, 1291.59);
+ new ShapeRef(router, polygon, 2430);
+
+ // shapeRef2431
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8825.89, 2297.19);
+ polygon.ps[1] = Point(8825.89, 2381.29);
+ polygon.ps[2] = Point(8779.66, 2381.29);
+ polygon.ps[3] = Point(8779.66, 2297.19);
+ new ShapeRef(router, polygon, 2431);
+
+ // shapeRef2432
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10799.2, 7810.79);
+ polygon.ps[1] = Point(10799.2, 7894.89);
+ polygon.ps[2] = Point(10753, 7894.89);
+ polygon.ps[3] = Point(10753, 7810.79);
+ new ShapeRef(router, polygon, 2432);
+
+ // shapeRef2433
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16353.6, 749.864);
+ polygon.ps[1] = Point(16353.6, 808.091);
+ polygon.ps[2] = Point(16308.9, 808.091);
+ polygon.ps[3] = Point(16308.9, 749.864);
+ new ShapeRef(router, polygon, 2433);
+
+ // shapeRef2434
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16641.9, 10184);
+ polygon.ps[1] = Point(16641.9, 10230.2);
+ polygon.ps[2] = Point(16557.8, 10230.2);
+ polygon.ps[3] = Point(16557.8, 10184);
+ new ShapeRef(router, polygon, 2434);
+
+ // shapeRef2435
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17297.6, 7138.17);
+ polygon.ps[1] = Point(17297.6, 7184.4);
+ polygon.ps[2] = Point(17213.5, 7184.4);
+ polygon.ps[3] = Point(17213.5, 7138.17);
+ new ShapeRef(router, polygon, 2435);
+
+ // shapeRef2436
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9009.99, 2297.19);
+ polygon.ps[1] = Point(9009.99, 2381.29);
+ polygon.ps[2] = Point(8963.76, 2381.29);
+ polygon.ps[3] = Point(8963.76, 2297.19);
+ new ShapeRef(router, polygon, 2436);
+
+ // shapeRef2437
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4939, 9312.42);
+ polygon.ps[1] = Point(4939, 9396.51);
+ polygon.ps[2] = Point(4892.77, 9396.51);
+ polygon.ps[3] = Point(4892.77, 9312.42);
+ new ShapeRef(router, polygon, 2437);
+
+ // shapeRef2438
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7565.1, 9081.42);
+ polygon.ps[1] = Point(7565.1, 9139.64);
+ polygon.ps[2] = Point(7520.4, 9139.64);
+ polygon.ps[3] = Point(7520.4, 9081.42);
+ new ShapeRef(router, polygon, 2438);
+
+ // shapeRef2439
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4939, 7752.57);
+ polygon.ps[1] = Point(4939, 7810.79);
+ polygon.ps[2] = Point(4894.31, 7810.79);
+ polygon.ps[3] = Point(4894.31, 7752.57);
+ new ShapeRef(router, polygon, 2439);
+
+ // shapeRef2440
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4939, 8323.76);
+ polygon.ps[1] = Point(4939, 8381.99);
+ polygon.ps[2] = Point(4894.31, 8381.99);
+ polygon.ps[3] = Point(4894.31, 8323.76);
+ new ShapeRef(router, polygon, 2440);
+
+ // shapeRef2441
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14598, 6656.51);
+ polygon.ps[1] = Point(14598, 6701.21);
+ polygon.ps[2] = Point(14539.8, 6701.21);
+ polygon.ps[3] = Point(14539.8, 6656.51);
+ new ShapeRef(router, polygon, 2441);
+
+ // shapeRef2442
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4939, 7810.79);
+ polygon.ps[1] = Point(4939, 7869.02);
+ polygon.ps[2] = Point(4894.31, 7869.02);
+ polygon.ps[3] = Point(4894.31, 7810.79);
+ new ShapeRef(router, polygon, 2442);
+
+ // shapeRef2443
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4939, 8381.99);
+ polygon.ps[1] = Point(4939, 8440.22);
+ polygon.ps[2] = Point(4894.31, 8440.22);
+ polygon.ps[3] = Point(4894.31, 8381.99);
+ new ShapeRef(router, polygon, 2443);
+
+ // shapeRef2444
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14656.2, 6656.51);
+ polygon.ps[1] = Point(14656.2, 6701.21);
+ polygon.ps[2] = Point(14598, 6701.21);
+ polygon.ps[3] = Point(14598, 6656.51);
+ new ShapeRef(router, polygon, 2444);
+
+ // shapeRef2445
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4939, 8723.12);
+ polygon.ps[1] = Point(4939, 8807.22);
+ polygon.ps[2] = Point(4892.77, 8807.22);
+ polygon.ps[3] = Point(4892.77, 8723.12);
+ new ShapeRef(router, polygon, 2445);
+
+ // shapeRef2446
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4939, 9228.32);
+ polygon.ps[1] = Point(4939, 9312.42);
+ polygon.ps[2] = Point(4892.77, 9312.42);
+ polygon.ps[3] = Point(4892.77, 9228.32);
+ new ShapeRef(router, polygon, 2446);
+
+ // shapeRef2447
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7755.29, 1354.06);
+ polygon.ps[1] = Point(7755.29, 1412.29);
+ polygon.ps[2] = Point(7710.6, 1412.29);
+ polygon.ps[3] = Point(7710.6, 1354.06);
+ new ShapeRef(router, polygon, 2447);
+
+ // shapeRef2448
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7598.1, 1354.06);
+ polygon.ps[1] = Point(7598.1, 1412.29);
+ polygon.ps[2] = Point(7553.4, 1412.29);
+ polygon.ps[3] = Point(7553.4, 1354.06);
+ new ShapeRef(router, polygon, 2448);
+
+ // shapeRef2449
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8328.79, 9774.02);
+ polygon.ps[1] = Point(8328.79, 9834.02);
+ polygon.ps[2] = Point(8273.79, 9834.02);
+ polygon.ps[3] = Point(8273.79, 9774.02);
+ new ShapeRef(router, polygon, 2449);
+
+ // shapeRef2450
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10502.2, 9147.42);
+ polygon.ps[1] = Point(10502.2, 9205.64);
+ polygon.ps[2] = Point(10457.5, 9205.64);
+ polygon.ps[3] = Point(10457.5, 9147.42);
+ new ShapeRef(router, polygon, 2450);
+
+ // shapeRef2451
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9042.99, 8348.99);
+ polygon.ps[1] = Point(9042.99, 8407.22);
+ polygon.ps[2] = Point(8998.3, 8407.22);
+ polygon.ps[3] = Point(8998.3, 8348.99);
+ new ShapeRef(router, polygon, 2451);
+
+ // shapeRef2452
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10964.2, 1115.29);
+ polygon.ps[1] = Point(10964.2, 1223.55);
+ polygon.ps[2] = Point(10917.4, 1223.55);
+ polygon.ps[3] = Point(10917.4, 1115.29);
+ new ShapeRef(router, polygon, 2452);
+
+ // shapeRef2453
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12521.5, 4971.4);
+ polygon.ps[1] = Point(12521.5, 5031.97);
+ polygon.ps[2] = Point(12449.9, 5031.97);
+ polygon.ps[3] = Point(12449.9, 4971.4);
+ new ShapeRef(router, polygon, 2453);
+
+ // shapeRef2454
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13030.8, 4519.4);
+ polygon.ps[1] = Point(13030.8, 4566.19);
+ polygon.ps[2] = Point(12922.5, 4566.19);
+ polygon.ps[3] = Point(12922.5, 4519.4);
+ new ShapeRef(router, polygon, 2454);
+
+ // shapeRef2455
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12521.5, 2198.19);
+ polygon.ps[1] = Point(12521.5, 2282.29);
+ polygon.ps[2] = Point(12475.3, 2282.29);
+ polygon.ps[3] = Point(12475.3, 2198.19);
+ new ShapeRef(router, polygon, 2455);
+
+ // shapeRef2456
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8711.86, 4202.51);
+ polygon.ps[1] = Point(8711.86, 4274.11);
+ polygon.ps[2] = Point(8651.29, 4274.11);
+ polygon.ps[3] = Point(8651.29, 4202.51);
+ new ShapeRef(router, polygon, 2456);
+
+ // shapeRef2457
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9019.99, 3443.51);
+ polygon.ps[1] = Point(9019.99, 3488.21);
+ polygon.ps[2] = Point(8961.76, 3488.21);
+ polygon.ps[3] = Point(8961.76, 3443.51);
+ new ShapeRef(router, polygon, 2457);
+
+ // shapeRef2458
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13324.2, 8883.22);
+ polygon.ps[1] = Point(13324.2, 8927.91);
+ polygon.ps[2] = Point(13266, 8927.91);
+ polygon.ps[3] = Point(13266, 8883.22);
+ new ShapeRef(router, polygon, 2458);
+
+ // shapeRef2459
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9237.59, 11221.6);
+ polygon.ps[1] = Point(9237.59, 11266.3);
+ polygon.ps[2] = Point(9179.36, 11266.3);
+ polygon.ps[3] = Point(9179.36, 11221.6);
+ new ShapeRef(router, polygon, 2459);
+
+ // shapeRef2460
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8684.29, 11221.6);
+ polygon.ps[1] = Point(8684.29, 11267.9);
+ polygon.ps[2] = Point(8600.2, 11267.9);
+ polygon.ps[3] = Point(8600.2, 11221.6);
+ new ShapeRef(router, polygon, 2460);
+
+ // shapeRef2461
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7202.1, 7293.4);
+ polygon.ps[1] = Point(7202.1, 7351.63);
+ polygon.ps[2] = Point(7157.4, 7351.63);
+ polygon.ps[3] = Point(7157.4, 7293.4);
+ new ShapeRef(router, polygon, 2461);
+
+ // shapeRef2462
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7305.66, 6524.51);
+ polygon.ps[1] = Point(7305.66, 6596.11);
+ polygon.ps[2] = Point(7245.1, 6596.11);
+ polygon.ps[3] = Point(7245.1, 6524.51);
+ new ShapeRef(router, polygon, 2462);
+
+ // shapeRef2463
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6387.1, 6798.21);
+ polygon.ps[1] = Point(6387.1, 6844.44);
+ polygon.ps[2] = Point(6303, 6844.44);
+ polygon.ps[3] = Point(6303, 6798.21);
+ new ShapeRef(router, polygon, 2463);
+
+ // shapeRef2464
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15138.3, 10854.1);
+ polygon.ps[1] = Point(15138.3, 10914.6);
+ polygon.ps[2] = Point(15066.7, 10914.6);
+ polygon.ps[3] = Point(15066.7, 10854.1);
+ new ShapeRef(router, polygon, 2464);
+
+ // shapeRef2465
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9939.69, 9976.02);
+ polygon.ps[1] = Point(9939.69, 10034.2);
+ polygon.ps[2] = Point(9894.99, 10034.2);
+ polygon.ps[3] = Point(9894.99, 9976.02);
+ new ShapeRef(router, polygon, 2465);
+
+ // shapeRef2466
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10314.9, 9383.85);
+ polygon.ps[1] = Point(10314.9, 9444.42);
+ polygon.ps[2] = Point(10243.3, 9444.42);
+ polygon.ps[3] = Point(10243.3, 9383.85);
+ new ShapeRef(router, polygon, 2466);
+
+ // shapeRef2467
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13209.3, 4552.4);
+ polygon.ps[1] = Point(13209.3, 4599.19);
+ polygon.ps[2] = Point(13101, 4599.19);
+ polygon.ps[3] = Point(13101, 4552.4);
+ new ShapeRef(router, polygon, 2467);
+
+ // shapeRef2468
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8684.29, 11330.6);
+ polygon.ps[1] = Point(8684.29, 11376.8);
+ polygon.ps[2] = Point(8600.2, 11376.8);
+ polygon.ps[3] = Point(8600.2, 11330.6);
+ new ShapeRef(router, polygon, 2468);
+
+ // shapeRef2469
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6542.1, 8041.79);
+ polygon.ps[1] = Point(6542.1, 8100.02);
+ polygon.ps[2] = Point(6497.4, 8100.02);
+ polygon.ps[3] = Point(6497.4, 8041.79);
+ new ShapeRef(router, polygon, 2469);
+
+ // shapeRef2470
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10314.9, 9444.42);
+ polygon.ps[1] = Point(10314.9, 9502.64);
+ polygon.ps[2] = Point(10270.2, 9502.64);
+ polygon.ps[3] = Point(10270.2, 9444.42);
+ new ShapeRef(router, polygon, 2470);
+
+ // shapeRef2471
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9194.59, 11698.9);
+ polygon.ps[1] = Point(9194.59, 11757.1);
+ polygon.ps[2] = Point(9149.9, 11757.1);
+ polygon.ps[3] = Point(9149.9, 11698.9);
+ new ShapeRef(router, polygon, 2471);
+
+ // shapeRef2472
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(649, 148.265);
+ polygon.ps[1] = Point(649, 208.827);
+ polygon.ps[2] = Point(577.401, 208.827);
+ polygon.ps[3] = Point(577.401, 148.265);
+ new ShapeRef(router, polygon, 2472);
+
+ // shapeRef2473
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8792.89, 10014.5);
+ polygon.ps[1] = Point(8792.89, 10075);
+ polygon.ps[2] = Point(8721.29, 10075);
+ polygon.ps[3] = Point(8721.29, 10014.5);
+ new ShapeRef(router, polygon, 2473);
+
+ // shapeRef2474
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(253, 148.265);
+ polygon.ps[1] = Point(253, 232.363);
+ polygon.ps[2] = Point(206.765, 232.363);
+ polygon.ps[3] = Point(206.765, 148.265);
+ new ShapeRef(router, polygon, 2474);
+
+ // shapeRef2475
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9009.99, 5657.9);
+ polygon.ps[1] = Point(9009.99, 5716.12);
+ polygon.ps[2] = Point(8965.3, 5716.12);
+ polygon.ps[3] = Point(8965.3, 5657.9);
+ new ShapeRef(router, polygon, 2475);
+
+ // shapeRef2476
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15138.3, 11893.9);
+ polygon.ps[1] = Point(15138.3, 11952.1);
+ polygon.ps[2] = Point(15093.7, 11952.1);
+ polygon.ps[3] = Point(15093.7, 11893.9);
+ new ShapeRef(router, polygon, 2476);
+
+ // shapeRef2477
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10572.8, 10692.3);
+ polygon.ps[1] = Point(10572.8, 10763.9);
+ polygon.ps[2] = Point(10512.2, 10763.9);
+ polygon.ps[3] = Point(10512.2, 10692.3);
+ new ShapeRef(router, polygon, 2477);
+
+ // shapeRef2478
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10667.2, 8521.76);
+ polygon.ps[1] = Point(10667.2, 8579.99);
+ polygon.ps[2] = Point(10622.5, 8579.99);
+ polygon.ps[3] = Point(10622.5, 8521.76);
+ new ShapeRef(router, polygon, 2478);
+
+ // shapeRef2479
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9751.69, 818.091);
+ polygon.ps[1] = Point(9751.69, 862.785);
+ polygon.ps[2] = Point(9693.46, 862.785);
+ polygon.ps[3] = Point(9693.46, 818.091);
+ new ShapeRef(router, polygon, 2479);
+
+ // shapeRef2480
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10964.2, 1057.06);
+ polygon.ps[1] = Point(10964.2, 1115.29);
+ polygon.ps[2] = Point(10919.5, 1115.29);
+ polygon.ps[3] = Point(10919.5, 1057.06);
+ new ShapeRef(router, polygon, 2480);
+
+ // shapeRef2481
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10799.2, 7810.79);
+ polygon.ps[1] = Point(10799.2, 7871.36);
+ polygon.ps[2] = Point(10727.6, 7871.36);
+ polygon.ps[3] = Point(10727.6, 7810.79);
+ new ShapeRef(router, polygon, 2481);
+
+ // shapeRef2482
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7476.1, 3575.51);
+ polygon.ps[1] = Point(7476.1, 3620.21);
+ polygon.ps[2] = Point(7417.87, 3620.21);
+ polygon.ps[3] = Point(7417.87, 3575.51);
+ new ShapeRef(router, polygon, 2482);
+
+ // shapeRef2483
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5302, 4575.4);
+ polygon.ps[1] = Point(5302, 4659.5);
+ polygon.ps[2] = Point(5255.77, 4659.5);
+ polygon.ps[3] = Point(5255.77, 4575.4);
+ new ShapeRef(router, polygon, 2483);
+
+ // shapeRef2484
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6321.1, 435.265);
+ polygon.ps[1] = Point(6321.1, 479.96);
+ polygon.ps[2] = Point(6262.87, 479.96);
+ polygon.ps[3] = Point(6262.87, 435.265);
+ new ShapeRef(router, polygon, 2484);
+
+ // shapeRef2485
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11296.4, 4371.11);
+ polygon.ps[1] = Point(11296.4, 4415.81);
+ polygon.ps[2] = Point(11238.2, 4415.81);
+ polygon.ps[3] = Point(11238.2, 4371.11);
+ new ShapeRef(router, polygon, 2485);
+
+ // shapeRef2486
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16618.4, 10184);
+ polygon.ps[1] = Point(16618.4, 10255.6);
+ polygon.ps[2] = Point(16557.8, 10255.6);
+ polygon.ps[3] = Point(16557.8, 10184);
+ new ShapeRef(router, polygon, 2486);
+
+ // shapeRef2487
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12815.7, 11642.9);
+ polygon.ps[1] = Point(12815.7, 11687.6);
+ polygon.ps[2] = Point(12757.5, 11687.6);
+ polygon.ps[3] = Point(12757.5, 11642.9);
+ new ShapeRef(router, polygon, 2487);
+
+ // shapeRef2488
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13159.2, 10791.3);
+ polygon.ps[1] = Point(13159.2, 10836);
+ polygon.ps[2] = Point(13101, 10836);
+ polygon.ps[3] = Point(13101, 10791.3);
+ new ShapeRef(router, polygon, 2488);
+
+ // shapeRef2489
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9009.99, 2320.72);
+ polygon.ps[1] = Point(9009.99, 2381.29);
+ polygon.ps[2] = Point(8938.39, 2381.29);
+ polygon.ps[3] = Point(8938.39, 2320.72);
+ new ShapeRef(router, polygon, 2489);
+
+ // shapeRef2490
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13101, 4552.4);
+ polygon.ps[1] = Point(13101, 4597.1);
+ polygon.ps[2] = Point(13042.8, 4597.1);
+ polygon.ps[3] = Point(13042.8, 4552.4);
+ new ShapeRef(router, polygon, 2490);
+
+ // shapeRef2491
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11296.4, 8993.72);
+ polygon.ps[1] = Point(11296.4, 9038.42);
+ polygon.ps[2] = Point(11238.2, 9038.42);
+ polygon.ps[3] = Point(11238.2, 8993.72);
+ new ShapeRef(router, polygon, 2491);
+
+ // shapeRef2492
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11164.4, 8195.3);
+ polygon.ps[1] = Point(11164.4, 8239.99);
+ polygon.ps[2] = Point(11106.2, 8239.99);
+ polygon.ps[3] = Point(11106.2, 8195.3);
+ new ShapeRef(router, polygon, 2492);
+
+ // shapeRef2493
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14598, 6908.71);
+ polygon.ps[1] = Point(14598, 6953.4);
+ polygon.ps[2] = Point(14539.8, 6953.4);
+ polygon.ps[3] = Point(14539.8, 6908.71);
+ new ShapeRef(router, polygon, 2493);
+
+ // shapeRef2494
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10037.4, 9708.42);
+ polygon.ps[1] = Point(10037.4, 9766.64);
+ polygon.ps[2] = Point(9992.69, 9766.64);
+ polygon.ps[3] = Point(9992.69, 9708.42);
+ new ShapeRef(router, polygon, 2494);
+
+ // shapeRef2495
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9835.79, 818.091);
+ polygon.ps[1] = Point(9835.79, 864.326);
+ polygon.ps[2] = Point(9751.69, 864.326);
+ polygon.ps[3] = Point(9751.69, 818.091);
+ new ShapeRef(router, polygon, 2495);
+
+ // shapeRef2496
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10964.2, 1115.29);
+ polygon.ps[1] = Point(10964.2, 1205.05);
+ polygon.ps[2] = Point(10888, 1205.05);
+ polygon.ps[3] = Point(10888, 1115.29);
+ new ShapeRef(router, polygon, 2496);
+
+ // shapeRef2497
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10799.2, 7726.7);
+ polygon.ps[1] = Point(10799.2, 7810.79);
+ polygon.ps[2] = Point(10753, 7810.79);
+ polygon.ps[3] = Point(10753, 7726.7);
+ new ShapeRef(router, polygon, 2497);
+
+ // shapeRef2498
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7560.2, 3575.51);
+ polygon.ps[1] = Point(7560.2, 3621.75);
+ polygon.ps[2] = Point(7476.1, 3621.75);
+ polygon.ps[3] = Point(7476.1, 3575.51);
+ new ShapeRef(router, polygon, 2498);
+
+ // shapeRef2499
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5302, 4491.31);
+ polygon.ps[1] = Point(5302, 4575.4);
+ polygon.ps[2] = Point(5255.77, 4575.4);
+ polygon.ps[3] = Point(5255.77, 4491.31);
+ new ShapeRef(router, polygon, 2499);
+
+ // shapeRef2500
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6405.2, 435.265);
+ polygon.ps[1] = Point(6405.2, 481.5);
+ polygon.ps[2] = Point(6321.1, 481.5);
+ polygon.ps[3] = Point(6321.1, 435.265);
+ new ShapeRef(router, polygon, 2500);
+
+ // shapeRef2501
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11238.2, 4371.11);
+ polygon.ps[1] = Point(11238.2, 4417.35);
+ polygon.ps[2] = Point(11154.1, 4417.35);
+ polygon.ps[3] = Point(11154.1, 4371.11);
+ new ShapeRef(router, polygon, 2501);
+
+ // shapeRef2502
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16557.8, 10184);
+ polygon.ps[1] = Point(16557.8, 10230.2);
+ polygon.ps[2] = Point(16473.7, 10230.2);
+ polygon.ps[3] = Point(16473.7, 10184);
+ new ShapeRef(router, polygon, 2502);
+
+ // shapeRef2503
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12757.5, 11642.9);
+ polygon.ps[1] = Point(12757.5, 11689.1);
+ polygon.ps[2] = Point(12673.4, 11689.1);
+ polygon.ps[3] = Point(12673.4, 11642.9);
+ new ShapeRef(router, polygon, 2503);
+
+ // shapeRef2504
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13101, 10791.3);
+ polygon.ps[1] = Point(13101, 10837.5);
+ polygon.ps[2] = Point(13016.9, 10837.5);
+ polygon.ps[3] = Point(13016.9, 10791.3);
+ new ShapeRef(router, polygon, 2504);
+
+ // shapeRef2505
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9009.99, 2381.29);
+ polygon.ps[1] = Point(9009.99, 2465.38);
+ polygon.ps[2] = Point(8963.76, 2465.38);
+ polygon.ps[3] = Point(8963.76, 2381.29);
+ new ShapeRef(router, polygon, 2505);
+
+ // shapeRef2506
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13190.7, 4552.4);
+ polygon.ps[1] = Point(13190.7, 4628.63);
+ polygon.ps[2] = Point(13101, 4628.63);
+ polygon.ps[3] = Point(13101, 4552.4);
+ new ShapeRef(router, polygon, 2506);
+
+ // shapeRef2507
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11238.2, 8992.18);
+ polygon.ps[1] = Point(11238.2, 9038.42);
+ polygon.ps[2] = Point(11154.1, 9038.42);
+ polygon.ps[3] = Point(11154.1, 8992.18);
+ new ShapeRef(router, polygon, 2507);
+
+ // shapeRef2508
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11106.2, 8193.76);
+ polygon.ps[1] = Point(11106.2, 8239.99);
+ polygon.ps[2] = Point(11022.1, 8239.99);
+ polygon.ps[3] = Point(11022.1, 8193.76);
+ new ShapeRef(router, polygon, 2508);
+
+ // shapeRef2509
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14682.1, 6907.17);
+ polygon.ps[1] = Point(14682.1, 6953.4);
+ polygon.ps[2] = Point(14598, 6953.4);
+ polygon.ps[3] = Point(14598, 6907.17);
+ new ShapeRef(router, polygon, 2509);
+
+ // shapeRef2510
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10068.9, 9618.65);
+ polygon.ps[1] = Point(10068.9, 9708.42);
+ polygon.ps[2] = Point(9992.69, 9708.42);
+ polygon.ps[3] = Point(9992.69, 9618.65);
+ new ShapeRef(router, polygon, 2510);
+
+ // shapeRef2511
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5302, 5085.31);
+ polygon.ps[1] = Point(5302, 5169.4);
+ polygon.ps[2] = Point(5255.77, 5169.4);
+ polygon.ps[3] = Point(5255.77, 5085.31);
+ new ShapeRef(router, polygon, 2511);
+
+ // shapeRef2512
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10512.2, 10692.3);
+ polygon.ps[1] = Point(10512.2, 10738.5);
+ polygon.ps[2] = Point(10428.1, 10738.5);
+ polygon.ps[3] = Point(10428.1, 10692.3);
+ new ShapeRef(router, polygon, 2512);
+
+ // shapeRef2513
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9194.59, 11638.3);
+ polygon.ps[1] = Point(9194.59, 11698.9);
+ polygon.ps[2] = Point(9122.99, 11698.9);
+ polygon.ps[3] = Point(9122.99, 11638.3);
+ new ShapeRef(router, polygon, 2513);
+
+ // shapeRef2514
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(649, 87.7033);
+ polygon.ps[1] = Point(649, 148.265);
+ polygon.ps[2] = Point(577.401, 148.265);
+ polygon.ps[3] = Point(577.401, 87.7033);
+ new ShapeRef(router, polygon, 2514);
+
+ // shapeRef2515
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9042.99, 8290.76);
+ polygon.ps[1] = Point(9042.99, 8348.99);
+ polygon.ps[2] = Point(8998.3, 8348.99);
+ polygon.ps[3] = Point(8998.3, 8290.76);
+ new ShapeRef(router, polygon, 2515);
+
+ // shapeRef2516
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9974.92, 11642.9);
+ polygon.ps[1] = Point(9974.92, 11687.6);
+ polygon.ps[2] = Point(9916.69, 11687.6);
+ polygon.ps[3] = Point(9916.69, 11642.9);
+ new ShapeRef(router, polygon, 2516);
+
+ // shapeRef2517
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15138.3, 10914.6);
+ polygon.ps[1] = Point(15138.3, 10972.9);
+ polygon.ps[2] = Point(15093.7, 10972.9);
+ polygon.ps[3] = Point(15093.7, 10914.6);
+ new ShapeRef(router, polygon, 2517);
+
+ // shapeRef2518
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9009.99, 5597.33);
+ polygon.ps[1] = Point(9009.99, 5657.9);
+ polygon.ps[2] = Point(8938.39, 5657.9);
+ polygon.ps[3] = Point(8938.39, 5597.33);
+ new ShapeRef(router, polygon, 2518);
+
+ // shapeRef2519
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15432.8, 1191.29);
+ polygon.ps[1] = Point(15432.8, 1235.98);
+ polygon.ps[2] = Point(15374.5, 1235.98);
+ polygon.ps[3] = Point(15374.5, 1191.29);
+ new ShapeRef(router, polygon, 2519);
+
+ // shapeRef2520
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6783.1, 3575.51);
+ polygon.ps[1] = Point(6783.1, 3620.21);
+ polygon.ps[2] = Point(6724.87, 3620.21);
+ polygon.ps[3] = Point(6724.87, 3575.51);
+ new ShapeRef(router, polygon, 2520);
+
+ // shapeRef2521
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5496.1, 5357.67);
+ polygon.ps[1] = Point(5496.1, 5402.36);
+ polygon.ps[2] = Point(5437.87, 5402.36);
+ polygon.ps[3] = Point(5437.87, 5357.67);
+ new ShapeRef(router, polygon, 2521);
+
+ // shapeRef2522
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4949, 5974.59);
+ polygon.ps[1] = Point(4949, 6019.29);
+ polygon.ps[2] = Point(4890.77, 6019.29);
+ polygon.ps[3] = Point(4890.77, 5974.59);
+ new ShapeRef(router, polygon, 2522);
+
+ // shapeRef2523
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4939, 6056.29);
+ polygon.ps[1] = Point(4939, 6114.51);
+ polygon.ps[2] = Point(4894.31, 6114.51);
+ polygon.ps[3] = Point(4894.31, 6056.29);
+ new ShapeRef(router, polygon, 2523);
+
+ // shapeRef2524
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8293.29, 435.265);
+ polygon.ps[1] = Point(8293.29, 479.96);
+ polygon.ps[2] = Point(8235.07, 479.96);
+ polygon.ps[3] = Point(8235.07, 435.265);
+ new ShapeRef(router, polygon, 2524);
+
+ // shapeRef2525
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15173.6, 1191.29);
+ polygon.ps[1] = Point(15173.6, 1235.98);
+ polygon.ps[2] = Point(15115.3, 1235.98);
+ polygon.ps[3] = Point(15115.3, 1191.29);
+ new ShapeRef(router, polygon, 2525);
+
+ // shapeRef2526
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5651.1, 4517.18);
+ polygon.ps[1] = Point(5651.1, 4575.4);
+ polygon.ps[2] = Point(5606.4, 4575.4);
+ polygon.ps[3] = Point(5606.4, 4517.18);
+ new ShapeRef(router, polygon, 2526);
+
+ // shapeRef2527
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10170.7, 10372);
+ polygon.ps[1] = Point(10170.7, 10430.2);
+ polygon.ps[2] = Point(10126, 10430.2);
+ polygon.ps[3] = Point(10126, 10372);
+ new ShapeRef(router, polygon, 2527);
+
+ // shapeRef2528
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8285.52, 10725.3);
+ polygon.ps[1] = Point(8285.52, 10770);
+ polygon.ps[2] = Point(8227.29, 10770);
+ polygon.ps[3] = Point(8227.29, 10725.3);
+ new ShapeRef(router, polygon, 2528);
+
+ // shapeRef2529
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6709.33, 7006.4);
+ polygon.ps[1] = Point(6709.33, 7051.1);
+ polygon.ps[2] = Point(6651.1, 7051.1);
+ polygon.ps[3] = Point(6651.1, 7006.4);
+ new ShapeRef(router, polygon, 2529);
+
+ // shapeRef2530
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6542.1, 7579.79);
+ polygon.ps[1] = Point(6542.1, 7638.02);
+ polygon.ps[2] = Point(6497.4, 7638.02);
+ polygon.ps[3] = Point(6497.4, 7579.79);
+ new ShapeRef(router, polygon, 2530);
+
+ // shapeRef2531
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7329.2, 6524.51);
+ polygon.ps[1] = Point(7329.2, 6570.75);
+ polygon.ps[2] = Point(7245.1, 6570.75);
+ polygon.ps[3] = Point(7245.1, 6524.51);
+ new ShapeRef(router, polygon, 2531);
+
+ // shapeRef2532
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6387.1, 6798.21);
+ polygon.ps[1] = Point(6387.1, 6869.81);
+ polygon.ps[2] = Point(6326.54, 6869.81);
+ polygon.ps[3] = Point(6326.54, 6798.21);
+ new ShapeRef(router, polygon, 2532);
+
+ // shapeRef2533
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5007.23, 5832.9);
+ polygon.ps[1] = Point(5007.23, 5877.59);
+ polygon.ps[2] = Point(4949, 5877.59);
+ polygon.ps[3] = Point(4949, 5832.9);
+ new ShapeRef(router, polygon, 2533);
+
+ // shapeRef2534
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11353.1, 3338.29);
+ polygon.ps[1] = Point(11353.1, 3396.51);
+ polygon.ps[2] = Point(11308.4, 3396.51);
+ polygon.ps[3] = Point(11308.4, 3338.29);
+ new ShapeRef(router, polygon, 2534);
+
+ // shapeRef2535
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15045.1, 1191.29);
+ polygon.ps[1] = Point(15045.1, 1235.98);
+ polygon.ps[2] = Point(14986.9, 1235.98);
+ polygon.ps[3] = Point(14986.9, 1191.29);
+ new ShapeRef(router, polygon, 2535);
+
+ // shapeRef2536
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4939, 6151.51);
+ polygon.ps[1] = Point(4939, 6209.74);
+ polygon.ps[2] = Point(4894.31, 6209.74);
+ polygon.ps[3] = Point(4894.31, 6151.51);
+ new ShapeRef(router, polygon, 2536);
+
+ // shapeRef2537
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15604.3, 1191.29);
+ polygon.ps[1] = Point(15604.3, 1235.98);
+ polygon.ps[2] = Point(15546, 1235.98);
+ polygon.ps[3] = Point(15546, 1191.29);
+ new ShapeRef(router, polygon, 2537);
+
+ // shapeRef2538
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7755.29, 1412.29);
+ polygon.ps[1] = Point(7755.29, 1470.51);
+ polygon.ps[2] = Point(7710.6, 1470.51);
+ polygon.ps[3] = Point(7710.6, 1412.29);
+ new ShapeRef(router, polygon, 2538);
+
+ // shapeRef2539
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12521.5, 3474.29);
+ polygon.ps[1] = Point(12521.5, 3532.51);
+ polygon.ps[2] = Point(12476.8, 3532.51);
+ polygon.ps[3] = Point(12476.8, 3474.29);
+ new ShapeRef(router, polygon, 2539);
+
+ // shapeRef2540
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11353.1, 1420.06);
+ polygon.ps[1] = Point(11353.1, 1478.29);
+ polygon.ps[2] = Point(11308.4, 1478.29);
+ polygon.ps[3] = Point(11308.4, 1420.06);
+ new ShapeRef(router, polygon, 2540);
+
+ // shapeRef2541
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16155.6, 749.864);
+ polygon.ps[1] = Point(16155.6, 808.091);
+ polygon.ps[2] = Point(16110.9, 808.091);
+ polygon.ps[3] = Point(16110.9, 749.864);
+ new ShapeRef(router, polygon, 2541);
+
+ // shapeRef2542
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(17274.1, 7112.81);
+ polygon.ps[1] = Point(17274.1, 7184.4);
+ polygon.ps[2] = Point(17213.5, 7184.4);
+ polygon.ps[3] = Point(17213.5, 7112.81);
+ new ShapeRef(router, polygon, 2542);
+
+ // shapeRef2543
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11353.1, 2249.29);
+ polygon.ps[1] = Point(11353.1, 2307.51);
+ polygon.ps[2] = Point(11308.4, 2307.51);
+ polygon.ps[3] = Point(11308.4, 2249.29);
+ new ShapeRef(router, polygon, 2543);
+
+ // shapeRef2544
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9105.49, 2341.29);
+ polygon.ps[1] = Point(9105.49, 2381.29);
+ polygon.ps[2] = Point(9029.99, 2381.29);
+ polygon.ps[3] = Point(9029.99, 2341.29);
+ new ShapeRef(router, polygon, 2544);
+
+ // shapeRef2545
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15479.8, 1356.29);
+ polygon.ps[1] = Point(15479.8, 1416.29);
+ polygon.ps[2] = Point(15424.8, 1416.29);
+ polygon.ps[3] = Point(15424.8, 1356.29);
+ new ShapeRef(router, polygon, 2545);
+
+ // shapeRef2546
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15656.8, 1356.29);
+ polygon.ps[1] = Point(15656.8, 1416.29);
+ polygon.ps[2] = Point(15601.8, 1416.29);
+ polygon.ps[3] = Point(15601.8, 1356.29);
+ new ShapeRef(router, polygon, 2546);
+
+ // shapeRef2547
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8676.52, 993.285);
+ polygon.ps[1] = Point(8676.52, 1037.98);
+ polygon.ps[2] = Point(8618.29, 1037.98);
+ polygon.ps[3] = Point(8618.29, 993.285);
+ new ShapeRef(router, polygon, 2547);
+
+ // shapeRef2548
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8260.29, 818.091);
+ polygon.ps[1] = Point(8260.29, 862.785);
+ polygon.ps[2] = Point(8202.07, 862.785);
+ polygon.ps[3] = Point(8202.07, 818.091);
+ new ShapeRef(router, polygon, 2548);
+
+ // shapeRef2549
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8618.29, 993.285);
+ polygon.ps[1] = Point(8618.29, 1037.98);
+ polygon.ps[2] = Point(8560.07, 1037.98);
+ polygon.ps[3] = Point(8560.07, 993.285);
+ new ShapeRef(router, polygon, 2549);
+
+ // shapeRef2550
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15325, 945.785);
+ polygon.ps[1] = Point(15325, 985.785);
+ polygon.ps[2] = Point(15249.5, 985.785);
+ polygon.ps[3] = Point(15249.5, 945.785);
+ new ShapeRef(router, polygon, 2550);
+
+ // shapeRef2551
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14310.3, 12302.3);
+ polygon.ps[1] = Point(14310.3, 12349.1);
+ polygon.ps[2] = Point(14202, 12349.1);
+ polygon.ps[3] = Point(14202, 12302.3);
+ new ShapeRef(router, polygon, 2551);
+
+ // shapeRef2552
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9260.59, 5599.67);
+ polygon.ps[1] = Point(9260.59, 5657.9);
+ polygon.ps[2] = Point(9215.9, 5657.9);
+ polygon.ps[3] = Point(9215.9, 5599.67);
+ new ShapeRef(router, polygon, 2552);
+
+ // shapeRef2553
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9491.59, 10372);
+ polygon.ps[1] = Point(9491.59, 10430.2);
+ polygon.ps[2] = Point(9446.9, 10430.2);
+ polygon.ps[3] = Point(9446.9, 10372);
+ new ShapeRef(router, polygon, 2553);
+
+ // shapeRef2554
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15765.9, 10791.3);
+ polygon.ps[1] = Point(15765.9, 10838.1);
+ polygon.ps[2] = Point(15657.6, 10838.1);
+ polygon.ps[3] = Point(15657.6, 10791.3);
+ new ShapeRef(router, polygon, 2554);
+
+ // shapeRef2555
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10799.2, 5657.9);
+ polygon.ps[1] = Point(10799.2, 5716.12);
+ polygon.ps[2] = Point(10754.5, 5716.12);
+ polygon.ps[3] = Point(10754.5, 5657.9);
+ new ShapeRef(router, polygon, 2555);
+
+ // shapeRef2556
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16066.6, 11396.8);
+ polygon.ps[1] = Point(16066.6, 11443.6);
+ polygon.ps[2] = Point(15958.3, 11443.6);
+ polygon.ps[3] = Point(15958.3, 11396.8);
+ new ShapeRef(router, polygon, 2556);
+
+ // shapeRef2557
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12521.5, 3994.51);
+ polygon.ps[1] = Point(12521.5, 4052.74);
+ polygon.ps[2] = Point(12476.8, 4052.74);
+ polygon.ps[3] = Point(12476.8, 3994.51);
+ new ShapeRef(router, polygon, 2557);
+
+ // shapeRef2558
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15115.3, 1191.29);
+ polygon.ps[1] = Point(15115.3, 1235.98);
+ polygon.ps[2] = Point(15057.1, 1235.98);
+ polygon.ps[3] = Point(15057.1, 1191.29);
+ new ShapeRef(router, polygon, 2558);
+
+ // shapeRef2559
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13534.2, 3872.51);
+ polygon.ps[1] = Point(13534.2, 3917.21);
+ polygon.ps[2] = Point(13476, 3917.21);
+ polygon.ps[3] = Point(13476, 3872.51);
+ new ShapeRef(router, polygon, 2559);
+
+ // shapeRef2560
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16056.6, 11547.7);
+ polygon.ps[1] = Point(16056.6, 11605.9);
+ polygon.ps[2] = Point(16011.9, 11605.9);
+ polygon.ps[3] = Point(16011.9, 11547.7);
+ new ShapeRef(router, polygon, 2560);
+
+ // shapeRef2561
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13478.5, 3792.51);
+ polygon.ps[1] = Point(13478.5, 3852.51);
+ polygon.ps[2] = Point(13423.5, 3852.51);
+ polygon.ps[3] = Point(13423.5, 3792.51);
+ new ShapeRef(router, polygon, 2561);
+
+ // shapeRef2562
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12353.1, 5244.67);
+ polygon.ps[1] = Point(12353.1, 5304.67);
+ polygon.ps[2] = Point(12298.1, 5304.67);
+ polygon.ps[3] = Point(12298.1, 5244.67);
+ new ShapeRef(router, polygon, 2562);
+
+ // shapeRef2563
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12380.6, 5209.67);
+ polygon.ps[1] = Point(12380.6, 5304.67);
+ polygon.ps[2] = Point(12325.6, 5304.67);
+ polygon.ps[3] = Point(12325.6, 5209.67);
+ new ShapeRef(router, polygon, 2563);
+
+ // shapeRef2564
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10314.9, 9600.15);
+ polygon.ps[1] = Point(10314.9, 9708.42);
+ polygon.ps[2] = Point(10268.1, 9708.42);
+ polygon.ps[3] = Point(10268.1, 9600.15);
+ new ShapeRef(router, polygon, 2564);
+
+ // shapeRef2565
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10039.5, 9600.15);
+ polygon.ps[1] = Point(10039.5, 9708.42);
+ polygon.ps[2] = Point(9992.69, 9708.42);
+ polygon.ps[3] = Point(9992.69, 9600.15);
+ new ShapeRef(router, polygon, 2565);
+
+ // shapeRef2566
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11528.1, 468.265);
+ polygon.ps[1] = Point(11528.1, 514.5);
+ polygon.ps[2] = Point(11444, 514.5);
+ polygon.ps[3] = Point(11444, 468.265);
+ new ShapeRef(router, polygon, 2566);
+
+ // shapeRef2567
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11353.1, 6522.29);
+ polygon.ps[1] = Point(11353.1, 6580.51);
+ polygon.ps[2] = Point(11308.4, 6580.51);
+ polygon.ps[3] = Point(11308.4, 6522.29);
+ new ShapeRef(router, polygon, 2567);
+
+ // shapeRef2568
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(12749.7, 4004.51);
+ polygon.ps[1] = Point(12749.7, 4049.21);
+ polygon.ps[2] = Point(12691.5, 4049.21);
+ polygon.ps[3] = Point(12691.5, 4004.51);
+ new ShapeRef(router, polygon, 2568);
+
+ // shapeRef2569
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15688.4, 1191.29);
+ polygon.ps[1] = Point(15688.4, 1237.52);
+ polygon.ps[2] = Point(15604.3, 1237.52);
+ polygon.ps[3] = Point(15604.3, 1191.29);
+ new ShapeRef(router, polygon, 2569);
+
+ // shapeRef2570
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15954.1, 8410.49);
+ polygon.ps[1] = Point(15954.1, 8450.49);
+ polygon.ps[2] = Point(15878.6, 8450.49);
+ polygon.ps[3] = Point(15878.6, 8410.49);
+ new ShapeRef(router, polygon, 2570);
+
+ // shapeRef2571
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16808.3, 8412.49);
+ polygon.ps[1] = Point(16808.3, 8452.49);
+ polygon.ps[2] = Point(16732.8, 8452.49);
+ polygon.ps[3] = Point(16732.8, 8412.49);
+ new ShapeRef(router, polygon, 2571);
+
+ // shapeRef2572
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5084.5, 8361.99);
+ polygon.ps[1] = Point(5084.5, 8401.99);
+ polygon.ps[2] = Point(4959, 8401.99);
+ polygon.ps[3] = Point(4959, 8361.99);
+ new ShapeRef(router, polygon, 2572);
+
+ // shapeRef2573
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5034.5, 8767.22);
+ polygon.ps[1] = Point(5034.5, 8807.22);
+ polygon.ps[2] = Point(4959, 8807.22);
+ polygon.ps[3] = Point(4959, 8767.22);
+ new ShapeRef(router, polygon, 2573);
+
+ // shapeRef2574
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5084.5, 9292.42);
+ polygon.ps[1] = Point(5084.5, 9332.42);
+ polygon.ps[2] = Point(4959, 9332.42);
+ polygon.ps[3] = Point(4959, 9292.42);
+ new ShapeRef(router, polygon, 2574);
+
+ // shapeRef2575
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4939, 9251.85);
+ polygon.ps[1] = Point(4939, 9312.42);
+ polygon.ps[2] = Point(4867.4, 9312.42);
+ polygon.ps[3] = Point(4867.4, 9251.85);
+ new ShapeRef(router, polygon, 2575);
+
+ // shapeRef2576
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4279, 9815.61);
+ polygon.ps[1] = Point(4279, 9877.02);
+ polygon.ps[2] = Point(4182.65, 9877.02);
+ polygon.ps[3] = Point(4182.65, 9815.61);
+ new ShapeRef(router, polygon, 2576);
+
+ // shapeRef2577
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4812.4, 10448);
+ polygon.ps[1] = Point(4812.4, 10544.4);
+ polygon.ps[2] = Point(4751, 10544.4);
+ polygon.ps[3] = Point(4751, 10448);
+ new ShapeRef(router, polygon, 2577);
+
+ // shapeRef2578
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(4543, 10521.9);
+ polygon.ps[1] = Point(4543, 10583.3);
+ polygon.ps[2] = Point(4446.65, 10583.3);
+ polygon.ps[3] = Point(4446.65, 10521.9);
+ new ShapeRef(router, polygon, 2578);
+
+ // shapeRef2579
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8742.52, 11221.6);
+ polygon.ps[1] = Point(8742.52, 11266.3);
+ polygon.ps[2] = Point(8684.29, 11266.3);
+ polygon.ps[3] = Point(8684.29, 11221.6);
+ new ShapeRef(router, polygon, 2579);
+
+ // shapeRef2580
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(5034.5, 9272.42);
+ polygon.ps[1] = Point(5034.5, 9312.42);
+ polygon.ps[2] = Point(4959, 9312.42);
+ polygon.ps[3] = Point(4959, 9272.42);
+ new ShapeRef(router, polygon, 2580);
+
+ // shapeRef2581
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14334, 468.265);
+ polygon.ps[1] = Point(14334, 512.96);
+ polygon.ps[2] = Point(14275.8, 512.96);
+ polygon.ps[3] = Point(14275.8, 468.265);
+ new ShapeRef(router, polygon, 2581);
+
+ // shapeRef2582
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14392.2, 468.265);
+ polygon.ps[1] = Point(14392.2, 512.96);
+ polygon.ps[2] = Point(14334, 512.96);
+ polygon.ps[3] = Point(14334, 468.265);
+ new ShapeRef(router, polygon, 2582);
+
+ // shapeRef2583
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16124.8, 11804.9);
+ polygon.ps[1] = Point(16124.8, 11849.6);
+ polygon.ps[2] = Point(16066.6, 11849.6);
+ polygon.ps[3] = Point(16066.6, 11804.9);
+ new ShapeRef(router, polygon, 2583);
+
+ // shapeRef2584
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(16583, 7435.4);
+ polygon.ps[1] = Point(16583, 7480.1);
+ polygon.ps[2] = Point(16524.8, 7480.1);
+ polygon.ps[3] = Point(16524.8, 7435.4);
+ new ShapeRef(router, polygon, 2584);
+
+ // shapeRef2585
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9675.69, 7301.18);
+ polygon.ps[1] = Point(9675.69, 7359.4);
+ polygon.ps[2] = Point(9630.99, 7359.4);
+ polygon.ps[3] = Point(9630.99, 7301.18);
+ new ShapeRef(router, polygon, 2585);
+
+ // shapeRef2586
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14916.7, 1356.29);
+ polygon.ps[1] = Point(14916.7, 1400.98);
+ polygon.ps[2] = Point(14858.4, 1400.98);
+ polygon.ps[3] = Point(14858.4, 1356.29);
+ new ShapeRef(router, polygon, 2586);
+
+ // shapeRef2587
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(13299, 9256.42);
+ polygon.ps[1] = Point(13299, 9301.11);
+ polygon.ps[2] = Point(13240.8, 9301.11);
+ polygon.ps[3] = Point(13240.8, 9256.42);
+ new ShapeRef(router, polygon, 2587);
+
+ // shapeRef2588
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(7202.1, 9213.42);
+ polygon.ps[1] = Point(7202.1, 9271.64);
+ polygon.ps[2] = Point(7157.4, 9271.64);
+ polygon.ps[3] = Point(7157.4, 9213.42);
+ new ShapeRef(router, polygon, 2588);
+
+ // shapeRef2589
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6542.1, 9877.02);
+ polygon.ps[1] = Point(6542.1, 9935.24);
+ polygon.ps[2] = Point(6497.4, 9935.24);
+ polygon.ps[3] = Point(6497.4, 9877.02);
+ new ShapeRef(router, polygon, 2589);
+
+ // shapeRef2590
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(8219.52, 6524.51);
+ polygon.ps[1] = Point(8219.52, 6569.21);
+ polygon.ps[2] = Point(8161.29, 6569.21);
+ polygon.ps[3] = Point(8161.29, 6524.51);
+ new ShapeRef(router, polygon, 2590);
+
+ // shapeRef2591
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(6113.1, 7975.79);
+ polygon.ps[1] = Point(6113.1, 8034.02);
+ polygon.ps[2] = Point(6068.4, 8034.02);
+ polygon.ps[3] = Point(6068.4, 7975.79);
+ new ShapeRef(router, polygon, 2591);
+
+ // shapeRef2592
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11240.7, 4122.51);
+ polygon.ps[1] = Point(11240.7, 4182.51);
+ polygon.ps[2] = Point(11185.7, 4182.51);
+ polygon.ps[3] = Point(11185.7, 4122.51);
+ new ShapeRef(router, polygon, 2592);
+
+ // shapeRef2593
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(10170.7, 10313.8);
+ polygon.ps[1] = Point(10170.7, 10372);
+ polygon.ps[2] = Point(10126, 10372);
+ polygon.ps[3] = Point(10126, 10313.8);
+ new ShapeRef(router, polygon, 2593);
+
+ // shapeRef2594
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(11662.6, 10711.3);
+ polygon.ps[1] = Point(11662.6, 10771.3);
+ polygon.ps[2] = Point(11607.6, 10771.3);
+ polygon.ps[3] = Point(11607.6, 10711.3);
+ new ShapeRef(router, polygon, 2594);
+
+ // shapeRef2595
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(14229.5, 12435.7);
+ polygon.ps[1] = Point(14229.5, 12530.7);
+ polygon.ps[2] = Point(14174.5, 12530.7);
+ polygon.ps[3] = Point(14174.5, 12435.7);
+ new ShapeRef(router, polygon, 2595);
+
+ // shapeRef2596
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(9675.69, 7359.4);
+ polygon.ps[1] = Point(9675.69, 7443.5);
+ polygon.ps[2] = Point(9629.45, 7443.5);
+ polygon.ps[3] = Point(9629.45, 7359.4);
+ new ShapeRef(router, polygon, 2596);
+
+ // shapeRef2597
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(649, 148.265);
+ polygon.ps[1] = Point(649, 232.363);
+ polygon.ps[2] = Point(602.765, 232.363);
+ polygon.ps[3] = Point(602.765, 148.265);
+ new ShapeRef(router, polygon, 2597);
+
+ // shapeRef2598
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(744.5, 145.765);
+ polygon.ps[1] = Point(744.5, 185.765);
+ polygon.ps[2] = Point(669, 185.765);
+ polygon.ps[3] = Point(669, 145.765);
+ new ShapeRef(router, polygon, 2598);
+
+ // shapeRef2599
+ polygon = Polygon(4);
+ polygon.ps[0] = Point(15138.3, 11833.3);
+ polygon.ps[1] = Point(15138.3, 11893.9);
+ polygon.ps[2] = Point(15066.7, 11893.9);
+ polygon.ps[3] = Point(15066.7, 11833.3);
+ new ShapeRef(router, polygon, 2599);
+
+ // connRef2600
+ connRef = new ConnRef(router, 2600);
+ srcPt = ConnEnd(Point(7765.29, 7425.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7915.29, 7128.4), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2601
+ connRef = new ConnRef(router, 2601);
+ srcPt = ConnEnd(Point(7945.29, 7128.4), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8293.29, 6854.21), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2602
+ connRef = new ConnRef(router, 2602);
+ srcPt = ConnEnd(Point(9435.59, 6963.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9153.59, 6151.51), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2603
+ connRef = new ConnRef(router, 2603);
+ srcPt = ConnEnd(Point(9123.59, 6151.51), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 5512.67), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2604
+ connRef = new ConnRef(router, 2604);
+ srcPt = ConnEnd(Point(9123.59, 6151.51), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8293.29, 6854.21), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2605
+ connRef = new ConnRef(router, 2605);
+ srcPt = ConnEnd(Point(9435.59, 6963.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9802.69, 7161.4), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2606
+ connRef = new ConnRef(router, 2606);
+ srcPt = ConnEnd(Point(9832.69, 7161.4), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10149, 7458.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2607
+ connRef = new ConnRef(router, 2607);
+ srcPt = ConnEnd(Point(10611.2, 8282.99), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10456.9, 7891.79), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2608
+ connRef = new ConnRef(router, 2608);
+ srcPt = ConnEnd(Point(10456.9, 7861.79), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10149, 7458.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2609
+ connRef = new ConnRef(router, 2609);
+ srcPt = ConnEnd(Point(7831.29, 9477.42), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7575.1, 9096.42), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2610
+ connRef = new ConnRef(router, 2610);
+ srcPt = ConnEnd(Point(7575.1, 9066.42), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7410.1, 8579.99), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2611
+ connRef = new ConnRef(router, 2611);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1361.29), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2612
+ connRef = new ConnRef(router, 2612);
+ srcPt = ConnEnd(Point(7831.29, 9477.42), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1361.29), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2613
+ connRef = new ConnRef(router, 2613);
+ srcPt = ConnEnd(Point(15239.5, 1331.29), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2614
+ connRef = new ConnRef(router, 2614);
+ srcPt = ConnEnd(Point(15239.5, 1331.29), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8684.29, 9976.02), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2615
+ connRef = new ConnRef(router, 2615);
+ srcPt = ConnEnd(Point(10116, 9345.42), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9384.59, 9642.42), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2616
+ connRef = new ConnRef(router, 2616);
+ srcPt = ConnEnd(Point(9354.59, 9642.42), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8684.29, 9976.02), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2617
+ connRef = new ConnRef(router, 2617);
+ srcPt = ConnEnd(Point(7765.29, 7425.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7509.1, 7993.79), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2618
+ connRef = new ConnRef(router, 2618);
+ srcPt = ConnEnd(Point(7509.1, 8023.79), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7410.1, 8579.99), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2619
+ connRef = new ConnRef(router, 2619);
+ srcPt = ConnEnd(Point(10611.2, 8282.99), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10677.2, 8564.99), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2620
+ connRef = new ConnRef(router, 2620);
+ srcPt = ConnEnd(Point(10677.2, 8594.99), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10710.2, 8873.22), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2621
+ connRef = new ConnRef(router, 2621);
+ srcPt = ConnEnd(Point(10710.2, 8873.22), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10512.2, 9132.42), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2622
+ connRef = new ConnRef(router, 2622);
+ srcPt = ConnEnd(Point(10512.2, 9162.42), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10116, 9345.42), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2623
+ connRef = new ConnRef(router, 2623);
+ srcPt = ConnEnd(Point(8835.89, 5004.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9052.99, 8333.99), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2624
+ connRef = new ConnRef(router, 2624);
+ srcPt = ConnEnd(Point(9052.99, 8363.99), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9085.99, 11632.9), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2625
+ connRef = new ConnRef(router, 2625);
+ srcPt = ConnEnd(Point(8835.89, 5004.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 4656.4), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2626
+ connRef = new ConnRef(router, 2626);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 4656.4), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2627
+ connRef = new ConnRef(router, 2627);
+ srcPt = ConnEnd(Point(8835.89, 4626.4), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 4361.11), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2628
+ connRef = new ConnRef(router, 2628);
+ srcPt = ConnEnd(Point(8835.89, 4626.4), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2629
+ connRef = new ConnRef(router, 2629);
+ srcPt = ConnEnd(Point(8835.89, 3664.51), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 3946.51), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2630
+ connRef = new ConnRef(router, 2630);
+ srcPt = ConnEnd(Point(8835.89, 3976.51), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 4361.11), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2631
+ connRef = new ConnRef(router, 2631);
+ srcPt = ConnEnd(Point(9784.69, 5512.67), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9351.59, 5512.67), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2632
+ connRef = new ConnRef(router, 2632);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9351.59, 5512.67), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2633
+ connRef = new ConnRef(router, 2633);
+ srcPt = ConnEnd(Point(9321.59, 5512.67), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 5512.67), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2634
+ connRef = new ConnRef(router, 2634);
+ srcPt = ConnEnd(Point(9321.59, 5512.67), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 742.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2635
+ connRef = new ConnRef(router, 2635);
+ srcPt = ConnEnd(Point(8835.89, 3664.51), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 3448.51), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2636
+ connRef = new ConnRef(router, 2636);
+ srcPt = ConnEnd(Point(8835.89, 3418.51), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 3173.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2637
+ connRef = new ConnRef(router, 2637);
+ srcPt = ConnEnd(Point(8835.89, 3173.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 2924.29), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2638
+ connRef = new ConnRef(router, 2638);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 2924.29), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2639
+ connRef = new ConnRef(router, 2639);
+ srcPt = ConnEnd(Point(8835.89, 2894.29), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 2579.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2640
+ connRef = new ConnRef(router, 2640);
+ srcPt = ConnEnd(Point(8835.89, 2894.29), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2641
+ connRef = new ConnRef(router, 2641);
+ srcPt = ConnEnd(Point(8835.89, 2108.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 2366.29), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2642
+ connRef = new ConnRef(router, 2642);
+ srcPt = ConnEnd(Point(8835.89, 2396.29), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 2579.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2643
+ connRef = new ConnRef(router, 2643);
+ srcPt = ConnEnd(Point(8835.89, 2108.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8440.29, 2108.29), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2644
+ connRef = new ConnRef(router, 2644);
+ srcPt = ConnEnd(Point(8410.29, 2108.29), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8161.29, 2108.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2645
+ connRef = new ConnRef(router, 2645);
+ srcPt = ConnEnd(Point(8458.29, 1676.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8440.29, 2150.29), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2646
+ connRef = new ConnRef(router, 2646);
+ srcPt = ConnEnd(Point(8410.29, 2150.29), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 2108.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2647
+ connRef = new ConnRef(router, 2647);
+ srcPt = ConnEnd(Point(8410.29, 2150.29), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8161.29, 2108.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2648
+ connRef = new ConnRef(router, 2648);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15359.5, 1346.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2649
+ connRef = new ConnRef(router, 2649);
+ srcPt = ConnEnd(Point(8458.29, 1280.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15359.5, 1346.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2650
+ connRef = new ConnRef(router, 2650);
+ srcPt = ConnEnd(Point(15389.5, 1346.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2651
+ connRef = new ConnRef(router, 2651);
+ srcPt = ConnEnd(Point(15389.5, 1346.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8458.29, 1676.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2652
+ connRef = new ConnRef(router, 2652);
+ srcPt = ConnEnd(Point(8458.29, 808.091), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8458.29, 1100.29), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2653
+ connRef = new ConnRef(router, 2653);
+ srcPt = ConnEnd(Point(8458.29, 1130.29), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8458.29, 1280.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2654
+ connRef = new ConnRef(router, 2654);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15100.3, 1346.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2655
+ connRef = new ConnRef(router, 2655);
+ srcPt = ConnEnd(Point(7996.29, 808.091), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15100.3, 1346.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2656
+ connRef = new ConnRef(router, 2656);
+ srcPt = ConnEnd(Point(15130.3, 1346.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2657
+ connRef = new ConnRef(router, 2657);
+ srcPt = ConnEnd(Point(15130.3, 1346.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8458.29, 808.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2658
+ connRef = new ConnRef(router, 2658);
+ srcPt = ConnEnd(Point(8458.29, 808.091), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8971.99, 808.091), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2659
+ connRef = new ConnRef(router, 2659);
+ srcPt = ConnEnd(Point(9001.99, 808.091), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9270.59, 808.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2660
+ connRef = new ConnRef(router, 2660);
+ srcPt = ConnEnd(Point(9270.59, 808.091), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9001.99, 1115.29), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2661
+ connRef = new ConnRef(router, 2661);
+ srcPt = ConnEnd(Point(8971.99, 1115.29), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8458.29, 1280.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2662
+ connRef = new ConnRef(router, 2662);
+ srcPt = ConnEnd(Point(7996.29, 808.091), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7996.29, 968.285), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2663
+ connRef = new ConnRef(router, 2663);
+ srcPt = ConnEnd(Point(7996.29, 998.285), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7996.29, 1148.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2664
+ connRef = new ConnRef(router, 2664);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15462.3, 1346.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2665
+ connRef = new ConnRef(router, 2665);
+ srcPt = ConnEnd(Point(7996.29, 1148.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15462.3, 1346.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2666
+ connRef = new ConnRef(router, 2666);
+ srcPt = ConnEnd(Point(15492.3, 1346.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2667
+ connRef = new ConnRef(router, 2667);
+ srcPt = ConnEnd(Point(15492.3, 1346.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9270.59, 808.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2668
+ connRef = new ConnRef(router, 2668);
+ srcPt = ConnEnd(Point(9270.59, 808.091), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9736.69, 808.091), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2669
+ connRef = new ConnRef(router, 2669);
+ srcPt = ConnEnd(Point(9766.69, 808.091), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10456.9, 808.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2670
+ connRef = new ConnRef(router, 2670);
+ srcPt = ConnEnd(Point(10456.9, 808.091), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10761.2, 808.091), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2671
+ connRef = new ConnRef(router, 2671);
+ srcPt = ConnEnd(Point(10791.2, 808.091), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10974.2, 808.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2672
+ connRef = new ConnRef(router, 2672);
+ srcPt = ConnEnd(Point(10974.2, 808.091), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10974.2, 1100.29), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2673
+ connRef = new ConnRef(router, 2673);
+ srcPt = ConnEnd(Point(10974.2, 1130.29), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10974.2, 1280.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2674
+ connRef = new ConnRef(router, 2674);
+ srcPt = ConnEnd(Point(10974.2, 1280.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10791.2, 1280.29), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2675
+ connRef = new ConnRef(router, 2675);
+ srcPt = ConnEnd(Point(10761.2, 1280.29), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10456.9, 1280.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2676
+ connRef = new ConnRef(router, 2676);
+ srcPt = ConnEnd(Point(8458.29, 1280.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9354.59, 1280.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2677
+ connRef = new ConnRef(router, 2677);
+ srcPt = ConnEnd(Point(8835.89, 2108.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9354.59, 1280.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2678
+ connRef = new ConnRef(router, 2678);
+ srcPt = ConnEnd(Point(9384.59, 1280.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10456.9, 1280.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2679
+ connRef = new ConnRef(router, 2679);
+ srcPt = ConnEnd(Point(9384.59, 1280.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9652.69, 1445.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2680
+ connRef = new ConnRef(router, 2680);
+ srcPt = ConnEnd(Point(9652.69, 1943.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9652.69, 1724.29), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2681
+ connRef = new ConnRef(router, 2681);
+ srcPt = ConnEnd(Point(8835.89, 2108.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9652.69, 1724.29), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2682
+ connRef = new ConnRef(router, 2682);
+ srcPt = ConnEnd(Point(9652.69, 1694.29), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8458.29, 1280.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2683
+ connRef = new ConnRef(router, 2683);
+ srcPt = ConnEnd(Point(9652.69, 1694.29), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9652.69, 1445.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2684
+ connRef = new ConnRef(router, 2684);
+ srcPt = ConnEnd(Point(9652.69, 1943.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9288.59, 2009.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2685
+ connRef = new ConnRef(router, 2685);
+ srcPt = ConnEnd(Point(8835.89, 2108.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9288.59, 2009.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2686
+ connRef = new ConnRef(router, 2686);
+ srcPt = ConnEnd(Point(9318.59, 2009.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10456.9, 1280.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2687
+ connRef = new ConnRef(router, 2687);
+ srcPt = ConnEnd(Point(9318.59, 2009.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10974.2, 1643.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2688
+ connRef = new ConnRef(router, 2688);
+ srcPt = ConnEnd(Point(10974.2, 1643.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10974.2, 1493.29), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2689
+ connRef = new ConnRef(router, 2689);
+ srcPt = ConnEnd(Point(10974.2, 1463.29), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10974.2, 1280.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2690
+ connRef = new ConnRef(router, 2690);
+ srcPt = ConnEnd(Point(10974.2, 1643.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11124.2, 1643.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2691
+ connRef = new ConnRef(router, 2691);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11124.2, 1643.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2692
+ connRef = new ConnRef(router, 2692);
+ srcPt = ConnEnd(Point(11154.2, 1643.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 1643.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2693
+ connRef = new ConnRef(router, 2693);
+ srcPt = ConnEnd(Point(11154.2, 1643.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 742.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2694
+ connRef = new ConnRef(router, 2694);
+ srcPt = ConnEnd(Point(10974.2, 458.265), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10974.2, 595.091), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2695
+ connRef = new ConnRef(router, 2695);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10974.2, 595.091), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2696
+ connRef = new ConnRef(router, 2696);
+ srcPt = ConnEnd(Point(10974.2, 625.091), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10974.2, 808.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2697
+ connRef = new ConnRef(router, 2697);
+ srcPt = ConnEnd(Point(10974.2, 625.091), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2698
+ connRef = new ConnRef(router, 2698);
+ srcPt = ConnEnd(Point(10149, 4361.11), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10530.2, 4361.11), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2699
+ connRef = new ConnRef(router, 2699);
+ srcPt = ConnEnd(Point(10560.2, 4361.11), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10743.2, 4361.11), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2700
+ connRef = new ConnRef(router, 2700);
+ srcPt = ConnEnd(Point(10743.2, 4361.11), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10926.2, 4361.11), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2701
+ connRef = new ConnRef(router, 2701);
+ srcPt = ConnEnd(Point(10956.2, 4361.11), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11073.2, 4361.11), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2702
+ connRef = new ConnRef(router, 2702);
+ srcPt = ConnEnd(Point(11396.1, 4361.11), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11579.1, 4361.11), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2703
+ connRef = new ConnRef(router, 2703);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11579.1, 4361.11), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2704
+ connRef = new ConnRef(router, 2704);
+ srcPt = ConnEnd(Point(11609.1, 4361.11), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11759.1, 4361.11), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2705
+ connRef = new ConnRef(router, 2705);
+ srcPt = ConnEnd(Point(11609.1, 4361.11), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2706
+ connRef = new ConnRef(router, 2706);
+ srcPt = ConnEnd(Point(11759.1, 4361.11), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10596.2, 4509.4), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2707
+ connRef = new ConnRef(router, 2707);
+ srcPt = ConnEnd(Point(8835.89, 4361.11), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10596.2, 4509.4), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2708
+ connRef = new ConnRef(router, 2708);
+ srcPt = ConnEnd(Point(10626.2, 4509.4), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12056.1, 4361.11), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2709
+ connRef = new ConnRef(router, 2709);
+ srcPt = ConnEnd(Point(12056.1, 4361.11), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12206.1, 4361.11), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2710
+ connRef = new ConnRef(router, 2710);
+ srcPt = ConnEnd(Point(12236.1, 4361.11), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12531.5, 4361.11), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2711
+ connRef = new ConnRef(router, 2711);
+ srcPt = ConnEnd(Point(12531.5, 4361.11), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12531.5, 4560.4), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2712
+ connRef = new ConnRef(router, 2712);
+ srcPt = ConnEnd(Point(12531.5, 4590.4), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12531.5, 4740.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2713
+ connRef = new ConnRef(router, 2713);
+ srcPt = ConnEnd(Point(12531.5, 4740.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12531.5, 4956.4), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2714
+ connRef = new ConnRef(router, 2714);
+ srcPt = ConnEnd(Point(12531.5, 4986.4), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12531.5, 5169.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2715
+ connRef = new ConnRef(router, 2715);
+ srcPt = ConnEnd(Point(12531.5, 5512.67), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12531.5, 5329.67), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2716
+ connRef = new ConnRef(router, 2716);
+ srcPt = ConnEnd(Point(12531.5, 5299.67), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12531.5, 5169.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2717
+ connRef = new ConnRef(router, 2717);
+ srcPt = ConnEnd(Point(12531.5, 4740.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12907.5, 4509.4), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2718
+ connRef = new ConnRef(router, 2718);
+ srcPt = ConnEnd(Point(12937.5, 4509.4), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13266, 4126.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2719
+ connRef = new ConnRef(router, 2719);
+ srcPt = ConnEnd(Point(13266, 3631.51), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13266, 3847.51), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2720
+ connRef = new ConnRef(router, 2720);
+ srcPt = ConnEnd(Point(10116, 9345.42), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13266, 3847.51), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2721
+ connRef = new ConnRef(router, 2721);
+ srcPt = ConnEnd(Point(13266, 3877.51), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13266, 4126.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2722
+ connRef = new ConnRef(router, 2722);
+ srcPt = ConnEnd(Point(13266, 3877.51), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10116, 10174), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2723
+ connRef = new ConnRef(router, 2723);
+ srcPt = ConnEnd(Point(12531.5, 4361.11), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12531.5, 4009.51), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2724
+ connRef = new ConnRef(router, 2724);
+ srcPt = ConnEnd(Point(12531.5, 3979.51), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12531.5, 3730.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2725
+ connRef = new ConnRef(router, 2725);
+ srcPt = ConnEnd(Point(12531.5, 3979.51), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 5004.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2726
+ connRef = new ConnRef(router, 2726);
+ srcPt = ConnEnd(Point(12531.5, 3338.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12531.5, 3517.51), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2727
+ connRef = new ConnRef(router, 2727);
+ srcPt = ConnEnd(Point(12531.5, 3547.51), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12531.5, 3730.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2728
+ connRef = new ConnRef(router, 2728);
+ srcPt = ConnEnd(Point(12531.5, 3547.51), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 1643.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2729
+ connRef = new ConnRef(router, 2729);
+ srcPt = ConnEnd(Point(12531.5, 3338.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12531.5, 3056.29), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2730
+ connRef = new ConnRef(router, 2730);
+ srcPt = ConnEnd(Point(12531.5, 3026.29), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12531.5, 2678.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2731
+ connRef = new ConnRef(router, 2731);
+ srcPt = ConnEnd(Point(12531.5, 2678.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12531.5, 2297.29), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2732
+ connRef = new ConnRef(router, 2732);
+ srcPt = ConnEnd(Point(12531.5, 2267.29), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12531.5, 1844.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2733
+ connRef = new ConnRef(router, 2733);
+ srcPt = ConnEnd(Point(12531.5, 1844.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12170.1, 1844.29), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2734
+ connRef = new ConnRef(router, 2734);
+ srcPt = ConnEnd(Point(9501.59, 6481.51), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12170.1, 1844.29), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2735
+ connRef = new ConnRef(router, 2735);
+ srcPt = ConnEnd(Point(12140.1, 1844.29), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11990.1, 1844.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2736
+ connRef = new ConnRef(router, 2736);
+ srcPt = ConnEnd(Point(12140.1, 1844.29), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 2108.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2737
+ connRef = new ConnRef(router, 2737);
+ srcPt = ConnEnd(Point(11990.1, 1577.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11990.1, 1727.29), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2738
+ connRef = new ConnRef(router, 2738);
+ srcPt = ConnEnd(Point(9501.59, 6481.51), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11990.1, 1727.29), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2739
+ connRef = new ConnRef(router, 2739);
+ srcPt = ConnEnd(Point(11990.1, 1757.29), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11990.1, 1844.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2740
+ connRef = new ConnRef(router, 2740);
+ srcPt = ConnEnd(Point(12531.5, 1844.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12170.1, 1742.29), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2741
+ connRef = new ConnRef(router, 2741);
+ srcPt = ConnEnd(Point(12140.1, 1742.29), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11990.1, 1577.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2742
+ connRef = new ConnRef(router, 2742);
+ srcPt = ConnEnd(Point(12140.1, 1742.29), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 2108.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2743
+ connRef = new ConnRef(router, 2743);
+ srcPt = ConnEnd(Point(13872, 8249.99), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13872, 8432.99), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2744
+ connRef = new ConnRef(router, 2744);
+ srcPt = ConnEnd(Point(13872, 8462.99), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13872, 8708.22), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2745
+ connRef = new ConnRef(router, 2745);
+ srcPt = ConnEnd(Point(11924.1, 7612.79), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11924.1, 7828.79), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2746
+ connRef = new ConnRef(router, 2746);
+ srcPt = ConnEnd(Point(11924.1, 7858.79), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11924.1, 8074.79), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2747
+ connRef = new ConnRef(router, 2747);
+ srcPt = ConnEnd(Point(11924.1, 7858.79), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9171.59, 458.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2748
+ connRef = new ConnRef(router, 2748);
+ srcPt = ConnEnd(Point(15868.6, 8249.99), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15868.6, 8432.99), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2749
+ connRef = new ConnRef(router, 2749);
+ srcPt = ConnEnd(Point(15868.6, 8462.99), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15868.6, 8708.22), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2750
+ connRef = new ConnRef(router, 2750);
+ srcPt = ConnEnd(Point(16722.8, 8249.99), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16722.8, 8399.99), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2751
+ connRef = new ConnRef(router, 2751);
+ srcPt = ConnEnd(Point(16722.8, 8429.99), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16722.8, 8642.22), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2752
+ connRef = new ConnRef(router, 2752);
+ srcPt = ConnEnd(Point(13872, 7062.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8636.29, 4192.51), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2753
+ connRef = new ConnRef(router, 2753);
+ srcPt = ConnEnd(Point(4322, 2150.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8636.29, 4192.51), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2754
+ connRef = new ConnRef(router, 2754);
+ srcPt = ConnEnd(Point(8666.29, 4192.51), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13167, 8249.99), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2755
+ connRef = new ConnRef(router, 2755);
+ srcPt = ConnEnd(Point(10809.2, 7128.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10116, 9693.42), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2756
+ connRef = new ConnRef(router, 2756);
+ srcPt = ConnEnd(Point(10116, 9345.42), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10116, 9693.42), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2757
+ connRef = new ConnRef(router, 2757);
+ srcPt = ConnEnd(Point(10116, 9723.42), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8293.29, 6854.21), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2758
+ connRef = new ConnRef(router, 2758);
+ srcPt = ConnEnd(Point(10116, 9723.42), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10116, 10174), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2759
+ connRef = new ConnRef(router, 2759);
+ srcPt = ConnEnd(Point(10809.2, 7128.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15359.5, 1181.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2760
+ connRef = new ConnRef(router, 2760);
+ srcPt = ConnEnd(Point(17741.5, 5822.9), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15359.5, 1181.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2761
+ connRef = new ConnRef(router, 2761);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15359.5, 1181.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2762
+ connRef = new ConnRef(router, 2762);
+ srcPt = ConnEnd(Point(15389.5, 1181.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(18368.5, 5070.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2763
+ connRef = new ConnRef(router, 2763);
+ srcPt = ConnEnd(Point(15389.5, 1181.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 742.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2764
+ connRef = new ConnRef(router, 2764);
+ srcPt = ConnEnd(Point(18368.5, 5070.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13608, 6664.51), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2765
+ connRef = new ConnRef(router, 2765);
+ srcPt = ConnEnd(Point(13608, 6694.51), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7410.1, 8579.99), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2766
+ connRef = new ConnRef(router, 2766);
+ srcPt = ConnEnd(Point(13608, 6694.51), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(18725.5, 5822.9), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2767
+ connRef = new ConnRef(router, 2767);
+ srcPt = ConnEnd(Point(10809.2, 7128.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10809.2, 7311.4), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2768
+ connRef = new ConnRef(router, 2768);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10809.2, 7311.4), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2769
+ connRef = new ConnRef(router, 2769);
+ srcPt = ConnEnd(Point(10809.2, 7341.4), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10809.2, 7579.79), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2770
+ connRef = new ConnRef(router, 2770);
+ srcPt = ConnEnd(Point(10809.2, 7341.4), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2771
+ connRef = new ConnRef(router, 2771);
+ srcPt = ConnEnd(Point(10809.2, 8074.79), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10809.2, 7825.79), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2772
+ connRef = new ConnRef(router, 2772);
+ srcPt = ConnEnd(Point(10809.2, 7795.79), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10809.2, 7579.79), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2773
+ connRef = new ConnRef(router, 2773);
+ srcPt = ConnEnd(Point(10809.2, 8074.79), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9850.69, 6400.51), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2774
+ connRef = new ConnRef(router, 2774);
+ srcPt = ConnEnd(Point(8835.89, 5004.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9850.69, 6400.51), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2775
+ connRef = new ConnRef(router, 2775);
+ srcPt = ConnEnd(Point(9850.69, 6430.51), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11040.2, 8873.22), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2776
+ connRef = new ConnRef(router, 2776);
+ srcPt = ConnEnd(Point(11429.1, 8873.22), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11253.2, 8873.22), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2777
+ connRef = new ConnRef(router, 2777);
+ srcPt = ConnEnd(Point(11223.2, 8873.22), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11040.2, 8873.22), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2778
+ connRef = new ConnRef(router, 2778);
+ srcPt = ConnEnd(Point(11990.1, 8873.22), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12305.1, 8873.22), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2779
+ connRef = new ConnRef(router, 2779);
+ srcPt = ConnEnd(Point(12335.1, 8873.22), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12889.5, 8873.22), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2780
+ connRef = new ConnRef(router, 2780);
+ srcPt = ConnEnd(Point(8835.89, 2108.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9034.99, 3433.51), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2781
+ connRef = new ConnRef(router, 2781);
+ srcPt = ConnEnd(Point(8835.89, 5004.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9034.99, 3433.51), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2782
+ connRef = new ConnRef(router, 2782);
+ srcPt = ConnEnd(Point(9004.99, 3433.51), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7798.29, 3565.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2783
+ connRef = new ConnRef(router, 2783);
+ srcPt = ConnEnd(Point(7146.1, 3565.51), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7461.1, 3565.51), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2784
+ connRef = new ConnRef(router, 2784);
+ srcPt = ConnEnd(Point(7491.1, 3565.51), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7798.29, 3565.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2785
+ connRef = new ConnRef(router, 2785);
+ srcPt = ConnEnd(Point(7146.1, 3565.51), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6798.1, 3565.51), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2786
+ connRef = new ConnRef(router, 2786);
+ srcPt = ConnEnd(Point(6768.1, 3565.51), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6519.1, 3565.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2787
+ connRef = new ConnRef(router, 2787);
+ srcPt = ConnEnd(Point(6519.1, 3565.51), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6204.1, 3565.51), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2788
+ connRef = new ConnRef(router, 2788);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6204.1, 3565.51), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2789
+ connRef = new ConnRef(router, 2789);
+ srcPt = ConnEnd(Point(6174.1, 3565.51), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6024.1, 3565.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2790
+ connRef = new ConnRef(router, 2790);
+ srcPt = ConnEnd(Point(6174.1, 3565.51), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2791
+ connRef = new ConnRef(router, 2791);
+ srcPt = ConnEnd(Point(6024.1, 3565.51), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(5709.1, 3565.51), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2792
+ connRef = new ConnRef(router, 2792);
+ srcPt = ConnEnd(Point(5679.1, 3565.51), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(5312, 3565.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2793
+ connRef = new ConnRef(router, 2793);
+ srcPt = ConnEnd(Point(5312, 3565.51), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(5312, 3814.51), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2794
+ connRef = new ConnRef(router, 2794);
+ srcPt = ConnEnd(Point(5312, 3844.51), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(5312, 4126.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2795
+ connRef = new ConnRef(router, 2795);
+ srcPt = ConnEnd(Point(5312, 4938.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(5312, 4590.4), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2796
+ connRef = new ConnRef(router, 2796);
+ srcPt = ConnEnd(Point(5312, 4560.4), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(5312, 4126.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2797
+ connRef = new ConnRef(router, 2797);
+ srcPt = ConnEnd(Point(5312, 5964.59), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(5312, 5362.67), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2798
+ connRef = new ConnRef(router, 2798);
+ srcPt = ConnEnd(Point(5312, 5332.67), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(5312, 4938.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2799
+ connRef = new ConnRef(router, 2799);
+ srcPt = ConnEnd(Point(5312, 4126.51), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(5312, 5154.4), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2800
+ connRef = new ConnRef(router, 2800);
+ srcPt = ConnEnd(Point(5312, 5184.4), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(5312, 5964.59), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2801
+ connRef = new ConnRef(router, 2801);
+ srcPt = ConnEnd(Point(8835.89, 5512.67), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8407.29, 5512.67), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2802
+ connRef = new ConnRef(router, 2802);
+ srcPt = ConnEnd(Point(8377.29, 5512.67), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8095.29, 5512.67), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2803
+ connRef = new ConnRef(router, 2803);
+ srcPt = ConnEnd(Point(5312, 4938.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(5511.1, 5347.67), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2804
+ connRef = new ConnRef(router, 2804);
+ srcPt = ConnEnd(Point(5312, 5964.59), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(5511.1, 5347.67), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2805
+ connRef = new ConnRef(router, 2805);
+ srcPt = ConnEnd(Point(5481.1, 5347.67), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4982, 5347.67), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2806
+ connRef = new ConnRef(router, 2806);
+ srcPt = ConnEnd(Point(5312, 5964.59), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4964, 5964.59), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2807
+ connRef = new ConnRef(router, 2807);
+ srcPt = ConnEnd(Point(4982, 5347.67), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4964, 5964.59), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2808
+ connRef = new ConnRef(router, 2808);
+ srcPt = ConnEnd(Point(4934, 5964.59), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4553, 5964.59), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2809
+ connRef = new ConnRef(router, 2809);
+ srcPt = ConnEnd(Point(4553, 5964.59), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4949, 6041.29), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2810
+ connRef = new ConnRef(router, 2810);
+ srcPt = ConnEnd(Point(5312, 5964.59), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4949, 6041.29), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2811
+ connRef = new ConnRef(router, 2811);
+ srcPt = ConnEnd(Point(4949, 6071.29), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4949, 6613.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2812
+ connRef = new ConnRef(router, 2812);
+ srcPt = ConnEnd(Point(4949, 7579.79), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4949, 7795.79), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2813
+ connRef = new ConnRef(router, 2813);
+ srcPt = ConnEnd(Point(4949, 7825.79), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4949, 8107.79), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2814
+ connRef = new ConnRef(router, 2814);
+ srcPt = ConnEnd(Point(4949, 8107.79), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4949, 8366.99), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2815
+ connRef = new ConnRef(router, 2815);
+ srcPt = ConnEnd(Point(4949, 8396.99), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4949, 8579.99), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2816
+ connRef = new ConnRef(router, 2816);
+ srcPt = ConnEnd(Point(4949, 8579.99), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4949, 8792.22), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2817
+ connRef = new ConnRef(router, 2817);
+ srcPt = ConnEnd(Point(4949, 8822.22), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4949, 9114.42), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2818
+ connRef = new ConnRef(router, 2818);
+ srcPt = ConnEnd(Point(4949, 9114.42), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4949, 9297.42), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2819
+ connRef = new ConnRef(router, 2819);
+ srcPt = ConnEnd(Point(4949, 9327.42), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4949, 9576.42), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2820
+ connRef = new ConnRef(router, 2820);
+ srcPt = ConnEnd(Point(4289, 9576.42), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4289, 9862.02), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2821
+ connRef = new ConnRef(router, 2821);
+ srcPt = ConnEnd(Point(4289, 9892.02), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4289, 10075), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2822
+ connRef = new ConnRef(router, 2822);
+ srcPt = ConnEnd(Point(4949, 10438), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4766, 10438), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2823
+ connRef = new ConnRef(router, 2823);
+ srcPt = ConnEnd(Point(4736, 10438), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4553, 10438), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2824
+ connRef = new ConnRef(router, 2824);
+ srcPt = ConnEnd(Point(4553, 10438), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4553, 10568.3), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2825
+ connRef = new ConnRef(router, 2825);
+ srcPt = ConnEnd(Point(4553, 10598.3), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4553, 10748.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2826
+ connRef = new ConnRef(router, 2826);
+ srcPt = ConnEnd(Point(11363.1, 1280.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 1463.29), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2827
+ connRef = new ConnRef(router, 2827);
+ srcPt = ConnEnd(Point(10116, 10174), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 1463.29), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2828
+ connRef = new ConnRef(router, 2828);
+ srcPt = ConnEnd(Point(11363.1, 1493.29), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 1643.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2829
+ connRef = new ConnRef(router, 2829);
+ srcPt = ConnEnd(Point(11363.1, 1280.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 1130.29), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2830
+ connRef = new ConnRef(router, 2830);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 1130.29), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2831
+ connRef = new ConnRef(router, 2831);
+ srcPt = ConnEnd(Point(9501.59, 8249.99), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 1130.29), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2832
+ connRef = new ConnRef(router, 2832);
+ srcPt = ConnEnd(Point(11363.1, 1100.29), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 808.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2833
+ connRef = new ConnRef(router, 2833);
+ srcPt = ConnEnd(Point(11363.1, 1100.29), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2834
+ connRef = new ConnRef(router, 2834);
+ srcPt = ConnEnd(Point(11363.1, 808.091), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 625.091), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2835
+ connRef = new ConnRef(router, 2835);
+ srcPt = ConnEnd(Point(11363.1, 595.091), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 458.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2836
+ connRef = new ConnRef(router, 2836);
+ srcPt = ConnEnd(Point(11363.1, 458.265), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11513.1, 458.265), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2837
+ connRef = new ConnRef(router, 2837);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11513.1, 458.265), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2838
+ connRef = new ConnRef(router, 2838);
+ srcPt = ConnEnd(Point(11543.1, 458.265), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11726.1, 458.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2839
+ connRef = new ConnRef(router, 2839);
+ srcPt = ConnEnd(Point(11543.1, 458.265), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2840
+ connRef = new ConnRef(router, 2840);
+ srcPt = ConnEnd(Point(11543.1, 458.265), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10116, 10174), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2841
+ connRef = new ConnRef(router, 2841);
+ srcPt = ConnEnd(Point(11726.1, 458.265), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11942.1, 458.265), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2842
+ connRef = new ConnRef(router, 2842);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11942.1, 458.265), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2843
+ connRef = new ConnRef(router, 2843);
+ srcPt = ConnEnd(Point(11972.1, 458.265), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12089.1, 458.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2844
+ connRef = new ConnRef(router, 2844);
+ srcPt = ConnEnd(Point(11972.1, 458.265), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2845
+ connRef = new ConnRef(router, 2845);
+ srcPt = ConnEnd(Point(12089.1, 458.265), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14971.9, 1346.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2846
+ connRef = new ConnRef(router, 2846);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14971.9, 1346.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2847
+ connRef = new ConnRef(router, 2847);
+ srcPt = ConnEnd(Point(15001.9, 1346.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12353.1, 643.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2848
+ connRef = new ConnRef(router, 2848);
+ srcPt = ConnEnd(Point(15001.9, 1346.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2849
+ connRef = new ConnRef(router, 2849);
+ srcPt = ConnEnd(Point(12353.1, 643.091), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12709.5, 577.091), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2850
+ connRef = new ConnRef(router, 2850);
+ srcPt = ConnEnd(Point(12739.5, 577.091), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12856.5, 458.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2851
+ connRef = new ConnRef(router, 2851);
+ srcPt = ConnEnd(Point(12856.5, 458.265), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13185, 458.265), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2852
+ connRef = new ConnRef(router, 2852);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13185, 458.265), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2853
+ connRef = new ConnRef(router, 2853);
+ srcPt = ConnEnd(Point(10809.2, 7128.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13185, 458.265), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2854
+ connRef = new ConnRef(router, 2854);
+ srcPt = ConnEnd(Point(13215, 458.265), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13509, 458.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2855
+ connRef = new ConnRef(router, 2855);
+ srcPt = ConnEnd(Point(13215, 458.265), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2856
+ connRef = new ConnRef(router, 2856);
+ srcPt = ConnEnd(Point(13509, 458.265), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13857, 458.265), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2857
+ connRef = new ConnRef(router, 2857);
+ srcPt = ConnEnd(Point(13887, 458.265), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14037, 458.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2858
+ connRef = new ConnRef(router, 2858);
+ srcPt = ConnEnd(Point(13887, 458.265), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7410.1, 8579.99), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2859
+ connRef = new ConnRef(router, 2859);
+ srcPt = ConnEnd(Point(14037, 458.265), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14319, 458.265), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2860
+ connRef = new ConnRef(router, 2860);
+ srcPt = ConnEnd(Point(14349, 458.265), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14565, 458.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2861
+ connRef = new ConnRef(router, 2861);
+ srcPt = ConnEnd(Point(15239.5, 458.265), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14811, 458.265), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2862
+ connRef = new ConnRef(router, 2862);
+ srcPt = ConnEnd(Point(14781, 458.265), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14565, 458.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2863
+ connRef = new ConnRef(router, 2863);
+ srcPt = ConnEnd(Point(15239.5, 458.265), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15622.3, 458.265), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2864
+ connRef = new ConnRef(router, 2864);
+ srcPt = ConnEnd(Point(15652.3, 458.265), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15967.6, 458.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2865
+ connRef = new ConnRef(router, 2865);
+ srcPt = ConnEnd(Point(15967.6, 458.265), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16150.6, 458.265), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2866
+ connRef = new ConnRef(router, 2866);
+ srcPt = ConnEnd(Point(16180.6, 458.265), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16363.6, 458.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2867
+ connRef = new ConnRef(router, 2867);
+ srcPt = ConnEnd(Point(16363.6, 458.265), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16363.6, 793.091), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2868
+ connRef = new ConnRef(router, 2868);
+ srcPt = ConnEnd(Point(16363.6, 823.091), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16363.6, 1280.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2869
+ connRef = new ConnRef(router, 2869);
+ srcPt = ConnEnd(Point(15967.6, 458.265), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16165.6, 793.091), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2870
+ connRef = new ConnRef(router, 2870);
+ srcPt = ConnEnd(Point(16165.6, 823.091), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16363.6, 1280.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2871
+ connRef = new ConnRef(router, 2871);
+ srcPt = ConnEnd(Point(16165.6, 823.091), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 1643.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2872
+ connRef = new ConnRef(router, 2872);
+ srcPt = ConnEnd(Point(11495.1, 8074.79), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11121.2, 8074.79), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2873
+ connRef = new ConnRef(router, 2873);
+ srcPt = ConnEnd(Point(11091.2, 8074.79), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10809.2, 8074.79), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2874
+ connRef = new ConnRef(router, 2874);
+ srcPt = ConnEnd(Point(11495.1, 8074.79), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11495.1, 7759.79), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2875
+ connRef = new ConnRef(router, 2875);
+ srcPt = ConnEnd(Point(8684.29, 9976.02), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11495.1, 7759.79), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2876
+ connRef = new ConnRef(router, 2876);
+ srcPt = ConnEnd(Point(11495.1, 7729.79), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11495.1, 7425.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2877
+ connRef = new ConnRef(router, 2877);
+ srcPt = ConnEnd(Point(11495.1, 7425.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12008.1, 7425.4), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2878
+ connRef = new ConnRef(router, 2878);
+ srcPt = ConnEnd(Point(12038.1, 7425.4), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12856.5, 7425.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2879
+ connRef = new ConnRef(router, 2879);
+ srcPt = ConnEnd(Point(12038.1, 7425.4), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7831.29, 9477.42), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2880
+ connRef = new ConnRef(router, 2880);
+ srcPt = ConnEnd(Point(17052.8, 7062.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17052.8, 7179.4), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2881
+ connRef = new ConnRef(router, 2881);
+ srcPt = ConnEnd(Point(15407.5, 7425.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17052.8, 7179.4), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2882
+ connRef = new ConnRef(router, 2882);
+ srcPt = ConnEnd(Point(17052.8, 7209.4), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17052.8, 7425.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2883
+ connRef = new ConnRef(router, 2883);
+ srcPt = ConnEnd(Point(7765.29, 610.091), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(18501, 11860.9), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2884
+ connRef = new ConnRef(router, 2884);
+ srcPt = ConnEnd(Point(18401.5, 11860.9), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(18501, 11860.9), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2885
+ connRef = new ConnRef(router, 2885);
+ srcPt = ConnEnd(Point(18531, 11860.9), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(18630.5, 11860.9), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2886
+ connRef = new ConnRef(router, 2886);
+ srcPt = ConnEnd(Point(12889.5, 8873.22), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13251, 8873.22), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2887
+ connRef = new ConnRef(router, 2887);
+ srcPt = ConnEnd(Point(13281, 8873.22), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13872, 8873.22), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2888
+ connRef = new ConnRef(router, 2888);
+ srcPt = ConnEnd(Point(10456.9, 458.265), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10761.2, 458.265), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2889
+ connRef = new ConnRef(router, 2889);
+ srcPt = ConnEnd(Point(10791.2, 458.265), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10974.2, 458.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2890
+ connRef = new ConnRef(router, 2890);
+ srcPt = ConnEnd(Point(9171.59, 458.265), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15619.3, 1346.29), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2891
+ connRef = new ConnRef(router, 2891);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15619.3, 1346.29), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2892
+ connRef = new ConnRef(router, 2892);
+ srcPt = ConnEnd(Point(15589.3, 1346.29), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8458.29, 313.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2893
+ connRef = new ConnRef(router, 2893);
+ srcPt = ConnEnd(Point(15589.3, 1346.29), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2894
+ connRef = new ConnRef(router, 2894);
+ srcPt = ConnEnd(Point(8194.29, 313.265), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8044.29, 313.265), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2895
+ connRef = new ConnRef(router, 2895);
+ srcPt = ConnEnd(Point(8014.29, 313.265), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7864.29, 313.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2896
+ connRef = new ConnRef(router, 2896);
+ srcPt = ConnEnd(Point(8458.29, 425.265), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8308.29, 425.265), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2897
+ connRef = new ConnRef(router, 2897);
+ srcPt = ConnEnd(Point(8278.29, 425.265), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8062.29, 425.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2898
+ connRef = new ConnRef(router, 2898);
+ srcPt = ConnEnd(Point(8062.29, 425.265), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7780.29, 425.265), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2899
+ connRef = new ConnRef(router, 2899);
+ srcPt = ConnEnd(Point(7750.29, 425.265), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7344.1, 425.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2900
+ connRef = new ConnRef(router, 2900);
+ srcPt = ConnEnd(Point(7344.1, 425.265), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6963.1, 425.265), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2901
+ connRef = new ConnRef(router, 2901);
+ srcPt = ConnEnd(Point(6933.1, 425.265), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6618.1, 425.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2902
+ connRef = new ConnRef(router, 2902);
+ srcPt = ConnEnd(Point(6123.1, 425.265), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6306.1, 425.265), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2903
+ connRef = new ConnRef(router, 2903);
+ srcPt = ConnEnd(Point(6336.1, 425.265), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6618.1, 425.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2904
+ connRef = new ConnRef(router, 2904);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15100.3, 1181.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2905
+ connRef = new ConnRef(router, 2905);
+ srcPt = ConnEnd(Point(10809.2, 7128.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15100.3, 1181.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2906
+ connRef = new ConnRef(router, 2906);
+ srcPt = ConnEnd(Point(15130.3, 1181.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 742.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2907
+ connRef = new ConnRef(router, 2907);
+ srcPt = ConnEnd(Point(15130.3, 1181.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10809.2, 4542.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2908
+ connRef = new ConnRef(router, 2908);
+ srcPt = ConnEnd(Point(8835.89, 5512.67), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14873.4, 1346.29), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2909
+ connRef = new ConnRef(router, 2909);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14873.4, 1346.29), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2910
+ connRef = new ConnRef(router, 2910);
+ srcPt = ConnEnd(Point(14843.4, 1346.29), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4322, 2150.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2911
+ connRef = new ConnRef(router, 2911);
+ srcPt = ConnEnd(Point(14843.4, 1346.29), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2912
+ connRef = new ConnRef(router, 2912);
+ srcPt = ConnEnd(Point(15239.5, 742.091), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15492.3, 1181.29), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2913
+ connRef = new ConnRef(router, 2913);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15492.3, 1181.29), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2914
+ connRef = new ConnRef(router, 2914);
+ srcPt = ConnEnd(Point(15462.3, 1181.29), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2915
+ connRef = new ConnRef(router, 2915);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15717.9, 1346.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2916
+ connRef = new ConnRef(router, 2916);
+ srcPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15717.9, 1346.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2917
+ connRef = new ConnRef(router, 2917);
+ srcPt = ConnEnd(Point(15747.9, 1346.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2918
+ connRef = new ConnRef(router, 2918);
+ srcPt = ConnEnd(Point(15747.9, 1346.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2919
+ connRef = new ConnRef(router, 2919);
+ srcPt = ConnEnd(Point(11396.1, 4361.11), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11253.2, 4361.11), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2920
+ connRef = new ConnRef(router, 2920);
+ srcPt = ConnEnd(Point(11223.2, 4361.11), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11073.2, 4361.11), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2921
+ connRef = new ConnRef(router, 2921);
+ srcPt = ConnEnd(Point(13200, 6788.21), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14583, 6788.21), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2922
+ connRef = new ConnRef(router, 2922);
+ srcPt = ConnEnd(Point(14613, 6788.21), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16231.6, 6788.21), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2923
+ connRef = new ConnRef(router, 2923);
+ srcPt = ConnEnd(Point(5312, 4938.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(5661.1, 4590.4), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2924
+ connRef = new ConnRef(router, 2924);
+ srcPt = ConnEnd(Point(5661.1, 4560.4), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(5793.1, 4126.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2925
+ connRef = new ConnRef(router, 2925);
+ srcPt = ConnEnd(Point(18137.5, 10174), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(18236.5, 8561.99), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2926
+ connRef = new ConnRef(router, 2926);
+ srcPt = ConnEnd(Point(18236.5, 8531.99), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(18302.5, 6788.21), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2927
+ connRef = new ConnRef(router, 2927);
+ srcPt = ConnEnd(Point(18236.5, 8531.99), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9784.69, 5512.67), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2928
+ connRef = new ConnRef(router, 2928);
+ srcPt = ConnEnd(Point(18137.5, 10174), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17624.5, 10174), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2929
+ connRef = new ConnRef(router, 2929);
+ srcPt = ConnEnd(Point(10116, 9345.42), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17624.5, 10174), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2930
+ connRef = new ConnRef(router, 2930);
+ srcPt = ConnEnd(Point(17594.5, 10174), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16920.8, 10174), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2931
+ connRef = new ConnRef(router, 2931);
+ srcPt = ConnEnd(Point(17594.5, 10174), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10116, 10174), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2932
+ connRef = new ConnRef(router, 2932);
+ srcPt = ConnEnd(Point(16920.8, 10174), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16572.8, 10174), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2933
+ connRef = new ConnRef(router, 2933);
+ srcPt = ConnEnd(Point(16542.8, 10174), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15868.6, 10174), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2934
+ connRef = new ConnRef(router, 2934);
+ srcPt = ConnEnd(Point(12122.1, 10174), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13923, 10174), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2935
+ connRef = new ConnRef(router, 2935);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13923, 10174), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2936
+ connRef = new ConnRef(router, 2936);
+ srcPt = ConnEnd(Point(13953, 10174), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15868.6, 10174), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2937
+ connRef = new ConnRef(router, 2937);
+ srcPt = ConnEnd(Point(13953, 10174), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2938
+ connRef = new ConnRef(router, 2938);
+ srcPt = ConnEnd(Point(10116, 10174), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10324.9, 9723.42), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2939
+ connRef = new ConnRef(router, 2939);
+ srcPt = ConnEnd(Point(10324.9, 9693.42), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10116, 9345.42), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2940
+ connRef = new ConnRef(router, 2940);
+ srcPt = ConnEnd(Point(10116, 10174), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10116, 10357), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2941
+ connRef = new ConnRef(router, 2941);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10116, 10357), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2942
+ connRef = new ConnRef(router, 2942);
+ srcPt = ConnEnd(Point(10116, 10387), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10116, 10682.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2943
+ connRef = new ConnRef(router, 2943);
+ srcPt = ConnEnd(Point(10116, 10387), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 742.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2944
+ connRef = new ConnRef(router, 2944);
+ srcPt = ConnEnd(Point(10116, 10682.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10497.2, 10682.3), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2945
+ connRef = new ConnRef(router, 2945);
+ srcPt = ConnEnd(Point(10527.2, 10682.3), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10710.2, 10682.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2946
+ connRef = new ConnRef(router, 2946);
+ srcPt = ConnEnd(Point(11007.2, 10682.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10923.2, 10682.3), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2947
+ connRef = new ConnRef(router, 2947);
+ srcPt = ConnEnd(Point(10893.2, 10682.3), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10710.2, 10682.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2948
+ connRef = new ConnRef(router, 2948);
+ srcPt = ConnEnd(Point(11007.2, 10682.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10842.2, 10965.6), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2949
+ connRef = new ConnRef(router, 2949);
+ srcPt = ConnEnd(Point(10842.2, 10995.6), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10578.2, 11211.6), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2950
+ connRef = new ConnRef(router, 2950);
+ srcPt = ConnEnd(Point(9949.69, 11211.6), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9733.69, 11211.6), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2951
+ connRef = new ConnRef(router, 2951);
+ srcPt = ConnEnd(Point(9703.69, 11211.6), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9402.59, 11211.6), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2952
+ connRef = new ConnRef(router, 2952);
+ srcPt = ConnEnd(Point(9402.59, 11211.6), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9252.59, 11211.6), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2953
+ connRef = new ConnRef(router, 2953);
+ srcPt = ConnEnd(Point(9222.59, 11211.6), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9019.99, 11211.6), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2954
+ connRef = new ConnRef(router, 2954);
+ srcPt = ConnEnd(Point(9019.99, 11211.6), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8699.29, 11211.6), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2955
+ connRef = new ConnRef(router, 2955);
+ srcPt = ConnEnd(Point(8669.29, 11211.6), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8392.29, 11211.6), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2956
+ connRef = new ConnRef(router, 2956);
+ srcPt = ConnEnd(Point(7963.29, 11211.6), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7963.29, 11028.6), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2957
+ connRef = new ConnRef(router, 2957);
+ srcPt = ConnEnd(Point(7963.29, 10998.6), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7963.29, 10715.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2958
+ connRef = new ConnRef(router, 2958);
+ srcPt = ConnEnd(Point(7963.29, 10715.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8212.29, 10715.3), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2959
+ connRef = new ConnRef(router, 2959);
+ srcPt = ConnEnd(Point(4553, 5964.59), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8212.29, 10715.3), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2960
+ connRef = new ConnRef(router, 2960);
+ srcPt = ConnEnd(Point(8242.29, 10715.3), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8392.29, 10715.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2961
+ connRef = new ConnRef(router, 2961);
+ srcPt = ConnEnd(Point(8392.29, 10715.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8669.29, 10715.3), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2962
+ connRef = new ConnRef(router, 2962);
+ srcPt = ConnEnd(Point(8699.29, 10715.3), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9019.99, 10715.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2963
+ connRef = new ConnRef(router, 2963);
+ srcPt = ConnEnd(Point(9402.59, 11211.6), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13314, 9246.42), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2964
+ connRef = new ConnRef(router, 2964);
+ srcPt = ConnEnd(Point(17052.8, 7062.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13314, 9246.42), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2965
+ connRef = new ConnRef(router, 2965);
+ srcPt = ConnEnd(Point(13284, 9246.42), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8769.89, 12015.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2966
+ connRef = new ConnRef(router, 2966);
+ srcPt = ConnEnd(Point(6552.1, 7293.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6636.1, 6996.4), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2967
+ connRef = new ConnRef(router, 2967);
+ srcPt = ConnEnd(Point(6750.1, 6514.51), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6636.1, 6996.4), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2968
+ connRef = new ConnRef(router, 2968);
+ srcPt = ConnEnd(Point(6666.1, 6996.4), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7212.1, 7029.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2969
+ connRef = new ConnRef(router, 2969);
+ srcPt = ConnEnd(Point(7212.1, 7029.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7212.1, 7278.4), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2970
+ connRef = new ConnRef(router, 2970);
+ srcPt = ConnEnd(Point(7212.1, 7308.4), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7212.1, 7645.79), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2971
+ connRef = new ConnRef(router, 2971);
+ srcPt = ConnEnd(Point(7212.1, 9048.42), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7212.1, 9198.42), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2972
+ connRef = new ConnRef(router, 2972);
+ srcPt = ConnEnd(Point(17052.8, 7062.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7212.1, 9198.42), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2973
+ connRef = new ConnRef(router, 2973);
+ srcPt = ConnEnd(Point(7212.1, 9228.42), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7212.1, 9411.42), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2974
+ connRef = new ConnRef(router, 2974);
+ srcPt = ConnEnd(Point(6552.1, 8315.99), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6552.1, 8056.79), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2975
+ connRef = new ConnRef(router, 2975);
+ srcPt = ConnEnd(Point(6552.1, 8026.79), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6552.1, 7810.79), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2976
+ connRef = new ConnRef(router, 2976);
+ srcPt = ConnEnd(Point(6552.1, 9543.42), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6552.1, 9862.02), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2977
+ connRef = new ConnRef(router, 2977);
+ srcPt = ConnEnd(Point(17052.8, 7062.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6552.1, 9862.02), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2978
+ connRef = new ConnRef(router, 2978);
+ srcPt = ConnEnd(Point(6552.1, 9892.02), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6552.1, 10108), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2979
+ connRef = new ConnRef(router, 2979);
+ srcPt = ConnEnd(Point(6552.1, 7293.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6552.1, 7564.79), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2980
+ connRef = new ConnRef(router, 2980);
+ srcPt = ConnEnd(Point(6783.1, 7546.79), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6552.1, 7564.79), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2981
+ connRef = new ConnRef(router, 2981);
+ srcPt = ConnEnd(Point(6552.1, 7594.79), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6552.1, 7810.79), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2982
+ connRef = new ConnRef(router, 2982);
+ srcPt = ConnEnd(Point(6750.1, 6514.51), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7230.1, 6514.51), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2983
+ connRef = new ConnRef(router, 2983);
+ srcPt = ConnEnd(Point(7146.1, 6250.51), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7230.1, 6514.51), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2984
+ connRef = new ConnRef(router, 2984);
+ srcPt = ConnEnd(Point(7260.1, 6514.51), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7765.29, 6514.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2985
+ connRef = new ConnRef(router, 2985);
+ srcPt = ConnEnd(Point(7765.29, 6514.51), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8146.29, 6514.51), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2986
+ connRef = new ConnRef(router, 2986);
+ srcPt = ConnEnd(Point(17052.8, 7062.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8146.29, 6514.51), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2987
+ connRef = new ConnRef(router, 2987);
+ srcPt = ConnEnd(Point(8176.29, 6514.51), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8618.29, 6514.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2988
+ connRef = new ConnRef(router, 2988);
+ srcPt = ConnEnd(Point(5760.1, 7326.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6402.1, 6788.21), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2989
+ connRef = new ConnRef(router, 2989);
+ srcPt = ConnEnd(Point(7146.1, 6250.51), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6402.1, 6788.21), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2990
+ connRef = new ConnRef(router, 2990);
+ srcPt = ConnEnd(Point(6372.1, 6788.21), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6123.1, 7744.79), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2991
+ connRef = new ConnRef(router, 2991);
+ srcPt = ConnEnd(Point(6123.1, 7744.79), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6123.1, 7960.79), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2992
+ connRef = new ConnRef(router, 2992);
+ srcPt = ConnEnd(Point(17052.8, 7062.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6123.1, 7960.79), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2993
+ connRef = new ConnRef(router, 2993);
+ srcPt = ConnEnd(Point(6123.1, 7990.79), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6123.1, 8282.99), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2994
+ connRef = new ConnRef(router, 2994);
+ srcPt = ConnEnd(Point(10875.2, 11632.9), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9931.69, 11632.9), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2995
+ connRef = new ConnRef(router, 2995);
+ srcPt = ConnEnd(Point(9901.69, 11632.9), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9085.99, 11632.9), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2996
+ connRef = new ConnRef(router, 2996);
+ srcPt = ConnEnd(Point(9901.69, 11632.9), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 5004.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2997
+ connRef = new ConnRef(router, 2997);
+ srcPt = ConnEnd(Point(10875.2, 11632.9), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11414.1, 11632.9), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2998
+ connRef = new ConnRef(router, 2998);
+ srcPt = ConnEnd(Point(11444.1, 11632.9), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11990.1, 11632.9), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef2999
+ connRef = new ConnRef(router, 2999);
+ srcPt = ConnEnd(Point(13575, 11632.9), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12772.5, 11632.9), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3000
+ connRef = new ConnRef(router, 3000);
+ srcPt = ConnEnd(Point(12742.5, 11632.9), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11990.1, 11632.9), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3001
+ connRef = new ConnRef(router, 3001);
+ srcPt = ConnEnd(Point(13575, 11632.9), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14517, 11632.9), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3002
+ connRef = new ConnRef(router, 3002);
+ srcPt = ConnEnd(Point(14547, 11632.9), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15868.6, 11632.9), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3003
+ connRef = new ConnRef(router, 3003);
+ srcPt = ConnEnd(Point(16198.6, 11632.9), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16081.6, 11632.9), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3004
+ connRef = new ConnRef(router, 3004);
+ srcPt = ConnEnd(Point(10116, 9345.42), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16081.6, 11632.9), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3005
+ connRef = new ConnRef(router, 3005);
+ srcPt = ConnEnd(Point(16051.6, 11632.9), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15868.6, 11632.9), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3006
+ connRef = new ConnRef(router, 3006);
+ srcPt = ConnEnd(Point(16051.6, 11632.9), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10116, 10174), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3007
+ connRef = new ConnRef(router, 3007);
+ srcPt = ConnEnd(Point(15868.6, 12081.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15868.6, 11908.9), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3008
+ connRef = new ConnRef(router, 3008);
+ srcPt = ConnEnd(Point(15868.6, 11878.9), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15868.6, 11632.9), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3009
+ connRef = new ConnRef(router, 3009);
+ srcPt = ConnEnd(Point(15868.6, 11878.9), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 5512.67), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3010
+ connRef = new ConnRef(router, 3010);
+ srcPt = ConnEnd(Point(15868.6, 12081.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15868.6, 12178.3), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3011
+ connRef = new ConnRef(router, 3011);
+ srcPt = ConnEnd(Point(15868.6, 12208.3), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15868.6, 12292.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3012
+ connRef = new ConnRef(router, 3012);
+ srcPt = ConnEnd(Point(15272.5, 12292.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15589.3, 12292.3), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3013
+ connRef = new ConnRef(router, 3013);
+ srcPt = ConnEnd(Point(15619.3, 12292.3), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15868.6, 12292.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3014
+ connRef = new ConnRef(router, 3014);
+ srcPt = ConnEnd(Point(15272.5, 12292.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15001.9, 12292.3), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3015
+ connRef = new ConnRef(router, 3015);
+ srcPt = ConnEnd(Point(14971.9, 12292.3), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14697, 12292.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3016
+ connRef = new ConnRef(router, 3016);
+ srcPt = ConnEnd(Point(14004, 12292.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14187, 12292.3), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3017
+ connRef = new ConnRef(router, 3017);
+ srcPt = ConnEnd(Point(14217, 12292.3), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14400, 12292.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3018
+ connRef = new ConnRef(router, 3018);
+ srcPt = ConnEnd(Point(9501.59, 6481.51), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9270.59, 5672.9), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3019
+ connRef = new ConnRef(router, 3019);
+ srcPt = ConnEnd(Point(9270.59, 5642.9), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 5004.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3020
+ connRef = new ConnRef(router, 3020);
+ srcPt = ConnEnd(Point(9501.59, 6481.51), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9501.59, 7344.4), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3021
+ connRef = new ConnRef(router, 3021);
+ srcPt = ConnEnd(Point(9501.59, 7374.4), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9501.59, 8249.99), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3022
+ connRef = new ConnRef(router, 3022);
+ srcPt = ConnEnd(Point(9501.59, 9976.02), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9501.59, 10357), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3023
+ connRef = new ConnRef(router, 3023);
+ srcPt = ConnEnd(Point(9501.59, 10387), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9501.59, 10781.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3024
+ connRef = new ConnRef(router, 3024);
+ srcPt = ConnEnd(Point(9501.59, 10781.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10342.9, 10781.3), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3025
+ connRef = new ConnRef(router, 3025);
+ srcPt = ConnEnd(Point(9085.99, 11632.9), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10342.9, 10781.3), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3026
+ connRef = new ConnRef(router, 3026);
+ srcPt = ConnEnd(Point(10372.9, 10781.3), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10875.2, 10781.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3027
+ connRef = new ConnRef(router, 3027);
+ srcPt = ConnEnd(Point(10875.2, 10781.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11645.1, 10781.3), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3028
+ connRef = new ConnRef(router, 3028);
+ srcPt = ConnEnd(Point(11675.1, 10781.3), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12531.5, 10781.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3029
+ connRef = new ConnRef(router, 3029);
+ srcPt = ConnEnd(Point(13575, 10781.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13116, 10781.3), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3030
+ connRef = new ConnRef(router, 3030);
+ srcPt = ConnEnd(Point(13086, 10781.3), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12531.5, 10781.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3031
+ connRef = new ConnRef(router, 3031);
+ srcPt = ConnEnd(Point(13575, 10781.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14286, 10781.3), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3032
+ connRef = new ConnRef(router, 3032);
+ srcPt = ConnEnd(Point(14316, 10781.3), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15019.9, 10781.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3033
+ connRef = new ConnRef(router, 3033);
+ srcPt = ConnEnd(Point(16198.6, 10781.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15780.9, 10781.3), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3034
+ connRef = new ConnRef(router, 3034);
+ srcPt = ConnEnd(Point(15750.9, 10781.3), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15019.9, 10781.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3035
+ connRef = new ConnRef(router, 3035);
+ srcPt = ConnEnd(Point(6189.1, 214.265), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6105.1, 214.265), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3036
+ connRef = new ConnRef(router, 3036);
+ srcPt = ConnEnd(Point(10974.2, 1643.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6105.1, 214.265), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3037
+ connRef = new ConnRef(router, 3037);
+ srcPt = ConnEnd(Point(6075.1, 214.265), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(5925.1, 214.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3038
+ connRef = new ConnRef(router, 3038);
+ srcPt = ConnEnd(Point(6075.1, 214.265), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9652.69, 1943.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3039
+ connRef = new ConnRef(router, 3039);
+ srcPt = ConnEnd(Point(7765.29, 610.091), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7765.29, 836.285), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3040
+ connRef = new ConnRef(router, 3040);
+ srcPt = ConnEnd(Point(7765.29, 866.285), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7765.29, 1148.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3041
+ connRef = new ConnRef(router, 3041);
+ srcPt = ConnEnd(Point(10423.9, 6250.51), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10423.9, 6400.51), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3042
+ connRef = new ConnRef(router, 3042);
+ srcPt = ConnEnd(Point(10423.9, 6430.51), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10423.9, 6547.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3043
+ connRef = new ConnRef(router, 3043);
+ srcPt = ConnEnd(Point(10423.9, 6430.51), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 5004.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3044
+ connRef = new ConnRef(router, 3044);
+ srcPt = ConnEnd(Point(15019.9, 10781.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15148.3, 10929.6), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3045
+ connRef = new ConnRef(router, 3045);
+ srcPt = ConnEnd(Point(7897.29, 983.285), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7897.29, 4428.4), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3046
+ connRef = new ConnRef(router, 3046);
+ srcPt = ConnEnd(Point(8835.89, 5512.67), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7897.29, 4428.4), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3047
+ connRef = new ConnRef(router, 3047);
+ srcPt = ConnEnd(Point(7897.29, 4458.4), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7897.29, 8939.22), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3048
+ connRef = new ConnRef(router, 3048);
+ srcPt = ConnEnd(Point(17052.8, 7062.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17228.5, 7194.4), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3049
+ connRef = new ConnRef(router, 3049);
+ srcPt = ConnEnd(Point(17198.5, 7194.4), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17052.8, 7425.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3050
+ connRef = new ConnRef(router, 3050);
+ srcPt = ConnEnd(Point(17198.5, 7194.4), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3051
+ connRef = new ConnRef(router, 3051);
+ srcPt = ConnEnd(Point(4553, 5964.59), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4934, 5822.9), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3052
+ connRef = new ConnRef(router, 3052);
+ srcPt = ConnEnd(Point(5312, 5964.59), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4934, 5822.9), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3053
+ connRef = new ConnRef(router, 3053);
+ srcPt = ConnEnd(Point(4964, 5822.9), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(5991.1, 6382.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3054
+ connRef = new ConnRef(router, 3054);
+ srcPt = ConnEnd(Point(11363.1, 2843.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 2264.29), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3055
+ connRef = new ConnRef(router, 3055);
+ srcPt = ConnEnd(Point(11363.1, 2234.29), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 1643.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3056
+ connRef = new ConnRef(router, 3056);
+ srcPt = ConnEnd(Point(11363.1, 2234.29), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3057
+ connRef = new ConnRef(router, 3057);
+ srcPt = ConnEnd(Point(11363.1, 2843.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 3323.29), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3058
+ connRef = new ConnRef(router, 3058);
+ srcPt = ConnEnd(Point(11363.1, 3353.29), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 3697.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3059
+ connRef = new ConnRef(router, 3059);
+ srcPt = ConnEnd(Point(11363.1, 3697.51), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 4461.4), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3060
+ connRef = new ConnRef(router, 3060);
+ srcPt = ConnEnd(Point(11363.1, 4491.4), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 5169.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3061
+ connRef = new ConnRef(router, 3061);
+ srcPt = ConnEnd(Point(11363.1, 5169.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 5365.67), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3062
+ connRef = new ConnRef(router, 3062);
+ srcPt = ConnEnd(Point(11363.1, 5395.67), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 5756.9), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3063
+ connRef = new ConnRef(router, 3063);
+ srcPt = ConnEnd(Point(11363.1, 5756.9), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 6565.51), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3064
+ connRef = new ConnRef(router, 3064);
+ srcPt = ConnEnd(Point(11363.1, 6595.51), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 7579.79), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3065
+ connRef = new ConnRef(router, 3065);
+ srcPt = ConnEnd(Point(11363.1, 6595.51), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14037, 458.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3066
+ connRef = new ConnRef(router, 3066);
+ srcPt = ConnEnd(Point(11363.1, 6595.51), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10116, 10174), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3067
+ connRef = new ConnRef(router, 3067);
+ srcPt = ConnEnd(Point(11363.1, 7579.79), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 8399.99), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3068
+ connRef = new ConnRef(router, 3068);
+ srcPt = ConnEnd(Point(11363.1, 8429.99), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 9213.42), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3069
+ connRef = new ConnRef(router, 3069);
+ srcPt = ConnEnd(Point(11363.1, 10537), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 9991.02), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3070
+ connRef = new ConnRef(router, 3070);
+ srcPt = ConnEnd(Point(10116, 9345.42), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 9991.02), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3071
+ connRef = new ConnRef(router, 3071);
+ srcPt = ConnEnd(Point(11363.1, 9961.02), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 9213.42), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3072
+ connRef = new ConnRef(router, 3072);
+ srcPt = ConnEnd(Point(11363.1, 9961.02), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10116, 10174), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3073
+ connRef = new ConnRef(router, 3073);
+ srcPt = ConnEnd(Point(11363.1, 10537), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 11163.6), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3074
+ connRef = new ConnRef(router, 3074);
+ srcPt = ConnEnd(Point(11363.1, 11193.6), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11363.1, 12127.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3075
+ connRef = new ConnRef(router, 3075);
+ srcPt = ConnEnd(Point(11363.1, 12127.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11909.1, 12127.3), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3076
+ connRef = new ConnRef(router, 3076);
+ srcPt = ConnEnd(Point(11939.1, 12127.3), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12531.5, 12127.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3077
+ connRef = new ConnRef(router, 3077);
+ srcPt = ConnEnd(Point(12531.5, 12127.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12907.5, 12127.3), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3078
+ connRef = new ConnRef(router, 3078);
+ srcPt = ConnEnd(Point(12937.5, 12127.3), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13233, 12127.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3079
+ connRef = new ConnRef(router, 3079);
+ srcPt = ConnEnd(Point(8161.29, 1280.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8344.29, 1280.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3080
+ connRef = new ConnRef(router, 3080);
+ srcPt = ConnEnd(Point(8374.29, 1280.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8458.29, 1280.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3081
+ connRef = new ConnRef(router, 3081);
+ srcPt = ConnEnd(Point(8161.29, 1280.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7912.29, 1280.29), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3082
+ connRef = new ConnRef(router, 3082);
+ srcPt = ConnEnd(Point(7882.29, 1280.29), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7608.1, 1280.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3083
+ connRef = new ConnRef(router, 3083);
+ srcPt = ConnEnd(Point(7608.1, 1280.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7608.1, 1397.29), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3084
+ connRef = new ConnRef(router, 3084);
+ srcPt = ConnEnd(Point(7608.1, 1427.29), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7608.1, 1610.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3085
+ connRef = new ConnRef(router, 3085);
+ srcPt = ConnEnd(Point(7608.1, 2777.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7608.1, 2993.29), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3086
+ connRef = new ConnRef(router, 3086);
+ srcPt = ConnEnd(Point(7608.1, 3023.29), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7608.1, 3206.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3087
+ connRef = new ConnRef(router, 3087);
+ srcPt = ConnEnd(Point(10809.2, 7128.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9949.69, 9961.02), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3088
+ connRef = new ConnRef(router, 3088);
+ srcPt = ConnEnd(Point(9949.69, 9991.02), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9237.59, 12458.7), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3089
+ connRef = new ConnRef(router, 3089);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14971.9, 1181.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3090
+ connRef = new ConnRef(router, 3090);
+ srcPt = ConnEnd(Point(16557.8, 11982.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14971.9, 1181.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3091
+ connRef = new ConnRef(router, 3091);
+ srcPt = ConnEnd(Point(9237.59, 12458.7), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14971.9, 1181.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3092
+ connRef = new ConnRef(router, 3092);
+ srcPt = ConnEnd(Point(15001.9, 1181.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 742.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3093
+ connRef = new ConnRef(router, 3093);
+ srcPt = ConnEnd(Point(15001.9, 1181.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16788.8, 12458.7), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3094
+ connRef = new ConnRef(router, 3094);
+ srcPt = ConnEnd(Point(15868.6, 11632.9), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16051.6, 11794.9), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3095
+ connRef = new ConnRef(router, 3095);
+ srcPt = ConnEnd(Point(16081.6, 11794.9), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16198.6, 11982.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3096
+ connRef = new ConnRef(router, 3096);
+ srcPt = ConnEnd(Point(1385, 4773.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1568, 4773.4), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3097
+ connRef = new ConnRef(router, 3097);
+ srcPt = ConnEnd(Point(1598, 4773.4), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(1715, 4773.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3098
+ connRef = new ConnRef(router, 3098);
+ srcPt = ConnEnd(Point(1598, 4773.4), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 5512.67), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3099
+ connRef = new ConnRef(router, 3099);
+ srcPt = ConnEnd(Point(2837, 4773.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(3020, 4773.4), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3100
+ connRef = new ConnRef(router, 3100);
+ srcPt = ConnEnd(Point(3050, 4773.4), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(3233, 4773.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3101
+ connRef = new ConnRef(router, 3101);
+ srcPt = ConnEnd(Point(3050, 4773.4), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 5512.67), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3102
+ connRef = new ConnRef(router, 3102);
+ srcPt = ConnEnd(Point(4553, 5964.59), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4949, 6136.51), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3103
+ connRef = new ConnRef(router, 3103);
+ srcPt = ConnEnd(Point(5312, 5964.59), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(4949, 6136.51), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3104
+ connRef = new ConnRef(router, 3104);
+ srcPt = ConnEnd(Point(4949, 6166.51), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(6750.1, 6514.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3105
+ connRef = new ConnRef(router, 3105);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14745, 1346.29), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3106
+ connRef = new ConnRef(router, 3106);
+ srcPt = ConnEnd(Point(9435.59, 6963.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14745, 1346.29), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3107
+ connRef = new ConnRef(router, 3107);
+ srcPt = ConnEnd(Point(14715, 1346.29), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3108
+ connRef = new ConnRef(router, 3108);
+ srcPt = ConnEnd(Point(14715, 1346.29), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 5512.67), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3109
+ connRef = new ConnRef(router, 3109);
+ srcPt = ConnEnd(Point(14715, 1346.29), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8293.29, 6854.21), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3110
+ connRef = new ConnRef(router, 3110);
+ srcPt = ConnEnd(Point(9435.59, 6963.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9667.69, 6184.51), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3111
+ connRef = new ConnRef(router, 3111);
+ srcPt = ConnEnd(Point(9637.69, 6184.51), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9784.69, 5512.67), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3112
+ connRef = new ConnRef(router, 3112);
+ srcPt = ConnEnd(Point(9637.69, 6184.51), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8293.29, 6854.21), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3113
+ connRef = new ConnRef(router, 3113);
+ srcPt = ConnEnd(Point(6552.1, 10715.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7098.1, 10240), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3114
+ connRef = new ConnRef(router, 3114);
+ srcPt = ConnEnd(Point(7831.29, 9477.42), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7098.1, 10240), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3115
+ connRef = new ConnRef(router, 3115);
+ srcPt = ConnEnd(Point(7128.1, 10240), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7410.1, 8579.99), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3116
+ connRef = new ConnRef(router, 3116);
+ srcPt = ConnEnd(Point(7831.29, 9477.42), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8212.29, 9675.42), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3117
+ connRef = new ConnRef(router, 3117);
+ srcPt = ConnEnd(Point(8242.29, 9675.42), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8684.29, 9976.02), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3118
+ connRef = new ConnRef(router, 3118);
+ srcPt = ConnEnd(Point(7831.29, 9477.42), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8311.29, 9844.02), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3119
+ connRef = new ConnRef(router, 3119);
+ srcPt = ConnEnd(Point(8341.29, 9844.02), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8684.29, 9976.02), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3120
+ connRef = new ConnRef(router, 3120);
+ srcPt = ConnEnd(Point(10116, 9345.42), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10324.9, 9459.42), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3121
+ connRef = new ConnRef(router, 3121);
+ srcPt = ConnEnd(Point(8684.29, 9976.02), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8802.89, 10090), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3122
+ connRef = new ConnRef(router, 3122);
+ srcPt = ConnEnd(Point(9085.99, 11632.9), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9204.59, 11713.9), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3123
+ connRef = new ConnRef(router, 3123);
+ srcPt = ConnEnd(Point(8835.89, 5512.67), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9019.99, 5672.9), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3124
+ connRef = new ConnRef(router, 3124);
+ srcPt = ConnEnd(Point(8835.89, 2108.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9019.99, 2366.29), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3125
+ connRef = new ConnRef(router, 3125);
+ srcPt = ConnEnd(Point(9019.99, 2396.29), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 2579.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3126
+ connRef = new ConnRef(router, 3126);
+ srcPt = ConnEnd(Point(8458.29, 1676.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8458.29, 1493.29), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3127
+ connRef = new ConnRef(router, 3127);
+ srcPt = ConnEnd(Point(8458.29, 1463.29), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8458.29, 1280.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3128
+ connRef = new ConnRef(router, 3128);
+ srcPt = ConnEnd(Point(8458.29, 1280.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8603.29, 1478.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3129
+ connRef = new ConnRef(router, 3129);
+ srcPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8603.29, 1478.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3130
+ connRef = new ConnRef(router, 3130);
+ srcPt = ConnEnd(Point(8633.29, 1478.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8458.29, 1676.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3131
+ connRef = new ConnRef(router, 3131);
+ srcPt = ConnEnd(Point(8633.29, 1478.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 742.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3132
+ connRef = new ConnRef(router, 3132);
+ srcPt = ConnEnd(Point(7996.29, 808.091), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8245.29, 808.091), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3133
+ connRef = new ConnRef(router, 3133);
+ srcPt = ConnEnd(Point(8275.29, 808.091), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8458.29, 808.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3134
+ connRef = new ConnRef(router, 3134);
+ srcPt = ConnEnd(Point(7996.29, 808.091), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8260.29, 932.285), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3135
+ connRef = new ConnRef(router, 3135);
+ srcPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8260.29, 932.285), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3136
+ connRef = new ConnRef(router, 3136);
+ srcPt = ConnEnd(Point(8260.29, 902.285), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8458.29, 808.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3137
+ connRef = new ConnRef(router, 3137);
+ srcPt = ConnEnd(Point(8260.29, 902.285), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 742.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3138
+ connRef = new ConnRef(router, 3138);
+ srcPt = ConnEnd(Point(7996.29, 1148.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8603.29, 983.285), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3139
+ connRef = new ConnRef(router, 3139);
+ srcPt = ConnEnd(Point(8633.29, 983.285), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9270.59, 808.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3140
+ connRef = new ConnRef(router, 3140);
+ srcPt = ConnEnd(Point(7996.29, 1148.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 998.285), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3141
+ connRef = new ConnRef(router, 3141);
+ srcPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 998.285), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3142
+ connRef = new ConnRef(router, 3142);
+ srcPt = ConnEnd(Point(15239.5, 968.285), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9270.59, 808.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3143
+ connRef = new ConnRef(router, 3143);
+ srcPt = ConnEnd(Point(15239.5, 968.285), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 742.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3144
+ connRef = new ConnRef(router, 3144);
+ srcPt = ConnEnd(Point(12531.5, 5512.67), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12676.5, 5314.67), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3145
+ connRef = new ConnRef(router, 3145);
+ srcPt = ConnEnd(Point(8835.89, 5004.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12676.5, 5314.67), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3146
+ connRef = new ConnRef(router, 3146);
+ srcPt = ConnEnd(Point(12706.5, 5314.67), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12531.5, 5169.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3147
+ connRef = new ConnRef(router, 3147);
+ srcPt = ConnEnd(Point(12531.5, 5512.67), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12338.1, 5314.67), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3148
+ connRef = new ConnRef(router, 3148);
+ srcPt = ConnEnd(Point(10116, 9345.42), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12338.1, 5314.67), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3149
+ connRef = new ConnRef(router, 3149);
+ srcPt = ConnEnd(Point(12368.1, 5314.67), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12531.5, 5169.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3150
+ connRef = new ConnRef(router, 3150);
+ srcPt = ConnEnd(Point(12368.1, 5314.67), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10116, 10174), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3151
+ connRef = new ConnRef(router, 3151);
+ srcPt = ConnEnd(Point(12531.5, 4740.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13086, 4542.4), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3152
+ connRef = new ConnRef(router, 3152);
+ srcPt = ConnEnd(Point(13116, 4542.4), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13266, 4126.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3153
+ connRef = new ConnRef(router, 3153);
+ srcPt = ConnEnd(Point(13266, 3631.51), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13461, 3862.51), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3154
+ connRef = new ConnRef(router, 3154);
+ srcPt = ConnEnd(Point(8835.89, 5004.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13461, 3862.51), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3155
+ connRef = new ConnRef(router, 3155);
+ srcPt = ConnEnd(Point(13491, 3862.51), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(13266, 4126.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3156
+ connRef = new ConnRef(router, 3156);
+ srcPt = ConnEnd(Point(12531.5, 4361.11), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12706.5, 3994.51), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3157
+ connRef = new ConnRef(router, 3157);
+ srcPt = ConnEnd(Point(12676.5, 3994.51), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12531.5, 3730.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3158
+ connRef = new ConnRef(router, 3158);
+ srcPt = ConnEnd(Point(12676.5, 3994.51), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8835.89, 5004.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3159
+ connRef = new ConnRef(router, 3159);
+ srcPt = ConnEnd(Point(12676.5, 3994.51), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10116, 10174), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3160
+ connRef = new ConnRef(router, 3160);
+ srcPt = ConnEnd(Point(11429.1, 8873.22), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11253.2, 9048.42), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3161
+ connRef = new ConnRef(router, 3161);
+ srcPt = ConnEnd(Point(11223.2, 9048.42), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11040.2, 8873.22), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3162
+ connRef = new ConnRef(router, 3162);
+ srcPt = ConnEnd(Point(5312, 4938.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(5496.1, 4590.4), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3163
+ connRef = new ConnRef(router, 3163);
+ srcPt = ConnEnd(Point(5496.1, 4560.4), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(5312, 4126.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3164
+ connRef = new ConnRef(router, 3164);
+ srcPt = ConnEnd(Point(5312, 5964.59), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(5496.1, 5184.4), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3165
+ connRef = new ConnRef(router, 3165);
+ srcPt = ConnEnd(Point(5496.1, 5154.4), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(5312, 4126.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3166
+ connRef = new ConnRef(router, 3166);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15820.6, 1346.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3167
+ connRef = new ConnRef(router, 3167);
+ srcPt = ConnEnd(Point(14037, 458.265), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15820.6, 1346.29), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3168
+ connRef = new ConnRef(router, 3168);
+ srcPt = ConnEnd(Point(15850.6, 1346.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 1181.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3169
+ connRef = new ConnRef(router, 3169);
+ srcPt = ConnEnd(Point(15850.6, 1346.29), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14565, 458.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3170
+ connRef = new ConnRef(router, 3170);
+ srcPt = ConnEnd(Point(11495.1, 8074.79), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11121.2, 8249.99), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3171
+ connRef = new ConnRef(router, 3171);
+ srcPt = ConnEnd(Point(11091.2, 8249.99), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10809.2, 8074.79), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3172
+ connRef = new ConnRef(router, 3172);
+ srcPt = ConnEnd(Point(15407.5, 7425.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16509.8, 7425.4), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3173
+ connRef = new ConnRef(router, 3173);
+ srcPt = ConnEnd(Point(16539.8, 7425.4), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17052.8, 7425.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3174
+ connRef = new ConnRef(router, 3174);
+ srcPt = ConnEnd(Point(15407.5, 7425.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16509.8, 7546.79), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3175
+ connRef = new ConnRef(router, 3175);
+ srcPt = ConnEnd(Point(16539.8, 7546.79), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17052.8, 7425.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3176
+ connRef = new ConnRef(router, 3176);
+ srcPt = ConnEnd(Point(18630.5, 11860.9), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(18531, 11982.3), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3177
+ connRef = new ConnRef(router, 3177);
+ srcPt = ConnEnd(Point(18501, 11982.3), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(18401.5, 11860.9), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3178
+ connRef = new ConnRef(router, 3178);
+ srcPt = ConnEnd(Point(18501, 11982.3), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9171.59, 458.265), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3179
+ connRef = new ConnRef(router, 3179);
+ srcPt = ConnEnd(Point(10809.2, 4542.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10809.2, 5642.9), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3180
+ connRef = new ConnRef(router, 3180);
+ srcPt = ConnEnd(Point(10809.2, 5672.9), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10809.2, 7128.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3181
+ connRef = new ConnRef(router, 3181);
+ srcPt = ConnEnd(Point(15239.5, 1511.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15619.3, 1181.29), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3182
+ connRef = new ConnRef(router, 3182);
+ srcPt = ConnEnd(Point(10809.2, 7128.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15619.3, 1181.29), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3183
+ connRef = new ConnRef(router, 3183);
+ srcPt = ConnEnd(Point(15589.3, 1181.29), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15239.5, 742.091), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3184
+ connRef = new ConnRef(router, 3184);
+ srcPt = ConnEnd(Point(15589.3, 1181.29), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10809.2, 4542.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3185
+ connRef = new ConnRef(router, 3185);
+ srcPt = ConnEnd(Point(15589.3, 1181.29), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10116, 10174), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3186
+ connRef = new ConnRef(router, 3186);
+ srcPt = ConnEnd(Point(11396.1, 4361.11), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11253.2, 4509.4), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3187
+ connRef = new ConnRef(router, 3187);
+ srcPt = ConnEnd(Point(11223.2, 4509.4), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11073.2, 4361.11), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3188
+ connRef = new ConnRef(router, 3188);
+ srcPt = ConnEnd(Point(11396.1, 4361.11), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11253.2, 4192.51), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3189
+ connRef = new ConnRef(router, 3189);
+ srcPt = ConnEnd(Point(11223.2, 4192.51), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(11073.2, 4361.11), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3190
+ connRef = new ConnRef(router, 3190);
+ srcPt = ConnEnd(Point(13200, 6788.21), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14583, 6963.4), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3191
+ connRef = new ConnRef(router, 3191);
+ srcPt = ConnEnd(Point(14613, 6963.4), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16231.6, 6788.21), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3192
+ connRef = new ConnRef(router, 3192);
+ srcPt = ConnEnd(Point(13200, 6788.21), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14583, 6646.51), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3193
+ connRef = new ConnRef(router, 3193);
+ srcPt = ConnEnd(Point(14613, 6646.51), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16231.6, 6788.21), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3194
+ connRef = new ConnRef(router, 3194);
+ srcPt = ConnEnd(Point(10116, 10174), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9982.69, 9723.42), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3195
+ connRef = new ConnRef(router, 3195);
+ srcPt = ConnEnd(Point(9982.69, 9693.42), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10116, 9345.42), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3196
+ connRef = new ConnRef(router, 3196);
+ srcPt = ConnEnd(Point(9019.99, 11211.6), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8699.29, 11386.8), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3197
+ connRef = new ConnRef(router, 3197);
+ srcPt = ConnEnd(Point(17052.8, 7062.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8699.29, 11386.8), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3198
+ connRef = new ConnRef(router, 3198);
+ srcPt = ConnEnd(Point(8669.29, 11386.8), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(8392.29, 11211.6), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3199
+ connRef = new ConnRef(router, 3199);
+ srcPt = ConnEnd(Point(8669.29, 11386.8), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(17052.8, 7425.4), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3200
+ connRef = new ConnRef(router, 3200);
+ srcPt = ConnEnd(Point(16198.6, 11632.9), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16066.6, 11532.7), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3201
+ connRef = new ConnRef(router, 3201);
+ srcPt = ConnEnd(Point(8835.89, 5004.4), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16066.6, 11532.7), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3202
+ connRef = new ConnRef(router, 3202);
+ srcPt = ConnEnd(Point(16066.6, 11562.7), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15868.6, 11632.9), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3203
+ connRef = new ConnRef(router, 3203);
+ srcPt = ConnEnd(Point(16198.6, 11632.9), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16081.6, 11386.8), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3204
+ connRef = new ConnRef(router, 3204);
+ srcPt = ConnEnd(Point(16051.6, 11386.8), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15868.6, 11632.9), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3205
+ connRef = new ConnRef(router, 3205);
+ srcPt = ConnEnd(Point(14004, 12292.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14187, 12425.7), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3206
+ connRef = new ConnRef(router, 3206);
+ srcPt = ConnEnd(Point(10116, 9345.42), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14187, 12425.7), 4);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3207
+ connRef = new ConnRef(router, 3207);
+ srcPt = ConnEnd(Point(14217, 12425.7), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(14400, 12292.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3208
+ connRef = new ConnRef(router, 3208);
+ srcPt = ConnEnd(Point(14217, 12425.7), 8);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10116, 10174), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3209
+ connRef = new ConnRef(router, 3209);
+ srcPt = ConnEnd(Point(9501.59, 8249.99), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9685.69, 7374.4), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3210
+ connRef = new ConnRef(router, 3210);
+ srcPt = ConnEnd(Point(9685.69, 7344.4), 1);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9501.59, 6481.51), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3211
+ connRef = new ConnRef(router, 3211);
+ srcPt = ConnEnd(Point(16198.6, 10781.3), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15780.9, 10914.6), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3212
+ connRef = new ConnRef(router, 3212);
+ srcPt = ConnEnd(Point(10116, 9345.42), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15780.9, 10914.6), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3213
+ connRef = new ConnRef(router, 3213);
+ srcPt = ConnEnd(Point(15750.9, 10914.6), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15019.9, 10781.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3214
+ connRef = new ConnRef(router, 3214);
+ srcPt = ConnEnd(Point(15750.9, 10914.6), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(10116, 10174), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3215
+ connRef = new ConnRef(router, 3215);
+ srcPt = ConnEnd(Point(15019.9, 11794.9), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(15148.3, 11908.9), 2);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3216
+ connRef = new ConnRef(router, 3216);
+ srcPt = ConnEnd(Point(7608.1, 1280.29), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7765.29, 1397.29), 1);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3217
+ connRef = new ConnRef(router, 3217);
+ srcPt = ConnEnd(Point(7765.29, 1427.29), 2);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(7608.1, 1610.29), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3218
+ connRef = new ConnRef(router, 3218);
+ srcPt = ConnEnd(Point(16788.8, 12458.7), 15);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(12937.5, 12458.7), 8);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3219
+ connRef = new ConnRef(router, 3219);
+ srcPt = ConnEnd(Point(12907.5, 12458.7), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(16557.8, 11982.3), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ // connRef3220
+ connRef = new ConnRef(router, 3220);
+ srcPt = ConnEnd(Point(12907.5, 12458.7), 4);
+ connRef->setSourceEndpoint(srcPt);
+ dstPt = ConnEnd(Point(9237.59, 12458.7), 15);
+ connRef->setDestEndpoint(dstPt);
+ connRef->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+
+ router->outputDiagram("output/UnsatisfiableRangeAssertion");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/validPaths01.cpp b/src/3rdparty/adaptagrams/libavoid/tests/validPaths01.cpp
new file mode 100644
index 0000000..eb79ee2
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/validPaths01.cpp
@@ -0,0 +1,457 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 200);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 110);
+ router->setRoutingPenalty((PenaltyType)5, 100);
+ router->setRoutingOption((RoutingOption)0, false);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+ Polygon poly3075375(4);
+ poly3075375.ps[0] = Point(51925, 52070);
+ poly3075375.ps[1] = Point(51925, 52130);
+ poly3075375.ps[2] = Point(51725, 52130);
+ poly3075375.ps[3] = Point(51725, 52070);
+ new ShapeRef(router, poly3075375, 3075375);
+
+ Polygon poly101599344(4);
+ poly101599344.ps[0] = Point(50275, 52410);
+ poly101599344.ps[1] = Point(50275, 52490);
+ poly101599344.ps[2] = Point(50075, 52490);
+ poly101599344.ps[3] = Point(50075, 52410);
+ new ShapeRef(router, poly101599344, 101599344);
+
+ Polygon poly127957550(4);
+ poly127957550.ps[0] = Point(52010, 51617);
+ poly127957550.ps[1] = Point(52010, 51683);
+ poly127957550.ps[2] = Point(51890, 51683);
+ poly127957550.ps[3] = Point(51890, 51617);
+ ShapeRef *shapeRef127957550 = new ShapeRef(router, poly127957550, 127957550);
+ new ShapeConnectionPin(shapeRef127957550, 2147483646, 0.5, 0.5, true, 0, (ConnDirFlags) 1);
+ new ShapeConnectionPin(shapeRef127957550, 2147483646, 0.5, 0.5, true, 0, (ConnDirFlags) 2);
+ new ShapeConnectionPin(shapeRef127957550, 2147483646, 0.5, 0.5, true, 0, (ConnDirFlags) 4);
+ new ShapeConnectionPin(shapeRef127957550, 2147483646, 0.5, 0.5, true, 0, (ConnDirFlags) 8);
+
+ Polygon poly129612347(4);
+ poly129612347.ps[0] = Point(51900, 51696);
+ poly129612347.ps[1] = Point(51900, 51754);
+ poly129612347.ps[2] = Point(51815, 51754);
+ poly129612347.ps[3] = Point(51815, 51696);
+ new ShapeRef(router, poly129612347, 129612347);
+
+ Polygon poly203389050(4);
+ poly203389050.ps[0] = Point(51825, 52260);
+ poly203389050.ps[1] = Point(51825, 52340);
+ poly203389050.ps[2] = Point(51625, 52340);
+ poly203389050.ps[3] = Point(51625, 52260);
+ new ShapeRef(router, poly203389050, 203389050);
+
+ Polygon poly208676910(4);
+ poly208676910.ps[0] = Point(51950, 51760);
+ poly208676910.ps[1] = Point(51950, 51840);
+ poly208676910.ps[2] = Point(51750, 51840);
+ poly208676910.ps[3] = Point(51750, 51760);
+ new ShapeRef(router, poly208676910, 208676910);
+
+ Polygon poly219117032(4);
+ poly219117032.ps[0] = Point(50225, 52070);
+ poly219117032.ps[1] = Point(50225, 52130);
+ poly219117032.ps[2] = Point(50025, 52130);
+ poly219117032.ps[3] = Point(50025, 52070);
+ new ShapeRef(router, poly219117032, 219117032);
+
+ Polygon poly258454350(4);
+ poly258454350.ps[0] = Point(50185, 51617);
+ poly258454350.ps[1] = Point(50185, 51683);
+ poly258454350.ps[2] = Point(50065, 51683);
+ poly258454350.ps[3] = Point(50065, 51617);
+ ShapeRef *shapeRef258454350 = new ShapeRef(router, poly258454350, 258454350);
+ new ShapeConnectionPin(shapeRef258454350, 2147483646, 0.5, 0.5, true, 0, (ConnDirFlags) 1);
+ new ShapeConnectionPin(shapeRef258454350, 2147483646, 0.5, 0.5, true, 0, (ConnDirFlags) 2);
+ new ShapeConnectionPin(shapeRef258454350, 2147483646, 0.5, 0.5, true, 0, (ConnDirFlags) 4);
+ new ShapeConnectionPin(shapeRef258454350, 2147483646, 0.5, 0.5, true, 0, (ConnDirFlags) 8);
+
+ Polygon poly274504590(4);
+ poly274504590.ps[0] = Point(51400, 52470);
+ poly274504590.ps[1] = Point(51400, 52530);
+ poly274504590.ps[2] = Point(51150, 52530);
+ poly274504590.ps[3] = Point(51150, 52470);
+ new ShapeRef(router, poly274504590, 274504590);
+
+ Polygon poly320957826(4);
+ poly320957826.ps[0] = Point(50275, 51910);
+ poly320957826.ps[1] = Point(50275, 51990);
+ poly320957826.ps[2] = Point(50075, 51990);
+ poly320957826.ps[3] = Point(50075, 51910);
+ new ShapeRef(router, poly320957826, 320957826);
+
+ Polygon poly368436384(4);
+ poly368436384.ps[0] = Point(50325, 51696);
+ poly368436384.ps[1] = Point(50325, 51754);
+ poly368436384.ps[2] = Point(50240, 51754);
+ poly368436384.ps[3] = Point(50240, 51696);
+ new ShapeRef(router, poly368436384, 368436384);
+
+ Polygon poly381499178(4);
+ poly381499178.ps[0] = Point(51850, 51345);
+ poly381499178.ps[1] = Point(51850, 51405);
+ poly381499178.ps[2] = Point(51650, 51405);
+ poly381499178.ps[3] = Point(51650, 51345);
+ new ShapeRef(router, poly381499178, 381499178);
+
+ Polygon poly426410694(4);
+ poly426410694.ps[0] = Point(50325, 52270);
+ poly426410694.ps[1] = Point(50325, 52330);
+ poly426410694.ps[2] = Point(50125, 52330);
+ poly426410694.ps[3] = Point(50125, 52270);
+ new ShapeRef(router, poly426410694, 426410694);
+
+ Polygon poly428912890(4);
+ poly428912890.ps[0] = Point(51825, 51510);
+ poly428912890.ps[1] = Point(51825, 51590);
+ poly428912890.ps[2] = Point(51625, 51590);
+ poly428912890.ps[3] = Point(51625, 51510);
+ new ShapeRef(router, poly428912890, 428912890);
+
+ Polygon poly468897320(4);
+ poly468897320.ps[0] = Point(50425, 51520);
+ poly468897320.ps[1] = Point(50425, 51580);
+ poly468897320.ps[2] = Point(50225, 51580);
+ poly468897320.ps[3] = Point(50225, 51520);
+ new ShapeRef(router, poly468897320, 468897320);
+
+ Polygon poly517518507(4);
+ poly517518507.ps[0] = Point(51925, 51910);
+ poly517518507.ps[1] = Point(51925, 51990);
+ poly517518507.ps[2] = Point(51725, 51990);
+ poly517518507.ps[3] = Point(51725, 51910);
+ new ShapeRef(router, poly517518507, 517518507);
+
+ Polygon poly565878858(4);
+ poly565878858.ps[0] = Point(51160, 52500);
+ poly565878858.ps[1] = Point(51160, 52810);
+ poly565878858.ps[2] = Point(50890, 52810);
+ poly565878858.ps[3] = Point(50890, 52500);
+ new ShapeRef(router, poly565878858, 565878858);
+
+ Polygon poly706147100(4);
+ poly706147100.ps[0] = Point(51160, 50990);
+ poly706147100.ps[1] = Point(51160, 51300);
+ poly706147100.ps[2] = Point(50890, 51300);
+ poly706147100.ps[3] = Point(50890, 50990);
+ new ShapeRef(router, poly706147100, 706147100);
+
+ Polygon poly746254622(4);
+ poly746254622.ps[0] = Point(50275, 51760);
+ poly746254622.ps[1] = Point(50275, 51840);
+ poly746254622.ps[2] = Point(50075, 51840);
+ poly746254622.ps[3] = Point(50075, 51760);
+ new ShapeRef(router, poly746254622, 746254622);
+
+ Polygon poly829835240(4);
+ poly829835240.ps[0] = Point(50425, 51360);
+ poly829835240.ps[1] = Point(50425, 51440);
+ poly829835240.ps[2] = Point(50225, 51440);
+ poly829835240.ps[3] = Point(50225, 51360);
+ new ShapeRef(router, poly829835240, 829835240);
+
+ Polygon poly157548160(4);
+ poly157548160.ps[0] = Point(51550, 51500);
+ poly157548160.ps[1] = Point(51550, 52225);
+ poly157548160.ps[2] = Point(50525, 52225);
+ poly157548160.ps[3] = Point(50525, 51500);
+ new ShapeRef(router, poly157548160, 157548160);
+
+ ConnRef *connRef6675422 = new ConnRef(router, 6675422);
+ ConnEnd srcPt6675422(Point(51100, 51290), 2);
+ connRef6675422->setSourceEndpoint(srcPt6675422);
+ ConnEnd dstPt6675422(Point(51150, 51510), 1);
+ connRef6675422->setDestEndpoint(dstPt6675422);
+ connRef6675422->setRoutingType((ConnType)2);
+
+ ConnRef *connRef13259320 = new ConnRef(router, 13259320);
+ ConnEnd srcPt13259320(Point(50535, 51675), 4);
+ connRef13259320->setSourceEndpoint(srcPt13259320);
+ ConnEnd dstPt13259320(Point(50315, 51725), 8);
+ connRef13259320->setDestEndpoint(dstPt13259320);
+ connRef13259320->setRoutingType((ConnType)2);
+
+ ConnRef *connRef17108208 = new ConnRef(router, 17108208);
+ ConnEnd srcPt17108208(Point(51540, 52050), 8);
+ connRef17108208->setSourceEndpoint(srcPt17108208);
+ ConnEnd dstPt17108208(Point(51735, 52100), 4);
+ connRef17108208->setDestEndpoint(dstPt17108208);
+ connRef17108208->setRoutingType((ConnType)2);
+
+ ConnRef *connRef41442471 = new ConnRef(router, 41442471);
+ ConnEnd srcPt41442471(Point(51075, 52215), 2);
+ connRef41442471->setSourceEndpoint(srcPt41442471);
+ ConnEnd dstPt41442471(Point(51050, 52510), 1);
+ connRef41442471->setDestEndpoint(dstPt41442471);
+ connRef41442471->setRoutingType((ConnType)2);
+
+ ConnRef *connRef45863720 = new ConnRef(router, 45863720);
+ ConnEnd srcPt45863720(Point(51660, 51375), 4);
+ connRef45863720->setSourceEndpoint(srcPt45863720);
+ ConnEnd dstPt45863720(Point(51300, 51510), 1);
+ connRef45863720->setDestEndpoint(dstPt45863720);
+ connRef45863720->setRoutingType((ConnType)2);
+
+ ConnRef *connRef52653348 = new ConnRef(router, 52653348);
+ ConnEnd srcPt52653348(Point(50535, 52050), 4);
+ connRef52653348->setSourceEndpoint(srcPt52653348);
+ ConnEnd dstPt52653348(Point(50215, 52100), 8);
+ connRef52653348->setDestEndpoint(dstPt52653348);
+ connRef52653348->setRoutingType((ConnType)2);
+
+ ConnRef *connRef57649636 = new ConnRef(router, 57649636);
+ ConnEnd srcPt57649636(Point(51540, 52125), 8);
+ connRef57649636->setSourceEndpoint(srcPt57649636);
+ ConnEnd dstPt57649636(Point(51915, 52100), 8);
+ connRef57649636->setDestEndpoint(dstPt57649636);
+ connRef57649636->setRoutingType((ConnType)2);
+
+ ConnRef *connRef64735671 = new ConnRef(router, 64735671);
+ ConnEnd srcPt64735671(Point(51375, 52215), 2);
+ connRef64735671->setSourceEndpoint(srcPt64735671);
+ ConnEnd dstPt64735671(Point(51815, 52300), 8);
+ connRef64735671->setDestEndpoint(dstPt64735671);
+ connRef64735671->setRoutingType((ConnType)2);
+
+ ConnRef *connRef81789576 = new ConnRef(router, 81789576);
+ ConnEnd srcPt81789576(Point(50950, 51290), 2);
+ connRef81789576->setSourceEndpoint(srcPt81789576);
+ ConnEnd dstPt81789576(Point(50925, 51510), 1);
+ connRef81789576->setDestEndpoint(dstPt81789576);
+ connRef81789576->setRoutingType((ConnType)2);
+
+ ConnRef *connRef87742344 = new ConnRef(router, 87742344);
+ ConnEnd srcPt87742344(Point(51540, 51600), 8);
+ connRef87742344->setSourceEndpoint(srcPt87742344);
+ ConnEnd dstPt87742344(shapeRef127957550, 2147483646);
+ connRef87742344->setDestEndpoint(dstPt87742344);
+ connRef87742344->setRoutingType((ConnType)2);
+
+ ConnRef *connRef92624219 = new ConnRef(router, 92624219);
+ ConnEnd srcPt92624219(Point(51450, 52215), 2);
+ connRef92624219->setSourceEndpoint(srcPt92624219);
+ ConnEnd dstPt92624219(Point(51635, 52300), 4);
+ connRef92624219->setDestEndpoint(dstPt92624219);
+ connRef92624219->setRoutingType((ConnType)2);
+
+ ConnRef *connRef126568050 = new ConnRef(router, 126568050);
+ ConnEnd srcPt126568050(Point(51540, 51975), 8);
+ connRef126568050->setSourceEndpoint(srcPt126568050);
+ ConnEnd dstPt126568050(Point(51915, 51950), 8);
+ connRef126568050->setDestEndpoint(dstPt126568050);
+ connRef126568050->setRoutingType((ConnType)2);
+
+ ConnRef *connRef128113340 = new ConnRef(router, 128113340);
+ ConnEnd srcPt128113340(Point(51300, 52215), 2);
+ connRef128113340->setSourceEndpoint(srcPt128113340);
+ ConnEnd dstPt128113340(Point(51390, 52500), 8);
+ connRef128113340->setDestEndpoint(dstPt128113340);
+ connRef128113340->setRoutingType((ConnType)2);
+
+ ConnRef *connRef157642749 = new ConnRef(router, 157642749);
+ ConnEnd srcPt157642749(Point(51225, 52215), 2);
+ connRef157642749->setSourceEndpoint(srcPt157642749);
+ // Problem point:
+ ConnEnd dstPt157642749(Point(51160, 52500), 4);
+ connRef157642749->setDestEndpoint(dstPt157642749);
+ connRef157642749->setRoutingType((ConnType)2);
+
+ ConnRef *connRef182970626 = new ConnRef(router, 182970626);
+ ConnEnd srcPt182970626(Point(51000, 52215), 2);
+ connRef182970626->setSourceEndpoint(srcPt182970626);
+ ConnEnd dstPt182970626(Point(51000, 52510), 1);
+ connRef182970626->setDestEndpoint(dstPt182970626);
+ connRef182970626->setRoutingType((ConnType)2);
+
+ ConnRef *connRef191618599 = new ConnRef(router, 191618599);
+ ConnEnd srcPt191618599(Point(50535, 51900), 4);
+ connRef191618599->setSourceEndpoint(srcPt191618599);
+ ConnEnd dstPt191618599(Point(50265, 51950), 8);
+ connRef191618599->setDestEndpoint(dstPt191618599);
+ connRef191618599->setRoutingType((ConnType)2);
+
+ ConnRef *connRef215646300 = new ConnRef(router, 215646300);
+ ConnEnd srcPt215646300(Point(50415, 51400), 8);
+ connRef215646300->setSourceEndpoint(srcPt215646300);
+ ConnEnd dstPt215646300(Point(50775, 51510), 1);
+ connRef215646300->setDestEndpoint(dstPt215646300);
+ connRef215646300->setRoutingType((ConnType)2);
+
+ ConnRef *connRef217181718 = new ConnRef(router, 217181718);
+ ConnEnd srcPt217181718(Point(51000, 51290), 2);
+ connRef217181718->setSourceEndpoint(srcPt217181718);
+ ConnEnd dstPt217181718(Point(51000, 51510), 1);
+ connRef217181718->setDestEndpoint(dstPt217181718);
+ connRef217181718->setRoutingType((ConnType)2);
+
+ ConnRef *connRef217236398 = new ConnRef(router, 217236398);
+ ConnEnd srcPt217236398(Point(50700, 52215), 2);
+ connRef217236398->setSourceEndpoint(srcPt217236398);
+ ConnEnd dstPt217236398(Point(50135, 52300), 4);
+ connRef217236398->setDestEndpoint(dstPt217236398);
+ connRef217236398->setRoutingType((ConnType)2);
+
+ ConnRef *connRef227676560 = new ConnRef(router, 227676560);
+ ConnEnd srcPt227676560(Point(50850, 51510), 1);
+ connRef227676560->setSourceEndpoint(srcPt227676560);
+ ConnEnd dstPt227676560(Point(50235, 51400), 4);
+ connRef227676560->setDestEndpoint(dstPt227676560);
+ connRef227676560->setRoutingType((ConnType)2);
+
+ ConnRef *connRef235740708 = new ConnRef(router, 235740708);
+ ConnEnd srcPt235740708(Point(51540, 51675), 8);
+ connRef235740708->setSourceEndpoint(srcPt235740708);
+ ConnEnd dstPt235740708(Point(51870, 51725), 8);
+ connRef235740708->setDestEndpoint(dstPt235740708);
+ connRef235740708->setRoutingType((ConnType)2);
+
+ ConnRef *connRef307166980 = new ConnRef(router, 307166980);
+ ConnEnd srcPt307166980(Point(50925, 52215), 2);
+ connRef307166980->setSourceEndpoint(srcPt307166980);
+ ConnEnd dstPt307166980(Point(50950, 52510), 1);
+ connRef307166980->setDestEndpoint(dstPt307166980);
+ connRef307166980->setRoutingType((ConnType)2);
+
+ ConnRef *connRef314353850 = new ConnRef(router, 314353850);
+ ConnEnd srcPt314353850(Point(51050, 51290), 2);
+ connRef314353850->setSourceEndpoint(srcPt314353850);
+ ConnEnd dstPt314353850(Point(51075, 51510), 1);
+ connRef314353850->setDestEndpoint(dstPt314353850);
+ connRef314353850->setRoutingType((ConnType)2);
+
+ ConnRef *connRef356343444 = new ConnRef(router, 356343444);
+ ConnEnd srcPt356343444(Point(50625, 51510), 1);
+ connRef356343444->setSourceEndpoint(srcPt356343444);
+ ConnEnd dstPt356343444(Point(50415, 51550), 8);
+ connRef356343444->setDestEndpoint(dstPt356343444);
+ connRef356343444->setRoutingType((ConnType)2);
+
+ ConnRef *connRef401560509 = new ConnRef(router, 401560509);
+ ConnEnd srcPt401560509(Point(50625, 52215), 2);
+ connRef401560509->setSourceEndpoint(srcPt401560509);
+ ConnEnd dstPt401560509(Point(50315, 52300), 8);
+ connRef401560509->setDestEndpoint(dstPt401560509);
+ connRef401560509->setRoutingType((ConnType)2);
+
+ ConnRef *connRef413072940 = new ConnRef(router, 413072940);
+ ConnEnd srcPt413072940(Point(51840, 51375), 8);
+ connRef413072940->setSourceEndpoint(srcPt413072940);
+ ConnEnd dstPt413072940(Point(51225, 51510), 1);
+ connRef413072940->setDestEndpoint(dstPt413072940);
+ connRef413072940->setRoutingType((ConnType)2);
+
+ ConnRef *connRef413766381 = new ConnRef(router, 413766381);
+ ConnEnd srcPt413766381(Point(50535, 51750), 4);
+ connRef413766381->setSourceEndpoint(srcPt413766381);
+ ConnEnd dstPt413766381(Point(50265, 51800), 8);
+ connRef413766381->setDestEndpoint(dstPt413766381);
+ connRef413766381->setRoutingType((ConnType)2);
+
+ ConnRef *connRef422359365 = new ConnRef(router, 422359365);
+ ConnEnd srcPt422359365(Point(50535, 51825), 4);
+ connRef422359365->setSourceEndpoint(srcPt422359365);
+ ConnEnd dstPt422359365(Point(50085, 51800), 4);
+ connRef422359365->setDestEndpoint(dstPt422359365);
+ connRef422359365->setRoutingType((ConnType)2);
+
+ ConnRef *connRef427415850 = new ConnRef(router, 427415850);
+ ConnEnd srcPt427415850(Point(50775, 52215), 2);
+ connRef427415850->setSourceEndpoint(srcPt427415850);
+ ConnEnd dstPt427415850(Point(50265, 52450), 8);
+ connRef427415850->setDestEndpoint(dstPt427415850);
+ connRef427415850->setRoutingType((ConnType)2);
+
+ ConnRef *connRef444649182 = new ConnRef(router, 444649182);
+ ConnEnd srcPt444649182(Point(51540, 51750), 8);
+ connRef444649182->setSourceEndpoint(srcPt444649182);
+ ConnEnd dstPt444649182(Point(51760, 51800), 4);
+ connRef444649182->setDestEndpoint(dstPt444649182);
+ connRef444649182->setRoutingType((ConnType)2);
+
+ ConnRef *connRef505297694 = new ConnRef(router, 505297694);
+ ConnEnd srcPt505297694(Point(50700, 51510), 1);
+ connRef505297694->setSourceEndpoint(srcPt505297694);
+ ConnEnd dstPt505297694(Point(50235, 51550), 4);
+ connRef505297694->setDestEndpoint(dstPt505297694);
+ connRef505297694->setRoutingType((ConnType)2);
+
+ ConnRef *connRef528809632 = new ConnRef(router, 528809632);
+ ConnEnd srcPt528809632(Point(51540, 51900), 8);
+ connRef528809632->setSourceEndpoint(srcPt528809632);
+ ConnEnd dstPt528809632(Point(51735, 51950), 4);
+ connRef528809632->setDestEndpoint(dstPt528809632);
+ connRef528809632->setRoutingType((ConnType)2);
+
+ ConnRef *connRef548127810 = new ConnRef(router, 548127810);
+ ConnEnd srcPt548127810(Point(50535, 51975), 4);
+ connRef548127810->setSourceEndpoint(srcPt548127810);
+ ConnEnd dstPt548127810(Point(50085, 51950), 4);
+ connRef548127810->setDestEndpoint(dstPt548127810);
+ connRef548127810->setRoutingType((ConnType)2);
+
+ ConnRef *connRef648819584 = new ConnRef(router, 648819584);
+ ConnEnd srcPt648819584(Point(51540, 51825), 8);
+ connRef648819584->setSourceEndpoint(srcPt648819584);
+ ConnEnd dstPt648819584(Point(51940, 51800), 8);
+ connRef648819584->setDestEndpoint(dstPt648819584);
+ connRef648819584->setRoutingType((ConnType)2);
+
+ ConnRef *connRef651183694 = new ConnRef(router, 651183694);
+ ConnEnd srcPt651183694(Point(51635, 51550), 4);
+ connRef651183694->setSourceEndpoint(srcPt651183694);
+ ConnEnd dstPt651183694(Point(51450, 51510), 1);
+ connRef651183694->setDestEndpoint(dstPt651183694);
+ connRef651183694->setRoutingType((ConnType)2);
+
+ ConnRef *connRef655025700 = new ConnRef(router, 655025700);
+ ConnEnd srcPt655025700(Point(51150, 52215), 2);
+ connRef655025700->setSourceEndpoint(srcPt655025700);
+ ConnEnd dstPt655025700(Point(51100, 52510), 1);
+ connRef655025700->setDestEndpoint(dstPt655025700);
+ connRef655025700->setRoutingType((ConnType)2);
+
+ ConnRef *connRef662151765 = new ConnRef(router, 662151765);
+ ConnEnd srcPt662151765(Point(50535, 51600), 4);
+ connRef662151765->setSourceEndpoint(srcPt662151765);
+ ConnEnd dstPt662151765(shapeRef258454350, 2147483646);
+ connRef662151765->setDestEndpoint(dstPt662151765);
+ connRef662151765->setRoutingType((ConnType)2);
+
+ ConnRef *connRef678159455 = new ConnRef(router, 678159455);
+ ConnEnd srcPt678159455(Point(51815, 51550), 8);
+ connRef678159455->setSourceEndpoint(srcPt678159455);
+ ConnEnd dstPt678159455(Point(51375, 51510), 1);
+ connRef678159455->setDestEndpoint(dstPt678159455);
+ connRef678159455->setRoutingType((ConnType)2);
+
+ ConnRef *connRef803304040 = new ConnRef(router, 803304040);
+ ConnEnd srcPt803304040(Point(50850, 52215), 2);
+ connRef803304040->setSourceEndpoint(srcPt803304040);
+ ConnEnd dstPt803304040(Point(50085, 52450), 4);
+ connRef803304040->setDestEndpoint(dstPt803304040);
+ connRef803304040->setRoutingType((ConnType)2);
+
+ ConnRef *connRef960638799 = new ConnRef(router, 960638799);
+ ConnEnd srcPt960638799(Point(50535, 52125), 4);
+ connRef960638799->setSourceEndpoint(srcPt960638799);
+ ConnEnd dstPt960638799(Point(50035, 52100), 4);
+ connRef960638799->setDestEndpoint(dstPt960638799);
+ connRef960638799->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/validPaths01");
+ int result = router->existsInvalidOrthogonalPaths();
+ delete router;
+ return result;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/validPaths02.cpp b/src/3rdparty/adaptagrams/libavoid/tests/validPaths02.cpp
new file mode 100644
index 0000000..2de3f3b
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/validPaths02.cpp
@@ -0,0 +1,53 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 200);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 110);
+ router->setRoutingPenalty((PenaltyType)5, 100);
+ router->setRoutingOption((RoutingOption)0, false);
+ router->setRoutingOption((RoutingOption)1, true);
+ router->setRoutingParameter(idealNudgingDistance, 25);
+
+ Polygon poly186982048(4);
+ poly186982048.ps[0] = Point(52660, 50490);
+ poly186982048.ps[1] = Point(52660, 50960);
+ poly186982048.ps[2] = Point(52090, 50960);
+ poly186982048.ps[3] = Point(52090, 50490);
+ ShapeRef *shapeRef186982048 = new ShapeRef(router, poly186982048, 186982048);
+ new ShapeConnectionPin(shapeRef186982048, 5, 0.982456, 0.12766, true, 0, (ConnDirFlags) 8);
+ new ShapeConnectionPin(shapeRef186982048, 13, 0.982456, 0.234043, true, 0, (ConnDirFlags) 8);
+
+ Polygon poly197692264(4);
+ poly197692264.ps[0] = Point(52560, 50342);
+ poly197692264.ps[1] = Point(52560, 50425);
+ poly197692264.ps[2] = Point(52440, 50425);
+ poly197692264.ps[3] = Point(52440, 50342);
+ ShapeRef *shapeRef197692264 = new ShapeRef(router, poly197692264, 197692264);
+ new ShapeConnectionPin(shapeRef197692264, 1, 0.5, 0.39759, true, 0, (ConnDirFlags) 13);
+ new ShapeConnectionPin(shapeRef197692264, 2, 0.5, 1, true, 10, (ConnDirFlags) 2);
+
+ ConnRef *connRef111820287 = new ConnRef(router, 111820287);
+ ConnEnd srcPt111820287(shapeRef186982048, 13);
+ connRef111820287->setSourceEndpoint(srcPt111820287);
+ ConnEnd dstPt111820287(shapeRef197692264, 2);
+ connRef111820287->setDestEndpoint(dstPt111820287);
+ connRef111820287->setRoutingType((ConnType)2);
+
+ ConnRef *connRef744282799 = new ConnRef(router, 744282799);
+ ConnEnd srcPt744282799(shapeRef186982048, 5);
+ connRef744282799->setSourceEndpoint(srcPt744282799);
+ ConnEnd dstPt744282799(shapeRef197692264, 1);
+ connRef744282799->setDestEndpoint(dstPt744282799);
+ connRef744282799->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/validPaths02");
+ int result = router->existsInvalidOrthogonalPaths();
+ delete router;
+ return result;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/tests/vertlineassertion.cpp b/src/3rdparty/adaptagrams/libavoid/tests/vertlineassertion.cpp
new file mode 100644
index 0000000..2609dd8
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/tests/vertlineassertion.cpp
@@ -0,0 +1,2214 @@
+#include "libavoid/libavoid.h"
+using namespace Avoid;
+int main(void) {
+ Router *router = new Router(
+ PolyLineRouting | OrthogonalRouting);
+ router->setRoutingPenalty((PenaltyType)0, 50);
+ router->setRoutingPenalty((PenaltyType)1, 0);
+ router->setRoutingPenalty((PenaltyType)2, 0);
+ router->setRoutingPenalty((PenaltyType)3, 4000);
+ router->setRoutingPenalty((PenaltyType)4, 0);
+
+ Polygon poly2(4);
+ poly2.ps[0] = Point(129, 898);
+ poly2.ps[1] = Point(129, 918);
+ poly2.ps[2] = Point(109, 918);
+ poly2.ps[3] = Point(109, 898);
+ new ShapeRef(router, poly2, 2);
+
+ Polygon poly3(4);
+ poly3.ps[0] = Point(272, 951);
+ poly3.ps[1] = Point(272, 971);
+ poly3.ps[2] = Point(252, 971);
+ poly3.ps[3] = Point(252, 951);
+ new ShapeRef(router, poly3, 3);
+
+ Polygon poly4(4);
+ poly4.ps[0] = Point(139, 931);
+ poly4.ps[1] = Point(139, 971);
+ poly4.ps[2] = Point(99, 971);
+ poly4.ps[3] = Point(99, 931);
+ new ShapeRef(router, poly4, 4);
+
+ Polygon poly5(4);
+ poly5.ps[0] = Point(665, 212.5);
+ poly5.ps[1] = Point(665, 459.5);
+ poly5.ps[2] = Point(593, 459.5);
+ poly5.ps[3] = Point(593, 212.5);
+ new ShapeRef(router, poly5, 5);
+
+ Polygon poly6(4);
+ poly6.ps[0] = Point(518, 52);
+ poly6.ps[1] = Point(518, 96);
+ poly6.ps[2] = Point(398, 96);
+ poly6.ps[3] = Point(398, 52);
+ new ShapeRef(router, poly6, 6);
+
+ Polygon poly7(4);
+ poly7.ps[0] = Point(361, 899);
+ poly7.ps[1] = Point(361, 919);
+ poly7.ps[2] = Point(341, 919);
+ poly7.ps[3] = Point(341, 899);
+ new ShapeRef(router, poly7, 7);
+
+ Polygon poly8(4);
+ poly8.ps[0] = Point(470, 930);
+ poly8.ps[1] = Point(470, 950);
+ poly8.ps[2] = Point(450, 950);
+ poly8.ps[3] = Point(450, 930);
+ new ShapeRef(router, poly8, 8);
+
+ Polygon poly9(4);
+ poly9.ps[0] = Point(422, 930);
+ poly9.ps[1] = Point(422, 950);
+ poly9.ps[2] = Point(402, 950);
+ poly9.ps[3] = Point(402, 930);
+ new ShapeRef(router, poly9, 9);
+
+ Polygon poly10(4);
+ poly10.ps[0] = Point(414, 861);
+ poly10.ps[1] = Point(414, 881);
+ poly10.ps[2] = Point(394, 881);
+ poly10.ps[3] = Point(394, 861);
+ new ShapeRef(router, poly10, 10);
+
+ Polygon poly11(4);
+ poly11.ps[0] = Point(414, 840);
+ poly11.ps[1] = Point(414, 860);
+ poly11.ps[2] = Point(394, 860);
+ poly11.ps[3] = Point(394, 840);
+ new ShapeRef(router, poly11, 11);
+
+ Polygon poly12(4);
+ poly12.ps[0] = Point(302, 852);
+ poly12.ps[1] = Point(302, 872);
+ poly12.ps[2] = Point(282, 872);
+ poly12.ps[3] = Point(282, 852);
+ new ShapeRef(router, poly12, 12);
+
+ Polygon poly13(4);
+ poly13.ps[0] = Point(193, 852);
+ poly13.ps[1] = Point(193, 872);
+ poly13.ps[2] = Point(173, 872);
+ poly13.ps[3] = Point(173, 852);
+ new ShapeRef(router, poly13, 13);
+
+ Polygon poly14(4);
+ poly14.ps[0] = Point(541, 851);
+ poly14.ps[1] = Point(541, 871);
+ poly14.ps[2] = Point(521, 871);
+ poly14.ps[3] = Point(521, 851);
+ new ShapeRef(router, poly14, 14);
+
+ Polygon poly15(4);
+ poly15.ps[0] = Point(401, 739);
+ poly15.ps[1] = Point(401, 783);
+ poly15.ps[2] = Point(313, 783);
+ poly15.ps[3] = Point(313, 739);
+ new ShapeRef(router, poly15, 15);
+
+ Polygon poly16(4);
+ poly16.ps[0] = Point(466, 757);
+ poly16.ps[1] = Point(466, 777);
+ poly16.ps[2] = Point(446, 777);
+ poly16.ps[3] = Point(446, 757);
+ new ShapeRef(router, poly16, 16);
+
+ Polygon poly17(4);
+ poly17.ps[0] = Point(466, 688);
+ poly17.ps[1] = Point(466, 708);
+ poly17.ps[2] = Point(446, 708);
+ poly17.ps[3] = Point(446, 688);
+ new ShapeRef(router, poly17, 17);
+
+ Polygon poly18(4);
+ poly18.ps[0] = Point(467, 616);
+ poly18.ps[1] = Point(467, 636);
+ poly18.ps[2] = Point(447, 636);
+ poly18.ps[3] = Point(447, 616);
+ new ShapeRef(router, poly18, 18);
+
+ Polygon poly19(4);
+ poly19.ps[0] = Point(441, 471);
+ poly19.ps[1] = Point(441, 491);
+ poly19.ps[2] = Point(421, 491);
+ poly19.ps[3] = Point(421, 471);
+ new ShapeRef(router, poly19, 19);
+
+ Polygon poly20(4);
+ poly20.ps[0] = Point(359.5, 575);
+ poly20.ps[1] = Point(359.5, 619);
+ poly20.ps[2] = Point(196.5, 619);
+ poly20.ps[3] = Point(196.5, 575);
+ new ShapeRef(router, poly20, 20);
+
+ Polygon poly21(4);
+ poly21.ps[0] = Point(386, 437);
+ poly21.ps[1] = Point(386, 457);
+ poly21.ps[2] = Point(366, 457);
+ poly21.ps[3] = Point(366, 437);
+ new ShapeRef(router, poly21, 21);
+
+ Polygon poly22(4);
+ poly22.ps[0] = Point(466, 391);
+ poly22.ps[1] = Point(466, 411);
+ poly22.ps[2] = Point(446, 411);
+ poly22.ps[3] = Point(446, 391);
+ new ShapeRef(router, poly22, 22);
+
+ Polygon poly23(4);
+ poly23.ps[0] = Point(466, 325);
+ poly23.ps[1] = Point(466, 345);
+ poly23.ps[2] = Point(446, 345);
+ poly23.ps[3] = Point(446, 325);
+ new ShapeRef(router, poly23, 23);
+
+ Polygon poly24(4);
+ poly24.ps[0] = Point(413, 325);
+ poly24.ps[1] = Point(413, 345);
+ poly24.ps[2] = Point(393, 345);
+ poly24.ps[3] = Point(393, 325);
+ new ShapeRef(router, poly24, 24);
+
+ Polygon poly25(4);
+ poly25.ps[0] = Point(535, 182);
+ poly25.ps[1] = Point(535, 202);
+ poly25.ps[2] = Point(515, 202);
+ poly25.ps[3] = Point(515, 182);
+ new ShapeRef(router, poly25, 25);
+
+ Polygon poly26(4);
+ poly26.ps[0] = Point(466, 255);
+ poly26.ps[1] = Point(466, 275);
+ poly26.ps[2] = Point(446, 275);
+ poly26.ps[3] = Point(446, 255);
+ new ShapeRef(router, poly26, 26);
+
+ Polygon poly27(4);
+ poly27.ps[0] = Point(466, 160);
+ poly27.ps[1] = Point(466, 180);
+ poly27.ps[2] = Point(446, 180);
+ poly27.ps[3] = Point(446, 160);
+ new ShapeRef(router, poly27, 27);
+
+ Polygon poly28(4);
+ poly28.ps[0] = Point(386, 289);
+ poly28.ps[1] = Point(386, 309);
+ poly28.ps[2] = Point(366, 309);
+ poly28.ps[3] = Point(366, 289);
+ new ShapeRef(router, poly28, 28);
+
+ Polygon poly29(4);
+ poly29.ps[0] = Point(231, 270);
+ poly29.ps[1] = Point(231, 290);
+ poly29.ps[2] = Point(211, 290);
+ poly29.ps[3] = Point(211, 270);
+ new ShapeRef(router, poly29, 29);
+
+ Polygon poly30(4);
+ poly30.ps[0] = Point(231, 289);
+ poly30.ps[1] = Point(231, 309);
+ poly30.ps[2] = Point(211, 309);
+ poly30.ps[3] = Point(211, 289);
+ new ShapeRef(router, poly30, 30);
+
+ Polygon poly31(4);
+ poly31.ps[0] = Point(340, 256);
+ poly31.ps[1] = Point(340, 276);
+ poly31.ps[2] = Point(320, 276);
+ poly31.ps[3] = Point(320, 256);
+ new ShapeRef(router, poly31, 31);
+
+ Polygon poly32(4);
+ poly32.ps[0] = Point(290, 256);
+ poly32.ps[1] = Point(290, 276);
+ poly32.ps[2] = Point(270, 276);
+ poly32.ps[3] = Point(270, 256);
+ new ShapeRef(router, poly32, 32);
+
+ Polygon poly33(4);
+ poly33.ps[0] = Point(164, 251);
+ poly33.ps[1] = Point(164, 271);
+ poly33.ps[2] = Point(144, 271);
+ poly33.ps[3] = Point(144, 251);
+ new ShapeRef(router, poly33, 33);
+
+ Polygon poly34(4);
+ poly34.ps[0] = Point(231, 214);
+ poly34.ps[1] = Point(231, 234);
+ poly34.ps[2] = Point(211, 234);
+ poly34.ps[3] = Point(211, 214);
+ new ShapeRef(router, poly34, 34);
+
+ Polygon poly35(4);
+ poly35.ps[0] = Point(231, 195);
+ poly35.ps[1] = Point(231, 215);
+ poly35.ps[2] = Point(211, 215);
+ poly35.ps[3] = Point(211, 195);
+ new ShapeRef(router, poly35, 35);
+
+ Polygon poly36(4);
+ poly36.ps[0] = Point(299, 173);
+ poly36.ps[1] = Point(299, 193);
+ poly36.ps[2] = Point(279, 193);
+ poly36.ps[3] = Point(279, 173);
+ new ShapeRef(router, poly36, 36);
+
+ Polygon poly37(4);
+ poly37.ps[0] = Point(326, 141);
+ poly37.ps[1] = Point(326, 161);
+ poly37.ps[2] = Point(306, 161);
+ poly37.ps[3] = Point(306, 141);
+ new ShapeRef(router, poly37, 37);
+
+ Polygon poly38(4);
+ poly38.ps[0] = Point(326, 120);
+ poly38.ps[1] = Point(326, 140);
+ poly38.ps[2] = Point(306, 140);
+ poly38.ps[3] = Point(306, 120);
+ new ShapeRef(router, poly38, 38);
+
+ Polygon poly39(4);
+ poly39.ps[0] = Point(295.5, 39.5);
+ poly39.ps[1] = Point(295.5, 74.5);
+ poly39.ps[2] = Point(34.5, 74.5);
+ poly39.ps[3] = Point(34.5, 39.5);
+ new ShapeRef(router, poly39, 39);
+
+ Polygon poly40(4);
+ poly40.ps[0] = Point(245, 895);
+ poly40.ps[1] = Point(245, 915);
+ poly40.ps[2] = Point(225, 915);
+ poly40.ps[3] = Point(225, 895);
+ new ShapeRef(router, poly40, 40);
+
+ Polygon poly41(4);
+ poly41.ps[0] = Point(466, 543);
+ poly41.ps[1] = Point(466, 563);
+ poly41.ps[2] = Point(446, 563);
+ poly41.ps[3] = Point(446, 543);
+ new ShapeRef(router, poly41, 41);
+
+ Polygon poly42(4);
+ poly42.ps[0] = Point(231, 233);
+ poly42.ps[1] = Point(231, 253);
+ poly42.ps[2] = Point(211, 253);
+ poly42.ps[3] = Point(211, 233);
+ new ShapeRef(router, poly42, 42);
+
+ Polygon poly43(4);
+ poly43.ps[0] = Point(231, 308);
+ poly43.ps[1] = Point(231, 328);
+ poly43.ps[2] = Point(211, 328);
+ poly43.ps[3] = Point(211, 308);
+ new ShapeRef(router, poly43, 43);
+
+ Polygon poly44(4);
+ poly44.ps[0] = Point(164, 347);
+ poly44.ps[1] = Point(164, 367);
+ poly44.ps[2] = Point(144, 367);
+ poly44.ps[3] = Point(144, 347);
+ new ShapeRef(router, poly44, 44);
+
+ Polygon poly45(4);
+ poly45.ps[0] = Point(164, 373);
+ poly45.ps[1] = Point(164, 393);
+ poly45.ps[2] = Point(144, 393);
+ poly45.ps[3] = Point(144, 373);
+ new ShapeRef(router, poly45, 45);
+
+ Polygon poly46(4);
+ poly46.ps[0] = Point(274, 346);
+ poly46.ps[1] = Point(274, 366);
+ poly46.ps[2] = Point(254, 366);
+ poly46.ps[3] = Point(254, 346);
+ new ShapeRef(router, poly46, 46);
+
+ Polygon poly47(4);
+ poly47.ps[0] = Point(274, 372);
+ poly47.ps[1] = Point(274, 392);
+ poly47.ps[2] = Point(254, 392);
+ poly47.ps[3] = Point(254, 372);
+ new ShapeRef(router, poly47, 47);
+
+ Polygon poly48(4);
+ poly48.ps[0] = Point(594, 173);
+ poly48.ps[1] = Point(594, 213);
+ poly48.ps[2] = Point(554, 213);
+ poly48.ps[3] = Point(554, 173);
+ new ShapeRef(router, poly48, 48);
+
+ Polygon poly49(4);
+ poly49.ps[0] = Point(476, 121);
+ poly49.ps[1] = Point(476, 161);
+ poly49.ps[2] = Point(436, 161);
+ poly49.ps[3] = Point(436, 121);
+ new ShapeRef(router, poly49, 49);
+
+ Polygon poly50(4);
+ poly50.ps[0] = Point(476, 642);
+ poly50.ps[1] = Point(476, 682);
+ poly50.ps[2] = Point(436, 682);
+ poly50.ps[3] = Point(436, 642);
+ new ShapeRef(router, poly50, 50);
+
+ Polygon poly51(4);
+ poly51.ps[0] = Point(174, 206);
+ poly51.ps[1] = Point(174, 246);
+ poly51.ps[2] = Point(134, 246);
+ poly51.ps[3] = Point(134, 206);
+ new ShapeRef(router, poly51, 51);
+
+ Polygon poly52(4);
+ poly52.ps[0] = Point(174, 279);
+ poly52.ps[1] = Point(174, 319);
+ poly52.ps[2] = Point(134, 319);
+ poly52.ps[3] = Point(134, 279);
+ new ShapeRef(router, poly52, 52);
+
+ Polygon poly53(4);
+ poly53.ps[0] = Point(325, 426);
+ poly53.ps[1] = Point(325, 466);
+ poly53.ps[2] = Point(285, 466);
+ poly53.ps[3] = Point(285, 426);
+ new ShapeRef(router, poly53, 53);
+
+ Polygon poly54(4);
+ poly54.ps[0] = Point(325, 279);
+ poly54.ps[1] = Point(325, 319);
+ poly54.ps[2] = Point(285, 319);
+ poly54.ps[3] = Point(285, 279);
+ new ShapeRef(router, poly54, 54);
+
+ Polygon poly55(4);
+ poly55.ps[0] = Point(476, 208);
+ poly55.ps[1] = Point(476, 248);
+ poly55.ps[2] = Point(436, 248);
+ poly55.ps[3] = Point(436, 208);
+ new ShapeRef(router, poly55, 55);
+
+ Polygon poly56(4);
+ poly56.ps[0] = Point(476, 281);
+ poly56.ps[1] = Point(476, 321);
+ poly56.ps[2] = Point(436, 321);
+ poly56.ps[3] = Point(436, 281);
+ new ShapeRef(router, poly56, 56);
+
+ Polygon poly57(4);
+ poly57.ps[0] = Point(476, 714);
+ poly57.ps[1] = Point(476, 754);
+ poly57.ps[2] = Point(436, 754);
+ poly57.ps[3] = Point(436, 714);
+ new ShapeRef(router, poly57, 57);
+
+ Polygon poly58(4);
+ poly58.ps[0] = Point(476, 570);
+ poly58.ps[1] = Point(476, 610);
+ poly58.ps[2] = Point(436, 610);
+ poly58.ps[3] = Point(436, 570);
+ new ShapeRef(router, poly58, 58);
+
+ Polygon poly59(4);
+ poly59.ps[0] = Point(476, 498);
+ poly59.ps[1] = Point(476, 538);
+ poly59.ps[2] = Point(436, 538);
+ poly59.ps[3] = Point(436, 498);
+ new ShapeRef(router, poly59, 59);
+
+ Polygon poly60(4);
+ poly60.ps[0] = Point(620, 841);
+ poly60.ps[1] = Point(620, 881);
+ poly60.ps[2] = Point(580, 881);
+ poly60.ps[3] = Point(580, 841);
+ new ShapeRef(router, poly60, 60);
+
+ Polygon poly61(4);
+ poly61.ps[0] = Point(307, 884);
+ poly61.ps[1] = Point(307, 924);
+ poly61.ps[2] = Point(267, 924);
+ poly61.ps[3] = Point(267, 884);
+ new ShapeRef(router, poly61, 61);
+
+ Polygon poly62(4);
+ poly62.ps[0] = Point(543, 931);
+ poly62.ps[1] = Point(543, 971);
+ poly62.ps[2] = Point(503, 971);
+ poly62.ps[3] = Point(503, 931);
+ new ShapeRef(router, poly62, 62);
+
+ Polygon poly63(4);
+ poly63.ps[0] = Point(476, 841);
+ poly63.ps[1] = Point(476, 881);
+ poly63.ps[2] = Point(436, 881);
+ poly63.ps[3] = Point(436, 841);
+ new ShapeRef(router, poly63, 63);
+
+ Polygon poly64(4);
+ poly64.ps[0] = Point(371, 841);
+ poly64.ps[1] = Point(371, 881);
+ poly64.ps[2] = Point(331, 881);
+ poly64.ps[3] = Point(331, 841);
+ new ShapeRef(router, poly64, 64);
+
+ Polygon poly65(4);
+ poly65.ps[0] = Point(371, 798);
+ poly65.ps[1] = Point(371, 838);
+ poly65.ps[2] = Point(331, 838);
+ poly65.ps[3] = Point(331, 798);
+ new ShapeRef(router, poly65, 65);
+
+ Polygon poly66(4);
+ poly66.ps[0] = Point(139, 841);
+ poly66.ps[1] = Point(139, 881);
+ poly66.ps[2] = Point(99, 881);
+ poly66.ps[3] = Point(99, 841);
+ new ShapeRef(router, poly66, 66);
+
+ Polygon poly67(4);
+ poly67.ps[0] = Point(371, 931);
+ poly67.ps[1] = Point(371, 971);
+ poly67.ps[2] = Point(331, 971);
+ poly67.ps[3] = Point(331, 931);
+ new ShapeRef(router, poly67, 67);
+
+ Polygon poly68(4);
+ poly68.ps[0] = Point(258, 841);
+ poly68.ps[1] = Point(258, 881);
+ poly68.ps[2] = Point(218, 881);
+ poly68.ps[3] = Point(218, 841);
+ new ShapeRef(router, poly68, 68);
+
+ Polygon poly69(4);
+ poly69.ps[0] = Point(205, 884);
+ poly69.ps[1] = Point(205, 924);
+ poly69.ps[2] = Point(165, 924);
+ poly69.ps[3] = Point(165, 884);
+ new ShapeRef(router, poly69, 69);
+
+ Polygon poly70(4);
+ poly70.ps[0] = Point(476, 351);
+ poly70.ps[1] = Point(476, 391);
+ poly70.ps[2] = Point(436, 391);
+ poly70.ps[3] = Point(436, 351);
+ new ShapeRef(router, poly70, 70);
+
+ Polygon poly71(4);
+ poly71.ps[0] = Point(125, 336);
+ poly71.ps[1] = Point(125, 376);
+ poly71.ps[2] = Point(85, 376);
+ poly71.ps[3] = Point(85, 336);
+ new ShapeRef(router, poly71, 71);
+
+ Polygon poly72(4);
+ poly72.ps[0] = Point(232, 336);
+ poly72.ps[1] = Point(232, 376);
+ poly72.ps[2] = Point(192, 376);
+ poly72.ps[3] = Point(192, 336);
+ new ShapeRef(router, poly72, 72);
+
+ Polygon poly73(4);
+ poly73.ps[0] = Point(232, 362);
+ poly73.ps[1] = Point(232, 402);
+ poly73.ps[2] = Point(192, 402);
+ poly73.ps[3] = Point(192, 362);
+ new ShapeRef(router, poly73, 73);
+
+ Polygon poly74(4);
+ poly74.ps[0] = Point(125, 362);
+ poly74.ps[1] = Point(125, 402);
+ poly74.ps[2] = Point(85, 402);
+ poly74.ps[3] = Point(85, 362);
+ new ShapeRef(router, poly74, 74);
+
+ Polygon poly75(4);
+ poly75.ps[0] = Point(77.5, 716);
+ poly75.ps[1] = Point(77.5, 880);
+ poly75.ps[2] = Point(20.5, 880);
+ poly75.ps[3] = Point(20.5, 716);
+ new ShapeRef(router, poly75, 75);
+
+ Polygon poly76(4);
+ poly76.ps[0] = Point(187, 713);
+ poly76.ps[1] = Point(187, 733);
+ poly76.ps[2] = Point(167, 733);
+ poly76.ps[3] = Point(167, 713);
+ new ShapeRef(router, poly76, 76);
+
+ Polygon poly77(4);
+ poly77.ps[0] = Point(139, 714);
+ poly77.ps[1] = Point(139, 754);
+ poly77.ps[2] = Point(99, 754);
+ poly77.ps[3] = Point(99, 714);
+ new ShapeRef(router, poly77, 77);
+
+ Polygon poly78(4);
+ poly78.ps[0] = Point(422, 951);
+ poly78.ps[1] = Point(422, 971);
+ poly78.ps[2] = Point(402, 971);
+ poly78.ps[3] = Point(402, 951);
+ new ShapeRef(router, poly78, 78);
+
+ Polygon poly79(4);
+ poly79.ps[0] = Point(187, 734);
+ poly79.ps[1] = Point(187, 754);
+ poly79.ps[2] = Point(167, 754);
+ poly79.ps[3] = Point(167, 734);
+ new ShapeRef(router, poly79, 79);
+
+ Polygon poly80(4);
+ poly80.ps[0] = Point(470, 951);
+ poly80.ps[1] = Point(470, 971);
+ poly80.ps[2] = Point(450, 971);
+ poly80.ps[3] = Point(450, 951);
+ new ShapeRef(router, poly80, 80);
+
+ Polygon poly81(4);
+ poly81.ps[0] = Point(669.5, 899.5);
+ poly81.ps[1] = Point(669.5, 934.5);
+ poly81.ps[2] = Point(532.5, 934.5);
+ poly81.ps[3] = Point(532.5, 899.5);
+ new ShapeRef(router, poly81, 81);
+
+ Polygon poly82(4);
+ poly82.ps[0] = Point(491, 471);
+ poly82.ps[1] = Point(491, 491);
+ poly82.ps[2] = Point(471, 491);
+ poly82.ps[3] = Point(471, 471);
+ new ShapeRef(router, poly82, 82);
+
+ Polygon poly83(4);
+ poly83.ps[0] = Point(565, 512);
+ poly83.ps[1] = Point(565, 532);
+ poly83.ps[2] = Point(545, 532);
+ poly83.ps[3] = Point(545, 512);
+ new ShapeRef(router, poly83, 83);
+
+ Polygon poly84(4);
+ poly84.ps[0] = Point(538, 531);
+ poly84.ps[1] = Point(538, 551);
+ poly84.ps[2] = Point(518, 551);
+ poly84.ps[3] = Point(518, 531);
+ new ShapeRef(router, poly84, 84);
+
+ Polygon poly85(4);
+ poly85.ps[0] = Point(272, 782);
+ poly85.ps[1] = Point(272, 802);
+ poly85.ps[2] = Point(252, 802);
+ poly85.ps[3] = Point(252, 782);
+ new ShapeRef(router, poly85, 85);
+
+ Polygon poly86(4);
+ poly86.ps[0] = Point(515, 512);
+ poly86.ps[1] = Point(515, 532);
+ poly86.ps[2] = Point(495, 532);
+ poly86.ps[3] = Point(495, 512);
+ new ShapeRef(router, poly86, 86);
+
+ Polygon poly87(4);
+ poly87.ps[0] = Point(391, 534);
+ poly87.ps[1] = Point(391, 574);
+ poly87.ps[2] = Point(351, 574);
+ poly87.ps[3] = Point(351, 534);
+ new ShapeRef(router, poly87, 87);
+
+ Polygon poly88(4);
+ poly88.ps[0] = Point(420, 573);
+ poly88.ps[1] = Point(420, 593);
+ poly88.ps[2] = Point(400, 593);
+ poly88.ps[3] = Point(400, 573);
+ new ShapeRef(router, poly88, 88);
+
+ Polygon poly89(4);
+ poly89.ps[0] = Point(421, 509);
+ poly89.ps[1] = Point(421, 529);
+ poly89.ps[2] = Point(401, 529);
+ poly89.ps[3] = Point(401, 509);
+ new ShapeRef(router, poly89, 89);
+
+ Polygon poly90(4);
+ poly90.ps[0] = Point(476, 426);
+ poly90.ps[1] = Point(476, 466);
+ poly90.ps[2] = Point(436, 466);
+ poly90.ps[3] = Point(436, 426);
+ new ShapeRef(router, poly90, 90);
+
+ Polygon poly91(4);
+ poly91.ps[0] = Point(290, 970);
+ poly91.ps[1] = Point(290, 1010);
+ poly91.ps[2] = Point(234, 1010);
+ poly91.ps[3] = Point(234, 970);
+ new ShapeRef(router, poly91, 91);
+
+ Polygon poly92(4);
+ poly92.ps[0] = Point(85, 888);
+ poly92.ps[1] = Point(85, 928);
+ poly92.ps[2] = Point(29, 928);
+ poly92.ps[3] = Point(29, 888);
+ new ShapeRef(router, poly92, 92);
+
+ Polygon poly93(4);
+ poly93.ps[0] = Point(290, 991);
+ poly93.ps[1] = Point(290, 1031);
+ poly93.ps[2] = Point(234, 1031);
+ poly93.ps[3] = Point(234, 991);
+ new ShapeRef(router, poly93, 93);
+
+ Polygon poly94(4);
+ poly94.ps[0] = Point(317, 889);
+ poly94.ps[1] = Point(317, 929);
+ poly94.ps[2] = Point(261, 929);
+ poly94.ps[3] = Point(261, 889);
+ new ShapeRef(router, poly94, 94);
+
+ Polygon poly95(4);
+ poly95.ps[0] = Point(488, 870);
+ poly95.ps[1] = Point(488, 910);
+ poly95.ps[2] = Point(432, 910);
+ poly95.ps[3] = Point(432, 870);
+ new ShapeRef(router, poly95, 95);
+
+ Polygon poly96(4);
+ poly96.ps[0] = Point(440, 970);
+ poly96.ps[1] = Point(440, 1010);
+ poly96.ps[2] = Point(384, 1010);
+ poly96.ps[3] = Point(384, 970);
+ new ShapeRef(router, poly96, 96);
+
+ Polygon poly97(4);
+ poly97.ps[0] = Point(370, 851);
+ poly97.ps[1] = Point(370, 891);
+ poly97.ps[2] = Point(314, 891);
+ poly97.ps[3] = Point(314, 851);
+ new ShapeRef(router, poly97, 97);
+
+ Polygon poly98(4);
+ poly98.ps[0] = Point(494, 830);
+ poly98.ps[1] = Point(494, 870);
+ poly98.ps[2] = Point(438, 870);
+ poly98.ps[3] = Point(438, 830);
+ new ShapeRef(router, poly98, 98);
+
+ Polygon poly99(4);
+ poly99.ps[0] = Point(258, 842);
+ poly99.ps[1] = Point(258, 882);
+ poly99.ps[2] = Point(202, 882);
+ poly99.ps[3] = Point(202, 842);
+ new ShapeRef(router, poly99, 99);
+
+ Polygon poly100(4);
+ poly100.ps[0] = Point(211, 792);
+ poly100.ps[1] = Point(211, 832);
+ poly100.ps[2] = Point(155, 832);
+ poly100.ps[3] = Point(155, 792);
+ new ShapeRef(router, poly100, 100);
+
+ Polygon poly101(4);
+ poly101.ps[0] = Point(559, 791);
+ poly101.ps[1] = Point(559, 831);
+ poly101.ps[2] = Point(503, 831);
+ poly101.ps[3] = Point(503, 791);
+ new ShapeRef(router, poly101, 101);
+
+ Polygon poly102(4);
+ poly102.ps[0] = Point(546, 747);
+ poly102.ps[1] = Point(546, 787);
+ poly102.ps[2] = Point(490, 787);
+ poly102.ps[3] = Point(490, 747);
+ new ShapeRef(router, poly102, 102);
+
+ Polygon poly103(4);
+ poly103.ps[0] = Point(422, 678);
+ poly103.ps[1] = Point(422, 718);
+ poly103.ps[2] = Point(366, 718);
+ poly103.ps[3] = Point(366, 678);
+ new ShapeRef(router, poly103, 103);
+
+ Polygon poly104(4);
+ poly104.ps[0] = Point(423, 606);
+ poly104.ps[1] = Point(423, 646);
+ poly104.ps[2] = Point(367, 646);
+ poly104.ps[3] = Point(367, 606);
+ new ShapeRef(router, poly104, 104);
+
+ Polygon poly105(4);
+ poly105.ps[0] = Point(397, 461);
+ poly105.ps[1] = Point(397, 501);
+ poly105.ps[2] = Point(341, 501);
+ poly105.ps[3] = Point(341, 461);
+ new ShapeRef(router, poly105, 105);
+
+ Polygon poly106(4);
+ poly106.ps[0] = Point(404, 377);
+ poly106.ps[1] = Point(404, 417);
+ poly106.ps[2] = Point(348, 417);
+ poly106.ps[3] = Point(348, 377);
+ new ShapeRef(router, poly106, 106);
+
+ Polygon poly107(4);
+ poly107.ps[0] = Point(546, 381);
+ poly107.ps[1] = Point(546, 421);
+ poly107.ps[2] = Point(490, 421);
+ poly107.ps[3] = Point(490, 381);
+ new ShapeRef(router, poly107, 107);
+
+ Polygon poly108(4);
+ poly108.ps[0] = Point(546, 315);
+ poly108.ps[1] = Point(546, 355);
+ poly108.ps[2] = Point(490, 355);
+ poly108.ps[3] = Point(490, 315);
+ new ShapeRef(router, poly108, 108);
+
+ Polygon poly109(4);
+ poly109.ps[0] = Point(431, 365);
+ poly109.ps[1] = Point(431, 405);
+ poly109.ps[2] = Point(375, 405);
+ poly109.ps[3] = Point(375, 365);
+ new ShapeRef(router, poly109, 109);
+
+ Polygon poly110(4);
+ poly110.ps[0] = Point(553, 122);
+ poly110.ps[1] = Point(553, 162);
+ poly110.ps[2] = Point(497, 162);
+ poly110.ps[3] = Point(497, 122);
+ new ShapeRef(router, poly110, 110);
+
+ Polygon poly111(4);
+ poly111.ps[0] = Point(546, 245);
+ poly111.ps[1] = Point(546, 285);
+ poly111.ps[2] = Point(490, 285);
+ poly111.ps[3] = Point(490, 245);
+ new ShapeRef(router, poly111, 111);
+
+ Polygon poly112(4);
+ poly112.ps[0] = Point(422, 150);
+ poly112.ps[1] = Point(422, 190);
+ poly112.ps[2] = Point(366, 190);
+ poly112.ps[3] = Point(366, 150);
+ new ShapeRef(router, poly112, 112);
+
+ Polygon poly113(4);
+ poly113.ps[0] = Point(404, 229);
+ poly113.ps[1] = Point(404, 269);
+ poly113.ps[2] = Point(348, 269);
+ poly113.ps[3] = Point(348, 229);
+ new ShapeRef(router, poly113, 113);
+
+ Polygon poly114(4);
+ poly114.ps[0] = Point(249, 210);
+ poly114.ps[1] = Point(249, 250);
+ poly114.ps[2] = Point(193, 250);
+ poly114.ps[3] = Point(193, 210);
+ new ShapeRef(router, poly114, 114);
+
+ Polygon poly115(4);
+ poly115.ps[0] = Point(249, 229);
+ poly115.ps[1] = Point(249, 269);
+ poly115.ps[2] = Point(193, 269);
+ poly115.ps[3] = Point(193, 229);
+ new ShapeRef(router, poly115, 115);
+
+ Polygon poly116(4);
+ poly116.ps[0] = Point(420, 246);
+ poly116.ps[1] = Point(420, 286);
+ poly116.ps[2] = Point(364, 286);
+ poly116.ps[3] = Point(364, 246);
+ new ShapeRef(router, poly116, 116);
+
+ Polygon poly117(4);
+ poly117.ps[0] = Point(246, 246);
+ poly117.ps[1] = Point(246, 286);
+ poly117.ps[2] = Point(190, 286);
+ poly117.ps[3] = Point(190, 246);
+ new ShapeRef(router, poly117, 117);
+
+ Polygon poly118(4);
+ poly118.ps[0] = Point(120, 241);
+ poly118.ps[1] = Point(120, 281);
+ poly118.ps[2] = Point(64, 281);
+ poly118.ps[3] = Point(64, 241);
+ new ShapeRef(router, poly118, 118);
+
+ Polygon poly119(4);
+ poly119.ps[0] = Point(249, 154);
+ poly119.ps[1] = Point(249, 194);
+ poly119.ps[2] = Point(193, 194);
+ poly119.ps[3] = Point(193, 154);
+ new ShapeRef(router, poly119, 119);
+
+ Polygon poly120(4);
+ poly120.ps[0] = Point(249, 135);
+ poly120.ps[1] = Point(249, 175);
+ poly120.ps[2] = Point(193, 175);
+ poly120.ps[3] = Point(193, 135);
+ new ShapeRef(router, poly120, 120);
+
+ Polygon poly121(4);
+ poly121.ps[0] = Point(317, 213);
+ poly121.ps[1] = Point(317, 253);
+ poly121.ps[2] = Point(261, 253);
+ poly121.ps[3] = Point(261, 213);
+ new ShapeRef(router, poly121, 121);
+
+ Polygon poly122(4);
+ poly122.ps[0] = Point(344, 81);
+ poly122.ps[1] = Point(344, 121);
+ poly122.ps[2] = Point(288, 121);
+ poly122.ps[3] = Point(288, 81);
+ new ShapeRef(router, poly122, 122);
+
+ Polygon poly123(4);
+ poly123.ps[0] = Point(344, 160);
+ poly123.ps[1] = Point(344, 200);
+ poly123.ps[2] = Point(288, 200);
+ poly123.ps[3] = Point(288, 160);
+ new ShapeRef(router, poly123, 123);
+
+ Polygon poly124(4);
+ poly124.ps[0] = Point(263, 835);
+ poly124.ps[1] = Point(263, 875);
+ poly124.ps[2] = Point(207, 875);
+ poly124.ps[3] = Point(207, 835);
+ new ShapeRef(router, poly124, 124);
+
+ Polygon poly125(4);
+ poly125.ps[0] = Point(422, 533);
+ poly125.ps[1] = Point(422, 573);
+ poly125.ps[2] = Point(366, 573);
+ poly125.ps[3] = Point(366, 533);
+ new ShapeRef(router, poly125, 125);
+
+ Polygon poly126(4);
+ poly126.ps[0] = Point(249, 173);
+ poly126.ps[1] = Point(249, 213);
+ poly126.ps[2] = Point(193, 213);
+ poly126.ps[3] = Point(193, 173);
+ new ShapeRef(router, poly126, 126);
+
+ Polygon poly127(4);
+ poly127.ps[0] = Point(249, 248);
+ poly127.ps[1] = Point(249, 288);
+ poly127.ps[2] = Point(193, 288);
+ poly127.ps[3] = Point(193, 248);
+ new ShapeRef(router, poly127, 127);
+
+ Polygon poly128(4);
+ poly128.ps[0] = Point(182, 287);
+ poly128.ps[1] = Point(182, 327);
+ poly128.ps[2] = Point(126, 327);
+ poly128.ps[3] = Point(126, 287);
+ new ShapeRef(router, poly128, 128);
+
+ Polygon poly129(4);
+ poly129.ps[0] = Point(182, 413);
+ poly129.ps[1] = Point(182, 453);
+ poly129.ps[2] = Point(126, 453);
+ poly129.ps[3] = Point(126, 413);
+ new ShapeRef(router, poly129, 129);
+
+ Polygon poly130(4);
+ poly130.ps[0] = Point(292, 286);
+ poly130.ps[1] = Point(292, 326);
+ poly130.ps[2] = Point(236, 326);
+ poly130.ps[3] = Point(236, 286);
+ new ShapeRef(router, poly130, 130);
+
+ Polygon poly131(4);
+ poly131.ps[0] = Point(292, 412);
+ poly131.ps[1] = Point(292, 452);
+ poly131.ps[2] = Point(236, 452);
+ poly131.ps[3] = Point(236, 412);
+ new ShapeRef(router, poly131, 131);
+
+ Polygon poly132(4);
+ poly132.ps[0] = Point(205, 653);
+ poly132.ps[1] = Point(205, 693);
+ poly132.ps[2] = Point(149, 693);
+ poly132.ps[3] = Point(149, 653);
+ new ShapeRef(router, poly132, 132);
+
+ Polygon poly133(4);
+ poly133.ps[0] = Point(440, 891);
+ poly133.ps[1] = Point(440, 931);
+ poly133.ps[2] = Point(384, 931);
+ poly133.ps[3] = Point(384, 891);
+ new ShapeRef(router, poly133, 133);
+
+ Polygon poly134(4);
+ poly134.ps[0] = Point(205, 674);
+ poly134.ps[1] = Point(205, 714);
+ poly134.ps[2] = Point(149, 714);
+ poly134.ps[3] = Point(149, 674);
+ new ShapeRef(router, poly134, 134);
+
+ Polygon poly135(4);
+ poly135.ps[0] = Point(488, 991);
+ poly135.ps[1] = Point(488, 1031);
+ poly135.ps[2] = Point(432, 1031);
+ poly135.ps[3] = Point(432, 991);
+ new ShapeRef(router, poly135, 135);
+
+ Polygon poly136(4);
+ poly136.ps[0] = Point(571, 461);
+ poly136.ps[1] = Point(571, 501);
+ poly136.ps[2] = Point(515, 501);
+ poly136.ps[3] = Point(515, 461);
+ new ShapeRef(router, poly136, 136);
+
+ Polygon poly137(4);
+ poly137.ps[0] = Point(583, 452);
+ poly137.ps[1] = Point(583, 492);
+ poly137.ps[2] = Point(527, 492);
+ poly137.ps[3] = Point(527, 452);
+ new ShapeRef(router, poly137, 137);
+
+ Polygon poly138(4);
+ poly138.ps[0] = Point(556, 571);
+ poly138.ps[1] = Point(556, 611);
+ poly138.ps[2] = Point(500, 611);
+ poly138.ps[3] = Point(500, 571);
+ new ShapeRef(router, poly138, 138);
+
+ Polygon poly139(4);
+ poly139.ps[0] = Point(290, 722);
+ poly139.ps[1] = Point(290, 762);
+ poly139.ps[2] = Point(234, 762);
+ poly139.ps[3] = Point(234, 722);
+ new ShapeRef(router, poly139, 139);
+
+ Polygon poly140(4);
+ poly140.ps[0] = Point(595, 502);
+ poly140.ps[1] = Point(595, 542);
+ poly140.ps[2] = Point(539, 542);
+ poly140.ps[3] = Point(539, 502);
+ new ShapeRef(router, poly140, 140);
+
+ Polygon poly141(4);
+ poly141.ps[0] = Point(438, 613);
+ poly141.ps[1] = Point(438, 653);
+ poly141.ps[2] = Point(382, 653);
+ poly141.ps[3] = Point(382, 613);
+ new ShapeRef(router, poly141, 141);
+
+ Polygon poly142(4);
+ poly142.ps[0] = Point(439, 449);
+ poly142.ps[1] = Point(439, 489);
+ poly142.ps[2] = Point(383, 489);
+ poly142.ps[3] = Point(383, 449);
+ new ShapeRef(router, poly142, 142);
+
+ ConnRef *connRef143 = new ConnRef(router, 143);
+ ConnEnd srcPt143(Point(262, 940), 15);
+ connRef143->setSourceEndpoint(srcPt143);
+ ConnEnd dstPt143(Point(119, 951), 15);
+ connRef143->setDestEndpoint(dstPt143);
+ connRef143->setRoutingType((ConnType)2);
+
+ ConnRef *connRef144 = new ConnRef(router, 144);
+ ConnEnd srcPt144(Point(262, 940), 15);
+ connRef144->setSourceEndpoint(srcPt144);
+ ConnEnd dstPt144(Point(351, 951), 15);
+ connRef144->setDestEndpoint(dstPt144);
+ connRef144->setRoutingType((ConnType)2);
+
+ ConnRef *connRef145 = new ConnRef(router, 145);
+ ConnEnd srcPt145(Point(119, 908), 15);
+ connRef145->setSourceEndpoint(srcPt145);
+ ConnEnd dstPt145(Point(119, 951), 15);
+ connRef145->setDestEndpoint(dstPt145);
+ connRef145->setRoutingType((ConnType)2);
+
+ ConnRef *connRef146 = new ConnRef(router, 146);
+ ConnEnd srcPt146(Point(119, 908), 15);
+ connRef146->setSourceEndpoint(srcPt146);
+ ConnEnd dstPt146(Point(119, 861), 15);
+ connRef146->setDestEndpoint(dstPt146);
+ connRef146->setRoutingType((ConnType)2);
+
+ ConnRef *connRef147 = new ConnRef(router, 147);
+ ConnEnd srcPt147(Point(262, 961), 15);
+ connRef147->setSourceEndpoint(srcPt147);
+ ConnEnd dstPt147(Point(119, 951), 15);
+ connRef147->setDestEndpoint(dstPt147);
+ connRef147->setRoutingType((ConnType)2);
+
+ ConnRef *connRef148 = new ConnRef(router, 148);
+ ConnEnd srcPt148(Point(262, 961), 15);
+ connRef148->setSourceEndpoint(srcPt148);
+ ConnEnd dstPt148(Point(351, 951), 15);
+ connRef148->setDestEndpoint(dstPt148);
+ connRef148->setRoutingType((ConnType)2);
+
+ ConnRef *connRef149 = new ConnRef(router, 149);
+ ConnEnd srcPt149(Point(629, 336), 15);
+ connRef149->setSourceEndpoint(srcPt149);
+ ConnEnd dstPt149(Point(456, 446), 15);
+ connRef149->setDestEndpoint(dstPt149);
+ connRef149->setRoutingType((ConnType)2);
+
+ ConnRef *connRef150 = new ConnRef(router, 150);
+ ConnEnd srcPt150(Point(351, 909), 15);
+ connRef150->setSourceEndpoint(srcPt150);
+ ConnEnd dstPt150(Point(351, 951), 15);
+ connRef150->setDestEndpoint(dstPt150);
+ connRef150->setRoutingType((ConnType)2);
+
+ ConnRef *connRef151 = new ConnRef(router, 151);
+ ConnEnd srcPt151(Point(460, 940), 15);
+ connRef151->setSourceEndpoint(srcPt151);
+ ConnEnd dstPt151(Point(351, 951), 15);
+ connRef151->setDestEndpoint(dstPt151);
+ connRef151->setRoutingType((ConnType)2);
+
+ ConnRef *connRef152 = new ConnRef(router, 152);
+ ConnEnd srcPt152(Point(412, 940), 15);
+ connRef152->setSourceEndpoint(srcPt152);
+ ConnEnd dstPt152(Point(351, 951), 15);
+ connRef152->setDestEndpoint(dstPt152);
+ connRef152->setRoutingType((ConnType)2);
+
+ ConnRef *connRef153 = new ConnRef(router, 153);
+ ConnEnd srcPt153(Point(404, 871), 15);
+ connRef153->setSourceEndpoint(srcPt153);
+ ConnEnd dstPt153(Point(351, 861), 15);
+ connRef153->setDestEndpoint(dstPt153);
+ connRef153->setRoutingType((ConnType)2);
+
+ ConnRef *connRef154 = new ConnRef(router, 154);
+ ConnEnd srcPt154(Point(404, 850), 15);
+ connRef154->setSourceEndpoint(srcPt154);
+ ConnEnd dstPt154(Point(351, 861), 15);
+ connRef154->setDestEndpoint(dstPt154);
+ connRef154->setRoutingType((ConnType)2);
+
+ ConnRef *connRef155 = new ConnRef(router, 155);
+ ConnEnd srcPt155(Point(292, 862), 15);
+ connRef155->setSourceEndpoint(srcPt155);
+ ConnEnd dstPt155(Point(351, 818), 15);
+ connRef155->setDestEndpoint(dstPt155);
+ connRef155->setRoutingType((ConnType)2);
+
+ ConnRef *connRef156 = new ConnRef(router, 156);
+ ConnEnd srcPt156(Point(292, 862), 15);
+ connRef156->setSourceEndpoint(srcPt156);
+ ConnEnd dstPt156(Point(238, 861), 15);
+ connRef156->setDestEndpoint(dstPt156);
+ connRef156->setRoutingType((ConnType)2);
+
+ ConnRef *connRef157 = new ConnRef(router, 157);
+ ConnEnd srcPt157(Point(183, 862), 15);
+ connRef157->setSourceEndpoint(srcPt157);
+ ConnEnd dstPt157(Point(119, 861), 15);
+ connRef157->setDestEndpoint(dstPt157);
+ connRef157->setRoutingType((ConnType)2);
+
+ ConnRef *connRef158 = new ConnRef(router, 158);
+ ConnEnd srcPt158(Point(183, 862), 15);
+ connRef158->setSourceEndpoint(srcPt158);
+ ConnEnd dstPt158(Point(238, 861), 15);
+ connRef158->setDestEndpoint(dstPt158);
+ connRef158->setRoutingType((ConnType)2);
+
+ ConnRef *connRef159 = new ConnRef(router, 159);
+ ConnEnd srcPt159(Point(183, 862), 15);
+ connRef159->setSourceEndpoint(srcPt159);
+ ConnEnd dstPt159(Point(185, 904), 15);
+ connRef159->setDestEndpoint(dstPt159);
+ connRef159->setRoutingType((ConnType)2);
+
+ ConnRef *connRef160 = new ConnRef(router, 160);
+ ConnEnd srcPt160(Point(531, 861), 15);
+ connRef160->setSourceEndpoint(srcPt160);
+ ConnEnd dstPt160(Point(600, 861), 15);
+ connRef160->setDestEndpoint(dstPt160);
+ connRef160->setRoutingType((ConnType)2);
+
+ ConnRef *connRef161 = new ConnRef(router, 161);
+ ConnEnd srcPt161(Point(531, 861), 15);
+ connRef161->setSourceEndpoint(srcPt161);
+ ConnEnd dstPt161(Point(456, 861), 15);
+ connRef161->setDestEndpoint(dstPt161);
+ connRef161->setRoutingType((ConnType)2);
+
+ ConnRef *connRef162 = new ConnRef(router, 162);
+ ConnEnd srcPt162(Point(456, 767), 15);
+ connRef162->setSourceEndpoint(srcPt162);
+ ConnEnd dstPt162(Point(456, 861), 15);
+ connRef162->setDestEndpoint(dstPt162);
+ connRef162->setRoutingType((ConnType)2);
+
+ ConnRef *connRef163 = new ConnRef(router, 163);
+ ConnEnd srcPt163(Point(456, 698), 15);
+ connRef163->setSourceEndpoint(srcPt163);
+ ConnEnd dstPt163(Point(456, 662), 15);
+ connRef163->setDestEndpoint(dstPt163);
+ connRef163->setRoutingType((ConnType)2);
+
+ ConnRef *connRef164 = new ConnRef(router, 164);
+ ConnEnd srcPt164(Point(456, 698), 15);
+ connRef164->setSourceEndpoint(srcPt164);
+ ConnEnd dstPt164(Point(456, 734), 15);
+ connRef164->setDestEndpoint(dstPt164);
+ connRef164->setRoutingType((ConnType)2);
+
+ ConnRef *connRef165 = new ConnRef(router, 165);
+ ConnEnd srcPt165(Point(457, 626), 15);
+ connRef165->setSourceEndpoint(srcPt165);
+ ConnEnd dstPt165(Point(456, 662), 15);
+ connRef165->setDestEndpoint(dstPt165);
+ connRef165->setRoutingType((ConnType)2);
+
+ ConnRef *connRef166 = new ConnRef(router, 166);
+ ConnEnd srcPt166(Point(457, 626), 15);
+ connRef166->setSourceEndpoint(srcPt166);
+ ConnEnd dstPt166(Point(456, 590), 15);
+ connRef166->setDestEndpoint(dstPt166);
+ connRef166->setRoutingType((ConnType)2);
+
+ ConnRef *connRef167 = new ConnRef(router, 167);
+ ConnEnd srcPt167(Point(431, 481), 15);
+ connRef167->setSourceEndpoint(srcPt167);
+ ConnEnd dstPt167(Point(456, 518), 15);
+ connRef167->setDestEndpoint(dstPt167);
+ connRef167->setRoutingType((ConnType)2);
+
+ ConnRef *connRef168 = new ConnRef(router, 168);
+ ConnEnd srcPt168(Point(431, 481), 15);
+ connRef168->setSourceEndpoint(srcPt168);
+ ConnEnd dstPt168(Point(456, 446), 15);
+ connRef168->setDestEndpoint(dstPt168);
+ connRef168->setRoutingType((ConnType)2);
+
+ ConnRef *connRef169 = new ConnRef(router, 169);
+ ConnEnd srcPt169(Point(376, 447), 15);
+ connRef169->setSourceEndpoint(srcPt169);
+ ConnEnd dstPt169(Point(305, 446), 15);
+ connRef169->setDestEndpoint(dstPt169);
+ connRef169->setRoutingType((ConnType)2);
+
+ ConnRef *connRef170 = new ConnRef(router, 170);
+ ConnEnd srcPt170(Point(376, 447), 15);
+ connRef170->setSourceEndpoint(srcPt170);
+ ConnEnd dstPt170(Point(456, 446), 15);
+ connRef170->setDestEndpoint(dstPt170);
+ connRef170->setRoutingType((ConnType)2);
+
+ ConnRef *connRef171 = new ConnRef(router, 171);
+ ConnEnd srcPt171(Point(456, 401), 15);
+ connRef171->setSourceEndpoint(srcPt171);
+ ConnEnd dstPt171(Point(305, 446), 15);
+ connRef171->setDestEndpoint(dstPt171);
+ connRef171->setRoutingType((ConnType)2);
+
+ ConnRef *connRef172 = new ConnRef(router, 172);
+ ConnEnd srcPt172(Point(456, 401), 15);
+ connRef172->setSourceEndpoint(srcPt172);
+ ConnEnd dstPt172(Point(456, 371), 15);
+ connRef172->setDestEndpoint(dstPt172);
+ connRef172->setRoutingType((ConnType)2);
+
+ ConnRef *connRef173 = new ConnRef(router, 173);
+ ConnEnd srcPt173(Point(456, 401), 15);
+ connRef173->setSourceEndpoint(srcPt173);
+ ConnEnd dstPt173(Point(456, 446), 15);
+ connRef173->setDestEndpoint(dstPt173);
+ connRef173->setRoutingType((ConnType)2);
+
+ ConnRef *connRef174 = new ConnRef(router, 174);
+ ConnEnd srcPt174(Point(456, 335), 15);
+ connRef174->setSourceEndpoint(srcPt174);
+ ConnEnd dstPt174(Point(456, 371), 15);
+ connRef174->setDestEndpoint(dstPt174);
+ connRef174->setRoutingType((ConnType)2);
+
+ ConnRef *connRef175 = new ConnRef(router, 175);
+ ConnEnd srcPt175(Point(403, 335), 15);
+ connRef175->setSourceEndpoint(srcPt175);
+ ConnEnd dstPt175(Point(456, 301), 15);
+ connRef175->setDestEndpoint(dstPt175);
+ connRef175->setRoutingType((ConnType)2);
+
+ ConnRef *connRef176 = new ConnRef(router, 176);
+ ConnEnd srcPt176(Point(525, 192), 15);
+ connRef176->setSourceEndpoint(srcPt176);
+ ConnEnd dstPt176(Point(456, 228), 15);
+ connRef176->setDestEndpoint(dstPt176);
+ connRef176->setRoutingType((ConnType)2);
+
+ ConnRef *connRef177 = new ConnRef(router, 177);
+ ConnEnd srcPt177(Point(456, 265), 15);
+ connRef177->setSourceEndpoint(srcPt177);
+ ConnEnd dstPt177(Point(456, 228), 15);
+ connRef177->setDestEndpoint(dstPt177);
+ connRef177->setRoutingType((ConnType)2);
+
+ ConnRef *connRef178 = new ConnRef(router, 178);
+ ConnEnd srcPt178(Point(456, 265), 15);
+ connRef178->setSourceEndpoint(srcPt178);
+ ConnEnd dstPt178(Point(456, 301), 15);
+ connRef178->setDestEndpoint(dstPt178);
+ connRef178->setRoutingType((ConnType)2);
+
+ ConnRef *connRef179 = new ConnRef(router, 179);
+ ConnEnd srcPt179(Point(456, 170), 15);
+ connRef179->setSourceEndpoint(srcPt179);
+ ConnEnd dstPt179(Point(456, 141), 15);
+ connRef179->setDestEndpoint(dstPt179);
+ connRef179->setRoutingType((ConnType)2);
+
+ ConnRef *connRef180 = new ConnRef(router, 180);
+ ConnEnd srcPt180(Point(456, 170), 15);
+ connRef180->setSourceEndpoint(srcPt180);
+ ConnEnd dstPt180(Point(456, 228), 15);
+ connRef180->setDestEndpoint(dstPt180);
+ connRef180->setRoutingType((ConnType)2);
+
+ ConnRef *connRef181 = new ConnRef(router, 181);
+ ConnEnd srcPt181(Point(376, 299), 15);
+ connRef181->setSourceEndpoint(srcPt181);
+ ConnEnd dstPt181(Point(305, 299), 15);
+ connRef181->setDestEndpoint(dstPt181);
+ connRef181->setRoutingType((ConnType)2);
+
+ ConnRef *connRef182 = new ConnRef(router, 182);
+ ConnEnd srcPt182(Point(376, 299), 15);
+ connRef182->setSourceEndpoint(srcPt182);
+ ConnEnd dstPt182(Point(456, 301), 15);
+ connRef182->setDestEndpoint(dstPt182);
+ connRef182->setRoutingType((ConnType)2);
+
+ ConnRef *connRef183 = new ConnRef(router, 183);
+ ConnEnd srcPt183(Point(221, 280), 15);
+ connRef183->setSourceEndpoint(srcPt183);
+ ConnEnd dstPt183(Point(154, 299), 15);
+ connRef183->setDestEndpoint(dstPt183);
+ connRef183->setRoutingType((ConnType)2);
+
+ ConnRef *connRef184 = new ConnRef(router, 184);
+ ConnEnd srcPt184(Point(221, 280), 15);
+ connRef184->setSourceEndpoint(srcPt184);
+ ConnEnd dstPt184(Point(305, 299), 15);
+ connRef184->setDestEndpoint(dstPt184);
+ connRef184->setRoutingType((ConnType)2);
+
+ ConnRef *connRef185 = new ConnRef(router, 185);
+ ConnEnd srcPt185(Point(221, 299), 15);
+ connRef185->setSourceEndpoint(srcPt185);
+ ConnEnd dstPt185(Point(154, 299), 15);
+ connRef185->setDestEndpoint(dstPt185);
+ connRef185->setRoutingType((ConnType)2);
+
+ ConnRef *connRef186 = new ConnRef(router, 186);
+ ConnEnd srcPt186(Point(221, 299), 15);
+ connRef186->setSourceEndpoint(srcPt186);
+ ConnEnd dstPt186(Point(305, 299), 15);
+ connRef186->setDestEndpoint(dstPt186);
+ connRef186->setRoutingType((ConnType)2);
+
+ ConnRef *connRef187 = new ConnRef(router, 187);
+ ConnEnd srcPt187(Point(330, 266), 15);
+ connRef187->setSourceEndpoint(srcPt187);
+ ConnEnd dstPt187(Point(305, 299), 15);
+ connRef187->setDestEndpoint(dstPt187);
+ connRef187->setRoutingType((ConnType)2);
+
+ ConnRef *connRef188 = new ConnRef(router, 188);
+ ConnEnd srcPt188(Point(330, 266), 15);
+ connRef188->setSourceEndpoint(srcPt188);
+ ConnEnd dstPt188(Point(456, 228), 15);
+ connRef188->setDestEndpoint(dstPt188);
+ connRef188->setRoutingType((ConnType)2);
+
+ ConnRef *connRef189 = new ConnRef(router, 189);
+ ConnEnd srcPt189(Point(280, 266), 15);
+ connRef189->setSourceEndpoint(srcPt189);
+ ConnEnd dstPt189(Point(305, 299), 15);
+ connRef189->setDestEndpoint(dstPt189);
+ connRef189->setRoutingType((ConnType)2);
+
+ ConnRef *connRef190 = new ConnRef(router, 190);
+ ConnEnd srcPt190(Point(280, 266), 15);
+ connRef190->setSourceEndpoint(srcPt190);
+ ConnEnd dstPt190(Point(456, 228), 15);
+ connRef190->setDestEndpoint(dstPt190);
+ connRef190->setRoutingType((ConnType)2);
+
+ ConnRef *connRef191 = new ConnRef(router, 191);
+ ConnEnd srcPt191(Point(154, 261), 15);
+ connRef191->setSourceEndpoint(srcPt191);
+ ConnEnd dstPt191(Point(154, 226), 15);
+ connRef191->setDestEndpoint(dstPt191);
+ connRef191->setRoutingType((ConnType)2);
+
+ ConnRef *connRef192 = new ConnRef(router, 192);
+ ConnEnd srcPt192(Point(154, 261), 15);
+ connRef192->setSourceEndpoint(srcPt192);
+ ConnEnd dstPt192(Point(154, 299), 15);
+ connRef192->setDestEndpoint(dstPt192);
+ connRef192->setRoutingType((ConnType)2);
+
+ ConnRef *connRef193 = new ConnRef(router, 193);
+ ConnEnd srcPt193(Point(221, 224), 15);
+ connRef193->setSourceEndpoint(srcPt193);
+ ConnEnd dstPt193(Point(456, 228), 15);
+ connRef193->setDestEndpoint(dstPt193);
+ connRef193->setRoutingType((ConnType)2);
+
+ ConnRef *connRef194 = new ConnRef(router, 194);
+ ConnEnd srcPt194(Point(221, 205), 15);
+ connRef194->setSourceEndpoint(srcPt194);
+ ConnEnd dstPt194(Point(456, 228), 15);
+ connRef194->setDestEndpoint(dstPt194);
+ connRef194->setRoutingType((ConnType)2);
+
+ ConnRef *connRef195 = new ConnRef(router, 195);
+ ConnEnd srcPt195(Point(289, 183), 15);
+ connRef195->setSourceEndpoint(srcPt195);
+ ConnEnd dstPt195(Point(154, 226), 15);
+ connRef195->setDestEndpoint(dstPt195);
+ connRef195->setRoutingType((ConnType)2);
+
+ ConnRef *connRef196 = new ConnRef(router, 196);
+ ConnEnd srcPt196(Point(289, 183), 15);
+ connRef196->setSourceEndpoint(srcPt196);
+ ConnEnd dstPt196(Point(456, 228), 15);
+ connRef196->setDestEndpoint(dstPt196);
+ connRef196->setRoutingType((ConnType)2);
+
+ ConnRef *connRef197 = new ConnRef(router, 197);
+ ConnEnd srcPt197(Point(316, 151), 15);
+ connRef197->setSourceEndpoint(srcPt197);
+ ConnEnd dstPt197(Point(154, 226), 15);
+ connRef197->setDestEndpoint(dstPt197);
+ connRef197->setRoutingType((ConnType)2);
+
+ ConnRef *connRef198 = new ConnRef(router, 198);
+ ConnEnd srcPt198(Point(316, 130), 15);
+ connRef198->setSourceEndpoint(srcPt198);
+ ConnEnd dstPt198(Point(154, 226), 15);
+ connRef198->setDestEndpoint(dstPt198);
+ connRef198->setRoutingType((ConnType)2);
+
+ ConnRef *connRef199 = new ConnRef(router, 199);
+ ConnEnd srcPt199(Point(235, 905), 15);
+ connRef199->setSourceEndpoint(srcPt199);
+ ConnEnd dstPt199(Point(287, 904), 15);
+ connRef199->setDestEndpoint(dstPt199);
+ connRef199->setRoutingType((ConnType)2);
+
+ ConnRef *connRef200 = new ConnRef(router, 200);
+ ConnEnd srcPt200(Point(456, 553), 15);
+ connRef200->setSourceEndpoint(srcPt200);
+ ConnEnd dstPt200(Point(456, 590), 15);
+ connRef200->setDestEndpoint(dstPt200);
+ connRef200->setRoutingType((ConnType)2);
+
+ ConnRef *connRef201 = new ConnRef(router, 201);
+ ConnEnd srcPt201(Point(456, 553), 15);
+ connRef201->setSourceEndpoint(srcPt201);
+ ConnEnd dstPt201(Point(456, 518), 15);
+ connRef201->setDestEndpoint(dstPt201);
+ connRef201->setRoutingType((ConnType)2);
+
+ ConnRef *connRef202 = new ConnRef(router, 202);
+ ConnEnd srcPt202(Point(221, 243), 15);
+ connRef202->setSourceEndpoint(srcPt202);
+ ConnEnd dstPt202(Point(456, 228), 15);
+ connRef202->setDestEndpoint(dstPt202);
+ connRef202->setRoutingType((ConnType)2);
+
+ ConnRef *connRef203 = new ConnRef(router, 203);
+ ConnEnd srcPt203(Point(221, 318), 15);
+ connRef203->setSourceEndpoint(srcPt203);
+ ConnEnd dstPt203(Point(305, 299), 15);
+ connRef203->setDestEndpoint(dstPt203);
+ connRef203->setRoutingType((ConnType)2);
+
+ ConnRef *connRef204 = new ConnRef(router, 204);
+ ConnEnd srcPt204(Point(154, 357), 15);
+ connRef204->setSourceEndpoint(srcPt204);
+ ConnEnd dstPt204(Point(212, 356), 15);
+ connRef204->setDestEndpoint(dstPt204);
+ connRef204->setRoutingType((ConnType)2);
+
+ ConnRef *connRef205 = new ConnRef(router, 205);
+ ConnEnd srcPt205(Point(154, 383), 15);
+ connRef205->setSourceEndpoint(srcPt205);
+ ConnEnd dstPt205(Point(212, 382), 15);
+ connRef205->setDestEndpoint(dstPt205);
+ connRef205->setRoutingType((ConnType)2);
+
+ ConnRef *connRef206 = new ConnRef(router, 206);
+ ConnEnd srcPt206(Point(264, 356), 15);
+ connRef206->setSourceEndpoint(srcPt206);
+ ConnEnd dstPt206(Point(305, 299), 15);
+ connRef206->setDestEndpoint(dstPt206);
+ connRef206->setRoutingType((ConnType)2);
+
+ ConnRef *connRef207 = new ConnRef(router, 207);
+ ConnEnd srcPt207(Point(264, 382), 15);
+ connRef207->setSourceEndpoint(srcPt207);
+ ConnEnd dstPt207(Point(305, 299), 15);
+ connRef207->setDestEndpoint(dstPt207);
+ connRef207->setRoutingType((ConnType)2);
+
+ ConnRef *connRef208 = new ConnRef(router, 208);
+ ConnEnd srcPt208(Point(574, 193), 15);
+ connRef208->setSourceEndpoint(srcPt208);
+ ConnEnd dstPt208(Point(525, 192), 15);
+ connRef208->setDestEndpoint(dstPt208);
+ connRef208->setRoutingType((ConnType)2);
+
+ ConnRef *connRef209 = new ConnRef(router, 209);
+ ConnEnd srcPt209(Point(456, 141), 15);
+ connRef209->setSourceEndpoint(srcPt209);
+ ConnEnd dstPt209(Point(458, 74), 15);
+ connRef209->setDestEndpoint(dstPt209);
+ connRef209->setRoutingType((ConnType)2);
+
+ ConnRef *connRef210 = new ConnRef(router, 210);
+ ConnEnd srcPt210(Point(456, 662), 15);
+ connRef210->setSourceEndpoint(srcPt210);
+ ConnEnd dstPt210(Point(629, 336), 15);
+ connRef210->setDestEndpoint(dstPt210);
+ connRef210->setRoutingType((ConnType)2);
+
+ ConnRef *connRef211 = new ConnRef(router, 211);
+ ConnEnd srcPt211(Point(154, 226), 15);
+ connRef211->setSourceEndpoint(srcPt211);
+ ConnEnd dstPt211(Point(221, 243), 15);
+ connRef211->setDestEndpoint(dstPt211);
+ connRef211->setRoutingType((ConnType)2);
+
+ ConnRef *connRef212 = new ConnRef(router, 212);
+ ConnEnd srcPt212(Point(221, 318), 15);
+ connRef212->setSourceEndpoint(srcPt212);
+ ConnEnd dstPt212(Point(154, 299), 15);
+ connRef212->setDestEndpoint(dstPt212);
+ connRef212->setRoutingType((ConnType)2);
+
+ ConnRef *connRef213 = new ConnRef(router, 213);
+ ConnEnd srcPt213(Point(456, 228), 15);
+ connRef213->setSourceEndpoint(srcPt213);
+ ConnEnd dstPt213(Point(629, 336), 15);
+ connRef213->setDestEndpoint(dstPt213);
+ connRef213->setRoutingType((ConnType)2);
+
+ ConnRef *connRef214 = new ConnRef(router, 214);
+ ConnEnd srcPt214(Point(456, 734), 15);
+ connRef214->setSourceEndpoint(srcPt214);
+ ConnEnd dstPt214(Point(49, 798), 15);
+ connRef214->setDestEndpoint(dstPt214);
+ connRef214->setRoutingType((ConnType)2);
+
+ ConnRef *connRef215 = new ConnRef(router, 215);
+ ConnEnd srcPt215(Point(177, 744), 15);
+ connRef215->setSourceEndpoint(srcPt215);
+ ConnEnd dstPt215(Point(456, 734), 15);
+ connRef215->setDestEndpoint(dstPt215);
+ connRef215->setRoutingType((ConnType)2);
+
+ ConnRef *connRef216 = new ConnRef(router, 216);
+ ConnEnd srcPt216(Point(456, 590), 15);
+ connRef216->setSourceEndpoint(srcPt216);
+ ConnEnd dstPt216(Point(278, 597), 15);
+ connRef216->setDestEndpoint(dstPt216);
+ connRef216->setRoutingType((ConnType)2);
+
+ ConnRef *connRef217 = new ConnRef(router, 217);
+ ConnEnd srcPt217(Point(555, 522), 15);
+ connRef217->setSourceEndpoint(srcPt217);
+ ConnEnd dstPt217(Point(456, 590), 15);
+ connRef217->setDestEndpoint(dstPt217);
+ connRef217->setRoutingType((ConnType)2);
+
+ ConnRef *connRef218 = new ConnRef(router, 218);
+ ConnEnd srcPt218(Point(528, 541), 15);
+ connRef218->setSourceEndpoint(srcPt218);
+ ConnEnd dstPt218(Point(456, 590), 15);
+ connRef218->setDestEndpoint(dstPt218);
+ connRef218->setRoutingType((ConnType)2);
+
+ ConnRef *connRef219 = new ConnRef(router, 219);
+ ConnEnd srcPt219(Point(505, 522), 15);
+ connRef219->setSourceEndpoint(srcPt219);
+ ConnEnd dstPt219(Point(456, 590), 15);
+ connRef219->setDestEndpoint(dstPt219);
+ connRef219->setRoutingType((ConnType)2);
+
+ ConnRef *connRef220 = new ConnRef(router, 220);
+ ConnEnd srcPt220(Point(481, 481), 15);
+ connRef220->setSourceEndpoint(srcPt220);
+ ConnEnd dstPt220(Point(456, 518), 15);
+ connRef220->setDestEndpoint(dstPt220);
+ connRef220->setRoutingType((ConnType)2);
+
+ ConnRef *connRef221 = new ConnRef(router, 221);
+ ConnEnd srcPt221(Point(411, 519), 15);
+ connRef221->setSourceEndpoint(srcPt221);
+ ConnEnd dstPt221(Point(456, 518), 15);
+ connRef221->setDestEndpoint(dstPt221);
+ connRef221->setRoutingType((ConnType)2);
+
+ ConnRef *connRef222 = new ConnRef(router, 222);
+ ConnEnd srcPt222(Point(600, 861), 15);
+ connRef222->setSourceEndpoint(srcPt222);
+ ConnEnd dstPt222(Point(601, 917), 15);
+ connRef222->setDestEndpoint(dstPt222);
+ connRef222->setRoutingType((ConnType)2);
+
+ ConnRef *connRef223 = new ConnRef(router, 223);
+ ConnEnd srcPt223(Point(460, 940), 15);
+ connRef223->setSourceEndpoint(srcPt223);
+ ConnEnd dstPt223(Point(523, 951), 15);
+ connRef223->setDestEndpoint(dstPt223);
+ connRef223->setRoutingType((ConnType)2);
+
+ ConnRef *connRef224 = new ConnRef(router, 224);
+ ConnEnd srcPt224(Point(412, 940), 15);
+ connRef224->setSourceEndpoint(srcPt224);
+ ConnEnd dstPt224(Point(523, 951), 15);
+ connRef224->setDestEndpoint(dstPt224);
+ connRef224->setRoutingType((ConnType)2);
+
+ ConnRef *connRef225 = new ConnRef(router, 225);
+ ConnEnd srcPt225(Point(523, 951), 15);
+ connRef225->setSourceEndpoint(srcPt225);
+ ConnEnd dstPt225(Point(412, 961), 15);
+ connRef225->setDestEndpoint(dstPt225);
+ connRef225->setRoutingType((ConnType)2);
+
+ ConnRef *connRef226 = new ConnRef(router, 226);
+ ConnEnd srcPt226(Point(460, 961), 15);
+ connRef226->setSourceEndpoint(srcPt226);
+ ConnEnd dstPt226(Point(523, 951), 15);
+ connRef226->setDestEndpoint(dstPt226);
+ connRef226->setRoutingType((ConnType)2);
+
+ ConnRef *connRef227 = new ConnRef(router, 227);
+ ConnEnd srcPt227(Point(456, 861), 15);
+ connRef227->setSourceEndpoint(srcPt227);
+ ConnEnd dstPt227(Point(629, 336), 15);
+ connRef227->setDestEndpoint(dstPt227);
+ connRef227->setRoutingType((ConnType)2);
+
+ ConnRef *connRef228 = new ConnRef(router, 228);
+ ConnEnd srcPt228(Point(456, 861), 15);
+ connRef228->setSourceEndpoint(srcPt228);
+ ConnEnd dstPt228(Point(49, 798), 15);
+ connRef228->setDestEndpoint(dstPt228);
+ connRef228->setRoutingType((ConnType)2);
+
+ ConnRef *connRef229 = new ConnRef(router, 229);
+ ConnEnd srcPt229(Point(262, 792), 15);
+ connRef229->setSourceEndpoint(srcPt229);
+ ConnEnd dstPt229(Point(456, 861), 15);
+ connRef229->setDestEndpoint(dstPt229);
+ connRef229->setRoutingType((ConnType)2);
+
+ ConnRef *connRef230 = new ConnRef(router, 230);
+ ConnEnd srcPt230(Point(351, 861), 15);
+ connRef230->setSourceEndpoint(srcPt230);
+ ConnEnd dstPt230(Point(351, 909), 15);
+ connRef230->setDestEndpoint(dstPt230);
+ connRef230->setRoutingType((ConnType)2);
+
+ ConnRef *connRef231 = new ConnRef(router, 231);
+ ConnEnd srcPt231(Point(351, 818), 15);
+ connRef231->setSourceEndpoint(srcPt231);
+ ConnEnd dstPt231(Point(404, 871), 15);
+ connRef231->setDestEndpoint(dstPt231);
+ connRef231->setRoutingType((ConnType)2);
+
+ ConnRef *connRef232 = new ConnRef(router, 232);
+ ConnEnd srcPt232(Point(351, 818), 15);
+ connRef232->setSourceEndpoint(srcPt232);
+ ConnEnd dstPt232(Point(404, 850), 15);
+ connRef232->setDestEndpoint(dstPt232);
+ connRef232->setRoutingType((ConnType)2);
+
+ ConnRef *connRef233 = new ConnRef(router, 233);
+ ConnEnd srcPt233(Point(119, 861), 15);
+ connRef233->setSourceEndpoint(srcPt233);
+ ConnEnd dstPt233(Point(49, 798), 15);
+ connRef233->setDestEndpoint(dstPt233);
+ connRef233->setRoutingType((ConnType)2);
+
+ ConnRef *connRef234 = new ConnRef(router, 234);
+ ConnEnd srcPt234(Point(262, 792), 15);
+ connRef234->setSourceEndpoint(srcPt234);
+ ConnEnd dstPt234(Point(119, 861), 15);
+ connRef234->setDestEndpoint(dstPt234);
+ connRef234->setRoutingType((ConnType)2);
+
+ ConnRef *connRef235 = new ConnRef(router, 235);
+ ConnEnd srcPt235(Point(412, 961), 15);
+ connRef235->setSourceEndpoint(srcPt235);
+ ConnEnd dstPt235(Point(351, 951), 15);
+ connRef235->setDestEndpoint(dstPt235);
+ connRef235->setRoutingType((ConnType)2);
+
+ ConnRef *connRef236 = new ConnRef(router, 236);
+ ConnEnd srcPt236(Point(460, 961), 15);
+ connRef236->setSourceEndpoint(srcPt236);
+ ConnEnd dstPt236(Point(351, 951), 15);
+ connRef236->setDestEndpoint(dstPt236);
+ connRef236->setRoutingType((ConnType)2);
+
+ ConnRef *connRef237 = new ConnRef(router, 237);
+ ConnEnd srcPt237(Point(235, 905), 15);
+ connRef237->setSourceEndpoint(srcPt237);
+ ConnEnd dstPt237(Point(185, 904), 15);
+ connRef237->setDestEndpoint(dstPt237);
+ connRef237->setRoutingType((ConnType)2);
+
+ ConnRef *connRef238 = new ConnRef(router, 238);
+ ConnEnd srcPt238(Point(456, 371), 15);
+ connRef238->setSourceEndpoint(srcPt238);
+ ConnEnd dstPt238(Point(403, 335), 15);
+ connRef238->setDestEndpoint(dstPt238);
+ connRef238->setRoutingType((ConnType)2);
+
+ ConnRef *connRef239 = new ConnRef(router, 239);
+ ConnEnd srcPt239(Point(105, 356), 15);
+ connRef239->setSourceEndpoint(srcPt239);
+ ConnEnd dstPt239(Point(154, 357), 15);
+ connRef239->setDestEndpoint(dstPt239);
+ connRef239->setRoutingType((ConnType)2);
+
+ ConnRef *connRef240 = new ConnRef(router, 240);
+ ConnEnd srcPt240(Point(212, 356), 15);
+ connRef240->setSourceEndpoint(srcPt240);
+ ConnEnd dstPt240(Point(264, 356), 15);
+ connRef240->setDestEndpoint(dstPt240);
+ connRef240->setRoutingType((ConnType)2);
+
+ ConnRef *connRef241 = new ConnRef(router, 241);
+ ConnEnd srcPt241(Point(212, 382), 15);
+ connRef241->setSourceEndpoint(srcPt241);
+ ConnEnd dstPt241(Point(264, 382), 15);
+ connRef241->setDestEndpoint(dstPt241);
+ connRef241->setRoutingType((ConnType)2);
+
+ ConnRef *connRef242 = new ConnRef(router, 242);
+ ConnEnd srcPt242(Point(105, 382), 15);
+ connRef242->setSourceEndpoint(srcPt242);
+ ConnEnd dstPt242(Point(154, 383), 15);
+ connRef242->setDestEndpoint(dstPt242);
+ connRef242->setRoutingType((ConnType)2);
+
+ ConnRef *connRef243 = new ConnRef(router, 243);
+ ConnEnd srcPt243(Point(49, 798), 15);
+ connRef243->setSourceEndpoint(srcPt243);
+ ConnEnd dstPt243(Point(119, 734), 15);
+ connRef243->setDestEndpoint(dstPt243);
+ connRef243->setRoutingType((ConnType)2);
+
+ ConnRef *connRef244 = new ConnRef(router, 244);
+ ConnEnd srcPt244(Point(177, 723), 15);
+ connRef244->setSourceEndpoint(srcPt244);
+ ConnEnd dstPt244(Point(456, 734), 15);
+ connRef244->setDestEndpoint(dstPt244);
+ connRef244->setRoutingType((ConnType)2);
+
+ ConnRef *connRef245 = new ConnRef(router, 245);
+ ConnEnd srcPt245(Point(119, 734), 15);
+ connRef245->setSourceEndpoint(srcPt245);
+ ConnEnd dstPt245(Point(177, 723), 15);
+ connRef245->setDestEndpoint(dstPt245);
+ connRef245->setRoutingType((ConnType)2);
+
+ ConnRef *connRef246 = new ConnRef(router, 246);
+ ConnEnd srcPt246(Point(119, 734), 15);
+ connRef246->setSourceEndpoint(srcPt246);
+ ConnEnd dstPt246(Point(177, 744), 15);
+ connRef246->setDestEndpoint(dstPt246);
+ connRef246->setRoutingType((ConnType)2);
+
+ ConnRef *connRef247 = new ConnRef(router, 247);
+ ConnEnd srcPt247(Point(481, 481), 15);
+ connRef247->setSourceEndpoint(srcPt247);
+ ConnEnd dstPt247(Point(456, 446), 15);
+ connRef247->setDestEndpoint(dstPt247);
+ connRef247->setRoutingType((ConnType)2);
+
+ ConnRef *connRef248 = new ConnRef(router, 248);
+ ConnEnd srcPt248(Point(410, 583), 15);
+ connRef248->setSourceEndpoint(srcPt248);
+ ConnEnd dstPt248(Point(371, 554), 15);
+ connRef248->setDestEndpoint(dstPt248);
+ connRef248->setRoutingType((ConnType)2);
+
+ ConnRef *connRef249 = new ConnRef(router, 249);
+ ConnEnd srcPt249(Point(410, 583), 15);
+ connRef249->setSourceEndpoint(srcPt249);
+ ConnEnd dstPt249(Point(456, 590), 15);
+ connRef249->setDestEndpoint(dstPt249);
+ connRef249->setRoutingType((ConnType)2);
+
+ ConnRef *connRef250 = new ConnRef(router, 250);
+ ConnEnd srcPt250(Point(411, 519), 15);
+ connRef250->setSourceEndpoint(srcPt250);
+ ConnEnd dstPt250(Point(371, 554), 15);
+ connRef250->setDestEndpoint(dstPt250);
+ connRef250->setRoutingType((ConnType)2);
+
+ ConnRef *connRef251 = new ConnRef(router, 251);
+ ConnEnd srcPt251(Point(456, 446), 15);
+ connRef251->setSourceEndpoint(srcPt251);
+ ConnEnd dstPt251(Point(555, 522), 15);
+ connRef251->setDestEndpoint(dstPt251);
+ connRef251->setRoutingType((ConnType)2);
+
+ ConnRef *connRef252 = new ConnRef(router, 252);
+ ConnEnd srcPt252(Point(456, 446), 15);
+ connRef252->setSourceEndpoint(srcPt252);
+ ConnEnd dstPt252(Point(528, 541), 15);
+ connRef252->setDestEndpoint(dstPt252);
+ connRef252->setRoutingType((ConnType)2);
+
+ ConnRef *connRef253 = new ConnRef(router, 253);
+ ConnEnd srcPt253(Point(456, 446), 15);
+ connRef253->setSourceEndpoint(srcPt253);
+ ConnEnd dstPt253(Point(505, 522), 15);
+ connRef253->setDestEndpoint(dstPt253);
+ connRef253->setRoutingType((ConnType)2);
+
+ ConnRef *connRef254 = new ConnRef(router, 254);
+ ConnEnd srcPt254(Point(262, 990), 15);
+ connRef254->setSourceEndpoint(srcPt254);
+ ConnEnd dstPt254(Point(262, 940), 15);
+ connRef254->setDestEndpoint(dstPt254);
+ connRef254->setRoutingType((ConnType)2);
+
+ ConnRef *connRef255 = new ConnRef(router, 255);
+ ConnEnd srcPt255(Point(57, 908), 15);
+ connRef255->setSourceEndpoint(srcPt255);
+ ConnEnd dstPt255(Point(119, 908), 15);
+ connRef255->setDestEndpoint(dstPt255);
+ connRef255->setRoutingType((ConnType)2);
+
+ ConnRef *connRef256 = new ConnRef(router, 256);
+ ConnEnd srcPt256(Point(262, 1011), 15);
+ connRef256->setSourceEndpoint(srcPt256);
+ ConnEnd dstPt256(Point(262, 961), 15);
+ connRef256->setDestEndpoint(dstPt256);
+ connRef256->setRoutingType((ConnType)2);
+
+ ConnRef *connRef257 = new ConnRef(router, 257);
+ ConnEnd srcPt257(Point(289, 909), 15);
+ connRef257->setSourceEndpoint(srcPt257);
+ ConnEnd dstPt257(Point(351, 909), 15);
+ connRef257->setDestEndpoint(dstPt257);
+ connRef257->setRoutingType((ConnType)2);
+
+ ConnRef *connRef258 = new ConnRef(router, 258);
+ ConnEnd srcPt258(Point(460, 890), 15);
+ connRef258->setSourceEndpoint(srcPt258);
+ ConnEnd dstPt258(Point(460, 940), 15);
+ connRef258->setDestEndpoint(dstPt258);
+ connRef258->setRoutingType((ConnType)2);
+
+ ConnRef *connRef259 = new ConnRef(router, 259);
+ ConnEnd srcPt259(Point(412, 990), 15);
+ connRef259->setSourceEndpoint(srcPt259);
+ ConnEnd dstPt259(Point(412, 940), 15);
+ connRef259->setDestEndpoint(dstPt259);
+ connRef259->setRoutingType((ConnType)2);
+
+ ConnRef *connRef260 = new ConnRef(router, 260);
+ ConnEnd srcPt260(Point(342, 871), 15);
+ connRef260->setSourceEndpoint(srcPt260);
+ ConnEnd dstPt260(Point(404, 871), 15);
+ connRef260->setDestEndpoint(dstPt260);
+ connRef260->setRoutingType((ConnType)2);
+
+ ConnRef *connRef261 = new ConnRef(router, 261);
+ ConnEnd srcPt261(Point(466, 850), 15);
+ connRef261->setSourceEndpoint(srcPt261);
+ ConnEnd dstPt261(Point(404, 850), 15);
+ connRef261->setDestEndpoint(dstPt261);
+ connRef261->setRoutingType((ConnType)2);
+
+ ConnRef *connRef262 = new ConnRef(router, 262);
+ ConnEnd srcPt262(Point(230, 862), 15);
+ connRef262->setSourceEndpoint(srcPt262);
+ ConnEnd dstPt262(Point(292, 862), 15);
+ connRef262->setDestEndpoint(dstPt262);
+ connRef262->setRoutingType((ConnType)2);
+
+ ConnRef *connRef263 = new ConnRef(router, 263);
+ ConnEnd srcPt263(Point(183, 812), 15);
+ connRef263->setSourceEndpoint(srcPt263);
+ ConnEnd dstPt263(Point(183, 862), 15);
+ connRef263->setDestEndpoint(dstPt263);
+ connRef263->setRoutingType((ConnType)2);
+
+ ConnRef *connRef264 = new ConnRef(router, 264);
+ ConnEnd srcPt264(Point(531, 811), 15);
+ connRef264->setSourceEndpoint(srcPt264);
+ ConnEnd dstPt264(Point(531, 861), 15);
+ connRef264->setDestEndpoint(dstPt264);
+ connRef264->setRoutingType((ConnType)2);
+
+ ConnRef *connRef265 = new ConnRef(router, 265);
+ ConnEnd srcPt265(Point(518, 767), 15);
+ connRef265->setSourceEndpoint(srcPt265);
+ ConnEnd dstPt265(Point(456, 767), 15);
+ connRef265->setDestEndpoint(dstPt265);
+ connRef265->setRoutingType((ConnType)2);
+
+ ConnRef *connRef266 = new ConnRef(router, 266);
+ ConnEnd srcPt266(Point(394, 698), 15);
+ connRef266->setSourceEndpoint(srcPt266);
+ ConnEnd dstPt266(Point(456, 698), 15);
+ connRef266->setDestEndpoint(dstPt266);
+ connRef266->setRoutingType((ConnType)2);
+
+ ConnRef *connRef267 = new ConnRef(router, 267);
+ ConnEnd srcPt267(Point(395, 626), 15);
+ connRef267->setSourceEndpoint(srcPt267);
+ ConnEnd dstPt267(Point(457, 626), 15);
+ connRef267->setDestEndpoint(dstPt267);
+ connRef267->setRoutingType((ConnType)2);
+
+ ConnRef *connRef268 = new ConnRef(router, 268);
+ ConnEnd srcPt268(Point(369, 481), 15);
+ connRef268->setSourceEndpoint(srcPt268);
+ ConnEnd dstPt268(Point(431, 481), 15);
+ connRef268->setDestEndpoint(dstPt268);
+ connRef268->setRoutingType((ConnType)2);
+
+ ConnRef *connRef269 = new ConnRef(router, 269);
+ ConnEnd srcPt269(Point(376, 397), 15);
+ connRef269->setSourceEndpoint(srcPt269);
+ ConnEnd dstPt269(Point(376, 447), 15);
+ connRef269->setDestEndpoint(dstPt269);
+ connRef269->setRoutingType((ConnType)2);
+
+ ConnRef *connRef270 = new ConnRef(router, 270);
+ ConnEnd srcPt270(Point(518, 401), 15);
+ connRef270->setSourceEndpoint(srcPt270);
+ ConnEnd dstPt270(Point(456, 401), 15);
+ connRef270->setDestEndpoint(dstPt270);
+ connRef270->setRoutingType((ConnType)2);
+
+ ConnRef *connRef271 = new ConnRef(router, 271);
+ ConnEnd srcPt271(Point(518, 335), 15);
+ connRef271->setSourceEndpoint(srcPt271);
+ ConnEnd dstPt271(Point(456, 335), 15);
+ connRef271->setDestEndpoint(dstPt271);
+ connRef271->setRoutingType((ConnType)2);
+
+ ConnRef *connRef272 = new ConnRef(router, 272);
+ ConnEnd srcPt272(Point(403, 385), 15);
+ connRef272->setSourceEndpoint(srcPt272);
+ ConnEnd dstPt272(Point(403, 335), 15);
+ connRef272->setDestEndpoint(dstPt272);
+ connRef272->setRoutingType((ConnType)2);
+
+ ConnRef *connRef273 = new ConnRef(router, 273);
+ ConnEnd srcPt273(Point(525, 142), 15);
+ connRef273->setSourceEndpoint(srcPt273);
+ ConnEnd dstPt273(Point(525, 192), 15);
+ connRef273->setDestEndpoint(dstPt273);
+ connRef273->setRoutingType((ConnType)2);
+
+ ConnRef *connRef274 = new ConnRef(router, 274);
+ ConnEnd srcPt274(Point(518, 265), 15);
+ connRef274->setSourceEndpoint(srcPt274);
+ ConnEnd dstPt274(Point(456, 265), 15);
+ connRef274->setDestEndpoint(dstPt274);
+ connRef274->setRoutingType((ConnType)2);
+
+ ConnRef *connRef275 = new ConnRef(router, 275);
+ ConnEnd srcPt275(Point(394, 170), 15);
+ connRef275->setSourceEndpoint(srcPt275);
+ ConnEnd dstPt275(Point(456, 170), 15);
+ connRef275->setDestEndpoint(dstPt275);
+ connRef275->setRoutingType((ConnType)2);
+
+ ConnRef *connRef276 = new ConnRef(router, 276);
+ ConnEnd srcPt276(Point(376, 249), 15);
+ connRef276->setSourceEndpoint(srcPt276);
+ ConnEnd dstPt276(Point(376, 299), 15);
+ connRef276->setDestEndpoint(dstPt276);
+ connRef276->setRoutingType((ConnType)2);
+
+ ConnRef *connRef277 = new ConnRef(router, 277);
+ ConnEnd srcPt277(Point(221, 230), 15);
+ connRef277->setSourceEndpoint(srcPt277);
+ ConnEnd dstPt277(Point(221, 280), 15);
+ connRef277->setDestEndpoint(dstPt277);
+ connRef277->setRoutingType((ConnType)2);
+
+ ConnRef *connRef278 = new ConnRef(router, 278);
+ ConnEnd srcPt278(Point(221, 249), 15);
+ connRef278->setSourceEndpoint(srcPt278);
+ ConnEnd dstPt278(Point(221, 299), 15);
+ connRef278->setDestEndpoint(dstPt278);
+ connRef278->setRoutingType((ConnType)2);
+
+ ConnRef *connRef279 = new ConnRef(router, 279);
+ ConnEnd srcPt279(Point(392, 266), 15);
+ connRef279->setSourceEndpoint(srcPt279);
+ ConnEnd dstPt279(Point(330, 266), 15);
+ connRef279->setDestEndpoint(dstPt279);
+ connRef279->setRoutingType((ConnType)2);
+
+ ConnRef *connRef280 = new ConnRef(router, 280);
+ ConnEnd srcPt280(Point(218, 266), 15);
+ connRef280->setSourceEndpoint(srcPt280);
+ ConnEnd dstPt280(Point(280, 266), 15);
+ connRef280->setDestEndpoint(dstPt280);
+ connRef280->setRoutingType((ConnType)2);
+
+ ConnRef *connRef281 = new ConnRef(router, 281);
+ ConnEnd srcPt281(Point(92, 261), 15);
+ connRef281->setSourceEndpoint(srcPt281);
+ ConnEnd dstPt281(Point(154, 261), 15);
+ connRef281->setDestEndpoint(dstPt281);
+ connRef281->setRoutingType((ConnType)2);
+
+ ConnRef *connRef282 = new ConnRef(router, 282);
+ ConnEnd srcPt282(Point(221, 174), 15);
+ connRef282->setSourceEndpoint(srcPt282);
+ ConnEnd dstPt282(Point(221, 224), 15);
+ connRef282->setDestEndpoint(dstPt282);
+ connRef282->setRoutingType((ConnType)2);
+
+ ConnRef *connRef283 = new ConnRef(router, 283);
+ ConnEnd srcPt283(Point(221, 155), 15);
+ connRef283->setSourceEndpoint(srcPt283);
+ ConnEnd dstPt283(Point(221, 205), 15);
+ connRef283->setDestEndpoint(dstPt283);
+ connRef283->setRoutingType((ConnType)2);
+
+ ConnRef *connRef284 = new ConnRef(router, 284);
+ ConnEnd srcPt284(Point(289, 233), 15);
+ connRef284->setSourceEndpoint(srcPt284);
+ ConnEnd dstPt284(Point(289, 183), 15);
+ connRef284->setDestEndpoint(dstPt284);
+ connRef284->setRoutingType((ConnType)2);
+
+ ConnRef *connRef285 = new ConnRef(router, 285);
+ ConnEnd srcPt285(Point(316, 101), 15);
+ connRef285->setSourceEndpoint(srcPt285);
+ ConnEnd dstPt285(Point(316, 151), 15);
+ connRef285->setDestEndpoint(dstPt285);
+ connRef285->setRoutingType((ConnType)2);
+
+ ConnRef *connRef286 = new ConnRef(router, 286);
+ ConnEnd srcPt286(Point(316, 180), 15);
+ connRef286->setSourceEndpoint(srcPt286);
+ ConnEnd dstPt286(Point(316, 130), 15);
+ connRef286->setDestEndpoint(dstPt286);
+ connRef286->setRoutingType((ConnType)2);
+
+ ConnRef *connRef287 = new ConnRef(router, 287);
+ ConnEnd srcPt287(Point(235, 855), 15);
+ connRef287->setSourceEndpoint(srcPt287);
+ ConnEnd dstPt287(Point(235, 905), 15);
+ connRef287->setDestEndpoint(dstPt287);
+ connRef287->setRoutingType((ConnType)2);
+
+ ConnRef *connRef288 = new ConnRef(router, 288);
+ ConnEnd srcPt288(Point(394, 553), 15);
+ connRef288->setSourceEndpoint(srcPt288);
+ ConnEnd dstPt288(Point(456, 553), 15);
+ connRef288->setDestEndpoint(dstPt288);
+ connRef288->setRoutingType((ConnType)2);
+
+ ConnRef *connRef289 = new ConnRef(router, 289);
+ ConnEnd srcPt289(Point(221, 193), 15);
+ connRef289->setSourceEndpoint(srcPt289);
+ ConnEnd dstPt289(Point(221, 243), 15);
+ connRef289->setDestEndpoint(dstPt289);
+ connRef289->setRoutingType((ConnType)2);
+
+ ConnRef *connRef290 = new ConnRef(router, 290);
+ ConnEnd srcPt290(Point(221, 268), 15);
+ connRef290->setSourceEndpoint(srcPt290);
+ ConnEnd dstPt290(Point(221, 318), 15);
+ connRef290->setDestEndpoint(dstPt290);
+ connRef290->setRoutingType((ConnType)2);
+
+ ConnRef *connRef291 = new ConnRef(router, 291);
+ ConnEnd srcPt291(Point(154, 307), 15);
+ connRef291->setSourceEndpoint(srcPt291);
+ ConnEnd dstPt291(Point(154, 357), 15);
+ connRef291->setDestEndpoint(dstPt291);
+ connRef291->setRoutingType((ConnType)2);
+
+ ConnRef *connRef292 = new ConnRef(router, 292);
+ ConnEnd srcPt292(Point(154, 433), 15);
+ connRef292->setSourceEndpoint(srcPt292);
+ ConnEnd dstPt292(Point(154, 383), 15);
+ connRef292->setDestEndpoint(dstPt292);
+ connRef292->setRoutingType((ConnType)2);
+
+ ConnRef *connRef293 = new ConnRef(router, 293);
+ ConnEnd srcPt293(Point(264, 306), 15);
+ connRef293->setSourceEndpoint(srcPt293);
+ ConnEnd dstPt293(Point(264, 356), 15);
+ connRef293->setDestEndpoint(dstPt293);
+ connRef293->setRoutingType((ConnType)2);
+
+ ConnRef *connRef294 = new ConnRef(router, 294);
+ ConnEnd srcPt294(Point(264, 432), 15);
+ connRef294->setSourceEndpoint(srcPt294);
+ ConnEnd dstPt294(Point(264, 382), 15);
+ connRef294->setDestEndpoint(dstPt294);
+ connRef294->setRoutingType((ConnType)2);
+
+ ConnRef *connRef295 = new ConnRef(router, 295);
+ ConnEnd srcPt295(Point(177, 673), 15);
+ connRef295->setSourceEndpoint(srcPt295);
+ ConnEnd dstPt295(Point(177, 723), 15);
+ connRef295->setDestEndpoint(dstPt295);
+ connRef295->setRoutingType((ConnType)2);
+
+ ConnRef *connRef296 = new ConnRef(router, 296);
+ ConnEnd srcPt296(Point(412, 911), 15);
+ connRef296->setSourceEndpoint(srcPt296);
+ ConnEnd dstPt296(Point(412, 961), 15);
+ connRef296->setDestEndpoint(dstPt296);
+ connRef296->setRoutingType((ConnType)2);
+
+ ConnRef *connRef297 = new ConnRef(router, 297);
+ ConnEnd srcPt297(Point(177, 694), 15);
+ connRef297->setSourceEndpoint(srcPt297);
+ ConnEnd dstPt297(Point(177, 744), 15);
+ connRef297->setDestEndpoint(dstPt297);
+ connRef297->setRoutingType((ConnType)2);
+
+ ConnRef *connRef298 = new ConnRef(router, 298);
+ ConnEnd srcPt298(Point(460, 1011), 15);
+ connRef298->setSourceEndpoint(srcPt298);
+ ConnEnd dstPt298(Point(460, 961), 15);
+ connRef298->setDestEndpoint(dstPt298);
+ connRef298->setRoutingType((ConnType)2);
+
+ ConnRef *connRef299 = new ConnRef(router, 299);
+ ConnEnd srcPt299(Point(543, 481), 15);
+ connRef299->setSourceEndpoint(srcPt299);
+ ConnEnd dstPt299(Point(481, 481), 15);
+ connRef299->setDestEndpoint(dstPt299);
+ connRef299->setRoutingType((ConnType)2);
+
+ ConnRef *connRef300 = new ConnRef(router, 300);
+ ConnEnd srcPt300(Point(555, 472), 15);
+ connRef300->setSourceEndpoint(srcPt300);
+ ConnEnd dstPt300(Point(555, 522), 15);
+ connRef300->setDestEndpoint(dstPt300);
+ connRef300->setRoutingType((ConnType)2);
+
+ ConnRef *connRef301 = new ConnRef(router, 301);
+ ConnEnd srcPt301(Point(528, 591), 15);
+ connRef301->setSourceEndpoint(srcPt301);
+ ConnEnd dstPt301(Point(528, 541), 15);
+ connRef301->setDestEndpoint(dstPt301);
+ connRef301->setRoutingType((ConnType)2);
+
+ ConnRef *connRef302 = new ConnRef(router, 302);
+ ConnEnd srcPt302(Point(262, 742), 15);
+ connRef302->setSourceEndpoint(srcPt302);
+ ConnEnd dstPt302(Point(262, 792), 15);
+ connRef302->setDestEndpoint(dstPt302);
+ connRef302->setRoutingType((ConnType)2);
+
+ ConnRef *connRef303 = new ConnRef(router, 303);
+ ConnEnd srcPt303(Point(567, 522), 15);
+ connRef303->setSourceEndpoint(srcPt303);
+ ConnEnd dstPt303(Point(505, 522), 15);
+ connRef303->setDestEndpoint(dstPt303);
+ connRef303->setRoutingType((ConnType)2);
+
+ ConnRef *connRef304 = new ConnRef(router, 304);
+ ConnEnd srcPt304(Point(410, 633), 15);
+ connRef304->setSourceEndpoint(srcPt304);
+ ConnEnd dstPt304(Point(410, 583), 15);
+ connRef304->setDestEndpoint(dstPt304);
+ connRef304->setRoutingType((ConnType)2);
+
+ ConnRef *connRef305 = new ConnRef(router, 305);
+ ConnEnd srcPt305(Point(411, 469), 15);
+ connRef305->setSourceEndpoint(srcPt305);
+ ConnEnd dstPt305(Point(411, 519), 15);
+ connRef305->setDestEndpoint(dstPt305);
+ connRef305->setRoutingType((ConnType)2);
+
+ ConnRef *connRef306 = new ConnRef(router, 306);
+ ConnEnd srcPt306(Point(456, 861), 15);
+ connRef306->setSourceEndpoint(srcPt306);
+ ConnEnd dstPt306(Point(404, 871), 15);
+ connRef306->setDestEndpoint(dstPt306);
+ connRef306->setRoutingType((ConnType)2);
+
+ ConnRef *connRef307 = new ConnRef(router, 307);
+ ConnEnd srcPt307(Point(456, 861), 15);
+ connRef307->setSourceEndpoint(srcPt307);
+ ConnEnd dstPt307(Point(404, 850), 15);
+ connRef307->setDestEndpoint(dstPt307);
+ connRef307->setRoutingType((ConnType)2);
+
+ ConnRef *connRef308 = new ConnRef(router, 308);
+ ConnEnd srcPt308(Point(287, 904), 15);
+ connRef308->setSourceEndpoint(srcPt308);
+ ConnEnd dstPt308(Point(292, 862), 15);
+ connRef308->setDestEndpoint(dstPt308);
+ connRef308->setRoutingType((ConnType)2);
+
+ ConnRef *connRef309 = new ConnRef(router, 309);
+ ConnEnd srcPt309(Point(351, 861), 15);
+ connRef309->setSourceEndpoint(srcPt309);
+ ConnEnd dstPt309(Point(292, 862), 15);
+ connRef309->setDestEndpoint(dstPt309);
+ connRef309->setRoutingType((ConnType)2);
+
+ ConnRef *connRef310 = new ConnRef(router, 310);
+ ConnEnd srcPt310(Point(456, 734), 15);
+ connRef310->setSourceEndpoint(srcPt310);
+ ConnEnd dstPt310(Point(456, 767), 15);
+ connRef310->setDestEndpoint(dstPt310);
+ connRef310->setRoutingType((ConnType)2);
+
+ ConnRef *connRef311 = new ConnRef(router, 311);
+ ConnEnd srcPt311(Point(456, 301), 15);
+ connRef311->setSourceEndpoint(srcPt311);
+ ConnEnd dstPt311(Point(456, 335), 15);
+ connRef311->setDestEndpoint(dstPt311);
+ connRef311->setRoutingType((ConnType)2);
+
+ ConnRef *connRef312 = new ConnRef(router, 312);
+ ConnEnd srcPt312(Point(154, 226), 15);
+ connRef312->setSourceEndpoint(srcPt312);
+ ConnEnd dstPt312(Point(221, 224), 15);
+ connRef312->setDestEndpoint(dstPt312);
+ connRef312->setRoutingType((ConnType)2);
+
+ ConnRef *connRef313 = new ConnRef(router, 313);
+ ConnEnd srcPt313(Point(154, 226), 15);
+ connRef313->setSourceEndpoint(srcPt313);
+ ConnEnd dstPt313(Point(221, 205), 15);
+ connRef313->setDestEndpoint(dstPt313);
+ connRef313->setRoutingType((ConnType)2);
+
+ ConnRef *connRef314 = new ConnRef(router, 314);
+ ConnEnd srcPt314(Point(456, 141), 15);
+ connRef314->setSourceEndpoint(srcPt314);
+ ConnEnd dstPt314(Point(316, 151), 15);
+ connRef314->setDestEndpoint(dstPt314);
+ connRef314->setRoutingType((ConnType)2);
+
+ ConnRef *connRef315 = new ConnRef(router, 315);
+ ConnEnd srcPt315(Point(456, 141), 15);
+ connRef315->setSourceEndpoint(srcPt315);
+ ConnEnd dstPt315(Point(316, 130), 15);
+ connRef315->setDestEndpoint(dstPt315);
+ connRef315->setRoutingType((ConnType)2);
+
+ router->processTransaction();
+ router->outputDiagram("output/vertlineassertion");
+ delete router;
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libavoid/timer.cpp b/src/3rdparty/adaptagrams/libavoid/timer.cpp
new file mode 100644
index 0000000..142c4ad
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/timer.cpp
@@ -0,0 +1,188 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2013 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+
+#include <cstdio>
+#include <cstdlib>
+#include <climits>
+
+#include "libavoid/timer.h"
+#include "libavoid/debug.h"
+#include "libavoid/assertions.h"
+
+namespace Avoid {
+
+#ifdef AVOID_PROFILE
+
+Timer::Timer()
+{
+ reset();
+}
+
+
+void Timer::reset(void)
+{
+ for (size_t i = 0; i < tmCount; ++i)
+ {
+ m_total_time[i] = 0;
+ m_tally[i] = 0;
+ m_max_time[i] = 0;
+ for (size_t j = 0; j < TIMER_VARIABLES_COUNT; ++j)
+ {
+ m_variables[i][j] = 0;
+ }
+ }
+ m_is_running = false;
+ m_type = m_last_type = tmCount;
+}
+
+
+void Timer::initialise(const TimerIndex t)
+{
+ COLA_ASSERT(t != tmCount);
+ COLA_ASSERT(m_type == tmCount);
+
+ m_type = t;
+}
+
+void Timer::start(void)
+{
+ COLA_ASSERT(!m_is_running);
+ m_start_time[m_type] = clock(); // CPU time
+ m_is_running = true;
+}
+
+
+void Timer::stop(void)
+{
+ COLA_ASSERT(m_is_running);
+ clock_t stopTime = clock(); // CPU time
+ m_is_running = false;
+
+ bigclock_t timeDiff;
+ if (stopTime < m_start_time[m_type])
+ {
+ // Uh-oh, the clock value has wrapped around.
+ //
+ bigclock_t realStopTime = ((bigclock_t) stopTime) + ULONG_MAX + 1;
+ timeDiff = realStopTime - m_start_time[m_type];
+ }
+ else
+ {
+ timeDiff = stopTime - m_start_time[m_type];
+ }
+
+ COLA_ASSERT(timeDiff < LONG_MAX);
+
+ m_total_time[m_type] += timeDiff;
+ m_tally[m_type]++;
+ if (((clock_t) timeDiff) > m_max_time[m_type])
+ {
+ m_max_time[m_type] = (clock_t) timeDiff;
+ }
+ m_last_type = m_type;
+
+ m_type = tmCount;
+}
+
+static const char* timerNames[] =
+{
+ "Adds",
+ "Dels",
+ "Movs",
+ "Pths",
+ "OrthogGraph",
+ "OrthogRoute",
+ "OrthogCentre",
+ "OrthogNudge",
+ "HyperedgeForest",
+ "HyperedgeMTST",
+ "HyperedgeImprove",
+ "HyperedgeAlt"
+};
+
+
+void Timer::printAll(FILE *fp)
+{
+ for (unsigned int i = 0; i < tmCount; i++)
+ {
+ fprintf(fp, "%s: ", timerNames[i]);
+ print((TimerIndex) i, fp);
+ }
+ fprintf(fp, "\n");
+}
+
+#define toMsec(tot) ((bigclock_t) ((tot) / (((double) CLOCKS_PER_SEC) / 1000)))
+#define toAvg(tot, cnt) ((((cnt) > 0) ? ((long double) (tot)) / (cnt) : 0))
+
+void Timer::printHyperedgePaper(FILE *fp)
+{
+ fprintf(fp, "%5lld & %5lld & %5lld & %5lld\n\n",
+ toMsec(m_total_time[tmOrthogGraph]),
+ toMsec(m_total_time[tmHyperedgeForest] + m_total_time[tmHyperedgeMTST]),
+ toMsec(m_total_time[tmHyperedgeAlt]),
+ toMsec(m_total_time[tmHyperedgeImprove]));
+}
+
+void Timer::print(const TimerIndex t, FILE *fp)
+{
+ bigclock_t avg = toMsec(toAvg(m_total_time[t], m_tally[t]));
+ clock_t max = toMsec(m_max_time[t]);
+ fprintf(fp, "%lld %d %lld %ld",
+ toMsec(m_total_time[t]), m_tally[t], avg, max);
+
+ for (size_t j = 0; j < TIMER_VARIABLES_COUNT; ++j)
+ {
+ if (m_variables[t][j] > 0)
+ {
+ fprintf(fp, ", %lu: %u", j, m_variables[t][j]);
+ }
+ }
+ fprintf(fp, "\n");
+}
+
+void Timer::varIncrement(size_t i, unsigned int val)
+{
+ COLA_ASSERT(i < TIMER_VARIABLES_COUNT);
+
+ if (m_is_running)
+ {
+ m_variables[m_type][i] += val;
+ }
+}
+
+void Timer::varMax(size_t i, unsigned int val)
+{
+ COLA_ASSERT(i < TIMER_VARIABLES_COUNT);
+
+ if (m_is_running)
+ {
+ m_variables[m_type][i] = std::max(m_variables[m_type][i], val);
+ }
+}
+
+#endif
+
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/timer.h b/src/3rdparty/adaptagrams/libavoid/timer.h
new file mode 100644
index 0000000..17a07d5
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/timer.h
@@ -0,0 +1,104 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2013 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+
+#ifndef AVOID_TIMER_H
+#define AVOID_TIMER_H
+
+#include <ctime>
+
+namespace Avoid {
+
+//#define AVOID_PROFILE
+
+#ifndef AVOID_PROFILE
+
+ #define TIMER_START(r, t) do {} while(0)
+ #define TIMER_STOP(r) do {} while(0)
+ #define TIMER_VAR_ADD(r, n, v) do {} while(0)
+ #define TIMER_VAR_MAX(r, n, v) do {} while(0)
+
+#else
+
+ #define TIMER_START(r, t) r->timers.initialise(t); r->timers.start()
+ #define TIMER_STOP(r) r->timers.stop()
+ #define TIMER_VAR_ADD(r, n, v) r->timers.varIncrement(n, v);
+ #define TIMER_VAR_MAX(r, n, v) r->timers.varMax(n, v)
+
+typedef unsigned long long int bigclock_t;
+
+enum TimerIndex
+{
+ tmAdd,
+ tmDel,
+ tmMov,
+ tmPth,
+ tmOrthogGraph,
+ tmOrthogRoute,
+ tmOrthogCentre,
+ tmOrthogNudge,
+ tmHyperedgeForest,
+ tmHyperedgeMTST,
+ tmHyperedgeImprove,
+ tmHyperedgeAlt,
+ tmCount
+};
+
+static const bool timerStart = true;
+static const bool timerDelay = false;
+
+static const size_t TIMER_VARIABLES_COUNT = 2;
+
+class Timer
+{
+ public:
+ Timer();
+ void initialise(const TimerIndex t);
+ void start(void);
+ void stop(void);
+ void reset(void);
+ void varIncrement(size_t i, unsigned int val);
+ void varMax(size_t i, unsigned int val);
+
+ void print(TimerIndex, FILE *fp);
+ void printAll(FILE *fp);
+ void printHyperedgePaper(FILE *fp);
+
+ private:
+ clock_t m_start_time[tmCount];
+ bigclock_t m_total_time[tmCount];
+ int m_tally[tmCount];
+ clock_t m_max_time[tmCount];
+ unsigned int m_variables[tmCount][TIMER_VARIABLES_COUNT];
+
+ bool m_is_running;
+ TimerIndex m_type;
+ TimerIndex m_last_type;
+};
+
+#endif
+
+}
+
+#endif
diff --git a/src/3rdparty/adaptagrams/libavoid/vertices.cpp b/src/3rdparty/adaptagrams/libavoid/vertices.cpp
new file mode 100644
index 0000000..6034e0a
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/vertices.cpp
@@ -0,0 +1,739 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2009 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+
+#include <iostream>
+#include <cstdlib>
+
+#include "libavoid/vertices.h"
+#include "libavoid/geometry.h"
+#include "libavoid/graph.h" // For alertConns
+#include "libavoid/debug.h"
+#include "libavoid/router.h"
+#include "libavoid/assertions.h"
+#include "libavoid/connend.h"
+
+using std::ostream;
+
+
+namespace Avoid {
+
+
+VertID::VertID()
+{
+}
+
+
+VertID::VertID(unsigned int id, unsigned short n, VertIDProps p)
+ : objID(id),
+ vn(n),
+ props(p)
+{
+}
+
+
+VertID::VertID(const VertID& other)
+ : objID(other.objID),
+ vn(other.vn),
+ props(other.props)
+{
+}
+
+
+VertID& VertID::operator= (const VertID& rhs)
+{
+ // Gracefully handle self assignment
+ //if (this == &rhs) return *this;
+
+ objID = rhs.objID;
+ vn = rhs.vn;
+ props = rhs.props;
+
+ return *this;
+}
+
+
+bool VertID::operator==(const VertID& rhs) const
+{
+ if ((objID != rhs.objID) || (vn != rhs.vn))
+ {
+ return false;
+ }
+ return true;
+}
+
+
+bool VertID::operator!=(const VertID& rhs) const
+{
+ if ((objID != rhs.objID) || (vn != rhs.vn))
+ {
+ return true;
+ }
+ return false;
+}
+
+
+bool VertID::operator<(const VertID& rhs) const
+{
+ if ((objID < rhs.objID) ||
+ ((objID == rhs.objID) && (vn < rhs.vn)))
+ {
+ return true;
+ }
+ return false;
+}
+
+
+VertID VertID::operator+(const int& rhs) const
+{
+ return VertID(objID, vn + rhs, props);
+}
+
+
+VertID VertID::operator-(const int& rhs) const
+{
+ return VertID(objID, vn - rhs, props);
+}
+
+
+VertID& VertID::operator++(int)
+{
+ vn += 1;
+ return *this;
+}
+
+
+void VertID::print(FILE *file) const
+{
+ fprintf(file, "[%u,%d, p=%u]", objID, vn, (unsigned int) props);
+}
+
+void VertID::db_print(void) const
+{
+ db_printf("[%u,%d, p=%u]", objID, vn, (unsigned int) props);
+}
+
+
+const unsigned short VertID::src = 1;
+const unsigned short VertID::tar = 2;
+
+// Property flags:
+const unsigned short VertID::PROP_ConnPoint = 1;
+const unsigned short VertID::PROP_OrthShapeEdge = 2;
+const unsigned short VertID::PROP_ConnectionPin = 4;
+const unsigned short VertID::PROP_ConnCheckpoint = 8;
+const unsigned short VertID::PROP_DummyPinHelper = 16;
+
+
+ostream& operator<<(ostream& os, const VertID& vID)
+{
+ return os << '[' << vID.objID << ',' << vID.vn << ']';
+}
+
+
+
+VertInf::VertInf(Router *router, const VertID& vid, const Point& vpoint,
+ const bool addToRouter)
+ : _router(router),
+ id(vid),
+ point(vpoint),
+ lstPrev(nullptr),
+ lstNext(nullptr),
+ shPrev(nullptr),
+ shNext(nullptr),
+ visListSize(0),
+ orthogVisListSize(0),
+ invisListSize(0),
+ pathNext(nullptr),
+ m_orthogonalPartner(nullptr),
+ m_treeRoot(nullptr),
+ visDirections(ConnDirNone),
+ orthogVisPropFlags(0)
+{
+ point.id = vid.objID;
+ point.vn = vid.vn;
+
+ if (addToRouter)
+ {
+ _router->vertices.addVertex(this);
+ }
+}
+
+
+VertInf::~VertInf()
+{
+ COLA_ASSERT(orphaned());
+}
+
+
+EdgeInf *VertInf::hasNeighbour(VertInf *target, bool orthogonal) const
+{
+ const EdgeInfList& visEdgeList = (orthogonal) ? orthogVisList : visList;
+ EdgeInfList::const_iterator finish = visEdgeList.end();
+ for (EdgeInfList::const_iterator edge = visEdgeList.begin(); edge != finish; ++edge)
+ {
+ if ((*edge)->otherVert(this) == target)
+ {
+ return *edge;
+ }
+ }
+ return nullptr;
+}
+
+void VertInf::Reset(const VertID& vid, const Point& vpoint)
+{
+ id = vid;
+ point = vpoint;
+ point.id = id.objID;
+ point.vn = id.vn;
+}
+
+
+void VertInf::Reset(const Point& vpoint)
+{
+ point = vpoint;
+ point.id = id.objID;
+ point.vn = id.vn;
+}
+
+
+// Returns true if this vertex is not involved in any (in)visibility graphs.
+bool VertInf::orphaned(void)
+{
+ return (visList.empty() && invisList.empty() && orthogVisList.empty());
+}
+
+
+void VertInf::removeFromGraph(const bool isConnVert)
+{
+ if (isConnVert)
+ {
+ COLA_ASSERT(id.isConnPt());
+ }
+
+ // For each vertex.
+ EdgeInfList::const_iterator finish = visList.end();
+ EdgeInfList::const_iterator edge;
+ while ((edge = visList.begin()) != finish)
+ {
+ // Remove each visibility edge
+ (*edge)->alertConns();
+ delete (*edge);
+ }
+
+ finish = orthogVisList.end();
+ while ((edge = orthogVisList.begin()) != finish)
+ {
+ // Remove each orthogonal visibility edge.
+ (*edge)->alertConns();
+ delete (*edge);
+ }
+
+ finish = invisList.end();
+ while ((edge = invisList.begin()) != finish)
+ {
+ // Remove each invisibility edge
+ delete (*edge);
+ }
+}
+
+
+void VertInf::orphan(void)
+{
+ // For each vertex.
+ EdgeInfList::const_iterator finish = visList.end();
+ EdgeInfList::const_iterator edge;
+ while ((edge = visList.begin()) != finish)
+ {
+ // Remove each visibility edge
+ (*edge)->makeInactive();
+ }
+
+ finish = orthogVisList.end();
+ while ((edge = orthogVisList.begin()) != finish)
+ {
+ // Remove each orthogonal visibility edge.
+ (*edge)->makeInactive();
+ }
+
+ finish = invisList.end();
+ while ((edge = invisList.begin()) != finish)
+ {
+ // Remove each invisibility edge
+ (*edge)->makeInactive();
+ }
+}
+
+// Returns the direction of this vertex relative to the other specified vertex.
+//
+ConnDirFlags VertInf::directionFrom(const VertInf *other) const
+{
+ double epsilon = 0.000001;
+ Point thisPoint = point;
+ Point otherPoint = other->point;
+ Point diff = thisPoint - otherPoint;
+
+ ConnDirFlags directions = ConnDirNone;
+ if (diff.y > epsilon)
+ {
+ directions |= ConnDirUp;
+ }
+ if (diff.y < -epsilon)
+ {
+ directions |= ConnDirDown;
+ }
+ if (diff.x > epsilon)
+ {
+ directions |= ConnDirRight;
+ }
+ if (diff.x < -epsilon)
+ {
+ directions |= ConnDirLeft;
+ }
+ return directions;
+}
+
+// Given a set of directions, mark visibility edges in all other directions
+// as being invalid so they get ignored during the search.
+//
+void VertInf::setVisibleDirections(const ConnDirFlags directions)
+{
+ for (EdgeInfList::const_iterator edge = visList.begin();
+ edge != visList.end(); ++edge)
+ {
+ if (directions == ConnDirAll)
+ {
+ (*edge)->setDisabled(false);
+ }
+ else
+ {
+ VertInf *otherVert = (*edge)->otherVert(this);
+ ConnDirFlags direction = otherVert->directionFrom(this);
+ bool visible = (direction & directions);
+ (*edge)->setDisabled(!visible);
+ }
+ }
+
+ for (EdgeInfList::const_iterator edge = orthogVisList.begin();
+ edge != orthogVisList.end(); ++edge)
+ {
+ if (directions == ConnDirAll)
+ {
+ (*edge)->setDisabled(false);
+ }
+ else
+ {
+ VertInf *otherVert = (*edge)->otherVert(this);
+ ConnDirFlags direction = otherVert->directionFrom(this);
+ bool visible = (direction & directions);
+ (*edge)->setDisabled(!visible);
+ }
+ }
+}
+
+// Number of points in path from end back to start, or zero if no path exists.
+//
+unsigned int VertInf::pathLeadsBackTo(const VertInf *start) const
+{
+ unsigned int pathlen = 1;
+ for (const VertInf *i = this; i != start; i = i->pathNext)
+ {
+ if ((pathlen > 1) && (i == this))
+ {
+ // We have a circular path, so path not found.
+ return 0;
+ }
+
+ pathlen++;
+ if (i == nullptr)
+ {
+ // Path not found.
+ return 0;
+ }
+
+ // Check we don't have an apparent infinite connector path.
+ COLA_ASSERT(pathlen < 20000);
+ }
+ return pathlen;
+}
+
+VertInf **VertInf::makeTreeRootPointer(VertInf *root)
+{
+ m_treeRoot = (VertInf **) malloc(sizeof(VertInf *));
+ *m_treeRoot = root;
+ return m_treeRoot;
+}
+
+VertInf *VertInf::treeRoot(void) const
+{
+ return (m_treeRoot) ? *m_treeRoot : nullptr;
+}
+
+VertInf **VertInf::treeRootPointer(void) const
+{
+ return m_treeRoot;
+}
+
+void VertInf::clearTreeRootPointer(void)
+{
+ m_treeRoot = nullptr;
+}
+
+void VertInf::setTreeRootPointer(VertInf **pointer)
+{
+ m_treeRoot = pointer;
+}
+
+void VertInf::setSPTFRoot(VertInf *root)
+{
+ // Use the m_treeRoot instance var, but as just a normal VertInf pointer.
+ m_treeRoot = (VertInf **) root;
+}
+
+
+VertInf *VertInf::sptfRoot(void) const
+{
+ // Use the m_treeRoot instance var, but as just a normal VertInf pointer.
+ return (VertInf *) m_treeRoot;
+}
+
+
+bool directVis(VertInf *src, VertInf *dst)
+{
+ ShapeSet ss = ShapeSet();
+
+ Point& p = src->point;
+ Point& q = dst->point;
+
+ VertID& pID = src->id;
+ VertID& qID = dst->id;
+
+ // We better be part of the same instance of libavoid.
+ Router *router = src->_router;
+ COLA_ASSERT(router == dst->_router);
+
+ ContainsMap& contains = router->contains;
+ if (pID.isConnPt())
+ {
+ ss.insert(contains[pID].begin(), contains[pID].end());
+ }
+ if (qID.isConnPt())
+ {
+ ss.insert(contains[qID].begin(), contains[qID].end());
+ }
+
+ // The "beginning" should be the first shape vertex, rather
+ // than an endpoint, which are also stored in "vertices".
+ VertInf *endVert = router->vertices.end();
+ for (VertInf *k = router->vertices.shapesBegin(); k != endVert;
+ k = k->lstNext)
+ {
+ if ((ss.find(k->id.objID) == ss.end()))
+ {
+ if (segmentIntersect(p, q, k->point, k->shNext->point))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+
+VertInfList::VertInfList()
+ : _firstShapeVert(nullptr),
+ _firstConnVert(nullptr),
+ _lastShapeVert(nullptr),
+ _lastConnVert(nullptr),
+ _shapeVertices(0),
+ _connVertices(0)
+{
+}
+
+
+#define checkVertInfListConditions() \
+ do { \
+ COLA_ASSERT((!_firstConnVert && (_connVertices == 0)) || \
+ ((_firstConnVert->lstPrev == nullptr) && (_connVertices > 0))); \
+ COLA_ASSERT((!_firstShapeVert && (_shapeVertices == 0)) || \
+ ((_firstShapeVert->lstPrev == nullptr) && (_shapeVertices > 0))); \
+ COLA_ASSERT(!_lastShapeVert || (_lastShapeVert->lstNext == nullptr)); \
+ COLA_ASSERT(!_lastConnVert || (_lastConnVert->lstNext == _firstShapeVert)); \
+ COLA_ASSERT((!_firstConnVert && !_lastConnVert) || \
+ (_firstConnVert && _lastConnVert) ); \
+ COLA_ASSERT((!_firstShapeVert && !_lastShapeVert) || \
+ (_firstShapeVert && _lastShapeVert) ); \
+ COLA_ASSERT(!_firstShapeVert || !(_firstShapeVert->id.isConnPt())); \
+ COLA_ASSERT(!_lastShapeVert || !(_lastShapeVert->id.isConnPt())); \
+ COLA_ASSERT(!_firstConnVert || _firstConnVert->id.isConnPt()); \
+ COLA_ASSERT(!_lastConnVert || _lastConnVert->id.isConnPt()); \
+ } while(0)
+
+
+void VertInfList::addVertex(VertInf *vert)
+{
+ checkVertInfListConditions();
+ COLA_ASSERT(vert->lstPrev == nullptr);
+ COLA_ASSERT(vert->lstNext == nullptr);
+
+ if (vert->id.isConnPt())
+ {
+ // A Connector vertex
+ if (_firstConnVert)
+ {
+ // Join with previous front
+ vert->lstNext = _firstConnVert;
+ _firstConnVert->lstPrev = vert;
+
+ // Make front
+ _firstConnVert = vert;
+ }
+ else
+ {
+ // Make front and back
+ _firstConnVert = vert;
+ _lastConnVert = vert;
+
+ // Link to front of shapes list
+ vert->lstNext = _firstShapeVert;
+ }
+ _connVertices++;
+ }
+ else // if (vert->id.shape > 0)
+ {
+ // A Shape vertex
+ if (_lastShapeVert)
+ {
+ // Join with previous back
+ vert->lstPrev = _lastShapeVert;
+ _lastShapeVert->lstNext = vert;
+
+ // Make back
+ _lastShapeVert = vert;
+ }
+ else
+ {
+ // Make first and last
+ _firstShapeVert = vert;
+ _lastShapeVert = vert;
+
+ // Join with conns list
+ if (_lastConnVert)
+ {
+ COLA_ASSERT(_lastConnVert->lstNext == nullptr);
+
+ _lastConnVert->lstNext = vert;
+ }
+ }
+ _shapeVertices++;
+ }
+ checkVertInfListConditions();
+}
+
+
+// Removes a vertex from the list and returns a pointer to the vertex
+// following the removed one.
+VertInf *VertInfList::removeVertex(VertInf *vert)
+{
+ if (vert == nullptr)
+ {
+ return nullptr;
+ }
+ // Conditions for correct data structure
+ checkVertInfListConditions();
+
+ VertInf *following = vert->lstNext;
+
+ if (vert->id.isConnPt())
+ {
+ // A Connector vertex
+ if (vert == _firstConnVert)
+ {
+
+ if (vert == _lastConnVert)
+ {
+ _firstConnVert = nullptr;
+ _lastConnVert = nullptr;
+ }
+ else
+ {
+ // Set new first
+ _firstConnVert = _firstConnVert->lstNext;
+
+ if (_firstConnVert)
+ {
+ // Set previous
+ _firstConnVert->lstPrev = nullptr;
+ }
+ }
+ }
+ else if (vert == _lastConnVert)
+ {
+ // Set new last
+ _lastConnVert = _lastConnVert->lstPrev;
+
+ // Make last point to shapes list
+ _lastConnVert->lstNext = _firstShapeVert;
+ }
+ else
+ {
+ vert->lstNext->lstPrev = vert->lstPrev;
+ vert->lstPrev->lstNext = vert->lstNext;
+ }
+ _connVertices--;
+ }
+ else // if (vert->id.shape > 0)
+ {
+ // A Shape vertex
+ if (vert == _lastShapeVert)
+ {
+ // Set new last
+ _lastShapeVert = _lastShapeVert->lstPrev;
+
+ if (vert == _firstShapeVert)
+ {
+ _firstShapeVert = nullptr;
+ if (_lastConnVert)
+ {
+ _lastConnVert->lstNext = nullptr;
+ }
+ }
+
+ if (_lastShapeVert)
+ {
+ _lastShapeVert->lstNext = nullptr;
+ }
+ }
+ else if (vert == _firstShapeVert)
+ {
+ // Set new first
+ _firstShapeVert = _firstShapeVert->lstNext;
+
+ // Correct the last conn vertex
+ if (_lastConnVert)
+ {
+ _lastConnVert->lstNext = _firstShapeVert;
+ }
+
+ if (_firstShapeVert)
+ {
+ _firstShapeVert->lstPrev = nullptr;
+ }
+ }
+ else
+ {
+ vert->lstNext->lstPrev = vert->lstPrev;
+ vert->lstPrev->lstNext = vert->lstNext;
+ }
+ _shapeVertices--;
+ }
+ vert->lstPrev = nullptr;
+ vert->lstNext = nullptr;
+
+ checkVertInfListConditions();
+
+ return following;
+}
+
+
+VertInf *VertInfList::getVertexByID(const VertID& id)
+{
+ VertID searchID = id;
+ if (searchID.vn == kUnassignedVertexNumber)
+ {
+ unsigned int topbit = ((unsigned int) 1) << 31;
+ if (searchID.objID & topbit)
+ {
+ searchID.objID = searchID.objID & ~topbit;
+ searchID.vn = VertID::src;
+ }
+ else
+ {
+ searchID.vn = VertID::tar;
+ }
+ }
+ VertInf *last = end();
+ for (VertInf *curr = connsBegin(); curr != last; curr = curr->lstNext)
+ {
+ if (curr->id == searchID)
+ {
+ return curr;
+ }
+ }
+ return nullptr;
+}
+
+
+VertInf *VertInfList::getVertexByPos(const Point& p)
+{
+ VertInf *last = end();
+ for (VertInf *curr = shapesBegin(); curr != last; curr = curr->lstNext)
+ {
+ if (curr->point == p)
+ {
+ return curr;
+ }
+ }
+ return nullptr;
+}
+
+
+VertInf *VertInfList::shapesBegin(void)
+{
+ return _firstShapeVert;
+}
+
+
+VertInf *VertInfList::connsBegin(void)
+{
+ if (_firstConnVert)
+ {
+ return _firstConnVert;
+ }
+ // No connector vertices
+ return _firstShapeVert;
+}
+
+
+VertInf *VertInfList::end(void)
+{
+ return nullptr;
+}
+
+
+unsigned int VertInfList::connsSize(void) const
+{
+ return _connVertices;
+}
+
+
+unsigned int VertInfList::shapesSize(void) const
+{
+ return _shapeVertices;
+}
+
+
+}
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/vertices.h b/src/3rdparty/adaptagrams/libavoid/vertices.h
new file mode 100644
index 0000000..aac43bb
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/vertices.h
@@ -0,0 +1,226 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2013 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+
+#ifndef AVOID_VERTICES_H
+#define AVOID_VERTICES_H
+
+#include <list>
+#include <set>
+#include <map>
+#include <iostream>
+#include <cstdio>
+#include <utility>
+
+#include "libavoid/geomtypes.h"
+
+namespace Avoid {
+
+class EdgeInf;
+class VertInf;
+class Router;
+
+typedef std::list<EdgeInf *> EdgeInfList;
+typedef std::pair<VertInf *, VertInf *> VertexPair;
+
+typedef unsigned int ConnDirFlags;
+typedef unsigned short VertIDProps;
+
+
+class VertID
+{
+ public:
+ unsigned int objID;
+ unsigned short vn;
+ // Properties:
+ VertIDProps props;
+
+ static const unsigned short src;
+ static const unsigned short tar;
+
+ static const VertIDProps PROP_ConnPoint;
+ static const VertIDProps PROP_OrthShapeEdge;
+ static const VertIDProps PROP_ConnectionPin;
+ static const VertIDProps PROP_ConnCheckpoint;
+ static const VertIDProps PROP_DummyPinHelper;
+
+ VertID();
+ VertID(unsigned int id, unsigned short n, VertIDProps p = 0);
+ VertID(const VertID& other);
+ VertID& operator= (const VertID& rhs);
+ bool operator==(const VertID& rhs) const;
+ bool operator!=(const VertID& rhs) const;
+ bool operator<(const VertID& rhs) const;
+ VertID operator+(const int& rhs) const;
+ VertID operator-(const int& rhs) const;
+ VertID& operator++(int);
+ void print(FILE *file = stdout) const;
+ void db_print(void) const;
+ friend std::ostream& operator<<(std::ostream& os, const VertID& vID);
+
+ // Property tests:
+ inline bool isOrthShapeEdge(void) const
+ {
+ return (props & PROP_OrthShapeEdge) ? true : false;
+ }
+ inline bool isConnPt(void) const
+ {
+ return (props & PROP_ConnPoint) ? true : false;
+ }
+ inline bool isConnectionPin(void) const
+ {
+ return (props & PROP_ConnectionPin) ? true : false;
+ }
+ inline bool isConnCheckpoint(void) const
+ {
+ return (props & PROP_ConnCheckpoint) ? true : false;
+ }
+ inline bool isDummyPinHelper(void) const
+ {
+ return (props & PROP_DummyPinHelper) ? true : false;
+ }
+};
+
+
+// An ID given to all dummy vertices inserted to allow creation of the
+// orthogonal visibility graph since the vertices in the orthogonal graph
+// mostly do not correspond to shape corners or connector endpoints.
+//
+static const VertID dummyOrthogID(0, 0);
+static const VertID dummyOrthogShapeID(0, 0, VertID::PROP_OrthShapeEdge);
+
+class ANode;
+
+class VertInf
+{
+ public:
+ VertInf(Router *router, const VertID& vid, const Point& vpoint,
+ const bool addToRouter = true);
+ ~VertInf();
+ void Reset(const VertID& vid, const Point& vpoint);
+ void Reset(const Point& vpoint);
+ void removeFromGraph(const bool isConnVert = true);
+ bool orphaned(void);
+
+ unsigned int pathLeadsBackTo(const VertInf *start) const;
+ void setVisibleDirections(const ConnDirFlags directions);
+ ConnDirFlags directionFrom(const VertInf *other) const;
+ // Checks if this vertex has the target as a visibility neighbour.
+ EdgeInf *hasNeighbour(VertInf *target, bool orthogonal) const;
+ void orphan(void);
+
+ VertInf **makeTreeRootPointer(VertInf *root);
+ VertInf *treeRoot(void) const;
+ VertInf **treeRootPointer(void) const;
+ void setTreeRootPointer(VertInf **pointer);
+ void clearTreeRootPointer(void);
+
+ void setSPTFRoot(VertInf *root);
+ VertInf *sptfRoot(void) const;
+
+ Router *_router;
+ VertID id;
+ Point point;
+ VertInf *lstPrev;
+ VertInf *lstNext;
+ VertInf *shPrev;
+ VertInf *shNext;
+ EdgeInfList visList;
+ unsigned int visListSize;
+ EdgeInfList orthogVisList;
+ unsigned int orthogVisListSize;
+ EdgeInfList invisList;
+ unsigned int invisListSize;
+ VertInf *pathNext;
+
+ // The tree root and distance value used when computing MTSTs.
+ // XXX: Maybe these should be allocated as a separate struct
+ // and referenced via a pointer. This would be slower due
+ // to memory allocation, but would save 2 x 8 = 24 bytes per
+ // VertInf on 64-bit machines.
+ VertInf *m_orthogonalPartner;
+ VertInf **m_treeRoot;
+ double sptfDist;
+
+ ConnDirFlags visDirections;
+ std::list<ANode *> aStarDoneNodes;
+ std::list<ANode *> aStarPendingNodes;
+ // Flags for orthogonal visibility properties, i.e., whether the
+ // line points to a shape edge, connection point or an obstacle.
+ unsigned int orthogVisPropFlags;
+};
+
+
+// Orthogonal visibility property flags
+static const unsigned int XL_EDGE = 1;
+static const unsigned int XL_CONN = 2;
+static const unsigned int XH_EDGE = 4;
+static const unsigned int XH_CONN = 8;
+static const unsigned int YL_EDGE = 16;
+static const unsigned int YL_CONN = 32;
+static const unsigned int YH_EDGE = 64;
+static const unsigned int YH_CONN = 128;
+
+
+bool directVis(VertInf *src, VertInf *dst);
+
+
+// A linked list of all the vertices in the router instance. All the
+// connector endpoints are listed first, then all the shape vertices.
+// Dummy vertices inserted for orthogonal routing are classed as shape
+// vertices but have VertID(0, 0).
+//
+class VertInfList
+{
+ public:
+ VertInfList();
+ void addVertex(VertInf *vert);
+ VertInf *removeVertex(VertInf *vert);
+ VertInf *getVertexByID(const VertID& id);
+ VertInf *getVertexByPos(const Point& p);
+ VertInf *shapesBegin(void);
+ VertInf *connsBegin(void);
+ VertInf *end(void);
+ unsigned int connsSize(void) const;
+ unsigned int shapesSize(void) const;
+ private:
+ VertInf *_firstShapeVert;
+ VertInf *_firstConnVert;
+ VertInf *_lastShapeVert;
+ VertInf *_lastConnVert;
+ unsigned int _shapeVertices;
+ unsigned int _connVertices;
+};
+
+
+typedef std::set<unsigned int> ShapeSet;
+typedef std::map<VertID, ShapeSet> ContainsMap;
+
+
+}
+
+
+#endif
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/viscluster.cpp b/src/3rdparty/adaptagrams/libavoid/viscluster.cpp
new file mode 100644
index 0000000..ebc0c50
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/viscluster.cpp
@@ -0,0 +1,116 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+#include <cstdlib>
+
+#include "libavoid/viscluster.h"
+#include "libavoid/router.h"
+#include "libavoid/assertions.h"
+#include "libavoid/debug.h"
+
+
+namespace Avoid {
+
+
+ClusterRef::ClusterRef(Router *router, Polygon& polygon, const unsigned int id)
+ : m_router(router),
+ m_polygon(polygon, router),
+ m_rectangular_polygon(m_polygon.boundingRectPolygon()),
+ m_active(false)
+{
+ COLA_ASSERT(m_router != nullptr);
+ m_id = m_router->assignId(id);
+
+ m_router->addCluster(this);
+}
+
+
+ClusterRef::~ClusterRef()
+{
+ if (m_router->m_currently_calling_destructors == false)
+ {
+ err_printf("ERROR: ClusterRef::~ClusterRef() shouldn't be called directly.\n");
+ err_printf(" It is owned by the router. Call Router::deleteCluster() instead.\n");
+ abort();
+ }
+}
+
+
+void ClusterRef::makeActive(void)
+{
+ COLA_ASSERT(!m_active);
+
+ // Add to clusterRefs list.
+ m_clusterrefs_pos = m_router->clusterRefs.insert(
+ m_router->clusterRefs.begin(), this);
+
+ m_active = true;
+}
+
+
+void ClusterRef::makeInactive(void)
+{
+ COLA_ASSERT(m_active);
+
+ // Remove from clusterRefs list.
+ m_router->clusterRefs.erase(m_clusterrefs_pos);
+
+ m_active = false;
+}
+
+
+void ClusterRef::setNewPoly(Polygon& poly)
+{
+ m_polygon = ReferencingPolygon(poly, m_router);
+ m_rectangular_polygon = m_polygon.boundingRectPolygon();
+}
+
+
+unsigned int ClusterRef::id(void) const
+{
+ return m_id;
+}
+
+
+ReferencingPolygon& ClusterRef::polygon(void)
+{
+ return m_polygon;
+}
+
+
+Polygon& ClusterRef::rectangularPolygon(void)
+{
+ return m_rectangular_polygon;
+}
+
+
+Router *ClusterRef::router(void) const
+{
+ return m_router;
+}
+
+
+}
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/viscluster.h b/src/3rdparty/adaptagrams/libavoid/viscluster.h
new file mode 100644
index 0000000..f5ddadc
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/viscluster.h
@@ -0,0 +1,136 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+//! @file viscluster.h
+//! @brief Contains the interface for the ClusterRef class.
+
+#ifndef AVOID_CLUSTER_H
+#define AVOID_CLUSTER_H
+
+#include <list>
+
+#include "libavoid/geometry.h"
+#include "libavoid/dllexport.h"
+
+namespace Avoid {
+
+class Router;
+class ClusterRef;
+typedef std::list<ClusterRef *> ClusterRefList;
+
+
+//! @brief The ClusterRef class represents a cluster object.
+//!
+//! Cluster are boundaries around groups of shape objects. Ideally, only
+//! connectors with one endpoint inside the cluster and one endpoint outside
+//! the cluster will cross the cluster boundary. Connectors that begin and
+//! end inside a cluster will not route outside it, and connectors that begin
+//! and end outside the cluster will not enter the cluster.
+//!
+//! @note While the functionality of this class works, it is currently
+//! experimental you will likely suffer a large performance hit
+//! when using it.
+//!
+class AVOID_EXPORT ClusterRef
+{
+ public:
+ //! @brief Cluster reference constructor.
+ //!
+ //! Creates a cluster object reference, but does not yet place it
+ //! into the Router scene. You can add or remove the cluster to/from
+ //! the scene with Router::addCluster() and Router::delCluster(). The
+ //! cluster can effectively be moved with ClusterRef::setNewPoly()
+ //! method.
+ //!
+ //! The poly argument should be used to specify a polygon boundary.
+ //! The rectangular boundary will be automatically generated from this.
+ //! The polygon boundary could be a convex hull consisting of points
+ //! from the boundaries of shapes.
+ //!
+ //! @note Regarding IDs:
+ //! You can let libavoid manually handle IDs by not specifying
+ //! them. Alternatively, you can specify all IDs yourself, but
+ //! you must be careful to makes sure that each object in the
+ //! scene (shape, connector, cluster, etc) is given a unique,
+ //! positive ID. This uniqueness is checked if assertions are
+ //! enabled, but if not and there are clashes then strange
+ //! things can happen.
+ //!
+ //! @param[in] router The router scene to place the cluster into.
+ //! @param[in] poly A Polygon representing the boundary of the
+ //! cluster.
+ //! @param[in] id Optionally, a positive integer ID unique
+ //! among all objects.
+ //!
+ ClusterRef(Router *router, Polygon& poly, const unsigned int id = 0);
+
+// To prevent C++ objects from being destroyed in garbage collected languages
+// when the libraries are called from SWIG, we hide the declarations of the
+// destructors and prevent generation of default destructors.
+#ifndef SWIG
+ //! @brief Cluster reference destructor.
+ ~ClusterRef();
+#endif
+ //! @brief Update the polygon boundary for this cluster.
+ //!
+ //! You should specify a polygon boundary. The rectangular one will
+ //! be generated automatically from this.
+ //!
+ //! @param[in] poly A Polygon representing the boundary of the
+ //! cluster.
+ void setNewPoly(Polygon& poly);
+ //! @brief Returns the ID of this cluster.
+ //! @returns The ID of the cluster.
+ unsigned int id(void) const;
+ //! @brief Returns a reference to the polygon boundary of this
+ //! cluster.
+ //! @returns A reference to the polygon boundary of the cluster.
+ ReferencingPolygon& polygon(void);
+ //! @brief Returns a reference to the rectangular boundary of this
+ //! cluster.
+ //! @returns A reference to the rectangular boundary of the cluster.
+ Polygon& rectangularPolygon(void);
+ //! @brief Returns a pointer to the router scene this cluster is in.
+ //! @returns A pointer to the router scene for this cluster.
+ Router *router(void) const;
+
+ void makeActive(void);
+ void makeInactive(void);
+
+ private:
+ Router *m_router;
+ unsigned int m_id;
+ ReferencingPolygon m_polygon;
+ Polygon m_rectangular_polygon;
+ bool m_active;
+ ClusterRefList::iterator m_clusterrefs_pos;
+};
+
+
+}
+
+
+#endif
+
+
diff --git a/src/3rdparty/adaptagrams/libavoid/visibility.cpp b/src/3rdparty/adaptagrams/libavoid/visibility.cpp
new file mode 100644
index 0000000..3adadd4
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/visibility.cpp
@@ -0,0 +1,676 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2009 Monash University
+ *
+ * --------------------------------------------------------------------
+ * The Visibility Sweep technique is based upon the method described
+ * in Section 5.2 of:
+ * Lee, D.-T. (1978). Proximity and reachability in the plane.,
+ * PhD thesis, Department of Electrical Engineering,
+ * University of Illinois, Urbana, IL.
+ * --------------------------------------------------------------------
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+
+#include <algorithm>
+#include <cfloat>
+
+#include "libavoid/shape.h"
+#include "libavoid/debug.h"
+#include "libavoid/visibility.h"
+#include "libavoid/vertices.h"
+#include "libavoid/graph.h"
+#include "libavoid/geometry.h"
+#include "libavoid/router.h"
+#include "libavoid/assertions.h"
+
+
+namespace Avoid {
+
+
+static void vertexSweep(VertInf *vert);
+
+void Obstacle::computeVisibilityNaive(void)
+{
+ if ( !(router()->InvisibilityGrph) )
+ {
+ // Clear shape from graph.
+ removeFromGraph();
+ }
+
+ VertInf *shapeBegin = firstVert();
+ VertInf *shapeEnd = lastVert()->lstNext;
+
+ VertInf *pointsBegin = router()->vertices.connsBegin();
+ for (VertInf *curr = shapeBegin; curr != shapeEnd; curr = curr->lstNext)
+ {
+ bool knownNew = true;
+
+ db_printf("-- CONSIDERING --\n");
+ curr->id.db_print();
+
+ db_printf("\tFirst Half:\n");
+ for (VertInf *j = pointsBegin ; j != curr; j = j->lstNext)
+ {
+ if (j->id == dummyOrthogID)
+ {
+ // Don't include orthogonal dummy vertices.
+ continue;
+ }
+ EdgeInf::checkEdgeVisibility(curr, j, knownNew);
+ }
+
+ db_printf("\tSecond Half:\n");
+ VertInf *pointsEnd = router()->vertices.end();
+ for (VertInf *k = shapeEnd; k != pointsEnd; k = k->lstNext)
+ {
+ if (k->id == dummyOrthogID)
+ {
+ // Don't include orthogonal dummy vertices.
+ continue;
+ }
+ EdgeInf::checkEdgeVisibility(curr, k, knownNew);
+ }
+ }
+}
+
+
+void Obstacle::computeVisibilitySweep(void)
+{
+ if ( !(router()->InvisibilityGrph) )
+ {
+ // Clear shape from graph.
+ removeFromGraph();
+ }
+
+ VertInf *startIter = firstVert();
+ VertInf *endIter = lastVert()->lstNext;
+
+ for (VertInf *i = startIter; i != endIter; i = i->lstNext)
+ {
+ vertexSweep(i);
+ }
+}
+
+
+void vertexVisibility(VertInf *point, VertInf *partner, bool knownNew,
+ const bool gen_contains)
+{
+ Router *router = point->_router;
+ const VertID& pID = point->id;
+
+ // Make sure we're only doing ptVis for endpoints.
+ COLA_ASSERT(pID.isConnPt());
+
+ if ( !(router->InvisibilityGrph) )
+ {
+ point->removeFromGraph();
+ }
+
+ if (gen_contains && pID.isConnPt())
+ {
+ router->generateContains(point);
+ }
+
+ if (router->UseLeesAlgorithm)
+ {
+ vertexSweep(point);
+ }
+ else
+ {
+ VertInf *shapesEnd = router->vertices.end();
+ for (VertInf *k = router->vertices.connsBegin(); k != shapesEnd;
+ k = k->lstNext)
+ {
+ if (k->id == dummyOrthogID)
+ {
+ // Don't include orthogonal dummy vertices.
+ continue;
+ }
+ else if (k->id.isConnPt() && !k->id.isConnectionPin() &&
+ !(k->id.isConnCheckpoint() && k->id.objID == pID.objID))
+ {
+ // Include connection pins, but not connectors.
+ // Also include checkpoints with same ID as sweep point.
+ continue;
+ }
+ EdgeInf::checkEdgeVisibility(point, k, knownNew);
+ }
+ if (partner)
+ {
+ EdgeInf::checkEdgeVisibility(point, partner, knownNew);
+ }
+ }
+}
+
+
+//============================================================================
+// SWEEP CODE
+//
+
+
+class PointPair
+{
+ public:
+ PointPair(const Point& centerPoint, VertInf *inf)
+ : vInf(inf),
+ centerPoint(centerPoint)
+ {
+ angle = rotationalAngle(vInf->point - centerPoint);
+ distance = euclideanDist(centerPoint, vInf->point);
+ }
+ bool operator<(const PointPair& rhs) const
+ {
+ // Firstly order by angle.
+ if (angle == rhs.angle)
+ {
+ // If the points are collinear, then order them in increasing
+ // distance from the point we are sweeping around.
+ if (distance == rhs.distance)
+ {
+ // XXX: Add this assertion back if we require that
+ // connector endpoints have unique IDs. For the
+ // moment it is okay for them to have the same ID.
+ //COLA_ASSERT(vInf->id != rhs.vInf->id);
+
+ // If comparing two points at the same physical
+ // position, then order them by their VertIDs.
+ return vInf->id < rhs.vInf->id;
+ }
+ return distance < rhs.distance;
+ }
+ return angle < rhs.angle;
+ }
+
+ VertInf *vInf;
+ double angle;
+ double distance;
+ Point centerPoint;
+};
+
+typedef std::set<PointPair > VertSet;
+
+
+class EdgePair
+{
+ public:
+ EdgePair()
+ : vInf1(nullptr),
+ vInf2(nullptr),
+ dist1(0.0),
+ dist2(0.0),
+ angle(0.0),
+ angleDist(0.0)
+ {
+ // The default constuctor should never be called.
+ // This is defined to appease the MSVC compiler.
+ COLA_ASSERT(false);
+ }
+ EdgePair(const PointPair& p1, VertInf *v)
+ : vInf1(p1.vInf),
+ vInf2(v),
+ dist1(p1.distance),
+ dist2(euclideanDist(vInf2->point, p1.centerPoint)),
+ angle(p1.angle),
+ angleDist(p1.distance),
+ centerPoint(p1.centerPoint)
+ {
+ }
+ bool operator<(const EdgePair& rhs) const
+ {
+ COLA_ASSERT(angle == rhs.angle);
+ if (angleDist == rhs.angleDist)
+ {
+ return (dist2 < rhs.dist2);
+ }
+ return (angleDist < rhs.angleDist);
+ }
+ bool operator==(const EdgePair& rhs) const
+ {
+ if (((vInf1->id == rhs.vInf1->id) &&
+ (vInf2->id == rhs.vInf2->id)) ||
+ ((vInf1->id == rhs.vInf2->id) &&
+ (vInf2->id == rhs.vInf1->id)))
+ {
+ return true;
+ }
+ return false;
+ }
+ bool operator!=(const EdgePair& rhs) const
+ {
+ if (((vInf1->id == rhs.vInf1->id) &&
+ (vInf2->id == rhs.vInf2->id)) ||
+ ((vInf1->id == rhs.vInf2->id) &&
+ (vInf2->id == rhs.vInf1->id)))
+ {
+ return false;
+ }
+ return true;
+ }
+ void setNegativeAngle(void)
+ {
+ angle = -1.0;
+ }
+ double setCurrAngle(const PointPair& p)
+ {
+ if (p.vInf->point == vInf1->point)
+ {
+ angleDist = dist1;
+ angle = p.angle;
+ }
+ else if (p.vInf->point == vInf2->point)
+ {
+ angleDist = dist2;
+ angle = p.angle;
+ }
+ else if (p.angle != angle)
+ {
+ COLA_ASSERT(p.angle > angle);
+ angle = p.angle;
+ Point pp;
+ int result = rayIntersectPoint(vInf1->point, vInf2->point,
+ centerPoint, p.vInf->point, &(pp.x), &(pp.y));
+ if (result != DO_INTERSECT)
+ {
+ // This can happen with points that appear to have the
+ // same angle but at are at slightly different positions
+ angleDist = std::min(dist1, dist2);
+ }
+ else
+ {
+ angleDist = euclideanDist(pp, centerPoint);
+ }
+ }
+
+ return angleDist;
+ }
+
+ VertInf *vInf1;
+ VertInf *vInf2;
+ double dist1;
+ double dist2;
+ double angle;
+ double angleDist;
+ Point centerPoint;
+};
+
+typedef std::list<EdgePair> SweepEdgeList;
+
+
+#define AHEAD 1
+#define BEHIND -1
+
+class isBoundingShape
+{
+ public:
+ // Class instance remembers the ShapeSet.
+ isBoundingShape(ShapeSet& set) :
+ ss(set)
+ { }
+ // The following is an overloading of the function call operator.
+ bool operator () (const PointPair& pp)
+ {
+ if (!(pp.vInf->id.isConnPt()) &&
+ (ss.find(pp.vInf->id.objID) != ss.end()))
+ {
+ return true;
+ }
+ return false;
+ }
+ private:
+ // MSVC wants to generate the assignment operator and the default
+ // constructor, but fails. Therefore we declare them private and
+ // don't implement them.
+ isBoundingShape & operator=(isBoundingShape const &);
+ isBoundingShape();
+
+ ShapeSet& ss;
+};
+
+
+static bool sweepVisible(SweepEdgeList& T, const PointPair& point,
+ std::set<unsigned int>& onBorderIDs, int *blocker)
+{
+ if (T.empty())
+ {
+ // No blocking edges.
+ return true;
+ }
+
+ Router *router = point.vInf->_router;
+ bool visible = true;
+
+ SweepEdgeList::const_iterator closestIt = T.begin();
+ SweepEdgeList::const_iterator end = T.end();
+ while (closestIt != end)
+ {
+ if ((point.vInf->point == closestIt->vInf1->point) ||
+ (point.vInf->point == closestIt->vInf2->point))
+ {
+ // If the ray intersects just the endpoint of a
+ // blocking edge then ignore that edge.
+ ++closestIt;
+ continue;
+ }
+ break;
+ }
+ if (closestIt == end)
+ {
+ return true;
+ }
+
+ if (point.vInf->id.isConnPt())
+ {
+ // It's a connector endpoint, so we have to ignore
+ // edges of containing shapes for determining visibility.
+ ShapeSet& rss = router->contains[point.vInf->id];
+ while (closestIt != end)
+ {
+ if (rss.find(closestIt->vInf1->id.objID) == rss.end())
+ {
+ // This is not a containing edge so do the normal
+ // test and then stop.
+ if (point.distance > closestIt->angleDist)
+ {
+ visible = false;
+ }
+ else if ((point.distance == closestIt->angleDist) &&
+ onBorderIDs.find(closestIt->vInf1->id.objID) !=
+ onBorderIDs.end())
+ {
+ // Touching, but centerPoint is on another edge of
+ // shape shape, so count as blocking.
+ visible = false;
+ }
+ break;
+ }
+ // This was a containing edge, so consider the next along.
+ ++closestIt;
+ }
+ }
+ else
+ {
+ // Just test to see if this point is closer than the closest
+ // edge blocking this ray.
+ if (point.distance > closestIt->angleDist)
+ {
+ visible = false;
+ }
+ else if ((point.distance == closestIt->angleDist) &&
+ onBorderIDs.find(closestIt->vInf1->id.objID) !=
+ onBorderIDs.end())
+ {
+ // Touching, but centerPoint is on another edge of
+ // shape shape, so count as blocking.
+ visible = false;
+ }
+ }
+
+ if (!visible)
+ {
+ *blocker = (*closestIt).vInf1->id.objID;
+ }
+ return visible;
+}
+
+
+static void vertexSweep(VertInf *vert)
+{
+ Router *router = vert->_router;
+ VertID& pID = vert->id;
+ Point& pPoint = vert->point;
+
+ VertInf *centerInf = vert;
+ VertID centerID = pID;
+ Point centerPoint = pPoint;
+
+ // List of shape (and maybe endpt) vertices, except p
+ // Sort list, around
+ VertSet v;
+
+ // Initialise the vertex list
+ ShapeSet& ss = router->contains[centerID];
+ VertInf *beginVert = router->vertices.connsBegin();
+ VertInf *endVert = router->vertices.end();
+ for (VertInf *inf = beginVert; inf != endVert; inf = inf->lstNext)
+ {
+ if (inf == centerInf)
+ {
+ // Don't include the center point itself.
+ continue;
+ }
+ else if (inf->id == dummyOrthogID)
+ {
+ // Don't include orthogonal dummy vertices.
+ continue;
+ }
+
+ if (centerID.isConnPt() && (ss.find(inf->id.objID) != ss.end()) &&
+ !inf->id.isConnPt())
+ {
+ // Don't include edge points of containing shapes.
+ unsigned int shapeID = inf->id.objID;
+ db_printf("Center is inside shape %u so ignore shape edges.\n",
+ shapeID);
+ continue;
+ }
+
+ if (inf->id.isConnPt())
+ {
+ // Add connector endpoint.
+ if (centerID.isConnPt())
+ {
+ if (inf->id.isConnectionPin())
+ {
+ v.insert(PointPair(centerPoint, inf));
+ }
+ else if (centerID.isConnectionPin())
+ {
+ // Connection pins have visibility to everything.
+ v.insert(PointPair(centerPoint, inf));
+ }
+ else if (inf->id.objID == centerID.objID)
+ {
+ // Center is an endpoint, so only include the other
+ // endpoints or checkpoints from the matching connector.
+ v.insert(PointPair(centerPoint, inf));
+ }
+ }
+ else
+ {
+ // Center is a shape vertex, so add all endpoint vertices.
+ v.insert(PointPair(centerPoint, inf));
+ }
+ }
+ else
+ {
+ // Add shape vertex.
+ v.insert(PointPair(centerPoint, inf));
+ }
+ }
+ std::set<unsigned int> onBorderIDs;
+
+ // Add edges to T that intersect the initial ray.
+ SweepEdgeList e;
+ VertSet::const_iterator vbegin = v.begin();
+ VertSet::const_iterator vend = v.end();
+ const Point xaxis(DBL_MAX, centerInf->point.y);
+ for (VertSet::const_iterator t = vbegin; t != vend; ++t)
+ {
+ VertInf *k = t->vInf;
+
+ COLA_ASSERT(centerInf != k);
+
+ VertInf *kPrev = k->shPrev;
+ VertInf *kNext = k->shNext;
+ if (kPrev && (kPrev != centerInf) &&
+ (vecDir(centerInf->point, xaxis, kPrev->point) == AHEAD))
+ {
+ if (segmentIntersect(centerInf->point, xaxis, kPrev->point,
+ k->point))
+ {
+ EdgePair intPair = EdgePair(*t, kPrev);
+ e.push_back(intPair);
+ }
+ if (pointOnLine(kPrev->point, k->point, centerInf->point))
+ {
+ // Record that centerPoint is on an obstacle line.
+ onBorderIDs.insert(k->id.objID);
+ }
+ }
+ else if (kNext && (kNext != centerInf) &&
+ (vecDir(centerInf->point, xaxis, kNext->point) == AHEAD))
+ {
+ if (segmentIntersect(centerInf->point, xaxis, kNext->point,
+ k->point))
+ {
+ EdgePair intPair = EdgePair(*t, kNext);
+ e.push_back(intPair);
+ }
+ if (pointOnLine(kNext->point, k->point, centerInf->point))
+ {
+ // Record that centerPoint is on an obstacle line.
+ onBorderIDs.insert(k->id.objID);
+ }
+ }
+ }
+ for (SweepEdgeList::iterator c = e.begin(); c != e.end(); ++c)
+ {
+ (*c).setNegativeAngle();
+ }
+
+
+ // Start the actual sweep.
+ db_printf("SWEEP: "); centerID.db_print(); db_printf("\n");
+
+ isBoundingShape isBounding(ss);
+ for (VertSet::const_iterator t = vbegin; t != vend; ++t)
+ {
+ VertInf *currInf = (*t).vInf;
+ VertID& currID = currInf->id;
+ Point& currPt = currInf->point;
+
+ const double& currDist = (*t).distance;
+
+ EdgeInf *edge = EdgeInf::existingEdge(centerInf, currInf);
+ if (edge == nullptr)
+ {
+ edge = new EdgeInf(centerInf, currInf);
+ }
+
+ for (SweepEdgeList::iterator c = e.begin(); c != e.end(); ++c)
+ {
+ (*c).setCurrAngle(*t);
+ }
+ e.sort();
+
+ // Check visibility.
+ int blocker = 0;
+ bool currVisible = sweepVisible(e, *t, onBorderIDs, &blocker);
+
+ bool cone1 = true, cone2 = true;
+ if (!(centerID.isConnPt()))
+ {
+ cone1 = inValidRegion(router->IgnoreRegions,
+ centerInf->shPrev->point, centerPoint,
+ centerInf->shNext->point, currInf->point);
+ }
+ if (!(currInf->id.isConnPt()))
+ {
+ cone2 = inValidRegion(router->IgnoreRegions,
+ currInf->shPrev->point, currInf->point,
+ currInf->shNext->point, centerPoint);
+ }
+
+ if (!cone1 || !cone2)
+ {
+ if (router->InvisibilityGrph)
+ {
+ db_printf("\tSetting invisibility edge... \n\t\t");
+ edge->addBlocker(0);
+ edge->db_print();
+ }
+ }
+ else
+ {
+ if (currVisible)
+ {
+ db_printf("\tSetting visibility edge... \n\t\t");
+ edge->setDist(currDist);
+ edge->db_print();
+ }
+ else if (router->InvisibilityGrph)
+ {
+ db_printf("\tSetting invisibility edge... \n\t\t");
+ edge->addBlocker(blocker);
+ edge->db_print();
+ }
+ }
+
+ if (!(edge->added()) && !(router->InvisibilityGrph))
+ {
+ delete edge;
+ edge = nullptr;
+ }
+
+ if (!(currID.isConnPt()))
+ {
+ // This is a shape edge
+
+ if (currInf->shPrev != centerInf)
+ {
+ Point& prevPt = currInf->shPrev->point;
+ int prevDir = vecDir(centerPoint, currPt, prevPt);
+ EdgePair prevPair = EdgePair(*t, currInf->shPrev);
+
+ if (prevDir == BEHIND)
+ {
+ e.remove(prevPair);
+ }
+ else if (prevDir == AHEAD)
+ {
+ e.push_front(prevPair);
+ }
+ }
+
+ if (currInf->shNext != centerInf)
+ {
+ Point& nextPt = currInf->shNext->point;
+ int nextDir = vecDir(centerPoint, currPt, nextPt);
+ EdgePair nextPair = EdgePair(*t, currInf->shNext);
+
+ if (nextDir == BEHIND)
+ {
+ e.remove(nextPair);
+ }
+ else if (nextDir == AHEAD)
+ {
+ e.push_front(nextPair);
+ }
+ }
+ }
+ }
+}
+
+
+}
+
diff --git a/src/3rdparty/adaptagrams/libavoid/visibility.h b/src/3rdparty/adaptagrams/libavoid/visibility.h
new file mode 100644
index 0000000..771d5f5
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/visibility.h
@@ -0,0 +1,41 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2004-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+*/
+
+
+#ifndef AVOID_VISIBILITY_H
+#define AVOID_VISIBILITY_H
+
+
+namespace Avoid {
+
+class VertInf;
+
+extern void vertexVisibility(VertInf *point, VertInf *partner, bool knownNew,
+ const bool gen_contains = false);
+
+}
+
+
+#endif
+
diff --git a/src/3rdparty/adaptagrams/libavoid/vpsc.cpp b/src/3rdparty/adaptagrams/libavoid/vpsc.cpp
new file mode 100644
index 0000000..0a8efb0
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/vpsc.cpp
@@ -0,0 +1,1500 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2005-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+ * Michael Wybrow
+ *
+ * --------------
+ *
+ * This file contains a slightly modified version of IncSolver() from libvpsc:
+ * A solver for the problem of Variable Placement with Separation Constraints.
+ * It has the following changes from the Adaptagrams VPSC version:
+ * - The required VPSC code has been consolidated into a single file.
+ * - Unnecessary code, like the Solver() class, has been removed.
+ * - The PairingHeap code has been replaced by a STL priority_queue.
+ *
+ * Modifications: Michael Wybrow
+ *
+*/
+
+#include "libavoid/vpsc.h"
+
+#ifndef USELIBVPSC
+
+#include <iostream>
+#include <cmath>
+#include <sstream>
+#include <map>
+#include <cfloat>
+#include <cstdio>
+
+#include "libavoid/assertions.h"
+#include "libavoid/debug.h"
+
+
+using namespace std;
+
+namespace Avoid {
+
+static const double ZERO_UPPERBOUND=-1e-10;
+static const double LAGRANGIAN_TOLERANCE=-1e-4;
+
+
+IncSolver::IncSolver(Variables const &vs, Constraints const &cs)
+ : m(cs.size()),
+ cs(cs),
+ n(vs.size()),
+ vs(vs),
+ needsScaling(false)
+{
+ for(unsigned i=0;i<n;++i) {
+ vs[i]->in.clear();
+ vs[i]->out.clear();
+
+ // Set needsScaling if any variables have a scale other than 1.
+ needsScaling |= (vs[i]->scale != 1);
+ }
+ for(unsigned i=0;i<m;++i) {
+ Constraint *c=cs[i];
+ c->left->out.push_back(c);
+ c->right->in.push_back(c);
+ c->needsScaling = needsScaling;
+ }
+ bs=new Blocks(vs);
+#ifdef LIBVPSC_LOGGING
+ printBlocks();
+ //COLA_ASSERT(!constraintGraphIsCyclic(n,vs));
+#endif
+
+ inactive=cs;
+ for(Constraints::iterator i=inactive.begin();i!=inactive.end();++i) {
+ (*i)->active=false;
+ }
+}
+IncSolver::~IncSolver() {
+ delete bs;
+}
+
+void IncSolver::addConstraint(Constraint *c)
+{
+ ++m;
+ c->active = false;
+ inactive.push_back(c);
+ c->left->out.push_back(c);
+ c->right->in.push_back(c);
+ c->needsScaling = needsScaling;
+}
+
+// useful in debugging
+void IncSolver::printBlocks() {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ for(set<Block*>::iterator i=bs->begin();i!=bs->end();++i) {
+ Block *b=*i;
+ f<<" "<<*b<<endl;
+ }
+ for(unsigned i=0;i<m;i++) {
+ f<<" "<<*cs[i]<<endl;
+ }
+#endif
+}
+
+/*
+ * Stores the relative positions of the variables in their finalPosition
+ * field.
+ */
+void IncSolver::copyResult() {
+ for(Variables::const_iterator i=vs.begin();i!=vs.end();++i) {
+ Variable* v=*i;
+ v->finalPosition=v->position();
+ COLA_ASSERT(v->finalPosition==v->finalPosition);
+ }
+}
+
+struct node {
+ set<node*> in;
+ set<node*> out;
+};
+// useful in debugging - cycles would be BAD
+bool IncSolver::constraintGraphIsCyclic(const unsigned n, Variable* const vs[]) {
+ map<Variable*, node*> varmap;
+ vector<node*> graph;
+ for(unsigned i=0;i<n;i++) {
+ node *u=new node;
+ graph.push_back(u);
+ varmap[vs[i]]=u;
+ }
+ for(unsigned i=0;i<n;i++) {
+ for(vector<Constraint*>::iterator c=vs[i]->in.begin();c!=vs[i]->in.end();++c) {
+ Variable *l=(*c)->left;
+ varmap[vs[i]]->in.insert(varmap[l]);
+ }
+
+ for(vector<Constraint*>::iterator c=vs[i]->out.begin();c!=vs[i]->out.end();++c) {
+ Variable *r=(*c)->right;
+ varmap[vs[i]]->out.insert(varmap[r]);
+ }
+ }
+ while(graph.size()>0) {
+ node *u=nullptr;
+ vector<node*>::iterator i=graph.begin();
+ for(;i!=graph.end();++i) {
+ u=*i;
+ if(u->in.size()==0) {
+ break;
+ }
+ }
+ if(i==graph.end() && graph.size()>0) {
+ //cycle found!
+ return true;
+ } else {
+ graph.erase(i);
+ for(set<node*>::iterator j=u->out.begin();j!=u->out.end();++j) {
+ node *v=*j;
+ v->in.erase(u);
+ }
+ delete u;
+ }
+ }
+ for(unsigned i=0; i<graph.size(); ++i) {
+ delete graph[i];
+ }
+ return false;
+}
+
+// useful in debugging - cycles would be BAD
+bool IncSolver::blockGraphIsCyclic() {
+ map<Block*, node*> bmap;
+ vector<node*> graph;
+ size_t length = bs->size();
+ for (size_t i = 0; i < length; ++i)
+ {
+ Block *b = bs->at(i);
+ node *u=new node;
+ graph.push_back(u);
+ bmap[b]=u;
+ }
+ for (size_t i = 0; i < length; ++i)
+ {
+ Block *b = bs->at(i);
+ b->setUpInConstraints();
+ Constraint *c=b->findMinInConstraint();
+ while(c!=nullptr) {
+ Block *l=c->left->block;
+ bmap[b]->in.insert(bmap[l]);
+ b->deleteMinInConstraint();
+ c=b->findMinInConstraint();
+ }
+
+ b->setUpOutConstraints();
+ c=b->findMinOutConstraint();
+ while(c!=nullptr) {
+ Block *r=c->right->block;
+ bmap[b]->out.insert(bmap[r]);
+ b->deleteMinOutConstraint();
+ c=b->findMinOutConstraint();
+ }
+ }
+ while(graph.size()>0) {
+ node *u=nullptr;
+ vector<node*>::iterator i=graph.begin();
+ for(;i!=graph.end();++i) {
+ u=*i;
+ if(u->in.size()==0) {
+ break;
+ }
+ }
+ if(i==graph.end() && graph.size()>0) {
+ //cycle found!
+ return true;
+ } else {
+ graph.erase(i);
+ for(set<node*>::iterator j=u->out.begin();j!=u->out.end();++j) {
+ node *v=*j;
+ v->in.erase(u);
+ }
+ delete u;
+ }
+ }
+ for(unsigned i=0; i<graph.size(); i++) {
+ delete graph[i];
+ }
+ return false;
+}
+
+bool IncSolver::solve() {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<"solve_inc()..."<<endl;
+#endif
+ satisfy();
+ double lastcost = DBL_MAX, cost = bs->cost();
+ while(fabs(lastcost-cost)>0.0001) {
+ satisfy();
+ lastcost=cost;
+ cost = bs->cost();
+#ifdef LIBVPSC_LOGGING
+ f<<" bs->size="<<bs->size()<<", cost="<<cost<<endl;
+#endif
+ }
+ copyResult();
+ return bs->size()!=n;
+}
+/*
+ * incremental version of satisfy that allows refinement after blocks are
+ * moved.
+ *
+ * - move blocks to new positions
+ * - repeatedly merge across most violated constraint until no more
+ * violated constraints exist
+ *
+ * Note: there is a special case to handle when the most violated constraint
+ * is between two variables in the same block. Then, we must split the block
+ * over an active constraint between the two variables. We choose the
+ * constraint with the most negative lagrangian multiplier.
+ */
+bool IncSolver::satisfy() {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<"satisfy_inc()..."<<endl;
+#endif
+ splitBlocks();
+ //long splitCtr = 0;
+ Constraint* v = nullptr;
+ //CBuffer buffer(inactive);
+ while ( (v = mostViolated(inactive)) &&
+ (v->equality || ((v->slack() < ZERO_UPPERBOUND) && !v->active)) )
+ {
+ COLA_ASSERT(!v->active);
+ Block *lb = v->left->block, *rb = v->right->block;
+ if(lb != rb) {
+ lb->merge(rb,v);
+ } else {
+ if(lb->isActiveDirectedPathBetween(v->right,v->left)) {
+ // cycle found, relax the violated, cyclic constraint
+ v->unsatisfiable=true;
+ continue;
+ //UnsatisfiableException e;
+ //lb->getActiveDirectedPathBetween(e.path,v->right,v->left);
+ //e.path.push_back(v);
+ //throw e;
+ }
+ //if(splitCtr++>10000) {
+ //throw "Cycle Error!";
+ //}
+ // constraint is within block, need to split first
+ try {
+ Constraint* splitConstraint
+ =lb->splitBetween(v->left,v->right,lb,rb);
+ if(splitConstraint!=nullptr) {
+ COLA_ASSERT(!splitConstraint->active);
+ inactive.push_back(splitConstraint);
+ } else {
+ v->unsatisfiable=true;
+ continue;
+ }
+ } catch(UnsatisfiableException e) {
+ e.path.push_back(v);
+ /*
+ std::cerr << "Unsatisfiable:" << std::endl;
+ for(std::vector<Constraint*>::iterator r=e.path.begin();
+ r!=e.path.end();++r)
+ {
+ std::cerr << **r <<std::endl;
+ }
+ */
+ v->unsatisfiable=true;
+ continue;
+ }
+ if(v->slack()>=0) {
+ COLA_ASSERT(!v->active);
+ // v was satisfied by the above split!
+ inactive.push_back(v);
+ bs->insert(lb);
+ bs->insert(rb);
+ } else {
+ bs->insert(lb->merge(rb,v));
+ delete ((lb->deleted) ? lb : rb);
+ }
+ }
+#ifdef LIBVPSC_LOGGING
+ f<<"...remaining blocks="<<bs->size()<<", cost="<<bs->cost()<<endl;
+#endif
+ }
+#ifdef LIBVPSC_LOGGING
+ f<<" finished merges."<<endl;
+#endif
+ bs->cleanup();
+ bool activeConstraints=false;
+ for(unsigned i=0;i<m;i++) {
+ v=cs[i];
+ if(v->active) activeConstraints=true;
+ if(v->slack() < ZERO_UPPERBOUND) {
+ ostringstream s;
+ s<<"Unsatisfied constraint: "<<*v;
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<s.str()<<endl;
+#endif
+ throw s.str().c_str();
+ }
+ }
+#ifdef LIBVPSC_LOGGING
+ f<<" finished cleanup."<<endl;
+ printBlocks();
+#endif
+ copyResult();
+ return activeConstraints;
+}
+void IncSolver::moveBlocks() {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<"moveBlocks()..."<<endl;
+#endif
+ size_t length = bs->size();
+ for (size_t i = 0; i < length; ++i)
+ {
+ Block *b = bs->at(i);
+ b->updateWeightedPosition();
+ //b->posn = b->wposn / b->weight;
+ }
+#ifdef LIBVPSC_LOGGING
+ f<<" moved blocks."<<endl;
+#endif
+}
+void IncSolver::splitBlocks() {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+#endif
+ moveBlocks();
+ splitCnt=0;
+ // Split each block if necessary on min LM
+ size_t length = bs->size();
+ for (size_t i = 0; i < length; ++i)
+ {
+ Block *b = bs->at(i);
+ Constraint* v=b->findMinLM();
+ if(v!=nullptr && v->lm < LAGRANGIAN_TOLERANCE) {
+ COLA_ASSERT(!v->equality);
+#ifdef LIBVPSC_LOGGING
+ f<<" found split point: "<<*v<<" lm="<<v->lm<<endl;
+#endif
+ splitCnt++;
+ Block *b = v->left->block, *l=nullptr, *r=nullptr;
+ COLA_ASSERT(v->left->block == v->right->block);
+ //double pos = b->posn;
+ b->split(l,r,v);
+ //l->posn=r->posn=pos;
+ //l->wposn = l->posn * l->weight;
+ //r->wposn = r->posn * r->weight;
+ l->updateWeightedPosition();
+ r->updateWeightedPosition();
+ bs->insert(l);
+ bs->insert(r);
+ b->deleted=true;
+ COLA_ASSERT(!v->active);
+ inactive.push_back(v);
+#ifdef LIBVPSC_LOGGING
+ f<<" new blocks: "<<*l<<" and "<<*r<<endl;
+#endif
+ }
+ }
+ //if(splitCnt>0) { std::cout<<" splits: "<<splitCnt<<endl; }
+#ifdef LIBVPSC_LOGGING
+ f<<" finished splits."<<endl;
+#endif
+ bs->cleanup();
+}
+
+/*
+ * Scan constraint list for the most violated constraint, or the first equality
+ * constraint
+ */
+Constraint* IncSolver::mostViolated(Constraints &l)
+{
+ double slackForMostViolated = DBL_MAX;
+ Constraint* mostViolated = nullptr;
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f << "Looking for most violated..." << endl;
+#endif
+ size_t lSize = l.size();
+ size_t deleteIndex = lSize;
+ Constraint *constraint = nullptr;
+ double slack = 0;
+ for (size_t index = 0; index < lSize; ++index)
+ {
+ constraint = l[index];
+ slack = constraint->slack();
+ if (constraint->equality || slack < slackForMostViolated)
+ {
+ slackForMostViolated = slack;
+ mostViolated = constraint;
+ deleteIndex = index;
+ if (constraint->equality)
+ {
+ break;
+ }
+ }
+ }
+ // Because the constraint list is not order dependent we just
+ // move the last element over the deletePoint and resize
+ // downwards. There is always at least 1 element in the
+ // vector because of search.
+ if ( (deleteIndex < lSize) &&
+ (((slackForMostViolated < ZERO_UPPERBOUND) && !mostViolated->active) ||
+ mostViolated->equality) )
+ {
+ l[deleteIndex] = l[lSize-1];
+ l.resize(lSize-1);
+ }
+#ifdef LIBVPSC_LOGGING
+ if (mostViolated)
+ {
+ f << " most violated is: " << *mostViolated << endl;
+ }
+ else
+ {
+ f << " non found." << endl;
+ }
+#endif
+ return mostViolated;
+}
+
+
+using std::set;
+using std::vector;
+using std::iterator;
+using std::list;
+using std::copy;
+#define __NOTNAN(p) (p)==(p)
+
+
+Blocks::Blocks(vector<Variable*> const &vs) : vs(vs),nvs(vs.size()) {
+ blockTimeCtr=0;
+ m_blocks.resize(nvs);
+ for(size_t i=0;i<nvs;i++) {
+ m_blocks[i] = new Block(this, vs[i]);
+ }
+}
+Blocks::~Blocks(void)
+{
+ blockTimeCtr=0;
+ size_t length = m_blocks.size();
+ for (size_t i = 0; i < length; ++i)
+ {
+ delete m_blocks[i];
+ }
+ m_blocks.clear();
+}
+
+/*
+ * returns a list of variables with total ordering determined by the constraint
+ * DAG
+ */
+list<Variable*> *Blocks::totalOrder() {
+ list<Variable*> *order = new list<Variable*>;
+ for(size_t i=0;i<nvs;i++) {
+ vs[i]->visited=false;
+ }
+ for(size_t i=0;i<nvs;i++) {
+ if(vs[i]->in.size()==0) {
+ dfsVisit(vs[i],order);
+ }
+ }
+ return order;
+}
+// Recursive depth first search giving total order by pushing nodes in the DAG
+// onto the front of the list when we finish searching them
+void Blocks::dfsVisit(Variable *v, list<Variable*> *order) {
+ v->visited=true;
+ vector<Constraint*>::iterator it=v->out.begin();
+ for(;it!=v->out.end();++it) {
+ Constraint *c=*it;
+ if(!c->right->visited) {
+ dfsVisit(c->right, order);
+ }
+ }
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" order="<<*v<<endl;
+#endif
+ order->push_front(v);
+}
+/*
+ * Processes incoming constraints, most violated to least, merging with the
+ * neighbouring (left) block until no more violated constraints are found
+ */
+void Blocks::mergeLeft(Block *r) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<"mergeLeft called on "<<*r<<endl;
+#endif
+ r->timeStamp=++blockTimeCtr;
+ r->setUpInConstraints();
+ Constraint *c=r->findMinInConstraint();
+ while (c != nullptr && c->slack()<0) {
+#ifdef LIBVPSC_LOGGING
+ f<<"mergeLeft on constraint: "<<*c<<endl;
+#endif
+ r->deleteMinInConstraint();
+ Block *l = c->left->block;
+ if (l->in==nullptr) l->setUpInConstraints();
+ double dist = c->right->offset - c->left->offset - c->gap;
+ if (r->vars->size() < l->vars->size()) {
+ dist=-dist;
+ std::swap(l, r);
+ }
+ blockTimeCtr++;
+ r->merge(l, c, dist);
+ r->mergeIn(l);
+ r->timeStamp=blockTimeCtr;
+ removeBlock(l);
+ c=r->findMinInConstraint();
+ }
+#ifdef LIBVPSC_LOGGING
+ f<<"merged "<<*r<<endl;
+#endif
+}
+/*
+ * Symmetrical to mergeLeft
+ */
+void Blocks::mergeRight(Block *l) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<"mergeRight called on "<<*l<<endl;
+#endif
+ l->setUpOutConstraints();
+ Constraint *c = l->findMinOutConstraint();
+ while (c != nullptr && c->slack()<0) {
+#ifdef LIBVPSC_LOGGING
+ f<<"mergeRight on constraint: "<<*c<<endl;
+#endif
+ l->deleteMinOutConstraint();
+ Block *r = c->right->block;
+ r->setUpOutConstraints();
+ double dist = c->left->offset + c->gap - c->right->offset;
+ if (l->vars->size() > r->vars->size()) {
+ dist=-dist;
+ std::swap(l, r);
+ }
+ l->merge(r, c, dist);
+ l->mergeOut(r);
+ removeBlock(r);
+ c=l->findMinOutConstraint();
+ }
+#ifdef LIBVPSC_LOGGING
+ f<<"merged "<<*l<<endl;
+#endif
+}
+void Blocks::removeBlock(Block *doomed) {
+ doomed->deleted=true;
+ //erase(doomed);
+}
+
+// Clears up deleted blocks from the blocks list.
+void Blocks::cleanup(void)
+{
+ // We handle removal of items in-place by doing a single linear pass over
+ // the vector. We use two indexes, j to refer to elements we've checked
+ // from the original list and i to refer to the current position we are
+ // writing in the updated list.
+ size_t i = 0;
+
+ // For all items in the current blocks list...
+ size_t length = m_blocks.size();
+ for (size_t j = 0; j < length; )
+ {
+ if (m_blocks[j]->deleted)
+ {
+ // The element is deleted, so free it and increment j.
+ delete m_blocks[j];
+ ++j;
+ }
+ else
+ {
+ // The current element is still valid.
+ if (j > i)
+ {
+ // If we've not looking at same element, then copy from j to i.
+ m_blocks[i] = m_blocks[j];
+ }
+ // Increment both indexes.
+ ++i;
+ ++j;
+ }
+ }
+ m_blocks.resize(i);
+}
+/*
+ * Splits block b across constraint c into two new blocks, l and r (c's left
+ * and right sides respectively)
+ */
+void Blocks::split(Block *b, Block *&l, Block *&r, Constraint *c) {
+ b->split(l,r,c);
+ m_blocks.push_back(l);
+ m_blocks.push_back(r);
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<"Split left: "<<*l<<endl;
+ f<<"Split right: "<<*r<<endl;
+#endif
+ r->posn = b->posn;
+ //COLA_ASSERT(r->weight!=0);
+ //r->wposn = r->posn * r->weight;
+ mergeLeft(l);
+ // r may have been merged!
+ r = c->right->block;
+ r->updateWeightedPosition();
+ //r->posn = r->wposn / r->weight;
+ mergeRight(r);
+ removeBlock(b);
+
+ COLA_ASSERT(__NOTNAN(l->posn));
+ COLA_ASSERT(__NOTNAN(r->posn));
+}
+/*
+ * returns the cost total squared distance of variables from their desired
+ * positions
+ */
+double Blocks::cost() {
+ double c = 0;
+ size_t length = m_blocks.size();
+ for (size_t i = 0; i < length; ++i)
+ {
+ c += m_blocks[i]->cost();
+ }
+ return c;
+}
+
+void PositionStats::addVariable(Variable* v) {
+ double ai=scale/v->scale;
+ double bi=v->offset/v->scale;
+ double wi=v->weight;
+ AB+=wi*ai*bi;
+ AD+=wi*ai*v->desiredPosition;
+ A2+=wi*ai*ai;
+ /*
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f << "adding v[" << v->id << "], blockscale=" << scale << ", despos="
+ << v->desiredPosition << ", ai=" << ai << ", bi=" << bi
+ << ", AB=" << AB << ", AD=" << AD << ", A2=" << A2;
+#endif
+*/
+}
+void Block::addVariable(Variable* v) {
+ v->block=this;
+ vars->push_back(v);
+ if(ps.A2==0) ps.scale=v->scale;
+ //weight+= v->weight;
+ //wposn += v->weight * (v->desiredPosition - v->offset);
+ //posn=wposn/weight;
+ ps.addVariable(v);
+ posn=(ps.AD - ps.AB) / ps.A2;
+ COLA_ASSERT(__NOTNAN(posn));
+ /*
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f << ", posn=" << posn << endl;
+#endif
+*/
+}
+Block::Block(Blocks *blocks, Variable* const v)
+ : vars(new vector<Variable*>)
+ , posn(0)
+ //, weight(0)
+ //, wposn(0)
+ , deleted(false)
+ , timeStamp(0)
+ , in(nullptr)
+ , out(nullptr)
+ , blocks(blocks)
+{
+ if(v!=nullptr) {
+ v->offset=0;
+ addVariable(v);
+ }
+}
+
+void Block::updateWeightedPosition() {
+ //wposn=0;
+ ps.AB=ps.AD=ps.A2=0;
+ for (Vit v=vars->begin();v!=vars->end();++v) {
+ //wposn += ((*v)->desiredPosition - (*v)->offset) * (*v)->weight;
+ ps.addVariable(*v);
+ }
+ posn=(ps.AD - ps.AB) / ps.A2;
+ COLA_ASSERT(__NOTNAN(posn));
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f << ", posn=" << posn << endl;
+#endif
+}
+Block::~Block(void)
+{
+ delete vars;
+ delete in;
+ delete out;
+}
+void Block::setUpInConstraints() {
+ setUpConstraintHeap(in,true);
+}
+void Block::setUpOutConstraints() {
+ setUpConstraintHeap(out,false);
+}
+void Block::setUpConstraintHeap(Heap* &h,bool in) {
+ delete h;
+ h = new Heap();
+ for (Vit i=vars->begin();i!=vars->end();++i) {
+ Variable *v=*i;
+ vector<Constraint*> *cs=in?&(v->in):&(v->out);
+ for (Cit j=cs->begin();j!=cs->end();++j) {
+ Constraint *c=*j;
+ c->timeStamp=blocks->blockTimeCtr;
+ if ( ((c->left->block != this) && in) ||
+ ((c->right->block != this) && !in) )
+ {
+ h->push(c);
+ }
+ }
+ }
+}
+Block* Block::merge(Block* b, Constraint* c) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" merging on: "<<*c<<",c->left->offset="<<c->left->offset<<",c->right->offset="<<c->right->offset<<endl;
+#endif
+ double dist = c->right->offset - c->left->offset - c->gap;
+ Block *l=c->left->block;
+ Block *r=c->right->block;
+ if (l->vars->size() < r->vars->size()) {
+ r->merge(l,c,dist);
+ } else {
+ l->merge(r,c,-dist);
+ }
+ Block* mergeBlock=b->deleted?this:b;
+#ifdef LIBVPSC_LOGGING
+ f<<" merged block="<<*mergeBlock<<endl;
+#endif
+ return mergeBlock;
+}
+/*
+ * Merges b into this block across c. Can be either a
+ * right merge or a left merge
+ * @param b block to merge into this
+ * @param c constraint being merged
+ * @param distance separation required to satisfy c
+ */
+void Block::merge(Block *b, Constraint *c, double dist) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" merging: "<<*b<<"dist="<<dist<<endl;
+#endif
+ c->active=true;
+ //wposn+=b->wposn-dist*b->weight;
+ //weight+=b->weight;
+ for(Vit i=b->vars->begin();i!=b->vars->end();++i) {
+ Variable *v=*i;
+ //v->block=this;
+ //vars->push_back(v);
+ v->offset+=dist;
+ addVariable(v);
+ }
+#ifdef LIBVPSC_LOGGING
+ for(Vit i=vars->begin();i!=vars->end();++i) {
+ Variable *v=*i;
+ f<<" v["<<v->id<<"]: d="<<v->desiredPosition
+ <<" a="<<v->scale<<" o="<<v->offset
+ <<endl;
+ }
+ f<<" AD="<<ps.AD<<" AB="<<ps.AB<<" A2="<<ps.A2<<endl;
+#endif
+ //posn=wposn/weight;
+ //COLA_ASSERT(wposn==ps.AD - ps.AB);
+ posn=(ps.AD - ps.AB) / ps.A2;
+ COLA_ASSERT(__NOTNAN(posn));
+ b->deleted=true;
+}
+
+void Block::mergeIn(Block *b) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" merging constraint heaps... "<<endl;
+#endif
+ // We check the top of the heaps to remove possible internal constraints
+ findMinInConstraint();
+ b->findMinInConstraint();
+ while (!b->in->empty())
+ {
+ in->push(b->in->top());
+ b->in->pop();
+ }
+#ifdef LIBVPSC_LOGGING
+ f<<" merged heap: "<<*in<<endl;
+#endif
+}
+void Block::mergeOut(Block *b) {
+ findMinOutConstraint();
+ b->findMinOutConstraint();
+ while (!b->out->empty())
+ {
+ out->push(b->out->top());
+ b->out->pop();
+ }
+}
+Constraint *Block::findMinInConstraint() {
+ Constraint *v = nullptr;
+ vector<Constraint*> outOfDate;
+ while (!in->empty()) {
+ v = in->top();
+ Block *lb=v->left->block;
+ Block *rb=v->right->block;
+ // rb may not be this if called between merge and mergeIn
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" checking constraint ... "<<*v;
+ f<<" timestamps: left="<<lb->timeStamp<<" right="<<rb->timeStamp<<" constraint="<<v->timeStamp<<endl;
+#endif
+ if(lb == rb) {
+ // constraint has been merged into the same block
+#ifdef LIBVPSC_LOGGING
+ if(v->slack()<0) {
+ f<<" violated internal constraint found! "<<*v<<endl;
+ f<<" lb="<<*lb<<endl;
+ f<<" rb="<<*rb<<endl;
+ }
+#endif
+ in->pop();
+#ifdef LIBVPSC_LOGGING
+ f<<" ... skipping internal constraint"<<endl;
+#endif
+ } else if(v->timeStamp < lb->timeStamp) {
+ // block at other end of constraint has been moved since this
+ in->pop();
+ outOfDate.push_back(v);
+#ifdef LIBVPSC_LOGGING
+ f<<" reinserting out of date (reinsert later)"<<endl;
+#endif
+ } else {
+ break;
+ }
+ }
+ for(Cit i=outOfDate.begin();i!=outOfDate.end();++i) {
+ v=*i;
+ v->timeStamp=blocks->blockTimeCtr;
+ in->push(v);
+ }
+ if(in->empty()) {
+ v=nullptr;
+ } else {
+ v=in->top();
+ }
+ return v;
+}
+Constraint *Block::findMinOutConstraint() {
+ if(out->empty()) return nullptr;
+ Constraint *v = out->top();
+ while (v->left->block == v->right->block) {
+ out->pop();
+ if(out->empty()) return nullptr;
+ v = out->top();
+ }
+ return v;
+}
+void Block::deleteMinInConstraint() {
+ in->pop();
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<"deleteMinInConstraint... "<<endl;
+ f<<" result: "<<*in<<endl;
+#endif
+}
+void Block::deleteMinOutConstraint() {
+ out->pop();
+}
+inline bool Block::canFollowLeft(Constraint const* c, Variable const* last) const {
+ return c->left->block==this && c->active && last!=c->left;
+}
+inline bool Block::canFollowRight(Constraint const* c, Variable const* last) const {
+ return c->right->block==this && c->active && last!=c->right;
+}
+
+// computes the derivative of v and the lagrange multipliers
+// of v's out constraints (as the recursive sum of those below.
+// Does not backtrack over u.
+// also records the constraint with minimum lagrange multiplier
+// in min_lm
+double Block::compute_dfdv(Variable* const v, Variable* const u,
+ Constraint *&min_lm) {
+ double dfdv=v->dfdv();
+ for(Cit it=v->out.begin();it!=v->out.end();++it) {
+ Constraint *c=*it;
+ if(canFollowRight(c,u)) {
+ c->lm=compute_dfdv(c->right,v,min_lm);
+ dfdv+=c->lm*c->left->scale;
+ if(!c->equality&&(min_lm==nullptr||c->lm<min_lm->lm)) min_lm=c;
+ }
+ }
+ for(Cit it=v->in.begin();it!=v->in.end();++it) {
+ Constraint *c=*it;
+ if(canFollowLeft(c,u)) {
+ c->lm=-compute_dfdv(c->left,v,min_lm);
+ dfdv-=c->lm*c->right->scale;
+ if(!c->equality&&(min_lm==nullptr||c->lm<min_lm->lm)) min_lm=c;
+ }
+ }
+ return dfdv/v->scale;
+}
+double Block::compute_dfdv(Variable* const v, Variable* const u) {
+ double dfdv = v->dfdv();
+ for(Cit it = v->out.begin(); it != v->out.end(); ++it) {
+ Constraint *c = *it;
+ if(canFollowRight(c,u)) {
+ c->lm = compute_dfdv(c->right,v);
+ dfdv += c->lm * c->left->scale;
+ }
+ }
+ for(Cit it=v->in.begin();it!=v->in.end();++it) {
+ Constraint *c = *it;
+ if(canFollowLeft(c,u)) {
+ c->lm = - compute_dfdv(c->left,v);
+ dfdv -= c->lm * c->right->scale;
+ }
+ }
+ return dfdv/v->scale;
+}
+
+// The top level v and r are variables between which we want to find the
+// constraint with the smallest lm.
+// Similarly, m is initially nullptr and is only assigned a value if the next
+// variable to be visited is r or if a possible min constraint is returned from
+// a nested call (rather than nullptr).
+// Then, the search for the m with minimum lm occurs as we return from
+// the recursion (checking only constraints traversed left-to-right
+// in order to avoid creating any new violations).
+// We also do not consider equality constraints as potential split points
+bool Block::split_path(
+ Variable* r,
+ Variable* const v,
+ Variable* const u,
+ Constraint* &m,
+ bool desperation=false
+ )
+{
+ for(Cit it(v->in.begin());it!=v->in.end();++it) {
+ Constraint *c=*it;
+ if(canFollowLeft(c,u)) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" left split path: "<<*c<<endl;
+#endif
+ if(c->left==r) {
+ if(desperation&&!c->equality) m=c;
+ return true;
+ } else {
+ if(split_path(r,c->left,v,m)) {
+ if(desperation && !c->equality && (!m||c->lm<m->lm)) {
+ m=c;
+ }
+ return true;
+ }
+ }
+ }
+ }
+ for(Cit it(v->out.begin());it!=v->out.end();++it) {
+ Constraint *c=*it;
+ if(canFollowRight(c,u)) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" right split path: "<<*c<<endl;
+#endif
+ if(c->right==r) {
+ if(!c->equality) m=c;
+ return true;
+ } else {
+ if(split_path(r,c->right,v,m)) {
+ if(!c->equality && (!m||c->lm<m->lm))
+ m=c;
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+/*
+Block::Pair Block::compute_dfdv_between(
+ Variable* r, Variable* const v, Variable* const u,
+ const Direction dir = NONE, bool changedDirection = false) {
+ double dfdv=v->weight*(v->position() - v->desiredPosition);
+ Constraint *m=nullptr;
+ for(Cit it(v->in.begin());it!=v->in.end();++it) {
+ Constraint *c=*it;
+ if(canFollowLeft(c,u)) {
+ if(dir==RIGHT) {
+ changedDirection = true;
+ }
+ if(c->left==r) {
+ r=nullptr;
+ if(!c->equality) m=c;
+ }
+ Pair p=compute_dfdv_between(r,c->left,v,
+ LEFT,changedDirection);
+ dfdv -= c->lm = -p.first;
+ if(r && p.second)
+ m = p.second;
+ }
+ }
+ for(Cit it(v->out.begin());it!=v->out.end();++it) {
+ Constraint *c=*it;
+ if(canFollowRight(c,u)) {
+ if(dir==LEFT) {
+ changedDirection = true;
+ }
+ if(c->right==r) {
+ r=nullptr;
+ if(!c->equality) m=c;
+ }
+ Pair p=compute_dfdv_between(r,c->right,v,
+ RIGHT,changedDirection);
+ dfdv += c->lm = p.first;
+ if(r && p.second)
+ m = changedDirection && !c->equality && c->lm < p.second->lm
+ ? c
+ : p.second;
+ }
+ }
+ return Pair(dfdv,m);
+}
+*/
+
+// resets LMs for all active constraints to 0 by
+// traversing active constraint tree starting from v,
+// not back tracking over u
+void Block::reset_active_lm(Variable* const v, Variable* const u) {
+ for(Cit it=v->out.begin();it!=v->out.end();++it) {
+ Constraint *c=*it;
+ if(canFollowRight(c,u)) {
+ c->lm=0;
+ reset_active_lm(c->right,v);
+ }
+ }
+ for(Cit it=v->in.begin();it!=v->in.end();++it) {
+ Constraint *c=*it;
+ if(canFollowLeft(c,u)) {
+ c->lm=0;
+ reset_active_lm(c->left,v);
+ }
+ }
+}
+void Block::list_active(Variable* const v, Variable* const u) {
+ for(Cit it=v->out.begin();it!=v->out.end();++it) {
+ Constraint *c=*it;
+ if(canFollowRight(c,u)) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" "<<*c<<endl;
+#endif
+ list_active(c->right,v);
+ }
+ }
+ for(Cit it=v->in.begin();it!=v->in.end();++it) {
+ Constraint *c=*it;
+ if(canFollowLeft(c,u)) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" "<<*c<<endl;
+#endif
+ list_active(c->left,v);
+ }
+ }
+}
+/*
+ * finds the constraint with the minimum lagrange multiplier, that is, the constraint
+ * that most wants to split
+ */
+Constraint *Block::findMinLM() {
+ Constraint *min_lm=nullptr;
+ reset_active_lm(vars->front(),nullptr);
+ compute_dfdv(vars->front(),nullptr,min_lm);
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" langrangians: "<<endl;
+ list_active(vars->front(),nullptr);
+#endif
+ return min_lm;
+}
+Constraint *Block::findMinLMBetween(Variable* const lv, Variable* const rv) {
+ reset_active_lm(vars->front(),nullptr);
+ compute_dfdv(vars->front(),nullptr);
+ Constraint *min_lm=nullptr;
+ split_path(rv,lv,nullptr,min_lm);
+#if 0
+ if(min_lm==nullptr) {
+ split_path(rv,lv,nullptr,min_lm,true);
+ }
+#else
+ if(min_lm==nullptr) {
+ //err_printf("Couldn't find split point!\n");
+ UnsatisfiableException e;
+ getActivePathBetween(e.path,lv,rv,nullptr);
+ throw e;
+ }
+ COLA_ASSERT(min_lm!=nullptr);
+#endif
+ return min_lm;
+}
+
+// populates block b by traversing the active constraint tree adding variables as they're
+// visited. Starts from variable v and does not backtrack over variable u.
+void Block::populateSplitBlock(Block *b, Variable* v, Variable const* u) {
+ b->addVariable(v);
+ for (Cit c=v->in.begin();c!=v->in.end();++c) {
+ if (canFollowLeft(*c,u))
+ populateSplitBlock(b, (*c)->left, v);
+ }
+ for (Cit c=v->out.begin();c!=v->out.end();++c) {
+ if (canFollowRight(*c,u))
+ populateSplitBlock(b, (*c)->right, v);
+ }
+}
+/*
+ * Returns the active path between variables u and v... not back tracking over w
+ */
+bool Block::getActivePathBetween(Constraints& path, Variable const* u,
+ Variable const* v, Variable const *w) const {
+ if(u==v) return true;
+ for (Cit_const c=u->in.begin();c!=u->in.end();++c) {
+ if (canFollowLeft(*c,w)) {
+ if(getActivePathBetween(path, (*c)->left, v, u)) {
+ path.push_back(*c);
+ return true;
+ }
+ }
+ }
+ for (Cit_const c=u->out.begin();c!=u->out.end();++c) {
+ if (canFollowRight(*c,w)) {
+ if(getActivePathBetween(path, (*c)->right, v, u)) {
+ path.push_back(*c);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+// Search active constraint tree from u to see if there is a directed path to v.
+// Returns true if path is found with all constraints in path having their visited flag
+// set true.
+bool Block::isActiveDirectedPathBetween(Variable const* u, Variable const* v) const {
+ if(u==v) return true;
+ for (Cit_const c=u->out.begin();c!=u->out.end();++c) {
+ if(canFollowRight(*c,nullptr)) {
+ if(isActiveDirectedPathBetween((*c)->right,v)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+bool Block::getActiveDirectedPathBetween(
+ Constraints& path, Variable const* u, Variable const* v) const {
+ if(u==v) return true;
+ for (Cit_const c=u->out.begin();c!=u->out.end();++c) {
+ if(canFollowRight(*c,nullptr)) {
+ if(getActiveDirectedPathBetween(path,(*c)->right,v)) {
+ path.push_back(*c);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+/*
+ * Block needs to be split because of a violated constraint between vl and vr.
+ * We need to search the active constraint tree between l and r and find the constraint
+ * with min lagrangrian multiplier and split at that point.
+ * Returns the split constraint
+ */
+Constraint* Block::splitBetween(Variable* const vl, Variable* const vr,
+ Block* &lb, Block* &rb) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" need to split between: "<<*vl<<" and "<<*vr<<endl;
+#endif
+ Constraint *c=findMinLMBetween(vl, vr);
+#ifdef LIBVPSC_LOGGING
+ f<<" going to split on: "<<*c<<endl;
+#endif
+ if(c!=nullptr) {
+ split(lb,rb,c);
+ deleted = true;
+ }
+ return c;
+}
+
+/*
+ * Creates two new blocks, l and r, and splits this block across constraint c,
+ * placing the left subtree of constraints (and associated variables) into l
+ * and the right into r.
+ */
+void Block::split(Block* &l, Block* &r, Constraint* c) {
+ c->active=false;
+ l=new Block(blocks);
+ populateSplitBlock(l,c->left,c->right);
+ //COLA_ASSERT(l->weight>0);
+ r=new Block(blocks);
+ populateSplitBlock(r,c->right,c->left);
+ //COLA_ASSERT(r->weight>0);
+}
+
+/*
+ * Computes the cost (squared euclidean distance from desired positions) of the
+ * current positions for variables in this block
+ */
+double Block::cost() {
+ double c = 0;
+ for (Vit v=vars->begin();v!=vars->end();++v) {
+ double diff = (*v)->position() - (*v)->desiredPosition;
+ c += (*v)->weight * diff * diff;
+ }
+ return c;
+}
+ostream& operator <<(ostream &os, const Block& b)
+{
+ os<<"Block(posn="<<b.posn<<"):";
+ for(Block::Vit v=b.vars->begin();v!=b.vars->end();++v) {
+ os<<" "<<**v;
+ }
+ if(b.deleted) {
+ os<<" Deleted!";
+ }
+ return os;
+}
+
+Constraint::Constraint(Variable *left, Variable *right, double gap, bool equality)
+: left(left),
+ right(right),
+ gap(gap),
+ timeStamp(0),
+ active(false),
+ equality(equality),
+ unsatisfiable(false),
+ needsScaling(true),
+ creator(nullptr)
+{
+ // In hindsight I think it's probably better to build the constraint DAG
+ // (by creating variable in/out lists) when needed, rather than in advance
+ //left->out.push_back(this);
+ //right->in.push_back(this);
+}
+Constraint::~Constraint() {
+ // see constructor: the following is just way too slow.
+ // Better to create a
+ // new DAG on demand than maintain the lists dynamically.
+ //Constraints::iterator i;
+ //for(i=left->out.begin(); i!=left->out.end(); i++) {
+ //if(*i==this) break;
+ //}
+ //left->out.erase(i);
+ //for(i=right->in.begin(); i!=right->in.end(); i++) {
+ //if(*i==this) break;
+ //}
+ //right->in.erase(i);
+}
+std::string Constraint::toString(void) const
+{
+ std::stringstream stream;
+ stream << "Constraint: var(" << left->id << ") ";
+ if (gap < 0)
+ {
+ stream << "- " << -gap << " ";
+ }
+ else
+ {
+ stream << "+ " << gap << " ";
+ }
+ stream << ((equality) ? "==" : "<=");
+ stream << " var(" << right->id << ") ";
+ return stream.str();
+}
+
+std::ostream& operator <<(std::ostream &os, const Constraint &c)
+{
+ const char *type = c.equality ? "=" : "<=";
+ std::ostringstream lscale, rscale;
+ if (c.left->scale != 1)
+ {
+ lscale << c.left->scale << "*";
+ }
+ if (c.right->scale != 1)
+ {
+ rscale << c.right->scale << "*";
+ }
+ os << lscale.str() << *c.left << "+" << c.gap << type <<
+ rscale.str() << *c.right;
+ if (c.left->block && c.right->block)
+ {
+ os << "(" << c.slack() << ")" << (c.active ? "-active" : "") <<
+ "(lm=" << c.lm << ")";
+ }
+ else
+ {
+ os << "(vars have no position)";
+ }
+ return os;
+}
+
+bool CompareConstraints::operator() (
+ Constraint *const &l, Constraint *const &r
+) const {
+ double const sl =
+ l->left->block->timeStamp > l->timeStamp
+ ||l->left->block==l->right->block
+ ?-DBL_MAX:l->slack();
+ double const sr =
+ r->left->block->timeStamp > r->timeStamp
+ ||r->left->block==r->right->block
+ ?-DBL_MAX:r->slack();
+ if(sl==sr) {
+ // arbitrary choice based on id
+ if(l->left->id==r->left->id) {
+ if(l->right->id<r->right->id) return true;
+ return false;
+ }
+ if(l->left->id<r->left->id) return true;
+ return false;
+ }
+ return sl > sr;
+}
+
+std::ostream& operator <<(std::ostream &os, const Variable &v) {
+ if(v.block)
+ os << "(" << v.id << "=" << v.position() << ")";
+ else
+ os << "(" << v.id << "=" << v.desiredPosition << ")";
+ return os;
+}
+
+typedef std::list<std::map<Variable *, double> > VarOffsetMapList;
+
+class EqualityConstraintSet
+{
+ public:
+ EqualityConstraintSet(Variables vs)
+ {
+ for (size_t i = 0; i < vs.size(); ++i)
+ {
+ std::map<Variable *, double> varSet;
+ varSet[vs[i]] = 0;
+ variableGroups.push_back(varSet);
+ }
+ }
+ bool isRedundant(Variable *lhs, Variable *rhs, double sep)
+ {
+ VarOffsetMapList::iterator lhsSet = setForVar(lhs);
+ VarOffsetMapList::iterator rhsSet = setForVar(rhs);
+ if (lhsSet == rhsSet)
+ {
+ // Check if this is a redundant constraint.
+ if (fabs(((*lhsSet)[lhs] + sep) - (*rhsSet)[rhs]) < 0.0001)
+ {
+ // If so, return true.
+ return true;
+ }
+ }
+ return false;
+ }
+ void mergeSets(Variable *lhs, Variable *rhs, double sep)
+ {
+ VarOffsetMapList::iterator lhsSet = setForVar(lhs);
+ VarOffsetMapList::iterator rhsSet = setForVar(rhs);
+ if (lhsSet == rhsSet)
+ {
+ return;
+ }
+
+ double rhsOldOffset = (*rhsSet)[rhs];
+ double rhsNewOffset = (*lhsSet)[lhs] + sep;
+ double offset = rhsNewOffset - rhsOldOffset;
+
+ // Update offsets
+ for (std::map<Variable *, double>::iterator it = rhsSet->begin();
+ it != rhsSet->end(); ++it)
+ {
+ it->second += offset;
+ }
+
+ // Merge rhsSet into lhsSet
+ lhsSet->insert(rhsSet->begin(), rhsSet->end());
+ variableGroups.erase(rhsSet);
+ }
+
+ private:
+ VarOffsetMapList::iterator setForVar(Variable *var)
+ {
+ for (VarOffsetMapList::iterator it = variableGroups.begin();
+ it != variableGroups.end(); ++it)
+ {
+ if (it->find(var) != it->end())
+ {
+ return it;
+ }
+ }
+ return variableGroups.end();
+ }
+
+ VarOffsetMapList variableGroups;
+};
+
+Constraints constraintsRemovingRedundantEqualities(Variables const &vars,
+ Constraints const &constraints)
+{
+ EqualityConstraintSet equalitySets(vars);
+ Constraints cs = Constraints(constraints.size());
+ int csSize = 0;
+
+ for (unsigned i = 0; i < constraints.size(); ++i)
+ {
+ Constraint *c = constraints[i];
+ if (c->equality)
+ {
+ if (!equalitySets.isRedundant(c->left, c->right, c->gap))
+ {
+ // Only add non-redundant equalities
+ equalitySets.mergeSets(c->left, c->right, c->gap);
+ cs[csSize++] = c;
+ }
+ }
+ else
+ {
+ // Add all non-equalities
+ cs[csSize++] = c;
+ }
+ }
+ cs.resize(csSize);
+ return cs;
+}
+
+
+}
+
+#endif
diff --git a/src/3rdparty/adaptagrams/libavoid/vpsc.h b/src/3rdparty/adaptagrams/libavoid/vpsc.h
new file mode 100644
index 0000000..947cb90
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libavoid/vpsc.h
@@ -0,0 +1,341 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libavoid - Fast, Incremental, Object-avoiding Line Router
+ *
+ * Copyright (C) 2005-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * Licensees holding a valid commercial license may use this file in
+ * accordance with the commercial license agreement provided with the
+ * library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+ * Michael Wybrow
+ *
+ * --------------
+ *
+ * This file contains a slightly modified version of IncSolver() from libvpsc:
+ * A solver for the problem of Variable Placement with Separation Constraints.
+ * It has the following changes from the Adaptagrams VPSC version:
+ * - The required VPSC code has been consolidated into a single file.
+ * - Unnecessary code (like Solver) has been removed.
+ * - The PairingHeap code has been replaced by a STL priority_queue.
+ *
+ * Modifications: Michael Wybrow
+ *
+*/
+
+#ifndef LIBAVOID_VPSC_H
+#define LIBAVOID_VPSC_H
+
+
+#ifdef USELIBVPSC
+
+// By default, libavoid will use it's own version of VPSC defined in this file.
+//
+// Alternatively, you can directly use IncSolver from libvpsc. This
+// introduces a dependency on libvpsc but it can be preferable in cases
+// where you are building all of Adaptagrams together and want to work
+// with a set of CompoundConstraints or other classes built upon the
+// base libvpsc Constraint classes.
+
+// Include necessary headers from libvpsc.
+#include "libvpsc/variable.h"
+#include "libvpsc/constraint.h"
+#include "libvpsc/rectangle.h"
+#include "libvpsc/solve_VPSC.h"
+
+// Use the libvpsc versions of things needed by libavoid.
+using vpsc::Variable;
+using vpsc::Variables;
+using vpsc::Constraint;
+using vpsc::Constraints;
+using vpsc::IncSolver;
+using vpsc::delete_object;
+
+#else
+
+#include <vector>
+#include <list>
+#include <set>
+#include <queue>
+#include <iostream>
+#include <cfloat>
+
+#include "libavoid/assertions.h"
+
+namespace Avoid {
+
+class Variable;
+class Constraint;
+class Blocks;
+typedef std::vector<Variable*> Variables;
+typedef std::vector<Constraint*> Constraints;
+class CompareConstraints {
+public:
+ bool operator() (Constraint *const &l, Constraint *const &r) const;
+};
+struct PositionStats {
+ PositionStats() : scale(0), AB(0), AD(0), A2(0) {}
+ void addVariable(Variable* const v);
+ double scale;
+ double AB;
+ double AD;
+ double A2;
+};
+
+typedef std::priority_queue<Constraint*,std::vector<Constraint*>,
+ CompareConstraints> Heap;
+
+class Block
+{
+ typedef Variables::iterator Vit;
+ typedef Constraints::iterator Cit;
+ typedef Constraints::const_iterator Cit_const;
+
+ friend std::ostream& operator <<(std::ostream &os,const Block &b);
+public:
+ Variables *vars;
+ double posn;
+ //double weight;
+ //double wposn;
+ PositionStats ps;
+ Block(Blocks *blocks, Variable* const v=nullptr);
+ ~Block(void);
+ Constraint* findMinLM();
+ Constraint* findMinLMBetween(Variable* const lv, Variable* const rv);
+ Constraint* findMinInConstraint();
+ Constraint* findMinOutConstraint();
+ void deleteMinInConstraint();
+ void deleteMinOutConstraint();
+ void updateWeightedPosition();
+ void merge(Block *b, Constraint *c, double dist);
+ Block* merge(Block *b, Constraint *c);
+ void mergeIn(Block *b);
+ void mergeOut(Block *b);
+ void split(Block *&l, Block *&r, Constraint *c);
+ Constraint* splitBetween(Variable* vl, Variable* vr, Block* &lb, Block* &rb);
+ void setUpInConstraints();
+ void setUpOutConstraints();
+ double cost();
+ bool deleted;
+ long timeStamp;
+ Heap *in;
+ Heap *out;
+ bool getActivePathBetween(Constraints& path, Variable const* u,
+ Variable const* v, Variable const *w) const;
+ bool isActiveDirectedPathBetween(
+ Variable const* u, Variable const* v) const;
+ bool getActiveDirectedPathBetween(Constraints& path, Variable const * u, Variable const * v) const;
+private:
+ typedef enum {NONE, LEFT, RIGHT} Direction;
+ typedef std::pair<double, Constraint*> Pair;
+ void reset_active_lm(Variable* const v, Variable* const u);
+ void list_active(Variable* const v, Variable* const u);
+ double compute_dfdv(Variable* const v, Variable* const u);
+ double compute_dfdv(Variable* const v, Variable* const u, Constraint *&min_lm);
+ bool split_path(Variable*, Variable* const, Variable* const,
+ Constraint* &min_lm, bool desperation);
+ bool canFollowLeft(Constraint const* c, Variable const* last) const;
+ bool canFollowRight(Constraint const* c, Variable const* last) const;
+ void populateSplitBlock(Block *b, Variable* v, Variable const* u);
+ void addVariable(Variable* v);
+ void setUpConstraintHeap(Heap* &h,bool in);
+
+ // Parent container, that holds the blockTimeCtr.
+ Blocks *blocks;
+};
+
+
+class Constraint;
+typedef std::vector<Constraint*> Constraints;
+class Variable
+{
+ friend std::ostream& operator <<(std::ostream &os, const Variable &v);
+ friend class Block;
+ friend class Constraint;
+ friend class IncSolver;
+public:
+ int id; // useful in log files
+ double desiredPosition;
+ double finalPosition;
+ double weight; // how much the variable wants to
+ // be at it's desired position
+ double scale; // translates variable to another space
+ double offset;
+ Block *block;
+ bool visited;
+ bool fixedDesiredPosition;
+ Constraints in;
+ Constraints out;
+ inline Variable(const int id, const double desiredPos=-1.0,
+ const double weight=1.0, const double scale=1.0)
+ : id(id)
+ , desiredPosition(desiredPos)
+ , weight(weight)
+ , scale(scale)
+ , offset(0)
+ , block(nullptr)
+ , visited(false)
+ , fixedDesiredPosition(false)
+ {
+ }
+ double dfdv(void) const {
+ return 2. * weight * ( position() - desiredPosition );
+ }
+private:
+ inline double position(void) const {
+ return (block->ps.scale*block->posn+offset)/scale;
+ }
+ inline double unscaledPosition(void) const {
+ COLA_ASSERT(block->ps.scale == 1);
+ COLA_ASSERT(scale == 1);
+ return block->posn + offset;
+ }
+};
+
+
+class Constraint
+{
+public:
+ Constraint(Variable *left, Variable *right, double gap, bool equality=false);
+ ~Constraint();
+ inline double slack(void) const
+ {
+ if (unsatisfiable)
+ {
+ return DBL_MAX;
+ }
+ if (needsScaling)
+ {
+ return right->scale * right->position() - gap -
+ left->scale * left->position();
+ }
+ COLA_ASSERT(left->scale == 1);
+ COLA_ASSERT(right->scale == 1);
+ return right->unscaledPosition() - gap - left->unscaledPosition();
+ }
+ std::string toString(void) const;
+
+ friend std::ostream& operator <<(std::ostream &os,const Constraint &c);
+ Variable *left;
+ Variable *right;
+ double gap;
+ double lm;
+ long timeStamp;
+ bool active;
+ const bool equality;
+ bool unsatisfiable;
+ bool needsScaling;
+ void *creator;
+};
+/*
+ * A block structure defined over the variables such that each block contains
+ * 1 or more variables, with the invariant that all constraints inside a block
+ * are satisfied by keeping the variables fixed relative to one another
+ */
+class Blocks
+{
+public:
+ Blocks(Variables const &vs);
+ ~Blocks(void);
+ void mergeLeft(Block *r);
+ void mergeRight(Block *l);
+ void split(Block *b, Block *&l, Block *&r, Constraint *c);
+ std::list<Variable*> *totalOrder();
+ void cleanup();
+ double cost();
+
+ size_t size() const;
+ Block *at(size_t index) const;
+ void insert(Block *block);
+
+ long blockTimeCtr;
+private:
+ void dfsVisit(Variable *v, std::list<Variable*> *order);
+ void removeBlock(Block *doomed);
+
+ std::vector<Block *> m_blocks;
+ Variables const &vs;
+ size_t nvs;
+};
+
+inline size_t Blocks::size() const
+{
+ return m_blocks.size();
+}
+
+inline Block *Blocks::at(size_t index) const
+{
+ return m_blocks[index];
+}
+
+inline void Blocks::insert(Block *block)
+{
+ m_blocks.push_back(block);
+}
+
+struct UnsatisfiableException {
+ Constraints path;
+};
+struct UnsatisfiedConstraint {
+ UnsatisfiedConstraint(Constraint& c):c(c) {}
+ Constraint& c;
+};
+/*
+ * Variable Placement with Separation Constraints problem instance
+ */
+class IncSolver {
+public:
+ unsigned splitCnt;
+ bool satisfy();
+ bool solve();
+ void moveBlocks();
+ void splitBlocks();
+ IncSolver(Variables const &vs, Constraints const &cs);
+
+ ~IncSolver();
+ void addConstraint(Constraint *constraint);
+ Variables const & getVariables() { return vs; }
+protected:
+ Blocks *bs;
+ size_t m;
+ Constraints const &cs;
+ size_t n;
+ Variables const &vs;
+ bool needsScaling;
+
+ void printBlocks();
+ void copyResult();
+private:
+ bool constraintGraphIsCyclic(const unsigned n, Variable* const vs[]);
+ bool blockGraphIsCyclic();
+ Constraints inactive;
+ Constraints violated;
+ Constraint* mostViolated(Constraints &l);
+};
+
+struct delete_object
+{
+ template <typename T>
+ void operator()(T *ptr){ delete ptr;}
+};
+
+extern Constraints constraintsRemovingRedundantEqualities(
+ Variables const &vars, Constraints const &constraints);
+
+}
+
+#endif // ! USELIBVPSC
+
+#endif // AVOID_VPSC_H
diff --git a/src/3rdparty/adaptagrams/libcola/CMakeLists.txt b/src/3rdparty/adaptagrams/libcola/CMakeLists.txt
new file mode 100644
index 0000000..59bbacc
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/CMakeLists.txt
@@ -0,0 +1,30 @@
+
+set(libcola_SRC
+ box.cpp
+ cluster.cpp
+ cola.cpp
+ convex_hull.cpp
+ compound_constraints.cpp
+ conjugate_gradient.cpp
+ connected_components.cpp
+ gradient_projection.cpp
+ shapepair.cpp
+ straightener.cpp
+
+
+ # -------
+ # Headers
+ box.h
+ cluster.h
+ cola.h
+ compound_constraints.h
+ conjugate_gradient.h
+ convex_hull.h
+ gradient_projection.h
+ shapepair.cpp
+ shortest_paths.h
+ straightener.h
+)
+
+include_directories("${CMAKE_CURRENT_SOURCE_DIR}/..")
+add_inkscape_lib(cola_LIB "${libcola_SRC}")
diff --git a/src/3rdparty/adaptagrams/libcola/Makefile.am b/src/3rdparty/adaptagrams/libcola/Makefile.am
new file mode 100644
index 0000000..e35f7ae
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/Makefile.am
@@ -0,0 +1,60 @@
+EXTRA_DIST=libcola.pc.in
+
+lib_LTLIBRARIES = libcola.la
+libcola_la_CPPFLAGS = -I$(top_srcdir) $(CAIROMM_CFLAGS) -I$(includedir)/libcola -fPIC
+
+# Depends on libvpsc
+libcola_la_LIBADD = $(top_builddir)/libvpsc/libvpsc.la $(CAIROMM_LIBS)
+
+libcola_la_SOURCES = cola.h\
+ cola.cpp\
+ colafd.cpp\
+ conjugate_gradient.cpp\
+ conjugate_gradient.h\
+ exceptions.h\
+ gradient_projection.cpp\
+ gradient_projection.h\
+ shortest_paths.h\
+ straightener.h\
+ straightener.cpp\
+ connected_components.cpp\
+ convex_hull.h\
+ convex_hull.cpp\
+ cluster.cpp\
+ compound_constraints.h\
+ compound_constraints.cpp\
+ pseudorandom.h \
+ pseudorandom.cpp \
+ output_svg.cpp\
+ output_svg.h \
+ unused.h \
+ cc_clustercontainmentconstraints.cpp \
+ cc_clustercontainmentconstraints.h \
+ cc_nonoverlapconstraints.cpp \
+ cc_nonoverlapconstraints.h \
+ box.cpp \
+ box.h \
+ shapepair.cpp \
+ shapepainr.h
+
+libcolaincludedir = $(includedir)/libcola
+libcolainclude_HEADERS = cola.h\
+ cluster.h\
+ commondefs.h\
+ compound_constraints.h\
+ pseudorandom.h \
+ exceptions.h\
+ gradient_projection.h\
+ sparse_matrix.h\
+ straightener.h \
+ output_svg.h \
+ unused.h \
+ cc_clustercontainmentconstraints.h \
+ cc_nonoverlapconstraints.h \
+ box.h \
+ shapepair.h
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = libcola.pc
+
+SUBDIRS = . tests
diff --git a/src/3rdparty/adaptagrams/libcola/box.cpp b/src/3rdparty/adaptagrams/libcola/box.cpp
new file mode 100644
index 0000000..8ad3cba
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/box.cpp
@@ -0,0 +1,111 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+ *
+*/
+
+#include "libcola/box.h"
+
+namespace cola {
+
+Box::Box(double xMin, double xMax, double yMin, double yMax)
+{
+ m_min[vpsc::XDIM] = nonNegative(xMin);
+ m_max[vpsc::XDIM] = nonNegative(xMax);
+ m_min[vpsc::YDIM] = nonNegative(yMin);
+ m_max[vpsc::YDIM] = nonNegative(yMax);
+}
+
+Box::Box(double all)
+{
+ double value = nonNegative(all);
+ m_min[vpsc::XDIM] = value;
+ m_max[vpsc::XDIM] = value;
+ m_min[vpsc::YDIM] = value;
+ m_max[vpsc::YDIM] = value;
+}
+
+Box::Box()
+{
+ m_min[vpsc::XDIM] = 0;
+ m_max[vpsc::XDIM] = 0;
+ m_min[vpsc::YDIM] = 0;
+ m_max[vpsc::YDIM] = 0;
+}
+
+Box::~Box()
+{
+}
+
+bool Box::empty(void) const
+{
+ // values will be nonnegative so can sum to check if empty.
+ int total = m_min[vpsc::XDIM] + m_max[vpsc::XDIM] +
+ m_min[vpsc::YDIM] + m_max[vpsc::YDIM];
+ return (total == 0);
+}
+
+void Box::outputCode(FILE *fp) const
+{
+ if ((m_min[vpsc::XDIM] == m_max[vpsc::XDIM]) &&
+ (m_min[vpsc::XDIM] == m_min[vpsc::YDIM]) &&
+ (m_min[vpsc::XDIM] == m_max[vpsc::YDIM]))
+ {
+ fprintf(fp, "Box(%g)", m_min[vpsc::XDIM]);
+ }
+ else
+ {
+ fprintf(fp, "Box(%g, %g, %g, %g)", m_min[vpsc::XDIM],
+ m_max[vpsc::XDIM], m_min[vpsc::YDIM], m_max[vpsc::YDIM]);
+ }
+}
+
+vpsc::Rectangle Box::rectangleByApplyingBox(
+ const vpsc::Rectangle rectangle) const
+{
+ if (!rectangle.isValid())
+ {
+ return rectangle;
+ }
+
+ return vpsc::Rectangle(
+ rectangle.getMinX() - m_min[vpsc::XDIM],
+ rectangle.getMaxX() + m_max[vpsc::XDIM],
+ rectangle.getMinY() - m_min[vpsc::YDIM],
+ rectangle.getMaxY() + m_max[vpsc::YDIM]);
+}
+
+double Box::nonNegative(double value)
+{
+ return (value >= 0) ? value: 0;
+}
+
+double Box::min(size_t dim) const
+{
+ return (dim < 2) ? m_min[dim] : 0;
+}
+
+double Box::max(size_t dim) const
+{
+ return (dim < 2) ? m_max[dim] : 0;
+}
+
+
+}
+
diff --git a/src/3rdparty/adaptagrams/libcola/box.h b/src/3rdparty/adaptagrams/libcola/box.h
new file mode 100644
index 0000000..ff8f018
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/box.h
@@ -0,0 +1,82 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+ *
+*/
+
+#ifndef LIBCOLA_BOX_H
+#define LIBCOLA_BOX_H
+
+#include <cstdio>
+
+#include "libvpsc/rectangle.h"
+
+
+namespace cola {
+
+/**
+ * @brief A box consisting of four edge values for representing padding or
+ * margins for rectangles.
+ */
+class Box
+{
+ public:
+ /**
+ * @brief Constructs a padding or margin box consisting of a value for
+ * each edge.
+ *
+ * Values should be nonnegative.
+ *
+ * @param[in] xMin Minimum horizontal value.
+ * @param[in] xMax Maximum horizontal value.
+ * @param[in] yMin Minimum vertical value.
+ * @param[in] yMax Maximum vertical value.
+ */
+ Box(double xMin, double xMax, double yMin, double yMax);
+ /**
+ * @brief Constructs a padding or margin box consisting of a value for
+ * each edge.
+ *
+ * Values should be nonnegative.
+ *
+ * @param[in] all The value to be used for all four edges.
+ */
+ Box(double all);
+ /**
+ * @brief Constructs an empty padding or margin box.
+ */
+ Box();
+ ~Box();
+
+ bool empty(void) const;
+ double min(size_t dim) const;
+ double max(size_t dim) const;
+ void outputCode(FILE *fp) const;
+ vpsc::Rectangle rectangleByApplyingBox(
+ const vpsc::Rectangle rectangle) const;
+
+ private:
+ static double nonNegative(double value);
+
+ double m_min[2];
+ double m_max[2];
+};
+
+} // namespace cola
+#endif
diff --git a/src/3rdparty/adaptagrams/libcola/cc_clustercontainmentconstraints.cpp b/src/3rdparty/adaptagrams/libcola/cc_clustercontainmentconstraints.cpp
new file mode 100644
index 0000000..390f5e1
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/cc_clustercontainmentconstraints.cpp
@@ -0,0 +1,194 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2010 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+ *
+*/
+
+#include <sstream>
+
+#include "libcola/cola.h"
+#include "libcola/compound_constraints.h"
+#include "libcola/cc_clustercontainmentconstraints.h"
+
+using vpsc::XDIM;
+using vpsc::YDIM;
+
+
+namespace cola {
+
+static const int AboveBoundary = 1;
+static const int BelowBoundary = -1;
+
+class ClusterShapeOffsets : public SubConstraintInfo
+{
+ public:
+ ClusterShapeOffsets(unsigned ind, vpsc::Dim dim, double offset, int boundarySide,
+ unsigned int boundaryVar) :
+ SubConstraintInfo(ind),
+ offset(offset),
+ dim(dim),
+ boundarySide(boundarySide),
+ boundaryVar(boundaryVar)
+ {
+ }
+ double offset; // half the width or height value
+ vpsc::Dim dim; // The dimension
+ int boundarySide; // The boundary side we are constraining on.
+ unsigned int boundaryVar; // The boundary var.
+};
+
+
+ClusterContainmentConstraints::ClusterContainmentConstraints(Cluster *cluster,
+ unsigned int priority, std::vector<vpsc::Rectangle*>& boundingBoxes)
+ : CompoundConstraint(vpsc::HORIZONTAL, priority)
+{
+ Box padding = cluster->padding();
+ _combineSubConstraints = true;
+ for (std::set<unsigned>::iterator curr = cluster->nodes.begin();
+ curr != cluster->nodes.end(); ++curr)
+ {
+ unsigned id = *curr;
+ double halfW = (boundingBoxes[id]->width() / 2.0);
+ double halfH = (boundingBoxes[id]->height() / 2.0);
+ _subConstraintInfo.push_back(new ClusterShapeOffsets(
+ id, XDIM, halfW + padding.min(XDIM), AboveBoundary,
+ cluster->clusterVarId));
+ _subConstraintInfo.push_back(new ClusterShapeOffsets(
+ id, XDIM, halfW + padding.max(XDIM), BelowBoundary,
+ cluster->clusterVarId + 1));
+ _subConstraintInfo.push_back(new ClusterShapeOffsets(
+ id, YDIM, halfH + padding.min(YDIM), AboveBoundary,
+ cluster->clusterVarId));
+ _subConstraintInfo.push_back(new ClusterShapeOffsets(
+ id, YDIM, halfH + padding.max(YDIM), BelowBoundary,
+ cluster->clusterVarId + 1));
+ }
+ for (std::vector<Cluster *>::iterator curr = cluster->clusters.begin();
+ curr != cluster->clusters.end(); ++curr)
+ {
+ Cluster *childCluster = *curr;
+ Box margin = childCluster->margin();
+ _subConstraintInfo.push_back(new ClusterShapeOffsets(
+ childCluster->clusterVarId, XDIM,
+ padding.min(XDIM) + margin.min(XDIM), AboveBoundary,
+ cluster->clusterVarId));
+ _subConstraintInfo.push_back(new ClusterShapeOffsets(
+ childCluster->clusterVarId + 1, XDIM,
+ padding.max(XDIM) + margin.max(XDIM), BelowBoundary,
+ cluster->clusterVarId + 1));
+ _subConstraintInfo.push_back(new ClusterShapeOffsets(
+ childCluster->clusterVarId, YDIM,
+ padding.min(YDIM) + margin.min(YDIM), AboveBoundary,
+ cluster->clusterVarId));
+ _subConstraintInfo.push_back(new ClusterShapeOffsets(
+ childCluster->clusterVarId + 1, YDIM,
+ padding.max(YDIM) + margin.max(YDIM), BelowBoundary,
+ cluster->clusterVarId + 1));
+ }
+}
+
+
+std::string ClusterContainmentConstraints::toString(void) const
+{
+ std::ostringstream stream;
+ stream << "ClusterContainmentConstraints()";
+ return stream.str();
+}
+
+
+void ClusterContainmentConstraints::generateVariables(const vpsc::Dim dim,
+ vpsc::Variables& vars)
+{
+ COLA_UNUSED(dim);
+ COLA_UNUSED(vars);
+}
+
+
+
+SubConstraintAlternatives
+ClusterContainmentConstraints::getCurrSubConstraintAlternatives(vpsc::Variables vs[])
+{
+ SubConstraintAlternatives alternatives;
+
+ ClusterShapeOffsets *info = static_cast<ClusterShapeOffsets *>
+ (_subConstraintInfo[_currSubConstraintIndex]);
+
+ assertValidVariableIndex(vs[_primaryDim], info->varIndex);
+ if (info->boundarySide == BelowBoundary)
+ {
+ // Constrain the objects with negative offsets to be
+ // to the left of the boundary.
+ vpsc::Constraint constraint = vpsc::Constraint(
+ vs[info->dim][info->varIndex], vs[info->dim][info->boundaryVar],
+ info->offset);
+ alternatives.push_back(SubConstraint(info->dim, constraint));
+ }
+ else
+ {
+ // Constrain the objects with positive offsets to be
+ // to the right of the boundary.
+ vpsc::Constraint constraint = vpsc::Constraint(
+ vs[info->dim][info->boundaryVar], vs[info->dim][info->varIndex],
+ info->offset);
+ alternatives.push_back(SubConstraint(info->dim, constraint));
+ }
+
+ //fprintf(stderr, "===== BOUNDARYLINE ALTERNATIVES -======\n");
+ return alternatives;
+}
+
+
+void ClusterContainmentConstraints::generateSeparationConstraints(
+ const vpsc::Dim dim, vpsc::Variables& vs, vpsc::Constraints& cs,
+ std::vector<vpsc::Rectangle*>& bbs)
+{
+ COLA_UNUSED(bbs);
+ for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin();
+ o != _subConstraintInfo.end(); ++o)
+ {
+ ClusterShapeOffsets *info = static_cast<ClusterShapeOffsets *> (*o);
+
+ if (info->dim != dim)
+ {
+ continue;
+ }
+
+ vpsc::Constraint *constraint = nullptr;
+ if (info->boundarySide == BelowBoundary)
+ {
+ // Constrain the objects with negative offsets to be
+ // to the left of the boundary.
+ constraint = new vpsc::Constraint(vs[info->varIndex],
+ vs[info->boundaryVar], info->offset);
+ }
+ else
+ {
+ // Constrain the objects with positive offsets to be
+ // to the right of the boundary.
+ constraint = new vpsc::Constraint(vs[info->boundaryVar],
+ vs[info->varIndex], info->offset);
+ }
+ constraint->creator = this;
+ cs.push_back(constraint);
+ }
+}
+
+
+} // namespace cola
+
diff --git a/src/3rdparty/adaptagrams/libcola/cc_clustercontainmentconstraints.h b/src/3rdparty/adaptagrams/libcola/cc_clustercontainmentconstraints.h
new file mode 100644
index 0000000..5fbe75e
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/cc_clustercontainmentconstraints.h
@@ -0,0 +1,52 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2010 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+ *
+*/
+
+#ifndef COLA_CC_CLUSTERCONTAINMENTCONSTRAINTS_H
+#define COLA_CC_CLUSTERCONTAINMENTCONSTRAINTS_H
+
+#include <vector>
+#include "libcola/compound_constraints.h"
+
+namespace vpsc {
+class Rectangle;
+}
+
+namespace cola {
+
+class ClusterContainmentConstraints : public CompoundConstraint
+{
+ public:
+ ClusterContainmentConstraints(Cluster *cluster, unsigned int priority,
+ std::vector<vpsc::Rectangle*>& boundingBoxes);
+ SubConstraintAlternatives getCurrSubConstraintAlternatives(
+ vpsc::Variables vs[]);
+
+ void generateVariables(const vpsc::Dim dim, vpsc::Variables& vars);
+ void generateSeparationConstraints(const vpsc::Dim dim,
+ vpsc::Variables& vars, vpsc::Constraints& cs,
+ std::vector<vpsc::Rectangle*>& bbs);
+ std::string toString(void) const;
+};
+
+
+} // namespace cola
+#endif // COLA_CC_CLUSTERCONTAINMENTCONSTRAINTS
diff --git a/src/3rdparty/adaptagrams/libcola/cc_nonoverlapconstraints.cpp b/src/3rdparty/adaptagrams/libcola/cc_nonoverlapconstraints.cpp
new file mode 100644
index 0000000..69502d0
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/cc_nonoverlapconstraints.cpp
@@ -0,0 +1,590 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2010-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+ *
+*/
+
+#include <sstream>
+
+#include "libcola/cola.h"
+#include "libcola/compound_constraints.h"
+#include "libcola/cc_nonoverlapconstraints.h"
+
+using vpsc::XDIM;
+using vpsc::YDIM;
+
+
+namespace cola {
+
+//-----------------------------------------------------------------------------
+// NonOverlapConstraintExemptions code
+//-----------------------------------------------------------------------------
+
+NonOverlapConstraintExemptions::NonOverlapConstraintExemptions()
+{
+}
+
+void NonOverlapConstraintExemptions::addExemptGroupOfNodes(
+ ListOfNodeIndexes listOfNodeGroups)
+{
+ m_exempt_pairs.clear();
+
+ const size_t listSize = listOfNodeGroups.size();
+ for (size_t l = 0; l < listSize; ++l)
+ {
+ NodeIndexes ids(listOfNodeGroups[l]);
+
+ // Sort and remove duplicate IDs for this group.
+ std::sort(ids.begin(), ids.end());
+ NodeIndexes::iterator last = std::unique(ids.begin(), ids.end());
+ ids.erase(last, ids.end());
+
+ // Add all combinations of pairs of IDs for this group to m_exempt_pairs
+ const size_t idsSize = ids.size();
+ for (size_t i = 0; i < idsSize; ++i)
+ {
+ for (size_t j = i + 1; j < idsSize; ++j)
+ {
+ m_exempt_pairs.insert(ShapePair(ids[i], ids[j]));
+ }
+ }
+
+ }
+}
+
+bool NonOverlapConstraintExemptions::shapePairIsExempt(
+ ShapePair shapePair) const
+{
+ return (m_exempt_pairs.count(shapePair) == 1);
+}
+
+//-----------------------------------------------------------------------------
+// NonOverlapConstraints code
+//-----------------------------------------------------------------------------
+
+NonOverlapConstraints::NonOverlapConstraints(
+ NonOverlapConstraintExemptions *exemptions, unsigned int priority)
+ : CompoundConstraint(vpsc::HORIZONTAL, priority),
+ pairInfoListSorted(false),
+ initialSortCompleted(false),
+ m_exemptions(exemptions)
+{
+ // All work is done by repeated addShape() calls.
+}
+
+void NonOverlapConstraints::addShape(unsigned id, double halfW, double halfH,
+ unsigned int group, std::set<unsigned> exemptions)
+{
+ // Setup pairInfos for all other shapes.
+ for (std::map<unsigned, OverlapShapeOffsets>::iterator curr =
+ shapeOffsets.begin(); curr != shapeOffsets.end(); ++curr)
+ {
+ unsigned otherId = curr->first;
+ if ((shapeOffsets[otherId].group == group) && (id != otherId) && exemptions.count(otherId)==0)
+ {
+ if (m_exemptions &&
+ m_exemptions->shapePairIsExempt(ShapePair(otherId, id)))
+ {
+ continue;
+ }
+
+ // Apply non-overlap only to objects in the same group (cluster).
+ pairInfoList.push_back(ShapePairInfo(otherId, id));
+ }
+ }
+
+ shapeOffsets[id] = OverlapShapeOffsets(id, halfW, halfH, group);
+}
+
+void NonOverlapConstraints::resizeShape(unsigned id, double halfW, double halfH)
+{
+ OverlapShapeOffsets oso = shapeOffsets[id];
+ oso.resize(halfW, halfH);
+}
+
+void NonOverlapConstraints::removeShape(unsigned id)
+{
+ // Remove the OverlapShapeOffsets object for this id.
+ shapeOffsets.erase(id);
+ // Remove all ShapePairInfo objects having this id as one of their two indices.
+ std::list<ShapePairInfo>::iterator it = pairInfoList.begin();
+ while (it != pairInfoList.end()) {
+ ShapePairInfo spi = *it;
+ if (spi.varIndex1==id || spi.varIndex2==id) {
+ it = pairInfoList.erase(it); // now it points to next list element after one erased
+ } else {
+ it++;
+ }
+ }
+}
+
+// This is expected to be called after all addNode calls.
+void NonOverlapConstraints::addCluster(Cluster *cluster, unsigned int group)
+{
+ unsigned id = cluster->clusterVarId;
+ // Setup pairInfos for all other shapes.
+ for (std::map<unsigned, OverlapShapeOffsets>::iterator curr =
+ shapeOffsets.begin(); curr != shapeOffsets.end(); ++curr)
+ {
+ unsigned otherId = curr->first;
+ if (shapeOffsets[otherId].group != group)
+ {
+ // Don't apply if not in same group.
+ continue;
+ }
+ if (cluster->nodes.count(otherId) > 0)
+ {
+ // Don't apply non-overlap to child nodes.
+ continue;
+ }
+ if (m_cluster_cluster_exemptions.count(ShapePair(id, otherId)) > 0)
+ {
+ // Don't apply if exempt due to non-strict cluster hierarchy.
+ continue;
+ }
+ // Apply non-overlap only to objects in the same group (cluster).
+ pairInfoList.push_back(ShapePairInfo(otherId, id));
+ }
+
+ shapeOffsets[id] = OverlapShapeOffsets(id, cluster, group);
+}
+
+
+void NonOverlapConstraints::setClusterClusterExemptions(
+ std::set<ShapePair> exemptions)
+{
+ m_cluster_cluster_exemptions = exemptions;
+}
+
+void NonOverlapConstraints::generateVariables(const vpsc::Dim dim,
+ vpsc::Variables& vars)
+{
+ COLA_UNUSED(dim);
+ COLA_UNUSED(vars);
+}
+
+void NonOverlapConstraints::computeOverlapForShapePairInfo(ShapePairInfo& info,
+ vpsc::Variables vs[])
+{
+ OverlapShapeOffsets& shape1 = shapeOffsets[info.varIndex1];
+ OverlapShapeOffsets& shape2 = shapeOffsets[info.varIndex2];
+
+ double xPos1 = vs[0][info.varIndex1]->finalPosition;
+ double xPos2 = vs[0][info.varIndex2]->finalPosition;
+ double yPos1 = vs[1][info.varIndex1]->finalPosition;
+ double yPos2 = vs[1][info.varIndex2]->finalPosition;
+
+ double left1 = xPos1 - shape1.halfDim[0];
+ double right1 = xPos1 + shape1.halfDim[0];
+ double bottom1 = yPos1 - shape1.halfDim[1];
+ double top1 = yPos1 + shape1.halfDim[1];
+
+ if (shape1.cluster)
+ {
+ COLA_ASSERT(shape1.halfDim[0] == 0);
+ COLA_ASSERT(shape1.halfDim[1] == 0);
+ COLA_ASSERT(info.varIndex1 + 1 < vs[0].size());
+ right1 = vs[0][info.varIndex1 + 1]->finalPosition;
+ COLA_ASSERT(info.varIndex1 + 1 < vs[1].size());
+ top1 = vs[1][info.varIndex1 + 1]->finalPosition;
+ left1 -= shape1.rectPadding.min(XDIM);
+ bottom1 -= shape1.rectPadding.min(YDIM);
+ right1 += shape1.rectPadding.max(XDIM);
+ top1 += shape1.rectPadding.max(YDIM);
+ }
+
+ double left2 = xPos2 - shape2.halfDim[0];
+ double right2 = xPos2 + shape2.halfDim[0];
+ double bottom2 = yPos2 - shape2.halfDim[1];
+ double top2 = yPos2 + shape2.halfDim[1];
+
+ if (shape2.cluster)
+ {
+ COLA_ASSERT(shape2.halfDim[0] == 0);
+ COLA_ASSERT(shape2.halfDim[1] == 0);
+ COLA_ASSERT(info.varIndex2 + 1 < vs[0].size());
+ right2 = vs[0][info.varIndex2 + 1]->finalPosition;
+ COLA_ASSERT(info.varIndex2 + 1 < vs[1].size());
+ top2 = vs[1][info.varIndex2 + 1]->finalPosition;
+ left2 -= shape2.rectPadding.min(XDIM);
+ bottom2 -= shape2.rectPadding.min(YDIM);
+ right2 += shape2.rectPadding.max(XDIM);
+ top2 += shape2.rectPadding.max(YDIM);
+ }
+
+ // If lr < 0, then left edge of shape1 is on the left
+ // of right edge of shape2.
+ double spaceR = left2 - right1;
+ double spaceL = left1 - right2;
+ // Below
+ double spaceA = bottom2 - top1;
+ // Above
+ double spaceB = bottom1 - top2;
+
+ double costL = 0;
+ double costR = 0;
+ double costB = 0;
+ double costA = 0;
+ info.overlapMax = 0;
+ bool xOverlap = false;
+ bool yOverlap = false;
+ if ((spaceR < 0) && (spaceL < 0))
+ {
+ costL = std::max(-spaceL, 0.0);
+ costR = std::max(-spaceR, 0.0);
+
+ info.overlapMax = std::max(costL, costR);
+
+ xOverlap = true;
+ }
+ if ((spaceB < 0) && (spaceA < 0))
+ {
+ costB = std::max(-spaceB, 0.0);
+ costA = std::max(-spaceA, 0.0);
+
+ info.overlapMax = std::max(info.overlapMax, costB);
+ info.overlapMax = std::max(info.overlapMax, costA);
+
+ yOverlap = true;
+ }
+
+ if (!xOverlap || !yOverlap)
+ {
+ // Overlap must occur in both dimensions.
+ info.overlapMax = 0;
+ }
+ else
+ {
+ // Increase the overlap value for overlap where one shape is fully
+ // within the other. This results in these situations being
+ // resolved first and will sometimes prevent us from committing to
+ // bad non-overlap choices and getting stuck later.
+ // XXX Another alternative would be to look at previously added
+ // non-overlap constraints that become unsatified and then
+ // allow them to be rechosen maybe just a single time.
+ double penalty = 100000;
+ if ( (left1 >= left2) && (right1 <= right2) &&
+ (bottom1 >= bottom2) && (top1 <= top2) )
+ {
+ // Shape 1 is inside shape 2.
+ double smallShapeArea = (right1 - left1) * (top1 - bottom1);
+ info.overlapMax = penalty + smallShapeArea;
+ }
+ else if ( (left2 >= left1) && (right2 <= right1) &&
+ (bottom2 >= bottom1) && (top2 <= top1) )
+ {
+ // Shape 2 is inside shape 1.
+ double smallShapeArea = (right2 - left2) * (top2 - bottom2);
+ info.overlapMax = penalty + smallShapeArea;
+ }
+ // There is overlap.
+ //printf("[%02d][%02d] L %g, R %G, B %g, A %g\n", info.varIndex1,
+ // info.varIndex2, spaceL, spaceR, spaceB, spaceA);
+ }
+}
+
+std::string NonOverlapConstraints::toString(void) const
+{
+ std::ostringstream stream;
+ stream << "NonOverlapConstraints()";
+ return stream.str();
+}
+
+void NonOverlapConstraints::computeAndSortOverlap(vpsc::Variables vs[])
+{
+ for (std::list<ShapePairInfo>::iterator curr = pairInfoList.begin();
+ curr != pairInfoList.end(); ++curr)
+ {
+ ShapePairInfo& info = static_cast<ShapePairInfo&> (*curr);
+
+ if (info.processed)
+ {
+ // Once we reach the processed nodes, which will always be at
+ // the back, we can some computing overlap since this no longer
+ // matters.
+ break;
+ }
+ computeOverlapForShapePairInfo(info, vs);
+ }
+ pairInfoList.sort();
+}
+
+
+void NonOverlapConstraints::markCurrSubConstraintAsActive(const bool satisfiable)
+{
+ ShapePairInfo info = pairInfoList.front();
+ pairInfoList.pop_front();
+
+ info.processed = true;
+ info.satisfied = satisfiable;
+ info.overlapMax = 0;
+
+ pairInfoList.push_back(info);
+ pairInfoListSorted = false;
+}
+
+
+
+SubConstraintAlternatives
+NonOverlapConstraints::getCurrSubConstraintAlternatives(vpsc::Variables vs[])
+{
+ SubConstraintAlternatives alternatives;
+ if (initialSortCompleted == false)
+ {
+ // Initally sort the shape pair info objects.
+ computeAndSortOverlap(vs);
+ pairInfoListSorted = true;
+ initialSortCompleted = true;
+ }
+
+ // Take the first in the list.
+ ShapePairInfo& info = pairInfoList.front();
+ if (pairInfoListSorted == false)
+ {
+ // Only need to compute if not sorted.
+ computeOverlapForShapePairInfo(info, vs);
+ }
+
+ if (info.overlapMax == 0)
+ {
+ if (pairInfoListSorted)
+ {
+ // Seeing no overlap in the sorted list means we have solved
+ // all non-overlap. Nothing more to do.
+ _currSubConstraintIndex = pairInfoList.size();
+ return alternatives;
+ }
+ computeAndSortOverlap(vs);
+ pairInfoListSorted = true;
+ return alternatives;
+ }
+ OverlapShapeOffsets& shape1 = shapeOffsets[info.varIndex1];
+ OverlapShapeOffsets& shape2 = shapeOffsets[info.varIndex2];
+
+ double xSepL = shape1.halfDim[0] + shape2.halfDim[0];
+ double ySepB = shape1.halfDim[1] + shape2.halfDim[1];
+ double xSepR = xSepL;
+ double ySepT = ySepB;
+
+ unsigned varIndexL1 = info.varIndex1;
+ unsigned varIndexL2 = info.varIndex2;
+ // Clusters have left and right variables, instead of centre variables.
+ unsigned varIndexR1 =
+ (shape1.cluster) ? (info.varIndex1 + 1) : info.varIndex1;
+ unsigned varIndexR2 =
+ (shape2.cluster) ? (info.varIndex2 + 1) : info.varIndex2;
+
+ assertValidVariableIndex(vs[XDIM], varIndexL1);
+ assertValidVariableIndex(vs[YDIM], varIndexL1);
+ assertValidVariableIndex(vs[XDIM], varIndexR1);
+ assertValidVariableIndex(vs[YDIM], varIndexR1);
+ assertValidVariableIndex(vs[XDIM], varIndexL2);
+ assertValidVariableIndex(vs[YDIM], varIndexL2);
+ assertValidVariableIndex(vs[XDIM], varIndexR2);
+ assertValidVariableIndex(vs[YDIM], varIndexR2);
+
+ //
+ double xSepCostL = xSepL;
+ double xSepCostR = xSepR;
+ double ySepCostB = ySepB;
+ double ySepCostT = ySepT;
+
+ double desiredX1 = vs[XDIM][info.varIndex1]->desiredPosition;
+ double desiredY1 = vs[YDIM][info.varIndex1]->desiredPosition;
+ double desiredX2 = vs[XDIM][info.varIndex2]->desiredPosition;
+ double desiredY2 = vs[YDIM][info.varIndex2]->desiredPosition;
+
+ // Clusters have two variables instead of a centre variable -- one for
+ // each boundary side, so we need to remap the desired positions and the
+ // separations values for the purposes of cost sorting.
+ if (shape1.cluster)
+ {
+ double width = vs[XDIM][info.varIndex1 + 1]->finalPosition -
+ vs[XDIM][info.varIndex1]->finalPosition;
+ double height = vs[YDIM][info.varIndex1 + 1]->finalPosition -
+ vs[YDIM][info.varIndex1]->finalPosition;
+ desiredX1 += width / 2;
+ desiredY1 += height / 2;
+ xSepCostL += width / 2;
+ xSepCostR += width / 2;
+ ySepCostB += height / 2;
+ ySepCostT += height / 2;
+ xSepL += shape1.rectPadding.min(XDIM);
+ xSepR += shape1.rectPadding.max(XDIM);
+ ySepB += shape1.rectPadding.min(YDIM);
+ ySepT += shape1.rectPadding.max(YDIM);
+ }
+ if (shape2.cluster)
+ {
+ double width = vs[XDIM][info.varIndex2 + 1]->finalPosition -
+ vs[XDIM][info.varIndex2]->finalPosition;
+ double height = vs[YDIM][info.varIndex2 + 1]->finalPosition -
+ vs[YDIM][info.varIndex2]->finalPosition;
+ desiredX2 += width / 2;
+ desiredY2 += height / 2;
+ xSepCostL += width / 2;
+ xSepCostR += width / 2;
+ ySepCostB += height / 2;
+ ySepCostT += height / 2;
+ xSepL += shape2.rectPadding.min(XDIM);
+ xSepR += shape2.rectPadding.max(XDIM);
+ ySepB += shape2.rectPadding.min(YDIM);
+ ySepT += shape2.rectPadding.max(YDIM);
+ }
+
+ // We get problems with numerical inaccuracy in the topology constraint
+ // generation, so make sure the rectagles are separated by at least a
+ // tiny distance.
+ xSepL += 10e-10;
+ xSepR += 10e-10;
+ ySepB += 10e-10;
+ ySepT += 10e-10;
+
+ // Compute the cost to move in each direction based on the
+ // desired positions for the two objects.
+ double costR = xSepCostR - (desiredX2 - desiredX1);
+ double costL = xSepCostL - (desiredX1 - desiredX2);
+
+ double costT = ySepCostT - (desiredY2 - desiredY1);
+ double costB = ySepCostB - (desiredY1 - desiredY2);
+
+ vpsc::Constraint constraintL(vs[XDIM][varIndexR2],
+ vs[XDIM][varIndexL1], xSepL);
+ alternatives.push_back(SubConstraint(XDIM, constraintL, costL));
+
+ vpsc::Constraint constraintR(vs[XDIM][varIndexR1],
+ vs[XDIM][varIndexL2], xSepR);
+ alternatives.push_back(SubConstraint(XDIM, constraintR, costR));
+
+ vpsc::Constraint constraintB(vs[YDIM][varIndexR2],
+ vs[YDIM][varIndexL1], ySepB);
+ alternatives.push_back(SubConstraint(YDIM, constraintB, costB));
+
+ vpsc::Constraint constraintT(vs[YDIM][varIndexR1],
+ vs[YDIM][varIndexL2], ySepT);
+ alternatives.push_back(SubConstraint(YDIM, constraintT, costT));
+
+ //fprintf(stderr, "===== NONOVERLAP ALTERNATIVES -====== \n");
+
+ return alternatives;
+}
+
+
+bool NonOverlapConstraints::subConstraintsRemaining(void) const
+{
+ //printf(". %3d of %4d\n", _currSubConstraintIndex, pairInfoList.size());
+ return _currSubConstraintIndex < pairInfoList.size();
+}
+
+
+void NonOverlapConstraints::markAllSubConstraintsAsInactive(void)
+{
+ for (std::list<ShapePairInfo>::iterator curr = pairInfoList.begin();
+ curr != pairInfoList.end(); ++curr)
+ {
+ ShapePairInfo& info = (*curr);
+ info.satisfied = false;
+ info.processed = false;
+ }
+ _currSubConstraintIndex = 0;
+ initialSortCompleted = false;
+}
+
+
+void NonOverlapConstraints::generateSeparationConstraints(
+ const vpsc::Dim dim, vpsc::Variables& vs, vpsc::Constraints& cs,
+ std::vector<vpsc::Rectangle*>& boundingBoxes)
+{
+ for (std::list<ShapePairInfo>::iterator info = pairInfoList.begin();
+ info != pairInfoList.end(); ++info)
+ {
+ assertValidVariableIndex(vs, info->varIndex1);
+ assertValidVariableIndex(vs, info->varIndex2);
+
+ OverlapShapeOffsets& shape1 = shapeOffsets[info->varIndex1];
+ OverlapShapeOffsets& shape2 = shapeOffsets[info->varIndex2];
+
+ vpsc::Rectangle rect1 = (shape1.cluster) ?
+ shape1.cluster->bounds : *boundingBoxes[info->varIndex1];
+ vpsc::Rectangle rect2 = (shape2.cluster) ?
+ shape2.cluster->bounds : *boundingBoxes[info->varIndex2];
+
+ double pos1 = rect1.getCentreD(dim);
+ double pos2 = rect2.getCentreD(dim);
+
+ double below1 = shape1.halfDim[dim];
+ double above1 = shape1.halfDim[dim];
+ double below2 = shape2.halfDim[dim];
+ double above2 = shape2.halfDim[dim];
+
+ vpsc::Variable *varLeft1 = nullptr;
+ vpsc::Variable *varLeft2 = nullptr;
+ vpsc::Variable *varRight1 = nullptr;
+ vpsc::Variable *varRight2 = nullptr;
+ if (shape1.cluster)
+ {
+ // Must constraint to cluster boundary variables.
+ varLeft1 = vs[shape1.cluster->clusterVarId];
+ varRight1 = vs[shape1.cluster->clusterVarId + 1];
+ rect1 = shape1.cluster->margin().rectangleByApplyingBox(rect1);
+ below1 = shape1.cluster->margin().min(dim);
+ above1 = shape1.cluster->margin().max(dim);
+ }
+ else
+ {
+ // Must constrain to rectangle centre postion variable.
+ varLeft1 = varRight1 = vs[info->varIndex1];
+ }
+
+ if (shape2.cluster)
+ {
+ // Must constraint to cluster boundary variables.
+ varLeft2 = vs[shape2.cluster->clusterVarId];
+ varRight2 = vs[shape2.cluster->clusterVarId + 1];
+ rect2 = shape2.cluster->margin().rectangleByApplyingBox(rect2);
+ below2 = shape2.cluster->margin().min(dim);
+ above2 = shape2.cluster->margin().max(dim);
+ }
+ else
+ {
+ // Must constrain to rectangle centre postion variable.
+ varLeft2 = varRight2 = vs[info->varIndex2];
+ }
+
+ if (rect1.overlapD(!dim, &rect2) > 0.0005)
+ {
+ vpsc::Constraint *constraint = nullptr;
+ if (pos1 < pos2)
+ {
+ constraint = new vpsc::Constraint(varRight1, varLeft2,
+ above1 + below2);
+ }
+ else
+ {
+ constraint = new vpsc::Constraint(varRight2, varLeft1,
+ below1 + above2);
+ }
+ constraint->creator = this;
+ cs.push_back(constraint);
+ }
+ }
+}
+
+
+} // namespace cola
diff --git a/src/3rdparty/adaptagrams/libcola/cc_nonoverlapconstraints.h b/src/3rdparty/adaptagrams/libcola/cc_nonoverlapconstraints.h
new file mode 100644
index 0000000..0904ece
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/cc_nonoverlapconstraints.h
@@ -0,0 +1,210 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2010-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+ *
+*/
+
+#ifndef COLA_CC_NONOVERLAPCONSTRAINTS_H
+#define COLA_CC_NONOVERLAPCONSTRAINTS_H
+
+#include <vector>
+
+#include "libcola/cola.h"
+#include "libcola/compound_constraints.h"
+#include "libcola/shapepair.h"
+
+namespace vpsc {
+class Rectangle;
+}
+
+namespace cola {
+
+class Cluster;
+
+class OverlapShapeOffsets : public SubConstraintInfo
+{
+ public:
+ OverlapShapeOffsets(unsigned ind, double xOffset, double yOffset,
+ unsigned int group)
+ : SubConstraintInfo(ind),
+ cluster(nullptr),
+ rectPadding(0),
+ group(group)
+ {
+ halfDim[0] = xOffset;
+ halfDim[1] = yOffset;
+ }
+ OverlapShapeOffsets(unsigned ind, Cluster *cluster, unsigned int group)
+ : SubConstraintInfo(ind),
+ cluster(cluster),
+ rectPadding(cluster->margin()),
+ group(group)
+ {
+ halfDim[0] = 0;
+ halfDim[1] = 0;
+ }
+ OverlapShapeOffsets()
+ : SubConstraintInfo(1000000),
+ cluster(nullptr),
+ rectPadding(0)
+ {
+ }
+ bool usesClusterBounds(void) const
+ {
+ return (cluster && !cluster->clusterIsFromFixedRectangle());
+ }
+ void resize(double xOffset, double yOffset)
+ {
+ halfDim[0] = xOffset;
+ halfDim[1] = yOffset;
+ }
+ Cluster *cluster;
+ double halfDim[2]; // Half width and height values.
+ Box rectPadding; // Used for cluster padding.
+ unsigned int group;
+};
+
+
+class ShapePairInfo
+{
+ public:
+ ShapePairInfo(unsigned ind1, unsigned ind2, unsigned ord = 1)
+ : order(ord),
+ satisfied(false),
+ processed(false)
+ {
+ COLA_ASSERT(ind1 != ind2);
+ // Assign the lesser value to varIndex1.
+ varIndex1 = (ind1 < ind2) ? ind1 : ind2;
+ // Assign the greater value to varIndex2.
+ varIndex2 = (ind1 > ind2) ? ind1 : ind2;
+ }
+ bool operator<(const ShapePairInfo& rhs) const
+ {
+ // Make sure the processed ones are at the end after sorting.
+ int processedInt = processed ? 1 : 0;
+ int rhsProcessedInt = rhs.processed ? 1 : 0;
+ if (processedInt != rhsProcessedInt)
+ {
+ return processedInt < rhsProcessedInt;
+ }
+ // Use cluster ordering for primary sorting.
+ if (order != rhs.order)
+ {
+ return order < rhs.order;
+ }
+ return overlapMax > rhs.overlapMax;
+ }
+ unsigned short order;
+ unsigned short varIndex1;
+ unsigned short varIndex2;
+ bool satisfied;
+ bool processed;
+ double overlapMax;
+};
+
+
+// Stores IDs of all rectangles exempt from non-overlap constraints.
+class NonOverlapConstraintExemptions {
+ public:
+ NonOverlapConstraintExemptions();
+ void addExemptGroupOfNodes(ListOfNodeIndexes listOfNodeGroups);
+ bool shapePairIsExempt(ShapePair shapePair) const;
+ std::set<ShapePair> getExemptPairs(void) {return m_exempt_pairs;}
+
+ private:
+ std::set<ShapePair> m_exempt_pairs;
+};
+
+// Non-overlap constraints prevent a set of given shapes from overlapping.
+class NonOverlapConstraints : public CompoundConstraint {
+ public:
+ NonOverlapConstraints(NonOverlapConstraintExemptions *exemptions,
+ unsigned int priority = PRIORITY_NONOVERLAP);
+ //! @brief Use this method to add all the shapes between which you want
+ //! to prevent overlaps.
+ //! @param id This will be used as index into both the vars and
+ //! boundingBoxes vectors when you call the
+ //! generateSeparationConstraints method.
+ //! @param halfW If you add two shapes with half-widths hwi and hwj, then
+ //! if a horizontal separation constraint is generated between
+ //! them its gap will be hwi + hwj.
+ //! @param halfH Similar to halfW.
+ //! @param group Assign a group number to this shape. A separation constraint
+ //! will be generated between two shapes only if they belong to
+ //! the same group. This is useful for clusters.
+ //! @param exemptions Optional set of IDs of shapes to be skipped, i.e. such that
+ //! a separation constraint should /not/ be generated between
+ //! that shape and the one being added.
+ void addShape(unsigned id, double halfW, double halfH,
+ unsigned int group = 1, std::set<unsigned> exemptions = std::set<unsigned>());
+ void resizeShape(unsigned id, double halfW, double halfH);
+ void removeShape(unsigned id);
+ void addCluster(Cluster *cluster, unsigned int group);
+ void computeAndSortOverlap(vpsc::Variables vs[]);
+ void markCurrSubConstraintAsActive(const bool satisfiable);
+ void markAllSubConstraintsAsInactive(void);
+ bool subConstraintsRemaining(void) const;
+ SubConstraintAlternatives getCurrSubConstraintAlternatives(
+ vpsc::Variables vs[]);
+ std::string toString(void) const;
+ void setClusterClusterExemptions(std::set<ShapePair> exemptions);
+
+ void generateVariables(const vpsc::Dim dim, vpsc::Variables& vars);
+ void generateSeparationConstraints(const vpsc::Dim dim,
+ vpsc::Variables& vars, vpsc::Constraints& gcs);
+ //! @brief Generate separation constraints in one dimension, to ensure
+ //! nonoverlap between all shapes in that dimension.
+ //! @param dim The dimension for which to generate constraints.
+ //! @param vars The variables between which the constraints will hold.
+ //! @param gcs The generated constraints will be added to this vector.
+ //! @param boundingBoxes For those id's corresponding to added shapes
+ //! (not clusters), the rectangle boundingBox[id] will be consulted
+ //! in order to determine:
+ //! (1) whether a separation constraint is called for, i.e. whether the
+ //! shapes in question span any of the same coods in the dimension
+ //! opposite to dim;
+ //! (2) which var is left and which is right in the separation constraint.
+ //! Note however that the dimensions of the boundingBoxes do NOT determine
+ //! the gaps of the separation constraints, which are instead based on the
+ //! half-width and half-height passed when adding the shapes.
+ void generateSeparationConstraints(const vpsc::Dim dim,
+ vpsc::Variables& vars, vpsc::Constraints& gcs,
+ std::vector<vpsc::Rectangle*>& boundingBoxes);
+
+ private:
+ void computeOverlapForShapePairInfo(ShapePairInfo& info,
+ vpsc::Variables vs[]);
+
+ std::list<ShapePairInfo> pairInfoList;
+ std::map<unsigned, OverlapShapeOffsets> shapeOffsets;
+ bool pairInfoListSorted;
+ bool initialSortCompleted;
+
+ // Cluster variables
+ size_t clusterVarStartIndex;
+ size_t currClusterIndex;
+ size_t clusterMode;
+
+ NonOverlapConstraintExemptions *m_exemptions;
+ std::set<ShapePair> m_cluster_cluster_exemptions;
+};
+
+} // namespace cola
+#endif // COLA_CC_NONOVERLAPCONSTRAINTS
diff --git a/src/3rdparty/adaptagrams/libcola/cluster.cpp b/src/3rdparty/adaptagrams/libcola/cluster.cpp
new file mode 100644
index 0000000..6fbfc0b
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/cluster.cpp
@@ -0,0 +1,719 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+ * Michael Wybrow
+*/
+
+#include "libvpsc/assertions.h"
+#include "libcola/commondefs.h"
+#include "libcola/cola.h"
+#include "libcola/convex_hull.h"
+#include "libcola/cluster.h"
+
+using vpsc::generateXConstraints;
+using vpsc::generateYConstraints;
+using namespace std;
+
+namespace cola {
+
+Cluster::Cluster()
+ : bounds(),
+ clusterVarId(0),
+ varWeight(0.0001),
+ internalEdgeWeightFactor(1.),
+ desiredBoundsSet(false),
+ desiredBounds()
+{
+ // XXX We use a really low weight here until we properly set the source
+ // of the variable value back in updatePositions() type manner.
+ varWeight = 0.0000001;
+}
+
+Cluster::~Cluster()
+{
+ for_each(clusters.begin(), clusters.end(), delete_object());
+ clusters.clear();
+}
+
+void Cluster::setDesiredBounds(const vpsc::Rectangle db)
+{
+ desiredBoundsSet = true;
+ desiredBounds = db;
+}
+
+void Cluster::unsetDesiredBounds(void)
+{
+ desiredBoundsSet=false;
+}
+
+
+// Checks to see if the shape at the given index is contained within this
+// cluster or its child clusters.
+//
+void Cluster::countContainedNodes(std::vector<unsigned>& counts)
+{
+ vector<unsigned> invalidNodes;
+ for (set<unsigned>::iterator it = nodes.begin(); it != nodes.end(); ++it)
+ {
+ unsigned nodeIndex = *it;
+ if (nodeIndex < counts.size())
+ {
+ // Node index is valid, increase count.
+ counts[*it] += 1;
+ }
+ else
+ {
+ fprintf(stderr, "Warning: Invalid node index %u specified in "
+ "cluster. Ignoring...\n", nodeIndex);
+ invalidNodes.push_back(nodeIndex);
+ }
+ }
+ for (size_t i = 0; i < invalidNodes.size(); ++i)
+ {
+ nodes.erase(invalidNodes[i]);
+ }
+
+ for (vector<Cluster*>::const_iterator i = clusters.begin();
+ i != clusters.end(); ++i)
+ {
+ (*i)->countContainedNodes(counts);
+ }
+}
+
+void Cluster::computeBoundingRect(const vpsc::Rectangles& rs)
+{
+ bounds = vpsc::Rectangle();
+ for (vector<Cluster*>::const_iterator i = clusters.begin();
+ i != clusters.end(); ++i)
+ {
+ (*i)->computeBoundingRect(rs);
+ vpsc::Rectangle rectangle =
+ (*i)->margin().rectangleByApplyingBox((*i)->bounds);
+ bounds = bounds.unionWith(rectangle);
+ }
+ for (set<unsigned>::const_iterator i = nodes.begin();
+ i != nodes.end(); ++i)
+ {
+ vpsc::Rectangle* r=rs[*i];
+ bounds = bounds.unionWith(*r);
+ }
+ bounds = padding().rectangleByApplyingBox(bounds);
+}
+
+void Cluster::computeVarRect(vpsc::Variables& vars, size_t dim)
+{
+ if ((clusterVarId > 0) && (vars.size() > clusterVarId))
+ {
+ varRect.setMinD(dim, vars[clusterVarId]->finalPosition);
+ varRect.setMaxD(dim, vars[clusterVarId + 1]->finalPosition);
+ }
+
+ for (vector<Cluster*>::const_iterator i = clusters.begin();
+ i != clusters.end(); ++i)
+ {
+ (*i)->computeVarRect(vars, dim);
+ }
+}
+
+bool Cluster::clusterIsFromFixedRectangle(void) const
+{
+ return false;
+}
+
+void ConvexCluster::computeBoundary(const vpsc::Rectangles& rs)
+{
+ unsigned n = 4 * nodes.size();
+ valarray<double> X(n);
+ valarray<double> Y(n);
+ unsigned pctr = 0;
+ vector<unsigned> nodesVector(nodes.begin(), nodes.end());
+ for (size_t i = 0; i < nodesVector.size(); ++i)
+ {
+ vpsc::Rectangle* r=rs[nodesVector[i]];
+ // Bottom Right
+ X[pctr]=r->getMaxX();
+ Y[pctr++]=r->getMinY();
+ // Top Right
+ X[pctr]=r->getMaxX();
+ Y[pctr++]=r->getMaxY();
+ // Top Left
+ X[pctr]=r->getMinX();
+ Y[pctr++]=r->getMaxY();
+ // Bottom Left
+ X[pctr]=r->getMinX();
+ Y[pctr++]=r->getMinY();
+ }
+ /*
+ for(unsigned i=0;i<n;i++) {
+ printf("X[%d]=%f, Y[%d]=%f;\n",i,X[i],i,Y[i]);
+ }
+ */
+ vector<unsigned> hull;
+ hull::convex(X,Y,hull);
+ hullX.resize(hull.size());
+ hullY.resize(hull.size());
+ hullRIDs.resize(hull.size());
+ hullCorners.resize(hull.size());
+ for (unsigned j=0;j<hull.size();j++)
+ {
+ hullX[j]=X[hull[j]];
+ hullY[j]=Y[hull[j]];
+ hullRIDs[j]=nodesVector[hull[j]/4];
+ hullCorners[j]=hull[j]%4;
+ }
+}
+
+
+void ConvexCluster::printCreationCode(FILE *fp) const
+{
+ fprintf(fp, " ConvexCluster *cluster%llu = new ConvexCluster();\n",
+ (unsigned long long) this);
+ for(set<unsigned>::const_iterator i = nodes.begin();
+ i != nodes.end(); ++i)
+ {
+ fprintf(fp, " cluster%llu->addChildNode(%u);\n",
+ (unsigned long long) this, *i);
+ }
+ for(vector<Cluster *>::const_iterator i = clusters.begin();
+ i != clusters.end(); ++i)
+ {
+ (*i)->printCreationCode(fp);
+ fprintf(fp, " cluster%llu->addChildCluster(cluster%llu);\n",
+ (unsigned long long) this, (unsigned long long) *i);
+ }
+}
+
+void ConvexCluster::outputToSVG(FILE *fp) const
+{
+ for(vector<Cluster *>::const_iterator i = clusters.begin();
+ i != clusters.end(); ++i)
+ {
+ (*i)->outputToSVG(fp);
+ }
+}
+
+
+RectangularCluster::RectangularCluster()
+ : Cluster(),
+ m_rectangle_index(-1),
+ m_margin(0),
+ m_padding(0)
+{
+ minEdgeRect[vpsc::XDIM] = nullptr;
+ minEdgeRect[vpsc::YDIM] = nullptr;
+ maxEdgeRect[vpsc::XDIM] = nullptr;
+ maxEdgeRect[vpsc::YDIM] = nullptr;
+}
+
+RectangularCluster::RectangularCluster(unsigned rectIndex)
+ : Cluster(),
+ m_rectangle_index(rectIndex),
+ m_margin(0),
+ m_padding(0)
+{
+ minEdgeRect[vpsc::XDIM] = nullptr;
+ minEdgeRect[vpsc::YDIM] = nullptr;
+ maxEdgeRect[vpsc::XDIM] = nullptr;
+ maxEdgeRect[vpsc::YDIM] = nullptr;
+}
+
+RectangularCluster::~RectangularCluster()
+{
+ for (size_t dim = 0; dim < 2; ++dim)
+ {
+ if (minEdgeRect[dim])
+ {
+ delete minEdgeRect[dim];
+ minEdgeRect[dim] = nullptr;
+ }
+ if (maxEdgeRect[dim])
+ {
+ delete maxEdgeRect[dim];
+ maxEdgeRect[dim] = nullptr;
+ }
+ }
+}
+
+void RectangularCluster::setMargin(const Box margin)
+{
+ m_margin = margin;
+}
+
+
+void RectangularCluster::setMargin(double margin)
+{
+ m_margin = Box(margin);
+}
+
+
+Box RectangularCluster::margin(void) const
+{
+ return m_margin;
+}
+
+
+void RectangularCluster::setPadding(const Box padding)
+{
+ m_padding = padding;
+}
+
+
+void RectangularCluster::setPadding(double padding)
+{
+ m_padding = Box(padding);
+}
+
+
+Box RectangularCluster::padding(void) const
+{
+ return m_padding;
+}
+
+
+void RectangularCluster::countContainedNodes(std::vector<unsigned>& counts)
+{
+ if (m_rectangle_index >= 0)
+ {
+ // This cluster is the shape in question.
+ counts[m_rectangle_index] += 1;
+ }
+ Cluster::countContainedNodes(counts);
+}
+
+
+void RectangularCluster::generateFixedRectangleConstraints(
+ cola::CompoundConstraints& idleConstraints,
+ vpsc::Rectangles& rc, vpsc::Variables (&vars)[2]) const
+{
+ COLA_UNUSED(vars);
+
+ if (m_rectangle_index < 0)
+ {
+ // Not based on a Rectangle.
+ return;
+ }
+
+ double halfWidth = rc[m_rectangle_index]->width() / 2;
+ double halfHeight = rc[m_rectangle_index]->height() / 2;
+
+ cola::SeparationConstraint *sc =
+ new cola::SeparationConstraint(vpsc::XDIM, clusterVarId,
+ m_rectangle_index, halfWidth, true);
+ idleConstraints.push_back(sc);
+ sc = new cola::SeparationConstraint(vpsc::XDIM,
+ m_rectangle_index, clusterVarId + 1, halfWidth, true);
+ idleConstraints.push_back(sc);
+
+ sc = new cola::SeparationConstraint(vpsc::YDIM,
+ clusterVarId, m_rectangle_index, halfHeight, true);
+ idleConstraints.push_back(sc);
+ sc = new cola::SeparationConstraint(vpsc::YDIM,
+ m_rectangle_index, clusterVarId + 1, halfHeight, true);
+ idleConstraints.push_back(sc);
+}
+
+
+void RectangularCluster::computeBoundary(const vpsc::Rectangles& rs)
+{
+ double xMin=DBL_MAX, xMax=-DBL_MAX, yMin=DBL_MAX, yMax=-DBL_MAX;
+ for (std::set<unsigned>::iterator it = nodes.begin();
+ it != nodes.end(); ++it)
+ {
+ xMin=std::min(xMin,rs[*it]->getMinX());
+ xMax=std::max(xMax,rs[*it]->getMaxX());
+ yMin=std::min(yMin,rs[*it]->getMinY());
+ yMax=std::max(yMax,rs[*it]->getMaxY());
+ }
+ hullX.resize(4);
+ hullY.resize(4);
+ hullX[3]=xMin;
+ hullY[3]=yMin;
+ hullX[2]=xMin;
+ hullY[2]=yMax;
+ hullX[1]=xMax;
+ hullY[1]=yMax;
+ hullX[0]=xMax;
+ hullY[0]=yMin;
+}
+
+
+void RectangularCluster::printCreationCode(FILE *fp) const
+{
+ fprintf(fp, " RectangularCluster *cluster%llu = "
+ "new RectangularCluster(",
+ (unsigned long long) this);
+ if (m_rectangle_index != -1)
+ {
+ fprintf(fp, "%d", m_rectangle_index);
+ }
+ fprintf(fp, ");\n");
+ if (!m_margin.empty())
+ {
+ fprintf(fp, " cluster%llu->setMargin(",
+ (unsigned long long) this);
+ m_margin.outputCode(fp);
+ fprintf(fp, ");\n");
+ }
+ if (!m_padding.empty())
+ {
+ fprintf(fp, " cluster%llu->setPadding(",
+ (unsigned long long) this);
+ m_padding.outputCode(fp);
+ fprintf(fp, ");\n");
+ }
+ for(set<unsigned>::const_iterator i = nodes.begin();
+ i != nodes.end(); ++i)
+ {
+ fprintf(fp, " cluster%llu->addChildNode(%u);\n",
+ (unsigned long long) this, *i);
+ }
+ for(vector<Cluster *>::const_iterator i = clusters.begin();
+ i != clusters.end(); ++i)
+ {
+ (*i)->printCreationCode(fp);
+ fprintf(fp, " cluster%llu->addChildCluster(cluster%llu);\n",
+ (unsigned long long) this, (unsigned long long) *i);
+ }
+}
+
+void RectangularCluster::outputToSVG(FILE *fp) const
+{
+ double rounding = 4;
+ if (varRect.isValid())
+ {
+ fprintf(fp, "<rect id=\"cluster-%llu-r\" x=\"%g\" y=\"%g\" width=\"%g\" "
+ "height=\"%g\" style=\"stroke-width: 1px; stroke: black; "
+ "fill: green; fill-opacity: 0.3;\" rx=\"%g\" ry=\"%g\" />\n",
+ (unsigned long long) this, varRect.getMinX(), varRect.getMinY(),
+ varRect.getMaxX() - varRect.getMinX(),
+ varRect.getMaxY() - varRect.getMinY(), rounding, rounding);
+ }
+ else
+ {
+ fprintf(fp, "<rect id=\"cluster-%llu\" x=\"%g\" y=\"%g\" width=\"%g\" "
+ "height=\"%g\" style=\"stroke-width: 1px; stroke: black; "
+ "fill: red; fill-opacity: 0.3;\" rx=\"%g\" ry=\"%g\" />\n",
+ (unsigned long long) this, bounds.getMinX(), bounds.getMinY(),
+ bounds.getMaxX() - bounds.getMinX(),
+ bounds.getMaxY() - bounds.getMinY(), rounding, rounding);
+ }
+
+ for(vector<Cluster *>::const_iterator i = clusters.begin();
+ i != clusters.end(); ++i)
+ {
+ (*i)->outputToSVG(fp);
+ }
+}
+
+
+
+int RectangularCluster::rectangleIndex(void) const
+{
+ return m_rectangle_index;
+}
+
+bool RectangularCluster::clusterIsFromFixedRectangle(void) const
+{
+ return (m_rectangle_index >= 0);
+}
+
+void RectangularCluster::computeBoundingRect(const vpsc::Rectangles& rs)
+{
+ if (clusterIsFromFixedRectangle())
+ {
+ // For bounds, just use this shape's rectangle.
+ bounds = *(rs[m_rectangle_index]);
+ }
+ else
+ {
+ Cluster::computeBoundingRect(rs);
+ }
+}
+void RectangularCluster::addChildNode(unsigned index)
+{
+ if ((m_rectangle_index == (int) index) && (m_rectangle_index > 0))
+ {
+ fprintf(stderr, "Warning: ignoring cluster (%u) added as child of "
+ "itself.\n", index);
+ return;
+ }
+ Cluster::addChildNode(index);
+}
+
+
+RootCluster::RootCluster()
+ : m_allows_multiple_parents(false)
+{
+}
+
+void Cluster::recPathToCluster(RootCluster *rootCluster, Clusters currentPath)
+{
+ // Reset cluster-cluster overlap exceptions.
+ m_cluster_cluster_overlap_exceptions.clear();
+ m_nodes_replaced_with_clusters.clear();
+ m_overlap_replacement_map.clear();
+
+ // Add this cluster to the path.
+ currentPath.push_back(this);
+
+ // Recusively all on each child cluster.
+ for (unsigned i = 0; i < clusters.size(); ++i)
+ {
+ clusters[i]->recPathToCluster(rootCluster, currentPath);
+ }
+
+ // And store the path to each child node.
+ for (std::set<unsigned>::iterator it = nodes.begin();
+ it != nodes.end(); ++it)
+ {
+ rootCluster->m_cluster_vectors_leading_to_nodes[*it].
+ push_back(currentPath);
+ }
+}
+
+
+void RootCluster::calculateClusterPathsToEachNode(size_t nodesCount)
+{
+ m_cluster_vectors_leading_to_nodes.clear();
+ m_cluster_vectors_leading_to_nodes.resize(nodesCount);
+
+ recPathToCluster(this, Clusters());
+
+ for (unsigned i = 0; i < m_cluster_vectors_leading_to_nodes.size(); ++i)
+ {
+ size_t paths = m_cluster_vectors_leading_to_nodes[i].size();
+ for (size_t j = 1; j < paths; ++j)
+ {
+ for (size_t k = 0; k < j; ++k)
+ {
+ // For each pair of paths.
+
+ // Find the lowest common ancestor by finding where the two
+ // paths from the root cluster to node i diverge.
+ Clusters pathJ = m_cluster_vectors_leading_to_nodes[i][j];
+ Clusters pathK = m_cluster_vectors_leading_to_nodes[i][k];
+ size_t lcaIndex = 0;
+ while ((lcaIndex < pathJ.size()) &&
+ (lcaIndex < pathK.size()) &&
+ (pathJ[lcaIndex] == pathK[lcaIndex]))
+ {
+ ++lcaIndex;
+ }
+ COLA_ASSERT(lcaIndex > 0);
+
+ // lcaIndex will be the clusters/nodes that need to overlap
+ // due to these two paths to node i.
+ size_t lcaChildJIndex = i;
+ size_t lcaChildKIndex = i;
+ Cluster *lcaChildJCluster = nullptr;
+ Cluster *lcaChildKCluster = nullptr;
+
+ // lcaIndex < path{J,K}.size() means the child J or K of
+ // the lca is a Cluster. At least one of them will always
+ // be a cluster.
+ COLA_ASSERT((lcaIndex < pathJ.size()) ||
+ (lcaIndex < pathK.size()));
+ if (lcaIndex < pathJ.size())
+ {
+ lcaChildJCluster = pathJ[lcaIndex];
+ lcaChildJIndex = lcaChildJCluster->clusterVarId;
+ }
+ if (lcaIndex < pathK.size())
+ {
+ lcaChildKCluster = pathK[lcaIndex];
+ lcaChildKIndex = lcaChildKCluster->clusterVarId;
+ }
+
+ // We want to exclude the overlapping children of the lca
+ // from having non-overlap constraints generated for them
+ // (siblings of a particular cluster usually have
+ // non-overlap constraints generated for them).
+ Cluster *lcaCluster = pathJ[lcaIndex - 1];
+ lcaCluster->m_cluster_cluster_overlap_exceptions.insert(
+ ShapePair(lcaChildJIndex, lcaChildKIndex));
+
+ if (lcaChildJCluster)
+ {
+ // In cluster J, replace node i with cluster K for the
+ // purpose of non-overlap with siblings, and remember
+ // this replacement so we can still generate non-overlap
+ // constraints between multiple nodes that are children
+ // of the same overlapping clusters.
+ lcaChildJCluster->m_overlap_replacement_map[i] =
+ lcaChildKCluster;
+ lcaChildJCluster->m_nodes_replaced_with_clusters.insert(i);
+ }
+
+ if (lcaChildKCluster)
+ {
+ // In cluster K, replace node i with cluster J for the
+ // purpose of non-overlap with siblings, and remember
+ // this replacement so we can still generate non-overlap
+ // constraints between multiple nodes that are children
+ // of the same overlapping clusters.
+ lcaChildKCluster->m_overlap_replacement_map[i] =
+ lcaChildJCluster;
+ lcaChildKCluster->m_nodes_replaced_with_clusters.insert(i);
+ }
+ }
+ }
+ }
+}
+
+
+void RootCluster::computeBoundary(const vpsc::Rectangles& rs)
+{
+ for (unsigned i = 0; i < clusters.size(); ++i)
+ {
+ clusters[i]->computeBoundary(rs);
+ }
+}
+
+void RootCluster::printCreationCode(FILE *fp) const
+{
+ fprintf(fp, " RootCluster *cluster%llu = new RootCluster();\n",
+ (unsigned long long) this);
+ for(set<unsigned>::const_iterator i = nodes.begin();
+ i != nodes.end(); ++i)
+ {
+ fprintf(fp, " cluster%llu->addChildNode(%u);\n",
+ (unsigned long long) this, *i);
+ }
+ for(vector<Cluster *>::const_iterator i = clusters.begin();
+ i != clusters.end(); ++i)
+ {
+ (*i)->printCreationCode(fp);
+ fprintf(fp, " cluster%llu->addChildCluster(cluster%llu);\n",
+ (unsigned long long) this, (unsigned long long) *i);
+ }
+}
+
+void RootCluster::outputToSVG(FILE *fp) const
+{
+ for(vector<Cluster *>::const_iterator i = clusters.begin();
+ i != clusters.end(); ++i)
+ {
+ (*i)->outputToSVG(fp);
+ }
+
+}
+
+
+bool RootCluster::allowsMultipleParents(void) const
+{
+ return m_allows_multiple_parents;
+}
+
+void RootCluster::setAllowsMultipleParents(const bool value)
+{
+ m_allows_multiple_parents = value;
+}
+
+void Cluster::updateBounds(const vpsc::Dim dim)
+{
+ if (dim == vpsc::HORIZONTAL)
+ {
+ bounds = vpsc::Rectangle(vMin->finalPosition, vMax->finalPosition,
+ bounds.getMinY(), bounds.getMaxY());
+ }
+ else
+ {
+ bounds = vpsc::Rectangle(bounds.getMinX(), bounds.getMaxX(),
+ vMin->finalPosition, vMax->finalPosition);
+ }
+ for (unsigned i=0; i < clusters.size(); ++i)
+ {
+ clusters[i]->updateBounds(dim);
+ }
+}
+
+
+void Cluster::createVars(const vpsc::Dim dim, const vpsc::Rectangles& rs,
+ vpsc::Variables& vars)
+{
+ for (vector<Cluster*>::iterator i = clusters.begin();
+ i != clusters.end(); ++i)
+ {
+ (*i)->createVars(dim, rs, vars);
+ }
+ if (dim==vpsc::HORIZONTAL)
+ {
+ double desiredMinX = bounds.getMinX(), desiredMaxX = bounds.getMaxX();
+ if (desiredBoundsSet)
+ {
+ desiredMinX = desiredBounds.getMinX();
+ desiredMaxX = desiredBounds.getMaxX();
+ }
+ clusterVarId = vars.size();
+ vars.push_back(vXMin = new vpsc::Variable(
+ vars.size(), desiredMinX, varWeight));
+ vars.push_back(vXMax = new vpsc::Variable(
+ vars.size(), desiredMaxX, varWeight));
+ }
+ else
+ {
+ double desiredMinY = bounds.getMinY(), desiredMaxY = bounds.getMaxY();
+ if (desiredBoundsSet)
+ {
+ desiredMinY = desiredBounds.getMinY();
+ desiredMaxY = desiredBounds.getMaxY();
+ }
+ clusterVarId = vars.size();
+ vars.push_back(vYMin = new vpsc::Variable(
+ vars.size(), desiredMinY, varWeight));
+ vars.push_back(vYMax = new vpsc::Variable(
+ vars.size(), desiredMaxY, varWeight));
+ }
+}
+
+// Returns the total area covered by contents of this cluster (not
+// including space between nodes/clusters).
+//
+double Cluster::area(const vpsc::Rectangles& rs)
+{
+ double a = 0;
+ for (set<unsigned>::iterator i = nodes.begin(); i != nodes.end(); ++i)
+ {
+ vpsc::Rectangle *r = rs[*i];
+ a += r->width() * r->height();
+ }
+ for (Clusters::iterator i = clusters.begin(); i!= clusters.end(); ++i)
+ {
+ a += (*i)->area(rs);
+ }
+ return a;
+}
+
+void Cluster::addChildNode(unsigned index)
+{
+ this->nodes.insert(index);
+}
+
+void Cluster::addChildCluster(Cluster *cluster)
+{
+ if (cluster == this)
+ {
+ fprintf(stderr, "Warning: ignoring cluster added as child of itself.\n");
+ return;
+ }
+ this->clusters.push_back(cluster);
+}
+
+
+} // namespace cola
diff --git a/src/3rdparty/adaptagrams/libcola/cluster.h b/src/3rdparty/adaptagrams/libcola/cluster.h
new file mode 100644
index 0000000..118d703
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/cluster.h
@@ -0,0 +1,371 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+ * Michael Wybrow
+*/
+
+#ifndef COLA_CLUSTER_H
+#define COLA_CLUSTER_H
+
+#include <cstdio>
+
+#include "libvpsc/rectangle.h"
+#include "libvpsc/variable.h"
+
+#include "libcola/compound_constraints.h"
+#include "libcola/commondefs.h"
+#include "libcola/box.h"
+#include "libcola/shapepair.h"
+
+namespace cola {
+
+class Cluster;
+typedef std::vector<Cluster *> Clusters;
+typedef std::vector<Clusters> ClustersList;
+
+/**
+ * @brief A cluster defines a hierarchical partitioning over the nodes
+ * which should be kept disjoint by the layout somehow.
+ *
+ * You should not use this directly. This is an abstract base class.
+ * At the top level you should be using RootCluster, and then below that
+ * either RectangualarCLuster or ConvexCluster.
+ */
+class Cluster
+{
+ public:
+ Cluster();
+
+// To prevent C++ objects from being destroyed in garbage collected languages
+// when the libraries are called from SWIG, we hide the declarations of the
+// destructors and prevent generation of default destructors.
+#ifndef SWIG
+ virtual ~Cluster();
+#endif
+ virtual void computeBoundary(const vpsc::Rectangles& rs) = 0;
+ virtual void computeBoundingRect(const vpsc::Rectangles& rs);
+
+ /**
+ * @brief Mark a rectangle as being a child of this cluster.
+ *
+ * @param[in] index The index of the Rectangle in the rectangles vector.
+ */
+ virtual void addChildNode(unsigned index);
+ /**
+ * @brief Mark a cluster as being a sub-cluster of this cluster.
+ *
+ * @param[in] cluster The Cluster to be marked as a sub-cluster.
+ */
+ void addChildCluster(Cluster *cluster);
+
+ virtual cola::Box padding(void) const
+ {
+ return cola::Box();
+ }
+ virtual cola::Box margin(void) const
+ {
+ return cola::Box();
+ }
+
+ void setDesiredBounds(const vpsc::Rectangle bounds);
+ void unsetDesiredBounds();
+ void createVars(const vpsc::Dim dim, const vpsc::Rectangles& rs,
+ vpsc::Variables& vars);
+ virtual void printCreationCode(FILE *fp) const = 0;
+ virtual void countContainedNodes(std::vector<unsigned>& counts);
+ virtual bool clusterIsFromFixedRectangle(void) const;
+ virtual void outputToSVG(FILE *fp) const = 0;
+
+ // Returns the total area covered by contents of this cluster
+ // (not including space between nodes/clusters).
+ double area(const vpsc::Rectangles& rs);
+
+ // Sets bounds based on the finalPositions of vMin and vMax.
+ //
+ void updateBounds(const vpsc::Dim dim);
+
+ virtual void computeVarRect(vpsc::Variables& vs, size_t dim);
+
+ vpsc::Rectangle bounds;
+ vpsc::Rectangle varRect;
+ vpsc::Variable *vXMin, *vXMax, *vYMin, *vYMax;
+
+ // This will be the id of the left/bottom boundary,
+ // and the right/top will be clusterVarId + 1.
+ unsigned clusterVarId;
+
+ double varWeight;
+ double internalEdgeWeightFactor;
+ std::set<unsigned> nodes;
+ std::vector<Cluster*> clusters;
+ std::valarray<double> hullX, hullY;
+
+ protected:
+ void recPathToCluster(RootCluster *rootCluster,
+ Clusters currentPath);
+ bool includesAllNodesFrom(const Cluster *rhs) const;
+
+ // The following are for handling the generation of the correct
+ // set of non-overlap constraints in the case overlapping clusters
+ // (i.e., multiple inheritence). 1) We need to exclude the overlapping
+ // clusters from having non-overlap constraints. 2) We replace nodes
+ // with multiple parent clusters when enforcing non-overlap with their
+ // siblings and instead inforce non-overlap with the other clusters
+ // they are part of, since otherwise there is nothing stopping the
+ // other siblings of each cluster from overlapping each other. 3) We
+ // also need to enforce overlap still between the set of nodes replaced
+ // from each cluster in this way, since they may now be part of some
+ // new set.
+ std::set<ShapePair> m_cluster_cluster_overlap_exceptions;
+ std::map<unsigned, Cluster *> m_overlap_replacement_map;
+ std::set<unsigned> m_nodes_replaced_with_clusters;
+
+ private:
+ friend class ConstrainedFDLayout;
+ friend class RootCluster;
+
+ bool desiredBoundsSet;
+ vpsc::Rectangle desiredBounds;
+
+ vpsc::Variable *vMin, *vMax;
+};
+
+
+/**
+ * @brief Holds the cluster hierarchy specification for a diagram.
+ *
+ * This is not considered a cluster itself, but it records all the nodes in
+ * the diagram not contained within any clusters, as well as optionally a
+ * hierarchy of clusters.
+ *
+ * You can add clusters via addChildCluster() and nodes via addChildNode().
+ *
+ * You can specify just the shapes contained in clusters, but not the nodes
+ * at this top level---the library will add any remaining nodes not appearing
+ * in the cluster hierarchy as children of the root cluster.
+ *
+ * It is possible to add a node as the child of two parent clusters. In this
+ * case, the clusters will overlap to contain this (and possibly other nodes).
+ * The library will warn you if you do this unless you have called the method
+ * setAllowsMultipleParents() to mark this intention.
+ *
+ * Be careful not to create cycles in the cluster hierarchy (i.e., to mark
+ * two clusters as children of each other. The library does not check for
+ * this and strange things may occur.
+ */
+class RootCluster : public Cluster
+{
+ public:
+ RootCluster();
+ void computeBoundary(const vpsc::Rectangles& rs);
+ // There are just shapes at the top level, so
+ // effectively no clusters in the diagram scene.
+ bool flat(void) const
+ {
+ return clusters.empty();
+ }
+ virtual void printCreationCode(FILE *fp) const;
+ virtual void outputToSVG(FILE *fp) const;
+
+ //! Returns true if this cluster hierarchy allows multiple parents,
+ //! otherwise returns false.
+ //!
+ //! Defaults to false. If this is false, the library will display
+ //! warnings if you add a single node to multiple clusters.
+ //!
+ //! @sa setAllowsMultipleParents()
+ bool allowsMultipleParents(void) const;
+
+ //! Set whether the cluster hierarchy should allow multiple parents.
+ //!
+ //! @param value New value for this setting.
+ //!
+ //! sa allowsMultipleParents()
+ void setAllowsMultipleParents(const bool value);
+ private:
+ void calculateClusterPathsToEachNode(size_t nodesCount);
+
+ friend class ConstrainedFDLayout;
+ friend class Cluster;
+
+ bool m_allows_multiple_parents;
+
+ std::vector<ClustersList> m_cluster_vectors_leading_to_nodes;
+};
+
+/**
+ * @brief Defines a rectangular cluster, either variable-sized with floating
+ * sides or a fixed size based on a particular rectangle.
+ *
+ * The chosen constructor decides the type and behaviour of the cluster.
+ */
+class RectangularCluster : public Cluster
+{
+ public:
+ /**
+ * @brief A rectangular cluster of variable size that contains
+ * its children.
+ */
+ RectangularCluster();
+ /**
+ * @brief A fixed size rectangular cluster based on a particular
+ * rectangle.
+ *
+ * This rectangle might be constrained in the other ways like normal
+ * rectangles.
+ *
+ * @param[in] rectIndex The index of the rectangle that this cluster
+ * represents.
+ */
+ RectangularCluster(unsigned rectIndex);
+
+ /**
+ * @brief Sets the margin size for this cluster.
+ *
+ * This value represents the outer spacing that will be put between
+ * the cluster boundary on all sides and other clusters (plus their
+ * margin) and rectangles at the same level when non-overlap
+ * constraints are enabled.
+ *
+ * @param[in] margin The size of the margin for this cluster.
+ */
+ void setMargin(double margin);
+ /**
+ * @brief Sets the margin box for this cluster.
+ *
+ * This box represents the outer spacing that will be put between
+ * the cluster boundary and other clusters (plus their margin) and
+ * rectangles at the same level when non-overlap constraints are
+ * enabled.
+ *
+ * @param[in] margin The box representing the margins for this
+ * cluster.
+ */
+ void setMargin(const cola::Box margin);
+ /**
+ * @brief Returns the margin box for this cluster.
+ *
+ * @return The margin box for the cluster.
+ */
+ cola::Box margin(void) const;
+
+ /**
+ * @brief Sets the padding size for this cluster.
+ *
+ * This value represents the inner spacing that will be put between
+ * the cluster boundary and other child clusters (plus their margin)
+ * and child rectangles on all sides.
+ *
+ * @param[in] padding The size of the padding for this cluster.
+ */
+ void setPadding(double padding);
+ /**
+ * @brief Sets the padding box for this cluster.
+ *
+ * This box represents the inner spacing that will be put between
+ * the cluster boundary and other child clusters (plus their margin)
+ * and child rectangles for each edge.
+ *
+ * @param[in] padding The Box representing padding values for this
+ * cluster.
+ */
+ void setPadding(const cola::Box padding);
+ /**
+ * @brief Returns the padding box for this cluster.
+ *
+ * @return The padding box for the cluster.
+ */
+ cola::Box padding(void) const;
+
+#ifndef SWIG
+ virtual ~RectangularCluster();
+#endif
+ void computeBoundary(const vpsc::Rectangles& rs);
+ virtual void countContainedNodes(std::vector<unsigned>& counts);
+ virtual void printCreationCode(FILE *fp) const;
+ virtual void outputToSVG(FILE *fp) const;
+ virtual void computeBoundingRect(const vpsc::Rectangles& rs);
+ virtual void addChildNode(unsigned index);
+ inline vpsc::Rectangle *getMinEdgeRect(const vpsc::Dim dim)
+ {
+ if (minEdgeRect[dim])
+ {
+ delete minEdgeRect[dim];
+ }
+ minEdgeRect[dim] = new vpsc::Rectangle(bounds);
+
+ // Set the Min and Max positions to be the min minus an offset.
+ double edgePosition = minEdgeRect[dim]->getMinD(dim);
+ minEdgeRect[dim]->setMinD(dim, edgePosition - m_margin.min(dim));
+ minEdgeRect[dim]->setMaxD(dim, edgePosition);
+
+ return minEdgeRect[dim];
+ }
+
+ inline vpsc::Rectangle *getMaxEdgeRect(const vpsc::Dim dim)
+ {
+ if (maxEdgeRect[dim])
+ {
+ delete maxEdgeRect[dim];
+ }
+ maxEdgeRect[dim] = new vpsc::Rectangle(bounds);
+
+ // Set the Min and Max positions to be the max plus an offset.
+ double edgePosition = maxEdgeRect[dim]->getMaxD(dim);
+ maxEdgeRect[dim]->setMaxD(dim, edgePosition + m_margin.max(dim));
+ maxEdgeRect[dim]->setMinD(dim, edgePosition);
+
+ return maxEdgeRect[dim];
+ }
+ virtual bool clusterIsFromFixedRectangle(void) const;
+ int rectangleIndex(void) const;
+
+ // For fixed sized clusters based on a rectangle, this method
+ // generates the constraints that attach the cluster edges to the
+ // centre position of the relevant rectangle.
+ void generateFixedRectangleConstraints(
+ cola::CompoundConstraints& idleConstraints,
+ vpsc::Rectangles& rc, vpsc::Variables (&vars)[2]) const;
+
+ private:
+ vpsc::Rectangle *minEdgeRect[2];
+ vpsc::Rectangle *maxEdgeRect[2];
+ int m_rectangle_index;
+ Box m_margin;
+ Box m_padding;
+};
+
+/**
+ * @brief Defines a cluster that will be treated as a convex boundary around
+ * the child nodes and clusters.
+ */
+class ConvexCluster : public Cluster
+{
+ public:
+ void computeBoundary(const vpsc::Rectangles& rs);
+ virtual void printCreationCode(FILE *fp) const;
+ virtual void outputToSVG(FILE *fp) const;
+
+ std::valarray<unsigned> hullRIDs;
+ std::valarray<unsigned char> hullCorners;
+};
+
+
+} // namespace cola
+#endif // COLA_CLUSTER_H
diff --git a/src/3rdparty/adaptagrams/libcola/cola.cpp b/src/3rdparty/adaptagrams/libcola/cola.cpp
new file mode 100644
index 0000000..739c6ea
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/cola.cpp
@@ -0,0 +1,700 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+*/
+
+#include <cmath>
+
+#include "libvpsc/assertions.h"
+#include "libcola/commondefs.h"
+#include "libcola/cola.h"
+#include "libcola/conjugate_gradient.h"
+#include "libcola/straightener.h"
+#include "libcola/shortest_paths.h"
+#include "libcola/cluster.h"
+
+using namespace std;
+using namespace vpsc;
+using straightener::generateClusterBoundaries;
+
+namespace cola {
+
+ConstrainedMajorizationLayout
+::ConstrainedMajorizationLayout(
+ vector<Rectangle*>& rs,
+ const vector<Edge>& es,
+ RootCluster *clusterHierarchy,
+ const double idealLength,
+ EdgeLengths eLengths,
+ TestConvergence *doneTest,
+ PreIteration* preIteration,
+ bool useNeighbourStress)
+ : n(rs.size()),
+ lap2(valarray<double>(n*n)),
+ Dij(valarray<double>(n*n)),
+ tol(1e-7),
+ done(doneTest),
+ using_default_done(false),
+ preIteration(preIteration),
+ X(valarray<double>(n)), Y(valarray<double>(n)),
+ stickyNodes(false),
+ startX(valarray<double>(n)), startY(valarray<double>(n)),
+ constrainedLayout(false),
+ nonOverlappingClusters(false),
+ clusterHierarchy(clusterHierarchy),
+ gpX(nullptr), gpY(nullptr),
+ ccs(nullptr),
+ unsatisfiableX(nullptr), unsatisfiableY(nullptr),
+ avoidOverlaps(None),
+ straightenEdges(nullptr),
+ bendWeight(0.1), potBendWeight(0.1),
+ xSkipping(true),
+ scaling(true),
+ externalSolver(false),
+ majorization(true)
+{
+ if (done == nullptr)
+ {
+ done = new TestConvergence();
+ using_default_done = true;
+ }
+
+ boundingBoxes.resize(rs.size());
+ copy(rs.begin(),rs.end(),boundingBoxes.begin());
+
+ done->reset();
+
+ COLA_ASSERT(!straightenEdges||straightenEdges->size()==es.size());
+
+ double** D=new double*[n];
+ for(unsigned i=0;i<n;i++) {
+ D[i]=new double[n];
+ }
+
+ std::valarray<double> edgeLengths(eLengths.data(), eLengths.size());
+ // Correct zero or negative entries in eLengths array.
+ for (size_t i = 0; i < edgeLengths.size(); ++i)
+ {
+ if (edgeLengths[i] <= 0)
+ {
+ fprintf(stderr, "Warning: ignoring non-positive length at index %d "
+ "in ideal edge length array.\n", (int) i);
+ edgeLengths[i] = 1;
+ }
+ }
+
+ if (useNeighbourStress) {
+ for(unsigned i=0;i<n;i++) {
+ for(unsigned j=0;j<n;j++) {
+ D[i][j]=std::numeric_limits<double>::max();
+ }
+ }
+ bool haveLengths = edgeLengths.size() == es.size();
+ for (unsigned i = 0; i < es.size(); i++) {
+ unsigned source = es[i].first;
+ unsigned target = es[i].second;
+ D[source][target] = D[target][source] = (haveLengths ? edgeLengths[i] : 1.0);
+ }
+ } else {
+ shortest_paths::johnsons(n,D,es,edgeLengths);
+ //shortest_paths::neighbours(n,D,es,edgeLengths);
+ }
+
+ edge_length = idealLength;
+ if(clusterHierarchy) {
+ for(Clusters::const_iterator i=clusterHierarchy->clusters.begin();
+ i!=clusterHierarchy->clusters.end();i++) {
+ Cluster *c=*i;
+ for(set<unsigned>::iterator j=c->nodes.begin();j!=c->nodes.end();j++) {
+ for(set<unsigned>::iterator k=c->nodes.begin();k!=c->nodes.end();k++) {
+ unsigned a=*j, b=*k;
+ if(a==b) continue;
+ D[a][b]/=c->internalEdgeWeightFactor;
+ }
+ }
+ }
+ }
+ // Lij_{i!=j}=1/(Dij^2)
+ //
+ for(unsigned i = 0; i<n; i++) {
+ X[i]=rs[i]->getCentreX();
+ Y[i]=rs[i]->getCentreY();
+ double degree = 0;
+ for(unsigned j=0;j<n;j++) {
+ double d = edge_length * D[i][j];
+ Dij[i*n + j] = d;
+ if(i==j) continue;
+ double lij=0;
+ if(d!=0 && !std::isinf(d)) {
+ lij=1./(d*d);
+ }
+ degree += lap2[i*n + j] = lij;
+ }
+ lap2[i*n + i]=-degree;
+ delete [] D[i];
+ }
+ //GradientProjection::dumpSquareMatrix(Dij);
+ delete [] D;
+}
+// stickyNodes adds a small force attracting nodes
+// back to their starting positions
+void ConstrainedMajorizationLayout::setStickyNodes(
+ const double stickyWeight,
+ valarray<double> const & startX,
+ valarray<double> const & startY) {
+ COLA_ASSERT( startX.size()==n && startY.size()==n);
+ stickyNodes = true;
+ // not really constrained but we want to use GP solver rather than
+ // ConjugateGradient
+ constrainedLayout = true;
+ this->stickyWeight=stickyWeight;
+ this->startX = startX;
+ this->startY = startY;
+ for(unsigned i = 0; i<n; i++) {
+ lap2[i*n+i]-=stickyWeight;
+ }
+}
+
+void ConstrainedMajorizationLayout::majorize(
+ valarray<double> const & Dij, GradientProjection* gp,
+ valarray<double>& coords,
+ valarray<double> const & startCoords)
+{
+ double L_ij,dist_ij,degree;
+ /* compute the vector b */
+ /* multiply on-the-fly with distance-based laplacian */
+ valarray<double> b(n);
+ for (unsigned i = 0; i < n; i++) {
+ b[i] = degree = 0;
+ for (unsigned j = 0; j < n; j++) {
+ if (j == i) continue;
+ dist_ij = euclidean_distance(i, j);
+ /* skip zero distances */
+ if (dist_ij > 1e-30 && Dij[i*n+j] > 1e-30 && Dij[i*n+j] < 1e10) {
+ /* calculate L_ij := w_{ij}*d_{ij}/dist_{ij} */
+ L_ij = 1.0 / (dist_ij * Dij[i*n+j]);
+ degree -= L_ij;
+ b[i] += L_ij * coords[j];
+ }
+ }
+ if(stickyNodes) {
+ //double l = startCoords[i]-coords[i];
+ //l/=10.;
+ //b[i]-=stickyWeight*(coords[i]+l);
+ b[i] -= stickyWeight*startCoords[i];
+ }
+ b[i] += degree * coords[i];
+ COLA_ASSERT(!std::isnan(b[i]));
+ }
+ if(constrainedLayout) {
+ //printf("GP iteration...\n");
+ gp->solve(b,coords);
+ } else {
+ //printf("CG iteration...\n");
+ conjugate_gradient(lap2, coords, b, n, tol, n);
+ }
+ moveBoundingBoxes();
+}
+void ConstrainedMajorizationLayout::newton(
+ valarray<double> const & Dij, GradientProjection* gp,
+ valarray<double>& coords,
+ valarray<double> const & startCoords)
+{
+ COLA_UNUSED(startCoords);
+ /* compute the vector b */
+ /* multiply on-the-fly with distance-based laplacian */
+ valarray<double> b(n);
+ valarray<double> A(n*n);
+ for (unsigned i = 0; i < n; i++) {
+ b[i] = 0;
+ double Aii = 0;
+ for (unsigned j = 0; j < n; j++) {
+ if (j == i) continue;
+ double d = Dij[i*n+j];
+ double l = euclidean_distance(i,j);
+ double dx = coords[i]-coords[j];
+ double dy2 = l*l - dx*dx;
+ /* skip zero distances */
+ if (l > 1e-30
+ && d > 1e-30 && d < 1e10) {
+ if(d>80 && l > d) continue;
+ b[i]+=dx*(l-d)/(l*d*d);
+ Aii-=A[i*n+j]=(d*dy2/(l*l*l)-1)/(d*d);
+ }
+ }
+ A[i*n+i]=Aii;
+ }
+ if(constrainedLayout) {
+ //printf("GP iteration...\n");
+ gp->solve(b,coords);
+ } else {
+ //printf("CG iteration...\n");
+ /*
+ unsigned N=n-1;
+ valarray<double> b2(N);
+ valarray<double> A2(N*N);
+ valarray<double> x(N);
+ for(unsigned i=0;i<N;i++) {
+ b2=b[i];
+ x=coords[i];
+ for(unsigned j=0;j<N;j++) {
+ A2[i*N+j]=A[i*n+j];
+ }
+ }
+ conjugate_gradient(A2, x, b2, N, tol, N);
+ */
+ //valarray<double> x=coords;
+ //x-=x.sum()/n;
+ //conjugate_gradient(A, x, b, n, tol, n);
+ //double stepsize=0.5;
+ valarray<double> x=b;
+ // stepsize = g.g / (g A g)
+ double numerator = 0;
+ for(unsigned i=0;i<n;i++) {
+ numerator+=x[i]*x[i];
+ }
+ double denominator = 0;
+ for(unsigned i=0;i<n;i++) {
+ double r=0;
+ for(unsigned j=0;j<n;j++) {
+ r+=A[i*n+j]*x[j];
+ }
+ denominator+=r*x[i];
+ }
+ double stepsize=numerator/(2*denominator);
+ double oldstress=compute_stress(Dij);
+ valarray<double> oldcoords=coords;
+ while(stepsize>0.00001) {
+ coords=oldcoords-stepsize*x;
+ double stress=compute_stress(Dij);
+ printf(" stress=%f, stepsize=%f\n",stress,stepsize);
+ if(oldstress>=stress) {
+ break;
+ }
+ coords=oldcoords;
+ stepsize*=0.5;
+ }
+ }
+ moveBoundingBoxes();
+}
+inline double ConstrainedMajorizationLayout
+::compute_stress(valarray<double> const &Dij) {
+ double sum = 0, d, diff;
+ for (unsigned i = 1; i < n; i++) {
+ for (unsigned j = 0; j < i; j++) {
+ d = Dij[i*n+j];
+ if(!std::isinf(d)&&d!=numeric_limits<double>::max()) {
+ diff = d - euclidean_distance(i,j);
+ if(d>80&&diff<0) continue;
+ sum += diff*diff / (d*d);
+ }
+ }
+ if(stickyNodes) {
+ double l = startX[i]-X[i];
+ sum += stickyWeight*l*l;
+ l = startY[i]-Y[i];
+ sum += stickyWeight*l*l;
+ }
+ }
+ //printf("stress=%f\n",sum);
+ return sum;
+}
+
+void ConstrainedMajorizationLayout::run(bool x, bool y) {
+ if(constrainedLayout) {
+ vector<vpsc::Rectangle*>* pbb = boundingBoxes.empty()?nullptr:&boundingBoxes;
+ SolveWithMosek mosek = Off;
+ if(externalSolver) mosek=Outer;
+ // scaling doesn't currently work with straighten edges because sparse
+ // matrix used with dummy nodes is not properly scaled at the moment.
+ if(straightenEdges) setScaling(false);
+ gpX=new GradientProjection(
+ HORIZONTAL,&lap2,tol,100,ccs,unsatisfiableX,
+ avoidOverlaps,clusterHierarchy,pbb,scaling,mosek);
+ gpY=new GradientProjection(
+ VERTICAL,&lap2,tol,100,ccs,unsatisfiableY,
+ avoidOverlaps,clusterHierarchy,pbb,scaling,mosek);
+ }
+ if(n>0) do {
+ // to enforce clusters with non-intersecting, convex boundaries we
+ // could create cluster boundaries here with chains of dummy nodes (a
+ // dummy node for each vertex of the convex hull) connected by dummy
+ // straightenEdges and we'd then continue on to straightenEdges below.
+ // This should work assuming we already have a feasible (i.e. non
+ // overlapping cluster) state. The former could be enforced by an
+ // earlier stage involving simple rectangular cluster boundaries.
+ vector<straightener::Edge*> cedges;
+ if(!straightenEdges && nonOverlappingClusters) {
+ straightenEdges = &cedges;
+ }
+ if(preIteration) {
+ if ((*preIteration)()) {
+ for(vector<Lock>::iterator l=preIteration->locks.begin();
+ l!=preIteration->locks.end();l++) {
+ unsigned id=l->getID();
+ double x=l->pos(HORIZONTAL), y=l->pos(VERTICAL);
+ X[id]=x;
+ Y[id]=y;
+ if(stickyNodes) {
+ startX[id]=x;
+ startY[id]=y;
+ }
+ boundingBoxes[id]->moveCentre(x,y);
+ if(constrainedLayout) {
+ gpX->fixPos(id,X[id]);
+ gpY->fixPos(id,Y[id]);
+ }
+ }
+ } else { break; }
+ }
+ /* Axis-by-axis optimization: */
+ if(straightenEdges) {
+ if(x) straighten(*straightenEdges,HORIZONTAL);
+ if(y) straighten(*straightenEdges,VERTICAL);
+ } else {
+ if(majorization) {
+ if(x) majorize(Dij,gpX,X,startX);
+ if(y) majorize(Dij,gpY,Y,startY);
+ } else {
+ if(x) newton(Dij,gpX,X,startX);
+ if(y) newton(Dij,gpY,Y,startY);
+ }
+ }
+ if(clusterHierarchy) {
+ for(Clusters::iterator c=clusterHierarchy->clusters.begin();
+ c!=clusterHierarchy->clusters.end();c++) {
+ (*c)->computeBoundary(boundingBoxes);
+ }
+ }
+ if(preIteration && constrainedLayout) {
+ for(vector<Lock>::iterator l=preIteration->locks.begin();
+ l!=preIteration->locks.end();l++) {
+ gpX->unfixPos(l->getID());
+ gpY->unfixPos(l->getID());
+ }
+ }
+ } while(!(*done)(compute_stress(Dij),X,Y));
+}
+double ConstrainedMajorizationLayout::computeStress() {
+ return compute_stress(Dij);
+}
+void ConstrainedMajorizationLayout::runOnce(bool x, bool y) {
+ if(constrainedLayout) {
+ vector<vpsc::Rectangle*>* pbb = boundingBoxes.empty()?nullptr:&boundingBoxes;
+ SolveWithMosek mosek = Off;
+ if(externalSolver) mosek=Outer;
+ // scaling doesn't currently work with straighten edges because sparse
+ // matrix used with dummy nodes is not properly scaled at the moment.
+ if(straightenEdges) setScaling(false);
+ gpX=new GradientProjection(
+ HORIZONTAL,&lap2,tol,100,ccs,unsatisfiableX,
+ avoidOverlaps,clusterHierarchy,pbb,scaling,mosek);
+ gpY=new GradientProjection(
+ VERTICAL,&lap2,tol,100,ccs,unsatisfiableY,
+ avoidOverlaps,clusterHierarchy,pbb,scaling,mosek);
+ }
+ if(n>0) {
+ // to enforce clusters with non-intersecting, convex boundaries we
+ // could create cluster boundaries here with chains of dummy nodes (a
+ // dummy node for each vertex of the convex hull) connected by dummy
+ // straightenEdges and we'd then continue on to straightenEdges below.
+ // This should work assuming we already have a feasible (i.e. non
+ // overlapping cluster) state. The former could be enforced by an
+ // earlier stage involving simple rectangular cluster boundaries.
+ vector<straightener::Edge*> cedges;
+ if(!straightenEdges && nonOverlappingClusters) {
+ straightenEdges = &cedges;
+ }
+ if(preIteration) {
+ if ((*preIteration)()) {
+ for(vector<Lock>::iterator l=preIteration->locks.begin();
+ l!=preIteration->locks.end();l++) {
+ unsigned id=l->getID();
+ double x=l->pos(HORIZONTAL), y=l->pos(VERTICAL);
+ X[id]=x;
+ Y[id]=y;
+ if(stickyNodes) {
+ startX[id]=x;
+ startY[id]=y;
+ }
+ boundingBoxes[id]->moveCentre(x,y);
+ if(constrainedLayout) {
+ gpX->fixPos(id,X[id]);
+ gpY->fixPos(id,Y[id]);
+ }
+ }
+ } else { return; }
+ }
+ /* Axis-by-axis optimization: */
+ if(straightenEdges) {
+ if(x) straighten(*straightenEdges,HORIZONTAL);
+ if(y) straighten(*straightenEdges,VERTICAL);
+ } else {
+ if(majorization) {
+ if(x) majorize(Dij,gpX,X,startX);
+ if(y) majorize(Dij,gpY,Y,startY);
+ } else {
+ if(x) newton(Dij,gpX,X,startX);
+ if(y) newton(Dij,gpY,Y,startY);
+ }
+ }
+ if(clusterHierarchy) {
+ for(Clusters::iterator c=clusterHierarchy->clusters.begin();
+ c!=clusterHierarchy->clusters.end();c++) {
+ (*c)->computeBoundary(boundingBoxes);
+ }
+ }
+ if(preIteration && constrainedLayout) {
+ for(vector<Lock>::iterator l=preIteration->locks.begin();
+ l!=preIteration->locks.end();l++) {
+ gpX->unfixPos(l->getID());
+ gpY->unfixPos(l->getID());
+ }
+ }
+ }
+}
+void ConstrainedMajorizationLayout::straighten(vector<straightener::Edge*>& sedges, Dim dim) {
+ GradientProjection * gp;
+ valarray<double>* coords;
+ valarray<double>* startCoords;
+ if(dim==HORIZONTAL) {
+ gp=gpX;
+ coords=&X;
+ startCoords=&startX;
+ } else {
+ gp=gpY;
+ coords=&Y;
+ startCoords=&startY;
+ }
+ vector<straightener::Node*> snodes;
+ if(dim==HORIZONTAL) {
+ Rectangle::setXBorder(0.0001);
+ }
+ for (unsigned i=0;i<n;i++) {
+ snodes.push_back(new straightener::Node(i,boundingBoxes[i]));
+ }
+ if(dim==HORIZONTAL) {
+ Rectangle::setXBorder(0);
+ }
+ for (unsigned i=n;i<gp->getNumStaticVars();i++) {
+ // insert some dummy nodes
+ snodes.push_back(new straightener::Node(i,-100,-100));
+ }
+ vector<straightener::Cluster*> sclusters;
+
+ if(nonOverlappingClusters && clusterHierarchy) {
+ generateClusterBoundaries(dim,snodes,sedges,boundingBoxes,
+ *clusterHierarchy,sclusters);
+ }
+ vector<SeparationConstraint*> cs;
+ straightener::generateConstraints(dim,snodes,sedges,cs,xSkipping);
+ straightener::LinearConstraints linearConstraints;
+ for(unsigned i=0;i<sedges.size();i++) {
+ sedges[i]->nodePath(snodes,!nonOverlappingClusters);
+ vector<unsigned>& path=sedges[i]->path;
+ vector<unsigned>& activePath=sedges[i]->activePath;
+ // take u and v as the ends of the line
+ // unsigned u=path[0];
+ // unsigned v=path[path.size()-1];
+ double total_length=0;
+ for(unsigned j=1;j<path.size();j++) {
+ unsigned u=path[j-1], v=path[j];
+ total_length+=snodes[u]->euclidean_distance(snodes[v]);
+ }
+ // keep potential bends straight
+ for(unsigned j=1;j<activePath.size();j++) {
+ unsigned uj=activePath[j-1], vj=activePath[j];
+ unsigned u=path[uj], v=path[vj];
+ for(unsigned k=uj+1;k<vj;k++) {
+ unsigned b=path[k];
+ // might be useful to have greater weight for potential bends than actual bends
+ linearConstraints.push_back(new straightener::LinearConstraint(
+ *snodes[u],*snodes[v],*snodes[b],-potBendWeight));
+ }
+ }
+ // straighten actual bends
+ for(unsigned j=1;j<activePath.size()-1;j++) {
+ unsigned u=path[activePath[j-1]],
+ b=path[activePath[j]],
+ v=path[activePath[j+1]];
+ linearConstraints.push_back(new straightener::LinearConstraint(
+ *snodes[u],*snodes[v],*snodes[b],-bendWeight));
+ }
+ }
+ //std::cout << (dim==HORIZONTAL?"X":"Y") << " snodes.size "<<snodes.size()<< " n="<<n<<std::endl;
+ //std::cout << "Generated "<<linearConstraints.size()<< " linear constraints"<<std::endl;
+ SparseMap Q(snodes.size());
+ for(straightener::LinearConstraints::iterator i=linearConstraints.begin();
+ i!= linearConstraints.end();i++) {
+ straightener::LinearConstraint* c=*i;
+ Q(c->u,c->u)+=c->w*c->duu;
+ Q(c->u,c->v)+=c->w*c->duv;
+ Q(c->u,c->b)+=c->w*c->dub;
+ Q(c->v,c->u)+=c->w*c->duv;
+ Q(c->v,c->v)+=c->w*c->dvv;
+ Q(c->v,c->b)+=c->w*c->dvb;
+ Q(c->b,c->b)+=c->w*c->dbb;
+ Q(c->b,c->u)+=c->w*c->dub;
+ Q(c->b,c->v)+=c->w*c->dvb;
+ }
+ double boundaryWeight = 0.0001;
+ for(unsigned i=0;i<sclusters.size();i++) {
+ // for each cluster boundary chain create an attractive force between
+ // each pair of adjacent nodes
+ straightener::Cluster* c = sclusters[i];
+ for(unsigned j=0;j<c->boundary.size();j++) {
+ straightener::Edge* e = c->boundary[j];
+ Q(e->startNode,e->endNode)+=boundaryWeight;
+ Q(e->endNode,e->startNode)+=boundaryWeight;
+ Q(e->startNode,e->startNode)-=boundaryWeight;
+ Q(e->endNode,e->endNode)-=boundaryWeight;
+ }
+ }
+ constrainedLayout = true;
+ SparseMatrix sparseQ(Q);
+ gp->straighten(&sparseQ,cs,snodes);
+ //return;
+ majorize(Dij,gp,*coords,*startCoords);
+ valarray<double> const & r=gp->getFullResult();
+ for(unsigned i=0;i<snodes.size();i++) {
+ snodes[i]->pos[dim] = r[i];
+ }
+ for(unsigned i=0;i<sedges.size();i++) {
+ sedges[i]->createRouteFromPath(snodes);
+ sedges[i]->dummyNodes.clear();
+ sedges[i]->path.clear();
+ }
+ for(unsigned i=0;i<sclusters.size();i++) {
+ straightener::Cluster *sc = sclusters[i];
+ //sc->updateActualBoundary();
+ delete sc;
+ }
+ for(unsigned i=0;i<cs.size();i++) {
+ delete cs[i];
+ }
+ for(unsigned i=0;i<linearConstraints.size();i++) {
+ delete linearConstraints[i];
+ }
+ for(unsigned i=0;i<snodes.size();i++) {
+ delete snodes[i];
+ }
+}
+
+Rectangle bounds(vector<Rectangle*>& rs) {
+ COLA_ASSERT(!rs.empty());
+
+ double left = rs[0]->getMinX(), right = rs[0]->getMaxX(),
+ top = rs[0]->getMinY(), bottom = rs[0]->getMaxY();
+
+ for(unsigned i = 1; i < rs.size(); i++) {
+ left = min(left,rs[i]->getMinX());
+ right = max(right,rs[i]->getMaxX());
+ top = min(top,rs[i]->getMinY());
+ bottom = max(bottom,rs[i]->getMaxY());
+ }
+ return Rectangle(left, right, top, bottom);
+}
+
+#if 0
+ void removeClusterOverlap(RootCluster& clusterHierarchy, vpsc::Rectangles& rs, Locks& locks, vpsc::Dim dim) {
+ if(clusterHierarchy.nodes.size()>0 || clusterHierarchy.clusters.size()>0) {
+ vpsc::Variables vars;
+ vpsc::Constraints cs;
+ for(unsigned i=0;i<rs.size();i++) {
+ vars.push_back(new vpsc::Variable(i, rs[i]->getCentreD(dim)));
+ }
+
+ clusterHierarchy.computeBoundingRect(rs);
+ clusterHierarchy.createVars(dim,rs,vars);
+ clusterHierarchy.generateNonOverlapConstraints(dim, cola::Both, rs, vars, cs);
+
+ /*
+ if(dim==vpsc::HORIZONTAL) {
+ vpsc::Rectangle::setXBorder(0.001);
+ // use rs->size() rather than n because some of the variables may
+ // be dummy vars with no corresponding rectangle
+ generateXConstraints(rs,vars,cs,true);
+ vpsc::Rectangle::setXBorder(0);
+ } else {
+ generateYConstraints(rs,vars,cs);
+ }
+ */
+ for(Locks::iterator l=locks.begin();
+ l!=locks.end();l++) {
+ unsigned id=l->getID();
+ double x=l->pos(HORIZONTAL), y=l->pos(VERTICAL);
+ Variable* v=vars[id];
+ v->desiredPosition = (dim==vpsc::HORIZONTAL)?x:y;
+ v->weight = 1000;
+ }
+ /*
+ vpsc::Solver s(vars,cs);
+ try {
+ s.satisfy();
+ } catch(const char* e) {
+ cerr << "ERROR from solver in GraphData::removeOverlap : " << e << endl;
+ }
+ */
+ vpsc::IncSolver s(vars,cs);
+ try {
+ s.solve();
+ } catch(const char* e) {
+ cerr << "ERROR from solver in GraphData::removeOverlap : " << e << endl;
+ }
+ clusterHierarchy.updateBounds(dim);
+ /*
+ for(unsigned i=0;i<cs.size();++i) {
+ if(cs[i]->unsatisfiable) {
+ cout << "Unsatisfiable constraint: " << *cs[i] << endl;
+ }
+ }
+ */
+ for(unsigned i=0;i<rs.size();i++) {
+ rs[i]->moveCentreD(dim,vars[i]->finalPosition);
+ }
+ for(Locks::iterator l=locks.begin();
+ l!=locks.end();l++) {
+ //unsigned id=l->getID();
+ }
+ for_each(vars.begin(),vars.end(),delete_object());
+ for_each(cs.begin(),cs.end(),delete_object());
+ }
+ }
+ void removeClusterOverlapFast(RootCluster& clusterHierarchy, vpsc::Rectangles& rs, Locks& locks) {
+ removeClusterOverlap(clusterHierarchy, rs, locks, vpsc::HORIZONTAL);
+ removeClusterOverlap(clusterHierarchy, rs, locks, vpsc::VERTICAL);
+ }
+#endif
+
+ ConstrainedMajorizationLayout* simpleCMLFactory(
+ vpsc::Rectangles& rs,
+ std::vector<Edge> const & es,
+ RootCluster* clusterHierarchy,
+ const double idealLength,
+ bool useNeighbourStress
+ ) {
+ cola::EdgeLengths eLengths;
+ for(size_t i = 0; i < es.size(); ++i) {
+ eLengths.push_back(1);
+ }
+ return new ConstrainedMajorizationLayout(rs, es, clusterHierarchy, idealLength,
+ eLengths, nullptr, nullptr, useNeighbourStress);
+ };
+
+} // namespace cola
diff --git a/src/3rdparty/adaptagrams/libcola/cola.h b/src/3rdparty/adaptagrams/libcola/cola.h
new file mode 100644
index 0000000..40043cd
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/cola.h
@@ -0,0 +1,1002 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2015 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+ * Michael Wybrow
+*/
+
+#ifndef COLA_H
+#define COLA_H
+
+#include <utility>
+#include <iterator>
+#include <vector>
+#include <valarray>
+#include <algorithm>
+#include <cmath>
+#include <iostream>
+
+#include "libcola/gradient_projection.h"
+#include "libcola/cluster.h"
+#include "libcola/straightener.h"
+#include "libcola/exceptions.h"
+#include "libcola/pseudorandom.h"
+
+namespace vpsc { class Rectangle; }
+namespace topology {
+ class ColaTopologyAddon;
+}
+namespace dialect {
+ class Graph;
+}
+
+
+/**
+ * @namespace cola
+ * @brief libcola: Force-directed network layout subject to
+ * separation constraints library.
+ *
+ * You should use COLA via an instance of the ConstrainedFDLayout class.
+*/
+namespace cola {
+
+class NonOverlapConstraints;
+class NonOverlapConstraintExemptions;
+
+//! @brief A vector of node Indexes.
+typedef std::vector<unsigned> NodeIndexes;
+
+//! @brief A vector of NodeIndexes.
+typedef std::vector<NodeIndexes> ListOfNodeIndexes;
+
+//! Edges are simply a pair of indices to entries in the Node vector
+typedef std::pair<unsigned, unsigned> Edge;
+
+//! EdgeLengths is a vector of ideal lengths for edges corresponding to
+//! edges in the edge list.
+typedef std::vector<double> EdgeLengths;
+#define StandardEdgeLengths EdgeLengths()
+
+/**
+ * @brief A Lock specifies a required position for a node.
+ */
+class Lock {
+public:
+ Lock() {}
+ /**
+ * @brief Constructs a Lock object for a given node and position.
+ *
+ * @param[in] id The index of the node in the Rectangles vector.
+ * @param[in] X The node's fixed position in the x-dimension.
+ * @param[in] Y The node's fixed position in the y-dimension.
+ */
+ Lock(unsigned id, double X, double Y) : id(id), x(X), y(Y) {
+ }
+ unsigned getID() const {
+ return id;
+ }
+ double pos(vpsc::Dim dim) const {
+ return dim==vpsc::HORIZONTAL?x:y;
+ }
+private:
+ unsigned id;
+ double x;
+ double y;
+};
+//! @brief A vector of Lock objects.
+typedef std::vector<cola::Lock> Locks;
+
+/**
+ * @brief A Resize specifies a new required bounding box for a node.
+ */
+class Resize {
+public:
+ Resize() {}
+ /**
+ * @brief Constructs a Resize object for a given node and it's new
+ * bounding box.
+ *
+ * @param[in] id The index of the node in the Rectangles vector.
+ * @param[in] x The minimum horizontal value for the node's new
+ * bounding box.
+ * @param[in] y The minimum vertical value for the node's new
+ * bounding box.
+ * @param[in] w The width value for the node's new bounding box.
+ * @param[in] h The height value for the node's new bounding box.
+ */
+ Resize(unsigned id, double x, double y, double w, double h)
+ : id(id), target(x,x+w,y,y+h) {}
+ unsigned getID() const {
+ return id;
+ }
+ const vpsc::Rectangle* getTarget() const {
+ return &target;
+ }
+private:
+ unsigned id;
+ vpsc::Rectangle target;
+};
+//! @brief A vector of Resize objects.
+typedef std::vector<cola::Resize> Resizes;
+
+/*
+ * Setting a desired position for a node adds a term to the goal function
+ * drawing the node towards that desired position
+ */
+struct DesiredPosition {
+ unsigned id;
+ double x;
+ double y;
+ double weight;
+};
+typedef std::vector<cola::DesiredPosition> DesiredPositions;
+
+/*
+ * desired positions which should override those computed by applying forces
+ * are passed in for a set of nodes. The first entry is the Node->id, the
+ * second is the desired position.
+ */
+typedef std::pair<unsigned,double> DesiredPositionInDim;
+typedef std::vector<DesiredPositionInDim> DesiredPositionsInDim;
+
+/**
+ * @brief A default functor that is called before each iteration in the
+ * main loop of the ConstrainedFDLayout::run() method.
+ *
+ * Override the operator() for things like locking the position of nodes
+ * for the duration of the iteration.
+ *
+ * If the operator() returns false the subsequent iterations are
+ * abandoned, i.e., layout ends immediately. You can make it return true
+ * when a user-interrupt is detected, for instance.
+ */
+class PreIteration {
+public:
+ /**
+ * @brief Constructs a PreIteration object that handles locking and
+ * resizing of nodes.
+ *
+ * @param[in] locks A list of nodes (by index) and positions at which
+ * they should be locked.
+ * @param[in] resizes A list of nodes (by index) and required dimensions
+ * for their bounding rects to be resized to.
+ */
+ PreIteration(
+ Locks& locks=__locksNotUsed,
+ Resizes& resizes=__resizesNotUsed)
+ : locks(locks)
+ , resizes(resizes)
+ , changed(true) {}
+ PreIteration(Resizes& resizes)
+ : locks(__locksNotUsed)
+ , resizes(resizes)
+ , changed(true) {}
+
+// To prevent C++ objects from being destroyed in garbage collected languages
+// when the libraries are called from SWIG, we hide the declarations of the
+// destructors and prevent generation of default destructors.
+#ifndef SWIG
+ virtual ~PreIteration() {}
+#endif
+ virtual bool operator()() { return true; }
+ Locks& locks;
+ Resizes& resizes;
+ bool changed;
+private:
+ static Locks __locksNotUsed;
+ static Resizes __resizesNotUsed;
+};
+
+/**
+ * @brief A default functor that is called after each iteration of the layout
+ * algorithm.
+ *
+ * You can either instantiate ConstrainedFDLayout with an instance of this
+ * class setting the tolerance and maxiterations as desired, or create a
+ * derived class implementing the operator() to do your own convergence test,
+ * or create your own operator() that calls the TestConvergence::operator() in
+ * order to do any other post processing you might need, e.g., to animate
+ * changes.
+ */
+class TestConvergence {
+public:
+ double old_stress;
+ TestConvergence(const double tol = 1e-4, const unsigned maxiterations = 100)
+ : tolerance(tol),
+ maxiterations(maxiterations)
+ { reset(); }
+ virtual ~TestConvergence() {}
+
+public:
+ virtual bool operator()(const double new_stress, std::valarray<double> & X, std::valarray<double> & Y)
+ {
+ COLA_UNUSED(X);
+ COLA_UNUSED(Y);
+
+ iterations++;
+ //std::cout<<"iteration="<<iterations<<", old_stress="<<old_stress<<", new_stress="<<new_stress<<std::endl;
+ if (old_stress == DBL_MAX) {
+ old_stress = new_stress;
+ return iterations >= maxiterations;
+ }
+ // converged if relative decrease in stress falls below threshold
+ // or if stress increases (shouldn't happen for straight majorization)
+ bool converged =
+ (old_stress - new_stress) / (new_stress + 1e-10) < tolerance
+ || iterations > maxiterations;
+ old_stress = new_stress;
+ return converged;
+ }
+ void reset() {
+ old_stress = DBL_MAX;
+ iterations = 0;
+ }
+ const double tolerance;
+ const unsigned maxiterations;
+ unsigned iterations;
+};
+
+/**
+ * @brief Implements the Constrained Majorization graph layout algorithm
+ * (deprecated).
+ *
+ * The optimisation method used is "stress majorization", where a sequence of
+ * quadratic functions which strictly bound the stress from above, is solved
+ * to monotonically reduce the stress (by iteratively changing the
+ * configuration of nodes).
+ *
+ * Once the problem has been set up, call run() or runOnce() to run the
+ * layout algorithm.
+ *
+ * @note We recommend the use of ConstrainedFDLayout instead of this class.
+ * ConstrainedFDLayout tends to produce better results and has more
+ * features. We are no longer working on ConstrainedMajorizationLayout.
+ */
+class ConstrainedMajorizationLayout {
+public:
+ /**
+ * @brief Constructs a constrained majorization layout instance.
+ *
+ * @param[in] rs Bounding boxes of nodes at their initial positions.
+ * @param[in] es Simple pair edges, giving indices of the start and end
+ * nodes in rs.
+ * @param[in] clusterHierarchy A pointer to a RootCluster object defining
+ * the cluster hierarchy (optional).
+ * @param[in] idealLength Aa scalar modifier of ideal edge lengths in
+ * eLengths.
+ * @param[in] eLengths Individual ideal lengths for edges.
+ * The actual ideal length used for the ith edge is
+ * idealLength*eLengths[i], or if eLengths is empty
+ * then just idealLength is used (i.e., eLengths[i]
+ * is assumed to be 1).
+ * @param[in] done A test of convergence operation called at the end of
+ * each iteration (optional).
+ * @param[in] preIteration An operation called before each iteration
+ * (optional).
+ */
+ ConstrainedMajorizationLayout(
+ vpsc::Rectangles& rs,
+ std::vector<Edge> const & es,
+ RootCluster* clusterHierarchy,
+ const double idealLength,
+ EdgeLengths eLengths = StandardEdgeLengths,
+ TestConvergence *doneTest = nullptr,
+ PreIteration* preIteration=nullptr,
+ bool useNeighbourStress = false);
+ /**
+ * @brief Specify a set of compound constraints to apply to the layout.
+ *
+ * @param[in] ccs The compound constraints.
+ */
+ void setConstraints(cola::CompoundConstraints* ccs) {
+ constrainedLayout = true;
+ this->ccs=ccs;
+ }
+
+ void setConstraintsVector(cola::CompoundConstraints& ccs) {
+ constrainedLayout = true;
+ cola::CompoundConstraints *ccsp = new cola::CompoundConstraints;
+ for (size_t i = 0; i < ccs.size(); ++i) {
+ ccsp->push_back(ccs.at(i));
+ }
+ this->ccs=ccsp;
+ }
+
+ /**
+ * @brief Register to receive information about unsatisfiable constraints.
+ *
+ * In the case of unsatisifiable constraints, the solver will drop
+ * unsatisfiable constraints of lowest priority. Information about these
+ * will be written to these lists after each iteration of constrained
+ * layout.
+ *
+ * param[out] unsatisfiableX A pointer to an UnsatisfiableConstraintInfos
+ * object that will be used to record
+ * unsatisfiable constraints in the x-dimension.
+ * param[out] unsatisfiableY A pointer to an UnsatisfiableConstraintInfos
+ * object that will be used to record
+ * unsatisfiable constraints in the y-dimension.
+ */
+ void setUnsatisfiableConstraintInfo(
+ UnsatisfiableConstraintInfos *unsatisfiableX,
+ UnsatisfiableConstraintInfos *unsatisfiableY) {
+ this->unsatisfiableX = unsatisfiableX;
+ this->unsatisfiableY = unsatisfiableY;
+ }
+ /**
+ * Sticky nodes causes nodes to spring back to (startX,startY) when
+ * unconstrained.
+ */
+ void setStickyNodes(const double stickyWeight,
+ std::valarray<double> const & startX,
+ std::valarray<double> const & startY);
+
+ /**
+ * Scaling speeds up the solver by conditioning the quadratic terms matrix.
+ */
+ void setScaling(bool scaling) {
+ this->scaling=scaling;
+ }
+ /**
+ * Says that the Mosek optimisation library should be used to solve the
+ * quadratic programs rather than the libvpsc solver.
+ */
+ void setExternalSolver(bool externalSolver) {
+ this->externalSolver=externalSolver;
+ }
+ /**
+ * At each iteration of layout, generate constraints to avoid overlaps.
+ * If bool horizontal is true, all overlaps will be resolved horizontally,
+ * otherwise some overlaps will be left to be resolved vertically where
+ * doing so leads to less displacement
+ */
+ void setAvoidOverlaps(bool horizontal = false) {
+ constrainedLayout = true;
+ this->avoidOverlaps = horizontal ? Horizontal : Both;
+ }
+ /**
+ * Add constraints to prevent clusters overlapping.
+ */
+ void setNonOverlappingClusters() {
+ constrainedLayout = true;
+ nonOverlappingClusters = true;
+ }
+ /**
+ * For the specified edges (with routings), generate dummy vars and
+ * constraints to try and straighten them. bendWeight controls how hard we
+ * try to straighten existing bends potBendWeight controls how much we try
+ * to keep straight edges straight
+ */
+ void setStraightenEdges(std::vector<straightener::Edge*>* straightenEdges,
+ double bendWeight = 0.01, double potBendWeight = 0.1,
+ bool xSkipping = true) {
+ for(std::vector<straightener::Edge*>::const_iterator e=straightenEdges->begin();
+ e!=straightenEdges->end();e++) {
+ (*e)->rerouteAround(boundingBoxes);
+ }
+ constrainedLayout = true;
+ this->xSkipping = xSkipping;
+ this->straightenEdges = straightenEdges;
+ this->bendWeight = bendWeight;
+ this->potBendWeight = potBendWeight;
+ }
+ /**
+ * Update position of bounding boxes.
+ */
+ void moveBoundingBoxes() {
+ for(unsigned i=0;i<n;i++) {
+ boundingBoxes[i]->moveCentre(X[i],Y[i]);
+ }
+ }
+
+ ~ConstrainedMajorizationLayout() {
+ if (using_default_done)
+ {
+ delete done;
+ }
+
+ if(constrainedLayout) {
+ delete gpX;
+ delete gpY;
+ }
+ }
+ /**
+ * @brief Implements the main layout loop, taking descent steps until
+ * stress is no-longer significantly reduced.
+ *
+ * @param[in] x If true, layout will be performed in x-dimension
+ * (default: true).
+ * @param[in] y If true, layout will be performed in y-dimension
+ * (default: true).
+ */
+ void run(bool x=true, bool y=true);
+ /**
+ * @brief Same as run(), but only applies one iteration.
+ *
+ * This may be useful here it's too hard to implement a call-back
+ * (e.g., in java apps).
+ *
+ * @param[in] x If true, layout will be performed in x-dimension
+ * (default: true).
+ * @param[in] y If true, layout will be performed in y-dimension
+ * (default: true).
+ */
+ void runOnce(bool x=true, bool y=true);
+ void straighten(std::vector<straightener::Edge*>&, vpsc::Dim);
+ void setConstrainedLayout(bool c) {
+ constrainedLayout=c;
+ }
+ double computeStress();
+private:
+ double euclidean_distance(unsigned i, unsigned j) {
+ return sqrt(
+ (X[i] - X[j]) * (X[i] - X[j]) +
+ (Y[i] - Y[j]) * (Y[i] - Y[j]));
+ }
+ double compute_stress(std::valarray<double> const & Dij);
+ void majorize(std::valarray<double> const & Dij,GradientProjection* gp, std::valarray<double>& coords, std::valarray<double> const & startCoords);
+ void newton(std::valarray<double> const & Dij,GradientProjection* gp, std::valarray<double>& coords, std::valarray<double> const & startCoords);
+ unsigned n; //< number of nodes
+ //std::valarray<double> degrees;
+ std::valarray<double> lap2; //< graph laplacian
+ std::valarray<double> Q; //< quadratic terms matrix used in computations
+ std::valarray<double> Dij; //< all pairs shortest path distances
+ double tol; //< convergence tolerance
+ TestConvergence *done; //< functor used to determine if layout is finished
+ bool using_default_done; // Whether we allocated a default TestConvergence object.
+ PreIteration* preIteration; //< client can use this to create locks on nodes
+ vpsc::Rectangles boundingBoxes; //< node bounding boxes
+ /*
+ * stickyNodes controls whether nodes are attracted to their starting
+ * positions (at time of ConstrainedMajorizationLayout instantiation)
+ * stored in startX, startY
+ */
+ std::valarray<double> X, Y;
+ bool stickyNodes;
+ double stickyWeight;
+ std::valarray<double> startX;
+ std::valarray<double> startY;
+ double edge_length;
+ bool constrainedLayout;
+ bool nonOverlappingClusters;
+ /*
+ * A cluster is a set of nodes that are somehow semantically grouped
+ * and should therefore be kept together a bit more tightly than, and
+ * preferably without overlapping, the rest of the graph.
+ *
+ * We achieve this by augmenting the L matrix with stronger attractive
+ * forces between all members of a cluster (other than the root)
+ * and by maintaining a (preferably convex) hull around those
+ * constituents which, using constraints and dummy variables, is
+ * prevented from overlapping other parts of the graph.
+ *
+ * Clusters are defined over the graph in a hierarchy starting with
+ * a single root cluster.
+ *
+ * Need to:
+ * - augment Lap matrix with intra cluster forces
+ * - compute convex hull of each cluster
+ * - from convex hull generate "StraightenEdges"
+ */
+ RootCluster *clusterHierarchy;
+ GradientProjection *gpX, *gpY;
+ cola::CompoundConstraints *ccs;
+ UnsatisfiableConstraintInfos *unsatisfiableX, *unsatisfiableY;
+ NonOverlapConstraintsMode avoidOverlaps;
+ std::vector<straightener::Edge*>* straightenEdges;
+
+ double bendWeight, potBendWeight;
+ /*
+ * determines whether we should leave some overlaps to be resolved
+ * vertically when generating straightening constraints in the x-dim
+ */
+ bool xSkipping;
+ /*
+ * when using the gradient projection optimisation method, the following
+ * controls whether the problem should be preconditioned by affine scaling
+ */
+ bool scaling;
+ /*
+ * if the Mosek quadratic programming environment is available it may be
+ * used to solve each iteration of stress majorization... slow but useful
+ * for testing
+ */
+ bool externalSolver;
+ bool majorization;
+};
+
+vpsc::Rectangle bounds(vpsc::Rectangles& rs);
+
+class ConstrainedFDLayout;
+
+/**
+ * @brief Interface for writing COLA addons to handle topology preserving
+ * layout.
+ */
+class TopologyAddonInterface
+{
+ public:
+ TopologyAddonInterface()
+ {
+ }
+
+ virtual ~TopologyAddonInterface()
+ {
+ }
+
+ virtual TopologyAddonInterface *clone(void) const
+ {
+ return new TopologyAddonInterface(*this);
+ }
+
+ virtual void freeAssociatedObjects(void)
+ {
+ }
+
+ virtual void handleResizes(const Resizes& resizeList, unsigned n,
+ std::valarray<double>& X, std::valarray<double>& Y,
+ cola::CompoundConstraints& ccs,
+ vpsc::Rectangles& boundingBoxes,
+ cola::RootCluster* clusterHierarchy)
+ {
+ COLA_UNUSED(resizeList);
+ COLA_UNUSED(n);
+ COLA_UNUSED(X);
+ COLA_UNUSED(Y);
+ COLA_UNUSED(ccs);
+ COLA_UNUSED(boundingBoxes);
+ COLA_UNUSED(clusterHierarchy);
+ }
+ virtual void computePathLengths(unsigned short** G)
+ {
+ COLA_UNUSED(G);
+ }
+ virtual double computeStress(void) const
+ {
+ return 0;
+ }
+ virtual bool useTopologySolver(void) const
+ {
+ return false;
+ }
+ virtual void makeFeasible(bool generateNonOverlapConstraints,
+ vpsc::Rectangles& boundingBoxes,
+ cola::RootCluster* clusterHierarchy)
+ {
+ COLA_UNUSED(generateNonOverlapConstraints);
+ COLA_UNUSED(boundingBoxes);
+ COLA_UNUSED(clusterHierarchy);
+ }
+ virtual void moveTo(const vpsc::Dim dim, vpsc::Variables& vs,
+ vpsc::Constraints& cs, std::valarray<double> &coords,
+ cola::RootCluster* clusterHierarchy)
+ {
+ COLA_UNUSED(dim);
+ COLA_UNUSED(vs);
+ COLA_UNUSED(cs);
+ COLA_UNUSED(coords);
+ COLA_UNUSED(clusterHierarchy);
+ }
+ virtual double applyForcesAndConstraints(ConstrainedFDLayout *layout,
+ const vpsc::Dim dim, std::valarray<double>& g,
+ vpsc::Variables& vs, vpsc::Constraints& cs,
+ std::valarray<double> &coords,
+ DesiredPositionsInDim& des, double oldStress)
+ {
+ COLA_UNUSED(layout);
+ COLA_UNUSED(dim);
+ COLA_UNUSED(g);
+ COLA_UNUSED(vs);
+ COLA_UNUSED(cs);
+ COLA_UNUSED(coords);
+ COLA_UNUSED(des);
+ COLA_UNUSED(oldStress);
+ return 0;
+ }
+};
+
+
+/**
+ * @brief Implements a constrained force-directed layout algorithm.
+ *
+ * This method is based on a non-linear gradient projection technique.
+ * Conceptually it's similar to a force directed method like
+ * Fruchterman-Reingold---but using a more principled goal function and
+ * optimisation techniques.
+ */
+class ConstrainedFDLayout {
+public:
+ /**
+ * @brief Constructs a constrained force-directed layout instance.
+ *
+ * If an empty edges (es) vector is passed to the constructor, then
+ * constraint satisfaction will be performed, but no force-directed
+ * layout. In this case, idealLength and eLengths have no effect.
+ *
+ * Conversely, if no constraints or clusters are specified and no overlap
+ * prevention is enabled, but edge info is given, then pure force-directed
+ * layout will be performed.
+ *
+ * @param[in] rs Bounding boxes of nodes at their initial positions.
+ * @param[in] es Simple pair edges, giving indices of the start and end
+ * nodes in rs.
+ * @param[in] idealLength A scalar modifier of ideal edge lengths in
+ * eLengths or of 1 if no ideal lengths are
+ * specified.
+ * @param[in] eLengths Individual ideal lengths for edges.
+ * The actual ideal length used for the ith edge is
+ * idealLength*eLengths[i], or if eLengths is nullptr a
+ * then just idealLength is used (i.e., eLengths[i]
+ * is assumed to be 1).
+ * @param[in] done A test of convergence operation called at the end of
+ * each iteration (optional). If not given, uses a
+ * default TestConvergence object.
+ * @param[in] preIteration An operation called before each iteration
+ * (optional).
+ */
+ ConstrainedFDLayout(
+ const vpsc::Rectangles& rs,
+ const std::vector<cola::Edge>& es,
+ const double idealLength,
+ const EdgeLengths& eLengths = StandardEdgeLengths,
+ TestConvergence* doneTest = nullptr,
+ PreIteration* preIteration = nullptr);
+ ~ConstrainedFDLayout();
+
+ /**
+ * @brief Implements the main layout loop, taking descent steps until
+ * stress is no-longer significantly reduced.
+ *
+ * @param[in] x If true, layout will be performed in x-dimension
+ * (default: true).
+ * @param[in] y If true, layout will be performed in y-dimension
+ * (default: true).
+ */
+ void run(bool x=true, bool y=true);
+
+ /**
+ * @brief Same as run(), but only applies one iteration.
+ *
+ * This may be useful here it's too hard to implement a call-back
+ * (e.g., in java apps).
+ *
+ * @param[in] x If true, layout will be performed in x-dimension
+ * (default: true).
+ * @param[in] y If true, layout will be performed in y-dimension
+ * (default: true).
+ */
+ void runOnce(bool x=true, bool y=true);
+
+ /**
+ * @brief Specify a set of compound constraints to apply to the layout.
+ *
+ * @param[in] ccs The compound constraints.
+ */
+ void setConstraints(const cola::CompoundConstraints& ccs);
+
+ /**
+ * @brief Specifies whether non-overlap constraints should be
+ * automatically generated between all nodes, as well as any
+ * exemptions to this.
+ *
+ * The optional second parameter indicates groups of nodes that should be
+ * exempt from having non-overlap constraints generated between each other.
+ * For example, you might want to do this for nodes representing ports, or
+ * the child nodes in a particular cluster.
+ *
+ * @param[in] avoidOverlaps New boolean value for this option.
+ * @param[in] listOfNodeGroups A list of groups of node indexes which will
+ * not have non-overlap constraints generated
+ * between each other.
+ */
+ void setAvoidNodeOverlaps(bool avoidOverlaps,
+ ListOfNodeIndexes listOfNodeGroups =
+ ListOfNodeIndexes());
+
+ /**
+ * @brief Set an addon for doing topology preserving layout.
+ *
+ * It is expected that you would use the topology::ColaTopologyAddon()
+ * from libtopology rather than write your own. This is done so that
+ * libcola does not have to depend on libtopology.
+ *
+ * @param[in] topology Instance of a class implementing the
+ * TopologyAddonInterface.
+ * @sa topology::ColaTopologyAddon
+ */
+ void setTopology(TopologyAddonInterface *topology);
+ TopologyAddonInterface *getTopology(void);
+
+ void setDesiredPositions(DesiredPositions *desiredPositions);
+
+ /**
+ * @brief Specifies an optional hierarchy for clustering nodes.
+ *
+ * @param[in] hierarchy A pointer to a RootCluster object defining the
+ * the cluster hierarchy (optional).
+ */
+ void setClusterHierarchy(RootCluster *hierarchy)
+ {
+ clusterHierarchy = hierarchy;
+ }
+ /**
+ * @brief Register to receive information about unsatisfiable constraints.
+ *
+ * In the case of unsatisifiable constraints, the solver will drop
+ * unsatisfiable constraints of lowest priority. Information about these
+ * will be written to these lists after each iteration of constrained
+ * layout.
+ *
+ * param[out] unsatisfiableX A pointer to a UnsatisfiableConstraintInfos
+ * object that will be used to record
+ * unsatisfiable constraints in the x-dimension.
+ * param[out] unsatisfiableY A pointer to a UnsatisfiableConstraintInfos
+ * object that will be used to record
+ * unsatisfiable constraints in the y-dimension.
+ */
+ void setUnsatisfiableConstraintInfo(
+ UnsatisfiableConstraintInfos *unsatisfiableX,
+ UnsatisfiableConstraintInfos *unsatisfiableY)
+ {
+ unsatisfiable.resize(2);
+ unsatisfiable[0]=unsatisfiableX;
+ unsatisfiable[1]=unsatisfiableY;
+ }
+ /**
+ * @brief Finds a feasible starting position for nodes that satisfies the
+ * given constraints.
+ *
+ * Starts with an initial position (x, y) for the nodes. This position
+ * is then iteratively updated with a greedy heuristic that tries adding
+ * additional constraints based on compound constraint priority to the
+ * satisfiable set, so as to satisfy as many of the placement constraints
+ * as possible. This includes automatically generated constraints for
+ * non-overlap and cluster containment.
+ *
+ * @param[in] xBorder Optional border width to add to left and right
+ * sides of rectangles. Defaults to 1.
+ * @param[in] yBorder Optional border width to add to top and bottom
+ * sides of rectangles. Defaults to 1.
+ *
+ * @note This method doesn't do force-directed layout. All forces are
+ * ignored and it merely satisfies the constraints with minimal
+ * movement to nodes.
+ */
+ void makeFeasible(double xBorder=1, double yBorder=1);
+
+ /**
+ * @brief A convenience method that can be called from Java to free
+ * the memory of nodes (Rectangles), CompoundConstraints, etc.
+ *
+ * This assumes that the ConstrainedFDLayout instance takes ownership
+ * of all the objects passed to it.
+ *
+ * This is useful because in SWIG we have problems with Java wrapper
+ * classes going out of scope and causing objects like Rectanges to
+ * sometimes be freed when the layout instance still needs them. For
+ * this reason we prevent the Java wrappers from deleting the internal
+ * C++ instances, and let them be cleaned up later via this method.
+ */
+ void freeAssociatedObjects(void);
+
+ //! @brief Generates an SVG file containing debug output and code that
+ //! can be used to regenerate the instance.
+ //!
+ //! This method can be called before or after run() or makeFeasible()
+ //! have been called.
+ //!
+ //! @param[in] filename A string indicating the filename (without
+ //! extension) for the output file. Defaults to
+ //! "libcola-debug.svg" if no filename is given.
+ //!
+ void outputInstanceToSVG(std::string filename = std::string());
+
+ /**
+ * @brief Specifies whether neighbour stress should be used.
+ *
+ * Under neighbour stress, only the terms representing neighbouring
+ * nodes contribute to the stress function. This can help to distribute
+ * nodes more evenly, eliminating long-range forces.
+ *
+ * Default value is false.
+ *
+ * @param[in] useNeighbourStress New boolean value for this option.
+ */
+ void setUseNeighbourStress(bool useNeighbourStress);
+
+ /**
+ * @brief Retrieve a copy of the "D matrix" computed by the computePathLengths
+ * method, linearised as a vector.
+ *
+ * This is especially useful for projects in SWIG target languages that want to
+ * do their own computations with stress.
+ *
+ * D is the required euclidean distances between pairs of nodes
+ * based on the shortest paths between them (using
+ * m_idealEdgeLength*eLengths[edge] as the edge length, if eLengths array
+ * is provided otherwise just m_idealEdgeLength).
+ *
+ * @return vector representing the D matrix.
+ */
+ std::vector<double> readLinearD(void);
+
+ /**
+ * @brief Retrieve a copy of the "G matrix" computed by the computePathLengths
+ * method, linearised as a vector.
+ *
+ * * This is especially useful for projects in SWIG target languages that want to
+ * do their own computations with stress.
+ *
+ * G is a matrix of unsigned ints such that G[u][v]=
+ * 0 if there are no forces required between u and v
+ * (for example, if u and v are in unconnected components)
+ * 1 if attractive forces are required between u and v
+ * (i.e. if u and v are immediately connected by an edge and there is
+ * no topology route between u and v (for which an attractive force
+ * is computed elsewhere))
+ * 2 if no attractive force is required between u and v but there is
+ * a connected path between them.
+ *
+ * @return vector representing the G matrix.
+ */
+ std::vector<unsigned> readLinearG(void);
+
+ double computeStress() const;
+
+private:
+ unsigned n; // number of nodes
+ std::valarray<double> X, Y;
+ vpsc::Rectangles boundingBoxes;
+ double applyForcesAndConstraints(const vpsc::Dim dim,const double oldStress);
+ double computeStepSize(const SparseMatrix& H, const std::valarray<double>& g,
+ const std::valarray<double>& d) const;
+ void computeDescentVectorOnBothAxes(const bool xaxis, const bool yaxis,
+ double stress, std::valarray<double>& x0, std::valarray<double>& x1);
+ void moveTo(const vpsc::Dim dim, std::valarray<double>& target);
+ double applyDescentVector(
+ const std::valarray<double>& d,
+ const std::valarray<double>& oldCoords,
+ std::valarray<double> &coords,
+ const double oldStress,
+ double stepsize
+ /*,topology::TopologyConstraints *s=nullptr*/);
+ void computePathLengths(
+ const std::vector<Edge>& es, std::valarray<double> eLengths);
+ void generateNonOverlapAndClusterCompoundConstraints(
+ vpsc::Variables (&vs)[2]);
+ void handleResizes(const Resizes&);
+ void setPosition(std::valarray<double>& pos);
+ void moveBoundingBoxes();
+ bool noForces(double, double, unsigned) const;
+ void computeForces(const vpsc::Dim dim, SparseMap &H,
+ std::valarray<double> &g);
+ void recGenerateClusterVariablesAndConstraints(
+ vpsc::Variables (&vars)[2], unsigned int& priority,
+ cola::NonOverlapConstraints *noc, Cluster *cluster,
+ cola::CompoundConstraints& idleConstraints);
+ std::vector<double> offsetDir(double minD);
+
+ void computeNeighbours(std::vector<Edge> es);
+ std::vector<std::vector<unsigned> > neighbours;
+ std::vector<std::vector<double> > neighbourLengths;
+ TestConvergence *done;
+ bool using_default_done; // Whether we allocated a default TestConvergence object.
+ PreIteration* preIteration;
+ cola::CompoundConstraints ccs;
+ double** D;
+ unsigned short** G;
+ double minD;
+ PseudoRandom random;
+
+ TopologyAddonInterface *topologyAddon;
+ std::vector<UnsatisfiableConstraintInfos*> unsatisfiable;
+ bool rungekutta;
+ DesiredPositions *desiredPositions;
+ cola::CompoundConstraints extraConstraints;
+
+ RootCluster *clusterHierarchy;
+ double rectClusterBuffer;
+ double m_idealEdgeLength;
+ bool m_generateNonOverlapConstraints;
+ bool m_useNeighbourStress;
+ const std::valarray<double> m_edge_lengths;
+
+ NonOverlapConstraintExemptions *m_nonoverlap_exemptions;
+
+ friend class topology::ColaTopologyAddon;
+ friend class dialect::Graph;
+};
+
+struct ProjectionResult {
+ int errorLevel;
+ std::string unsatinfo;
+};
+
+/**
+ * @brief Attempt to do a projection onto a vector of cola CompoundConstraints.
+ * @param dim the dimension in which to perform the projection
+ * @param rs the rectangles representing the nodes
+ * @param ccs the constraints
+ * @param preventOverlaps boolean saying whether you want overlap prevention
+ * constraints to be automatically generated
+ * @param accept an integer indicating which types of infeasibilities you will accept.
+ * The default value of 0 means you accept no infeasibility.
+ * For other values, see the description of the "errorLevel" in the
+ * doctext for the solve function below.
+ * @param debugLevel see solve function below
+ * @note Rectangle positions are updated if and only if the error level is less
+ * than or equal to the accept level.
+ * @return a ProjectionResult indicating whether the projection was feasible or not.
+ * @sa solve
+ */
+ProjectionResult projectOntoCCs(vpsc::Dim dim, vpsc::Rectangles &rs, cola::CompoundConstraints ccs,
+ bool preventOverlaps, int accept=0, unsigned debugLevel=0);
+
+/**
+ * @brief Constructs a solver and attempts to solve the passed constraints on the passed vars.
+ * @param debugLevel: controls how much information comes back when the projection fails. See below.
+ * @return a ProjectionResult, containing:
+ * errorLevel:
+ * 0: all constraints were satisfiable.
+ * 1: some constraints were unsatisfiable, but they were all nonoverlap constraints.
+ * 2: some constraints were unsatisfiable which were /not/ nonoverlap constraints.
+ * unsatinfo:
+ * The amount of information reported depends on the debugLevel:
+ * 0: nothing reported (empty string)
+ * 1: description of the unsatisfied constraints
+ * 2: the info from level 1, plus a description of all "related" constraints (those sharing a variable).
+ * This is useful for understanding the conflicts.
+ */
+ProjectionResult solve(vpsc::Variables &vs, vpsc::Constraints &cs, vpsc::Rectangles &rs,
+ unsigned debugLevel=0);
+
+
+ConstrainedMajorizationLayout* simpleCMLFactory(
+ vpsc::Rectangles& rs,
+ std::vector<Edge> const & es,
+ RootCluster* clusterHierarchy,
+ const double idealLength,
+ bool useNeighbourStress = false
+ );
+
+/*
+ * find shortest path lengths from node s to all other nodes.
+ * @param s starting node
+ * @param n total number of nodes
+ * @param d n vector of path lengths
+ * @param es edge pairs
+ * @param eLengths edge weights
+ */
+void dijkstra(const unsigned s, const unsigned n, double* d,
+ const std::vector<cola::Edge>& es,
+ const std::valarray<double> & eLengths);
+
+#if 0
+void removeClusterOverlapFast(RootCluster& clusterHierarchy, vpsc::Rectangles& rs, Locks& locks);
+#endif
+
+void setupVarsAndConstraints(unsigned n, const CompoundConstraints& ccs,
+ const vpsc::Dim dim, vpsc::Rectangles& boundingBoxes,
+ RootCluster *clusterHierarchy,
+ vpsc::Variables& vs, vpsc::Constraints& cs,
+ std::valarray<double> &coords);
+void setVariableDesiredPositions(vpsc::Variables& vs, vpsc::Constraints& cs,
+ const DesiredPositionsInDim& des, std::valarray<double>& coords);
+
+}
+#endif // COLA_H
diff --git a/src/3rdparty/adaptagrams/libcola/cola_log.h b/src/3rdparty/adaptagrams/libcola/cola_log.h
new file mode 100644
index 0000000..5909c93
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/cola_log.h
@@ -0,0 +1,204 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+*/
+
+/*
+Logging code from DJJ article: http://www.ddj.com/cpp/201804215.
+
+Title: Logging In C++
+Author: Petru Marginean
+Keywords: OCT07 C++
+Description: Unpublished source code accompanying the article by Petru Marginean, in which he presents a C++ logging framework that is typesafe, thread-safe, and portable.
+ */
+#ifndef __COLA_LOG_H__
+#define __COLA_LOG_H__
+
+#include <sstream>
+#include <string>
+#include <cstdio>
+#include <iomanip>
+
+namespace cola {
+inline std::string NowTime();
+
+enum TLogLevel {logERROR, logWARNING, logINFO, logDEBUG, logDEBUG1, logDEBUG2, logDEBUG3, logDEBUG4};
+
+template <typename T>
+class Log
+{
+public:
+ Log();
+ virtual ~Log();
+ std::ostringstream& Get(TLogLevel level = logINFO);
+public:
+ static TLogLevel& ReportingLevel();
+ static std::string ToString(TLogLevel level);
+ static TLogLevel FromString(const std::string& level);
+protected:
+ std::ostringstream os;
+private:
+ Log(const Log&);
+ Log& operator =(const Log&);
+};
+
+template <typename T>
+Log<T>::Log()
+{
+}
+
+template <typename T>
+std::ostringstream& Log<T>::Get(TLogLevel level)
+{
+ os << "- " << NowTime();
+ os << " " << ToString(level) << ": ";
+ os << std::string(level > logDEBUG ? level - logDEBUG : 0, '\t');
+ return os;
+}
+
+template <typename T>
+Log<T>::~Log()
+{
+ os << std::endl;
+ T::Output(os.str());
+}
+
+template <typename T>
+TLogLevel& Log<T>::ReportingLevel()
+{
+ static TLogLevel reportingLevel = cola::logDEBUG4;
+ return reportingLevel;
+}
+
+template <typename T>
+std::string Log<T>::ToString(TLogLevel level)
+{
+ static const char* const buffer[] = {"ERROR", "WARNING", "INFO", "DEBUG", "DEBUG1", "DEBUG2", "DEBUG3", "DEBUG4"};
+ return buffer[level];
+}
+
+template <typename T>
+TLogLevel Log<T>::FromString(const std::string& level)
+{
+ if (level == "DEBUG4")
+ return logDEBUG4;
+ if (level == "DEBUG3")
+ return logDEBUG3;
+ if (level == "DEBUG2")
+ return logDEBUG2;
+ if (level == "DEBUG1")
+ return logDEBUG1;
+ if (level == "DEBUG")
+ return logDEBUG;
+ if (level == "INFO")
+ return logINFO;
+ if (level == "WARNING")
+ return logWARNING;
+ if (level == "ERROR")
+ return logERROR;
+ Log<T>().Get(logWARNING) << "Unknown logging level '" << level << "'. Using INFO level as default.";
+ return logINFO;
+}
+
+class Output2FILE
+{
+public:
+ static FILE*& Stream();
+ static void Output(const std::string& msg);
+};
+
+inline FILE*& Output2FILE::Stream()
+{
+ static FILE* pStream = stderr;
+ return pStream;
+}
+
+inline void Output2FILE::Output(const std::string& msg)
+{
+ FILE* pStream = Stream();
+ if (!pStream)
+ return;
+ fprintf(pStream, "%s", msg.c_str());
+ fflush(pStream);
+}
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
+# if defined (BUILDING_FILELOG_DLL)
+# define FILELOG_DECLSPEC __declspec (dllexport)
+# elif defined (USING_FILELOG_DLL)
+# define FILELOG_DECLSPEC __declspec (dllimport)
+# else
+# define FILELOG_DECLSPEC
+# endif // BUILDING_DBSIMPLE_DLL
+#else
+# define FILELOG_DECLSPEC
+#endif // _WIN32
+
+class FILELOG_DECLSPEC FILELog : public Log<Output2FILE> {};
+//typedef Log<Output2FILE> FILELog;
+
+#ifndef FILELOG_MAX_LEVEL
+#define FILELOG_MAX_LEVEL cola::logDEBUG4
+#endif
+
+#define FILE_LOG(level) \
+ if (level > FILELOG_MAX_LEVEL) ;\
+ else if (level > cola::FILELog::ReportingLevel() || !cola::Output2FILE::Stream()) ; \
+ else cola::FILELog().Get(level)
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
+
+#include <windows.h>
+
+inline std::string NowTime()
+{
+ const int MAX_LEN = 200;
+ char buffer[MAX_LEN];
+ if (GetTimeFormatA(LOCALE_USER_DEFAULT, 0, 0,
+ "HH':'mm':'ss", buffer, MAX_LEN) == 0)
+ return "Error in NowTime()";
+
+ static DWORD first = GetTickCount();
+ std::stringstream result;
+ result << buffer << "." << std::setfill('0') << std::setw(3) << ((long)(GetTickCount() - first) % 1000);
+ return result.str();
+}
+
+#else
+
+#include <sys/time.h>
+
+inline std::string NowTime()
+{
+ char buffer[11];
+ time_t t;
+ time(&t);
+ tm r;
+ strftime(buffer, sizeof(buffer), "%X", localtime_r(&t, &r));
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ std::stringstream result;
+ result << buffer << "." << std::setfill('0') << std::setw(3) << ((long)tv.tv_usec / 1000);
+ return result.str();
+}
+
+#endif //WIN32
+
+} // namespace cola
+
+#endif //__COLA_LOG_H__
diff --git a/src/3rdparty/adaptagrams/libcola/colafd.cpp b/src/3rdparty/adaptagrams/libcola/colafd.cpp
new file mode 100644
index 0000000..8476f6b
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/colafd.cpp
@@ -0,0 +1,1681 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2015 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+ * Michael Wybrow
+ *
+*/
+
+// cmath needs ::strcpy_s under MinGW so include cstring.
+#include <cstring>
+
+#include <vector>
+#include <cmath>
+#include <limits>
+
+#include "libvpsc/solve_VPSC.h"
+#include "libvpsc/variable.h"
+#include "libvpsc/constraint.h"
+#include "libvpsc/rectangle.h"
+#include "libvpsc/exceptions.h"
+
+#include "libcola/commondefs.h"
+#include "libcola/cola.h"
+#include "libcola/shortest_paths.h"
+#include "libcola/straightener.h"
+#include "libcola/cc_clustercontainmentconstraints.h"
+#include "libcola/cc_nonoverlapconstraints.h"
+
+#ifdef MAKEFEASIBLE_DEBUG
+ #include "libcola/output_svg.h"
+#endif
+
+// Needs to come last since it will include windows.h on WIN32 and
+// may mess up C++ std library include on GCC 4.4
+#include "libcola/cola_log.h"
+
+using namespace std;
+using vpsc::Dim;
+using vpsc::XDIM;
+using vpsc::YDIM;
+using vpsc::IncSolver;
+using vpsc::Variable;
+using vpsc::Variables;
+using vpsc::Constraint;
+using vpsc::Constraints;
+using vpsc::Rectangle;
+using vpsc::Rectangles;
+
+namespace cola {
+
+template <class T>
+void delete_vector(vector<T*> &v) {
+ for_each(v.begin(),v.end(),delete_object());
+ v.clear();
+}
+Resizes PreIteration::__resizesNotUsed;
+Locks PreIteration::__locksNotUsed;
+inline double dotProd(valarray<double> x, valarray<double> y) {
+ COLA_ASSERT(x.size()==y.size());
+ double dp=0;
+ for(unsigned i=0;i<x.size();i++) {
+ dp+=x[i]*y[i];
+ }
+ return dp;
+}
+template <typename T>
+void dumpSquareMatrix(unsigned n, T** L) {
+ printf("Matrix %dX%d\n{",n,n);
+ for(unsigned i=0;i<n;i++) {
+ printf("{");
+ for(unsigned j=0;j<n;j++) {
+ std::cout<<L[i][j];
+ char c=j==n-1?'}':',';
+ printf("%c",c);
+ }
+ char c=i==n-1?'}':',';
+ printf("%c\n",c);
+ }
+}
+
+ConstrainedFDLayout::ConstrainedFDLayout(const vpsc::Rectangles& rs,
+ const std::vector< Edge >& es, const double idealLength,
+ const EdgeLengths& eLengths,
+ TestConvergence *doneTest, PreIteration* preIteration)
+ : n(rs.size()),
+ X(valarray<double>(n)),
+ Y(valarray<double>(n)),
+ done(doneTest),
+ using_default_done(false),
+ preIteration(preIteration),
+ topologyAddon(new TopologyAddonInterface()),
+ rungekutta(true),
+ desiredPositions(nullptr),
+ clusterHierarchy(nullptr),
+ rectClusterBuffer(0),
+ m_idealEdgeLength(idealLength),
+ m_generateNonOverlapConstraints(false),
+ m_useNeighbourStress(false),
+ m_edge_lengths(eLengths.data(), eLengths.size()),
+ m_nonoverlap_exemptions(new NonOverlapConstraintExemptions())
+{
+ minD = DBL_MAX;
+
+ if (done == nullptr)
+ {
+ done = new TestConvergence();
+ using_default_done = true;
+ }
+
+ computeNeighbours(es);
+
+ //FILELog::ReportingLevel() = logDEBUG1;
+ FILELog::ReportingLevel() = logERROR;
+ boundingBoxes = rs;
+ done->reset();
+ unsigned i=0;
+ for(vpsc::Rectangles::const_iterator ri=rs.begin();ri!=rs.end();++ri,++i) {
+ X[i]=(*ri)->getCentreX();
+ Y[i]=(*ri)->getCentreY();
+ FILE_LOG(logDEBUG) << *ri;
+ }
+ D=new double*[n];
+ G=new unsigned short*[n];
+ for(unsigned i=0;i<n;i++) {
+ D[i]=new double[n];
+ G[i]=new unsigned short[n];
+ }
+
+ computePathLengths(es,m_edge_lengths);
+}
+
+std::vector<double> ConstrainedFDLayout::readLinearD(void)
+{
+ std::vector<double> d;
+ d.resize(n*n);
+ for (unsigned i = 0; i < n; ++i) {
+ for (unsigned j = 0; j < n; ++j) {
+ d[n*i + j] = D[i][j];
+ }
+ }
+ return d;
+}
+
+std::vector<unsigned> ConstrainedFDLayout::readLinearG(void)
+{
+ std::vector<unsigned> g;
+ g.resize(n*n);
+ for (unsigned i = 0; i < n; ++i) {
+ for (unsigned j = 0; j < n; ++j) {
+ g[n*i + j] = G[i][j];
+ }
+ }
+ return g;
+}
+
+void ConstrainedFDLayout::computeNeighbours(vector<Edge> es) {
+ for (unsigned i = 0; i < n; ++i) {
+ neighbours.push_back(vector<unsigned>(n));
+ }
+ for (vector<Edge>::iterator it = es.begin(); it!=es.end(); ++it) {
+ Edge e = *it;
+ unsigned s = e.first, t = e.second;
+ neighbours[s][t] = 1;
+ neighbours[t][s] = 1;
+ }
+}
+
+void dijkstra(const unsigned s, const unsigned n, double* d,
+ const vector<Edge>& es, const std::valarray<double> & eLengths)
+{
+ shortest_paths::dijkstra(s,n,d,es,eLengths);
+}
+
+void ConstrainedFDLayout::setConstraints(const cola::CompoundConstraints& ccs)
+{
+ this->ccs = ccs;
+}
+
+void ConstrainedFDLayout::setAvoidNodeOverlaps(bool avoidOverlaps,
+ std::vector<std::vector<unsigned> > listOfNodeGroups)
+{
+ m_generateNonOverlapConstraints = avoidOverlaps;
+ m_nonoverlap_exemptions->addExemptGroupOfNodes(listOfNodeGroups);
+}
+
+void ConstrainedFDLayout::setUseNeighbourStress(bool useNeighbourStress)
+{
+ m_useNeighbourStress = useNeighbourStress;
+}
+
+void ConstrainedFDLayout::setDesiredPositions(DesiredPositions *desiredPositions)
+{
+ this->desiredPositions = desiredPositions;
+}
+
+
+/*
+ * Sets up the D and G matrices. D is the required euclidean distances
+ * between pairs of nodes based on the shortest paths between them (using
+ * m_idealEdgeLength*eLengths[edge] as the edge length, if eLengths array
+ * is provided otherwise just m_idealEdgeLength). G is a matrix of
+ * unsigned ints such that G[u][v]=
+ * 0 if there are no forces required between u and v
+ * (for example, if u and v are in unconnected components)
+ * 1 if attractive forces are required between u and v
+ * (i.e. if u and v are immediately connected by an edge and there is
+ * no topology route between u and v (for which an attractive force
+ * is computed elsewhere))
+ * 2 if no attractive force is required between u and v but there is
+ * a connected path between them.
+ */
+void ConstrainedFDLayout::computePathLengths(
+ const vector<Edge>& es, std::valarray<double> eLengths)
+{
+ // Correct zero or negative entries in eLengths array.
+ for (size_t i = 0; i < eLengths.size(); ++i)
+ {
+ if (eLengths[i] <= 0)
+ {
+ fprintf(stderr, "Warning: ignoring non-positive length at index %d "
+ "in ideal edge length array.\n", (int) i);
+ eLengths[i] = 1;
+ }
+ }
+
+ shortest_paths::johnsons(n,D,es,eLengths);
+ //dumpSquareMatrix<double>(n,D);
+ for(unsigned i=0;i<n;i++) {
+ for(unsigned j=0;j<n;j++) {
+ if(i==j) continue;
+ double& d=D[i][j];
+ unsigned short& p=G[i][j];
+ p=2;
+ if(d==DBL_MAX) {
+ // i and j are in disconnected subgraphs
+ p=0;
+ } else {
+ d*=m_idealEdgeLength;
+ }
+
+ if ((d > 0) && (d < minD)) {
+ minD = d;
+ }
+ }
+ }
+ if (minD == DBL_MAX) minD = 1;
+
+ for(vector<Edge>::const_iterator e=es.begin();e!=es.end();++e) {
+ unsigned u=e->first, v=e->second;
+ G[u][v]=G[v][u]=1;
+ }
+ topologyAddon->computePathLengths(G);
+ //dumpSquareMatrix<short>(n,G);
+}
+
+typedef valarray<double> Position;
+void getPosition(Position& X, Position& Y, Position& pos) {
+ unsigned n=X.size();
+ COLA_ASSERT(Y.size()==n);
+ COLA_ASSERT(pos.size()==2*n);
+ for(unsigned i=0;i<n;++i) {
+ pos[i]=X[i];
+ pos[i+n]=Y[i];
+ }
+}
+/*
+ * moves all rectangles to the desired position while respecting
+ * constraints.
+ * @param pos target positions of both axes
+ */
+void ConstrainedFDLayout::setPosition(Position& pos) {
+ COLA_ASSERT(Y.size()==X.size());
+ COLA_ASSERT(pos.size()==2*X.size());
+ moveTo(vpsc::HORIZONTAL,pos);
+ moveTo(vpsc::VERTICAL,pos);
+}
+/*
+ * Layout is performed by minimizing the P-stress goal function iteratively.
+ * At each iteration taking a step in the steepest-descent direction.
+ * x0 is the current position, x1 is the x0 - descentvector.
+ */
+void ConstrainedFDLayout::computeDescentVectorOnBothAxes(
+ const bool xAxis, const bool yAxis,
+ double stress, Position& x0, Position& x1) {
+ setPosition(x0);
+ if(xAxis) {
+ applyForcesAndConstraints(vpsc::HORIZONTAL,stress);
+ }
+ if(yAxis) {
+ applyForcesAndConstraints(vpsc::VERTICAL,stress);
+ }
+ getPosition(X,Y,x1);
+}
+
+/*
+ * run() implements the main layout loop, taking descent steps until
+ * stress is no-longer significantly reduced.
+ * done is a callback used to check stress but also to report updated
+ * positions.
+ */
+void ConstrainedFDLayout::run(const bool xAxis, const bool yAxis)
+{
+ // This generates constraints for non-overlap inside and outside
+ // of clusters. To assign correct variable indexes it requires
+ // that vs[] contains elements equal to the number of rectangles.
+ vpsc::Variables vs[2];
+ vs[0].resize(n);
+ vs[1].resize(n);
+ generateNonOverlapAndClusterCompoundConstraints(vs);
+
+ FILE_LOG(logDEBUG) << "ConstrainedFDLayout::run...";
+ double stress=DBL_MAX;
+ do {
+ if(preIteration) {
+ if(!(*preIteration)()) {
+ break;
+ }
+ //printf("preIteration->changed=%d\n",preIteration->changed);
+ if(preIteration->changed) {
+ stress=DBL_MAX;
+ }
+ if(preIteration->resizes.size()>0) {
+ FILE_LOG(logDEBUG) << " Resize event!";
+ handleResizes(preIteration->resizes);
+ }
+ }
+ unsigned N=2*n;
+ Position x0(N),x1(N);
+ getPosition(X,Y,x0);
+ if(rungekutta) {
+ Position a(N),b(N),c(N),d(N),ia(N),ib(N);
+ computeDescentVectorOnBothAxes(xAxis,yAxis,stress,x0,a);
+ ia=x0+(a-x0)/2.0;
+ computeDescentVectorOnBothAxes(xAxis,yAxis,stress,ia,b);
+ ib=x0+(b-x0)/2.0;
+ computeDescentVectorOnBothAxes(xAxis,yAxis,stress,ib,c);
+ computeDescentVectorOnBothAxes(xAxis,yAxis,stress,c,d);
+ x1=a+2.0*b+2.0*c+d;
+ x1/=6.0;
+ } else {
+ computeDescentVectorOnBothAxes(xAxis,yAxis,stress,x0,x1);
+ }
+ setPosition(x1);
+ stress=computeStress();
+ FILE_LOG(logDEBUG) << "stress="<<stress;
+ } while(!(*done)(stress,X,Y));
+ for(unsigned i=0;i<n;i++) {
+ vpsc::Rectangle *r=boundingBoxes[i];
+ FILE_LOG(logDEBUG) << *r;
+ }
+ FILE_LOG(logDEBUG) << "ConstrainedFDLayout::run done.";
+
+ // Clear extra constraints.
+ for_each(extraConstraints.begin(), extraConstraints.end(), delete_object());
+ extraConstraints.clear();
+
+ // Free extra variables used for cluster containment.
+ for (size_t dim = 0; dim < 2; ++dim)
+ {
+ for (size_t i = n; i < vs[dim].size(); ++i)
+ {
+ delete vs[dim][i];
+ }
+ }
+}
+
+/*
+ * Same as run, but only applies one iteration. This may be useful
+ * where it's too hard to implement a call-back (e.g. in java apps)
+ */
+void ConstrainedFDLayout::runOnce(const bool xAxis, const bool yAxis) {
+ if(n==0) return;
+ double stress=DBL_MAX;
+ unsigned N=2*n;
+ Position x0(N),x1(N);
+ getPosition(X,Y,x0);
+ if(rungekutta) {
+ Position a(N),b(N),c(N),d(N),ia(N),ib(N);
+ computeDescentVectorOnBothAxes(xAxis,yAxis,stress,x0,a);
+ ia=x0+(a-x0)/2.0;
+ computeDescentVectorOnBothAxes(xAxis,yAxis,stress,ia,b);
+ ib=x0+(b-x0)/2.0;
+ computeDescentVectorOnBothAxes(xAxis,yAxis,stress,ib,c);
+ computeDescentVectorOnBothAxes(xAxis,yAxis,stress,c,d);
+ x1=a+2.0*b+2.0*c+d;
+ x1/=6.0;
+ } else {
+ computeDescentVectorOnBothAxes(xAxis,yAxis,stress,x0,x1);
+ }
+}
+
+
+// Used for sorting the CompoundConstraints from lowest priority to highest.
+static bool cmpCompoundConstraintPriority(const cola::CompoundConstraint *lhs,
+ const cola::CompoundConstraint *rhs)
+{
+ return lhs->priority() < rhs->priority();
+}
+
+
+void ConstrainedFDLayout::recGenerateClusterVariablesAndConstraints(
+ vpsc::Variables (&vars)[2], unsigned int& priority,
+ cola::NonOverlapConstraints *noc, Cluster *cluster,
+ cola::CompoundConstraints& idleConstraints)
+{
+ for (std::vector<Cluster*>::iterator curr = cluster->clusters.begin();
+ curr != cluster->clusters.end(); ++curr)
+ {
+ // For each of the child clusters, recursively call this function.
+ recGenerateClusterVariablesAndConstraints(vars, priority,
+ noc, *curr, idleConstraints);
+ }
+
+ if ( (noc == nullptr) && (dynamic_cast<RootCluster *> (cluster) == nullptr) )
+ {
+ double freeWeight = 0.00000000001;
+ // Then create left and right variables for the boundary of this
+ // cluster.
+ vpsc::Variable *variable = nullptr;
+ cluster->clusterVarId = vars[XDIM].size();
+ COLA_ASSERT(vars[XDIM].size() == vars[YDIM].size());
+ // Left:
+ variable = new vpsc::Variable(vars[XDIM].size(),
+ cluster->bounds.getMinX(), freeWeight);
+ vars[XDIM].push_back(variable);
+ // Right:
+ variable = new vpsc::Variable(vars[XDIM].size(),
+ cluster->bounds.getMaxX(), freeWeight);
+ vars[XDIM].push_back(variable);
+ // Bottom::
+ variable = new vpsc::Variable(vars[YDIM].size(),
+ cluster->bounds.getMinY(), freeWeight);
+ vars[YDIM].push_back(variable);
+ // Top:
+ variable = new vpsc::Variable(vars[YDIM].size(),
+ cluster->bounds.getMaxY(), freeWeight);
+ vars[YDIM].push_back(variable);
+
+ RectangularCluster *rc = dynamic_cast<RectangularCluster *> (cluster);
+ if (rc)
+ {
+ rc->generateFixedRectangleConstraints(idleConstraints,
+ boundingBoxes, vars);
+ }
+
+ priority--;
+ cola::ClusterContainmentConstraints *ccc =
+ new cola::ClusterContainmentConstraints(cluster, priority,
+ boundingBoxes);
+ idleConstraints.push_back(ccc);
+ }
+
+ if (noc)
+ {
+ // Enforce non-overlap between all the shapes and clusters at this
+ // level.
+ //printf("Cluster #%d non-overlap constraints - nodes %d clusters %d\n",
+ // (int) cluster->clusterVarId, (int) cluster->nodes.size(),
+ // (int) cluster->clusters.size());
+ unsigned int group = cluster->clusterVarId;
+ // The set of clusters to put non-overlap constraints between is the
+ // child clusters of this cluster. We will also add any overlapping
+ // clusters (due to multiple inheritence) to this set.
+ std::set<Cluster *> expandedClusterSet(cluster->clusters.begin(),
+ cluster->clusters.end());
+ for (std::set<unsigned>::iterator curr = cluster->nodes.begin();
+ curr != cluster->nodes.end(); ++curr)
+ {
+ unsigned id = *curr;
+
+ if (cluster->m_overlap_replacement_map.count(id) > 0)
+ {
+ // This shape is child of another cluster also, so replace
+ // this node with the other cluster for the purpose of
+ // non-overlap with other children of the current cluster.
+ expandedClusterSet.insert(
+ cluster->m_overlap_replacement_map[id]);
+ }
+ // Normal case: Add shape for generation of non-overlap
+ // constraints.
+ noc->addShape(id, boundingBoxes[id]->width() / 2,
+ boundingBoxes[id]->height() / 2, group);
+ }
+ for (std::set<Cluster*>::iterator curr = expandedClusterSet.begin();
+ curr != expandedClusterSet.end(); ++curr)
+ {
+ Cluster *cluster = *curr;
+ RectangularCluster *rectCluster =
+ dynamic_cast<RectangularCluster *> (cluster);
+ if (rectCluster && rectCluster->clusterIsFromFixedRectangle())
+ {
+ // Treat it like a shape for non-overlap.
+ unsigned id = rectCluster->rectangleIndex();
+ noc->addShape(id, boundingBoxes[id]->width() / 2,
+ boundingBoxes[id]->height() / 2, group);
+ }
+ else
+ {
+ // Normal cluster.
+ noc->addCluster(cluster, group);
+ }
+ }
+
+ // For the set of shapes that have been replaced due to multiple
+ // inheritance, still generate overlap constraints between them.
+ // (The group uses the ID of the right side variable of the cluster
+ // so it is not the same group as the cluster itself.)
+ for (std::set<unsigned>::iterator curr =
+ cluster->m_nodes_replaced_with_clusters.begin();
+ curr != cluster->m_nodes_replaced_with_clusters.end(); ++curr)
+ {
+ unsigned id = *curr;
+ noc->addShape(id, boundingBoxes[id]->width() / 2,
+ boundingBoxes[id]->height() / 2, group + 1);
+ }
+
+ }
+}
+
+void ConstrainedFDLayout::generateNonOverlapAndClusterCompoundConstraints(
+ vpsc::Variables (&vs)[2])
+{
+ if (clusterHierarchy && !clusterHierarchy->flat())
+ {
+ // Add remaining nodes that aren't contained within any clusters
+ // as children of the root cluster.
+ std::vector<unsigned> nodesInClusterCounts(boundingBoxes.size(), 0);
+ clusterHierarchy->countContainedNodes(nodesInClusterCounts);
+
+ for (unsigned int i = 0; i < nodesInClusterCounts.size(); ++i)
+ {
+ unsigned count = nodesInClusterCounts[i];
+ if (!clusterHierarchy->allowsMultipleParents() &&
+ count > 1)
+ {
+ fprintf(stderr, "Warning: node %u is contained in %d "
+ "clusters.\n", i, count);
+ }
+
+ if (count == 0)
+ {
+ // Not present in hierarchy, so add to root cluster.
+ clusterHierarchy->nodes.insert(i);
+ }
+ }
+
+ // Add non-overlap and containment constraints for all clusters
+ // and nodes.
+ unsigned int priority = PRIORITY_NONOVERLAP;
+ clusterHierarchy->computeBoundingRect(boundingBoxes);
+
+ // Generate the containment constraints
+ recGenerateClusterVariablesAndConstraints(vs, priority,
+ nullptr, clusterHierarchy, extraConstraints);
+
+ // Compute overlapping clusters.
+ clusterHierarchy->calculateClusterPathsToEachNode(boundingBoxes.size());
+
+ // Generate non-overlap constraints between all clusters and
+ // all contained nodes.
+ if (m_generateNonOverlapConstraints)
+ {
+ priority--;
+ cola::NonOverlapConstraints *noc =
+ new cola::NonOverlapConstraints(m_nonoverlap_exemptions,
+ priority);
+ noc->setClusterClusterExemptions(
+ clusterHierarchy->m_cluster_cluster_overlap_exceptions);
+ recGenerateClusterVariablesAndConstraints(vs, priority,
+ noc, clusterHierarchy, extraConstraints);
+ extraConstraints.push_back(noc);
+ }
+ }
+ else if (m_generateNonOverlapConstraints)
+ {
+ // Add standard non-overlap constraints between each pair of
+ // nodes.
+ cola::NonOverlapConstraints *noc =
+ new cola::NonOverlapConstraints(m_nonoverlap_exemptions);
+ for (unsigned int i = 0; i < boundingBoxes.size(); ++i)
+ {
+ noc->addShape(i, boundingBoxes[i]->width() / 2,
+ boundingBoxes[i]->height() / 2);
+ }
+ extraConstraints.push_back(noc);
+ }
+}
+
+void ConstrainedFDLayout::makeFeasible(double xBorder, double yBorder)
+{
+ vpsc::Variables vs[2];
+ vpsc::Constraints valid[2];
+
+ vpsc::Rectangle::setXBorder(xBorder);
+ vpsc::Rectangle::setYBorder(yBorder);
+
+ // Populate all the variables for shapes.
+ for (unsigned int dim = 0; dim < 2; ++dim)
+ {
+ vs[dim] = vpsc::Variables(boundingBoxes.size());
+ for (unsigned int i = 0; i < vs[dim].size(); ++i)
+ {
+ double pos = (dim == 0) ?
+ boundingBoxes[i]->getCentreX() :
+ boundingBoxes[i]->getCentreY();
+ vs[dim][i] = new vpsc::Variable(i, pos, 1);
+ }
+ }
+
+ vector<double> priorPos(boundingBoxes.size());
+
+ generateNonOverlapAndClusterCompoundConstraints(vs);
+
+ // Make a copy of the compound constraints and sort them by priority.
+ cola::CompoundConstraints idleConstraints = ccs;
+ // Append extraConstraints to idleConstraints.
+ idleConstraints.insert(idleConstraints.end(),
+ extraConstraints.begin(), extraConstraints.end());
+
+ std::sort(idleConstraints.begin(), idleConstraints.end(),
+ cmpCompoundConstraintPriority);
+
+ // Initialise extra variables for compound constraints.
+ for (unsigned int dim = 0; dim < 2; ++dim)
+ {
+ generateVariables(idleConstraints, (vpsc::Dim) dim, vs[dim]);
+ }
+
+#ifdef MAKEFEASIBLE_DEBUG
+ int iteration = 0;
+ vector<string> labels(boundingBoxes.size());
+ for(unsigned i=0;i<boundingBoxes.size();++i)
+ {
+ stringstream ss;
+ ss << i;
+ labels[i]=ss.str();
+ }
+#endif
+
+ // We can keep adding new constraints to the existing VPSC instances so
+ // long as everything is satisfiable. Only when it's not do we discard
+ // the existing VPSC instance for that dimension and create a new one.
+ vpsc::IncSolver *solver[2] = { nullptr };
+
+ // Main makeFeasible loop.
+ while (!idleConstraints.empty())
+ {
+ // idleConstraints is sorted lowest to highest priority, so the
+ // highest priority constraint will be at the back of the vector.
+ cola::CompoundConstraint *cc = idleConstraints.back();
+ idleConstraints.pop_back();
+
+#ifdef MAKEFEASIBLE_DEBUG
+ {
+ // Debugging SVG time slice output.
+ std::vector<cola::Edge> es;
+ for (unsigned int i = 0; i < boundingBoxes.size(); ++i)
+ {
+ boundingBoxes[i]->moveCentreX(vs[0][i]->finalPosition);
+ boundingBoxes[i]->moveCentreY(vs[1][i]->finalPosition);
+ }
+ iteration++;
+ std::sstream filename;
+ filename << "out/file-" << std::setfill('0') << std::setw(5) << iteration << ".pdf";
+
+ OutputFile of(boundingBoxes,es,clusterHierarchy,filename.str().c_str(),true,false);
+ of.setLabels(labels);
+ of.generate();
+ }
+#endif
+
+ cc->markAllSubConstraintsAsInactive();
+ bool subConstraintSatisfiable = true;
+
+ if (cc->shouldCombineSubConstraints())
+ {
+ // We are processing a combined set of satisfiable constraints,
+ // such as for containment within cluster boundary variables, so
+ // we just add all the required constraints and solve in both
+ // the X and Y dimension once to set the cluster boundaries to
+ // meaningful values.
+ while (cc->subConstraintsRemaining())
+ {
+ cola::SubConstraintAlternatives alternatives =
+ cc->getCurrSubConstraintAlternatives(vs);
+ // There should be no alternatives, just guaranteed
+ // satisfiable constraints.
+ COLA_ASSERT(alternatives.size() == 1);
+ vpsc::Dim& dim = alternatives.front().dim;
+ vpsc::Constraint& constraint = alternatives.front().constraint;
+ vpsc::Constraint *newConstraint =
+ new vpsc::Constraint(constraint);
+ valid[dim].push_back(newConstraint);
+ if (solver[dim])
+ {
+ // If we have an existing valid solver instance, add the
+ // constraint to that.
+ solver[dim]->addConstraint(newConstraint);
+ }
+ cc->markCurrSubConstraintAsActive(subConstraintSatisfiable);
+ }
+ // Satisfy the constraints in each dimension.
+ for (size_t dim = 0; dim < 2; ++dim)
+ {
+ if (solver[dim] == nullptr)
+ {
+ // Create a new VPSC solver if necessary.
+ solver[dim] = new vpsc::IncSolver(vs[dim], valid[dim]);
+ }
+ solver[dim]->satisfy();
+ }
+ continue;
+ }
+
+ while (cc->subConstraintsRemaining())
+ {
+ cola::SubConstraintAlternatives alternatives =
+ cc->getCurrSubConstraintAlternatives(vs);
+ alternatives.sort();
+
+ if (alternatives.empty())
+ {
+ continue;
+ }
+
+ while (!alternatives.empty())
+ {
+ // Reset subConstraintSatisfiable for new solve.
+ subConstraintSatisfiable = true;
+
+ vpsc::Dim& dim = alternatives.front().dim;
+ vpsc::Constraint& constraint = alternatives.front().constraint;
+
+ // Store current values for variables.
+ for (unsigned int i = 0; i < priorPos.size(); ++i)
+ {
+ priorPos[i] = vs[dim][i]->finalPosition;
+ }
+
+ // Some solving...
+ try
+ {
+ // Add the constraint from this alternative to the
+ // valid constraint set.
+ vpsc::Constraint *newConstraint =
+ new vpsc::Constraint(constraint);
+ valid[dim].push_back(newConstraint);
+
+ //fprintf(stderr, ".%d %3d - ", dim, valid[dim].size());
+
+ // Try to satisfy this set of constraints..
+ if (solver[dim] == nullptr)
+ {
+ // Create a new VPSC solver if necessary.
+ solver[dim] = new vpsc::IncSolver(vs[dim], valid[dim]);
+ }
+ else
+ {
+ // Or just add the constraint to the existing solver.
+ solver[dim]->addConstraint(newConstraint);
+ }
+ solver[dim]->satisfy();
+ }
+ catch (char *str)
+ {
+ subConstraintSatisfiable = false;
+
+ std::cerr << "++++ IN ERROR BLOCK" << std::endl;
+ std::cerr << str << std::endl;
+ for (vpsc::Rectangles::iterator r = boundingBoxes.begin();
+ r != boundingBoxes.end(); ++r)
+ {
+ std::cerr << **r <<std::endl;
+ }
+ }
+ for (size_t i = 0; i < valid[dim].size(); ++i)
+ {
+ if (valid[dim][i]->unsatisfiable)
+ {
+ // It might have made one of the earlier added
+ // constraints unsatisfiable, so we mark that one
+ // as okay since we will be reverting the most
+ // recent one.
+ valid[dim][i]->unsatisfiable = false;
+
+ subConstraintSatisfiable = false;
+ }
+ }
+
+ if (!subConstraintSatisfiable)
+ {
+ // Since we had unsatisfiable constraints we must
+ // discard this solver instance.
+ delete solver[dim];
+ solver[dim] = nullptr;
+
+ // Restore previous values for variables.
+ for (unsigned int i = 0; i < priorPos.size(); ++i)
+ {
+ vs[dim][i]->finalPosition = priorPos[i];
+ }
+
+ // Delete the newly added (and unsatisfiable)
+ // constraint from the valid constraint set.
+ delete valid[dim].back();
+ valid[dim].pop_back();
+ }
+ else
+ {
+ // Satisfied, so don't need to consider other alternatives.
+ break;
+ }
+ // Move on to the next alternative.
+ alternatives.pop_front();
+ }
+#ifdef MAKEFEASIBLE_DEBUG
+ if (true || idleConstraints.size() == 0)
+ {
+ // Debugging SVG time slice output, but don't show this for
+ // constraints that promised satisfiable.
+ std::vector<cola::Edge> es;
+ for (unsigned int i = 0; i < boundingBoxes.size(); ++i)
+ {
+ boundingBoxes[i]->moveCentreX(vs[0][i]->finalPosition);
+ boundingBoxes[i]->moveCentreY(vs[1][i]->finalPosition);
+ }
+ iteration++;
+ std::sstream filename;
+ filename << "out/file-" << std::setfill('0') << std::setw(5) << iteration << ".pdf";
+
+ OutputFile of(boundingBoxes,es,clusterHierarchy,filename.str().c_str(),
+ true,false);
+ of.setLabels(labels);
+ of.generate();
+ }
+#endif
+ cc->markCurrSubConstraintAsActive(subConstraintSatisfiable);
+ }
+ }
+
+ // Delete the persistent VPSC solver instances.
+ for (size_t dim = 0; dim < 2; ++dim)
+ {
+ if (solver[dim])
+ {
+ delete solver[dim];
+ solver[dim] = nullptr;
+ }
+ }
+
+ // Write positions from solver variables back to Rectangles.
+ for (unsigned int i = 0; i < boundingBoxes.size(); ++i)
+ {
+ boundingBoxes[i]->moveCentreX(vs[0][i]->finalPosition);
+ boundingBoxes[i]->moveCentreY(vs[1][i]->finalPosition);
+ }
+
+ vpsc::Rectangle::setXBorder(0);
+ vpsc::Rectangle::setYBorder(0);
+
+ // Cleanup.
+ for (unsigned int dim = 0; dim < 2; ++dim)
+ {
+ for_each(valid[dim].begin(), valid[dim].end(), delete_object());
+ for_each(vs[dim].begin(), vs[dim].end(), delete_object());
+ }
+
+ topologyAddon->makeFeasible(m_generateNonOverlapConstraints,
+ boundingBoxes, clusterHierarchy);
+
+ // Update the X and Y vectors with the new shape positions.
+ for (unsigned int i = 0; i < boundingBoxes.size(); ++i)
+ {
+ X[i] = boundingBoxes[i]->getCentreX();
+ Y[i] = boundingBoxes[i]->getCentreY();
+ }
+
+ // Clear extra constraints for cluster containment and non-overlap.
+ for_each(extraConstraints.begin(), extraConstraints.end(), delete_object());
+ extraConstraints.clear();
+}
+
+ConstrainedFDLayout::~ConstrainedFDLayout()
+{
+ if (using_default_done)
+ {
+ delete done;
+ }
+
+ for (unsigned i = 0; i < n; ++i)
+ {
+ delete [] G[i];
+ delete [] D[i];
+ }
+ delete [] G;
+ delete [] D;
+ delete topologyAddon;
+ delete m_nonoverlap_exemptions;
+}
+
+void ConstrainedFDLayout::freeAssociatedObjects(void)
+{
+ // Free Rectangles
+ for_each(boundingBoxes.begin(), boundingBoxes.end(), delete_object());
+ boundingBoxes.clear();
+
+ // Free compound constraints
+ std::list<CompoundConstraint *> freeList(ccs.begin(), ccs.end());
+ freeList.sort();
+ freeList.unique();
+ if (freeList.size() != ccs.size())
+ {
+ // The compound constraint list had repeated elements.
+ fprintf(stderr, "Warning: CompoundConstraints vector contained %d "
+ "duplicates.\n", (int) (ccs.size() - freeList.size()));
+ }
+ ccs.clear();
+ for_each(freeList.begin(), freeList.end(), delete_object());
+
+ if (clusterHierarchy)
+ {
+ delete clusterHierarchy;
+ clusterHierarchy = nullptr;
+ }
+
+ topologyAddon->freeAssociatedObjects();
+}
+
+void ConstrainedFDLayout::setTopology(TopologyAddonInterface *newTopology)
+{
+ COLA_ASSERT(topologyAddon);
+ delete topologyAddon;
+ topologyAddon = newTopology->clone();
+}
+
+TopologyAddonInterface *ConstrainedFDLayout::getTopology(void)
+{
+ return topologyAddon->clone();
+}
+
+
+void setupVarsAndConstraints(unsigned n, const CompoundConstraints& ccs,
+ const vpsc::Dim dim, vpsc::Rectangles& boundingBoxes,
+ RootCluster *clusterHierarchy,
+ vpsc::Variables& vs, vpsc::Constraints& cs,
+ valarray<double> &coords)
+{
+ vs.resize(n);
+ for (unsigned i = 0; i < n; ++i)
+ {
+ vs[i] = new vpsc::Variable(i, coords[i]);
+ }
+
+ if (clusterHierarchy && !clusterHierarchy->flat())
+ {
+ // Create variables for clusters
+ clusterHierarchy->computeBoundingRect(boundingBoxes);
+ clusterHierarchy->createVars(dim, boundingBoxes, vs);
+ }
+
+ for (CompoundConstraints::const_iterator c = ccs.begin();
+ c != ccs.end(); ++c)
+ {
+ (*c)->generateVariables(dim, vs);
+ }
+ for (CompoundConstraints::const_iterator c = ccs.begin();
+ c != ccs.end(); ++c)
+ {
+ (*c)->generateSeparationConstraints(dim, vs, cs, boundingBoxes);
+ }
+}
+
+
+static void setupExtraConstraints(const CompoundConstraints& ccs,
+ const vpsc::Dim dim, vpsc::Variables& vs, vpsc::Constraints& cs,
+ vpsc::Rectangles& boundingBoxes)
+{
+ for (CompoundConstraints::const_iterator c = ccs.begin();
+ c != ccs.end(); ++c)
+ {
+ (*c)->generateVariables(dim, vs);
+ }
+ for (CompoundConstraints::const_iterator c = ccs.begin();
+ c != ccs.end(); ++c)
+ {
+ (*c)->generateSeparationConstraints(dim, vs, cs, boundingBoxes);
+ }
+}
+
+void updateCompoundConstraints(const vpsc::Dim dim,
+ const CompoundConstraints& ccs)
+{
+ for (CompoundConstraints::const_iterator c = ccs.begin();
+ c != ccs.end(); ++c)
+ {
+ (*c)->updatePosition(dim);
+ }
+}
+void project(vpsc::Variables& vs, vpsc::Constraints& cs, valarray<double>& coords) {
+ unsigned n=coords.size();
+ vpsc::IncSolver s(vs,cs);
+ s.solve();
+ for(unsigned i=0;i<n;++i) {
+ coords[i]=vs[i]->finalPosition;
+ }
+}
+void setVariableDesiredPositions(vpsc::Variables& vs, vpsc::Constraints& cs,
+ const DesiredPositionsInDim& des, valarray<double>& coords)
+{
+ COLA_UNUSED(cs);
+
+ unsigned n=coords.size();
+ COLA_ASSERT(vs.size()>=n);
+ for(unsigned i=0;i<n;++i) {
+ vpsc::Variable* v=vs[i];
+ v->desiredPosition = coords[i];
+ v->weight=1;
+ }
+ for (DesiredPositionsInDim::const_iterator d=des.begin();
+ d!=des.end(); ++d) {
+ COLA_ASSERT(d->first<vs.size());
+ vpsc::Variable* v=vs[d->first];
+ v->desiredPosition = d->second;
+ v->weight=10000;
+ }
+}
+void checkUnsatisfiable(const vpsc::Constraints& cs,
+ UnsatisfiableConstraintInfos* unsatisfiable) {
+ for(vpsc::Constraints::const_iterator c=cs.begin();c!=cs.end();++c) {
+ if((*c)->unsatisfiable) {
+ UnsatisfiableConstraintInfo* i=new UnsatisfiableConstraintInfo(*c);
+ unsatisfiable->push_back(i);
+ }
+ }
+}
+
+void ConstrainedFDLayout::handleResizes(const Resizes& resizeList)
+{
+ topologyAddon->handleResizes(resizeList, n, X, Y, ccs, boundingBoxes,
+ clusterHierarchy);
+}
+
+/*
+ * move positions of nodes in specified axis while respecting constraints
+ * @param dim axis
+ * @param target array of desired positions (for both axes)
+ */
+void ConstrainedFDLayout::moveTo(const vpsc::Dim dim, Position& target) {
+ COLA_ASSERT(target.size()==2*n);
+ FILE_LOG(logDEBUG) << "ConstrainedFDLayout::moveTo(): dim="<<dim;
+ valarray<double> &coords = (dim==vpsc::HORIZONTAL)?X:Y;
+ vpsc::Variables vs;
+ vpsc::Constraints cs;
+ setupVarsAndConstraints(n, ccs, dim, boundingBoxes,
+ clusterHierarchy, vs, cs, coords);
+ DesiredPositionsInDim des;
+ if(preIteration) {
+ for(vector<Lock>::iterator l=preIteration->locks.begin();
+ l!=preIteration->locks.end();l++) {
+ des.push_back(make_pair(l->getID(),l->pos(dim)));
+ FILE_LOG(logDEBUG1)<<"desi: v["<<l->getID()<<"]=("<<l->pos(vpsc::HORIZONTAL)
+ <<","<<l->pos(vpsc::VERTICAL)<<")";
+ }
+ }
+ for(unsigned i=0, j=(dim==vpsc::HORIZONTAL?0:n);i<n;++i,++j) {
+ vpsc::Variable* v=vs[i];
+ v->desiredPosition = target[j];
+ }
+ setVariableDesiredPositions(vs,cs,des,coords);
+ if (topologyAddon->useTopologySolver())
+ {
+ topologyAddon->moveTo(dim, vs, cs, coords, clusterHierarchy);
+ } else {
+ // Add non-overlap constraints, but not variables again.
+ setupExtraConstraints(extraConstraints, dim, vs, cs, boundingBoxes);
+ // Projection.
+ project(vs,cs,coords);
+ moveBoundingBoxes();
+ }
+ updateCompoundConstraints(dim, ccs);
+ for_each(vs.begin(),vs.end(),delete_object());
+ for_each(cs.begin(),cs.end(),delete_object());
+}
+/*
+ * The following computes an unconstrained solution then uses Projection to
+ * make this solution feasible with respect to constraints by moving things as
+ * little as possible. If "meta-constraints" such as avoidOverlaps or edge
+ * straightening are required then dummy variables will be generated.
+ */
+double ConstrainedFDLayout::applyForcesAndConstraints(const vpsc::Dim dim, const double oldStress) {
+ FILE_LOG(logDEBUG) << "ConstrainedFDLayout::applyForcesAndConstraints(): dim="<<dim;
+ valarray<double> g(n);
+ valarray<double> &coords = (dim==vpsc::HORIZONTAL)?X:Y;
+ DesiredPositionsInDim des;
+ if(preIteration) {
+ for(vector<Lock>::iterator l=preIteration->locks.begin();
+ l!=preIteration->locks.end();l++) {
+ des.push_back(make_pair(l->getID(),l->pos(dim)));
+ FILE_LOG(logDEBUG1)<<"desi: v["<<l->getID()<<"]=("<<l->pos(vpsc::HORIZONTAL)
+ <<","<<l->pos(vpsc::VERTICAL)<<")";
+ }
+ }
+ vpsc::Variables vs;
+ vpsc::Constraints cs;
+ double stress;
+ setupVarsAndConstraints(n, ccs, dim, boundingBoxes,
+ clusterHierarchy, vs, cs, coords);
+
+ if (topologyAddon->useTopologySolver())
+ {
+ stress = topologyAddon->applyForcesAndConstraints(this, dim, g, vs, cs,
+ coords, des, oldStress);
+ } else {
+ // Add non-overlap constraints, but not variables again.
+ setupExtraConstraints(extraConstraints, dim, vs, cs, boundingBoxes);
+ // Projection.
+ SparseMap HMap(n);
+ computeForces(dim,HMap,g);
+ SparseMatrix H(HMap);
+ valarray<double> oldCoords=coords;
+ applyDescentVector(g,oldCoords,coords,oldStress,computeStepSize(H,g,g));
+ setVariableDesiredPositions(vs,cs,des,coords);
+ project(vs,cs,coords);
+ valarray<double> d(n);
+ d=oldCoords-coords;
+ double stepsize=computeStepSize(H,g,d);
+ stepsize=max(0.,min(stepsize,1.));
+ //printf(" dim=%d beta: ",dim);
+ stress = applyDescentVector(d,oldCoords,coords,oldStress,stepsize);
+ moveBoundingBoxes();
+ }
+ updateCompoundConstraints(dim, ccs);
+ if(unsatisfiable.size()==2) {
+ checkUnsatisfiable(cs,unsatisfiable[dim]);
+ }
+ FILE_LOG(logDEBUG) << "ConstrainedFDLayout::applyForcesAndConstraints... done, stress="<<stress;
+ if (clusterHierarchy)
+ {
+ clusterHierarchy->computeVarRect(vs, dim);
+ clusterHierarchy->computeBoundingRect(boundingBoxes);
+ }
+
+ for_each(vs.begin(),vs.end(),delete_object());
+ for_each(cs.begin(),cs.end(),delete_object());
+ return stress;
+}
+/*
+ * Attempts to set coords=oldCoords-stepsize*d. If this does not reduce
+ * the stress from oldStress then stepsize is halved. This is repeated
+ * until stepsize falls below a threshhold.
+ * @param d is a descent vector (a movement vector intended to reduce the
+ * stress)
+ * @param oldCoords are the previous position vector
+ * @param coords will hold the new position after applying d
+ * @param stepsize is a scalar multiple of the d to apply
+ */
+double ConstrainedFDLayout::applyDescentVector(
+ valarray<double> const &d,
+ valarray<double> const &oldCoords,
+ valarray<double> &coords,
+ const double oldStress,
+ double stepsize
+ )
+{
+ COLA_UNUSED(oldStress);
+
+ COLA_ASSERT(d.size()==oldCoords.size());
+ COLA_ASSERT(d.size()==coords.size());
+ while(fabs(stepsize)>0.00000000001) {
+ coords=oldCoords-stepsize*d;
+ double stress=computeStress();
+ //printf(" applyDV: oldstress=%f, stress=%f, stepsize=%f\n", oldStress,stress,stepsize);
+ //if(oldStress>=stress) {
+ return stress;
+ //}
+ coords=oldCoords;
+ stepsize*=0.5;
+ }
+ return computeStress();
+}
+
+
+// Computes X and Y offsets for nodes that are at the same position.
+std::vector<double> ConstrainedFDLayout::offsetDir(double minD)
+{
+ std::vector<double> u(2);
+ double l = 0;
+ for (size_t i = 0; i < 2; ++i)
+ {
+ double x = u[i] = random.getNextBetween(0.01, 1) - 0.5;
+ l += x * x;
+ }
+ l = sqrt(l);
+
+ for (size_t i = 0; i < 2; ++i)
+ {
+ u[i] *= (minD / l);
+ }
+
+ return u;
+}
+
+
+/*
+ * Computes:
+ * - the matrix of second derivatives (the Hessian) H, used in
+ * calculating stepsize; and
+ * - the vector g, the negative gradient (steepest-descent) direction.
+ */
+void ConstrainedFDLayout::computeForces(
+ const vpsc::Dim dim,
+ SparseMap &H,
+ valarray<double> &g) {
+ if(n==1) return;
+ g=0;
+ // for each node:
+ for(unsigned u=0;u<n;u++) {
+ // Stress model
+ double Huu=0;
+ for(unsigned v=0;v<n;v++) {
+ if(u==v) continue;
+ if (m_useNeighbourStress && neighbours[u][v]!=1) continue;
+
+ // The following loop randomly displaces nodes that are at identical positions
+ double rx=X[u]-X[v], ry=Y[u]-Y[v];
+ double sd2 = rx*rx+ry*ry;
+ unsigned maxDisplaces = n; // avoid infinite loop in the case of numerical issues, such as huge values
+
+ while (maxDisplaces--)
+ {
+ if ((sd2) > 1e-3)
+ {
+ break;
+ }
+
+ std::vector<double> rd = offsetDir(minD);
+ X[v] += rd[0];
+ Y[v] += rd[1];
+ rx=X[u]-X[v], ry=Y[u]-Y[v];
+ sd2 = rx*rx+ry*ry;
+ }
+
+ unsigned short p = G[u][v];
+ // no forces between disconnected parts of the graph
+ if(p==0) continue;
+ double l=sqrt(sd2);
+ double d=D[u][v];
+ if(l>d && p>1) continue; // attractive forces not required
+ double d2=d*d;
+ /* force apart zero distances */
+ if (l < 1e-30) {
+ l=0.1;
+ }
+ double dx=dim==vpsc::HORIZONTAL?rx:ry;
+ double dy=dim==vpsc::HORIZONTAL?ry:rx;
+ g[u]+=dx*(l-d)/(d2*l);
+ Huu-=H(u,v)=(d*dy*dy/(l*l*l)-1)/d2;
+ }
+ H(u,u)=Huu;
+ }
+ if(desiredPositions) {
+ for(DesiredPositions::const_iterator p=desiredPositions->begin();
+ p!=desiredPositions->end();++p) {
+ unsigned i = p->id;
+ double d=(dim==vpsc::HORIZONTAL)
+ ?p->x-X[i]:p->y-Y[i];
+ d*=p->weight;
+ g[i]-=d;
+ H(i,i)+=p->weight;
+ }
+ }
+}
+/*
+ * Returns the optimal step-size in the direction d, given gradient g and
+ * hessian H.
+ */
+double ConstrainedFDLayout::computeStepSize(
+ SparseMatrix const &H,
+ valarray<double> const &g,
+ valarray<double> const &d) const
+{
+ COLA_ASSERT(g.size()==d.size());
+ COLA_ASSERT(g.size()==H.rowSize());
+ // stepsize = g'd / (d' H d)
+ double numerator = dotProd(g,d);
+ valarray<double> Hd(d.size());
+ H.rightMultiply(d,Hd);
+ double denominator = dotProd(d,Hd);
+ //COLA_ASSERT(numerator>=0);
+ //COLA_ASSERT(denominator>=0);
+ if(denominator==0) return 0;
+ return numerator/denominator;
+}
+/*
+ * Just computes the cost (Stress) at the current X,Y position
+ * used to test termination.
+ * This method will call preIteration if one is set.
+ */
+double ConstrainedFDLayout::computeStress() const {
+ FILE_LOG(logDEBUG)<<"ConstrainedFDLayout::computeStress()";
+ double stress=0;
+ for(unsigned u=0;(u + 1)<n;u++) {
+ for(unsigned v=u+1;v<n;v++) {
+ if (m_useNeighbourStress && neighbours[u][v]!=1) continue;
+ unsigned short p=G[u][v];
+ // no forces between disconnected parts of the graph
+ if(p==0) continue;
+ double rx=X[u]-X[v], ry=Y[u]-Y[v];
+ double l=sqrt(rx*rx+ry*ry);
+ double d=D[u][v];
+ if(l>d && p>1) continue; // no attractive forces required
+ double d2=d*d;
+ double rl=d-l;
+ double s=rl*rl/d2;
+ stress+=s;
+ FILE_LOG(logDEBUG2)<<"s("<<u<<","<<v<<")="<<s;
+ }
+ }
+ if(preIteration) {
+ if ((*preIteration)()) {
+ for(vector<Lock>::iterator l=preIteration->locks.begin();
+ l!=preIteration->locks.end();l++) {
+ double dx=l->pos(vpsc::HORIZONTAL)-X[l->getID()], dy=l->pos(vpsc::VERTICAL)-Y[l->getID()];
+ double s=10000*(dx*dx+dy*dy);
+ stress+=s;
+ FILE_LOG(logDEBUG2)<<"d("<<l->getID()<<")="<<s;
+ }
+ }
+ }
+ stress += topologyAddon->computeStress();
+ if(desiredPositions) {
+ for(DesiredPositions::const_iterator p = desiredPositions->begin();
+ p!=desiredPositions->end();++p) {
+ double dx = X[p->id] - p->x, dy = Y[p->id] - p->y;
+ stress+=0.5*p->weight*(dx*dx+dy*dy);
+ }
+ }
+ return stress;
+}
+void ConstrainedFDLayout::moveBoundingBoxes() {
+ for(unsigned i=0;i<n;i++) {
+ boundingBoxes[i]->moveCentre(X[i],Y[i]);
+ }
+}
+
+static const double LIMIT = 100000000;
+
+static void reduceRange(double& val)
+{
+ val = std::min(val, LIMIT);
+ val = std::max(val, -LIMIT);
+}
+
+void ConstrainedFDLayout::outputInstanceToSVG(std::string instanceName)
+{
+ std::string filename;
+ if (!instanceName.empty())
+ {
+ filename = instanceName;
+ }
+ else
+ {
+ filename = "libcola-debug";
+ }
+ filename += ".svg";
+ FILE *fp = fopen(filename.c_str(), "w");
+
+ if (fp == nullptr)
+ {
+ return;
+ }
+
+
+ double minX = LIMIT;
+ double minY = LIMIT;
+ double maxX = -LIMIT;
+ double maxY = -LIMIT;
+
+ // Find the bounds of the diagram.
+ for (size_t i = 0; i < boundingBoxes.size(); ++i)
+ {
+ double rMinX = boundingBoxes[i]->getMinX();
+ double rMaxX = boundingBoxes[i]->getMaxX();
+ double rMinY = boundingBoxes[i]->getMinY();
+ double rMaxY = boundingBoxes[i]->getMaxY();
+
+ reduceRange(rMinX);
+ reduceRange(rMaxX);
+ reduceRange(rMinY);
+ reduceRange(rMaxY);
+
+ if (rMinX > -LIMIT)
+ {
+ minX = std::min(minX, rMinX);
+ }
+ if (rMaxX < LIMIT)
+ {
+ maxX = std::max(maxX,rMaxX);
+ }
+ if (rMinY > -LIMIT)
+ {
+ minY = std::min(minY, rMinY);
+ }
+ if (rMaxY < LIMIT)
+ {
+ maxY = std::max(maxY, rMaxY);
+ }
+ }
+
+ minX -= 50;
+ minY -= 50;
+ maxX += 50;
+ maxY += 50;
+
+ fprintf(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ fprintf(fp, "<svg xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\" xmlns=\"http://www.w3.org/2000/svg\" width=\"100%%\" height=\"100%%\" viewBox=\"%g %g %g %g\">\n", minX, minY, maxX - minX, maxY - minY);
+
+ // Output source code to generate this ConstrainedFDLayout instance.
+ fprintf(fp, "<!-- Source code to generate this instance:\n");
+ fprintf(fp, "#include <vector>\n");
+ fprintf(fp, "#include <utility>\n");
+ fprintf(fp, "#include \"libcola/cola.h\"\n");
+ fprintf(fp, "using namespace cola;\n");
+ fprintf(fp, "int main(void) {\n");
+ fprintf(fp, " CompoundConstraints ccs;\n");
+ fprintf(fp, " std::vector<Edge> es;\n");
+ fprintf(fp, " EdgeLengths eLengths;\n");
+ fprintf(fp, " double defaultEdgeLength=%g;\n", m_idealEdgeLength);
+ fprintf(fp, " std::vector<vpsc::Rectangle*> rs;\n");
+ fprintf(fp, " vpsc::Rectangle *rect = nullptr;\n\n");
+ for (size_t i = 0; i < boundingBoxes.size(); ++i)
+ {
+ fprintf(fp, " rect = new vpsc::Rectangle(%g, %g, %g, %g);\n",
+ boundingBoxes[i]->getMinX(), boundingBoxes[i]->getMaxX(),
+ boundingBoxes[i]->getMinY(), boundingBoxes[i]->getMaxY());
+ fprintf(fp, " rs.push_back(rect);\n\n");
+ }
+
+ for (size_t i = 0; i < n; ++i)
+ {
+ for (size_t j = i + 1; j < n; ++j)
+ {
+ if (G[i][j] == 1)
+ {
+ fprintf(fp, " es.push_back(std::make_pair(%lu, %lu));\n", i, j);
+ }
+ }
+ }
+ fprintf(fp, "\n");
+
+ if (m_edge_lengths.size() > 0)
+ {
+ fprintf(fp, " eLengths.resize(%d);\n", (int) m_edge_lengths.size());
+ for (size_t i = 0; i < m_edge_lengths.size(); ++i)
+ {
+ fprintf(fp, " eLengths[%d] = %g;\n", (int) i, m_edge_lengths[i]);
+ }
+ fprintf(fp, "\n");
+ }
+
+ for (cola::CompoundConstraints::iterator c = ccs.begin();
+ c != ccs.end(); ++c)
+ {
+ (*c)->printCreationCode(fp);
+ }
+
+ fprintf(fp, " ConstrainedFDLayout alg(rs, es, defaultEdgeLength, eLengths);\n");
+ if (clusterHierarchy)
+ {
+ clusterHierarchy->printCreationCode(fp);
+ fprintf(fp, " alg.setClusterHierarchy(cluster%llu);\n",
+ (unsigned long long) clusterHierarchy);
+ }
+ fprintf(fp, " alg.setConstraints(ccs);\n");
+ fprintf(fp, " alg.setAvoidNodeOverlaps(%s);\n",
+ (m_generateNonOverlapConstraints) ? "true" : "false");
+ fprintf(fp, " alg.makeFeasible();\n");
+ fprintf(fp, " alg.run();\n");
+ fprintf(fp, " alg.freeAssociatedObjects();\n");
+ fprintf(fp, " return 0;\n");
+ fprintf(fp, "};\n");
+ fprintf(fp, "-->\n");
+
+ if (clusterHierarchy)
+ {
+ clusterHierarchy->computeBoundingRect(boundingBoxes);
+ fprintf(fp, "<g inkscape:groupmode=\"layer\" "
+ "inkscape:label=\"Clusters\">\n");
+ clusterHierarchy->outputToSVG(fp);
+ fprintf(fp, "</g>\n");
+ }
+
+ fprintf(fp, "<g inkscape:groupmode=\"layer\" "
+ "inkscape:label=\"Rects\">\n");
+ for (size_t i = 0; i < boundingBoxes.size(); ++i)
+ {
+ double minX = boundingBoxes[i]->getMinX();
+ double maxX = boundingBoxes[i]->getMaxX();
+ double minY = boundingBoxes[i]->getMinY();
+ double maxY = boundingBoxes[i]->getMaxY();
+
+ fprintf(fp, "<rect id=\"rect-%u\" x=\"%g\" y=\"%g\" width=\"%g\" "
+ "height=\"%g\" style=\"stroke-width: 1px; stroke: black; "
+ "fill: blue; fill-opacity: 0.3;\" />\n",
+ (unsigned) i, minX, minY, maxX - minX, maxY - minY);
+ }
+ fprintf(fp, "</g>\n");
+
+ fprintf(fp, "<g inkscape:groupmode=\"layer\" "
+ "inkscape:label=\"Edges\">\n");
+ for (size_t i = 0; i < n; ++i)
+ {
+ for (size_t j = i + 1; j < n; ++j)
+ {
+ if (G[i][j] == 1)
+ {
+ fprintf(fp, "<path d=\"M %g %g L %g %g\" "
+ "style=\"stroke-width: 1px; stroke: black;\" />\n",
+ boundingBoxes[i]->getCentreX(),
+ boundingBoxes[i]->getCentreY(),
+ boundingBoxes[j]->getCentreX(),
+ boundingBoxes[j]->getCentreY());
+ }
+ }
+ }
+ fprintf(fp, "</g>\n");
+
+ fprintf(fp, "</svg>\n");
+ fclose(fp);
+}
+
+ProjectionResult projectOntoCCs(Dim dim, Rectangles &rs, CompoundConstraints ccs,
+ bool preventOverlaps, int accept, unsigned debugLevel)
+{
+ size_t n = rs.size();
+ // Set up nonoverlap constraints if desired.
+ NonOverlapConstraintExemptions *nocexemps = nullptr;
+ NonOverlapConstraints *noc = nullptr;
+ if (preventOverlaps) {
+ nocexemps = new NonOverlapConstraintExemptions();
+ noc = new NonOverlapConstraints(nocexemps);
+ for (size_t i = 0; i < n; ++i) {
+ noc->addShape(i, rs[i]->width()/2.0, rs[i]->height()/2.0);
+ }
+ ccs.push_back(noc);
+ }
+ // Set up vars and constraints.
+ Variables vs;
+ Constraints cs;
+ vs.resize(n);
+ for (size_t i = 0; i < n; ++i) {
+ vs[i] = new Variable(i, rs[i]->getCentreD(dim));
+ }
+ for (CompoundConstraints::iterator it=ccs.begin(); it!=ccs.end(); ++it) {
+ CompoundConstraint *cc = *it;
+ cc->generateVariables(dim, vs);
+ cc->generateSeparationConstraints(dim, vs, cs, rs);
+ }
+ // Solve, if possible.
+ ProjectionResult result = solve(vs, cs, rs, debugLevel);
+ // If good enough, accept positions.
+ if (result.errorLevel <= accept) {
+ for (size_t i = 0; i < n; ++i) {
+ rs[i]->moveCentreD(dim, vs[i]->finalPosition);
+ }
+ }
+ // Clean up
+ for (Variables::iterator it=vs.begin(); it!=vs.end(); ++it) delete *it;
+ for (Constraints::iterator it=cs.begin(); it!=cs.end(); ++it) delete *it;
+ delete noc;
+ delete nocexemps;
+ // Return
+ return result;
+}
+
+ProjectionResult solve(Variables &vs, Constraints &cs, Rectangles &rs, unsigned debugLevel)
+{
+ int result = 0;
+ IncSolver solv(vs,cs);
+ try {
+ solv.solve();
+ } catch (vpsc::UnsatisfiedConstraint uc) {
+ }
+ for (Constraints::iterator it=cs.begin(); it!=cs.end(); it++) {
+ Constraint *c = *it;
+ if (c->unsatisfiable) {
+ CompoundConstraint *cc = (CompoundConstraint*)(c->creator);
+ if (cc->toString() == "NonOverlapConstraints()") {
+ result = 1;
+ } else {
+ result = 2;
+ break;
+ }
+ }
+ }
+ std::string unsatinfo;
+ if (debugLevel>0) {
+ std::set<Variable*> varsInvolved;
+ unsatinfo += "===================================================\n";
+ unsatinfo += "UNSATISFIED CONSTRAINTS:\n";
+ char buf [1000];
+ for (Constraints::iterator it=cs.begin(); it!=cs.end(); it++) {
+ Constraint *c = *it;
+ if (c->unsatisfiable) {
+ varsInvolved.insert(c->left);
+ varsInvolved.insert(c->right);
+ sprintf(buf, "v_%d + %f", c->left->id, c->gap);
+ unsatinfo += buf;
+ unsatinfo += c->equality ? " == " : " <= ";
+ sprintf(buf, "v_%d\n", c->right->id);
+ unsatinfo += buf;
+ if ((unsigned) c->left->id < rs.size()) {
+ Rectangle *r = rs[c->left->id];
+ sprintf(buf, " v_%d rect: [%f, %f] x [%f, %f]\n", c->left->id,
+ r->getMinX(), r->getMaxX(), r->getMinY(), r->getMaxY());
+ unsatinfo += buf;
+ }
+ if ((unsigned) c->right->id < rs.size()) {
+ Rectangle *r = rs[c->right->id];
+ sprintf(buf, " v_%d rect: [%f, %f] x [%f, %f]\n", c->right->id,
+ r->getMinX(), r->getMaxX(), r->getMinY(), r->getMaxY());
+ unsatinfo += buf;
+ }
+ CompoundConstraint *cc = (CompoundConstraint*)(c->creator);
+ unsatinfo += " Creator: " + cc->toString() + "\n";
+ }
+ }
+ if (debugLevel>1) {
+ unsatinfo += "--------------------------------------------------\n";
+ unsatinfo += "RELATED CONSTRAINTS:\n";
+ std::set<Variable*>::iterator lit, rit, eit = varsInvolved.end();
+ for (Constraints::iterator it=cs.begin(); it!=cs.end(); it++) {
+ Constraint *c = *it;
+ lit = varsInvolved.find(c->left);
+ rit = varsInvolved.find(c->right);
+ if (lit != eit || rit != eit) {
+ sprintf(buf, "v_%d + %f", c->left->id, c->gap);
+ unsatinfo += buf;
+ unsatinfo += c->equality ? " == " : " <= ";
+ sprintf(buf, "v_%d\n", c->right->id);
+ unsatinfo += buf;
+ if ((unsigned) c->left->id < rs.size()) {
+ Rectangle *r = rs[c->left->id];
+ sprintf(buf, " v_%d rect: [%f, %f] x [%f, %f]\n", c->left->id,
+ r->getMinX(), r->getMaxX(), r->getMinY(), r->getMaxY());
+ unsatinfo += buf;
+ }
+ if ((unsigned) c->right->id < rs.size()) {
+ Rectangle *r = rs[c->right->id];
+ sprintf(buf, " v_%d rect: [%f, %f] x [%f, %f]\n", c->right->id,
+ r->getMinX(), r->getMaxX(), r->getMinY(), r->getMaxY());
+ unsatinfo += buf;
+ }
+ CompoundConstraint *cc = (CompoundConstraint*)(c->creator);
+ unsatinfo += " Creator: " + cc->toString() + "\n";
+ }
+ }
+ }
+ }
+ ProjectionResult pr;
+ pr.errorLevel = result;
+ pr.unsatinfo = unsatinfo;
+ return pr;
+}
+
+} // namespace cola
diff --git a/src/3rdparty/adaptagrams/libcola/commondefs.h b/src/3rdparty/adaptagrams/libcola/commondefs.h
new file mode 100644
index 0000000..6d56f62
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/commondefs.h
@@ -0,0 +1,98 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+*/
+
+#ifndef _COMMONDEFS_H
+#define _COMMONDEFS_H
+
+/* Notes to compilation using MSVC.
+
+ Compiler options:
+ /Zc:forScope
+*/
+#if defined(_MSC_VER)
+// Microsoft Visual C++ (MS VC) specific code goes here
+#include <float.h>
+#include <malloc.h> // Contains _alloca
+#endif
+
+#include "libvpsc/assertions.h"
+#include <valarray>
+
+namespace cola {
+
+/*
+ * resolve overlaps:
+ * None: not at all
+ * Horizontal: only horizontally
+ * Both: resolve in either Horizontal or Vertical direction
+ * depending on which leads to less displacement
+ */
+enum NonOverlapConstraintsMode { None, Horizontal, Both };
+
+class FixedList {
+public:
+ FixedList(const unsigned n) : array(std::valarray<bool>(n)),allFixed(false)
+ {
+ array=false;
+ }
+ void set(const unsigned i, const bool value=true) {
+ COLA_ASSERT(i<array.size());
+ array[i]=value;
+ }
+ bool check(const unsigned i) const {
+ if(allFixed||i>=array.size()) {
+ return false;
+ }
+ return array[i];
+ }
+ void unsetAll() {
+ array=false;
+ }
+ void fixAll(bool val) {
+ allFixed=val;
+ }
+private:
+ std::valarray<bool> array;
+ bool allFixed;
+};
+
+/*
+ * templated delete functor for use in for_each loop over vector
+ */
+struct delete_object
+{
+ template <typename T>
+ void operator()(T *ptr){ delete ptr;}
+};
+/*
+ * Sum over the results of calling operation for each member in the
+ * iterator. Handier than std::accumulate because we can use with
+ * mem_fun to pass in a getter method.
+ */
+template <class InputIterator, class T, class Operation >
+T sum_over(InputIterator beg, InputIterator end, T init, Operation op)
+{
+ for ( ; beg != end; ++beg)
+ init = init + op(*beg);
+ return init;
+}
+} // namespace cola
+
+#endif
diff --git a/src/3rdparty/adaptagrams/libcola/compound_constraints.cpp b/src/3rdparty/adaptagrams/libcola/compound_constraints.cpp
new file mode 100644
index 0000000..af9fa3e
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/compound_constraints.cpp
@@ -0,0 +1,1671 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+ * Michael Wybrow
+*/
+
+#include <algorithm>
+#include <climits>
+#include <sstream>
+
+#include <libvpsc/variable.h>
+#include <libvpsc/constraint.h>
+#include <libvpsc/assertions.h>
+
+#include "libcola/cola.h"
+#include "libcola/compound_constraints.h"
+#include "libcola/exceptions.h"
+
+using std::vector;
+using vpsc::XDIM;
+using vpsc::YDIM;
+
+namespace cola {
+
+void SubConstraintInfo::updateVarIDsWithMapping(
+ const VariableIDMap& idMap, bool forward)
+{
+ varIndex = idMap.mappingForVariable(varIndex, forward);
+}
+
+//-----------------------------------------------------------------------------
+// BoundaryConstraint code
+//-----------------------------------------------------------------------------
+
+class Offset : public SubConstraintInfo
+{
+ public:
+ Offset(unsigned ind, double offset) :
+ SubConstraintInfo(ind),
+ distOffset(offset)
+ {
+ }
+ double distOffset;
+};
+
+
+BoundaryConstraint::BoundaryConstraint(const vpsc::Dim dim)
+ : CompoundConstraint(dim),
+ position(0),
+ variable(nullptr)
+{
+}
+
+
+void BoundaryConstraint::updatePosition(const vpsc::Dim dim)
+{
+ if (dim == _primaryDim)
+ {
+ position = variable->finalPosition;
+ }
+}
+
+
+void BoundaryConstraint::addShape(const unsigned int index,
+ const double offset)
+{
+ _subConstraintInfo.push_back(new Offset(index, offset));
+}
+
+
+void BoundaryConstraint::printCreationCode(FILE *fp) const
+{
+ fprintf(fp, " BoundaryConstraint *boundary%llu = "
+ "new BoundaryConstraint(vpsc::%cDIM);\n",
+ (unsigned long long) this, (_primaryDim == 0) ? 'X' : 'Y');
+ for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin();
+ o != _subConstraintInfo.end(); ++o)
+ {
+ Offset *info = static_cast<Offset *> (*o);
+ fprintf(fp, " boundary%llu->addShape(%u, %g);\n",
+ (unsigned long long) this, info->varIndex, info->distOffset);
+ }
+ fprintf(fp, " ccs.push_back(boundary%llu);\n\n",
+ (unsigned long long) this);
+}
+
+
+std::string BoundaryConstraint::toString(void) const
+{
+ std::ostringstream stream;
+ stream << "BoundaryConstraint(";
+ stream << "dim: " << ((_primaryDim == 0) ? 'X' : 'Y');
+ stream << "): {";
+ bool first = true;
+ for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin();
+ o != _subConstraintInfo.end(); ++o)
+ {
+ Offset *info = static_cast<Offset *> (*o);
+ if (!first)
+ {
+ stream << ", ";
+ }
+ stream << "(" << "rect: " << info->varIndex << ", offset: " << info->distOffset << ")";
+ first = false;
+ }
+ stream << "}";
+ return stream.str();
+}
+
+
+void BoundaryConstraint::generateVariables(const vpsc::Dim dim,
+ vpsc::Variables& vars)
+{
+ if (dim == _primaryDim)
+ {
+ // Just one variable is generated, associated with the position
+ // of the boundary. This variable can float freely.
+ variable = new vpsc::Variable(vars.size(), position, freeWeight);
+ vars.push_back(variable);
+ }
+}
+
+
+void BoundaryConstraint::generateSeparationConstraints(const vpsc::Dim dim,
+ vpsc::Variables& vars, vpsc::Constraints& cs,
+ vpsc::Rectangles& bbs)
+{
+ COLA_UNUSED(bbs);
+ if (dim == _primaryDim)
+ {
+ COLA_ASSERT(variable != nullptr);
+ for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin();
+ o != _subConstraintInfo.end(); ++o)
+ {
+ Offset *info = static_cast<Offset *> (*o);
+ assertValidVariableIndex(vars, info->varIndex);
+ vpsc::Constraint *constraint = nullptr;
+ if (info->distOffset < 0)
+ {
+ // Constrain the objects with negative offsets to be
+ // to the left of the boundary.
+ constraint = new vpsc::Constraint(vars[info->varIndex],
+ variable, -info->distOffset);
+ }
+ else
+ {
+ // Constrain the objects with positive offsets to be
+ // to the right of the boundary.
+ constraint = new vpsc::Constraint(variable,
+ vars[info->varIndex], info->distOffset);
+ }
+ constraint->creator = this;
+ cs.push_back(constraint);
+ }
+ }
+}
+
+
+SubConstraintAlternatives
+BoundaryConstraint::getCurrSubConstraintAlternatives(vpsc::Variables vs[])
+{
+ SubConstraintAlternatives alternatives;
+
+ Offset *info = static_cast<Offset *>
+ (_subConstraintInfo[_currSubConstraintIndex]);
+
+ assertValidVariableIndex(vs[_primaryDim], info->varIndex);
+ if (info->distOffset < 0)
+ {
+ // Constrain the objects with negative offsets to be
+ // to the left of the boundary.
+ vpsc::Constraint constraint = vpsc::Constraint(
+ vs[_primaryDim][info->varIndex], variable, -info->distOffset);
+ alternatives.push_back(SubConstraint(_primaryDim, constraint));
+ }
+ else
+ {
+ // Constrain the objects with positive offsets to be
+ // to the right of the boundary.
+ vpsc::Constraint constraint = vpsc::Constraint(
+ variable, vs[_primaryDim][info->varIndex], info->distOffset);
+ alternatives.push_back(SubConstraint(_primaryDim, constraint));
+ }
+
+ //fprintf(stderr, "===== BOUNDARYLINE ALTERNATIVES -======\n");
+ return alternatives;
+}
+
+
+
+//-----------------------------------------------------------------------------
+// AlignmentConstraint code
+//-----------------------------------------------------------------------------
+
+AlignmentConstraint::AlignmentConstraint(const vpsc::Dim dim, double position)
+ : CompoundConstraint(dim),
+ indicator(nullptr),
+ variable(nullptr),
+ _position(position),
+ _isFixed(false)
+{
+}
+
+
+void AlignmentConstraint::addShape(const unsigned int index,
+ const double offset)
+{
+ _subConstraintInfo.push_back(new Offset(index, offset));
+}
+
+
+void AlignmentConstraint::updatePosition(const vpsc::Dim dim)
+{
+ if (dim == _primaryDim)
+ {
+ _position = variable->finalPosition;
+ }
+}
+
+
+void AlignmentConstraint::fixPos(double pos)
+{
+ _position = pos;
+ _isFixed = true;
+}
+
+
+void AlignmentConstraint::unfixPos()
+{
+ _isFixed = false;
+}
+
+
+double AlignmentConstraint::position(void) const
+{
+ return _position;
+}
+
+bool AlignmentConstraint::isFixed(void) const
+{
+ return _isFixed;
+}
+
+void AlignmentConstraint::generateVariables(const vpsc::Dim dim,
+ vpsc::Variables& vars)
+{
+ if (dim == _primaryDim)
+ {
+ // Variable representing the position of a guideline.
+ variable = new vpsc::Variable(vars.size(), _position, freeWeight);
+ if (_isFixed)
+ {
+ variable->fixedDesiredPosition = true;
+ variable->weight = 100000;
+ }
+ vars.push_back(variable);
+ }
+}
+
+
+void AlignmentConstraint::generateSeparationConstraints(const vpsc::Dim dim,
+ vpsc::Variables& vars, vpsc::Constraints& cs,
+ vpsc::Rectangles& bbs)
+{
+ COLA_UNUSED(bbs);
+ if (dim == _primaryDim)
+ {
+ COLA_ASSERT(variable != nullptr);
+ // Constrain each object to be offset from the guideline by
+ // some exact amount.
+ for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin();
+ o != _subConstraintInfo.end(); ++o)
+ {
+ Offset *info = static_cast<Offset *> (*o);
+ assertValidVariableIndex(vars, info->varIndex);
+ vpsc::Constraint *constraint = new vpsc::Constraint(
+ variable, vars[info->varIndex], info->distOffset, true);
+ constraint->creator = this;
+ cs.push_back(constraint);
+ }
+ }
+}
+
+void AlignmentConstraint::updateShapeOffsetsForDifferentCentres(
+ const std::vector<double>& offsets, bool forward)
+{
+ for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin();
+ o != _subConstraintInfo.end(); ++o)
+ {
+ Offset *info = static_cast<Offset *> (*o);
+ if (offsets[info->varIndex] == 0)
+ {
+ continue;
+ }
+
+ if (forward)
+ {
+ info->distOffset -= offsets[info->varIndex];
+ }
+ else
+ {
+ info->distOffset += offsets[info->varIndex];
+ }
+ }
+}
+
+void AlignmentConstraint::printCreationCode(FILE *fp) const
+{
+ fprintf(fp, " AlignmentConstraint *alignment%llu = "
+ "new AlignmentConstraint(vpsc::%cDIM, %g);\n",
+ (unsigned long long) this, (_primaryDim == 0) ? 'X' : 'Y',
+ _position);
+ if (_isFixed)
+ {
+ fprintf(fp, " alignment%llu->fixPos(%g);\n",
+ (unsigned long long) this, _position);
+ }
+ for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin();
+ o != _subConstraintInfo.end(); ++o)
+ {
+ Offset *info = static_cast<Offset *> (*o);
+ fprintf(fp, " alignment%llu->addShape(%u, %g);\n",
+ (unsigned long long) this, info->varIndex, info->distOffset);
+ }
+ fprintf(fp, " ccs.push_back(alignment%llu);\n\n",
+ (unsigned long long) this);
+}
+
+
+std::string AlignmentConstraint::toString(void) const
+{
+ std::ostringstream stream;
+ stream << "AlignmentConstraint(";
+ stream << "dim: " << ((_primaryDim == 0) ? 'X' : 'Y');
+ stream << ", pos: " << _position;
+ if (_isFixed)
+ {
+ stream << ", fixed: true";
+ }
+#if 0
+ // TODO: buggy. Not the right value.
+ if (variable)
+ {
+ stream << ", varInd: " << variable->id;
+ }
+#endif
+ stream << "): {";
+ bool first = true;
+ for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin();
+ o != _subConstraintInfo.end(); ++o)
+ {
+ Offset *info = static_cast<Offset *> (*o);
+ if (!first)
+ {
+ stream << ", ";
+ }
+ stream << "(" << "rect: " << info->varIndex << ", offset: " << info->distOffset << ")";
+ first = false;
+ }
+ stream << "}";
+ return stream.str();
+}
+
+
+SubConstraintAlternatives
+AlignmentConstraint::getCurrSubConstraintAlternatives(vpsc::Variables vs[])
+{
+ SubConstraintAlternatives alternatives;
+
+ Offset *info = static_cast<Offset *>
+ (_subConstraintInfo[_currSubConstraintIndex]);
+
+ assertValidVariableIndex(vs[_primaryDim], info->varIndex);
+ vpsc::Constraint constraint(variable, vs[_primaryDim][info->varIndex],
+ info->distOffset, true);
+ alternatives.push_back(SubConstraint(_primaryDim, constraint));
+
+ //fprintf(stderr, "===== ALIGN ALTERNATIVES -======\n");
+ return alternatives;
+}
+
+
+//-----------------------------------------------------------------------------
+// SeparationConstraint code
+//-----------------------------------------------------------------------------
+
+
+class VarIndexPair : public SubConstraintInfo
+{
+ public:
+ VarIndexPair(unsigned ind1, unsigned ind2)
+ : SubConstraintInfo(ind1),
+ lConstraint(nullptr),
+ rConstraint(nullptr),
+ varIndex2(ind2)
+ {
+ }
+ VarIndexPair(AlignmentConstraint *l, AlignmentConstraint *r)
+ : SubConstraintInfo(0),
+ lConstraint(l),
+ rConstraint(r),
+ varIndex2(0)
+ {
+ }
+ unsigned indexL(void) const
+ {
+ return (lConstraint) ?
+ (unsigned) lConstraint->variable->id : varIndex;
+ }
+ unsigned indexR(void) const
+ {
+ return (rConstraint) ?
+ (unsigned) rConstraint->variable->id : varIndex2;
+ }
+ void updateVarIDsWithMapping(const VariableIDMap& idMap, bool forward)
+ {
+ varIndex = idMap.mappingForVariable(varIndex, forward);
+ varIndex2 = idMap.mappingForVariable(varIndex2, forward);
+ }
+
+ AlignmentConstraint *lConstraint;
+ AlignmentConstraint *rConstraint;
+ unsigned varIndex2;
+};
+
+
+SeparationConstraint::SeparationConstraint(const vpsc::Dim dim,
+ unsigned l, unsigned r, double g, bool equality)
+ : CompoundConstraint(dim),
+ gap(g),
+ equality(equality),
+ vpscConstraint(nullptr)
+{
+ _subConstraintInfo.push_back(new VarIndexPair(l, r));
+}
+
+
+SeparationConstraint::SeparationConstraint(const vpsc::Dim dim,
+ AlignmentConstraint *l, AlignmentConstraint *r, double g,
+ bool equality)
+ : CompoundConstraint(dim),
+ gap(g),
+ equality(equality)
+{
+ COLA_ASSERT(l);
+ COLA_ASSERT(r);
+
+ _subConstraintInfo.push_back(new VarIndexPair(l, r));
+}
+
+
+void SeparationConstraint::printCreationCode(FILE *fp) const
+{
+ assert(_subConstraintInfo.size() == 1);
+ VarIndexPair *varIndexPair = (VarIndexPair *) _subConstraintInfo.front();
+ if (varIndexPair->lConstraint && varIndexPair->rConstraint)
+ {
+ fprintf(fp, " SeparationConstraint *separation%llu = "
+ "new SeparationConstraint(vpsc::%cDIM, alignment%llu, "
+ "alignment%llu, %g, %s);\n",
+ (unsigned long long) this, (_primaryDim == 0) ? 'X' : 'Y',
+ (unsigned long long) varIndexPair->lConstraint,
+ (unsigned long long) varIndexPair->rConstraint, gap,
+ (equality) ? "true" : "false");
+ }
+ else
+ {
+ fprintf(fp, " SeparationConstraint *separation%llu = "
+ "new SeparationConstraint(vpsc::%cDIM, %u, %u, %g, %s);\n",
+ (unsigned long long) this, (_primaryDim == 0) ? 'X' : 'Y',
+ varIndexPair->indexL(), varIndexPair->indexR(), gap,
+ (equality) ? "true" : "false");
+ }
+ fprintf(fp, " ccs.push_back(separation%llu);\n\n",
+ (unsigned long long) this);
+}
+
+
+std::string SeparationConstraint::toString(void) const
+{
+ std::ostringstream stream;
+ stream << "SeparationConstraint(";
+ stream << "dim: " << ((_primaryDim == 0) ? 'X' : 'Y');
+ stream << ", sep: " << gap;
+ stream << ", equality: " << ((equality) ? "true" : "false");
+ stream << "): {";
+ VarIndexPair *varIndexPair = (VarIndexPair *) _subConstraintInfo.front();
+ if (varIndexPair->lConstraint && varIndexPair->rConstraint)
+ {
+ stream << "(alignment: " << varIndexPair->indexL() << "), ";
+ stream << "(alignment: " << varIndexPair->indexR() << "), ";
+ }
+ else
+ {
+ stream << "(rect: " << varIndexPair->indexL() << "), ";
+ stream << "(rect: " << varIndexPair->indexR() << "), ";
+ }
+ stream << "}";
+ return stream.str();
+}
+
+
+void SeparationConstraint::generateVariables(const vpsc::Dim dim,
+ vpsc::Variables& vars)
+{
+ COLA_UNUSED(dim);
+ COLA_UNUSED(vars);
+
+ // No additional variables are required!
+}
+
+
+SubConstraintAlternatives
+SeparationConstraint::getCurrSubConstraintAlternatives(vpsc::Variables vs[])
+{
+ SubConstraintAlternatives alternatives;
+
+ VarIndexPair *info = static_cast<VarIndexPair *>
+ (_subConstraintInfo[_currSubConstraintIndex]);
+
+ assertValidVariableIndex(vs[_primaryDim], info->indexL());
+ assertValidVariableIndex(vs[_primaryDim], info->indexR());
+ vpsc::Constraint constraint(vs[_primaryDim][info->indexL()],
+ vs[_primaryDim][info->indexR()], gap, equality);
+ alternatives.push_back(SubConstraint(_primaryDim, constraint));
+
+ //fprintf(stderr, "===== SEPARATION ALTERNATIVES -======\n");
+ return alternatives;
+}
+
+
+void SeparationConstraint::generateSeparationConstraints(const vpsc::Dim dim,
+ vpsc::Variables& vs, vpsc::Constraints& cs,
+ vpsc::Rectangles& bbs)
+{
+ COLA_UNUSED(bbs);
+ if (dim == _primaryDim)
+ {
+ VarIndexPair *info =
+ static_cast<VarIndexPair *> (_subConstraintInfo.front());
+
+ unsigned left = info->indexL();
+ unsigned right = info->indexR();
+ assertValidVariableIndex(vs, left);
+ assertValidVariableIndex(vs, right);
+ vpscConstraint =
+ new vpsc::Constraint(vs[left], vs[right], gap, equality);
+ vpscConstraint->creator = this;
+ cs.push_back(vpscConstraint);
+ }
+}
+
+
+unsigned SeparationConstraint::left(void) const
+{
+ VarIndexPair *info =
+ static_cast<VarIndexPair *> (_subConstraintInfo.front());
+
+ return info->indexL();
+}
+
+
+unsigned SeparationConstraint::right(void) const
+{
+ VarIndexPair *info =
+ static_cast<VarIndexPair *> (_subConstraintInfo.front());
+
+ return info->indexR();
+}
+
+
+void SeparationConstraint::setSeparation(double gap)
+{
+ this->gap = gap;
+ if (vpscConstraint != nullptr)
+ {
+ vpscConstraint->gap = gap;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// OrthogonalEdgeConstraint code
+//-----------------------------------------------------------------------------
+
+OrthogonalEdgeConstraint::OrthogonalEdgeConstraint(const vpsc::Dim dim,
+ unsigned l, unsigned r)
+ : CompoundConstraint(dim),
+ left(l),
+ right(r),
+ vpscConstraint(nullptr)
+{
+}
+
+
+void OrthogonalEdgeConstraint::generateVariables(const vpsc::Dim dim,
+ vpsc::Variables& vars)
+{
+ COLA_UNUSED(dim);
+ COLA_UNUSED(vars);
+
+ // No additional variables are required!
+}
+
+
+void OrthogonalEdgeConstraint::printCreationCode(FILE *fp) const
+{
+ fprintf(fp, " /* OrthogonalEdgeConstraint *orthogonal%llu = nullptr; */\n\n",
+ (unsigned long long) this);
+}
+
+
+std::string OrthogonalEdgeConstraint::toString(void) const
+{
+ std::ostringstream stream;
+ stream << "OrthogonalEdgeConstraint()";
+ return stream.str();
+}
+
+
+
+SubConstraintAlternatives
+OrthogonalEdgeConstraint::getCurrSubConstraintAlternatives(
+ vpsc::Variables vs[])
+{
+ COLA_UNUSED(vs);
+
+ // XXX: What to do here?
+ _currSubConstraintIndex = _subConstraintInfo.size();
+ return SubConstraintAlternatives();
+}
+
+
+void OrthogonalEdgeConstraint::generateSeparationConstraints(
+ const vpsc::Dim dim, vpsc::Variables& vs, vpsc::Constraints& cs,
+ vpsc::Rectangles& bbs)
+{
+ COLA_UNUSED(bbs);
+ if (dim == _primaryDim)
+ {
+ assertValidVariableIndex(vs, left);
+ assertValidVariableIndex(vs, right);
+ vpscConstraint = new vpsc::Constraint(vs[left], vs[right], 0, true);
+ vpscConstraint->creator = this;
+ cs.push_back(vpscConstraint);
+ }
+}
+
+
+void OrthogonalEdgeConstraint::generateTopologyConstraints(const vpsc::Dim k,
+ const vpsc::Rectangles& rs, vector<vpsc::Variable*> const & vars,
+ vector<vpsc::Constraint*> & cs)
+{
+ assertValidVariableIndex(vars, left);
+ assertValidVariableIndex(vars, right);
+ double lBound, rBound, pos;
+ if (k == vpsc::HORIZONTAL)
+ {
+ lBound = rs[left]->getCentreY();
+ rBound = rs[right]->getCentreY();
+ pos = rs[left]->getCentreX();
+ }
+ else
+ {
+ lBound = rs[left]->getCentreX();
+ rBound = rs[right]->getCentreX();
+ pos = rs[left]->getCentreY();
+ }
+ double minBound = std::min(lBound, rBound);
+ double maxBound = std::max(lBound, rBound);
+ for (unsigned i = 0; i < rs.size(); ++i)
+ {
+ if (i==left || i==right) continue;
+ vpsc::Rectangle *r = rs[i];
+ if (r->allowOverlap()) continue;
+ double l, rMin, rMax, rCentre;
+ rectBounds(k, r, rMin, rMax, rCentre, l);
+ if ( ((rMin >= minBound) && (rMin <= maxBound)) ||
+ ((rMax >= minBound) && (rMax <= maxBound)))
+ {
+ double g = l / 2;
+ if (rCentre < pos)
+ {
+ cs.push_back(new vpsc::Constraint(vars[i], vars[left], g));
+ }
+ else
+ {
+ cs.push_back(new vpsc::Constraint(vars[left], vars[i], g));
+ }
+ }
+ }
+}
+
+
+void OrthogonalEdgeConstraint::rectBounds(const vpsc::Dim k,
+ vpsc::Rectangle const *r, double& cmin, double& cmax,
+ double& centre, double & l) const
+{
+ if (k == vpsc::HORIZONTAL)
+ {
+ cmin = r->getMinY();
+ cmax = r->getMaxY();
+ centre = r->getCentreX();
+ l = r->width();
+ }
+ else
+ {
+ cmin = r->getMinX();
+ cmax = r->getMaxX();
+ centre = r->getCentreY();
+ l = r->height();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// MultiSeparationConstraint code
+//-----------------------------------------------------------------------------
+
+class AlignmentPair : public SubConstraintInfo
+{
+ public:
+ AlignmentPair(AlignmentConstraint *ac1, AlignmentConstraint *ac2)
+ : SubConstraintInfo(0),
+ alignment1(ac1),
+ alignment2(ac2)
+ {
+ }
+ AlignmentConstraint *alignment1;
+ AlignmentConstraint *alignment2;
+};
+
+
+MultiSeparationConstraint::MultiSeparationConstraint(const vpsc::Dim dim,
+ double minSep, bool equality)
+ : CompoundConstraint(dim),
+ indicator(nullptr),
+ sep(minSep),
+ equality(equality)
+{
+}
+
+
+void MultiSeparationConstraint::addAlignmentPair(AlignmentConstraint *ac1,
+ AlignmentConstraint *ac2)
+{
+ _subConstraintInfo.push_back(new AlignmentPair(ac1, ac2));
+}
+
+
+void MultiSeparationConstraint::printCreationCode(FILE *fp) const
+{
+ fprintf(fp, " MultiSeparationConstraint *multiSep%llu = "
+ "new MultiSeparationConstraint(vpsc::%cDIM, %g, %s);\n",
+ (unsigned long long) this, (_primaryDim == 0) ? 'X' : 'Y', sep,
+ (equality) ? "true" : "false");
+ for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin();
+ o != _subConstraintInfo.end(); ++o)
+ {
+ AlignmentPair *pair = static_cast<AlignmentPair *> (*o);
+ fprintf(fp, " multiSep%llu->addAlignmentPair("
+ "alignment%llu, alignment%llu);\n",
+ (unsigned long long) this,
+ (unsigned long long) pair->alignment1,
+ (unsigned long long) pair->alignment2);
+ }
+ fprintf(fp, " ccs.push_back(multiSep%llu);\n\n",
+ (unsigned long long) this);
+}
+
+
+std::string MultiSeparationConstraint::toString(void) const
+{
+ std::ostringstream stream;
+ stream << "MultiSeparationConstraint(";
+ stream << "dim: " << ((_primaryDim == 0) ? 'X' : 'Y');
+ stream << ", sep: " << sep;
+ stream << ", equality: " << ((equality) ? "true" : "false");
+ stream << "): {";
+ bool first = true;
+ for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin();
+ o != _subConstraintInfo.end(); ++o)
+ {
+ if (!first)
+ {
+ stream << ", ";
+ }
+ AlignmentPair *pair = static_cast<AlignmentPair *> (*o);
+ stream << "(alignment: " << pair->alignment1->variable->id
+ << ", alignment: " << pair->alignment2->variable->id << ")";
+ first = false;
+ }
+ stream << "}";
+ return stream.str();
+}
+
+
+void MultiSeparationConstraint::generateVariables(const vpsc::Dim dim,
+ vpsc::Variables& vars)
+{
+ COLA_UNUSED(dim);
+ COLA_UNUSED(vars);
+
+ // No additional variables are required!
+}
+
+
+SubConstraintAlternatives
+MultiSeparationConstraint::getCurrSubConstraintAlternatives(
+ vpsc::Variables vs[])
+{
+ COLA_UNUSED(vs);
+
+ SubConstraintAlternatives alternatives;
+
+ AlignmentPair *info = static_cast<AlignmentPair *>
+ (_subConstraintInfo[_currSubConstraintIndex]);
+
+ AlignmentConstraint *c1 = info->alignment1;
+ AlignmentConstraint *c2 = info->alignment2;
+ if (!c1->variable || !c2->variable)
+ {
+ throw InvalidConstraint(this);
+ }
+ vpsc::Constraint constraint(c1->variable, c2->variable, sep, equality);
+ alternatives.push_back(SubConstraint(_primaryDim, constraint));
+
+ //fprintf(stderr, "===== MULTI SEPARATION ALTERNATIVES -======\n");
+ return alternatives;
+}
+
+
+void MultiSeparationConstraint::setSeparation(double sep)
+{
+ this->sep = sep;
+}
+
+
+void MultiSeparationConstraint::generateSeparationConstraints(
+ const vpsc::Dim dim, vpsc::Variables& vs, vpsc::Constraints& gcs,
+ vpsc::Rectangles& bbs)
+{
+ COLA_UNUSED(vs);
+ COLA_UNUSED(bbs);
+
+ if (dim == _primaryDim)
+ {
+ for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin();
+ o != _subConstraintInfo.end(); ++o)
+ {
+ AlignmentPair *info = static_cast<AlignmentPair *> (*o);
+ AlignmentConstraint *c1 = info->alignment1;
+ AlignmentConstraint *c2 = info->alignment2;
+ if (!c1->variable || !c2->variable)
+ {
+ throw InvalidConstraint(this);
+ }
+ vpsc::Constraint *c = new vpsc::Constraint(
+ c1->variable, c2->variable, sep, equality);
+ c->creator = this;
+ gcs.push_back(c);
+ cs.push_back(c);
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// DistributionConstraint code
+//-----------------------------------------------------------------------------
+
+DistributionConstraint::DistributionConstraint(const vpsc::Dim dim)
+ : CompoundConstraint(dim),
+ indicator(nullptr)
+{
+}
+
+
+void DistributionConstraint::addAlignmentPair(AlignmentConstraint *ac1,
+ AlignmentConstraint *ac2)
+{
+ _subConstraintInfo.push_back(new AlignmentPair(ac1, ac2));
+}
+
+
+void DistributionConstraint::generateVariables(const vpsc::Dim dim,
+ vpsc::Variables& vars)
+{
+ COLA_UNUSED(dim);
+ COLA_UNUSED(vars);
+
+ // No additional variables are required!
+}
+
+
+void DistributionConstraint::setSeparation(double sep)
+{
+ this->sep = sep;
+}
+
+
+void DistributionConstraint::printCreationCode(FILE *fp) const
+{
+ fprintf(fp, " DistributionConstraint *distribution%llu = "
+ "new DistributionConstraint(vpsc::%cDIM);\n",
+ (unsigned long long) this, (_primaryDim == 0) ? 'X' : 'Y');
+ fprintf(fp, " distribution%llu->setSeparation(%g);\n",
+ (unsigned long long) this, sep);
+ for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin();
+ o != _subConstraintInfo.end(); ++o)
+ {
+ AlignmentPair *pair = static_cast<AlignmentPair *> (*o);
+ fprintf(fp, " distribution%llu->addAlignmentPair("
+ "alignment%llu, alignment%llu);\n",
+ (unsigned long long) this,
+ (unsigned long long) pair->alignment1,
+ (unsigned long long) pair->alignment2);
+ }
+ fprintf(fp, " ccs.push_back(distribution%llu);\n\n",
+ (unsigned long long) this);
+}
+
+
+std::string DistributionConstraint::toString(void) const
+{
+ std::ostringstream stream;
+ stream << "DistributionConstraint(";
+ stream << "dim: " << ((_primaryDim == 0) ? 'X' : 'Y');
+ stream << ", sep: " << sep;
+ stream << "): {";
+ bool first = true;
+ for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin();
+ o != _subConstraintInfo.end(); ++o)
+ {
+ if (!first)
+ {
+ stream << ", ";
+ }
+ AlignmentPair *pair = static_cast<AlignmentPair *> (*o);
+ stream << "(alignment: " << pair->alignment1->variable->id
+ << ", alignment: " << pair->alignment2->variable->id << ")";
+ first = false;
+ }
+ stream << "}";
+ return stream.str();
+}
+
+
+SubConstraintAlternatives
+DistributionConstraint::getCurrSubConstraintAlternatives(vpsc::Variables vs[])
+{
+ COLA_UNUSED(vs);
+
+ SubConstraintAlternatives alternatives;
+
+ AlignmentPair *info = static_cast<AlignmentPair *>
+ (_subConstraintInfo[_currSubConstraintIndex]);
+ AlignmentConstraint *c1 = info->alignment1;
+ AlignmentConstraint *c2 = info->alignment2;
+ if (!c1->variable || !c2->variable)
+ {
+ throw InvalidConstraint(this);
+ }
+ vpsc::Constraint constraint(c1->variable, c2->variable, sep, true);
+ alternatives.push_back(SubConstraint(_primaryDim, constraint));
+
+ //fprintf(stderr, "===== DISTRIBUTION ALTERNATIVES -======\n");
+ return alternatives;
+}
+
+
+void DistributionConstraint::generateSeparationConstraints(
+ const vpsc::Dim dim, vpsc::Variables& vars, vpsc::Constraints& gcs,
+ vpsc::Rectangles& bbs)
+{
+ COLA_UNUSED(vars);
+ COLA_UNUSED(bbs);
+
+ if (dim == _primaryDim)
+ {
+ cs.clear();
+ for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin();
+ o != _subConstraintInfo.end(); ++o)
+ {
+ AlignmentPair *info = static_cast<AlignmentPair *> (*o);
+ AlignmentConstraint *c1 = info->alignment1;
+ AlignmentConstraint *c2 = info->alignment2;
+ if (!c1->variable || !c2->variable)
+ {
+ throw InvalidConstraint(this);
+ }
+ vpsc::Constraint *c=new vpsc::Constraint(
+ c1->variable, c2->variable, sep, true);
+ c->creator = this;
+ gcs.push_back(c);
+ cs.push_back(c);
+#if 0
+ // The following was an experiment to allow variable distributions
+ // solved by optimisation rather than satisfying constraints
+ if(isVariable) {
+ // set second derivatives of:
+ // (u + g - v)^2 = g^2 + 2gu + u^2 - 2gv - 2uv + v^2
+ (*Q)[make_pair(c1->variable->id,c1->variable->id)]+=w;
+ (*Q)[make_pair(c2->variable->id,c2->variable->id)]+=w;
+ (*Q)[make_pair(variable->id,variable->id)]+=w;
+ (*Q)[make_pair(c1->variable->id,c2->variable->id)]-=w;
+ (*Q)[make_pair(c2->variable->id,c1->variable->id)]-=w;
+ (*Q)[make_pair(c1->variable->id,variable->id)]+=w;
+ (*Q)[make_pair(variable->id,c1->variable->id)]+=w;
+ (*Q)[make_pair(c2->variable->id,variable->id)]-=w;
+ (*Q)[make_pair(variable->id,c2->variable->id)]-=w;
+ }
+#endif
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// FixedRelativeConstraint code
+//-----------------------------------------------------------------------------
+
+class RelativeOffset : public SubConstraintInfo
+{
+ public:
+ RelativeOffset(unsigned indL, unsigned indR, vpsc::Dim dim,
+ double offset)
+ : SubConstraintInfo(indL),
+ varIndex2(indR),
+ dim(dim),
+ distOffset(offset)
+ {
+ }
+ void updateVarIDsWithMapping(const VariableIDMap& idMap, bool forward)
+ {
+ varIndex = idMap.mappingForVariable(varIndex, forward);
+ varIndex2 = idMap.mappingForVariable(varIndex2, forward);
+ }
+
+ unsigned varIndex2;
+ vpsc::Dim dim;
+ double distOffset;
+};
+
+
+FixedRelativeConstraint::FixedRelativeConstraint(const vpsc::Rectangles& rs,
+ std::vector<unsigned> shapeIds, const bool fixedPosition)
+ : CompoundConstraint(vpsc::XDIM),
+ m_fixed_position(fixedPosition),
+ m_shape_vars(shapeIds)
+{
+ _combineSubConstraints = true;
+
+ // Make sure that m_shape_vars doesn't contain duplicates.
+ std::sort(m_shape_vars.begin(), m_shape_vars.end());
+ std::vector<unsigned>::iterator last =
+ std::unique(m_shape_vars.begin(), m_shape_vars.end());
+ m_shape_vars.erase(last, m_shape_vars.end());
+
+ unsigned firstId = UINT_MAX;
+ COLA_ASSERT(m_shape_vars.size() >= 2);
+ for (std::vector<unsigned>::iterator it = m_shape_vars.begin();
+ it != m_shape_vars.end(); ++it)
+ {
+ COLA_ASSERT(*it < rs.size());
+
+ if (it == m_shape_vars.begin())
+ {
+ firstId = *it;
+ }
+ else
+ {
+ unsigned thisId = *it;
+ _subConstraintInfo.push_back(
+ new RelativeOffset(firstId, thisId, vpsc::XDIM,
+ rs[thisId]->getCentreX() - rs[firstId]->getCentreX()));
+ _subConstraintInfo.push_back(
+ new RelativeOffset(firstId, thisId, vpsc::YDIM,
+ rs[thisId]->getCentreY() - rs[firstId]->getCentreY()));
+ }
+ }
+}
+
+void FixedRelativeConstraint::updateVarIDsWithMapping(
+ const VariableIDMap& idMap, bool forward)
+{
+ CompoundConstraint::updateVarIDsWithMapping(idMap, forward);
+
+ // We need to map variables in m_shape_vars too,
+ // since this is used in generateVariables().
+ for (size_t i = 0; i < m_shape_vars.size(); ++i)
+ {
+ m_shape_vars[i] = idMap.mappingForVariable(m_shape_vars[i], forward);
+ }
+}
+
+
+
+void FixedRelativeConstraint::generateVariables(const vpsc::Dim dim,
+ vpsc::Variables& vars)
+{
+ COLA_UNUSED(dim);
+ COLA_UNUSED(vars);
+
+ // No additional variables are required!
+
+ // Fix shape positions if required.
+ if (m_fixed_position)
+ {
+ for (std::vector<unsigned>::iterator it = m_shape_vars.begin();
+ it != m_shape_vars.end(); ++it)
+ {
+ vars[*it]->fixedDesiredPosition = true;
+ vars[*it]->weight = 100000;
+ }
+ }
+}
+
+
+void FixedRelativeConstraint::printCreationCode(FILE *fp) const
+{
+ fprintf(fp, " std::vector<unsigned> fixedRelativeSet%llu;\n",
+ (unsigned long long) this);
+ for (std::vector<unsigned>::const_iterator it = m_shape_vars.begin();
+ it != m_shape_vars.end(); ++it)
+ {
+ fprintf(fp, " fixedRelativeSet%llu.push_back(%u);\n",
+ (unsigned long long) this, *it);
+ }
+ fprintf(fp, " FixedRelativeConstraint *fixedRelative%llu = "
+ "new FixedRelativeConstraint(rs, fixedRelativeSet%llu, %s);\n",
+ (unsigned long long) this, (unsigned long long) this,
+ (m_fixed_position) ? "true" : "false");
+ fprintf(fp, " ccs.push_back(fixedRelative%llu);\n\n",
+ (unsigned long long) this);
+}
+
+
+std::string FixedRelativeConstraint::toString(void) const
+{
+ std::ostringstream stream;
+ stream << "FixedRelativeConstraint(";
+ stream << "fixedPos: " << ((m_fixed_position) ? "true" : "false");
+ stream << "): {";
+ bool first = true;
+ for (std::vector<unsigned>::const_iterator it = m_shape_vars.begin();
+ it != m_shape_vars.end(); ++it)
+ {
+ if (!first)
+ {
+ stream << ", ";
+ }
+ stream << "(rect: " << *it << ")";
+ first = false;
+ }
+ stream << "}";
+ return stream.str();
+}
+
+
+SubConstraintAlternatives
+FixedRelativeConstraint::getCurrSubConstraintAlternatives(vpsc::Variables vs[])
+{
+ COLA_UNUSED(vs);
+
+ SubConstraintAlternatives alternatives;
+
+ RelativeOffset *offset = static_cast<RelativeOffset *>
+ (_subConstraintInfo[_currSubConstraintIndex]);
+
+ vpsc::Dim dim = offset->dim;
+ vpsc::Constraint constraint(vs[dim][offset->varIndex],
+ vs[dim][offset->varIndex2], offset->distOffset, true);
+ alternatives.push_back(SubConstraint(dim, constraint));
+
+ //fprintf(stderr, "===== FixedRelativeConstraint ALTERNATIVES -======\n");
+ return alternatives;
+}
+
+
+void FixedRelativeConstraint::generateSeparationConstraints(
+ const vpsc::Dim dim, vpsc::Variables& vars, vpsc::Constraints& ccs,
+ vpsc::Rectangles& bbs)
+{
+ COLA_UNUSED(vars);
+ COLA_UNUSED(bbs);
+
+ for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin();
+ o != _subConstraintInfo.end(); ++o)
+ {
+ RelativeOffset *offset = static_cast<RelativeOffset *> (*o);
+ if (dim != offset->dim)
+ {
+ continue;
+ }
+
+ assertValidVariableIndex(vars, offset->varIndex);
+ assertValidVariableIndex(vars, offset->varIndex2);
+ vpsc::Constraint *c =
+ new vpsc::Constraint(vars[offset->varIndex],
+ vars[offset->varIndex2], offset->distOffset, true);
+ c->creator = this;
+ ccs.push_back(c);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// PageBoundaryConstraint code
+//-----------------------------------------------------------------------------
+
+class PageBoundaryShapeOffsets : public SubConstraintInfo
+{
+ public:
+ PageBoundaryShapeOffsets(unsigned ind, double xOffset, double yOffset) :
+ SubConstraintInfo(ind)
+ {
+ halfDim[0] = xOffset;
+ halfDim[1] = yOffset;
+ }
+ double halfDim[2]; // half width and height values;
+};
+
+
+PageBoundaryConstraints::PageBoundaryConstraints(double xLow, double xHigh,
+ double yLow, double yHigh, double weight)
+ : CompoundConstraint(vpsc::HORIZONTAL)
+{
+ COLA_ASSERT(xLow < xHigh);
+ COLA_ASSERT(yLow < yHigh);
+
+ leftMargin[vpsc::XDIM] = xLow;
+ rightMargin[vpsc::XDIM] = xHigh;
+ leftMargin[vpsc::YDIM] = yLow;
+ rightMargin[vpsc::YDIM] = yHigh;
+
+ for (unsigned i = 0; i < 2; ++i)
+ {
+ actualLeftMargin[i] = leftMargin[i];
+ actualRightMargin[i] = rightMargin[i];
+ leftWeight[i] = weight;
+ rightWeight[i] = weight;
+ vl[i] = nullptr;
+ vr[i] = nullptr;
+ }
+}
+
+
+void PageBoundaryConstraints::addShape(unsigned id, double halfW, double halfH)
+{
+ _subConstraintInfo.push_back(new PageBoundaryShapeOffsets(id, halfW, halfH));
+}
+
+
+void PageBoundaryConstraints::printCreationCode(FILE *fp) const
+{
+ fprintf(fp, " PageBoundaryConstraints *pageBoundary%llu = "
+ "new PageBoundaryConstraints(%g, %g, %g, %g, %g);\n",
+ (unsigned long long) this, leftMargin[vpsc::XDIM],
+ rightMargin[vpsc::XDIM], leftMargin[vpsc::YDIM],
+ rightMargin[vpsc::YDIM], leftWeight[0]);
+ for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin();
+ o != _subConstraintInfo.end(); ++o)
+ {
+ PageBoundaryShapeOffsets *offsets =
+ static_cast<PageBoundaryShapeOffsets *> (*o);
+ fprintf(fp, " pageBoundary%llu->addShape(%u, %g, %g);\n",
+ (unsigned long long) this, offsets->varIndex,
+ offsets->halfDim[XDIM], offsets->halfDim[YDIM]);
+ }
+ fprintf(fp, " ccs.push_back(pageBoundary%llu);\n\n",
+ (unsigned long long) this);
+}
+
+
+std::string PageBoundaryConstraints::toString(void) const
+{
+ std::ostringstream stream;
+ stream << "PageBoundaryConstraints(";
+ stream << "xLow: " << leftMargin[vpsc::XDIM];
+ stream << ", xHigh: " << rightMargin[vpsc::XDIM];
+ stream << ", yLow: " << leftMargin[vpsc::YDIM];
+ stream << ", yHigh: " << rightMargin[vpsc::YDIM];
+ stream << ", weight: " << leftWeight[0];
+ stream << "): {";
+ bool first = true;
+ for (SubConstraintInfoList::const_iterator o = _subConstraintInfo.begin();
+ o != _subConstraintInfo.end(); ++o)
+ {
+ if (!first)
+ {
+ stream << ", ";
+ }
+ PageBoundaryShapeOffsets *offsets =
+ static_cast<PageBoundaryShapeOffsets *> (*o);
+ stream << "(rect: " << offsets->varIndex;
+ stream << ", halfWidth: " << offsets->halfDim[XDIM];
+ stream << ", halfHeight: " << offsets->halfDim[YDIM];
+ stream <<")";
+ first = false;
+ }
+ stream << "}";
+ return stream.str();
+}
+
+SubConstraintAlternatives
+PageBoundaryConstraints::getCurrSubConstraintAlternatives(vpsc::Variables vs[])
+{
+ COLA_UNUSED(vs);
+
+ // Page boundary constraints do not need to be evaluated at the
+ // time of makeFeasible, so we return an empty list here.
+ _currSubConstraintIndex = _subConstraintInfo.size();
+ return SubConstraintAlternatives();
+}
+
+
+void PageBoundaryConstraints::updatePosition(const vpsc::Dim dim)
+{
+ if (vl[dim])
+ {
+ actualLeftMargin[dim] = vl[dim]->finalPosition;
+ }
+
+ if (vr[dim])
+ {
+ actualRightMargin[dim] = vr[dim]->finalPosition;
+ }
+}
+
+
+double PageBoundaryConstraints::getActualLeftMargin(const vpsc::Dim dim)
+{
+ return actualLeftMargin[dim];
+}
+
+
+double PageBoundaryConstraints::getActualRightMargin(const vpsc::Dim dim)
+{
+ return actualRightMargin[dim];
+}
+
+
+void PageBoundaryConstraints::generateVariables(const vpsc::Dim dim,
+ vpsc::Variables& vars)
+{
+ // create 2 dummy vars, based on the dimension we are in
+ if (leftWeight[dim])
+ {
+ vars.push_back(vl[dim] = new vpsc::Variable(vars.size(),
+ leftMargin[dim], leftWeight[dim]));
+ vl[dim]->fixedDesiredPosition = true;
+ }
+
+ if (rightWeight[dim])
+ {
+ vars.push_back(vr[dim] = new vpsc::Variable(vars.size(),
+ rightMargin[dim], rightWeight[dim]));
+ vr[dim]->fixedDesiredPosition = true;
+ }
+}
+
+
+void PageBoundaryConstraints::generateSeparationConstraints(
+ const vpsc::Dim dim, vpsc::Variables& vs, vpsc::Constraints& cs,
+ vpsc::Rectangles& bbs)
+{
+ COLA_UNUSED(bbs);
+ // For each of the "real" variables, create a constraint that puts
+ // that var between our two new dummy vars, depending on the dimension.
+ for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin();
+ o != _subConstraintInfo.end(); ++o)
+ {
+ PageBoundaryShapeOffsets *info =
+ static_cast<PageBoundaryShapeOffsets *> (*o);
+ assertValidVariableIndex(vs, info->varIndex);
+ if (vl[dim])
+ {
+ vpsc::Constraint *constraint = new vpsc::Constraint(vl[dim],
+ vs[info->varIndex], info->halfDim[dim]);
+ constraint->creator = this;
+ cs.push_back(constraint);
+ }
+
+ if (vr[dim])
+ {
+ vpsc::Constraint *constraint = new vpsc::Constraint(
+ vs[info->varIndex], vr[dim], info->halfDim[dim]);
+ constraint->creator = this;
+ cs.push_back(constraint);
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Support code
+//-----------------------------------------------------------------------------
+
+
+struct GenerateVariables
+{
+ GenerateVariables(const vpsc::Dim dim, vpsc::Variables& vars)
+ : dim(dim),
+ vars(vars)
+ {
+ }
+ void operator() (CompoundConstraint *c)
+ {
+ c->generateVariables(dim, vars);
+ }
+
+ const vpsc::Dim dim;
+ vpsc::Variables& vars;
+};
+
+
+struct GenerateSeparationConstraints
+{
+ GenerateSeparationConstraints(const vpsc::Dim dim, vpsc::Variables& vars,
+ vpsc::Constraints& cs, vpsc::Rectangles& bbs)
+ : dim(dim),
+ vars(vars),
+ cs(cs),
+ bbs(bbs)
+ {
+ }
+ void operator() (CompoundConstraint *c)
+ {
+ c->generateSeparationConstraints(dim, vars, cs, bbs);
+ }
+ const vpsc::Dim dim;
+ vpsc::Variables& vars;
+ vpsc::Constraints& cs;
+ vpsc::Rectangles& bbs;
+};
+
+
+void generateVariablesAndConstraints(CompoundConstraints& ccs,
+ const vpsc::Dim dim, vpsc::Variables& vars, vpsc::Constraints& cs,
+ vpsc::Rectangles& bbs)
+{
+ for_each(ccs.begin(), ccs.end(),
+ GenerateVariables(dim, vars));
+ for_each(ccs.begin(), ccs.end(),
+ GenerateSeparationConstraints(dim, vars, cs, bbs));
+}
+
+
+void generateVariables(CompoundConstraints& ccs, const vpsc::Dim dim,
+ vpsc::Variables& vars)
+{
+ for_each(ccs.begin(), ccs.end(),
+ GenerateVariables(dim, vars));
+}
+
+
+CompoundConstraint::CompoundConstraint(vpsc::Dim primaryDim,
+ unsigned int priority) :
+ _primaryDim(primaryDim),
+ _secondaryDim((vpsc::Dim) ((primaryDim + 1) % 2)),
+ _priority(priority),
+ _combineSubConstraints(false),
+ _currSubConstraintIndex(0)
+{
+}
+
+
+CompoundConstraint::~CompoundConstraint()
+{
+ // Free memory from the subConstraintInfo list.
+ for_each(_subConstraintInfo.begin(), _subConstraintInfo.end(), delete_object());
+ _subConstraintInfo.clear();
+}
+
+
+vpsc::Dim CompoundConstraint::dimension(void) const
+{
+ return _primaryDim;
+}
+
+
+unsigned int CompoundConstraint::priority(void) const
+{
+ return _priority;
+}
+
+
+void CompoundConstraint::printCreationCode(FILE *fp) const
+{
+ COLA_UNUSED(fp);
+
+ // Do nothing. Subclasses can implement this.
+}
+
+void CompoundConstraint::updateVarIDsWithMapping(const VariableIDMap& idMap,
+ bool forward)
+{
+ for (SubConstraintInfoList::iterator o = _subConstraintInfo.begin();
+ o != _subConstraintInfo.end(); ++o)
+ {
+ (*o)->updateVarIDsWithMapping(idMap, forward);
+ }
+}
+
+
+std::list<unsigned> CompoundConstraint::subConstraintObjIndexes(void) const
+{
+ std::list<unsigned> idList;
+ for (size_t i = 0; i < _subConstraintInfo.size(); ++i)
+ {
+ idList.push_back(_subConstraintInfo[i]->varIndex);
+ }
+ return idList;
+}
+
+
+bool CompoundConstraint::subConstraintsRemaining(void) const
+{
+ return _currSubConstraintIndex < _subConstraintInfo.size();
+}
+
+
+void CompoundConstraint::markAllSubConstraintsAsInactive(void)
+{
+ for (size_t i = 0; i < _subConstraintInfo.size(); ++i)
+ {
+ _subConstraintInfo[i]->satisfied = false;
+ }
+ _currSubConstraintIndex = 0;
+}
+
+
+void CompoundConstraint::markCurrSubConstraintAsActive(const bool satisfiable)
+{
+ _subConstraintInfo[_currSubConstraintIndex]->satisfied = satisfiable;
+
+ _currSubConstraintIndex++;
+}
+
+
+void CompoundConstraint::assertValidVariableIndex(const vpsc::Variables& vars,
+ const unsigned index)
+{
+ if (index >= vars.size())
+ {
+ throw InvalidVariableIndexException(this, index);
+ }
+}
+
+
+bool CompoundConstraint::shouldCombineSubConstraints(void) const
+{
+ return _combineSubConstraints;
+}
+
+
+UnsatisfiableConstraintInfo::UnsatisfiableConstraintInfo(
+ const vpsc::Constraint *c)
+ : leftVarIndex(c->left->id),
+ rightVarIndex(c->right->id),
+ separation(c->gap),
+ equality(c->equality),
+ cc((CompoundConstraint *)c->creator)
+{
+}
+
+// Variable mapping.
+
+VariableIDMap::VariableIDMap()
+{
+}
+
+VariableIDMap::~VariableIDMap()
+{
+}
+
+typedef std::pair<unsigned, unsigned> IDPair;
+typedef std::list<IDPair> IDPairList;
+
+bool VariableIDMap::addMappingForVariable(const unsigned from,
+ const unsigned to)
+{
+ bool found = false;
+ for (IDPairList::iterator it = m_mapping.begin(); it != m_mapping.end();
+ ++it)
+ {
+ IDPair& ids = *it;
+
+ if (ids.first == from)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ m_mapping.push_back(std::make_pair(from, to));
+ return true;
+ }
+ //fprintf(stderr, "VariableIDMap: mapping already exists for var %u\n", from);
+ return false;
+}
+
+void VariableIDMap::printCreationCode(FILE *fp) const
+{
+ fprintf(fp, " cola::VariableIDMap idMap;\n");
+ for (IDPairList::const_iterator it = m_mapping.begin();
+ it != m_mapping.end(); ++it)
+ {
+ fprintf(fp, " idMap.addMappingForVariable(%u, %u);\n",
+ it->first, it->second);
+ }
+ fprintf(fp, " \n");
+}
+
+unsigned VariableIDMap::mappingForVariable(const unsigned var,
+ bool forward) const
+{
+ for (IDPairList::const_iterator it = m_mapping.begin();
+ it != m_mapping.end(); ++it)
+ {
+ const IDPair& ids = *it;
+
+ if (forward)
+ {
+ if (ids.first == var)
+ {
+ return ids.second;
+ }
+ }
+ else // (!forward)
+ {
+ if (ids.second == var)
+ {
+ return ids.first;
+ }
+ }
+ }
+
+ //fprintf(stderr, "Warning: mapping not found for var %u\n", var);
+
+ // Just return original variable index.
+ return var;
+}
+
+void VariableIDMap::clear(void)
+{
+ m_mapping.clear();
+}
+
+
+} // namespace cola
+
diff --git a/src/3rdparty/adaptagrams/libcola/compound_constraints.h b/src/3rdparty/adaptagrams/libcola/compound_constraints.h
new file mode 100644
index 0000000..4d24152
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/compound_constraints.h
@@ -0,0 +1,829 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+*/
+
+#ifndef _COMPOUND_CONSTRAINTS_H
+#define _COMPOUND_CONSTRAINTS_H
+
+#include <vector>
+#include <list>
+#include <set>
+#include <utility>
+
+#include "libvpsc/rectangle.h"
+#include "libvpsc/constraint.h"
+#include "libcola/sparse_matrix.h"
+#include "libcola/unused.h"
+
+namespace vpsc {
+ class Constraint;
+ class Variable;
+
+// Avoid SWIG redefinition warnings.
+#ifndef SWIG
+ typedef std::vector<vpsc::Constraint *> Constraints;
+ typedef std::vector<vpsc::Variable *> Variables;
+#endif
+}
+namespace cola {
+
+class Cluster;
+class RootCluster;
+
+
+// A component of a CompoundConstraint.
+class SubConstraint
+{
+ public:
+ SubConstraint(vpsc::Dim dim, vpsc::Constraint constraint,
+ double cost = 0)
+ : dim(dim),
+ constraint(constraint),
+ cost(cost)
+ {
+ }
+ bool operator<(const SubConstraint& rhs) const
+ {
+ return cost < rhs.cost;
+ }
+
+ vpsc::Dim dim;
+ vpsc::Constraint constraint;
+ double cost;
+};
+
+
+// A list of alternative SubConstraints.
+typedef std::list<SubConstraint> SubConstraintAlternatives;
+
+static const double freeWeight = 0.0001;
+
+static const unsigned int DEFAULT_CONSTRAINT_PRIORITY = 30000;
+static const unsigned int PRIORITY_NONOVERLAP =
+ DEFAULT_CONSTRAINT_PRIORITY - 2000;
+
+/**
+ * @brief Holds a mapping between two sets of Variable indices.
+ *
+ * This can be used to rewrite the Rectangles to which a set of
+ * CompoundConstraints apply to. This is useful when creating another
+ * instance of the problem, but using the same CompoundConstraints list.
+ * You should not usually need to use this yourself. It is utilised by
+ * addons such as topology::AvoidTopologyAddon.
+ *
+ * If a mapping for a particular value is not set, it is considered to be
+ * equal on both sides of the mapping.
+ */
+class VariableIDMap
+{
+ public:
+ VariableIDMap();
+ ~VariableIDMap();
+
+ /**
+ * @brief Adds a mapping between a pair of variables.
+ *
+ * @param[in] from The variable index to map from.
+ * @param[in] to The variable index to map to.
+ * @return True if the mapping was successfully added.
+ */
+ bool addMappingForVariable(const unsigned from, const unsigned to);
+ unsigned mappingForVariable(const unsigned var,
+ bool forward = true) const;
+ void clear(void);
+ void printCreationCode(FILE *fp) const;
+
+ private:
+ std::list<std::pair<unsigned, unsigned> > m_mapping;
+};
+
+class SubConstraintInfo
+{
+ public:
+ SubConstraintInfo(unsigned ind) :
+ varIndex(ind),
+ satisfied(false)
+ {
+ }
+ virtual ~SubConstraintInfo()
+ {
+ }
+ virtual void updateVarIDsWithMapping(const VariableIDMap& idMap,
+ bool forward);
+
+ unsigned varIndex;
+ bool satisfied;
+};
+
+typedef std::vector<SubConstraintInfo *> SubConstraintInfoList;
+
+
+/**
+ * @brief An abstract base class for all high-level compound constraints.
+ *
+ * A compound constraint is a conceptual, diagramming application oriented
+ * type of constraint, which can be translated into a set of simple
+ * separation constraints, possibly extra dummy variables, and perhaps
+ * even some extra terms for the quadratic objective function used
+ * in the gradient projection solver.
+ */
+class CompoundConstraint {
+public:
+ CompoundConstraint(vpsc::Dim primaryDim,
+ unsigned int priority = DEFAULT_CONSTRAINT_PRIORITY);
+ /**
+ * @brief Implemented by the compound constraint to generate any
+ * additional required variables in the given dimension.
+ *
+ * Generate any additional variables required by this compound constraint
+ * when operating in the given dimension dim and add them to vars. These
+ * variables should be cleaned up by the caller after the VPSC problem is
+ * solved.
+ *
+ * The variables' ideal position and weight should be set by the compound
+ * constraint and they should be added to the end of vars.
+ *
+ * @param[in] dim The current active dimension.
+ * @param[in,out] vars The list of variables for the overall problem
+ * instance to which any variables generated should
+ * be appended.
+ */
+ virtual void generateVariables(const vpsc::Dim dim,
+ vpsc::Variables& vars) = 0;
+ /**
+ * @brief Implemented by the compound constraint to generate the low-level
+ * separation constraints in the given dimension.
+ *
+ * These constraints will be added to the list of constraints cs.
+ *
+ * @param[in] dim The current active dimension.
+ * @param[in] vars The list of variables for the overall problem
+ * instance.
+ * @param[in,out] cs The list of constraints to which the generated
+ * constraints will be added.
+ * @param[in] bbs The list of bounding boxes for all rectangles
+ * in the current problem. It has the same order as
+ * vars.
+ */
+ virtual void generateSeparationConstraints(const vpsc::Dim dim,
+ vpsc::Variables& var, vpsc::Constraints& cs,
+ vpsc::Rectangles& bbs) = 0;
+ /**
+ * @brief Implemented by the compound constraint to send position
+ * information back to the interface.
+ *
+ * This will be called for each compound constraint once the VPSC
+ * instance is solved to allow them to pass information such as
+ * variable values back to the graphical user interface.
+ *
+ * @param[in] dim The current active dimension.
+ */
+ virtual void updatePosition(const vpsc::Dim dim)
+ {
+ COLA_UNUSED(dim);
+ }
+
+ /**
+ * @brief Returns a textual description of the compound constraint.
+ *
+ * @return A string describing the compound constraint.
+ */
+ virtual std::string toString(void) const = 0;
+
+// To prevent C++ objects from being destroyed in garbage collected languages
+// when the libraries are called from SWIG, we hide the declarations of the
+// destructors and prevent generation of default destructors.
+#ifndef SWIG
+ virtual ~CompoundConstraint();
+#endif
+
+ vpsc::Dim dimension(void) const;
+ unsigned int priority(void) const;
+ virtual void updateVarIDsWithMapping(const VariableIDMap& idMap,
+ bool forward = true);
+ virtual void updateShapeOffsetsForDifferentCentres(
+ const std::vector<double>& offsets, bool forward = true)
+ {
+ COLA_UNUSED(offsets);
+ COLA_UNUSED(forward);
+ }
+
+ // The following methods are only needed for initially solving feasibility
+ // of the constraints, and do not need to be implemented for most compound
+ // constraints.
+ virtual void markAllSubConstraintsAsInactive(void);
+ virtual bool subConstraintsRemaining(void) const;
+ virtual void markCurrSubConstraintAsActive(const bool satisfiable);
+ virtual SubConstraintAlternatives getCurrSubConstraintAlternatives(
+ vpsc::Variables vs[]) = 0;
+ std::list<unsigned> subConstraintObjIndexes(void) const;
+ virtual void printCreationCode(FILE *fp) const;
+ bool shouldCombineSubConstraints(void) const;
+
+protected:
+ void assertValidVariableIndex(const vpsc::Variables& vars,
+ const unsigned index);
+
+ // The dimension that this compound constraint operates.
+ vpsc::Dim _primaryDim;
+ // The alternate dimension.
+ vpsc::Dim _secondaryDim;
+ // The priority used to assign order for solving constraints.
+ unsigned int _priority;
+ // Describes whether to process sub constraints individually, or all
+ // at once, during the makeFeasible opteration.
+ bool _combineSubConstraints;
+
+ // Info about the sub constraints within this compound constraint.
+ SubConstraintInfoList _subConstraintInfo;
+ // The index of the current subConstraint being made feasible.
+ size_t _currSubConstraintIndex;
+};
+//! @brief A vector of pointers to CompoundConstraint objects.
+typedef std::vector<CompoundConstraint *> CompoundConstraints;
+
+
+/**
+ * @brief Generate all the variables and constraints for a collection of
+ * CompoundConstraints.
+ */
+void generateVariablesAndConstraints(CompoundConstraints& ccs,
+ const vpsc::Dim dim, vpsc::Variables& vars, vpsc::Constraints& cs,
+ vpsc::Rectangles& bbs);
+
+
+/**
+ * @brief Generate just all the variables for a collection of
+ * CompoundConstraints.
+ */
+void generateVariables(CompoundConstraints& ccs, const vpsc::Dim dim,
+ vpsc::Variables& vars);
+
+
+/**
+ * @brief A boundary constraint specifies a bounding line that a set of nodes
+ * must be either to the left or right of.
+ *
+ * A boundary constraint gives a bounding line in a particular dimension (with
+ * position stored in a variable) and a set of nodes required to be to the left
+ * of that line and nodes required to be to the right of the line. Separations
+ * are determined by offsets passed to addShape().
+ */
+class BoundaryConstraint : public CompoundConstraint
+{
+ public:
+ /**
+ * @brief Constructs a new BoundaryConstraint in the specified
+ * dimension.
+ *
+ * @param[in] dim The dimension the constraints will operate in.
+ */
+ BoundaryConstraint(const vpsc::Dim dim);
+ /**
+ * @brief Mark a node as being part of this boundary constraint.
+ *
+ * @param[in] index The index of the node in the Rectangles vector.
+ * @param[in] offset The minimum amount to separate the node from the
+ * boundary line. Negative if left-of, positive if
+ * right-of. Will usually be equal to half a node's
+ * size plus a buffer amount.
+ */
+ void addShape(const unsigned int index, const double offset);
+
+ /**
+ * @brief Returns a textual description of the compound constraint.
+ *
+ * @return A string describing the compound constraint.
+ */
+ std::string toString(void) const;
+
+ SubConstraintAlternatives getCurrSubConstraintAlternatives(
+ vpsc::Variables vs[]);
+ void generateVariables(const vpsc::Dim dim, vpsc::Variables& vars);
+ void generateSeparationConstraints(const vpsc::Dim dim,
+ vpsc::Variables& vars, vpsc::Constraints& cs,
+ vpsc::Rectangles& bbs);
+ void updatePosition(const vpsc::Dim dim);
+ void printCreationCode(FILE *fp) const;
+
+ //! Holds the position of the boundary line, once layout is complete.
+ double position;
+
+ vpsc::Variable* variable;
+};
+
+
+/**
+ * @brief An alignment constraint specifies a alignment line that a set of
+ * nodes must be constrained to by an exact amount.
+ *
+ * This is represented as a variable representing the position of a vertical
+ * or horizontal and a then group of nodes and offsets for those nodes such
+ * that the nodes must be spaced exactly at those offsets from the alignment
+ * position.
+ *
+ * Optionally, the alignment may be given a suggested position and/or marked
+ * as "fixed". When fixed, the position variable will be given a higher
+ * weight to attempt to keep it at that position.
+ */
+class AlignmentConstraint : public CompoundConstraint
+{
+ public:
+ /**
+ * @brief Constructs a new AlignmentConstraint in the specified
+ * dimension.
+ *
+ * @param[in] dim The dimension the constraints will operate in.
+ */
+ AlignmentConstraint(const vpsc::Dim dim, double position = 0.0);
+ /**
+ * @brief Mark a node as being part of this alignment constraint.
+ *
+ * @param[in] index The index of the node in the Rectangles vector.
+ * @param[in] offset The exact amount to separate the node from the
+ * alignment line. Negative if left-of, positive if
+ * right-of. Will usually be equal to half a node's
+ * size if aligning to the side of a node, or zero
+ * if aligning with the centre of a node.
+ */
+ void addShape(const unsigned int index, const double offset);
+ /**
+ * @brief Mark the alignment as ideally having a fixed position.
+ *
+ * This causes the position variable for the alignment to be given
+ * the ideal position pos and a higher weight.
+ *
+ * @param[in] pos The ideal position value for the alignment.
+ */
+ void fixPos(double pos);
+ /**
+ * @brief Mark the alignment as not having a fixed position.
+ *
+ * This is the default.
+ */
+ void unfixPos(void);
+ /**
+ * @brief Indicates if the alignment position is marked as fixed.
+ *
+ * @returns True if the alignment position is marked as fixed, or
+ * false otherwise.
+ */
+ bool isFixed(void) const;
+
+ /**
+ * @brief Returns a textual description of the compound constraint.
+ *
+ * @return A string describing the compound constraint.
+ */
+ std::string toString(void) const;
+
+ SubConstraintAlternatives getCurrSubConstraintAlternatives(
+ vpsc::Variables vs[]);
+ void generateVariables(const vpsc::Dim dim, vpsc::Variables& vars);
+ void generateSeparationConstraints(const vpsc::Dim dim,
+ vpsc::Variables& vars, vpsc::Constraints& cs,
+ vpsc::Rectangles& bbs);
+ void updatePosition(const vpsc::Dim dim);
+ double position(void) const;
+ void printCreationCode(FILE *fp) const;
+ void updateShapeOffsetsForDifferentCentres(
+ const std::vector<double>& offsets, bool forward = true);
+
+ /// Generic pointer to an indicator object being used to represent
+ /// this compound constraint in the GUI.
+ void *indicator;
+
+ vpsc::Variable* variable;
+ private:
+ // The position of the alignment line
+ double _position;
+ bool _isFixed;
+};
+
+
+/**
+ * @brief A separation constraint specifies a simple horizontal or vertical
+ * spacing constraint between 2 nodes or alignment constraints.
+ *
+ * The non-equality constraint is lPos + g <= rPos
+ * and the equality constraint is lPos + g = rPos
+ *
+ * @note With an equality, you can effectively reverse the ordering of the
+ * two variables by making the gap a negative number. This is not so
+ * for the non-equality case, there you need to keep the same gap value
+ * but reverse the order of the variables passed to the constructor.
+ */
+class SeparationConstraint : public CompoundConstraint
+{
+ public:
+ /**
+ * @brief Constructs a new SeparationConstraint between two nodes in
+ * the specified dimension.
+ *
+ * The constraint will keep the centre of the left node to the left of
+ * the right node by exactly or more than the specified gap.
+ *
+ * @param[in] dim The dimension the constraint will operate in.
+ * @param[in] l The index of the left node.
+ * @param[in] r The index of the right node.
+ * @param[in] g The minimum or exact distance to separate the
+ * two nodes.
+ * @param[in] equality Whether or not the constraint is an exact
+ * distance.
+ */
+ SeparationConstraint(const vpsc::Dim dim, unsigned l, unsigned r,
+ double g, bool equality = false);
+ /**
+ * @brief Constructs a new SeparationConstraint between two alignment
+ * constraints in the specified dimension.
+ *
+ * The constraint will keep the centre of the left alignment line to
+ * the left of the right alignment line by exactly or more than the
+ * specified gap.
+ *
+ * @param[in] dim The dimension the constraint will operate in.
+ * @param[in] l A pointer to the left AlignmentConstraint.
+ * @param[in] r A pointer to the right AlignmentConstraint.
+ * @param[in] g The minimum or exact distance to separate the
+ * two alignment constraints.
+ * @param[in] equality Whether or not the constraint is an exact
+ * distance.
+ */
+ SeparationConstraint(const vpsc::Dim dim, AlignmentConstraint *l,
+ AlignmentConstraint *r, double g, bool equality = false);
+
+ /**
+ * @brief Returns a textual description of the compound constraint.
+ *
+ * @return A string describing the compound constraint.
+ */
+ std::string toString(void) const;
+
+ SubConstraintAlternatives getCurrSubConstraintAlternatives(
+ vpsc::Variables vs[]);
+ void generateVariables(const vpsc::Dim dim, vpsc::Variables& vars);
+ void generateSeparationConstraints(const vpsc::Dim dim,
+ vpsc::Variables& vs, vpsc::Constraints& cs,
+ vpsc::Rectangles& bbs);
+ void setSeparation(double gap);
+ unsigned left(void) const;
+ unsigned right(void) const;
+ void printCreationCode(FILE *fp) const;
+
+ double gap;
+ bool equality;
+ vpsc::Constraint *vpscConstraint;
+};
+
+
+// XXX: This is experimental
+//
+// Orthogonal edges must have their end points aligned horizontally or
+// vertically
+class OrthogonalEdgeConstraint : public CompoundConstraint
+{
+ public:
+ OrthogonalEdgeConstraint(const vpsc::Dim dim, unsigned l, unsigned r);
+
+ SubConstraintAlternatives getCurrSubConstraintAlternatives(
+ vpsc::Variables vs[]);
+ void generateVariables(const vpsc::Dim dim, vpsc::Variables& vars);
+ void generateSeparationConstraints(const vpsc::Dim dim,
+ vpsc::Variables& vs, vpsc::Constraints& cs,
+ vpsc::Rectangles& bbs);
+ void generateTopologyConstraints(const vpsc::Dim k,
+ vpsc::Rectangles const& rs,
+ std::vector<vpsc::Variable*> const& vars,
+ std::vector<vpsc::Constraint*>& cs);
+ void printCreationCode(FILE *fp) const;
+ std::string toString(void) const;
+
+ unsigned left;
+ unsigned right;
+ vpsc::Constraint* vpscConstraint;
+ private:
+ void rectBounds(const vpsc::Dim k, vpsc::Rectangle const *r,
+ double& cmin, double& cmax, double& centre, double& l) const;
+};
+
+
+/**
+ * @brief A multi-separation constraint Specifies a set of horizontal or
+ * vertical equal spacing constraints between pairs of alignment
+ * constraints.
+ *
+ * This is a way of arranging a group of alignment lines to be equally
+ * distributed, or given a uniform minimum spacing.
+ */
+class MultiSeparationConstraint : public CompoundConstraint
+{
+ public:
+ /**
+ * @brief Constructs a new empty MultiSeparationConstraint with a
+ * minimum or exact spacing.
+ *
+ * @param[in] dim The dimension the constraints will operate in.
+ * @param[in] minSep The minimum or exact distance to separate the
+ * alignment constraints.
+ * @param[in] equality Whether or not the constraints will be an exact
+ * distance.
+ */
+ MultiSeparationConstraint(const vpsc::Dim dim, double minSep = 0,
+ bool equality = false);
+ /**
+ * @brief Mark a pair of alignment constraints as being part of this
+ * multi separation constraint.
+ *
+ * You will often specify spacing beteen a set of alignments (e.g.,
+ * {1, 2, 3, 4}) by calling this method with each neighbouring pair
+ * (e.g., {(1, 2), (2, 3), (3, 4)}), but you can also specify
+ * non-neighbouring alignment constraints, if you wish them to have
+ * equal exact or minimum separation.
+ *
+ * @param[in] ac1 A pointer to the left AlignmentConstraint object
+ * of the pair.
+ * @param[in] ac2 A pointer to the right AlignmentConstraint object
+ * of the pair.
+ */
+ void addAlignmentPair(AlignmentConstraint *ac1,
+ AlignmentConstraint *ac2);
+ /**
+ * @brief Alter the minimum or exact spacing between each pair of
+ * alignment constraints.
+ *
+ * @param[in] sep The minimum or exact distance to separate the
+ * alignment constraints.
+ */
+ void setSeparation(double sep);
+
+ /**
+ * @brief Returns a textual description of the compound constraint.
+ *
+ * @return A string describing the compound constraint.
+ */
+ std::string toString(void) const;
+
+ SubConstraintAlternatives getCurrSubConstraintAlternatives(
+ vpsc::Variables vs[]);
+ void generateVariables(const vpsc::Dim dim, vpsc::Variables& vars);
+ void generateSeparationConstraints(const vpsc::Dim dim,
+ vpsc::Variables& vs, vpsc::Constraints& gcs,
+ vpsc::Rectangles& bbs);
+ void printCreationCode(FILE *fp) const;
+
+ vpsc::Constraints cs;
+
+ /// Generic pointer to an indicator object being used to represent
+ /// this compound constraint in the GUI.
+ void *indicator;
+
+ double sep;
+ bool equality;
+};
+
+
+/**
+ * @brief A distribution constraint specifies an ordered set of alignment
+ * constraints and a fixed separation required between them.
+ *
+ * This compound constraint it used to keep a set of alignment constraints
+ * equally distributed.
+ *
+ * If no separation distance is set, then it is detemined from the distance
+ * between the two outer alignments, divided by the number of alignments - 1.
+ */
+class DistributionConstraint : public CompoundConstraint {
+ public:
+ /**
+ * @brief Constructs a new empty DistributionConstraint with a
+ * minimum or exact spacing.
+ *
+ * @param[in] dim The dimension the constraints will operate in.
+ */
+ DistributionConstraint(const vpsc::Dim dim);
+ /**
+ * @brief Mark a pair of alignment constraints as being part of this
+ * distribution constraint.
+ *
+ * You should specify spacing beteen a set of alignments (e.g.,
+ * {1, 2, 3, 4}) by calling this method with each neighbouring pair
+ * (e.g., {(1, 2), (2, 3), (3, 4)}).
+ *
+ * @param[in] ac1 A pointer to the left AlignmentConstraint object
+ * of the pair.
+ * @param[in] ac2 A pointer to the right AlignmentConstraint object
+ * of the pair.
+ */
+ void addAlignmentPair(AlignmentConstraint *ac1,
+ AlignmentConstraint *ac2);
+ /**
+ * @brief Alter the exact spacing between each pair of alignment
+ * constraints.
+ *
+ * @param[in] sep The exact distance to separate the alignment
+ * constraints.
+ */
+ void setSeparation(double sep);
+
+ /**
+ * @brief Returns a textual description of the compound constraint.
+ *
+ * @return A string describing the compound constraint.
+ */
+ std::string toString(void) const;
+
+ SubConstraintAlternatives getCurrSubConstraintAlternatives(
+ vpsc::Variables vs[]);
+ void generateVariables(const vpsc::Dim dim, vpsc::Variables& vars);
+ void generateSeparationConstraints(const vpsc::Dim dim,
+ vpsc::Variables& vars, vpsc::Constraints& gcs,
+ vpsc::Rectangles& bbs);
+ void printCreationCode(FILE *fp) const;
+
+ vpsc::Constraints cs;
+
+ /// Generic pointer to an indicator object being used to represent
+ /// this compound constraint in the GUI.
+ void *indicator;
+
+ double sep;
+};
+
+/**
+ * @brief A fixed-relative constraint specifies that a group of nodes are
+ * constrained to be fixed in position relative to each other.
+ *
+ * These nodes are fixed relative to each other in both the x- and y-dimensions
+ * but still free to move as a group.
+ *
+ * Optionally, this compound constraint can be marked as desiring a fixed
+ * position. If this is specified, the group of nodes will attempt to stay
+ * close to its current position.
+ */
+class FixedRelativeConstraint : public CompoundConstraint {
+ public:
+ /**
+ * @brief Constructs a new FixedRelativeConstraint between a set of
+ * nodes, optionally with a fixed position.
+ *
+ * @param[in] rs The list of bounding boxes for the rectangles
+ * for all nodes in the current problem.
+ * @param[in] shapeIds A vector of indices into the rc vector for the
+ * nodes that will be fixed relative to each other.
+ * @param[in] fixedPosition Whether of not the nodes should ideally be
+ * fixed to the current position. The default
+ * is not fixed.
+ */
+ FixedRelativeConstraint(const vpsc::Rectangles& rs,
+ std::vector<unsigned> shapeIds,
+ const bool fixedPosition = false);
+
+ /**
+ * @brief Returns a textual description of the compound constraint.
+ *
+ * @return A string describing the compound constraint.
+ */
+ std::string toString(void) const;
+
+ SubConstraintAlternatives getCurrSubConstraintAlternatives(
+ vpsc::Variables vs[]);
+ void generateVariables(const vpsc::Dim dim, vpsc::Variables& vars);
+ void generateSeparationConstraints(const vpsc::Dim dim,
+ vpsc::Variables& vars, vpsc::Constraints& gcs,
+ vpsc::Rectangles& bbs);
+ void printCreationCode(FILE *fp) const;
+ void updateVarIDsWithMapping(const VariableIDMap& idMap,
+ bool forward = true);
+
+ private:
+ bool m_fixed_position;
+ std::vector<unsigned> m_shape_vars;
+};
+
+
+/**
+ * @brief A page boundary contraint specifies constraints that attempt to keep
+ * the given nodes within a defined rectangular region.
+ *
+ * This compound constraint creates dummy variables for each of the four edges
+ * of the page and constraints between all nodes and these dummy vars such
+ * that nodes are contained between the edges. The variables for the page
+ * edges have a high weight but will "balloon out" if other constraints force
+ * nodes to stick out past the ideal edge positions.
+ */
+class PageBoundaryConstraints : public CompoundConstraint {
+ public:
+ /**
+ * @brief Constructs a new PageBoundaryConstraints object with given
+ * page boundary positions and weight.
+ *
+ * @param[in] xLow The position of the left edge of the page.
+ * @param[in] xHigh The position of the right edge of the page.
+ * @param[in] yLow The position of the bottom edge of the page.
+ * @param[in] yHigh The position of the top edge of the page.
+ * @param[in] weight The weight to give the positions variables
+ * for the page edges. The default is 100.0.
+ */
+ PageBoundaryConstraints(double xLow, double xHigh,
+ double yLow, double yHigh, double weight = 100.0);
+ /**
+ * @brief Mark a node as being contained within this page boundary.
+ *
+ * @param[in] index The index of the node in the Rectangles vector.
+ * @param[in] halfW Half of the width of the node. Needed because
+ * node position variables represent their centre.
+ * @param[in] halfH Half of the height of the node.
+ */
+ void addShape(unsigned index, double halfW, double halfH);
+
+ /**
+ * @brief Returns a textual description of the compound constraint.
+ *
+ * @return A string describing the compound constraint.
+ */
+ std::string toString(void) const;
+
+ SubConstraintAlternatives getCurrSubConstraintAlternatives(
+ vpsc::Variables vs[]);
+ void generateVariables(const vpsc::Dim dim, vpsc::Variables& vars);
+ void generateSeparationConstraints(const vpsc::Dim dim,
+ vpsc::Variables& vars, vpsc::Constraints& gcs,
+ vpsc::Rectangles& bbs);
+ void updatePosition(const vpsc::Dim dim);
+ double getActualLeftMargin(const vpsc::Dim dim);
+ double getActualRightMargin(const vpsc::Dim dim);
+ void printCreationCode(FILE *fp) const;
+
+ private:
+ double leftMargin[2];
+ double rightMargin[2];
+ double actualLeftMargin[2];
+ double actualRightMargin[2];
+ double leftWeight[2];
+ double rightWeight[2];
+ vpsc::Variable *vl[2], *vr[2];
+};
+
+
+/**
+ * @brief Info about constraints that could not be satisfied in gradient
+ * projection process.
+ */
+class UnsatisfiableConstraintInfo {
+ public:
+ UnsatisfiableConstraintInfo(const vpsc::Constraint* c);
+
+ //! The index of the left variable.
+ unsigned leftVarIndex;
+ //! The index of the right variable.
+ unsigned rightVarIndex;
+ //! The separation.
+ double separation;
+ //! Whether the separation is an exact distance or not.
+ bool equality;
+ //! The index of the CompoundConstraint that created this.
+ cola::CompoundConstraint *cc;
+
+ std::string toString(void) const
+ {
+ std::stringstream stream;
+ stream << "Unsatisfiable constraint: var(" << leftVarIndex << ") ";
+ if (separation < 0)
+ {
+ stream << "- " << -separation;
+ }
+ else
+ {
+ stream << "+ " << separation;
+ }
+ stream << " " << ((equality) ? "== " : "<= ");
+ stream << "var(" << rightVarIndex << ")";
+ if (cc)
+ {
+ stream << "\n From " << cc->toString();
+ }
+
+ return stream.str();
+ }
+};
+//! @brief A vector of pointers to UnsatisfiableConstraintInfo objects.
+typedef std::vector<UnsatisfiableConstraintInfo *> UnsatisfiableConstraintInfos;
+
+} // namespace cola
+#endif // _COMPOUND_CONSTRAINTS_H
diff --git a/src/3rdparty/adaptagrams/libcola/conjugate_gradient.cpp b/src/3rdparty/adaptagrams/libcola/conjugate_gradient.cpp
new file mode 100644
index 0000000..adb7fa6
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/conjugate_gradient.cpp
@@ -0,0 +1,137 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006 Nathan Hurst <njh@njhurst.com>
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Nathan Hurst
+ * Tim Dwyer
+ *
+*/
+
+
+#include <cmath>
+#include <cstdlib>
+#include <cassert>
+#include <valarray>
+
+#include "libvpsc/assertions.h"
+#include "libcola/commondefs.h"
+#include "libcola/conjugate_gradient.h"
+
+/* lifted wholely from wikipedia. Well, apart from the bug in the wikipedia version. */
+
+using std::valarray;
+
+static void
+matrix_times_vector(valarray<double> const &matrix, /* m * n */
+ valarray<double> const &vec, /* n */
+ valarray<double> &result) /* m */
+{
+ unsigned n = vec.size();
+ unsigned m = result.size();
+ COLA_ASSERT(m*n == matrix.size());
+# if defined(_MSC_VER)
+ // magmy: The following lines show how operator[] is defined for valarray under MSVC
+ // _Ty valarray<_Ty>::operator[](size_t _Off) const;
+ // _Ty &valarray<_Ty>::operator[](size_t _Off);
+ // As a consequence, it is not possible to take the address of a constant valarray[n].
+ // This looks like a bug in the Microsoft's <valarray> file.
+ // Below is a workaround
+ double const *mp = &const_cast<valarray<double> &>(matrix)[0];
+# else
+ const double* mp = &matrix[0];
+# endif
+ for (unsigned i = 0; i < m; i++) {
+ double res = 0;
+ for (unsigned j = 0; j < n; j++)
+ res += *mp++ * vec[j];
+ result[i] = res;
+ }
+}
+
+/*
+static double Linfty(valarray<double> const &vec) {
+ return std::max(vec.max(), -vec.min());
+}
+*/
+
+double
+inner(valarray<double> const &x,
+ valarray<double> const &y) {
+ double total = 0;
+ for(unsigned i = 0; i < x.size(); i++)
+ total += x[i]*y[i];
+ return total;// (x*y).sum(); <- this is more concise, but ineff
+}
+
+double compute_cost(valarray<double> const &A,
+ valarray<double> const &b,
+ valarray<double> const &x,
+ const unsigned n) {
+ // computes cost = 2 b x - x A x
+ double cost = 2. * inner(b,x);
+ valarray<double> Ax(n);
+ for (unsigned i=0; i<n; i++) {
+ Ax[i] = 0;
+ for (unsigned j=0; j<n; j++) {
+ Ax[i] += A[i*n+j]*x[j];
+ }
+ }
+ return cost - inner(x,Ax);
+}
+void
+conjugate_gradient(valarray<double> const &A,
+ valarray<double> &x,
+ valarray<double> const &b,
+ unsigned const n, double const tol,
+ unsigned const max_iterations) {
+ //printf("Conjugate Gradient...\n");
+ valarray<double> Ap(n), p(n), r(n);
+ matrix_times_vector(A,x,Ap);
+ r=b-Ap;
+ double r_r = inner(r,r);
+ unsigned k = 0;
+ double tol_squared = tol*tol;
+#ifdef EXAMINE_COST
+ double previousCost=compute_cost(A,b,x,n),cost;
+#endif
+ while(k < max_iterations && r_r > tol_squared) {
+ k++;
+ double r_r_new = r_r;
+ if(k == 1)
+ p = r;
+ else {
+ r_r_new = inner(r,r);
+ if(r_r_new<tol_squared) break;
+ p = r + (r_r_new/r_r)*p;
+ }
+ matrix_times_vector(A, p, Ap);
+ double alpha_k = r_r_new / inner(p, Ap);
+ x += alpha_k*p;
+#ifdef EXAMINE_COST
+ cost=compute_cost(A,b,x,n);
+ printf(" CG[%d] %.15f %.15f\n",k,previousCost,cost);
+ previousCost=cost;
+#endif
+ r -= alpha_k*Ap;
+ r_r = r_r_new;
+ }
+ //printf(" CG finished after %d iterations\n",k);
+ //printf("njh: %d iters, Linfty = %g L2 = %g\n", k,
+ //std::max(-r.min(), r.max()), sqrt(r_r));
+ // x is solution
+}
diff --git a/src/3rdparty/adaptagrams/libcola/conjugate_gradient.h b/src/3rdparty/adaptagrams/libcola/conjugate_gradient.h
new file mode 100644
index 0000000..e21cd16
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/conjugate_gradient.h
@@ -0,0 +1,36 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+*/
+
+#ifndef _CONJUGATE_GRADIENT_H
+#define _CONJUGATE_GRADIENT_H
+
+#include <valarray>
+
+double
+inner(std::valarray<double> const &x,
+ std::valarray<double> const &y);
+
+void
+conjugate_gradient(std::valarray<double> const &A,
+ std::valarray<double> &x,
+ std::valarray<double> const &b,
+ unsigned const n, double const tol,
+ unsigned const max_iterations);
+#endif // _CONJUGATE_GRADIENT_H
diff --git a/src/3rdparty/adaptagrams/libcola/connected_components.cpp b/src/3rdparty/adaptagrams/libcola/connected_components.cpp
new file mode 100644
index 0000000..fc65dc9
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/connected_components.cpp
@@ -0,0 +1,160 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+*/
+
+
+#include <map>
+#include <list>
+
+#include "libvpsc/rectangle.h"
+#include "libvpsc/assertions.h"
+#include "libcola/commondefs.h"
+#include "libcola/connected_components.h"
+
+using namespace std;
+using namespace vpsc;
+namespace cola {
+ Component::~Component() {
+ /*
+ for(unsigned i=0;i<scx.size();i++) {
+ delete scx[i];
+ }
+ for(unsigned i=0;i<scy.size();i++) {
+ delete scy[i];
+ }
+ */
+ }
+ void Component::moveRectangles(double x, double y) {
+ for(unsigned i=0;i<rects.size();i++) {
+ rects[i]->moveCentreX(rects[i]->getCentreX()+x);
+ rects[i]->moveCentreY(rects[i]->getCentreY()+y);
+ }
+ }
+ Rectangle* Component::getBoundingBox()
+ {
+ Rectangle boundingBox;
+ for (unsigned i = 0; i < rects.size(); ++i)
+ {
+ boundingBox = boundingBox.unionWith(*(rects[i]));
+ }
+ return new Rectangle(boundingBox);
+ }
+
+ namespace ccomponents {
+ struct Node {
+ unsigned id;
+ bool visited;
+ vector<Node*> neighbours;
+ list<Node*>::iterator listPos;
+ Rectangle* r;
+ };
+ // Depth first search traversal of graph to find connected component
+ void dfs(Node* v,
+ list<Node*>& remaining,
+ Component* component,
+ map<unsigned,pair<Component*,unsigned> > &cmap) {
+ v->visited=true;
+ remaining.erase(v->listPos);
+ cmap[v->id]=make_pair(component,static_cast<unsigned>(component->node_ids.size()));
+ component->node_ids.push_back(v->id);
+ component->rects.push_back(v->r);
+ for(unsigned i=0;i<v->neighbours.size();i++) {
+ Node* u=v->neighbours[i];
+ if(!u->visited) {
+ dfs(u,remaining,component,cmap);
+ }
+ }
+ }
+ }
+
+ using namespace ccomponents;
+
+ // for a graph of n nodes, return connected components
+ void connectedComponents(
+ const vector<Rectangle*> &rs,
+ const vector<Edge> &es,
+ //const SeparationConstraints &scx,
+ //const SeparationConstraints &scy,
+ vector<Component*> &components) {
+ unsigned n=rs.size();
+ vector<Node> vs(n);
+ list<Node*> remaining;
+ for(unsigned i=0;i<n;i++) {
+ vs[i].id=i;
+ vs[i].visited=false;
+ vs[i].r=rs[i];
+ vs[i].listPos = remaining.insert(remaining.end(),&vs[i]);
+ }
+ vector<Edge>::const_iterator ei;
+ for(ei=es.begin();ei!=es.end();ei++) {
+ vs[ei->first].neighbours.push_back(&vs[ei->second]);
+ vs[ei->second].neighbours.push_back(&vs[ei->first]);
+ }
+ map<unsigned,pair<Component*,unsigned> > cmap;
+ while(!remaining.empty()) {
+ Component* component=new Component;
+ Node* v=*remaining.begin();
+ dfs(v,remaining,component,cmap);
+ components.push_back(component);
+ }
+ for(ei=es.begin();ei!=es.end();ei++) {
+ pair<Component*,unsigned> u=cmap[ei->first],
+ v=cmap[ei->second];
+ COLA_ASSERT(u.first==v.first);
+ u.first->edges.push_back(make_pair(u.second,v.second));
+ }
+ /*
+ SeparationConstraints::const_iterator ci;
+ for(ci=scx.begin();ci!=scx.end();ci++) {
+ SeparationConstraint *c=*ci;
+ pair<Component*,unsigned> u=cmap[c->left],
+ v=cmap[c->right];
+ COLA_ASSERT(u.first==v.first);
+ u.first->scx.push_back(
+ new SeparationConstraint(u.second,v.second,c->gap));
+ }
+ for(ci=scy.begin();ci!=scy.end();ci++) {
+ SeparationConstraint *c=*ci;
+ pair<Component*,unsigned> u=cmap[c->left],
+ v=cmap[c->right];
+ COLA_ASSERT(u.first==v.first);
+ u.first->scy.push_back(
+ new SeparationConstraint(u.second,v.second,c->gap));
+ }
+ */
+ }
+ void separateComponents(const vector<Component*> &components) {
+ unsigned n=components.size();
+ vector<Rectangle*> bbs(n);
+ valarray<double> origX(n);
+ valarray<double> origY(n);
+ for(unsigned i=0;i<n;i++) {
+ bbs[i]=components[i]->getBoundingBox();
+ origX[i]=bbs[i]->getCentreX();
+ origY[i]=bbs[i]->getCentreY();
+ }
+ removeoverlaps(bbs);
+ for(unsigned i=0;i<n;i++) {
+ components[i]->moveRectangles(
+ bbs[i]->getCentreX()-origX[i],
+ bbs[i]->getCentreY()-origY[i]);
+ delete bbs[i];
+ }
+ }
+}
diff --git a/src/3rdparty/adaptagrams/libcola/connected_components.h b/src/3rdparty/adaptagrams/libcola/connected_components.h
new file mode 100644
index 0000000..578eab2
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/connected_components.h
@@ -0,0 +1,54 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+*/
+
+#ifndef CONNECTED_COMPONENTS_H
+#define CONNECTED_COMPONENTS_H
+#include "libcola/cola.h"
+#include <vector>
+
+namespace cola {
+// a graph component with a list of node_ids giving indices for some larger list of nodes
+// for the nodes in this component,
+// and a list of edges - node indices relative to this component
+class Component {
+public:
+ std::vector<unsigned> node_ids;
+ std::vector<vpsc::Rectangle*> rects;
+ std::vector<cola::Edge> edges;
+ //CompoundConstraints cx, cy;
+ ~Component();
+ void moveRectangles(double x, double y);
+ vpsc::Rectangle* getBoundingBox();
+};
+// for a graph of n nodes, return connected components
+void connectedComponents(
+ const std::vector<vpsc::Rectangle*> &rs,
+ const std::vector<cola::Edge> &es,
+ //const CompoundConstraints &cx,
+ //const CompoundConstraints &cy,
+ std::vector<Component*> &components);
+
+// move the contents of each component so that the components do not
+// overlap.
+void separateComponents(const std::vector<Component*> &components);
+
+} // namespace cola
+
+#endif // CONNECTED_COMPONENTS_H
diff --git a/src/3rdparty/adaptagrams/libcola/convex_hull.cpp b/src/3rdparty/adaptagrams/libcola/convex_hull.cpp
new file mode 100644
index 0000000..3ecbfea
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/convex_hull.cpp
@@ -0,0 +1,129 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+*/
+
+#include <valarray>
+#include <cfloat>
+#include <algorithm>
+
+#include "libvpsc/assertions.h"
+#include "libcola/convex_hull.h"
+
+
+namespace hull {
+using namespace std;
+/**
+ * CrossProduct of three points: If the result is 0, the points are collinear;
+ * if it is positive, the three points (in order) constitute a "left turn",
+ * otherwise a "right turn".
+ */
+inline double crossProduct(
+ double x0, double y0,
+ double x1, double y1,
+ double x2, double y2) {
+ return (x1-x0)*(y2-y0)-(x2-x0)*(y1-y0);
+}
+struct CounterClockwiseOrder {
+ CounterClockwiseOrder(
+ const unsigned p,
+ std::valarray<double> const & X, std::valarray<double> const & Y)
+ :px(X[p]), py(Y[p]), X(X), Y(Y) {};
+ bool operator() (unsigned i, unsigned j) {
+ // o=crossProduct(px,py,X[i],Y[i],X[j],Y[j]);
+ double xi=X[i]-px;
+ double xj=X[j]-px;
+ // since py is the min y pos, yi and yj must be positive
+ double yi=Y[i]-py;
+ double yj=Y[j]-py;
+
+ // use cross product rule
+ double o = xi*yj-xj*yi;
+ if(o!=0) {
+ return o>0;
+ }
+ // in case of ties choose point farthest from p
+ return (xi*xi+yi*yi) < (xj*xj+yj*yj);
+ }
+ const double px;
+ const double py;
+ std::valarray<double> const & X;
+ std::valarray<double> const & Y;
+};
+void convex(const unsigned n, const double* X, const double* Y, vector<unsigned> & h) {
+ const valarray<double> XA(X,n);
+ const valarray<double> YA(Y,n);
+ convex(XA,YA,h);
+}
+/**
+ * Implementation of Graham's scan convex hull finding algorithm.
+ * X and Y give the horizontal and vertical positions of the pointset.
+ * The result is returned in hull as a list of indices referencing points in X and Y.
+ */
+void convex(valarray<double> const & X, valarray<double> const & Y, vector<unsigned> & h) {
+ unsigned n=X.size();
+ COLA_ASSERT(n==Y.size());
+ unsigned p0=0;
+ // find point p0 with min Y position, choose leftmost in case of tie.
+ // This is our "pivot" point
+ double minY=DBL_MAX,minX=DBL_MAX;
+ for(unsigned i=0;i<n;i++) {
+ if ( (Y[i] < minY) || ((Y[i] == minY) && (X[i] < minX)) )
+ {
+ p0=i;
+ minY=Y[i];
+ minX=X[i];
+ }
+ }
+ // sort remaining points by the angle line p0-p1 (p1 in points) makes
+ // with x-axis
+ vector<unsigned> points;
+ for(unsigned i=0;i<n;i++) {
+ if(i!=p0) points.push_back(i);
+ }
+ CounterClockwiseOrder order(p0,X,Y);
+ sort(points.begin(),points.end(),order);
+ // now we maintain a stack in h, adding points while each successive
+ // point is a "left turn", backtracking if we make a right turn.
+ h.clear();
+ h.push_back(p0);
+ h.push_back(points[0]);
+ for(unsigned i=1;i<points.size();i++) {
+ double o=crossProduct(
+ X[h[h.size()-2]],Y[h[h.size()-2]],
+ X[h[h.size()-1]],Y[h[h.size()-1]],
+ X[points[i]],Y[points[i]]);
+ if(o==0) {
+ h.pop_back();
+ h.push_back(points[i]);
+ } else if(o>0) {
+ h.push_back(points[i]);
+ } else {
+ while(o<=0 && h.size()>2) {
+ h.pop_back();
+ o=crossProduct(
+ X[h[h.size()-2]],Y[h[h.size()-2]],
+ X[h[h.size()-1]],Y[h[h.size()-1]],
+ X[points[i]],Y[points[i]]);
+ }
+ h.push_back(points[i]);
+ }
+ }
+}
+
+} // namespace hull
diff --git a/src/3rdparty/adaptagrams/libcola/convex_hull.h b/src/3rdparty/adaptagrams/libcola/convex_hull.h
new file mode 100644
index 0000000..e17c6a8
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/convex_hull.h
@@ -0,0 +1,31 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+*/
+
+#ifndef CONVEX_HULL_H
+#define CONVEX_HULL_H
+#include <vector>
+#include <valarray>
+
+namespace hull {
+void convex(const unsigned n, const double* X, const double* Y, std::vector<unsigned> & hull);
+void convex(const std::valarray<double> & X, const std::valarray<double> & Y, std::vector<unsigned> & hull);
+}
+
+#endif // CONVEX_HULL_H
diff --git a/src/3rdparty/adaptagrams/libcola/doc/description.doc b/src/3rdparty/adaptagrams/libcola/doc/description.doc
new file mode 100644
index 0000000..cf8cdda
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/doc/description.doc
@@ -0,0 +1,50 @@
+/*!
+
+\if LIBCOLA_DOC
+@mainpage libcola: Force-directed Network Layout ubject to Separation Constraints
+\endif
+\if ADAPTAGRAMS_DOC
+@page libcola libcola &mdash; Overview
+\endif
+
+libcola is a cross-platform C++ library for constraint graph layout. Specifically, force-directed layout using the stress-majorization method subject to separation constraints. Applications include layout with non-overlapping nodes and clusters, directed graph layout and layout preserving the crossing properties of a given starting layout.
+
+libcola is part of the
+<a href="http://www.adaptagrams.org/">Adaptagrams project</a>.
+There are no official releases yet, though the code is stable and
+available from the Adaptagrams
+<a href="https://github.com/mjwybrow/adaptagrams">GitHub
+repository</a>.
+
+The API is documented using Doxygen. The documentation you are currently
+reading can be obtained by running doxygen in the cola directory.
+
+libcola is written and maintained by
+<a href="http://users.monash.edu/~mwybrow/">Michael Wybrow</a> and
+<a href="http://ialab.it.monash.edu/~dwyer/">Tim Dwyer</a>,
+members of <a href="http://ialab.it.monash.edu/">Immersive Analytics Lab</a> at Monash University, Australia.
+
+The algorithms used for ConstrainedFDLayout are described in the following papers. If you use libcola, please cite the relevant paper.
+- Tim Dwyer, Kim Marriott, and Michael Wybrow. Topology preserving
+ constrained graph layout. In Proc. 16th Intl. Symp. Graph Drawing
+ (GD'08), volume 5417 of Lecture Notes in Computer Science, pages
+ 230-241. Springer, 2009.
+- Tim Dwyer, Kim Marriott, and Michael Wybrow. Dunnart: A
+ constraint-based network diagram authoring tool. In Proc. 16th Intl.
+ Symp. Graph Drawing (GD'08), volume 5417 of Lecture Notes in Computer
+ Science, pages 420-431. Springer, 2009.
+- Tim Dwyer, Kim Marriott, Falk Schreiber, Peter J. Stuckey,
+ Michael Woodward, and Michael Wybrow. Exploration of networks using
+ overview+detail with constraint-based cooperative layout. IEEE
+ Transactions on Visualization and Computer Graphics, 14(6):1293-1300,
+ 2008.
+
+The method used in ConstrainedMajorizationLayout is described in:
+- Tim Dwyer and Kim Marriott. Constrained stress majorization using diagonally
+ scaled gradient projection. In Proc. 15th Intl. Symp. Graph Drawing (GD
+ '07), volume 4875 of Lecture Notes in Computer Science. Springer, 2008.
+
+
+*/
+
+
diff --git a/src/3rdparty/adaptagrams/libcola/exceptions.h b/src/3rdparty/adaptagrams/libcola/exceptions.h
new file mode 100644
index 0000000..516e69e
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/exceptions.h
@@ -0,0 +1,54 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+*/
+
+#ifndef SEEN_LIBCOLA_EXCEPTIONS_H
+#define SEEN_LIBCOLA_EXCEPTIONS_H
+#include <string>
+#include <sstream>
+
+namespace cola {
+class CompoundConstraint;
+
+struct InvalidConstraint {
+ InvalidConstraint(CompoundConstraint *c):constraint(c) {}
+ CompoundConstraint *constraint;
+};
+
+
+class InvalidVariableIndexException
+{
+public:
+ InvalidVariableIndexException(CompoundConstraint *c, unsigned i)
+ : constraint(c),
+ index(i)
+ { }
+ std::string what() const throw()
+ {
+ std::stringstream s;
+ s << "Invalid variable index: " << index;
+ return s.str();
+ }
+ CompoundConstraint *constraint;
+ unsigned index;
+};
+
+
+} // namespace cola
+#endif //SEEN_LIBCOLA_EXCEPTIONS_H
diff --git a/src/3rdparty/adaptagrams/libcola/gradient_projection.cpp b/src/3rdparty/adaptagrams/libcola/gradient_projection.cpp
new file mode 100644
index 0000000..b53e876
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/gradient_projection.cpp
@@ -0,0 +1,482 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+*/
+
+/**********************************************************
+ *
+ * Solve a quadratic function f(X) = X' A X + b X
+ * subject to a set of separation constraints cs
+ *
+ **********************************************************/
+
+#include <iostream>
+#include <cmath>
+#include <ctime>
+
+#include <libvpsc/solve_VPSC.h>
+#include <libvpsc/variable.h>
+#include <libvpsc/constraint.h>
+#include <libvpsc/assertions.h>
+
+#include "libcola/cluster.h"
+#include "libcola/gradient_projection.h"
+#include "libcola/straightener.h"
+#include "libcola/commondefs.h"
+//#define CHECK_CONVERGENCE_BY_COST 1
+
+
+using namespace std;
+using namespace vpsc;
+namespace cola {
+GradientProjection::GradientProjection(
+ const Dim k,
+ std::valarray<double> *denseQ,
+ const double tol,
+ const unsigned max_iterations,
+ CompoundConstraints const *ccs,
+ UnsatisfiableConstraintInfos *unsatisfiableConstraints,
+ NonOverlapConstraintsMode nonOverlapConstraints,
+ RootCluster* clusterHierarchy,
+ vpsc::Rectangles* rs,
+ const bool scaling,
+ SolveWithMosek solveWithMosek)
+ : k(k),
+ denseSize(static_cast<unsigned>((floor(sqrt(static_cast<double>(denseQ->size())))))),
+ denseQ(denseQ),
+ rs(rs),
+ ccs(ccs),
+ unsatisfiableConstraints(unsatisfiableConstraints),
+ nonOverlapConstraints(nonOverlapConstraints),
+ clusterHierarchy(clusterHierarchy),
+ tolerance(tol),
+ max_iterations(max_iterations),
+ sparseQ(nullptr),
+ solveWithMosek(solveWithMosek),
+ scaling(scaling)
+{
+ //printf("GP Instance: scaling=%d, mosek=%d\n",scaling,solveWithMosek);
+ for(unsigned i=0;i<denseSize;i++) {
+ vars.push_back(new vpsc::Variable(i,1,1));
+ }
+ if(scaling) {
+ scaledDenseQ.resize(denseSize*denseSize);
+ for(unsigned i=0;i<denseSize;i++) {
+ vars[i]->scale=1./sqrt(fabs((*denseQ)[i*denseSize+i]));
+ // XXX: Scale can sometimes be set to infinity here when
+ // there are nodes not connected to any other node.
+ // Thus we just set the scale for such a variable to 1.
+ if (!std::isfinite(vars[i]->scale))
+ {
+ vars[i]->scale = 1;
+ }
+ }
+ // the following computes S'QS for Q=denseQ
+ // and S is diagonal matrix of scale factors
+ for(unsigned i=0;i<denseSize;i++) {
+ for(unsigned j=0;j<denseSize;j++) {
+ scaledDenseQ[i*denseSize+j]=(*denseQ)[i*denseSize+j]*vars[i]->scale
+ *vars[j]->scale;
+ }
+ }
+ this->denseQ = &scaledDenseQ;
+ }
+ //dumpSquareMatrix(*this->denseQ);
+ //dumpSquareMatrix(scaledDenseQ);
+
+ if(ccs) {
+ for(CompoundConstraints::const_iterator c=ccs->begin();
+ c!=ccs->end();++c) {
+ (*c)->generateVariables(k, vars);
+ OrthogonalEdgeConstraint* e=dynamic_cast<OrthogonalEdgeConstraint*>(*c);
+ if(e) {
+ orthogonalEdges.push_back(e);
+ }
+ }
+ for(CompoundConstraints::const_iterator c=ccs->begin();
+ c!=ccs->end();++c) {
+ (*c)->generateSeparationConstraints(k, vars, gcs, *rs);
+ }
+ }
+ /*
+ if(clusterHierarchy) {
+ clusterHierarchy->createVars(k,*rs,vars);
+ }
+ */
+ numStaticVars=vars.size();
+ //solver=setupVPSC();
+}
+static inline double dotProd(valarray<double> const & a, valarray<double> const & b) {
+ double p = 0;
+ for (unsigned i=0; i<a.size(); i++) {
+ p += a[i]*b[i];
+ }
+ return p;
+}
+double GradientProjection::computeCost(
+ valarray<double> const &b,
+ valarray<double> const &x) const {
+ // computes cost = 2 b x - x A x
+ double cost = 2. * dotProd(b,x);
+ valarray<double> Ax(x.size());
+ for (unsigned i=0; i<denseSize; i++) {
+ Ax[i] = 0;
+ for (unsigned j=0; j<denseSize; j++) {
+ Ax[i] += (*denseQ)[i*denseSize+j]*x[j];
+ }
+ }
+ if(sparseQ) {
+ valarray<double> r(x.size());
+ sparseQ->rightMultiply(x,r);
+ Ax+=r;
+ }
+ return cost - dotProd(x,Ax);
+}
+
+double GradientProjection::computeSteepestDescentVector(
+ valarray<double> const &b,
+ valarray<double> const &x,
+ valarray<double> &g) const {
+ // find steepest descent direction
+ // g = 2 ( b - A x )
+ // where: A = denseQ + sparseQ
+ // g = 2 ( b - denseQ x) - 2 sparseQ x
+ //
+ // except the 2s don't matter because we compute
+ // the optimal stepsize anyway
+ COLA_ASSERT(x.size()==b.size() && b.size()==g.size());
+ g = b;
+ for (unsigned i=0; i<denseSize; i++) {
+ for (unsigned j=0; j<denseSize; j++) {
+ g[i] -= (*denseQ)[i*denseSize+j]*x[j];
+ }
+ }
+ // sparse part:
+ if(sparseQ) {
+ valarray<double> r(x.size());
+ sparseQ->rightMultiply(x,r);
+ g-=r;
+ }
+ return computeStepSize(g,g);
+}
+// compute optimal step size along descent vector d relative to
+// a gradient related vector g
+// stepsize = ( g' d ) / ( d' A d )
+double GradientProjection::computeStepSize(
+ valarray<double> const & g, valarray<double> const & d) const {
+ COLA_ASSERT(g.size()==d.size());
+ valarray<double> Ad;
+ if(sparseQ) {
+ Ad.resize(g.size());
+ sparseQ->rightMultiply(d,Ad);
+ }
+ double const numerator = dotProd(g, d);
+ double denominator = 0;
+ for (unsigned i=0; i<g.size(); i++) {
+ double r = sparseQ ? Ad[i] : 0;
+ if(i<denseSize) { for (unsigned j=0; j<denseSize; j++) {
+ r += (*denseQ)[i*denseSize+j] * d[j];
+ } }
+ denominator += r * d[i];
+ }
+ if(denominator==0) {
+ return 0;
+ }
+ return numerator/(2.*denominator);
+}
+
+bool GradientProjection::runSolver(valarray<double> & result) {
+ bool activeConstraints = false;
+ switch(solveWithMosek) {
+ case Off:
+ activeConstraints = solver->satisfy();
+ for (unsigned i=0;i<vars.size();i++) {
+ result[i]=vars[i]->finalPosition;
+ }
+ break;
+ case Inner:
+#ifdef MOSEK_AVAILABLE
+ float *ba=new float[vars.size()];
+ float *coords=new float[vars.size()];
+ for(unsigned i=0;i<vars.size();i++) {
+ ba[i]=vars[i]->desiredPosition;
+ }
+ mosek_quad_solve_sep(menv,ba,coords);
+ for(unsigned i=0;i<vars.size();i++) {
+ //printf("x[%d]=%f\n",i,coords[i]);
+ result[i]=coords[i];
+ }
+ delete [] ba;
+ delete [] coords;
+ break;
+#endif
+ default:
+ break;
+ }
+ return activeConstraints;
+}
+
+/*
+ * Use gradient-projection to solve an instance of
+ * the Variable Placement with Separation Constraints problem.
+ */
+unsigned GradientProjection::solve(
+ valarray<double> const &linearCoefficients,
+ valarray<double> &x) {
+ COLA_ASSERT(linearCoefficients.size()==x.size());
+ COLA_ASSERT(x.size()==denseSize);
+ COLA_ASSERT(numStaticVars>=denseSize);
+ COLA_ASSERT(sparseQ==nullptr ||
+ (sparseQ!=nullptr && (vars.size()==sparseQ->rowSize())) );
+
+ if(max_iterations==0) return 0;
+
+ bool converged=false;
+
+ solver = setupVPSC();
+#ifdef MOSEK_AVAILABLE
+ if(solveWithMosek==Outer) {
+ float* ba=new float[vars.size()];
+ float* xa=new float[vars.size()];
+ for(unsigned i=0;i<vars.size();i++) {
+ ba[i]=-linearCoefficients[i];
+ }
+ mosek_quad_solve_sep(menv,ba,xa);
+ for(unsigned i=0;i<vars.size();i++) {
+ //printf("mosek result x[%d]=%f\n",i,xa[i]);
+ x[i]=xa[i];
+ }
+ delete [] ba;
+ delete [] xa;
+ return 1;
+ }
+#endif
+ // it may be that we have to consider dummy vars, which the caller didn't know
+ // about. Thus vars.size() may not equal x.size()
+ unsigned n = vars.size();
+ valarray<double> b(n);
+ result.resize(n);
+
+ // load desired positions into vars, note that we keep desired positions
+ // already calculated for dummy vars
+ for (unsigned i=0;i<x.size();i++) {
+ COLA_ASSERT(!std::isnan(x[i]));
+ COLA_ASSERT(std::isfinite(x[i]));
+ b[i]=i<linearCoefficients.size()?linearCoefficients[i]:0;
+ result[i]=x[i];
+ if(scaling) {
+ b[i]*=vars[i]->scale;
+ result[i]/=vars[i]->scale;
+ }
+ if(!vars[i]->fixedDesiredPosition) vars[i]->desiredPosition=result[i];
+ }
+ runSolver(result);
+
+ valarray<double> g(n); /* gradient */
+ valarray<double> previous(n); /* stored positions */
+ valarray<double> d(n); /* actual descent vector */
+
+#ifdef CHECK_CONVERGENCE_BY_COST
+ double previousCost = DBL_MAX;
+#endif
+ unsigned counter=0;
+ double stepSize;
+ for (; counter<max_iterations&&!converged; counter++) {
+ previous=result;
+ stepSize=0;
+ double alpha=computeSteepestDescentVector(b,result,g);
+
+ //printf("Iteration[%d]\n",counter);
+ // move to new unconstrained position
+ for (unsigned i=0; i<n; i++) {
+ // dividing by variable weight is a cheap trick to make these
+ // weights mean something in terms of the descent vector
+ double step=alpha*g[i]/vars[i]->weight;
+ result[i]+=step;
+ //printf(" after unconstrained step: x[%d]=%f\n",i,result[i]);
+ stepSize+=step*step;
+ COLA_ASSERT(!std::isnan(result[i]));
+ COLA_ASSERT(std::isfinite(result[i]));
+ if(!vars[i]->fixedDesiredPosition) vars[i]->desiredPosition=result[i];
+ }
+
+ //project to constraint boundary
+ bool constrainedOptimum = false;
+ constrainedOptimum=runSolver(result);
+ stepSize=0;
+ for (unsigned i=0;i<n;i++) {
+ double step = previous[i]-result[i];
+ stepSize+=step*step;
+ }
+ //constrainedOptimum=false;
+ // beta seems, more often than not, to be >1!
+ if(constrainedOptimum) {
+ // The following step limits the step-size in the feasible
+ // direction
+ d = result - previous;
+ const double beta = 0.5*computeStepSize(g, d);
+ // beta > 1.0 takes us back outside the feasible region
+ // beta < 0 clearly not useful and may happen due to numerical imp.
+ //printf("beta=%f\n",beta);
+ if(beta>0&&beta<0.99999) {
+ stepSize=0;
+ for (unsigned i=0; i<n; i++) {
+ double step=beta*d[i];
+ result[i]=previous[i]+step;
+ stepSize+=step*step;
+ }
+ }
+ }
+#ifdef CHECK_CONVERGENCE_BY_COST
+ /* This would be the slow way to detect convergence */
+ //if(counter%2) {
+ double cost = computeCost(b,result);
+ printf(" gp[%d] %.15f %.15f\n",counter,previousCost,cost);
+ //COLA_ASSERT(previousCost>cost);
+ if(fabs(previousCost - cost) < tolerance) {
+ converged = true;
+ }
+ previousCost = cost;
+ //}
+#else
+ if(stepSize<tolerance) converged = true;
+#endif
+ }
+ //printf("GP[%d] converged after %d iterations.\n",k,counter);
+ for(unsigned i=0;i<x.size();i++) {
+ x[i]=result[i];
+ if(scaling) {
+ x[i]*=vars[i]->scale;
+ }
+ }
+ destroyVPSC(solver);
+ return counter;
+}
+// Setup an instance of the Variable Placement with Separation Constraints
+// for one iteration.
+// Generate transient local constraints --- such as non-overlap constraints
+// --- that are only relevant to one iteration, and merge these with the
+// global constraint list (including alignment constraints,
+// dir-edge constraints, containment constraints, etc).
+IncSolver* GradientProjection::setupVPSC() {
+ if(nonOverlapConstraints!=None) {
+ if(clusterHierarchy) {
+ //printf("Setup up cluster constraints, dim=%d--------------\n",k);
+ //clusterHierarchy->generateNonOverlapConstraints(k,nonOverlapConstraints,*rs,vars,lcs);
+ } else {
+ for(vector<OrthogonalEdgeConstraint*>::iterator i=orthogonalEdges.begin();i!=orthogonalEdges.end();i++) {
+ OrthogonalEdgeConstraint* e=*i;
+ e->generateTopologyConstraints(k,*rs,vars,lcs);
+ }
+ if(k==HORIZONTAL) {
+ // Make rectangles a little bit wider when processing horizontally so that any overlap
+ // resolved horizontally is strictly non-overlapping when processing vertically
+ Rectangle::setXBorder(0.0001);
+ // use rs->size() rather than n because some of the variables may
+ // be dummy vars with no corresponding rectangle
+ generateXConstraints(*rs,vars,lcs,nonOverlapConstraints==Both?true:false);
+ Rectangle::setXBorder(0);
+ } else {
+ generateYConstraints(*rs,vars,lcs);
+ }
+ }
+ }
+ cs=gcs;
+ cs.insert(cs.end(),lcs.begin(),lcs.end());
+ switch(solveWithMosek) {
+ case Off:
+ break;
+#ifdef MOSEK_AVAILABLE
+ case Inner:
+ menv = mosek_init_sep_ls(vars.size(),cs);
+ break;
+ case Outer:
+ unsigned n = vars.size();
+ float* lap = new float[n*(n+1)/2];
+ unsigned k=0;
+ for(unsigned i=0;i<n;i++) {
+ for(unsigned j=i;j<n;j++) {
+ lap[k]=(*denseQ)[i*n+j];
+ k++;
+ }
+ }
+ menv = mosek_init_sep(lap,n,cs,1);
+ delete [] lap;
+ break;
+#endif
+ default:
+ break;
+ }
+ return new IncSolver(vars,cs);
+}
+void GradientProjection::destroyVPSC(IncSolver *vpsc) {
+ if(ccs) {
+ for(CompoundConstraints::const_iterator c=ccs->begin();
+ c!=ccs->end();++c) {
+ (*c)->updatePosition(vpsc::XDIM);
+ (*c)->updatePosition(vpsc::YDIM);
+ }
+ }
+ if(unsatisfiableConstraints) {
+ unsatisfiableConstraints->clear();
+ for(Constraints::iterator i=cs.begin();i!=cs.end();i++) {
+ Constraint* c=*i;
+ if(c->unsatisfiable) {
+ UnsatisfiableConstraintInfo *ci = new UnsatisfiableConstraintInfo(c);
+ unsatisfiableConstraints->push_back(ci);
+ }
+ }
+ }
+ if(clusterHierarchy) {
+ clusterHierarchy->computeBoundary(*rs);
+ }
+ if(sparseQ) {
+ for(unsigned i=numStaticVars;i<vars.size();i++) {
+ delete vars[i];
+ }
+ vars.resize(numStaticVars);
+ sparseQ=nullptr;
+ }
+ for(vector<Constraint*>::iterator i=lcs.begin();i!=lcs.end();i++) {
+ delete *i;
+ }
+ lcs.clear();
+ delete vpsc;
+#ifdef MOSEK_AVAILABLE
+ if(solveWithMosek!=Off) mosek_delete(menv);
+#endif
+}
+void GradientProjection::straighten(
+ cola::SparseMatrix const * Q,
+ vector<SeparationConstraint*> const & cs,
+ vector<straightener::Node*> const & snodes)
+{
+ COLA_ASSERT(Q->rowSize()==snodes.size());
+ COLA_ASSERT(vars.size()==numStaticVars);
+ sparseQ = Q;
+ for(unsigned i=numStaticVars;i<snodes.size();i++) {
+ Variable* v=new vpsc::Variable(i,snodes[i]->pos[k],1);
+ COLA_ASSERT(v->desiredPosition==snodes[i]->pos[k]);
+ vars.push_back(v);
+ }
+ COLA_ASSERT(lcs.size()==0);
+ for(vector<SeparationConstraint*>::const_iterator i=cs.begin();i!=cs.end();i++) {
+ (*i)->generateSeparationConstraints(k, vars, lcs, *rs);
+ }
+}
+} // namespace cola
diff --git a/src/3rdparty/adaptagrams/libcola/gradient_projection.h b/src/3rdparty/adaptagrams/libcola/gradient_projection.h
new file mode 100644
index 0000000..0e85780
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/gradient_projection.h
@@ -0,0 +1,165 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+*/
+
+#ifndef _GRADIENT_PROJECTION_H
+#define _GRADIENT_PROJECTION_H
+
+#include <iostream>
+#include <cmath>
+#include <valarray>
+
+#include "libvpsc/solve_VPSC.h"
+#include "libvpsc/variable.h"
+#include "libvpsc/constraint.h"
+#include "libvpsc/rectangle.h"
+#include "libcola/commondefs.h"
+#include "libcola/compound_constraints.h"
+#include "libcola/cluster.h"
+#include "libcola/sparse_matrix.h"
+#ifdef MOSEK_AVAILABLE
+#include "libvpsc/mosek_quad_solve.h"
+#endif
+
+namespace straightener {
+ class Node;
+}
+namespace cola {
+
+enum SolveWithMosek { Off, Inner, Outer };
+
+class GradientProjection {
+public:
+ /**
+ * GradientProjection solves a linear system
+ * Qx=b
+ * subject to separation constraints.
+ * The usual use-case is with a dense square matrix (denseQ).
+ * However, certain CompoundConstraints and also clusters add dummy
+ * variables and simple goal terms which populate a sparse matrix
+ * sparseQ (constructed in this constructor).
+ * A motivated person could rewrite the constructor to allow
+ * arbitrary sparse terms (if they had a use for it).
+ */
+ GradientProjection(
+ const vpsc::Dim k,
+ std::valarray<double> *denseQ,
+ const double tol,
+ const unsigned max_iterations,
+ CompoundConstraints const *ccs,
+ UnsatisfiableConstraintInfos *unsatisfiableConstraints,
+ NonOverlapConstraintsMode nonOverlapConstraints = None,
+ RootCluster* clusterHierarchy = nullptr,
+ vpsc::Rectangles* rs = nullptr,
+ const bool scaling = false,
+ SolveWithMosek solveWithMosek = Off);
+ static void dumpSquareMatrix(std::valarray<double> const &L) {
+ unsigned n=static_cast<unsigned>(floor(sqrt(static_cast<double>(L.size()))));
+ printf("Matrix %dX%d\n{",n,n);
+ for(unsigned i=0;i<n;i++) {
+ printf("{");
+ for(unsigned j=0;j<n;j++) {
+ char c=j==n-1?'}':',';
+ printf("%f%c",1. * L[i*n+j],c);
+ }
+ char c=i==n-1?'}':',';
+ printf("%c\n",c);
+ }
+ }
+
+ unsigned getNumStaticVars() const {
+ return numStaticVars;
+ }
+ ~GradientProjection() {
+ //destroyVPSC(solver);
+ for(vpsc::Constraints::iterator i(gcs.begin()); i!=gcs.end(); i++) {
+ delete *i;
+ }
+ gcs.clear();
+ for(unsigned i=0;i<vars.size();i++) {
+ delete vars[i];
+ }
+ }
+ unsigned solve(std::valarray<double> const & b, std::valarray<double> & x);
+ void unfixPos(unsigned i) {
+ if(vars[i]->fixedDesiredPosition) {
+ vars[i]->weight=1;
+ vars[i]->fixedDesiredPosition=false;
+ }
+ }
+ void fixPos(const unsigned i,const double pos) {
+ vars[i]->weight=100000.;
+ vars[i]->desiredPosition=pos;
+ vars[i]->fixedDesiredPosition=true;
+ }
+ vpsc::Dim getDimension() const {
+ return k;
+ }
+ void straighten(
+ cola::SparseMatrix const * Q,
+ std::vector<SeparationConstraint*> const & ccs,
+ std::vector<straightener::Node*> const & snodes);
+ std::valarray<double> const & getFullResult() const {
+ return result;
+ }
+private:
+ vpsc::IncSolver* setupVPSC();
+ double computeCost(std::valarray<double> const &b,
+ std::valarray<double> const &x) const;
+ double computeSteepestDescentVector(
+ std::valarray<double> const &b, std::valarray<double> const &place,
+ std::valarray<double> &g) const;
+ double computeScaledSteepestDescentVector(
+ std::valarray<double> const &b, std::valarray<double> const &place,
+ std::valarray<double> &g) const;
+ double computeStepSize(
+ std::valarray<double> const & g, std::valarray<double> const & d) const;
+ bool runSolver(std::valarray<double> & result);
+ void destroyVPSC(vpsc::IncSolver *vpsc);
+ vpsc::Dim k;
+ unsigned numStaticVars; // number of variables that persist
+ // throughout iterations
+ const unsigned denseSize; // denseQ has denseSize^2 entries
+ std::valarray<double> *denseQ; // dense square graph laplacian matrix
+ std::valarray<double> scaledDenseQ; // scaled dense square graph laplacian matrix
+ std::vector<vpsc::Rectangle*>* rs;
+ CompoundConstraints const *ccs;
+ UnsatisfiableConstraintInfos *unsatisfiableConstraints;
+ NonOverlapConstraintsMode nonOverlapConstraints;
+ Cluster* clusterHierarchy;
+ double tolerance;
+ unsigned max_iterations;
+ cola::SparseMatrix const * sparseQ; // sparse components of goal function
+ vpsc::Variables vars; // all variables
+ // computations
+ vpsc::Constraints gcs; /* global constraints - persist throughout all
+ iterations */
+ vpsc::Constraints lcs; /* local constraints - only for current iteration */
+ vpsc::Constraints cs; /* working list of constraints: gcs +lcs */
+ std::valarray<double> result;
+#ifdef MOSEK_AVAILABLE
+ MosekEnv* menv;
+#endif
+ vpsc::IncSolver* solver;
+ SolveWithMosek solveWithMosek;
+ const bool scaling;
+ std::vector<OrthogonalEdgeConstraint*> orthogonalEdges;
+};
+} // namespace cola
+#endif /* _GRADIENT_PROJECTION_H */
diff --git a/src/3rdparty/adaptagrams/libcola/libcola.pc.in b/src/3rdparty/adaptagrams/libcola/libcola.pc.in
new file mode 100644
index 0000000..f9d0688
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/libcola.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libcola
+Description: A library for constraint graph layout
+URL: http://www.adaptagrams.org/
+Version: @VERSION@
+Libs: -L${libdir} -lcola
+Cflags: -I${includedir}/libcola
diff --git a/src/3rdparty/adaptagrams/libcola/output_svg.cpp b/src/3rdparty/adaptagrams/libcola/output_svg.cpp
new file mode 100644
index 0000000..cd564e6
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/output_svg.cpp
@@ -0,0 +1,389 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+*/
+
+#include <string>
+#include <iostream>
+#include <sstream>
+#include <list>
+
+#include "libcola/output_svg.h"
+#include "libcola/cola.h"
+#include "libcola/straightener.h"
+
+using namespace cola;
+using vpsc::Rectangle;
+using std::endl;
+using std::cout;
+using std::ios;
+using std::max;
+using std::min;
+using std::ofstream;
+using std::vector;
+using std::list;
+
+void OutputFile::generate() {
+ unsigned E=es.size();
+ bool cleanupRoutes=false;
+ if(routes==nullptr) {
+ cleanupRoutes=true;
+ routes = new vector<straightener::Route*>(E);
+ for(unsigned i=0;i<E;i++) {
+ straightener::Route* r=new straightener::Route(2);
+ r->xs[0]=rs[es[i].first]->getCentreX();
+ r->ys[0]=rs[es[i].first]->getCentreY();
+ r->xs[1]=rs[es[i].second]->getCentreX();
+ r->ys[1]=rs[es[i].second]->getCentreY();
+ (*routes)[i]=r;
+ }
+ }
+
+#if defined (CAIRO_HAS_SVG_SURFACE) && defined (CAIRO_HAS_PDF_SURFACE)
+ double width,height,r=2;
+ if(rects) r=rs[0]->width()/2;
+ double xmin=DBL_MAX, ymin=xmin;
+ double xmax=-DBL_MAX, ymax=xmax;
+ for (unsigned i=0;i<rs.size();i++) {
+ double x=rs[i]->getCentreX(), y=rs[i]->getCentreY();
+ xmin=min(xmin,x);
+ ymin=min(ymin,y);
+ xmax=max(xmax,x);
+ ymax=max(ymax,y);
+ }
+ xmax+=2*r;
+ ymax+=2*r;
+ xmin-=2*r;
+ ymin-=2*r;
+ width=xmax-xmin;
+ height=ymax-ymin;
+
+ Cairo::RefPtr<Cairo::Context> cr;
+ openCairo(cr,width,height);
+
+ /* set background colour
+ cr->save(); // save the state of the context
+ cr->set_source_rgb(0.86, 0.85, 0.47);
+ cr->paint(); // fill image with the color
+ cr->restore(); // color is back to black now
+ */
+
+ cr->set_line_width(1.);
+ cr->set_font_size(8);
+ cr->save();
+ if(rc) for(Clusters::const_iterator c=rc->clusters.begin();c!=rc->clusters.end();c++) {
+ draw_cluster_boundary(cr,**c,xmin,ymin);
+ }
+ if(curvedEdges)
+ draw_curved_edges(cr,es,xmin,ymin);
+ else
+ draw_edges(cr,*routes,xmin,ymin);
+ Cairo::TextExtents te;
+ for (unsigned i=0;i<rs.size();i++) {
+ if(!rects) {
+ double x=rs[i]->getCentreX()-xmin, y=rs[i]->getCentreY()-ymin;
+ cr->arc(x,y,r, 0.0, 2.0 * M_PI);
+ cr->fill();
+ } else {
+ double x=rs[i]->getMinX()-xmin+0.5, y=rs[i]->getMinY()-ymin+0.5;
+ std::string str;
+ if(labels.size()==rs.size()) {
+ str=labels[i];
+ } else {
+ std::stringstream s; s<<i;
+ str=s.str();
+ }
+ cr->get_text_extents(str,te);
+ /*
+ double llx = x-te.width/2.-1;
+ double lly = y-te.height/2.-1;
+ cr->rectangle(llx,lly,te.width+2,te.height+2);
+ */
+ cr->rectangle(x,y,
+ rs[i]->width()-1,rs[i]->height()-1);
+ cr->stroke_preserve();
+ cr->save();
+ cr->set_source_rgba(245./255., 233./255., 177./255., 0.6);
+ cr->fill();
+ cr->restore();
+ if(labels.size()==rs.size()) {
+ cr->move_to(x-te.x_bearing+te.width/2.,y-te.y_bearing+te.height/2.);
+ cr->show_text(str);
+ }
+ cr->stroke();
+ }
+ }
+
+ cr->show_page();
+
+ std::cout << "Wrote file \"" << fname << "\"" << std::endl;
+
+#else
+ std::cout <<
+ "WARNING: cola::OutputFile::generate(): No SVG file produced." <<
+ std::endl <<
+ " You must have cairomm (and cairo with SVG support) " <<
+ "this to work." << std::endl;
+#endif
+
+ if(cleanupRoutes) {
+ for(unsigned i=0;i<E;i++) {
+ delete (*routes)[i];
+ }
+ delete routes;
+ }
+}
+
+#ifdef HAVE_CAIROMM
+void OutputFile::draw_cluster_boundary(Cairo::RefPtr<Cairo::Context> const &cr,
+ Cluster &c,
+ const double xmin,
+ const double ymin) {
+ c.computeBoundary(rs);
+ cr->save();
+ // background
+ cr->set_source_rgb(0.7, 0.7, 224./255.);
+ cr->move_to(c.hullX[0]-xmin,c.hullY[0]-ymin);
+ for(unsigned i=1;i<c.hullX.size();i++) {
+ cr->line_to(c.hullX[i]-xmin,c.hullY[i]-ymin);
+ }
+ cr->line_to(c.hullX[0]-xmin,c.hullY[0]-ymin);
+ cr->fill();
+ cr->restore();
+ // outline
+ cr->move_to(c.hullX[0]-xmin,c.hullY[0]-ymin);
+ for(unsigned i=1;i<c.hullX.size();i++) {
+ cr->line_to(c.hullX[i]-xmin,c.hullY[i]-ymin);
+ }
+ cr->line_to(c.hullX[0]-xmin,c.hullY[0]-ymin);
+ cr->stroke();
+}
+
+void OutputFile::draw_edges(Cairo::RefPtr<Cairo::Context> &cr,
+ vector<straightener::Route*> const & es, double const xmin, double const ymin) {
+ cr->save();
+ // background
+ cr->set_source_rgba(0,0,1,0.5);
+ for (unsigned i=0;i<es.size();i++) {
+ const straightener::Route* r=es[i];
+ cr->move_to(r->xs[0]-xmin,r->ys[0]-ymin);
+ for (unsigned j=1;j<r->n;j++) {
+ cr->line_to(r->xs[j]-xmin,r->ys[j]-ymin);
+ }
+ cr->stroke();
+ }
+ cr->restore();
+}
+
+namespace bundles {
+struct CEdge {
+ unsigned startID, endID;
+ double x0,y0,x1,y1,x2,y2,x3,y3;
+};
+struct CBundle;
+struct CNode {
+ double x,y;
+ vector<CEdge*> edges;
+ list<CBundle*> bundles;
+};
+double vangle(double ax,double ay, double bx, double by) {
+ double ab=ax*bx+ay*by;
+ double len=sqrt(ax*ax+ay*ay)*sqrt(bx*bx+by*by);
+ double angle=acos(ab/len);
+ //printf("ab=%f len=%f angle=%f\n",ab,len,angle);
+ return angle;
+}
+struct CBundle {
+ unsigned w;
+ double x0, y0;
+ double sx,sy;
+ vector<CEdge*> edges;
+ CBundle(CNode const &u) : w(u.edges.size()), x0(u.x), y0(u.y), sx(w*u.x), sy(w*u.y) { }
+ void addEdge(CEdge *e) {
+ if(x0==e->x0 && y0==e->y0) {
+ sx+=e->x3; sy+=e->y3;
+ } else {
+ sx+=e->x0; sy+=e->y0;
+ }
+ edges.push_back(e);
+ }
+ double x1() const {
+ return sx/(w+edges.size());
+ }
+ double y1() const {
+ return sy/(w+edges.size());
+ }
+ double angle(CBundle* const &b) const {
+ double ax=x1()-x0;
+ double ay=y1()-y0;
+ double bx=b->x1()-b->x0;
+ double by=b->y1()-b->y0;
+ return vangle(ax,ay,bx,by);
+ }
+ double yangle() const {
+ double x=x1()-x0;
+ double y=y1()-y0;
+ double o=x<0?1:-1;
+ return vangle(0,1,x,y)*o+M_PI;
+ }
+ void merge(CBundle* b) {
+ for(unsigned i=0;i<b->edges.size();i++) {
+ addEdge(b->edges[i]);
+ }
+ }
+ void dump() {
+ printf("Bundle: ");
+ for(unsigned i=0;i<edges.size();i++) {
+ printf("(%d,%d) ",edges[i]->startID,edges[i]->endID);
+ }
+ }
+};
+struct clockwise {
+ bool operator() (CBundle* const &a, CBundle* const &b) {
+ return a->yangle()<b->yangle();
+ }
+};
+} //namespace bundles
+
+/*
+ * draw edges bundled. That is, edges are drawn as splines, with the control points
+ * between adjacent edges outgoing from a particular node shared if the angle between them
+ * is less than pi/8
+ */
+void OutputFile::draw_curved_edges(Cairo::RefPtr<Cairo::Context> &cr,
+ vector<cola::Edge> const & es,
+ const double xmin,
+ const double ymin) {
+ using namespace bundles;
+ vector<CNode> nodes(rs.size());
+ vector<CEdge> edges(es.size());
+ for (unsigned i=0;i<es.size();i++) {
+ CEdge *e=&edges[i];
+ unsigned start=es[i].first;
+ unsigned end=es[i].second;
+ e->startID=start;
+ e->endID=end;
+ nodes[start].x=rs[start]->getCentreX()-xmin;
+ nodes[start].y=rs[start]->getCentreY()-ymin;
+ nodes[end].x=rs[end]->getCentreX()-xmin;
+ nodes[end].y=rs[end]->getCentreY()-ymin;
+ e->x0=nodes[start].x;
+ e->x1=nodes[start].x;
+ e->x2=nodes[end].x;
+ e->x3=nodes[end].x;
+ e->y0=nodes[start].y;
+ e->y1=nodes[start].y;
+ e->y2=nodes[end].y;
+ e->y3=nodes[end].y;
+ nodes[end].edges.push_back(e);
+ nodes[start].edges.push_back(e);
+ }
+
+ for (unsigned i=0;i<nodes.size();i++) {
+ CNode u=nodes[i];
+ if(u.edges.size()<2) continue;
+ for (unsigned j=0;j<u.edges.size();j++) {
+ CBundle* b=new CBundle(u);
+ b->addEdge(u.edges[j]);
+ u.bundles.push_back(b);
+ }
+ u.bundles.sort(clockwise());
+ /*
+ printf("Sorted: \n");
+ list<CBundle*>::iterator i,j;
+ for(list<CBundle*>::iterator i=u.bundles.begin();i!=u.bundles.end();i++) {
+ CBundle* a=*i;
+ a->dump();
+ printf(" angle=%f\n",a->yangle());
+ }
+ printf("---------\n");
+ */
+ while(true) {
+ double minAngle=DBL_MAX;
+ list<CBundle*>::iterator mini,minj,i,j;
+ for(i=u.bundles.begin();i!=u.bundles.end();i++) {
+ j=i;
+ if(++j==u.bundles.end()) {
+ j=u.bundles.begin();
+ }
+ CBundle* a=*i;
+ CBundle* b=*j;
+ double angle=b->yangle()-a->yangle();
+ if(angle<0) angle+=2*M_PI;
+ //printf("between ");
+ //a->dump(); b->dump();
+ //printf(" angle=%f\n",angle);
+ if(angle<minAngle) {
+ minAngle=angle;
+ mini=i;
+ minj=j;
+ }
+ }
+ if(minAngle>cos(M_PI/8.)) break;
+ CBundle* a=*mini;
+ CBundle* b=*minj;
+ //a->dump();
+ //b->dump();
+ b->merge(a);
+ //printf("***Merged on %f***: ",minAngle);
+ //b->dump();
+ //printf("\n");
+ u.bundles.erase(mini);
+ if(u.bundles.size() < 2) break;
+ }
+ for(list<CBundle*>::iterator i=u.bundles.begin();i!=u.bundles.end();i++) {
+ CBundle* b=*i;
+ for(unsigned i=0;i<b->edges.size();i++) {
+ CEdge* e=b->edges[i];
+ if(e->x0==u.x&&e->y0==u.y) {
+ e->x1=b->x1();
+ e->y1=b->y1();
+ } else {
+ e->x2=b->x1();
+ e->y2=b->y1();
+ }
+ }
+ }
+ }
+
+ cr->save();
+ // background
+ cr->set_source_rgba(0,0,1,0.2);
+ for (unsigned i=0;i<edges.size();i++) {
+ CEdge &e=edges[i];
+ cr->move_to(e.x0,e.y0);
+ cr->curve_to(e.x1,e.y1,e.x2,e.y2,e.x3,e.y3);
+ cr->stroke();
+ }
+ cr->restore();
+}
+void OutputFile::openCairo(Cairo::RefPtr<Cairo::Context> &cr, double width, double height) {
+ if(fname.rfind("pdf") == (fname.length()-3) ) {
+ printf("writing pdf file: %s\n",fname.c_str());
+ Cairo::RefPtr<Cairo::PdfSurface> pdfsurface =
+ Cairo::PdfSurface::create(fname, width, height);
+ cr = Cairo::Context::create(pdfsurface);
+ } else {
+ printf("writing svg file: %s\n",fname.c_str());
+ Cairo::RefPtr<Cairo::SvgSurface> svgsurface =
+ Cairo::SvgSurface::create(fname, width, height);
+ cr = Cairo::Context::create(svgsurface);
+ }
+}
+
+#endif // HAVE_CAIROMM
diff --git a/src/3rdparty/adaptagrams/libcola/output_svg.h b/src/3rdparty/adaptagrams/libcola/output_svg.h
new file mode 100644
index 0000000..d68f161
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/output_svg.h
@@ -0,0 +1,80 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+*/
+
+#ifndef _OUTPUT_SVG_H
+#define _OUTPUT_SVG_H
+
+#include "libcola/config.h"
+#include "libcola/cola.h"
+
+#ifdef HAVE_CAIROMM
+#include <cairomm/context.h>
+#include <cairomm/surface.h>
+#endif
+
+class OutputFile {
+public:
+ std::vector<vpsc::Rectangle*> const &rs;
+ std::vector<cola::Edge> const &es;
+ std::vector<straightener::Route*> *routes;
+ cola::RootCluster const * rc;
+ std::string const fname;
+ bool rects;
+ bool curvedEdges;
+ OutputFile(std::vector<vpsc::Rectangle*> const &rs,
+ std::vector<cola::Edge> const &es,
+ cola::RootCluster const * rc,
+ std::string const fname,
+ const bool rects=false,
+ const bool curvedEdges=false)
+ : rs(rs),
+ es(es),
+ routes(nullptr),
+ rc(rc),
+ fname(fname),
+ rects(rects),
+ curvedEdges(curvedEdges) {}
+ void generate();
+ void setLabels(std::vector<std::string> ls) {
+ labels.resize(ls.size());
+ std::copy(ls.begin(),ls.end(),labels.begin());
+ }
+ void setLabels(const unsigned n, const char **ls) {
+ labels.resize(n);
+ for(unsigned i=0;i<n;i++) {
+ labels[i]=ls[i];
+ }
+ }
+private:
+#ifdef HAVE_CAIROMM
+ void draw_cluster_boundary(Cairo::RefPtr<Cairo::Context> const &cr,
+ cola::Cluster &c, const double xmin, const double ymin);
+ void draw_edges(Cairo::RefPtr<Cairo::Context> &cr,
+ std::vector<straightener::Route*> const & es,
+ double const xmin, double const ymin);
+ void draw_curved_edges(Cairo::RefPtr<Cairo::Context> &cr,
+ std::vector<cola::Edge> const & es,
+ const double xmin,
+ const double ymin);
+ void openCairo(Cairo::RefPtr<Cairo::Context> &cr, double width, double height);
+#endif // HAVE_CAIROMM
+ std::vector<std::string> labels;
+};
+#endif // _OUTPUT_SVG_H
diff --git a/src/3rdparty/adaptagrams/libcola/pseudorandom.cpp b/src/3rdparty/adaptagrams/libcola/pseudorandom.cpp
new file mode 100644
index 0000000..6577b3a
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/pseudorandom.cpp
@@ -0,0 +1,48 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2015 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+*/
+
+#include "libcola/pseudorandom.h"
+
+namespace cola {
+
+PseudoRandom::PseudoRandom(double s)
+ : a(214013),
+ c(2531011),
+ m(2147483648),
+ range(32767),
+ seed(s)
+{
+}
+
+double PseudoRandom::getNext(void)
+{
+ seed = (seed * a + c) % m;
+ return (seed >> 16) / range;
+}
+
+double PseudoRandom::getNextBetween(double min, double max)
+{
+ return min + getNext() * (max - min);
+}
+
+
+}
+
diff --git a/src/3rdparty/adaptagrams/libcola/pseudorandom.h b/src/3rdparty/adaptagrams/libcola/pseudorandom.h
new file mode 100644
index 0000000..bb3b269
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/pseudorandom.h
@@ -0,0 +1,44 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2015 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+*/
+
+#ifndef COLA_PSEUDORANDOM_H
+#define COLA_PSEUDORANDOM_H
+
+namespace cola {
+
+class PseudoRandom
+{
+public:
+ PseudoRandom(double s = 1);
+
+ double getNext(void);
+ double getNextBetween(double min, double max);
+
+private:
+ int a;
+ int c;
+ unsigned int m;
+ double range;
+ unsigned int seed;
+};
+
+}
+#endif // COLA_PSEUDORANDOM_H
diff --git a/src/3rdparty/adaptagrams/libcola/shapepair.cpp b/src/3rdparty/adaptagrams/libcola/shapepair.cpp
new file mode 100644
index 0000000..5673322
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/shapepair.cpp
@@ -0,0 +1,47 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+ *
+*/
+
+#include "libvpsc/assertions.h"
+
+#include "libcola/shapepair.h"
+
+namespace cola {
+
+ShapePair::ShapePair(unsigned ind1, unsigned ind2)
+{
+ COLA_ASSERT(ind1 != ind2);
+ // Assign the lesser value to m_index1.
+ m_index1 = (ind1 < ind2) ? ind1 : ind2;
+ // Assign the greater value to m_index2.
+ m_index2 = (ind1 > ind2) ? ind1 : ind2;
+}
+
+bool ShapePair::operator<(const ShapePair& rhs) const
+{
+ if (m_index1 != rhs.m_index1)
+ {
+ return m_index1 < rhs.m_index1;
+ }
+ return m_index2 < rhs.m_index2;
+}
+
+};
diff --git a/src/3rdparty/adaptagrams/libcola/shapepair.h b/src/3rdparty/adaptagrams/libcola/shapepair.h
new file mode 100644
index 0000000..7c122cb
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/shapepair.h
@@ -0,0 +1,49 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Michael Wybrow
+ *
+*/
+
+#ifndef COLA_SHAPEPAIR_H
+#define COLA_SHAPEPAIR_H
+
+namespace cola {
+
+// A pair of indexes.
+// Specified unordered but stored ordered so it can be compared and
+// stored in a set.
+//
+class ShapePair
+{
+ public:
+ ShapePair(unsigned ind1, unsigned ind2);
+ bool operator<(const ShapePair& rhs) const;
+ unsigned short index1(void) const {return m_index1;}
+ unsigned short index2(void) const {return m_index2;}
+
+ private:
+ unsigned short m_index1;
+ unsigned short m_index2;
+};
+
+
+};
+
+#endif
+
diff --git a/src/3rdparty/adaptagrams/libcola/shortest_paths.h b/src/3rdparty/adaptagrams/libcola/shortest_paths.h
new file mode 100644
index 0000000..22b54e3
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/shortest_paths.h
@@ -0,0 +1,245 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2014 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+*/
+
+#ifndef SHORTEST_PATHS_H
+#define SHORTEST_PATHS_H
+
+#include <vector>
+#include <valarray>
+#include <cfloat>
+#include <cassert>
+#include <algorithm>
+#include <iostream>
+#include <limits>
+
+#include "libcola/commondefs.h"
+#include <libvpsc/pairing_heap.h>
+#include <libvpsc/assertions.h>
+
+template <class T>
+struct PairNode;
+
+namespace shortest_paths {
+
+template <typename T>
+struct Node {
+ unsigned id;
+ T d;
+ Node* p; // predecessor
+ std::vector<Node<T>*> neighbours;
+ std::vector<T> nweights;
+ PairNode<Node<T>*>* qnode;
+};
+template <typename T>
+struct CompareNodes {
+ bool operator() (Node<T> *const &u, Node<T> *const &v) const {
+ if(u==v) return false; // with g++ 4.1.2 unless I have this explicit check
+ // it returns true for this case when using -O3 optimization
+ // CRAZY!
+ if(u->d < v->d) {
+ return true;
+ }
+ return false;
+ }
+};
+
+typedef std::pair<unsigned,unsigned> Edge;
+template <typename T>
+/**
+ * returns the adjacency matrix, 0 entries for non-adjacent nodes
+ * @param n total number of nodes
+ * @param D n*n matrix of shortest paths
+ * @param es edge pairs
+ * @param eweights edge weights, if empty then all weights will be taken as 1
+ */
+void neighbours(unsigned const n, T** D, std::vector<Edge> const & es,
+ std::valarray<T> const & eweights = std::valarray<T>());
+/**
+ * find all pairs shortest paths, n^3 dynamic programming approach
+ * @param n total number of nodes
+ * @param D n*n matrix of shortest paths
+ * @param es edge pairs
+ * @param eweights edge weights, if empty then all weights will be taken as 1
+ */
+template <typename T>
+void floyd_warshall(unsigned const n, T** D, std::vector<Edge> const & es,
+ std::valarray<T> const & eweights = std::valarray<T>());
+
+/**
+ * find all pairs shortest paths, faster, uses dijkstra
+ * @param n total number of nodes
+ * @param D n*n matrix of shortest paths
+ * @param es edge pairs
+ * @param eweights edge weights, if empty then all weights will be taken as 1
+ */
+template <typename T>
+void johnsons(unsigned const n, T** D, std::vector<Edge> const & es,
+ std::valarray<T> const & eweights = std::valarray<T>());
+/**
+ * find shortest path lengths from node s to all other nodes
+ * @param s starting node
+ * @param n total number of nodes
+ * @param d n vector of path lengths
+ * @param es edge pairs
+ * @param eweights edge weights, if empty then all weights will be taken as 1
+ */
+template <typename T>
+void dijkstra(unsigned const s, unsigned const n, T* d,
+ std::vector<Edge> const & es,
+ std::valarray<T> const & eweights = std::valarray<T>());
+
+
+//-----------------------------------------------------------------------------
+// Implementation:
+
+// O(n^3) time dynamic programming approach. Slow, but fool proof.
+// Use for testing.
+template <typename T>
+void floyd_warshall(
+ unsigned const n,
+ T** D,
+ std::vector<Edge> const & es,
+ std::valarray<T> const & eweights)
+{
+ COLA_ASSERT((eweights.size() == 0) || (eweights.size() == es.size()));
+ for(unsigned i=0;i<n;i++) {
+ for(unsigned j=0;j<n;j++) {
+ if(i==j) D[i][j]=0;
+ else D[i][j]=std::numeric_limits<T>::max();
+ }
+ }
+ for(unsigned i=0;i<es.size();i++) {
+ unsigned u=es[i].first, v=es[i].second;
+ COLA_ASSERT(u<n&&v<n);
+ D[u][v] = D[v][u] = (eweights.size() > 0) ? eweights[i] : 1;
+ }
+ for(unsigned k=0; k<n; k++) {
+ for(unsigned i=0; i<n; i++) {
+ for(unsigned j=0; j<n; j++) {
+ D[i][j]=std::min(D[i][j],D[i][k]+D[k][j]);
+ }
+ }
+ }
+}
+// Simply returns the adjacency graph
+template <typename T>
+void neighbours(
+ unsigned const n,
+ T** D,
+ std::vector<Edge> const & es,
+ std::valarray<T> const & eweights)
+{
+ COLA_ASSERT((eweights.size() == 0) || (eweights.size() == es.size()));
+ for(unsigned i=0;i<n;i++) {
+ for(unsigned j=0;j<n;j++) {
+ D[i][j]=0;
+ }
+ }
+ for(unsigned i=0;i<es.size();i++) {
+ unsigned u=es[i].first, v=es[i].second;
+ COLA_ASSERT(u<n&&v<n);
+ D[u][v] = D[v][u] = (eweights.size() > 0) ? eweights[i] : 1;
+ }
+}
+template <typename T>
+void dijkstra_init(
+ std::vector<Node<T> > & vs,
+ std::vector<Edge> const& es,
+ std::valarray<T> const & eweights) {
+ COLA_ASSERT((eweights.size() == 0) || (eweights.size() == es.size()));
+#ifndef NDEBUG
+ const unsigned n=vs.size();
+#endif
+ for(unsigned i=0;i<es.size();i++) {
+ unsigned u=es[i].first, v=es[i].second;
+ COLA_ASSERT(u<n);
+ COLA_ASSERT(v<n);
+ T w = (eweights.size() > 0) ? eweights[i] : 1;
+ vs[u].neighbours.push_back(&vs[v]);
+ vs[u].nweights.push_back(w);
+ vs[v].neighbours.push_back(&vs[u]);
+ vs[v].nweights.push_back(w);
+ }
+}
+template <typename T>
+void dijkstra(
+ unsigned const s,
+ std::vector<Node<T> > & vs,
+ T* d)
+{
+ const unsigned n=vs.size();
+ COLA_ASSERT(s<n);
+ for(unsigned i=0;i<n;i++) {
+ vs[i].id=i;
+ vs[i].d=std::numeric_limits<T>::max();
+ vs[i].p=nullptr;
+ }
+ vs[s].d=0;
+ PairingHeap<Node<T>*,CompareNodes<T> > Q;
+ for(unsigned i=0;i<n;i++) {
+ vs[i].qnode = Q.insert(&vs[i]);
+ }
+ while(!Q.isEmpty()) {
+ Node<T> *u=Q.extractMin();
+ d[u->id]=u->d;
+ for(unsigned i=0;i<u->neighbours.size();i++) {
+ Node<T> *v=u->neighbours[i];
+ T w=u->nweights[i];
+ if(u->d!=std::numeric_limits<T>::max()
+ && v->d > u->d+w) {
+ v->p=u;
+ v->d=u->d+w;
+ Q.decreaseKey(v->qnode,v);
+ }
+ }
+ }
+}
+template <typename T>
+void dijkstra(
+ unsigned const s,
+ unsigned const n,
+ T* d,
+ std::vector<Edge> const & es,
+ std::valarray<T> const & eweights)
+{
+ COLA_ASSERT((eweights.size() == 0) || (eweights.size() == es.size()));
+ COLA_ASSERT(s<n);
+ std::vector<Node<T> > vs(n);
+ dijkstra_init(vs,es,eweights);
+ dijkstra(s,vs,d);
+}
+
+template <typename T>
+void johnsons(
+ unsigned const n,
+ T** D,
+ std::vector<Edge> const & es,
+ std::valarray<T> const & eweights)
+{
+ std::vector<Node<T> > vs(n);
+ dijkstra_init(vs,es,eweights);
+ for(unsigned k=0;k<n;k++) {
+ dijkstra(k,vs,D[k]);
+ }
+}
+
+} //namespace shortest_paths
+#endif //SHORTEST_PATHS_H
diff --git a/src/3rdparty/adaptagrams/libcola/sparse_matrix.h b/src/3rdparty/adaptagrams/libcola/sparse_matrix.h
new file mode 100644
index 0000000..f4ec858
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/sparse_matrix.h
@@ -0,0 +1,140 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+*/
+
+/*
+ * Yale Sparse Matrix implementation (from Wikipedia definition).
+ * It stores an initial sparse n×n matrix M in row form using three arrays, A,
+ * IA, JA. NZ denotes the number of nonzero entries in matrix M. The array A
+ * then is of length NZ and holds all nonzero entries of M. The array IA stores
+ * at IA(i) the position of the first element of row i in the sparse array A.
+ * The length of row i is determined by IA(i+1) - IA(i). Therefore IA needs to
+ * be of length N + 1. In array JA, the column index of the element A(j) is
+ * stored. JA is of length NZ.
+ */
+#ifndef _SPARSE_MATRIX_H
+#define _SPARSE_MATRIX_H
+
+#include <valarray>
+#include <map>
+#include <cstdio>
+
+#include "libvpsc/assertions.h"
+
+namespace cola {
+struct SparseMap {
+ SparseMap(unsigned n = 0) : n(n) {};
+ unsigned n;
+ typedef std::pair<unsigned, unsigned> SparseIndex;
+ typedef std::map<SparseIndex,double> SparseLookup;
+ typedef SparseLookup::const_iterator ConstIt;
+ SparseLookup lookup;
+ double& operator[](const SparseIndex& k) {
+ return lookup[k];
+ }
+ double& operator()(const unsigned i, const unsigned j) {
+ return lookup[std::make_pair(i,j)];
+ }
+ double getIJ(const unsigned i, const unsigned j) const {
+ COLA_ASSERT(i<n);
+ COLA_ASSERT(j<n);
+ ConstIt v=lookup.find(std::make_pair(i,j));
+ if(v!=lookup.end()) {
+ return v->second;
+ }
+ return 0;
+ }
+ size_t nonZeroCount() const {
+ return lookup.size();
+ }
+ void resize(unsigned n) {
+ this->n = n;
+ }
+ void clear() {
+ lookup.clear();
+ }
+};
+/*
+ * Yale Sparse Matrix implementation (from Wikipedia definition).
+ * It stores an initial sparse n×n matrix M in row form using three arrays, A,
+ * IA, JA. NZ denotes the number of nonzero entries in matrix M. The array A
+ * then is of length NZ and holds all nonzero entries of M. The array IA stores
+ * at IA(i) the position of the first element of row i in the sparse array A.
+ * The length of row i is determined by IA(i+1) - IA(i). Therefore IA needs to
+ * be of length N + 1. In array JA, the column index of the element A(j) is
+ * stored. JA is of length NZ.
+ */
+class SparseMatrix {
+public:
+ SparseMatrix(SparseMap const & m)
+ : n(m.n), NZ((unsigned)m.nonZeroCount()), sparseMap(m),
+ A(std::valarray<double>(NZ)), IA(std::valarray<unsigned>(n+1)), JA(std::valarray<unsigned>(NZ)) {
+ unsigned cnt=0;
+ int lastrow=-1;
+ for(SparseMap::ConstIt i=m.lookup.begin(); i!=m.lookup.end(); i++) {
+ SparseMap::SparseIndex p = i->first;
+ COLA_ASSERT(p.first<n);
+ COLA_ASSERT(p.second<n);
+ A[cnt]=i->second;
+ if((int)p.first!=lastrow) {
+ for(unsigned r=lastrow+1;r<=p.first;r++) {
+ IA[r]=cnt;
+ }
+ lastrow=p.first;
+ }
+ JA[cnt]=p.second;
+ cnt++;
+ }
+ for(unsigned r=lastrow+1;r<=n;r++) {
+ IA[r]=NZ;
+ }
+ }
+ void rightMultiply(std::valarray<double> const & v, std::valarray<double> & r) const {
+ COLA_ASSERT(v.size()>=n);
+ COLA_ASSERT(r.size()>=n);
+ for(unsigned i=0;i<n;i++) {
+ r[i]=0;
+ for(unsigned j=IA[i];j<IA[i+1];j++) {
+ r[i]+=A[j]*v[JA[j]];
+ }
+ }
+ }
+ double getIJ(const unsigned i, const unsigned j) const {
+ return sparseMap.getIJ(i,j);
+ }
+ void print() const {
+ for(unsigned i=0;i<n;i++) {
+ for(unsigned j=0;j<n;j++) {
+ printf("%f ",getIJ(i,j));
+ }
+ printf("\n");
+ }
+ }
+ unsigned rowSize() const {
+ return n;
+ }
+private:
+ const unsigned n,NZ;
+ SparseMap const & sparseMap;
+ std::valarray<double> A;
+ std::valarray<unsigned> IA, JA;
+};
+} //namespace cola
+#endif /* _SPARSE_MATRIX_H */
diff --git a/src/3rdparty/adaptagrams/libcola/straightener.cpp b/src/3rdparty/adaptagrams/libcola/straightener.cpp
new file mode 100644
index 0000000..dc22d18
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/straightener.cpp
@@ -0,0 +1,798 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2005-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+ *
+*/
+
+/*
+ * Functions to automatically generate constraints for the
+ * rectangular node overlap removal problem.
+ */
+
+#include <set>
+#include <list>
+#include <cassert>
+#include <iostream>
+#include <cmath>
+
+#include "libvpsc/assertions.h"
+#include "libcola/commondefs.h"
+#include "libcola/cola.h"
+#include "libcola/compound_constraints.h"
+#include "libcola/straightener.h"
+
+//#define STRAIGHTENER_DEBUG 1
+
+using std::list;
+using std::make_pair;
+using std::pair;
+using std::set;
+using std::vector;
+using std::copy;
+
+namespace straightener {
+
+ // is point p on line a-b?
+ static bool pointOnLine(double px,double py, double ax, double ay, double bx, double by, double& tx) {
+ double dx=bx-ax;
+ double dy=by-ay;
+ double ty=0;
+ if(fabs(dx)<0.0001&&fabs(dy)<0.0001) {
+ // runty line!
+ tx=px-ax;
+ ty=py-ay;
+ } else {
+ if(fabs(dx)<0.0001) {
+ //vertical line
+ if(fabs(px-ax)<0.01) {
+ tx=(py-ay)/dy;
+ }
+ } else {
+ tx=(px-ax)/dx;
+ }
+ if(fabs(dy)<0.0001) {
+ //horizontal line
+ if(fabs(py-ay)<0.01) {
+ ty=tx;
+ }
+ } else {
+ ty=(py-ay)/dy;
+ }
+ }
+ //printf(" tx=%f,ty=%f\n",tx,ty);
+ if(fabs(tx-ty)<0.001 && tx>=0 && tx<=1) {
+ return true;
+ }
+ return false;
+ }
+ void Route::rerouteAround(vpsc::Rectangle* rect) {
+ // the first and last points should not be inside this
+ // rectangle - note that we should not be routing around
+ // rectangles directly connected to this route
+ COLA_ASSERT(!rect->inside(xs[0],ys[0]));
+ COLA_ASSERT(!rect->inside(xs[n-1],ys[n-1]));
+ // first, we examine each point and if it is inside the rectangle, we
+ // project to the nearest edge of the rectangle
+ for(unsigned i=1;i<n-1;i++) {
+ double &x=xs[i], &y=ys[i];
+ if(rect->inside(x,y)) {
+ enum ProjectSide {LEFT, BOTTOM, RIGHT, TOP};
+ unsigned projectSide = LEFT;
+ double minDist = x - rect->getMinX();
+ double dist = y - rect->getMinY();
+ if(dist<minDist) {
+ projectSide = BOTTOM;
+ minDist = dist;
+ }
+ dist = rect->getMaxX() - x;
+ if(dist<minDist) {
+ projectSide = RIGHT;
+ minDist = dist;
+ }
+ dist = rect->getMaxY() - y;
+ if(dist<minDist) {
+ projectSide = TOP;
+ minDist = dist;
+ }
+ switch(projectSide) {
+ case LEFT:
+ x=rect->getMinX();
+ break;
+ case BOTTOM:
+ y=rect->getMinY();
+ break;
+ case RIGHT:
+ x=rect->getMaxX();
+ break;
+ case TOP:
+ y=rect->getMaxY();
+ break;
+ }
+
+ }
+ }
+ // the new route is copied into rxs, rys.
+ vector<double> rxs, rys;
+ double prevX=xs[0], prevY=ys[0];
+ rxs.push_back(prevX);
+ rys.push_back(prevY);
+
+ // check each segment in turn to see if it intersects
+ // with the rectangle.
+ // If an intersecting segment is found:
+ // 1) the segment passes right through the rectangle
+ // - we insert new segments routed around the rectangle
+ // 2) the segment terminates inside the rectangle
+ // - we follow connected segments until we find the exit
+ // point, then we insert a route around the rectangle
+ // 3) the segment just touches one side
+ //
+ for(unsigned i=1;i<n;i++) {
+ // we have projected all points to the boundary already so we shouldn't find any inside
+ COLA_ASSERT(!rect->inside(xs[i],ys[i]));
+ vpsc::RectangleIntersections ri;
+ rect->lineIntersections(prevX,prevY,
+ xs[i],ys[i],ri);
+ if(ri.intersects) {
+ int count=ri.countIntersections();
+ COLA_ASSERT(count>0); // can't be 0 because we have detected an intersection
+ COLA_ASSERT(count<4); // assumes no zero width or height rects which would be
+ // the only way for a line segment to touch all 4 sides at once
+ if(count==3) { // runs along one side
+ COLA_ASSERT(!rect->inside(xs[i],ys[i]));
+ } else if(count==2) { // passes right through
+ COLA_ASSERT(!rect->inside(xs[i],ys[i]));
+ double x1=0, y1=0, x2=0, y2=0;
+ ri.nearest(prevX, prevY, x1, y1);
+ ri.nearest(xs[i], ys[i], x2, y2);
+ rect->routeAround(x1, y1, x2, y2, rxs, rys);
+ } else if(count==1) {
+ // single intersection, earlier projection step ensures it is on the
+ // perimeter, so nothing to do
+ }
+ }
+ prevX=xs[i];
+ prevY=ys[i];
+ COLA_ASSERT(!rect->inside(prevX,prevY));
+ rxs.push_back(prevX);
+ rys.push_back(prevY);
+ }
+ delete [] xs;
+ delete [] ys;
+ n=rxs.size();
+ COLA_ASSERT(rys.size()==n);
+ xs = new double[n];
+ ys = new double[n];
+ copy(rxs.begin(),rxs.end(),xs);
+ copy(rys.begin(),rys.end(),ys);
+ }
+ /**
+ * sets up the path information for an edge,
+ * i.e. nodes are added to the path list in the order they appear on the
+ * edge, from startNode to endNode.
+ * activePath contains at least the first and last node in the edge.
+ * If allActive is true then
+ * activePath list is also set up with a subset of nodes from path, each of
+ * which is active (a start/end node or involved in a violated constraint).
+ */
+ void Edge::nodePath(vector<Node*>& nodes, bool allActive = true) {
+ list<unsigned> ds(dummyNodes.size());
+ copy(dummyNodes.begin(),dummyNodes.end(),ds.begin());
+ //printf("Edge::nodePath: (%d,%d) dummyNodes:%d\n",startNode,endNode,ds.size());
+ path.clear();
+ activePath.clear();
+ path.push_back(startNode);
+ activePath.push_back(0);
+ for(unsigned i=1;i<route->n;i++) {
+ //printf(" checking segment %d-%d\n",i-1,i);
+ set<pair<double,unsigned> > pntsOnLineSegment;
+ for(list<unsigned>::iterator j=ds.begin();j!=ds.end();) {
+ double px=nodes[*j]->pos[0];
+ double py=nodes[*j]->pos[1];
+ double ax=route->xs[i-1];
+ double ay=route->ys[i-1];
+ double bx=route->xs[i];
+ double by=route->ys[i];
+ double t=0;
+ list<unsigned>::iterator copyit=j++;
+ //printf(" px=%f, py=%f, ax=%f, ay=%f, bx=%f, by=%f\n",px,py,ax,ay,bx,by);
+ if(pointOnLine(px,py,ax,ay,bx,by,t)) {
+ //printf(" got node %d\n",*copyit);
+ pntsOnLineSegment.insert(make_pair(t,*copyit));
+ ds.erase(copyit);
+ }
+ }
+ for(set<pair<double,unsigned> >::iterator j=pntsOnLineSegment.begin();j!=pntsOnLineSegment.end();j++) {
+ if(allActive && nodes[j->second]->active) {
+ activePath.push_back(path.size());
+ }
+ path.push_back(j->second);
+ }
+ //printf("\n");
+ }
+ activePath.push_back(path.size());
+ path.push_back(endNode);
+ COLA_ASSERT(ds.empty());
+ }
+ void Edge::createRouteFromPath(std::vector<Node *> const & nodes) {
+ Route* r=new Route(path.size());
+#ifdef STRAIGHTENER_DEBUG
+ //printf("Route:");
+#endif
+ for(unsigned i=0;i<path.size();i++) {
+ r->xs[i]=nodes[path[i]]->pos[0];
+ r->ys[i]=nodes[path[i]]->pos[1];
+#ifdef STRAIGHTENER_DEBUG
+ //printf("(%f,%f)",r->xs[i],r->ys[i]);
+#endif
+ }
+#ifdef STRAIGHTENER_DEBUG
+ //printf("\n");
+#endif
+ setRoute(r);
+ }
+
+ typedef enum {Open, Close} EventType;
+ struct Event {
+ EventType type;
+ Node *v;
+ Edge *e;
+ double pos;
+ Event(EventType t, Node *v, double p) : type(t),v(v),e(nullptr),pos(p) {};
+ Event(EventType t, Edge *e, double p) : type(t),v(nullptr),e(e),pos(p) {};
+ };
+ /*
+ * the following relation defines a strict weak ordering over events, i.e.:
+ * irreflexivity: CompareEvents(e,e) == false
+ * antisymetry: CompareEvents(a,b) => !CompareEvents(b,a)
+ * transitivity: CompareEvents(a,b) && CompareEvents(b,c) => CompareEvents(a,c)
+ * transitivity of equivalence:
+ * !CompareEvents(a,b) && !CompareEvents(b,a) && !CompareEvents(b,c) && !CompareEvents(c,b)
+ * => !CompareEvents(a,c) && !CompareEvents(c,a)
+ */
+ struct CompareEvents {
+ bool operator() (Event *const &a, Event *const &b) const {
+ if(a->pos < b->pos) {
+ return true;
+ } else if(a->pos==b->pos) {
+ // All opens should come before closes when at the same position
+ if(a->type==Open && b->type==Close) return true;
+ if(a->type==Close && b->type==Open) return false;
+ // Edge opens at the same position as node opens, edge comes first
+ if(a->type==Open && b->type==Open) {
+ if(a->e && b->v) return true;
+ if(b->e && a->v) return false;
+ }
+ // Edge closes at the same position as node closes, node comes first
+ if(a->type==Close && b->type==Close) {
+ if(a->e && b->v) return false;
+ if(b->e && a->v) return true;
+ }
+ }
+ return false;
+ }
+ };
+
+ /**
+ * Search along scan line at conjpos for open edges to the left of v
+ * as far as l, and to the right of v as far as r.
+ * The result is a list of nodes L (including l,v,r and a bunch of
+ * new dummy nodes for each edge intersected - excluding edges
+ * connected to v).
+ * The new dummy nodes are also added to the end of the canonical
+ * node list: nodes.
+ */
+ void sortNeighbours(const vpsc::Dim dim, Node * v, Node * l, Node * r,
+ const double conjpos, vector<Edge*> const & openEdges,
+ vector<Node *>& L,vector<Node *>& nodes) {
+ double minpos=-DBL_MAX, maxpos=DBL_MAX;
+ if(l!=nullptr) {
+ L.push_back(l);
+ minpos=l->scanpos;
+ }
+ typedef pair<double,Edge*> PosEdgePair;
+ set<PosEdgePair> sortedEdges;
+ for(unsigned i=0;i<openEdges.size();i++) {
+ Edge *e=openEdges[i];
+ vector<double> bs;
+ if(dim==vpsc::HORIZONTAL) {
+ e->xpos(conjpos,bs);
+ } else {
+ e->ypos(conjpos,bs);
+ }
+ //std::cerr << "edge(intersections="<<bs.size()<<":("<<e->startNode<<","<<e->endNode<<"))"<<std::endl;
+ for(vector<double>::iterator it=bs.begin();it!=bs.end();it++) {
+ sortedEdges.insert(make_pair(*it,e));
+ }
+ }
+ for(set<PosEdgePair>::iterator i=sortedEdges.begin();i!=sortedEdges.end();i++) {
+ double pos=i->first;
+ if(pos < minpos) continue;
+ if(pos > v->scanpos) break;
+ // if edge is connected (start or end) to v then skip
+ // need to record start and end positions of edge segment!
+ Edge* e=i->second;
+ if(e->startNode==v->id||e->endNode==v->id) continue;
+ //if(l!=nullptr&&(e->startNode==l->id||e->endNode==l->id)) continue;
+ //cerr << "edge("<<e->startNode<<","<<e->endNode<<",pts="<<e->pts<<")"<<endl;
+ // here, we probably want to search for existing dummy
+ // nodes associated with the same edge within some
+ // range of (pos,conjpos), rather than creating new ones.
+ // Would require some sort of quad-tree structure
+ Node* d=dim==vpsc::HORIZONTAL?
+ new Node(nodes.size(),pos,conjpos,e):
+ new Node(nodes.size(),conjpos,pos,e);
+ L.push_back(d);
+ nodes.push_back(d);
+ }
+ L.push_back(v);
+
+ if(r!=nullptr) {
+ maxpos=r->scanpos;
+ }
+ for(set<PosEdgePair>::iterator i=sortedEdges.begin();i!=sortedEdges.end();i++) {
+ if(i->first < v->scanpos) continue;
+ if(i->first > maxpos) break;
+ double pos=i->first;
+ // if edge is connected (start or end) to v then skip
+ // need to record start and end positions of edge segment!
+ Edge* e=i->second;
+ if(e->startNode==v->id||e->endNode==v->id) continue;
+ //if(r!=nullptr&&(e->startNode==r->id||e->endNode==r->id)) continue;
+ //cerr << "edge("<<e->startNode<<","<<e->endNode<<",pts="<<e->pts<<")"<<endl;
+ Node* d=dim==vpsc::HORIZONTAL?
+ new Node(nodes.size(),pos,conjpos,e):
+ new Node(nodes.size(),conjpos,pos,e);
+ L.push_back(d);
+ nodes.push_back(d);
+ }
+ if(r!=nullptr) {
+ L.push_back(r);
+ }
+ }
+ static double overlap(vpsc::Dim k, Node const *u, Node const *v) {
+ if (u->pos[k] <= v->pos[k] && v->getMin(k) < u->getMax(k))
+ return u->getMax(k) - v->getMin(k);
+ if (v->pos[k] <= u->pos[k] && u->getMin(k) < v->getMax(k))
+ return v->getMax(k) - u->getMin(k);
+ return 0;
+ }
+
+ static cola::SeparationConstraint* createConstraint(
+ Node* u, Node* v, vpsc::Dim dim) {
+ double g=u->length[dim]+v->length[dim];
+ g/=2;
+ double sep=v->pos[dim]-u->pos[dim];
+ if(sep < g) {
+ u->active = true;
+ v->active = true;
+ }
+ //cerr << "Constraint: "<< u->id << "+"<<g<<"<="<<v->id<<endl;
+ return new cola::SeparationConstraint(dim, u->id, v->id, g);
+ }
+
+ template <typename T>
+ Event* createEvent(
+ const vpsc::Dim dim,
+ const EventType type,
+ T *v,
+ double border) {
+ double pos = (type==Open) ? v->getMin((vpsc::Dim)!dim)-border
+ : v->getMax((vpsc::Dim)!dim)+border ;
+ return new Event(type,v,pos);
+ }
+ /**
+ * Generates constraints to prevent node/edge and edge/edge intersections.
+ * Can be invoked to generate either horizontal or vertical constraints
+ * depending on dim parameter.
+ * For horizontal constraints, a vertical scan (from top to bottom) is
+ * conducted, looking for node/edge boundaries, and then searching along
+ * the horizontal limit of that boundary for intersections with other
+ * nodes/edges.
+ */
+ void generateConstraints(
+ const vpsc::Dim dim,
+ vector<Node*> & nodes,
+ vector<Edge*> const & edges,
+ vector<cola::SeparationConstraint*>& cs,
+ bool xSkipping = true) {
+ vector<Event*> events;
+ double nodeFudge=-0.01, edgeFudge=0;
+#ifdef STRAIGHTENER_DEBUG
+ cout << (dim==vpsc::HORIZONTAL
+ ?"scanning top to bottom..."
+ :"scanning left to right...")
+ << endl;
+#endif
+ for(unsigned i=0;i<nodes.size();i++) {
+ Node *v=nodes[i];
+ if(v->scan) {
+ v->scanpos=v->pos[dim];
+ events.push_back(createEvent(dim,Open,v,nodeFudge));
+ events.push_back(createEvent(dim,Close,v,nodeFudge));
+ }
+ }
+ for(unsigned i=0;i<edges.size();i++) {
+ Edge *e=edges[i];
+ events.push_back(createEvent(dim,Open,e,edgeFudge));
+ events.push_back(createEvent(dim,Close,e,edgeFudge));
+ }
+ std::sort(events.begin(),events.end(),CompareEvents());
+
+ NodeSet openNodes;
+ vector<Edge*> openEdges;
+ // scan opening and closing events in order
+ for(unsigned i=0;i<events.size();i++) {
+ Event *e=events[i];
+ Node *v=e->v;
+ if(v!=nullptr) {
+ v->open = true;
+#ifdef STRAIGHTENER_DEBUG
+ printf("NEvent@%f,nid=%d,(%f,%f),w=%f,h=%f,openn=%d,opene=%d\n",e->pos,v->id,v->pos[0],v->pos[1],v->length[0],v->length[1],(int)openNodes.size(),(int)openEdges.size());
+#endif
+ Node *l=nullptr, *r=nullptr;
+ if(!openNodes.empty()) {
+ // it points to the first node to the right of v
+ NodeSet::iterator it=openNodes.lower_bound(v);
+ // step left to find the first node to the left of v
+ while(it--!=openNodes.begin()) {
+ if(!xSkipping
+ || dim!=vpsc::HORIZONTAL
+ || overlap(vpsc::HORIZONTAL,*it,v) <= 0
+ || overlap(vpsc::HORIZONTAL,*it,v) <= overlap(vpsc::VERTICAL,*it,v)) {
+ l=*it;
+ break;
+ }
+#ifdef STRAIGHTENER_DEBUG
+ printf("l=%d\n",l->id);
+#endif
+ }
+ it=openNodes.upper_bound(v);
+ while(it!=openNodes.end()) {
+ if(!xSkipping
+ || dim!=vpsc::HORIZONTAL
+ || overlap(vpsc::HORIZONTAL,v,*it) <= 0
+ || overlap(vpsc::HORIZONTAL,v,*it) <= overlap(vpsc::VERTICAL,v,*it)) {
+ r=*it;
+ break;
+ }
+ it++;
+ }
+ }
+ vector<Node*> L;
+ sortNeighbours(dim,v,l,r,e->pos,openEdges,L,nodes);
+#ifdef STRAIGHTENER_DEBUG
+ printf("L=[");
+ for(unsigned i=0;i<L.size();i++) {
+ printf("%d ",L[i]->id);
+ }
+ printf("]\n");
+#endif
+ // for each dummy node w in L:
+ // if w left of v create constraints l<w, w<v
+ // if w right of v create constraints v<w, w<r
+ for(vector<Node*>::iterator i=L.begin();i!=L.end();i++) {
+ Node* w=*i;
+ if(w->dummy) {
+ // node is on an edge
+ Edge *edge=w->edge;
+ if(w->pos[dim]<v->pos[dim]) { // w left of v
+ if(l!=nullptr&&!edge->isEnd(l->id)) {
+ cs.push_back(createConstraint(l,w,dim));
+ }
+ if(!edge->isEnd(v->id)) {
+ cs.push_back(createConstraint(w,v,dim));
+ }
+ } else { // w right of v
+ if(!edge->isEnd(v->id)) {
+ cs.push_back(createConstraint(v,w,dim));
+ }
+ if(r!=nullptr&&!edge->isEnd(r->id)) {
+ cs.push_back(createConstraint(w,r,dim));
+ }
+ }
+ }
+ }
+ if(e->type==Close) {
+ if(l!=nullptr) cs.push_back(createConstraint(l,v,dim));
+ if(r!=nullptr) cs.push_back(createConstraint(v,r,dim));
+ }
+ }
+ if(e->type==Open) {
+ if(v!=nullptr) {
+ openNodes.insert(v);
+ } else {
+#ifdef STRAIGHTENER_DEBUG
+ printf("EdgeOpen@%f,eid=%d,(u,v)=(%d,%d)\n", e->pos,e->e->id,e->e->startNode,e->e->endNode);
+#endif
+ e->e->openInd=openEdges.size();
+ openEdges.push_back(e->e);
+ }
+ } else {
+ // Close
+ if(v!=nullptr) {
+ openNodes.erase(v);
+ v->open=false;
+ } else {
+#ifdef STRAIGHTENER_DEBUG
+ printf("EdgeClose@%f,eid=%d,(u,v)=(%d,%d)\n", e->pos,e->e->id,e->e->startNode,e->e->endNode);
+#endif
+ unsigned i=e->e->openInd;
+ COLA_ASSERT(openEdges.size()>0);
+ openEdges[i]=openEdges[openEdges.size()-1];
+ openEdges[i]->openInd=i;
+ openEdges.resize(openEdges.size()-1);
+ }
+ }
+ delete e;
+ }
+ }
+ /**
+ * set up straightener clusters.
+ * For each cola::cluster c:
+ * create a straightener::cluster sc
+ * set each node in c to belong to sc
+ * set scanpos based on avg pos in scan dir
+ * create a chain of dummy nodes for cluster boundary
+ */
+ void generateClusterBoundaries(
+ const vpsc::Dim dim,
+ vector<straightener::Node*> & nodes,
+ vector<straightener::Edge*> & edges,
+ vector<vpsc::Rectangle*> const & rs,
+ cola::Cluster const & clusterHierarchy,
+ vector<straightener::Cluster*>& sclusters) {
+ sclusters.clear();
+ for(vector<cola::Cluster*>::const_iterator i
+ =clusterHierarchy.clusters.begin();
+ i!=clusterHierarchy.clusters.end(); i++) {
+ if(cola::ConvexCluster* c=dynamic_cast<cola::ConvexCluster*>(*i)) {
+ straightener::Cluster* sc=new straightener::Cluster(c);
+ // compute scanpos based on average position in scan direction
+ sc->scanpos=0;
+ for(set<unsigned>::iterator it= c->nodes.begin();
+ it != c->nodes.end(); ++it) {
+ straightener::Node* u = nodes[*it];
+ sc->scanpos+=u->pos[dim];
+ u->cluster = sc;
+ }
+ sc->scanpos/=c->nodes.size();
+ sclusters.push_back(sc);
+ c->computeBoundary(rs);
+ // create a chain of dummy nodes for the boundary
+ Node* first = new Node(nodes.size(),c->hullX[0],c->hullY[0]);
+ nodes.push_back(first);
+ Node* u = first;
+ unsigned i=1;
+ for(;i<c->hullX.size();i++) {
+ Node* v = new Node(nodes.size(),c->hullX[i],c->hullY[i]);
+ nodes.push_back(v);
+ Edge* e = new Edge(edges.size(),u->id,v->id,
+ c->hullX[i-1],c->hullY[i-1],c->hullX[i],c->hullY[i]);
+ edges.push_back(e);
+ sc->boundary.push_back(e);
+ u=v;
+ }
+ edges.push_back(
+ new Edge(edges.size(),u->id,first->id,
+ c->hullX[i-1],c->hullY[i-1],c->hullX[0],c->hullY[0]));
+ }
+ }
+ }
+
+ void Cluster::updateActualBoundary()
+ {
+ unsigned n=0;
+ for(std::vector<Edge*>::const_iterator e=boundary.begin();
+ e!=boundary.end();e++) {
+ n+=(*e)->getRoute()->n;
+ }
+ colaCluster->hullX.resize(n);
+ colaCluster->hullY.resize(n);
+ unsigned i=0;
+ for(std::vector<Edge*>::const_iterator e=boundary.begin();
+ e!=boundary.end();e++) {
+ Route const * r=(*e)->getRoute();
+ for(unsigned j=0;j<r->n;j++) {
+ colaCluster->hullX[i]=r->xs[j];
+ colaCluster->hullY[i++]=r->ys[j];
+ }
+ }
+ }
+ Straightener::Straightener(
+ const double strength,
+ const vpsc::Dim dim,
+ std::vector<vpsc::Rectangle*> const & rs,
+ cola::FixedList const & fixed,
+ std::vector<Edge*> const & edges,
+ vpsc::Variables const & vs,
+ vpsc::Variables & lvs,
+ vpsc::Constraints & lcs,
+ std::valarray<double> &oldCoords,
+ std::valarray<double> &oldG)
+ : strength(strength),
+ dim(dim),
+ fixed(fixed),
+ edges(edges),
+ vs(vs),
+ lvs(lvs)
+ {
+ unsigned n=rs.size();
+ for (unsigned i=0;i<n;i++) {
+ nodes.push_back(new straightener::Node(i,rs[i]));
+ }
+ vector<cola::SeparationConstraint*> cs;
+ straightener::generateConstraints(dim,nodes,edges,cs);
+ // after generateConstraints we have new dummy nodes at the end of snodes and
+ // constraints in cs
+ // need to create variables for dummy nodes in lvs and constraints in lcs
+ N=nodes.size();
+ g.resize(N);
+ coords.resize(N);
+ for(unsigned i=0;i<n;i++) {
+ g[i]=oldG[i];
+ coords[i]=oldCoords[i];
+ }
+ for (unsigned i=n;i<N;i++) {
+ double desiredPos = nodes[i]->pos[dim];
+ lvs.push_back(new vpsc::Variable(i,desiredPos,1));
+ g[i]=0;
+ coords[i]=desiredPos;
+ }
+ for (vector<cola::SeparationConstraint*>::iterator i=cs.begin();i!=cs.end();i++) {
+ unsigned lv=(*i)->left();
+ unsigned rv=(*i)->right();
+ double gap=(*i)->gap;
+ vpsc::Variable* l = lv<n?vs[lv]:lvs[lv-n];
+ vpsc::Variable* r = rv<n?vs[rv]:lvs[rv-n];
+ lcs.push_back(new vpsc::Constraint(l,r,gap));
+ }
+ for(unsigned i=0;i<edges.size();i++) {
+ edges[i]->nodePath(nodes,false);
+ }
+ for_each(cs.begin(),cs.end(),cola::delete_object());
+ }
+ Straightener::~Straightener() {
+ for_each(nodes.begin(),nodes.end(),cola::delete_object());
+ }
+ void Straightener::computeForces(cola::SparseMap &H) {
+ // hessian matrix:
+ // diagonal: sum dy2/l^3
+ // off-diag: -dy2/l^3
+ for(unsigned i=0;i<edges.size();i++) {
+ //printf("Straightening path:\n");
+ //edges[i]->print();
+ vector<unsigned>& path=edges[i]->path;
+ COLA_ASSERT(path.size()>0);
+ for(unsigned j=1;j<path.size();j++) {
+ unsigned u=path[j-1], v=path[j];
+ double x1=nodes[u]->pos[0], x2=nodes[v]->pos[0],
+ y1=nodes[u]->pos[1], y2=nodes[v]->pos[1];
+ double dx=x1-x2, dy=y1-y2;
+ double dx2=dx*dx, dy2=dy*dy;
+ double l=sqrt(dx2+dy2);
+ if(l<0.0000001) continue;
+ double f=dim==vpsc::HORIZONTAL?dx:dy;
+ f*=strength/l;
+ if(!fixed.check(u)) { g[u]+=f; }
+ if(!fixed.check(v)) { g[v]-=f; }
+ double h=dim==vpsc::HORIZONTAL?dy2:dx2;
+ h*=strength/(l*l*l);
+ H(u,u)+=h;
+ H(v,v)+=h;
+ H(u,v)-=h;
+ H(v,u)-=h;
+ }
+ }
+ }
+ double Straightener::computeStress(std::valarray<double> const &coords) {
+ double stress=0;
+ for(unsigned i=0;i<edges.size();i++) {
+ vector<unsigned>& path=edges[i]->path;
+ COLA_ASSERT(path.size()>0);
+ for(unsigned j=1;j<path.size();j++) {
+ unsigned u=path[j-1], v=path[j];
+ double x1,x2,y1,y2;
+ if(dim==vpsc::HORIZONTAL) {
+ x1=coords[u];
+ x2=coords[v];
+ y1=nodes[u]->pos[1];
+ y2=nodes[v]->pos[1];
+ } else {
+ x1=nodes[u]->pos[0];
+ x2=nodes[v]->pos[0];
+ y1=coords[u];
+ y2=coords[v];
+ }
+ double dx=x1-x2, dy=y1-y2;
+ double dx2=dx*dx, dy2=dy*dy;
+ double l=sqrt(dx2+dy2);
+ stress+=l;
+ }
+ }
+ return strength*stress;
+ }
+ double Straightener::computeStress2(std::valarray<double> const &coords)
+ {
+ COLA_UNUSED(coords);
+
+ double stress=0;
+ for(unsigned i=0;i<edges.size();i++) {
+ double d = edges[i]->idealLength;
+ double weight=1/(d*d);
+ //printf("pathLength=%f\n",pathLength(edges[i],nodes));
+ double sqrtf=fabs(d-pathLength(edges[i],nodes));
+ stress+=weight*sqrtf*sqrtf;
+ }
+ return strength*stress;
+ }
+ void Straightener::updateNodePositions() {
+ // real nodes
+ for (unsigned i=0;i<N;i++) {
+ Node *n=nodes[i];
+ n->pos[dim]=coords[i];
+ }
+ // dummy bend nodes
+ //printf("got %d dummy nodes\n", (int) lvs.size());
+ dummyNodesX.resize(lvs.size());
+ dummyNodesY.resize(lvs.size());
+ for (unsigned i=0;i<lvs.size();i++) {
+ COLA_ASSERT(i+vs.size() < nodes.size());
+ Node *n=nodes[i+vs.size()];
+ dummyNodesX[i]=n->pos[0];
+ dummyNodesY[i]=n->pos[1];
+ }
+ }
+ void Straightener::finalizeRoutes() {
+ for(unsigned i=0;i<edges.size();i++) {
+ edges[i]->createRouteFromPath(nodes);
+ edges[i]->dummyNodes.clear();
+ edges[i]->path.clear();
+ }
+ }
+ void setEdgeLengths(double **D, vector<Edge*> & edges) {
+ for(unsigned i=0;i<edges.size();i++) {
+ Edge* e=edges[i];
+ e->idealLength=D[e->startNode][e->endNode];
+ }
+ }
+ double pathLength(Edge const * e, vector<Node*> const & nodes) {
+ double length=0;
+ vector<unsigned> const & path=e->path;
+ for(unsigned i=1;i<path.size();i++) {
+ Node *u=nodes[path[i-1]], *v=nodes[path[i]];
+ double dx=u->pos[0]-v->pos[0];
+ double dy=u->pos[1]-v->pos[1];
+ length+=sqrt(dx*dx+dy*dy);
+ }
+ return length;
+ }
+ double computeStressFromRoutes(double strength, vector<Edge*> & edges) {
+ double stress=0;
+ for(unsigned i=0;i<edges.size();i++) {
+ Edge* e=edges[i];
+ double d = e->idealLength;
+ double weight=1/(d*d);
+ double sqrtf=fabs(d-e->getRoute()->routeLength());
+ stress+=weight*sqrtf*sqrtf;
+ }
+ return strength*stress;
+ }
+}
+
diff --git a/src/3rdparty/adaptagrams/libcola/straightener.h b/src/3rdparty/adaptagrams/libcola/straightener.h
new file mode 100644
index 0000000..846f4f9
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/straightener.h
@@ -0,0 +1,389 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+*/
+
+#ifndef STRAIGHTENER_H
+#define STRAIGHTENER_H
+
+#include <set>
+#include <cfloat>
+#include <iostream>
+#include <iterator>
+
+#include "libvpsc/rectangle.h"
+#include "libcola/commondefs.h"
+
+namespace cola {
+ class Cluster;
+ class ConvexCluster;
+ class SeparationConstraint;
+}
+namespace straightener {
+
+struct Route {
+ Route(unsigned n) : n(n), xs(new double[n]), ys(new double[n]) {}
+ ~Route() {
+ delete [] xs;
+ delete [] ys;
+ }
+ void print() {
+ std::cout << "double xs[]={";
+ std::copy(xs,xs+n-1,std::ostream_iterator<double>(std::cout,","));
+ std::cout << xs[n-1] << "};" << std::endl << "double ys[]={";
+ std::copy(ys,ys+n-1,std::ostream_iterator<double>(std::cout,","));
+ std::cout << ys[n-1] << "};" << std::endl;
+ }
+ void boundingBox(double &xmin,double &ymin,double &xmax,double &ymax) {
+ xmin=ymin=DBL_MAX;
+ xmax=ymax=-DBL_MAX;
+ for(unsigned i=0;i<n;i++) {
+ xmin=std::min(xmin,xs[i]);
+ xmax=std::max(xmax,xs[i]);
+ ymin=std::min(ymin,ys[i]);
+ ymax=std::max(ymax,ys[i]);
+ }
+ }
+ double routeLength () const {
+ double length=0;
+ for(unsigned i=1;i<n;i++) {
+ double dx=xs[i-1]-xs[i];
+ double dy=ys[i-1]-ys[i];
+ length+=sqrt(dx*dx+dy*dy);
+ }
+ return length;
+ }
+ void rerouteAround(vpsc::Rectangle *rect);
+ unsigned n;
+ double *xs;
+ double *ys;
+};
+class Node;
+struct DebugPoint {
+ double x,y;
+};
+struct DebugLine {
+ DebugLine(double x0,double y0,double x1,double y1,unsigned colour)
+ : x0(x0),y0(y0),x1(x1),y1(y1),colour(colour) {}
+ double x0,y0,x1,y1;
+ unsigned colour;
+};
+class ScanObject {
+public:
+ const unsigned id;
+ double getMin(vpsc::Dim d) const {
+ return min[d];
+ }
+ double getMax(vpsc::Dim d) const {
+ return max[d];
+ }
+ ScanObject(unsigned id) : id(id) {}
+protected:
+ double min[2], max[2];
+};
+class Edge : public ScanObject {
+public:
+ unsigned openInd; // position in openEdges
+ unsigned startNode, endNode;
+ double idealLength;
+ std::vector<unsigned> dummyNodes;
+ std::vector<unsigned> path;
+ std::vector<unsigned> activePath;
+ std::vector<DebugPoint> debugPoints;
+ std::vector<DebugLine> debugLines;
+ void print() {
+ printf("Edge[%d]=(%d,%d)\n",id,startNode,endNode);
+ route->print();
+ }
+ // if the edge route intersects with any of the rectangles in rects then reroute
+ // those parts of the route around the rectangle boundaries
+ void rerouteAround(std::vector<vpsc::Rectangle*> const &rects) {
+ unsigned rid=0;
+ for(std::vector<vpsc::Rectangle*>::const_iterator r=rects.begin();r!=rects.end();r++,rid++) {
+ if(rid!=startNode && rid!=endNode) {
+ route->rerouteAround(*r);
+ }
+ }
+ updateBoundingBox();
+ }
+ // Edge with a non-trivial route
+ Edge(unsigned id, unsigned start, unsigned end, Route* route)
+ : ScanObject(id), startNode(start), endNode(end), route(route)
+ {
+ updateBoundingBox();
+ }
+ // Edge with a trivial route
+ Edge(unsigned id, unsigned start, unsigned end,
+ double x1, double y1, double x2, double y2)
+ : ScanObject(id), startNode(start), endNode(end) {
+ route = new Route(2);
+ route->xs[0]=x1; route->ys[0]=y1;
+ route->xs[1]=x2; route->ys[1]=y2;
+ updateBoundingBox();
+ }
+ ~Edge() {
+ delete route;
+ }
+ bool isEnd(unsigned n) const {
+ if(startNode==n||endNode==n) return true;
+ return false;
+ }
+ void nodePath(std::vector<Node*>& nodes, bool allActive);
+ void createRouteFromPath(std::vector<Node *> const & nodes);
+ void xpos(double y, std::vector<double>& xs) const {
+ // search line segments for intersection points with y pos
+ for(unsigned i=1;i<route->n;i++) {
+ double ax=route->xs[i-1], bx=route->xs[i], ay=route->ys[i-1], by=route->ys[i];
+ double r=(y-ay)/(by-ay);
+ // as long as y is between ay and by then r>0
+ if(r>=0&&r<=1) {
+ xs.push_back(ax+(bx-ax)*r);
+ }
+ }
+ }
+ void ypos(double x, std::vector<double>& ys) const {
+ // search line segments for intersection points with x pos
+ for(unsigned i=1;i<route->n;i++) {
+ double ax=route->xs[i-1], bx=route->xs[i], ay=route->ys[i-1], by=route->ys[i];
+ double r=(x-ax)/(bx-ax);
+ // as long as y is between ax and bx then r>0
+ if(r>0&&r<=1) {
+ ys.push_back(ay+(by-ay)*r);
+ }
+ }
+ }
+ Route const * getRoute() const {
+ return route;
+ }
+ void setRoute(Route * r) {
+ delete route;
+ route=r;
+ updateBoundingBox();
+ }
+private:
+ void updateBoundingBox() {
+ route->boundingBox(min[0],min[1],max[0],max[1]);
+ }
+ Route* route;
+};
+class Straightener {
+public:
+ Straightener(
+ const double strength,
+ const vpsc::Dim dim,
+ std::vector<vpsc::Rectangle*> const & rs,
+ cola::FixedList const & fixed,
+ std::vector<Edge*> const & edges,
+ vpsc::Variables const & vs,
+ vpsc::Variables & lvs,
+ vpsc::Constraints & lcs,
+ std::valarray<double> & oldCoords,
+ std::valarray<double> & oldG);
+ ~Straightener();
+ void updateNodePositions();
+ void finalizeRoutes();
+ void computeForces(cola::SparseMap &H);
+ void computeForces2(cola::SparseMap &H);
+ double computeStress(std::valarray<double> const &coords);
+ double computeStress2(std::valarray<double> const &coords);
+ std::valarray<double> dummyNodesX;
+ std::valarray<double> dummyNodesY;
+ std::valarray<double> g;
+ std::valarray<double> coords;
+ unsigned N;
+private:
+ double strength;
+ const vpsc::Dim dim;
+ cola::FixedList const & fixed;
+ std::vector<Edge*> const & edges;
+ vpsc::Variables const & vs;
+ vpsc::Variables & lvs;
+ std::vector<Node*> nodes;
+ double len(const unsigned u, const unsigned v,
+ double& dx, double& dy,
+ double& dx2, double& dy2);
+ double gRule1(const unsigned a, const unsigned b);
+ double gRule2(const unsigned a, const unsigned b, const unsigned c);
+ double hRuleD1(const unsigned u, const unsigned v, const double sqrtf);
+ double hRuleD2(const unsigned u, const unsigned v, const unsigned w, const double sqrtf);
+ double hRule2(const unsigned u, const unsigned v, const unsigned w, const double sqrtf);
+ double hRule3(const unsigned u, const unsigned v, const unsigned w, const double sqrtf);
+ double hRule4(const unsigned a, const unsigned b, const unsigned c, const unsigned d);
+ double hRule56(const unsigned u, const unsigned v,
+ const unsigned a, const unsigned b, const unsigned c);
+ double hRule7(const unsigned a, const unsigned b,
+ const unsigned c, const unsigned d, const double sqrtf);
+ double hRule8(const unsigned u, const unsigned v, const unsigned w,
+ const unsigned a, const unsigned b, const unsigned c);
+};
+class Cluster {
+public:
+ cola::ConvexCluster* colaCluster;
+ Cluster(cola::ConvexCluster* c) : colaCluster(c) {}
+ double scanpos;
+ std::vector<Edge*> boundary;
+ void updateActualBoundary();
+};
+class Node : public ScanObject {
+public:
+ Cluster* cluster;
+ // Nodes may optionally belong to a cluster.
+ // Neg cluster_id means no cluster - i.e. top-level membership.
+ double pos[2];
+ double scanpos;
+ double length[2];
+ Edge* edge;
+ bool dummy; // nodes on edge paths (but not ends) are dummy
+ bool scan; // triggers scan events
+ bool active; // node is active if it is not dummy or is dummy and involved in
+ // a violated constraint
+ bool open; // a node is opened (if scan is true) when the scanline first reaches
+ // its boundary and closed when the scanline leaves it.
+ Node(unsigned id, vpsc::Rectangle const * r) :
+ ScanObject(id),cluster(nullptr),
+ edge(nullptr),dummy(false),scan(true),active(true),open(false) {
+ for(unsigned i=0;i<2;i++) {
+ pos[i]=r->getCentreD(i);
+ min[i]=r->getMinD(i);
+ max[i]=r->getMaxD(i);
+ length[i]=r->length(i);
+ }
+ }
+ Node(unsigned id, const double x, const double y) :
+ ScanObject(id),cluster(nullptr),
+ edge(nullptr),dummy(false),scan(false),active(true),open(false) {
+ pos[vpsc::HORIZONTAL]=x;
+ pos[vpsc::VERTICAL]=y;
+ for(unsigned i=0;i<2;i++) {
+ length[i]=4;
+ min[i]=pos[i]-length[i]/2.0;
+ max[i]=pos[i]+length[i]/2.0;
+ }
+ }
+ double euclidean_distance(Node const * v) const {
+ double dx=pos[0]-v->pos[0];
+ double dy=pos[1]-v->pos[1];
+ return sqrt(dx*dx+dy*dy);
+ }
+
+private:
+ friend void sortNeighbours(const vpsc::Dim dim, Node * v, Node * l, Node * r,
+ const double conjpos, std::vector<Edge*> const & openEdges,
+ std::vector<Node *>& L, std::vector<Node *>& nodes);
+ Node(const unsigned id, const double x, const double y, Edge* e) :
+ ScanObject(id),cluster(nullptr),
+ edge(e),dummy(true),scan(false),active(false) {
+ pos[vpsc::HORIZONTAL]=x;
+ pos[vpsc::VERTICAL]=y;
+ for(unsigned i=0;i<2;i++) {
+ length[i]=4;
+ min[i]=pos[i]-length[i]/2.0;
+ max[i]=pos[i]+length[i]/2.0;
+ }
+ e->dummyNodes.push_back(id);
+ }
+};
+struct CmpNodePos {
+ bool operator() (const Node* u, const Node* v) const {
+ double upos = u->scanpos;
+ double vpos = v->scanpos;
+ bool tiebreaker = u < v;
+ if (u->cluster != v->cluster) {
+ if(u->cluster!=nullptr) {
+ upos = u->cluster->scanpos;
+ }
+ if(v->cluster!=nullptr) {
+ vpos = v->cluster->scanpos;
+ }
+ tiebreaker = u->cluster < v->cluster;
+ }
+ if (upos < vpos) {
+ return true;
+ }
+ if (vpos < upos) {
+ return false;
+ }
+ return tiebreaker;
+ }
+};
+typedef std::set<Node*,CmpNodePos> NodeSet;
+// defines references to three variables for which the goal function
+// will be altered to prefer points u-b-v are in a linear arrangement
+// such that b is placed at u+t(v-u).
+struct LinearConstraint {
+ LinearConstraint(
+ Node const & u,
+ Node const & v,
+ Node const & b,
+ double w)
+ : u(u.id),v(v.id),b(b.id),w(w)
+ {
+ // from cosine rule: ub.uv/|uv|=|ub|cos(theta)
+ double uvx = v.pos[0] - u.pos[0],
+ uvy = v.pos[1] - u.pos[1],
+ ubx = b.pos[0] - u.pos[0],
+ uby = b.pos[1] - u.pos[1],
+ duv2 = uvx * uvx + uvy * uvy;
+ if(duv2 < 0.0001) {
+ t=0;
+ } else {
+ t = (uvx * ubx + uvy * uby)/duv2;
+ }
+ duu=(1-t)*(1-t);
+ duv=t*(1-t);
+ dub=t-1;
+ dvv=t*t;
+ dvb=-t;
+ dbb=1;
+ //printf("New LC: t=%f\n",t);
+ }
+ unsigned u;
+ unsigned v;
+ unsigned b;
+ double w; // weight
+ double t;
+ // 2nd partial derivatives of the goal function
+ // (X[b] - (1-t) X[u] - t X[v])^2
+ double duu;
+ double duv;
+ double dub;
+ double dvv;
+ double dvb;
+ double dbb;
+};
+void setEdgeLengths(double **D, std::vector<Edge*> & edges);
+double pathLength(Edge const * e, std::vector<Node*> const & nodes);
+double computeStressFromRoutes(double strength, std::vector<Edge*> & edges);
+typedef std::vector<LinearConstraint*> LinearConstraints;
+void generateConstraints(
+ const vpsc::Dim dim,
+ std::vector<Node*> & nodes,
+ std::vector<Edge*> const & edges,
+ std::vector<cola::SeparationConstraint*>& cs,
+ bool xSkipping);
+void nodePath(Edge& e, std::vector<Node*>& nodes, std::vector<unsigned>& path);
+void generateClusterBoundaries(
+ const vpsc::Dim dim,
+ std::vector<Node*> & nodes,
+ std::vector<Edge*> & edges,
+ std::vector<vpsc::Rectangle*> const & rs,
+ cola::Cluster const & clusterHierarchy,
+ std::vector<straightener::Cluster*>& sclusters);
+
+} // namespace straightener
+#endif
diff --git a/src/3rdparty/adaptagrams/libcola/tests/FixedRelativeConstraint01.cpp b/src/3rdparty/adaptagrams/libcola/tests/FixedRelativeConstraint01.cpp
new file mode 100755
index 0000000..378219e
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/FixedRelativeConstraint01.cpp
@@ -0,0 +1,51 @@
+#include <vector>
+#include "libcola/cola.h"
+using namespace cola;
+int main(void) {
+ CompoundConstraints ccs;
+ std::vector<Edge> es;
+ double defaultEdgeLength=40;
+ std::vector<vpsc::Rectangle*> rs;
+ vpsc::Rectangle *rect = nullptr;
+ std::vector<unsigned> fixedShapes;
+
+ double textW = 100;
+ double textH = 10;
+ double circleW = 5;
+ double circleH = 5;
+
+ rect = new vpsc::Rectangle(303-circleW, 303+circleW, 300-circleH, 300+circleH);
+ rs.push_back(rect);
+ fixedShapes.push_back(rs.size() - 1);
+
+ rect = new vpsc::Rectangle(310-circleW, 310+circleW, 302-circleH, 302+circleH);
+ rs.push_back(rect);
+ fixedShapes.push_back(rs.size() - 1);
+
+ rect = new vpsc::Rectangle(313-circleW, 313+circleW, 297-circleH, 297+circleH);
+ rs.push_back(rect);
+ fixedShapes.push_back(rs.size() - 1);
+
+ rect = new vpsc::Rectangle(300-textW, 300+textW, 300-textH, 300+textH);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(310-textW, 310+textW, 305-textH, 305+textH);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(317-textW, 317+textW, 295-textH, 295+textH);
+ rs.push_back(rect);
+
+ ConstrainedFDLayout alg(rs, es, defaultEdgeLength);
+ alg.setAvoidNodeOverlaps(true);
+
+ ccs.push_back(new FixedRelativeConstraint(rs, fixedShapes, true));
+ alg.setConstraints(ccs);
+
+ alg.makeFeasible();
+
+ // Can be used to output a "libcola-debug.svg" file:
+ //alg.outputInstanceToSVG();
+ alg.freeAssociatedObjects();
+
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libcola/tests/Makefile.am b/src/3rdparty/adaptagrams/libcola/tests/Makefile.am
new file mode 100644
index 0000000..a73ff82
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/Makefile.am
@@ -0,0 +1,68 @@
+AM_CPPFLAGS = -I$(top_srcdir) $(CAIROMM_CFLAGS)
+
+LDADD = \
+ $(top_builddir)/libvpsc/libvpsc.la \
+ $(top_builddir)/libtopology/libtopology.la \
+ $(top_builddir)/libcola/libcola.la \
+ $(top_builddir)/libavoid/libavoid.la \
+ $(CAIROMM_LIBS)
+
+check_PROGRAMS = random_graph page_bounds constrained unsatisfiable invalid makefeasible rectclustershapecontainment FixedRelativeConstraint01 StillOverlap01 StillOverlap02 shortest_paths rectangularClusters01 overlappingClusters01 overlappingClusters02 overlappingClusters04 initialOverlap
+#check_PROGRAMS = unconstrained constrained containment shortest_paths connected_components large_graph convex_hull scale_free trees random_graph large_graph topology boundary planar #resize
+#check_PROGRAMS = topology boundary planar resize resizealignment
+
+# problem_SOURCES = problem.cpp
+
+initialOverlap_SOURCES = initialOverlap.cpp
+
+overlappingClusters01_SOURCES = overlappingClusters01.cpp
+overlappingClusters02_SOURCES = overlappingClusters02.cpp
+overlappingClusters04_SOURCES = overlappingClusters04.cpp
+
+rectangularClusters01_SOURCES = rectangularClusters01.cpp
+
+StillOverlap01_SOURCES = StillOverlap01.cpp
+StillOverlap02_SOURCES = StillOverlap02.cpp
+
+FixedRelativeConstraint01_SOURCES = FixedRelativeConstraint01.cpp
+
+rectclustershapecontainment_SOURCES = rectclustershapecontainment.cpp
+
+random_graph_SOURCES = random_graph.cpp
+
+page_bounds_SOURCES = page_bounds.cpp
+
+constrained_SOURCES = constrained.cpp
+
+unsatisfiable_SOURCES = unsatisfiable.cpp
+
+invalid_SOURCES = invalid.cpp
+
+makefeasible_LDADD = $(LDADD) $(top_srcdir)/libavoid/libavoid.la
+makefeasible_SOURCES = makefeasible02.cpp
+
+shortest_paths_SOURCES = shortest_paths.cpp
+#unconstrained_SOURCES = unconstrained.cpp
+#containment_SOURCES = containment.cpp
+#topology_SOURCES = topology.cpp
+#boundary_SOURCES = boundary.cpp
+#resize_SOURCES = resize.cpp
+#resizealignment_SOURCES = resizealignment.cpp
+#planar_SOURCES = planar.cpp
+#connected_components_SOURCES = connected_components.cpp
+# test Requires boost
+#sparse_matrix_SOURCES = sparse_matrix.cpp
+#convex_hull_SOURCES = convex_hull.cpp
+#convex_hull_LDADD = $(LDADD) -lcairo -lcairomm-1.0
+#aarontest_SOURCES = aarontest.cpp
+#aarontest_LDADD = $(top_srcdir)/libcola/libcola.la $(top_builddir)/libvpsc/libvpsc.la -lcairo -lcairomm-1.0
+#qo1_SOURCES = qo1.c
+#qo1_LDADD = -L$(mosek_home)/bin -lmosek -lguide -limf
+#small_graph_SOURCES = small_graph.cpp
+#large_graph_SOURCES = large_graph.cpp
+#gml_graph_LDADD = $(common_LDADD) /usr/lib/libboost_regex.so
+#gml_graph_SOURCES = gml_graph.cpp
+#scale_free_SOURCES = scale_free.cpp
+#trees_SOURCES = trees.cpp
+
+TESTS = $(check_PROGRAMS)
diff --git a/src/3rdparty/adaptagrams/libcola/tests/StillOverlap01.cpp b/src/3rdparty/adaptagrams/libcola/tests/StillOverlap01.cpp
new file mode 100755
index 0000000..1b87767
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/StillOverlap01.cpp
@@ -0,0 +1,221 @@
+#include <vector>
+#include "libcola/cola.h"
+using namespace cola;
+int main(void) {
+ CompoundConstraints ccs;
+ std::vector<Edge> es;
+ double defaultEdgeLength=40;
+ std::vector<vpsc::Rectangle*> rs;
+ vpsc::Rectangle *rect = nullptr;
+
+ rect = new vpsc::Rectangle(210, 240, 83.5, 113.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(210, 240, 125.5, 155.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(377, 407, 43.5, 73.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(251, 281, 43.5, 73.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(110, 140, 43.5, 73.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(29, 79, 55.5, 105.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(427, 477, 32.5, 82.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(300, 350, 32.5, 82.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(171, 221, 32.5, 82.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(33, 83, 115.5, 165.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(522, 572, 115.5, 165.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(519, 569, 35.5, 85.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(192, 258, 123.5, 173.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(192, 258, 65.5, 115.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(359, 425, -16.5, 33.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(233, 299, -16.5, 33.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(154, 220, 33.5, 83.5);
+ rs.push_back(rect);
+
+ AlignmentConstraint *alignment140600592030544 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140600592030544->addShape(1, 0);
+ alignment140600592030544->addShape(0, 0);
+ ccs.push_back(alignment140600592030544);
+
+ AlignmentConstraint *alignment140600592030848 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140600592030848->addShape(2, 0);
+ ccs.push_back(alignment140600592030848);
+
+ AlignmentConstraint *alignment140600592031040 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140600592031040->addShape(3, 0);
+ ccs.push_back(alignment140600592031040);
+
+ AlignmentConstraint *alignment140600592031168 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140600592031168->addShape(4, 0);
+ ccs.push_back(alignment140600592031168);
+
+ AlignmentConstraint *alignment140600592031296 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140600592031296->addShape(5, 0);
+ ccs.push_back(alignment140600592031296);
+
+ AlignmentConstraint *alignment140600592031456 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140600592031456->addShape(6, 0);
+ ccs.push_back(alignment140600592031456);
+
+ AlignmentConstraint *alignment140600592031616 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140600592031616->addShape(7, 0);
+ ccs.push_back(alignment140600592031616);
+
+ AlignmentConstraint *alignment140600592031776 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140600592031776->addShape(8, 0);
+ ccs.push_back(alignment140600592031776);
+
+ AlignmentConstraint *alignment140600592031936 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140600592031936->addShape(9, 0);
+ ccs.push_back(alignment140600592031936);
+
+ AlignmentConstraint *alignment140600592032240 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140600592032240->addShape(10, 0);
+ ccs.push_back(alignment140600592032240);
+
+ AlignmentConstraint *alignment140600592032400 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140600592032400->addShape(11, 0);
+ ccs.push_back(alignment140600592032400);
+
+ SeparationConstraint *separation140600592044112 = new SeparationConstraint(vpsc::XDIM, alignment140600592031296, alignment140600592031936, 4, false);
+ ccs.push_back(separation140600592044112);
+
+ SeparationConstraint *separation140600592045280 = new SeparationConstraint(vpsc::XDIM, alignment140600592031936, alignment140600592031168, 67, false);
+ ccs.push_back(separation140600592045280);
+
+ SeparationConstraint *separation140600592045376 = new SeparationConstraint(vpsc::XDIM, alignment140600592031168, alignment140600592031776, 71, false);
+ ccs.push_back(separation140600592045376);
+
+ SeparationConstraint *separation140600592045520 = new SeparationConstraint(vpsc::XDIM, alignment140600592031776, alignment140600592030544, 29, false);
+ ccs.push_back(separation140600592045520);
+
+ SeparationConstraint *separation140600592045696 = new SeparationConstraint(vpsc::XDIM, alignment140600592030544, alignment140600592031040, 41, false);
+ ccs.push_back(separation140600592045696);
+
+ SeparationConstraint *separation140600592045872 = new SeparationConstraint(vpsc::XDIM, alignment140600592031040, alignment140600592031616, 59, false);
+ ccs.push_back(separation140600592045872);
+
+ SeparationConstraint *separation140600592043472 = new SeparationConstraint(vpsc::XDIM, alignment140600592031616, alignment140600592030848, 67, false);
+ ccs.push_back(separation140600592043472);
+
+ SeparationConstraint *separation140600592043648 = new SeparationConstraint(vpsc::XDIM, alignment140600592030848, alignment140600592031456, 60, false);
+ ccs.push_back(separation140600592043648);
+
+ SeparationConstraint *separation140600592043824 = new SeparationConstraint(vpsc::XDIM, alignment140600592031456, alignment140600592032400, 92, false);
+ ccs.push_back(separation140600592043824);
+
+ SeparationConstraint *separation140600592046048 = new SeparationConstraint(vpsc::XDIM, alignment140600592032400, alignment140600592032240, 3, false);
+ ccs.push_back(separation140600592046048);
+
+ AlignmentConstraint *alignment140600592044208 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140600592044208->addShape(0, 0);
+ ccs.push_back(alignment140600592044208);
+
+ AlignmentConstraint *alignment140600592044368 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140600592044368->addShape(5, 0);
+ ccs.push_back(alignment140600592044368);
+
+ AlignmentConstraint *alignment140600592044528 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140600592044528->addShape(1, 0);
+ alignment140600592044528->addShape(9, 0);
+ alignment140600592044528->addShape(10, 0);
+ ccs.push_back(alignment140600592044528);
+
+ AlignmentConstraint *alignment140600592044752 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140600592044752->addShape(6, 0);
+ alignment140600592044752->addShape(4, 0);
+ alignment140600592044752->addShape(7, 0);
+ alignment140600592044752->addShape(8, 0);
+ alignment140600592044752->addShape(3, 0);
+ alignment140600592044752->addShape(11, 0);
+ alignment140600592044752->addShape(2, 0);
+ ccs.push_back(alignment140600592044752);
+
+ SeparationConstraint *separation140600592045088 = new SeparationConstraint(vpsc::YDIM, alignment140600592044752, alignment140600592044368, 22.1429, false);
+ ccs.push_back(separation140600592045088);
+
+ SeparationConstraint *separation140600590330720 = new SeparationConstraint(vpsc::YDIM, alignment140600592044368, alignment140600592044208, 18, false);
+ ccs.push_back(separation140600590330720);
+
+ SeparationConstraint *separation140600590330896 = new SeparationConstraint(vpsc::YDIM, alignment140600592044208, alignment140600592044528, 42, false);
+ ccs.push_back(separation140600590330896);
+
+ AlignmentConstraint *alignment140600590331072 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140600590331072->addShape(0, 0);
+ alignment140600590331072->addShape(12, 0);
+ ccs.push_back(alignment140600590331072);
+
+ SeparationConstraint *separation140600590331376 = new SeparationConstraint(vpsc::YDIM, 0, 12, 50, true);
+ ccs.push_back(separation140600590331376);
+
+ AlignmentConstraint *alignment140600590331520 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140600590331520->addShape(1, 0);
+ alignment140600590331520->addShape(13, 0);
+ ccs.push_back(alignment140600590331520);
+
+ SeparationConstraint *separation140600590331744 = new SeparationConstraint(vpsc::YDIM, 1, 13, -50, true);
+ ccs.push_back(separation140600590331744);
+
+ AlignmentConstraint *alignment140600590331888 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140600590331888->addShape(2, 0);
+ alignment140600590331888->addShape(14, 0);
+ ccs.push_back(alignment140600590331888);
+
+ SeparationConstraint *separation140600590332112 = new SeparationConstraint(vpsc::YDIM, 2, 14, -50, true);
+ ccs.push_back(separation140600590332112);
+
+ AlignmentConstraint *alignment140600592043200 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140600592043200->addShape(3, 0);
+ alignment140600592043200->addShape(15, 0);
+ ccs.push_back(alignment140600592043200);
+
+ SeparationConstraint *separation140600590332784 = new SeparationConstraint(vpsc::YDIM, 3, 15, -50, true);
+ ccs.push_back(separation140600590332784);
+
+ AlignmentConstraint *alignment140600590332880 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140600590332880->addShape(4, 0);
+ alignment140600590332880->addShape(16, 0);
+ ccs.push_back(alignment140600590332880);
+
+ SeparationConstraint *separation140600590333104 = new SeparationConstraint(vpsc::XDIM, 4, 16, 62, true);
+ ccs.push_back(separation140600590333104);
+
+ ConstrainedFDLayout alg(rs, es, defaultEdgeLength);
+ alg.setAvoidNodeOverlaps(true);
+ RootCluster *cluster140600590333360 = new RootCluster();
+ alg.setClusterHierarchy(cluster140600590333360);
+ alg.setConstraints(ccs);
+ alg.makeFeasible();
+ alg.run();
+ alg.outputInstanceToSVG("test-StillOverlap01");
+ alg.freeAssociatedObjects();
+ return 0;
+};
+
diff --git a/src/3rdparty/adaptagrams/libcola/tests/StillOverlap02.cpp b/src/3rdparty/adaptagrams/libcola/tests/StillOverlap02.cpp
new file mode 100755
index 0000000..c45eef6
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/StillOverlap02.cpp
@@ -0,0 +1,1863 @@
+#include <vector>
+#include "libcola/cola.h"
+using namespace cola;
+int main(void) {
+ CompoundConstraints ccs;
+ std::vector<Edge> es;
+ double defaultEdgeLength=40;
+ std::vector<vpsc::Rectangle*> rs;
+ vpsc::Rectangle *rect = nullptr;
+
+ rect = new vpsc::Rectangle(80.8448, 110.845, -23.9565, 6.04346);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(-121.155, 128.845, -212.957, -142.957);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(209.095, 239.095, -389.957, -359.957);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(209.095, 239.095, -240.957, -210.957);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(274.428, 304.428, -130.957, -100.957);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(140.845, 170.845, -78.9565, -48.9565);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(80.8448, 110.845, -55.9565, -25.9565);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(501.428, 531.428, -232.623, -202.623);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(501.428, 531.428, -140.623, -110.623);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(485.428, 515.428, -33.3565, -3.35654);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(737.928, 767.928, -133.957, -103.957);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(140.845, 170.845, 314.043, 344.043);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(375.428, 405.428, 191.443, 221.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(443.428, 473.428, 202.243, 232.243);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(558.428, 588.428, 136.777, 166.777);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(634.214, 664.214, 136.777, 166.777);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(764.214, 794.214, 136.777, 166.777);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(819.095, 849.095, 156.443, 186.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(853.595, 883.595, 76.0435, 106.043);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(711.928, 741.928, 202.243, 232.243);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(542.428, 572.428, 280.443, 310.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(296.428, 326.428, 440.943, 470.943);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(202.428, 232.428, 693.943, 723.943);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(407.428, 473.428, 685.943, 735.943);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(375.428, 405.428, 693.943, 723.943);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(542.428, 572.428, 632.443, 662.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(517.428, 547.428, 444.443, 474.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(566.928, 596.928, 444.443, 474.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(879.345, 909.345, 280.443, 310.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(879.345, 909.345, 478.443, 508.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(836.095, 866.095, 332.443, 362.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(797.928, 827.928, 436.443, 466.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(55.8448, 85.8448, 507.443, 537.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(375.428, 405.428, 1026.76, 1056.76);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(375.428, 405.428, 1074.76, 1104.76);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(-102.489, -72.4885, 1051.76, 1081.76);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(797.928, 827.928, 802.515, 832.515);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(839.928, 1079.93, 198.443, 268.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(768, 1008, 844.515, 914.515);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(626.928, 656.928, 972.765, 1002.76);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(426.956, 456.956, 972.765, 1002.76);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(224.428, 254.428, 972.765, 1002.76);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(375.428, 405.428, 870.765, 900.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(255.428, 285.428, 870.765, 900.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(744.928, 774.928, 332.443, 362.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(30, 354, -347.957, -302.957);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(-183.905, 137.095, 68.0435, 252.043);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(375.428, 405.428, 530.443, 560.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(375.428, 405.428, 332.443, 362.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1.84481, 31.8448, 870.765, 900.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(127.095, 157.095, 870.765, 900.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(991.345, 1021.34, 478.443, 508.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(991.345, 1021.34, 600.443, 630.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(38.8448, 68.8448, 693.943, 723.943);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(-58.1552, -28.1552, 768.765, 798.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(130.845, 180.845, -399.957, -349.957);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(130.845, 180.845, -250.957, -200.957);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(-112.489, -62.4885, -43.3565, 6.64346);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(289.428, 339.428, 192.243, 242.243);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(532.428, 582.428, 192.243, 242.243);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(567.428, 617.428, -150.623, -100.623);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(843.595, 893.595, -150.623, -100.623);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(616.928, 666.928, -43.3565, 6.64346);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(787.928, 837.928, -43.3565, 6.64346);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(869.345, 919.345, 520.443, 570.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(289.428, 339.428, 322.443, 372.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(130.845, 180.845, 430.943, 480.943);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(869.345, 919.345, 374.443, 424.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(286.428, 336.428, 683.943, 733.943);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(130.845, 180.845, 520.443, 570.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(130.845, 180.845, 1116.76, 1166.76);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(676.928, 726.928, 962.765, 1012.76);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(520.428, 570.428, 962.765, 1012.76);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(336.428, 386.428, 962.765, 1012.76);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(676.928, 726.928, 860.765, 910.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(130.845, 180.845, 1064.76, 1114.76);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(425.428, 475.428, 860.765, 910.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(305.428, 355.428, 860.765, 910.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(787.928, 837.928, 1064.76, 1114.76);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(532.428, 582.428, 520.443, 570.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(787.928, 837.928, 192.243, 242.243);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(295.428, 345.428, 520.443, 570.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(475.428, 525.428, 683.943, 733.943);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(113.095, 163.095, 683.943, 733.943);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(-19.1552, 30.8448, 520.443, 570.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(295.428, 345.428, 572.443, 622.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(295.428, 345.428, 631.943, 681.943);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(289.428, 339.428, -43.3565, 6.64346);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(177.428, 227.428, 860.765, 910.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(289.428, 339.428, -250.957, -200.957);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(532.428, 582.428, 322.443, 372.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(787.928, 837.928, 622.443, 672.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(556.928, 606.928, 860.765, 910.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(139.095, 189.095, 66.0435, 116.043);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(-68.1552, -18.1552, 683.943, 733.943);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(425.428, 475.428, 758.765, 808.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(177.428, 227.428, 758.765, 808.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(51.8448, 101.845, 860.765, 910.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(-68.1552, -18.1552, 860.765, 910.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(305.428, 355.428, 758.765, 808.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(616.928, 666.928, 218.443, 268.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(981.345, 1031.34, 520.443, 570.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(981.345, 1031.34, 656.943, 706.943);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(592.428, 839.428, 486.443, 556.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(626.928, 656.928, 596.443, 626.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(616.928, 666.928, 656.943, 706.943);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(616.928, 666.928, 750.515, 800.515);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(626.928, 656.928, 717.515, 747.515);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(209.095, 239.095, 76.0435, 106.043);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(62.8448, 128.845, 16.0435, 66.0435);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(191.095, 257.095, -449.957, -399.957);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(191.095, 257.095, -300.957, -250.957);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(194.428, 260.428, -140.957, -90.9565);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(184.845, 250.845, -88.9565, -38.9565);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(62.8448, 128.845, -115.957, -65.9565);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(483.428, 549.428, -292.623, -242.623);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(483.428, 549.428, -200.623, -150.623);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(467.428, 533.428, -93.3565, -43.3565);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(719.928, 785.928, -93.9565, -43.9565);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(122.845, 188.845, 254.043, 304.043);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(357.428, 423.428, 131.443, 181.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(425.428, 491.428, 142.243, 192.243);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(540.428, 606.428, 76.7768, 126.777);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(616.214, 682.214, 76.7768, 126.777);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(684.214, 750.214, 126.777, 176.777);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(863.095, 929.095, 146.443, 196.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(897.595, 963.595, 66.0435, 116.043);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(693.928, 759.928, 242.243, 292.243);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(586.428, 652.428, 270.443, 320.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(278.428, 344.428, 380.943, 430.943);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(184.428, 250.428, 633.943, 683.943);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(357.428, 423.428, 633.943, 683.943);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(524.428, 590.428, 572.443, 622.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(437.428, 503.428, 434.443, 484.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(610.928, 676.928, 434.443, 484.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(923.345, 989.345, 270.443, 320.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(923.345, 989.345, 468.443, 518.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(880.095, 946.095, 322.443, 372.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(841.928, 907.928, 426.443, 476.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(37.8448, 103.845, 447.443, 497.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(357.428, 423.428, 1066.76, 1116.76);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(357.428, 423.428, 1014.76, 1064.76);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(-58.4885, 7.51148, 1041.76, 1091.76);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(841.928, 907.928, 792.515, 842.515);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(608.928, 674.928, 912.765, 962.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(408.956, 474.956, 912.765, 962.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(268.428, 334.428, 962.765, 1012.76);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(357.428, 423.428, 810.765, 860.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(237.428, 303.428, 810.765, 860.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(664.928, 730.928, 322.443, 372.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(357.428, 423.428, 470.443, 520.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(357.428, 423.428, 272.443, 322.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(-16.1552, 49.8448, 810.765, 860.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(109.095, 175.095, 810.765, 860.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1035.34, 1101.34, 468.443, 518.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1035.34, 1101.34, 590.443, 640.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(20.8448, 86.8448, 633.943, 683.943);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(-14.1552, 51.8448, 758.765, 808.765);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(670.928, 736.928, 586.443, 636.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(670.928, 736.928, 707.515, 757.515);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(191.095, 257.095, 16.0435, 66.0435);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(58.8448, 128.845, -192.957, -142.957);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(839.928, 909.928, 218.443, 268.443);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(768.5, 838.5, 844.515, 894.515);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(67.0948, 137.095, 150.043, 200.043);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(67.0948, 137.095, 202.043, 252.043);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(-36.9052, 13.0948, 182.043, 252.043);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(15.0948, 65.0948, 182.043, 252.043);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(592.428, 662.428, 486.443, 536.443);
+ rs.push_back(rect);
+
+ AlignmentConstraint *alignment1114387328 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1114387328->addShape(4, 0);
+ ccs.push_back(alignment1114387328);
+
+ AlignmentConstraint *alignment1103856272 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1103856272->addShape(0, 0);
+ alignment1103856272->addShape(6, 0);
+ ccs.push_back(alignment1103856272);
+
+ AlignmentConstraint *alignment1102536224 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1102536224->addShape(7, 0);
+ alignment1102536224->addShape(8, 0);
+ ccs.push_back(alignment1102536224);
+
+ AlignmentConstraint *alignment1113412976 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1113412976->addShape(10, 0);
+ ccs.push_back(alignment1113412976);
+
+ AlignmentConstraint *alignment1103859296 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1103859296->addShape(13, 0);
+ ccs.push_back(alignment1103859296);
+
+ AlignmentConstraint *alignment1108560576 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1108560576->addShape(14, 0);
+ ccs.push_back(alignment1108560576);
+
+ AlignmentConstraint *alignment1102536400 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1102536400->addShape(15, 0);
+ ccs.push_back(alignment1102536400);
+
+ AlignmentConstraint *alignment1102857472 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1102857472->addShape(16, 0);
+ ccs.push_back(alignment1102857472);
+
+ AlignmentConstraint *alignment1103856000 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1103856000->addShape(17, 0);
+ ccs.push_back(alignment1103856000);
+
+ AlignmentConstraint *alignment1103638512 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1103638512->addShape(19, 0);
+ ccs.push_back(alignment1103638512);
+
+ AlignmentConstraint *alignment1103638608 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1103638608->addShape(22, 0);
+ ccs.push_back(alignment1103638608);
+
+ AlignmentConstraint *alignment1095948608 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1095948608->addShape(26, 0);
+ ccs.push_back(alignment1095948608);
+
+ AlignmentConstraint *alignment1095948704 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1095948704->addShape(30, 0);
+ ccs.push_back(alignment1095948704);
+
+ AlignmentConstraint *alignment1109826288 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1109826288->addShape(32, 0);
+ ccs.push_back(alignment1109826288);
+
+ AlignmentConstraint *alignment1109826384 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1109826384->addShape(40, 0);
+ ccs.push_back(alignment1109826384);
+
+ AlignmentConstraint *alignment1110086352 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1110086352->addShape(41, 0);
+ ccs.push_back(alignment1110086352);
+
+ AlignmentConstraint *alignment1110086480 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1110086480->addShape(43, 0);
+ ccs.push_back(alignment1110086480);
+
+ AlignmentConstraint *alignment1100384896 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100384896->addShape(44, 0);
+ ccs.push_back(alignment1100384896);
+
+ AlignmentConstraint *alignment1100385056 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100385056->addShape(33, 0);
+ alignment1100385056->addShape(42, 0);
+ alignment1100385056->addShape(48, 0);
+ alignment1100385056->addShape(12, 0);
+ alignment1100385056->addShape(47, 0);
+ alignment1100385056->addShape(34, 0);
+ alignment1100385056->addShape(24, 0);
+ ccs.push_back(alignment1100385056);
+
+ AlignmentConstraint *alignment1114389776 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1114389776->addShape(49, 0);
+ ccs.push_back(alignment1114389776);
+
+ AlignmentConstraint *alignment1114389936 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1114389936->addShape(50, 0);
+ ccs.push_back(alignment1114389936);
+
+ AlignmentConstraint *alignment1103858368 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1103858368->addShape(53, 0);
+ ccs.push_back(alignment1103858368);
+
+ AlignmentConstraint *alignment1103858496 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1103858496->addShape(35, 0);
+ alignment1103858496->addShape(57, 0);
+ ccs.push_back(alignment1103858496);
+
+ AlignmentConstraint *alignment1103858720 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1103858720->addShape(60, 0);
+ ccs.push_back(alignment1103858720);
+
+ AlignmentConstraint *alignment1103857616 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1103857616->addShape(61, 0);
+ alignment1103857616->addShape(18, 0);
+ ccs.push_back(alignment1103857616);
+
+ AlignmentConstraint *alignment1103857840 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1103857840->addShape(64, 0);
+ alignment1103857840->addShape(28, 0);
+ alignment1103857840->addShape(67, 0);
+ alignment1103857840->addShape(29, 0);
+ ccs.push_back(alignment1103857840);
+
+ AlignmentConstraint *alignment1103858032 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1103858032->addShape(68, 0);
+ alignment1103858032->addShape(21, 0);
+ ccs.push_back(alignment1103858032);
+
+ AlignmentConstraint *alignment1103741312 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1103741312->addShape(72, 0);
+ ccs.push_back(alignment1103741312);
+
+ AlignmentConstraint *alignment1103741440 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1103741440->addShape(73, 0);
+ ccs.push_back(alignment1103741440);
+
+ AlignmentConstraint *alignment1103741600 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1103741600->addShape(71, 0);
+ alignment1103741600->addShape(74, 0);
+ ccs.push_back(alignment1103741600);
+
+ AlignmentConstraint *alignment1103741824 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1103741824->addShape(66, 0);
+ alignment1103741824->addShape(56, 0);
+ alignment1103741824->addShape(70, 0);
+ alignment1103741824->addShape(69, 0);
+ alignment1103741824->addShape(5, 0);
+ alignment1103741824->addShape(11, 0);
+ alignment1103741824->addShape(55, 0);
+ alignment1103741824->addShape(75, 0);
+ ccs.push_back(alignment1103741824);
+
+ AlignmentConstraint *alignment1103742144 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1103742144->addShape(9, 0);
+ alignment1103742144->addShape(82, 0);
+ ccs.push_back(alignment1103742144);
+
+ AlignmentConstraint *alignment1103743632 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1103743632->addShape(83, 0);
+ ccs.push_back(alignment1103743632);
+
+ AlignmentConstraint *alignment1113416080 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1113416080->addShape(84, 0);
+ ccs.push_back(alignment1113416080);
+
+ AlignmentConstraint *alignment1113416240 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1113416240->addShape(81, 0);
+ alignment1113416240->addShape(85, 0);
+ alignment1113416240->addShape(86, 0);
+ ccs.push_back(alignment1113416240);
+
+ AlignmentConstraint *alignment1103744288 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1103744288->addShape(87, 0);
+ alignment1103744288->addShape(89, 0);
+ alignment1103744288->addShape(58, 0);
+ alignment1103744288->addShape(65, 0);
+ ccs.push_back(alignment1103744288);
+
+ AlignmentConstraint *alignment1103744448 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1103744448->addShape(79, 0);
+ alignment1103744448->addShape(59, 0);
+ alignment1103744448->addShape(90, 0);
+ alignment1103744448->addShape(25, 0);
+ alignment1103744448->addShape(20, 0);
+ ccs.push_back(alignment1103744448);
+
+ AlignmentConstraint *alignment1103744704 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1103744704->addShape(80, 0);
+ alignment1103744704->addShape(91, 0);
+ alignment1103744704->addShape(63, 0);
+ alignment1103744704->addShape(31, 0);
+ alignment1103744704->addShape(78, 0);
+ alignment1103744704->addShape(36, 0);
+ ccs.push_back(alignment1103744704);
+
+ AlignmentConstraint *alignment1103744992 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1103744992->addShape(27, 0);
+ alignment1103744992->addShape(92, 0);
+ ccs.push_back(alignment1103744992);
+
+ AlignmentConstraint *alignment1114376272 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1114376272->addShape(93, 0);
+ ccs.push_back(alignment1114376272);
+
+ AlignmentConstraint *alignment1114376400 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1114376400->addShape(95, 0);
+ alignment1114376400->addShape(76, 0);
+ ccs.push_back(alignment1114376400);
+
+ AlignmentConstraint *alignment1114376624 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1114376624->addShape(96, 0);
+ alignment1114376624->addShape(88, 0);
+ ccs.push_back(alignment1114376624);
+
+ AlignmentConstraint *alignment1114376816 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1114376816->addShape(97, 0);
+ ccs.push_back(alignment1114376816);
+
+ AlignmentConstraint *alignment1114376944 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1114376944->addShape(94, 0);
+ alignment1114376944->addShape(54, 0);
+ alignment1114376944->addShape(98, 0);
+ ccs.push_back(alignment1114376944);
+
+ AlignmentConstraint *alignment1114377168 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1114377168->addShape(77, 0);
+ alignment1114377168->addShape(99, 0);
+ ccs.push_back(alignment1114377168);
+
+ AlignmentConstraint *alignment1114377360 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1114377360->addShape(51, 0);
+ alignment1114377360->addShape(101, 0);
+ alignment1114377360->addShape(102, 0);
+ alignment1114377360->addShape(52, 0);
+ ccs.push_back(alignment1114377360);
+
+ AlignmentConstraint *alignment1114377600 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1114377600->addShape(107, 0);
+ alignment1114377600->addShape(62, 0);
+ alignment1114377600->addShape(105, 0);
+ alignment1114377600->addShape(106, 0);
+ alignment1114377600->addShape(104, 0);
+ alignment1114377600->addShape(39, 0);
+ alignment1114377600->addShape(100, 0);
+ ccs.push_back(alignment1114377600);
+
+ AlignmentConstraint *alignment1114378048 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1114378048->addShape(3, 0);
+ alignment1114378048->addShape(2, 0);
+ alignment1114378048->addShape(108, 0);
+ ccs.push_back(alignment1114378048);
+
+ SeparationConstraint *separation1114378272 = new SeparationConstraint(vpsc::XDIM, alignment1103858496, alignment1114376944, 44.3333, false);
+ ccs.push_back(separation1114378272);
+
+ SeparationConstraint *separation1114378416 = new SeparationConstraint(vpsc::XDIM, alignment1114376944, alignment1113416080, 24.6667, false);
+ ccs.push_back(separation1114378416);
+
+ SeparationConstraint *separation1114378592 = new SeparationConstraint(vpsc::XDIM, alignment1113416080, alignment1114389776, 11, false);
+ ccs.push_back(separation1114378592);
+
+ SeparationConstraint *separation1114378768 = new SeparationConstraint(vpsc::XDIM, alignment1114389776, alignment1103858368, 23, false);
+ ccs.push_back(separation1114378768);
+
+ SeparationConstraint *separation1114378944 = new SeparationConstraint(vpsc::XDIM, alignment1103858368, alignment1109826288, 17, false);
+ ccs.push_back(separation1114378944);
+
+ SeparationConstraint *separation1114379120 = new SeparationConstraint(vpsc::XDIM, alignment1109826288, alignment1114376816, 6, false);
+ ccs.push_back(separation1114379120);
+
+ SeparationConstraint *separation1114379296 = new SeparationConstraint(vpsc::XDIM, alignment1114376816, alignment1103856272, 19, false);
+ ccs.push_back(separation1114379296);
+
+ SeparationConstraint *separation1114379472 = new SeparationConstraint(vpsc::XDIM, alignment1103856272, alignment1103743632, 14, false);
+ ccs.push_back(separation1114379472);
+
+ SeparationConstraint *separation1114379648 = new SeparationConstraint(vpsc::XDIM, alignment1103743632, alignment1114389936, 4, false);
+ ccs.push_back(separation1114379648);
+
+ SeparationConstraint *separation1114379824 = new SeparationConstraint(vpsc::XDIM, alignment1114389936, alignment1103741824, 13.75, false);
+ ccs.push_back(separation1114379824);
+
+ SeparationConstraint *separation1114380000 = new SeparationConstraint(vpsc::XDIM, alignment1103741824, alignment1114376272, 8.25, false);
+ ccs.push_back(separation1114380000);
+
+ SeparationConstraint *separation1114380176 = new SeparationConstraint(vpsc::XDIM, alignment1114376272, alignment1114376624, 23, false);
+ ccs.push_back(separation1114380176);
+
+ SeparationConstraint *separation1114380352 = new SeparationConstraint(vpsc::XDIM, alignment1114376624, alignment1103638608, 15, false);
+ ccs.push_back(separation1114380352);
+
+ SeparationConstraint *separation1114380528 = new SeparationConstraint(vpsc::XDIM, alignment1103638608, alignment1114378048, 6.66667, false);
+ ccs.push_back(separation1114380528);
+
+ SeparationConstraint *separation1114380704 = new SeparationConstraint(vpsc::XDIM, alignment1114378048, alignment1110086352, 15.3333, false);
+ ccs.push_back(separation1114380704);
+
+ SeparationConstraint *separation1114380880 = new SeparationConstraint(vpsc::XDIM, alignment1110086352, alignment1110086480, 8, false);
+ ccs.push_back(separation1114380880);
+
+ SeparationConstraint *separation1114381056 = new SeparationConstraint(vpsc::XDIM, alignment1110086480, alignment1114387328, 5, false);
+ ccs.push_back(separation1114381056);
+
+ SeparationConstraint *separation1116666144 = new SeparationConstraint(vpsc::XDIM, alignment1114387328, alignment1103858032, 22, false);
+ ccs.push_back(separation1116666144);
+
+ SeparationConstraint *separation1103743760 = new SeparationConstraint(vpsc::XDIM, alignment1103858032, alignment1103744288, 3, false);
+ ccs.push_back(separation1103743760);
+
+ SeparationConstraint *separation1103743904 = new SeparationConstraint(vpsc::XDIM, alignment1103744288, alignment1113416240, 6, false);
+ ccs.push_back(separation1103743904);
+
+ SeparationConstraint *separation1103744080 = new SeparationConstraint(vpsc::XDIM, alignment1113416240, alignment1114377168, 10, false);
+ ccs.push_back(separation1103744080);
+
+ SeparationConstraint *separation1114381232 = new SeparationConstraint(vpsc::XDIM, alignment1114377168, alignment1103741440, 17, false);
+ ccs.push_back(separation1114381232);
+
+ SeparationConstraint *separation1114381376 = new SeparationConstraint(vpsc::XDIM, alignment1103741440, alignment1100385056, 29, false);
+ ccs.push_back(separation1114381376);
+
+ SeparationConstraint *separation1114381552 = new SeparationConstraint(vpsc::XDIM, alignment1100385056, alignment1109826384, 41, false);
+ ccs.push_back(separation1114381552);
+
+ SeparationConstraint *separation1114381728 = new SeparationConstraint(vpsc::XDIM, alignment1109826384, alignment1114376400, 4, false);
+ ccs.push_back(separation1114381728);
+
+ SeparationConstraint *separation1114370064 = new SeparationConstraint(vpsc::XDIM, alignment1114376400, alignment1103859296, 3, false);
+ ccs.push_back(separation1114370064);
+
+ SeparationConstraint *separation1114370240 = new SeparationConstraint(vpsc::XDIM, alignment1103859296, alignment1103742144, 7, false);
+ ccs.push_back(separation1114370240);
+
+ SeparationConstraint *separation1114370416 = new SeparationConstraint(vpsc::XDIM, alignment1103742144, alignment1102536224, 16, false);
+ ccs.push_back(separation1114370416);
+
+ SeparationConstraint *separation1114370592 = new SeparationConstraint(vpsc::XDIM, alignment1102536224, alignment1095948608, 16, false);
+ ccs.push_back(separation1114370592);
+
+ SeparationConstraint *separation1114370768 = new SeparationConstraint(vpsc::XDIM, alignment1095948608, alignment1103741312, 13, false);
+ ccs.push_back(separation1114370768);
+
+ SeparationConstraint *separation1114370944 = new SeparationConstraint(vpsc::XDIM, alignment1103741312, alignment1103744448, 12, false);
+ ccs.push_back(separation1114370944);
+
+ SeparationConstraint *separation1114371120 = new SeparationConstraint(vpsc::XDIM, alignment1103744448, alignment1108560576, 16, false);
+ ccs.push_back(separation1114371120);
+
+ SeparationConstraint *separation1114371296 = new SeparationConstraint(vpsc::XDIM, alignment1108560576, alignment1103744992, 8.5, false);
+ ccs.push_back(separation1114371296);
+
+ SeparationConstraint *separation1114371472 = new SeparationConstraint(vpsc::XDIM, alignment1103744992, alignment1103858720, 10.5, false);
+ ccs.push_back(separation1114371472);
+
+ SeparationConstraint *separation1114371648 = new SeparationConstraint(vpsc::XDIM, alignment1103858720, alignment1114377600, 23.7143, false);
+ ccs.push_back(separation1114371648);
+
+ SeparationConstraint *separation1114371824 = new SeparationConstraint(vpsc::XDIM, alignment1114377600, alignment1102536400, 7.28571, false);
+ ccs.push_back(separation1114371824);
+
+ SeparationConstraint *separation1114372000 = new SeparationConstraint(vpsc::XDIM, alignment1102536400, alignment1103741600, 49, false);
+ ccs.push_back(separation1114372000);
+
+ SeparationConstraint *separation1114372176 = new SeparationConstraint(vpsc::XDIM, alignment1103741600, alignment1103638512, 25, false);
+ ccs.push_back(separation1114372176);
+
+ SeparationConstraint *separation1114372352 = new SeparationConstraint(vpsc::XDIM, alignment1103638512, alignment1113412976, 26, false);
+ ccs.push_back(separation1114372352);
+
+ SeparationConstraint *separation1114372528 = new SeparationConstraint(vpsc::XDIM, alignment1113412976, alignment1100384896, 7, false);
+ ccs.push_back(separation1114372528);
+
+ SeparationConstraint *separation1114372704 = new SeparationConstraint(vpsc::XDIM, alignment1100384896, alignment1102857472, 15, false);
+ ccs.push_back(separation1114372704);
+
+ SeparationConstraint *separation1114372880 = new SeparationConstraint(vpsc::XDIM, alignment1102857472, alignment1103744704, 21.8333, false);
+ ccs.push_back(separation1114372880);
+
+ SeparationConstraint *separation1114373056 = new SeparationConstraint(vpsc::XDIM, alignment1103744704, alignment1103856000, 21.1667, false);
+ ccs.push_back(separation1114373056);
+
+ SeparationConstraint *separation1114373232 = new SeparationConstraint(vpsc::XDIM, alignment1103856000, alignment1095948704, 17, false);
+ ccs.push_back(separation1114373232);
+
+ SeparationConstraint *separation1114373408 = new SeparationConstraint(vpsc::XDIM, alignment1095948704, alignment1103857616, 17.5, false);
+ ccs.push_back(separation1114373408);
+
+ SeparationConstraint *separation1114373584 = new SeparationConstraint(vpsc::XDIM, alignment1103857616, alignment1103857840, 25.75, false);
+ ccs.push_back(separation1114373584);
+
+ SeparationConstraint *separation1114373760 = new SeparationConstraint(vpsc::XDIM, alignment1103857840, alignment1114377360, 52.25, false);
+ ccs.push_back(separation1114373760);
+
+ AlignmentConstraint *alignment1114373936 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114373936->addShape(0, 0);
+ ccs.push_back(alignment1114373936);
+
+ AlignmentConstraint *alignment1114374096 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114374096->addShape(4, 0);
+ ccs.push_back(alignment1114374096);
+
+ AlignmentConstraint *alignment1114374256 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114374256->addShape(5, 0);
+ ccs.push_back(alignment1114374256);
+
+ AlignmentConstraint *alignment1114374416 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114374416->addShape(6, 0);
+ ccs.push_back(alignment1114374416);
+
+ AlignmentConstraint *alignment1114374576 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114374576->addShape(7, 0);
+ ccs.push_back(alignment1114374576);
+
+ AlignmentConstraint *alignment1114374736 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114374736->addShape(10, 0);
+ ccs.push_back(alignment1114374736);
+
+ AlignmentConstraint *alignment1114374896 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114374896->addShape(11, 0);
+ ccs.push_back(alignment1114374896);
+
+ AlignmentConstraint *alignment1114375056 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114375056->addShape(12, 0);
+ ccs.push_back(alignment1114375056);
+
+ AlignmentConstraint *alignment1114375216 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114375216->addShape(15, 0);
+ alignment1114375216->addShape(16, 0);
+ alignment1114375216->addShape(14, 0);
+ ccs.push_back(alignment1114375216);
+
+ AlignmentConstraint *alignment1114375488 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114375488->addShape(17, 0);
+ ccs.push_back(alignment1114375488);
+
+ AlignmentConstraint *alignment1114375616 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114375616->addShape(26, 0);
+ alignment1114375616->addShape(27, 0);
+ ccs.push_back(alignment1114375616);
+
+ AlignmentConstraint *alignment1114375840 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114375840->addShape(28, 0);
+ alignment1114375840->addShape(20, 0);
+ ccs.push_back(alignment1114375840);
+
+ AlignmentConstraint *alignment1114429984 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114429984->addShape(31, 0);
+ ccs.push_back(alignment1114429984);
+
+ AlignmentConstraint *alignment1114430112 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114430112->addShape(32, 0);
+ ccs.push_back(alignment1114430112);
+
+ AlignmentConstraint *alignment1114430272 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114430272->addShape(33, 0);
+ ccs.push_back(alignment1114430272);
+
+ AlignmentConstraint *alignment1114430432 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114430432->addShape(35, 0);
+ ccs.push_back(alignment1114430432);
+
+ AlignmentConstraint *alignment1114430592 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114430592->addShape(36, 0);
+ ccs.push_back(alignment1114430592);
+
+ AlignmentConstraint *alignment1114430752 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114430752->addShape(51, 0);
+ alignment1114430752->addShape(29, 0);
+ ccs.push_back(alignment1114430752);
+
+ AlignmentConstraint *alignment1114430976 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114430976->addShape(52, 0);
+ ccs.push_back(alignment1114430976);
+
+ AlignmentConstraint *alignment1114431104 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114431104->addShape(55, 0);
+ alignment1114431104->addShape(2, 0);
+ ccs.push_back(alignment1114431104);
+
+ AlignmentConstraint *alignment1114431328 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114431328->addShape(61, 0);
+ alignment1114431328->addShape(60, 0);
+ alignment1114431328->addShape(8, 0);
+ ccs.push_back(alignment1114431328);
+
+ AlignmentConstraint *alignment1114431568 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114431568->addShape(66, 0);
+ alignment1114431568->addShape(21, 0);
+ ccs.push_back(alignment1114431568);
+
+ AlignmentConstraint *alignment1114431760 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114431760->addShape(67, 0);
+ ccs.push_back(alignment1114431760);
+
+ AlignmentConstraint *alignment1114431888 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114431888->addShape(70, 0);
+ ccs.push_back(alignment1114431888);
+
+ AlignmentConstraint *alignment1114432048 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114432048->addShape(71, 0);
+ alignment1114432048->addShape(73, 0);
+ alignment1114432048->addShape(40, 0);
+ alignment1114432048->addShape(72, 0);
+ alignment1114432048->addShape(41, 0);
+ alignment1114432048->addShape(39, 0);
+ ccs.push_back(alignment1114432048);
+
+ AlignmentConstraint *alignment1114432464 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114432464->addShape(78, 0);
+ alignment1114432464->addShape(75, 0);
+ alignment1114432464->addShape(34, 0);
+ ccs.push_back(alignment1114432464);
+
+ AlignmentConstraint *alignment1114432688 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114432688->addShape(13, 0);
+ alignment1114432688->addShape(19, 0);
+ alignment1114432688->addShape(58, 0);
+ alignment1114432688->addShape(80, 0);
+ alignment1114432688->addShape(59, 0);
+ ccs.push_back(alignment1114432688);
+
+ AlignmentConstraint *alignment1114433040 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114433040->addShape(85, 0);
+ ccs.push_back(alignment1114433040);
+
+ AlignmentConstraint *alignment1114433200 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114433200->addShape(86, 0);
+ ccs.push_back(alignment1114433200);
+
+ AlignmentConstraint *alignment1114433360 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114433360->addShape(87, 0);
+ alignment1114433360->addShape(9, 0);
+ alignment1114433360->addShape(62, 0);
+ alignment1114433360->addShape(63, 0);
+ alignment1114433360->addShape(57, 0);
+ ccs.push_back(alignment1114433360);
+
+ AlignmentConstraint *alignment1114433696 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114433696->addShape(56, 0);
+ alignment1114433696->addShape(3, 0);
+ alignment1114433696->addShape(89, 0);
+ ccs.push_back(alignment1114433696);
+
+ AlignmentConstraint *alignment1114433920 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114433920->addShape(65, 0);
+ alignment1114433920->addShape(48, 0);
+ alignment1114433920->addShape(30, 0);
+ alignment1114433920->addShape(90, 0);
+ alignment1114433920->addShape(44, 0);
+ ccs.push_back(alignment1114433920);
+
+ AlignmentConstraint *alignment1114434272 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114434272->addShape(91, 0);
+ alignment1114434272->addShape(25, 0);
+ ccs.push_back(alignment1114434272);
+
+ AlignmentConstraint *alignment1114434496 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114434496->addShape(68, 0);
+ alignment1114434496->addShape(94, 0);
+ alignment1114434496->addShape(83, 0);
+ alignment1114434496->addShape(22, 0);
+ alignment1114434496->addShape(53, 0);
+ alignment1114434496->addShape(24, 0);
+ alignment1114434496->addShape(82, 0);
+ ccs.push_back(alignment1114434496);
+
+ AlignmentConstraint *alignment1114436928 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114436928->addShape(97, 0);
+ alignment1114436928->addShape(43, 0);
+ alignment1114436928->addShape(49, 0);
+ alignment1114436928->addShape(77, 0);
+ alignment1114436928->addShape(42, 0);
+ alignment1114436928->addShape(74, 0);
+ alignment1114436928->addShape(76, 0);
+ alignment1114436928->addShape(50, 0);
+ alignment1114436928->addShape(88, 0);
+ alignment1114436928->addShape(92, 0);
+ alignment1114436928->addShape(98, 0);
+ ccs.push_back(alignment1114436928);
+
+ AlignmentConstraint *alignment1114369232 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114369232->addShape(96, 0);
+ alignment1114369232->addShape(95, 0);
+ alignment1114369232->addShape(99, 0);
+ alignment1114369232->addShape(54, 0);
+ ccs.push_back(alignment1114369232);
+
+ AlignmentConstraint *alignment1114369456 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114369456->addShape(100, 0);
+ ccs.push_back(alignment1114369456);
+
+ AlignmentConstraint *alignment1114369616 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114369616->addShape(81, 0);
+ alignment1114369616->addShape(101, 0);
+ alignment1114369616->addShape(69, 0);
+ alignment1114369616->addShape(79, 0);
+ alignment1114369616->addShape(64, 0);
+ alignment1114369616->addShape(47, 0);
+ alignment1114369616->addShape(84, 0);
+ ccs.push_back(alignment1114369616);
+
+ AlignmentConstraint *alignment1114437392 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114437392->addShape(104, 0);
+ ccs.push_back(alignment1114437392);
+
+ AlignmentConstraint *alignment1100848528 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100848528->addShape(102, 0);
+ alignment1100848528->addShape(105, 0);
+ ccs.push_back(alignment1100848528);
+
+ AlignmentConstraint *alignment1100848752 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100848752->addShape(106, 0);
+ ccs.push_back(alignment1100848752);
+
+ AlignmentConstraint *alignment1100848880 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100848880->addShape(107, 0);
+ ccs.push_back(alignment1100848880);
+
+ AlignmentConstraint *alignment1100849040 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100849040->addShape(18, 0);
+ alignment1100849040->addShape(93, 0);
+ alignment1100849040->addShape(108, 0);
+ ccs.push_back(alignment1100849040);
+
+ SeparationConstraint *separation1100849264 = new SeparationConstraint(vpsc::YDIM, alignment1114431104, alignment1114433696, 30.1667, false);
+ ccs.push_back(separation1100849264);
+
+ SeparationConstraint *separation1100849360 = new SeparationConstraint(vpsc::YDIM, alignment1114433696, alignment1114374576, 8.33333, false);
+ ccs.push_back(separation1100849360);
+
+ SeparationConstraint *separation1100849536 = new SeparationConstraint(vpsc::YDIM, alignment1114374576, alignment1114431328, 18.3333, false);
+ ccs.push_back(separation1100849536);
+
+ SeparationConstraint *separation1100849712 = new SeparationConstraint(vpsc::YDIM, alignment1114431328, alignment1114374736, 6.66667, false);
+ ccs.push_back(separation1100849712);
+
+ SeparationConstraint *separation1100849888 = new SeparationConstraint(vpsc::YDIM, alignment1114374736, alignment1114374096, 3, false);
+ ccs.push_back(separation1100849888);
+
+ SeparationConstraint *separation1100850064 = new SeparationConstraint(vpsc::YDIM, alignment1114374096, alignment1114374256, 3, false);
+ ccs.push_back(separation1100850064);
+
+ SeparationConstraint *separation1100850240 = new SeparationConstraint(vpsc::YDIM, alignment1114374256, alignment1114374416, 23, false);
+ ccs.push_back(separation1100850240);
+
+ SeparationConstraint *separation1100850416 = new SeparationConstraint(vpsc::YDIM, alignment1114374416, alignment1114433360, 11.6, false);
+ ccs.push_back(separation1100850416);
+
+ SeparationConstraint *separation1100850592 = new SeparationConstraint(vpsc::YDIM, alignment1114433360, alignment1114373936, 9.4, false);
+ ccs.push_back(separation1100850592);
+
+ SeparationConstraint *separation1100850768 = new SeparationConstraint(vpsc::YDIM, alignment1114373936, alignment1100849040, 18.6667, false);
+ ccs.push_back(separation1100850768);
+
+ SeparationConstraint *separation1100850944 = new SeparationConstraint(vpsc::YDIM, alignment1100849040, alignment1114375216, 14.6667, false);
+ ccs.push_back(separation1100850944);
+
+ SeparationConstraint *separation1100851120 = new SeparationConstraint(vpsc::YDIM, alignment1114375216, alignment1114375488, 19.6667, false);
+ ccs.push_back(separation1100851120);
+
+ SeparationConstraint *separation1100851296 = new SeparationConstraint(vpsc::YDIM, alignment1114375488, alignment1114375056, 32, false);
+ ccs.push_back(separation1100851296);
+
+ SeparationConstraint *separation1100851472 = new SeparationConstraint(vpsc::YDIM, alignment1114375056, alignment1114432688, 10.8, false);
+ ccs.push_back(separation1100851472);
+
+ SeparationConstraint *separation1100851648 = new SeparationConstraint(vpsc::YDIM, alignment1114432688, alignment1114369456, 26.2, false);
+ ccs.push_back(separation1100851648);
+
+ SeparationConstraint *separation1100851824 = new SeparationConstraint(vpsc::YDIM, alignment1114369456, alignment1114375840, 7.5, false);
+ ccs.push_back(separation1100851824);
+
+ SeparationConstraint *separation1100852000 = new SeparationConstraint(vpsc::YDIM, alignment1114375840, alignment1114374896, 15.5, false);
+ ccs.push_back(separation1100852000);
+
+ SeparationConstraint *separation1100852176 = new SeparationConstraint(vpsc::YDIM, alignment1114374896, alignment1114433920, 18.4, false);
+ ccs.push_back(separation1100852176);
+
+ SeparationConstraint *separation1100852352 = new SeparationConstraint(vpsc::YDIM, alignment1114433920, alignment1114431760, 4.6, false);
+ ccs.push_back(separation1100852352);
+
+ SeparationConstraint *separation1100852528 = new SeparationConstraint(vpsc::YDIM, alignment1114431760, alignment1114429984, 25, false);
+ ccs.push_back(separation1100852528);
+
+ SeparationConstraint *separation1100852704 = new SeparationConstraint(vpsc::YDIM, alignment1114429984, alignment1114431568, 4.5, false);
+ ccs.push_back(separation1100852704);
+
+ SeparationConstraint *separation1100852880 = new SeparationConstraint(vpsc::YDIM, alignment1114431568, alignment1114375616, 3.5, false);
+ ccs.push_back(separation1100852880);
+
+ SeparationConstraint *separation1100853056 = new SeparationConstraint(vpsc::YDIM, alignment1114375616, alignment1114430752, 8, false);
+ ccs.push_back(separation1100853056);
+
+ SeparationConstraint *separation1100853232 = new SeparationConstraint(vpsc::YDIM, alignment1114430752, alignment1114430112, 29, false);
+ ccs.push_back(separation1100853232);
+
+ SeparationConstraint *separation1100853408 = new SeparationConstraint(vpsc::YDIM, alignment1114430112, alignment1114369616, 10.1429, false);
+ ccs.push_back(separation1100853408);
+
+ SeparationConstraint *separation1100853584 = new SeparationConstraint(vpsc::YDIM, alignment1114369616, alignment1114433040, 24.8571, false);
+ ccs.push_back(separation1100853584);
+
+ SeparationConstraint *separation1100853760 = new SeparationConstraint(vpsc::YDIM, alignment1114433040, alignment1114437392, 14, false);
+ ccs.push_back(separation1100853760);
+
+ SeparationConstraint *separation1100853936 = new SeparationConstraint(vpsc::YDIM, alignment1114437392, alignment1114430976, 4, false);
+ ccs.push_back(separation1100853936);
+
+ SeparationConstraint *separation1100854112 = new SeparationConstraint(vpsc::YDIM, alignment1114430976, alignment1114434272, 6.5, false);
+ ccs.push_back(separation1100854112);
+
+ SeparationConstraint *separation1100854288 = new SeparationConstraint(vpsc::YDIM, alignment1114434272, alignment1114433200, 9.5, false);
+ ccs.push_back(separation1100854288);
+
+ SeparationConstraint *separation1100854464 = new SeparationConstraint(vpsc::YDIM, alignment1114433200, alignment1100848528, 25, false);
+ ccs.push_back(separation1100854464);
+
+ SeparationConstraint *separation1100854640 = new SeparationConstraint(vpsc::YDIM, alignment1100848528, alignment1114434496, 9.42857, false);
+ ccs.push_back(separation1100854640);
+
+ SeparationConstraint *separation1100854816 = new SeparationConstraint(vpsc::YDIM, alignment1114434496, alignment1100848880, 23.5714, false);
+ ccs.push_back(separation1100854816);
+
+ SeparationConstraint *separation1100854992 = new SeparationConstraint(vpsc::YDIM, alignment1100848880, alignment1100848752, 43, false);
+ ccs.push_back(separation1100854992);
+
+ SeparationConstraint *separation1100855168 = new SeparationConstraint(vpsc::YDIM, alignment1100848752, alignment1114369232, 8.25, false);
+ ccs.push_back(separation1100855168);
+
+ SeparationConstraint *separation1100855344 = new SeparationConstraint(vpsc::YDIM, alignment1114369232, alignment1114430592, 33.75, false);
+ ccs.push_back(separation1100855344);
+
+ SeparationConstraint *separation1100855520 = new SeparationConstraint(vpsc::YDIM, alignment1114430592, alignment1114436928, 36.3636, false);
+ ccs.push_back(separation1100855520);
+
+ SeparationConstraint *separation1100855696 = new SeparationConstraint(vpsc::YDIM, alignment1114436928, alignment1114432048, 54.1364, false);
+ ccs.push_back(separation1100855696);
+
+ SeparationConstraint *separation1100855872 = new SeparationConstraint(vpsc::YDIM, alignment1114432048, alignment1114430272, 40.5, false);
+ ccs.push_back(separation1100855872);
+
+ SeparationConstraint *separation1100856048 = new SeparationConstraint(vpsc::YDIM, alignment1114430272, alignment1114430432, 25, false);
+ ccs.push_back(separation1100856048);
+
+ SeparationConstraint *separation1100856224 = new SeparationConstraint(vpsc::YDIM, alignment1114430432, alignment1114432464, 17, false);
+ ccs.push_back(separation1100856224);
+
+ SeparationConstraint *separation1100856400 = new SeparationConstraint(vpsc::YDIM, alignment1114432464, alignment1114431888, 33, false);
+ ccs.push_back(separation1100856400);
+
+ AlignmentConstraint *alignment1100856576 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100856576->addShape(0, 0);
+ alignment1100856576->addShape(109, 0);
+ ccs.push_back(alignment1100856576);
+
+ SeparationConstraint *separation1100856800 = new SeparationConstraint(vpsc::YDIM, 0, 109, 50, true);
+ ccs.push_back(separation1100856800);
+
+ AlignmentConstraint *alignment1100856944 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100856944->addShape(2, 0);
+ alignment1100856944->addShape(110, 0);
+ ccs.push_back(alignment1100856944);
+
+ SeparationConstraint *separation1100857168 = new SeparationConstraint(vpsc::YDIM, 2, 110, -50, true);
+ ccs.push_back(separation1100857168);
+
+ AlignmentConstraint *alignment1100857312 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100857312->addShape(3, 0);
+ alignment1100857312->addShape(111, 0);
+ ccs.push_back(alignment1100857312);
+
+ SeparationConstraint *separation1100857536 = new SeparationConstraint(vpsc::YDIM, 3, 111, -50, true);
+ ccs.push_back(separation1100857536);
+
+ AlignmentConstraint *alignment1100857680 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100857680->addShape(4, 0);
+ alignment1100857680->addShape(112, 0);
+ ccs.push_back(alignment1100857680);
+
+ SeparationConstraint *separation1100857904 = new SeparationConstraint(vpsc::XDIM, 4, 112, -62, true);
+ ccs.push_back(separation1100857904);
+
+ AlignmentConstraint *alignment1100858048 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100858048->addShape(5, 0);
+ alignment1100858048->addShape(113, 0);
+ ccs.push_back(alignment1100858048);
+
+ SeparationConstraint *separation1100858272 = new SeparationConstraint(vpsc::XDIM, 5, 113, 62, true);
+ ccs.push_back(separation1100858272);
+
+ AlignmentConstraint *alignment1100858416 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100858416->addShape(6, 0);
+ alignment1100858416->addShape(114, 0);
+ ccs.push_back(alignment1100858416);
+
+ SeparationConstraint *separation1100858640 = new SeparationConstraint(vpsc::YDIM, 6, 114, -50, true);
+ ccs.push_back(separation1100858640);
+
+ AlignmentConstraint *alignment1100858784 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100858784->addShape(7, 0);
+ alignment1100858784->addShape(115, 0);
+ ccs.push_back(alignment1100858784);
+
+ SeparationConstraint *separation1100859008 = new SeparationConstraint(vpsc::YDIM, 7, 115, -50, true);
+ ccs.push_back(separation1100859008);
+
+ AlignmentConstraint *alignment1100859152 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100859152->addShape(8, 0);
+ alignment1100859152->addShape(116, 0);
+ ccs.push_back(alignment1100859152);
+
+ SeparationConstraint *separation1100859376 = new SeparationConstraint(vpsc::YDIM, 8, 116, -50, true);
+ ccs.push_back(separation1100859376);
+
+ AlignmentConstraint *alignment1100859520 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100859520->addShape(9, 0);
+ alignment1100859520->addShape(117, 0);
+ ccs.push_back(alignment1100859520);
+
+ SeparationConstraint *separation1100859744 = new SeparationConstraint(vpsc::YDIM, 9, 117, -50, true);
+ ccs.push_back(separation1100859744);
+
+ AlignmentConstraint *alignment1100859888 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100859888->addShape(10, 0);
+ alignment1100859888->addShape(118, 0);
+ ccs.push_back(alignment1100859888);
+
+ SeparationConstraint *separation1100860112 = new SeparationConstraint(vpsc::YDIM, 10, 118, 50, true);
+ ccs.push_back(separation1100860112);
+
+ AlignmentConstraint *alignment1100860256 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100860256->addShape(11, 0);
+ alignment1100860256->addShape(119, 0);
+ ccs.push_back(alignment1100860256);
+
+ SeparationConstraint *separation1100860480 = new SeparationConstraint(vpsc::YDIM, 11, 119, -50, true);
+ ccs.push_back(separation1100860480);
+
+ AlignmentConstraint *alignment1100860624 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100860624->addShape(12, 0);
+ alignment1100860624->addShape(120, 0);
+ ccs.push_back(alignment1100860624);
+
+ SeparationConstraint *separation1100860848 = new SeparationConstraint(vpsc::YDIM, 12, 120, -50, true);
+ ccs.push_back(separation1100860848);
+
+ AlignmentConstraint *alignment1100860992 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100860992->addShape(13, 0);
+ alignment1100860992->addShape(121, 0);
+ ccs.push_back(alignment1100860992);
+
+ SeparationConstraint *separation1100861216 = new SeparationConstraint(vpsc::YDIM, 13, 121, -50, true);
+ ccs.push_back(separation1100861216);
+
+ AlignmentConstraint *alignment1100861360 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100861360->addShape(14, 0);
+ alignment1100861360->addShape(122, 0);
+ ccs.push_back(alignment1100861360);
+
+ SeparationConstraint *separation1100861584 = new SeparationConstraint(vpsc::YDIM, 14, 122, -50, true);
+ ccs.push_back(separation1100861584);
+
+ AlignmentConstraint *alignment1100861728 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100861728->addShape(15, 0);
+ alignment1100861728->addShape(123, 0);
+ ccs.push_back(alignment1100861728);
+
+ SeparationConstraint *separation1100861952 = new SeparationConstraint(vpsc::YDIM, 15, 123, -50, true);
+ ccs.push_back(separation1100861952);
+
+ AlignmentConstraint *alignment1100862096 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100862096->addShape(16, 0);
+ alignment1100862096->addShape(124, 0);
+ ccs.push_back(alignment1100862096);
+
+ SeparationConstraint *separation1100862320 = new SeparationConstraint(vpsc::XDIM, 16, 124, -62, true);
+ ccs.push_back(separation1100862320);
+
+ AlignmentConstraint *alignment1100862464 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100862464->addShape(17, 0);
+ alignment1100862464->addShape(125, 0);
+ ccs.push_back(alignment1100862464);
+
+ SeparationConstraint *separation1100862688 = new SeparationConstraint(vpsc::XDIM, 17, 125, 62, true);
+ ccs.push_back(separation1100862688);
+
+ AlignmentConstraint *alignment1100862832 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100862832->addShape(18, 0);
+ alignment1100862832->addShape(126, 0);
+ ccs.push_back(alignment1100862832);
+
+ SeparationConstraint *separation1100863056 = new SeparationConstraint(vpsc::XDIM, 18, 126, 62, true);
+ ccs.push_back(separation1100863056);
+
+ AlignmentConstraint *alignment1100863200 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100863200->addShape(19, 0);
+ alignment1100863200->addShape(127, 0);
+ ccs.push_back(alignment1100863200);
+
+ SeparationConstraint *separation1100863424 = new SeparationConstraint(vpsc::YDIM, 19, 127, 50, true);
+ ccs.push_back(separation1100863424);
+
+ AlignmentConstraint *alignment1100863568 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100863568->addShape(20, 0);
+ alignment1100863568->addShape(128, 0);
+ ccs.push_back(alignment1100863568);
+
+ SeparationConstraint *separation1100863792 = new SeparationConstraint(vpsc::XDIM, 20, 128, 62, true);
+ ccs.push_back(separation1100863792);
+
+ AlignmentConstraint *alignment1100863936 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100863936->addShape(21, 0);
+ alignment1100863936->addShape(129, 0);
+ ccs.push_back(alignment1100863936);
+
+ SeparationConstraint *separation1100864160 = new SeparationConstraint(vpsc::YDIM, 21, 129, -50, true);
+ ccs.push_back(separation1100864160);
+
+ AlignmentConstraint *alignment1100864304 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100864304->addShape(22, 0);
+ alignment1100864304->addShape(130, 0);
+ ccs.push_back(alignment1100864304);
+
+ SeparationConstraint *separation1100864528 = new SeparationConstraint(vpsc::YDIM, 22, 130, -50, true);
+ ccs.push_back(separation1100864528);
+
+ AlignmentConstraint *alignment1100864672 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100864672->addShape(24, 0);
+ alignment1100864672->addShape(131, 0);
+ ccs.push_back(alignment1100864672);
+
+ SeparationConstraint *separation1100864896 = new SeparationConstraint(vpsc::YDIM, 24, 131, -50, true);
+ ccs.push_back(separation1100864896);
+
+ AlignmentConstraint *alignment1100865040 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100865040->addShape(25, 0);
+ alignment1100865040->addShape(132, 0);
+ ccs.push_back(alignment1100865040);
+
+ SeparationConstraint *separation1100865264 = new SeparationConstraint(vpsc::YDIM, 25, 132, -50, true);
+ ccs.push_back(separation1100865264);
+
+ AlignmentConstraint *alignment1100865408 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100865408->addShape(26, 0);
+ alignment1100865408->addShape(133, 0);
+ ccs.push_back(alignment1100865408);
+
+ SeparationConstraint *separation1100865632 = new SeparationConstraint(vpsc::XDIM, 26, 133, -62, true);
+ ccs.push_back(separation1100865632);
+
+ AlignmentConstraint *alignment1100865776 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100865776->addShape(27, 0);
+ alignment1100865776->addShape(134, 0);
+ ccs.push_back(alignment1100865776);
+
+ SeparationConstraint *separation1100866000 = new SeparationConstraint(vpsc::XDIM, 27, 134, 62, true);
+ ccs.push_back(separation1100866000);
+
+ AlignmentConstraint *alignment1100866144 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100866144->addShape(28, 0);
+ alignment1100866144->addShape(135, 0);
+ ccs.push_back(alignment1100866144);
+
+ SeparationConstraint *separation1100866368 = new SeparationConstraint(vpsc::XDIM, 28, 135, 62, true);
+ ccs.push_back(separation1100866368);
+
+ AlignmentConstraint *alignment1100866512 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100866512->addShape(29, 0);
+ alignment1100866512->addShape(136, 0);
+ ccs.push_back(alignment1100866512);
+
+ SeparationConstraint *separation1100866736 = new SeparationConstraint(vpsc::XDIM, 29, 136, 62, true);
+ ccs.push_back(separation1100866736);
+
+ AlignmentConstraint *alignment1100866880 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100866880->addShape(30, 0);
+ alignment1100866880->addShape(137, 0);
+ ccs.push_back(alignment1100866880);
+
+ SeparationConstraint *separation1100867104 = new SeparationConstraint(vpsc::XDIM, 30, 137, 62, true);
+ ccs.push_back(separation1100867104);
+
+ AlignmentConstraint *alignment1100867248 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100867248->addShape(31, 0);
+ alignment1100867248->addShape(138, 0);
+ ccs.push_back(alignment1100867248);
+
+ SeparationConstraint *separation1100867472 = new SeparationConstraint(vpsc::XDIM, 31, 138, 62, true);
+ ccs.push_back(separation1100867472);
+
+ AlignmentConstraint *alignment1100867616 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100867616->addShape(32, 0);
+ alignment1100867616->addShape(139, 0);
+ ccs.push_back(alignment1100867616);
+
+ SeparationConstraint *separation1100867840 = new SeparationConstraint(vpsc::YDIM, 32, 139, -50, true);
+ ccs.push_back(separation1100867840);
+
+ AlignmentConstraint *alignment1100867984 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100867984->addShape(33, 0);
+ alignment1100867984->addShape(140, 0);
+ ccs.push_back(alignment1100867984);
+
+ SeparationConstraint *separation1100868208 = new SeparationConstraint(vpsc::YDIM, 33, 140, 50, true);
+ ccs.push_back(separation1100868208);
+
+ AlignmentConstraint *alignment1100868352 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100868352->addShape(34, 0);
+ alignment1100868352->addShape(141, 0);
+ ccs.push_back(alignment1100868352);
+
+ SeparationConstraint *separation1100868576 = new SeparationConstraint(vpsc::YDIM, 34, 141, -50, true);
+ ccs.push_back(separation1100868576);
+
+ AlignmentConstraint *alignment1100868720 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100868720->addShape(35, 0);
+ alignment1100868720->addShape(142, 0);
+ ccs.push_back(alignment1100868720);
+
+ SeparationConstraint *separation1100868944 = new SeparationConstraint(vpsc::XDIM, 35, 142, 62, true);
+ ccs.push_back(separation1100868944);
+
+ AlignmentConstraint *alignment1100869088 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100869088->addShape(36, 0);
+ alignment1100869088->addShape(143, 0);
+ ccs.push_back(alignment1100869088);
+
+ SeparationConstraint *separation1100869312 = new SeparationConstraint(vpsc::XDIM, 36, 143, 62, true);
+ ccs.push_back(separation1100869312);
+
+ AlignmentConstraint *alignment1100869456 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100869456->addShape(39, 0);
+ alignment1100869456->addShape(144, 0);
+ ccs.push_back(alignment1100869456);
+
+ SeparationConstraint *separation1100869680 = new SeparationConstraint(vpsc::YDIM, 39, 144, -50, true);
+ ccs.push_back(separation1100869680);
+
+ AlignmentConstraint *alignment1100869824 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100869824->addShape(40, 0);
+ alignment1100869824->addShape(145, 0);
+ ccs.push_back(alignment1100869824);
+
+ SeparationConstraint *separation1100870048 = new SeparationConstraint(vpsc::YDIM, 40, 145, -50, true);
+ ccs.push_back(separation1100870048);
+
+ AlignmentConstraint *alignment1100870192 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100870192->addShape(41, 0);
+ alignment1100870192->addShape(146, 0);
+ ccs.push_back(alignment1100870192);
+
+ SeparationConstraint *separation1100870416 = new SeparationConstraint(vpsc::XDIM, 41, 146, 62, true);
+ ccs.push_back(separation1100870416);
+
+ AlignmentConstraint *alignment1100870560 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100870560->addShape(42, 0);
+ alignment1100870560->addShape(147, 0);
+ ccs.push_back(alignment1100870560);
+
+ SeparationConstraint *separation1100870784 = new SeparationConstraint(vpsc::YDIM, 42, 147, -50, true);
+ ccs.push_back(separation1100870784);
+
+ AlignmentConstraint *alignment1114434864 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1114434864->addShape(43, 0);
+ alignment1114434864->addShape(148, 0);
+ ccs.push_back(alignment1114434864);
+
+ SeparationConstraint *separation1114435088 = new SeparationConstraint(vpsc::YDIM, 43, 148, -50, true);
+ ccs.push_back(separation1114435088);
+
+ AlignmentConstraint *alignment1114435232 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1114435232->addShape(44, 0);
+ alignment1114435232->addShape(149, 0);
+ ccs.push_back(alignment1114435232);
+
+ SeparationConstraint *separation1114435456 = new SeparationConstraint(vpsc::XDIM, 44, 149, -62, true);
+ ccs.push_back(separation1114435456);
+
+ AlignmentConstraint *alignment1114435600 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1114435600->addShape(47, 0);
+ alignment1114435600->addShape(150, 0);
+ ccs.push_back(alignment1114435600);
+
+ SeparationConstraint *separation1114435824 = new SeparationConstraint(vpsc::YDIM, 47, 150, -50, true);
+ ccs.push_back(separation1114435824);
+
+ AlignmentConstraint *alignment1114435968 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1114435968->addShape(48, 0);
+ alignment1114435968->addShape(151, 0);
+ ccs.push_back(alignment1114435968);
+
+ SeparationConstraint *separation1114436192 = new SeparationConstraint(vpsc::YDIM, 48, 151, -50, true);
+ ccs.push_back(separation1114436192);
+
+ AlignmentConstraint *alignment1114436336 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1114436336->addShape(49, 0);
+ alignment1114436336->addShape(152, 0);
+ ccs.push_back(alignment1114436336);
+
+ SeparationConstraint *separation1114436560 = new SeparationConstraint(vpsc::YDIM, 49, 152, -50, true);
+ ccs.push_back(separation1114436560);
+
+ AlignmentConstraint *alignment1114436704 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1114436704->addShape(50, 0);
+ alignment1114436704->addShape(153, 0);
+ ccs.push_back(alignment1114436704);
+
+ SeparationConstraint *separation1100875040 = new SeparationConstraint(vpsc::YDIM, 50, 153, -50, true);
+ ccs.push_back(separation1100875040);
+
+ AlignmentConstraint *alignment1100875184 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100875184->addShape(51, 0);
+ alignment1100875184->addShape(154, 0);
+ ccs.push_back(alignment1100875184);
+
+ SeparationConstraint *separation1100875408 = new SeparationConstraint(vpsc::XDIM, 51, 154, 62, true);
+ ccs.push_back(separation1100875408);
+
+ AlignmentConstraint *alignment1100875552 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100875552->addShape(52, 0);
+ alignment1100875552->addShape(155, 0);
+ ccs.push_back(alignment1100875552);
+
+ SeparationConstraint *separation1100875776 = new SeparationConstraint(vpsc::XDIM, 52, 155, 62, true);
+ ccs.push_back(separation1100875776);
+
+ AlignmentConstraint *alignment1100875920 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100875920->addShape(53, 0);
+ alignment1100875920->addShape(156, 0);
+ ccs.push_back(alignment1100875920);
+
+ SeparationConstraint *separation1100876144 = new SeparationConstraint(vpsc::YDIM, 53, 156, -50, true);
+ ccs.push_back(separation1100876144);
+
+ AlignmentConstraint *alignment1100876288 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100876288->addShape(54, 0);
+ alignment1100876288->addShape(157, 0);
+ ccs.push_back(alignment1100876288);
+
+ SeparationConstraint *separation1100876512 = new SeparationConstraint(vpsc::XDIM, 54, 157, 62, true);
+ ccs.push_back(separation1100876512);
+
+ AlignmentConstraint *alignment1100876656 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100876656->addShape(104, 0);
+ alignment1100876656->addShape(158, 0);
+ ccs.push_back(alignment1100876656);
+
+ SeparationConstraint *separation1100876880 = new SeparationConstraint(vpsc::XDIM, 104, 158, 62, true);
+ ccs.push_back(separation1100876880);
+
+ AlignmentConstraint *alignment1100877024 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment1100877024->addShape(107, 0);
+ alignment1100877024->addShape(159, 0);
+ ccs.push_back(alignment1100877024);
+
+ SeparationConstraint *separation1100877248 = new SeparationConstraint(vpsc::XDIM, 107, 159, 62, true);
+ ccs.push_back(separation1100877248);
+
+ AlignmentConstraint *alignment1100877392 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment1100877392->addShape(108, 0);
+ alignment1100877392->addShape(160, 0);
+ ccs.push_back(alignment1100877392);
+
+ SeparationConstraint *separation1100877616 = new SeparationConstraint(vpsc::YDIM, 108, 160, -50, true);
+ ccs.push_back(separation1100877616);
+
+ ConstrainedFDLayout alg(rs, es, defaultEdgeLength);
+ alg.setAvoidNodeOverlaps(true);
+ RootCluster *cluster1100877760 = new RootCluster();
+ cluster1100877760->addChildNode(0);
+ cluster1100877760->addChildNode(2);
+ cluster1100877760->addChildNode(3);
+ cluster1100877760->addChildNode(4);
+ cluster1100877760->addChildNode(5);
+ cluster1100877760->addChildNode(6);
+ cluster1100877760->addChildNode(7);
+ cluster1100877760->addChildNode(8);
+ cluster1100877760->addChildNode(9);
+ cluster1100877760->addChildNode(10);
+ cluster1100877760->addChildNode(11);
+ cluster1100877760->addChildNode(12);
+ cluster1100877760->addChildNode(13);
+ cluster1100877760->addChildNode(14);
+ cluster1100877760->addChildNode(15);
+ cluster1100877760->addChildNode(16);
+ cluster1100877760->addChildNode(17);
+ cluster1100877760->addChildNode(18);
+ cluster1100877760->addChildNode(19);
+ cluster1100877760->addChildNode(20);
+ cluster1100877760->addChildNode(21);
+ cluster1100877760->addChildNode(22);
+ cluster1100877760->addChildNode(23);
+ cluster1100877760->addChildNode(24);
+ cluster1100877760->addChildNode(25);
+ cluster1100877760->addChildNode(26);
+ cluster1100877760->addChildNode(27);
+ cluster1100877760->addChildNode(28);
+ cluster1100877760->addChildNode(29);
+ cluster1100877760->addChildNode(30);
+ cluster1100877760->addChildNode(31);
+ cluster1100877760->addChildNode(32);
+ cluster1100877760->addChildNode(33);
+ cluster1100877760->addChildNode(34);
+ cluster1100877760->addChildNode(35);
+ cluster1100877760->addChildNode(36);
+ cluster1100877760->addChildNode(39);
+ cluster1100877760->addChildNode(40);
+ cluster1100877760->addChildNode(41);
+ cluster1100877760->addChildNode(42);
+ cluster1100877760->addChildNode(43);
+ cluster1100877760->addChildNode(44);
+ cluster1100877760->addChildNode(47);
+ cluster1100877760->addChildNode(48);
+ cluster1100877760->addChildNode(49);
+ cluster1100877760->addChildNode(50);
+ cluster1100877760->addChildNode(51);
+ cluster1100877760->addChildNode(52);
+ cluster1100877760->addChildNode(53);
+ cluster1100877760->addChildNode(54);
+ cluster1100877760->addChildNode(55);
+ cluster1100877760->addChildNode(56);
+ cluster1100877760->addChildNode(57);
+ cluster1100877760->addChildNode(58);
+ cluster1100877760->addChildNode(59);
+ cluster1100877760->addChildNode(60);
+ cluster1100877760->addChildNode(61);
+ cluster1100877760->addChildNode(62);
+ cluster1100877760->addChildNode(63);
+ cluster1100877760->addChildNode(64);
+ cluster1100877760->addChildNode(65);
+ cluster1100877760->addChildNode(66);
+ cluster1100877760->addChildNode(67);
+ cluster1100877760->addChildNode(68);
+ cluster1100877760->addChildNode(69);
+ cluster1100877760->addChildNode(70);
+ cluster1100877760->addChildNode(71);
+ cluster1100877760->addChildNode(72);
+ cluster1100877760->addChildNode(73);
+ cluster1100877760->addChildNode(74);
+ cluster1100877760->addChildNode(75);
+ cluster1100877760->addChildNode(76);
+ cluster1100877760->addChildNode(77);
+ cluster1100877760->addChildNode(78);
+ cluster1100877760->addChildNode(79);
+ cluster1100877760->addChildNode(80);
+ cluster1100877760->addChildNode(81);
+ cluster1100877760->addChildNode(82);
+ cluster1100877760->addChildNode(83);
+ cluster1100877760->addChildNode(84);
+ cluster1100877760->addChildNode(85);
+ cluster1100877760->addChildNode(86);
+ cluster1100877760->addChildNode(87);
+ cluster1100877760->addChildNode(88);
+ cluster1100877760->addChildNode(89);
+ cluster1100877760->addChildNode(90);
+ cluster1100877760->addChildNode(91);
+ cluster1100877760->addChildNode(92);
+ cluster1100877760->addChildNode(93);
+ cluster1100877760->addChildNode(94);
+ cluster1100877760->addChildNode(95);
+ cluster1100877760->addChildNode(96);
+ cluster1100877760->addChildNode(97);
+ cluster1100877760->addChildNode(98);
+ cluster1100877760->addChildNode(99);
+ cluster1100877760->addChildNode(100);
+ cluster1100877760->addChildNode(101);
+ cluster1100877760->addChildNode(102);
+ cluster1100877760->addChildNode(104);
+ cluster1100877760->addChildNode(105);
+ cluster1100877760->addChildNode(106);
+ cluster1100877760->addChildNode(107);
+ cluster1100877760->addChildNode(108);
+ cluster1100877760->addChildNode(109);
+ cluster1100877760->addChildNode(110);
+ cluster1100877760->addChildNode(111);
+ cluster1100877760->addChildNode(112);
+ cluster1100877760->addChildNode(113);
+ cluster1100877760->addChildNode(114);
+ cluster1100877760->addChildNode(115);
+ cluster1100877760->addChildNode(116);
+ cluster1100877760->addChildNode(117);
+ cluster1100877760->addChildNode(118);
+ cluster1100877760->addChildNode(119);
+ cluster1100877760->addChildNode(120);
+ cluster1100877760->addChildNode(121);
+ cluster1100877760->addChildNode(122);
+ cluster1100877760->addChildNode(123);
+ cluster1100877760->addChildNode(124);
+ cluster1100877760->addChildNode(125);
+ cluster1100877760->addChildNode(126);
+ cluster1100877760->addChildNode(127);
+ cluster1100877760->addChildNode(128);
+ cluster1100877760->addChildNode(129);
+ cluster1100877760->addChildNode(130);
+ cluster1100877760->addChildNode(131);
+ cluster1100877760->addChildNode(132);
+ cluster1100877760->addChildNode(133);
+ cluster1100877760->addChildNode(134);
+ cluster1100877760->addChildNode(135);
+ cluster1100877760->addChildNode(136);
+ cluster1100877760->addChildNode(137);
+ cluster1100877760->addChildNode(138);
+ cluster1100877760->addChildNode(139);
+ cluster1100877760->addChildNode(140);
+ cluster1100877760->addChildNode(141);
+ cluster1100877760->addChildNode(142);
+ cluster1100877760->addChildNode(143);
+ cluster1100877760->addChildNode(144);
+ cluster1100877760->addChildNode(145);
+ cluster1100877760->addChildNode(146);
+ cluster1100877760->addChildNode(147);
+ cluster1100877760->addChildNode(148);
+ cluster1100877760->addChildNode(149);
+ cluster1100877760->addChildNode(150);
+ cluster1100877760->addChildNode(151);
+ cluster1100877760->addChildNode(152);
+ cluster1100877760->addChildNode(153);
+ cluster1100877760->addChildNode(154);
+ cluster1100877760->addChildNode(155);
+ cluster1100877760->addChildNode(156);
+ cluster1100877760->addChildNode(157);
+ cluster1100877760->addChildNode(158);
+ cluster1100877760->addChildNode(159);
+ cluster1100877760->addChildNode(160);
+ RectangularCluster *cluster1100878032 = new RectangularCluster();
+ cluster1100878032->addChildNode(161);
+ cluster1100877760->addChildCluster(cluster1100878032);
+ RectangularCluster *cluster1100878416 = new RectangularCluster();
+ cluster1100878416->addChildNode(162);
+ cluster1100877760->addChildCluster(cluster1100878416);
+ RectangularCluster *cluster1100878800 = new RectangularCluster();
+ cluster1100878800->addChildNode(163);
+ cluster1100877760->addChildCluster(cluster1100878800);
+ RectangularCluster *cluster1100879168 = new RectangularCluster();
+ cluster1100877760->addChildCluster(cluster1100879168);
+ RectangularCluster *cluster1100879488 = new RectangularCluster();
+ cluster1100879488->addChildNode(164);
+ cluster1100879488->addChildNode(165);
+ cluster1100879488->addChildNode(166);
+ cluster1100879488->addChildNode(167);
+ cluster1100877760->addChildCluster(cluster1100879488);
+ RectangularCluster *cluster1100879920 = new RectangularCluster();
+ cluster1100879920->addChildNode(168);
+ cluster1100877760->addChildCluster(cluster1100879920);
+ alg.setClusterHierarchy(cluster1100877760);
+ alg.setConstraints(ccs);
+ alg.makeFeasible();
+ alg.run();
+ alg.outputInstanceToSVG("test-StillOverlap02");
+ alg.freeAssociatedObjects();
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libcola/tests/boundary.cpp b/src/3rdparty/adaptagrams/libcola/tests/boundary.cpp
new file mode 100644
index 0000000..18e962d
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/boundary.cpp
@@ -0,0 +1,121 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+/** \file boundary.cpp
+ *
+ * a clustered graph using libtopology to preserve the cluster boundary.
+ */
+/*
+* Authors:
+* Tim Dwyer <tgdwyer@gmail.com>
+*/
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+
+#include <vector>
+#include <valarray>
+#include <algorithm>
+#include <float.h>
+#include "graphlayouttest.h"
+#include <libtopology/topology_graph.h>
+#include <libproject/project.h>
+using namespace std;
+using namespace topology;
+
+Node* addNode( Nodes& vs, vpsc::Rectangle* r) {
+ Node *v = new Node(vs.size(), r);
+ vs.push_back(v);
+ return v;
+}
+void addToPath(EdgePoints& ps, Node *v, EdgePoint::RectIntersect i) {
+ ps.push_back(new EdgePoint(v,i));
+}
+struct SetDesiredPos : public PreIteration {
+ SetDesiredPos(Locks& locks) : PreIteration(locks) {}
+};
+struct Test : TestConvergence {
+ Test(const double d,const unsigned i,topology::Nodes& vs, topology::Edges& es,const string fname) : TestConvergence(d,i), vs(vs), es(es), fname(fname) {}
+ bool operator()(const double new_stress, valarray<double> & X, valarray<double> & Y) {
+ bool converged= TestConvergence::operator()(new_stress,X,Y);
+ if(converged) {
+ cerr << "stress="<<new_stress<<" iteration="<<iterations<<endl;
+ stringstream ss;
+ ss << fname << "-" << setfill('0') << setw(3) << iterations << ".svg";
+ cerr << "writing file: " << ss.str() << endl;
+ writeFile(vs,es,ss.str());
+ }
+ return converged;
+ }
+ double lastStress;
+ topology::Nodes& vs;
+ topology::Edges& es;
+ const string fname;
+};
+void clusterBoundary() {
+ vector<cola::Edge> es;
+ vector<vpsc::Rectangle*> rs;
+ rs.push_back(new vpsc::Rectangle(395,449,155,189));
+ rs.push_back(new vpsc::Rectangle(309,363,155,189));
+ double idealLength=60;
+ // set up topology graph
+ topology::Nodes vs;
+ for(vector<Rectangle*>::iterator i = rs.begin(); i!=rs.end();++i) {
+ addNode(vs,*i);
+ }
+ Edges tes;
+ EdgePoints ps;
+ addToPath(ps,vs[1],EdgePoint::BL);
+ addToPath(ps,vs[0],EdgePoint::BR);
+ addToPath(ps,vs[0],EdgePoint::TR);
+ addToPath(ps,vs[1],EdgePoint::TL);
+ ps.push_back(ps[0]);
+ tes.push_back(new topology::Edge(idealLength, ps));
+
+ writeFile(vs,tes,"boundary-000.svg");
+
+ Locks locks;
+ locks.push_back(Lock(0,rs[0]->getCentreX(), rs[0]->getCentreY()+10));
+ locks.push_back(Lock(1,rs[1]->getCentreX(), rs[1]->getCentreY()));
+ SetDesiredPos preIteration(locks);
+
+ Test test(0.00001,100,vs,tes,"boundary");
+ cola::ConstrainedFDLayout alg(rs,es,idealLength,nullptr,test,&preIteration);
+
+ alg.setTopology(&vs,&tes);
+ alg.run(true,true);
+ double finalStress=alg.computeStress();
+ printf("finalStress=%f\n",finalStress);
+
+ //assert(finalStress<1e-5);
+ for_each(rs.begin(),rs.end(),cola::delete_object());
+ for_each(tes.begin(),tes.end(),cola::delete_object());
+ for_each(vs.begin(),vs.end(),cola::delete_object());
+}
+int main() {
+ clusterBoundary();
+ return 0;
+}
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=80 :
diff --git a/src/3rdparty/adaptagrams/libcola/tests/connected_components.cpp b/src/3rdparty/adaptagrams/libcola/tests/connected_components.cpp
new file mode 100644
index 0000000..d5df479
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/connected_components.cpp
@@ -0,0 +1,69 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+#include <iostream>
+#include <vector>
+#include <set>
+#include <libvpsc/rectangle.h>
+#include <libcola/cola.h>
+#include <libcola/connected_components.h>
+#include "graphlayouttest.h"
+
+using namespace std;
+using namespace cola;
+
+int main() {
+ const unsigned V = 7;
+ unsigned c1[]={0,1,2,3};
+ set<unsigned> expected_c1(c1,c1+4);
+ unsigned c2[]={4,5,6};
+ set<unsigned> expected_c2(c2,c2+3);
+
+ Edge edge_array[] = { Edge(0, 1), Edge(1, 2), Edge(3, 2), Edge(1, 3),
+ Edge(4, 5), Edge(5, 6), Edge(6, 4) };
+ const std::size_t E = sizeof(edge_array) / sizeof(Edge);
+ vector<Edge> es(edge_array,edge_array+E);
+ vector<Component*> cs;
+ vpsc::Rectangles rs;
+ double width=100,height=100;
+ for(unsigned i=0;i<V;i++) {
+ double x=getRand(width), y=getRand(height);
+ rs.push_back(new vpsc::Rectangle(x,x+5,y,y+5));
+ }
+ connectedComponents(rs,es,cs);
+ set<unsigned> result_c1(cs[0]->node_ids.begin(),cs[0]->node_ids.end());
+ set<unsigned> result_c2(cs[1]->node_ids.begin(),cs[1]->node_ids.end());
+ assert(expected_c1==result_c1);
+ assert(expected_c2==result_c2);
+ for(unsigned i=0;i<cs.size();i++) {
+ printf("Component %d:\n",i);
+ for(unsigned j=0;j<cs[i]->edges.size();j++) {
+ Edge& e=cs[i]->edges[j];
+ printf("(%d,%d) ",e.first,e.second);
+ }
+ cout << endl;
+ }
+ return 0;
+}
diff --git a/src/3rdparty/adaptagrams/libcola/tests/constrained.cpp b/src/3rdparty/adaptagrams/libcola/tests/constrained.cpp
new file mode 100644
index 0000000..20215f7
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/constrained.cpp
@@ -0,0 +1,99 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+/** \file constrained.cpp
+ *
+ * runs constraint layout on a small graph. nodes 0 and 3 are constrained
+ * to a vertical line
+ *
+ *
+ * Authors:
+ * Tim Dwyer <tgdwyer@gmail.com>
+ */
+#include <iostream>
+
+#include <vector>
+#include <algorithm>
+#include <float.h>
+#include <libcola/cola.h>
+#include <libcola/output_svg.h>
+inline double getRand(double range) {
+ return range*rand()/RAND_MAX;
+}
+
+using namespace std;
+using namespace cola;
+/**
+* \brief Determines when to terminate layout of a particular graph based
+* on a given relative tolerance.
+*/
+int main() {
+
+ const unsigned V = 4;
+ typedef pair < unsigned, unsigned >Edge;
+ Edge edge_array[] = { Edge(0, 1), Edge(1, 2), Edge(2, 3), Edge(1, 3) };
+ unsigned E = sizeof(edge_array) / sizeof(Edge);
+ vector<Edge> es(edge_array,edge_array+E);
+ double width=100;
+ double height=100;
+ vector<vpsc::Rectangle*> rs;
+ for(unsigned i=0;i<V;i++) {
+ double x=getRand(width), y=getRand(height);
+ rs.push_back(new vpsc::Rectangle(x,x+5,y,y+5));
+ }
+ CompoundConstraints ccs;
+ AlignmentConstraint ac(vpsc::XDIM);
+ ccs.push_back(&ac);
+ ac.addShape(0,0);
+ ac.addShape(3,0);
+ // apply steepest descent layout
+ ConstrainedFDLayout alg2(rs,es,width/2);
+ alg2.setConstraints(ccs);
+ alg2.run();
+ assert(alg2.computeStress()<0.0013);
+ // the following pair of nodes should line-up
+ assert(fabs(rs[0]->getCentreX()-rs[3]->getCentreX())<0.001);
+ // reset rectangles to random positions
+ for(unsigned i=0;i<V;i++) {
+ double x=getRand(width), y=getRand(height);
+ rs[i]->moveCentre(x,y);
+ }
+ // apply scaled majorization layout
+ ConstrainedMajorizationLayout alg(rs,es,nullptr,width/2);
+ alg.setConstraints(&ccs);
+ alg.setScaling(true);
+ alg.run();
+ // the following pair of nodes should line-up
+ assert(fabs(rs[0]->getCentreX()-rs[3]->getCentreX())<0.001);
+ cout<<rs[0]->getCentreX()<<","<<rs[3]->getCentreX()<<endl;
+ OutputFile output(rs,es,nullptr,"constrained.svg");
+ output.rects=true;
+ output.generate();
+
+ for(unsigned i=0;i<V;i++) {
+ delete rs[i];
+ }
+ return 0;
+}
diff --git a/src/3rdparty/adaptagrams/libcola/tests/containment.cpp b/src/3rdparty/adaptagrams/libcola/tests/containment.cpp
new file mode 100644
index 0000000..488700e
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/containment.cpp
@@ -0,0 +1,89 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+/** \file containment.cpp
+ *
+ * simple test of clustered graph layout
+ *
+ * Authors:
+ * Tim Dwyer <tgdwyer@gmail.com>
+ */
+#include <iostream>
+
+#include <map>
+#include <vector>
+#include <algorithm>
+#include <float.h>
+#include <iomanip>
+#include <libcola/cola.h>
+#include <libcola/output_svg.h>
+#include "graphlayouttest.h"
+
+using namespace cola;
+using namespace std;
+
+vector<vpsc::Rectangle*> rs;
+vector<Edge> es;
+RectangularCluster rc, rd;
+RootCluster root;
+unsigned iteration=0;
+
+int main() {
+
+ const unsigned V = 5;
+ typedef pair < unsigned, unsigned >Edge;
+ Edge edge_array[] = { Edge(0, 1), Edge(1, 2), Edge(2, 3), Edge(3, 4) };
+ const std::size_t E = sizeof(edge_array) / sizeof(Edge);
+ es.resize(E);
+ copy(edge_array,edge_array+E,es.begin());
+ double width=100;
+ double height=100;
+ for(unsigned i=0;i<V;i++) {
+ double x=getRand(width), y=getRand(height);
+ rs.push_back(new vpsc::Rectangle(x,x+20,y,y+15));
+ }
+
+ const unsigned c[]={0,4}, d[]={1,2,3};
+ unsigned nc=sizeof(c)/sizeof(unsigned), nd=sizeof(d)/sizeof(unsigned);
+ CheckProgress test(0.0001,100);
+ ConstrainedMajorizationLayout alg(rs,es,&root,30,nullptr,test);
+ alg.setScaling(true);
+ rc.nodes.resize(nc);
+ copy(c,c+nc,rc.nodes.begin());
+ rd.nodes.resize(nd);
+ copy(d,d+nd,rd.nodes.begin());
+ root.clusters.push_back(&rc);
+ root.clusters.push_back(&rd);
+ alg.run();
+ alg.setAvoidOverlaps();
+ alg.run();
+ OutputFile of(rs,es,&root,"containment.svg",false,true);
+ of.generate();
+ for(unsigned i=0;i<V;i++) {
+ delete rs[i];
+ }
+ return 0;
+}
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 :
diff --git a/src/3rdparty/adaptagrams/libcola/tests/containment2.cpp b/src/3rdparty/adaptagrams/libcola/tests/containment2.cpp
new file mode 100644
index 0000000..d499ffc
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/containment2.cpp
@@ -0,0 +1,157 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+/** \file
+ * Interface between Inkscape code (SPItem) and graphlayout functions.
+ * Authors:
+ * Tim Dwyer <tgdwyer@gmail.com>
+ */
+#include <iostream>
+
+#include <map>
+#include <vector>
+#include <algorithm>
+#include <float.h>
+#include <iomanip>
+#include <libcola/cola.h>
+#include <libcola/output_svg.h>
+#include "graphlayouttest.h"
+
+using namespace cola;
+using namespace std;
+
+vector<vpsc::Rectangle*> rs;
+vector<Edge> es;
+RootCluster root;
+unsigned iteration=0;
+
+/**
+* \brief Determines when to terminate layout of a particular graph based
+* on a given relative tolerance.
+*/
+int main() {
+
+ const unsigned V = 19;
+ const char* labels[]={
+ "Hamza Alghamdi",
+ "Nawaf Alhazmi",
+ "Marwan Al-Shehhi",
+ "Mohand Alshehri",
+ "Ahmed Alghamdi",
+ "Saeed Alghamdi",
+ "Salem Alhazmi",
+ "Hani Hanjour",
+ "Mohamed Atta",
+ "Ziad Jarrah",
+ "Ahmed Al Haznawi",
+ "Fayez Ahmed",
+ "Ahmed Alnami",
+ "Khalid Al-Mihdhar",
+ "Majed Moqed",
+ "Abdul Aziz Al-Omari",
+ "Waleed Alshehri",
+ "Wail Alshehri",
+ "Satam Suqami"};
+
+ typedef pair < unsigned, unsigned >Edge;
+ Edge edge_array[] = {
+ Edge(0,1), Edge(0,3), Edge(0,4), Edge(0,5), Edge(0,10),
+ Edge(1,5), Edge(1,6), Edge(1,7), Edge(1,12), Edge(1,13),
+ Edge(2,8), Edge(2,9), Edge(2,11), Edge(2,15),
+ Edge(3,11),
+ Edge(5,10), Edge(5,12),
+ Edge(7,13), Edge(7,14),
+ Edge(8,9), Edge(8,15),
+ Edge(9,10),
+ Edge(15,16),
+ Edge(16,17), Edge(16,18),
+ Edge(17,18)
+ };
+ double g=10;
+ CompoundConstraints scy;
+ scy.push_back(new SeparationConstraint(0,10,g));
+ scy.push_back(new SeparationConstraint(0,3,g));
+ scy.push_back(new SeparationConstraint(0,4,g));
+ scy.push_back(new SeparationConstraint(0,12,g));
+ scy.push_back(new SeparationConstraint(0,5,g));
+ scy.push_back(new SeparationConstraint(1,12,g));
+ scy.push_back(new SeparationConstraint(1,5,g));
+ scy.push_back(new SeparationConstraint(1,13,g));
+ scy.push_back(new SeparationConstraint(1,6,g));
+ scy.push_back(new SeparationConstraint(1,7,g));
+ scy.push_back(new SeparationConstraint(2,8,g));
+ scy.push_back(new SeparationConstraint(2,9,g));
+ scy.push_back(new SeparationConstraint(2,15,g));
+ scy.push_back(new SeparationConstraint(2,11,g));
+ scy.push_back(new SeparationConstraint(5,12,g));
+ scy.push_back(new SeparationConstraint(7,13,g));
+ scy.push_back(new SeparationConstraint(7,14,g));
+ scy.push_back(new SeparationConstraint(16,17,g));
+ scy.push_back(new SeparationConstraint(16,18,g));
+ const std::size_t E = sizeof(edge_array) / sizeof(Edge);
+ es.resize(E);
+ copy(edge_array,edge_array+E,es.begin());
+ double width=100;
+ double height=100;
+ for(unsigned i=0;i<V;i++) {
+ double x=getRand(width), y=getRand(height);
+ rs.push_back(new vpsc::Rectangle(x,x+17,y,y+10));
+ }
+
+ RectangularCluster c;
+ c.nodes.push_back(0);
+ c.nodes.push_back(1);
+ RectangularCluster d;
+ d.nodes.push_back(3);
+ d.nodes.push_back(11);
+ RectangularCluster e;
+ e.nodes.push_back(8);
+ e.nodes.push_back(9);
+ e.nodes.push_back(10);
+ e.nodes.push_back(15);
+ e.nodes.push_back(16);
+ RectangularCluster f;
+ f.nodes.push_back(17);
+ f.nodes.push_back(18);
+ root.clusters.push_back(&c);
+ root.clusters.push_back(&d);
+ root.clusters.push_back(&e);
+ root.clusters.push_back(&f);
+ OutputFile of(rs,es,&root,"containment2.svg",true,true);
+ //of.setLabels(V,labels);
+ CheckProgress test(0.0001,100);
+ ConstrainedMajorizationLayout alg(rs,es,&root,30,nullptr,test);
+ alg.setScaling(false);
+ //alg.setYSeparationConstraints(&scy);
+ //alg.run();
+ alg.setAvoidOverlaps();
+ alg.run();
+ of.generate();
+ for(unsigned i=0;i<V;i++) {
+ delete rs[i];
+ }
+ return 0;
+}
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 :
diff --git a/src/3rdparty/adaptagrams/libcola/tests/convex_hull.cpp b/src/3rdparty/adaptagrams/libcola/tests/convex_hull.cpp
new file mode 100644
index 0000000..38b6629
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/convex_hull.cpp
@@ -0,0 +1,180 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+/**
+ * Really basic regression test of convex hull implementation
+ * declared in libcola/convex_hull.h
+ */
+#include <valarray>
+#include <algorithm>
+#include <libcola/convex_hull.h>
+#include "graphlayouttest.h"
+
+#include <string>
+#include <iostream>
+#include <cairomm/context.h>
+#include <cairomm/surface.h>
+
+/* M_PI is defined in math.h in the case of Microsoft Visual C++ */
+#if defined(_MSC_VER)
+#define _USE_MATH_DEFINES
+#include <math.h>
+#endif
+using namespace std;
+
+typedef vector<unsigned> Hull;
+/**
+ * generates a random set of n points in X and Y.
+ */
+void randTest(unsigned n, valarray<double>& X, valarray<double>& Y) {
+ X.resize(n);
+ Y.resize(n);
+ srand(time(nullptr));
+ for(unsigned i=0;i<n;i++) {
+ X[i]=getRand(1.);
+ Y[i]=getRand(1.);
+ }
+}
+/**
+ * generates a set of 8 points (actually the vertices of two rectangles)
+ * which lineup horizontally. The expected hull are the lower-left and
+ * top-left corners of the left rectangle and the top-right/lower-right
+ * corners of the right rectangle.
+ */
+void tworects(valarray<double>& X, valarray<double>& Y, Hull& expectedHull) {
+ const unsigned n=8;
+ X.resize(n);
+ Y.resize(n);
+ X[0]=330.011898, Y[0]=203.250425;
+ X[1]=330.011898, Y[1]=237.250425;
+ X[2]=276.011898, Y[2]=237.250425;
+ X[3]=276.011898, Y[3]=203.250425;
+ X[4]=459.998300, Y[4]=203.250425;
+ X[5]=459.998300, Y[5]=237.250425;
+ X[6]=405.998300, Y[6]=237.250425;
+ X[7]=405.998300, Y[7]=203.250425;
+ unsigned hull[]={3,4,5,2};
+ unsigned m=sizeof(hull)/sizeof(unsigned);
+ expectedHull.resize(m);
+ copy(hull,hull+m,expectedHull.begin());
+}
+
+int drawCairo(const string& fname,
+ const valarray<double>& X, const valarray<double>& Y,
+ const Hull& hull);
+
+int main(int argc, char** argv) {
+ valarray<double> X, Y;
+ Hull h,expectedHull;
+ tworects(X,Y,expectedHull);
+ hull::convex(X,Y,h);
+ printf("hull size=%d\n",h.size());
+ pair<Hull::iterator,Hull::iterator> r
+ =mismatch(h.begin(),h.end(),expectedHull.begin());
+ assert(r.first==h.end());
+ drawCairo("convex_tworects.svg",X,Y,h);
+
+ randTest(20,X,Y);
+ hull::convex(X,Y,h);
+ drawCairo("convex_hull_random.svg",X,Y,h);
+ return 0;
+}
+
+/***********CAIRO CODE***************************************************/
+double width = 600;
+double height = 400;
+double border=10;
+void dot(Cairo::RefPtr<Cairo::Context> & cr, double x, double y) {
+ cr->arc(x, y,
+ 2., 0.0, 2.0 * M_PI);
+ cr->stroke();
+}
+
+double xcoord(double x) {
+ return border+x*width;
+}
+double ycoord(double y) {
+ return border+y*height;
+}
+int drawCairo(const string& fname,
+ const valarray<double>& Xin, const valarray<double>& Yin,
+ const Hull& hull) {
+#ifdef CAIRO_HAS_SVG_SURFACE
+ unsigned n=Xin.size();
+ assert(Yin.size()==n);
+
+ // normalise coords to range 0-1
+ valarray<double> X=Xin, Y=Yin;
+ X-=X.min();
+ Y-=Y.min();
+ X/=X.max();
+ Y/=Y.max();
+
+ Cairo::RefPtr<Cairo::SvgSurface> surface =
+ Cairo::SvgSurface::create(fname, width+2*border, height+2*border);
+
+ Cairo::RefPtr<Cairo::Context> cr = Cairo::Context::create(surface);
+
+ cr->save(); // save the state of the context
+ cr->set_source_rgba(0.0, 0.0, 0.0, 0.7);
+ // draw a circle at each coordinate
+ for(unsigned i=0;i<n;i++) {
+ dot(cr,xcoord(X[i]),ycoord(Y[i]));
+ }
+
+ cr->set_source_rgba(0.0, 0.0, 0.0, 0.3);
+ cr->move_to(xcoord(X[hull[0]]),ycoord(Y[hull[0]]));
+ for(unsigned i=1;i<hull.size();i++) {
+ cr->line_to(xcoord(X[hull[i]]),ycoord(Y[hull[i]]));
+ }
+ cr->line_to(xcoord(X[hull[0]]),ycoord(Y[hull[0]]));
+ cr->stroke();
+ cr->set_source_rgba(0.0, 0.0, 0.0, 1.);
+ for(vector<unsigned>::const_iterator i=hull.begin();i!=hull.end();++i) {
+ unsigned j=*i;
+ stringstream ss;
+ ss<<j;
+ printf("p[%d]=(%f,%f)\n",j,X[j],Y[j]);
+ cr->move_to(xcoord(X[j]),ycoord(Y[j]));
+ cr->show_text(ss.str());
+ cr->stroke();
+ }
+ cr->restore();
+
+ cr->show_page();
+
+ cout << "Wrote SVG file \"" << fname << "\"" << endl;
+ return 0;
+
+#else
+
+ cout << "You must compile cairo with SVG support for this example to work."
+ << endl;
+ return 1;
+
+#endif
+
+}
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4 :
diff --git a/src/3rdparty/adaptagrams/libcola/tests/cycle_detector.cpp b/src/3rdparty/adaptagrams/libcola/tests/cycle_detector.cpp
new file mode 100644
index 0000000..3b9a0a4
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/cycle_detector.cpp
@@ -0,0 +1,386 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+#include <iostream>
+#include <vector>
+#include <assert.h>
+#include <libcola/cola.h>
+#include <libcola/cycle_detector.h>
+#include "graphlayouttest.h"
+
+using namespace std;
+using namespace cola;
+using namespace cycle_detector;
+using vpsc::Rectangle;
+
+int main() {
+ CycleDetector *cd;
+ Edges case_a, case_b, case_c, case_d, case_e, case_f, case_g;
+
+ CyclicEdges *cycles = nullptr;
+ vector<Rectangle *> rs;
+ unsigned V;
+
+ // create case A
+ // case A consists of a basic graph where the start point is a source
+ cout << endl << "ENTERING CASE A" << endl;
+ V = 5;
+ case_a.push_back(Edge(0, 1));
+ case_a.push_back(Edge(1, 2));
+ case_a.push_back(Edge(2, 3));
+ case_a.push_back(Edge(3, 4));
+ case_a.push_back(Edge(4, 1));
+
+ // detect the cycles
+ cd = new CycleDetector(V, &case_a);
+ cycles = cd->detect_cycles();
+
+ if (cycles != nullptr) {
+ cout << "cycles->size(): " << cycles->size() << endl;
+ for (unsigned i = 0; i < case_a.size(); i++) {
+ // print out the cycles
+ if ((*cycles)[i]) cout << "Cyclic edge found: (" << case_a[i].first << ", " << case_a[i].second << ")" << endl;
+ }
+
+ cout << endl;
+
+ // output a picture
+ rs.push_back(new Rectangle(10,10+5,10,10+5));
+ rs.push_back(new Rectangle(30,30+5,30,30+5));
+ rs.push_back(new Rectangle(30,30+5,60,60+5));
+ rs.push_back(new Rectangle(65,65+5,60,60+5));
+ rs.push_back(new Rectangle(65,65+5,30,30+5));
+
+ assert(rs.size() == V);
+
+ output_svg(rs, case_a, "cycle_detector_case_a.svg", false, true, cycles);
+ for (unsigned i = 0; i < rs.size(); i++) { delete rs[i]; }
+ rs.clear();
+ delete cycles;
+ }
+ else {
+ cout << "No cycles found" << endl;
+ }
+
+ // create case B
+ // case B is the same graph of case A but with more elements
+ cout << endl << "ENTERING CASE B" << endl;
+ V = 7;
+ case_b.push_back(Edge(0, 1));
+ case_b.push_back(Edge(1, 2));
+ case_b.push_back(Edge(2, 3));
+ case_b.push_back(Edge(3, 4));
+ case_b.push_back(Edge(4, 1));
+ case_b.push_back(Edge(5, 2));
+ case_b.push_back(Edge(6, 5));
+
+ // detect the cycles
+ cd->mod_graph(V, &case_b);
+ cycles = cd->detect_cycles();
+
+ if (cycles != nullptr) {
+ cout << "cycles->size(): " << cycles->size() << endl;
+ for (unsigned i = 0; i < case_b.size(); i++) {
+ // print out the cycles
+ if ((*cycles)[i]) cout << "Cyclic edge found: (" << case_b[i].first << ", " << case_b[i].second << ")" << endl;
+ }
+
+ cout << endl;
+
+ // output a picture
+ rs.push_back(new Rectangle(10,10+5,10,10+5));
+ rs.push_back(new Rectangle(30,30+5,30,30+5));
+ rs.push_back(new Rectangle(30,30+5,60,60+5));
+ rs.push_back(new Rectangle(65,65+5,60,60+5));
+ rs.push_back(new Rectangle(65,65+5,30,30+5));
+ rs.push_back(new Rectangle(30,30+5,90,90+5));
+ rs.push_back(new Rectangle(65,65+5,90,90+5));
+
+ assert(rs.size() == V);
+
+ output_svg(rs, case_b, "cycle_detector_case_b.svg", false, true, cycles);
+ for (unsigned i = 0; i < rs.size(); i++) { delete rs[i]; }
+ rs.clear();
+ delete cycles;
+ }
+
+ // create case C
+ // case C is a more complicated graph with nested cycles
+ cout << endl << "ENTERING CASE C" << endl;
+ V = 14;
+ case_c.push_back(Edge(0, 1));
+ case_c.push_back(Edge(0, 5));
+ case_c.push_back(Edge(0, 6));
+ case_c.push_back(Edge(2, 0));
+ case_c.push_back(Edge(3, 5));
+ case_c.push_back(Edge(4, 3));
+ case_c.push_back(Edge(5, 4));
+ case_c.push_back(Edge(5, 13));
+ case_c.push_back(Edge(6, 2));
+ case_c.push_back(Edge(6, 9));
+ case_c.push_back(Edge(7, 6));
+ case_c.push_back(Edge(8, 7));
+ case_c.push_back(Edge(9, 10));
+ case_c.push_back(Edge(9, 11));
+ case_c.push_back(Edge(9, 12));
+ case_c.push_back(Edge(10, 6));
+ case_c.push_back(Edge(12, 10));
+ case_c.push_back(Edge(13, 4));
+
+ // detect the cycles
+ //cd = new CycleDetector(V, &case_c);
+ cd->mod_graph(V, &case_c);
+ cycles = cd->detect_cycles();
+ if (cycles != nullptr) {
+ cout << "cycles->size(): " << cycles->size() << endl;
+ for (unsigned i = 0; i < case_c.size(); i++) {
+ // print out the cycles
+ if ((*cycles)[i]) cout << "Cyclic edge found: (" << case_c[i].first << ", " << case_c[i].second << ")" << endl;
+ }
+
+ cout << endl;
+
+ // output a picture
+ rs.push_back(new Rectangle(10,10+5,10,10+5)); // node 0
+ rs.push_back(new Rectangle(20,20+5,40,40+5)); // node 1
+ rs.push_back(new Rectangle(40,40+5,30,30+5)); // node 2
+ rs.push_back(new Rectangle(30,30+5,60,60+5)); // node 3
+ rs.push_back(new Rectangle(60,60+5,60,60+5)); // node 4
+ rs.push_back(new Rectangle(10,10+5,90,90+5)); // node 5
+ rs.push_back(new Rectangle(80,80+5,15,15+5)); // node 6
+ rs.push_back(new Rectangle(110,110+5,15,15+5)); // node 7
+ rs.push_back(new Rectangle(140,140+5,15,15+5)); // node 8
+ rs.push_back(new Rectangle(110,110+5,60,60+5)); // node 9
+ rs.push_back(new Rectangle(100,100+5,85,85+5)); // node 10
+ rs.push_back(new Rectangle(140,140+5,50,50+5)); // node 11
+ rs.push_back(new Rectangle(140,140+5,70,70+5)); // node 12
+ rs.push_back(new Rectangle(45,45+5,90,90+5)); // node 13
+
+ assert(rs.size() == V);
+
+ output_svg(rs, case_c, "cycle_detector_case_c.svg", false, true, cycles);
+ for(int i = 0; i < V; i++) { delete rs[i]; }
+ rs.clear();
+ delete cycles;
+ }
+
+ // create case D
+ // case D consists of the same graph as case A but with a different starting location
+ cout << endl << "ENTERING CASE D" << endl;
+ V = 5;
+ case_d.push_back(Edge(0, 1));
+ case_d.push_back(Edge(1, 2));
+ case_d.push_back(Edge(2, 3));
+ case_d.push_back(Edge(3, 0));
+ case_d.push_back(Edge(4, 1));
+
+ // detect the cycles
+ cd->mod_graph(V, &case_d);
+ cycles = cd->detect_cycles();
+
+ if (cycles != nullptr) {
+ cout << "cycles->size(): " << cycles->size() << endl;
+ for (unsigned i = 0; i < case_d.size(); i++) {
+ // print out the cycles
+ if ((*cycles)[i]) cout << "Cyclic edge found: (" << case_d[i].first << ", " << case_d[i].second << ")" << endl;
+ }
+
+ cout << endl;
+
+ // output a picture
+ rs.push_back(new Rectangle(65,65+5,60,60+5));
+ rs.push_back(new Rectangle(65,65+5,30,30+5));
+ rs.push_back(new Rectangle(30,30+5,30,30+5));
+ rs.push_back(new Rectangle(30,30+5,60,60+5));
+ rs.push_back(new Rectangle(10,10+5,10,10+5));
+
+ assert(rs.size() == V);
+
+ output_svg(rs, case_d, "cycle_detector_case_d.svg", false, true, cycles);
+ for (unsigned i = 0; i < rs.size(); i++) { delete rs[i]; }
+ rs.clear();
+ delete cycles;
+ }
+ else {
+ cout << "No cycles found" << endl;
+ }
+
+ // create case E
+ // case E is a reordering of case C
+ cout << endl << "ENTERING CASE E" << endl;
+ V = 14;
+ case_e.push_back(Edge(0, 6));
+ case_e.push_back(Edge(0, 9));
+ case_e.push_back(Edge(1, 4));
+ case_e.push_back(Edge(3, 10));
+ case_e.push_back(Edge(4, 3));
+ case_e.push_back(Edge(5, 0));
+ case_e.push_back(Edge(6, 7));
+ case_e.push_back(Edge(7, 0));
+ case_e.push_back(Edge(7, 2));
+ case_e.push_back(Edge(7, 10));
+ case_e.push_back(Edge(8, 5));
+ case_e.push_back(Edge(9, 12));
+ case_e.push_back(Edge(9, 11));
+ case_e.push_back(Edge(9, 13));
+ case_e.push_back(Edge(10, 1));
+ case_e.push_back(Edge(10, 4));
+ case_e.push_back(Edge(12, 0));
+ case_e.push_back(Edge(11, 12));
+
+ // detect the cycles
+ cd->mod_graph(V, &case_e);
+ cycles = cd->detect_cycles();
+ if (cycles != nullptr) {
+ cout << "cycles->size(): " << cycles->size() << endl;
+ for (unsigned i = 0; i < case_e.size(); i++) {
+ // print out the cycles
+ if ((*cycles)[i]) cout << "Cyclic edge found: (" << case_e[i].first << ", " << case_e[i].second << ")" << endl;
+ }
+
+ cout << endl;
+
+ // output a picture
+ rs.push_back(new Rectangle(80,80+5,15,15+5)); // node 6
+ rs.push_back(new Rectangle(45,45+5,90,90+5)); // node 13
+ rs.push_back(new Rectangle(20,20+5,40,40+5)); // node 1
+ rs.push_back(new Rectangle(30,30+5,60,60+5)); // node 3
+ rs.push_back(new Rectangle(60,60+5,60,60+5)); // node 4
+ rs.push_back(new Rectangle(110,110+5,15,15+5)); // node 7
+ rs.push_back(new Rectangle(40,40+5,30,30+5)); // node 2
+ rs.push_back(new Rectangle(10,10+5,10,10+5)); // node 0
+ rs.push_back(new Rectangle(140,140+5,15,15+5)); // node 8
+ rs.push_back(new Rectangle(110,110+5,60,60+5)); // node 9
+ rs.push_back(new Rectangle(10,10+5,90,90+5)); // node 5
+ rs.push_back(new Rectangle(140,140+5,70,70+5)); // node 12
+ rs.push_back(new Rectangle(100,100+5,85,85+5)); // node 10
+ rs.push_back(new Rectangle(140,140+5,50,50+5)); // node 11
+
+ assert(rs.size() == V);
+
+ output_svg(rs, case_e, "cycle_detector_case_e.svg", false, true, cycles);
+ for(int i = 0; i < V; i++) { delete rs[i]; }
+ rs.clear();
+ delete cycles;
+ }
+
+ // create case F
+ // case F consists of the same graph with sinks
+ cout << endl << "ENTERING CASE F" << endl;
+ V = 3;
+ case_f.push_back(Edge(0, 1));
+ case_f.push_back(Edge(0, 2));
+ case_f.push_back(Edge(1, 2));
+
+ // detect the cycles
+ cd->mod_graph(V, &case_f);
+ cycles = cd->detect_cycles();
+
+ if (cycles != nullptr) {
+ // output a picture
+ rs.push_back(new Rectangle(10,10+5,10,10+5));
+ rs.push_back(new Rectangle(40,40+5,30,30+5));
+ rs.push_back(new Rectangle(15,15+5,60,60+5));
+
+ assert(rs.size() == V);
+
+ output_svg(rs, case_f, "cycle_detector_case_f.svg", false, true, cycles);
+ for (unsigned i = 0; i < rs.size(); i++) { delete rs[i]; }
+ rs.clear();
+
+ cout << "No cycles found" << endl;
+ }
+
+ // This tests the cycle detectors ability to cycle through a chain of cyclic ancestors
+ cout << endl << "ENTERING CYCLIC ANCESTOR TEST" << endl;
+ Node a(1), b(2), c(3), d(4), e(5), f(6);
+ // set up the chain
+ f.cyclicAncestor = &e;
+ e.cyclicAncestor = &d;
+ d.cyclicAncestor = &c;
+ c.cyclicAncestor = &b;
+ b.cyclicAncestor = &a;
+ a.cyclicAncestor = &a;
+
+ Node *ca = cd->get_highest_ca(&f);
+ if (ca != nullptr) { cout << "Highest cyclic ancestor found at vertex(" << ca->id << ")" << endl; }
+
+ // create case G
+ // case G hows the ability to find nested cycles and to reassign cyclic ancestors
+ cout << endl << "ENTERING CASE G" << endl;
+ V = 7;
+ case_g.push_back(Edge(0, 1));
+ case_g.push_back(Edge(1, 2));
+ case_g.push_back(Edge(2, 3));
+ case_g.push_back(Edge(3, 4));
+ case_g.push_back(Edge(4, 5));
+ case_g.push_back(Edge(5, 6));
+ case_g.push_back(Edge(6, 5));
+ case_g.push_back(Edge(5, 4));
+ case_g.push_back(Edge(4, 3));
+ case_g.push_back(Edge(3, 2));
+ case_g.push_back(Edge(2, 1));
+ case_g.push_back(Edge(1, 0));
+ case_g.push_back(Edge(0, 6));
+
+ // detect the cycles
+ cd->mod_graph(V, &case_g);
+ cycles = cd->detect_cycles();
+
+ if (cycles != nullptr) {
+ cout << "cycles->size(): " << cycles->size() << endl;
+ for (unsigned i = 0; i < case_g.size(); i++) {
+ // print out the cycles
+ if ((*cycles)[i]) cout << "Cyclic edge found: (" << case_g[i].first << ", " << case_g[i].second << ")" << endl;
+ }
+
+ cout << endl;
+
+ // output a picture
+ cout << "No picture generated" << endl;
+
+ /*rs.push_back(new Rectangle(50,50+5,10,10+5));
+ rs.push_back(new Rectangle(50,50+5,30,30+5));
+ rs.push_back(new Rectangle(50,50+5,60,60+5));
+ rs.push_back(new Rectangle(10,10+5,70,70+5));
+ rs.push_back(new Rectangle(50,50+5,100,100+5));
+ rs.push_back(new Rectangle(10,10+5,40,40+5));
+
+ assert(rs.size() == V);
+
+ output_svg(rs, case_a, "cycle_detector_case_g.svg", false, true, cycles);
+ for (unsigned i = 0; i < rs.size(); i++) { delete rs[i]; }
+ rs.clear();*/
+ delete cycles;
+ }
+ else {
+ cout << "No cycles found" << endl;
+ }
+
+ // END TEST
+ delete cd;
+
+ return 0;
+}
diff --git a/src/3rdparty/adaptagrams/libcola/tests/data/1138_bus.txt b/src/3rdparty/adaptagrams/libcola/tests/data/1138_bus.txt
new file mode 100644
index 0000000..fb63ec3
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/data/1138_bus.txt
@@ -0,0 +1,1458 @@
+4 0
+562 0
+9 1
+562 1
+10 2
+33 2
+34 2
+103 2
+474 2
+6 3
+26 3
+100 3
+101 3
+102 3
+8 4
+6 5
+36 5
+97 5
+102 5
+36 6
+100 6
+101 6
+102 6
+25 7
+34 7
+723 7
+9 8
+103 8
+103 9
+11 10
+37 10
+565 10
+33 12
+103 12
+412 13
+15 14
+16 14
+17 14
+18 14
+410 14
+20 19
+36 19
+101 19
+21 20
+22 20
+23 20
+24 20
+34 25
+27 26
+28 26
+29 26
+100 26
+31 30
+99 30
+99 31
+99 32
+103 33
+552 33
+103 34
+709 34
+710 35
+101 36
+38 37
+97 37
+411 37
+98 38
+40 39
+42 39
+44 39
+41 40
+43 40
+145 42
+485 43
+48 44
+47 45
+47 46
+53 47
+505 47
+49 48
+52 48
+50 49
+51 49
+124 51
+53 52
+54 52
+424 53
+444 53
+446 53
+62 55
+65 56
+69 57
+66 58
+67 59
+129 60
+128 61
+63 62
+64 62
+70 63
+130 63
+225 63
+1094 64
+66 65
+67 65
+73 65
+182 65
+225 65
+67 66
+68 66
+73 67
+89 67
+200 67
+69 68
+181 69
+195 69
+1062 69
+1064 69
+1073 69
+71 70
+72 71
+120 71
+74 73
+75 73
+77 73
+79 73
+118 73
+203 74
+809 74
+917 74
+76 75
+77 75
+126 75
+1049 76
+78 77
+451 77
+415 78
+416 78
+453 78
+80 79
+446 79
+451 79
+447 80
+449 80
+463 80
+93 81
+93 82
+94 83
+86 84
+125 84
+86 85
+240 85
+250 85
+252 85
+266 85
+268 85
+282 85
+290 85
+292 85
+293 85
+301 85
+314 85
+87 86
+104 88
+114 88
+90 89
+91 90
+107 90
+114 90
+115 90
+92 91
+93 92
+251 92
+263 92
+270 92
+287 92
+291 92
+292 92
+293 92
+321 92
+322 92
+323 92
+324 92
+325 92
+95 93
+263 93
+317 93
+324 93
+96 94
+261 94
+267 94
+299 94
+144 95
+703 95
+704 95
+267 96
+412 98
+724 99
+731 99
+101 100
+102 100
+102 101
+477 102
+105 104
+108 104
+107 106
+109 107
+1028 108
+110 109
+327 109
+366 109
+369 109
+366 110
+367 110
+700 110
+112 111
+369 111
+685 111
+113 112
+114 112
+689 112
+1008 113
+116 115
+125 115
+118 117
+122 118
+120 119
+121 120
+503 120
+122 121
+123 121
+124 122
+124 123
+126 123
+125 124
+128 124
+545 124
+128 125
+127 126
+132 129
+172 129
+212 129
+131 130
+132 130
+135 130
+143 131
+741 131
+133 132
+135 134
+138 134
+739 134
+140 135
+138 136
+140 136
+760 136
+140 137
+876 137
+881 137
+139 138
+828 139
+829 139
+257 141
+365 141
+143 142
+742 142
+744 142
+825 142
+826 143
+317 144
+702 144
+146 145
+147 146
+165 148
+172 149
+174 150
+179 151
+182 152
+206 153
+197 154
+212 155
+218 156
+225 157
+181 158
+204 158
+171 159
+232 159
+221 160
+742 160
+162 161
+168 161
+208 161
+222 161
+231 161
+185 162
+200 162
+226 162
+165 163
+165 164
+166 164
+174 164
+193 164
+191 165
+200 165
+217 165
+174 166
+179 167
+208 167
+186 168
+187 169
+193 169
+177 170
+216 170
+172 171
+221 171
+754 171
+183 172
+210 173
+215 173
+178 174
+176 175
+177 175
+206 175
+206 176
+213 177
+216 177
+202 178
+208 179
+182 180
+182 181
+204 181
+220 181
+183 182
+200 182
+225 182
+192 183
+212 183
+186 184
+186 185
+217 185
+187 186
+205 186
+208 186
+210 188
+215 188
+198 189
+194 190
+196 190
+197 190
+210 190
+198 191
+217 191
+219 191
+197 192
+198 192
+207 192
+215 193
+210 194
+211 196
+200 199
+201 199
+217 200
+202 201
+220 204
+215 205
+207 206
+223 206
+214 209
+216 209
+217 209
+211 210
+503 212
+216 213
+217 215
+219 218
+229 218
+221 220
+224 220
+224 221
+232 221
+742 221
+231 222
+1025 223
+227 226
+228 227
+230 227
+231 227
+231 230
+235 233
+306 233
+235 234
+242 234
+269 234
+271 234
+297 234
+298 234
+285 235
+260 236
+286 236
+308 236
+365 236
+701 236
+238 237
+269 237
+269 238
+280 238
+258 239
+241 240
+245 240
+252 240
+256 240
+265 240
+274 240
+278 240
+288 240
+290 240
+291 240
+292 240
+293 240
+298 240
+309 240
+320 240
+326 240
+243 241
+244 241
+271 243
+297 244
+309 245
+247 246
+254 246
+254 247
+281 248
+256 249
+262 249
+288 249
+316 249
+266 250
+309 251
+312 251
+254 253
+284 253
+257 254
+259 254
+262 254
+289 255
+316 255
+320 255
+260 257
+326 257
+277 258
+288 259
+267 261
+275 261
+313 261
+310 263
+275 264
+299 264
+306 265
+281 266
+283 266
+301 266
+269 267
+300 267
+283 268
+274 269
+278 269
+279 269
+317 269
+319 269
+273 272
+302 272
+314 272
+311 273
+284 276
+288 276
+308 277
+291 282
+290 287
+297 294
+296 295
+298 296
+695 299
+313 300
+311 302
+304 303
+314 303
+328 303
+314 304
+321 305
+322 307
+325 310
+314 311
+315 314
+318 314
+322 314
+321 315
+703 317
+328 318
+324 323
+334 329
+335 330
+336 331
+349 332
+349 333
+336 334
+336 335
+337 336
+338 336
+339 336
+339 337
+339 338
+340 339
+341 339
+341 340
+342 341
+343 341
+344 341
+369 341
+345 342
+345 343
+345 344
+346 345
+348 345
+366 345
+347 346
+348 347
+349 348
+365 350
+352 351
+407 351
+408 351
+362 352
+381 352
+381 353
+382 353
+374 354
+382 355
+397 355
+393 356
+394 356
+478 357
+473 358
+714 359
+478 360
+479 360
+402 361
+713 361
+363 362
+364 362
+372 362
+373 362
+387 362
+394 362
+406 362
+473 362
+698 365
+367 366
+371 366
+370 368
+371 370
+375 374
+376 374
+377 374
+378 374
+379 374
+380 374
+388 374
+403 374
+383 382
+384 382
+385 382
+386 382
+391 382
+388 387
+389 387
+390 387
+394 387
+400 387
+404 387
+394 391
+473 392
+478 392
+394 393
+397 394
+398 394
+404 394
+405 394
+406 394
+473 394
+405 395
+715 395
+716 395
+715 396
+716 396
+472 399
+401 400
+713 400
+408 403
+478 405
+482 405
+715 405
+716 405
+410 409
+411 409
+730 409
+475 410
+476 410
+485 410
+412 411
+477 411
+708 411
+723 411
+430 413
+432 413
+431 414
+432 414
+432 415
+461 415
+432 416
+461 416
+418 417
+544 417
+420 419
+421 419
+469 419
+424 422
+515 422
+465 423
+515 423
+425 424
+426 424
+465 424
+436 425
+518 425
+428 427
+429 427
+430 427
+431 427
+433 432
+509 432
+563 432
+509 434
+533 435
+437 436
+438 436
+440 436
+457 436
+439 438
+459 438
+441 440
+443 442
+469 442
+505 442
+515 442
+457 443
+445 444
+446 444
+448 446
+536 446
+463 447
+449 448
+450 449
+452 451
+454 453
+456 455
+563 455
+458 457
+459 457
+460 459
+462 461
+464 463
+544 463
+967 464
+466 465
+543 467
+542 468
+471 470
+477 470
+480 470
+491 470
+706 470
+707 470
+473 472
+709 474
+723 474
+481 475
+477 476
+707 477
+708 477
+479 478
+713 478
+725 478
+483 480
+484 480
+490 480
+491 480
+732 480
+482 481
+708 483
+732 483
+490 484
+730 485
+490 486
+490 487
+491 488
+491 489
+491 490
+733 490
+706 491
+706 492
+504 493
+512 494
+520 495
+521 496
+522 497
+499 498
+818 498
+913 498
+501 500
+504 500
+506 500
+520 500
+530 500
+535 500
+606 501
+608 501
+612 501
+936 501
+506 502
+512 502
+552 502
+504 503
+520 504
+525 504
+577 504
+507 506
+508 506
+514 506
+520 506
+521 506
+546 506
+618 507
+638 507
+780 507
+510 508
+514 508
+519 508
+533 508
+519 509
+913 510
+925 510
+519 511
+513 512
+539 512
+789 513
+794 513
+515 514
+516 514
+517 514
+535 514
+546 514
+992 516
+994 516
+956 518
+966 518
+521 520
+522 521
+581 522
+769 522
+778 522
+801 522
+532 523
+984 523
+1000 523
+567 524
+526 525
+530 525
+920 526
+932 526
+1067 526
+1072 526
+1073 526
+1123 526
+528 527
+808 527
+818 527
+577 529
+582 529
+779 529
+796 529
+802 529
+531 530
+533 530
+553 531
+646 531
+651 531
+662 531
+667 531
+671 531
+672 531
+676 531
+907 531
+911 531
+917 531
+1046 531
+534 533
+535 533
+541 533
+884 534
+536 535
+537 535
+538 535
+541 535
+808 537
+913 537
+947 537
+952 537
+963 537
+799 539
+542 540
+542 541
+544 541
+545 541
+543 542
+550 547
+562 548
+565 549
+551 550
+554 550
+565 550
+557 551
+559 551
+560 552
+709 552
+573 553
+908 553
+555 554
+556 554
+563 554
+565 554
+558 555
+578 555
+620 555
+902 555
+557 556
+978 557
+979 557
+985 557
+988 557
+990 557
+997 557
+999 557
+578 558
+979 559
+561 560
+565 560
+562 561
+566 562
+566 564
+566 565
+772 567
+794 567
+784 568
+578 569
+775 570
+782 571
+795 572
+580 574
+581 575
+783 575
+785 576
+801 576
+1089 576
+779 577
+579 578
+781 578
+782 578
+894 578
+926 578
+586 579
+775 580
+795 580
+796 580
+798 580
+779 582
+802 582
+584 583
+1067 583
+606 584
+612 584
+658 584
+596 585
+597 586
+613 586
+594 587
+596 587
+590 588
+594 589
+615 589
+600 590
+610 591
+603 592
+599 593
+596 595
+602 595
+606 595
+1104 598
+600 599
+781 599
+601 600
+632 600
+639 601
+603 602
+604 602
+1091 602
+611 603
+614 603
+606 604
+609 605
+609 607
+1100 607
+1067 608
+614 610
+1122 616
+628 617
+638 617
+619 618
+631 619
+623 620
+1060 620
+624 621
+640 621
+638 622
+641 622
+637 623
+634 624
+633 625
+634 625
+638 626
+630 627
+641 627
+636 628
+642 628
+630 629
+634 629
+795 629
+633 631
+640 631
+635 634
+1093 635
+651 643
+661 643
+649 644
+1059 644
+663 645
+1050 645
+1040 646
+677 647
+1041 647
+671 648
+1054 648
+652 649
+669 650
+1044 650
+652 651
+662 651
+665 651
+667 651
+675 651
+1053 651
+1047 652
+676 653
+1056 653
+656 654
+664 654
+677 655
+1054 656
+670 657
+671 657
+676 658
+1049 659
+1057 659
+676 660
+671 661
+1055 663
+681 664
+680 665
+1050 666
+678 668
+1057 668
+1120 669
+678 670
+672 671
+681 671
+1048 671
+1049 671
+1051 671
+1057 671
+1120 671
+674 673
+1045 673
+1049 674
+1042 675
+677 676
+1040 676
+1058 676
+1046 679
+1056 679
+1052 680
+688 682
+688 683
+690 684
+686 685
+687 685
+688 687
+693 687
+698 687
+699 687
+701 687
+692 688
+690 689
+693 689
+696 689
+691 690
+694 690
+694 692
+694 693
+697 696
+699 698
+706 705
+725 706
+708 707
+723 710
+733 710
+713 711
+713 712
+714 713
+733 713
+716 715
+723 717
+723 718
+723 719
+723 720
+723 721
+723 722
+724 723
+733 723
+727 726
+730 726
+730 727
+729 728
+730 728
+730 729
+742 734
+741 735
+742 736
+741 737
+743 738
+740 739
+741 739
+743 739
+748 740
+758 740
+742 741
+745 742
+755 743
+745 744
+747 746
+757 746
+756 747
+752 748
+750 749
+758 749
+756 751
+761 751
+756 753
+764 753
+763 754
+756 755
+760 759
+765 760
+766 760
+762 761
+767 765
+768 767
+771 767
+822 769
+771 770
+773 772
+794 772
+800 772
+801 772
+775 774
+780 774
+780 775
+795 775
+796 775
+1126 775
+792 776
+794 776
+799 776
+778 777
+779 778
+786 778
+796 779
+948 779
+782 781
+801 783
+785 784
+787 784
+795 784
+796 784
+801 784
+1127 785
+948 786
+788 787
+795 787
+1131 787
+1093 788
+790 789
+794 789
+798 791
+1109 791
+793 792
+824 792
+794 793
+799 793
+798 795
+797 796
+802 796
+804 796
+1118 796
+1113 797
+1136 801
+803 802
+1137 804
+820 805
+886 806
+896 807
+919 808
+810 809
+917 809
+908 811
+884 812
+939 812
+1121 812
+814 813
+908 813
+917 813
+816 815
+926 815
+817 816
+906 816
+819 818
+887 820
+896 820
+920 820
+879 821
+884 821
+934 821
+824 823
+836 827
+837 827
+873 827
+832 828
+838 828
+832 829
+839 829
+840 830
+868 830
+841 831
+868 831
+842 832
+843 833
+873 833
+844 834
+861 834
+845 835
+868 835
+858 837
+859 837
+847 846
+872 847
+853 848
+862 848
+863 848
+854 849
+872 849
+855 850
+857 850
+856 851
+868 851
+875 852
+872 857
+860 859
+862 861
+868 862
+864 863
+868 863
+868 865
+876 865
+877 866
+868 867
+870 867
+876 867
+869 868
+870 869
+876 869
+881 871
+881 872
+877 873
+875 874
+881 874
+877 876
+882 876
+881 878
+881 880
+936 883
+1122 883
+913 884
+917 884
+894 885
+926 885
+936 885
+895 886
+896 886
+923 887
+916 888
+890 889
+907 889
+916 889
+892 891
+898 891
+926 891
+920 893
+935 893
+1125 893
+1124 894
+896 895
+912 896
+916 896
+943 896
+913 897
+925 897
+899 898
+907 898
+912 900
+1128 900
+905 901
+986 902
+904 903
+938 903
+943 903
+921 905
+938 905
+922 906
+911 907
+916 907
+926 907
+909 908
+911 910
+934 913
+937 913
+962 913
+925 914
+990 915
+917 916
+929 916
+918 917
+1129 917
+939 918
+922 920
+923 920
+926 920
+932 920
+936 920
+929 921
+1132 921
+924 923
+927 926
+936 926
+928 927
+936 927
+930 929
+948 931
+933 932
+941 932
+946 934
+936 935
+1133 935
+953 939
+953 940
+943 942
+960 944
+964 945
+951 947
+954 947
+956 947
+957 947
+963 947
+950 949
+954 949
+955 949
+964 950
+968 950
+974 950
+959 951
+954 952
+958 953
+957 956
+966 956
+972 956
+972 959
+961 960
+962 960
+967 960
+965 961
+971 962
+967 964
+968 964
+970 965
+969 968
+971 970
+982 973
+976 975
+988 975
+1000 975
+988 977
+982 978
+981 980
+983 980
+997 980
+985 982
+986 984
+988 984
+998 986
+992 987
+994 987
+989 988
+991 990
+993 992
+996 994
+997 994
+996 995
+997 996
+1026 1001
+1034 1002
+1031 1003
+1038 1004
+1006 1005
+1012 1005
+1018 1005
+1020 1005
+1029 1005
+1034 1005
+1022 1007
+1009 1008
+1017 1008
+1018 1008
+1020 1008
+1021 1008
+1039 1008
+1039 1010
+1039 1011
+1022 1012
+1028 1012
+1029 1012
+1036 1012
+1037 1012
+1038 1012
+1038 1013
+1028 1014
+1023 1015
+1033 1015
+1028 1016
+1032 1018
+1020 1019
+1023 1022
+1024 1022
+1026 1022
+1033 1023
+1027 1024
+1026 1025
+1027 1026
+1034 1026
+1030 1029
+1033 1031
+1035 1031
+1035 1034
+1049 1042
+1049 1043
+1052 1043
+1046 1044
+1057 1045
+1053 1048
+1050 1049
+1051 1049
+1055 1050
+1055 1054
+1057 1054
+1060 1058
+1071 1061
+1084 1061
+1073 1062
+1074 1063
+1086 1063
+1076 1064
+1079 1064
+1067 1065
+1070 1066
+1068 1067
+1091 1067
+1085 1068
+1076 1069
+1112 1069
+1087 1070
+1074 1071
+1073 1072
+1074 1073
+1080 1073
+1085 1073
+1081 1074
+1076 1075
+1077 1076
+1079 1076
+1087 1076
+1094 1076
+1083 1077
+1084 1077
+1116 1078
+1086 1082
+1105 1088
+1111 1088
+1090 1089
+1092 1090
+1107 1090
+1097 1092
+1095 1094
+1099 1094
+1104 1094
+1112 1094
+1102 1095
+1106 1095
+1111 1095
+1099 1096
+1098 1097
+1100 1099
+1119 1100
+1111 1101
+1117 1103
+1118 1103
+1108 1105
+1113 1109
+1118 1110
+1114 1113
+1115 1113
+1119 1116
+1135 1121
+1134 1123
+1134 1128
+1135 1130
diff --git a/src/3rdparty/adaptagrams/libcola/tests/data/uetzNetworkGSC-all.gml b/src/3rdparty/adaptagrams/libcola/tests/data/uetzNetworkGSC-all.gml
new file mode 100644
index 0000000..99c4053
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/data/uetzNetworkGSC-all.gml
@@ -0,0 +1,26139 @@
+graph [
+ directed 1
+ node [
+ id 1
+ pajek_id 1
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1294.0522048684777
+ y 1122.6497967871214
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 2
+ pajek_id 2
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2055.718178872795
+ y 1059.2791761907554
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 3
+ pajek_id 3
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1256.6354129633914
+ y 1695.6123461841953
+ w 20.0
+ h 20.0
+ fill "#FFFF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 4
+ pajek_id 4
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1184.7211808078375
+ y 935.8910996786233
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 5
+ pajek_id 5
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2298.0954772536134
+ y 1437.502173559352
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 6
+ pajek_id 6
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1897.6814785435922
+ y 550.7159507323732
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 7
+ pajek_id 7
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1901.322129497895
+ y 1044.3438487090452
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 8
+ pajek_id 8
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2780.868057459027
+ y 880.0661109912785
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 9
+ pajek_id 9
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1538.3317441868267
+ y 1411.5744527134639
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 10
+ pajek_id 10
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 396.0152636117873
+ y 1131.0468905861571
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 11
+ pajek_id 11
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2807.6418756553476
+ y 1965.421804479885
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 12
+ pajek_id 12
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1483.7207919217562
+ y 1613.0999970511837
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 13
+ pajek_id 13
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 254.92863023355244
+ y 592.4142543364859
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 14
+ pajek_id 14
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2356.3555481078492
+ y 762.7982298395269
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 15
+ pajek_id 15
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 358.86149369612554
+ y 718.6522617063977
+ w 20.0
+ h 20.0
+ fill "#FFFF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 16
+ pajek_id 16
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1989.7728584457432
+ y 593.5406100260483
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 17
+ pajek_id 17
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1176.0589697518428
+ y 274.6599182522517
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 18
+ pajek_id 18
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 815.4286293876028
+ y 1519.2372285089286
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 19
+ pajek_id 19
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1292.8058349907271
+ y 1534.9166231756176
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 20
+ pajek_id 20
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1712.1139015143726
+ y 1743.9840389531971
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 21
+ pajek_id 21
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1159.0926195442978
+ y 60.0
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 22
+ pajek_id 22
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1698.8281996861965
+ y 938.1788913033595
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 23
+ pajek_id 23
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2117.1960623698105
+ y 377.3080137329175
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 24
+ pajek_id 24
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1988.5172976949088
+ y 1626.9118171301184
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 25
+ pajek_id 25
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1951.0677192239534
+ y 1227.8213042650113
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 26
+ pajek_id 26
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1209.2907663600151
+ y 571.9488583740487
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 27
+ pajek_id 27
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1553.217522639471
+ y 514.0779699887444
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 28
+ pajek_id 28
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1216.2131040787344
+ y 1306.3244872331861
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 29
+ pajek_id 29
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2495.910234238144
+ y 1509.2542926345884
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 30
+ pajek_id 30
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2589.368846133916
+ y 902.4410855851487
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 31
+ pajek_id 31
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1900.4466132863522
+ y 960.4878587369396
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 32
+ pajek_id 32
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1480.404193494587
+ y 503.45364906241434
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 33
+ pajek_id 33
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1786.4697371577445
+ y 2321.7848119927116
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 34
+ pajek_id 34
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1609.213005284541
+ y 1590.2108893694465
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 35
+ pajek_id 35
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 600.5008950141041
+ y 1277.5609673161835
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 36
+ pajek_id 36
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 60.0
+ y 768.8625017780407
+ w 20.0
+ h 20.0
+ fill "#FFFF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 37
+ pajek_id 37
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 382.9141452731493
+ y 1259.7726277058914
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 38
+ pajek_id 38
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 687.2063369120657
+ y 1082.3933671094655
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 39
+ pajek_id 39
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1027.5033292569951
+ y 1088.9830040963775
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 40
+ pajek_id 40
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1632.4747876484166
+ y 710.5037615118014
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 41
+ pajek_id 41
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 748.4550588733631
+ y 1062.8651339361004
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 42
+ pajek_id 42
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 963.8979533416527
+ y 1723.250139029375
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 43
+ pajek_id 43
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1411.3947986828978
+ y 1157.8550891438708
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 44
+ pajek_id 44
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2648.6214914664592
+ y 360.6532255567197
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 45
+ pajek_id 45
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1012.524198351514
+ y 1566.9080651878785
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 46
+ pajek_id 46
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1673.0588337518445
+ y 1520.3103374282064
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 47
+ pajek_id 47
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2292.062233641057
+ y 807.7075902196876
+ w 20.0
+ h 20.0
+ fill "#FFFF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 48
+ pajek_id 48
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2077.483685032171
+ y 1214.6266410102694
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 49
+ pajek_id 49
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1250.7982377330313
+ y 984.2480480318932
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 50
+ pajek_id 50
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 826.5624689443126
+ y 1458.2342219655006
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 51
+ pajek_id 51
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1043.503156998524
+ y 1914.4120411204835
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 52
+ pajek_id 52
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1097.4841298080655
+ y 608.9543419822743
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 53
+ pajek_id 53
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1151.8669553096083
+ y 1688.783506135614
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 54
+ pajek_id 54
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1100.1774339936296
+ y 449.9360013393336
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 55
+ pajek_id 55
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1797.1270429940496
+ y 517.7947984237063
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 56
+ pajek_id 56
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1958.7774891972645
+ y 951.067065374911
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 57
+ pajek_id 57
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1320.7173946510097
+ y 666.953428346941
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 58
+ pajek_id 58
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 409.511718757674
+ y 754.8270051102944
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 59
+ pajek_id 59
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 456.52944375010406
+ y 1644.5489937771122
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 60
+ pajek_id 60
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1650.4029796871373
+ y 1281.9794653489726
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 61
+ pajek_id 61
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2203.5059215970086
+ y 1103.986465771347
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 62
+ pajek_id 62
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1648.5790338469196
+ y 1619.5713910478498
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 63
+ pajek_id 63
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1441.449939123268
+ y 278.4421140050705
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 64
+ pajek_id 64
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1646.3755592037082
+ y 1867.8552090742746
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 65
+ pajek_id 65
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1690.4064173252282
+ y 1106.6596200585911
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 66
+ pajek_id 66
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1375.2079396723311
+ y 1567.1239230162141
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 67
+ pajek_id 67
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1381.6936762897983
+ y 930.9429010096588
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 68
+ pajek_id 68
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2246.515691754706
+ y 1228.672822112808
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 69
+ pajek_id 69
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2513.1221976499774
+ y 2123.5607442911432
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 70
+ pajek_id 70
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 325.1248018822786
+ y 1301.1300387216584
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 71
+ pajek_id 71
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 905.4567507395766
+ y 1635.3403866013616
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 72
+ pajek_id 72
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1409.3758774490468
+ y 2445.8494772528247
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 73
+ pajek_id 73
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 270.55209645867626
+ y 1976.484880612065
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 74
+ pajek_id 74
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1846.104723102188
+ y 2357.13888536703
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 75
+ pajek_id 75
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1931.8467589445268
+ y 1416.3573716456167
+ w 20.0
+ h 20.0
+ fill "#FFFF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 76
+ pajek_id 76
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 219.41564456563447
+ y 351.74606877700694
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 77
+ pajek_id 77
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1574.267945560331
+ y 994.005057804803
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 78
+ pajek_id 78
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2258.765897434142
+ y 975.7865089151361
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 79
+ pajek_id 79
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1003.0168039671166
+ y 818.3149905376152
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 80
+ pajek_id 80
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2162.351384651877
+ y 639.3742942428671
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 81
+ pajek_id 81
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1175.3498984884113
+ y 205.4073989675603
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 82
+ pajek_id 82
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1025.8732247508035
+ y 146.60499318409438
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 83
+ pajek_id 83
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 784.8316721743003
+ y 739.8886774008013
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 84
+ pajek_id 84
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2358.3905436512314
+ y 1757.8833117002607
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 85
+ pajek_id 85
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 187.0231231288874
+ y 464.9030131392583
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 86
+ pajek_id 86
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1680.1684155817545
+ y 989.3992861143759
+ w 20.0
+ h 20.0
+ fill "#FFFF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 87
+ pajek_id 87
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1592.5433115122046
+ y 1133.073079548351
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 88
+ pajek_id 88
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 984.0210982272379
+ y 1907.6496174273066
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 89
+ pajek_id 89
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1908.2544551347682
+ y 1953.0395792102486
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 90
+ pajek_id 90
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1760.6396933740039
+ y 454.1561397683437
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 91
+ pajek_id 91
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1510.4214829476575
+ y 255.4247158499462
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 92
+ pajek_id 92
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2156.911158437812
+ y 1737.2936541047445
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 93
+ pajek_id 93
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2330.4433111549088
+ y 1066.919264412134
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 94
+ pajek_id 94
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1489.0049739638976
+ y 1102.8420420131365
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 95
+ pajek_id 95
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1381.821327085725
+ y 1425.799958792195
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 96
+ pajek_id 96
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2026.5031721150344
+ y 1195.03677714938
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 97
+ pajek_id 97
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1566.5985533781122
+ y 2134.591986800821
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 98
+ pajek_id 98
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1866.8579043433465
+ y 496.54994132044186
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 99
+ pajek_id 99
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1709.8596572466934
+ y 1537.0985557194695
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 100
+ pajek_id 100
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1058.888749291412
+ y 1423.3219452240978
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 101
+ pajek_id 101
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1026.841049144297
+ y 1526.2197338662158
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 102
+ pajek_id 102
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1234.128325564796
+ y 1058.423971642138
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 103
+ pajek_id 103
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2269.604004829725
+ y 1961.2578434564753
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 104
+ pajek_id 104
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1204.604308471341
+ y 331.2782608195139
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 105
+ pajek_id 105
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1456.5954783621391
+ y 2393.969680005851
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 106
+ pajek_id 106
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1030.6221217055054
+ y 1655.7105879228054
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 107
+ pajek_id 107
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1825.2038903621162
+ y 1764.5225692398108
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 108
+ pajek_id 108
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 855.344393246044
+ y 1581.4397578617163
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 109
+ pajek_id 109
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2290.109859607357
+ y 1866.4142704202714
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 110
+ pajek_id 110
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2016.9300946422195
+ y 1800.0828289087844
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 111
+ pajek_id 111
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2311.298477488912
+ y 1203.9224047333146
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 112
+ pajek_id 112
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2173.9918013172064
+ y 1358.97529576786
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 113
+ pajek_id 113
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 402.8249532029572
+ y 2005.0535234158124
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 114
+ pajek_id 114
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1370.447752295795
+ y 1698.544524957459
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 115
+ pajek_id 115
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 824.5410187470699
+ y 2203.3482170965663
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 116
+ pajek_id 116
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1899.5312814624624
+ y 341.64788217907767
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 117
+ pajek_id 117
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1275.5334231652173
+ y 435.5539332588777
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 118
+ pajek_id 118
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1799.057369842763
+ y 898.644722551811
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 119
+ pajek_id 119
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 936.3882990544396
+ y 542.1677084693897
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 120
+ pajek_id 120
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2035.2157086365958
+ y 549.5503878259726
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 121
+ pajek_id 121
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2306.5008116638155
+ y 2172.8922465255055
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 122
+ pajek_id 122
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 794.0600584680333
+ y 1767.0092661358444
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 123
+ pajek_id 123
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 967.8528471899847
+ y 1305.606206649742
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 124
+ pajek_id 124
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2478.6497152538377
+ y 1203.6776389496872
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 125
+ pajek_id 125
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1997.321116636319
+ y 2192.367195588601
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 126
+ pajek_id 126
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1177.3434085029842
+ y 778.6424846605535
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 127
+ pajek_id 127
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1585.5048018331465
+ y 1455.2573996761384
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 128
+ pajek_id 128
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 472.28484900676176
+ y 718.0672675218485
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 129
+ pajek_id 129
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 794.0849295823707
+ y 1371.6459663216558
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 130
+ pajek_id 130
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2008.8851806591924
+ y 1293.0028606195688
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 131
+ pajek_id 131
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1441.295381525302
+ y 564.6073812973832
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 132
+ pajek_id 132
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1861.1042483735764
+ y 1523.2486386191717
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 133
+ pajek_id 133
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 957.7655245033009
+ y 114.39870152004505
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 134
+ pajek_id 134
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1961.9942877269461
+ y 124.43728726767961
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 135
+ pajek_id 135
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2317.512327717449
+ y 924.258173136443
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 136
+ pajek_id 136
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1800.1506277595804
+ y 2261.975902475042
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 137
+ pajek_id 137
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 595.234814691012
+ y 1025.317899636531
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 138
+ pajek_id 138
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 964.840641154222
+ y 247.01750927240698
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 139
+ pajek_id 139
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 588.9999815953205
+ y 2079.3235704527674
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 140
+ pajek_id 140
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2110.3560493557006
+ y 505.8109983485984
+ w 20.0
+ h 20.0
+ fill "#FFFF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 141
+ pajek_id 141
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1399.3112848730054
+ y 1227.804800096851
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 142
+ pajek_id 142
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1334.1378233999883
+ y 1813.8827309253875
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 143
+ pajek_id 143
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1805.918047276415
+ y 624.9341989045439
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 144
+ pajek_id 144
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1467.2887831794974
+ y 1491.092756875548
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 145
+ pajek_id 145
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1369.2679808531936
+ y 1127.5618294352796
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 146
+ pajek_id 146
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2025.2400562476682
+ y 1570.3163109170114
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 147
+ pajek_id 147
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2055.8364822532835
+ y 684.3901430356791
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 148
+ pajek_id 148
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2458.5244327113796
+ y 1391.3830145494958
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 149
+ pajek_id 149
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1552.825479830451
+ y 1252.8654366828728
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 150
+ pajek_id 150
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2642.703200490143
+ y 873.2840758651536
+ w 20.0
+ h 20.0
+ fill "#FFFF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 151
+ pajek_id 151
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2493.621315614442
+ y 1057.6778103427564
+ w 20.0
+ h 20.0
+ fill "#FFFF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 152
+ pajek_id 152
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2048.524265153669
+ y 2396.6375817898183
+ w 20.0
+ h 20.0
+ fill "#FFFF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 153
+ pajek_id 153
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1295.8980767195865
+ y 1281.8240646387455
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 154
+ pajek_id 154
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 948.0256773985192
+ y 874.4275219392624
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 155
+ pajek_id 155
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1060.558142370161
+ y 2121.7015632861817
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 156
+ pajek_id 156
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1588.0692311325395
+ y 2419.735277431223
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 157
+ pajek_id 157
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1399.2208755506806
+ y 668.8198477332975
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 158
+ pajek_id 158
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1580.2791211407448
+ y 894.9665199234698
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 159
+ pajek_id 159
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1585.445364428028
+ y 1518.9113878761736
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 160
+ pajek_id 160
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2149.623427593962
+ y 1585.663447804202
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 161
+ pajek_id 161
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1073.2288913412556
+ y 1374.5854206557112
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 162
+ pajek_id 162
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 493.61694579516404
+ y 1365.494793302807
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 163
+ pajek_id 163
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1286.2369050296045
+ y 1067.3473338636227
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 164
+ pajek_id 164
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 927.1316689881887
+ y 1385.503225606381
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 165
+ pajek_id 165
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2193.2522202024475
+ y 1206.1206658070653
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 166
+ pajek_id 166
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 772.1411120215096
+ y 1970.8119423759322
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 167
+ pajek_id 167
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1145.792529275603
+ y 1177.4939749954644
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 168
+ pajek_id 168
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 782.4194952141179
+ y 2042.5751921467117
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 169
+ pajek_id 169
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1254.116200428233
+ y 2594.759114678682
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 170
+ pajek_id 170
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2678.2734809510507
+ y 2096.8291622390625
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 171
+ pajek_id 171
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2400.4372550336543
+ y 1652.7179946898918
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 172
+ pajek_id 172
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1386.2112759254533
+ y 1638.7948048718672
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 173
+ pajek_id 173
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 943.8883491218697
+ y 1073.7919591358736
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 174
+ pajek_id 174
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1179.1603874552718
+ y 1122.3817446803446
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 175
+ pajek_id 175
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2233.8795632906877
+ y 1527.7817714192893
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 176
+ pajek_id 176
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2163.4669644146798
+ y 1260.955553479491
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 177
+ pajek_id 177
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1869.4250586602952
+ y 2472.448020780895
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 178
+ pajek_id 178
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1112.7457233061032
+ y 1329.0846670907608
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 179
+ pajek_id 179
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1118.8056866951574
+ y 852.6869706221119
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 180
+ pajek_id 180
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1307.2508861643091
+ y 2462.7701746985686
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 181
+ pajek_id 181
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1380.5745060829129
+ y 1076.2706855348051
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 182
+ pajek_id 182
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2036.4065621255
+ y 2529.571297575046
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 183
+ pajek_id 183
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1074.9510652351762
+ y 801.3658771409633
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 184
+ pajek_id 184
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 255.45722686156626
+ y 1805.532111761012
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 185
+ pajek_id 185
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2342.5052901155595
+ y 1982.0954207181567
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 186
+ pajek_id 186
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1178.1746215798703
+ y 871.8443836872366
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 187
+ pajek_id 187
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1537.0518689637947
+ y 1540.5124880929002
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 188
+ pajek_id 188
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1236.2077456256104
+ y 1534.272658840872
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 189
+ pajek_id 189
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1621.2397812102838
+ y 1400.4425940981625
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 190
+ pajek_id 190
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 766.3905805597286
+ y 886.402470142523
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 191
+ pajek_id 191
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2168.7884396974873
+ y 550.016818013951
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 192
+ pajek_id 192
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 993.9061877291988
+ y 1029.772643432917
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 193
+ pajek_id 193
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 463.0359831362713
+ y 1022.0861273460611
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 194
+ pajek_id 194
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 639.0038131671084
+ y 555.7612618656989
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 195
+ pajek_id 195
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1814.9683409976778
+ y 2445.753076164031
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 196
+ pajek_id 196
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1686.4439166148054
+ y 1938.4699461276296
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 197
+ pajek_id 197
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 930.0951591923147
+ y 1241.663890087508
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 198
+ pajek_id 198
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 520.2346633262122
+ y 1199.2357895089199
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 199
+ pajek_id 199
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1971.6382604373562
+ y 343.1014653785635
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 200
+ pajek_id 200
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2027.0179357401762
+ y 1349.107156613678
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 201
+ pajek_id 201
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2087.081528540994
+ y 802.4499939958602
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 202
+ pajek_id 202
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 625.0171226735023
+ y 1914.7856839077308
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 203
+ pajek_id 203
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1899.9652173985933
+ y 2072.1438307043504
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 204
+ pajek_id 204
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1606.0783659797662
+ y 1837.1508274695605
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 205
+ pajek_id 205
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 901.3919870421247
+ y 1513.1982896128998
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 206
+ pajek_id 206
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2538.1638433893568
+ y 1616.7551606942914
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 207
+ pajek_id 207
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1866.691494571614
+ y 2114.4934954074397
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 208
+ pajek_id 208
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1028.2574487173333
+ y 973.0790458888064
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 209
+ pajek_id 209
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1753.7616445481387
+ y 928.4269154425315
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 210
+ pajek_id 210
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 434.8320641528154
+ y 900.7941512774352
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 211
+ pajek_id 211
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1197.692612238198
+ y 1656.3283202472192
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 212
+ pajek_id 212
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2262.872473159019
+ y 855.5192882246674
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 213
+ pajek_id 213
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2005.7033668568552
+ y 1687.3129033516693
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 214
+ pajek_id 214
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2005.4330911080656
+ y 1248.6067376996575
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 215
+ pajek_id 215
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1497.6387156758587
+ y 409.988817350047
+ w 20.0
+ h 20.0
+ fill "#FFFF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 216
+ pajek_id 216
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1511.6499513985573
+ y 2019.1033155888222
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 217
+ pajek_id 217
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1832.9845660337855
+ y 1594.9330492361391
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 218
+ pajek_id 218
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2124.163466904739
+ y 1121.7594517130105
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 219
+ pajek_id 219
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2114.0594425877107
+ y 879.072087899176
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 220
+ pajek_id 220
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2060.685078868419
+ y 1835.1973884802942
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 221
+ pajek_id 221
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2250.360824827312
+ y 908.8247250753682
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 222
+ pajek_id 222
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1619.44524541997
+ y 1208.958636465997
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 223
+ pajek_id 223
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1420.5578431824722
+ y 1022.1078286320392
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 224
+ pajek_id 224
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1804.5906551872706
+ y 1356.7859367888193
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 225
+ pajek_id 225
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1182.3901258139676
+ y 1078.275091742608
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 226
+ pajek_id 226
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 939.5649257137159
+ y 750.6386331311932
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 227
+ pajek_id 227
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1227.5697565955718
+ y 1194.722525770867
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 228
+ pajek_id 228
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1677.315636418083
+ y 818.1002681824733
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 229
+ pajek_id 229
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1969.8218697907696
+ y 2124.400924405766
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 230
+ pajek_id 230
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1346.0361911089835
+ y 591.0926251849802
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 231
+ pajek_id 231
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1937.4480655403545
+ y 1484.3086656977262
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 232
+ pajek_id 232
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 913.1080893674856
+ y 2448.9010701058382
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 233
+ pajek_id 233
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 980.1355123328368
+ y 2143.0193206720637
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 234
+ pajek_id 234
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2468.507735819624
+ y 680.6867726745393
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 235
+ pajek_id 235
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 961.6345650781091
+ y 965.0860824711237
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 236
+ pajek_id 236
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 492.09673495414074
+ y 284.8975707321614
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 237
+ pajek_id 237
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1446.3792419244076
+ y 1813.9029462286976
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 238
+ pajek_id 238
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1813.9462106455926
+ y 947.4822230702299
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 239
+ pajek_id 239
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1428.5911518460912
+ y 1609.8340596280282
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 240
+ pajek_id 240
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1005.3650634855937
+ y 882.2530156601648
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 241
+ pajek_id 241
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1970.4155162426391
+ y 1125.8976010185038
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 242
+ pajek_id 242
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 240.57076448405542
+ y 1473.723263945339
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 243
+ pajek_id 243
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2046.1993784054494
+ y 950.6121816835345
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 244
+ pajek_id 244
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2808.307733786458
+ y 1514.739154198832
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 245
+ pajek_id 245
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1882.8938446652257
+ y 1459.0281000095843
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 246
+ pajek_id 246
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1723.9114037847546
+ y 2365.644132764209
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 247
+ pajek_id 247
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1936.717394034969
+ y 1594.3192138208242
+ w 20.0
+ h 20.0
+ fill "#FFFF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 248
+ pajek_id 248
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1971.7509493535508
+ y 1179.4845850946012
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 249
+ pajek_id 249
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1058.6250365444143
+ y 859.7134012319751
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 250
+ pajek_id 250
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1875.0949016123318
+ y 2018.8968281970356
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 251
+ pajek_id 251
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 802.2218018782783
+ y 830.0503347776802
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 252
+ pajek_id 252
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 813.0528123889172
+ y 1656.3453211681867
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 253
+ pajek_id 253
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1273.6722755380645
+ y 562.4903627029978
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 254
+ pajek_id 254
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 738.6225904711797
+ y 1832.437257453023
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 255
+ pajek_id 255
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2123.755229836545
+ y 2672.877537298277
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 256
+ pajek_id 256
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 766.238178017943
+ y 627.4085851267696
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 257
+ pajek_id 257
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1129.8317234871274
+ y 1757.6767114954823
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 258
+ pajek_id 258
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2009.7762232303267
+ y 2041.0971651622217
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 259
+ pajek_id 259
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1736.9465300050063
+ y 1793.4455313056224
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 260
+ pajek_id 260
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 648.0899197694613
+ y 1133.071910642336
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 261
+ pajek_id 261
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2673.608535682633
+ y 1969.3166527926637
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 262
+ pajek_id 262
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1190.4241821550581
+ y 1456.8778384709221
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 263
+ pajek_id 263
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1773.3304812765168
+ y 1171.6981943217245
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 264
+ pajek_id 264
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2455.8689870091684
+ y 1698.2588839027976
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 265
+ pajek_id 265
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1572.4184904317372
+ y 1079.9405584556314
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 266
+ pajek_id 266
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 930.5993117411441
+ y 932.4301787306301
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 267
+ pajek_id 267
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1241.016109181929
+ y 1641.851386078472
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 268
+ pajek_id 268
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1778.3112226979574
+ y 1527.5198182466306
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 269
+ pajek_id 269
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1997.6945206439827
+ y 1435.167335502786
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 270
+ pajek_id 270
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2928.2834579168007
+ y 1108.202244706911
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 271
+ pajek_id 271
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1549.1458457473145
+ y 592.3498910478805
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 272
+ pajek_id 272
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2567.1609182049815
+ y 349.9728983492399
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 273
+ pajek_id 273
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1790.3664691634244
+ y 2391.926302478362
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 274
+ pajek_id 274
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1156.9233946634465
+ y 1363.0451223083915
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 275
+ pajek_id 275
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 856.1024353157368
+ y 2058.0580043741106
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 276
+ pajek_id 276
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2007.3448524911623
+ y 955.2249749444019
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 277
+ pajek_id 277
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1867.826843063508
+ y 1168.1178614284738
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 278
+ pajek_id 278
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1849.7065836818551
+ y 1931.1333235795955
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 279
+ pajek_id 279
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1260.0763722109286
+ y 655.2169595822215
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 280
+ pajek_id 280
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1899.1104082490497
+ y 1614.8129891919102
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 281
+ pajek_id 281
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2378.43114046961
+ y 2184.529789498435
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 282
+ pajek_id 282
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2040.929028434561
+ y 2329.0083925520726
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 283
+ pajek_id 283
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1329.822091272441
+ y 817.7805081038614
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 284
+ pajek_id 284
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1916.5095601095395
+ y 1315.8369929397447
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 285
+ pajek_id 285
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1540.8732018426379
+ y 1757.2830276053164
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 286
+ pajek_id 286
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1497.5518877310492
+ y 2332.209587716714
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 287
+ pajek_id 287
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1820.876610989953
+ y 1705.7800792711614
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 288
+ pajek_id 288
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2053.621424690008
+ y 137.4950984709352
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 289
+ pajek_id 289
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2288.638168809773
+ y 1661.1373438648448
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 290
+ pajek_id 290
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2521.628031511117
+ y 1112.8442155271284
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 291
+ pajek_id 291
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2621.075261275747
+ y 1040.7003954194217
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 292
+ pajek_id 292
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1489.7226658046911
+ y 1212.598420726727
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 293
+ pajek_id 293
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1344.039251806568
+ y 765.4921416388333
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 294
+ pajek_id 294
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2783.106085646018
+ y 1011.1576483698651
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 295
+ pajek_id 295
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 666.034857878941
+ y 1196.1544941612838
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 296
+ pajek_id 296
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1069.4593629564115
+ y 1627.9059240200613
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 297
+ pajek_id 297
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1798.2247140891636
+ y 1428.1375539568382
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 298
+ pajek_id 298
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1934.1343683875075
+ y 2404.2315045912405
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 299
+ pajek_id 299
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2699.851785344458
+ y 427.8558563028148
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 300
+ pajek_id 300
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 834.2031874852718
+ y 250.70469068286297
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 301
+ pajek_id 301
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1004.0710874574961
+ y 1280.167160042513
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 302
+ pajek_id 302
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1750.4516583745296
+ y 1471.2162955489407
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 303
+ pajek_id 303
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2401.7820655598725
+ y 2272.1863557268275
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 304
+ pajek_id 304
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1814.6823768957051
+ y 2071.5062836539637
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 305
+ pajek_id 305
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2520.536274654057
+ y 992.8636618688267
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 306
+ pajek_id 306
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2265.0881548319567
+ y 2065.5837863656484
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 307
+ pajek_id 307
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1257.8172960656739
+ y 803.4108171125971
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 308
+ pajek_id 308
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 776.7856178664061
+ y 1694.4563434703907
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 309
+ pajek_id 309
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1440.886631358504
+ y 1532.750033969016
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 310
+ pajek_id 310
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1989.010230552772
+ y 259.2322753906619
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 311
+ pajek_id 311
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 793.6486929322533
+ y 1180.108345062422
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 312
+ pajek_id 312
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1917.539646877893
+ y 2281.8557999514537
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 313
+ pajek_id 313
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 867.9822424379655
+ y 1709.027298137467
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 314
+ pajek_id 314
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1484.2011650524655
+ y 1345.1479429348788
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 315
+ pajek_id 315
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1076.084829910138
+ y 996.0235144558553
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 316
+ pajek_id 316
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1693.090850412172
+ y 2090.5966253636116
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 317
+ pajek_id 317
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2037.1290633056465
+ y 369.80076511683393
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 318
+ pajek_id 318
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1007.8277192737382
+ y 1754.1325273022699
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 319
+ pajek_id 319
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2172.028629136008
+ y 1461.0364064098994
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 320
+ pajek_id 320
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2257.1227609527
+ y 1310.8862977736107
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 321
+ pajek_id 321
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1300.745991888025
+ y 2187.297908294803
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 322
+ pajek_id 322
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2204.6686322693918
+ y 1410.994870895594
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 323
+ pajek_id 323
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 864.8355633586339
+ y 1982.7204827008345
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 324
+ pajek_id 324
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 800.0003105548103
+ y 1923.7791435231852
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 325
+ pajek_id 325
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1024.7502660900132
+ y 1366.1758015615299
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 326
+ pajek_id 326
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2050.7149391093694
+ y 1257.3982758996383
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 327
+ pajek_id 327
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 960.7821525481202
+ y 1584.4968382633942
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 328
+ pajek_id 328
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1124.4061711877166
+ y 1046.726994002646
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 329
+ pajek_id 329
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1108.4893044148541
+ y 1194.3431578903087
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 330
+ pajek_id 330
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1100.133655193655
+ y 1137.6918022343907
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 331
+ pajek_id 331
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1760.6862781934046
+ y 1320.6513715309195
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 332
+ pajek_id 332
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1200.2523322538245
+ y 1002.7964728390644
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 333
+ pajek_id 333
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1181.4892595539825
+ y 1225.6989123360675
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 334
+ pajek_id 334
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1868.4127438749463
+ y 1117.6967188028786
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 335
+ pajek_id 335
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2168.6794851454647
+ y 1162.2427344452735
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 336
+ pajek_id 336
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1920.9638225147678
+ y 876.5150707247215
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 337
+ pajek_id 337
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2920.808088394186
+ y 892.3685934633982
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 338
+ pajek_id 338
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1645.909927183584
+ y 1471.9956590731072
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 339
+ pajek_id 339
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1447.1109049135396
+ y 1746.1534799232427
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 340
+ pajek_id 340
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1303.087697302223
+ y 1599.75182872408
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 341
+ pajek_id 341
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1404.1964183968635
+ y 1732.988309973422
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 342
+ pajek_id 342
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 188.7586938483705
+ y 732.4710661793797
+ w 20.0
+ h 20.0
+ fill "#FFFF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 343
+ pajek_id 343
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 237.5145668340565
+ y 798.209667685809
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 344
+ pajek_id 344
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 655.6090365411286
+ y 768.8237020380398
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 345
+ pajek_id 345
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1239.593772491194
+ y 142.24994629451373
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 346
+ pajek_id 346
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 668.4582174721975
+ y 1570.710895937615
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 347
+ pajek_id 347
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 704.1732692312117
+ y 1623.8128247520694
+ w 20.0
+ h 20.0
+ fill "#FFFF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 348
+ pajek_id 348
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1806.5024342076917
+ y 1845.9002776470725
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 349
+ pajek_id 349
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1572.0491307665409
+ y 1632.2321415433307
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 350
+ pajek_id 350
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2170.491596866099
+ y 252.15493902189132
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 351
+ pajek_id 351
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2236.6106720779644
+ y 313.9614539100346
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 352
+ pajek_id 352
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1956.787709026074
+ y 478.6286472297293
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 353
+ pajek_id 353
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1521.6247356278914
+ y 651.1377056441239
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 354
+ pajek_id 354
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2673.4749982408534
+ y 1517.3687949519558
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 355
+ pajek_id 355
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2462.8285772682266
+ y 853.132399611773
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 356
+ pajek_id 356
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2723.74809870115
+ y 928.6302426931661
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 357
+ pajek_id 357
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1370.7051182886262
+ y 1487.7369332080375
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 358
+ pajek_id 358
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 468.7736750192556
+ y 1245.6923887724063
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 359
+ pajek_id 359
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 769.1240346507418
+ y 1297.5083732935518
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 360
+ pajek_id 360
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1281.6747231335723
+ y 1222.571355135779
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 361
+ pajek_id 361
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2579.810673602955
+ y 486.0242869026378
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 362
+ pajek_id 362
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1625.153907135859
+ y 1657.7991036276171
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 363
+ pajek_id 363
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1685.4668204197178
+ y 1675.1432793501972
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 364
+ pajek_id 364
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1649.065379741583
+ y 1710.3631889761837
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 365
+ pajek_id 365
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1735.2434575622904
+ y 1652.0103910358575
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 366
+ pajek_id 366
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1546.6380216667462
+ y 1660.4291808801559
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 367
+ pajek_id 367
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1592.959070056042
+ y 1701.930864398132
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 368
+ pajek_id 368
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2000.4352383965368
+ y 1758.4816008564803
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 369
+ pajek_id 369
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1468.5107210693257
+ y 1274.5523522286858
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 370
+ pajek_id 370
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1343.841518355971
+ y 868.6992458482348
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 371
+ pajek_id 371
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 956.4416724575727
+ y 1542.5109738519532
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 372
+ pajek_id 372
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1033.5848153857899
+ y 2047.0346481519837
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 373
+ pajek_id 373
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1145.9845954789732
+ y 2010.3598901708774
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 374
+ pajek_id 374
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 966.9695596108811
+ y 2038.5494954424362
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 375
+ pajek_id 375
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1101.5378289239488
+ y 2056.772094668872
+ w 20.0
+ h 20.0
+ fill "#FFFF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 376
+ pajek_id 376
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1015.5518645355227
+ y 498.21676713384437
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 377
+ pajek_id 377
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1108.5018026732564
+ y 1836.2444968902573
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 378
+ pajek_id 378
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1050.8064474323255
+ y 1820.5838099325315
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 379
+ pajek_id 379
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1022.4653344068506
+ y 1715.6126995231655
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 380
+ pajek_id 380
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 973.3911705488091
+ y 1656.6045446044554
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 381
+ pajek_id 381
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 980.1312729019277
+ y 1790.1875755402975
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 382
+ pajek_id 382
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1165.9502913921285
+ y 1848.0553893620186
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 383
+ pajek_id 383
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1847.4512820966625
+ y 997.8047505299883
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 384
+ pajek_id 384
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1834.8709235195802
+ y 1082.3420824375842
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 385
+ pajek_id 385
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1926.272882956845
+ y 1130.2140856000237
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 386
+ pajek_id 386
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2019.5057069987238
+ y 1083.2924715168538
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 387
+ pajek_id 387
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 340.467937490798
+ y 1722.2588619668122
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 388
+ pajek_id 388
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 613.237652883032
+ y 1579.9427905965279
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 389
+ pajek_id 389
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1655.1932187894404
+ y 1782.2310536598284
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 390
+ pajek_id 390
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1637.2667690847445
+ y 952.3525949687174
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 391
+ pajek_id 391
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2630.804204930251
+ y 2213.7673865428937
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 392
+ pajek_id 392
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1080.8078508715175
+ y 1570.3664421378583
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 393
+ pajek_id 393
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2234.068836486567
+ y 1160.6502978141489
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 394
+ pajek_id 394
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1086.7948765031201
+ y 76.91119774421213
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 395
+ pajek_id 395
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2461.9112093928975
+ y 1766.6838415805391
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 396
+ pajek_id 396
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 113.1199288710568
+ y 369.28510273478156
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 397
+ pajek_id 397
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1776.1814775671203
+ y 1971.90651207382
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 398
+ pajek_id 398
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1707.0558465571435
+ y 1296.0087781780164
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 399
+ pajek_id 399
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1417.7718529314445
+ y 1350.7244506853776
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 400
+ pajek_id 400
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2125.52060844245
+ y 1048.4849048770884
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 401
+ pajek_id 401
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1552.3770468848625
+ y 2260.559438155617
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 402
+ pajek_id 402
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1874.1651337345234
+ y 1245.0945400298474
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 403
+ pajek_id 403
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1256.6383628219503
+ y 1450.7738470869801
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 404
+ pajek_id 404
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2259.967596935999
+ y 2120.7466929344328
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 405
+ pajek_id 405
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2500.5496931980915
+ y 1966.736685021926
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 406
+ pajek_id 406
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2347.7927648395157
+ y 2091.6701739856917
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 407
+ pajek_id 407
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2392.889146581768
+ y 2044.8922015795006
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 408
+ pajek_id 408
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2417.761515347872
+ y 1975.5515523680338
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 409
+ pajek_id 409
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1793.9182626491624
+ y 1627.666690778881
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 410
+ pajek_id 410
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 719.1430254147674
+ y 1486.956454607635
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 411
+ pajek_id 411
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 724.2454716778103
+ y 1551.3831943720716
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 412
+ pajek_id 412
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2447.6879968351877
+ y 1876.5514180960204
+ w 20.0
+ h 20.0
+ fill "#FFFF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 413
+ pajek_id 413
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2091.9643045079483
+ y 1974.8640522416667
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 414
+ pajek_id 414
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2028.15537010984
+ y 1956.056476995101
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 415
+ pajek_id 415
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1984.2252245737018
+ y 1908.623346940285
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 416
+ pajek_id 416
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2119.7472033124163
+ y 1865.6311815257598
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 417
+ pajek_id 417
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2130.68571853772
+ y 1928.6302578749373
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 418
+ pajek_id 418
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2122.510896875806
+ y 1780.9007711280406
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 419
+ pajek_id 419
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2066.857133577992
+ y 1911.002176703526
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 420
+ pajek_id 420
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2174.073650971839
+ y 1808.4465867530826
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 421
+ pajek_id 421
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2173.188445315479
+ y 1879.1912761247552
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 422
+ pajek_id 422
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2445.130066970032
+ y 1152.7800567449078
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 423
+ pajek_id 423
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2355.4692035510784
+ y 1402.5903362442382
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 424
+ pajek_id 424
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2415.2373515095965
+ y 1088.9498827129119
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 425
+ pajek_id 425
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2039.5995058528129
+ y 1430.5751740405808
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 426
+ pajek_id 426
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 322.6815092460105
+ y 2116.2903817807914
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 427
+ pajek_id 427
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 268.5119994462548
+ y 2056.087634484369
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 428
+ pajek_id 428
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1146.757825786496
+ y 364.2656095233129
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 429
+ pajek_id 429
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1489.2719624004453
+ y 693.8971583258162
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 430
+ pajek_id 430
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1827.8677422310066
+ y 766.7899007728367
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 431
+ pajek_id 431
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1798.3747778112622
+ y 1215.8365936661658
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 432
+ pajek_id 432
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 804.3580561584004
+ y 501.9583186324991
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 433
+ pajek_id 433
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 849.2647555481542
+ y 434.2847659573615
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 434
+ pajek_id 434
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2328.3994872753374
+ y 2321.663189777115
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 435
+ pajek_id 435
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 618.9825732416654
+ y 1813.9348120438804
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 436
+ pajek_id 436
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 700.4298252161705
+ y 1333.1902810428091
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 437
+ pajek_id 437
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1395.7113829826137
+ y 1284.9840905117753
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 438
+ pajek_id 438
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2630.3138122865585
+ y 1172.8988923967477
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 439
+ pajek_id 439
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2615.848167339149
+ y 1246.8020908359208
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 440
+ pajek_id 440
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 469.43123730699017
+ y 854.8438020056724
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 441
+ pajek_id 441
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2116.96992696925
+ y 1379.4358280316942
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 442
+ pajek_id 442
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2081.349871481623
+ y 1329.7245666590386
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 443
+ pajek_id 443
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2424.702556920728
+ y 768.839004481539
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 444
+ pajek_id 444
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 890.6313761901736
+ y 115.79231393666316
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 445
+ pajek_id 445
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 857.1356243649586
+ y 174.88311586144653
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 446
+ pajek_id 446
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 512.8629774244184
+ y 2201.527945647691
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 447
+ pajek_id 447
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 677.7488039882435
+ y 1909.537866326766
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 448
+ pajek_id 448
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1338.956871819991
+ y 1010.8829829830978
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 449
+ pajek_id 449
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1324.088243934198
+ y 1729.0798093126218
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 450
+ pajek_id 450
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1724.263819989563
+ y 504.51288018417335
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 451
+ pajek_id 451
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1910.6105654550115
+ y 630.6123921072538
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 452
+ pajek_id 452
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1710.4548801725487
+ y 647.7553354187357
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 453
+ pajek_id 453
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1702.9391298385015
+ y 563.411307161135
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 454
+ pajek_id 454
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1826.116078147204
+ y 450.3392482519506
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 455
+ pajek_id 455
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2011.5270490887758
+ y 760.825852289636
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 456
+ pajek_id 456
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2101.9753242282413
+ y 581.5866515110404
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 457
+ pajek_id 457
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2603.3686351996375
+ y 1409.84659720882
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 458
+ pajek_id 458
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2438.056345618056
+ y 1523.7553993407314
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 459
+ pajek_id 459
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2331.6849268576207
+ y 1134.766411504912
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 460
+ pajek_id 460
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1059.0576214306932
+ y 2264.1041145319637
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 461
+ pajek_id 461
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1458.141237363875
+ y 755.4394205573406
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 462
+ pajek_id 462
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 424.1436855406298
+ y 1477.224543730106
+ w 20.0
+ h 20.0
+ fill "#FFFF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 463
+ pajek_id 463
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 378.7154942468852
+ y 1401.5037756061158
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 464
+ pajek_id 464
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 314.0529479996145
+ y 1373.0410118674613
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 465
+ pajek_id 465
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 353.0119560198315
+ y 1455.904690398989
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 466
+ pajek_id 466
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 834.3766918623855
+ y 1291.1793247114124
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 467
+ pajek_id 467
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 893.5300096467302
+ y 1847.377115763661
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 468
+ pajek_id 468
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 716.2809799836317
+ y 2178.244847004791
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 469
+ pajek_id 469
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2541.4812097684
+ y 2043.553501917624
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 470
+ pajek_id 470
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1119.6037534804425
+ y 1102.2487155380616
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 471
+ pajek_id 471
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1007.8554543482325
+ y 1148.2192014655018
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 472
+ pajek_id 472
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2355.376017232971
+ y 1455.616264520982
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 473
+ pajek_id 473
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2394.6586276164862
+ y 1491.7526626843892
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 474
+ pajek_id 474
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2248.1811205504373
+ y 1647.7634009017388
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 475
+ pajek_id 475
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2337.1166010827837
+ y 1520.6716608448314
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 476
+ pajek_id 476
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2420.759607231811
+ y 1589.229118968443
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 477
+ pajek_id 477
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2314.5533268916042
+ y 1604.0297855841632
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 478
+ pajek_id 478
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2364.2202931300694
+ y 1575.671922904723
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 479
+ pajek_id 479
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2194.5964587031503
+ y 1638.225011658421
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 480
+ pajek_id 480
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1065.4992788010986
+ y 1464.6555423148318
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 481
+ pajek_id 481
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 968.0925172159282
+ y 1354.4290172504502
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 482
+ pajek_id 482
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1126.8845029318243
+ y 1435.5731026238109
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 483
+ pajek_id 483
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1213.8500385478933
+ y 1383.2655755080937
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 484
+ pajek_id 484
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1391.466199058675
+ y 2589.0242705868145
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 485
+ pajek_id 485
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1324.9339892036385
+ y 2618.7726752706
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 486
+ pajek_id 486
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1447.1572287025065
+ y 927.5802766521502
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 487
+ pajek_id 487
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2147.787079263979
+ y 2593.4264109946484
+ w 20.0
+ h 20.0
+ fill "#FFFF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 488
+ pajek_id 488
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2020.4864930201384
+ y 2667.000204943657
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 489
+ pajek_id 489
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2455.283559589994
+ y 2086.657483037342
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 490
+ pajek_id 490
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1682.851876497575
+ y 1583.6120931079872
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 491
+ pajek_id 491
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1161.1187083008704
+ y 1611.7393863381692
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 492
+ pajek_id 492
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1041.2626018954427
+ y 1598.954971993218
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 493
+ pajek_id 493
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2297.354570397635
+ y 534.3652679637769
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 494
+ pajek_id 494
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 526.5370388426392
+ y 485.54459385039985
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 495
+ pajek_id 495
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 560.2941765427282
+ y 402.56083072436417
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 496
+ pajek_id 496
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 377.08394387788996
+ y 1333.3317088869094
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 497
+ pajek_id 497
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 489.3047686961877
+ y 1939.8674034964001
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 498
+ pajek_id 498
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 527.233322511409
+ y 2017.0516767470162
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 499
+ pajek_id 499
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1605.5668452162006
+ y 1992.166283565707
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 500
+ pajek_id 500
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1546.0840293799524
+ y 1955.4015275314973
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 501
+ pajek_id 501
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2656.759269426316
+ y 1685.5061982513696
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 502
+ pajek_id 502
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1728.2354096255438
+ y 1051.4437767810607
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 503
+ pajek_id 503
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 317.98253615853616
+ y 835.2488823603016
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 504
+ pajek_id 504
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1227.6068253899532
+ y 1819.6331253463359
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 505
+ pajek_id 505
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1574.3747014862265
+ y 289.21933118032086
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 506
+ pajek_id 506
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1436.7167412577667
+ y 2136.3809474284844
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 507
+ pajek_id 507
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1928.2290848617536
+ y 1695.8756254197222
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 508
+ pajek_id 508
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2229.8166656736694
+ y 1842.5176093374575
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 509
+ pajek_id 509
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2191.4931676161536
+ y 1969.3723460631686
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 510
+ pajek_id 510
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2404.7934790895088
+ y 917.1422166878989
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 511
+ pajek_id 511
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2395.2429436891007
+ y 834.027810518057
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 512
+ pajek_id 512
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1638.416583359785
+ y 1075.9248111470263
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 513
+ pajek_id 513
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1117.2425662770952
+ y 945.1325831390579
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 514
+ pajek_id 514
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1071.8339051492999
+ y 667.2084929230319
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 515
+ pajek_id 515
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2080.1550476846883
+ y 2248.7722822540536
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 516
+ pajek_id 516
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 941.7035591125789
+ y 2315.12355349285
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 517
+ pajek_id 517
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 864.0401900606075
+ y 854.7476458360196
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 518
+ pajek_id 518
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1451.1619559522182
+ y 1947.3205327227465
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 519
+ pajek_id 519
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1481.5993172162407
+ y 1688.7490679204407
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 520
+ pajek_id 520
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 132.29183753554184
+ y 1549.9709751408773
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 521
+ pajek_id 521
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 201.92596700389458
+ y 1601.853692109065
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 522
+ pajek_id 522
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2153.1192264901847
+ y 822.9210553334786
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 523
+ pajek_id 523
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 640.2772506993291
+ y 1675.9420021748028
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 524
+ pajek_id 524
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1320.8511741047305
+ y 408.77871976114494
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 525
+ pajek_id 525
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2213.924926553872
+ y 2763.501088516637
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 526
+ pajek_id 526
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2074.4442713188187
+ y 2170.28081217305
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 527
+ pajek_id 527
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1907.281150461828
+ y 1756.8956641399836
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 528
+ pajek_id 528
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2125.030039415664
+ y 2128.3283642176266
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 529
+ pajek_id 529
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1748.248950250427
+ y 1911.7557662270228
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 530
+ pajek_id 530
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1150.8356799670266
+ y 1544.1121345992892
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 531
+ pajek_id 531
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1477.1689178603895
+ y 1147.0096180737971
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 532
+ pajek_id 532
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1458.9597650345672
+ y 1060.9858986563445
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 533
+ pajek_id 533
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1495.8280010142782
+ y 989.2245050486312
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 534
+ pajek_id 534
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 784.4777027529236
+ y 948.7566853266054
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 535
+ pajek_id 535
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2110.665526987148
+ y 1497.723078348779
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 536
+ pajek_id 536
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 3038.33263338064
+ y 1192.8113918381189
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 537
+ pajek_id 537
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1603.7304792610369
+ y 454.1950074099879
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 538
+ pajek_id 538
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1801.2035133048555
+ y 2119.4411185171184
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 539
+ pajek_id 539
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1950.4501795255455
+ y 2049.3079413070072
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 540
+ pajek_id 540
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1757.897607156828
+ y 2049.7669278996045
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 541
+ pajek_id 541
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1854.7360726993138
+ y 1393.7369312635797
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 542
+ pajek_id 542
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1415.8484373759234
+ y 1900.9653905466644
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 543
+ pajek_id 543
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1497.5005911357582
+ y 2480.683702039123
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 544
+ pajek_id 544
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 719.9288183455253
+ y 236.78163159716667
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 545
+ pajek_id 545
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2509.6237885742785
+ y 2373.522488677848
+ w 20.0
+ h 20.0
+ fill "#FF3333"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 546
+ pajek_id 546
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2436.169862983399
+ y 2416.0522801899683
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 547
+ pajek_id 547
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 647.1888372458554
+ y 1741.9224475898036
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 548
+ pajek_id 548
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 681.8502532202343
+ y 1799.6304470782582
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 549
+ pajek_id 549
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1985.5267000858494
+ y 2369.7344325668428
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 550
+ pajek_id 550
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1991.106100021963
+ y 2440.329057425812
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 551
+ pajek_id 551
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1931.1619344063192
+ y 2470.578249185151
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 552
+ pajek_id 552
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1875.3109201344084
+ y 2408.7968384052087
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 553
+ pajek_id 553
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1587.9274187718331
+ y 1318.0146867000844
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 554
+ pajek_id 554
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 930.2559142741628
+ y 1891.3731392078669
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 555
+ pajek_id 555
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1227.5755919224916
+ y 2306.541693351298
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 556
+ pajek_id 556
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1304.4750058932211
+ y 2321.289347146842
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 557
+ pajek_id 557
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 2217.1358311583554
+ y 1273.7535975697697
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ node [
+ id 558
+ pajek_id 558
+ label ""
+ labelgraphics [
+ anchor "c"
+ fontName "Tahoma"
+ alignment "left"
+ fontSize 13
+ fontStyle "plain"
+ color "#000000"
+ type "text"
+ ]
+ graphics [
+ x 1066.387215640596
+ y 1714.3761855178568
+ w 20.0
+ h 20.0
+ fill "#00FF00"
+ outline "#000000"
+ frameThickness 3.0
+ rounding 5.0
+ gradient 0.0
+ type "oval"
+ ]
+ ]
+ edge [
+ id 1
+ source 1
+ target 87
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 2
+ source 1
+ target 223
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 3
+ source 1
+ target 266
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 4
+ source 1
+ target 328
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 5
+ source 1
+ target 329
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 6
+ source 1
+ target 330
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 7
+ source 1
+ target 331
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 8
+ source 1
+ target 332
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 9
+ source 1
+ target 333
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 10
+ source 2
+ target 334
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 11
+ source 2
+ target 335
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 12
+ source 3
+ target 172
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 13
+ source 3
+ target 188
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 14
+ source 3
+ target 257
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 15
+ source 4
+ target 225
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 16
+ source 5
+ target 175
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 17
+ source 6
+ target 143
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 18
+ source 7
+ target 118
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 19
+ source 7
+ target 284
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 20
+ source 7
+ target 336
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 21
+ source 8
+ target 30
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 22
+ source 8
+ target 337
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 23
+ source 9
+ target 338
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 24
+ source 10
+ target 198
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 25
+ source 11
+ target 261
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 26
+ source 12
+ target 66
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 27
+ source 12
+ target 114
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 28
+ source 12
+ target 144
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 29
+ source 12
+ target 189
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 30
+ source 12
+ target 237
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 31
+ source 12
+ target 239
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 32
+ source 12
+ target 267
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 33
+ source 12
+ target 268
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 34
+ source 12
+ target 339
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 35
+ source 12
+ target 340
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 36
+ source 12
+ target 341
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 37
+ source 13
+ target 15
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 38
+ source 13
+ target 85
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 39
+ source 14
+ target 212
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 40
+ source 15
+ target 342
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 41
+ source 15
+ target 343
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 42
+ source 15
+ target 344
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 43
+ source 16
+ target 143
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 44
+ source 16
+ target 191
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 45
+ source 17
+ target 54
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 46
+ source 17
+ target 345
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 47
+ source 18
+ target 100
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 48
+ source 18
+ target 346
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 49
+ source 18
+ target 347
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 50
+ source 19
+ target 267
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 51
+ source 20
+ target 348
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 52
+ source 20
+ target 349
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 53
+ source 21
+ target 81
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 54
+ source 22
+ target 65
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 55
+ source 23
+ target 140
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 56
+ source 23
+ target 350
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 57
+ source 23
+ target 351
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 58
+ source 23
+ target 352
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 59
+ source 24
+ target 217
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 60
+ source 25
+ target 284
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 61
+ source 26
+ target 119
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 62
+ source 26
+ target 353
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 63
+ source 27
+ target 353
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 64
+ source 28
+ target 178
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 65
+ source 29
+ target 148
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 66
+ source 29
+ target 175
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 67
+ source 29
+ target 206
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 68
+ source 29
+ target 354
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 69
+ source 30
+ target 212
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 70
+ source 30
+ target 294
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 71
+ source 30
+ target 355
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 72
+ source 30
+ target 356
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 73
+ source 31
+ target 334
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 74
+ source 32
+ target 353
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 75
+ source 33
+ target 312
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 76
+ source 34
+ target 217
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 77
+ source 34
+ target 220
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 78
+ source 34
+ target 262
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 79
+ source 34
+ target 357
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 80
+ source 35
+ target 358
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 81
+ source 35
+ target 359
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 82
+ source 36
+ target 342
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 83
+ source 37
+ target 162
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 84
+ source 38
+ target 311
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 85
+ source 39
+ target 174
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 86
+ source 40
+ target 228
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 87
+ source 41
+ target 311
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 88
+ source 42
+ target 53
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 89
+ source 43
+ target 265
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 90
+ source 43
+ target 360
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 91
+ source 44
+ target 361
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 92
+ source 45
+ target 53
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 93
+ source 46
+ target 118
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 94
+ source 46
+ target 285
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 95
+ source 46
+ target 362
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 96
+ source 46
+ target 363
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 97
+ source 46
+ target 364
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 98
+ source 46
+ target 365
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 99
+ source 46
+ target 366
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 100
+ source 46
+ target 367
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 101
+ source 46
+ target 368
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 102
+ source 46
+ target 369
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 103
+ source 47
+ target 78
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 104
+ source 48
+ target 284
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 105
+ source 49
+ target 167
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 106
+ source 49
+ target 370
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 107
+ source 50
+ target 371
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 108
+ source 51
+ target 155
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 109
+ source 51
+ target 233
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 110
+ source 51
+ target 325
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 111
+ source 51
+ target 372
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 112
+ source 51
+ target 373
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 113
+ source 51
+ target 374
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 114
+ source 51
+ target 375
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 115
+ source 52
+ target 126
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 116
+ source 52
+ target 376
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 117
+ source 53
+ target 62
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 118
+ source 53
+ target 66
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 119
+ source 53
+ target 371
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 120
+ source 53
+ target 377
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 121
+ source 53
+ target 378
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 122
+ source 53
+ target 379
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 123
+ source 53
+ target 380
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 124
+ source 53
+ target 381
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 125
+ source 53
+ target 382
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 126
+ source 54
+ target 126
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 127
+ source 54
+ target 138
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 128
+ source 55
+ target 143
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 129
+ source 56
+ target 147
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 130
+ source 56
+ target 383
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 131
+ source 56
+ target 384
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 132
+ source 56
+ target 385
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 133
+ source 56
+ target 386
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 134
+ source 57
+ target 283
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 135
+ source 58
+ target 210
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 136
+ source 59
+ target 387
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 137
+ source 59
+ target 388
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 138
+ source 60
+ target 189
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 139
+ source 61
+ target 93
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 140
+ source 61
+ target 326
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 141
+ source 62
+ target 110
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 142
+ source 62
+ target 265
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 143
+ source 62
+ target 278
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 144
+ source 62
+ target 338
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 145
+ source 62
+ target 389
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 146
+ source 63
+ target 215
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 147
+ source 64
+ target 97
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 148
+ source 64
+ target 99
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 149
+ source 65
+ target 158
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 150
+ source 65
+ target 222
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 151
+ source 65
+ target 297
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 152
+ source 65
+ target 390
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 153
+ source 66
+ target 127
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 154
+ source 66
+ target 340
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 155
+ source 67
+ target 181
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 156
+ source 68
+ target 326
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 157
+ source 69
+ target 185
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 158
+ source 69
+ target 391
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 159
+ source 70
+ target 162
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 160
+ source 71
+ target 327
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 161
+ source 71
+ target 392
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 162
+ source 72
+ target 286
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 163
+ source 73
+ target 113
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 164
+ source 74
+ target 312
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 165
+ source 75
+ target 247
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 166
+ source 75
+ target 284
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 167
+ source 75
+ target 302
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 168
+ source 75
+ target 326
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 169
+ source 76
+ target 85
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 170
+ source 77
+ target 87
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 171
+ source 78
+ target 393
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 172
+ source 79
+ target 315
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 173
+ source 80
+ target 147
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 174
+ source 81
+ target 117
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 175
+ source 81
+ target 394
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 176
+ source 82
+ target 138
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 177
+ source 83
+ target 194
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 178
+ source 83
+ target 235
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 179
+ source 84
+ target 171
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 180
+ source 84
+ target 395
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 181
+ source 85
+ target 396
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 182
+ source 86
+ target 209
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 183
+ source 87
+ target 118
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 184
+ source 87
+ target 145
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 185
+ source 87
+ target 284
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 186
+ source 87
+ target 369
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 187
+ source 88
+ target 318
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 188
+ source 89
+ target 397
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 189
+ source 90
+ target 143
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 190
+ source 91
+ target 215
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 191
+ source 92
+ target 110
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 192
+ source 93
+ target 111
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 193
+ source 94
+ target 126
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 194
+ source 94
+ target 302
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 195
+ source 95
+ target 392
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 196
+ source 95
+ target 398
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 197
+ source 95
+ target 399
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 198
+ source 96
+ target 111
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 199
+ source 96
+ target 284
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 200
+ source 96
+ target 398
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 201
+ source 96
+ target 400
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 202
+ source 97
+ target 286
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 203
+ source 97
+ target 401
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 204
+ source 98
+ target 143
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 205
+ source 99
+ target 204
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 206
+ source 99
+ target 222
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 207
+ source 99
+ target 402
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 208
+ source 100
+ target 129
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 209
+ source 100
+ target 227
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 210
+ source 100
+ target 340
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 211
+ source 100
+ target 403
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 212
+ source 101
+ target 318
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 213
+ source 101
+ target 325
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 214
+ source 102
+ target 227
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 215
+ source 103
+ target 121
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 216
+ source 103
+ target 280
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 217
+ source 103
+ target 404
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 218
+ source 103
+ target 405
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 219
+ source 103
+ target 406
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 220
+ source 103
+ target 407
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 221
+ source 103
+ target 408
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 222
+ source 104
+ target 117
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 223
+ source 105
+ target 156
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 224
+ source 106
+ target 188
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 225
+ source 106
+ target 252
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 226
+ source 106
+ target 257
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 227
+ source 106
+ target 318
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 228
+ source 107
+ target 409
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 229
+ source 108
+ target 267
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 230
+ source 108
+ target 388
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 231
+ source 108
+ target 410
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 232
+ source 108
+ target 411
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 233
+ source 109
+ target 220
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 234
+ source 109
+ target 412
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 235
+ source 110
+ target 217
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 236
+ source 110
+ target 278
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 237
+ source 110
+ target 289
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 238
+ source 110
+ target 413
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 239
+ source 110
+ target 414
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 240
+ source 110
+ target 415
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 241
+ source 110
+ target 416
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 242
+ source 110
+ target 417
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 243
+ source 110
+ target 418
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 244
+ source 110
+ target 419
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 245
+ source 110
+ target 420
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 246
+ source 110
+ target 421
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 247
+ source 111
+ target 422
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 248
+ source 111
+ target 423
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 249
+ source 111
+ target 424
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 250
+ source 112
+ target 425
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 251
+ source 113
+ target 202
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 252
+ source 113
+ target 426
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 253
+ source 113
+ target 427
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 254
+ source 114
+ target 142
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 255
+ source 114
+ target 239
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 256
+ source 115
+ target 275
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 257
+ source 116
+ target 352
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 258
+ source 117
+ target 253
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 259
+ source 117
+ target 428
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 260
+ source 117
+ target 429
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 261
+ source 118
+ target 143
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 262
+ source 118
+ target 212
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 263
+ source 118
+ target 276
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 264
+ source 118
+ target 352
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 265
+ source 118
+ target 353
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 266
+ source 118
+ target 429
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 267
+ source 118
+ target 430
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 268
+ source 118
+ target 431
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 269
+ source 119
+ target 256
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 270
+ source 119
+ target 432
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 271
+ source 119
+ target 433
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 272
+ source 120
+ target 147
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 273
+ source 121
+ target 434
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 274
+ source 122
+ target 202
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 275
+ source 122
+ target 392
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 276
+ source 122
+ target 435
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 277
+ source 123
+ target 129
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 278
+ source 123
+ target 436
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 279
+ source 123
+ target 437
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 280
+ source 124
+ target 393
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 281
+ source 124
+ target 438
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 282
+ source 124
+ target 439
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 283
+ source 125
+ target 258
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 284
+ source 126
+ target 235
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 285
+ source 127
+ target 141
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 286
+ source 127
+ target 217
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 287
+ source 127
+ target 239
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 288
+ source 127
+ target 284
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 289
+ source 127
+ target 309
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 290
+ source 128
+ target 440
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 291
+ source 129
+ target 162
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 292
+ source 130
+ target 263
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 293
+ source 130
+ target 320
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 294
+ source 130
+ target 441
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 295
+ source 130
+ target 442
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 296
+ source 131
+ target 429
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 297
+ source 132
+ target 302
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 298
+ source 133
+ target 138
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 299
+ source 134
+ target 310
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 300
+ source 135
+ target 234
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 301
+ source 135
+ target 326
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 302
+ source 135
+ target 443
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 303
+ source 136
+ target 312
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 304
+ source 137
+ target 210
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 305
+ source 137
+ target 311
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 306
+ source 138
+ target 300
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 307
+ source 138
+ target 444
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 308
+ source 138
+ target 445
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 309
+ source 139
+ target 446
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 310
+ source 139
+ target 447
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 311
+ source 140
+ target 147
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 312
+ source 141
+ target 227
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 313
+ source 141
+ target 448
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 314
+ source 142
+ target 237
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 315
+ source 142
+ target 239
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 316
+ source 142
+ target 267
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 317
+ source 142
+ target 321
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 318
+ source 142
+ target 339
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 319
+ source 142
+ target 340
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 320
+ source 142
+ target 341
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 321
+ source 142
+ target 449
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 322
+ source 143
+ target 228
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 323
+ source 143
+ target 450
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 324
+ source 143
+ target 451
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 325
+ source 143
+ target 452
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 326
+ source 143
+ target 453
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 327
+ source 143
+ target 454
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 328
+ source 144
+ target 239
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 329
+ source 145
+ target 174
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 330
+ source 146
+ target 220
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 331
+ source 146
+ target 284
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 332
+ source 147
+ target 455
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 333
+ source 147
+ target 456
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 334
+ source 148
+ target 320
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 335
+ source 148
+ target 457
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 336
+ source 148
+ target 458
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 337
+ source 149
+ target 314
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 338
+ source 150
+ target 305
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 339
+ source 151
+ target 291
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 340
+ source 151
+ target 459
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 341
+ source 152
+ target 312
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 342
+ source 153
+ target 188
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 343
+ source 153
+ target 448
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 344
+ source 154
+ target 315
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 345
+ source 155
+ target 460
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 346
+ source 156
+ target 246
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 347
+ source 157
+ target 461
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 348
+ source 158
+ target 461
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 349
+ source 159
+ target 349
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 350
+ source 160
+ target 175
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 351
+ source 161
+ target 357
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 352
+ source 161
+ target 359
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 353
+ source 162
+ target 436
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 354
+ source 162
+ target 462
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 355
+ source 162
+ target 463
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 356
+ source 162
+ target 464
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 357
+ source 162
+ target 465
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 358
+ source 163
+ target 227
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 359
+ source 164
+ target 262
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 360
+ source 164
+ target 359
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 361
+ source 164
+ target 466
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 362
+ source 165
+ target 326
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 363
+ source 166
+ target 467
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 364
+ source 167
+ target 325
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 365
+ source 168
+ target 467
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 366
+ source 168
+ target 468
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 367
+ source 169
+ target 180
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 368
+ source 170
+ target 469
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 369
+ source 171
+ target 175
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 370
+ source 171
+ target 206
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 371
+ source 171
+ target 395
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 372
+ source 172
+ target 187
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 373
+ source 173
+ target 470
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 374
+ source 174
+ target 266
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 375
+ source 174
+ target 369
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 376
+ source 174
+ target 471
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 377
+ source 175
+ target 280
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 378
+ source 175
+ target 331
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 379
+ source 175
+ target 458
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 380
+ source 175
+ target 472
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 381
+ source 175
+ target 473
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 382
+ source 175
+ target 474
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 383
+ source 175
+ target 475
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 384
+ source 175
+ target 476
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 385
+ source 175
+ target 477
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 386
+ source 175
+ target 478
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 387
+ source 175
+ target 479
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 388
+ source 176
+ target 326
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 389
+ source 177
+ target 312
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 390
+ source 178
+ target 225
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 391
+ source 178
+ target 227
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 392
+ source 178
+ target 296
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 393
+ source 178
+ target 480
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 394
+ source 178
+ target 481
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 395
+ source 178
+ target 482
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 396
+ source 178
+ target 483
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 397
+ source 179
+ target 315
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 398
+ source 180
+ target 321
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 399
+ source 180
+ target 484
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 400
+ source 180
+ target 485
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 401
+ source 181
+ target 222
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 402
+ source 181
+ target 225
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 403
+ source 181
+ target 227
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 404
+ source 181
+ target 486
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 405
+ source 182
+ target 255
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 406
+ source 182
+ target 312
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 407
+ source 182
+ target 487
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 408
+ source 182
+ target 488
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 409
+ source 183
+ target 315
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 410
+ source 184
+ target 387
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 411
+ source 185
+ target 306
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 412
+ source 185
+ target 368
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 413
+ source 185
+ target 469
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 414
+ source 185
+ target 489
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 415
+ source 186
+ target 315
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 416
+ source 187
+ target 302
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 417
+ source 187
+ target 357
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 418
+ source 187
+ target 490
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 419
+ source 188
+ target 280
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 420
+ source 188
+ target 467
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 421
+ source 188
+ target 470
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 422
+ source 188
+ target 491
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 423
+ source 188
+ target 492
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 424
+ source 189
+ target 239
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 425
+ source 189
+ target 334
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 426
+ source 190
+ target 266
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 427
+ source 191
+ target 493
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 428
+ source 192
+ target 470
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 429
+ source 193
+ target 198
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 430
+ source 193
+ target 440
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 431
+ source 194
+ target 494
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 432
+ source 194
+ target 495
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 433
+ source 195
+ target 312
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 434
+ source 196
+ target 259
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 435
+ source 197
+ target 325
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 436
+ source 198
+ target 359
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 437
+ source 198
+ target 496
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 438
+ source 199
+ target 352
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 439
+ source 200
+ target 284
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 440
+ source 201
+ target 243
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 441
+ source 202
+ target 467
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 442
+ source 202
+ target 497
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 443
+ source 202
+ target 498
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 444
+ source 203
+ target 278
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 445
+ source 204
+ target 216
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 446
+ source 204
+ target 259
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 447
+ source 204
+ target 499
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 448
+ source 204
+ target 500
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 449
+ source 205
+ target 492
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 450
+ source 206
+ target 458
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 451
+ source 206
+ target 476
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 452
+ source 206
+ target 501
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 453
+ source 207
+ target 278
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 454
+ source 208
+ target 470
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 455
+ source 209
+ target 502
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 456
+ source 210
+ target 503
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 457
+ source 211
+ target 296
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 458
+ source 211
+ target 403
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 459
+ source 211
+ target 504
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 460
+ source 212
+ target 355
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 461
+ source 213
+ target 280
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 462
+ source 214
+ target 284
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 463
+ source 215
+ target 429
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 464
+ source 215
+ target 505
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 465
+ source 216
+ target 506
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 466
+ source 217
+ target 231
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 467
+ source 217
+ target 245
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 468
+ source 217
+ target 507
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 469
+ source 218
+ target 326
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 470
+ source 219
+ target 243
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 471
+ source 219
+ target 276
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 472
+ source 220
+ target 258
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 473
+ source 220
+ target 306
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 474
+ source 220
+ target 508
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 475
+ source 220
+ target 509
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 476
+ source 221
+ target 276
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 477
+ source 221
+ target 510
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 478
+ source 221
+ target 511
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 479
+ source 222
+ target 502
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 480
+ source 222
+ target 512
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 481
+ source 223
+ target 265
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 482
+ source 224
+ target 302
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 483
+ source 225
+ target 315
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 484
+ source 225
+ target 513
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 485
+ source 226
+ target 266
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 486
+ source 226
+ target 514
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 487
+ source 227
+ target 315
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 488
+ source 227
+ target 437
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 489
+ source 228
+ target 265
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 490
+ source 229
+ target 258
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 491
+ source 229
+ target 278
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 492
+ source 229
+ target 515
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 493
+ source 230
+ target 293
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 494
+ source 231
+ target 284
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 495
+ source 232
+ target 516
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 496
+ source 233
+ target 516
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 497
+ source 234
+ target 361
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 498
+ source 235
+ target 325
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 499
+ source 235
+ target 517
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 500
+ source 236
+ target 495
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 501
+ source 237
+ target 518
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 502
+ source 238
+ target 502
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 503
+ source 239
+ target 267
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 504
+ source 239
+ target 339
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 505
+ source 239
+ target 340
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 506
+ source 239
+ target 341
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 507
+ source 239
+ target 349
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 508
+ source 239
+ target 449
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 509
+ source 239
+ target 519
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 510
+ source 240
+ target 315
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 511
+ source 241
+ target 284
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 512
+ source 242
+ target 496
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 513
+ source 242
+ target 520
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 514
+ source 242
+ target 521
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 515
+ source 243
+ target 402
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 516
+ source 243
+ target 522
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 517
+ source 244
+ target 354
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 518
+ source 245
+ target 284
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 519
+ source 246
+ target 312
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 520
+ source 247
+ target 284
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 521
+ source 247
+ target 302
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 522
+ source 247
+ target 312
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 523
+ source 247
+ target 326
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 524
+ source 248
+ target 284
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 525
+ source 249
+ target 315
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 526
+ source 250
+ target 397
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 527
+ source 251
+ target 266
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 528
+ source 252
+ target 523
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 529
+ source 253
+ target 307
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 530
+ source 253
+ target 524
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 531
+ source 254
+ target 308
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 532
+ source 255
+ target 525
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 533
+ source 256
+ target 344
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 534
+ source 257
+ target 318
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 535
+ source 258
+ target 312
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 536
+ source 258
+ target 526
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 537
+ source 258
+ target 527
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 538
+ source 258
+ target 528
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 539
+ source 259
+ target 302
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 540
+ source 259
+ target 397
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 541
+ source 259
+ target 529
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 542
+ source 260
+ target 311
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 543
+ source 261
+ target 405
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 544
+ source 262
+ target 301
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 545
+ source 262
+ target 392
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 546
+ source 262
+ target 530
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 547
+ source 263
+ target 265
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 548
+ source 264
+ target 289
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 549
+ source 265
+ target 429
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 550
+ source 265
+ target 531
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 551
+ source 265
+ target 532
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 552
+ source 265
+ target 533
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 553
+ source 266
+ target 344
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 554
+ source 266
+ target 534
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 555
+ source 267
+ target 340
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 556
+ source 268
+ target 425
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 557
+ source 269
+ target 284
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 558
+ source 269
+ target 535
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 559
+ source 270
+ target 294
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 560
+ source 270
+ target 536
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 561
+ source 271
+ target 461
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 562
+ source 271
+ target 537
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 563
+ source 272
+ target 361
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 564
+ source 273
+ target 312
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 565
+ source 274
+ target 325
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 566
+ source 274
+ target 403
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 567
+ source 275
+ target 467
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 568
+ source 276
+ target 334
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 569
+ source 277
+ target 431
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 570
+ source 278
+ target 287
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 571
+ source 278
+ target 538
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 572
+ source 278
+ target 539
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 573
+ source 278
+ target 540
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 574
+ source 279
+ target 429
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 575
+ source 279
+ target 514
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 576
+ source 280
+ target 284
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 577
+ source 281
+ target 306
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 578
+ source 282
+ target 312
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 579
+ source 283
+ target 448
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 580
+ source 284
+ target 393
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 581
+ source 284
+ target 425
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 582
+ source 284
+ target 431
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 583
+ source 284
+ target 437
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 584
+ source 284
+ target 442
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 585
+ source 284
+ target 459
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 586
+ source 284
+ target 541
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 587
+ source 285
+ target 542
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 588
+ source 286
+ target 543
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 589
+ source 287
+ target 302
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 590
+ source 288
+ target 310
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 591
+ source 289
+ target 423
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 592
+ source 290
+ target 291
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 593
+ source 290
+ target 459
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 594
+ source 291
+ target 305
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 595
+ source 292
+ target 437
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 596
+ source 293
+ target 448
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 597
+ source 294
+ target 356
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 598
+ source 295
+ target 311
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 599
+ source 296
+ target 467
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 600
+ source 297
+ target 527
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 601
+ source 298
+ target 312
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 602
+ source 299
+ target 361
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 603
+ source 300
+ target 544
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 604
+ source 301
+ target 311
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 605
+ source 302
+ target 409
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 606
+ source 302
+ target 431
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 607
+ source 302
+ target 541
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 608
+ source 303
+ target 306
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 609
+ source 303
+ target 545
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 610
+ source 303
+ target 546
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 611
+ source 304
+ target 397
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 612
+ source 305
+ target 459
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 613
+ source 306
+ target 509
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 614
+ source 307
+ target 461
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 615
+ source 307
+ target 470
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 616
+ source 308
+ target 325
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 617
+ source 308
+ target 447
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 618
+ source 308
+ target 547
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 619
+ source 308
+ target 548
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 620
+ source 309
+ target 340
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 621
+ source 310
+ target 352
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 622
+ source 311
+ target 325
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 623
+ source 312
+ target 549
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 624
+ source 312
+ target 550
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 625
+ source 312
+ target 551
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 626
+ source 312
+ target 552
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 627
+ source 313
+ target 327
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 628
+ source 314
+ target 325
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 629
+ source 314
+ target 326
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 630
+ source 314
+ target 403
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 631
+ source 314
+ target 553
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 632
+ source 315
+ target 325
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 633
+ source 316
+ target 397
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 634
+ source 317
+ target 352
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 635
+ source 318
+ target 492
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 636
+ source 318
+ target 554
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 637
+ source 319
+ target 425
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 638
+ source 320
+ target 335
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 639
+ source 321
+ target 555
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 640
+ source 321
+ target 556
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 641
+ source 322
+ target 425
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 642
+ source 323
+ target 467
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 643
+ source 324
+ target 467
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 644
+ source 325
+ target 327
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 645
+ source 326
+ target 557
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+ edge [
+ id 646
+ source 327
+ target 558
+ pajek [
+ dir 0.0
+ weight 1.0
+ ]
+ graphics [
+ fill "#000000"
+ outline "#000000"
+ frameThickness 1.0
+ rounding 5.0
+ gradient 0.0
+ arrow "none"
+ thickness 1.0
+ ]
+ ]
+]
diff --git a/src/3rdparty/adaptagrams/libcola/tests/gml_graph.cpp b/src/3rdparty/adaptagrams/libcola/tests/gml_graph.cpp
new file mode 100644
index 0000000..6a280cf
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/gml_graph.cpp
@@ -0,0 +1,257 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <boost/regex.hpp>
+#include "graphlayouttest.h"
+
+using namespace std;
+using namespace cola;
+
+typedef map<unsigned,unsigned> NodeIdMap;
+typedef map<string,list<unsigned> > Partitions;
+
+Edge readEdge(ifstream &f) {
+ string l;
+ int indent=1;
+ unsigned source, target;
+ boost::regex sourceRE(".*source\\s+(\\d+).*");
+ boost::regex targetRE(".*target\\s+(\\d+).*");
+ boost::smatch matches;
+ while(!getline(f,l).eof()) {
+ if(boost::regex_match(l,matches,sourceRE)) {
+ std::istringstream i(matches[1]);
+ i>>source;
+ }
+ if(boost::regex_match(l,matches,targetRE)) {
+ std::istringstream i(matches[1]);
+ i>>target;
+ }
+ if(l.find("[")!=string::npos) {
+ indent++;
+ }
+ if(l.find("]")!=string::npos) {
+ indent--;
+ if(indent==0) {
+ return make_pair(source,target);
+ }
+ }
+ }
+ cerr << "Incomplete edge definition!" << endl;
+ return make_pair(0,0);
+}
+
+unsigned readNode(ifstream &f, NodeIdMap &nodeIdMap,
+ Partitions &partitions) {
+ static unsigned nodeCtr=0;
+ int indent=1;
+ string l;
+ boost::regex idRE("\\s*id\\s+(\\d+).*");
+ boost::regex fillRE(".*fill\\s+\"#(.+)\".*");
+ boost::smatch matches;
+ unsigned id;
+ while(!getline(f,l).eof()) {
+ if(boost::regex_match(l,matches,idRE)) {
+ std::istringstream i(matches[1]);
+ i>>id;
+ nodeIdMap[id]=nodeCtr++;
+ }
+ if(boost::regex_match(l,matches,fillRE)) {
+ string partition(matches[1]);
+ Partitions::iterator i=partitions.find(partition);
+ partitions[partition].push_back(nodeIdMap[id]);
+ }
+ if(l.find("[")!=string::npos) {
+ indent++;
+ }
+ if(l.find("]")!=string::npos) {
+ indent--;
+ if(indent==0) {
+ return nodeCtr;
+ }
+ }
+ }
+ cerr << "Incomplete node definition!" << endl;
+ return 0;
+}
+
+struct PostIteration : TestConvergence {
+ PostIteration(vector<vpsc::Rectangle*> &rs, vector<list<unsigned> > &ps, vector<double> &bs, const double d,const unsigned i) : TestConvergence(d,i), rs(rs), ps(ps), bs(bs) {}
+ bool operator()(const double new_stress, valarray<double> & X, valarray<double> & Y) {
+ static int iterations=0;
+ unsigned n=X.size();
+ double centreX=0,centreY=0;
+ for(unsigned i=0;i<n;i++) {
+ centreX+=X[i];
+ centreY+=Y[i];
+ }
+ centreX/=(double)n;
+ centreY/=(double)n;
+ //printf("centre=(%f,%f)\n",centreX,centreY);
+ for(unsigned i=0;i<ps.size();i++) {
+ for(list<unsigned>::iterator v=ps[i].begin();v!=ps[i].end();v++) {
+ double dx=X[*v]-centreX, dy=Y[*v]-centreY;
+ double l=sqrt(dx*dx+dy*dy);
+ if(i>0) {
+ double r=bs[i-1]+10;
+ if(l<r) {
+ double dx1=dx*(r/l), dy1=dy*(r/l);
+ X[*v]=centreX+dx1;
+ Y[*v]=centreY+dy1;
+ }
+ }
+ if(i<ps.size()-1) {
+ double r=bs[i]-10;
+ if(l>r) {
+ double dx1=dx*(r/l), dy1=dy*(r/l);
+ X[*v]=centreX+dx1;
+ Y[*v]=centreY+dy1;
+ }
+ }
+ }
+ }
+ for(unsigned i=0;i<rs.size();i++) {
+ rs[i]->moveCentre(X[i],Y[i]);
+ }
+ cout << iterations++ << ":stress="<<new_stress<<endl;
+ return TestConvergence::operator()(new_stress,X,Y);
+ }
+ vector<vpsc::Rectangle*> &rs;
+ vector<list<unsigned> > &ps;
+ vector<double> &bs;
+};
+int main() {
+ //const char *fname="data/test.gml";
+ string fname("data/uetzNetworkGSC-all.gml");
+ ifstream f(fname.c_str());
+ if(!f.is_open()) {
+ cout << "Error opening file: " << fname << endl;
+ exit(1);
+ }
+ unsigned V = 0;
+ double defaultEdgeLength=40;
+ vector<Edge> es;
+ CompoundConstraints cx,cy;
+ NodeIdMap nodeIdMap;
+ Partitions partitions;
+ string l;
+ boost::regex nodeRE(".*node\\s+\\[.*");
+ boost::regex edgeRE(".*edge\\s+\\[.*");
+ while(!getline(f,l).eof()) {
+ if(boost::regex_match(l,nodeRE)) {
+ V=readNode(f,nodeIdMap,partitions);
+ }
+ if(boost::regex_match(l,edgeRE)) {
+ pair<unsigned,unsigned> e=readEdge(f);
+ unsigned start=nodeIdMap[e.first];
+ unsigned end=nodeIdMap[e.second];
+ //printf("edge (%d,%d)\n",start,end);
+ es.push_back(make_pair(start,end));
+ //cy.push_back(
+ //new SeparationConstraint(start,end,defaultEdgeLength/3));
+ }
+ }
+ assert(V==nodeIdMap.size());
+ /*
+ unsigned p1=V++;
+ unsigned p2=V++;
+ // red at the top
+ list<unsigned> &p=partitions[string("FF3333")];
+ //double cgap=defaultEdgeLength/3;
+ double cgap=0;
+ for(list<unsigned>::iterator j=p.begin();j!=p.end();j++) {
+ cy.push_back(
+ new SeparationConstraint(*j,p1,cgap));
+ }
+ // yellow in the middle
+ p=partitions[string("FFFF00")];
+ for(list<unsigned>::iterator j=p.begin();j!=p.end();j++) {
+ cy.push_back(
+ new SeparationConstraint(p1,*j,cgap));
+ cy.push_back(
+ new SeparationConstraint(*j,p2,cgap));
+ }
+ // green at the bottom
+ p=partitions[string("00FF00")];
+ for(list<unsigned>::iterator j=p.begin();j!=p.end();j++) {
+ cy.push_back(
+ new SeparationConstraint(p2,*j,cgap));
+ }
+ */
+ cout << "V="<<V<<endl;
+ double width=1000;
+ double height=1000;
+ vector<vpsc::Rectangle*> rs;
+ cout << "|V|=" << V << endl;
+ //srand(time(nullptr));
+ for(unsigned i=0;i<V;i++) {
+ double x=getRand(width), y=getRand(height);
+ rs.push_back(new vpsc::Rectangle(x,x+1,y,y+1));
+ }
+ vector<list<unsigned> > ps;
+ ps.push_back(partitions[string("FF3333")]);
+ ps.push_back(partitions[string("FFFF00")]);
+ ps.push_back(partitions[string("00FF00")]);
+ vector<double> bs;
+ bs.push_back(80);
+ bs.push_back(120);
+ PostIteration test(rs,ps,bs,0.0001,200);
+ ConstrainedMajorizationLayout alg(rs,es,nullptr,defaultEdgeLength,nullptr,test);
+ //ConstrainedFDLayout alg(rs,es,nullptr,defaultEdgeLength,nullptr,test);
+ //alg.setConstrainedLayout(true);
+ //alg.setScaling(true);
+ //alg.setXConstraints(&cx);
+ //alg.setYConstraints(&cy);
+ alg.run();
+ /*
+ vector<ColourRGBA> colours(V);
+ list<unsigned> &p=partitions[string("FF3333")];
+ for(list<unsigned>::iterator i=p.begin();i!=p.end();i++) {
+ //colours[*i]=ColourRGBA(1.,0,0.3,1.);
+ colours[*i]=ColourRGBA(0,0,0,1.);
+ }
+ p=partitions[string("FFFF00")];
+ for(list<unsigned>::iterator i=p.begin();i!=p.end();i++) {
+ //colours[*i]=ColourRGBA((unsigned)255,162,99,255);
+ colours[*i]=ColourRGBA(0,0,0,1.);
+ }
+ p=partitions[string("00FF00")];
+ for(list<unsigned>::iterator i=p.begin();i!=p.end();i++) {
+ //colours[*i]=ColourRGBA((unsigned)24,157,0,255);
+ colours[*i]=ColourRGBA(0,0,0,1.);
+ }
+ */
+ OutputFile of(rs,es,nullptr,"gml_graph-constrained.svg",false,true);
+ //of.colours=&colours;
+ of.generate();
+ for(unsigned i=0;i<V;i++) {
+ delete rs[i];
+ }
+ return 0;
+}
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 :
diff --git a/src/3rdparty/adaptagrams/libcola/tests/graphlayouttest.h b/src/3rdparty/adaptagrams/libcola/tests/graphlayouttest.h
new file mode 100644
index 0000000..2cc51e7
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/graphlayouttest.h
@@ -0,0 +1,275 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+#include <sstream>
+#include <ctime>
+
+#include <libvpsc/rectangle.h>
+#include <libcola/cola.h>
+#include <libtopology/topology_graph.h>
+#include <libcola/output_svg.h>
+
+inline double getRand(double range) {
+ return range*rand()/RAND_MAX;
+}
+
+namespace DFS {
+using namespace std;
+using namespace cola;
+struct Node {
+ unsigned id;
+ bool visited;
+ typedef vector<Node*> PNodes;
+ PNodes neighbours;
+ void visit(vector<unsigned> &order) {
+ visited=true;
+ unsigned mid=neighbours.size()/2;
+ for(unsigned i=0;i<mid;i++) {
+ if(!neighbours[i]->visited) {
+ neighbours[i]->visit(order);
+ }
+ }
+ order.push_back(id);
+ for(unsigned i=mid;i<neighbours.size();i++) {
+ if(!neighbours[i]->visited) {
+ neighbours[i]->visit(order);
+ }
+ }
+ }
+ void visit_leaves(vector<unsigned> &order) {
+ unsigned mid=neighbours.size()/2;
+ Node *v;
+ for(unsigned i=0;i<mid;i++) {
+ v=neighbours[i];
+ if(v->neighbours.size()==0) {
+ order.push_back(v->id);
+ }
+ }
+ order.push_back(id);
+ for(unsigned i=mid;i<neighbours.size();i++) {
+ v=neighbours[i];
+ if(v->neighbours.size()==0) {
+ order.push_back(v->id);
+ }
+ }
+ }
+};
+
+struct Graph {
+ typedef vector<Edge> Edges;
+ typedef vector<Node> Nodes;
+ Nodes nodes;
+ vector<unsigned> order;
+ vector<vector<unsigned> > leaves;
+ Graph(unsigned n,vector<Edge> &edges) {
+ nodes.resize(n);
+ order.resize(0);
+ leaves.resize(n);
+ for(Edges::iterator i=edges.begin();i!=edges.end();i++) {
+ nodes[i->first].neighbours.push_back(&nodes[i->second]);
+ }
+ for(unsigned i=0;i<nodes.size();i++) {
+ nodes[i].id=i;
+ nodes[i].visited=false;
+ }
+ for(Nodes::iterator i=nodes.begin();i!=nodes.end();i++) {
+ if(!i->visited) {
+ i->visit(order);
+ }
+ }
+ for(unsigned i=0;i<nodes.size();i++) {
+ leaves[i].resize(0);
+ nodes[i].visit_leaves(leaves[i]);
+ }
+ assert(order.size()==nodes.size());
+ }
+};
+} // namespace DFS
+using namespace cola;
+using namespace std;
+struct CheckProgress : TestConvergence {
+ CheckProgress(const double d,const unsigned i) : TestConvergence(d,i) {}
+ bool operator()(const double new_stress, valarray<double> & X, valarray<double> & Y) {
+ cout << "stress="<<new_stress<<" iteration="<<iterations<<endl;
+ return TestConvergence::operator()(new_stress,X,Y);
+ }
+};
+
+enum SolverType { CG, UGP, SGP, IP };
+void run_test(
+ vector<pair<double,double> > const &startpos,
+ vector<Edge> const &es,
+ const double defaultEdgeLength,
+ CompoundConstraints &ccs,
+ const SolverType s,
+ const bool constrained,
+ const char *fname,
+ const char *testdesc) {
+ vector<vpsc::Rectangle*> rs;
+ unsigned V=startpos.size();
+ cout << "|V|=" << V << endl;
+ //srand(time(nullptr));
+ for(unsigned i=0;i<V;i++) {
+ double x=startpos[i].first, y=startpos[i].second;
+ rs.push_back(new vpsc::Rectangle(x,x+1,y,y+1));
+ }
+ CheckProgress test(0.001,100);
+ clock_t starttime=clock();
+ ConstrainedMajorizationLayout alg(rs,es,nullptr,defaultEdgeLength,
+ StandardEdgeLengths,&test);
+ switch(s) {
+ cout << "Solver: ";
+ case SGP:
+ cout << "Scaled GP" << endl;
+ alg.setConstrainedLayout(true);
+ alg.setScaling(true);
+ break;
+ case UGP:
+ cout << "Unscaled GP" << endl;
+ alg.setConstrainedLayout(true);
+ alg.setScaling(false);
+ break;
+ case CG:
+ cout << "Conjugate Gradient" << endl;
+ alg.setConstrainedLayout(false);
+ break;
+ case IP:
+ cout << "Interior Point" << endl;
+ alg.setExternalSolver(true);
+ alg.setConstrainedLayout(true);
+ break;
+ }
+ if(!constrained) {
+ cout << "Unconstrained layout" << endl;
+ } else {
+ cout << "Constrained layout" << endl;
+ printf("|CompoundConstraints|=%u\n",(unsigned)ccs.size());
+ alg.setConstraints(&ccs);
+ }
+ alg.run();
+ double t=double(clock()-starttime)/double(CLOCKS_PER_SEC);
+ ostringstream ss;
+ ss << fname << "_" << V << "_" << testdesc << ".svg";
+
+ cout<<ss.str()<<" Time="<<t<<endl;
+ OutputFile of(rs,es,nullptr,ss.str().c_str(),false,true);
+ of.generate();
+ for(unsigned i=0;i<V;i++) {
+ delete rs[i];
+ }
+}
+void writeFile(const topology::Nodes& vs, const topology::Edges& es, const string& outputFileName) {
+ const unsigned n=vs.size();
+ vector<cola::Edge> cedges;
+
+ for(unsigned i=0;i<es.size();i++) {
+ cedges.push_back(make_pair(1,2));
+ }
+
+ vector<straightener::Route*> routes;
+ for(topology::Edges::const_iterator e=es.begin();e!=es.end();++e) {
+ routes.push_back((*e)->getRoute());
+ }
+
+ vector<string> labels(n);
+ for(unsigned i=0;i<n;++i) {
+ stringstream ss;
+ ss << i;
+ labels[i]=ss.str();
+ }
+
+ vector<vpsc::Rectangle*> rs;
+ for(topology::Nodes::const_iterator i=vs.begin();i!=vs.end();++i) {
+ rs.push_back((*i)->rect);
+ }
+ OutputFile of(rs,cedges,nullptr,outputFileName,true,false);
+ of.setLabels(labels);
+ of.routes=&routes;
+ of.generate();
+
+ for_each(routes.begin(),routes.end(),delete_object());
+}
+
+void writeDunnartFile(const topology::Nodes& vs, const vector<std::pair<unsigned int, unsigned int> >& es, const string& outputFileName) {
+ FILE *fp = fopen(outputFileName.c_str(), "w");
+ assert (fp != nullptr);
+
+ fprintf(fp, "<svg xmlns:dunnart=\"http://www.csse.monash.edu.au/~mwybrow/dunnart.dtd\">\n");
+ for(unsigned int i = 0; i < vs.size(); ++i) {
+ vpsc::Rectangle *rect = vs[i]->rect;
+
+ int id = i + 1;
+ fprintf(fp, "<rect id=\"%d\" dunnart:label=\"\" dunnart:width=\"20\" "
+ "dunnart:height=\"20\" dunnart:xPos=\"%f\" "
+ "dunnart:yPos=\"%f\" dunnart:type=\"rect\" />\n", id,
+ rect->getCentreX(), rect->getCentreY());
+ }
+
+ for(unsigned int i = 0; i < es.size(); ++i) {
+ const std::pair<unsigned int, unsigned int>& edge = es[i];
+
+ int id = i + 1 + vs.size();
+ fprintf(fp, "<path id=\"%d\" dunnart:srcID=\"%d\" "
+ "dunnart:srcFlags=\"544\" dunnart:dstID=\"%d\" "
+ "dunnart:dstFlags=\"544\" dunnart:directed=\"1\" "
+ "dunnart:type=\"connAvoidPoly\" />\n", id,
+ edge.first + 1, edge.second + 1);
+ }
+
+ fprintf(fp, "</svg>\n");
+
+ fclose(fp);
+
+#if 0
+ for(unsigned i=0;i<es.size();i++) {
+ cedges.push_back(make_pair(1,2));
+ }
+
+ vector<straightener::Route*> routes;
+ for(topology::Edges::const_iterator e=es.begin();e!=es.end();++e) {
+ routes.push_back((*e)->getRoute());
+ }
+
+ vector<string> labels(n);
+ for(unsigned i=0;i<n;++i) {
+ stringstream ss;
+ ss << i;
+ labels[i]=ss.str();
+ }
+
+ vector<vpsc::Rectangle*> rs;
+ for(topology::Nodes::const_iterator i=vs.begin();i!=vs.end();++i) {
+ rs.push_back((*i)->rect);
+ }
+ OutputFile of(rs,cedges,nullptr,outputFileName,true,false);
+ of.setLabels(labels);
+ of.routes=&routes;
+ of.generate();
+
+ for_each(routes.begin(),routes.end(),delete_object());
+#endif
+}
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:
diff --git a/src/3rdparty/adaptagrams/libcola/tests/initialOverlap.cpp b/src/3rdparty/adaptagrams/libcola/tests/initialOverlap.cpp
new file mode 100644
index 0000000..4f0a8bf
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/initialOverlap.cpp
@@ -0,0 +1,168 @@
+// Check that rectangles that start at same position don't get stuck on top of each other
+// during force-directed layout.
+#include <vector>
+#include <utility>
+#include "libcola/cola.h"
+#include "libcola/pseudorandom.h"
+
+using namespace cola;
+
+int main(void) {
+ CompoundConstraints ccs;
+ std::vector<Edge> es;
+ EdgeLengths eLengths;
+ double defaultEdgeLength=1;
+ std::vector<vpsc::Rectangle*> rs;
+ vpsc::Rectangle *rect = nullptr;
+
+ rect = new vpsc::Rectangle(0, 100, 0, 60);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 100, 0, 60);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 100, 0, 60);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 20, 0, 20);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 60, 0, 60);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 60, 0, 60);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 60, 0, 60);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 60, 0, 60);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 20, 0, 20);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 60, 0, 60);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 60, 0, 60);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 20, 0, 20);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 100, 0, 60);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 20, 0, 20);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 20, 0, 20);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 60, 0, 60);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 60, 0, 60);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 60, 0, 60);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 60, 0, 60);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 100, 0, 60);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 100, 0, 60);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 100, 0, 60);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 100, 0, 60);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(0, 100, 0, 60);
+ rs.push_back(rect);
+
+ es.push_back(std::make_pair(0, 3));
+ es.push_back(std::make_pair(1, 3));
+ es.push_back(std::make_pair(2, 3));
+ es.push_back(std::make_pair(2, 8));
+ es.push_back(std::make_pair(2, 11));
+ es.push_back(std::make_pair(3, 4));
+ es.push_back(std::make_pair(3, 5));
+ es.push_back(std::make_pair(6, 8));
+ es.push_back(std::make_pair(7, 8));
+ es.push_back(std::make_pair(8, 22));
+ es.push_back(std::make_pair(8, 23));
+ es.push_back(std::make_pair(9, 11));
+ es.push_back(std::make_pair(10, 11));
+ es.push_back(std::make_pair(11, 12));
+ es.push_back(std::make_pair(11, 23));
+ es.push_back(std::make_pair(12, 13));
+ es.push_back(std::make_pair(12, 14));
+ es.push_back(std::make_pair(13, 17));
+ es.push_back(std::make_pair(13, 18));
+ es.push_back(std::make_pair(13, 19));
+ es.push_back(std::make_pair(13, 20));
+ es.push_back(std::make_pair(14, 15));
+ es.push_back(std::make_pair(14, 16));
+ es.push_back(std::make_pair(14, 20));
+ es.push_back(std::make_pair(14, 21));
+
+ eLengths.resize(25);
+ eLengths[0] = 100;
+ eLengths[1] = 100;
+ eLengths[2] = 100;
+ eLengths[3] = 100;
+ eLengths[4] = 100;
+ eLengths[5] = 100;
+ eLengths[6] = 100;
+ eLengths[7] = 100;
+ eLengths[8] = 100;
+ eLengths[9] = 100;
+ eLengths[10] = 100;
+ eLengths[11] = 100;
+ eLengths[12] = 100;
+ eLengths[13] = 100;
+ eLengths[14] = 100;
+ eLengths[15] = 100;
+ eLengths[16] = 100;
+ eLengths[17] = 100;
+ eLengths[18] = 100;
+ eLengths[19] = 100;
+ eLengths[20] = 100;
+ eLengths[21] = 100;
+ eLengths[22] = 100;
+ eLengths[23] = 100;
+ eLengths[24] = 100;
+
+ ConstrainedFDLayout alg(rs, es, defaultEdgeLength, eLengths);
+ alg.run();
+ //alg.outputInstanceToSVG("initialOverlap");
+
+ bool overlaps = false;
+
+ for (size_t i = 0; i < rs.size(); ++i)
+ {
+ for (size_t j = i + 1; j < rs.size(); ++j)
+ {
+ overlaps |= ((rs[i]->overlapD(0, rs[j]) > 0) && (rs[i]->overlapD(1, rs[j]) > 0));
+ if (overlaps)
+ {
+ break;
+ }
+ }
+ if (overlaps)
+ {
+ break;
+ }
+ }
+
+ alg.freeAssociatedObjects();
+
+ return (overlaps) ? 1 : 0;
+};
diff --git a/src/3rdparty/adaptagrams/libcola/tests/invalid.cpp b/src/3rdparty/adaptagrams/libcola/tests/invalid.cpp
new file mode 100644
index 0000000..175a6b7
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/invalid.cpp
@@ -0,0 +1,80 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+
+/** \file
+ * Interface between Inkscape code (SPItem) and graphlayout functions.
+ *
+ * Authors:
+ * Tim Dwyer <tgdwyer@gmail.com>
+ */
+#include <iostream>
+
+#include <vector>
+#include <algorithm>
+#include <float.h>
+#include <libcola/cola.h>
+//#include <libvspc/exceptions.h>
+#include <libvpsc/constraint.h>
+#include "graphlayouttest.h"
+
+using namespace std;
+using namespace cola;
+int main() {
+
+ const unsigned V = 2;
+ typedef pair < unsigned, unsigned >Edge;
+ Edge edge_array[] = { Edge(0, 1) };
+ unsigned E = sizeof(edge_array) / sizeof(Edge);
+ vector<Edge> es(edge_array,edge_array+E);
+ double width=100;
+ double height=100;
+ vector<vpsc::Rectangle*> rs;
+ for(unsigned i=0;i<V;i++) {
+ double x=getRand(width), y=getRand(height);
+ rs.push_back(new vpsc::Rectangle(x,x+5,y,y+5));
+ }
+ ConstrainedFDLayout alg(rs, es, width/2);
+ CompoundConstraints ccs;
+ AlignmentConstraint ac(vpsc::YDIM);
+ ccs.push_back(&ac);
+ ac.addShape(0,0);
+ ac.addShape(5,0);
+ alg.setConstraints(ccs);
+ try {
+ alg.run();
+ } catch (cola::InvalidVariableIndexException& e) {
+ cerr << e.what() << endl;
+ return 0;
+ }
+ //assert(fabs(rs[0]->getCentreX()-rs[3]->getCentreX())<0.001);
+ cout<<rs[0]->getCentreX()<<","<<rs[1]->getCentreX()<<endl;
+ //output_svg(rs,es,"unsatisfiable.svg");
+ for(unsigned i=0;i<V;i++) {
+ delete rs[i];
+ }
+ return 1;
+}
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 :
diff --git a/src/3rdparty/adaptagrams/libcola/tests/large_graph.cpp b/src/3rdparty/adaptagrams/libcola/tests/large_graph.cpp
new file mode 100644
index 0000000..a236991
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/large_graph.cpp
@@ -0,0 +1,144 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+// Loads a graph from a text file, generates constraints for each edge requiring them
+// to point downwards, and proceeds to produce a layout using libcola.
+// The input file format is 2 numeric node labels per line separated by a space,
+// each pair representing a directed edge. Node labels are simply used as array
+// offsets so they should start from 0.
+// The graph should be connected.
+// Default input file is the matrix market 1138_bus graph.
+// Running times:
+// no constraints - steepest descent solver: 149 seconds
+// no constraints - mosek: 49.47 seconds
+// no constraints - conjugate gradient solver: 12.2 seconds
+// dir-edge constraints - mosek: 214.2 seconds
+//
+// V=1138
+#include<iostream>
+#include<iomanip>
+#include<fstream>
+#include<vector>
+#include<valarray>
+#include <libvpsc/linesegment.h>
+#include "graphlayouttest.h"
+
+using namespace std;
+using namespace cola;
+
+int countCrossings(vpsc::Rectangles& rs, vector<cola::Edge>& es) {
+ int crossings=0;
+ for(unsigned i=0;i<es.size()-1;++i) {
+ for(unsigned j=i+1;j<es.size();++j) {
+ Edge e1=es[i], e2=es[j];
+ Rectangle *e1a=rs[e1.first],
+ *e1b=rs[e1.second],
+ *e2a=rs[e2.first],
+ *e2b=rs[e2.second];
+ linesegment::LineSegment s1(
+ linesegment::Vector(e1a->getCentreX(),e1a->getCentreY()),
+ linesegment::Vector(e1b->getCentreX(),e1b->getCentreY()));
+ linesegment::LineSegment s2(
+ linesegment::Vector(e2a->getCentreX(),e2a->getCentreY()),
+ linesegment::Vector(e2b->getCentreX(),e2b->getCentreY()));
+ linesegment::Vector point;
+ if(s1.Intersect(s2,point)==linesegment::LineSegment::INTERSECTING) {
+ ++crossings;
+ }
+ }
+ }
+ return crossings;
+}
+int main() {
+ const char *fname="data/1138_bus.txt"; //"data/dg_850.txt";
+ ifstream f(fname);
+ if(!f.is_open()) {
+ cout << "Error opening file: " << fname << endl;
+ exit(1);
+ }
+ string startlabel, endlabel;
+ unsigned V = 0;
+ double defaultEdgeLength=40;
+ vector<Edge> es;
+ CompoundConstraints cx,cy;
+ while(!getline(f,startlabel,' ').eof()) {
+ getline(f,endlabel);
+ unsigned start = atoi(startlabel.c_str()),
+ end = atoi(endlabel.c_str());
+ es.push_back(make_pair(start,end));
+ cy.push_back(
+ new SeparationConstraint(end,start,defaultEdgeLength/3));
+ V=max(V,max(start,end));
+ }
+ V++;
+ /*
+ DFS::Graph dfs(V,es);
+ for(unsigned i=1;i<dfs.order.size();i++) {
+ cx.push_back(
+ new SeparationConstraint(dfs.order[i-1],dfs.order[i],0));
+ }
+ */
+ cout << "V="<<V<<endl;
+ double width=1000;
+ double height=1000;
+ vector<pair<double,double> > startpos(V);
+ //srand(time(nullptr));
+ for(unsigned i=0;i<V;i++) {
+ double x=getRand(width), y=getRand(height);
+ startpos[i]=make_pair(x,y);
+ }
+ //const char *testname="large_graph";
+ //run_test(startpos,es,defaultEdgeLength,cx,cy,CG,false,testname,"cg");
+ //run_test(startpos,es,defaultEdgeLength,cx,cy,IP,false,testname,"ip");
+ //run_test(startpos,es,defaultEdgeLength,cx,cy,UGP,false,testname,"ugp");
+ //run_test(startpos,es,defaultEdgeLength,cx,cy,SGP,false,testname,"sgp");
+ //run_test(startpos,es,defaultEdgeLength,cx,cy,IP,true,testname,"cip");
+ //run_test(startpos,es,defaultEdgeLength,cx,cy,UGP,true,testname,"cugp");
+ //run_test(startpos,es,defaultEdgeLength,cx,cy,SGP,true,testname,"csgp");
+ vector<vpsc::Rectangle*> rs;
+ for(unsigned i=0;i<V;i++) {
+ double x=getRand(width), y=getRand(height);
+ rs.push_back(new vpsc::Rectangle(x,x+5,y,y+5));
+ }
+ cout<<"Initial crossings="<<countCrossings(rs,es)<<endl;
+ CheckProgress test(0.0001,200);
+ ConstrainedMajorizationLayout alg(rs,es,nullptr,defaultEdgeLength,nullptr,test);
+ alg.setYConstraints(&cy);
+ alg.run();
+ cout<<"Majorization crossings="<<countCrossings(rs,es)<<endl;
+ OutputFile output1(rs,es,nullptr,"large_graph-majorization.pdf");
+ output1.generate();
+ ConstrainedFDLayout alg2(rs,es,defaultEdgeLength,nullptr,test);
+ alg2.setYConstraints(&cy);
+ alg2.run();
+ cout<<"PStress crossings="<<countCrossings(rs,es)<<endl;
+ OutputFile output(rs,es,nullptr,"large_graph.pdf");
+ output.generate();
+ for(unsigned i=0;i<V;i++) {
+ delete rs[i];
+ }
+ return 0;
+}
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 :
diff --git a/src/3rdparty/adaptagrams/libcola/tests/makefeasible.cpp b/src/3rdparty/adaptagrams/libcola/tests/makefeasible.cpp
new file mode 100644
index 0000000..4bfb082
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/makefeasible.cpp
@@ -0,0 +1,368 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+#include <iostream>
+#include <vector>
+#include <cmath>
+#include <time.h>
+#include <valarray>
+#include <fstream>
+#include <sstream>
+
+#include <libavoid/libavoid.h>
+#include <libavoid/router.h>
+
+#include "graphlayouttest.h"
+
+using namespace std;
+using namespace cola;
+using namespace vpsc;
+
+/*
+// |V|=12, |E|=23
+static const unsigned DAGDEPTH = 3;
+static const unsigned BRANCHFACTOR = 3;
+static const double EXTRAEDGEPROB = 0.5;
+*/
+/*
+// |V|=26, |E|=61
+static const unsigned DAGDEPTH = 3;
+static const unsigned BRANCHFACTOR = 4;
+static const double EXTRAEDGEPROB = 0.1;
+*/
+
+/*
+// |V|=62, |E|=85
+static const unsigned DAGDEPTH = 4;
+static const unsigned BRANCHFACTOR = 4;
+static const double EXTRAEDGEPROB = 0.01;
+*/
+/*
+// |V|=131, |E|=166
+static const unsigned DAGDEPTH = 5;
+static const unsigned BRANCHFACTOR = 4;
+static const double EXTRAEDGEPROB = 0.005;
+*/
+
+static const unsigned DAGDEPTH = 6;
+static const unsigned BRANCHFACTOR = 4;
+static const double EXTRAEDGEPROB = 0.002;
+/*
+// |V|=343, |E|=487
+seed=1208390913;
+static const unsigned DAGDEPTH = 6;
+static const unsigned BRANCHFACTOR = 4;
+static const double EXTRAEDGEPROB = 0.002;
+*/
+
+void makeEdge(unsigned u, unsigned v,
+ vector<Edge> &edges, CompoundConstraints &ccs) {
+ edges.push_back(make_pair(u,v));
+ ccs.push_back(new SeparationConstraint(vpsc::YDIM, u,v,5));
+}
+vector<Edge> random_dag(unsigned depth, unsigned maxbranch, unsigned &V,
+ CompoundConstraints &ccs) {
+ printf("DAG depth=%d\nmaxbranch=%d\nextraedgeprob%f\n",depth,maxbranch,EXTRAEDGEPROB);
+ vector<Edge> edges;
+ unsigned lstart=0, lend=1;
+ V=0;
+ for(unsigned i=0;i<depth;i++) {
+ for(unsigned j=lstart;j<lend;j++) {
+ //makeEdge(j,++V,edges,cy);
+ //makeEdge(j,++V,edges,cy);
+ for(unsigned k=0;k<maxbranch;k++) {
+ double r=(double)rand()/(double)RAND_MAX;
+ if(r < 0.5) {
+ makeEdge(j,++V,edges,ccs);
+ }
+ }
+ }
+ lstart=lend;
+ lend=V+1;
+ }
+ V++;
+ /*
+ DFS::Graph dfs(V,edges);
+ for(unsigned i=1;i<dfs.order.size();i++) {
+ cx.push_back(
+ new SeparationConstraint(dfs.order[i-1],dfs.order[i],0.5));
+ }
+ */
+ for(unsigned i=0;i<V;++i) {
+ for(unsigned j=i+1;j<V;++j) {
+ double r=(double)rand()/(double)RAND_MAX;
+ if(r < EXTRAEDGEPROB) {
+ makeEdge(i,j,edges,ccs);
+ }
+ }
+ }
+ /*
+ for(unsigned i=0;i<dfs.leaves.size();i++) {
+ for(unsigned j=1;j<dfs.leaves[i].size();j++) {
+ cx.push_back( new SeparationConstraint(dfs.leaves[i][j-1],dfs.leaves[i][j],10));
+ }
+ }
+ */
+ return edges;
+}
+void removeoverlaps(vpsc::Rectangles &rs, bool bothaxes) {
+ double xBorder=0, yBorder=0;
+ static const double EXTRA_GAP=1e-5;
+ unsigned n=rs.size();
+ try {
+ // The extra gap avoids numerical imprecision problems
+ Rectangle::setXBorder(xBorder+EXTRA_GAP);
+ Rectangle::setYBorder(yBorder+EXTRA_GAP);
+ vpsc::Variables vs(n);
+ unsigned i=0;
+ for(Variables::iterator v=vs.begin();v!=vs.end();++v,++i) {
+ *v=new Variable(i,0,1);
+ }
+ vpsc::Constraints cs;
+ vpsc::generateXConstraints(rs,vs,cs,bothaxes);
+ vpsc::IncSolver vpsc_x(vs,cs);
+ vpsc_x.solve();
+ vpsc::Rectangles::iterator r=rs.begin();
+ for(Variables::iterator v=vs.begin();v!=vs.end();++v,++r) {
+ assert((*v)->finalPosition==(*v)->finalPosition);
+ (*r)->moveCentreX((*v)->finalPosition);
+ }
+ assert(r==rs.end());
+ for_each(cs.begin(),cs.end(),vpsc::delete_object());
+ cs.clear();
+ if(bothaxes) {
+ // Removing the extra gap here ensures things that were moved to be adjacent to one another above are not considered overlapping
+ Rectangle::setXBorder(Rectangle::xBorder-EXTRA_GAP);
+ vpsc::generateYConstraints(rs,vs,cs);
+ vpsc::IncSolver vpsc_y(vs,cs);
+ vpsc_y.solve();
+ r=rs.begin();
+ for(Variables::iterator v=vs.begin();v!=vs.end();++v,++r) {
+ (*r)->moveCentreY((*v)->finalPosition);
+ }
+ for_each(cs.begin(),cs.end(),vpsc::delete_object());
+ cs.clear();
+ Rectangle::setYBorder(Rectangle::yBorder-EXTRA_GAP);
+ vpsc::generateXConstraints(rs,vs,cs,false);
+ vpsc::IncSolver vpsc_x2(vs,cs);
+ vpsc_x2.solve();
+ r=rs.begin();
+ for(Variables::iterator v=vs.begin();v!=vs.end();++v,++r) {
+ (*r)->moveCentreX((*v)->finalPosition);
+ }
+ for_each(cs.begin(),cs.end(),vpsc::delete_object());
+ }
+ for_each(vs.begin(),vs.end(),vpsc::delete_object());
+ } catch (char *str) {
+ std::cerr<<str<<std::endl;
+ for(vpsc::Rectangles::iterator r=rs.begin();r!=rs.end();++r) {
+ std::cerr << **r <<std::endl;
+ }
+ }
+ Rectangle::setXBorder(xBorder);
+ Rectangle::setYBorder(yBorder);
+}
+/*
+void writeTextFile(vector<cola::Edge>& edges) {
+ ofstream outfile("new.txt",ofstream::binary);
+ for(vector<cola::Edge>::iterator e=edges.begin();e!=edges.end();++e) {
+ outfile<<"node"<<e->first<<",node"<<e->second<<endl;
+ }
+ outfile.close();
+}
+*/
+/*
+ * Make feasible:
+ * - remove overlaps between rectangular boundaries of nodes/clusters
+ * (respecting structural constraints)
+ * - perform routing (preserve previous topology using rubber banding)
+ */
+void makeFeasible(vpsc::Rectangles& rs, vector<cola::Edge>& edges,
+ std::vector<topology::Edge*>& routes,
+ std::vector<topology::Node*>& topologyNodes, double defaultEdgeLength) {
+ printf("Removing overlaps...\n");
+ removeoverlaps(rs,false);
+ printf("done.\n");
+ printf("Running libavoid to compute routes...\n");
+ clock_t libavoidstarttime=clock();
+ // find feasible routes for edges
+ Avoid::Router *router = new Avoid::Router(Avoid::PolyLineRouting);
+ // Use rotational sweep for point visibility
+ router->UseLeesAlgorithm = true;
+ // Don't use invisibility graph.
+ router->InvisibilityGrph = false;
+ double g=0; // make shape that libavoid sees slightly smaller
+ for(unsigned i=0;i<rs.size();++i) {
+ vpsc::Rectangle* r=rs[i];
+ double x=r->getMinX()+g;
+ double X=r->getMaxX()-g;
+ double y=r->getMinY()+g;
+ double Y=r->getMaxY()-g;
+ // Create the ShapeRef:
+ Avoid::Polygon shapePoly(4);
+ // AntiClockwise!
+ shapePoly.ps[0] = Avoid::Point(X,y);
+ shapePoly.ps[1] = Avoid::Point(X,Y);
+ shapePoly.ps[2] = Avoid::Point(x,Y);
+ shapePoly.ps[3] = Avoid::Point(x,y);
+ //if(i==4||i==13||i==9) {
+ //printf("rect[%d]:{%f,%f,%f,%f}\n",i,x,y,X,Y);
+ //}
+ unsigned int shapeID = i + 1;
+ Avoid::ShapeRef *shapeRef = new Avoid::ShapeRef(router, shapePoly,
+ shapeID);
+ // ShapeRef constructor makes a copy of polygon so we can free it:
+ router->addShape(shapeRef);
+ }
+ for(unsigned i=0;i<edges.size();++i) {
+ cola::Edge e=edges[i];
+ Avoid::ConnRef *connRef;
+ unsigned int connID = i + rs.size() + 1;
+ Rectangle* r0=rs[e.first], *r1=rs[e.second];
+ Avoid::Point srcPt(r0->getCentreX(),r0->getCentreY());
+ Avoid::Point dstPt(r1->getCentreX(),r1->getCentreY());
+ connRef = new Avoid::ConnRef(router, srcPt, dstPt, connID);
+ router->processTransaction();
+ const Avoid::Polygon& route = connRef->route();
+ vector<topology::EdgePoint*> eps;
+ eps.push_back( new topology::EdgePoint( topologyNodes[e.first],
+ topology::EdgePoint::CENTRE));
+ for(size_t j=1;j+1<route.size();j++) {
+ const Avoid::Point& p = route.ps[j];
+ const unsigned nodeID=p.id-1;
+ topology::Node* node=topologyNodes[nodeID];
+ topology::EdgePoint::RectIntersect ri;
+ switch(p.vn) {
+ case 0: ri=topology::EdgePoint::BR;
+ break;
+ case 1: ri=topology::EdgePoint::TR;
+ break;
+ case 2: ri=topology::EdgePoint::TL;
+ break;
+ case 3: ri=topology::EdgePoint::BL;
+ break;
+ default: ri=topology::EdgePoint::CENTRE;
+ }
+ eps.push_back(new topology::EdgePoint(node,ri));
+ }
+ eps.push_back(new topology::EdgePoint(topologyNodes[e.second],
+ topology::EdgePoint::CENTRE));
+ topology::Edge* edgeRoute=new topology::Edge(i,defaultEdgeLength, eps);
+ edgeRoute->assertConvexBends();
+ routes.push_back(edgeRoute);
+
+ }
+ writeFile(topologyNodes,routes,"beautify0.svg");
+ assert(topology::assertNoSegmentRectIntersection(topologyNodes,routes));
+ double libavoidtime=double(clock()-libavoidstarttime)/double(CLOCKS_PER_SEC);
+ cout << "done. Libavoid ran in " << libavoidtime << " seconds" << endl;
+ delete router;
+}
+int main() {
+ unsigned V;
+ CompoundConstraints ccs;
+
+ int seed = time(nullptr);
+ //seed=1207906420;
+ //seed=1207920674;
+ //seed=1207982613;
+ //seed=1207984219;
+ seed=1207984299;
+ //seed=1207984743;
+ //seed=1207985027; // very short edge which seems to cause problems
+ //seed=1207986026; // error if we don't check neighbour is actually on scanline when determining visibility when generating straight constraints
+ //seed=1207991731;
+ //seed=1208303930;
+ //seed=1208304508;
+ //seed=1208316284;
+ //seed=1208319019;
+ //seed=1208321702;
+ printf("random seed=%d\n",seed);
+ srand(seed);
+ vector<Edge> es = random_dag(DAGDEPTH,BRANCHFACTOR,V,ccs);
+ double defaultEdgeLength=40;
+
+ cout << "V="<<V<<endl;
+ cout << "E="<<es.size()<<endl;
+ double width=700;
+ double height=700;
+ vector<pair<double,double> > startpos(V);
+ for(unsigned i=0;i<V;i++) {
+ double x=getRand(width), y=getRand(height);
+ startpos[i]=make_pair(x,y);
+ }
+ vector<vpsc::Rectangle*> rs;
+ vector<topology::Node*> topologyNodes;
+ vector<topology::Edge*> routes;
+ for(unsigned i=0;i<V;i++) {
+ double x=getRand(width), y=getRand(height);
+ vpsc::Rectangle* r =new vpsc::Rectangle(x,x+30,y,y+10);
+ rs.push_back(r);
+ topologyNodes.push_back(new topology::Node(i,r));
+ }
+ CheckProgress test(0.01,100);
+ clock_t unconstrainedstarttime=clock();
+ //writeTextFile(es);
+ es.clear();
+ ConstrainedFDLayout alg2(rs,es,defaultEdgeLength,nullptr,test);
+ //alg2.setConstraints(&ccs);
+
+ alg2.makeFeasible(true);
+ alg2.run();
+
+ alg2.outputInstanceToSVG();
+#if 0
+ double totaltime=0;
+ double unconstrainedtime=double(clock()-unconstrainedstarttime)/double(CLOCKS_PER_SEC);
+ totaltime+=unconstrainedstarttime;
+ cout<<"unconstrained layout ran in "<<unconstrainedtime<<" seconds"<<endl;
+ clock_t makefeasiblestarttime=clock();
+ makeFeasible(rs,es,routes,topologyNodes,defaultEdgeLength);
+ double makefeasibletime=double(clock()-makefeasiblestarttime)/double(CLOCKS_PER_SEC);
+ totaltime+=makefeasibletime;
+ cout<<"makefeasible ran in "<<makefeasibletime<<" seconds"<<endl;
+ clock_t beautifystarttime=clock();
+ test.reset();
+ alg2.setTopology(&topologyNodes, &routes);
+ writeFile(topologyNodes,routes,"beautify1.svg");
+ std::stringstream dunnartfile;
+ dunnartfile << "v" << V << "e" << (int) es.size() << ".svg";
+ writeDunnartFile(topologyNodes,es,dunnartfile.str().c_str());
+
+ alg2.run();
+ double beautifytime=double(clock()-beautifystarttime)/double(CLOCKS_PER_SEC);
+ totaltime+=beautifytime;
+ cout<<"beautify ran in "<<beautifytime<<" seconds"<<endl;
+ cout<<"TOTAL="<<totaltime<<endl;
+ cout <<"---------------------------------------------"<< endl;
+ cout <<V<<" & "<<es.size()<<" & "<<unconstrainedtime<<" & "<<makefeasibletime<<" & "<<beautifytime<<" & "<<totaltime<<" \\\\ % Seed: "<< seed <<endl;
+ writeFile(topologyNodes,routes,"beautify2.svg");
+#endif
+ for(unsigned i=0;i<V;i++) {
+ delete rs[i];
+ }
+ return 0;
+}
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 :
diff --git a/src/3rdparty/adaptagrams/libcola/tests/makefeasible02.cpp b/src/3rdparty/adaptagrams/libcola/tests/makefeasible02.cpp
new file mode 100755
index 0000000..82d55b7
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/makefeasible02.cpp
@@ -0,0 +1,932 @@
+#include <vector>
+#include "libcola/cola.h"
+using namespace cola;
+int main(void) {
+ CompoundConstraints ccs;
+ std::vector<Edge> es;
+ double defaultEdgeLength=40;
+ std::vector<vpsc::Rectangle*> rs;
+ vpsc::Rectangle *rect = nullptr;
+
+ rect = new vpsc::Rectangle(252, 272, 930, 950);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(109, 129, 898, 918);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(252, 272, 951, 971);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(99, 139, 931, 971);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(593, 665, 212.5, 459.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(398, 518, 52, 96);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(341, 361, 899, 919);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(450, 470, 930, 950);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(402, 422, 930, 950);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(394, 414, 861, 881);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(394, 414, 840, 860);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(282, 302, 852, 872);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(173, 193, 852, 872);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(521, 541, 851, 871);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(313, 401, 739, 783);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(446, 466, 757, 777);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(446, 466, 688, 708);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(447, 467, 616, 636);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(421, 441, 471, 491);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(196.5, 359.5, 575, 619);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(366, 386, 437, 457);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(446, 466, 391, 411);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(446, 466, 325, 345);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(393, 413, 325, 345);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(515, 535, 182, 202);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(446, 466, 255, 275);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(446, 466, 160, 180);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(366, 386, 289, 309);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(211, 231, 270, 290);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(211, 231, 289, 309);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(320, 340, 256, 276);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(270, 290, 256, 276);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(144, 164, 251, 271);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(211, 231, 214, 234);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(211, 231, 195, 215);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(279, 299, 173, 193);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(306, 326, 141, 161);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(306, 326, 120, 140);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(34.5, 295.5, 39.5, 74.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(225, 245, 895, 915);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(446, 466, 543, 563);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(211, 231, 233, 253);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(211, 231, 308, 328);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(144, 164, 347, 367);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(144, 164, 373, 393);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(254, 274, 346, 366);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(254, 274, 372, 392);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(554, 594, 173, 213);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(436, 476, 121, 161);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(436, 476, 642, 682);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(134, 174, 206, 246);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(134, 174, 279, 319);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(285, 325, 426, 466);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(285, 325, 279, 319);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(436, 476, 208, 248);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(436, 476, 281, 321);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(436, 476, 714, 754);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(436, 476, 570, 610);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(436, 476, 498, 538);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(580, 620, 841, 881);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(267, 307, 884, 924);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(503, 543, 931, 971);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(436, 476, 841, 881);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(331, 371, 841, 881);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(331, 371, 798, 838);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(99, 139, 841, 881);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(331, 371, 931, 971);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(218, 258, 841, 881);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(165, 205, 884, 924);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(436, 476, 351, 391);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(85, 125, 336, 376);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(192, 232, 336, 376);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(192, 232, 362, 402);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(85, 125, 362, 402);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(20.5, 77.5, 716, 880);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(167, 187, 713, 733);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(99, 139, 714, 754);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(402, 422, 951, 971);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(167, 187, 734, 754);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(450, 470, 951, 971);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(532.5, 669.5, 899.5, 934.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(471, 491, 471, 491);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(545, 565, 512, 532);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(518, 538, 531, 551);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(252, 272, 782, 802);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(495, 515, 512, 532);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(351, 391, 534, 574);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(400, 420, 573, 593);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(401, 421, 509, 529);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(436, 476, 426, 466);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(234, 290, 970, 1010);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(29, 85, 888, 928);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(234, 290, 991, 1031);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(261, 317, 889, 929);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(432, 488, 870, 910);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(384, 440, 970, 1010);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(314, 370, 851, 891);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(438, 494, 830, 870);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(202, 258, 842, 882);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(155, 211, 792, 832);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(503, 559, 791, 831);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(490, 546, 747, 787);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(366, 422, 678, 718);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(367, 423, 606, 646);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(341, 397, 461, 501);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(348, 404, 377, 417);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(490, 546, 381, 421);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(490, 546, 315, 355);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(375, 431, 365, 405);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(497, 553, 122, 162);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(490, 546, 245, 285);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(366, 422, 150, 190);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(348, 404, 229, 269);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(193, 249, 210, 250);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(193, 249, 229, 269);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(364, 420, 246, 286);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(190, 246, 246, 286);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(64, 120, 241, 281);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(193, 249, 154, 194);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(193, 249, 135, 175);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(261, 317, 213, 253);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(288, 344, 81, 121);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(288, 344, 160, 200);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(207, 263, 835, 875);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(366, 422, 533, 573);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(193, 249, 173, 213);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(193, 249, 248, 288);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(126, 182, 287, 327);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(126, 182, 413, 453);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(236, 292, 286, 326);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(236, 292, 412, 452);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(149, 205, 653, 693);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(384, 440, 891, 931);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(149, 205, 674, 714);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(432, 488, 991, 1031);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(515, 571, 461, 501);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(527, 583, 452, 492);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(500, 556, 571, 611);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(234, 290, 722, 762);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(539, 595, 502, 542);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(382, 438, 613, 653);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(383, 439, 449, 489);
+ rs.push_back(rect);
+
+#if 1
+ AlignmentConstraint *alignment2424608 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment2424608->addShape(0, 0);
+ alignment2424608->addShape(2, 0);
+ alignment2424608->addShape(45, 0);
+ alignment2424608->addShape(46, 0);
+ alignment2424608->addShape(84, 0);
+ alignment2424608->addShape(90, 0);
+ alignment2424608->addShape(92, 0);
+ alignment2424608->addShape(129, 0);
+ alignment2424608->addShape(130, 0);
+ alignment2424608->addShape(138, 0);
+ ccs.push_back(alignment2424608);
+ AlignmentConstraint *alignment2424744 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment2424744->addShape(1, 0);
+ alignment2424744->addShape(3, 0);
+ alignment2424744->addShape(65, 0);
+ alignment2424744->addShape(76, 0);
+ ccs.push_back(alignment2424744);
+ AlignmentConstraint *alignment1216038856 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216038856->addShape(4, 0);
+ ccs.push_back(alignment1216038856);
+ AlignmentConstraint *alignment1216038920 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216038920->addShape(5, 0);
+ alignment1216038920->addShape(7, 0);
+ alignment1216038920->addShape(15, 0);
+ alignment1216038920->addShape(16, 0);
+ alignment1216038920->addShape(17, 0);
+ alignment1216038920->addShape(21, 0);
+ alignment1216038920->addShape(22, 0);
+ alignment1216038920->addShape(25, 0);
+ alignment1216038920->addShape(26, 0);
+ alignment1216038920->addShape(40, 0);
+ alignment1216038920->addShape(48, 0);
+ alignment1216038920->addShape(49, 0);
+ alignment1216038920->addShape(54, 0);
+ alignment1216038920->addShape(55, 0);
+ alignment1216038920->addShape(56, 0);
+ alignment1216038920->addShape(57, 0);
+ alignment1216038920->addShape(58, 0);
+ alignment1216038920->addShape(62, 0);
+ alignment1216038920->addShape(69, 0);
+ alignment1216038920->addShape(79, 0);
+ alignment1216038920->addShape(89, 0);
+ alignment1216038920->addShape(94, 0);
+ alignment1216038920->addShape(134, 0);
+ ccs.push_back(alignment1216038920);
+ AlignmentConstraint *alignment1216038984 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216038984->addShape(6, 0);
+ alignment1216038984->addShape(63, 0);
+ alignment1216038984->addShape(64, 0);
+ alignment1216038984->addShape(66, 0);
+ ccs.push_back(alignment1216038984);
+ AlignmentConstraint *alignment1216039048 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216039048->addShape(8, 0);
+ alignment1216039048->addShape(77, 0);
+ alignment1216039048->addShape(87, 0);
+ alignment1216039048->addShape(88, 0);
+ alignment1216039048->addShape(95, 0);
+ alignment1216039048->addShape(132, 0);
+ alignment1216039048->addShape(140, 0);
+ alignment1216039048->addShape(141, 0);
+ ccs.push_back(alignment1216039048);
+ AlignmentConstraint *alignment1216039112 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216039112->addShape(9, 0);
+ alignment1216039112->addShape(10, 0);
+ alignment1216039112->addShape(23, 0);
+ alignment1216039112->addShape(108, 0);
+ ccs.push_back(alignment1216039112);
+ AlignmentConstraint *alignment1216039176 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216039176->addShape(11, 0);
+ alignment1216039176->addShape(35, 0);
+ alignment1216039176->addShape(60, 0);
+ alignment1216039176->addShape(93, 0);
+ alignment1216039176->addShape(120, 0);
+ ccs.push_back(alignment1216039176);
+ AlignmentConstraint *alignment1216039240 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216039240->addShape(12, 0);
+ alignment1216039240->addShape(68, 0);
+ alignment1216039240->addShape(99, 0);
+ ccs.push_back(alignment1216039240);
+ AlignmentConstraint *alignment1216039304 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216039304->addShape(13, 0);
+ alignment1216039304->addShape(83, 0);
+ alignment1216039304->addShape(100, 0);
+ alignment1216039304->addShape(137, 0);
+ ccs.push_back(alignment1216039304);
+ AlignmentConstraint *alignment1216040464 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216040464->addShape(14, 0);
+ ccs.push_back(alignment1216040464);
+ AlignmentConstraint *alignment1216040528 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216040528->addShape(18, 0);
+ ccs.push_back(alignment1216040528);
+ AlignmentConstraint *alignment1216040592 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216040592->addShape(19, 0);
+ alignment1216040592->addShape(31, 0);
+ ccs.push_back(alignment1216040592);
+ AlignmentConstraint *alignment1216040656 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216040656->addShape(20, 0);
+ alignment1216040656->addShape(27, 0);
+ alignment1216040656->addShape(86, 0);
+ alignment1216040656->addShape(105, 0);
+ alignment1216040656->addShape(112, 0);
+ ccs.push_back(alignment1216040656);
+ AlignmentConstraint *alignment1216040720 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216040720->addShape(24, 0);
+ alignment1216040720->addShape(61, 0);
+ alignment1216040720->addShape(109, 0);
+ ccs.push_back(alignment1216040720);
+ AlignmentConstraint *alignment1216040784 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216040784->addShape(28, 0);
+ alignment1216040784->addShape(29, 0);
+ alignment1216040784->addShape(33, 0);
+ alignment1216040784->addShape(34, 0);
+ alignment1216040784->addShape(41, 0);
+ alignment1216040784->addShape(42, 0);
+ alignment1216040784->addShape(113, 0);
+ alignment1216040784->addShape(114, 0);
+ alignment1216040784->addShape(116, 0);
+ alignment1216040784->addShape(118, 0);
+ alignment1216040784->addShape(119, 0);
+ alignment1216040784->addShape(125, 0);
+ alignment1216040784->addShape(126, 0);
+ ccs.push_back(alignment1216040784);
+ AlignmentConstraint *alignment1216034032 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216034032->addShape(30, 0);
+ ccs.push_back(alignment1216034032);
+ AlignmentConstraint *alignment1216035736 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216035736->addShape(32, 0);
+ alignment1216035736->addShape(43, 0);
+ alignment1216035736->addShape(44, 0);
+ alignment1216035736->addShape(50, 0);
+ alignment1216035736->addShape(51, 0);
+ alignment1216035736->addShape(127, 0);
+ alignment1216035736->addShape(128, 0);
+ ccs.push_back(alignment1216035736);
+ AlignmentConstraint *alignment1216035800 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216035800->addShape(36, 0);
+ alignment1216035800->addShape(37, 0);
+ alignment1216035800->addShape(121, 0);
+ alignment1216035800->addShape(122, 0);
+ ccs.push_back(alignment1216035800);
+ AlignmentConstraint *alignment1216035864 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216035864->addShape(38, 0);
+ ccs.push_back(alignment1216035864);
+ AlignmentConstraint *alignment1216035928 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216035928->addShape(39, 0);
+ alignment1216035928->addShape(67, 0);
+ alignment1216035928->addShape(98, 0);
+ alignment1216035928->addShape(123, 0);
+ ccs.push_back(alignment1216035928);
+ AlignmentConstraint *alignment1216035992 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216035992->addShape(47, 0);
+ ccs.push_back(alignment1216035992);
+ AlignmentConstraint *alignment1216036056 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216036056->addShape(52, 0);
+ alignment1216036056->addShape(53, 0);
+ ccs.push_back(alignment1216036056);
+ AlignmentConstraint *alignment1216036120 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216036120->addShape(59, 0);
+ alignment1216036120->addShape(80, 0);
+ ccs.push_back(alignment1216036120);
+ AlignmentConstraint *alignment1216036184 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216036184->addShape(70, 0);
+ alignment1216036184->addShape(73, 0);
+ ccs.push_back(alignment1216036184);
+ AlignmentConstraint *alignment1216036248 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216036248->addShape(71, 0);
+ alignment1216036248->addShape(72, 0);
+ ccs.push_back(alignment1216036248);
+ AlignmentConstraint *alignment1216036312 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216036312->addShape(74, 0);
+ ccs.push_back(alignment1216036312);
+ AlignmentConstraint *alignment1216036376 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216036376->addShape(75, 0);
+ alignment1216036376->addShape(78, 0);
+ alignment1216036376->addShape(131, 0);
+ alignment1216036376->addShape(133, 0);
+ ccs.push_back(alignment1216036376);
+ AlignmentConstraint *alignment1216036440 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216036440->addShape(81, 0);
+ ccs.push_back(alignment1216036440);
+ AlignmentConstraint *alignment1216036504 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216036504->addShape(82, 0);
+ alignment1216036504->addShape(136, 0);
+ ccs.push_back(alignment1216036504);
+ AlignmentConstraint *alignment1216036568 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216036568->addShape(85, 0);
+ ccs.push_back(alignment1216036568);
+ AlignmentConstraint *alignment1216036632 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216036632->addShape(91, 0);
+ ccs.push_back(alignment1216036632);
+ AlignmentConstraint *alignment1216034712 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216034712->addShape(96, 0);
+ ccs.push_back(alignment1216034712);
+ AlignmentConstraint *alignment1216034776 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216034776->addShape(97, 0);
+ ccs.push_back(alignment1216034776);
+ AlignmentConstraint *alignment1216034840 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216034840->addShape(101, 0);
+ alignment1216034840->addShape(106, 0);
+ alignment1216034840->addShape(107, 0);
+ alignment1216034840->addShape(110, 0);
+ ccs.push_back(alignment1216034840);
+ AlignmentConstraint *alignment1216034904 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216034904->addShape(102, 0);
+ alignment1216034904->addShape(103, 0);
+ alignment1216034904->addShape(111, 0);
+ alignment1216034904->addShape(115, 0);
+ alignment1216034904->addShape(124, 0);
+ ccs.push_back(alignment1216034904);
+ AlignmentConstraint *alignment1216034968 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216034968->addShape(104, 0);
+ ccs.push_back(alignment1216034968);
+ AlignmentConstraint *alignment1216035032 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216035032->addShape(117, 0);
+ ccs.push_back(alignment1216035032);
+ AlignmentConstraint *alignment1216035096 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216035096->addShape(135, 0);
+ ccs.push_back(alignment1216035096);
+ AlignmentConstraint *alignment1216035160 = new AlignmentConstraint((vpsc::Dim) 0, 0);
+ alignment1216035160->addShape(139, 0);
+ ccs.push_back(alignment1216035160);
+#endif
+
+#if 1
+ AlignmentConstraint *alignment1216035224 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216035224->addShape(0, 0);
+ alignment1216035224->addShape(7, 0);
+ alignment1216035224->addShape(8, 0);
+ ccs.push_back(alignment1216035224);
+ AlignmentConstraint *alignment1216035288 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216035288->addShape(1, 0);
+ alignment1216035288->addShape(6, 0);
+ alignment1216035288->addShape(39, 0);
+ alignment1216035288->addShape(60, 0);
+ alignment1216035288->addShape(68, 0);
+ alignment1216035288->addShape(91, 0);
+ alignment1216035288->addShape(93, 0);
+ alignment1216035288->addShape(132, 0);
+ ccs.push_back(alignment1216035288);
+ AlignmentConstraint *alignment1216035352 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216035352->addShape(2, 0);
+ alignment1216035352->addShape(77, 0);
+ alignment1216035352->addShape(79, 0);
+ ccs.push_back(alignment1216035352);
+ AlignmentConstraint *alignment1216035416 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216035416->addShape(3, 0);
+ alignment1216035416->addShape(61, 0);
+ alignment1216035416->addShape(66, 0);
+ ccs.push_back(alignment1216035416);
+ AlignmentConstraint *alignment1216035480 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216035480->addShape(4, 0);
+ alignment1216035480->addShape(22, 0);
+ alignment1216035480->addShape(23, 0);
+ alignment1216035480->addShape(107, 0);
+ ccs.push_back(alignment1216035480);
+ AlignmentConstraint *alignment1216035544 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216035544->addShape(5, 0);
+ ccs.push_back(alignment1216035544);
+ AlignmentConstraint *alignment1216035608 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216035608->addShape(9, 0);
+ alignment1216035608->addShape(96, 0);
+ ccs.push_back(alignment1216035608);
+ AlignmentConstraint *alignment1216042672 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216042672->addShape(10, 0);
+ alignment1216042672->addShape(97, 0);
+ alignment1216042672->addShape(123, 0);
+ ccs.push_back(alignment1216042672);
+ AlignmentConstraint *alignment1216042736 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216042736->addShape(11, 0);
+ alignment1216042736->addShape(12, 0);
+ alignment1216042736->addShape(13, 0);
+ alignment1216042736->addShape(59, 0);
+ alignment1216042736->addShape(62, 0);
+ alignment1216042736->addShape(63, 0);
+ alignment1216042736->addShape(65, 0);
+ alignment1216042736->addShape(67, 0);
+ alignment1216042736->addShape(98, 0);
+ ccs.push_back(alignment1216042736);
+ AlignmentConstraint *alignment1216042800 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216042800->addShape(14, 0);
+ ccs.push_back(alignment1216042800);
+ AlignmentConstraint *alignment1216042864 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216042864->addShape(15, 0);
+ alignment1216042864->addShape(101, 0);
+ ccs.push_back(alignment1216042864);
+ AlignmentConstraint *alignment1216042928 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216042928->addShape(16, 0);
+ alignment1216042928->addShape(102, 0);
+ alignment1216042928->addShape(133, 0);
+ ccs.push_back(alignment1216042928);
+ AlignmentConstraint *alignment1216042992 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216042992->addShape(17, 0);
+ alignment1216042992->addShape(103, 0);
+ ccs.push_back(alignment1216042992);
+ AlignmentConstraint *alignment1216043056 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216043056->addShape(18, 0);
+ alignment1216043056->addShape(81, 0);
+ alignment1216043056->addShape(104, 0);
+ alignment1216043056->addShape(135, 0);
+ ccs.push_back(alignment1216043056);
+ AlignmentConstraint *alignment1216043120 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216043120->addShape(19, 0);
+ ccs.push_back(alignment1216043120);
+ AlignmentConstraint *alignment1216043184 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216043184->addShape(20, 0);
+ alignment1216043184->addShape(52, 0);
+ alignment1216043184->addShape(89, 0);
+ ccs.push_back(alignment1216043184);
+ AlignmentConstraint *alignment1216043248 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216043248->addShape(21, 0);
+ alignment1216043248->addShape(105, 0);
+ alignment1216043248->addShape(106, 0);
+ ccs.push_back(alignment1216043248);
+ AlignmentConstraint *alignment1216043312 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216043312->addShape(24, 0);
+ alignment1216043312->addShape(47, 0);
+ alignment1216043312->addShape(125, 0);
+ ccs.push_back(alignment1216043312);
+ AlignmentConstraint *alignment1216043376 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216043376->addShape(25, 0);
+ alignment1216043376->addShape(30, 0);
+ alignment1216043376->addShape(31, 0);
+ alignment1216043376->addShape(32, 0);
+ alignment1216043376->addShape(110, 0);
+ alignment1216043376->addShape(115, 0);
+ alignment1216043376->addShape(116, 0);
+ alignment1216043376->addShape(117, 0);
+ alignment1216043376->addShape(126, 0);
+ ccs.push_back(alignment1216043376);
+ AlignmentConstraint *alignment1216043440 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216043440->addShape(26, 0);
+ alignment1216043440->addShape(111, 0);
+ alignment1216043440->addShape(118, 0);
+ ccs.push_back(alignment1216043440);
+ AlignmentConstraint *alignment1216043504 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216043504->addShape(27, 0);
+ alignment1216043504->addShape(29, 0);
+ alignment1216043504->addShape(51, 0);
+ alignment1216043504->addShape(53, 0);
+ alignment1216043504->addShape(55, 0);
+ ccs.push_back(alignment1216043504);
+ AlignmentConstraint *alignment1216043568 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216043568->addShape(28, 0);
+ ccs.push_back(alignment1216043568);
+ AlignmentConstraint *alignment1216043632 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216043632->addShape(33, 0);
+ alignment1216043632->addShape(50, 0);
+ alignment1216043632->addShape(54, 0);
+ ccs.push_back(alignment1216043632);
+ AlignmentConstraint *alignment1216043696 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216043696->addShape(34, 0);
+ ccs.push_back(alignment1216043696);
+ AlignmentConstraint *alignment1216043760 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216043760->addShape(35, 0);
+ alignment1216043760->addShape(122, 0);
+ ccs.push_back(alignment1216043760);
+ AlignmentConstraint *alignment1216043824 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216043824->addShape(36, 0);
+ alignment1216043824->addShape(119, 0);
+ ccs.push_back(alignment1216043824);
+ AlignmentConstraint *alignment1216043888 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216043888->addShape(37, 0);
+ ccs.push_back(alignment1216043888);
+ AlignmentConstraint *alignment1216043952 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216043952->addShape(38, 0);
+ ccs.push_back(alignment1216043952);
+ AlignmentConstraint *alignment1216044016 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216044016->addShape(40, 0);
+ alignment1216044016->addShape(86, 0);
+ alignment1216044016->addShape(124, 0);
+ ccs.push_back(alignment1216044016);
+ AlignmentConstraint *alignment1216044080 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216044080->addShape(41, 0);
+ ccs.push_back(alignment1216044080);
+ AlignmentConstraint *alignment1216044144 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216044144->addShape(42, 0);
+ ccs.push_back(alignment1216044144);
+ AlignmentConstraint *alignment1216044208 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216044208->addShape(43, 0);
+ alignment1216044208->addShape(45, 0);
+ alignment1216044208->addShape(70, 0);
+ alignment1216044208->addShape(71, 0);
+ ccs.push_back(alignment1216044208);
+ AlignmentConstraint *alignment1216044272 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216044272->addShape(44, 0);
+ alignment1216044272->addShape(46, 0);
+ alignment1216044272->addShape(72, 0);
+ alignment1216044272->addShape(73, 0);
+ alignment1216044272->addShape(108, 0);
+ ccs.push_back(alignment1216044272);
+ AlignmentConstraint *alignment1216044336 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216044336->addShape(48, 0);
+ alignment1216044336->addShape(109, 0);
+ ccs.push_back(alignment1216044336);
+ AlignmentConstraint *alignment1216044400 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216044400->addShape(49, 0);
+ ccs.push_back(alignment1216044400);
+ AlignmentConstraint *alignment1216044464 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216044464->addShape(56, 0);
+ alignment1216044464->addShape(76, 0);
+ ccs.push_back(alignment1216044464);
+ AlignmentConstraint *alignment1216044528 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216044528->addShape(57, 0);
+ alignment1216044528->addShape(137, 0);
+ ccs.push_back(alignment1216044528);
+ AlignmentConstraint *alignment1216044592 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216044592->addShape(58, 0);
+ alignment1216044592->addShape(82, 0);
+ alignment1216044592->addShape(85, 0);
+ alignment1216044592->addShape(88, 0);
+ alignment1216044592->addShape(139, 0);
+ ccs.push_back(alignment1216044592);
+ AlignmentConstraint *alignment1216021552 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216021552->addShape(64, 0);
+ ccs.push_back(alignment1216021552);
+ AlignmentConstraint *alignment1216021616 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216021616->addShape(69, 0);
+ ccs.push_back(alignment1216021616);
+ AlignmentConstraint *alignment1216021680 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216021680->addShape(74, 0);
+ ccs.push_back(alignment1216021680);
+ AlignmentConstraint *alignment1216021744 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216021744->addShape(75, 0);
+ ccs.push_back(alignment1216021744);
+ AlignmentConstraint *alignment1216021808 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216021808->addShape(78, 0);
+ alignment1216021808->addShape(138, 0);
+ ccs.push_back(alignment1216021808);
+ AlignmentConstraint *alignment1216021872 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216021872->addShape(80, 0);
+ ccs.push_back(alignment1216021872);
+ AlignmentConstraint *alignment1216021936 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216021936->addShape(83, 0);
+ ccs.push_back(alignment1216021936);
+ AlignmentConstraint *alignment1216022000 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216022000->addShape(84, 0);
+ ccs.push_back(alignment1216022000);
+ AlignmentConstraint *alignment1216022064 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216022064->addShape(87, 0);
+ ccs.push_back(alignment1216022064);
+ AlignmentConstraint *alignment1216022128 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216022128->addShape(90, 0);
+ alignment1216022128->addShape(95, 0);
+ ccs.push_back(alignment1216022128);
+ AlignmentConstraint *alignment1216022192 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216022192->addShape(92, 0);
+ alignment1216022192->addShape(134, 0);
+ ccs.push_back(alignment1216022192);
+ AlignmentConstraint *alignment1216022256 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216022256->addShape(94, 0);
+ ccs.push_back(alignment1216022256);
+ AlignmentConstraint *alignment1216022320 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216022320->addShape(99, 0);
+ alignment1216022320->addShape(100, 0);
+ ccs.push_back(alignment1216022320);
+ AlignmentConstraint *alignment1216022384 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216022384->addShape(112, 0);
+ alignment1216022384->addShape(114, 0);
+ ccs.push_back(alignment1216022384);
+ AlignmentConstraint *alignment1216022448 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216022448->addShape(113, 0);
+ alignment1216022448->addShape(120, 0);
+ ccs.push_back(alignment1216022448);
+ AlignmentConstraint *alignment1216022512 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216022512->addShape(121, 0);
+ ccs.push_back(alignment1216022512);
+ AlignmentConstraint *alignment1216022576 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216022576->addShape(127, 0);
+ alignment1216022576->addShape(129, 0);
+ ccs.push_back(alignment1216022576);
+ AlignmentConstraint *alignment1216022640 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216022640->addShape(128, 0);
+ alignment1216022640->addShape(130, 0);
+ ccs.push_back(alignment1216022640);
+ AlignmentConstraint *alignment1216022704 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216022704->addShape(131, 0);
+ ccs.push_back(alignment1216022704);
+ AlignmentConstraint *alignment1216022768 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216022768->addShape(136, 0);
+ alignment1216022768->addShape(141, 0);
+ ccs.push_back(alignment1216022768);
+ AlignmentConstraint *alignment1216022832 = new AlignmentConstraint((vpsc::Dim) 1, 0);
+ alignment1216022832->addShape(140, 0);
+ ccs.push_back(alignment1216022832);
+#endif
+
+ ConstrainedFDLayout alg(rs, es, defaultEdgeLength);
+ alg.setAvoidNodeOverlaps(true);
+ alg.setConstraints(ccs);
+ alg.makeFeasible();
+ alg.outputInstanceToSVG();
+ //alg.run();
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libcola/tests/makemovie.sh b/src/3rdparty/adaptagrams/libcola/tests/makemovie.sh
new file mode 100644
index 0000000..cd571f9
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/makemovie.sh
@@ -0,0 +1,10 @@
+pattern=containment
+width=200
+height=260
+rm ${pattern}*.pdf
+for file in ${pattern}*.svg
+do
+ echo adding $file...
+ inkscape -w$width -h$height -A ${file%.svg}.pdf $file 2> /dev/null
+done
+convert -page ${width}x${height} -delay 15 ${pattern}*.pdf $pattern.gif
diff --git a/src/3rdparty/adaptagrams/libcola/tests/max_acyclic_subgraph.cpp b/src/3rdparty/adaptagrams/libcola/tests/max_acyclic_subgraph.cpp
new file mode 100644
index 0000000..cb2eb38
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/max_acyclic_subgraph.cpp
@@ -0,0 +1,346 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+#include <iostream>
+#include <vector>
+#include <assert.h>
+#include <libcola/cola.h>
+#include <libcola/max_acyclic_subgraph.h>
+#include "graphlayouttest.h"
+
+using namespace std;
+using namespace cola;
+using vpsc::Rectangle;
+
+int main() {
+ MaxAcyclicSubgraph *mas;
+ Edges case_a, case_b, case_c, case_d, case_e, case_f;
+ Edges *subgraph = nullptr;
+
+ vector<Rectangle *> rs;
+ unsigned V;
+
+ // create case A
+ // case A consists of a basic graph where the start point is a source
+ cout << endl << "ENTERING CASE A" << endl;
+ V = 5;
+ case_a.push_back(Edge(0, 1));
+ case_a.push_back(Edge(1, 2));
+ case_a.push_back(Edge(2, 3));
+ case_a.push_back(Edge(3, 4));
+ case_a.push_back(Edge(4, 1));
+
+ // detect the subgraph
+ mas = new MaxAcyclicSubgraph(V, &case_a);
+ subgraph = mas->find_subgraph();
+
+ if (subgraph != nullptr) {
+ cout << "subgraph->size(): " << subgraph->size() << endl;
+ cout << "Ea: ";
+ for (unsigned i = 0; i < subgraph->size(); i++) {
+ // print out the subgraph
+ cout << "(" << (*subgraph)[i].first << ", " << (*subgraph)[i].second << ") ";
+ }
+
+ cout << endl;
+
+ // output a picture
+ rs.push_back(new Rectangle(10,10+5,10,10+5));
+ rs.push_back(new Rectangle(30,30+5,30,30+5));
+ rs.push_back(new Rectangle(30,30+5,60,60+5));
+ rs.push_back(new Rectangle(65,65+5,60,60+5));
+ rs.push_back(new Rectangle(65,65+5,30,30+5));
+
+ assert(rs.size() == V);
+
+ output_svg(rs, case_a, "mas_case_a.svg", false, true, subgraph);
+ for (unsigned i = 0; i < rs.size(); i++) { delete rs[i]; }
+ rs.clear();
+
+ delete subgraph;
+ }
+ else {
+ cout << "No subgraph found" << endl;
+ }
+
+ // create case B
+ // case B is the same graph of case A but with more elements
+ cout << endl << "ENTERING CASE B" << endl;
+ V = 7;
+ case_b.push_back(Edge(0, 1));
+ case_b.push_back(Edge(1, 2));
+ case_b.push_back(Edge(2, 3));
+ case_b.push_back(Edge(3, 4));
+ case_b.push_back(Edge(4, 1));
+ case_b.push_back(Edge(5, 2));
+ case_b.push_back(Edge(6, 5));
+
+ // detect the subgraph
+ mas->mod_graph(V, &case_b);
+ subgraph = mas->find_subgraph();
+
+ if (subgraph != nullptr) {
+ cout << "subgraph->size(): " << subgraph->size() << endl;
+ cout << "Ea: ";
+ for (unsigned i = 0; i < subgraph->size(); i++) {
+ // print out the subgraph
+ cout << "(" << (*subgraph)[i].first << ", " << (*subgraph)[i].second << ") ";
+ }
+
+ cout << endl;
+
+ // output a picture
+ rs.push_back(new Rectangle(10,10+5,10,10+5));
+ rs.push_back(new Rectangle(30,30+5,30,30+5));
+ rs.push_back(new Rectangle(30,30+5,60,60+5));
+ rs.push_back(new Rectangle(65,65+5,60,60+5));
+ rs.push_back(new Rectangle(65,65+5,30,30+5));
+ rs.push_back(new Rectangle(30,30+5,90,90+5));
+ rs.push_back(new Rectangle(65,65+5,90,90+5));
+
+ assert(rs.size() == V);
+
+ output_svg(rs, case_b, "mas_case_b.svg", false, true, subgraph);
+ for (unsigned i = 0; i < rs.size(); i++) { delete rs[i]; }
+ rs.clear();
+
+ delete subgraph;
+ }
+ else {
+ cout << "No subgraph found" << endl;
+ }
+
+ // create case C
+ // case C is a more complicated graph with nested subgraph
+ cout << endl << "ENTERING CASE C" << endl;
+ V = 14;
+ case_c.push_back(Edge(0, 1));
+ case_c.push_back(Edge(0, 5));
+ case_c.push_back(Edge(0, 6));
+ case_c.push_back(Edge(2, 0));
+ case_c.push_back(Edge(3, 5));
+ case_c.push_back(Edge(4, 3));
+ case_c.push_back(Edge(5, 4));
+ case_c.push_back(Edge(5, 13));
+ case_c.push_back(Edge(6, 2));
+ case_c.push_back(Edge(6, 9));
+ case_c.push_back(Edge(7, 6));
+ case_c.push_back(Edge(8, 7));
+ case_c.push_back(Edge(9, 10));
+ case_c.push_back(Edge(9, 11));
+ case_c.push_back(Edge(9, 12));
+ case_c.push_back(Edge(10, 6));
+ case_c.push_back(Edge(12, 10));
+ case_c.push_back(Edge(13, 4));
+
+ // detect the subgraph
+ mas->mod_graph(V, &case_c);
+ subgraph = mas->find_subgraph();
+
+ if (subgraph != nullptr) {
+ cout << "subgraph->size(): " << subgraph->size() << endl;
+ cout << "Ea: ";
+ for (unsigned i = 0; i < subgraph->size(); i++) {
+ // print out the subgraph
+ cout << "(" << (*subgraph)[i].first << ", " << (*subgraph)[i].second << ") ";
+ }
+
+ cout << endl;
+
+ // output a picture
+ rs.push_back(new Rectangle(10,10+5,10,10+5)); // node 0
+ rs.push_back(new Rectangle(20,20+5,40,40+5)); // node 1
+ rs.push_back(new Rectangle(40,40+5,30,30+5)); // node 2
+ rs.push_back(new Rectangle(30,30+5,60,60+5)); // node 3
+ rs.push_back(new Rectangle(60,60+5,60,60+5)); // node 4
+ rs.push_back(new Rectangle(10,10+5,90,90+5)); // node 5
+ rs.push_back(new Rectangle(80,80+5,15,15+5)); // node 6
+ rs.push_back(new Rectangle(110,110+5,15,15+5)); // node 7
+ rs.push_back(new Rectangle(140,140+5,15,15+5)); // node 8
+ rs.push_back(new Rectangle(110,110+5,60,60+5)); // node 9
+ rs.push_back(new Rectangle(100,100+5,85,85+5)); // node 10
+ rs.push_back(new Rectangle(140,140+5,50,50+5)); // node 11
+ rs.push_back(new Rectangle(140,140+5,70,70+5)); // node 12
+ rs.push_back(new Rectangle(45,45+5,90,90+5)); // node 13
+
+ assert(rs.size() == V);
+
+ output_svg(rs, case_c, "mas_case_c.svg", false, true, subgraph);
+ for(int i = 0; i < V; i++) { delete rs[i]; }
+ rs.clear();
+ delete subgraph;
+ }
+ else {
+ cout << "No subgraph found" << endl;
+ }
+
+ // create case D
+ // case D consists of the same graph as case A but with a different starting location
+ cout << endl << "ENTERING CASE D" << endl;
+ V = 5;
+ case_d.push_back(Edge(0, 1));
+ case_d.push_back(Edge(1, 2));
+ case_d.push_back(Edge(2, 3));
+ case_d.push_back(Edge(3, 0));
+ case_d.push_back(Edge(4, 1));
+
+ // detect the subgraph
+ mas->mod_graph(V, &case_d);
+ subgraph = mas->find_subgraph();
+
+ if (subgraph != nullptr) {
+ cout << "subgraph->size(): " << subgraph->size() << endl;
+ cout << "Ea: ";
+ for (unsigned i = 0; i < subgraph->size(); i++) {
+ // print out the subgraph
+ cout << "(" << (*subgraph)[i].first << ", " << (*subgraph)[i].second << ") ";
+ }
+
+ cout << endl;
+
+ // output a picture
+ rs.push_back(new Rectangle(65,65+5,60,60+5));
+ rs.push_back(new Rectangle(65,65+5,30,30+5));
+ rs.push_back(new Rectangle(30,30+5,30,30+5));
+ rs.push_back(new Rectangle(30,30+5,60,60+5));
+ rs.push_back(new Rectangle(10,10+5,10,10+5));
+
+ assert(rs.size() == V);
+
+ output_svg(rs, case_d, "mas_case_d.svg", false, true, subgraph);
+ for (unsigned i = 0; i < rs.size(); i++) { delete rs[i]; }
+ rs.clear();
+ delete subgraph;
+ }
+ else {
+ cout << "No subgraph found" << endl;
+ }
+
+ // create case E
+ // case E is a reordering of case C
+ cout << endl << "ENTERING CASE E" << endl;
+ V = 14;
+ case_e.push_back(Edge(0, 6));
+ case_e.push_back(Edge(0, 9));
+ case_e.push_back(Edge(1, 4));
+ case_e.push_back(Edge(3, 10));
+ case_e.push_back(Edge(4, 3));
+ case_e.push_back(Edge(5, 0));
+ case_e.push_back(Edge(6, 7));
+ case_e.push_back(Edge(7, 0));
+ case_e.push_back(Edge(7, 2));
+ case_e.push_back(Edge(7, 10));
+ case_e.push_back(Edge(8, 5));
+ case_e.push_back(Edge(9, 12));
+ case_e.push_back(Edge(9, 11));
+ case_e.push_back(Edge(9, 13));
+ case_e.push_back(Edge(10, 1));
+ case_e.push_back(Edge(10, 4));
+ case_e.push_back(Edge(12, 0));
+ case_e.push_back(Edge(11, 12));
+
+ // detect the subgraph
+ mas->mod_graph(V, &case_e);
+ subgraph = mas->find_subgraph();
+ if (subgraph != nullptr) {
+ cout << "subgraph->size(): " << subgraph->size() << endl;
+ cout << "Ea: ";
+ for (unsigned i = 0; i < subgraph->size(); i++) {
+ // print out the subgraph
+ cout << "(" << (*subgraph)[i].first << ", " << (*subgraph)[i].second << ") ";
+ }
+
+ cout << endl;
+
+ // output a picture
+ rs.push_back(new Rectangle(80,80+5,15,15+5)); // node 6
+ rs.push_back(new Rectangle(45,45+5,90,90+5)); // node 13
+ rs.push_back(new Rectangle(20,20+5,40,40+5)); // node 1
+ rs.push_back(new Rectangle(30,30+5,60,60+5)); // node 3
+ rs.push_back(new Rectangle(60,60+5,60,60+5)); // node 4
+ rs.push_back(new Rectangle(110,110+5,15,15+5)); // node 7
+ rs.push_back(new Rectangle(40,40+5,30,30+5)); // node 2
+ rs.push_back(new Rectangle(10,10+5,10,10+5)); // node 0
+ rs.push_back(new Rectangle(140,140+5,15,15+5)); // node 8
+ rs.push_back(new Rectangle(110,110+5,60,60+5)); // node 9
+ rs.push_back(new Rectangle(10,10+5,90,90+5)); // node 5
+ rs.push_back(new Rectangle(140,140+5,70,70+5)); // node 12
+ rs.push_back(new Rectangle(100,100+5,85,85+5)); // node 10
+ rs.push_back(new Rectangle(140,140+5,50,50+5)); // node 11
+
+ assert(rs.size() == V);
+
+ output_svg(rs, case_e, "mas_case_e.svg", false, true, subgraph);
+ for(int i = 0; i < V; i++) { delete rs[i]; }
+ rs.clear();
+ delete subgraph;
+ }
+ else {
+ cout << "No subgraph found" << endl;
+ }
+
+ // create case F
+ // case F consists of the same graph with sinks
+ cout << endl << "ENTERING CASE F" << endl;
+ V = 3;
+ case_f.push_back(Edge(0, 1));
+ case_f.push_back(Edge(0, 2));
+ case_f.push_back(Edge(1, 2));
+
+ // detect the subgraph
+ mas->mod_graph(V, &case_f);
+ subgraph = mas->find_subgraph();
+
+ if (subgraph != nullptr) {
+ cout << "subgraph->size(): " << subgraph->size() << endl;
+ cout << "Ea: ";
+ for (unsigned i = 0; i < subgraph->size(); i++) {
+ // print out the subgraph
+ cout << "(" << (*subgraph)[i].first << ", " << (*subgraph)[i].second << ") ";
+ }
+
+ cout << endl;
+
+ // output a picture
+ rs.push_back(new Rectangle(10,10+5,10,10+5));
+ rs.push_back(new Rectangle(40,40+5,30,30+5));
+ rs.push_back(new Rectangle(15,15+5,60,60+5));
+
+ assert(rs.size() == V);
+
+ output_svg(rs, case_f, "mas_case_f.svg", false, true, subgraph);
+ for (unsigned i = 0; i < rs.size(); i++) { delete rs[i]; }
+ rs.clear();
+ delete subgraph;
+ }
+ else {
+ cout << "No subgraph found" << endl;
+ }
+
+ // END TEST
+ delete mas;
+
+ return 0;
+}
diff --git a/src/3rdparty/adaptagrams/libcola/tests/overlappingClusters01.cpp b/src/3rdparty/adaptagrams/libcola/tests/overlappingClusters01.cpp
new file mode 100644
index 0000000..6031c71
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/overlappingClusters01.cpp
@@ -0,0 +1,333 @@
+// Based on debug file from Christoph Daniel Schulze
+// cgraph_3_after_layout.svg
+#include <vector>
+#include <utility>
+#include "libcola/cola.h"
+using namespace cola;
+int main(void) {
+ CompoundConstraints ccs;
+ std::vector<Edge> es;
+ EdgeLengths eLengths;
+ double defaultEdgeLength=50;
+ std::vector<vpsc::Rectangle*> rs;
+ vpsc::Rectangle *rect = nullptr;
+
+ rect = new vpsc::Rectangle(245.517, 247.517, 279.574, 281.574);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(222.742, 224.742, 318.708, 320.708);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(460.345, 462.345, 716.936, 718.936);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(607.846, 609.846, 665.496, 667.496);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(640.191, 642.191, 637.391, 639.391);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(743.519, 745.519, 865.48, 867.48);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(807.112, 809.112, 759.798, 761.798);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(807.112, 809.112, 699.132, 701.132);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(121.997, 123.997, 221.049, 223.049);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(224.354, 226.354, 80, 82);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(448.583, 450.583, 517.722, 519.722);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(460.345, 462.345, 639.516, 641.516);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(607.846, 609.846, 583.991, 585.991);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(607.846, 609.846, 684.476, 686.476);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(625.623, 627.623, 602.774, 604.774);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(289.325, 291.325, 455.243, 457.243);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(207.785, 209.785, 222.762, 224.762);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(159.658, 161.658, 254.197, 256.197);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(650.816, 652.816, 809.48, 811.48);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(685.012, 687.012, 795.932, 797.932);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(751.112, 753.112, 643.132, 645.132);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(751.112, 753.112, 608.903, 610.903);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(320.184, 322.184, 377.132, 379.132);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(336.233, 338.233, 382.124, 384.124);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(153.571, 155.571, 391.657, 393.657);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(405.396, 407.396, 745.874, 747.874);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(460.345, 462.345, 727.442, 729.442);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(551.846, 553.846, 527.991, 529.991);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(669.714, 671.714, 583.991, 585.991);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(171.168, 221.168, 258.197, 308.197);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(110.328, 160.328, 266.708, 316.708);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(217.18, 267.18, 109.481, 159.481);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(632.075, 682.075, 858.531, 908.531);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(689.012, 739.012, 813.48, 863.48);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(755.112, 805.112, 647.132, 697.132);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(786.403, 836.403, 560.258, 610.258);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(261.651, 311.651, 247.06, 297.06);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(304.164, 354.164, 322.708, 372.708);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(70, 120, 325.132, 375.132);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(353.92, 403.92, 770.169, 820.169);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(464.345, 514.345, 749.874, 799.874);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(555.846, 605.846, 531.991, 581.991);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(696.038, 746.038, 531.991, 581.991);
+ rs.push_back(rect);
+
+ es.push_back(std::make_pair(0, 1));
+ es.push_back(std::make_pair(0, 22));
+ es.push_back(std::make_pair(1, 23));
+ es.push_back(std::make_pair(1, 24));
+ es.push_back(std::make_pair(2, 3));
+ es.push_back(std::make_pair(2, 25));
+ es.push_back(std::make_pair(3, 4));
+ es.push_back(std::make_pair(3, 26));
+ es.push_back(std::make_pair(3, 27));
+ es.push_back(std::make_pair(4, 28));
+ es.push_back(std::make_pair(5, 6));
+ es.push_back(std::make_pair(5, 18));
+ es.push_back(std::make_pair(6, 7));
+ es.push_back(std::make_pair(6, 19));
+ es.push_back(std::make_pair(6, 20));
+ es.push_back(std::make_pair(7, 21));
+ es.push_back(std::make_pair(8, 17));
+ es.push_back(std::make_pair(9, 31));
+ es.push_back(std::make_pair(10, 11));
+ es.push_back(std::make_pair(10, 12));
+ es.push_back(std::make_pair(10, 13));
+ es.push_back(std::make_pair(10, 14));
+ es.push_back(std::make_pair(10, 15));
+ es.push_back(std::make_pair(10, 22));
+ es.push_back(std::make_pair(10, 23));
+ es.push_back(std::make_pair(11, 12));
+ es.push_back(std::make_pair(11, 25));
+ es.push_back(std::make_pair(11, 26));
+ es.push_back(std::make_pair(12, 27));
+ es.push_back(std::make_pair(12, 28));
+ es.push_back(std::make_pair(13, 14));
+ es.push_back(std::make_pair(13, 18));
+ es.push_back(std::make_pair(13, 19));
+ es.push_back(std::make_pair(14, 20));
+ es.push_back(std::make_pair(14, 21));
+ es.push_back(std::make_pair(15, 24));
+ es.push_back(std::make_pair(16, 17));
+ es.push_back(std::make_pair(16, 36));
+ es.push_back(std::make_pair(17, 29));
+ es.push_back(std::make_pair(17, 30));
+ es.push_back(std::make_pair(18, 32));
+ es.push_back(std::make_pair(19, 33));
+ es.push_back(std::make_pair(20, 34));
+ es.push_back(std::make_pair(21, 35));
+ es.push_back(std::make_pair(22, 36));
+ es.push_back(std::make_pair(23, 37));
+ es.push_back(std::make_pair(24, 38));
+ es.push_back(std::make_pair(25, 39));
+ es.push_back(std::make_pair(26, 40));
+ es.push_back(std::make_pair(27, 41));
+ es.push_back(std::make_pair(28, 42));
+ es.push_back(std::make_pair(31, 36));
+ es.push_back(std::make_pair(32, 33));
+ es.push_back(std::make_pair(34, 35));
+ es.push_back(std::make_pair(36, 37));
+ es.push_back(std::make_pair(39, 40));
+ es.push_back(std::make_pair(41, 42));
+
+ double padding = 6;
+ ConstrainedFDLayout alg(rs, es, defaultEdgeLength, eLengths);
+ alg.setAvoidNodeOverlaps(true);
+ RootCluster *cluster140389150311456 = new RootCluster();
+ cluster140389150311456->addChildNode(0);
+ cluster140389150311456->addChildNode(1);
+ cluster140389150311456->addChildNode(2);
+ cluster140389150311456->addChildNode(3);
+ cluster140389150311456->addChildNode(4);
+ cluster140389150311456->addChildNode(5);
+ cluster140389150311456->addChildNode(6);
+ cluster140389150311456->addChildNode(7);
+ cluster140389150311456->addChildNode(8);
+ cluster140389150311456->addChildNode(9);
+ cluster140389150311456->addChildNode(10);
+ cluster140389150311456->addChildNode(11);
+ cluster140389150311456->addChildNode(12);
+ cluster140389150311456->addChildNode(13);
+ cluster140389150311456->addChildNode(14);
+ cluster140389150311456->addChildNode(15);
+ cluster140389150311456->addChildNode(16);
+ cluster140389150311456->addChildNode(17);
+ cluster140389150311456->addChildNode(18);
+ cluster140389150311456->addChildNode(19);
+ cluster140389150311456->addChildNode(20);
+ cluster140389150311456->addChildNode(21);
+ cluster140389150311456->addChildNode(22);
+ cluster140389150311456->addChildNode(23);
+ cluster140389150311456->addChildNode(24);
+ cluster140389150311456->addChildNode(25);
+ cluster140389150311456->addChildNode(26);
+ cluster140389150311456->addChildNode(27);
+ cluster140389150311456->addChildNode(28);
+ RectangularCluster *cluster140389152494880 = new RectangularCluster();
+ cluster140389152494880->setPadding(padding);
+ cluster140389152494880->addChildNode(36);
+ cluster140389150311456->addChildCluster(cluster140389152494880);
+ RectangularCluster *cluster140389150048048 = new RectangularCluster();
+ cluster140389150048048->setPadding(padding);
+ cluster140389150048048->addChildNode(38);
+ cluster140389150048048->addChildNode(37);
+ cluster140389150311456->addChildCluster(cluster140389150048048);
+ RectangularCluster *cluster140389150180400 = new RectangularCluster();
+ cluster140389150180400->setPadding(padding);
+ cluster140389150180400->addChildNode(30);
+ cluster140389150180400->addChildNode(29);
+ cluster140389150311456->addChildCluster(cluster140389150180400);
+ RectangularCluster *cluster140389150298288 = new RectangularCluster();
+ cluster140389150298288->setPadding(padding);
+ cluster140389150298288->addChildNode(39);
+ cluster140389150311456->addChildCluster(cluster140389150298288);
+ RectangularCluster *cluster140389150179600 = new RectangularCluster();
+ cluster140389150179600->setPadding(padding);
+ cluster140389150179600->addChildNode(41);
+ cluster140389150179600->addChildNode(40);
+ cluster140389150311456->addChildCluster(cluster140389150179600);
+ RectangularCluster *cluster140389150131760 = new RectangularCluster();
+ cluster140389150131760->setPadding(padding);
+ cluster140389150131760->addChildNode(42);
+ cluster140389150311456->addChildCluster(cluster140389150131760);
+ RectangularCluster *cluster140389150091712 = new RectangularCluster();
+ cluster140389150091712->setPadding(padding);
+ cluster140389150091712->addChildNode(32);
+ cluster140389150311456->addChildCluster(cluster140389150091712);
+ RectangularCluster *cluster140389152581264 = new RectangularCluster();
+ cluster140389152581264->setPadding(padding);
+ cluster140389152581264->addChildNode(34);
+ cluster140389152581264->addChildNode(33);
+ cluster140389150311456->addChildCluster(cluster140389152581264);
+ RectangularCluster *cluster140389144224352 = new RectangularCluster();
+ cluster140389144224352->setPadding(padding);
+ cluster140389144224352->addChildNode(35);
+ cluster140389150311456->addChildCluster(cluster140389144224352);
+ RectangularCluster *cluster140389144198304 = new RectangularCluster();
+ cluster140389144198304->setPadding(padding);
+ cluster140389144198304->addChildNode(30);
+ cluster140389144198304->addChildNode(29);
+ cluster140389150311456->addChildCluster(cluster140389144198304);
+ RectangularCluster *cluster140389144177184 = new RectangularCluster();
+ cluster140389144177184->setPadding(padding);
+ cluster140389144177184->addChildNode(31);
+ cluster140389150311456->addChildCluster(cluster140389144177184);
+ RectangularCluster *cluster140389144168944 = new RectangularCluster();
+ cluster140389144168944->setPadding(padding);
+ cluster140389144168944->addChildNode(36);
+ cluster140389144168944->addChildNode(37);
+ cluster140389150311456->addChildCluster(cluster140389144168944);
+ RectangularCluster *cluster140389144228288 = new RectangularCluster();
+ cluster140389144228288->setPadding(padding);
+ cluster140389144228288->addChildNode(39);
+ cluster140389144228288->addChildNode(40);
+ cluster140389150311456->addChildCluster(cluster140389144228288);
+ RectangularCluster *cluster140389144244064 = new RectangularCluster();
+ cluster140389144228288->setPadding(padding);
+ cluster140389144244064->addChildNode(42);
+ cluster140389144244064->addChildNode(41);
+ cluster140389150311456->addChildCluster(cluster140389144244064);
+ RectangularCluster *cluster140389144206000 = new RectangularCluster();
+ cluster140389144206000->setPadding(padding);
+ cluster140389144206000->addChildNode(32);
+ cluster140389144206000->addChildNode(33);
+ cluster140389150311456->addChildCluster(cluster140389144206000);
+ RectangularCluster *cluster140389144175920 = new RectangularCluster();
+ cluster140389144175920->setPadding(padding);
+ cluster140389144175920->addChildNode(35);
+ cluster140389144175920->addChildNode(34);
+ cluster140389150311456->addChildCluster(cluster140389144175920);
+ RectangularCluster *cluster140389144214752 = new RectangularCluster();
+ cluster140389144214752->setPadding(padding);
+ cluster140389144214752->addChildNode(38);
+ cluster140389150311456->addChildCluster(cluster140389144214752);
+ alg.setClusterHierarchy(cluster140389150311456);
+ alg.setConstraints(ccs);
+
+ UnsatisfiableConstraintInfos unsatisfiableX, unsatisfiableY;
+ alg.setUnsatisfiableConstraintInfo(&unsatisfiableX, &unsatisfiableY);
+
+ //alg.makeFeasible();
+ alg.run();
+ //alg.outputInstanceToSVG("overlappingClusters01");
+
+ for (size_t i = 0; i < unsatisfiableX.size(); ++i)
+ {
+ printf("%s\n", unsatisfiableX[i]->toString().c_str());
+ }
+ for (size_t i = 0; i < unsatisfiableY.size(); ++i)
+ {
+ printf("%s\n", unsatisfiableY[i]->toString().c_str());
+ }
+ alg.freeAssociatedObjects();
+ return (unsatisfiableX.empty() && unsatisfiableY.empty()) ? 0 : 1;
+};
diff --git a/src/3rdparty/adaptagrams/libcola/tests/overlappingClusters02.cpp b/src/3rdparty/adaptagrams/libcola/tests/overlappingClusters02.cpp
new file mode 100644
index 0000000..a6bdaf2
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/overlappingClusters02.cpp
@@ -0,0 +1,100 @@
+// Based on Euler Diagram generation example discussed with Aidan Delaney.
+//
+// B
+// +-----------------------------+
+// A | 2 C |
+// +-----------+----------------+ +---+ |
+// | | 1 | | 0 | |
+// | | | +---+ |
+// | 3 +----------------+------------+
+// | |
+// | | 4
+// +----------------------------+
+//
+
+#include <vector>
+#include <utility>
+#include <cstdlib>
+#include "libcola/cola.h"
+using namespace cola;
+int main(void) {
+ CompoundConstraints ccs;
+ std::vector<Edge> es;
+ EdgeLengths eLengths;
+ double defaultEdgeLength=10;
+ std::vector<vpsc::Rectangle*> rs;
+ vpsc::Rectangle *rect = nullptr;
+
+ double width = 5;
+ double height = 5;
+ double pos = 0;
+
+ size_t nodes = 5;
+ for (size_t i = 0; i < nodes; ++i)
+ {
+ rect = new vpsc::Rectangle(pos, pos +width, pos, pos +height);
+ rs.push_back(rect);
+
+ // XXX randomness is needed because COLA doesn't currently untangle
+ // the graph properly if all the nodes begin at the same position.
+ pos += (rand() % 10) - 5;
+ }
+
+ // Euler dual graph (optional)
+ es.push_back(std::make_pair(2, 4));
+ es.push_back(std::make_pair(3, 4));
+ es.push_back(std::make_pair(1, 3));
+ es.push_back(std::make_pair(2, 1));
+ es.push_back(std::make_pair(2, 0));
+
+ // Padding around the inside of clusters.
+ double padding = 3;
+
+ ConstrainedFDLayout alg(rs, es, defaultEdgeLength, eLengths);
+ alg.setAvoidNodeOverlaps(true);
+ RootCluster *rootCluster = new RootCluster();
+
+ // A contains 1, 3
+ RectangularCluster *clusterA = new RectangularCluster();
+ clusterA->setPadding(padding);
+ clusterA->addChildNode(1);
+ clusterA->addChildNode(3);
+
+ // C contains 0
+ RectangularCluster *clusterC = new RectangularCluster();
+ clusterC->setPadding(padding);
+ clusterC->addChildNode(0);
+
+ // B contains 1, 2, C
+ RectangularCluster *clusterB = new RectangularCluster();
+ clusterB->setPadding(padding);
+ clusterB->addChildNode(1);
+ clusterB->addChildNode(2);
+ clusterB->addChildCluster(clusterC);
+
+ // node 4 is in the empty set.
+
+ rootCluster->addChildCluster(clusterA);
+ rootCluster->addChildCluster(clusterB);
+
+ alg.setConstraints(ccs);
+
+ UnsatisfiableConstraintInfos unsatisfiableX, unsatisfiableY;
+ alg.setUnsatisfiableConstraintInfo(&unsatisfiableX, &unsatisfiableY);
+
+ alg.setClusterHierarchy(rootCluster);
+ //alg.makeFeasible();
+ alg.run();
+ alg.outputInstanceToSVG("overlappingClusters02");
+
+ for (size_t i = 0; i < unsatisfiableX.size(); ++i)
+ {
+ printf("%s\n", unsatisfiableX[i]->toString().c_str());
+ }
+ for (size_t i = 0; i < unsatisfiableY.size(); ++i)
+ {
+ printf("%s\n", unsatisfiableY[i]->toString().c_str());
+ }
+ alg.freeAssociatedObjects();
+ return (unsatisfiableX.empty() && unsatisfiableY.empty()) ? 0 : 1;
+};
diff --git a/src/3rdparty/adaptagrams/libcola/tests/overlappingClusters04.cpp b/src/3rdparty/adaptagrams/libcola/tests/overlappingClusters04.cpp
new file mode 100644
index 0000000..45a06ff
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/overlappingClusters04.cpp
@@ -0,0 +1,61 @@
+// From Aidan Delaney: a_b_ab_abc.json.svg
+// Regression test for SEGFAULT caused by specifing an invalid node index 7
+// in cluster description.
+#include <vector>
+#include <utility>
+#include "libcola/cola.h"
+using namespace cola;
+int main(void) {
+ CompoundConstraints ccs;
+ std::vector<Edge> es;
+ EdgeLengths eLengths;
+ double defaultEdgeLength=10;
+ std::vector<vpsc::Rectangle*> rs;
+ vpsc::Rectangle *rect = nullptr;
+
+ rect = new vpsc::Rectangle(0, 5, 0, 5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(-2, 3, -2, 3);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(-1, 4, -1, 4);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1, 6, 1, 6);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1, 6, 1, 6);
+ rs.push_back(rect);
+
+
+ ConstrainedFDLayout alg(rs, es, defaultEdgeLength, eLengths);
+ alg.setAvoidNodeOverlaps(true);
+
+ RootCluster *cluster33771480 = new RootCluster();
+ RectangularCluster *cluster33771952 = new RectangularCluster();
+ cluster33771952->setPadding(Box(2));
+ cluster33771952->addChildNode(1);
+ cluster33771952->addChildNode(3);
+ cluster33771952->addChildNode(7);
+ cluster33771480->addChildCluster(cluster33771952);
+
+ RectangularCluster *cluster33772496 = new RectangularCluster();
+ cluster33772496->setPadding(Box(2));
+ cluster33772496->addChildNode(2);
+ cluster33772496->addChildNode(3);
+ cluster33772496->addChildNode(7);
+ cluster33771480->addChildCluster(cluster33772496);
+
+ RectangularCluster *cluster33773040 = new RectangularCluster();
+ cluster33773040->setPadding(Box(2));
+ cluster33773040->addChildNode(7);
+ cluster33771480->addChildCluster(cluster33773040);
+
+ alg.setClusterHierarchy(cluster33771480);
+
+ alg.setConstraints(ccs);
+ alg.makeFeasible();
+ //alg.outputInstanceToSVG("overlappingCLusters04");
+ alg.freeAssociatedObjects();
+};
diff --git a/src/3rdparty/adaptagrams/libcola/tests/page_bounds.cpp b/src/3rdparty/adaptagrams/libcola/tests/page_bounds.cpp
new file mode 100644
index 0000000..b753cbf
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/page_bounds.cpp
@@ -0,0 +1,102 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+/**
+ * \file page_bounds.cpp
+ *
+ * test/example showing the use of page boundary constraints
+ */
+#include<iostream>
+#include<vector>
+#include <cmath>
+#include <time.h>
+#include <valarray>
+
+#include "graphlayouttest.h"
+
+vector<Edge> random_graph(unsigned n) {
+ vector<Edge> edges;
+ for(unsigned i=1;i<n;i++) {
+ edges.push_back(make_pair(i-1,i));
+ }
+ for(unsigned i=0;i<n;i++) {
+ for(unsigned j=i+1;j<n;j++) {
+ double r=(double)rand()/(double)RAND_MAX;
+ if(r < 1./(double)n) {
+ edges.push_back(make_pair(i,j));
+ }
+ }
+ }
+
+ return edges;
+}
+int main() {
+ unsigned V=30;
+ CompoundConstraints ccs;
+ vector<Edge> es = random_graph(V);
+ double defaultEdgeLength=40;
+ cola::PageBoundaryConstraints* pbc =
+ new cola::PageBoundaryConstraints(0,200,0,200,100);
+
+ double w=2.0, h=2.0;
+ for(unsigned i=0;i<V;i++) {
+ pbc->addShape(i, w/2, h/2);
+ }
+ ccs.push_back(pbc);
+
+ cout << "V="<<V<<endl;
+ double width=1000;
+ double height=1000;
+ //srand(time(nullptr));
+ vector<pair<double,double> > startpos(V);
+ for(unsigned i=0;i<V;i++) {
+ double x=getRand(width), y=getRand(height);
+ startpos[i]=make_pair(x,y);
+ }
+
+ /*void run_test(
+ vector<pair<double,double> > const &startpos,
+ vector<Edge> const &es,
+ const double defaultEdgeLength,
+ CompoundConstraints &cx,
+ CompoundConstraints &cy,
+ const SolverType s,
+ const bool constrained,
+ const char *fname,
+ const char *testdesc) {
+ */
+
+/*
+ run_test(startpos,es,defaultEdgeLength,cx,cy,CG,false,"random","cg");
+ run_test(startpos,es,defaultEdgeLength,cx,cy,IP,false,"random", "ip");
+ run_test(startpos,es,defaultEdgeLength,cx,cy,UGP,false,"random", "ugp");
+ run_test(startpos,es,defaultEdgeLength,cx,cy,SGP,false,"random", "sgp");
+ run_test(startpos,es,defaultEdgeLength,cx,cy,IP,true,"random", "cip");
+ run_test(startpos,es,defaultEdgeLength,cx,cy,SGP,true,"random", "csgp");
+ */
+ run_test(startpos,es,defaultEdgeLength,ccs,UGP,true,"random", "cugp");
+ return 0;
+}
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 :
diff --git a/src/3rdparty/adaptagrams/libcola/tests/planar.cpp b/src/3rdparty/adaptagrams/libcola/tests/planar.cpp
new file mode 100644
index 0000000..f5eae9c
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/planar.cpp
@@ -0,0 +1,287 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+/** \file topology.cpp
+ *
+ * tests topology preserving layout. graph is a triangle.
+ * We have a fourth disconnected node starting inside the triangle.
+ * We give the disconnected node a desired position outside the triangle
+ * and begin layout. Layout should converge to near zero stress as all
+ * edges should be able to reach their desired lengths, and disconnected
+ * node should still be inside the triangle at the end.
+ */
+/*
+* Authors:
+* Tim Dwyer <tgdwyer@gmail.com>
+*/
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+
+#include <vector>
+#include <valarray>
+#include <algorithm>
+#include <float.h>
+#include <libcola/cola.h>
+#include <libtopology/topology_graph.h>
+#include "graphlayouttest.h"
+using namespace std;
+using namespace cola;
+
+struct TestCase {
+ topology::Nodes vs;
+ topology::Edges tes;
+ topology::EdgePoints ps;
+ vector<vpsc::Rectangle*> rs;
+ vector<Edge> es;
+ void addNode(double minX, double minY, double w, double h) {
+ vpsc::Rectangle* r = new Rectangle(minX, minX+w, minY, minY+h);
+ rs.push_back(r);
+ topology::Node *v = new topology::Node(vs.size(), r);
+ vs.push_back(v);
+ }
+ void addToPath(unsigned vID, topology::EdgePoint::RectIntersect i) {
+ ps.push_back(new topology::EdgePoint(vs[vID],i));
+ }
+ void addEdge(double l) {
+ tes.push_back(new topology::Edge(l, ps));
+ es.push_back(make_pair(ps[0]->node->id,ps[ps.size()-1]->node->id));
+ ps.clear();
+ }
+ ~TestCase() {
+ for_each(rs.begin(),rs.end(),delete_object());
+ for_each(tes.begin(),tes.end(),delete_object());
+ for_each(vs.begin(),vs.end(),delete_object());
+ }
+};
+void writeFile(const topology::Nodes& vs, const topology::Edges& es, const char *outputFileName) {
+ const unsigned n=vs.size();
+ vector<cola::Edge> cedges;
+
+ for(unsigned i=0;i<es.size();i++) {
+ cedges.push_back(make_pair(1,2));
+ }
+
+ vector<straightener::Route*> routes;
+ for(topology::Edges::const_iterator e=es.begin();e!=es.end();++e) {
+ routes.push_back((*e)->getRoute());
+ }
+
+ vector<string> labels(n);
+ for(unsigned i=0;i<n;++i) {
+ stringstream ss;
+ ss << i;
+ labels[i]=ss.str();
+ }
+
+ vector<vpsc::Rectangle*> rs;
+ for(topology::Nodes::const_iterator i=vs.begin();i!=vs.end();++i) {
+ rs.push_back((*i)->rect);
+ }
+ OutputFile of(rs,cedges,nullptr,outputFileName,true,false);
+ of.setLabels(labels);
+ of.routes=&routes;
+ of.generate();
+
+ for_each(routes.begin(),routes.end(),delete_object());
+}
+struct Test : TestConvergence {
+ Test(const double d,const unsigned i,topology::Nodes& vs, topology::Edges& es) : TestConvergence(d,i), vs(vs), es(es) {}
+ bool operator()(const double new_stress, valarray<double> & X, valarray<double> & Y) {
+ cout << "stress="<<new_stress<<" iteration="<<iterations<<endl;
+ stringstream ss;
+ ss << "planar-" << setfill('0') << setw(3) << ++iterations << ".svg";
+ writeFile(vs,es,ss.str().c_str());
+ if(iterations<100) {
+ return false;
+ }
+ return true;
+ return TestConvergence::operator()(new_stress,X,Y);
+ }
+ double lastStress;
+ topology::Nodes& vs;
+ topology::Edges& es;
+};
+void test() {
+ TestCase t;
+t.addNode(144.000000,511.000000,8.000000,8.000000);
+t.addNode(413.000000,155.000000,8.000000,8.000000);
+t.addNode(437.000000,169.000000,8.000000,8.000000);
+t.addNode(436.000000,122.000000,8.000000,8.000000);
+t.addNode(460.000000,150.000000,8.000000,8.000000);
+t.addNode(466.000000,178.000000,8.000000,8.000000);
+t.addNode(469.000000,198.000000,8.000000,8.000000);
+t.addNode(378.000000,332.000000,8.000000,8.000000);
+t.addNode(368.000000,315.000000,8.000000,8.000000);
+t.addNode(332.000000,341.000000,8.000000,8.000000);
+t.addNode(282.000000,374.000000,8.000000,8.000000);
+t.addNode(329.000000,364.000000,8.000000,8.000000);
+t.addNode(346.000000,390.000000,8.000000,8.000000);
+t.addNode(375.000000,402.000000,8.000000,8.000000);
+t.addNode(357.000000,438.000000,8.000000,8.000000);
+t.addNode(382.000000,422.000000,8.000000,8.000000);
+t.addNode(453.000000,280.000000,8.000000,8.000000);
+t.addNode(452.000000,258.000000,8.000000,8.000000);
+t.addNode(530.000000,449.000000,8.000000,8.000000);
+t.addNode(576.000000,431.000000,8.000000,8.000000);
+t.addNode(577.000000,408.000000,8.000000,8.000000);
+t.addNode(606.000000,438.000000,8.000000,8.000000);
+t.addNode(624.000000,467.000000,8.000000,8.000000);
+t.addNode(620.000000,492.000000,8.000000,8.000000);
+t.addNode(681.000000,492.000000,8.000000,8.000000);
+t.addNode(729.000000,528.000000,8.000000,8.000000);
+t.addNode(765.000000,515.000000,8.000000,8.000000);
+t.addNode(765.000000,492.000000,8.000000,8.000000);
+t.addNode(858.000000,538.000000,8.000000,8.000000);
+t.addNode(2.000000,544.000000,8.000000,8.000000);
+t.addToPath(28,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(27,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(28,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(26,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(25,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(28,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(25,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(29,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(17,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(24,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(16,(topology::EdgePoint::RectIntersect)4);
+//t.addToPath(20,(topology::EdgePoint::RectIntersect)1);
+t.addToPath(24,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(16,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(7,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(24,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(25,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(22,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(24,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(22,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(0,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(22,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(23,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(22,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(18,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(21,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(20,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(20,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(19,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(18,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(20,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(18,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(16,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(14,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(18,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(13,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(14,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(15,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(14,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(12,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(13,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(12,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(10,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(11,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(12,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(10,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(11,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(9,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(13,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(9,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(10,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(6,(topology::EdgePoint::RectIntersect)4);
+//t.addToPath(8,(topology::EdgePoint::RectIntersect)2);
+t.addToPath(9,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(6,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(7,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(8,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(7,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(6,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(25,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(5,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(10,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(5,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(29,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(29,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(1,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(3,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(2,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(5,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(6,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(4,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(5,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(3,(topology::EdgePoint::RectIntersect)4);
+t.addToPath(4,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+t.addToPath(29,(topology::EdgePoint::RectIntersect)4);
+//t.addToPath(1,(topology::EdgePoint::RectIntersect)2);
+t.addToPath(3,(topology::EdgePoint::RectIntersect)4);
+t.addEdge(70.000000);
+ writeFile(t.vs,t.tes,"planar-000.svg");
+ Test test(0.00001,100,t.vs,t.tes);
+ ConstrainedFDLayout alg(t.rs,t.es,70.0,nullptr,test,nullptr);
+ alg.setTopology(&t.vs,&t.tes);
+ alg.run(true,true);
+ double finalStress=alg.computeStress();
+ printf("finalStress=%f\n",finalStress);
+
+ //assert(finalStress<1e-5);
+}
+int main() {
+ test();
+ return 0;
+}
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=80 :
diff --git a/src/3rdparty/adaptagrams/libcola/tests/random_graph.cpp b/src/3rdparty/adaptagrams/libcola/tests/random_graph.cpp
new file mode 100644
index 0000000..68e2ee1
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/random_graph.cpp
@@ -0,0 +1,113 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+#include<iostream>
+#include<vector>
+#include <cmath>
+#include <time.h>
+#include <valarray>
+
+#include "graphlayouttest.h"
+
+vector<Edge> random_graph(unsigned n) {
+ vector<Edge> edges;
+ for(unsigned i=1;i<n;i++) {
+ edges.push_back(make_pair(i-1,i));
+ }
+ for(unsigned i=0;i<n;i++) {
+ for(unsigned j=i+1;j<n;j++) {
+ double r=(double)rand()/(double)RAND_MAX;
+ if(r < 1./(double)n) {
+ edges.push_back(make_pair(i,j));
+ }
+ }
+ }
+
+ return edges;
+}
+int main() {
+ unsigned V=100;
+ CompoundConstraints ccs;
+ vector<Edge> es = random_graph(V);
+ double defaultEdgeLength=40;
+ for(unsigned i=0;i<es.size();i++) {
+ unsigned start=es[i].first, end=es[i].second;
+ ccs.push_back(
+ new SeparationConstraint(vpsc::YDIM, start,end,-10));
+ }
+
+ cout << "V="<<V<<endl;
+ double width=1000;
+ double height=1000;
+ //srand(time(nullptr));
+ vector<pair<double,double> > startpos(V);
+ for(unsigned i=0;i<V;i++) {
+ double x=getRand(width), y=getRand(height);
+ startpos[i]=make_pair(x,y);
+ }
+
+ /*void run_test(
+ vector<pair<double,double> > const &startpos,
+ vector<Edge> const &es,
+ const double defaultEdgeLength,
+ CompoundConstraints &cx,
+ CompoundConstraints &cy,
+ const SolverType s,
+ const bool constrained,
+ const char *fname,
+ const char *testdesc) {
+ */
+
+/*
+ run_test(startpos,es,defaultEdgeLength,cx,cy,CG,false,"random","cg");
+ run_test(startpos,es,defaultEdgeLength,cx,cy,IP,false,"random", "ip");
+ run_test(startpos,es,defaultEdgeLength,cx,cy,UGP,false,"random", "ugp");
+ run_test(startpos,es,defaultEdgeLength,cx,cy,SGP,false,"random", "sgp");
+ run_test(startpos,es,defaultEdgeLength,cx,cy,IP,true,"random", "cip");
+ run_test(startpos,es,defaultEdgeLength,cx,cy,UGP,true,"random", "cugp");
+ run_test(startpos,es,defaultEdgeLength,cx,cy,SGP,true,"random", "csgp");
+ */
+ vector<vpsc::Rectangle*> rs;
+ for(unsigned i=0;i<V;i++) {
+ double x=getRand(width), y=getRand(height);
+ rs.push_back(new vpsc::Rectangle(x,x+5,y,y+5));
+ }
+ CheckProgress test(0.0001,200);
+ ConstrainedMajorizationLayout alg(rs,es,nullptr,defaultEdgeLength,
+ StandardEdgeLengths,&test);
+ //alg.setYConstraints(&cy);
+ alg.run();
+ ConstrainedFDLayout alg2(rs,es,defaultEdgeLength,
+ StandardEdgeLengths, &test);
+ //alg2.setYConstraints(&cy);
+ alg2.run();
+ OutputFile output(rs,es,nullptr,"random.pdf");
+ output.generate();
+ for(unsigned i=0;i<V;i++) {
+ delete rs[i];
+ }
+ return 0;
+}
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 :
diff --git a/src/3rdparty/adaptagrams/libcola/tests/rectangularClusters01.cpp b/src/3rdparty/adaptagrams/libcola/tests/rectangularClusters01.cpp
new file mode 100644
index 0000000..4269b3b
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/rectangularClusters01.cpp
@@ -0,0 +1,1135 @@
+#include <vector>
+#include <utility>
+#include "libcola/cola.h"
+using namespace cola;
+int main(void) {
+ CompoundConstraints ccs;
+ std::vector<Edge> es;
+ EdgeLengths eLengths;
+ double defaultEdgeLength=1;
+ std::vector<vpsc::Rectangle*> rs;
+ vpsc::Rectangle *rect = nullptr;
+
+ rect = new vpsc::Rectangle(56.4457, 117.446, 954.77, 1043.77);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(119.446, 127.446, 992.02, 1000.02);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(119.446, 127.446, 1004.27, 1012.27);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(119.446, 127.446, 1016.52, 1024.52);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(46.4457, 54.4457, 1004.27, 1012.27);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(2165.45, 2239.45, 976.562, 1065.56);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(2155.45, 2163.45, 1026.06, 1034.06);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(-106.554, 6.44565, 955.683, 1044.68);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(8.44565, 16.4457, 1005.18, 1013.18);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(331.446, 412.446, 1015.55, 1104.55);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(414.446, 422.446, 1065.05, 1073.05);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(356.112, 364.112, 1106.55, 1114.55);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(339.779, 347.779, 1106.55, 1114.55);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(321.446, 329.446, 1073.22, 1081.22);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(321.446, 329.446, 1056.88, 1064.88);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(477.446, 559.446, 948.569, 1037.57);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(561.446, 569.446, 998.069, 1006.07);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(503.946, 511.946, 1039.57, 1047.57);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(467.446, 475.446, 998.069, 1006.07);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(56.4457, 127.446, 863.77, 952.77);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(129.446, 137.446, 913.27, 921.27);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(46.4457, 54.4457, 913.27, 921.27);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(177.446, 281.446, 922.444, 1011.44);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(283.446, 291.446, 971.944, 979.944);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(167.446, 175.446, 986.644, 994.644);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(167.446, 175.446, 976.844, 984.844);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(167.446, 175.446, 967.044, 975.044);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(167.446, 175.446, 957.244, 965.244);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(331.446, 427.446, 924.551, 1013.55);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(429.446, 437.446, 974.051, 982.051);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(321.446, 329.446, 974.051, 982.051);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(609.446, 730.446, 936.692, 1025.69);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(732.446, 740.446, 971.492, 979.492);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(732.446, 740.446, 981.292, 989.292);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(732.446, 740.446, 991.092, 999.092);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(732.446, 740.446, 1000.89, 1008.89);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(599.446, 607.446, 986.192, 994.192);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(780.446, 846.446, 838.172, 932.172);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(848.446, 856.446, 890.172, 898.172);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(770.446, 778.446, 890.172, 898.172);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(780.446, 846.446, 934.172, 1028.17);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(848.446, 856.446, 986.172, 994.172);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(770.446, 778.446, 986.172, 994.172);
+ rs.push_back(rect);
+
+ // rect-43
+ rect = new vpsc::Rectangle(941.446, 1155.45, 922.958, 1025.96);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1147.45, 1155.45, 979.458, 987.458);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(941.446, 949.446, 998.358, 1006.36);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(941.446, 949.446, 985.757, 993.757);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(941.446, 949.446, 973.158, 981.158);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(941.446, 949.446, 960.558, 968.558);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(780.446, 846.446, 1030.17, 1124.17);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(848.446, 856.446, 1082.17, 1090.17);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(770.446, 778.446, 1082.17, 1090.17);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1195.45, 1263.45, 938.653, 1017.65);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1265.45, 1273.45, 983.153, 991.153);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1185.45, 1193.45, 989.653, 997.653);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1185.45, 1193.45, 976.653, 984.653);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1313.45, 1374.45, 934.988, 1013.99);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1376.45, 1384.45, 979.488, 987.488);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1303.45, 1311.45, 979.488, 987.488);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1586.45, 1660.45, 855.704, 944.704);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1576.45, 1584.45, 905.204, 913.204);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1424.45, 1536.45, 866.456, 945.456);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1538.45, 1546.45, 910.956, 918.956);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1414.45, 1422.45, 910.956, 918.956);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1445.45, 1515.45, 947.456, 1036.46);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1517.45, 1525.45, 996.956, 1004.96);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1471.95, 1479.95, 1038.46, 1046.46);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1435.45, 1443.45, 996.956, 1004.96);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1699.45, 1748.45, 970.163, 1059.16);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1750.45, 1758.45, 1019.66, 1027.66);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1689.45, 1697.45, 1027.83, 1035.83);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1689.45, 1697.45, 1011.5, 1019.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1811.45, 1898.45, 1010.04, 1099.04);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1900.45, 1908.45, 1059.54, 1067.54);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1801.45, 1809.45, 1067.7, 1075.7);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1801.45, 1809.45, 1051.37, 1059.37);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1699.45, 1761.45, 1061.16, 1134.16);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1763.45, 1771.45, 1102.66, 1110.66);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1689.45, 1697.45, 1102.66, 1110.66);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(2053.45, 2115.45, 985.999, 1080);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(2117.45, 2125.45, 1038, 1046);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(2080.11, 2088.11, 1082, 1090);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(2062.78, 2070.78, 1082, 1090);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(2043.45, 2051.45, 1038, 1046);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1948.45, 2003.45, 996.147, 1090.15);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(2005.45, 2013.45, 1048.15, 1056.15);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1975.11, 1983.11, 1092.15, 1100.15);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1957.78, 1965.78, 1092.15, 1100.15);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1938.45, 1946.45, 1048.15, 1056.15);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1565.45, 1649.45, 951.936, 1040.94);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1651.45, 1659.45, 1001.44, 1009.44);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(1555.45, 1563.45, 1001.44, 1009.44);
+ rs.push_back(rect);
+
+ es.push_back(std::make_pair(0, 1));
+ es.push_back(std::make_pair(0, 2));
+ es.push_back(std::make_pair(0, 3));
+ es.push_back(std::make_pair(0, 4));
+ es.push_back(std::make_pair(1, 26));
+ es.push_back(std::make_pair(2, 25));
+ es.push_back(std::make_pair(3, 6));
+ es.push_back(std::make_pair(3, 24));
+ es.push_back(std::make_pair(4, 8));
+ es.push_back(std::make_pair(5, 6));
+ es.push_back(std::make_pair(6, 80));
+ es.push_back(std::make_pair(7, 8));
+ es.push_back(std::make_pair(9, 10));
+ es.push_back(std::make_pair(9, 11));
+ es.push_back(std::make_pair(9, 12));
+ es.push_back(std::make_pair(9, 13));
+ es.push_back(std::make_pair(9, 14));
+ es.push_back(std::make_pair(10, 17));
+ es.push_back(std::make_pair(15, 16));
+ es.push_back(std::make_pair(15, 17));
+ es.push_back(std::make_pair(15, 18));
+ es.push_back(std::make_pair(16, 36));
+ es.push_back(std::make_pair(16, 67));
+ es.push_back(std::make_pair(18, 29));
+ es.push_back(std::make_pair(19, 20));
+ es.push_back(std::make_pair(19, 21));
+ es.push_back(std::make_pair(20, 27));
+ es.push_back(std::make_pair(22, 23));
+ es.push_back(std::make_pair(22, 24));
+ es.push_back(std::make_pair(22, 25));
+ es.push_back(std::make_pair(22, 26));
+ es.push_back(std::make_pair(22, 27));
+ es.push_back(std::make_pair(23, 30));
+ es.push_back(std::make_pair(28, 29));
+ es.push_back(std::make_pair(28, 30));
+ es.push_back(std::make_pair(31, 32));
+ es.push_back(std::make_pair(31, 33));
+ es.push_back(std::make_pair(31, 34));
+ es.push_back(std::make_pair(31, 35));
+ es.push_back(std::make_pair(31, 36));
+ es.push_back(std::make_pair(32, 39));
+ es.push_back(std::make_pair(32, 48));
+ es.push_back(std::make_pair(34, 42));
+ es.push_back(std::make_pair(35, 51));
+ es.push_back(std::make_pair(35, 54));
+ es.push_back(std::make_pair(37, 38));
+ es.push_back(std::make_pair(37, 39));
+ es.push_back(std::make_pair(38, 47));
+ es.push_back(std::make_pair(40, 41));
+ es.push_back(std::make_pair(40, 42));
+ es.push_back(std::make_pair(41, 46));
+ es.push_back(std::make_pair(43, 44));
+ es.push_back(std::make_pair(43, 45));
+ es.push_back(std::make_pair(43, 46));
+ es.push_back(std::make_pair(43, 47));
+ es.push_back(std::make_pair(43, 48));
+ es.push_back(std::make_pair(44, 55));
+ es.push_back(std::make_pair(45, 50));
+ es.push_back(std::make_pair(49, 50));
+ es.push_back(std::make_pair(49, 51));
+ es.push_back(std::make_pair(52, 53));
+ es.push_back(std::make_pair(52, 54));
+ es.push_back(std::make_pair(52, 55));
+ es.push_back(std::make_pair(53, 58));
+ es.push_back(std::make_pair(56, 57));
+ es.push_back(std::make_pair(56, 58));
+ es.push_back(std::make_pair(57, 63));
+ es.push_back(std::make_pair(57, 66));
+ es.push_back(std::make_pair(59, 60));
+ es.push_back(std::make_pair(60, 62));
+ es.push_back(std::make_pair(61, 62));
+ es.push_back(std::make_pair(61, 63));
+ es.push_back(std::make_pair(64, 65));
+ es.push_back(std::make_pair(64, 66));
+ es.push_back(std::make_pair(64, 67));
+ es.push_back(std::make_pair(65, 91));
+ es.push_back(std::make_pair(68, 69));
+ es.push_back(std::make_pair(68, 70));
+ es.push_back(std::make_pair(68, 71));
+ es.push_back(std::make_pair(69, 75));
+ es.push_back(std::make_pair(70, 85));
+ es.push_back(std::make_pair(71, 90));
+ es.push_back(std::make_pair(72, 73));
+ es.push_back(std::make_pair(72, 74));
+ es.push_back(std::make_pair(72, 75));
+ es.push_back(std::make_pair(73, 88));
+ es.push_back(std::make_pair(75, 77));
+ es.push_back(std::make_pair(76, 77));
+ es.push_back(std::make_pair(76, 78));
+ es.push_back(std::make_pair(79, 80));
+ es.push_back(std::make_pair(79, 81));
+ es.push_back(std::make_pair(79, 82));
+ es.push_back(std::make_pair(79, 83));
+ es.push_back(std::make_pair(83, 85));
+ es.push_back(std::make_pair(84, 85));
+ es.push_back(std::make_pair(84, 86));
+ es.push_back(std::make_pair(84, 87));
+ es.push_back(std::make_pair(84, 88));
+ es.push_back(std::make_pair(89, 90));
+ es.push_back(std::make_pair(89, 91));
+
+ eLengths.resize(100);
+ eLengths[0] = 59.6059;
+ eLengths[1] = 59.6059;
+ eLengths[2] = 59.6059;
+ eLengths[3] = 59.6059;
+ eLengths[4] = 63.5296;
+ eLengths[5] = 77.5769;
+ eLengths[6] = 65.8274;
+ eLengths[7] = 65.8274;
+ eLengths[8] = 65.8274;
+ eLengths[9] = 65.8274;
+ eLengths[10] = 65.8274;
+ eLengths[11] = 66.1651;
+ eLengths[12] = 66.1651;
+ eLengths[13] = 66.1651;
+ eLengths[14] = 62.5822;
+ eLengths[15] = 62.5822;
+ eLengths[16] = 74.0984;
+ eLengths[17] = 74.0984;
+ eLengths[18] = 74.0984;
+ eLengths[19] = 74.0984;
+ eLengths[20] = 74.0984;
+ eLengths[21] = 71.111;
+ eLengths[22] = 71.111;
+ eLengths[23] = 80.7601;
+ eLengths[24] = 80.7601;
+ eLengths[25] = 80.7601;
+ eLengths[26] = 80.7601;
+ eLengths[27] = 80.7601;
+ eLengths[28] = 63.0851;
+ eLengths[29] = 63.0851;
+ eLengths[30] = 63.0851;
+ eLengths[31] = 63.0851;
+ eLengths[32] = 115.481;
+ eLengths[33] = 115.481;
+ eLengths[34] = 115.481;
+ eLengths[35] = 115.481;
+ eLengths[36] = 115.481;
+ eLengths[37] = 63.0851;
+ eLengths[38] = 63.0851;
+ eLengths[39] = 57.7745;
+ eLengths[40] = 57.7745;
+ eLengths[41] = 57.7745;
+ eLengths[42] = 55.5618;
+ eLengths[43] = 55.5618;
+ eLengths[44] = 63.5296;
+ eLengths[45] = 74.186;
+ eLengths[46] = 74.186;
+ eLengths[47] = 62.2718;
+ eLengths[48] = 62.2718;
+ eLengths[49] = 62.2718;
+ eLengths[50] = 56.4555;
+ eLengths[51] = 56.4555;
+ eLengths[52] = 56.4555;
+ eLengths[53] = 67.8863;
+ eLengths[54] = 67.8863;
+ eLengths[55] = 67.8863;
+ eLengths[56] = 53.5447;
+ eLengths[57] = 53.5447;
+ eLengths[58] = 61.9596;
+ eLengths[59] = 61.9596;
+ eLengths[60] = 61.9596;
+ eLengths[61] = 61.9596;
+ eLengths[62] = 60.111;
+ eLengths[63] = 60.111;
+ eLengths[64] = 60.111;
+ eLengths[65] = 60.111;
+ eLengths[66] = 66.8471;
+ eLengths[67] = 66.8471;
+ eLengths[68] = 18.3712;
+ eLengths[69] = 18.3712;
+ eLengths[70] = 18.3712;
+ eLengths[71] = 18.3712;
+ eLengths[72] = 10.6066;
+ eLengths[73] = 10.6066;
+ eLengths[74] = 15;
+ eLengths[75] = 15;
+ eLengths[76] = 15;
+ eLengths[77] = 10.6066;
+ eLengths[78] = 10.6066;
+ eLengths[79] = 23.7171;
+ eLengths[80] = 30;
+ eLengths[81] = 23.7171;
+ eLengths[82] = 23.7171;
+ eLengths[83] = 25.9808;
+ eLengths[84] = 21.2132;
+ eLengths[85] = 21.2132;
+ eLengths[86] = 15;
+ eLengths[87] = 21.2132;
+ eLengths[88] = 10.6066;
+ eLengths[89] = 15;
+ eLengths[90] = 15;
+ eLengths[91] = 10.6066;
+ eLengths[92] = 10.6066;
+ eLengths[93] = 15;
+ eLengths[94] = 10.6066;
+ eLengths[95] = 15;
+ eLengths[96] = 15;
+ eLengths[97] = 15;
+ eLengths[98] = 18.3712;
+ eLengths[99] = 15;
+
+ SeparationConstraint *separation479625808 = new SeparationConstraint(vpsc::XDIM, 0, 1, 36.5, true);
+ ccs.push_back(separation479625808);
+
+ SeparationConstraint *separation479626000 = new SeparationConstraint(vpsc::YDIM, 0, 1, -3.25, true);
+ ccs.push_back(separation479626000);
+
+ SeparationConstraint *separation479625936 = new SeparationConstraint(vpsc::XDIM, 0, 2, 36.5, true);
+ ccs.push_back(separation479625936);
+
+ SeparationConstraint *separation479626128 = new SeparationConstraint(vpsc::YDIM, 0, 2, 9, true);
+ ccs.push_back(separation479626128);
+
+ SeparationConstraint *separation479626064 = new SeparationConstraint(vpsc::XDIM, 0, 3, 36.5, true);
+ ccs.push_back(separation479626064);
+
+ SeparationConstraint *separation479626256 = new SeparationConstraint(vpsc::YDIM, 0, 3, 21.25, true);
+ ccs.push_back(separation479626256);
+
+ SeparationConstraint *separation479626192 = new SeparationConstraint(vpsc::XDIM, 0, 4, -36.5, true);
+ ccs.push_back(separation479626192);
+
+ SeparationConstraint *separation479626384 = new SeparationConstraint(vpsc::YDIM, 0, 4, 9, true);
+ ccs.push_back(separation479626384);
+
+ SeparationConstraint *separation479626320 = new SeparationConstraint(vpsc::XDIM, 5, 6, -43, true);
+ ccs.push_back(separation479626320);
+
+ SeparationConstraint *separation479626512 = new SeparationConstraint(vpsc::YDIM, 5, 6, 9, true);
+ ccs.push_back(separation479626512);
+
+ SeparationConstraint *separation479626448 = new SeparationConstraint(vpsc::XDIM, 7, 8, 62.5, true);
+ ccs.push_back(separation479626448);
+
+ SeparationConstraint *separation479626640 = new SeparationConstraint(vpsc::YDIM, 7, 8, 9, true);
+ ccs.push_back(separation479626640);
+
+ SeparationConstraint *separation479626576 = new SeparationConstraint(vpsc::XDIM, 9, 10, 46.5, true);
+ ccs.push_back(separation479626576);
+
+ SeparationConstraint *separation479626768 = new SeparationConstraint(vpsc::YDIM, 9, 10, 9, true);
+ ccs.push_back(separation479626768);
+
+ SeparationConstraint *separation479626704 = new SeparationConstraint(vpsc::XDIM, 9, 11, -11.8333, true);
+ ccs.push_back(separation479626704);
+
+ SeparationConstraint *separation479626896 = new SeparationConstraint(vpsc::YDIM, 9, 11, 50.5, true);
+ ccs.push_back(separation479626896);
+
+ SeparationConstraint *separation479626832 = new SeparationConstraint(vpsc::XDIM, 9, 12, -28.1667, true);
+ ccs.push_back(separation479626832);
+
+ SeparationConstraint *separation479627024 = new SeparationConstraint(vpsc::YDIM, 9, 12, 50.5, true);
+ ccs.push_back(separation479627024);
+
+ SeparationConstraint *separation479626960 = new SeparationConstraint(vpsc::XDIM, 9, 13, -46.5, true);
+ ccs.push_back(separation479626960);
+
+ SeparationConstraint *separation479627152 = new SeparationConstraint(vpsc::YDIM, 9, 13, 17.1667, true);
+ ccs.push_back(separation479627152);
+
+ SeparationConstraint *separation479627088 = new SeparationConstraint(vpsc::XDIM, 9, 14, -46.5, true);
+ ccs.push_back(separation479627088);
+
+ SeparationConstraint *separation479627280 = new SeparationConstraint(vpsc::YDIM, 9, 14, 0.833333, true);
+ ccs.push_back(separation479627280);
+
+ SeparationConstraint *separation479627216 = new SeparationConstraint(vpsc::XDIM, 15, 16, 47, true);
+ ccs.push_back(separation479627216);
+
+ SeparationConstraint *separation479627408 = new SeparationConstraint(vpsc::YDIM, 15, 16, 9, true);
+ ccs.push_back(separation479627408);
+
+ SeparationConstraint *separation479627344 = new SeparationConstraint(vpsc::XDIM, 15, 17, -10.5, true);
+ ccs.push_back(separation479627344);
+
+ SeparationConstraint *separation479627536 = new SeparationConstraint(vpsc::YDIM, 15, 17, 50.5, true);
+ ccs.push_back(separation479627536);
+
+ SeparationConstraint *separation479627472 = new SeparationConstraint(vpsc::XDIM, 15, 18, -47, true);
+ ccs.push_back(separation479627472);
+
+ SeparationConstraint *separation479627664 = new SeparationConstraint(vpsc::YDIM, 15, 18, 9, true);
+ ccs.push_back(separation479627664);
+
+ SeparationConstraint *separation479627600 = new SeparationConstraint(vpsc::XDIM, 19, 20, 41.5, true);
+ ccs.push_back(separation479627600);
+
+ SeparationConstraint *separation479627792 = new SeparationConstraint(vpsc::YDIM, 19, 20, 9, true);
+ ccs.push_back(separation479627792);
+
+ SeparationConstraint *separation479627728 = new SeparationConstraint(vpsc::XDIM, 19, 21, -41.5, true);
+ ccs.push_back(separation479627728);
+
+ SeparationConstraint *separation479627920 = new SeparationConstraint(vpsc::YDIM, 19, 21, 9, true);
+ ccs.push_back(separation479627920);
+
+ SeparationConstraint *separation479627856 = new SeparationConstraint(vpsc::XDIM, 22, 23, 58, true);
+ ccs.push_back(separation479627856);
+
+ SeparationConstraint *separation479628048 = new SeparationConstraint(vpsc::YDIM, 22, 23, 9, true);
+ ccs.push_back(separation479628048);
+
+ SeparationConstraint *separation479627984 = new SeparationConstraint(vpsc::XDIM, 22, 24, -58, true);
+ ccs.push_back(separation479627984);
+
+ SeparationConstraint *separation479628176 = new SeparationConstraint(vpsc::YDIM, 22, 24, 23.7, true);
+ ccs.push_back(separation479628176);
+
+ SeparationConstraint *separation479628112 = new SeparationConstraint(vpsc::XDIM, 22, 25, -58, true);
+ ccs.push_back(separation479628112);
+
+ SeparationConstraint *separation479628304 = new SeparationConstraint(vpsc::YDIM, 22, 25, 13.9, true);
+ ccs.push_back(separation479628304);
+
+ SeparationConstraint *separation479628240 = new SeparationConstraint(vpsc::XDIM, 22, 26, -58, true);
+ ccs.push_back(separation479628240);
+
+ SeparationConstraint *separation479628432 = new SeparationConstraint(vpsc::YDIM, 22, 26, 4.1, true);
+ ccs.push_back(separation479628432);
+
+ SeparationConstraint *separation479628368 = new SeparationConstraint(vpsc::XDIM, 22, 27, -58, true);
+ ccs.push_back(separation479628368);
+
+ SeparationConstraint *separation479628560 = new SeparationConstraint(vpsc::YDIM, 22, 27, -5.7, true);
+ ccs.push_back(separation479628560);
+
+ SeparationConstraint *separation479628496 = new SeparationConstraint(vpsc::XDIM, 28, 29, 54, true);
+ ccs.push_back(separation479628496);
+
+ SeparationConstraint *separation479628688 = new SeparationConstraint(vpsc::YDIM, 28, 29, 9, true);
+ ccs.push_back(separation479628688);
+
+ SeparationConstraint *separation479628624 = new SeparationConstraint(vpsc::XDIM, 28, 30, -54, true);
+ ccs.push_back(separation479628624);
+
+ SeparationConstraint *separation479628816 = new SeparationConstraint(vpsc::YDIM, 28, 30, 9, true);
+ ccs.push_back(separation479628816);
+
+ SeparationConstraint *separation479628752 = new SeparationConstraint(vpsc::XDIM, 31, 32, 66.5, true);
+ ccs.push_back(separation479628752);
+
+ SeparationConstraint *separation479622736 = new SeparationConstraint(vpsc::YDIM, 31, 32, -5.7, true);
+ ccs.push_back(separation479622736);
+
+ SeparationConstraint *separation479622800 = new SeparationConstraint(vpsc::XDIM, 31, 33, 66.5, true);
+ ccs.push_back(separation479622800);
+
+ SeparationConstraint *separation479622864 = new SeparationConstraint(vpsc::YDIM, 31, 33, 4.1, true);
+ ccs.push_back(separation479622864);
+
+ SeparationConstraint *separation479622928 = new SeparationConstraint(vpsc::XDIM, 31, 34, 66.5, true);
+ ccs.push_back(separation479622928);
+
+ SeparationConstraint *separation479622992 = new SeparationConstraint(vpsc::YDIM, 31, 34, 13.9, true);
+ ccs.push_back(separation479622992);
+
+ SeparationConstraint *separation479623056 = new SeparationConstraint(vpsc::XDIM, 31, 35, 66.5, true);
+ ccs.push_back(separation479623056);
+
+ SeparationConstraint *separation479623120 = new SeparationConstraint(vpsc::YDIM, 31, 35, 23.7, true);
+ ccs.push_back(separation479623120);
+
+ SeparationConstraint *separation479623184 = new SeparationConstraint(vpsc::XDIM, 31, 36, -66.5, true);
+ ccs.push_back(separation479623184);
+
+ SeparationConstraint *separation479623248 = new SeparationConstraint(vpsc::YDIM, 31, 36, 9, true);
+ ccs.push_back(separation479623248);
+
+ SeparationConstraint *separation479623312 = new SeparationConstraint(vpsc::XDIM, 37, 38, 39, true);
+ ccs.push_back(separation479623312);
+
+ SeparationConstraint *separation479623440 = new SeparationConstraint(vpsc::YDIM, 37, 38, 9, true);
+ ccs.push_back(separation479623440);
+
+ SeparationConstraint *separation479623504 = new SeparationConstraint(vpsc::XDIM, 37, 39, -39, true);
+ ccs.push_back(separation479623504);
+
+ SeparationConstraint *separation479623568 = new SeparationConstraint(vpsc::YDIM, 37, 39, 9, true);
+ ccs.push_back(separation479623568);
+
+ SeparationConstraint *separation479623632 = new SeparationConstraint(vpsc::XDIM, 40, 41, 39, true);
+ ccs.push_back(separation479623632);
+
+ SeparationConstraint *separation479623696 = new SeparationConstraint(vpsc::YDIM, 40, 41, 9, true);
+ ccs.push_back(separation479623696);
+
+ SeparationConstraint *separation479623760 = new SeparationConstraint(vpsc::XDIM, 40, 42, -39, true);
+ ccs.push_back(separation479623760);
+
+ SeparationConstraint *separation479623888 = new SeparationConstraint(vpsc::YDIM, 40, 42, 9, true);
+ ccs.push_back(separation479623888);
+
+ SeparationConstraint *separation479623952 = new SeparationConstraint(vpsc::XDIM, 43, 44, 103, true);
+ ccs.push_back(separation479623952);
+
+ SeparationConstraint *separation479624016 = new SeparationConstraint(vpsc::YDIM, 43, 44, 9, true);
+ ccs.push_back(separation479624016);
+
+ SeparationConstraint *separation479624080 = new SeparationConstraint(vpsc::XDIM, 43, 45, -103, true);
+ ccs.push_back(separation479624080);
+
+ SeparationConstraint *separation479624144 = new SeparationConstraint(vpsc::YDIM, 43, 45, 27.9, true);
+ ccs.push_back(separation479624144);
+
+ SeparationConstraint *separation479624208 = new SeparationConstraint(vpsc::XDIM, 43, 46, -103, true);
+ ccs.push_back(separation479624208);
+
+ SeparationConstraint *separation479624272 = new SeparationConstraint(vpsc::YDIM, 43, 46, 15.3, true);
+ ccs.push_back(separation479624272);
+
+ SeparationConstraint *separation479624336 = new SeparationConstraint(vpsc::XDIM, 43, 47, -103, true);
+ ccs.push_back(separation479624336);
+
+ SeparationConstraint *separation479624400 = new SeparationConstraint(vpsc::YDIM, 43, 47, 2.7, true);
+ ccs.push_back(separation479624400);
+
+ SeparationConstraint *separation479624528 = new SeparationConstraint(vpsc::XDIM, 43, 48, -103, true);
+ ccs.push_back(separation479624528);
+
+ SeparationConstraint *separation479624592 = new SeparationConstraint(vpsc::YDIM, 43, 48, -9.9, true);
+ ccs.push_back(separation479624592);
+
+ SeparationConstraint *separation479624656 = new SeparationConstraint(vpsc::XDIM, 49, 50, 39, true);
+ ccs.push_back(separation479624656);
+
+ SeparationConstraint *separation479624720 = new SeparationConstraint(vpsc::YDIM, 49, 50, 9, true);
+ ccs.push_back(separation479624720);
+
+ SeparationConstraint *separation479624784 = new SeparationConstraint(vpsc::XDIM, 49, 51, -39, true);
+ ccs.push_back(separation479624784);
+
+ SeparationConstraint *separation479624848 = new SeparationConstraint(vpsc::YDIM, 49, 51, 9, true);
+ ccs.push_back(separation479624848);
+
+ SeparationConstraint *separation479624912 = new SeparationConstraint(vpsc::XDIM, 52, 53, 40, true);
+ ccs.push_back(separation479624912);
+
+ SeparationConstraint *separation479624976 = new SeparationConstraint(vpsc::YDIM, 52, 53, 9, true);
+ ccs.push_back(separation479624976);
+
+ SeparationConstraint *separation479625040 = new SeparationConstraint(vpsc::XDIM, 52, 54, -40, true);
+ ccs.push_back(separation479625040);
+
+ SeparationConstraint *separation479625104 = new SeparationConstraint(vpsc::YDIM, 52, 54, 15.5, true);
+ ccs.push_back(separation479625104);
+
+ SeparationConstraint *separation479625168 = new SeparationConstraint(vpsc::XDIM, 52, 55, -40, true);
+ ccs.push_back(separation479625168);
+
+ SeparationConstraint *separation479625232 = new SeparationConstraint(vpsc::YDIM, 52, 55, 2.5, true);
+ ccs.push_back(separation479625232);
+
+ SeparationConstraint *separation479625296 = new SeparationConstraint(vpsc::XDIM, 56, 57, 36.5, true);
+ ccs.push_back(separation479625296);
+
+ SeparationConstraint *separation479625360 = new SeparationConstraint(vpsc::YDIM, 56, 57, 9, true);
+ ccs.push_back(separation479625360);
+
+ SeparationConstraint *separation479625424 = new SeparationConstraint(vpsc::XDIM, 56, 58, -36.5, true);
+ ccs.push_back(separation479625424);
+
+ SeparationConstraint *separation479625552 = new SeparationConstraint(vpsc::YDIM, 56, 58, 9, true);
+ ccs.push_back(separation479625552);
+
+ SeparationConstraint *separation479625616 = new SeparationConstraint(vpsc::XDIM, 59, 60, -43, true);
+ ccs.push_back(separation479625616);
+
+ SeparationConstraint *separation479625680 = new SeparationConstraint(vpsc::YDIM, 59, 60, 9, true);
+ ccs.push_back(separation479625680);
+
+ SeparationConstraint *separation479625744 = new SeparationConstraint(vpsc::XDIM, 61, 62, 62, true);
+ ccs.push_back(separation479625744);
+
+ SeparationConstraint *separation479625488 = new SeparationConstraint(vpsc::YDIM, 61, 62, 9, true);
+ ccs.push_back(separation479625488);
+
+ SeparationConstraint *separation479624464 = new SeparationConstraint(vpsc::XDIM, 61, 63, -62, true);
+ ccs.push_back(separation479624464);
+
+ SeparationConstraint *separation479623824 = new SeparationConstraint(vpsc::YDIM, 61, 63, 9, true);
+ ccs.push_back(separation479623824);
+
+ SeparationConstraint *separation479623376 = new SeparationConstraint(vpsc::XDIM, 64, 65, 41, true);
+ ccs.push_back(separation479623376);
+
+ SeparationConstraint *separation479628944 = new SeparationConstraint(vpsc::YDIM, 64, 65, 9, true);
+ ccs.push_back(separation479628944);
+
+ SeparationConstraint *separation479628880 = new SeparationConstraint(vpsc::XDIM, 64, 66, -4.5, true);
+ ccs.push_back(separation479628880);
+
+ SeparationConstraint *separation479629008 = new SeparationConstraint(vpsc::YDIM, 64, 66, 50.5, true);
+ ccs.push_back(separation479629008);
+
+ SeparationConstraint *separation479629072 = new SeparationConstraint(vpsc::XDIM, 64, 67, -41, true);
+ ccs.push_back(separation479629072);
+
+ SeparationConstraint *separation479629136 = new SeparationConstraint(vpsc::YDIM, 64, 67, 9, true);
+ ccs.push_back(separation479629136);
+
+ SeparationConstraint *separation479629200 = new SeparationConstraint(vpsc::XDIM, 68, 69, 30.5, true);
+ ccs.push_back(separation479629200);
+
+ SeparationConstraint *separation479629264 = new SeparationConstraint(vpsc::YDIM, 68, 69, 9, true);
+ ccs.push_back(separation479629264);
+
+ SeparationConstraint *separation479629328 = new SeparationConstraint(vpsc::XDIM, 68, 70, -30.5, true);
+ ccs.push_back(separation479629328);
+
+ SeparationConstraint *separation479629392 = new SeparationConstraint(vpsc::YDIM, 68, 70, 17.1667, true);
+ ccs.push_back(separation479629392);
+
+ SeparationConstraint *separation479629456 = new SeparationConstraint(vpsc::XDIM, 68, 71, -30.5, true);
+ ccs.push_back(separation479629456);
+
+ SeparationConstraint *separation479629520 = new SeparationConstraint(vpsc::YDIM, 68, 71, 0.833333, true);
+ ccs.push_back(separation479629520);
+
+ SeparationConstraint *separation479629584 = new SeparationConstraint(vpsc::XDIM, 72, 73, 49.5, true);
+ ccs.push_back(separation479629584);
+
+ SeparationConstraint *separation479629648 = new SeparationConstraint(vpsc::YDIM, 72, 73, 9, true);
+ ccs.push_back(separation479629648);
+
+ SeparationConstraint *separation479629712 = new SeparationConstraint(vpsc::XDIM, 72, 74, -49.5, true);
+ ccs.push_back(separation479629712);
+
+ SeparationConstraint *separation479629776 = new SeparationConstraint(vpsc::YDIM, 72, 74, 17.1667, true);
+ ccs.push_back(separation479629776);
+
+ SeparationConstraint *separation479629840 = new SeparationConstraint(vpsc::XDIM, 72, 75, -49.5, true);
+ ccs.push_back(separation479629840);
+
+ SeparationConstraint *separation479629904 = new SeparationConstraint(vpsc::YDIM, 72, 75, 0.833333, true);
+ ccs.push_back(separation479629904);
+
+ SeparationConstraint *separation479629968 = new SeparationConstraint(vpsc::XDIM, 76, 77, 37, true);
+ ccs.push_back(separation479629968);
+
+ SeparationConstraint *separation479630032 = new SeparationConstraint(vpsc::YDIM, 76, 77, 9, true);
+ ccs.push_back(separation479630032);
+
+ SeparationConstraint *separation479630096 = new SeparationConstraint(vpsc::XDIM, 76, 78, -37, true);
+ ccs.push_back(separation479630096);
+
+ SeparationConstraint *separation479630160 = new SeparationConstraint(vpsc::YDIM, 76, 78, 9, true);
+ ccs.push_back(separation479630160);
+
+ SeparationConstraint *separation479630224 = new SeparationConstraint(vpsc::XDIM, 79, 80, 37, true);
+ ccs.push_back(separation479630224);
+
+ SeparationConstraint *separation479630288 = new SeparationConstraint(vpsc::YDIM, 79, 80, 9, true);
+ ccs.push_back(separation479630288);
+
+ SeparationConstraint *separation479630352 = new SeparationConstraint(vpsc::XDIM, 79, 81, -0.333334, true);
+ ccs.push_back(separation479630352);
+
+ SeparationConstraint *separation479630416 = new SeparationConstraint(vpsc::YDIM, 79, 81, 53, true);
+ ccs.push_back(separation479630416);
+
+ SeparationConstraint *separation477486176 = new SeparationConstraint(vpsc::XDIM, 79, 82, -17.6667, true);
+ ccs.push_back(separation477486176);
+
+ SeparationConstraint *separation477486240 = new SeparationConstraint(vpsc::YDIM, 79, 82, 53, true);
+ ccs.push_back(separation477486240);
+
+ SeparationConstraint *separation477486304 = new SeparationConstraint(vpsc::XDIM, 79, 83, -37, true);
+ ccs.push_back(separation477486304);
+
+ SeparationConstraint *separation477486368 = new SeparationConstraint(vpsc::YDIM, 79, 83, 9, true);
+ ccs.push_back(separation477486368);
+
+ SeparationConstraint *separation477486432 = new SeparationConstraint(vpsc::XDIM, 84, 85, 33.5, true);
+ ccs.push_back(separation477486432);
+
+ SeparationConstraint *separation477486496 = new SeparationConstraint(vpsc::YDIM, 84, 85, 9, true);
+ ccs.push_back(separation477486496);
+
+ SeparationConstraint *separation477486560 = new SeparationConstraint(vpsc::XDIM, 84, 86, 3.16667, true);
+ ccs.push_back(separation477486560);
+
+ SeparationConstraint *separation477486624 = new SeparationConstraint(vpsc::YDIM, 84, 86, 53, true);
+ ccs.push_back(separation477486624);
+
+ SeparationConstraint *separation477486688 = new SeparationConstraint(vpsc::XDIM, 84, 87, -14.1667, true);
+ ccs.push_back(separation477486688);
+
+ SeparationConstraint *separation477486752 = new SeparationConstraint(vpsc::YDIM, 84, 87, 53, true);
+ ccs.push_back(separation477486752);
+
+ SeparationConstraint *separation477486816 = new SeparationConstraint(vpsc::XDIM, 84, 88, -33.5, true);
+ ccs.push_back(separation477486816);
+
+ SeparationConstraint *separation477486880 = new SeparationConstraint(vpsc::YDIM, 84, 88, 9, true);
+ ccs.push_back(separation477486880);
+
+ SeparationConstraint *separation477486944 = new SeparationConstraint(vpsc::XDIM, 89, 90, 48, true);
+ ccs.push_back(separation477486944);
+
+ SeparationConstraint *separation477487008 = new SeparationConstraint(vpsc::YDIM, 89, 90, 9, true);
+ ccs.push_back(separation477487008);
+
+ SeparationConstraint *separation477487072 = new SeparationConstraint(vpsc::XDIM, 89, 91, -48, true);
+ ccs.push_back(separation477487072);
+
+ SeparationConstraint *separation477487136 = new SeparationConstraint(vpsc::YDIM, 89, 91, 9, true);
+ ccs.push_back(separation477487136);
+
+ SeparationConstraint *separation477487200 = new SeparationConstraint(vpsc::XDIM, 7, 0, 137, false);
+ ccs.push_back(separation477487200);
+
+ SeparationConstraint *separation477487264 = new SeparationConstraint(vpsc::XDIM, 0, 5, 118.5, false);
+ ccs.push_back(separation477487264);
+
+ SeparationConstraint *separation477487328 = new SeparationConstraint(vpsc::XDIM, 79, 5, 118, false);
+ ccs.push_back(separation477487328);
+
+ SeparationConstraint *separation477487392 = new SeparationConstraint(vpsc::XDIM, 9, 15, 146.5, false);
+ ccs.push_back(separation477487392);
+
+ SeparationConstraint *separation477487456 = new SeparationConstraint(vpsc::XDIM, 28, 15, 139, false);
+ ccs.push_back(separation477487456);
+
+ SeparationConstraint *separation477487520 = new SeparationConstraint(vpsc::XDIM, 0, 22, 142.5, false);
+ ccs.push_back(separation477487520);
+
+ SeparationConstraint *separation477487584 = new SeparationConstraint(vpsc::XDIM, 0, 22, 142.5, false);
+ ccs.push_back(separation477487584);
+
+ SeparationConstraint *separation477487648 = new SeparationConstraint(vpsc::XDIM, 0, 22, 142.5, false);
+ ccs.push_back(separation477487648);
+
+ SeparationConstraint *separation477487712 = new SeparationConstraint(vpsc::XDIM, 19, 22, 137.5, false);
+ ccs.push_back(separation477487712);
+
+ SeparationConstraint *separation477487776 = new SeparationConstraint(vpsc::XDIM, 22, 28, 150, false);
+ ccs.push_back(separation477487776);
+
+ SeparationConstraint *separation477487840 = new SeparationConstraint(vpsc::XDIM, 15, 31, 151.5, false);
+ ccs.push_back(separation477487840);
+
+ SeparationConstraint *separation477487904 = new SeparationConstraint(vpsc::XDIM, 31, 37, 143.5, false);
+ ccs.push_back(separation477487904);
+
+ SeparationConstraint *separation477487968 = new SeparationConstraint(vpsc::XDIM, 31, 40, 143.5, false);
+ ccs.push_back(separation477487968);
+
+ SeparationConstraint *separation477488032 = new SeparationConstraint(vpsc::XDIM, 31, 43, 207.5, false);
+ ccs.push_back(separation477488032);
+
+ SeparationConstraint *separation477488096 = new SeparationConstraint(vpsc::XDIM, 37, 43, 235, false);
+ ccs.push_back(separation477488096);
+
+ SeparationConstraint *separation477488160 = new SeparationConstraint(vpsc::XDIM, 40, 43, 235, false);
+ ccs.push_back(separation477488160);
+
+ SeparationConstraint *separation477488224 = new SeparationConstraint(vpsc::XDIM, 49, 43, 235, false);
+ ccs.push_back(separation477488224);
+
+ SeparationConstraint *separation477488288 = new SeparationConstraint(vpsc::XDIM, 31, 49, 143.5, false);
+ ccs.push_back(separation477488288);
+
+ SeparationConstraint *separation477488352 = new SeparationConstraint(vpsc::XDIM, 31, 52, 217.5, false);
+ ccs.push_back(separation477488352);
+
+ SeparationConstraint *separation477488416 = new SeparationConstraint(vpsc::XDIM, 43, 52, 181, false);
+ ccs.push_back(separation477488416);
+
+ SeparationConstraint *separation477488480 = new SeparationConstraint(vpsc::XDIM, 52, 56, 114.5, false);
+ ccs.push_back(separation477488480);
+
+ SeparationConstraint *separation477488544 = new SeparationConstraint(vpsc::XDIM, 61, 59, 143, false);
+ ccs.push_back(separation477488544);
+
+ SeparationConstraint *separation477488608 = new SeparationConstraint(vpsc::XDIM, 56, 61, 136.5, false);
+ ccs.push_back(separation477488608);
+
+ SeparationConstraint *separation477488672 = new SeparationConstraint(vpsc::XDIM, 15, 64, 126, false);
+ ccs.push_back(separation477488672);
+
+ SeparationConstraint *separation477488736 = new SeparationConstraint(vpsc::XDIM, 56, 64, 136.5, false);
+ ccs.push_back(separation477488736);
+
+ SeparationConstraint *separation477488800 = new SeparationConstraint(vpsc::XDIM, 89, 68, 116.5, false);
+ ccs.push_back(separation477488800);
+
+ SeparationConstraint *separation477488864 = new SeparationConstraint(vpsc::XDIM, 68, 72, 131, false);
+ ccs.push_back(separation477488864);
+
+ SeparationConstraint *separation477488928 = new SeparationConstraint(vpsc::XDIM, 76, 72, 124.5, false);
+ ccs.push_back(separation477488928);
+
+ SeparationConstraint *separation477488992 = new SeparationConstraint(vpsc::XDIM, 84, 79, 108.5, false);
+ ccs.push_back(separation477488992);
+
+ SeparationConstraint *separation477489056 = new SeparationConstraint(vpsc::XDIM, 72, 84, 121, false);
+ ccs.push_back(separation477489056);
+
+ SeparationConstraint *separation477489120 = new SeparationConstraint(vpsc::XDIM, 64, 89, 127, false);
+ ccs.push_back(separation477489120);
+
+ cola::Box margin = cola::Box(10, 30, 30, 60); //30
+ cola::Box padding = cola::Box(); // cola::Box(10, 30, 30, 60); //10
+ ConstrainedFDLayout alg(rs, es, defaultEdgeLength, eLengths);
+ RootCluster *cluster476902600 = new RootCluster();
+ cluster476902600->addChildNode(0);
+ cluster476902600->addChildNode(1);
+ cluster476902600->addChildNode(2);
+ cluster476902600->addChildNode(3);
+ cluster476902600->addChildNode(4);
+ cluster476902600->addChildNode(5);
+ cluster476902600->addChildNode(6);
+ cluster476902600->addChildNode(7);
+ cluster476902600->addChildNode(8);
+ cluster476902600->addChildNode(9);
+ cluster476902600->addChildNode(10);
+ cluster476902600->addChildNode(11);
+ cluster476902600->addChildNode(12);
+ cluster476902600->addChildNode(13);
+ cluster476902600->addChildNode(14);
+ cluster476902600->addChildNode(15);
+ cluster476902600->addChildNode(16);
+ cluster476902600->addChildNode(17);
+ cluster476902600->addChildNode(18);
+ cluster476902600->addChildNode(19);
+ cluster476902600->addChildNode(20);
+ cluster476902600->addChildNode(21);
+ cluster476902600->addChildNode(22);
+ cluster476902600->addChildNode(23);
+ cluster476902600->addChildNode(24);
+ cluster476902600->addChildNode(25);
+ cluster476902600->addChildNode(26);
+ cluster476902600->addChildNode(27);
+ cluster476902600->addChildNode(28);
+ cluster476902600->addChildNode(29);
+ cluster476902600->addChildNode(30);
+ RectangularCluster *cluster417213744 = new RectangularCluster();
+ cluster417213744->setMargin(margin);
+ cluster417213744->setPadding(padding);
+ cluster417213744->addChildNode(59);
+ cluster417213744->addChildNode(60);
+ cluster417213744->addChildNode(61);
+ cluster417213744->addChildNode(62);
+ cluster417213744->addChildNode(63);
+ cluster417213744->addChildNode(64);
+ cluster417213744->addChildNode(65);
+ cluster417213744->addChildNode(66);
+ cluster417213744->addChildNode(67);
+ cluster417213744->addChildNode(89);
+ cluster417213744->addChildNode(90);
+ cluster417213744->addChildNode(91);
+ RectangularCluster *cluster417215984 = new RectangularCluster();
+ cluster417215984->setMargin(margin);
+ cluster417215984->setPadding(padding);
+ cluster417215984->addChildNode(31);
+ cluster417215984->addChildNode(32);
+ cluster417215984->addChildNode(33);
+ cluster417215984->addChildNode(34);
+ cluster417215984->addChildNode(35);
+ cluster417215984->addChildNode(36);
+ cluster417215984->addChildNode(37);
+ cluster417215984->addChildNode(38);
+ cluster417215984->addChildNode(39);
+ cluster417215984->addChildNode(40);
+ cluster417215984->addChildNode(41);
+ cluster417215984->addChildNode(42);
+ cluster417215984->addChildNode(43);
+ cluster417215984->addChildNode(44);
+ cluster417215984->addChildNode(45);
+ cluster417215984->addChildNode(46);
+ cluster417215984->addChildNode(47);
+ cluster417215984->addChildNode(48);
+ cluster417215984->addChildNode(49);
+ cluster417215984->addChildNode(50);
+ cluster417215984->addChildNode(51);
+ cluster417215984->addChildNode(52);
+ cluster417215984->addChildNode(53);
+ cluster417215984->addChildNode(54);
+ cluster417215984->addChildNode(55);
+ cluster417215984->addChildNode(56);
+ cluster417215984->addChildNode(57);
+ cluster417215984->addChildNode(58);
+ cluster417213744->addChildCluster(cluster417215984);
+ RectangularCluster *cluster417215760 = new RectangularCluster();
+ cluster417215760->setMargin(margin);
+ cluster417215760->setPadding(padding);
+ cluster417215760->addChildNode(68);
+ cluster417215760->addChildNode(69);
+ cluster417215760->addChildNode(70);
+ cluster417215760->addChildNode(71);
+ cluster417215760->addChildNode(72);
+ cluster417215760->addChildNode(73);
+ cluster417215760->addChildNode(74);
+ cluster417215760->addChildNode(75);
+ cluster417215760->addChildNode(76);
+ cluster417215760->addChildNode(77);
+ cluster417215760->addChildNode(78);
+ cluster417215760->addChildNode(79);
+ cluster417215760->addChildNode(80);
+ cluster417215760->addChildNode(81);
+ cluster417215760->addChildNode(82);
+ cluster417215760->addChildNode(83);
+ cluster417215760->addChildNode(84);
+ cluster417215760->addChildNode(85);
+ cluster417215760->addChildNode(86);
+ cluster417215760->addChildNode(87);
+ cluster417215760->addChildNode(88);
+ cluster417213744->addChildCluster(cluster417215760);
+ cluster476902600->addChildCluster(cluster417213744);
+ alg.setClusterHierarchy(cluster476902600);
+ alg.setConstraints(ccs);
+
+ UnsatisfiableConstraintInfos unsatisfiableX, unsatisfiableY;
+ alg.setUnsatisfiableConstraintInfo(&unsatisfiableX, &unsatisfiableY);
+
+ // rect-43 and associated port rects.
+ cola::NodeIndexes nonOverlapExemptGroup;
+ nonOverlapExemptGroup.push_back(44);
+ nonOverlapExemptGroup.push_back(45);
+ nonOverlapExemptGroup.push_back(46);
+ nonOverlapExemptGroup.push_back(47);
+ nonOverlapExemptGroup.push_back(48);
+ nonOverlapExemptGroup.push_back(43);
+
+ std::vector<cola::NodeIndexes> nonOverlapExemptGroupList;
+ nonOverlapExemptGroupList.push_back(nonOverlapExemptGroup);
+ alg.setAvoidNodeOverlaps(true, nonOverlapExemptGroupList);
+
+ //alg.makeFeasible();
+ alg.run();
+ alg.outputInstanceToSVG("rectangularClusters01");
+
+ for (size_t i = 0; i < unsatisfiableX.size(); ++i)
+ {
+ printf("%s\n", unsatisfiableX[i]->toString().c_str());
+ }
+ for (size_t i = 0; i < unsatisfiableY.size(); ++i)
+ {
+ printf("%s\n", unsatisfiableY[i]->toString().c_str());
+ }
+ alg.freeAssociatedObjects();
+ return (unsatisfiableX.empty() && unsatisfiableY.empty()) ? 0 : 1;
+};
diff --git a/src/3rdparty/adaptagrams/libcola/tests/rectclustershapecontainment.cpp b/src/3rdparty/adaptagrams/libcola/tests/rectclustershapecontainment.cpp
new file mode 100644
index 0000000..3c3d704
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/rectclustershapecontainment.cpp
@@ -0,0 +1,2173 @@
+#include <vector>
+#include "libcola/cola.h"
+using namespace cola;
+int main(void) {
+ CompoundConstraints ccs;
+ std::vector<Edge> es;
+ double defaultEdgeLength=40;
+ std::vector<vpsc::Rectangle*> rs;
+ vpsc::Rectangle *rect = nullptr;
+
+ rect = new vpsc::Rectangle(478, 488, 399, 409);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(284, 294, 938, 948);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(141, 151, 906, 916);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(284, 294, 959, 969);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(131, 161, 938, 968);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(550, 762, 155.5, 522.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(430, 540, -6, 158);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(373, 383, 907, 917);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(482, 492, 938, 948);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(434, 444, 938, 948);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(426, 436, 869, 879);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(426, 436, 848, 858);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(314, 324, 860, 870);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(205, 215, 860, 870);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(553, 563, 859, 869);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(345, 423, 746, 780);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(478, 488, 765, 775);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(-34.5, 162.5, 723, 877);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(478, 488, 696, 706);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(478, 488, 624, 634);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(453, 463, 479, 489);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(154.5, 457.5, 574, 624);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(398, 408, 445, 455);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(453, 463, 331, 341);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(403, 413, 331, 341);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(547, 557, 191, 201);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(478, 488, 260, 270);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(478, 488, 168, 178);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(380, 390, 297, 307);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(228, 238, 286, 296);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(228, 238, 307, 317);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(352, 362, 259, 269);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(302, 312, 259, 269);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(176, 186, 259, 269);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(228, 238, 234, 244);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(228, 238, 213, 223);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(311, 321, 181, 191);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(338, 348, 149, 159);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(338, 348, 128, 138);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(40.5, 291.5, 45.5, 70.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(257, 267, 903, 913);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(478, 488, 551, 561);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(276, 286, 213, 223);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(276, 286, 286, 296);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(176, 186, 355, 365);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(176, 186, 381, 391);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(286, 296, 354, 364);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(286, 296, 380, 390);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(586, 616, 180, 210);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(468, 498, 128, 158);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(468, 498, 649, 679);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(166, 196, 213, 243);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(166, 196, 286, 316);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(317, 347, 433, 463);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(317, 347, 286, 316);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(468, 498, 215, 245);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(468, 498, 288, 318);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(468, 498, 721, 751);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(468, 498, 577, 607);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(468, 498, 505, 535);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(612, 642, 848, 878);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(299, 329, 891, 921);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(535, 565, 938, 968);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(468, 498, 848, 878);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(363, 393, 848, 878);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(131, 161, 848, 878);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(363, 393, 938, 968);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(250, 280, 848, 878);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(197, 227, 891, 921);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(468, 498, 358, 388);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(117, 147, 344, 374);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(224, 254, 344, 374);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(224, 254, 370, 400);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(117, 147, 370, 400);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(363, 393, 805, 835);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(181, 227, 711, 741);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(131, 161, 721, 751);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(434, 444, 959, 969);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(199, 209, 742, 752);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(482, 492, 959, 969);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(565.5, 692.5, 842.5, 997.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(503, 513, 479, 489);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(577, 587, 520, 530);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(550, 560, 539, 549);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(284, 294, 790, 800);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(527, 537, 520, 530);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(383, 413, 541, 571);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(432, 442, 581, 591);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(433, 443, 517, 527);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(468, 498, 433, 463);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(91, 101, 906, 916);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(503, 513, 331, 341);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(276, 286, 234, 244);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(276, 286, 307, 317);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(522, 568, 389, 419);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(266, 312, 878, 908);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(185, 231, 896, 926);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(266, 312, 899, 929);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(417, 463, 897, 927);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(464, 510, 878, 908);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(416, 462, 878, 908);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(470, 516, 859, 889);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(470, 516, 838, 868);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(358, 404, 850, 880);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(187, 233, 800, 830);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(535, 581, 799, 829);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(522, 568, 755, 785);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(522, 568, 686, 716);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(522, 568, 614, 644);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(497, 543, 469, 499);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(380, 426, 385, 415);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(497, 543, 321, 351);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(385, 431, 271, 301);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(529, 575, 131, 161);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(522, 568, 250, 280);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(522, 568, 158, 188);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(362, 408, 237, 267);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(210, 256, 226, 256);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(210, 256, 247, 277);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(396, 442, 249, 279);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(346, 392, 249, 279);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(220, 266, 249, 279);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(210, 256, 174, 204);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(210, 256, 153, 183);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(293, 339, 121, 151);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(320, 366, 89, 119);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(320, 366, 68, 98);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(239, 285, 843, 873);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(522, 568, 541, 571);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(258, 304, 153, 183);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(258, 304, 226, 256);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(158, 204, 295, 325);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(158, 204, 321, 351);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(268, 314, 294, 324);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(268, 314, 320, 350);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(416, 462, 899, 929);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(181, 227, 682, 712);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(464, 510, 899, 929);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(547, 593, 469, 499);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(559, 605, 460, 490);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(532, 578, 479, 509);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(266, 312, 730, 760);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(571, 617, 510, 540);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(414, 460, 521, 551);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(415, 461, 457, 487);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(73, 119, 846, 876);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(547, 593, 321, 351);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(258, 304, 174, 204);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(258, 304, 247, 277);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(550.5, 600.5, 304.5, 334.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(550.5, 600.5, 344.5, 374.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(621.5, 651.5, 473, 523);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(661.5, 691.5, 473, 523);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(470.5, 500.5, 108.5, 158.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(113, 163, 765.5, 795.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(113, 163, 805.5, 835.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(408, 458, 584.5, 614.5);
+ rs.push_back(rect);
+
+ rect = new vpsc::Rectangle(614.5, 644.5, 843, 893);
+ rs.push_back(rect);
+
+ AlignmentConstraint *alignment140664475503328 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475503328->addShape(0, 0);
+ alignment140664475503328->addShape(16, 0);
+ alignment140664475503328->addShape(18, 0);
+ alignment140664475503328->addShape(19, 0);
+ alignment140664475503328->addShape(26, 0);
+ alignment140664475503328->addShape(27, 0);
+ alignment140664475503328->addShape(41, 0);
+ alignment140664475503328->addShape(49, 0);
+ alignment140664475503328->addShape(50, 0);
+ alignment140664475503328->addShape(55, 0);
+ alignment140664475503328->addShape(56, 0);
+ alignment140664475503328->addShape(57, 0);
+ alignment140664475503328->addShape(58, 0);
+ alignment140664475503328->addShape(59, 0);
+ alignment140664475503328->addShape(63, 0);
+ alignment140664475503328->addShape(69, 0);
+ alignment140664475503328->addShape(89, 0);
+ ccs.push_back(alignment140664475503328);
+
+ AlignmentConstraint *alignment140664481097440 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664481097440->addShape(1, 0);
+ alignment140664481097440->addShape(3, 0);
+ alignment140664481097440->addShape(46, 0);
+ alignment140664481097440->addShape(47, 0);
+ alignment140664481097440->addShape(84, 0);
+ ccs.push_back(alignment140664481097440);
+
+ AlignmentConstraint *alignment140664483416688 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664483416688->addShape(2, 0);
+ alignment140664483416688->addShape(4, 0);
+ alignment140664483416688->addShape(65, 0);
+ alignment140664483416688->addShape(76, 0);
+ ccs.push_back(alignment140664483416688);
+
+ AlignmentConstraint *alignment140664481096784 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664481096784->addShape(3, 0);
+ alignment140664481096784->addShape(46, 0);
+ alignment140664481096784->addShape(47, 0);
+ alignment140664481096784->addShape(84, 0);
+ ccs.push_back(alignment140664481096784);
+
+ AlignmentConstraint *alignment140664475503952 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475503952->addShape(4, 0);
+ alignment140664475503952->addShape(65, 0);
+ alignment140664475503952->addShape(76, 0);
+ ccs.push_back(alignment140664475503952);
+
+ AlignmentConstraint *alignment140664475504304 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475504304->addShape(7, 0);
+ alignment140664475504304->addShape(64, 0);
+ alignment140664475504304->addShape(66, 0);
+ alignment140664475504304->addShape(74, 0);
+ ccs.push_back(alignment140664475504304);
+
+ AlignmentConstraint *alignment140664475504496 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475504496->addShape(8, 0);
+ alignment140664475504496->addShape(79, 0);
+ ccs.push_back(alignment140664475504496);
+
+ AlignmentConstraint *alignment140664475504720 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475504720->addShape(9, 0);
+ alignment140664475504720->addShape(77, 0);
+ alignment140664475504720->addShape(87, 0);
+ alignment140664475504720->addShape(88, 0);
+ ccs.push_back(alignment140664475504720);
+
+ AlignmentConstraint *alignment140664483418000 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664483418000->addShape(10, 0);
+ alignment140664483418000->addShape(11, 0);
+ ccs.push_back(alignment140664483418000);
+
+ AlignmentConstraint *alignment140664483418368 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664483418368->addShape(11, 0);
+ ccs.push_back(alignment140664483418368);
+
+ AlignmentConstraint *alignment140664483418496 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664483418496->addShape(12, 0);
+ ccs.push_back(alignment140664483418496);
+
+ AlignmentConstraint *alignment140664483418656 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664483418656->addShape(13, 0);
+ alignment140664483418656->addShape(68, 0);
+ ccs.push_back(alignment140664483418656);
+
+ AlignmentConstraint *alignment140664483418880 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664483418880->addShape(14, 0);
+ ccs.push_back(alignment140664483418880);
+
+ AlignmentConstraint *alignment140664483419008 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664483419008->addShape(16, 0);
+ alignment140664483419008->addShape(18, 0);
+ alignment140664483419008->addShape(19, 0);
+ alignment140664483419008->addShape(26, 0);
+ alignment140664483419008->addShape(27, 0);
+ alignment140664483419008->addShape(41, 0);
+ alignment140664483419008->addShape(49, 0);
+ alignment140664483419008->addShape(50, 0);
+ alignment140664483419008->addShape(55, 0);
+ alignment140664483419008->addShape(56, 0);
+ alignment140664483419008->addShape(57, 0);
+ alignment140664483419008->addShape(58, 0);
+ alignment140664483419008->addShape(59, 0);
+ alignment140664483419008->addShape(63, 0);
+ alignment140664483419008->addShape(69, 0);
+ alignment140664483419008->addShape(89, 0);
+ ccs.push_back(alignment140664483419008);
+
+ AlignmentConstraint *alignment140664476991552 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476991552->addShape(18, 0);
+ alignment140664476991552->addShape(19, 0);
+ alignment140664476991552->addShape(26, 0);
+ alignment140664476991552->addShape(27, 0);
+ alignment140664476991552->addShape(41, 0);
+ alignment140664476991552->addShape(49, 0);
+ alignment140664476991552->addShape(50, 0);
+ alignment140664476991552->addShape(55, 0);
+ alignment140664476991552->addShape(56, 0);
+ alignment140664476991552->addShape(57, 0);
+ alignment140664476991552->addShape(58, 0);
+ alignment140664476991552->addShape(59, 0);
+ alignment140664476991552->addShape(63, 0);
+ alignment140664476991552->addShape(69, 0);
+ alignment140664476991552->addShape(89, 0);
+ ccs.push_back(alignment140664476991552);
+
+ AlignmentConstraint *alignment140664476992272 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476992272->addShape(19, 0);
+ alignment140664476992272->addShape(26, 0);
+ alignment140664476992272->addShape(27, 0);
+ alignment140664476992272->addShape(41, 0);
+ alignment140664476992272->addShape(49, 0);
+ alignment140664476992272->addShape(50, 0);
+ alignment140664476992272->addShape(55, 0);
+ alignment140664476992272->addShape(56, 0);
+ alignment140664476992272->addShape(57, 0);
+ alignment140664476992272->addShape(58, 0);
+ alignment140664476992272->addShape(59, 0);
+ alignment140664476992272->addShape(63, 0);
+ alignment140664476992272->addShape(69, 0);
+ alignment140664476992272->addShape(89, 0);
+ ccs.push_back(alignment140664476992272);
+
+ AlignmentConstraint *alignment140664476992960 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476992960->addShape(20, 0);
+ alignment140664476992960->addShape(23, 0);
+ ccs.push_back(alignment140664476992960);
+
+ AlignmentConstraint *alignment140664476993456 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476993456->addShape(22, 0);
+ ccs.push_back(alignment140664476993456);
+
+ AlignmentConstraint *alignment140664476993584 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476993584->addShape(23, 0);
+ ccs.push_back(alignment140664476993584);
+
+ AlignmentConstraint *alignment140664476993744 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476993744->addShape(24, 0);
+ ccs.push_back(alignment140664476993744);
+
+ AlignmentConstraint *alignment140664476993904 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476993904->addShape(25, 0);
+ alignment140664476993904->addShape(62, 0);
+ ccs.push_back(alignment140664476993904);
+
+ AlignmentConstraint *alignment140664476994128 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476994128->addShape(26, 0);
+ alignment140664476994128->addShape(27, 0);
+ alignment140664476994128->addShape(41, 0);
+ alignment140664476994128->addShape(49, 0);
+ alignment140664476994128->addShape(50, 0);
+ alignment140664476994128->addShape(55, 0);
+ alignment140664476994128->addShape(56, 0);
+ alignment140664476994128->addShape(57, 0);
+ alignment140664476994128->addShape(58, 0);
+ alignment140664476994128->addShape(59, 0);
+ alignment140664476994128->addShape(63, 0);
+ alignment140664476994128->addShape(69, 0);
+ alignment140664476994128->addShape(89, 0);
+ ccs.push_back(alignment140664476994128);
+
+ AlignmentConstraint *alignment140664476994608 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476994608->addShape(27, 0);
+ alignment140664476994608->addShape(41, 0);
+ alignment140664476994608->addShape(49, 0);
+ alignment140664476994608->addShape(50, 0);
+ alignment140664476994608->addShape(55, 0);
+ alignment140664476994608->addShape(56, 0);
+ alignment140664476994608->addShape(57, 0);
+ alignment140664476994608->addShape(58, 0);
+ alignment140664476994608->addShape(59, 0);
+ alignment140664476994608->addShape(63, 0);
+ alignment140664476994608->addShape(69, 0);
+ alignment140664476994608->addShape(89, 0);
+ ccs.push_back(alignment140664476994608);
+
+ AlignmentConstraint *alignment140664476995232 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476995232->addShape(28, 0);
+ ccs.push_back(alignment140664476995232);
+
+ AlignmentConstraint *alignment140664476995392 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476995392->addShape(29, 0);
+ alignment140664476995392->addShape(30, 0);
+ alignment140664476995392->addShape(34, 0);
+ alignment140664476995392->addShape(35, 0);
+ ccs.push_back(alignment140664476995392);
+
+ AlignmentConstraint *alignment140664476995616 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476995616->addShape(30, 0);
+ alignment140664476995616->addShape(34, 0);
+ alignment140664476995616->addShape(35, 0);
+ ccs.push_back(alignment140664476995616);
+
+ AlignmentConstraint *alignment140664476995888 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476995888->addShape(31, 0);
+ ccs.push_back(alignment140664476995888);
+
+ AlignmentConstraint *alignment140664476996016 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476996016->addShape(32, 0);
+ ccs.push_back(alignment140664476996016);
+
+ AlignmentConstraint *alignment140664476996176 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476996176->addShape(33, 0);
+ alignment140664476996176->addShape(44, 0);
+ alignment140664476996176->addShape(45, 0);
+ alignment140664476996176->addShape(51, 0);
+ alignment140664476996176->addShape(52, 0);
+ ccs.push_back(alignment140664476996176);
+
+ AlignmentConstraint *alignment140664476996480 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476996480->addShape(34, 0);
+ alignment140664476996480->addShape(35, 0);
+ ccs.push_back(alignment140664476996480);
+
+ AlignmentConstraint *alignment140664476996704 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476996704->addShape(35, 0);
+ ccs.push_back(alignment140664476996704);
+
+ AlignmentConstraint *alignment140664476996832 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476996832->addShape(36, 0);
+ alignment140664476996832->addShape(61, 0);
+ ccs.push_back(alignment140664476996832);
+
+ AlignmentConstraint *alignment140664476997056 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476997056->addShape(37, 0);
+ alignment140664476997056->addShape(38, 0);
+ ccs.push_back(alignment140664476997056);
+
+ AlignmentConstraint *alignment140664476993184 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476993184->addShape(38, 0);
+ ccs.push_back(alignment140664476993184);
+
+ AlignmentConstraint *alignment140664476993312 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476993312->addShape(40, 0);
+ ccs.push_back(alignment140664476993312);
+
+ AlignmentConstraint *alignment140664476997808 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476997808->addShape(41, 0);
+ alignment140664476997808->addShape(49, 0);
+ alignment140664476997808->addShape(50, 0);
+ alignment140664476997808->addShape(55, 0);
+ alignment140664476997808->addShape(56, 0);
+ alignment140664476997808->addShape(57, 0);
+ alignment140664476997808->addShape(58, 0);
+ alignment140664476997808->addShape(59, 0);
+ alignment140664476997808->addShape(63, 0);
+ alignment140664476997808->addShape(69, 0);
+ alignment140664476997808->addShape(89, 0);
+ ccs.push_back(alignment140664476997808);
+
+ AlignmentConstraint *alignment140664476998480 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476998480->addShape(42, 0);
+ alignment140664476998480->addShape(43, 0);
+ alignment140664476998480->addShape(92, 0);
+ alignment140664476998480->addShape(93, 0);
+ ccs.push_back(alignment140664476998480);
+
+ AlignmentConstraint *alignment140664476998704 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476998704->addShape(43, 0);
+ alignment140664476998704->addShape(92, 0);
+ alignment140664476998704->addShape(93, 0);
+ ccs.push_back(alignment140664476998704);
+
+ AlignmentConstraint *alignment140664476998976 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476998976->addShape(44, 0);
+ alignment140664476998976->addShape(45, 0);
+ alignment140664476998976->addShape(51, 0);
+ alignment140664476998976->addShape(52, 0);
+ ccs.push_back(alignment140664476998976);
+
+ AlignmentConstraint *alignment140664476999216 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476999216->addShape(45, 0);
+ alignment140664476999216->addShape(51, 0);
+ alignment140664476999216->addShape(52, 0);
+ ccs.push_back(alignment140664476999216);
+
+ AlignmentConstraint *alignment140664476999488 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476999488->addShape(46, 0);
+ alignment140664476999488->addShape(47, 0);
+ alignment140664476999488->addShape(84, 0);
+ ccs.push_back(alignment140664476999488);
+
+ AlignmentConstraint *alignment140664476999728 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476999728->addShape(47, 0);
+ alignment140664476999728->addShape(84, 0);
+ ccs.push_back(alignment140664476999728);
+
+ AlignmentConstraint *alignment140664476999920 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476999920->addShape(48, 0);
+ ccs.push_back(alignment140664476999920);
+
+ AlignmentConstraint *alignment140664477000048 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477000048->addShape(49, 0);
+ alignment140664477000048->addShape(50, 0);
+ alignment140664477000048->addShape(55, 0);
+ alignment140664477000048->addShape(56, 0);
+ alignment140664477000048->addShape(57, 0);
+ alignment140664477000048->addShape(58, 0);
+ alignment140664477000048->addShape(59, 0);
+ alignment140664477000048->addShape(63, 0);
+ alignment140664477000048->addShape(69, 0);
+ alignment140664477000048->addShape(89, 0);
+ ccs.push_back(alignment140664477000048);
+
+ AlignmentConstraint *alignment140664477000656 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477000656->addShape(50, 0);
+ alignment140664477000656->addShape(55, 0);
+ alignment140664477000656->addShape(56, 0);
+ alignment140664477000656->addShape(57, 0);
+ alignment140664477000656->addShape(58, 0);
+ alignment140664477000656->addShape(59, 0);
+ alignment140664477000656->addShape(63, 0);
+ alignment140664477000656->addShape(69, 0);
+ alignment140664477000656->addShape(89, 0);
+ ccs.push_back(alignment140664477000656);
+
+ AlignmentConstraint *alignment140664477001184 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477001184->addShape(51, 0);
+ alignment140664477001184->addShape(52, 0);
+ ccs.push_back(alignment140664477001184);
+
+ AlignmentConstraint *alignment140664477001408 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477001408->addShape(52, 0);
+ ccs.push_back(alignment140664477001408);
+
+ AlignmentConstraint *alignment140664477001536 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477001536->addShape(53, 0);
+ alignment140664477001536->addShape(54, 0);
+ ccs.push_back(alignment140664477001536);
+
+ AlignmentConstraint *alignment140664477001760 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477001760->addShape(54, 0);
+ ccs.push_back(alignment140664477001760);
+
+ AlignmentConstraint *alignment140664477001888 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477001888->addShape(55, 0);
+ alignment140664477001888->addShape(56, 0);
+ alignment140664477001888->addShape(57, 0);
+ alignment140664477001888->addShape(58, 0);
+ alignment140664477001888->addShape(59, 0);
+ alignment140664477001888->addShape(63, 0);
+ alignment140664477001888->addShape(69, 0);
+ alignment140664477001888->addShape(89, 0);
+ ccs.push_back(alignment140664477001888);
+
+ AlignmentConstraint *alignment140664477002240 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477002240->addShape(56, 0);
+ alignment140664477002240->addShape(57, 0);
+ alignment140664477002240->addShape(58, 0);
+ alignment140664477002240->addShape(59, 0);
+ alignment140664477002240->addShape(63, 0);
+ alignment140664477002240->addShape(69, 0);
+ alignment140664477002240->addShape(89, 0);
+ ccs.push_back(alignment140664477002240);
+
+ AlignmentConstraint *alignment140664477002640 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477002640->addShape(57, 0);
+ alignment140664477002640->addShape(58, 0);
+ alignment140664477002640->addShape(59, 0);
+ alignment140664477002640->addShape(63, 0);
+ alignment140664477002640->addShape(69, 0);
+ alignment140664477002640->addShape(89, 0);
+ ccs.push_back(alignment140664477002640);
+
+ AlignmentConstraint *alignment140664477003008 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477003008->addShape(58, 0);
+ alignment140664477003008->addShape(59, 0);
+ alignment140664477003008->addShape(63, 0);
+ alignment140664477003008->addShape(69, 0);
+ alignment140664477003008->addShape(89, 0);
+ ccs.push_back(alignment140664477003008);
+
+ AlignmentConstraint *alignment140664477003344 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477003344->addShape(59, 0);
+ alignment140664477003344->addShape(63, 0);
+ alignment140664477003344->addShape(69, 0);
+ alignment140664477003344->addShape(89, 0);
+ ccs.push_back(alignment140664477003344);
+
+ AlignmentConstraint *alignment140664477003568 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477003568->addShape(60, 0);
+ ccs.push_back(alignment140664477003568);
+
+ AlignmentConstraint *alignment140664477003728 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477003728->addShape(61, 0);
+ ccs.push_back(alignment140664477003728);
+
+ AlignmentConstraint *alignment140664477003888 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477003888->addShape(62, 0);
+ ccs.push_back(alignment140664477003888);
+
+ AlignmentConstraint *alignment140664477004048 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477004048->addShape(63, 0);
+ alignment140664477004048->addShape(69, 0);
+ alignment140664477004048->addShape(89, 0);
+ ccs.push_back(alignment140664477004048);
+
+ AlignmentConstraint *alignment140664477004320 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477004320->addShape(64, 0);
+ alignment140664477004320->addShape(66, 0);
+ alignment140664477004320->addShape(74, 0);
+ ccs.push_back(alignment140664477004320);
+
+ AlignmentConstraint *alignment140664477004560 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477004560->addShape(65, 0);
+ alignment140664477004560->addShape(76, 0);
+ ccs.push_back(alignment140664477004560);
+
+ AlignmentConstraint *alignment140664477004752 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477004752->addShape(66, 0);
+ alignment140664477004752->addShape(74, 0);
+ ccs.push_back(alignment140664477004752);
+
+ AlignmentConstraint *alignment140664477004944 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477004944->addShape(67, 0);
+ ccs.push_back(alignment140664477004944);
+
+ AlignmentConstraint *alignment140664477005072 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477005072->addShape(68, 0);
+ ccs.push_back(alignment140664477005072);
+
+ AlignmentConstraint *alignment140664477005232 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477005232->addShape(69, 0);
+ alignment140664477005232->addShape(89, 0);
+ ccs.push_back(alignment140664477005232);
+
+ AlignmentConstraint *alignment140664477005456 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477005456->addShape(70, 0);
+ alignment140664477005456->addShape(73, 0);
+ ccs.push_back(alignment140664477005456);
+
+ AlignmentConstraint *alignment140664477005648 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664477005648->addShape(71, 0);
+ alignment140664477005648->addShape(72, 0);
+ ccs.push_back(alignment140664477005648);
+
+ AlignmentConstraint *alignment140664476997248 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476997248->addShape(72, 0);
+ ccs.push_back(alignment140664476997248);
+
+ AlignmentConstraint *alignment140664476997376 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476997376->addShape(73, 0);
+ ccs.push_back(alignment140664476997376);
+
+ AlignmentConstraint *alignment140664476997536 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664476997536->addShape(74, 0);
+ ccs.push_back(alignment140664476997536);
+
+ AlignmentConstraint *alignment140664475640112 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475640112->addShape(76, 0);
+ ccs.push_back(alignment140664475640112);
+
+ AlignmentConstraint *alignment140664475640272 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475640272->addShape(77, 0);
+ alignment140664475640272->addShape(87, 0);
+ alignment140664475640272->addShape(88, 0);
+ ccs.push_back(alignment140664475640272);
+
+ AlignmentConstraint *alignment140664475640544 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475640544->addShape(78, 0);
+ ccs.push_back(alignment140664475640544);
+
+ AlignmentConstraint *alignment140664475640672 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475640672->addShape(79, 0);
+ ccs.push_back(alignment140664475640672);
+
+ AlignmentConstraint *alignment140664475640832 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475640832->addShape(81, 0);
+ alignment140664475640832->addShape(91, 0);
+ ccs.push_back(alignment140664475640832);
+
+ AlignmentConstraint *alignment140664475641056 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475641056->addShape(82, 0);
+ ccs.push_back(alignment140664475641056);
+
+ AlignmentConstraint *alignment140664475641184 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475641184->addShape(83, 0);
+ ccs.push_back(alignment140664475641184);
+
+ AlignmentConstraint *alignment140664475641344 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475641344->addShape(84, 0);
+ ccs.push_back(alignment140664475641344);
+
+ AlignmentConstraint *alignment140664475641504 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475641504->addShape(85, 0);
+ ccs.push_back(alignment140664475641504);
+
+ AlignmentConstraint *alignment140664475641664 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475641664->addShape(86, 0);
+ ccs.push_back(alignment140664475641664);
+
+ AlignmentConstraint *alignment140664475641824 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475641824->addShape(87, 0);
+ alignment140664475641824->addShape(88, 0);
+ ccs.push_back(alignment140664475641824);
+
+ AlignmentConstraint *alignment140664475642048 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475642048->addShape(88, 0);
+ ccs.push_back(alignment140664475642048);
+
+ AlignmentConstraint *alignment140664475642176 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475642176->addShape(89, 0);
+ ccs.push_back(alignment140664475642176);
+
+ AlignmentConstraint *alignment140664475642336 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475642336->addShape(90, 0);
+ ccs.push_back(alignment140664475642336);
+
+ AlignmentConstraint *alignment140664475642496 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475642496->addShape(91, 0);
+ ccs.push_back(alignment140664475642496);
+
+ AlignmentConstraint *alignment140664475642656 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475642656->addShape(92, 0);
+ alignment140664475642656->addShape(93, 0);
+ ccs.push_back(alignment140664475642656);
+
+ AlignmentConstraint *alignment140664475642880 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475642880->addShape(93, 0);
+ ccs.push_back(alignment140664475642880);
+
+ SeparationConstraint *separation140664475644192 = new SeparationConstraint(vpsc::XDIM, alignment140664475642336, alignment140664476997376, 36, false);
+ ccs.push_back(separation140664475644192);
+
+ SeparationConstraint *separation140664481097840 = new SeparationConstraint(vpsc::XDIM, alignment140664476997376, alignment140664475640112, 14, false);
+ ccs.push_back(separation140664481097840);
+
+ SeparationConstraint *separation140664476990640 = new SeparationConstraint(vpsc::XDIM, alignment140664475640112, alignment140664477001408, 35, false);
+ ccs.push_back(separation140664476990640);
+
+ SeparationConstraint *separation140664481098032 = new SeparationConstraint(vpsc::XDIM, alignment140664477001408, alignment140664475640544, 23, false);
+ ccs.push_back(separation140664481098032);
+
+ SeparationConstraint *separation140664481098176 = new SeparationConstraint(vpsc::XDIM, alignment140664475640544, alignment140664483418656, 7, false);
+ ccs.push_back(separation140664481098176);
+
+ SeparationConstraint *separation140664481098320 = new SeparationConstraint(vpsc::XDIM, alignment140664477005072, alignment140664476996704, 21, false);
+ ccs.push_back(separation140664481098320);
+
+ SeparationConstraint *separation140664481098496 = new SeparationConstraint(vpsc::XDIM, alignment140664476996704, alignment140664476997248, 6, false);
+ ccs.push_back(separation140664481098496);
+
+ SeparationConstraint *separation140664481098672 = new SeparationConstraint(vpsc::XDIM, alignment140664476997248, alignment140664476993312, 23, false);
+ ccs.push_back(separation140664481098672);
+
+ SeparationConstraint *separation140664476989584 = new SeparationConstraint(vpsc::XDIM, alignment140664476993312, alignment140664477004944, 3, false);
+ ccs.push_back(separation140664476989584);
+
+ SeparationConstraint *separation140664476989760 = new SeparationConstraint(vpsc::XDIM, alignment140664477004944, alignment140664475642880, 16, false);
+ ccs.push_back(separation140664476989760);
+
+ SeparationConstraint *separation140664476989936 = new SeparationConstraint(vpsc::XDIM, alignment140664475642880, alignment140664475641344, 8, false);
+ ccs.push_back(separation140664476989936);
+
+ SeparationConstraint *separation140664476990112 = new SeparationConstraint(vpsc::XDIM, alignment140664476999488, alignment140664476996016, 16.6667, false);
+ ccs.push_back(separation140664476990112);
+
+ SeparationConstraint *separation140664476990288 = new SeparationConstraint(vpsc::XDIM, alignment140664476996016, alignment140664477003728, 7, false);
+ ccs.push_back(separation140664476990288);
+
+ SeparationConstraint *separation140664476990464 = new SeparationConstraint(vpsc::XDIM, alignment140664476996832, alignment140664483418496, 4, false);
+ ccs.push_back(separation140664476990464);
+
+ SeparationConstraint *separation140664475645632 = new SeparationConstraint(vpsc::XDIM, alignment140664483418496, alignment140664477001760, 13, false);
+ ccs.push_back(separation140664475645632);
+
+ SeparationConstraint *separation140664475645808 = new SeparationConstraint(vpsc::XDIM, alignment140664477001760, alignment140664476993184, 11, false);
+ ccs.push_back(separation140664475645808);
+
+ SeparationConstraint *separation140664475645984 = new SeparationConstraint(vpsc::XDIM, alignment140664476993184, alignment140664476995888, 14, false);
+ ccs.push_back(separation140664475645984);
+
+ SeparationConstraint *separation140664475646160 = new SeparationConstraint(vpsc::XDIM, alignment140664476995888, alignment140664476997536, 21, false);
+ ccs.push_back(separation140664475646160);
+
+ SeparationConstraint *separation140664475646336 = new SeparationConstraint(vpsc::XDIM, alignment140664476997536, alignment140664476995232, 7, false);
+ ccs.push_back(separation140664475646336);
+
+ SeparationConstraint *separation140664475646512 = new SeparationConstraint(vpsc::XDIM, alignment140664476995232, alignment140664475641664, 13, false);
+ ccs.push_back(separation140664475646512);
+
+ SeparationConstraint *separation140664475646688 = new SeparationConstraint(vpsc::XDIM, alignment140664475641664, alignment140664476993456, 5, false);
+ ccs.push_back(separation140664475646688);
+
+ SeparationConstraint *separation140664475646864 = new SeparationConstraint(vpsc::XDIM, alignment140664476993456, alignment140664476993744, 5, false);
+ ccs.push_back(separation140664475646864);
+
+ SeparationConstraint *separation140664475647040 = new SeparationConstraint(vpsc::XDIM, alignment140664476993744, alignment140664483418368, 23, false);
+ ccs.push_back(separation140664475647040);
+
+ SeparationConstraint *separation140664475647216 = new SeparationConstraint(vpsc::XDIM, alignment140664483418368, alignment140664475641824, 6.5, false);
+ ccs.push_back(separation140664475647216);
+
+ SeparationConstraint *separation140664475647392 = new SeparationConstraint(vpsc::XDIM, alignment140664475504720, alignment140664476993584, 19.75, false);
+ ccs.push_back(separation140664475647392);
+
+ SeparationConstraint *separation140664475647568 = new SeparationConstraint(vpsc::XDIM, alignment140664476993584, alignment140664475642176, 25, false);
+ ccs.push_back(separation140664475647568);
+
+ SeparationConstraint *separation140664475647744 = new SeparationConstraint(vpsc::XDIM, alignment140664475642176, alignment140664475640672, 4, false);
+ ccs.push_back(separation140664475647744);
+
+ SeparationConstraint *separation140664475647920 = new SeparationConstraint(vpsc::XDIM, alignment140664475640672, alignment140664475642496, 21, false);
+ ccs.push_back(separation140664475647920);
+
+ SeparationConstraint *separation140664475648096 = new SeparationConstraint(vpsc::XDIM, alignment140664475642496, alignment140664475641504, 24, false);
+ ccs.push_back(separation140664475648096);
+
+ SeparationConstraint *separation140664475648272 = new SeparationConstraint(vpsc::XDIM, alignment140664475641504, alignment140664477003888, 18, false);
+ ccs.push_back(separation140664475648272);
+
+ SeparationConstraint *separation140664475648448 = new SeparationConstraint(vpsc::XDIM, alignment140664476993904, alignment140664475641184, 4, false);
+ ccs.push_back(separation140664475648448);
+
+ SeparationConstraint *separation140664475648624 = new SeparationConstraint(vpsc::XDIM, alignment140664475641184, alignment140664483418880, 3, false);
+ ccs.push_back(separation140664475648624);
+
+ SeparationConstraint *separation140664475648800 = new SeparationConstraint(vpsc::XDIM, alignment140664483418880, alignment140664475641056, 24, false);
+ ccs.push_back(separation140664475648800);
+
+ SeparationConstraint *separation140664475648976 = new SeparationConstraint(vpsc::XDIM, alignment140664475641056, alignment140664476999920, 19, false);
+ ccs.push_back(separation140664475648976);
+
+ SeparationConstraint *separation140664475649152 = new SeparationConstraint(vpsc::XDIM, alignment140664476999920, alignment140664477003568, 26, false);
+ ccs.push_back(separation140664475649152);
+
+ AlignmentConstraint *alignment140664475649328 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475649328->addShape(0, 0);
+ ccs.push_back(alignment140664475649328);
+
+ AlignmentConstraint *alignment140664475649488 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475649488->addShape(1, 0);
+ alignment140664475649488->addShape(8, 0);
+ alignment140664475649488->addShape(9, 0);
+ ccs.push_back(alignment140664475649488);
+
+ AlignmentConstraint *alignment140664475649760 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475649760->addShape(2, 0);
+ alignment140664475649760->addShape(7, 0);
+ alignment140664475649760->addShape(90, 0);
+ ccs.push_back(alignment140664475649760);
+
+ AlignmentConstraint *alignment140664475650000 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475650000->addShape(3, 0);
+ alignment140664475650000->addShape(77, 0);
+ alignment140664475650000->addShape(79, 0);
+ ccs.push_back(alignment140664475650000);
+
+ AlignmentConstraint *alignment140664475650240 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475650240->addShape(4, 0);
+ alignment140664475650240->addShape(62, 0);
+ alignment140664475650240->addShape(66, 0);
+ ccs.push_back(alignment140664475650240);
+
+ AlignmentConstraint *alignment140664475650480 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475650480->addShape(7, 0);
+ alignment140664475650480->addShape(90, 0);
+ ccs.push_back(alignment140664475650480);
+
+ AlignmentConstraint *alignment140664475650672 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475650672->addShape(8, 0);
+ alignment140664475650672->addShape(9, 0);
+ ccs.push_back(alignment140664475650672);
+
+ AlignmentConstraint *alignment140664475650864 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475650864->addShape(9, 0);
+ ccs.push_back(alignment140664475650864);
+
+ AlignmentConstraint *alignment140664475639072 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475639072->addShape(10, 0);
+ ccs.push_back(alignment140664475639072);
+
+ AlignmentConstraint *alignment140664475639232 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475639232->addShape(11, 0);
+ ccs.push_back(alignment140664475639232);
+
+ AlignmentConstraint *alignment140664475639392 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475639392->addShape(12, 0);
+ alignment140664475639392->addShape(13, 0);
+ alignment140664475639392->addShape(14, 0);
+ alignment140664475639392->addShape(60, 0);
+ alignment140664475639392->addShape(63, 0);
+ alignment140664475639392->addShape(64, 0);
+ alignment140664475639392->addShape(65, 0);
+ alignment140664475639392->addShape(67, 0);
+ ccs.push_back(alignment140664475639392);
+
+ AlignmentConstraint *alignment140664475639872 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475639872->addShape(13, 0);
+ alignment140664475639872->addShape(14, 0);
+ alignment140664475639872->addShape(60, 0);
+ alignment140664475639872->addShape(63, 0);
+ alignment140664475639872->addShape(64, 0);
+ alignment140664475639872->addShape(65, 0);
+ alignment140664475639872->addShape(67, 0);
+ ccs.push_back(alignment140664475639872);
+
+ AlignmentConstraint *alignment140664475653264 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475653264->addShape(14, 0);
+ alignment140664475653264->addShape(60, 0);
+ alignment140664475653264->addShape(63, 0);
+ alignment140664475653264->addShape(64, 0);
+ alignment140664475653264->addShape(65, 0);
+ alignment140664475653264->addShape(67, 0);
+ ccs.push_back(alignment140664475653264);
+
+ AlignmentConstraint *alignment140664475653632 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475653632->addShape(16, 0);
+ ccs.push_back(alignment140664475653632);
+
+ AlignmentConstraint *alignment140664475653792 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475653792->addShape(18, 0);
+ ccs.push_back(alignment140664475653792);
+
+ AlignmentConstraint *alignment140664475653952 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475653952->addShape(19, 0);
+ ccs.push_back(alignment140664475653952);
+
+ AlignmentConstraint *alignment140664475654112 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475654112->addShape(20, 0);
+ alignment140664475654112->addShape(81, 0);
+ ccs.push_back(alignment140664475654112);
+
+ AlignmentConstraint *alignment140664475654336 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475654336->addShape(22, 0);
+ alignment140664475654336->addShape(53, 0);
+ alignment140664475654336->addShape(89, 0);
+ ccs.push_back(alignment140664475654336);
+
+ AlignmentConstraint *alignment140664475654528 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475654528->addShape(23, 0);
+ alignment140664475654528->addShape(24, 0);
+ alignment140664475654528->addShape(91, 0);
+ ccs.push_back(alignment140664475654528);
+
+ AlignmentConstraint *alignment140664475654720 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475654720->addShape(24, 0);
+ alignment140664475654720->addShape(91, 0);
+ ccs.push_back(alignment140664475654720);
+
+ AlignmentConstraint *alignment140664475654912 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475654912->addShape(25, 0);
+ alignment140664475654912->addShape(48, 0);
+ ccs.push_back(alignment140664475654912);
+
+ AlignmentConstraint *alignment140664475655104 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475655104->addShape(26, 0);
+ alignment140664475655104->addShape(31, 0);
+ alignment140664475655104->addShape(32, 0);
+ alignment140664475655104->addShape(33, 0);
+ ccs.push_back(alignment140664475655104);
+
+ AlignmentConstraint *alignment140664475655344 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475655344->addShape(27, 0);
+ ccs.push_back(alignment140664475655344);
+
+ AlignmentConstraint *alignment140664475655504 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475655504->addShape(28, 0);
+ alignment140664475655504->addShape(52, 0);
+ alignment140664475655504->addShape(54, 0);
+ alignment140664475655504->addShape(56, 0);
+ ccs.push_back(alignment140664475655504);
+
+ AlignmentConstraint *alignment140664475655776 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475655776->addShape(29, 0);
+ alignment140664475655776->addShape(43, 0);
+ ccs.push_back(alignment140664475655776);
+
+ AlignmentConstraint *alignment140664475656000 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475656000->addShape(30, 0);
+ alignment140664475656000->addShape(93, 0);
+ ccs.push_back(alignment140664475656000);
+
+ AlignmentConstraint *alignment140664475656192 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475656192->addShape(31, 0);
+ alignment140664475656192->addShape(32, 0);
+ alignment140664475656192->addShape(33, 0);
+ ccs.push_back(alignment140664475656192);
+
+ AlignmentConstraint *alignment140664475656432 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475656432->addShape(32, 0);
+ alignment140664475656432->addShape(33, 0);
+ ccs.push_back(alignment140664475656432);
+
+ AlignmentConstraint *alignment140664475656624 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475656624->addShape(33, 0);
+ ccs.push_back(alignment140664475656624);
+
+ AlignmentConstraint *alignment140664475656752 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475656752->addShape(34, 0);
+ alignment140664475656752->addShape(92, 0);
+ ccs.push_back(alignment140664475656752);
+
+ AlignmentConstraint *alignment140664475656976 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475656976->addShape(35, 0);
+ alignment140664475656976->addShape(42, 0);
+ ccs.push_back(alignment140664475656976);
+
+ AlignmentConstraint *alignment140664475657168 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475657168->addShape(36, 0);
+ ccs.push_back(alignment140664475657168);
+
+ AlignmentConstraint *alignment140664475657296 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475657296->addShape(37, 0);
+ ccs.push_back(alignment140664475657296);
+
+ AlignmentConstraint *alignment140664475657456 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475657456->addShape(38, 0);
+ ccs.push_back(alignment140664475657456);
+
+ AlignmentConstraint *alignment140664475657616 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475657616->addShape(40, 0);
+ alignment140664475657616->addShape(61, 0);
+ alignment140664475657616->addShape(68, 0);
+ ccs.push_back(alignment140664475657616);
+
+ AlignmentConstraint *alignment140664475657888 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475657888->addShape(41, 0);
+ alignment140664475657888->addShape(86, 0);
+ ccs.push_back(alignment140664475657888);
+
+ AlignmentConstraint *alignment140664475658080 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475658080->addShape(42, 0);
+ ccs.push_back(alignment140664475658080);
+
+ AlignmentConstraint *alignment140664475658208 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475658208->addShape(43, 0);
+ ccs.push_back(alignment140664475658208);
+
+ AlignmentConstraint *alignment140664475658368 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475658368->addShape(44, 0);
+ alignment140664475658368->addShape(46, 0);
+ alignment140664475658368->addShape(70, 0);
+ alignment140664475658368->addShape(71, 0);
+ ccs.push_back(alignment140664475658368);
+
+ AlignmentConstraint *alignment140664475658640 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475658640->addShape(45, 0);
+ alignment140664475658640->addShape(47, 0);
+ alignment140664475658640->addShape(72, 0);
+ alignment140664475658640->addShape(73, 0);
+ ccs.push_back(alignment140664475658640);
+
+ AlignmentConstraint *alignment140664475658912 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475658912->addShape(46, 0);
+ alignment140664475658912->addShape(70, 0);
+ alignment140664475658912->addShape(71, 0);
+ ccs.push_back(alignment140664475658912);
+
+ AlignmentConstraint *alignment140664475659184 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475659184->addShape(47, 0);
+ alignment140664475659184->addShape(72, 0);
+ alignment140664475659184->addShape(73, 0);
+ ccs.push_back(alignment140664475659184);
+
+ AlignmentConstraint *alignment140664475659424 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475659424->addShape(48, 0);
+ ccs.push_back(alignment140664475659424);
+
+ AlignmentConstraint *alignment140664475659552 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475659552->addShape(49, 0);
+ ccs.push_back(alignment140664475659552);
+
+ AlignmentConstraint *alignment140664475659712 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475659712->addShape(50, 0);
+ ccs.push_back(alignment140664475659712);
+
+ AlignmentConstraint *alignment140664475659872 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475659872->addShape(51, 0);
+ alignment140664475659872->addShape(55, 0);
+ ccs.push_back(alignment140664475659872);
+
+ AlignmentConstraint *alignment140664475660096 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475660096->addShape(52, 0);
+ alignment140664475660096->addShape(54, 0);
+ alignment140664475660096->addShape(56, 0);
+ ccs.push_back(alignment140664475660096);
+
+ AlignmentConstraint *alignment140664475660336 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475660336->addShape(53, 0);
+ alignment140664475660336->addShape(89, 0);
+ ccs.push_back(alignment140664475660336);
+
+ AlignmentConstraint *alignment140664475660528 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475660528->addShape(54, 0);
+ alignment140664475660528->addShape(56, 0);
+ ccs.push_back(alignment140664475660528);
+
+ AlignmentConstraint *alignment140664475660720 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475660720->addShape(55, 0);
+ ccs.push_back(alignment140664475660720);
+
+ AlignmentConstraint *alignment140664475660848 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475660848->addShape(56, 0);
+ ccs.push_back(alignment140664475660848);
+
+ AlignmentConstraint *alignment140664475661008 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475661008->addShape(57, 0);
+ alignment140664475661008->addShape(76, 0);
+ ccs.push_back(alignment140664475661008);
+
+ AlignmentConstraint *alignment140664475661232 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475661232->addShape(58, 0);
+ ccs.push_back(alignment140664475661232);
+
+ AlignmentConstraint *alignment140664475661360 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475661360->addShape(59, 0);
+ alignment140664475661360->addShape(88, 0);
+ ccs.push_back(alignment140664475661360);
+
+ AlignmentConstraint *alignment140664475661584 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475661584->addShape(60, 0);
+ alignment140664475661584->addShape(63, 0);
+ alignment140664475661584->addShape(64, 0);
+ alignment140664475661584->addShape(65, 0);
+ alignment140664475661584->addShape(67, 0);
+ ccs.push_back(alignment140664475661584);
+
+ AlignmentConstraint *alignment140664475661936 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475661936->addShape(61, 0);
+ alignment140664475661936->addShape(68, 0);
+ ccs.push_back(alignment140664475661936);
+
+ AlignmentConstraint *alignment140664475662160 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475662160->addShape(62, 0);
+ alignment140664475662160->addShape(66, 0);
+ ccs.push_back(alignment140664475662160);
+
+ AlignmentConstraint *alignment140664475662352 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475662352->addShape(63, 0);
+ alignment140664475662352->addShape(64, 0);
+ alignment140664475662352->addShape(65, 0);
+ alignment140664475662352->addShape(67, 0);
+ ccs.push_back(alignment140664475662352);
+
+ AlignmentConstraint *alignment140664475662544 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475662544->addShape(64, 0);
+ alignment140664475662544->addShape(65, 0);
+ alignment140664475662544->addShape(67, 0);
+ ccs.push_back(alignment140664475662544);
+
+ AlignmentConstraint *alignment140664475662816 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475662816->addShape(65, 0);
+ alignment140664475662816->addShape(67, 0);
+ ccs.push_back(alignment140664475662816);
+
+ AlignmentConstraint *alignment140664475663008 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475663008->addShape(66, 0);
+ ccs.push_back(alignment140664475663008);
+
+ AlignmentConstraint *alignment140664475663136 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475663136->addShape(67, 0);
+ ccs.push_back(alignment140664475663136);
+
+ AlignmentConstraint *alignment140664475663296 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475663296->addShape(68, 0);
+ ccs.push_back(alignment140664475663296);
+
+ AlignmentConstraint *alignment140664475663456 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475663456->addShape(69, 0);
+ ccs.push_back(alignment140664475663456);
+
+ AlignmentConstraint *alignment140664475663616 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475663616->addShape(70, 0);
+ alignment140664475663616->addShape(71, 0);
+ ccs.push_back(alignment140664475663616);
+
+ AlignmentConstraint *alignment140664475663840 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475663840->addShape(71, 0);
+ ccs.push_back(alignment140664475663840);
+
+ AlignmentConstraint *alignment140664475663968 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475663968->addShape(72, 0);
+ alignment140664475663968->addShape(73, 0);
+ ccs.push_back(alignment140664475663968);
+
+ AlignmentConstraint *alignment140664475664192 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475664192->addShape(73, 0);
+ ccs.push_back(alignment140664475664192);
+
+ AlignmentConstraint *alignment140664475664320 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475664320->addShape(74, 0);
+ ccs.push_back(alignment140664475664320);
+
+ AlignmentConstraint *alignment140664475664480 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475664480->addShape(76, 0);
+ ccs.push_back(alignment140664475664480);
+
+ AlignmentConstraint *alignment140664475664640 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475664640->addShape(77, 0);
+ alignment140664475664640->addShape(79, 0);
+ ccs.push_back(alignment140664475664640);
+
+ AlignmentConstraint *alignment140664475664864 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475664864->addShape(78, 0);
+ ccs.push_back(alignment140664475664864);
+
+ AlignmentConstraint *alignment140664475664992 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475664992->addShape(79, 0);
+ ccs.push_back(alignment140664475664992);
+
+ AlignmentConstraint *alignment140664475665152 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475665152->addShape(81, 0);
+ ccs.push_back(alignment140664475665152);
+
+ AlignmentConstraint *alignment140664475665312 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475665312->addShape(82, 0);
+ alignment140664475665312->addShape(85, 0);
+ ccs.push_back(alignment140664475665312);
+
+ AlignmentConstraint *alignment140664475665536 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475665536->addShape(83, 0);
+ ccs.push_back(alignment140664475665536);
+
+ AlignmentConstraint *alignment140664475665664 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475665664->addShape(84, 0);
+ ccs.push_back(alignment140664475665664);
+
+ AlignmentConstraint *alignment140664475665824 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475665824->addShape(85, 0);
+ ccs.push_back(alignment140664475665824);
+
+ AlignmentConstraint *alignment140664475665984 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475665984->addShape(86, 0);
+ ccs.push_back(alignment140664475665984);
+
+ AlignmentConstraint *alignment140664475666144 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475666144->addShape(87, 0);
+ ccs.push_back(alignment140664475666144);
+
+ AlignmentConstraint *alignment140664475666304 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475666304->addShape(88, 0);
+ ccs.push_back(alignment140664475666304);
+
+ AlignmentConstraint *alignment140664475666464 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475666464->addShape(89, 0);
+ ccs.push_back(alignment140664475666464);
+
+ AlignmentConstraint *alignment140664475666624 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475666624->addShape(90, 0);
+ ccs.push_back(alignment140664475666624);
+
+ AlignmentConstraint *alignment140664475666784 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475666784->addShape(91, 0);
+ ccs.push_back(alignment140664475666784);
+
+ AlignmentConstraint *alignment140664475666944 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475666944->addShape(92, 0);
+ ccs.push_back(alignment140664475666944);
+
+ AlignmentConstraint *alignment140664475667104 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475667104->addShape(93, 0);
+ ccs.push_back(alignment140664475667104);
+
+ SeparationConstraint *separation140664475667264 = new SeparationConstraint(vpsc::YDIM, alignment140664475657456, alignment140664475659552, 10, false);
+ ccs.push_back(separation140664475667264);
+
+ SeparationConstraint *separation140664475667440 = new SeparationConstraint(vpsc::YDIM, alignment140664475659552, alignment140664475657296, 11, false);
+ ccs.push_back(separation140664475667440);
+
+ SeparationConstraint *separation140664475667616 = new SeparationConstraint(vpsc::YDIM, alignment140664475657296, alignment140664475655344, 19, false);
+ ccs.push_back(separation140664475667616);
+
+ SeparationConstraint *separation140664475667792 = new SeparationConstraint(vpsc::YDIM, alignment140664475655344, alignment140664475657168, 13, false);
+ ccs.push_back(separation140664475667792);
+
+ SeparationConstraint *separation140664475667968 = new SeparationConstraint(vpsc::YDIM, alignment140664475657168, alignment140664475659424, 9, false);
+ ccs.push_back(separation140664475667968);
+
+ SeparationConstraint *separation140664475668144 = new SeparationConstraint(vpsc::YDIM, alignment140664475654912, alignment140664475658080, 22.5, false);
+ ccs.push_back(separation140664475668144);
+
+ SeparationConstraint *separation140664475668320 = new SeparationConstraint(vpsc::YDIM, alignment140664475658080, alignment140664475659872, 11, false);
+ ccs.push_back(separation140664475668320);
+
+ SeparationConstraint *separation140664475668496 = new SeparationConstraint(vpsc::YDIM, alignment140664475660720, alignment140664475666944, 9, false);
+ ccs.push_back(separation140664475668496);
+
+ SeparationConstraint *separation140664475668672 = new SeparationConstraint(vpsc::YDIM, alignment140664475666944, alignment140664475656624, 25, false);
+ ccs.push_back(separation140664475668672);
+
+ SeparationConstraint *separation140664475668848 = new SeparationConstraint(vpsc::YDIM, alignment140664475655104, alignment140664475658208, 26.75, false);
+ ccs.push_back(separation140664475668848);
+
+ SeparationConstraint *separation140664475669024 = new SeparationConstraint(vpsc::YDIM, alignment140664475658208, alignment140664475660096, 10.6667, false);
+ ccs.push_back(separation140664475669024);
+
+ SeparationConstraint *separation140664475669200 = new SeparationConstraint(vpsc::YDIM, alignment140664475660848, alignment140664475667104, 9, false);
+ ccs.push_back(separation140664475669200);
+
+ SeparationConstraint *separation140664475669376 = new SeparationConstraint(vpsc::YDIM, alignment140664475667104, alignment140664475666784, 24, false);
+ ccs.push_back(separation140664475669376);
+
+ SeparationConstraint *separation140664475669552 = new SeparationConstraint(vpsc::YDIM, alignment140664475666784, alignment140664475663840, 23, false);
+ ccs.push_back(separation140664475669552);
+
+ SeparationConstraint *separation140664475669728 = new SeparationConstraint(vpsc::YDIM, alignment140664475658368, alignment140664475663456, 13.75, false);
+ ccs.push_back(separation140664475669728);
+
+ SeparationConstraint *separation140664475669904 = new SeparationConstraint(vpsc::YDIM, alignment140664475663456, alignment140664475664192, 12, false);
+ ccs.push_back(separation140664475669904);
+
+ SeparationConstraint *separation140664475670080 = new SeparationConstraint(vpsc::YDIM, alignment140664475658640, alignment140664475649328, 18.75, false);
+ ccs.push_back(separation140664475670080);
+
+ SeparationConstraint *separation140664475670256 = new SeparationConstraint(vpsc::YDIM, alignment140664475649328, alignment140664475666464, 44, false);
+ ccs.push_back(separation140664475670256);
+
+ SeparationConstraint *separation140664475670432 = new SeparationConstraint(vpsc::YDIM, alignment140664475654336, alignment140664475665152, 35.3333, false);
+ ccs.push_back(separation140664475670432);
+
+ SeparationConstraint *separation140664475670608 = new SeparationConstraint(vpsc::YDIM, alignment140664475665152, alignment140664475661360, 37, false);
+ ccs.push_back(separation140664475670608);
+
+ SeparationConstraint *separation140664475670784 = new SeparationConstraint(vpsc::YDIM, alignment140664475666304, alignment140664475665824, 3, false);
+ ccs.push_back(separation140664475670784);
+
+ SeparationConstraint *separation140664475670960 = new SeparationConstraint(vpsc::YDIM, alignment140664475665824, alignment140664475665536, 19, false);
+ ccs.push_back(separation140664475670960);
+
+ SeparationConstraint *separation140664475671136 = new SeparationConstraint(vpsc::YDIM, alignment140664475665536, alignment140664475665984, 12, false);
+ ccs.push_back(separation140664475671136);
+
+ SeparationConstraint *separation140664475671312 = new SeparationConstraint(vpsc::YDIM, alignment140664475665984, alignment140664475666144, 30, false);
+ ccs.push_back(separation140664475671312);
+
+ SeparationConstraint *separation140664475671488 = new SeparationConstraint(vpsc::YDIM, alignment140664475666144, alignment140664475661232, 6, false);
+ ccs.push_back(separation140664475671488);
+
+ SeparationConstraint *separation140664475671664 = new SeparationConstraint(vpsc::YDIM, alignment140664475661232, alignment140664475653952, 37, false);
+ ccs.push_back(separation140664475671664);
+
+ SeparationConstraint *separation140664475508000 = new SeparationConstraint(vpsc::YDIM, alignment140664475653952, alignment140664475659712, 35, false);
+ ccs.push_back(separation140664475508000);
+
+ SeparationConstraint *separation140664475508176 = new SeparationConstraint(vpsc::YDIM, alignment140664475659712, alignment140664475653792, 37, false);
+ ccs.push_back(separation140664475508176);
+
+ SeparationConstraint *separation140664475508352 = new SeparationConstraint(vpsc::YDIM, alignment140664475653792, alignment140664475664480, 35, false);
+ ccs.push_back(separation140664475508352);
+
+ SeparationConstraint *separation140664475508528 = new SeparationConstraint(vpsc::YDIM, alignment140664475664480, alignment140664475664864, 11, false);
+ ccs.push_back(separation140664475508528);
+
+ SeparationConstraint *separation140664475508704 = new SeparationConstraint(vpsc::YDIM, alignment140664475664864, alignment140664475653632, 23, false);
+ ccs.push_back(separation140664475508704);
+
+ SeparationConstraint *separation140664475508880 = new SeparationConstraint(vpsc::YDIM, alignment140664475653632, alignment140664475665664, 25, false);
+ ccs.push_back(separation140664475508880);
+
+ SeparationConstraint *separation140664475509056 = new SeparationConstraint(vpsc::YDIM, alignment140664475665664, alignment140664475664320, 25, false);
+ ccs.push_back(separation140664475509056);
+
+ SeparationConstraint *separation140664475509232 = new SeparationConstraint(vpsc::YDIM, alignment140664475664320, alignment140664475639232, 33, false);
+ ccs.push_back(separation140664475509232);
+
+ SeparationConstraint *separation140664475509408 = new SeparationConstraint(vpsc::YDIM, alignment140664475639232, alignment140664475663136, 10, false);
+ ccs.push_back(separation140664475509408);
+
+ SeparationConstraint *separation140664475509584 = new SeparationConstraint(vpsc::YDIM, alignment140664475639392, alignment140664475639072, 10.375, false);
+ ccs.push_back(separation140664475509584);
+
+ SeparationConstraint *separation140664475509760 = new SeparationConstraint(vpsc::YDIM, alignment140664475639072, alignment140664475663296, 32, false);
+ ccs.push_back(separation140664475509760);
+
+ SeparationConstraint *separation140664475509936 = new SeparationConstraint(vpsc::YDIM, alignment140664475657616, alignment140664475666624, 4.33333, false);
+ ccs.push_back(separation140664475509936);
+
+ SeparationConstraint *separation140664475510112 = new SeparationConstraint(vpsc::YDIM, alignment140664475650480, alignment140664475650864, 31.5, false);
+ ccs.push_back(separation140664475510112);
+
+ SeparationConstraint *separation140664475510288 = new SeparationConstraint(vpsc::YDIM, alignment140664475650864, alignment140664475663008, 10, false);
+ ccs.push_back(separation140664475510288);
+
+ SeparationConstraint *separation140664475510464 = new SeparationConstraint(vpsc::YDIM, alignment140664475663008, alignment140664475664992, 11, false);
+ ccs.push_back(separation140664475510464);
+
+ AlignmentConstraint *alignment140664475511088 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475511088->addShape(75, 0);
+ alignment140664475511088->addShape(75, 0);
+ ccs.push_back(alignment140664475511088);
+
+ SeparationConstraint *separation140664475511312 = new SeparationConstraint(vpsc::YDIM, 75, 75, -50, true);
+ ccs.push_back(separation140664475511312);
+
+ AlignmentConstraint *alignment140664475511456 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475511456->addShape(0, 0);
+ alignment140664475511456->addShape(94, 0);
+ ccs.push_back(alignment140664475511456);
+
+ SeparationConstraint *separation140664475511680 = new SeparationConstraint(vpsc::XDIM, 0, 94, 62, true);
+ ccs.push_back(separation140664475511680);
+
+ AlignmentConstraint *alignment140664475511824 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475511824->addShape(1, 0);
+ alignment140664475511824->addShape(95, 0);
+ ccs.push_back(alignment140664475511824);
+
+ SeparationConstraint *separation140664475512048 = new SeparationConstraint(vpsc::YDIM, 1, 95, -50, true);
+ ccs.push_back(separation140664475512048);
+
+ AlignmentConstraint *alignment140664475512192 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475512192->addShape(2, 0);
+ alignment140664475512192->addShape(96, 0);
+ ccs.push_back(alignment140664475512192);
+
+ SeparationConstraint *separation140664475512416 = new SeparationConstraint(vpsc::XDIM, 2, 96, 62, true);
+ ccs.push_back(separation140664475512416);
+
+ AlignmentConstraint *alignment140664475512560 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475512560->addShape(3, 0);
+ alignment140664475512560->addShape(97, 0);
+ ccs.push_back(alignment140664475512560);
+
+ SeparationConstraint *separation140664475512784 = new SeparationConstraint(vpsc::YDIM, 3, 97, -50, true);
+ ccs.push_back(separation140664475512784);
+
+ AlignmentConstraint *alignment140664475650992 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475650992->addShape(7, 0);
+ alignment140664475650992->addShape(98, 0);
+ ccs.push_back(alignment140664475650992);
+
+ SeparationConstraint *separation140664475651216 = new SeparationConstraint(vpsc::XDIM, 7, 98, 62, true);
+ ccs.push_back(separation140664475651216);
+
+ AlignmentConstraint *alignment140664475651360 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475651360->addShape(8, 0);
+ alignment140664475651360->addShape(99, 0);
+ ccs.push_back(alignment140664475651360);
+
+ SeparationConstraint *separation140664475651584 = new SeparationConstraint(vpsc::YDIM, 8, 99, -50, true);
+ ccs.push_back(separation140664475651584);
+
+ AlignmentConstraint *alignment140664475651728 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475651728->addShape(9, 0);
+ alignment140664475651728->addShape(100, 0);
+ ccs.push_back(alignment140664475651728);
+
+ SeparationConstraint *separation140664475651952 = new SeparationConstraint(vpsc::YDIM, 9, 100, -50, true);
+ ccs.push_back(separation140664475651952);
+
+ AlignmentConstraint *alignment140664475652096 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475652096->addShape(10, 0);
+ alignment140664475652096->addShape(101, 0);
+ ccs.push_back(alignment140664475652096);
+
+ SeparationConstraint *separation140664475652320 = new SeparationConstraint(vpsc::XDIM, 10, 101, 62, true);
+ ccs.push_back(separation140664475652320);
+
+ AlignmentConstraint *alignment140664475652464 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475652464->addShape(11, 0);
+ alignment140664475652464->addShape(102, 0);
+ ccs.push_back(alignment140664475652464);
+
+ SeparationConstraint *separation140664475652688 = new SeparationConstraint(vpsc::XDIM, 11, 102, 62, true);
+ ccs.push_back(separation140664475652688);
+
+ AlignmentConstraint *alignment140664475652832 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475652832->addShape(12, 0);
+ alignment140664475652832->addShape(103, 0);
+ ccs.push_back(alignment140664475652832);
+
+ SeparationConstraint *separation140664475517040 = new SeparationConstraint(vpsc::XDIM, 12, 103, 62, true);
+ ccs.push_back(separation140664475517040);
+
+ AlignmentConstraint *alignment140664475517184 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475517184->addShape(13, 0);
+ alignment140664475517184->addShape(104, 0);
+ ccs.push_back(alignment140664475517184);
+
+ SeparationConstraint *separation140664475517408 = new SeparationConstraint(vpsc::YDIM, 13, 104, -50, true);
+ ccs.push_back(separation140664475517408);
+
+ AlignmentConstraint *alignment140664475517552 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475517552->addShape(14, 0);
+ alignment140664475517552->addShape(105, 0);
+ ccs.push_back(alignment140664475517552);
+
+ SeparationConstraint *separation140664475517776 = new SeparationConstraint(vpsc::YDIM, 14, 105, -50, true);
+ ccs.push_back(separation140664475517776);
+
+ AlignmentConstraint *alignment140664475517920 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475517920->addShape(16, 0);
+ alignment140664475517920->addShape(106, 0);
+ ccs.push_back(alignment140664475517920);
+
+ SeparationConstraint *separation140664475518144 = new SeparationConstraint(vpsc::XDIM, 16, 106, 62, true);
+ ccs.push_back(separation140664475518144);
+
+ AlignmentConstraint *alignment140664475518288 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475518288->addShape(18, 0);
+ alignment140664475518288->addShape(107, 0);
+ ccs.push_back(alignment140664475518288);
+
+ SeparationConstraint *separation140664475518512 = new SeparationConstraint(vpsc::XDIM, 18, 107, 62, true);
+ ccs.push_back(separation140664475518512);
+
+ AlignmentConstraint *alignment140664475518656 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475518656->addShape(19, 0);
+ alignment140664475518656->addShape(108, 0);
+ ccs.push_back(alignment140664475518656);
+
+ SeparationConstraint *separation140664475518880 = new SeparationConstraint(vpsc::XDIM, 19, 108, 62, true);
+ ccs.push_back(separation140664475518880);
+
+ AlignmentConstraint *alignment140664475519024 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475519024->addShape(20, 0);
+ alignment140664475519024->addShape(109, 0);
+ ccs.push_back(alignment140664475519024);
+
+ SeparationConstraint *separation140664475519248 = new SeparationConstraint(vpsc::XDIM, 20, 109, 62, true);
+ ccs.push_back(separation140664475519248);
+
+ AlignmentConstraint *alignment140664475519392 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475519392->addShape(22, 0);
+ alignment140664475519392->addShape(110, 0);
+ ccs.push_back(alignment140664475519392);
+
+ SeparationConstraint *separation140664475519616 = new SeparationConstraint(vpsc::YDIM, 22, 110, -50, true);
+ ccs.push_back(separation140664475519616);
+
+ AlignmentConstraint *alignment140664475519760 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475519760->addShape(23, 0);
+ alignment140664475519760->addShape(111, 0);
+ ccs.push_back(alignment140664475519760);
+
+ SeparationConstraint *separation140664475519984 = new SeparationConstraint(vpsc::XDIM, 23, 111, 62, true);
+ ccs.push_back(separation140664475519984);
+
+ AlignmentConstraint *alignment140664475520128 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475520128->addShape(24, 0);
+ alignment140664475520128->addShape(112, 0);
+ ccs.push_back(alignment140664475520128);
+
+ SeparationConstraint *separation140664475520352 = new SeparationConstraint(vpsc::YDIM, 24, 112, -50, true);
+ ccs.push_back(separation140664475520352);
+
+ AlignmentConstraint *alignment140664475520496 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475520496->addShape(25, 0);
+ alignment140664475520496->addShape(113, 0);
+ ccs.push_back(alignment140664475520496);
+
+ SeparationConstraint *separation140664475520720 = new SeparationConstraint(vpsc::YDIM, 25, 113, -50, true);
+ ccs.push_back(separation140664475520720);
+
+ AlignmentConstraint *alignment140664475520864 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475520864->addShape(26, 0);
+ alignment140664475520864->addShape(114, 0);
+ ccs.push_back(alignment140664475520864);
+
+ SeparationConstraint *separation140664475521088 = new SeparationConstraint(vpsc::XDIM, 26, 114, 62, true);
+ ccs.push_back(separation140664475521088);
+
+ AlignmentConstraint *alignment140664475521232 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475521232->addShape(27, 0);
+ alignment140664475521232->addShape(115, 0);
+ ccs.push_back(alignment140664475521232);
+
+ SeparationConstraint *separation140664475521456 = new SeparationConstraint(vpsc::XDIM, 27, 115, 62, true);
+ ccs.push_back(separation140664475521456);
+
+ AlignmentConstraint *alignment140664475521600 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475521600->addShape(28, 0);
+ alignment140664475521600->addShape(116, 0);
+ ccs.push_back(alignment140664475521600);
+
+ SeparationConstraint *separation140664475521824 = new SeparationConstraint(vpsc::YDIM, 28, 116, -50, true);
+ ccs.push_back(separation140664475521824);
+
+ AlignmentConstraint *alignment140664475521968 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475521968->addShape(29, 0);
+ alignment140664475521968->addShape(117, 0);
+ ccs.push_back(alignment140664475521968);
+
+ SeparationConstraint *separation140664475522192 = new SeparationConstraint(vpsc::YDIM, 29, 117, -50, true);
+ ccs.push_back(separation140664475522192);
+
+ AlignmentConstraint *alignment140664475522336 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475522336->addShape(30, 0);
+ alignment140664475522336->addShape(118, 0);
+ ccs.push_back(alignment140664475522336);
+
+ SeparationConstraint *separation140664475522560 = new SeparationConstraint(vpsc::YDIM, 30, 118, -50, true);
+ ccs.push_back(separation140664475522560);
+
+ AlignmentConstraint *alignment140664475522704 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475522704->addShape(31, 0);
+ alignment140664475522704->addShape(119, 0);
+ ccs.push_back(alignment140664475522704);
+
+ SeparationConstraint *separation140664475522928 = new SeparationConstraint(vpsc::XDIM, 31, 119, 62, true);
+ ccs.push_back(separation140664475522928);
+
+ AlignmentConstraint *alignment140664475523072 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475523072->addShape(32, 0);
+ alignment140664475523072->addShape(120, 0);
+ ccs.push_back(alignment140664475523072);
+
+ SeparationConstraint *separation140664475523296 = new SeparationConstraint(vpsc::XDIM, 32, 120, 62, true);
+ ccs.push_back(separation140664475523296);
+
+ AlignmentConstraint *alignment140664475523440 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475523440->addShape(33, 0);
+ alignment140664475523440->addShape(121, 0);
+ ccs.push_back(alignment140664475523440);
+
+ SeparationConstraint *separation140664475523664 = new SeparationConstraint(vpsc::XDIM, 33, 121, 62, true);
+ ccs.push_back(separation140664475523664);
+
+ AlignmentConstraint *alignment140664475523808 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475523808->addShape(34, 0);
+ alignment140664475523808->addShape(122, 0);
+ ccs.push_back(alignment140664475523808);
+
+ SeparationConstraint *separation140664475524032 = new SeparationConstraint(vpsc::YDIM, 34, 122, -50, true);
+ ccs.push_back(separation140664475524032);
+
+ AlignmentConstraint *alignment140664475524176 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475524176->addShape(35, 0);
+ alignment140664475524176->addShape(123, 0);
+ ccs.push_back(alignment140664475524176);
+
+ SeparationConstraint *separation140664475524400 = new SeparationConstraint(vpsc::YDIM, 35, 123, -50, true);
+ ccs.push_back(separation140664475524400);
+
+ AlignmentConstraint *alignment140664475524544 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475524544->addShape(36, 0);
+ alignment140664475524544->addShape(124, 0);
+ ccs.push_back(alignment140664475524544);
+
+ SeparationConstraint *separation140664475524768 = new SeparationConstraint(vpsc::YDIM, 36, 124, -50, true);
+ ccs.push_back(separation140664475524768);
+
+ AlignmentConstraint *alignment140664475524912 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475524912->addShape(37, 0);
+ alignment140664475524912->addShape(125, 0);
+ ccs.push_back(alignment140664475524912);
+
+ SeparationConstraint *separation140664475525136 = new SeparationConstraint(vpsc::YDIM, 37, 125, -50, true);
+ ccs.push_back(separation140664475525136);
+
+ AlignmentConstraint *alignment140664475525280 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475525280->addShape(38, 0);
+ alignment140664475525280->addShape(126, 0);
+ ccs.push_back(alignment140664475525280);
+
+ SeparationConstraint *separation140664475525504 = new SeparationConstraint(vpsc::YDIM, 38, 126, -50, true);
+ ccs.push_back(separation140664475525504);
+
+ AlignmentConstraint *alignment140664475525648 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475525648->addShape(40, 0);
+ alignment140664475525648->addShape(127, 0);
+ ccs.push_back(alignment140664475525648);
+
+ SeparationConstraint *separation140664475525872 = new SeparationConstraint(vpsc::YDIM, 40, 127, -50, true);
+ ccs.push_back(separation140664475525872);
+
+ AlignmentConstraint *alignment140664475526016 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475526016->addShape(41, 0);
+ alignment140664475526016->addShape(128, 0);
+ ccs.push_back(alignment140664475526016);
+
+ SeparationConstraint *separation140664475526240 = new SeparationConstraint(vpsc::XDIM, 41, 128, 62, true);
+ ccs.push_back(separation140664475526240);
+
+ AlignmentConstraint *alignment140664475526384 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475526384->addShape(42, 0);
+ alignment140664475526384->addShape(129, 0);
+ ccs.push_back(alignment140664475526384);
+
+ SeparationConstraint *separation140664475526608 = new SeparationConstraint(vpsc::YDIM, 42, 129, -50, true);
+ ccs.push_back(separation140664475526608);
+
+ AlignmentConstraint *alignment140664475526752 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475526752->addShape(43, 0);
+ alignment140664475526752->addShape(130, 0);
+ ccs.push_back(alignment140664475526752);
+
+ SeparationConstraint *separation140664475526976 = new SeparationConstraint(vpsc::YDIM, 43, 130, -50, true);
+ ccs.push_back(separation140664475526976);
+
+ AlignmentConstraint *alignment140664475527120 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475527120->addShape(44, 0);
+ alignment140664475527120->addShape(131, 0);
+ ccs.push_back(alignment140664475527120);
+
+ SeparationConstraint *separation140664475527344 = new SeparationConstraint(vpsc::YDIM, 44, 131, -50, true);
+ ccs.push_back(separation140664475527344);
+
+ AlignmentConstraint *alignment140664475527488 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475527488->addShape(45, 0);
+ alignment140664475527488->addShape(132, 0);
+ ccs.push_back(alignment140664475527488);
+
+ SeparationConstraint *separation140664475527712 = new SeparationConstraint(vpsc::YDIM, 45, 132, -50, true);
+ ccs.push_back(separation140664475527712);
+
+ AlignmentConstraint *alignment140664475527856 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475527856->addShape(46, 0);
+ alignment140664475527856->addShape(133, 0);
+ ccs.push_back(alignment140664475527856);
+
+ SeparationConstraint *separation140664475528080 = new SeparationConstraint(vpsc::YDIM, 46, 133, -50, true);
+ ccs.push_back(separation140664475528080);
+
+ AlignmentConstraint *alignment140664475528224 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475528224->addShape(47, 0);
+ alignment140664475528224->addShape(134, 0);
+ ccs.push_back(alignment140664475528224);
+
+ SeparationConstraint *separation140664475528448 = new SeparationConstraint(vpsc::YDIM, 47, 134, -50, true);
+ ccs.push_back(separation140664475528448);
+
+ AlignmentConstraint *alignment140664475528592 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475528592->addShape(77, 0);
+ alignment140664475528592->addShape(135, 0);
+ ccs.push_back(alignment140664475528592);
+
+ SeparationConstraint *separation140664475528816 = new SeparationConstraint(vpsc::YDIM, 77, 135, -50, true);
+ ccs.push_back(separation140664475528816);
+
+ AlignmentConstraint *alignment140664475528960 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475528960->addShape(78, 0);
+ alignment140664475528960->addShape(136, 0);
+ ccs.push_back(alignment140664475528960);
+
+ SeparationConstraint *separation140664475529184 = new SeparationConstraint(vpsc::YDIM, 78, 136, -50, true);
+ ccs.push_back(separation140664475529184);
+
+ AlignmentConstraint *alignment140664475529328 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475529328->addShape(79, 0);
+ alignment140664475529328->addShape(137, 0);
+ ccs.push_back(alignment140664475529328);
+
+ SeparationConstraint *separation140664475529552 = new SeparationConstraint(vpsc::YDIM, 79, 137, -50, true);
+ ccs.push_back(separation140664475529552);
+
+ AlignmentConstraint *alignment140664475529696 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475529696->addShape(81, 0);
+ alignment140664475529696->addShape(138, 0);
+ ccs.push_back(alignment140664475529696);
+
+ SeparationConstraint *separation140664475529920 = new SeparationConstraint(vpsc::XDIM, 81, 138, 62, true);
+ ccs.push_back(separation140664475529920);
+
+ AlignmentConstraint *alignment140664475530064 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475530064->addShape(82, 0);
+ alignment140664475530064->addShape(139, 0);
+ ccs.push_back(alignment140664475530064);
+
+ SeparationConstraint *separation140664475530288 = new SeparationConstraint(vpsc::YDIM, 82, 139, -50, true);
+ ccs.push_back(separation140664475530288);
+
+ AlignmentConstraint *alignment140664475530432 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475530432->addShape(83, 0);
+ alignment140664475530432->addShape(140, 0);
+ ccs.push_back(alignment140664475530432);
+
+ SeparationConstraint *separation140664475530656 = new SeparationConstraint(vpsc::YDIM, 83, 140, -50, true);
+ ccs.push_back(separation140664475530656);
+
+ AlignmentConstraint *alignment140664475530800 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475530800->addShape(84, 0);
+ alignment140664475530800->addShape(141, 0);
+ ccs.push_back(alignment140664475530800);
+
+ SeparationConstraint *separation140664475531024 = new SeparationConstraint(vpsc::YDIM, 84, 141, -50, true);
+ ccs.push_back(separation140664475531024);
+
+ AlignmentConstraint *alignment140664475531168 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475531168->addShape(85, 0);
+ alignment140664475531168->addShape(142, 0);
+ ccs.push_back(alignment140664475531168);
+
+ SeparationConstraint *separation140664475531392 = new SeparationConstraint(vpsc::XDIM, 85, 142, 62, true);
+ ccs.push_back(separation140664475531392);
+
+ AlignmentConstraint *alignment140664475531536 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475531536->addShape(87, 0);
+ alignment140664475531536->addShape(143, 0);
+ ccs.push_back(alignment140664475531536);
+
+ SeparationConstraint *separation140664475531760 = new SeparationConstraint(vpsc::YDIM, 87, 143, -50, true);
+ ccs.push_back(separation140664475531760);
+
+ AlignmentConstraint *alignment140664475531904 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475531904->addShape(88, 0);
+ alignment140664475531904->addShape(144, 0);
+ ccs.push_back(alignment140664475531904);
+
+ SeparationConstraint *separation140664475532128 = new SeparationConstraint(vpsc::YDIM, 88, 144, -50, true);
+ ccs.push_back(separation140664475532128);
+
+ AlignmentConstraint *alignment140664475532272 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475532272->addShape(90, 0);
+ alignment140664475532272->addShape(145, 0);
+ ccs.push_back(alignment140664475532272);
+
+ SeparationConstraint *separation140664475532496 = new SeparationConstraint(vpsc::YDIM, 90, 145, -50, true);
+ ccs.push_back(separation140664475532496);
+
+ AlignmentConstraint *alignment140664475532640 = new AlignmentConstraint(vpsc::YDIM, 0);
+ alignment140664475532640->addShape(91, 0);
+ alignment140664475532640->addShape(146, 0);
+ ccs.push_back(alignment140664475532640);
+
+ SeparationConstraint *separation140664475532864 = new SeparationConstraint(vpsc::XDIM, 91, 146, 62, true);
+ ccs.push_back(separation140664475532864);
+
+ AlignmentConstraint *alignment140664475533008 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475533008->addShape(92, 0);
+ alignment140664475533008->addShape(147, 0);
+ ccs.push_back(alignment140664475533008);
+
+ SeparationConstraint *separation140664475533232 = new SeparationConstraint(vpsc::YDIM, 92, 147, -50, true);
+ ccs.push_back(separation140664475533232);
+
+ AlignmentConstraint *alignment140664475533376 = new AlignmentConstraint(vpsc::XDIM, 0);
+ alignment140664475533376->addShape(93, 0);
+ alignment140664475533376->addShape(148, 0);
+ ccs.push_back(alignment140664475533376);
+
+ SeparationConstraint *separation140664475533600 = new SeparationConstraint(vpsc::YDIM, 93, 148, -50, true);
+ ccs.push_back(separation140664475533600);
+
+ RootCluster *cluster140664475533920 = new RootCluster();
+
+ RectangularCluster *cluster140664475534416 = new RectangularCluster(5);
+ cluster140664475534416->addChildNode(149);
+ cluster140664475534416->addChildNode(150);
+ cluster140664475534416->addChildNode(151);
+ cluster140664475534416->addChildNode(152);
+ cluster140664475533920->addChildCluster(cluster140664475534416);
+
+ RectangularCluster *cluster140664475535040 = new RectangularCluster(6);
+ cluster140664475535040->addChildNode(153);
+ cluster140664475533920->addChildCluster(cluster140664475535040);
+
+ RectangularCluster *cluster140664475535648 = new RectangularCluster(15);
+ cluster140664475533920->addChildCluster(cluster140664475535648);
+
+ RectangularCluster *cluster140664475535952 = new RectangularCluster(17);
+ cluster140664475535952->addChildNode(154);
+ cluster140664475535952->addChildNode(155);
+ cluster140664475533920->addChildCluster(cluster140664475535952);
+
+ RectangularCluster *cluster140664475536320 = new RectangularCluster(21);
+ cluster140664475536320->addChildNode(156);
+ cluster140664475533920->addChildCluster(cluster140664475536320);
+
+ RectangularCluster *cluster140664475536720 = new RectangularCluster(39);
+ cluster140664475533920->addChildCluster(cluster140664475536720);
+
+ RectangularCluster *cluster140664475537056 = new RectangularCluster(80);
+ cluster140664475537056->addChildNode(157);
+ cluster140664475533920->addChildCluster(cluster140664475537056);
+
+ ConstrainedFDLayout alg(rs, es, defaultEdgeLength);
+ alg.setAvoidNodeOverlaps(true);
+ alg.setClusterHierarchy(cluster140664475533920);
+ alg.setConstraints(ccs);
+ alg.makeFeasible();
+
+ alg.outputInstanceToSVG("test-rectclustershapecontainment");
+ //alg.run();
+ alg.freeAssociatedObjects();
+
+ return 0;
+};
diff --git a/src/3rdparty/adaptagrams/libcola/tests/resize.cpp b/src/3rdparty/adaptagrams/libcola/tests/resize.cpp
new file mode 100644
index 0000000..97c2e9d
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/resize.cpp
@@ -0,0 +1,132 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+/** \file nodedragging.cpp
+ *
+ * tests interaction with layout and solver. We have a number of disconnected
+ * shapes. One shape is "dragged" through the others. Overlaps should be
+ * avoided.
+ */
+/*
+* Authors:
+* Tim Dwyer <tgdwyer@gmail.com>
+*/
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+
+#include <vector>
+#include <valarray>
+#include <algorithm>
+#include <float.h>
+#include <libcola/cola.h>
+#include <libtopology/topology_graph.h>
+#include <libproject/project.h>
+#include "graphlayouttest.h"
+using namespace std;
+using namespace cola;
+
+string outFName="resize";
+
+topology::Node* addNode(
+ topology::Nodes& vs, vpsc::Rectangle* r) {
+ topology::Node *v = new topology::Node(vs.size(), r);
+ vs.push_back(v);
+ return v;
+}
+void addToPath(topology::EdgePoints& ps, topology::Node *v, topology::EdgePoint::RectIntersect i) {
+ ps.push_back(new topology::EdgePoint(v,i));
+}
+struct Test : TestConvergence {
+ Test(const double d,const unsigned i,topology::Nodes& vs, topology::Edges& es) : TestConvergence(d,i), vs(vs), es(es), iter(1) {}
+ bool operator()(const double new_stress, valarray<double> & X, valarray<double> & Y) {
+ bool converged = TestConvergence::operator()(new_stress,X,Y);
+ if(converged) {
+ cout << "stress="<<new_stress<<" iteration="<<iter<<endl;
+ stringstream ss;
+ ss<<outFName<<"-"<< setfill('0') << setw(3) << iter++ << ".svg";
+ writeFile(vs,es,ss.str());
+ }
+ return converged;
+ }
+ double lastStress;
+ topology::Nodes& vs;
+ topology::Edges& es;
+ int iter;
+};
+
+void resize() {
+//printf(
+//"tests resizing of a shape. We have a number of disconnected"
+//"shapes. One shape is 'enlarged'. Overlaps should be"
+//"avoided."
+//"\n");
+ const unsigned V = 9;
+ Edge edge_array[] = { Edge(0, 1), Edge(1, 2), Edge(2, 0) };
+ const std::size_t E = sizeof(edge_array) / sizeof(Edge);
+ vector<Edge> es(edge_array,edge_array+E);
+ vector<vpsc::Rectangle*> rs;
+ const double w=54, h=34;
+ const double
+ x[]={406, 444, 474, 406, 441, 375, 408, 373, 339},
+ y[]={279, 224, 179, 92, 135, 135, 179, 226, 179};
+ const unsigned resizeID=6;
+ for(unsigned i=0;i<V;++i) {
+ rs.push_back(new vpsc::Rectangle(x[i],x[i]+w,y[i],y[i]+h));
+ }
+ double idealLength=60;
+ // set up topology graph
+ topology::Nodes vs;
+ for(vector<Rectangle*>::iterator i = rs.begin(); i!=rs.end();++i) {
+ addNode(vs,*i);
+ }
+ topology::Edges tes;
+ writeFile(vs,tes,outFName+"-000.svg");
+
+ Resizes resize;
+ vpsc::Rectangle* r=rs[resizeID];
+ resize.push_back(Resize(resizeID,r->getCentreX()-30, r->getCentreY()-30,
+ r->width()+60,r->height()+60));
+ PreIteration preIteration(resize);
+ Test test(0.00001,100,vs,tes);
+ ConstrainedFDLayout alg(rs,es,idealLength,nullptr,test,&preIteration);
+ alg.setTopology(&vs,&tes);
+
+ alg.run(true,true);
+
+ double finalStress=alg.computeStress();
+ printf("finalStress=%f\n",finalStress);
+
+ //assert(finalStress<1e-5);
+ for_each(rs.begin(),rs.end(),delete_object());
+ for_each(tes.begin(),tes.end(),delete_object());
+ for_each(vs.begin(),vs.end(),delete_object());
+}
+int main() {
+ resize();
+ return 0;
+}
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=80 :
+
diff --git a/src/3rdparty/adaptagrams/libcola/tests/runtest.sh b/src/3rdparty/adaptagrams/libcola/tests/runtest.sh
new file mode 100755
index 0000000..2ee1526
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/runtest.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+r=0
+while [ $r == 0 ]
+do
+ ./beautify
+ r=$?
+ echo result=$r
+done
diff --git a/src/3rdparty/adaptagrams/libcola/tests/scale_free.cpp b/src/3rdparty/adaptagrams/libcola/tests/scale_free.cpp
new file mode 100644
index 0000000..d9c2934
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/scale_free.cpp
@@ -0,0 +1,135 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+// generates a random graph with a power-law distribution of node degrees
+// the algorithm is pretty much the Barabasi-Albert model but with an extra step
+// so that I can guarantee the number of nodes in the graph.
+// We begin with an initial chain of m nodes.
+// Then, we add new nodes, connecting them to existing nodes v with probability
+// degree(v)/(sum all degrees)
+// We perform an extra step, looking for disconnected nodes, connecting them
+// to other nodes again with probability dependent on degree
+#include<iostream>
+#include<vector>
+#include <cmath>
+#include <time.h>
+#include <valarray>
+
+#include "graphlayouttest.h"
+
+void scale_free(const unsigned n = 50) {
+ const unsigned m = 3; // begin with a chain of m nodes
+ const double g=0.08; // edge density, every time we add a node we add 1+g*rand(0-1) edges
+ // connecting them to existing nodes with probability based on degree
+ unsigned d[n];
+ double defaultEdgeLength=100;
+ vector<Edge> es;
+ CompoundConstraints cx,cy;
+ for(unsigned i=0;i<n;i++) {
+ d[i]=0;
+ }
+ unsigned sumdegree=0;
+ for(unsigned i=1;i<m;i++) {
+ es.push_back(make_pair(i-1,i));
+ d[i]++;d[i-1]++;
+ sumdegree+=2;
+ }
+ srand(3);
+ for(unsigned i=2;i<n;i++) {
+ for(unsigned j=0;j<i;j++) {
+ double p=(double)d[j]/(double)sumdegree;
+ double r=(double)rand()/(double)RAND_MAX;
+ if(r*p>g) {
+ es.push_back(make_pair(j,i));
+ d[j]++;d[i]++;
+ sumdegree+=2;
+ }
+ }
+ }
+ for(unsigned i=0;i<n;i++) {
+ if(d[i]==0) {
+ double maxP=0;
+ unsigned end=0;
+ for(unsigned j=0;j<n;j++) {
+ if(j==i) continue;
+ double p=(double)d[j]/(double)sumdegree;
+ double r=(double)rand()/(double)RAND_MAX;
+ if(r*p>maxP) {
+ maxP=r*p;
+ end=j;
+ }
+ }
+ if(end>i) {
+ es.push_back(make_pair(i,end));
+ } else {
+ es.push_back(make_pair(end,i));
+ }
+ d[end]++;d[i]++;
+ sumdegree+=2;
+ }
+ }
+ valarray<double> eweights(es.size());
+ sort(d,d+n);
+ unsigned degree=0,ctr=0;
+ printf("degree distribution:\n");
+ for(unsigned i=0;i<n;i++) {
+ if(degree!=d[i]) {
+ if(degree!=0) printf("%d,%d\n",degree,ctr);
+ degree=d[i];
+ ctr=0;
+ }
+ ctr++;
+ }
+ printf("%d,%d\n",degree,ctr);
+ for(unsigned i=0;i<es.size();i++) {
+ unsigned a=es[i].first, b=es[i].second;
+ eweights[i]=1;
+ cy.push_back(new SeparationConstraint(a,b,defaultEdgeLength/3));
+ }
+
+ cout << "|V|="<<n<<endl;
+ double width=1000;
+ double height=1000;
+ vector<pair<double,double> > startpos(n);
+ for(unsigned i=0;i<n;i++) {
+ double x=getRand(width), y=getRand(height);
+ startpos[i]=make_pair(x,y);
+ }
+ const char *f="scalefree";
+ //run_test(startpos,es,defaultEdgeLength,cx,cy,CG,false,f,"cg");
+ //run_test(startpos,es,defaultEdgeLength,cx,cy,IP,false,f,"ip");
+ //run_test(startpos,es,defaultEdgeLength,cx,cy,UGP,false,f,"ugp");
+ //run_test(startpos,es,defaultEdgeLength,cx,cy,SGP,false,f,"sgp");
+ //run_test(startpos,es,defaultEdgeLength,cx,cy,IP,true,f,"cip");
+ //run_test(startpos,es,defaultEdgeLength,cx,cy,UGP,true,f,"cugp");
+ run_test(startpos,es,defaultEdgeLength,cx,cy,SGP,true,f,"csgp");
+}
+int main() {
+ for(unsigned i=1;i<2;i++) {
+ scale_free(i*50);
+ }
+ return 0;
+}
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 :
diff --git a/src/3rdparty/adaptagrams/libcola/tests/shortest_paths.cpp b/src/3rdparty/adaptagrams/libcola/tests/shortest_paths.cpp
new file mode 100644
index 0000000..617f136
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/shortest_paths.cpp
@@ -0,0 +1,140 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+#include <fstream>
+#include <iostream>
+#include <iomanip>
+//#define TEST_AGAINST_BOOST
+#ifdef TEST_AGAINST_BOOST
+#include <boost/config.hpp>
+#include <boost/property_map.hpp>
+#include <boost/graph/adjacency_list.hpp>
+#include <boost/graph/graphviz.hpp>
+#include <boost/graph/johnson_all_pairs_shortest.hpp>
+using namespace boost;
+#endif // TEST_AGAINST_BOOST
+#include <libcola/shortest_paths.h>
+#include <cmath>
+#include <time.h>
+#include <assert.h>
+
+using namespace std;
+// creates a (not necessarily connected random graph) with n nodes.
+vector<shortest_paths::Edge> random_graph(unsigned n) {
+ vector<shortest_paths::Edge> edges;
+ for(unsigned i=0;i<n;i++) {
+ for(unsigned j=i+1;j<n;j++) {
+ double r=(double)rand()/(double)RAND_MAX;
+ if(r < 0.1) {
+ edges.push_back(make_pair(i,j));
+ }
+ }
+ }
+
+ return edges;
+}
+clock_t lastTime;
+static void resetClock() {
+ lastTime=clock();
+}
+static double getRunTime() {
+ clock_t time = clock()-lastTime;
+ return (double)time/(double)CLOCKS_PER_SEC;
+}
+
+int
+main(void)
+{
+ bool dump=false;
+ srand(time(0));
+#ifdef TEST_AGAINST_BOOST
+ typedef adjacency_list<vecS, vecS, undirectedS, no_property,
+ property< edge_weight_t, double, property< edge_weight2_t, double > > > Graph;
+ Graph g;
+#endif
+ unsigned V = 100;
+ vector<shortest_paths::Edge> es = random_graph(V);
+ unsigned E=es.size();
+ cout << " Test graph |V|="<<V<<",|E|="<<E<<endl;
+ valarray<double> weights(E);
+ for(unsigned i=0;i<E;i++) {
+ weights[i]=round((static_cast<double>(rand())/static_cast<double>(RAND_MAX))*10);
+#ifdef TEST_AGAINST_BOOST
+ add_edge(es[i].first,es[i].second,weights[i],g);
+#endif
+ }
+
+#ifdef TEST_AGAINST_BOOST
+ vector < double >d(V, (numeric_limits < double >::max)());
+ typedef vector<double> weight_vec;
+ vector<weight_vec> D(V,weight_vec(V));
+ cout<<"Running boost::johnson_all_pairs_shortest_paths..."<<endl;
+ resetClock();
+ johnson_all_pairs_shortest_paths(g, D, distance_map(&d[0]));
+ cout<<" ...done, time="<<getRunTime()<<endl;
+#endif
+ double** D1=new double*[V];
+ for(unsigned i=0;i<V;i++) {
+ D1[i]=new double[V];
+ }
+ cout<<"Running shortest_paths::johnsons..."<<endl;
+ resetClock();
+ shortest_paths::johnsons(V,D1,es,weights);
+ cout<<" ...done, time="<<getRunTime()<<endl;
+ double** D2=new double*[V];
+ for(unsigned i=0;i<V;i++) {
+ D2[i]=new double[V];
+ }
+ cout<<"Running shortest_paths::floyd_warshall..."<<endl;
+ resetClock();
+ shortest_paths::floyd_warshall(V,D2,es,weights);
+ cout<<" ...done, time="<<getRunTime()<<endl;
+
+ for (unsigned int i = 0; i < V; ++i) {
+ if(dump) cout << i << " -> ";
+ for (unsigned int j = 0; j < V; ++j) {
+ if(dump) cout << setw(5) << D1[i][j];
+ assert(D1[i][j]==D2[i][j]);
+#ifdef TEST_AGAINST_BOOST
+ assert(D[i][j]==D2[i][j]);
+#endif
+ }
+ if(dump) cout << endl;
+ }
+#ifdef TEST_AGAINST_BOOST
+ if(dump) {
+ ofstream fout("figs/johnson-eg.dot");
+ fout << "graph A {\n" << "node[shape=\"circle\"]\n";
+
+ graph_traits < Graph >::edge_iterator ei, ei_end;
+ for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
+ fout << source(*ei, g) << " -- " << target(*ei, g)
+ << "[label=" << get(edge_weight, g)[*ei] << "]\n";
+
+ fout << "}\n";
+ }
+#endif
+ return 0;
+}
diff --git a/src/3rdparty/adaptagrams/libcola/tests/small_graph.cpp b/src/3rdparty/adaptagrams/libcola/tests/small_graph.cpp
new file mode 100644
index 0000000..53103c9
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/small_graph.cpp
@@ -0,0 +1,111 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+// Loads a graph from a text file, generates constraints for each edge requiring them
+// to point downwards, and proceeds to produce a layout using libcola.
+// The input file format is 2 numeric node labels per line separated by a space,
+// each pair representing a directed edge. Node labels are simply used as array
+// offsets so they should start from 0.
+// The graph should be connected.
+// Default input file is the matrix market 1138_bus graph.
+// Running times:
+// no constraints - steepest descent solver: 149 seconds
+// no constraints - conjugate gradient solver: 21.7 seconds
+// dir-edge constraints - conj grad. solver: 155.69 seconds
+#include<iostream>
+#include<iomanip>
+#include<fstream>
+#include<vector>
+#include<valarray>
+#include<libcola/output_svg.h>
+#include<graphlayouttest.h>
+
+using namespace std;
+using namespace cola;
+
+struct CheckProgress : TestConvergence {
+ CheckProgress(const double d,const unsigned i) : TestConvergence(d,i) {}
+ bool operator()(const double new_stress, valarray<double> & X, valarray<double> & Y) {
+ cout << "stress="<<new_stress<<endl;
+ return TestConvergence::operator()(new_stress,X,Y);
+ }
+};
+int main() {
+ const char *fname="data/wheel.txt"; //"data/dg_850.txt";
+ ifstream f(fname);
+ if(!f.is_open()) {
+ cout << "Error opening file: " << fname << endl;
+ exit(1);
+ }
+ string startlabel, endlabel;
+ unsigned V = 0;
+ double defaultEdgeLength=40;
+ vector<Edge> es;
+ CompoundConstraints cy;
+ //CompoundConstraints cx;
+ while(!getline(f,startlabel,' ').eof()) {
+ getline(f,endlabel);
+ unsigned start = atoi(startlabel.c_str()),
+ end = atoi(endlabel.c_str());
+ es.push_back(make_pair(start,end));
+ //cx.push_back(
+ //new SeparationConstraint(start,end,defaultEdgeLength/3));
+ cy.push_back(
+ new SeparationConstraint(start,end,defaultEdgeLength/3));
+ V=max(V,max(start,end));
+ }
+ V++;
+ cout << "V="<<V<<endl;
+ double width=1000;
+ double height=1000;
+ vector<vpsc::Rectangle*> rs;
+ //srand(time(nullptr));
+ for(unsigned i=0;i<V;i++) {
+ double x=getRand(width), y=getRand(height);
+ rs.push_back(new vpsc::Rectangle(x,x+1,y,y+1));
+ }
+ CheckProgress test(0.001,100);
+ clock_t starttime=clock();
+ ConstrainedMajorizationLayout alg(rs,es,nullptr,defaultEdgeLength,nullptr,test);
+ bool constrained=false;
+ if(!constrained) {
+ cout << "Unconstrained layout" << endl;
+ alg.setConstrainedLayout(true);
+ alg.run();
+ } else {
+ cout << "Constrained layout" << endl;
+ //alg.setXConstraints(&cx);
+ alg.setYConstraints(&cy);
+ alg.run();
+ }
+ double t=double(clock()-starttime)/double(CLOCKS_PER_SEC);
+ cout<<"Time="<<t<<endl;
+ output_svg(rs,es,nullptr,"small_graph.svg",true);
+ for(unsigned i=0;i<V;i++) {
+ delete rs[i];
+ }
+ return 0;
+}
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 :
diff --git a/src/3rdparty/adaptagrams/libcola/tests/sparse_matrix.cpp b/src/3rdparty/adaptagrams/libcola/tests/sparse_matrix.cpp
new file mode 100644
index 0000000..099fcf3
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/sparse_matrix.cpp
@@ -0,0 +1,88 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+#include <map>
+#include <valarray>
+#include <libcola/sparse_matrix.h>
+#include <boost/numeric/ublas/matrix_sparse.hpp>
+#include <boost/numeric/ublas/vector.hpp>
+#include <boost/numeric/ublas/io.hpp>
+#include <time.h>
+#include <cmath>
+
+using namespace boost::numeric::ublas;
+int sparse_test(const unsigned n, cola::SparseMatrix::SparseMap& cm, mapped_matrix<double>& bm) {
+ printf("Sparse test...");
+ srand(time(0));
+ for (unsigned i = 0; i < n; ++ i) {
+ for (unsigned j = 0; j < n; ++ j) {
+ double r=(double)rand()/(double)RAND_MAX;
+ double s=(double)rand()/(double)RAND_MAX;
+ if(r < 0.2) {
+ cm[std::make_pair(i,j)] = s;
+ bm (i, j) = s;
+ }
+ }
+ }
+}
+int dense_test(const unsigned n, cola::SparseMatrix::SparseMap& cm, mapped_matrix<double>& bm) {
+ printf("Dense test...");
+ for (unsigned i = 0; i < n; ++ i) {
+ for (unsigned j = 0; j < n; ++ j) {
+ bm (i, j) = n * i + j;
+ cm[std::make_pair(i,j)]=bm(i,j);
+ }
+ }
+}
+
+void test(int (*generate)(const unsigned, cola::SparseMatrix::SparseMap&, mapped_matrix<double>&)) {
+ using std::valarray;
+ const unsigned n = 20;
+ mapped_matrix<double> bm (n, n, n * n);
+ cola::SparseMatrix::SparseMap cm;
+ generate(n,cm,bm);
+ vector<double> bv (n);
+ valarray<double> cv(n);
+ for (unsigned i = 0; i < n; ++ i) {
+ bv(i) = i;
+ cv[i] = i;
+ }
+ vector<double> br(n);
+ valarray<double> cr(n);
+ cola::SparseMatrix a(cm,n);
+ br=prod(bm,bv);
+ a.rightMultiply(cv,cr);
+ for (unsigned i = 0; i < n; ++ i) {
+ assert(fabs(cr[i]-br(i))<0.000001);
+ }
+ printf(" passed!\n");
+}
+int main() {
+ test(&dense_test);
+ test(&sparse_test);
+ return 0;
+}
+
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4 :
diff --git a/src/3rdparty/adaptagrams/libcola/tests/test_cg.cpp b/src/3rdparty/adaptagrams/libcola/tests/test_cg.cpp
new file mode 100644
index 0000000..13e7d02
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/test_cg.cpp
@@ -0,0 +1,164 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+#include <stdio.h>
+#include <cassert>
+#include <libcola/conjugate_gradient.h>
+#include <gsl/gsl_linalg.h>
+
+using std::valarray;
+
+static valarray<double>
+outer_prod(valarray<double> x, valarray<double> y) {
+ valarray<double> result(x.size()*y.size());
+ for(int j = 0; j < x.size(); j++) {
+ for(int i = 0; i < y.size(); i++) {
+ result[j*y.size() + i] = x[j]*y[i];
+ }
+ }
+ return result;
+}
+
+static double
+uniform() {
+ return double(rand())/ RAND_MAX;
+}
+
+static void
+matrix_times_vector(valarray<double> const &matrix, /* m * n */
+ valarray<double> const &vec, /* n */
+ valarray<double> &result) /* m */
+{
+ unsigned n = vec.size();
+ unsigned m = result.size();
+ assert(m*n == matrix.size());
+ const double* mp = &matrix[0];
+ for (unsigned i = 0; i < m; i++) {
+ double res = 0;
+ for (unsigned j = 0; j < n; j++)
+ res += *mp++ * vec[j];
+ result[i] = res;
+ }
+}
+
+static double
+Linfty(valarray<double> const &vec) {
+ return std::max(vec.max(), -vec.min());
+}
+
+int
+main (void)
+{
+ double tolerance = 1e-6;
+ for(int iters = 0; iters < 100; iters++) {
+ const unsigned N = unsigned(uniform()*40) + 1;
+ double A_data[N*N];
+ printf("%ux%u matrix\n", N,N);
+ for(int r = 0; r < N; r++) {
+ for(int c = 0; c <= r; c++) {
+ A_data[r*N + c] = A_data[c*N + r] = fabs(uniform());
+ }
+ }
+
+ double * A_c[N];
+ for(int i = 0; i < N; i++)
+ A_c[i] = &A_data[N*i];
+
+ double b_data[N];
+ for(int i = 0; i < N; i++)
+ b_data[i] = uniform()*3;
+ std::valarray<double> b(b_data, N), xx(0.0, N);
+ std::valarray<double> A(A_data, N*N);
+
+ conjugate_gradient(A, xx, b, N, tolerance, 2*N);
+
+ gsl_matrix_view m
+ = gsl_matrix_view_array (A_data, N, N);
+ gsl_vector_view bgsl
+ = gsl_vector_view_array (b_data, N);
+
+ gsl_vector *xgsl = gsl_vector_alloc (N);
+
+ int s;
+
+ gsl_permutation * p = gsl_permutation_alloc (N);
+
+ gsl_linalg_LU_decomp (&m.matrix, p, &s);
+
+ gsl_linalg_LU_solve (&m.matrix, p, &bgsl.vector, xgsl);
+
+ std::valarray<double> gsl_xx(0.0, N);
+ for(unsigned i = 0; i < xx.size(); i++) {
+ gsl_xx[i] = gsl_vector_get(xgsl, i);
+ }
+
+ double err = Linfty(xx - gsl_xx);
+ printf ("|xx-nxgsl|_infty = %g\n", err);
+ if(err > tolerance) {
+#if 0 //dubious value
+ for(int r = 0; r < N; r++) {
+ for(int c = 0; c < N; c++) {
+ printf("%g ", A_data[r*N + c]);
+ }
+ printf("\n");
+ }
+#endif
+ printf("\nx njh-cg = \n");
+ for(unsigned i = 0; i < xx.size(); i++)
+ printf("%g ", xx[i]);
+ printf("\nxgsl = ");
+ for(unsigned i = 0; i < xx.size(); i++)
+ printf("%g ", gsl_xx[i]);
+ printf("\n");
+ valarray<double> result(0.0,N);
+ matrix_times_vector(A, xx, result);
+ result -= b;
+ printf("\nA xx -b = ");
+ for(unsigned i = 0; i < xx.size(); i++)
+ printf("%g ", result[i]);
+ printf("\n");
+ matrix_times_vector(A, gsl_xx, result);
+ result -= b;
+ printf("\nA gsl_xx -b = ");
+ for(unsigned i = 0; i < xx.size(); i++)
+ printf("%g ", result[i]);
+ printf("\n");
+
+ printf("FAILED!!!!!!!!!!!!!!!!!!!!!!!!\n");
+ exit(1);
+ }
+ }
+ return 0;
+}
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
diff --git a/src/3rdparty/adaptagrams/libcola/tests/topology.cpp b/src/3rdparty/adaptagrams/libcola/tests/topology.cpp
new file mode 100644
index 0000000..4c94ef7
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/topology.cpp
@@ -0,0 +1,177 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+/** \file topology.cpp
+ *
+ * tests topology preserving layout. graph is a triangle.
+ * We have a fourth disconnected node starting inside the triangle.
+ * We give the disconnected node a desired position outside the triangle
+ * and begin layout. Layout should converge to near zero stress as all
+ * edges should be able to reach their desired lengths, and disconnected
+ * node should still be inside the triangle at the end.
+ *
+ *
+ * Authors:
+ * Tim Dwyer <tgdwyer@gmail.com>
+ */
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+
+#include <vector>
+#include <valarray>
+#include <algorithm>
+#include <float.h>
+#include <libcola/cola.h>
+#include <libtopology/topology_graph.h>
+#include "graphlayouttest.h"
+using namespace std;
+using namespace cola;
+
+topology::Node* addNode(
+ topology::Nodes& vs, vpsc::Rectangle* r) {
+ topology::Node *v = new topology::Node(vs.size(), r);
+ vs.push_back(v);
+ return v;
+}
+void addToPath(topology::EdgePoints& ps, topology::Node *v, topology::EdgePoint::RectIntersect i) {
+ ps.push_back(new topology::EdgePoint(v,i));
+}
+struct SetDesiredPos : public PreIteration {
+ SetDesiredPos(Locks& locks) : PreIteration(locks) {}
+ bool operator()() {
+ return true;
+ }
+};
+void writeFile(const topology::Nodes& vs, const topology::Edges& es, const char *outputFileName) {
+ const unsigned n=vs.size();
+ vector<cola::Edge> cedges;
+
+ for(unsigned i=0;i<es.size();i++) {
+ cedges.push_back(make_pair(1,2));
+ }
+
+ vector<straightener::Route*> routes;
+ for(topology::Edges::const_iterator e=es.begin();e!=es.end();++e) {
+ routes.push_back((*e)->getRoute());
+ }
+
+ vector<string> labels(n);
+ for(unsigned i=0;i<n;++i) {
+ stringstream ss;
+ ss << i;
+ labels[i]=ss.str();
+ }
+
+ vector<vpsc::Rectangle*> rs;
+ for(topology::Nodes::const_iterator i=vs.begin();i!=vs.end();++i) {
+ rs.push_back((*i)->rect);
+ }
+ OutputFile of(rs,cedges,nullptr,outputFileName,true,false);
+ of.setLabels(labels);
+ of.routes=&routes;
+ of.generate();
+
+ for_each(routes.begin(),routes.end(),delete_object());
+}
+struct Test : TestConvergence {
+ Test(const double d,const unsigned i,topology::Nodes& vs, topology::Edges& es) : TestConvergence(d,i), vs(vs), es(es) {}
+ bool operator()(const double new_stress, valarray<double> & X, valarray<double> & Y) {
+ cout << "stress="<<new_stress<<" iteration="<<iterations<<endl;
+ stringstream ss;
+ ss << "topology-" << setfill('0') << setw(3) << ++iterations << ".svg";
+ writeFile(vs,es,ss.str().c_str());
+ if(iterations<100) {
+ return false;
+ }
+ return true;
+ return TestConvergence::operator()(new_stress,X,Y);
+ }
+ double lastStress;
+ topology::Nodes& vs;
+ topology::Edges& es;
+};
+void randomMove(int i) {
+ printf("We have a triangle of three connected nodes and a fourth disconnected node. We set the fourth node's desired position at a point some random direction outside the triangle.\n");
+ printf("Using srand=%d\n",i);
+ srand(i);
+ const unsigned V = 4;
+ Edge edge_array[] = { Edge(0, 1), Edge(1, 2), Edge(2, 0) };
+ const std::size_t E = sizeof(edge_array) / sizeof(Edge);
+ vector<Edge> es(edge_array,edge_array+E);
+ vector<vpsc::Rectangle*> rs;
+ double x[]={200,250,300,250},y[]={200,250,200,225},size=10;
+ for(unsigned i=0;i<V;++i) {
+ rs.push_back(new vpsc::Rectangle(x[i],x[i]+size,y[i],y[i]+size));
+ }
+ double idealLength=60;
+ // set up topology graph
+ topology::Nodes vs;
+ for(vector<Rectangle*>::iterator i = rs.begin(); i!=rs.end();++i) {
+ addNode(vs,*i);
+ }
+ topology::Edges tes;
+ unsigned eID=0;
+ for(vector<Edge>::iterator e=es.begin();e!=es.end();++e, ++eID) {
+ topology::EdgePoints ps;
+ addToPath(ps,vs[e->first],topology::EdgePoint::CENTRE);
+ addToPath(ps,vs[e->second],topology::EdgePoint::CENTRE);
+ tes.push_back(new topology::Edge(eID, idealLength, ps));
+ }
+ writeFile(vs,tes,"topology-000.svg");
+ Locks locks;
+ // we move the 4th node somewhere outside the triangle. The triangle should be
+ // dragged along!
+ const double PI = 2.0*acos(0.0);
+ double angle = getRand(2.0*PI);
+ double dx=150*cos(angle), dy=150*sin(angle);
+
+ double lx=rs[3]->getCentreX()+dx,
+ ly=rs[3]->getCentreY()+dy;
+ //double lx=353.886210, ly=342.789705;
+ locks.push_back(Lock(3,lx,ly));
+ printf(" Lock: %f,%f\n",lx,ly);
+ SetDesiredPos preIteration(locks);
+ Test test(0.00001,100,vs,tes);
+ ConstrainedFDLayout alg(rs,es,idealLength,nullptr,test,&preIteration);
+
+ alg.setTopology(&vs,&tes);
+ alg.run(true,true);
+ double finalStress=alg.computeStress();
+ printf("finalStress=%f\n",finalStress);
+
+ //assert(finalStress<1e-5);
+ for_each(rs.begin(),rs.end(),delete_object());
+ for_each(tes.begin(),tes.end(),delete_object());
+ for_each(vs.begin(),vs.end(),delete_object());
+}
+int main() {
+ unsigned i=0;
+ for(;i<1;i++) {
+ randomMove(i);
+ }
+ return 0;
+}
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=80 :
diff --git a/src/3rdparty/adaptagrams/libcola/tests/trees.cpp b/src/3rdparty/adaptagrams/libcola/tests/trees.cpp
new file mode 100644
index 0000000..72fb296
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/trees.cpp
@@ -0,0 +1,103 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+#include<iostream>
+#include<vector>
+#include <cmath>
+#include <time.h>
+#include <valarray>
+
+#include "graphlayouttest.h"
+
+using namespace std;
+using namespace cola;
+
+void makeEdge(unsigned u, unsigned v,
+ vector<Edge> &edges, CompoundConstraints &cy) {
+ edges.push_back(make_pair(u,v));
+ cy.push_back(new SeparationConstraint(u,v,20));
+}
+vector<Edge> random_tree(unsigned depth, unsigned maxbranch, unsigned &V,
+ CompoundConstraints &cx, CompoundConstraints &cy) {
+ vector<Edge> edges;
+ unsigned lstart=0, lend=1;
+ V=0;
+ for(unsigned i=0;i<depth;i++) {
+ for(unsigned j=lstart;j<lend;j++) {
+ //makeEdge(j,++V,edges,cy);
+ //makeEdge(j,++V,edges,cy);
+ for(unsigned k=0;k<maxbranch;k++) {
+ double r=(double)rand()/(double)RAND_MAX;
+ if(r < 0.5) {
+ makeEdge(j,++V,edges,cy);
+ }
+ }
+ }
+ lstart=lend;
+ lend=V+1;
+ }
+ V++;
+ DFS::Graph dfs(V,edges);
+ for(unsigned i=1;i<dfs.order.size();i++) {
+ cx.push_back(
+ new SeparationConstraint(dfs.order[i-1],dfs.order[i],0.5));
+ }
+ /*
+ for(unsigned i=0;i<dfs.leaves.size();i++) {
+ for(unsigned j=1;j<dfs.leaves[i].size();j++) {
+ cx.push_back(
+ new SeparationConstraint(dfs.leaves[i][j-1],dfs.leaves[i][j],10));
+ }
+ }
+ */
+ return edges;
+}
+int main() {
+ unsigned V;
+ CompoundConstraints cx,cy;
+ //srand(time(nullptr));
+ srand(3);
+ vector<Edge> es = random_tree(7,4,V,cx,cy);
+ double defaultEdgeLength=40;
+
+ cout << "V="<<V<<endl;
+ double width=1000;
+ double height=1000;
+ vector<pair<double,double> > startpos(V);
+ for(unsigned i=0;i<V;i++) {
+ double x=getRand(width), y=getRand(height);
+ startpos[i]=make_pair(x,y);
+ }
+ const char *testname="trees";
+ run_test(startpos,es,defaultEdgeLength,cx,cy,CG,false,testname,"cg");
+ run_test(startpos,es,defaultEdgeLength,cx,cy,IP,false,testname,"ip");
+ run_test(startpos,es,defaultEdgeLength,cx,cy,SGP,false,testname,"sgp");
+ run_test(startpos,es,defaultEdgeLength,cx,cy,UGP,false,testname,"ugp");
+ run_test(startpos,es,defaultEdgeLength,cx,cy,IP,true,testname,"cip");
+ run_test(startpos,es,defaultEdgeLength,cx,cy,SGP,true,testname,"csgp");
+ run_test(startpos,es,defaultEdgeLength,cx,cy,UGP,true,testname,"cugp");
+ return 0;
+}
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 :
diff --git a/src/3rdparty/adaptagrams/libcola/tests/unconstrained.cpp b/src/3rdparty/adaptagrams/libcola/tests/unconstrained.cpp
new file mode 100644
index 0000000..f6f112b
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/unconstrained.cpp
@@ -0,0 +1,71 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+/** \file unconstrained.cpp
+ *
+ * Unconstrained graph layout test. Simple graph with 4 nodes and 4 edges,
+ * a triangle with a dangle. Final stress checked.
+ *
+ *
+ * Authors:
+ * Tim Dwyer <tgdwyer@gmail.com>
+ */
+#include <iostream>
+#include <fstream>
+
+#include <vector>
+#include <valarray>
+#include <algorithm>
+#include <float.h>
+#include "graphlayouttest.h"
+using namespace std;
+
+using namespace cola;
+int main() {
+
+ const unsigned V = 4;
+ Edge edge_array[] = { Edge(0, 1), Edge(1, 2), Edge(2, 3), Edge(1, 3) };
+ const std::size_t E = sizeof(edge_array) / sizeof(Edge);
+ vector<Edge> es(E);
+ copy(edge_array,edge_array+E,es.begin());
+ double width=100;
+ double height=100;
+ vector<vpsc::Rectangle*> rs;
+ for(unsigned i=0;i<V;i++) {
+ double x=getRand(width), y=getRand(height);
+ rs.push_back(new vpsc::Rectangle(x,x+5,y,y+5));
+ }
+ CheckProgress test(1e-9,100);
+ ConstrainedFDLayout alg(rs,es,width/2,nullptr,&test);
+ alg.run();
+ double stress = alg.computeStress();
+ assert(stress < 0.0013);
+ OutputFile output(rs,es,nullptr,"unconstrained.svg");
+ output.generate();
+ for(unsigned i=0;i<V;i++) {
+ delete rs[i];
+ }
+ return 0;
+}
diff --git a/src/3rdparty/adaptagrams/libcola/tests/unsatisfiable.cpp b/src/3rdparty/adaptagrams/libcola/tests/unsatisfiable.cpp
new file mode 100644
index 0000000..4e768f7
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/unsatisfiable.cpp
@@ -0,0 +1,85 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+
+/** \file
+ * Interface between Inkscape code (SPItem) and graphlayout functions.
+ *
+ * Authors:
+ * Tim Dwyer <tgdwyer@gmail.com>
+ */
+#include <iostream>
+
+#include <vector>
+#include <algorithm>
+#include <float.h>
+#include <libcola/cola.h>
+#include <libvpsc/exceptions.h>
+#include <libvpsc/constraint.h>
+#include "graphlayouttest.h"
+
+using namespace std;
+using namespace cola;
+int main() {
+
+ const unsigned V = 2;
+ typedef pair < unsigned, unsigned >Edge;
+ Edge edge_array[] = { Edge(0, 1) };
+ unsigned E = sizeof(edge_array) / sizeof(Edge);
+ vector<Edge> es(edge_array,edge_array+E);
+ double width=100;
+ double height=100;
+ vector<vpsc::Rectangle*> rs;
+ for(unsigned i=0;i<V;i++) {
+ double x=getRand(width), y=getRand(height);
+ rs.push_back(new vpsc::Rectangle(x,x+5,y,y+5));
+ }
+ ConstrainedFDLayout alg(rs,es,width/2);
+ CompoundConstraints ccs;
+ AlignmentConstraint ac(vpsc::YDIM, 1);
+ ccs.push_back(&ac);
+ ac.addShape(0,0);
+ ac.addShape(1,0);
+ ccs.push_back(new SeparationConstraint(vpsc::YDIM, 0,1,10));
+ alg.setConstraints(ccs);
+ try {
+ alg.run();
+ } catch (vpsc::UnsatisfiableException& e) {
+ cerr << "Unsatisfiable" << endl;
+ for(vector<vpsc::Constraint*>::iterator i=e.path.begin();
+ i!=e.path.end();i++) {
+ cout << **i << endl;
+ }
+ exit(1);
+ }
+ //assert(fabs(rs[0]->getCentreX()-rs[3]->getCentreX())<0.001);
+ cout<<rs[0]->getCentreX()<<","<<rs[1]->getCentreX()<<endl;
+ //output_svg(rs,es,"unsatisfiable.svg");
+ for(unsigned i=0;i<V;i++) {
+ delete rs[i];
+ }
+ return 0;
+}
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4:textwidth=99 :
diff --git a/src/3rdparty/adaptagrams/libcola/tests/view_cd_output.sh b/src/3rdparty/adaptagrams/libcola/tests/view_cd_output.sh
new file mode 100755
index 0000000..cb74ae8
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/view_cd_output.sh
@@ -0,0 +1,43 @@
+#! /bin/bash
+
+if [ $# -lt 1 ] ; then
+ echo "Need case letter (eg: A) or ALL for all cases (CLEAN to delete)"
+ exit
+else
+ CASE=$1
+ shift
+fi
+
+cd /home/kierans/libcola3/libcola/tests
+
+if [ $CASE == 'a' -o $CASE == 'A' ] ; then
+ inkview cycle_detector_case_a.svg
+fi
+
+if [ $CASE == 'b' -o $CASE == 'B' ] ; then
+ inkview cycle_detector_case_b.svg
+fi
+
+if [ $CASE == 'c' -o $CASE == 'C' ] ; then
+ inkview cycle_detector_case_c.svg
+fi
+
+if [ $CASE == 'd' -o $CASE == 'D' ] ; then
+ inkview cycle_detector_case_d.svg
+fi
+
+if [ $CASE == 'e' -o $CASE == 'E' ] ; then
+ inkview cycle_detector_case_e.svg
+fi
+
+if [ $CASE == 'f' -o $CASE == 'F' ] ; then
+ inkview cycle_detector_case_f.svg
+fi
+
+if [ $CASE == 'all' -o $CASE == 'ALL' ] ; then
+ inkview cycle_detector_case_a.svg cycle_detector_case_b.svg cycle_detector_case_c.svg cycle_detector_case_d.svg cycle_detector_case_e.svg cycle_detector_case_f.svg
+fi
+
+if [ $CASE == 'clean' ] ; then
+ rm cycle_detector_case* -fv
+fi
diff --git a/src/3rdparty/adaptagrams/libcola/tests/view_mas_output.sh b/src/3rdparty/adaptagrams/libcola/tests/view_mas_output.sh
new file mode 100755
index 0000000..11f5a8a
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/tests/view_mas_output.sh
@@ -0,0 +1,43 @@
+#! /bin/bash
+
+if [ $# -lt 1 ] ; then
+ echo "Need case letter (eg: A) or ALL for all cases (CLEAN to delete)"
+ exit
+else
+ CASE=$1
+ shift
+fi
+
+cd /home/kierans/libcola3/libcola/tests
+
+if [ $CASE == 'a' -o $CASE == 'A' ] ; then
+ inkview mas_case_a.svg
+fi
+
+if [ $CASE == 'b' -o $CASE == 'B' ] ; then
+ inkview mas_case_b.svg
+fi
+
+if [ $CASE == 'c' -o $CASE == 'C' ] ; then
+ inkview mas_case_c.svg
+fi
+
+if [ $CASE == 'd' -o $CASE == 'D' ] ; then
+ inkview mas_case_d.svg
+fi
+
+if [ $CASE == 'e' -o $CASE == 'E' ] ; then
+ inkview mas_case_e.svg
+fi
+
+if [ $CASE == 'f' -o $CASE == 'F' ] ; then
+ inkview mas_case_f.svg
+fi
+
+if [ $CASE == 'all' -o $CASE == 'ALL' ] ; then
+ inkview mas_case_a.svg mas_case_b.svg mas_case_c.svg mas_case_d.svg mas_case_e.svg mas_case_f.svg
+fi
+
+if [ $CASE == 'clean' ] ; then
+ rm mas_case* -fv
+fi
diff --git a/src/3rdparty/adaptagrams/libcola/unused.h b/src/3rdparty/adaptagrams/libcola/unused.h
new file mode 100644
index 0000000..1e519fe
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libcola/unused.h
@@ -0,0 +1,26 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libcola - A library providing force-directed network layout using the
+ * stress-majorization method subject to separation constraints.
+ *
+ * Copyright (C) 2006-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+*/
+
+#ifndef _UNUSED_H
+#define _UNUSED_H
+
+#define COLA_UNUSED(expr) do { (void)(expr); } while (0)
+
+#endif
diff --git a/src/3rdparty/adaptagrams/libvpsc/CMakeLists.txt b/src/3rdparty/adaptagrams/libvpsc/CMakeLists.txt
new file mode 100644
index 0000000..538ad30
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/CMakeLists.txt
@@ -0,0 +1,28 @@
+
+set(libvpsc_SRC
+ block.cpp
+ blocks.cpp
+ cbuffer.cpp
+ constraint.cpp
+ rectangle.cpp
+ solve_VPSC.cpp
+ variable.cpp
+
+
+ # -------
+ # Headers
+ assertions.h
+ block.h
+ blocks.h
+ cbuffer.h
+ constraint.h
+ exceptions.h
+ linesegment.h
+ pairing_heap.h
+ rectangle.h
+ solve_VPSC.h
+ variable.h
+)
+
+include_directories("${CMAKE_CURRENT_SOURCE_DIR}/..")
+add_inkscape_lib(vpsc_LIB "${libvpsc_SRC}")
diff --git a/src/3rdparty/adaptagrams/libvpsc/COPYING b/src/3rdparty/adaptagrams/libvpsc/COPYING
new file mode 100644
index 0000000..6ff1d7b
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/COPYING
@@ -0,0 +1,505 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
+
diff --git a/src/3rdparty/adaptagrams/libvpsc/Makefile.am b/src/3rdparty/adaptagrams/libvpsc/Makefile.am
new file mode 100644
index 0000000..12e779a
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/Makefile.am
@@ -0,0 +1,42 @@
+EXTRA_DIST=libvpsc.pc.in
+lib_LTLIBRARIES = libvpsc.la
+libvpsc_la_CPPFLAGS = -I$(top_srcdir) -I$(includedir)/libvpsc -fPIC
+libvpsc_la_LDFLAGS = -no-undefined
+
+#DEFS=-DLIBVPSC_LOGGING
+
+
+libvpsc_la_SOURCES = block.cpp\
+ blocks.cpp\
+ constraint.cpp\
+ rectangle.cpp\
+ solve_VPSC.cpp\
+ variable.cpp\
+ cbuffer.cpp\
+ isnan.h\
+ block.h\
+ blocks.h\
+ constraint.h\
+ rectangle.h\
+ pairingheap.h\
+ solve_VPSC.h\
+ variable.h\
+ cbuffer.h\
+ linesegment.h\
+ assertions.h
+
+libvpscincludedir = $(includedir)/libvpsc
+
+libvpscinclude_HEADERS = solve_VPSC.h \
+ block.h\
+ constraint.h\
+ exceptions.h\
+ rectangle.h\
+ variable.h \
+ assertions.h
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = libvpsc.pc
+
+SUBDIRS = . tests
+
diff --git a/src/3rdparty/adaptagrams/libvpsc/assertions.h b/src/3rdparty/adaptagrams/libvpsc/assertions.h
new file mode 100644
index 0000000..f197069
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/assertions.h
@@ -0,0 +1,102 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2009 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+*/
+
+#ifndef VPSC_ASSERTIONS_H
+#define VPSC_ASSERTIONS_H
+
+#ifdef NDEBUG
+
+ #define COLA_ASSERT(expr) static_cast<void>(0)
+
+#else // Not NDEBUG
+
+ // sstream needs ::strcpy_s under MinGW so include cstring.
+ #include <cstring>
+
+ #include <sstream>
+ #include <cassert>
+
+ #if defined(USE_ASSERT_EXCEPTIONS)
+
+ // String seems to be missing on MinGW's gcc,
+ // so define it here if it is missing.
+ #ifndef __STRING
+ #define __STRING(x) #x
+ #endif
+
+ #if !defined(__ASSERT_FUNCTION)
+ #define COLA_ASSERT(expr) \
+ if (!(expr)) { \
+ throw vpsc::CriticalFailure(__STRING(expr), __FILE__, __LINE__); \
+ }
+ #else
+ #define COLA_ASSERT(expr) \
+ if (!(expr)) { \
+ throw vpsc::CriticalFailure(__STRING(expr), __FILE__, __LINE__, \
+ __ASSERT_FUNCTION); \
+ }
+ #endif
+
+ #else
+ #define COLA_ASSERT(expr) assert(expr)
+ #endif
+
+namespace vpsc {
+
+// Critical failure: either something went wrong, or (more likely) there
+// was infeasible input.
+class CriticalFailure
+{
+ public:
+ CriticalFailure(const char *expr, const char *file, int line,
+ const char *function = nullptr)
+ : expr(expr),
+ file(file),
+ line(line),
+ function(function)
+ {
+ }
+ std::string what() const
+ {
+ std::stringstream s;
+ s << "ERROR: Critical assertion failed.\n";
+ s << " expression: " << expr << "\n";
+ s << " at line " << line << " of " << file << "\n";
+ if (function)
+ {
+ s << " in: " << function << "\n";
+ }
+
+ return s.str();
+ }
+ private:
+ const char *expr;
+ const char *file;
+ int line;
+ const char *function;
+};
+
+}
+
+#endif // NDEBUG
+
+
+#endif // VPSC_ASSERTIONS_H
+
diff --git a/src/3rdparty/adaptagrams/libvpsc/block.cpp b/src/3rdparty/adaptagrams/libvpsc/block.cpp
new file mode 100644
index 0000000..dfcf6c9
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/block.cpp
@@ -0,0 +1,647 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2005-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+*/
+
+/*
+ * @brief A block is a group of variables that must be moved together to improve
+ * the goal function without violating already active constraints.
+ * The variables in a block are spanned by a tree of active constraints.
+ *
+ */
+
+#include "libvpsc/block.h"
+#include "libvpsc/variable.h"
+#include <cassert>
+#include "libvpsc/pairing_heap.h"
+#include "libvpsc/constraint.h"
+#include "libvpsc/exceptions.h"
+#include "libvpsc/blocks.h"
+
+#ifdef LIBVPSC_LOGGING
+#include <fstream>
+using std::ios;
+using std::ofstream;
+using std::endl;
+#endif
+
+#define __NOTNAN(p) (p)==(p)
+
+namespace vpsc {
+void PositionStats::addVariable(Variable* v) {
+ double ai=scale/v->scale;
+ double bi=v->offset/v->scale;
+ double wi=v->weight;
+ AB+=wi*ai*bi;
+ AD+=wi*ai*v->desiredPosition;
+ A2+=wi*ai*ai;
+ /*
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f << "adding v[" << v->id << "], blockscale=" << scale << ", despos="
+ << v->desiredPosition << ", ai=" << ai << ", bi=" << bi
+ << ", AB=" << AB << ", AD=" << AD << ", A2=" << A2;
+#endif
+*/
+}
+void Block::addVariable(Variable* v) {
+ v->block=this;
+ vars->push_back(v);
+ if(ps.A2==0) ps.scale=v->scale;
+ //weight+= v->weight;
+ //wposn += v->weight * (v->desiredPosition - v->offset);
+ //posn=wposn/weight;
+ ps.addVariable(v);
+ posn=(ps.AD - ps.AB) / ps.A2;
+ COLA_ASSERT(__NOTNAN(posn));
+ /*
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f << ", posn=" << posn << endl;
+#endif
+*/
+}
+Block::Block(Blocks *blocks, Variable* const v)
+ : vars(new std::vector<Variable*>)
+ , posn(0)
+ //, weight(0)
+ //, wposn(0)
+ , deleted(false)
+ , timeStamp(0)
+ , in(nullptr)
+ , out(nullptr)
+ , blocks(blocks)
+{
+ if(v!=nullptr) {
+ v->offset=0;
+ addVariable(v);
+ }
+}
+
+void Block::updateWeightedPosition() {
+ //wposn=0;
+ ps.AB=ps.AD=ps.A2=0;
+ for (Vit v=vars->begin();v!=vars->end();++v) {
+ //wposn += ((*v)->desiredPosition - (*v)->offset) * (*v)->weight;
+ ps.addVariable(*v);
+ }
+ posn=(ps.AD - ps.AB) / ps.A2;
+ COLA_ASSERT(__NOTNAN(posn));
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f << ", posn=" << posn << endl;
+#endif
+}
+Block::~Block(void)
+{
+ delete vars;
+ delete in;
+ delete out;
+}
+void Block::setUpInConstraints() {
+ setUpConstraintHeap(in,true);
+}
+void Block::setUpOutConstraints() {
+ setUpConstraintHeap(out,false);
+}
+void Block::setUpConstraintHeap(PairingHeap<Constraint*,CompareConstraints>* &h,bool in) {
+ delete h;
+ h = new PairingHeap<Constraint*,CompareConstraints>();
+ for (Vit i=vars->begin();i!=vars->end();++i) {
+ Variable *v=*i;
+ std::vector<Constraint*> *cs=in?&(v->in):&(v->out);
+ for (Cit j=cs->begin();j!=cs->end();++j) {
+ Constraint *c=*j;
+ c->timeStamp=blocks->blockTimeCtr;
+ if ( ((c->left->block != this) && in) ||
+ ((c->right->block != this) && !in) )
+ {
+ h->insert(c);
+ }
+ }
+ }
+}
+Block* Block::merge(Block* b, Constraint* c) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" merging on: "<<*c<<",c->left->offset="<<c->left->offset<<",c->right->offset="<<c->right->offset<<endl;
+#endif
+ double dist = c->right->offset - c->left->offset - c->gap;
+ Block *l=c->left->block;
+ Block *r=c->right->block;
+ if (l->vars->size() < r->vars->size()) {
+ r->merge(l,c,dist);
+ } else {
+ l->merge(r,c,-dist);
+ }
+ Block* mergeBlock=b->deleted?this:b;
+#ifdef LIBVPSC_LOGGING
+ f<<" merged block="<<*mergeBlock<<endl;
+#endif
+ return mergeBlock;
+}
+/*
+ * Merges b into this block across c. Can be either a
+ * right merge or a left merge
+ * @param b block to merge into this
+ * @param c constraint being merged
+ * @param distance separation required to satisfy c
+ */
+void Block::merge(Block *b, Constraint *c, double dist) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" merging: "<<*b<<"dist="<<dist<<endl;
+#endif
+ c->active=true;
+ //wposn+=b->wposn-dist*b->weight;
+ //weight+=b->weight;
+ for(Vit i=b->vars->begin();i!=b->vars->end();++i) {
+ Variable *v=*i;
+ //v->block=this;
+ //vars->push_back(v);
+ v->offset+=dist;
+ addVariable(v);
+ }
+#ifdef LIBVPSC_LOGGING
+ for(Vit i=vars->begin();i!=vars->end();++i) {
+ Variable *v=*i;
+ f<<" v["<<v->id<<"]: d="<<v->desiredPosition
+ <<" a="<<v->scale<<" o="<<v->offset
+ <<endl;
+ }
+ f<<" AD="<<ps.AD<<" AB="<<ps.AB<<" A2="<<ps.A2<<endl;
+#endif
+ //posn=wposn/weight;
+ //COLA_ASSERT(wposn==ps.AD - ps.AB);
+ posn=(ps.AD - ps.AB) / ps.A2;
+ COLA_ASSERT(__NOTNAN(posn));
+ b->deleted=true;
+}
+
+void Block::mergeIn(Block *b) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" merging constraint heaps... "<<endl;
+#endif
+ // We check the top of the heaps to remove possible internal constraints
+ findMinInConstraint();
+ b->findMinInConstraint();
+ in->merge(b->in);
+#ifdef LIBVPSC_LOGGING
+ f<<" merged heap: "<<*in<<endl;
+#endif
+}
+void Block::mergeOut(Block *b) {
+ findMinOutConstraint();
+ b->findMinOutConstraint();
+ out->merge(b->out);
+}
+Constraint *Block::findMinInConstraint() {
+ Constraint *v = nullptr;
+ std::vector<Constraint*> outOfDate;
+ while (!in->isEmpty()) {
+ v = in->findMin();
+ Block *lb=v->left->block;
+ Block *rb=v->right->block;
+ // rb may not be this if called between merge and mergeIn
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" checking constraint ... "<<*v;
+ f<<" timestamps: left="<<lb->timeStamp<<" right="<<rb->timeStamp<<" constraint="<<v->timeStamp<<endl;
+#endif
+ if(lb == rb) {
+ // constraint has been merged into the same block
+#ifdef LIBVPSC_LOGGING
+ if(v->slack()<0) {
+ f<<" violated internal constraint found! "<<*v<<endl;
+ f<<" lb="<<*lb<<endl;
+ f<<" rb="<<*rb<<endl;
+ }
+#endif
+ in->deleteMin();
+#ifdef LIBVPSC_LOGGING
+ f<<" ... skipping internal constraint"<<endl;
+#endif
+ } else if(v->timeStamp < lb->timeStamp) {
+ // block at other end of constraint has been moved since this
+ in->deleteMin();
+ outOfDate.push_back(v);
+#ifdef LIBVPSC_LOGGING
+ f<<" reinserting out of date (reinsert later)"<<endl;
+#endif
+ } else {
+ break;
+ }
+ }
+ for(Cit i=outOfDate.begin();i!=outOfDate.end();++i) {
+ v=*i;
+ v->timeStamp=blocks->blockTimeCtr;
+ in->insert(v);
+ }
+ if(in->isEmpty()) {
+ v=nullptr;
+ } else {
+ v=in->findMin();
+ }
+ return v;
+}
+Constraint *Block::findMinOutConstraint() {
+ if(out->isEmpty()) return nullptr;
+ Constraint *v = out->findMin();
+ while (v->left->block == v->right->block) {
+ out->deleteMin();
+ if(out->isEmpty()) return nullptr;
+ v = out->findMin();
+ }
+ return v;
+}
+void Block::deleteMinInConstraint() {
+ in->deleteMin();
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<"deleteMinInConstraint... "<<endl;
+ f<<" result: "<<*in<<endl;
+#endif
+}
+void Block::deleteMinOutConstraint() {
+ out->deleteMin();
+}
+inline bool Block::canFollowLeft(Constraint const* c, Variable const* last) const {
+ return c->left->block==this && c->active && last!=c->left;
+}
+inline bool Block::canFollowRight(Constraint const* c, Variable const* last) const {
+ return c->right->block==this && c->active && last!=c->right;
+}
+
+// computes the derivative of v and the lagrange multipliers
+// of v's out constraints (as the recursive sum of those below.
+// Does not backtrack over u.
+// also records the constraint with minimum lagrange multiplier
+// in min_lm
+double Block::compute_dfdv(Variable* const v, Variable* const u,
+ Constraint *&min_lm) {
+ double dfdv=v->dfdv();
+ for(Cit it=v->out.begin();it!=v->out.end();++it) {
+ Constraint *c=*it;
+ if(canFollowRight(c,u)) {
+ c->lm=compute_dfdv(c->right,v,min_lm);
+ dfdv+=c->lm*c->left->scale;
+ if(!c->equality&&(min_lm==nullptr||c->lm<min_lm->lm)) min_lm=c;
+ }
+ }
+ for(Cit it=v->in.begin();it!=v->in.end();++it) {
+ Constraint *c=*it;
+ if(canFollowLeft(c,u)) {
+ c->lm=-compute_dfdv(c->left,v,min_lm);
+ dfdv-=c->lm*c->right->scale;
+ if(!c->equality&&(min_lm==nullptr||c->lm<min_lm->lm)) min_lm=c;
+ }
+ }
+ return dfdv/v->scale;
+}
+double Block::compute_dfdv(Variable* const v, Variable* const u) {
+ double dfdv = v->dfdv();
+ for(Cit it = v->out.begin(); it != v->out.end(); ++it) {
+ Constraint *c = *it;
+ if(canFollowRight(c,u)) {
+ c->lm = compute_dfdv(c->right,v);
+ dfdv += c->lm * c->left->scale;
+ }
+ }
+ for(Cit it=v->in.begin();it!=v->in.end();++it) {
+ Constraint *c = *it;
+ if(canFollowLeft(c,u)) {
+ c->lm = - compute_dfdv(c->left,v);
+ dfdv -= c->lm * c->right->scale;
+ }
+ }
+ return dfdv/v->scale;
+}
+
+// The top level v and r are variables between which we want to find the
+// constraint with the smallest lm.
+// Similarly, m is initially nullptr and is only assigned a value if the next
+// variable to be visited is r or if a possible min constraint is returned from
+// a nested call (rather than nullptr).
+// Then, the search for the m with minimum lm occurs as we return from
+// the recursion (checking only constraints traversed left-to-right
+// in order to avoid creating any new violations).
+// We also do not consider equality constraints as potential split points
+bool Block::split_path(
+ Variable* r,
+ Variable* const v,
+ Variable* const u,
+ Constraint* &m,
+ bool desperation=false
+ )
+{
+ for(Cit it(v->in.begin());it!=v->in.end();++it) {
+ Constraint *c=*it;
+ if(canFollowLeft(c,u)) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" left split path: "<<*c<<endl;
+#endif
+ if(c->left==r) {
+ if(desperation&&!c->equality) m=c;
+ return true;
+ } else {
+ if(split_path(r,c->left,v,m)) {
+ if(desperation && !c->equality && (!m||c->lm<m->lm)) {
+ m=c;
+ }
+ return true;
+ }
+ }
+ }
+ }
+ for(Cit it(v->out.begin());it!=v->out.end();++it) {
+ Constraint *c=*it;
+ if(canFollowRight(c,u)) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" right split path: "<<*c<<endl;
+#endif
+ if(c->right==r) {
+ if(!c->equality) m=c;
+ return true;
+ } else {
+ if(split_path(r,c->right,v,m)) {
+ if(!c->equality && (!m||c->lm<m->lm))
+ m=c;
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+/*
+Block::Pair Block::compute_dfdv_between(
+ Variable* r, Variable* const v, Variable* const u,
+ const Direction dir = NONE, bool changedDirection = false) {
+ double dfdv=v->weight*(v->position() - v->desiredPosition);
+ Constraint *m=nullptr;
+ for(Cit it(v->in.begin());it!=v->in.end();++it) {
+ Constraint *c=*it;
+ if(canFollowLeft(c,u)) {
+ if(dir==RIGHT) {
+ changedDirection = true;
+ }
+ if(c->left==r) {
+ r=nullptr;
+ if(!c->equality) m=c;
+ }
+ Pair p=compute_dfdv_between(r,c->left,v,
+ LEFT,changedDirection);
+ dfdv -= c->lm = -p.first;
+ if(r && p.second)
+ m = p.second;
+ }
+ }
+ for(Cit it(v->out.begin());it!=v->out.end();++it) {
+ Constraint *c=*it;
+ if(canFollowRight(c,u)) {
+ if(dir==LEFT) {
+ changedDirection = true;
+ }
+ if(c->right==r) {
+ r=nullptr;
+ if(!c->equality) m=c;
+ }
+ Pair p=compute_dfdv_between(r,c->right,v,
+ RIGHT,changedDirection);
+ dfdv += c->lm = p.first;
+ if(r && p.second)
+ m = changedDirection && !c->equality && c->lm < p.second->lm
+ ? c
+ : p.second;
+ }
+ }
+ return Pair(dfdv,m);
+}
+*/
+
+// resets LMs for all active constraints to 0 by
+// traversing active constraint tree starting from v,
+// not back tracking over u
+void Block::reset_active_lm(Variable* const v, Variable* const u) {
+ for(Cit it=v->out.begin();it!=v->out.end();++it) {
+ Constraint *c=*it;
+ if(canFollowRight(c,u)) {
+ c->lm=0;
+ reset_active_lm(c->right,v);
+ }
+ }
+ for(Cit it=v->in.begin();it!=v->in.end();++it) {
+ Constraint *c=*it;
+ if(canFollowLeft(c,u)) {
+ c->lm=0;
+ reset_active_lm(c->left,v);
+ }
+ }
+}
+void Block::list_active(Variable* const v, Variable* const u) {
+ for(Cit it=v->out.begin();it!=v->out.end();++it) {
+ Constraint *c=*it;
+ if(canFollowRight(c,u)) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" "<<*c<<endl;
+#endif
+ list_active(c->right,v);
+ }
+ }
+ for(Cit it=v->in.begin();it!=v->in.end();++it) {
+ Constraint *c=*it;
+ if(canFollowLeft(c,u)) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" "<<*c<<endl;
+#endif
+ list_active(c->left,v);
+ }
+ }
+}
+/*
+ * finds the constraint with the minimum lagrange multiplier, that is, the constraint
+ * that most wants to split
+ */
+Constraint *Block::findMinLM() {
+ Constraint *min_lm=nullptr;
+ reset_active_lm(vars->front(),nullptr);
+ compute_dfdv(vars->front(),nullptr,min_lm);
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" langrangians: "<<endl;
+ list_active(vars->front(),nullptr);
+#endif
+ return min_lm;
+}
+Constraint *Block::findMinLMBetween(Variable* const lv, Variable* const rv) {
+ reset_active_lm(vars->front(),nullptr);
+ compute_dfdv(vars->front(),nullptr);
+ Constraint *min_lm=nullptr;
+ split_path(rv,lv,nullptr,min_lm);
+#if 0
+ if(min_lm==nullptr) {
+ split_path(rv,lv,nullptr,min_lm,true);
+ }
+#else
+ if(min_lm==nullptr) {
+#ifdef LIBVPSC_DEBUG
+ fprintf(stderr,"Couldn't find split point!\n");
+#endif
+ UnsatisfiableException e;
+ getActivePathBetween(e.path,lv,rv,nullptr);
+ throw e;
+ }
+ COLA_ASSERT(min_lm!=nullptr);
+#endif
+ return min_lm;
+}
+
+// populates block b by traversing the active constraint tree adding variables as they're
+// visited. Starts from variable v and does not backtrack over variable u.
+void Block::populateSplitBlock(Block *b, Variable* v, Variable const* u) {
+ b->addVariable(v);
+ for (Cit c=v->in.begin();c!=v->in.end();++c) {
+ if (canFollowLeft(*c,u))
+ populateSplitBlock(b, (*c)->left, v);
+ }
+ for (Cit c=v->out.begin();c!=v->out.end();++c) {
+ if (canFollowRight(*c,u))
+ populateSplitBlock(b, (*c)->right, v);
+ }
+}
+/*
+ * Returns the active path between variables u and v... not back tracking over w
+ */
+bool Block::getActivePathBetween(Constraints& path, Variable const* u,
+ Variable const* v, Variable const *w) const {
+ if(u==v) return true;
+ for (Cit_const c=u->in.begin();c!=u->in.end();++c) {
+ if (canFollowLeft(*c,w)) {
+ if(getActivePathBetween(path, (*c)->left, v, u)) {
+ path.push_back(*c);
+ return true;
+ }
+ }
+ }
+ for (Cit_const c=u->out.begin();c!=u->out.end();++c) {
+ if (canFollowRight(*c,w)) {
+ if(getActivePathBetween(path, (*c)->right, v, u)) {
+ path.push_back(*c);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+// Search active constraint tree from u to see if there is a directed path to v.
+// Returns true if path is found with all constraints in path having their visited flag
+// set true.
+bool Block::isActiveDirectedPathBetween(Variable const* u, Variable const* v) const {
+ if(u==v) return true;
+ for (Cit_const c=u->out.begin();c!=u->out.end();++c) {
+ if(canFollowRight(*c,nullptr)) {
+ if(isActiveDirectedPathBetween((*c)->right,v)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+bool Block::getActiveDirectedPathBetween(
+ Constraints& path, Variable const* u, Variable const* v) const {
+ if(u==v) return true;
+ for (Cit_const c=u->out.begin();c!=u->out.end();++c) {
+ if(canFollowRight(*c,nullptr)) {
+ if(getActiveDirectedPathBetween(path,(*c)->right,v)) {
+ path.push_back(*c);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+/*
+ * Block needs to be split because of a violated constraint between vl and vr.
+ * We need to search the active constraint tree between l and r and find the constraint
+ * with min lagrangrian multiplier and split at that point.
+ * Returns the split constraint
+ */
+Constraint* Block::splitBetween(Variable* const vl, Variable* const vr,
+ Block* &lb, Block* &rb) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" need to split between: "<<*vl<<" and "<<*vr<<endl;
+#endif
+ Constraint *c=findMinLMBetween(vl, vr);
+#ifdef LIBVPSC_LOGGING
+ f<<" going to split on: "<<*c<<endl;
+#endif
+ if(c!=nullptr) {
+ split(lb,rb,c);
+ deleted = true;
+ }
+ return c;
+}
+
+/*
+ * Creates two new blocks, l and r, and splits this block across constraint c,
+ * placing the left subtree of constraints (and associated variables) into l
+ * and the right into r.
+ */
+void Block::split(Block* &l, Block* &r, Constraint* c) {
+ c->active=false;
+ l=new Block(blocks);
+ populateSplitBlock(l,c->left,c->right);
+ //COLA_ASSERT(l->weight>0);
+ r=new Block(blocks);
+ populateSplitBlock(r,c->right,c->left);
+ //COLA_ASSERT(r->weight>0);
+}
+
+/*
+ * Computes the cost (squared euclidean distance from desired positions) of the
+ * current positions for variables in this block
+ */
+double Block::cost() {
+ double c = 0;
+ for (Vit v=vars->begin();v!=vars->end();++v) {
+ double diff = (*v)->position() - (*v)->desiredPosition;
+ c += (*v)->weight * diff * diff;
+ }
+ return c;
+}
+std::ostream& operator <<(std::ostream &os, const Block& b)
+{
+ os<<"Block(posn="<<b.posn<<"):";
+ for(Block::Vit v=b.vars->begin();v!=b.vars->end();++v) {
+ os<<" "<<**v;
+ }
+ if(b.deleted) {
+ os<<" Deleted!";
+ }
+ return os;
+}
+
+}
+
diff --git a/src/3rdparty/adaptagrams/libvpsc/block.h b/src/3rdparty/adaptagrams/libvpsc/block.h
new file mode 100644
index 0000000..448ead0
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/block.h
@@ -0,0 +1,113 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2005-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+*/
+
+/*
+ * \brief A block is a group of variables that must be moved together to improve
+ * the goal function without violating already active constraints.
+ * The variables in a block are spanned by a tree of active constraints.
+ */
+
+#ifndef VPSC_BLOCK_H
+#define VPSC_BLOCK_H
+
+#include <iostream>
+#include <vector>
+
+template <class T, class TCompare> class PairingHeap;
+
+namespace vpsc {
+class Variable;
+class Constraint;
+class CompareConstraints;
+class Blocks;
+
+struct PositionStats {
+ PositionStats() : scale(0), AB(0), AD(0), A2(0) {}
+ void addVariable(Variable* const v);
+ double scale;
+ double AB;
+ double AD;
+ double A2;
+};
+
+class Block
+{
+ typedef std::vector<Variable*> Variables;
+ typedef std::vector<Constraint*> Constraints;
+ typedef Variables::iterator Vit;
+ typedef Constraints::iterator Cit;
+ typedef Constraints::const_iterator Cit_const;
+
+ friend std::ostream& operator <<(std::ostream &os,const Block &b);
+public:
+ Variables *vars;
+ double posn;
+ //double weight;
+ //double wposn;
+ PositionStats ps;
+ Block(Blocks *blocks, Variable* const v=nullptr);
+ ~Block(void);
+ Constraint* findMinLM();
+ Constraint* findMinLMBetween(Variable* const lv, Variable* const rv);
+ Constraint* findMinInConstraint();
+ Constraint* findMinOutConstraint();
+ void deleteMinInConstraint();
+ void deleteMinOutConstraint();
+ void updateWeightedPosition();
+ void merge(Block *b, Constraint *c, double dist);
+ Block* merge(Block *b, Constraint *c);
+ void mergeIn(Block *b);
+ void mergeOut(Block *b);
+ void split(Block *&l, Block *&r, Constraint *c);
+ Constraint* splitBetween(Variable* vl, Variable* vr, Block* &lb, Block* &rb);
+ void setUpInConstraints();
+ void setUpOutConstraints();
+ double cost();
+ bool deleted;
+ long timeStamp;
+ PairingHeap<Constraint*,CompareConstraints> *in;
+ PairingHeap<Constraint*,CompareConstraints> *out;
+ bool getActivePathBetween(Constraints& path, Variable const* u,
+ Variable const* v, Variable const *w) const;
+ bool isActiveDirectedPathBetween(
+ Variable const* u, Variable const* v) const;
+ bool getActiveDirectedPathBetween(Constraints& path, Variable const * u, Variable const * v) const;
+private:
+ typedef enum {NONE, LEFT, RIGHT} Direction;
+ typedef std::pair<double, Constraint*> Pair;
+ void reset_active_lm(Variable* const v, Variable* const u);
+ void list_active(Variable* const v, Variable* const u);
+ double compute_dfdv(Variable* const v, Variable* const u);
+ double compute_dfdv(Variable* const v, Variable* const u, Constraint *&min_lm);
+ bool split_path(Variable*, Variable* const, Variable* const,
+ Constraint* &min_lm, bool desperation);
+ bool canFollowLeft(Constraint const* c, Variable const* last) const;
+ bool canFollowRight(Constraint const* c, Variable const* last) const;
+ void populateSplitBlock(Block *b, Variable* v, Variable const* u);
+ void addVariable(Variable* v);
+ void setUpConstraintHeap(PairingHeap<Constraint*,CompareConstraints>* &h,bool in);
+
+ // Parent container, that holds the blockTimeCtr.
+ Blocks *blocks;
+};
+}
+
+#endif // VPSC_BLOCK_H
diff --git a/src/3rdparty/adaptagrams/libvpsc/blocks.cpp b/src/3rdparty/adaptagrams/libvpsc/blocks.cpp
new file mode 100644
index 0000000..7481084
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/blocks.cpp
@@ -0,0 +1,249 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2005-2012 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+ * Michael Wybrow
+*/
+
+/*
+ * @brief A block structure defined over the variables
+ *
+ * A block structure defined over the variables such that each block contains
+ * 1 or more variables, with the invariant that all constraints inside a block
+ * are satisfied by keeping the variables fixed relative to one another
+ */
+
+#include "libvpsc/blocks.h"
+#include "libvpsc/block.h"
+#include "libvpsc/constraint.h"
+#include "libvpsc/variable.h"
+#include "libvpsc/assertions.h"
+
+#ifdef LIBVPSC_LOGGING
+#include <fstream>
+using std::ios;
+using std::ofstream;
+using std::endl;
+#endif
+using std::vector;
+using std::iterator;
+using std::list;
+using std::copy;
+#define __NOTNAN(p) (p)==(p)
+
+namespace vpsc {
+
+
+Blocks::Blocks(vector<Variable*> const &vs) : vs(vs),nvs(vs.size()) {
+ blockTimeCtr=0;
+ m_blocks.resize(nvs);
+ for(size_t i=0;i<nvs;i++) {
+ m_blocks[i] = new Block(this, vs[i]);
+ }
+}
+Blocks::~Blocks(void)
+{
+ blockTimeCtr=0;
+ size_t length = m_blocks.size();
+ for (size_t i = 0; i < length; ++i)
+ {
+ delete m_blocks[i];
+ }
+ m_blocks.clear();
+}
+
+/*
+ * returns a list of variables with total ordering determined by the constraint
+ * DAG
+ */
+list<Variable*> *Blocks::totalOrder() {
+ list<Variable*> *order = new list<Variable*>;
+ for(size_t i=0;i<nvs;i++) {
+ vs[i]->visited=false;
+ }
+ for(size_t i=0;i<nvs;i++) {
+ if(vs[i]->in.size()==0) {
+ dfsVisit(vs[i],order);
+ }
+ }
+ return order;
+}
+// Recursive depth first search giving total order by pushing nodes in the DAG
+// onto the front of the list when we finish searching them
+void Blocks::dfsVisit(Variable *v, list<Variable*> *order) {
+ v->visited=true;
+ vector<Constraint*>::iterator it=v->out.begin();
+ for(;it!=v->out.end();++it) {
+ Constraint *c=*it;
+ if(!c->right->visited) {
+ dfsVisit(c->right, order);
+ }
+ }
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<" order="<<*v<<endl;
+#endif
+ order->push_front(v);
+}
+/*
+ * Processes incoming constraints, most violated to least, merging with the
+ * neighbouring (left) block until no more violated constraints are found
+ */
+void Blocks::mergeLeft(Block *r) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<"mergeLeft called on "<<*r<<endl;
+#endif
+ r->timeStamp=++blockTimeCtr;
+ r->setUpInConstraints();
+ Constraint *c=r->findMinInConstraint();
+ while (c != nullptr && c->slack()<0) {
+#ifdef LIBVPSC_LOGGING
+ f<<"mergeLeft on constraint: "<<*c<<endl;
+#endif
+ r->deleteMinInConstraint();
+ Block *l = c->left->block;
+ if (l->in==nullptr) l->setUpInConstraints();
+ double dist = c->right->offset - c->left->offset - c->gap;
+ if (r->vars->size() < l->vars->size()) {
+ dist=-dist;
+ std::swap(l, r);
+ }
+ blockTimeCtr++;
+ r->merge(l, c, dist);
+ r->mergeIn(l);
+ r->timeStamp=blockTimeCtr;
+ removeBlock(l);
+ c=r->findMinInConstraint();
+ }
+#ifdef LIBVPSC_LOGGING
+ f<<"merged "<<*r<<endl;
+#endif
+}
+/*
+ * Symmetrical to mergeLeft
+ */
+void Blocks::mergeRight(Block *l) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<"mergeRight called on "<<*l<<endl;
+#endif
+ l->setUpOutConstraints();
+ Constraint *c = l->findMinOutConstraint();
+ while (c != nullptr && c->slack()<0) {
+#ifdef LIBVPSC_LOGGING
+ f<<"mergeRight on constraint: "<<*c<<endl;
+#endif
+ l->deleteMinOutConstraint();
+ Block *r = c->right->block;
+ r->setUpOutConstraints();
+ double dist = c->left->offset + c->gap - c->right->offset;
+ if (l->vars->size() > r->vars->size()) {
+ dist=-dist;
+ std::swap(l, r);
+ }
+ l->merge(r, c, dist);
+ l->mergeOut(r);
+ removeBlock(r);
+ c=l->findMinOutConstraint();
+ }
+#ifdef LIBVPSC_LOGGING
+ f<<"merged "<<*l<<endl;
+#endif
+}
+void Blocks::removeBlock(Block *doomed) {
+ doomed->deleted=true;
+ //erase(doomed);
+}
+
+// Clears up deleted blocks from the blocks list.
+void Blocks::cleanup(void)
+{
+ // We handle removal of items in-place by doing a single linear pass over
+ // the vector. We use two indexes, j to refer to elements we've checked
+ // from the original list and i to refer to the current position we are
+ // writing in the updated list.
+ size_t i = 0;
+
+ // For all items in the current blocks list...
+ size_t length = m_blocks.size();
+ for (size_t j = 0; j < length; )
+ {
+ if (m_blocks[j]->deleted)
+ {
+ // The element is deleted, so free it and increment j.
+ delete m_blocks[j];
+ ++j;
+ }
+ else
+ {
+ // The current element is still valid.
+ if (j > i)
+ {
+ // If we've not looking at same element, then copy from j to i.
+ m_blocks[i] = m_blocks[j];
+ }
+ // Increment both indexes.
+ ++i;
+ ++j;
+ }
+ }
+ m_blocks.resize(i);
+}
+/*
+ * Splits block b across constraint c into two new blocks, l and r (c's left
+ * and right sides respectively)
+ */
+void Blocks::split(Block *b, Block *&l, Block *&r, Constraint *c) {
+ b->split(l,r,c);
+ m_blocks.push_back(l);
+ m_blocks.push_back(r);
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<"Split left: "<<*l<<endl;
+ f<<"Split right: "<<*r<<endl;
+#endif
+ r->posn = b->posn;
+ //COLA_ASSERT(r->weight!=0);
+ //r->wposn = r->posn * r->weight;
+ mergeLeft(l);
+ // r may have been merged!
+ r = c->right->block;
+ r->updateWeightedPosition();
+ //r->posn = r->wposn / r->weight;
+ mergeRight(r);
+ removeBlock(b);
+
+ COLA_ASSERT(__NOTNAN(l->posn));
+ COLA_ASSERT(__NOTNAN(r->posn));
+}
+/*
+ * returns the cost total squared distance of variables from their desired
+ * positions
+ */
+double Blocks::cost() {
+ double c = 0;
+ size_t length = m_blocks.size();
+ for (size_t i = 0; i < length; ++i)
+ {
+ c += m_blocks[i]->cost();
+ }
+ return c;
+}
+
+}
diff --git a/src/3rdparty/adaptagrams/libvpsc/blocks.h b/src/3rdparty/adaptagrams/libvpsc/blocks.h
new file mode 100644
index 0000000..a3613db
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/blocks.h
@@ -0,0 +1,96 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2005-2012 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+ * Michael Wybrow
+*/
+
+/*
+ * @brief A block structure defined over the variables
+ *
+ * A block structure defined over the variables such that each block contains
+ * 1 or more variables, with the invariant that all constraints inside a block
+ * are satisfied by keeping the variables fixed relative to one another
+ *
+ */
+
+#ifndef VPSC_BLOCKS_H
+#define VPSC_BLOCKS_H
+
+#ifdef LIBVPSC_LOGGING
+#define LOGFILE "libvpsc.log"
+#endif
+
+#include <list>
+#include <vector>
+
+// size_t is strangely not defined on some older MinGW GCC versions.
+#include <cstddef>
+
+namespace vpsc {
+class Block;
+class Variable;
+class Constraint;
+/*
+ * A block structure defined over the variables such that each block contains
+ * 1 or more variables, with the invariant that all constraints inside a block
+ * are satisfied by keeping the variables fixed relative to one another
+ */
+class Blocks
+{
+public:
+ Blocks(std::vector<Variable*> const &vs);
+ ~Blocks(void);
+ void mergeLeft(Block *r);
+ void mergeRight(Block *l);
+ void split(Block *b, Block *&l, Block *&r, Constraint *c);
+ std::list<Variable*> *totalOrder();
+ void cleanup();
+ double cost();
+
+ size_t size() const;
+ Block *at(size_t index) const;
+ void insert(Block *block);
+
+ long blockTimeCtr;
+private:
+ void dfsVisit(Variable *v, std::list<Variable*> *order);
+ void removeBlock(Block *doomed);
+
+ std::vector<Block*> m_blocks;
+ std::vector<Variable*> const &vs;
+ size_t nvs;
+};
+
+inline size_t Blocks::size() const
+{
+ return m_blocks.size();
+}
+
+inline Block *Blocks::at(size_t index) const
+{
+ return m_blocks[index];
+}
+
+inline void Blocks::insert(Block *block)
+{
+ m_blocks.push_back(block);
+}
+
+}
+#endif // VPSC_BLOCKS_H
diff --git a/src/3rdparty/adaptagrams/libvpsc/cbuffer.cpp b/src/3rdparty/adaptagrams/libvpsc/cbuffer.cpp
new file mode 100644
index 0000000..9428922
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/cbuffer.cpp
@@ -0,0 +1,95 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2005-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+ *
+*/
+
+#include <cfloat>
+
+#include "libvpsc/cbuffer.h"
+#include "libvpsc/constraint.h"
+#include "libvpsc/assertions.h"
+
+namespace vpsc {
+ static const double ZERO_UPPERBOUND=-0.0000001;
+ void CBuffer::load() {
+ size=0;
+ double buffMaxSlack=-DBL_MAX;
+ unsigned buffMaxSlackPos=0;
+ for(Constraints::iterator i=master_list.begin();
+ i!=master_list.end();++i) {
+ Constraint *c=*i;
+ double slack = c->slack();
+ if(c->equality||slack<ZERO_UPPERBOUND) {
+ if(size<maxsize) {
+ // make sure buffer is full
+ buffer[size]=c;
+ if(slack>buffMaxSlack) {
+ buffMaxSlack=slack;
+ buffMaxSlackPos=size;
+ }
+ size++;
+ } else {
+ // if c is more violated than the least violated
+ // constraint in the buffer then replace it
+ buffer[buffMaxSlackPos]=c;
+ // need to search the buffer for the new least
+ // violated constraint
+ buffMaxSlack=-DBL_MAX;
+ for(unsigned i=0;i<size;i++) {
+ c=buffer[i];
+ if(!c->equality&&buffMaxSlack < c->slack()) {
+ buffMaxSlack = slack;
+ buffMaxSlackPos = i;
+ }
+ }
+ }
+ }
+ }
+ }
+ Constraint* CBuffer::mostViolated() {
+ Constraint* v=nullptr;
+ while(true) {
+ if(size==0) {
+ load();
+ if(size==0) break;
+ }
+ double minSlack=DBL_MAX;
+ int i,deletePos=-1;
+ for(i=0;i<(int)size;i++) {
+ Constraint *c=buffer[i];
+ double slack = c->slack();
+ if(!(c->equality||slack < ZERO_UPPERBOUND)) {
+ COLA_ASSERT(size>0);
+ buffer[i--]=buffer[--size];
+ } else if(c->equality||slack < minSlack) {
+ v=c;
+ deletePos=i;
+ minSlack=slack;
+ }
+ }
+ if(deletePos>=0) {
+ COLA_ASSERT(size>0);
+ buffer[deletePos]=buffer[--size];
+ break;
+ }
+ }
+ return v;
+ }
+}
diff --git a/src/3rdparty/adaptagrams/libvpsc/cbuffer.h b/src/3rdparty/adaptagrams/libvpsc/cbuffer.h
new file mode 100644
index 0000000..9cf302c
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/cbuffer.h
@@ -0,0 +1,49 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2005-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+ *
+ */
+#ifndef VPSC_CBUFFER_H
+#define VPSC_CBUFFER_H
+
+#include <vector>
+
+namespace vpsc {
+ class Constraint;
+ class CBuffer {
+ public:
+ CBuffer(std::vector<Constraint*>& l,
+ const unsigned maxsize=5)
+ : master_list(l), maxsize(maxsize), size(0) {
+ buffer.resize(maxsize);
+ load();
+ }
+ void reset() { size=0; }
+ void load();
+ Constraint* mostViolated();
+ private:
+ std::vector<Constraint*>& master_list;
+ std::vector<Constraint*> buffer;
+ const unsigned maxsize;
+ unsigned size;
+ };
+}
+
+#endif // VPSC_CBUFFER_H
+
diff --git a/src/3rdparty/adaptagrams/libvpsc/constraint.cpp b/src/3rdparty/adaptagrams/libvpsc/constraint.cpp
new file mode 100644
index 0000000..96581c7
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/constraint.cpp
@@ -0,0 +1,218 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2005-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+*/
+
+
+#include <map>
+#include <list>
+#include <sstream>
+#include <cassert>
+#include <cfloat>
+#include <cmath>
+
+
+#include "libvpsc/constraint.h"
+#include "libvpsc/variable.h"
+
+namespace vpsc {
+Constraint::Constraint(Variable *left, Variable *right, double gap, bool equality)
+: left(left),
+ right(right),
+ gap(gap),
+ timeStamp(0),
+ active(false),
+ equality(equality),
+ unsatisfiable(false),
+ needsScaling(true),
+ creator(nullptr)
+{
+ // In hindsight I think it's probably better to build the constraint DAG
+ // (by creating variable in/out lists) when needed, rather than in advance
+ //left->out.push_back(this);
+ //right->in.push_back(this);
+}
+Constraint::~Constraint() {
+ // see constructor: the following is just way too slow.
+ // Better to create a
+ // new DAG on demand than maintain the lists dynamically.
+ //Constraints::iterator i;
+ //for(i=left->out.begin(); i!=left->out.end(); i++) {
+ //if(*i==this) break;
+ //}
+ //left->out.erase(i);
+ //for(i=right->in.begin(); i!=right->in.end(); i++) {
+ //if(*i==this) break;
+ //}
+ //right->in.erase(i);
+}
+std::ostream& operator <<(std::ostream &os, const Constraint &c)
+{
+ const char *type = c.equality ? "=" : "<=";
+ std::ostringstream lscale, rscale;
+ if (c.left->scale != 1)
+ {
+ lscale << c.left->scale << "*";
+ }
+ if (c.right->scale != 1)
+ {
+ rscale << c.right->scale << "*";
+ }
+ os << lscale.str() << *c.left << "+" << c.gap << type <<
+ rscale.str() << *c.right;
+ if (c.left->block && c.right->block)
+ {
+ os << "(" << c.slack() << ")" << (c.active ? "-active" : "") <<
+ "(lm=" << c.lm << ")";
+ }
+ else
+ {
+ os << "(vars have no position)";
+ }
+ return os;
+}
+#include "libvpsc/block.h"
+bool CompareConstraints::operator() (
+ Constraint *const &l, Constraint *const &r
+) const {
+ double const sl =
+ l->left->block->timeStamp > l->timeStamp
+ ||l->left->block==l->right->block
+ ?-DBL_MAX:l->slack();
+ double const sr =
+ r->left->block->timeStamp > r->timeStamp
+ ||r->left->block==r->right->block
+ ?-DBL_MAX:r->slack();
+ if(sl==sr) {
+ // arbitrary choice based on id
+ if(l->left->id==r->left->id) {
+ if(l->right->id<r->right->id) return true;
+ return false;
+ }
+ if(l->left->id<r->left->id) return true;
+ return false;
+ }
+ return sl < sr;
+}
+
+
+typedef std::list<std::map<Variable *, double> > VarOffsetMapList;
+
+class EqualityConstraintSet
+{
+ public:
+ EqualityConstraintSet(Variables vs)
+ {
+ for (size_t i = 0; i < vs.size(); ++i)
+ {
+ std::map<Variable *, double> varSet;
+ varSet[vs[i]] = 0;
+ variableGroups.push_back(varSet);
+ }
+ }
+ bool isRedundant(Variable *lhs, Variable *rhs, double sep)
+ {
+ VarOffsetMapList::iterator lhsSet = setForVar(lhs);
+ VarOffsetMapList::iterator rhsSet = setForVar(rhs);
+ COLA_ASSERT(lhsSet != variableGroups.end());
+ COLA_ASSERT(rhsSet != variableGroups.end());
+ if (lhsSet == rhsSet)
+ {
+ // Check if this is a redundant constraint.
+ if (fabs(((*lhsSet)[lhs] + sep) - (*rhsSet)[rhs]) < 0.0001)
+ {
+ // If so, return true.
+ return true;
+ }
+ }
+ return false;
+ }
+ void mergeSets(Variable *lhs, Variable *rhs, double sep)
+ {
+ VarOffsetMapList::iterator lhsSet = setForVar(lhs);
+ VarOffsetMapList::iterator rhsSet = setForVar(rhs);
+ if (lhsSet == rhsSet)
+ {
+ return;
+ }
+
+ double rhsOldOffset = (*rhsSet)[rhs];
+ double rhsNewOffset = (*lhsSet)[lhs] + sep;
+ double offset = rhsNewOffset - rhsOldOffset;
+
+ // Update offsets
+ for (std::map<Variable *, double>::iterator it = rhsSet->begin();
+ it != rhsSet->end(); ++it)
+ {
+ it->second += offset;
+ }
+
+ // Merge rhsSet into lhsSet
+ lhsSet->insert(rhsSet->begin(), rhsSet->end());
+ variableGroups.erase(rhsSet);
+ }
+
+ private:
+ VarOffsetMapList::iterator setForVar(Variable *var)
+ {
+ for (VarOffsetMapList::iterator it = variableGroups.begin();
+ it != variableGroups.end(); ++it)
+ {
+ if (it->find(var) != it->end())
+ {
+ return it;
+ }
+ }
+ return variableGroups.end();
+ }
+
+ VarOffsetMapList variableGroups;
+};
+
+Constraints constraintsRemovingRedundantEqualities(const Variables& vars,
+ const Constraints& constraints)
+{
+ EqualityConstraintSet equalitySets(vars);
+ Constraints cs = Constraints(constraints.size());
+ int csSize = 0;
+
+ for (unsigned i = 0; i < constraints.size(); ++i)
+ {
+ Constraint *c = constraints[i];
+ if (c->equality)
+ {
+ if (!equalitySets.isRedundant(c->left, c->right, c->gap))
+ {
+ // Only add non-redundant equalities
+ equalitySets.mergeSets(c->left, c->right, c->gap);
+ cs[csSize++] = c;
+ }
+ }
+ else
+ {
+ // Add all non-equalities
+ cs[csSize++] = c;
+ }
+ }
+ cs.resize(csSize);
+ return cs;
+}
+
+
+}
diff --git a/src/3rdparty/adaptagrams/libvpsc/constraint.h b/src/3rdparty/adaptagrams/libvpsc/constraint.h
new file mode 100644
index 0000000..271a2cf
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/constraint.h
@@ -0,0 +1,139 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2005-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+*/
+
+
+#ifndef VPSC_CONSTRAINT_H
+#define VPSC_CONSTRAINT_H
+
+// cmath needs ::strcpy_s under MinGW so include cstring.
+#include <cstring>
+
+#include <cfloat>
+#include <iostream>
+#include <vector>
+#include <sstream>
+
+#include "libvpsc/variable.h"
+
+namespace vpsc {
+
+class Variable;
+typedef std::vector<Variable *> Variables;
+
+//! @brief A constraint determines a minimum or exact spacing required between
+//! two Variable objects.
+//!
+class Constraint
+{
+ friend std::ostream& operator <<(std::ostream &os,const Constraint &c);
+public:
+ //! @brief Constructs a minimum or exact spacing constraint between two
+ //! Variable objects.
+ //!
+ //! (left + gap < right) or (left + gap == right)
+ //!
+ //! @param[in] left The left Variable.
+ //! @param[in] right The right Variable.
+ //! @param[in] gap The minimum or exact distance to separate the
+ //! variables by.
+ //! @param[in] equality Whether the separation is an exact distance or
+ //! not. The default is false.
+ Constraint(Variable *left, Variable *right, double gap,
+ bool equality = false);
+ ~Constraint();
+
+ /**
+ * @brief Returns a textual description of the constraint.
+ *
+ * @return A string describing the constraint.
+ */
+ std::string toString(void) const
+ {
+ std::stringstream stream;
+ stream << "Constraint: var(" << left->id << ") ";
+ if (gap < 0)
+ {
+ stream << "- " << -gap << " ";
+ }
+ else
+ {
+ stream << "+ " << gap << " ";
+ }
+ stream << ((equality) ? "==" : "<=");
+ stream << " var(" << right->id << ") ";
+ return stream.str();
+ }
+
+ inline double slack(void) const
+ {
+ if (unsatisfiable)
+ {
+ return DBL_MAX;
+ }
+ if (needsScaling)
+ {
+ return right->scale * right->position() - gap -
+ left->scale * left->position();
+ }
+ COLA_ASSERT(left->scale == 1);
+ COLA_ASSERT(right->scale == 1);
+ return right->unscaledPosition() - gap - left->unscaledPosition();
+ }
+
+ //! @brief The left Variable.
+ Variable *left;
+ //! @brief The right Variable.
+ Variable *right;
+ //! @brief The minimum or exact distance to separate the variables by.
+ double gap;
+ double lm;
+ long timeStamp;
+ bool active;
+ //! @brief Whether the separation is an exact distance or not.
+ const bool equality;
+ //! @brief Denote whether this constraint was unsatisifable (once the VPSC
+ //! instance has been solved or satisfied).
+ bool unsatisfiable;
+ bool needsScaling;
+ void *creator;
+};
+
+class CompareConstraints {
+public:
+ bool operator() (Constraint *const &l, Constraint *const &r) const;
+};
+
+//! @brief A vector of pointers to Constraint objects.
+typedef std::vector<Constraint*> Constraints;
+
+/** @brief Given a set of variables and constraints, returns a modified set
+ * of constraints with all redundant equality constraints removed.
+ *
+ * VPSC doesn't work well with redundant equality constraints, usually showing
+ * them as unsatisfiable. This function looks for cycles of equality
+ * constraints and removes the redundant ones.
+ */
+extern Constraints constraintsRemovingRedundantEqualities(
+ const Variables& vars, const Constraints& constraints);
+
+}
+
+#endif // VPSC_CONSTRAINT_H
diff --git a/src/3rdparty/adaptagrams/libvpsc/doc/description.doc b/src/3rdparty/adaptagrams/libvpsc/doc/description.doc
new file mode 100644
index 0000000..ee66b35
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/doc/description.doc
@@ -0,0 +1,36 @@
+/*!
+
+\if LIBVPSC_DOC
+@mainpage libvpsc: Variable Placement with Separation Constraints solver
+\endif
+\if ADAPTAGRAMS_DOC
+@page libvpsc libvpsc &mdash; Overview
+\endif
+
+
+libvpsc is a cross-platform C++ library for solving for the Variable Placement with Separation Constraints problem. This is a quadratic programming problem in which the squared differences between a placement vector and some ideal placement are minimised subject to a set of separation constraints. This is very useful in a number of layout problems.
+
+libvpsc is part of the
+<a href="http://www.adaptagrams.org/">Adaptagrams project</a>.
+There are no official releases yet, though the code is stable and
+available from the Adaptagrams
+<a href="https://github.com/mjwybrow/adaptagrams">GitHub
+repository</a>.
+
+The API is documented using Doxygen. The documentation you are currently
+reading can be obtained by running doxygen in the cola directory.
+
+libcola is written and maintained by
+<a href="http://users.monash.edu/~mwybrow/">Michael Wybrow</a> and
+<a href="http://ialab.it.monash.edu/~dwyer/">Tim Dwyer</a>,
+members of <a href="http://ialab.it.monash.edu/">Immersive Analytics Lab</a> at Monash University, Australia.
+
+The algorithms used for VPSC are described in the following papers. If you use libcola, please cite the relevant paper.
+- Tim Dwyer, Kim Marriott, and Peter J. Stuckey. Fast node overlap removal.\n
+ In Proceedings 13th International Symposium on Graph Drawing (GD '05),\n
+ volume 3843 of LNCS, pages 153-164. Springer, 2006.
+
+
+*/
+
+
diff --git a/src/3rdparty/adaptagrams/libvpsc/exceptions.h b/src/3rdparty/adaptagrams/libvpsc/exceptions.h
new file mode 100644
index 0000000..5f66afe
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/exceptions.h
@@ -0,0 +1,36 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2005-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+*/
+
+#ifndef VPSC_EXCEPTIONS_H
+#define VPSC_EXCEPTIONS_H
+
+#include <vector>
+namespace vpsc {
+class Constraint;
+struct UnsatisfiableException {
+ std::vector<Constraint*> path;
+};
+struct UnsatisfiedConstraint {
+ UnsatisfiedConstraint(Constraint& c):c(c) {}
+ Constraint& c;
+};
+} // namespace vpsc
+
+#endif // VPSC_EXCEPTIONS_H
diff --git a/src/3rdparty/adaptagrams/libvpsc/libvpsc.pc.in b/src/3rdparty/adaptagrams/libvpsc/libvpsc.pc.in
new file mode 100644
index 0000000..9b6ff52
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/libvpsc.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libvpsc
+Description: A solver for the Variable Placement with Separation Constraints problem.
+URL: http://www.adaptagrams.org/
+Version: @VERSION@
+Requires:
+Libs: -L${libdir} -lvpsc
+Cflags: -I${includedir}/libvpsc \ No newline at end of file
diff --git a/src/3rdparty/adaptagrams/libvpsc/linesegment.h b/src/3rdparty/adaptagrams/libvpsc/linesegment.h
new file mode 100644
index 0000000..caca3a2
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/linesegment.h
@@ -0,0 +1,138 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2005-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+*/
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// 2D Line Segment Intersection example
+// Implementation of the theory provided by Paul Bourke
+//
+// Written by Damian Coventry
+// Tuesday, 9 January 2007
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef VPSC_LINESEGMENT_H
+#define VPSC_LINESEGMENT_H
+
+namespace linesegment {
+class Vector
+{
+public:
+ double x_, y_;
+
+ Vector(double f = 0.0f)
+ : x_(f), y_(f) {}
+
+ Vector(double x, double y)
+ : x_(x), y_(y) {}
+};
+
+class LineSegment
+{
+public:
+ Vector begin_;
+ Vector end_;
+
+ LineSegment(const Vector& begin, const Vector& end)
+ : begin_(begin), end_(end) {}
+
+ enum IntersectResult { PARALLEL, COINCIDENT, NOT_INTERSECTING, INTERSECTING };
+
+ IntersectResult Intersect(const LineSegment& other_line, Vector& intersection)
+ {
+ double dx1=end_.x_ - begin_.x_;
+ double dy1=end_.y_ - begin_.y_;
+ double dx2=other_line.end_.x_ - other_line.begin_.x_;
+ double dy2=other_line.end_.y_ - other_line.begin_.y_;
+
+ double denom = dy2 * dx1 - dy1 * dx2;
+
+ double nume_a = dx2 * (begin_.y_ - other_line.begin_.y_) -
+ dy2 * (begin_.x_ - other_line.begin_.x_);
+
+ double nume_b = dx1 * (begin_.y_ - other_line.begin_.y_) -
+ dy1 * (begin_.x_ - other_line.begin_.x_);
+
+ if(denom == 0.0f)
+ {
+ if(nume_a == 0.0f && nume_b == 0.0f)
+ {
+ return COINCIDENT;
+ }
+ return PARALLEL;
+ }
+
+ double ua = nume_a / denom;
+ double ub = nume_b / denom;
+
+ if(ua >= 0.0f && ua <= 1.0f && ub >= 0.0f && ub <= 1.0f)
+ {
+ // Get the intersection point.
+ intersection.x_ = begin_.x_ + ua*dx1;
+ intersection.y_ = begin_.y_ + ua*dy1;
+
+ return INTERSECTING;
+ }
+
+ return NOT_INTERSECTING;
+ }
+};
+
+void DoLineSegmentIntersection(const Vector& p0, const Vector& p1, const Vector& p2, const Vector& p3)
+{
+ LineSegment linesegment0(p0, p1);
+ LineSegment linesegment1(p2, p3);
+
+ Vector intersection;
+
+ std::cout << "Line Segment 0: (" << p0.x_ << ", " << p0.y_ << ") to (" << p1.x_ << ", " << p1.y_ << ")\n"
+ << "Line Segment 1: (" << p2.x_ << ", " << p2.y_ << ") to (" << p3.x_ << ", " << p3.y_ << ")\n";
+
+ switch(linesegment0.Intersect(linesegment1, intersection))
+ {
+ case LineSegment::PARALLEL:
+ std::cout << "The lines are parallel\n\n";
+ break;
+ case LineSegment::COINCIDENT:
+ std::cout << "The lines are coincident\n\n";
+ break;
+ case LineSegment::NOT_INTERSECTING:
+ std::cout << "The lines do not intersect\n\n";
+ break;
+ case LineSegment::INTERSECTING:
+ std::cout << "The lines intersect at (" << intersection.x_ << ", " << intersection.y_ << ")\n\n";
+ break;
+ }
+}
+
+int test()
+{
+ DoLineSegmentIntersection(Vector(0.0f, 0.0f), Vector(5.0f, 5.0f), Vector(5.0f, 0.0f), Vector(0.0f, 5.0f));
+ DoLineSegmentIntersection(Vector(1.0f, 3.0f), Vector(9.0f, 3.0f), Vector(0.0f, 1.0f), Vector(2.0f, 1.0f));
+ DoLineSegmentIntersection(Vector(1.0f, 5.0f), Vector(6.0f, 8.0f), Vector(0.5f, 3.0f), Vector(6.0f, 4.0f));
+ DoLineSegmentIntersection(Vector(1.0f, 1.0f), Vector(3.0f, 8.0f), Vector(0.5f, 2.0f), Vector(4.0f, 7.0f));
+ DoLineSegmentIntersection(Vector(1.0f, 2.0f), Vector(3.0f, 6.0f), Vector(2.0f, 4.0f), Vector(4.0f, 8.0f));
+ DoLineSegmentIntersection(Vector(3.5f, 9.0f), Vector(3.5f, 0.5f), Vector(3.0f, 1.0f), Vector(9.0f, 1.0f));
+ DoLineSegmentIntersection(Vector(2.0f, 3.0f), Vector(7.0f, 9.0f), Vector(1.0f, 2.0f), Vector(5.0f, 7.0f));
+ return 0;
+}
+} // namespace linesegment
+
+#endif // VPSC_LINESEGMENT_H
diff --git a/src/3rdparty/adaptagrams/libvpsc/pairing_heap.h b/src/3rdparty/adaptagrams/libvpsc/pairing_heap.h
new file mode 100644
index 0000000..479519a
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/pairing_heap.h
@@ -0,0 +1,394 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2005 Mark Allen Weiss
+ * Copyright (C) 2005-2008 Monash University
+ *
+ * ----------------------------------------------------------------------------
+ * Pairing heap datastructure implementation:
+ * Based on example code in "Data structures and Algorithm Analysis in C++"
+ * by Mark Allen Weiss, used and released under the LGPL by permission
+ * of the author.
+ * No promises about correctness. Use at your own risk!
+ * ----------------------------------------------------------------------------
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Mark Allen Weiss
+ * Tim Dwyer
+*/
+
+#ifndef VPSC_PAIRING_HEAP_H
+#define VPSC_PAIRING_HEAP_H
+
+#include <cstdlib>
+#include <fstream>
+#include <vector>
+#include <list>
+
+#include "libvpsc/assertions.h"
+
+class Underflow { };
+
+// Pairing heap class
+//
+// CONSTRUCTION: with no parameters
+//
+// ******************PUBLIC OPERATIONS*********************
+// PairNode & insert( x ) --> Insert x
+// deleteMin( minItem ) --> Remove (and optionally return) smallest item
+// T findMin( ) --> Return smallest item
+// bool isEmpty( ) --> Return true if empty; else false
+// void makeEmpty( ) --> Remove all items
+// void decreaseKey( PairNode p, newVal )
+// --> Decrease value in node p
+// ******************ERRORS********************************
+// Throws Underflow as warranted
+
+
+template <class T>
+struct PairNode
+{
+ T element;
+ PairNode *leftChild;
+ PairNode *nextSibling;
+ PairNode *prev;
+
+ PairNode( const T & theElement ) :
+ element( theElement ),
+ leftChild(nullptr), nextSibling(nullptr), prev(nullptr)
+ { }
+};
+
+template <class T, class TCompare>
+class PairingHeap;
+
+template <class T,class TCompare>
+std::ostream& operator <<(std::ostream &os, const PairingHeap<T,TCompare> &b);
+
+template <class T, class TCompare = std::less<T> >
+class PairingHeap
+{
+#ifndef SWIG
+ friend std::ostream& operator<< <T,TCompare> (std::ostream &os, const PairingHeap<T,TCompare> &b);
+#endif
+public:
+ PairingHeap() : root(nullptr), counter(0), siblingsTreeArray(5) { }
+ PairingHeap(const PairingHeap & rhs) {
+ // uses operator= to make deep copy
+ *this = rhs;
+ }
+ ~PairingHeap() { makeEmpty(); }
+ const PairingHeap & operator=( const PairingHeap & rhs );
+ bool isEmpty() const { return root == nullptr; }
+ unsigned size() const { return counter; }
+ PairNode<T> *insert( const T & x );
+ const T & findMin( ) const;
+ void deleteMin( );
+ const T extractMin( ) {
+ T v = findMin();
+ deleteMin();
+ return v;
+ }
+ void makeEmpty() {
+ reclaimMemory(root);
+ root = nullptr;
+ counter = 0;
+ }
+ void decreaseKey( PairNode<T> *p, const T & newVal );
+ void merge( PairingHeap<T,TCompare> *rhs );
+protected:
+ // Destructively gets the root for merging into another heap.
+ PairNode<T> * removeRootForMerge(unsigned& size) {
+ PairNode<T> *r=root;
+ root=nullptr;
+ size=counter;
+ counter=0;
+ return r;
+ }
+ TCompare lessThan;
+private:
+ PairNode<T> *root;
+ unsigned counter;
+
+ // Used by PairingHeap::combineSiblings(). We keep this as member
+ // variable to save some vector resize operations during subsequent uses.
+ std::vector<PairNode<T> *> siblingsTreeArray;
+
+ void reclaimMemory( PairNode<T> *t ) const;
+ void compareAndLink( PairNode<T> * & first, PairNode<T> *second ) const;
+ PairNode<T> * combineSiblings( PairNode<T> *firstSibling );
+ PairNode<T> * clone( PairNode<T> * t ) const;
+};
+
+
+/**
+* Insert item x into the priority queue, maintaining heap order.
+* Return a pointer to the node containing the new item.
+*/
+template <class T,class TCompare>
+PairNode<T> *
+PairingHeap<T,TCompare>::insert( const T & x )
+{
+ PairNode<T> *newNode = new PairNode<T>( x );
+
+ if( root == nullptr )
+ root = newNode;
+ else
+ compareAndLink( root, newNode );
+ counter++;
+ return newNode;
+}
+
+/**
+* Find the smallest item in the priority queue.
+* Return the smallest item, or throw Underflow if empty.
+*/
+template <class T,class TCompare>
+const T & PairingHeap<T,TCompare>::findMin( ) const
+{
+ if( isEmpty( ) )
+ throw Underflow( );
+ return root->element;
+}
+/**
+ * Remove the smallest item from the priority queue.
+ * Throws Underflow if empty.
+ */
+template <class T,class TCompare>
+void PairingHeap<T,TCompare>::deleteMin( )
+{
+ if( isEmpty( ) )
+ throw Underflow( );
+
+ PairNode<T> *oldRoot = root;
+
+ if( root->leftChild == nullptr )
+ root = nullptr;
+ else
+ root = combineSiblings( root->leftChild );
+ COLA_ASSERT(counter);
+ counter--;
+ delete oldRoot;
+}
+
+/**
+* Deep copy.
+*/
+template <class T,class TCompare>
+const PairingHeap<T,TCompare> &
+PairingHeap<T,TCompare>::operator=( const PairingHeap<T,TCompare> & rhs )
+{
+ if( this != &rhs )
+ {
+ makeEmpty( );
+ root = clone( rhs.root );
+ counter = rhs.size();
+ }
+
+ return *this;
+}
+
+/**
+* Internal method to make the tree empty.
+* WARNING: This is prone to running out of stack space.
+*/
+template <class T,class TCompare>
+void PairingHeap<T,TCompare>::reclaimMemory( PairNode<T> * t ) const
+{
+ if( t != nullptr )
+ {
+ reclaimMemory( t->leftChild );
+ reclaimMemory( t->nextSibling );
+ delete t;
+ }
+}
+
+/**
+* Change the value of the item stored in the pairing heap.
+* Does nothing if newVal is larger than currently stored value.
+* p points to a node returned by insert.
+* newVal is the new value, which must be smaller
+* than the currently stored value.
+*/
+template <class T,class TCompare>
+void PairingHeap<T,TCompare>::decreaseKey( PairNode<T> *p,
+ const T & newVal )
+{
+ COLA_ASSERT(!lessThan(p->element,newVal)); // newVal cannot be bigger
+ p->element = newVal;
+ if( p != root )
+ {
+ if( p->nextSibling != nullptr )
+ p->nextSibling->prev = p->prev;
+ if( p->prev->leftChild == p )
+ p->prev->leftChild = p->nextSibling;
+ else
+ p->prev->nextSibling = p->nextSibling;
+
+ p->nextSibling = nullptr;
+ compareAndLink( root, p );
+ }
+}
+
+/**
+ * Merges rhs into this pairing heap by inserting its root
+ */
+template <class T,class TCompare>
+void PairingHeap<T,TCompare>::merge( PairingHeap<T,TCompare> *rhs )
+{
+ unsigned rhsSize;
+ PairNode<T> *broot=rhs->removeRootForMerge(rhsSize);
+ if (root == nullptr) {
+ root = broot;
+ } else {
+ compareAndLink(root, broot);
+ }
+ counter+=rhsSize;
+}
+
+/**
+* Internal method that is the basic operation to maintain order.
+* Links first and second together to satisfy heap order.
+* first is root of tree 1, which may not be nullptr.
+* first->nextSibling MUST be nullptr on entry.
+* second is root of tree 2, which may be nullptr.
+* first becomes the result of the tree merge.
+*/
+template <class T,class TCompare>
+void PairingHeap<T,TCompare>::
+compareAndLink( PairNode<T> * & first,
+ PairNode<T> *second ) const
+{
+ if( second == nullptr )
+ return;
+
+ if( lessThan(second->element,first->element) )
+ {
+ // Attach first as leftmost child of second
+ second->prev = first->prev;
+ first->prev = second;
+ first->nextSibling = second->leftChild;
+ if( first->nextSibling != nullptr )
+ first->nextSibling->prev = first;
+ second->leftChild = first;
+ first = second;
+ }
+ else
+ {
+ // Attach second as leftmost child of first
+ second->prev = first;
+ first->nextSibling = second->nextSibling;
+ if( first->nextSibling != nullptr )
+ first->nextSibling->prev = first;
+ second->nextSibling = first->leftChild;
+ if( second->nextSibling != nullptr )
+ second->nextSibling->prev = second;
+ first->leftChild = second;
+ }
+}
+
+/**
+* Internal method that implements two-pass merging.
+* firstSibling the root of the conglomerate;
+* assumed not nullptr.
+*/
+template <class T,class TCompare>
+PairNode<T> *
+PairingHeap<T,TCompare>::combineSiblings( PairNode<T> *firstSibling )
+{
+ if( firstSibling->nextSibling == nullptr )
+ return firstSibling;
+
+ // Store the subtrees in an array
+ int numSiblings = 0;
+ for( ; firstSibling != nullptr; numSiblings++ )
+ {
+ if( numSiblings == (int)siblingsTreeArray.size( ) )
+ siblingsTreeArray.resize( numSiblings * 2 );
+ siblingsTreeArray[ numSiblings ] = firstSibling;
+ firstSibling->prev->nextSibling = nullptr; // break links
+ firstSibling = firstSibling->nextSibling;
+ }
+ if( numSiblings == (int)siblingsTreeArray.size( ) )
+ siblingsTreeArray.resize( numSiblings + 1 );
+ siblingsTreeArray[ numSiblings ] = nullptr;
+
+ // Combine subtrees two at a time, going left to right
+ int i = 0;
+ for( ; i + 1 < numSiblings; i += 2 )
+ compareAndLink( siblingsTreeArray[ i ], siblingsTreeArray[ i + 1 ] );
+
+ int j = i - 2;
+
+ // j has the result of last compareAndLink.
+ // If an odd number of trees, get the last one.
+ if( j == numSiblings - 3 )
+ compareAndLink( siblingsTreeArray[ j ], siblingsTreeArray[ j + 2 ] );
+
+ // Now go right to left, merging last tree with
+ // next to last. The result becomes the new last.
+ for( ; j >= 2; j -= 2 )
+ compareAndLink( siblingsTreeArray[ j - 2 ], siblingsTreeArray[ j ] );
+ return siblingsTreeArray[ 0 ];
+}
+
+/**
+* Internal method to clone subtree.
+* WARNING: This is prone to running out of stack space.
+*/
+template <class T,class TCompare>
+PairNode<T> *
+PairingHeap<T,TCompare>::clone( PairNode<T> * t ) const
+{
+ if( t == nullptr )
+ return nullptr;
+ else
+ {
+ PairNode<T> *p = new PairNode<T>( t->element );
+ if( ( p->leftChild = clone( t->leftChild ) ) != nullptr )
+ p->leftChild->prev = p;
+ if( ( p->nextSibling = clone( t->nextSibling ) ) != nullptr )
+ p->nextSibling->prev = p;
+ return p;
+ }
+}
+
+template <class T,class TCompare>
+std::ostream& operator <<(std::ostream &os, const PairingHeap<T,TCompare> &b)
+{
+ os<<"Heap:";
+ if (b.root != nullptr) {
+ PairNode<T> *r = b.root;
+ std::list<PairNode<T>*> q;
+ q.push_back(r);
+ while (!q.empty()) {
+ r = q.front();
+ q.pop_front();
+ if (r->leftChild != nullptr) {
+ os << *r->element << ">";
+ PairNode<T> *c = r->leftChild;
+ while (c != nullptr) {
+ q.push_back(c);
+ os << "," << *c->element;
+ c = c->nextSibling;
+ }
+ os << "|";
+ }
+ }
+ }
+ return os;
+}
+
+#endif /* VPSC_PAIRING_HEAP_H */
diff --git a/src/3rdparty/adaptagrams/libvpsc/rectangle.cpp b/src/3rdparty/adaptagrams/libvpsc/rectangle.cpp
new file mode 100644
index 0000000..6d80c34
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/rectangle.cpp
@@ -0,0 +1,744 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2005-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+*/
+
+/*
+ * @brief Functions to automatically generate constraints for the
+ * rectangular node overlap removal problem.
+ *
+ */
+
+#include <cmath>
+#include <set>
+#include <cstdlib>
+#include <algorithm>
+#include <cstdio>
+
+#include "libvpsc/assertions.h"
+#include "libvpsc/solve_VPSC.h"
+#include "libvpsc/rectangle.h"
+#include "libvpsc/constraint.h"
+#include "libvpsc/variable.h"
+
+using std::set;
+using std::vector;
+
+namespace vpsc {
+
+double Rectangle::xBorder = 0;
+double Rectangle::yBorder = 0;
+
+std::ostream& operator <<(std::ostream &os, const Rectangle &r) {
+ os << "Hue[0.17],Rectangle[{"<<r.getMinX()<<","<<r.getMinY()<<"},{"<<r.getMaxX()<<","<<r.getMaxY()<<"}]";
+ return os;
+}
+
+Rectangle::Rectangle(double x, double X, double y, double Y,bool allowOverlap)
+ : minX(x),
+ maxX(X),
+ minY(y),
+ maxY(Y),
+ overlap(allowOverlap)
+{
+ COLA_ASSERT(x<X);
+ COLA_ASSERT(y<Y);
+ COLA_ASSERT(getMinX()<getMaxX());
+ COLA_ASSERT(getMinY()<getMaxY());
+}
+
+Rectangle::Rectangle()
+ : minX(1),
+ maxX(-1),
+ minY(1),
+ maxY(-1),
+ overlap(false)
+{
+ // Creates an invalid Rectangle
+}
+
+bool Rectangle::isValid(void) const
+{
+ return ((minX <= maxX) && (minY <= maxY));
+}
+
+Rectangle Rectangle::unionWith(const Rectangle& rhs) const
+{
+ if (!isValid())
+ {
+ return Rectangle(rhs);
+ }
+ else if (!rhs.isValid())
+ {
+ return Rectangle(*this);
+ }
+
+ double newMaxY = std::max(rhs.getMaxY(),maxY);
+ double newMinY = std::min(rhs.getMinY(),minY);
+ double newMinX = std::min(rhs.getMinX(),minX);
+ double newMaxX = std::max(rhs.getMaxX(),maxX);
+
+ return Rectangle(newMinX, newMaxX, newMinY, newMaxY);
+}
+
+void Rectangle::reset(unsigned d, double x, double X) {
+ if(d==0) {
+ minX=x;
+ maxX=X;
+ } else {
+ minY=x;
+ maxY=X;
+ }
+}
+
+struct Node;
+struct CmpNodePos { bool operator()(const Node* u, const Node* v) const; };
+
+typedef set<Node*,CmpNodePos> NodeSet;
+
+struct Node {
+ Variable *v;
+ Rectangle *r;
+ double pos;
+ Node *firstAbove, *firstBelow;
+ NodeSet *leftNeighbours, *rightNeighbours;
+ Node(Variable *v, Rectangle *r, double p)
+ : v(v),r(r),pos(p),
+ firstAbove(nullptr), firstBelow(nullptr),
+ leftNeighbours(nullptr), rightNeighbours(nullptr)
+
+ {
+ COLA_ASSERT(r->width()<1e40);
+ }
+ ~Node() {
+ delete leftNeighbours;
+ delete rightNeighbours;
+ }
+ void addLeftNeighbour(Node *u) {
+ COLA_ASSERT(leftNeighbours!=nullptr);
+ leftNeighbours->insert(u);
+ }
+ void addRightNeighbour(Node *u) {
+ COLA_ASSERT(rightNeighbours!=nullptr);
+ rightNeighbours->insert(u);
+ }
+ void setNeighbours(NodeSet *left, NodeSet *right) {
+ leftNeighbours=left;
+ rightNeighbours=right;
+ for(NodeSet::iterator i=left->begin();i!=left->end();++i) {
+ Node *v=*(i);
+ v->addRightNeighbour(this);
+ }
+ for(NodeSet::iterator i=right->begin();i!=right->end();++i) {
+ Node *v=*(i);
+ v->addLeftNeighbour(this);
+ }
+ }
+};
+bool CmpNodePos::operator() (const Node* u, const Node* v) const {
+ COLA_ASSERT(!std::isnan(u->pos));
+ COLA_ASSERT(!std::isnan(v->pos));
+ if (u->pos < v->pos) {
+ return true;
+ }
+ if (v->pos < u->pos) {
+ return false;
+ }
+ return u < v;
+}
+
+NodeSet* getLeftNeighbours(NodeSet &scanline,Node *v) {
+ NodeSet *leftv = new NodeSet;
+ NodeSet::iterator i=scanline.find(v);
+ while(i!=scanline.begin()) {
+ Node *u=*(--i);
+ if(u->r->overlapX(v->r)<=0) {
+ leftv->insert(u);
+ return leftv;
+ }
+ if(u->r->overlapX(v->r)<=u->r->overlapY(v->r)) {
+ leftv->insert(u);
+ }
+ }
+ return leftv;
+}
+NodeSet* getRightNeighbours(NodeSet &scanline,Node *v) {
+ NodeSet *rightv = new NodeSet;
+ NodeSet::iterator i=scanline.find(v);
+ for(++i;i!=scanline.end(); ++i) {
+ Node *u=*(i);
+ if(u->r->overlapX(v->r)<=0) {
+ rightv->insert(u);
+ return rightv;
+ }
+ if(u->r->overlapX(v->r)<=u->r->overlapY(v->r)) {
+ rightv->insert(u);
+ }
+ }
+ return rightv;
+}
+
+typedef enum {Open, Close} EventType;
+struct Event {
+ EventType type;
+ Node *v;
+ double pos;
+ Event(EventType t, Node *v, double p) : type(t),v(v),pos(p) {};
+};
+int compare_events(const void *a, const void *b) {
+ Event *ea=*(Event**)a;
+ Event *eb=*(Event**)b;
+ if(ea->pos==eb->pos) {
+ // when comparing opening and closing
+ // open must come first
+ if(ea->type==Open) return -1;
+ return 1;
+ } else if(ea->pos > eb->pos) {
+ return 1;
+ } else if(ea->pos < eb->pos) {
+ return -1;
+ } else if(std::isnan(ea->pos) != std::isnan(ea->pos)) {
+ /* See comment in CmpNodePos. */
+ return ( std::isnan(ea->pos)
+ ? -1
+ : 1 );
+ }
+ return 0;
+}
+
+/*
+ * Prepares constraints in order to apply VPSC horizontally. Assumes
+ * variables have already been created.
+ * useNeighbourLists determines whether or not a heuristic is used to
+ * deciding whether to resolve all overlap in the x pass, or leave some
+ * overlaps for the y pass.
+ */
+void generateXConstraints(const Rectangles& rs, const Variables& vars,
+ Constraints& cs, const bool useNeighbourLists)
+{
+ const unsigned n = rs.size();
+ COLA_ASSERT(vars.size()>=n);
+ Event **events=new Event*[2*n];
+ unsigned i,ctr=0;
+ for(i=0;i<n;i++) {
+ vars[i]->desiredPosition=rs[i]->getCentreX();
+ Node *v = new Node(vars[i],rs[i],rs[i]->getCentreX());
+ events[ctr++]=new Event(Open,v,rs[i]->getMinY());
+ events[ctr++]=new Event(Close,v,rs[i]->getMaxY());
+ }
+ qsort((Event*)events, (size_t)2*n, sizeof(Event*), compare_events );
+
+ NodeSet scanline;
+ for(i=0;i<2*n;i++) {
+ Event *e=events[i];
+ Node *v=e->v;
+ if(e->type==Open) {
+ scanline.insert(v);
+ if(useNeighbourLists) {
+ v->setNeighbours(
+ getLeftNeighbours(scanline,v),
+ getRightNeighbours(scanline,v)
+ );
+ } else {
+ NodeSet::iterator it=scanline.find(v);
+ if(it!=scanline.begin()) {
+ Node *u=*(--it);
+ v->firstAbove=u;
+ u->firstBelow=v;
+ }
+ it=scanline.find(v);
+ if(++it!=scanline.end()) {
+ Node *u=*it;
+ v->firstBelow=u;
+ u->firstAbove=v;
+ }
+ }
+ } else {
+ size_t result;
+ // Close event
+ if(useNeighbourLists) {
+ for(NodeSet::iterator i=v->leftNeighbours->begin();
+ i!=v->leftNeighbours->end();i++
+ ) {
+ Node *u=*i;
+ double sep = (v->r->width()+u->r->width())/2.0;
+ cs.push_back(new Constraint(u->v,v->v,sep));
+ result=u->rightNeighbours->erase(v);
+ COLA_ASSERT(result==1);
+ }
+
+ for(NodeSet::iterator i=v->rightNeighbours->begin();
+ i!=v->rightNeighbours->end();i++
+ ) {
+ Node *u=*i;
+ double sep = (v->r->width()+u->r->width())/2.0;
+ cs.push_back(new Constraint(v->v,u->v,sep));
+ result=u->leftNeighbours->erase(v);
+ COLA_ASSERT(result==1);
+ }
+ } else {
+ Node *l=v->firstAbove, *r=v->firstBelow;
+ if(l!=nullptr) {
+ double sep = (v->r->width()+l->r->width())/2.0;
+ cs.push_back(new Constraint(l->v,v->v,sep));
+ l->firstBelow=v->firstBelow;
+ }
+ if(r!=nullptr) {
+ double sep = (v->r->width()+r->r->width())/2.0;
+ cs.push_back(new Constraint(v->v,r->v,sep));
+ r->firstAbove=v->firstAbove;
+ }
+ }
+ result=scanline.erase(v);
+ COLA_ASSERT(result==1);
+ delete v;
+ }
+ delete e;
+ }
+ COLA_ASSERT(scanline.size()==0);
+ delete [] events;
+}
+
+/*
+ * Prepares constraints in order to apply VPSC vertically to remove ALL
+ * overlap.
+ */
+void generateYConstraints(const Rectangles& rs, const Variables& vars,
+ Constraints& cs)
+{
+ const unsigned n = rs.size();
+ COLA_ASSERT(vars.size()>=n);
+ Event **events=new Event*[2*n];
+ unsigned ctr=0;
+ Rectangles::const_iterator ri=rs.begin(), re=rs.end();
+ Variables::const_iterator vi=vars.begin(), ve=vars.end();
+ for(;ri!=re&&vi!=ve;++ri,++vi) {
+ Rectangle* r=*ri;
+ Variable* v=*vi;
+ v->desiredPosition=r->getCentreY();
+ Node *node = new Node(v,r,r->getCentreY());
+ COLA_ASSERT(r->getMinX()<r->getMaxX());
+ events[ctr++]=new Event(Open,node,r->getMinX());
+ events[ctr++]=new Event(Close,node,r->getMaxX());
+ }
+ COLA_ASSERT(ri==rs.end());
+ qsort((Event*)events, (size_t)2*n, sizeof(Event*), compare_events );
+ NodeSet scanline;
+#ifndef NDEBUG
+ size_t deletes=0;
+#endif
+ for(unsigned i=0;i<2*n;i++) {
+ Event *e=events[i];
+ Node *v=e->v;
+ if(e->type==Open) {
+ scanline.insert(v);
+ NodeSet::iterator it=scanline.find(v);
+ if(it!=scanline.begin()) {
+ Node *u=*(--it);
+ v->firstAbove=u;
+ u->firstBelow=v;
+ }
+ it=scanline.find(v);
+ if(++it!=scanline.end()) {
+ Node *u=*it;
+ v->firstBelow=u;
+ u->firstAbove=v;
+ }
+ } else {
+ // Close event
+ Node *l=v->firstAbove, *r=v->firstBelow;
+ if(l!=nullptr) {
+ double sep = (v->r->height()+l->r->height())/2.0;
+ cs.push_back(new Constraint(l->v,v->v,sep));
+ l->firstBelow=v->firstBelow;
+ }
+ if(r!=nullptr) {
+ double sep = (v->r->height()+r->r->height())/2.0;
+ cs.push_back(new Constraint(v->v,r->v,sep));
+ r->firstAbove=v->firstAbove;
+ }
+#ifndef NDEBUG
+ deletes++;
+ size_t erased=
+#endif
+ scanline.erase(v);
+ COLA_ASSERT(erased==1);
+ delete v;
+ }
+ delete e;
+ }
+ COLA_ASSERT(scanline.size()==0);
+ COLA_ASSERT(deletes==n);
+ delete [] events;
+}
+#include "libvpsc/linesegment.h"
+using namespace linesegment;
+inline bool checkIntersection(
+ const LineSegment::IntersectResult result,
+ Vector const &intersection,
+ RectangleIntersections &ri,
+ bool &side, double &sideX, double &sideY) {
+ switch(result) {
+ case LineSegment::INTERSECTING:
+ ri.intersects=side=true;
+ sideX=intersection.x_;
+ sideY=intersection.y_;
+ case LineSegment::PARALLEL:
+ case LineSegment::NOT_INTERSECTING:
+ return true;
+ case LineSegment::COINCIDENT:
+ ri.intersects=ri.top=ri.bottom=ri.left=ri.right=false;
+ return false;
+ }
+ return false;
+}
+void Rectangle::
+lineIntersections(double x1, double y1, double x2, double y2, RectangleIntersections &ri) const {
+ Vector intersection;
+ LineSegment l(Vector(x1,y1),Vector(x2,y2));
+ LineSegment top(Vector(getMinX(),getMaxY()),Vector(getMaxX(),getMaxY()));
+ if(!checkIntersection(
+ l.Intersect(top,intersection),intersection,
+ ri,ri.top,ri.topX,ri.topY)) {
+ return;
+ }
+ LineSegment bottom(Vector(getMinX(),getMinY()),Vector(getMaxX(),getMinY()));
+ if(!checkIntersection(
+ l.Intersect(bottom,intersection),intersection,
+ ri,ri.bottom,ri.bottomX,ri.bottomY)) {
+ return;
+ }
+ LineSegment left(Vector(getMinX(),getMinY()),Vector(getMinX(),getMaxY()));
+ if(!checkIntersection(
+ l.Intersect(left,intersection),intersection,
+ ri,ri.left,ri.leftX,ri.leftY)) {
+ return;
+ }
+ LineSegment right(Vector(getMaxX(),getMinY()),Vector(getMaxX(),getMaxY()));
+ if(!checkIntersection(
+ l.Intersect(right,intersection),intersection,
+ ri,ri.right,ri.rightX,ri.rightY)) {
+ return;
+ }
+}
+static const double ERROR_MARGIN = 1e-4;
+inline bool eq(double a, double b) {
+ return fabs(a-b)<ERROR_MARGIN;
+ //return a==b;
+}
+/*
+bool Rectangle::inside(double x, double y) const {
+ return x>(minX+ERROR_MARGIN) && x<(maxX-ERROR_MARGIN)
+ && y>(minY+ERROR_MARGIN) && y<(maxY-ERROR_MARGIN);
+}
+*/
+// p1=(x1,y1),p2=(x2,y2) are points on the boundary. Puts the shortest
+// path round the outside of the rectangle from p1 to p2 into xs, ys.
+void Rectangle::routeAround(double x1, double y1, double x2, double y2,
+ std::vector<double> &xs, std::vector<double> &ys) {
+ COLA_ASSERT(eq(x1,minX) || eq(x1,maxX) || eq(y1,minY) || eq(y1,maxY));
+ COLA_ASSERT(eq(x2,minX) || eq(x2,maxX) || eq(y2,minY) || eq(y2,maxY));
+ xs.push_back(x1);
+ ys.push_back(y1);
+ bool top1=eq(y1,maxY), top2=eq(y2,maxY),
+ bottom1=eq(y1,minY), bottom2=eq(y2,minY);
+ bool left1=eq(x1,minX), left2=eq(x2,minX),
+ right1=eq(x1,maxX), right2=eq(x2,maxX);
+ bool leftright = (left1 && right2) || (right1 && left2);
+ bool topbottom = (top1 && bottom2) || (bottom1 && top2);
+ bool lefttop = (left1 && top2) || (top1 && left2);
+ bool righttop = (right1 && top2) || (top1 && right2);
+ bool leftbottom = (left1 && bottom2) || (bottom1 && left2);
+ bool rightbottom = (right1 && bottom2) || (bottom1 && right2);
+ if(lefttop) {
+ xs.push_back(minX);
+ ys.push_back(maxY);
+ } else if(righttop) {
+ xs.push_back(maxX);
+ ys.push_back(maxY);
+ } else if(leftbottom) {
+ xs.push_back(minX);
+ ys.push_back(minY);
+ } else if(rightbottom) {
+ xs.push_back(maxX);
+ ys.push_back(minY);
+ } else if(leftright) {
+ double midY = y1+(y2-y1)/2.0;
+ if(left1) { // left to right
+ if(midY<getCentreY()) { // route below
+ // bottom left
+ xs.push_back(getMinX());
+ ys.push_back(getMinY());
+ // bottom right
+ xs.push_back(getMaxX());
+ ys.push_back(getMinY());
+ } else { // route above
+ // top left
+ xs.push_back(getMinX());
+ ys.push_back(getMaxY());
+ // top right
+ xs.push_back(getMaxX());
+ ys.push_back(getMaxY());
+ }
+ } else { // right to left
+ if(midY<getCentreY()) { // route below
+ // bottom right
+ xs.push_back(getMaxX());
+ ys.push_back(getMinY());
+ // bottom left
+ xs.push_back(getMinX());
+ ys.push_back(getMinY());
+ } else { // route above
+ // top right
+ xs.push_back(getMaxX());
+ ys.push_back(getMaxY());
+ // top left
+ xs.push_back(getMinX());
+ ys.push_back(getMaxY());
+ }
+ }
+ } else if(topbottom) {
+ double midX = x1+(x2-x1)/2.0;
+ if(top1) {
+ if(midX<getCentreX()) { // route left
+ // top left
+ xs.push_back(getMinX());
+ ys.push_back(getMaxY());
+ // bottom left
+ xs.push_back(getMinX());
+ ys.push_back(getMinY());
+ } else { // route right
+ // top right
+ xs.push_back(getMaxX());
+ ys.push_back(getMaxY());
+ // bottom right
+ xs.push_back(getMaxX());
+ ys.push_back(getMinY());
+ }
+ } else { // bottom to top
+ if(midX<getCentreX()) { // route left
+ // bottom left
+ xs.push_back(getMinX());
+ ys.push_back(getMinY());
+ // top left
+ xs.push_back(getMinX());
+ ys.push_back(getMaxY());
+ } else { // route right
+ // bottom right
+ xs.push_back(getMaxX());
+ ys.push_back(getMinY());
+ // top right
+ xs.push_back(getMaxX());
+ ys.push_back(getMaxY());
+ }
+ }
+ }
+ xs.push_back(x2);
+ ys.push_back(y2);
+}
+
+/*
+ * moves all the rectangles to remove all overlaps. Heuristic
+ * attempts to move by as little as possible.
+ * no overlaps guaranteed.
+ * @param rs the rectangles which will be moved to remove overlap
+ */
+void removeoverlaps(Rectangles& rs) {
+ const set<unsigned> fixed = set<unsigned>();
+ removeoverlaps(rs,fixed);
+}
+#define ISNOTNAN(d) (d)==(d)
+/*
+ * Moves rectangles to remove all overlaps. A heuristic
+ * attempts to move by as little as possible. The heuristic is
+ * that the overlaps are removed horizontally and then vertically,
+ * each pass being a quadratic program in which the total squared movement
+ * is minimised subject to non-overlap constraints. An optional third
+ * horizontal pass (in addition to the first horizontal pass and the second
+ * vertical pass) can be applied wherein the x-positions of rectangles are reset to their
+ * original positions and overlap removal repeated. This may avoid some
+ * unnecessary movement.
+ * @param rs the rectangles which will be moved to remove overlap
+ * @param fixed a set of indices to rectangles which should not be moved
+ * @param thirdPass optionally run the third horizontal pass described above.
+ */
+void removeoverlaps(Rectangles& rs, const set<unsigned>& fixed, bool thirdPass) {
+ const double xBorder=Rectangle::xBorder, yBorder=Rectangle::yBorder;
+ static const double EXTRA_GAP=1e-3;
+ static const size_t ARRAY_UNUSED=1;
+ unsigned n=rs.size();
+ try {
+ // The extra gap avoids numerical imprecision problems
+ Rectangle::setXBorder(xBorder+EXTRA_GAP);
+ Rectangle::setYBorder(yBorder+EXTRA_GAP);
+ Variables vs(n);
+ Variables::iterator v;
+ unsigned i=0;
+ vector<double> initX(thirdPass?n:ARRAY_UNUSED);
+ for(v=vs.begin();v!=vs.end();++v,++i) {
+ double weight=1;
+ if(fixed.find(i)!=fixed.end()) {
+ weight=10000;
+ }
+ *v=new Variable(i,0,weight);
+ if(thirdPass) {
+ initX[i]=rs[i]->getCentreX();
+ }
+ }
+ Constraints cs;
+ generateXConstraints(rs,vs,cs,true);
+ Solver vpsc_x(vs,cs);
+ vpsc_x.solve();
+ Rectangles::iterator r=rs.begin();
+ for(v=vs.begin();v!=vs.end();++v,++r) {
+ COLA_ASSERT(ISNOTNAN((*v)->finalPosition));
+ (*r)->moveCentreX((*v)->finalPosition);
+ }
+ COLA_ASSERT(r==rs.end());
+ for_each(cs.begin(),cs.end(),delete_object());
+ cs.clear();
+ // Removing the extra gap here ensures things that were moved to be
+ // adjacent to one another above are not considered overlapping
+ Rectangle::setXBorder(xBorder);
+ generateYConstraints(rs,vs,cs);
+ Solver vpsc_y(vs,cs);
+ vpsc_y.solve();
+ r=rs.begin();
+ for(v=vs.begin();v!=vs.end();++v,++r) {
+ COLA_ASSERT(ISNOTNAN((*v)->finalPosition));
+ (*r)->moveCentreY((*v)->finalPosition);
+ }
+ for_each(cs.begin(),cs.end(),delete_object());
+ cs.clear();
+ Rectangle::setYBorder(yBorder);
+ if(thirdPass) {
+ // we reset x positions to their original values
+ // and apply a third pass horizontally so that
+ // rectangles which were moved unnecessarily in the
+ // first horizontal pass (i.e. their overlap
+ // was later resolved vertically) have an
+ // opportunity now to stay put.
+ Rectangle::setXBorder(xBorder+EXTRA_GAP);
+ r=rs.begin();
+ for(v=vs.begin();v!=vs.end();++v,++r) {
+ (*r)->moveCentreX(initX[(*v)->id]);
+ }
+ generateXConstraints(rs,vs,cs,false);
+ Solver vpsc_x2(vs,cs);
+ vpsc_x2.solve();
+ r=rs.begin();
+ for(v=vs.begin();v!=vs.end();++v,++r) {
+ COLA_ASSERT(ISNOTNAN((*v)->finalPosition));
+ (*r)->moveCentreX((*v)->finalPosition);
+ }
+ }
+ Rectangle::setXBorder(xBorder);
+ for_each(cs.begin(),cs.end(),delete_object());
+ for_each(vs.begin(),vs.end(),delete_object());
+ } catch (char *str) {
+ std::cerr<<str<<std::endl;
+ for(Rectangles::iterator r=rs.begin();r!=rs.end();++r) {
+ std::cerr << **r <<std::endl;
+ }
+ }
+ COLA_ASSERT(noRectangleOverlaps(rs));
+}
+
+
+bool noRectangleOverlaps(const Rectangles& rs)
+{
+ Rectangle *u, *v;
+ Rectangles::const_iterator i=rs.begin(), j, e=rs.end();
+ for (;i!=e;++i)
+ {
+ u=*i;
+ for (j=i+1;j!=e;++j)
+ {
+ v=*j;
+ if (u->overlapX(v)>0)
+ {
+ COLA_ASSERT(u->overlapY(v)==0);
+ }
+ }
+ }
+ return true;
+}
+
+// checks if line segment is strictly overlapping.
+// That is, if any point on the line is inside the rectangle.
+bool Rectangle::overlaps(double x1, double y1, double x2, double y2)
+{
+ RectangleIntersections ri;
+ lineIntersections(x1,y1,x2,y2,ri);
+ if(ri.intersects) {
+ if(ri.countIntersections()==1) {
+ // special case when one point is touching
+ // the boundary of the rectangle but no part
+ // of the line is interior
+ if(!inside(x1,y1)&&!inside(x2,y2)) {
+ return false;
+ }
+ }
+ printf("Rectangle/Segment intersection (SVG):\n");
+ printf("<svg style=\"stroke: black; fill: none;\">\n");
+ printf("<polyline points=\"%f,%f %f,%f\" />\n",x1,y1,x2,y2);
+ printf("<rect x=\"%f\" y=\"%f\" width=\"%f\" height=\"%f\" />\n",
+ getMinX(),getMinY(),width(),height());
+ printf("</svg>\n");
+ ri.printIntersections();
+ return true;
+ }
+ return false;
+}
+
+
+void RectangleIntersections::printIntersections()
+{
+ printf("intersections:\n");
+ if(top) printf(" top=%d:(%f,%f)\n",top,topX,topY);
+ if(bottom) printf(" bottom=%d:(%f,%f)\n",bottom,bottomX,bottomY);
+ if(left) printf(" left=%d:(%f,%f)\n",left,leftX,leftY);
+ if(right) printf(" right=%d:(%f,%f)\n",right,rightX,rightY);
+}
+
+// Of the stored intersections, this returns the one closest to the
+// specified point
+void RectangleIntersections::nearest(double x, double y, double &xi, double &yi) {
+ bool is[]={top, right, bottom, left};
+ double xs[]={topX, rightX, bottomX, leftX};
+ double ys[]={topY, rightY, bottomY, leftY};
+ double dx, dy, l, minl = 999999999999999.0;
+ for(unsigned i=0;i<4;i++)
+ {
+ if(is[i])
+ {
+ dx=xs[i]-x;
+ dy=ys[i]-y;
+ l=dx*dx + dy*dy;
+ if(l<minl)
+ {
+ minl=l;
+ xi=xs[i];
+ yi=ys[i];
+ }
+ }
+ }
+}
+
+}
diff --git a/src/3rdparty/adaptagrams/libvpsc/rectangle.h b/src/3rdparty/adaptagrams/libvpsc/rectangle.h
new file mode 100644
index 0000000..df76399
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/rectangle.h
@@ -0,0 +1,302 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2005-2010 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+*/
+
+/*
+ * Functions to automatically generate constraints for the
+ * rectangular node overlap removal problem.
+ *
+ */
+#ifndef VPSC_RECTANGLE_H
+#define VPSC_RECTANGLE_H
+
+#include <iostream>
+#include <vector>
+#include <set>
+#include <cassert>
+#include <cmath>
+
+#include "libvpsc/assertions.h"
+
+namespace vpsc {
+
+//! @brief Indicates the x- or y-dimension.
+enum Dim {
+ //! The x-dimension (0).
+ HORIZONTAL = 0,
+ //! The x-dimension (0).
+ XDIM = 0,
+ //! The y-dimension (1).
+ VERTICAL = 1,
+ //! The y-dimension (1).
+ YDIM = 1,
+ // The dimension is not set.
+ UNSET = 2
+};
+
+inline Dim conjugate(Dim d) {
+ return static_cast<Dim>(!d);
+}
+/* records the positions and sides through which a particular line intersects with a rectangle
+ */
+struct RectangleIntersections {
+ bool intersects, top, bottom, left, right;
+ double topX, topY, bottomX, bottomY, leftX, leftY, rightX, rightY;
+ RectangleIntersections()
+ : intersects(false),top(false),bottom(false),left(false),right(false),
+ topX(0),topY(0),bottomX(0),bottomY(0),leftX(0),leftY(0),rightX(0),rightY(0) {}
+ int countIntersections() {
+ return left+right+top+bottom;
+ }
+ void printIntersections(void);
+ // Of the stored intersections, this returns the one closest to the
+ // specified point
+ void nearest(double x, double y, double & xi, double & yi);
+};
+
+/**
+ * @brief A rectangle represents a fixed-size shape in the diagram that may
+ * be moved to prevent overlaps and satisfy constraints.
+ */
+class Rectangle {
+public:
+ /**
+ * @brief Constructs a rectangle by specifying the positions of all
+ * four sides.
+ *
+ * @param[in] x Minimum horizontal value.
+ * @param[in] X Maximum horizontal value.
+ * @param[in] y Minimum vertical value.
+ * @param[in] Y Maximum vertical value.
+ * @param[in] allowOverlap not used currently.
+ */
+ Rectangle(double x, double X, double y, double Y,
+ bool allowOverlap = false);
+ Rectangle(Rectangle const &Other)
+ : minX(Other.minX)
+ , maxX(Other.maxX)
+ , minY(Other.minY)
+ , maxY(Other.maxY)
+ , overlap(Other.overlap) { }
+ Rectangle();
+ bool isValid(void) const;
+ Rectangle unionWith(const Rectangle& rhs) const;
+ /*
+ * reset the dimensions in one axis
+ * @param d axis (0==X, 1==Y)
+ * @param x min value
+ * @param X max value
+ */
+ void reset(const unsigned d, double x, double X);
+ double getMaxX() const { return maxX+xBorder; }
+ double getMaxY() const { return maxY+yBorder; }
+ double getMinX() const { return minX-xBorder; }
+ double getMinY() const { return minY-yBorder; }
+ /*
+ * @param d axis: 0=horizontal 1=vertical
+ */
+ double getMinD(unsigned const d) const {
+ COLA_ASSERT(d==0||d==1);
+ return ( d == 0 ? getMinX() : getMinY() );
+ }
+ /*
+ * @param d axis: 0=horizontal 1=vertical
+ */
+ double getMaxD(unsigned const d) const {
+ COLA_ASSERT(d==0||d==1);
+ return ( d == 0 ? getMaxX() : getMaxY() );
+ }
+ void setMinD(unsigned const d, const double val)
+ { if ( d == 0) { minX = val; } else { minY = val; } }
+ void setMaxD(unsigned const d, const double val)
+ { if ( d == 0) { maxX = val; } else { maxY = val; } }
+ double getCentreX() const { return getMinX()+width()/2.0; }
+ double getCentreY() const { return getMinY()+height()/2.0; }
+ /*
+ * @param d axis: 0=horizontal 1=vertical
+ */
+ double getCentreD(unsigned const d) const {
+ COLA_ASSERT(d==0||d==1);
+ return getMinD(d)+length(d)/2.0;
+ }
+ double width() const { return getMaxX()-getMinX(); }
+ double height() const { return getMaxY()-getMinY(); }
+ /*
+ * @param d axis: 0=width 1=height
+ * @return width or height
+ */
+ double length(unsigned const d) const {
+ COLA_ASSERT(d==0||d==1);
+ return ( d == 0 ? width() : height() );
+ }
+ void set_width(double w) { maxX = minX + w - 2.0*xBorder; }
+ void set_height(double h) { maxY = minY + h - 2.0*yBorder; }
+ void moveCentreD(const unsigned d, double p) {
+ COLA_ASSERT(d==0||d==1);
+ if(d == 0) { moveCentreX(p);
+ } else { moveCentreY(p); }
+ }
+ void moveCentreX(double x) {
+ moveMinX(x-width()/2.0);
+ }
+ void moveCentreY(double y) {
+ moveMinY(y-height()/2.0);
+ }
+ void moveCentre(double x, double y) {
+ moveCentreX(x);
+ moveCentreY(y);
+ }
+ void moveMinX(double x) {
+ double w=width();
+ minX=x+xBorder;
+ maxX=x+w-xBorder;
+ COLA_ASSERT(fabs(width()-w)<1e-9);
+ }
+ void moveMinY(double y) {
+ double h=height();
+ maxY=y+h-yBorder;
+ minY=y+yBorder;
+ COLA_ASSERT(fabs(height()-h)<1e-9);
+ }
+ double overlapD(const unsigned d, Rectangle* r) {
+ if(d==0) {
+ return overlapX(r);
+ } else {
+ return overlapY(r);
+ }
+ }
+ double overlapX(Rectangle *r) const {
+ double ux=getCentreX(), vx=r->getCentreX();
+ if (ux <= vx && r->getMinX() < getMaxX())
+ return getMaxX() - r->getMinX();
+ if (vx <= ux && getMinX() < r->getMaxX())
+ return r->getMaxX() - getMinX();
+ return 0;
+ }
+ double overlapY(Rectangle *r) const {
+ double uy=getCentreY(), vy=r->getCentreY();
+ if (uy <= vy && r->getMinY() < getMaxY()) {
+ return getMaxY() - r->getMinY();
+ }
+ if (vy <= uy && getMinY() < r->getMaxY()) {
+ return r->getMaxY() - getMinY();
+ }
+ return 0;
+ }
+ bool allowOverlap() {
+ return overlap;
+ }
+ void offset(double dx, double dy) {
+ minX += dx;
+ maxX += dx;
+ minY += dy;
+ maxY += dy;
+ }
+ // returns the intersections between the line segment from (x1,y1)
+ // to (x2,y2) and this rectangle. Any intersections points with
+ // sides are reported, lines coincident with a side are considered not
+ // to intersect.
+ void lineIntersections(double x1, double y1, double x2, double y2, RectangleIntersections &ri) const;
+ bool inside(double x, double y) const {
+ return x>getMinX() && x<getMaxX() && y>getMinY() && y<getMaxY();
+ }
+ // checks if line segment is strictly overlapping.
+ // That is, if any point on the line is inside the rectangle.
+ bool overlaps(double x1, double y1, double x2, double y2);
+ // p1=(x1,y1),p2=(x2,y2) are points on the boundary. Puts the shortest
+ // path round the outside of the rectangle from p1 to p2 into xs, ys.
+ void routeAround(double x1, double y1, double x2, double y2,
+ std::vector<double> &xs, std::vector<double> &ys);
+ /*
+ * xBorder and yBorder can be set to add a border to the boundary of the
+ * rectangle. In other words, the size of the rectangle returned by the
+ * getters (getMinX, getMaxX, etc) will be slightly larger than the
+ * internal representation. This is useful in situations where we need the
+ * size considered in one axis to be slightly different to that considered
+ * in the other axis for example, to avoid numerical precision problems in
+ * the axis-by-axis overlap removal process.
+ */
+ static double xBorder,yBorder;
+ static void setXBorder(double x) {xBorder=x;}
+ static void setYBorder(double y) {yBorder=y;}
+
+private:
+ double minX,maxX,minY,maxY;
+ bool overlap;
+};
+
+//! @brief A vector of pointers to Rectangle objects.
+typedef std::vector<Rectangle*> Rectangles;
+
+std::ostream& operator<<(std::ostream& os, vpsc::Rectangle const &r);
+
+class Variable;
+typedef std::vector<Variable *> Variables;
+class Constraint;
+typedef std::vector<Constraint *> Constraints;
+
+void generateXConstraints(const Rectangles& rs, const Variables& vars,
+ Constraints& cs, const bool useNeighbourLists);
+void generateYConstraints(const Rectangles& rs, const Variables& vars,
+ Constraints& cs);
+
+/**
+ * @brief Uses VPSC to remove overlaps between rectangles.
+ *
+ * Moves rectangles to remove all overlaps. Heuristic attempts to move
+ * shapes by as little as possible.
+ *
+ * @param[in,out] rs The rectangles which will be moved to remove overlap
+ */
+void removeoverlaps(Rectangles& rs);
+
+/**
+ * @brief Uses VPSC to remove overlaps between rectangles, excluding some
+ * that should not be moved.
+ *
+ * Moves rectangles to remove all overlaps. A heuristic attempts to move
+ * shapes by as little as possible. The heuristic is that the overlaps
+ * are removed horizontally and then vertically, each pass being a
+ * quadratic program in which the total squared movement is minimised
+ * subject to non-overlap constraints.
+ *
+ * An optional third horizontal pass (in addition to the first horizontal
+ * pass and the second vertical pass) can be applied wherein the
+ * x-positions of rectangles are reset to their original positions and
+ * overlap removal repeated. This may avoid some unnecessary movement.
+ *
+ * @param[in,out] rs The rectangles which will be moved to remove overlap
+ * @param[in] fixed A set of indices to rectangles which should not be moved.
+ * @param[in] thirdPass Optionally run the third horizontal pass described above.
+ */
+void removeoverlaps(Rectangles& rs, const std::set<unsigned>& fixed,
+ bool thirdPass = true);
+
+// Useful for assertions:
+bool noRectangleOverlaps(const Rectangles& rs);
+
+struct delete_object
+{
+ template <typename T>
+ void operator()(T *ptr){ delete ptr;}
+};
+
+} // namespace vpsc
+#endif // VPSC_RECTANGLE_H
diff --git a/src/3rdparty/adaptagrams/libvpsc/solve_VPSC.cpp b/src/3rdparty/adaptagrams/libvpsc/solve_VPSC.cpp
new file mode 100644
index 0000000..08cc1e4
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/solve_VPSC.cpp
@@ -0,0 +1,561 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2005-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+ * Michael Wybrow
+*/
+
+#include <cmath>
+#include <sstream>
+#include <map>
+#include <cfloat>
+#include <set>
+
+#include "libvpsc/constraint.h"
+#include "libvpsc/block.h"
+#include "libvpsc/blocks.h"
+#include "libvpsc/solve_VPSC.h"
+#include "libvpsc/cbuffer.h"
+#include "libvpsc/variable.h"
+#include "libvpsc/assertions.h"
+#include "libvpsc/exceptions.h"
+
+#ifdef LIBVPSC_LOGGING
+#include <fstream>
+#endif
+
+using namespace std;
+
+namespace vpsc {
+
+static const double ZERO_UPPERBOUND=-1e-10;
+static const double LAGRANGIAN_TOLERANCE=-1e-4;
+
+IncSolver::IncSolver(Variables const &vs, Constraints const &cs)
+ : Solver(vs,cs)
+{
+ inactive=cs;
+ for(Constraints::iterator i=inactive.begin();i!=inactive.end();++i) {
+ (*i)->active=false;
+ }
+}
+Solver::Solver(Variables const &vs, Constraints const &cs)
+ : m(cs.size()),
+ cs(cs),
+ n(vs.size()),
+ vs(vs),
+ needsScaling(false)
+{
+ for(unsigned i=0;i<n;++i) {
+ vs[i]->in.clear();
+ vs[i]->out.clear();
+
+ // Set needsScaling if any variables have a scale other than 1.
+ needsScaling |= (vs[i]->scale != 1);
+ }
+ for(unsigned i=0;i<m;++i) {
+ Constraint *c=cs[i];
+ c->left->out.push_back(c);
+ c->right->in.push_back(c);
+ c->needsScaling = needsScaling;
+ }
+ bs=new Blocks(vs);
+#ifdef LIBVPSC_LOGGING
+ printBlocks();
+ //COLA_ASSERT(!constraintGraphIsCyclic(n,vs));
+#endif
+}
+Solver::~Solver() {
+ delete bs;
+}
+
+void IncSolver::addConstraint(Constraint *c)
+{
+ ++m;
+ c->active = false;
+ inactive.push_back(c);
+ c->left->out.push_back(c);
+ c->right->in.push_back(c);
+ c->needsScaling = needsScaling;
+}
+
+// useful in debugging
+void Solver::printBlocks() {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ for(set<Block*>::iterator i=bs->begin();i!=bs->end();++i) {
+ Block *b=*i;
+ f<<" "<<*b<<endl;
+ }
+ for(unsigned i=0;i<m;i++) {
+ f<<" "<<*cs[i]<<endl;
+ }
+#endif
+}
+
+/**
+ * Stores the relative positions of the variables in their finalPosition
+ * field.
+ */
+void Solver::copyResult() {
+ for(Variables::const_iterator i=vs.begin();i!=vs.end();++i) {
+ Variable* v=*i;
+ v->finalPosition=v->position();
+ COLA_ASSERT(v->finalPosition==v->finalPosition);
+ }
+}
+/**
+* Produces a feasible - though not necessarily optimal - solution by
+* examining blocks in the partial order defined by the directed acyclic
+* graph of constraints. For each block (when processing left to right) we
+* maintain the invariant that all constraints to the left of the block
+* (incoming constraints) are satisfied. This is done by repeatedly merging
+* blocks into bigger blocks across violated constraints (most violated
+* first) fixing the position of variables inside blocks relative to one
+* another so that constraints internal to the block are satisfied.
+*/
+bool Solver::satisfy() {
+ list<Variable*> *vList=bs->totalOrder();
+ for(list<Variable*>::iterator i=vList->begin();i!=vList->end();++i) {
+ Variable *v=*i;
+ if(!v->block->deleted) {
+ bs->mergeLeft(v->block);
+ }
+ }
+ bs->cleanup();
+ bool activeConstraints=false;
+ for(unsigned i=0;i<m;i++) {
+ if(cs[i]->active) activeConstraints=true;
+ if(cs[i]->slack() < ZERO_UPPERBOUND) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<"Error: Unsatisfied constraint: "<<*cs[i]<<endl;
+#endif
+ //COLA_ASSERT(cs[i]->slack()>-0.0000001);
+ throw UnsatisfiedConstraint(*cs[i]);
+ }
+ }
+ delete vList;
+ copyResult();
+ return activeConstraints;
+}
+
+void Solver::refine() {
+ bool solved=false;
+ // Solve shouldn't loop indefinately
+ // ... but just to make sure we limit the number of iterations
+ unsigned maxtries=100;
+ while(!solved&&maxtries>0) {
+ solved=true;
+ maxtries--;
+ size_t length = bs->size();
+ for (size_t i = 0; i < length; ++i)
+ {
+ Block *b = bs->at(i);
+ b->setUpInConstraints();
+ b->setUpOutConstraints();
+ }
+ for (size_t i = 0; i < length; ++i)
+ {
+ Block *b = bs->at(i);
+ Constraint *c=b->findMinLM();
+ if(c!=nullptr && c->lm<LAGRANGIAN_TOLERANCE) {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<"Split on constraint: "<<*c<<endl;
+#endif
+ // Split on c
+ Block *l=nullptr, *r=nullptr;
+ bs->split(b,l,r,c);
+ bs->cleanup();
+ // split alters the block set so we have to restart
+ solved=false;
+ break;
+ }
+ }
+ }
+ for(unsigned i=0;i<m;i++) {
+ if(cs[i]->slack() < ZERO_UPPERBOUND) {
+ COLA_ASSERT(cs[i]->slack()>ZERO_UPPERBOUND);
+ throw UnsatisfiedConstraint(*cs[i]);
+ }
+ }
+}
+/**
+ * Calculate the optimal solution. After using satisfy() to produce a
+ * feasible solution, refine() examines each block to see if further
+ * refinement is possible by splitting the block. This is done repeatedly
+ * until no further improvement is possible.
+ */
+bool Solver::solve() {
+ satisfy();
+ refine();
+ copyResult();
+ return bs->size()!=n;
+}
+
+bool IncSolver::solve() {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<"solve_inc()..."<<endl;
+#endif
+ satisfy();
+ double lastcost = DBL_MAX, cost = bs->cost();
+ while(fabs(lastcost-cost)>0.0001) {
+ satisfy();
+ lastcost=cost;
+ cost = bs->cost();
+#ifdef LIBVPSC_LOGGING
+ f<<" bs->size="<<bs->size()<<", cost="<<cost<<endl;
+#endif
+ }
+ copyResult();
+ return bs->size()!=n;
+}
+/**
+ * incremental version of satisfy that allows refinement after blocks are
+ * moved.
+ *
+ * - move blocks to new positions
+ * - repeatedly merge across most violated constraint until no more
+ * violated constraints exist
+ *
+ * Note: there is a special case to handle when the most violated constraint
+ * is between two variables in the same block. Then, we must split the block
+ * over an active constraint between the two variables. We choose the
+ * constraint with the most negative lagrangian multiplier.
+ */
+bool IncSolver::satisfy() {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<"satisfy_inc()..."<<endl;
+#endif
+ splitBlocks();
+ //long splitCtr = 0;
+ Constraint* v = nullptr;
+ //CBuffer buffer(inactive);
+ while ( (v = mostViolated(inactive)) &&
+ (v->equality || ((v->slack() < ZERO_UPPERBOUND) && !v->active)) )
+ {
+ COLA_ASSERT(!v->active);
+ Block *lb = v->left->block, *rb = v->right->block;
+ if(lb != rb) {
+ lb->merge(rb,v);
+ } else {
+ if(lb->isActiveDirectedPathBetween(v->right,v->left)) {
+ // cycle found, relax the violated, cyclic constraint
+ v->unsatisfiable=true;
+ continue;
+ //UnsatisfiableException e;
+ //lb->getActiveDirectedPathBetween(e.path,v->right,v->left);
+ //e.path.push_back(v);
+ //throw e;
+ }
+ //if(splitCtr++>10000) {
+ //throw "Cycle Error!";
+ //}
+ // constraint is within block, need to split first
+ try {
+ Constraint* splitConstraint
+ =lb->splitBetween(v->left,v->right,lb,rb);
+ if(splitConstraint!=nullptr) {
+ COLA_ASSERT(!splitConstraint->active);
+ inactive.push_back(splitConstraint);
+ } else {
+ v->unsatisfiable=true;
+ continue;
+ }
+ } catch(UnsatisfiableException e) {
+ e.path.push_back(v);
+#ifdef LIBVPSC_DEBUG
+ std::cerr << "Unsatisfiable:" << std::endl;
+ for(std::vector<Constraint*>::iterator r=e.path.begin();
+ r!=e.path.end();++r)
+ {
+ std::cerr << **r <<std::endl;
+ }
+#endif
+ v->unsatisfiable=true;
+ continue;
+ }
+ if(v->slack()>=0) {
+ COLA_ASSERT(!v->active);
+ // v was satisfied by the above split!
+ inactive.push_back(v);
+ bs->insert(lb);
+ bs->insert(rb);
+ } else {
+ bs->insert(lb->merge(rb,v));
+ delete ((lb->deleted) ? lb : rb);
+ }
+ }
+#ifdef LIBVPSC_LOGGING
+ f<<"...remaining blocks="<<bs->size()<<", cost="<<bs->cost()<<endl;
+#endif
+ }
+#ifdef LIBVPSC_LOGGING
+ f<<" finished merges."<<endl;
+#endif
+ bs->cleanup();
+ bool activeConstraints=false;
+ for(unsigned i=0;i<m;i++) {
+ v=cs[i];
+ if(v->active) activeConstraints=true;
+ if(v->slack() < ZERO_UPPERBOUND) {
+ ostringstream s;
+ s<<"Unsatisfied constraint: "<<*v;
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<s.str()<<endl;
+#endif
+ throw (char *) s.str().c_str();
+ }
+ }
+#ifdef LIBVPSC_LOGGING
+ f<<" finished cleanup."<<endl;
+ printBlocks();
+#endif
+ copyResult();
+ return activeConstraints;
+}
+void IncSolver::moveBlocks() {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f<<"moveBlocks()..."<<endl;
+#endif
+ size_t length = bs->size();
+ for (size_t i = 0; i < length; ++i)
+ {
+ Block *b = bs->at(i);
+ b->updateWeightedPosition();
+ //b->posn = b->wposn / b->weight;
+ }
+#ifdef LIBVPSC_LOGGING
+ f<<" moved blocks."<<endl;
+#endif
+}
+void IncSolver::splitBlocks() {
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+#endif
+ moveBlocks();
+ splitCnt=0;
+ // Split each block if necessary on min LM
+ size_t length = bs->size();
+ for (size_t i = 0; i < length; ++i)
+ {
+ Block *b = bs->at(i);
+ Constraint* v=b->findMinLM();
+ if(v!=nullptr && v->lm < LAGRANGIAN_TOLERANCE) {
+ COLA_ASSERT(!v->equality);
+#ifdef LIBVPSC_LOGGING
+ f<<" found split point: "<<*v<<" lm="<<v->lm<<endl;
+#endif
+ splitCnt++;
+ Block *b = v->left->block, *l=nullptr, *r=nullptr;
+ COLA_ASSERT(v->left->block == v->right->block);
+ //double pos = b->posn;
+ b->split(l,r,v);
+ //l->posn=r->posn=pos;
+ //l->wposn = l->posn * l->weight;
+ //r->wposn = r->posn * r->weight;
+ l->updateWeightedPosition();
+ r->updateWeightedPosition();
+ bs->insert(l);
+ bs->insert(r);
+ b->deleted=true;
+ COLA_ASSERT(!v->active);
+ inactive.push_back(v);
+#ifdef LIBVPSC_LOGGING
+ f<<" new blocks: "<<*l<<" and "<<*r<<endl;
+#endif
+ }
+ }
+ //if(splitCnt>0) { std::cout<<" splits: "<<splitCnt<<endl; }
+#ifdef LIBVPSC_LOGGING
+ f<<" finished splits."<<endl;
+#endif
+ bs->cleanup();
+}
+
+/**
+ * Scan constraint list for the most violated constraint, or the first equality
+ * constraint
+ */
+Constraint* IncSolver::mostViolated(Constraints &l)
+{
+ double slackForMostViolated = DBL_MAX;
+ Constraint* mostViolated = nullptr;
+#ifdef LIBVPSC_LOGGING
+ ofstream f(LOGFILE,ios::app);
+ f << "Looking for most violated..." << endl;
+#endif
+ size_t lSize = l.size();
+ size_t deleteIndex = lSize;
+ Constraint *constraint = nullptr;
+ double slack = 0;
+ for (size_t index = 0; index < lSize; ++index)
+ {
+ constraint = l[index];
+ slack = constraint->slack();
+ if (constraint->equality || slack < slackForMostViolated)
+ {
+ slackForMostViolated = slack;
+ mostViolated = constraint;
+ deleteIndex = index;
+ if (constraint->equality)
+ {
+ break;
+ }
+ }
+ }
+ // Because the constraint list is not order dependent we just
+ // move the last element over the deletePoint and resize
+ // downwards. There is always at least 1 element in the
+ // vector because of search.
+ if ( (deleteIndex < lSize) &&
+ (((slackForMostViolated < ZERO_UPPERBOUND) && !mostViolated->active) ||
+ mostViolated->equality) )
+ {
+ l[deleteIndex] = l[lSize-1];
+ l.resize(lSize-1);
+ }
+#ifdef LIBVPSC_LOGGING
+ if (mostViolated)
+ {
+ f << " most violated is: " << *mostViolated << endl;
+ }
+ else
+ {
+ f << " non found." << endl;
+ }
+#endif
+ return mostViolated;
+}
+
+struct node {
+ set<node*> in;
+ set<node*> out;
+};
+// useful in debugging - cycles would be BAD
+bool Solver::constraintGraphIsCyclic(const unsigned n, Variable* const vs[]) {
+ map<Variable*, node*> varmap;
+ vector<node*> graph;
+ for(unsigned i=0;i<n;i++) {
+ node *u=new node;
+ graph.push_back(u);
+ varmap[vs[i]]=u;
+ }
+ for(unsigned i=0;i<n;i++) {
+ for(vector<Constraint*>::iterator c=vs[i]->in.begin();c!=vs[i]->in.end();++c) {
+ Variable *l=(*c)->left;
+ varmap[vs[i]]->in.insert(varmap[l]);
+ }
+
+ for(vector<Constraint*>::iterator c=vs[i]->out.begin();c!=vs[i]->out.end();++c) {
+ Variable *r=(*c)->right;
+ varmap[vs[i]]->out.insert(varmap[r]);
+ }
+ }
+ while(graph.size()>0) {
+ node *u=nullptr;
+ vector<node*>::iterator i=graph.begin();
+ for(;i!=graph.end();++i) {
+ u=*i;
+ if(u->in.size()==0) {
+ break;
+ }
+ }
+ if(i==graph.end() && graph.size()>0) {
+ //cycle found!
+ return true;
+ } else {
+ graph.erase(i);
+ for(set<node*>::iterator j=u->out.begin();j!=u->out.end();++j) {
+ node *v=*j;
+ v->in.erase(u);
+ }
+ delete u;
+ }
+ }
+ for(unsigned i=0; i<graph.size(); ++i) {
+ delete graph[i];
+ }
+ return false;
+}
+
+// useful in debugging - cycles would be BAD
+bool Solver::blockGraphIsCyclic() {
+ map<Block*, node*> bmap;
+ vector<node*> graph;
+ size_t length = bs->size();
+ for (size_t i = 0; i < length; ++i)
+ {
+ Block *b = bs->at(i);
+ node *u=new node;
+ graph.push_back(u);
+ bmap[b]=u;
+ }
+ for (size_t i = 0; i < length; ++i)
+ {
+ Block *b = bs->at(i);
+ b->setUpInConstraints();
+ Constraint *c=b->findMinInConstraint();
+ while(c!=nullptr) {
+ Block *l=c->left->block;
+ bmap[b]->in.insert(bmap[l]);
+ b->deleteMinInConstraint();
+ c=b->findMinInConstraint();
+ }
+
+ b->setUpOutConstraints();
+ c=b->findMinOutConstraint();
+ while(c!=nullptr) {
+ Block *r=c->right->block;
+ bmap[b]->out.insert(bmap[r]);
+ b->deleteMinOutConstraint();
+ c=b->findMinOutConstraint();
+ }
+ }
+ while(graph.size()>0) {
+ node *u=nullptr;
+ vector<node*>::iterator i=graph.begin();
+ for(;i!=graph.end();++i) {
+ u=*i;
+ if(u->in.size()==0) {
+ break;
+ }
+ }
+ if(i==graph.end() && graph.size()>0) {
+ //cycle found!
+ return true;
+ } else {
+ graph.erase(i);
+ for(set<node*>::iterator j=u->out.begin();j!=u->out.end();++j) {
+ node *v=*j;
+ v->in.erase(u);
+ }
+ delete u;
+ }
+ }
+ for(unsigned i=0; i<graph.size(); i++) {
+ delete graph[i];
+ }
+ return false;
+}
+}
diff --git a/src/3rdparty/adaptagrams/libvpsc/solve_VPSC.h b/src/3rdparty/adaptagrams/libvpsc/solve_VPSC.h
new file mode 100644
index 0000000..5f7713c
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/solve_VPSC.h
@@ -0,0 +1,130 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2005-2013 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+ * Michael Wybrow
+*/
+
+//
+// TODO: Really, we should have three classes: VPSC, IncrementalVPSC and
+// StaticVPSC, where the latter two inherit from VPSC. StaticVPSC would be
+// the equivalent of what is currently VPSC.
+// Also, a lot of the code specific to one or other of these concrete
+// implementations should be moved from Block and Blocks: e.g. mergeLeft etc.
+//
+#ifndef VPSC_SOLVE_VPSC_H
+#define VPSC_SOLVE_VPSC_H
+
+#include <vector>
+
+/**
+ * @namespace vpsc
+ * @brief libvpsc: Variable Placement with Separation Constraints
+ * quadratic program solver library.
+ *
+ * You should use VPSC via an instance of the IncSolver or Solver classes.
+ */
+namespace vpsc {
+class Variable;
+typedef std::vector<Variable*> Variables;
+class Constraint;
+class Blocks;
+typedef std::vector<Constraint*> Constraints;
+
+/**
+ * @brief Static solver for Variable Placement with Separation Constraints
+ * problem instance
+ *
+ * This class attempts to solve a least-squares problem subject to a set
+ * of separation constraints. The solve() and satisfy() methods return true
+ * if any constraints are active, in both cases false means an unconstrained
+ * optimum has been found.
+ *
+ * @sa IncSolver
+ */
+class Solver {
+public:
+ //! @brief Results in an approximate solution subject to the constraints.
+ //! @return true if any constraints are active, or false if an unconstrained
+ //! optimum has been found.
+ virtual bool satisfy();
+ //! @brief Results in an optimum solution subject to the constraints
+ //! @return true if any constraints are active, or false if an unconstrained
+ //! optimum has been found.
+ virtual bool solve();
+
+ Solver(Variables const &vs, Constraints const &cs);
+ virtual ~Solver();
+ //! @brief Returns the Variables in this problem instance.
+ //! @returns A vector of Variable objects.
+ Variables const & getVariables() { return vs; }
+protected:
+ Blocks *bs;
+ size_t m;
+ std::vector<Constraint*> const &cs;
+ size_t n;
+ std::vector<Variable*> const &vs;
+ bool needsScaling;
+
+ void printBlocks();
+ void copyResult();
+private:
+ void refine();
+ bool constraintGraphIsCyclic(const unsigned n, Variable* const vs[]);
+ bool blockGraphIsCyclic();
+};
+
+/**
+ * @brief Incremental solver for Variable Placement with Separation Constraints
+ * problem instance
+ *
+ * This class attempts to solve a least-squares problem subject to a set
+ * of sepation constraints. The solve() and satisfy() methods return true
+ * if any constraints are active, in both cases false means an unconstrained
+ * optimum has been found. This is an incremental version of that allows
+ * refinement after blocks are moved. This version is preferred if you are
+ * using VPSC in an interactive context.
+ *
+ * @sa Solver
+ */
+class IncSolver : public Solver {
+public:
+ IncSolver(Variables const &vs, Constraints const &cs);
+ //! @brief Results in an approximate solution subject to the constraints.
+ //! @return true if any constraints are active, or false if an unconstrained
+ bool satisfy();
+ //! @brief Results in an optimum solution subject to the constraints
+ //! @return true if any constraints are active, or false if an unconstrained
+ //! optimum has been found.
+ bool solve();
+ //! @brief Adds a constraint to the existing VPSC solver.
+ //!
+ //! @param constraint The new additional constraint to add.
+ void addConstraint(Constraint *constraint);
+private:
+ void moveBlocks();
+ void splitBlocks();
+
+ unsigned splitCnt;
+ Constraints inactive;
+ Constraints violated;
+ Constraint* mostViolated(Constraints &l);
+};
+
+}
+#endif // VPSC_SOLVE_VPSC_H
diff --git a/src/3rdparty/adaptagrams/libvpsc/tests/Makefile.am b/src/3rdparty/adaptagrams/libvpsc/tests/Makefile.am
new file mode 100644
index 0000000..d155c52
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/tests/Makefile.am
@@ -0,0 +1,15 @@
+AM_CPPFLAGS = -I$(top_srcdir)
+
+check_PROGRAMS = rectangleoverlap block satisfy_inc # cycle
+satisfy_inc_SOURCES = satisfy_inc.cpp
+satisfy_inc_LDADD = $(top_builddir)/libvpsc/libvpsc.la # -L$(mosek_home)/bin -lmosek -lguide -limf -lirc
+block_SOURCES = block.cpp
+block_LDADD = $(top_builddir)/libvpsc/libvpsc.la
+rectangleoverlap_SOURCES = rectangleoverlap.cpp
+rectangleoverlap_LDADD = $(top_builddir)/libvpsc/libvpsc.la
+
+#cycle_SOURCES = cycle.cpp
+#cycle_LDADD = $(top_builddir)/libvpsc/libvpsc.la
+
+TESTS = $(check_PROGRAMS)
+
diff --git a/src/3rdparty/adaptagrams/libvpsc/tests/block.cpp b/src/3rdparty/adaptagrams/libvpsc/tests/block.cpp
new file mode 100644
index 0000000..08080e9
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/tests/block.cpp
@@ -0,0 +1,105 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2005-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+#include <cassert>
+#include <iostream>
+
+#include "libvpsc/variable.h"
+#include "libvpsc/constraint.h"
+#include "libvpsc/blocks.h"
+#include "libvpsc/block.h"
+using namespace std;
+using namespace vpsc;
+
+
+void test1() {
+ Blocks *blocks = new Blocks(Variables());
+ cout << "Block test 1..." << endl;
+ Variable *a1=new Variable(1,0,1);
+ Variable *a2=new Variable(2,0,1);
+ Constraint *c=new Constraint(a1,a2,1);
+ a1->out.push_back(c);
+ a2->in.push_back(c);
+ Block *b1=new Block(blocks, a1);
+ Block *b2=new Block(blocks, a2);
+ b1->merge(b2,c);
+ cout << "Block: " << *b1 << endl;
+ a1->desiredPosition = -1;
+ a2->desiredPosition = 2;
+ Constraint *m = b1->findMinLMBetween(a1,a2);
+ cout << "Min lm constraint: " << *m << endl;
+ assert(c==m);
+ cout << " lm=" << c->lm << endl;
+ cout << "Block test 1... Success!" << endl;
+}
+
+/*
+ * Constraint tree:
+ * \_/
+ * / \
+ */
+void test2() {
+ Blocks *blocks = new Blocks(Variables());
+ cout << "Block test 2..." << endl;
+ Variable *a[]={
+ new Variable(0,0,1),
+ new Variable(1,0,1),
+ new Variable(2,1,1),
+ new Variable(3,2,1),
+ new Variable(4,3,1),
+ new Variable(5,3,1)};
+ Constraint *c[]={
+ new Constraint(a[0],a[2],2),
+ new Constraint(a[1],a[2],2),
+ new Constraint(a[2],a[3],2),
+ new Constraint(a[3],a[4],2),
+ new Constraint(a[3],a[5],2)};
+ for(int i=0;i<6;i++) {
+ new Block(blocks,a[i]);
+ }
+ for(int i=0;i<5;i++) {
+ c[i]->left->out.push_back(c[i]);
+ c[i]->right->in.push_back(c[i]);
+ }
+ for(int i=0;i<5;i++) {
+ Block *l=c[i]->left->block, *r=c[i]->right->block;
+ l->merge(r,c[i]);
+ }
+ Block *b=a[0]->block;
+ cout << "Block: " << *b << endl;
+ for(int i=0;i<6;i++) {
+ a[i]->desiredPosition = i!=4?-2:5;
+ }
+ cout << "calc min lm:" << endl;
+ Constraint *m = b->findMinLMBetween(a[0],a[4]);
+ cout << "Min lm constraint: " << *m << endl;
+ assert(m==c[3]);
+ cout << "Block test 2... Success!" << endl;
+}
+int main() {
+ test1();
+ test2();
+ return 0;
+}
diff --git a/src/3rdparty/adaptagrams/libvpsc/tests/cycle.cpp b/src/3rdparty/adaptagrams/libvpsc/tests/cycle.cpp
new file mode 100644
index 0000000..26dda3a
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/tests/cycle.cpp
@@ -0,0 +1,106 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2005-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+#include <iostream>
+#include <cassert>
+#include <cmath>
+#include <algorithm>
+#include <libvpsc/rectangle.h>
+#include <libvpsc/variable.h>
+#include <libvpsc/constraint.h>
+#include <libvpsc/solve_VPSC.h>
+using namespace std;
+using namespace vpsc;
+inline bool approxEquals(const double a, const double b) {
+ return fabs((double)a-b)<0.0001;
+}
+void test1() {
+ cout << "Test 1..." << endl;
+ vector<Variable*> a;
+ a.push_back(new Variable(0,0,1));
+ a.push_back(new Variable(1,1,1));
+ vector<Constraint*> c;
+ c.push_back(new Constraint(a[0],a[1],2));
+ c.push_back(new Constraint(a[1],a[0],2));
+ double expected[]={1.5,-0.5};
+ try {
+ IncSolver vpsc(a,c);
+ vpsc.solve();
+ } catch (UnsatisfiableException& e) {
+ cerr << "Unsatisfiable" << endl;
+ for(vector<Constraint*>::iterator i=e.path.begin();
+ i!=e.path.end();i++) {
+ cout << **i << endl;
+ }
+ exit(1);
+ }
+ //catch(...) {
+ //cerr << "Unknown error!" << endl;
+ //exit(1);
+ //}
+
+ for(size_t i=0;i<a.size();i++) {
+ assert(approxEquals(a[i]->finalPosition,expected[i]));
+ }
+ for_each(a.begin(),a.end(),delete_object());
+ for_each(c.begin(),c.end(),delete_object());
+ cout << "Test 1... done." << endl;
+}
+void test2() {
+ cout << "Test 2..." << endl;
+ vector<Variable *> a;
+ a.push_back(new Variable(0,8,1));
+ a.push_back(new Variable(1,5,1));
+ a.push_back(new Variable(2,3,1));
+ a.push_back(new Variable(3,1,1));
+ vector<Constraint*> c;
+ c.push_back(new Constraint(a[0],a[3],3));
+ c.push_back(new Constraint(a[0],a[1],3));
+ c.push_back(new Constraint(a[1],a[3],3));
+ c.push_back(new Constraint(a[1],a[2],3));
+ c.push_back(new Constraint(a[2],a[3],3));
+ c.push_back(new Constraint(a[2],a[3],3));
+ //double expected[]={-3.71429,4,1,-0.714286,2.28571,2.28571,7,5.28571,8.28571,11.2857};
+ try {
+ IncSolver vpsc(a,c);
+ vpsc.solve();
+ } catch (char const *msg) {
+ cerr << msg << endl;
+ exit(1);
+ }
+
+ /*
+ for(int i=0;i<n;i++) {
+ assert(approxEquals(a[i]->position(),expected[i]));
+ }
+ */
+ cout << "Test 2... done." << endl;
+ for_each(a.begin(),a.end(),delete_object());
+ for_each(c.begin(),c.end(),delete_object());
+}
+int main() {
+ test1();
+ return 0;
+}
diff --git a/src/3rdparty/adaptagrams/libvpsc/tests/rectangleoverlap.cpp b/src/3rdparty/adaptagrams/libvpsc/tests/rectangleoverlap.cpp
new file mode 100644
index 0000000..d8ad72e
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/tests/rectangleoverlap.cpp
@@ -0,0 +1,660 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2005-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+#include <cstdio>
+#include <cassert>
+#include <cstdlib>
+#include <math.h>
+#include <time.h>
+#include <libvpsc/rectangle.h>
+#include <libvpsc/variable.h>
+#include <libvpsc/constraint.h>
+#include <libvpsc/solve_VPSC.h>
+using namespace std;
+using namespace vpsc;
+
+inline double getRand(double range) {
+ return range*rand()/RAND_MAX;
+}
+void printRects(vector<Rectangle*> &rs) {
+ printf("Set of %d rectangles:\n",(int)rs.size());
+ for(unsigned i=0;i<rs.size();++i) {
+ cout << *rs[i] << endl;
+ }
+}
+void generateRandomRects(unsigned n, vector<Rectangle*> &rs) {
+ rs.resize(n);
+ static double const rect_size = 5;
+ static double const min_rect_size = 1e-4;
+ static double const fld_size = sqrt(rect_size * n / 2.0);
+ double coords[4];
+ for (unsigned i = 0; i < n; ++i) {
+ for (unsigned d = 0; d < 2; ++d) {
+ //unsigned const end = 1 + (rand() % (fld_size - 1));
+ //unsigned const start = rand() % end;
+ double const start = getRand(fld_size);
+ double const end = start + min_rect_size
+ + getRand(rect_size);
+ coords[2 * d] = start;
+ coords[2 * d + 1] = end;
+ }
+ rs[i]=new Rectangle(coords[0],coords[1],coords[2],coords[3]);
+ }
+}
+vector<Rectangle*>& generateRects(double coords[][4], unsigned n,vector<Rectangle *>& rs) {
+ rs.resize(n);
+ for (unsigned i = 0; i < n; ++i) {
+ rs[i]=new Rectangle(coords[i][0],coords[i][1],coords[i][2],coords[i][3]);
+ }
+ return rs;
+}
+void test(vector<Rectangle *> &rs, double &cost, double &duration) {
+ unsigned n=rs.size();
+ vector<Rectangle *> ors(n);
+ for (unsigned i = 0; i < n; ++i) {
+ ors[i]=new Rectangle(rs[i]->getMinX(),rs[i]->getMaxX(),rs[i]->getMinY(),rs[i]->getMaxY());
+ }
+
+ clock_t starttime = clock();
+ removeoverlaps(rs);
+ duration = (double)(clock() - starttime)/CLOCKS_PER_SEC;
+ cost = 0;
+ for(unsigned i=0;i<n;i++) {
+ double dx=rs[i]->getCentreX()-ors[i]->getCentreX();
+ double dy=rs[i]->getCentreY()-ors[i]->getCentreY();
+ cost+=sqrt(dx*dx+dy*dy);
+ delete rs[i];
+ delete ors[i];
+ }
+}
+double test1[][4]={ { 0, 50, 0, 30 }, { 10, 20, 10, 29 },
+{ 30, 70, 39, 70 }, { 0, 90, 40, 50 }, { 30, 70, 1, 29 } };
+unsigned n1=5;
+double test2[][4]={ { 7, 22, 39, 54 }, { 7, 33, 0, 59 },
+{ 3, 26, 16, 56 }, { 7, 17, 18, 20 }, { 1, 59, 11, 26 },
+{ 19, 20, 13, 49 }, { 1, 10, 0, 4 }, { 47, 52, 1, 3 } };
+unsigned n2=8;
+double test3[][4]={ { 8, 32, 29, 36 }, { 19, 24, 2, 27 },
+{ 4, 5, 27, 55 }, { 6, 7, 13, 26 }, { 3, 39, 46, 62 },
+{ 6, 23, 2, 19 }, { 18, 39, 5, 23 }, { 35, 63, 42, 78 },
+{ 16, 18, 14, 72 }, { 12, 32, 10, 58 } };
+unsigned n3=10;
+double test4[][4]={ { 315.755, 355.288, 353.595, 449.627 },
+{ 395.048, 395.635, 253.943, 362.228 },
+{ 254.439, 393.289, 278.708, 286.346 },
+{ 209.852, 370.831, 326.496, 507.255 },
+{ 271.947, 415.74, 362.228, 450.318 },
+{ 293.408, 405.197, 220.61, 244.119 },
+{ 276.482, 386.472, 286.346, 435.767 },
+{ 268.211, 436.23, 192.807, 220.61 },
+{ 378.008, 502.118, 358.437, 475.587 },
+{ 340.68, 472.597, 249.492, 335.448 } };
+unsigned n4=10;
+double test5[][4]={ { 7, 22, 39, 54 }, { 7, 33, 0, 59 },
+{ 3, 26, 16, 56 }, { 7, 17, 18, 20 }, { 1, 59, 11, 26 },
+{ 19, 20, 13, 49 }, { 1, 10, 0, 4 }, { 47, 52, 1, 3 } };
+unsigned n5=8;
+double test6[][4]={ { 40, 69, 63, 69 }, { 1, 5, 27, 64 },
+{ 34, 66, 20, 22 }, { 1, 24, 10, 25 }, { 1, 19, 9, 61 },
+{ 0, 56, 8, 70 }, { 33, 35, 13, 28 }, { 11, 31, 33, 35 },
+{ 12, 22, 3, 23 } };
+unsigned n6=9;
+double test7[][4]={ { 341.594, 388.459, 373.491, 518.168 },
+{ 271.214, 324.782, 311.332, 409.166 },
+{ 293.848, 475.064, 305.194, 391.162 },
+{ 255.317, 447.738, 342.671, 489.923 },
+{ 228.375, 261.057, 206.422, 327.794 },
+{ 383.552, 462.834, 363.132, 412.843 },
+{ 288.859, 481.054, 351.895, 497.728 },
+{ 201.307, 368.511, 387.02, 394.95 },
+{ 257.961, 259.673, 386.503, 518.403 },
+{ 200.178, 275.606, 364.968, 466.787 } };
+unsigned n7=10;
+double test8[][4]={{12.807,15.7566,14.9478,16.7924},
+{7.76228,11.6532,4.75249,4.75349},
+{7.84596,10.1387,15.465,16.7709},
+{1.80748,3.0357,5.9983,6.16279},
+{6.46447,7.47249,12.8694,13.4378},
+{14.0026,17.3342,5.10141,9.81088},
+{6.84223,6.85932,6.40395,9.21135},
+{7.63462,10.3552,6.78124,8.59953},
+{0.26429,2.80847,14.5724,17.7455},
+{14.7686,15.7148,3.46036,5.66776},
+{10.635,11.4893,12.5044,16.941},
+{6.32027,10.7117,14.2953,15.6276},
+{11.9942,13.1118,10.6893,11.4477},
+{11.9384,15.1357,2.20982,6.92982},
+{2.89395,4.29002,11.7058,16.2896},
+{9.44116,12.7547,9.75556,11.1811},
+{5.2475,8.00607,15.3652,17.026},
+{2.09541,3.76981,2.5526,3.16739},
+{3.14595,6.66351,10.3007,14.4881},
+{4.88109,9.38044,9.02416,10.2954},
+{7.55378,9.14715,13.9686,16.0468},
+{1.70299,5.42198,14.1913,14.2191},
+{14.4877,14.4897,6.14013,8.50074},
+{12.9909,14.5163,10.322,12.4457},
+{11.616,12.0848,3.7601,5.45419},
+{10.3087,13.358,3.04666,3.53389},
+{2.28263,2.44881,13.806,15.8206},
+{3.31805,5.47662,3.91187,6.85355},
+{0.484138,2.06164,3.57335,7.87753},
+{4.73784,5.12359,9.383,11.9217},
+{12.2921,12.7769,12.329,12.8139},
+{12.7351,16.7141,12.7658,13.78},
+{3.71614,5.79872,1.53137,4.97126},
+{10.7423,14.8183,2.57104,2.94168},
+{9.93995,10.1557,1.3432,1.499},
+{0.198099,0.204966,9.29459,11.8795},
+{14.1043,18.8473,11.2028,14.1971},
+{4.23857,4.95743,14.7047,17.1439},
+{13.936,15.9612,10.7744,14.8598},
+{11.355,15.6824,2.49113,5.96963},
+{12.8528,16.3913,3.82582,6.67259},
+{13.9445,14.7354,10.8576,12.9503},
+{13.0041,15.6166,2.07035,3.70034},
+{2.31809,5.03195,1.13659,5.8604},
+{10.2454,14.5396,10.9442,15.4321},
+{7.12259,11.3929,7.20864,10.4059},
+{6.54862,9.88399,1.82828,5.89899},
+{4.27072,7.52613,7.99016,11.1703},
+{8.84828,9.15453,10.1489,11.7934},
+{7.71027,8.97206,3.26462,4.02636},
+{14.3383,15.1727,3.02586,3.26268},
+{9.21233,11.1919,13.9814,16.1433},
+{13.1946,16.1613,12.2268,13.1319},
+{13.0462,15.6689,7.03513,8.59752},
+{8.72724,11.3859,5.69193,7.8238},
+{10.6241,14.1033,7.88946,9.95327},
+{8.48376,10.8714,8.86955,11.2137},
+{3.55633,4.14351,13.7308,18.4988},
+{1.79802,4.68843,11.0964,11.6543},
+{13.1535,14.6895,1.52144,2.50643},
+{1.24533,4.27261,13.345,13.4925},
+{14.4031,18.7944,15.4447,18.0096},
+{8.56933,11.3392,0.446787,1.18762},
+{11.311,16.0574,8.41,8.76508},
+{13.5332,17.8479,8.2067,11.4446},
+{5.73826,6.63581,10.8364,11.6186},
+{10.1995,11.5202,6.54248,9.49804},
+{14.6456,16.7915,7.01621,7.57531},
+{15.1444,16.4184,1.45761,2.35577},
+{11.8169,12.0382,14.8149,19.3316},
+{10.148,11.1227,15.0087,18.1595},
+{10.9498,14.7849,12.3852,13.9467},
+{10.7631,10.9141,5.24419,8.64319},
+{11.2486,12.6029,6.25029,10.0076},
+{12.8731,16.0703,4.96619,8.54006},
+{6.92828,8.53172,8.36509,11.8971},
+{3.1677,7.20423,14.5582,17.1794},
+{14.1426,16.9327,15.1198,19.1306},
+{2.52943,6.64027,5.18935,8.58545},
+{6.89613,11.4515,3.7672,6.23813},
+{2.91428,6.40636,1.4231,4.10552},
+{9.81892,12.9687,8.25114,10.1775},
+{14.6192,14.7412,10.8349,15.1725},
+{6.96657,11.7009,11.0638,11.8966},
+{7.03182,9.20687,2.04293,2.60462},
+{7.47955,9.28533,7.45213,8.37318},
+{6.24651,9.79246,8.61803,9.91034},
+{4.73642,7.48461,9.59481,12.748},
+{8.70644,11.1702,2.54172,4.26587},
+{14.9028,19.4109,6.238,8.04256},
+{5.22907,8.45899,1.98714,4.94042},
+{8.96884,12.3636,1.72663,3.39844},
+{6.96563,8.04735,10.6198,11.3663},
+{1.65099,5.65883,10.5002,13.9039},
+{11.3337,11.5138,5.31369,7.75029},
+{2.79561,4.08151,7.04269,9.00167}};
+
+unsigned n8=96;
+double test9[][4]={{2.67865,4.81342,8.67025,11.5025},
+{5.77912,6.94355,9.80043,12.2904},
+{11.9459,13.8675,3.66967,7.38408},
+{6.72663,8.30474,3.37566,7.24571},
+{9.2081,10.9827,10.9557,11.8868},
+{0.161903,3.31202,3.35371,3.84933},
+{4.46508,9.18934,9.43037,10.9125},
+{3.84059,5.2565,8.66868,8.70713},
+{4.67598,5.15207,5.2252,8.92099},
+{1.19252,1.31215,7.97481,8.27191},
+{4.57641,5.71063,0.440628,4.17365},
+{6.80268,11.5523,3.78375,4.79819},
+{11.2172,13.7652,8.44876,11.1649},
+{11.4673,13.1644,6.09156,7.41026},
+{12.2995,13.585,0.155239,4.63887},
+{12.3513,15.3947,8.3437,11.1337},
+{3.92566,6.15611,12.432,16.3993},
+{12.6351,14.6039,9.96391,13.1152},
+{0.682894,2.48867,7.66904,8.86704},
+{3.50189,7.28939,8.37741,8.96276},
+{2.37719,4.19762,11.1129,12.0465},
+{5.53568,8.1444,11.9056,15.5818},
+{7.32876,11.2713,12.1655,15.0785},
+{2.534,6.15563,9.30845,11.2833},
+{8.00852,12.8051,2.16786,4.90262},
+{11.8095,12.814,11.5818,13.7731},
+{7.54398,9.23043,7.36953,10.7315},
+{8.36918,9.83071,11.8668,11.8776},
+{5.72267,9.66642,1.46379,3.71362},
+{11.2725,14.6538,4.76772,7.30304},
+{5.8638,10.7623,5.99865,10.0994},
+{11.0224,12.6455,0.852638,2.20201},
+{4.03151,8.51056,6.12449,10.3672},
+{7.75136,10.6782,10.648,11.8606},
+{11.9663,14.3993,2.83154,5.46437},
+{6.05275,8.00044,10.9675,15.3426},
+{10.9702,13.146,8.98465,12.4718},
+{4.99665,7.91376,9.19241,9.71153},
+{3.7422,4.00542,2.00556,2.53918},
+{9.01679,10.9439,12.8107,15.1367},
+{10.0117,11.5009,0.194049,3.08568},
+{8.29117,13.1323,6.99045,8.65707},
+{5.97395,10.5816,5.77559,7.35126},
+{5.68856,6.51699,4.40392,5.82242},
+{0.209729,3.89072,7.36013,8.98447},
+{0.360264,1.88558,0.319886,3.22738},
+{2.02163,2.07428,3.2753,8.12958},
+{5.05075,5.86987,12.7958,16.7689},
+{10.6484,15.5931,7.23546,10.4741},
+{7.20998,7.46939,2.44384,5.10459},
+{12.5022,15.1819,10.6593,13.5708},
+{2.3619,2.45407,5.75168,7.28966},
+{12.131,16.661,4.39608,8.19289},
+{9.81023,10.731,6.67919,9.31523},
+{6.97712,10.166,8.4813,13.3432},
+{6.45378,7.44457,8.96504,11.9806},
+{8.70396,11.5729,7.15588,12.1524},
+{9.93058,14.0306,0.849502,1.80855},
+{8.32174,8.34616,7.52595,12.0431},
+{2.79979,5.93358,4.90296,7.6893},
+{0.72484,5.42439,3.48229,5.77743},
+{6.05275,10.2779,7.4252,7.72184},
+{4.41176,6.91184,11.8809,15.3923},
+{6.50435,8.04432,11.4826,15.3172},
+{12.16,14.3518,1.13763,4.17255},
+{7.82506,10.5124,8.05713,9.03876}};
+unsigned n9=66;
+double test10[][4]={{15.9875,18.9768,15.3193,17.9811},
+{16.5669,19.7216,1.05824,1.58667},
+{8.80629,9.88527,9.71101,13.2142},
+{19.568,20.1767,3.28922,8.03561},
+{13.6363,15.6827,12.9329,16.6542},
+{2.32913,3.58085,8.28597,12.6503},
+{6.86597,11.2847,5.9172,10.236},
+{8.57413,11.0048,18.0203,18.4095},
+{7.68828,8.89193,9.52038,12.3945},
+{13.5784,15.499,0.824193,4.7533},
+{5.70392,8.26946,10.1955,12.8184},
+{17.9857,22.6483,14.2013,16.0377},
+{14.7965,16.4222,11.9332,16.5984},
+{20.5111,23.1383,0.355473,0.834461},
+{5.88763,9.2761,8.31995,11.6173},
+{13.8307,16.6334,17.2376,19.8715},
+{7.20005,8.99179,19.0137,23.483},
+{3.67112,6.97933,18.6142,21.1208},
+{0.936183,5.81945,5.11063,7.47703},
+{9.85383,12.4861,7.80027,11.677},
+{8.07584,11.1964,13.8571,17.9736},
+{8.07017,10.0661,8.42816,9.79417},
+{10.8259,11.6232,16.7028,19.3248},
+{18.55,19.3911,17.174,22.0082},
+{1.34073,1.93538,17.9341,20.4509},
+{11.7558,12.1994,0.295703,2.19289},
+{12.4063,13.662,0.965124,5.21391},
+{2.2033,2.85518,16.4455,20.0191},
+{6.3853,9.77239,0.892142,2.17773},
+{0.546736,5.29679,12.1949,15.2469},
+{14.1365,17.5213,14.7027,15.1512},
+{9.46879,11.9145,11.8539,14.4408},
+{8.49611,8.98075,17.1388,17.5066},
+{1.53577,2.52014,0.615943,4.13396},
+{7.12078,9.05901,20.3739,23.44},
+{2.7104,7.09713,16.4442,20.8587},
+{12.9707,14.2845,12.5642,16.2281},
+{13.5086,14.3207,17.7611,20.1056},
+{19.2264,24.1481,2.063,5.27645},
+{15.2016,18.2491,1.10228,3.37286},
+{16.7733,18.1385,2.35807,7.0123},
+{19.8272,21.9464,18.27,22.8376},
+{4.27133,8.48869,19.5925,21.488},
+{19.6951,23.7284,10.5207,11.1889},
+{0.799027,3.61863,1.42504,3.44902},
+{1.31871,5.95584,16.4147,18.2479},
+{19.8398,21.0495,15.2495,15.8842},
+{3.15773,5.76599,11.1562,12.2007},
+{4.61422,4.78559,16.6607,16.9497},
+{11.0064,11.5745,16.521,19.5463},
+{13.3865,15.7969,12.215,14.3112},
+{0.272424,4.59201,7.19502,9.58004},
+{15.6377,16.4926,18.5978,19.0178},
+{1.44957,1.65985,5.24023,10.1284},
+{0.0559948,0.138395,3.75354,4.46554},
+{3.24015,3.86196,12.205,14.0543},
+{2.64686,3.51587,16.1429,16.6103},
+{2.56003,5.14236,5.6624,8.31491},
+{13.7143,16.5806,7.32777,10.6354},
+{15.8994,20.4036,0.171759,0.567584},
+{11.1247,11.5263,7.61341,8.80042},
+{10.7869,11.8353,7.73861,8.39933},
+{16.7563,18.1604,15.6377,20.3633},
+{4.7627,5.87556,0.850618,4.25755},
+{11.2178,15.6734,14.2378,15.9026},
+{2.00323,5.94744,1.78428,4.77571},
+{16.0705,20.0359,9.50528,12.9563},
+{14.9808,18.3586,9.56819,10.8817},
+{13.7005,17.173,10.5755,15.5172},
+{6.24185,6.44174,11.9766,16.0609},
+{14.0767,16.1476,11.9904,14.2274},
+{18.3009,20.9378,0.109473,0.330122},
+{0.395109,4.35458,19.8694,23.5078},
+{17.4949,22.4626,6.16132,10.5268},
+{0.992178,2.11099,18.813,22.5419},
+{8.41369,12.6754,20.0682,22.6},
+{19.5239,23.6359,3.22945,3.81068},
+{6.60361,6.84761,11.8174,12.6899},
+{8.95351,9.96275,11.2373,12.3269},
+{13.8414,17.1229,18.182,20.7568},
+{13.0468,17.4872,16.8349,21.2615},
+{16.6053,17.1026,5.24778,8.1272},
+{1.20043,2.96974,10.1904,13.8153},
+{7.73924,7.74809,1.53703,3.76274},
+{15.0915,18.4866,18.6576,18.9426},
+{10.69,13.9811,6.92511,9.44625},
+{8.66032,12.8382,6.67974,9.08735},
+{3.24707,3.91176,7.21641,8.75134},
+{20.5281,23.518,5.04016,5.38868},
+{8.78238,13.6922,11.9149,12.334},
+{19.1358,19.5264,15.9157,16.8192},
+{4.52551,7.52884,12.1049,16.4566},
+{18.467,22.8957,2.97024,7.48362},
+{17.9618,18.9449,2.7601,4.06645},
+{10.8057,15.3718,7.7254,8.32173},
+{19.6416,21.5781,7.62473,11.5731},
+{5.14712,8.87694,0.495145,1.50088},
+{4.11719,6.22953,3.59814,8.25023},
+{6.34314,9.83141,1.90886,3.52039},
+{11.6041,11.7642,12.6177,16.2647},
+{17.4351,19.786,0.846214,2.85357},
+{7.90974,12.4031,10.5818,10.868},
+{3.33578,5.53021,19.271,22.6137},
+{14.3296,18.1074,3.76864,6.21134},
+{1.39798,4.21194,14.7015,18.9814},
+{13.3463,13.89,4.76333,8.78979},
+{7.78517,12.3834,12.0445,12.1204},
+{1.21553,4.14149,10.9523,11.5827},
+{10.7328,15.0635,11.2248,16.0148},
+{1.89816,6.42421,6.21479,9.51491},
+{5.76369,9.87896,0.471237,2.08597},
+{1.10543,3.50571,6.4243,6.85217},
+{13.4916,16.9187,13.4167,14.751},
+{6.61683,9.79075,4.44435,7.2165},
+{17.5276,21.8159,3.22316,7.12862},
+{8.09408,10.3727,0.167984,1.77021},
+{8.04815,12.6168,7.91666,11.0816},
+{1.32248,2.63905,12.5164,17.4845},
+{7.324,11.7358,9.05354,13.7152},
+{15.0274,18.5751,11.55,13.6444},
+{15.3627,16.1478,19.7391,21.3528},
+{16.5701,19.0741,18.0876,18.9877},
+{19.9719,20.1289,10.2999,14.2899},
+{5.77124,9.49847,20.3551,23.9988},
+{9.4065,13.7029,1.45775,2.17524},
+{8.22117,12.8533,16.9079,17.5996},
+{8.20293,12.4012,15.7691,15.783},
+{9.33037,11.8253,0.286895,2.70091},
+{12.5114,14.6471,11.0241,13.8678},
+{14.6423,15.2091,5.08987,9.29257},
+{10.4729,12.308,1.7717,6.27227},
+{9.65187,11.9638,14.3196,18.937},
+{5.1704,6.94718,18.4884,22.8028},
+{4.66015,8.43071,12.6095,14.2635},
+{19.5384,21.1589,7.47562,10.9592},
+{20.3595,24.407,0.804689,2.94465},
+{0.775119,2.53222,1.35017,2.38185},
+{14.1459,18.0717,13.111,17.3643},
+{15.9535,16.9371,3.47482,6.36462},
+{15.1727,17.7769,13.1324,16.2993},
+{17.2678,19.5719,19.2912,23.3942},
+{14.5832,17.1443,19.2559,24.0751},
+{1.57289,3.42857,7.75497,11.9183},
+{2.63994,5.18274,5.84108,8.64802},
+{7.56056,8.51991,0.284378,0.750091},
+{8.4225,12.0985,13.1443,16.5509},
+{12.4397,13.7349,16.1177,21.0089},
+{18.411,22.1179,12.4302,16.1478},
+{16.7343,19.9381,0.87138,4.38391},
+{0.729191,5.0941,0.4316,3.36382},
+{7.96699,10.079,15.0613,19.489},
+{14.4215,16.2705,13.932,15.6623},
+{9.37756,12.4608,12.8857,16.6014},
+{12.0729,12.5163,2.59841,7.39714},
+{7.52658,11.0203,15.2853,19.805},
+{16.0919,20.3462,13.6464,15.1218},
+{6.17075,10.0034,17.5729,21.8258},
+{8.94533,11.0185,7.98461,12.5047},
+{0.249775,1.8787,2.72361,7.6554},
+{11.5167,11.8826,8.7937,10.8008},
+{14.3038,17.8052,19.0873,20.7193},
+{19.7272,24.1131,5.29434,7.64106},
+{19.7624,20.0966,13.2827,17.354},
+{5.58186,7.99298,3.3987,5.8269},
+{19.7479,20.3262,16.1492,17.465},
+{3.25902,6.3684,17.0948,20.9851},
+{12.7549,14.4322,1.40931,6.02218},
+{12.232,13.2567,0.559319,3.07481},
+{0.138414,4.75571,14.9273,18.2745},
+{6.04241,6.23422,9.62104,10.3701}};
+unsigned n10=170;
+double test11[][4]={{2.20847,5.99613,25.7684,29.5065},
+{4.38169,7.14163,-7.79499,-7.42678},
+{17.1816,19.4476,-5.03151,-3.38153},
+{10.6383,11.0169,-0.356332,3.85003},
+{13.3309,15.7634,21.4146,24.0122},
+{17.1354,20.5384,27.9053,29.8839},
+{4.82128,7.88931,4.90792,5.71239},
+{13.1802,14.7891,24.0123,26.5035},
+{9.1468,9.95493,-3.73661,-1.29955},
+{14.4021,17.8989,19.2669,23.5805},
+{3.53936,4.95206,17.2632,19.2913},
+{11.2732,15.3951,10.4298,11.6976},
+{9.82902,13.9892,17.9523,19.9811},
+{10.0265,11.0793,16.4791,17.5196},
+{1.27427,5.64116,7.85316,8.33764},
+{3.70992,7.16293,5.06311,6.98578},
+{9.95501,13.9876,-3.13412,-1.29965},
+{17.6086,21.8963,15.3022,17.9743},
+{2.05607,2.66477,-0.552748,0.286511},
+{12.6971,13.3533,-4.23798,-3.73671},
+{7.7961,11.69,7.35371,11.9837},
+{7.68167,9.93012,1.7933,3.98514},
+{1.2176,2.27018,0.286611,3.17168},
+{4.98578,7.91342,12.8464,16.1781},
+{16.5918,21.3527,4.59687,5.72758},
+{9.12809,9.56481,1.38197,2.061},
+{14.6904,19.1649,-3.38143,-1.21492},
+{11.3046,15.5357,14.6315,17.2819},
+{3.69836,4.52282,5.06311,5.67974},
+{12.2713,13.7058,11.6977,14.6314},
+{0.130993,3.26738,-4.32728,-3.7221},
+{11.4317,12.3544,19.9812,22.2083},
+{10.0298,10.1041,11.1483,12.7055},
+{16.2023,16.7313,1.49517,4.59677},
+{12.4149,15.8265,4.33334,6.45789},
+{17.575,19.9519,12.3124,15.3021},
+{17.0991,22.0233,3.78959,6.02599},
+{3.99216,5.32933,0.583351,0.882127},
+{16.5929,18.003,14.3823,17.6574},
+{13.5273,15.1372,16.4791,20.1285},
+{12.3687,15.2044,6.45799,7.83514},
+{8.04258,9.47375,17.3137,21.5515},
+{7.329,10.9322,7.65703,11.5161},
+{1.98895,2.89459,1.84656,3.17168},
+{0.520521,2.46608,6.71895,10.4866},
+{13.184,16.1474,6.45799,7.30869},
+{2.13915,4.58689,17.2632,19.8192},
+{15.8375,18.2786,15.9558,18.1255},
+{14.7223,16.4109,16.4791,17.3636},
+{4.00206,7.29287,-4.32728,-1.41062},
+{16.6028,18.6157,14.6315,17.1786},
+{3.19495,7.10528,-1.41052,0.583251},
+{1.69626,5.11997,0.326338,1.84646},
+{12.1579,12.759,-0.356332,0.328198},
+{3.51735,7.12098,5.71249,7.85306},
+{0.953512,5.10372,3.17178,5.06301},
+{13.2737,14.3319,18.7924,21.1975},
+{1.46188,5.99876,10.3471,12.8463},
+{8.39195,9.77825,1.66426,2.061},
+{1.81344,5.57851,-3.53802,0.326238},
+{1.31773,2.99152,29.5066,33.3419},
+{5.33625,7.15652,19.4265,19.8527},
+{0.432492,3.44635,7.60608,10.3589},
+{1.60933,2.36115,-1.16144,0.286511},
+{9.27774,10.4284,-1.86525,-1.56998},
+{11.8878,13.7671,-5.11518,-4.23808},
+{10.0073,10.2574,11.282,12.9297},
+{10.5778,11.703,0.629406,0.965262},
+{3.17349,7.96657,16.1782,17.2631},
+{11.2281,13.6998,12.2002,12.4339},
+{13.7166,18.3124,19.2669,21.4145},
+{10.5388,15.0813,0.328298,4.33324},
+{9.05987,12.0136,-1.29945,-0.356432},
+{6.74526,7.05518,-8.26859,-7.79509},
+{17.7736,20.6859,5.72768,8.29825},
+{2.22113,7.1491,21.4284,25.7683},
+{16.1247,17.7842,2.70437,3.3773},
+{8.34023,10.0276,13.9827,18.7779},
+{15.1872,18.2348,17.1787,17.2902},
+{16.5308,17.6299,6.45799,8.71682},
+{5.98601,9.22204,23.2905,26.0581},
+{7.64095,10.7424,18.778,22.0208},
+{15.0585,19.52,17.7993,19.2668},
+{17.646,20.037,0.451228,3.78949},
+{0.0160052,1.94859,4.68464,6.71885},
+{7.29434,9.17489,13.9827,17.3136},
+{17.7896,21.639,6.02609,9.48842},
+{4.43065,8.71164,19.8528,23.2904},
+{16.5231,21.0708,3.3774,4.59677},
+{14.2096,16.0172,17.282,17.9522},
+{8.32648,9.09478,3.98524,7.65693},
+{3.6703,7.6841,0.583351,4.90782},
+{9.90605,10.9591,11.5162,13.1508},
+{14.7669,18.5129,-1.21482,3.3773},
+{3.48104,6.74301,29.5066,30.5551},
+{9.22657,10.4539,-5.59946,-1.29955},
+{8.12181,8.34154,-2.11601,1.66416},
+{4.11375,5.37752,30.5552,34.3283},
+{9.11434,12.5991,8.88212,10.4297},
+{11.3365,14.9133,-8.77796,-4.9549},
+{15.7809,16.0235,-2.30357,0.667869},
+{15.4629,16.7224,4.59687,6.45789},
+{13.3766,16.7042,21.4146,25.1652},
+{7.87643,10.2361,12.8464,13.9826},
+{7.38842,11.7536,11.5162,16.479},
+{5.15799,9.74446,-7.42668,-4.32738},
+{16.0009,16.044,-3.82308,0.667869},
+{15.6318,18.7733,8.71692,11.607},
+{10.7258,12.2305,7.30879,8.88202},
+{8.17133,9.84923,-1.56988,1.38187},
+{3.5179,5.38762,0.583351,5.06301},
+{9.4516,10.8319,22.0209,26.7891},
+{9.94456,11.8221,19.9812,21.2926},
+{5.14479,8.31779,3.92878,7.65693},
+{14.6057,18.2633,0.667969,4.59677},
+{5.62784,8.67939,17.3137,19.4264},
+{10.9244,13.5481,-1.29955,-1.29945},
+{5.76759,6.30746,-3.722,-3.5131},
+{7.13259,9.6258,8.33774,11.5161},
+{1.05144,1.32443,10.359,10.9074},
+{16.4807,19.9127,26.5036,27.9052},
+{5.9629,7.66553,-1.41052,-1.14028},
+{13.6489,16.9728,22.2084,25.5279},
+{2.50777,4.43837,19.8193,21.4283},
+{1.57577,3.7409,15.383,18.2258},
+{17.1816,18.8466,17.2903,17.7992},
+{8.43156,13.0154,-4.9548,-3.13422},
+{1.88827,6.19077,6.98588,10.347},
+{14.73,15.2147,17.9523,18.7923},
+{5.55742,8.69305,2.0611,3.92868}};
+unsigned n11=130;
+double test12[][4]={
+{4.92744,6.6604,4.27234,8.301},
+{1.54924,2.51053,4.48526,9.19033},
+{1.55587,5.56226,-0.660563,3.35611},
+{1.87055,2.251,3.56944,6.75421},
+{1.58179,2.94863,5.24022,8.78858},
+{1.88069,5.98638,3.94188,5.24012},
+{1.81447,5.62383,5.24022,9.22211},
+{4.06842,6.37182,-0.053975,3.94178},
+{4.03643,4.2387,3.35621,3.94178},
+{1.16362,3.67328,0.29063,3.01001},
+};
+unsigned n12=10;
+int main() {
+ double c,t;
+ vector<Rectangle*> rs;
+ cout << "test1" << endl;
+ test(generateRects(test1,n1,rs),c,t);
+ cout << "test2" << endl;
+ test(generateRects(test2,n2,rs),c,t);
+ cout << "test3" << endl;
+ test(generateRects(test3,n3,rs),c,t);
+ cout << "test4" << endl;
+ test(generateRects(test4,n4,rs),c,t);
+ cout << "test5" << endl;
+ test(generateRects(test5,n5,rs),c,t);
+ cout << "test6" << endl;
+ test(generateRects(test6,n6,rs),c,t);
+ cout << "test7" << endl;
+ test(generateRects(test7,n7,rs),c,t);
+ cout << "test8" << endl;
+ test(generateRects(test8,n8,rs),c,t);
+ cout << "test9" << endl;
+ test(generateRects(test9,n9,rs),c,t);
+ cout << "test10" << endl;
+ test(generateRects(test10,n10,rs),c,t);
+ cout << "test11" << endl;
+ test(generateRects(test11,n11,rs),c,t);
+ cout << "test12" << endl;
+ test(generateRects(test12,n12,rs),c,t);
+ int max_size=100, repeats=100,step=10;
+ //srand(time(nullptr));
+ for(int i=10;i<=max_size;i+=step) {
+ //if(i%5==0) cout << i << endl;
+ double disp=0, time=0;
+ for(int repeat=repeats;repeat--;) {
+ vector<Rectangle*> rs;
+ generateRandomRects(i,rs);
+ //printRects(rs);
+ test(rs,c,t);
+ disp+=c;
+ time+=t;
+ }
+ disp/=repeats;
+ time/=repeats;
+ cout << i << "," << time << "," << disp << endl;
+ }
+ return 0;
+}
diff --git a/src/3rdparty/adaptagrams/libvpsc/tests/satisfy_inc.cpp b/src/3rdparty/adaptagrams/libvpsc/tests/satisfy_inc.cpp
new file mode 100644
index 0000000..60aeb09
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/tests/satisfy_inc.cpp
@@ -0,0 +1,666 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2005-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file LICENSE; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+
+#include <libvpsc/rectangle.h>
+#include <libvpsc/variable.h>
+#include <libvpsc/constraint.h>
+#include <libvpsc/solve_VPSC.h>
+#include <algorithm>
+#include <cstdio>
+#include <ctime>
+#include <cmath>
+#include <cassert>
+
+using namespace std;
+using namespace vpsc;
+
+static inline double getRand(const int range) {
+ return (double)range*rand()/(RAND_MAX+1.0);
+}
+inline bool approxEquals(const double a, const double b) {
+ return fabs((double)a-b)<0.01;
+}
+typedef vector<Constraint*> CS;
+
+bool checkResult(unsigned n, Variable *a[], unsigned m, Constraint *c[], double expected[]=nullptr) {
+ std::vector<Variable*> aa(a,a+n);
+ std::vector<Constraint*> cc(c,c+m);
+ IncSolver vpsc(aa,cc);
+ vpsc.solve();
+#ifdef MOSEK_AVAILABLE
+ //printf("Checking with mosek...");
+ MosekEnv* menv = mosek_init_sep_ls(n,c,m);
+ float *b=new float[n];
+ float *x=new float[n];
+ for(unsigned i=0;i<n;i++) {
+ b[i]=a[i]->desiredPosition;
+ }
+ mosek_quad_solve_sep(menv,b,x);
+ mosek_delete(menv);
+#endif
+ for(unsigned i=0;i<n;i++) {
+ char s=',';
+ if(i==n-1) s='\n';
+#ifdef MOSEK_AVAILABLE
+ //printf("%f(%f)%c",a[i]->finalPosition,x[i],s);
+ if(!(approxEquals(a[i]->finalPosition,x[i]))) {
+ return false;
+ }
+ assert(approxEquals(a[i]->finalPosition,x[i]));
+#endif
+ if(expected) assert(approxEquals(a[i]->finalPosition,expected[i]));
+ }
+#ifdef MOSEK_AVAILABLE
+ delete [] b;
+ delete [] x;
+#endif
+ return true;
+}
+void dumpMatlabProblem(unsigned n, Variable *a[], unsigned m, Constraint *c[]){
+ printf("H=2*eye(%d);\n",n);
+ printf("f=-2*[ ");
+ for(unsigned i=0;i<n;i++) {
+ printf("%f ",a[i]->desiredPosition);
+ }
+ printf("];\n");
+ printf("s=[ ");
+ for(unsigned i=0;i<n;i++) {
+ printf("%f ",a[i]->scale);
+ }
+ printf("];\n");
+ printf("C=zeros(%d,%d);\n",m,n);
+ for(unsigned i=0;i<m;i++) {
+ printf("C(%d,[%d %d])=[1 -1];\n",i+1,c[i]->left->id+1,c[i]->right->id+1);
+ }
+ printf("A=C*diag(s);\n");
+ printf("b=[ ");
+ for(unsigned i=0;i<m;i++) {
+ printf("%f ",-1.*c[i]->gap);
+ }
+ printf("];\n");
+ printf("quadprog(H,f,A,b)\n");
+}
+void test1() {
+ cout << "Test 1..." << endl;
+ Variable *a[] = {
+ new Variable(0,2,1,1.),
+ new Variable(1,9,1,1),
+ new Variable(2,9,1,1),
+ new Variable(3,9,1,1),
+ new Variable(4,2,1,1)};
+ Constraint *c[] = {
+ new Constraint(a[0],a[4],3),
+ new Constraint(a[0],a[1],3),
+ new Constraint(a[1],a[2],3),
+ new Constraint(a[2],a[4],3),
+ new Constraint(a[3],a[4],3)};
+ unsigned int n = sizeof(a)/sizeof(Variable*);
+ unsigned int m = sizeof(c)/sizeof(Constraint*);
+ double expected[]={1.4,4.4,7.4,7.4,10.4};
+ checkResult(n,a,m,c,expected);
+ cout << "Test 1... done." << endl;
+}
+void test1a() {
+ cout << "Test 1a..." << endl;
+ /* matlab:
+ H=2*eye(2)
+ f=[0 0]
+ A=[ 2 -1 ]
+ b=[ -2 ]
+ quadprog(H,f,A,b)
+ */
+ Variable *a[] = {
+ new Variable(0,0,1,2.),
+ new Variable(1,0,1,1)};
+ Constraint *c[] = {
+ new Constraint(a[0],a[1],2)};
+ unsigned int n = sizeof(a)/sizeof(Variable*);
+ unsigned int m = sizeof(c)/sizeof(Constraint*);
+ double expected[]={-0.8,0.4};
+ checkResult(n,a,m,c,expected);
+ cout << "Test 1a... done." << endl;
+}
+void test1b() {
+ cout << "Test 1b..." << endl;
+ /* matlab:
+ H=2*eye(2)
+ f=[0 0]
+ A=[ 1 -2 ]
+ b=[ -2 ]
+ quadprog(H,f,A,b)
+ */
+ Variable *a[] = {
+ new Variable(0,0,1,1.),
+ new Variable(1,0,1,2)};
+ Constraint *c[] = {
+ new Constraint(a[0],a[1],2)};
+ unsigned int n = sizeof(a)/sizeof(Variable*);
+ unsigned int m = sizeof(c)/sizeof(Constraint*);
+ double expected[]={-0.4,0.8};
+ checkResult(n,a,m,c,expected);
+ cout << "Test 1b... done." << endl;
+}
+void test1c() {
+ cout << "Test 1c..." << endl;
+ /* matlab:
+ H=2*eye(3)
+ f=-2*[ 1 1 1 ]
+ s=[ 3 2 4 ]
+ C=zeros(2,3)
+ C(1,1:2)=[1 -1]
+ C(2,2:3)=[1 -1]
+ A=C*diag(s)
+ b=[-2 -2 ]
+ quadprog(H,f,A,b)
+ */
+ Variable *a[] = {
+ new Variable(0,1,1,3),
+ new Variable(1,1,1,2),
+ new Variable(2,1,1,4)};
+ Constraint *c[] = {
+ new Constraint(a[0],a[1],2),
+ new Constraint(a[1],a[2],2)};
+ unsigned int n = sizeof(a)/sizeof(Variable*);
+ unsigned int m = sizeof(c)/sizeof(Constraint*);
+ double expected[]={0.2623, 1.3934, 1.1967};
+ checkResult(n,a,m,c,expected);
+ cout << "Test 1c... done." << endl;
+}
+
+// no splits required
+void test2() {
+ cout << "Test 2..." << endl;
+ Variable *a[] = {
+ new Variable(0,4,1),
+ new Variable(1,6,1),
+ new Variable(2,9,1),
+ new Variable(3,2,1),
+ new Variable(4,5,1)};
+ Constraint *c[] = {
+ new Constraint(a[0],a[2],3),
+ new Constraint(a[0],a[3],3),
+ new Constraint(a[1],a[4],3),
+ new Constraint(a[2],a[4],3),
+ new Constraint(a[2],a[3],3),
+ new Constraint(a[3],a[4],3)};
+ double expected[]={0.5,6,3.5,6.5,9.5};
+ unsigned int n = sizeof(a)/sizeof(Variable*);
+ unsigned int m = sizeof(c)/sizeof(Constraint*);
+ checkResult(n,a,m,c,expected);
+ cout << "Test 2... done." << endl;
+}
+
+// split required
+void test3() {
+ /* matlab:
+ H=2*eye(5)
+ f=-2*[ 5 6 7 4 3 ]
+ s=[ 1 1 1 1 1 ]
+ C=zeros(5,5)
+ C(1,[1 5])=[1 -1]
+ C(2,[2 3])=[1 -1]
+ C(3,[3 4])=[1 -1]
+ C(4,[3 5])=[1 -1]
+ C(5,[4 5])=[1 -1]
+ A=C*diag(s)
+ b=-3*ones(5,1)
+ quadprog(H,f,A,b)
+ */
+ cout << "Test 3..." << endl;
+ Variable *a[] = {
+ new Variable(0,5,1),
+ new Variable(1,6,1),
+ new Variable(2,7,1),
+ new Variable(3,4,1),
+ new Variable(4,3,1)};
+ Constraint *c[] = {
+ new Constraint(a[0],a[4],3),
+ new Constraint(a[1],a[2],3),
+ new Constraint(a[2],a[3],3),
+ new Constraint(a[2],a[4],3),
+ new Constraint(a[3],a[4],3)};
+ double expected[]={5,0.5,3.5,6.5,9.5};
+ unsigned int n = sizeof(a)/sizeof(Variable*);
+ unsigned int m = sizeof(c)/sizeof(Constraint*);
+ checkResult(n,a,m,c,expected);
+ cout << "Test 3... done." << endl;
+}
+// split required
+void test4() {
+ /* matlab:
+ H=2*eye(5)
+ f=-2*[ 7 1 6 0 2 ]
+ s=[ 5 8 3 1 7 ]
+ C=zeros(6,5)
+ C(1,[1 4])=[1 -1]
+ C(2,[1 2])=[1 -1]
+ C(3,[2 5])=[1 -1]
+ C(4,[3 5])=[1 -1]
+ C(5,[3 4])=[1 -1]
+ C(6,[4 5])=[1 -1]
+ A=C*diag(s)
+ b=-3*ones(6,1)
+ quadprog(H,f,A,b)
+ */
+ cout << "Test 4..." << endl;
+ Variable *a[] = {
+ new Variable(0,7,1,1),
+ new Variable(1,1,1,1),
+ new Variable(2,6,1,1),
+ new Variable(3,0,1,1),
+ new Variable(4,2,1,1)};
+ Constraint *c[] = {
+ new Constraint(a[0],a[3],3),
+ new Constraint(a[0],a[1],3),
+ new Constraint(a[1],a[4],3),
+ new Constraint(a[2],a[4],3),
+ new Constraint(a[2],a[3],3),
+ new Constraint(a[3],a[4],3)};
+ double expected[]={0.8,3.8,0.8,3.8,6.8};
+ unsigned int n = sizeof(a)/sizeof(Variable*);
+ unsigned int m = sizeof(c)/sizeof(Constraint*);
+ checkResult(n,a,m,c,expected);
+ cout << "Test 4... done." << endl;
+}
+void test5() {
+ cout << "Test 5..." << endl;
+ Variable *a[] = {
+ new Variable(0,0,1), new Variable(1,9,1), new
+ Variable(2,1,1), new Variable(3,9,1), new
+ Variable(4,5,1), new Variable(5,1,1), new
+ Variable(6,2,1), new Variable(7,1,1), new
+ Variable(8,6,1), new Variable(9,3,1)};
+ Constraint *c[] = {
+ new Constraint(a[0],a[3],3), new Constraint(a[1],a[8],3),
+ new Constraint(a[1],a[6],3), new Constraint(a[2],a[6],3),
+ new Constraint(a[3],a[5],3), new Constraint(a[3],a[6],3),
+ new Constraint(a[3],a[7],3), new Constraint(a[4],a[8],3),
+ new Constraint(a[4],a[7],3), new Constraint(a[5],a[8],3),
+ new Constraint(a[5],a[7],3), new Constraint(a[5],a[8],3),
+ new Constraint(a[6],a[9],3), new Constraint(a[7],a[8],3),
+ new Constraint(a[7],a[9],3), new Constraint(a[8],a[9],3)
+ };
+ double expected[]={-3.71429,4,1,-0.714286,2.28571,2.28571,7,5.28571,8.28571,11.2857};
+ unsigned int n = sizeof(a)/sizeof(Variable*);
+ unsigned int m = sizeof(c)/sizeof(Constraint*);
+ checkResult(n,a,m,c,expected);
+ cout << "Test 5... done." << endl;
+}
+void test6() {
+ cout << "Test 6..." << endl;
+ Variable *a[] = {
+ new Variable(0,7,1),
+ new Variable(1,0,1),
+ new Variable(2,3,1),
+ new Variable(3,1,1),
+ new Variable(4,4,1)
+ };
+ Constraint *c[] = {
+ new Constraint(a[0],a[3],3),
+ new Constraint(a[0],a[2],3),
+ new Constraint(a[1],a[4],3),
+ new Constraint(a[1],a[4],3),
+ new Constraint(a[2],a[3],3),
+ new Constraint(a[3],a[4],3)
+ };
+ double expected[]={-0.75,0,2.25,5.25,8.25};
+ unsigned int n = sizeof(a)/sizeof(Variable*);
+ unsigned int m = sizeof(c)/sizeof(Constraint*);
+ checkResult(n,a,m,c,expected);
+ cout << "Test 6... done." << endl;
+}
+void test7() {
+ cout << "Test 7..." << endl;
+ Variable *a[] = {
+ new Variable(0,4,1),
+ new Variable(1,2,1),
+ new Variable(2,3,1),
+ new Variable(3,1,1),
+ new Variable(4,8,1)
+ };
+ Constraint *c[] = {
+ new Constraint(a[0],a[4],3),
+ new Constraint(a[0],a[2],3),
+ new Constraint(a[1],a[3],3),
+ new Constraint(a[2],a[3],3),
+ new Constraint(a[2],a[4],3),
+ new Constraint(a[3],a[4],3)
+ };
+ double expected[]={-0.5,2,2.5,5.5,8.5};
+ unsigned int n = sizeof(a)/sizeof(Variable*);
+ unsigned int m = sizeof(c)/sizeof(Constraint*);
+ checkResult(n,a,m,c,expected);
+ cout << "Test 7... done." << endl;
+}
+void test8() {
+ /* matlab:
+ H=2*eye(5)
+ f=-2*[ 3 4 0 5 6 ]
+ s=[ 1 1 1 1 1 ]
+ C=zeros(6,5)
+ C(1,[1 2])=[1 -1]
+ C(2,[1 3])=[1 -1]
+ C(3,[2 3])=[1 -1]
+ C(4,[2 5])=[1 -1]
+ C(5,[3 4])=[1 -1]
+ C(6,[4 5])=[1 -1]
+ A=C*diag(s)
+ b=-3*ones(6,1)
+ quadprog(H,f,A,b)
+ */
+ // This cycles when using the heuristic of merging on the least
+ // violated, violated constraint first.
+ cout << "Test 8..." << endl;
+ Variable *a[] = {
+ new Variable(0,3,1),
+ new Variable(1,4,1),
+ new Variable(2,0,1),
+ new Variable(3,5,1),
+ new Variable(4,6,1)
+ };
+ Constraint *c[] = {
+ new Constraint(a[0],a[1],3),
+ new Constraint(a[0],a[2],3),
+ new Constraint(a[1],a[2],3),
+ new Constraint(a[1],a[4],3),
+ new Constraint(a[2],a[3],3),
+ new Constraint(a[2],a[3],3),
+ new Constraint(a[3],a[4],3),
+ new Constraint(a[3],a[4],3)
+ };
+ double expected[]={-2.4,0.6,3.6,6.6,9.6};
+ unsigned int n = sizeof(a)/sizeof(Variable*);
+ unsigned int m = sizeof(c)/sizeof(Constraint*);
+ checkResult(n,a,m,c,expected);
+ cout << "Test 8... done." << endl;
+}
+void test9() {
+ /* matlab:
+ H=2*eye(5)
+ f=-2*[ 8 2 6 5 3 ]
+ s=[ 1 1 1 1 1 ]
+ C=zeros(7,5)
+ C(1,[1 5])=[1 -1]
+ C(2,[1 4])=[1 -1]
+ C(3,[2 3])=[1 -1]
+ C(4,[2 5])=[1 -1]
+ C(5,[3 4])=[1 -1]
+ C(6,[3 5])=[1 -1]
+ C(7,[4 5])=[1 -1]
+ A=C*diag(s)
+ b=-3*ones(7,1)
+ quadprog(H,f,A,b)
+ */
+ cout << "Test 9..." << endl;
+ Variable *a[] = {
+ new Variable(0,8,1),
+ new Variable(1,2,1),
+ new Variable(2,6,1),
+ new Variable(3,5,1),
+ new Variable(4,3,1)};
+ Constraint *c[] = {
+ new Constraint(a[0],a[4],3),
+ new Constraint(a[0],a[3],3),
+ new Constraint(a[1],a[2],3),
+ new Constraint(a[1],a[4],3),
+ new Constraint(a[2],a[3],3),
+ new Constraint(a[2],a[4],3),
+ new Constraint(a[3],a[4],3)};
+ double expected[]={3.6,0.6,3.6,6.6,9.6};
+ unsigned int n = sizeof(a)/sizeof(Variable*);
+ unsigned int m = sizeof(c)/sizeof(Constraint*);
+ checkResult(n,a,m,c,expected);
+ cout << "Test 9... done." << endl;
+}
+
+void test10() {
+ cout << "Test 10..." << endl;
+ Variable *a[] = {
+ new Variable(0,8.56215,1,4.99888),
+new Variable(1,1.27641,1,8.06009),
+new Variable(2,6.28523,1,1.06585),
+new Variable(3,4.09743,1,0.924166),
+new Variable(4,0.369025,1,6.12702)};
+
+ Constraint *c[] = {
+ new Constraint(a[0],a[2],3),
+new Constraint(a[0],a[1],3),
+new Constraint(a[0],a[1],3),
+new Constraint(a[1],a[3],3),
+new Constraint(a[1],a[3],3),
+new Constraint(a[1],a[2],3),
+new Constraint(a[2],a[4],3),
+new Constraint(a[2],a[4],3),
+new Constraint(a[3],a[4],3),
+new Constraint(a[3],a[4],3)};
+
+ //double expected[]={-1,2,5,5,8};
+ unsigned int n = sizeof(a)/sizeof(Variable*);
+ unsigned int m = sizeof(c)/sizeof(Constraint*);
+ std::vector<Variable*> aa(a,a+n);
+ std::vector<Constraint*> cc(c,c+m);
+ IncSolver vpsc(aa,cc);
+ vpsc.solve();
+ assert(checkResult(n,a,m,c,nullptr));
+ cout << "Test 10... done." << endl;
+}
+void test11() {
+ cout << "Test 11..." << endl;
+ Variable *a[] = {
+ new Variable(0,1.31591,1,9.02545),
+new Variable(1,1.48155,1,3.68918),
+new Variable(2,3.5091,1,2.07033),
+new Variable(3,3.47131,1,8.75145),
+new Variable(4,0.77374,1,0.967941)};
+
+ Constraint *c[] = {
+new Constraint(a[0],a[3],3),
+new Constraint(a[0],a[1],3),
+new Constraint(a[1],a[4],3),
+new Constraint(a[1],a[2],3),
+new Constraint(a[2],a[4],3),
+new Constraint(a[2],a[4],3),
+new Constraint(a[3],a[4],3),
+new Constraint(a[3],a[4],3)};
+
+ //double expected[]={-1,2,5,5,8};
+ unsigned int n = sizeof(a)/sizeof(Variable*);
+ unsigned int m = sizeof(c)/sizeof(Constraint*);
+ //dumpMatlabProblem(n,a,m,c);
+ std::vector<Variable*> aa(a,a+n);
+ std::vector<Constraint*> cc(c,c+m);
+ IncSolver vpsc(aa,cc);
+ vpsc.solve();
+ assert(checkResult(n,a,m,c,nullptr));
+ cout << "Test 11... done." << endl;
+}
+void test12() {
+ cout << "Test 12..." << endl;
+ Variable *a[] = {
+new Variable(0,2.83063,1,6.67901),
+new Variable(1,6.81696,1,7.28642),
+new Variable(2,9.27616,1,0.918345),
+new Variable(3,3.4094,1,3.39673),
+new Variable(4,2.92492,1,2.36269)};
+
+ Constraint *c[] = {
+new Constraint(a[0],a[3],3),
+new Constraint(a[0],a[2],3),
+new Constraint(a[0],a[1],3),
+new Constraint(a[1],a[4],3),
+new Constraint(a[1],a[4],3),
+new Constraint(a[1],a[4],3),
+new Constraint(a[2],a[4],3),
+new Constraint(a[2],a[4],3),
+new Constraint(a[3],a[4],3),
+new Constraint(a[3],a[4],3),
+new Constraint(a[3],a[4],3),
+new Constraint(a[3],a[4],3)};
+
+ //double expected[]={-1,2,5,5,8};
+ unsigned int n = sizeof(a)/sizeof(Variable*);
+ unsigned int m = sizeof(c)/sizeof(Constraint*);
+ //dumpMatlabProblem(n,a,m,c);
+ assert(checkResult(n,a,m,c,nullptr));
+ cout << "Test 12... done." << endl;
+}
+void test13() {
+ cout << "Test 13..." << endl;
+ Variable *a[] = {
+new Variable(0,0.485024,1,1),
+new Variable(1,3.52714,1,1),
+new Variable(2,4.01263,1,1),
+new Variable(3,4.58524,1,1),
+new Variable(4,5.40796,1,1)};
+
+ Constraint *c[] = {
+new Constraint(a[0],a[4],3),
+new Constraint(a[0],a[4],3),
+new Constraint(a[0],a[4],3),
+new Constraint(a[0],a[2],3),
+new Constraint(a[1],a[3],3),
+new Constraint(a[1],a[3],3),
+new Constraint(a[1],a[2],3),
+new Constraint(a[2],a[4],3),
+new Constraint(a[2],a[4],3),
+new Constraint(a[2],a[4],3),
+new Constraint(a[2],a[3],3),
+new Constraint(a[3],a[4],3),
+new Constraint(a[3],a[4],3),
+new Constraint(a[3],a[4],3)};
+
+ //double expected[]={-1,2,5,5,8};
+ unsigned int n = sizeof(a)/sizeof(Variable*);
+ unsigned int m = sizeof(c)/sizeof(Constraint*);
+ //dumpMatlabProblem(n,a,m,c);
+ assert(checkResult(n,a,m,c,nullptr));
+ cout << "Test 13... done." << endl;
+}
+
+// n=number vars
+// m=max constraints per var
+void rand_test(unsigned n, unsigned m) {
+ Variable **a=new Variable*[n];
+ CS cs;
+ for(unsigned i=0;i<n;i++) {
+ a[i]=new Variable(i,getRand(10),1,1);//getRand(10));
+ }
+ for(unsigned i=0;i<n-1;i++) {
+ for(int j=0;j<getRand(m)+1;j++) {
+ int e = static_cast<int>(i + getRand(n-1-i)+1);
+ cs.push_back(new Constraint(a[i],a[e],3));
+ }
+ }
+ Constraint **acs=new Constraint*[cs.size()];
+ for(unsigned i=0;i<cs.size();i++) {
+ acs[i]=cs[i];
+ }
+ try {
+ if(!checkResult(n,a,cs.size(),acs)) {
+ throw "Check failed!";
+ }
+ } catch (char const *msg) {
+ cout << msg << endl;
+ cout<<"digraph g {"<<endl;
+ for(CS::iterator i(cs.begin());i!=cs.end();i++) {
+ Constraint *c=*i;
+ cout << c->left->id << "->" << c->right->id << ";" << endl;
+ }
+ cout<<"}"<<endl;
+ for(unsigned i=0;i<n;i++) {
+ if(i!=0) cout << "," << endl;
+ cout << "new Variable("<<i<<","<<a[i]->desiredPosition<< ",1,"
+ << a[i]->scale <<")";
+ //cout << "a[i]->Pos="<<a[i]->position() << endl;
+ }
+ cout << "};" << endl;
+ for(CS::iterator i(cs.begin());i!=cs.end();i++) {
+ if(i!=cs.begin()) cout << "," << endl;
+ Constraint *c=*i;
+ //cout << c->left->id << "->" << c->right->id << ";" << endl;
+ cout << "new Constraint(a[" << c->left->id << "],a[" << c->right->id << "],3)";
+
+ }
+ cout << "};" << endl;
+ throw "test failed!";
+ }
+ /*
+ for(unsigned i=0;i<n;i++) {
+ a[i]->desiredPosition=getRand(10);
+ }
+ vpsc.solve();
+ try {
+ if(!checkResult(n,a,m,acs)) {
+ throw "2nd Check failed!";
+ }
+ } catch (char const *msg) {
+ cout << msg << endl;
+ for(unsigned i=0;i<n;i++) {
+ if(i!=0) cout << "," << endl;
+ cout << "new Variable("<<i<<","<<a[i]->desiredPosition<< ",1)";
+ //cout << "a[i]->Pos="<<a[i]->position() << endl;
+ }
+ cout << "};" << endl;
+ for(CS::iterator i(cs.begin());i!=cs.end();i++) {
+ if(i!=cs.begin()) cout << "," << endl;
+ Constraint *c=*i;
+ //cout << c->left->id << "->" << c->right->id << ";" << endl;
+ cout << "new Constraint(a[" << c->left->id << "],a[" << c->right->id << "],3)";
+
+ }
+ cout << "};" << endl;
+ throw "test failed!";
+ }
+ */
+ for_each(a,a+n,delete_object());
+ delete [] a;
+ for_each(cs.begin(),cs.end(),delete_object());
+ delete [] acs;
+}
+int main() {
+ srand(time(nullptr));
+ test10();
+ test2();
+ test3();
+ test4();
+ test5();
+ test6();
+ test7();
+ test8();
+ test9();
+ test10();
+ test11();
+ test12();
+ test13();
+ for(int i=0;i<1000;i++) {
+ if(i%100==0) cout << "i=" << i << endl;
+ rand_test(100,3);
+ }
+ for(int i=0;i<10000;i++) {
+ if(i%100==0) cout << "i=" << i << endl;
+ rand_test(5,3);
+ }
+ return 0;
+}
diff --git a/src/3rdparty/adaptagrams/libvpsc/variable.cpp b/src/3rdparty/adaptagrams/libvpsc/variable.cpp
new file mode 100644
index 0000000..4466c68
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/variable.cpp
@@ -0,0 +1,31 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2005-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+*/
+
+#include "libvpsc/variable.h"
+namespace vpsc {
+std::ostream& operator <<(std::ostream &os, const Variable &v) {
+ if(v.block)
+ os << "(" << v.id << "=" << v.position() << ")";
+ else
+ os << "(" << v.id << "=" << v.desiredPosition << ")";
+ return os;
+}
+}
diff --git a/src/3rdparty/adaptagrams/libvpsc/variable.h b/src/3rdparty/adaptagrams/libvpsc/variable.h
new file mode 100644
index 0000000..aaad753
--- /dev/null
+++ b/src/3rdparty/adaptagrams/libvpsc/variable.h
@@ -0,0 +1,95 @@
+/*
+ * vim: ts=4 sw=4 et tw=0 wm=0
+ *
+ * libvpsc - A solver for the problem of Variable Placement with
+ * Separation Constraints.
+ *
+ * Copyright (C) 2005-2008 Monash University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * See the file LICENSE.LGPL distributed with the library.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Author(s): Tim Dwyer
+*/
+
+#ifndef VPSC_VARIABLE_H
+#define VPSC_VARIABLE_H
+
+#include <vector>
+#include <iostream>
+
+#include "libvpsc/block.h"
+#include "libvpsc/assertions.h"
+
+namespace vpsc {
+
+class Constraint;
+typedef std::vector<Constraint*> Constraints;
+
+/**
+ * @brief A variable is comprised of an ideal position, final position and
+ * a weight.
+ *
+ * When creating a variable you specify an ideal value, and a weight---how
+ * much the variable wants to be at its ideal position. After solving the
+ * problem you can read back the final position for the variable.
+*/
+class Variable
+{
+ friend std::ostream& operator <<(std::ostream &os, const Variable &v);
+ friend class Block;
+ friend class Constraint;
+ friend class Solver;
+public:
+ int id; // useful in log files
+ double desiredPosition;
+ double finalPosition;
+ double weight; // how much the variable wants to
+ // be at it's desired position
+ double scale; // translates variable to another space
+ double offset;
+ Block *block;
+ bool visited;
+ bool fixedDesiredPosition;
+ Constraints in;
+ Constraints out;
+ char *toString();
+ inline Variable(const int id, const double desiredPos=-1.0,
+ const double weight=1.0, const double scale=1.0)
+ : id(id)
+ , desiredPosition(desiredPos)
+ , finalPosition(desiredPos)
+ , weight(weight)
+ , scale(scale)
+ , offset(0)
+ , block(nullptr)
+ , visited(false)
+ , fixedDesiredPosition(false)
+ {
+ }
+ double dfdv(void) const {
+ return 2. * weight * ( position() - desiredPosition );
+ }
+private:
+ inline double position(void) const {
+ return (block->ps.scale*block->posn+offset)/scale;
+ }
+ inline double unscaledPosition(void) const {
+ COLA_ASSERT(block->ps.scale == 1);
+ COLA_ASSERT(scale == 1);
+ return block->posn + offset;
+ }
+};
+
+//! @brief A vector of pointers to Variable objects.
+typedef std::vector<Variable*> Variables;
+
+}
+#endif // VPSC_VARIABLE_H
diff --git a/src/3rdparty/autotrace/CMakeLists.txt b/src/3rdparty/autotrace/CMakeLists.txt
new file mode 100644
index 0000000..97b6445
--- /dev/null
+++ b/src/3rdparty/autotrace/CMakeLists.txt
@@ -0,0 +1,48 @@
+set ( autotrace_SRC
+config.h
+autotrace.c
+autotrace.h
+bitmap.c
+bitmap.h
+CMakeLists.txt
+color.c
+color.h
+curve.c
+curve.h
+despeckle.c
+despeckle.h
+epsilon-equal.c
+epsilon-equal.h
+exception.c
+exception.h
+filename.c
+filename.h
+fit.c
+fit.h
+image-header.h
+image-proc.c
+image-proc.h
+input.c
+input.h
+intl.h
+logreport.c
+logreport.h
+median.c
+module.c
+output.c
+output.h
+private.h
+pxl-outline.c
+pxl-outline.h
+quantize.h
+spline.c
+spline.h
+thin-image.c
+thin-image.h
+types.h
+vector.c
+vector.h
+xstd.h
+)
+
+add_inkscape_lib(autotrace_LIB "${autotrace_SRC}")
diff --git a/src/3rdparty/autotrace/autotrace.c b/src/3rdparty/autotrace/autotrace.c
new file mode 100644
index 0000000..a2b65de
--- /dev/null
+++ b/src/3rdparty/autotrace/autotrace.c
@@ -0,0 +1,386 @@
+/* autotrace.c --- Autotrace API
+
+ Copyright (C) 2000, 2001, 2002 Martin Weber
+
+ The author can be contacted at <martweb@gmx.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* Def: HAVE_CONFIG_H */
+#include "intl.h"
+
+#include "private.h"
+
+#include "autotrace.h"
+#include "exception.h"
+
+#include "fit.h"
+#include "bitmap.h"
+#include "spline.h"
+
+#include "input.h"
+
+#include "xstd.h"
+#include "image-header.h"
+#include "image-proc.h"
+#include "quantize.h"
+#include "thin-image.h"
+#include "despeckle.h"
+
+#include <locale.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define AT_DEFAULT_DPI 72
+
+at_fitting_opts_type *at_fitting_opts_new(void)
+{
+ at_fitting_opts_type *opts;
+ XMALLOC(opts, sizeof(at_fitting_opts_type));
+ *opts = new_fitting_opts();
+ return opts;
+}
+
+at_fitting_opts_type *at_fitting_opts_copy(at_fitting_opts_type * original)
+{
+ at_fitting_opts_type *new_opts;
+ if (original == NULL)
+ return NULL;
+
+ new_opts = at_fitting_opts_new();
+ *new_opts = *original;
+ if (original->background_color)
+ new_opts->background_color = at_color_copy(original->background_color);
+ return new_opts;
+}
+
+void at_fitting_opts_free(at_fitting_opts_type * opts)
+{
+ free(opts->background_color);
+ free(opts);
+}
+
+at_input_opts_type *at_input_opts_new(void)
+{
+ at_input_opts_type *opts;
+ XMALLOC(opts, sizeof(at_input_opts_type));
+ opts->background_color = NULL;
+ opts->charcode = 0;
+ return opts;
+}
+
+at_input_opts_type *at_input_opts_copy(at_input_opts_type * original)
+{
+ at_input_opts_type *opts;
+ opts = at_input_opts_new();
+ *opts = *original;
+ if (original->background_color)
+ opts->background_color = at_color_copy(original->background_color);
+ return opts;
+}
+
+void at_input_opts_free(at_input_opts_type * opts)
+{
+ free(opts->background_color);
+ free(opts);
+}
+
+at_output_opts_type *at_output_opts_new(void)
+{
+ at_output_opts_type *opts;
+ XMALLOC(opts, sizeof(at_output_opts_type));
+ opts->dpi = AT_DEFAULT_DPI;
+ return opts;
+}
+
+at_output_opts_type *at_output_opts_copy(at_output_opts_type * original)
+{
+ at_output_opts_type *opts = at_output_opts_new();
+ *opts = *original;
+ return opts;
+}
+
+void at_output_opts_free(at_output_opts_type * opts)
+{
+ free(opts);
+}
+
+at_bitmap *at_bitmap_read(at_bitmap_reader * reader, gchar * filename, at_input_opts_type * opts, at_msg_func msg_func, gpointer msg_data)
+{
+ gboolean new_opts = FALSE;
+ at_bitmap *bitmap;
+ XMALLOC(bitmap, sizeof(at_bitmap));
+ if (opts == NULL) {
+ opts = at_input_opts_new();
+ new_opts = TRUE;
+ }
+ *bitmap = (*reader->func) (filename, opts, msg_func, msg_data, reader->data);
+ if (new_opts)
+ at_input_opts_free(opts);
+ return bitmap;
+}
+
+at_bitmap *at_bitmap_new(unsigned short width, unsigned short height, unsigned int planes)
+{
+ at_bitmap *bitmap;
+ XMALLOC(bitmap, sizeof(at_bitmap));
+ *bitmap = at_bitmap_init(NULL, width, height, planes);
+ return bitmap;
+}
+
+at_bitmap *at_bitmap_copy(const at_bitmap * src)
+{
+ at_bitmap *dist;
+ unsigned short width, height, planes;
+
+ width = at_bitmap_get_width(src);
+ height = at_bitmap_get_height(src);
+ planes = at_bitmap_get_planes(src);
+
+ dist = at_bitmap_new(width, height, planes);
+ memcpy(dist->bitmap, src->bitmap, width * height * planes * sizeof(unsigned char));
+ return dist;
+}
+
+at_bitmap at_bitmap_init(unsigned char *area, unsigned short width, unsigned short height, unsigned int planes)
+{
+ at_bitmap bitmap;
+
+ if (area)
+ bitmap.bitmap = area;
+ else {
+ if (0 == (width * height))
+ bitmap.bitmap = NULL;
+ else
+ XCALLOC(bitmap.bitmap, width * height * planes * sizeof(unsigned char));
+ }
+
+ bitmap.width = width;
+ bitmap.height = height;
+ bitmap.np = planes;
+ return bitmap;
+}
+
+void at_bitmap_free(at_bitmap * bitmap)
+{
+ free(AT_BITMAP_BITS(bitmap));
+ free(bitmap);
+}
+
+unsigned short at_bitmap_get_width(const at_bitmap * bitmap)
+{
+ return bitmap->width;
+}
+
+unsigned short at_bitmap_get_height(const at_bitmap * bitmap)
+{
+ return bitmap->height;
+}
+
+unsigned short at_bitmap_get_planes(const at_bitmap * bitmap)
+{
+ /* Here we use cast rather changing the type definition of
+ at_bitmap::np to keep binary compatibility. */
+ return (unsigned short)bitmap->np;
+}
+
+void at_bitmap_get_color(const at_bitmap * bitmap, unsigned int row, unsigned int col, at_color * color)
+{
+ unsigned char *p;
+ g_return_if_fail(color);
+ g_return_if_fail(bitmap);
+
+ p = AT_BITMAP_PIXEL(bitmap, row, col);
+ if (at_bitmap_get_planes(bitmap) >= 3)
+ at_color_set(color, p[0], p[1], p[2]);
+ else
+ at_color_set(color, p[0], p[0], p[0]);
+}
+
+gboolean at_bitmap_equal_color(const at_bitmap * bitmap, unsigned int row, unsigned int col, at_color * color)
+{
+ at_color c;
+
+ g_return_val_if_fail(bitmap, FALSE);
+ g_return_val_if_fail(color, FALSE);
+
+ at_bitmap_get_color(bitmap, row, col, &c);
+ return at_color_equal(&c, color);
+}
+
+at_splines_type *at_splines_new(at_bitmap * bitmap, at_fitting_opts_type * opts, at_msg_func msg_func, gpointer msg_data)
+{
+ return at_splines_new_full(bitmap, opts, msg_func, msg_data, NULL, NULL, NULL, NULL);
+}
+
+/* at_splines_new_full modify its argument: BITMAP
+ when despeckle, quantize and/or thin_image are invoked. */
+at_splines_type *at_splines_new_full(at_bitmap * bitmap, at_fitting_opts_type * opts, at_msg_func msg_func, gpointer msg_data, at_progress_func notify_progress, gpointer progress_data, at_testcancel_func test_cancel, gpointer testcancel_data)
+{
+ image_header_type image_header;
+ at_splines_type *splines = NULL;
+ pixel_outline_list_type pixels;
+ QuantizeObj *myQuant = NULL; /* curently not used */
+ at_exception_type exp = at_exception_new(msg_func, msg_data);
+ at_distance_map dist_map, *dist = NULL;
+
+#define CANCELP (test_cancel && test_cancel(testcancel_data))
+#define FATALP (at_exception_got_fatal(&exp))
+#define FREE_SPLINE() do {if (splines) {at_splines_free(splines); splines = NULL;}} while(0)
+
+#define CANCEL_THEN_CLEANUP_DIST() if (CANCELP) goto cleanup_dist;
+#define CANCEL_THEN_CLEANUP_PIXELS() if (CANCELP) {FREE_SPLINE(); goto cleanup_pixels;}
+
+#define FATAL_THEN_RETURN() if (FATALP) return splines;
+#define FATAL_THEN_CLEANUP_DIST() if (FATALP) goto cleanup_dist;
+#define FATAL_THEN_CLEANUP_PIXELS() if (FATALP) {FREE_SPLINE(); goto cleanup_pixels;}
+
+ if (opts->despeckle_level > 0) {
+ despeckle(bitmap, opts->despeckle_level, opts->despeckle_tightness, opts->noise_removal, &exp);
+ FATAL_THEN_RETURN();
+ }
+
+ image_header.width = at_bitmap_get_width(bitmap);
+ image_header.height = at_bitmap_get_height(bitmap);
+
+ if (opts->color_count > 0) {
+ quantize(bitmap, opts->color_count, opts->background_color, &myQuant, &exp);
+ if (myQuant)
+ quantize_object_free(myQuant); /* curently not used */
+ FATAL_THEN_RETURN();
+ }
+
+ if (opts->centerline) {
+ if (opts->preserve_width) {
+ /* Preserve line width prior to thinning. */
+ dist_map = new_distance_map(bitmap, 255, /*padded= */ TRUE, &exp);
+ dist = &dist_map;
+ FATAL_THEN_RETURN();
+ }
+ /* Hereafter, dist is allocated. dist must be freed if
+ the execution is canceled or exception is raised;
+ use FATAL_THEN_CLEANUP_DIST. */
+ thin_image(bitmap, opts->background_color, &exp);
+ FATAL_THEN_CLEANUP_DIST()
+ }
+
+ /* Hereafter, pixels is allocated. pixels must be freed if
+ the execution is canceled; use CANCEL_THEN_CLEANUP_PIXELS. */
+ if (opts->centerline) {
+ at_color background_color = { 0xff, 0xff, 0xff };
+ if (opts->background_color)
+ background_color = *opts->background_color;
+
+ pixels = find_centerline_pixels(bitmap, background_color, notify_progress, progress_data, test_cancel, testcancel_data, &exp);
+ } else
+ pixels = find_outline_pixels(bitmap, opts->background_color, notify_progress, progress_data, test_cancel, testcancel_data, &exp);
+ FATAL_THEN_CLEANUP_DIST();
+ CANCEL_THEN_CLEANUP_DIST();
+
+ XMALLOC(splines, sizeof(at_splines_type));
+ *splines = fitted_splines(pixels, opts, dist, image_header.width, image_header.height, &exp, notify_progress, progress_data, test_cancel, testcancel_data);
+ FATAL_THEN_CLEANUP_PIXELS();
+ CANCEL_THEN_CLEANUP_PIXELS();
+
+ if (notify_progress)
+ notify_progress(1.0, progress_data);
+
+cleanup_pixels:
+ free_pixel_outline_list(&pixels);
+cleanup_dist:
+ if (dist)
+ free_distance_map(dist);
+ return splines;
+#undef CANCELP
+#undef FATALP
+#undef FREE_SPLINE
+#undef CANCEL_THEN_CLEANUP_DIST
+#undef CANCEL_THEN_CLEANUP_PIXELS
+
+#undef FATAL_THEN_RETURN
+#undef FATAL_THEN_CLEANUP_DIST
+#undef FATAL_THEN_CLEANUP_PIXELS
+
+}
+
+void at_splines_write(at_spline_writer * writer, FILE * writeto, gchar * file_name, at_output_opts_type * opts, at_splines_type * splines, at_msg_func msg_func, gpointer msg_data)
+{
+ gboolean new_opts = FALSE;
+ int llx, lly, urx, ury;
+ llx = 0;
+ lly = 0;
+ urx = splines->width;
+ ury = splines->height;
+
+ if (!file_name)
+ file_name = "";
+
+ if (opts == NULL) {
+ new_opts = TRUE;
+ opts = at_output_opts_new();
+ }
+
+ setlocale(LC_NUMERIC, "C");
+ (*writer->func) (writeto, file_name, llx, lly, urx, ury, opts, *splines, msg_func, msg_data, writer->data);
+ if (new_opts)
+ at_output_opts_free(opts);
+}
+
+void at_splines_free(at_splines_type * splines)
+{
+ free_spline_list_array(splines);
+ if (splines->background_color)
+ at_color_free(splines->background_color);
+ free(splines);
+}
+
+const char *at_version(gboolean long_format)
+{
+ if (long_format)
+ return "AutoTrace version " AUTOTRACE_VERSION;
+
+ return AUTOTRACE_VERSION;
+}
+
+const char *at_home_site(void)
+{
+ return AUTOTRACE_WEB;
+}
+
+void autotrace_init(void)
+{
+ static int initialized = 0;
+ if (!initialized) {
+#ifdef ENABLE_NLS
+ setlocale(LC_ALL, "");
+ //bindtextdomain(PACKAGE, LOCALEDIR);
+#endif /* Def: ENABLE_NLS */
+
+ /* Initialize subsystems */
+ at_input_init();
+ at_output_init();
+ at_module_init();
+
+ initialized = 1;
+ }
+}
+
+const char *at_fitting_opts_doc_func(char *string)
+{
+ return _(string);
+}
diff --git a/src/3rdparty/autotrace/autotrace.h b/src/3rdparty/autotrace/autotrace.h
new file mode 100644
index 0000000..dc49be1
--- /dev/null
+++ b/src/3rdparty/autotrace/autotrace.h
@@ -0,0 +1,413 @@
+/* autotrace.h --- Autotrace API
+
+ Copyright (C) 2000, 2001, 2002 Martin Weber
+
+ The author can be contacted at <martweb@gmx.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef AUTOTRACE_H
+#define AUTOTRACE_H
+
+#include <stdio.h>
+
+#include "types.h"
+#include "color.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef N_
+#define N_(x) x
+#endif /* Not def: N_ */
+
+/* ===================================================================== *
+ * Typedefs
+ * ===================================================================== */
+
+/* Third degree is the highest we deal with. */
+ enum _at_polynomial_degree {
+ AT_LINEARTYPE = 1,
+ AT_QUADRATICTYPE = 2,
+ AT_CUBICTYPE = 3,
+ AT_PARALLELELLIPSETYPE = 4,
+ AT_ELLIPSETYPE = 5,
+ AT_CIRCLETYPE = 6
+ /* not the real number of points to define a
+ circle but to distinguish between a cubic spline */
+ };
+
+ enum _at_msg_type {
+ AT_MSG_NOT_SET = 0, /* is used in autotrace internally */
+ AT_MSG_FATAL = 1,
+ AT_MSG_WARNING,
+ };
+
+ typedef struct _at_fitting_opts_type at_fitting_opts_type;
+ typedef struct _at_input_opts_type at_input_opts_type;
+ typedef struct _at_output_opts_type at_output_opts_type;
+ typedef struct _at_bitmap at_bitmap;
+ typedef enum _at_polynomial_degree at_polynomial_degree;
+ typedef struct _at_spline_type at_spline_type;
+ typedef struct _at_spline_list_type at_spline_list_type;
+ typedef struct _at_spline_list_array_type at_spline_list_array_type;
+#define at_splines_type at_spline_list_array_type
+ typedef enum _at_msg_type at_msg_type;
+
+/* A Bezier spline can be represented as four points in the real plane:
+ a starting point, ending point, and two control points. The
+ curve always lies in the convex hull defined by the four points. It
+ is also convenient to save the divergence of the spline from the
+ straight line defined by the endpoints. */
+ struct _at_spline_type {
+ at_real_coord v[4]; /* The control points. */
+ at_polynomial_degree degree;
+ gfloat linearity;
+ };
+
+/* Each outline in a character is typically represented by many
+ splines. So, here is a list structure for that: */
+ struct _at_spline_list_type {
+ at_spline_type *data;
+ unsigned length;
+ gboolean clockwise;
+ at_color color;
+ gboolean open;
+ };
+
+/* Each character is in general made up of many outlines. So here is one
+ more list structure. */
+ struct _at_spline_list_array_type {
+ at_spline_list_type *data;
+ unsigned length;
+
+ /* splines bbox */
+ unsigned short height, width;
+
+ /* the values for following members are inherited from
+ at_fitting_opts_type */
+ at_color *background_color;
+ gboolean centerline;
+ gboolean preserve_width;
+ gfloat width_weight_factor;
+
+ };
+
+/* Fitting option.
+ With using at_fitting_opts_doc macro, the description of
+ each option could be get. e.g. at_fitting_opts_doc(background_color) */
+ struct _at_fitting_opts_type {
+#define at_doc__background_color \
+N_("background-color <hexadezimal>: the color of the background that " \
+"should be ignored, for example FFFFFF; " \
+"default is no background color.")
+ at_color *background_color;
+
+#define at_doc__charcode \
+N_("charcode <unsigned>: code of character to load from GF file, " \
+"allowed are 0..255; default is the first character in font.")
+ unsigned charcode;
+
+#define at_doc__color_count \
+N_("color-count <unsigned>: number of colors a color bitmap is reduced to, " \
+"it does not work on grayscale, allowed are 1..256; " \
+"default is 0, that means not color reduction is done.")
+ unsigned color_count;
+
+#define at_doc__corner_always_threshold \
+N_("corner-always-threshold <angle-in-degrees>: if the angle at a pixel is " \
+"less than this, it is considered a corner, even if it is within " \
+"`corner-surround' pixels of another corner; default is 60. ")
+ gfloat corner_always_threshold;
+
+#define at_doc__corner_surround \
+N_("corner-surround <unsigned>: number of pixels on either side of a " \
+"point to consider when determining if that point is a corner; " \
+"default is 4. ")
+ unsigned corner_surround;
+
+#define at_doc__corner_threshold \
+N_("corner-threshold <angle-in-degrees>: if a pixel, its predecessor(s), " \
+"and its successor(s) meet at an angle smaller than this, it's a " \
+"corner; default is 100. ")
+ gfloat corner_threshold;
+
+#define at_doc__error_threshold \
+N_("error-threshold <real>: subdivide fitted curves that are off by " \
+"more pixels than this; default is 2.0. ")
+ gfloat error_threshold;
+
+#define at_doc__filter_iterations \
+N_("filter-iterations <unsigned>: smooth the curve this many times " \
+"before fitting; default is 4.")
+ unsigned filter_iterations;
+
+#define at_doc__line_reversion_threshold \
+N_("line-reversion-threshold <real>: if a spline is closer to a straight " \
+"line than this, weighted by the square of the curve length, keep it a " \
+"straight line even if it is a list with curves; default is .01. ")
+ gfloat line_reversion_threshold;
+
+#define at_doc__line_threshold \
+N_("line-threshold <real>: if the spline is not more than this far away " \
+"from the straight line defined by its endpoints," \
+"then output a straight line; default is 1. ")
+ gfloat line_threshold;
+
+#define at_doc__remove_adjacent_corners \
+N_("remove-adjacent-corners: remove corners that are adjacent; " \
+"default doesn't remove.")
+ gboolean remove_adjacent_corners;
+
+#define at_doc__tangent_surround \
+N_("tangent-surround <unsigned>: number of points on either side of a " \
+"point to consider when computing the tangent at that point; " \
+" default is 3.")
+ unsigned tangent_surround;
+
+#define at_doc__despeckle_level \
+N_("despeckle-level <unsigned>: 0..20; default is no despeckling. ")
+ unsigned despeckle_level;
+
+#define at_doc__despeckle_tightness \
+N_("despeckle-tightness <real>: 0.0..8.0; default is 2.0. ")
+ gfloat despeckle_tightness;
+
+#define at_doc__noise_removal \
+N_("noise-removal <real>: 1.0..0.0; default is 0.99. ")
+ gfloat noise_removal;
+
+#define at_doc__centerline \
+N_("centerline: trace a character's centerline, rather than its outline. ")
+ gboolean centerline;
+
+#define at_doc__preserve_width \
+N_("preserve-width: whether to preserve linewith with centerline fitting; " \
+"default doesn't preserve.")
+ gboolean preserve_width;
+
+#define at_doc__width_weight_factor \
+N_("width-weight-factor <real>: weight factor for fitting the linewidth.")
+ gfloat width_weight_factor;
+ };
+
+ struct _at_input_opts_type {
+ at_color *background_color;
+ unsigned charcode; /* Character code used only in GF input. */
+ };
+
+ struct _at_output_opts_type {
+ int dpi; /* DPI is used only in MIF output. */
+ };
+
+ struct _at_bitmap {
+ unsigned short height;
+ unsigned short width;
+ unsigned char *bitmap;
+ unsigned int np;
+ };
+
+ typedef
+ void (*at_msg_func) (const gchar * msg, at_msg_type msg_type, gpointer client_data);
+
+/*
+ * Autotrace initializer
+ */
+#define AUTOTRACE_INIT
+ void autotrace_init(void);
+
+/*
+ * IO Handler typedefs
+ */
+
+ typedef struct _at_bitmap_reader at_bitmap_reader;
+ struct _at_bitmap_reader;
+
+ typedef struct _at_spline_writer at_spline_writer;
+ struct _at_spline_writer;
+
+/*
+ * Progress handler typedefs
+ * 0.0 <= percentage <= 1.0
+ */
+ typedef void (*at_progress_func) (gfloat percentage, gpointer client_data);
+
+/*
+ * Test cancel
+ * Return TRUE if auto-tracing should be stopped.
+ */
+ typedef gboolean(*at_testcancel_func) (gpointer client_data);
+
+/* ===================================================================== *
+ * Functions
+ * ===================================================================== */
+
+/* --------------------------------------------------------------------- *
+ * Fitting option related
+ *
+ * TODO: internal data access, copy
+ * --------------------------------------------------------------------- */
+ at_fitting_opts_type *at_fitting_opts_new(void);
+ at_fitting_opts_type *at_fitting_opts_copy(at_fitting_opts_type * original);
+ void at_fitting_opts_free(at_fitting_opts_type * opts);
+
+/* Gettextize */
+#define at_fitting_opts_doc(opt) at_fitting_opts_doc_func(at_doc__##opt)
+/* Don't use next function directly from clients */
+ const char *at_fitting_opts_doc_func(char *string);
+
+/* --------------------------------------------------------------------- *
+ * Input option related
+ *
+ * TODO: internal data access
+ * --------------------------------------------------------------------- */
+ at_input_opts_type *at_input_opts_new(void);
+ at_input_opts_type *at_input_opts_copy(at_input_opts_type * original);
+ void at_input_opts_free(at_input_opts_type * opts);
+
+/* --------------------------------------------------------------------- *
+ * Output option related
+ *
+ * TODO: internal data access
+ * --------------------------------------------------------------------- */
+ at_output_opts_type *at_output_opts_new(void);
+ at_output_opts_type *at_output_opts_copy(at_output_opts_type * original);
+ void at_output_opts_free(at_output_opts_type * opts);
+
+/* --------------------------------------------------------------------- *
+ * Bitmap related
+ *
+ * TODO: internal data access
+ * --------------------------------------------------------------------- */
+
+/* There is two way to build at_bitmap.
+ 1. Using input reader
+ Use at_bitmap_read.
+ at_input_get_handler_by_suffix or
+ at_input_get_handler will help you to get at_bitmap_reader.
+ 2. Allocating a bitmap and rendering an image on it by yourself
+ Use at_bitmap_new.
+
+ In both case, you have to call at_bitmap_free when at_bitmap *
+ data are no longer needed. */
+ at_bitmap *at_bitmap_read(at_bitmap_reader * reader, gchar * filename, at_input_opts_type * opts, at_msg_func msg_func, gpointer msg_data);
+ at_bitmap *at_bitmap_new(unsigned short width, unsigned short height, unsigned int planes);
+ at_bitmap *at_bitmap_copy(const at_bitmap * src);
+
+/* We have to export functions that supports internal datum
+ access. Such functions might be useful for
+ at_bitmap_new user. */
+ unsigned short at_bitmap_get_width(const at_bitmap * bitmap);
+ unsigned short at_bitmap_get_height(const at_bitmap * bitmap);
+ unsigned short at_bitmap_get_planes(const at_bitmap * bitmap);
+ void at_bitmap_get_color(const at_bitmap * bitmap, unsigned int row, unsigned int col, at_color * color);
+ gboolean at_bitmap_equal_color(const at_bitmap * bitmap, unsigned int row, unsigned int col, at_color * color);
+ void at_bitmap_free(at_bitmap * bitmap);
+
+/* --------------------------------------------------------------------- *
+ * Spline related
+ *
+ * TODO: internal data access
+ * --------------------------------------------------------------------- */
+/* at_splines_new
+
+ args:
+
+ BITMAP is modified in at_splines_new according to opts. Therefore
+ if you need the original bitmap image, you have to make a backup of
+ BITMAP with using at_bitmap_copy.
+
+ MSG_FUNC and MSG_DATA are used to notify a client errors and
+ warning from autotrace. NULL is valid value for MSG_FUNC if
+ the client is not interested in the notifications. */
+ at_splines_type *at_splines_new(at_bitmap * bitmap, at_fitting_opts_type * opts, at_msg_func msg_func, gpointer msg_data);
+
+/* at_splines_new_full
+
+ args:
+
+ NOTIFY_PROGRESS is called repeatedly inside at_splines_new_full
+ to notify the progress of the execution. This might be useful for
+ interactive applications. NOTIFY_PROGRESS is called following
+ format:
+
+ NOTIFY_PROGRESS (percentage, progress_data);
+
+ test_cancel is called repeatedly inside at_splines_new_full
+ to test whether the execution is canceled or not.
+ If test_cancel returns TRUE, execution of at_splines_new_full
+ is stopped as soon as possible and returns NULL. If test_cancel
+ returns FALSE, nothing happens. test_cancel is called following
+ format:
+
+ TEST_CANCEL (testcancel_data);
+
+ NULL is valid value for notify_progress and/or test_cancel if
+ you don't need to know the progress of the execution and/or
+ cancel the execution */
+ at_splines_type *at_splines_new_full(at_bitmap * bitmap, at_fitting_opts_type * opts, at_msg_func msg_func, gpointer msg_data, at_progress_func notify_progress, gpointer progress_data, at_testcancel_func test_cancel, gpointer testcancel_data);
+
+ void at_splines_write(at_spline_writer * writer, FILE * writeto, gchar * file_name, at_output_opts_type * opts, at_splines_type * splines, at_msg_func msg_func, gpointer msg_data);
+
+ void at_splines_free(at_splines_type * splines);
+
+/* --------------------------------------------------------------------- *
+ * Input related
+ * --------------------------------------------------------------------- */
+ at_bitmap_reader *at_input_get_handler(gchar * filename);
+ at_bitmap_reader *at_input_get_handler_by_suffix(gchar * suffix);
+
+ const char **at_input_list_new(void);
+ void at_input_list_free(const char **list);
+
+/* at_input_shortlist
+ return value: Do free by yourself */
+ char *at_input_shortlist(void);
+
+/* --------------------------------------------------------------------- *
+ * Output related
+ * --------------------------------------------------------------------- */
+ at_spline_writer *at_output_get_handler(gchar * filename);
+ at_spline_writer *at_output_get_handler_by_suffix(gchar * suffix);
+ const char **at_output_list_new(void);
+ void at_output_list_free(const char **list);
+
+/* at_output_shortlist
+ return value: Do free by yourself */
+ char *at_output_shortlist(void);
+
+/* --------------------------------------------------------------------- *
+ * Misc
+ * --------------------------------------------------------------------- */
+
+/* at_version
+
+ args:
+ LONG_FORMAT == TRUE: "AutoTrace version x.y"
+ LONG_FORMAT == FALSE: "x.y"
+
+ return value: Don't free. It is allocated statically */
+ const char *at_version(gboolean long_format);
+
+/* at_home_site
+
+ return value: Don't free. It is allocated statically */
+ const char *at_home_site(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* AUTOTRACE_H */
diff --git a/src/3rdparty/autotrace/bitmap.c b/src/3rdparty/autotrace/bitmap.c
new file mode 100644
index 0000000..759a0df
--- /dev/null
+++ b/src/3rdparty/autotrace/bitmap.c
@@ -0,0 +1,8 @@
+/* bitmap.c: operations on bitmaps. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* Def: HAVE_CONFIG_H */
+
+#include "bitmap.h"
+#include "xstd.h"
diff --git a/src/3rdparty/autotrace/bitmap.h b/src/3rdparty/autotrace/bitmap.h
new file mode 100644
index 0000000..0f9b45a
--- /dev/null
+++ b/src/3rdparty/autotrace/bitmap.h
@@ -0,0 +1,13 @@
+/* bitmap.h: definition for a bitmap type. No packing is done by
+ default; each pixel is represented by an entire byte. Among other
+ things, this means the type can be used for both grayscale and binary
+ images. */
+
+#ifndef BITMAP_H
+#define BITMAP_H
+
+#include "autotrace.h"
+#include "input.h"
+#include <stdio.h>
+
+#endif /* not BITMAP_H */
diff --git a/src/3rdparty/autotrace/color.c b/src/3rdparty/autotrace/color.c
new file mode 100644
index 0000000..14a70f4
--- /dev/null
+++ b/src/3rdparty/autotrace/color.c
@@ -0,0 +1,114 @@
+/* color.c: declarations for color handling.
+
+ Copyright (C) 2000, 2001, 2002 Martin Weber
+
+ The author can be contacted at <martweb@gmx.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* Def: HAVE_CONFIG_H */
+
+#include "intl.h"
+#include "color.h"
+#include "exception.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+at_color *at_color_new(unsigned char r, unsigned char g, unsigned char b)
+{
+ at_color *color;
+ color = g_new(at_color, 1);
+ color->r = r;
+ color->g = g;
+ color->b = b;
+ return color;
+}
+
+at_color *at_color_parse(const gchar * string, GError ** err)
+{
+ GError *local_err = NULL;
+ unsigned char c[6];
+ int i;
+
+ if (!string)
+ return NULL;
+ else if (string[0] == '\0')
+ return NULL;
+ else if (strlen(string) != 6) {
+ g_set_error(err, AT_ERROR, AT_ERROR_WRONG_COLOR_STRING, _("color string is too short: %s"), string);
+ return NULL;
+ }
+
+ for (i = 0; i < 6; i++) {
+ char ch = string[i];
+ if (ch >= '0' && ch <= '9')
+ c[i] = ch - '0';
+ else if (ch >= 'A' && ch <= 'F')
+ c[i] = ch - 'A' + 10;
+ else if (ch >= 'a' && ch <= 'f')
+ c[i] = ch - 'a' + 10;
+ else {
+ g_set_error(&local_err, AT_ERROR, AT_ERROR_WRONG_COLOR_STRING, _("wrong char in color string: %c"), string[i]);
+ g_propagate_error(err, local_err);
+ return NULL;
+ }
+ }
+ return at_color_new((unsigned char)(16 * c[0] + c[1]), (unsigned char)(16 * c[2] + c[3]), (unsigned char)(16 * c[4] + c[5]));
+}
+
+at_color *at_color_copy(const at_color * original)
+{
+ if (original == NULL)
+ return NULL;
+
+ return at_color_new(original->r, original->g, original->b);
+}
+
+gboolean at_color_equal(const at_color * c1, const at_color * c2)
+{
+ if (c1 == c2 || ((c1->r == c2->r) && (c1->g == c2->g) && (c1->b == c2->b)))
+ return TRUE;
+
+ return FALSE;
+}
+
+void at_color_set(at_color * c, unsigned char r, unsigned char g, unsigned char b)
+{
+ g_return_if_fail(c);
+ c->r = r;
+ c->g = g;
+ c->b = b;
+}
+
+unsigned char at_color_luminance(const at_color * color)
+{
+ return ((unsigned char)((color->r) * 0.30 + (color->g) * 0.59 + (color->b) * 0.11 + 0.5));
+}
+
+void at_color_free(at_color * color)
+{
+ g_free(color);
+}
+
+GType at_color_get_type(void)
+{
+ static GType our_type = 0;
+ if (our_type == 0)
+ our_type = g_boxed_type_register_static("AtColor", (GBoxedCopyFunc) at_color_copy, (GBoxedFreeFunc) at_color_free);
+ return our_type;
+}
diff --git a/src/3rdparty/autotrace/color.h b/src/3rdparty/autotrace/color.h
new file mode 100644
index 0000000..88651db
--- /dev/null
+++ b/src/3rdparty/autotrace/color.h
@@ -0,0 +1,53 @@
+/* color.h: declarations for color handling.
+
+ Copyright (C) 2000, 2001, 2002 Martin Weber
+
+ The author can be contacted at <martweb@gmx.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef AT_COLOR_H
+#define AT_COLOR_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _at_color at_color;
+struct _at_color {
+ guint8 r;
+ guint8 g;
+ guint8 b;
+};
+
+at_color *at_color_new(guint8 r, guint8 g, guint8 b);
+at_color *at_color_parse(const gchar * string, GError ** err);
+at_color *at_color_copy(const at_color * original);
+gboolean at_color_equal(const at_color * c1, const at_color * c2);
+void at_color_set(at_color * c1, guint8 r, guint8 g, guint8 b);
+/* RGB to grayscale */
+unsigned char at_color_luminance(const at_color * color);
+void at_color_free(at_color * color);
+
+GType at_color_get_type(void);
+#define AT_TYPE_COLOR (at_color_get_type ())
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* not AT_COLOR_H */
diff --git a/src/3rdparty/autotrace/config.h b/src/3rdparty/autotrace/config.h
new file mode 100644
index 0000000..4bde2a1
--- /dev/null
+++ b/src/3rdparty/autotrace/config.h
@@ -0,0 +1,117 @@
+/* config.h. Generated from config.h.in by configure. */
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Package version */
+#define AUTOTRACE_VERSION "0.40.0"
+
+/* Project home page */
+#define AUTOTRACE_WEB "https://github.com/autotrace/autotrace"
+
+/* always defined to indicate that i18n is enabled */
+#define ENABLE_NLS 1
+
+/* Define to the gettext package name. */
+#define GETTEXT_PACKAGE "autotrace"
+
+/* Define to 1 if you have the `bind_textdomain_codeset' function. */
+#define HAVE_BIND_TEXTDOMAIN_CODESET 1
+
+/* Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the
+ CoreFoundation framework. */
+/* #undef HAVE_CFLOCALECOPYCURRENT */
+
+/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in
+ the CoreFoundation framework. */
+/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */
+
+/* Define to 1 if you have the `dcgettext' function. */
+#define HAVE_DCGETTEXT 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+#define HAVE_GETTEXT 1
+
+/* Define if you have the iconv() function and it works. */
+/* #undef HAVE_ICONV */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define if your <locale.h> file defines LC_MESSAGES. */
+#define HAVE_LC_MESSAGES 1
+
+/* PNG library is available or not */
+#define HAVE_LIBPNG 1
+
+/* pstoedit library is available or not */
+#define HAVE_LIBPSTOEDIT 1
+
+/* SWF library is available or not */
+/* #undef HAVE_LIBSWF */
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have the `localtime_r' function. */
+#define HAVE_LOCALTIME_R 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to the sub-directory where libtool stores uninstalled libraries. */
+#define LT_OBJDIR ".libs/"
+
+/* Package name */
+#define PACKAGE "autotrace"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "autotrace"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "autotrace 0.40.0"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "autotrace"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.40.0"
+
+/* Define to 1 if all of the C90 standard headers exist (not just the ones
+ required in a freestanding environment). This macro is provided for
+ backward compatibility; new code need not use it. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "0.40.0"
diff --git a/src/3rdparty/autotrace/curve.c b/src/3rdparty/autotrace/curve.c
new file mode 100644
index 0000000..4ee2603
--- /dev/null
+++ b/src/3rdparty/autotrace/curve.c
@@ -0,0 +1,255 @@
+/* curve.c: operations on the lists of pixels and lists of curves.
+
+ The code was partially derived from limn.
+
+ Copyright (C) 1992 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* Def: HAVE_CONFIG_H */
+
+#include "logreport.h"
+#include "curve.h"
+#include "xstd.h"
+
+static at_real_coord int_to_real_coord(at_coord);
+
+/* Return an entirely empty curve. */
+
+curve_type new_curve(void)
+{
+ curve_type curve;
+ XMALLOC(curve, sizeof(struct curve));
+ curve->point_list = NULL;
+ CURVE_LENGTH(curve) = 0;
+ CURVE_CYCLIC(curve) = FALSE;
+ CURVE_START_TANGENT(curve) = CURVE_END_TANGENT(curve) = NULL;
+ PREVIOUS_CURVE(curve) = NEXT_CURVE(curve) = NULL;
+
+ return curve;
+}
+
+/* Don't copy the points or tangents, but copy everything else. */
+
+curve_type copy_most_of_curve(curve_type old_curve)
+{
+ curve_type curve = new_curve();
+
+ CURVE_CYCLIC(curve) = CURVE_CYCLIC(old_curve);
+ PREVIOUS_CURVE(curve) = PREVIOUS_CURVE(old_curve);
+ NEXT_CURVE(curve) = NEXT_CURVE(old_curve);
+
+ return curve;
+}
+
+/* The length of CURVE will be zero if we ended up not being able to fit
+ it (which in turn implies a problem elsewhere in the program, but at
+ any rate, we shouldn't try here to free the nonexistent curve). */
+
+void free_curve(curve_type curve)
+{
+ if (CURVE_LENGTH(curve) > 0)
+ free(curve->point_list);
+ if (CURVE_START_TANGENT(curve))
+ free(CURVE_START_TANGENT(curve));
+ if (CURVE_END_TANGENT(curve))
+ free(CURVE_END_TANGENT(curve));
+}
+
+void append_pixel(curve_type curve, at_coord coord)
+{
+ append_point(curve, int_to_real_coord(coord));
+}
+
+void append_point(curve_type curve, at_real_coord coord)
+{
+ CURVE_LENGTH(curve)++;
+ XREALLOC(curve->point_list, CURVE_LENGTH(curve) * sizeof(point_type));
+ LAST_CURVE_POINT(curve) = coord;
+ /* The t value does not need to be set. */
+}
+
+/* Print a curve in human-readable form. It turns out we never care
+ about most of the points on the curve, and so it is pointless to
+ print them all out umpteen times. What matters is that we have some
+ from the end and some from the beginning. */
+
+#define NUM_TO_PRINT 3
+
+#define LOG_CURVE_POINT(c, p, print_t) \
+ do \
+ { \
+ LOG ("(%.3f,%.3f)", CURVE_POINT (c, p).x, CURVE_POINT (c, p).y); \
+ if (print_t) \
+ LOG ("/%.2f", CURVE_T (c, p)); \
+ } \
+ while (0)
+
+void log_curve(curve_type curve, gboolean print_t)
+{
+ unsigned this_point;
+
+ LOG("curve id = %lx:\n", (unsigned long)(uintptr_t)curve);
+ LOG(" length = %u.\n", CURVE_LENGTH(curve));
+ if (CURVE_CYCLIC(curve))
+ LOG(" cyclic.\n");
+
+ /* It should suffice to check just one of the tangents for being null
+ -- either they both should be, or neither should be. */
+ if (CURVE_START_TANGENT(curve) != NULL)
+ LOG(" tangents = (%.3f,%.3f) & (%.3f,%.3f).\n", CURVE_START_TANGENT(curve)->dx, CURVE_START_TANGENT(curve)->dy, CURVE_END_TANGENT(curve)->dx, CURVE_END_TANGENT(curve)->dy);
+
+ LOG(" ");
+
+ /* If the curve is short enough, don't use ellipses. */
+ if (CURVE_LENGTH(curve) <= NUM_TO_PRINT * 2) {
+ for (this_point = 0; this_point < CURVE_LENGTH(curve); this_point++) {
+ LOG_CURVE_POINT(curve, this_point, print_t);
+ LOG(" ");
+
+ if (this_point != CURVE_LENGTH(curve) - 1 && (this_point + 1) % NUM_TO_PRINT == 0)
+ LOG("\n ");
+ }
+ } else {
+ for (this_point = 0; this_point < NUM_TO_PRINT && this_point < CURVE_LENGTH(curve); this_point++) {
+ LOG_CURVE_POINT(curve, this_point, print_t);
+ LOG(" ");
+ }
+
+ LOG("...\n ...");
+
+ for (this_point = CURVE_LENGTH(curve) - NUM_TO_PRINT; this_point < CURVE_LENGTH(curve); this_point++) {
+ LOG(" ");
+ LOG_CURVE_POINT(curve, this_point, print_t);
+ }
+ }
+
+ LOG(".\n");
+}
+
+/* Like `log_curve', but write the whole thing. */
+
+void log_entire_curve(curve_type curve)
+{
+ unsigned this_point;
+
+ LOG("curve id = %lx:\n", (unsigned long)(uintptr_t)curve);
+ LOG(" length = %u.\n", CURVE_LENGTH(curve));
+ if (CURVE_CYCLIC(curve))
+ LOG(" cyclic.\n");
+
+ /* It should suffice to check just one of the tangents for being null
+ -- either they both should be, or neither should be. */
+ if (CURVE_START_TANGENT(curve) != NULL)
+ LOG(" tangents = (%.3f,%.3f) & (%.3f,%.3f).\n", CURVE_START_TANGENT(curve)->dx, CURVE_START_TANGENT(curve)->dy, CURVE_END_TANGENT(curve)->dx, CURVE_END_TANGENT(curve)->dy);
+
+ LOG(" ");
+
+ for (this_point = 0; this_point < CURVE_LENGTH(curve); this_point++) {
+ LOG(" ");
+ LOG_CURVE_POINT(curve, this_point, TRUE);
+ /* Compiler warning `Condition is always true' can be ignored */
+ }
+
+ LOG(".\n");
+}
+
+/* Return an initialized but empty curve list. */
+
+curve_list_type new_curve_list(void)
+{
+ curve_list_type curve_list;
+
+ curve_list.length = 0;
+ curve_list.data = NULL;
+
+ return curve_list;
+}
+
+/* Free a curve list and all the curves it contains. */
+
+void free_curve_list(curve_list_type * curve_list)
+{
+ unsigned this_curve;
+
+ for (this_curve = 0; this_curve < curve_list->length; this_curve++) {
+ free_curve(curve_list->data[this_curve]);
+ free(curve_list->data[this_curve]);
+ }
+
+ /* If the character was empty, it won't have any curves. */
+ free(curve_list->data);
+}
+
+/* Add an element to a curve list. */
+
+void append_curve(curve_list_type * curve_list, curve_type curve)
+{
+ curve_list->length++;
+ XREALLOC(curve_list->data, curve_list->length * sizeof(curve_type));
+ curve_list->data[curve_list->length - 1] = curve;
+}
+
+/* Return an initialized but empty curve list array. */
+
+curve_list_array_type new_curve_list_array(void)
+{
+ curve_list_array_type curve_list_array;
+
+ CURVE_LIST_ARRAY_LENGTH(curve_list_array) = 0;
+ curve_list_array.data = NULL;
+
+ return curve_list_array;
+}
+
+/* Free a curve list array and all the curve lists it contains. */
+
+void free_curve_list_array(curve_list_array_type * curve_list_array, at_progress_func notify_progress, gpointer client_data)
+{
+ unsigned this_list;
+
+ for (this_list = 0; this_list < CURVE_LIST_ARRAY_LENGTH(*curve_list_array); this_list++) {
+ if (notify_progress)
+ notify_progress(((gfloat) this_list) / (CURVE_LIST_ARRAY_LENGTH(*curve_list_array) * (gfloat) 3.0) + (gfloat) 0.666, client_data);
+ free_curve_list(&CURVE_LIST_ARRAY_ELT(*curve_list_array, this_list));
+ }
+
+ /* If the character was empty, it won't have any curves. */
+ free(curve_list_array->data);
+}
+
+/* Add an element to a curve list array. */
+
+void append_curve_list(curve_list_array_type * curve_list_array, curve_list_type curve_list)
+{
+ CURVE_LIST_ARRAY_LENGTH(*curve_list_array)++;
+ XREALLOC(curve_list_array->data, CURVE_LIST_ARRAY_LENGTH(*curve_list_array) * sizeof(curve_list_type));
+ LAST_CURVE_LIST_ARRAY_ELT(*curve_list_array) = curve_list;
+}
+
+/* Turn an integer point into a real one. */
+
+static at_real_coord int_to_real_coord(at_coord int_coord)
+{
+ at_real_coord real_coord;
+
+ real_coord.x = int_coord.x;
+ real_coord.y = int_coord.y;
+ real_coord.z = 0.0;
+
+ return real_coord;
+}
diff --git a/src/3rdparty/autotrace/curve.h b/src/3rdparty/autotrace/curve.h
new file mode 100644
index 0000000..1efcf4e
--- /dev/null
+++ b/src/3rdparty/autotrace/curve.h
@@ -0,0 +1,131 @@
+/* curve.h: data structures for the conversion from pixels to splines. */
+
+#ifndef CURVE_H
+#define CURVE_H
+
+#include "autotrace.h"
+#include "vector.h"
+
+/* We are simultaneously manipulating two different representations of
+ the same outline: one based on (x,y) positions in the plane, and one
+ based on parametric splines. (We are trying to match the latter to
+ the former.) Although the original (x,y)'s are pixel positions,
+ i.e., integers, after filtering they are reals. */
+
+typedef struct {
+ at_real_coord coord;
+ gfloat t;
+} point_type;
+
+/* It turns out to be convenient to break the list of all the pixels in
+ the outline into sublists, divided at ``corners''. Then each of the
+ sublists is treated independently. Each of these sublists is a `curve'. */
+
+struct curve {
+ point_type *point_list;
+ unsigned length;
+ gboolean cyclic;
+ vector_type *start_tangent;
+ vector_type *end_tangent;
+ struct curve *previous;
+ struct curve *next;
+};
+
+typedef struct curve *curve_type;
+
+/* Get at the coordinates and the t values. */
+#define CURVE_POINT(c, n) ((c)->point_list[n].coord)
+#define LAST_CURVE_POINT(c) ((c)->point_list[(c)->length-1].coord)
+#define CURVE_T(c, n) ((c)->point_list[n].t)
+#define LAST_CURVE_T(c) ((c)->point_list[(c)->length-1].t)
+
+/* This is the length of `point_list'. */
+#define CURVE_LENGTH(c) ((c)->length)
+
+/* A curve is ``cyclic'' if it didn't have any corners, after all, so
+ the last point is adjacent to the first. */
+#define CURVE_CYCLIC(c) ((c)->cyclic)
+
+/* If the curve is cyclic, the next and previous points should wrap
+ around; otherwise, if we get to the end, we return CURVE_LENGTH and
+ -1, respectively. */
+#define CURVE_NEXT(c, n) \
+ ((n) + 1 >= CURVE_LENGTH (c) \
+ ? CURVE_CYCLIC (c) ? ((n) + 1) % CURVE_LENGTH (c) : CURVE_LENGTH (c) \
+ : (n) + 1)
+#define CURVE_PREV(c, n) \
+ ((signed int) (n) - 1 < 0 \
+ ? CURVE_CYCLIC (c) ? (signed int) CURVE_LENGTH (c) + (signed int) (n) - 1 : -1\
+ : (signed int) (n) - 1)
+
+/* The tangents at the endpoints are computed using the neighboring curves. */
+#define CURVE_START_TANGENT(c) ((c)->start_tangent)
+#define CURVE_END_TANGENT(c) ((c)->end_tangent)
+#define PREVIOUS_CURVE(c) ((c)->previous)
+#define NEXT_CURVE(c) ((c)->next)
+
+/* Return an entirely empty curve. */
+extern curve_type new_curve(void);
+
+/* Return a curve the same as C, except without any points. */
+extern curve_type copy_most_of_curve(curve_type c);
+
+/* Free the memory C uses. */
+extern void free_curve(curve_type c);
+
+/* Append the point P to the end of C's list. */
+extern void append_pixel(curve_type c, at_coord p);
+
+/* Like `append_pixel', for a point in real coordinates. */
+extern void append_point(curve_type c, at_real_coord p);
+
+/* Write some or all, respectively, of the curve C in human-readable
+ form to the log file, if logging is enabled. */
+extern void log_curve(curve_type c, gboolean print_t);
+extern void log_entire_curve(curve_type c);
+
+/* Display the curve C online, if displaying is enabled. */
+extern void display_curve(curve_type);
+
+/* So, an outline is a list of curves. */
+typedef struct {
+ curve_type *data;
+ unsigned length;
+ gboolean clockwise;
+ gboolean open;
+} curve_list_type;
+
+/* Number of curves in the list. */
+#define CURVE_LIST_LENGTH(c_l) ((c_l).length)
+
+/* Access the individual curves. */
+#define CURVE_LIST_ELT(c_l, n) ((c_l).data[n])
+#define LAST_CURVE_LIST_ELT(c_l) ((c_l).data[CURVE_LIST_LENGTH (c_l) - 1])
+
+/* Says whether the outline that this curve list represents moves
+ clockwise or counterclockwise. */
+#define CURVE_LIST_CLOCKWISE(c_l) ((c_l).clockwise)
+
+extern curve_list_type new_curve_list(void);
+extern void free_curve_list(curve_list_type *);
+extern void append_curve(curve_list_type *, curve_type);
+
+/* And a character is a list of outlines. I named this
+ `curve_list_array_type' because `curve_list_list_type' seemed pretty
+ monstrous. */
+typedef struct {
+ curve_list_type *data;
+ unsigned length;
+} curve_list_array_type;
+
+/* Turns out we can use the same definitions for lists of lists as for
+ just lists. But we define the usual names, just in case. */
+#define CURVE_LIST_ARRAY_LENGTH CURVE_LIST_LENGTH
+#define CURVE_LIST_ARRAY_ELT CURVE_LIST_ELT
+#define LAST_CURVE_LIST_ARRAY_ELT LAST_CURVE_LIST_ELT
+
+extern curve_list_array_type new_curve_list_array(void);
+extern void free_curve_list_array(curve_list_array_type *, at_progress_func, gpointer);
+extern void append_curve_list(curve_list_array_type *, curve_list_type);
+
+#endif /* not CURVE_H */
diff --git a/src/3rdparty/autotrace/despeckle.c b/src/3rdparty/autotrace/despeckle.c
new file mode 100644
index 0000000..3ab66ac
--- /dev/null
+++ b/src/3rdparty/autotrace/despeckle.c
@@ -0,0 +1,710 @@
+/* despeckle.c: Bitmap despeckler
+
+ Copyright (C) 2001 David A. Bartold / Martin Weber
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License
+ as published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* Def: HAVE_CONFIG_H */
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <time.h>
+#include "xstd.h"
+#include "logreport.h"
+#include "types.h"
+#include "bitmap.h"
+#include "despeckle.h"
+
+/* Calculate Error - compute the error between two colors
+ *
+ * Input parameters:
+ * Two 24 bit RGB colors
+ *
+ * Returns:
+ * The squared error between the two colors
+ */
+
+static int calc_error(unsigned char *color1, unsigned char *color2)
+{
+ int the_error;
+ int temp;
+
+ temp = color1[0] - color2[0];
+ the_error = temp * temp;
+ temp = color1[1] - color2[1];
+ the_error += temp * temp;
+ temp = color1[2] - color2[2];
+ the_error += temp * temp;
+
+ return the_error;
+}
+
+/* Calculate Error - compute the error between two colors
+ *
+ * Input parameters:
+ * Two 8 bit gray scale colors
+ *
+ * Returns:
+ * The squared error between the two colors
+ */
+
+static int calc_error_8(unsigned char *color1, unsigned char *color2)
+{
+ int the_error;
+
+ the_error = abs(color1[0] - color2[0]);
+
+ return the_error;
+}
+
+/* Find Size - Find the number of adjacent pixels of the same color
+ *
+ * Input Parameters:
+ * An 24 bit image, the current location inside the image, and the palette
+ * index of the color we are looking for
+ *
+ * Modified Parameters:
+ * A mask array used to prevent backtracking over already counted pixels
+ *
+ * Returns:
+ * Number of adjacent pixels found having the same color
+ */
+
+static int find_size( /* in */ unsigned char *index,
+ /* in */ int x,
+ /* in */ int y,
+ /* in */ int width,
+ /* in */ int height,
+ /* in */ unsigned char *bitmap,
+ /* in/out */ unsigned char *mask)
+{
+ int count;
+ int x1, x2;
+
+ if (y < 0 || y >= height || mask[y * width + x] == 1 || bitmap[3 * (y * width + x)] != index[0] || bitmap[3 * (y * width + x) + 1] != index[1] || bitmap[3 * (y * width + x) + 2] != index[2])
+ return 0;
+
+ for (x1 = x; x1 >= 0 && bitmap[3 * (y * width + x1)] == index[0] && bitmap[3 * (y * width + x1) + 1] == index[1] && bitmap[3 * (y * width + x1) + 2] == index[2] && mask[y * width + x] != 1; x1--) ;
+ x1++;
+
+ for (x2 = x; x2 < width && bitmap[3 * (y * width + x2)] == index[0] && bitmap[3 * (y * width + x2) + 1] == index[1] && bitmap[3 * (y * width + x2) + 2] == index[2] && mask[y * width + x] != 1; x2++) ;
+ x2--;
+
+ count = x2 - x1 + 1;
+ for (x = x1; x <= x2; x++)
+ mask[y * width + x] = 1;
+
+ for (x = x1; x <= x2; x++) {
+ count += find_size(index, x, y - 1, width, height, bitmap, mask);
+ count += find_size(index, x, y + 1, width, height, bitmap, mask);
+ }
+
+ return count;
+}
+
+/* Find Size - Find the number of adjacent pixels of the same color
+ *
+ * Input Parameters:
+ * An 8 bit image, the current location inside the image, and the palette
+ * index of the color we are looking for
+ *
+ * Modified Parameters:
+ * A mask array used to prevent backtracking over already counted pixels
+ *
+ * Returns:
+ * Number of adjacent pixels found having the same color
+ */
+
+static int find_size_8( /* in */ unsigned char *index,
+ /* in */ int x,
+ /* in */ int y,
+ /* in */ int width,
+ /* in */ int height,
+ /* in */ unsigned char *bitmap,
+ /* in/out */ unsigned char *mask)
+{
+ int count;
+ int x1, x2;
+
+ if (y < 0 || y >= height || mask[y * width + x] == 1 || bitmap[(y * width + x)] != index[0])
+ return 0;
+
+ for (x1 = x; x1 >= 0 && bitmap[(y * width + x1)] == index[0] && mask[y * width + x] != 1; x1--) ;
+ x1++;
+
+ for (x2 = x; x2 < width && bitmap[(y * width + x2)] == index[0] && mask[y * width + x] != 1; x2++) ;
+ x2--;
+
+ count = x2 - x1 + 1;
+ for (x = x1; x <= x2; x++)
+ mask[y * width + x] = 1;
+
+ for (x = x1; x <= x2; x++) {
+ count += find_size_8(index, x, y - 1, width, height, bitmap, mask);
+ count += find_size_8(index, x, y + 1, width, height, bitmap, mask);
+ }
+
+ return count;
+}
+
+/* Find Most Similar Neighbor - Given a position in an 24 bit bitmap and a color
+ * index, traverse over a blob of adjacent pixels having the same value.
+ * Return the color index of the neighbor pixel that has the most similar
+ * color.
+ *
+ * Input parameters:
+ * 24 bit bitmap, the current location inside the image,
+ * and the color index of the blob
+ *
+ * Modified parameters:
+ * Mask used to prevent backtracking
+ *
+ * Output parameters:
+ * Closest index != index and the error between the two colors squared
+ */
+
+static void find_most_similar_neighbor( /* in */ unsigned char *index,
+ /* in/out */ unsigned char **closest_index,
+ /* in/out */ int *error_amt,
+ /* in */ int x,
+ /* in */ int y,
+ /* in */ int width,
+ /* in */ int height,
+ /* in */ unsigned char *bitmap,
+ /* in/out */ unsigned char *mask)
+{
+ int x1, x2;
+ int temp_error;
+ unsigned char *value, *temp;
+
+ if (y < 0 || y >= height || mask[y * width + x] == 2)
+ return;
+
+ temp = &bitmap[3 * (y * width + x)];
+
+ assert(closest_index != NULL);
+
+ if (temp[0] != index[0] || temp[1] != index[1] || temp[2] != index[2]) {
+ value = temp;
+
+ temp_error = calc_error(index, value);
+
+ if (*closest_index == NULL || temp_error < *error_amt)
+ *closest_index = value, *error_amt = temp_error;
+
+ return;
+ }
+
+ for (x1 = x; x1 >= 0 && bitmap[3 * (y * width + x1)] == index[0] && bitmap[3 * (y * width + x1) + 1] == index[1] && bitmap[3 * (y * width + x1) + 2] == index[2]; x1--) ;
+ x1++;
+
+ for (x2 = x; x2 < width && bitmap[3 * (y * width + x2)] == index[0] && bitmap[3 * (y * width + x2) + 1] == index[1] && bitmap[3 * (y * width + x2) + 2] == index[2]; x2++) ;
+ x2--;
+
+ if (x1 > 0) {
+ value = &bitmap[3 * (y * width + x1 - 1)];
+
+ temp_error = calc_error(index, value);
+
+ if (*closest_index == NULL || temp_error < *error_amt)
+ *closest_index = value, *error_amt = temp_error;
+ }
+
+ if (x2 < width - 1) {
+ value = &bitmap[3 * (y * width + x2 + 1)];
+
+ temp_error = calc_error(index, value);
+
+ if (*closest_index == NULL || temp_error < *error_amt)
+ *closest_index = value, *error_amt = temp_error;
+ }
+
+ for (x = x1; x <= x2; x++)
+ mask[y * width + x] = 2;
+
+ for (x = x1; x <= x2; x++) {
+ find_most_similar_neighbor(index, closest_index, error_amt, x, y - 1, width, height, bitmap, mask);
+ find_most_similar_neighbor(index, closest_index, error_amt, x, y + 1, width, height, bitmap, mask);
+ }
+}
+
+/* Find Most Similar Neighbor - Given a position in an 8 bit bitmap and a color
+ * index, traverse over a blob of adjacent pixels having the same value.
+ * Return the color index of the neighbor pixel that has the most similar
+ * color.
+ *
+ * Input parameters:
+ * 8 bit bitmap, the current location inside the image,
+ * and the color index of the blob
+ *
+ * Modified parameters:
+ * Mask used to prevent backtracking
+ *
+ * Output parameters:
+ * Closest index != index and the error between the two colors squared
+ */
+
+static void find_most_similar_neighbor_8( /* in */ unsigned char *index,
+ /* in/out */ unsigned char **closest_index,
+ /* in/out */ int *error_amt,
+ /* in */ int x,
+ /* in */ int y,
+ /* in */ int width,
+ /* in */ int height,
+ /* in */ unsigned char *bitmap,
+ /* in/out */ unsigned char *mask)
+{
+ int x1, x2;
+ int temp_error;
+ unsigned char *value, *temp;
+
+ if (y < 0 || y >= height || mask[y * width + x] == 2)
+ return;
+
+ temp = &bitmap[(y * width + x)];
+
+ assert(closest_index != NULL);
+
+ if (temp[0] != index[0]) {
+ value = temp;
+
+ temp_error = calc_error_8(index, value);
+
+ if (*closest_index == NULL || temp_error < *error_amt)
+ *closest_index = value, *error_amt = temp_error;
+
+ return;
+ }
+
+ for (x1 = x; x1 >= 0 && bitmap[(y * width + x1)] == index[0]; x1--) ;
+ x1++;
+
+ for (x2 = x; x2 < width && bitmap[(y * width + x2)] == index[0]; x2++) ;
+ x2--;
+
+ if (x1 > 0) {
+ value = &bitmap[(y * width + x1 - 1)];
+
+ temp_error = calc_error_8(index, value);
+
+ if (*closest_index == NULL || temp_error < *error_amt)
+ *closest_index = value, *error_amt = temp_error;
+ }
+
+ if (x2 < width - 1) {
+ value = &bitmap[(y * width + x2 + 1)];
+
+ temp_error = calc_error_8(index, value);
+
+ if (*closest_index == NULL || temp_error < *error_amt)
+ *closest_index = value, *error_amt = temp_error;
+ }
+
+ for (x = x1; x <= x2; x++)
+ mask[y * width + x] = 2;
+
+ for (x = x1; x <= x2; x++) {
+ find_most_similar_neighbor_8(index, closest_index, error_amt, x, y - 1, width, height, bitmap, mask);
+ find_most_similar_neighbor_8(index, closest_index, error_amt, x, y + 1, width, height, bitmap, mask);
+ }
+}
+
+/* Fill - change the color of a blob
+ *
+ * Input parameters:
+ * The new color
+ *
+ * Modified parameters:
+ * 24 bit pixbuf and its mask (used to prevent backtracking)
+ */
+
+static void fill( /* in */ unsigned char *to_index,
+ /* in */ int x,
+ /* in */ int y,
+ /* in */ int width,
+ /* in */ int height,
+ /* in/out */ unsigned char *bitmap,
+ /* in/out */ unsigned char *mask)
+{
+ int x1, x2;
+
+ if (y < 0 || y >= height || mask[y * width + x] != 2)
+ return;
+
+ for (x1 = x; x1 >= 0 && mask[y * width + x1] == 2; x1--) ;
+ x1++;
+ for (x2 = x; x2 < width && mask[y * width + x2] == 2; x2++) ;
+ x2--;
+
+ assert(x1 >= 0 && x2 < width);
+
+ for (x = x1; x <= x2; x++) {
+ bitmap[3 * (y * width + x)] = to_index[0];
+ bitmap[3 * (y * width + x) + 1] = to_index[1];
+ bitmap[3 * (y * width + x) + 2] = to_index[2];
+ mask[y * width + x] = 3;
+ }
+
+ for (x = x1; x <= x2; x++) {
+ fill(to_index, x, y - 1, width, height, bitmap, mask);
+ fill(to_index, x, y + 1, width, height, bitmap, mask);
+ }
+}
+
+/* Fill - change the color of a blob
+ *
+ * Input parameters:
+ * The new color
+ *
+ * Modified parameters:
+ * 8 bit pixbuf and its mask (used to prevent backtracking)
+ */
+
+static void fill_8( /* in */ unsigned char *to_index,
+ /* in */ int x,
+ /* in */ int y,
+ /* in */ int width,
+ /* in */ int height,
+ /* in/out */ unsigned char *bitmap,
+ /* in/out */ unsigned char *mask)
+{
+ int x1, x2;
+
+ if (y < 0 || y >= height || mask[y * width + x] != 2)
+ return;
+
+ for (x1 = x; x1 >= 0 && mask[y * width + x1] == 2; x1--) ;
+ x1++;
+ for (x2 = x; x2 < width && mask[y * width + x2] == 2; x2++) ;
+ x2--;
+
+ assert(x1 >= 0 && x2 < width);
+
+ for (x = x1; x <= x2; x++) {
+ bitmap[(y * width + x)] = to_index[0];
+ mask[y * width + x] = 3;
+ }
+
+ for (x = x1; x <= x2; x++) {
+ fill_8(to_index, x, y - 1, width, height, bitmap, mask);
+ fill_8(to_index, x, y + 1, width, height, bitmap, mask);
+ }
+}
+
+/* Ignore - blob is big enough, mask it off
+ *
+ * Modified parameters:
+ * its mask (used to prevent backtracking)
+ */
+
+static void ignore( /* in */ int x,
+ /* in */ int y,
+ /* in */ int width,
+ /* in */ int height,
+ /* in/out */ unsigned char *mask)
+{
+ int x1, x2;
+
+ if (y < 0 || y >= height || mask[y * width + x] != 1)
+ return;
+
+ for (x1 = x; x1 >= 0 && mask[y * width + x1] == 1; x1--) ;
+ x1++;
+ for (x2 = x; x2 < width && mask[y * width + x2] == 1; x2++) ;
+ x2--;
+
+ assert(x1 >= 0 && x2 < width);
+
+ for (x = x1; x <= x2; x++)
+ mask[y * width + x] = 3;
+
+ for (x = x1; x <= x2; x++) {
+ ignore(x, y - 1, width, height, mask);
+ ignore(x, y + 1, width, height, mask);
+ }
+}
+
+/* Recolor - conditionally change a feature's color to the closest color of all
+ * neighboring pixels
+ *
+ * Input parameters:
+ * The color palette, current blob size, and adaptive tightness
+ *
+ * Adaptive Tightness: (integer 1 to 256)
+ * 1 = really tight
+ * 256 = turn off the feature
+ *
+ * Modified parameters:
+ * 24 bit pixbuf and its mask (used to prevent backtracking)
+ *
+ * Returns:
+ * TRUE - feature was recolored, thus coalesced
+ * FALSE - feature wasn't recolored
+ */
+
+static gboolean recolor( /* in */ double adaptive_tightness,
+ /* in */ int x,
+ /* in */ int y,
+ /* in */ int width,
+ /* in */ int height,
+ /* in/out */ unsigned char *bitmap,
+ /* in/out */ unsigned char *mask)
+{
+ unsigned char *index, *to_index;
+ int error_amt, max_error;
+
+ index = &bitmap[3 * (y * width + x)];
+ to_index = NULL;
+ error_amt = 0;
+ max_error = (int)(3.0 * adaptive_tightness * adaptive_tightness);
+
+ find_most_similar_neighbor(index, &to_index, &error_amt, x, y, width, height, bitmap, mask);
+
+ /* This condition only fails if the bitmap is all the same color */
+ if (to_index != NULL) {
+ /*
+ * If the difference between the two colors is too great,
+ * don't coalesce the feature with its neighbor(s). This prevents a
+ * color from turning into its complement.
+ */
+
+ if (calc_error(index, to_index) > max_error)
+ fill(index, x, y, width, height, bitmap, mask);
+ else {
+ fill(to_index, x, y, width, height, bitmap, mask);
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/* Recolor - conditionally change a feature's color to the closest color of all
+ * neighboring pixels
+ *
+ * Input parameters:
+ * The color palette, current blob size, and adaptive tightness
+ *
+ * Adaptive Tightness: (integer 1 to 256)
+ * 1 = really tight
+ * 256 = turn off the feature
+ *
+ * Modified parameters:
+ * 8 bit pixbuf and its mask (used to prevent backtracking)
+ *
+ * Returns:
+ * TRUE - feature was recolored, thus coalesced
+ * FALSE - feature wasn't recolored
+ */
+
+static gboolean recolor_8( /* in */ double adaptive_tightness,
+ /* in */ int x,
+ /* in */ int y,
+ /* in */ int width,
+ /* in */ int height,
+ /* in/out */ unsigned char *bitmap,
+ /* in/out */ unsigned char *mask)
+{
+ unsigned char *index, *to_index;
+ int error_amt;
+
+ index = &bitmap[(y * width + x)];
+ to_index = NULL;
+ error_amt = 0;
+
+ find_most_similar_neighbor_8(index, &to_index, &error_amt, x, y, width, height, bitmap, mask);
+
+ /* This condition only fails if the bitmap is all the same color */
+ if (to_index != NULL) {
+ /*
+ * If the difference between the two colors is too great,
+ * don't coalesce the feature with its neighbor(s). This prevents a
+ * color from turning into its complement.
+ */
+
+ if (calc_error_8(index, to_index) > adaptive_tightness)
+ fill_8(index, x, y, width, height, bitmap, mask);
+ else {
+ fill_8(to_index, x, y, width, height, bitmap, mask);
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/* Despeckle Iteration - Despeckle all regions smaller than cur_size pixels
+ *
+ * Input Parameters:
+ * Current blob size, maximum blob size
+ * for all iterations (used to selectively recolor blobs), adaptive
+ * tightness and noise removal
+ *
+ * Modified Parameters:
+ * The 24 bit pixbuf is despeckled
+ */
+
+static void despeckle_iteration( /* in */ int level,
+ /* in */ double adaptive_tightness,
+ /* in */ double noise_max,
+ /* in */ int width,
+ /* in */ int height,
+ /* in/out */ unsigned char *bitmap)
+{
+ unsigned char *mask;
+ int x, y;
+ int current_size;
+ int tightness;
+
+ /* Size doubles each iteration level, so current_size = 2^level */
+ current_size = 1 << level;
+ tightness = (int)(noise_max / (1.0 + adaptive_tightness * level));
+
+ mask = (unsigned char *)calloc(width * height, sizeof(unsigned char));
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ if (mask[y * width + x] == 0) {
+ int size;
+
+ size = find_size(&bitmap[3 * (y * width + x)], x, y, width, height, bitmap, mask);
+
+ assert(size > 0);
+
+ if (size < current_size) {
+ if (recolor(tightness, x, y, width, height, bitmap, mask))
+ x--;
+ } else
+ ignore(x, y, width, height, mask);
+ }
+ }
+ }
+
+ free(mask);
+}
+
+/* Despeckle Iteration - Despeckle all regions smaller than cur_size pixels
+ *
+ * Input Parameters:
+ * Current blob size, maximum blob size
+ * for all iterations (used to selectively recolor blobs), adaptive
+ * tightness and noise removal
+ *
+ * Modified Parameters:
+ * The 8 bit pixbuf is despeckled
+ */
+
+static void despeckle_iteration_8( /* in */ int level,
+ /* in */ double adaptive_tightness,
+ /* in */ double noise_max,
+ /* in */ int width,
+ /* in */ int height,
+ /* in/out */ unsigned char *bitmap)
+{
+ unsigned char *mask;
+ int x, y;
+ int current_size;
+ int tightness;
+
+ /* Size doubles each iteration level, so current_size = 2^level */
+ current_size = 1 << level;
+ tightness = (int)(noise_max / (1.0 + adaptive_tightness * level));
+
+ mask = (unsigned char *)calloc(width * height, sizeof(unsigned char));
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ if (mask[y * width + x] == 0) {
+ int size;
+
+ size = find_size_8(&bitmap[(y * width + x)], x, y, width, height, bitmap, mask);
+
+ assert(size > 0);
+
+ if (size < current_size) {
+ if (recolor_8(tightness, x, y, width, height, bitmap, mask))
+ x--;
+ } else
+ ignore(x, y, width, height, mask);
+ }
+ }
+ }
+
+ free(mask);
+}
+
+/* Despeckle - Despeckle a 8 or 24 bit image
+ *
+ * Input Parameters:
+ * Adaptive feature coalescing value, the despeckling level and noise removal
+ *
+ * Despeckling level (level): Integer from 0 to ~20
+ * 0 = perform no despeckling
+ * An increase of the despeckling level by one doubles the size of features.
+ * The Maximum value must be smaller then the logarithm base two of the number
+ * of pixels.
+ *
+ * Feature coalescing (tightness): Real from 0.0 to ~8.0
+ * 0 = Turn it off (whites may turn black and vice versa, etc)
+ * 3 = Good middle value
+ * 8 = Really tight
+ *
+ * Noise removal (noise_removal): Real from 1.0 to 0.0
+ * 1 = Maximum noise removal
+ * You should always use the highest value, only if certain parts of the image
+ * disappear you should lower it.
+ *
+ * Modified Parameters:
+ * The bitmap is despeckled.
+ */
+
+void despeckle( /* in/out */ at_bitmap * bitmap,
+ /* in */ int level,
+ /* in */ gfloat tightness,
+ /* in */ gfloat noise_removal,
+ /* exception handling */ at_exception_type * excep)
+{
+ int i, planes, max_level;
+ short width, height;
+ unsigned char *bits;
+ double noise_max, adaptive_tightness;
+
+ planes = AT_BITMAP_PLANES(bitmap);
+ noise_max = noise_removal * 255.0;
+ width = AT_BITMAP_WIDTH(bitmap);
+ height = AT_BITMAP_HEIGHT(bitmap);
+ bits = AT_BITMAP_BITS(bitmap);
+ max_level = (int)(log(width * height) / log(2.0) - 0.5);
+ if (level > max_level)
+ level = max_level;
+ adaptive_tightness = (noise_removal * (1.0 + tightness * level) - 1.0) / level;
+
+ if (planes == 3) {
+ for (i = 0; i < level; i++)
+ despeckle_iteration(i, adaptive_tightness, noise_max, width, height, bits);
+ } else if (planes == 1) {
+ for (i = 0; i < level; i++)
+ despeckle_iteration_8(i, adaptive_tightness, noise_max, width, height, bits);
+ } else {
+ LOG("despeckle: %u-plane images are not supported", planes);
+ at_exception_fatal(excep, "despeckle: wrong plane images are passed");
+ return;
+ }
+
+}
diff --git a/src/3rdparty/autotrace/despeckle.h b/src/3rdparty/autotrace/despeckle.h
new file mode 100644
index 0000000..3b206e7
--- /dev/null
+++ b/src/3rdparty/autotrace/despeckle.h
@@ -0,0 +1,54 @@
+/* despeckle.h: Bitmap despeckler for AutoTrace
+
+ Copyright (C) 2001 David A. Bartold / Martin Weber
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License
+ as published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA. */
+
+#ifndef DESPECKLE_H
+#define DESPECKLE_H
+
+#include "types.h"
+#include "bitmap.h"
+#include "exception.h"
+
+/* Despeckle - Despeckle a 8 or 24 bit image
+ *
+ * Input Parameters:
+ * Adaptive feature coalescing value, the despeckling level and noise removal
+ *
+ * Despeckling level (level): Integer from 0 to ~20
+ * 0 = perform no despeckling
+ * An increase of the despeckling level by one doubles the size of features.
+ * The Maximum value must be smaller then the logarithm base two of the number
+ * of pixels.
+ *
+ * Feature coalescing (tightness): Real from 0.0 to ~8.0
+ * 0 = Turn it off (whites may turn black and vice versa, etc)
+ * 3 = Good middle value
+ * 8 = Really tight
+ *
+ * Noise removal (noise_removal): Real from 1.0 to 0.0
+ * 1 = Maximum noise removal
+ * You should always use the highest value, only if certain parts of the image
+ * disappear you should lower it.
+ *
+ * Modified Parameters:
+ * The bitmap is despeckled.
+ */
+
+extern void despeckle(at_bitmap * bitmap, int level, gfloat tightness, gfloat noise_removal, at_exception_type * exp);
+
+#endif /* not DESPECKLE_H */
diff --git a/src/3rdparty/autotrace/epsilon-equal.c b/src/3rdparty/autotrace/epsilon-equal.c
new file mode 100644
index 0000000..8d26886
--- /dev/null
+++ b/src/3rdparty/autotrace/epsilon-equal.c
@@ -0,0 +1,22 @@
+/* epsilon-equal.c: define a error resist compare. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* Def: HAVE_CONFIG_H */
+
+#include "types.h"
+#include "epsilon-equal.h"
+#include <math.h>
+
+/* Numerical errors sometimes make a floating point number just slightly
+ larger or smaller than its TRUE value. When it matters, we need to
+ compare with some tolerance, REAL_EPSILON, defined in kbase.h. */
+
+gboolean epsilon_equal(gfloat v1, gfloat v2)
+{
+ if (v1 == v2 /* Usually they'll be exactly equal, anyway. */
+ || fabs(v1 - v2) <= REAL_EPSILON)
+ return TRUE;
+
+ return FALSE;
+}
diff --git a/src/3rdparty/autotrace/epsilon-equal.h b/src/3rdparty/autotrace/epsilon-equal.h
new file mode 100644
index 0000000..8b547ba
--- /dev/null
+++ b/src/3rdparty/autotrace/epsilon-equal.h
@@ -0,0 +1,17 @@
+/* epsilon-equal.h: define an error resist compare. */
+
+#ifndef EPSILON_EQUAL_H
+#define EPSILON_EQUAL_H
+
+#include "types.h"
+
+/* Says whether V1 and V2 are within REAL_EPSILON of each other.
+ Fixed-point arithmetic would be better, to guarantee machine
+ independence, but it's so much more painful to work with. The value
+ here is smaller than can be represented in either a `fix_word' or a
+ `scaled_num', so more precision than this will be lost when we
+ output, anyway. */
+extern gboolean epsilon_equal(gfloat v1, gfloat v2);
+#define REAL_EPSILON 0.00001
+
+#endif /* not EPSILON_EQUAL_H */
diff --git a/src/3rdparty/autotrace/exception.c b/src/3rdparty/autotrace/exception.c
new file mode 100644
index 0000000..c98777e
--- /dev/null
+++ b/src/3rdparty/autotrace/exception.c
@@ -0,0 +1,47 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* Def: HAVE_CONFIG_H */
+
+#include "exception.h"
+
+at_exception_type at_exception_new(at_msg_func client_func, gpointer client_data)
+{
+ at_exception_type e;
+ e.msg_type = AT_MSG_NOT_SET;
+ e.client_func = client_func;
+ e.client_data = client_data;
+ return e;
+}
+
+gboolean at_exception_got_fatal(at_exception_type * exception)
+{
+ return (exception->msg_type == AT_MSG_FATAL) ? TRUE : FALSE;
+}
+
+void at_exception_fatal(at_exception_type * exception, const gchar * message)
+{
+ if (!exception)
+ return;
+ exception->msg_type = AT_MSG_FATAL;
+ if (exception->client_func) {
+ exception->client_func(message, AT_MSG_FATAL, exception->client_data);
+ }
+}
+
+void at_exception_warning(at_exception_type * exception, const gchar * message)
+{
+ if (!exception)
+ return;
+ exception->msg_type = AT_MSG_WARNING;
+ if (exception->client_func) {
+ exception->client_func(message, AT_MSG_WARNING, exception->client_data);
+ }
+}
+
+GQuark at_error_quark(void)
+{
+ static GQuark q = 0;
+ if (q == 0)
+ q = g_quark_from_static_string("at-error-quark");
+ return q;
+}
diff --git a/src/3rdparty/autotrace/exception.h b/src/3rdparty/autotrace/exception.h
new file mode 100644
index 0000000..793e879
--- /dev/null
+++ b/src/3rdparty/autotrace/exception.h
@@ -0,0 +1,39 @@
+/* exception.h: facility to handle error in autotrace */
+
+#ifndef AT_EXCEPTION_H
+#define AT_EXCEPTION_H
+
+#include "autotrace.h"
+#include "types.h"
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Protocol:
+ If a function raises a FATAL(including propagation),
+ the function must release resources allocated by the
+ function itself. */
+ typedef struct _at_exception_type at_exception_type;
+ struct _at_exception_type {
+ at_msg_type msg_type;
+ at_msg_func client_func;
+ gpointer client_data;
+ };
+
+ at_exception_type at_exception_new(at_msg_func client_func, gpointer client_data);
+ gboolean at_exception_got_fatal(at_exception_type * exception);
+ void at_exception_fatal(at_exception_type * exception, const gchar * message);
+ void at_exception_warning(at_exception_type * exception, const gchar * message);
+
+#define AT_ERROR at_error_quark()
+ GQuark at_error_quark(void);
+ typedef enum {
+ AT_ERROR_WRONG_COLOR_STRING,
+ } AtError;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* Not def: AT_EXCEPTION_H */
diff --git a/src/3rdparty/autotrace/filename.c b/src/3rdparty/autotrace/filename.c
new file mode 100644
index 0000000..3ae8c58
--- /dev/null
+++ b/src/3rdparty/autotrace/filename.c
@@ -0,0 +1,45 @@
+/* filename.c: Function manipulate file names
+ Was: find-suffix, remove-suffix */
+
+/* remove-suffx.c: remove any suffix.
+
+Copyright (C) 1999 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* Def: HAVE_CONFIG_H */
+
+#include "filename.h"
+#include "xstd.h"
+#include <string.h>
+#include <glib.h>
+
+gchar *find_suffix(gchar * name)
+{
+ gchar *dot_pos = strrchr(name, '.');
+ gchar *slash_pos = strrchr(name, G_DIR_SEPARATOR);
+
+ /* If the name is `foo' or `/foo.bar/baz', we have no extension. */
+ return dot_pos == NULL || dot_pos < slash_pos ? NULL : dot_pos + 1;
+}
+
+gchar *remove_suffix(gchar * s)
+{
+ gchar *suffix = find_suffix(s);
+
+ return suffix == NULL ? s : suffix - 2 - s < 0 ? NULL : g_strndup(s, (unsigned)(suffix - 2 - s));
+}
diff --git a/src/3rdparty/autotrace/filename.h b/src/3rdparty/autotrace/filename.h
new file mode 100644
index 0000000..baf373d
--- /dev/null
+++ b/src/3rdparty/autotrace/filename.h
@@ -0,0 +1,33 @@
+/* filename.h: Function manipulate file names
+ Was: find-suffix, remove-suffix */
+
+/* remove-suffx.h: declarations for shared routines.
+
+Copyright (C) 1992 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef FILENAME_H
+#define FILENAME_H
+#include "types.h"
+
+/* If NAME has a suffix, return a pointer to its first character (i.e.,
+ the one after the `.'); otherwise, return NULL. */
+extern gchar *find_suffix(gchar * name);
+
+/* Return NAME with any suffix removed. */
+extern gchar *remove_suffix(gchar * name);
+
+#endif /* Not def: FILENAME_H */
diff --git a/src/3rdparty/autotrace/fit.c b/src/3rdparty/autotrace/fit.c
new file mode 100644
index 0000000..ffc0556
--- /dev/null
+++ b/src/3rdparty/autotrace/fit.c
@@ -0,0 +1,1442 @@
+/* fit.c: turn a bitmap representation of a curve into a list of splines.
+ Some of the ideas, but not the code, comes from the Phoenix thesis.
+ See README for the reference.
+
+ The code was partially derived from limn.
+
+ Copyright (C) 1992 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* Def: HAVE_CONFIG_H */
+
+#include "autotrace.h"
+#include "fit.h"
+#include "logreport.h"
+#include "spline.h"
+#include "vector.h"
+#include "curve.h"
+#include "pxl-outline.h"
+#include "epsilon-equal.h"
+#include "xstd.h"
+#include <math.h>
+#ifndef FLT_MAX
+#include <limits.h>
+#include <float.h>
+#endif
+#ifndef FLT_MIN
+#include <limits.h>
+#include <float.h>
+#endif
+#include <string.h>
+#include <assert.h>
+
+#define SQUARE(x) ((x) * (x))
+#define CUBE(x) ((x) * (x) * (x))
+
+/* We need to manipulate lists of array indices. */
+
+typedef struct index_list {
+ unsigned *data;
+ unsigned length;
+} index_list_type;
+
+/* The usual accessor macros. */
+#define GET_INDEX(i_l, n) ((i_l).data[n])
+#define INDEX_LIST_LENGTH(i_l) ((i_l).length)
+#define GET_LAST_INDEX(i_l) ((i_l).data[INDEX_LIST_LENGTH (i_l) - 1])
+
+static void append_index(index_list_type *, unsigned);
+static void free_index_list(index_list_type *);
+static index_list_type new_index_list(void);
+static void remove_adjacent_corners(index_list_type *, unsigned, gboolean, at_exception_type * exception);
+static void change_bad_lines(spline_list_type *, fitting_opts_type *);
+static void filter(curve_type, fitting_opts_type *);
+static void find_vectors(unsigned, pixel_outline_type, vector_type *, vector_type *, unsigned);
+static index_list_type find_corners(pixel_outline_type, fitting_opts_type *, at_exception_type * exception);
+static gfloat find_error(curve_type, spline_type, unsigned *, at_exception_type * exception);
+static vector_type find_half_tangent(curve_type, gboolean start, unsigned *, unsigned);
+static void find_tangent(curve_type, gboolean, gboolean, unsigned);
+static spline_type fit_one_spline(curve_type, at_exception_type * exception);
+static spline_list_type *fit_curve(curve_type, fitting_opts_type *, at_exception_type * exception);
+static spline_list_type fit_curve_list(curve_list_type, fitting_opts_type *, at_distance_map *, at_exception_type * exception);
+static spline_list_type *fit_with_least_squares(curve_type, fitting_opts_type *, at_exception_type * exception);
+static spline_list_type *fit_with_line(curve_type);
+static void remove_knee_points(curve_type, gboolean);
+static void set_initial_parameter_values(curve_type);
+static gboolean spline_linear_enough(spline_type *, curve_type, fitting_opts_type *);
+static curve_list_array_type split_at_corners(pixel_outline_list_type, fitting_opts_type *, at_exception_type * exception);
+static at_coord real_to_int_coord(at_real_coord);
+static gfloat distance(at_real_coord, at_real_coord);
+
+/* Get a new set of fitting options */
+fitting_opts_type new_fitting_opts(void)
+{
+ fitting_opts_type fitting_opts;
+
+ fitting_opts.background_color = NULL;
+ fitting_opts.charcode = 0;
+ fitting_opts.color_count = 0;
+ fitting_opts.corner_always_threshold = (gfloat) 60.0;
+ fitting_opts.corner_surround = 4;
+ fitting_opts.corner_threshold = (gfloat) 100.0;
+ fitting_opts.error_threshold = (gfloat) 2.0;
+ fitting_opts.filter_iterations = 4;
+ fitting_opts.line_reversion_threshold = (gfloat) .01;
+ fitting_opts.line_threshold = (gfloat) 1.0;
+ fitting_opts.remove_adjacent_corners = FALSE;
+ fitting_opts.tangent_surround = 3;
+ fitting_opts.despeckle_level = 0;
+ fitting_opts.despeckle_tightness = 2.0;
+ fitting_opts.noise_removal = (gfloat) 0.99;
+ fitting_opts.centerline = FALSE;
+ fitting_opts.preserve_width = FALSE;
+ fitting_opts.width_weight_factor = 6.0;
+
+ return (fitting_opts);
+}
+
+/* The top-level call that transforms the list of pixels in the outlines
+ of the original character to a list of spline lists fitted to those
+ pixels. */
+
+spline_list_array_type fitted_splines(pixel_outline_list_type pixel_outline_list, fitting_opts_type * fitting_opts, at_distance_map * dist, unsigned short width, unsigned short height, at_exception_type * exception, at_progress_func notify_progress, gpointer progress_data, at_testcancel_func test_cancel, gpointer testcancel_data)
+{
+ unsigned this_list;
+
+ spline_list_array_type char_splines = new_spline_list_array();
+ curve_list_array_type curve_array = split_at_corners(pixel_outline_list,
+ fitting_opts,
+ exception);
+
+ char_splines.centerline = fitting_opts->centerline;
+ char_splines.preserve_width = fitting_opts->preserve_width;
+ char_splines.width_weight_factor = fitting_opts->width_weight_factor;
+
+ if (fitting_opts->background_color)
+ char_splines.background_color = at_color_copy(fitting_opts->background_color);
+ else
+ char_splines.background_color = NULL;
+ /* Set dummy values. Real value is set in upper context. */
+ char_splines.width = width;
+ char_splines.height = height;
+
+ for (this_list = 0; this_list < CURVE_LIST_ARRAY_LENGTH(curve_array); this_list++) {
+ spline_list_type curve_list_splines;
+ curve_list_type curves = CURVE_LIST_ARRAY_ELT(curve_array, this_list);
+
+ if (notify_progress)
+ notify_progress((((gfloat) this_list) / ((gfloat) CURVE_LIST_ARRAY_LENGTH(curve_array) * (gfloat) 3.0) + (gfloat) 0.333), progress_data);
+ if (test_cancel && test_cancel(testcancel_data))
+ goto cleanup;
+
+ LOG("\nFitting curve list #%u:\n", this_list);
+
+ curve_list_splines = fit_curve_list(curves, fitting_opts, dist, exception);
+ if (at_exception_got_fatal(exception)) {
+ if (char_splines.background_color)
+ at_color_free(char_splines.background_color);
+ goto cleanup;
+ }
+ curve_list_splines.clockwise = curves.clockwise;
+
+ memcpy(&(curve_list_splines.color), &(O_LIST_OUTLINE(pixel_outline_list, this_list).color), sizeof(at_color));
+ append_spline_list(&char_splines, curve_list_splines);
+ }
+cleanup:
+ free_curve_list_array(&curve_array, notify_progress, progress_data);
+
+ return char_splines;
+}
+
+/* Fit the list of curves CURVE_LIST to a list of splines, and return
+ it. CURVE_LIST represents a single closed paths, e.g., either the
+ inside or outside outline of an `o'. */
+
+static spline_list_type fit_curve_list(curve_list_type curve_list, fitting_opts_type * fitting_opts, at_distance_map * dist, at_exception_type * exception)
+{
+ curve_type curve;
+ unsigned this_curve, this_spline;
+ unsigned curve_list_length = CURVE_LIST_LENGTH(curve_list);
+ spline_list_type curve_list_splines = empty_spline_list();
+
+ curve_list_splines.open = curve_list.open;
+
+ /* Remove the extraneous ``knee'' points before filtering. Since the
+ corners have already been found, we don't need to worry about
+ removing a point that should be a corner. */
+
+ LOG("\nRemoving knees:\n");
+ for (this_curve = 0; this_curve < curve_list_length; this_curve++) {
+ LOG("#%u:", this_curve);
+ remove_knee_points(CURVE_LIST_ELT(curve_list, this_curve), CURVE_LIST_CLOCKWISE(curve_list));
+ }
+
+ if (dist != NULL) {
+ unsigned this_point;
+ unsigned height = dist->height;
+ for (this_curve = 0; this_curve < curve_list_length; this_curve++) {
+ curve = CURVE_LIST_ELT(curve_list, this_curve);
+ for (this_point = 0; this_point < CURVE_LENGTH(curve); this_point++) {
+ unsigned x, y;
+ float width, w;
+ at_real_coord *coord = &CURVE_POINT(curve, this_point);
+ x = (unsigned)(coord->x);
+ y = height - (unsigned)(coord->y) - 1;
+
+ /* Each (x, y) is a point on the skeleton of the curve, which
+ might be offset from the TRUE centerline, where the width
+ is maximal. Therefore, use as the local line width the
+ maximum distance over the neighborhood of (x, y). */
+ width = dist->d[y][x];
+ if (y >= 1) {
+ if ((w = dist->d[y - 1][x]) > width)
+ width = w;
+ if (x >= 1) {
+ if ((w = dist->d[y][x - 1]) > width)
+ width = w;
+ if ((w = dist->d[y - 1][x - 1]) > width)
+ width = w;
+ }
+ if (x + 1 < dist->width) {
+ if ((w = dist->d[y][x + 1]) > width)
+ width = w;
+ if ((w = dist->d[y - 1][x + 1]) > width)
+ width = w;
+ }
+ }
+ if (y + 1 < height) {
+ if ((w = dist->d[y + 1][x]) > width)
+ width = w;
+ if (x >= 1 && (w = dist->d[y + 1][x - 1]) > width)
+ width = w;
+ if (x + 1 < dist->width && (w = dist->d[y + 1][x + 1]) > width)
+ width = w;
+ }
+ coord->z = width * (fitting_opts->width_weight_factor);
+ }
+ }
+ }
+
+ /* We filter all the curves in CURVE_LIST at once; otherwise, we would
+ look at an unfiltered curve when computing tangents. */
+
+ LOG("\nFiltering curves:\n");
+ for (this_curve = 0; this_curve < curve_list.length; this_curve++) {
+ LOG("#%u: ", this_curve);
+ filter(CURVE_LIST_ELT(curve_list, this_curve), fitting_opts);
+ }
+
+ /* Make the first point in the first curve also be the last point in
+ the last curve, so the fit to the whole curve list will begin and
+ end at the same point. This may cause slight errors in computing
+ the tangents and t values, but it's worth it for the continuity.
+ Of course we don't want to do this if the two points are already
+ the same, as they are if the curve is cyclic. (We don't append it
+ earlier, in `split_at_corners', because that confuses the
+ filtering.) Finally, we can't append the point if the curve is
+ exactly three points long, because we aren't adding any more data,
+ and three points isn't enough to determine a spline. Therefore,
+ the fitting will fail. */
+ curve = CURVE_LIST_ELT(curve_list, 0);
+ if (CURVE_CYCLIC(curve) == TRUE)
+ append_point(curve, CURVE_POINT(curve, 0));
+
+ /* Finally, fit each curve in the list to a list of splines. */
+ for (this_curve = 0; this_curve < curve_list_length; this_curve++) {
+ spline_list_type *curve_splines;
+ curve_type current_curve = CURVE_LIST_ELT(curve_list, this_curve);
+
+ LOG("\nFitting curve #%u:\n", this_curve);
+
+ curve_splines = fit_curve(current_curve, fitting_opts, exception);
+ if (at_exception_got_fatal(exception))
+ goto cleanup;
+ else if (curve_splines == NULL) {
+ LOG("Could not fit curve #%u", this_curve);
+ at_exception_warning(exception, "Could not fit curve");
+ } else {
+ LOG("Fitted splines for curve #%u:\n", this_curve);
+ for (this_spline = 0; this_spline < SPLINE_LIST_LENGTH(*curve_splines); this_spline++) {
+ LOG(" %u: ", this_spline);
+ if (logging)
+ print_spline(SPLINE_LIST_ELT(*curve_splines, this_spline));
+ }
+
+ /* After fitting, we may need to change some would-be lines
+ back to curves, because they are in a list with other
+ curves. */
+ change_bad_lines(curve_splines, fitting_opts);
+
+ concat_spline_lists(&curve_list_splines, *curve_splines);
+ free_spline_list(*curve_splines);
+ free(curve_splines);
+ }
+ }
+
+ if (logging) {
+ LOG("\nFitted splines are:\n");
+ for (this_spline = 0; this_spline < SPLINE_LIST_LENGTH(curve_list_splines); this_spline++) {
+ LOG(" %u: ", this_spline);
+ print_spline(SPLINE_LIST_ELT(curve_list_splines, this_spline));
+ }
+ }
+cleanup:
+ return curve_list_splines;
+}
+
+/* Transform a set of locations to a list of splines (the fewer the
+ better). We are guaranteed that CURVE does not contain any corners.
+ We return NULL if we cannot fit the points at all. */
+
+static spline_list_type *fit_curve(curve_type curve, fitting_opts_type * fitting_opts, at_exception_type * exception)
+{
+ spline_list_type *fittedsplines;
+
+ if (CURVE_LENGTH(curve) < 2) {
+ LOG("Tried to fit curve with less than two points");
+ at_exception_warning(exception, "Tried to fit curve with less than two points");
+ return NULL;
+ }
+
+ /* Do we have enough points to fit with a spline? */
+ fittedsplines = CURVE_LENGTH(curve) < 4 ? fit_with_line(curve)
+ : fit_with_least_squares(curve, fitting_opts, exception);
+
+ return fittedsplines;
+}
+
+/* As mentioned above, the first step is to find the corners in
+ PIXEL_LIST, the list of points. (Presumably we can't fit a single
+ spline around a corner.) The general strategy is to look through all
+ the points, remembering which we want to consider corners. Then go
+ through that list, producing the curve_list. This is dictated by the
+ fact that PIXEL_LIST does not necessarily start on a corner---it just
+ starts at the character's first outline pixel, going left-to-right,
+ top-to-bottom. But we want all our splines to start and end on real
+ corners.
+
+ For example, consider the top of a capital `C' (this is in cmss20):
+ x
+ ***********
+ ******************
+
+ PIXEL_LIST will start at the pixel below the `x'. If we considered
+ this pixel a corner, we would wind up matching a very small segment
+ from there to the end of the line, probably as a straight line, which
+ is certainly not what we want.
+
+ PIXEL_LIST has one element for each closed outline on the character.
+ To preserve this information, we return an array of curve_lists, one
+ element (which in turn consists of several curves, one between each
+ pair of corners) for each element in PIXEL_LIST. */
+
+static curve_list_array_type split_at_corners(pixel_outline_list_type pixel_list, fitting_opts_type * fitting_opts, at_exception_type * exception)
+{
+ unsigned this_pixel_o;
+ curve_list_array_type curve_array = new_curve_list_array();
+
+ LOG("\nFinding corners:\n");
+
+ for (this_pixel_o = 0; this_pixel_o < O_LIST_LENGTH(pixel_list); this_pixel_o++) {
+ curve_type curve, first_curve;
+ index_list_type corner_list;
+ unsigned p, this_corner;
+ curve_list_type curve_list = new_curve_list();
+ pixel_outline_type pixel_o = O_LIST_OUTLINE(pixel_list, this_pixel_o);
+
+ CURVE_LIST_CLOCKWISE(curve_list) = O_CLOCKWISE(pixel_o);
+ curve_list.open = pixel_o.open;
+
+ LOG("#%u:", this_pixel_o);
+
+ /* If the outline does not have enough points, we can't do
+ anything. The endpoints of the outlines are automatically
+ corners. We need at least `corner_surround' more pixels on
+ either side of a point before it is conceivable that we might
+ want another corner. */
+ if (O_LENGTH(pixel_o) > fitting_opts->corner_surround * 2 + 2)
+ corner_list = find_corners(pixel_o, fitting_opts, exception);
+
+ else {
+ int surround;
+ if ((surround = (int)(O_LENGTH(pixel_o) - 3) / 2) >= 2) {
+ unsigned save_corner_surround = fitting_opts->corner_surround;
+ fitting_opts->corner_surround = surround;
+ corner_list = find_corners(pixel_o, fitting_opts, exception);
+ fitting_opts->corner_surround = save_corner_surround;
+ } else {
+ corner_list.length = 0;
+ corner_list.data = NULL;
+ }
+ }
+
+ /* Remember the first curve so we can make it be the `next' of the
+ last one. (And vice versa.) */
+ first_curve = new_curve();
+
+ curve = first_curve;
+
+ if (corner_list.length == 0) { /* No corners. Use all of the pixel outline as the curve. */
+ for (p = 0; p < O_LENGTH(pixel_o); p++)
+ append_pixel(curve, O_COORDINATE(pixel_o, p));
+
+ if (curve_list.open == TRUE)
+ CURVE_CYCLIC(curve) = FALSE;
+ else
+ CURVE_CYCLIC(curve) = TRUE;
+ } else { /* Each curve consists of the points between (inclusive) each pair
+ of corners. */
+ for (this_corner = 0; this_corner < corner_list.length - 1; this_corner++) {
+ curve_type previous_curve = curve;
+ unsigned corner = GET_INDEX(corner_list, this_corner);
+ unsigned next_corner = GET_INDEX(corner_list, this_corner + 1);
+
+ for (p = corner; p <= next_corner; p++)
+ append_pixel(curve, O_COORDINATE(pixel_o, p));
+
+ append_curve(&curve_list, curve);
+ curve = new_curve();
+ NEXT_CURVE(previous_curve) = curve;
+ PREVIOUS_CURVE(curve) = previous_curve;
+ }
+
+ /* The last curve is different. It consists of the points
+ (inclusive) between the last corner and the end of the list,
+ and the beginning of the list and the first corner. */
+ for (p = GET_LAST_INDEX(corner_list); p < O_LENGTH(pixel_o); p++)
+ append_pixel(curve, O_COORDINATE(pixel_o, p));
+
+ if (!pixel_o.open) {
+ for (p = 0; p <= GET_INDEX(corner_list, 0); p++)
+ append_pixel(curve, O_COORDINATE(pixel_o, p));
+ } else {
+ curve_type last_curve = PREVIOUS_CURVE(curve);
+ PREVIOUS_CURVE(first_curve) = NULL;
+ if (last_curve)
+ NEXT_CURVE(last_curve) = NULL;
+ }
+ }
+
+ LOG(" [%u].\n", corner_list.length);
+ free_index_list(&corner_list);
+
+ /* Add `curve' to the end of the list, updating the pointers in
+ the chain. */
+ append_curve(&curve_list, curve);
+ NEXT_CURVE(curve) = first_curve;
+ PREVIOUS_CURVE(first_curve) = curve;
+
+ /* And now add the just-completed curve list to the array. */
+ append_curve_list(&curve_array, curve_list);
+ } /* End of considering each pixel outline. */
+
+ return curve_array;
+}
+
+/* We consider a point to be a corner if (1) the angle defined by the
+ `corner_surround' points coming into it and going out from it is less
+ than `corner_threshold' degrees, and no point within
+ `corner_surround' points has a smaller angle; or (2) the angle is less
+ than `corner_always_threshold' degrees.
+
+ Because of the different cases, it is convenient to have the
+ following macro to append a corner on to the list we return. The
+ character argument C is simply so that the different cases can be
+ distinguished in the log file. */
+
+#define APPEND_CORNER(index, angle, c) \
+ do \
+ { \
+ append_index (&corner_list, index); \
+ LOG (" (%d,%d)%c%.3f", \
+ O_COORDINATE (pixel_outline, index).x, \
+ O_COORDINATE (pixel_outline, index).y, \
+ c, angle); \
+ } \
+ while (0)
+
+static index_list_type find_corners(pixel_outline_type pixel_outline, fitting_opts_type * fitting_opts, at_exception_type * exception)
+{
+ unsigned p, start_p, end_p;
+ index_list_type corner_list = new_index_list();
+
+ start_p = 0;
+ end_p = O_LENGTH(pixel_outline) - 1;
+ if (pixel_outline.open) {
+ if (end_p <= fitting_opts->corner_surround * 2)
+ return corner_list;
+ APPEND_CORNER(0, 0.0, '@');
+ start_p += fitting_opts->corner_surround;
+ end_p -= fitting_opts->corner_surround;
+ }
+
+ /* Consider each pixel on the outline in turn. */
+ for (p = start_p; p <= end_p; p++) {
+ gfloat corner_angle;
+ vector_type in_vector, out_vector;
+
+ /* Check if the angle is small enough. */
+ find_vectors(p, pixel_outline, &in_vector, &out_vector, fitting_opts->corner_surround);
+ corner_angle = Vangle(in_vector, out_vector, exception);
+ if (at_exception_got_fatal(exception))
+ goto cleanup;
+
+ if (fabs(corner_angle) <= fitting_opts->corner_threshold) {
+ /* We want to keep looking, instead of just appending the
+ first pixel we find with a small enough angle, since there
+ might be another corner within `corner_surround' pixels, with
+ a smaller angle. If that is the case, we want that one. */
+ gfloat best_corner_angle = corner_angle;
+ unsigned best_corner_index = p;
+ index_list_type equally_good_list = new_index_list();
+ /* As we come into the loop, `p' is the index of the point
+ that has an angle less than `corner_angle'. We use `i' to
+ move through the pixels next to that, and `q' for moving
+ through the adjacent pixels to each `p'. */
+ unsigned q = p;
+ unsigned i = p + 1;
+
+ while (TRUE) {
+ /* Perhaps the angle is sufficiently small that we want to
+ consider this a corner, even if it's not the best
+ (unless we've already wrapped around in the search,
+ i.e., `q<i', in which case we have already added the
+ corner, and we don't want to add it again). We want to
+ do this check on the first candidate we find, as well
+ as the others in the loop, hence this comes before the
+ stopping condition. */
+ if (corner_angle <= fitting_opts->corner_always_threshold && q >= p)
+ APPEND_CORNER(q, corner_angle, '\\');
+
+ /* Exit the loop if we've looked at `corner_surround'
+ pixels past the best one we found, or if we've looked
+ at all the pixels. */
+ if (i >= best_corner_index + fitting_opts->corner_surround || i >= O_LENGTH(pixel_outline))
+ break;
+
+ /* Check the angle. */
+ q = i % O_LENGTH(pixel_outline);
+ find_vectors(q, pixel_outline, &in_vector, &out_vector, fitting_opts->corner_surround);
+ corner_angle = Vangle(in_vector, out_vector, exception);
+ if (at_exception_got_fatal(exception))
+ goto cleanup;
+
+ /* If we come across a corner that is just as good as the
+ best one, we should make it a corner, too. This
+ happens, for example, at the points on the `W' in some
+ typefaces, where the ``points'' are flat. */
+ if (epsilon_equal(corner_angle, best_corner_angle))
+ append_index(&equally_good_list, q);
+
+ else if (corner_angle < best_corner_angle) {
+ best_corner_angle = corner_angle;
+ /* We want to check `corner_surround' pixels beyond the
+ new best corner. */
+ i = best_corner_index = q;
+ free_index_list(&equally_good_list);
+ equally_good_list = new_index_list();
+ }
+
+ i++;
+ }
+
+ /* After we exit the loop, `q' is the index of the last point
+ we checked. We have already added the corner if
+ `best_corner_angle' is less than `corner_always_threshold'.
+ Again, if we've already wrapped around, we don't want to
+ add the corner again. */
+ if (best_corner_angle > fitting_opts->corner_always_threshold && best_corner_index >= p) {
+ unsigned j;
+
+ APPEND_CORNER(best_corner_index, best_corner_angle, '/');
+
+ for (j = 0; j < INDEX_LIST_LENGTH(equally_good_list); j++)
+ APPEND_CORNER(GET_INDEX(equally_good_list, j), best_corner_angle, '@');
+ }
+ free_index_list(&equally_good_list);
+
+ /* If we wrapped around in our search, we're done; otherwise,
+ we don't want the outer loop to look at the pixels that we
+ already looked at in searching for the best corner. */
+ p = (q < p) ? O_LENGTH(pixel_outline) : q;
+ } /* End of searching for the best corner. */
+ } /* End of considering each pixel. */
+
+ if (INDEX_LIST_LENGTH(corner_list) > 0)
+ /* We never want two corners next to each other, since the
+ only way to fit such a ``curve'' would be with a straight
+ line, which usually interrupts the continuity dreadfully. */
+ remove_adjacent_corners(&corner_list, O_LENGTH(pixel_outline) - (pixel_outline.open ? 2 : 1), fitting_opts->remove_adjacent_corners, exception);
+cleanup:
+ return corner_list;
+}
+
+/* Return the difference vectors coming in and going out of the outline
+ OUTLINE at the point whose index is TEST_INDEX. In Phoenix,
+ Schneider looks at a single point on either side of the point we're
+ considering. That works for him because his points are not touching.
+ But our points *are* touching, and so we have to look at
+ `corner_surround' points on either side, to get a better picture of
+ the outline's shape. */
+
+static void find_vectors(unsigned test_index, pixel_outline_type outline, vector_type * in, vector_type * out, unsigned corner_surround)
+{
+ int i;
+ unsigned n_done;
+ at_coord candidate = O_COORDINATE(outline, test_index);
+
+ in->dx = in->dy = in->dz = 0.0;
+ out->dx = out->dy = out->dz = 0.0;
+
+ /* Add up the differences from p of the `corner_surround' points
+ before p. */
+ for (i = O_PREV(outline, test_index), n_done = 0; n_done < corner_surround; i = O_PREV(outline, i), n_done++)
+ *in = Vadd(*in, IPsubtract(O_COORDINATE(outline, i), candidate));
+
+ /* And the points after p. */
+ for (i = O_NEXT(outline, test_index), n_done = 0; n_done < corner_surround; i = O_NEXT(outline, i), n_done++)
+ *out = Vadd(*out, IPsubtract(O_COORDINATE(outline, i), candidate));
+}
+
+/* Remove adjacent points from the index list LIST. We do this by first
+ sorting the list and then running through it. Since these lists are
+ quite short, a straight selection sort (e.g., p.139 of the Art of
+ Computer Programming, vol.3) is good enough. LAST_INDEX is the index
+ of the last pixel on the outline, i.e., the next one is the first
+ pixel. We need this for checking the adjacency of the last corner.
+
+ We need to do this because the adjacent corners turn into
+ two-pixel-long curves, which can only be fit by straight lines. */
+
+static void remove_adjacent_corners(index_list_type * list, unsigned last_index, gboolean remove_adj_corners, at_exception_type * exception)
+{
+ unsigned j;
+ unsigned last;
+ index_list_type new_list = new_index_list();
+
+ for (j = INDEX_LIST_LENGTH(*list) - 1; j > 0; j--) {
+ unsigned search;
+ unsigned temp;
+ /* Find maximal element below `j'. */
+ unsigned max_index = j;
+
+ for (search = 0; search < j; search++)
+ if (GET_INDEX(*list, search) > GET_INDEX(*list, max_index))
+ max_index = search;
+
+ if (max_index != j) {
+ temp = GET_INDEX(*list, j);
+ GET_INDEX(*list, j) = GET_INDEX(*list, max_index);
+ GET_INDEX(*list, max_index) = temp;
+
+ /* xx -- really have to sort? */
+ LOG("needed exchange");
+ at_exception_warning(exception, "needed exchange");
+ }
+ }
+
+ /* The list is sorted. Now look for adjacent entries. Each time
+ through the loop we insert the current entry and, if appropriate,
+ the next entry. */
+ for (j = 0; j < INDEX_LIST_LENGTH(*list) - 1; j++) {
+ unsigned current = GET_INDEX(*list, j);
+ unsigned next = GET_INDEX(*list, j + 1);
+
+ /* We should never have inserted the same element twice. */
+ /* assert (current != next); */
+
+ if ((remove_adj_corners) && ((next == current + 1) || (next == current)))
+ j++;
+
+ append_index(&new_list, current);
+ }
+
+ /* Don't append the last element if it is 1) adjacent to the previous
+ one; or 2) adjacent to the very first one. */
+ last = GET_LAST_INDEX(*list);
+ if (INDEX_LIST_LENGTH(new_list) == 0 || !(last == GET_LAST_INDEX(new_list) + 1 || (last == last_index && GET_INDEX(*list, 0) == 0)))
+ append_index(&new_list, last);
+
+ free_index_list(list);
+ *list = new_list;
+}
+
+/* A ``knee'' is a point which forms a ``right angle'' with its
+ predecessor and successor. See the documentation (the `Removing
+ knees' section) for an example and more details.
+
+ The argument CLOCKWISE tells us which direction we're moving. (We
+ can't figure that information out from just the single segment with
+ which we are given to work.)
+
+ We should never find two consecutive knees.
+
+ Since the first and last points are corners (unless the curve is
+ cyclic), it doesn't make sense to remove those. */
+
+/* This evaluates to TRUE if the vector V is zero in one direction and
+ nonzero in the other. */
+#define ONLY_ONE_ZERO(v) \
+ (((v).dx == 0.0 && (v).dy != 0.0) || ((v).dy == 0.0 && (v).dx != 0.0))
+
+/* There are four possible cases for knees, one for each of the four
+ corners of a rectangle; and then the cases differ depending on which
+ direction we are going around the curve. The tests are listed here
+ in the order of upper left, upper right, lower right, lower left.
+ Perhaps there is some simple pattern to the
+ clockwise/counterclockwise differences, but I don't see one. */
+#define CLOCKWISE_KNEE(prev_delta, next_delta) \
+ ((prev_delta.dx == -1.0 && next_delta.dy == 1.0) \
+ || (prev_delta.dy == 1.0 && next_delta.dx == 1.0) \
+ || (prev_delta.dx == 1.0 && next_delta.dy == -1.0) \
+ || (prev_delta.dy == -1.0 && next_delta.dx == -1.0))
+
+#define COUNTERCLOCKWISE_KNEE(prev_delta, next_delta) \
+ ((prev_delta.dy == 1.0 && next_delta.dx == -1.0) \
+ || (prev_delta.dx == 1.0 && next_delta.dy == 1.0) \
+ || (prev_delta.dy == -1.0 && next_delta.dx == 1.0) \
+ || (prev_delta.dx == -1.0 && next_delta.dy == -1.0))
+
+static void remove_knee_points(curve_type curve, gboolean clockwise)
+{
+ unsigned i;
+ unsigned offset = (CURVE_CYCLIC(curve) == TRUE) ? 0 : 1;
+ at_coord previous = real_to_int_coord(CURVE_POINT(curve, CURVE_PREV(curve, offset)));
+ curve_type trimmed_curve = copy_most_of_curve(curve);
+
+ if (CURVE_CYCLIC(curve) == FALSE)
+ append_pixel(trimmed_curve, real_to_int_coord(CURVE_POINT(curve, 0)));
+
+ for (i = offset; i < CURVE_LENGTH(curve) - offset; i++) {
+ at_coord current = real_to_int_coord(CURVE_POINT(curve, i));
+ at_coord next = real_to_int_coord(CURVE_POINT(curve, CURVE_NEXT(curve, i)));
+ vector_type prev_delta = IPsubtract(previous, current);
+ vector_type next_delta = IPsubtract(next, current);
+
+ if (ONLY_ONE_ZERO(prev_delta) && ONLY_ONE_ZERO(next_delta)
+ && ((clockwise && CLOCKWISE_KNEE(prev_delta, next_delta))
+ || (!clockwise && COUNTERCLOCKWISE_KNEE(prev_delta, next_delta))))
+ LOG(" (%d,%d)", current.x, current.y);
+ else {
+ previous = current;
+ append_pixel(trimmed_curve, current);
+ }
+ }
+
+ if (CURVE_CYCLIC(curve) == FALSE)
+ append_pixel(trimmed_curve, real_to_int_coord(LAST_CURVE_POINT(curve)));
+
+ if (CURVE_LENGTH(trimmed_curve) == CURVE_LENGTH(curve))
+ LOG(" (none)");
+
+ LOG(".\n");
+
+ free_curve(curve);
+ *curve = *trimmed_curve;
+ free(trimmed_curve); /* free_curve? --- Masatake */
+}
+
+/* Smooth the curve by adding in neighboring points. Do this
+ `filter_iterations' times. But don't change the corners. */
+
+static void filter(curve_type curve, fitting_opts_type * fitting_opts)
+{
+ unsigned iteration, this_point;
+ unsigned offset = (CURVE_CYCLIC(curve) == TRUE) ? 0 : 1;
+ at_real_coord prev_new_point;
+
+ /* We must have at least three points---the previous one, the current
+ one, and the next one. But if we don't have at least five, we will
+ probably collapse the curve down onto a single point, which means
+ we won't be able to fit it with a spline. */
+ if (CURVE_LENGTH(curve) < 5) {
+ LOG("Length is %u, not enough to filter.\n", CURVE_LENGTH(curve));
+ return;
+ }
+
+ prev_new_point.x = FLT_MAX;
+ prev_new_point.y = FLT_MAX;
+ prev_new_point.z = FLT_MAX;
+
+ for (iteration = 0; iteration < fitting_opts->filter_iterations; iteration++) {
+ curve_type newcurve = copy_most_of_curve(curve);
+ gboolean collapsed = FALSE;
+
+ /* Keep the first point on the curve. */
+ if (offset)
+ append_point(newcurve, CURVE_POINT(curve, 0));
+
+ for (this_point = offset; this_point < CURVE_LENGTH(curve) - offset; this_point++) {
+ vector_type in, out, sum;
+ at_real_coord new_point;
+
+ /* Calculate the vectors in and out, computed by looking at n points
+ on either side of this_point. Experimental it was found that 2 is
+ optimal. */
+
+ signed int prev, prevprev; /* have to be signed */
+ unsigned int next, nextnext;
+ at_real_coord candidate = CURVE_POINT(curve, this_point);
+
+ prev = CURVE_PREV(curve, this_point);
+ prevprev = CURVE_PREV(curve, prev);
+ next = CURVE_NEXT(curve, this_point);
+ nextnext = CURVE_NEXT(curve, next);
+
+ /* Add up the differences from p of the `surround' points
+ before p. */
+ in.dx = in.dy = in.dz = 0.0;
+
+ in = Vadd(in, Psubtract(CURVE_POINT(curve, prev), candidate));
+ if (prevprev >= 0)
+ in = Vadd(in, Psubtract(CURVE_POINT(curve, prevprev), candidate));
+
+ /* And the points after p. Don't use more points after p than we
+ ended up with before it. */
+ out.dx = out.dy = out.dz = 0.0;
+
+ out = Vadd(out, Psubtract(CURVE_POINT(curve, next), candidate));
+ if (nextnext < CURVE_LENGTH(curve))
+ out = Vadd(out, Psubtract(CURVE_POINT(curve, nextnext), candidate));
+
+ /* Start with the old point. */
+ new_point = candidate;
+ sum = Vadd(in, out);
+ /* We added 2*n+2 points, so we have to divide the sum by 2*n+2 */
+ new_point.x += sum.dx / 6;
+ new_point.y += sum.dy / 6;
+ new_point.z += sum.dz / 6;
+ if (fabs(prev_new_point.x - new_point.x) < 0.3 && fabs(prev_new_point.y - new_point.y) < 0.3 && fabs(prev_new_point.z - new_point.z) < 0.3) {
+ collapsed = TRUE;
+ break;
+ }
+
+ /* Put the newly computed point into a separate curve, so it
+ doesn't affect future computation (on this iteration). */
+ append_point(newcurve, prev_new_point = new_point);
+ }
+
+ if (collapsed)
+ free_curve(newcurve);
+ else {
+ /* Just as with the first point, we have to keep the last point. */
+ if (offset)
+ append_point(newcurve, LAST_CURVE_POINT(curve));
+
+ /* Set the original curve to the newly filtered one, and go again. */
+ free_curve(curve);
+ *curve = *newcurve;
+ }
+ free(newcurve);
+ }
+
+ if (logging)
+ log_curve(curve, FALSE);
+}
+
+/* This routine returns the curve fitted to a straight line in a very
+ simple way: make the first and last points on the curve be the
+ endpoints of the line. This simplicity is justified because we are
+ called only on very short curves. */
+
+static spline_list_type *fit_with_line(curve_type curve)
+{
+ spline_type line;
+
+ LOG("Fitting with straight line:\n");
+
+ SPLINE_DEGREE(line) = LINEARTYPE;
+ START_POINT(line) = CONTROL1(line) = CURVE_POINT(curve, 0);
+ END_POINT(line) = CONTROL2(line) = LAST_CURVE_POINT(curve);
+
+ /* Make sure that this line is never changed to a cubic. */
+ SPLINE_LINEARITY(line) = 0;
+
+ if (logging) {
+ LOG(" ");
+ print_spline(line);
+ }
+
+ return new_spline_list_with_spline(line);
+}
+
+/* The least squares method is well described in Schneider's thesis.
+ Briefly, we try to fit the entire curve with one spline. If that
+ fails, we subdivide the curve. */
+
+static spline_list_type *fit_with_least_squares(curve_type curve, fitting_opts_type * fitting_opts, at_exception_type * exception)
+{
+ gfloat error = 0, best_error = FLT_MAX;
+ spline_type spline, best_spline;
+ spline_list_type *spline_list = NULL;
+ unsigned worst_point = 0;
+ gfloat previous_error = FLT_MAX;
+
+ LOG("\nFitting with least squares:\n");
+
+ /* Phoenix reduces the number of points with a ``linear spline
+ technique''. But for fitting letterforms, that is
+ inappropriate. We want all the points we can get. */
+
+ /* It makes no difference whether we first set the `t' values or
+ find the tangents. This order makes the documentation a little
+ more coherent. */
+
+ LOG("Finding tangents:\n");
+ find_tangent(curve, /* to_start */ TRUE, /* cross_curve */ FALSE,
+ fitting_opts->tangent_surround);
+ find_tangent(curve, /* to_start */ FALSE, /* cross_curve */ FALSE,
+ fitting_opts->tangent_surround);
+
+ set_initial_parameter_values(curve);
+
+ /* Now we loop, subdividing, until CURVE has
+ been fit. */
+ while (TRUE) {
+ spline = best_spline = fit_one_spline(curve, exception);
+ if (at_exception_got_fatal(exception))
+ goto cleanup;
+
+ if (SPLINE_DEGREE(spline) == LINEARTYPE)
+ LOG(" fitted to line:\n");
+ else
+ LOG(" fitted to spline:\n");
+
+ if (logging) {
+ LOG(" ");
+ print_spline(spline);
+ }
+
+ if (SPLINE_DEGREE(spline) == LINEARTYPE)
+ break;
+
+ error = find_error(curve, spline, &worst_point, exception);
+ if (error <= previous_error) {
+ best_error = error;
+ best_spline = spline;
+ }
+ break;
+ }
+
+ if (SPLINE_DEGREE(spline) == LINEARTYPE) {
+ spline_list = new_spline_list_with_spline(spline);
+ LOG("Accepted error of %.3f.\n", error);
+ return (spline_list);
+ }
+
+ /* Go back to the best fit. */
+ spline = best_spline;
+ error = best_error;
+
+ if (error < fitting_opts->error_threshold && CURVE_CYCLIC(curve) == FALSE) {
+ /* The points were fitted with a
+ spline. We end up here whenever a fit is accepted. We have
+ one more job: see if the ``curve'' that was fit should really
+ be a straight line. */
+ if (spline_linear_enough(&spline, curve, fitting_opts)) {
+ SPLINE_DEGREE(spline) = LINEARTYPE;
+ LOG("Changed to line.\n");
+ }
+ spline_list = new_spline_list_with_spline(spline);
+ LOG("Accepted error of %.3f.\n", error);
+ } else {
+ /* We couldn't fit the curve acceptably, so subdivide. */
+ unsigned subdivision_index;
+ spline_list_type *left_spline_list;
+ spline_list_type *right_spline_list;
+ curve_type left_curve = new_curve();
+ curve_type right_curve = new_curve();
+
+ /* Keep the linked list of curves intact. */
+ NEXT_CURVE(right_curve) = NEXT_CURVE(curve);
+ PREVIOUS_CURVE(right_curve) = left_curve;
+ NEXT_CURVE(left_curve) = right_curve;
+ PREVIOUS_CURVE(left_curve) = curve;
+ NEXT_CURVE(curve) = left_curve;
+
+ LOG("\nSubdividing (error %.3f):\n", error);
+ LOG(" Original point: (%.3f,%.3f), #%u.\n", CURVE_POINT(curve, worst_point).x, CURVE_POINT(curve, worst_point).y, worst_point);
+ subdivision_index = worst_point;
+ LOG(" Final point: (%.3f,%.3f), #%u.\n", CURVE_POINT(curve, subdivision_index).x, CURVE_POINT(curve, subdivision_index).y, subdivision_index);
+
+ /* The last point of the left-hand curve will also be the first
+ point of the right-hand curve. */
+ CURVE_LENGTH(left_curve) = subdivision_index + 1;
+ CURVE_LENGTH(right_curve) = CURVE_LENGTH(curve) - subdivision_index;
+ left_curve->point_list = curve->point_list;
+ right_curve->point_list = curve->point_list + subdivision_index;
+
+ /* We want to use the tangents of the curve which we are
+ subdividing for the start tangent for left_curve and the
+ end tangent for right_curve. */
+ CURVE_START_TANGENT(left_curve) = CURVE_START_TANGENT(curve);
+ CURVE_END_TANGENT(right_curve) = CURVE_END_TANGENT(curve);
+
+ /* We have to set up the two curves before finding the tangent at
+ the subdivision point. The tangent at that point must be the
+ same for both curves, or noticeable bumps will occur in the
+ character. But we want to use information on both sides of the
+ point to compute the tangent, hence cross_curve = true. */
+ find_tangent(left_curve, /* to_start_point: */ FALSE,
+ /* cross_curve: */ TRUE, fitting_opts->tangent_surround);
+ CURVE_START_TANGENT(right_curve) = CURVE_END_TANGENT(left_curve);
+
+ /* Now that we've set up the curves, we can fit them. */
+ left_spline_list = fit_curve(left_curve, fitting_opts, exception);
+ if (at_exception_got_fatal(exception))
+ /* TODO: Memory allocated for left_curve and right_curve
+ will leak. */
+ goto cleanup;
+
+ right_spline_list = fit_curve(right_curve, fitting_opts, exception);
+ /* TODO: Memory allocated for left_curve and right_curve
+ will leak. */
+ if (at_exception_got_fatal(exception))
+ goto cleanup;
+
+ /* Neither of the subdivided curves could be fit, so fail. */
+ if (left_spline_list == NULL && right_spline_list == NULL)
+ return NULL;
+
+ /* Put the two together (or whichever of them exist). */
+ spline_list = new_spline_list();
+
+ if (left_spline_list == NULL) {
+ LOG("Could not fit spline to left curve (%lx).\n", (unsigned long)(uintptr_t)left_curve);
+ at_exception_warning(exception, "Could not fit left spline list");
+ } else {
+ concat_spline_lists(spline_list, *left_spline_list);
+ free_spline_list(*left_spline_list);
+ free(left_spline_list);
+ }
+
+ if (right_spline_list == NULL) {
+ LOG("Could not fit spline to right curve (%lx).\n", (unsigned long)(uintptr_t)right_curve);
+ at_exception_warning(exception, "Could not fit right spline list");
+ } else {
+ concat_spline_lists(spline_list, *right_spline_list);
+ free_spline_list(*right_spline_list);
+ free(right_spline_list);
+ }
+ if (CURVE_END_TANGENT(left_curve))
+ free(CURVE_END_TANGENT(left_curve));
+ free(left_curve);
+ free(right_curve);
+ }
+cleanup:
+ return spline_list;
+}
+
+/* Our job here is to find alpha1 (and alpha2), where t1_hat (t2_hat) is
+ the tangent to CURVE at the starting (ending) point, such that:
+
+ control1 = alpha1*t1_hat + starting point
+ control2 = alpha2*t2_hat + ending_point
+
+ and the resulting spline (starting_point .. control1 and control2 ..
+ ending_point) minimizes the least-square error from CURVE.
+
+ See pp.57--59 of the Phoenix thesis.
+
+ The B?(t) here corresponds to B_i^3(U_i) there.
+ The Bernshte\u in polynomials of degree n are defined by
+ B_i^n(t) = { n \choose i } t^i (1-t)^{n-i}, i = 0..n */
+
+#define B0(t) CUBE ((gfloat) 1.0 - (t))
+#define B1(t) ((gfloat) 3.0 * (t) * SQUARE ((gfloat) 1.0 - (t)))
+#define B2(t) ((gfloat) 3.0 * SQUARE (t) * ((gfloat) 1.0 - (t)))
+#define B3(t) CUBE (t)
+
+static spline_type fit_one_spline(curve_type curve, at_exception_type * exception)
+{
+ /* Since our arrays are zero-based, the `C0' and `C1' here correspond
+ to `C1' and `C2' in the paper. */
+ gfloat X_C1_det, C0_X_det, C0_C1_det;
+ gfloat alpha1, alpha2;
+ spline_type spline;
+ vector_type start_vector, end_vector;
+ unsigned i;
+ vector_type *A;
+ vector_type t1_hat = *CURVE_START_TANGENT(curve);
+ vector_type t2_hat = *CURVE_END_TANGENT(curve);
+ gfloat C[2][2] = { {0.0, 0.0}, {0.0, 0.0} };
+ gfloat X[2] = { 0.0, 0.0 };
+
+ XMALLOC(A, CURVE_LENGTH(curve) * 2 * sizeof(vector_type)); /* A dynamically allocated array. */
+
+ START_POINT(spline) = CURVE_POINT(curve, 0);
+ END_POINT(spline) = LAST_CURVE_POINT(curve);
+ start_vector = make_vector(START_POINT(spline));
+ end_vector = make_vector(END_POINT(spline));
+
+ for (i = 0; i < CURVE_LENGTH(curve); i++) {
+ A[(i << 1) + 0] = Vmult_scalar(t1_hat, B1(CURVE_T(curve, i)));
+ A[(i << 1) + 1] = Vmult_scalar(t2_hat, B2(CURVE_T(curve, i)));
+ }
+
+ for (i = 0; i < CURVE_LENGTH(curve); i++) {
+ vector_type temp, temp0, temp1, temp2, temp3;
+ vector_type *Ai = A + (i << 1);
+
+ C[0][0] += Vdot(Ai[0], Ai[0]);
+ C[0][1] += Vdot(Ai[0], Ai[1]);
+ /* C[1][0] = C[0][1] (this is assigned outside the loop) */
+ C[1][1] += Vdot(Ai[1], Ai[1]);
+
+ /* Now the right-hand side of the equation in the paper. */
+ temp0 = Vmult_scalar(start_vector, B0(CURVE_T(curve, i)));
+ temp1 = Vmult_scalar(start_vector, B1(CURVE_T(curve, i)));
+ temp2 = Vmult_scalar(end_vector, B2(CURVE_T(curve, i)));
+ temp3 = Vmult_scalar(end_vector, B3(CURVE_T(curve, i)));
+
+ temp = make_vector(Vsubtract_point(CURVE_POINT(curve, i), Vadd(temp0, Vadd(temp1, Vadd(temp2, temp3)))));
+
+ X[0] += Vdot(temp, Ai[0]);
+ X[1] += Vdot(temp, Ai[1]);
+ }
+ free(A);
+
+ C[1][0] = C[0][1];
+
+ X_C1_det = X[0] * C[1][1] - X[1] * C[0][1];
+ C0_X_det = C[0][0] * X[1] - C[0][1] * X[0];
+ C0_C1_det = C[0][0] * C[1][1] - C[1][0] * C[0][1];
+ if (C0_C1_det == 0.0) {
+ /* Zero determinant */
+ alpha1 = 0;
+ alpha2 = 0;
+ } else {
+ alpha1 = X_C1_det / C0_C1_det;
+ alpha2 = C0_X_det / C0_C1_det;
+ }
+ CONTROL1(spline) = Vadd_point(START_POINT(spline), Vmult_scalar(t1_hat, alpha1));
+ CONTROL2(spline) = Vadd_point(END_POINT(spline), Vmult_scalar(t2_hat, alpha2));
+ SPLINE_DEGREE(spline) = CUBICTYPE;
+
+ return spline;
+}
+
+/* Find reasonable values for t for each point on CURVE. The method is
+ called chord-length parameterization, which is described in Plass &
+ Stone. The basic idea is just to use the distance from one point to
+ the next as the t value, normalized to produce values that increase
+ from zero for the first point to one for the last point. */
+
+static void set_initial_parameter_values(curve_type curve)
+{
+ unsigned p;
+
+ LOG("\nAssigning initial t values:\n ");
+
+ CURVE_T(curve, 0) = 0.0;
+
+ for (p = 1; p < CURVE_LENGTH(curve); p++) {
+ at_real_coord point = CURVE_POINT(curve, p), previous_p = CURVE_POINT(curve, p - 1);
+ gfloat d = distance(point, previous_p);
+ CURVE_T(curve, p) = CURVE_T(curve, p - 1) + d;
+ }
+
+ if (LAST_CURVE_T(curve) == 0.0)
+ LAST_CURVE_T(curve) = 1.0;
+
+ for (p = 1; p < CURVE_LENGTH(curve); p++)
+ CURVE_T(curve, p) = CURVE_T(curve, p) / LAST_CURVE_T(curve);
+
+ if (logging)
+ log_entire_curve(curve);
+}
+
+/* Find an approximation to the tangent to an endpoint of CURVE (to the
+ first point if TO_START_POINT is TRUE, else the last). If
+ CROSS_CURVE is TRUE, consider points on the adjacent curve to CURVE.
+
+ It is important to compute an accurate approximation, because the
+ control points that we eventually decide upon to fit the curve will
+ be placed on the half-lines defined by the tangents and
+ endpoints...and we never recompute the tangent after this. */
+
+static void find_tangent(curve_type curve, gboolean to_start_point, gboolean cross_curve, unsigned tangent_surround)
+{
+ vector_type tangent;
+ vector_type **curve_tangent = (to_start_point == TRUE) ? &(CURVE_START_TANGENT(curve))
+ : &(CURVE_END_TANGENT(curve));
+ unsigned n_points = 0;
+
+ LOG(" tangent to %s: ", (to_start_point == TRUE) ? "start" : "end");
+
+ if (*curve_tangent == NULL) {
+ XMALLOC(*curve_tangent, sizeof(vector_type));
+ do {
+ tangent = find_half_tangent(curve, to_start_point, &n_points, tangent_surround);
+
+ if ((cross_curve == TRUE) || (CURVE_CYCLIC(curve) == TRUE)) {
+ curve_type adjacent_curve = (to_start_point == TRUE) ? PREVIOUS_CURVE(curve) : NEXT_CURVE(curve);
+ vector_type tangent2 = (to_start_point == FALSE) ? find_half_tangent(adjacent_curve, TRUE, &n_points,
+ tangent_surround) : find_half_tangent(adjacent_curve, TRUE, &n_points,
+ tangent_surround);
+
+ LOG("(adjacent curve half tangent (%.3f,%.3f,%.3f)) ", tangent2.dx, tangent2.dy, tangent2.dz);
+ tangent = Vadd(tangent, tangent2);
+ }
+ tangent_surround--;
+
+ }
+ while (tangent.dx == 0.0 && tangent.dy == 0.0);
+
+ assert(n_points > 0);
+ **curve_tangent = Vmult_scalar(tangent, (gfloat) (1.0 / n_points));
+ if ((CURVE_CYCLIC(curve) == TRUE) && CURVE_START_TANGENT(curve))
+ *CURVE_START_TANGENT(curve) = **curve_tangent;
+ if ((CURVE_CYCLIC(curve) == TRUE) && CURVE_END_TANGENT(curve))
+ *CURVE_END_TANGENT(curve) = **curve_tangent;
+ } else
+ LOG("(already computed) ");
+
+ LOG("(%.3f,%.3f,%.3f).\n", (*curve_tangent)->dx, (*curve_tangent)->dy, (*curve_tangent)->dz);
+}
+
+/* Find the change in y and change in x for `tangent_surround' (a global)
+ points along CURVE. Increment N_POINTS by the number of points we
+ actually look at. */
+
+static vector_type find_half_tangent(curve_type c, gboolean to_start_point, unsigned *n_points, unsigned tangent_surround)
+{
+ unsigned p;
+ int factor = to_start_point ? 1 : -1;
+ unsigned tangent_index = to_start_point ? 0 : c->length - 1;
+ at_real_coord tangent_point = CURVE_POINT(c, tangent_index);
+ vector_type tangent = { 0.0, 0.0 };
+ unsigned int surround;
+
+ if ((surround = CURVE_LENGTH(c) / 2) > tangent_surround)
+ surround = tangent_surround;
+
+ for (p = 1; p <= surround; p++) {
+ int this_index = p * factor + tangent_index;
+ at_real_coord this_point;
+
+ if (this_index < 0 || this_index >= (int)c->length)
+ break;
+
+ this_point = CURVE_POINT(c, p * factor + tangent_index);
+
+ /* Perhaps we should weight the tangent from `this_point' by some
+ factor dependent on the distance from the tangent point. */
+ tangent = Vadd(tangent, Vmult_scalar(Psubtract(this_point, tangent_point), (gfloat) factor));
+ (*n_points)++;
+ }
+
+ return tangent;
+}
+
+/* When this routine is called, we have computed a spline representation
+ for the digitized curve. The question is, how good is it? If the
+ fit is very good indeed, we might have an error of zero on each
+ point, and then WORST_POINT becomes irrelevant. But normally, we
+ return the error at the worst point, and the index of that point in
+ WORST_POINT. The error computation itself is the Euclidean distance
+ from the original curve CURVE to the fitted spline SPLINE. */
+
+static gfloat find_error(curve_type curve, spline_type spline, unsigned *worst_point, at_exception_type * exception)
+{
+ unsigned this_point;
+ gfloat total_error = 0.0;
+ gfloat worst_error = FLT_MIN;
+
+ *worst_point = CURVE_LENGTH(curve) + 1; /* A sentinel value. */
+
+ for (this_point = 0; this_point < CURVE_LENGTH(curve); this_point++) {
+ at_real_coord curve_point = CURVE_POINT(curve, this_point);
+ gfloat t = CURVE_T(curve, this_point);
+ at_real_coord spline_point = evaluate_spline(spline, t);
+ gfloat this_error = distance(curve_point, spline_point);
+ if (this_error >= worst_error) {
+ *worst_point = this_point;
+ worst_error = this_error;
+ }
+ total_error += this_error;
+ }
+
+ if (*worst_point == CURVE_LENGTH(curve) + 1) { /* Didn't have any ``worst point''; the error should be zero. */
+ if (epsilon_equal(total_error, 0.0))
+ LOG(" Every point fit perfectly.\n");
+ else {
+ LOG("No worst point found; something is wrong");
+ at_exception_warning(exception, "No worst point found; something is wrong");
+ }
+ } else {
+ if (epsilon_equal(total_error, 0.0))
+ LOG(" Every point fit perfectly.\n");
+ else {
+ LOG(" Worst error (at (%.3f,%.3f,%.3f), point #%u) was %.3f.\n", CURVE_POINT(curve, *worst_point).x, CURVE_POINT(curve, *worst_point).y, CURVE_POINT(curve, *worst_point).z, *worst_point, worst_error);
+ LOG(" Total error was %.3f.\n", total_error);
+ LOG(" Average error (over %u points) was %.3f.\n", CURVE_LENGTH(curve), total_error / CURVE_LENGTH(curve));
+ }
+ }
+
+ return worst_error;
+}
+
+/* Supposing that we have accepted the error, another question arises:
+ would we be better off just using a straight line? */
+
+static gboolean spline_linear_enough(spline_type * spline, curve_type curve, fitting_opts_type * fitting_opts)
+{
+ gfloat A, B, C;
+ unsigned this_point;
+ gfloat dist = 0.0, start_end_dist, threshold;
+
+ LOG("Checking linearity:\n");
+
+ A = END_POINT(*spline).x - START_POINT(*spline).x;
+ B = END_POINT(*spline).y - START_POINT(*spline).y;
+ C = END_POINT(*spline).z - START_POINT(*spline).z;
+
+ start_end_dist = (gfloat) (SQUARE(A) + SQUARE(B) + SQUARE(C));
+ LOG("start_end_distance is %.3f.\n", sqrt(start_end_dist));
+
+ LOG(" Line endpoints are (%.3f, %.3f, %.3f) and ", START_POINT(*spline).x, START_POINT(*spline).y, START_POINT(*spline).z);
+ LOG("(%.3f, %.3f, %.3f)\n", END_POINT(*spline).x, END_POINT(*spline).y, END_POINT(*spline).z);
+
+ /* LOG (" Line is %.3fx + %.3fy + %.3f = 0.\n", A, B, C); */
+
+ for (this_point = 0; this_point < CURVE_LENGTH(curve); this_point++) {
+ gfloat a, b, c, w;
+ gfloat t = CURVE_T(curve, this_point);
+ at_real_coord spline_point = evaluate_spline(*spline, t);
+
+ a = spline_point.x - START_POINT(*spline).x;
+ b = spline_point.y - START_POINT(*spline).y;
+ c = spline_point.z - START_POINT(*spline).z;
+ w = (A * a + B * b + C * c) / start_end_dist;
+
+ dist += (gfloat) sqrt(SQUARE(a - A * w) + SQUARE(b - B * w) + SQUARE(c - C * w));
+ }
+ LOG(" Total distance is %.3f, ", dist);
+
+ dist /= (CURVE_LENGTH(curve) - 1);
+ LOG("which is %.3f normalized.\n", dist);
+
+ /* We want reversion of short curves to splines to be more likely than
+ reversion of long curves, hence the second division by the curve
+ length, for use in `change_bad_lines'. */
+ SPLINE_LINEARITY(*spline) = dist;
+ LOG(" Final linearity: %.3f.\n", SPLINE_LINEARITY(*spline));
+ if (start_end_dist * (gfloat) 0.5 > fitting_opts->line_threshold)
+ threshold = fitting_opts->line_threshold;
+ else
+ threshold = start_end_dist * (gfloat) 0.5;
+ LOG("threshold is %.3f .\n", threshold);
+ if (dist < threshold)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* Unfortunately, we cannot tell in isolation whether a given spline
+ should be changed to a line or not. That can only be known after the
+ entire curve has been fit to a list of splines. (The curve is the
+ pixel outline between two corners.) After subdividing the curve, a
+ line may very well fit a portion of the curve just as well as the
+ spline---but unless a spline is truly close to being a line, it
+ should not be combined with other lines. */
+
+static void change_bad_lines(spline_list_type * spline_list, fitting_opts_type * fitting_opts)
+{
+ unsigned this_spline;
+ gboolean found_cubic = FALSE;
+ unsigned length = SPLINE_LIST_LENGTH(*spline_list);
+
+ LOG("\nChecking for bad lines (length %u):\n", length);
+
+ /* First see if there are any splines in the fitted shape. */
+ for (this_spline = 0; this_spline < length; this_spline++) {
+ if (SPLINE_DEGREE(SPLINE_LIST_ELT(*spline_list, this_spline)) == CUBICTYPE) {
+ found_cubic = TRUE;
+ break;
+ }
+ }
+
+ /* If so, change lines back to splines (we haven't done anything to
+ their control points, so we only have to change the degree) unless
+ the spline is close enough to being a line. */
+ if (found_cubic)
+ for (this_spline = 0; this_spline < length; this_spline++) {
+ spline_type s = SPLINE_LIST_ELT(*spline_list, this_spline);
+
+ if (SPLINE_DEGREE(s) == LINEARTYPE) {
+ LOG(" #%u: ", this_spline);
+ if (SPLINE_LINEARITY(s) > fitting_opts->line_reversion_threshold) {
+ LOG("reverted, ");
+ SPLINE_DEGREE(SPLINE_LIST_ELT(*spline_list, this_spline))
+ = CUBICTYPE;
+ }
+ LOG("linearity %.3f.\n", SPLINE_LINEARITY(s));
+ }
+ } else
+ LOG(" No lines.\n");
+}
+
+/* Lists of array indices (well, that is what we use it for). */
+
+static index_list_type new_index_list(void)
+{
+ index_list_type index_list;
+
+ index_list.data = NULL;
+ INDEX_LIST_LENGTH(index_list) = 0;
+
+ return index_list;
+}
+
+static void free_index_list(index_list_type * index_list)
+{
+ if (INDEX_LIST_LENGTH(*index_list) > 0) {
+ free(index_list->data);
+ index_list->data = NULL;
+ INDEX_LIST_LENGTH(*index_list) = 0;
+ }
+}
+
+static void append_index(index_list_type * list, unsigned new_index)
+{
+ INDEX_LIST_LENGTH(*list)++;
+ XREALLOC(list->data, INDEX_LIST_LENGTH(*list) * sizeof(unsigned));
+ list->data[INDEX_LIST_LENGTH(*list) - 1] = new_index;
+}
+
+/* Turn an real point into a integer one. */
+
+static at_coord real_to_int_coord(at_real_coord real_coord)
+{
+ at_coord int_coord;
+
+ int_coord.x = lround(real_coord.x);
+ int_coord.y = lround(real_coord.y);
+
+ return int_coord;
+}
+
+/* Return the Euclidean distance between P1 and P2. */
+
+static gfloat distance(at_real_coord p1, at_real_coord p2)
+{
+ gfloat x = p1.x - p2.x, y = p1.y - p2.y, z = p1.z - p2.z;
+ return (gfloat) sqrt(SQUARE(x)
+ + SQUARE(y) + SQUARE(z));
+}
diff --git a/src/3rdparty/autotrace/fit.h b/src/3rdparty/autotrace/fit.h
new file mode 100644
index 0000000..1875887
--- /dev/null
+++ b/src/3rdparty/autotrace/fit.h
@@ -0,0 +1,22 @@
+/* fit.h: convert the pixel representation to splines. */
+
+#ifndef FIT_H
+#define FIT_H
+
+#include "autotrace.h"
+#include "image-proc.h"
+#include "pxl-outline.h"
+#include "spline.h"
+#include "exception.h"
+
+/* See fit.c for descriptions of these variables, all of which can be
+ set using options. */
+typedef at_fitting_opts_type fitting_opts_type;
+
+/* Fit splines and lines to LIST. */
+extern spline_list_array_type fitted_splines(pixel_outline_list_type, fitting_opts_type *, at_distance_map *, unsigned short width, unsigned short height, at_exception_type * exception, at_progress_func, gpointer, at_testcancel_func, gpointer);
+
+/* Get a new set of fitting options */
+extern fitting_opts_type new_fitting_opts(void);
+
+#endif /* not FIT_H */
diff --git a/src/3rdparty/autotrace/image-header.h b/src/3rdparty/autotrace/image-header.h
new file mode 100644
index 0000000..c685735
--- /dev/null
+++ b/src/3rdparty/autotrace/image-header.h
@@ -0,0 +1,18 @@
+/* image-header.h: declarations for a generic image header. */
+
+#ifndef IMAGE_HEADER_H
+#define IMAGE_HEADER_H
+
+#include "types.h"
+
+/* The important general information about the image data.
+ See `get_{img,pbm}_header' for the full details of the headers for
+ the particular formats. */
+typedef struct {
+ unsigned short hres, vres; /* In pixels per inch. */
+ unsigned short width, height; /* In bits. */
+ unsigned short depth; /* Perhaps the depth? */
+ unsigned format; /* (for pbm) Whether packed or not. */
+} image_header_type;
+
+#endif /* not IMAGE_HEADER_H */
diff --git a/src/3rdparty/autotrace/image-proc.c b/src/3rdparty/autotrace/image-proc.c
new file mode 100644
index 0000000..7709175
--- /dev/null
+++ b/src/3rdparty/autotrace/image-proc.c
@@ -0,0 +1,493 @@
+/* image-proc.c: image processing routines */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* Def: HAVE_CONFIG_H */
+
+#include <assert.h>
+#include <math.h>
+#include "xstd.h"
+#include "logreport.h"
+#include "image-proc.h"
+
+#define BLACK 0
+#define WHITE 0xff
+#ifndef M_SQRT2
+#define M_SQRT2 1.41421356237
+#endif
+
+/* Threshold for binarizing a monochrome image */
+#define GRAY_THRESHOLD 225
+
+/* RGB to grayscale */
+#define LUMINANCE(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11 + 0.5)
+
+#if 0
+struct etyp {
+ int t00, t11, t01, t01s;
+};
+
+static gboolean get_edge(bitmap_type, int y, int x, struct etyp *t);
+static void check(int v1, int v2, int v3, struct etyp *t);
+#endif
+
+/* Allocate storage for a new distance map with the same dimensions
+ as BITMAP and initialize it so that pixels in BITMAP with value
+ TARGET_VALUE are at distance zero and all other pixels are at
+ distance infinity. Then compute the gray-weighted distance from
+ every non-target point to the nearest target point. */
+
+at_distance_map new_distance_map(at_bitmap * bitmap, unsigned char target_value, gboolean padded, at_exception_type * exp)
+{
+ signed x, y;
+ float d, min;
+ at_distance_map dist;
+ unsigned char *b = AT_BITMAP_BITS(bitmap);
+ unsigned w = AT_BITMAP_WIDTH(bitmap);
+ unsigned h = AT_BITMAP_HEIGHT(bitmap);
+ unsigned spp = AT_BITMAP_PLANES(bitmap);
+
+ dist.height = h;
+ dist.width = w;
+ XMALLOC(dist.d, h * sizeof(float *));
+ XMALLOC(dist.weight, h * sizeof(float *));
+ for (y = 0; y < (signed)h; y++) {
+ XCALLOC(dist.d[y], w * sizeof(float));
+ XMALLOC(dist.weight[y], w * sizeof(float));
+ }
+
+ if (spp == 3) {
+ for (y = 0; y < (signed)h; y++) {
+ for (x = 0; x < (signed)w; x++, b += spp) {
+ int gray;
+ float fgray;
+ gray = (int)LUMINANCE(b[0], b[1], b[2]);
+ dist.d[y][x] = (gray == target_value ? 0.0F : 1.0e10F);
+ fgray = gray * 0.0039215686F; /* = gray / 255.0F */
+ dist.weight[y][x] = 1.0F - fgray;
+/* dist.weight[y][x] = 1.0F - (fgray * fgray);*/
+/* dist.weight[y][x] = (fgray < 0.5F ? 1.0F - fgray : -2.0F * fgray * (fgray - 1.0F));*/
+ }
+ }
+ } else {
+ for (y = 0; y < (signed)h; y++) {
+ for (x = 0; x < (signed)w; x++, b += spp) {
+ int gray;
+ float fgray;
+ gray = b[0];
+ dist.d[y][x] = (gray == target_value ? 0.0F : 1.0e10F);
+ fgray = gray * 0.0039215686F; /* = gray / 255.0F */
+ dist.weight[y][x] = 1.0F - fgray;
+/* dist.weight[y][x] = 1.0F - (fgray * fgray);*/
+/* dist.weight[y][x] = (fgray < 0.5F ? 1.0F - fgray : -2.0F * fgray * (fgray - 1.0F)); */
+ }
+ }
+ }
+
+ /* If the image is padded then border points are all at most
+ one unit away from the nearest target point. */
+ if (padded) {
+ for (y = 0; y < (signed)h; y++) {
+ if (dist.d[y][0] > dist.weight[y][0])
+ dist.d[y][0] = dist.weight[y][0];
+ if (dist.d[y][w - 1] > dist.weight[y][w - 1])
+ dist.d[y][w - 1] = dist.weight[y][w - 1];
+ }
+ for (x = 0; x < (signed)w; x++) {
+ if (dist.d[0][x] > dist.weight[0][x])
+ dist.d[0][x] = dist.weight[0][x];
+ if (dist.d[h - 1][x] > dist.weight[h - 1][x])
+ dist.d[h - 1][x] = dist.weight[h - 1][x];
+ }
+ }
+
+ /* Scan the image from left to right, top to bottom.
+ Examine the already-visited neighbors of each point (those
+ situated above or to the left of it). Each neighbor knows
+ the distance to its nearest target point; add to this distance
+ the distance from the central point to the neighbor (either
+ sqrt(2) or one) multiplied by the central point's weight
+ (derived from its gray level). Replace the distance already
+ stored at the central point if the new distance is smaller. */
+ for (y = 1; y < (signed)h; y++) {
+ for (x = 1; x < (signed)w; x++) {
+ if (dist.d[y][x] == 0.0F)
+ continue;
+
+ min = dist.d[y][x];
+
+ /* upper-left neighbor */
+ d = dist.d[y - 1][x - 1] + (float)M_SQRT2 *dist.weight[y][x];
+ if (d < min)
+ min = dist.d[y][x] = d;
+
+ /* upper neighbor */
+ d = dist.d[y - 1][x] + dist.weight[y][x];
+ if (d < min)
+ min = dist.d[y][x] = d;
+
+ /* left neighbor */
+ d = dist.d[y][x - 1] + dist.weight[y][x];
+ if (d < min)
+ min = dist.d[y][x] = d;
+
+ /* upper-right neighbor (except at the last column) */
+ if (x + 1 < (signed)w) {
+ d = dist.d[y - 1][x + 1] + (float)M_SQRT2 *dist.weight[y][x];
+ if (d < min)
+ min = dist.d[y][x] = d;
+ }
+ }
+ }
+
+ /* Same as above, but now scanning right to left, bottom to top. */
+ for (y = h - 2; y >= 0; y--) {
+ for (x = w - 2; x >= 0; x--) {
+ min = dist.d[y][x];
+
+ /* lower-right neighbor */
+ d = dist.d[y + 1][x + 1] + (float)M_SQRT2 *dist.weight[y][x];
+ if (d < min)
+ min = dist.d[y][x] = d;
+
+ /* lower neighbor */
+ d = dist.d[y + 1][x] + dist.weight[y][x];
+ if (d < min)
+ min = dist.d[y][x] = d;
+
+ /* right neighbor */
+ d = dist.d[y][x + 1] + dist.weight[y][x];
+ if (d < min)
+ min = dist.d[y][x] = d;
+
+ /* lower-left neighbor (except at the first column) */
+ if (x - 1 >= 0) {
+ d = dist.d[y + 1][x - 1] + (float)M_SQRT2 *dist.weight[y][x];
+ if (d < min)
+ min = dist.d[y][x] = d;
+ }
+ }
+ }
+ return dist;
+}
+
+/* Free the dynamically-allocated storage associated with a distance map. */
+
+void free_distance_map(at_distance_map * dist)
+{
+ unsigned y, h;
+
+ if (!dist)
+ return;
+
+ h = dist->height;
+
+ if (dist->d != NULL) {
+ for (y = 0; y < h; y++)
+ free((gpointer *) dist->d[y]);
+ free((gpointer *) dist->d);
+ }
+ if (dist->weight != NULL) {
+ for (y = 0; y < h; y++)
+ free((gpointer *) dist->weight[y]);
+ free((gpointer *) dist->weight);
+ }
+}
+
+#if 0
+void medial_axis(bitmap_type * bitmap, at_distance_map * dist, const at_color * bg_color)
+{
+ unsigned x, y, test;
+ unsigned w, h;
+ unsigned char *b;
+ float **d, f;
+ at_color bg;
+
+ assert(bitmap != NULL);
+
+ assert(AT_BITMAP_PLANES(*bitmap) == 1);
+
+ b = AT_BITMAP_BITS(*bitmap);
+ assert(b != NULL);
+ assert(dist != NULL);
+ d = dist->d;
+ assert(d != NULL);
+
+ h = AT_BITMAP_HEIGHT(*dist);
+ w = AT_BITMAP_WIDTH(*dist);
+ assert(AT_BITMAP_WIDTH(*bitmap) == w && AT_BITMAP_HEIGHT(*bitmap) == h);
+
+ if (bg_color)
+ bg = *bg_color;
+ else
+ bg.r = bg.g = bg.b = 255;
+
+ f = d[0][0] + 0.5;
+ test = (f < d[1][0]) + (f < d[1][1]) + (f < d[0][1]);
+ if (test > 1)
+ b[0] = bg.r;
+
+ f = d[0][w - 1] + 0.5;
+ test = (f < d[1][w - 1]) + (f < d[1][w - 2]) + (f < d[0][w - 2]);
+ if (test > 1)
+ b[w - 1] = bg.r;
+
+ for (x = 1; x < w - 1; x++) {
+ f = d[0][x] + 0.5;
+ test = (f < d[0][x - 1]) + (f < d[0][x + 1]) + (f < d[1][x - 1])
+ + (f < d[1][x]) + (f < d[1][x + 1]);
+ if (test > 1)
+ b[x] = bg.r;
+ }
+ b += w;
+
+ for (y = 1; y < h - 1; y++) {
+ f = d[y][0] + 0.5;
+ test = (f < d[y - 1][0]) + (f < d[y - 1][1]) + (f < d[y][1])
+ + (f < d[y + 1][0]) + (f < d[y + 1][1]);
+ if (test > 1)
+ b[0] = bg.r;
+
+ for (x = 1; x < w - 1; x++) {
+ f = d[y][x] + 0.5;
+ test = (f < d[y - 1][x - 1]) + (f < d[y - 1][x]) + (f < d[y - 1][x + 1])
+ + (f < d[y][x - 1]) + (f < d[y][x + 1])
+ + (f < d[y + 1][x - 1]) + (f < d[y + 1][x]) + (f < d[y + 1][x + 1]);
+ if (test > 1)
+ b[x] = bg.r;
+ }
+
+ f = d[y][w - 1] + 0.5;
+ test = (f < d[y - 1][w - 1]) + (f < d[y - 1][w - 2]) + (f < d[y][w - 2])
+ + (f < d[y + 1][w - 1]) + (f < d[y + 1][w - 2]);
+ if (test > 1)
+ b[w - 1] = bg.r;
+
+ b += w;
+ }
+
+ for (x = 1; x < w - 1; x++) {
+ f = d[h - 1][x] + 0.5;
+ test = (f < d[h - 1][x - 1]) + (f < d[h - 1][x + 1])
+ + (f < d[h - 2][x - 1]) + (f < d[h - 2][x]) + (f < d[h - 2][x + 1]);
+ if (test > 1)
+ b[x] = bg.r;
+ }
+
+ f = d[h - 1][0] + 0.5;
+ test = (f < d[h - 2][0]) + (f < d[h - 2][1]) + (f < d[h - 1][1]);
+ if (test > 1)
+ b[0] = bg.r;
+
+ f = d[h - 1][w - 1] + 0.5;
+ test = (f < d[h - 2][w - 1]) + (f < d[h - 2][w - 2]) + (f < d[h - 1][w - 2]);
+ if (test > 1)
+ b[w - 1] = bg.r;
+}
+#endif
+
+/* Binarize a grayscale or color image. */
+
+void binarize(at_bitmap * bitmap)
+{
+ unsigned i, npixels, spp;
+ unsigned char *b;
+
+ assert(bitmap != NULL);
+ assert(AT_BITMAP_BITS(bitmap) != NULL);
+
+ b = AT_BITMAP_BITS(bitmap);
+ spp = AT_BITMAP_PLANES(bitmap);
+ npixels = AT_BITMAP_WIDTH(bitmap) * AT_BITMAP_HEIGHT(bitmap);
+
+ if (spp == 1) {
+ for (i = 0; i < npixels; i++)
+ b[i] = (b[i] > GRAY_THRESHOLD ? WHITE : BLACK);
+ } else if (spp == 3) {
+ unsigned char *rgb = b;
+ for (i = 0; i < npixels; i++, rgb += 3) {
+ b[i] = (LUMINANCE(rgb[0], rgb[1], rgb[2]) > GRAY_THRESHOLD ? WHITE : BLACK);
+ }
+ XREALLOC(AT_BITMAP_BITS(bitmap), npixels);
+ AT_BITMAP_PLANES(bitmap) = 1;
+ } else {
+ WARNING("binarize: %u-plane images are not supported", spp);
+ }
+}
+
+#if 0
+/* Thin a binary image, replacing the original image with the thinned one. */
+
+at_bitmap ip_thin(bitmap_type input_b)
+{
+ unsigned y, x, i;
+ gboolean k, again;
+ struct etyp t;
+ unsigned w = AT_BITMAP_WIDTH(input_b);
+ unsigned h = AT_BITMAP_HEIGHT(input_b);
+ size_t num_bytes = w * h;
+ bitmap_type b = input_b;
+
+ if (AT_BITMAP_PLANES(input_b) != 1) {
+ FATAL("thin: single-plane image required; " "%u-plane images cannot be thinned", AT_BITMAP_PLANES(input_b));
+ return b;
+ }
+
+ /* Process and return a copy of the input image. */
+ XMALLOC(b.bitmap, num_bytes);
+ memcpy(b.bitmap, input_b.bitmap, num_bytes);
+
+ /* Set background pixels to zero, foreground pixels to one. */
+ for (i = 0; i < num_bytes; i++)
+ b.bitmap[i] = (b.bitmap[i] == BLACK ? 1 : 0);
+
+ again = TRUE;
+ while (again) {
+ again = FALSE;
+
+ for (y = 1; y < h - 1; y++) {
+ for (x = 1; x < w - 1; x++) {
+ /* During processing, pixels are used to store edge
+ type codes, so we can't just test for WHITE or BLACK. */
+ if (*AT_BITMAP_PIXEL(b, y, x) == 0)
+ continue;
+
+ k = (!get_edge(b, y, x, &t)
+ || (get_edge(b, y, x + 1, &t) && *AT_BITMAP_PIXEL(b, y - 1, x)
+ && *AT_BITMAP_PIXEL(b, y + 1, x))
+ || (get_edge(b, y + 1, x, &t) && *AT_BITMAP_PIXEL(b, y, x - 1)
+ && *AT_BITMAP_PIXEL(b, y, x + 1))
+ || (get_edge(b, y, x + 1, &t) && get_edge(b, y + 1, x + 1, &t)
+ && get_edge(b, y + 1, x, &t)));
+ if (k)
+ continue;
+
+ get_edge(b, y, x, &t);
+ if (t.t01)
+ *AT_BITMAP_PIXEL(b, y, x) |= 4;
+ *AT_BITMAP_PIXEL(b, y, x) |= 2;
+ again = TRUE;
+ }
+ }
+
+ for (y = 0; y < h; y++)
+ for (x = 0; x < w; x++)
+ if (*AT_BITMAP_PIXEL(b, y, x) & 02)
+ *AT_BITMAP_PIXEL(b, y, x) = 0;
+
+ for (y = 1; y < h - 1; y++) {
+ for (x = 1; x < w - 1; x++) {
+ if (*AT_BITMAP_PIXEL(b, y, x) == 0)
+ continue;
+
+ k = (!get_edge(b, y, x, &t)
+ || ((*AT_BITMAP_PIXEL(b, y, x) & 04) == 0)
+ || (get_edge(b, y + 1, x, &t) && (*AT_BITMAP_PIXEL(b, y, x - 1))
+ && *AT_BITMAP_PIXEL(b, y, x + 1))
+ || (get_edge(b, y, x + 1, &t) && *AT_BITMAP_PIXEL(b, y - 1, x)
+ && *AT_BITMAP_PIXEL(b, y + 1, x))
+ || (get_edge(b, y + 1, x, &t) && get_edge(b, y, x + 1, &t)
+ && get_edge(b, y + 1, x + 1, &t)));
+ if (k)
+ continue;
+
+ *AT_BITMAP_PIXEL(b, y, x) |= 02;
+ again = TRUE;
+ }
+ }
+
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ if (*AT_BITMAP_PIXEL(b, y, x) & 02)
+ *AT_BITMAP_PIXEL(b, y, x) = 0;
+ else if (*AT_BITMAP_PIXEL(b, y, x) > 0)
+ *AT_BITMAP_PIXEL(b, y, x) = 1;
+ }
+ }
+ }
+
+ /* Staircase removal; northward bias. */
+ for (y = 1; y < h - 1; y++) {
+ for (x = 1; x < w - 1; x++) {
+ if (*AT_BITMAP_PIXEL(b, y, x) == 0)
+ continue;
+
+ k = !(*AT_BITMAP_PIXEL(b, y - 1, x)
+ && ((*AT_BITMAP_PIXEL(b, y, x + 1) && !*AT_BITMAP_PIXEL(b, y - 1, x + 1)
+ && !*AT_BITMAP_PIXEL(b, y + 1, x - 1)
+ && (!*AT_BITMAP_PIXEL(b, y, x - 1) || !*AT_BITMAP_PIXEL(b, y + 1, x)))
+ || (*AT_BITMAP_PIXEL(b, y, x - 1) && !*AT_BITMAP_PIXEL(b, y - 1, x - 1)
+ && !*AT_BITMAP_PIXEL(b, y + 1, x + 1) && (!*AT_BITMAP_PIXEL(b, y, x + 1) || !*AT_BITMAP_PIXEL(b, y + 1, x)))));
+ if (k)
+ continue;
+
+ *AT_BITMAP_PIXEL(b, y, x) |= 02;
+ }
+ }
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ if (*AT_BITMAP_PIXEL(b, y, x) & 02)
+ *AT_BITMAP_PIXEL(b, y, x) = 0;
+ else if (*AT_BITMAP_PIXEL(b, y, x) > 0)
+ *AT_BITMAP_PIXEL(b, y, x) = 1;
+ }
+ }
+
+ /* Southward bias */
+ for (y = 1; y < h - 1; y++) {
+ for (x = 1; x < w - 1; x++) {
+ if (*AT_BITMAP_PIXEL(b, y, x) == 0)
+ continue;
+
+ k = !(*AT_BITMAP_PIXEL(b, y + 1, x)
+ && ((*AT_BITMAP_PIXEL(b, y, x + 1) && !*AT_BITMAP_PIXEL(b, y + 1, x + 1)
+ && !*AT_BITMAP_PIXEL(b, y - 1, x - 1) && (!*AT_BITMAP_PIXEL(b, y, x - 1)
+ || !*AT_BITMAP_PIXEL(b, y - 1, x))) || (*AT_BITMAP_PIXEL(b, y, x - 1)
+ && !*AT_BITMAP_PIXEL(b, y + 1, x - 1) && !*AT_BITMAP_PIXEL(b, y - 1, x + 1)
+ && (!*AT_BITMAP_PIXEL(b, y, x + 1) || !*AT_BITMAP_PIXEL(b, y - 1, x)))));
+ if (k)
+ continue;
+
+ *AT_BITMAP_PIXEL(b, y, x) |= 02;
+ }
+ }
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ if (*AT_BITMAP_PIXEL(b, y, x) & 02)
+ *AT_BITMAP_PIXEL(b, y, x) = 0;
+ else if (*AT_BITMAP_PIXEL(b, y, x) > 0)
+ *AT_BITMAP_PIXEL(b, y, x) = 1;
+ }
+ }
+
+ /* Set background pixels to WHITE, foreground pixels to BLACK. */
+ for (i = 0; i < num_bytes; i++)
+ b.bitmap[i] = (b.bitmap[i] == 0 ? WHITE : BLACK);
+ return b;
+}
+
+gboolean get_edge(bitmap_type b, int y, int x, struct etyp * t)
+{
+ t->t00 = 0;
+ t->t01 = 0;
+ t->t01s = 0;
+ t->t11 = 0;
+ check(*AT_BITMAP_PIXEL(b, y - 1, x - 1), *AT_BITMAP_PIXEL(b, y - 1, x), *AT_BITMAP_PIXEL(b, y - 1, x + 1), t);
+ check(*AT_BITMAP_PIXEL(b, y - 1, x + 1), *AT_BITMAP_PIXEL(b, y, x + 1), *AT_BITMAP_PIXEL(b, y + 1, x + 1), t);
+ check(*AT_BITMAP_PIXEL(b, y + 1, x + 1), *AT_BITMAP_PIXEL(b, y + 1, x), *AT_BITMAP_PIXEL(b, y + 1, x - 1), t);
+ check(*AT_BITMAP_PIXEL(b, y + 1, x - 1), *AT_BITMAP_PIXEL(b, y, x - 1), *AT_BITMAP_PIXEL(b, y - 1, x - 1), t);
+ return *AT_BITMAP_PIXEL(b, y, x) && t->t00 && t->t11 && !t->t01s;
+}
+
+void check(int v1, int v2, int v3, struct etyp *t)
+{
+ if (!v2 && (!v1 || !v3))
+ t->t00 = 1;
+ if (v2 && (v1 || v3))
+ t->t11 = 1;
+ if ((!v1 && v2) || (!v2 && v3)) {
+ t->t01s = t->t01;
+ t->t01 = 1;
+ }
+}
+#endif
diff --git a/src/3rdparty/autotrace/image-proc.h b/src/3rdparty/autotrace/image-proc.h
new file mode 100644
index 0000000..5c131a7
--- /dev/null
+++ b/src/3rdparty/autotrace/image-proc.h
@@ -0,0 +1,21 @@
+/* image-proc.h: image processing routines */
+
+#ifndef IMAGE_PROC_H
+#define IMAGE_PROC_H
+
+#include "bitmap.h"
+#include "color.h"
+
+typedef struct {
+ unsigned height, width;
+ float **weight;
+ float **d;
+} at_distance_map;
+
+/* Allocate and compute a new distance map. */
+extern at_distance_map new_distance_map(at_bitmap *, unsigned char target_value, gboolean padded, at_exception_type * exp);
+
+/* Free the dynamically-allocated storage associated with a distance map. */
+extern void free_distance_map(at_distance_map *);
+
+#endif /* not IMAGE_PROC_H */
diff --git a/src/3rdparty/autotrace/input.c b/src/3rdparty/autotrace/input.c
new file mode 100644
index 0000000..7566766
--- /dev/null
+++ b/src/3rdparty/autotrace/input.c
@@ -0,0 +1,231 @@
+/* input.c: interface for input handlers
+
+ Copyright (C) 1999, 2000, 2001 Bernhard Herzog.
+ Copyright (C) 2003 Masatake YAMATO
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License
+ as published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* Def: HAVE_CONFIG_H */
+
+#include "autotrace.h"
+#include "private.h"
+#include "input.h"
+#include "xstd.h"
+#include "filename.h"
+#include <string.h>
+#include <glib.h>
+
+typedef struct _at_input_format_entry at_input_format_entry;
+struct _at_input_format_entry {
+ at_bitmap_reader reader;
+ const gchar *descr;
+ GDestroyNotify user_data_destroy_func;
+};
+
+static GHashTable *at_input_formats = NULL;
+static at_input_format_entry *at_input_format_new(const char *descr, at_input_func reader, gpointer user_data, GDestroyNotify user_data_destroy_func);
+static void at_input_format_free(at_input_format_entry * entry);
+
+/*
+ * Helper functions
+ */
+static void input_list_set(gpointer key, gpointer value, gpointer user_data);
+static void input_list_strlen(gpointer key, gpointer value, gpointer user_data);
+static void input_list_strcat(gpointer key, gpointer value, gpointer user_data);
+
+/**
+ * at_input_init:
+ * Initialize at_input input plugin sub system.
+ *
+ * Return value: 1 for success, else for failure
+ **/
+int at_input_init(void)
+{
+ if (at_input_formats)
+ return 1;
+
+ at_input_formats = g_hash_table_new_full(g_str_hash, (GEqualFunc) g_str_equal, g_free, (GDestroyNotify) at_input_format_free);
+ if (!at_input_formats)
+ return 0;
+ return 1;
+}
+
+static at_input_format_entry *at_input_format_new(const gchar * descr, at_input_func reader, gpointer user_data, GDestroyNotify user_data_destroy_func)
+{
+ at_input_format_entry *entry;
+ entry = g_malloc(sizeof(at_input_format_entry));
+ if (entry) {
+ entry->reader.func = reader;
+ entry->reader.data = user_data;
+ entry->descr = g_strdup(descr);
+ entry->user_data_destroy_func = user_data_destroy_func;
+ }
+ return entry;
+}
+
+static void at_input_format_free(at_input_format_entry * entry)
+{
+ g_free((gpointer) entry->descr);
+ if (entry->user_data_destroy_func)
+ entry->user_data_destroy_func(entry->reader.data);
+ g_free(entry);
+
+}
+
+int at_input_add_handler(const gchar * suffix, const gchar * description, at_input_func reader)
+{
+ return at_input_add_handler_full(suffix, description, reader, 0, NULL, NULL);
+}
+
+int at_input_add_handler_full(const gchar * suffix, const gchar * description, at_input_func reader, gboolean override, gpointer user_data, GDestroyNotify user_data_destroy_func)
+{
+ gchar *gsuffix_raw;
+ gchar *gsuffix;
+ const gchar *gdescription;
+ at_input_format_entry *old_entry;
+ at_input_format_entry *new_entry;
+
+ g_return_val_if_fail(suffix, 0);
+ g_return_val_if_fail(description, 0);
+ g_return_val_if_fail(reader, 0);
+
+ gsuffix_raw = g_strdup((gchar *) suffix);
+ g_return_val_if_fail(gsuffix_raw, 0);
+ gsuffix = g_ascii_strdown(gsuffix_raw, strlen(gsuffix_raw));
+ g_free(gsuffix_raw);
+
+ gdescription = (const gchar *)description;
+
+ old_entry = g_hash_table_lookup(at_input_formats, gsuffix);
+ if (old_entry && !override) {
+ g_free(gsuffix);
+ return 1;
+ }
+
+ new_entry = at_input_format_new(gdescription, reader, user_data, user_data_destroy_func);
+ g_return_val_if_fail(new_entry, 0);
+
+ g_hash_table_replace(at_input_formats, gsuffix, new_entry);
+ return 1;
+}
+
+at_bitmap_reader *at_input_get_handler(gchar * filename)
+{
+ char *ext = find_suffix(filename);
+ if (ext == NULL)
+ ext = "";
+
+ return at_input_get_handler_by_suffix(ext);
+}
+
+at_bitmap_reader *at_input_get_handler_by_suffix(gchar * suffix)
+{
+ at_input_format_entry *format;
+ gchar *gsuffix_raw;
+ gchar *gsuffix;
+
+ if (!suffix || suffix[0] == '\0')
+ return NULL;
+
+ gsuffix_raw = g_strdup(suffix);
+ g_return_val_if_fail(gsuffix_raw, NULL);
+ gsuffix = g_ascii_strdown(gsuffix_raw, strlen(gsuffix_raw));
+ g_free(gsuffix_raw);
+ format = g_hash_table_lookup(at_input_formats, gsuffix);
+ g_free(gsuffix);
+
+ if (format)
+ return &(format->reader);
+ else
+ return NULL;
+}
+
+const char **at_input_list_new(void)
+{
+ char **list, **tmp;
+ gint format_count;
+ gint list_count;
+
+ format_count = g_hash_table_size(at_input_formats);
+ list_count = 2 * format_count;
+ list = g_new(gchar *, list_count + 1);
+ list[list_count] = NULL;
+
+ tmp = list;
+ g_hash_table_foreach(at_input_formats, input_list_set, &tmp);
+ return (const char **)list;
+}
+
+void at_input_list_free(const char **list)
+{
+ free((char **)list);
+}
+
+char *at_input_shortlist(void)
+{
+ gint length = 0, count;
+ char *list, *tmp;
+ g_hash_table_foreach(at_input_formats, input_list_strlen, &length);
+ count = g_hash_table_size(at_input_formats);
+
+ /* 2 for ", " */
+ length += (2 * count);
+ list = g_malloc(length + 1);
+ list[0] = '\0';
+
+ tmp = list;
+ g_hash_table_foreach(at_input_formats, input_list_strcat, &tmp);
+
+ /* remove final ", " */
+ g_return_val_if_fail(list[length - 2] == ',', NULL);
+ list[length - 2] = '\0';
+ return list;
+}
+
+static void input_list_set(gpointer key, gpointer value, gpointer user_data)
+{
+ at_input_format_entry *format = value;
+ const char ***list_ptr = user_data;
+ const char **list = *list_ptr;
+ list[0] = key;
+ list[1] = format->descr;
+ *list_ptr = &(list[2]);
+}
+
+static void input_list_strlen(gpointer key, gpointer value, gpointer user_data)
+{
+ gint *length;
+ g_return_if_fail(key);
+ g_return_if_fail(user_data);
+
+ length = user_data;
+ *length += strlen(key);
+}
+
+static void input_list_strcat(gpointer key, gpointer value, gpointer user_data)
+{
+ gchar **list_ptr;
+ gchar *list;
+ list_ptr = user_data;
+ list = *list_ptr;
+ strcat(list, key);
+ strcat(list, ", ");
+
+ /* 2 for ", " */
+ *list_ptr = list + strlen(key) + 2;
+}
diff --git a/src/3rdparty/autotrace/input.h b/src/3rdparty/autotrace/input.h
new file mode 100644
index 0000000..b4a7d9b
--- /dev/null
+++ b/src/3rdparty/autotrace/input.h
@@ -0,0 +1,95 @@
+/* input.h: interface for input handlers
+
+ Copyright (C) 1999, 2000, 2001 Bernhard Herzog.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License
+ as published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA. */
+
+#ifndef INPUT_H
+#define INPUT_H
+#include "types.h"
+#include "autotrace.h"
+#include "exception.h"
+
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Input handler should be implemented with using
+ following functions and macros. */
+
+ typedef
+ at_bitmap(*at_input_func) (gchar * name, at_input_opts_type * opts, at_msg_func msg_func, gpointer msg_data, gpointer user_data);
+
+/* at_input_add_handler
+ Register an input handler to autotrace.
+ If a handler for the suffix is already existed, do nothing. */
+ extern int at_input_add_handler(const gchar * suffix, const gchar * description, at_input_func reader);
+/* at_input_add_handler_full
+ If OVERRIDE is TRUE and if the old handler for suffix is existed,
+ remove the old handler first then add new handler.
+ If OVERRIDE is false, do nothing. */
+ extern int at_input_add_handler_full(const gchar * suffix, const gchar * description, at_input_func reader, gboolean override, gpointer user_data, GDestroyNotify user_data_destroy_func);
+
+/* at_bitmap_init
+ Return initialized at_bitmap value.
+
+ args:
+ AREA is used as a storage of returned value.
+ If AREA is NULL, the storage is newly allocated
+ by at_bitmap_init. In such case the size of storage
+ is automatically calculated by WIDTH, HEIGHT and PLANES.
+
+ PLANES must be 1(gray scale) or 3(RGB color).
+
+ return value:
+ The return value is not newly allocated.
+ Only the storage is allocated if AREA is NULL.
+ On the other hand, at_bitmap_new allocates
+ mem for at_bitmap; and returns a pointer
+ for the mem.
+ at_bitmap_new is for autotrace library user.
+ at_bitmap_init is for input-handler developer.
+ Don't use at_bitmap_new in your input-handler. */
+ extern at_bitmap at_bitmap_init(unsigned char *area, unsigned short width, unsigned short height, unsigned int planes);
+
+/* TODO: free storage */
+
+/* The number of color planes of each pixel */
+#define AT_BITMAP_PLANES(b) ((b)->np)
+
+/* The pixels, represented as an array of bytes (in contiguous storage).
+ Each pixel is represented by np bytes. */
+#define AT_BITMAP_BITS(b) ((b)->bitmap)
+
+/* These are convenient abbreviations for geting inside the members. */
+#define AT_BITMAP_WIDTH(b) ((b)->width)
+#define AT_BITMAP_HEIGHT(b) ((b)->height)
+
+/* This is the pixel at [ROW,COL]. */
+#define AT_BITMAP_PIXEL(b, row, col) \
+ ((AT_BITMAP_BITS (b) + (row) * AT_BITMAP_PLANES (b) * AT_BITMAP_WIDTH (b) \
+ + (col) * AT_BITMAP_PLANES(b)))
+
+/* at_ prefix removed version */
+#define AT_BITMAP_VALID_PIXEL(b, row, col) \
+ ((row) < AT_BITMAP_HEIGHT (b) && (col) < AT_BITMAP_WIDTH (b))
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* Not def: INPUT_H */
diff --git a/src/3rdparty/autotrace/intl.h b/src/3rdparty/autotrace/intl.h
new file mode 100644
index 0000000..7cc6f81
--- /dev/null
+++ b/src/3rdparty/autotrace/intl.h
@@ -0,0 +1,22 @@
+#ifndef __INTL_H__
+#define __INTL_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* Def: HAVE_CONFIG_H */
+
+#ifdef ENABLE_NLS
+#include <libintl.h>
+#define _(String) dgettext(PACKAGE,String)
+#define N_(String) (String)
+#else /* NLS is disabled */
+#define _(String) (String)
+#define N_(String) (String)
+#define textdomain(String) (String)
+#define gettext(String) (String)
+#define dgettext(Domain,String) (String)
+#define dcgettext(Domain,String,Type) (String)
+#define bindtextdomain(Domain,Directory) (Domain)
+#endif
+
+#endif
diff --git a/src/3rdparty/autotrace/logreport.c b/src/3rdparty/autotrace/logreport.c
new file mode 100644
index 0000000..7784a7c
--- /dev/null
+++ b/src/3rdparty/autotrace/logreport.c
@@ -0,0 +1,9 @@
+/* logreport.c: showing information to the user. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* Def: HAVE_CONFIG_H */
+
+#include "logreport.h"
+
+gboolean logging = FALSE;
diff --git a/src/3rdparty/autotrace/logreport.h b/src/3rdparty/autotrace/logreport.h
new file mode 100644
index 0000000..04a548c
--- /dev/null
+++ b/src/3rdparty/autotrace/logreport.h
@@ -0,0 +1,32 @@
+/* logreport.h: status reporting routines. */
+
+#ifndef LOGREPORT_H
+#define LOGREPORT_H
+
+#include <stdio.h>
+#include "types.h"
+#include <stdlib.h>
+
+#ifdef _EXPORTING
+#define DECLSPEC __declspec(dllexport)
+#elif _IMPORTING
+#define DECLSPEC __declspec(dllimport)
+#else
+#define DECLSPEC
+#endif
+
+/* Whether to write a log */
+extern gboolean logging;
+
+#define LOG(...) \
+ do { if (logging) fprintf (stdout, __VA_ARGS__); } while (0)
+
+/* Define common sorts of messages. */
+
+#define FATAL(...) \
+ do { fputs ("fatal: ", stderr); LOG("fatal: "); fprintf (stderr, __VA_ARGS__); LOG (__VA_ARGS__); fputs (".\n", stderr); exit (1); } while (0)
+
+#define WARNING(...) \
+ do { fputs ("warning: ", stderr); LOG ("warning: "); fprintf (stderr, __VA_ARGS__); LOG (__VA_ARGS__); fputs (".\n", stderr); } while (0)
+
+#endif /* not LOGREPORT_H */
diff --git a/src/3rdparty/autotrace/median.c b/src/3rdparty/autotrace/median.c
new file mode 100644
index 0000000..60e8c7f
--- /dev/null
+++ b/src/3rdparty/autotrace/median.c
@@ -0,0 +1,863 @@
+/* median.c: median cut - reducing a high color bitmap to certain number of colors
+
+ Copyright (C) 2001, 2002 Martin Weber
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License
+ as published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* Def: HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "logreport.h"
+#include "xstd.h"
+#include "quantize.h"
+
+#define MAXNUMCOLORS 256
+
+#if 0
+#define R_SCALE
+#define G_SCALE
+#define B_SCALE
+#else
+
+/* scale RGB distances by *2,*3,*1 */
+#define R_SCALE <<1
+#define G_SCALE *3
+#define B_SCALE
+#endif
+
+#define BITS_IN_SAMPLE 8
+
+#define R_SHIFT (BITS_IN_SAMPLE - PRECISION_R)
+#define G_SHIFT (BITS_IN_SAMPLE - PRECISION_G)
+#define B_SHIFT (BITS_IN_SAMPLE - PRECISION_B)
+
+typedef struct {
+ /* The bounds of the box (inclusive); expressed as histogram indexes */
+ int Rmin, Rmax;
+ int Gmin, Gmax;
+ int Bmin, Bmax;
+ /* The volume (actually 2-norm) of the box */
+ int volume;
+ /* The number of nonzero histogram cells within this box */
+ long colorcount;
+} box, *boxptr;
+
+static void zero_histogram_rgb(Histogram histogram)
+{
+ int r, g, b;
+ for (r = 0; r < HIST_R_ELEMS; r++)
+ for (g = 0; g < HIST_G_ELEMS; g++)
+ for (b = 0; b < HIST_B_ELEMS; b++)
+ histogram[r * MR + g * MG + b] = 0;
+}
+
+static void generate_histogram_rgb(Histogram histogram, at_bitmap * image, const at_color * ignoreColor)
+{
+ unsigned char *src = image->bitmap;
+ int num_elems;
+ ColorFreq *col;
+
+ num_elems = AT_BITMAP_WIDTH(image) * AT_BITMAP_HEIGHT(image);
+ zero_histogram_rgb(histogram);
+
+ switch (AT_BITMAP_PLANES(image)) {
+ case 3:
+ while (num_elems--) {
+ /* If we have an ignorecolor, skip it. */
+ if (ignoreColor) {
+ if ((src[0] == ignoreColor->r)
+ && (src[1] == ignoreColor->g)
+ && (src[2] == ignoreColor->b)) {
+ src += 3;
+ continue;
+ }
+ }
+ col = &histogram[(src[0] >> R_SHIFT) * MR + (src[1] >> G_SHIFT) * MG + (src[2] >> B_SHIFT)];
+ (*col)++;
+ src += 3;
+ }
+ break;
+
+ case 1:
+ while (--num_elems >= 0) {
+ if (ignoreColor && src[num_elems] == ignoreColor->r)
+ continue;
+ col = &histogram[(src[num_elems] >> R_SHIFT) * MR + (src[num_elems] >> G_SHIFT) * MG + (src[num_elems] >> B_SHIFT)];
+ (*col)++;
+ }
+ break;
+ default:
+ /* To avoid compiler warning */ ;
+ }
+}
+
+static boxptr find_biggest_volume(boxptr boxlist, int numboxes)
+/* Find the splittable box with the largest (scaled) volume */
+/* Returns 0 if no splittable boxes remain */
+{
+ boxptr boxp;
+ int i;
+ int maxv = 0;
+ boxptr which = 0;
+
+ for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
+ if (boxp->volume > maxv) {
+ which = boxp;
+ maxv = boxp->volume;
+ }
+ }
+
+ return which;
+}
+
+static void update_box_rgb(Histogram histogram, boxptr boxp)
+/* Shrink the min/max bounds of a box to enclose only nonzero elements, */
+/* and recompute its volume and population */
+{
+ ColorFreq *histp;
+ int R, G, B;
+ int Rmin, Rmax, Gmin, Gmax, Bmin, Bmax;
+ int dist0, dist1, dist2;
+ long ccount;
+
+ Rmin = boxp->Rmin;
+ Rmax = boxp->Rmax;
+ Gmin = boxp->Gmin;
+ Gmax = boxp->Gmax;
+ Bmin = boxp->Bmin;
+ Bmax = boxp->Bmax;
+
+ if (Rmax > Rmin)
+ for (R = Rmin; R <= Rmax; R++)
+ for (G = Gmin; G <= Gmax; G++) {
+ histp = histogram + R * MR + G * MG + Bmin;
+ for (B = Bmin; B <= Bmax; B++)
+ if (*histp++ != 0) {
+ boxp->Rmin = Rmin = R;
+ goto have_Rmin;
+ }
+ }
+have_Rmin:
+ if (Rmax > Rmin)
+ for (R = Rmax; R >= Rmin; R--)
+ for (G = Gmin; G <= Gmax; G++) {
+ histp = histogram + R * MR + G * MG + Bmin;
+ for (B = Bmin; B <= Bmax; B++)
+ if (*histp++ != 0) {
+ boxp->Rmax = Rmax = R;
+ goto have_Rmax;
+ }
+ }
+have_Rmax:
+ if (Gmax > Gmin)
+ for (G = Gmin; G <= Gmax; G++)
+ for (R = Rmin; R <= Rmax; R++) {
+ histp = histogram + R * MR + G * MG + Bmin;
+ for (B = Bmin; B <= Bmax; B++)
+ if (*histp++ != 0) {
+ boxp->Gmin = Gmin = G;
+ goto have_Gmin;
+ }
+ }
+have_Gmin:
+ if (Gmax > Gmin)
+ for (G = Gmax; G >= Gmin; G--)
+ for (R = Rmin; R <= Rmax; R++) {
+ histp = histogram + R * MR + G * MG + Bmin;
+ for (B = Bmin; B <= Bmax; B++)
+ if (*histp++ != 0) {
+ boxp->Gmax = Gmax = G;
+ goto have_Gmax;
+ }
+ }
+have_Gmax:
+ if (Bmax > Bmin)
+ for (B = Bmin; B <= Bmax; B++)
+ for (R = Rmin; R <= Rmax; R++) {
+ histp = histogram + R * MR + Gmin * MG + B;
+ for (G = Gmin; G <= Gmax; G++, histp += MG)
+ if (*histp != 0) {
+ boxp->Bmin = Bmin = B;
+ goto have_Bmin;
+ }
+ }
+have_Bmin:
+ if (Bmax > Bmin)
+ for (B = Bmax; B >= Bmin; B--)
+ for (R = Rmin; R <= Rmax; R++) {
+ histp = histogram + R * MR + Gmin * MG + B;
+ for (G = Gmin; G <= Gmax; G++, histp += MG)
+ if (*histp != 0) {
+ boxp->Bmax = Bmax = B;
+ goto have_Bmax;
+ }
+ }
+have_Bmax:
+
+ /* Update box volume.
+ * We use 2-norm rather than real volume here; this biases the method
+ * against making long narrow boxes, and it has the side benefit that
+ * a box is splittable iff norm > 0.
+ * Since the differences are expressed in histogram-cell units,
+ * we have to shift back to JSAMPLE units to get consistent distances;
+ * after which, we scale according to the selected distance scale factors.
+ */
+ dist0 = Rmax - Rmin;
+ dist1 = Gmax - Gmin;
+ dist2 = Bmax - Bmin;
+ boxp->volume = dist0 * dist0 + dist1 * dist1 + dist2 * dist2;
+
+ /* Now scan remaining volume of box and compute population */
+ ccount = 0;
+ for (R = Rmin; R <= Rmax; R++)
+ for (G = Gmin; G <= Gmax; G++) {
+ histp = histogram + R * MR + G * MG + Bmin;
+ for (B = Bmin; B <= Bmax; B++, histp++)
+ if (*histp != 0) {
+ ccount++;
+ }
+ }
+
+ boxp->colorcount = ccount;
+}
+
+static int median_cut_rgb(Histogram histogram, boxptr boxlist, int numboxes, int desired_colors)
+/* Repeatedly select and split the largest box until we have enough boxes */
+{
+ int n, lb;
+ int R, G, B, cmax;
+ boxptr b1, b2;
+
+ while (numboxes < desired_colors) {
+ /* Select box to split.
+ * Current algorithm: by population for first half, then by volume.
+ */
+ b1 = find_biggest_volume(boxlist, numboxes);
+
+ if (b1 == 0) /* no splittable boxes left! */
+ break;
+ b2 = boxlist + numboxes; /* where new box will go */
+ /* Copy the color bounds to the new box. */
+ b2->Rmax = b1->Rmax;
+ b2->Gmax = b1->Gmax;
+ b2->Bmax = b1->Bmax;
+ b2->Rmin = b1->Rmin;
+ b2->Gmin = b1->Gmin;
+ b2->Bmin = b1->Bmin;
+ /* Choose which axis to split the box on.
+ * Current algorithm: longest scaled axis.
+ * See notes in update_box about scaling distances.
+ */
+ R = b1->Rmax - b1->Rmin;
+ G = b1->Gmax - b1->Gmin;
+ B = b1->Bmax - b1->Bmin;
+ /* We want to break any ties in favor of green, then red, blue last.
+ */
+ cmax = G;
+ n = 1;
+ if (R > cmax) {
+ cmax = R;
+ n = 0;
+ }
+ if (B > cmax) {
+ n = 2;
+ }
+ /* Choose split point along selected axis, and update box bounds.
+ * Current algorithm: split at halfway point.
+ * (Since the box has been shrunk to minimum volume,
+ * any split will produce two nonempty subboxes.)
+ * Note that lb value is max for lower box, so must be < old max.
+ */
+ switch (n) {
+ case 0:
+ lb = (b1->Rmax + b1->Rmin) / 2;
+ b1->Rmax = lb;
+ b2->Rmin = lb + 1;
+ break;
+ case 1:
+ lb = (b1->Gmax + b1->Gmin) / 2;
+ b1->Gmax = lb;
+ b2->Gmin = lb + 1;
+ break;
+ case 2:
+ lb = (b1->Bmax + b1->Bmin) / 2;
+ b1->Bmax = lb;
+ b2->Bmin = lb + 1;
+ break;
+ }
+ /* Update stats for boxes */
+ update_box_rgb(histogram, b1);
+ update_box_rgb(histogram, b2);
+ numboxes++;
+ }
+ return numboxes;
+}
+
+static void compute_color_rgb(QuantizeObj * quantobj, Histogram histogram, boxptr boxp, int icolor)
+/* Compute representative color for a box, put it in colormap[icolor] */
+{
+ /* Current algorithm: mean weighted by pixels (not colors) */
+ /* Note it is important to get the rounding correct! */
+ ColorFreq *histp;
+ int R, G, B;
+ int Rmin, Rmax;
+ int Gmin, Gmax;
+ int Bmin, Bmax;
+ unsigned long count;
+ unsigned long total = 0;
+ unsigned long Rtotal = 0;
+ unsigned long Gtotal = 0;
+ unsigned long Btotal = 0;
+
+ Rmin = boxp->Rmin;
+ Rmax = boxp->Rmax;
+ Gmin = boxp->Gmin;
+ Gmax = boxp->Gmax;
+ Bmin = boxp->Bmin;
+ Bmax = boxp->Bmax;
+
+ for (R = Rmin; R <= Rmax; R++)
+ for (G = Gmin; G <= Gmax; G++) {
+ histp = histogram + R * MR + G * MG + Bmin;
+ for (B = Bmin; B <= Bmax; B++) {
+ if ((count = *histp++) != 0) {
+ total += count;
+ Rtotal += ((R << R_SHIFT) + ((1 << R_SHIFT) >> 1)) * count;
+ Gtotal += ((G << G_SHIFT) + ((1 << G_SHIFT) >> 1)) * count;
+ Btotal += ((B << B_SHIFT) + ((1 << B_SHIFT) >> 1)) * count;
+ }
+ }
+ }
+
+ quantobj->cmap[icolor].r = (unsigned char)((Rtotal + (total >> 1)) / total);
+ quantobj->cmap[icolor].g = (unsigned char)((Gtotal + (total >> 1)) / total);
+ quantobj->cmap[icolor].b = (unsigned char)((Btotal + (total >> 1)) / total);
+ quantobj->freq[icolor] = total;
+}
+
+static void select_colors_rgb(QuantizeObj * quantobj, Histogram histogram)
+/* Master routine for color selection */
+{
+ boxptr boxlist;
+ int numboxes;
+ int desired = quantobj->desired_number_of_colors;
+ int i;
+
+ /* Allocate workspace for box list */
+ XMALLOC(boxlist, desired * sizeof(box));
+
+ /* Initialize one box containing whole space */
+ numboxes = 1;
+ boxlist[0].Rmin = 0;
+ boxlist[0].Rmax = (1 << PRECISION_R) - 1;
+ boxlist[0].Gmin = 0;
+ boxlist[0].Gmax = (1 << PRECISION_G) - 1;
+ boxlist[0].Bmin = 0;
+ boxlist[0].Bmax = (1 << PRECISION_B) - 1;
+ /* Shrink it to actually-used volume and set its statistics */
+ update_box_rgb(histogram, boxlist);
+ /* Perform median-cut to produce final box list */
+ numboxes = median_cut_rgb(histogram, boxlist, numboxes, desired);
+ quantobj->actual_number_of_colors = numboxes;
+ /* Compute the representative color for each box, fill colormap */
+ for (i = 0; i < numboxes; i++)
+ compute_color_rgb(quantobj, histogram, boxlist + i, i);
+ free(boxlist);
+}
+
+/*
+ * These routines are concerned with the time-critical task of mapping input
+ * colors to the nearest color in the selected colormap.
+ *
+ * We re-use the histogram space as an "inverse color map", essentially a
+ * cache for the results of nearest-color searches. All colors within a
+ * histogram cell will be mapped to the same colormap entry, namely the one
+ * closest to the cell's center. This may not be quite the closest entry to
+ * the actual input color, but it's almost as good. A zero in the cache
+ * indicates we haven't found the nearest color for that cell yet; the array
+ * is cleared to zeroes before starting the mapping pass. When we find the
+ * nearest color for a cell, its colormap index plus one is recorded in the
+ * cache for future use. The pass2 scanning routines call fill_inverse_cmap
+ * when they need to use an unfilled entry in the cache.
+ *
+ * Our method of efficiently finding nearest colors is based on the "locally
+ * sorted search" idea described by Heckbert and on the incremental distance
+ * calculation described by Spencer W. Thomas in chapter III.1 of Graphics
+ * Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that
+ * the distances from a given colormap entry to each cell of the histogram can
+ * be computed quickly using an incremental method: the differences between
+ * distances to adjacent cells themselves differ by a constant. This allows a
+ * fairly fast implementation of the "brute force" approach of computing the
+ * distance from every colormap entry to every histogram cell. Unfortunately,
+ * it needs a work array to hold the best-distance-so-far for each histogram
+ * cell (because the inner loop has to be over cells, not colormap entries).
+ * The work array elements have to be ints, so the work array would need
+ * 256Kb at our recommended precision. This is not feasible in DOS machines.
+
+[ 256*1024/4 = 65,536 ]
+
+ * To get around these problems, we apply Thomas' method to compute the
+ * nearest colors for only the cells within a small subbox of the histogram.
+ * The work array need be only as big as the subbox, so the memory usage
+ * problem is solved. Furthermore, we need not fill subboxes that are never
+ * referenced in pass2; many images use only part of the color gamut, so a
+ * fair amount of work is saved. An additional advantage of this
+ * approach is that we can apply Heckbert's locality criterion to quickly
+ * eliminate colormap entries that are far away from the subbox; typically
+ * three-fourths of the colormap entries are rejected by Heckbert's criterion,
+ * and we need not compute their distances to individual cells in the subbox.
+ * The speed of this approach is heavily influenced by the subbox size: too
+ * small means too much overhead, too big loses because Heckbert's criterion
+ * can't eliminate as many colormap entries. Empirically the best subbox
+ * size seems to be about 1/512th of the histogram (1/8th in each direction).
+ *
+ * Thomas' article also describes a refined method which is asymptotically
+ * faster than the brute-force method, but it is also far more complex and
+ * cannot efficiently be applied to small subboxes. It is therefore not
+ * useful for programs intended to be portable to DOS machines. On machines
+ * with plenty of memory, filling the whole histogram in one shot with Thomas'
+ * refined method might be faster than the present code --- but then again,
+ * it might not be any faster, and it's certainly more complicated.
+ */
+
+/* log2(histogram cells in update box) for each axis; this can be adjusted */
+#define BOX_R_LOG (PRECISION_R-3)
+#define BOX_G_LOG (PRECISION_G-3)
+#define BOX_B_LOG (PRECISION_B-3)
+
+#define BOX_R_ELEMS (1<<BOX_R_LOG) /* # of hist cells in update box */
+#define BOX_G_ELEMS (1<<BOX_G_LOG)
+#define BOX_B_ELEMS (1<<BOX_B_LOG)
+
+#define BOX_R_SHIFT (R_SHIFT + BOX_R_LOG)
+#define BOX_G_SHIFT (G_SHIFT + BOX_G_LOG)
+#define BOX_B_SHIFT (B_SHIFT + BOX_B_LOG)
+
+/*
+ * The next three routines implement inverse colormap filling. They could
+ * all be folded into one big routine, but splitting them up this way saves
+ * some stack space (the mindist[] and bestdist[] arrays need not coexist)
+ * and may allow some compilers to produce better code by registerizing more
+ * inner-loop variables.
+ */
+
+static int find_nearby_colors(QuantizeObj * quantobj, int minR, int minG, int minB, int *colorlist)
+/* Locate the colormap entries close enough to an update box to be candidates
+ * for the nearest entry to some cell(s) in the update box. The update box
+ * is specified by the center coordinates of its first cell. The number of
+ * candidate colormap entries is returned, and their colormap indexes are
+ * placed in colorlist[].
+ * This routine uses Heckbert's "locally sorted search" criterion to select
+ * the colors that need further consideration.
+ */
+{
+ int numcolors = quantobj->actual_number_of_colors;
+ int maxR, maxG, maxB;
+ int centerR, centerG, centerB;
+ int i, x, ncolors;
+ int minmaxdist, min_dist = 0, max_dist, tdist;
+ int mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */
+
+ /* Compute TRUE coordinates of update box's upper corner and center.
+ * Actually we compute the coordinates of the center of the upper-corner
+ * histogram cell, which are the upper bounds of the volume we care about.
+ * Note that since ">>" rounds down, the "center" values may be closer to
+ * min than to max; hence comparisons to them must be "<=", not "<".
+ */
+ maxR = minR + ((1 << BOX_R_SHIFT) - (1 << R_SHIFT));
+ centerR = (minR + maxR) >> 1;
+ maxG = minG + ((1 << BOX_G_SHIFT) - (1 << G_SHIFT));
+ centerG = (minG + maxG) >> 1;
+ maxB = minB + ((1 << BOX_B_SHIFT) - (1 << B_SHIFT));
+ centerB = (minB + maxB) >> 1;
+
+ /* For each color in colormap, find:
+ * 1. its minimum squared-distance to any point in the update box
+ * (zero if color is within update box);
+ * 2. its maximum squared-distance to any point in the update box.
+ * Both of these can be found by considering only the corners of the box.
+ * We save the minimum distance for each color in mindist[];
+ * only the smallest maximum distance is of interest.
+ */
+ minmaxdist = 0x7FFFFFFFL;
+
+ for (i = 0; i < numcolors; i++) {
+ /* We compute the squared-R-distance term, then add in the other two. */
+ x = quantobj->cmap[i].r;
+ if (x < minR) {
+ tdist = (x - minR) R_SCALE;
+ min_dist = tdist * tdist;
+ tdist = (x - maxR) R_SCALE;
+ max_dist = tdist * tdist;
+ } else if (x > maxR) {
+ tdist = (x - maxR) R_SCALE;
+ min_dist = tdist * tdist;
+ tdist = (x - minR) R_SCALE;
+ max_dist = tdist * tdist;
+ } else {
+ /* within cell range so no contribution to min_dist */
+ min_dist = 0;
+ if (x <= centerR) {
+ tdist = (x - maxR) R_SCALE;
+ max_dist = tdist * tdist;
+ } else {
+ tdist = (x - minR) R_SCALE;
+ max_dist = tdist * tdist;
+ }
+ }
+
+ x = quantobj->cmap[i].g;
+ if (x < minG) {
+ tdist = (x - minG) G_SCALE;
+ min_dist += tdist * tdist;
+ tdist = (x - maxG) G_SCALE;
+ max_dist += tdist * tdist;
+ } else if (x > maxG) {
+ tdist = (x - maxG) G_SCALE;
+ min_dist += tdist * tdist;
+ tdist = (x - minG) G_SCALE;
+ max_dist += tdist * tdist;
+ } else {
+ /* within cell range so no contribution to min_dist */
+ if (x <= centerG) {
+ tdist = (x - maxG) G_SCALE;
+ max_dist += tdist * tdist;
+ } else {
+ tdist = (x - minG) G_SCALE;
+ max_dist += tdist * tdist;
+ }
+ }
+
+ x = quantobj->cmap[i].b;
+ if (x < minB) {
+ tdist = (x - minB) B_SCALE;
+ min_dist += tdist * tdist;
+ tdist = (x - maxB) B_SCALE;
+ max_dist += tdist * tdist;
+ } else if (x > maxB) {
+ tdist = (x - maxB) B_SCALE;
+ min_dist += tdist * tdist;
+ tdist = (x - minB) B_SCALE;
+ max_dist += tdist * tdist;
+ } else {
+ /* within cell range so no contribution to min_dist */
+ if (x <= centerB) {
+ tdist = (x - maxB) B_SCALE;
+ max_dist += tdist * tdist;
+ } else {
+ tdist = (x - minB) B_SCALE;
+ max_dist += tdist * tdist;
+ }
+ }
+
+ mindist[i] = min_dist; /* save away the results */
+ if (max_dist < minmaxdist)
+ minmaxdist = max_dist;
+ }
+
+ /* Now we know that no cell in the update box is more than minmaxdist
+ * away from some colormap entry. Therefore, only colors that are
+ * within minmaxdist of some part of the box need be considered.
+ */
+ ncolors = 0;
+ for (i = 0; i < numcolors; i++) {
+ if (mindist[i] <= minmaxdist)
+ colorlist[ncolors++] = i;
+ }
+ return ncolors;
+}
+
+static void find_best_colors(QuantizeObj * quantobj, int minR, int minG, int minB, int numcolors, int *colorlist, int *bestcolor)
+/* Find the closest colormap entry for each cell in the update box,
+ given the list of candidate colors prepared by find_nearby_colors.
+ Return the indexes of the closest entries in the bestcolor[] array.
+ This routine uses Thomas' incremental distance calculation method to
+ find the distance from a colormap entry to successive cells in the box.
+ */
+{
+ int iR, iG, iB;
+ int i, icolor;
+ int *bptr; /* pointer into bestdist[] array */
+ int *cptr; /* pointer into bestcolor[] array */
+ int dist0, dist1; /* initial distance values */
+ int dist2; /* current distance in inner loop */
+ int xx0, xx1; /* distance increments */
+ int xx2;
+ int inR, inG, inB; /* initial values for increments */
+
+ /* This array holds the distance to the nearest-so-far color for each cell */
+ int bestdist[BOX_R_ELEMS * BOX_G_ELEMS * BOX_B_ELEMS];
+
+ /* Initialize best-distance for each cell of the update box */
+ bptr = bestdist;
+ for (i = BOX_R_ELEMS * BOX_G_ELEMS * BOX_B_ELEMS - 1; i >= 0; i--)
+ *bptr++ = 0x7FFFFFFFL;
+
+ /* For each color selected by find_nearby_colors,
+ * compute its distance to the center of each cell in the box.
+ * If that's less than best-so-far, update best distance and color number.
+ */
+
+ /* Nominal steps between cell centers ("x" in Thomas article) */
+#define STEP_R ((1 << R_SHIFT) R_SCALE)
+#define STEP_G ((1 << G_SHIFT) G_SCALE)
+#define STEP_B ((1 << B_SHIFT) B_SCALE)
+
+ for (i = 0; i < numcolors; i++) {
+ icolor = colorlist[i];
+ /* Compute (square of) distance from minR/G/B to this color */
+ inR = (minR - quantobj->cmap[icolor].r) R_SCALE;
+ dist0 = inR * inR;
+ inG = (minG - quantobj->cmap[icolor].g) G_SCALE;
+ dist0 += inG * inG;
+ inB = (minB - quantobj->cmap[icolor].b) B_SCALE;
+ dist0 += inB * inB;
+ /* Form the initial difference increments */
+ inR = inR * (2 * STEP_R) + STEP_R * STEP_R;
+ inG = inG * (2 * STEP_G) + STEP_G * STEP_G;
+ inB = inB * (2 * STEP_B) + STEP_B * STEP_B;
+ /* Now loop over all cells in box, updating distance per Thomas method */
+ bptr = bestdist;
+ cptr = bestcolor;
+ xx0 = inR;
+ for (iR = BOX_R_ELEMS - 1; iR >= 0; iR--) {
+ dist1 = dist0;
+ xx1 = inG;
+ for (iG = BOX_G_ELEMS - 1; iG >= 0; iG--) {
+ dist2 = dist1;
+ xx2 = inB;
+ for (iB = BOX_B_ELEMS - 1; iB >= 0; iB--) {
+ if (dist2 < *bptr) {
+ *bptr = dist2;
+ *cptr = icolor;
+ }
+ dist2 += xx2;
+ xx2 += 2 * STEP_B * STEP_B;
+ bptr++;
+ cptr++;
+ }
+ dist1 += xx1;
+ xx1 += 2 * STEP_G * STEP_G;
+ }
+ dist0 += xx0;
+ xx0 += 2 * STEP_R * STEP_R;
+ }
+ }
+}
+
+static void fill_inverse_cmap_rgb(QuantizeObj * quantobj, Histogram histogram, int R, int G, int B)
+/* Fill the inverse-colormap entries in the update box that contains
+ histogram cell R/G/B. (Only that one cell MUST be filled, but
+ we can fill as many others as we wish.) */
+{
+ int minR, minG, minB; /* lower left corner of update box */
+ int iR, iG, iB;
+ int *cptr; /* pointer into bestcolor[] array */
+ ColorFreq *cachep; /* pointer into main cache array */
+ /* This array lists the candidate colormap indexes. */
+ int colorlist[MAXNUMCOLORS];
+ int numcolors; /* number of candidate colors */
+ /* This array holds the actually closest colormap index for each cell. */
+ int bestcolor[BOX_R_ELEMS * BOX_G_ELEMS * BOX_B_ELEMS];
+
+ /* Convert cell coordinates to update box ID */
+ R >>= BOX_R_LOG;
+ G >>= BOX_G_LOG;
+ B >>= BOX_B_LOG;
+
+ /* Compute TRUE coordinates of update box's origin corner.
+ * Actually we compute the coordinates of the center of the corner
+ * histogram cell, which are the lower bounds of the volume we care about.
+ */
+ minR = (R << BOX_R_SHIFT) + ((1 << R_SHIFT) >> 1);
+ minG = (G << BOX_G_SHIFT) + ((1 << G_SHIFT) >> 1);
+ minB = (B << BOX_B_SHIFT) + ((1 << B_SHIFT) >> 1);
+
+ /* Determine which colormap entries are close enough to be candidates
+ * for the nearest entry to some cell in the update box.
+ */
+ numcolors = find_nearby_colors(quantobj, minR, minG, minB, colorlist);
+
+ /* Determine the actually nearest colors. */
+ find_best_colors(quantobj, minR, minG, minB, numcolors, colorlist, bestcolor);
+
+ /* Save the best color numbers (plus 1) in the main cache array */
+ R <<= BOX_R_LOG; /* convert ID back to base cell indexes */
+ G <<= BOX_G_LOG;
+ B <<= BOX_B_LOG;
+ cptr = bestcolor;
+ for (iR = 0; iR < BOX_R_ELEMS; iR++) {
+ for (iG = 0; iG < BOX_G_ELEMS; iG++) {
+ cachep = &histogram[(R + iR) * MR + (G + iG) * MG + B];
+ for (iB = 0; iB < BOX_B_ELEMS; iB++) {
+ *cachep++ = (*cptr++) + 1;
+ }
+ }
+ }
+}
+
+/* This is pass 1 */
+static void median_cut_pass1_rgb(QuantizeObj * quantobj, at_bitmap * image, const at_color * ignoreColor)
+{
+ generate_histogram_rgb(quantobj->histogram, image, ignoreColor);
+ select_colors_rgb(quantobj, quantobj->histogram);
+}
+
+/* Map some rows of pixels to the output colormapped representation. */
+static void median_cut_pass2_rgb(QuantizeObj * quantobj, at_bitmap * image, const at_color * bgColor)
+ /* This version performs no dithering */
+{
+ Histogram histogram = quantobj->histogram;
+ ColorFreq *cachep;
+ int R, G, B;
+ int origR, origG, origB;
+ int row, col;
+ int spp = AT_BITMAP_PLANES(image);
+ int width = AT_BITMAP_WIDTH(image);
+ int height = AT_BITMAP_HEIGHT(image);
+ unsigned char *src, *dest;
+ at_color bg_color = { 0xff, 0xff, 0xff };
+
+ zero_histogram_rgb(histogram);
+
+ if (bgColor) {
+ /* Find the nearest colormap entry for the background color. */
+ R = bgColor->r >> R_SHIFT;
+ G = bgColor->g >> G_SHIFT;
+ B = bgColor->b >> B_SHIFT;
+ cachep = &histogram[R * MR + G * MG + B];
+ if (*cachep == 0)
+ fill_inverse_cmap_rgb(quantobj, histogram, R, G, B);
+ bg_color = quantobj->cmap[*cachep - 1];
+ }
+
+ src = dest = image->bitmap;
+ if (spp == 3) {
+ for (row = 0; row < height; row++) {
+ for (col = 0; col < width; col++) {
+ /* get pixel value and index into the cache */
+ origR = (*src++);
+ origG = (*src++);
+ origB = (*src++);
+
+ /*
+ if (origR > 253 && origG > 253 && origB > 253)
+ {
+ (*dest++) = 255; (*dest++) = 255; (*dest++) = 255;
+ continue;
+ }
+ */
+
+ /* get pixel value and index into the cache */
+ R = origR >> R_SHIFT;
+ G = origG >> G_SHIFT;
+ B = origB >> B_SHIFT;
+ cachep = &histogram[R * MR + G * MG + B];
+ /* If we have not seen this color before, find nearest
+ colormap entry and update the cache */
+ if (*cachep == 0) {
+ fill_inverse_cmap_rgb(quantobj, histogram, R, G, B);
+ }
+ /* Now emit the colormap index for this cell */
+ dest[0] = quantobj->cmap[*cachep - 1].r;
+ dest[1] = quantobj->cmap[*cachep - 1].g;
+ dest[2] = quantobj->cmap[*cachep - 1].b;
+
+ /* If the colormap entry for this pixel is the same as the
+ background's colormap entry, set the pixel to the
+ background color. */
+ if (bgColor && (dest[0] == bg_color.r && dest[1] == bg_color.g && dest[2] == bg_color.b)) {
+ dest[0] = bgColor->r;
+ dest[1] = bgColor->g;
+ dest[2] = bgColor->b;
+ }
+ dest += 3;
+ }
+ }
+ } else if (spp == 1) {
+ long idx = width * height;
+ while (--idx >= 0) {
+ origR = src[idx];
+ R = origR >> R_SHIFT;
+ G = origR >> G_SHIFT;
+ B = origR >> B_SHIFT;
+ cachep = &histogram[R * MR + G * MG + B];
+ if (*cachep == 0)
+ fill_inverse_cmap_rgb(quantobj, histogram, R, G, B);
+
+ dest[idx] = quantobj->cmap[*cachep - 1].r;
+
+ /* If the colormap entry for this pixel is the same as the
+ background's colormap entry, set the pixel to the
+ background color. */
+ if (bgColor && dest[idx] == bg_color.r)
+ dest[idx] = bgColor->r;
+ }
+ }
+}
+
+static QuantizeObj *initialize_median_cut(int num_colors)
+{
+ QuantizeObj *quantobj;
+
+ /* Initialize the data structures */
+ XMALLOC(quantobj, sizeof(QuantizeObj));
+
+ XMALLOC(quantobj->histogram, sizeof(ColorFreq) * HIST_R_ELEMS * HIST_G_ELEMS * HIST_B_ELEMS);
+ quantobj->desired_number_of_colors = num_colors;
+
+ return quantobj;
+}
+
+void quantize(at_bitmap * image, long ncolors, const at_color * bgColor, QuantizeObj ** iQuant, at_exception_type * exp)
+{
+ QuantizeObj *quantobj;
+ unsigned int spp = AT_BITMAP_PLANES(image);
+
+ if (spp != 3 && spp != 1) {
+ LOG("quantize: %u-plane images are not supported", spp);
+ at_exception_fatal(exp, "quantize: wrong plane images are passed");
+ return;
+ }
+
+ /* If a pointer was sent in, let's use it. */
+ if (iQuant) {
+ if (*iQuant == NULL) {
+ quantobj = initialize_median_cut(ncolors);
+ median_cut_pass1_rgb(quantobj, image, bgColor);
+ *iQuant = quantobj;
+ } else
+ quantobj = *iQuant;
+ } else {
+ quantobj = initialize_median_cut(ncolors);
+ median_cut_pass1_rgb(quantobj, image, NULL);
+ }
+
+ median_cut_pass2_rgb(quantobj, image, bgColor);
+
+ if (iQuant == NULL)
+ quantize_object_free(quantobj);
+}
+
+void quantize_object_free(QuantizeObj * quantobj)
+{
+ free(quantobj->histogram);
+ free(quantobj);
+}
diff --git a/src/3rdparty/autotrace/module.c b/src/3rdparty/autotrace/module.c
new file mode 100644
index 0000000..ab8187a
--- /dev/null
+++ b/src/3rdparty/autotrace/module.c
@@ -0,0 +1,52 @@
+/* module.c --- Autotrace plugin module management subsystem
+
+ Copyright (C) 2003 Martin Weber
+ Copyright (C) 2003 Masatake YAMATO
+
+ The author can be contacted at <martweb@gmx.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* Def: HAVE_CONFIG_H */
+#include "intl.h"
+
+#include "private.h"
+
+#include "input.h"
+
+static int install_input_readers(void);
+static int install_output_writers(void);
+
+int at_module_init(void)
+{
+ int r, w;
+ /* TODO: Loading every thing in dynamic.
+ For a while, these are staticly added. */
+ r = install_input_readers();
+ w = install_output_writers();
+ return (int)(r << 2 | w);
+}
+
+static int install_input_readers(void)
+{
+ return 0;
+}
+
+static int install_output_writers(void)
+{
+ return 0;
+}
diff --git a/src/3rdparty/autotrace/output.c b/src/3rdparty/autotrace/output.c
new file mode 100644
index 0000000..5b5a88e
--- /dev/null
+++ b/src/3rdparty/autotrace/output.c
@@ -0,0 +1,243 @@
+/* output.c: interface for output handlers
+
+ Copyright (C) 1999, 2000, 2001 Bernhard Herzog.
+ Copyright (C) 2003 Masatake YAMATO
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License
+ as published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA. */
+
+/* TODO: Unify output codes and input codes. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* Def: HAVE_CONFIG_H */
+
+#include "autotrace.h"
+#include "private.h"
+#include "output.h"
+#include "xstd.h"
+#include "filename.h"
+#include <string.h>
+#include <glib.h>
+
+typedef struct _at_output_format_entry at_output_format_entry;
+struct _at_output_format_entry {
+ at_spline_writer writer;
+ const char *descr;
+ GDestroyNotify user_data_destroy_func;
+};
+
+static GHashTable *at_output_formats = NULL;
+static at_output_format_entry *at_output_format_new(const char *descr, at_output_func writer, gpointer user_data, GDestroyNotify user_data_destroy_func);
+static void at_output_format_free(at_output_format_entry * entry);
+
+/*
+ * Helper functions
+ */
+static void output_list_set(gpointer key, gpointer value, gpointer user_data);
+static void output_list_strlen(gpointer key, gpointer value, gpointer user_data);
+static void output_list_strcat(gpointer key, gpointer value, gpointer user_data);
+
+int at_output_init(void)
+{
+ if (at_output_formats)
+ return 1;
+
+ at_output_formats = g_hash_table_new_full(g_str_hash, (GEqualFunc) g_str_equal, g_free, (GDestroyNotify) at_output_format_free);
+ if (!at_output_formats)
+ return 0;
+ return 1;
+}
+
+static at_output_format_entry *at_output_format_new(const gchar * descr, at_output_func writer, gpointer user_data, GDestroyNotify user_data_destroy_func)
+{
+ at_output_format_entry *entry;
+ entry = g_malloc(sizeof(at_output_format_entry));
+ if (entry) {
+ entry->writer.func = writer;
+ entry->writer.data = user_data;
+ entry->descr = g_strdup(descr);
+ entry->user_data_destroy_func = user_data_destroy_func;
+ }
+ return entry;
+}
+
+static void at_output_format_free(at_output_format_entry * entry)
+{
+ g_free((gpointer) entry->descr);
+ if (entry->user_data_destroy_func)
+ entry->user_data_destroy_func(entry->writer.data);
+ g_free(entry);
+
+}
+
+int at_output_add_handler(const gchar * suffix, const gchar * description, at_output_func writer)
+{
+ return at_output_add_handler_full(suffix, description, writer, 0, NULL, NULL);
+}
+
+int at_output_add_handler_full(const gchar * suffix, const gchar * description, at_output_func writer, gboolean override, gpointer user_data, GDestroyNotify user_data_destroy_func)
+{
+ gchar *gsuffix_raw;
+ gchar *gsuffix;
+ const gchar *gdescription;
+ at_output_format_entry *old_entry;
+ at_output_format_entry *new_entry;
+
+ g_return_val_if_fail(suffix, 0);
+ g_return_val_if_fail(description, 0);
+ g_return_val_if_fail(writer, 0);
+
+ gsuffix_raw = g_strdup((gchar *) suffix);
+ g_return_val_if_fail(gsuffix_raw, 0);
+ gsuffix = g_ascii_strdown(gsuffix_raw, strlen(gsuffix_raw));
+ g_free(gsuffix_raw);
+
+ gdescription = (const gchar *)description;
+
+ old_entry = g_hash_table_lookup(at_output_formats, gsuffix);
+ if (old_entry && !override) {
+ g_free(gsuffix);
+ return 1;
+ }
+
+ new_entry = at_output_format_new(gdescription, writer, user_data, user_data_destroy_func);
+ g_return_val_if_fail(new_entry, 0);
+
+ g_hash_table_replace(at_output_formats, gsuffix, new_entry);
+ return 1;
+}
+
+at_spline_writer *at_output_get_handler(gchar * filename)
+{
+ char *ext = find_suffix(filename);
+ if (ext == NULL)
+ ext = "";
+
+ return at_output_get_handler_by_suffix(ext);
+}
+
+at_spline_writer *at_output_get_handler_by_suffix(gchar * suffix)
+{
+ at_output_format_entry *format;
+ gchar *gsuffix_raw;
+ gchar *gsuffix;
+
+ if (!suffix || suffix[0] == '\0')
+ return NULL;
+
+ gsuffix_raw = g_strdup(suffix);
+ g_return_val_if_fail(gsuffix_raw, NULL);
+ gsuffix = g_ascii_strdown(gsuffix_raw, strlen(gsuffix_raw));
+ g_free(gsuffix_raw);
+ format = g_hash_table_lookup(at_output_formats, gsuffix);
+ g_free(gsuffix);
+
+ if (format)
+ return &(format->writer);
+ else
+ return NULL;
+}
+
+const char **at_output_list_new(void)
+{
+ char **list, **tmp;
+ gint format_count;
+ gint list_count;
+
+ format_count = g_hash_table_size(at_output_formats);
+ list_count = 2 * format_count;
+ list = g_new(gchar *, list_count + 1);
+ list[list_count] = NULL;
+
+ tmp = list;
+ g_hash_table_foreach(at_output_formats, output_list_set, &tmp);
+ return (const char **)list;
+}
+
+void at_output_list_free(const char **list)
+{
+ free((char **)list);
+}
+
+char *at_output_shortlist(void)
+{
+ gint length = 0, count;
+ char *list, *tmp;
+ g_hash_table_foreach(at_output_formats, output_list_strlen, &length);
+ count = g_hash_table_size(at_output_formats);
+
+ /* 2 for ", " */
+ length += (2 * count);
+ list = g_malloc(length + 1);
+ list[0] = '\0';
+
+ tmp = list;
+ g_hash_table_foreach(at_output_formats, output_list_strcat, &tmp);
+
+ /* remove final ", " */
+ g_return_val_if_fail(list[length - 2] == ',', NULL);
+ list[length - 2] = '\0';
+ return list;
+}
+
+static void output_list_set(gpointer key, gpointer value, gpointer user_data)
+{
+ at_output_format_entry *format = value;
+ const char ***list_ptr = user_data;
+ const char **list = *list_ptr;
+ list[0] = key;
+ list[1] = format->descr;
+ *list_ptr = &(list[2]);
+}
+
+static void output_list_strlen(gpointer key, gpointer value, gpointer user_data)
+{
+ gint *length;
+ g_return_if_fail(key);
+ g_return_if_fail(user_data);
+
+ length = user_data;
+ *length += strlen(key);
+}
+
+static void output_list_strcat(gpointer key, gpointer value, gpointer user_data)
+{
+ gchar **list_ptr;
+ gchar *list;
+ list_ptr = user_data;
+ list = *list_ptr;
+ strcat(list, key);
+ strcat(list, ", ");
+
+ /* 2 for ", " */
+ *list_ptr = list + strlen(key) + 2;
+}
+
+void at_spline_list_foreach(at_spline_list_type * list, AtSplineListForeachFunc func, gpointer user_data)
+{
+ unsigned i;
+ for (i = 0; i < AT_SPLINE_LIST_LENGTH(list); i++) {
+ func(list, AT_SPLINE_LIST_ELT(list, i), i, user_data);
+ }
+}
+
+void at_spline_list_array_foreach(at_spline_list_array_type * list_array, AtSplineListArrayForeachFunc func, gpointer user_data)
+{
+ unsigned i;
+ for (i = 0; i < AT_SPLINE_LIST_ARRAY_LENGTH(list_array); i++) {
+ func(list_array, AT_SPLINE_LIST_ARRAY_ELT(list_array, i), i, user_data);
+ }
+}
diff --git a/src/3rdparty/autotrace/output.h b/src/3rdparty/autotrace/output.h
new file mode 100644
index 0000000..de88abc
--- /dev/null
+++ b/src/3rdparty/autotrace/output.h
@@ -0,0 +1,89 @@
+/* output.h: interface for output handlers
+
+ Copyright (C) 1999, 2000, 2001, 2002 Bernhard Herzog.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License
+ as published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA. */
+
+#ifndef OUTPUT_H
+#define OUTPUT_H
+#include <stdio.h>
+#include "autotrace.h"
+#include "types.h"
+#include "exception.h"
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+ typedef
+ int (*at_output_func) (FILE *, gchar * name, int llx, int lly, int urx, int ury, at_output_opts_type * opts, at_splines_type shape, at_msg_func msg_func, gpointer msg_data, gpointer user_data);
+
+ extern int at_output_add_handler(const gchar * suffix, const gchar * description, at_output_func writer);
+
+ extern int at_output_add_handler_full(const gchar * suffix, const gchar * description, at_output_func writer, gboolean override, gpointer user_data, GDestroyNotify user_data_destroy_func);
+
+/* Data struct hierarchy:
+ spline_list_array (splines)
+ -> spline_list...
+ --> spline */
+
+/* Accessors to the Data member */
+#define AT_SPLINE_START_POINT_VALUE(spl) ((spl).v[0])
+#define AT_SPLINE_CONTROL1_VALUE(spl) ((spl).v[1])
+#define AT_SPLINE_CONTROL2_VALUE(spl) ((spl).v[2])
+#define AT_SPLINE_END_POINT_VALUE(spl) ((spl).v[3])
+#define AT_SPLINE_DEGREE_VALUE(spl) ((spl).degree)
+
+#define AT_SPLINE_START_POINT(spl) (&AT_SPLINE_START_POINT_VALUE(*(spl)))
+#define AT_SPLINE_CONTROL1(spl) (&AT_SPLINE_CONTROL1_VALUE(*(spl)))
+#define AT_SPLINE_CONTROL2(spl) (&AT_SPLINE_CONTROL2_VALUE(*(spl)))
+#define AT_SPLINE_END_POINT(spl) (&AT_SPLINE_END_POINT_VALUE(*(spl)))
+#define AT_SPLINE_DEGREE(spl) AT_SPLINE_DEGREE_VALUE(*(spl))
+
+#define AT_SPLINE_LIST_LENGTH_VALUE(spll) ((spll).length)
+#define AT_SPLINE_LIST_LENGTH(spll) AT_SPLINE_LIST_LENGTH_VALUE(*(spll))
+#define AT_SPLINE_LIST_DATA_VALUE(spll) ((spll).data)
+#define AT_SPLINE_LIST_DATA(spll) AT_SPLINE_LIST_DATA_VALUE((*spll))
+#define AT_SPLINE_LIST_ELT_VALUE(spll,index) AT_SPLINE_LIST_DATA_VALUE(spll)[(index)]
+#define AT_SPLINE_LIST_ELT(spll,index) (&(AT_SPLINE_LIST_ELT_VALUE((*spll), (index))))
+#define AT_SPLINE_LIST_COLOR_VALUE(spll) ((spll).color)
+#define AT_SPLINE_LIST_COLOR(spll) (&(AT_SPLINE_LIST_COLOR_VALUE(*spll)))
+#define AT_SPLINE_LIST_IS_OPENED_VALUE(spll) ((spll).open)
+#define AT_SPLINE_LIST_IS_OPENED(spll) AT_SPLINE_LIST_IS_OPENED_VALUE(*(spll))
+
+#define AT_SPLINE_LIST_ARRAY_LENGTH_VALUE AT_SPLINE_LIST_LENGTH_VALUE
+#define AT_SPLINE_LIST_ARRAY_LENGTH AT_SPLINE_LIST_LENGTH
+#define AT_SPLINE_LIST_ARRAY_ELT_VALUE AT_SPLINE_LIST_ELT_VALUE
+#define AT_SPLINE_LIST_ARRAY_ELT AT_SPLINE_LIST_ELT
+
+#define AT_SPLINE_LIST_ARRAY_IS_CENTERLINE_VALUE(splla) ((splla).centerline)
+#define AT_SPLINE_LIST_ARRAY_IS_CENTERLINE(splla) AT_SPLINE_LIST_ARRAY_IS_CENTERLINE_VALUE(*(splla))
+
+/*
+ * Glib style traversing
+ */
+
+ typedef void (*AtSplineListForeachFunc) (at_spline_list_type * spline_list, at_spline_type * spline, int index, gpointer user_data);
+ typedef void (*AtSplineListArrayForeachFunc) (at_spline_list_array_type * spline_list_array, at_spline_list_type * spline_list, int index, gpointer user_data);
+
+ void at_spline_list_foreach(at_spline_list_type *, AtSplineListForeachFunc func, gpointer user_data);
+ void at_spline_list_array_foreach(at_spline_list_array_type *, AtSplineListArrayForeachFunc func, gpointer user_data);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* not OUTPUT_H */
diff --git a/src/3rdparty/autotrace/private.h b/src/3rdparty/autotrace/private.h
new file mode 100644
index 0000000..acb6815
--- /dev/null
+++ b/src/3rdparty/autotrace/private.h
@@ -0,0 +1,43 @@
+/* private.h --- Autotrace library private decls
+
+ Copyright (C) 2003 Martin Weber
+ Copyright (C) 2003 Masatake YAMATO
+
+ The author can be contacted at <martweb@gmx.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef PRIVATE_H
+#define PRIVATE_H
+
+#include "autotrace.h"
+#include "input.h"
+#include "output.h"
+
+struct _at_bitmap_reader {
+ at_input_func func;
+ gpointer data;
+};
+
+struct _at_spline_writer {
+ at_output_func func;
+ gpointer data;
+};
+
+int at_input_init(void);
+int at_output_init(void);
+int at_param_init(void);
+int at_module_init(void);
+#endif /* Not def: PRIVATE_H */
diff --git a/src/3rdparty/autotrace/pxl-outline.c b/src/3rdparty/autotrace/pxl-outline.c
new file mode 100644
index 0000000..d51f8ef
--- /dev/null
+++ b/src/3rdparty/autotrace/pxl-outline.c
@@ -0,0 +1,889 @@
+/* pxl-outline.c: find the outlines of a bitmap image; each outline is made up of one or more pixels;
+ and each pixel participates via one or more edges. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* Def: HAVE_CONFIG_H */
+
+#include "logreport.h"
+#include "types.h"
+#include "bitmap.h"
+#include "color.h"
+#include "bitmap.h"
+#include "xstd.h"
+#include "pxl-outline.h"
+#include <assert.h>
+
+/* We consider each pixel to consist of four edges, and we travel along
+ edges, instead of through pixel centers. This is necessary for those
+ unfortunate times when a single pixel is on both an inside and an
+ outside outline.
+
+ The numbers chosen here are not arbitrary; the code that figures out
+ which edge to move to depends on particular values. See the
+ `TRY_PIXEL' macro in `edge.c'. To emphasize this, I've written in the
+ numbers we need for each edge value. */
+
+typedef enum {
+ TOP = 1, LEFT = 2, BOTTOM = 3, RIGHT = 0, NO_EDGE = 4
+} edge_type;
+
+/* This choice is also not arbitrary: starting at the top edge makes the
+ code find outside outlines before inside ones, which is certainly
+ what we want. */
+#define START_EDGE top
+
+typedef enum {
+ NORTH = 0, NORTHWEST = 1, WEST = 2, SOUTHWEST = 3, SOUTH = 4,
+ SOUTHEAST = 5, EAST = 6, NORTHEAST = 7
+} direction_type;
+
+#define NUM_EDGES NO_EDGE
+
+#define COMPUTE_DELTA(axis, dir) \
+ ((dir) % 2 != 0 \
+ ? COMPUTE_##axis##_DELTA ((dir) - 1) \
+ + COMPUTE_##axis##_DELTA (((dir) + 1) % 8) \
+ : COMPUTE_##axis##_DELTA (dir) \
+ )
+
+#define COMPUTE_ROW_DELTA(dir) \
+ ((dir) == NORTH ? -1 : (dir) == SOUTH ? +1 : 0)
+
+#define COMPUTE_COL_DELTA(dir) \
+ ((dir) == WEST ? -1 : (dir) == EAST ? +1 : 0)
+
+static pixel_outline_type find_one_outline(at_bitmap *, edge_type, unsigned short, unsigned short, at_bitmap *, gboolean, gboolean, at_exception_type *);
+static pixel_outline_type find_one_centerline(at_bitmap *, direction_type, unsigned short, unsigned short, at_bitmap *);
+static void append_pixel_outline(pixel_outline_list_type *, pixel_outline_type);
+static pixel_outline_type new_pixel_outline(void);
+static void free_pixel_outline(pixel_outline_type *);
+static void concat_pixel_outline(pixel_outline_type *, const pixel_outline_type *);
+static void append_outline_pixel(pixel_outline_type *, at_coord);
+static gboolean is_marked_edge(edge_type, unsigned short, unsigned short, at_bitmap *);
+static gboolean is_outline_edge(edge_type, at_bitmap *, unsigned short, unsigned short, at_color, at_exception_type *);
+static gboolean is_unmarked_outline_edge(unsigned short, unsigned short, edge_type, at_bitmap *, at_bitmap *, at_color, at_exception_type *);
+
+static void mark_edge(edge_type e, unsigned short, unsigned short, at_bitmap *);
+/* static edge_type opposite_edge(edge_type); */
+
+static gboolean is_marked_dir(unsigned short, unsigned short, direction_type, at_bitmap *);
+static gboolean is_other_dir_marked(unsigned short, unsigned short, direction_type, at_bitmap *);
+static void mark_dir(unsigned short, unsigned short, direction_type, at_bitmap *);
+static gboolean next_unmarked_pixel(unsigned short *, unsigned short *, direction_type *, at_bitmap *, at_bitmap *);
+
+gboolean is_valid_dir(unsigned short, unsigned short, direction_type, at_bitmap *, at_bitmap *);
+
+static at_coord next_point(at_bitmap *, edge_type *, unsigned short *, unsigned short *, at_color, gboolean, at_bitmap *, at_exception_type *);
+static unsigned num_neighbors(unsigned short, unsigned short, at_bitmap *);
+
+#define CHECK_FATAL() if (at_exception_got_fatal(exp)) goto cleanup;
+
+/* We go through a bitmap TOP to BOTTOM, LEFT to RIGHT, looking for each pixel with an unmarked edge
+ that we consider a starting point of an outline. */
+
+pixel_outline_list_type find_outline_pixels(at_bitmap * bitmap, at_color * bg_color, at_progress_func notify_progress, gpointer progress_data, at_testcancel_func test_cancel, gpointer testcancel_data, at_exception_type * exp)
+{
+ pixel_outline_list_type outline_list;
+ unsigned short row, col;
+ at_bitmap *marked = at_bitmap_new(AT_BITMAP_WIDTH(bitmap), AT_BITMAP_HEIGHT(bitmap), 1);
+ unsigned int max_progress = AT_BITMAP_HEIGHT(bitmap) * AT_BITMAP_WIDTH(bitmap);
+
+ O_LIST_LENGTH(outline_list) = 0;
+ outline_list.data = NULL;
+
+ for (row = 0; row < AT_BITMAP_HEIGHT(bitmap); row++) {
+ for (col = 0; col < AT_BITMAP_WIDTH(bitmap); col++) {
+ edge_type edge;
+ at_color color;
+ gboolean is_background;
+
+ if (notify_progress)
+ notify_progress((gfloat) (row * AT_BITMAP_WIDTH(bitmap) + col) / ((gfloat) max_progress * (gfloat) 3.0), progress_data);
+
+ /* A valid edge can be TOP for an outside outline.
+ Outside outlines are traced counterclockwise */
+ at_bitmap_get_color(bitmap, row, col, &color);
+ if (!(is_background = (gboolean) (bg_color && at_color_equal(&color, bg_color)))
+ && is_unmarked_outline_edge(row, col, edge = TOP, bitmap, marked, color, exp)) {
+ pixel_outline_type outline;
+
+ CHECK_FATAL(); /* FREE(DONE) outline_list */
+
+ LOG("#%u: (counterclockwise)", O_LIST_LENGTH(outline_list));
+
+ outline = find_one_outline(bitmap, edge, row, col, marked, FALSE, FALSE, exp);
+ CHECK_FATAL(); /* FREE(DONE) outline_list */
+
+ O_CLOCKWISE(outline) = FALSE;
+ append_pixel_outline(&outline_list, outline);
+
+ LOG(" [%u].\n", O_LENGTH(outline));
+ } else
+ CHECK_FATAL(); /* FREE(DONE) outline_list */
+
+ /* A valid edge can be BOTTOM for an inside outline.
+ Inside outlines are traced clockwise */
+ if (row != 0) {
+ at_bitmap_get_color(bitmap, row - 1, col, &color);
+ if (!(bg_color && at_color_equal(&color, bg_color))
+ && is_unmarked_outline_edge(row - 1, col, edge = BOTTOM, bitmap, marked, color, exp)) {
+ pixel_outline_type outline;
+
+ CHECK_FATAL(); /* FREE(DONE) outline_list */
+
+ /* This lines are for debugging only: */
+ if (is_background) {
+ LOG("#%u: (clockwise)", O_LIST_LENGTH(outline_list));
+
+ outline = find_one_outline(bitmap, edge, row - 1, col, marked, TRUE, FALSE, exp);
+ CHECK_FATAL(); /* FREE(DONE) outline_list */
+
+ O_CLOCKWISE(outline) = TRUE;
+ append_pixel_outline(&outline_list, outline);
+
+ LOG(" [%u].\n", O_LENGTH(outline));
+ } else {
+ outline = find_one_outline(bitmap, edge, row - 1, col, marked, TRUE, TRUE, exp);
+ CHECK_FATAL(); /* FREE(DONE) outline_list */
+ }
+ } else
+ CHECK_FATAL(); /* FREE(DONE) outline_list */
+ }
+ if (test_cancel && test_cancel(testcancel_data)) {
+ free_pixel_outline_list(&outline_list);
+ goto cleanup;
+ }
+ }
+ }
+cleanup:
+ at_bitmap_free(marked);
+ if (at_exception_got_fatal(exp))
+ free_pixel_outline_list(&outline_list);
+ return outline_list;
+}
+
+/* We calculate one single outline here. We pass the position of the starting pixel and the
+ starting edge. All edges we track along will be marked and the outline pixels are appended
+ to the coordinate list. */
+
+static pixel_outline_type find_one_outline(at_bitmap * bitmap, edge_type original_edge, unsigned short original_row, unsigned short original_col, at_bitmap * marked, gboolean clockwise, gboolean ignore, at_exception_type * exp)
+{
+ pixel_outline_type outline;
+ unsigned short row = original_row, col = original_col;
+ edge_type edge = original_edge;
+ at_coord pos;
+
+ pos.x = col + ((edge == RIGHT) || (edge == BOTTOM) ? 1 : 0);
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - row - 1 + ((edge == TOP) || (edge == RIGHT) ? 1 : 0);
+
+ if (!ignore)
+ outline = new_pixel_outline();
+ at_bitmap_get_color(bitmap, row, col, &outline.color);
+
+ do {
+ /* Put this edge into the output list */
+ if (!ignore) {
+ LOG(" (%d,%d)", pos.x, pos.y);
+ append_outline_pixel(&outline, pos);
+ }
+
+ mark_edge(edge, row, col, marked);
+ pos = next_point(bitmap, &edge, &row, &col, outline.color, clockwise, marked, exp);
+ CHECK_FATAL();
+ }
+ while (edge != NO_EDGE);
+
+cleanup:
+ if (at_exception_got_fatal(exp))
+ free_pixel_outline(&outline);
+ return outline;
+}
+
+gboolean is_valid_dir(unsigned short row, unsigned short col, direction_type dir, at_bitmap * bitmap, at_bitmap * marked)
+{
+
+ at_color c;
+ int new_row = COMPUTE_DELTA(ROW, dir) + row;
+ int new_col = COMPUTE_DELTA(COL, dir) + col;
+
+ if ((new_row < 0) || (new_col < 0) || (new_row >= AT_BITMAP_HEIGHT(bitmap)) || (new_col >= AT_BITMAP_WIDTH(bitmap)))
+ return FALSE; // Must not call at_bitmap_get_color() with negative row or col.
+
+ at_bitmap_get_color(bitmap, COMPUTE_DELTA(ROW, dir) + row, COMPUTE_DELTA(COL, dir) + col, &c);
+ return ((gboolean) (!is_marked_dir(row, col, dir, marked)
+ && COMPUTE_DELTA(ROW, dir) + row > 0 && COMPUTE_DELTA(COL, dir) + col > 0 && AT_BITMAP_VALID_PIXEL(bitmap, COMPUTE_DELTA(ROW, dir) + row, COMPUTE_DELTA(COL, dir) + col)
+ && at_bitmap_equal_color(bitmap, row, col, &c)));
+}
+
+pixel_outline_list_type find_centerline_pixels(at_bitmap * bitmap, at_color bg_color, at_progress_func notify_progress, gpointer progress_data, at_testcancel_func test_cancel, gpointer testcancel_data, at_exception_type * exp)
+{
+ pixel_outline_list_type outline_list;
+ signed short row, col;
+ at_bitmap *marked = at_bitmap_new(AT_BITMAP_WIDTH(bitmap), AT_BITMAP_HEIGHT(bitmap), 1);
+ unsigned int max_progress = AT_BITMAP_HEIGHT(bitmap) * AT_BITMAP_WIDTH(bitmap);
+
+ O_LIST_LENGTH(outline_list) = 0;
+ outline_list.data = NULL;
+
+ for (row = 0; row < AT_BITMAP_HEIGHT(bitmap); row++) {
+ for (col = 0; col < AT_BITMAP_WIDTH(bitmap);) {
+ direction_type dir = EAST;
+ pixel_outline_type outline;
+ gboolean clockwise = FALSE;
+
+ if (notify_progress)
+ notify_progress((gfloat) (row * AT_BITMAP_WIDTH(bitmap) + col) / ((gfloat) max_progress * (gfloat) 3.0), progress_data);
+
+ if (at_bitmap_equal_color(bitmap, row, col, &bg_color)) {
+ col++;
+ continue;
+ }
+
+ if (!is_valid_dir(row, col, dir, bitmap, marked)
+ || (!is_valid_dir(COMPUTE_DELTA(ROW, dir) + row, COMPUTE_DELTA(COL, dir) + col, dir, bitmap, marked)
+ && num_neighbors(row, col, bitmap) > 2)
+ || num_neighbors(row, col, bitmap) > 4 || num_neighbors(COMPUTE_DELTA(ROW, dir) + row, COMPUTE_DELTA(COL, dir) + col, bitmap) > 4 || (is_other_dir_marked(row, col, dir, marked)
+ && is_other_dir_marked(row + COMPUTE_DELTA(ROW, dir), col + COMPUTE_DELTA(COL, dir), dir, marked))) {
+ dir = SOUTHEAST;
+ if (!is_valid_dir(row, col, dir, bitmap, marked)
+ || (!is_valid_dir(COMPUTE_DELTA(ROW, dir) + row, COMPUTE_DELTA(COL, dir) + col, dir, bitmap, marked)
+ && num_neighbors(row, col, bitmap) > 2)
+ || num_neighbors(row, col, bitmap) > 4 || num_neighbors(COMPUTE_DELTA(ROW, dir) + row, COMPUTE_DELTA(COL, dir) + col, bitmap) > 4 || (is_other_dir_marked(row, col, dir, marked)
+ && is_other_dir_marked(row + COMPUTE_DELTA(ROW, dir), col + COMPUTE_DELTA(COL, dir), dir, marked))) {
+ dir = SOUTH;
+ if (!is_valid_dir(row, col, dir, bitmap, marked)
+ || (!is_valid_dir(COMPUTE_DELTA(ROW, dir) + row, COMPUTE_DELTA(COL, dir) + col, dir, bitmap, marked)
+ && num_neighbors(row, col, bitmap) > 2)
+ || num_neighbors(row, col, bitmap) > 4 || num_neighbors(COMPUTE_DELTA(ROW, dir) + row, COMPUTE_DELTA(COL, dir) + col, bitmap) > 4 || (is_other_dir_marked(row, col, dir, marked)
+ && is_other_dir_marked(row + COMPUTE_DELTA(ROW, dir), col + COMPUTE_DELTA(COL, dir), dir, marked))) {
+ dir = SOUTHWEST;
+ if (!is_valid_dir(row, col, dir, bitmap, marked)
+ || (!is_valid_dir(COMPUTE_DELTA(ROW, dir) + row, COMPUTE_DELTA(COL, dir) + col, dir, bitmap, marked)
+ && num_neighbors(row, col, bitmap) > 2)
+ || num_neighbors(row, col, bitmap) > 4 || num_neighbors(COMPUTE_DELTA(ROW, dir) + row, COMPUTE_DELTA(COL, dir) + col, bitmap) > 4 || (is_other_dir_marked(row, col, dir, marked)
+ && is_other_dir_marked(row + COMPUTE_DELTA(ROW, dir), col + COMPUTE_DELTA(COL, dir), dir, marked))) {
+ col++;
+ continue;
+ }
+ }
+ }
+ }
+
+ LOG("#%u: (%sclockwise) ", O_LIST_LENGTH(outline_list), clockwise ? "" : "counter");
+
+ outline = find_one_centerline(bitmap, dir, row, col, marked);
+
+ /* If the outline is open (i.e., we didn't return to the
+ starting pixel), search from the starting pixel in the
+ opposite direction and concatenate the two outlines. */
+
+ if (outline.open) {
+ pixel_outline_type partial_outline;
+ gboolean okay = FALSE;
+
+ if (dir == EAST) {
+ dir = SOUTH;
+ if (!(okay = is_valid_dir(row, col, dir, bitmap, marked))) {
+ dir = SOUTHWEST;
+ if (!(okay = is_valid_dir(row, col, dir, bitmap, marked))) {
+ dir = SOUTHEAST;
+ okay = is_valid_dir(row, col, dir, bitmap, marked);
+ }
+ }
+ } else if (dir == SOUTHEAST) {
+ dir = SOUTHWEST;
+ if (!(okay = is_valid_dir(row, col, dir, bitmap, marked))) {
+ dir = EAST;
+ if (!(okay = is_valid_dir(row, col, dir, bitmap, marked))) {
+ dir = SOUTH;
+ okay = is_valid_dir(row, col, dir, bitmap, marked);
+ }
+ }
+ } else if (dir == SOUTH) {
+ dir = EAST;
+ if (!(okay = is_valid_dir(row, col, dir, bitmap, marked))) {
+ dir = SOUTHEAST;
+ if (!(okay = is_valid_dir(row, col, dir, bitmap, marked))) {
+ dir = SOUTHWEST;
+ okay = is_valid_dir(row, col, dir, bitmap, marked);
+ }
+ }
+ } else if (dir == SOUTHWEST) {
+ dir = SOUTHEAST;
+ if (!(okay = is_valid_dir(row, col, dir, bitmap, marked))) {
+ dir = EAST;
+ if (!(okay = is_valid_dir(row, col, dir, bitmap, marked))) {
+ dir = SOUTH;
+ okay = is_valid_dir(row, col, dir, bitmap, marked);
+ }
+ }
+ }
+ if (okay) {
+ partial_outline = find_one_centerline(bitmap, dir, row, col, marked);
+ concat_pixel_outline(&outline, &partial_outline);
+ if (partial_outline.data)
+ free(partial_outline.data);
+ } else
+ col++;
+ }
+
+ /* Outside outlines will start at a top edge, and move
+ counterclockwise, and inside outlines will start at a
+ bottom edge, and move clockwise. This happens because of
+ the order in which we look at the edges. */
+ O_CLOCKWISE(outline) = clockwise;
+ if (O_LENGTH(outline) > 1)
+ append_pixel_outline(&outline_list, outline);
+ LOG("(%s)", (outline.open ? " open" : " closed"));
+ LOG(" [%u].\n", O_LENGTH(outline));
+ if (O_LENGTH(outline) == 1)
+ free_pixel_outline(&outline);
+ }
+ }
+ if (test_cancel && test_cancel(testcancel_data)) {
+ if (O_LIST_LENGTH(outline_list) != 0)
+ free_pixel_outline_list(&outline_list);
+ goto cleanup;
+ }
+cleanup:
+ at_bitmap_free(marked);
+ return outline_list;
+}
+
+static pixel_outline_type find_one_centerline(at_bitmap * bitmap, direction_type search_dir, unsigned short original_row, unsigned short original_col, at_bitmap * marked)
+{
+ pixel_outline_type outline = new_pixel_outline();
+ direction_type original_dir = search_dir;
+ unsigned short row = original_row, col = original_col;
+ unsigned short prev_row, prev_col;
+ at_coord pos;
+
+ outline.open = FALSE;
+ at_bitmap_get_color(bitmap, row, col, &outline.color);
+
+ /* Add the starting pixel to the output list, changing from bitmap
+ to Cartesian coordinates and specifying the left edge so that
+ the coordinates won't be adjusted. */
+ pos.x = col;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - row - 1;
+ LOG(" (%d,%d)", pos.x, pos.y);
+ append_outline_pixel(&outline, pos);
+
+ for (;;) {
+ prev_row = row;
+ prev_col = col;
+
+ /* If there is no adjacent, unmarked pixel, we can't proceed
+ any further, so return an open outline. */
+ if (!next_unmarked_pixel(&row, &col, &search_dir, bitmap, marked)) {
+ outline.open = TRUE;
+ break;
+ }
+
+ /* If we've moved to a new pixel, mark all edges of the previous
+ pixel so that it won't be revisited. */
+ if (!(prev_row == original_row && prev_col == original_col))
+ mark_dir(prev_row, prev_col, search_dir, marked);
+ mark_dir(row, col, (direction_type) ((search_dir + 4) % 8), marked);
+
+ /* If we've returned to the starting pixel, we're done. */
+ if (row == original_row && col == original_col)
+ break;
+
+ /* Add the new pixel to the output list. */
+ pos.x = col;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - row - 1;
+ LOG(" (%d,%d)", pos.x, pos.y);
+ append_outline_pixel(&outline, pos);
+ }
+ mark_dir(original_row, original_col, original_dir, marked);
+ return outline;
+}
+
+/* Add an outline to an outline list. */
+
+static void append_pixel_outline(pixel_outline_list_type * outline_list, pixel_outline_type outline)
+{
+ O_LIST_LENGTH(*outline_list)++;
+ XREALLOC(outline_list->data, outline_list->length * sizeof(pixel_outline_type));
+ O_LIST_OUTLINE(*outline_list, O_LIST_LENGTH(*outline_list) - 1) = outline;
+}
+
+/* Free the list of outline lists. */
+
+void free_pixel_outline_list(pixel_outline_list_type * outline_list)
+{
+ unsigned this_outline;
+
+ for (this_outline = 0; this_outline < outline_list->length; this_outline++) {
+ pixel_outline_type o = outline_list->data[this_outline];
+ free_pixel_outline(&o);
+ }
+ free(outline_list->data);
+ outline_list->data = NULL;
+ outline_list->length = 0;
+}
+
+/* Return an empty list of pixels. */
+
+static pixel_outline_type new_pixel_outline(void)
+{
+ pixel_outline_type pixel_outline;
+
+ O_LENGTH(pixel_outline) = 0;
+ pixel_outline.data = NULL;
+ pixel_outline.open = FALSE;
+
+ return pixel_outline;
+}
+
+static void free_pixel_outline(pixel_outline_type * outline)
+{
+ free(outline->data);
+ outline->data = NULL;
+ outline->length = 0;
+}
+
+/* Concatenate two pixel lists. The two lists are assumed to have the
+ same starting pixel and to proceed in opposite directions therefrom. */
+
+static void concat_pixel_outline(pixel_outline_type * o1, const pixel_outline_type * o2)
+{
+ int src, dst;
+ unsigned o1_length, o2_length;
+ if (!o1 || !o2 || O_LENGTH(*o2) <= 1)
+ return;
+
+ o1_length = O_LENGTH(*o1);
+ o2_length = O_LENGTH(*o2);
+ O_LENGTH(*o1) += o2_length - 1;
+ /* Resize o1 to the sum of the lengths of o1 and o2 minus one (because
+ the two lists are assumed to share the same starting pixel). */
+ XREALLOC(o1->data, O_LENGTH(*o1) * sizeof(at_coord));
+ /* Shift the contents of o1 to the end of the new array to make room
+ to prepend o2. */
+ for (src = o1_length - 1, dst = O_LENGTH(*o1) - 1; src >= 0; src--, dst--)
+ O_COORDINATE(*o1, dst) = O_COORDINATE(*o1, src);
+ /* Prepend the contents of o2 (in reverse order) to o1. */
+ for (src = o2_length - 1, dst = 0; src > 0; src--, dst++)
+ O_COORDINATE(*o1, dst) = O_COORDINATE(*o2, src);
+}
+
+/* Add a point to the pixel list. */
+
+static void append_outline_pixel(pixel_outline_type * o, at_coord c)
+{
+ O_LENGTH(*o)++;
+ XREALLOC(o->data, O_LENGTH(*o) * sizeof(at_coord));
+ O_COORDINATE(*o, O_LENGTH(*o) - 1) = c;
+}
+
+/* Is this really an edge and is it still unmarked? */
+
+static gboolean is_unmarked_outline_edge(unsigned short row, unsigned short col, edge_type edge, at_bitmap * bitmap, at_bitmap * marked, at_color color, at_exception_type * exp)
+{
+ return (gboolean) (!is_marked_edge(edge, row, col, marked)
+ && is_outline_edge(edge, bitmap, row, col, color, exp));
+}
+
+/* We check to see if the edge of the pixel at position ROW and COL
+ is an outline edge */
+
+static gboolean is_outline_edge(edge_type edge, at_bitmap * bitmap, unsigned short row, unsigned short col, at_color color, at_exception_type * exp)
+{
+ /* If this pixel isn't of the same color, it's not part of the outline. */
+ if (!at_bitmap_equal_color(bitmap, row, col, &color))
+ return FALSE;
+
+ switch (edge) {
+ case LEFT:
+ return (gboolean) (col == 0 || !at_bitmap_equal_color(bitmap, row, col - 1, &color));
+ case TOP:
+ return (gboolean) (row == 0 || !at_bitmap_equal_color(bitmap, row - 1, col, &color));
+
+ case RIGHT:
+ return (gboolean) (col == AT_BITMAP_WIDTH(bitmap) - 1 || !at_bitmap_equal_color(bitmap, row, col + 1, &color));
+
+ case BOTTOM:
+ return (gboolean) (row == AT_BITMAP_HEIGHT(bitmap) - 1 || !at_bitmap_equal_color(bitmap, row + 1, col, &color));
+
+ case NO_EDGE:
+ g_assert_not_reached();
+ default:
+ g_assert_not_reached();
+ }
+ return FALSE; /* NOT REACHED */
+}
+
+/* If EDGE is not already marked, we mark it; otherwise, it's a fatal error.
+ The position ROW and COL should be inside the bitmap MARKED. EDGE can be
+ NO_EDGE. */
+
+static void mark_edge(edge_type edge, unsigned short row, unsigned short col, at_bitmap * marked)
+{
+ *AT_BITMAP_PIXEL(marked, row, col) |= 1 << edge;
+}
+
+/* Mark the direction of the pixel ROW/COL in MARKED. */
+
+static void mark_dir(unsigned short row, unsigned short col, direction_type dir, at_bitmap * marked)
+{
+ *AT_BITMAP_PIXEL(marked, row, col) |= 1 << dir;
+}
+
+/* Test if the direction of pixel at ROW/COL in MARKED is marked. */
+
+static gboolean is_marked_dir(unsigned short row, unsigned short col, direction_type dir, at_bitmap * marked)
+{
+ return (gboolean) ((*AT_BITMAP_PIXEL(marked, row, col) & 1 << dir) != 0);
+}
+
+static gboolean is_other_dir_marked(unsigned short row, unsigned short col, direction_type dir, at_bitmap * marked)
+{
+ return (gboolean) ((*AT_BITMAP_PIXEL(marked, row, col) & (255 - (1 << dir) - (1 << ((dir + 4) % 8)))) != 0);
+}
+
+static gboolean next_unmarked_pixel(unsigned short *row, unsigned short *col, direction_type * dir, at_bitmap * bitmap, at_bitmap * marked)
+{
+ unsigned short orig_row = *row, orig_col = *col;
+ direction_type orig_dir = *dir, test_dir = *dir;
+
+ do {
+ if (is_valid_dir(orig_row, orig_col, test_dir, bitmap, marked)) {
+ *row = orig_row + COMPUTE_DELTA(ROW, test_dir);
+ *col = orig_col + COMPUTE_DELTA(COL, test_dir);
+ *dir = test_dir;
+ break;
+ }
+
+ if (orig_dir == test_dir)
+ test_dir = (direction_type) ((orig_dir + 2) % 8);
+ else if ((orig_dir + 2) % 8 == test_dir)
+ test_dir = (direction_type) ((orig_dir + 6) % 8);
+ else if ((orig_dir + 6) % 8 == test_dir)
+ test_dir = (direction_type) ((orig_dir + 1) % 8);
+ else if ((orig_dir + 1) % 8 == test_dir)
+ test_dir = (direction_type) ((orig_dir + 7) % 8);
+ else if ((orig_dir + 7) % 8 == test_dir)
+ test_dir = (direction_type) ((orig_dir + 3) % 8);
+ else if ((orig_dir + 3) % 8 == test_dir)
+ test_dir = (direction_type) ((orig_dir + 5) % 8);
+ else if ((orig_dir + 5) % 8 == test_dir)
+ break;
+ }
+ while (1);
+ if ((*row != orig_row || *col != orig_col) && (!(is_other_dir_marked(orig_row, orig_col, test_dir, marked)
+ && is_other_dir_marked(orig_row + COMPUTE_DELTA(ROW, test_dir), orig_col + COMPUTE_DELTA(COL, test_dir), test_dir, marked))))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* Return the number of pixels adjacent to pixel ROW/COL that are black. */
+
+static unsigned num_neighbors(unsigned short row, unsigned short col, at_bitmap * bitmap)
+{
+ unsigned dir, count = 0;
+ at_color color;
+
+ at_bitmap_get_color(bitmap, row, col, &color);
+ for (dir = NORTH; dir <= NORTHEAST; dir++) {
+ int delta_r = COMPUTE_DELTA(ROW, dir);
+ int delta_c = COMPUTE_DELTA(COL, dir);
+ unsigned int test_row = row + delta_r;
+ unsigned int test_col = col + delta_c;
+ if (AT_BITMAP_VALID_PIXEL(bitmap, test_row, test_col)
+ && at_bitmap_equal_color(bitmap, test_row, test_col, &color))
+ ++count;
+ }
+ return count;
+}
+
+/* Test if the edge EDGE at ROW/COL in MARKED is marked. */
+
+static gboolean is_marked_edge(edge_type edge, unsigned short row, unsigned short col, at_bitmap * marked)
+{
+ return (gboolean) (edge == NO_EDGE ? FALSE : (*AT_BITMAP_PIXEL(marked, row, col) & (1 << edge)) != 0);
+}
+
+static at_coord next_point(at_bitmap * bitmap, edge_type * edge, unsigned short *row, unsigned short *col, at_color color, gboolean clockwise, at_bitmap * marked, at_exception_type * exp)
+{
+ at_coord pos = { 0, 0 };
+
+ if (!clockwise)
+ switch (*edge) {
+ case TOP:
+ /* WEST */
+ if ((*col >= 1 && !is_marked_edge(TOP, *row, *col - 1, marked)
+ && is_outline_edge(TOP, bitmap, *row, *col - 1, color, exp))) {
+ /**edge = TOP;*/
+ (*col)--;
+ pos.x = *col;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row;
+ break;
+ }
+ CHECK_FATAL();
+ /* NORTHWEST */
+ if ((*col >= 1 && *row >= 1 && !is_marked_edge(RIGHT, *row - 1, *col - 1, marked)
+ && is_outline_edge(RIGHT, bitmap, *row - 1, *col - 1, color, exp)) && !(is_marked_edge(LEFT, *row - 1, *col, marked) && is_marked_edge(TOP, *row, *col - 1, marked)) && !(is_marked_edge(BOTTOM, *row - 1, *col, marked) && is_marked_edge(RIGHT, *row, *col - 1, marked))) {
+ *edge = RIGHT;
+ (*col)--;
+ (*row)--;
+ pos.x = *col + 1;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row;
+ break;
+ }
+ CHECK_FATAL();
+ if ((!is_marked_edge(LEFT, *row, *col, marked)
+ && is_outline_edge(LEFT, bitmap, *row, *col, color, exp))) {
+ *edge = LEFT;
+ pos.x = *col;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row - 1;
+ break;
+ }
+ CHECK_FATAL();
+ *edge = NO_EDGE;
+ break;
+ case RIGHT:
+ /* NORTH */
+ if ((*row >= 1 && !is_marked_edge(RIGHT, *row - 1, *col, marked)
+ && is_outline_edge(RIGHT, bitmap, *row - 1, *col, color, exp))) {
+ /**edge = RIGHT;*/
+ (*row)--;
+ pos.x = *col + 1;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row;
+ break;
+ }
+ CHECK_FATAL();
+ /* NORTHEAST */
+ if ((*col + 1 < AT_BITMAP_WIDTH(marked) && *row >= 1 && !is_marked_edge(BOTTOM, *row - 1, *col + 1, marked)
+ && is_outline_edge(BOTTOM, bitmap, *row - 1, *col + 1, color, exp)) && !(is_marked_edge(LEFT, *row, *col + 1, marked) && is_marked_edge(BOTTOM, *row - 1, *col, marked)) && !(is_marked_edge(TOP, *row, *col + 1, marked) && is_marked_edge(RIGHT, *row - 1, *col, marked))) {
+ *edge = BOTTOM;
+ (*col)++;
+ (*row)--;
+ pos.x = *col + 1;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row - 1;
+ break;
+ }
+ CHECK_FATAL();
+ if ((!is_marked_edge(TOP, *row, *col, marked)
+ && is_outline_edge(TOP, bitmap, *row, *col, color, exp))) {
+ *edge = TOP;
+ pos.x = *col;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row;
+ break;
+ }
+ CHECK_FATAL();
+ *edge = NO_EDGE;
+ break;
+ case BOTTOM:
+ /* EAST */
+ if ((*col + 1 < AT_BITMAP_WIDTH(marked)
+ && !is_marked_edge(BOTTOM, *row, *col + 1, marked)
+ && is_outline_edge(BOTTOM, bitmap, *row, *col + 1, color, exp))) {
+ /**edge = BOTTOM;*/
+ (*col)++;
+ pos.x = *col + 1;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row - 1;
+ break;
+ }
+ CHECK_FATAL();
+ /* SOUTHEAST */
+ if ((*col + 1 < AT_BITMAP_WIDTH(marked) && *row + 1 < AT_BITMAP_HEIGHT(marked)
+ && !is_marked_edge(LEFT, *row + 1, *col + 1, marked)
+ && is_outline_edge(LEFT, bitmap, *row + 1, *col + 1, color, exp)) && !(is_marked_edge(TOP, *row + 1, *col, marked) && is_marked_edge(LEFT, *row, *col + 1, marked)) && !(is_marked_edge(RIGHT, *row + 1, *col, marked) && is_marked_edge(BOTTOM, *row, *col + 1, marked))) {
+ *edge = LEFT;
+ (*col)++;
+ (*row)++;
+ pos.x = *col;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row - 1;
+ break;
+ }
+ CHECK_FATAL();
+ if ((!is_marked_edge(RIGHT, *row, *col, marked)
+ && is_outline_edge(RIGHT, bitmap, *row, *col, color, exp))) {
+ *edge = RIGHT;
+ pos.x = *col + 1;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row;
+ break;
+ }
+ CHECK_FATAL();
+ *edge = NO_EDGE;
+ break;
+ case LEFT:
+ /* SOUTH */
+ if ((*row + 1 < AT_BITMAP_HEIGHT(marked)
+ && !is_marked_edge(LEFT, *row + 1, *col, marked)
+ && is_outline_edge(LEFT, bitmap, *row + 1, *col, color, exp))) {
+ /**edge = LEFT;*/
+ (*row)++;
+ pos.x = *col;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row - 1;
+ break;
+ }
+ CHECK_FATAL();
+ /* SOUTHWEST */
+ if ((*col >= 1 && *row + 1 < AT_BITMAP_HEIGHT(marked)
+ && !is_marked_edge(TOP, *row + 1, *col - 1, marked)
+ && is_outline_edge(TOP, bitmap, *row + 1, *col - 1, color, exp)) && !(is_marked_edge(RIGHT, *row, *col - 1, marked) && is_marked_edge(TOP, *row + 1, *col, marked)) && !(is_marked_edge(BOTTOM, *row, *col - 1, marked) && is_marked_edge(LEFT, *row + 1, *col, marked))) {
+ *edge = TOP;
+ (*col)--;
+ (*row)++;
+ pos.x = *col;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row;
+ break;
+ }
+ CHECK_FATAL();
+ if ((!is_marked_edge(BOTTOM, *row, *col, marked)
+ && is_outline_edge(BOTTOM, bitmap, *row, *col, color, exp))) {
+ *edge = BOTTOM;
+ pos.x = *col + 1;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row - 1;
+ break;
+ }
+ CHECK_FATAL();
+ case NO_EDGE:
+ default:
+ *edge = NO_EDGE;
+ break;
+ } else
+ switch (*edge) {
+ case TOP:
+ if ((!is_marked_edge(LEFT, *row, *col, marked)
+ && is_outline_edge(LEFT, bitmap, *row, *col, color, exp))) {
+ *edge = LEFT;
+ pos.x = *col;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row - 1;
+ break;
+ }
+ CHECK_FATAL();
+ /* WEST */
+ if ((*col >= 1 && !is_marked_edge(TOP, *row, *col - 1, marked)
+ && is_outline_edge(TOP, bitmap, *row, *col - 1, color, exp))) {
+ /**edge = TOP;*/
+ (*col)--;
+ pos.x = *col;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row;
+ break;
+ }
+ CHECK_FATAL();
+ /* NORTHWEST */
+ if ((*col >= 1 && *row >= 1 && !is_marked_edge(RIGHT, *row - 1, *col - 1, marked)
+ && is_outline_edge(RIGHT, bitmap, *row - 1, *col - 1, color, exp))) {
+ *edge = RIGHT;
+ (*col)--;
+ (*row)--;
+ pos.x = *col + 1;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row;
+ break;
+ }
+ CHECK_FATAL();
+ *edge = NO_EDGE;
+ break;
+ case RIGHT:
+ if ((!is_marked_edge(TOP, *row, *col, marked)
+ && is_outline_edge(TOP, bitmap, *row, *col, color, exp))) {
+ *edge = TOP;
+ pos.x = *col;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row;
+ break;
+ }
+ CHECK_FATAL();
+ /* NORTH */
+ if ((*row >= 1 && !is_marked_edge(RIGHT, *row - 1, *col, marked)
+ && is_outline_edge(RIGHT, bitmap, *row - 1, *col, color, exp))) {
+ /**edge = RIGHT;*/
+ (*row)--;
+ pos.x = *col + 1;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row;
+ break;
+ }
+ CHECK_FATAL();
+ /* NORTHEAST */
+ if ((*col + 1 < AT_BITMAP_WIDTH(marked) && *row >= 1 && !is_marked_edge(BOTTOM, *row - 1, *col + 1, marked)
+ && is_outline_edge(BOTTOM, bitmap, *row - 1, *col + 1, color, exp))) {
+ *edge = BOTTOM;
+ (*col)++;
+ (*row)--;
+ pos.x = *col + 1;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row - 1;
+ break;
+ }
+ CHECK_FATAL();
+ *edge = NO_EDGE;
+ break;
+ case BOTTOM:
+ if ((!is_marked_edge(RIGHT, *row, *col, marked)
+ && is_outline_edge(RIGHT, bitmap, *row, *col, color, exp))) {
+ *edge = RIGHT;
+ pos.x = *col + 1;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row;
+ break;
+ }
+ CHECK_FATAL();
+ /* EAST */
+ if ((*col + 1 < AT_BITMAP_WIDTH(marked)
+ && !is_marked_edge(BOTTOM, *row, *col + 1, marked)
+ && is_outline_edge(BOTTOM, bitmap, *row, *col + 1, color, exp))) {
+ /**edge = BOTTOM;*/
+ (*col)++;
+ pos.x = *col + 1;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row - 1;
+ break;
+ }
+ CHECK_FATAL();
+ /* SOUTHEAST */
+ if ((*col + 1 < AT_BITMAP_WIDTH(marked) && *row + 1 < AT_BITMAP_HEIGHT(marked)
+ && !is_marked_edge(LEFT, *row + 1, *col + 1, marked)
+ && is_outline_edge(LEFT, bitmap, *row + 1, *col + 1, color, exp))) {
+ *edge = LEFT;
+ (*col)++;
+ (*row)++;
+ pos.x = *col;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row - 1;
+ break;
+ }
+ CHECK_FATAL();
+ *edge = NO_EDGE;
+ break;
+ case LEFT:
+ if ((!is_marked_edge(BOTTOM, *row, *col, marked)
+ && is_outline_edge(BOTTOM, bitmap, *row, *col, color, exp))) {
+ *edge = BOTTOM;
+ pos.x = *col + 1;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row - 1;
+ break;
+ }
+ CHECK_FATAL();
+ /* SOUTH */
+ if ((*row + 1 < AT_BITMAP_HEIGHT(marked)
+ && !is_marked_edge(LEFT, *row + 1, *col, marked)
+ && is_outline_edge(LEFT, bitmap, *row + 1, *col, color, exp))) {
+ /**edge = LEFT;*/
+ (*row)++;
+ pos.x = *col;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row - 1;
+ break;
+ }
+ CHECK_FATAL();
+ /* SOUTHWEST */
+ if ((*col >= 1 && *row + 1 < AT_BITMAP_HEIGHT(marked)
+ && !is_marked_edge(TOP, *row + 1, *col - 1, marked)
+ && is_outline_edge(TOP, bitmap, *row + 1, *col - 1, color, exp))) {
+ *edge = TOP;
+ (*col)--;
+ (*row)++;
+ pos.x = *col;
+ pos.y = AT_BITMAP_HEIGHT(bitmap) - *row;
+ break;
+ }
+ CHECK_FATAL();
+ case NO_EDGE:
+ default:
+ *edge = NO_EDGE;
+ break;
+ }
+cleanup:
+ return (pos);
+}
diff --git a/src/3rdparty/autotrace/pxl-outline.h b/src/3rdparty/autotrace/pxl-outline.h
new file mode 100644
index 0000000..e00d802
--- /dev/null
+++ b/src/3rdparty/autotrace/pxl-outline.h
@@ -0,0 +1,58 @@
+/* pxl-outline.h: find a list of outlines which make up one character. */
+
+#ifndef PXL_OUTLINE_H
+#define PXL_OUTLINE_H
+
+#include "autotrace.h"
+#include "exception.h"
+#include "bitmap.h"
+#include "color.h"
+
+/* This is a list of contiguous points on the bitmap. */
+typedef struct {
+ at_coord *data;
+ unsigned length;
+ gboolean clockwise;
+ at_color color;
+ gboolean open;
+} pixel_outline_type;
+
+/* The Nth coordinate in the list. */
+#define O_COORDINATE(p_o, n) ((p_o).data[n])
+
+/* The length of the list. */
+#define O_LENGTH(p_o) ((p_o).length)
+
+/* Whether the outline moves clockwise or counterclockwise. */
+#define O_CLOCKWISE(p_o) ((p_o).clockwise)
+
+/* Since a pixel outline is cyclic, the index of the next coordinate
+ after the last is the first, and the previous coordinate before the
+ first is the last. */
+#define O_NEXT(p_o, n) (((n) + 1) % O_LENGTH (p_o))
+#define O_PREV(p_o, n) ((n) == 0 \
+ ? O_LENGTH (p_o) - 1 \
+ : (n) - 1)
+
+/* And the character turns into a list of such lists. */
+typedef struct {
+ pixel_outline_type *data;
+ unsigned length;
+} pixel_outline_list_type;
+
+/* The Nth list in the list of lists. */
+#define O_LIST_OUTLINE(p_o_l, n) ((p_o_l).data[n])
+
+/* The length of the list of lists. */
+#define O_LIST_LENGTH(p_o_l) ((p_o_l).length)
+
+/* Find all pixels on the outline in the character C. */
+extern pixel_outline_list_type find_outline_pixels(at_bitmap * bitmap, at_color * bg_color, at_progress_func notify_progress, gpointer progress_data, at_testcancel_func test_cancel, gpointer testcancel_data, at_exception_type * exp);
+
+/* Find all pixels on the center line of the character C. */
+extern pixel_outline_list_type find_centerline_pixels(at_bitmap * bitmap, at_color bg_color, at_progress_func notify_progress, gpointer progress_data, at_testcancel_func test_cancel, gpointer testcancel_data, at_exception_type * exp);
+
+/* Free the memory in the list. */
+extern void free_pixel_outline_list(pixel_outline_list_type *);
+
+#endif /* not PXL_OUTLINE_H */
diff --git a/src/3rdparty/autotrace/quantize.h b/src/3rdparty/autotrace/quantize.h
new file mode 100644
index 0000000..3e62c2e
--- /dev/null
+++ b/src/3rdparty/autotrace/quantize.h
@@ -0,0 +1,52 @@
+/* quantize.h: Quantize a high color bitmap
+
+ Copyright (C) 2001, 2002 Martin Weber
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License
+ as published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA. */
+
+#include "bitmap.h"
+#include "color.h"
+#include "exception.h"
+
+#ifndef QUANTIZE_H
+#define QUANTIZE_H
+
+#define PRECISION_R 7
+#define PRECISION_G 7
+#define PRECISION_B 7
+
+#define HIST_R_ELEMS (1<<PRECISION_R)
+#define HIST_G_ELEMS (1<<PRECISION_G)
+#define HIST_B_ELEMS (1<<PRECISION_B)
+
+#define MR HIST_G_ELEMS*HIST_B_ELEMS
+#define MG HIST_B_ELEMS
+
+typedef unsigned long ColorFreq;
+typedef ColorFreq *Histogram;
+
+typedef struct {
+ int desired_number_of_colors; /* Number of colors we will allow */
+ int actual_number_of_colors; /* Number of colors actually needed */
+ at_color cmap[256]; /* colormap created by quantization */
+ ColorFreq freq[256];
+ Histogram histogram; /* holds the histogram */
+} QuantizeObj;
+
+void quantize(at_bitmap *, long ncolors, const at_color * bgColor, QuantizeObj **, at_exception_type * exp);
+
+void quantize_object_free(QuantizeObj * obj);
+#endif /* NOT QUANTIZE_H */
diff --git a/src/3rdparty/autotrace/spline.c b/src/3rdparty/autotrace/spline.c
new file mode 100644
index 0000000..3aa0f73
--- /dev/null
+++ b/src/3rdparty/autotrace/spline.c
@@ -0,0 +1,160 @@
+/* spline.c: spline and spline list (represented as arrays) manipulation. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* Def: HAVE_CONFIG_H */
+
+#include "logreport.h"
+#include "types.h"
+#include "spline.h"
+#include "vector.h"
+#include "xstd.h"
+#include <assert.h>
+
+/* Print a spline in human-readable form. */
+
+void print_spline(spline_type s)
+{
+ assert(SPLINE_DEGREE(s) == LINEARTYPE || SPLINE_DEGREE(s) == CUBICTYPE);
+
+ if (SPLINE_DEGREE(s) == LINEARTYPE)
+ fprintf(stdout, "(%.3f,%.3f)--(%.3f,%.3f).\n", START_POINT(s).x, START_POINT(s).y, END_POINT(s).x, END_POINT(s).y);
+
+ else if (SPLINE_DEGREE(s) == CUBICTYPE)
+ fprintf(stdout, "(%.3f,%.3f)..ctrls(%.3f,%.3f)&(%.3f,%.3f)..(%.3f,%.3f).\n", START_POINT(s).x, START_POINT(s).y, CONTROL1(s).x, CONTROL1(s).y, CONTROL2(s).x, CONTROL2(s).y, END_POINT(s).x, END_POINT(s).y);
+}
+
+/* Evaluate the spline S at a given T value. This is an implementation
+ of de Casteljau's algorithm. See Schneider's thesis, p.37.
+ The variable names are taken from there. */
+
+at_real_coord evaluate_spline(spline_type s, gfloat t)
+{
+ spline_type V[4]; /* We need degree+1 splines, but assert degree <= 3. */
+ signed i, j;
+ gfloat one_minus_t = (gfloat) 1.0 - t;
+ polynomial_degree degree = SPLINE_DEGREE(s);
+
+ for (i = 0; i <= degree; i++) {
+ V[0].v[i].x = s.v[i].x;
+ V[0].v[i].y = s.v[i].y;
+ V[0].v[i].z = s.v[i].z;
+ }
+
+ for (j = 1; j <= degree; j++)
+ for (i = 0; i <= degree - j; i++) {
+ at_real_coord t1 = Pmult_scalar(V[j - 1].v[i], one_minus_t);
+ at_real_coord t2 = Pmult_scalar(V[j - 1].v[i + 1], t);
+ at_real_coord temp = Padd(t1, t2);
+ V[j].v[i].x = temp.x;
+ V[j].v[i].y = temp.y;
+ V[j].v[i].z = temp.z;
+ }
+
+ return V[degree].v[0];
+}
+
+/* Return a new, empty, spline list. */
+
+spline_list_type *new_spline_list(void)
+{
+ spline_list_type *answer;
+
+ XMALLOC(answer, sizeof(spline_list_type));
+ *answer = empty_spline_list();
+ return answer;
+}
+
+spline_list_type empty_spline_list(void)
+{
+ spline_list_type answer;
+ SPLINE_LIST_DATA(answer) = NULL;
+ SPLINE_LIST_LENGTH(answer) = 0;
+ return answer;
+}
+
+/* Return a new spline list with SPLINE as the first element. */
+
+spline_list_type *new_spline_list_with_spline(spline_type spline)
+{
+ spline_list_type *answer;
+
+ answer = new_spline_list();
+ XMALLOC(SPLINE_LIST_DATA(*answer), sizeof(spline_type));
+ SPLINE_LIST_ELT(*answer, 0) = spline;
+ SPLINE_LIST_LENGTH(*answer) = 1;
+
+ return answer;
+}
+
+/* Free the storage in a spline list. We don't have to free the
+ elements, since they are arrays in automatic storage. And we don't
+ want to free the list if it was empty. */
+
+void free_spline_list(spline_list_type spline_list)
+{
+ free(SPLINE_LIST_DATA(spline_list));
+}
+
+/* Append the spline S to the list SPLINE_LIST. */
+
+void append_spline(spline_list_type * l, spline_type s)
+{
+ assert(l != NULL);
+
+ SPLINE_LIST_LENGTH(*l)++;
+ XREALLOC(SPLINE_LIST_DATA(*l), SPLINE_LIST_LENGTH(*l) * sizeof(spline_type));
+ LAST_SPLINE_LIST_ELT(*l) = s;
+}
+
+/* Tack the elements in the list S2 onto the end of S1.
+ S2 is not changed. */
+
+void concat_spline_lists(spline_list_type * s1, spline_list_type s2)
+{
+ unsigned this_spline;
+ unsigned new_length;
+
+ assert(s1 != NULL);
+
+ new_length = SPLINE_LIST_LENGTH(*s1) + SPLINE_LIST_LENGTH(s2);
+
+ XREALLOC(SPLINE_LIST_DATA(*s1), new_length * sizeof(spline_type));
+
+ for (this_spline = 0; this_spline < SPLINE_LIST_LENGTH(s2); this_spline++)
+ SPLINE_LIST_ELT(*s1, SPLINE_LIST_LENGTH(*s1)++)
+ = SPLINE_LIST_ELT(s2, this_spline);
+}
+
+/* Return a new, empty, spline list array. */
+
+spline_list_array_type new_spline_list_array(void)
+{
+ spline_list_array_type answer;
+
+ SPLINE_LIST_ARRAY_DATA(answer) = NULL;
+ SPLINE_LIST_ARRAY_LENGTH(answer) = 0;
+
+ return answer;
+}
+
+/* Free the storage in a spline list array. We don't
+ want to free the list if it is empty. */
+void free_spline_list_array(spline_list_array_type * spline_list_array)
+{
+ unsigned this_list;
+
+ for (this_list = 0; this_list < SPLINE_LIST_ARRAY_LENGTH(*spline_list_array); this_list++)
+ free_spline_list(SPLINE_LIST_ARRAY_ELT(*spline_list_array, this_list));
+
+ free(SPLINE_LIST_ARRAY_DATA(*spline_list_array));
+}
+
+/* Append the spline S to the list SPLINE_LIST_ARRAY. */
+
+void append_spline_list(spline_list_array_type * l, spline_list_type s)
+{
+ SPLINE_LIST_ARRAY_LENGTH(*l)++;
+ XREALLOC(SPLINE_LIST_ARRAY_DATA(*l), SPLINE_LIST_ARRAY_LENGTH(*l) * sizeof(spline_list_type));
+ LAST_SPLINE_LIST_ARRAY_ELT(*l) = s;
+}
diff --git a/src/3rdparty/autotrace/spline.h b/src/3rdparty/autotrace/spline.h
new file mode 100644
index 0000000..6cbd143
--- /dev/null
+++ b/src/3rdparty/autotrace/spline.h
@@ -0,0 +1,88 @@
+/* spline.h: manipulate the spline representation.
+ Some of macrs are only renamed macros in output.h. */
+
+#ifndef SPLINE_H
+#define SPLINE_H
+
+#include <stdio.h>
+#include "autotrace.h"
+#include "output.h"
+
+typedef at_polynomial_degree polynomial_degree;
+typedef at_spline_type spline_type;
+
+#define LINEARTYPE AT_LINEARTYPE
+#define QUADRATICTYPE AT_QUADRATICTYPE
+#define CUBICTYPE AT_CUBICTYPE
+#define PARALLELELLIPSETYPE AT_PARALLELELLIPSETYPE
+#define ELLIPSETYPE AT_ELLIPSETYPE
+#define CIRCLETYPE AT_CIRCLETYPE
+
+#define START_POINT AT_SPLINE_START_POINT_VALUE
+#define CONTROL1 AT_SPLINE_CONTROL1_VALUE
+#define CONTROL2 AT_SPLINE_CONTROL2_VALUE
+#define END_POINT AT_SPLINE_END_POINT_VALUE
+#define SPLINE_DEGREE AT_SPLINE_DEGREE_VALUE
+#define SPLINE_LINEARITY(spl) ((spl).linearity)
+
+#ifndef _IMPORTING
+/* Print a spline on the given file. */
+extern void print_spline(spline_type);
+
+/* Evaluate SPLINE at the given T value. */
+extern at_real_coord evaluate_spline(spline_type spline, gfloat t);
+#endif
+
+/* Each outline in a character is typically represented by many
+ splines. So, here is a list structure for that: */
+typedef at_spline_list_type spline_list_type;
+
+/* An empty list will have length zero (and null data). */
+#define SPLINE_LIST_LENGTH AT_SPLINE_LIST_LENGTH_VALUE
+
+/* The address of the beginning of the array of data. */
+#define SPLINE_LIST_DATA AT_SPLINE_LIST_DATA_VALUE
+
+/* The element INDEX in S_L. */
+#define SPLINE_LIST_ELT AT_SPLINE_LIST_ELT_VALUE
+
+/* The last element in S_L. */
+#define LAST_SPLINE_LIST_ELT(s_l) \
+ (SPLINE_LIST_DATA (s_l)[SPLINE_LIST_LENGTH (s_l) - 1])
+
+/* The previous and next elements to INDEX in S_L. */
+#define NEXT_SPLINE_LIST_ELT(s_l, index) \
+ SPLINE_LIST_ELT (s_l, ((index) + 1) % SPLINE_LIST_LENGTH (s_l))
+#define PREV_SPLINE_LIST_ELT(s_l, index) \
+ SPLINE_LIST_ELT (s_l, index == 0 \
+ ? SPLINE_LIST_LENGTH (s_l) - 1 \
+ : index - 1)
+
+#ifndef _IMPORTING
+/* Construct and destroy new `spline_list_type' objects. */
+extern spline_list_type *new_spline_list(void); /* Allocate new memory */
+extern spline_list_type empty_spline_list(void); /* No allocation */
+extern spline_list_type *new_spline_list_with_spline(spline_type);
+extern void free_spline_list(spline_list_type);
+
+/* Append the spline S to the list S_LIST. */
+extern void append_spline(spline_list_type * s_list, spline_type s);
+
+/* Append the elements in list S2 to S1, changing S1. */
+extern void concat_spline_lists(spline_list_type * s1, spline_list_type s2);
+#endif
+
+typedef at_spline_list_array_type spline_list_array_type;
+
+/* Turns out we can use the same definitions for lists of lists as for
+ just lists. But we define the usual names, just in case. */
+#define SPLINE_LIST_ARRAY_LENGTH AT_SPLINE_LIST_ARRAY_LENGTH_VALUE
+#define SPLINE_LIST_ARRAY_DATA SPLINE_LIST_DATA
+#define SPLINE_LIST_ARRAY_ELT AT_SPLINE_LIST_ARRAY_ELT_VALUE
+#define LAST_SPLINE_LIST_ARRAY_ELT LAST_SPLINE_LIST_ELT
+
+extern spline_list_array_type new_spline_list_array(void);
+extern void append_spline_list(spline_list_array_type *, spline_list_type);
+extern void free_spline_list_array(spline_list_array_type *);
+
+#endif /* not SPLINE_H */
diff --git a/src/3rdparty/autotrace/thin-image.c b/src/3rdparty/autotrace/thin-image.c
new file mode 100644
index 0000000..2e220ec
--- /dev/null
+++ b/src/3rdparty/autotrace/thin-image.c
@@ -0,0 +1,353 @@
+/* thin-image.c: thin binary image
+
+ Copyright (C) 2001, 2002 Martin Weber
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License
+ as published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* Def: HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "thin-image.h"
+#include "logreport.h"
+#include "types.h"
+#include "bitmap.h"
+#include "xstd.h"
+#include <string.h>
+
+#define PIXEL_SET(p, new) ((void)memcpy((p), (new), sizeof(Pixel)))
+#define PIXEL_EQUAL(p1, p2) \
+ ((p1)[0] == (p2)[0] && (p1)[1] == (p2)[1] && (p1)[2] == (p2)[2])
+
+typedef unsigned char Pixel[3]; /* RGB pixel data type */
+
+void thin3(at_bitmap * image, Pixel colour);
+void thin1(at_bitmap * image, unsigned char colour);
+
+/* -------------------------------- ThinImage - Thin binary image. --------------------------- *
+ *
+ * Description:
+ * Thins the supplied binary image using Rosenfeld's parallel
+ * thinning algorithm.
+ *
+ * On Entry:
+ * image = Image to thin.
+ *
+ * -------------------------------------------------------------------------------------------- */
+
+/* Direction masks: */
+/* N S W E */
+static unsigned int masks[] = { 0200, 0002, 0040, 0010 };
+
+/* True if pixel neighbor map indicates the pixel is 8-simple and */
+/* not an end point and thus can be deleted. The neighborhood */
+/* map is defined as an integer of bits abcdefghi with a non-zero */
+/* bit representing a non-zero pixel. The bit assignment for the */
+/* neighborhood is: */
+/* */
+/* a b c */
+/* d e f */
+/* g h i */
+
+static unsigned char todelete[512] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+};
+
+static at_color background = { 0xff, 0xff, 0xff };
+
+void thin_image(at_bitmap * image, const at_color * bg, at_exception_type * exp)
+{
+ /* This is nasty as we need to call thin once for each
+ * colour in the image the way I do this is to keep a second
+ * copy of the bitmap and to use this to keep
+ * track of which colours have not yet been processed,
+ * trades time for pathological case memory.....*/
+ long m, n, num_pixels;
+ at_bitmap bm;
+ unsigned int spp = AT_BITMAP_PLANES(image), width = AT_BITMAP_WIDTH(image), height = AT_BITMAP_HEIGHT(image);
+
+ if (bg)
+ background = *bg;
+
+ bm.height = image->height;
+ bm.width = image->width;
+ bm.np = image->np;
+ XMALLOC(bm.bitmap, height * width * spp);
+ memcpy(bm.bitmap, image->bitmap, height * width * spp);
+ /* that clones the image */
+
+ num_pixels = height * width;
+ switch (spp) {
+ case 3:
+ {
+ Pixel *ptr = (Pixel *) AT_BITMAP_BITS(&bm);
+ Pixel bg_color;
+ bg_color[0] = background.r;
+ bg_color[1] = background.g;
+ bg_color[2] = background.b;
+
+ for (n = num_pixels - 1; n >= 0L; --n) {
+ Pixel p;
+
+ PIXEL_SET(p, ptr[n]);
+ if (!PIXEL_EQUAL(p, bg_color)) {
+ /* we have a new colour in the image */
+ LOG("Thinning colour (%x, %x, %x)\n", p[0], p[1], p[2]);
+ for (m = n - 1; m >= 0L; --m) {
+ if (PIXEL_EQUAL(ptr[m], p))
+ PIXEL_SET(ptr[m], bg_color);
+ }
+ thin3(image, p);
+ }
+ }
+ break;
+ }
+
+ case 1:
+ {
+ unsigned char *ptr = AT_BITMAP_BITS(&bm);
+ unsigned char bg_color;
+
+ if (background.r == background.g && background.g == background.b)
+ bg_color = background.r;
+ else
+ bg_color = at_color_luminance(&background);
+
+ for (n = num_pixels - 1; n >= 0L; --n) {
+ unsigned char c = ptr[n];
+ if (c != bg_color) {
+ LOG("Thinning colour %x\n", c);
+ for (m = n - 1; m >= 0L; --m)
+ if (ptr[m] == c)
+ ptr[m] = bg_color;
+ thin1(image, c);
+ }
+ }
+ break;
+ }
+
+ default:
+ {
+ LOG("thin_image: %u-plane images are not supported", spp);
+ at_exception_fatal(exp, "thin_image: wrong plane images are passed");
+ goto cleanup;
+ }
+ }
+cleanup:
+ free(bm.bitmap);
+}
+
+void thin3(at_bitmap * image, Pixel colour)
+{
+ Pixel *ptr, *y_ptr, *y1_ptr;
+ Pixel bg_color;
+ unsigned int xsize, ysize; /* Image resolution */
+ unsigned int x, y; /* Pixel location */
+ unsigned int i; /* Pass index */
+ unsigned int pc = 0; /* Pass count */
+ unsigned int count = 1; /* Deleted pixel count */
+ unsigned int p, q; /* Neighborhood maps of adjacent */
+ /* cells */
+ unsigned char *qb; /* Neighborhood maps of previous */
+ /* scanline */
+ unsigned int m; /* Deletion direction mask */
+
+ bg_color[0] = background.r;
+ bg_color[1] = background.g;
+ bg_color[2] = background.b;
+
+ LOG(" Thinning image.....\n ");
+ xsize = AT_BITMAP_WIDTH(image);
+ ysize = AT_BITMAP_HEIGHT(image);
+ XMALLOC(qb, xsize * sizeof(unsigned char));
+ qb[xsize - 1] = 0; /* Used for lower-right pixel */
+ ptr = (Pixel *) AT_BITMAP_BITS(image);
+
+ while (count) { /* Scan image while deletions */
+ pc++;
+ count = 0;
+
+ for (i = 0; i < 4; i++) {
+
+ m = masks[i];
+
+ /* Build initial previous scan buffer. */
+ p = PIXEL_EQUAL(ptr[0], colour);
+ for (x = 0; x < xsize - 1; x++)
+ qb[x] = (unsigned char)(p = ((p << 1) & 0006) | (unsigned int)PIXEL_EQUAL(ptr[x + 1], colour));
+
+ /* Scan image for pixel deletion candidates. */
+ y_ptr = ptr;
+ y1_ptr = ptr + xsize;
+ for (y = 0; y < ysize - 1; y++, y_ptr += xsize, y1_ptr += xsize) {
+ q = qb[0];
+ p = ((q << 2) & 0330) | (unsigned int)PIXEL_EQUAL(y1_ptr[0], colour);
+
+ for (x = 0; x < xsize - 1; x++) {
+ q = qb[x];
+ p = ((p << 1) & 0666) | ((q << 3) & 0110) | (unsigned int)PIXEL_EQUAL(y1_ptr[x + 1], colour);
+ qb[x] = (unsigned char)p;
+ if ((i != 2 || x != 0) && ((p & m) == 0) && todelete[p]) {
+ count++; /* delete the pixel */
+ PIXEL_SET(y_ptr[x], bg_color);
+ }
+ }
+
+ /* Process right edge pixel. */
+ p = (p << 1) & 0666;
+ if (i != 3 && (p & m) == 0 && todelete[p]) {
+ count++;
+ PIXEL_SET(y_ptr[xsize - 1], bg_color);
+ }
+ }
+
+ if (i != 1) {
+ /* Process bottom scan line. */
+ q = qb[0];
+ p = ((q << 2) & 0330);
+
+ y_ptr = ptr + xsize * (ysize - 1);
+ for (x = 0; x < xsize; x++) {
+ q = qb[x];
+ p = ((p << 1) & 0666) | ((q << 3) & 0110);
+ if ((i != 2 || x != 0) && (p & m) == 0 && todelete[p]) {
+ count++;
+ PIXEL_SET(y_ptr[x], bg_color);
+ }
+ }
+ }
+ }
+ LOG("ThinImage: pass %d, %d pixels deleted\n", pc, count);
+ }
+ free(qb);
+}
+
+void thin1(at_bitmap * image, unsigned char colour)
+{
+ unsigned char *ptr, *y_ptr, *y1_ptr;
+ unsigned char bg_color;
+ unsigned int xsize, ysize; /* Image resolution */
+ unsigned int x, y; /* Pixel location */
+ unsigned int i; /* Pass index */
+ unsigned int pc = 0; /* Pass count */
+ unsigned int count = 1; /* Deleted pixel count */
+ unsigned int p, q; /* Neighborhood maps of adjacent */
+ /* cells */
+ unsigned char *qb; /* Neighborhood maps of previous */
+ /* scanline */
+ unsigned int m; /* Deletion direction mask */
+
+ if (background.r == background.g && background.g == background.b)
+ bg_color = background.r;
+ else
+ bg_color = at_color_luminance(&background);
+
+ LOG(" Thinning image.....\n ");
+ xsize = AT_BITMAP_WIDTH(image);
+ ysize = AT_BITMAP_HEIGHT(image);
+ XMALLOC(qb, xsize * sizeof(unsigned char));
+ qb[xsize - 1] = 0; /* Used for lower-right pixel */
+ ptr = AT_BITMAP_BITS(image);
+
+ while (count) { /* Scan image while deletions */
+ pc++;
+ count = 0;
+
+ for (i = 0; i < 4; i++) {
+
+ m = masks[i];
+
+ /* Build initial previous scan buffer. */
+ p = (ptr[0] == colour);
+ for (x = 0; x < xsize - 1; x++)
+ qb[x] = (unsigned char)(p = ((p << 1) & 0006) | (unsigned int)(ptr[x + 1] == colour));
+
+ /* Scan image for pixel deletion candidates. */
+ y_ptr = ptr;
+ y1_ptr = ptr + xsize;
+ for (y = 0; y < ysize - 1; y++, y_ptr += xsize, y1_ptr += xsize) {
+ q = qb[0];
+ p = ((q << 2) & 0330) | (y1_ptr[0] == colour);
+
+ for (x = 0; x < xsize - 1; x++) {
+ q = qb[x];
+ p = ((p << 1) & 0666) | ((q << 3) & 0110) | (unsigned int)(y1_ptr[x + 1] == colour);
+ qb[x] = (unsigned char)p;
+ if (((p & m) == 0) && todelete[p]) {
+ count++;
+ y_ptr[x] = bg_color; /* delete the pixel */
+ }
+ }
+
+ /* Process right edge pixel. */
+ p = (p << 1) & 0666;
+ if ((p & m) == 0 && todelete[p]) {
+ count++;
+ y_ptr[xsize - 1] = bg_color;
+ }
+ }
+
+ /* Process bottom scan line. */
+ q = qb[0];
+ p = ((q << 2) & 0330);
+
+ y_ptr = ptr + xsize * (ysize - 1);
+ for (x = 0; x < xsize; x++) {
+ q = qb[x];
+ p = ((p << 1) & 0666) | ((q << 3) & 0110);
+ if ((p & m) == 0 && todelete[p]) {
+ count++;
+ y_ptr[x] = bg_color;
+ }
+ }
+ }
+ LOG("thin1: pass %d, %d pixels deleted\n", pc, count);
+ }
+ free(qb);
+}
diff --git a/src/3rdparty/autotrace/thin-image.h b/src/3rdparty/autotrace/thin-image.h
new file mode 100644
index 0000000..fdeba2a
--- /dev/null
+++ b/src/3rdparty/autotrace/thin-image.h
@@ -0,0 +1,36 @@
+/* thin-image.h: thin binary image
+
+ Copyright (C) 2001, 2002 Martin Weber
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License
+ as published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA. */
+
+#ifndef THIN_IMAGE_H
+#define THIN_IMAGE_H
+
+/*
+ * C code from the article
+ * "Efficient Binary Image Thinning using Neighborhood Maps"
+ * by Joseph M. Cychosz, 3ksnn64@ecn.purdue.edu
+ * in "Graphics Gems IV", Academic Press, 1994
+ */
+
+#include "bitmap.h"
+#include "color.h"
+#include "exception.h"
+
+void thin_image(at_bitmap * image, const at_color * bg_color, at_exception_type * exp);
+
+#endif /* not THIN_IMAGE_H */
diff --git a/src/3rdparty/autotrace/types.h b/src/3rdparty/autotrace/types.h
new file mode 100644
index 0000000..a7b6843
--- /dev/null
+++ b/src/3rdparty/autotrace/types.h
@@ -0,0 +1,42 @@
+/* types.h: general types
+ Copyright (C) 2000, 2001 Martin Weber
+
+ The author can be contacted at <martweb@gmx.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef AT_TYPES_H
+#define AT_TYPES_H
+
+#include <stdint.h>
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Cartesian points. */
+ typedef struct _at_coord {
+ gushort x, y;
+ } at_coord;
+
+ typedef struct _at_real_coord {
+ gfloat x, y, z;
+ } at_real_coord;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* not AT_TYPES_H */
diff --git a/src/3rdparty/autotrace/vector.c b/src/3rdparty/autotrace/vector.c
new file mode 100644
index 0000000..2b6375a
--- /dev/null
+++ b/src/3rdparty/autotrace/vector.c
@@ -0,0 +1,260 @@
+/* vector.c: vector/point operations. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* Def: HAVE_CONFIG_H */
+
+#include "vector.h"
+#include "logreport.h"
+#include "epsilon-equal.h"
+#include <math.h>
+#include <errno.h>
+#include <assert.h>
+#include <string.h>
+
+static gfloat acos_d(gfloat, at_exception_type * excep);
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+
+/* Given the point COORD, return the corresponding vector. */
+
+vector_type make_vector(const at_real_coord c)
+{
+ vector_type v;
+
+ v.dx = c.x;
+ v.dy = c.y;
+ v.dz = c.z;
+
+ return v;
+}
+
+/* And the converse: given a vector, return the corresponding point. */
+
+at_real_coord vector_to_point(const vector_type v)
+{
+ at_real_coord coord;
+
+ coord.x = v.dx;
+ coord.y = v.dy;
+
+ return coord;
+}
+
+gfloat magnitude(const vector_type v)
+{
+ return (gfloat) sqrt(v.dx * v.dx + v.dy * v.dy + v.dz * v.dz);
+}
+
+vector_type normalize(const vector_type v)
+{
+ vector_type new_v;
+ gfloat m = magnitude(v);
+
+ /* assert (m > 0.0); */
+
+ if (m > 0.0) {
+ new_v.dx = v.dx / m;
+ new_v.dy = v.dy / m;
+ new_v.dz = v.dz / m;
+ } else {
+ new_v.dx = v.dx;
+ new_v.dy = v.dy;
+ new_v.dz = v.dz;
+ }
+
+ return new_v;
+}
+
+vector_type Vadd(const vector_type v1, const vector_type v2)
+{
+ vector_type new_v;
+
+ new_v.dx = v1.dx + v2.dx;
+ new_v.dy = v1.dy + v2.dy;
+ new_v.dz = v1.dz + v2.dz;
+
+ return new_v;
+}
+
+gfloat Vdot(const vector_type v1, const vector_type v2)
+{
+ return v1.dx * v2.dx + v1.dy * v2.dy + v1.dz * v2.dz;
+}
+
+vector_type Vmult_scalar(const vector_type v, const gfloat r)
+{
+ vector_type new_v;
+
+ new_v.dx = v.dx * r;
+ new_v.dy = v.dy * r;
+ new_v.dz = v.dz * r;
+
+ return new_v;
+}
+
+/* Given the IN_VECTOR and OUT_VECTOR, return the angle between them in
+ degrees, in the range zero to 180. */
+
+gfloat Vangle(const vector_type in_vector, const vector_type out_vector, at_exception_type * exp)
+{
+ vector_type v1 = normalize(in_vector);
+ vector_type v2 = normalize(out_vector);
+
+ return acos_d(Vdot(v2, v1), exp);
+}
+
+at_real_coord Vadd_point(const at_real_coord c, const vector_type v)
+{
+ at_real_coord new_c;
+
+ new_c.x = c.x + v.dx;
+ new_c.y = c.y + v.dy;
+ new_c.z = c.z + v.dz;
+ return new_c;
+}
+
+at_real_coord Vsubtract_point(const at_real_coord c, const vector_type v)
+{
+ at_real_coord new_c;
+
+ new_c.x = c.x - v.dx;
+ new_c.y = c.y - v.dy;
+ new_c.z = c.z - v.dz;
+ return new_c;
+}
+
+at_coord Vadd_int_point(const at_coord c, const vector_type v)
+{
+ at_coord a;
+
+ a.x = (unsigned short)lround((gfloat) c.x + v.dx);
+ a.y = (unsigned short)lround((gfloat) c.y + v.dy);
+ return a;
+}
+
+vector_type Vabs(const vector_type v)
+{
+ vector_type new_v;
+
+ new_v.dx = (gfloat) fabs(v.dx);
+ new_v.dy = (gfloat) fabs(v.dy);
+ new_v.dz = (gfloat) fabs(v.dz);
+ return new_v;
+}
+
+/* Operations on points. */
+
+at_real_coord Padd(const at_real_coord coord1, const at_real_coord coord2)
+{
+ at_real_coord sum;
+
+ sum.x = coord1.x + coord2.x;
+ sum.y = coord1.y + coord2.y;
+ sum.z = coord1.z + coord2.z;
+
+ return sum;
+}
+
+at_real_coord Pmult_scalar(const at_real_coord coord, const gfloat r)
+{
+ at_real_coord answer;
+
+ answer.x = coord.x * r;
+ answer.y = coord.y * r;
+ answer.z = coord.z * r;
+
+ return answer;
+}
+
+vector_type Psubtract(const at_real_coord c1, const at_real_coord c2)
+{
+ vector_type v;
+
+ v.dx = c1.x - c2.x;
+ v.dy = c1.y - c2.y;
+ v.dz = c1.z - c2.z;
+
+ return v;
+}
+
+/* Operations on integer points. */
+
+vector_type IPsubtract(const at_coord coord1, const at_coord coord2)
+{
+ vector_type v;
+
+ v.dx = (gfloat) (coord1.x - coord2.x);
+ v.dy = (gfloat) (coord1.y - coord2.y);
+ v.dz = 0.0;
+
+ return v;
+}
+
+at_coord IPsubtractP(const at_coord c1, const at_coord c2)
+{
+ at_coord c;
+
+ c.x = c1.x - c2.x;
+ c.y = c1.y - c2.y;
+
+ return c;
+}
+
+at_coord IPadd(const at_coord c1, const at_coord c2)
+{
+ at_coord c;
+
+ c.x = c1.x + c2.x;
+ c.y = c1.y + c2.y;
+
+ return c;
+}
+
+at_coord IPmult_scalar(const at_coord c, const int i)
+{
+ at_coord a;
+
+ a.x = (unsigned short)(c.x * i);
+ a.y = (unsigned short)(c.y * i);
+
+ return a;
+}
+
+at_real_coord IPmult_real(const at_coord c, const gfloat r)
+{
+ at_real_coord a;
+
+ a.x = c.x * r;
+ a.y = c.y * r;
+
+ return a;
+}
+
+gboolean IPequal(const at_coord c1, const at_coord c2)
+{
+ if ((c1.x == c2.x) && (c1.y == c2.y))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static gfloat acos_d(gfloat v, at_exception_type * excep)
+{
+ gfloat a;
+
+ if (epsilon_equal(v, 1.0))
+ v = 1.0;
+ else if (epsilon_equal(v, -1.0))
+ v = -1.0;
+
+ errno = 0;
+ a = (gfloat) acos(v);
+ if (errno == ERANGE || errno == EDOM) {
+ at_exception_fatal(excep, strerror(errno));
+ return 0.0;
+ }
+
+ return a * (gfloat) 180.0 / (gfloat) M_PI;
+}
diff --git a/src/3rdparty/autotrace/vector.h b/src/3rdparty/autotrace/vector.h
new file mode 100644
index 0000000..fe26254
--- /dev/null
+++ b/src/3rdparty/autotrace/vector.h
@@ -0,0 +1,65 @@
+/* vector.h: operations on vectors and points. */
+
+#ifndef VECTOR_H
+#define VECTOR_H
+
+#include "types.h"
+#include "exception.h"
+
+/* Our vectors are represented as displacements along the x and y axes. */
+
+typedef struct {
+ gfloat dx, dy, dz;
+} vector_type;
+
+/* Consider a point as a vector from the origin. */
+extern vector_type make_vector(const at_real_coord);
+
+/* And a vector as a point, i.e., a displacement from the origin. */
+extern at_real_coord vector_to_point(const vector_type);
+
+/* Definitions for these common operations can be found in any decent
+ linear algebra book, and most calculus books. */
+
+extern gfloat magnitude(const vector_type);
+extern vector_type normalize(const vector_type);
+
+extern vector_type Vadd(const vector_type, const vector_type);
+extern gfloat Vdot(const vector_type, const vector_type);
+extern vector_type Vmult_scalar(const vector_type, const gfloat);
+extern gfloat Vangle(const vector_type in, const vector_type out, at_exception_type * exp);
+
+/* These operations could have been named `P..._vector' just as well as
+ V..._point, so we may as well allow both names. */
+#define Padd_vector Vadd_point
+extern at_real_coord Vadd_point(const at_real_coord, const vector_type);
+
+#define Psubtract_vector Vsubtract_point
+extern at_real_coord Vsubtract_point(const at_real_coord, const vector_type);
+
+/* This returns the rounded sum. */
+#define IPadd_vector Vadd_int_point
+extern at_coord Vadd_int_point(const at_coord, const vector_type);
+
+/* Take the absolute value of both components. */
+extern vector_type Vabs(const vector_type);
+
+/* Operations on points with real coordinates. It is not orthogonal,
+ but more convenient, to have the subtraction operator return a
+ vector, and the addition operator return a point. */
+extern vector_type Psubtract(const at_real_coord, const at_real_coord);
+
+/* These are heavily used in spline fitting. */
+extern at_real_coord Padd(const at_real_coord, const at_real_coord);
+extern at_real_coord Pmult_scalar(const at_real_coord, const gfloat);
+
+/* Similarly, for points with integer coordinates; here, a subtraction
+ operator that does return another point is useful. */
+extern vector_type IPsubtract(const at_coord, const at_coord);
+extern at_coord IPsubtractP(const at_coord, const at_coord);
+extern at_coord IPadd(const at_coord, const at_coord);
+extern at_coord IPmult_scalar(const at_coord, const int);
+extern at_real_coord IPmult_real(const at_coord, const gfloat);
+extern gboolean IPequal(const at_coord, const at_coord);
+
+#endif /* not VECTOR_H */
diff --git a/src/3rdparty/autotrace/xstd.h b/src/3rdparty/autotrace/xstd.h
new file mode 100644
index 0000000..a8862e3
--- /dev/null
+++ b/src/3rdparty/autotrace/xstd.h
@@ -0,0 +1,85 @@
+/* xstd.h: Wrappers for functions in C standard library
+ Was: xmem, xfile */
+
+/* These call the corresponding function in the standard library, and
+ abort if those routines fail. */
+
+#ifndef XSTD_H
+#define XSTD_H
+
+#include "types.h"
+#include <assert.h>
+#include <stdlib.h>
+
+/*
+ * XMEM
+ */
+#ifndef __cplusplus
+#define XMALLOC(new_mem, size) \
+do \
+ { \
+ assert(size); \
+ new_mem = (gpointer) malloc (size); \
+ assert(new_mem); \
+ } while (0)
+
+#define XCALLOC(new_mem, size) \
+do \
+ { \
+ assert(size); \
+ new_mem = (gpointer) calloc (size, 1); \
+ assert(new_mem); \
+ } while (0)
+
+#define XREALLOC(old_ptr, size) \
+do \
+ { \
+ gpointer new_mem; \
+ \
+ if (old_ptr == NULL) \
+ XMALLOC (new_mem, size); \
+ else \
+ { \
+ new_mem = (gpointer) realloc (old_ptr, size); \
+ assert(new_mem); \
+ } \
+ \
+ old_ptr = new_mem; \
+} while (0)
+
+#else
+/* Use templates if Cplusplus... */
+#define XMALLOC(new_mem, size) \
+do \
+ { \
+ assert(size); \
+ (gpointer&)(new_mem) = (gpointer) malloc (size); \
+ assert(new_mem); \
+ } while (0)
+
+#define XCALLOC(new_mem, sizex) \
+do \
+ { \
+ assert(sizex); \
+ (gpointer&)(new_mem) = (void *) calloc (sizex, 1); \
+ assert(new_mem); \
+ } while (0)
+
+#define XREALLOC(old_ptr, size) \
+do \
+ { \
+ gpointer new_mem; \
+ \
+ if (old_ptr == NULL) \
+ XMALLOC (new_mem, (size)); \
+ else \
+ { \
+ (gpointer&) new_mem = (gpointer) realloc ((old_ptr), (size)); \
+ assert(new_mem); \
+ } \
+ \
+ (gpointer&)old_ptr = new_mem; \
+ } while (0)
+#endif
+
+#endif /* Not XSTD_H */
diff --git a/src/3rdparty/libcroco/.clang-format b/src/3rdparty/libcroco/.clang-format
new file mode 100644
index 0000000..7612e59
--- /dev/null
+++ b/src/3rdparty/libcroco/.clang-format
@@ -0,0 +1,16 @@
+BasedOnStyle: LLVM
+
+AlwaysBreakAfterDefinitionReturnType: All
+BreakBeforeBinaryOperators: NonAssignment
+BreakBeforeBraces: Custom
+BraceWrapping:
+ AfterEnum: true
+ AfterCaseLabel: true
+ AfterStruct: true
+ AfterFunction: true
+
+BinPackParameters: false
+ColumnLimit: 80
+IndentWidth: 8
+SpaceAfterCStyleCast: true
+SpaceBeforeParens: Always
diff --git a/src/3rdparty/libcroco/ABOUT-NLS b/src/3rdparty/libcroco/ABOUT-NLS
new file mode 100644
index 0000000..28d38c7
--- /dev/null
+++ b/src/3rdparty/libcroco/ABOUT-NLS
@@ -0,0 +1,226 @@
+Notes on the Free Translation Project
+*************************************
+
+ Free software is going international! The Free Translation Project
+is a way to get maintainers of free software, translators, and users all
+together, so that will gradually become able to speak many languages.
+A few packages already provide translations for their messages.
+
+ If you found this `ABOUT-NLS' file inside a distribution, you may
+assume that the distributed package does use GNU `gettext' internally,
+itself available at your nearest GNU archive site. But you do *not*
+need to install GNU `gettext' prior to configuring, installing or using
+this package with messages translated.
+
+ Installers will find here some useful hints. These notes also
+explain how users should proceed for getting the programs to use the
+available translations. They tell how people wanting to contribute and
+work at translations should contact the appropriate team.
+
+ When reporting bugs in the `intl/' directory or bugs which may be
+related to internationalization, you should tell about the version of
+`gettext' which is used. The information can be found in the
+`intl/VERSION' file, in internationalized packages.
+
+One advise in advance
+=====================
+
+ If you want to exploit the full power of internationalization, you
+should configure it using
+
+ ./configure --with-included-gettext
+
+to force usage of internationalizing routines provided within this
+package, despite the existence of internationalizing capabilities in the
+operating system where this package is being installed. So far, only
+the `gettext' implementation in the GNU C library version 2 provides as
+many features (such as locale alias or message inheritance) as the
+implementation here. It is also not possible to offer this additional
+functionality on top of a `catgets' implementation. Future versions of
+GNU `gettext' will very likely convey even more functionality. So it
+might be a good idea to change to GNU `gettext' as soon as possible.
+
+ So you need not provide this option if you are using GNU libc 2 or
+you have installed a recent copy of the GNU gettext package with the
+included `libintl'.
+
+INSTALL Matters
+===============
+
+ Some packages are "localizable" when properly installed; the
+programs they contain can be made to speak your own native language.
+Most such packages use GNU `gettext'. Other packages have their own
+ways to internationalization, predating GNU `gettext'.
+
+ By default, this package will be installed to allow translation of
+messages. It will automatically detect whether the system provides
+usable `catgets' (if using this is selected by the installer) or
+`gettext' functions. If neither is available, the GNU `gettext' own
+library will be used. This library is wholly contained within this
+package, usually in the `intl/' subdirectory, so prior installation of
+the GNU `gettext' package is *not* required. Installers may use
+special options at configuration time for changing the default
+behaviour. The commands:
+
+ ./configure --with-included-gettext
+ ./configure --with-catgets
+ ./configure --disable-nls
+
+will respectively bypass any pre-existing `catgets' or `gettext' to use
+the internationalizing routines provided within this package, enable
+the use of the `catgets' functions (if found on the locale system), or
+else, *totally* disable translation of messages.
+
+ When you already have GNU `gettext' installed on your system and run
+configure without an option for your new package, `configure' will
+probably detect the previously built and installed `libintl.a' file and
+will decide to use this. This might be not what is desirable. You
+should use the more recent version of the GNU `gettext' library. I.e.
+if the file `intl/VERSION' shows that the library which comes with this
+package is more recent, you should use
+
+ ./configure --with-included-gettext
+
+to prevent auto-detection.
+
+ By default the configuration process will not test for the `catgets'
+function and therefore they will not be used. The reasons are already
+given above: the emulation on top of `catgets' cannot provide all the
+extensions provided by the GNU `gettext' library. If you nevertheless
+want to use the `catgets' functions use
+
+ ./configure --with-catgets
+
+to enable the test for `catgets' (this causes no harm if `catgets' is
+not available on your system). If you really select this option we
+would like to hear about the reasons because we cannot think of any
+good one ourself.
+
+ Internationalized packages have usually many `po/LL.po' files, where
+LL gives an ISO 639 two-letter code identifying the language. Unless
+translations have been forbidden at `configure' time by using the
+`--disable-nls' switch, all available translations are installed
+together with the package. However, the environment variable `LINGUAS'
+may be set, prior to configuration, to limit the installed set.
+`LINGUAS' should then contain a space separated list of two-letter
+codes, stating which languages are allowed.
+
+Using This Package
+==================
+
+ As a user, if your language has been installed for this package, you
+only have to set the `LANG' environment variable to the appropriate
+ISO 639 `LL' two-letter code prior to using the programs in the
+package. For example, let's suppose that you speak German. At the
+shell prompt, merely execute `setenv LANG de' (in `csh'),
+`export LANG; LANG=de' (in `sh') or `export LANG=de' (in `bash'). This
+can be done from your `.login' or `.profile' file, once and for all.
+
+ An operating system might already offer message localization for
+many of its programs, while other programs have been installed locally
+with the full capabilities of GNU `gettext'. Just using `gettext'
+extended syntax for `LANG' would break proper localization of already
+available operating system programs. In this case, users should set
+both `LANGUAGE' and `LANG' variables in their environment, as programs
+using GNU `gettext' give preference to `LANGUAGE'. For example, some
+Swedish users would rather read translations in German than English for
+when Swedish is not available. This is easily accomplished by setting
+`LANGUAGE' to `sv:de' while leaving `LANG' to `sv'.
+
+Translating Teams
+=================
+
+ For the Free Translation Project to be a success, we need interested
+people who like their own language and write it well, and who are also
+able to synergize with other translators speaking the same language.
+Each translation team has its own mailing list, courtesy of Linux
+International. You may reach your translation team at the address
+`LL@li.org', replacing LL by the two-letter ISO 639 code for your
+language. Language codes are *not* the same as the country codes given
+in ISO 3166. The following translation teams exist, as of December
+1997:
+
+ Chinese `zh', Czech `cs', Danish `da', Dutch `nl', English `en',
+ Esperanto `eo', Finnish `fi', French `fr', German `de', Hungarian
+ `hu', Irish `ga', Italian `it', Indonesian `id', Japanese `ja',
+ Korean `ko', Latin `la', Norwegian `no', Persian `fa', Polish
+ `pl', Portuguese `pt', Russian `ru', Slovenian `sl', Spanish `es',
+ Swedish `sv', and Turkish `tr'.
+
+For example, you may reach the Chinese translation team by writing to
+`zh@li.org'.
+
+ If you'd like to volunteer to *work* at translating messages, you
+should become a member of the translating team for your own language.
+The subscribing address is *not* the same as the list itself, it has
+`-request' appended. For example, speakers of Swedish can send a
+message to `sv-request@li.org', having this message body:
+
+ subscribe
+
+ Keep in mind that team members are expected to participate
+*actively* in translations, or at solving translational difficulties,
+rather than merely lurking around. If your team does not exist yet and
+you want to start one, or if you are unsure about what to do or how to
+get started, please write to `translation@iro.umontreal.ca' to reach the
+coordinator for all translator teams.
+
+ The English team is special. It works at improving and uniformizing
+the terminology in use. Proven linguistic skill are praised more than
+programming skill, here.
+
+Available Packages
+==================
+
+ Languages are not equally supported in all packages. The following
+matrix shows the current state of internationalization, as of December
+1997. The matrix shows, in regard of each package, for which languages
+PO files have been submitted to translation coordination.
+
+ Ready PO files cs da de en es fi fr it ja ko nl no pl pt ru sl sv
+ .----------------------------------------------------.
+ bash | [] [] [] | 3
+ bison | [] [] [] | 3
+ clisp | [] [] [] [] | 4
+ cpio | [] [] [] [] [] [] | 6
+ diffutils | [] [] [] [] [] | 5
+ enscript | [] [] [] [] [] [] | 6
+ fileutils | [] [] [] [] [] [] [] [] [] [] | 10
+ findutils | [] [] [] [] [] [] [] [] [] | 9
+ flex | [] [] [] [] | 4
+ gcal | [] [] [] [] [] | 5
+ gettext | [] [] [] [] [] [] [] [] [] [] [] | 12
+ grep | [] [] [] [] [] [] [] [] [] [] | 10
+ hello | [] [] [] [] [] [] [] [] [] [] [] | 11
+ id-utils | [] [] [] | 3
+ indent | [] [] [] [] [] | 5
+ libc | [] [] [] [] [] [] [] | 7
+ m4 | [] [] [] [] [] [] | 6
+ make | [] [] [] [] [] [] | 6
+ music | [] [] | 2
+ ptx | [] [] [] [] [] [] [] [] | 8
+ recode | [] [] [] [] [] [] [] [] [] | 9
+ sh-utils | [] [] [] [] [] [] [] [] | 8
+ sharutils | [] [] [] [] [] [] | 6
+ tar | [] [] [] [] [] [] [] [] [] [] [] | 11
+ texinfo | [] [] [] | 3
+ textutils | [] [] [] [] [] [] [] [] [] | 9
+ wdiff | [] [] [] [] [] [] [] [] | 8
+ `----------------------------------------------------'
+ 17 languages cs da de en es fi fr it ja ko nl no pl pt ru sl sv
+ 27 packages 6 4 25 1 18 1 26 2 1 12 20 9 19 7 4 7 17 179
+
+ Some counters in the preceding matrix are higher than the number of
+visible blocks let us expect. This is because a few extra PO files are
+used for implementing regional variants of languages, or language
+dialects.
+
+ For a PO file in the matrix above to be effective, the package to
+which it applies should also have been internationalized and
+distributed as such by its maintainer. There might be an observable
+lag between the mere existence a PO file and its wide availability in a
+distribution.
+
+ If December 1997 seems to be old, you may fetch a more recent copy
+of this `ABOUT-NLS' file on most GNU archive sites.
+
diff --git a/src/3rdparty/libcroco/AUTHORS b/src/3rdparty/libcroco/AUTHORS
new file mode 100644
index 0000000..75562c3
--- /dev/null
+++ b/src/3rdparty/libcroco/AUTHORS
@@ -0,0 +1,13 @@
+Dodji Seketeli <dodji@gnome.org>
+-----------------------------------
+Initial Author, main maintainer and main architect.
+
+Gael Chamoulaud <strider@gnome.org>
+##########################################
+Programmer.
+
+Rob BUIS <rwlbuis@xs4all.nl>
+----------------------------
+Sent several patches.
+
+
diff --git a/src/3rdparty/libcroco/CMakeLists.txt b/src/3rdparty/libcroco/CMakeLists.txt
new file mode 100644
index 0000000..d3e0366
--- /dev/null
+++ b/src/3rdparty/libcroco/CMakeLists.txt
@@ -0,0 +1,33 @@
+cmake_minimum_required(VERSION 3.6)
+
+project(libcroco LANGUAGES C)
+
+if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
+ set(LIBCROCO_STANDALONE TRUE)
+endif()
+
+set(LIBCROCO_MAJOR_VERSION 0)
+set(LIBCROCO_MINOR_VERSION 6)
+set(LIBCROCO_MICRO_VERSION 99)
+set(LIBCROCO_VERSION ${LIBCROCO_MAJOR_VERSION}.${LIBCROCO_MINOR_VERSION}.${LIBCROCO_MICRO_VERSION})
+math(EXPR LIBCROCO_VERSION_NUMBER "${LIBCROCO_MAJOR_VERSION} * 10000 +
+ ${LIBCROCO_MINOR_VERSION} * 100 +
+ ${LIBCROCO_MICRO_VERSION}")
+
+find_package(PkgConfig REQUIRED)
+
+set(GLIB_REQUIRED 2.0)
+set(LIBXML_REQUIRED 2.4.23)
+
+pkg_check_modules(GLIB REQUIRED glib-2.0>=${GLIB_REQUIRED})
+pkg_check_modules(LIBXML REQUIRED libxml-2.0>=${LIBXML_REQUIRED})
+
+add_subdirectory(src)
+
+option(LIBCROCO_TESTING "Build tests" "${LIBCROCO_STANDALONE}")
+
+if (LIBCROCO_TESTING)
+ enable_testing()
+ add_subdirectory(csslint)
+ add_subdirectory(tests)
+endif()
diff --git a/src/3rdparty/libcroco/CODING-STYLE b/src/3rdparty/libcroco/CODING-STYLE
new file mode 100644
index 0000000..1e76519
--- /dev/null
+++ b/src/3rdparty/libcroco/CODING-STYLE
@@ -0,0 +1,113 @@
+Author: Dodji Seketeli.
+-----------------------
+
+Introduction
+------------
+
+The coding standard we use are based on the GNU coding standards
+available at http://www.gnu.org/prep/standards_toc.html
+and on the Gnome Coding standards available at
+http://developer.gnome.org/doc/guides/programming-guidelines/book1.html .
+
+Please, make sure you read these documents before you read this one.
+
+I) General coding style rules
+---------------------------
+
+Coding style refers to the way the code is formatted.
+Here are the guidelines we use in this project:
+
+Indentation Style
+- - - - - - - - - -
+
+We use the 2-spaces tab indentation style (the GNU's one) .
+
+Make sure as much as possible that each code line does not
+exceed 80 characters length. Why ? because you don't know
+who will read your code. The smallest screens are 80 chars
+wide. So, please, make the code available to everybody.
+
+
+Functions naming
+- - - - - - - -
+
+We use the GNU name scheme to name our functions.
+
+GOOD:
+
+int
+my_function_name (char a_variable_name)
+{
+ printf ("The variable value is %c", a_variable_name) ;
+ return 0 ;
+}
+
+
+BAD:
+
+int
+myFunctionName (char blabla)
+{
+ printf ("This is awfull\n") ;
+}
+
+or
+
+int my_FunctionName (char Blabla) {
+ printf ("This is bad\n") ;
+}
+
+The words of the function names are separared by an underscore ('_') and
+are written in lower case.
+The name functions arguments always start with by a "a_" .
+
+Avoid for instance the Java function (method) name scheme by mixing
+upper and lower case in the function names.
+
+
+Be genereous with white spaces:
+
+GOOD:
+
+int foo (int a_parameter)
+{
+ if (test == TRUE) {
+ printf ("Coucou\n") ;
+ }
+}
+
+BAD:
+
+int foo(int a_parameter)
+{
+ if(test==TRUE) {
+ printf("coucou\n")
+ }
+}
+
+
+To ensure that the each line of code is less than 80 characters,
+if a function has many parameters, you can write it this way:
+
+
+Constants naming
+- - - - - - - - -
+Constants (defines or constant variables) must be in upper case.
+The worlds of the constant name must be separated by an underscore ('_').
+For instance:
+
+GOOD:
+gint A_CONSTANT = 10 ;
+#define ANOTHER_CONSTANT 100 ;
+
+BAD:
+gin a_Constant = 10 ;
+#define another_Constant ;
+
+
+structure and enum naming
+---------------------
+
+
+II) Object Oriented C programming
+-----------------------------
diff --git a/src/3rdparty/libcroco/COPYING b/src/3rdparty/libcroco/COPYING
new file mode 100644
index 0000000..eb685a5
--- /dev/null
+++ b/src/3rdparty/libcroco/COPYING
@@ -0,0 +1,481 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/src/3rdparty/libcroco/COPYING.LIB b/src/3rdparty/libcroco/COPYING.LIB
new file mode 100644
index 0000000..eb685a5
--- /dev/null
+++ b/src/3rdparty/libcroco/COPYING.LIB
@@ -0,0 +1,481 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/src/3rdparty/libcroco/COPYRIGHTS b/src/3rdparty/libcroco/COPYRIGHTS
new file mode 100644
index 0000000..fa33102
--- /dev/null
+++ b/src/3rdparty/libcroco/COPYRIGHTS
@@ -0,0 +1,4 @@
+Except where otherwise noted in the source code all the files are:
+
+ Copyright (C) 2003-2004 Dodji Seketeli. All Rights Reserved.
+
diff --git a/src/3rdparty/libcroco/Doxyfile b/src/3rdparty/libcroco/Doxyfile
new file mode 100644
index 0000000..0c210a3
--- /dev/null
+++ b/src/3rdparty/libcroco/Doxyfile
@@ -0,0 +1,946 @@
+# Doxyfile 1.2.16
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = Libcroco
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = docs/apis
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch,
+# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Korean,
+# Norwegian, Polish, Portuguese, Romanian, Russian, Slovak, Slovene,
+# Spanish, Swedish and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these class will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited
+# members of a class in the documentation of that class as if those members were
+# ordinary class members. Constructors, destructors and assignment operators of
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. It is allowed to use relative paths in the argument list.
+
+STRIP_FROM_PATH =
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower case letters. If set to YES upper case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# reimplements.
+
+INHERIT_DOCS = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consist of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C.
+# For instance some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = src
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp
+# *.h++ *.idl *.odl
+
+FILE_PATTERNS = *.c *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+
+INPUT_FILTER =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse.
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the Html help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript and frames is required (for instance Mozilla, Netscape 4.0+,
+# or Internet explorer 4.0+). Note that for large projects the tree generation
+# can take a very long time. In such cases it is better to disable this feature.
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimised for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_XML = NO
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line and do not end with a semicolon. Such function macros are typically
+# used for boiler-plate code, and will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tagfiles.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off. Note that this
+# option is superceded by the HAVE_DOT option below. This is only a fallback. It is
+# recommended to install and use dot, since it yield more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermedate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
+
+# The CGI_NAME tag should be the name of the CGI script that
+# starts the search engine (doxysearch) with the correct parameters.
+# A script with this name will be generated by doxygen.
+
+CGI_NAME = search.cgi
+
+# The CGI_URL tag should be the absolute URL to the directory where the
+# cgi binaries are located. See the documentation of your http daemon for
+# details.
+
+CGI_URL =
+
+# The DOC_URL tag should be the absolute URL to the directory where the
+# documentation is located. If left blank the absolute path to the
+# documentation, with file:// prepended to it, will be used.
+
+DOC_URL =
+
+# The DOC_ABSPATH tag should be the absolute path to the directory where the
+# documentation is located. If left blank the directory on the local machine
+# will be used.
+
+DOC_ABSPATH =
+
+# The BIN_ABSPATH tag must point to the directory where the doxysearch binary
+# is installed.
+
+BIN_ABSPATH = /usr/local/bin/
+
+# The EXT_DOC_PATHS tag can be used to specify one or more paths to
+# documentation generated for other projects. This allows doxysearch to search
+# the documentation for these projects as well.
+
+EXT_DOC_PATHS =
diff --git a/src/3rdparty/libcroco/Makefile.am b/src/3rdparty/libcroco/Makefile.am
new file mode 100644
index 0000000..4b482f3
--- /dev/null
+++ b/src/3rdparty/libcroco/Makefile.am
@@ -0,0 +1,72 @@
+ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
+
+DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
+
+SUBDIRS = src csslint docs tests win32
+
+PKG_CONFIG_FILE_UNINSTALLED=libcroco-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@-uninstalled.pc
+PKG_CONFIG_FILE=libcroco-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@.pc
+
+pkgconfigdir=$(libdir)/pkgconfig
+pkgconfig_DATA=$(PKG_CONFIG_FILE)
+
+INCLUDE_DIR_NAME=@PACKAGE@-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@
+extraincludedir=$(includedir)/$INCLUDE_DIR_NAME
+
+CROCO_CONFIG_FILE_UNINSTALLED=croco-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@-config-uninstalled
+CROCO_CONFIG_FILE=croco-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@-config
+bin_SCRIPTS=$(CROCO_CONFIG_FILE)
+
+#man_MANS = croco-config.1
+
+EXTRA_DIST= croco-config.in $(PKG_CONFIG_FILE) TODO Doxyfile \
+HACKING COPYING.LIB COPYING libcroco.spec libcroco-zip.in \
+autogen.sh libcroco.doap config.h.win32.in config.h.win32
+
+all-local: $(PKG_CONFIG_FILE_UNINSTALLED) $(PKG_CONFIG_FILE) \
+$(CROCO_CONFIG_FILE_UNINSTALLED) $(CROCO_CONFIG_FILE)
+
+
+%-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@.pc: %.pc
+ cp $< $@
+
+%-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@-uninstalled.pc: %.pc
+ cp $< $@
+
+%-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@-config: %-config
+ cp $< $@
+
+%-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@-config-uninstalled: %-config
+ cp $< $@
+
+clean-local: cleantest
+distclean-local:
+ -rm ./croco-0.6-config ./libcroco-0.6.pc ./libcroco-0.6-uninstalled.pc ./croco-0.6-config-uninstalled
+
+cleantest:
+ if test -x $(top_srcdir)/tests/testctl ; then $(top_srcdir)/tests/testctl cleanup ; fi
+
+cleantar:
+ @(rm -f libcroco*.tar.gz)
+ @(rm -rf $(top_srcdir)/rpmbuildroot)
+
+rpm: cleantar
+ @(mkdir -p $(top_srcdir)/rpmbuildroot ; $(MAKE) dist && rpmbuild -ta --buildroot $(top_srcdir)/rpmbuildroot $(distdir).tar.gz)
+
+test: all
+ if test -x $(top_srcdir)/tests/testctl ; then $(top_srcdir)/tests/testctl cleanup ; $(top_srcdir)/tests/testctl run ; fi
+
+apidoc:
+ if ! test -d docs/apis ; then mkdir -p docs/apis ; fi ;
+ doxygen Doxyfile
+
+ChangeLog:
+ $(AM_V_GEN) if test -f $(top_srcdir)/.git/HEAD; then \
+ git log --stat > $@; \
+ fi
+
+dist: ChangeLog
+
+.PHONY: ChangeLog
+
+
diff --git a/src/3rdparty/libcroco/NEWS b/src/3rdparty/libcroco/NEWS
new file mode 100644
index 0000000..a74ee44
--- /dev/null
+++ b/src/3rdparty/libcroco/NEWS
@@ -0,0 +1,178 @@
+0.6.99
+ * Apply inkscape modifications
+ * Consider significant digits for number formatting
+ * Use single instead of double quotes for string output
+ * cr_cascade_set_sheet: Allow a_sheet=NULL
+ * cr_stylesheet_new: Fix reference counting
+ * Mem leak fixes
+
+0.6.13
+ * Visual Studio builds: Enhance security of x64 binaries
+ * win32/replace.py: Fix replacing items in files with UTF-8 content
+ * tknzr: support only max long rgb values
+ * input: check end of input before reading a byte
+
+0.6.12
+ * Add support for Visual Studio 2017 (Chun-wei Fan)
+ * Misc bug fixes
+
+0.6.11
+ * Fix regression in cr_tknzr_consume_chars (Florian Müllner)
+ * Misc bug fixes
+
+0.6.10
+ * Misc bug fixes
+
+0.6.9
+ * Added Visual Studio projects (Chun-wei Fan)
+ * Lots of warnings fixed (РуÑлан Ижбулатов)
+ * Improve build system (Nuno Araujo, Ignacio Casal Quinteiro)
+ * Misc bug fixes
+
+0.6.8
+ * Handle signed units (Jasper St. Pierre, #686239)
+
+0.6.6.6
+ * Fix 'green' colour (#685679)
+ * Build fixes
+
+0.6.6
+ * Mem leak fixes (#678736)
+
+0.6.5
+
+ Changes & Bugfixes since 0.6.4
+ ==============================
+ * Fix mapping of 'green' colour (#672332)
+
+0.6.4
+
+ Changes & Bugfixes since 0.6.3
+ ==============================
+ * Use -Bsymbolic-functions when available
+ * Modernise and simplify configure
+ * #666248: vc++ compilation support
+ * #640897: fix format string warning in testcase
+
+0.6.3:
+
+ Bugfixes since 0.6.2
+ ====================
+ - #342370: ensure the library and compiler flags are not hardcoded into the pc file
+ - add gtk-doc build infrastructure
+
+0.6.2: February 4, 2009
+
+ Bugfixes since 0.6.1
+ ====================
+
+ - #306823: improve precision of non-integer numbers [Peter Moulder]
+ - #148790, #333834: Cygwin fixes
+ - #340298: Documentation fixes [Peter Moulder]
+ - #375194: fix to builtin color processing [Dom Lachowicz]
+ - #380438: Leak and trace message in cr_token_clear [Mark Rogers]
+ - #381040: floating numbers always output to exactly 3 digits after
+ decimal points [Dom Lachowicz]
+ - #336621: cr_tknzr_get_next_token wasn't handling "<!--" correctly
+ - #372011: comments not parsed correctly [Benjamin Dauvergne]
+ - #394680: problem parsing function name starting with 'u' or 'r'
+ [Benjamin Dauvergne]
+ - #139878: keep end of ruleset parsing location, and give it to the
+ end_selector sac-handler. [Benjamin Dauvergne]
+ - #394294: Escape are wrongly computed [Benjamin Dauvergne]
+ - #314831: Escapes not recognized [Benjamin Dauvergne]
+ - #395099: overly aggressive rule matching [Bruno Haible]
+ - #553937: CRDocHandler instances created with reference count of 0
+ [Robert Staudinger]
+
+ - Various fixes to the font handling [Bruno Haible]
+ - Add ‘const’ to various function prototypes [Peter Moulder]
+
+
+0.6.1: March 5, 2006
+
+ Bugfixes since 0.6.0
+ ====================
+
+ - parse fractional parts of numbers properly [Dom Lachowicz]
+ - win32 port [Tor Lillqvist]
+ - gtk-doc compliance [Sven Herzberg]
+ - test infrastructure enhancements [Peter Moulder]
+ - nasty memory management bug fix [ArjanV, Daniel Veillard]
+
+0.6.0: June 9, 2004
+
+ Enhancements since 0.5.1
+ ========================
+
+ - add parsing location to all the CSS constructions at SAC level [Dodji Seketeli]
+ - add --dump-location option to csslint [Dodji Seketeli]
+ - enable several API/ABI incompatible versions of Libcroco to be
+ installed on the same box [Dodji Seketeli]
+ - CSS properties inheritance support [Benjamin Dauvergne]
+ - CRStyle struct gatehering code cleanup [Benjamin Dauvergne]
+ - Better support for font selection [Dodji Seketeli]
+
+ Bugfixes since 0.5.1
+ ======================
+
+ - #143308: fix parsing of non trivial functional #notations. [Dodji Seketeli]
+ - #143450: fix gcc 2.xx errors. [Dodji Seketeli]
+ - #139881: proper setting of parsing locations in urls. [Dodji Seketeli]
+ - #138267: remove C99-isms.
+ - #139889: fix an infinite loop in the parser [Dodji Seketeli]
+ - #139891: better @media rule reporting [Dodji Seketeli]
+ - #140317: fix class sel without class name crash [Dodji Seketeli]
+ - #140334: fix an infinite loop in the parser [Dodji Seketeli]
+ - attribute selectors evaluation fixes. [Dodji Seketeli]
+ - Better support of descendant selectors evaluation [Dodji Seketeli]
+ - Better regression tests framework [Dodji Seketeli]
+
+0.5.1: April 18 2004:
+
+ - fixes: #140334, #140317, #139891, #139615. [Dodji Seketeli]
+
+0.5: March 16 2004:
+
+ - better regression suite framework [Dodji Seketeli]
+ - support of the 'color' property gathering [Benjamin Dauvergne]
+ - furious memory leaks/corruptions hunting [Dodji Seketeli, Rob BUIS]
+ - total support of the !important keyword [Dodji Seketeli, Rob BUIS]
+ - selectors evaluation in csslint [Dodji Seketeli, Rob BUIS]
+ - fix compilation warnings [David A Knight, Dodji Seketeli]
+ - more complete CSS statement serialisation [Dodji Seketeli]
+ - better gathering of style information [Dodjij Seketeli]
+ - better cascading algorithm conformance [Dodji Seketeli, Rob BUIS]
+ - @import rule parsing fix [Dodji Seketeli]
+ - support of CSS3 indentifiers [Dodji Seketeli]
+ - better w3c DOM integration support [Rob BUIS, Dodji Seketeli]
+ - many parsing fixes [Dodji Seketeli]
+ - style structure debugging facility [Dodji Seketeli]
+ - better fragment parsing support [Dodji Seketeli]
+ - Split libcroco and sewfox [Dodji Seketeli]
+ - class selector evaluation fix [Rob BUIS]
+ - csslint cleanup and bugfixes [Dodji Seketeli]
+ - :first-child pseudo class selector support [Dodji Seketeli]
+ - pluggable pseudo class selectors evaluators [Dodji Seketeli]
+
+
+libcroco 0.2.0
+ 2003 Jun 29
+ libcroco 0.2.0 ChangeLog:
+ * Went forward in the layout engine. Can now render
+ simple xml element along with simple CSS sheets.
+ Supported layout is normal layout for box and inline
+ context.
+ * Cleaned up the parsing api. Fixed a lot of bugs.
+ * Added some new api calls to the parsing api.
+ * See the ChangeLog shipped within the tarball for
+ more precise descriptions.
+
+libcroco 0.1.0
+
+ 2003 Mar 19
+ With the approval off all contributors the library has been
+ relicensed from GPL -> LGPL
+
+------------------------------------------------------------------------------
+
diff --git a/src/3rdparty/libcroco/README.md b/src/3rdparty/libcroco/README.md
new file mode 100644
index 0000000..d7aa48e
--- /dev/null
+++ b/src/3rdparty/libcroco/README.md
@@ -0,0 +1,15 @@
+[![build status](https://gitlab.com/inkscape/libcroco/badges/master/pipeline.svg)](https://gitlab.com/inkscape/libcroco/-/pipelines)
+
+What is The Croco Project ?
+------------------------------
+
+Libcroco is a standalone css2 parsing and manipulation library.
+The parser provides a low level event driven SAC like api
+and a css object model like api.
+Libcroco provides a CSS2 selection engine and an experimental
+xml/css rendering engine.
+
+This is a fork of the original
+[Gnome libcroco](https://gitlab.gnome.org/Archive/libcroco)
+project, which was discontinued. It's sole purpose is to be used with
+[Inkscape](https://gitlab.com/inkscape/inkscape). \ No newline at end of file
diff --git a/src/3rdparty/libcroco/TODO b/src/3rdparty/libcroco/TODO
new file mode 100644
index 0000000..d0062d6
--- /dev/null
+++ b/src/3rdparty/libcroco/TODO
@@ -0,0 +1,45 @@
+
+*coding:)
+
+
+
+Well, in the cr_statement_xxx_parse_functions, memleaks
+occur (the parsing result set in the sac callback is not freed)
+when a parsing fails. This is because the unrecoverable error
+does not get called when the standalone parsing functions exported
+by CRParser are called independently.
+I have now to support 2 modes of parsing. Normal and standalone.
+In standalone mode, the standalone parsing functions must
+call the "unrecoverable_error" sac callback when they fail.
+
+implements the width:20% case. (on going)
+ implement the size wrapping using the rightmost_x field of CRLayEngPriv.
+
+Provide support for font selection. (hard, started, is well underway.)
+ First make sure to be able to gather all the font related property
+ values.
+ Then, figure out how to implement a font selector that uses
+ pango. (on going)
+
+Go forward in the cascading implementation in cr-sel-eng.c
+ test/debug it.
+ write test cases to test/debug/validate this kind of stylesheets:
+ P {border: thick}
+ P {display: block}
+ /*
+ *stylesheets where the same selector is used several times
+ *to define different declarations.
+ */
+ write test cases to test/debug/validate the multi stylesheet support.
+
+
+*Doc:)
+
+Write examples of how to use the SAC api of libcroco and how to
+walk the css stylesheet tree.
+
+Finish the design of the instruction set of the selection engine.
+ The draft design is in the file
+ docs/designs/docs/design/sel-instr.txt.
+
+Write a little doc about how to use the parser as it is today.
diff --git a/src/3rdparty/libcroco/acinclude.m4 b/src/3rdparty/libcroco/acinclude.m4
new file mode 100644
index 0000000..cc65b75
--- /dev/null
+++ b/src/3rdparty/libcroco/acinclude.m4
@@ -0,0 +1,319 @@
+dnl Macros to check the presence of generic (non-typed) symbols.
+dnl Copyright (c) 2006-2008 Diego Pettenò <flameeyes@gmail.com>
+dnl Copyright (c) 2006-2008 xine project
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2, or (at your option)
+dnl any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+dnl 02110-1301, USA.
+dnl
+dnl As a special exception, the copyright owners of the
+dnl macro gives unlimited permission to copy, distribute and modify the
+dnl configure scripts that are the output of Autoconf when processing the
+dnl Macro. You need not follow the terms of the GNU General Public
+dnl License when using or distributing such scripts, even though portions
+dnl of the text of the Macro appear in them. The GNU General Public
+dnl License (GPL) does govern all other use of the material that
+dnl constitutes the Autoconf Macro.
+dnl
+dnl This special exception to the GPL applies to versions of the
+dnl Autoconf Macro released by this project. When you make and
+dnl distribute a modified version of the Autoconf Macro, you may extend
+dnl this special exception to the GPL to apply to your modified version as
+dnl well.
+
+dnl Check if the flag is supported by compiler
+dnl CC_CHECK_CFLAGS_SILENT([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND])
+
+AC_DEFUN([CC_CHECK_CFLAGS_SILENT], [
+ AC_CACHE_VAL(AS_TR_SH([cc_cv_cflags_$1]),
+ [ac_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $1"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([int a;])],
+ [eval "AS_TR_SH([cc_cv_cflags_$1])='yes'"],
+ [eval "AS_TR_SH([cc_cv_cflags_$1])='no'"])
+ CFLAGS="$ac_save_CFLAGS"
+ ])
+
+ AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes],
+ [$2], [$3])
+])
+
+dnl Check if the flag is supported by compiler (cacheable)
+dnl CC_CHECK_CFLAGS([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND])
+
+AC_DEFUN([CC_CHECK_CFLAGS], [
+ AC_CACHE_CHECK([if $CC supports $1 flag],
+ AS_TR_SH([cc_cv_cflags_$1]),
+ CC_CHECK_CFLAGS_SILENT([$1]) dnl Don't execute actions here!
+ )
+
+ AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes],
+ [$2], [$3])
+])
+
+dnl CC_CHECK_CFLAG_APPEND(FLAG, [action-if-found], [action-if-not-found])
+dnl Check for CFLAG and appends them to CFLAGS if supported
+AC_DEFUN([CC_CHECK_CFLAG_APPEND], [
+ AC_CACHE_CHECK([if $CC supports $1 flag],
+ AS_TR_SH([cc_cv_cflags_$1]),
+ CC_CHECK_CFLAGS_SILENT([$1]) dnl Don't execute actions here!
+ )
+
+ AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes],
+ [CFLAGS="$CFLAGS $1"; DEBUG_CFLAGS="$DEBUG_CFLAGS $1"; $2], [$3])
+])
+
+dnl CC_CHECK_CFLAGS_APPEND([FLAG1 FLAG2], [action-if-found], [action-if-not])
+AC_DEFUN([CC_CHECK_CFLAGS_APPEND], [
+ for flag in $1; do
+ CC_CHECK_CFLAG_APPEND($flag, [$2], [$3])
+ done
+])
+
+dnl Check if the flag is supported by linker (cacheable)
+dnl CC_CHECK_LDFLAGS([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND])
+
+AC_DEFUN([CC_CHECK_LDFLAGS], [
+ AC_CACHE_CHECK([if $CC supports $1 flag],
+ AS_TR_SH([cc_cv_ldflags_$1]),
+ [ac_save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $1"
+ AC_LANG_PUSH([C])
+ AC_LINK_IFELSE([AC_LANG_SOURCE([int main() { return 1; }])],
+ [eval "AS_TR_SH([cc_cv_ldflags_$1])='yes'"],
+ [eval "AS_TR_SH([cc_cv_ldflags_$1])="])
+ AC_LANG_POP([C])
+ LDFLAGS="$ac_save_LDFLAGS"
+ ])
+
+ AS_IF([eval test x$]AS_TR_SH([cc_cv_ldflags_$1])[ = xyes],
+ [$2], [$3])
+])
+
+dnl define the LDFLAGS_NOUNDEFINED variable with the correct value for
+dnl the current linker to avoid undefined references in a shared object.
+AC_DEFUN([CC_NOUNDEFINED], [
+ dnl We check $host for which systems to enable this for.
+ AC_REQUIRE([AC_CANONICAL_HOST])
+
+ case $host in
+ dnl FreeBSD (et al.) does not complete linking for shared objects when pthreads
+ dnl are requested, as different implementations are present; to avoid problems
+ dnl use -Wl,-z,defs only for those platform not behaving this way.
+ *-freebsd* | *-openbsd*) ;;
+ *)
+ dnl First of all check for the --no-undefined variant of GNU ld. This allows
+ dnl for a much more readable commandline, so that people can understand what
+ dnl it does without going to look for what the heck -z defs does.
+ for possible_flags in "-Wl,--no-undefined" "-Wl,-z,defs"; do
+ CC_CHECK_LDFLAGS([$possible_flags], [LDFLAGS_NOUNDEFINED="$possible_flags"])
+ break
+ done
+ ;;
+ esac
+
+ AC_SUBST([LDFLAGS_NOUNDEFINED])
+])
+
+dnl Check for a -Werror flag or equivalent. -Werror is the GCC
+dnl and ICC flag that tells the compiler to treat all the warnings
+dnl as fatal. We usually need this option to make sure that some
+dnl constructs (like attributes) are not simply ignored.
+dnl
+dnl Other compilers don't support -Werror per se, but they support
+dnl an equivalent flag:
+dnl - Sun Studio compiler supports -errwarn=%all
+AC_DEFUN([CC_CHECK_WERROR], [
+ AC_CACHE_CHECK(
+ [for $CC way to treat warnings as errors],
+ [cc_cv_werror],
+ [CC_CHECK_CFLAGS_SILENT([-Werror], [cc_cv_werror=-Werror],
+ [CC_CHECK_CFLAGS_SILENT([-errwarn=%all], [cc_cv_werror=-errwarn=%all])])
+ ])
+])
+
+AC_DEFUN([CC_CHECK_ATTRIBUTE], [
+ AC_REQUIRE([CC_CHECK_WERROR])
+ AC_CACHE_CHECK([if $CC supports __attribute__(( ifelse([$2], , [$1], [$2]) ))],
+ AS_TR_SH([cc_cv_attribute_$1]),
+ [ac_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $cc_cv_werror"
+ AC_LANG_PUSH([C])
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([$3])],
+ [eval "AS_TR_SH([cc_cv_attribute_$1])='yes'"],
+ [eval "AS_TR_SH([cc_cv_attribute_$1])='no'"])
+ AC_LANG_POP([C])
+ CFLAGS="$ac_save_CFLAGS"
+ ])
+
+ AS_IF([eval test x$]AS_TR_SH([cc_cv_attribute_$1])[ = xyes],
+ [AC_DEFINE(
+ AS_TR_CPP([SUPPORT_ATTRIBUTE_$1]), 1,
+ [Define this if the compiler supports __attribute__(( ifelse([$2], , [$1], [$2]) ))]
+ )
+ $4],
+ [$5])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_CONSTRUCTOR], [
+ CC_CHECK_ATTRIBUTE(
+ [constructor],,
+ [void __attribute__((constructor)) ctor() { int a; }],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_FORMAT], [
+ CC_CHECK_ATTRIBUTE(
+ [format], [format(printf, n, n)],
+ [void __attribute__((format(printf, 1, 2))) printflike(const char *fmt, ...) { fmt = (void *)0; }],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_FORMAT_ARG], [
+ CC_CHECK_ATTRIBUTE(
+ [format_arg], [format_arg(printf)],
+ [char *__attribute__((format_arg(1))) gettextlike(const char *fmt) { fmt = (void *)0; }],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_VISIBILITY], [
+ CC_CHECK_ATTRIBUTE(
+ [visibility_$1], [visibility("$1")],
+ [void __attribute__((visibility("$1"))) $1_function() { }],
+ [$2], [$3])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_NONNULL], [
+ CC_CHECK_ATTRIBUTE(
+ [nonnull], [nonnull()],
+ [void __attribute__((nonnull())) some_function(void *foo, void *bar) { foo = (void*)0; bar = (void*)0; }],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_UNUSED], [
+ CC_CHECK_ATTRIBUTE(
+ [unused], ,
+ [void some_function(void *foo, __attribute__((unused)) void *bar);],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_SENTINEL], [
+ CC_CHECK_ATTRIBUTE(
+ [sentinel], ,
+ [void some_function(void *foo, ...) __attribute__((sentinel));],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_DEPRECATED], [
+ CC_CHECK_ATTRIBUTE(
+ [deprecated], ,
+ [void some_function(void *foo, ...) __attribute__((deprecated));],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_ALIAS], [
+ CC_CHECK_ATTRIBUTE(
+ [alias], [weak, alias],
+ [void other_function(void *foo) { }
+ void some_function(void *foo) __attribute__((weak, alias("other_function")));],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_MALLOC], [
+ CC_CHECK_ATTRIBUTE(
+ [malloc], ,
+ [void * __attribute__((malloc)) my_alloc(int n);],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_PACKED], [
+ CC_CHECK_ATTRIBUTE(
+ [packed], ,
+ [struct astructure { char a; int b; long c; void *d; } __attribute__((packed));],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_CONST], [
+ CC_CHECK_ATTRIBUTE(
+ [const], ,
+ [int __attribute__((const)) twopow(int n) { return 1 << n; } ],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_FLAG_VISIBILITY], [
+ AC_REQUIRE([CC_CHECK_WERROR])
+ AC_CACHE_CHECK([if $CC supports -fvisibility=hidden],
+ [cc_cv_flag_visibility],
+ [cc_flag_visibility_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $cc_cv_werror"
+ CC_CHECK_CFLAGS_SILENT([-fvisibility=hidden],
+ cc_cv_flag_visibility='yes',
+ cc_cv_flag_visibility='no')
+ CFLAGS="$cc_flag_visibility_save_CFLAGS"])
+
+ AS_IF([test "x$cc_cv_flag_visibility" = "xyes"],
+ [AC_DEFINE([SUPPORT_FLAG_VISIBILITY], 1,
+ [Define this if the compiler supports the -fvisibility flag])
+ $1],
+ [$2])
+])
+
+AC_DEFUN([CC_FUNC_EXPECT], [
+ AC_REQUIRE([CC_CHECK_WERROR])
+ AC_CACHE_CHECK([if compiler has __builtin_expect function],
+ [cc_cv_func_expect],
+ [ac_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $cc_cv_werror"
+ AC_LANG_PUSH([C])
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+ [int some_function() {
+ int a = 3;
+ return (int)__builtin_expect(a, 3);
+ }])],
+ [cc_cv_func_expect=yes],
+ [cc_cv_func_expect=no])
+ AC_LANG_POP([C])
+ CFLAGS="$ac_save_CFLAGS"
+ ])
+
+ AS_IF([test "x$cc_cv_func_expect" = "xyes"],
+ [AC_DEFINE([SUPPORT__BUILTIN_EXPECT], 1,
+ [Define this if the compiler supports __builtin_expect() function])
+ $1],
+ [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_ALIGNED], [
+ AC_REQUIRE([CC_CHECK_WERROR])
+ AC_CACHE_CHECK([highest __attribute__ ((aligned ())) supported],
+ [cc_cv_attribute_aligned],
+ [ac_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $cc_cv_werror"
+ AC_LANG_PUSH([C])
+ for cc_attribute_align_try in 64 32 16 8 4 2; do
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+ int main() {
+ static char c __attribute__ ((aligned($cc_attribute_align_try))) = 0;
+ return c;
+ }])], [cc_cv_attribute_aligned=$cc_attribute_align_try; break])
+ done
+ AC_LANG_POP([C])
+ CFLAGS="$ac_save_CFLAGS"
+ ])
+
+ if test "x$cc_cv_attribute_aligned" != "x"; then
+ AC_DEFINE_UNQUOTED([ATTRIBUTE_ALIGNED_MAX], [$cc_cv_attribute_aligned],
+ [Define the highest alignment supported])
+ fi
+])
diff --git a/src/3rdparty/libcroco/autogen.sh b/src/3rdparty/libcroco/autogen.sh
new file mode 100755
index 0000000..8a7d049
--- /dev/null
+++ b/src/3rdparty/libcroco/autogen.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+test -n "$srcdir" || srcdir=`dirname "$0"`
+test -n "$srcdir" || srcdir=.
+
+olddir=`pwd`
+
+cd $srcdir
+
+(test -f configure.ac) || {
+ echo "*** ERROR: Directory "\`$srcdir\'" does not look like the top-level project directory ***"
+ exit 1
+}
+
+PKG_NAME=`autoconf --trace 'AC_INIT:$1' configure.ac`
+
+if [ "$#" = 0 -a "x$NOCONFIGURE" = "x" ]; then
+ echo "*** WARNING: I am going to run \`configure' with no arguments." >&2
+ echo "*** If you wish to pass any to it, please specify them on the" >&2
+ echo "*** \`$0\' command line." >&2
+ echo "" >&2
+fi
+
+aclocal --install || exit 1
+gtkdocize --copy || exit 1
+autoreconf --verbose --force --install -Wno-portability || exit 1
+
+cd $olddir
+if [ "$NOCONFIGURE" = "" ]; then
+ $srcdir/configure "$@" || exit 1
+
+ if [ "$1" = "--help" ]; then exit 0 else
+ echo "Now type \`make\' to compile $PKG_NAME" || exit 1
+ fi
+else
+ echo "Skipping configure process."
+fi
diff --git a/src/3rdparty/libcroco/config.h.win32.in b/src/3rdparty/libcroco/config.h.win32.in
new file mode 100644
index 0000000..63d5c09
--- /dev/null
+++ b/src/3rdparty/libcroco/config.h.win32.in
@@ -0,0 +1,99 @@
+/* config.h.in. Handwritten for Windows compilation with MSVC. */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the
+ * GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the
+ * GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Fan, Chun-wei
+ * See COPYRIGHTS file for copyright information.
+ */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+/*#undef HAVE_DLFCN_H*/
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#ifndef _MSC_VER
+#define HAVE_INTTYPES_H 1
+#endif
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#if (!defined(_MSC_VER) || (_MSC_VER >= 1600))
+#define HAVE_STDINT_H 1
+#endif
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#ifndef _MSC_VER
+#define HAVE_STRINGS_H 1
+#endif
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#ifndef _MSC_VER
+#define HAVE_UNISTD_H 1
+#endif
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#define LT_OBJDIR ".libs/"
+
+/* Name of package */
+#define PACKAGE "libcroco"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "http://bugzilla.gnome.org/enter_bug.cgi?product=libcroco"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "libcroco"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "libcroco @LIBCROCO_VERSION@"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "libcroco"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "@LIBCROCO_VERSION@"
+
+/* Define to 1 if the C compiler supports function prototypes. */
+#define PROTOTYPES 1
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "@LIBCROCO_VERSION@"
+
+/* Define like PROTOTYPES; this can be used by system headers. */
+#define __PROTOTYPES 1
diff --git a/src/3rdparty/libcroco/configure.ac b/src/3rdparty/libcroco/configure.ac
new file mode 100644
index 0000000..59aa072
--- /dev/null
+++ b/src/3rdparty/libcroco/configure.ac
@@ -0,0 +1,191 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.64)
+AC_INIT([libcroco],[0.6.99],[https://gitlab.com/inkscape/libcroco/-/issues],[libcroco])
+AC_CONFIG_SRCDIR([src/cr-input.c])
+AC_CANONICAL_HOST
+
+# gnu strictness to generate the INSTALL file
+AM_INIT_AUTOMAKE([1.13 tar-ustar dist-xz no-dist-gzip -Wno-portability foreign])
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+
+if test -z "$enable_maintainer_mode"; then
+ enable_maintainer_mode=yes
+fi
+AM_MAINTAINER_MODE([enable])
+
+m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
+
+LIBCROCO_MAJOR_VERSION=0
+LIBCROCO_MINOR_VERSION=6
+LIBCROCO_MICRO_VERSION=99
+
+LIBCROCO_CURRENT=3
+LIBCROCO_REVISION=1
+LIBCROCO_AGE=0
+
+#LIBCROCO_VERSION_INFO=`expr $LIBCROCO_MAJOR_VERSION + $LIBCROCO_MINOR_VERSION`:$LIBCROCO_MICRO_VERSION:$LIBCROCO_MINOR_VERSION
+LIBCROCO_VERSION_INFO="$LIBCROCO_CURRENT:$LIBCROCO_REVISION:$LIBCROCO_AGE"
+LIBCROCO_VERSION=$LIBCROCO_MAJOR_VERSION.$LIBCROCO_MINOR_VERSION.$LIBCROCO_MICRO_VERSION
+LIBCROCO_VERSION_NUMBER=`expr $LIBCROCO_MAJOR_VERSION \* 10000 + $LIBCROCO_MINOR_VERSION \* 100 + $LIBCROCO_MICRO_VERSION`
+
+AC_SUBST(LIBCROCO_MAJOR_VERSION)
+AC_SUBST(LIBCROCO_MINOR_VERSION)
+AC_SUBST(LIBCROCO_MICRO_VERSION)
+AC_SUBST(LIBCROCO_VERSION)
+AC_SUBST(LIBCROCO_VERSION_INFO)
+AC_SUBST(LIBCROCO_VERSION_NUMBER)
+AC_SUBST(LIBCROCO_CURRENT)
+AC_SUBST(LIBCROCO_AGE)
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_CPP
+AC_PROG_MAKE_SET
+AC_STDC_HEADERS
+AC_ISC_POSIX
+
+LT_INIT([])
+
+CROCO_LIB=libcroco-$LIBCROCO_MAJOR_VERSION.$LIBCROCO_MINOR_VERSION.la
+AC_SUBST(CROCO_LIB)
+
+case "$host" in
+ *-*-cygwin*|*-*-mingw*)
+ platform_win32=yes
+ ;;
+ *)
+ platform_win32=no
+ ;;
+esac
+AM_CONDITIONAL(PLATFORM_WIN32, [test "$platform_win32" = "yes"])
+
+GTK_DOC_CHECK([1.0])
+
+dnl **************************************************************
+dnl check for the different --enable-option=val
+dnl messages issued by the user
+dnl ***************************************************************
+G_DISABLE_CHECKS=0
+AC_ARG_ENABLE(checks,
+ AC_HELP_STRING([--enable-checks=yes|no],
+ [enables runtime safety checks. Default=yes]),
+ WITH_CHECKS=$enableval,
+ WITH_CHECKS="yes")
+
+if test "$WITH_CHECKS" = "no" ; then
+ G_DISABLE_CHECKS=1
+fi
+AC_SUBST(G_DISABLE_CHECKS)
+
+dnl ************************************************
+dnl end of check of the different --enable-feature options
+dnl *************************************************
+
+##############
+# Dependencies
+##############
+
+GLIB_REQUIRED=2.0
+LIBXML_REQUIRED=2.4.23
+
+PKG_CHECK_MODULES([CROCO],[
+ glib-2.0 >= $GLIB_REQUIRED
+ libxml-2.0 >= $LIBXML_REQUIRED])
+
+##########################################################
+# Check for -Bsymbolic-functions linker flag used to avoid
+# intra-library PLT jumps, if available.
+##########################################################
+
+AC_ARG_ENABLE([Bsymbolic],
+ [AS_HELP_STRING([--disable-Bsymbolic],
+ [disable linking with -Bsymbolic])],
+ [],[enable_Bsymbolic=yes])
+
+BSYMBOLIC_LDFLAG=
+if test "$enable_Bsymbolic" != "no"; then
+ CC_CHECK_LDFLAGS(["-Wl,-Bsymbolic-functions"],
+ [BSYMBOLIC_LDFLAG="-Wl,-Bsymbolic-functions"],
+ [if test "$enable_Bsymbolic" = "auto"; then
+ AC_MSG_WARN([-Bsymbolic not supported by ld; disabling])
+ enable_Bsymbolic=no
+ else
+ AC_MSG_ERROR([-Bsymbolic requested but not supported by ld. Use --disable-Bsymbolic to disable])
+ fi])
+fi
+
+AC_SUBST([BSYMBOLIC_LDFLAG])
+
+##############################################
+# Check whether MSVC toolset is explicitly set
+##############################################
+
+AM_CONDITIONAL(MSVC_BASE_NO_TOOLSET_SET, [test x$MSVC_BASE_TOOLSET = x])
+AM_CONDITIONAL(MSVC_NO_TOOLSET_SET, [test x$MSVC_TOOLSET = x])
+
+###################
+# Compiler warnings
+###################
+
+CC_CHECK_CFLAGS_APPEND([ \
+ -Wall -Wextra \
+ -Wunused -Wreturn-type -Wswitch -Wcomment -Wtrigraphs \
+ -Wchar-subscripts -Wparentheses -Winline -Wredundant-decls \
+ -Wformat-nonliteral -Werror=format-security \
+ -Wsign-compare -Werror=implicit-function-declaration \
+ -Wpointer-arith -Wwrite-strings -Wstrict-prototypes \
+ -Wcast-align -Wimplicit -Wuninitialized \
+ -Wmissing-prototypes -Wmissing-declarations -Wnested-externs \
+ -Wpacked -Wmissing-format-attribute -Wshadow \
+ -Wstrict-aliasing=2 -Winit-self -Wunsafe-loop-optimizations \
+ -Wdeclaration-after-statement -Wold-style-definition \
+ -Wno-missing-field-initializers -Wno-unused-parameter \
+ -fno-common -Wno-switch-enum])
+
+##########################################
+
+AC_OUTPUT([
+Makefile
+libcroco.pc
+libcroco.spec
+libcroco-zip
+croco-config
+config.h.win32
+win32/Makefile
+win32/vs9/Makefile
+win32/vs9/croco-version-paths.vsprops
+win32/vs10/Makefile
+win32/vs10/croco-version-paths.props
+win32/vs11/Makefile
+win32/vs12/Makefile
+win32/vs14/Makefile
+win32/vs15/Makefile
+win32/vs16/Makefile
+docs/Makefile
+docs/examples/Makefile
+docs/reference/Makefile
+tests/Makefile
+tests/test-inputs/Makefile
+tests/test-output-refs/Makefile
+global-test-vars.sh
+src/Makefile
+src/libcroco-config.h
+csslint/Makefile
+
+])
+
+dnl =======================================================================
+echo "
+ =====================================================================
+ LIBCROCO, GNOME CSS2 PARSING AND MANIPULATION TOOLKIT $VERSION
+ =====================================================================
+
+ prefix: : ${prefix}
+ source code location: : ${srcdir}
+ compiler: : ${CC}
+ cflags: : ${CFLAGS}
+
+ Maintainer mode: : ${USE_MAINTAINER_MODE}
+"
diff --git a/src/3rdparty/libcroco/croco-config.1 b/src/3rdparty/libcroco/croco-config.1
new file mode 100644
index 0000000..9418e72
--- /dev/null
+++ b/src/3rdparty/libcroco/croco-config.1
@@ -0,0 +1,37 @@
+.TH LIBCROCO 1 "20 January 2003" Version 0.1.0
+.SH NAME
+croco-config - script to get information about the installed version of LIBCROCO
+.SH SYNOPSIS
+.B croco-config
+[\-\-prefix\fI[=DIR]\fP] [\-\-libs] [\-\-cflags] [\-\-version] [\-\-help]
+.SH DESCRIPTION
+\fIcroco-config\fP is a tool used to determine the necessary flags to compile and
+link programs that uses \fILIBCROCO\fP.
+.SH OPTIONS
+.l
+\fIcroco-config\fP accepts the following options:
+.TP 8
+.B \-\-version
+Print the currently installed version of \fILIBCROCO\fP on the standard output.
+.TP 8
+.B \-\-libs
+Print the linker flags necessary to link a \fILIBCROCO\fP program.
+.TP 8
+.B \-\-cflags
+Print the compiler flags necessary to compile a \fILIBCROCO\fP program.
+.TP 8
+.B \-\-prefix=PREFIX
+If specified, use PREFIX instead of the installation prefix that
+\fILIBCROCO\fP was built with when computing the output for the
+\-\-cflags and \-\-libs options. This option must be specified before
+any \-\-libs or \-\-cflags options.
+.SH AUTHOR
+This manual page was written by Gael CHAMOULAUD (strider) <strider@freespiders.org>
+.SH REPORTING BUGS
+Please report bugs at http://bugzilla.gnome.org.
+.SH COPYRIGHT
+Copyright (C) 2002-2003 Dodji SEKETELI, Gael CHAMOULAUD.
+.br
+This is a free software; see the source for copying conditions. There is
+NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
diff --git a/src/3rdparty/libcroco/croco-config.in b/src/3rdparty/libcroco/croco-config.in
new file mode 100644
index 0000000..36ef10a
--- /dev/null
+++ b/src/3rdparty/libcroco/croco-config.in
@@ -0,0 +1,82 @@
+#! /bin/sh
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+exec_prefix_set=no
+
+usage()
+{
+ cat <<EOF
+Usage: croco-config [OPTION]...
+
+Known values for OPTION are:
+
+ --prefix=DIR change CROCO prefix [default $prefix]
+ --exec-prefix=DIR change CROCO executable prefix [default $exec_prefix]
+ --libs print library linking information
+ --cflags print pre-processor and compiler flags
+ --help display this help and exit
+ --version output version information
+EOF
+
+ exit $1
+}
+
+if test $# -eq 0; then
+ usage 1
+fi
+
+while test $# -gt 0; do
+ case "$1" in
+ -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ case "$1" in
+ --prefix=*)
+ prefix=$optarg
+ if test $exec_prefix_set = no ; then
+ exec_prefix=$optarg
+ fi
+ ;;
+
+ --prefix)
+ echo $prefix
+ ;;
+
+ --exec-prefix=*)
+ exec_prefix=$optarg
+ exec_prefix_set=yes
+ ;;
+
+ --exec-prefix)
+ echo $exec_prefix
+ ;;
+
+ --version)
+ echo @VERSION@
+ exit 0
+ ;;
+
+ --help)
+ usage 0
+ ;;
+
+ --cflags)
+ echo @CROCO_CFLAGS@ @GLIB2_CFLAGS@ @LIBXML2_CFLAGS@
+ ;;
+
+ --libs)
+ echo @CROCO_LIBS@ @GLIB2_LIBS@ @LIBXML2_LIBS@
+ ;;
+
+ *)
+ usage
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+
+exit 0
diff --git a/src/3rdparty/libcroco/csslint/CMakeLists.txt b/src/3rdparty/libcroco/csslint/CMakeLists.txt
new file mode 100644
index 0000000..8f125c8
--- /dev/null
+++ b/src/3rdparty/libcroco/csslint/CMakeLists.txt
@@ -0,0 +1,16 @@
+set(csslint_EXE csslint)
+
+add_executable(${csslint_EXE} csslint.c)
+
+target_include_directories(${csslint_EXE}
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/src
+ ${CMAKE_BINARY_DIR}/src
+ ${GLIB_INCLUDE_DIRS}
+ ${LIBXML_INCLUDE_DIRS}
+)
+
+target_link_libraries(${csslint_EXE}
+ PRIVATE
+ croco_LIB
+)
diff --git a/src/3rdparty/libcroco/csslint/ChangeLog b/src/3rdparty/libcroco/csslint/ChangeLog
new file mode 100644
index 0000000..b7b1df6
--- /dev/null
+++ b/src/3rdparty/libcroco/csslint/ChangeLog
@@ -0,0 +1,29 @@
+2004-01-27 Gael CHAMOULAUD <strider@gnome.org>
+
+ * csslint/csslint.c: (csslint_show_version): Made smallish cleanup
+
+2003-06-28 Gaël Chamoulaud <strider@freespiders.org>
+
+ * csslint.c (csslint_show_version): Added CROCO_LAYENG_ENABLED test
+ in csslint_show_version function.
+
+2003-04-02 Gaël Chamoulaud <strider@freespiders.org>
+
+ * csslint.1: updated man page
+
+2003-03-24 Gaël Chamoulaud <strider@freespiders.org>
+
+ * csslint.c (csslint_usage): Added the ability to parse
+ a CSS file and builds a CSS object model.
+ * csslint.1: updated csslint man page
+
+
+2003-03-23 Gaël Chamoulaud <strider@freespiders.org>
+
+ * Makefile.am (AM_CFLAGS): added a man page for csslint program.
+
+ * csslint.1: added a man page for csslint program.
+
+ * csslint.c: initialized the csslint program. A command CSS
+ parser tool for LIBCRCCO.
+
diff --git a/src/3rdparty/libcroco/csslint/Makefile.am b/src/3rdparty/libcroco/csslint/Makefile.am
new file mode 100644
index 0000000..3969962
--- /dev/null
+++ b/src/3rdparty/libcroco/csslint/Makefile.am
@@ -0,0 +1,18 @@
+bin_PROGRAMS = csslint-0.6
+#man_MANS = csslint.1
+
+csslint_0_6_SOURCES = csslint.c
+
+croco_lib = $(top_builddir)/src/@CROCO_LIB@
+
+csslint_0_6_LDADD = $(croco_lib)
+
+csslint_0_6_CPPFLAGS = \
+ -I$(top_srcdir)/intl \
+ -I$(top_srcdir)/src \
+ -I$(top_builddir)/src \
+ $(CROCO_CFLAGS)
+
+csslint_0_6_LDFLAGS=$(CROCO_LIBS)
+
+#EXTRA_DIST = $(man_MANS)
diff --git a/src/3rdparty/libcroco/csslint/csslint.1 b/src/3rdparty/libcroco/csslint/csslint.1
new file mode 100644
index 0000000..a4c76a0
--- /dev/null
+++ b/src/3rdparty/libcroco/csslint/csslint.1
@@ -0,0 +1,64 @@
+.\"Generated by db2man.xsl. Don't modify this, modify the source.
+.de Sh \" Subsection
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Ip \" List item
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.TH "CSSLINT" 1 "" "" "csslint Manual"
+.SH NAME
+csslint \- command line CSS tool
+.SH "SYNOPSIS"
+
+.nf
+\fBcsslint\fR [\fB--version\fR | \fB--cssom\fR]
+.fi
+
+.SH "INTRODUCTION"
+
+.PP
+The csslint program parses one or more CSS files, specified on the command line as \fIcssfile\fR\&. It prints various types of output, depending upon the options selected\&. It is useful for detecting errors both in CSS code and in the CSS parser itself\&.
+
+.PP
+It is included in libcroco\&.
+
+.SH "OPTIONS"
+
+.TP
+\fB--version\fR
+Display the version of libcroco used\&.
+
+.TP
+\fB--cssom\fR
+parse a CSS file and builds a CSS object model\&.
+
+.SH AUTHOR
+Written by Gael CHAMOULAUD (strider) <strider@freespiders.org>
+
+.SH REPORTING BUGS
+Please report bugs at http://bugzilla.gnome.org.
+
+.SH COPYRIGHT
+Copyright (C) 2002-2003 Dodji SEKETELI, Gael CHAMOULAUD.
+.br
+This is a free software; see the source for copying conditions. There is
+NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE.
+
+.SH SEE ALSO
+.br
+croco-config (1)
+
+
diff --git a/src/3rdparty/libcroco/csslint/csslint.c b/src/3rdparty/libcroco/csslint/csslint.c
new file mode 100644
index 0000000..3495eff
--- /dev/null
+++ b/src/3rdparty/libcroco/csslint/csslint.c
@@ -0,0 +1,1011 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * csslint.c : a small tester program for libcroco.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Initial Author: Gael Chamoulaud.
+ * Main programmer: Dodji Seketeli
+ * Contributor: Rob Buis
+ * See COPYRGIGHTS file for copyright information.
+ */
+
+#include "libcroco.h"
+#include "cr-libxml-node-iface.h"
+#include <libxml/xpath.h>
+
+#include <glib.h>
+#include <string.h>
+
+/**
+ *The options data structure.
+ *The variable of this data structure are set
+ *during the parsing the command line by the
+ *parse_command_line() function.
+ */
+struct Options {
+ gboolean show_version;
+ gboolean use_cssom;
+ gboolean display_help;
+ gboolean evaluate;
+ gboolean dump_location;
+ gchar *author_sheet_path;
+ gchar *user_sheet_path;
+ gchar *ua_sheet_path;
+ gchar *xml_path;
+ gchar *xpath;
+ gchar **css_files_list;
+};
+
+struct SacContext {
+ gint level;
+
+};
+
+static enum CRStatus sac_parse_and_display_locations (guchar * a_file_uri);
+
+static void parse_cmd_line (int a_argc, char **a_argv,
+ struct Options *a_options);
+
+static void display_version (void);
+
+static void display_usage (void);
+
+static enum CRStatus cssom_parse (guchar * a_file_uri);
+
+static enum CRStatus get_and_dump_node_style (xmlNode * a_node,
+ CRSelEng * a_sel_eng,
+ CRCascade * a_cascade);
+
+static enum CRStatus evaluate_selectors (gchar * a_xml_path,
+ gchar * a_author_sheet_path,
+ gchar * a_user_sheet_path,
+ gchar * a_ua_sheet_path,
+ gchar * a_xpath);
+
+/**
+ *Parses the command line.
+ *@param a_argc the argc parameter of the main routine.
+ *@param the argv parameter of the main routine.
+ *@param a_options out parameter the parsed options.
+ */
+static void
+parse_cmd_line (int a_argc, char **a_argv, struct Options *a_options)
+{
+ int i = 0;
+
+ g_return_if_fail (a_options);
+
+ if (a_argc <= 1) {
+ display_usage ();
+ }
+
+ for (i = 1; i < a_argc; i++) {
+ if (a_argv[i][0] != '-')
+ break;
+
+ if ((!strcmp (a_argv[i], "-version")) ||
+ (!strcmp (a_argv[i], "-v"))) {
+ a_options->show_version = TRUE;
+ } else if (!strcmp (a_argv[i], "--evaluate") ||
+ !strcmp (a_argv[i], "-e")) {
+ for (i++; i < a_argc; i++) {
+ if (!strcmp (a_argv[i], "--author-sheet")) {
+ if (a_options->author_sheet_path) {
+ display_usage ();
+ exit (-1);
+ }
+ i++;
+ if (i >= a_argc
+ || a_argv[i][0] == '-') {
+ g_print ("--author-sheet should be followed by a path to the sheet\n");
+ display_usage ();
+ exit (-1);
+ }
+ a_options->author_sheet_path =
+ a_argv[i];
+ } else if (!strcmp
+ (a_argv[i], "--user-sheet")) {
+ if (a_options->user_sheet_path) {
+ display_usage ();
+ exit (-1);
+ }
+ i++;
+ if (i >= a_argc
+ || a_argv[i][0] == '-') {
+ g_print ("--user-sheet should be followed by a path to the sheet\n");
+ display_usage ();
+ exit (-1);
+ }
+ a_options->user_sheet_path =
+ a_argv[i];
+ } else if (!strcmp (a_argv[i], "--ua-sheet")) {
+ if (a_options->ua_sheet_path) {
+ display_usage ();
+ exit (-1);
+ }
+ i++;
+ if (i >= a_argc
+ || a_argv[i][0] == '-') {
+ g_print ("--ua-sheet should be followed by a path to the sheet\n");
+ display_usage ();
+ exit (-1);
+ }
+ a_options->ua_sheet_path = a_argv[i];
+ } else if (!strcmp (a_argv[i], "--xml")) {
+ i++;
+ if (i >= a_argc
+ || a_argv[i][0] == '-') {
+ g_print ("--xml should be followed by a path to the xml document\n");
+ display_usage ();
+ exit (-1);
+ }
+ a_options->xml_path = a_argv[i];
+ } else if (!strcmp (a_argv[i], "--xpath")) {
+ i++;
+ if (i >= a_argc
+ || a_argv[i][0] == '-') {
+ g_print ("--xpath should be followed by an xpath expression\n");
+ display_usage ();
+ exit (-1);
+ }
+ a_options->xpath = a_argv[i];
+ } else {
+ break;
+ }
+ }
+ if (!a_options->author_sheet_path
+ && !a_options->user_sheet_path &&
+ !a_options->ua_sheet_path) {
+ g_print ("Error: you must specify at least one stylesheet\n");
+ display_usage ();
+ exit (-1);
+
+ }
+ if (!a_options->xpath) {
+ g_printerr
+ ("Error: you must specify an xpath expression using the --xpath option\n");
+ display_usage ();
+ exit (-1);
+
+ }
+ a_options->evaluate = TRUE;
+ } else if (!strcmp (a_argv[i], "--dump-location")) {
+ a_options->dump_location = TRUE;
+ a_options->use_cssom = FALSE;
+ } else if (!strcmp (a_argv[i], "--help") ||
+ !strcmp (a_argv[i], "-h")) {
+ a_options->display_help = TRUE;
+ } else {
+ display_usage ();
+ exit (-1);
+ }
+ }
+
+ if (i >= a_argc) {
+ a_options->css_files_list = NULL;
+ } else {
+ if (a_argv[i][0] == '-') {
+ display_usage ();
+ exit (-1);
+ }
+ a_options->css_files_list = &a_argv[i];
+ }
+}
+
+/**
+ *Displays the version text.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_version (void)
+{
+ g_print ("%s\n", LIBCROCO_VERSION);
+}
+
+/**
+ *Displays the usage text.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_usage (void)
+{
+ g_print ("Usage: csslint <path to a css file>\n");
+ g_print ("\t| csslint -v|--version\n");
+ g_print ("\t| csslint --dump-location <path to a css file>\n");
+ g_print ("\t| csslint <--evaluate | -e> [--author-sheet <path> --user-sheet <path> --ua-sheet <path>\n\t ] --xml <path> --xpath <xpath expression>\n");
+}
+
+/**
+ *The test of the cr_input_read_byte() method.
+ *Reads the each byte of a_file_uri using the
+ *cr_input_read_byte() method. Each byte is send to
+ *stdout.
+ *@param a_file_uri the file to read.
+ *@return CR_OK upon successful completion of the
+ *function, an error code otherwise.
+ */
+static enum CRStatus
+cssom_parse (guchar * a_file_uri)
+{
+ enum CRStatus status = CR_OK;
+ CROMParser *parser = NULL;
+ CRStyleSheet *stylesheet = NULL;
+
+ g_return_val_if_fail (a_file_uri, CR_BAD_PARAM_ERROR);
+
+ parser = cr_om_parser_new (NULL);
+ status = cr_om_parser_parse_file (parser,
+ a_file_uri, CR_ASCII, &stylesheet);
+ if (status == CR_OK && stylesheet) {
+ cr_stylesheet_dump (stylesheet, stdout);
+ g_print ("\n");
+ cr_stylesheet_destroy (stylesheet);
+ }
+ cr_om_parser_destroy (parser);
+
+ return status;
+}
+
+static enum CRStatus
+get_and_dump_node_style (xmlNode * a_node,
+ CRSelEng * a_sel_eng, CRCascade * a_cascade)
+{
+ CRPropList *prop_list = NULL,
+ *pair = NULL,
+ *prev_pair = NULL;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_node && a_sel_eng && a_cascade,
+ CR_BAD_PARAM_ERROR);
+
+ status = cr_sel_eng_get_matched_properties_from_cascade
+ (a_sel_eng, a_cascade, a_node, &prop_list);
+ if (status != CR_OK) {
+ g_printerr ("Error: unable to run the selection engine\n");
+ return CR_OK;
+ }
+ g_print ("Properties of xml element %s are:\n", a_node->name);
+ for (pair = prop_list; pair; pair = cr_prop_list_get_next (pair)) {
+ CRDeclaration *decl = NULL;
+
+ cr_prop_list_get_decl (pair, &decl);
+ if (decl) {
+ prev_pair = cr_prop_list_get_prev (pair);
+ if (prev_pair) {
+ g_print ("\n");
+ prev_pair = NULL;
+ }
+ cr_declaration_dump_one (decl, stdout, 2);
+ decl = NULL;
+ }
+ }
+ g_print ("\n=====================\n\n");
+
+ if (prop_list) {
+ cr_prop_list_destroy (prop_list);
+ prop_list = NULL;
+ }
+
+ return CR_OK;
+}
+
+static enum CRStatus
+evaluate_selectors (gchar * a_xml_path,
+ gchar * a_author_sheet_path,
+ gchar * a_user_sheet_path,
+ gchar * a_ua_sheet_path, gchar * a_xpath)
+{
+ CRSelEng *sel_eng = NULL;
+ xmlDoc *xml_doc = NULL;
+ xmlXPathContext *xpath_context = NULL;
+ xmlXPathObject *xpath_object = NULL;
+ CRStyleSheet *author_sheet = NULL,
+ *user_sheet = NULL,
+ *ua_sheet = NULL;
+ CRCascade *cascade = NULL;
+ xmlNode *cur_node = NULL;
+ gint i = 0;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_xml_path && a_xpath, CR_BAD_PARAM_ERROR);
+
+ xml_doc = xmlParseFile (a_xml_path);
+ if (!xml_doc) {
+ g_printerr ("Error: Could not parse file %s\n", a_xml_path);
+ status = CR_ERROR;
+ goto end;
+ }
+ if (a_author_sheet_path) {
+ status = cr_om_parser_simply_parse_file
+ ((const guchar *) a_author_sheet_path, CR_ASCII, &author_sheet);
+ if (!author_sheet) {
+ g_printerr ("Error: Could not parse author sheet\n");
+ }
+ }
+ if (a_user_sheet_path) {
+ status = cr_om_parser_simply_parse_file
+ ((const guchar *) a_user_sheet_path, CR_ASCII, &user_sheet);
+ if (!user_sheet) {
+ g_printerr ("Error: Could not parse author sheet\n");
+ }
+ }
+ if (a_ua_sheet_path) {
+ status = cr_om_parser_simply_parse_file
+ ((const guchar *) a_ua_sheet_path, CR_ASCII, &ua_sheet);
+ if (!ua_sheet) {
+ g_printerr ("Error: Could not parse ua sheet\n");
+ }
+ }
+ cascade = cr_cascade_new (author_sheet, user_sheet, ua_sheet);
+
+ if (author_sheet)
+ cr_stylesheet_unref (author_sheet);
+
+ if (user_sheet)
+ cr_stylesheet_unref (user_sheet);
+
+ if (ua_sheet)
+ cr_stylesheet_unref (ua_sheet);
+
+ if (!cascade) {
+ g_printerr ("Could not instantiate the cascade\n");
+ status = CR_ERROR;
+ goto end;
+ }
+ sel_eng = cr_sel_eng_new (&cr_libxml_node_iface);
+ if (!sel_eng) {
+ g_printerr
+ ("Error: Could not instantiate the selection engine\n");
+ status = CR_ERROR;
+ goto end;
+ }
+ xpath_context = xmlXPathNewContext (xml_doc);
+ if (!xpath_context) {
+ g_printerr
+ ("Error: Could not instantiate the xpath context\n");
+ status = CR_ERROR;
+ goto end;
+ }
+ xpath_object = xmlXPathEvalExpression ((const xmlChar *) a_xpath, xpath_context);
+ if (!xpath_object) {
+ g_printerr ("Error: Could not evaluate xpath expression\n");
+ status = CR_ERROR;
+ goto end;
+ }
+ if (xpath_object->type != XPATH_NODESET || !xpath_object->nodesetval) {
+ g_printerr
+ ("Error: xpath does not evalualuate to a node set\n");
+ status = CR_ERROR;
+ goto end;
+ }
+
+ for (i = 0; i < xpath_object->nodesetval->nodeNr; i++) {
+ cur_node = xpath_object->nodesetval->nodeTab[i];
+ if (cur_node->type == XML_ELEMENT_NODE) {
+ status = get_and_dump_node_style (cur_node, sel_eng,
+ cascade);
+ }
+ }
+
+ end:
+
+ if (xpath_context) {
+ xmlXPathFreeContext (xpath_context);
+ xpath_context = NULL;
+ }
+ if (xpath_object) {
+ xmlXPathFreeObject (xpath_object);
+ xpath_object = NULL;
+ }
+ if (sel_eng) {
+ cr_sel_eng_destroy (sel_eng);
+ sel_eng = NULL;
+ }
+ if (cascade) {
+ cr_cascade_destroy (cascade);
+ cascade = NULL;
+ }
+ if (xml_doc) {
+ xmlFreeDoc (xml_doc);
+ xml_doc = NULL;
+ }
+
+ return status;
+}
+
+/***************************
+ *SAC related stuff for the
+ *line/col annotation stylesheet
+ *dumping
+ ***************************/
+static void
+start_document (CRDocHandler * a_this)
+{
+ struct SacContext *context = NULL;
+
+ g_return_if_fail (a_this);
+
+ context = g_try_malloc (sizeof (struct SacContext));
+ if (!context) {
+ cr_utils_trace_info ("instantiation of sac context failed");
+ return;
+ }
+ cr_doc_handler_set_ctxt (a_this, context);
+}
+
+static void
+end_document (CRDocHandler * a_this)
+{
+ struct SacContext *context = NULL;
+
+ g_return_if_fail (a_this);
+
+ cr_doc_handler_get_ctxt (a_this, (gpointer *) (gpointer) & context);
+ if (context) {
+ g_free (context);
+ context = NULL;
+ }
+}
+
+static void
+charset (CRDocHandler *a_this,
+ CRString *a_charset,
+ CRParsingLocation *a_charset_sym_location)
+{
+ gchar *str = NULL ;
+
+ g_return_if_fail (a_this && a_charset && a_charset_sym_location) ;
+
+ str = (gchar*)cr_string_peek_raw_str (a_charset) ;
+ if (str) {
+ g_print ("\n\n@charset \"%s\";\n\n", str) ;
+ str = NULL ;
+ } else {
+ return ;
+ }
+ g_print ("/********************************************\n") ;
+ g_print (" * Parsing location information of the @charset rule\n") ;
+ g_print (" ********************************************/\n") ;
+ if (a_charset_sym_location) {
+ str = cr_parsing_location_to_string (a_charset_sym_location, 0) ;
+ if (str) {
+ g_print (" /*@charset*/\n") ;
+ g_print (" /*%s*/\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ }
+ str = (gchar*) cr_string_peek_raw_str (a_charset) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ str = NULL ;
+ }
+ str = cr_parsing_location_to_string (&a_charset->location, 0) ;
+ if (str) {
+ g_print (" /*%s*/\n\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+}
+
+static void
+import_style (CRDocHandler *a_this,
+ GList *a_media_list,
+ CRString *a_uri,
+ CRString *a_uri_default_ns,
+ CRParsingLocation *a_location)
+{
+ gchar *str = NULL ;
+ GString *gstr = NULL ;
+ GList *cur_media = NULL ;
+
+ g_return_if_fail (a_this && a_location) ;
+
+ gstr = g_string_new (NULL) ;
+ if (!gstr) {
+ cr_utils_trace_info ("Out of memory error") ;
+ return ;
+ }
+ for (cur_media = a_media_list ;
+ cur_media ;
+ cur_media = g_list_next (cur_media)) {
+ str = (gchar*)cr_string_peek_raw_str
+ ((CRString*)cur_media->data) ;
+ if (str) {
+ if (g_list_previous (cur_media)) {
+ g_string_append_printf (gstr, ", %s",
+ str) ;
+ } else {
+ g_string_append_printf (gstr, "%s",
+ str) ;
+ }
+ }
+ }
+ str = (gchar*)cr_string_peek_raw_str (a_uri) ;
+ if (str) {
+ g_print ("@import url(\"%s\") ", str) ;
+ if (gstr) {
+ g_print ("%s;\n\n", gstr->str) ;
+ }
+ str = NULL ;
+ }
+ str = cr_parsing_location_to_string (a_location, 0) ;
+ if (str) {
+ g_print ("/*****************************************************\n") ;
+ g_print (" *Parsing location information for the @import rule\n") ;
+ g_print (" ******************************************************/\n\n") ;
+ g_print (" /*@import*/\n") ;
+ g_print (" /*%s*/\n\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+
+ str = (gchar*)cr_string_peek_raw_str (a_uri) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ str = cr_parsing_location_to_string
+ (&a_uri->location, 0) ;
+ if (str) {
+ g_print (" /*%s*/\n\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ }
+
+ for (cur_media = a_media_list ;
+ cur_media ;
+ cur_media = g_list_next (cur_media)) {
+ str = (gchar*)cr_string_peek_raw_str
+ ((CRString*)cur_media->data) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ }
+ str = cr_parsing_location_to_string
+ (&((CRString*)cur_media->data)->location, 0) ;
+ if (str) {
+ g_print (" /*%s*/\n\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ }
+
+ if (gstr) {
+ g_string_free (gstr, TRUE) ;
+ gstr = NULL ;
+ }
+}
+
+static void
+start_font_face (CRDocHandler *a_this,
+ CRParsingLocation *a_location)
+{
+ gchar *str = NULL ;
+
+ g_print ("@font-face {\n") ;
+ g_print ("/******************************************************\n") ;
+ g_print (" Parsing location information for the @font-face rule\n") ;
+ g_print (" ******************************************************/\n\n") ;
+
+ g_print (" /*@font-face*/\n") ;
+ if (a_location) {
+ str = cr_parsing_location_to_string (a_location, 0) ;
+ }
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+}
+
+static void
+end_font_face (CRDocHandler *a_this)
+{
+ g_print ("}\n") ;
+}
+
+static void
+start_media (CRDocHandler *a_this,
+ GList *a_media_list,
+ CRParsingLocation *a_location)
+{
+ GList *cur_media = NULL ;
+ gchar *str = NULL ;
+
+ g_print ("@media ") ;
+ for (cur_media = a_media_list ;
+ cur_media ;
+ cur_media = g_list_next (cur_media)) {
+ CRString *crstr = cur_media->data ;
+ if (crstr) {
+ str = (gchar*)cr_string_peek_raw_str (crstr) ;
+ if (str) {
+ if (cur_media->prev) {
+ g_print (", %s", str) ;
+ } else {
+ g_print ("%s", str) ;
+ }
+ }
+ }
+ }
+ /*****************************
+ *new print parsing locations
+ *****************************/
+ g_print ("\n /*@media*/\n") ;
+ if (a_location)
+ str = cr_parsing_location_to_string (a_location,
+ 0) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ for (cur_media = a_media_list ;
+ cur_media ;
+ cur_media = g_list_next (cur_media)) {
+ CRString *crstr = cur_media->data ;
+ if (crstr) {
+ str = (gchar*)cr_string_peek_raw_str (crstr) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ str = cr_parsing_location_to_string
+ (&crstr->location, 0) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ }
+ }
+ }
+ g_print ("\n{\n") ;
+}
+
+static void
+end_media (CRDocHandler *a_this,
+ GList *a_media_list)
+{
+ g_print ("\n}\n") ;
+}
+
+static void
+start_page (CRDocHandler *a_this,
+ CRString *a_name,
+ CRString *a_pseudo_page,
+ CRParsingLocation *a_location)
+{
+ gchar *str = NULL ;
+
+ g_print ("@page ") ;
+ if (a_name)
+ str = (gchar*)cr_string_peek_raw_str (a_name) ;
+ if (str) {
+ g_print ("%s ", str) ;
+ }
+ if (a_pseudo_page)
+ str = (gchar*) cr_string_peek_raw_str (a_pseudo_page) ;
+ if (str) {
+ g_print (":%s", str) ;
+ str = NULL ;
+ }
+ /*************************************
+ *print parsing location information
+ ************************************/
+ g_print ("\n\n /*@page*/\n") ;
+ if (a_location)
+ str = cr_parsing_location_to_string
+ (a_location, 0) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ if (a_name)
+ str = (gchar*)cr_string_peek_raw_str (a_name) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ str = cr_parsing_location_to_string
+ (&a_name->location, 0) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ }
+ if (a_pseudo_page)
+ str = (gchar*) cr_string_peek_raw_str
+ (a_pseudo_page) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ str = cr_parsing_location_to_string
+ (&a_pseudo_page->location, 0) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ }
+ g_print ("\n{\n") ;
+}
+
+static void
+end_page (CRDocHandler *a_this,
+ CRString *a_name,
+ CRString *pseudo_page)
+{
+ g_print ("}\n") ;
+}
+
+static void
+dump_location_annotated_simple_sel (CRSimpleSel *a_this)
+{
+ CRSimpleSel *cur_simple_sel = a_this ;
+ CRAdditionalSel *cur_add_sel = NULL ;
+ gchar *str0 = NULL ;
+
+ g_return_if_fail (a_this) ;
+
+ /*first, display the entire simple sel*/
+ str0 = (gchar *) cr_simple_sel_one_to_string
+ (cur_simple_sel) ;
+ if (str0) {
+ g_print ("/*%s*/\n", str0) ;
+ g_free (str0) ;
+ str0 = NULL ;
+ }
+ g_print ("/*") ;
+ cr_parsing_location_dump
+ (&cur_simple_sel->location, 0,
+ stdout);
+ g_print ("*/\n") ;
+
+ /*now display the details of the simple sel*/
+ if (cur_simple_sel->name) {
+ str0 = (gchar*) cr_string_peek_raw_str
+ (cur_simple_sel->name) ;
+ if (str0) {
+ g_print (" /*%s*/\n", str0) ;
+ str0 = NULL ;
+ }
+ str0 = cr_parsing_location_to_string
+ (&cur_simple_sel->name->location,
+ 0) ;
+ if (str0) {
+ g_print (" /*%s*/\n", str0) ;
+ g_free (str0) ;
+ str0 = NULL ;
+ }
+ }
+ for (cur_add_sel = cur_simple_sel->add_sel;
+ cur_add_sel;
+ cur_add_sel = cur_add_sel->next) {
+ str0 = (gchar *) cr_additional_sel_one_to_string
+ (cur_add_sel) ;
+ if (str0) {
+ g_print ("\n /*%s*/\n", str0) ;
+ g_free (str0) ;
+ str0 = NULL ;
+ }
+ str0 = cr_parsing_location_to_string
+ (&cur_add_sel->location, 0) ;
+ if (str0) {
+ g_print (" /*%s*/\n", str0) ;
+ g_free (str0) ;
+ str0 = NULL ;
+ }
+ }
+}
+
+static void
+start_selector (CRDocHandler * a_this, CRSelector * a_selector_list)
+{
+ struct SacContext *context = NULL;
+ CRSelector *cur_sel = NULL ;
+ CRSimpleSel *cur_simple_sel = NULL ;
+
+ g_return_if_fail (a_this);
+
+ cr_doc_handler_get_ctxt (a_this, (gpointer *) (gpointer) & context);
+ if (context) {
+ context->level++;
+ }
+ cr_selector_dump (a_selector_list, stdout);
+ g_print (" {\n") ;
+ g_print ("/************************************************\n") ;
+ g_print (" *Parsing location information of the selector\n") ;
+ g_print (" ************************************************/\n") ;
+
+ for (cur_sel = a_selector_list;
+ cur_sel ;
+ cur_sel = cur_sel->next) {
+ for (cur_simple_sel = cur_sel->simple_sel ;
+ cur_simple_sel ;
+ cur_simple_sel = cur_simple_sel->next) {
+
+ dump_location_annotated_simple_sel
+ (cur_simple_sel) ;
+ }
+ }
+}
+
+static void
+end_selector (CRDocHandler * a_this,
+ CRSelector *a_selector_list)
+{
+ struct SacContext *context = NULL;
+
+ g_return_if_fail (a_this);
+
+ cr_doc_handler_get_ctxt (a_this, (gpointer *) (gpointer) & context);
+ if (context) {
+ context->level--;
+ }
+ g_print (" }\n") ;
+}
+
+static void
+property (CRDocHandler *a_this,
+ CRString *a_name,
+ CRTerm *a_expr,
+ gboolean a_is_important)
+{
+ gchar *str = NULL ;
+ CRTerm *cur_term = NULL ;
+
+ str = (gchar*) cr_string_peek_raw_str (a_name) ;
+ if (str) {
+ g_print ("\n\n") ;
+ g_print ("%s", str) ;
+ str = NULL ;
+ if (a_expr) {
+ str = (gchar *) cr_term_to_string (a_expr) ;
+ if (str) {
+ g_print (" : %s;\n\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ } else {
+ g_print (";\n\n") ;
+ }
+ }
+
+ /*Now dump each part of the property declaration*/
+
+ g_print ("\n") ;
+ g_print ("/************************************************\n") ;
+ g_print (" *Parsing location information of the property\n") ;
+ g_print (" ************************************************/\n") ;
+
+ str = (gchar*) cr_string_peek_raw_str (a_name) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ str = NULL ;
+ }
+ str = cr_parsing_location_to_string (&a_name->location, 0) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+
+ for (cur_term = a_expr ;
+ cur_term;
+ cur_term = cur_term->next) {
+ str = (gchar *) cr_term_one_to_string (cur_term) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ str = cr_parsing_location_to_string
+ (&cur_term->location, 0) ;
+ if (str) {
+ g_print (" /*%s*/\n", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ }
+}
+
+
+static enum CRStatus
+sac_parse_and_display_locations (guchar * a_file_uri)
+{
+ enum CRStatus status = CR_OK;
+ CRDocHandler *sac_handler = NULL;
+ CRParser *parser = NULL;
+
+ g_return_val_if_fail (a_file_uri, CR_BAD_PARAM_ERROR);
+
+ parser = cr_parser_new_from_file (a_file_uri, CR_UTF_8);
+ if (!parser) {
+ cr_utils_trace_info ("parser instantiation failed");
+ return CR_ERROR;
+ }
+ sac_handler = cr_doc_handler_new ();
+ if (!sac_handler) {
+ cr_utils_trace_info ("sac handler instantiation failed");
+ status = CR_OUT_OF_MEMORY_ERROR;
+ goto cleanup;
+ }
+ sac_handler->start_document = start_document ;
+ sac_handler->end_document = end_document ;
+ sac_handler->charset = charset ;
+ sac_handler->import_style = import_style ;
+ sac_handler->start_font_face = start_font_face ;
+ sac_handler->end_font_face = end_font_face ;
+ sac_handler->start_media = start_media ;
+ sac_handler->end_media = end_media ;
+ sac_handler->start_page = start_page ;
+ sac_handler->end_page = end_page ;
+ sac_handler->start_selector = start_selector;
+ sac_handler->end_selector = end_selector;
+ sac_handler->property = property ;
+
+ cr_parser_set_sac_handler (parser, sac_handler) ;
+ status = cr_parser_parse (parser) ;
+
+ cleanup:
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ }
+ return status;
+}
+
+int
+main (int argc, char **argv)
+{
+ struct Options options;
+ enum CRStatus status = CR_OK;
+
+ memset (&options, 0, sizeof (struct Options));
+ options.use_cssom = TRUE;
+ parse_cmd_line (argc, argv, &options);
+
+ if (options.show_version == TRUE) {
+ display_version ();
+ return 0;
+ }
+
+ if (options.display_help == TRUE) {
+ display_usage ();
+ return 0;
+ }
+ if (options.use_cssom == TRUE) {
+ if (options.evaluate == TRUE) {
+ status = evaluate_selectors
+ (options.xml_path,
+ options.author_sheet_path,
+ options.user_sheet_path,
+ options.ua_sheet_path, options.xpath);
+ } else if (options.css_files_list != NULL) {
+ status = cssom_parse ((guchar *) options.css_files_list[0]);
+ }
+ } else if (options.dump_location == TRUE) {
+ if (options.css_files_list) {
+ status = sac_parse_and_display_locations
+ ((guchar *) options.css_files_list[0]) ;
+ } else {
+ display_usage () ;
+ return -1 ;
+ }
+ }
+
+ return (status == CR_OK) ? 0 : -2;
+}
diff --git a/src/3rdparty/libcroco/docs/Makefile.am b/src/3rdparty/libcroco/docs/Makefile.am
new file mode 100644
index 0000000..ece8c4b
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS=examples reference
+
+EXTRA_DIST=usage.txt
diff --git a/src/3rdparty/libcroco/docs/design/parser-architecture.txt b/src/3rdparty/libcroco/docs/design/parser-architecture.txt
new file mode 100644
index 0000000..67b7713
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/design/parser-architecture.txt
@@ -0,0 +1,146 @@
+Libcroco parser architecture
+-----------------------------
+
+Author: Dodji Seketeli <dodji@seketeli.org>
+
+$Id$
+
+I) Forethoughts.
+===================
+
+Libcroco's parser is a simple recursive descent parser.
+The major design focus has been simplicity, reliability and
+conformance.
+
+Simplicity
+-----------
+We want the code to be maintainable by anyone who knows the CSS spec
+and who knows how to code in C. Therefore, we avoid to overuse
+the C preprocessor magic and all the tricks that tend to turn C into
+a maintenance nightmare.
+
+We also try to adhere to the Gnome coding guidelines specified
+at http://developer.gnome.org/doc/guides/programming-guidelines.
+
+
+Reliability
+-----------
+Each single function of the libcroco library should never crash,
+and this, whatever the arguments it takes.
+As a consequence we tend to be paranoid when it comes to check
+pointers values before dereferencing them for example...
+
+Conformance
+-----------
+We try to stick to the CSS spec. We know this is almost impossible to achieve
+given the resources we have but we think it is a sane target to chase.
+
+II) Overall architecture
+=========================
+The parser is organized around several main classes:
+
+1/ CRInput
+2/ CRTknzr (Tokenizer or lexer)
+3/ CRParser
+4/ CROMParser
+
+II.1 The CRInput class
+-----------------------
+The CRInput class provides the abstraction of
+an utf8-encoded character stream.
+
+Ideally, it should abstract local data sources
+(local files and in-memory buffers)
+and remote data sources (sockets, url-identified resources) but for the
+moment, it can only abstract local data sources.
+
+Adding a new type of data source should be transparent for the
+classes that already use CRInput. After all, this is what abstraction is about :)
+
+
+II.2 The CRTknzr class
+----------------------
+The main job of the tokenizer (or lexer) is to
+provide a get_next_token() method.
+This methods returns the next CSS token found in the input stream.
+(Note that the input stream here is an instance of CRInput).
+
+This provides an extremely useful facility to the parser.
+
+II.3 The CRParser class
+-------------------------
+The core of the parser.
+
+The main job of this class is to provide a cr_parser_parse_stylesheet()
+method. During the parsing (the execution of the cr_parser_stylesheet())
+the parser sends events to notify the application when it encounters
+remarkable CSS constructions. This is the SAC (Simple API for CSS) API model.
+
+To achieve that task, almost each production of the CSS grammar
+has a matching parsing function (or method) in this class.
+
+For example, the following production named "ruleset" (specified in the
+CSS2 spec in appendix D.1):
+
+ruleset : selector [ ',' S* selector ]*
+ '{' S* declaration [ ';' S* declaration ]* '}' S*
+
+is "implemented" by the cr_parser_parse_ruleset() method.
+
+The same thing applies for the "selector" production:
+
+selector : simple_selector [ combinator simple_selector ]*
+
+which is implemented by the cr_parser_parse_selector() method... and so on
+and so forth.
+
+II.3.1 Structure of a parsing method.
+-------------------------------------
+A parsing method (e.g cr_parser_parse_ruleset()) is there
+to:
+
+ * try to recognize a substring of the incoming character string
+ as something that matches a given CSS grammar production.
+
+ e.g: the job of the cr_parser_parse_ruleset() is to try
+ to recognize if "what" comes next in the input stream
+ is a CSS2 "ruleset".
+
+ * build a basic abstract data structure to
+ store the information encountered
+ during the parsing of the current character string.
+
+ eg: cr_parser_parse_declaration() has the following prototype:
+
+ enum CRStatus
+ cr_parser_parse_declaration (CRParser *a_this, GString **a_property,
+ CRTerm **a_value) ;
+
+ In case of successful parsing, this method returns
+ (via its parameters) the property _and_ the
+ value of the CSS2 declaration.
+ Note that a CSS2 declaration is specified as follows:
+
+ declaration : property ':' S* expr prio?
+ | /* empty */
+
+ * After completion, say if the parsing has succeeded or not.
+
+ eg: cr_parser_parse_declaration() returns CR_OK if the
+ parsing has succeeded, and error code otherwise. Obviously,
+ the out parameters "a_property" and "a_value" are valid if and only
+ if the return value is CR_OK.
+
+ * whenever the function is parsing a construct that must
+ be notified to the user as part of the SAC API spec, notify
+ the user by calling the right SAC callback.
+
+ * if the parsing failed, leave the position in the stream unchanged.
+ That is, the position in the character stream should be as if
+ the parsing function hasn't been called at all.
+
+
+II.4 The selection Engine.
+--------------------------
+
+Hmmh, I should kick my ass to write this down ... \ No newline at end of file
diff --git a/src/3rdparty/libcroco/docs/design/sel-instr.txt b/src/3rdparty/libcroco/docs/design/sel-instr.txt
new file mode 100644
index 0000000..6b19389
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/design/sel-instr.txt
@@ -0,0 +1,64 @@
+Draft of the libcroco selector internal instruction set.
+*********************************************************
+
+READERS SHOULD READ THE CHAPTER 5 of THE CSS2 CSS2 SPEC INTITLED
+"Selectors" FIRST.
+
+I) Introduction
+''''''''''''''''''''
+This is the instructions set understood by the libcroco
+sel-eng.c module (Selection engine).
+
+The purpose of the selection engine is to basically to say whether if a given
+xml node is matched by a given css2 selector or not.
+
+II) Rationale
+''''''''''''''''''''
+For the sake of performance (mostly processing speed) each CSS2
+selector is compiled into a sequences of atomic selection instructions
+that are easily executable by the selection engine.
+
+III) Selection instruction set overview
+''''''''''''''''''''''''''''''''''''''''
+
+Each selection instruction returns a boolean value (TRUE or FALSE).
+The execution of a sequence of selection instruction stops at the
+first instruction that returns a FALSE value and the selection engine
+returns returns the value FALSE to say that the current xml node
+is matched by the CSS2 selection expression being evaluated.
+
+Note that during the evaluation of a CSS2 selection expression,
+all the contextual information are stored into an evaluation context.
+For example, the context will hold a pointer to the xml node the
+selection engine is trying to match.
+
+III.1) The instruction set.
+'''''''''''''''''''''''''''
+
+set-cur-node 'a_node'
+----------------------
+a_node: an xml node
+Sets the current xml node (in the context) to a_node.
+
+match-n-ancestor 'a_n' 'a_parent'
+----------------------------------
+a_parent: a string.
+a_n: a number. The depth of the ancestor
+
+Returns true if the current xml node has an ancestor
+located at a depth 'n' (going upward from the current node)
+and named 'a_parent'. An ancestor located at depth '0' designates
+the current xml node. An ancesstor located at depth '1' designates
+the parent of the current xml node etc ...
+
+match-any
+---------
+Always returns true.
+
+match-first-child 'a_name'
+--------------------------
+Returns true if the current xml element's name equal 'a_name' and
+if the current xml element is the first child of its parent.
+
+TODO: continue reading the chapter 5 of the css2 spec and finish
+the design of this instruction set.
diff --git a/src/3rdparty/libcroco/docs/examples/Makefile.am b/src/3rdparty/libcroco/docs/examples/Makefile.am
new file mode 100644
index 0000000..e960594
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/examples/Makefile.am
@@ -0,0 +1 @@
+EXTRA_DIST=cssom-example-1.c sac-example-1.c sac-example-2.c
diff --git a/src/3rdparty/libcroco/docs/examples/cssom-example-1.c b/src/3rdparty/libcroco/docs/examples/cssom-example-1.c
new file mode 100644
index 0000000..85079ce
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/examples/cssom-example-1.c
@@ -0,0 +1,109 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/**
+ *This is an example that shows how to use
+ *the CSSOM api of the libcroco CSS2 parsing library.
+ *It just parses the CSS document given in argument and
+ *it dumps it (serializes) it on the screen.
+ *
+ *To compile it using gcc, type
+ *
+ *gcc -g -Wall `croco-0.6-config --cflags` `croco-0.6-config --libs` -o cssom-example-1 cssom-example-1.c
+ *
+ *Prior to that, you must have compiled and installed libcroco, of course.
+ *
+ *@author Dodji Seketeli
+ */
+
+#include <string.h>
+#include <libcroco/libcroco.h>
+
+/**
+ *Displays the usage of this program.
+ *@param prg_name the name of the program.
+ */
+void
+display_usage (char *prg_name)
+{
+ printf ("\nusage: %s [options] <css file to parse>\n\n",
+ prg_name) ;
+ printf ("\twhere options are:\n") ;
+ printf ("\t--help|h\tdisplays this help\n") ;
+ printf ("\n") ;
+}
+
+
+/**
+ *Main entry point.
+ *This function illustrates a way to use libcroco.
+ *In this example, we will use a CSS Object Model parser
+ *to parse a cascading style sheet and dump what we have parsed on stdout.
+ *
+ *The goal of the object model parser is to parse a css and build
+ *an abstract tree out of it. One can then walk the tree to perform
+ *whatever action he wants. In our case, the function used to
+ *dump the tree on stdout will walk the tree and dump each one of its
+ *components (a.k.a. css statements).
+ */
+int
+main (int argc, char **argv)
+{
+ short i = 0 ;
+ enum CRStatus status = CR_OK ;
+ CRStyleSheet *stylesheet = NULL ;
+
+ /*first parse command line arguments*/
+ for (i = 1 ; i < argc ; i++)
+ {
+ if (argv[i][0] != '-')
+ break ;
+ if (!strcmp (argv[i],"--help")
+ || !strcmp (argv[i], "-h"))
+ {
+ display_usage (argv[0]) ;
+ return 0 ;
+ }
+ else
+ {
+ display_usage (argv[0]) ;
+ return 0 ;
+ }
+ }
+ if (i >= argc)
+ {
+ display_usage (argv[0]) ;
+ return 0;
+ }
+
+ /*****************************************************
+ *Enough plumbering... now, the real libcroco stuffs.
+ ***************************************************/
+
+ /*
+ *What we want here is to simply parse
+ *a CSS document using the cssom api.
+ */
+ status = cr_om_parser_simply_parse_file ((const guchar*)argv[i] /*sheet*/,
+ CR_ASCII /*the encoding*/,
+ &stylesheet) ;
+ if (status == CR_OK && stylesheet)
+ {
+ /*
+ *everything went well,
+ *so dump the stylesheet on stdout.
+ */
+ cr_stylesheet_dump (stylesheet, stdout) ;
+ }
+
+ if (stylesheet)
+ {
+ /*
+ *free the the memory used to hold the css
+ *object model
+ */
+ cr_stylesheet_destroy (stylesheet) ;
+ stylesheet = NULL ;
+ }
+
+ return 0 ;
+}
diff --git a/src/3rdparty/libcroco/docs/examples/sac-example-1.c b/src/3rdparty/libcroco/docs/examples/sac-example-1.c
new file mode 100644
index 0000000..074fc07
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/examples/sac-example-1.c
@@ -0,0 +1,198 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/**
+ *This test example shows how to use the SAC api.
+ *
+ *This features a simple parser that says "hey" when
+ *it encounters the beginning of a CSS ruleset, and "woohoo"
+ *at the end of a CSS ruleset.
+ *
+ *To compile this file, type:
+ *
+ *gcc -g -Wall -o sac-example-1 `croco-0.6-config --cflags` `croco-0.6-config --libs` sac-example-1.c
+ *
+ *Make sure you have compiled and installed libcroco prior to trying to
+ *compile this file :)
+ *
+ *Once you have compiled it, type:
+ *
+ *./sac-example-1 <a-path-to-a-css-file>
+ *
+ *to try it on a CSS file of your choice.
+ *
+ *Initial Author: Dodji Seketeli <Dodji 47 seketeli dot org>
+ */
+
+#include <string.h>
+#include <libcroco/libcroco.h>
+
+/**
+ *This is a callback function that will
+ *be called at the beginning of each css ruleset.
+ *@param a_handler a pointer to the current sac
+ *document handler
+ *@param a_selector a pointer to the selector.
+ *of the current ruleset.
+ */
+static void
+start_selector_cb (CRDocHandler *a_handler,
+ CRSelector *a_selector)
+{
+ printf ("==========================================\n") ;
+ printf ("Hey, this is the beginning of a ruleset\n") ;
+}
+
+/**
+ *This is a callback function that will be called at the end
+ *of the each css ruleset.
+ */
+static void
+end_selector_cb (CRDocHandler *a_handler,
+ CRSelector *a_selector)
+{
+ printf ("Woohoo, this is the end of a ruleset\n") ;
+ printf ("======================================\n\n") ;
+}
+
+/**
+ *Displays some information about how to use this program.
+ *@param a_prog_name the name of the current program.
+ */
+void
+display_usage (unsigned char *a_prog_name)
+{
+ unsigned char *prog_name = a_prog_name ;
+
+ if (!prog_name)
+ {
+ prog_name = (unsigned char*)"sac-example-1" ;
+ }
+
+ printf ("usage: %s [--help] | <css file name>\n", prog_name) ;
+}
+
+int
+main (int argc, char **argv)
+{
+ unsigned short i = 0 ;
+ unsigned char * file_path = NULL ;
+ CRParser * parser = NULL ;
+ CRDocHandler *sac_handler = NULL ;
+
+ if (argc <= 1)
+ {
+ display_usage ((unsigned char*)argv[0]) ;
+ return -1 ;
+ }
+
+ /*
+ *Let's parse the
+ *command line arguments of this
+ *program in this loop.
+ */
+ for (i=1 ; i < argc ;i++)
+ {
+ if (*argv[i] != '-')
+ break ;
+
+ if (!strcmp (argv[i], "--help")
+ || !strcmp (argv[i], "-h"))
+ {
+ display_usage ((unsigned char*)argv[0]) ;
+ return -1;
+ }
+ else
+ {
+ /*
+ *no other option is
+ *available now, so this is
+ *a bit redundant...
+ */
+ display_usage ((unsigned char*)argv[0]) ;
+ }
+ }
+
+ if (i > argc)
+ {
+ /*
+ *no file name has been given
+ *in parameter, go out.
+ */
+ return -1 ;
+ }
+
+ /****************************************
+ *Now, the real libcroco related stuffs...
+ ****************************************/
+
+ file_path = (unsigned char*)argv[i] ;
+
+ /*
+ *Instantiate the libcroco parser.
+ */
+ parser = cr_parser_new_from_file (file_path,
+ CR_ASCII) ;
+ if (!parser)
+ {
+ /*
+ *Damned, something bad happened ...
+ */
+ return -1;
+ }
+
+ /*
+ *Instantiates the SAC document handler.
+ */
+ sac_handler = cr_doc_handler_new () ;
+ if (!sac_handler)
+ {
+ /*
+ *Argh, something bad happened here :-\
+ *Let's release the resources we allocated
+ *and let's get out.
+ */
+
+ cr_parser_destroy (parser) ;
+ return -1;
+ }
+
+ /******************
+ *Sets some of the sac document handlers.
+ ****************/
+
+ /*
+ *This sac handler callback function will get called by the parser
+ *each time it encounters the beginning of a ruleset.
+ */
+ sac_handler->start_selector = start_selector_cb ;
+
+ /*
+ *This sac handler callback function will get called by the parser
+ *each time it encounters the end of a ruleset.
+ */
+ sac_handler->end_selector = end_selector_cb ;
+
+ /*
+ *Let's register our sac handler into the parser.
+ */
+ cr_parser_set_sac_handler (parser, sac_handler) ;
+
+ /*
+ *Now, let's do the parsing !!!
+ */
+ cr_parser_parse (parser) ;
+
+ /*******************************************************
+ *End of the parsing. A lot of sentences beginning with "Hey"
+ *may have been printed on the screen...
+ ***********************************************/
+
+ /*
+ *Time to free the resources we allocated.
+ */
+ cr_parser_destroy (parser) ;
+
+ cr_doc_handler_unref (sac_handler) ;
+
+ return 0 ;
+}
diff --git a/src/3rdparty/libcroco/docs/examples/sac-example-2.c b/src/3rdparty/libcroco/docs/examples/sac-example-2.c
new file mode 100644
index 0000000..63b002d
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/examples/sac-example-2.c
@@ -0,0 +1,349 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+/**
+ *This test example shows how to use the SAC api.
+ *
+ *This features a simple parser that prints the selector list
+ *and the properties list of each CSS ruleset found.
+ *It also prints the number of properties found in each CSS ruleset.
+ *
+ *At the end of the parsing, it a prints the number of rulesets found
+ *in the CSS document.
+ *
+ *To to this, several handler callbacks have been registered.
+ *We have also created a data structure that we call a parsing context.
+ *This parsing context stores the data necessary to achieve the calculation
+ *done during the parsing (count the number of rulesets and the number
+ *of properties per ruleset)
+ *The parsing context itself is stored in the "app_data" field of the sac handler.
+ *This field is there to provide applications with a
+ *place to store the custom data they want to be able to get/set during the parsing.
+ *
+ *To compile this file, type:
+ *
+ *gcc -g -Wall -o sac-example-2 `croco-0.6-config --cflags` `croco-0.6-config --libs` sac-example-2.c
+ *
+ *Make sure you have compiled and installed libcroco prior to trying to
+ *compile this file :)
+ *
+ *Once you have compiled it, type:
+ *
+ *./sac-example-2 <a-path-to-a-css-file>
+ *
+ *to try it on a CSS file of your choice.
+ *
+ *Initial Author: Dodji Seketeli <Dodji 47 seketeli dot org>
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <libcroco/libcroco.h>
+
+/**
+ *A Context that will hold the
+ *variables necessary to count the number
+ *of rulesets and the number of properties
+ *per ruleset.
+ */
+struct MyFooContext
+{
+ /**the total number of rulesets in the stylesheet.*/
+ int nb_rulesets ;
+
+ /**the number of property per ruleset.*/
+ int nb_props_per_ruleset ;
+} ;
+
+/**
+ *This callback is called only once, at the beginning of
+ *the CSS Document.
+ *So here, we will allocate a custom parsing context
+ *where we will store data necessary for us to
+ *count the number of rulesets and properties found in
+ *the CSS document.
+ *@param a_handler the sac handler.
+ */
+static void
+start_document_cb (CRDocHandler *a_handler)
+{
+ struct MyFooContext * parsing_context = NULL ;
+
+ /*
+ *Allocate the parsing context.
+ *Our custom parsing context.
+ */
+ parsing_context = (struct MyFooContext*) malloc
+ (sizeof (struct MyFooContext)) ;
+ if (!parsing_context)
+ {
+ /*
+ *the system ran out of memory. Advertise it and
+ *stop the program.
+ */
+ fprintf (stderr, "program ran out of memory") ;
+ exit (-1) ;
+ }
+
+ /*
+ *Initialize the newly allocated custom parsing context
+ *to zero.
+ */
+ memset (parsing_context, 0, sizeof (struct MyFooContext)) ;
+
+ /*
+ *Store the parsing context in the document handler.
+ *The app_data field CRDocHandler is especially there
+ *for that: give applications a place to store some data
+ *during the parsing.
+ */
+ a_handler->app_data = parsing_context ;
+}
+
+/**
+ *This callback function will
+ *be called at the beginning of each css ruleset.
+ *@param a_handler a pointer to the current sac
+ *document handler
+ *@param a_selector a pointer to the selector.
+ *of the current ruleset.
+ */
+static void
+start_selector_cb (CRDocHandler *a_handler,
+ CRSelector *a_selector)
+{
+ struct MyFooContext *context = NULL ;
+
+ context = (struct MyFooContext*) a_handler->app_data ;
+ if (!context)
+ return ;
+ context->nb_props_per_ruleset = 0 ;
+
+ cr_selector_dump (a_selector, stdout) ;
+ printf (" {\n") ;
+
+}
+
+/**
+ *This callback function is called when
+ *the parser encounters a CSS property.
+ *@param a_handler the SAC handler.
+ *@param a_name string that contains the
+ *name of the property.
+ *@param a_value the value of the property.
+ */
+static void
+property_cb (CRDocHandler *a_handler,
+ CRString *a_name,
+ CRTerm *a_value,
+ gboolean a_important)
+{
+ struct MyFooContext *context = NULL ;
+
+ context = (struct MyFooContext *)a_handler->app_data ;
+
+ if (!context || !a_name)
+ return ;
+ context->nb_props_per_ruleset ++ ;
+
+ printf ("%s : ", cr_string_peek_raw_str (a_name)) ;
+ cr_term_dump (a_value, stdout) ;
+ printf ("\n") ;
+}
+
+
+/**
+ *This is a callback function that will be called at the end
+ *of the each css ruleset.
+ */
+static void
+end_selector_cb (CRDocHandler *a_handler,
+ CRSelector *a_selector)
+{
+ struct MyFooContext *context = NULL ;
+
+ context = (struct MyFooContext*)a_handler->app_data ;
+ if (!context)
+ return ;
+ context->nb_rulesets ++ ;
+ printf ("\n}\n") ;
+ printf ("**Number of properties in this ruleset: %d\n\n\n",
+ context->nb_props_per_ruleset) ;
+}
+
+/**
+ *This callback is called only once at the end
+ *of the CSS document.
+ *@param a_handler the SAC handler.
+ */
+static void
+end_document_cb (CRDocHandler *a_handler)
+{
+ struct MyFooContext *context = NULL ;
+
+ context = (struct MyFooContext*) a_handler->app_data ;
+ if (!context)
+ return ;
+
+ printf ("\nTotal number of rulesets: %d\n",
+ context->nb_rulesets) ;
+
+ free (context) ;
+ a_handler->app_data = NULL ;
+}
+
+/**
+ *Displays some information about how to use this program.
+ *@param a_prog_name the name of the current program.
+ */
+void
+display_usage (unsigned char *a_prog_name)
+{
+ unsigned char *prog_name = a_prog_name ;
+
+ if (!prog_name)
+ {
+ prog_name = (unsigned char*) "sac-example-1" ;
+ }
+
+ printf ("usage: %s [--help] | <css file name>\n", prog_name) ;
+}
+
+int
+main (int argc, char **argv)
+{
+ unsigned short i = 0 ;
+ unsigned char * file_path = NULL ;
+ CRParser * parser = NULL ;
+ CRDocHandler *sac_handler = NULL ;
+
+ if (argc <= 1)
+ {
+ display_usage ((unsigned char*)argv[0]) ;
+ return -1 ;
+ }
+
+ /*
+ *Let's parse the
+ *command line arguments of this
+ *program in this loop.
+ */
+ for (i=1 ; i < argc ;i++)
+ {
+ if (*argv[i] != '-')
+ break ;
+
+ if (!strcmp (argv[i], "--help")
+ || !strcmp (argv[i], "-h"))
+ {
+ display_usage ((unsigned char*)argv[0]) ;
+ return -1;
+ }
+ else
+ {
+ /*
+ *no other option is
+ *available now, so this is
+ *a bit redundant...
+ */
+ /*display_usage ((unsigned char*)argv[0]) ;*/
+ }
+ }
+
+ if (i > argc)
+ {
+ /*
+ *no file name has been given
+ *in parameter, go out.
+ */
+ return -1;
+ }
+
+ /****************************************
+ *Now, the real libcroco related stuffs...
+ ****************************************/
+
+ file_path = (unsigned char*)argv[i] ;
+
+ /*
+ *Instantiate the libcroco parser.
+ */
+ parser = cr_parser_new_from_file (file_path,
+ CR_ASCII) ;
+ if (!parser)
+ {
+ /*
+ *Damned, something bad happened ...
+ */
+ return -1 ;
+ }
+
+ /*
+ *Instantiates the SAC document handler.
+ */
+ sac_handler = cr_doc_handler_new () ;
+ if (!sac_handler)
+ {
+ /*
+ *Argh, something bad happened here :-\
+ *Let's release the resources we allocated
+ *and let's get out.
+ */
+
+ cr_parser_destroy (parser) ;
+ return -1 ;
+ }
+
+ /****************************************
+ *Set some of the sac document handlers.
+ ****************************************/
+
+ /*
+ *This callback function will be called by the parser
+ *only once, at the beginning of the CSS Document.
+ */
+ sac_handler->start_document = start_document_cb ;
+
+ /*
+ *This callback function will be called by the parser
+ *only once, at the end of the CSS Document.
+ */
+ sac_handler->end_document =end_document_cb ;
+
+ /*
+ *This callback function will be called by the parser
+ *each time it encounters the beginning of a ruleset.
+ */
+ sac_handler->start_selector = start_selector_cb ;
+
+ /*
+ *This callback function will be called by the parser
+ *each time it encounters the beginning of a ruleset.
+ */
+ sac_handler->property = property_cb ;
+
+ /*
+ *This sac handler callback function will be called by the parser
+ *each time it encounters the end of a ruleset.
+ */
+ sac_handler->end_selector = end_selector_cb ;
+
+ /*
+ *Let's register our sac handler into the parser.
+ */
+ cr_parser_set_sac_handler (parser, sac_handler) ;
+
+ /*
+ *Now, let's do the parsing !!!
+ */
+ cr_parser_parse (parser) ;
+
+ /*******************************************************
+ *End of the parsing. A Couple of CSS rulesets must have
+ *been printed on the screen...
+ ***********************************************/
+
+ /*
+ *Time to free the resources we allocated.
+ */
+ cr_parser_destroy (parser) ;
+
+ return 0 ;
+}
diff --git a/src/3rdparty/libcroco/docs/examples/selection-example-1.c b/src/3rdparty/libcroco/docs/examples/selection-example-1.c
new file mode 100644
index 0000000..3215a99
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/examples/selection-example-1.c
@@ -0,0 +1,191 @@
+/**
+ * This example looks up a node from a document with an
+ * xpath expression, then reports all properties that apply
+ * from a given stylesheet.
+ *
+ * To compile it using gcc, type
+ *
+ * gcc -g -Wall `croco-0.6-config --cflags` `croco-0.6-config --libs` -o selection-example-1 selection-example-1.c
+ *
+ * Initial author: Stefan Seefeld.
+ */
+
+#include <libcroco/libcroco.h>
+#include <libcroco/cr-libxml-node-iface.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+
+void
+usage_and_exit (char *progname)
+{
+ fprintf (stderr,
+ "Usage: %s <xml doc> <stylesheet> <xpath>\n",
+ progname);
+ exit(-1);
+}
+
+struct workspace
+{
+ xmlDoc *document;
+ xmlXPathContext *xpath;
+ xmlXPathObject *result;
+ CRStyleSheet *stylesheet;
+ CRCascade *cascade;
+ CRSelEng *selector;
+};
+
+/**
+ *construct workspace members in order...
+ * return 0 on success and -1 on error
+ */
+int
+init (struct workspace *ws, char **args)
+{
+ enum CRStatus status = CR_OK;
+
+ ws->document = 0;
+ ws->xpath = 0;
+ ws->result = 0;
+ ws->stylesheet = 0;
+ ws->cascade = 0;
+ ws->selector = 0;
+
+
+ ws->document = xmlParseFile(args[0]);
+ if (!ws->document)
+ {
+ fprintf(stderr, "could not parse the document %s", args[0]);
+ return -1;
+ }
+ ws->xpath = xmlXPathNewContext(ws->document);
+ if (!ws->xpath)
+ {
+ fprintf(stderr, "Error: unable to create new XPath context\n");
+ return -1;
+ }
+ ws->result = xmlXPathEvalExpression((xmlChar *)args[2], ws->xpath);
+ if (!ws->result)
+ {
+ fprintf(stderr, "Error: unable to evaluate xpath expression\n");
+ return -1;
+ }
+ if (ws->result->type != XPATH_NODESET || !ws->result->nodesetval)
+ {
+ fprintf(stderr, "Error: xpath does not evaluate to a node set\n");
+ return -1;
+ }
+
+ status = cr_om_parser_simply_parse_file((const guchar*)args[1] /*sheet*/,
+ CR_ASCII /*the encoding*/,
+ &ws->stylesheet);
+ if (status != CR_OK || !ws->stylesheet)
+ {
+ fprintf(stderr, "could not parse the stylesheet %s", args[1]);
+ return -1;
+ }
+ ws->cascade = cr_cascade_new(ws->stylesheet, 0, 0);
+ ws->selector = cr_sel_eng_new(&cr_libxml_node_iface);
+ return 1 ;
+}
+
+/* ...and destruct in reverse order*/
+void
+fini(struct workspace *ws)
+{
+ if (ws->selector)
+ {
+ cr_sel_eng_destroy(ws->selector);
+ ws->selector = NULL ;
+ }
+ if (ws->cascade)
+ {
+ cr_cascade_destroy(ws->cascade);
+ ws->cascade = NULL ;
+ }
+
+ if (ws->result)
+ {
+ xmlXPathFreeObject(ws->result);
+ ws->result = NULL ;
+ }
+ if (ws->xpath)
+ {
+ xmlXPathFreeContext(ws->xpath);
+ ws->xpath = NULL ;
+ }
+ if (ws->document)
+ {
+ xmlFreeDoc(ws->document);
+ ws->document = NULL ;
+ }
+ xmlCleanupParser () ;
+}
+
+void
+print_properties_real (CRPropList *proplist)
+{
+ CRDeclaration *decl = NULL ;
+ CRPropList *cur_pair = NULL ;
+
+ for (cur_pair = proplist ; cur_pair ;
+ cur_pair= cr_prop_list_get_next (cur_pair)) {
+ gchar *str = NULL ;
+ decl = NULL ;
+
+ cr_prop_list_get_decl (cur_pair, &decl) ;
+ if (decl) {
+ str = cr_declaration_to_string (decl, 0) ;
+ if (str) {
+ printf ("%s\n", str) ;
+ g_free (str);
+ str = NULL ;
+ }
+ }
+ }
+}
+
+void
+print_properties (struct workspace *ws)
+{
+ enum CRStatus status;
+ CRPropList *prop_list = NULL;
+ xmlNode *node = ws->result->nodesetval->nodeTab[0];
+
+ status = cr_sel_eng_get_matched_properties_from_cascade
+ (ws->selector, ws->cascade,
+ node, &prop_list);
+
+ if (status != CR_OK)
+ fprintf(stderr, "Error retrieving properties\n");
+ else
+ {
+ xmlChar *prop = NULL ;
+ prop = xmlGetNodePath(node) ;
+ if (prop) {
+ printf("properties for node %s :\n", prop);
+ xmlFree (prop) ;
+ prop = NULL ;
+ }
+ print_properties_real (prop_list) ;
+ }
+ cr_prop_list_destroy (prop_list) ;
+}
+
+int
+main(int argc, char **argv)
+{
+ struct workspace ws;
+ if (argc != 4) usage_and_exit(argv[0]);
+ if (!init(&ws, argv + 1)) {
+ fini(&ws);
+ return -1 ;
+ }
+
+ if (ws.result->nodesetval->nodeNr == 0)
+ printf("no matching nodes found\n");
+ else
+ print_properties(&ws);
+
+ fini(&ws);
+ return 0;
+}
diff --git a/src/3rdparty/libcroco/docs/examples/selection-example-1.css b/src/3rdparty/libcroco/docs/examples/selection-example-1.css
new file mode 100644
index 0000000..044e053
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/examples/selection-example-1.css
@@ -0,0 +1,41 @@
+report
+{
+ color : red;
+}
+
+report > entry
+{
+ color : blue;
+}
+
+note
+{
+ color : note-color;
+ frame : solid;
+}
+
+note[id]
+{
+ color : note-id-color;
+ frame : solid;
+}
+
+note[id=bar]
+{
+ margin : 5px;
+ color: note-id-bar-color ;
+}
+
+note[id=foo]
+{
+ color : note-id-foo-color;
+}
+
+entry[type=notice] note[id=bar]
+{
+ padding : 5px;
+}
+
+note + notea {
+ color: notea-color ;
+}
diff --git a/src/3rdparty/libcroco/docs/examples/selection-example-1.xml b/src/3rdparty/libcroco/docs/examples/selection-example-1.xml
new file mode 100644
index 0000000..4c3f558
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/examples/selection-example-1.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" ?>
+<report>
+ <entry type="notice">
+ <note id="foo"/>
+ <notea/>
+ <note id="bar"/>
+ </entry>
+ <entry>
+ <notea/>
+ <note/>
+ <note id="foo"/>
+ <note id="bar"/>
+ </entry>
+</report>
diff --git a/src/3rdparty/libcroco/docs/reference/Makefile.am b/src/3rdparty/libcroco/docs/reference/Makefile.am
new file mode 100644
index 0000000..0ec463d
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/reference/Makefile.am
@@ -0,0 +1,53 @@
+## Process this file with automake to produce Makefile.in
+NULL=
+
+# The name of the module, e.g. 'glib'.
+DOC_MODULE=libcroco
+
+# The top-level SGML file. Change it if you want.
+DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
+
+# The directory containing the source code. Relative to $(srcdir).
+# gtk-doc will search all .c & .h files beneath here for inline comments
+# documenting functions and macros.
+DOC_SOURCE_DIR=../../src
+
+# Extra options to pass to gtkdoc-scanobj or gtkdoc-scangobj.
+SCANGOBJ_OPTIONS=--type-init-func="g_type_init()"
+
+# Extra options to supply to gtkdoc-scan.
+SCAN_OPTIONS=
+
+# Extra options to supply to gtkdoc-mkdb.
+MKDB_OPTIONS=--sgml-mode --output-format=xml
+
+# Extra options to supply to gtkdoc-fixref.
+FIXXREF_OPTIONS=
+
+# Used for dependencies.
+HFILE_GLOB=$(top_srcdir)/src/*.h
+CFILE_GLOB=$(top_srcdir)/src/*.c
+
+# Header files to ignore when scanning.
+IGNORE_HFILES=\
+ $(NULL)
+
+# Images to copy into HTML directory.
+HTML_IMAGES=\
+ $(NULL)
+
+# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
+content_files=\
+ $(NULL)
+
+# CFLAGS and LDFLAGS for compiling scan program. Only needed if your app/lib
+# contains GtkObjects/GObjects and you want to document signals and properties.
+GTKDOC_CFLAGS=\
+ $(CROCO_CFLAGS) \
+ $(NULL)
+GTKDOC_LIBS=\
+ $(CROCO_LIBS) \
+ $(NULL)
+
+include $(top_srcdir)/gtk-doc.make
+
diff --git a/src/3rdparty/libcroco/docs/reference/libcroco-docs.sgml b/src/3rdparty/libcroco/docs/reference/libcroco-docs.sgml
new file mode 100644
index 0000000..f67e318
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/reference/libcroco-docs.sgml
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
+<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
+ <bookinfo>
+ <title>Libcroco Reference Manual</title>
+ </bookinfo>
+
+ <chapter>
+ <title>Extensive APIs description</title>
+ <xi:include href="xml/cr-additional-sel.xml"/>
+ <xi:include href="xml/cr-attr-sel.xml"/>
+ <xi:include href="xml/cr-cascade.xml"/>
+ <xi:include href="xml/cr-declaration.xml"/>
+ <xi:include href="xml/cr-doc-handler.xml"/>
+ <xi:include href="xml/cr-enc-handler.xml"/>
+ <xi:include href="xml/cr-fonts.xml"/>
+ <xi:include href="xml/cr-input.xml"/>
+ <xi:include href="xml/cr-num.xml"/>
+ <xi:include href="xml/cr-om-parser.xml"/>
+ <xi:include href="xml/cr-parser.xml"/>
+ <xi:include href="xml/cr-parsing-location.xml"/>
+ <xi:include href="xml/cr-prop-list.xml"/>
+ <xi:include href="xml/cr-pseudo.xml"/>
+ <xi:include href="xml/cr-rgb.xml"/>
+ <xi:include href="xml/cr-sel-eng.xml"/>
+ <xi:include href="xml/cr-selector.xml"/>
+ <xi:include href="xml/cr-simple-sel.xml"/>
+ <xi:include href="xml/cr-statement.xml"/>
+ <xi:include href="xml/cr-string.xml"/>
+ <xi:include href="xml/cr-style.xml"/>
+ <xi:include href="xml/cr-stylesheet.xml"/>
+ <xi:include href="xml/cr-term.xml"/>
+ <xi:include href="xml/cr-tknzr.xml"/>
+ <xi:include href="xml/cr-token.xml"/>
+ <xi:include href="xml/cr-utils.xml"/>
+ <xi:include href="xml/libcroco-config.xml"/>
+ </chapter>
+</book>
diff --git a/src/3rdparty/libcroco/docs/release-notes-template.txt b/src/3rdparty/libcroco/docs/release-notes-template.txt
new file mode 100644
index 0000000..df66f98
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/release-notes-template.txt
@@ -0,0 +1,41 @@
+Application
+===========
+
+Libcroco 0.4
+
+Description
+===========
+
+Libcroco is a CSS parsing and manipulation library
+written in C for the gnome project.
+
+It provides :
+
+-two CSS parsing apis: SAC and CSSOM.
+-A CSS2 selection and cascading engine based on libxml2.
+-An experimental XML/CSS rendering engine.
+
+Changes
+=======
+- Removed the pango dependency from the
+ selection engine and put it in the layout engine. (Dodji Seketeli)
+- Added a test example to demonstrate the use of the selection engine (Stefan Seefeld)
+
+Fixes
+=====
+- Fixed some gcc-2.96 parse errors (Dodji Seketeli)
+- Make sure the header files are C++ friendly (Dodji Seketeli)
+- Make sure the code examples compile with g++ (Dodji Seketeli)
+- Fixed a bug in the selection engine (Dodji Seketeli)
+
+Homepage
+========
+http://www.freespiders.org/projects/libcroco
+
+Download
+========
+http://ftp.gnome.org/pub/GNOME/sources/libcroco
+
+GNOME Software Map entry
+========================
+http://www.gnome.org/softwaremap/projects/libcroco
diff --git a/src/3rdparty/libcroco/docs/usage.txt b/src/3rdparty/libcroco/docs/usage.txt
new file mode 100644
index 0000000..a061116
--- /dev/null
+++ b/src/3rdparty/libcroco/docs/usage.txt
@@ -0,0 +1,47 @@
+initial author: Dodji Seketeli <dodji@seketeli.org>
+
+Note:
+----
+Users can generate an html doc of all the functions of libcroco.
+This is documentation is an unvaluable tool to master the libcroco
+usage and internals.
+To generate the documentation, just cd into the libcroco project
+directory and type 'make apidoc' ;
+This will generate the documentation in the docs/api directory.
+
+
+Usage of the libcroco css2 parsing library
+===========================================
+
+libcroco has two main user programming interfaces:
+the SAC parser, and the CSSOM parser.
+
+
+The SAC parser
+''''''''''''''''
+
+The SAC (Simple Api for CSS) is the lowest level parsing api
+provided by libcroco.
+It is an event driven api in which the parser notifies the
+caller whenever it encounters a remarquable css construction.
+
+The SAC parser is implemented in the CRParser class.
+To use it, one must first instantiate a CRParser.
+
+I said earlier the the SAC parser notifies it caller
+whenever it encounters certain css language constructions during
+the parsing. "Notifies" actually means that it calls a subset of given
+callback function pointers set. This set of function pointers is
+called a "Document Handler". So, by overriding some function pointers
+of the document handler, the user can define the actions to be
+performed when a given css language construction is encountered.
+
+The SAC parser's api is defined in cr-parser.h and
+the document handler's api is defined in cr-doc-handler.h .
+
+
+The CSSOM parser
+'''''''''''''''''
+
+
+
diff --git a/src/3rdparty/libcroco/global-test-vars.sh.in b/src/3rdparty/libcroco/global-test-vars.sh.in
new file mode 100644
index 0000000..cfe1849
--- /dev/null
+++ b/src/3rdparty/libcroco/global-test-vars.sh.in
@@ -0,0 +1,12 @@
+TEST_OUT_DIR=./tests
+TEST_SOURCE_DIR=@srcdir@/tests
+TEST_INPUTS_DIR="$TEST_SOURCE_DIR"/test-inputs
+CSSLINT=./csslint/.libs/csslint-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@
+if ! test -x $CSSLINT ; then
+ echo "Error: Could not find an executable csslint. I was looking for $CSSLINT" >&2
+ exit 1
+fi
+
+if ! test x"$VALGRIND" = x ; then
+ CSSLINT="$VALGRIND $CSSLINT"
+fi
diff --git a/src/3rdparty/libcroco/libcroco-indent b/src/3rdparty/libcroco/libcroco-indent
new file mode 100755
index 0000000..f367987
--- /dev/null
+++ b/src/3rdparty/libcroco/libcroco-indent
@@ -0,0 +1,102 @@
+#!/bin/sh
+#This is just a smallish indent script to indent mlview
+#to indent all the sources correctly (before committing for ex),
+#type:
+#./indent-mlview src/*.[ch]
+
+#Here go some explanations of the indent options:
+#
+#-bad: forces a blank line after every block of declaration
+#=============================================================
+#-bap: forces a blank line after every procedure body
+#=============================================================
+#-bbb: forces a blank line before every boxed comment.
+#=============================================================
+#-sob: forces indent to swallow every optional blank line.
+#=============================================================
+#-bl -bli2 formats braces like this:
+#if (x > 2)
+# {
+# x-- ;
+# }
+#=============================================================
+#-nce formats the "else" not to cudle up to the
+#immediately preceding }:
+#if (x > 2)
+# {
+# x-- ;
+# }
+#else
+# {
+# x++ ;
+# }
+#==============================
+#-ce is the contrary of -nce
+#=============================================================
+#-ss: put a space before a semi colon that is at the same line as a
+#for.
+#=============================================================
+#-pcs: puts a space between the name of a procedure being called
+#and the '('.
+#=============================================================
+#-bs: puts a space between the sizeof operator and its argument.
+#=============================================================
+#-saf: puts a space between a for an the following parenthesis.
+#=============================================================
+#-sai: puts a space between an if and its arguments
+#=============================================================
+#-saw: puts a space between a while and its arguments
+#=============================================================
+#-psl: causes the type of a procedure being defined to be placed
+#on the line before the name of the procedure.
+#=============================================================
+#-bls: formats braces in struct declarations like this:
+#struct foo
+#{
+# int x;
+#};
+#-brs: formats braces in struct decls like this:
+#struct foo {
+# int x;
+#};
+#=============================================================
+#-bc: forces a newline after each comma in a declaration.
+#=============================================================
+#-i2: puts indentation at 2 blank chars.
+#=============================================================
+#-lp:
+#without -lp the code looks like this:
+#p1 = first_procedure (second_procedure (p2, p3),
+# third_procedure (p4, p5));
+#with -lp the code looks like this:
+#p1 = first_procedure (second_procedure (p2, p3),
+# third_procedure (p4, p5));
+#=============================================================
+#-ppi2: indents preprocessor directives using 2 spaces.
+#=============================================================
+#=============================================================
+#-ts2:set tabs spaces to 2 blank chars.
+#=============================================================
+#-l60 == --line-length60
+#=============================================================
+#-bbo: break long lines before boolean operators when found.
+#=============================================================
+
+INDENT=`which indent`
+GREP=`which grep`
+if test x$INDENT = x ; then
+ echo "Argh !!! Could not find indent in your PATH. Exited."
+ exit -1
+ if test x$GREP = x ; then
+ echo "Argh!!! Could not find grep in you PATH. Exited."
+ exit -1 ;
+ fi
+ is_gnu=`$INDENT -version | $GREP gnu`
+ if test x$is_gnu = x ; then
+ echo "Found a indent that is not the GNU one. Exited."
+ exit -1 ;
+ fi
+fi
+
+exec $INDENT -bad -bap -nbbb -br -ce -ss -pcs -bs -saf -sai \
+-cdw -saw -psl -brs -bc -i8 -ppi0 -lp -ts0 -bbo -sob $@
diff --git a/src/3rdparty/libcroco/libcroco-zip.in b/src/3rdparty/libcroco/libcroco-zip.in
new file mode 100755
index 0000000..5b6e2ee
--- /dev/null
+++ b/src/3rdparty/libcroco/libcroco-zip.in
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# Build distribution zipfiles for libcroco on Win32: Runtime and
+# developer.
+
+ZIP=/tmp/libcroco-@VERSION@.zip
+DEVZIP=/tmp/libcroco-dev-@VERSION@.zip
+
+# The DLL name generated by libtool with the passed --version-info
+DLLNAME=libcroco-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@-`expr @LIBCROCO_CURRENT@ - @LIBCROCO_AGE@`.dll
+
+cd @prefix@
+rm $ZIP
+
+zip $ZIP -@ <<EOF
+bin/$DLLNAME
+EOF
+
+rm $DEVZIP
+zip -r $DEVZIP -@ <<EOF
+bin/csslint-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@.exe
+include/libcroco-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@
+lib/libcroco-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@.dll.a
+lib/pkgconfig/libcroco-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@.pc
+EOF
diff --git a/src/3rdparty/libcroco/libcroco.doap b/src/3rdparty/libcroco/libcroco.doap
new file mode 100644
index 0000000..4ffc1c6
--- /dev/null
+++ b/src/3rdparty/libcroco/libcroco.doap
@@ -0,0 +1,30 @@
+<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
+ xmlns:foaf="http://xmlns.com/foaf/0.1/"
+ xmlns:gnome="http://api.gnome.org/doap-extensions#"
+ xmlns="http://usefulinc.com/ns/doap#">
+
+ <name xml:lang="en">libcroco</name>
+ <shortdesc xml:lang="en">A CSS parsing library</shortdesc>
+ <description>A CSS parsing library</description>
+ <homepage rdf:resource="http://www.linuxfromscratch.org/blfs/view/svn/general/libcroco.html" />
+ <mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/libcroco-list" />
+ <download-page rdf:resource="https://download.gnome.org/sources/libcroco/" />
+ <category rdf:resource="http://api.gnome.org/doap-extensions#core" />
+ <programming-language>C</programming-language>
+
+ <maintainer>
+ <foaf:Person>
+ <foaf:name>Abhishek Sharma</foaf:name>
+ <foaf:mbox rdf:resource="mailto:abhisheks@gnome.org" />
+ <gnome:userid>abhisheks</gnome:userid>
+ </foaf:Person>
+ </maintainer>
+ <maintainer>
+ <foaf:Person>
+ <foaf:name>Dodji Seketeli</foaf:name>
+ <foaf:mbox rdf:resource="mailto:dodji@gnome.org" />
+ <gnome:userid>dodji</gnome:userid>
+ </foaf:Person>
+ </maintainer>
+</Project>
diff --git a/src/3rdparty/libcroco/libcroco.pc.in b/src/3rdparty/libcroco/libcroco.pc.in
new file mode 100644
index 0000000..3d0dc0a
--- /dev/null
+++ b/src/3rdparty/libcroco/libcroco.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libcroco
+Version: @VERSION@
+Description: a CSS2 Parsing and manipulation Library in C.
+Requires: glib-2.0 libxml-2.0
+Libs: -L${libdir} -lcroco-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@
+Cflags: -I${includedir}/libcroco-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@
diff --git a/src/3rdparty/libcroco/libcroco.spec.in b/src/3rdparty/libcroco/libcroco.spec.in
new file mode 100644
index 0000000..466d379
--- /dev/null
+++ b/src/3rdparty/libcroco/libcroco.spec.in
@@ -0,0 +1,82 @@
+%define lib_major 0
+
+Name: libcroco
+Summary: CSS2 parser library
+Version: @VERSION@
+Release: 1
+License: LGPL
+Group: System/Libraries
+Source0: ftp://ftp.gnome.org/pub/GNOME/sources/%{name}-%{version}.tar.gz
+URL: http://savannah.nongnu.org/projects/libcroco
+BuildRoot: %{_tmppath}/%{name}-%{version}-root
+BuildRequires: libxml2-devel
+BuildRequires: glib2-devel
+
+%description
+libcroco is a standalone css2 parsing library.
+It provides a low level event driven SAC like api
+and a css object model like api.
+
+%package devel
+Summary: Libraries and include files for developing with librsvg.
+Group: Development/C
+Requires: %{name} = %{version}-%{release}
+Provides: %{name}-devel = %{version}-%{release}
+Requires: libxml2-devel
+Requires: glib2-devel
+
+%description devel
+This package provides the necessary development libraries and include
+files to allow you to develop with libcroco?
+
+%prep
+%setup -q
+
+%build
+
+%configure
+
+make
+
+%install
+[ -n "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != / ] && rm -rf $RPM_BUILD_ROOT
+%makeinstall
+
+%clean
+[ -n "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != / ] && rm -rf $RPM_BUILD_ROOT
+
+
+%post -p /sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+%files
+%defattr(-, root, root)
+%doc AUTHORS COPYING COPYING.LIB ChangeLog NEWS README.md
+%{_bindir}/csslint
+%{_mandir}/man1/csslint*
+%{_libdir}/*.so.*
+
+%files devel
+%defattr(-,root,root)
+%{_bindir}/croco-config
+%{_mandir}/man1/croco-config*
+%{_libdir}/*.la
+%{_libdir}/*.a
+%{_libdir}/*.so
+%{_includedir}/*
+%{_libdir}/pkgconfig/*
+
+%changelog
+* Tue Jul 8 2003 Christian Schaller <Uraeus@gnome.org>
+- Udate for 0.3 and Red Hat
+
+* Mon Jul 7 2003 Frederic Crozat <fcrozat@mandrakesoft.com> - 0.2.0-1mdk
+- Release 0.2.0
+- WARNING : binary compat is broken, you need to recompile apps built with libcroco 0.1
+
+* Fri Jun 13 2003 Götz Waschk <waschk@linux-mandrake.com> 0.1.0-2mdk
+- rebuild for new rpm
+
+* Fri Apr 18 2003 Frederic Crozat <fcrozat@mandrakesoft.com> - 0.1.0-1mdk
+- First Mdk package.
diff --git a/src/3rdparty/libcroco/src/CMakeLists.txt b/src/3rdparty/libcroco/src/CMakeLists.txt
new file mode 100644
index 0000000..077c847
--- /dev/null
+++ b/src/3rdparty/libcroco/src/CMakeLists.txt
@@ -0,0 +1,85 @@
+set(G_DISABLE_CHECKS 0)
+configure_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/libcroco-config.h.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/libcroco-config.h")
+
+set(libcroco_headers
+ cr-additional-sel.h
+ cr-attr-sel.h
+ cr-cascade.h
+ cr-declaration.h
+ cr-doc-handler.h
+ cr-enc-handler.h
+ cr-fonts.h
+ cr-input.h
+ cr-libxml-node-iface.h
+ cr-node-iface.h
+ cr-num.h
+ cr-om-parser.h
+ cr-parser.h
+ cr-parsing-location.h
+ cr-prop-list.h
+ cr-pseudo.h
+ cr-rgb.h
+ cr-sel-eng.h
+ cr-selector.h
+ cr-simple-sel.h
+ cr-statement.h
+ cr-string.h
+ cr-style.h
+ cr-stylesheet.h
+ cr-term.h
+ cr-tknzr.h
+ cr-token.h
+ cr-utils.h
+ libcroco.h
+)
+
+set(libcroco_SRC
+ cr-additional-sel.c
+ cr-attr-sel.c
+ cr-cascade.c
+ cr-declaration.c
+ cr-doc-handler.c
+ cr-enc-handler.c
+ cr-fonts.c
+ cr-input.c
+ cr-libxml-node-iface.c
+ cr-num.c
+ cr-om-parser.c
+ cr-parser.c
+ cr-parsing-location.c
+ cr-prop-list.c
+ cr-pseudo.c
+ cr-rgb.c
+ cr-selector.c
+ cr-sel-eng.c
+ cr-simple-sel.c
+ cr-statement.c
+ cr-string.c
+ cr-style.c
+ cr-stylesheet.c
+ cr-term.c
+ cr-tknzr.c
+ cr-token.c
+ cr-utils.c
+ ${libcroco_headers}
+)
+
+add_library(croco_LIB STATIC "${libcroco_SRC}")
+
+target_include_directories(croco_LIB
+ PRIVATE
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${LIBXML_INCLUDE_DIRS}
+ PUBLIC
+ ${GLIB_INCLUDE_DIRS}
+)
+
+target_link_libraries(croco_LIB
+ PRIVATE
+ ${GLIB_LDFLAGS}
+ INTERFACE
+ ${LIBXML_LDFLAGS}
+ m
+)
diff --git a/src/3rdparty/libcroco/src/Makefile.am b/src/3rdparty/libcroco/src/Makefile.am
new file mode 100644
index 0000000..00711d4
--- /dev/null
+++ b/src/3rdparty/libcroco/src/Makefile.am
@@ -0,0 +1,136 @@
+NULL =
+
+lib_LTLIBRARIES=libcroco-0.6.la
+
+if PLATFORM_WIN32
+no_undefined = -no-undefined
+endif
+
+#Headers files to be distributed
+crocoincdir = $(includedir)/$(PACKAGE)-$(LIBCROCO_MAJOR_VERSION).$(LIBCROCO_MINOR_VERSION)/libcroco
+crocoinc_HEADERS = \
+ libcroco.h \
+ cr-additional-sel.h \
+ cr-attr-sel.h \
+ cr-cascade.h \
+ cr-declaration.h \
+ cr-doc-handler.h \
+ cr-enc-handler.h \
+ cr-input.h \
+ cr-libxml-node-iface.h \
+ cr-num.h \
+ cr-om-parser.h \
+ cr-parser.h \
+ cr-pseudo.h \
+ cr-rgb.h \
+ cr-selector.h \
+ cr-simple-sel.h \
+ cr-statement.h \
+ cr-stylesheet.h \
+ cr-term.h \
+ cr-tknzr.h \
+ cr-token.h \
+ cr-utils.h \
+ cr-fonts.h \
+ cr-sel-eng.h \
+ cr-style.h \
+ cr-prop-list.h \
+ cr-parsing-location.h \
+ cr-string.h \
+ libcroco-config.h \
+ $(NULL)
+
+libcroco_0_6_la_SOURCES = \
+ cr-utils.c \
+ cr-utils.h \
+ cr-input.c \
+ cr-input.h \
+ cr-enc-handler.c \
+ cr-enc-handler.h \
+ cr-libxml-node-iface.c \
+ cr-node-iface.h \
+ cr-num.c \
+ cr-num.h \
+ cr-rgb.c \
+ cr-rgb.h \
+ cr-token.c \
+ cr-token.h \
+ cr-tknzr.c \
+ cr-tknzr.h \
+ cr-term.c \
+ cr-term.h \
+ cr-attr-sel.c \
+ cr-attr-sel.h \
+ cr-pseudo.c \
+ cr-pseudo.h \
+ cr-additional-sel.c \
+ cr-additional-sel.h \
+ cr-simple-sel.c \
+ cr-simple-sel.h \
+ cr-selector.c \
+ cr-selector.h \
+ cr-doc-handler.c \
+ cr-doc-handler.h \
+ cr-parser.c \
+ cr-parser.h \
+ cr-declaration.c \
+ cr-declaration.h \
+ cr-statement.c \
+ cr-statement.h \
+ cr-stylesheet.c \
+ cr-stylesheet.h \
+ cr-cascade.c \
+ cr-cascade.h \
+ cr-om-parser.c \
+ cr-om-parser.h \
+ cr-style.c \
+ cr-style.h \
+ cr-sel-eng.c \
+ cr-sel-eng.h \
+ cr-fonts.c \
+ cr-fonts.h \
+ cr-prop-list.c \
+ cr-prop-list.h \
+ cr-parsing-location.c \
+ cr-parsing-location.h \
+ cr-string.c \
+ cr-string.h \
+ $(NULL)
+
+libcroco_0_6_la_CPPFLAGS = \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/intl \
+ -I$(top_builddir)/src \
+ $(AM_CPPFLAGS)
+
+libcroco_0_6_la_CFLAGS = \
+ $(CROCO_CFLAGS) \
+ $(AM_CFLAGS)
+
+libcroco_0_6_la_LDFLAGS = \
+ -version-info @LIBCROCO_VERSION_INFO@ \
+ $(no_undefined) \
+ $(BSYMBOLIC_LDFLAG) \
+ $(AM_LDFLAGS)
+
+libcroco_0_6_la_LIBADD = \
+ $(CROCO_LIBS)
+
+EXTRA_DIST = libcroco.symbols
+
+# MSVC Build Items
+
+MSVCPROJS = croco
+
+croco_FILES = $(libcroco_0_6_la_SOURCES)
+croco_EXCLUDES = dummy
+
+croco_HEADERS_DIR = $(crocoincdir)
+croco_HEADERS_INST = $(crocoinc_HEADERS)
+croco_HEADERS_EXCLUDES = dummy
+
+include $(top_srcdir)/win32/Makefile.msvcproj
+
+dist-hook: \
+ $(top_builddir)/win32/vs9/croco.vcproj \
+ $(top_builddir)/win32/vs9/croco.headers
diff --git a/src/3rdparty/libcroco/src/cr-additional-sel.c b/src/3rdparty/libcroco/src/cr-additional-sel.c
new file mode 100644
index 0000000..0296a6d
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-additional-sel.c
@@ -0,0 +1,456 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ *
+ */
+
+#include "cr-additional-sel.h"
+#include "string.h"
+
+/**
+ * CRAdditionalSel:
+ *
+ * #CRAdditionalSel abstracts an additional selector.
+ * An additional selector is the selector part
+ * that comes after the combination of type selectors.
+ * It can be either "a class selector (the .class part),
+ * a pseudo class selector, an attribute selector
+ * or an id selector.
+ */
+
+/**
+ * cr_additional_sel_new:
+ *
+ * Default constructor of #CRAdditionalSel.
+ * Returns the newly build instance of #CRAdditionalSel.
+ */
+CRAdditionalSel *
+cr_additional_sel_new (void)
+{
+ CRAdditionalSel *result = NULL;
+
+ result = g_try_malloc (sizeof (CRAdditionalSel));
+
+ if (result == NULL) {
+ cr_utils_trace_debug ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRAdditionalSel));
+
+ return result;
+}
+
+/**
+ * cr_additional_sel_new_with_type:
+ * @a_sel_type: the type of the newly built instance
+ * of #CRAdditionalSel.
+ *
+ * Constructor of #CRAdditionalSel.
+ * Returns the newly built instance of #CRAdditionalSel.
+ */
+CRAdditionalSel *
+cr_additional_sel_new_with_type (enum AddSelectorType a_sel_type)
+{
+ CRAdditionalSel *result = NULL;
+
+ result = cr_additional_sel_new ();
+
+ g_return_val_if_fail (result, NULL);
+
+ result->type = a_sel_type;
+
+ return result;
+}
+
+/**
+ * cr_additional_sel_set_class_name:
+ * @a_this: the "this pointer" of the current instance
+ * of #CRAdditionalSel .
+ * @a_class_name: the new class name to set.
+ *
+ * Sets a new class name to a
+ * CLASS additional selector.
+ */
+void
+cr_additional_sel_set_class_name (CRAdditionalSel * a_this,
+ CRString * a_class_name)
+{
+ g_return_if_fail (a_this && a_this->type == CLASS_ADD_SELECTOR);
+
+ if (a_this->content.class_name) {
+ cr_string_destroy (a_this->content.class_name);
+ }
+
+ a_this->content.class_name = a_class_name;
+}
+
+/**
+ * cr_additional_sel_set_id_name:
+ * @a_this: the "this pointer" of the current instance
+ * of #CRAdditionalSel .
+ * @a_id: the new id to set.
+ *
+ * Sets a new id name to an
+ * ID additional selector.
+ */
+void
+cr_additional_sel_set_id_name (CRAdditionalSel * a_this, CRString * a_id)
+{
+ g_return_if_fail (a_this && a_this->type == ID_ADD_SELECTOR);
+
+ if (a_this->content.id_name) {
+ cr_string_destroy (a_this->content.id_name);
+ }
+
+ a_this->content.id_name = a_id;
+}
+
+/**
+ * cr_additional_sel_set_pseudo:
+ * @a_this: the "this pointer" of the current instance
+ * of #CRAdditionalSel .
+ * @a_pseudo: the new pseudo to set.
+ *
+ * Sets a new pseudo to a
+ * PSEUDO additional selector.
+ */
+void
+cr_additional_sel_set_pseudo (CRAdditionalSel * a_this, CRPseudo * a_pseudo)
+{
+ g_return_if_fail (a_this
+ && a_this->type == PSEUDO_CLASS_ADD_SELECTOR);
+
+ if (a_this->content.pseudo) {
+ cr_pseudo_destroy (a_this->content.pseudo);
+ }
+
+ a_this->content.pseudo = a_pseudo;
+}
+
+/**
+ * cr_additional_sel_set_attr_sel:
+ * @a_this: the "this pointer" of the current instance
+ * of #CRAdditionalSel .
+ * @a_sel: the new instance of #CRAttrSel to set.
+ *
+ * Sets a new instance of #CRAttrSel to
+ * a ATTRIBUTE additional selector.
+ */
+void
+cr_additional_sel_set_attr_sel (CRAdditionalSel * a_this, CRAttrSel * a_sel)
+{
+ g_return_if_fail (a_this && a_this->type == ATTRIBUTE_ADD_SELECTOR);
+
+ if (a_this->content.attr_sel) {
+ cr_attr_sel_destroy (a_this->content.attr_sel);
+ }
+
+ a_this->content.attr_sel = a_sel;
+}
+
+/**
+ * cr_additional_sel_append:
+ * @a_this: the "this pointer" of the current instance
+ * of #CRAdditionalSel .
+ * @a_sel: the new instance to #CRAdditional to append.
+ *
+ * Appends a new instance of #CRAdditional to the
+ * current list of #CRAdditional.
+ *
+ * Returns the new list of CRAdditionalSel or NULL if an error arises.
+ */
+CRAdditionalSel *
+cr_additional_sel_append (CRAdditionalSel * a_this, CRAdditionalSel * a_sel)
+{
+ CRAdditionalSel *cur_sel = NULL;
+
+ g_return_val_if_fail (a_sel, NULL);
+
+ if (a_this == NULL) {
+ return a_sel;
+ }
+
+ if (a_sel == NULL)
+ return NULL;
+
+ for (cur_sel = a_this;
+ cur_sel && cur_sel->next; cur_sel = cur_sel->next) ;
+
+ g_return_val_if_fail (cur_sel != NULL, NULL);
+
+ cur_sel->next = a_sel;
+ a_sel->prev = cur_sel;
+
+ return a_this;
+}
+
+/**
+ * cr_additional_sel_prepend:
+ * @a_this: the "this pointer" of the current instance
+ * of #CRAdditionalSel .
+ * @a_sel: the new instance to #CRAdditional to preappend.
+ *
+ * Preppends a new instance of #CRAdditional to the
+ * current list of #CRAdditional.
+ *
+ * Returns the new list of CRAdditionalSel or NULL if an error arises.
+ */
+CRAdditionalSel *
+cr_additional_sel_prepend (CRAdditionalSel * a_this, CRAdditionalSel * a_sel)
+{
+ g_return_val_if_fail (a_sel, NULL);
+
+ if (a_this == NULL) {
+ return a_sel;
+ }
+
+ a_sel->next = a_this;
+ a_this->prev = a_sel;
+
+ return a_sel;
+}
+
+guchar *
+cr_additional_sel_to_string (CRAdditionalSel const * a_this)
+{
+ guchar *result = NULL;
+ GString *str_buf = NULL;
+ CRAdditionalSel const *cur = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ str_buf = g_string_new (NULL);
+
+ for (cur = a_this; cur; cur = cur->next) {
+ switch (cur->type) {
+ case CLASS_ADD_SELECTOR:
+ {
+ if (cur->content.class_name) {
+ g_string_append_printf
+ (str_buf, ".%s",
+ cur->content.class_name->stryng->str);
+ }
+ }
+ break;
+
+ case ID_ADD_SELECTOR:
+ {
+ if (cur->content.id_name) {
+ g_string_append_printf
+ (str_buf, "#%s",
+ cur->content.id_name->stryng->str);
+ }
+ }
+
+ break;
+
+ case PSEUDO_CLASS_ADD_SELECTOR:
+ {
+ if (cur->content.pseudo) {
+ guchar *tmp_str = NULL;
+
+ tmp_str = cr_pseudo_to_string
+ (cur->content.pseudo);
+ if (tmp_str) {
+ g_string_append_printf
+ (str_buf, ":%s",
+ tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+ }
+ break;
+
+ case ATTRIBUTE_ADD_SELECTOR:
+ if (cur->content.attr_sel) {
+ guchar *tmp_str = NULL;
+
+ g_string_append_c (str_buf, '[');
+ tmp_str = cr_attr_sel_to_string
+ (cur->content.attr_sel);
+ if (tmp_str) {
+ g_string_append_printf
+ (str_buf, "%s]", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (str_buf) {
+ result = (guchar *) str_buf->str;
+ g_string_free (str_buf, FALSE);
+ str_buf = NULL;
+ }
+
+ return result;
+}
+
+guchar *
+cr_additional_sel_one_to_string (CRAdditionalSel const *a_this)
+{
+ guchar *result = NULL;
+ GString *str_buf = NULL;
+
+ g_return_val_if_fail (a_this, NULL) ;
+
+ str_buf = g_string_new (NULL) ;
+
+ switch (a_this->type) {
+ case CLASS_ADD_SELECTOR:
+ if (a_this->content.class_name) {
+ g_string_append_printf
+ (str_buf, ".%s",
+ a_this->content.class_name->stryng->str);
+ }
+ break;
+
+ case ID_ADD_SELECTOR:
+ if (a_this->content.id_name) {
+ g_string_append_printf
+ (str_buf, "#%s",
+ a_this->content.id_name->stryng->str);
+ }
+
+ break;
+
+ case PSEUDO_CLASS_ADD_SELECTOR:
+ {
+ if (a_this->content.pseudo) {
+ guchar *tmp_str = NULL;
+
+ tmp_str = cr_pseudo_to_string
+ (a_this->content.pseudo);
+ if (tmp_str) {
+ g_string_append_printf
+ (str_buf, ":%s",
+ tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+ }
+ break;
+
+ case ATTRIBUTE_ADD_SELECTOR:
+ if (a_this->content.attr_sel) {
+ guchar *tmp_str = NULL;
+
+ g_string_append_printf (str_buf, "[");
+ tmp_str = cr_attr_sel_to_string
+ (a_this->content.attr_sel);
+ if (tmp_str) {
+ g_string_append_printf
+ (str_buf, "%s]", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (str_buf) {
+ result = (guchar *) str_buf->str;
+ g_string_free (str_buf, FALSE);
+ str_buf = NULL;
+ }
+
+ return result;
+}
+
+/**
+ * cr_additional_sel_dump:
+ * @a_this: the "this pointer" of the current instance of
+ * #CRAdditionalSel.
+ * @a_fp: the destination file.
+ *
+ * Dumps the current instance of #CRAdditionalSel to a file
+ */
+void
+cr_additional_sel_dump (CRAdditionalSel const * a_this, FILE * a_fp)
+{
+ guchar *tmp_str = NULL;
+
+ g_return_if_fail (a_fp);
+
+ if (a_this) {
+ tmp_str = cr_additional_sel_to_string (a_this);
+ if (tmp_str) {
+ fprintf (a_fp, "%s", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+}
+
+/**
+ * cr_additional_sel_destroy:
+ * @a_this: the "this pointer" of the current instance
+ * of #CRAdditionalSel .
+ *
+ * Destroys an instance of #CRAdditional.
+ */
+void
+cr_additional_sel_destroy (CRAdditionalSel * a_this)
+{
+ g_return_if_fail (a_this);
+
+ switch (a_this->type) {
+ case CLASS_ADD_SELECTOR:
+ cr_string_destroy (a_this->content.class_name);
+ a_this->content.class_name = NULL;
+ break;
+
+ case PSEUDO_CLASS_ADD_SELECTOR:
+ cr_pseudo_destroy (a_this->content.pseudo);
+ a_this->content.pseudo = NULL;
+ break;
+
+ case ID_ADD_SELECTOR:
+ cr_string_destroy (a_this->content.id_name);
+ a_this->content.id_name = NULL;
+ break;
+
+ case ATTRIBUTE_ADD_SELECTOR:
+ cr_attr_sel_destroy (a_this->content.attr_sel);
+ a_this->content.attr_sel = NULL;
+ break;
+
+ default:
+ break;
+ }
+
+ if (a_this->next) {
+ cr_additional_sel_destroy (a_this->next);
+ }
+
+ g_free (a_this);
+}
diff --git a/src/3rdparty/libcroco/src/cr-additional-sel.h b/src/3rdparty/libcroco/src/cr-additional-sel.h
new file mode 100644
index 0000000..7ca3e07
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-additional-sel.h
@@ -0,0 +1,98 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See the COPYRIGHTS file for copyright information.
+ */
+
+
+#ifndef __CR_ADD_SEL_H__
+#define __CR_ADD_SEL_H__
+
+#include <stdio.h>
+#include <glib.h>
+#include "cr-utils.h"
+#include "cr-attr-sel.h"
+#include "cr-pseudo.h"
+#include "cr-additional-sel.h"
+
+G_BEGIN_DECLS
+
+enum AddSelectorType
+{
+ NO_ADD_SELECTOR = 0 ,
+ CLASS_ADD_SELECTOR = 1 ,
+ PSEUDO_CLASS_ADD_SELECTOR = 1 << 1,
+ ID_ADD_SELECTOR = 1 << 3,
+ ATTRIBUTE_ADD_SELECTOR = 1 << 4
+} ;
+
+union CRAdditionalSelectorContent
+{
+ CRString *class_name ;
+ CRString *id_name ;
+ CRPseudo *pseudo ;
+ CRAttrSel *attr_sel ;
+} ;
+
+typedef struct _CRAdditionalSel CRAdditionalSel ;
+
+struct _CRAdditionalSel
+{
+ enum AddSelectorType type ;
+ union CRAdditionalSelectorContent content ;
+
+ CRAdditionalSel * next ;
+ CRAdditionalSel * prev ;
+ CRParsingLocation location ;
+} ;
+
+CRAdditionalSel * cr_additional_sel_new (void) ;
+
+CRAdditionalSel * cr_additional_sel_new_with_type (enum AddSelectorType a_sel_type) ;
+
+CRAdditionalSel * cr_additional_sel_append (CRAdditionalSel *a_this,
+ CRAdditionalSel *a_sel) ;
+
+void cr_additional_sel_set_class_name (CRAdditionalSel *a_this,
+ CRString *a_class_name) ;
+
+void cr_additional_sel_set_id_name (CRAdditionalSel *a_this,
+ CRString *a_id) ;
+
+void cr_additional_sel_set_pseudo (CRAdditionalSel *a_this,
+ CRPseudo *a_pseudo) ;
+
+void cr_additional_sel_set_attr_sel (CRAdditionalSel *a_this,
+ CRAttrSel *a_sel) ;
+
+CRAdditionalSel * cr_additional_sel_prepend (CRAdditionalSel *a_this,
+ CRAdditionalSel *a_sel) ;
+
+guchar * cr_additional_sel_to_string (CRAdditionalSel const *a_this) ;
+
+guchar * cr_additional_sel_one_to_string (CRAdditionalSel const *a_this) ;
+
+void cr_additional_sel_dump (CRAdditionalSel const *a_this, FILE *a_fp) ;
+
+void cr_additional_sel_destroy (CRAdditionalSel *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_ADD_SEL_H*/
diff --git a/src/3rdparty/libcroco/src/cr-attr-sel.c b/src/3rdparty/libcroco/src/cr-attr-sel.c
new file mode 100644
index 0000000..b4c64c3
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-attr-sel.c
@@ -0,0 +1,221 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * See COPYRIGHTS file for copyrights information.
+ */
+
+#include <stdio.h>
+#include "cr-attr-sel.h"
+
+/**
+ * CRAttrSel:
+ *
+ * #CRAdditionalSel abstracts an attribute selector.
+ * Attributes selectors are described in the css2 spec [5.8].
+ * There are more generally used in the css2 selectors described in
+ * css2 spec [5] .
+ */
+
+/**
+ * cr_attr_sel_new:
+ * The constructor of #CRAttrSel.
+ * Returns the newly allocated instance
+ * of #CRAttrSel.
+ */
+CRAttrSel *
+cr_attr_sel_new (void)
+{
+ CRAttrSel *result = NULL;
+
+ result = g_malloc0 (sizeof (CRAttrSel));
+
+ return result;
+}
+
+/**
+ * cr_attr_sel_append_attr_sel:
+ * @a_this: the this pointer of the current instance of #CRAttrSel.
+ * @a_attr_sel: selector to append.
+ *
+ * Appends an attribute selector to the current list of
+ * attribute selectors represented by a_this.
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_attr_sel_append_attr_sel (CRAttrSel * a_this, CRAttrSel * a_attr_sel)
+{
+ CRAttrSel *cur_sel = NULL;
+
+ g_return_val_if_fail (a_this && a_attr_sel,
+ CR_BAD_PARAM_ERROR);
+
+ for (cur_sel = a_this;
+ cur_sel->next;
+ cur_sel = cur_sel->next) ;
+
+ cur_sel->next = a_attr_sel;
+ a_attr_sel->prev = cur_sel;
+
+ return CR_OK;
+}
+
+/**
+ * cr_attr_sel_prepend_attr_sel:
+ *@a_this: the "this pointer" of the current instance *of #CRAttrSel.
+ *@a_attr_sel: the attribute selector to append.
+ *
+ *Prepends an attribute selector to the list of
+ *attributes selector represented by a_this.
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_attr_sel_prepend_attr_sel (CRAttrSel * a_this,
+ CRAttrSel * a_attr_sel)
+{
+ g_return_val_if_fail (a_this && a_attr_sel,
+ CR_BAD_PARAM_ERROR);
+
+ a_attr_sel->next = a_this;
+ a_this->prev = a_attr_sel;
+
+ return CR_OK;
+}
+
+/**
+ * cr_attr_sel_to_string:
+ * @a_this: the current instance of #CRAttrSel.
+ *
+ * Serializes an attribute selector into a string
+ * Returns the serialized attribute selector.
+ */
+guchar *
+cr_attr_sel_to_string (CRAttrSel const * a_this)
+{
+ CRAttrSel const *cur = NULL;
+ guchar *result = NULL;
+ GString *str_buf = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ str_buf = g_string_new (NULL);
+
+ for (cur = a_this; cur; cur = cur->next) {
+ if (cur->prev) {
+ g_string_append_c (str_buf, ' ');
+ }
+
+ if (cur->name) {
+ gchar const *name = cur->name->stryng->str;
+ if (name) {
+ g_string_append (str_buf, (const gchar *) name);
+ }
+ }
+
+ if (cur->value) {
+ gchar const *value = cur->value->stryng->str;
+ if (value) {
+ switch (cur->match_way) {
+ case SET:
+ break;
+
+ case EQUALS:
+ g_string_append_c (str_buf, '=');
+ break;
+
+ case INCLUDES:
+ g_string_append (str_buf, "~=");
+ break;
+
+ case DASHMATCH:
+ g_string_append (str_buf, "|=");
+ break;
+
+ default:
+ break;
+ }
+
+ g_string_append_printf
+ (str_buf, "\"%s\"", value);
+ }
+ }
+ }
+
+ if (str_buf) {
+ result = (guchar *) str_buf->str;
+ g_string_free (str_buf, FALSE);
+ }
+
+ return result;
+}
+
+/**
+ * cr_attr_sel_dump:
+ * @a_this: the "this pointer" of the current instance of
+ * #CRAttrSel.
+ * @a_fp: the destination file.
+ *
+ * Dumps the current instance of #CRAttrSel to a file.
+ */
+void
+cr_attr_sel_dump (CRAttrSel const * a_this, FILE * a_fp)
+{
+ guchar *tmp_str = NULL;
+
+ g_return_if_fail (a_this);
+
+ tmp_str = cr_attr_sel_to_string (a_this);
+
+ if (tmp_str) {
+ fprintf (a_fp, "%s", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+}
+
+/**
+ *cr_attr_sel_destroy:
+ *@a_this: the "this pointer" of the current
+ *instance of #CRAttrSel.
+ *
+ *Destroys the current instance of #CRAttrSel.
+ *Frees all the fields if they are non null.
+ */
+void
+cr_attr_sel_destroy (CRAttrSel * a_this)
+{
+ g_return_if_fail (a_this);
+
+ if (a_this->name) {
+ cr_string_destroy (a_this->name);
+ a_this->name = NULL;
+ }
+
+ if (a_this->value) {
+ cr_string_destroy (a_this->value);
+ a_this->value = NULL;
+ }
+
+ if (a_this->next) {
+ cr_attr_sel_destroy (a_this->next);
+ a_this->next = NULL;
+ }
+
+ g_free (a_this);
+}
+
diff --git a/src/3rdparty/libcroco/src/cr-attr-sel.h b/src/3rdparty/libcroco/src/cr-attr-sel.h
new file mode 100644
index 0000000..82d5a87
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-attr-sel.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#ifndef __CR_ATTR_SEL_H__
+#define __CR_ATTR_SEL_H__
+
+#include <stdio.h>
+#include <glib.h>
+#include "cr-utils.h"
+#include "cr-parsing-location.h"
+#include "cr-string.h"
+
+G_BEGIN_DECLS
+
+
+struct _CRAttrSel ;
+typedef struct _CRAttrSel CRAttrSel ;
+
+enum AttrMatchWay
+{
+ NO_MATCH = 0,
+ SET,
+ EQUALS,
+ INCLUDES,
+ DASHMATCH
+} ;
+
+struct _CRAttrSel
+{
+ CRString *name ;
+ CRString *value ;
+ enum AttrMatchWay match_way ;
+ CRAttrSel *next ;
+ CRAttrSel *prev ;
+ CRParsingLocation location ;
+} ;
+
+CRAttrSel * cr_attr_sel_new (void) ;
+
+enum CRStatus cr_attr_sel_append_attr_sel (CRAttrSel * a_this,
+ CRAttrSel *a_attr_sel) ;
+
+enum CRStatus cr_attr_sel_prepend_attr_sel (CRAttrSel *a_this,
+ CRAttrSel *a_attr_sel) ;
+
+guchar * cr_attr_sel_to_string (CRAttrSel const *a_this) ;
+
+void cr_attr_sel_dump (CRAttrSel const *a_this, FILE *a_fp) ;
+
+void cr_attr_sel_destroy (CRAttrSel *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_ATTR_SEL_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-cascade.c b/src/3rdparty/libcroco/src/cr-cascade.c
new file mode 100644
index 0000000..3f32a51
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-cascade.c
@@ -0,0 +1,214 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the
+ * GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the
+ * GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ *$Id$
+ */
+
+#include <string.h>
+#include "cr-cascade.h"
+
+#define PRIVATE(a_this) ((a_this)->priv)
+
+struct _CRCascadePriv {
+ /**
+ *the 3 style sheets of the cascade:
+ *author, user, and useragent sheet.
+ *Intended to be addressed by
+ *sheets[ORIGIN_AUTHOR] or sheets[ORIGIN_USER]
+ *of sheets[ORIGIN_UA] ;
+ */
+ CRStyleSheet *sheets[3];
+ guint ref_count;
+};
+
+/**
+ * cr_cascade_new:
+ *@a_author_sheet: the author origin style sheet. May be NULL.
+ *@a_user_sheet: the user origin style sheet. May be NULL.
+ *@a_ua_sheet: the user agent origin style sheet. May be NULL.
+ *
+ *Constructor of the #CRCascade class.
+ *Note that all three parameters of this
+ *method are ref counted and their refcount is increased.
+ *Their refcount will be decreased at the destruction of
+ *the instance of #CRCascade.
+ *So the caller should not call their destructor. The caller
+ *should call their ref/unref method instead if it wants
+ *
+ *Returns the newly built instance of CRCascade or NULL if
+ *an error arose during construction.
+ */
+CRCascade *
+cr_cascade_new (CRStyleSheet * a_author_sheet,
+ CRStyleSheet * a_user_sheet, CRStyleSheet * a_ua_sheet)
+{
+ CRCascade *result = NULL;
+
+ result = g_try_malloc (sizeof (CRCascade));
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRCascade));
+
+ PRIVATE (result) = g_try_malloc (sizeof (CRCascadePriv));
+ if (!PRIVATE (result)) {
+ cr_utils_trace_info ("Out of memory");
+ g_free (result);
+ return NULL;
+ }
+ memset (PRIVATE (result), 0, sizeof (CRCascadePriv));
+
+ if (a_author_sheet) {
+ cr_cascade_set_sheet (result, a_author_sheet, ORIGIN_AUTHOR);
+ }
+ if (a_user_sheet) {
+ cr_cascade_set_sheet (result, a_user_sheet, ORIGIN_USER);
+ }
+ if (a_ua_sheet) {
+ cr_cascade_set_sheet (result, a_ua_sheet, ORIGIN_UA);
+ }
+
+ return result;
+}
+
+/**
+ * cr_cascade_get_sheet:
+ *@a_this: the current instance of #CRCascade.
+ *@a_origin: the origin of the style sheet as
+ *defined in the css2 spec in chapter 6.4.
+ *Gets a given origin sheet.
+ *
+ *Gets a sheet, part of the cascade.
+ *Note that the returned stylesheet
+ *is refcounted so if the caller wants
+ *to manage its lifecycle, it must use
+ *cr_stylesheet_ref()/cr_stylesheet_unref() instead
+ *of the cr_stylesheet_destroy() method.
+ *Returns the style sheet, or NULL if it does not
+ *exist.
+ */
+CRStyleSheet *
+cr_cascade_get_sheet (CRCascade * a_this, enum CRStyleOrigin a_origin)
+{
+ g_return_val_if_fail (a_this
+ && (unsigned)a_origin < NB_ORIGINS, NULL);
+
+ return PRIVATE (a_this)->sheets[a_origin];
+}
+
+/**
+ * cr_cascade_set_sheet:
+ *@a_this: the current instance of #CRCascade.
+ *@a_sheet: the stylesheet to set. May be NULL.
+ *@a_origin: the origin of the stylesheet.
+ *
+ *Sets a stylesheet in the cascade
+ *
+ *Returns CR_OK upon successful completion, an error
+ *code otherwise.
+ */
+enum CRStatus
+cr_cascade_set_sheet (CRCascade * a_this,
+ CRStyleSheet * a_sheet, enum CRStyleOrigin a_origin)
+{
+ g_return_val_if_fail (a_this
+ && (unsigned)a_origin < NB_ORIGINS, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->sheets[a_origin])
+ cr_stylesheet_unref (PRIVATE (a_this)->sheets[a_origin]);
+ PRIVATE (a_this)->sheets[a_origin] = a_sheet;
+ if (a_sheet) {
+ cr_stylesheet_ref (a_sheet);
+ a_sheet->origin = a_origin;
+ }
+ return CR_OK;
+}
+
+/**
+ *cr_cascade_ref:
+ *@a_this: the current instance of #CRCascade
+ *
+ *Increases the reference counter of the current instance
+ *of #CRCascade.
+ */
+void
+cr_cascade_ref (CRCascade * a_this)
+{
+ g_return_if_fail (a_this && PRIVATE (a_this));
+
+ PRIVATE (a_this)->ref_count++;
+}
+
+/**
+ * cr_cascade_unref:
+ *@a_this: the current instance of
+ *#CRCascade.
+ *
+ *Decrements the reference counter associated
+ *to this instance of #CRCascade. If the reference
+ *counter reaches zero, the instance is destroyed
+ *using cr_cascade_destroy()
+ */
+void
+cr_cascade_unref (CRCascade * a_this)
+{
+ g_return_if_fail (a_this && PRIVATE (a_this));
+
+ if (PRIVATE (a_this)->ref_count)
+ PRIVATE (a_this)->ref_count--;
+ if (!PRIVATE (a_this)->ref_count) {
+ cr_cascade_destroy (a_this);
+ }
+}
+
+/**
+ * cr_cascade_destroy:
+ * @a_this: the current instance of #CRCascade
+ *
+ * Destructor of #CRCascade.
+ */
+void
+cr_cascade_destroy (CRCascade * a_this)
+{
+ g_return_if_fail (a_this);
+
+ if (PRIVATE (a_this)) {
+ gulong i = 0;
+
+ for (i = 0; i < NB_ORIGINS; i++) {
+ if (PRIVATE (a_this)->sheets[i]) {
+ if (cr_stylesheet_unref
+ (PRIVATE (a_this)->sheets[i])
+ == TRUE) {
+ PRIVATE (a_this)->sheets[i] = NULL;
+ }
+ }
+ }
+ g_free (PRIVATE (a_this));
+ PRIVATE (a_this) = NULL;
+ }
+ g_free (a_this);
+}
diff --git a/src/3rdparty/libcroco/src/cr-cascade.h b/src/3rdparty/libcroco/src/cr-cascade.h
new file mode 100644
index 0000000..3119ae8
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-cascade.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the
+ * GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the
+ * GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ */
+
+/*
+ *$Id$
+ */
+
+#ifndef __CR_CASCADE_H__
+#define __CR_CASCADE_H__
+
+#include "cr-stylesheet.h"
+
+/**
+ *@file
+ *the declaration of the #CRCascade class.
+ */
+
+G_BEGIN_DECLS
+
+
+typedef struct _CRCascadePriv CRCascadePriv ;
+
+/**
+ *An abstraction of the "Cascade" defined
+ *in the css2 spec, chapter 6.4.
+ */
+typedef struct _CRCascade CRCascade ;
+
+struct _CRCascade
+{
+ CRCascadePriv *priv ;
+};
+
+
+CRCascade * cr_cascade_new (CRStyleSheet *a_author_sheet,
+ CRStyleSheet *a_user_sheet,
+ CRStyleSheet *a_ua_sheet) ;
+
+CRStyleSheet * cr_cascade_get_sheet (CRCascade *a_this,
+ enum CRStyleOrigin a_origin) ;
+
+enum CRStatus cr_cascade_set_sheet (CRCascade *a_this,
+ CRStyleSheet *a_sheet,
+ enum CRStyleOrigin a_origin) ;
+
+void cr_cascade_ref (CRCascade *a_this) ;
+
+void cr_cascade_unref (CRCascade *a_this) ;
+
+void cr_cascade_destroy (CRCascade *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_CASCADE_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-declaration.c b/src/3rdparty/libcroco/src/cr-declaration.c
new file mode 100644
index 0000000..f998a2a
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-declaration.c
@@ -0,0 +1,794 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli.
+ * See COPYRIGHTS file for copyright information.
+ */
+
+
+#include <string.h>
+#include "cr-declaration.h"
+#include "cr-statement.h"
+#include "cr-parser.h"
+
+/**
+ *@CRDeclaration:
+ *
+ *The definition of the #CRDeclaration class.
+ */
+
+/**
+ * dump:
+ *@a_this: the current instance of #CRDeclaration.
+ *@a_fp: the destination file pointer.
+ *@a_indent: the number of indentation white char.
+ *
+ *Dumps (serializes) one css declaration to a file.
+ */
+static void
+dump (CRDeclaration const * a_this, FILE * a_fp, glong a_indent)
+{
+ guchar *str = NULL;
+
+ g_return_if_fail (a_this);
+
+ str = (guchar *) cr_declaration_to_string (a_this, a_indent);
+ if (str) {
+ fprintf (a_fp, "%s", str);
+ g_free (str);
+ str = NULL;
+ }
+}
+
+/**
+ * cr_declaration_new:
+ * @a_statement: the statement this declaration belongs to. can be NULL.
+ *@a_property: the property string of the declaration
+ *@a_value: the value expression of the declaration.
+ *Constructor of #CRDeclaration.
+ *
+ *Returns the newly built instance of #CRDeclaration, or NULL in
+ *case of error.
+ *
+ *The returned CRDeclaration takes ownership of @a_property and @a_value.
+ *(E.g. cr_declaration_destroy on this CRDeclaration will also free
+ *@a_property and @a_value.)
+ */
+CRDeclaration *
+cr_declaration_new (CRStatement * a_statement,
+ CRString * a_property, CRTerm * a_value)
+{
+ CRDeclaration *result = NULL;
+
+ g_return_val_if_fail (a_property, NULL);
+
+ if (a_statement)
+ g_return_val_if_fail (a_statement
+ && ((a_statement->type == RULESET_STMT)
+ || (a_statement->type
+ == AT_FONT_FACE_RULE_STMT)
+ || (a_statement->type
+ == AT_PAGE_RULE_STMT)), NULL);
+
+ result = g_try_malloc (sizeof (CRDeclaration));
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRDeclaration));
+ result->property = a_property;
+ result->value = a_value;
+
+ if (a_value) {
+ cr_term_ref (a_value);
+ }
+ result->parent_statement = a_statement;
+ return result;
+}
+
+/**
+ * cr_declaration_parse_from_buf:
+ *@a_statement: the parent css2 statement of this
+ *this declaration. Must be non NULL and of type
+ *RULESET_STMT (must be a ruleset).
+ *@a_str: the string that contains the statement.
+ *@a_enc: the encoding of a_str.
+ *
+ *Parses a text buffer that contains
+ *a css declaration.
+ *Returns the parsed declaration, or NULL in case of error.
+ */
+CRDeclaration *
+cr_declaration_parse_from_buf (CRStatement * a_statement,
+ const guchar * a_str, enum CREncoding a_enc)
+{
+ enum CRStatus status = CR_OK;
+ CRTerm *value = NULL;
+ CRString *property = NULL;
+ CRDeclaration *result = NULL;
+ CRParser *parser = NULL;
+ gboolean important = FALSE;
+
+ g_return_val_if_fail (a_str, NULL);
+ if (a_statement)
+ g_return_val_if_fail (a_statement->type == RULESET_STMT,
+ NULL);
+
+ parser = cr_parser_new_from_buf ((guchar*)a_str, strlen ((const char *) a_str), a_enc, FALSE);
+ g_return_val_if_fail (parser, NULL);
+
+ status = cr_parser_try_to_skip_spaces_and_comments (parser);
+ if (status != CR_OK)
+ goto cleanup;
+
+ status = cr_parser_parse_declaration (parser, &property,
+ &value, &important);
+ if (status != CR_OK || !property)
+ goto cleanup;
+
+ result = cr_declaration_new (a_statement, property, value);
+ if (result) {
+ property = NULL;
+ value = NULL;
+ result->important = important;
+ }
+
+ cleanup:
+
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ }
+
+ if (property) {
+ cr_string_destroy (property);
+ property = NULL;
+ }
+
+ if (value) {
+ cr_term_destroy (value);
+ value = NULL;
+ }
+
+ return result;
+}
+
+/**
+ * cr_declaration_parse_list_from_buf:
+ *@a_str: the input buffer that contains the list of declaration to
+ *parse.
+ *@a_enc: the encoding of a_str
+ *
+ *Parses a ';' separated list of properties declaration.
+ *Returns the parsed list of declaration, NULL if parsing failed.
+ */
+CRDeclaration *
+cr_declaration_parse_list_from_buf (const guchar * a_str,
+ enum CREncoding a_enc)
+{
+
+ enum CRStatus status = CR_OK;
+ CRTerm *value = NULL;
+ CRString *property = NULL;
+ CRDeclaration *result = NULL,
+ *cur_decl = NULL;
+ CRParser *parser = NULL;
+ CRTknzr *tokenizer = NULL;
+ gboolean important = FALSE;
+ gboolean first = TRUE;
+
+ g_return_val_if_fail (a_str, NULL);
+
+ parser = cr_parser_new_from_buf ((guchar*)a_str, strlen ((const char *) a_str), a_enc, FALSE);
+ g_return_val_if_fail (parser, NULL);
+ status = cr_parser_get_tknzr (parser, &tokenizer);
+ if (status != CR_OK || !tokenizer) {
+ if (status == CR_OK)
+ status = CR_ERROR;
+ goto cleanup;
+ }
+
+ for (;; first = FALSE) {
+ status = cr_parser_try_to_skip_spaces_and_comments (parser);
+ if (status != CR_OK)
+ goto cleanup;
+
+ if (!first) {
+ guint32 c = 0;
+
+ status = cr_tknzr_peek_char (tokenizer, &c);
+ if (status != CR_OK) {
+ goto cleanup;
+ }
+ if (c == ';') {
+ status = cr_tknzr_read_char (tokenizer, &c);
+ } else {
+ cr_tknzr_read_char (tokenizer, &c);
+ continue; // try to keep reading until we reach the end or a ;
+ }
+ important = FALSE;
+
+ status = cr_parser_try_to_skip_spaces_and_comments (parser);
+ if (status != CR_OK)
+ goto cleanup;
+ }
+
+ status = cr_parser_parse_declaration (parser, &property,
+ &value, &important);
+ if (status != CR_OK || !property) {
+ if (status == CR_END_OF_INPUT_ERROR) {
+ break;
+ } else {
+ continue; // even if one declaration is broken, it's no reason to discard others (see http://www.w3.org/TR/CSS21/syndata.html#declaration)
+ }
+ }
+ cur_decl = cr_declaration_new (NULL, property, value);
+ if (cur_decl) {
+ cur_decl->important = important;
+ if (result) {
+ result = cr_declaration_append (result, cur_decl);
+ } else {
+ result = cur_decl;
+ }
+ property = NULL;
+ value = NULL;
+ cur_decl = NULL;
+ } else {
+ break;
+ }
+ }
+
+ cleanup:
+
+ if (status == CR_END_OF_INPUT_ERROR && result) {
+ status = CR_OK;
+ }
+
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ }
+
+ if (property) {
+ cr_string_destroy (property);
+ property = NULL;
+ }
+
+ if (value) {
+ cr_term_destroy (value);
+ value = NULL;
+ }
+
+ if (status != CR_OK && result) {
+ cr_declaration_destroy (result);
+ result = NULL;
+ }
+ return result;
+}
+
+/**
+ * cr_declaration_append:
+ *@a_this: the current declaration list.
+ *@a_new: the declaration to append.
+ *
+ *Appends a new declaration to the current declarations list.
+ *Returns the declaration list with a_new appended to it, or NULL
+ *in case of error.
+ */
+CRDeclaration *
+cr_declaration_append (CRDeclaration * a_this, CRDeclaration * a_new)
+{
+ CRDeclaration *cur = NULL;
+
+ g_return_val_if_fail (a_new, NULL);
+
+ if (!a_this)
+ return a_new;
+
+ for (cur = a_this; cur && cur->next; cur = cur->next) ;
+
+ cur->next = a_new;
+ a_new->prev = cur;
+
+ return a_this;
+}
+
+/**
+ * cr_declaration_unlink:
+ *@a_decls: the declaration to unlink.
+ *
+ *Unlinks the declaration from the declaration list.
+ *case of a successful completion, NULL otherwise.
+ *
+ *Returns a pointer to the unlinked declaration in
+ */
+CRDeclaration *
+cr_declaration_unlink (CRDeclaration * a_decl)
+{
+ CRDeclaration *result = a_decl;
+
+ g_return_val_if_fail (result, NULL);
+
+ /*
+ *some sanity checks first
+ */
+ if (a_decl->prev) {
+ g_return_val_if_fail (a_decl->prev->next == a_decl, NULL);
+
+ }
+ if (a_decl->next) {
+ g_return_val_if_fail (a_decl->next->prev == a_decl, NULL);
+ }
+
+ /*
+ *now, the real unlinking job.
+ */
+ if (a_decl->prev) {
+ a_decl->prev->next = a_decl->next;
+ }
+ if (a_decl->next) {
+ a_decl->next->prev = a_decl->prev;
+ }
+ if (a_decl->parent_statement) {
+ CRDeclaration **children_decl_ptr = NULL;
+
+ switch (a_decl->parent_statement->type) {
+ case RULESET_STMT:
+ if (a_decl->parent_statement->kind.ruleset) {
+ children_decl_ptr =
+ &a_decl->parent_statement->
+ kind.ruleset->decl_list;
+ }
+
+ break;
+
+ case AT_FONT_FACE_RULE_STMT:
+ if (a_decl->parent_statement->kind.font_face_rule) {
+ children_decl_ptr =
+ &a_decl->parent_statement->
+ kind.font_face_rule->decl_list;
+ }
+ break;
+ case AT_PAGE_RULE_STMT:
+ if (a_decl->parent_statement->kind.page_rule) {
+ children_decl_ptr =
+ &a_decl->parent_statement->
+ kind.page_rule->decl_list;
+ }
+
+ default:
+ break;
+ }
+ if (children_decl_ptr
+ && *children_decl_ptr && *children_decl_ptr == a_decl)
+ *children_decl_ptr = (*children_decl_ptr)->next;
+ }
+
+ a_decl->next = NULL;
+ a_decl->prev = NULL;
+ a_decl->parent_statement = NULL;
+
+ return result;
+}
+
+/**
+ * cr_declaration_prepend:
+ * @a_this: the current declaration list.
+ * @a_new: the declaration to prepend.
+ *
+ * prepends a declaration to the current declaration list.
+ *
+ * Returns the list with a_new prepended or NULL in case of error.
+ */
+CRDeclaration *
+cr_declaration_prepend (CRDeclaration * a_this, CRDeclaration * a_new)
+{
+ CRDeclaration *cur = NULL;
+
+ g_return_val_if_fail (a_new, NULL);
+
+ if (!a_this)
+ return a_new;
+
+ a_this->prev = a_new;
+ a_new->next = a_this;
+
+ for (cur = a_new; cur && cur->prev; cur = cur->prev) ;
+
+ return cur;
+}
+
+/**
+ * cr_declaration_append2:
+ *@a_this: the current declaration list.
+ *@a_prop: the property string of the declaration to append.
+ *@a_value: the value of the declaration to append.
+ *
+ *Appends a declaration to the current declaration list.
+ *Returns the list with the new property appended to it, or NULL in
+ *case of an error.
+ */
+CRDeclaration *
+cr_declaration_append2 (CRDeclaration * a_this,
+ CRString * a_prop, CRTerm * a_value)
+{
+ CRDeclaration *new_elem = NULL;
+
+ if (a_this) {
+ new_elem = cr_declaration_new (a_this->parent_statement,
+ a_prop, a_value);
+ } else {
+ new_elem = cr_declaration_new (NULL, a_prop, a_value);
+ }
+
+ g_return_val_if_fail (new_elem, NULL);
+
+ return cr_declaration_append (a_this, new_elem);
+}
+
+/**
+ * cr_declaration_dump:
+ *@a_this: the current instance of #CRDeclaration.
+ *@a_fp: the destination file.
+ *@a_indent: the number of indentation white char.
+ *@a_one_per_line: whether to put one declaration per line of not .
+ *
+ *
+ *Dumps a declaration list to a file.
+ */
+void
+cr_declaration_dump (CRDeclaration const * a_this, FILE * a_fp, glong a_indent,
+ gboolean a_one_per_line)
+{
+ CRDeclaration const *cur = NULL;
+
+ g_return_if_fail (a_this);
+
+ for (cur = a_this; cur; cur = cur->next) {
+ if (cur->prev) {
+ if (a_one_per_line == TRUE)
+ fprintf (a_fp, ";\n");
+ else
+ fprintf (a_fp, "; ");
+ }
+ dump (cur, a_fp, a_indent);
+ }
+}
+
+/**
+ * cr_declaration_dump_one:
+ *@a_this: the current instance of #CRDeclaration.
+ *@a_fp: the destination file.
+ *@a_indent: the number of indentation white char.
+ *
+ *Dumps the first declaration of the declaration list to a file.
+ */
+void
+cr_declaration_dump_one (CRDeclaration const * a_this, FILE * a_fp, glong a_indent)
+{
+ g_return_if_fail (a_this);
+
+ dump (a_this, a_fp, a_indent);
+}
+
+/**
+ * cr_declaration_to_string:
+ *@a_this: the current instance of #CRDeclaration.
+ *@a_indent: the number of indentation white char
+ *to put before the actual serialisation.
+ *
+ *Serializes the declaration into a string
+ *Returns the serialized form the declaration. The caller must
+ *free the string using g_free().
+ */
+gchar *
+cr_declaration_to_string (CRDeclaration const * a_this, gulong a_indent)
+{
+ GString *stringue = NULL;
+
+ gchar *result = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ stringue = g_string_new (NULL);
+
+ if (a_this->property
+ && a_this->property->stryng
+ && a_this->property->stryng->str) {
+ gchar const *str = a_this->property->stryng->str;
+ if (str) {
+ cr_utils_dump_n_chars2 (' ', stringue,
+ a_indent);
+ g_string_append (stringue, str);
+ } else
+ goto error;
+
+ if (a_this->value) {
+ guchar *value_str = NULL;
+
+ value_str = cr_term_to_string (a_this->value);
+ if (value_str) {
+ g_string_append_printf (stringue, " : %s",
+ value_str);
+ g_free (value_str);
+ } else
+ goto error;
+ }
+ if (a_this->important == TRUE) {
+ g_string_append_printf (stringue, " %s",
+ "!important");
+ }
+ }
+ if (stringue && stringue->str) {
+ result = stringue->str;
+ g_string_free (stringue, FALSE);
+ }
+ return result;
+
+ error:
+ if (stringue) {
+ g_string_free (stringue, TRUE);
+ stringue = NULL;
+ }
+
+ return result;
+}
+
+/**
+ * cr_declaration_list_to_string:
+ *@a_this: the current instance of #CRDeclaration.
+ *@a_indent: the number of indentation white char
+ *to put before the actual serialisation.
+ *
+ *Serializes the declaration list into a string
+ */
+guchar *
+cr_declaration_list_to_string (CRDeclaration const * a_this, gulong a_indent)
+{
+ CRDeclaration const *cur = NULL;
+ GString *stringue = NULL;
+ guchar *str = NULL,
+ *result = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ stringue = g_string_new (NULL);
+
+ for (cur = a_this; cur; cur = cur->next) {
+ str = (guchar *) cr_declaration_to_string (cur, a_indent);
+ if (str) {
+ g_string_append_printf (stringue, "%s;", str);
+ g_free (str);
+ } else
+ break;
+ }
+ if (stringue && stringue->str) {
+ result = (guchar *) stringue->str;
+ g_string_free (stringue, FALSE);
+ }
+
+ return result;
+}
+
+/**
+ * cr_declaration_list_to_string2:
+ *@a_this: the current instance of #CRDeclaration.
+ *@a_indent: the number of indentation white char
+ *@a_one_decl_per_line: whether to output one doc per line or not.
+ *to put before the actual serialisation.
+ *
+ *Serializes the declaration list into a string
+ *Returns the serialized form the declararation.
+ */
+guchar *
+cr_declaration_list_to_string2 (CRDeclaration const * a_this,
+ gulong a_indent, gboolean a_one_decl_per_line)
+{
+ CRDeclaration const *cur = NULL;
+ GString *stringue = NULL;
+ guchar *str = NULL,
+ *result = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ stringue = g_string_new (NULL);
+
+ for (cur = a_this; cur; cur = cur->next) {
+ str = (guchar *) cr_declaration_to_string (cur, a_indent);
+ if (str) {
+ if (a_one_decl_per_line == TRUE) {
+ if (cur->next)
+ g_string_append_printf (stringue,
+ "%s;\n", str);
+ else
+ g_string_append (stringue,
+ (const gchar *) str);
+ } else {
+ if (cur->next)
+ g_string_append_printf (stringue,
+ "%s;", str);
+ else
+ g_string_append (stringue,
+ (const gchar *) str);
+ }
+ g_free (str);
+ } else
+ break;
+ }
+ if (stringue && stringue->str) {
+ result = (guchar *) stringue->str;
+ g_string_free (stringue, FALSE);
+ }
+
+ return result;
+}
+
+/**
+ * cr_declaration_nr_props:
+ *@a_this: the current instance of #CRDeclaration.
+ *Return the number of properties in the declaration
+ */
+gint
+cr_declaration_nr_props (CRDeclaration const * a_this)
+{
+ CRDeclaration const *cur = NULL;
+ int nr = 0;
+
+ g_return_val_if_fail (a_this, -1);
+
+ for (cur = a_this; cur; cur = cur->next)
+ nr++;
+ return nr;
+}
+
+/**
+ * cr_declaration_get_from_list:
+ *@a_this: the current instance of #CRDeclaration.
+ *@itemnr: the index into the declaration list.
+ *
+ *Use an index to get a CRDeclaration from the declaration list.
+ *
+ *Returns #CRDeclaration at position itemnr,
+ *if itemnr > number of declarations - 1,
+ *it will return NULL.
+ */
+CRDeclaration *
+cr_declaration_get_from_list (CRDeclaration * a_this, int itemnr)
+{
+ CRDeclaration *cur = NULL;
+ int nr = 0;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ for (cur = a_this; cur; cur = cur->next)
+ if (nr++ == itemnr)
+ return cur;
+ return NULL;
+}
+
+/**
+ * cr_declaration_get_by_prop_name:
+ *@a_this: the current instance of #CRDeclaration.
+ *@a_prop: the property name to search for.
+ *
+ *Use property name to get a CRDeclaration from the declaration list.
+ *Returns #CRDeclaration with property name a_prop, or NULL if not found.
+ */
+CRDeclaration *
+cr_declaration_get_by_prop_name (CRDeclaration * a_this,
+ const guchar * a_prop)
+{
+ CRDeclaration *cur = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+ g_return_val_if_fail (a_prop, NULL);
+
+ for (cur = a_this; cur; cur = cur->next) {
+ if (cur->property
+ && cur->property->stryng
+ && cur->property->stryng->str) {
+ if (!strcmp (cur->property->stryng->str,
+ (const char *) a_prop)) {
+ return cur;
+ }
+ }
+ }
+ return NULL;
+}
+
+/**
+ * cr_declaration_ref:
+ *@a_this: the current instance of #CRDeclaration.
+ *
+ *Increases the ref count of the current instance of #CRDeclaration.
+ */
+void
+cr_declaration_ref (CRDeclaration * a_this)
+{
+ g_return_if_fail (a_this);
+
+ a_this->ref_count++;
+}
+
+/**
+ * cr_declaration_unref:
+ *@a_this: the current instance of #CRDeclaration.
+ *
+ *Decrements the ref count of the current instance of #CRDeclaration.
+ *If the ref count reaches zero, the current instance of #CRDeclaration
+ *if destroyed.
+ *Returns TRUE if @a_this was destroyed (ref count reached zero),
+ *FALSE otherwise.
+ */
+gboolean
+cr_declaration_unref (CRDeclaration * a_this)
+{
+ g_return_val_if_fail (a_this, FALSE);
+
+ if (a_this->ref_count) {
+ a_this->ref_count--;
+ }
+
+ if (a_this->ref_count == 0) {
+ cr_declaration_destroy (a_this);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * cr_declaration_destroy:
+ *@a_this: the current instance of #CRDeclaration.
+ *
+ *Destructor of the declaration list.
+ */
+void
+cr_declaration_destroy (CRDeclaration * a_this)
+{
+ CRDeclaration *cur = NULL;
+
+ g_return_if_fail (a_this);
+
+ /*
+ * Go to the last element of the list.
+ */
+ for (cur = a_this; cur->next; cur = cur->next)
+ g_assert (cur->next->prev == cur);
+
+ /*
+ * Walk backward the list and free each "next" element.
+ * Meanwhile, free each property/value pair contained in the list.
+ */
+ for (; cur; cur = cur->prev) {
+ g_free (cur->next);
+ cur->next = NULL;
+
+ if (cur->property) {
+ cr_string_destroy (cur->property);
+ cur->property = NULL;
+ }
+
+ if (cur->value) {
+ cr_term_destroy (cur->value);
+ cur->value = NULL;
+ }
+ }
+
+ g_free (a_this);
+}
diff --git a/src/3rdparty/libcroco/src/cr-declaration.h b/src/3rdparty/libcroco/src/cr-declaration.h
new file mode 100644
index 0000000..eee8be3
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-declaration.h
@@ -0,0 +1,136 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * See the COPYRIGHTS file for copyright information.
+ */
+
+#ifndef __CR_DECLARATION_H__
+#define __CR_DECLARATION_H__
+
+#include <stdio.h>
+#include "cr-utils.h"
+#include "cr-term.h"
+#include "cr-parsing-location.h"
+
+G_BEGIN_DECLS
+
+/**
+ *@file
+ *The declaration of the #CRDeclaration class.
+ */
+
+/*forward declaration of what is defined in cr-statement.h*/
+typedef struct _CRStatement CRStatement ;
+
+/**
+ *The abstraction of a css declaration defined by the
+ *css2 spec in chapter 4.
+ *It is actually a chained list of property/value pairs.
+ */
+typedef struct _CRDeclaration CRDeclaration ;
+struct _CRDeclaration
+{
+ /**The property.*/
+ CRString *property ;
+
+ /**The value of the property.*/
+ CRTerm *value ;
+
+ /*the ruleset that contains this declaration*/
+ CRStatement *parent_statement ;
+
+ /*the next declaration*/
+ CRDeclaration *next ;
+
+ /*the previous one declaration*/
+ CRDeclaration *prev ;
+
+ /*does the declaration have the important keyword ?*/
+ gboolean important ;
+
+ glong ref_count ;
+
+ CRParsingLocation location ;
+ /*reserved for future usage*/
+ gpointer rfu0 ;
+ gpointer rfu1 ;
+ gpointer rfu2 ;
+ gpointer rfu3 ;
+} ;
+
+
+CRDeclaration * cr_declaration_new (CRStatement *a_statement,
+ CRString *a_property,
+ CRTerm *a_value) ;
+
+
+CRDeclaration * cr_declaration_parse_from_buf (CRStatement *a_statement,
+ const guchar *a_str,
+ enum CREncoding a_enc) ;
+
+CRDeclaration * cr_declaration_parse_list_from_buf (const guchar *a_str,
+ enum CREncoding a_enc) ;
+
+CRDeclaration * cr_declaration_append (CRDeclaration *a_this,
+ CRDeclaration *a_new) ;
+
+CRDeclaration * cr_declaration_append2 (CRDeclaration *a_this,
+ CRString *a_prop,
+ CRTerm *a_value) ;
+
+CRDeclaration * cr_declaration_prepend (CRDeclaration *a_this,
+ CRDeclaration *a_new) ;
+
+CRDeclaration * cr_declaration_unlink (CRDeclaration * a_decl) ;
+
+void
+cr_declaration_dump (CRDeclaration const *a_this,
+ FILE *a_fp, glong a_indent,
+ gboolean a_one_per_line) ;
+
+void cr_declaration_dump_one (CRDeclaration const *a_this,
+ FILE *a_fp, glong a_indent) ;
+
+gint cr_declaration_nr_props (CRDeclaration const *a_this) ;
+
+CRDeclaration * cr_declaration_get_from_list (CRDeclaration *a_this,
+ int itemnr) ;
+
+CRDeclaration * cr_declaration_get_by_prop_name (CRDeclaration *a_this,
+ const guchar *a_str) ;
+
+gchar * cr_declaration_to_string (CRDeclaration const *a_this,
+ gulong a_indent) ;
+
+guchar * cr_declaration_list_to_string (CRDeclaration const *a_this,
+ gulong a_indent) ;
+
+guchar * cr_declaration_list_to_string2 (CRDeclaration const *a_this,
+ gulong a_indent,
+ gboolean a_one_decl_per_line) ;
+
+void cr_declaration_ref (CRDeclaration *a_this) ;
+
+gboolean cr_declaration_unref (CRDeclaration *a_this) ;
+
+void cr_declaration_destroy (CRDeclaration *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_DECLARATION_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-doc-handler.c b/src/3rdparty/libcroco/src/cr-doc-handler.c
new file mode 100644
index 0000000..b0ef13c
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-doc-handler.c
@@ -0,0 +1,276 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * See COPRYRIGHTS file for copyright information.
+ */
+
+#include <string.h>
+#include "cr-doc-handler.h"
+#include "cr-parser.h"
+
+/**
+ *@CRDocHandler:
+ *
+ *The definition of the CRDocHandler class.
+ *Contains methods to instantiate, destroy,
+ *and initialize instances of #CRDocHandler
+ *to custom values.
+ */
+
+#define PRIVATE(obj) (obj)->priv
+
+struct _CRDocHandlerPriv {
+ /**
+ *This pointer is to hold an application parsing context.
+ *For example, it used by the Object Model parser to
+ *store it parsing context. #CRParser does not touch it, but
+ *#CROMParser does. #CROMParser allocates this pointer at
+ *the beginning of the css document, and frees it at the end
+ *of the document.
+ */
+ gpointer context;
+
+ /**
+ *The place where #CROMParser puts the result of its parsing, if
+ *any.
+ */
+ gpointer result;
+ /**
+ *a pointer to the parser used to parse
+ *the current document.
+ */
+ CRParser *parser ;
+};
+
+/**
+ * cr_doc_handler_new:
+ *Constructor of #CRDocHandler.
+ *
+ *Returns the newly built instance of
+ *#CRDocHandler
+ *
+ */
+CRDocHandler *
+cr_doc_handler_new (void)
+{
+ CRDocHandler *result = NULL;
+
+ result = g_try_malloc (sizeof (CRDocHandler));
+
+ g_return_val_if_fail (result, NULL);
+
+ memset (result, 0, sizeof (CRDocHandler));
+ result->ref_count++;
+
+ result->priv = g_try_malloc (sizeof (CRDocHandlerPriv));
+ if (!result->priv) {
+ cr_utils_trace_info ("Out of memory exception");
+ g_free (result);
+ return NULL;
+ }
+
+ cr_doc_handler_set_default_sac_handler (result);
+
+ return result;
+}
+
+/**
+ * cr_doc_handler_get_ctxt:
+ *@a_this: the current instance of #CRDocHandler.
+ *@a_ctxt: out parameter. The new parsing context.
+ *
+ *Gets the private parsing context associated to the document handler
+ *The private parsing context is used by libcroco only.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_doc_handler_get_ctxt (CRDocHandler const * a_this, gpointer * a_ctxt)
+{
+ g_return_val_if_fail (a_this && a_this->priv, CR_BAD_PARAM_ERROR);
+
+ *a_ctxt = a_this->priv->context;
+
+ return CR_OK;
+}
+
+/**
+ * cr_doc_handler_set_ctxt:
+ *@a_this: the current instance of #CRDocHandler
+ *@a_ctxt: a pointer to the parsing context.
+ *
+ *Sets the private parsing context.
+ *This is used by libcroco only.
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_doc_handler_set_ctxt (CRDocHandler * a_this, gpointer a_ctxt)
+{
+ g_return_val_if_fail (a_this && a_this->priv, CR_BAD_PARAM_ERROR);
+ a_this->priv->context = a_ctxt;
+ return CR_OK;
+}
+
+/**
+ * cr_doc_handler_get_result:
+ *@a_this: the current instance of #CRDocHandler
+ *@a_result: out parameter. The returned result.
+ *
+ *Gets the private parsing result.
+ *The private parsing result is used by libcroco only.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_doc_handler_get_result (CRDocHandler const * a_this, gpointer * a_result)
+{
+ g_return_val_if_fail (a_this && a_this->priv, CR_BAD_PARAM_ERROR);
+
+ *a_result = a_this->priv->result;
+
+ return CR_OK;
+}
+
+/**
+ * cr_doc_handler_set_result:
+ *@a_this: the current instance of #CRDocHandler
+ *@a_result: the new result.
+ *
+ *Sets the private parsing context.
+ *This is used by libcroco only.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_doc_handler_set_result (CRDocHandler * a_this, gpointer a_result)
+{
+ g_return_val_if_fail (a_this && a_this->priv, CR_BAD_PARAM_ERROR);
+ a_this->priv->result = a_result;
+ return CR_OK;
+}
+
+/**
+ *cr_doc_handler_set_default_sac_handler:
+ *@a_this: a pointer to the current instance of #CRDocHandler.
+ *
+ *Sets the sac handlers contained in the current
+ *instance of DocHandler to the default handlers.
+ *For the time being the default handlers are
+ *test handlers. This is expected to change in a
+ *near future, when the libcroco gets a bit debugged.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_doc_handler_set_default_sac_handler (CRDocHandler * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ a_this->start_document = NULL;
+ a_this->end_document = NULL;
+ a_this->import_style = NULL;
+ a_this->namespace_declaration = NULL;
+ a_this->comment = NULL;
+ a_this->start_selector = NULL;
+ a_this->end_selector = NULL;
+ a_this->property = NULL;
+ a_this->start_font_face = NULL;
+ a_this->end_font_face = NULL;
+ a_this->start_media = NULL;
+ a_this->end_media = NULL;
+ a_this->start_page = NULL;
+ a_this->end_page = NULL;
+ a_this->ignorable_at_rule = NULL;
+ a_this->error = NULL;
+ a_this->unrecoverable_error = NULL;
+ return CR_OK;
+}
+
+/**
+ * cr_doc_handler_ref:
+ *@a_this: the current instance of #CRDocHandler.
+ */
+void
+cr_doc_handler_ref (CRDocHandler * a_this)
+{
+ g_return_if_fail (a_this);
+
+ a_this->ref_count++;
+}
+
+/**
+ * cr_doc_handler_unref:
+ *@a_this: the current instance of #CRDocHandler.
+ *
+ *Decreases the ref count of the current instance of #CRDocHandler.
+ *If the ref count reaches '0' then, destroys the instance.
+ *
+ *Returns TRUE if the instance as been destroyed, FALSE otherwise.
+ */
+gboolean
+cr_doc_handler_unref (CRDocHandler * a_this)
+{
+ g_return_val_if_fail (a_this, FALSE);
+
+ if (a_this->ref_count > 0) {
+ a_this->ref_count--;
+ }
+
+ if (a_this->ref_count == 0) {
+ cr_doc_handler_destroy (a_this);
+ return TRUE;
+ }
+ return FALSE ;
+}
+
+/**
+ * cr_doc_handler_destroy:
+ *@a_this: the instance of #CRDocHandler to
+ *destroy.
+ *
+ *The destructor of the #CRDocHandler class.
+ */
+void
+cr_doc_handler_destroy (CRDocHandler * a_this)
+{
+ g_return_if_fail (a_this);
+
+ if (a_this->priv) {
+ g_free (a_this->priv);
+ a_this->priv = NULL;
+ }
+ g_free (a_this);
+}
+
+/**
+ * cr_doc_handler_associate_a_parser:
+ *Associates a parser to the current document handler
+ *
+ *@a_this: the current instance of document handler.
+ *@a_parser: the parser to associate.
+ */
+void
+cr_doc_handler_associate_a_parser (CRDocHandler *a_this,
+ gpointer a_parser)
+{
+ g_return_if_fail (a_this && PRIVATE (a_this)
+ && a_parser) ;
+
+ PRIVATE (a_this)->parser = a_parser ;
+}
diff --git a/src/3rdparty/libcroco/src/cr-doc-handler.h b/src/3rdparty/libcroco/src/cr-doc-handler.h
new file mode 100644
index 0000000..d12673f
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-doc-handler.h
@@ -0,0 +1,298 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * See the COPYRIGHTS file for copyright information.
+ */
+
+#ifndef __CR_DOC_HANDLER_H__
+#define __CR_DOC_HANDLER_H__
+
+/**
+ *@file
+ *The declaration of the #CRDocumentHandler class.
+ *This class is actually the parsing events handler.
+ */
+
+#include <glib.h>
+#include "cr-utils.h"
+#include "cr-input.h"
+#include "cr-stylesheet.h"
+
+G_BEGIN_DECLS
+
+
+typedef struct _CRDocHandler CRDocHandler ;
+
+struct _CRDocHandlerPriv ;
+typedef struct _CRDocHandlerPriv CRDocHandlerPriv ;
+
+
+/**
+ *The SAC document handler.
+ *An instance of this class is to
+ *be passed to a parser. Then, during the parsing
+ *the parser calls the convenient function pointer
+ *whenever a particular event (a css construction) occurs.
+ */
+struct _CRDocHandler
+{
+ CRDocHandlerPriv *priv ;
+
+ /**
+ *This pointer is to be used by the application for
+ *it custom needs. It is there to extend the doc handler.
+ */
+ gpointer app_data ;
+
+ /**
+ *Is called at the beginning of the parsing of the document.
+ *@param a_this a pointer to the current instance of
+ *#CRDocHandler.
+ */
+ void (*start_document) (CRDocHandler *a_this) ;
+
+ /**
+ *Is called to notify the end of the parsing of the document.
+ *@param a_this a pointer to the current instance of
+ *#CRDocHandler.
+ */
+ void (*end_document) (CRDocHandler *a_this) ;
+
+ /**
+ *Is called to notify an at charset rule.
+ *@param a_this the document handler.
+ *@param a_charset the declared charset.
+ */
+ void (*charset) (CRDocHandler *a_this,
+ CRString *a_charset,
+ CRParsingLocation *a_charset_sym_location) ;
+
+ /**
+ *Is called to notify an import statement in
+ *the stylesheet.
+ *@param a_this the current instance of #CRDocHandler.
+ *@param a_media_list a doubly linked list of GString objects.
+ *Each GString object contains a string which is the
+ *destination media for style information.
+ *@param a_uri the uri of the imported style sheet.
+ *@param a_uri_default_ns the default namespace of URI
+ *@param a_location the parsing location of the '\@import'
+ *keyword.
+ *of the imported style sheet.
+ */
+ void (*import_style) (CRDocHandler *a_this,
+ GList *a_media_list,
+ CRString *a_uri,
+ CRString *a_uri_default_ns,
+ CRParsingLocation *a_location) ;
+
+ void (*import_style_result) (CRDocHandler *a_this,
+ GList *a_media_list,
+ CRString *a_uri,
+ CRString *a_uri_default_ns,
+ CRStyleSheet *a_sheet) ;
+
+ /**
+ *Is called to notify a namespace declaration.
+ *Not used yet.
+ *@param a_this the current instance of #CRDocHandler.
+ *@param a_prefix the prefix of the namespace.
+ *@param a_uri the uri of the namespace.
+ *@param a_location the location of the "@namespace" keyword.
+ */
+ void (*namespace_declaration) (CRDocHandler *a_this,
+ CRString *a_prefix,
+ CRString *a_uri,
+ CRParsingLocation *a_location) ;
+
+ /**
+ *Is called to notify a comment.
+ *@param a_this a pointer to the current instance
+ *of #CRDocHandler.
+ *@param a_comment the comment.
+ */
+ void (*comment) (CRDocHandler *a_this,
+ CRString *a_comment) ;
+
+ /**
+ *Is called to notify the beginning of a rule
+ *statement.
+ *@param a_this the current instance of #CRDocHandler.
+ *@param a_selector_list the list of selectors that precedes
+ *the rule declarations.
+ */
+ void (*start_selector) (CRDocHandler * a_this,
+ CRSelector *a_selector_list) ;
+
+ /**
+ *Is called to notify the end of a rule statement.
+ *@param a_this the current instance of #CRDocHandler.
+ *@param a_selector_list the list of selectors that precedes
+ *the rule declarations. This pointer is the same as
+ *the one passed to start_selector() ;
+ */
+ void (*end_selector) (CRDocHandler *a_this,
+ CRSelector *a_selector_list) ;
+
+
+ /**
+ *Is called to notify a declaration.
+ *@param a_this a pointer to the current instance
+ *of #CRDocHandler.
+ *@param a_name the name of the parsed property.
+ *@param a_expression a css expression that represents
+ *the value of the property. A css expression is
+ *actually a linked list of 'terms'. Each term can
+ *be linked to other using operators.
+ *
+ */
+ void (*property) (CRDocHandler *a_this,
+ CRString *a_name,
+ CRTerm *a_expression,
+ gboolean a_is_important) ;
+ /**
+ *Is called to notify the start of a font face statement.
+ *The parser invokes this method at the beginning of every
+ *font face statement in the style sheet. There will
+ *be a corresponding end_font_face () event for every
+ *start_font_face () event.
+ *
+ *@param a_this a pointer to the current instance of
+ *#CRDocHandler.
+ *@param a_location the parsing location of the "\@font-face"
+ *keyword.
+ */
+ void (*start_font_face) (CRDocHandler *a_this,
+ CRParsingLocation *a_location) ;
+
+ /**
+ *Is called to notify the end of a font face statement.
+ *@param a_this a pointer to the current instance of
+ *#CRDocHandler.
+ */
+ void (*end_font_face) (CRDocHandler *a_this) ;
+
+
+ /**
+ *Is called to notify the beginning of a media statement.
+ *The parser will invoke this method at the beginning of
+ *every media statement in the style sheet. There will be
+ *a corresponding end_media() event for every start_media()
+ *event.
+ *@param a_this a pointer to the current instance of
+ *#CRDocHandler.
+ *@param a_media_list a double linked list of
+ #CRString * objects.
+ *Each CRString objects is actually a destination media for
+ *the style information.
+ */
+ void (*start_media) (CRDocHandler *a_this,
+ GList *a_media_list,
+ CRParsingLocation *a_location) ;
+
+ /**
+ *Is called to notify the end of a media statement.
+ *@param a_this a pointer to the current instance
+ *of #CRDocHandler.
+ *@param a_media_list a double linked list of GString * objects.
+ *Each GString objects is actually a destination media for
+ *the style information.
+ */
+ void (*end_media) (CRDocHandler *a_this,
+ GList *a_media_list) ;
+
+ /**
+ *Is called to notify the beginning of a page statement.
+ *The parser invokes this function at the beginning of
+ *every page statement in the style sheet. There will be
+ *a corresponding end_page() event for every single
+ *start_page() event.
+ *@param a_this a pointer to the current instance of
+ *#CRDocHandler.
+ *@param a_name the name of the page (if any, null otherwise).
+ *@param a_pseudo_page the pseudo page (if any, null otherwise).
+ *@param a_location the parsing location of the "\@page" keyword.
+ */
+ void (*start_page) (CRDocHandler *a_this,
+ CRString *a_name,
+ CRString *a_pseudo_page,
+ CRParsingLocation *a_location) ;
+
+ /**
+ *Is called to notify the end of a page statement.
+ *@param a_this a pointer to the current instance of
+ *#CRDocHandler.
+ *@param a_name the name of the page (if any, null otherwise).
+ *@param a_pseudo_page the pseudo page (if any, null otherwise).
+ */
+ void (*end_page) (CRDocHandler *a_this,
+ CRString *a_name,
+ CRString *pseudo_page) ;
+
+ /**
+ *Is Called to notify an unknown at-rule not supported
+ *by this parser.
+ */
+ void (*ignorable_at_rule) (CRDocHandler *a_this,
+ CRString *a_name) ;
+
+ /**
+ *Is called to notify a parsing error. After this error
+ *the application must ignore the rule being parsed, if
+ *any. After completion of this callback,
+ *the parser will then try to resume the parsing,
+ *ignoring the current error.
+ */
+ void (*error) (CRDocHandler *a_this) ;
+
+ /**
+ *Is called to notify an unrecoverable parsing error.
+ *This is the place to put emergency routines that free allocated
+ *resources.
+ */
+ void (*unrecoverable_error) (CRDocHandler *a_this) ;
+
+ gboolean resolve_import ;
+ gulong ref_count ;
+} ;
+
+CRDocHandler * cr_doc_handler_new (void) ;
+
+enum CRStatus cr_doc_handler_set_result (CRDocHandler *a_this, gpointer a_result) ;
+
+enum CRStatus cr_doc_handler_get_result (CRDocHandler const *a_this, gpointer * a_result) ;
+
+enum CRStatus cr_doc_handler_set_ctxt (CRDocHandler *a_this, gpointer a_ctxt) ;
+
+enum CRStatus cr_doc_handler_get_ctxt (CRDocHandler const *a_this, gpointer * a_ctxt) ;
+
+enum CRStatus cr_doc_handler_set_default_sac_handler (CRDocHandler *a_this) ;
+
+void cr_doc_handler_associate_a_parser (CRDocHandler *a_this,
+ gpointer a_parser) ;
+
+void cr_doc_handler_ref (CRDocHandler *a_this) ;
+
+gboolean cr_doc_handler_unref (CRDocHandler *a_this) ;
+
+void cr_doc_handler_destroy (CRDocHandler *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_DOC_HANDLER_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-enc-handler.c b/src/3rdparty/libcroco/src/cr-enc-handler.c
new file mode 100644
index 0000000..65adc7a
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-enc-handler.c
@@ -0,0 +1,184 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ *$Id$
+ */
+
+/**
+ *@file
+ *The definition of the #CREncHandler class.
+ */
+
+#include "cr-enc-handler.h"
+#include "cr-utils.h"
+
+#include <string.h>
+
+struct CREncAlias {
+ const gchar *name;
+ enum CREncoding encoding;
+};
+
+static struct CREncAlias gv_default_aliases[] = {
+ {"UTF-8", CR_UTF_8},
+ {"UTF_8", CR_UTF_8},
+ {"UTF8", CR_UTF_8},
+ {"UTF-16", CR_UTF_16},
+ {"UTF_16", CR_UTF_16},
+ {"UTF16", CR_UTF_16},
+ {"UCS1", CR_UCS_1},
+ {"UCS-1", CR_UCS_1},
+ {"UCS_1", CR_UCS_1},
+ {"ISO-8859-1", CR_UCS_1},
+ {"ISO_8859-1", CR_UCS_1},
+ {"UCS-1", CR_UCS_1},
+ {"UCS_1", CR_UCS_1},
+ {"UCS4", CR_UCS_4},
+ {"UCS-4", CR_UCS_4},
+ {"UCS_4", CR_UCS_4},
+ {"ASCII", CR_ASCII},
+ {0, 0}
+};
+
+static CREncHandler gv_default_enc_handlers[] = {
+ {CR_UCS_1, cr_utils_ucs1_to_utf8, cr_utils_utf8_to_ucs1,
+ cr_utils_ucs1_str_len_as_utf8, cr_utils_utf8_str_len_as_ucs1},
+
+ {CR_ISO_8859_1, cr_utils_ucs1_to_utf8, cr_utils_utf8_to_ucs1,
+ cr_utils_ucs1_str_len_as_utf8, cr_utils_utf8_str_len_as_ucs1},
+
+ {CR_ASCII, cr_utils_ucs1_to_utf8, cr_utils_utf8_to_ucs1,
+ cr_utils_ucs1_str_len_as_utf8, cr_utils_utf8_str_len_as_ucs1},
+
+ {0, NULL, NULL, NULL, NULL}
+};
+
+/**
+ * cr_enc_handler_get_instance:
+ *@a_enc: the encoding of the Handler.
+ *
+ *Gets the instance of encoding handler.
+ *This function implements a singleton pattern.
+ *
+ *Returns the instance of #CREncHandler.
+ */
+CREncHandler *
+cr_enc_handler_get_instance (enum CREncoding a_enc)
+{
+ gulong i = 0;
+
+ for (i = 0; gv_default_enc_handlers[i].encoding; i++) {
+ if (gv_default_enc_handlers[i].encoding == a_enc) {
+ return (CREncHandler *) & gv_default_enc_handlers[i];
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * cr_enc_handler_resolve_enc_alias:
+ *@a_alias_name: the encoding name.
+ *@a_enc: output param. The returned encoding type
+ *or 0 if the alias is not supported.
+ *
+ *Given an encoding name (called an alias name)
+ *the function returns the matching encoding type.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_enc_handler_resolve_enc_alias (const guchar * a_alias_name,
+ enum CREncoding *a_enc)
+{
+ gulong i = 0;
+ guchar *alias_name_up = NULL;
+ enum CRStatus status = CR_ENCODING_NOT_FOUND_ERROR;
+
+ g_return_val_if_fail (a_alias_name != NULL, CR_BAD_PARAM_ERROR);
+
+ alias_name_up = (guchar *) g_ascii_strup ((const gchar *) a_alias_name, -1);
+
+ for (i = 0; gv_default_aliases[i].name; i++) {
+ if (!strcmp (gv_default_aliases[i].name, (const gchar *) alias_name_up)) {
+ *a_enc = gv_default_aliases[i].encoding;
+ status = CR_OK;
+ break;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * cr_enc_handler_convert_input:
+ *@a_this: the current instance of #CREncHandler.
+ *@a_in: the input buffer to convert.
+ *@a_in_len: in/out parameter. The len of the input
+ *buffer to convert. After return, contains the number of
+ *bytes actually consumed.
+ *@a_out: output parameter. The converted output buffer.
+ *Must be freed by the buffer.
+ *@a_out_len: output parameter. The length of the output buffer.
+ *
+ *Converts a raw input buffer into an utf8 buffer.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_enc_handler_convert_input (CREncHandler * a_this,
+ const guchar * a_in,
+ gulong * a_in_len,
+ guchar ** a_out, gulong * a_out_len)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this && a_in && a_in_len && a_out,
+ CR_BAD_PARAM_ERROR);
+
+ if (a_this->decode_input == NULL)
+ return CR_OK;
+
+ if (a_this->enc_str_len_as_utf8) {
+ status = a_this->enc_str_len_as_utf8 (a_in,
+ &a_in[*a_in_len - 1],
+ a_out_len);
+
+ g_return_val_if_fail (status == CR_OK, status);
+ } else {
+ *a_out_len = *a_in_len;
+ }
+
+ *a_out = g_malloc0 (*a_out_len);
+
+ status = a_this->decode_input (a_in, a_in_len, *a_out, a_out_len);
+
+ if (status != CR_OK) {
+ g_free (*a_out);
+ *a_out = NULL;
+ }
+
+ g_return_val_if_fail (status == CR_OK, status);
+
+ return CR_OK;
+}
diff --git a/src/3rdparty/libcroco/src/cr-enc-handler.h b/src/3rdparty/libcroco/src/cr-enc-handler.h
new file mode 100644
index 0000000..0727764
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-enc-handler.h
@@ -0,0 +1,94 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ *$Id$
+ */
+
+/**
+ *@file:
+ *The declaration of the #CREncHandler class.
+ *
+ */
+
+#ifndef __CR_ENC_HANDLER_H__
+#define __CR_ENC_HANDLER_H__
+
+#include "cr-utils.h"
+
+G_BEGIN_DECLS
+
+
+typedef struct _CREncHandler CREncHandler ;
+
+typedef enum CRStatus (*CREncInputFunc) (const guchar * a_in,
+ gulong *a_in_len,
+ guchar *a_out,
+ gulong *a_out_len) ;
+
+typedef enum CRStatus (*CREncOutputFunc) (const guchar * a_in,
+ gulong *a_in_len,
+ guchar *a_out,
+ gulong *a_out_len) ;
+
+typedef enum CRStatus (*CREncInputStrLenAsUtf8Func)
+(const guchar *a_in_start,
+ const guchar *a_in_end,
+ gulong *a_in_size);
+
+typedef enum CRStatus (*CREncUtf8StrLenAsOutputFunc)
+(const guchar *a_in_start,
+ const guchar *a_in_end,
+ gulong *a_in_size) ;
+
+/**
+ *This class is responsible of the
+ *the encoding conversions stuffs in
+ *libcroco.
+ */
+
+struct _CREncHandler
+{
+ enum CREncoding encoding ;
+ CREncInputFunc decode_input ;
+ CREncInputFunc encode_output ;
+ CREncInputStrLenAsUtf8Func enc_str_len_as_utf8 ;
+ CREncUtf8StrLenAsOutputFunc utf8_str_len_as_enc ;
+} ;
+
+CREncHandler *
+cr_enc_handler_get_instance (enum CREncoding a_enc) ;
+
+enum CRStatus
+cr_enc_handler_resolve_enc_alias (const guchar *a_alias_name,
+ enum CREncoding *a_enc) ;
+
+enum CRStatus
+cr_enc_handler_convert_input (CREncHandler *a_this,
+ const guchar *a_in,
+ gulong *a_in_len,
+ guchar **a_out,
+ gulong *a_out_len) ;
+
+G_END_DECLS
+
+#endif /*__CR_ENC_HANDLER_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-fonts.c b/src/3rdparty/libcroco/src/cr-fonts.c
new file mode 100644
index 0000000..3f7a287
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-fonts.c
@@ -0,0 +1,943 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of
+ * the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the
+ * GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ *See COPYRIGHTS file for copyright information
+ */
+
+#include "cr-fonts.h"
+#include <string.h>
+
+static enum CRStatus
+cr_font_family_to_string_real (CRFontFamily const * a_this,
+ gboolean a_walk_list, GString ** a_string)
+{
+ guchar const *name = NULL;
+ enum CRStatus result = CR_OK;
+
+ if (!*a_string) {
+ *a_string = g_string_new (NULL);
+ g_return_val_if_fail (*a_string,
+ CR_INSTANCIATION_FAILED_ERROR);
+ }
+
+ if (!a_this) {
+ g_string_append (*a_string, "NULL");
+ return CR_OK;
+ }
+
+ switch (a_this->type) {
+ case FONT_FAMILY_SANS_SERIF:
+ name = (guchar const *) "sans-serif";
+ break;
+
+ case FONT_FAMILY_SERIF:
+ name = (guchar const *) "sans-serif";
+ break;
+
+ case FONT_FAMILY_CURSIVE:
+ name = (guchar const *) "cursive";
+ break;
+
+ case FONT_FAMILY_FANTASY:
+ name = (guchar const *) "fantasy";
+ break;
+
+ case FONT_FAMILY_MONOSPACE:
+ name = (guchar const *) "monospace";
+ break;
+
+ case FONT_FAMILY_NON_GENERIC:
+ name = (guchar const *) a_this->name;
+ break;
+
+ default:
+ name = NULL;
+ break;
+ }
+
+ if (name) {
+ if (a_this->prev) {
+ g_string_append_printf (*a_string, ", %s", name);
+ } else {
+ g_string_append (*a_string, (const gchar *) name);
+ }
+ }
+ if (a_walk_list == TRUE && a_this->next) {
+ result = cr_font_family_to_string_real (a_this->next,
+ TRUE, a_string);
+ }
+ return result;
+}
+
+static const gchar *
+cr_predefined_absolute_font_size_to_string (enum CRPredefinedAbsoluteFontSize
+ a_code)
+{
+ gchar const *str = NULL;
+
+ switch (a_code) {
+ case FONT_SIZE_XX_SMALL:
+ str = "xx-small";
+ break;
+ case FONT_SIZE_X_SMALL:
+ str = "x-small";
+ break;
+ case FONT_SIZE_SMALL:
+ str = "small";
+ break;
+ case FONT_SIZE_MEDIUM:
+ str = "medium";
+ break;
+ case FONT_SIZE_LARGE:
+ str = "large";
+ break;
+ case FONT_SIZE_X_LARGE:
+ str = "x-large";
+ break;
+ case FONT_SIZE_XX_LARGE:
+ str = "xx-large";
+ break;
+ default:
+ str = "unknown absolute font size value";
+ }
+ return str;
+}
+
+static const gchar *
+cr_relative_font_size_to_string (enum CRRelativeFontSize a_code)
+{
+ gchar const *str = NULL;
+
+ switch (a_code) {
+ case FONT_SIZE_LARGER:
+ str = "larger";
+ break;
+ case FONT_SIZE_SMALLER:
+ str = "smaller";
+ break;
+ default:
+ str = "unknown relative font size value";
+ break;
+ }
+ return str;
+}
+
+/**
+ * cr_font_family_new:
+ * @a_type: the type of font family to create.
+ * @a_name: the name of the font family.
+ *
+ * create a font family.
+ *
+ * Returns the newly built font family.
+ */
+CRFontFamily *
+cr_font_family_new (enum CRFontFamilyType a_type, guchar * a_name)
+{
+ CRFontFamily *result = NULL;
+
+ result = g_try_malloc (sizeof (CRFontFamily));
+
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRFontFamily));
+ result->type = a_type;
+
+ cr_font_family_set_name (result, a_name);
+
+ return result;
+}
+
+/**
+ * cr_font_family_to_string:
+ * @a_this: the current instance of #CRFontFamily.
+ * @a_walk_font_family_list: whether the serialize the entire list.
+ *
+ * Returns the seriliazed font family. The caller has to free it using
+ * g_free().
+ */
+guchar *
+cr_font_family_to_string (CRFontFamily const * a_this,
+ gboolean a_walk_font_family_list)
+{
+ enum CRStatus status = CR_OK;
+ guchar *result = NULL;
+ GString *stringue = NULL;
+
+ if (!a_this) {
+ result = (guchar *) g_strdup ("NULL");
+ g_return_val_if_fail (result, NULL);
+ return result;
+ }
+ status = cr_font_family_to_string_real (a_this,
+ a_walk_font_family_list,
+ &stringue);
+
+ if (status == CR_OK && stringue) {
+ result = (guchar *) stringue->str;
+ g_string_free (stringue, FALSE);
+ stringue = NULL;
+
+ } else {
+ if (stringue) {
+ g_string_free (stringue, TRUE);
+ stringue = NULL;
+ }
+ }
+
+ return result;
+}
+
+/**
+ * cr_font_family_set_name:
+ * @a_this: the current instance of #CRFontFamily.
+ * @a_name: the new name
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_font_family_set_name (CRFontFamily * a_this, guchar * a_name)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ /*
+ *only non generic font families can have a name
+ */
+
+ if (a_this->type != FONT_FAMILY_NON_GENERIC) {
+ return CR_BAD_PARAM_ERROR;
+ }
+
+ if (a_this->name) {
+ g_free (a_this->name);
+ a_this->name = NULL;
+ }
+
+ a_this->name = a_name;
+ return CR_OK;
+}
+
+/**
+ * cr_font_family_append:
+ * @a_this: the current instance of #CRFontFamily.
+ * @a_family_to_append: the font family to append to the list
+ *
+ * Returns the new font family list.
+ */
+CRFontFamily *
+cr_font_family_append (CRFontFamily * a_this,
+ CRFontFamily * a_family_to_append)
+{
+ CRFontFamily *cur_ff = NULL;
+
+ g_return_val_if_fail (a_family_to_append, NULL);
+
+ if (!a_this)
+ return a_family_to_append;
+
+ for (cur_ff = a_this; cur_ff && cur_ff->next; cur_ff = cur_ff->next) ;
+
+ cur_ff->next = a_family_to_append;
+ a_family_to_append->prev = cur_ff;
+
+ return a_this;
+
+}
+
+/**
+ * cr_font_family_prepend:
+ * @a_this: the current instance #CRFontFamily.
+ * @a_family_to_prepend: the font family to prepend to the list.
+ *
+ * Returns the font family list.
+ */
+CRFontFamily *
+cr_font_family_prepend (CRFontFamily * a_this,
+ CRFontFamily * a_family_to_prepend)
+{
+ g_return_val_if_fail (a_this && a_family_to_prepend, NULL);
+
+ if (!a_this)
+ return a_family_to_prepend;
+
+ a_family_to_prepend->next = a_this;
+ a_this->prev = a_family_to_prepend;
+
+ return a_family_to_prepend;
+}
+
+/**
+ * cr_font_family_destroy:
+ * @a_this: the current instance of #CRFontFamily.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_font_family_destroy (CRFontFamily * a_this)
+{
+ CRFontFamily *cur_ff = NULL;
+
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ for (cur_ff = a_this; cur_ff && cur_ff->next; cur_ff = cur_ff->next) ;
+
+ for (; cur_ff; cur_ff = cur_ff->prev) {
+ if (a_this->name) {
+ g_free (a_this->name);
+ a_this->name = NULL;
+ }
+
+ if (cur_ff->next) {
+ g_free (cur_ff->next);
+
+ }
+
+ if (cur_ff->prev == NULL) {
+ g_free (a_this);
+ }
+ }
+
+ return CR_OK;
+}
+
+/***************************************************
+ *'font-size' manipulation functions definitions
+ ***************************************************/
+
+/**
+ * cr_font_size_new:
+ *
+ * Returns the newly created font size.
+ */
+CRFontSize *
+cr_font_size_new (void)
+{
+ CRFontSize *result = NULL;
+
+ result = g_try_malloc (sizeof (CRFontSize));
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRFontSize));
+
+ return result;
+}
+
+/**
+ * cr_font_size_clear:
+ * @a_this: the current instance of #CRFontSize
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_font_size_clear (CRFontSize * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ switch (a_this->type) {
+ case PREDEFINED_ABSOLUTE_FONT_SIZE:
+ case RELATIVE_FONT_SIZE:
+ case INHERITED_FONT_SIZE:
+ memset (a_this, 0, sizeof (CRFontSize));
+ break;
+
+ case ABSOLUTE_FONT_SIZE:
+ memset (a_this, 0, sizeof (CRFontSize));
+ break;
+
+ default:
+ return CR_UNKNOWN_TYPE_ERROR;
+ }
+
+ return CR_OK;
+}
+
+/**
+ * cr_font_size_copy:
+ * @a_dst: the destination #CRFontSize (where to copy to).
+ * @a_src: the source #CRFontSize (where to copy from).
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_font_size_copy (CRFontSize * a_dst, CRFontSize const * a_src)
+{
+ g_return_val_if_fail (a_dst && a_src, CR_BAD_PARAM_ERROR);
+
+ switch (a_src->type) {
+ case PREDEFINED_ABSOLUTE_FONT_SIZE:
+ case RELATIVE_FONT_SIZE:
+ case INHERITED_FONT_SIZE:
+ cr_font_size_clear (a_dst);
+ memcpy (a_dst, a_src, sizeof (CRFontSize));
+ break;
+
+ case ABSOLUTE_FONT_SIZE:
+ cr_font_size_clear (a_dst);
+ cr_num_copy (&a_dst->value.absolute,
+ &a_src->value.absolute);
+ a_dst->type = a_src->type;
+ break;
+
+ default:
+ return CR_UNKNOWN_TYPE_ERROR;
+ }
+ return CR_OK;
+}
+
+/**
+ * cr_font_size_set_predefined_absolute_font_size:
+ * @a_this: the current instance of #CRFontSize.
+ * @a_predefined: what to set.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_font_size_set_predefined_absolute_font_size (CRFontSize *a_this,
+ enum CRPredefinedAbsoluteFontSize a_predefined)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
+ g_return_val_if_fail ((unsigned)a_predefined < NB_PREDEFINED_ABSOLUTE_FONT_SIZES,
+ CR_BAD_PARAM_ERROR) ;
+
+ a_this->type = PREDEFINED_ABSOLUTE_FONT_SIZE ;
+ a_this->value.predefined = a_predefined ;
+
+ return CR_OK ;
+}
+
+/**
+ * cr_font_size_set_relative_font_size:
+ * @a_this: the current instance of #CRFontSize
+ * @a_relative: the new relative font size
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_font_size_set_relative_font_size (CRFontSize *a_this,
+ enum CRRelativeFontSize a_relative)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
+ g_return_val_if_fail ((unsigned)a_relative < NB_RELATIVE_FONT_SIZE,
+ CR_BAD_PARAM_ERROR) ;
+
+ a_this->type = RELATIVE_FONT_SIZE ;
+ a_this->value.relative = a_relative ;
+ return CR_OK ;
+}
+
+/**
+ * cr_font_size_set_absolute_font_size:
+ * @a_this: the current instance of #CRFontSize
+ * @a_num_type: the type of number to set.
+ * @a_value: the actual value to set.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_font_size_set_absolute_font_size (CRFontSize *a_this,
+ enum CRNumType a_num_type,
+ gdouble a_value)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
+ g_return_val_if_fail ((unsigned)a_num_type < NB_NUM_TYPE,
+ CR_BAD_PARAM_ERROR) ;
+
+ a_this->type = ABSOLUTE_FONT_SIZE ;
+ cr_num_set (&a_this->value.absolute,
+ a_value, a_num_type) ;
+ return CR_OK ;
+}
+
+/**
+ * cr_font_size_set_to_inherit:
+ * @a_this: the current instance of #CRFontSize
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_font_size_set_to_inherit (CRFontSize *a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
+
+ cr_font_size_clear (a_this) ;
+ a_this->type = INHERITED_FONT_SIZE ;
+
+ return CR_OK ;
+}
+
+/**
+ * cr_font_size_is_set_to_inherit:
+ * @a_this: the current instance of #CRFontSize.
+ *
+ * Returns TRUE if the current instance is set to 'inherit'.
+ */
+gboolean
+cr_font_size_is_set_to_inherit (CRFontSize const *a_this)
+{
+ g_return_val_if_fail (a_this, FALSE) ;
+
+ return a_this->type == INHERITED_FONT_SIZE ;
+}
+
+/**
+ * cr_font_size_to_string:
+ * @a_this: the current instance of #CRFontSize
+ *
+ * Returns the serialized form of #CRFontSize. The returned string
+ * has to bee freed using g_free().
+ */
+gchar *
+cr_font_size_to_string (CRFontSize const * a_this)
+{
+ gchar *str = NULL;
+
+ if (!a_this) {
+ str = g_strdup ("NULL");
+ g_return_val_if_fail (str, NULL);
+ return str;
+ }
+ switch (a_this->type) {
+ case PREDEFINED_ABSOLUTE_FONT_SIZE:
+ str = g_strdup (cr_predefined_absolute_font_size_to_string
+ (a_this->value.predefined));
+ break;
+ case ABSOLUTE_FONT_SIZE:
+ str = (gchar *) cr_num_to_string (&a_this->value.absolute);
+ break;
+ case RELATIVE_FONT_SIZE:
+ str = g_strdup (cr_relative_font_size_to_string
+ (a_this->value.relative));
+ break;
+ case INHERITED_FONT_SIZE:
+ str = g_strdup ("inherit");
+ break;
+ default:
+ break;
+ }
+ return str;
+}
+
+/**
+ * cr_font_size_get_smaller_predefined:
+ * @a_font_size: the font size to consider.
+ * @a_smaller_size: out parameter. The a smaller value than @a_font_size.
+ */
+void
+cr_font_size_get_smaller_predefined_font_size
+ (enum CRPredefinedAbsoluteFontSize a_font_size,
+ enum CRPredefinedAbsoluteFontSize *a_smaller_size)
+{
+ enum CRPredefinedAbsoluteFontSize result = FONT_SIZE_MEDIUM ;
+
+ g_return_if_fail (a_smaller_size) ;
+ g_return_if_fail ((unsigned)a_font_size < NB_PREDEFINED_ABSOLUTE_FONT_SIZES) ;
+
+ switch (a_font_size) {
+ case FONT_SIZE_XX_SMALL:
+ result = FONT_SIZE_XX_SMALL ;
+ break ;
+ case FONT_SIZE_X_SMALL:
+ result = FONT_SIZE_XX_SMALL ;
+ break ;
+ case FONT_SIZE_SMALL:
+ result = FONT_SIZE_X_SMALL;
+ break ;
+ case FONT_SIZE_MEDIUM:
+ result = FONT_SIZE_SMALL;
+ break ;
+ case FONT_SIZE_LARGE:
+ result = FONT_SIZE_MEDIUM;
+ break ;
+ case FONT_SIZE_X_LARGE:
+ result = FONT_SIZE_LARGE;
+ break ;
+ case FONT_SIZE_XX_LARGE:
+ result = FONT_SIZE_XX_LARGE;
+ break ;
+ case FONT_SIZE_INHERIT:
+ cr_utils_trace_info ("can't return a smaller size for FONT_SIZE_INHERIT") ;
+ result = FONT_SIZE_MEDIUM ;
+ break ;
+ default:
+ cr_utils_trace_info ("Unknown FONT_SIZE") ;
+ result = FONT_SIZE_MEDIUM ;
+ break ;
+ }
+ *a_smaller_size = result ;
+}
+
+
+/**
+ * cr_font_size_get_larger_predefined_font_size:
+ * @a_font_size: the font size to consider.
+ * @a_larger_size: out parameter. the font size considered larger than
+ * @a_font_size.
+ *
+ */
+void
+cr_font_size_get_larger_predefined_font_size
+ (enum CRPredefinedAbsoluteFontSize a_font_size,
+ enum CRPredefinedAbsoluteFontSize *a_larger_size)
+{
+ enum CRPredefinedAbsoluteFontSize result = FONT_SIZE_MEDIUM ;
+
+ g_return_if_fail (a_larger_size) ;
+ g_return_if_fail ((unsigned)a_font_size < NB_PREDEFINED_ABSOLUTE_FONT_SIZES) ;
+
+ switch (a_font_size) {
+ case FONT_SIZE_XX_SMALL:
+ result = FONT_SIZE_X_SMALL ;
+ break ;
+ case FONT_SIZE_X_SMALL:
+ result = FONT_SIZE_SMALL ;
+ break ;
+ case FONT_SIZE_SMALL:
+ result = FONT_SIZE_MEDIUM;
+ break ;
+ case FONT_SIZE_MEDIUM:
+ result = FONT_SIZE_LARGE;
+ break ;
+ case FONT_SIZE_LARGE:
+ result = FONT_SIZE_X_LARGE;
+ break ;
+ case FONT_SIZE_X_LARGE:
+ result = FONT_SIZE_XX_LARGE ;
+ break ;
+ case FONT_SIZE_XX_LARGE:
+ result = FONT_SIZE_XX_LARGE;
+ break ;
+ case FONT_SIZE_INHERIT:
+ cr_utils_trace_info ("can't return a bigger size for FONT_SIZE_INHERIT") ;
+ result = FONT_SIZE_MEDIUM ;
+ break ;
+ default:
+ cr_utils_trace_info ("Unknown FONT_SIZE") ;
+ result = FONT_SIZE_MEDIUM ;
+ break ;
+ }
+ *a_larger_size = result ;
+}
+
+/**
+ * cr_font_size_is_predefined_absolute_font_size:
+ * @a_font_size: the font size to consider.
+ *
+ * Returns TRUE if the instance is an predefined absolute font size, FALSE
+ * otherwise.
+ */
+gboolean
+cr_font_size_is_predefined_absolute_font_size
+ (enum CRPredefinedAbsoluteFontSize a_font_size)
+{
+ if ((unsigned)a_font_size < NB_PREDEFINED_ABSOLUTE_FONT_SIZES) {
+ return TRUE ;
+ } else {
+ return FALSE ;
+ }
+}
+
+/**
+ * cr_font_size_adjust_to_string:
+ * @a_this: the instance of #CRFontSizeAdjust.
+ *
+ * Returns the serialized form of #CRFontSizeAdjust
+ */
+gchar *
+cr_font_size_adjust_to_string (CRFontSizeAdjust const * a_this)
+{
+ gchar *str = NULL;
+
+ if (!a_this) {
+ str = g_strdup ("NULL");
+ g_return_val_if_fail (str, NULL);
+ return str;
+ }
+
+ switch (a_this->type) {
+ case FONT_SIZE_ADJUST_NONE:
+ str = g_strdup ("none");
+ break;
+ case FONT_SIZE_ADJUST_NUMBER:
+ if (a_this->num)
+ str = (gchar *) cr_num_to_string (a_this->num);
+ else
+ str = g_strdup ("unknown font-size-adjust property value"); /* Should raise an error no?*/
+ break;
+ case FONT_SIZE_ADJUST_INHERIT:
+ str = g_strdup ("inherit");
+ }
+ return str;
+}
+
+/**
+ * cr_font_style_to_string:
+ * @a_code: the current instance of #CRFontStyle .
+ *
+ * Returns the serialized #CRFontStyle. The caller must free the returned
+ * string using g_free().
+ */
+const gchar *
+cr_font_style_to_string (enum CRFontStyle a_code)
+{
+ gchar *str = NULL;
+
+ switch (a_code) {
+ case FONT_STYLE_NORMAL:
+ str = (gchar *) "normal";
+ break;
+ case FONT_STYLE_ITALIC:
+ str = (gchar *) "italic";
+ break;
+ case FONT_STYLE_OBLIQUE:
+ str = (gchar *) "oblique";
+ break;
+ case FONT_STYLE_INHERIT:
+ str = (gchar *) "inherit";
+ break;
+ default:
+ str = (gchar *) "unknown font style value";
+ break;
+ }
+ return str;
+}
+
+/**
+ * cr_font_variant_to_string:
+ * @a_code: the current instance of #CRFontVariant.
+ *
+ * Returns the serialized form of #CRFontVariant. The caller has
+ * to free the returned string using g_free().
+ */
+const gchar *
+cr_font_variant_to_string (enum CRFontVariant a_code)
+{
+ gchar *str = NULL;
+
+ switch (a_code) {
+ case FONT_VARIANT_NORMAL:
+ str = (gchar *) "normal";
+ break;
+ case FONT_VARIANT_SMALL_CAPS:
+ str = (gchar *) "small-caps";
+ break;
+ case FONT_VARIANT_INHERIT:
+ str = (gchar *) "inherit";
+ break;
+ }
+ return str;
+}
+
+/**
+ * cr_font_weight_get_bolder:
+ * @a_weight: the #CRFontWeight to consider.
+ *
+ * Returns a font weight bolder than @a_weight
+ */
+enum CRFontWeight
+cr_font_weight_get_bolder (enum CRFontWeight a_weight)
+{
+ if (a_weight == FONT_WEIGHT_INHERIT) {
+ cr_utils_trace_info ("can't return a bolder weight for FONT_WEIGHT_INHERIT") ;
+ return a_weight;
+ } else if (a_weight >= FONT_WEIGHT_900) {
+ return FONT_WEIGHT_900 ;
+ } else if (a_weight < FONT_WEIGHT_NORMAL) {
+ return FONT_WEIGHT_NORMAL ;
+ } else if (a_weight == FONT_WEIGHT_BOLDER
+ || a_weight == FONT_WEIGHT_LIGHTER) {
+ cr_utils_trace_info ("FONT_WEIGHT_BOLDER or FONT_WEIGHT_LIGHTER should not appear here") ;
+ return FONT_WEIGHT_NORMAL ;
+ } else {
+ return a_weight << 1 ;
+ }
+}
+
+/**
+ * cr_font_weight_to_string:
+ * @a_code: the font weight to consider.
+ *
+ * Returns the serialized form of #CRFontWeight.
+ */
+const gchar *
+cr_font_weight_to_string (enum CRFontWeight a_code)
+{
+ gchar *str = NULL;
+
+ switch (a_code) {
+ case FONT_WEIGHT_NORMAL:
+ str = (gchar *) "normal";
+ break;
+ case FONT_WEIGHT_BOLD:
+ str = (gchar *) "bold";
+ break;
+ case FONT_WEIGHT_BOLDER:
+ str = (gchar *) "bolder";
+ break;
+ case FONT_WEIGHT_LIGHTER:
+ str = (gchar *) "lighter";
+ break;
+ case FONT_WEIGHT_100:
+ str = (gchar *) "100";
+ break;
+ case FONT_WEIGHT_200:
+ str = (gchar *) "200";
+ break;
+ case FONT_WEIGHT_300:
+ str = (gchar *) "300";
+ break;
+ case FONT_WEIGHT_400:
+ str = (gchar *) "400";
+ break;
+ case FONT_WEIGHT_500:
+ str = (gchar *) "500";
+ break;
+ case FONT_WEIGHT_600:
+ str = (gchar *) "600";
+ break;
+ case FONT_WEIGHT_700:
+ str = (gchar *) "700";
+ break;
+ case FONT_WEIGHT_800:
+ str = (gchar *) "800";
+ break;
+ case FONT_WEIGHT_900:
+ str = (gchar *) "900";
+ break;
+ case FONT_WEIGHT_INHERIT:
+ str = (gchar *) "inherit";
+ break;
+ default:
+ str = (gchar *) "unknown font-weight property value";
+ break;
+ }
+ return str;
+}
+
+/**
+ * cr_font_stretch_to_string:
+ * @a_code: the instance of #CRFontStretch to consider.
+ *
+ * Returns the serialized form of #CRFontStretch.
+ */
+const gchar *
+cr_font_stretch_to_string (enum CRFontStretch a_code)
+{
+ gchar *str = NULL;
+
+ switch (a_code) {
+ case FONT_STRETCH_NORMAL:
+ str = (gchar *) "normal";
+ break;
+ case FONT_STRETCH_WIDER:
+ str = (gchar *) "wider";
+ break;
+ case FONT_STRETCH_NARROWER:
+ str = (gchar *) "narrower";
+ break;
+ case FONT_STRETCH_ULTRA_CONDENSED:
+ str = (gchar *) "ultra-condensed";
+ break;
+ case FONT_STRETCH_EXTRA_CONDENSED:
+ str = (gchar *) "extra-condensed";
+ break;
+ case FONT_STRETCH_CONDENSED:
+ str = (gchar *) "condensed";
+ break;
+ case FONT_STRETCH_SEMI_CONDENSED:
+ str = (gchar *) "semi-condensed";
+ break;
+ case FONT_STRETCH_SEMI_EXPANDED:
+ str = (gchar *) "semi-expanded";
+ break;
+ case FONT_STRETCH_EXPANDED:
+ str = (gchar *) "expanded";
+ break;
+ case FONT_STRETCH_EXTRA_EXPANDED:
+ str = (gchar *) "extra-expaned";
+ break;
+ case FONT_STRETCH_ULTRA_EXPANDED:
+ str = (gchar *) "ultra-expanded";
+ break;
+ case FONT_STRETCH_INHERIT:
+ str = (gchar *) "inherit";
+ break;
+ }
+ return str;
+}
+
+/**
+ * cr_font_size_destroy:
+ * @a_font_size: the font size to destroy
+ *
+ */
+void
+cr_font_size_destroy (CRFontSize * a_font_size)
+{
+ g_return_if_fail (a_font_size);
+
+ g_free (a_font_size) ;
+}
+
+/*******************************************************
+ *'font-size-adjust' manipulation function definition
+ *******************************************************/
+
+/**
+ * cr_font_size_adjust_new:
+ *
+ * Returns a newly built instance of #CRFontSizeAdjust
+ */
+CRFontSizeAdjust *
+cr_font_size_adjust_new (void)
+{
+ CRFontSizeAdjust *result = NULL;
+
+ result = g_try_malloc (sizeof (CRFontSizeAdjust));
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRFontSizeAdjust));
+
+ return result;
+}
+
+/**
+ * cr_font_size_adjust_destroy:
+ * @a_this: the current instance of #CRFontSizeAdjust.
+ *
+ */
+void
+cr_font_size_adjust_destroy (CRFontSizeAdjust * a_this)
+{
+ g_return_if_fail (a_this);
+
+ if (a_this->type == FONT_SIZE_ADJUST_NUMBER && a_this->num) {
+ cr_num_destroy (a_this->num);
+ a_this->num = NULL;
+ }
+}
diff --git a/src/3rdparty/libcroco/src/cr-fonts.h b/src/3rdparty/libcroco/src/cr-fonts.h
new file mode 100644
index 0000000..9eaeeeb
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-fonts.h
@@ -0,0 +1,315 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of
+ * the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the
+ * GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#ifndef __CR_FONTS_H__
+#define __CR_FONTS_H__
+
+#include "cr-utils.h"
+#include "cr-num.h"
+
+/**
+ *@file
+ *Various type declarations about font selection related
+ *properties.
+ */
+G_BEGIN_DECLS
+
+
+enum CRFontFamilyType
+{
+ FONT_FAMILY_SANS_SERIF,
+ FONT_FAMILY_SERIF,
+ FONT_FAMILY_CURSIVE,
+ FONT_FAMILY_FANTASY,
+ FONT_FAMILY_MONOSPACE,
+ FONT_FAMILY_NON_GENERIC,
+ FONT_FAMILY_INHERIT,
+ /**/
+ NB_FONT_FAMILIE_TYPES
+} ;
+
+typedef struct _CRFontFamily CRFontFamily ;
+
+struct _CRFontFamily
+{
+ enum CRFontFamilyType type ;
+
+ /*
+ *The name of the font family, in case
+ *it is non generic.
+ *Is set only if the type is FONT_FAMILY_NON_GENERIC.
+ */
+ guchar *name ;
+
+ CRFontFamily *next ;
+ CRFontFamily *prev ;
+} ;
+
+
+/**
+ *The different types
+ *of absolute font size.
+ *This is used by the 'font-size'
+ *property defined in css2 spec
+ *in chapter 15.2.4 .
+ *These values a indexes of
+ *table of size so please, do not
+ *change their definition order unless
+ *you know what you are doing.
+ */
+enum CRPredefinedAbsoluteFontSize
+{
+ FONT_SIZE_XX_SMALL=0,
+ FONT_SIZE_X_SMALL,
+ FONT_SIZE_SMALL,
+ FONT_SIZE_MEDIUM,
+ FONT_SIZE_LARGE,
+ FONT_SIZE_X_LARGE,
+ FONT_SIZE_XX_LARGE,
+ FONT_SIZE_INHERIT,
+ NB_PREDEFINED_ABSOLUTE_FONT_SIZES
+} ;
+
+/**
+ *The different types
+ *of relative font size.
+ *This is used by the 'font-size'
+ *property defined in css2 spec
+ *in chapter 15.2.4 .
+ *These values a indexes of
+ *table of size so please, do not
+ *change their definition order unless
+ *you know what you are doing.
+ */
+enum CRRelativeFontSize
+{
+ FONT_SIZE_LARGER,
+ FONT_SIZE_SMALLER,
+ NB_RELATIVE_FONT_SIZE
+} ;
+
+/**
+ *The type of font-size property.
+ *Used to define the type of #CRFontSize .
+ *See css2 spec chapter 15.2.4 to understand.
+ */
+enum CRFontSizeType {
+ /**
+ *If the type of #CRFontSize is
+ *PREDEFINED_ABSOLUTE_FONT_SIZE,
+ *the CRFontSize::value.predefined_absolute
+ *field will be defined.
+ */
+ PREDEFINED_ABSOLUTE_FONT_SIZE,
+
+ /**
+ *If the type of #CRFontSize is
+ *ABSOLUTE_FONT_SIZE,
+ *the CRFontSize::value.absolute
+ *field will be defined.
+ */
+ ABSOLUTE_FONT_SIZE,
+
+ /**
+ *If the type of #CRFontSize is
+ *RELATIVE_FONT_SIZE,
+ *the CRFontSize::value.relative
+ *field will be defined.
+ */
+ RELATIVE_FONT_SIZE,
+
+ /**
+ *If the type of #CRFontSize is
+ *INHERITED_FONT_SIZE,
+ *the None of the field of the CRFontSize::value enum
+ *will be defined.
+ */
+ INHERITED_FONT_SIZE,
+
+ NB_FONT_SIZE_TYPE
+} ;
+
+typedef struct _CRFontSize CRFontSize ;
+struct _CRFontSize {
+ enum CRFontSizeType type ;
+ union {
+ enum CRPredefinedAbsoluteFontSize predefined ;
+ enum CRRelativeFontSize relative ;
+ CRNum absolute ;
+ } value;
+} ;
+
+enum CRFontSizeAdjustType
+{
+ FONT_SIZE_ADJUST_NONE = 0,
+ FONT_SIZE_ADJUST_NUMBER,
+ FONT_SIZE_ADJUST_INHERIT
+} ;
+typedef struct _CRFontSizeAdjust CRFontSizeAdjust ;
+struct _CRFontSizeAdjust
+{
+ enum CRFontSizeAdjustType type ;
+ CRNum *num ;
+} ;
+
+enum CRFontStyle
+{
+ FONT_STYLE_NORMAL=0,
+ FONT_STYLE_ITALIC,
+ FONT_STYLE_OBLIQUE,
+ FONT_STYLE_INHERIT
+} ;
+
+enum CRFontVariant
+{
+ FONT_VARIANT_NORMAL=0,
+ FONT_VARIANT_SMALL_CAPS,
+ FONT_VARIANT_INHERIT
+} ;
+
+enum CRFontWeight
+{
+ FONT_WEIGHT_NORMAL = 1,
+ FONT_WEIGHT_BOLD = 1<<1,
+ FONT_WEIGHT_BOLDER = 1<<2,
+ FONT_WEIGHT_LIGHTER = 1<<3,
+ FONT_WEIGHT_100 = 1<<4,
+ FONT_WEIGHT_200 = 1<<5,
+ FONT_WEIGHT_300 = 1<<6,
+ FONT_WEIGHT_400 = 1<<7,
+ FONT_WEIGHT_500 = 1<<8,
+ FONT_WEIGHT_600 = 1<<9,
+ FONT_WEIGHT_700 = 1<<10,
+ FONT_WEIGHT_800 = 1<<11,
+ FONT_WEIGHT_900 = 1<<12,
+ FONT_WEIGHT_INHERIT = 1<<13,
+ NB_FONT_WEIGHTS
+} ;
+
+enum CRFontStretch
+{
+ FONT_STRETCH_NORMAL=0,
+ FONT_STRETCH_WIDER,
+ FONT_STRETCH_NARROWER,
+ FONT_STRETCH_ULTRA_CONDENSED,
+ FONT_STRETCH_EXTRA_CONDENSED,
+ FONT_STRETCH_CONDENSED,
+ FONT_STRETCH_SEMI_CONDENSED,
+ FONT_STRETCH_SEMI_EXPANDED,
+ FONT_STRETCH_EXPANDED,
+ FONT_STRETCH_EXTRA_EXPANDED,
+ FONT_STRETCH_ULTRA_EXPANDED,
+ FONT_STRETCH_INHERIT
+} ;
+
+/**************************************
+ *'font-family' manipulation functions
+ ***************************************/
+CRFontFamily *
+cr_font_family_new (enum CRFontFamilyType a_type, guchar *a_name) ;
+
+CRFontFamily *
+cr_font_family_append (CRFontFamily *a_this,
+ CRFontFamily *a_family_to_append) ;
+
+guchar *
+cr_font_family_to_string (CRFontFamily const *a_this,
+ gboolean a_walk_font_family_list) ;
+
+CRFontFamily *
+cr_font_family_prepend (CRFontFamily *a_this,
+ CRFontFamily *a_family_to_prepend);
+
+enum CRStatus
+cr_font_family_destroy (CRFontFamily *a_this) ;
+
+enum CRStatus
+cr_font_family_set_name (CRFontFamily *a_this, guchar *a_name) ;
+
+
+/************************************
+ *'font-size' manipulation functions
+ ***********************************/
+
+CRFontSize * cr_font_size_new (void) ;
+
+enum CRStatus cr_font_size_clear (CRFontSize *a_this) ;
+
+enum CRStatus cr_font_size_copy (CRFontSize *a_dst,
+ CRFontSize const *a_src) ;
+enum CRStatus cr_font_size_set_predefined_absolute_font_size (CRFontSize *a_this,
+ enum CRPredefinedAbsoluteFontSize a_predefined) ;
+enum CRStatus cr_font_size_set_relative_font_size (CRFontSize *a_this,
+ enum CRRelativeFontSize a_relative) ;
+
+enum CRStatus cr_font_size_set_absolute_font_size (CRFontSize *a_this,
+ enum CRNumType a_num_type,
+ gdouble a_value) ;
+
+enum CRStatus cr_font_size_set_to_inherit (CRFontSize *a_this) ;
+
+gboolean cr_font_size_is_set_to_inherit (CRFontSize const *a_this) ;
+
+gchar* cr_font_size_to_string (CRFontSize const *a_this) ;
+
+void cr_font_size_destroy (CRFontSize *a_font_size) ;
+
+/*******************************************************
+ *'font-size-adjust' manipulation function declarations
+ *******************************************************/
+
+CRFontSizeAdjust * cr_font_size_adjust_new (void) ;
+
+gchar * cr_font_size_adjust_to_string (CRFontSizeAdjust const *a_this) ;
+
+void cr_font_size_adjust_destroy (CRFontSizeAdjust *a_this) ;
+
+void
+cr_font_size_get_smaller_predefined_font_size (enum CRPredefinedAbsoluteFontSize a_font_size,
+ enum CRPredefinedAbsoluteFontSize *a_smaller_size) ;
+void
+cr_font_size_get_larger_predefined_font_size (enum CRPredefinedAbsoluteFontSize a_font_size,
+ enum CRPredefinedAbsoluteFontSize *a_larger_size) ;
+
+gboolean
+cr_font_size_is_predefined_absolute_font_size (enum CRPredefinedAbsoluteFontSize a_font_size) ;
+
+/***********************************
+ *various other font related functions
+ ***********************************/
+const gchar * cr_font_style_to_string (enum CRFontStyle a_code) ;
+
+const gchar * cr_font_weight_to_string (enum CRFontWeight a_code) ;
+
+enum CRFontWeight
+cr_font_weight_get_bolder (enum CRFontWeight a_weight) ;
+
+const gchar * cr_font_variant_to_string (enum CRFontVariant a_code) ;
+
+const gchar * cr_font_stretch_to_string (enum CRFontStretch a_code) ;
+
+G_END_DECLS
+
+#endif
diff --git a/src/3rdparty/libcroco/src/cr-input.c b/src/3rdparty/libcroco/src/cr-input.c
new file mode 100644
index 0000000..645c4c5
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-input.c
@@ -0,0 +1,1181 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include "stdio.h"
+#include <string.h>
+#include "cr-input.h"
+#include "cr-enc-handler.h"
+
+/**
+ *@CRInput:
+ *
+ *The definition of the #CRInput class.
+ */
+
+/*******************
+ *Private type defs
+ *******************/
+
+/**
+ *The private attributes of
+ *the #CRInputPriv class.
+ */
+struct _CRInputPriv {
+ /*
+ *The input buffer
+ */
+ guchar *in_buf;
+ gulong in_buf_size;
+
+ gulong nb_bytes;
+
+ /*
+ *The index of the next byte
+ *to be read.
+ */
+ gulong next_byte_index;
+
+ /*
+ *The current line number
+ */
+ gulong line;
+
+ /*
+ *The current col number
+ */
+ gulong col;
+
+ gboolean end_of_line;
+ gboolean end_of_input;
+
+ /*
+ *the reference count of this
+ *instance.
+ */
+ guint ref_count;
+ gboolean free_in_buf;
+};
+
+#define PRIVATE(object) (object)->priv
+
+/***************************
+ *private constants
+ **************************/
+#define CR_INPUT_MEM_CHUNK_SIZE 1024 * 4
+
+static CRInput *cr_input_new_real (void);
+
+static CRInput *
+cr_input_new_real (void)
+{
+ CRInput *result = NULL;
+
+ result = g_try_malloc (sizeof (CRInput));
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRInput));
+
+ PRIVATE (result) = g_try_malloc (sizeof (CRInputPriv));
+ if (!PRIVATE (result)) {
+ cr_utils_trace_info ("Out of memory");
+ g_free (result);
+ return NULL;
+ }
+ memset (PRIVATE (result), 0, sizeof (CRInputPriv));
+ PRIVATE (result)->free_in_buf = TRUE;
+ return result;
+}
+
+/****************
+ *Public methods
+ ***************/
+
+/**
+ * cr_input_new_from_buf:
+ *@a_buf: the memory buffer to create the input stream from.
+ *The #CRInput keeps this pointer so user should not free it !.
+ *@a_len: the size of the input buffer.
+ *@a_enc: the buffer's encoding.
+ *@a_free_buf: if set to TRUE, this a_buf will be freed
+ *at the destruction of this instance. If set to false, it is up
+ *to the caller to free it.
+ *
+ *Creates a new input stream from a memory buffer.
+ *Returns the newly built instance of #CRInput.
+ */
+CRInput *
+cr_input_new_from_buf (guchar * a_buf,
+ gulong a_len,
+ enum CREncoding a_enc,
+ gboolean a_free_buf)
+{
+ CRInput *result = NULL;
+ enum CRStatus status = CR_OK;
+ CREncHandler *enc_handler = NULL;
+ gulong len = a_len;
+
+ g_return_val_if_fail (a_buf, NULL);
+
+ result = cr_input_new_real ();
+ g_return_val_if_fail (result, NULL);
+
+ /*transform the encoding in utf8 */
+ if (a_enc != CR_UTF_8) {
+ enc_handler = cr_enc_handler_get_instance (a_enc);
+ if (!enc_handler) {
+ goto error;
+ }
+
+ status = cr_enc_handler_convert_input
+ (enc_handler, a_buf, &len,
+ &PRIVATE (result)->in_buf,
+ &PRIVATE (result)->in_buf_size);
+ if (status != CR_OK)
+ goto error;
+ PRIVATE (result)->free_in_buf = TRUE;
+ if (a_free_buf == TRUE && a_buf) {
+ g_free (a_buf) ;
+ a_buf = NULL ;
+ }
+ PRIVATE (result)->nb_bytes = PRIVATE (result)->in_buf_size;
+ } else {
+ PRIVATE (result)->in_buf = (guchar *) a_buf;
+ PRIVATE (result)->in_buf_size = a_len;
+ PRIVATE (result)->nb_bytes = a_len;
+ PRIVATE (result)->free_in_buf = a_free_buf;
+ }
+ PRIVATE (result)->line = 1;
+ PRIVATE (result)->col = 0;
+ return result;
+
+ error:
+ if (result) {
+ cr_input_destroy (result);
+ result = NULL;
+ }
+
+ return NULL;
+}
+
+/**
+ * cr_input_new_from_uri:
+ *@a_file_uri: the file to create *the input stream from.
+ *@a_enc: the encoding of the file *to create the input from.
+ *
+ *Creates a new input stream from
+ *a file.
+ *
+ *Returns the newly created input stream if
+ *this method could read the file and create it,
+ *NULL otherwise.
+ */
+
+CRInput *
+cr_input_new_from_uri (const gchar * a_file_uri, enum CREncoding a_enc)
+{
+ CRInput *result = NULL;
+ enum CRStatus status = CR_OK;
+ FILE *file_ptr = NULL;
+ guchar tmp_buf[CR_INPUT_MEM_CHUNK_SIZE] = { 0 };
+ gulong nb_read = 0,
+ len = 0;
+ gboolean loop = TRUE;
+ guchar *buf = NULL;
+
+ g_return_val_if_fail (a_file_uri, NULL);
+
+ file_ptr = fopen (a_file_uri, "r");
+
+ if (file_ptr == NULL) {
+
+#ifdef CR_DEBUG
+ cr_utils_trace_debug ("could not open file");
+#endif
+ g_warning ("Could not open file %s\n", a_file_uri);
+
+ return NULL;
+ }
+
+ /*load the file */
+ while (loop) {
+ nb_read = fread (tmp_buf, 1 /*read bytes */ ,
+ CR_INPUT_MEM_CHUNK_SIZE /*nb of bytes */ ,
+ file_ptr);
+
+ if (nb_read != CR_INPUT_MEM_CHUNK_SIZE) {
+ /*we read less chars than we wanted */
+ if (feof (file_ptr)) {
+ /*we reached eof */
+ loop = FALSE;
+ } else {
+ /*a pb occurred !! */
+ cr_utils_trace_debug ("an io error occurred");
+ status = CR_ERROR;
+ goto cleanup;
+ }
+ }
+
+ if (status == CR_OK) {
+ /*read went well */
+ buf = g_realloc (buf, len + CR_INPUT_MEM_CHUNK_SIZE);
+ memcpy (buf + len, tmp_buf, nb_read);
+ len += nb_read;
+ }
+ }
+
+ if (status == CR_OK) {
+ result = cr_input_new_from_buf (buf, len, a_enc, TRUE);
+ if (!result) {
+ goto cleanup;
+ }
+ /*
+ *we should free buf here because it's own by CRInput.
+ *(see the last parameter of cr_input_new_from_buf().
+ */
+ buf = NULL;
+ }
+
+ cleanup:
+ if (file_ptr) {
+ fclose (file_ptr);
+ file_ptr = NULL;
+ }
+
+ if (buf) {
+ g_free (buf);
+ buf = NULL;
+ }
+
+ return result;
+}
+
+/**
+ * cr_input_destroy:
+ *@a_this: the current instance of #CRInput.
+ *
+ *The destructor of the #CRInput class.
+ */
+void
+cr_input_destroy (CRInput * a_this)
+{
+ if (a_this == NULL)
+ return;
+
+ if (PRIVATE (a_this)) {
+ if (PRIVATE (a_this)->in_buf && PRIVATE (a_this)->free_in_buf) {
+ g_free (PRIVATE (a_this)->in_buf);
+ PRIVATE (a_this)->in_buf = NULL;
+ }
+
+ g_free (PRIVATE (a_this));
+ PRIVATE (a_this) = NULL;
+ }
+
+ g_free (a_this);
+}
+
+/**
+ * cr_input_ref:
+ *@a_this: the current instance of #CRInput.
+ *
+ *Increments the reference count of the current
+ *instance of #CRInput.
+ */
+void
+cr_input_ref (CRInput * a_this)
+{
+ g_return_if_fail (a_this && PRIVATE (a_this));
+
+ PRIVATE (a_this)->ref_count++;
+}
+
+/**
+ * cr_input_unref:
+ *@a_this: the current instance of #CRInput.
+ *
+ *Decrements the reference count of this instance
+ *of #CRInput. If the reference count goes down to
+ *zero, this instance is destroyed.
+ *
+ * Returns TRUE if the instance of #CRInput got destroyed, false otherwise.
+ */
+gboolean
+cr_input_unref (CRInput * a_this)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), FALSE);
+
+ if (PRIVATE (a_this)->ref_count) {
+ PRIVATE (a_this)->ref_count--;
+ }
+
+ if (PRIVATE (a_this)->ref_count == 0) {
+ cr_input_destroy (a_this);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * cr_input_end_of_input:
+ *@a_this: the current instance of #CRInput.
+ *@a_end_of_input: out parameter. Is set to TRUE if
+ *the current instance has reached the end of its input buffer,
+ *FALSE otherwise.
+ *
+ *Tests whether the current instance of
+ *#CRInput has reached its input buffer.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ * Note that all the out parameters of this method are valid if
+ * and only if this method returns CR_OK.
+ */
+enum CRStatus
+cr_input_end_of_input (CRInput const * a_this, gboolean * a_end_of_input)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_end_of_input, CR_BAD_PARAM_ERROR);
+
+ *a_end_of_input = (PRIVATE (a_this)->next_byte_index
+ >= PRIVATE (a_this)->in_buf_size) ? TRUE : FALSE;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_get_nb_bytes_left:
+ *@a_this: the current instance of #CRInput.
+ *
+ *Returns the number of bytes left in the input stream
+ *before the end, -1 in case of error.
+ */
+glong
+cr_input_get_nb_bytes_left (CRInput const * a_this)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), -1);
+ g_return_val_if_fail (PRIVATE (a_this)->nb_bytes
+ <= PRIVATE (a_this)->in_buf_size, -1);
+ g_return_val_if_fail (PRIVATE (a_this)->next_byte_index
+ <= PRIVATE (a_this)->nb_bytes, -1);
+
+ if (PRIVATE (a_this)->end_of_input)
+ return 0;
+
+ return PRIVATE (a_this)->nb_bytes - PRIVATE (a_this)->next_byte_index;
+}
+
+/**
+ * cr_input_read_byte:
+ *@a_this: the current instance of #CRInput.
+ *@a_byte: out parameter the returned byte.
+ *
+ *Gets the next byte of the input.
+ *Updates the state of the input so that
+ *the next invocation of this method returns
+ *the next coming byte.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise. All the out parameters of this method are valid if
+ *and only if this method returns CR_OK.
+ */
+enum CRStatus
+cr_input_read_byte (CRInput * a_this, guchar * a_byte)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_byte, CR_BAD_PARAM_ERROR);
+
+ g_return_val_if_fail (PRIVATE (a_this)->next_byte_index <=
+ PRIVATE (a_this)->nb_bytes, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->end_of_input == TRUE)
+ return CR_END_OF_INPUT_ERROR;
+
+ *a_byte = PRIVATE (a_this)->in_buf[PRIVATE (a_this)->next_byte_index];
+
+ if (PRIVATE (a_this)->nb_bytes -
+ PRIVATE (a_this)->next_byte_index < 2) {
+ PRIVATE (a_this)->end_of_input = TRUE;
+ } else {
+ PRIVATE (a_this)->next_byte_index++;
+ }
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_read_char:
+ *@a_this: the current instance of CRInput.
+ *@a_char: out parameter. The read character.
+ *
+ *Reads an unicode character from the current instance of
+ *#CRInput.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_input_read_char (CRInput * a_this, guint32 * a_char)
+{
+ enum CRStatus status = CR_OK;
+ gulong consumed = 0,
+ nb_bytes_left = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_char,
+ CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->end_of_input == TRUE)
+ return CR_END_OF_INPUT_ERROR;
+
+ nb_bytes_left = cr_input_get_nb_bytes_left (a_this);
+
+ if (nb_bytes_left < 1) {
+ return CR_END_OF_INPUT_ERROR;
+ }
+
+ status = cr_utils_read_char_from_utf8_buf
+ (PRIVATE (a_this)->in_buf
+ +
+ PRIVATE (a_this)->next_byte_index,
+ nb_bytes_left, a_char, &consumed);
+
+ if (status == CR_OK) {
+ /*update next byte index */
+ PRIVATE (a_this)->next_byte_index += consumed;
+
+ /*update line and column number */
+ if (PRIVATE (a_this)->end_of_line == TRUE) {
+ PRIVATE (a_this)->col = 1;
+ PRIVATE (a_this)->line++;
+ PRIVATE (a_this)->end_of_line = FALSE;
+ } else if (*a_char != '\n') {
+ PRIVATE (a_this)->col++;
+ }
+
+ if (*a_char == '\n') {
+ PRIVATE (a_this)->end_of_line = TRUE;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * cr_input_set_line_num:
+ *@a_this: the "this pointer" of the current instance of #CRInput.
+ *@a_line_num: the new line number.
+ *
+ *Setter of the current line number.
+ *
+ *Return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_set_line_num (CRInput * a_this, glong a_line_num)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->line = a_line_num;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_get_line_num:
+ *@a_this: the "this pointer" of the current instance of #CRInput.
+ *@a_line_num: the returned line number.
+ *
+ *Getter of the current line number.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_get_line_num (CRInput const * a_this, glong * a_line_num)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_line_num, CR_BAD_PARAM_ERROR);
+
+ *a_line_num = PRIVATE (a_this)->line;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_set_column_num:
+ *@a_this: the "this pointer" of the current instance of #CRInput.
+ *@a_col: the new column number.
+ *
+ *Setter of the current column number.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_set_column_num (CRInput * a_this, glong a_col)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->col = a_col;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_get_column_num:
+ *@a_this: the "this pointer" of the current instance of #CRInput.
+ *@a_col: out parameter
+ *
+ *Getter of the current column number.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_get_column_num (CRInput const * a_this, glong * a_col)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_col,
+ CR_BAD_PARAM_ERROR);
+
+ *a_col = PRIVATE (a_this)->col;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_increment_line_num:
+ *@a_this: the "this pointer" of the current instance of #CRInput.
+ *@a_increment: the increment to add to the line number.
+ *
+ *Increments the current line number.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_increment_line_num (CRInput * a_this, glong a_increment)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->line += a_increment;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_increment_col_num:
+ *@a_this: the "this pointer" of the current instance of #CRInput.
+ *@a_increment: the increment to add to the column number.
+ *
+ *Increments the current column number.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_increment_col_num (CRInput * a_this, glong a_increment)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->col += a_increment;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_consume_char:
+ *@a_this: the this pointer.
+ *@a_char: the character to consume. If set to zero,
+ *consumes any character.
+ *
+ *Consumes the next character of the input stream if
+ *and only if that character equals a_char.
+ *
+ *Returns CR_OK upon successful completion, CR_PARSING_ERROR if
+ *next char is different from a_char, an other error code otherwise
+ */
+enum CRStatus
+cr_input_consume_char (CRInput * a_this, guint32 a_char)
+{
+ guint32 c;
+ enum CRStatus status;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ if ((status = cr_input_peek_char (a_this, &c)) != CR_OK) {
+ return status;
+ }
+
+ if (c == a_char || a_char == 0) {
+ status = cr_input_read_char (a_this, &c);
+ } else {
+ return CR_PARSING_ERROR;
+ }
+
+ return status;
+}
+
+/**
+ * cr_input_consume_chars:
+ *@a_this: the this pointer of the current instance of #CRInput.
+ *@a_char: the character to consume.
+ *@a_nb_char: in/out parameter. The number of characters to consume.
+ *If set to a negative value, the function will consume all the occurrences
+ *of a_char found.
+ *After return, if the return value equals CR_OK, this variable contains
+ *the number of characters actually consumed.
+ *
+ *Consumes up to a_nb_char occurrences of the next contiguous characters
+ *which equal a_char. Note that the next character of the input stream
+ **MUST* equal a_char to trigger the consumption, or else, the error
+ *code CR_PARSING_ERROR is returned.
+ *If the number of contiguous characters that equals a_char is less than
+ *a_nb_char, then this function consumes all the characters it can consume.
+ *
+ *Returns CR_OK if at least one character has been consumed, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_input_consume_chars (CRInput * a_this, guint32 a_char, gulong * a_nb_char)
+{
+ enum CRStatus status = CR_OK;
+ gulong nb_consumed = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_nb_char,
+ CR_BAD_PARAM_ERROR);
+
+ g_return_val_if_fail (a_char != 0 || a_nb_char != NULL,
+ CR_BAD_PARAM_ERROR);
+
+ for (nb_consumed = 0; ((status == CR_OK)
+ && (*a_nb_char > 0
+ && nb_consumed < *a_nb_char));
+ nb_consumed++) {
+ status = cr_input_consume_char (a_this, a_char);
+ }
+
+ *a_nb_char = nb_consumed;
+
+ if ((nb_consumed > 0)
+ && ((status == CR_PARSING_ERROR)
+ || (status == CR_END_OF_INPUT_ERROR))) {
+ status = CR_OK;
+ }
+
+ return status;
+}
+
+/**
+ * cr_input_consume_white_spaces:
+ *@a_this: the "this pointer" of the current instance of #CRInput.
+ *@a_nb_chars: in/out parameter. The number of white spaces to
+ *consume. After return, holds the number of white spaces actually consumed.
+ *
+ *Same as cr_input_consume_chars() but this one consumes white
+ *spaces.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_consume_white_spaces (CRInput * a_this, gulong * a_nb_chars)
+{
+ enum CRStatus status = CR_OK;
+ guint32 cur_char = 0,
+ nb_consumed = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_nb_chars,
+ CR_BAD_PARAM_ERROR);
+
+ for (nb_consumed = 0;
+ ((*a_nb_chars > 0) && (nb_consumed < *a_nb_chars));
+ nb_consumed++) {
+ status = cr_input_peek_char (a_this, &cur_char);
+ if (status != CR_OK)
+ break;
+
+ /*if the next char is a white space, consume it ! */
+ if (cr_utils_is_white_space (cur_char) == TRUE) {
+ status = cr_input_read_char (a_this, &cur_char);
+ if (status != CR_OK)
+ break;
+ continue;
+ }
+
+ break;
+
+ }
+
+ *a_nb_chars = (gulong) nb_consumed;
+
+ if (nb_consumed && status == CR_END_OF_INPUT_ERROR) {
+ status = CR_OK;
+ }
+
+ return status;
+}
+
+/**
+ * cr_input_peek_char:
+ *@a_this: the current instance of #CRInput.
+ *@a_char: out parameter. The returned character.
+ *
+ *Same as cr_input_read_char() but does not update the
+ *internal state of the input stream. The next call
+ *to cr_input_peek_char() or cr_input_read_char() will thus
+ *return the same character as the current one.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_input_peek_char (CRInput const * a_this, guint32 * a_char)
+{
+ enum CRStatus status = CR_OK;
+ gulong consumed = 0,
+ nb_bytes_left = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_char, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->next_byte_index >=
+ PRIVATE (a_this)->in_buf_size) {
+ return CR_END_OF_INPUT_ERROR;
+ }
+
+ nb_bytes_left = cr_input_get_nb_bytes_left (a_this);
+
+ if (nb_bytes_left < 1) {
+ return CR_END_OF_INPUT_ERROR;
+ }
+
+ status = cr_utils_read_char_from_utf8_buf
+ (PRIVATE (a_this)->in_buf +
+ PRIVATE (a_this)->next_byte_index,
+ nb_bytes_left, a_char, &consumed);
+
+ return status;
+}
+
+/**
+ * cr_input_peek_byte:
+ *@a_this: the current instance of #CRInput.
+ *@a_origin: the origin to consider in the calculation
+ *of the position of the byte to peek.
+ *@a_offset: the offset of the byte to peek, starting from
+ *the origin specified by a_origin.
+ *@a_byte: out parameter the peeked byte.
+ *
+ *Gets a byte from the input stream,
+ *starting from the current position in the input stream.
+ *Unlike cr_input_peek_next_byte() this method
+ *does not update the state of the current input stream.
+ *Subsequent calls to cr_input_peek_byte with the same arguments
+ *will return the same byte.
+ *
+ *Returns CR_OK upon successful completion or,
+ *CR_BAD_PARAM_ERROR if at least one of the parameters is invalid;
+ *CR_OUT_OF_BOUNDS_ERROR if the indexed byte is out of bounds.
+ */
+enum CRStatus
+cr_input_peek_byte (CRInput const * a_this, enum CRSeekPos a_origin,
+ gulong a_offset, guchar * a_byte)
+{
+ gulong abs_offset = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_byte, CR_BAD_PARAM_ERROR);
+
+ switch (a_origin) {
+
+ case CR_SEEK_CUR:
+ abs_offset = PRIVATE (a_this)->next_byte_index - 1 + a_offset;
+ break;
+
+ case CR_SEEK_BEGIN:
+ abs_offset = a_offset;
+ break;
+
+ case CR_SEEK_END:
+ abs_offset = PRIVATE (a_this)->in_buf_size - 1 - a_offset;
+ break;
+
+ default:
+ return CR_BAD_PARAM_ERROR;
+ }
+
+ if (abs_offset < PRIVATE (a_this)->in_buf_size) {
+
+ *a_byte = PRIVATE (a_this)->in_buf[abs_offset];
+
+ return CR_OK;
+
+ } else {
+ return CR_END_OF_INPUT_ERROR;
+ }
+}
+
+/**
+ * cr_input_peek_byte2:
+ *@a_this: the current byte input stream.
+ *@a_offset: the offset of the byte to peek, starting
+ *from the current input position pointer.
+ *@a_eof: out parameter. Is set to true is we reach end of
+ *stream. If set to NULL by the caller, this parameter is not taken
+ *in account.
+ *
+ *Same as cr_input_peek_byte() but with a simplified
+ *interface.
+ *
+ *Returns the read byte or 0 if something bad happened.
+ */
+guchar
+cr_input_peek_byte2 (CRInput const * a_this, gulong a_offset, gboolean * a_eof)
+{
+ guchar result = 0;
+ enum CRStatus status = CR_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), 0);
+
+ if (a_eof)
+ *a_eof = FALSE;
+
+ status = cr_input_peek_byte (a_this, CR_SEEK_CUR, a_offset, &result);
+
+ if ((status == CR_END_OF_INPUT_ERROR)
+ && a_eof)
+ *a_eof = TRUE;
+
+ return result;
+}
+
+/**
+ * cr_input_get_byte_addr:
+ *@a_this: the current instance of #CRInput.
+ *@a_offset: the offset of the byte in the input stream starting
+ *from the beginning of the stream.
+ *
+ *Gets the memory address of the byte located at a given offset
+ *in the input stream.
+ *
+ *Returns the address, otherwise NULL if an error occurred.
+ */
+guchar *
+cr_input_get_byte_addr (CRInput * a_this, gulong a_offset)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
+
+ if (a_offset >= PRIVATE (a_this)->nb_bytes) {
+ return NULL;
+ }
+
+ return &PRIVATE (a_this)->in_buf[a_offset];
+}
+
+/**
+ * cr_input_get_cur_byte_addr:
+ *@a_this: the current input stream
+ *@a_offset: out parameter. The returned address.
+ *
+ *Gets the address of the current character pointer.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_get_cur_byte_addr (CRInput * a_this, guchar ** a_offset)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_offset,
+ CR_BAD_PARAM_ERROR);
+
+ if (!PRIVATE (a_this)->next_byte_index) {
+ return CR_START_OF_INPUT_ERROR;
+ }
+
+ *a_offset = cr_input_get_byte_addr
+ (a_this, PRIVATE (a_this)->next_byte_index - 1);
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_seek_index:
+ *@a_this: the current instance of #CRInput.
+ *@a_origin: the origin to consider during the calculation
+ *of the absolute position of the new "current byte index".
+ *@a_pos: the relative offset of the new "current byte index."
+ *This offset is relative to the origin a_origin.
+ *
+ *Sets the "current byte index" of the current instance
+ *of #CRInput. Next call to cr_input_get_byte() will return
+ *the byte next after the new "current byte index".
+ *
+ *Returns CR_OK upon successful completion otherwise returns
+ *CR_BAD_PARAM_ERROR if at least one of the parameters is not valid
+ *or CR_OUT_BOUNDS_ERROR in case of error.
+ */
+enum CRStatus
+cr_input_seek_index (CRInput * a_this, enum CRSeekPos a_origin, gint a_pos)
+{
+
+ glong abs_offset = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ switch (a_origin) {
+
+ case CR_SEEK_CUR:
+ abs_offset = PRIVATE (a_this)->next_byte_index - 1 + a_pos;
+ break;
+
+ case CR_SEEK_BEGIN:
+ abs_offset = a_pos;
+ break;
+
+ case CR_SEEK_END:
+ abs_offset = PRIVATE (a_this)->in_buf_size - 1 - a_pos;
+ break;
+
+ default:
+ return CR_BAD_PARAM_ERROR;
+ }
+
+ if ((abs_offset > 0)
+ && (gulong) abs_offset < PRIVATE (a_this)->nb_bytes) {
+
+ /*update the input stream's internal state */
+ PRIVATE (a_this)->next_byte_index = abs_offset + 1;
+
+ return CR_OK;
+ }
+
+ return CR_OUT_OF_BOUNDS_ERROR;
+}
+
+/**
+ * cr_input_get_cur_pos:
+ *@a_this: the current instance of #CRInput.
+ *@a_pos: out parameter. The returned position.
+ *
+ *Gets the position of the "current byte index" which
+ *is basically the position of the last returned byte in the
+ *input stream.
+ *
+ *Returns CR_OK upon successful completion. Otherwise,
+ *CR_BAD_PARAMETER_ERROR if at least one of the arguments is invalid.
+ *CR_START_OF_INPUT if no call to either cr_input_read_byte()
+ *or cr_input_seek_index() have been issued before calling
+ *cr_input_get_cur_pos()
+ *Note that the out parameters of this function are valid if and only if this
+ *function returns CR_OK.
+ */
+enum CRStatus
+cr_input_get_cur_pos (CRInput const * a_this, CRInputPos * a_pos)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pos,
+ CR_BAD_PARAM_ERROR);
+
+ a_pos->next_byte_index = PRIVATE (a_this)->next_byte_index;
+ a_pos->line = PRIVATE (a_this)->line;
+ a_pos->col = PRIVATE (a_this)->col;
+ a_pos->end_of_line = PRIVATE (a_this)->end_of_line;
+ a_pos->end_of_file = PRIVATE (a_this)->end_of_input;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_get_parsing_location:
+ *@a_this: the current instance of #CRInput
+ *@a_loc: the set parsing location.
+ *
+ *Gets the current parsing location.
+ *The Parsing location is a public datastructure that
+ *represents the current line/column/byte offset/ in the input
+ *stream.
+ *
+ *Returns CR_OK upon successful completion, an error
+ *code otherwise.
+ */
+enum CRStatus
+cr_input_get_parsing_location (CRInput const *a_this,
+ CRParsingLocation *a_loc)
+{
+ g_return_val_if_fail (a_this
+ && PRIVATE (a_this)
+ && a_loc,
+ CR_BAD_PARAM_ERROR) ;
+
+ a_loc->line = PRIVATE (a_this)->line ;
+ a_loc->column = PRIVATE (a_this)->col ;
+ if (PRIVATE (a_this)->next_byte_index) {
+ a_loc->byte_offset = PRIVATE (a_this)->next_byte_index - 1 ;
+ } else {
+ a_loc->byte_offset = PRIVATE (a_this)->next_byte_index ;
+ }
+ return CR_OK ;
+}
+
+/**
+ * cr_input_get_cur_index:
+ *@a_this: the "this pointer" of the current instance of
+ *#CRInput
+ *@a_index: out parameter. The returned index.
+ *
+ *Getter of the next byte index.
+ *It actually returns the index of the
+ *next byte to be read.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_input_get_cur_index (CRInput const * a_this, glong * a_index)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_index, CR_BAD_PARAM_ERROR);
+
+ *a_index = PRIVATE (a_this)->next_byte_index;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_set_cur_index:
+ *@a_this: the "this pointer" of the current instance
+ *of #CRInput .
+ *@a_index: the new index to set.
+ *
+ *Setter of the next byte index.
+ *It sets the index of the next byte to be read.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_set_cur_index (CRInput * a_this, glong a_index)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->next_byte_index = a_index;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_set_end_of_file:
+ *@a_this: the current instance of #CRInput.
+ *@a_eof: the new end of file flag.
+ *
+ *Sets the end of file flag.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_set_end_of_file (CRInput * a_this, gboolean a_eof)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->end_of_input = a_eof;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_get_end_of_file:
+ *@a_this: the current instance of #CRInput.
+ *@a_eof: out parameter the place to put the end of
+ *file flag.
+ *
+ *Gets the end of file flag.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_get_end_of_file (CRInput const * a_this, gboolean * a_eof)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_eof, CR_BAD_PARAM_ERROR);
+
+ *a_eof = PRIVATE (a_this)->end_of_input;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_set_end_of_line:
+ *@a_this: the current instance of #CRInput.
+ *@a_eol: the new end of line flag.
+ *
+ *Sets the end of line flag.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_input_set_end_of_line (CRInput * a_this, gboolean a_eol)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->end_of_line = a_eol;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_get_end_of_line:
+ *@a_this: the current instance of #CRInput
+ *@a_eol: out parameter. The place to put
+ *the returned flag
+ *
+ *Gets the end of line flag of the current input.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_input_get_end_of_line (CRInput const * a_this, gboolean * a_eol)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_eol, CR_BAD_PARAM_ERROR);
+
+ *a_eol = PRIVATE (a_this)->end_of_line;
+
+ return CR_OK;
+}
+
+/**
+ * cr_input_set_cur_pos:
+ *@a_this: the "this pointer" of the current instance of
+ *#CRInput.
+ *@a_pos: the new position.
+ *
+ *Sets the current position in the input stream.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_input_set_cur_pos (CRInput * a_this, CRInputPos const * a_pos)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pos,
+ CR_BAD_PARAM_ERROR);
+
+ cr_input_set_column_num (a_this, a_pos->col);
+ cr_input_set_line_num (a_this, a_pos->line);
+ cr_input_set_cur_index (a_this, a_pos->next_byte_index);
+ cr_input_set_end_of_line (a_this, a_pos->end_of_line);
+ cr_input_set_end_of_file (a_this, a_pos->end_of_file);
+
+ return CR_OK;
+}
diff --git a/src/3rdparty/libcroco/src/cr-input.h b/src/3rdparty/libcroco/src/cr-input.h
new file mode 100644
index 0000000..9eb402a
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-input.h
@@ -0,0 +1,174 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See the COPYRIGHTS file for copyrights information.
+ */
+
+#ifndef __CR_INPUT_SRC_H__
+#define __CR_INPUT_SRC_H__
+
+
+#include <glib.h>
+#include "cr-utils.h"
+#include "cr-parsing-location.h"
+
+G_BEGIN_DECLS
+
+/**
+ *@file
+ *The libcroco basic input stream class
+ *declaration file.
+ */
+
+typedef struct _CRInput CRInput ;
+typedef struct _CRInputPriv CRInputPriv ;
+
+/**
+ *The #CRInput class provides the abstraction of
+ *an utf8-encoded character stream.
+ */
+struct _CRInput
+{
+ CRInputPriv *priv ;
+} ;
+
+typedef struct _CRInputPos CRInputPos ;
+
+struct _CRInputPos
+{
+ glong line ;
+ glong col ;
+ gboolean end_of_file ;
+ gboolean end_of_line ;
+ glong next_byte_index ;
+} ;
+
+CRInput *
+cr_input_new_from_buf (guchar *a_buf, gulong a_len,
+ enum CREncoding a_enc, gboolean a_free_buf) ;
+CRInput *
+cr_input_new_from_uri (const gchar *a_file_uri,
+ enum CREncoding a_enc) ;
+
+void
+cr_input_destroy (CRInput *a_this) ;
+
+void
+cr_input_ref (CRInput *a_this) ;
+
+gboolean
+cr_input_unref (CRInput *a_this) ;
+
+enum CRStatus
+cr_input_read_byte (CRInput *a_this, guchar *a_byte) ;
+
+enum CRStatus
+cr_input_read_char (CRInput *a_this, guint32 *a_char) ;
+
+enum CRStatus
+cr_input_consume_chars (CRInput *a_this, guint32 a_char,
+ gulong *a_nb_char) ;
+
+enum CRStatus
+cr_input_consume_char (CRInput *a_this, guint32 a_char) ;
+
+enum CRStatus
+cr_input_consume_white_spaces (CRInput *a_this, gulong *a_nb_chars) ;
+
+enum CRStatus
+cr_input_peek_byte (CRInput const *a_this, enum CRSeekPos a_origin,
+ gulong a_offset, guchar *a_byte) ;
+
+guchar
+cr_input_peek_byte2 (CRInput const *a_this, gulong a_offset,
+ gboolean *a_eof) ;
+
+enum CRStatus
+cr_input_peek_char (CRInput const *a_this, guint32 *a_char) ;
+
+guchar *
+cr_input_get_byte_addr (CRInput *a_this,
+ gulong a_offset) ;
+
+enum CRStatus
+cr_input_get_cur_byte_addr (CRInput *a_this, guchar ** a_offset) ;
+
+enum CRStatus
+cr_input_seek_index (CRInput *a_this,
+ enum CRSeekPos a_origin, gint a_pos) ;
+
+enum CRStatus
+cr_input_get_cur_index (CRInput const *a_this, glong *a_index) ;
+
+enum CRStatus
+cr_input_set_cur_index (CRInput *a_this, glong a_index) ;
+
+enum CRStatus
+cr_input_get_cur_pos (CRInput const *a_this, CRInputPos * a_pos) ;
+
+enum CRStatus
+cr_input_set_cur_pos (CRInput *a_this, CRInputPos const *a_pos) ;
+
+enum CRStatus
+cr_input_get_parsing_location (CRInput const *a_this,
+ CRParsingLocation *a_loc) ;
+
+enum CRStatus
+cr_input_get_end_of_line (CRInput const *a_this, gboolean *a_eol) ;
+
+enum CRStatus
+cr_input_set_end_of_line (CRInput *a_this, gboolean a_eol) ;
+
+enum CRStatus
+cr_input_get_end_of_file (CRInput const *a_this, gboolean *a_eof) ;
+
+enum CRStatus
+cr_input_set_end_of_file (CRInput *a_this, gboolean a_eof) ;
+
+enum CRStatus
+cr_input_set_line_num (CRInput *a_this, glong a_line_num) ;
+
+enum CRStatus
+cr_input_get_line_num (CRInput const *a_this, glong *a_line_num) ;
+
+enum CRStatus
+cr_input_set_column_num (CRInput *a_this, glong a_col) ;
+
+enum CRStatus
+cr_input_get_column_num (CRInput const *a_this, glong *a_col) ;
+
+enum CRStatus
+cr_input_increment_line_num (CRInput *a_this,
+ glong a_increment) ;
+
+enum CRStatus
+cr_input_increment_col_num (CRInput *a_this,
+ glong a_increment) ;
+
+glong
+cr_input_get_nb_bytes_left (CRInput const *a_this) ;
+
+enum CRStatus
+cr_input_end_of_input (CRInput const *a_this, gboolean *a_end_of_input) ;
+
+G_END_DECLS
+
+#endif /*__CR_INPUT_SRC_H__*/
+
diff --git a/src/3rdparty/libcroco/src/cr-libxml-node-iface.c b/src/3rdparty/libcroco/src/cr-libxml-node-iface.c
new file mode 100644
index 0000000..bc860f9
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-libxml-node-iface.c
@@ -0,0 +1,81 @@
+#include <libxml/tree.h>
+#include <string.h>
+#include "cr-libxml-node-iface.h"
+
+static CRXMLNodePtr
+libxml_getParentNode(CRXMLNodePtr cnode)
+{
+ xmlNode const *xnode = (xmlNode const *) cnode;
+ return xnode->parent;
+}
+
+static CRXMLNodePtr
+libxml_getFirstChild(CRXMLNodePtr cnode)
+{
+ xmlNode const *xnode = (xmlNode const *) cnode;
+ return xnode->children;
+}
+
+static CRXMLNodePtr
+libxml_getNextSibling(CRXMLNodePtr cnode)
+{
+ xmlNode const *xnode = (xmlNode const *) cnode;
+ return xnode->next;
+}
+
+static CRXMLNodePtr
+libxml_getPrevSibling(CRXMLNodePtr cnode)
+{
+ xmlNode const *xnode = (xmlNode const *) cnode;
+ return xnode->prev;
+}
+
+static char const *
+local_part(char const *const qname)
+{
+ char const *ret = strrchr(qname, ':');
+ if (ret)
+ return ++ret;
+ else
+ return qname;
+}
+
+static char const *
+libxml_getLocalName(CRXMLNodePtr cnode)
+{
+ xmlNode const *xnode = (xmlNode const *) cnode;
+ return local_part((char *)xnode->name);
+}
+
+static char *
+libxml_getProp(CRXMLNodePtr cnode, char const *cprop)
+{
+ xmlNodePtr xnode = (xmlNodePtr) cnode;
+ xmlChar const *xprop = (xmlChar const *) cprop;
+ return (char *)xmlGetProp(xnode, xprop);
+}
+
+static gboolean
+libxml_isElementNode(CRXMLNodePtr cnode)
+{
+ xmlNode const *xnode = (xmlNode const *) cnode;
+ return xnode->type == XML_ELEMENT_NODE;
+}
+
+static void
+libxml_freePropVal(void *const cval)
+{
+ xmlFree(cval);
+}
+
+CRNodeIface const cr_libxml_node_iface = {
+ libxml_getParentNode,
+ libxml_getFirstChild,
+ libxml_getNextSibling,
+ libxml_getPrevSibling,
+ libxml_getLocalName,
+ libxml_getProp, /* fixme: Check whether we want xmlGetNoNsProp instead. */
+
+ libxml_freePropVal,
+ libxml_isElementNode
+};
diff --git a/src/3rdparty/libcroco/src/cr-libxml-node-iface.h b/src/3rdparty/libcroco/src/cr-libxml-node-iface.h
new file mode 100644
index 0000000..b4a6212
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-libxml-node-iface.h
@@ -0,0 +1,14 @@
+#ifndef __CR_LIBXML_NODE_IFACE_H__
+#define __CR_LIBXML_NODE_IFACE_H__
+
+#include <glib.h>
+#include "cr-node-iface.h"
+
+G_BEGIN_DECLS
+
+extern CRNodeIface const cr_libxml_node_iface;
+
+G_END_DECLS
+
+
+#endif/*__CR_LIBXML_NODE_IFACE_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-node-iface.h b/src/3rdparty/libcroco/src/cr-node-iface.h
new file mode 100644
index 0000000..01898d6
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-node-iface.h
@@ -0,0 +1,34 @@
+#ifndef __CR_NODE_IFACE_H__
+#define __CR_NODE_IFACE_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef gconstpointer CRXMLNodePtr ;
+typedef struct _CRNodeIface CRNodeIface ;
+
+struct _CRNodeIface {
+ /* Names based on DOM. */
+ CRXMLNodePtr (*getParentNode)(CRXMLNodePtr);
+ CRXMLNodePtr (*getFirstChild)(CRXMLNodePtr);
+ CRXMLNodePtr (*getNextSibling)(CRXMLNodePtr);
+ CRXMLNodePtr (*getPrevSibling)(CRXMLNodePtr);
+ char const *(*getLocalName)(CRXMLNodePtr);
+ char *(*getProp)(CRXMLNodePtr, char const *);
+
+ /* Others. */
+ void (*freePropVal)(void *);
+ gboolean (*isElementNode)(CRXMLNodePtr);
+
+#if 0
+ char const *getLang(CRXMLNodePtr);
+ /* todo: Make it easy to have the default xml rules for lang. Maybe interpret NULL
+ like this. Or provide a cr_get_xml_lang(CRNodeIface const *, CRXMLNodePtr) function. */
+#endif
+};
+
+G_END_DECLS
+
+
+#endif/*__CR_NODE_IFACE_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-num.c b/src/3rdparty/libcroco/src/cr-num.c
new file mode 100644
index 0000000..12da520
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-num.c
@@ -0,0 +1,345 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyrights information.
+ */
+
+/**
+ *@CRNum:
+ *
+ *The definition
+ *of the #CRNum class.
+ */
+
+#include "cr-num.h"
+#include "string.h"
+
+#include <float.h>
+#include <math.h>
+#include <stdio.h>
+
+/**
+ * cr_num_new:
+ *
+ *#CRNum.
+ *
+ *Returns the newly built instance of
+ *#CRNum.
+ */
+CRNum *
+cr_num_new (void)
+{
+ CRNum *result = NULL;
+
+ result = g_try_malloc (sizeof (CRNum));
+
+ if (result == NULL) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRNum));
+
+ return result;
+}
+
+/**
+ * cr_num_new_with_val:
+ * @a_val: the numerical value of the number.
+ * @a_type: the type of number.
+ *
+ * A constructor of #CRNum.
+ *
+ * Returns the newly built instance of #CRNum or
+ * NULL if an error arises.
+ */
+CRNum *
+cr_num_new_with_val (gdouble a_val, enum CRNumType a_type)
+{
+ CRNum *result = NULL;
+
+ result = cr_num_new ();
+
+ g_return_val_if_fail (result, NULL);
+
+ result->val = a_val;
+ result->type = a_type;
+
+ return result;
+}
+
+
+/**
+ * Like g_ascii_dtostr() but uses not more than DBL_DIG significant digits
+ * to avoid results like "1.0000000000000001".
+ */
+static void
+pretty_ascii_dtostr (gchar *buffer, gint buf_len, gdouble d)
+{
+ gint digits = DBL_DIG - ceil (log10 (fabs (d)));
+ gchar format[8] = "%.";
+ sprintf (format + 2, "%df", CLAMP (digits, 0, 9999));
+
+ g_ascii_formatd (buffer, buf_len, format, d);
+
+ // strip trailing zeros and trailing dot
+ if (strchr (buffer, '.') != NULL) {
+ gsize pos = strlen (buffer) - 1;
+ while (buffer[pos] == '0') {
+ --pos;
+ }
+ if (buffer[pos] == '.') {
+ --pos;
+ }
+ buffer[pos + 1] = '\0';
+ }
+}
+
+/**
+ * cr_num_to_string:
+ *@a_this: the current instance of #CRNum.
+ *
+ *Returns the newly built string representation
+ *of the current instance of #CRNum. The returned
+ *string is NULL terminated. The caller *must*
+ *free the returned string.
+ */
+guchar *
+cr_num_to_string (CRNum const * a_this)
+{
+ gdouble test_val = 0.0;
+
+ guchar *tmp_char1 = NULL,
+ *tmp_char2 = NULL,
+ *result = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ test_val = a_this->val - (glong) a_this->val;
+
+ if (!test_val) {
+ tmp_char1 = (guchar *) g_strdup_printf ("%ld", (glong) a_this->val);
+ } else {
+ tmp_char1 = (guchar *) g_new0 (char, G_ASCII_DTOSTR_BUF_SIZE + 1);
+ if (tmp_char1 != NULL)
+ pretty_ascii_dtostr ((gchar *) tmp_char1, G_ASCII_DTOSTR_BUF_SIZE, a_this->val);
+ }
+
+ g_return_val_if_fail (tmp_char1, NULL);
+
+ switch (a_this->type) {
+ case NUM_LENGTH_EM:
+ tmp_char2 = (guchar *) "em";
+ break;
+
+ case NUM_LENGTH_EX:
+ tmp_char2 = (guchar *) "ex";
+ break;
+
+ case NUM_LENGTH_PX:
+ tmp_char2 = (guchar *) "px";
+ break;
+
+ case NUM_LENGTH_IN:
+ tmp_char2 = (guchar *) "in";
+ break;
+
+ case NUM_LENGTH_CM:
+ tmp_char2 = (guchar *) "cm";
+ break;
+
+ case NUM_LENGTH_MM:
+ tmp_char2 = (guchar *) "mm";
+ break;
+
+ case NUM_LENGTH_PT:
+ tmp_char2 = (guchar *) "pt";
+ break;
+
+ case NUM_LENGTH_PC:
+ tmp_char2 = (guchar *) "pc";
+ break;
+
+ case NUM_ANGLE_DEG:
+ tmp_char2 = (guchar *) "deg";
+ break;
+
+ case NUM_ANGLE_RAD:
+ tmp_char2 = (guchar *) "rad";
+ break;
+
+ case NUM_ANGLE_GRAD:
+ tmp_char2 = (guchar *) "grad";
+ break;
+
+ case NUM_TIME_MS:
+ tmp_char2 = (guchar *) "ms";
+ break;
+
+ case NUM_TIME_S:
+ tmp_char2 = (guchar *) "s";
+ break;
+
+ case NUM_FREQ_HZ:
+ tmp_char2 = (guchar *) "Hz";
+ break;
+
+ case NUM_FREQ_KHZ:
+ tmp_char2 = (guchar *) "KHz";
+ break;
+
+ case NUM_PERCENTAGE:
+ tmp_char2 = (guchar *) "%";
+ break;
+ case NUM_INHERIT:
+ tmp_char2 = (guchar *) "inherit";
+ break ;
+ case NUM_AUTO:
+ tmp_char2 = (guchar *) "auto";
+ break ;
+ case NUM_GENERIC:
+ tmp_char2 = NULL ;
+ break ;
+ default:
+ tmp_char2 = (guchar *) "unknown";
+ break;
+ }
+
+ if (tmp_char2) {
+ result = (guchar *) g_strconcat ((gchar *) tmp_char1, tmp_char2, NULL);
+ g_free (tmp_char1);
+ } else {
+ result = tmp_char1;
+ }
+
+ return result;
+}
+
+/**
+ * cr_num_copy:
+ *@a_src: the instance of #CRNum to copy.
+ *Must be non NULL.
+ *@a_dest: the destination of the copy.
+ *Must be non NULL
+ *
+ *Copies an instance of #CRNum.
+ *
+ *Returns CR_OK upon successful completion, an
+ *error code otherwise.
+ */
+enum CRStatus
+cr_num_copy (CRNum * a_dest, CRNum const * a_src)
+{
+ g_return_val_if_fail (a_dest && a_src, CR_BAD_PARAM_ERROR);
+
+ memcpy (a_dest, a_src, sizeof (CRNum));
+
+ return CR_OK;
+}
+
+/**
+ * cr_num_dup:
+ *@a_this: the instance of #CRNum to duplicate.
+ *
+ *Duplicates an instance of #CRNum
+ *
+ *Returns the newly created (duplicated) instance of #CRNum.
+ *Must be freed by cr_num_destroy().
+ */
+CRNum *
+cr_num_dup (CRNum const * a_this)
+{
+ CRNum *result = NULL;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ result = cr_num_new ();
+ g_return_val_if_fail (result, NULL);
+
+ status = cr_num_copy (result, a_this);
+ if (status != CR_OK)
+ g_clear_pointer (&result, cr_num_destroy);
+
+ return result;
+}
+
+/**
+ * cr_num_set:
+ *Sets an instance of #CRNum.
+ *@a_this: the current instance of #CRNum to be set.
+ *@a_val: the new numerical value to be hold by the current
+ *instance of #CRNum
+ *@a_type: the new type of #CRNum.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_num_set (CRNum * a_this, gdouble a_val, enum CRNumType a_type)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ a_this->val = a_val;
+ a_this->type = a_type;
+
+ return CR_OK;
+}
+
+/**
+ * cr_num_is_fixed_length:
+ * @a_this: the current instance of #CRNum .
+ *
+ *Tests if the current instance of #CRNum is a fixed
+ *length value or not. Typically a fixed length value
+ *is anything from NUM_LENGTH_EM to NUM_LENGTH_PC.
+ *See the definition of #CRNumType to see what we mean.
+ *
+ *Returns TRUE if the instance of #CRNum is a fixed length number,
+ *FALSE otherwise.
+ */
+gboolean
+cr_num_is_fixed_length (CRNum const * a_this)
+{
+ gboolean result = FALSE;
+
+ g_return_val_if_fail (a_this, FALSE);
+
+ if (a_this->type >= NUM_LENGTH_EM
+ && a_this->type <= NUM_LENGTH_PC) {
+ result = TRUE ;
+ }
+ return result ;
+}
+
+/**
+ * cr_num_destroy:
+ *@a_this: the this pointer of
+ *the current instance of #CRNum.
+ *
+ *The destructor of #CRNum.
+ */
+void
+cr_num_destroy (CRNum * a_this)
+{
+ g_return_if_fail (a_this);
+
+ g_free (a_this);
+}
diff --git a/src/3rdparty/libcroco/src/cr-num.h b/src/3rdparty/libcroco/src/cr-num.h
new file mode 100644
index 0000000..2b73aaf
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-num.h
@@ -0,0 +1,127 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information
+ */
+
+
+/**
+ *@file
+ *The declaration
+ *of the #CRNum class.
+ */
+
+#ifndef __CR_NUM_H__
+#define __CR_NUM_H__
+
+#include <glib.h>
+#include "cr-utils.h"
+#include "cr-parsing-location.h"
+
+G_BEGIN_DECLS
+
+/**
+ *@file
+ *The declaration of the #CRNum class.
+ *
+ */
+
+/**
+ *The different types
+ *of numbers.
+ *Please, do not modify
+ *the declaration order of the enum
+ *members, unless you know
+ *what you are doing.
+ */
+enum CRNumType
+{
+ NUM_AUTO = 0,
+ NUM_GENERIC,
+ NUM_LENGTH_EM,
+ NUM_LENGTH_EX,
+ NUM_LENGTH_PX,
+ NUM_LENGTH_IN,
+ NUM_LENGTH_CM,
+ NUM_LENGTH_MM,
+ NUM_LENGTH_PT,
+ NUM_LENGTH_PC,
+ NUM_ANGLE_DEG,
+ NUM_ANGLE_RAD,
+ NUM_ANGLE_GRAD,
+ NUM_TIME_MS,
+ NUM_TIME_S,
+ NUM_FREQ_HZ,
+ NUM_FREQ_KHZ,
+ NUM_PERCENTAGE,
+ NUM_INHERIT,
+ NUM_UNKNOWN_TYPE,
+ NB_NUM_TYPE
+} ;
+
+
+/**
+ *An abstraction of a number (num)
+ *as defined in the css2 spec.
+ */
+typedef struct _CRNum CRNum ;
+
+/**
+ *An abstraction of a number (num)
+ *as defined in the css2 spec.
+ */
+struct _CRNum
+{
+ enum CRNumType type ;
+ gdouble val ;
+ CRParsingLocation location ;
+} ;
+
+CRNum *
+cr_num_new (void) ;
+
+CRNum *
+cr_num_new_with_val (gdouble a_val,
+ enum CRNumType a_type) ;
+
+CRNum *
+cr_num_dup (CRNum const *a_this) ;
+
+guchar *
+cr_num_to_string (CRNum const *a_this) ;
+
+enum CRStatus
+cr_num_copy (CRNum *a_dest, CRNum const *a_src) ;
+
+enum CRStatus
+cr_num_set (CRNum *a_this, gdouble a_val,
+ enum CRNumType a_type) ;
+
+gboolean
+cr_num_is_fixed_length (CRNum const *a_this) ;
+
+void
+cr_num_destroy (CRNum *a_this) ;
+
+
+G_END_DECLS
+
+
+#endif /*__CR_NUM_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-om-parser.c b/src/3rdparty/libcroco/src/cr-om-parser.c
new file mode 100644
index 0000000..3b0ae26
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-om-parser.c
@@ -0,0 +1,1150 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include <string.h>
+#include "cr-utils.h"
+#include "cr-om-parser.h"
+
+/**
+ *@CROMParser:
+ *
+ *The definition of the CSS Object Model Parser.
+ *This parser uses (and sits) the SAC api of libcroco defined
+ *in cr-parser.h and cr-doc-handler.h
+ */
+
+struct _CROMParserPriv {
+ CRParser *parser;
+};
+
+#define PRIVATE(a_this) ((a_this)->priv)
+
+/*
+ *Forward declaration of a type defined later
+ *in this file.
+ */
+struct _ParsingContext;
+typedef struct _ParsingContext ParsingContext;
+
+static ParsingContext *new_parsing_context (void);
+
+static void destroy_context (ParsingContext * a_ctxt);
+
+static void unrecoverable_error (CRDocHandler * a_this);
+
+static void error (CRDocHandler * a_this);
+
+static void property (CRDocHandler * a_this,
+ CRString * a_name,
+ CRTerm * a_expression,
+ gboolean a_important);
+
+static void end_selector (CRDocHandler * a_this,
+ CRSelector * a_selector_list);
+
+static void start_selector (CRDocHandler * a_this,
+ CRSelector * a_selector_list);
+
+static void start_font_face (CRDocHandler * a_this,
+ CRParsingLocation *a_location);
+
+static void end_font_face (CRDocHandler * a_this);
+
+static void end_document (CRDocHandler * a_this);
+
+static void start_document (CRDocHandler * a_this);
+
+static void charset (CRDocHandler * a_this,
+ CRString * a_charset,
+ CRParsingLocation *a_location);
+
+static void start_page (CRDocHandler * a_this, CRString * a_page,
+ CRString * a_pseudo_page,
+ CRParsingLocation *a_location);
+
+static void end_page (CRDocHandler * a_this, CRString * a_page,
+ CRString * a_pseudo_page);
+
+static void start_media (CRDocHandler * a_this,
+ GList * a_media_list,
+ CRParsingLocation *a_location);
+
+static void end_media (CRDocHandler * a_this,
+ GList * a_media_list);
+
+static void import_style (CRDocHandler * a_this,
+ GList * a_media_list,
+ CRString * a_uri,
+ CRString * a_uri_default_ns,
+ CRParsingLocation *a_location);
+
+struct _ParsingContext {
+ CRStyleSheet *stylesheet;
+ CRStatement *cur_stmt;
+ CRStatement *cur_media_stmt;
+};
+
+/********************************************
+ *Private methods
+ ********************************************/
+
+static ParsingContext *
+new_parsing_context (void)
+{
+ ParsingContext *result = NULL;
+
+ result = g_try_malloc (sizeof (ParsingContext));
+ if (!result) {
+ cr_utils_trace_info ("Out of Memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (ParsingContext));
+ return result;
+}
+
+static void
+destroy_context (ParsingContext * a_ctxt)
+{
+ g_return_if_fail (a_ctxt);
+
+ if (a_ctxt->stylesheet) {
+ cr_stylesheet_destroy (a_ctxt->stylesheet);
+ a_ctxt->stylesheet = NULL;
+ }
+ if (a_ctxt->cur_stmt) {
+ cr_statement_destroy (a_ctxt->cur_stmt);
+ a_ctxt->cur_stmt = NULL;
+ }
+ g_free (a_ctxt);
+}
+
+static enum CRStatus
+cr_om_parser_init_default_sac_handler (CROMParser * a_this)
+{
+ CRDocHandler *sac_handler = NULL;
+ gboolean created_handler = FALSE;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->parser,
+ CR_BAD_PARAM_ERROR);
+
+ status = cr_parser_get_sac_handler (PRIVATE (a_this)->parser,
+ &sac_handler);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ if (!sac_handler) {
+ sac_handler = cr_doc_handler_new ();
+ created_handler = TRUE;
+ }
+
+ /*
+ *initialize here the sac handler.
+ */
+ sac_handler->start_document = start_document;
+ sac_handler->end_document = end_document;
+ sac_handler->start_selector = start_selector;
+ sac_handler->end_selector = end_selector;
+ sac_handler->property = property;
+ sac_handler->start_font_face = start_font_face;
+ sac_handler->end_font_face = end_font_face;
+ sac_handler->error = error;
+ sac_handler->unrecoverable_error = unrecoverable_error;
+ sac_handler->charset = charset;
+ sac_handler->start_page = start_page;
+ sac_handler->end_page = end_page;
+ sac_handler->start_media = start_media;
+ sac_handler->end_media = end_media;
+ sac_handler->import_style = import_style;
+
+ if (created_handler) {
+ status = cr_parser_set_sac_handler (PRIVATE (a_this)->parser,
+ sac_handler);
+ cr_doc_handler_unref (sac_handler);
+ }
+
+ return status;
+
+}
+
+static void
+start_document (CRDocHandler * a_this)
+{
+ ParsingContext *ctxt = NULL;
+ CRStyleSheet *stylesheet = NULL;
+
+ g_return_if_fail (a_this);
+
+ ctxt = new_parsing_context ();
+ g_return_if_fail (ctxt);
+
+ stylesheet = cr_stylesheet_new (NULL);
+ ctxt->stylesheet = stylesheet;
+ cr_doc_handler_set_ctxt (a_this, ctxt);
+}
+
+static void
+start_font_face (CRDocHandler * a_this,
+ CRParsingLocation *a_location)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+
+ (void) a_location;
+
+ g_return_if_fail (a_this);
+
+ g_return_if_fail (a_this);
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+ g_return_if_fail (status == CR_OK && ctxt);
+ g_return_if_fail (ctxt->cur_stmt == NULL);
+
+ ctxt->cur_stmt =
+ cr_statement_new_at_font_face_rule (ctxt->stylesheet, NULL);
+
+ g_return_if_fail (ctxt->cur_stmt);
+}
+
+static void
+end_font_face (CRDocHandler * a_this)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+ CRStatement *stmts = NULL;
+
+ g_return_if_fail (a_this);
+
+ g_return_if_fail (a_this);
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+ g_return_if_fail (status == CR_OK && ctxt);
+ g_return_if_fail
+ (ctxt->cur_stmt
+ && ctxt->cur_stmt->type == AT_FONT_FACE_RULE_STMT
+ && ctxt->stylesheet);
+
+ stmts = cr_statement_append (ctxt->stylesheet->statements,
+ ctxt->cur_stmt);
+ if (!stmts)
+ goto error;
+
+ ctxt->stylesheet->statements = stmts;
+ stmts = NULL;
+ ctxt->cur_stmt = NULL;
+
+ return;
+
+ error:
+
+ if (ctxt->cur_stmt) {
+ cr_statement_destroy (ctxt->cur_stmt);
+ ctxt->cur_stmt = NULL;
+ }
+
+ if (!stmts) {
+ cr_statement_destroy (stmts);
+ stmts = NULL;
+ }
+}
+
+static void
+end_document (CRDocHandler * a_this)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+
+ g_return_if_fail (a_this);
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+ g_return_if_fail (status == CR_OK && ctxt);
+
+ if (!ctxt->stylesheet || ctxt->cur_stmt)
+ goto error;
+
+ status = cr_doc_handler_set_result (a_this, ctxt->stylesheet);
+ g_return_if_fail (status == CR_OK);
+
+ ctxt->stylesheet = NULL;
+ destroy_context (ctxt);
+ cr_doc_handler_set_ctxt (a_this, NULL);
+
+ return;
+
+ error:
+ if (ctxt) {
+ destroy_context (ctxt);
+ }
+}
+
+static void
+charset (CRDocHandler * a_this, CRString * a_charset,
+ CRParsingLocation *a_location)
+{
+ enum CRStatus status = CR_OK;
+ CRStatement *stmt = NULL,
+ *stmt2 = NULL;
+ CRString *charset = NULL;
+
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+
+ (void) a_location;
+
+ g_return_if_fail (a_this);
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+ g_return_if_fail (status == CR_OK && ctxt);
+ g_return_if_fail (ctxt->stylesheet);
+
+ charset = cr_string_dup (a_charset) ;
+ stmt = cr_statement_new_at_charset_rule (ctxt->stylesheet, charset);
+ if (stmt)
+ stmt2 = cr_statement_append (ctxt->stylesheet->statements, stmt);
+ if (!stmt2) {
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ }
+ if (charset) {
+ cr_string_destroy (charset);
+ }
+ return;
+ }
+ ctxt->stylesheet->statements = stmt2;
+ stmt2 = NULL;
+}
+
+static void
+start_page (CRDocHandler * a_this,
+ CRString * a_page,
+ CRString * a_pseudo,
+ CRParsingLocation *a_location)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+
+ (void) a_location;
+
+ g_return_if_fail (a_this);
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+ g_return_if_fail (status == CR_OK && ctxt);
+ g_return_if_fail (ctxt->cur_stmt == NULL);
+
+ ctxt->cur_stmt = cr_statement_new_at_page_rule
+ (ctxt->stylesheet, NULL, NULL, NULL);
+ if (a_page) {
+ ctxt->cur_stmt->kind.page_rule->name =
+ cr_string_dup (a_page) ;
+
+ if (!ctxt->cur_stmt->kind.page_rule->name) {
+ goto error;
+ }
+ }
+ if (a_pseudo) {
+ ctxt->cur_stmt->kind.page_rule->pseudo =
+ cr_string_dup (a_pseudo) ;
+ if (!ctxt->cur_stmt->kind.page_rule->pseudo) {
+ goto error;
+ }
+ }
+ return;
+
+ error:
+ if (ctxt->cur_stmt) {
+ cr_statement_destroy (ctxt->cur_stmt);
+ ctxt->cur_stmt = NULL;
+ }
+}
+
+static void
+end_page (CRDocHandler * a_this,
+ CRString * a_page,
+ CRString * a_pseudo_page)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+ CRStatement *stmt = NULL;
+
+ (void) a_page;
+ (void) a_pseudo_page;
+
+ g_return_if_fail (a_this);
+
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+
+ g_return_if_fail (status == CR_OK && ctxt);
+
+ g_return_if_fail (ctxt->cur_stmt
+ && ctxt->cur_stmt->type == AT_PAGE_RULE_STMT
+ && ctxt->stylesheet);
+
+ stmt = cr_statement_append (ctxt->stylesheet->statements,
+ ctxt->cur_stmt);
+
+ if (stmt) {
+ ctxt->stylesheet->statements = stmt;
+ stmt = NULL;
+ ctxt->cur_stmt = NULL;
+ }
+
+ if (ctxt->cur_stmt) {
+ cr_statement_destroy (ctxt->cur_stmt);
+ ctxt->cur_stmt = NULL;
+ }
+ a_page = NULL; /*keep compiler happy */
+ a_pseudo_page = NULL; /*keep compiler happy */
+}
+
+static void
+start_media (CRDocHandler * a_this,
+ GList * a_media_list,
+ CRParsingLocation *a_location)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+ GList *media_list = NULL;
+
+ (void) a_location;
+
+ g_return_if_fail (a_this);
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+ g_return_if_fail (status == CR_OK && ctxt);
+
+ g_return_if_fail (ctxt
+ && ctxt->cur_stmt == NULL
+ && ctxt->cur_media_stmt == NULL
+ && ctxt->stylesheet);
+ if (a_media_list) {
+ /*duplicate the media_list */
+ media_list = cr_utils_dup_glist_of_cr_string
+ (a_media_list);
+ }
+ ctxt->cur_media_stmt =
+ cr_statement_new_at_media_rule
+ (ctxt->stylesheet, NULL, media_list);
+
+}
+
+static void
+end_media (CRDocHandler * a_this, GList * a_media_list)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+ CRStatement *stmts = NULL;
+
+ (void) a_media_list;
+
+ g_return_if_fail (a_this);
+
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+
+ g_return_if_fail (status == CR_OK && ctxt);
+
+ g_return_if_fail (ctxt
+ && ctxt->cur_media_stmt
+ && ctxt->cur_media_stmt->type == AT_MEDIA_RULE_STMT
+ && ctxt->stylesheet);
+
+ stmts = cr_statement_append (ctxt->stylesheet->statements,
+ ctxt->cur_media_stmt);
+
+ if (!stmts) {
+ cr_statement_destroy (ctxt->cur_media_stmt);
+ ctxt->cur_media_stmt = NULL;
+ }
+
+ ctxt->stylesheet->statements = stmts;
+ stmts = NULL;
+
+ ctxt->cur_stmt = NULL ;
+ ctxt->cur_media_stmt = NULL ;
+ a_media_list = NULL;
+}
+
+static void
+import_style (CRDocHandler * a_this,
+ GList * a_media_list,
+ CRString * a_uri,
+ CRString * a_uri_default_ns,
+ CRParsingLocation *a_location)
+{
+ enum CRStatus status = CR_OK;
+ CRString *uri = NULL;
+ CRStatement *stmt = NULL,
+ *stmt2 = NULL;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+ GList *media_list = NULL ;
+
+ (void) a_uri_default_ns;
+ (void) a_location;
+
+ g_return_if_fail (a_this);
+
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+
+ g_return_if_fail (status == CR_OK && ctxt);
+
+ g_return_if_fail (ctxt->stylesheet);
+
+ uri = cr_string_dup (a_uri) ;
+
+ if (a_media_list)
+ media_list = cr_utils_dup_glist_of_cr_string (a_media_list) ;
+
+ stmt = cr_statement_new_at_import_rule
+ (ctxt->stylesheet, uri, media_list, NULL);
+
+ if (!stmt)
+ goto error;
+
+ if (ctxt->cur_stmt) {
+ stmt2 = cr_statement_append (ctxt->cur_stmt, stmt);
+ if (!stmt2)
+ goto error;
+ ctxt->cur_stmt = stmt2;
+ stmt2 = NULL;
+ stmt = NULL;
+ } else {
+ stmt2 = cr_statement_append (ctxt->stylesheet->statements,
+ stmt);
+ if (!stmt2)
+ goto error;
+ ctxt->stylesheet->statements = stmt2;
+ stmt2 = NULL;
+ stmt = NULL;
+ }
+
+ return;
+
+ error:
+ if (uri) {
+ cr_string_destroy (uri);
+ }
+
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ }
+ a_uri_default_ns = NULL; /*keep compiler happy */
+}
+
+static void
+start_selector (CRDocHandler * a_this, CRSelector * a_selector_list)
+{
+ enum CRStatus status = CR_OK ;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+
+ g_return_if_fail (a_this);
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+ g_return_if_fail (status == CR_OK && ctxt);
+ if (ctxt->cur_stmt) {
+ /*hmm, this should be NULL so free it */
+ cr_statement_destroy (ctxt->cur_stmt);
+ ctxt->cur_stmt = NULL;
+ }
+
+ ctxt->cur_stmt = cr_statement_new_ruleset
+ (ctxt->stylesheet, a_selector_list, NULL, NULL);
+}
+
+static void
+end_selector (CRDocHandler * a_this, CRSelector * a_selector_list)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+
+ (void) a_selector_list;
+
+ g_return_if_fail (a_this);
+
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+
+ g_return_if_fail (status == CR_OK && ctxt);
+
+ g_return_if_fail (ctxt->cur_stmt && ctxt->stylesheet);
+
+ if (ctxt->cur_stmt) {
+ CRStatement *stmts = NULL;
+
+ if (ctxt->cur_media_stmt) {
+ CRAtMediaRule *media_rule = NULL;
+
+ media_rule = ctxt->cur_media_stmt->kind.media_rule;
+
+ stmts = cr_statement_append
+ (media_rule->rulesets, ctxt->cur_stmt);
+
+ if (!stmts) {
+ cr_utils_trace_info
+ ("Could not append a new statement");
+ cr_statement_destroy (media_rule->rulesets);
+ ctxt->cur_media_stmt->
+ kind.media_rule->rulesets = NULL;
+ return;
+ }
+ media_rule->rulesets = stmts;
+ ctxt->cur_stmt = NULL;
+ } else {
+ stmts = cr_statement_append
+ (ctxt->stylesheet->statements,
+ ctxt->cur_stmt);
+ if (!stmts) {
+ cr_utils_trace_info
+ ("Could not append a new statement");
+ cr_statement_destroy (ctxt->cur_stmt);
+ ctxt->cur_stmt = NULL;
+ return;
+ }
+ ctxt->stylesheet->statements = stmts;
+ ctxt->cur_stmt = NULL;
+ }
+
+ }
+
+ a_selector_list = NULL; /*keep compiler happy */
+}
+
+static void
+property (CRDocHandler * a_this,
+ CRString * a_name,
+ CRTerm * a_expression,
+ gboolean a_important)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+ CRDeclaration *decl = NULL,
+ *decl2 = NULL;
+ CRString *str = NULL;
+
+ g_return_if_fail (a_this);
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+ g_return_if_fail (status == CR_OK && ctxt);
+
+ /*
+ *make sure a current ruleset statement has been allocated
+ *already.
+ */
+ g_return_if_fail
+ (ctxt->cur_stmt
+ &&
+ (ctxt->cur_stmt->type == RULESET_STMT
+ || ctxt->cur_stmt->type == AT_FONT_FACE_RULE_STMT
+ || ctxt->cur_stmt->type == AT_PAGE_RULE_STMT));
+
+ if (a_name) {
+ str = cr_string_dup (a_name);
+ g_return_if_fail (str);
+ }
+
+ /*instantiates a new declaration */
+ decl = cr_declaration_new (ctxt->cur_stmt, str, a_expression);
+ if (decl == NULL)
+ g_clear_pointer (&str, cr_string_destroy);
+ g_return_if_fail (decl);
+ str = NULL;
+ decl->important = a_important;
+ /*
+ *add the new declaration to the current statement
+ *being build.
+ */
+ switch (ctxt->cur_stmt->type) {
+ case RULESET_STMT:
+ decl2 = cr_declaration_append
+ (ctxt->cur_stmt->kind.ruleset->decl_list, decl);
+ if (!decl2) {
+ cr_utils_trace_info
+ ("Could not append decl to ruleset");
+ goto error;
+ }
+ ctxt->cur_stmt->kind.ruleset->decl_list = decl2;
+ decl = NULL;
+ decl2 = NULL;
+ break;
+
+ case AT_FONT_FACE_RULE_STMT:
+ decl2 = cr_declaration_append
+ (ctxt->cur_stmt->kind.font_face_rule->decl_list,
+ decl);
+ if (!decl2) {
+ cr_utils_trace_info
+ ("Could not append decl to ruleset");
+ goto error;
+ }
+ ctxt->cur_stmt->kind.font_face_rule->decl_list = decl2;
+ decl = NULL;
+ decl2 = NULL;
+ break;
+ case AT_PAGE_RULE_STMT:
+ decl2 = cr_declaration_append
+ (ctxt->cur_stmt->kind.page_rule->decl_list, decl);
+ if (!decl2) {
+ cr_utils_trace_info
+ ("Could not append decl to ruleset");
+ goto error;
+ }
+ ctxt->cur_stmt->kind.page_rule->decl_list = decl2;
+ decl = NULL;
+ decl2 = NULL;
+ break;
+
+ default:
+ goto error;
+ break;
+ }
+
+ return;
+
+ error:
+ if (str) {
+ g_free (str);
+ str = NULL;
+ }
+
+ if (decl) {
+ cr_declaration_destroy (decl);
+ decl = NULL;
+ }
+}
+
+static void
+error (CRDocHandler * a_this)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+
+ g_return_if_fail (a_this);
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+ g_return_if_fail (status == CR_OK && ctxt);
+
+ if (ctxt->cur_stmt) {
+ cr_statement_destroy (ctxt->cur_stmt);
+ ctxt->cur_stmt = NULL;
+ }
+}
+
+static void
+unrecoverable_error (CRDocHandler * a_this)
+{
+ enum CRStatus status = CR_OK;
+ ParsingContext *ctxt = NULL;
+ ParsingContext **ctxtptr = NULL;
+
+ ctxtptr = &ctxt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
+ g_return_if_fail (status == CR_OK);
+
+ if (ctxt) {
+ if (ctxt->stylesheet) {
+ status = cr_doc_handler_set_result
+ (a_this, ctxt->stylesheet);
+ g_return_if_fail (status == CR_OK);
+ }
+ g_free (ctxt);
+ cr_doc_handler_set_ctxt (a_this, NULL);
+ }
+}
+
+/********************************************
+ *Public methods
+ ********************************************/
+
+/**
+ * cr_om_parser_new:
+ *@a_input: the input stream.
+ *
+ *Constructor of the CROMParser.
+ *Returns the newly built instance of #CROMParser.
+ */
+CROMParser *
+cr_om_parser_new (CRInput * a_input)
+{
+ CROMParser *result = NULL;
+ enum CRStatus status = CR_OK;
+
+ result = g_try_malloc (sizeof (CROMParser));
+
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CROMParser));
+ PRIVATE (result) = g_try_malloc (sizeof (CROMParserPriv));
+
+ if (!PRIVATE (result)) {
+ cr_utils_trace_info ("Out of memory");
+ goto error;
+ }
+
+ memset (PRIVATE (result), 0, sizeof (CROMParserPriv));
+
+ PRIVATE (result)->parser = cr_parser_new_from_input (a_input);
+
+ if (!PRIVATE (result)->parser) {
+ cr_utils_trace_info ("parsing instantiation failed");
+ goto error;
+ }
+
+ status = cr_om_parser_init_default_sac_handler (result);
+
+ if (status != CR_OK) {
+ goto error;
+ }
+
+ return result;
+
+ error:
+
+ if (result) {
+ cr_om_parser_destroy (result);
+ }
+
+ return NULL;
+}
+
+/**
+ * cr_om_parser_parse_buf:
+ *@a_this: the current instance of #CROMParser.
+ *@a_buf: the in memory buffer to parse.
+ *@a_len: the length of the in memory buffer in number of bytes.
+ *@a_enc: the encoding of the in memory buffer.
+ *@a_result: out parameter the resulting style sheet
+ *
+ *Parses the content of an in memory buffer.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_om_parser_parse_buf (CROMParser * a_this,
+ const guchar * a_buf,
+ gulong a_len,
+ enum CREncoding a_enc, CRStyleSheet ** a_result)
+{
+
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this && a_result, CR_BAD_PARAM_ERROR);
+
+ if (!PRIVATE (a_this)->parser) {
+ PRIVATE (a_this)->parser = cr_parser_new (NULL);
+ }
+
+ status = cr_parser_parse_buf (PRIVATE (a_this)->parser,
+ a_buf, a_len, a_enc);
+
+ if (status == CR_OK) {
+ CRStyleSheet *result = NULL;
+ CRStyleSheet **resultptr = NULL;
+ CRDocHandler *sac_handler = NULL;
+
+ cr_parser_get_sac_handler (PRIVATE (a_this)->parser,
+ &sac_handler);
+ g_return_val_if_fail (sac_handler, CR_ERROR);
+ resultptr = &result;
+ status = cr_doc_handler_get_result (sac_handler,
+ (gpointer *) resultptr);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ if (result)
+ *a_result = result;
+ }
+
+ return status;
+}
+
+/**
+ * cr_om_parser_simply_parse_buf:
+ *@a_buf: the css2 in memory buffer.
+ *@a_len: the length of the in memory buffer.
+ *@a_enc: the encoding of the in memory buffer.
+ *@a_result: out parameter. The resulting css2 style sheet.
+ *
+ *The simpler way to parse an in memory css2 buffer.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_om_parser_simply_parse_buf (const guchar * a_buf,
+ gulong a_len,
+ enum CREncoding a_enc,
+ CRStyleSheet ** a_result)
+{
+ CROMParser *parser = NULL;
+ enum CRStatus status = CR_OK;
+
+ parser = cr_om_parser_new (NULL);
+ if (!parser) {
+ cr_utils_trace_info ("Could not create om parser");
+ cr_utils_trace_info ("System possibly out of memory");
+ return CR_ERROR;
+ }
+
+ status = cr_om_parser_parse_buf (parser, a_buf, a_len,
+ a_enc, a_result);
+
+ if (parser) {
+ cr_om_parser_destroy (parser);
+ parser = NULL;
+ }
+
+ return status;
+}
+
+/**
+ * cr_om_parser_parse_file:
+ *@a_this: the current instance of the cssom parser.
+ *@a_file_uri: the uri of the file.
+ *(only local file paths are supported so far)
+ *@a_enc: the encoding of the file.
+ *@a_result: out parameter. A pointer
+ *the build css object model.
+ *
+ *Parses a css2 stylesheet contained
+ *in a file.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_om_parser_parse_file (CROMParser * a_this,
+ const guchar * a_file_uri,
+ enum CREncoding a_enc, CRStyleSheet ** a_result)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this && a_file_uri && a_result,
+ CR_BAD_PARAM_ERROR);
+
+ if (!PRIVATE (a_this)->parser) {
+ PRIVATE (a_this)->parser = cr_parser_new_from_file
+ (a_file_uri, a_enc);
+ }
+
+ status = cr_parser_parse_file (PRIVATE (a_this)->parser,
+ a_file_uri, a_enc);
+
+ if (status == CR_OK) {
+ CRStyleSheet *result = NULL;
+ CRStyleSheet **resultptr = NULL;
+ CRDocHandler *sac_handler = NULL;
+
+ cr_parser_get_sac_handler (PRIVATE (a_this)->parser,
+ &sac_handler);
+ g_return_val_if_fail (sac_handler, CR_ERROR);
+ resultptr = &result;
+ status = cr_doc_handler_get_result
+ (sac_handler, (gpointer *) resultptr);
+ g_return_val_if_fail (status == CR_OK, status);
+ if (result)
+ *a_result = result;
+ }
+
+ return status;
+}
+
+/**
+ * cr_om_parser_simply_parse_file:
+ *@a_file_path: the css2 local file path.
+ *@a_enc: the file encoding.
+ *@a_result: out parameter. The returned css stylesheet.
+ *Must be freed by the caller using cr_stylesheet_destroy.
+ *
+ *The simpler method to parse a css2 file.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ *Note that this method uses cr_om_parser_parse_file() so both methods
+ *have the same return values.
+ */
+enum CRStatus
+cr_om_parser_simply_parse_file (const guchar * a_file_path,
+ enum CREncoding a_enc,
+ CRStyleSheet ** a_result)
+{
+ CROMParser *parser = NULL;
+ enum CRStatus status = CR_OK;
+
+ parser = cr_om_parser_new (NULL);
+ if (!parser) {
+ cr_utils_trace_info ("Could not allocate om parser");
+ cr_utils_trace_info ("System may be out of memory");
+ return CR_ERROR;
+ }
+
+ status = cr_om_parser_parse_file (parser, a_file_path,
+ a_enc, a_result);
+ if (parser) {
+ cr_om_parser_destroy (parser);
+ parser = NULL;
+ }
+
+ return status;
+}
+
+/**
+ * cr_om_parser_parse_paths_to_cascade:
+ *@a_this: the current instance of #CROMParser
+ *@a_author_path: the path to the author stylesheet
+ *@a_user_path: the path to the user stylesheet
+ *@a_ua_path: the path to the User Agent stylesheet
+ *@a_encoding: the encoding of the sheets.
+ *@a_result: out parameter. The resulting cascade if the parsing
+ *was okay
+ *
+ *Parses three sheets located by their paths and build a cascade
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise
+ */
+enum CRStatus
+cr_om_parser_parse_paths_to_cascade (CROMParser * a_this,
+ const guchar * a_author_path,
+ const guchar * a_user_path,
+ const guchar * a_ua_path,
+ enum CREncoding a_encoding,
+ CRCascade ** a_result)
+{
+ enum CRStatus status = CR_OK;
+
+ /*0->author sheet, 1->user sheet, 2->UA sheet */
+ CRStyleSheet *sheets[3];
+ guchar *paths[3];
+ CRCascade *result = NULL;
+ gint i = 0;
+
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ memset (sheets, 0, sizeof (CRStyleSheet*) * 3);
+ paths[0] = (guchar *) a_author_path;
+ paths[1] = (guchar *) a_user_path;
+ paths[2] = (guchar *) a_ua_path;
+
+ for (i = 0; i < 3; i++) {
+ status = cr_om_parser_parse_file (a_this, paths[i],
+ a_encoding, &sheets[i]);
+ if (status != CR_OK) {
+ if (sheets[i]) {
+ cr_stylesheet_unref (sheets[i]);
+ sheets[i] = NULL;
+ }
+ continue;
+ }
+ }
+ result = cr_cascade_new (sheets[0], sheets[1], sheets[2]);
+ if (!result) {
+ for (i = 0; i < 3; i++) {
+ cr_stylesheet_unref (sheets[i]);
+ sheets[i] = 0;
+ }
+ return CR_ERROR;
+ }
+ *a_result = result;
+ return CR_OK;
+}
+
+/**
+ * cr_om_parser_simply_parse_paths_to_cascade:
+ *@a_author_path: the path to the author stylesheet
+ *@a_user_path: the path to the user stylesheet
+ *@a_ua_path: the path to the User Agent stylesheet
+ *@a_encoding: the encoding of the sheets.
+ *@a_result: out parameter. The resulting cascade if the parsing
+ *was okay
+ *
+ *Parses three sheets located by their paths and build a cascade
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise
+ */
+enum CRStatus
+cr_om_parser_simply_parse_paths_to_cascade (const guchar * a_author_path,
+ const guchar * a_user_path,
+ const guchar * a_ua_path,
+ enum CREncoding a_encoding,
+ CRCascade ** a_result)
+{
+ enum CRStatus status = CR_OK;
+ CROMParser *parser = NULL;
+
+ parser = cr_om_parser_new (NULL);
+ if (!parser) {
+ cr_utils_trace_info ("could not allocated om parser");
+ cr_utils_trace_info ("System may be out of memory");
+ return CR_ERROR;
+ }
+ status = cr_om_parser_parse_paths_to_cascade (parser,
+ a_author_path,
+ a_user_path,
+ a_ua_path,
+ a_encoding, a_result);
+ if (parser) {
+ cr_om_parser_destroy (parser);
+ parser = NULL;
+ }
+ return status;
+}
+
+/**
+ * cr_om_parser_destroy:
+ *@a_this: the current instance of #CROMParser.
+ *
+ *Destructor of the #CROMParser.
+ */
+void
+cr_om_parser_destroy (CROMParser * a_this)
+{
+ g_return_if_fail (a_this && PRIVATE (a_this));
+
+ if (PRIVATE (a_this)->parser) {
+ cr_parser_destroy (PRIVATE (a_this)->parser);
+ PRIVATE (a_this)->parser = NULL;
+ }
+
+ if (PRIVATE (a_this)) {
+ g_free (PRIVATE (a_this));
+ PRIVATE (a_this) = NULL;
+ }
+
+ if (a_this) {
+ g_free (a_this);
+ a_this = NULL;
+ }
+}
diff --git a/src/3rdparty/libcroco/src/cr-om-parser.h b/src/3rdparty/libcroco/src/cr-om-parser.h
new file mode 100644
index 0000000..13d35b1
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-om-parser.h
@@ -0,0 +1,98 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the
+ * GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ *$Id$
+ */
+
+#ifndef __CR_OM_PARSER_H__
+#define __CR_OM_PARSER_H__
+
+#include "cr-parser.h"
+#include "cr-cascade.h"
+
+
+/**
+ *@file
+ *The definition of the CSS Object Model Parser.
+ *This parser uses (and sits) the SAC api of libcroco defined
+ *in cr-parser.h and cr-doc-handler.h
+ */
+
+G_BEGIN_DECLS
+
+typedef struct _CROMParser CROMParser ;
+typedef struct _CROMParserPriv CROMParserPriv ;
+
+/**
+ *The Object model parser.
+ *Can parse a css file and build a css object model.
+ *This parser uses an instance of #CRParser and defines
+ *a set of SAC callbacks to build the Object Model.
+ */
+struct _CROMParser
+{
+ CROMParserPriv *priv ;
+} ;
+
+CROMParser * cr_om_parser_new (CRInput *a_input) ;
+
+
+enum CRStatus cr_om_parser_simply_parse_file (const guchar *a_file_path,
+ enum CREncoding a_enc,
+ CRStyleSheet **a_result) ;
+
+enum CRStatus cr_om_parser_parse_file (CROMParser *a_this,
+ const guchar *a_file_uri,
+ enum CREncoding a_enc,
+ CRStyleSheet **a_result) ;
+
+enum CRStatus cr_om_parser_simply_parse_buf (const guchar *a_buf,
+ gulong a_len,
+ enum CREncoding a_enc,
+ CRStyleSheet **a_result) ;
+
+enum CRStatus cr_om_parser_parse_buf (CROMParser *a_this,
+ const guchar *a_buf,
+ gulong a_len,
+ enum CREncoding a_enc,
+ CRStyleSheet **a_result) ;
+
+enum CRStatus cr_om_parser_parse_paths_to_cascade (CROMParser *a_this,
+ const guchar *a_author_path,
+ const guchar *a_user_path,
+ const guchar *a_ua_path,
+ enum CREncoding a_encoding,
+ CRCascade ** a_result) ;
+
+enum CRStatus cr_om_parser_simply_parse_paths_to_cascade (const guchar *a_author_path,
+ const guchar *a_user_path,
+ const guchar *a_ua_path,
+ enum CREncoding a_encoding,
+ CRCascade ** a_result) ;
+
+void cr_om_parser_destroy (CROMParser *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_OM_PARSER_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-parser.c b/src/3rdparty/libcroco/src/cr-parser.c
new file mode 100644
index 0000000..e9a5f90
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-parser.c
@@ -0,0 +1,4568 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the
+ * GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyrights information.
+ */
+
+/**
+ *@CRParser:
+ *
+ *The definition of the #CRParser class.
+ */
+
+#include "string.h"
+#include "cr-parser.h"
+#include "cr-num.h"
+#include "cr-term.h"
+#include "cr-simple-sel.h"
+#include "cr-attr-sel.h"
+
+/*
+ *Random notes:
+ *CSS core syntax vs CSS level 2 syntax
+ *=====================================
+ *
+ *One must keep in mind
+ *that css UA must comply with two syntaxes.
+ *
+ *1/the specific syntax that defines the css language
+ *for a given level of specification (e.g css2 syntax
+ *defined in appendix D.1 of the css2 spec)
+ *
+ *2/the core (general) syntax that is there to allow
+ *UAs to parse style sheets written in levels of CSS that
+ *didn't exist at the time the UAs were created.
+ *
+ *the name of parsing functions (or methods) contained in this file
+ *follows the following scheme: cr_parser_parse_<production_name> (...) ;
+ *where <production_name> is the name
+ *of a production of the css2 language.
+ *When a given production is
+ *defined by the css2 level grammar *and* by the
+ *css core syntax, there will be two functions to parse that production:
+ *one will parse the production defined by the css2 level grammar and the
+ *other will parse the production defined by the css core grammar.
+ *The css2 level grammar related parsing function will be called:
+ *cr_parser_parse_<production_name> (...) ;
+ *Then css core grammar related parsing function will be called:
+ *cr_parser_parse_<production_name>_core (...) ;
+ *
+ *If a production is defined only by the css core grammar, then
+ *it will be named:
+ *cr_parser_parse_<production_name>_core (...) ;
+ */
+
+typedef struct _CRParserError CRParserError;
+
+/**
+ *An abstraction of an error reported by by the
+ *parsing routines.
+ */
+struct _CRParserError {
+ guchar *msg;
+ enum CRStatus status;
+ glong line;
+ glong column;
+ glong byte_num;
+};
+
+enum CRParserState {
+ READY_STATE = 0,
+ TRY_PARSE_CHARSET_STATE,
+ CHARSET_PARSED_STATE,
+ TRY_PARSE_IMPORT_STATE,
+ IMPORT_PARSED_STATE,
+ TRY_PARSE_RULESET_STATE,
+ RULESET_PARSED_STATE,
+ TRY_PARSE_MEDIA_STATE,
+ MEDIA_PARSED_STATE,
+ TRY_PARSE_PAGE_STATE,
+ PAGE_PARSED_STATE,
+ TRY_PARSE_FONT_FACE_STATE,
+ FONT_FACE_PARSED_STATE
+} ;
+
+/**
+ *The private attributes of
+ *#CRParser.
+ */
+struct _CRParserPriv {
+ /**
+ *The tokenizer
+ */
+ CRTknzr *tknzr;
+
+ /**
+ *The sac handlers to call
+ *to notify the parsing of
+ *the css2 constructions.
+ */
+ CRDocHandler *sac_handler;
+
+ /**
+ *A stack of errors reported
+ *by the parsing routines.
+ *Contains instance of #CRParserError.
+ *This pointer is the top of the stack.
+ */
+ GList *err_stack;
+
+ enum CRParserState state;
+ gboolean resolve_import;
+ gboolean is_case_sensitive;
+ gboolean use_core_grammar;
+};
+
+#define PRIVATE(obj) ((obj)->priv)
+
+#define CHARS_TAB_SIZE 12
+
+#define RECURSIVE_CALLERS_LIMIT 100
+
+/**
+ * IS_NUM:
+ *@a_char: the char to test.
+ *return TRUE if the character is a number ([0-9]), FALSE otherwise
+ */
+#define IS_NUM(a_char) (((a_char) >= '0' && (a_char) <= '9')?TRUE:FALSE)
+
+/**
+ *Checks if 'status' equals CR_OK. If not, goto the 'error' label.
+ *
+ *@param status the status (of type enum CRStatus) to test.
+ *@param is_exception if set to FALSE, the final status returned
+ *by the current function will be CR_PARSING_ERROR. If set to TRUE, the
+ *current status will be the current value of the 'status' variable.
+ *
+ */
+#define CHECK_PARSING_STATUS(status, is_exception) \
+if ((status) != CR_OK) \
+{ \
+ if (is_exception == FALSE) \
+ { \
+ status = CR_PARSING_ERROR ; \
+ } \
+ goto error ; \
+}
+
+/**
+ * CHECK_PARSING_STATUS_ERR:
+ *@a_this: the current instance of #CRParser .
+ *@a_status: the status to check. Is of type enum #CRStatus.
+ *@a_is_exception: in case of error, if is TRUE, the status
+ *is set to CR_PARSING_ERROR before goto error. If is false, the
+ *real low level status is kept and will be returned by the
+ *upper level function that called this macro. Usually, this must
+ *be set to FALSE.
+ *
+ *same as CHECK_PARSING_STATUS() but this one pushes an error
+ *on the parser error stack when an error arises.
+ *
+ */
+#define CHECK_PARSING_STATUS_ERR(a_this, a_status, a_is_exception,\
+ a_err_msg, a_err_status) \
+if ((a_status) != CR_OK) \
+{ \
+ if (a_is_exception == FALSE) a_status = CR_PARSING_ERROR ; \
+ cr_parser_push_error (a_this, a_err_msg, a_err_status) ; \
+ goto error ; \
+}
+
+/**
+ *Peeks the next char from the input stream of the current parser
+ *by invoking cr_tknzr_input_peek_char().
+ *invokes CHECK_PARSING_STATUS on the status returned by
+ *cr_tknzr_peek_char().
+ *
+ *@param a_this the current instance of #CRParser.
+ *@param a_to_char a pointer to the char where to store the
+ *char peeked.
+ */
+#define PEEK_NEXT_CHAR(a_this, a_to_char) \
+{\
+status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr, a_to_char) ; \
+CHECK_PARSING_STATUS (status, TRUE) \
+}
+
+/**
+ *Reads the next char from the input stream of the current parser.
+ *In case of error, jumps to the "error:" label located in the
+ *function where this macro is called.
+ *@param a_this the current instance of #CRParser
+ *@param to_char a pointer to the guint32 char where to store
+ *the character read.
+ */
+#define READ_NEXT_CHAR(a_this, a_to_char) \
+status = cr_tknzr_read_char (PRIVATE (a_this)->tknzr, a_to_char) ; \
+CHECK_PARSING_STATUS (status, TRUE)
+
+/**
+ *Gets information about the current position in
+ *the input of the parser.
+ *In case of failure, this macro returns from the
+ *calling function and
+ *returns a status code of type enum #CRStatus.
+ *@param a_this the current instance of #CRParser.
+ *@param a_pos out parameter. A pointer to the position
+ *inside the current parser input. Must
+ */
+#define RECORD_INITIAL_POS(a_this, a_pos) \
+status = cr_tknzr_get_cur_pos (PRIVATE \
+(a_this)->tknzr, a_pos) ; \
+g_return_val_if_fail (status == CR_OK, status)
+
+/**
+ *Gets the address of the current byte inside the
+ *parser input.
+ *@param parser the current instance of #CRParser.
+ *@param addr out parameter a pointer (guchar*)
+ *to where the address must be put.
+ */
+#define RECORD_CUR_BYTE_ADDR(a_this, a_addr) \
+status = cr_tknzr_get_cur_byte_addr \
+ (PRIVATE (a_this)->tknzr, a_addr) ; \
+CHECK_PARSING_STATUS (status, TRUE)
+
+/**
+ *Peeks a byte from the topmost parser input at
+ *a given offset from the current position.
+ *If it fails, goto the "error:" label.
+ *
+ *@param a_parser the current instance of #CRParser.
+ *@param a_offset the offset of the byte to peek, the
+ *current byte having the offset '0'.
+ *@param a_byte_ptr out parameter a pointer (guchar*) to
+ *where the peeked char is to be stored.
+ */
+#define PEEK_BYTE(a_parser, a_offset, a_byte_ptr) \
+status = cr_tknzr_peek_byte (PRIVATE (a_this)->tknzr, \
+ a_offset, \
+ a_byte_ptr) ; \
+CHECK_PARSING_STATUS (status, TRUE) ;
+
+#define BYTE(a_parser, a_offset, a_eof) \
+cr_tknzr_peek_byte2 (PRIVATE (a_this)->tknzr, a_offset, a_eof)
+
+/**
+ *Reads a byte from the topmost parser input
+ *steam.
+ *If it fails, goto the "error" label.
+ *@param a_this the current instance of #CRParser.
+ *@param a_byte_ptr the guchar * where to put the read char.
+ */
+#define READ_NEXT_BYTE(a_this, a_byte_ptr) \
+status = cr_tknzr_read_byte (PRIVATE (a_this)->tknzr, a_byte_ptr) ; \
+CHECK_PARSING_STATUS (status, TRUE) ;
+
+/**
+ *Skips a given number of byte in the topmost
+ *parser input. Don't update line and column number.
+ *In case of error, jumps to the "error:" label
+ *of the surrounding function.
+ *@param a_parser the current instance of #CRParser.
+ *@param a_nb_bytes the number of bytes to skip.
+ */
+#define SKIP_BYTES(a_this, a_nb_bytes) \
+status = cr_tknzr_seek_index (PRIVATE (a_this)->tknzr, \
+ CR_SEEK_CUR, a_nb_bytes) ; \
+CHECK_PARSING_STATUS (status, TRUE) ;
+
+/**
+ *Skip utf8 encoded characters.
+ *Updates line and column numbers.
+ *@param a_parser the current instance of #CRParser.
+ *@param a_nb_chars the number of chars to skip. Must be of
+ *type glong.
+ */
+#define SKIP_CHARS(a_parser, a_nb_chars) \
+{ \
+glong nb_chars = a_nb_chars ; \
+status = cr_tknzr_consume_chars \
+ (PRIVATE (a_parser)->tknzr,0, &nb_chars) ; \
+CHECK_PARSING_STATUS (status, TRUE) ; \
+}
+
+/**
+ *Tests the condition and if it is false, sets
+ *status to "CR_PARSING_ERROR" and goto the 'error'
+ *label.
+ *@param condition the condition to test.
+ */
+#define ENSURE_PARSING_COND(condition) \
+if (! (condition)) {status = CR_PARSING_ERROR; goto error ;}
+
+#define ENSURE_PARSING_COND_ERR(a_this, a_condition, \
+ a_err_msg, a_err_status) \
+if (! (a_condition)) \
+{ \
+ status = CR_PARSING_ERROR; \
+ cr_parser_push_error (a_this, a_err_msg, a_err_status) ; \
+ goto error ; \
+}
+
+#define GET_NEXT_TOKEN(a_this, a_token_ptr) \
+status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, \
+ a_token_ptr) ; \
+ENSURE_PARSING_COND (status == CR_OK) ;
+
+#ifdef WITH_UNICODE_ESCAPE_AND_RANGE
+static enum CRStatus cr_parser_parse_unicode_escape (CRParser * a_this,
+ guint32 * a_unicode);
+static enum CRStatus cr_parser_parse_escape (CRParser * a_this,
+ guint32 * a_esc_code);
+
+static enum CRStatus cr_parser_parse_unicode_range (CRParser * a_this,
+ CRString ** a_inf,
+ CRString ** a_sup);
+#endif
+
+static enum CRStatus cr_parser_parse_stylesheet_core (CRParser * a_this);
+
+static enum CRStatus cr_parser_parse_atrule_core (CRParser * a_this);
+
+static enum CRStatus cr_parser_parse_ruleset_core (CRParser * a_this);
+
+static enum CRStatus cr_parser_parse_selector_core (CRParser * a_this);
+
+static enum CRStatus cr_parser_parse_declaration_core (CRParser * a_this);
+
+static enum CRStatus cr_parser_parse_any_core (CRParser * a_this,
+ guint n_calls);
+
+static enum CRStatus cr_parser_parse_block_core (CRParser * a_this,
+ guint n_calls);
+
+static enum CRStatus cr_parser_parse_value_core (CRParser * a_this);
+
+static enum CRStatus cr_parser_parse_string (CRParser * a_this,
+ CRString ** a_str);
+
+static enum CRStatus cr_parser_parse_ident (CRParser * a_this,
+ CRString ** a_str);
+
+static enum CRStatus cr_parser_parse_uri (CRParser * a_this,
+ CRString ** a_str);
+
+static enum CRStatus cr_parser_parse_function (CRParser * a_this,
+ CRString ** a_func_name,
+ CRTerm ** a_expr);
+static enum CRStatus cr_parser_parse_property (CRParser * a_this,
+ CRString ** a_property);
+
+static enum CRStatus cr_parser_parse_attribute_selector (CRParser * a_this,
+ CRAttrSel ** a_sel);
+
+static enum CRStatus cr_parser_parse_simple_selector (CRParser * a_this,
+ CRSimpleSel ** a_sel);
+
+static enum CRStatus cr_parser_parse_simple_sels (CRParser * a_this,
+ CRSimpleSel ** a_sel);
+
+static CRParserError *cr_parser_error_new (const guchar * a_msg,
+ enum CRStatus);
+
+static void cr_parser_error_set_msg (CRParserError * a_this,
+ const guchar * a_msg);
+
+static void cr_parser_error_dump (CRParserError * a_this);
+
+static void cr_parser_error_set_status (CRParserError * a_this,
+ enum CRStatus a_status);
+
+static void cr_parser_error_set_pos (CRParserError * a_this,
+ glong a_line,
+ glong a_column, glong a_byte_num);
+static void
+ cr_parser_error_destroy (CRParserError * a_this);
+
+static enum CRStatus cr_parser_push_error (CRParser * a_this,
+ const guchar * a_msg,
+ enum CRStatus a_status);
+
+static enum CRStatus cr_parser_dump_err_stack (CRParser * a_this,
+ gboolean a_clear_errs);
+static enum CRStatus
+ cr_parser_clear_errors (CRParser * a_this);
+
+/*****************************
+ *error managemet methods
+ *****************************/
+
+/**
+ *Constructor of #CRParserError class.
+ *@param a_msg the brute error message.
+ *@param a_status the error status.
+ *@return the newly built instance of #CRParserError.
+ */
+static CRParserError *
+cr_parser_error_new (const guchar * a_msg, enum CRStatus a_status)
+{
+ CRParserError *result = NULL;
+
+ result = g_try_malloc (sizeof (CRParserError));
+
+ if (result == NULL) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRParserError));
+
+ cr_parser_error_set_msg (result, a_msg);
+ cr_parser_error_set_status (result, a_status);
+
+ return result;
+}
+
+/**
+ *Sets the message associated to this instance of #CRError.
+ *@param a_this the current instance of #CRParserError.
+ *@param a_msg the new message.
+ */
+static void
+cr_parser_error_set_msg (CRParserError * a_this, const guchar * a_msg)
+{
+ g_return_if_fail (a_this);
+
+ if (a_this->msg) {
+ g_free (a_this->msg);
+ }
+
+ a_this->msg = (guchar *) g_strdup ((const gchar *) a_msg);
+}
+
+/**
+ *Sets the error status.
+ *@param a_this the current instance of #CRParserError.
+ *@param a_status the new error status.
+ *
+ */
+static void
+cr_parser_error_set_status (CRParserError * a_this, enum CRStatus a_status)
+{
+ g_return_if_fail (a_this);
+
+ a_this->status = a_status;
+}
+
+/**
+ *Sets the position of the parser error.
+ *@param a_this the current instance of #CRParserError.
+ *@param a_line the line number.
+ *@param a_column the column number.
+ *@param a_byte_num the byte number.
+ */
+static void
+cr_parser_error_set_pos (CRParserError * a_this,
+ glong a_line, glong a_column, glong a_byte_num)
+{
+ g_return_if_fail (a_this);
+
+ a_this->line = a_line;
+ a_this->column = a_column;
+ a_this->byte_num = a_byte_num;
+}
+
+static void
+cr_parser_error_dump (CRParserError * a_this)
+{
+ g_return_if_fail (a_this);
+
+ g_printerr ("parsing error: %ld:%ld:", a_this->line, a_this->column);
+
+ g_printerr ("%s\n", a_this->msg);
+}
+
+/**
+ *The destructor of #CRParserError.
+ *@param a_this the current instance of #CRParserError.
+ */
+static void
+cr_parser_error_destroy (CRParserError * a_this)
+{
+ g_return_if_fail (a_this);
+
+ if (a_this->msg) {
+ g_free (a_this->msg);
+ a_this->msg = NULL;
+ }
+
+ g_free (a_this);
+}
+
+/**
+ *Pushes an error on the parser error stack.
+ *@param a_this the current instance of #CRParser.
+ *@param a_msg the error message.
+ *@param a_status the error status.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_push_error (CRParser * a_this,
+ const guchar * a_msg, enum CRStatus a_status)
+{
+ enum CRStatus status = CR_OK;
+
+ CRParserError *error = NULL;
+ CRInputPos pos;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_msg, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &pos);
+
+ error = cr_parser_error_new (a_msg, a_status);
+
+ g_return_val_if_fail (error, CR_ERROR);
+
+ cr_parser_error_set_pos
+ (error, pos.line, pos.col, pos.next_byte_index - 1);
+
+ PRIVATE (a_this)->err_stack =
+ g_list_prepend (PRIVATE (a_this)->err_stack, error);
+
+ if (PRIVATE (a_this)->err_stack == NULL)
+ goto error;
+
+ return CR_OK;
+
+ error:
+
+ if (error) {
+ cr_parser_error_destroy (error);
+ error = NULL;
+ }
+
+ return status;
+}
+
+/**
+ *Dumps the error stack using g_printerr.
+ *@param a_this the current instance of #CRParser.
+ *@param a_clear_errs whether to clear the error stack
+ *after the dump or not.
+ *@return CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+static enum CRStatus
+cr_parser_dump_err_stack (CRParser * a_this, gboolean a_clear_errs)
+{
+ GList *cur = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->err_stack == NULL)
+ return CR_OK;
+
+ for (cur = PRIVATE (a_this)->err_stack; cur; cur = cur->next) {
+ cr_parser_error_dump ((CRParserError *) cur->data);
+ }
+
+ if (a_clear_errs == TRUE) {
+ cr_parser_clear_errors (a_this);
+ }
+
+ return CR_OK;
+}
+
+/**
+ *Clears all the errors contained in the parser error stack.
+ *Frees all the errors, and the stack that contains'em.
+ *@param a_this the current instance of #CRParser.
+ */
+static enum CRStatus
+cr_parser_clear_errors (CRParser * a_this)
+{
+ GList *cur = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ for (cur = PRIVATE (a_this)->err_stack; cur; cur = cur->next) {
+ if (cur->data) {
+ cr_parser_error_destroy ((CRParserError *)
+ cur->data);
+ }
+ }
+
+ if (PRIVATE (a_this)->err_stack) {
+ g_list_free (PRIVATE (a_this)->err_stack);
+ PRIVATE (a_this)->err_stack = NULL;
+ }
+
+ return CR_OK;
+}
+
+/**
+ * cr_parser_try_to_skip_spaces_and_comments:
+ *@a_this: the current instance of #CRParser.
+ *
+ *Same as cr_parser_try_to_skip_spaces() but this one skips
+ *spaces and comments.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_try_to_skip_spaces_and_comments (CRParser * a_this)
+{
+ enum CRStatus status = CR_ERROR;
+ CRToken *token = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
+ do {
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token);
+ if (status != CR_OK)
+ goto error;
+ }
+ while ((token != NULL)
+ && (token->type == COMMENT_TK || token->type == S_TK));
+
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
+
+ return status;
+
+ error:
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ return status;
+}
+
+/***************************************
+ *End of Parser input handling routines
+ ***************************************/
+
+
+/*************************************
+ *Non trivial terminal productions
+ *parsing routines
+ *************************************/
+
+/**
+ *Parses a css stylesheet following the core css grammar.
+ *This is mainly done for test purposes.
+ *During the parsing, no callback is called. This is just
+ *to validate that the stylesheet is well formed according to the
+ *css core syntax.
+ *stylesheet : [ CDO | CDC | S | statement ]*;
+ *@param a_this the current instance of #CRParser.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_stylesheet_core (CRParser * a_this)
+{
+ CRToken *token = NULL;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ continue_parsing:
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ if (status == CR_END_OF_INPUT_ERROR) {
+ status = CR_OK;
+ goto done;
+ } else if (status != CR_OK) {
+ goto error;
+ }
+
+ switch (token->type) {
+
+ case CDO_TK:
+ case CDC_TK:
+ goto continue_parsing;
+ break;
+ default:
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+ token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token = NULL;
+ status = cr_parser_parse_statement_core (a_this);
+ cr_parser_clear_errors (a_this);
+ if (status == CR_OK) {
+ goto continue_parsing;
+ } else if (status == CR_END_OF_INPUT_ERROR) {
+ goto done;
+ } else {
+ goto error;
+ }
+ }
+
+ done:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_parser_clear_errors (a_this);
+ return CR_OK;
+
+ error:
+ cr_parser_push_error
+ (a_this, (const guchar *) "could not recognize next production", CR_ERROR);
+
+ cr_parser_dump_err_stack (a_this, TRUE);
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ *Parses an at-rule as defined by the css core grammar
+ *in chapter 4.1 in the css2 spec.
+ *at-rule : ATKEYWORD S* any* [ block | ';' S* ];
+ *@param a_this the current instance of #CRParser.
+ *@return CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_atrule_core (CRParser * a_this)
+{
+ CRToken *token = NULL;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token
+ &&
+ (token->type == ATKEYWORD_TK
+ || token->type == IMPORT_SYM_TK
+ || token->type == PAGE_SYM_TK
+ || token->type == MEDIA_SYM_TK
+ || token->type == FONT_FACE_SYM_TK
+ || token->type == CHARSET_SYM_TK));
+
+ cr_token_destroy (token);
+ token = NULL;
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ do {
+ status = cr_parser_parse_any_core (a_this, 0);
+ } while (status == CR_OK);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token);
+ ENSURE_PARSING_COND (status == CR_OK && token);
+
+ if (token->type == CBO_TK) {
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+ token);
+ token = NULL;
+ status = cr_parser_parse_block_core (a_this, 0);
+ CHECK_PARSING_STATUS (status,
+ FALSE);
+ goto done;
+ } else if (token->type == SEMICOLON_TK) {
+ goto done;
+ } else {
+ status = CR_PARSING_ERROR ;
+ goto error;
+ }
+
+ done:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+ return CR_OK;
+
+ error:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr,
+ &init_pos);
+ return status;
+}
+
+/**
+ *Parses a ruleset as defined by the css core grammar in chapter
+ *4.1 of the css2 spec.
+ *ruleset ::= selector? '{' S* declaration? [ ';' S* declaration? ]* '}' S*;
+ *@param a_this the current instance of #CRParser.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_ruleset_core (CRParser * a_this)
+{
+ CRToken *token = NULL;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_parser_parse_selector_core (a_this);
+
+ ENSURE_PARSING_COND (status == CR_OK
+ || status == CR_PARSING_ERROR
+ || status == CR_END_OF_INPUT_ERROR);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token
+ && token->type == CBO_TK);
+ cr_token_destroy (token);
+ token = NULL;
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ status = cr_parser_parse_declaration_core (a_this);
+
+ parse_declaration_list:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token);
+ if (token->type == CBC_TK) {
+ goto done;
+ }
+
+ ENSURE_PARSING_COND (status == CR_OK
+ && token && token->type == SEMICOLON_TK);
+
+ cr_token_destroy (token);
+ token = NULL;
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ status = cr_parser_parse_declaration_core (a_this);
+ cr_parser_clear_errors (a_this);
+ ENSURE_PARSING_COND (status == CR_OK || status == CR_PARSING_ERROR);
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token);
+ if (token->type == CBC_TK) {
+ cr_token_destroy (token);
+ token = NULL;
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ goto done;
+ } else {
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+ token);
+ token = NULL;
+ goto parse_declaration_list;
+ }
+
+ done:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (status == CR_OK) {
+ return CR_OK;
+ }
+
+ error:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ *Parses a "selector" as specified by the css core
+ *grammar.
+ *selector : any+;
+ *@param a_this the current instance of #CRParser.
+ *@return CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_selector_core (CRParser * a_this)
+{
+ CRToken *token = NULL;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_parser_parse_any_core (a_this, 0);
+ CHECK_PARSING_STATUS (status, FALSE);
+
+ do {
+ status = cr_parser_parse_any_core (a_this, 0);
+
+ } while (status == CR_OK);
+
+ return CR_OK;
+
+ error:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ *Parses a "block" as defined in the css core grammar
+ *in chapter 4.1 of the css2 spec.
+ *block ::= '{' S* [ any | block | ATKEYWORD S* | ';' ]* '}' S*;
+ *@param a_this the current instance of #CRParser.
+ *@param n_calls used to limit recursion depth
+ *FIXME: code this function.
+ */
+static enum CRStatus
+cr_parser_parse_block_core (CRParser * a_this,
+ guint n_calls)
+{
+ CRToken *token = NULL;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ if (n_calls > RECURSIVE_CALLERS_LIMIT)
+ return CR_ERROR;
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token
+ && token->type == CBO_TK);
+
+ parse_block_content:
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token);
+
+ if (token->type == CBC_TK) {
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ goto done;
+ } else if (token->type == SEMICOLON_TK) {
+ goto parse_block_content;
+ } else if (token->type == ATKEYWORD_TK) {
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ goto parse_block_content;
+ } else if (token->type == CBO_TK) {
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ status = cr_parser_parse_block_core (a_this, n_calls + 1);
+ CHECK_PARSING_STATUS (status, FALSE);
+ goto parse_block_content;
+ } else {
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ status = cr_parser_parse_any_core (a_this, n_calls + 1);
+ CHECK_PARSING_STATUS (status, FALSE);
+ goto parse_block_content;
+ }
+
+ done:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (status == CR_OK)
+ return CR_OK;
+
+ error:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+static enum CRStatus
+cr_parser_parse_declaration_core (CRParser * a_this)
+{
+ CRToken *token = NULL;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_ERROR;
+ CRString *prop = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_parser_parse_property (a_this, &prop);
+ CHECK_PARSING_STATUS (status, FALSE);
+ cr_parser_clear_errors (a_this);
+ ENSURE_PARSING_COND (status == CR_OK && prop);
+ cr_string_destroy (prop);
+ prop = NULL;
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token
+ && token->type == DELIM_TK
+ && token->u.unichar == ':');
+ cr_token_destroy (token);
+ token = NULL;
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ status = cr_parser_parse_value_core (a_this);
+ CHECK_PARSING_STATUS (status, FALSE);
+
+ return CR_OK;
+
+ error:
+
+ if (prop) {
+ cr_string_destroy (prop);
+ prop = NULL;
+ }
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ *Parses a "value" production as defined by the css core grammar
+ *in chapter 4.1.
+ *value ::= [ any | block | ATKEYWORD S* ]+;
+ *@param a_this the current instance of #CRParser.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_value_core (CRParser * a_this)
+{
+ CRToken *token = NULL;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_ERROR;
+ glong ref = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ continue_parsing:
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token);
+
+ switch (token->type) {
+ case CBO_TK:
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+ token);
+ token = NULL;
+ status = cr_parser_parse_block_core (a_this, 0);
+ CHECK_PARSING_STATUS (status, FALSE);
+ ref++;
+ goto continue_parsing;
+
+ case ATKEYWORD_TK:
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ ref++;
+ goto continue_parsing;
+
+ default:
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+ token);
+ token = NULL;
+ status = cr_parser_parse_any_core (a_this, 0);
+ if (status == CR_OK) {
+ ref++;
+ goto continue_parsing;
+ } else if (status == CR_PARSING_ERROR) {
+ status = CR_OK;
+ goto done;
+ } else {
+ goto error;
+ }
+ }
+
+ done:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (status == CR_OK && ref)
+ return CR_OK;
+ error:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ *Parses an "any" as defined by the css core grammar in the
+ *css2 spec in chapter 4.1.
+ *any ::= [ IDENT | NUMBER | PERCENTAGE | DIMENSION | STRING
+ * | DELIM | URI | HASH | UNICODE-RANGE | INCLUDES
+ * | FUNCTION | DASHMATCH | '(' any* ')' | '[' any* ']' ] S*;
+ *
+ *@param a_this the current instance of #CRParser.
+ *@param n_calls used to limit recursion depth
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_any_core (CRParser * a_this,
+ guint n_calls)
+{
+ CRToken *token1 = NULL,
+ *token2 = NULL;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_ERROR;
+
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ if (n_calls > RECURSIVE_CALLERS_LIMIT)
+ return CR_ERROR;
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token1);
+
+ ENSURE_PARSING_COND (status == CR_OK && token1);
+
+ switch (token1->type) {
+ case IDENT_TK:
+ case NUMBER_TK:
+ case RGB_TK:
+ case PERCENTAGE_TK:
+ case DIMEN_TK:
+ case EMS_TK:
+ case EXS_TK:
+ case LENGTH_TK:
+ case ANGLE_TK:
+ case FREQ_TK:
+ case TIME_TK:
+ case STRING_TK:
+ case DELIM_TK:
+ case URI_TK:
+ case HASH_TK:
+ case UNICODERANGE_TK:
+ case INCLUDES_TK:
+ case DASHMATCH_TK:
+ case S_TK:
+ case COMMENT_TK:
+ case IMPORTANT_SYM_TK:
+ status = CR_OK;
+ break;
+ case FUNCTION_TK:
+ /*
+ *this case isn't specified by the spec but it
+ *does happen. So we have to handle it.
+ *We must consider function with parameters.
+ *We consider parameter as being an "any*" production.
+ */
+ do {
+ status = cr_parser_parse_any_core (a_this, n_calls + 1);
+ } while (status == CR_OK);
+
+ ENSURE_PARSING_COND (status == CR_PARSING_ERROR);
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token2);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token2 && token2->type == PC_TK);
+ break;
+ case PO_TK:
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token2);
+ ENSURE_PARSING_COND (status == CR_OK && token2);
+
+ if (token2->type == PC_TK) {
+ cr_token_destroy (token2);
+ token2 = NULL;
+ goto done;
+ } else {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token2);
+ token2 = NULL;
+ }
+
+ do {
+ status = cr_parser_parse_any_core (a_this, n_calls + 1);
+ } while (status == CR_OK);
+
+ ENSURE_PARSING_COND (status == CR_PARSING_ERROR);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token2);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token2 && token2->type == PC_TK);
+ status = CR_OK;
+ break;
+
+ case BO_TK:
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token2);
+ ENSURE_PARSING_COND (status == CR_OK && token2);
+
+ if (token2->type == BC_TK) {
+ cr_token_destroy (token2);
+ token2 = NULL;
+ goto done;
+ } else {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token2);
+ token2 = NULL;
+ }
+
+ do {
+ status = cr_parser_parse_any_core (a_this, n_calls + 1);
+ } while (status == CR_OK);
+
+ ENSURE_PARSING_COND (status == CR_PARSING_ERROR);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token2);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token2 && token2->type == BC_TK);
+ status = CR_OK;
+ break;
+ default:
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+
+ done:
+ if (token1) {
+ cr_token_destroy (token1);
+ token1 = NULL;
+ }
+
+ if (token2) {
+ cr_token_destroy (token2);
+ token2 = NULL;
+ }
+
+ return CR_OK;
+
+ error:
+
+ if (token1) {
+ cr_token_destroy (token1);
+ token1 = NULL;
+ }
+
+ if (token2) {
+ cr_token_destroy (token2);
+ token2 = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+ return status;
+}
+
+/**
+ *Parses an attribute selector as defined in the css2 spec in
+ *appendix D.1:
+ *attrib ::= '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S*
+ * [ IDENT | STRING ] S* ]? ']'
+ *
+ *@param a_this the "this pointer" of the current instance of
+ *#CRParser .
+ *@param a_sel out parameter. The successfully parsed attribute selector.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_attribute_selector (CRParser * a_this,
+ CRAttrSel ** a_sel)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+ CRToken *token = NULL;
+ CRAttrSel *result = NULL;
+ CRParsingLocation location = {0,0,0} ;
+
+ g_return_val_if_fail (a_this && a_sel, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token
+ && token->type == BO_TK);
+ cr_parsing_location_copy
+ (&location, &token->location) ;
+ cr_token_destroy (token);
+ token = NULL;
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ result = cr_attr_sel_new ();
+ if (!result) {
+ cr_utils_trace_info ("result failed") ;
+ status = CR_OUT_OF_MEMORY_ERROR ;
+ goto error ;
+ }
+ cr_parsing_location_copy (&result->location,
+ &location) ;
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token && token->type == IDENT_TK);
+
+ result->name = token->u.str;
+ token->u.str = NULL;
+ cr_token_destroy (token);
+ token = NULL;
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token);
+
+ if (token->type == INCLUDES_TK) {
+ result->match_way = INCLUDES;
+ goto parse_right_part;
+ } else if (token->type == DASHMATCH_TK) {
+ result->match_way = DASHMATCH;
+ goto parse_right_part;
+ } else if (token->type == DELIM_TK && token->u.unichar == '=') {
+ result->match_way = EQUALS;
+ goto parse_right_part;
+ } else if (token->type == BC_TK) {
+ result->match_way = SET;
+ goto done;
+ }
+
+ parse_right_part:
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token);
+
+ if (token->type == IDENT_TK) {
+ result->value = token->u.str;
+ token->u.str = NULL;
+ } else if (token->type == STRING_TK) {
+ result->value = token->u.str;
+ token->u.str = NULL;
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+
+ ENSURE_PARSING_COND (status == CR_OK && token
+ && token->type == BC_TK);
+ done:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (*a_sel) {
+ status = cr_attr_sel_append_attr_sel (*a_sel, result);
+ CHECK_PARSING_STATUS (status, FALSE);
+ } else {
+ *a_sel = result;
+ }
+
+ cr_parser_clear_errors (a_this);
+ return CR_OK;
+
+ error:
+
+ if (result) {
+ cr_attr_sel_destroy (result);
+ result = NULL;
+ }
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ *Parses a "property" as specified by the css2 spec at [4.1.1]:
+ *property : IDENT S*;
+ *
+ *@param a_this the "this pointer" of the current instance of #CRParser.
+ *@param GString a_property out parameter. The parsed property without the
+ *trailing spaces. If *a_property is NULL, this function allocates a
+ *new instance of GString and set it content to the parsed property.
+ *If not, the property is just appended to a_property's previous content.
+ *In both cases, it is up to the caller to free a_property.
+ *@return CR_OK upon successful completion, CR_PARSING_ERROR if the
+ *next construction was not a "property", or an error code.
+ */
+static enum CRStatus
+cr_parser_parse_property (CRParser * a_this,
+ CRString ** a_property)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->tknzr
+ && a_property,
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_parser_parse_ident (a_this, a_property);
+ CHECK_PARSING_STATUS (status, TRUE);
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ cr_parser_clear_errors (a_this);
+ return CR_OK;
+
+ error:
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_term:
+ *@a_term: out parameter. The successfully parsed term.
+ *
+ *Parses a "term" as defined in the css2 spec, appendix D.1:
+ *term ::= unary_operator? [NUMBER S* | PERCENTAGE S* | LENGTH S* |
+ *EMS S* | EXS S* | ANGLE S* | TIME S* | FREQ S* | function ] |
+ *STRING S* | IDENT S* | URI S* | RGB S* | UNICODERANGE S* | hexcolor
+ *
+ * As a special case for 'an+b', parse integer followed immediately by 'n'.
+ * The 'an' is parsed as a DIMEN.
+ *
+ *TODO: handle parsing of 'RGB'
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_term (CRParser * a_this, CRTerm ** a_term)
+{
+ enum CRStatus status = CR_PARSING_ERROR;
+ CRInputPos init_pos;
+ CRTerm *result = NULL;
+ CRTerm *param = NULL;
+ CRToken *token = NULL;
+ CRString *func_name = NULL;
+ CRParsingLocation location = {0,0,0} ;
+
+ g_return_val_if_fail (a_this && a_term, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ result = cr_term_new ();
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token);
+ if (status != CR_OK || !token)
+ goto error;
+
+ cr_parsing_location_copy (&location, &token->location) ;
+ if (token->type == DELIM_TK && token->u.unichar == '+') {
+ result->unary_op = PLUS_UOP;
+ cr_token_destroy (token) ;
+ token = NULL ;
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token);
+ if (status != CR_OK || !token)
+ goto error;
+ } else if (token->type == DELIM_TK && token->u.unichar == '-') {
+ result->unary_op = MINUS_UOP;
+ cr_token_destroy (token) ;
+ token = NULL ;
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token);
+ if (status != CR_OK || !token)
+ goto error;
+ }
+
+ if (token->type == EMS_TK
+ || token->type == EXS_TK
+ || token->type == LENGTH_TK
+ || token->type == ANGLE_TK
+ || token->type == TIME_TK
+ || token->type == FREQ_TK
+ || token->type == PERCENTAGE_TK
+ || token->type == NUMBER_TK) {
+ status = cr_term_set_number (result, token->u.num);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token->u.num = NULL;
+ status = CR_OK;
+ } else if (token && token->type == FUNCTION_TK) {
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+ token);
+ token = NULL;
+ status = cr_parser_parse_function (a_this, &func_name,
+ &param);
+
+ if (status == CR_OK) {
+ status = cr_term_set_function (result,
+ func_name,
+ param);
+ CHECK_PARSING_STATUS (status, TRUE);
+ }
+ } else if (token && token->type == STRING_TK) {
+ status = cr_term_set_string (result,
+ token->u.str);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token->u.str = NULL;
+ } else if (token && token->type == IDENT_TK) {
+ status = cr_term_set_ident (result, token->u.str);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token->u.str = NULL;
+ } else if (token && token->type == URI_TK) {
+ status = cr_term_set_uri (result, token->u.str);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token->u.str = NULL;
+ } else if (token && token->type == RGB_TK) {
+ status = cr_term_set_rgb (result, token->u.rgb);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token->u.rgb = NULL;
+ } else if (token && token->type == UNICODERANGE_TK) {
+ result->type = TERM_UNICODERANGE;
+ status = CR_PARSING_ERROR;
+ } else if (token && token->type == HASH_TK) {
+ status = cr_term_set_hash (result, token->u.str);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token->u.str = NULL;
+ } else if (token && token->type == DIMEN_TK) {
+ gboolean n = !strcmp(token->dimen->stryng->str, "n");
+ status = cr_term_set_number (result, token->u.num);
+ result->n = n; // For nth-child (an+b)
+ CHECK_PARSING_STATUS (status, TRUE);
+ token->u.num = NULL;
+ status = CR_OK;
+ } else {
+ status = CR_PARSING_ERROR;
+ }
+
+ if (status != CR_OK) {
+ goto error;
+ }
+ cr_parsing_location_copy (&result->location,
+ &location) ;
+ *a_term = cr_term_append_term (*a_term, result);
+
+ result = NULL;
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_parser_clear_errors (a_this);
+ return CR_OK;
+
+ error:
+
+ if (result) {
+ cr_term_destroy (result);
+ result = NULL;
+ }
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (param) {
+ cr_term_destroy (param);
+ param = NULL;
+ }
+
+ if (func_name) {
+ cr_string_destroy (func_name);
+ func_name = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_simple_selector:
+ *@a_this: the "this pointer" of the current instance of #CRParser.
+ *@a_sel: out parameter. Is set to the successfully parsed simple
+ *selector.
+ *
+ *Parses a "simple_selector" as defined by the css2 spec in appendix D.1 :
+ *element_name? [ HASH | class | attrib | pseudo ]* S*
+ *and where pseudo is:
+ *pseudo ::= ':' [ IDENT | FUNCTION S* IDENT S* ')' ]
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_simple_selector (CRParser * a_this, CRSimpleSel ** a_sel)
+{
+ enum CRStatus status = CR_ERROR;
+ CRInputPos init_pos;
+ CRToken *token = NULL;
+ CRSimpleSel *sel = NULL;
+ CRPseudo *pseudo = NULL;
+ CRAdditionalSel *add_sel_list = NULL;
+ gboolean found_sel = FALSE;
+
+ g_return_val_if_fail (a_this && a_sel, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ if (status != CR_OK)
+ goto error;
+
+ sel = cr_simple_sel_new ();
+ ENSURE_PARSING_COND (sel);
+
+ cr_parsing_location_copy
+ (&sel->location,
+ &token->location) ;
+
+ if (token && token->type == DELIM_TK
+ && token->u.unichar == '*') {
+ int comb = (int)sel->type_mask | (int) UNIVERSAL_SELECTOR;
+ sel->type_mask = (enum SimpleSelectorType)comb;
+ sel->name = cr_string_new_from_string ("*");
+ found_sel = TRUE;
+ } else if (token && token->type == IDENT_TK) {
+ int comb = (int)sel->type_mask | (int) TYPE_SELECTOR;
+ sel->type_mask = (enum SimpleSelectorType)comb;
+ sel->name = token->u.str;
+ token->u.str = NULL;
+ found_sel = TRUE;
+ } else {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr,
+ token);
+ token = NULL;
+ }
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ while (cr_tknzr_get_nb_bytes_left ((PRIVATE (a_this)->tknzr))) {
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ status = cr_tknzr_get_next_token
+ (PRIVATE (a_this)->tknzr,
+ &token);
+ if (status != CR_OK)
+ goto error;
+
+ if (token && token->type == HASH_TK) {
+ /*we parsed an attribute id */
+ CRAdditionalSel *add_sel = NULL;
+
+ add_sel = cr_additional_sel_new_with_type
+ (ID_ADD_SELECTOR);
+
+ add_sel->content.id_name = token->u.str;
+ token->u.str = NULL;
+
+ cr_parsing_location_copy
+ (&add_sel->location,
+ &token->location) ;
+ add_sel_list =
+ cr_additional_sel_append
+ (add_sel_list, add_sel);
+ found_sel = TRUE;
+ } else if (token && (token->type == DELIM_TK)
+ && (token->u.unichar == '.')) {
+ cr_token_destroy (token);
+ token = NULL;
+
+ status = cr_tknzr_get_next_token
+ (PRIVATE (a_this)->tknzr, &token);
+ if (status != CR_OK)
+ goto error;
+
+ if (token && token->type == IDENT_TK) {
+ CRAdditionalSel *add_sel = NULL;
+
+ add_sel = cr_additional_sel_new_with_type
+ (CLASS_ADD_SELECTOR);
+
+ add_sel->content.class_name = token->u.str;
+ token->u.str = NULL;
+
+ add_sel_list =
+ cr_additional_sel_append
+ (add_sel_list, add_sel);
+ found_sel = TRUE;
+
+ cr_parsing_location_copy
+ (&add_sel->location,
+ & token->location) ;
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ } else if (token && token->type == BO_TK) {
+ CRAttrSel *attr_sel = NULL;
+ CRAdditionalSel *add_sel = NULL;
+
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ if (status != CR_OK)
+ goto error;
+ token = NULL;
+
+ status = cr_parser_parse_attribute_selector
+ (a_this, &attr_sel);
+ CHECK_PARSING_STATUS (status, FALSE);
+
+ add_sel = cr_additional_sel_new_with_type
+ (ATTRIBUTE_ADD_SELECTOR);
+
+ ENSURE_PARSING_COND (add_sel != NULL);
+
+ add_sel->content.attr_sel = attr_sel;
+
+ add_sel_list =
+ cr_additional_sel_append
+ (add_sel_list, add_sel);
+ found_sel = TRUE;
+ cr_parsing_location_copy
+ (&add_sel->location,
+ &attr_sel->location) ;
+ } else if (token && (token->type == DELIM_TK)
+ && (token->u.unichar == ':')) {
+
+ /*try to parse a pseudo */
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ pseudo = cr_pseudo_new ();
+
+ status = cr_tknzr_get_next_token
+ (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token);
+
+ cr_parsing_location_copy
+ (&pseudo->location,
+ &token->location) ;
+
+ /* Save selector name for use by 'type' pseudo selectors */
+ if (sel->name)
+ pseudo->sel_name = cr_string_dup (sel->name);
+
+ if (token->type == IDENT_TK) {
+ pseudo->type = IDENT_PSEUDO;
+ pseudo->name = token->u.str;
+ token->u.str = NULL;
+ found_sel = TRUE;
+ } else if (token->type == FUNCTION_TK) {
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ status = cr_parser_parse_function (a_this, &pseudo->name, &pseudo->term);
+ ENSURE_PARSING_COND (status == CR_OK);
+
+ pseudo->type = FUNCTION_PSEUDO;
+ found_sel = TRUE;
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+
+ if (status == CR_OK) {
+ CRAdditionalSel *add_sel = NULL;
+
+ add_sel = cr_additional_sel_new_with_type
+ (PSEUDO_CLASS_ADD_SELECTOR);
+
+ add_sel->content.pseudo = pseudo;
+ cr_parsing_location_copy
+ (&add_sel->location,
+ &pseudo->location) ;
+ pseudo = NULL;
+ add_sel_list =
+ cr_additional_sel_append
+ (add_sel_list, add_sel);
+ status = CR_OK;
+ }
+ } else {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ break;
+ }
+ } // for loop
+
+ if (status == CR_OK && found_sel == TRUE) {
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ sel->add_sel = add_sel_list;
+ add_sel_list = NULL;
+
+ if (*a_sel == NULL) {
+ *a_sel = sel;
+ } else {
+ cr_simple_sel_append_simple_sel (*a_sel, sel);
+ }
+
+ sel = NULL;
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_parser_clear_errors (a_this);
+ return CR_OK;
+ } else {
+ status = CR_PARSING_ERROR;
+ }
+
+ error:
+
+ g_clear_pointer (&pseudo, cr_pseudo_destroy);
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (add_sel_list) {
+ cr_additional_sel_destroy (add_sel_list);
+ add_sel_list = NULL;
+ }
+
+ if (sel) {
+ cr_simple_sel_destroy (sel);
+ sel = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+
+}
+
+/**
+ * cr_parser_parse_simple_sels:
+ *@a_this: the this pointer of the current instance of #CRParser.
+ *@a_start: a pointer to the
+ *first chararcter of the successfully parsed
+ *string.
+ *@a_end: a pointer to the last character of the successfully parsed
+ *string.
+ *
+ *Parses a "selector" as defined by the css2 spec in appendix D.1:
+ *selector ::= simple_selector [ combinator simple_selector ]*
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_simple_sels (CRParser * a_this,
+ CRSimpleSel ** a_sel)
+{
+ enum CRStatus status = CR_ERROR;
+ CRInputPos init_pos;
+ CRSimpleSel *sel = NULL;
+ guint32 cur_char = 0;
+
+ g_return_val_if_fail (a_this
+ && PRIVATE (a_this)
+ && a_sel,
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_parser_parse_simple_selector (a_this, &sel);
+ CHECK_PARSING_STATUS (status, FALSE);
+
+ *a_sel = cr_simple_sel_append_simple_sel (*a_sel, sel);
+
+ for (;;) {
+ guint32 next_char = 0;
+ enum Combinator comb = NO_COMBINATOR;
+
+ sel = NULL;
+
+ status =
+ cr_tknzr_peek_char (PRIVATE (a_this)->tknzr, &next_char);
+ if (status == CR_END_OF_INPUT_ERROR)
+ break;
+ if (status != CR_OK)
+ goto error;
+
+ if (next_char == '+') {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ comb = COMB_PLUS;
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ } else if (next_char == '~') {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ comb = COMB_TILDE;
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ } else if (next_char == '>') {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ comb = COMB_GT;
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ } else {
+ comb = COMB_WS;
+ }
+
+ status = cr_parser_parse_simple_selector (a_this, &sel);
+ if (status != CR_OK)
+ break;
+
+ if (comb != NO_COMBINATOR && sel) {
+ sel->combinator = comb;
+ comb = NO_COMBINATOR;
+ }
+ if (sel) {
+ *a_sel = cr_simple_sel_append_simple_sel (*a_sel,
+ sel) ;
+ }
+ }
+ cr_parser_clear_errors (a_this);
+ return CR_OK;
+
+ error:
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_selector:
+ *@a_this: the current instance of #CRParser.
+ *@a_selector: the parsed list of comma separated
+ *selectors.
+ *
+ *Parses a comma separated list of selectors.
+ *
+ *Returns CR_OK upon successful completion, an error
+ *code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_selector (CRParser * a_this,
+ CRSelector ** a_selector)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+ guint32 cur_char = 0,
+ next_char = 0;
+ CRSimpleSel *simple_sels = NULL;
+ CRSelector *selector = NULL;
+
+ g_return_val_if_fail (a_this && a_selector, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_parser_parse_simple_sels (a_this, &simple_sels);
+ CHECK_PARSING_STATUS (status, FALSE);
+
+ if (simple_sels) {
+ selector = cr_selector_append_simple_sel
+ (selector, simple_sels);
+ if (selector) {
+ cr_parsing_location_copy
+ (&selector->location,
+ &simple_sels->location) ;
+ }
+ simple_sels = NULL;
+ } else {
+ status = CR_PARSING_ERROR ;
+ goto error ;
+ }
+
+ status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr,
+ &next_char);
+ if (status != CR_OK) {
+ if (status == CR_END_OF_INPUT_ERROR) {
+ status = CR_OK;
+ goto okay;
+ } else {
+ goto error;
+ }
+ }
+
+ if (next_char == ',') {
+ for (;;) {
+ simple_sels = NULL;
+
+ status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr,
+ &next_char);
+ if (status != CR_OK) {
+ if (status == CR_END_OF_INPUT_ERROR) {
+ status = CR_OK;
+ break;
+ } else {
+ goto error;
+ }
+ }
+
+ if (next_char != ',')
+ break;
+
+ /*consume the ',' char */
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_parser_parse_simple_sels
+ (a_this, &simple_sels);
+
+ CHECK_PARSING_STATUS (status, FALSE);
+
+ if (simple_sels) {
+ selector =
+ cr_selector_append_simple_sel
+ (selector, simple_sels);
+
+ simple_sels = NULL;
+ }
+ }
+ }
+
+ okay:
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ if (!*a_selector) {
+ *a_selector = selector;
+ } else {
+ *a_selector = cr_selector_append (*a_selector, selector);
+ }
+
+ selector = NULL;
+ return CR_OK;
+
+ error:
+
+ if (simple_sels) {
+ cr_simple_sel_destroy (simple_sels);
+ simple_sels = NULL;
+ }
+
+ if (selector) {
+ cr_selector_unref (selector);
+ selector = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_function:
+ *@a_this: the "this pointer" of the current instance of #CRParser.
+ *
+ *@a_func_name: out parameter. The parsed function name
+ *@a_expr: out parameter. The successfully parsed term.
+ *
+ *Parses a "function" as defined in css spec at appendix D.1:
+ *function ::= FUNCTION S* expr ')' S*
+ *FUNCTION ::= ident'('
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_function (CRParser * a_this,
+ CRString ** a_func_name,
+ CRTerm ** a_expr)
+{
+ CRInputPos init_pos;
+ enum CRStatus status = CR_OK;
+ CRToken *token = NULL;
+ CRTerm *expr = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_func_name,
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ if (status != CR_OK)
+ goto error;
+
+ if (token && token->type == FUNCTION_TK) {
+ *a_func_name = token->u.str;
+ token->u.str = NULL;
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ cr_token_destroy (token);
+ token = NULL;
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this) ;
+
+ status = cr_parser_parse_expr (a_this, &expr);
+
+ CHECK_PARSING_STATUS (status, FALSE);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ if (status != CR_OK)
+ goto error;
+
+ ENSURE_PARSING_COND (token && token->type == PC_TK);
+
+ cr_token_destroy (token);
+ token = NULL;
+
+ if (expr) {
+ *a_expr = cr_term_append_term (*a_expr, expr);
+ expr = NULL;
+ }
+
+ cr_parser_clear_errors (a_this);
+ return CR_OK;
+
+ error:
+
+ if (*a_func_name) {
+ cr_string_destroy (*a_func_name);
+ *a_func_name = NULL;
+ }
+
+ if (expr) {
+ cr_term_destroy (expr);
+ expr = NULL;
+ }
+
+ if (token) {
+ cr_token_destroy (token);
+
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_uri:
+ *@a_this: the current instance of #CRParser.
+ *@a_str: the successfully parsed url.
+ *
+ *Parses an uri as defined by the css spec [4.1.1]:
+ * URI ::= url\({w}{string}{w}\)
+ * |url\({w}([!#$%&*-~]|{nonascii}|{escape})*{w}\)
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_uri (CRParser * a_this, CRString ** a_str)
+{
+
+ enum CRStatus status = CR_PARSING_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
+
+ status = cr_tknzr_parse_token (PRIVATE (a_this)->tknzr,
+ URI_TK, NO_ET, a_str, NULL);
+ return status;
+}
+
+/**
+ * cr_parser_parse_string:
+ *@a_this: the current instance of #CRParser.
+ *@a_start: out parameter. Upon successful completion,
+ *points to the beginning of the string, points to an undefined value
+ *otherwise.
+ *@a_end: out parameter. Upon successful completion, points to
+ *the beginning of the string, points to an undefined value otherwise.
+ *
+ *Parses a string type as defined in css spec [4.1.1]:
+ *
+ *string ::= {string1}|{string2}
+ *string1 ::= \"([\t !#$%&(-~]|\\{nl}|\'|{nonascii}|{escape})*\"
+ *string2 ::= \'([\t !#$%&(-~]|\\{nl}|\"|{nonascii}|{escape})*\'
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_string (CRParser * a_this, CRString ** a_str)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->tknzr
+ && a_str, CR_BAD_PARAM_ERROR);
+
+ status = cr_tknzr_parse_token (PRIVATE (a_this)->tknzr,
+ STRING_TK, NO_ET, a_str, NULL);
+ return status;
+}
+
+/**
+ *Parses an "ident" as defined in css spec [4.1.1]:
+ *ident ::= {nmstart}{nmchar}*
+ *
+ *@param a_this the currens instance of #CRParser.
+ *
+ *@param a_str a pointer to parsed ident. If *a_str is NULL,
+ *this function allocates a new instance of #CRString. If not,
+ *the function just appends the parsed string to the one passed.
+ *In both cases it is up to the caller to free *a_str.
+ *
+ *@return CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_ident (CRParser * a_this, CRString ** a_str)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->tknzr
+ && a_str, CR_BAD_PARAM_ERROR);
+
+ status = cr_tknzr_parse_token (PRIVATE (a_this)->tknzr,
+ IDENT_TK, NO_ET, a_str, NULL);
+ return status;
+}
+
+/**
+ *the next rule is ignored as well. This seems to be a bug
+ *Parses a stylesheet as defined in the css2 spec in appendix D.1:
+ *stylesheet ::= [ CHARSET_SYM S* STRING S* ';' ]?
+ * [S|CDO|CDC]* [ import [S|CDO|CDC]* ]*
+ * [ [ ruleset | media | page | font_face ] [S|CDO|CDC]* ]*
+ *
+ *TODO: Finish the code of this function. Think about splitting it into
+ *smaller functions.
+ *
+ *@param a_this the "this pointer" of the current instance of #CRParser.
+ *@param a_start out parameter. A pointer to the first character of
+ *the successfully parsed string.
+ *@param a_end out parameter. A pointer to the first character of
+ *the successfully parsed string.
+ *
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_parser_parse_stylesheet (CRParser * a_this)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+ CRToken *token = NULL;
+ CRString *charset = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ PRIVATE (a_this)->state = READY_STATE;
+
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->start_document) {
+ PRIVATE (a_this)->sac_handler->start_document
+ (PRIVATE (a_this)->sac_handler);
+ }
+
+ parse_charset:
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+
+ if (status == CR_END_OF_INPUT_ERROR)
+ goto done;
+ CHECK_PARSING_STATUS (status, TRUE);
+
+ if (token && token->type == CHARSET_SYM_TK) {
+ CRParsingLocation location = {0,0,0} ;
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+ token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token = NULL;
+
+ status = cr_parser_parse_charset (a_this,
+ &charset,
+ &location);
+
+ if (status == CR_OK && charset) {
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->charset) {
+ PRIVATE (a_this)->sac_handler->charset
+ (PRIVATE (a_this)->sac_handler,
+ charset, &location);
+ }
+ } else if (status != CR_END_OF_INPUT_ERROR) {
+ status = cr_parser_parse_atrule_core (a_this);
+ CHECK_PARSING_STATUS (status, FALSE);
+ }
+
+ if (charset) {
+ cr_string_destroy (charset);
+ charset = NULL;
+ }
+ } else if (token
+ && (token->type == S_TK
+ || token->type == COMMENT_TK)) {
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+ token);
+ token = NULL;
+ CHECK_PARSING_STATUS (status, TRUE);
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ goto parse_charset ;
+ } else if (token) {
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+ token);
+ token = NULL;
+ CHECK_PARSING_STATUS (status, TRUE);
+ }
+
+/* parse_imports:*/
+ do {
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+ cr_parser_try_to_skip_spaces_and_comments (a_this) ;
+ status = cr_tknzr_get_next_token
+ (PRIVATE (a_this)->tknzr, &token);
+
+ if (status == CR_END_OF_INPUT_ERROR)
+ goto done;
+ CHECK_PARSING_STATUS (status, TRUE);
+ } while (token
+ && (token->type == S_TK
+ || token->type == CDO_TK || token->type == CDC_TK));
+
+ if (token) {
+ status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+ token);
+ token = NULL;
+ }
+
+ for (;;) {
+ status = cr_tknzr_get_next_token
+ (PRIVATE (a_this)->tknzr, &token);
+ if (status == CR_END_OF_INPUT_ERROR)
+ goto done;
+ CHECK_PARSING_STATUS (status, TRUE);
+
+ if (token && token->type == IMPORT_SYM_TK) {
+ GList *media_list = NULL;
+ CRString *import_string = NULL;
+ CRParsingLocation location = {0,0,0} ;
+
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ CHECK_PARSING_STATUS (status, TRUE);
+
+ status = cr_parser_parse_import (a_this,
+ &media_list,
+ &import_string,
+ &location);
+ if (status == CR_OK) {
+ if (import_string
+ && PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->import_style) {
+ PRIVATE (a_this)->sac_handler->import_style
+ (PRIVATE(a_this)->sac_handler,
+ media_list,
+ import_string,
+ NULL, &location) ;
+
+ if (PRIVATE (a_this)->sac_handler->resolve_import == TRUE) {
+ /*
+ *TODO: resolve the
+ *import rule.
+ */
+ }
+
+ if (PRIVATE (a_this)->sac_handler->import_style_result) {
+ PRIVATE (a_this)->sac_handler->import_style_result
+ (PRIVATE (a_this)->sac_handler,
+ media_list, import_string,
+ NULL, NULL);
+ }
+ }
+ } else if (status != CR_END_OF_INPUT_ERROR) {
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->error) {
+ PRIVATE (a_this)->sac_handler->error
+ (PRIVATE (a_this)->sac_handler);
+ }
+ status = cr_parser_parse_atrule_core (a_this);
+ CHECK_PARSING_STATUS (status, TRUE) ;
+ } else {
+ goto error ;
+ }
+
+ /*
+ *then, after calling the appropriate
+ *SAC handler, free
+ *the media_list and import_string.
+ */
+ if (media_list) {
+ GList *cur = NULL;
+
+ /*free the medium list */
+ for (cur = media_list; cur; cur = cur->next) {
+ if (cur->data) {
+ cr_string_destroy (cur->data);
+ }
+ }
+
+ g_list_free (media_list);
+ media_list = NULL;
+ }
+
+ if (import_string) {
+ cr_string_destroy (import_string);
+ import_string = NULL;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ } else if (token
+ && (token->type == S_TK
+ || token->type == CDO_TK
+ || token->type == CDC_TK)) {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+
+ do {
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ status = cr_tknzr_get_next_token
+ (PRIVATE (a_this)->tknzr, &token);
+
+ if (status == CR_END_OF_INPUT_ERROR)
+ goto done;
+ CHECK_PARSING_STATUS (status, TRUE);
+ } while (token
+ && (token->type == S_TK
+ || token->type == CDO_TK
+ || token->type == CDC_TK));
+ } else {
+ if (token) {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ }
+ goto parse_ruleset_and_others;
+ }
+ }
+
+ parse_ruleset_and_others:
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ for (;;) {
+ status = cr_tknzr_get_next_token
+ (PRIVATE (a_this)->tknzr, &token);
+ if (status == CR_END_OF_INPUT_ERROR)
+ goto done;
+ CHECK_PARSING_STATUS (status, TRUE);
+
+ if (token
+ && (token->type == S_TK
+ || token->type == CDO_TK || token->type == CDC_TK)) {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+
+ do {
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments
+ (a_this);
+ status = cr_tknzr_get_next_token
+ (PRIVATE (a_this)->tknzr, &token);
+ } while (token
+ && (token->type == S_TK
+ || token->type == COMMENT_TK
+ || token->type == CDO_TK
+ || token->type == CDC_TK));
+ if (token) {
+ cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ }
+ } else if (token
+ && (token->type == HASH_TK
+ || (token->type == DELIM_TK
+ && token->u.unichar == '.')
+ || (token->type == DELIM_TK
+ && token->u.unichar == ':')
+ || (token->type == DELIM_TK
+ && token->u.unichar == '*')
+ || (token->type == BO_TK)
+ || token->type == IDENT_TK)) {
+ /*
+ *Try to parse a CSS2 ruleset.
+ *if the parsing fails, try to parse
+ *a css core ruleset.
+ */
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token = NULL;
+
+ status = cr_parser_parse_ruleset (a_this);
+
+ if (status == CR_OK) {
+ continue;
+ } else {
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->error) {
+ PRIVATE (a_this)->sac_handler->
+ error
+ (PRIVATE (a_this)->
+ sac_handler);
+ }
+
+ status = cr_parser_parse_ruleset_core
+ (a_this);
+
+ if (status == CR_OK) {
+ continue;
+ } else {
+ break;
+ }
+ }
+ } else if (token && token->type == MEDIA_SYM_TK) {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token = NULL;
+
+ status = cr_parser_parse_media (a_this);
+ if (status == CR_OK) {
+ continue;
+ } else {
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->error) {
+ PRIVATE (a_this)->sac_handler->
+ error
+ (PRIVATE (a_this)->
+ sac_handler);
+ }
+
+ status = cr_parser_parse_atrule_core (a_this);
+
+ if (status == CR_OK) {
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ } else if (token && token->type == PAGE_SYM_TK) {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token = NULL;
+ status = cr_parser_parse_page (a_this);
+
+ if (status == CR_OK) {
+ continue;
+ } else {
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->error) {
+ PRIVATE (a_this)->sac_handler->
+ error
+ (PRIVATE (a_this)->
+ sac_handler);
+ }
+
+ status = cr_parser_parse_atrule_core (a_this);
+
+ if (status == CR_OK) {
+ continue;
+ } else {
+ break;
+ }
+ }
+ } else if (token && token->type == FONT_FACE_SYM_TK) {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token = NULL;
+ status = cr_parser_parse_font_face (a_this);
+
+ if (status == CR_OK) {
+ continue;
+ } else {
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->error) {
+ PRIVATE (a_this)->sac_handler->
+ error
+ (PRIVATE (a_this)->
+ sac_handler);
+ }
+
+ status = cr_parser_parse_atrule_core (a_this);
+
+ if (status == CR_OK) {
+ continue;
+ } else {
+ break;
+ }
+ }
+ } else {
+ status = cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr, token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ token = NULL;
+ status = cr_parser_parse_statement_core (a_this);
+
+ if (status == CR_OK) {
+ continue;
+ } else {
+ break;
+ }
+ }
+ }
+
+ done:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (status == CR_END_OF_INPUT_ERROR || status == CR_OK) {
+
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->end_document) {
+ PRIVATE (a_this)->sac_handler->end_document
+ (PRIVATE (a_this)->sac_handler);
+ }
+
+ return CR_OK;
+ }
+
+ cr_parser_push_error
+ (a_this, (const guchar *) "could not recognize next production", CR_ERROR);
+
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->unrecoverable_error) {
+ PRIVATE (a_this)->sac_handler->
+ unrecoverable_error (PRIVATE (a_this)->sac_handler);
+ }
+
+ cr_parser_dump_err_stack (a_this, TRUE);
+
+ return status;
+
+ error:
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->unrecoverable_error) {
+ PRIVATE (a_this)->sac_handler->
+ unrecoverable_error (PRIVATE (a_this)->sac_handler);
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/****************************************
+ *Public CRParser Methods
+ ****************************************/
+
+/**
+ * cr_parser_new:
+ * @a_tknzr: the tokenizer to use for the parsing.
+ *
+ *Creates a new parser to parse data
+ *coming the input stream given in parameter.
+ *
+ *Returns the newly created instance of #CRParser,
+ *or NULL if an error occurred.
+ */
+CRParser *
+cr_parser_new (CRTknzr * a_tknzr)
+{
+ CRParser *result = NULL;
+ enum CRStatus status = CR_OK;
+
+ result = g_malloc0 (sizeof (CRParser));
+
+ PRIVATE (result) = g_malloc0 (sizeof (CRParserPriv));
+
+ if (a_tknzr) {
+ status = cr_parser_set_tknzr (result, a_tknzr);
+ if (status != CR_OK)
+ cr_parser_destroy (result);
+ }
+
+ g_return_val_if_fail (status == CR_OK, NULL);
+
+ return result;
+}
+
+/**
+ * cr_parser_new_from_buf:
+ *@a_buf: the buffer to parse.
+ *@a_len: the length of the data in the buffer.
+ *@a_enc: the encoding of the input buffer a_buf.
+ *@a_free_buf: if set to TRUE, a_buf will be freed
+ *during the destruction of the newly built instance
+ *of #CRParser. If set to FALSE, it is up to the caller to
+ *eventually free it.
+ *
+ *Instantiates a new parser from a memory buffer.
+ *
+ *Returns the newly built parser, or NULL if an error arises.
+ */
+CRParser *
+cr_parser_new_from_buf (guchar * a_buf,
+ gulong a_len,
+ enum CREncoding a_enc,
+ gboolean a_free_buf)
+{
+ CRParser *result = NULL;
+ CRInput *input = NULL;
+
+ g_return_val_if_fail (a_buf, NULL);
+
+ input = cr_input_new_from_buf (a_buf, a_len, a_enc, a_free_buf);
+ g_return_val_if_fail (input, NULL);
+
+ result = cr_parser_new_from_input (input);
+ if (!result) {
+ cr_input_destroy (input);
+ input = NULL;
+ return NULL;
+ }
+ return result;
+}
+
+/**
+ * cr_parser_new_from_input:
+ * @a_input: the parser input stream to use.
+ *
+ * Returns a newly built parser input.
+ */
+CRParser *
+cr_parser_new_from_input (CRInput * a_input)
+{
+ CRParser *result = NULL;
+ CRTknzr *tokenizer = NULL;
+
+ if (a_input) {
+ tokenizer = cr_tknzr_new (a_input);
+ g_return_val_if_fail (tokenizer, NULL);
+ }
+
+ result = cr_parser_new (tokenizer);
+ if (!result)
+ g_clear_pointer (&tokenizer, cr_tknzr_unref);
+ g_return_val_if_fail (result, NULL);
+
+ return result;
+}
+
+/**
+ * cr_parser_new_from_file:
+ * @a_file_uri: the uri of the file to parse.
+ * @a_enc: the file encoding to use.
+ *
+ * Returns the newly built parser.
+ */
+CRParser *
+cr_parser_new_from_file (const guchar * a_file_uri, enum CREncoding a_enc)
+{
+ CRParser *result = NULL;
+ CRTknzr *tokenizer = NULL;
+
+ tokenizer = cr_tknzr_new_from_uri (a_file_uri, a_enc);
+ if (!tokenizer) {
+ cr_utils_trace_info ("Could not open input file");
+ return NULL;
+ }
+
+ result = cr_parser_new (tokenizer);
+ if (!result)
+ g_clear_pointer (&tokenizer, cr_tknzr_unref);
+ g_return_val_if_fail (result, NULL);
+ return result;
+}
+
+/**
+ * cr_parser_set_sac_handler:
+ *@a_this: the "this pointer" of the current instance of #CRParser.
+ *@a_handler: the handler to set.
+ *
+ *Sets a SAC document handler to the parser.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_set_sac_handler (CRParser * a_this, CRDocHandler * a_handler)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->sac_handler) {
+ cr_doc_handler_unref (PRIVATE (a_this)->sac_handler);
+ }
+
+ PRIVATE (a_this)->sac_handler = a_handler;
+ cr_doc_handler_ref (a_handler);
+
+ return CR_OK;
+}
+
+/**
+ * cr_parser_get_sac_handler:
+ *@a_this: the "this pointer" of the current instance of
+ *#CRParser.
+ *@a_handler: out parameter. The returned handler.
+ *
+ *Gets the SAC document handler.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_parser_get_sac_handler (CRParser * a_this, CRDocHandler ** a_handler)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ *a_handler = PRIVATE (a_this)->sac_handler;
+
+ return CR_OK;
+}
+
+/**
+ * cr_parser_set_default_sac_handler:
+ *@a_this: a pointer to the current instance of #CRParser.
+ *
+ *Sets the SAC handler associated to the current instance
+ *of #CRParser to the default SAC handler.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_set_default_sac_handler (CRParser * a_this)
+{
+ CRDocHandler *default_sac_handler = NULL;
+ enum CRStatus status = CR_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ default_sac_handler = cr_doc_handler_new ();
+
+ cr_doc_handler_set_default_sac_handler (default_sac_handler);
+
+ status = cr_parser_set_sac_handler (a_this, default_sac_handler);
+
+ if (status != CR_OK) {
+ cr_doc_handler_destroy (default_sac_handler);
+ default_sac_handler = NULL;
+ }
+
+ return status;
+}
+
+/**
+ * cr_parser_set_use_core_grammar:
+ * @a_this: the current instance of #CRParser.
+ * @a_use_core_grammar: where to parse against the css core grammar.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_set_use_core_grammar (CRParser * a_this,
+ gboolean a_use_core_grammar)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->use_core_grammar = a_use_core_grammar;
+
+ return CR_OK;
+}
+
+/**
+ * cr_parser_get_use_core_grammar:
+ * @a_this: the current instance of #CRParser.
+ * @a_use_core_grammar: whether to use the core grammar or not.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_get_use_core_grammar (CRParser const * a_this,
+ gboolean * a_use_core_grammar)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ *a_use_core_grammar = PRIVATE (a_this)->use_core_grammar;
+
+ return CR_OK;
+}
+
+/**
+ * cr_parser_parse_file:
+ *@a_this: a pointer to the current instance of #CRParser.
+ *@a_file_uri: the uri to the file to load. For the time being,
+ *@a_enc: the encoding of the file to parse.
+ *only local files are supported.
+ *
+ *Parses a the given in parameter.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_file (CRParser * a_this,
+ const guchar * a_file_uri, enum CREncoding a_enc)
+{
+ enum CRStatus status = CR_ERROR;
+ CRTknzr *tknzr = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_file_uri, CR_BAD_PARAM_ERROR);
+
+ tknzr = cr_tknzr_new_from_uri (a_file_uri, a_enc);
+
+ g_return_val_if_fail (tknzr != NULL, CR_ERROR);
+
+ status = cr_parser_set_tknzr (a_this, tknzr);
+ if (status != CR_OK)
+ g_clear_pointer (&tknzr, cr_tknzr_unref);
+ g_return_val_if_fail (status == CR_OK, CR_ERROR);
+
+ status = cr_parser_parse (a_this);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_expr:
+ * @a_this: the current instance of #CRParser.
+ * @a_expr: out parameter. the parsed expression.
+ *
+ *Parses an expression as defined by the css2 spec in appendix
+ *D.1:
+ *expr: term [ operator term ]*
+ *
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_expr (CRParser * a_this, CRTerm ** a_expr)
+{
+ enum CRStatus status = CR_ERROR;
+ CRInputPos init_pos;
+ CRTerm *expr = NULL,
+ *expr2 = NULL;
+ guchar next_byte = 0;
+ gulong nb_terms = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_expr, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_parser_parse_term (a_this, &expr);
+
+ CHECK_PARSING_STATUS (status, FALSE);
+
+ for (;;) {
+ guchar operatr = 0;
+
+ status = cr_tknzr_peek_byte (PRIVATE (a_this)->tknzr,
+ 1, &next_byte);
+ if (status != CR_OK) {
+ if (status == CR_END_OF_INPUT_ERROR) {
+ /*
+ if (!nb_terms)
+ {
+ goto error ;
+ }
+ */
+ status = CR_OK;
+ break;
+ } else {
+ goto error;
+ }
+ }
+
+ if (next_byte == '/' || next_byte == ',') {
+ READ_NEXT_BYTE (a_this, &operatr);
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_parser_parse_term (a_this, &expr2);
+
+ if (status != CR_OK || expr2 == NULL) {
+ status = CR_OK;
+ break;
+ }
+
+ switch (operatr) {
+ case '/':
+ expr2->the_operator = DIVIDE;
+ break;
+ case ',':
+ expr2->the_operator = COMMA;
+
+ default:
+ break;
+ }
+
+ expr = cr_term_append_term (expr, expr2);
+ expr2 = NULL;
+ operatr = 0;
+ nb_terms++;
+ }
+
+ if (status == CR_OK) {
+ *a_expr = cr_term_append_term (*a_expr, expr);
+ expr = NULL;
+
+ cr_parser_clear_errors (a_this);
+ return CR_OK;
+ }
+
+ error:
+
+ if (expr) {
+ cr_term_destroy (expr);
+ expr = NULL;
+ }
+
+ if (expr2) {
+ cr_term_destroy (expr2);
+ expr2 = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_prio:
+ *@a_this: the current instance of #CRParser.
+ *@a_prio: a string representing the priority.
+ *Today, only "!important" is returned as only this
+ *priority is defined by css2.
+ *
+ *Parses a declaration priority as defined by
+ *the css2 grammar in appendix C:
+ *prio: IMPORTANT_SYM S*
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_prio (CRParser * a_this, CRString ** a_prio)
+{
+ enum CRStatus status = CR_ERROR;
+ CRInputPos init_pos;
+ CRToken *token = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_prio
+ && *a_prio == NULL, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ if (status == CR_END_OF_INPUT_ERROR) {
+ goto error;
+ }
+ ENSURE_PARSING_COND (status == CR_OK
+ && token && token->type == IMPORTANT_SYM_TK);
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ *a_prio = cr_string_new_from_string ("!important");
+ cr_token_destroy (token);
+ token = NULL;
+ return CR_OK;
+
+ error:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_declaration:
+ *@a_this: the "this pointer" of the current instance of #CRParser.
+ *@a_property: the successfully parsed property. The caller
+ * *must* free the returned pointer.
+ *@a_expr: the expression that represents the attribute value.
+ *The caller *must* free the returned pointer.
+ *
+ *TODO: return the parsed priority, so that
+ *upper layers can take benefit from it.
+ *Parses a "declaration" as defined by the css2 spec in appendix D.1:
+ *declaration ::= [property ':' S* expr prio?]?
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_declaration (CRParser * a_this,
+ CRString ** a_property,
+ CRTerm ** a_expr, gboolean * a_important)
+{
+ enum CRStatus status = CR_ERROR;
+ CRInputPos init_pos;
+ guint32 cur_char = 0;
+ CRTerm *expr = NULL;
+ CRString *prio = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_property && a_expr
+ && a_important, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_parser_parse_property (a_this, a_property);
+
+ if (status == CR_END_OF_INPUT_ERROR)
+ goto error;
+
+ CHECK_PARSING_STATUS_ERR
+ (a_this, status, FALSE,
+ (const guchar *) "while parsing declaration: next property is malformed",
+ CR_SYNTAX_ERROR);
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ if (cur_char != ':') {
+ status = CR_PARSING_ERROR;
+ cr_parser_push_error
+ (a_this,
+ (const guchar *) "while parsing declaration: this char must be ':'",
+ CR_SYNTAX_ERROR);
+ goto error;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_parser_parse_expr (a_this, &expr);
+
+ CHECK_PARSING_STATUS_ERR
+ (a_this, status, FALSE,
+ (const guchar *) "while parsing declaration: next expression is malformed",
+ CR_SYNTAX_ERROR);
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ status = cr_parser_parse_prio (a_this, &prio);
+ if (prio) {
+ cr_string_destroy (prio);
+ prio = NULL;
+ *a_important = TRUE;
+ } else {
+ *a_important = FALSE;
+ }
+ if (*a_expr) {
+ cr_term_append_term (*a_expr, expr);
+ expr = NULL;
+ } else {
+ *a_expr = expr;
+ expr = NULL;
+ }
+
+ cr_parser_clear_errors (a_this);
+ return CR_OK;
+
+ error:
+
+ if (expr) {
+ cr_term_destroy (expr);
+ expr = NULL;
+ }
+
+ if (*a_property) {
+ cr_string_destroy (*a_property);
+ *a_property = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_statement_core:
+ *@a_this: the current instance of #CRParser.
+ *
+ *Parses a statement as defined by the css core grammar in
+ *chapter 4.1 of the css2 spec.
+ *statement : ruleset | at-rule;
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_statement_core (CRParser * a_this)
+{
+ CRToken *token = NULL;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+
+ ENSURE_PARSING_COND (status == CR_OK && token);
+
+ switch (token->type) {
+ case ATKEYWORD_TK:
+ case IMPORT_SYM_TK:
+ case PAGE_SYM_TK:
+ case MEDIA_SYM_TK:
+ case FONT_FACE_SYM_TK:
+ case CHARSET_SYM_TK:
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ status = cr_parser_parse_atrule_core (a_this);
+ CHECK_PARSING_STATUS (status, TRUE);
+ break;
+
+ default:
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ status = cr_parser_parse_ruleset_core (a_this);
+ cr_parser_clear_errors (a_this);
+ CHECK_PARSING_STATUS (status, TRUE);
+ }
+
+ return CR_OK;
+
+ error:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_ruleset:
+ *@a_this: the "this pointer" of the current instance of #CRParser.
+ *
+ *Parses a "ruleset" as defined in the css2 spec at appendix D.1.
+ *ruleset ::= selector [ ',' S* selector ]*
+ *'{' S* declaration? [ ';' S* declaration? ]* '}' S*;
+ *
+ *This methods calls the SAC handler on the relevant SAC handler
+ *callbacks whenever it encounters some specific constructions.
+ *See the documentation of #CRDocHandler (the SAC handler) to know
+ *when which SAC handler is called.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_ruleset (CRParser * a_this)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+ guint32 cur_char = 0,
+ next_char = 0;
+ CRString *property = NULL;
+ CRTerm *expr = NULL;
+ CRSimpleSel *simple_sels = NULL;
+ CRSelector *selector = NULL;
+ gboolean start_selector = FALSE,
+ is_important = FALSE;
+ CRParsingLocation end_parsing_location;
+
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_parser_parse_selector (a_this, &selector);
+ CHECK_PARSING_STATUS (status, FALSE);
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ ENSURE_PARSING_COND_ERR
+ (a_this, cur_char == '{',
+ (const guchar *) "while parsing rulset: current char should be '{'",
+ CR_SYNTAX_ERROR);
+
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->start_selector) {
+ /*
+ *the selector is ref counted so that the parser's user
+ *can choose to keep it.
+ */
+ if (selector) {
+ cr_selector_ref (selector);
+ }
+
+ PRIVATE (a_this)->sac_handler->start_selector
+ (PRIVATE (a_this)->sac_handler, selector);
+ start_selector = TRUE;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ PRIVATE (a_this)->state = TRY_PARSE_RULESET_STATE;
+
+ status = cr_parser_parse_declaration (a_this, &property,
+ &expr,
+ &is_important);
+ if (expr) {
+ cr_term_ref (expr);
+ }
+ if (status == CR_OK
+ && PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->property) {
+ PRIVATE (a_this)->sac_handler->property
+ (PRIVATE (a_this)->sac_handler, property, expr,
+ is_important);
+ }
+ if (status == CR_OK) {
+ /*
+ *free the allocated
+ *'property' and 'term' before parsing
+ *next declarations.
+ */
+ if (property) {
+ cr_string_destroy (property);
+ property = NULL;
+ }
+ if (expr) {
+ cr_term_unref (expr);
+ expr = NULL;
+ }
+ } else {/*status != CR_OK*/
+ guint32 c = 0 ;
+ /*
+ *test if we have reached '}', which
+ *would mean that we are parsing an empty ruleset (eg. x{ })
+ *In that case, goto end_of_ruleset.
+ */
+ status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr, &c) ;
+ if (status == CR_OK && c == '}') {
+ status = CR_OK ;
+ goto end_of_ruleset ;
+ }
+ }
+ CHECK_PARSING_STATUS_ERR
+ (a_this, status, FALSE,
+ (const guchar *) "while parsing ruleset: next construction should be a declaration",
+ CR_SYNTAX_ERROR);
+
+ for (;;) {
+ PEEK_NEXT_CHAR (a_this, &next_char);
+ if (next_char != ';')
+ break;
+
+ /*consume the ';' char */
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_parser_parse_declaration (a_this, &property,
+ &expr, &is_important);
+
+ if (expr) {
+ cr_term_ref (expr);
+ }
+ if (status == CR_OK
+ && PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->property) {
+ PRIVATE (a_this)->sac_handler->property
+ (PRIVATE (a_this)->sac_handler,
+ property, expr, is_important);
+ }
+ if (property) {
+ cr_string_destroy (property);
+ property = NULL;
+ }
+ if (expr) {
+ cr_term_unref (expr);
+ expr = NULL;
+ }
+ }
+
+ end_of_ruleset:
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ cr_parser_get_parsing_location (a_this, &end_parsing_location);
+ READ_NEXT_CHAR (a_this, &cur_char);
+ ENSURE_PARSING_COND_ERR
+ (a_this, cur_char == '}',
+ (const guchar *) "while parsing rulset: current char must be a '}'",
+ CR_SYNTAX_ERROR);
+
+ selector->location = end_parsing_location;
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->end_selector) {
+ PRIVATE (a_this)->sac_handler->end_selector
+ (PRIVATE (a_this)->sac_handler, selector);
+ start_selector = FALSE;
+ }
+
+ if (expr) {
+ cr_term_unref (expr);
+ expr = NULL;
+ }
+
+ if (simple_sels) {
+ cr_simple_sel_destroy (simple_sels);
+ simple_sels = NULL;
+ }
+
+ if (selector) {
+ cr_selector_unref (selector);
+ selector = NULL;
+ }
+
+ cr_parser_clear_errors (a_this);
+ PRIVATE (a_this)->state = RULESET_PARSED_STATE;
+
+ return CR_OK;
+
+ error:
+ if (start_selector == TRUE
+ && PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->error) {
+ PRIVATE (a_this)->sac_handler->error
+ (PRIVATE (a_this)->sac_handler);
+ }
+ if (expr) {
+ cr_term_unref (expr);
+ expr = NULL;
+ }
+ if (simple_sels) {
+ cr_simple_sel_destroy (simple_sels);
+ simple_sels = NULL;
+ }
+ if (property) {
+ cr_string_destroy (property);
+ }
+ if (selector) {
+ cr_selector_unref (selector);
+ selector = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_import:
+ *@a_this: the "this pointer" of the current instance
+ *of #CRParser.
+ *@a_media_list: out parameter. A linked list of
+ *#CRString
+ *Each CRString is a string that contains
+ *a 'medium' declaration part of the successfully
+ *parsed 'import' declaration.
+ *@a_import_string: out parameter.
+ *A string that contains the 'import
+ *string". The import string can be either an uri (if it starts with
+ *the substring "uri(") or a any other css2 string. Note that
+ * *a_import_string must be initially set to NULL or else, this function
+ *will return CR_BAD_PARAM_ERROR.
+ *@a_location: the location (line, column) where the import has been parsed
+ *
+ *Parses an 'import' declaration as defined in the css2 spec
+ *in appendix D.1:
+ *
+ *import ::=
+ *\@import [STRING|URI] S* [ medium [ ',' S* medium]* ]? ';' S*
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_import (CRParser * a_this,
+ GList ** a_media_list,
+ CRString ** a_import_string,
+ CRParsingLocation *a_location)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+ guint32 cur_char = 0,
+ next_char = 0;
+ CRString *medium = NULL;
+
+ g_return_val_if_fail (a_this
+ && a_import_string
+ && (*a_import_string == NULL),
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ if (BYTE (a_this, 1, NULL) == '@'
+ && BYTE (a_this, 2, NULL) == 'i'
+ && BYTE (a_this, 3, NULL) == 'm'
+ && BYTE (a_this, 4, NULL) == 'p'
+ && BYTE (a_this, 5, NULL) == 'o'
+ && BYTE (a_this, 6, NULL) == 'r'
+ && BYTE (a_this, 7, NULL) == 't') {
+ SKIP_CHARS (a_this, 1);
+ if (a_location) {
+ cr_parser_get_parsing_location
+ (a_this, a_location) ;
+ }
+ SKIP_CHARS (a_this, 6);
+ status = CR_OK;
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ PRIVATE (a_this)->state = TRY_PARSE_IMPORT_STATE;
+
+ PEEK_NEXT_CHAR (a_this, &next_char);
+
+ if (next_char == '"' || next_char == '\'') {
+ status = cr_parser_parse_string (a_this, a_import_string);
+
+ CHECK_PARSING_STATUS (status, FALSE);
+ } else {
+ status = cr_parser_parse_uri (a_this, a_import_string);
+
+ CHECK_PARSING_STATUS (status, FALSE);
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_parser_parse_ident (a_this, &medium);
+
+ if (status == CR_OK && medium) {
+ *a_media_list = g_list_append (*a_media_list, medium);
+ medium = NULL;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ for (; status == CR_OK;) {
+ if ((status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr,
+ &next_char)) != CR_OK) {
+ if (status == CR_END_OF_INPUT_ERROR) {
+ status = CR_OK;
+ goto okay;
+ }
+ goto error;
+ }
+
+ if (next_char == ',') {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ } else {
+ break;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_parser_parse_ident (a_this, &medium);
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ if ((status == CR_OK) && medium) {
+ *a_media_list = g_list_append (*a_media_list, medium);
+
+ medium = NULL;
+ }
+
+ CHECK_PARSING_STATUS (status, FALSE);
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ }
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ READ_NEXT_CHAR (a_this, &cur_char);
+ ENSURE_PARSING_COND (cur_char == ';');
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ okay:
+ cr_parser_clear_errors (a_this);
+ PRIVATE (a_this)->state = IMPORT_PARSED_STATE;
+
+ return CR_OK;
+
+ error:
+
+ if (*a_media_list) {
+ GList *cur = NULL;
+
+ /*
+ *free each element of *a_media_list.
+ *Note that each element of *a_medium list *must*
+ *be a GString* or else, the code that is coming next
+ *will corrupt the memory and lead to hard to debug
+ *random crashes.
+ *This is where C++ and its compile time
+ *type checking mechanism (through STL containers) would
+ *have prevented us to go through this hassle.
+ */
+ for (cur = *a_media_list; cur; cur = cur->next) {
+ if (cur->data) {
+ cr_string_destroy (cur->data);
+ }
+ }
+
+ g_list_free (*a_media_list);
+ *a_media_list = NULL;
+ }
+
+ if (*a_import_string) {
+ cr_string_destroy (*a_import_string);
+ *a_import_string = NULL;
+ }
+
+ if (medium) {
+ cr_string_destroy (medium);
+ medium = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_media:
+ *@a_this: the "this pointer" of the current instance of #CRParser.
+ *
+ *Parses a 'media' declaration as specified in the css2 spec at
+ *appendix D.1:
+ *
+ *media ::= \@media S* medium [ ',' S* medium ]* '{' S* ruleset* '}' S*
+ *
+ *Note that this function calls the required sac handlers during the parsing
+ *to notify media productions. See #CRDocHandler to know the callback called
+ *during \@media parsing.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_media (CRParser * a_this)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+ CRToken *token = NULL;
+ guint32 next_char = 0,
+ cur_char = 0;
+ CRString *medium = NULL;
+ GList *media_list = NULL;
+ CRParsingLocation location = {0,0,0} ;
+
+ g_return_val_if_fail (a_this
+ && PRIVATE (a_this),
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token
+ && token->type == MEDIA_SYM_TK);
+ cr_parsing_location_copy (&location, &token->location) ;
+ cr_token_destroy (token);
+ token = NULL;
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token && token->type == IDENT_TK);
+
+ medium = token->u.str;
+ token->u.str = NULL;
+ cr_token_destroy (token);
+ token = NULL;
+
+ if (medium) {
+ media_list = g_list_append (media_list, medium);
+ medium = NULL;
+ }
+
+ for (; status == CR_OK;) {
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ PEEK_NEXT_CHAR (a_this, &next_char);
+
+ if (next_char == ',') {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ } else {
+ break;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_parser_parse_ident (a_this, &medium);
+
+ CHECK_PARSING_STATUS (status, FALSE);
+
+ if (medium) {
+ media_list = g_list_append (media_list, medium);
+ medium = NULL;
+ }
+ }
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ ENSURE_PARSING_COND (cur_char == '{');
+
+ /*
+ *call the SAC handler api here.
+ */
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->start_media) {
+ PRIVATE (a_this)->sac_handler->start_media
+ (PRIVATE (a_this)->sac_handler, media_list,
+ &location);
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ PRIVATE (a_this)->state = TRY_PARSE_MEDIA_STATE;
+
+ for (; status == CR_OK;) {
+ status = cr_parser_parse_ruleset (a_this);
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ }
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ ENSURE_PARSING_COND (cur_char == '}');
+
+ /*
+ *call the right SAC handler api here.
+ */
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->end_media) {
+ PRIVATE (a_this)->sac_handler->end_media
+ (PRIVATE (a_this)->sac_handler, media_list);
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ /*
+ *Then, free the data structures passed to
+ *the last call to the SAC handler.
+ */
+ if (medium) {
+ cr_string_destroy (medium);
+ medium = NULL;
+ }
+
+ if (media_list) {
+ GList *cur = NULL;
+
+ for (cur = media_list; cur; cur = cur->next) {
+ cr_string_destroy (cur->data);
+ }
+
+ g_list_free (media_list);
+ media_list = NULL;
+ }
+
+ cr_parser_clear_errors (a_this);
+ PRIVATE (a_this)->state = MEDIA_PARSED_STATE;
+
+ return CR_OK;
+
+ error:
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (medium) {
+ cr_string_destroy (medium);
+ medium = NULL;
+ }
+
+ if (media_list) {
+ GList *cur = NULL;
+
+ for (cur = media_list; cur; cur = cur->next) {
+ cr_string_destroy (cur->data);
+ }
+
+ g_list_free (media_list);
+ media_list = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_page:
+ *@a_this: the "this pointer" of the current instance of #CRParser.
+ *
+ *Parses '\@page' rule as specified in the css2 spec in appendix D.1:
+ *page ::= PAGE_SYM S* IDENT? pseudo_page? S*
+ *'{' S* declaration [ ';' S* declaration ]* '}' S*
+ *
+ *This function also calls the relevant SAC handlers whenever it
+ *encounters a construction that must
+ *be reported to the calling application.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_page (CRParser * a_this)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+ CRToken *token = NULL;
+ CRTerm *css_expression = NULL;
+ CRString *page_selector = NULL,
+ *page_pseudo_class = NULL,
+ *property = NULL;
+ gboolean important = TRUE;
+ CRParsingLocation location = {0,0,0} ;
+
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token) ;
+ ENSURE_PARSING_COND (status == CR_OK
+ && token
+ && token->type == PAGE_SYM_TK);
+
+ cr_parsing_location_copy (&location, &token->location) ;
+ cr_token_destroy (token);
+ token = NULL;
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token);
+
+ if (token->type == IDENT_TK) {
+ page_selector = token->u.str;
+ token->u.str = NULL;
+ cr_token_destroy (token);
+ token = NULL;
+ } else {
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ }
+
+ /*
+ *try to parse pseudo_page
+ */
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK && token);
+
+ if (token->type == DELIM_TK && token->u.unichar == ':') {
+ cr_token_destroy (token);
+ token = NULL;
+ status = cr_parser_parse_ident (a_this, &page_pseudo_class);
+ CHECK_PARSING_STATUS (status, FALSE);
+ } else {
+ cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
+ token = NULL;
+ }
+
+ /*
+ *parse_block
+ *
+ */
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+
+ ENSURE_PARSING_COND (status == CR_OK && token
+ && token->type == CBO_TK);
+
+ cr_token_destroy (token);
+ token = NULL;
+
+ /*
+ *Call the appropriate SAC handler here.
+ */
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->start_page) {
+ PRIVATE (a_this)->sac_handler->start_page
+ (PRIVATE (a_this)->sac_handler,
+ page_selector, page_pseudo_class,
+ &location);
+ }
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ PRIVATE (a_this)->state = TRY_PARSE_PAGE_STATE;
+
+ status = cr_parser_parse_declaration (a_this, &property,
+ &css_expression,
+ &important);
+ ENSURE_PARSING_COND (status == CR_OK);
+
+ /*
+ *call the relevant SAC handler here...
+ */
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->property) {
+ if (css_expression)
+ cr_term_ref (css_expression);
+
+ PRIVATE (a_this)->sac_handler->property
+ (PRIVATE (a_this)->sac_handler,
+ property, css_expression, important);
+ }
+ /*
+ *... and free the data structure passed to that last
+ *SAC handler.
+ */
+ if (property) {
+ cr_string_destroy (property);
+ property = NULL;
+ }
+ if (css_expression) {
+ cr_term_unref (css_expression);
+ css_expression = NULL;
+ }
+
+ for (;;) {
+ /*parse the other ';' separated declarations */
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+ status = cr_tknzr_get_next_token
+ (PRIVATE (a_this)->tknzr, &token);
+
+ ENSURE_PARSING_COND (status == CR_OK && token);
+
+ if (token->type != SEMICOLON_TK) {
+ cr_tknzr_unget_token
+ (PRIVATE (a_this)->tknzr,
+ token);
+ token = NULL ;
+ break;
+ }
+
+ cr_token_destroy (token);
+ token = NULL;
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_parser_parse_declaration (a_this, &property,
+ &css_expression,
+ &important);
+ if (status != CR_OK)
+ break ;
+
+ /*
+ *call the relevant SAC handler here...
+ */
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->property) {
+ cr_term_ref (css_expression);
+ PRIVATE (a_this)->sac_handler->property
+ (PRIVATE (a_this)->sac_handler,
+ property, css_expression, important);
+ }
+ /*
+ *... and free the data structure passed to that last
+ *SAC handler.
+ */
+ if (property) {
+ cr_string_destroy (property);
+ property = NULL;
+ }
+ if (css_expression) {
+ cr_term_unref (css_expression);
+ css_expression = NULL;
+ }
+ }
+ cr_parser_try_to_skip_spaces_and_comments
+ (a_this) ;
+ if (token) {
+ cr_token_destroy (token) ;
+ token = NULL ;
+ }
+
+ status = cr_tknzr_get_next_token
+ (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token
+ && token->type == CBC_TK) ;
+ cr_token_destroy (token) ;
+ token = NULL ;
+ /*
+ *call the relevant SAC handler here.
+ */
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->end_page) {
+ PRIVATE (a_this)->sac_handler->end_page
+ (PRIVATE (a_this)->sac_handler,
+ page_selector, page_pseudo_class);
+ }
+
+ if (page_selector) {
+ cr_string_destroy (page_selector);
+ page_selector = NULL;
+ }
+
+ if (page_pseudo_class) {
+ cr_string_destroy (page_pseudo_class);
+ page_pseudo_class = NULL;
+ }
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ /*here goes the former implem of this function ... */
+
+ cr_parser_clear_errors (a_this);
+ PRIVATE (a_this)->state = PAGE_PARSED_STATE;
+
+ return CR_OK;
+
+ error:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+ if (page_selector) {
+ cr_string_destroy (page_selector);
+ page_selector = NULL;
+ }
+ if (page_pseudo_class) {
+ cr_string_destroy (page_pseudo_class);
+ page_pseudo_class = NULL;
+ }
+ if (property) {
+ cr_string_destroy (property);
+ property = NULL;
+ }
+ if (css_expression) {
+ cr_term_destroy (css_expression);
+ css_expression = NULL;
+ }
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+ return status;
+}
+
+/**
+ * cr_parser_parse_charset:
+ *@a_this: the "this pointer" of the current instance of #CRParser.
+ *@a_value: out parameter. The actual parsed value of the charset
+ *declararation. Note that for safety check reasons, *a_value must be
+ *set to NULL.
+ *@a_charset_sym_location: the parsing location of the charset rule
+ *
+ *Parses a charset declaration as defined implicitly by the css2 spec in
+ *appendix D.1:
+ *charset ::= CHARSET_SYM S* STRING S* ';'
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_charset (CRParser * a_this, CRString ** a_value,
+ CRParsingLocation *a_charset_sym_location)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+ CRToken *token = NULL;
+ CRString *charset_str = NULL;
+
+ g_return_val_if_fail (a_this && a_value
+ && (*a_value == NULL),
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+
+ ENSURE_PARSING_COND (status == CR_OK
+ && token && token->type == CHARSET_SYM_TK);
+ if (a_charset_sym_location) {
+ cr_parsing_location_copy (a_charset_sym_location,
+ &token->location) ;
+ }
+ cr_token_destroy (token);
+ token = NULL;
+
+ PRIVATE (a_this)->state = TRY_PARSE_CHARSET_STATE;
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token && token->type == STRING_TK);
+ charset_str = token->u.str;
+ token->u.str = NULL;
+ cr_token_destroy (token);
+ token = NULL;
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+
+ ENSURE_PARSING_COND (status == CR_OK
+ && token && token->type == SEMICOLON_TK);
+ cr_token_destroy (token);
+ token = NULL;
+
+ if (charset_str) {
+ *a_value = charset_str;
+ charset_str = NULL;
+ }
+
+ PRIVATE (a_this)->state = CHARSET_PARSED_STATE;
+ return CR_OK;
+
+ error:
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (*a_value) {
+ cr_string_destroy (*a_value);
+ *a_value = NULL;
+ }
+
+ if (charset_str) {
+ cr_string_destroy (charset_str);
+ charset_str = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+
+ return status;
+}
+
+/**
+ * cr_parser_parse_font_face:
+ *@a_this: the current instance of #CRParser.
+ *
+ *Parses the "\@font-face" rule specified in the css1 spec in
+ *appendix D.1:
+ *
+ *font_face ::= FONT_FACE_SYM S*
+ *'{' S* declaration [ ';' S* declaration ]* '}' S*
+ *
+ *This function will call SAC handlers whenever it is necessary.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_font_face (CRParser * a_this)
+{
+ enum CRStatus status = CR_ERROR;
+ CRInputPos init_pos;
+ CRString *property = NULL;
+ CRTerm *css_expression = NULL;
+ CRToken *token = NULL;
+ gboolean important = FALSE;
+ guint32 next_char = 0,
+ cur_char = 0;
+ CRParsingLocation location = {0,0,0} ;
+
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+ ENSURE_PARSING_COND (status == CR_OK
+ && token
+ && token->type == FONT_FACE_SYM_TK);
+
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ if (token) {
+ cr_parsing_location_copy (&location,
+ &token->location) ;
+ cr_token_destroy (token);
+ token = NULL;
+ }
+ status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+ &token);
+ ENSURE_PARSING_COND (status == CR_OK && token
+ && token->type == CBO_TK);
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+ /*
+ *here, call the relevant SAC handler.
+ */
+ if (PRIVATE (a_this)->sac_handler
+ && PRIVATE (a_this)->sac_handler->start_font_face) {
+ PRIVATE (a_this)->sac_handler->start_font_face
+ (PRIVATE (a_this)->sac_handler, &location);
+ }
+ PRIVATE (a_this)->state = TRY_PARSE_FONT_FACE_STATE;
+ /*
+ *and resume the parsing.
+ */
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ status = cr_parser_parse_declaration (a_this, &property,
+ &css_expression, &important);
+ if (status == CR_OK) {
+ /*
+ *here, call the relevant SAC handler.
+ */
+ cr_term_ref (css_expression);
+ if (PRIVATE (a_this)->sac_handler &&
+ PRIVATE (a_this)->sac_handler->property) {
+ PRIVATE (a_this)->sac_handler->property
+ (PRIVATE (a_this)->sac_handler,
+ property, css_expression, important);
+ }
+ ENSURE_PARSING_COND (css_expression && property);
+ }
+ /*free the data structures allocated during last parsing. */
+ if (property) {
+ cr_string_destroy (property);
+ property = NULL;
+ }
+ if (css_expression) {
+ cr_term_unref (css_expression);
+ css_expression = NULL;
+ }
+ for (;;) {
+ PEEK_NEXT_CHAR (a_this, &next_char);
+ if (next_char == ';') {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ } else {
+ break;
+ }
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ status = cr_parser_parse_declaration (a_this,
+ &property,
+ &css_expression,
+ &important);
+ if (status != CR_OK)
+ break;
+ /*
+ *here, call the relevant SAC handler.
+ */
+ cr_term_ref (css_expression);
+ if (PRIVATE (a_this)->sac_handler->property) {
+ PRIVATE (a_this)->sac_handler->property
+ (PRIVATE (a_this)->sac_handler,
+ property, css_expression, important);
+ }
+ /*
+ *Then, free the data structures allocated during
+ *last parsing.
+ */
+ if (property) {
+ cr_string_destroy (property);
+ property = NULL;
+ }
+ if (css_expression) {
+ cr_term_unref (css_expression);
+ css_expression = NULL;
+ }
+ }
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+ READ_NEXT_CHAR (a_this, &cur_char);
+ ENSURE_PARSING_COND (cur_char == '}');
+ /*
+ *here, call the relevant SAC handler.
+ */
+ if (PRIVATE (a_this)->sac_handler->end_font_face) {
+ PRIVATE (a_this)->sac_handler->end_font_face
+ (PRIVATE (a_this)->sac_handler);
+ }
+ cr_parser_try_to_skip_spaces_and_comments (a_this);
+
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+ cr_parser_clear_errors (a_this);
+ PRIVATE (a_this)->state = FONT_FACE_PARSED_STATE;
+ return CR_OK;
+
+ error:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+ if (property) {
+ cr_string_destroy (property);
+ property = NULL;
+ }
+ if (css_expression) {
+ cr_term_destroy (css_expression);
+ css_expression = NULL;
+ }
+ cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
+ return status;
+}
+
+/**
+ * cr_parser_parse:
+ *@a_this: the current instance of #CRParser.
+ *
+ *Parses the data that comes from the
+ *input previously associated to the current instance of
+ *#CRParser.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse (CRParser * a_this)
+{
+ enum CRStatus status = CR_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->use_core_grammar == FALSE) {
+ status = cr_parser_parse_stylesheet (a_this);
+ } else {
+ status = cr_parser_parse_stylesheet_core (a_this);
+ }
+
+ return status;
+}
+
+/**
+ * cr_parser_set_tknzr:
+ * @a_this: the current instance of #CRParser;
+ * @a_tknzr: the new tokenizer.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_set_tknzr (CRParser * a_this, CRTknzr * a_tknzr)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->tknzr) {
+ cr_tknzr_unref (PRIVATE (a_this)->tknzr);
+ }
+
+ PRIVATE (a_this)->tknzr = a_tknzr;
+
+ if (a_tknzr)
+ cr_tknzr_ref (a_tknzr);
+
+ return CR_OK;
+}
+
+/**
+ * cr_parser_get_tknzr:
+ *@a_this: the current instance of #CRParser
+ *@a_tknzr: out parameter. The returned tokenizer
+ *
+ *Getter of the parser's underlying tokenizer
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise
+ */
+enum CRStatus
+cr_parser_get_tknzr (CRParser * a_this, CRTknzr ** a_tknzr)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_tknzr, CR_BAD_PARAM_ERROR);
+
+ *a_tknzr = PRIVATE (a_this)->tknzr;
+ return CR_OK;
+}
+
+/**
+ * cr_parser_get_parsing_location:
+ *@a_this: the current instance of #CRParser
+ *@a_loc: the parsing location to get.
+ *
+ *Gets the current parsing location.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_parser_get_parsing_location (CRParser const *a_this,
+ CRParsingLocation *a_loc)
+{
+ g_return_val_if_fail (a_this
+ && PRIVATE (a_this)
+ && a_loc, CR_BAD_PARAM_ERROR) ;
+
+ return cr_tknzr_get_parsing_location
+ (PRIVATE (a_this)->tknzr, a_loc) ;
+}
+
+/**
+ * cr_parser_parse_buf:
+ *@a_this: the current instance of #CRparser
+ *@a_buf: the input buffer
+ *@a_len: the length of the input buffer
+ *@a_enc: the encoding of the buffer
+ *
+ *Parses a stylesheet from a buffer
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parser_parse_buf (CRParser * a_this,
+ const guchar * a_buf,
+ gulong a_len, enum CREncoding a_enc)
+{
+ enum CRStatus status = CR_ERROR;
+ CRTknzr *tknzr = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_buf, CR_BAD_PARAM_ERROR);
+
+ tknzr = cr_tknzr_new_from_buf ((guchar*)a_buf, a_len, a_enc, FALSE);
+
+ g_return_val_if_fail (tknzr != NULL, CR_ERROR);
+
+ status = cr_parser_set_tknzr (a_this, tknzr);
+ if (status != CR_OK)
+ g_clear_pointer (&tknzr, cr_tknzr_unref);
+ g_return_val_if_fail (status == CR_OK, CR_ERROR);
+
+ status = cr_parser_parse (a_this);
+
+ return status;
+}
+
+/**
+ * cr_parser_destroy:
+ *@a_this: the current instance of #CRParser to
+ *destroy.
+ *
+ *Destroys the current instance
+ *of #CRParser.
+ */
+void
+cr_parser_destroy (CRParser * a_this)
+{
+ g_return_if_fail (a_this && PRIVATE (a_this));
+
+ if (PRIVATE (a_this)->tknzr) {
+ if (cr_tknzr_unref (PRIVATE (a_this)->tknzr) == TRUE)
+ PRIVATE (a_this)->tknzr = NULL;
+ }
+
+ if (PRIVATE (a_this)->sac_handler) {
+ cr_doc_handler_unref (PRIVATE (a_this)->sac_handler);
+ PRIVATE (a_this)->sac_handler = NULL;
+ }
+
+ if (PRIVATE (a_this)->err_stack) {
+ cr_parser_clear_errors (a_this);
+ PRIVATE (a_this)->err_stack = NULL;
+ }
+
+ if (PRIVATE (a_this)) {
+ g_free (PRIVATE (a_this));
+ PRIVATE (a_this) = NULL;
+ }
+
+ g_free (a_this);
+}
diff --git a/src/3rdparty/libcroco/src/cr-parser.h b/src/3rdparty/libcroco/src/cr-parser.h
new file mode 100644
index 0000000..24cf5df
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-parser.h
@@ -0,0 +1,130 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyrights information.
+ */
+
+#ifndef __CR_PARSER_H__
+#define __CR_PARSER_H__
+
+#include <glib.h>
+#include "cr-input.h"
+#include "cr-tknzr.h"
+#include "cr-utils.h"
+#include "cr-doc-handler.h"
+
+G_BEGIN_DECLS
+
+/**
+ *@file
+ *The declaration file
+ *of the #CRParser class.
+ */
+typedef struct _CRParser CRParser ;
+typedef struct _CRParserPriv CRParserPriv ;
+
+
+/**
+ *The implementation of
+ *the SAC parser.
+ *The Class is opaque
+ *and must be manipulated through
+ *the provided methods.
+ */
+struct _CRParser {
+ CRParserPriv *priv ;
+} ;
+
+
+CRParser * cr_parser_new (CRTknzr *a_tknzr) ;
+
+CRParser * cr_parser_new_from_buf (guchar *a_buf, gulong a_len,
+ enum CREncoding a_enc,
+ gboolean a_free_buf) ;
+
+CRParser * cr_parser_new_from_file (const guchar *a_file_uri,
+ enum CREncoding a_enc) ;
+
+CRParser * cr_parser_new_from_input (CRInput *a_input) ;
+
+enum CRStatus cr_parser_set_tknzr (CRParser *a_this, CRTknzr *a_tknzr) ;
+
+enum CRStatus cr_parser_get_tknzr (CRParser *a_this, CRTknzr **a_tknzr) ;
+
+enum CRStatus cr_parser_get_parsing_location (CRParser const *a_this, CRParsingLocation *a_loc) ;
+
+enum CRStatus cr_parser_try_to_skip_spaces_and_comments (CRParser *a_this) ;
+
+
+enum CRStatus cr_parser_set_sac_handler (CRParser *a_this,
+ CRDocHandler *a_handler) ;
+
+enum CRStatus cr_parser_get_sac_handler (CRParser *a_this,
+ CRDocHandler **a_handler) ;
+
+enum CRStatus cr_parser_set_use_core_grammar (CRParser *a_this,
+ gboolean a_use_core_grammar) ;
+enum CRStatus cr_parser_get_use_core_grammar (CRParser const *a_this,
+ gboolean *a_use_core_grammar) ;
+
+enum CRStatus cr_parser_parse (CRParser *a_this) ;
+
+enum CRStatus cr_parser_parse_file (CRParser *a_this,
+ const guchar *a_file_uri,
+ enum CREncoding a_enc) ;
+
+enum CRStatus cr_parser_parse_buf (CRParser *a_this, const guchar *a_buf,
+ gulong a_len, enum CREncoding a_enc) ;
+
+enum CRStatus cr_parser_set_default_sac_handler (CRParser *a_this) ;
+
+enum CRStatus cr_parser_parse_term (CRParser *a_this, CRTerm **a_term) ;
+
+enum CRStatus cr_parser_parse_selector (CRParser * a_this, CRSelector ** a_selector) ;
+
+enum CRStatus cr_parser_parse_expr (CRParser *a_this, CRTerm **a_expr) ;
+
+enum CRStatus cr_parser_parse_prio (CRParser *a_this, CRString **a_prio) ;
+
+enum CRStatus cr_parser_parse_declaration (CRParser *a_this, CRString **a_property,
+ CRTerm **a_expr, gboolean *a_important) ;
+
+enum CRStatus cr_parser_parse_statement_core (CRParser *a_this) ;
+
+enum CRStatus cr_parser_parse_ruleset (CRParser *a_this) ;
+
+enum CRStatus cr_parser_parse_import (CRParser *a_this, GList ** a_media_list,
+ CRString **a_import_string,
+ CRParsingLocation *a_location) ;
+
+enum CRStatus cr_parser_parse_media (CRParser *a_this) ;
+
+enum CRStatus cr_parser_parse_page (CRParser *a_this) ;
+
+enum CRStatus cr_parser_parse_charset (CRParser *a_this, CRString **a_value,
+ CRParsingLocation *a_charset_sym_location) ;
+
+enum CRStatus cr_parser_parse_font_face (CRParser *a_this) ;
+
+void cr_parser_destroy (CRParser *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_PARSER_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-parsing-location.c b/src/3rdparty/libcroco/src/cr-parsing-location.c
new file mode 100644
index 0000000..0aa0a45
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-parsing-location.c
@@ -0,0 +1,172 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli.
+ * See the COPYRIGHTS file for copyright information.
+ */
+
+#include <string.h>
+#include "cr-parsing-location.h"
+
+/**
+ *@CRParsingLocation:
+ *
+ *Definition of the #CRparsingLocation class.
+ */
+
+
+/**
+ * cr_parsing_location_new:
+ *Instantiates a new parsing location.
+ *
+ *Returns the newly instantiated #CRParsingLocation.
+ *Must be freed by cr_parsing_location_destroy()
+ */
+CRParsingLocation *
+cr_parsing_location_new (void)
+{
+ CRParsingLocation * result = NULL ;
+
+ result = g_try_malloc (sizeof (CRParsingLocation)) ;
+ if (!result) {
+ cr_utils_trace_info ("Out of memory error") ;
+ return NULL ;
+ }
+ cr_parsing_location_init (result) ;
+ return result ;
+}
+
+/**
+ * cr_parsing_location_init:
+ *@a_this: the current instance of #CRParsingLocation.
+ *
+ *Initializes the an instance of #CRparsingLocation.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_parsing_location_init (CRParsingLocation *a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
+
+ memset (a_this, 0, sizeof (CRParsingLocation)) ;
+ return CR_OK ;
+}
+
+/**
+ * cr_parsing_location_copy:
+ *@a_to: the destination of the copy.
+ *Must be allocated by the caller.
+ *@a_from: the source of the copy.
+ *
+ *Copies an instance of CRParsingLocation into another one.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_parsing_location_copy (CRParsingLocation *a_to,
+ CRParsingLocation const *a_from)
+{
+ g_return_val_if_fail (a_to && a_from, CR_BAD_PARAM_ERROR) ;
+
+ memcpy (a_to, a_from, sizeof (CRParsingLocation)) ;
+ return CR_OK ;
+}
+
+/**
+ * cr_parsing_location_to_string:
+ *@a_this: the current instance of #CRParsingLocation.
+ *@a_mask: a bitmap that defines which parts of the
+ *parsing location are to be serialized (line, column or byte offset)
+ *
+ *Returns the serialized string or NULL in case of an error.
+ */
+gchar *
+cr_parsing_location_to_string (CRParsingLocation const *a_this,
+ enum CRParsingLocationSerialisationMask a_mask)
+{
+ GString *result = NULL ;
+ gchar *str = NULL ;
+
+ g_return_val_if_fail (a_this, NULL) ;
+
+ if (!a_mask) {
+ a_mask = DUMP_LINE | DUMP_COLUMN | DUMP_BYTE_OFFSET ;
+ }
+ result =g_string_new (NULL) ;
+ if (!result)
+ return NULL ;
+ if (a_mask & DUMP_LINE) {
+ g_string_append_printf (result, "line:%d ",
+ a_this->line) ;
+ }
+ if (a_mask & DUMP_COLUMN) {
+ g_string_append_printf (result, "column:%d ",
+ a_this->column) ;
+ }
+ if (a_mask & DUMP_BYTE_OFFSET) {
+ g_string_append_printf (result, "byte offset:%d ",
+ a_this->byte_offset) ;
+ }
+ if (result->len) {
+ str = result->str ;
+ g_string_free (result, FALSE) ;
+ } else {
+ g_string_free (result, TRUE) ;
+ }
+ return str ;
+}
+
+/**
+ * cr_parsing_location_dump:
+ * @a_this: current instance of #CRParsingLocation
+ * @a_mask: the serialization mask.
+ * @a_fp: the file pointer to dump the parsing location to.
+ */
+void
+cr_parsing_location_dump (CRParsingLocation const *a_this,
+ enum CRParsingLocationSerialisationMask a_mask,
+ FILE *a_fp)
+{
+ gchar *str = NULL ;
+
+ g_return_if_fail (a_this && a_fp) ;
+ str = cr_parsing_location_to_string (a_this, a_mask) ;
+ if (str) {
+ fprintf (a_fp, "%s", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+}
+
+/**
+ * cr_parsing_location_destroy:
+ *@a_this: the current instance of #CRParsingLocation. Must
+ *have been allocated with cr_parsing_location_new().
+ *
+ *Destroys the current instance of #CRParsingLocation
+ */
+void
+cr_parsing_location_destroy (CRParsingLocation *a_this)
+{
+ g_return_if_fail (a_this) ;
+ g_free (a_this) ;
+}
+
diff --git a/src/3rdparty/libcroco/src/cr-parsing-location.h b/src/3rdparty/libcroco/src/cr-parsing-location.h
new file mode 100644
index 0000000..b8064a5
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-parsing-location.h
@@ -0,0 +1,70 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli.
+ * See the COPYRIGHTS file for copyright information.
+ */
+
+#ifndef __CR_PARSING_LOCATION_H__
+#define __CR_PARSING_LOCATION_H__
+
+#include "cr-utils.h"
+
+G_BEGIN_DECLS
+
+/**
+ *@file
+ *The declaration of the CRParsingLocation
+ *object. This object keeps track of line/column/byte offset/
+ *at which the parsing of a given CSS construction appears.
+ */
+
+typedef struct _CRParsingLocation CRParsingLocation;
+struct _CRParsingLocation {
+ guint line ;
+ guint column ;
+ guint byte_offset ;
+} ;
+
+
+enum CRParsingLocationSerialisationMask {
+ DUMP_LINE = 1,
+ DUMP_COLUMN = 1 << 1,
+ DUMP_BYTE_OFFSET = 1 << 2
+} ;
+
+CRParsingLocation * cr_parsing_location_new (void) ;
+
+enum CRStatus cr_parsing_location_init (CRParsingLocation *a_this) ;
+
+enum CRStatus cr_parsing_location_copy (CRParsingLocation *a_to,
+ CRParsingLocation const *a_from) ;
+
+gchar * cr_parsing_location_to_string (CRParsingLocation const *a_this,
+ enum CRParsingLocationSerialisationMask a_mask) ;
+void cr_parsing_location_dump (CRParsingLocation const *a_this,
+ enum CRParsingLocationSerialisationMask a_mask,
+ FILE *a_fp) ;
+
+void cr_parsing_location_destroy (CRParsingLocation *a_this) ;
+
+
+
+G_END_DECLS
+#endif
diff --git a/src/3rdparty/libcroco/src/cr-prop-list.c b/src/3rdparty/libcroco/src/cr-prop-list.c
new file mode 100644
index 0000000..8e42cee
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-prop-list.c
@@ -0,0 +1,404 @@
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyrights information.
+ */
+
+#include <string.h>
+#include "cr-prop-list.h"
+
+#define PRIVATE(a_obj) (a_obj)->priv
+
+struct _CRPropListPriv {
+ CRString *prop;
+ CRDeclaration *decl;
+ CRPropList *next;
+ CRPropList *prev;
+};
+
+static CRPropList *cr_prop_list_allocate (void);
+
+/**
+ *Default allocator of CRPropList
+ *@return the newly allocated CRPropList or NULL
+ *if an error arises.
+ */
+static CRPropList *
+cr_prop_list_allocate (void)
+{
+ CRPropList *result = NULL;
+
+ result = g_try_malloc (sizeof (CRPropList));
+ if (!result) {
+ cr_utils_trace_info ("could not allocate CRPropList");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRPropList));
+ PRIVATE (result) = g_try_malloc (sizeof (CRPropListPriv));
+ if (!PRIVATE (result)) {
+ cr_utils_trace_info ("could not allocate CRPropListPriv");
+ g_free (result);
+ return NULL;
+ }
+ memset (PRIVATE (result), 0, sizeof (CRPropListPriv));
+ return result;
+}
+
+/****************
+ *public methods
+ ***************/
+
+/**
+ * cr_prop_list_append:
+ *@a_this: the current instance of #CRPropList
+ *@a_to_append: the property list to append
+ *
+ *Appends a property list to the current one.
+ *
+ *Returns the resulting prop list, or NULL if an error
+ *occurred
+ */
+CRPropList *
+cr_prop_list_append (CRPropList * a_this, CRPropList * a_to_append)
+{
+ CRPropList *cur = NULL;
+
+ g_return_val_if_fail (a_to_append, NULL);
+
+ if (!a_this)
+ return a_to_append;
+
+ /*go fetch the last element of the list */
+ for (cur = a_this;
+ cur && PRIVATE (cur) && PRIVATE (cur)->next;
+ cur = PRIVATE (cur)->next) ;
+ g_return_val_if_fail (cur, NULL);
+ PRIVATE (cur)->next = a_to_append;
+ PRIVATE (a_to_append)->prev = cur;
+ return a_this;
+}
+
+/**
+ * cr_prop_list_append2:
+ *Appends a pair of prop/declaration to
+ *the current prop list.
+ *@a_this: the current instance of #CRPropList
+ *@a_prop: the property to consider
+ *@a_decl: the declaration to consider
+ *
+ *Returns the resulting property list, or NULL in case
+ *of an error.
+ */
+CRPropList *
+cr_prop_list_append2 (CRPropList * a_this,
+ CRString * a_prop,
+ CRDeclaration * a_decl)
+{
+ CRPropList *list = NULL,
+ *result = NULL;
+
+ g_return_val_if_fail (a_prop && a_decl, NULL);
+
+ list = cr_prop_list_allocate ();
+ g_return_val_if_fail (list && PRIVATE (list), NULL);
+
+ PRIVATE (list)->prop = a_prop;
+ PRIVATE (list)->decl = a_decl;
+
+ result = cr_prop_list_append (a_this, list);
+ return result;
+}
+
+/**
+ * cr_prop_list_prepend:
+ *@a_this: the current instance of #CRPropList
+ *@a_to_prepend: the new list to prepend.
+ *
+ *Prepends a list to the current list
+ *Returns the new properties list.
+ */
+CRPropList *
+cr_prop_list_prepend (CRPropList * a_this, CRPropList * a_to_prepend)
+{
+ CRPropList *cur = NULL;
+
+ g_return_val_if_fail (a_to_prepend, NULL);
+
+ if (!a_this)
+ return a_to_prepend;
+
+ for (cur = a_to_prepend; cur && PRIVATE (cur)->next;
+ cur = PRIVATE (cur)->next) ;
+ g_return_val_if_fail (cur, NULL);
+ PRIVATE (cur)->next = a_this;
+ PRIVATE (a_this)->prev = cur;
+ return a_to_prepend;
+}
+
+/**
+ * cr_prop_list_prepend2:
+ *@a_this: the current instance of #CRPropList
+ *@a_prop_name: property name to append
+ *@a_decl: the property value to append.
+ *
+ *Prepends a property to a list of properties
+ *
+ *Returns the new property list.
+ */
+CRPropList *
+cr_prop_list_prepend2 (CRPropList * a_this,
+ CRString * a_prop_name, CRDeclaration * a_decl)
+{
+ CRPropList *list = NULL,
+ *result = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_prop_name && a_decl, NULL);
+
+ list = cr_prop_list_allocate ();
+ g_return_val_if_fail (list, NULL);
+ PRIVATE (list)->prop = a_prop_name;
+ PRIVATE (list)->decl = a_decl;
+ result = cr_prop_list_prepend (a_this, list);
+ return result;
+}
+
+/**
+ * cr_prop_list_set_prop:
+ *@a_this: the current instance of #CRPropList
+ *@a_prop: the property to set
+ *
+ *Sets the property of a CRPropList
+ */
+enum CRStatus
+cr_prop_list_set_prop (CRPropList * a_this, CRString * a_prop)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_prop, CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->prop = a_prop;
+ return CR_OK;
+}
+
+/**
+ * cr_prop_list_get_prop:
+ *@a_this: the current instance of #CRPropList
+ *@a_prop: out parameter. The returned property
+ *
+ *Getter of the property associated to the current instance
+ *of #CRPropList
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_prop_list_get_prop (CRPropList const * a_this, CRString ** a_prop)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_prop, CR_BAD_PARAM_ERROR);
+
+ *a_prop = PRIVATE (a_this)->prop;
+ return CR_OK;
+}
+
+/**
+ * cr_prop_list_set_decl:
+ * @a_this: the current instance of #CRPropList
+ * @a_decl: the new property value.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_prop_list_set_decl (CRPropList * a_this, CRDeclaration * a_decl)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_decl, CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->decl = a_decl;
+ return CR_OK;
+}
+
+/**
+ * cr_prop_list_get_decl:
+ * @a_this: the current instance of #CRPropList
+ * @a_decl: out parameter. The property value
+ *
+ * Returns CR_OK upon successful completion.
+ */
+enum CRStatus
+cr_prop_list_get_decl (CRPropList const * a_this, CRDeclaration ** a_decl)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_decl, CR_BAD_PARAM_ERROR);
+
+ *a_decl = PRIVATE (a_this)->decl;
+ return CR_OK;
+}
+
+/**
+ * cr_prop_list_lookup_prop:
+ *@a_this: the current instance of #CRPropList
+ *@a_prop: the property to lookup
+ *@a_prop_list: out parameter. The property/declaration
+ *pair found (if and only if the function returned code if CR_OK)
+ *
+ *Lookup a given property/declaration pair
+ *
+ *Returns CR_OK if a prop/decl pair has been found,
+ *CR_VALUE_NOT_FOUND_ERROR if not, or an error code if something
+ *bad happens.
+ */
+enum CRStatus
+cr_prop_list_lookup_prop (CRPropList * a_this,
+ CRString * a_prop, CRPropList ** a_pair)
+{
+ CRPropList *cur = NULL;
+
+ g_return_val_if_fail (a_prop && a_pair, CR_BAD_PARAM_ERROR);
+
+ if (!a_this)
+ return CR_VALUE_NOT_FOUND_ERROR;
+
+ g_return_val_if_fail (PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ for (cur = a_this; cur; cur = PRIVATE (cur)->next) {
+ if (PRIVATE (cur)->prop
+ && PRIVATE (cur)->prop->stryng
+ && PRIVATE (cur)->prop->stryng->str
+ && a_prop->stryng
+ && a_prop->stryng->str
+ && !strcmp (PRIVATE (cur)->prop->stryng->str,
+ a_prop->stryng->str))
+ break;
+ }
+
+ if (cur) {
+ *a_pair = cur;
+ return CR_OK;
+ }
+
+ return CR_VALUE_NOT_FOUND_ERROR;
+}
+
+/**
+ * cr_prop_list_get_next:
+ *@a_this: the current instance of CRPropList
+ *
+ *Gets the next prop/decl pair in the list
+ *
+ *Returns the next prop/declaration pair of the list,
+ *or NULL if we reached end of list (or if an error occurs)
+ */
+CRPropList *
+cr_prop_list_get_next (CRPropList * a_this)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
+
+ return PRIVATE (a_this)->next;
+}
+
+/**
+ * cr_prop_list_get_prev:
+ *@a_this: the current instance of CRPropList
+ *
+ *Gets the previous prop/decl pair in the list
+ *
+ *Returns the previous prop/declaration pair of the list,
+ *or NULL if we reached end of list (or if an error occurs)
+ */
+CRPropList *
+cr_prop_list_get_prev (CRPropList * a_this)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), NULL);
+
+ return PRIVATE (a_this)->prev;
+}
+
+/**
+ * cr_prop_list_unlink:
+ *@a_this: the current list of prop/decl pairs
+ *@a_pair: the prop/decl pair to unlink.
+ *
+ *Unlinks a prop/decl pair from the list
+ *
+ *Returns the new list or NULL in case of an error.
+ */
+CRPropList *
+cr_prop_list_unlink (CRPropList * a_this, CRPropList * a_pair)
+{
+ CRPropList *prev = NULL,
+ *next = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_pair, NULL);
+
+ /*some sanity checks */
+ if (PRIVATE (a_pair)->next) {
+ next = PRIVATE (a_pair)->next;
+ g_return_val_if_fail (PRIVATE (next), NULL);
+ g_return_val_if_fail (PRIVATE (next)->prev == a_pair, NULL);
+ }
+ if (PRIVATE (a_pair)->prev) {
+ prev = PRIVATE (a_pair)->prev;
+ g_return_val_if_fail (PRIVATE (prev), NULL);
+ g_return_val_if_fail (PRIVATE (prev)->next == a_pair, NULL);
+ }
+ if (prev) {
+ PRIVATE (prev)->next = next;
+ }
+ if (next) {
+ PRIVATE (next)->prev = prev;
+ }
+ PRIVATE (a_pair)->prev = PRIVATE (a_pair)->next = NULL;
+ if (a_this == a_pair) {
+ if (next)
+ return next;
+ return NULL;
+ }
+ return a_this;
+}
+
+/**
+ * cr_prop_list_destroy:
+ * @a_this: the current instance of #CRPropList
+ */
+void
+cr_prop_list_destroy (CRPropList * a_this)
+{
+ CRPropList *tail = NULL,
+ *cur = NULL;
+
+ g_return_if_fail (a_this && PRIVATE (a_this));
+
+ for (tail = a_this;
+ tail && PRIVATE (tail) && PRIVATE (tail)->next;
+ tail = cr_prop_list_get_next (tail)) ;
+ g_return_if_fail (tail);
+
+ cur = tail;
+
+ while (cur) {
+ tail = PRIVATE (cur)->prev;
+ if (tail && PRIVATE (tail))
+ PRIVATE (tail)->next = NULL;
+ PRIVATE (cur)->prev = NULL;
+ g_free (PRIVATE (cur));
+ PRIVATE (cur) = NULL;
+ g_free (cur);
+ cur = tail;
+ }
+}
diff --git a/src/3rdparty/libcroco/src/cr-prop-list.h b/src/3rdparty/libcroco/src/cr-prop-list.h
new file mode 100644
index 0000000..797ba43
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-prop-list.h
@@ -0,0 +1,80 @@
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyrights information.
+ */
+
+#ifndef __CR_PROP_LIST_H__
+#define __CR_PROP_LIST_H__
+
+#include "cr-utils.h"
+#include "cr-declaration.h"
+#include "cr-string.h"
+
+G_BEGIN_DECLS
+
+typedef struct _CRPropList CRPropList ;
+typedef struct _CRPropListPriv CRPropListPriv ;
+
+struct _CRPropList
+{
+ CRPropListPriv * priv;
+} ;
+
+CRPropList * cr_prop_list_append (CRPropList *a_this,
+ CRPropList *a_to_append) ;
+
+CRPropList * cr_prop_list_append2 (CRPropList *a_this,
+ CRString *a_prop,
+ CRDeclaration *a_decl) ;
+
+CRPropList * cr_prop_list_prepend (CRPropList *a_this,
+ CRPropList *a_to_append) ;
+
+CRPropList * cr_prop_list_prepend2 (CRPropList *a_this,
+ CRString *a_prop,
+ CRDeclaration *a_decl) ;
+
+enum CRStatus cr_prop_list_set_prop (CRPropList *a_this,
+ CRString *a_prop) ;
+
+enum CRStatus cr_prop_list_get_prop (CRPropList const *a_this,
+ CRString **a_prop) ;
+
+enum CRStatus cr_prop_list_lookup_prop (CRPropList *a_this,
+ CRString *a_prop,
+ CRPropList**a_pair) ;
+
+CRPropList * cr_prop_list_get_next (CRPropList *a_this) ;
+
+CRPropList * cr_prop_list_get_prev (CRPropList *a_this) ;
+
+enum CRStatus cr_prop_list_set_decl (CRPropList *a_this,
+ CRDeclaration *a_decl);
+
+enum CRStatus cr_prop_list_get_decl (CRPropList const *a_this,
+ CRDeclaration **a_decl) ;
+
+CRPropList * cr_prop_list_unlink (CRPropList *a_this,
+ CRPropList *a_pair) ;
+
+void cr_prop_list_destroy (CRPropList *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_PROP_LIST_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-pseudo.c b/src/3rdparty/libcroco/src/cr-pseudo.c
new file mode 100644
index 0000000..3644ab1
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-pseudo.c
@@ -0,0 +1,166 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include "cr-pseudo.h"
+
+/**
+ *@CRPseudo:
+ *The definition of the #CRPseudo class.
+ */
+
+/**
+ * cr_pseudo_new:
+ *Constructor of the #CRPseudo class.
+ *
+ *Returns the newly build instance.
+ */
+CRPseudo *
+cr_pseudo_new (void)
+{
+ CRPseudo *result = NULL;
+
+ result = g_malloc0 (sizeof (CRPseudo));
+
+ return result;
+}
+
+/**
+ * cr_pseudo_to_string:
+ * @a_this: the current instance of #CRPseud.
+ *
+ * Returns the serialized pseudo. Caller must free the returned
+ * string using g_free().
+ */
+guchar *
+cr_pseudo_to_string (CRPseudo const * a_this)
+{
+ guchar *result = NULL;
+ GString *str_buf = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ str_buf = g_string_new (NULL);
+
+ if (a_this->type == IDENT_PSEUDO) {
+ gchar const *name = NULL;
+
+ if (a_this->name == NULL) {
+ goto error;
+ }
+
+ name = a_this->name->stryng->str;
+
+ if (name) {
+ g_string_append (str_buf, (const gchar *) name);
+ name = NULL;
+ }
+ } else if (a_this->type == FUNCTION_PSEUDO) {
+ gchar const *name = NULL,
+ *arg = NULL;
+
+ if (a_this->name == NULL)
+ goto error;
+
+ name = a_this->name->stryng->str;
+
+ if (a_this->term && a_this->term->type == TERM_IDENT) {
+ arg = a_this->term->content.str->stryng->str;
+ }
+
+ if (name) {
+ g_string_append_printf (str_buf, "%s(", name);
+ name = NULL;
+
+ if (arg) {
+ g_string_append (str_buf, (const gchar *) arg);
+ arg = NULL;
+ }
+
+ g_string_append_c (str_buf, ')');
+ }
+ }
+
+ if (str_buf) {
+ result = (guchar *) str_buf->str;
+ g_string_free (str_buf, FALSE);
+ str_buf = NULL;
+ }
+
+ return result;
+
+ error:
+ g_string_free (str_buf, TRUE);
+ return NULL;
+}
+
+/**
+ * cr_pseudo_dump:
+ *@a_this: the current instance of pseudo
+ *@a_fp: the destination file pointer.
+ *
+ *Dumps the pseudo to a file.
+ *
+ */
+void
+cr_pseudo_dump (CRPseudo const * a_this, FILE * a_fp)
+{
+ guchar *tmp_str = NULL;
+
+ if (a_this) {
+ tmp_str = cr_pseudo_to_string (a_this);
+ if (tmp_str) {
+ fprintf (a_fp, "%s", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+}
+
+/**
+ * cr_pseudo_destroy:
+ *@a_this: the current instance to destroy.
+ *
+ *destructor of the #CRPseudo class.
+ */
+void
+cr_pseudo_destroy (CRPseudo * a_this)
+{
+ g_return_if_fail (a_this);
+
+ if (a_this->name) {
+ cr_string_destroy (a_this->name);
+ a_this->name = NULL;
+ }
+
+ if (a_this->sel_name) {
+ cr_string_destroy (a_this->sel_name);
+ a_this->sel_name = NULL;
+ }
+
+ if (a_this->term) {
+ cr_term_destroy (a_this->term);
+ a_this->term = NULL;
+ }
+
+ g_free (a_this);
+}
diff --git a/src/3rdparty/libcroco/src/cr-pseudo.h b/src/3rdparty/libcroco/src/cr-pseudo.h
new file mode 100644
index 0000000..b784350
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-pseudo.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * See COPYRIGHTS file for copyright information
+ */
+
+#ifndef __CR_PSEUDO_H__
+#define __CR_PSEUDO_H__
+
+#include <stdio.h>
+#include <glib.h>
+#include "cr-attr-sel.h"
+#include "cr-parsing-location.h"
+#include "cr-term.h"
+
+G_BEGIN_DECLS
+
+enum CRPseudoType
+{
+ IDENT_PSEUDO = 0,
+ FUNCTION_PSEUDO
+} ;
+
+typedef struct _CRPseudo CRPseudo ;
+
+/**
+ *The CRPseudo Class.
+ *Abstract a "pseudo" as defined by the css2 spec
+ *in appendix D.1 .
+ */
+struct _CRPseudo
+{
+ enum CRPseudoType type ;
+ CRString *name ;
+ CRString *sel_name;
+ CRTerm *term ;
+ CRParsingLocation location ;
+} ;
+
+CRPseudo * cr_pseudo_new (void) ;
+
+guchar * cr_pseudo_to_string (CRPseudo const *a_this) ;
+
+void cr_pseudo_dump (CRPseudo const *a_this, FILE *a_fp) ;
+
+void cr_pseudo_destroy (CRPseudo *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_PSEUDO_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-rgb.c b/src/3rdparty/libcroco/src/cr-rgb.c
new file mode 100644
index 0000000..e2a1fc8
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-rgb.c
@@ -0,0 +1,686 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyrights information.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "cr-rgb.h"
+#include "cr-term.h"
+#include "cr-parser.h"
+
+static const CRRgb gv_standard_colors[] = {
+ {(const guchar*)"aliceblue", 240, 248, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"antiquewhite", 250, 235, 215, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"aqua", 0, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"aquamarine", 127, 255, 212, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"azure", 240, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"beige", 245, 245, 220, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"bisque", 255, 228, 196, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"black", 0, 0, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"blanchedalmond", 255, 235, 205, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"blue", 0, 0, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"blueviolet", 138, 43, 226, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"brown", 165, 42, 42, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"burlywood", 222, 184, 135, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"cadetblue", 95, 158, 160, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"chartreuse", 127, 255, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"chocolate", 210, 105, 30, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"coral", 255, 127, 80, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"cornflowerblue", 100, 149, 237, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"cornsilk", 255, 248, 220, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"crimson", 220, 20, 60, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"cyan", 0, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkblue", 0, 0, 139, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkcyan", 0, 139, 139, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkgoldenrod", 184, 134, 11, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkgray", 169, 169, 169, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkgreen", 0, 100, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkgrey", 169, 169, 169, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkkhaki", 189, 183, 107, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkmagenta", 139, 0, 139, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkolivegreen", 85, 107, 47, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkorange", 255, 140, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkorchid", 153, 50, 204, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkred", 139, 0, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darksalmon", 233, 150, 122, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkseagreen", 143, 188, 143, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkslateblue", 72, 61, 139, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkslategray", 47, 79, 79, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkslategrey", 47, 79, 79, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkturquoise", 0, 206, 209, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"darkviolet", 148, 0, 211, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"deeppink", 255, 20, 147, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"deepskyblue", 0, 191, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"dimgray", 105, 105, 105, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"dimgrey", 105, 105, 105, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"dodgerblue", 30, 144, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"firebrick", 178, 34, 34, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"floralwhite", 255, 250, 240, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"forestgreen", 34, 139, 34, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"fuchsia", 255, 0, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"gainsboro", 220, 220, 220, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"ghostwhite", 248, 248, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"gold", 255, 215, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"goldenrod", 218, 165, 32, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"gray", 128, 128, 128, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"green", 0, 128, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"greenyellow", 173, 255, 47, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"grey", 128, 128, 128, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"honeydew", 240, 255, 240, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"hotpink", 255, 105, 180, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"indianred", 205, 92, 92, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"indigo", 75, 0, 130, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"ivory", 255, 255, 240, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"khaki", 240, 230, 140, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lavender", 230, 230, 250, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lavenderblush", 255, 240, 245, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lawngreen", 124, 252, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lemonchiffon", 255, 250, 205, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightblue", 173, 216, 230, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightcoral", 240, 128, 128, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightcyan", 224, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightgoldenrodyellow", 250, 250, 210, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightgray", 211, 211, 211, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightgreen", 144, 238, 144, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightgrey", 211, 211, 211, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightpink", 255, 182, 193, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightsalmon", 255, 160, 122, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightseagreen", 32, 178, 170, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightskyblue", 135, 206, 250, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightslategray", 119, 136, 153, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightslategrey", 119, 136, 153, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightsteelblue", 176, 196, 222, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lightyellow", 255, 255, 224, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"lime", 0, 255, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"limegreen", 50, 205, 50, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"linen", 250, 240, 230, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"magenta", 255, 0, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"maroon", 128, 0, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mediumaquamarine", 102, 205, 170, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mediumblue", 0, 0, 205, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mediumorchid", 186, 85, 211, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mediumpurple", 147, 112, 219, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mediumseagreen", 60, 179, 113, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mediumslateblue", 123, 104, 238, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mediumspringgreen", 0, 250, 154, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mediumturquoise", 72, 209, 204, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mediumvioletred", 199, 21, 133, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"midnightblue", 25, 25, 112, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mintcream", 245, 255, 250, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"mistyrose", 255, 228, 225, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"moccasin", 255, 228, 181, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"navajowhite", 255, 222, 173, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"navy", 0, 0, 128, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"oldlace", 253, 245, 230, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"olive", 128, 128, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"olivedrab", 107, 142, 35, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"orange", 255, 165, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"orangered", 255, 69, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"orchid", 218, 112, 214, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"palegoldenrod", 238, 232, 170, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"palegreen", 152, 251, 152, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"paleturquoise", 175, 238, 238, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"palevioletred", 219, 112, 147, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"papayawhip", 255, 239, 213, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"peachpuff", 255, 218, 185, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"peru", 205, 133, 63, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"pink", 255, 192, 203, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"plum", 221, 160, 221, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"powderblue", 176, 224, 230, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"purple", 128, 0, 128, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"rebeccapurple", 102, 51, 153, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"red", 255, 0, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"rosybrown", 188, 143, 143, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"royalblue", 65, 105, 225, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"saddlebrown", 139, 69, 19, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"salmon", 250, 128, 114, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"sandybrown", 244, 164, 96, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"seagreen", 46, 139, 87, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"seashell", 255, 245, 238, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"sienna", 160, 82, 45, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"silver", 192, 192, 192, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"skyblue", 135, 206, 235, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"slateblue", 106, 90, 205, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"slategray", 112, 128, 144, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"slategrey", 112, 128, 144, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"snow", 255, 250, 250, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"springgreen", 0, 255, 127, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"steelblue", 70, 130, 180, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"tan", 210, 180, 140, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"teal", 0, 128, 128, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"thistle", 216, 191, 216, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"tomato", 255, 99, 71, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"transparent", 255, 255, 255, FALSE, FALSE, TRUE, {0,0,0}},
+ {(const guchar*)"turquoise", 64, 224, 208, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"violet", 238, 130, 238, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"wheat", 245, 222, 179, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"white", 255, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"whitesmoke", 245, 245, 245, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"yellow", 255, 255, 0, FALSE, FALSE, FALSE, {0,0,0}},
+ {(const guchar*)"yellowgreen", 154, 205, 50, FALSE, FALSE, FALSE, {0,0,0}}
+};
+
+/**
+ * cr_rgb_new:
+ *
+ *The default constructor of #CRRgb.
+ *
+ *Returns the newly built instance of #CRRgb
+ */
+CRRgb *
+cr_rgb_new (void)
+{
+ CRRgb *result = NULL;
+
+ result = g_try_malloc (sizeof (CRRgb));
+
+ if (result == NULL) {
+ cr_utils_trace_info ("No more memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRRgb));
+
+ return result;
+}
+
+/**
+ * cr_rgb_new_with_vals:
+ *@a_red: the red component of the color.
+ *@a_green: the green component of the color.
+ *@a_blue: the blue component of the color.
+ *@a_unit: the unit of the rgb values.
+ *(either percentage or integer values)
+ *
+ *A constructor of #CRRgb.
+ *
+ *Returns the newly built instance of #CRRgb.
+ */
+CRRgb *
+cr_rgb_new_with_vals (gulong a_red, gulong a_green,
+ gulong a_blue, gboolean a_is_percentage)
+{
+ CRRgb *result = NULL;
+
+ result = cr_rgb_new ();
+
+ g_return_val_if_fail (result, NULL);
+
+ result->red = a_red;
+ result->green = a_green;
+ result->blue = a_blue;
+ result->is_percentage = a_is_percentage;
+
+ return result;
+}
+
+/**
+ * cr_rgb_to_string:
+ *@a_this: the instance of #CRRgb to serialize.
+ *
+ *Serializes the rgb into a zero terminated string.
+ *
+ *Returns the zero terminated string containing the serialized
+ *rgb. MUST BE FREED by the caller using g_free().
+ */
+guchar *
+cr_rgb_to_string (CRRgb const * a_this)
+{
+ guchar *result = NULL;
+ GString *str_buf = NULL;
+
+ str_buf = g_string_new (NULL);
+ g_return_val_if_fail (str_buf, NULL);
+
+ if (a_this->is_percentage == 1) {
+ g_string_append_printf (str_buf, "%ld", a_this->red);
+
+ g_string_append (str_buf, "%, ");
+
+ g_string_append_printf (str_buf, "%ld", a_this->green);
+ g_string_append (str_buf, "%, ");
+
+ g_string_append_printf (str_buf, "%ld", a_this->blue);
+ g_string_append_c (str_buf, '%');
+ } else {
+ g_string_append_printf (str_buf, "%ld", a_this->red);
+ g_string_append (str_buf, ", ");
+
+ g_string_append_printf (str_buf, "%ld", a_this->green);
+ g_string_append (str_buf, ", ");
+
+ g_string_append_printf (str_buf, "%ld", a_this->blue);
+ }
+
+ if (str_buf) {
+ result = (guchar *) str_buf->str;
+ g_string_free (str_buf, FALSE);
+ }
+
+ return result;
+}
+
+/**
+ * cr_rgb_dump:
+ *@a_this: the "this pointer" of
+ *the current instance of #CRRgb.
+ *@a_fp: the destination file pointer.
+ *
+ *Dumps the current instance of #CRRgb
+ *to a file.
+ */
+void
+cr_rgb_dump (CRRgb const * a_this, FILE * a_fp)
+{
+ guchar *str = NULL;
+
+ g_return_if_fail (a_this);
+
+ str = cr_rgb_to_string (a_this);
+
+ if (str) {
+ fprintf (a_fp, "%s", str);
+ g_free (str);
+ str = NULL;
+ }
+}
+
+/**
+ * cr_rgb_compute_from_percentage:
+ *@a_this: the current instance of #CRRgb
+ *
+ *If the rgb values are expressed in percentage,
+ *compute their real value.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_rgb_compute_from_percentage (CRRgb * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ if (a_this->is_percentage == FALSE)
+ return CR_OK;
+ a_this->red = a_this->red * 255 / 100;
+ a_this->green = a_this->green * 255 / 100;
+ a_this->blue = a_this->blue * 255 / 100;
+ a_this->is_percentage = FALSE;
+ return CR_OK;
+}
+
+/**
+ * cr_rgb_set:
+ *@a_this: the current instance of #CRRgb.
+ *@a_red: the red value.
+ *@a_green: the green value.
+ *@a_blue: the blue value.
+ *
+ *Sets rgb values to the RGB.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_rgb_set (CRRgb * a_this, gulong a_red,
+ gulong a_green, gulong a_blue, gboolean a_is_percentage)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+ if (a_is_percentage != FALSE) {
+ g_return_val_if_fail (a_red <= 100
+ && a_green <= 100
+ && a_blue <= 100, CR_BAD_PARAM_ERROR);
+ }
+
+ a_this->is_percentage = a_is_percentage;
+
+ a_this->red = a_red;
+ a_this->green = a_green;
+ a_this->blue = a_blue;
+ a_this->inherit = FALSE ;
+ a_this->is_transparent = FALSE ;
+ return CR_OK;
+}
+
+/**
+ * cr_rgb_set_to_inherit:
+ *@a_this: the current instance of #CRRgb
+ *
+ *sets the value of the rgb to inherit.
+ *Look at the css spec from chapter 6.1 to 6.2 to understand
+ *the meaning of "inherit".
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_rgb_set_to_inherit (CRRgb *a_this, gboolean a_inherit)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
+
+ a_this->inherit = a_inherit ;
+
+ return CR_OK ;
+}
+
+/**
+ * cr_rgb_is_set_to_inherit:
+ *
+ * @a_this: the current instance of #CRRgb.
+ *
+ * Returns TRUE if the rgb is set to the value "inherit", FALSE otherwise.
+ */
+gboolean
+cr_rgb_is_set_to_inherit (CRRgb const *a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
+
+ return a_this->inherit ;
+}
+
+/**
+ * cr_rgb_is_set_to_transparent:
+ *@a_this: the current instance of
+ *#CRRgb
+ *
+ *Tests if the rgb is set to the
+ *value "transparent" or not.
+ *
+ *Returns TRUE if the rgb has been set to
+ *transparent, FALSE otherwise.
+ */
+gboolean
+cr_rgb_is_set_to_transparent (CRRgb const *a_this)
+{
+ g_return_val_if_fail (a_this, FALSE) ;
+ return a_this->is_transparent ;
+}
+
+
+/**
+ * cr_rgb_set_to_transparent:
+ *@a_this: the current instance of #CRRgb
+ *@a_is_transparent: set to transparent or not.
+ *
+ *Sets the rgb to the "transparent" value (or not)
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_rgb_set_to_transparent (CRRgb *a_this,
+ gboolean a_is_transparent)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
+ a_this->is_transparent = a_is_transparent ;
+ return CR_OK ;
+}
+
+/**
+ * cr_rgb_set_from_rgb:
+ *@a_this: the current instance of #CRRgb.
+ *@a_rgb: the rgb to "copy"
+ *
+ *Sets the rgb from an other one.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_rgb_set_from_rgb (CRRgb * a_this, CRRgb const * a_rgb)
+{
+ g_return_val_if_fail (a_this && a_rgb, CR_BAD_PARAM_ERROR);
+
+ cr_rgb_copy (a_this, a_rgb) ;
+
+ return CR_OK;
+}
+
+static int
+cr_rgb_color_name_compare (const void *a,
+ const void *b)
+{
+ const char *a_color_name = a;
+ const CRRgb *rgb = b;
+
+ return g_ascii_strcasecmp (a_color_name, (const char *) rgb->name);
+}
+
+/**
+ * cr_rgb_set_from_name:
+ * @a_this: the current instance of #CRRgb
+ * @a_color_name: the color name
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_rgb_set_from_name (CRRgb * a_this, const guchar * a_color_name)
+{
+ enum CRStatus status = CR_OK;
+ CRRgb *result;
+
+ g_return_val_if_fail (a_this && a_color_name, CR_BAD_PARAM_ERROR);
+
+ result = bsearch (a_color_name,
+ gv_standard_colors,
+ G_N_ELEMENTS (gv_standard_colors),
+ sizeof (gv_standard_colors[0]),
+ cr_rgb_color_name_compare);
+ if (result != NULL)
+ cr_rgb_set_from_rgb (a_this, result);
+ else
+ status = CR_UNKNOWN_TYPE_ERROR;
+
+ return status;
+}
+
+/**
+ * cr_rgb_set_from_hex_str:
+ * @a_this: the current instance of #CRRgb
+ * @a_hex: the hexadecimal value to set.
+ *
+ * Returns CR_OK upon successful completion.
+ */
+enum CRStatus
+cr_rgb_set_from_hex_str (CRRgb * a_this, const guchar * a_hex)
+{
+ enum CRStatus status = CR_OK;
+ gulong i = 0;
+ guchar colors[3] = { 0 };
+
+ g_return_val_if_fail (a_this && a_hex, CR_BAD_PARAM_ERROR);
+
+ if (strlen ((const char *) a_hex) == 3) {
+ for (i = 0; i < 3; i++) {
+ if (a_hex[i] >= '0' && a_hex[i] <= '9') {
+ colors[i] = a_hex[i] - '0';
+ colors[i] = (colors[i] << 4) | colors[i];
+ } else if (a_hex[i] >= 'a' && a_hex[i] <= 'z') {
+ colors[i] = 10 + a_hex[i] - 'a';
+ colors[i] = (colors[i] << 4) | colors[i];
+ } else if (a_hex[i] >= 'A' && a_hex[i] <= 'Z') {
+ colors[i] = 10 + a_hex[i] - 'A';
+ colors[i] = (colors[i] << 4) | colors[i];
+ } else {
+ status = CR_UNKNOWN_TYPE_ERROR;
+ }
+ }
+ } else if (strlen ((const char *) a_hex) == 6) {
+ for (i = 0; i < 6; i++) {
+ if (a_hex[i] >= '0' && a_hex[i] <= '9') {
+ colors[i / 2] <<= 4;
+ colors[i / 2] |= a_hex[i] - '0';
+ status = CR_OK;
+ } else if (a_hex[i] >= 'a' && a_hex[i] <= 'z') {
+ colors[i / 2] <<= 4;
+ colors[i / 2] |= 10 + a_hex[i] - 'a';
+ status = CR_OK;
+ } else if (a_hex[i] >= 'A' && a_hex[i] <= 'Z') {
+ colors[i / 2] <<= 4;
+ colors[i / 2] |= 10 + a_hex[i] - 'A';
+ status = CR_OK;
+ } else {
+ status = CR_UNKNOWN_TYPE_ERROR;
+ }
+ }
+ } else {
+ status = CR_UNKNOWN_TYPE_ERROR;
+ }
+
+ if (status == CR_OK) {
+ status = cr_rgb_set (a_this, colors[0],
+ colors[1], colors[2], FALSE);
+ cr_rgb_set_to_transparent (a_this, FALSE) ;
+ }
+ return status;
+}
+
+/**
+ * cr_rgb_set_from_term:
+ *@a_this: the instance of #CRRgb to set
+ *@a_value: the terminal from which to set
+ *
+ *Set the rgb from a terminal symbol
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_rgb_set_from_term (CRRgb *a_this, const struct _CRTerm *a_value)
+{
+ enum CRStatus status = CR_OK ;
+ g_return_val_if_fail (a_this && a_value,
+ CR_BAD_PARAM_ERROR) ;
+
+ switch(a_value->type) {
+ case TERM_RGB:
+ if (a_value->content.rgb) {
+ cr_rgb_set_from_rgb
+ (a_this, a_value->content.rgb) ;
+ }
+ break ;
+ case TERM_IDENT:
+ if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str) {
+ if (!strncmp ("inherit",
+ a_value->content.str->stryng->str,
+ sizeof ("inherit")-1)) {
+ a_this->inherit = TRUE;
+ a_this->is_transparent = FALSE ;
+ } else {
+ status = cr_rgb_set_from_name
+ (a_this,
+ (const guchar *) a_value->content.str->stryng->str) ;
+ }
+ } else {
+ cr_utils_trace_info
+ ("a_value has NULL string value") ;
+ }
+ break ;
+ case TERM_HASH:
+ if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str) {
+ status = cr_rgb_set_from_hex_str
+ (a_this,
+ (const guchar *) a_value->content.str->stryng->str) ;
+ } else {
+ cr_utils_trace_info
+ ("a_value has NULL string value") ;
+ }
+ break ;
+ default:
+ status = CR_UNKNOWN_TYPE_ERROR ;
+ }
+ return status ;
+}
+
+enum CRStatus
+cr_rgb_copy (CRRgb *a_dest, CRRgb const *a_src)
+{
+ g_return_val_if_fail (a_dest && a_src,
+ CR_BAD_PARAM_ERROR) ;
+
+ memcpy (a_dest, a_src, sizeof (CRRgb)) ;
+ return CR_OK ;
+}
+
+/**
+ * cr_rgb_destroy:
+ *@a_this: the "this pointer" of the
+ *current instance of #CRRgb.
+ *
+ *Destructor of #CRRgb.
+ */
+void
+cr_rgb_destroy (CRRgb * a_this)
+{
+ g_return_if_fail (a_this);
+ g_free (a_this);
+}
+
+/**
+ * cr_rgb_parse_from_buf:
+ *@a_str: a string that contains a color description
+ *@a_enc: the encoding of a_str
+ *
+ *Parses a text buffer that contains a rgb color
+ *
+ *Returns the parsed color, or NULL in case of error
+ */
+CRRgb *
+cr_rgb_parse_from_buf (const guchar *a_str,
+ enum CREncoding a_enc)
+{
+ enum CRStatus status = CR_OK ;
+ CRTerm *value = NULL ;
+ CRParser * parser = NULL;
+ CRRgb *result = NULL;
+
+ g_return_val_if_fail (a_str, NULL);
+
+ parser = cr_parser_new_from_buf ((guchar *) a_str, strlen ((const char *) a_str), a_enc, FALSE);
+
+ g_return_val_if_fail (parser, NULL);
+
+ status = cr_parser_try_to_skip_spaces_and_comments (parser) ;
+ if (status != CR_OK)
+ goto cleanup;
+
+ status = cr_parser_parse_term (parser, &value);
+ if (status != CR_OK)
+ goto cleanup;
+
+ result = cr_rgb_new ();
+ if (!result)
+ goto cleanup;
+
+ status = cr_rgb_set_from_term (result, value);
+
+cleanup:
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ }
+ if (value) {
+ cr_term_destroy(value);
+ value = NULL;
+ }
+ return result ;
+}
+
diff --git a/src/3rdparty/libcroco/src/cr-rgb.h b/src/3rdparty/libcroco/src/cr-rgb.h
new file mode 100644
index 0000000..a127a44
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-rgb.h
@@ -0,0 +1,94 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * see COPYRIGHTS file for copyright information.
+ */
+
+#ifndef __CR_RGB_H__
+#define __CR_RGB_H__
+
+#include <stdio.h>
+#include <glib.h>
+#include "cr-utils.h"
+#include "cr-parsing-location.h"
+
+G_BEGIN_DECLS
+
+
+typedef struct _CRRgb CRRgb ;
+struct _CRRgb
+{
+ /*
+ *the unit of the rgb.
+ *Either NO_UNIT (integer) or
+ *UNIT_PERCENTAGE (percentage).
+ */
+ const guchar *name ;
+ glong red ;
+ glong green ;
+ glong blue ;
+ gboolean is_percentage ;
+ gboolean inherit ;
+ gboolean is_transparent ;
+ CRParsingLocation location ;
+} ;
+
+CRRgb * cr_rgb_new (void) ;
+
+CRRgb * cr_rgb_new_with_vals (gulong a_red, gulong a_green,
+ gulong a_blue, gboolean a_is_percentage) ;
+
+CRRgb *cr_rgb_parse_from_buf(const guchar *a_str,
+ enum CREncoding a_enc);
+
+enum CRStatus cr_rgb_compute_from_percentage (CRRgb *a_this) ;
+
+enum CRStatus cr_rgb_set (CRRgb *a_this, gulong a_red,
+ gulong a_green, gulong a_blue,
+ gboolean a_is_percentage) ;
+
+enum CRStatus cr_rgb_copy (CRRgb *a_dest, CRRgb const *a_src) ;
+
+enum CRStatus cr_rgb_set_to_inherit (CRRgb *a_this, gboolean a_inherit) ;
+
+gboolean cr_rgb_is_set_to_inherit (CRRgb const *a_this) ;
+
+gboolean cr_rgb_is_set_to_transparent (CRRgb const *a_this) ;
+
+enum CRStatus cr_rgb_set_to_transparent (CRRgb *a_this,
+ gboolean a_is_transparent) ;
+enum CRStatus cr_rgb_set_from_rgb (CRRgb *a_this, CRRgb const *a_rgb) ;
+
+enum CRStatus cr_rgb_set_from_name (CRRgb *a_this, const guchar *a_color_name) ;
+
+enum CRStatus cr_rgb_set_from_hex_str (CRRgb *a_this, const guchar * a_hex_value) ;
+
+struct _CRTerm;
+
+enum CRStatus cr_rgb_set_from_term (CRRgb *a_this, const struct _CRTerm *a_value);
+
+guchar * cr_rgb_to_string (CRRgb const *a_this) ;
+
+void cr_rgb_dump (CRRgb const *a_this, FILE *a_fp) ;
+
+void cr_rgb_destroy (CRRgb *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_RGB_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-sel-eng.c b/src/3rdparty/libcroco/src/cr-sel-eng.c
new file mode 100644
index 0000000..8ed485d
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-sel-eng.c
@@ -0,0 +1,2236 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser
+ * General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include <string.h>
+#include "cr-sel-eng.h"
+#include "cr-node-iface.h"
+
+/**
+ *@CRSelEng:
+ *
+ *The definition of the #CRSelEng class.
+ *The #CRSelEng is actually the "Selection Engine"
+ *class. This is highly experimental for at the moment and
+ *its api is very likely to change in a near future.
+ */
+
+#define PRIVATE(a_this) (a_this)->priv
+
+struct CRPseudoClassSelHandlerEntry {
+ guchar *name;
+ enum CRPseudoType type;
+ CRPseudoClassSelectorHandler handler;
+};
+
+struct _CRSelEngPriv {
+ /*not used yet */
+ gboolean case_sensitive;
+
+ CRNodeIface const *node_iface;
+ CRStyleSheet *sheet;
+ /**
+ *where to store the next statement
+ *to be visited so that we can remember
+ *it from one method call to another.
+ */
+ CRStatement *cur_stmt;
+ GList *pcs_handlers;
+ gint pcs_handlers_size;
+} ;
+
+static gboolean class_add_sel_matches_node (CRAdditionalSel * a_add_sel,
+ CRNodeIface const * a_node_iface, CRXMLNodePtr a_node);
+
+static gboolean id_add_sel_matches_node (CRAdditionalSel * a_add_sel,
+ CRNodeIface const * a_node_iface, CRXMLNodePtr a_node);
+
+static gboolean attr_add_sel_matches_node (CRAdditionalSel * a_add_sel,
+ CRNodeIface const * a_node_iface, CRXMLNodePtr a_node);
+
+static enum CRStatus sel_matches_node_real (CRSelEng * a_this,
+ CRSimpleSel * a_sel,
+ CRXMLNodePtr a_node,
+ gboolean * a_result,
+ gboolean a_eval_sel_list_from_end,
+ gboolean a_recurse);
+
+static enum CRStatus cr_sel_eng_get_matched_rulesets_real (CRSelEng * a_this,
+ CRStyleSheet *
+ a_stylesheet,
+ CRXMLNodePtr a_node,
+ CRStatement ***
+ a_rulesets,
+ gulong * a_len,
+ gulong * a_capacity);
+
+static enum CRStatus put_css_properties_in_props_list (CRPropList ** a_props,
+ CRStatement *
+ a_ruleset);
+
+static gboolean pseudo_class_add_sel_matches_node (CRSelEng * a_this,
+ CRAdditionalSel * a_add_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean empty_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean root_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean lang_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean only_child_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean first_child_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean first_of_type_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean last_child_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean last_of_type_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean nth_child_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean nth_of_type_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean nth_last_child_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static gboolean nth_last_of_type_pseudo_class_handler (CRSelEng * a_this,
+ CRAdditionalSel * a_sel,
+ CRXMLNodePtr a_node);
+
+static CRXMLNodePtr get_next_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node);
+
+static CRXMLNodePtr get_first_child_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node);
+
+static CRXMLNodePtr get_prev_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node);
+
+static CRXMLNodePtr get_next_parent_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node);
+
+static CRArguments get_arguments_from_function (CRAdditionalSel * a_sel);
+
+void
+cr_sel_eng_set_node_iface (CRSelEng *const a_this, CRNodeIface const *const a_node_iface)
+{
+ /* Allow NULL: the caller may be just ensuring that the previous node_iface
+ value doesn't get used until next cr_sel_eng_set_node_iface call. */
+ PRIVATE(a_this)->node_iface = a_node_iface;
+}
+
+/* Quick strcmp. Test only for == 0 or != 0, not < 0 or > 0. */
+#define strqcmp(str,lit,lit_len) \
+ (strlen (str) != (lit_len) || memcmp (str, lit, lit_len))
+
+static gboolean
+root_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr parent = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "root")
+ || a_sel->content.pseudo->type != IDENT_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :root only");
+ return FALSE;
+ }
+
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+
+ // libxml apears to set the parent of the root element to an
+ // element of type 'xml'.
+ return (parent == NULL || !strcmp(node_iface->getLocalName(parent),"xml") );
+}
+
+static gboolean
+empty_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr cur_node = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "empty")
+ || a_sel->content.pseudo->type != IDENT_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :empty only");
+ return FALSE;
+ }
+ node_iface = PRIVATE(a_this)->node_iface;
+
+ cur_node = node_iface->getFirstChild (a_node);
+
+ return (cur_node == NULL);
+}
+
+static gboolean
+lang_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr a_node)
+{
+ CRNodeIface const *node_iface;
+ CRXMLNodePtr node = a_node;
+ gboolean result = FALSE;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ node_iface = PRIVATE(a_this)->node_iface;
+
+ /* "xml:lang" needed for SVG */
+ if ( (strqcmp (a_sel->content.pseudo->name->stryng->str, "lang", 4 ) &&
+ (strqcmp (a_sel->content.pseudo->name->stryng->str, "xml:lang", 8 ) ) )
+ || a_sel->content.pseudo->type != FUNCTION_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :lang only");
+ return FALSE;
+ }
+ /*lang code should exist and be at least of length 2 */
+ if (!a_sel->content.pseudo->term
+ || a_sel->content.pseudo->term->type != TERM_IDENT
+ || !a_sel->content.pseudo->term->content.str->stryng
+ || a_sel->content.pseudo->term->content.str->stryng->len < 2)
+ return FALSE;
+ for (; node; node = get_next_parent_element_node (node_iface, node)) {
+ char *val = node_iface->getProp (node, "lang");
+ if (!val) val = node_iface->getProp (node, "xml:lang");
+ if (val) {
+ if (!strcasecmp(val, a_sel->content.pseudo->term->content.str->stryng->str)) {
+ result = TRUE;
+ break;
+ }
+ node_iface->freePropVal (val);
+ val = NULL;
+ }
+ }
+
+ return result;
+}
+
+static gboolean
+only_child_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr parent = NULL;
+ CRXMLNodePtr cur_node = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "only-child")
+ || a_sel->content.pseudo->type != IDENT_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :only-child only");
+ return FALSE;
+ }
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+ if (!parent)
+ return FALSE;
+
+ cur_node = get_first_child_element_node (node_iface, parent);
+ return (cur_node == a_node &&
+ !get_next_element_node(node_iface, cur_node) );
+}
+
+static gboolean
+only_of_type_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr parent = NULL;
+ CRXMLNodePtr cur_node = NULL;
+ int m = 0;
+ int child = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "only-of-type")
+ || a_sel->content.pseudo->type != IDENT_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :only-of-type selector only");
+ return FALSE;
+ }
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+ if (!parent)
+ return FALSE;
+
+ cur_node = get_first_child_element_node (node_iface, parent);
+
+ while (cur_node) {
+ if (!strcmp(node_iface->getLocalName(cur_node), a_sel->content.pseudo->sel_name->stryng->str)) {
+ ++m;
+ }
+ if (cur_node == a_node) {
+ child = m;
+ }
+ cur_node = get_next_element_node (node_iface, cur_node);
+ }
+ return (child == m && child == 1);
+}
+
+static gboolean
+first_child_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr node = NULL;
+ CRXMLNodePtr parent = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "first-child")
+ || a_sel->content.pseudo->type != IDENT_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :first-child only");
+ return FALSE;
+ }
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+ if (!parent)
+ return FALSE;
+ node = get_first_child_element_node (node_iface, parent);
+ return (node == a_node);
+}
+
+static gboolean
+first_of_type_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr parent = NULL;
+
+ // Count which child no. of type
+ CRXMLNodePtr cur_node = NULL;
+ int child = 0;
+ int found = FALSE;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "first-of-type")
+ || a_sel->content.pseudo->type != IDENT_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :first-of-type only");
+ return FALSE;
+ }
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+ if (!parent)
+ return FALSE;
+
+ cur_node = get_first_child_element_node (node_iface, parent);
+
+ while (cur_node) {
+ if(!strcmp(node_iface->getLocalName(cur_node), a_sel->content.pseudo->sel_name->stryng->str)) {
+ child++;
+ }
+ if (cur_node == a_node) {
+ found = TRUE;
+ break;
+ }
+ cur_node = get_next_element_node (node_iface, cur_node);
+ }
+
+ if (!found)
+ return FALSE;
+
+ return (child == 1);
+}
+
+static gboolean
+last_child_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr parent = NULL;
+
+ CRXMLNodePtr cur_node = NULL;
+ int m = 0;
+ int child = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "last-child")
+ || a_sel->content.pseudo->type != IDENT_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :last-child only");
+ return FALSE;
+ }
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+ if (!parent)
+ return FALSE;
+
+ cur_node = get_first_child_element_node (node_iface, parent);
+ while (cur_node) {
+ ++m;
+ if (cur_node == a_node) {
+ child = m;
+ }
+ cur_node = get_next_element_node (node_iface, cur_node);
+
+ }
+ return (m == child);
+}
+
+static gboolean
+last_of_type_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr parent = NULL;
+
+ CRXMLNodePtr cur_node = NULL;
+ int m = 0;
+ int child = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "last-of-type")
+ || a_sel->content.pseudo->type != IDENT_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :last-of-type only");
+ return FALSE;
+ }
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+ if (!parent)
+ return FALSE;
+
+ cur_node = get_first_child_element_node (node_iface, parent);
+
+ while (cur_node) {
+ if (!strcmp(node_iface->getLocalName(cur_node), a_sel->content.pseudo->sel_name->stryng->str)) {
+ ++m;
+ }
+ if (cur_node == a_node) {
+ child = m;
+ }
+ cur_node = get_next_element_node (node_iface, cur_node);
+ }
+
+ return (m == child);
+}
+
+// See https://www.w3.org/TR/selectors/#nth-child-pseudo
+static gboolean
+nth_child_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr parent = NULL;
+
+ /* Count which child this is */
+ CRXMLNodePtr cur_node = NULL;
+ int child = 0;
+ int found = FALSE;
+ int a, b;
+ CRArguments arg;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "nth-child")
+ || a_sel->content.pseudo->type != FUNCTION_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :nth-child only");
+ return FALSE;
+ }
+
+ /*pseude code term should exist */
+ if (!a_sel->content.pseudo->term)
+ return FALSE;
+
+ arg = get_arguments_from_function (a_sel);
+
+ if (arg.a == 0 && arg.b == 0)
+ return FALSE;
+
+ a = arg.a;
+ b = arg.b;
+
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+ if (!parent)
+ return FALSE;
+
+ cur_node = get_first_child_element_node (node_iface, parent);
+
+ while (cur_node) {
+ ++child;
+ if (cur_node == a_node) {
+ found = TRUE;
+ break;
+ }
+ cur_node = get_next_element_node (node_iface, cur_node);
+ }
+
+ if (!found)
+ return FALSE;
+
+ if (a == 0)
+ return (b == child);
+
+ return ((child - b)%a == 0 && (child - b)/a > -1);
+}
+
+static gboolean
+nth_of_type_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr parent = NULL;
+
+ // Count which child no. of required type
+ CRXMLNodePtr cur_node = NULL;
+ int child = 0;
+ int found = FALSE;
+ int a, b;
+ CRArguments arg;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "nth-of-type")
+ || a_sel->content.pseudo->type != FUNCTION_PSEUDO) {
+ cr_utils_trace_info ("This handler is for :nth-of-type only");
+ return FALSE;
+ }
+
+ // pseudo code term should exist
+ if (!a_sel->content.pseudo->term)
+ return FALSE;
+
+ arg = get_arguments_from_function (a_sel);
+
+ if (arg.a == 0 && arg.b == 0)
+ return FALSE;
+
+ a = arg.a;
+ b = arg.b;
+
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+ if (!parent)
+ return FALSE;
+
+ cur_node = get_first_child_element_node (node_iface, parent);
+
+ while (cur_node) {
+ // check if type match
+ if (!strcmp(node_iface->getLocalName(cur_node), a_sel->content.pseudo->sel_name->stryng->str))
+ ++child;
+ if (cur_node == a_node) {
+ found = TRUE;
+ break;
+ }
+ cur_node = get_next_element_node (node_iface, cur_node);
+ }
+
+ if (!found)
+ return FALSE;
+
+ if (a == 0)
+ return (b == child);
+
+ return ((child - b)%a == 0 && (child - b)/a > -1);
+}
+
+static gboolean
+nth_last_child_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr parent = NULL;
+
+ /* Count which child this is (child) and total number of children (m). */
+ CRXMLNodePtr cur_node = NULL;
+ int m = 0;
+ int child = 0;
+ int found = FALSE;
+ int a, b;
+ CRArguments arg;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "nth-last-child")) {
+ cr_utils_trace_info ("This handler is for :nth-last-child only");
+ return FALSE;
+ }
+
+ /*pseudo code term should exist */
+ if (!a_sel->content.pseudo->term)
+ return FALSE;
+
+ arg = get_arguments_from_function (a_sel);
+
+ if (arg.a == 0 && arg.b == 0)
+ return FALSE;
+
+ a = arg.a;
+ b = arg.b;
+
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+
+ if (!parent) {
+ return FALSE;
+ }
+
+ cur_node = get_first_child_element_node (node_iface, parent);
+
+ while (cur_node) {
+ if (cur_node == a_node) {
+ found = TRUE;
+ child = m;
+ }
+ cur_node = get_next_element_node (node_iface,cur_node);
+ ++m;
+ }
+
+ if (!found)
+ return FALSE;
+
+ if (a == 0)
+ return ((m - b) == child);
+
+ return ((m - child - b)%a == 0 && (m - child - b)/a > -1);
+}
+
+static gboolean
+nth_last_of_type_pseudo_class_handler (CRSelEng *const a_this,
+ CRAdditionalSel * a_sel, CRXMLNodePtr const a_node)
+{
+ CRNodeIface const *node_iface = NULL;
+ CRXMLNodePtr parent = NULL;
+ CRXMLNodePtr cur_node = NULL;
+ int m = 0;
+ int child = 0;
+ int found = FALSE;
+ CRArguments arg;
+ int a, b;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_sel && a_sel->content.pseudo
+ && a_sel->content.pseudo
+ && a_sel->content.pseudo->name
+ && a_sel->content.pseudo->name->stryng
+ && a_node, FALSE);
+
+ if (strcmp (a_sel->content.pseudo->name->stryng->str, "nth-last-of-type")) {
+ cr_utils_trace_info ("This handler is for :nth-last-of-type only");
+ return FALSE;
+ }
+
+ /*pseude code term should exist */
+ if (!a_sel->content.pseudo->term)
+ return FALSE;
+
+ arg = get_arguments_from_function (a_sel);
+
+ if (arg.a == 0 && arg.b == 0)
+ return FALSE;
+
+ a = arg.a;
+ b = arg.b;
+
+ node_iface = PRIVATE(a_this)->node_iface;
+ parent = node_iface->getParentNode (a_node);
+ if (!parent) {
+ return FALSE;
+ }
+
+ cur_node = get_first_child_element_node (node_iface, parent);
+
+ while (cur_node) {
+ if (!strcmp(node_iface->getLocalName(cur_node), a_sel->content.pseudo->sel_name->stryng->str))
+ ++m;
+ if (cur_node == a_node) {
+ found = TRUE;
+ child = m;
+ }
+ cur_node = get_next_element_node (node_iface, cur_node);
+ }
+
+ if (!found)
+ return FALSE;
+
+ if (a == 0)
+ return ((m - b) == child);
+
+ return ((m - child - b +1)%a == 0 && (m - child - b +1)/a > -1);
+
+}
+
+static gboolean
+pseudo_class_add_sel_matches_node (CRSelEng * a_this,
+ CRAdditionalSel * a_add_sel,
+ CRXMLNodePtr a_node)
+{
+ enum CRStatus status = CR_OK;
+ CRPseudoClassSelectorHandler handler = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_add_sel
+ && a_add_sel->content.pseudo
+ && a_add_sel->content.pseudo->name
+ && a_add_sel->content.pseudo->name->stryng
+ && a_add_sel->content.pseudo->name->stryng->str
+ && a_node, FALSE);
+
+ status = cr_sel_eng_get_pseudo_class_selector_handler
+ (a_this, (guchar *) a_add_sel->content.pseudo->name->stryng->str,
+ a_add_sel->content.pseudo->type, &handler);
+ if (status != CR_OK || !handler)
+ return FALSE;
+
+ return handler (a_this, a_add_sel, a_node);
+}
+
+/**
+ *@param a_add_sel the class additional selector to consider.
+ *@param a_node the xml node to consider.
+ *@return TRUE if the class additional selector matches
+ *the xml node given in argument, FALSE otherwise.
+ */
+static gboolean
+class_add_sel_matches_node (CRAdditionalSel * a_add_sel,
+ CRNodeIface const * a_node_iface, CRXMLNodePtr a_node)
+{
+ gboolean result = FALSE;
+ char *klass = NULL;
+
+ g_return_val_if_fail (a_add_sel
+ && a_add_sel->type == CLASS_ADD_SELECTOR
+ && a_add_sel->content.class_name
+ && a_add_sel->content.class_name->stryng
+ && a_add_sel->content.class_name->stryng->str
+ && a_node, FALSE);
+
+ klass = a_node_iface->getProp (a_node, "class");
+ if (klass) {
+ char const *cur;
+ for (cur = klass; cur && *cur; cur++) {
+ while (cur && *cur
+ && cr_utils_is_white_space (*cur)
+ == TRUE)
+ cur++;
+
+ if (!strncmp ((const char *) cur,
+ a_add_sel->content.class_name->stryng->str,
+ a_add_sel->content.class_name->stryng->len)) {
+ cur += a_add_sel->content.class_name->stryng->len;
+ if ((cur && !*cur)
+ || cr_utils_is_white_space (*cur) == TRUE)
+ result = TRUE;
+ } else { /* if it doesn't match, */
+ /* then skip to next whitespace character to try again */
+ while (cur && *cur && !(cr_utils_is_white_space(*cur) == TRUE))
+ cur++;
+ }
+ if (cur && !*cur)
+ break ;
+ }
+ a_node_iface->freePropVal (klass);
+ klass = NULL;
+ }
+ return result;
+
+}
+
+/**
+ *@return TRUE if the additional attribute selector matches
+ *the current xml node given in argument, FALSE otherwise.
+ *@param a_add_sel the additional attribute selector to consider.
+ *@param a_node the xml node to consider.
+ */
+static gboolean
+id_add_sel_matches_node (CRAdditionalSel * a_add_sel,
+ CRNodeIface const * a_node_iface, CRXMLNodePtr a_node)
+{
+ gboolean result = FALSE;
+ char *id = NULL;
+
+ g_return_val_if_fail (a_add_sel
+ && a_add_sel->type == ID_ADD_SELECTOR
+ && a_add_sel->content.id_name
+ && a_add_sel->content.id_name->stryng
+ && a_add_sel->content.id_name->stryng->str
+ && a_node, FALSE);
+ g_return_val_if_fail (a_add_sel
+ && a_add_sel->type == ID_ADD_SELECTOR
+ && a_node, FALSE);
+
+ id = a_node_iface->getProp (a_node, "id");
+ if (id) {
+ if (!strqcmp ((const char *) id, a_add_sel->content.id_name->stryng->str,
+ a_add_sel->content.id_name->stryng->len)) {
+ result = TRUE;
+ }
+ a_node_iface->freePropVal (id);
+ id = NULL;
+ }
+ return result;
+}
+
+/**
+ *Returns TRUE if the instance of #CRAdditional selector matches
+ *the node given in parameter, FALSE otherwise.
+ *@param a_add_sel the additional selector to evaluate.
+ *@param a_node the xml node against which the selector is to
+ *be evaluated
+ *return TRUE if the additional selector matches the current xml node
+ *FALSE otherwise.
+ */
+static gboolean
+attr_add_sel_matches_node (CRAdditionalSel * a_add_sel,
+ CRNodeIface const * a_node_iface, CRXMLNodePtr a_node)
+{
+ CRAttrSel *cur_sel = NULL;
+
+ g_return_val_if_fail (a_add_sel
+ && a_add_sel->type == ATTRIBUTE_ADD_SELECTOR
+ && a_node, FALSE);
+
+ for (cur_sel = a_add_sel->content.attr_sel;
+ cur_sel; cur_sel = cur_sel->next) {
+ char *value;
+
+ if (!cur_sel->name
+ || !cur_sel->name->stryng
+ || !cur_sel->name->stryng->str)
+ return FALSE;
+
+ value = a_node_iface->getProp (a_node, cur_sel->name->stryng->str);
+ if (!value)
+ goto free_and_return_false;
+
+ switch (cur_sel->match_way) {
+ case SET:
+ break;
+
+ case EQUALS:
+ if (!cur_sel->value
+ || !cur_sel->value->stryng
+ || !cur_sel->value->stryng->str) {
+ goto free_and_return_false;
+ }
+ if (strcmp
+ (value,
+ cur_sel->value->stryng->str)) {
+ goto free_and_return_false;
+ }
+ break;
+
+ case INCLUDES:
+ {
+ char const *ptr1 = NULL,
+ *ptr2 = NULL,
+ *cur = NULL;
+ gboolean found = FALSE;
+
+ /*
+ *here, make sure value is a space
+ *separated list of "words", where one
+ *value is exactly cur_sel->value->str
+ */
+ for (cur = value; *cur; cur++) {
+ /*
+ *set ptr1 to the first non white space
+ *char addr.
+ */
+ while (cr_utils_is_white_space (*cur)
+ && *cur)
+ cur++;
+ if (!*cur)
+ break;
+ ptr1 = cur;
+
+ /*
+ *set ptr2 to the end the word.
+ */
+ while (!cr_utils_is_white_space (*cur)
+ && *cur)
+ cur++;
+ cur--;
+ ptr2 = cur;
+
+ if (!strncmp
+ ((const char *) ptr1,
+ cur_sel->value->stryng->str,
+ ptr2 - ptr1 + 1)) {
+ found = TRUE;
+ break;
+ }
+ ptr1 = ptr2 = NULL;
+ }
+
+ if (!found) {
+ goto free_and_return_false;
+ }
+ }
+ break;
+
+ case DASHMATCH:
+ {
+ char const *ptr1 = NULL,
+ *ptr2 = NULL,
+ *cur = NULL;
+ gboolean found = FALSE;
+
+ /*
+ *here, make sure value is an hyphen
+ *separated list of "words", each of which
+ *starting with "cur_sel->value->str"
+ */
+ for (cur = value; *cur; cur++) {
+ if (*cur == '-')
+ cur++;
+ ptr1 = cur;
+
+ while (*cur != '-' && *cur)
+ cur++;
+ cur--;
+ ptr2 = cur;
+
+ if (g_strstr_len
+ ((const gchar *) ptr1, ptr2 - ptr1 + 1,
+ cur_sel->value->stryng->str)
+ == ptr1) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ goto free_and_return_false;
+ }
+ }
+ break;
+ default:
+ goto free_and_return_false;
+ }
+
+ a_node_iface->freePropVal (value);
+ continue;
+
+ free_and_return_false:
+ a_node_iface->freePropVal (value);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ *Evaluates if a given additional selector matches an xml node.
+ *@param a_add_sel the additional selector to consider.
+ *@param a_node the xml node to consider.
+ *@return TRUE is a_add_sel matches a_node, FALSE otherwise.
+ */
+static gboolean
+additional_selector_matches_node (CRSelEng * a_this,
+ CRAdditionalSel * a_add_sel,
+ CRXMLNodePtr a_node)
+{
+ CRAdditionalSel *cur_add_sel = NULL, *tail = NULL ;
+ gboolean evaluated = FALSE ;
+
+ for (tail = a_add_sel ;
+ tail && tail->next;
+ tail = tail->next) ;
+
+ g_return_val_if_fail (tail, FALSE) ;
+
+ for (cur_add_sel = tail ;
+ cur_add_sel ;
+ cur_add_sel = cur_add_sel->prev) {
+
+ evaluated = TRUE ;
+ if (cur_add_sel->type == NO_ADD_SELECTOR) {
+ return FALSE;
+ }
+
+ if (cur_add_sel->type == CLASS_ADD_SELECTOR
+ && cur_add_sel->content.class_name
+ && cur_add_sel->content.class_name->stryng
+ && cur_add_sel->content.class_name->stryng->str) {
+ if (!class_add_sel_matches_node (cur_add_sel,
+ PRIVATE(a_this)->node_iface,
+ a_node)) {
+ return FALSE;
+ }
+ continue ;
+ } else if (cur_add_sel->type == ID_ADD_SELECTOR
+ && cur_add_sel->content.id_name
+ && cur_add_sel->content.id_name->stryng
+ && cur_add_sel->content.id_name->stryng->str) {
+ if (!id_add_sel_matches_node (cur_add_sel,
+ PRIVATE(a_this)->node_iface,
+ a_node)) {
+ return FALSE;
+ }
+ continue ;
+ } else if (cur_add_sel->type == ATTRIBUTE_ADD_SELECTOR
+ && cur_add_sel->content.attr_sel) {
+ /*
+ *here, call a function that does the match
+ *against an attribute additional selector
+ *and an xml node.
+ */
+ if (!attr_add_sel_matches_node (cur_add_sel,
+ PRIVATE(a_this)->node_iface,
+ a_node)) {
+ return FALSE;
+ }
+ continue ;
+ } else if (cur_add_sel->type == PSEUDO_CLASS_ADD_SELECTOR
+ && cur_add_sel->content.pseudo) {
+ if (!pseudo_class_add_sel_matches_node
+ (a_this, cur_add_sel, a_node)) {
+ return FALSE;
+ }
+ continue ;
+ }
+ }
+ if (evaluated == TRUE)
+ return TRUE;
+ return FALSE ;
+}
+
+static CRXMLNodePtr
+get_next_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node)
+{
+ CRXMLNodePtr cur_node = a_node;
+
+ g_return_val_if_fail (a_node, NULL);
+
+ do {
+ cur_node = a_node_iface->getNextSibling (cur_node);
+ } while (cur_node && !a_node_iface->isElementNode(cur_node));
+ return cur_node;
+}
+
+static CRXMLNodePtr
+get_first_child_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node)
+{
+ CRXMLNodePtr cur_node = NULL;
+
+ g_return_val_if_fail (a_node, NULL);
+
+ cur_node = a_node_iface->getFirstChild (a_node);
+ if (!cur_node)
+ return cur_node;
+ if (a_node_iface->isElementNode (cur_node))
+ return cur_node;
+ return get_next_element_node (a_node_iface, cur_node);
+}
+
+static CRXMLNodePtr
+get_prev_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node)
+{
+ CRXMLNodePtr cur_node = a_node;
+
+ g_return_val_if_fail (a_node, NULL);
+
+ do {
+ cur_node = a_node_iface->getPrevSibling (cur_node);
+ } while (cur_node && !a_node_iface->isElementNode(cur_node));
+ return cur_node;
+}
+
+static CRXMLNodePtr
+get_next_parent_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node)
+{
+ CRXMLNodePtr cur_node = a_node;
+
+ g_return_val_if_fail (a_node, NULL);
+
+ do {
+ cur_node = a_node_iface->getParentNode (cur_node);
+ } while (cur_node && !a_node_iface->isElementNode (cur_node));
+ return cur_node;
+}
+
+static CRArguments
+get_arguments_from_function (CRAdditionalSel * a_sel)
+{
+ CRArguments arg;
+ arg.a = 0;
+ arg.b = 0;
+ switch (a_sel->content.pseudo->term->type) {
+ case TERM_NUMBER:
+ if (a_sel->content.pseudo->term->content.num) {
+ arg.b = a_sel->content.pseudo->term->content.num->val;
+ }
+ if (a_sel->content.pseudo->term->n) {
+ arg.a = arg.b;
+ arg.b = 0;
+ }
+ break;
+
+ case TERM_IDENT:
+ if (a_sel->content.pseudo->term->content.str) {
+ if (!strcmp(a_sel->content.pseudo->term->content.str->stryng->str, "even")) {
+ arg.a = 2;
+ arg.b = 0;
+ } else if (!strcmp(a_sel->content.pseudo->term->content.str->stryng->str, "odd")) {
+ arg.a = 2;
+ arg.b = 1;
+ } else if (!strcmp(a_sel->content.pseudo->term->content.str->stryng->str, "n")) {
+ /* 'n' without number */
+ arg.a = 1;
+ } else if (!strcmp(a_sel->content.pseudo->term->content.str->stryng->str, "-n")) {
+ /* '-n' without number */
+ arg.a = -1;
+ } else {
+ /* Unknown string */
+ arg.a = 0;
+ arg.b = 0;
+ return (arg);
+ }
+ }
+ break;
+
+ default:
+ cr_utils_trace_info ("Unknown term in nth style handler");
+ arg.a = 0;
+ arg.b = 0;
+ return (arg);
+ }
+
+ if (arg.a != 0 && a_sel->content.pseudo->term->next) {
+ /* check for b in 'an+b' */
+ if (a_sel->content.pseudo->term->next->type == TERM_NUMBER &&
+ a_sel->content.pseudo->term->next->content.num ) {
+ arg.b = a_sel->content.pseudo->term->next->content.num->val;
+ }
+ }
+
+ return (arg);
+}
+
+/**
+ *Evaluate a selector (a simple selectors list) and says
+ *if it matches the xml node given in parameter.
+ *The algorithm used here is the following:
+ *Walk the combinator separated list of simple selectors backward, starting
+ *from the end of the list. For each simple selector, looks if
+ *if matches the current node.
+ *
+ *@param a_this the selection engine.
+ *@param a_sel the simple selection list.
+ *@param a_node the xml node.
+ *@param a_result out parameter. Set to true if the
+ *selector matches the xml node, FALSE otherwise.
+ *@param a_recurse if set to TRUE, the function will walk to
+ *the next simple selector (after the evaluation of the current one)
+ *and recursively evaluate it. Must be usually set to TRUE unless you
+ *know what you are doing.
+ */
+static enum CRStatus
+sel_matches_node_real (CRSelEng * a_this, CRSimpleSel * a_sel,
+ CRXMLNodePtr a_node, gboolean * a_result,
+ gboolean a_eval_sel_list_from_end,
+ gboolean a_recurse)
+{
+ CRSimpleSel *cur_sel = NULL;
+ CRXMLNodePtr cur_node = NULL;
+ CRNodeIface const *node_iface = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_this && a_node
+ && a_result, CR_BAD_PARAM_ERROR);
+
+ node_iface = PRIVATE(a_this)->node_iface;
+ *a_result = FALSE;
+
+ if (!node_iface->isElementNode(a_node))
+ return CR_OK;
+
+ if (a_eval_sel_list_from_end == TRUE) {
+ /*go and get the last simple selector of the list */
+ for (cur_sel = a_sel;
+ cur_sel && cur_sel->next; cur_sel = cur_sel->next) ;
+ } else {
+ cur_sel = a_sel;
+ }
+
+ for (cur_node = a_node; cur_sel; cur_sel = cur_sel->prev) {
+ if (((cur_sel->type_mask & TYPE_SELECTOR)
+ && (cur_sel->name
+ && cur_sel->name->stryng
+ && cur_sel->name->stryng->str)
+ && (!strcmp (cur_sel->name->stryng->str,
+ (const char *) node_iface->getLocalName(cur_node))))
+ || (cur_sel->type_mask & UNIVERSAL_SELECTOR)) {
+ /*
+ *this simple selector
+ *matches the current xml node
+ *Let's see if the preceding
+ *simple selectors also match
+ *their xml node counterpart.
+ */
+ if (cur_sel->add_sel) {
+ if (additional_selector_matches_node (a_this, cur_sel->add_sel,
+ cur_node) == TRUE) {
+ goto walk_a_step_in_expr;
+ } else {
+ goto done;
+ }
+ } else {
+ goto walk_a_step_in_expr;
+ }
+ }
+ if (!(cur_sel->type_mask & TYPE_SELECTOR)
+ && !(cur_sel->type_mask & UNIVERSAL_SELECTOR)) {
+ if (!cur_sel->add_sel) {
+ goto done;
+ }
+ if (additional_selector_matches_node
+ (a_this, cur_sel->add_sel, cur_node)
+ == TRUE) {
+ goto walk_a_step_in_expr;
+ } else {
+ goto done;
+ }
+ } else {
+ goto done ;
+ }
+
+ walk_a_step_in_expr:
+ if (a_recurse == FALSE) {
+ *a_result = TRUE;
+ goto done;
+ }
+
+ /*
+ *here, depending on the combinator of cur_sel
+ *choose the axis of the xml tree traversal
+ *and walk one step in the xml tree.
+ */
+ if (!cur_sel->prev)
+ break;
+
+ switch (cur_sel->combinator) {
+ case NO_COMBINATOR:
+ break;
+
+ case COMB_WS: /*descendant selector */
+ {
+ CRXMLNodePtr n = NULL;
+ enum CRStatus status = CR_OK;
+ gboolean matches = FALSE;
+
+ /*
+ *walk the xml tree upward looking for a parent
+ *node that matches the preceding selector.
+ */
+ for (n = node_iface->getParentNode (cur_node);
+ n;
+ n = node_iface->getParentNode (n)) {
+ status = sel_matches_node_real
+ (a_this, cur_sel->prev,
+ n, &matches, FALSE, TRUE);
+
+ if (status != CR_OK)
+ goto done;
+
+ if (matches == TRUE) {
+ cur_node = n ;
+ break;
+ }
+ }
+
+ if (!n) {
+ /*
+ *didn't find any ancestor that matches
+ *the previous simple selector.
+ */
+ goto done;
+ }
+ /*
+ *in this case, the preceding simple sel
+ *will have been interpreted twice, which
+ *is a cpu and mem waste ... I need to find
+ *another way to do this. Anyway, this is
+ *my first attempt to write this function and
+ *I am a bit clueless.
+ */
+ break;
+ }
+
+ case COMB_PLUS:
+ cur_node = get_prev_element_node (node_iface, cur_node);
+ if (!cur_node)
+ goto done;
+ break;
+
+ case COMB_TILDE: /* General sibling selector. */
+ {
+ CRXMLNodePtr n = NULL;
+ enum CRStatus status = CR_OK;
+ gboolean matches = FALSE;
+
+ /*
+ * Walk through previous sibing nodes looking for a
+ * node that matches the preceding selector.
+ */
+ for (n = get_prev_element_node (node_iface, cur_node);
+ n;
+ n = get_prev_element_node (node_iface, n)) {
+ status = sel_matches_node_real
+ (a_this, cur_sel->prev,
+ n, &matches, FALSE, TRUE);
+
+ if (status != CR_OK)
+ goto done;
+
+ if (matches == TRUE) {
+ cur_node = n ;
+ break;
+ }
+ }
+
+ if (!n) {
+ /*
+ * Didn't find any previous sibling that matches
+ * the previous simple selector.
+ */
+ goto done;
+ }
+ /*
+ * See note above in COMB_WS section.
+ */
+ break;
+ }
+
+ case COMB_GT:
+ cur_node = get_next_parent_element_node (node_iface, cur_node);
+ if (!cur_node)
+ goto done;
+ break;
+
+ default:
+ goto done;
+ }
+ continue;
+ }
+
+ /*
+ *if we reached this point, it means the selector matches
+ *the xml node.
+ */
+ *a_result = TRUE;
+
+ done:
+ return CR_OK;
+}
+
+
+/**
+ *Returns array of the ruleset statements that matches the
+ *given xml node.
+ *The engine keeps in memory the last statement he
+ *visited during the match. So, the next call
+ *to this function will eventually return a rulesets list starting
+ *from the last ruleset statement visited during the previous call.
+ *The enable users to get matching rulesets in an incremental way.
+ *Note that for each statement returned,
+ *the engine calculates the specificity of the selector
+ *that matched the xml node and stores it in the "specifity" field
+ *of the statement structure.
+ *
+ *@param a_sel_eng the current selection engine
+ *@param a_node the xml node for which the request
+ *is being made.
+ *@param a_sel_list the list of selectors to perform the search in.
+ *@param a_rulesets in/out parameter. A pointer to the
+ *returned array of rulesets statements that match the xml node
+ *given in parameter. The caller allocates the array before calling this
+ *function.
+ *@param a_len in/out parameter the length (in sizeof (#CRStatement*))
+ *of the returned array.
+ *(the length of a_rulesets, more precisely).
+ *The caller must set it to the length of a_ruleset prior to calling this
+ *function. In return, the function sets it to the length
+ *(in sizeof (#CRStatement)) of the actually returned CRStatement array.
+ *@return CR_OUTPUT_TOO_SHORT_ERROR if found more rulesets than the size
+ *of the a_rulesets array. In this case, the first *a_len rulesets found
+ *are put in a_rulesets, and a further call will return the following
+ *ruleset(s) following the same principle.
+ *@return CR_OK if all the rulesets found have been returned. In this
+ *case, *a_len is set to the actual number of ruleset found.
+ *@return CR_BAD_PARAM_ERROR in case any of the given parameter are
+ *bad (e.g null pointer).
+ *@return CR_ERROR if any other error occurred.
+ */
+static enum CRStatus
+cr_sel_eng_get_matched_rulesets_real (CRSelEng * a_this,
+ CRStyleSheet * a_stylesheet,
+ CRXMLNodePtr a_node,
+ CRStatement *** a_rulesets,
+ gulong * a_len,
+ gulong * a_capacity)
+{
+ CRStatement *cur_stmt = NULL;
+ CRSelector *sel_list = NULL,
+ *cur_sel = NULL;
+ gboolean matches = FALSE;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this
+ && a_stylesheet
+ && a_node && a_rulesets, CR_BAD_PARAM_ERROR);
+
+ if (!a_stylesheet->statements) {
+ return CR_OK;
+ }
+
+ /*
+ *if this stylesheet is "new one"
+ *let's remember it for subsequent calls.
+ */
+ if (PRIVATE (a_this)->sheet != a_stylesheet) {
+ PRIVATE (a_this)->sheet = a_stylesheet;
+ PRIVATE (a_this)->cur_stmt = a_stylesheet->statements;
+ }
+
+ /*
+ *walk through the list of statements and,
+ *get the selectors list inside the statements that
+ *contain some, and try to match our xml node in these
+ *selectors lists.
+ */
+ for (cur_stmt = PRIVATE (a_this)->cur_stmt;
+ (PRIVATE (a_this)->cur_stmt = cur_stmt);
+ cur_stmt = cur_stmt->next) {
+ /*
+ *initialize the selector list in which we will
+ *really perform the search.
+ */
+ sel_list = NULL;
+
+ /*
+ *get the damn selector list in
+ *which we have to look
+ */
+ switch (cur_stmt->type) {
+ case RULESET_STMT:
+ if (cur_stmt->kind.ruleset
+ && cur_stmt->kind.ruleset->sel_list) {
+ sel_list = cur_stmt->kind.ruleset->sel_list;
+ }
+ break;
+
+ case AT_MEDIA_RULE_STMT:
+ if (cur_stmt->kind.media_rule
+ && cur_stmt->kind.media_rule->rulesets
+ && cur_stmt->kind.media_rule->rulesets->
+ kind.ruleset
+ && cur_stmt->kind.media_rule->rulesets->
+ kind.ruleset->sel_list) {
+ sel_list =
+ cur_stmt->kind.media_rule->
+ rulesets->kind.ruleset->sel_list;
+ }
+ break;
+
+ case AT_IMPORT_RULE_STMT:
+ if (cur_stmt->kind.import_rule) {
+ g_assert(!cur_stmt->kind.import_rule->sheet ||
+ !cur_stmt->kind.import_rule->sheet->next);
+ cr_sel_eng_get_matched_rulesets_real (
+ a_this, cur_stmt->kind.import_rule->sheet,
+ a_node, a_rulesets,
+ a_len, a_capacity);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!sel_list)
+ continue;
+
+ /*
+ *now, we have a comma separated selector list to look in.
+ *let's walk it and try to match the xml_node
+ *on each item of the list.
+ */
+ for (cur_sel = sel_list; cur_sel; cur_sel = cur_sel->next) {
+ if (!cur_sel->simple_sel)
+ continue;
+
+ status = cr_sel_eng_matches_node
+ (a_this, cur_sel->simple_sel,
+ a_node, &matches);
+
+ if (status == CR_OK && matches == TRUE) {
+ /*
+ *bingo!!! we found one ruleset that
+ *matches that fucking node.
+ *lets put it in the out array.
+ */
+
+ if (*a_len >= *a_capacity) {
+ *a_capacity = (*a_len) + 8;
+ *a_rulesets = (CRStatement **) g_try_realloc (*a_rulesets,
+ (*a_capacity) * sizeof (CRStatement *));
+ if (!*a_rulesets) {
+ cr_utils_trace_info("Out of memory");
+ return CR_ERROR;
+ }
+ }
+
+ {
+ (*a_rulesets)[(*a_len)++] = cur_stmt;
+
+ /*
+ *For the cascade computing algorithm
+ *(which is gonna take place later)
+ *we must compute the specificity
+ *(css2 spec chap 6.4.1) of the selector
+ *that matched the current xml node
+ *and store it in the css2 statement
+ *(statement == ruleset here).
+ */
+ status = cr_simple_sel_compute_specificity (cur_sel->simple_sel);
+
+ g_return_val_if_fail (status == CR_OK,
+ CR_ERROR);
+ cur_stmt->specificity =
+ cur_sel->simple_sel->
+ specificity;
+ }
+ }
+ }
+ }
+
+ /*
+ *if we reached this point, it means
+ *we reached the end of stylesheet.
+ *no need to store any info about the stylesheet
+ *anymore.
+ */
+ g_return_val_if_fail (!PRIVATE (a_this)->cur_stmt, CR_ERROR);
+ PRIVATE (a_this)->sheet = NULL;
+ return CR_OK;
+}
+
+static enum CRStatus
+put_css_properties_in_props_list (CRPropList ** a_props, CRStatement * a_stmt)
+{
+ CRPropList *props = NULL,
+ *pair = NULL,
+ *tmp_props = NULL;
+ CRDeclaration *cur_decl = NULL;
+
+ g_return_val_if_fail (a_props && a_stmt
+ && a_stmt->type == RULESET_STMT
+ && a_stmt->kind.ruleset, CR_BAD_PARAM_ERROR);
+
+ props = *a_props;
+
+ for (cur_decl = a_stmt->kind.ruleset->decl_list;
+ cur_decl; cur_decl = cur_decl->next) {
+ CRDeclaration *decl;
+
+ decl = NULL;
+ pair = NULL;
+
+ if (!cur_decl->property
+ || !cur_decl->property->stryng
+ || !cur_decl->property->stryng->str)
+ continue;
+ /*
+ *First, test if the property is not
+ *already present in our properties list
+ *If yes, apply the cascading rules to
+ *compute the precedence. If not, insert
+ *the property into the list
+ */
+ cr_prop_list_lookup_prop (props,
+ cur_decl->property,
+ &pair);
+
+ if (!pair) {
+ tmp_props = cr_prop_list_append2
+ (props, cur_decl->property, cur_decl);
+ if (tmp_props) {
+ props = tmp_props;
+ tmp_props = NULL;
+ }
+ continue;
+ }
+
+ /*
+ *A property with the same name already exists.
+ *We must apply here
+ *some cascading rules
+ *to compute the precedence.
+ */
+ cr_prop_list_get_decl (pair, &decl);
+ g_return_val_if_fail (decl, CR_ERROR);
+
+ /*
+ *first, look at the origin.
+ *6.4.1 says:
+ *"for normal declarations,
+ *author style sheets override user
+ *style sheets which override
+ *the default style sheet."
+ */
+ if (decl->parent_statement
+ && decl->parent_statement->parent_sheet
+ && (decl->parent_statement->parent_sheet->origin
+ < a_stmt->parent_sheet->origin)) {
+ /*
+ *if the already selected declaration
+ *is marked as being !important the current
+ *declaration must not override it
+ *(unless the already selected declaration
+ *has an UA origin)
+ */
+ if (decl->important == TRUE && cur_decl->important != TRUE
+ && decl->parent_statement->parent_sheet->origin
+ != ORIGIN_UA) {
+ continue;
+ }
+ tmp_props = cr_prop_list_unlink (props, pair);
+ if (props) {
+ cr_prop_list_destroy (pair);
+ }
+ props = tmp_props;
+ tmp_props = NULL;
+ props = cr_prop_list_append2
+ (props, cur_decl->property, cur_decl);
+
+ continue;
+ } else if (decl->parent_statement
+ && decl->parent_statement->parent_sheet
+ && (decl->parent_statement->
+ parent_sheet->origin
+ > a_stmt->parent_sheet->origin)) {
+ cr_utils_trace_info
+ ("We should not reach this line\n");
+ continue;
+ }
+
+ /*
+ *A property with the same
+ *name and the same origin already exists.
+ *shit. This is lasting longer than expected ...
+ *Luckily, the spec says in 6.4.1:
+ *"more specific selectors will override
+ *more general ones"
+ *and
+ *"if two rules have the same weight,
+ *origin and specificity,
+ *the later specified wins"
+ */
+ if (a_stmt->specificity
+ >= decl->parent_statement->specificity) {
+ if (decl->important == TRUE && cur_decl->important != TRUE)
+ continue;
+ props = cr_prop_list_unlink (props, pair);
+ if (pair) {
+ cr_prop_list_destroy (pair);
+ pair = NULL;
+ }
+ props = cr_prop_list_append2 (props,
+ cur_decl->property,
+ cur_decl);
+ }
+ }
+ /*TODO: this may leak. Check this out */
+ *a_props = props;
+
+ return CR_OK;
+}
+
+static void
+set_style_from_props (CRStyle * a_style, CRPropList * a_props)
+{
+ CRPropList *cur = NULL;
+ CRDeclaration *decl = NULL;
+
+ for (cur = a_props; cur; cur = cr_prop_list_get_next (cur)) {
+ cr_prop_list_get_decl (cur, &decl);
+ cr_style_set_style_from_decl (a_style, decl);
+ decl = NULL;
+ }
+}
+
+/****************************************
+ *PUBLIC METHODS
+ ****************************************/
+
+/**
+ * cr_sel_eng_new:
+ *Creates a new instance of #CRSelEng.
+ *
+ *@a_node_iface: Node interface
+ *
+ *Returns the newly built instance of #CRSelEng of
+ *NULL if an error occurs.
+ */
+CRSelEng *
+cr_sel_eng_new (CRNodeIface const * a_node_iface)
+{
+ CRSelEng *result = NULL;
+
+ result = (CRSelEng *) g_try_malloc (sizeof (CRSelEng));
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRSelEng));
+
+ PRIVATE (result) = (CRSelEngPriv *) g_try_malloc (sizeof (CRSelEngPriv));
+ if (!PRIVATE (result)) {
+ cr_utils_trace_info ("Out of memory");
+ g_free (result);
+ return NULL;
+ }
+ memset (PRIVATE (result), 0, sizeof (CRSelEngPriv));
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "root",
+ IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ root_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "empty",
+ IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ empty_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "lang",
+ FUNCTION_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ lang_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "only-child",
+ IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ only_child_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "only-of-type",
+ IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ only_of_type_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "first-child",
+ IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ first_child_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "first-of-type",
+ IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ first_of_type_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "last-child",
+ IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ last_child_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "last-of-type",
+ IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ last_of_type_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "nth-child",
+ FUNCTION_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ nth_child_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "nth-of-type",
+ FUNCTION_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ nth_of_type_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "nth-last-child",
+ FUNCTION_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ nth_last_child_pseudo_class_handler);
+ cr_sel_eng_register_pseudo_class_sel_handler
+ (result, (guchar *) "nth-last-of-type",
+ FUNCTION_PSEUDO, /*(CRPseudoClassSelectorHandler)*/
+ nth_last_of_type_pseudo_class_handler);
+
+ cr_sel_eng_set_node_iface (result, a_node_iface);
+
+ return result;
+}
+
+/**
+ * cr_sel_eng_register_pseudo_class_sel_handler:
+ *@a_this: the current instance of #CRSelEng
+ *@a_pseudo_class_sel_name: the name of the pseudo class selector.
+ *@a_pseudo_class_type: the type of the pseudo class selector.
+ *@a_handler: the actual handler or callback to be called during
+ *the selector evaluation process.
+ *
+ *Adds a new handler entry in the handlers entry table.
+ *
+ *Returns CR_OK, upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_sel_eng_register_pseudo_class_sel_handler (CRSelEng * a_this,
+ guchar * a_name,
+ enum CRPseudoType a_type,
+ CRPseudoClassSelectorHandler
+ a_handler)
+{
+ struct CRPseudoClassSelHandlerEntry *handler_entry = NULL;
+ GList *list = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_handler && a_name, CR_BAD_PARAM_ERROR);
+
+ handler_entry = (struct CRPseudoClassSelHandlerEntry *) g_try_malloc
+ (sizeof (struct CRPseudoClassSelHandlerEntry));
+ if (!handler_entry) {
+ return CR_OUT_OF_MEMORY_ERROR;
+ }
+ memset (handler_entry, 0,
+ sizeof (struct CRPseudoClassSelHandlerEntry));
+ handler_entry->name = (guchar *) g_strdup ((const gchar *) a_name);
+ handler_entry->type = a_type;
+ handler_entry->handler = a_handler;
+ list = g_list_append (PRIVATE (a_this)->pcs_handlers, handler_entry);
+ if (!list) {
+ return CR_OUT_OF_MEMORY_ERROR;
+ }
+ PRIVATE (a_this)->pcs_handlers = list;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_sel_eng_unregister_pseudo_class_sel_handler (CRSelEng * a_this,
+ guchar * a_name,
+ enum CRPseudoType a_type)
+{
+ GList *elem = NULL,
+ *deleted_elem = NULL;
+ gboolean found = FALSE;
+ struct CRPseudoClassSelHandlerEntry *entry = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ for (elem = PRIVATE (a_this)->pcs_handlers;
+ elem; elem = g_list_next (elem)) {
+ entry = (struct CRPseudoClassSelHandlerEntry *) elem->data;
+ if (!strcmp ((const char *) entry->name, (const char *) a_name)
+ && entry->type == a_type) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (found == FALSE)
+ return CR_PSEUDO_CLASS_SEL_HANDLER_NOT_FOUND_ERROR;
+ PRIVATE (a_this)->pcs_handlers = g_list_delete_link
+ (PRIVATE (a_this)->pcs_handlers, elem);
+ entry = (struct CRPseudoClassSelHandlerEntry *) elem->data;
+ if (entry->name) {
+ g_free (entry->name);
+ entry->name = NULL;
+ }
+ g_free (elem);
+ g_list_free (deleted_elem);
+
+ return CR_OK;
+}
+
+/**
+ * cr_sel_eng_unregister_all_pseudo_class_sel_handlers:
+ *@a_this: the current instance of #CRSelEng .
+ *
+ *Unregisters all the pseudo class sel handlers
+ *and frees all the associated allocated datastructures.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_sel_eng_unregister_all_pseudo_class_sel_handlers (CRSelEng * a_this)
+{
+ GList *elem = NULL;
+ struct CRPseudoClassSelHandlerEntry *entry = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ if (!PRIVATE (a_this)->pcs_handlers)
+ return CR_OK;
+ for (elem = PRIVATE (a_this)->pcs_handlers;
+ elem; elem = g_list_next (elem)) {
+ entry = (struct CRPseudoClassSelHandlerEntry *) elem->data;
+ if (!entry)
+ continue;
+ if (entry->name) {
+ g_free (entry->name);
+ entry->name = NULL;
+ }
+ g_free (entry);
+ elem->data = NULL;
+ }
+ g_list_free (PRIVATE (a_this)->pcs_handlers);
+ PRIVATE (a_this)->pcs_handlers = NULL;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_sel_eng_get_pseudo_class_selector_handler (CRSelEng * a_this,
+ guchar * a_name,
+ enum CRPseudoType a_type,
+ CRPseudoClassSelectorHandler *
+ a_handler)
+{
+ GList *elem = NULL;
+ struct CRPseudoClassSelHandlerEntry *entry = NULL;
+ gboolean found = FALSE;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_name, CR_BAD_PARAM_ERROR);
+
+ for (elem = PRIVATE (a_this)->pcs_handlers;
+ elem; elem = g_list_next (elem)) {
+ entry = (struct CRPseudoClassSelHandlerEntry *) elem->data;
+ if (!strcmp ((const char *) a_name, (const char *) entry->name)
+ && entry->type == a_type) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (found == FALSE)
+ return CR_PSEUDO_CLASS_SEL_HANDLER_NOT_FOUND_ERROR;
+ *a_handler = entry->handler;
+ return CR_OK;
+}
+
+/**
+ * cr_sel_eng_matches_node:
+ *@a_this: the selection engine.
+ *@a_sel: the simple selector against which the xml node
+ *is going to be matched.
+ *@a_node: the node against which the selector is going to be matched.
+ *@a_result: out parameter. The result of the match. Is set to
+ *TRUE if the selector matches the node, FALSE otherwise. This value
+ *is considered if and only if this functions returns CR_OK.
+ *
+ *Evaluates a chained list of simple selectors (known as a css2 selector).
+ *Says whether if this selector matches the xml node given in parameter or
+ *not.
+ *
+ *Returns the CR_OK if the selection ran correctly, an error code otherwise.
+ */
+enum CRStatus
+cr_sel_eng_matches_node (CRSelEng * a_this, CRSimpleSel * a_sel,
+ CRXMLNodePtr a_node, gboolean * a_result)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_this && a_node
+ && a_result, CR_BAD_PARAM_ERROR);
+
+ if (!PRIVATE(a_this)->node_iface->isElementNode (a_node)) {
+ *a_result = FALSE;
+ return CR_OK;
+ }
+
+ return sel_matches_node_real (a_this, a_sel,
+ a_node, a_result,
+ TRUE, TRUE);
+}
+
+/**
+ * cr_sel_eng_get_matched_rulesets:
+ *@a_this: the current instance of the selection engine.
+ *@a_sheet: the stylesheet that holds the selectors.
+ *@a_node: the xml node to consider during the walk through
+ *the stylesheet.
+ *@a_rulesets: out parameter. A pointer to an array of
+ *rulesets statement pointers. *a_rulesets is allocated by
+ *this function and must be freed by the caller. However, the caller
+ *must not alter the rulesets statements pointer because they
+ *point to statements that are still in the css stylesheet.
+ *@a_len: the length of *a_ruleset.
+ *
+ *Returns an array of pointers to selectors that matches
+ *the xml node given in parameter.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_sel_eng_get_matched_rulesets (CRSelEng * a_this,
+ CRStyleSheet * a_sheet,
+ CRXMLNodePtr a_node,
+ CRStatement *** a_rulesets, gulong * a_len)
+{
+ CRStatement **stmts_tab = NULL;
+ enum CRStatus status = CR_OK;
+ gulong capacity = 0;
+
+ g_return_val_if_fail (a_this
+ && a_sheet
+ && a_node
+ && a_rulesets && *a_rulesets == NULL
+ && a_len, CR_BAD_PARAM_ERROR);
+
+ *a_len = 0;
+
+ status = cr_sel_eng_get_matched_rulesets_real
+ (a_this, a_sheet, a_node, &stmts_tab, a_len, &capacity);
+ if (status == CR_ERROR)
+ goto error;
+
+ *a_rulesets = stmts_tab;
+
+ return CR_OK;
+
+ error:
+
+ if (stmts_tab) {
+ g_free (stmts_tab);
+ stmts_tab = NULL;
+
+ }
+
+ *a_len = 0;
+ return status;
+}
+
+/**
+ * Like cr_sel_eng_get_matched_rulesets_real, but process an entire (linked)
+ * list of stylesheets, not only a single one.
+ */
+static
+enum CRStatus
+cr_sel_eng_process_stylesheet ( CRSelEng * a_eng,
+ CRXMLNodePtr a_node,
+ CRStyleSheet * a_stylesheet,
+ CRStatement *** stmts_tab,
+ gulong * tab_size,
+ gulong * tab_len,
+ gulong * index)
+{
+ enum CRStatus status = CR_OK;
+ CRStyleSheet *cur = NULL;
+
+ for (cur = a_stylesheet; cur && status == CR_OK; cur = cur->next) {
+ status = cr_sel_eng_get_matched_rulesets_real
+ (a_eng, cur, a_node, stmts_tab, index, tab_size);
+ }
+
+ return status;
+}
+
+enum CRStatus
+cr_sel_eng_get_matched_properties_from_cascade (CRSelEng * a_this,
+ CRCascade * a_cascade,
+ CRXMLNodePtr a_node,
+ CRPropList ** a_props)
+{
+ CRStatement **stmts_tab = NULL;
+ enum CRStatus status = CR_OK;
+ gulong tab_size = 0,
+ tab_len = 0,
+ i = 0,
+ index = 0;
+ enum CRStyleOrigin origin;
+ CRStyleSheet *sheet = NULL;
+
+ g_return_val_if_fail (a_this
+ && a_cascade
+ && a_node && a_props, CR_BAD_PARAM_ERROR);
+
+ for (origin = ORIGIN_UA; origin < NB_ORIGINS; origin = (enum CRStyleOrigin) (origin + 1)) {
+ sheet = cr_cascade_get_sheet (a_cascade, origin);
+ if (!sheet)
+ continue;
+
+ status = cr_sel_eng_process_stylesheet (a_this, a_node, sheet, &stmts_tab, &tab_size, &tab_len, &index);
+ if (status != CR_OK) {
+ cr_utils_trace_info ("Error while running "
+ "selector engine");
+ return status;
+ }
+ }
+
+ /*
+ *TODO, walk down the stmts_tab and build the
+ *property_name/declaration hashtable.
+ *Make sure one can walk from the declaration to
+ *the stylesheet.
+ */
+ for (i = 0; i < index; i++) {
+ CRStatement *stmt = stmts_tab[i];
+ if (!stmt)
+ continue;
+ switch (stmt->type) {
+ case RULESET_STMT:
+ if (!stmt->parent_sheet)
+ continue;
+ status = put_css_properties_in_props_list
+ (a_props, stmt);
+ break;
+ default:
+ break;
+ }
+
+ }
+ status = CR_OK ;
+ if (stmts_tab) {
+ g_free (stmts_tab);
+ stmts_tab = NULL;
+ }
+
+ return status;
+}
+
+enum CRStatus
+cr_sel_eng_get_matched_style (CRSelEng * a_this,
+ CRCascade * a_cascade,
+ CRXMLNodePtr a_node,
+ CRStyle * a_parent_style,
+ CRStyle ** a_style,
+ gboolean a_set_props_to_initial_values)
+{
+ enum CRStatus status = CR_OK;
+
+ CRPropList *props = NULL;
+
+ g_return_val_if_fail (a_this && a_cascade
+ && a_node && a_style, CR_BAD_PARAM_ERROR);
+
+ status = cr_sel_eng_get_matched_properties_from_cascade
+ (a_this, a_cascade, a_node, &props);
+
+ g_return_val_if_fail (status == CR_OK, status);
+ if (props) {
+ if (!*a_style) {
+ *a_style = cr_style_new (a_set_props_to_initial_values) ;
+ g_return_val_if_fail (*a_style, CR_ERROR);
+ } else {
+ if (a_set_props_to_initial_values == TRUE) {
+ cr_style_set_props_to_initial_values (*a_style) ;
+ } else {
+ cr_style_set_props_to_default_values (*a_style);
+ }
+ }
+ (*a_style)->parent_style = a_parent_style;
+
+ set_style_from_props (*a_style, props);
+ if (props) {
+ cr_prop_list_destroy (props);
+ props = NULL;
+ }
+ }
+ return CR_OK;
+}
+
+/**
+ * cr_sel_eng_destroy:
+ *@a_this: the current instance of the selection engine.
+ *
+ *The destructor of #CRSelEng
+ */
+void
+cr_sel_eng_destroy (CRSelEng * a_this)
+{
+ g_return_if_fail (a_this);
+
+ if (!PRIVATE (a_this))
+ goto end ;
+ if (PRIVATE (a_this)->pcs_handlers) {
+ cr_sel_eng_unregister_all_pseudo_class_sel_handlers
+ (a_this) ;
+ PRIVATE (a_this)->pcs_handlers = NULL ;
+ }
+ g_free (PRIVATE (a_this));
+ PRIVATE (a_this) = NULL;
+ end:
+ if (a_this) {
+ g_free (a_this);
+ }
+}
diff --git a/src/3rdparty/libcroco/src/cr-sel-eng.h b/src/3rdparty/libcroco/src/cr-sel-eng.h
new file mode 100644
index 0000000..c666f48
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-sel-eng.h
@@ -0,0 +1,118 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyrights information.
+ */
+
+#ifndef __CR_SEL_ENG_H__
+#define __CR_SEL_ENG_H__
+
+#include "cr-utils.h"
+#include "cr-stylesheet.h"
+#include "cr-cascade.h"
+#include "cr-style.h"
+#include "cr-prop-list.h"
+#include "cr-node-iface.h"
+
+/**
+ *@file:
+ *The declaration of the #CRSelEng class.
+ *The #CRSelEng is actually the "Selection Engine"
+ *class.
+ */
+
+G_BEGIN_DECLS
+
+typedef struct _CRSelEng CRSelEng ;
+typedef struct _CRSelEngPriv CRSelEngPriv ;
+typedef struct _CRArguments CRArguments ;
+
+//stores arguments of function of type an+b
+struct _CRArguments
+{
+ int a;
+ int b;
+} ;
+
+/**
+ *The Selection engine class.
+ *The main service provided by this class, is
+ *the ability to interpret a libcroco implementation
+ *of css2 selectors, and given an xml node, say if
+ *the selector matches the node or not.
+ */
+struct _CRSelEng
+{
+ CRSelEngPriv *priv ;
+} ;
+
+void cr_sel_eng_set_node_iface(CRSelEng *a_this, CRNodeIface const *);
+
+typedef gboolean (*CRPseudoClassSelectorHandler) (CRSelEng* a_this,
+ CRAdditionalSel *a_add_sel,
+ CRXMLNodePtr a_node) ;
+CRSelEng * cr_sel_eng_new (CRNodeIface const *);
+
+enum CRStatus cr_sel_eng_register_pseudo_class_sel_handler (CRSelEng *a_this,
+ guchar *a_pseudo_class_sel_name,
+ enum CRPseudoType a_pseudo_class_type,
+ CRPseudoClassSelectorHandler a_handler) ;
+
+enum CRStatus cr_sel_eng_unregister_pseudo_class_sel_handler (CRSelEng *a_this,
+ guchar *a_pseudo_class_sel_name,
+ enum CRPseudoType a_pseudo_class_type) ;
+
+enum CRStatus cr_sel_eng_unregister_all_pseudo_class_sel_handlers (CRSelEng *a_this) ;
+
+enum CRStatus cr_sel_eng_get_pseudo_class_selector_handler (CRSelEng *a_this,
+ guchar *a_pseudo_class_sel_name,
+ enum CRPseudoType a_pseudo_class_type,
+ CRPseudoClassSelectorHandler *a_handler) ;
+
+enum CRStatus cr_sel_eng_matches_node (CRSelEng *a_this,
+ CRSimpleSel *a_sel,
+ CRXMLNodePtr a_node,
+ gboolean *a_result) ;
+
+enum CRStatus cr_sel_eng_get_matched_rulesets (CRSelEng *a_this,
+ CRStyleSheet *a_sheet,
+ CRXMLNodePtr a_node,
+ CRStatement ***a_rulesets,
+ gulong *a_len) ;
+
+enum CRStatus
+cr_sel_eng_get_matched_properties_from_cascade (CRSelEng *a_this,
+ CRCascade *a_cascade,
+ CRXMLNodePtr a_node,
+ CRPropList **a_props) ;
+
+enum CRStatus cr_sel_eng_get_matched_style (CRSelEng *a_this,
+ CRCascade *a_cascade,
+ CRXMLNodePtr a_node,
+ CRStyle *a_parent_style,
+ CRStyle **a_style,
+ gboolean a_set_props_to_initial_values) ;
+
+void cr_sel_eng_destroy (CRSelEng *a_this) ;
+
+G_END_DECLS
+
+
+#endif/*__CR_SEL_ENG_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-selector.c b/src/3rdparty/libcroco/src/cr-selector.c
new file mode 100644
index 0000000..496b02c
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-selector.c
@@ -0,0 +1,333 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include <string.h>
+#include "cr-selector.h"
+#include "cr-parser.h"
+
+/**
+ * cr_selector_new:
+ *
+ *@a_simple_sel: the initial simple selector list
+ *of the current instance of #CRSelector.
+ *
+ *Creates a new instance of #CRSelector.
+ *
+ *Returns the newly built instance of #CRSelector, or
+ *NULL in case of failure.
+ */
+CRSelector *
+cr_selector_new (CRSimpleSel * a_simple_sel)
+{
+ CRSelector *result = NULL;
+
+ result = (CRSelector *) g_try_malloc (sizeof (CRSelector));
+
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRSelector));
+ result->simple_sel = a_simple_sel;
+ return result;
+}
+
+/**
+ * cr_selector_parse_from_buf:
+ *
+ *@a_char_buf: the buffer to parse.
+ *@a_enc: the encoding of the input buffer a_char_buf.
+ *
+ *Parses a buf for selectors.
+ *
+ *Fix Me: parsing will fail for some cases if buf does not end with '{'.
+ *
+ *Returns the newly built instance of #CRSelector, or
+ *NULL in case of failure.
+ */
+CRSelector *
+cr_selector_parse_from_buf (const guchar * a_char_buf, enum CREncoding a_enc)
+{
+ CRParser *parser = NULL;
+ CRSelector *selector = NULL;
+ enum CRStatus status;
+
+ g_return_val_if_fail (a_char_buf, NULL);
+
+ parser = cr_parser_new_from_buf ((guchar*)a_char_buf, strlen ((const char *) a_char_buf),
+ a_enc, FALSE);
+ g_return_val_if_fail (parser, NULL);
+
+ status = cr_parser_parse_selector (parser, &selector);
+
+ if (status != CR_OK) {
+ if (selector) {
+ cr_selector_unref (selector);
+ selector = NULL;
+ }
+ }
+
+ cr_parser_destroy(parser);
+
+ return selector;
+}
+
+/**
+ * cr_selector_append:
+ *
+ *@a_this: the current instance of #CRSelector.
+ *@a_new: the instance of #CRSelector to be appended.
+ *
+ *Appends a new instance of #CRSelector to the current selector list.
+ *
+ *Returns the new list.
+ */
+CRSelector *
+cr_selector_append (CRSelector * a_this, CRSelector * a_new)
+{
+ CRSelector *cur = NULL;
+
+ if (!a_this) {
+ return a_new;
+ }
+
+ /*walk forward the list headed by a_this to get the list tail */
+ for (cur = a_this; cur && cur->next; cur = cur->next) ;
+
+ cur->next = a_new;
+ a_new->prev = cur;
+
+ return a_this;
+}
+
+/**
+ * cr_selector_prepend:
+ *
+ *@a_this: the current instance of #CRSelector list.
+ *@a_new: the instance of #CRSelector.
+ *
+ *Prepends an element to the #CRSelector list.
+ *
+ *Returns the new list.
+ */
+CRSelector *
+cr_selector_prepend (CRSelector * a_this, CRSelector * a_new)
+{
+ CRSelector *cur = NULL;
+
+ a_new->next = a_this;
+ a_this->prev = a_new;
+
+ for (cur = a_new; cur && cur->prev; cur = cur->prev) ;
+
+ return cur;
+}
+
+/**
+ * cr_selector_append_simple_sel:
+ *
+ *@a_this: the current instance of #CRSelector.
+ *@a_simple_sel: the simple selector to append.
+ *
+ *append a simple selector to the current #CRSelector list.
+ *
+ *Returns the new list or NULL in case of failure.
+ */
+CRSelector *
+cr_selector_append_simple_sel (CRSelector * a_this,
+ CRSimpleSel * a_simple_sel)
+{
+ CRSelector *selector = NULL;
+
+ selector = cr_selector_new (a_simple_sel);
+ g_return_val_if_fail (selector, NULL);
+
+ return cr_selector_append (a_this, selector);
+}
+
+guchar *
+cr_selector_to_string (CRSelector const * a_this)
+{
+ guchar *result = NULL;
+ GString *str_buf = NULL;
+
+ str_buf = (GString *) g_string_new (NULL);
+ g_return_val_if_fail (str_buf, NULL);
+
+ if (a_this) {
+ CRSelector const *cur = NULL;
+
+ for (cur = a_this; cur; cur = cur->next) {
+ if (cur->simple_sel) {
+ guchar *tmp_str = NULL;
+
+ tmp_str = cr_simple_sel_to_string
+ (cur->simple_sel);
+
+ if (tmp_str) {
+ if (cur->prev)
+ g_string_append (str_buf,
+ ", ");
+
+ g_string_append (str_buf, (const gchar *) tmp_str);
+
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+ }
+ }
+
+ if (str_buf) {
+ result = (guchar *) str_buf->str;
+ g_string_free (str_buf, FALSE);
+ str_buf = NULL;
+ }
+
+ return result;
+}
+
+/**
+ * cr_selector_dump:
+ *
+ *@a_this: the current instance of #CRSelector.
+ *@a_fp: the destination file.
+ *
+ *Serializes the current instance of #CRSelector to a file.
+ */
+void
+cr_selector_dump (CRSelector const * a_this, FILE * a_fp)
+{
+ guchar *tmp_buf = NULL;
+
+ if (a_this) {
+ tmp_buf = cr_selector_to_string (a_this);
+ if (tmp_buf) {
+ fprintf (a_fp, "%s", tmp_buf);
+ g_free (tmp_buf);
+ tmp_buf = NULL;
+ }
+ }
+}
+
+/**
+ * cr_selector_ref:
+ *
+ *@a_this: the current instance of #CRSelector.
+ *
+ *Increments the ref count of the current instance
+ *of #CRSelector.
+ */
+void
+cr_selector_ref (CRSelector * a_this)
+{
+ g_return_if_fail (a_this);
+
+ a_this->ref_count++;
+}
+
+/**
+ * cr_selector_unref:
+ *
+ *@a_this: the current instance of #CRSelector.
+ *
+ *Decrements the ref count of the current instance of
+ *#CRSelector.
+ *If the ref count reaches zero, the current instance of
+ *#CRSelector is destroyed.
+ *
+ *Returns TRUE if this function destroyed the current instance
+ *of #CRSelector, FALSE otherwise.
+ */
+gboolean
+cr_selector_unref (CRSelector * a_this)
+{
+ g_return_val_if_fail (a_this, FALSE);
+
+ if (a_this->ref_count) {
+ a_this->ref_count--;
+ }
+
+ if (a_this->ref_count == 0) {
+ cr_selector_destroy (a_this);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * cr_selector_destroy:
+ *
+ *@a_this: the current instance of #CRSelector.
+ *
+ *Destroys the selector list.
+ */
+void
+cr_selector_destroy (CRSelector * a_this)
+{
+ CRSelector *cur = NULL;
+
+ g_return_if_fail (a_this);
+
+ /*
+ *go and get the list tail. In the same time, free
+ *all the simple selectors contained in the list.
+ */
+ for (cur = a_this; cur && cur->next; cur = cur->next) {
+ if (cur->simple_sel) {
+ cr_simple_sel_destroy (cur->simple_sel);
+ cur->simple_sel = NULL;
+ }
+ }
+
+ if (cur) {
+ if (cur->simple_sel) {
+ cr_simple_sel_destroy (cur->simple_sel);
+ cur->simple_sel = NULL;
+ }
+ }
+
+ /*in case the list has only one element */
+ if (cur && !cur->prev) {
+ g_free (cur);
+ return;
+ }
+
+ /*walk backward the list and free each "next element" */
+ for (cur = cur->prev; cur && cur->prev; cur = cur->prev) {
+ if (cur->next) {
+ g_free (cur->next);
+ cur->next = NULL;
+ }
+ }
+
+ if (!cur)
+ return;
+
+ if (cur->next) {
+ g_free (cur->next);
+ cur->next = NULL;
+ }
+
+ g_free (cur);
+}
diff --git a/src/3rdparty/libcroco/src/cr-selector.h b/src/3rdparty/libcroco/src/cr-selector.h
new file mode 100644
index 0000000..a7e0295
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-selector.h
@@ -0,0 +1,95 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#ifndef __CR_SELECTOR_H__
+#define __CR_SELECTOR_H__
+
+#include <stdio.h>
+#include "cr-utils.h"
+#include "cr-simple-sel.h"
+#include "cr-parsing-location.h"
+
+/**
+ *@file
+ *The declaration file of the #CRSelector file.
+ */
+
+G_BEGIN_DECLS
+
+typedef struct _CRSelector CRSelector ;
+
+/**
+ *Abstracts a CSS2 selector as defined in the right part
+ *of the 'ruleset' production in the appendix D.1 of the
+ *css2 spec.
+ *It is actually the abstraction of a comma separated list
+ *of simple selectors list.
+ *In a css2 file, a selector is a list of simple selectors
+ *separated by a comma.
+ *e.g: sel0, sel1, sel2 ...
+ *Each seln is a simple selector
+ */
+struct _CRSelector
+{
+ /**
+ *A Selection expression.
+ *It is a list of basic selectors.
+ *Each basic selector can be either an element
+ *selector, an id selector, a class selector, an
+ *attribute selector, an universal selector etc ...
+ */
+ CRSimpleSel *simple_sel ;
+
+ /**The next selector list element*/
+ CRSelector *next ;
+ CRSelector *prev ;
+ CRParsingLocation location ;
+ glong ref_count ;
+};
+
+CRSelector* cr_selector_new (CRSimpleSel *a_sel_expr) ;
+
+CRSelector * cr_selector_parse_from_buf (const guchar * a_char_buf,
+ enum CREncoding a_enc) ;
+
+CRSelector* cr_selector_append (CRSelector *a_this, CRSelector *a_new) ;
+
+CRSelector* cr_selector_append_simple_sel (CRSelector *a_this,
+ CRSimpleSel *a_simple_sel) ;
+
+CRSelector* cr_selector_prepend (CRSelector *a_this, CRSelector *a_new) ;
+
+guchar * cr_selector_to_string (CRSelector const *a_this) ;
+
+void cr_selector_dump (CRSelector const *a_this, FILE *a_fp) ;
+
+void cr_selector_ref (CRSelector *a_this) ;
+
+gboolean cr_selector_unref (CRSelector *a_this) ;
+
+void cr_selector_destroy (CRSelector *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_SELECTOR_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-simple-sel.c b/src/3rdparty/libcroco/src/cr-simple-sel.c
new file mode 100644
index 0000000..095c159
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-simple-sel.c
@@ -0,0 +1,322 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include <string.h>
+#include <glib.h>
+#include "cr-simple-sel.h"
+
+/**
+ * cr_simple_sel_new:
+ *
+ *The constructor of #CRSimpleSel.
+ *
+ *Returns the new instance of #CRSimpleSel.
+ */
+CRSimpleSel *
+cr_simple_sel_new (void)
+{
+ CRSimpleSel *result = NULL;
+
+ result = (CRSimpleSel *) g_try_malloc (sizeof (CRSimpleSel));
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRSimpleSel));
+
+ return result;
+}
+
+/**
+ * cr_simple_sel_append_simple_sel:
+ *
+ *Appends a simpe selector to the current list of simple selector.
+ *
+ *@a_this: the this pointer of the current instance of #CRSimpleSel.
+ *@a_sel: the simple selector to append.
+ *
+ *Returns: the new list upon successful completion, an error code otherwise.
+ */
+CRSimpleSel *
+cr_simple_sel_append_simple_sel (CRSimpleSel * a_this, CRSimpleSel * a_sel)
+{
+ CRSimpleSel *cur = NULL;
+
+ g_return_val_if_fail (a_sel, NULL);
+
+ if (a_this == NULL)
+ return a_sel;
+
+ for (cur = a_this; cur->next; cur = cur->next) ;
+
+ cur->next = a_sel;
+ a_sel->prev = cur;
+
+ return a_this;
+}
+
+/**
+ * cr_simple_sel_prepend_simple_sel:
+ *
+ *@a_this: the this pointer of the current instance of #CRSimpleSel.
+ *@a_sel: the simple selector to prepend.
+ *
+ *Prepends a simple selector to the current list of simple selectors.
+ *
+ *Returns the new list upon successful completion, an error code otherwise.
+ */
+CRSimpleSel *
+cr_simple_sel_prepend_simple_sel (CRSimpleSel * a_this, CRSimpleSel * a_sel)
+{
+ g_return_val_if_fail (a_sel, NULL);
+
+ if (a_this == NULL)
+ return a_sel;
+
+ a_sel->next = a_this;
+ a_this->prev = a_sel;
+
+ return a_sel;
+}
+
+guchar *
+cr_simple_sel_to_string (CRSimpleSel const * a_this)
+{
+ GString *str_buf = NULL;
+ guchar *result = NULL;
+
+ CRSimpleSel const *cur = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ str_buf = g_string_new (NULL);
+ for (cur = a_this; cur; cur = cur->next) {
+ if (cur->name) {
+ gchar const *str = cur->name->stryng->str;
+
+ if (str) {
+ switch (cur->combinator) {
+ case COMB_WS:
+ g_string_append (str_buf, " ");
+ break;
+
+ case COMB_PLUS:
+ g_string_append (str_buf, "+");
+ break;
+
+ case COMB_TILDE:
+ g_string_append (str_buf, "~");
+ break;
+
+ case COMB_GT:
+ g_string_append (str_buf, ">");
+ break;
+
+ default:
+ break;
+ }
+
+ g_string_append (str_buf, (const gchar *) str);
+ }
+ }
+
+ if (cur->add_sel) {
+ guchar *tmp_str = NULL;
+
+ tmp_str = cr_additional_sel_to_string (cur->add_sel);
+ if (tmp_str) {
+ g_string_append (str_buf, (const gchar *) tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+ }
+
+ if (str_buf) {
+ result = (guchar *) str_buf->str;
+ g_string_free (str_buf, FALSE);
+ str_buf = NULL;
+ }
+
+ return result;
+}
+
+
+guchar *
+cr_simple_sel_one_to_string (CRSimpleSel const * a_this)
+{
+ GString *str_buf = NULL;
+ guchar *result = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ str_buf = g_string_new (NULL);
+ if (a_this->name) {
+ gchar const *str = a_this->name->stryng->str;
+
+ if (str) {
+ g_string_append_printf (str_buf, "%s", str);
+ }
+ }
+
+ if (a_this->add_sel) {
+ guchar *tmp_str = NULL;
+
+ tmp_str = cr_additional_sel_to_string (a_this->add_sel);
+ if (tmp_str) {
+ g_string_append_printf
+ (str_buf, "%s", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+
+ if (str_buf) {
+ result = (guchar *) str_buf->str;
+ g_string_free (str_buf, FALSE);
+ str_buf = NULL;
+ }
+
+ return result;
+}
+
+/**
+ * cr_simple_sel_dump:
+ *@a_this: the current instance of #CRSimpleSel.
+ *@a_fp: the destination file pointer.
+ *
+ *Dumps the selector to a file.
+ *TODO: add the support of unicode in the dump.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_simple_sel_dump (CRSimpleSel const * a_this, FILE * a_fp)
+{
+ guchar *tmp_str = NULL;
+
+ g_return_val_if_fail (a_fp, CR_BAD_PARAM_ERROR);
+
+ if (a_this) {
+ tmp_str = cr_simple_sel_to_string (a_this);
+ if (tmp_str) {
+ fprintf (a_fp, "%s", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+
+ return CR_OK;
+}
+
+/**
+ * cr_simple_sel_compute_specificity:
+ *
+ *@a_this: the current instance of #CRSimpleSel
+ *
+ *Computes the selector (combinator separated list of simple selectors)
+ *as defined in the css2 spec in chapter 6.4.3
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_simple_sel_compute_specificity (CRSimpleSel * a_this)
+{
+ CRAdditionalSel const *cur_add_sel = NULL;
+ CRSimpleSel const *cur_sel = NULL;
+ gulong a = 0,
+ b = 0,
+ c = 0;
+
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ for (cur_sel = a_this; cur_sel; cur_sel = cur_sel->next) {
+ if (cur_sel->type_mask & TYPE_SELECTOR) {
+ c++; /*hmmh, is this a new language ? */
+ } else if (!cur_sel->name
+ || !cur_sel->name->stryng
+ || !cur_sel->name->stryng->str) {
+ if (cur_sel->add_sel->type ==
+ PSEUDO_CLASS_ADD_SELECTOR) {
+ /*
+ *this is a pseudo element, and
+ *the spec says, "ignore pseudo elements".
+ */
+ continue;
+ }
+ }
+
+ for (cur_add_sel = cur_sel->add_sel;
+ cur_add_sel; cur_add_sel = cur_add_sel->next) {
+ switch (cur_add_sel->type) {
+ case ID_ADD_SELECTOR:
+ a++;
+ break;
+
+ case NO_ADD_SELECTOR:
+ continue;
+
+ default:
+ b++;
+ break;
+ }
+ }
+ }
+
+ /*we suppose a, b and c have 1 to 3 digits */
+ a_this->specificity = a * 1000000 + b * 1000 + c;
+
+ return CR_OK;
+}
+
+/**
+ * cr_simple_sel_destroy:
+ *
+ *@a_this: the this pointer of the current instance of #CRSimpleSel.
+ *
+ *The destructor of the current instance of
+ *#CRSimpleSel. Recursively calls the destructor of #CRSimpleSel->next
+ */
+void
+cr_simple_sel_destroy (CRSimpleSel * const a_this)
+{
+ g_return_if_fail (a_this);
+
+ if (a_this->name) {
+ cr_string_destroy (a_this->name);
+ a_this->name = NULL;
+ }
+
+ if (a_this->add_sel) {
+ cr_additional_sel_destroy (a_this->add_sel);
+ a_this->add_sel = NULL;
+ }
+
+ if (a_this->next) {
+ cr_simple_sel_destroy (a_this->next);
+ a_this->next = NULL;
+ }
+
+ g_free (a_this);
+}
diff --git a/src/3rdparty/libcroco/src/cr-simple-sel.h b/src/3rdparty/libcroco/src/cr-simple-sel.h
new file mode 100644
index 0000000..e53f587
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-simple-sel.h
@@ -0,0 +1,131 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+
+#ifndef __CR_SEL_H__
+#define __CR_SEL_H__
+
+#include <stdio.h>
+#include <glib.h>
+#include "cr-additional-sel.h"
+#include "cr-parsing-location.h"
+
+G_BEGIN_DECLS
+
+/**
+ *@file
+ *the declaration of the #CRSimpleSel class.
+ *
+ */
+enum Combinator
+{
+ NO_COMBINATOR,
+ COMB_WS, /*whitespace: descendent*/
+ COMB_PLUS, /*'+': immediately preceded by*/
+ COMB_TILDE, /*'~': preceded by, CSS 3*/
+ COMB_GT /*greater than ('>'): child*/
+} ;
+
+enum SimpleSelectorType
+{
+ NO_SELECTOR_TYPE = 0,
+ UNIVERSAL_SELECTOR = 1,
+ TYPE_SELECTOR = 1 << 1
+} ;
+
+typedef struct _CRSimpleSel CRSimpleSel ;
+
+/**
+ *The abstraction of a css2 simple selection list
+ *as defined by the right part of the "selector" production in the
+ *appendix D.1 of the css2 spec.
+ *It is basically a list of simple selector, each
+ *simple selector being separated by a combinator.
+ *
+ *In the libcroco's implementation, each simple selector
+ *is made of at most two parts:
+ *
+ *1/An element name or 'type selector' (which can hold a '*' and
+ *then been called 'universal selector')
+ *
+ *2/An additional selector that "specializes" the preceding type or
+ *universal selector. The additional selector can be either
+ *an id selector, or a class selector, or an attribute selector.
+ */
+struct _CRSimpleSel
+{
+ enum SimpleSelectorType type_mask ;
+ gboolean is_case_sentive ;
+ CRString * name ;
+ /**
+ *The combinator that separates
+ *this simple selector from the previous
+ *one.
+ */
+ enum Combinator combinator ;
+
+ /**
+ *The additional selector list of the
+ *current simple selector.
+ *An additional selector may
+ *be a class selector, an id selector,
+ *or an attribute selector.
+ *Note that this field is a linked list.
+ */
+ CRAdditionalSel *add_sel ;
+
+ /*
+ *the specificity as specified by
+ *chapter 6.4.3 of the spec.
+ */
+ gulong specificity ;
+
+ CRSimpleSel *next ;
+ CRSimpleSel *prev ;
+ CRParsingLocation location ;
+} ;
+
+CRSimpleSel * cr_simple_sel_new (void) ;
+
+CRSimpleSel * cr_simple_sel_append_simple_sel (CRSimpleSel *a_this,
+ CRSimpleSel *a_sel) ;
+
+CRSimpleSel * cr_simple_sel_prepend_simple_sel (CRSimpleSel *a_this,
+ CRSimpleSel *a_sel) ;
+
+guchar * cr_simple_sel_to_string (CRSimpleSel const *a_this) ;
+
+guchar * cr_simple_sel_one_to_string (CRSimpleSel const * a_this) ;
+
+enum CRStatus cr_simple_sel_dump (CRSimpleSel const *a_this, FILE *a_fp) ;
+
+enum CRStatus cr_simple_sel_dump_attr_sel_list (CRSimpleSel const *a_this) ;
+
+enum CRStatus cr_simple_sel_compute_specificity (CRSimpleSel *a_this) ;
+
+void cr_simple_sel_destroy (CRSimpleSel *a_this) ;
+
+G_END_DECLS
+
+
+#endif /*__CR_SIMPLE_SEL_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-statement.c b/src/3rdparty/libcroco/src/cr-statement.c
new file mode 100644
index 0000000..d624e9f
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-statement.c
@@ -0,0 +1,2810 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli.
+ * See COPYRIGHTS files for copyrights information.
+ */
+
+#include <string.h>
+#include "cr-statement.h"
+#include "cr-parser.h"
+
+/**
+ *@file
+ *Definition of the #CRStatement class.
+ */
+
+#define DECLARATION_INDENT_NB 2
+
+static void cr_statement_clear (CRStatement * a_this);
+
+static void
+parse_font_face_start_font_face_cb (CRDocHandler * a_this,
+ CRParsingLocation *a_location)
+{
+ CRStatement *stmt = NULL;
+ enum CRStatus status = CR_OK;
+
+ (void) a_location;
+
+ stmt = cr_statement_new_at_font_face_rule (NULL, NULL);
+ g_return_if_fail (stmt);
+
+ status = cr_doc_handler_set_ctxt (a_this, stmt);
+ g_return_if_fail (status == CR_OK);
+}
+
+static void
+parse_font_face_unrecoverable_error_cb (CRDocHandler * a_this)
+{
+ CRStatement *stmt = NULL;
+ CRStatement **stmtptr = NULL;
+ enum CRStatus status = CR_OK;
+
+ g_return_if_fail (a_this);
+
+ stmtptr = &stmt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr);
+ if (status != CR_OK) {
+ cr_utils_trace_info ("Couldn't get parsing context. "
+ "This may lead to some memory leaks.");
+ return;
+ }
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ cr_doc_handler_set_ctxt (a_this, NULL);
+ return;
+ }
+}
+
+static void
+parse_font_face_property_cb (CRDocHandler * a_this,
+ CRString * a_name,
+ CRTerm * a_value, gboolean a_important)
+{
+ enum CRStatus status = CR_OK;
+ CRString *name = NULL;
+ CRDeclaration *decl = NULL;
+ CRStatement *stmt = NULL;
+ CRStatement **stmtptr = NULL;
+
+ (void) a_important;
+
+ g_return_if_fail (a_this && a_name);
+
+ stmtptr = &stmt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr);
+ g_return_if_fail (status == CR_OK && stmt);
+ g_return_if_fail (stmt->type == AT_FONT_FACE_RULE_STMT);
+
+ name = cr_string_dup (a_name) ;
+ g_return_if_fail (name);
+ decl = cr_declaration_new (stmt, name, a_value);
+ if (!decl) {
+ cr_utils_trace_info ("cr_declaration_new () failed.");
+ goto error;
+ }
+ name = NULL;
+
+ stmt->kind.font_face_rule->decl_list =
+ cr_declaration_append (stmt->kind.font_face_rule->decl_list,
+ decl);
+ if (!stmt->kind.font_face_rule->decl_list)
+ goto error;
+ decl = NULL;
+
+ error:
+ if (decl) {
+ cr_declaration_unref (decl);
+ decl = NULL;
+ }
+ if (name) {
+ cr_string_destroy (name);
+ name = NULL;
+ }
+}
+
+static void
+parse_font_face_end_font_face_cb (CRDocHandler * a_this)
+{
+ CRStatement *result = NULL;
+ CRStatement **resultptr = NULL;
+ enum CRStatus status = CR_OK;
+
+ g_return_if_fail (a_this);
+
+ resultptr = &result;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) resultptr);
+ g_return_if_fail (status == CR_OK && result);
+ g_return_if_fail (result->type == AT_FONT_FACE_RULE_STMT);
+
+ status = cr_doc_handler_set_result (a_this, result);
+ g_return_if_fail (status == CR_OK);
+}
+
+static void
+parse_page_start_page_cb (CRDocHandler * a_this,
+ CRString * a_name,
+ CRString * a_pseudo_page,
+ CRParsingLocation *a_location)
+{
+ CRStatement *stmt = NULL;
+ enum CRStatus status = CR_OK;
+ CRString *page_name = NULL, *pseudo_name = NULL ;
+
+ (void) a_location;
+
+ if (a_name)
+ page_name = cr_string_dup (a_name) ;
+ if (a_pseudo_page)
+ pseudo_name = cr_string_dup (a_pseudo_page) ;
+
+ stmt = cr_statement_new_at_page_rule (NULL, NULL,
+ page_name,
+ pseudo_name);
+ page_name = NULL ;
+ pseudo_name = NULL ;
+ g_return_if_fail (stmt);
+ status = cr_doc_handler_set_ctxt (a_this, stmt);
+ g_return_if_fail (status == CR_OK);
+}
+
+static void
+parse_page_unrecoverable_error_cb (CRDocHandler * a_this)
+{
+ CRStatement *stmt = NULL;
+ CRStatement **stmtptr = NULL;
+ enum CRStatus status = CR_OK;
+
+ g_return_if_fail (a_this);
+
+ stmtptr = &stmt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr);
+ if (status != CR_OK) {
+ cr_utils_trace_info ("Couldn't get parsing context. "
+ "This may lead to some memory leaks.");
+ return;
+ }
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ cr_doc_handler_set_ctxt (a_this, NULL);
+ }
+}
+
+static void
+parse_page_property_cb (CRDocHandler * a_this,
+ CRString * a_name,
+ CRTerm * a_expression, gboolean a_important)
+{
+ CRString *name = NULL;
+ CRStatement *stmt = NULL;
+ CRStatement **stmtptr = NULL;
+ CRDeclaration *decl = NULL;
+ enum CRStatus status = CR_OK;
+
+ stmtptr = &stmt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr);
+ g_return_if_fail (status == CR_OK && stmt->type == AT_PAGE_RULE_STMT);
+
+ name = cr_string_dup (a_name);
+ g_return_if_fail (name);
+
+ decl = cr_declaration_new (stmt, name, a_expression);
+ if (!decl)
+ cr_string_destroy(name);
+ g_return_if_fail (decl);
+ decl->important = a_important;
+ stmt->kind.page_rule->decl_list =
+ cr_declaration_append (stmt->kind.page_rule->decl_list, decl);
+ g_return_if_fail (stmt->kind.page_rule->decl_list);
+}
+
+static void
+parse_page_end_page_cb (CRDocHandler * a_this,
+ CRString * a_name,
+ CRString * a_pseudo_page)
+{
+ enum CRStatus status = CR_OK;
+ CRStatement *stmt = NULL;
+ CRStatement **stmtptr = NULL;
+
+ (void) a_name;
+ (void) a_pseudo_page;
+
+ stmtptr = &stmt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr);
+ g_return_if_fail (status == CR_OK && stmt);
+ g_return_if_fail (stmt->type == AT_PAGE_RULE_STMT);
+
+ status = cr_doc_handler_set_result (a_this, stmt);
+ g_return_if_fail (status == CR_OK);
+}
+
+static void
+parse_at_media_start_media_cb (CRDocHandler * a_this,
+ GList * a_media_list,
+ CRParsingLocation *a_location)
+{
+ enum CRStatus status = CR_OK;
+ CRStatement *at_media = NULL;
+ GList *media_list = NULL;
+
+ (void) a_location;
+
+ g_return_if_fail (a_this && a_this->priv);
+
+ if (a_media_list) {
+ /*duplicate media list */
+ media_list = cr_utils_dup_glist_of_cr_string
+ (a_media_list);
+ }
+
+ g_return_if_fail (media_list);
+
+ /*make sure cr_statement_new_at_media_rule works in this case. */
+ at_media = cr_statement_new_at_media_rule (NULL, NULL, media_list);
+
+ status = cr_doc_handler_set_ctxt (a_this, at_media);
+ g_return_if_fail (status == CR_OK);
+ status = cr_doc_handler_set_result (a_this, at_media);
+ g_return_if_fail (status == CR_OK);
+}
+
+static void
+parse_at_media_unrecoverable_error_cb (CRDocHandler * a_this)
+{
+ enum CRStatus status = CR_OK;
+ CRStatement *stmt = NULL;
+ CRStatement **stmtptr = NULL;
+
+ g_return_if_fail (a_this);
+
+ stmtptr = &stmt;
+ status = cr_doc_handler_get_result (a_this, (gpointer *) stmtptr);
+ if (status != CR_OK) {
+ cr_utils_trace_info ("Couldn't get parsing context. "
+ "This may lead to some memory leaks.");
+ return;
+ }
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ cr_doc_handler_set_ctxt (a_this, NULL);
+ cr_doc_handler_set_result (a_this, NULL);
+ }
+}
+
+static void
+parse_at_media_start_selector_cb (CRDocHandler * a_this,
+ CRSelector * a_sellist)
+{
+ enum CRStatus status = CR_OK;
+ CRStatement *at_media = NULL;
+ CRStatement **at_media_ptr = NULL;
+ CRStatement *ruleset = NULL;
+
+ g_return_if_fail (a_this && a_this->priv && a_sellist);
+
+ at_media_ptr = &at_media;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) at_media_ptr);
+ g_return_if_fail (status == CR_OK && at_media);
+ g_return_if_fail (at_media->type == AT_MEDIA_RULE_STMT);
+ ruleset = cr_statement_new_ruleset (NULL, a_sellist, NULL, at_media);
+ g_return_if_fail (ruleset);
+ status = cr_doc_handler_set_ctxt (a_this, ruleset);
+ g_return_if_fail (status == CR_OK);
+}
+
+static void
+parse_at_media_property_cb (CRDocHandler * a_this,
+ CRString * a_name, CRTerm * a_value,
+ gboolean a_important)
+{
+ enum CRStatus status = CR_OK;
+
+ /*
+ *the current ruleset stmt, child of the
+ *current at-media being parsed.
+ */
+ CRStatement *stmt = NULL;
+ CRStatement **stmtptr = NULL;
+ CRDeclaration *decl = NULL;
+ CRString *name = NULL;
+
+ g_return_if_fail (a_this && a_name);
+
+ stmtptr = &stmt;
+ status = cr_doc_handler_get_ctxt (a_this,
+ (gpointer *) stmtptr);
+ g_return_if_fail (status == CR_OK && stmt);
+ g_return_if_fail (stmt->type == RULESET_STMT);
+
+ name = cr_string_dup (a_name) ;
+ g_return_if_fail (name);
+
+ decl = cr_declaration_new (stmt, name, a_value);
+ if (!decl)
+ cr_string_destroy(name);
+ g_return_if_fail (decl);
+ decl->important = a_important;
+ status = cr_statement_ruleset_append_decl (stmt, decl);
+ g_return_if_fail (status == CR_OK);
+}
+
+static void
+parse_at_media_end_selector_cb (CRDocHandler * a_this,
+ CRSelector * a_sellist)
+{
+ enum CRStatus status = CR_OK;
+
+ /*
+ *the current ruleset stmt, child of the
+ *current at-media being parsed.
+ */
+ CRStatement *stmt = NULL;
+ CRStatement **stmtptr = NULL;
+
+ g_return_if_fail (a_this && a_sellist);
+
+ stmtptr = &stmt;
+ status = cr_doc_handler_get_ctxt (a_this, (gpointer *) stmtptr);
+ g_return_if_fail (status == CR_OK && stmt
+ && stmt->type == RULESET_STMT);
+ g_return_if_fail (stmt->kind.ruleset->parent_media_rule);
+
+ status = cr_doc_handler_set_ctxt
+ (a_this, stmt->kind.ruleset->parent_media_rule);
+ g_return_if_fail (status == CR_OK);
+}
+
+static void
+parse_at_media_end_media_cb (CRDocHandler * a_this,
+ GList * a_media_list)
+{
+ enum CRStatus status = CR_OK;
+ CRStatement *at_media = NULL;
+ CRStatement **at_media_ptr = NULL;
+
+ (void) a_media_list;
+
+ g_return_if_fail (a_this && a_this->priv);
+
+ at_media_ptr = &at_media;
+ status = cr_doc_handler_get_ctxt (a_this,
+ (gpointer *) at_media_ptr);
+ g_return_if_fail (status == CR_OK && at_media);
+ status = cr_doc_handler_set_result (a_this, at_media);
+}
+
+static void
+parse_ruleset_start_selector_cb (CRDocHandler * a_this,
+ CRSelector * a_sellist)
+{
+ CRStatement *ruleset = NULL;
+
+ g_return_if_fail (a_this && a_this->priv && a_sellist);
+
+ ruleset = cr_statement_new_ruleset (NULL, a_sellist, NULL, NULL);
+ g_return_if_fail (ruleset);
+
+ cr_doc_handler_set_result (a_this, ruleset);
+}
+
+static void
+parse_ruleset_unrecoverable_error_cb (CRDocHandler * a_this)
+{
+ CRStatement *stmt = NULL;
+ CRStatement **stmtptr = NULL;
+ enum CRStatus status = CR_OK;
+
+ stmtptr = &stmt;
+ status = cr_doc_handler_get_result (a_this, (gpointer *) stmtptr);
+ if (status != CR_OK) {
+ cr_utils_trace_info ("Couldn't get parsing context. "
+ "This may lead to some memory leaks.");
+ return;
+ }
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ cr_doc_handler_set_result (a_this, NULL);
+ }
+}
+
+static void
+parse_ruleset_property_cb (CRDocHandler * a_this,
+ CRString * a_name,
+ CRTerm * a_value, gboolean a_important)
+{
+ enum CRStatus status = CR_OK;
+ CRStatement *ruleset = NULL;
+ CRStatement **rulesetptr = NULL;
+ CRDeclaration *decl = NULL;
+ CRString *stringue = NULL;
+
+ g_return_if_fail (a_this && a_this->priv && a_name);
+
+ rulesetptr = &ruleset;
+ status = cr_doc_handler_get_result (a_this, (gpointer *) rulesetptr);
+ g_return_if_fail (status == CR_OK
+ && ruleset
+ && ruleset->type == RULESET_STMT);
+
+ stringue = cr_string_dup (a_name);
+ g_return_if_fail (stringue);
+
+ decl = cr_declaration_new (ruleset, stringue, a_value);
+ if (!decl)
+ cr_string_destroy (stringue);
+ g_return_if_fail (decl);
+ decl->important = a_important;
+ status = cr_statement_ruleset_append_decl (ruleset, decl);
+ g_return_if_fail (status == CR_OK);
+}
+
+static void
+parse_ruleset_end_selector_cb (CRDocHandler * a_this,
+ CRSelector * a_sellist)
+{
+ CRStatement *result = NULL;
+ CRStatement **resultptr = NULL;
+ enum CRStatus status = CR_OK;
+
+ g_return_if_fail (a_this && a_sellist);
+
+ resultptr = &result;
+ status = cr_doc_handler_get_result (a_this, (gpointer *) resultptr);
+
+ g_return_if_fail (status == CR_OK
+ && result
+ && result->type == RULESET_STMT);
+}
+
+static void
+cr_statement_clear (CRStatement * a_this)
+{
+ g_return_if_fail (a_this);
+
+ switch (a_this->type) {
+ case AT_RULE_STMT:
+ break;
+ case RULESET_STMT:
+ if (!a_this->kind.ruleset)
+ return;
+ if (a_this->kind.ruleset->sel_list) {
+ cr_selector_unref (a_this->kind.ruleset->sel_list);
+ a_this->kind.ruleset->sel_list = NULL;
+ }
+ if (a_this->kind.ruleset->decl_list) {
+ cr_declaration_destroy
+ (a_this->kind.ruleset->decl_list);
+ a_this->kind.ruleset->decl_list = NULL;
+ }
+ g_free (a_this->kind.ruleset);
+ a_this->kind.ruleset = NULL;
+ break;
+
+ case AT_IMPORT_RULE_STMT:
+ if (!a_this->kind.import_rule)
+ return;
+ if (a_this->kind.import_rule->url) {
+ cr_string_destroy
+ (a_this->kind.import_rule->url) ;
+ a_this->kind.import_rule->url = NULL;
+ }
+ if (a_this->kind.import_rule->media_list) {
+ g_list_free_full (a_this->kind.import_rule->media_list,
+ (GDestroyNotify) cr_string_destroy);
+ }
+ if (a_this->kind.import_rule->sheet) {
+ cr_stylesheet_unref (a_this->kind.import_rule->sheet);
+ }
+ g_free (a_this->kind.import_rule);
+ a_this->kind.import_rule = NULL;
+ break;
+
+ case AT_MEDIA_RULE_STMT:
+ if (!a_this->kind.media_rule)
+ return;
+ if (a_this->kind.media_rule->rulesets) {
+ cr_statement_destroy
+ (a_this->kind.media_rule->rulesets);
+ a_this->kind.media_rule->rulesets = NULL;
+ }
+ if (a_this->kind.media_rule->media_list) {
+ GList *cur = NULL;
+
+ for (cur = a_this->kind.media_rule->media_list;
+ cur; cur = cur->next) {
+ if (cur->data) {
+ cr_string_destroy ((CRString *) cur->data);
+ cur->data = NULL;
+ }
+
+ }
+ g_list_free (a_this->kind.media_rule->media_list);
+ a_this->kind.media_rule->media_list = NULL;
+ }
+ g_free (a_this->kind.media_rule);
+ a_this->kind.media_rule = NULL;
+ break;
+
+ case AT_PAGE_RULE_STMT:
+ if (!a_this->kind.page_rule)
+ return;
+
+ if (a_this->kind.page_rule->decl_list) {
+ cr_declaration_destroy
+ (a_this->kind.page_rule->decl_list);
+ a_this->kind.page_rule->decl_list = NULL;
+ }
+ if (a_this->kind.page_rule->name) {
+ cr_string_destroy
+ (a_this->kind.page_rule->name);
+ a_this->kind.page_rule->name = NULL;
+ }
+ if (a_this->kind.page_rule->pseudo) {
+ cr_string_destroy
+ (a_this->kind.page_rule->pseudo);
+ a_this->kind.page_rule->pseudo = NULL;
+ }
+ g_free (a_this->kind.page_rule);
+ a_this->kind.page_rule = NULL;
+ break;
+
+ case AT_CHARSET_RULE_STMT:
+ if (!a_this->kind.charset_rule)
+ return;
+
+ if (a_this->kind.charset_rule->charset) {
+ cr_string_destroy
+ (a_this->kind.charset_rule->charset);
+ a_this->kind.charset_rule->charset = NULL;
+ }
+ g_free (a_this->kind.charset_rule);
+ a_this->kind.charset_rule = NULL;
+ break;
+
+ case AT_FONT_FACE_RULE_STMT:
+ if (!a_this->kind.font_face_rule)
+ return;
+
+ if (a_this->kind.font_face_rule->decl_list) {
+ cr_declaration_unref
+ (a_this->kind.font_face_rule->decl_list);
+ a_this->kind.font_face_rule->decl_list = NULL;
+ }
+ g_free (a_this->kind.font_face_rule);
+ a_this->kind.font_face_rule = NULL;
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ * cr_statement_ruleset_to_string:
+ *
+ *@a_this: the current instance of #CRStatement
+ *@a_indent: the number of whitespace to use for indentation
+ *
+ *Serializes the ruleset statement into a string
+ *
+ *Returns the newly allocated serialised string. Must be freed
+ *by the caller, using g_free().
+ */
+static gchar *
+cr_statement_ruleset_to_string (CRStatement const * a_this, glong a_indent)
+{
+ GString *stringue = NULL;
+ gchar *tmp_str = NULL,
+ *result = NULL;
+
+ g_return_val_if_fail (a_this && a_this->type == RULESET_STMT, NULL);
+
+ stringue = (GString *) g_string_new (NULL);
+ if (!stringue) {
+ return result;
+ }
+
+ if (a_this->kind.ruleset->sel_list) {
+ if (a_indent)
+ cr_utils_dump_n_chars2 (' ', stringue, a_indent);
+
+ tmp_str =
+ (gchar *) cr_selector_to_string (a_this->kind.ruleset->
+ sel_list);
+ if (tmp_str) {
+ g_string_append (stringue, tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+ g_string_append (stringue, " {\n");
+ if (a_this->kind.ruleset->decl_list) {
+ tmp_str = (gchar *) cr_declaration_list_to_string2
+ (a_this->kind.ruleset->decl_list,
+ a_indent + DECLARATION_INDENT_NB, TRUE);
+ if (tmp_str) {
+ g_string_append (stringue, tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ g_string_append (stringue, "\n");
+ cr_utils_dump_n_chars2 (' ', stringue, a_indent);
+ }
+ g_string_append (stringue, "}");
+ result = stringue->str;
+
+ g_string_free (stringue, FALSE);
+ stringue = NULL;
+
+ if (tmp_str) {
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ return result;
+}
+
+
+/**
+ * cr_statement_font_face_rule_to_string:
+ *
+ *@a_this: the current instance of #CRStatement to consider
+ *It must be a font face rule statement.
+ *@a_indent: the number of white spaces of indentation.
+ *
+ *Serializes a font face rule statement into a string.
+ *
+ *Returns the serialized string. Must be deallocated by the caller
+ *using g_free().
+ */
+static gchar *
+cr_statement_font_face_rule_to_string (CRStatement const * a_this,
+ glong a_indent)
+{
+ gchar *result = NULL, *tmp_str = NULL ;
+ GString *stringue = NULL ;
+
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_FONT_FACE_RULE_STMT,
+ NULL);
+
+ if (a_this->kind.font_face_rule->decl_list) {
+ stringue = (GString *) g_string_new (NULL) ;
+ g_return_val_if_fail (stringue, NULL) ;
+ if (a_indent)
+ cr_utils_dump_n_chars2 (' ', stringue,
+ a_indent);
+ g_string_append (stringue, "@font-face {\n");
+ tmp_str = (gchar *) cr_declaration_list_to_string2
+ (a_this->kind.font_face_rule->decl_list,
+ a_indent + DECLARATION_INDENT_NB, TRUE) ;
+ if (tmp_str) {
+ g_string_append (stringue,
+ tmp_str) ;
+ g_free (tmp_str) ;
+ tmp_str = NULL ;
+ }
+ g_string_append (stringue, "\n}");
+ }
+ if (stringue) {
+ result = stringue->str ;
+ g_string_free (stringue, FALSE) ;
+ stringue = NULL ;
+ }
+ return result ;
+}
+
+
+/**
+ * cr_statement_charset_to_string:
+ *
+ *Serialises an \@charset statement into a string.
+ *@a_this: the statement to serialize.
+ *@a_indent: the number of indentation spaces
+ *
+ *Returns the serialized charset statement. Must be
+ *freed by the caller using g_free().
+ */
+static gchar *
+cr_statement_charset_to_string (CRStatement const *a_this,
+ gulong a_indent)
+{
+ gchar *str = NULL ;
+ GString *stringue = NULL ;
+
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_CHARSET_RULE_STMT,
+ NULL) ;
+
+ if (a_this->kind.charset_rule
+ && a_this->kind.charset_rule->charset
+ && a_this->kind.charset_rule->charset->stryng
+ && a_this->kind.charset_rule->charset->stryng->str) {
+ stringue = g_string_new (NULL) ;
+ g_return_val_if_fail (stringue, NULL) ;
+ cr_utils_dump_n_chars2 (' ', stringue, a_indent);
+ g_string_append_printf (stringue,
+ "@charset \"%s\" ;",
+ a_this->kind.charset_rule->charset->stryng->str);
+ }
+ if (stringue) {
+ str = stringue->str ;
+ g_string_free (stringue, FALSE) ;
+ }
+ return str ;
+}
+
+
+/**
+ * cr_statement_at_page_rule_to_string:
+ *
+ *Serialises the at page rule statement into a string
+ *@a_this: the current instance of #CRStatement. Must
+ *be an "\@page" rule statement.
+ *
+ *Returns the serialized string. Must be freed by the caller
+ */
+static gchar *
+cr_statement_at_page_rule_to_string (CRStatement const *a_this,
+ gulong a_indent)
+{
+ GString *stringue = NULL;
+ gchar *result = NULL ;
+
+ stringue = (GString *) g_string_new (NULL) ;
+
+ cr_utils_dump_n_chars2 (' ', stringue, a_indent) ;
+ g_string_append (stringue, "@page");
+ if (a_this->kind.page_rule->name
+ && a_this->kind.page_rule->name->stryng) {
+ g_string_append_printf
+ (stringue, " %s",
+ a_this->kind.page_rule->name->stryng->str) ;
+ } else {
+ g_string_append (stringue, " ");
+ }
+ if (a_this->kind.page_rule->pseudo
+ && a_this->kind.page_rule->pseudo->stryng) {
+ g_string_append_printf
+ (stringue, " :%s",
+ a_this->kind.page_rule->pseudo->stryng->str) ;
+ }
+ if (a_this->kind.page_rule->decl_list) {
+ gchar *str = NULL ;
+ g_string_append (stringue, " {\n");
+ str = (gchar *) cr_declaration_list_to_string2
+ (a_this->kind.page_rule->decl_list,
+ a_indent + DECLARATION_INDENT_NB, TRUE) ;
+ if (str) {
+ g_string_append (stringue, str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ g_string_append (stringue, "\n}\n");
+ }
+ result = stringue->str ;
+ g_string_free (stringue, FALSE) ;
+ stringue = NULL ;
+ return result ;
+}
+
+
+/**
+ *Serializes an \@media statement.
+ *@param a_this the current instance of #CRStatement
+ *@param a_indent the number of spaces of indentation.
+ *@return the serialized \@media statement. Must be freed
+ *by the caller using g_free().
+ */
+static gchar *
+cr_statement_media_rule_to_string (CRStatement const *a_this,
+ gulong a_indent)
+{
+ gchar *str = NULL ;
+ GString *stringue = NULL ;
+ GList const *cur = NULL;
+
+ g_return_val_if_fail (a_this->type == AT_MEDIA_RULE_STMT,
+ NULL);
+
+ if (a_this->kind.media_rule) {
+ stringue = (GString *) g_string_new (NULL) ;
+ cr_utils_dump_n_chars2 (' ', stringue, a_indent);
+ g_string_append (stringue, "@media");
+
+ for (cur = a_this->kind.media_rule->media_list; cur;
+ cur = cur->next) {
+ CRString const *crstr = cur->data;
+ if (crstr && crstr->stryng) {
+ gchar const *str2 = crstr->stryng->str;
+ if (str2) {
+ if (cur->prev) {
+ g_string_append
+ (stringue,
+ ",");
+ }
+ g_string_append_printf
+ (stringue,
+ " %s", str2);
+ }
+ }
+ }
+ g_string_append (stringue, " {\n");
+ str = cr_statement_list_to_string
+ (a_this->kind.media_rule->rulesets,
+ a_indent + DECLARATION_INDENT_NB) ;
+ if (str) {
+ g_string_append (stringue, str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ g_string_append (stringue, "\n}");
+ }
+ if (stringue) {
+ str = stringue->str ;
+ g_string_free (stringue, FALSE) ;
+ }
+ return str ;
+}
+
+
+static gchar *
+cr_statement_import_rule_to_string (CRStatement const *a_this,
+ gulong a_indent)
+{
+ GString *stringue = NULL ;
+ gchar *str = NULL;
+
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_IMPORT_RULE_STMT
+ && a_this->kind.import_rule,
+ NULL) ;
+
+ if (a_this->kind.import_rule->url
+ && a_this->kind.import_rule->url->stryng) {
+ stringue = (GString *) g_string_new (NULL) ;
+ g_return_val_if_fail (stringue, NULL) ;
+ cr_utils_dump_n_chars2 (' ', stringue, a_indent);
+ if (a_this->kind.import_rule->url->stryng->str) {
+ g_string_append_printf (stringue,
+ "@import url(\"%s\")",
+ a_this->kind.import_rule->url->stryng->str);
+ } else /*there is no url, so no import rule, get out! */
+ return NULL;
+
+ if (a_this->kind.import_rule->media_list) {
+ GList const *cur = NULL;
+
+ for (cur = a_this->kind.import_rule->media_list;
+ cur; cur = cur->next) {
+ if (cur->data) {
+ CRString const *crstr = cur->data;
+
+ if (cur->prev) {
+ g_string_append
+ (stringue, ", ");
+ }
+ if (crstr
+ && crstr->stryng
+ && crstr->stryng->str) {
+ g_string_append_len
+ (stringue,
+ crstr->stryng->str,
+ crstr->stryng->len) ;
+ }
+ }
+ }
+ }
+ g_string_append (stringue, " ;");
+ }
+ if (stringue) {
+ str = stringue->str ;
+ g_string_free (stringue, FALSE) ;
+ stringue = NULL ;
+ }
+ return str ;
+}
+
+
+/*******************
+ *public functions
+ ******************/
+
+/**
+ * cr_statement_does_buf_parses_against_core:
+ *
+ *@a_buf: the buffer to parse.
+ *@a_encoding: the character encoding of a_buf.
+ *
+ *Tries to parse a buffer and says whether if the content of the buffer
+ *is a css statement as defined by the "Core CSS Grammar" (chapter 4 of the
+ *css spec) or not.
+ *
+ *Returns TRUE if the buffer parses against the core grammar, false otherwise.
+ */
+gboolean
+cr_statement_does_buf_parses_against_core (const guchar * a_buf,
+ enum CREncoding a_encoding)
+{
+ CRParser *parser = NULL;
+ enum CRStatus status = CR_OK;
+ gboolean result = FALSE;
+
+ parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
+ a_encoding, FALSE);
+ g_return_val_if_fail (parser, FALSE);
+
+ status = cr_parser_set_use_core_grammar (parser, TRUE);
+ if (status != CR_OK) {
+ goto cleanup;
+ }
+
+ status = cr_parser_parse_statement_core (parser);
+ if (status == CR_OK) {
+ result = TRUE;
+ }
+
+ cleanup:
+ if (parser) {
+ cr_parser_destroy (parser);
+ }
+
+ return result;
+}
+
+/**
+ * cr_statement_parse_from_buf:
+ *
+ *@a_buf: the buffer to parse.
+ *@a_encoding: the character encoding of a_buf.
+ *
+ *Parses a buffer that contains a css statement and returns
+ *an instance of #CRStatement in case of successful parsing.
+ *TODO: at support of "\@import" rules.
+ *
+ *Returns the newly built instance of #CRStatement in case
+ *of successful parsing, NULL otherwise.
+ */
+CRStatement *
+cr_statement_parse_from_buf (const guchar * a_buf, enum CREncoding a_encoding)
+{
+ CRStatement *result = NULL;
+
+ /*
+ *The strategy of this function is "brute force".
+ *It tries to parse all the types of CRStatement it knows about.
+ *I could do this a smarter way but I don't have the time now.
+ *I think I will revisit this when time of performances and
+ *pull based incremental parsing comes.
+ */
+
+ result = cr_statement_ruleset_parse_from_buf (a_buf, a_encoding);
+ if (!result) {
+ result = cr_statement_at_charset_rule_parse_from_buf
+ (a_buf, a_encoding);
+ } else {
+ goto out;
+ }
+
+ if (!result) {
+ result = cr_statement_at_media_rule_parse_from_buf
+ (a_buf, a_encoding);
+ } else {
+ goto out;
+ }
+
+ if (!result) {
+ result = cr_statement_at_charset_rule_parse_from_buf
+ (a_buf, a_encoding);
+ } else {
+ goto out;
+ }
+
+ if (!result) {
+ result = cr_statement_font_face_rule_parse_from_buf
+ (a_buf, a_encoding);
+
+ } else {
+ goto out;
+ }
+
+ if (!result) {
+ result = cr_statement_at_page_rule_parse_from_buf
+ (a_buf, a_encoding);
+ } else {
+ goto out;
+ }
+
+ if (!result) {
+ result = cr_statement_at_import_rule_parse_from_buf
+ (a_buf, a_encoding);
+ } else {
+ goto out;
+ }
+
+ out:
+ return result;
+}
+
+/**
+ * cr_statement_ruleset_parse_from_buf:
+ *
+ *@a_buf: the buffer to parse.
+ *@a_enc: the character encoding of a_buf.
+ *
+ *Parses a buffer that contains a ruleset statement and instantiates
+ *a #CRStatement of type RULESET_STMT.
+ *
+ *Returns the newly built instance of #CRStatement in case of successful parsing,
+ *NULL otherwise.
+ */
+CRStatement *
+cr_statement_ruleset_parse_from_buf (const guchar * a_buf,
+ enum CREncoding a_enc)
+{
+ enum CRStatus status = CR_OK;
+ CRStatement *result = NULL;
+ CRStatement **resultptr = NULL;
+ CRParser *parser = NULL;
+ CRDocHandler *sac_handler = NULL;
+
+ g_return_val_if_fail (a_buf, NULL);
+
+ parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
+ a_enc, FALSE);
+
+ g_return_val_if_fail (parser, NULL);
+
+ sac_handler = cr_doc_handler_new ();
+ g_return_val_if_fail (sac_handler, NULL);
+
+ sac_handler->start_selector = parse_ruleset_start_selector_cb;
+ sac_handler->end_selector = parse_ruleset_end_selector_cb;
+ sac_handler->property = parse_ruleset_property_cb;
+ sac_handler->unrecoverable_error =
+ parse_ruleset_unrecoverable_error_cb;
+
+ cr_parser_set_sac_handler (parser, sac_handler);
+ cr_parser_try_to_skip_spaces_and_comments (parser);
+ status = cr_parser_parse_ruleset (parser);
+ if (status != CR_OK) {
+ goto cleanup;
+ }
+
+ resultptr = &result;
+ status = cr_doc_handler_get_result (sac_handler,
+ (gpointer *) resultptr);
+ if (!((status == CR_OK) && result)) {
+ if (result) {
+ cr_statement_destroy (result);
+ result = NULL;
+ }
+ }
+
+ cleanup:
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ sac_handler = NULL ;
+ }
+ if (sac_handler) {
+ cr_doc_handler_unref (sac_handler);
+ sac_handler = NULL;
+ }
+ return result;
+}
+
+/**
+ * cr_statement_new_ruleset:
+ *
+ *@a_sel_list: the list of #CRSimpleSel (selectors)
+ *the rule applies to.
+ *@a_decl_list: the list of instances of #CRDeclaration
+ *that composes the ruleset.
+ *@a_media_types: a list of instances of GString that
+ *describe the media list this ruleset applies to.
+ *
+ *Creates a new instance of #CRStatement of type
+ *#CRRulSet.
+ *
+ *Returns the new instance of #CRStatement or NULL if something
+ *went wrong.
+ */
+CRStatement *
+cr_statement_new_ruleset (CRStyleSheet * a_sheet,
+ CRSelector * a_sel_list,
+ CRDeclaration * a_decl_list,
+ CRStatement * a_parent_media_rule)
+{
+ CRStatement *result = NULL;
+
+ g_return_val_if_fail (a_sel_list, NULL);
+
+ if (a_parent_media_rule) {
+ g_return_val_if_fail
+ (a_parent_media_rule->type == AT_MEDIA_RULE_STMT,
+ NULL);
+ g_return_val_if_fail (a_parent_media_rule->kind.media_rule,
+ NULL);
+ }
+
+ result = (CRStatement *) g_try_malloc (sizeof (CRStatement));
+
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRStatement));
+ result->type = RULESET_STMT;
+ result->kind.ruleset = (CRRuleSet *) g_try_malloc (sizeof (CRRuleSet));
+
+ if (!result->kind.ruleset) {
+ cr_utils_trace_info ("Out of memory");
+ if (result)
+ g_free (result);
+ return NULL;
+ }
+
+ memset (result->kind.ruleset, 0, sizeof (CRRuleSet));
+ result->kind.ruleset->sel_list = a_sel_list;
+ if (a_sel_list)
+ cr_selector_ref (a_sel_list);
+ result->kind.ruleset->decl_list = a_decl_list;
+
+ if (a_parent_media_rule) {
+ result->kind.ruleset->parent_media_rule = a_parent_media_rule;
+ a_parent_media_rule->kind.media_rule->rulesets =
+ cr_statement_append
+ (a_parent_media_rule->kind.media_rule->rulesets,
+ result);
+ }
+
+ cr_statement_set_parent_sheet (result, a_sheet);
+
+ return result;
+}
+
+/**
+ * cr_statement_at_media_rule_parse_from_buf:
+ *
+ *@a_buf: the input to parse.
+ *@a_enc: the encoding of the buffer.
+ *
+ *Parses a buffer that contains an "\@media" declaration
+ *and builds an \@media css statement.
+ *
+ *Returns the \@media statement, or NULL if the buffer could not
+ *be successfully parsed.
+ */
+CRStatement *
+cr_statement_at_media_rule_parse_from_buf (const guchar * a_buf,
+ enum CREncoding a_enc)
+{
+ CRParser *parser = NULL;
+ CRStatement *result = NULL;
+ CRStatement **resultptr = NULL;
+ CRDocHandler *sac_handler = NULL;
+ enum CRStatus status = CR_OK;
+
+ parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
+ a_enc, FALSE);
+ if (!parser) {
+ cr_utils_trace_info ("Instantiation of the parser failed");
+ goto cleanup;
+ }
+
+ sac_handler = cr_doc_handler_new ();
+ if (!sac_handler) {
+ cr_utils_trace_info
+ ("Instantiation of the sac handler failed");
+ goto cleanup;
+ }
+
+ sac_handler->start_media = parse_at_media_start_media_cb;
+ sac_handler->start_selector = parse_at_media_start_selector_cb;
+ sac_handler->property = parse_at_media_property_cb;
+ sac_handler->end_selector = parse_at_media_end_selector_cb;
+ sac_handler->end_media = parse_at_media_end_media_cb;
+ sac_handler->unrecoverable_error =
+ parse_at_media_unrecoverable_error_cb;
+
+ status = cr_parser_set_sac_handler (parser, sac_handler);
+ if (status != CR_OK)
+ goto cleanup;
+
+ status = cr_parser_try_to_skip_spaces_and_comments (parser);
+ if (status != CR_OK)
+ goto cleanup;
+
+ status = cr_parser_parse_media (parser);
+ if (status != CR_OK)
+ goto cleanup;
+
+ resultptr = &result;
+ status = cr_doc_handler_get_result (sac_handler,
+ (gpointer *) resultptr);
+ if (status != CR_OK)
+ goto cleanup;
+
+ cleanup:
+
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ sac_handler = NULL ;
+ }
+ if (sac_handler) {
+ cr_doc_handler_unref (sac_handler);
+ sac_handler = NULL;
+ }
+
+ return result;
+}
+
+/**
+ * cr_statement_new_at_media_rule:
+ *
+ *@a_ruleset: the ruleset statements contained
+ *in the \@media rule.
+ *@a_media: the media string list. A list of GString pointers.
+ *
+ *Instantiates an instance of #CRStatement of type
+ *AT_MEDIA_RULE_STMT (\@media ruleset).
+ *
+ */
+CRStatement *
+cr_statement_new_at_media_rule (CRStyleSheet * a_sheet,
+ CRStatement * a_rulesets, GList * a_media)
+{
+ CRStatement *result = NULL,
+ *cur = NULL;
+
+ if (a_rulesets)
+ g_return_val_if_fail (a_rulesets->type == RULESET_STMT, NULL);
+
+ result = (CRStatement *) g_try_malloc (sizeof (CRStatement));
+
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRStatement));
+ result->type = AT_MEDIA_RULE_STMT;
+
+ result->kind.media_rule = (CRAtMediaRule *) g_try_malloc (sizeof (CRAtMediaRule));
+ if (!result->kind.media_rule) {
+ cr_utils_trace_info ("Out of memory");
+ g_free (result);
+ return NULL;
+ }
+ memset (result->kind.media_rule, 0, sizeof (CRAtMediaRule));
+ result->kind.media_rule->rulesets = a_rulesets;
+ for (cur = a_rulesets; cur; cur = cur->next) {
+ if (cur->type != RULESET_STMT || !cur->kind.ruleset) {
+ cr_utils_trace_info ("Bad parameter a_rulesets. "
+ "It should be a list of "
+ "correct ruleset statement only !");
+ goto error;
+ }
+ cur->kind.ruleset->parent_media_rule = result;
+ }
+
+ result->kind.media_rule->media_list = a_media;
+ if (a_sheet) {
+ cr_statement_set_parent_sheet (result, a_sheet);
+ }
+
+ return result;
+
+ error:
+ g_clear_pointer (&result, cr_statement_destroy);
+ return NULL;
+}
+
+/**
+ * cr_statement_new_at_import_rule:
+ *
+ *@a_url: the url to connect to the get the file
+ *to be imported.
+ *@a_sheet: the imported parsed stylesheet.
+ *
+ *Creates a new instance of #CRStatment of type
+ *#CRAtImportRule.
+ *
+ *Returns the newly built instance of #CRStatement.
+ */
+CRStatement *
+cr_statement_new_at_import_rule (CRStyleSheet * a_container_sheet,
+ CRString * a_url,
+ GList * a_media_list,
+ CRStyleSheet * a_imported_sheet)
+{
+ CRStatement *result = NULL;
+
+ result = (CRStatement *) g_try_malloc (sizeof (CRStatement));
+
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRStatement));
+ result->type = AT_IMPORT_RULE_STMT;
+
+ result->kind.import_rule = (CRAtImportRule *) g_try_malloc (sizeof (CRAtImportRule));
+
+ if (!result->kind.import_rule) {
+ cr_utils_trace_info ("Out of memory");
+ g_free (result);
+ return NULL;
+ }
+
+ memset (result->kind.import_rule, 0, sizeof (CRAtImportRule));
+ result->kind.import_rule->url = a_url;
+ result->kind.import_rule->media_list = a_media_list;
+ result->kind.import_rule->sheet = a_imported_sheet;
+ if (a_container_sheet)
+ cr_statement_set_parent_sheet (result, a_container_sheet);
+
+ return result;
+}
+
+/**
+ * cr_statement_at_import_rule_parse_from_buf:
+ *
+ *@a_buf: the buffer to parse.
+ *@a_encoding: the encoding of a_buf.
+ *
+ *Parses a buffer that contains an "\@import" rule and
+ *instantiate a #CRStatement of type AT_IMPORT_RULE_STMT
+ *
+ *Returns the newly built instance of #CRStatement in case of
+ *a successful parsing, NULL otherwise.
+ */
+CRStatement *
+cr_statement_at_import_rule_parse_from_buf (const guchar * a_buf,
+ enum CREncoding a_encoding)
+{
+ enum CRStatus status = CR_OK;
+ CRParser *parser = NULL;
+ CRStatement *result = NULL;
+ GList *media_list = NULL;
+ CRString *import_string = NULL;
+ CRParsingLocation location = {0,0,0} ;
+
+ parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
+ a_encoding, FALSE);
+ if (!parser) {
+ cr_utils_trace_info ("Instantiation of parser failed.");
+ goto cleanup;
+ }
+
+ status = cr_parser_try_to_skip_spaces_and_comments (parser);
+ if (status != CR_OK)
+ goto cleanup;
+
+ status = cr_parser_parse_import (parser,
+ &media_list,
+ &import_string,
+ &location);
+ if (status != CR_OK || !import_string)
+ goto cleanup;
+
+ result = cr_statement_new_at_import_rule (NULL, import_string,
+ media_list, NULL);
+ if (result) {
+ cr_parsing_location_copy (&result->location,
+ &location) ;
+ import_string = NULL;
+ media_list = NULL;
+ }
+
+ cleanup:
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ }
+ if (media_list) {
+ for (; media_list;
+ media_list = g_list_next (media_list)) {
+ if (media_list->data) {
+ cr_string_destroy ((CRString*)media_list->data);
+ media_list->data = NULL;
+ }
+ }
+ g_list_free (media_list);
+ media_list = NULL;
+ }
+ if (import_string) {
+ cr_string_destroy (import_string);
+ import_string = NULL;
+ }
+
+ return result;
+}
+
+/**
+ * cr_statement_new_at_page_rule:
+ *
+ *@a_decl_list: a list of instances of #CRDeclarations
+ *which is actually the list of declarations that applies to
+ *this page rule.
+ *@a_selector: the page rule selector.
+ *
+ *Creates a new instance of #CRStatement of type
+ *#CRAtPageRule.
+ *
+ *Returns the newly built instance of #CRStatement or NULL
+ *in case of error.
+ */
+CRStatement *
+cr_statement_new_at_page_rule (CRStyleSheet * a_sheet,
+ CRDeclaration * a_decl_list,
+ CRString * a_name, CRString * a_pseudo)
+{
+ CRStatement *result = NULL;
+
+ result = (CRStatement *) g_try_malloc (sizeof (CRStatement));
+
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRStatement));
+ result->type = AT_PAGE_RULE_STMT;
+
+ result->kind.page_rule = (CRAtPageRule *) g_try_malloc (sizeof (CRAtPageRule));
+
+ if (!result->kind.page_rule) {
+ cr_utils_trace_info ("Out of memory");
+ g_free (result);
+ return NULL;
+ }
+
+ memset (result->kind.page_rule, 0, sizeof (CRAtPageRule));
+ if (a_decl_list) {
+ result->kind.page_rule->decl_list = a_decl_list;
+ cr_declaration_ref (a_decl_list);
+ }
+ result->kind.page_rule->name = a_name;
+ result->kind.page_rule->pseudo = a_pseudo;
+ if (a_sheet)
+ cr_statement_set_parent_sheet (result, a_sheet);
+
+ return result;
+}
+
+/**
+ * cr_statement_at_page_rule_parse_from_buf:
+ *
+ *@a_buf: the character buffer to parse.
+ *@a_encoding: the character encoding of a_buf.
+ *
+ *Parses a buffer that contains an "\@page" production and,
+ *if the parsing succeeds, builds the page statement.
+ *
+ *Returns the newly built at page statement in case of successful parsing,
+ *NULL otherwise.
+ */
+CRStatement *
+cr_statement_at_page_rule_parse_from_buf (const guchar * a_buf,
+ enum CREncoding a_encoding)
+{
+ enum CRStatus status = CR_OK;
+ CRParser *parser = NULL;
+ CRDocHandler *sac_handler = NULL;
+ CRStatement *result = NULL;
+ CRStatement **resultptr = NULL;
+
+ g_return_val_if_fail (a_buf, NULL);
+
+ parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
+ a_encoding, FALSE);
+ if (!parser) {
+ cr_utils_trace_info ("Instantiation of the parser failed.");
+ goto cleanup;
+ }
+
+ sac_handler = cr_doc_handler_new ();
+ if (!sac_handler) {
+ cr_utils_trace_info
+ ("Instantiation of the sac handler failed.");
+ goto cleanup;
+ }
+
+ sac_handler->start_page = parse_page_start_page_cb;
+ sac_handler->property = parse_page_property_cb;
+ sac_handler->end_page = parse_page_end_page_cb;
+ sac_handler->unrecoverable_error = parse_page_unrecoverable_error_cb;
+
+ status = cr_parser_set_sac_handler (parser, sac_handler);
+ if (status != CR_OK)
+ goto cleanup;
+
+ /*Now, invoke the parser to parse the "@page production" */
+ cr_parser_try_to_skip_spaces_and_comments (parser);
+ if (status != CR_OK)
+ goto cleanup;
+ status = cr_parser_parse_page (parser);
+ if (status != CR_OK)
+ goto cleanup;
+
+ resultptr = &result;
+ status = cr_doc_handler_get_result (sac_handler,
+ (gpointer *) resultptr);
+
+ cleanup:
+
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ sac_handler = NULL ;
+ }
+ if (sac_handler) {
+ cr_doc_handler_unref (sac_handler);
+ sac_handler = NULL;
+ }
+ return result;
+}
+
+/**
+ * cr_statement_new_at_charset_rule:
+ *
+ *@a_charset: the string representing the charset.
+ *Note that the newly built instance of #CRStatement becomes
+ *the owner of a_charset. The caller must not free a_charset !!!.
+ *
+ *Creates a new instance of #CRStatement of type
+ *#CRAtCharsetRule.
+ *
+ *Returns the newly built instance of #CRStatement or NULL
+ *if an error arises.
+ */
+CRStatement *
+cr_statement_new_at_charset_rule (CRStyleSheet * a_sheet,
+ CRString * a_charset)
+{
+ CRStatement *result = NULL;
+
+ g_return_val_if_fail (a_charset, NULL);
+
+ result = (CRStatement *) g_try_malloc (sizeof (CRStatement));
+
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRStatement));
+ result->type = AT_CHARSET_RULE_STMT;
+
+ result->kind.charset_rule = (CRAtCharsetRule *) g_try_malloc (sizeof (CRAtCharsetRule));
+
+ if (!result->kind.charset_rule) {
+ cr_utils_trace_info ("Out of memory");
+ g_free (result);
+ return NULL;
+ }
+ memset (result->kind.charset_rule, 0, sizeof (CRAtCharsetRule));
+ result->kind.charset_rule->charset = a_charset;
+ cr_statement_set_parent_sheet (result, a_sheet);
+
+ return result;
+}
+
+/**
+ * cr_statement_at_charset_rule_parse_from_buf:
+ *
+ *@a_buf: the buffer to parse.
+ *@a_encoding: the character encoding of the buffer.
+ *
+ *Parses a buffer that contains an '\@charset' rule and
+ *creates an instance of #CRStatement of type AT_CHARSET_RULE_STMT.
+ *
+ *Returns the newly built instance of #CRStatement.
+ */
+CRStatement *
+cr_statement_at_charset_rule_parse_from_buf (const guchar * a_buf,
+ enum CREncoding a_encoding)
+{
+ enum CRStatus status = CR_OK;
+ CRParser *parser = NULL;
+ CRStatement *result = NULL;
+ CRString *charset = NULL;
+
+ g_return_val_if_fail (a_buf, NULL);
+
+ parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
+ a_encoding, FALSE);
+ if (!parser) {
+ cr_utils_trace_info ("Instantiation of the parser failed.");
+ goto cleanup;
+ }
+
+ /*Now, invoke the parser to parse the "@charset production" */
+ cr_parser_try_to_skip_spaces_and_comments (parser);
+ if (status != CR_OK)
+ goto cleanup;
+ status = cr_parser_parse_charset (parser, &charset, NULL);
+ if (status != CR_OK || !charset)
+ goto cleanup;
+
+ result = cr_statement_new_at_charset_rule (NULL, charset);
+ if (result)
+ charset = NULL;
+
+ cleanup:
+
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ }
+ if (charset) {
+ cr_string_destroy (charset);
+ }
+
+ return result;
+}
+
+/**
+ * cr_statement_new_at_font_face_rule:
+ *
+ *@a_font_decls: a list of instances of #CRDeclaration. Each declaration
+ *is actually a font declaration.
+ *
+ *Creates an instance of #CRStatement of type #CRAtFontFaceRule.
+ *
+ *Returns the newly built instance of #CRStatement.
+ */
+CRStatement *
+cr_statement_new_at_font_face_rule (CRStyleSheet * a_sheet,
+ CRDeclaration * a_font_decls)
+{
+ CRStatement *result = NULL;
+
+ result = (CRStatement *) g_try_malloc (sizeof (CRStatement));
+
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRStatement));
+ result->type = AT_FONT_FACE_RULE_STMT;
+
+ result->kind.font_face_rule = (CRAtFontFaceRule *) g_try_malloc
+ (sizeof (CRAtFontFaceRule));
+
+ if (!result->kind.font_face_rule) {
+ cr_utils_trace_info ("Out of memory");
+ g_free (result);
+ return NULL;
+ }
+ memset (result->kind.font_face_rule, 0, sizeof (CRAtFontFaceRule));
+
+ result->kind.font_face_rule->decl_list = a_font_decls;
+ if (a_sheet)
+ cr_statement_set_parent_sheet (result, a_sheet);
+
+ return result;
+}
+
+/**
+ * cr_statement_font_face_rule_parse_from_buf:
+ *
+ *
+ *@a_buf: the buffer to parse.
+ *@a_encoding: the character encoding of a_buf.
+ *
+ *Parses a buffer that contains an "\@font-face" rule and builds
+ *an instance of #CRStatement of type AT_FONT_FACE_RULE_STMT out of it.
+ *
+ *Returns the newly built instance of #CRStatement in case of successufull
+ *parsing, NULL otherwise.
+ */
+CRStatement *
+cr_statement_font_face_rule_parse_from_buf (const guchar * a_buf,
+ enum CREncoding a_encoding)
+{
+ CRStatement *result = NULL;
+ CRStatement **resultptr = NULL;
+ CRParser *parser = NULL;
+ CRDocHandler *sac_handler = NULL;
+ enum CRStatus status = CR_OK;
+
+ parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
+ a_encoding, FALSE);
+ if (!parser)
+ goto cleanup;
+
+ sac_handler = cr_doc_handler_new ();
+ if (!sac_handler)
+ goto cleanup;
+
+ /*
+ *set sac callbacks here
+ */
+ sac_handler->start_font_face = parse_font_face_start_font_face_cb;
+ sac_handler->property = parse_font_face_property_cb;
+ sac_handler->end_font_face = parse_font_face_end_font_face_cb;
+ sac_handler->unrecoverable_error =
+ parse_font_face_unrecoverable_error_cb;
+
+ status = cr_parser_set_sac_handler (parser, sac_handler);
+ if (status != CR_OK)
+ goto cleanup;
+
+ /*
+ *cleanup spaces of comment that may be there before the real
+ *"@font-face" thing.
+ */
+ status = cr_parser_try_to_skip_spaces_and_comments (parser);
+ if (status != CR_OK)
+ goto cleanup;
+
+ status = cr_parser_parse_font_face (parser);
+ if (status != CR_OK)
+ goto cleanup;
+
+ resultptr = &result;
+ status = cr_doc_handler_get_result (sac_handler,
+ (gpointer *) resultptr);
+ if (status != CR_OK || !result)
+ goto cleanup;
+
+ cleanup:
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ sac_handler = NULL ;
+ }
+ if (sac_handler) {
+ cr_doc_handler_unref (sac_handler);
+ sac_handler = NULL;
+ }
+ return result;
+}
+
+/**
+ * cr_statement_set_parent_sheet:
+ *
+ *@a_this: the current instance of #CRStatement.
+ *@a_sheet: the sheet that contains the current statement.
+ *
+ *Sets the container stylesheet.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_set_parent_sheet (CRStatement * a_this, CRStyleSheet * a_sheet)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+ a_this->parent_sheet = a_sheet;
+ return CR_OK;
+}
+
+/**
+ * cr_statement_get_parent_sheet:
+ *
+ *@a_this: the current #CRStatement.
+ *@a_sheet: out parameter. A pointer to the sheets that
+ *
+ *Gets the sheets that contains the current statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_get_parent_sheet (CRStatement * a_this, CRStyleSheet ** a_sheet)
+{
+ g_return_val_if_fail (a_this && a_sheet, CR_BAD_PARAM_ERROR);
+ *a_sheet = a_this->parent_sheet;
+ return CR_OK;
+}
+
+/**
+ * cr_statement_append:
+ *
+ *@a_this: the current instance of the statement list.
+ *@a_new: a_new the new instance of #CRStatement to append.
+ *
+ *Appends a new statement to the statement list.
+ *
+ *Returns the new list statement list, or NULL in case of failure.
+ */
+CRStatement *
+cr_statement_append (CRStatement * a_this, CRStatement * a_new)
+{
+ CRStatement *cur = NULL;
+
+ g_return_val_if_fail (a_new, NULL);
+
+ if (!a_this) {
+ return a_new;
+ }
+
+ /*walk forward in the current list to find the tail list element */
+ for (cur = a_this; cur && cur->next; cur = cur->next) ;
+
+ cur->next = a_new;
+ a_new->prev = cur;
+
+ return a_this;
+}
+
+/**
+ * cr_statement_prepend:
+ *
+ *@a_this: the current instance of #CRStatement.
+ *@a_new: the new statement to prepend.
+ *
+ *Prepends the an instance of #CRStatement to
+ *the current statement list.
+ *
+ *Returns the new list with the new statement prepended,
+ *or NULL in case of an error.
+ */
+CRStatement *
+cr_statement_prepend (CRStatement * a_this, CRStatement * a_new)
+{
+ CRStatement *cur = NULL;
+
+ g_return_val_if_fail (a_new, NULL);
+
+ if (!a_this)
+ return a_new;
+
+ a_new->next = a_this;
+ a_this->prev = a_new;
+
+ /*walk backward in the prepended list to find the head list element */
+ for (cur = a_new; cur && cur->prev; cur = cur->prev) ;
+
+ return cur;
+}
+
+/**
+ * cr_statement_unlink:
+ *
+ *@a_this: the current statements list.
+ *@a_to_unlink: the statement to unlink from the list.
+ *
+ *Unlinks a statement from the statements list.
+ *
+ *Returns the new list where a_to_unlink has been unlinked
+ *from, or NULL in case of error.
+ */
+CRStatement *
+cr_statement_unlink (CRStatement * a_stmt)
+{
+ CRStatement *result = a_stmt;
+
+ g_return_val_if_fail (result, NULL);
+
+ /**
+ *Some sanity checks first
+ */
+ if (a_stmt->next) {
+ g_return_val_if_fail (a_stmt->next->prev == a_stmt, NULL);
+ }
+ if (a_stmt->prev) {
+ g_return_val_if_fail (a_stmt->prev->next == a_stmt, NULL);
+ }
+
+ /**
+ *Now, the real unlinking job.
+ */
+ if (a_stmt->next) {
+ a_stmt->next->prev = a_stmt->prev;
+ }
+ if (a_stmt->prev) {
+ a_stmt->prev->next = a_stmt->next;
+ }
+
+ if (a_stmt->parent_sheet
+ && a_stmt->parent_sheet->statements == a_stmt) {
+ a_stmt->parent_sheet->statements =
+ a_stmt->parent_sheet->statements->next;
+ }
+
+ a_stmt->next = NULL;
+ a_stmt->prev = NULL;
+ a_stmt->parent_sheet = NULL;
+
+ return result;
+}
+
+/**
+ * cr_statement_nr_rules:
+ *
+ *@a_this: the current instance of #CRStatement.
+ *
+ *Gets the number of rules in the statement list;
+ *
+ *Returns number of rules in the statement list.
+ */
+gint
+cr_statement_nr_rules (CRStatement const * a_this)
+{
+ CRStatement const *cur = NULL;
+ int nr = 0;
+
+ g_return_val_if_fail (a_this, -1);
+
+ for (cur = a_this; cur; cur = cur->next)
+ nr++;
+ return nr;
+}
+
+/**
+ * cr_statement_get_from_list:
+ *
+ *@a_this: the current instance of #CRStatement.
+ *@itemnr: the index into the statement list.
+ *
+ *Use an index to get a CRStatement from the statement list.
+ *
+ *Returns CRStatement at position itemnr, if itemnr > number of statements - 1,
+ *it will return NULL.
+ */
+CRStatement *
+cr_statement_get_from_list (CRStatement * a_this, int itemnr)
+{
+ CRStatement *cur = NULL;
+ int nr = 0;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ for (cur = a_this; cur; cur = cur->next)
+ if (nr++ == itemnr)
+ return cur;
+ return NULL;
+}
+
+/**
+ * cr_statement_ruleset_set_sel_list:
+ *
+ *@a_this: the current ruleset statement.
+ *@a_sel_list: the selector list to set. Note
+ *that this function increments the ref count of a_sel_list.
+ *The sel list will be destroyed at the destruction of the
+ *current instance of #CRStatement.
+ *
+ *Sets a selector list to a ruleset statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_ruleset_set_sel_list (CRStatement * a_this,
+ CRSelector * a_sel_list)
+{
+ g_return_val_if_fail (a_this && a_this->type == RULESET_STMT,
+ CR_BAD_PARAM_ERROR);
+
+ if (a_this->kind.ruleset->sel_list)
+ cr_selector_unref (a_this->kind.ruleset->sel_list);
+
+ a_this->kind.ruleset->sel_list = a_sel_list;
+
+ if (a_sel_list)
+ cr_selector_ref (a_sel_list);
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_ruleset_get_declarations:
+ *
+ *@a_this: the current instance of #CRStatement.
+ *@a_decl_list: out parameter. A pointer to the returned
+ *list of declaration. Must not be NULL.
+ *
+ *Gets a pointer to the list of declaration contained
+ *in the ruleset statement.
+ *
+ *Returns CR_OK upon successful completion, an error code if something
+ *bad happened.
+ */
+enum CRStatus
+cr_statement_ruleset_get_declarations (CRStatement * a_this,
+ CRDeclaration ** a_decl_list)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == RULESET_STMT
+ && a_this->kind.ruleset
+ && a_decl_list, CR_BAD_PARAM_ERROR);
+
+ *a_decl_list = a_this->kind.ruleset->decl_list;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_ruleset_get_sel_list:
+ *
+ *@a_this: the current ruleset statement.
+ *@a_list: out parameter. The returned selector list,
+ *if and only if the function returned CR_OK.
+ *
+ *Gets a pointer to the selector list contained in
+ *the current ruleset statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_ruleset_get_sel_list (CRStatement const * a_this, CRSelector ** a_list)
+{
+ g_return_val_if_fail (a_this && a_this->type == RULESET_STMT
+ && a_this->kind.ruleset, CR_BAD_PARAM_ERROR);
+
+ *a_list = a_this->kind.ruleset->sel_list;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_ruleset_set_decl_list:
+ *
+ *@a_this: the current ruleset statement.
+ *@a_list: the declaration list to be added to the current
+ *ruleset statement.
+ *
+ *Sets a declaration list to the current ruleset statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_ruleset_set_decl_list (CRStatement * a_this,
+ CRDeclaration * a_list)
+{
+ g_return_val_if_fail (a_this && a_this->type == RULESET_STMT
+ && a_this->kind.ruleset, CR_BAD_PARAM_ERROR);
+
+ if (a_this->kind.ruleset->decl_list == a_list)
+ return CR_OK;
+
+ if (a_this->kind.ruleset->sel_list) {
+ cr_declaration_destroy (a_this->kind.ruleset->decl_list);
+ }
+
+ a_this->kind.ruleset->sel_list = NULL;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_ruleset_append_decl2:
+ *
+ *@a_this: the current statement.
+ *@a_prop: the property of the declaration.
+ *@a_value: the value of the declaration.
+ *
+ *Appends a declaration to the current ruleset statement.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_statement_ruleset_append_decl2 (CRStatement * a_this,
+ CRString * a_prop,
+ CRTerm * a_value)
+{
+ CRDeclaration *new_decls = NULL;
+
+ g_return_val_if_fail (a_this && a_this->type == RULESET_STMT
+ && a_this->kind.ruleset, CR_BAD_PARAM_ERROR);
+
+ new_decls = cr_declaration_append2
+ (a_this->kind.ruleset->decl_list,
+ a_prop, a_value);
+ g_return_val_if_fail (new_decls, CR_ERROR);
+ a_this->kind.ruleset->decl_list = new_decls;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_ruleset_append_decl:
+ *
+ *Appends a declaration to the current statement.
+ *
+ *@a_this: the current statement.
+ *@a_declaration: the declaration to append.
+ *
+ *Returns CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_statement_ruleset_append_decl (CRStatement * a_this,
+ CRDeclaration * a_decl)
+{
+ CRDeclaration *new_decls = NULL;
+
+ g_return_val_if_fail (a_this && a_this->type == RULESET_STMT
+ && a_this->kind.ruleset, CR_BAD_PARAM_ERROR);
+
+ new_decls = cr_declaration_append
+ (a_this->kind.ruleset->decl_list, a_decl);
+ g_return_val_if_fail (new_decls, CR_ERROR);
+ a_this->kind.ruleset->decl_list = new_decls;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_at_import_rule_set_imported_sheet:
+ *
+ *Sets a stylesheet to the current \@import rule.
+ *@a_this: the current \@import rule.
+ *@a_sheet: the stylesheet. The stylesheet is owned
+ *by the current instance of #CRStatement, that is, the
+ *stylesheet will be destroyed when the current instance
+ *of #CRStatement is destroyed.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_import_rule_set_imported_sheet (CRStatement * a_this,
+ CRStyleSheet * a_sheet)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_IMPORT_RULE_STMT
+ && a_this->kind.import_rule,
+ CR_BAD_PARAM_ERROR);
+
+ a_this->kind.import_rule->sheet = a_sheet;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_at_import_rule_get_imported_sheet:
+ *
+ *@a_this: the current \@import rule statement.
+ *@a_sheet: out parameter. The returned stylesheet if and
+ *only if the function returns CR_OK.
+ *
+ *Gets the stylesheet contained by the \@import rule statement.
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_import_rule_get_imported_sheet (CRStatement * a_this,
+ CRStyleSheet ** a_sheet)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_IMPORT_RULE_STMT
+ && a_this->kind.import_rule,
+ CR_BAD_PARAM_ERROR);
+ *a_sheet = a_this->kind.import_rule->sheet;
+ return CR_OK;
+
+}
+
+/**
+ * cr_statement_at_import_rule_set_url:
+ *
+ *@a_this: the current \@import rule statement.
+ *@a_url: the url to set.
+ *
+ *Sets an url to the current \@import rule statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_import_rule_set_url (CRStatement * a_this,
+ CRString * a_url)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_IMPORT_RULE_STMT
+ && a_this->kind.import_rule,
+ CR_BAD_PARAM_ERROR);
+
+ if (a_this->kind.import_rule->url) {
+ cr_string_destroy (a_this->kind.import_rule->url);
+ }
+
+ a_this->kind.import_rule->url = a_url;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_at_import_rule_get_url:
+ *
+ *@a_this: the current \@import rule statement.
+ *@a_url: out parameter. The returned url if
+ *and only if the function returned CR_OK.
+ *
+ *Gets the url of the \@import rule statement.
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_import_rule_get_url (CRStatement const * a_this,
+ CRString ** a_url)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_IMPORT_RULE_STMT
+ && a_this->kind.import_rule,
+ CR_BAD_PARAM_ERROR);
+
+ *a_url = a_this->kind.import_rule->url;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_at_media_nr_rules:
+ *
+ *@a_this: the current instance of #CRStatement.
+ *
+ *Returns the number of rules in the media rule;
+ */
+int
+cr_statement_at_media_nr_rules (CRStatement const * a_this)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_MEDIA_RULE_STMT
+ && a_this->kind.media_rule, CR_BAD_PARAM_ERROR);
+
+ return cr_statement_nr_rules (a_this->kind.media_rule->rulesets);
+}
+
+/**
+ * cr_statement_at_media_get_from_list:
+ *
+ *@a_this: the current instance of #CRStatement.
+ *@itemnr: the index into the media rule list of rules.
+ *
+ *Use an index to get a CRStatement from the media rule list of rules.
+ *
+ *Returns CRStatement at position itemnr, if itemnr > number of rules - 1,
+ *it will return NULL.
+ */
+CRStatement *
+cr_statement_at_media_get_from_list (CRStatement * a_this, int itemnr)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_MEDIA_RULE_STMT
+ && a_this->kind.media_rule, NULL);
+
+ return cr_statement_get_from_list (a_this->kind.media_rule->rulesets,
+ itemnr);
+}
+
+/**
+ * cr_statement_at_page_rule_set_declarations:
+ *
+ *@a_this: the current \@page rule statement.
+ *@a_decl_list: the declaration list to add. Will be freed
+ *by the current instance of #CRStatement when it is destroyed.
+ *
+ *Sets a declaration list to the current \@page rule statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_page_rule_set_declarations (CRStatement * a_this,
+ CRDeclaration * a_decl_list)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_PAGE_RULE_STMT
+ && a_this->kind.page_rule, CR_BAD_PARAM_ERROR);
+
+ if (a_this->kind.page_rule->decl_list) {
+ cr_declaration_unref (a_this->kind.page_rule->decl_list);
+ }
+
+ a_this->kind.page_rule->decl_list = a_decl_list;
+
+ if (a_decl_list) {
+ cr_declaration_ref (a_decl_list);
+ }
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_at_page_rule_get_declarations:
+ *
+ *@a_this: the current \@page rule statement.
+ *@a_decl_list: out parameter. The returned declaration list.
+ *
+ *Gets the declaration list associated to the current \@page rule
+ *statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_page_rule_get_declarations (CRStatement * a_this,
+ CRDeclaration ** a_decl_list)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_PAGE_RULE_STMT
+ && a_this->kind.page_rule, CR_BAD_PARAM_ERROR);
+
+ *a_decl_list = a_this->kind.page_rule->decl_list;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_at_charset_rule_set_charset:
+ *
+ *
+ *@a_this: the current \@charset rule statement.
+ *@a_charset: the charset to set.
+ *
+ *Sets the charset of the current \@charset rule statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_charset_rule_set_charset (CRStatement * a_this,
+ CRString * a_charset)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_CHARSET_RULE_STMT
+ && a_this->kind.charset_rule,
+ CR_BAD_PARAM_ERROR);
+
+ if (a_this->kind.charset_rule->charset) {
+ cr_string_destroy (a_this->kind.charset_rule->charset);
+ }
+ a_this->kind.charset_rule->charset = a_charset;
+ return CR_OK;
+}
+
+/**
+ * cr_statement_at_charset_rule_get_charset:
+ *@a_this: the current \@charset rule statement.
+ *@a_charset: out parameter. The returned charset string if
+ *and only if the function returned CR_OK.
+ *
+ *Gets the charset string associated to the current
+ *\@charset rule statement.
+ *
+ * Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_charset_rule_get_charset (CRStatement const * a_this,
+ CRString ** a_charset)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_CHARSET_RULE_STMT
+ && a_this->kind.charset_rule,
+ CR_BAD_PARAM_ERROR);
+
+ *a_charset = a_this->kind.charset_rule->charset;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_at_font_face_rule_set_decls:
+ *
+ *@a_this: the current \@font-face rule statement.
+ *@a_decls: the declarations list to set.
+ *
+ *Sets a declaration list to the current \@font-face rule statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_font_face_rule_set_decls (CRStatement * a_this,
+ CRDeclaration * a_decls)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_FONT_FACE_RULE_STMT
+ && a_this->kind.font_face_rule,
+ CR_BAD_PARAM_ERROR);
+
+ if (a_this->kind.font_face_rule->decl_list) {
+ cr_declaration_unref (a_this->kind.font_face_rule->decl_list);
+ }
+
+ a_this->kind.font_face_rule->decl_list = a_decls;
+ cr_declaration_ref (a_decls);
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_at_font_face_rule_get_decls:
+ *
+ *@a_this: the current \@font-face rule statement.
+ *@a_decls: out parameter. The returned declaration list if
+ *and only if this function returns CR_OK.
+ *
+ *Gets the declaration list associated to the current instance
+ *of \@font-face rule statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_font_face_rule_get_decls (CRStatement * a_this,
+ CRDeclaration ** a_decls)
+{
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_FONT_FACE_RULE_STMT
+ && a_this->kind.font_face_rule,
+ CR_BAD_PARAM_ERROR);
+
+ *a_decls = a_this->kind.font_face_rule->decl_list;
+
+ return CR_OK;
+}
+
+/**
+ * cr_statement_at_font_face_rule_add_decl:
+ *
+ *@a_this: the current \@font-face rule statement.
+ *@a_prop: the property of the declaration.
+ *@a_value: the value of the declaration.
+ *
+ *Adds a declaration to the current \@font-face rule
+ *statement.
+ *
+ *Returns CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_statement_at_font_face_rule_add_decl (CRStatement * a_this,
+ CRString * a_prop, CRTerm * a_value)
+{
+ CRDeclaration *decls = NULL;
+
+ g_return_val_if_fail (a_this
+ && a_this->type == AT_FONT_FACE_RULE_STMT
+ && a_this->kind.font_face_rule,
+ CR_BAD_PARAM_ERROR);
+
+ decls = cr_declaration_append2
+ (a_this->kind.font_face_rule->decl_list,
+ a_prop, a_value);
+
+ g_return_val_if_fail (decls, CR_ERROR);
+
+ if (a_this->kind.font_face_rule->decl_list == NULL)
+ cr_declaration_ref (decls);
+
+ a_this->kind.font_face_rule->decl_list = decls;
+
+ return CR_OK;
+}
+
+
+/**
+ * cr_statement_to_string:
+ *
+ *@a_this: the current statement to serialize
+ *@a_indent: the number of white space of indentation.
+ *
+ *Serializes a css statement into a string
+ *
+ *Returns the serialized statement. Must be freed by the caller
+ *using g_free().
+ */
+gchar *
+cr_statement_to_string (CRStatement const * a_this, gulong a_indent)
+{
+ gchar *str = NULL ;
+
+ if (!a_this)
+ return NULL;
+
+ switch (a_this->type) {
+ case RULESET_STMT:
+ str = cr_statement_ruleset_to_string
+ (a_this, a_indent);
+ break;
+
+ case AT_FONT_FACE_RULE_STMT:
+ str = cr_statement_font_face_rule_to_string
+ (a_this, a_indent) ;
+ break;
+
+ case AT_CHARSET_RULE_STMT:
+ str = cr_statement_charset_to_string
+ (a_this, a_indent);
+ break;
+
+ case AT_PAGE_RULE_STMT:
+ str = cr_statement_at_page_rule_to_string
+ (a_this, a_indent);
+ break;
+
+ case AT_MEDIA_RULE_STMT:
+ str = cr_statement_media_rule_to_string
+ (a_this, a_indent);
+ break;
+
+ case AT_IMPORT_RULE_STMT:
+ str = cr_statement_import_rule_to_string
+ (a_this, a_indent);
+ break;
+
+ default:
+ cr_utils_trace_info ("Statement unrecognized");
+ break;
+ }
+ return str ;
+}
+
+gchar*
+cr_statement_list_to_string (CRStatement const *a_this, gulong a_indent)
+{
+ CRStatement const *cur_stmt = NULL ;
+ GString *stringue = NULL ;
+ gchar *str = NULL ;
+
+ g_return_val_if_fail (a_this, NULL) ;
+
+ stringue = g_string_new (NULL) ;
+ if (!stringue) {
+ cr_utils_trace_info ("Out of memory") ;
+ return NULL ;
+ }
+ for (cur_stmt = a_this ; cur_stmt;
+ cur_stmt = cur_stmt->next) {
+ str = cr_statement_to_string (cur_stmt, a_indent) ;
+ if (str) {
+ if (!cur_stmt->prev) {
+ g_string_append (stringue, str) ;
+ } else {
+ g_string_append_printf
+ (stringue, "\n%s", str) ;
+ }
+ g_free (str) ;
+ str = NULL ;
+ }
+ }
+ str = stringue->str ;
+ g_string_free (stringue, FALSE) ;
+ return str ;
+}
+
+/**
+ * cr_statement_dump:
+ *
+ *@a_this: the current css2 statement.
+ *@a_fp: the destination file pointer.
+ *@a_indent: the number of white space indentation characters.
+ *
+ *Dumps the css2 statement to a file.
+ */
+void
+cr_statement_dump (CRStatement const * a_this, FILE * a_fp, gulong a_indent)
+{
+ gchar *str = NULL ;
+
+ if (!a_this)
+ return;
+
+ str = cr_statement_to_string (a_this, a_indent) ;
+ if (str) {
+ fprintf (a_fp, "%s",str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+}
+
+/**
+ * cr_statement_dump_ruleset:
+ *
+ *@a_this: the current instance of #CRStatement.
+ *@a_fp: the destination file pointer.
+ *@a_indent: the number of indentation white spaces to add.
+ *
+ *Dumps a ruleset statement to a file.
+ */
+void
+cr_statement_dump_ruleset (CRStatement const * a_this, FILE * a_fp, glong a_indent)
+{
+ gchar *str = NULL;
+
+ g_return_if_fail (a_fp && a_this);
+ str = cr_statement_ruleset_to_string (a_this, a_indent);
+ if (str) {
+ fprintf (a_fp, "%s", str);
+ g_free (str);
+ str = NULL;
+ }
+}
+
+/**
+ * cr_statement_dump_font_face_rule:
+ *
+ *@a_this: the current instance of font face rule statement.
+ *@a_fp: the destination file pointer.
+ *@a_indent: the number of white space indentation.
+ *
+ *Dumps a font face rule statement to a file.
+ */
+void
+cr_statement_dump_font_face_rule (CRStatement const * a_this, FILE * a_fp,
+ glong a_indent)
+{
+ gchar *str = NULL ;
+ g_return_if_fail (a_this
+ && a_this->type == AT_FONT_FACE_RULE_STMT);
+
+ str = cr_statement_font_face_rule_to_string (a_this,
+ a_indent) ;
+ if (str) {
+ fprintf (a_fp, "%s", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+}
+
+/**
+ * cr_statement_dump_charset:
+ *
+ *@a_this: the current instance of the \@charset rule statement.
+ *@a_fp: the destination file pointer.
+ *@a_indent: the number of indentation white spaces.
+ *
+ *Dumps an \@charset rule statement to a file.
+ */
+void
+cr_statement_dump_charset (CRStatement const * a_this, FILE * a_fp, gulong a_indent)
+{
+ gchar *str = NULL;
+
+ g_return_if_fail (a_this && a_this->type == AT_CHARSET_RULE_STMT);
+
+ str = cr_statement_charset_to_string (a_this,
+ a_indent) ;
+ if (str) {
+ fprintf (a_fp, "%s", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+}
+
+
+/**
+ * cr_statement_dump_page:
+ *
+ *@a_this: the statement to dump on stdout.
+ *@a_fp: the destination file pointer.
+ *@a_indent: the number of indentation white spaces.
+ *
+ *Dumps an \@page rule statement on stdout.
+ */
+void
+cr_statement_dump_page (CRStatement const * a_this, FILE * a_fp, gulong a_indent)
+{
+ gchar *str = NULL;
+
+ g_return_if_fail (a_this
+ && a_this->type == AT_PAGE_RULE_STMT
+ && a_this->kind.page_rule);
+
+ str = cr_statement_at_page_rule_to_string (a_this, a_indent) ;
+ if (str) {
+ fprintf (a_fp, "%s", str);
+ g_free (str) ;
+ str = NULL ;
+ }
+}
+
+
+/**
+ * cr_statement_dump_media_rule:
+ *
+ *@a_this: the statement to dump.
+ *@a_fp: the destination file pointer
+ *@a_indent: the number of white spaces indentation.
+ *
+ *Dumps an \@media rule statement to a file.
+ */
+void
+cr_statement_dump_media_rule (CRStatement const * a_this,
+ FILE * a_fp,
+ gulong a_indent)
+{
+ gchar *str = NULL ;
+ g_return_if_fail (a_this->type == AT_MEDIA_RULE_STMT);
+
+ str = cr_statement_media_rule_to_string (a_this, a_indent) ;
+ if (str) {
+ fprintf (a_fp, "%s", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+}
+
+/**
+ * cr_statement_dump_import_rule:
+ *
+ *@a_fp: the destination file pointer.
+ *@a_indent: the number of white space indentations.
+ *
+ *Dumps an \@import rule statement to a file.
+ */
+void
+cr_statement_dump_import_rule (CRStatement const * a_this, FILE * a_fp,
+ gulong a_indent)
+{
+ gchar *str = NULL ;
+ g_return_if_fail (a_this
+ && a_this->type == AT_IMPORT_RULE_STMT
+ && a_fp
+ && a_this->kind.import_rule);
+
+ str = cr_statement_import_rule_to_string (a_this, a_indent) ;
+ if (str) {
+ fprintf (a_fp, "%s", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+}
+
+/**
+ * cr_statement_destroy:
+ *
+ * @a_this: the current instance of #CRStatement.
+ *
+ *Destructor of #CRStatement.
+ */
+void
+cr_statement_destroy (CRStatement * a_this)
+{
+ CRStatement *cur = NULL;
+
+ g_return_if_fail (a_this);
+
+ /*go get the tail of the list */
+ for (cur = a_this; cur && cur->next; cur = cur->next) {
+ cr_statement_clear (cur);
+ }
+
+ if (cur)
+ cr_statement_clear (cur);
+
+ if (cur->prev == NULL) {
+ g_free (a_this);
+ return;
+ }
+
+ /*walk backward and free next element */
+ for (cur = cur->prev; cur && cur->prev; cur = cur->prev) {
+ if (cur->next) {
+ g_free (cur->next);
+ cur->next = NULL;
+ }
+ }
+
+ if (!cur)
+ return;
+
+ /*free the one remaining list */
+ if (cur->next) {
+ g_free (cur->next);
+ cur->next = NULL;
+ }
+
+ g_free (cur);
+ cur = NULL;
+}
diff --git a/src/3rdparty/libcroco/src/cr-statement.h b/src/3rdparty/libcroco/src/cr-statement.h
new file mode 100644
index 0000000..06538d0
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-statement.h
@@ -0,0 +1,440 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include <stdio.h>
+#include "cr-utils.h"
+#include "cr-term.h"
+#include "cr-selector.h"
+#include "cr-declaration.h"
+
+#ifndef __CR_STATEMENT_H__
+#define __CR_STATEMENT_H__
+
+G_BEGIN_DECLS
+
+/**
+ *@file
+ *Declaration of the #CRStatement class.
+ */
+
+/*
+ *forward declaration of CRStyleSheet which is defined in
+ *cr-stylesheet.h
+ */
+
+struct _CRStatement ;
+
+/*
+ *typedef struct _CRStatement CRStatement ;
+ *this is forward declared in
+ *cr-declaration.h already.
+ */
+
+struct _CRAtMediaRule ;
+typedef struct _CRAtMediaRule CRAtMediaRule ;
+
+typedef struct _CRRuleSet CRRuleSet ;
+
+/**
+ *The abstraction of a css ruleset.
+ *A ruleset is made of a list of selectors,
+ *followed by a list of declarations.
+ */
+struct _CRRuleSet
+{
+ /**A list of instances of #CRSimpeSel*/
+ CRSelector *sel_list ;
+
+ /**A list of instances of #CRDeclaration*/
+ CRDeclaration *decl_list ;
+
+ /**
+ *The parent media rule, or NULL if
+ *no parent media rule exists.
+ */
+ CRStatement *parent_media_rule ;
+} ;
+
+/*
+ *a forward declaration of CRStylesheet.
+ *CRStylesheet is actually declared in
+ *cr-stylesheet.h
+ */
+struct _CRStyleSheet ;
+typedef struct _CRStyleSheet CRStyleSheet;
+
+
+/**The \@import rule abstraction.*/
+typedef struct _CRAtImportRule CRAtImportRule ;
+struct _CRAtImportRule
+{
+ /**the url of the import rule*/
+ CRString *url ;
+
+ GList *media_list ;
+
+ /**
+ *the stylesheet fetched from the url, if any.
+ *this is not "owned" by #CRAtImportRule which means
+ *it is not destroyed by the destructor of #CRAtImportRule.
+ */
+ CRStyleSheet * sheet;
+};
+
+
+/**abstraction of an \@media rule*/
+struct _CRAtMediaRule
+{
+ GList *media_list ;
+ CRStatement *rulesets ;
+} ;
+
+
+typedef struct _CRAtPageRule CRAtPageRule ;
+/**The \@page rule abstraction*/
+struct _CRAtPageRule
+{
+ /**a list of instances of #CRDeclaration*/
+ CRDeclaration *decl_list ;
+
+ /**page selector. Is a pseudo selector*/
+ CRString *name ;
+ CRString *pseudo ;
+} ;
+
+/**The \@charset rule abstraction*/
+typedef struct _CRAtCharsetRule CRAtCharsetRule ;
+struct _CRAtCharsetRule
+{
+ CRString * charset ;
+};
+
+/**The abstraction of the \@font-face rule.*/
+typedef struct _CRAtFontFaceRule CRAtFontFaceRule ;
+struct _CRAtFontFaceRule
+{
+ /*a list of instanaces of #CRDeclaration*/
+ CRDeclaration *decl_list ;
+} ;
+
+
+/**
+ *The possible types of css2 statements.
+ */
+enum CRStatementType
+{
+ /**
+ *A generic css at-rule
+ *each unknown at-rule will
+ *be of this type.
+ */
+
+ /**A css at-rule*/
+ AT_RULE_STMT = 0,
+
+ /*A css ruleset*/
+ RULESET_STMT,
+
+ /**A css2 import rule*/
+ AT_IMPORT_RULE_STMT,
+
+ /**A css2 media rule*/
+ AT_MEDIA_RULE_STMT,
+
+ /**A css2 page rule*/
+ AT_PAGE_RULE_STMT,
+
+ /**A css2 charset rule*/
+ AT_CHARSET_RULE_STMT,
+
+ /**A css2 font face rule*/
+ AT_FONT_FACE_RULE_STMT
+} ;
+
+
+/**
+ *The abstraction of css statement as defined
+ *in the chapter 4 and appendix D.1 of the css2 spec.
+ *A statement is actually a double chained list of
+ *statements.A statement can be a ruleset, an \@import
+ *rule, an \@page rule etc ...
+ */
+struct _CRStatement
+{
+ /**
+ *The type of the statement.
+ */
+ enum CRStatementType type ;
+
+ union
+ {
+ CRRuleSet *ruleset ;
+ CRAtImportRule *import_rule ;
+ CRAtMediaRule *media_rule ;
+ CRAtPageRule *page_rule ;
+ CRAtCharsetRule *charset_rule ;
+ CRAtFontFaceRule *font_face_rule ;
+ } kind ;
+
+ /*
+ *the specificity of the selector
+ *that matched this statement.
+ *This is only used by the cascading
+ *order determination algorithm.
+ */
+ gulong specificity ;
+
+ /*
+ *the style sheet that contains
+ *this css statement.
+ */
+ CRStyleSheet *parent_sheet ;
+ CRStatement *next ;
+ CRStatement *prev ;
+
+ CRParsingLocation location ;
+
+ /**
+ *a custom pointer usable by
+ *applications that use libcroco.
+ *libcroco itself will never modify
+ *this pointer.
+ */
+ gpointer app_data ;
+
+ /**
+ *a custom pointer used
+ *by the upper layers of libcroco.
+ *application should never use this
+ *pointer.
+ */
+ gpointer croco_data ;
+
+} ;
+
+
+gboolean
+cr_statement_does_buf_parses_against_core (const guchar *a_buf,
+ enum CREncoding a_encoding) ;
+CRStatement *
+cr_statement_parse_from_buf (const guchar *a_buf,
+ enum CREncoding a_encoding) ;
+CRStatement*
+cr_statement_new_ruleset (CRStyleSheet *a_sheet,
+ CRSelector *a_sel_list,
+ CRDeclaration *a_decl_list,
+ CRStatement *a_media_rule) ;
+CRStatement *
+cr_statement_ruleset_parse_from_buf (const guchar * a_buf,
+ enum CREncoding a_enc) ;
+
+CRStatement*
+cr_statement_new_at_import_rule (CRStyleSheet *a_container_sheet,
+ CRString *a_url,
+ GList *a_media_list,
+ CRStyleSheet *a_imported_sheet) ;
+
+CRStatement *
+cr_statement_at_import_rule_parse_from_buf (const guchar * a_buf,
+ enum CREncoding a_encoding) ;
+
+CRStatement *
+cr_statement_new_at_media_rule (CRStyleSheet *a_sheet,
+ CRStatement *a_ruleset,
+ GList *a_media) ;
+CRStatement *
+cr_statement_at_media_rule_parse_from_buf (const guchar *a_buf,
+ enum CREncoding a_enc) ;
+
+CRStatement *
+cr_statement_new_at_charset_rule (CRStyleSheet *a_sheet,
+ CRString *a_charset) ;
+CRStatement *
+cr_statement_at_charset_rule_parse_from_buf (const guchar *a_buf,
+ enum CREncoding a_encoding);
+
+
+CRStatement *
+cr_statement_new_at_font_face_rule (CRStyleSheet *a_sheet,
+ CRDeclaration *a_font_decls) ;
+CRStatement *
+cr_statement_font_face_rule_parse_from_buf (const guchar *a_buf,
+ enum CREncoding a_encoding) ;
+
+CRStatement *
+cr_statement_new_at_page_rule (CRStyleSheet *a_sheet,
+ CRDeclaration *a_decl_list,
+ CRString *a_name,
+ CRString *a_pseudo) ;
+CRStatement *
+cr_statement_at_page_rule_parse_from_buf (const guchar *a_buf,
+ enum CREncoding a_encoding) ;
+
+enum CRStatus
+cr_statement_set_parent_sheet (CRStatement *a_this,
+ CRStyleSheet *a_sheet) ;
+
+enum CRStatus
+cr_statement_get_parent_sheet (CRStatement *a_this,
+ CRStyleSheet **a_sheet) ;
+
+CRStatement *
+cr_statement_append (CRStatement *a_this,
+ CRStatement *a_new) ;
+
+CRStatement*
+cr_statement_prepend (CRStatement *a_this,
+ CRStatement *a_new) ;
+
+CRStatement *
+cr_statement_unlink (CRStatement *a_stmt) ;
+
+enum CRStatus
+cr_statement_ruleset_set_sel_list (CRStatement *a_this,
+ CRSelector *a_sel_list) ;
+
+enum CRStatus
+cr_statement_ruleset_get_sel_list (CRStatement const *a_this,
+ CRSelector **a_list) ;
+
+enum CRStatus
+cr_statement_ruleset_set_decl_list (CRStatement *a_this,
+ CRDeclaration *a_list) ;
+
+enum CRStatus
+cr_statement_ruleset_get_declarations (CRStatement *a_this,
+ CRDeclaration **a_decl_list) ;
+
+enum CRStatus
+cr_statement_ruleset_append_decl2 (CRStatement *a_this,
+ CRString *a_prop, CRTerm *a_value) ;
+
+enum CRStatus
+cr_statement_ruleset_append_decl (CRStatement *a_this,
+ CRDeclaration *a_decl) ;
+
+enum CRStatus
+cr_statement_at_import_rule_set_imported_sheet (CRStatement *a_this,
+ CRStyleSheet *a_sheet) ;
+
+enum CRStatus
+cr_statement_at_import_rule_get_imported_sheet (CRStatement *a_this,
+ CRStyleSheet **a_sheet) ;
+
+enum CRStatus
+cr_statement_at_import_rule_set_url (CRStatement *a_this,
+ CRString *a_url) ;
+
+enum CRStatus
+cr_statement_at_import_rule_get_url (CRStatement const *a_this,
+ CRString **a_url) ;
+
+gint
+cr_statement_at_media_nr_rules (CRStatement const *a_this) ;
+
+CRStatement *
+cr_statement_at_media_get_from_list (CRStatement *a_this, int itemnr) ;
+
+enum CRStatus
+cr_statement_at_page_rule_set_sel (CRStatement *a_this,
+ CRSelector *a_sel) ;
+
+enum CRStatus
+cr_statement_at_page_rule_get_sel (CRStatement const *a_this,
+ CRSelector **a_sel) ;
+
+enum CRStatus
+cr_statement_at_page_rule_set_declarations (CRStatement *a_this,
+ CRDeclaration *a_decl_list) ;
+
+enum CRStatus
+cr_statement_at_page_rule_get_declarations (CRStatement *a_this,
+ CRDeclaration **a_decl_list) ;
+
+enum CRStatus
+cr_statement_at_charset_rule_set_charset (CRStatement *a_this,
+ CRString *a_charset) ;
+
+enum CRStatus
+cr_statement_at_charset_rule_get_charset (CRStatement const *a_this,
+ CRString **a_charset) ;
+
+enum CRStatus
+cr_statement_at_font_face_rule_set_decls (CRStatement *a_this,
+ CRDeclaration *a_decls) ;
+
+enum CRStatus
+cr_statement_at_font_face_rule_get_decls (CRStatement *a_this,
+ CRDeclaration **a_decls) ;
+
+enum CRStatus
+cr_statement_at_font_face_rule_add_decl (CRStatement *a_this,
+ CRString *a_prop,
+ CRTerm *a_value) ;
+
+gchar *
+cr_statement_to_string (CRStatement const * a_this, gulong a_indent) ;
+
+gchar*
+cr_statement_list_to_string (CRStatement const *a_this, gulong a_indent) ;
+
+void
+cr_statement_dump (CRStatement const *a_this, FILE *a_fp, gulong a_indent) ;
+
+void
+cr_statement_dump_ruleset (CRStatement const * a_this, FILE * a_fp,
+ glong a_indent) ;
+
+void
+cr_statement_dump_font_face_rule (CRStatement const * a_this,
+ FILE * a_fp,
+ glong a_indent) ;
+
+void
+cr_statement_dump_page (CRStatement const * a_this, FILE * a_fp,
+ gulong a_indent) ;
+
+
+void
+cr_statement_dump_media_rule (CRStatement const * a_this,
+ FILE * a_fp,
+ gulong a_indent) ;
+
+void
+cr_statement_dump_import_rule (CRStatement const * a_this, FILE * a_fp,
+ gulong a_indent) ;
+void
+cr_statement_dump_charset (CRStatement const * a_this, FILE * a_fp,
+ gulong a_indent) ;
+gint
+cr_statement_nr_rules (CRStatement const *a_this) ;
+
+CRStatement *
+cr_statement_get_from_list (CRStatement *a_this, int itemnr) ;
+
+void
+cr_statement_destroy (CRStatement *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_STATEMENT_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-string.c b/src/3rdparty/libcroco/src/cr-string.c
new file mode 100644
index 0000000..ec5840e
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-string.c
@@ -0,0 +1,170 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli.
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include <string.h>
+#include "cr-string.h"
+
+/**
+ *Instantiates a #CRString
+ *@return the newly instantiated #CRString
+ *Must be freed with cr_string_destroy().
+ */
+CRString *
+cr_string_new (void)
+{
+ CRString *result = NULL ;
+
+ result = (CRString *) g_try_malloc (sizeof (CRString)) ;
+ if (!result) {
+ cr_utils_trace_info ("Out of memory") ;
+ return NULL ;
+ }
+ memset (result, 0, sizeof (CRString)) ;
+ result->stryng = g_string_new (NULL) ;
+ return result ;
+}
+
+/**
+ *Instantiate a string and initialise it to
+ *a_string.
+ *@param a_string the initial string
+ *@return the newly instantiated string.
+ */
+CRString *
+cr_string_new_from_string (const gchar * a_string)
+{
+ CRString *result = NULL ;
+
+ result = cr_string_new () ;
+ if (!result) {
+ cr_utils_trace_info ("Out of memory") ;
+ return NULL ;
+ }
+ if (a_string)
+ g_string_append (result->stryng, a_string) ;
+ return result ;
+}
+
+/**
+ *Instantiates a #CRString from an instance of GString.
+ *@param a_string the input string that will be copied into
+ *the newly instantiated #CRString
+ *@return the newly instantiated #CRString.
+ */
+CRString *
+cr_string_new_from_gstring (GString const *a_string)
+{
+ CRString *result = NULL ;
+
+ result = cr_string_new () ;
+ if (!result) {
+ cr_utils_trace_info ("Out of memory") ;
+ return NULL ;
+ }
+ if (a_string) {
+ g_string_append_len (result->stryng,
+ a_string->str,
+ a_string->len);
+
+ }
+ return result ;
+}
+
+CRString *
+cr_string_dup (CRString const *a_this)
+{
+ CRString *result = NULL ;
+ g_return_val_if_fail (a_this, NULL) ;
+
+ result = cr_string_new_from_gstring (a_this->stryng) ;
+ if (!result) {
+ cr_utils_trace_info ("Out of memory") ;
+ return NULL ;
+ }
+ cr_parsing_location_copy (&result->location,
+ &a_this->location) ;
+ return result ;
+}
+
+gchar *
+cr_string_dup2 (CRString const *a_this)
+{
+ gchar *result = NULL ;
+
+ g_return_val_if_fail (a_this, NULL) ;
+
+ if (a_this
+ && a_this->stryng
+ && a_this->stryng->str) {
+ result = g_strndup (a_this->stryng->str,
+ a_this->stryng->len) ;
+ }
+ return result ;
+}
+
+/**
+ *Returns a pointer to the internal raw NULL terminated string
+ *of the current instance of #CRString.
+ *@param a_this the current instance of #CRString
+ */
+const gchar *
+cr_string_peek_raw_str (CRString const *a_this)
+{
+ g_return_val_if_fail (a_this, NULL) ;
+
+ if (a_this->stryng && a_this->stryng->str)
+ return a_this->stryng->str ;
+ return NULL ;
+}
+
+/**
+ *Returns the length of the internal raw NULL terminated
+ *string of the current instance of #CRString.
+ *@param a_this the current instance of #CRString.
+ *@return the len of the internal raw NULL termninated string,
+ *of -1 if no length can be returned.
+ */
+gint
+cr_string_peek_raw_str_len (CRString const *a_this)
+{
+ g_return_val_if_fail (a_this && a_this->stryng,
+ -1) ;
+ return a_this->stryng->len ;
+}
+
+/**
+ *@param a_this the #CRString to destroy.
+ */
+void
+cr_string_destroy (CRString *a_this)
+{
+ if (!a_this) {
+ return;
+ }
+
+ if (a_this->stryng) {
+ g_string_free (a_this->stryng, TRUE) ;
+ a_this->stryng = NULL ;
+ }
+ g_free (a_this) ;
+}
diff --git a/src/3rdparty/libcroco/src/cr-string.h b/src/3rdparty/libcroco/src/cr-string.h
new file mode 100644
index 0000000..2700f0e
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-string.h
@@ -0,0 +1,76 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * See COPYRIGHTS file for copyright information.
+ */
+
+/**
+ *@file
+ *Declaration file of the #CRString class.
+ */
+
+#ifndef __CR_STRING_H__
+#define __CR_STRING_H__
+
+#include <glib.h>
+#include "cr-utils.h"
+#include "cr-parsing-location.h"
+
+G_BEGIN_DECLS
+
+typedef struct _CRString CRString ;
+
+/**
+ *This is a ship implementation of string based on GString.
+ *Actually, the aim of CRString is to store the parsing location
+ *(line,column,byte offset) at which a given string has been parsed
+ *in the input CSS.
+ *So this class has a gstring field of type GString that users can
+ *freely manipulate, and also a CRParginLocation type where the
+ *parsing location is store. If you don't want to deal with parsing
+ *location stuffs, then use GString instead. If we were in C++ for example,
+ *CRString would just inherit GString and just add accessors to
+ *the CRParsingLocation data ... but we are not and we still have
+ *to provide the parsing location information.
+ */
+struct _CRString {
+ /**
+ *The GString where all the string
+ *operation happen.
+ */
+ GString *stryng ;
+ /**
+ *The parsing location storage area.
+ */
+ CRParsingLocation location ;
+} ;
+
+CRString * cr_string_new (void) ;
+
+CRString *cr_string_new_from_string (const gchar * a_string) ;
+CRString * cr_string_new_from_gstring (GString const *a_string) ;
+CRString *cr_string_dup (CRString const *a_this) ;
+gchar *cr_string_dup2 (CRString const *a_this) ;
+const gchar *cr_string_peek_raw_str (CRString const *a_this) ;
+gint cr_string_peek_raw_str_len (CRString const *a_this) ;
+void cr_string_destroy (CRString *a_this) ;
+
+G_END_DECLS
+
+#endif
diff --git a/src/3rdparty/libcroco/src/cr-style.c b/src/3rdparty/libcroco/src/cr-style.c
new file mode 100644
index 0000000..9653c50
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-style.c
@@ -0,0 +1,2852 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of
+ * the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the
+ * GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli.
+ * see COPYRIGHTS file for copyright information
+ */
+
+#include <string.h>
+#include "cr-style.h"
+
+/**
+ *@file
+ *The definition of the #CRStyle class.
+ */
+
+/**
+ *A property ID.
+ *Each supported css property has an ID which is
+ *an entry into a property "population" jump table.
+ *each entry of the property population jump table
+ *contains code to transform the literal form of
+ *a property value into a strongly typed value.
+ */
+enum CRPropertyID {
+ PROP_ID_NOT_KNOWN = 0,
+ PROP_ID_PADDING_TOP,
+ PROP_ID_PADDING_RIGHT,
+ PROP_ID_PADDING_BOTTOM,
+ PROP_ID_PADDING_LEFT,
+ PROP_ID_PADDING,
+ PROP_ID_BORDER_TOP_WIDTH,
+ PROP_ID_BORDER_RIGHT_WIDTH,
+ PROP_ID_BORDER_BOTTOM_WIDTH,
+ PROP_ID_BORDER_LEFT_WIDTH,
+ PROP_ID_BORDER_WIDTH,
+ PROP_ID_BORDER_TOP_STYLE,
+ PROP_ID_BORDER_RIGHT_STYLE,
+ PROP_ID_BORDER_BOTTOM_STYLE,
+ PROP_ID_BORDER_LEFT_STYLE,
+ PROP_ID_BORDER_STYLE,
+ PROP_ID_BORDER_TOP_COLOR,
+ PROP_ID_BORDER_RIGHT_COLOR,
+ PROP_ID_BORDER_BOTTOM_COLOR,
+ PROP_ID_BORDER_LEFT_COLOR,
+ PROP_ID_BORDER_TOP,
+ PROP_ID_BORDER_RIGHT,
+ PROP_ID_BORDER_BOTTOM,
+ PROP_ID_BORDER_LEFT,
+ PROP_ID_BORDER,
+ PROP_ID_MARGIN_TOP,
+ PROP_ID_MARGIN_RIGHT,
+ PROP_ID_MARGIN_BOTTOM,
+ PROP_ID_MARGIN_LEFT,
+ PROP_ID_MARGIN,
+ PROP_ID_DISPLAY,
+ PROP_ID_POSITION,
+ PROP_ID_TOP,
+ PROP_ID_RIGHT,
+ PROP_ID_BOTTOM,
+ PROP_ID_LEFT,
+ PROP_ID_FLOAT,
+ PROP_ID_WIDTH,
+ PROP_ID_COLOR,
+ PROP_ID_BACKGROUND_COLOR,
+ PROP_ID_FONT_FAMILY,
+ PROP_ID_FONT_SIZE,
+ PROP_ID_FONT_STYLE,
+ PROP_ID_FONT_WEIGHT,
+ PROP_ID_WHITE_SPACE,
+ /*should be the last one. */
+ NB_PROP_IDS
+};
+
+typedef struct _CRPropertyDesc CRPropertyDesc;
+
+struct _CRPropertyDesc {
+ const gchar *name;
+ enum CRPropertyID prop_id;
+};
+
+static CRPropertyDesc gv_prop_table[] = {
+ {"padding-top", PROP_ID_PADDING_TOP},
+ {"padding-right", PROP_ID_PADDING_RIGHT},
+ {"padding-bottom", PROP_ID_PADDING_BOTTOM},
+ {"padding-left", PROP_ID_PADDING_LEFT},
+ {"padding", PROP_ID_PADDING},
+ {"border-top-width", PROP_ID_BORDER_TOP_WIDTH},
+ {"border-right-width", PROP_ID_BORDER_RIGHT_WIDTH},
+ {"border-bottom-width", PROP_ID_BORDER_BOTTOM_WIDTH},
+ {"border-left-width", PROP_ID_BORDER_LEFT_WIDTH},
+ {"border-width", PROP_ID_BORDER_WIDTH},
+ {"border-top-style", PROP_ID_BORDER_TOP_STYLE},
+ {"border-right-style", PROP_ID_BORDER_RIGHT_STYLE},
+ {"border-bottom-style", PROP_ID_BORDER_BOTTOM_STYLE},
+ {"border-left-style", PROP_ID_BORDER_LEFT_STYLE},
+ {"border-style", PROP_ID_BORDER_STYLE},
+ {"border-top", PROP_ID_BORDER_TOP},
+ {"border-right", PROP_ID_BORDER_RIGHT},
+ {"border-bottom", PROP_ID_BORDER_BOTTOM},
+ {"border-left", PROP_ID_BORDER_LEFT},
+ {"border", PROP_ID_BORDER},
+ {"margin-top", PROP_ID_MARGIN_TOP},
+ {"margin-right", PROP_ID_MARGIN_RIGHT},
+ {"margin-bottom", PROP_ID_MARGIN_BOTTOM},
+ {"margin-left", PROP_ID_MARGIN_LEFT},
+ {"margin", PROP_ID_MARGIN},
+ {"display", PROP_ID_DISPLAY},
+ {"position", PROP_ID_POSITION},
+ {"top", PROP_ID_TOP},
+ {"right", PROP_ID_RIGHT},
+ {"bottom", PROP_ID_BOTTOM},
+ {"left", PROP_ID_LEFT},
+ {"float", PROP_ID_FLOAT},
+ {"width", PROP_ID_WIDTH},
+ {"color", PROP_ID_COLOR},
+ {"border-top-color", PROP_ID_BORDER_TOP_COLOR},
+ {"border-right-color", PROP_ID_BORDER_RIGHT_COLOR},
+ {"border-bottom-color", PROP_ID_BORDER_BOTTOM_COLOR},
+ {"border-left-color", PROP_ID_BORDER_LEFT_COLOR},
+ {"background-color", PROP_ID_BACKGROUND_COLOR},
+ {"font-family", PROP_ID_FONT_FAMILY},
+ {"font-size", PROP_ID_FONT_SIZE},
+ {"font-style", PROP_ID_FONT_STYLE},
+ {"font-weight", PROP_ID_FONT_WEIGHT},
+ {"white-space", PROP_ID_WHITE_SPACE},
+ /*must be the last one */
+ {NULL, (enum CRPropertyID) 0}
+};
+
+/**
+ *A the key/value pair of this hash table
+ *are:
+ *key => name of the css property found in gv_prop_table
+ *value => matching property id found in gv_prop_table.
+ *So this hash table is here just to retrieval of a property id
+ *from a property name.
+ */
+static GHashTable *gv_prop_hash = NULL;
+
+/**
+ *incremented by each new instance of #CRStyle
+ *and decremented at the it destroy time.
+ *When this reaches zero, gv_prop_hash is destroyed.
+ */
+static gulong gv_prop_hash_ref_count = 0;
+
+struct CRNumPropEnumDumpInfo {
+ enum CRNumProp code;
+ const gchar *str;
+};
+
+static struct CRNumPropEnumDumpInfo gv_num_props_dump_infos[] = {
+ {NUM_PROP_TOP, "top"},
+ {NUM_PROP_RIGHT, "right"},
+ {NUM_PROP_BOTTOM, "bottom"},
+ {NUM_PROP_LEFT, "left"},
+ {NUM_PROP_PADDING_TOP, "padding-top"},
+ {NUM_PROP_PADDING_RIGHT, "padding-right"},
+ {NUM_PROP_PADDING_BOTTOM, "padding-bottom"},
+ {NUM_PROP_PADDING_LEFT, "padding-left"},
+ {NUM_PROP_BORDER_TOP, "border-top"},
+ {NUM_PROP_BORDER_RIGHT, "border-right"},
+ {NUM_PROP_BORDER_BOTTOM, "border-bottom"},
+ {NUM_PROP_BORDER_LEFT, "border-left"},
+ {NUM_PROP_MARGIN_TOP, "margin-top"},
+ {NUM_PROP_MARGIN_RIGHT, "margin-right"},
+ {NUM_PROP_MARGIN_BOTTOM, "margin-bottom"},
+ {NUM_PROP_MARGIN_LEFT, "margin-left"},
+ {NUM_PROP_WIDTH, "width"},
+ {(enum CRNumProp) 0, NULL}
+};
+
+struct CRRgbPropEnumDumpInfo {
+ enum CRRgbProp code;
+ const gchar *str;
+};
+
+static struct CRRgbPropEnumDumpInfo gv_rgb_props_dump_infos[] = {
+ {RGB_PROP_BORDER_TOP_COLOR, "border-top-color"},
+ {RGB_PROP_BORDER_RIGHT_COLOR, "border-right-color"},
+ {RGB_PROP_BORDER_BOTTOM_COLOR, "bottom-color"},
+ {RGB_PROP_BORDER_LEFT_COLOR, "left-color"},
+ {RGB_PROP_COLOR, "color"},
+ {RGB_PROP_BACKGROUND_COLOR, "background-color"},
+ {(enum CRRgbProp) 0, NULL}
+};
+
+struct CRBorderStylePropEnumDumpInfo {
+ enum CRBorderStyleProp code;
+ const gchar *str;
+
+};
+
+static struct CRBorderStylePropEnumDumpInfo gv_border_style_props_dump_infos[]
+ = {
+ {BORDER_STYLE_PROP_TOP, "border-style-top"},
+ {BORDER_STYLE_PROP_RIGHT, "border-style-right"},
+ {BORDER_STYLE_PROP_BOTTOM, "boder-style-bottom"},
+ {BORDER_STYLE_PROP_LEFT, "border-style-left"},
+ {(enum CRBorderStyleProp) 0, NULL}
+};
+
+static enum CRStatus
+ cr_style_init_properties (void);
+
+enum CRDirection {
+ DIR_TOP = 0,
+ DIR_RIGHT,
+ DIR_BOTTOM,
+ DIR_LEFT,
+
+ /*must be the last one */
+ NB_DIRS
+};
+
+static const gchar *num_prop_code_to_string (enum CRNumProp a_code);
+
+static const gchar *rgb_prop_code_to_string (enum CRRgbProp a_code);
+
+static const gchar *border_style_prop_code_to_string (enum CRBorderStyleProp
+ a_code);
+
+static enum CRStatus
+set_prop_padding_x_from_value (CRStyle * a_style,
+ CRTerm * a_value, enum CRDirection a_dir);
+
+static enum CRStatus
+set_prop_border_x_width_from_value (CRStyle * a_style,
+ CRTerm * a_value,
+ enum CRDirection a_dir);
+static enum CRStatus
+set_prop_border_width_from_value (CRStyle *a_style,
+ CRTerm *a_value) ;
+
+static enum CRStatus
+set_prop_border_x_style_from_value (CRStyle * a_style,
+ CRTerm * a_value,
+ enum CRDirection a_dir);
+static enum CRStatus
+set_prop_border_style_from_value (CRStyle *a_style,
+ CRTerm *a_value) ;
+
+static enum CRStatus
+set_prop_margin_x_from_value (CRStyle * a_style, CRTerm * a_value,
+ enum CRDirection a_dir);
+
+static enum CRStatus
+set_prop_display_from_value (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_position_from_value (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_x_from_value (CRStyle * a_style, CRTerm * a_value,
+ enum CRDirection a_dir);
+
+static enum CRStatus
+set_prop_float (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_width (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_color (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_background_color (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_border_x_color_from_value (CRStyle * a_style, CRTerm * a_value,
+ enum CRDirection a_dir);
+
+static enum CRStatus
+set_prop_border_x_from_value (CRStyle * a_style, CRTerm * a_value,
+ enum CRDirection a_dir);
+
+static enum CRStatus
+set_prop_border_from_value (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_padding_from_value (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_margin_from_value (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_font_family_from_value (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+init_style_font_size_field (CRStyle * a_style);
+
+static enum CRStatus
+set_prop_font_size_from_value (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_font_style_from_value (CRStyle * a_style, CRTerm * a_value);
+
+static enum CRStatus
+set_prop_font_weight_from_value (CRStyle * a_style, CRTerm * a_value);
+
+static const gchar *
+num_prop_code_to_string (enum CRNumProp a_code)
+{
+ guint len = sizeof (gv_num_props_dump_infos) /
+ sizeof (struct CRNumPropEnumDumpInfo);
+ if (a_code >= len) {
+ cr_utils_trace_info ("A field has been added "
+ "to 'enum CRNumProp' and no matching"
+ " entry has been "
+ "added to gv_num_prop_dump_infos table.\n"
+ "Please add the missing matching entry");
+ return NULL;
+ }
+ if (gv_num_props_dump_infos[a_code].code != a_code) {
+ cr_utils_trace_info ("mismatch between the order of fields in"
+ " 'enum CRNumProp' and "
+ "the order of entries in "
+ "the gv_num_prop_dump_infos table");
+ return NULL;
+ }
+ return gv_num_props_dump_infos[a_code].str;
+}
+
+static const gchar *
+rgb_prop_code_to_string (enum CRRgbProp a_code)
+{
+ guint len = sizeof (gv_rgb_props_dump_infos) /
+ sizeof (struct CRRgbPropEnumDumpInfo);
+
+ if (a_code >= len) {
+ cr_utils_trace_info ("A field has been added "
+ "to 'enum CRRgbProp' and no matching"
+ " entry has been "
+ "added to gv_rgb_prop_dump_infos table.\n"
+ "Please add the missing matching entry");
+ return NULL;
+ }
+ if (gv_rgb_props_dump_infos[a_code].code != a_code) {
+ cr_utils_trace_info ("mismatch between the order of fields in"
+ " 'enum CRRgbProp' and "
+ "the order of entries in "
+ "the gv_rgb_props_dump_infos table");
+ return NULL;
+ }
+ return gv_rgb_props_dump_infos[a_code].str;
+}
+
+static const gchar *
+border_style_prop_code_to_string (enum CRBorderStyleProp a_code)
+{
+ guint len = sizeof (gv_border_style_props_dump_infos) /
+ sizeof (struct CRBorderStylePropEnumDumpInfo);
+
+ if (a_code >= len) {
+ cr_utils_trace_info ("A field has been added "
+ "to 'enum CRBorderStyleProp' and no matching"
+ " entry has been "
+ "added to gv_border_style_prop_dump_infos table.\n"
+ "Please add the missing matching entry");
+ return NULL;
+ }
+ if (gv_border_style_props_dump_infos[a_code].code != a_code) {
+ cr_utils_trace_info ("mismatch between the order of fields in"
+ " 'enum CRBorderStyleProp' and "
+ "the order of entries in "
+ "the gv_border_style_props_dump_infos table");
+ return NULL;
+ }
+ return gv_border_style_props_dump_infos[a_code].str;
+}
+
+static enum CRStatus
+cr_style_init_properties (void)
+{
+
+ if (!gv_prop_hash) {
+ gulong i = 0;
+
+ gv_prop_hash = g_hash_table_new (g_str_hash, g_str_equal);
+ if (!gv_prop_hash) {
+ cr_utils_trace_info ("Out of memory");
+ return CR_ERROR;
+ }
+
+ /*load gv_prop_hash from gv_prop_table */
+ for (i = 0; gv_prop_table[i].name; i++) {
+ g_hash_table_insert
+ (gv_prop_hash,
+ (gpointer) gv_prop_table[i].name,
+ GINT_TO_POINTER (gv_prop_table[i].prop_id));
+ }
+ }
+
+ return CR_OK;
+}
+
+static enum CRPropertyID
+cr_style_get_prop_id (const guchar * a_prop)
+{
+ gpointer *raw_id = NULL;
+
+ if (!gv_prop_hash) {
+ cr_style_init_properties ();
+ }
+
+ raw_id = (gpointer *) g_hash_table_lookup (gv_prop_hash, a_prop);
+ if (!raw_id) {
+ return PROP_ID_NOT_KNOWN;
+ }
+ return (enum CRPropertyID)GPOINTER_TO_INT (raw_id);
+}
+
+static enum CRStatus
+set_prop_padding_x_from_value (CRStyle * a_style,
+ CRTerm * a_value, enum CRDirection a_dir)
+{
+ enum CRStatus status = CR_OK;
+ CRNum *num_val = NULL;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ if (a_value->type != TERM_NUMBER && a_value->type != TERM_IDENT)
+ return CR_BAD_PARAM_ERROR;
+
+ switch (a_dir) {
+ case DIR_TOP:
+ num_val = &a_style->num_props[NUM_PROP_PADDING_TOP].sv;
+ break;
+
+ case DIR_RIGHT:
+ num_val = &a_style->num_props[NUM_PROP_PADDING_RIGHT].sv;
+ break;
+
+ case DIR_BOTTOM:
+ num_val = &a_style->num_props[NUM_PROP_PADDING_BOTTOM].sv;
+ break;
+
+ case DIR_LEFT:
+ num_val = &a_style->num_props[NUM_PROP_PADDING_LEFT].sv;
+ break;
+
+ default:
+ return CR_BAD_PARAM_ERROR;
+ }
+
+ if (a_value->type == TERM_IDENT) {
+ if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strncmp ((const char *) "inherit",
+ a_value->content.str->stryng->str,
+ sizeof ("inherit")-1)) {
+ status = cr_num_set (num_val, 0.0, NUM_INHERIT);
+ return CR_OK;
+ } else
+ return CR_UNKNOWN_TYPE_ERROR;
+ }
+
+ g_return_val_if_fail (a_value->type == TERM_NUMBER
+ && a_value->content.num, CR_UNKNOWN_TYPE_ERROR);
+
+ switch (a_value->content.num->type) {
+ case NUM_LENGTH_EM:
+ case NUM_LENGTH_EX:
+ case NUM_LENGTH_PX:
+ case NUM_LENGTH_IN:
+ case NUM_LENGTH_CM:
+ case NUM_LENGTH_MM:
+ case NUM_LENGTH_PT:
+ case NUM_LENGTH_PC:
+ case NUM_PERCENTAGE:
+ status = cr_num_copy (num_val, a_value->content.num);
+ break;
+ default:
+ status = CR_UNKNOWN_TYPE_ERROR;
+ break;
+ }
+
+ return status;
+}
+
+static enum CRStatus
+set_prop_border_x_width_from_value (CRStyle * a_style,
+ CRTerm * a_value,
+ enum CRDirection a_dir)
+{
+ enum CRStatus status = CR_OK;
+ CRNum *num_val = NULL;
+
+ g_return_val_if_fail (a_value && a_style, CR_BAD_PARAM_ERROR);
+
+ switch (a_dir) {
+ case DIR_TOP:
+ num_val = &a_style->num_props[NUM_PROP_BORDER_TOP].sv;
+ break;
+
+ case DIR_RIGHT:
+ num_val = &a_style->num_props[NUM_PROP_BORDER_RIGHT].sv;
+ break;
+
+ case DIR_BOTTOM:
+ num_val = &a_style->num_props[NUM_PROP_BORDER_BOTTOM].sv;
+ break;
+
+ case DIR_LEFT:
+ num_val = &a_style->num_props[NUM_PROP_BORDER_LEFT].sv;
+ break;
+
+ default:
+ return CR_BAD_PARAM_ERROR;
+ break;
+ }
+
+ if (a_value->type == TERM_IDENT) {
+ if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str) {
+ if (!strncmp ("thin",
+ a_value->content.str->stryng->str,
+ sizeof ("thin")-1)) {
+ cr_num_set (num_val, BORDER_THIN,
+ NUM_LENGTH_PX);
+ } else if (!strncmp
+ ("medium",
+ a_value->content.str->stryng->str,
+ sizeof ("medium")-1)) {
+ cr_num_set (num_val, BORDER_MEDIUM,
+ NUM_LENGTH_PX);
+ } else if (!strncmp ("thick",
+ a_value->content.str->stryng->str,
+ sizeof ("thick")-1)) {
+ cr_num_set (num_val, BORDER_THICK,
+ NUM_LENGTH_PX);
+ } else {
+ return CR_UNKNOWN_TYPE_ERROR;
+ }
+ }
+ } else if (a_value->type == TERM_NUMBER) {
+ if (a_value->content.num) {
+ cr_num_copy (num_val, a_value->content.num);
+ }
+ } else if (a_value->type != TERM_NUMBER
+ || a_value->content.num == NULL) {
+ return CR_UNKNOWN_TYPE_ERROR;
+ }
+
+ return status;
+}
+
+static enum CRStatus
+set_prop_border_width_from_value (CRStyle *a_style,
+ CRTerm *a_value)
+{
+ CRTerm *cur_term = NULL ;
+ int dir;
+
+ g_return_val_if_fail (a_style && a_value,
+ CR_BAD_PARAM_ERROR) ;
+ cur_term = a_value ;
+
+ if (!cur_term)
+ return CR_ERROR ;
+
+ for (dir = (int) DIR_TOP ; dir < (int)NB_DIRS ; dir++) {
+ enum CRDirection direction = (enum CRDirection)dir;
+ set_prop_border_x_width_from_value (a_style,
+ cur_term,
+ direction) ;
+ }
+
+ cur_term = cur_term->next ;
+ if (!cur_term)
+ return CR_OK ;
+ set_prop_border_x_width_from_value (a_style, cur_term,
+ DIR_RIGHT) ;
+ set_prop_border_x_width_from_value (a_style, cur_term,
+ DIR_LEFT) ;
+
+ cur_term = cur_term->next ;
+ if (!cur_term)
+ return CR_OK ;
+ set_prop_border_x_width_from_value (a_style, cur_term,
+ DIR_BOTTOM) ;
+
+ cur_term = cur_term->next ;
+ if (!cur_term)
+ return CR_OK ;
+ set_prop_border_x_width_from_value (a_style, cur_term,
+ DIR_LEFT) ;
+
+ return CR_OK ;
+}
+
+static enum CRStatus
+set_prop_border_x_style_from_value (CRStyle * a_style,
+ CRTerm * a_value, enum CRDirection a_dir)
+{
+ enum CRStatus status = CR_OK;
+ enum CRBorderStyle *border_style_ptr = NULL;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ switch (a_dir) {
+ case DIR_TOP:
+ border_style_ptr = &a_style->
+ border_style_props[BORDER_STYLE_PROP_TOP];
+ break;
+
+ case DIR_RIGHT:
+ border_style_ptr =
+ &a_style->border_style_props[BORDER_STYLE_PROP_RIGHT];
+ break;
+
+ case DIR_BOTTOM:
+ border_style_ptr = &a_style->
+ border_style_props[BORDER_STYLE_PROP_BOTTOM];
+ break;
+
+ case DIR_LEFT:
+ border_style_ptr = &a_style->
+ border_style_props[BORDER_STYLE_PROP_LEFT];
+ break;
+
+ default:
+ break;
+ }
+
+ if (a_value->type != TERM_IDENT || !a_value->content.str) {
+ return CR_UNKNOWN_TYPE_ERROR;
+ }
+
+ if (!strncmp ("none",
+ a_value->content.str->stryng->str,
+ sizeof ("none")-1)) {
+ *border_style_ptr = BORDER_STYLE_NONE;
+ } else if (!strncmp ("hidden",
+ a_value->content.str->stryng->str,
+ sizeof ("hidden")-1)) {
+ *border_style_ptr = BORDER_STYLE_HIDDEN;
+ } else if (!strncmp ("dotted",
+ a_value->content.str->stryng->str,
+ sizeof ("dotted")-1)) {
+ *border_style_ptr = BORDER_STYLE_DOTTED;
+ } else if (!strncmp ("dashed",
+ a_value->content.str->stryng->str, sizeof ("dashed")-1)) {
+ *border_style_ptr = BORDER_STYLE_DASHED;
+ } else if (!strncmp ("solid",
+ a_value->content.str->stryng->str, sizeof ("solid")-1)) {
+ *border_style_ptr = BORDER_STYLE_SOLID;
+ } else if (!strncmp ("double",
+ a_value->content.str->stryng->str, sizeof ("double")-1)) {
+ *border_style_ptr = BORDER_STYLE_DOUBLE;
+ } else if (!strncmp ("groove",
+ a_value->content.str->stryng->str, sizeof ("groove")-1)) {
+ *border_style_ptr = BORDER_STYLE_GROOVE;
+ } else if (!strncmp ("ridge",
+ a_value->content.str->stryng->str,
+ sizeof ("ridge")-1)) {
+ *border_style_ptr = BORDER_STYLE_RIDGE;
+ } else if (!strncmp ("inset",
+ a_value->content.str->stryng->str,
+ sizeof ("inset")-1)) {
+ *border_style_ptr = BORDER_STYLE_INSET;
+ } else if (!strncmp ("outset",
+ a_value->content.str->stryng->str,
+ sizeof ("outset")-1)) {
+ *border_style_ptr = BORDER_STYLE_OUTSET;
+ } else if (!strncmp ("inherit",
+ a_value->content.str->stryng->str,
+ sizeof ("inherit")-1)) {
+ *border_style_ptr = BORDER_STYLE_INHERIT;
+ } else {
+ status = CR_UNKNOWN_TYPE_ERROR;
+ }
+
+ return status;
+}
+
+static enum CRStatus
+set_prop_border_style_from_value (CRStyle *a_style,
+ CRTerm *a_value)
+{
+ CRTerm *cur_term = NULL ;
+ int dir;
+
+ g_return_val_if_fail (a_style && a_value,
+ CR_BAD_PARAM_ERROR) ;
+
+ cur_term = a_value ;
+ if (!cur_term || cur_term->type != TERM_IDENT) {
+ return CR_ERROR ;
+ }
+
+ for (dir = (int)DIR_TOP ; dir < (int)NB_DIRS ; dir++) {
+ enum CRDirection direction = (enum CRDirection)dir;
+ set_prop_border_x_style_from_value (a_style,
+ cur_term,
+ direction) ;
+ }
+
+ cur_term = cur_term->next ;
+ if (!cur_term || cur_term->type != TERM_IDENT) {
+ return CR_OK ;
+ }
+
+ set_prop_border_x_style_from_value (a_style, cur_term,
+ DIR_RIGHT) ;
+ set_prop_border_x_style_from_value (a_style, cur_term,
+ DIR_LEFT) ;
+
+ cur_term = cur_term->next ;
+ if (!cur_term || cur_term->type != TERM_IDENT) {
+ return CR_OK ;
+ }
+ set_prop_border_x_style_from_value (a_style, cur_term,
+ DIR_BOTTOM) ;
+
+ cur_term = cur_term->next ;
+ if (!cur_term || cur_term->type != TERM_IDENT) {
+ return CR_OK ;
+ }
+ set_prop_border_x_style_from_value (a_style, cur_term,
+ DIR_LEFT) ;
+ return CR_OK ;
+}
+
+static enum CRStatus
+set_prop_margin_x_from_value (CRStyle * a_style, CRTerm * a_value,
+ enum CRDirection a_dir)
+{
+ enum CRStatus status = CR_OK;
+ CRNum *num_val = NULL;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ switch (a_dir) {
+ case DIR_TOP:
+ num_val = &a_style->num_props[NUM_PROP_MARGIN_TOP].sv;
+ break;
+
+ case DIR_RIGHT:
+ num_val = &a_style->num_props[NUM_PROP_MARGIN_RIGHT].sv;
+ break;
+
+ case DIR_BOTTOM:
+ num_val = &a_style->num_props[NUM_PROP_MARGIN_BOTTOM].sv;
+ break;
+
+ case DIR_LEFT:
+ num_val = &a_style->num_props[NUM_PROP_MARGIN_LEFT].sv;
+ break;
+
+ default:
+ break;
+ }
+
+ switch (a_value->type) {
+ case TERM_IDENT:
+ if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str,
+ "inherit")) {
+ status = cr_num_set (num_val, 0.0, NUM_INHERIT);
+ } else if (a_value->content.str
+ && a_value->content.str->stryng
+ && !strcmp (a_value->content.str->stryng->str,
+ "auto")) {
+ status = cr_num_set (num_val, 0.0, NUM_AUTO);
+ } else {
+ status = CR_UNKNOWN_TYPE_ERROR;
+ }
+ break ;
+
+ case TERM_NUMBER:
+ status = cr_num_copy (num_val, a_value->content.num);
+ break;
+
+ default:
+ status = CR_UNKNOWN_TYPE_ERROR;
+ break;
+ }
+
+ return status;
+}
+
+struct CRPropDisplayValPair {
+ const gchar *prop_name;
+ enum CRDisplayType type;
+};
+
+static enum CRStatus
+set_prop_display_from_value (CRStyle * a_style, CRTerm * a_value)
+{
+ static const struct CRPropDisplayValPair disp_vals_map[] = {
+ {"none", DISPLAY_NONE},
+ {"inline", DISPLAY_INLINE},
+ {"block", DISPLAY_BLOCK},
+ {"run-in", DISPLAY_RUN_IN},
+ {"compact", DISPLAY_COMPACT},
+ {"marker", DISPLAY_MARKER},
+ {"table", DISPLAY_TABLE},
+ {"inline-table", DISPLAY_INLINE_TABLE},
+ {"table-row-group", DISPLAY_TABLE_ROW_GROUP},
+ {"table-header-group", DISPLAY_TABLE_HEADER_GROUP},
+ {"table-footer-group", DISPLAY_TABLE_FOOTER_GROUP},
+ {"table-row", DISPLAY_TABLE_ROW},
+ {"table-column-group", DISPLAY_TABLE_COLUMN_GROUP},
+ {"table-column", DISPLAY_TABLE_COLUMN},
+ {"table-cell", DISPLAY_TABLE_CELL},
+ {"table-caption", DISPLAY_TABLE_CAPTION},
+ {"inherit", DISPLAY_INHERIT},
+ {NULL, DISPLAY_NONE}
+ };
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ switch (a_value->type) {
+ case TERM_IDENT:
+ {
+ int i = 0;
+
+ if (!a_value->content.str
+ || !a_value->content.str->stryng
+ || !a_value->content.str->stryng->str)
+ break;
+
+ for (i = 0; disp_vals_map[i].prop_name; i++) {
+ if (!strncmp
+ (disp_vals_map[i].prop_name,
+ a_value->content.str->stryng->str,
+ strlen (disp_vals_map[i].prop_name))) {
+ a_style->display =
+ disp_vals_map[i].type;
+ break;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return CR_OK;
+}
+
+struct CRPropPositionValPair {
+ const gchar *name;
+ enum CRPositionType type;
+};
+
+static enum CRStatus
+set_prop_position_from_value (CRStyle * a_style, CRTerm * a_value)
+{
+ enum CRStatus status = CR_UNKNOWN_PROP_VAL_ERROR;
+ static const struct CRPropPositionValPair position_vals_map[] = {
+ {"static", POSITION_STATIC},
+ {"relative", POSITION_RELATIVE},
+ {"absolute", POSITION_ABSOLUTE},
+ {"fixed", POSITION_FIXED},
+ {"inherit", POSITION_INHERIT},
+ {NULL, POSITION_STATIC}
+ /*must alwas be the last one */
+ };
+
+ g_return_val_if_fail (a_value, CR_BAD_PARAM_ERROR);
+
+ switch (a_value->type) {
+ case TERM_IDENT:
+ {
+ int i = 0;
+
+ if (!a_value->content.str
+ || !a_value->content.str->stryng
+ || !a_value->content.str->stryng->str)
+ break;
+
+ for (i = 0; position_vals_map[i].name; i++) {
+ if (!strncmp (position_vals_map[i].name,
+ a_value->content.str->stryng->str,
+ strlen (position_vals_map[i].
+ name))) {
+ a_style->position =
+ position_vals_map[i].type;
+ status = CR_OK;
+ break;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return status;
+}
+
+static enum CRStatus
+set_prop_x_from_value (CRStyle * a_style, CRTerm * a_value,
+ enum CRDirection a_dir)
+{
+ CRNum *box_offset = NULL;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ if (!(a_value->type == TERM_NUMBER)
+ && !(a_value->type == TERM_IDENT)) {
+ return CR_UNKNOWN_PROP_VAL_ERROR;
+ }
+
+ switch (a_dir) {
+ case DIR_TOP:
+ box_offset = &a_style->num_props[NUM_PROP_TOP].sv;
+ break;
+
+ case DIR_RIGHT:
+ box_offset = &a_style->num_props[NUM_PROP_RIGHT].sv;
+ break;
+
+ case DIR_BOTTOM:
+ box_offset = &a_style->num_props[NUM_PROP_BOTTOM].sv;
+ break;
+ case DIR_LEFT:
+ box_offset = &a_style->num_props[NUM_PROP_LEFT].sv;
+ break;
+
+ default:
+ break;
+ }
+
+ box_offset->type = NUM_AUTO;
+
+ if (a_value->type == TERM_NUMBER && a_value->content.num) {
+ cr_num_copy (box_offset, a_value->content.num);
+ } else if (a_value->type == TERM_IDENT
+ && a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str) {
+ if (!strncmp ("inherit",
+ a_value->content.str->stryng->str,
+ sizeof ("inherit")-1)) {
+ cr_num_set (box_offset, 0.0, NUM_INHERIT);
+ } else if (!strncmp ("auto",
+ a_value->content.str->stryng->str,
+ sizeof ("auto")-1)) {
+ box_offset->type = NUM_AUTO;
+ }
+ }
+
+ return CR_OK;
+}
+
+static enum CRStatus
+set_prop_float (CRStyle * a_style, CRTerm * a_value)
+{
+ g_return_val_if_fail (a_style && a_value,
+ CR_BAD_PARAM_ERROR);
+
+ /*the default float type as specified by the css2 spec */
+ a_style->float_type = FLOAT_NONE;
+
+ if (a_value->type != TERM_IDENT
+ || !a_value->content.str
+ || !a_value->content.str->stryng
+ || !a_value->content.str->stryng->str) {
+ /*unknown type, the float type is set to it's default value */
+ return CR_OK;
+ }
+
+ if (!strncmp ("none",
+ a_value->content.str->stryng->str,
+ sizeof ("none")-1)) {
+ a_style->float_type = FLOAT_NONE;
+ } else if (!strncmp ("left",
+ a_value->content.str->stryng->str,
+ sizeof ("left")-1)) {
+ a_style->float_type = FLOAT_LEFT;
+ } else if (!strncmp ("right",
+ a_value->content.str->stryng->str,
+ sizeof ("right")-1)) {
+ a_style->float_type = FLOAT_RIGHT;
+ } else if (!strncmp ("inherit",
+ a_value->content.str->stryng->str,
+ sizeof ("inherit")-1)) {
+ a_style->float_type = FLOAT_INHERIT;
+ }
+ return CR_OK;
+}
+
+static enum CRStatus
+set_prop_width (CRStyle * a_style, CRTerm * a_value)
+{
+ CRNum *width = NULL;
+ g_return_val_if_fail (a_style
+ && a_value,
+ CR_BAD_PARAM_ERROR);
+
+ width = &a_style->num_props[NUM_PROP_WIDTH].sv;
+ cr_num_set (width, 0.0, NUM_AUTO);
+
+ if (a_value->type == TERM_IDENT) {
+ if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str) {
+ if (!strncmp ("auto",
+ a_value->content.str->stryng->str,
+ sizeof ("auto")-1)) {
+ cr_num_set (width, 0.0, NUM_AUTO);
+ } else if (!strncmp ("inherit",
+ a_value->content.str->stryng->str,
+ sizeof ("inherit")-1)) {
+ cr_num_set (width, 0.0, NUM_INHERIT);
+ }
+ }
+ } else if (a_value->type == TERM_NUMBER) {
+ if (a_value->content.num) {
+ cr_num_copy (&a_style->num_props[NUM_PROP_WIDTH].sv,
+ a_value->content.num);
+ }
+ }
+ return CR_OK;
+}
+
+static enum CRStatus
+set_prop_color (CRStyle * a_style, CRTerm * a_value)
+{
+ enum CRStatus status = CR_OK;
+ CRRgb *a_rgb = &a_style->rgb_props[RGB_PROP_COLOR].sv;
+
+ g_return_val_if_fail (a_style
+ && a_value, CR_BAD_PARAM_ERROR);
+
+ status = cr_rgb_set_from_term (a_rgb, a_value);
+
+ return status;
+}
+
+static enum CRStatus
+set_prop_background_color (CRStyle * a_style, CRTerm * a_value)
+{
+ enum CRStatus status = CR_OK;
+ CRRgb *rgb = &a_style->rgb_props[RGB_PROP_BACKGROUND_COLOR].sv;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ status = cr_rgb_set_from_term (rgb, a_value);
+ return status;
+}
+
+/**
+ *Sets border-top-color, border-right-color,
+ *border-bottom-color or border-left-color properties
+ *in the style structure. The value is taken from a
+ *css2 term of type IDENT or RGB.
+ *@param a_style the style structure to set.
+ *@param a_value the css2 term to take the color information from.
+ *@param a_dir the direction (TOP, LEFT, RIGHT, or BOTTOM).
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+set_prop_border_x_color_from_value (CRStyle * a_style, CRTerm * a_value,
+ enum CRDirection a_dir)
+{
+ CRRgb *rgb_color = NULL;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ switch (a_dir) {
+ case DIR_TOP:
+ rgb_color = &a_style->rgb_props[RGB_PROP_BORDER_TOP_COLOR].sv;
+ break;
+
+ case DIR_RIGHT:
+ rgb_color =
+ &a_style->rgb_props[RGB_PROP_BORDER_RIGHT_COLOR].sv;
+ break;
+
+ case DIR_BOTTOM:
+ rgb_color =
+ &a_style->rgb_props[RGB_PROP_BORDER_BOTTOM_COLOR].sv;
+ break;
+
+ case DIR_LEFT:
+ rgb_color =
+ &a_style->rgb_props[RGB_PROP_BORDER_LEFT_COLOR].sv;
+ break;
+
+ default:
+ cr_utils_trace_info ("unknown DIR type");
+ return CR_BAD_PARAM_ERROR;
+ }
+
+ status = CR_UNKNOWN_PROP_VAL_ERROR;
+
+ if (a_value->type == TERM_IDENT) {
+ if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str) {
+ status = cr_rgb_set_from_name
+ (rgb_color,
+ (const guchar *) a_value->content.str->stryng->str);
+
+ }
+ if (status != CR_OK) {
+ cr_rgb_set_from_name (rgb_color, (const guchar *) "black");
+ }
+ } else if (a_value->type == TERM_RGB) {
+ if (a_value->content.rgb) {
+ status = cr_rgb_set_from_rgb
+ (rgb_color, a_value->content.rgb);
+ }
+ }
+ return status;
+}
+
+static enum CRStatus
+set_prop_border_x_from_value (CRStyle * a_style, CRTerm * a_value,
+ enum CRDirection a_dir)
+{
+ CRTerm *cur_term = NULL;
+
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ for (cur_term = a_value;
+ cur_term;
+ cur_term = cur_term->next) {
+ status = set_prop_border_x_width_from_value (a_style,
+ cur_term, a_dir);
+
+ if (status != CR_OK) {
+ status = set_prop_border_x_style_from_value
+ (a_style, cur_term, a_dir);
+ }
+ if (status != CR_OK) {
+ status = set_prop_border_x_color_from_value
+ (a_style, cur_term, a_dir);
+ }
+ }
+ return CR_OK;
+}
+
+static enum CRStatus
+set_prop_border_from_value (CRStyle * a_style, CRTerm * a_value)
+{
+ int dir;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ for (dir = 0; dir < (int)NB_DIRS; dir++) {
+ set_prop_border_x_from_value (a_style,
+ a_value,
+ (enum CRDirection)dir);
+ }
+
+ return CR_OK;
+}
+
+static enum CRStatus
+set_prop_padding_from_value (CRStyle * a_style, CRTerm * a_value)
+{
+ CRTerm *cur_term = NULL;
+ int dir;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ cur_term = a_value;
+
+ /*filter the eventual non NUMBER terms some user can have written here*/
+ while (cur_term && cur_term->type != TERM_NUMBER) {
+ cur_term = cur_term->next;
+ }
+ if (!cur_term)
+ return CR_ERROR ;
+
+ for (dir = 0; dir < (int)NB_DIRS; dir++) {
+ set_prop_padding_x_from_value (a_style,
+ cur_term, (enum CRDirection)dir);
+ }
+ cur_term = cur_term->next;
+
+ /*filter non NUMBER terms that some users can have written here...*/
+ while (cur_term && cur_term->type != TERM_NUMBER) {
+ cur_term = cur_term->next;
+ }
+ /*the user can have just written padding: 1px*/
+ if (!cur_term)
+ return CR_OK;
+
+ set_prop_padding_x_from_value (a_style, cur_term, DIR_RIGHT);
+ set_prop_padding_x_from_value (a_style, cur_term, DIR_LEFT);
+
+ while (cur_term && cur_term->type != TERM_NUMBER) {
+ cur_term = cur_term->next;
+ }
+ if (!cur_term)
+ return CR_OK;
+
+ set_prop_padding_x_from_value (a_style, cur_term, DIR_BOTTOM);
+
+ while (cur_term && cur_term->type != TERM_NUMBER) {
+ cur_term = cur_term->next;
+ }
+ if (!cur_term)
+ return CR_OK;
+ status = set_prop_padding_x_from_value (a_style, cur_term, DIR_LEFT);
+ return status;
+}
+
+static enum CRStatus
+set_prop_margin_from_value (CRStyle * a_style, CRTerm * a_value)
+{
+ CRTerm *cur_term = NULL;
+ int dir;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ cur_term = a_value;
+
+ while (cur_term && cur_term->type != TERM_NUMBER) {
+ cur_term = cur_term->next;
+ }
+
+ if (!cur_term)
+ return CR_OK;
+
+ for (dir = 0; dir < (int)NB_DIRS; dir++) {
+ set_prop_margin_x_from_value(a_style,
+ cur_term, (enum CRDirection)dir);
+ }
+ cur_term = cur_term->next;
+
+ while (cur_term && cur_term->type != TERM_NUMBER) {
+ cur_term = cur_term->next;
+ }
+ if (!cur_term)
+ return CR_OK;
+
+ set_prop_margin_x_from_value (a_style, cur_term, DIR_RIGHT);
+ set_prop_margin_x_from_value (a_style, cur_term, DIR_LEFT);
+
+ while (cur_term && cur_term->type != TERM_NUMBER) {
+ cur_term = cur_term->next;
+ }
+ if (!cur_term)
+ return CR_OK;
+
+ set_prop_margin_x_from_value (a_style, cur_term, DIR_BOTTOM);
+
+ while (cur_term && cur_term->type != TERM_NUMBER) {
+ cur_term = cur_term->next;
+ }
+ if (!cur_term)
+ return CR_OK;
+
+ status = set_prop_margin_x_from_value (a_style, cur_term, DIR_LEFT);
+
+ return status;
+}
+
+static enum CRStatus
+set_prop_font_family_from_value (CRStyle * a_style, CRTerm * a_value)
+{
+ CRTerm *cur_term = NULL;
+ CRFontFamily *font_family = NULL,
+ *cur_ff = NULL,
+ *cur_ff2 = NULL;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ if (a_value->type == TERM_IDENT &&
+ a_value->content.str &&
+ a_value->content.str->stryng &&
+ a_value->content.str->stryng->str &&
+ !strcmp ("inherit", a_value->content.str->stryng->str))
+ {
+ font_family = cr_font_family_new (FONT_FAMILY_INHERIT, NULL);
+ goto out;
+ }
+
+ for (cur_term = a_value; cur_term; cur_term = cur_term->next) {
+ switch (cur_term->type) {
+ case TERM_IDENT:
+ {
+ enum CRFontFamilyType font_type;
+
+ if (cur_term->content.str
+ && cur_term->content.str->stryng
+ && cur_term->content.str->stryng->str
+ && !strcmp
+ (cur_term->content.str->stryng->str,
+ "sans-serif")) {
+ font_type = FONT_FAMILY_SANS_SERIF;
+ } else if (cur_term->content.str
+ && cur_term->content.str->stryng
+ && cur_term->content.str->stryng->str
+ && !strcmp
+ (cur_term->content.str->stryng->str,
+ "serif")) {
+ font_type = FONT_FAMILY_SERIF;
+ } else if (cur_term->content.str
+ && cur_term->content.str->stryng
+ && cur_term->content.str->stryng->str
+ && !strcmp (cur_term->content.str->stryng->str,
+ "cursive")) {
+ font_type = FONT_FAMILY_CURSIVE;
+ } else if (cur_term->content.str
+ && cur_term->content.str->stryng
+ && cur_term->content.str->stryng->str
+ && !strcmp (cur_term->content.str->stryng->str,
+ "fantasy")) {
+ font_type = FONT_FAMILY_FANTASY;
+ } else if (cur_term->content.str
+ && cur_term->content.str->stryng
+ && cur_term->content.str->stryng->str
+ && !strcmp (cur_term->content.str->stryng->str,
+ "monospace")) {
+ font_type = FONT_FAMILY_MONOSPACE;
+ } else {
+ /*
+ *unknown property value.
+ *ignore it.
+ */
+ continue;
+ }
+
+ cur_ff = cr_font_family_new (font_type, NULL);
+ }
+ break;
+
+ case TERM_STRING:
+ {
+ if (cur_term->content.str
+ && cur_term->content.str->stryng
+ && cur_term->content.str->stryng->str) {
+ cur_ff = cr_font_family_new
+ (FONT_FAMILY_NON_GENERIC,
+ (guchar *) cur_term->content.str->stryng->str);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ cur_ff2 = cr_font_family_append (font_family, cur_ff);
+ if (cur_ff2) {
+ font_family = cur_ff2;
+ }
+ }
+
+ out:
+ if (font_family) {
+ if (a_style->font_family) {
+ cr_font_family_destroy (a_style->font_family);
+ a_style->font_family = NULL ;
+ }
+ a_style->font_family = font_family;
+ font_family = NULL ;
+ }
+
+ return CR_OK;
+}
+
+static enum CRStatus
+init_style_font_size_field (CRStyle * a_style)
+{
+ g_return_val_if_fail (a_style, CR_BAD_PARAM_ERROR);
+
+ memset (&a_style->font_size, 0,
+ sizeof (CRFontSizeVal)) ;
+ /*
+ if (!a_style->font_size) {
+ a_style->font_size = cr_font_size_new ();
+ if (!a_style->font_size) {
+ return CR_INSTANCIATION_FAILED_ERROR;
+ }
+ } else {
+ cr_font_size_clear (a_style->font_size);
+ }
+ */
+ return CR_OK;
+}
+
+static enum CRStatus
+set_prop_font_size_from_value (CRStyle * a_style, CRTerm * a_value)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ switch (a_value->type) {
+ case TERM_IDENT:
+ if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str,
+ "xx-small")) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ a_style->font_size.sv.type =
+ PREDEFINED_ABSOLUTE_FONT_SIZE;
+ a_style->font_size.sv.value.predefined =
+ FONT_SIZE_XX_SMALL;
+
+ } else if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str,
+ "x-small")) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ a_style->font_size.sv.type =
+ PREDEFINED_ABSOLUTE_FONT_SIZE;
+ a_style->font_size.sv.value.predefined =
+ FONT_SIZE_X_SMALL;
+ } else if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str,
+ "small")) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ a_style->font_size.sv.type =
+ PREDEFINED_ABSOLUTE_FONT_SIZE;
+ a_style->font_size.sv.value.predefined =
+ FONT_SIZE_SMALL;
+ } else if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str, "medium")) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ a_style->font_size.sv.type =
+ PREDEFINED_ABSOLUTE_FONT_SIZE;
+ a_style->font_size.sv.value.predefined =
+ FONT_SIZE_MEDIUM;
+ } else if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str,
+ "large")) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ a_style->font_size.sv.type =
+ PREDEFINED_ABSOLUTE_FONT_SIZE;
+ a_style->font_size.sv.value.predefined =
+ FONT_SIZE_LARGE;
+ } else if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str,
+ "x-large")) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ a_style->font_size.sv.type =
+ PREDEFINED_ABSOLUTE_FONT_SIZE;
+ a_style->font_size.sv.value.predefined =
+ FONT_SIZE_X_LARGE;
+ } else if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str,
+ "xx-large")) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ a_style->font_size.sv.type =
+ PREDEFINED_ABSOLUTE_FONT_SIZE;
+ a_style->font_size.sv.value.predefined =
+ FONT_SIZE_XX_LARGE;
+ } else if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str,
+ "larger")) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ a_style->font_size.sv.type = RELATIVE_FONT_SIZE;
+ a_style->font_size.sv.value.relative = FONT_SIZE_LARGER;
+ } else if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str,
+ "smaller")) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ a_style->font_size.sv.type = RELATIVE_FONT_SIZE;
+ a_style->font_size.sv.value.relative =
+ FONT_SIZE_SMALLER;
+ } else if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str
+ && !strcmp (a_value->content.str->stryng->str, "inherit")) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+ a_style->font_size.sv.type = INHERITED_FONT_SIZE;
+
+ } else {
+ cr_utils_trace_info ("Unknown value of font-size") ;
+ status = init_style_font_size_field (a_style);
+ return CR_UNKNOWN_PROP_VAL_ERROR;
+ }
+ break;
+
+ case TERM_NUMBER:
+ if (a_value->content.num) {
+ status = init_style_font_size_field (a_style);
+ g_return_val_if_fail (status == CR_OK, status);
+
+ a_style->font_size.sv.type = ABSOLUTE_FONT_SIZE;
+ cr_num_copy (&a_style->font_size.sv.value.absolute,
+ a_value->content.num) ;
+ }
+ break;
+
+ default:
+ status = init_style_font_size_field (a_style);
+ return CR_UNKNOWN_PROP_VAL_ERROR;
+ }
+ return CR_OK;
+}
+
+static enum CRStatus
+set_prop_font_style_from_value (CRStyle * a_style, CRTerm * a_value)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ switch (a_value->type) {
+ case TERM_IDENT:
+ if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str) {
+ if (!strcmp (a_value->content.str->stryng->str, "normal")) {
+ a_style->font_style = FONT_STYLE_NORMAL;
+ } else if (!strcmp
+ (a_value->content.str->stryng->str,
+ "italic")) {
+ a_style->font_style = FONT_STYLE_ITALIC;
+ } else if (!strcmp
+ (a_value->content.str->stryng->str,
+ "oblique")) {
+ a_style->font_style = FONT_STYLE_OBLIQUE;
+ } else if (!strcmp
+ (a_value->content.str->stryng->str,
+ "inherit")) {
+ a_style->font_style = FONT_STYLE_INHERIT;
+ } else {
+ status = CR_UNKNOWN_PROP_VAL_ERROR;
+ }
+ }
+ break;
+
+ default:
+ status = CR_UNKNOWN_PROP_VAL_ERROR;
+ break;
+ }
+
+ return status;
+}
+
+static enum CRStatus
+set_prop_font_weight_from_value (CRStyle * a_style, CRTerm * a_value)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ switch (a_value->type) {
+ case TERM_IDENT:
+ if (a_value->content.str
+ && a_value->content.str->stryng
+ && a_value->content.str->stryng->str) {
+ if (!strcmp (a_value->content.str->stryng->str,
+ "normal")) {
+ a_style->font_weight = FONT_WEIGHT_NORMAL;
+ } else if (!strcmp (a_value->content.str->stryng->str,
+ "bold")) {
+ a_style->font_weight = FONT_WEIGHT_BOLD;
+ } else if (!strcmp (a_value->content.str->stryng->str,
+ "bolder")) {
+ a_style->font_weight = FONT_WEIGHT_BOLDER;
+ } else if (!strcmp (a_value->content.str->stryng->str,
+ "lighter")) {
+ a_style->font_weight = FONT_WEIGHT_LIGHTER;
+ } else if (!strcmp (a_value->content.str->stryng->str,
+ "inherit")) {
+ a_style->font_weight = FONT_WEIGHT_INHERIT;
+
+ } else {
+ status = CR_UNKNOWN_PROP_VAL_ERROR;
+ }
+
+ }
+ break;
+
+ case TERM_NUMBER:
+ if (a_value->content.num
+ && (a_value->content.num->type == NUM_GENERIC
+ || a_value->content.num->type == NUM_AUTO)) {
+ if (a_value->content.num->val <= 150) {
+ a_style->font_weight = FONT_WEIGHT_100;
+ } else if (a_value->content.num->val <= 250) {
+ a_style->font_weight = FONT_WEIGHT_200;
+ } else if (a_value->content.num->val <= 350) {
+ a_style->font_weight = FONT_WEIGHT_300;
+ } else if (a_value->content.num->val <= 450) {
+ a_style->font_weight = FONT_WEIGHT_400;
+ } else if (a_value->content.num->val <= 550) {
+ a_style->font_weight = FONT_WEIGHT_500;
+ } else if (a_value->content.num->val <= 650) {
+ a_style->font_weight = FONT_WEIGHT_600;
+ } else if (a_value->content.num->val <= 750) {
+ a_style->font_weight = FONT_WEIGHT_700;
+ } else if (a_value->content.num->val <= 850) {
+ a_style->font_weight = FONT_WEIGHT_800;
+ } else {
+ a_style->font_weight = FONT_WEIGHT_900;
+ }
+ }
+ break;
+
+ default:
+ status = CR_UNKNOWN_PROP_VAL_ERROR;
+ break;
+ }
+
+ return status;
+}
+
+static enum CRStatus
+set_prop_white_space_from_value (CRStyle * a_style, CRTerm * a_value)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
+
+ switch (a_value->type) {
+ case TERM_IDENT:
+ if (a_value->content.str && a_value->content.str->stryng) {
+ if (!strcmp (a_value->content.str->stryng->str, "normal")) {
+ a_style->white_space = WHITE_SPACE_NORMAL;
+ } else if (!strcmp (a_value->content.str->stryng->str,
+ "pre")) {
+ a_style->white_space = WHITE_SPACE_PRE;
+ } else if (!strcmp (a_value->content.str->stryng->str,
+ "nowrap")) {
+ a_style->white_space = WHITE_SPACE_NOWRAP;
+ } else if (!strcmp (a_value->content.str->stryng->str,
+ "inherit")) {
+ a_style->white_space = WHITE_SPACE_INHERIT;
+ } else {
+ status = CR_UNKNOWN_PROP_VAL_ERROR;
+ }
+ }
+ break;
+ default:
+ status = CR_UNKNOWN_PROP_VAL_ERROR;
+ break;
+ }
+
+ return status;
+}
+
+/******************
+ *Public methods
+ ******************/
+
+/**
+ *Default constructor of #CRStyle.
+ *@param a_set_props_to_initial_values if TRUE, the style properties
+ *will be set to the default values. Only the style properties of the
+ *root box should be set to their initial values.
+ *Otherwise, the style values are set to their default value.
+ *Read the CSS2 spec, chapters 6.1.1 to 6.2.
+ */
+CRStyle *
+cr_style_new (gboolean a_set_props_to_initial_values)
+{
+ CRStyle *result = NULL;
+
+ result = (CRStyle *) g_try_malloc (sizeof (CRStyle));
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRStyle));
+ gv_prop_hash_ref_count++;
+
+ if (a_set_props_to_initial_values == TRUE) {
+ cr_style_set_props_to_initial_values (result);
+ } else {
+ cr_style_set_props_to_default_values (result);
+ }
+
+ return result;
+}
+
+/**
+ *Sets the style properties to their default values according to the css2 spec
+ * i.e inherit if the property is inherited, its initial value otherwise.
+ *@param a_this the current instance of #CRStyle.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_style_set_props_to_default_values (CRStyle * a_this)
+{
+ glong i = 0;
+
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ for (i = 0; i < NB_NUM_PROPS; i++)
+ {
+ switch (i)
+ {
+ case NUM_PROP_WIDTH:
+ case NUM_PROP_TOP:
+ case NUM_PROP_RIGHT:
+ case NUM_PROP_BOTTOM:
+ case NUM_PROP_LEFT:
+ cr_num_set (&a_this->num_props[i].sv, 0, NUM_AUTO);
+ break;
+
+ case NUM_PROP_PADDING_TOP:
+ case NUM_PROP_PADDING_RIGHT:
+ case NUM_PROP_PADDING_BOTTOM:
+ case NUM_PROP_PADDING_LEFT:
+ case NUM_PROP_BORDER_TOP:
+ case NUM_PROP_BORDER_RIGHT:
+ case NUM_PROP_BORDER_BOTTOM:
+ case NUM_PROP_BORDER_LEFT:
+ case NUM_PROP_MARGIN_TOP:
+ case NUM_PROP_MARGIN_RIGHT:
+ case NUM_PROP_MARGIN_BOTTOM:
+ case NUM_PROP_MARGIN_LEFT:
+ cr_num_set (&a_this->num_props[i].sv,
+ 0, NUM_LENGTH_PX);
+ break;
+
+ default:
+ cr_utils_trace_info ("Unknown property");
+ break;
+ }
+ }
+
+ for (i = 0; i < NB_RGB_PROPS; i++) {
+
+ switch (i) {
+ /*default foreground color is black */
+ case RGB_PROP_COLOR:
+ /*
+ *REVIEW: color is inherited and the default value is
+ *ua dependent.
+ */
+ cr_rgb_set_to_inherit (&a_this->rgb_props[i].sv,
+ TRUE) ;
+ break;
+
+ /*default background color is white */
+ case RGB_PROP_BACKGROUND_COLOR:
+ /* TODO: the default value should be transparent */
+ cr_rgb_set (&a_this->rgb_props[i].sv,
+ 255, 255, 255, FALSE);
+ cr_rgb_set_to_transparent (&a_this->rgb_props[i].sv,
+ TRUE) ;
+ break;
+
+ default:
+ /*
+ *TODO: for BORDER_COLOR the initial value should
+ * be the same as COLOR
+ */
+ cr_rgb_set (&a_this->rgb_props[i].sv, 0, 0, 0,
+ FALSE);
+ break;
+ }
+ }
+
+ for (i = 0; i < NB_BORDER_STYLE_PROPS; i++) {
+ a_this->border_style_props[i] = BORDER_STYLE_NONE;
+ }
+
+ a_this->display = DISPLAY_INLINE;
+ a_this->position = POSITION_STATIC;
+ a_this->float_type = FLOAT_NONE;
+ a_this->parent_style = NULL;
+ a_this->font_style = FONT_STYLE_INHERIT;
+ a_this->font_variant = FONT_VARIANT_INHERIT;
+ a_this->font_weight = FONT_WEIGHT_INHERIT;
+ a_this->font_family = NULL;
+
+ cr_font_size_set_to_inherit (&a_this->font_size.sv) ;
+ cr_font_size_clear (&a_this->font_size.cv) ;
+ cr_font_size_clear (&a_this->font_size.av) ;
+
+ /* To make the inheritance resolution possible and efficient */
+ a_this->inherited_props_resolved = FALSE ;
+ return CR_OK;
+}
+
+/**
+ *Sets the style properties to their initial value according to the css2 spec.
+ *This function should be used to initialize the style of the root element
+ *of an xml tree.
+ *Some properties are user agent dependent like font-family, and
+ *are not initialized, read the spec to make you renderer compliant.
+ *@param a_this the current instance of #CRStyle.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_style_set_props_to_initial_values (CRStyle *a_this)
+{
+ glong i = 0;
+
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ for (i = 0; i < NB_NUM_PROPS; i++) {
+ switch (i) {
+ case NUM_PROP_WIDTH:
+ cr_num_set (&a_this->num_props[i].sv, 800,
+ NUM_LENGTH_PX) ;
+ break ;
+ case NUM_PROP_TOP:
+ case NUM_PROP_RIGHT:
+ case NUM_PROP_BOTTOM:
+ case NUM_PROP_LEFT:
+ cr_num_set (&a_this->num_props[i].sv, 0, NUM_AUTO);
+ break;
+
+ case NUM_PROP_PADDING_TOP:
+ case NUM_PROP_PADDING_RIGHT:
+ case NUM_PROP_PADDING_BOTTOM:
+ case NUM_PROP_PADDING_LEFT:
+ case NUM_PROP_BORDER_TOP:
+ case NUM_PROP_BORDER_RIGHT:
+ case NUM_PROP_BORDER_BOTTOM:
+ case NUM_PROP_BORDER_LEFT:
+ case NUM_PROP_MARGIN_TOP:
+ case NUM_PROP_MARGIN_RIGHT:
+ case NUM_PROP_MARGIN_BOTTOM:
+ case NUM_PROP_MARGIN_LEFT:
+ cr_num_set (&a_this->num_props[i].sv,
+ 0, NUM_LENGTH_PX);
+ break;
+
+ default:
+ cr_utils_trace_info ("Unknown property");
+ break;
+ }
+ }
+
+ for (i = 0; i < NB_RGB_PROPS; i++) {
+
+ switch (i) {
+ /*default foreground color is black */
+ case RGB_PROP_COLOR:
+ cr_rgb_set (&a_this->rgb_props[i].sv, 0, 0, 0, FALSE);
+ break;
+
+ /*default background color is white */
+ case RGB_PROP_BACKGROUND_COLOR:
+ cr_rgb_set (&a_this->rgb_props[i].sv,
+ 255, 255, 255, FALSE);
+ cr_rgb_set_to_transparent (&a_this->rgb_props[i].sv,
+ TRUE) ;
+ break;
+ default:
+ cr_rgb_set (&a_this->rgb_props[i].sv, 0, 0, 0, FALSE);
+ break;
+ }
+ }
+
+ for (i = 0; i < NB_BORDER_STYLE_PROPS; i++) {
+ a_this->border_style_props[i] = BORDER_STYLE_NONE;
+ }
+
+ a_this->display = DISPLAY_BLOCK;
+ a_this->position = POSITION_STATIC;
+ a_this->float_type = FLOAT_NONE;
+ a_this->font_style = FONT_STYLE_NORMAL;
+ a_this->font_variant = FONT_VARIANT_NORMAL;
+ a_this->font_weight = FONT_WEIGHT_NORMAL;
+ a_this->font_stretch = FONT_STRETCH_NORMAL;
+ a_this->white_space = WHITE_SPACE_NORMAL;
+ cr_font_size_set_predefined_absolute_font_size
+ (&a_this->font_size.sv, FONT_SIZE_MEDIUM) ;
+ a_this->inherited_props_resolved = FALSE ;
+
+ return CR_OK;
+}
+
+/**
+ *Resolves the inherited properties.
+ *The function sets the "inherited" properties to either the value of
+ *their parent properties.
+ *This function is *NOT* recursive. So the inherited properties of
+ *the parent style must have been resolved prior to calling this function.
+ *@param a_this the instance where
+ *@return CR_OK if a root node is found and the propagation is successful,
+ *an error code otherwise
+ */
+enum CRStatus
+cr_style_resolve_inherited_properties (CRStyle *a_this)
+{
+ enum CRStatus ret = CR_OK;
+ glong i = 0;
+
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+ g_return_val_if_fail (a_this->parent_style, CR_BAD_PARAM_ERROR) ;
+
+ if (a_this->inherited_props_resolved == TRUE)
+ return CR_OK ;
+
+ for (i=0 ; i < NB_NUM_PROPS ;i++) {
+ if (a_this->num_props[i].sv.type == NUM_INHERIT) {
+ cr_num_copy (&a_this->num_props[i].cv,
+ &a_this->parent_style->num_props[i].cv);
+ }
+ }
+ for (i=0; i < NB_RGB_PROPS; i++) {
+ if (cr_rgb_is_set_to_inherit (&a_this->rgb_props[i].sv) == TRUE) {
+ cr_rgb_copy (
+ &a_this->rgb_props[i].cv,
+ &a_this->parent_style->rgb_props[i].cv);
+ }
+ }
+ for (i = 0; i < NB_BORDER_STYLE_PROPS; i++) {
+ if (a_this->border_style_props[i] == BORDER_STYLE_INHERIT) {
+ a_this->border_style_props[i] =
+ a_this->parent_style->border_style_props[i];
+ }
+ }
+
+ if (a_this->display == DISPLAY_INHERIT) {
+ a_this->display = a_this->parent_style->display;
+ }
+ if (a_this->position == POSITION_INHERIT) {
+ a_this->position = a_this->parent_style->position;
+ }
+ if (a_this->float_type == FLOAT_INHERIT) {
+ a_this->float_type = a_this->parent_style->float_type;
+ }
+ if (a_this->font_style == FONT_STYLE_INHERIT) {
+ a_this->font_style = a_this->parent_style->font_style;
+ }
+ if (a_this->font_variant == FONT_VARIANT_INHERIT) {
+ a_this->font_variant = a_this->parent_style->font_variant;
+ }
+ if (a_this->font_weight == FONT_WEIGHT_INHERIT) {
+ a_this->font_weight = a_this->parent_style->font_weight;
+ }
+ if (a_this->font_stretch == FONT_STRETCH_INHERIT) {
+ a_this->font_stretch = a_this->parent_style->font_stretch;
+ }
+ /*NULL is inherit marker for font_famiy*/
+ if (a_this->font_family == NULL) {
+ a_this->font_family = a_this->parent_style->font_family;
+ }
+ if (a_this->font_size.sv.type == INHERITED_FONT_SIZE) {
+ cr_font_size_copy (&a_this->font_size.cv,
+ &a_this->parent_style->font_size.cv) ;
+ }
+ a_this->inherited_props_resolved = TRUE ;
+ return ret;
+}
+
+/**
+ *Walks through a css2 property declaration, and populated the
+ *according field(s) in the #CRStyle structure.
+ *If the properties or their value(s) are/is not known,
+ *sets the corresponding field(s) of #CRStyle to its/their default
+ *value(s)
+ *@param a_this the instance of #CRStyle to set.
+ *@param a_decl the declaration from which the #CRStyle fields are set.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_style_set_style_from_decl (CRStyle * a_this, CRDeclaration * a_decl)
+{
+ CRTerm *value = NULL;
+ enum CRStatus status = CR_OK;
+
+ enum CRPropertyID prop_id = PROP_ID_NOT_KNOWN;
+
+ g_return_val_if_fail (a_this && a_decl
+ && a_decl
+ && a_decl->property
+ && a_decl->property->stryng
+ && a_decl->property->stryng->str,
+ CR_BAD_PARAM_ERROR);
+
+ prop_id = cr_style_get_prop_id
+ ((const guchar *) a_decl->property->stryng->str);
+
+ value = a_decl->value;
+ switch (prop_id) {
+ case PROP_ID_PADDING_TOP:
+ status = set_prop_padding_x_from_value
+ (a_this, value, DIR_TOP);
+ break;
+
+ case PROP_ID_PADDING_RIGHT:
+ status = set_prop_padding_x_from_value
+ (a_this, value, DIR_RIGHT);
+ break;
+ case PROP_ID_PADDING_BOTTOM:
+ status = set_prop_padding_x_from_value
+ (a_this, value, DIR_BOTTOM);
+ break;
+
+ case PROP_ID_PADDING_LEFT:
+ status = set_prop_padding_x_from_value
+ (a_this, value, DIR_LEFT);
+ break;
+
+ case PROP_ID_PADDING:
+ status = set_prop_padding_from_value (a_this, value) ;
+ break;
+
+ case PROP_ID_BORDER_TOP_WIDTH:
+ status = set_prop_border_x_width_from_value (a_this, value,
+ DIR_TOP);
+ break;
+
+ case PROP_ID_BORDER_RIGHT_WIDTH:
+ status = set_prop_border_x_width_from_value (a_this, value,
+ DIR_RIGHT);
+ break;
+
+ case PROP_ID_BORDER_BOTTOM_WIDTH:
+ status = set_prop_border_x_width_from_value (a_this, value,
+ DIR_BOTTOM);
+ break;
+
+ case PROP_ID_BORDER_LEFT_WIDTH:
+ status = set_prop_border_x_width_from_value (a_this, value,
+ DIR_LEFT);
+ break;
+
+ case PROP_ID_BORDER_WIDTH:
+ status = set_prop_border_width_from_value (a_this, value) ;
+ break ;
+
+ case PROP_ID_BORDER_TOP_STYLE:
+ status = set_prop_border_x_style_from_value (a_this, value,
+ DIR_TOP);
+ break;
+
+ case PROP_ID_BORDER_RIGHT_STYLE:
+ status = set_prop_border_x_style_from_value (a_this, value,
+ DIR_RIGHT);
+ break;
+
+ case PROP_ID_BORDER_BOTTOM_STYLE:
+ status = set_prop_border_x_style_from_value (a_this, value,
+ DIR_BOTTOM);
+ break;
+
+ case PROP_ID_BORDER_LEFT_STYLE:
+ status = set_prop_border_x_style_from_value (a_this, value,
+ DIR_LEFT);
+ break;
+
+ case PROP_ID_BORDER_STYLE:
+ status = set_prop_border_style_from_value (a_this, value) ;
+ break ;
+
+ case PROP_ID_BORDER_TOP_COLOR:
+ status = set_prop_border_x_color_from_value (a_this, value,
+ DIR_TOP);
+ break;
+
+ case PROP_ID_BORDER_RIGHT_COLOR:
+ status = set_prop_border_x_color_from_value (a_this, value,
+ DIR_RIGHT);
+ break;
+
+ case PROP_ID_BORDER_BOTTOM_COLOR:
+ status = set_prop_border_x_color_from_value (a_this, value,
+ DIR_BOTTOM);
+ break;
+
+ case PROP_ID_BORDER_LEFT_COLOR:
+ status = set_prop_border_x_color_from_value (a_this, value,
+ DIR_BOTTOM);
+ break;
+
+ case PROP_ID_BORDER_TOP:
+ status = set_prop_border_x_from_value (a_this, value,
+ DIR_TOP);
+ break;
+
+ case PROP_ID_BORDER_RIGHT:
+ status = set_prop_border_x_from_value (a_this, value,
+ DIR_RIGHT);
+ break;
+
+ case PROP_ID_BORDER_BOTTOM:
+ status = set_prop_border_x_from_value (a_this, value,
+ DIR_BOTTOM);
+ break;
+
+ case PROP_ID_BORDER_LEFT:
+ status = set_prop_border_x_from_value (a_this, value,
+ DIR_LEFT);
+ break;
+
+ case PROP_ID_MARGIN_TOP:
+ status = set_prop_margin_x_from_value (a_this, value,
+ DIR_TOP);
+ break;
+
+ case PROP_ID_BORDER:
+ status = set_prop_border_from_value (a_this, value);
+ break;
+
+ case PROP_ID_MARGIN_RIGHT:
+ status = set_prop_margin_x_from_value (a_this, value,
+ DIR_RIGHT);
+ break;
+
+ case PROP_ID_MARGIN_BOTTOM:
+ status = set_prop_margin_x_from_value (a_this, value,
+ DIR_BOTTOM);
+ break;
+
+ case PROP_ID_MARGIN_LEFT:
+ status = set_prop_margin_x_from_value (a_this, value,
+ DIR_LEFT);
+ break;
+
+ case PROP_ID_MARGIN:
+ status = set_prop_margin_from_value (a_this, value);
+ break;
+
+ case PROP_ID_DISPLAY:
+ status = set_prop_display_from_value (a_this, value);
+ break;
+
+ case PROP_ID_POSITION:
+ status = set_prop_position_from_value (a_this, value);
+ break;
+
+ case PROP_ID_TOP:
+ status = set_prop_x_from_value (a_this, value, DIR_TOP);
+ break;
+
+ case PROP_ID_RIGHT:
+ status = set_prop_x_from_value (a_this, value, DIR_RIGHT);
+ break;
+
+ case PROP_ID_BOTTOM:
+ status = set_prop_x_from_value (a_this, value, DIR_BOTTOM);
+ break;
+
+ case PROP_ID_LEFT:
+ status = set_prop_x_from_value (a_this, value, DIR_LEFT);
+ break;
+
+ case PROP_ID_FLOAT:
+ status = set_prop_float (a_this, value);
+ break;
+
+ case PROP_ID_WIDTH:
+ status = set_prop_width (a_this, value);
+ break;
+
+ case PROP_ID_COLOR:
+ status = set_prop_color (a_this, value);
+ break;
+
+ case PROP_ID_BACKGROUND_COLOR:
+ status = set_prop_background_color (a_this, value);
+ break;
+
+ case PROP_ID_FONT_FAMILY:
+ status = set_prop_font_family_from_value (a_this, value);
+ break;
+
+ case PROP_ID_FONT_SIZE:
+ status = set_prop_font_size_from_value (a_this, value);
+ break;
+
+ case PROP_ID_FONT_STYLE:
+ status = set_prop_font_style_from_value (a_this, value);
+ break;
+
+ case PROP_ID_FONT_WEIGHT:
+ status = set_prop_font_weight_from_value (a_this, value);
+ break;
+
+ case PROP_ID_WHITE_SPACE:
+ status = set_prop_white_space_from_value(a_this, value);
+ break;
+
+ default:
+ return CR_UNKNOWN_TYPE_ERROR;
+
+ }
+
+ return status;
+}
+
+/**
+ *Increases the reference count
+ *of the current instance of #CRStyle.
+ *@param a_this the current instance of #CRStyle.
+ *@return CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_style_ref (CRStyle * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ a_this->ref_count++;
+ return CR_OK;
+}
+
+/**
+ *Decreases the reference count of
+ *the current instance of #CRStyle.
+ *If the reference count reaches 0, the
+ *instance of #CRStyle is destoyed.
+ *@param a_this the current instance of #CRStyle.
+ *@return TRUE if the instance has been destroyed, FALSE
+ *otherwise.
+ */
+gboolean
+cr_style_unref (CRStyle * a_this)
+{
+ g_return_val_if_fail (a_this, FALSE);
+
+ if (a_this->ref_count)
+ a_this->ref_count--;
+
+ if (!a_this->ref_count) {
+ cr_style_destroy (a_this);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ *Duplicates the current instance of #CRStyle .
+ *The newly created instance of #CRStyle must be
+ *freed using cr_style_destroy ().
+ *@param a_this the current instance of #CRStyle.
+ *@return the newly duplicated instance of #CRStyle.
+ */
+CRStyle *
+cr_style_dup (CRStyle * a_this)
+{
+ CRStyle *result = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ result = cr_style_new (FALSE);
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ cr_style_copy (result, a_this);
+ return result;
+}
+
+/**
+ *Copies a style data structure into another.
+ *TODO: this is actually broken because it's based
+ *on memcpy although some data structures of CRStyle should
+ *be properly duplicated.
+ *@param a_dest the destination style datastructure
+ *@param a_src the source style datastructure.
+ *@return CR_OK upon successful completion, an error code otherwise
+ */
+enum CRStatus
+cr_style_copy (CRStyle * a_dest, CRStyle * a_src)
+{
+ g_return_val_if_fail (a_dest && a_src, CR_BAD_PARAM_ERROR);
+
+ memcpy (a_dest, a_src, sizeof (CRStyle));
+ return CR_OK;
+}
+
+/**
+ *dump a CRNumpPropVal in a string.
+ *@param a_prop_val the numerical property value to dump
+ *@param a_str the string to dump the numerical property into.
+ *Note that the string value is appended to a_str.
+ *@param a_nb_indent the number white chars of indentation.
+ */
+enum CRStatus
+cr_style_num_prop_val_to_string (CRNumPropVal * a_prop_val,
+ GString * a_str, guint a_nb_indent)
+{
+ enum CRStatus status = CR_OK;
+ guchar *tmp_str = NULL;
+ GString *str = NULL;
+
+ g_return_val_if_fail (a_prop_val && a_str, CR_BAD_PARAM_ERROR);
+
+ str = g_string_new (NULL);
+ cr_utils_dump_n_chars2 (' ', str, a_nb_indent);
+ g_string_append (str, "NumPropVal {");
+ tmp_str = cr_num_to_string (&a_prop_val->sv);
+ if (!tmp_str) {
+ status = CR_ERROR;
+ goto cleanup;
+ }
+ g_string_append_printf (str, "sv: %s ", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+
+ tmp_str = cr_num_to_string (&a_prop_val->cv);
+ if (!tmp_str) {
+ status = CR_ERROR;
+ goto cleanup;
+ }
+ g_string_append_printf (str, "cv: %s ", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+
+ tmp_str = cr_num_to_string (&a_prop_val->av);
+ if (!tmp_str) {
+ status = CR_ERROR;
+ goto cleanup;
+ }
+ g_string_append_printf (str, "av: %s ", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ g_string_append (str, "}");
+ g_string_append (a_str, str->str);
+ status = CR_OK;
+ cleanup:
+
+ if (tmp_str) {
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ if (str) {
+ g_string_free (str, TRUE);
+ }
+ return status;
+}
+
+enum CRStatus
+cr_style_rgb_prop_val_to_string (CRRgbPropVal * a_prop_val,
+ GString * a_str, guint a_nb_indent)
+{
+ enum CRStatus status = CR_OK;
+ guchar *tmp_str = NULL;
+ GString *str = NULL;
+
+ g_return_val_if_fail (a_prop_val && a_str, CR_BAD_PARAM_ERROR);
+
+ str = g_string_new (NULL);
+
+ cr_utils_dump_n_chars2 (' ', str, a_nb_indent);
+ g_string_append (str, "RGBPropVal {");
+ tmp_str = cr_rgb_to_string (&a_prop_val->sv);
+ if (!tmp_str) {
+ status = CR_ERROR;
+ goto cleanup;
+ }
+ g_string_append_printf (str, "sv: %s ", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ tmp_str = cr_rgb_to_string (&a_prop_val->cv);
+ if (!tmp_str) {
+ status = CR_ERROR;
+ goto cleanup;
+ }
+ g_string_append_printf (str, "cv: %s ", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ tmp_str = cr_rgb_to_string (&a_prop_val->av);
+ if (!tmp_str) {
+ status = CR_ERROR;
+ goto cleanup;
+ }
+ g_string_append_printf (str, "av: %s ", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+
+ g_string_append (str, "}");
+ g_string_append (a_str, str->str);
+ status = CR_OK;
+ cleanup:
+
+ if (tmp_str) {
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ if (str) {
+ g_string_free (str, TRUE);
+ }
+ return status;
+}
+
+enum CRStatus
+cr_style_border_style_to_string (enum CRBorderStyle a_prop,
+ GString * a_str, guint a_nb_indent)
+{
+ gchar *str = NULL;
+
+ g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
+
+ switch (a_prop) {
+ case BORDER_STYLE_NONE:
+ str = (gchar *) "border-style-none";
+ break;
+ case BORDER_STYLE_HIDDEN:
+ str = (gchar *) "border-style-hidden";
+ break;
+ case BORDER_STYLE_DOTTED:
+ str = (gchar *) "border-style-dotted";
+ break;
+ case BORDER_STYLE_DASHED:
+ str = (gchar *) "border-style-dashed";
+ break;
+ case BORDER_STYLE_SOLID:
+ str = (gchar *) "border-style-solid";
+ break;
+ case BORDER_STYLE_DOUBLE:
+ str = (gchar *) "border-style-double";
+ break;
+ case BORDER_STYLE_GROOVE:
+ str = (gchar *) "border-style-groove";
+ break;
+ case BORDER_STYLE_RIDGE:
+ str = (gchar *) "border-style-ridge";
+ break;
+ case BORDER_STYLE_INSET:
+ str = (gchar *) "border-style-inset";
+ break;
+ case BORDER_STYLE_OUTSET:
+ str = (gchar *) "border-style-outset";
+ break;
+ default:
+ str = (gchar *) "unknown border style";
+ break;
+ }
+ cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
+ g_string_append (a_str, str);
+ return CR_OK;
+}
+
+enum CRStatus
+cr_style_display_type_to_string (enum CRDisplayType a_code,
+ GString * a_str, guint a_nb_indent)
+{
+ gchar *str = NULL;
+
+ g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
+
+ switch (a_code) {
+ case DISPLAY_NONE:
+ str = (gchar *) "display-none";
+ break;
+ case DISPLAY_INLINE:
+ str = (gchar *) "display-inline";
+ break;
+ case DISPLAY_BLOCK:
+ str = (gchar *) "display-block";
+ break;
+ case DISPLAY_LIST_ITEM:
+ str = (gchar *) "display-list-item";
+ break;
+ case DISPLAY_RUN_IN:
+ str = (gchar *) "display-run-in";
+ break;
+ case DISPLAY_COMPACT:
+ str = (gchar *) "display-compact";
+ break;
+ case DISPLAY_MARKER:
+ str = (gchar *) "display-marker";
+ break;
+ case DISPLAY_TABLE:
+ str = (gchar *) "display-table";
+ break;
+ case DISPLAY_INLINE_TABLE:
+ str = (gchar *) "display-inline-table";
+ break;
+ case DISPLAY_TABLE_ROW_GROUP:
+ str = (gchar *) "display-table-row-group";
+ break;
+ case DISPLAY_TABLE_HEADER_GROUP:
+ str = (gchar *) "display-table-header-group";
+ break;
+ case DISPLAY_TABLE_FOOTER_GROUP:
+ str = (gchar *) "display-table-footer-group";
+ break;
+ case DISPLAY_TABLE_ROW:
+ str = (gchar *) "display-table-row";
+ break;
+ case DISPLAY_TABLE_COLUMN_GROUP:
+ str = (gchar *) "display-table-column-group";
+ break;
+ case DISPLAY_TABLE_COLUMN:
+ str = (gchar *) "display-table-column";
+ break;
+ case DISPLAY_TABLE_CELL:
+ str = (gchar *) "display-table-cell";
+ break;
+ case DISPLAY_TABLE_CAPTION:
+ str = (gchar *) "display-table-caption";
+ break;
+ case DISPLAY_INHERIT:
+ str = (gchar *) "display-inherit";
+ break;
+ default:
+ str = (gchar *) "unknown display property";
+ break;
+ }
+ cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
+ g_string_append (a_str, str);
+ return CR_OK;
+
+}
+
+enum CRStatus
+cr_style_position_type_to_string (enum CRPositionType a_code,
+ GString * a_str, guint a_nb_indent)
+{
+ gchar *str = NULL;
+
+ g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
+
+ switch (a_code) {
+ case POSITION_STATIC:
+ str = (gchar *) "position-static";
+ break;
+ case POSITION_RELATIVE:
+ str = (gchar *) "position-relative";
+ break;
+ case POSITION_ABSOLUTE:
+ str = (gchar *) "position-absolute";
+ break;
+ case POSITION_FIXED:
+ str = (gchar *) "position-fixed";
+ break;
+ case POSITION_INHERIT:
+ str = (gchar *) "position-inherit";
+ break;
+ default:
+ str = (gchar *) "unknown static property";
+ }
+ cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
+ g_string_append (a_str, str);
+ return CR_OK;
+}
+
+enum CRStatus
+cr_style_float_type_to_string (enum CRFloatType a_code,
+ GString * a_str, guint a_nb_indent)
+{
+ gchar *str = NULL;
+
+ g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
+
+ switch (a_code) {
+ case FLOAT_NONE:
+ str = (gchar *) "float-none";
+ break;
+ case FLOAT_LEFT:
+ str = (gchar *) "float-left";
+ break;
+ case FLOAT_RIGHT:
+ str = (gchar *) "float-right";
+ break;
+ case FLOAT_INHERIT:
+ str = (gchar *) "float-inherit";
+ break;
+ default:
+ str = (gchar *) "unknown float property value";
+ break;
+ }
+ cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
+ g_string_append (a_str, str);
+ return CR_OK;
+}
+
+enum CRStatus
+cr_style_white_space_type_to_string (enum CRWhiteSpaceType a_code,
+ GString * a_str, guint a_nb_indent)
+{
+ gchar *str = NULL;
+
+ g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
+
+ switch (a_code) {
+ case WHITE_SPACE_NORMAL:
+ str = (gchar *) "normal";
+ break;
+ case WHITE_SPACE_PRE:
+ str = (gchar *) "pre";
+ break;
+ case WHITE_SPACE_NOWRAP:
+ str = (gchar *) "nowrap";
+ break;
+ case WHITE_SPACE_INHERIT:
+ str = (gchar *) "inherited";
+ break;
+ default:
+ str = (gchar *) "unknown white space property value";
+ break;
+ }
+ cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
+ g_string_append (a_str, str);
+ return CR_OK;
+}
+
+/**
+ *Serializes in instance of #CRStyle into
+ *a string
+ *@param a_this the instance of #CRStyle to serialize
+ *@param a_str the string to serialise the style into.
+ *if *a_str is NULL, a new GString is instantiated, otherwise
+ *the style serialisation is appended to the existed *a_str
+ *@param the number of white space char to use for indentation.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_style_to_string (CRStyle * a_this, GString ** a_str, guint a_nb_indent)
+{
+ const gint INTERNAL_INDENT = 2;
+ gint indent = a_nb_indent + INTERNAL_INDENT;
+ gchar *tmp_str = NULL;
+ GString *str = NULL;
+ gint i = 0;
+
+ g_return_val_if_fail (a_this && a_str, CR_BAD_PARAM_ERROR);
+
+ if (!*a_str) {
+ str = g_string_new (NULL);
+ } else {
+ str = *a_str;
+ }
+ cr_utils_dump_n_chars2 (' ', str, a_nb_indent);
+ g_string_append (str, "style {\n");
+
+ /*loop over the num_props and to_string() them */
+ for (i = NUM_PROP_TOP; i < NB_NUM_PROPS; i++) {
+ /*
+ *to_string() the name of the num_prop
+ *(using num_prop_code_to_string)
+ *before outputting it value
+ */
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ tmp_str = (gchar *) num_prop_code_to_string ((enum CRNumProp) i);
+ if (tmp_str) {
+ g_string_append_printf (str, "%s: ", tmp_str);
+ } else {
+ g_string_append (str, "NULL");
+ }
+ tmp_str = NULL;
+ cr_style_num_prop_val_to_string (&a_this->num_props[i], str,
+ a_nb_indent +
+ INTERNAL_INDENT);
+ g_string_append (str, "\n");
+ }
+ /*loop over the rgb_props and to_string() them all */
+ for (i = RGB_PROP_BORDER_TOP_COLOR; i < NB_RGB_PROPS; i++) {
+ tmp_str = (gchar *) rgb_prop_code_to_string ((enum CRRgbProp) i);
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ if (tmp_str) {
+ g_string_append_printf (str, "%s: ", tmp_str);
+ } else {
+ g_string_append (str, "NULL: ");
+ }
+ tmp_str = NULL;
+ cr_style_rgb_prop_val_to_string (&a_this->rgb_props[i], str,
+ a_nb_indent +
+ INTERNAL_INDENT);
+ g_string_append (str, "\n");
+ }
+ /*loop over the border_style_props and to_string() them */
+ for (i = BORDER_STYLE_PROP_TOP; i < NB_BORDER_STYLE_PROPS; i++) {
+ tmp_str = (gchar *) border_style_prop_code_to_string ((enum CRBorderStyleProp) i);
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ if (tmp_str) {
+ g_string_append_printf (str, "%s: ", tmp_str);
+ } else {
+ g_string_append (str, "NULL: ");
+ }
+ tmp_str = NULL;
+ cr_style_border_style_to_string (a_this->
+ border_style_props[i], str,
+ 0);
+ g_string_append (str, "\n");
+ }
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ g_string_append (str, "display: ");
+ cr_style_display_type_to_string (a_this->display, str, 0);
+ g_string_append (str, "\n");
+
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ g_string_append (str, "position: ");
+ cr_style_position_type_to_string (a_this->position, str, 0);
+ g_string_append (str, "\n");
+
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ g_string_append (str, "float-type: ");
+ cr_style_float_type_to_string (a_this->float_type, str, 0);
+ g_string_append (str, "\n");
+
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ g_string_append (str, "white-space: ");
+ cr_style_white_space_type_to_string (a_this->white_space, str, 0);
+ g_string_append (str, "\n");
+
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ g_string_append (str, "font-family: ");
+ tmp_str = (gchar *) cr_font_family_to_string (a_this->font_family, TRUE);
+ if (tmp_str) {
+ g_string_append (str, tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ } else {
+ g_string_append (str, "NULL");
+ }
+ g_string_append (str, "\n");
+
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ tmp_str = cr_font_size_to_string (&a_this->font_size.sv);
+ if (tmp_str) {
+ g_string_append_printf (str, "font-size {sv:%s, ",
+ tmp_str) ;
+ } else {
+ g_string_append (str, "font-size {sv:NULL, ");
+ }
+ tmp_str = cr_font_size_to_string (&a_this->font_size.cv);
+ if (tmp_str) {
+ g_string_append_printf (str, "cv:%s, ", tmp_str);
+ } else {
+ g_string_append (str, "cv:NULL, ");
+ }
+ tmp_str = cr_font_size_to_string (&a_this->font_size.av);
+ if (tmp_str) {
+ g_string_append_printf (str, "av:%s}", tmp_str);
+ } else {
+ g_string_append (str, "av:NULL}");
+ }
+
+ tmp_str = NULL;
+ g_string_append (str, "\n");
+
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ tmp_str = cr_font_size_adjust_to_string (a_this->font_size_adjust);
+ if (tmp_str) {
+ g_string_append_printf (str, "font-size-adjust: %s", tmp_str);
+ } else {
+ g_string_append (str, "font-size-adjust: NULL");
+ }
+ tmp_str = NULL;
+ g_string_append (str, "\n");
+
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ tmp_str = (gchar *) cr_font_style_to_string (a_this->font_style);
+ if (tmp_str) {
+ g_string_append_printf (str, "font-style: %s", tmp_str);
+ } else {
+ g_string_append (str, "font-style: NULL");
+ }
+ tmp_str = NULL;
+ g_string_append (str, "\n");
+
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ tmp_str = (gchar *) cr_font_variant_to_string (a_this->font_variant);
+ if (tmp_str) {
+ g_string_append_printf (str, "font-variant: %s", tmp_str);
+ } else {
+ g_string_append (str, "font-variant: NULL");
+ }
+ tmp_str = NULL;
+ g_string_append (str, "\n");
+
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ tmp_str = (gchar *) cr_font_weight_to_string (a_this->font_weight);
+ if (tmp_str) {
+ g_string_append_printf (str, "font-weight: %s", tmp_str);
+ } else {
+ g_string_append (str, "font-weight: NULL");
+ }
+ tmp_str = NULL;
+ g_string_append (str, "\n");
+
+ cr_utils_dump_n_chars2 (' ', str, indent);
+ tmp_str = (gchar *) cr_font_stretch_to_string (a_this->font_stretch);
+ if (tmp_str) {
+ g_string_append_printf (str, "font-stretch: %s", tmp_str);
+ } else {
+ g_string_append (str, "font-stretch: NULL");
+ }
+ tmp_str = NULL;
+ g_string_append (str, "\n");
+
+
+ cr_utils_dump_n_chars2 (' ', str, a_nb_indent);
+ g_string_append (str, "}");
+
+ return CR_OK;
+}
+
+/**
+ *Destructor of the #CRStyle class.
+ *@param a_this the instance to destroy.
+ */
+void
+cr_style_destroy (CRStyle * a_this)
+{
+ g_return_if_fail (a_this);
+
+ g_free (a_this);
+}
+
diff --git a/src/3rdparty/libcroco/src/cr-style.h b/src/3rdparty/libcroco/src/cr-style.h
new file mode 100644
index 0000000..18aeaad
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-style.h
@@ -0,0 +1,339 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli.
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#ifndef __CR_STYLE_H__
+#define __CR_STYLE_H__
+
+#include "cr-utils.h"
+#include "cr-statement.h"
+#include "cr-fonts.h"
+
+/**
+ *@file
+ *The declaration of the #CRStyle class.
+ */
+G_BEGIN_DECLS
+
+typedef struct _CRStyle CRStyle ;
+
+enum CRBorderStyle
+{
+ BORDER_STYLE_NONE = 0,
+ BORDER_STYLE_HIDDEN,
+ BORDER_STYLE_DOTTED,
+ BORDER_STYLE_DASHED,
+ BORDER_STYLE_SOLID,
+ BORDER_STYLE_DOUBLE,
+ BORDER_STYLE_GROOVE,
+ BORDER_STYLE_RIDGE,
+ BORDER_STYLE_INSET,
+ BORDER_STYLE_OUTSET,
+ BORDER_STYLE_INHERIT
+} ;
+
+enum CRDisplayType
+{
+ DISPLAY_NONE,
+ DISPLAY_INLINE,
+ DISPLAY_BLOCK,
+ DISPLAY_LIST_ITEM,
+ DISPLAY_RUN_IN,
+ DISPLAY_COMPACT,
+ DISPLAY_MARKER,
+ DISPLAY_TABLE,
+ DISPLAY_INLINE_TABLE,
+ DISPLAY_TABLE_ROW_GROUP,
+ DISPLAY_TABLE_HEADER_GROUP,
+ DISPLAY_TABLE_FOOTER_GROUP,
+ DISPLAY_TABLE_ROW,
+ DISPLAY_TABLE_COLUMN_GROUP,
+ DISPLAY_TABLE_COLUMN,
+ DISPLAY_TABLE_CELL,
+ DISPLAY_TABLE_CAPTION,
+ DISPLAY_INHERIT
+} ;
+
+enum CRPositionType
+{
+ POSITION_STATIC,
+ POSITION_RELATIVE,
+ POSITION_ABSOLUTE,
+ POSITION_FIXED,
+ POSITION_INHERIT
+} ;
+
+enum CRFloatType
+{
+ FLOAT_NONE,
+ FLOAT_LEFT,
+ FLOAT_RIGHT,
+ FLOAT_INHERIT
+} ;
+
+enum CRWhiteSpaceType
+{
+ WHITE_SPACE_NORMAL,
+ WHITE_SPACE_PRE,
+ WHITE_SPACE_NOWRAP,
+ WHITE_SPACE_INHERIT
+} ;
+
+
+#define BORDER_THIN 2
+#define BORDER_MEDIUM 4
+#define BORDER_THICK 6
+
+
+/**
+ *A numerical css property value.
+ *This data type is actually split in 3 parts:
+ *1/the specified value
+ *2/the computed value
+ *3/the actual value.
+ *To understand the semantic of these three parts,
+ *see css2 spec chap 6.1 ("Specified, computed and actual values.").
+ */
+typedef struct _CRNumPropVal CRNumPropVal ;
+struct _CRNumPropVal
+{
+ /**specified value*/
+ CRNum sv ;
+ /**computed value*/
+ CRNum cv ;
+ /**actual value*/
+ CRNum av ;
+} ;
+
+/**
+ *An rgb css property value.
+ *This data type is actually split in 3 parts:
+ *1/the specified value
+ *2/the computed value
+ *3/the actual value.
+ *To understand the semantic of these three parts,
+ *see css2 spec chap 6.1 ("Specified, computed and actual values.").
+ */
+typedef struct _CRRgbPropVal CRRgbPropVal ;
+struct _CRRgbPropVal
+{
+ /**specified value*/
+ CRRgb sv ;
+ /**computed value*/
+ CRRgb cv ;
+ /**actual value*/
+ CRRgb av ;
+} ;
+
+
+enum CRNumProp
+{
+ NUM_PROP_TOP=0,
+ NUM_PROP_RIGHT,
+ NUM_PROP_BOTTOM,
+ NUM_PROP_LEFT,/*3*/
+
+ NUM_PROP_PADDING_TOP,
+ NUM_PROP_PADDING_RIGHT,
+ NUM_PROP_PADDING_BOTTOM,
+ NUM_PROP_PADDING_LEFT,/*7*/
+
+ NUM_PROP_BORDER_TOP,
+ NUM_PROP_BORDER_RIGHT,
+ NUM_PROP_BORDER_BOTTOM,
+ NUM_PROP_BORDER_LEFT,/*11*/
+
+ NUM_PROP_MARGIN_TOP,
+ NUM_PROP_MARGIN_RIGHT,
+ NUM_PROP_MARGIN_BOTTOM,
+ NUM_PROP_MARGIN_LEFT,/*15*/
+
+ NUM_PROP_WIDTH,
+
+ /*must be last*/
+ NB_NUM_PROPS
+} ;
+
+enum CRRgbProp
+{
+ RGB_PROP_BORDER_TOP_COLOR = 0,
+ RGB_PROP_BORDER_RIGHT_COLOR,
+ RGB_PROP_BORDER_BOTTOM_COLOR,
+ RGB_PROP_BORDER_LEFT_COLOR,
+ RGB_PROP_COLOR,
+ RGB_PROP_BACKGROUND_COLOR,
+
+ /*must be last*/
+ NB_RGB_PROPS
+} ;
+
+
+enum CRBorderStyleProp
+{
+ BORDER_STYLE_PROP_TOP = 0,
+ BORDER_STYLE_PROP_RIGHT,
+ BORDER_STYLE_PROP_BOTTOM,
+ BORDER_STYLE_PROP_LEFT,
+
+ /*must be last*/
+ NB_BORDER_STYLE_PROPS
+} ;
+
+enum CRBoxOffsetProp
+{
+ BOX_OFFSET_PROP_TOP = 0,
+ BOX_OFFSET_PROP_RIGHT,
+ BOX_OFFSET_PROP_BOTTOM,
+ BOX_OFFSET_PROP_LEFT,
+
+ /*must be last*/
+ NB_BOX_OFFSET_PROPS
+} ;
+
+typedef struct _CRFontSizeVal CRFontSizeVal ;
+struct _CRFontSizeVal {
+ /*specified value*/
+ CRFontSize sv ;
+ /*computed value*/
+ CRFontSize cv ;
+ /*actual value*/
+ CRFontSize av ;
+} ;
+
+/**
+ *The css2 style class.
+ *Contains computed and actual values
+ *inferred from the declarations found
+ *in the stylesheets.
+ *See css2 spec chapter 6.
+ */
+struct _CRStyle
+{
+ /**
+ *numerical properties.
+ *the properties are indexed by
+ *enum #CRNumProp.
+ */
+ CRNumPropVal num_props[NB_NUM_PROPS] ;
+
+ /**
+ *color properties.
+ *They are indexed by enum #CRRgbProp .
+ */
+ CRRgbPropVal rgb_props[NB_RGB_PROPS] ;
+
+ /**
+ *border style properties.
+ *They are indexed by enum #CRBorderStyleProp .
+ */
+ enum CRBorderStyle border_style_props[NB_BORDER_STYLE_PROPS] ;
+
+ /**box display type*/
+ enum CRDisplayType display ;
+
+ /**the positioning scheme*/
+ enum CRPositionType position ;
+
+ /**the float property*/
+ enum CRFloatType float_type ;
+
+ /*
+ *the 'font-family' property.
+ */
+ CRFontFamily *font_family ;
+
+ /**
+ *the 'font-size' property.
+ */
+ CRFontSizeVal font_size ;
+ CRFontSizeAdjust *font_size_adjust ;
+ enum CRFontStyle font_style ;
+ enum CRFontVariant font_variant ;
+ enum CRFontWeight font_weight ;
+ enum CRFontStretch font_stretch ;
+
+ /**
+ * the 'tex' properties
+ */
+ enum CRWhiteSpaceType white_space;
+
+ gboolean inherited_props_resolved ;
+ CRStyle *parent_style ;
+ gulong ref_count ;
+} ;
+
+enum CRStatus cr_style_white_space_type_to_string (enum CRWhiteSpaceType a_code,
+ GString * a_str, guint a_nb_indent) ;
+
+enum CRStatus cr_style_num_prop_val_to_string (CRNumPropVal *a_prop_val,
+ GString *a_str,
+ guint a_nb_indent) ;
+
+enum CRStatus cr_style_rgb_prop_val_to_string (CRRgbPropVal *a_prop_val,
+ GString *a_str,
+ guint a_nb_indent) ;
+
+enum CRStatus cr_style_border_style_to_string (enum CRBorderStyle a_prop,
+ GString *a_str,
+ guint a_nb_indent) ;
+
+enum CRStatus cr_style_display_type_to_string (enum CRDisplayType a_code,
+ GString *a_str,
+ guint a_nb_indent) ;
+
+enum CRStatus cr_style_position_type_to_string (enum CRPositionType a_code,
+ GString *a_str,
+ guint a_nb_indent) ;
+
+enum CRStatus cr_style_float_type_to_string (enum CRFloatType a_code,
+ GString *a_str,
+ guint a_nb_indent) ;
+
+CRStyle * cr_style_new (gboolean a_set_props_to_initial_values) ;
+
+enum CRStatus cr_style_set_props_to_default_values (CRStyle *a_this) ;
+enum CRStatus cr_style_set_props_to_initial_values (CRStyle *a_this) ;
+enum CRStatus cr_style_resolve_inherited_properties (CRStyle *a_this) ;
+enum CRStatus cr_style_propagate_from_parent (CRStyle *a_this);
+
+enum CRStatus cr_style_set_style_from_decl (CRStyle *a_this,
+ CRDeclaration *a_decl) ;
+
+
+enum CRStatus cr_style_copy (CRStyle *a_dest, CRStyle *a_src) ;
+
+enum CRStatus cr_style_ref (CRStyle *a_this) ;
+
+gboolean cr_style_unref (CRStyle *a_this) ;
+
+void cr_style_destroy (CRStyle *a_this) ;
+
+CRStyle * cr_style_dup (CRStyle *a_this) ;
+
+enum CRStatus cr_style_to_string (CRStyle *a_this,
+ GString **a_str,
+ guint a_nb_indent) ;
+
+G_END_DECLS
+
+#endif /*__CR_STYLE_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-stylesheet.c b/src/3rdparty/libcroco/src/cr-stylesheet.c
new file mode 100644
index 0000000..2ea0fa6
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-stylesheet.c
@@ -0,0 +1,268 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2004 Dodji Seketeli
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include "string.h"
+#include "cr-stylesheet.h"
+
+/**
+ *@file
+ *The definition of the #CRStyleSheet class
+ */
+
+/**
+ *Constructor of the #CRStyleSheet class.
+ *@param the initial list of css statements.
+ *@return the newly built css2 stylesheet, or NULL in case of error.
+ */
+CRStyleSheet *
+cr_stylesheet_new (CRStatement * a_stmts)
+{
+ CRStyleSheet *result;
+
+ result = (CRStyleSheet *) g_try_malloc (sizeof (CRStyleSheet));
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRStyleSheet));
+
+ if (a_stmts)
+ result->statements = a_stmts;
+
+ result->ref_count = 1;
+
+ return result;
+}
+
+/**
+ *@param a_this the current instance of #CRStyleSheet
+ *@return the serialized stylesheet.
+ */
+gchar *
+cr_stylesheet_to_string (CRStyleSheet const *a_this)
+{
+ gchar *str = NULL;
+ GString *stringue = NULL;
+ CRStatement const *cur_stmt = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ stringue = g_string_new (NULL) ;
+ g_return_val_if_fail (stringue, NULL) ;
+
+ for (cur_stmt = a_this->statements;
+ cur_stmt; cur_stmt = cur_stmt->next) {
+ if (cur_stmt->prev) {
+ g_string_append (stringue, "\n\n") ;
+ }
+ str = cr_statement_to_string (cur_stmt, 0) ;
+ if (str) {
+ g_string_append (stringue, str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ }
+
+ if (a_this->next) {
+ str = cr_stylesheet_to_string (a_this->next);
+ if (str) {
+ g_string_append (stringue, "\n") ;
+ g_string_append (stringue, str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+ }
+
+ if (stringue) {
+ str = stringue->str ;
+ g_string_free (stringue, FALSE) ;
+ stringue = NULL ;
+ }
+ return str ;
+}
+
+/**
+ *Dumps the current css2 stylesheet to a file.
+ *@param a_this the current instance of #CRStyleSheet.
+ *@param a_fp the destination file
+ */
+void
+cr_stylesheet_dump (CRStyleSheet const * a_this, FILE * a_fp)
+{
+ gchar *str = NULL ;
+
+ g_return_if_fail (a_this);
+
+ str = cr_stylesheet_to_string (a_this) ;
+ if (str) {
+ fprintf (a_fp, "%s", str) ;
+ g_free (str) ;
+ str = NULL ;
+ }
+}
+
+/**
+ *Return the number of rules in the stylesheet.
+ *@param a_this the current instance of #CRStyleSheet.
+ *@return number of rules in the stylesheet.
+ */
+gint
+cr_stylesheet_nr_rules (CRStyleSheet const * a_this)
+{
+ g_return_val_if_fail (a_this, -1);
+
+ return cr_statement_nr_rules (a_this->statements);
+}
+
+/**
+ *Use an index to get a CRStatement from the rules in a given stylesheet.
+ *@param a_this the current instance of #CRStatement.
+ *@param itemnr the index into the rules.
+ *@return CRStatement at position itemnr, if itemnr > number of rules - 1,
+ *it will return NULL.
+ */
+CRStatement *
+cr_stylesheet_statement_get_from_list (CRStyleSheet * a_this, int itemnr)
+{
+ g_return_val_if_fail (a_this, NULL);
+
+ return cr_statement_get_from_list (a_this->statements, itemnr);
+}
+
+/**
+ *Appends a new stylesheet to the current list of #CRStylesheet, setting
+ *the "origin" of the new stylesheet to be the same as the others in list.
+ *
+ *@param a_this the "this pointer" of the current instance
+ *of #CRStylesheet .
+ *@param a_new_stylesheet the stylesheet to append.
+ *@return the list of stylesheets with the a_new_stylesheet appended to it.
+ */
+CRStyleSheet *
+cr_stylesheet_append_stylesheet (CRStyleSheet * a_this, CRStyleSheet * a_new_stylesheet)
+{
+ CRStyleSheet *cur = NULL;
+
+ g_return_val_if_fail (a_new_stylesheet, NULL);
+
+ if (a_this == NULL)
+ return a_new_stylesheet;
+
+ for (cur = a_this; cur->next; cur = cur->next) ;
+
+ cur->next = a_new_stylesheet;
+ a_new_stylesheet->prev = cur;
+
+ /* The "origin" must apriori be the same for all stylesheets
+ in a list. We must set it correctly or errors will occur in
+ put_css_properties_in_props_list(). The "origin" of the initial
+ stylesheet in the list is set in cr_cascade_set_sheet(). */
+ a_new_stylesheet->origin = cur->origin;
+
+ return a_this;
+}
+
+/**
+ * cr_stylesheet_unlink:
+ *@a_this: the stylesheet to unlink.
+ *
+ *Unlinks the stylesheet from the stylesheet list.
+ *
+ *Returns a pointer to the unlinked stylesheet in
+ *case of a successfull completion, NULL otherwise.
+ */
+CRStyleSheet *
+cr_stylesheet_unlink (CRStyleSheet * a_this)
+{
+ CRStyleSheet *result = a_this;
+
+ g_return_val_if_fail (result, NULL);
+
+ /*
+ *some sanity checks first
+ */
+ if (a_this->prev) {
+ g_return_val_if_fail (a_this->prev->next == a_this, NULL);
+
+ }
+ if (a_this->next) {
+ g_return_val_if_fail (a_this->next->prev == a_this, NULL);
+ }
+
+ /*
+ *now, the real unlinking job.
+ */
+ if (a_this->prev) {
+ a_this->prev->next = a_this->next;
+ }
+ if (a_this->next) {
+ a_this->next->prev = a_this->prev;
+ }
+
+ a_this->next = NULL;
+ a_this->prev = NULL;
+
+ return a_this;
+}
+
+void
+cr_stylesheet_ref (CRStyleSheet * a_this)
+{
+ g_return_if_fail (a_this);
+
+ a_this->ref_count++;
+}
+
+gboolean
+cr_stylesheet_unref (CRStyleSheet * a_this)
+{
+ g_return_val_if_fail (a_this, FALSE);
+
+ if (!--a_this->ref_count) {
+ cr_stylesheet_destroy (a_this);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ *Destructor of the #CRStyleSheet class.
+ *@param a_this the current instance of the #CRStyleSheet class.
+ */
+void
+cr_stylesheet_destroy (CRStyleSheet * a_this)
+{
+ g_return_if_fail (a_this);
+
+ if (a_this->statements) {
+ cr_statement_destroy (a_this->statements);
+ a_this->statements = NULL;
+ }
+
+ if (a_this->next) {
+ cr_stylesheet_destroy (a_this->next);
+ }
+
+ g_free (a_this);
+}
diff --git a/src/3rdparty/libcroco/src/cr-stylesheet.h b/src/3rdparty/libcroco/src/cr-stylesheet.h
new file mode 100644
index 0000000..cf7b093
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-stylesheet.h
@@ -0,0 +1,117 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * see COPYRIGHTS file for copyright information.
+ */
+
+
+#ifndef __CR_STYLESHEET_H__
+#define __CR_STYLESHEET_H__
+
+#include "cr-utils.h"
+#include "cr-statement.h"
+
+G_BEGIN_DECLS
+
+/**
+ *@file
+ *The declaration of the #CRStyleSheet class.
+ */
+
+
+enum CRStyleOrigin
+{
+ /*Please don't change the order of
+ *the values enumerated here ...
+ *New values should be added at the end,
+ *just before ORIGIN_END.
+ */
+ ORIGIN_UA = 0,
+ ORIGIN_USER,
+ ORIGIN_AUTHOR,
+
+ /*must always be the last one*/
+ NB_ORIGINS
+} ;
+
+/**
+ *An abstraction of a css stylesheet as defined
+ *by the css2 spec in chapter 4.
+ */
+struct _CRStyleSheet
+{
+ /**The css statements list*/
+ CRStatement *statements ;
+
+ enum CRStyleOrigin origin ;
+
+ /*the parent import rule, if any.*/
+ CRStatement *parent_import_rule ;
+
+ /**custom data used by libcroco*/
+ gpointer croco_data ;
+
+ /**
+ *custom application data pointer
+ *Can be used by applications.
+ */
+ gpointer app_data ;
+
+ /**
+ *the reference count of this insance
+ *Please, don't never ever modify it
+ *directly. Use cr_stylesheet_ref()
+ *and cr_stylesheet_unref() instead.
+ */
+ gulong ref_count ;
+
+ /**
+ * A link to the next stylesheet.
+ */
+ CRStyleSheet *next;
+
+ /**
+ * A link to the previous stylesheet.
+ */
+ CRStyleSheet *prev;
+} ;
+
+CRStyleSheet * cr_stylesheet_new (CRStatement *a_stmts) ;
+
+gchar * cr_stylesheet_to_string (CRStyleSheet const *a_this) ;
+
+void cr_stylesheet_dump (CRStyleSheet const *a_this, FILE *a_fp) ;
+
+gint cr_stylesheet_nr_rules (CRStyleSheet const *a_this) ;
+
+CRStatement * cr_stylesheet_statement_get_from_list (CRStyleSheet *a_this, int itemnr) ;
+
+CRStyleSheet * cr_stylesheet_append_stylesheet (CRStyleSheet *a_this, CRStyleSheet *a_new_stylesheet) ;
+
+CRStyleSheet * cr_stylesheet_unlink (CRStyleSheet *a_this) ;
+
+void cr_stylesheet_ref (CRStyleSheet *a_this) ;
+
+gboolean cr_stylesheet_unref (CRStyleSheet *a_this) ;
+
+void cr_stylesheet_destroy (CRStyleSheet *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_STYLESHEET_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-term.c b/src/3rdparty/libcroco/src/cr-term.c
new file mode 100644
index 0000000..e370103
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-term.c
@@ -0,0 +1,744 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "cr-term.h"
+#include "cr-num.h"
+#include "cr-parser.h"
+
+/**
+ * Adds a quoted string onto the end of a GString, expanding it if necessary.
+ * Uses either single or double quotes.
+ *
+ * @pre val is not NULL and is null-terminated. Note that this is true for all
+ * GString::str values.
+ */
+static void
+_string_append_quoted (GString *string, const gchar *val)
+{
+ gchar quote = '\'';
+
+ if (!val) {
+ g_assert_not_reached ();
+ val = "";
+ }
+
+ if (strchr (val, '\'') && !strchr (val, '"')) {
+ quote = '"';
+ }
+
+ g_string_append_c (string, quote);
+
+ for (; *val; ++val) {
+ if (*val == quote || *val == '\\') {
+ g_string_append_c (string, '\\');
+ }
+ g_string_append_c (string, *val);
+ }
+
+ g_string_append_c (string, quote);
+}
+
+/**
+ *@file
+ *Definition of the #CRTem class.
+ */
+
+static void
+cr_term_clear (CRTerm * a_this)
+{
+ g_return_if_fail (a_this);
+
+ switch (a_this->type) {
+ case TERM_NUMBER:
+ if (a_this->content.num) {
+ cr_num_destroy (a_this->content.num);
+ a_this->content.num = NULL;
+ }
+ break;
+
+ case TERM_FUNCTION:
+ if (a_this->ext_content.func_param) {
+ cr_term_destroy (a_this->ext_content.func_param);
+ a_this->ext_content.func_param = NULL;
+ }
+ // fall through
+ case TERM_STRING:
+ case TERM_IDENT:
+ case TERM_URI:
+ case TERM_HASH:
+ if (a_this->content.str) {
+ cr_string_destroy (a_this->content.str);
+ a_this->content.str = NULL;
+ }
+ break;
+
+ case TERM_RGB:
+ if (a_this->content.rgb) {
+ cr_rgb_destroy (a_this->content.rgb);
+ a_this->content.rgb = NULL;
+ }
+ break;
+
+ case TERM_UNICODERANGE:
+ case TERM_NO_TYPE:
+ default:
+ break;
+ }
+
+ a_this->type = TERM_NO_TYPE;
+ a_this->n = FALSE;
+}
+
+/**
+ *Instantiate a #CRTerm.
+ *@return the newly build instance
+ *of #CRTerm.
+ */
+CRTerm *
+cr_term_new (void)
+{
+ CRTerm *result = NULL;
+
+ result = (CRTerm *) g_try_malloc (sizeof (CRTerm));
+ if (!result) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+ memset (result, 0, sizeof (CRTerm));
+ return result;
+}
+
+/**
+ *Parses an expression as defined by the css2 spec
+ *and builds the expression as a list of terms.
+ *@param a_buf the buffer to parse.
+ *@return a pointer to the first term of the expression or
+ *NULL if parsing failed.
+ */
+CRTerm *
+cr_term_parse_expression_from_buf (const guchar * a_buf,
+ enum CREncoding a_encoding)
+{
+ CRParser *parser = NULL;
+ CRTerm *result = NULL;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_buf, NULL);
+
+ parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
+ a_encoding, FALSE);
+ g_return_val_if_fail (parser, NULL);
+
+ status = cr_parser_try_to_skip_spaces_and_comments (parser);
+ if (status != CR_OK) {
+ goto cleanup;
+ }
+ status = cr_parser_parse_expr (parser, &result);
+ if (status != CR_OK) {
+ if (result) {
+ cr_term_destroy (result);
+ result = NULL;
+ }
+ }
+
+ cleanup:
+ if (parser) {
+ cr_parser_destroy (parser);
+ parser = NULL;
+ }
+
+ return result;
+}
+
+enum CRStatus
+cr_term_set_number (CRTerm * a_this, CRNum * a_num)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_term_clear (a_this);
+
+ a_this->type = TERM_NUMBER;
+ a_this->content.num = a_num;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_term_set_function (CRTerm * a_this, CRString * a_func_name,
+ CRTerm * a_func_param)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_term_clear (a_this);
+
+ a_this->type = TERM_FUNCTION;
+ a_this->content.str = a_func_name;
+ a_this->ext_content.func_param = a_func_param;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_term_set_string (CRTerm * a_this, CRString * a_str)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_term_clear (a_this);
+
+ a_this->type = TERM_STRING;
+ a_this->content.str = a_str;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_term_set_ident (CRTerm * a_this, CRString * a_str)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_term_clear (a_this);
+
+ a_this->type = TERM_IDENT;
+ a_this->content.str = a_str;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_term_set_uri (CRTerm * a_this, CRString * a_str)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_term_clear (a_this);
+
+ a_this->type = TERM_URI;
+ a_this->content.str = a_str;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_term_set_rgb (CRTerm * a_this, CRRgb * a_rgb)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_term_clear (a_this);
+
+ a_this->type = TERM_RGB;
+ a_this->content.rgb = a_rgb;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_term_set_hash (CRTerm * a_this, CRString * a_str)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_term_clear (a_this);
+
+ a_this->type = TERM_HASH;
+ a_this->content.str = a_str;
+ return CR_OK;
+}
+
+/**
+ *Appends a new term to the current list of #CRTerm.
+ *
+ *@param a_this the "this pointer" of the current instance
+ *of #CRTerm .
+ *@param a_new_term the term to append.
+ *@return the list of terms with the a_new_term appended to it.
+ */
+CRTerm *
+cr_term_append_term (CRTerm * a_this, CRTerm * a_new_term)
+{
+ CRTerm *cur = NULL;
+
+ g_return_val_if_fail (a_new_term, NULL);
+
+ if (a_this == NULL)
+ return a_new_term;
+
+ for (cur = a_this; cur->next; cur = cur->next) ;
+
+ cur->next = a_new_term;
+ a_new_term->prev = cur;
+
+ return a_this;
+}
+
+/**
+ *Prepends a term to the list of terms represented by a_this.
+ *
+ *@param a_this the "this pointer" of the current instance of
+ *#CRTerm .
+ *@param a_new_term the term to prepend.
+ *@return the head of the new list.
+ */
+CRTerm *
+cr_term_prepend_term (CRTerm * a_this, CRTerm * a_new_term)
+{
+ g_return_val_if_fail (a_this && a_new_term, NULL);
+
+ a_new_term->next = a_this;
+ a_this->prev = a_new_term;
+
+ return a_new_term;
+}
+
+/**
+ *Serializes the expression represented by
+ *the chained instances of #CRterm.
+ *@param a_this the current instance of #CRTerm
+ *@return the zero terminated string containing the serialized
+ *form of #CRTerm. MUST BE FREED BY THE CALLER using g_free().
+ */
+guchar *
+cr_term_to_string (CRTerm const * a_this)
+{
+ GString *str_buf = NULL;
+ CRTerm const *cur = NULL;
+ guchar *result = NULL,
+ *content = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ str_buf = g_string_new (NULL);
+ g_return_val_if_fail (str_buf, NULL);
+
+ for (cur = a_this; cur; cur = cur->next) {
+ if ((cur->content.str == NULL)
+ && (cur->content.num == NULL)
+ && (cur->content.str == NULL)
+ && (cur->content.rgb == NULL))
+ continue;
+
+ switch (cur->the_operator) {
+ case DIVIDE:
+ g_string_append (str_buf, " / ");
+ break;
+
+ case COMMA:
+ g_string_append (str_buf, ", ");
+ break;
+
+ case NO_OP:
+ if (cur->prev) {
+ g_string_append (str_buf, " ");
+ }
+ break;
+ default:
+
+ break;
+ }
+
+ switch (cur->unary_op) {
+ case PLUS_UOP:
+ g_string_append (str_buf, "+");
+ break;
+
+ case MINUS_UOP:
+ g_string_append (str_buf, "-");
+ break;
+
+ default:
+ break;
+ }
+
+ switch (cur->type) {
+ case TERM_NUMBER:
+ if (cur->content.num) {
+ content = cr_num_to_string (cur->content.num);
+ }
+
+ if (content) {
+ g_string_append (str_buf, (const gchar *) content);
+ g_free (content);
+ content = NULL;
+ }
+
+ break;
+
+ case TERM_FUNCTION:
+ if (cur->content.str) {
+ g_string_append_printf (str_buf, "%s(",
+ cur->content.str->stryng->str);
+
+ if (cur->ext_content.func_param) {
+ guchar *tmp_str = NULL;
+
+ tmp_str = cr_term_to_string
+ (cur->
+ ext_content.func_param);
+
+ if (tmp_str) {
+ g_string_append (str_buf,
+ (const gchar *) tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ }
+ g_string_append (str_buf, ")");
+ }
+
+ break;
+
+ case TERM_STRING:
+ if (cur->content.str) {
+ _string_append_quoted (str_buf,
+ cur->content.str->stryng->str);
+ }
+ break;
+
+ case TERM_IDENT:
+ if (cur->content.str && cur->content.str->stryng->str) {
+ g_string_append (str_buf, cur->content.str->stryng->str);
+ }
+ break;
+
+ case TERM_URI:
+ if (cur->content.str) {
+ g_string_append_printf
+ (str_buf, "url(%s)", cur->content.str->stryng->str);
+ }
+ break;
+
+ case TERM_RGB:
+ if (cur->content.rgb) {
+ guchar *tmp_str = NULL;
+
+ g_string_append (str_buf, "rgb(");
+ tmp_str = cr_rgb_to_string (cur->content.rgb);
+
+ if (tmp_str) {
+ g_string_append (str_buf, (const gchar *) tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ g_string_append (str_buf, ")");
+ }
+
+ break;
+
+ case TERM_UNICODERANGE:
+ g_string_append
+ (str_buf,
+ "?found unicoderange: dump not supported yet?");
+ break;
+
+ case TERM_HASH:
+ if (cur->content.str) {
+ g_string_append_printf (str_buf,
+ "#%s", cur->content.str->stryng->str);
+ }
+ break;
+
+ default:
+ g_string_append (str_buf,
+ "Unrecognized Term type");
+ break;
+ }
+ }
+
+ if (str_buf) {
+ result =(guchar *) str_buf->str;
+ g_string_free (str_buf, FALSE);
+ str_buf = NULL;
+ }
+
+ return result;
+}
+
+guchar *
+cr_term_one_to_string (CRTerm const * a_this)
+{
+ GString *str_buf = NULL;
+ guchar *result = NULL,
+ *content = NULL;
+
+ g_return_val_if_fail (a_this, NULL);
+
+ str_buf = g_string_new (NULL);
+ g_return_val_if_fail (str_buf, NULL);
+
+ if ((a_this->content.str == NULL)
+ && (a_this->content.num == NULL)
+ && (a_this->content.str == NULL)
+ && (a_this->content.rgb == NULL))
+ return NULL ;
+
+ switch (a_this->the_operator) {
+ case DIVIDE:
+ g_string_append_printf (str_buf, " / ");
+ break;
+
+ case COMMA:
+ g_string_append_printf (str_buf, ", ");
+ break;
+
+ case NO_OP:
+ if (a_this->prev) {
+ g_string_append_printf (str_buf, " ");
+ }
+ break;
+ default:
+
+ break;
+ }
+
+ switch (a_this->unary_op) {
+ case PLUS_UOP:
+ g_string_append_printf (str_buf, "+");
+ break;
+
+ case MINUS_UOP:
+ g_string_append_printf (str_buf, "-");
+ break;
+
+ default:
+ break;
+ }
+
+ switch (a_this->type) {
+ case TERM_NUMBER:
+ if (a_this->content.num) {
+ content = cr_num_to_string (a_this->content.num);
+ }
+
+ if (content) {
+ g_string_append (str_buf, (const gchar *) content);
+ g_free (content);
+ content = NULL;
+ }
+
+ break;
+
+ case TERM_FUNCTION:
+ if (a_this->content.str) {
+ g_string_append_printf (str_buf, "%s(",
+ a_this->content.str->stryng->str);
+
+ if (a_this->ext_content.func_param) {
+ guchar *tmp_str = NULL;
+
+ tmp_str = cr_term_to_string
+ (a_this->
+ ext_content.func_param);
+
+ if (tmp_str) {
+ g_string_append_printf
+ (str_buf,
+ "%s", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+
+ g_string_append_printf (str_buf, ")");
+ }
+ }
+
+ break;
+
+ case TERM_STRING:
+ if (a_this->content.str) {
+ _string_append_quoted (str_buf,
+ a_this->content.str->stryng->str);
+ }
+ break;
+
+ case TERM_IDENT:
+ if (a_this->content.str && a_this->content.str->stryng->str) {
+ g_string_append (str_buf, a_this->content.str->stryng->str);
+ }
+ break;
+
+ case TERM_URI:
+ if (a_this->content.str) {
+ g_string_append_printf
+ (str_buf, "url(%s)", a_this->content.str->stryng->str);
+ }
+ break;
+
+ case TERM_RGB:
+ if (a_this->content.rgb) {
+ guchar *tmp_str = NULL;
+
+ g_string_append_printf (str_buf, "rgb(");
+ tmp_str = cr_rgb_to_string (a_this->content.rgb);
+
+ if (tmp_str) {
+ g_string_append (str_buf, (const gchar *) tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ g_string_append_printf (str_buf, ")");
+ }
+
+ break;
+
+ case TERM_UNICODERANGE:
+ g_string_append_printf
+ (str_buf,
+ "?found unicoderange: dump not supported yet?");
+ break;
+
+ case TERM_HASH:
+ if (a_this->content.str) {
+ g_string_append_printf (str_buf,
+ "#%s", a_this->content.str->stryng->str);
+ }
+ break;
+
+ default:
+ g_string_append_printf (str_buf,
+ "%s",
+ "Unrecognized Term type");
+ break;
+ }
+
+ if (str_buf) {
+ result = (guchar *) str_buf->str;
+ g_string_free (str_buf, FALSE);
+ str_buf = NULL;
+ }
+
+ return result;
+}
+
+/**
+ *Dumps the expression (a list of terms connected by operators)
+ *to a file.
+ *TODO: finish the dump. The dump of some type of terms have not yet been
+ *implemented.
+ *@param a_this the current instance of #CRTerm.
+ *@param a_fp the destination file pointer.
+ */
+void
+cr_term_dump (CRTerm const * a_this, FILE * a_fp)
+{
+ guchar *content = NULL;
+
+ g_return_if_fail (a_this);
+
+ content = cr_term_to_string (a_this);
+
+ if (content) {
+ fprintf (a_fp, "%s", content);
+ g_free (content);
+ }
+}
+
+/**
+ *Return the number of terms in the expression.
+ *@param a_this the current instance of #CRTerm.
+ *@return number of terms in the expression.
+ */
+int
+cr_term_nr_values (CRTerm const *a_this)
+{
+ CRTerm const *cur = NULL ;
+ int nr = 0;
+
+ g_return_val_if_fail (a_this, -1) ;
+
+ for (cur = a_this ; cur ; cur = cur->next)
+ nr ++;
+ return nr;
+}
+
+/**
+ *Use an index to get a CRTerm from the expression.
+ *@param a_this the current instance of #CRTerm.
+ *@param itemnr the index into the expression.
+ *@return CRTerm at position itemnr, if itemnr > number of terms - 1,
+ *it will return NULL.
+ */
+CRTerm *
+cr_term_get_from_list (CRTerm *a_this, int itemnr)
+{
+ CRTerm *cur = NULL ;
+ int nr = 0;
+
+ g_return_val_if_fail (a_this, NULL) ;
+
+ for (cur = a_this ; cur ; cur = cur->next)
+ if (nr++ == itemnr)
+ return cur;
+ return NULL;
+}
+
+/**
+ *Increments the reference counter of the current instance
+ *of #CRTerm.*
+ *@param a_this the current instance of #CRTerm.
+ */
+void
+cr_term_ref (CRTerm * a_this)
+{
+ g_return_if_fail (a_this);
+
+ a_this->ref_count++;
+}
+
+/**
+ *Decrements the ref count of the current instance of
+ *#CRTerm. If the ref count reaches zero, the instance is
+ *destroyed.
+ *@param a_this the current instance of #CRTerm.
+ *@return TRUE if the current instance has been destroyed, FALSE otherwise.
+ */
+gboolean
+cr_term_unref (CRTerm * a_this)
+{
+ g_return_val_if_fail (a_this, FALSE);
+
+ if (a_this->ref_count) {
+ a_this->ref_count--;
+ }
+
+ if (a_this->ref_count == 0) {
+ cr_term_destroy (a_this);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ *The destructor of the #CRTerm class.
+ *@param a_this the "this pointer" of the current instance
+ *of #CRTerm.
+ */
+void
+cr_term_destroy (CRTerm * const a_this)
+{
+ g_return_if_fail (a_this);
+
+ cr_term_clear (a_this);
+
+ if (a_this->next) {
+ cr_term_destroy (a_this->next);
+ a_this->next = NULL;
+ }
+
+ g_free (a_this);
+}
+
+// vi:sw=8:ts=8
diff --git a/src/3rdparty/libcroco/src/cr-term.h b/src/3rdparty/libcroco/src/cr-term.h
new file mode 100644
index 0000000..39b9c6a
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-term.h
@@ -0,0 +1,195 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include <stdio.h>
+#include <glib.h>
+#include "cr-utils.h"
+#include "cr-rgb.h"
+#include "cr-num.h"
+#include "cr-string.h"
+
+#ifndef __CR_TERM_H__
+#define __CR_TERM_H__
+
+G_BEGIN_DECLS
+
+/**
+ *@file
+ *Declaration of the #CRTerm class.
+ */
+
+enum CRTermType
+{
+ TERM_NO_TYPE = 0,
+ TERM_NUMBER,
+ TERM_FUNCTION,
+ TERM_STRING,
+ TERM_IDENT,
+ TERM_URI,
+ TERM_RGB,
+ TERM_UNICODERANGE,
+ TERM_HASH
+} ;
+
+
+enum UnaryOperator
+{
+ NO_UNARY_UOP = 0,
+ PLUS_UOP,
+ MINUS_UOP,
+ EMPTY_UNARY_UOP
+} ;
+
+enum Operator
+{
+ NO_OP = 0,
+ DIVIDE,
+ COMMA
+} ;
+
+struct _CRTerm ;
+typedef struct _CRTerm CRTerm ;
+
+/**
+ *An abstraction of a css2 term as
+ *defined in the CSS2 spec in appendix D.1:
+ *term ::=
+ *[ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S*
+ *| ANGLE S* | TIME S* | FREQ S* | function ]
+ * | STRING S* | IDENT S* | URI S* | RGB S*
+ *| UNICODERANGE S* | hexcolor
+ */
+struct _CRTerm
+{
+ /**
+ *The type of the term.
+ */
+ enum CRTermType type ;
+
+ /**
+ *The unary operator associated to
+ *the current term.
+ */
+ enum UnaryOperator unary_op ;
+
+ /**
+ *The operator associated to the current term.
+ */
+ enum Operator the_operator ;
+
+
+ /**
+ *The content of the term.
+ *Depending of the type of the term,
+ *this holds either a number, a percentage ...
+ */
+ union
+ {
+ CRNum *num ;
+ CRString * str ;
+ CRRgb * rgb ;
+ } content ;
+
+ /**
+ *If the term is of type UNICODERANGE,
+ *this field holds the upper bound of the range.
+ *if the term is of type FUNCTION, this holds
+ *an instance of CRTerm that represents
+ * the expression which is the argument of the function.
+ */
+ union
+ {
+ CRTerm *func_param ;
+ } ext_content ;
+
+ /**
+ *A flag to indicate if there is an n as in the nth child expression 'an+b'.
+ */
+ gboolean n;
+
+ /**
+ *A spare pointer, just in case.
+ *Can be used by the application.
+ */
+ gpointer app_data ;
+
+ glong ref_count ;
+
+ /**
+ *A pointer to the next term,
+ *just in case this term is part of
+ *an expression.
+ */
+ CRTerm *next ;
+
+ /**
+ *A pointer to the previous
+ *term.
+ */
+ CRTerm *prev ;
+ CRParsingLocation location ;
+} ;
+
+CRTerm * cr_term_parse_expression_from_buf (const guchar *a_buf,
+ enum CREncoding a_encoding) ;
+CRTerm * cr_term_new (void) ;
+
+enum CRStatus cr_term_set_number (CRTerm *a_this, CRNum *a_num) ;
+
+enum CRStatus cr_term_set_function (CRTerm *a_this,
+ CRString *a_func_name,
+ CRTerm *a_func_param) ;
+
+enum CRStatus cr_term_set_string (CRTerm *a_this, CRString *a_str) ;
+
+enum CRStatus cr_term_set_ident (CRTerm *a_this, CRString *a_str) ;
+
+enum CRStatus cr_term_set_uri (CRTerm *a_this, CRString *a_str) ;
+
+enum CRStatus cr_term_set_rgb (CRTerm *a_this, CRRgb *a_rgb) ;
+
+enum CRStatus cr_term_set_hash (CRTerm *a_this, CRString *a_str) ;
+
+CRTerm * cr_term_append_term (CRTerm *a_this, CRTerm *a_new_term) ;
+
+CRTerm * cr_term_prepend_term (CRTerm *a_this, CRTerm *a_new_term) ;
+
+guchar * cr_term_to_string (CRTerm const *a_this) ;
+
+guchar * cr_term_one_to_string (CRTerm const * a_this) ;
+
+void cr_term_dump (CRTerm const *a_this, FILE *a_fp) ;
+
+int cr_term_nr_values (CRTerm const *a_this) ;
+
+CRTerm * cr_term_get_from_list (CRTerm *a_this, int itemnr) ;
+
+void cr_term_ref (CRTerm *a_this) ;
+
+gboolean cr_term_unref (CRTerm *a_this) ;
+
+void cr_term_destroy (CRTerm * a_term) ;
+
+G_END_DECLS
+
+#endif /*__CR_TERM_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-tknzr.c b/src/3rdparty/libcroco/src/cr-tknzr.c
new file mode 100644
index 0000000..821f89a
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-tknzr.c
@@ -0,0 +1,2777 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See the COPYRIGHTS file for copyrights information.
+ */
+
+/**
+ *@file
+ *The definition of the #CRTknzr (tokenizer)
+ *class.
+ */
+
+#include "string.h"
+#include "math.h"
+#include "cr-tknzr.h"
+#include "cr-doc-handler.h"
+
+struct _CRTknzrPriv {
+ /**The parser input stream of bytes*/
+ CRInput *input;
+
+ /**
+ *A cache where tknzr_unget_token()
+ *puts back the token. tknzr_get_next_token()
+ *first look in this cache, and if and
+ *only if it's empty, fetches the next token
+ *from the input stream.
+ */
+ CRToken *token_cache;
+
+ /**
+ *The position of the end of the previous token
+ *or char fetched.
+ */
+ CRInputPos prev_pos;
+
+ CRDocHandler *sac_handler;
+
+ /**
+ *The reference count of the current instance
+ *of #CRTknzr. Is manipulated by cr_tknzr_ref()
+ *and cr_tknzr_unref().
+ */
+ glong ref_count;
+};
+
+#define PRIVATE(obj) ((obj)->priv)
+
+/**
+ *return TRUE if the character is a number ([0-9]), FALSE otherwise
+ *@param a_char the char to test.
+ */
+#define IS_NUM(a_char) (((a_char) >= '0' && (a_char) <= '9')?TRUE:FALSE)
+
+/**
+ *Checks if 'status' equals CR_OK. If not, goto the 'error' label.
+ *
+ *@param status the status (of type enum CRStatus) to test.
+ *@param is_exception if set to FALSE, the final status returned the
+ *current function will be CR_PARSING_ERROR. If set to TRUE, the
+ *current status will be the current value of the 'status' variable.
+ *
+ */
+#define CHECK_PARSING_STATUS(status, is_exception) \
+if ((status) != CR_OK) \
+{ \
+ if (is_exception == FALSE) \
+ { \
+ status = CR_PARSING_ERROR ; \
+ } \
+ goto error ; \
+}
+
+/**
+ *Peeks the next char from the input stream of the current tokenizer.
+ *invokes CHECK_PARSING_STATUS on the status returned by
+ *cr_tknzr_input_peek_char().
+ *
+ *@param the current instance of #CRTkzr.
+ *@param to_char a pointer to the char where to store the
+ *char peeked.
+ */
+#define PEEK_NEXT_CHAR(a_tknzr, a_to_char) \
+{\
+status = cr_tknzr_peek_char (a_tknzr, a_to_char) ; \
+CHECK_PARSING_STATUS (status, TRUE) \
+}
+
+/**
+ *Reads the next char from the input stream of the current parser.
+ *In case of error, jumps to the "error:" label located in the
+ *function where this macro is called.
+ *@param parser the current instance of #CRTknzr
+ *@param to_char a pointer to the guint32 char where to store
+ *the character read.
+ */
+#define READ_NEXT_CHAR(a_tknzr, to_char) \
+status = cr_tknzr_read_char (a_tknzr, to_char) ;\
+CHECK_PARSING_STATUS (status, TRUE)
+
+/**
+ *Gets information about the current position in
+ *the input of the parser.
+ *In case of failure, this macro returns from the
+ *calling function and
+ *returns a status code of type enum #CRStatus.
+ *@param parser the current instance of #CRTknzr.
+ *@param pos out parameter. A pointer to the position
+ *inside the current parser input. Must
+ */
+#define RECORD_INITIAL_POS(a_tknzr, a_pos) \
+status = cr_input_get_cur_pos (PRIVATE \
+(a_tknzr)->input, a_pos) ; \
+g_return_val_if_fail (status == CR_OK, status)
+
+/**
+ *Gets the address of the current byte inside the
+ *parser input.
+ *@param parser the current instance of #CRTknzr.
+ *@param addr out parameter a pointer (guchar*)
+ *to where the address must be put.
+ */
+#define RECORD_CUR_BYTE_ADDR(a_tknzr, a_addr) \
+status = cr_input_get_cur_byte_addr \
+ (PRIVATE (a_tknzr)->input, a_addr) ; \
+CHECK_PARSING_STATUS (status, TRUE)
+
+/**
+ *Peeks a byte from the topmost parser input at
+ *a given offset from the current position.
+ *If it fails, goto the "error:" label.
+ *
+ *@param a_parser the current instance of #CRTknzr.
+ *@param a_offset the offset of the byte to peek, the
+ *current byte having the offset '0'.
+ *@param a_byte_ptr out parameter a pointer (guchar*) to
+ *where the peeked char is to be stored.
+ */
+#define PEEK_BYTE(a_tknzr, a_offset, a_byte_ptr) \
+status = cr_tknzr_peek_byte (a_tknzr, \
+ a_offset, \
+ a_byte_ptr) ; \
+CHECK_PARSING_STATUS (status, TRUE) ;
+
+#define BYTE(a_input, a_n, a_eof) \
+cr_input_peek_byte2 (a_input, a_n, a_eof)
+
+/**
+ *Reads a byte from the topmost parser input
+ *steam.
+ *If it fails, goto the "error" label.
+ *@param a_parser the current instance of #CRTknzr.
+ *@param a_byte_ptr the guchar * where to put the read char.
+ */
+#define READ_NEXT_BYTE(a_tknzr, a_byte_ptr) \
+status = \
+cr_input_read_byte (PRIVATE (a_tknzr)->input, a_byte_ptr) ;\
+CHECK_PARSING_STATUS (status, TRUE) ;
+
+/**
+ *Skips a given number of byte in the topmost
+ *parser input. Don't update line and column number.
+ *In case of error, jumps to the "error:" label
+ *of the surrounding function.
+ *@param a_parser the current instance of #CRTknzr.
+ *@param a_nb_bytes the number of bytes to skip.
+ */
+#define SKIP_BYTES(a_tknzr, a_nb_bytes) \
+status = cr_input_seek_index (PRIVATE (a_tknzr)->input, \
+ CR_SEEK_CUR, a_nb_bytes) ; \
+CHECK_PARSING_STATUS (status, TRUE) ;
+
+/**
+ *Skip utf8 encoded characters.
+ *Updates line and column numbers.
+ *@param a_parser the current instance of #CRTknzr.
+ *@param a_nb_chars the number of chars to skip. Must be of
+ *type glong.
+ */
+#define SKIP_CHARS(a_tknzr, a_nb_chars) \
+{ \
+gulong nb_chars = a_nb_chars ; \
+status = cr_input_consume_chars \
+ (PRIVATE (a_tknzr)->input,0, &nb_chars) ; \
+CHECK_PARSING_STATUS (status, TRUE) ; \
+}
+
+/**
+ *Tests the condition and if it is false, sets
+ *status to "CR_PARSING_ERROR" and goto the 'error'
+ *label.
+ *@param condition the condition to test.
+ */
+#define ENSURE_PARSING_COND(condition) \
+if (! (condition)) {status = CR_PARSING_ERROR; goto error ;}
+
+static enum CRStatus cr_tknzr_parse_nl (CRTknzr * a_this,
+ guchar ** a_start,
+ guchar ** a_end,
+ CRParsingLocation *a_location);
+
+static enum CRStatus cr_tknzr_parse_w (CRTknzr * a_this,
+ guchar ** a_start,
+ guchar ** a_end,
+ CRParsingLocation *a_location) ;
+
+static enum CRStatus cr_tknzr_parse_unicode_escape (CRTknzr * a_this,
+ guint32 * a_unicode,
+ CRParsingLocation *a_location) ;
+
+static enum CRStatus cr_tknzr_parse_escape (CRTknzr * a_this,
+ guint32 * a_esc_code,
+ CRParsingLocation *a_location);
+
+static enum CRStatus cr_tknzr_parse_string (CRTknzr * a_this,
+ CRString ** a_str);
+
+static enum CRStatus cr_tknzr_parse_comment (CRTknzr * a_this,
+ CRString ** a_comment);
+
+static enum CRStatus cr_tknzr_parse_nmstart (CRTknzr * a_this,
+ guint32 * a_char,
+ CRParsingLocation *a_location);
+
+static enum CRStatus cr_tknzr_parse_num (CRTknzr * a_this,
+ CRNum ** a_num);
+
+/**********************************
+ *PRIVATE methods
+ **********************************/
+
+/**
+ *Parses a "w" as defined by the css spec at [4.1.1]:
+ * w ::= [ \t\r\n\f]*
+ *
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_start out param. Upon successful completion, points
+ *to the beginning of the parsed white space, points to NULL otherwise.
+ *Can also point to NULL is there is no white space actually.
+ *@param a_end out param. Upon successful completion, points
+ *to the end of the parsed white space, points to NULL otherwise.
+ *Can also point to NULL is there is no white space actually.
+ */
+static enum CRStatus
+cr_tknzr_parse_w (CRTknzr * a_this,
+ guchar ** a_start,
+ guchar ** a_end,
+ CRParsingLocation *a_location)
+{
+ guint32 cur_char = 0;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_start && a_end,
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ *a_start = NULL;
+ *a_end = NULL;
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ if (cr_utils_is_white_space (cur_char) == FALSE) {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ if (a_location) {
+ cr_tknzr_get_parsing_location (a_this,
+ a_location) ;
+ }
+ RECORD_CUR_BYTE_ADDR (a_this, a_start);
+ *a_end = *a_start;
+
+ for (;;) {
+ gboolean is_eof = FALSE;
+
+ cr_input_get_end_of_file (PRIVATE (a_this)->input, &is_eof);
+ if (is_eof)
+ break;
+
+ status = cr_tknzr_peek_char (a_this, &cur_char);
+ if (status == CR_END_OF_INPUT_ERROR) {
+ status = CR_OK;
+ break;
+ } else if (status != CR_OK) {
+ goto error;
+ }
+
+ if (cr_utils_is_white_space (cur_char) == TRUE) {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ RECORD_CUR_BYTE_ADDR (a_this, a_end);
+ } else {
+ break;
+ }
+ }
+
+ return CR_OK;
+
+ error:
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+
+ return status;
+}
+
+/**
+ *Parses a newline as defined in the css2 spec:
+ * nl ::= \n|\r\n|\r|\f
+ *
+ *@param a_this the "this pointer" of the current instance of #CRTknzr.
+ *@param a_start a pointer to the first character of the successfully
+ *parsed string.
+ *@param a_end a pointer to the last character of the successfully parsed
+ *string.
+ *@result CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_tknzr_parse_nl (CRTknzr * a_this,
+ guchar ** a_start,
+ guchar ** a_end,
+ CRParsingLocation *a_location)
+{
+ CRInputPos init_pos;
+ guchar next_chars[2] = { 0 };
+ enum CRStatus status = CR_PARSING_ERROR;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_start && a_end, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ PEEK_BYTE (a_this, 1, &next_chars[0]);
+ PEEK_BYTE (a_this, 2, &next_chars[1]);
+
+ if ((next_chars[0] == '\r' && next_chars[1] == '\n')) {
+ SKIP_BYTES (a_this, 1);
+ if (a_location) {
+ cr_tknzr_get_parsing_location
+ (a_this, a_location) ;
+ }
+ SKIP_CHARS (a_this, 1);
+
+ RECORD_CUR_BYTE_ADDR (a_this, a_end);
+
+ status = CR_OK;
+ } else if (next_chars[0] == '\n'
+ || next_chars[0] == '\r' || next_chars[0] == '\f') {
+ SKIP_CHARS (a_this, 1);
+ if (a_location) {
+ cr_tknzr_get_parsing_location
+ (a_this, a_location) ;
+ }
+ RECORD_CUR_BYTE_ADDR (a_this, a_start);
+ *a_end = *a_start;
+ status = CR_OK;
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ return CR_OK ;
+
+ error:
+ cr_tknzr_set_cur_pos (a_this, &init_pos) ;
+ return status;
+}
+
+/**
+ *Go ahead in the parser input, skipping all the spaces.
+ *If the next char if not a white space, this function does nothing.
+ *In any cases, it stops when it encounters a non white space character.
+ *
+ *@param a_this the current instance of #CRTknzr.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_tknzr_try_to_skip_spaces (CRTknzr * a_this)
+{
+ enum CRStatus status = CR_ERROR;
+ guint32 cur_char = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
+
+ status = cr_input_peek_char (PRIVATE (a_this)->input, &cur_char);
+
+ if (status != CR_OK) {
+ if (status == CR_END_OF_INPUT_ERROR)
+ return CR_OK;
+ return status;
+ }
+
+ if (cr_utils_is_white_space (cur_char) == TRUE) {
+ gulong nb_chars = -1; /*consume all spaces */
+
+ status = cr_input_consume_white_spaces
+ (PRIVATE (a_this)->input, &nb_chars);
+ }
+
+ return status;
+}
+
+/**
+ *Parses a "comment" as defined in the css spec at [4.1.1]:
+ *COMMENT ::= \/\*[^*]*\*+([^/][^*]*\*+)*\/ .
+ *This complex regexp is just to say that comments start
+ *with the two chars '/''*' and ends with the two chars '*''/'.
+ *It also means that comments cannot be nested.
+ *So based on that, I've just tried to implement the parsing function
+ *simply and in a straight forward manner.
+ */
+static enum CRStatus
+cr_tknzr_parse_comment (CRTknzr * a_this,
+ CRString ** a_comment)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+ guint32 cur_char = 0, next_char= 0;
+ CRString *comment = NULL;
+ CRParsingLocation loc = {0,0,0} ;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input,
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+ READ_NEXT_CHAR (a_this, &cur_char) ;
+ ENSURE_PARSING_COND (cur_char == '/');
+ cr_tknzr_get_parsing_location (a_this, &loc) ;
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+ ENSURE_PARSING_COND (cur_char == '*');
+ comment = cr_string_new ();
+ for (;;) { /* [^*]* */
+ PEEK_NEXT_CHAR (a_this, &next_char);
+ if (next_char == '*')
+ break;
+ READ_NEXT_CHAR (a_this, &cur_char);
+ g_string_append_unichar (comment->stryng, cur_char);
+ }
+ /* Stop condition: next_char == '*' */
+ for (;;) { /* \*+ */
+ READ_NEXT_CHAR(a_this, &cur_char);
+ ENSURE_PARSING_COND (cur_char == '*');
+ g_string_append_unichar (comment->stryng, cur_char);
+ PEEK_NEXT_CHAR (a_this, &next_char);
+ if (next_char != '*')
+ break;
+ }
+ /* Stop condition: next_char != '*' */
+ for (;;) { /* ([^/][^*]*\*+)* */
+ if (next_char == '/')
+ break;
+ READ_NEXT_CHAR(a_this, &cur_char);
+ g_string_append_unichar (comment->stryng, cur_char);
+ for (;;) { /* [^*]* */
+ PEEK_NEXT_CHAR (a_this, &next_char);
+ if (next_char == '*')
+ break;
+ READ_NEXT_CHAR (a_this, &cur_char);
+ g_string_append_unichar (comment->stryng, cur_char);
+ }
+ /* Stop condition: next_char = '*', no need to verify, because peek and read exit to error anyway */
+ for (;;) { /* \*+ */
+ READ_NEXT_CHAR(a_this, &cur_char);
+ ENSURE_PARSING_COND (cur_char == '*');
+ g_string_append_unichar (comment->stryng, cur_char);
+ PEEK_NEXT_CHAR (a_this, &next_char);
+ if (next_char != '*')
+ break;
+ }
+ /* Continue condition: next_char != '*' */
+ }
+ /* Stop condition: next_char == '\/' */
+ READ_NEXT_CHAR(a_this, &cur_char);
+ g_string_append_unichar (comment->stryng, cur_char);
+
+ if (status == CR_OK) {
+ cr_parsing_location_copy (&comment->location,
+ &loc) ;
+ *a_comment = comment;
+ return CR_OK;
+ }
+ error:
+
+ if (comment) {
+ cr_string_destroy (comment);
+ comment = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+
+ return status;
+}
+
+/**
+ *Parses an 'unicode' escape sequence defined
+ *in css spec at chap 4.1.1:
+ *unicode ::= \\[0-9a-f]{1,6}[ \n\r\t\f]?
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_start out parameter. A pointer to the start
+ *of the unicode escape sequence. Must *NOT* be deleted by
+ *the caller.
+ *@param a_end out parameter. A pointer to the last character
+ *of the unicode escape sequence. Must *NOT* be deleted by the caller.
+ *@return CR_OK if parsing succeeded, an error code otherwise.
+ *Error code can be either CR_PARSING_ERROR if the string
+ *parsed just doesn't
+ *respect the production or another error if a
+ *lower level error occurred.
+ */
+static enum CRStatus
+cr_tknzr_parse_unicode_escape (CRTknzr * a_this,
+ guint32 * a_unicode,
+ CRParsingLocation *a_location)
+{
+ guint32 cur_char;
+ CRInputPos init_pos;
+ glong occur = 0;
+ guint32 unicode = 0;
+ guchar *tmp_char_ptr1 = NULL,
+ *tmp_char_ptr2 = NULL;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_unicode, CR_BAD_PARAM_ERROR);
+
+ /*first, let's backup the current position pointer */
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ if (cur_char != '\\') {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ if (a_location) {
+ cr_tknzr_get_parsing_location
+ (a_this, a_location) ;
+ }
+ PEEK_NEXT_CHAR (a_this, &cur_char);
+
+ for (occur = 0, unicode = 0; ((cur_char >= '0' && cur_char <= '9')
+ || (cur_char >= 'a' && cur_char <= 'f')
+ || (cur_char >= 'A' && cur_char <= 'F'))
+ && occur < 6; occur++) {
+ gint cur_char_val = 0;
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ if ((cur_char >= '0' && cur_char <= '9')) {
+ cur_char_val = (cur_char - '0');
+ } else if ((cur_char >= 'a' && cur_char <= 'f')) {
+ cur_char_val = 10 + (cur_char - 'a');
+ } else if ((cur_char >= 'A' && cur_char <= 'F')) {
+ cur_char_val = 10 + (cur_char - 'A');
+ }
+
+ unicode = unicode * 16 + cur_char_val;
+
+ PEEK_NEXT_CHAR (a_this, &cur_char);
+ }
+
+ /* Eat a whitespace if possible. */
+ cr_tknzr_parse_w (a_this, &tmp_char_ptr1,
+ &tmp_char_ptr2, NULL);
+ *a_unicode = unicode;
+ return CR_OK;
+
+ error:
+ /*
+ *restore the initial position pointer backuped at
+ *the beginning of this function.
+ */
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+
+ return status;
+}
+
+/**
+ *parses an escape sequence as defined by the css spec:
+ *escape ::= {unicode}|\\[ -~\200-\4177777]
+ *@param a_this the current instance of #CRTknzr .
+ */
+static enum CRStatus
+cr_tknzr_parse_escape (CRTknzr * a_this, guint32 * a_esc_code,
+ CRParsingLocation *a_location)
+{
+ enum CRStatus status = CR_OK;
+ guint32 cur_char = 0;
+ CRInputPos init_pos;
+ guchar next_chars[2];
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_esc_code, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ PEEK_BYTE (a_this, 1, &next_chars[0]);
+ PEEK_BYTE (a_this, 2, &next_chars[1]);
+
+ if (next_chars[0] != '\\') {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+
+ if ((next_chars[1] >= '0' && next_chars[1] <= '9')
+ || (next_chars[1] >= 'a' && next_chars[1] <= 'f')
+ || (next_chars[1] >= 'A' && next_chars[1] <= 'F')) {
+ status = cr_tknzr_parse_unicode_escape (a_this, a_esc_code,
+ a_location);
+ } else {
+ /*consume the '\' char */
+ READ_NEXT_CHAR (a_this, &cur_char);
+ if (a_location) {
+ cr_tknzr_get_parsing_location (a_this,
+ a_location) ;
+ }
+ /*then read the char after the '\' */
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ if (cur_char != ' ' && (cur_char < 200 || cur_char > 4177777)) {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ *a_esc_code = cur_char;
+
+ }
+ if (status == CR_OK) {
+ return CR_OK;
+ }
+ error:
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+ return status;
+}
+
+/**
+ *Parses a string type as defined in css spec [4.1.1]:
+ *
+ *string ::= {string1}|{string2}
+ *string1 ::= \"([\t !#$%&(-~]|\\{nl}|\'|{nonascii}|{escape})*\"
+ *string2 ::= \'([\t !#$%&(-~]|\\{nl}|\"|{nonascii}|{escape})*\'
+ *
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_start out parameter. Upon successful completion,
+ *points to the beginning of the string, points to an undefined value
+ *otherwise.
+ *@param a_end out parameter. Upon successful completion, points to
+ *the beginning of the string, points to an undefined value otherwise.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_tknzr_parse_string (CRTknzr * a_this, CRString ** a_str)
+{
+ guint32 cur_char = 0,
+ delim = 0;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_OK;
+ CRString *str = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_str, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ if (cur_char == '"')
+ delim = '"';
+ else if (cur_char == '\'')
+ delim = '\'';
+ else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ str = cr_string_new ();
+ if (str) {
+ cr_tknzr_get_parsing_location
+ (a_this, &str->location) ;
+ }
+ for (;;) {
+ guchar next_chars[2] = { 0 };
+
+ PEEK_BYTE (a_this, 1, &next_chars[0]);
+
+ if (next_chars[0] == '\\') {
+ guchar *tmp_char_ptr1 = NULL,
+ *tmp_char_ptr2 = NULL;
+ guint32 esc_code = 0;
+
+ PEEK_BYTE (a_this, 2, &next_chars[1]);
+
+ if (next_chars[1] == '\'' || next_chars[1] == '"' || next_chars[1] == '\\') {
+ g_string_append_unichar (str->stryng,
+ next_chars[1]);
+ SKIP_BYTES (a_this, 2);
+ status = CR_OK;
+ } else {
+ status = cr_tknzr_parse_escape
+ (a_this, &esc_code, NULL);
+
+ if (status == CR_OK) {
+ g_string_append_unichar
+ (str->stryng,
+ esc_code);
+ }
+ }
+
+ if (status != CR_OK) {
+ /*
+ *consume the '\' char, and try to parse
+ *a newline.
+ */
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ status = cr_tknzr_parse_nl
+ (a_this, &tmp_char_ptr1,
+ &tmp_char_ptr2, NULL);
+ }
+
+ CHECK_PARSING_STATUS (status, FALSE);
+ } else if (next_chars[0] == delim) {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ break;
+ } else if (next_chars[0] == '\t'
+ || (next_chars[0] >= ' ' && next_chars[0] <= '~')) {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ g_string_append_unichar (str->stryng,
+ cur_char);
+ status = CR_OK;
+ }
+
+ else if (cr_utils_is_nonascii (next_chars[0])) {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ g_string_append_unichar (str->stryng, cur_char);
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ }
+
+ if (status == CR_OK) {
+ if (*a_str == NULL) {
+ *a_str = str;
+ str = NULL;
+ } else {
+ (*a_str)->stryng = g_string_append_len
+ ((*a_str)->stryng,
+ str->stryng->str,
+ str->stryng->len);
+ cr_string_destroy (str);
+ }
+ return CR_OK;
+ }
+
+ error:
+
+ if (str) {
+ cr_string_destroy (str) ;
+ str = NULL;
+ }
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+ return status;
+}
+
+/**
+ *Parses the an nmstart as defined by the css2 spec [4.1.1]:
+ * nmstart [a-zA-Z]|{nonascii}|{escape}
+ *
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_start out param. A pointer to the starting point of
+ *the token.
+ *@param a_end out param. A pointer to the ending point of the
+ *token.
+ *@param a_char out param. The actual parsed nmchar.
+ *@return CR_OK upon successful completion,
+ *an error code otherwise.
+ */
+static enum CRStatus
+cr_tknzr_parse_nmstart (CRTknzr * a_this,
+ guint32 * a_char,
+ CRParsingLocation *a_location)
+{
+ CRInputPos init_pos;
+ enum CRStatus status = CR_OK;
+ guint32 cur_char = 0,
+ next_char = 0;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_char, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ PEEK_NEXT_CHAR (a_this, &next_char);
+
+ if (next_char == '\\') {
+ status = cr_tknzr_parse_escape (a_this, a_char,
+ a_location);
+
+ if (status != CR_OK)
+ goto error;
+
+ } else if (cr_utils_is_nonascii (next_char) == TRUE
+ || ((next_char >= 'a') && (next_char <= 'z'))
+ || ((next_char >= 'A') && (next_char <= 'Z'))
+ ) {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ if (a_location) {
+ cr_tknzr_get_parsing_location (a_this,
+ a_location) ;
+ }
+ *a_char = cur_char;
+ status = CR_OK;
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+
+ return CR_OK;
+
+ error:
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+
+ return status;
+
+}
+
+/**
+ *Parses an nmchar as described in the css spec at
+ *chap 4.1.1:
+ *nmchar ::= [a-z0-9-]|{nonascii}|{escape}
+ *
+ *Humm, I have added the possibility for nmchar to
+ *contain upper case letters.
+ *
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_start out param. A pointer to the starting point of
+ *the token.
+ *@param a_end out param. A pointer to the ending point of the
+ *token.
+ *@param a_char out param. The actual parsed nmchar.
+ *@return CR_OK upon successful completion,
+ *an error code otherwise.
+ */
+static enum CRStatus
+cr_tknzr_parse_nmchar (CRTknzr * a_this, guint32 * a_char,
+ CRParsingLocation *a_location)
+{
+ guint32 cur_char = 0,
+ next_char = 0;
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this) && a_char,
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_input_peek_char (PRIVATE (a_this)->input,
+ &next_char) ;
+ if (status != CR_OK)
+ goto error;
+
+ if (next_char == '\\') {
+ status = cr_tknzr_parse_escape (a_this, a_char,
+ a_location);
+
+ if (status != CR_OK)
+ goto error;
+
+ } else if (cr_utils_is_nonascii (next_char) == TRUE
+ || ((next_char >= 'a') && (next_char <= 'z'))
+ || ((next_char >= 'A') && (next_char <= 'Z'))
+ || ((next_char >= '0') && (next_char <= '9'))
+ || (next_char == '-')
+ || (next_char == '_') /*'_' not allowed by the spec. */
+ ) {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ *a_char = cur_char;
+ status = CR_OK;
+ if (a_location) {
+ cr_tknzr_get_parsing_location
+ (a_this, a_location) ;
+ }
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ return CR_OK;
+
+ error:
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+ return status;
+}
+
+/**
+ *Parses an "ident" as defined in css spec [4.1.1]:
+ *ident ::= {nmstart}{nmchar}*
+ *
+ *Actually parses it using the css3 grammar:
+ *ident ::= -?{nmstart}{nmchar}*
+ *@param a_this the currens instance of #CRTknzr.
+ *
+ *@param a_str a pointer to parsed ident. If *a_str is NULL,
+ *this function allocates a new instance of CRString. If not,
+ *the function just appends the parsed string to the one passed.
+ *In both cases it is up to the caller to free *a_str.
+ *
+ *@return CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+static enum CRStatus
+cr_tknzr_parse_ident (CRTknzr * a_this, CRString ** a_str)
+{
+ guint32 tmp_char = 0;
+ CRString *stringue = NULL ;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_OK;
+ gboolean location_is_set = FALSE ;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_str, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+ PEEK_NEXT_CHAR (a_this, &tmp_char) ;
+ stringue = cr_string_new () ;
+ g_return_val_if_fail (stringue,
+ CR_OUT_OF_MEMORY_ERROR) ;
+
+ if (tmp_char == '-') {
+ READ_NEXT_CHAR (a_this, &tmp_char) ;
+ cr_tknzr_get_parsing_location
+ (a_this, &stringue->location) ;
+ location_is_set = TRUE ;
+ g_string_append_unichar (stringue->stryng,
+ tmp_char) ;
+ }
+ status = cr_tknzr_parse_nmstart (a_this, &tmp_char, NULL);
+ if (status != CR_OK) {
+ status = CR_PARSING_ERROR;
+ goto end ;
+ }
+ if (location_is_set == FALSE) {
+ cr_tknzr_get_parsing_location
+ (a_this, &stringue->location) ;
+ location_is_set = TRUE ;
+ }
+ g_string_append_unichar (stringue->stryng, tmp_char);
+ for (;;) {
+ status = cr_tknzr_parse_nmchar (a_this,
+ &tmp_char,
+ NULL);
+ if (status != CR_OK) {
+ status = CR_OK ;
+ break;
+ }
+ g_string_append_unichar (stringue->stryng, tmp_char);
+ }
+ if (status == CR_OK) {
+ if (!*a_str) {
+ *a_str = stringue ;
+
+ } else {
+ g_string_append_len ((*a_str)->stryng,
+ stringue->stryng->str,
+ stringue->stryng->len) ;
+ cr_string_destroy (stringue) ;
+ }
+ stringue = NULL ;
+ }
+
+ error:
+ end:
+ if (stringue) {
+ cr_string_destroy (stringue) ;
+ stringue = NULL ;
+ }
+ if (status != CR_OK ) {
+ cr_tknzr_set_cur_pos (a_this, &init_pos) ;
+ }
+ return status ;
+}
+
+
+/**
+ *Parses a "name" as defined by css spec [4.1.1]:
+ *name ::= {nmchar}+
+ *
+ *@param a_this the current instance of #CRTknzr.
+ *
+ *@param a_str out parameter. A pointer to the successfully parsed
+ *name. If *a_str is set to NULL, this function allocates a new instance
+ *of CRString. If not, it just appends the parsed name to the passed *a_str.
+ *In both cases, it is up to the caller to free *a_str.
+ *
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_tknzr_parse_name (CRTknzr * a_this,
+ CRString ** a_str)
+{
+ guint32 tmp_char = 0;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_OK;
+ gboolean str_needs_free = FALSE,
+ is_first_nmchar=TRUE ;
+ glong i = 0;
+ CRParsingLocation loc = {0,0,0} ;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_str,
+ CR_BAD_PARAM_ERROR) ;
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ if (*a_str == NULL) {
+ *a_str = cr_string_new ();
+ str_needs_free = TRUE;
+ }
+ for (i = 0;; i++) {
+ if (is_first_nmchar == TRUE) {
+ status = cr_tknzr_parse_nmchar
+ (a_this, &tmp_char,
+ &loc) ;
+ is_first_nmchar = FALSE ;
+ } else {
+ status = cr_tknzr_parse_nmchar
+ (a_this, &tmp_char, NULL) ;
+ }
+ if (status != CR_OK)
+ break;
+ g_string_append_unichar ((*a_str)->stryng,
+ tmp_char);
+ }
+ if (i > 0) {
+ cr_parsing_location_copy
+ (&(*a_str)->location, &loc) ;
+ return CR_OK;
+ }
+ if (str_needs_free == TRUE && *a_str) {
+ cr_string_destroy (*a_str);
+ *a_str = NULL;
+ }
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+ return CR_PARSING_ERROR;
+}
+
+/**
+ *Parses a "hash" as defined by the css spec in [4.1.1]:
+ *HASH ::= #{name}
+ */
+static enum CRStatus
+cr_tknzr_parse_hash (CRTknzr * a_this, CRString ** a_str)
+{
+ guint32 cur_char = 0;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_OK;
+ gboolean str_needs_free = FALSE;
+ CRParsingLocation loc = {0,0,0} ;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input,
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+ READ_NEXT_CHAR (a_this, &cur_char);
+ if (cur_char != '#') {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ if (*a_str == NULL) {
+ *a_str = cr_string_new ();
+ str_needs_free = TRUE;
+ }
+ cr_tknzr_get_parsing_location (a_this,
+ &loc) ;
+ status = cr_tknzr_parse_name (a_this, a_str);
+ cr_parsing_location_copy (&(*a_str)->location, &loc) ;
+ if (status != CR_OK) {
+ goto error;
+ }
+ return CR_OK;
+
+ error:
+ if (str_needs_free == TRUE && *a_str) {
+ cr_string_destroy (*a_str);
+ *a_str = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+ return status;
+}
+
+/**
+ *Parses an uri as defined by the css spec [4.1.1]:
+ * URI ::= url\({w}{string}{w}\)
+ * |url\({w}([!#$%&*-~]|{nonascii}|{escape})*{w}\)
+ *
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_str the successfully parsed url.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_tknzr_parse_uri (CRTknzr * a_this,
+ CRString ** a_str)
+{
+ guint32 cur_char = 0;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_PARSING_ERROR;
+ guchar tab[4] = { 0 }, *tmp_ptr1 = NULL, *tmp_ptr2 = NULL;
+ CRString *str = NULL;
+ CRParsingLocation location = {0,0,0} ;
+
+ g_return_val_if_fail (a_this
+ && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_str,
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ PEEK_BYTE (a_this, 1, &tab[0]);
+ PEEK_BYTE (a_this, 2, &tab[1]);
+ PEEK_BYTE (a_this, 3, &tab[2]);
+ PEEK_BYTE (a_this, 4, &tab[3]);
+
+ if (tab[0] != 'u' || tab[1] != 'r' || tab[2] != 'l' || tab[3] != '(') {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ /*
+ *Here, we want to skip 4 bytes ('u''r''l''(').
+ *But we also need to keep track of the parsing location
+ *of the 'u'. So, we skip 1 byte, we record the parsing
+ *location, then we skip the 3 remaining bytes.
+ */
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this, &location) ;
+ SKIP_CHARS (a_this, 3);
+ cr_tknzr_try_to_skip_spaces (a_this);
+ status = cr_tknzr_parse_string (a_this, a_str);
+
+ if (status == CR_OK) {
+ guint32 next_char = 0;
+ status = cr_tknzr_parse_w (a_this, &tmp_ptr1,
+ &tmp_ptr2, NULL);
+ cr_tknzr_try_to_skip_spaces (a_this);
+ PEEK_NEXT_CHAR (a_this, &next_char);
+ if (next_char == ')') {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ status = CR_OK;
+ } else {
+ status = CR_PARSING_ERROR;
+ }
+ }
+ if (status != CR_OK) {
+ str = cr_string_new ();
+ for (;;) {
+ guint32 next_char = 0;
+ PEEK_NEXT_CHAR (a_this, &next_char);
+ if (strchr ("!#$%&", next_char)
+ || (next_char >= '*' && next_char <= '~')
+ || (cr_utils_is_nonascii (next_char) == TRUE)) {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ g_string_append_unichar
+ (str->stryng, cur_char);
+ status = CR_OK;
+ } else {
+ guint32 esc_code = 0;
+ status = cr_tknzr_parse_escape
+ (a_this, &esc_code, NULL);
+ if (status == CR_OK) {
+ g_string_append_unichar
+ (str->stryng,
+ esc_code);
+ } else {
+ status = CR_OK;
+ break;
+ }
+ }
+ }
+ cr_tknzr_try_to_skip_spaces (a_this);
+ READ_NEXT_CHAR (a_this, &cur_char);
+ if (cur_char == ')') {
+ status = CR_OK;
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ if (str) {
+ if (*a_str == NULL) {
+ *a_str = str;
+ str = NULL;
+ } else {
+ g_string_append_len
+ ((*a_str)->stryng,
+ str->stryng->str,
+ str->stryng->len);
+ cr_string_destroy (str);
+ }
+ }
+ }
+
+ cr_parsing_location_copy
+ (&(*a_str)->location,
+ &location) ;
+ return CR_OK ;
+ error:
+ if (str) {
+ cr_string_destroy (str);
+ str = NULL;
+ }
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+ return status;
+}
+
+/**
+ *parses an RGB as defined in the css2 spec.
+ *rgb: rgb '('S*{num}%?S* ',' {num}#?S*,S*{num}#?S*')'
+ *
+ *@param a_this the "this pointer" of the current instance of
+ *@param a_rgb out parameter the parsed rgb.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_tknzr_parse_rgb (CRTknzr * a_this, CRRgb ** a_rgb)
+{
+ enum CRStatus status = CR_OK;
+ CRInputPos init_pos;
+ CRNum *num = NULL;
+ guchar next_bytes[3] = { 0 }, cur_byte = 0;
+ glong red = 0,
+ green = 0,
+ blue = 0,
+ i = 0;
+ gboolean is_percentage = FALSE;
+ CRParsingLocation location = {0,0,0} ;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ PEEK_BYTE (a_this, 1, &next_bytes[0]);
+ PEEK_BYTE (a_this, 2, &next_bytes[1]);
+ PEEK_BYTE (a_this, 3, &next_bytes[2]);
+
+ if (((next_bytes[0] == 'r') || (next_bytes[0] == 'R'))
+ && ((next_bytes[1] == 'g') || (next_bytes[1] == 'G'))
+ && ((next_bytes[2] == 'b') || (next_bytes[2] == 'B'))) {
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this, &location) ;
+ SKIP_CHARS (a_this, 2);
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ READ_NEXT_BYTE (a_this, &cur_byte);
+ ENSURE_PARSING_COND (cur_byte == '(');
+
+ cr_tknzr_try_to_skip_spaces (a_this);
+ status = cr_tknzr_parse_num (a_this, &num);
+ ENSURE_PARSING_COND ((status == CR_OK) && (num != NULL));
+
+ red = (glong)num->val;
+ cr_num_destroy (num);
+ num = NULL;
+
+ PEEK_BYTE (a_this, 1, &next_bytes[0]);
+ if (next_bytes[0] == '%') {
+ SKIP_CHARS (a_this, 1);
+ is_percentage = TRUE;
+ }
+ cr_tknzr_try_to_skip_spaces (a_this);
+
+ for (i = 0; i < 2; i++) {
+ READ_NEXT_BYTE (a_this, &cur_byte);
+ ENSURE_PARSING_COND (cur_byte == ',');
+
+ cr_tknzr_try_to_skip_spaces (a_this);
+ status = cr_tknzr_parse_num (a_this, &num);
+ ENSURE_PARSING_COND ((status == CR_OK) && (num != NULL));
+
+ PEEK_BYTE (a_this, 1, &next_bytes[0]);
+ if (next_bytes[0] == '%') {
+ SKIP_CHARS (a_this, 1);
+ is_percentage = 1;
+ }
+
+ if (i == 0) {
+ green = (glong)num->val;
+ } else if (i == 1) {
+ blue = (glong)num->val;
+ }
+
+ if (num) {
+ cr_num_destroy (num);
+ num = NULL;
+ }
+ cr_tknzr_try_to_skip_spaces (a_this);
+ }
+
+ READ_NEXT_BYTE (a_this, &cur_byte);
+ if (*a_rgb == NULL) {
+ *a_rgb = cr_rgb_new_with_vals (red, green, blue,
+ is_percentage);
+
+ if (*a_rgb == NULL) {
+ status = CR_ERROR;
+ goto error;
+ }
+ status = CR_OK;
+ } else {
+ (*a_rgb)->red = red;
+ (*a_rgb)->green = green;
+ (*a_rgb)->blue = blue;
+ (*a_rgb)->is_percentage = is_percentage;
+
+ status = CR_OK;
+ }
+
+ if (status == CR_OK) {
+ if (a_rgb && *a_rgb) {
+ cr_parsing_location_copy
+ (&(*a_rgb)->location,
+ &location) ;
+ }
+ return CR_OK;
+ }
+
+ error:
+ if (num) {
+ cr_num_destroy (num);
+ num = NULL;
+ }
+
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+ return CR_OK;
+}
+
+/**
+ *Parses a atkeyword as defined by the css spec in [4.1.1]:
+ *ATKEYWORD ::= @{ident}
+ *
+ *@param a_this the "this pointer" of the current instance of
+ *#CRTknzr.
+ *
+ *@param a_str out parameter. The parsed atkeyword. If *a_str is
+ *set to NULL this function allocates a new instance of CRString and
+ *sets it to the parsed atkeyword. If not, this function just appends
+ *the parsed atkeyword to the end of *a_str. In both cases it is up to
+ *the caller to free *a_str.
+ *
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+static enum CRStatus
+cr_tknzr_parse_atkeyword (CRTknzr * a_this,
+ CRString ** a_str)
+{
+ guint32 cur_char = 0;
+ CRInputPos init_pos;
+ gboolean str_needs_free = FALSE;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_str, CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ if (cur_char != '@') {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+
+ if (*a_str == NULL) {
+ *a_str = cr_string_new ();
+ str_needs_free = TRUE;
+ }
+ status = cr_tknzr_parse_ident (a_this, a_str);
+ if (status != CR_OK) {
+ goto error;
+ }
+ return CR_OK;
+ error:
+
+ if (str_needs_free == TRUE && *a_str) {
+ cr_string_destroy (*a_str);
+ *a_str = NULL;
+ }
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+ return status;
+}
+
+static enum CRStatus
+cr_tknzr_parse_important (CRTknzr * a_this,
+ CRParsingLocation *a_location)
+{
+ guint32 cur_char = 0;
+ CRInputPos init_pos;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input,
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+ READ_NEXT_CHAR (a_this, &cur_char);
+ ENSURE_PARSING_COND (cur_char == '!');
+ if (a_location) {
+ cr_tknzr_get_parsing_location (a_this,
+ a_location) ;
+ }
+ cr_tknzr_try_to_skip_spaces (a_this);
+
+ if (BYTE (PRIVATE (a_this)->input, 1, NULL) == 'i'
+ && BYTE (PRIVATE (a_this)->input, 2, NULL) == 'm'
+ && BYTE (PRIVATE (a_this)->input, 3, NULL) == 'p'
+ && BYTE (PRIVATE (a_this)->input, 4, NULL) == 'o'
+ && BYTE (PRIVATE (a_this)->input, 5, NULL) == 'r'
+ && BYTE (PRIVATE (a_this)->input, 6, NULL) == 't'
+ && BYTE (PRIVATE (a_this)->input, 7, NULL) == 'a'
+ && BYTE (PRIVATE (a_this)->input, 8, NULL) == 'n'
+ && BYTE (PRIVATE (a_this)->input, 9, NULL) == 't') {
+ SKIP_BYTES (a_this, 9);
+ if (a_location) {
+ cr_tknzr_get_parsing_location (a_this,
+ a_location) ;
+ }
+ return CR_OK;
+ } else {
+ status = CR_PARSING_ERROR;
+ }
+
+ error:
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+
+ return status;
+}
+
+/**
+ *Parses a num as defined in the css spec [4.1.1]:
+ *[0-9]+|[0-9]*\.[0-9]+
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_num out parameter. The parsed number.
+ *@return CR_OK upon successful completion,
+ *an error code otherwise.
+ *
+ *The CSS specification says that numbers may be
+ *preceded by '+' or '-' to indicate the sign.
+ *Technically, the "num" construction as defined
+ *by the tokenizer doesn't allow this, but we parse
+ *it here for simplicity.
+ */
+static enum CRStatus
+cr_tknzr_parse_num (CRTknzr * a_this,
+ CRNum ** a_num)
+{
+ enum CRStatus status = CR_PARSING_ERROR;
+ enum CRNumType val_type = NUM_GENERIC;
+ gboolean parsing_dec, /* true iff seen decimal point. */
+ parsed, /* true iff the substring seen so far is a valid CSS
+ number, i.e. `[0-9]+|[0-9]*\.[0-9]+'. */
+ parsing_exp = FALSE; /* true if seen an exponential */
+ gdouble exponent = 0; /* Start off the exponent at 0 */
+ int exp_sign = 1;
+ guint32 cur_char = 0,
+ next_char = 0;
+ gdouble numerator, denominator = 1;
+ CRInputPos init_pos;
+ CRParsingLocation location = {0,0,0};
+ int sign = 1;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input,
+ CR_BAD_PARAM_ERROR);
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+ READ_NEXT_CHAR (a_this, &cur_char);
+
+ if (cur_char == '+' || cur_char == '-') {
+ if (cur_char == '-') {
+ sign = -1;
+ }
+ READ_NEXT_CHAR (a_this, &cur_char);
+ }
+
+ if (IS_NUM (cur_char)) {
+ numerator = (cur_char - '0');
+ parsing_dec = FALSE;
+ parsed = TRUE;
+ } else if (cur_char == '.') {
+ numerator = 0;
+ parsing_dec = TRUE;
+ parsed = FALSE;
+ } else {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+ cr_tknzr_get_parsing_location (a_this, &location) ;
+
+ for (;;) {
+ status = cr_tknzr_peek_char (a_this, &next_char);
+ if (status != CR_OK) {
+ if (status == CR_END_OF_INPUT_ERROR)
+ status = CR_OK;
+ break;
+ }
+ if (next_char == '.') {
+ if (parsing_dec) {
+ status = CR_PARSING_ERROR;
+ goto error;
+ }
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+ parsing_dec = TRUE;
+ parsed = FALSE; /* In CSS, there must be at least
+ one digit after `.'. */
+ } else if (!parsing_exp && (next_char == 'E' || next_char == 'e') && parsed) {
+ guchar next_byte;
+ PEEK_BYTE (a_this, 2, &next_byte)
+ if (next_byte == '+') {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ } else if (next_byte == '-') {
+ exp_sign = -1;
+ READ_NEXT_CHAR (a_this, &cur_char);
+ } else if (!IS_NUM (next_byte)) {
+ break;
+ }
+
+ READ_NEXT_CHAR (a_this, &cur_char);
+ parsing_exp = TRUE;
+ parsed = FALSE;
+ } else if (IS_NUM (next_char)) {
+ READ_NEXT_CHAR (a_this, &cur_char);
+ parsed = TRUE;
+
+ if (parsing_exp) {
+ exponent = exponent * 10 + (cur_char - '0');
+ } else {
+ numerator = numerator * 10 + (cur_char - '0');
+ if (parsing_dec) {
+ denominator *= 10;
+ }
+ }
+ } else {
+ break;
+ }
+ }
+
+ if (!parsed) {
+ status = CR_PARSING_ERROR;
+ }
+
+ /*
+ *Now, set the output param values.
+ */
+ if (status == CR_OK) {
+ gdouble val = ((numerator / denominator) * sign) * pow(10, exponent * exp_sign);
+ if (*a_num == NULL) {
+ *a_num = cr_num_new_with_val (val, val_type);
+
+ if (*a_num == NULL) {
+ status = CR_ERROR;
+ goto error;
+ }
+ } else {
+ (*a_num)->val = val;
+ (*a_num)->type = val_type;
+ }
+ cr_parsing_location_copy (&(*a_num)->location,
+ &location) ;
+ return CR_OK;
+ }
+
+ error:
+
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+
+ return status;
+}
+
+/*********************************************
+ *PUBLIC methods
+ ********************************************/
+
+CRTknzr *
+cr_tknzr_new (CRInput * a_input)
+{
+ CRTknzr *result = NULL;
+
+ result = (CRTknzr *) g_try_malloc (sizeof (CRTknzr));
+
+ if (result == NULL) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRTknzr));
+
+ result->priv = (CRTknzrPriv *)g_try_malloc (sizeof (CRTknzrPriv));
+
+ if (result->priv == NULL) {
+ cr_utils_trace_info ("Out of memory");
+
+ if (result) {
+ g_free (result);
+ result = NULL;
+ }
+
+ return NULL;
+ }
+ memset (result->priv, 0, sizeof (CRTknzrPriv));
+ if (a_input)
+ cr_tknzr_set_input (result, a_input);
+ return result;
+}
+
+CRTknzr *
+cr_tknzr_new_from_buf (guchar * a_buf, gulong a_len,
+ enum CREncoding a_enc,
+ gboolean a_free_at_destroy)
+{
+ CRTknzr *result = NULL;
+ CRInput *input = NULL;
+
+ input = cr_input_new_from_buf (a_buf, a_len, a_enc,
+ a_free_at_destroy);
+
+ g_return_val_if_fail (input != NULL, NULL);
+
+ result = cr_tknzr_new (input);
+
+ return result;
+}
+
+CRTknzr *
+cr_tknzr_new_from_uri (const guchar * a_file_uri,
+ enum CREncoding a_enc)
+{
+ CRTknzr *result = NULL;
+ CRInput *input = NULL;
+
+ input = cr_input_new_from_uri ((const gchar *) a_file_uri, a_enc);
+ g_return_val_if_fail (input != NULL, NULL);
+
+ result = cr_tknzr_new (input);
+
+ return result;
+}
+
+void
+cr_tknzr_ref (CRTknzr * a_this)
+{
+ g_return_if_fail (a_this && PRIVATE (a_this));
+
+ PRIVATE (a_this)->ref_count++;
+}
+
+gboolean
+cr_tknzr_unref (CRTknzr * a_this)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), FALSE);
+
+ if (PRIVATE (a_this)->ref_count > 0) {
+ PRIVATE (a_this)->ref_count--;
+ }
+
+ if (PRIVATE (a_this)->ref_count == 0) {
+ cr_tknzr_destroy (a_this);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+enum CRStatus
+cr_tknzr_set_input (CRTknzr * a_this, CRInput * a_input)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->input) {
+ cr_input_unref (PRIVATE (a_this)->input);
+ }
+
+ PRIVATE (a_this)->input = a_input;
+
+ cr_input_ref (PRIVATE (a_this)->input);
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_tknzr_get_input (CRTknzr * a_this, CRInput ** a_input)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ *a_input = PRIVATE (a_this)->input;
+
+ return CR_OK;
+}
+
+/*********************************
+ *Tokenizer input handling routines
+ *********************************/
+
+/**
+ *Reads the next byte from the parser input stream.
+ *@param a_this the "this pointer" of the current instance of
+ *#CRParser.
+ *@param a_byte out parameter the place where to store the byte
+ *read.
+ *@return CR_OK upon successful completion, an error
+ *code otherwise.
+ */
+enum CRStatus
+cr_tknzr_read_byte (CRTknzr * a_this, guchar * a_byte)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+
+ return cr_input_read_byte (PRIVATE (a_this)->input, a_byte);
+
+}
+
+/**
+ *Reads the next char from the parser input stream.
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_char out parameter. The read char.
+ *@return CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_tknzr_read_char (CRTknzr * a_this, guint32 * a_char)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_char, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->token_cache) {
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
+ &PRIVATE (a_this)->prev_pos);
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
+ PRIVATE (a_this)->token_cache = NULL;
+ }
+
+ return cr_input_read_char (PRIVATE (a_this)->input, a_char);
+}
+
+/**
+ *Peeks a char from the parser input stream.
+ *To "peek a char" means reads the next char without consuming it.
+ *Subsequent calls to this function return the same char.
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_char out parameter. The peeked char upon successful completion.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_tknzr_peek_char (CRTknzr * a_this, guint32 * a_char)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_char, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->token_cache) {
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
+ &PRIVATE (a_this)->prev_pos);
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
+ PRIVATE (a_this)->token_cache = NULL;
+ }
+
+ return cr_input_peek_char (PRIVATE (a_this)->input, a_char);
+}
+
+/**
+ *Peeks a byte ahead at a given position in the parser input stream.
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_offset the offset of the peeked byte starting from the current
+ *byte in the parser input stream.
+ *@param a_byte out parameter. The peeked byte upon
+ *successful completion.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_tknzr_peek_byte (CRTknzr * a_this, gulong a_offset, guchar * a_byte)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input && a_byte,
+ CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->token_cache) {
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
+ &PRIVATE (a_this)->prev_pos);
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
+ PRIVATE (a_this)->token_cache = NULL;
+ }
+
+ return cr_input_peek_byte (PRIVATE (a_this)->input,
+ CR_SEEK_CUR, a_offset, a_byte);
+}
+
+/**
+ *Same as cr_tknzr_peek_byte() but this api returns the byte peeked.
+ *@param a_this the current instance of #CRTknzr.
+ *@param a_offset the offset of the peeked byte starting from the current
+ *byte in the parser input stream.
+ *@param a_eof out parameter. If not NULL, is set to TRUE if we reached end of
+ *file, FALE otherwise. If the caller sets it to NULL, this parameter
+ *is just ignored.
+ *@return the peeked byte.
+ */
+guchar
+cr_tknzr_peek_byte2 (CRTknzr * a_this, gulong a_offset, gboolean * a_eof)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input, 0);
+
+ return cr_input_peek_byte2 (PRIVATE (a_this)->input, a_offset, a_eof);
+}
+
+/**
+ *Gets the number of bytes left in the topmost input stream
+ *associated to this parser.
+ *@param a_this the current instance of #CRTknzr
+ *@return the number of bytes left or -1 in case of error.
+ */
+glong
+cr_tknzr_get_nb_bytes_left (CRTknzr * a_this)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->token_cache) {
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
+ &PRIVATE (a_this)->prev_pos);
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
+ PRIVATE (a_this)->token_cache = NULL;
+ }
+
+ return cr_input_get_nb_bytes_left (PRIVATE (a_this)->input);
+}
+
+enum CRStatus
+cr_tknzr_get_cur_pos (CRTknzr * a_this, CRInputPos * a_pos)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_pos, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->token_cache) {
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
+ &PRIVATE (a_this)->prev_pos);
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
+ PRIVATE (a_this)->token_cache = NULL;
+ }
+
+ return cr_input_get_cur_pos (PRIVATE (a_this)->input, a_pos);
+}
+
+enum CRStatus
+cr_tknzr_get_parsing_location (CRTknzr *a_this,
+ CRParsingLocation *a_loc)
+{
+ g_return_val_if_fail (a_this
+ && PRIVATE (a_this)
+ && a_loc,
+ CR_BAD_PARAM_ERROR) ;
+
+ return cr_input_get_parsing_location
+ (PRIVATE (a_this)->input, a_loc) ;
+}
+
+enum CRStatus
+cr_tknzr_get_cur_byte_addr (CRTknzr * a_this, guchar ** a_addr)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
+ if (PRIVATE (a_this)->token_cache) {
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
+ &PRIVATE (a_this)->prev_pos);
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
+ PRIVATE (a_this)->token_cache = NULL;
+ }
+
+ return cr_input_get_cur_byte_addr (PRIVATE (a_this)->input, a_addr);
+}
+
+enum CRStatus
+cr_tknzr_seek_index (CRTknzr * a_this, enum CRSeekPos a_origin, gint a_pos)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->token_cache) {
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
+ &PRIVATE (a_this)->prev_pos);
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
+ PRIVATE (a_this)->token_cache = NULL;
+ }
+
+ return cr_input_seek_index (PRIVATE (a_this)->input, a_origin, a_pos);
+}
+
+enum CRStatus
+cr_tknzr_consume_chars (CRTknzr * a_this, guint32 a_char, glong * a_nb_char)
+{
+ gulong consumed = *(gulong *) a_nb_char;
+ enum CRStatus status;
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->token_cache) {
+ cr_input_set_cur_pos (PRIVATE (a_this)->input,
+ &PRIVATE (a_this)->prev_pos);
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
+ PRIVATE (a_this)->token_cache = NULL;
+ }
+
+ status = cr_input_consume_chars (PRIVATE (a_this)->input,
+ a_char, &consumed);
+ *a_nb_char = (glong) consumed;
+ return status;
+}
+
+enum CRStatus
+cr_tknzr_set_cur_pos (CRTknzr * a_this, CRInputPos * a_pos)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input, CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->token_cache) {
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
+ PRIVATE (a_this)->token_cache = NULL;
+ }
+
+ return cr_input_set_cur_pos (PRIVATE (a_this)->input, a_pos);
+}
+
+enum CRStatus
+cr_tknzr_unget_token (CRTknzr * a_this, CRToken * a_token)
+{
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->token_cache == NULL,
+ CR_BAD_PARAM_ERROR);
+
+ PRIVATE (a_this)->token_cache = a_token;
+
+ return CR_OK;
+}
+
+/**
+ *Returns the next token of the input stream.
+ *This method is really central. Each parsing
+ *method calls it.
+ *@param a_this the current tokenizer.
+ *@param a_tk out parameter. The returned token.
+ *for the sake of mem leak avoidance, *a_tk must
+ *be NULL.
+ *@param CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_tknzr_get_next_token (CRTknzr * a_this, CRToken ** a_tk)
+{
+ enum CRStatus status = CR_OK;
+ CRToken *token = NULL;
+ CRInputPos init_pos;
+ guint32 next_char = 0;
+ guchar next_bytes[4] = { 0 };
+ gboolean reached_eof = FALSE;
+ CRInput *input = NULL;
+ CRString *str = NULL;
+ CRRgb *rgb = NULL;
+ CRParsingLocation location = {0,0,0} ;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && a_tk && *a_tk == NULL
+ && PRIVATE (a_this)->input,
+ CR_BAD_PARAM_ERROR);
+
+ if (PRIVATE (a_this)->token_cache) {
+ *a_tk = PRIVATE (a_this)->token_cache;
+ PRIVATE (a_this)->token_cache = NULL;
+ return CR_OK;
+ }
+
+ RECORD_INITIAL_POS (a_this, &init_pos);
+
+ status = cr_input_get_end_of_file
+ (PRIVATE (a_this)->input, &reached_eof);
+ ENSURE_PARSING_COND (status == CR_OK);
+
+ if (reached_eof == TRUE) {
+ status = CR_END_OF_INPUT_ERROR;
+ goto error;
+ }
+
+ input = PRIVATE (a_this)->input;
+
+ PEEK_NEXT_CHAR (a_this, &next_char);
+ token = cr_token_new ();
+ ENSURE_PARSING_COND (token);
+
+ switch (next_char) {
+ case '@':
+ {
+ if (BYTE (input, 2, NULL) == 'f'
+ && BYTE (input, 3, NULL) == 'o'
+ && BYTE (input, 4, NULL) == 'n'
+ && BYTE (input, 5, NULL) == 't'
+ && BYTE (input, 6, NULL) == '-'
+ && BYTE (input, 7, NULL) == 'f'
+ && BYTE (input, 8, NULL) == 'a'
+ && BYTE (input, 9, NULL) == 'c'
+ && BYTE (input, 10, NULL) == 'e') {
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location
+ (a_this, &location) ;
+ SKIP_CHARS (a_this, 9);
+ status = cr_token_set_font_face_sym (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+ }
+
+ if (BYTE (input, 2, NULL) == 'c'
+ && BYTE (input, 3, NULL) == 'h'
+ && BYTE (input, 4, NULL) == 'a'
+ && BYTE (input, 5, NULL) == 'r'
+ && BYTE (input, 6, NULL) == 's'
+ && BYTE (input, 7, NULL) == 'e'
+ && BYTE (input, 8, NULL) == 't') {
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location
+ (a_this, &location) ;
+ SKIP_CHARS (a_this, 7);
+ status = cr_token_set_charset_sym (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+ }
+
+ if (BYTE (input, 2, NULL) == 'i'
+ && BYTE (input, 3, NULL) == 'm'
+ && BYTE (input, 4, NULL) == 'p'
+ && BYTE (input, 5, NULL) == 'o'
+ && BYTE (input, 6, NULL) == 'r'
+ && BYTE (input, 7, NULL) == 't') {
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location
+ (a_this, &location) ;
+ SKIP_CHARS (a_this, 6);
+ status = cr_token_set_import_sym (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+ }
+
+ if (BYTE (input, 2, NULL) == 'm'
+ && BYTE (input, 3, NULL) == 'e'
+ && BYTE (input, 4, NULL) == 'd'
+ && BYTE (input, 5, NULL) == 'i'
+ && BYTE (input, 6, NULL) == 'a') {
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ SKIP_CHARS (a_this, 5);
+ status = cr_token_set_media_sym (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+ }
+
+ if (BYTE (input, 2, NULL) == 'p'
+ && BYTE (input, 3, NULL) == 'a'
+ && BYTE (input, 4, NULL) == 'g'
+ && BYTE (input, 5, NULL) == 'e') {
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ SKIP_CHARS (a_this, 4);
+ status = cr_token_set_page_sym (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+ }
+ status = cr_tknzr_parse_atkeyword (a_this, &str);
+ if (status == CR_OK) {
+ status = cr_token_set_atkeyword (token, str);
+ CHECK_PARSING_STATUS (status, TRUE);
+ if (str) {
+ cr_parsing_location_copy (&token->location,
+ &str->location) ;
+ }
+ goto done;
+ }
+ }
+ break;
+
+ case 'u':
+
+ if (BYTE (input, 2, NULL) == 'r'
+ && BYTE (input, 3, NULL) == 'l'
+ && BYTE (input, 4, NULL) == '(') {
+ CRString *str2 = NULL;
+
+ status = cr_tknzr_parse_uri (a_this, &str2);
+ if (status == CR_OK) {
+ status = cr_token_set_uri (token, str2);
+ CHECK_PARSING_STATUS (status, TRUE);
+ if (str2) {
+ cr_parsing_location_copy (&token->location,
+ &str2->location) ;
+ }
+ goto done;
+ }
+ }
+ goto fallback;
+ break;
+
+ case 'r':
+ if (BYTE (input, 2, NULL) == 'g'
+ && BYTE (input, 3, NULL) == 'b'
+ && BYTE (input, 4, NULL) == '(') {
+ status = cr_tknzr_parse_rgb (a_this, &rgb);
+ if (status == CR_OK && rgb) {
+ status = cr_token_set_rgb (token, rgb);
+ CHECK_PARSING_STATUS (status, TRUE);
+ if (rgb) {
+ cr_parsing_location_copy (&token->location,
+ &rgb->location) ;
+ }
+ rgb = NULL;
+ goto done;
+ }
+
+ }
+ goto fallback;
+ break;
+
+ case '<':
+ if (BYTE (input, 2, NULL) == '!'
+ && BYTE (input, 3, NULL) == '-'
+ && BYTE (input, 4, NULL) == '-') {
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ SKIP_CHARS (a_this, 3);
+ status = cr_token_set_cdo (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+ }
+ break;
+
+ case '-':
+ if (BYTE (input, 2, NULL) == '-'
+ && BYTE (input, 3, NULL) == '>') {
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ SKIP_CHARS (a_this, 2);
+ status = cr_token_set_cdc (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+ } else {
+ status = cr_tknzr_parse_ident
+ (a_this, &str);
+ if (status == CR_OK) {
+ cr_token_set_ident
+ (token, str);
+ if (str) {
+ cr_parsing_location_copy (&token->location,
+ &str->location) ;
+ }
+ goto done;
+ } else {
+ goto parse_number;
+ }
+ }
+ break;
+
+ case '~':
+ if (BYTE (input, 2, NULL) == '=') {
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ SKIP_CHARS (a_this, 1);
+ status = cr_token_set_includes (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+ }
+ break;
+
+ case '|':
+ if (BYTE (input, 2, NULL) == '=') {
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ SKIP_CHARS (a_this, 1);
+ status = cr_token_set_dashmatch (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+ }
+ break;
+
+ case '/':
+ if (BYTE (input, 2, NULL) == '*') {
+ status = cr_tknzr_parse_comment (a_this, &str);
+
+ if (status == CR_OK) {
+ status = cr_token_set_comment (token, str);
+ str = NULL;
+ CHECK_PARSING_STATUS (status, TRUE);
+ if (str) {
+ cr_parsing_location_copy (&token->location,
+ &str->location) ;
+ }
+ goto done;
+ }
+ }
+ break ;
+
+ case ';':
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ status = cr_token_set_semicolon (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+
+ case '{':
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ status = cr_token_set_cbo (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ goto done;
+
+ case '}':
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ status = cr_token_set_cbc (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+
+ case '(':
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ status = cr_token_set_po (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+
+ case ')':
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ status = cr_token_set_pc (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+
+ case '[':
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ status = cr_token_set_bo (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+
+ case ']':
+ SKIP_CHARS (a_this, 1);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ status = cr_token_set_bc (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\f':
+ case '\r':
+ {
+ guchar *start = NULL,
+ *end = NULL;
+
+ status = cr_tknzr_parse_w (a_this, &start,
+ &end, &location);
+ if (status == CR_OK) {
+ status = cr_token_set_s (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ goto done;
+ }
+ }
+ break;
+
+ case '#':
+ {
+ status = cr_tknzr_parse_hash (a_this, &str);
+ if (status == CR_OK && str) {
+ status = cr_token_set_hash (token, str);
+ CHECK_PARSING_STATUS (status, TRUE);
+ if (str) {
+ cr_parsing_location_copy (&token->location,
+ &str->location) ;
+ }
+ str = NULL;
+ goto done;
+ }
+ }
+ break;
+
+ case '\'':
+ case '"':
+ status = cr_tknzr_parse_string (a_this, &str);
+ if (status == CR_OK && str) {
+ status = cr_token_set_string (token, str);
+ CHECK_PARSING_STATUS (status, TRUE);
+ if (str) {
+ cr_parsing_location_copy (&token->location,
+ &str->location) ;
+ }
+ str = NULL;
+ goto done;
+ }
+ break;
+
+ case '!':
+ status = cr_tknzr_parse_important (a_this, &location);
+ if (status == CR_OK) {
+ status = cr_token_set_important_sym (token);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ goto done;
+ }
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '.':
+ case '+':
+ /* '-' case is handled separately above for --> comments */
+ parse_number:
+ {
+ CRNum *num = NULL;
+
+ status = cr_tknzr_parse_num (a_this, &num);
+ if (status == CR_OK && num) {
+ next_bytes[0] = BYTE (input, 1, NULL);
+ next_bytes[1] = BYTE (input, 2, NULL);
+ next_bytes[2] = BYTE (input, 3, NULL);
+ next_bytes[3] = BYTE (input, 4, NULL);
+
+ if (next_bytes[0] == 'e'
+ && next_bytes[1] == 'm') {
+ num->type = NUM_LENGTH_EM;
+ status = cr_token_set_ems (token,
+ num);
+ num = NULL;
+ SKIP_CHARS (a_this, 2);
+ } else if (next_bytes[0] == 'e'
+ && next_bytes[1] == 'x') {
+ num->type = NUM_LENGTH_EX;
+ status = cr_token_set_exs (token,
+ num);
+ num = NULL;
+ SKIP_CHARS (a_this, 2);
+ } else if (next_bytes[0] == 'p'
+ && next_bytes[1] == 'x') {
+ num->type = NUM_LENGTH_PX;
+ status = cr_token_set_length
+ (token, num, LENGTH_PX_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 2);
+ } else if (next_bytes[0] == 'c'
+ && next_bytes[1] == 'm') {
+ num->type = NUM_LENGTH_CM;
+ status = cr_token_set_length
+ (token, num, LENGTH_CM_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 2);
+ } else if (next_bytes[0] == 'm'
+ && next_bytes[1] == 'm') {
+ num->type = NUM_LENGTH_MM;
+ status = cr_token_set_length
+ (token, num, LENGTH_MM_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 2);
+ } else if (next_bytes[0] == 'i'
+ && next_bytes[1] == 'n') {
+ num->type = NUM_LENGTH_IN;
+ status = cr_token_set_length
+ (token, num, LENGTH_IN_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 2);
+ } else if (next_bytes[0] == 'p'
+ && next_bytes[1] == 't') {
+ num->type = NUM_LENGTH_PT;
+ status = cr_token_set_length
+ (token, num, LENGTH_PT_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 2);
+ } else if (next_bytes[0] == 'p'
+ && next_bytes[1] == 'c') {
+ num->type = NUM_LENGTH_PC;
+ status = cr_token_set_length
+ (token, num, LENGTH_PC_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 2);
+ } else if (next_bytes[0] == 'd'
+ && next_bytes[1] == 'e'
+ && next_bytes[2] == 'g') {
+ num->type = NUM_ANGLE_DEG;
+ status = cr_token_set_angle
+ (token, num, ANGLE_DEG_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 3);
+ } else if (next_bytes[0] == 'r'
+ && next_bytes[1] == 'a'
+ && next_bytes[2] == 'd') {
+ num->type = NUM_ANGLE_RAD;
+ status = cr_token_set_angle
+ (token, num, ANGLE_RAD_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 3);
+ } else if (next_bytes[0] == 'g'
+ && next_bytes[1] == 'r'
+ && next_bytes[2] == 'a'
+ && next_bytes[3] == 'd') {
+ num->type = NUM_ANGLE_GRAD;
+ status = cr_token_set_angle
+ (token, num, ANGLE_GRAD_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 4);
+ } else if (next_bytes[0] == 'm'
+ && next_bytes[1] == 's') {
+ num->type = NUM_TIME_MS;
+ status = cr_token_set_time
+ (token, num, TIME_MS_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 2);
+ } else if (next_bytes[0] == 's') {
+ num->type = NUM_TIME_S;
+ status = cr_token_set_time
+ (token, num, TIME_S_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 1);
+ } else if (next_bytes[0] == 'H'
+ && next_bytes[1] == 'z') {
+ num->type = NUM_FREQ_HZ;
+ status = cr_token_set_freq
+ (token, num, FREQ_HZ_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 2);
+ } else if (next_bytes[0] == 'k'
+ && next_bytes[1] == 'H'
+ && next_bytes[2] == 'z') {
+ num->type = NUM_FREQ_KHZ;
+ status = cr_token_set_freq
+ (token, num, FREQ_KHZ_ET);
+ num = NULL;
+ SKIP_CHARS (a_this, 3);
+ } else if (next_bytes[0] == '%') {
+ num->type = NUM_PERCENTAGE;
+ status = cr_token_set_percentage
+ (token, num);
+ num = NULL;
+ SKIP_CHARS (a_this, 1);
+ } else {
+ status = cr_tknzr_parse_ident (a_this,
+ &str);
+ if (status == CR_OK && str) {
+ num->type = NUM_UNKNOWN_TYPE;
+ status = cr_token_set_dimen
+ (token, num, str);
+ num = NULL;
+ CHECK_PARSING_STATUS (status,
+ TRUE);
+ str = NULL;
+ } else {
+ status = cr_token_set_number
+ (token, num);
+ num = NULL;
+ CHECK_PARSING_STATUS (status, CR_OK);
+ str = NULL;
+ }
+ }
+ if (token && token->u.num) {
+ cr_parsing_location_copy (&token->location,
+ &token->u.num->location) ;
+ } else {
+ status = CR_ERROR ;
+ }
+ goto done ;
+ }
+ }
+ break;
+
+ default:
+ fallback:
+ /*process the fallback cases here */
+
+ if (next_char == '\\'
+ || (cr_utils_is_nonascii (next_char) == TRUE)
+ || ((next_char >= 'a') && (next_char <= 'z'))
+ || ((next_char >= 'A') && (next_char <= 'Z'))) {
+ status = cr_tknzr_parse_ident (a_this, &str);
+ if (status == CR_OK && str) {
+ guint32 next_c = 0;
+
+ status = cr_input_peek_char
+ (PRIVATE (a_this)->input, &next_c);
+
+ if (status == CR_OK && next_c == '(') {
+
+ SKIP_CHARS (a_this, 1);
+ status = cr_token_set_function
+ (token, str);
+ CHECK_PARSING_STATUS (status, TRUE);
+ /*ownership is transferred
+ *to token by cr_token_set_function.
+ */
+ if (str) {
+ cr_parsing_location_copy (&token->location,
+ &str->location) ;
+ }
+ str = NULL;
+ } else {
+ status = cr_token_set_ident (token,
+ str);
+ CHECK_PARSING_STATUS (status, TRUE);
+ if (str) {
+ cr_parsing_location_copy (&token->location,
+ &str->location) ;
+ }
+ str = NULL;
+ }
+ goto done;
+ } else {
+ if (str) {
+ cr_string_destroy (str);
+ str = NULL;
+ }
+ }
+ }
+ break;
+ }
+
+ READ_NEXT_CHAR (a_this, &next_char);
+ cr_tknzr_get_parsing_location (a_this,
+ &location) ;
+ status = cr_token_set_delim (token, next_char);
+ CHECK_PARSING_STATUS (status, TRUE);
+ cr_parsing_location_copy (&token->location,
+ &location) ;
+ done:
+
+ if (status == CR_OK && token) {
+ *a_tk = token;
+ /*
+ *store the previous position input stream pos.
+ */
+ memmove (&PRIVATE (a_this)->prev_pos,
+ &init_pos, sizeof (CRInputPos));
+ return CR_OK;
+ }
+
+ error:
+ if (token) {
+ cr_token_destroy (token);
+ token = NULL;
+ }
+
+ if (str) {
+ cr_string_destroy (str);
+ str = NULL;
+ }
+ cr_tknzr_set_cur_pos (a_this, &init_pos);
+ return status;
+
+}
+
+enum CRStatus
+cr_tknzr_parse_token (CRTknzr * a_this, enum CRTokenType a_type,
+ enum CRTokenExtraType a_et, gpointer a_res,
+ gpointer a_extra_res)
+{
+ enum CRStatus status = CR_OK;
+ CRToken *token = NULL;
+
+ g_return_val_if_fail (a_this && PRIVATE (a_this)
+ && PRIVATE (a_this)->input
+ && a_res, CR_BAD_PARAM_ERROR);
+
+ status = cr_tknzr_get_next_token (a_this, &token);
+ if (status != CR_OK)
+ return status;
+ if (token == NULL)
+ return CR_PARSING_ERROR;
+
+ if (token->type == a_type) {
+ switch (a_type) {
+ case NO_TK:
+ case S_TK:
+ case CDO_TK:
+ case CDC_TK:
+ case INCLUDES_TK:
+ case DASHMATCH_TK:
+ case IMPORT_SYM_TK:
+ case PAGE_SYM_TK:
+ case MEDIA_SYM_TK:
+ case FONT_FACE_SYM_TK:
+ case CHARSET_SYM_TK:
+ case IMPORTANT_SYM_TK:
+ status = CR_OK;
+ break;
+
+ case STRING_TK:
+ case IDENT_TK:
+ case HASH_TK:
+ case ATKEYWORD_TK:
+ case FUNCTION_TK:
+ case COMMENT_TK:
+ case URI_TK:
+ *((CRString **) a_res) = token->u.str;
+ token->u.str = NULL;
+ status = CR_OK;
+ break;
+
+ case EMS_TK:
+ case EXS_TK:
+ case PERCENTAGE_TK:
+ case NUMBER_TK:
+ *((CRNum **) a_res) = token->u.num;
+ token->u.num = NULL;
+ status = CR_OK;
+ break;
+
+ case LENGTH_TK:
+ case ANGLE_TK:
+ case TIME_TK:
+ case FREQ_TK:
+ if (token->extra_type == a_et) {
+ *((CRNum **) a_res) = token->u.num;
+ token->u.num = NULL;
+ status = CR_OK;
+ }
+ break;
+
+ case DIMEN_TK:
+ *((CRNum **) a_res) = token->u.num;
+ if (a_extra_res == NULL) {
+ status = CR_BAD_PARAM_ERROR;
+ goto error;
+ }
+
+ *((CRString **) a_extra_res) = token->dimen;
+ token->u.num = NULL;
+ token->dimen = NULL;
+ status = CR_OK;
+ break;
+
+ case DELIM_TK:
+ *((guint32 *) a_res) = token->u.unichar;
+ status = CR_OK;
+ break;
+
+ case UNICODERANGE_TK:
+ default:
+ status = CR_PARSING_ERROR;
+ break;
+ }
+
+ cr_token_destroy (token);
+ token = NULL;
+ } else {
+ cr_tknzr_unget_token (a_this, token);
+ token = NULL;
+ status = CR_PARSING_ERROR;
+ }
+
+ return status;
+
+ error:
+
+ if (token) {
+ cr_tknzr_unget_token (a_this, token);
+ token = NULL;
+ }
+
+ return status;
+}
+
+void
+cr_tknzr_destroy (CRTknzr * a_this)
+{
+ g_return_if_fail (a_this);
+
+ if (PRIVATE (a_this) && PRIVATE (a_this)->input) {
+ if (cr_input_unref (PRIVATE (a_this)->input)
+ == TRUE) {
+ PRIVATE (a_this)->input = NULL;
+ }
+ }
+
+ if (PRIVATE (a_this)->token_cache) {
+ cr_token_destroy (PRIVATE (a_this)->token_cache);
+ PRIVATE (a_this)->token_cache = NULL;
+ }
+
+ if (PRIVATE (a_this)) {
+ g_free (PRIVATE (a_this));
+ PRIVATE (a_this) = NULL;
+ }
+
+ g_free (a_this);
+}
diff --git a/src/3rdparty/libcroco/src/cr-tknzr.h b/src/3rdparty/libcroco/src/cr-tknzr.h
new file mode 100644
index 0000000..13985b3
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-tknzr.h
@@ -0,0 +1,115 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for coypyright information.
+ */
+
+/**
+ *@file
+ *The declaration of the #CRTknzr (tokenizer)
+ *class.
+ */
+
+#ifndef __CR_TKNZR_H__
+#define __CR_TKNZR_H__
+
+#include "cr-utils.h"
+#include "cr-input.h"
+#include "cr-token.h"
+
+G_BEGIN_DECLS
+
+
+typedef struct _CRTknzr CRTknzr ;
+typedef struct _CRTknzrPriv CRTknzrPriv ;
+
+/**
+ *The tokenizer is the class that knows
+ *about all the css token. Its main job is
+ *to return the next token found in the character
+ *input stream.
+ */
+struct _CRTknzr
+{
+ /*the private data of the tokenizer.*/
+ CRTknzrPriv *priv ;
+} ;
+
+CRTknzr * cr_tknzr_new (CRInput *a_input) ;
+
+CRTknzr * cr_tknzr_new_from_uri (const guchar *a_file_uri,
+ enum CREncoding a_enc) ;
+
+CRTknzr * cr_tknzr_new_from_buf (guchar *a_buf, gulong a_len,
+ enum CREncoding a_enc,
+ gboolean a_free_at_destroy) ;
+
+gboolean cr_tknzr_unref (CRTknzr *a_this) ;
+
+void cr_tknzr_ref (CRTknzr *a_this) ;
+
+enum CRStatus cr_tknzr_read_byte (CRTknzr *a_this, guchar *a_byte) ;
+
+enum CRStatus cr_tknzr_read_char (CRTknzr *a_this, guint32 *a_char);
+
+enum CRStatus cr_tknzr_peek_char (CRTknzr *a_this, guint32 *a_char) ;
+
+enum CRStatus cr_tknzr_peek_byte (CRTknzr *a_this, gulong a_offset,
+ guchar *a_byte) ;
+
+guchar cr_tknzr_peek_byte2 (CRTknzr *a_this, gulong a_offset,
+ gboolean *a_eof) ;
+
+enum CRStatus cr_tknzr_set_cur_pos (CRTknzr *a_this, CRInputPos *a_pos) ;
+
+glong cr_tknzr_get_nb_bytes_left (CRTknzr *a_this) ;
+
+enum CRStatus cr_tknzr_get_cur_pos (CRTknzr *a_this, CRInputPos *a_pos) ;
+
+enum CRStatus cr_tknzr_get_parsing_location (CRTknzr *a_this,
+ CRParsingLocation *a_loc) ;
+
+enum CRStatus cr_tknzr_seek_index (CRTknzr *a_this,
+ enum CRSeekPos a_origin,
+ gint a_pos) ;
+
+enum CRStatus cr_tknzr_get_cur_byte_addr (CRTknzr *a_this, guchar **a_addr) ;
+
+
+enum CRStatus cr_tknzr_consume_chars (CRTknzr *a_this, guint32 a_char,
+ glong *a_nb_char) ;
+
+enum CRStatus cr_tknzr_get_next_token (CRTknzr *a_this, CRToken ** a_tk) ;
+
+enum CRStatus cr_tknzr_unget_token (CRTknzr *a_this, CRToken *a_token) ;
+
+
+enum CRStatus cr_tknzr_parse_token (CRTknzr *a_this, enum CRTokenType a_type,
+ enum CRTokenExtraType a_et, gpointer a_res,
+ gpointer a_extra_res) ;
+enum CRStatus cr_tknzr_set_input (CRTknzr *a_this, CRInput *a_input) ;
+
+enum CRStatus cr_tknzr_get_input (CRTknzr *a_this, CRInput **a_input) ;
+
+void cr_tknzr_destroy (CRTknzr *a_this) ;
+
+G_END_DECLS
+
+#endif /*__CR_TKZNR_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-token.c b/src/3rdparty/libcroco/src/cr-token.c
new file mode 100644
index 0000000..95226d7
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-token.c
@@ -0,0 +1,636 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * see COPYRIGHTS file for copyright information.
+ */
+
+/**
+ *@file
+ *The definition of the #CRToken class.
+ *Abstracts a css2 token.
+ */
+#include <string.h>
+#include "cr-token.h"
+
+/*
+ *TODO: write a CRToken::to_string() method.
+ */
+
+/**
+ *Frees the attributes of the current instance
+ *of #CRtoken.
+ *@param a_this the current instance of #CRToken.
+ */
+static void
+cr_token_clear (CRToken * a_this)
+{
+ g_return_if_fail (a_this);
+
+ switch (a_this->type) {
+ case S_TK:
+ case CDO_TK:
+ case CDC_TK:
+ case INCLUDES_TK:
+ case DASHMATCH_TK:
+ case PAGE_SYM_TK:
+ case MEDIA_SYM_TK:
+ case FONT_FACE_SYM_TK:
+ case CHARSET_SYM_TK:
+ case IMPORT_SYM_TK:
+ case IMPORTANT_SYM_TK:
+ case SEMICOLON_TK:
+ case NO_TK:
+ case DELIM_TK:
+ case CBO_TK:
+ case CBC_TK:
+ case BO_TK:
+ case BC_TK:
+ break;
+
+ case STRING_TK:
+ case IDENT_TK:
+ case HASH_TK:
+ case URI_TK:
+ case FUNCTION_TK:
+ case COMMENT_TK:
+ case ATKEYWORD_TK:
+ if (a_this->u.str) {
+ cr_string_destroy (a_this->u.str);
+ a_this->u.str = NULL;
+ }
+ break;
+
+ case EMS_TK:
+ case EXS_TK:
+ case LENGTH_TK:
+ case ANGLE_TK:
+ case TIME_TK:
+ case FREQ_TK:
+ case PERCENTAGE_TK:
+ case NUMBER_TK:
+ case PO_TK:
+ case PC_TK:
+ if (a_this->u.num) {
+ cr_num_destroy (a_this->u.num);
+ a_this->u.num = NULL;
+ }
+ break;
+
+ case DIMEN_TK:
+ if (a_this->u.num) {
+ cr_num_destroy (a_this->u.num);
+ a_this->u.num = NULL;
+ }
+
+ if (a_this->dimen) {
+ cr_string_destroy (a_this->dimen);
+ a_this->dimen = NULL;
+ }
+
+ break;
+
+ case RGB_TK:
+ if (a_this->u.rgb) {
+ cr_rgb_destroy (a_this->u.rgb) ;
+ a_this->u.rgb = NULL ;
+ }
+ break ;
+
+ case UNICODERANGE_TK:
+ /*not supported yet. */
+ break;
+
+ default:
+ cr_utils_trace_info ("I don't know how to clear this token\n") ;
+ break;
+ }
+
+ a_this->type = NO_TK;
+}
+
+/**
+ *Default constructor of
+ *the #CRToken class.
+ *@return the newly built instance of #CRToken.
+ */
+CRToken *
+cr_token_new (void)
+{
+ CRToken *result = NULL;
+
+ result = (CRToken *) g_try_malloc (sizeof (CRToken));
+
+ if (result == NULL) {
+ cr_utils_trace_info ("Out of memory");
+ return NULL;
+ }
+
+ memset (result, 0, sizeof (CRToken));
+
+ return result;
+}
+
+/**
+ *Sets the type of curren instance of
+ *#CRToken to 'S_TK' (S in the css2 spec)
+ *@param a_this the current instance of #CRToken.
+ *@return CR_OK upon successful completion, an error
+ *code otherwise.
+ */
+enum CRStatus
+cr_token_set_s (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = S_TK;
+
+ return CR_OK;
+}
+
+/**
+ *Sets the type of the current instance of
+ *#CRToken to 'CDO_TK' (CDO as said by the css2 spec)
+ *@param a_this the current instance of #CRToken.
+ *@return CR_OK upon successful completion, an error
+ *code otherwise.
+ */
+enum CRStatus
+cr_token_set_cdo (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = CDO_TK;
+
+ return CR_OK;
+}
+
+/**
+ *Sets the type of the current token to
+ *CDC_TK (CDC as said by the css2 spec).
+ *@param a_this the current instance of #CRToken.
+ *@return CR_OK upon successful completion, an error
+ *code otherwise.
+ */
+enum CRStatus
+cr_token_set_cdc (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = CDC_TK;
+
+ return CR_OK;
+}
+
+/**
+ *Sets the type of the current instance of
+ *#CRToken to INCLUDES_TK (INCLUDES as said by the css2 spec).
+ *@param a_this the current instance of #CRToken.
+ *@return CR_OK upon successful completion, an error
+ *code otherwise.
+ */
+enum CRStatus
+cr_token_set_includes (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = INCLUDES_TK;
+
+ return CR_OK;
+}
+
+/**
+ *Sets the type of the current instance of
+ *#CRToken to DASHMATCH_TK (DASHMATCH as said by the css2 spec).
+ *@param a_this the current instance of #CRToken.
+ *@return CR_OK upon successful completion, an error
+ *code otherwise.
+ */
+enum CRStatus
+cr_token_set_dashmatch (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = DASHMATCH_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_comment (CRToken * a_this, CRString * a_str)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+ a_this->type = COMMENT_TK;
+ a_this->u.str = a_str ;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_string (CRToken * a_this, CRString * a_str)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = STRING_TK;
+
+ a_this->u.str = a_str ;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_ident (CRToken * a_this, CRString * a_ident)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+ a_this->type = IDENT_TK;
+ a_this->u.str = a_ident;
+ return CR_OK;
+}
+
+
+enum CRStatus
+cr_token_set_function (CRToken * a_this, CRString * a_fun_name)
+{
+ g_return_val_if_fail (a_this,
+ CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+ a_this->type = FUNCTION_TK;
+ a_this->u.str = a_fun_name;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_hash (CRToken * a_this, CRString * a_hash)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+ a_this->type = HASH_TK;
+ a_this->u.str = a_hash;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_rgb (CRToken * a_this, CRRgb * a_rgb)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+ a_this->type = RGB_TK;
+ a_this->u.rgb = a_rgb;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_import_sym (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = IMPORT_SYM_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_page_sym (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = PAGE_SYM_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_media_sym (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = MEDIA_SYM_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_font_face_sym (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+ a_this->type = FONT_FACE_SYM_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_charset_sym (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+ a_this->type = CHARSET_SYM_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_atkeyword (CRToken * a_this, CRString * a_atname)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+ a_this->type = ATKEYWORD_TK;
+ a_this->u.str = a_atname;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_important_sym (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+ cr_token_clear (a_this);
+ a_this->type = IMPORTANT_SYM_TK;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_ems (CRToken * a_this, CRNum * a_num)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+ cr_token_clear (a_this);
+ a_this->type = EMS_TK;
+ a_this->u.num = a_num;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_exs (CRToken * a_this, CRNum * a_num)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+ cr_token_clear (a_this);
+ a_this->type = EXS_TK;
+ a_this->u.num = a_num;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_length (CRToken * a_this, CRNum * a_num,
+ enum CRTokenExtraType a_et)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = LENGTH_TK;
+ a_this->extra_type = a_et;
+ a_this->u.num = a_num;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_angle (CRToken * a_this, CRNum * a_num,
+ enum CRTokenExtraType a_et)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = ANGLE_TK;
+ a_this->extra_type = a_et;
+ a_this->u.num = a_num;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_time (CRToken * a_this, CRNum * a_num,
+ enum CRTokenExtraType a_et)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = TIME_TK;
+ a_this->extra_type = a_et;
+ a_this->u.num = a_num;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_freq (CRToken * a_this, CRNum * a_num,
+ enum CRTokenExtraType a_et)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = FREQ_TK;
+ a_this->extra_type = a_et;
+ a_this->u.num = a_num;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_dimen (CRToken * a_this, CRNum * a_num,
+ CRString * a_dim)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+ cr_token_clear (a_this);
+ a_this->type = DIMEN_TK;
+ a_this->u.num = a_num;
+ a_this->dimen = a_dim;
+ return CR_OK;
+
+}
+
+enum CRStatus
+cr_token_set_percentage (CRToken * a_this, CRNum * a_num)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = PERCENTAGE_TK;
+ a_this->u.num = a_num;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_number (CRToken * a_this, CRNum * a_num)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = NUMBER_TK;
+ a_this->u.num = a_num;
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_uri (CRToken * a_this, CRString * a_uri)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = URI_TK;
+ a_this->u.str = a_uri;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_delim (CRToken * a_this, guint32 a_char)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = DELIM_TK;
+ a_this->u.unichar = a_char;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_semicolon (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = SEMICOLON_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_cbo (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = CBO_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_cbc (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = CBC_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_po (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = PO_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_pc (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = PC_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_bo (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = BO_TK;
+
+ return CR_OK;
+}
+
+enum CRStatus
+cr_token_set_bc (CRToken * a_this)
+{
+ g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+
+ cr_token_clear (a_this);
+
+ a_this->type = BC_TK;
+
+ return CR_OK;
+}
+
+/**
+ *The destructor of the #CRToken class.
+ *@param a_this the current instance of #CRToken.
+ */
+void
+cr_token_destroy (CRToken * a_this)
+{
+ g_return_if_fail (a_this);
+
+ cr_token_clear (a_this);
+
+ g_free (a_this);
+}
diff --git a/src/3rdparty/libcroco/src/cr-token.h b/src/3rdparty/libcroco/src/cr-token.h
new file mode 100644
index 0000000..35e914d
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-token.h
@@ -0,0 +1,212 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#ifndef __CR_TOKEN_H__
+#define __CR_TOKEN_H__
+
+#include "cr-utils.h"
+#include "cr-input.h"
+#include "cr-num.h"
+#include "cr-rgb.h"
+#include "cr-string.h"
+#include "cr-parsing-location.h"
+
+G_BEGIN_DECLS
+
+enum CRTokenType
+{
+ NO_TK, // 0
+ S_TK,
+ CDO_TK,
+ CDC_TK,
+ INCLUDES_TK,
+ DASHMATCH_TK, // 5
+ COMMENT_TK,
+ STRING_TK,
+ IDENT_TK,
+ HASH_TK,
+ IMPORT_SYM_TK, // 10
+ PAGE_SYM_TK,
+ MEDIA_SYM_TK,
+ FONT_FACE_SYM_TK,
+ CHARSET_SYM_TK,
+ ATKEYWORD_TK, // 15
+ IMPORTANT_SYM_TK,
+ EMS_TK,
+ EXS_TK,
+ LENGTH_TK,
+ ANGLE_TK, // 20
+ TIME_TK,
+ FREQ_TK,
+ DIMEN_TK,
+ PERCENTAGE_TK,
+ NUMBER_TK, // 25
+ RGB_TK,
+ URI_TK,
+ FUNCTION_TK,
+ UNICODERANGE_TK,
+ SEMICOLON_TK, // 30
+ CBO_TK, /*opening curly bracket*/
+ CBC_TK, /*closing curly bracket*/
+ PO_TK, /*opening parenthesis*/
+ PC_TK, /*closing parenthesis*/
+ BO_TK, /*opening bracket*/
+ BC_TK, /*closing bracket*/
+ DELIM_TK
+} ;
+
+enum CRTokenExtraType
+{
+ NO_ET = 0,
+ LENGTH_PX_ET,
+ LENGTH_CM_ET,
+ LENGTH_MM_ET,
+ LENGTH_IN_ET,
+ LENGTH_PT_ET,
+ LENGTH_PC_ET,
+ ANGLE_DEG_ET,
+ ANGLE_RAD_ET,
+ ANGLE_GRAD_ET,
+ TIME_MS_ET,
+ TIME_S_ET,
+ FREQ_HZ_ET,
+ FREQ_KHZ_ET
+} ;
+
+typedef struct _CRToken CRToken ;
+
+/**
+ *This class abstracts a css2 token.
+ */
+struct _CRToken
+{
+ enum CRTokenType type ;
+ enum CRTokenExtraType extra_type ;
+ CRInputPos pos ;
+
+ union
+ {
+ CRString *str ;
+ CRRgb *rgb ;
+ CRNum *num ;
+ guint32 unichar ;
+ } u ;
+
+ CRString * dimen ;
+ CRParsingLocation location ;
+} ;
+
+CRToken* cr_token_new (void) ;
+
+enum CRStatus cr_token_set_s (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_cdo (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_cdc (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_includes (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_dashmatch (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_comment (CRToken *a_this, CRString *a_str) ;
+
+enum CRStatus cr_token_set_string (CRToken *a_this, CRString *a_str) ;
+
+enum CRStatus cr_token_set_ident (CRToken *a_this, CRString * a_ident) ;
+
+enum CRStatus cr_token_set_hash (CRToken *a_this, CRString *a_hash) ;
+
+enum CRStatus cr_token_set_rgb (CRToken *a_this, CRRgb *a_rgb) ;
+
+enum CRStatus cr_token_set_import_sym (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_page_sym (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_media_sym (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_font_face_sym (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_charset_sym (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_atkeyword (CRToken *a_this, CRString *a_atname) ;
+
+enum CRStatus cr_token_set_important_sym (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_ems (CRToken *a_this, CRNum *a_num) ;
+
+enum CRStatus cr_token_set_exs (CRToken *a_this, CRNum *a_num) ;
+
+enum CRStatus cr_token_set_length (CRToken *a_this, CRNum *a_num,
+ enum CRTokenExtraType a_et) ;
+
+enum CRStatus cr_token_set_angle (CRToken *a_this, CRNum *a_num,
+ enum CRTokenExtraType a_et) ;
+
+enum CRStatus cr_token_set_time (CRToken *a_this, CRNum *a_num,
+ enum CRTokenExtraType a_et) ;
+
+enum CRStatus cr_token_set_freq (CRToken *a_this, CRNum *a_num,
+ enum CRTokenExtraType a_et) ;
+
+enum CRStatus cr_token_set_dimen (CRToken *a_this, CRNum *a_num,
+ CRString *a_dim) ;
+
+enum CRStatus cr_token_set_percentage (CRToken *a_this, CRNum *a_num) ;
+
+enum CRStatus cr_token_set_number (CRToken *a_this, CRNum *a_num) ;
+
+enum CRStatus cr_token_set_uri (CRToken *a_this, CRString *a_uri) ;
+
+enum CRStatus cr_token_set_function (CRToken *a_this,
+ CRString *a_fun_name) ;
+
+enum CRStatus cr_token_set_bc (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_bo (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_po (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_pc (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_cbc (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_cbo (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_semicolon (CRToken *a_this) ;
+
+enum CRStatus cr_token_set_delim (CRToken *a_this, guint32 a_char) ;
+
+
+/*
+ enum CRStatus
+ cr_token_set_unicoderange (CRToken *a_this,
+ CRUnicodeRange *a_range) ;
+*/
+
+void
+cr_token_destroy (CRToken *a_this) ;
+
+
+G_END_DECLS
+
+#endif /*__CR_TOKEN_H__*/
diff --git a/src/3rdparty/libcroco/src/cr-utils.c b/src/3rdparty/libcroco/src/cr-utils.c
new file mode 100644
index 0000000..523362a
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-utils.c
@@ -0,0 +1,1330 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include "cr-utils.h"
+#include "cr-string.h"
+
+/**
+ *@file:
+ *Some misc utility functions used
+ *in the libcroco.
+ *Note that troughout this file I will
+ *refer to the CSS SPECIFICATIONS DOCUMENTATION
+ *written by the w3c guys. You can find that document
+ *at http://www.w3.org/TR/REC-CSS2/ .
+ */
+
+/****************************
+ *Encoding transformations and
+ *encoding helpers
+ ****************************/
+
+/*
+ *Here is the correspondence between the ucs-4 charactere codes
+ *and there matching utf-8 encoding pattern as dscribed by RFC 2279:
+ *
+ *UCS-4 range (hex.) UTF-8 octet sequence (binary)
+ *------------------ -----------------------------
+ *0000 0000-0000 007F 0xxxxxxx
+ *0000 0080-0000 07FF 110xxxxx 10xxxxxx
+ *0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
+ *0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ *0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+ *0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx
+ */
+
+/**
+ *Given an utf8 string buffer, calculates
+ *the length of this string if it was encoded
+ *in ucs4.
+ *@param a_in_start a pointer to the beginning of
+ *the input utf8 string.
+ *@param a_in_end a pointre to the end of the input
+ *utf8 string (points to the last byte of the buffer)
+ *@param a_len out parameter the calculated length.
+ *@return CR_OK upon successful completion, an error code
+ *otherwise.
+ */
+enum CRStatus
+cr_utils_utf8_str_len_as_ucs4 (const guchar * a_in_start,
+ const guchar * a_in_end, gulong * a_len)
+{
+ guchar *byte_ptr = NULL;
+ gint len = 0;
+
+ /*
+ *to store the final decoded
+ *unicode char
+ */
+ guint c = 0;
+
+ g_return_val_if_fail (a_in_start && a_in_end && a_len,
+ CR_BAD_PARAM_ERROR);
+ *a_len = 0;
+
+ for (byte_ptr = (guchar *) a_in_start;
+ byte_ptr <= a_in_end; byte_ptr++) {
+ gint nb_bytes_2_decode = 0;
+
+ if (*byte_ptr <= 0x7F) {
+ /*
+ *7 bits long char
+ *encoded over 1 byte:
+ * 0xxx xxxx
+ */
+ c = *byte_ptr;
+ nb_bytes_2_decode = 1;
+
+ } else if ((*byte_ptr & 0xE0) == 0xC0) {
+ /*
+ *up to 11 bits long char.
+ *encoded over 2 bytes:
+ *110x xxxx 10xx xxxx
+ */
+ c = *byte_ptr & 0x1F;
+ nb_bytes_2_decode = 2;
+
+ } else if ((*byte_ptr & 0xF0) == 0xE0) {
+ /*
+ *up to 16 bit long char
+ *encoded over 3 bytes:
+ *1110 xxxx 10xx xxxx 10xx xxxx
+ */
+ c = *byte_ptr & 0x0F;
+ nb_bytes_2_decode = 3;
+
+ } else if ((*byte_ptr & 0xF8) == 0xF0) {
+ /*
+ *up to 21 bits long char
+ *encoded over 4 bytes:
+ *1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
+ */
+ c = *byte_ptr & 0x7;
+ nb_bytes_2_decode = 4;
+
+ } else if ((*byte_ptr & 0xFC) == 0xF8) {
+ /*
+ *up to 26 bits long char
+ *encoded over 5 bytes.
+ *1111 10xx 10xx xxxx 10xx xxxx
+ *10xx xxxx 10xx xxxx
+ */
+ c = *byte_ptr & 3;
+ nb_bytes_2_decode = 5;
+
+ } else if ((*byte_ptr & 0xFE) == 0xFC) {
+ /*
+ *up to 31 bits long char
+ *encoded over 6 bytes:
+ *1111 110x 10xx xxxx 10xx xxxx
+ *10xx xxxx 10xx xxxx 10xx xxxx
+ */
+ c = *byte_ptr & 1;
+ nb_bytes_2_decode = 6;
+
+ } else {
+ /*
+ *BAD ENCODING
+ */
+ return CR_ENCODING_ERROR;
+ }
+
+ /*
+ *Go and decode the remaining byte(s)
+ *(if any) to get the current character.
+ */
+ for (; nb_bytes_2_decode > 1; nb_bytes_2_decode--) {
+ /*decode the next byte */
+ byte_ptr++;
+
+ /*byte pattern must be: 10xx xxxx */
+ if ((*byte_ptr & 0xC0) != 0x80) {
+ return CR_ENCODING_ERROR;
+ }
+
+ c = (c << 6) | (*byte_ptr & 0x3F);
+ }
+
+ len++;
+ }
+
+ *a_len = len;
+
+ return CR_OK;
+}
+
+/**
+ *Given an ucs4 string, this function
+ *returns the size (in bytes) this string
+ *would have occupied if it was encoded in utf-8.
+ *@param a_in_start a pointer to the beginning of the input
+ *buffer.
+ *@param a_in_end a pointer to the end of the input buffer.
+ *@param a_len out parameter. The computed length.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_utils_ucs4_str_len_as_utf8 (const guint32 * a_in_start,
+ const guint32 * a_in_end, gulong * a_len)
+{
+ gint len = 0;
+ guint32 *char_ptr = NULL;
+
+ g_return_val_if_fail (a_in_start && a_in_end && a_len,
+ CR_BAD_PARAM_ERROR);
+
+ for (char_ptr = (guint32 *) a_in_start;
+ char_ptr <= a_in_end; char_ptr++) {
+ if (*char_ptr <= 0x7F) {
+ /*the utf-8 char would take 1 byte */
+ len += 1;
+ } else if (*char_ptr <= 0x7FF) {
+ /*the utf-8 char would take 2 bytes */
+ len += 2;
+ } else if (*char_ptr <= 0xFFFF) {
+ len += 3;
+ } else if (*char_ptr <= 0x1FFFFF) {
+ len += 4;
+ } else if (*char_ptr <= 0x3FFFFFF) {
+ len += 5;
+ } else if (*char_ptr <= 0x7FFFFFFF) {
+ len += 6;
+ }
+ }
+
+ *a_len = len;
+ return CR_OK;
+}
+
+/**
+ *Given an ucsA string, this function
+ *returns the size (in bytes) this string
+ *would have occupied if it was encoded in utf-8.
+ *@param a_in_start a pointer to the beginning of the input
+ *buffer.
+ *@param a_in_end a pointer to the end of the input buffer.
+ *@param a_len out parameter. The computed length.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_utils_ucs1_str_len_as_utf8 (const guchar * a_in_start,
+ const guchar * a_in_end, gulong * a_len)
+{
+ gint len = 0;
+ guchar *char_ptr = NULL;
+
+ g_return_val_if_fail (a_in_start && a_in_end && a_len,
+ CR_BAD_PARAM_ERROR);
+
+ for (char_ptr = (guchar *) a_in_start;
+ char_ptr <= a_in_end; char_ptr++) {
+ if (*char_ptr <= 0x7F) {
+ /*the utf-8 char would take 1 byte */
+ len += 1;
+ } else {
+ /*the utf-8 char would take 2 bytes */
+ len += 2;
+ }
+ }
+
+ *a_len = len;
+ return CR_OK;
+}
+
+/**
+ *Converts an utf8 buffer into an ucs4 buffer.
+ *
+ *@param a_in the input utf8 buffer to convert.
+ *@param a_in_len in/out parameter. The size of the
+ *input buffer to convert. After return, this parameter contains
+ *the actual number of bytes consumed.
+ *@param a_out the output converted ucs4 buffer. Must be allocated by
+ *the caller.
+ *@param a_out_len in/out parameter. The size of the output buffer.
+ *If this size is actually smaller than the real needed size, the function
+ *just converts what it can and returns a success status. After return,
+ *this param points to the actual number of characters decoded.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_utils_utf8_to_ucs4 (const guchar * a_in,
+ gulong * a_in_len, guint32 * a_out, gulong * a_out_len)
+{
+ gulong in_len = 0,
+ out_len = 0,
+ in_index = 0,
+ out_index = 0;
+ enum CRStatus status = CR_OK;
+
+ /*
+ *to store the final decoded
+ *unicode char
+ */
+ guint c = 0;
+
+ g_return_val_if_fail (a_in && a_in_len
+ && a_out && a_out_len, CR_BAD_PARAM_ERROR);
+
+ if (*a_in_len < 1) {
+ status = CR_OK;
+ goto end;
+ }
+
+ in_len = *a_in_len;
+ out_len = *a_out_len;
+
+ for (in_index = 0, out_index = 0;
+ (in_index < in_len) && (out_index < out_len);
+ in_index++, out_index++) {
+ gint nb_bytes_2_decode = 0;
+
+ if (a_in[in_index] <= 0x7F) {
+ /*
+ *7 bits long char
+ *encoded over 1 byte:
+ * 0xxx xxxx
+ */
+ c = a_in[in_index];
+ nb_bytes_2_decode = 1;
+
+ } else if ((a_in[in_index] & 0xE0) == 0xC0) {
+ /*
+ *up to 11 bits long char.
+ *encoded over 2 bytes:
+ *110x xxxx 10xx xxxx
+ */
+ c = a_in[in_index] & 0x1F;
+ nb_bytes_2_decode = 2;
+
+ } else if ((a_in[in_index] & 0xF0) == 0xE0) {
+ /*
+ *up to 16 bit long char
+ *encoded over 3 bytes:
+ *1110 xxxx 10xx xxxx 10xx xxxx
+ */
+ c = a_in[in_index] & 0x0F;
+ nb_bytes_2_decode = 3;
+
+ } else if ((a_in[in_index] & 0xF8) == 0xF0) {
+ /*
+ *up to 21 bits long char
+ *encoded over 4 bytes:
+ *1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
+ */
+ c = a_in[in_index] & 0x7;
+ nb_bytes_2_decode = 4;
+
+ } else if ((a_in[in_index] & 0xFC) == 0xF8) {
+ /*
+ *up to 26 bits long char
+ *encoded over 5 bytes.
+ *1111 10xx 10xx xxxx 10xx xxxx
+ *10xx xxxx 10xx xxxx
+ */
+ c = a_in[in_index] & 3;
+ nb_bytes_2_decode = 5;
+
+ } else if ((a_in[in_index] & 0xFE) == 0xFC) {
+ /*
+ *up to 31 bits long char
+ *encoded over 6 bytes:
+ *1111 110x 10xx xxxx 10xx xxxx
+ *10xx xxxx 10xx xxxx 10xx xxxx
+ */
+ c = a_in[in_index] & 1;
+ nb_bytes_2_decode = 6;
+
+ } else {
+ /*BAD ENCODING */
+ goto end;
+ }
+
+ /*
+ *Go and decode the remaining byte(s)
+ *(if any) to get the current character.
+ */
+ for (; nb_bytes_2_decode > 1; nb_bytes_2_decode--) {
+ /*decode the next byte */
+ in_index++;
+
+ /*byte pattern must be: 10xx xxxx */
+ if ((a_in[in_index] & 0xC0) != 0x80) {
+ goto end;
+ }
+
+ c = (c << 6) | (a_in[in_index] & 0x3F);
+ }
+
+ /*
+ *The decoded ucs4 char is now
+ *in c.
+ */
+
+ /************************
+ *Some security tests
+ ***********************/
+
+ /*be sure c is a char */
+ if (c == 0xFFFF || c == 0xFFFE)
+ goto end;
+
+ /*be sure c is inferior to the max ucs4 char value */
+ if (c > 0x10FFFF)
+ goto end;
+
+ /*
+ *c must be less than UTF16 "lower surrogate begin"
+ *or higher than UTF16 "High surrogate end"
+ */
+ if (c >= 0xD800 && c <= 0xDFFF)
+ goto end;
+
+ /*Avoid characters that equals zero */
+ if (c == 0)
+ goto end;
+
+ a_out[out_index] = c;
+ }
+
+ end:
+ *a_out_len = out_index + 1;
+ *a_in_len = in_index + 1;
+
+ return status;
+}
+
+/**
+ *Reads a character from an utf8 buffer.
+ *Actually decode the next character code (unicode character code)
+ *and returns it.
+ *@param a_in the starting address of the utf8 buffer.
+ *@param a_in_len the length of the utf8 buffer.
+ *@param a_out output parameter. The resulting read char.
+ *@param a_consumed the number of the bytes consumed to
+ *decode the returned character code.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_utils_read_char_from_utf8_buf (const guchar * a_in,
+ gulong a_in_len,
+ guint32 * a_out, gulong * a_consumed)
+{
+ gulong in_index = 0,
+ nb_bytes_2_decode = 0;
+ enum CRStatus status = CR_OK;
+
+ /*
+ *to store the final decoded
+ *unicode char
+ */
+ guint32 c = 0;
+
+ g_return_val_if_fail (a_in && a_out && a_out
+ && a_consumed, CR_BAD_PARAM_ERROR);
+
+ if (a_in_len < 1) {
+ status = CR_OK;
+ goto end;
+ }
+
+ if (*a_in <= 0x7F) {
+ /*
+ *7 bits long char
+ *encoded over 1 byte:
+ * 0xxx xxxx
+ */
+ c = *a_in;
+ nb_bytes_2_decode = 1;
+
+ } else if ((*a_in & 0xE0) == 0xC0) {
+ /*
+ *up to 11 bits long char.
+ *encoded over 2 bytes:
+ *110x xxxx 10xx xxxx
+ */
+ c = *a_in & 0x1F;
+ nb_bytes_2_decode = 2;
+
+ } else if ((*a_in & 0xF0) == 0xE0) {
+ /*
+ *up to 16 bit long char
+ *encoded over 3 bytes:
+ *1110 xxxx 10xx xxxx 10xx xxxx
+ */
+ c = *a_in & 0x0F;
+ nb_bytes_2_decode = 3;
+
+ } else if ((*a_in & 0xF8) == 0xF0) {
+ /*
+ *up to 21 bits long char
+ *encoded over 4 bytes:
+ *1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
+ */
+ c = *a_in & 0x7;
+ nb_bytes_2_decode = 4;
+
+ } else if ((*a_in & 0xFC) == 0xF8) {
+ /*
+ *up to 26 bits long char
+ *encoded over 5 bytes.
+ *1111 10xx 10xx xxxx 10xx xxxx
+ *10xx xxxx 10xx xxxx
+ */
+ c = *a_in & 3;
+ nb_bytes_2_decode = 5;
+
+ } else if ((*a_in & 0xFE) == 0xFC) {
+ /*
+ *up to 31 bits long char
+ *encoded over 6 bytes:
+ *1111 110x 10xx xxxx 10xx xxxx
+ *10xx xxxx 10xx xxxx 10xx xxxx
+ */
+ c = *a_in & 1;
+ nb_bytes_2_decode = 6;
+
+ } else {
+ /*BAD ENCODING */
+ goto end;
+ }
+
+ if (nb_bytes_2_decode > a_in_len) {
+ status = CR_END_OF_INPUT_ERROR;
+ goto end;
+ }
+
+ /*
+ *Go and decode the remaining byte(s)
+ *(if any) to get the current character.
+ */
+ for (in_index = 1; in_index < nb_bytes_2_decode; in_index++) {
+ /*byte pattern must be: 10xx xxxx */
+ if ((a_in[in_index] & 0xC0) != 0x80) {
+ goto end;
+ }
+
+ c = (c << 6) | (a_in[in_index] & 0x3F);
+ }
+
+ /*
+ *The decoded ucs4 char is now
+ *in c.
+ */
+
+ /************************
+ *Some security tests
+ ***********************/
+
+ /*be sure c is a char */
+ if (c == 0xFFFF || c == 0xFFFE)
+ goto end;
+
+ /*be sure c is inferior to the max ucs4 char value */
+ if (c > 0x10FFFF)
+ goto end;
+
+ /*
+ *c must be less than UTF16 "lower surrogate begin"
+ *or higher than UTF16 "High surrogate end"
+ */
+ if (c >= 0xD800 && c <= 0xDFFF)
+ goto end;
+
+ /*Avoid characters that equals zero */
+ if (c == 0)
+ goto end;
+
+ *a_out = c;
+
+ end:
+ *a_consumed = nb_bytes_2_decode;
+
+ return status;
+}
+
+/**
+ *
+ */
+enum CRStatus
+cr_utils_utf8_str_len_as_ucs1 (const guchar * a_in_start,
+ const guchar * a_in_end, gulong * a_len)
+{
+ /*
+ *Note: this function can be made shorter
+ *but it considers all the cases of the utf8 encoding
+ *to ease further extensions ...
+ */
+
+ guchar *byte_ptr = NULL;
+ gint len = 0;
+
+ /*
+ *to store the final decoded
+ *unicode char
+ */
+ guint c = 0;
+
+ g_return_val_if_fail (a_in_start && a_in_end && a_len,
+ CR_BAD_PARAM_ERROR);
+ *a_len = 0;
+
+ for (byte_ptr = (guchar *) a_in_start;
+ byte_ptr <= a_in_end; byte_ptr++) {
+ gint nb_bytes_2_decode = 0;
+
+ if (*byte_ptr <= 0x7F) {
+ /*
+ *7 bits long char
+ *encoded over 1 byte:
+ * 0xxx xxxx
+ */
+ c = *byte_ptr;
+ nb_bytes_2_decode = 1;
+
+ } else if ((*byte_ptr & 0xE0) == 0xC0) {
+ /*
+ *up to 11 bits long char.
+ *encoded over 2 bytes:
+ *110x xxxx 10xx xxxx
+ */
+ c = *byte_ptr & 0x1F;
+ nb_bytes_2_decode = 2;
+
+ } else if ((*byte_ptr & 0xF0) == 0xE0) {
+ /*
+ *up to 16 bit long char
+ *encoded over 3 bytes:
+ *1110 xxxx 10xx xxxx 10xx xxxx
+ */
+ c = *byte_ptr & 0x0F;
+ nb_bytes_2_decode = 3;
+
+ } else if ((*byte_ptr & 0xF8) == 0xF0) {
+ /*
+ *up to 21 bits long char
+ *encoded over 4 bytes:
+ *1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
+ */
+ c = *byte_ptr & 0x7;
+ nb_bytes_2_decode = 4;
+
+ } else if ((*byte_ptr & 0xFC) == 0xF8) {
+ /*
+ *up to 26 bits long char
+ *encoded over 5 bytes.
+ *1111 10xx 10xx xxxx 10xx xxxx
+ *10xx xxxx 10xx xxxx
+ */
+ c = *byte_ptr & 3;
+ nb_bytes_2_decode = 5;
+
+ } else if ((*byte_ptr & 0xFE) == 0xFC) {
+ /*
+ *up to 31 bits long char
+ *encoded over 6 bytes:
+ *1111 110x 10xx xxxx 10xx xxxx
+ *10xx xxxx 10xx xxxx 10xx xxxx
+ */
+ c = *byte_ptr & 1;
+ nb_bytes_2_decode = 6;
+
+ } else {
+ /*
+ *BAD ENCODING
+ */
+ return CR_ENCODING_ERROR;
+ }
+
+ /*
+ *Go and decode the remaining byte(s)
+ *(if any) to get the current character.
+ */
+ for (; nb_bytes_2_decode > 1; nb_bytes_2_decode--) {
+ /*decode the next byte */
+ byte_ptr++;
+
+ /*byte pattern must be: 10xx xxxx */
+ if ((*byte_ptr & 0xC0) != 0x80) {
+ return CR_ENCODING_ERROR;
+ }
+
+ c = (c << 6) | (*byte_ptr & 0x3F);
+ }
+
+ /*
+ *The decoded ucs4 char is now
+ *in c.
+ */
+
+ if (c <= 0xFF) { /*Add other conditions to support
+ *other char sets (ucs2, ucs3, ucs4).
+ */
+ len++;
+ } else {
+ /*the char is too long to fit
+ *into the supposed charset len.
+ */
+ return CR_ENCODING_ERROR;
+ }
+ }
+
+ *a_len = len;
+
+ return CR_OK;
+}
+
+/**
+ *Converts an utf8 string into an ucs4 string.
+ *@param a_in the input string to convert.
+ *@param a_in_len in/out parameter. The length of the input
+ *string. After return, points to the actual number of bytes
+ *consumed. This can be useful to debug the input stream in case
+ *of encoding error.
+ *@param a_out out parameter. Points to the output string. It is allocated
+ *by this function and must be freed by the caller.
+ *@param a_out_len out parameter. The length of the output string.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ *
+ */
+enum CRStatus
+cr_utils_utf8_str_to_ucs4 (const guchar * a_in,
+ gulong * a_in_len,
+ guint32 ** a_out, gulong * a_out_len)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_in && a_in_len
+ && a_out && a_out_len, CR_BAD_PARAM_ERROR);
+
+ status = cr_utils_utf8_str_len_as_ucs4 (a_in,
+ &a_in[*a_in_len - 1],
+ a_out_len);
+
+ g_return_val_if_fail (status == CR_OK, status);
+
+ *a_out = (guint32 *) g_malloc0 (*a_out_len * sizeof (guint32));
+
+ status = cr_utils_utf8_to_ucs4 (a_in, a_in_len, *a_out, a_out_len);
+
+ return status;
+}
+
+/**
+ *Converts an ucs4 buffer into an utf8 buffer.
+ *
+ *@param a_in the input ucs4 buffer to convert.
+ *@param a_in_len in/out parameter. The size of the
+ *input buffer to convert. After return, this parameter contains
+ *the actual number of characters consumed.
+ *@param a_out the output converted utf8 buffer. Must be allocated by
+ *the caller.
+ *@param a_out_len in/out parameter. The size of the output buffer.
+ *If this size is actually smaller than the real needed size, the function
+ *just converts what it can and returns a success status. After return,
+ *this param points to the actual number of bytes in the buffer.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_utils_ucs4_to_utf8 (const guint32 * a_in,
+ gulong * a_in_len, guchar * a_out, gulong * a_out_len)
+{
+ gulong in_len = 0,
+ in_index = 0,
+ out_index = 0;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_in && a_in_len && a_out && a_out_len,
+ CR_BAD_PARAM_ERROR);
+
+ if (*a_in_len < 1) {
+ status = CR_OK;
+ goto end;
+ }
+
+ in_len = *a_in_len;
+
+ for (in_index = 0; in_index < in_len; in_index++) {
+ /*
+ *FIXME: return whenever we encounter forbidden char values.
+ */
+
+ if (a_in[in_index] <= 0x7F) {
+ a_out[out_index] = a_in[in_index];
+ out_index++;
+ } else if (a_in[in_index] <= 0x7FF) {
+ a_out[out_index] = (0xC0 | (a_in[in_index] >> 6));
+ a_out[out_index + 1] =
+ (0x80 | (a_in[in_index] & 0x3F));
+ out_index += 2;
+ } else if (a_in[in_index] <= 0xFFFF) {
+ a_out[out_index] = (0xE0 | (a_in[in_index] >> 12));
+ a_out[out_index + 1] =
+ (0x80 | ((a_in[in_index] >> 6) & 0x3F));
+ a_out[out_index + 2] =
+ (0x80 | (a_in[in_index] & 0x3F));
+ out_index += 3;
+ } else if (a_in[in_index] <= 0x1FFFFF) {
+ a_out[out_index] = (0xF0 | (a_in[in_index] >> 18));
+ a_out[out_index + 1]
+ = (0x80 | ((a_in[in_index] >> 12) & 0x3F));
+ a_out[out_index + 2]
+ = (0x80 | ((a_in[in_index] >> 6) & 0x3F));
+ a_out[out_index + 3]
+ = (0x80 | (a_in[in_index] & 0x3F));
+ out_index += 4;
+ } else if (a_in[in_index] <= 0x3FFFFFF) {
+ a_out[out_index] = (0xF8 | (a_in[in_index] >> 24));
+ a_out[out_index + 1] =
+ (0x80 | (a_in[in_index] >> 18));
+ a_out[out_index + 2]
+ = (0x80 | ((a_in[in_index] >> 12) & 0x3F));
+ a_out[out_index + 3]
+ = (0x80 | ((a_in[in_index] >> 6) & 0x3F));
+ a_out[out_index + 4]
+ = (0x80 | (a_in[in_index] & 0x3F));
+ out_index += 5;
+ } else if (a_in[in_index] <= 0x7FFFFFFF) {
+ a_out[out_index] = (0xFC | (a_in[in_index] >> 30));
+ a_out[out_index + 1] =
+ (0x80 | (a_in[in_index] >> 24));
+ a_out[out_index + 2]
+ = (0x80 | ((a_in[in_index] >> 18) & 0x3F));
+ a_out[out_index + 3]
+ = (0x80 | ((a_in[in_index] >> 12) & 0x3F));
+ a_out[out_index + 4]
+ = (0x80 | ((a_in[in_index] >> 6) & 0x3F));
+ a_out[out_index + 4]
+ = (0x80 | (a_in[in_index] & 0x3F));
+ out_index += 6;
+ } else {
+ status = CR_ENCODING_ERROR;
+ goto end;
+ }
+ } /*end for */
+
+ end:
+ *a_in_len = in_index + 1;
+ *a_out_len = out_index + 1;
+
+ return status;
+}
+
+/**
+ *Converts an ucs4 string into an utf8 string.
+ *@param a_in the input string to convert.
+ *@param a_in_len in/out parameter. The length of the input
+ *string. After return, points to the actual number of characters
+ *consumed. This can be useful to debug the input string in case
+ *of encoding error.
+ *@param a_out out parameter. Points to the output string. It is allocated
+ *by this function and must be freed by the caller.
+ *@param a_out_len out parameter. The length (in bytes) of the output string.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_utils_ucs4_str_to_utf8 (const guint32 * a_in,
+ gulong * a_in_len,
+ guchar ** a_out, gulong * a_out_len)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_in && a_in_len && a_out
+ && a_out_len, CR_BAD_PARAM_ERROR);
+
+ status = cr_utils_ucs4_str_len_as_utf8 (a_in,
+ &a_in[*a_out_len - 1],
+ a_out_len);
+
+ g_return_val_if_fail (status == CR_OK, status);
+
+ status = cr_utils_ucs4_to_utf8 (a_in, a_in_len, *a_out, a_out_len);
+
+ return status;
+}
+
+/**
+ *Converts an ucs1 buffer into an utf8 buffer.
+ *The caller must know the size of the resulting buffer and
+ *allocate it prior to calling this function.
+ *
+ *@param a_in the input ucs1 buffer.
+ *
+ *@param a_in_len in/out parameter. The length of the input buffer.
+ *After return, points to the number of bytes actually consumed even
+ *in case of encoding error.
+ *
+ *@param a_out out parameter. The output utf8 converted buffer.
+ *
+ *@param a_out_len in/out parameter. The size of the output buffer.
+ *If the output buffer size is shorter than the actual needed size,
+ *this function just convert what it can.
+ *
+ *@return CR_OK upon successful completion, an error code otherwise.
+ *
+ */
+enum CRStatus
+cr_utils_ucs1_to_utf8 (const guchar * a_in,
+ gulong * a_in_len, guchar * a_out, gulong * a_out_len)
+{
+ gulong out_index = 0,
+ in_index = 0,
+ in_len = 0,
+ out_len = 0;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_in && a_in_len
+ && a_out_len,
+ CR_BAD_PARAM_ERROR);
+
+ if (*a_in_len == 0) {
+ *a_out_len = 0 ;
+ return status;
+ }
+ g_return_val_if_fail (a_out, CR_BAD_PARAM_ERROR) ;
+
+ in_len = *a_in_len;
+ out_len = *a_out_len;
+
+ for (in_index = 0, out_index = 0;
+ (in_index < in_len) && (out_index < out_len); in_index++) {
+ /*
+ *FIXME: return whenever we encounter forbidden char values.
+ */
+
+ if (a_in[in_index] <= 0x7F) {
+ a_out[out_index] = a_in[in_index];
+ out_index++;
+ } else {
+ a_out[out_index] = (0xC0 | (a_in[in_index] >> 6));
+ a_out[out_index + 1] =
+ (0x80 | (a_in[in_index] & 0x3F));
+ out_index += 2;
+ }
+ } /*end for */
+
+ *a_in_len = in_index;
+ *a_out_len = out_index;
+
+ return status;
+}
+
+/**
+ *Converts an ucs1 string into an utf8 string.
+ *@param a_in_start the beginning of the input string to convert.
+ *@param a_in_end the end of the input string to convert.
+ *@param a_out out parameter. The converted string.
+ *@param a_out out parameter. The length of the converted string.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ *
+ */
+enum CRStatus
+cr_utils_ucs1_str_to_utf8 (const guchar * a_in,
+ gulong * a_in_len,
+ guchar ** a_out, gulong * a_out_len)
+{
+ gulong out_len = 0;
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_in && a_in_len && a_out
+ && a_out_len, CR_BAD_PARAM_ERROR);
+
+ if (*a_in_len < 1) {
+ *a_out_len = 0;
+ *a_out = NULL;
+ return CR_OK;
+ }
+
+ status = cr_utils_ucs1_str_len_as_utf8 (a_in, &a_in[*a_in_len - 1],
+ &out_len);
+
+ g_return_val_if_fail (status == CR_OK, status);
+
+ *a_out = (guchar *) g_malloc0 (out_len);
+
+ status = cr_utils_ucs1_to_utf8 (a_in, a_in_len, *a_out, &out_len);
+
+ *a_out_len = out_len;
+
+ return status;
+}
+
+/**
+ *Converts an utf8 buffer into an ucs1 buffer.
+ *The caller must know the size of the resulting
+ *converted buffer, and allocated it prior to calling this
+ *function.
+ *
+ *@param a_in the input utf8 buffer to convert.
+ *
+ *@param a_in_len in/out parameter. The size of the input utf8 buffer.
+ *After return, points to the number of bytes consumed
+ *by the function even in case of encoding error.
+ *
+ *@param a_out out parameter. Points to the resulting buffer.
+ *Must be allocated by the caller. If the size of a_out is shorter
+ *than its required size, this function converts what it can and return
+ *a successful status.
+ *
+ *@param a_out_len in/out parameter. The size of the output buffer.
+ *After return, points to the number of bytes consumed even in case of
+ *encoding error.
+ *
+ *@return CR_OK upon successful completion, an error code otherwise.
+ */
+enum CRStatus
+cr_utils_utf8_to_ucs1 (const guchar * a_in,
+ gulong * a_in_len, guchar * a_out, gulong * a_out_len)
+{
+ gulong in_index = 0,
+ out_index = 0,
+ in_len = 0,
+ out_len = 0;
+ enum CRStatus status = CR_OK;
+
+ /*
+ *to store the final decoded
+ *unicode char
+ */
+ guint32 c = 0;
+
+ g_return_val_if_fail (a_in && a_in_len
+ && a_out && a_out_len, CR_BAD_PARAM_ERROR);
+
+ if (*a_in_len < 1) {
+ goto end;
+ }
+
+ in_len = *a_in_len;
+ out_len = *a_out_len;
+
+ for (in_index = 0, out_index = 0;
+ (in_index < in_len) && (out_index < out_len);
+ in_index++, out_index++) {
+ gint nb_bytes_2_decode = 0;
+
+ if (a_in[in_index] <= 0x7F) {
+ /*
+ *7 bits long char
+ *encoded over 1 byte:
+ * 0xxx xxxx
+ */
+ c = a_in[in_index];
+ nb_bytes_2_decode = 1;
+
+ } else if ((a_in[in_index] & 0xE0) == 0xC0) {
+ /*
+ *up to 11 bits long char.
+ *encoded over 2 bytes:
+ *110x xxxx 10xx xxxx
+ */
+ c = a_in[in_index] & 0x1F;
+ nb_bytes_2_decode = 2;
+
+ } else if ((a_in[in_index] & 0xF0) == 0xE0) {
+ /*
+ *up to 16 bit long char
+ *encoded over 3 bytes:
+ *1110 xxxx 10xx xxxx 10xx xxxx
+ */
+ c = a_in[in_index] & 0x0F;
+ nb_bytes_2_decode = 3;
+
+ } else if ((a_in[in_index] & 0xF8) == 0xF0) {
+ /*
+ *up to 21 bits long char
+ *encoded over 4 bytes:
+ *1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
+ */
+ c = a_in[in_index] & 0x7;
+ nb_bytes_2_decode = 4;
+
+ } else if ((a_in[in_index] & 0xFC) == 0xF8) {
+ /*
+ *up to 26 bits long char
+ *encoded over 5 bytes.
+ *1111 10xx 10xx xxxx 10xx xxxx
+ *10xx xxxx 10xx xxxx
+ */
+ c = a_in[in_index] & 3;
+ nb_bytes_2_decode = 5;
+
+ } else if ((a_in[in_index] & 0xFE) == 0xFC) {
+ /*
+ *up to 31 bits long char
+ *encoded over 6 bytes:
+ *1111 110x 10xx xxxx 10xx xxxx
+ *10xx xxxx 10xx xxxx 10xx xxxx
+ */
+ c = a_in[in_index] & 1;
+ nb_bytes_2_decode = 6;
+
+ } else {
+ /*BAD ENCODING */
+ status = CR_ENCODING_ERROR;
+ goto end;
+ }
+
+ /*
+ *Go and decode the remaining byte(s)
+ *(if any) to get the current character.
+ */
+ if (in_index + nb_bytes_2_decode - 1 >= in_len) {
+ goto end;
+ }
+
+ for (; nb_bytes_2_decode > 1; nb_bytes_2_decode--) {
+ /*decode the next byte */
+ in_index++;
+
+ /*byte pattern must be: 10xx xxxx */
+ if ((a_in[in_index] & 0xC0) != 0x80) {
+ status = CR_ENCODING_ERROR;
+ goto end;
+ }
+
+ c = (c << 6) | (a_in[in_index] & 0x3F);
+ }
+
+ /*
+ *The decoded ucs4 char is now
+ *in c.
+ */
+
+ if (c > 0xFF) {
+ status = CR_ENCODING_ERROR;
+ goto end;
+ }
+
+ a_out[out_index] = c;
+ }
+
+ end:
+ *a_out_len = out_index;
+ *a_in_len = in_index;
+
+ return status;
+}
+
+/**
+ *Converts an utf8 buffer into an
+ *ucs1 buffer.
+ *@param a_in_start the start of the input buffer.
+ *@param a_in_end the end of the input buffer.
+ *@param a_out out parameter. The resulting converted ucs4 buffer.
+ *Must be freed by the caller.
+ *@param a_out_len out parameter. The length of the converted buffer.
+ *@return CR_OK upon successful completion, an error code otherwise.
+ *Note that out parameters are valid if and only if this function
+ *returns CR_OK.
+ */
+enum CRStatus
+cr_utils_utf8_str_to_ucs1 (const guchar * a_in,
+ gulong * a_in_len,
+ guchar ** a_out, gulong * a_out_len)
+{
+ enum CRStatus status = CR_OK;
+
+ g_return_val_if_fail (a_in && a_in_len
+ && a_out && a_out_len, CR_BAD_PARAM_ERROR);
+
+ if (*a_in_len < 1) {
+ *a_out_len = 0;
+ *a_out = NULL;
+ return CR_OK;
+ }
+
+ status = cr_utils_utf8_str_len_as_ucs4 (a_in, &a_in[*a_in_len - 1],
+ a_out_len);
+
+ g_return_val_if_fail (status == CR_OK, status);
+
+ *a_out = (guchar *) g_malloc0 (*a_out_len * sizeof (guint32));
+
+ status = cr_utils_utf8_to_ucs1 (a_in, a_in_len, *a_out, a_out_len);
+ return status;
+}
+
+/*****************************************
+ *CSS basic types identification utilities
+ *****************************************/
+
+/**
+ *Returns TRUE if a_char is a white space as
+ *defined in the css spec in chap 4.1.1.
+ *
+ *white-space ::= ' '| \t|\r|\n|\f
+ *
+ *@param a_char the character to test.
+ *return TRUE if is a white space, false otherwise.
+ */
+gboolean
+cr_utils_is_white_space (guint32 a_char)
+{
+ switch (a_char) {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ case '\f':
+ return TRUE;
+ break;
+ default:
+ return FALSE;
+ }
+}
+
+/**
+ *Returns true if the character is a newline
+ *as defined in the css spec in the chap 4.1.1.
+ *
+ *nl ::= \n|\r\n|\r|\f
+ *
+ *@param a_char the character to test.
+ *@return TRUE if the character is a newline, FALSE otherwise.
+ */
+gboolean
+cr_utils_is_newline (guint32 a_char)
+{
+ switch (a_char) {
+ case '\n':
+ case '\r':
+ case '\f':
+ return TRUE;
+ break;
+ default:
+ return FALSE;
+ }
+}
+
+/**
+ *returns TRUE if the char is part of an hexa num char:
+ *i.e hexa_char ::= [0-9A-F]
+ */
+gboolean
+cr_utils_is_hexa_char (guint32 a_char)
+{
+ if ((a_char >= '0' && a_char <= '9')
+ || (a_char >= 'A' && a_char <= 'F')) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ *Returns true if the character is a nonascii
+ *character (as defined in the css spec chap 4.1.1):
+ *
+ *nonascii ::= [^\0-\177]
+ *
+ *@param a_char the character to test.
+ *@return TRUE if the character is a nonascii char,
+ *FALSE otherwise.
+ */
+gboolean
+cr_utils_is_nonascii (guint32 a_char)
+{
+ if (a_char <= 177) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ *Dumps a character a_nb times on a file.
+ *@param a_char the char to dump
+ *@param a_fp the destination file pointer
+ *@param a_nb the number of times a_char is to be dumped.
+ */
+void
+cr_utils_dump_n_chars (guchar a_char, FILE * a_fp, glong a_nb)
+{
+ glong i = 0;
+
+ for (i = 0; i < a_nb; i++) {
+ fprintf (a_fp, "%c", a_char);
+ }
+}
+
+void
+cr_utils_dump_n_chars2 (guchar a_char, GString * a_string, glong a_nb)
+{
+ glong i = 0;
+
+ g_return_if_fail (a_string);
+
+ for (i = 0; i < a_nb; i++) {
+ g_string_append_printf (a_string, "%c", a_char);
+ }
+}
+
+/**
+ *Duplicates a list of GString instances.
+ *@return the duplicated list of GString instances or NULL if
+ *something bad happened.
+ *@param a_list_of_strings the list of strings to be duplicated.
+ */
+GList *
+cr_utils_dup_glist_of_string (GList const * a_list_of_strings)
+{
+ GList const *cur = NULL;
+ GList *result = NULL;
+
+ g_return_val_if_fail (a_list_of_strings, NULL);
+
+ for (cur = a_list_of_strings; cur; cur = cur->next) {
+ GString *str = NULL;
+
+ str = g_string_new_len (((GString *) cur->data)->str,
+ ((GString *) cur->data)->len);
+ if (str)
+ result = g_list_append (result, str);
+ }
+
+ return result;
+}
+
+/**
+ *Duplicate a GList where the GList::data is a CRString.
+ *@param a_list_of_strings the list to duplicate
+ *@return the duplicated list, or NULL if something bad
+ *happened.
+ */
+GList *
+cr_utils_dup_glist_of_cr_string (GList const * a_list_of_strings)
+{
+ GList const *cur = NULL;
+ GList *result = NULL;
+
+ g_return_val_if_fail (a_list_of_strings, NULL);
+
+ for (cur = a_list_of_strings; cur; cur = cur->next) {
+ CRString *str = NULL;
+
+ str = cr_string_dup ((CRString const *) cur->data) ;
+ if (str)
+ result = g_list_append (result, str);
+ }
+
+ return result;
+}
diff --git a/src/3rdparty/libcroco/src/cr-utils.h b/src/3rdparty/libcroco/src/cr-utils.h
new file mode 100644
index 0000000..cff9c80
--- /dev/null
+++ b/src/3rdparty/libcroco/src/cr-utils.h
@@ -0,0 +1,245 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * Look at file COPYRIGHTS for copyright information
+ */
+
+#ifndef __CR_DEFS_H__
+#define __CR_DEFS_H__
+
+#include <stdio.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+/**
+ *@file
+ *The Croco library basic types definitions
+ *And global definitions.
+ */
+
+/**
+ *The status type returned
+ *by the methods of the croco library.
+ */
+enum CRStatus {
+ CR_OK,
+ CR_BAD_PARAM_ERROR,
+ CR_INSTANCIATION_FAILED_ERROR,
+ CR_UNKNOWN_TYPE_ERROR,
+ CR_UNKNOWN_PROP_ERROR,
+ CR_UNKNOWN_PROP_VAL_ERROR,
+ CR_UNEXPECTED_POSITION_SCHEME,
+ CR_START_OF_INPUT_ERROR,
+ CR_END_OF_INPUT_ERROR,
+ CR_OUTPUT_TOO_SHORT_ERROR,
+ CR_INPUT_TOO_SHORT_ERROR,
+ CR_OUT_OF_BOUNDS_ERROR,
+ CR_EMPTY_PARSER_INPUT_ERROR,
+ CR_ENCODING_ERROR,
+ CR_ENCODING_NOT_FOUND_ERROR,
+ CR_PARSING_ERROR,
+ CR_SYNTAX_ERROR,
+ CR_NO_ROOT_NODE_ERROR,
+ CR_NO_TOKEN,
+ CR_OUT_OF_MEMORY_ERROR,
+ CR_PSEUDO_CLASS_SEL_HANDLER_NOT_FOUND_ERROR,
+ CR_BAD_PSEUDO_CLASS_SEL_HANDLER_ERROR,
+ CR_ERROR,
+ CR_FILE_NOT_FOUND_ERROR,
+ CR_VALUE_NOT_FOUND_ERROR
+} ;
+
+/**
+ *Values used by
+ *cr_input_seek_position() ;
+ */
+enum CRSeekPos {
+ CR_SEEK_CUR,
+ CR_SEEK_BEGIN,
+ CR_SEEK_END
+} ;
+
+/**
+ *Encoding values.
+ */
+enum CREncoding
+{
+ CR_UCS_4 = 1/*Must be not NULL*/,
+ CR_UCS_1,
+ CR_ISO_8859_1,
+ CR_ASCII,
+ CR_UTF_8,
+ CR_UTF_16,
+ CR_AUTO/*should be the last one*/
+} ;
+
+
+
+
+#define CROCO_LOG_DOMAIN "LIBCROCO"
+
+#ifdef __GNUC__
+#define cr_utils_trace(a_log_level, a_msg) \
+g_log (CROCO_LOG_DOMAIN, \
+ G_LOG_LEVEL_CRITICAL, \
+ "file %s: line %d (%s): %s\n", \
+ __FILE__, \
+ __LINE__, \
+ __PRETTY_FUNCTION__, \
+ a_msg)
+#else /*__GNUC__*/
+
+#define cr_utils_trace(a_log_level, a_msg) \
+g_log (CROCO_LOG_DOMAIN, \
+ G_LOG_LEVEL_CRITICAL, \
+ "file %s: line %d: %s\n", \
+ __FILE__, \
+ __LINE__, \
+ a_msg)
+#endif
+
+/**
+ *Traces an info message.
+ *The file, line and enclosing function
+ *of the message will be automatically
+ *added to the message.
+ *@param a_msg the msg to trace.
+ */
+#define cr_utils_trace_info(a_msg) \
+cr_utils_trace (G_LOG_LEVEL_INFO, a_msg)
+
+/**
+ *Trace a debug message.
+ *The file, line and enclosing function
+ *of the message will be automatically
+ *added to the message.
+ *@param a_msg the msg to trace.
+ */
+#define cr_utils_trace_debug(a_msg) \
+cr_utils_trace (G_LOG_LEVEL_DEBUG, a_msg) ;
+
+
+/****************************
+ *Encoding transformations and
+ *encoding helpers
+ ****************************/
+
+enum CRStatus
+cr_utils_read_char_from_utf8_buf (const guchar * a_in, gulong a_in_len,
+ guint32 *a_out, gulong *a_consumed) ;
+
+enum CRStatus
+cr_utils_ucs1_to_utf8 (const guchar *a_in, gulong *a_in_len,
+ guchar *a_out, gulong *a_out_len) ;
+
+enum CRStatus
+cr_utils_utf8_to_ucs1 (const guchar * a_in, gulong * a_in_len,
+ guchar *a_out, gulong *a_out_len) ;
+
+enum CRStatus
+cr_utils_ucs4_to_utf8 (const guint32 *a_in, gulong *a_in_len,
+ guchar *a_out, gulong *a_out_len) ;
+
+enum CRStatus
+cr_utils_utf8_str_len_as_ucs4 (const guchar *a_in_start,
+ const guchar *a_in_end,
+ gulong *a_len) ;
+enum CRStatus
+cr_utils_ucs1_str_len_as_utf8 (const guchar *a_in_start,
+ const guchar *a_in_end,
+ gulong *a_len) ;
+enum CRStatus
+cr_utils_utf8_str_len_as_ucs1 (const guchar *a_in_start,
+ const guchar *a_in_end,
+ gulong *a_len) ;
+enum CRStatus
+cr_utils_ucs4_str_len_as_utf8 (const guint32 *a_in_start,
+ const guint32 *a_in_end,
+ gulong *a_len) ;
+
+enum CRStatus
+cr_utils_ucs1_str_to_utf8 (const guchar *a_in_start,
+ gulong *a_in_len,
+ guchar **a_out,
+ gulong *a_len) ;
+
+enum CRStatus
+cr_utils_utf8_str_to_ucs1 (const guchar * a_in_start,
+ gulong * a_in_len,
+ guchar **a_out,
+ gulong *a_out_len) ;
+
+enum CRStatus
+cr_utils_utf8_to_ucs4 (const guchar * a_in,
+ gulong * a_in_len,
+ guint32 *a_out, gulong *a_out_len) ;
+
+enum CRStatus
+cr_utils_ucs4_str_to_utf8 (const guint32 *a_in,
+ gulong *a_in_len,
+ guchar **a_out, gulong *a_out_len) ;
+
+enum CRStatus
+cr_utils_utf8_str_to_ucs4 (const guchar * a_in,
+ gulong *a_in_len,
+ guint32 **a_out,
+ gulong *a_out_len) ;
+
+
+/*****************************************
+ *CSS basic types identification utilities
+ *****************************************/
+
+gboolean
+cr_utils_is_newline (guint32 a_char) ;
+
+gboolean
+cr_utils_is_white_space (guint32 a_char) ;
+
+gboolean
+cr_utils_is_nonascii (guint32 a_char) ;
+
+gboolean
+cr_utils_is_hexa_char (guint32 a_char) ;
+
+
+/**********************************
+ *Miscellaneous utility functions
+ ***********************************/
+
+void
+cr_utils_dump_n_chars (guchar a_char,
+ FILE *a_fp,
+ glong a_nb) ;
+
+void
+cr_utils_dump_n_chars2 (guchar a_char,
+ GString *a_string,
+ glong a_nb) ;
+GList *
+cr_utils_dup_glist_of_string (GList const *a_list) ;
+
+GList *
+cr_utils_dup_glist_of_cr_string (GList const * a_list_of_strings) ;
+
+G_END_DECLS
+
+#endif /*__CR_DEFS_H__*/
diff --git a/src/3rdparty/libcroco/src/libcroco-config.h.in b/src/3rdparty/libcroco/src/libcroco-config.h.in
new file mode 100644
index 0000000..7f2e217
--- /dev/null
+++ b/src/3rdparty/libcroco/src/libcroco-config.h.in
@@ -0,0 +1,17 @@
+#ifndef LIBCROCO_VERSION_NUMBER
+#define LIBCROCO_VERSION_NUMBER @LIBCROCO_VERSION_NUMBER@
+#endif
+
+#ifndef LIBCROCO_VERSION
+#define LIBCROCO_VERSION "@LIBCROCO_VERSION@"
+#endif
+
+#ifndef G_DISABLE_CHECKS
+#if @G_DISABLE_CHECKS@
+#define G_DISABLE_CHECKS @G_DISABLE_CHECKS@
+#endif
+#endif
+
+#ifndef CROCO_HAVE_LIBXML2
+#define CROCO_HAVE_LIBXML2 (1)
+#endif
diff --git a/src/3rdparty/libcroco/src/libcroco.h b/src/3rdparty/libcroco/src/libcroco.h
new file mode 100644
index 0000000..eabc596
--- /dev/null
+++ b/src/3rdparty/libcroco/src/libcroco.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef __LIBCROCO_H__
+#define __LIBCROCO_H__
+
+#include "libcroco-config.h"
+
+#include "cr-utils.h"
+#include "cr-pseudo.h"
+#include "cr-term.h"
+#include "cr-attr-sel.h"
+#include "cr-simple-sel.h"
+#include "cr-selector.h"
+#include "cr-enc-handler.h"
+#include "cr-doc-handler.h"
+#include "cr-input.h"
+#include "cr-parser.h"
+#include "cr-statement.h"
+#include "cr-stylesheet.h"
+#include "cr-om-parser.h"
+#include "cr-prop-list.h"
+#include "cr-sel-eng.h"
+#include "cr-style.h"
+#include "cr-string.h"
+
+#endif /*__LIBCROCO_H__*/
diff --git a/src/3rdparty/libcroco/src/libcroco.symbols b/src/3rdparty/libcroco/src/libcroco.symbols
new file mode 100644
index 0000000..c201652
--- /dev/null
+++ b/src/3rdparty/libcroco/src/libcroco.symbols
@@ -0,0 +1,538 @@
+;This file is part of The Croco Library
+;This program is free software; you can redistribute it and/or
+;modify it under the terms of version 2.1 of the GNU Lesser General Public
+;License as published by the Free Software Foundation.
+
+;This program is distributed in the hope that it will be useful,
+;but WITHOUT ANY WARRANTY; without even the implied warranty of
+;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;GNU General Public License for more details.
+
+;You should have received a copy of the GNU Lesser General Public License
+;along with this program; if not, write to the Free Software
+;Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+;USA
+
+;Author: Fan, Chun-wei
+;See COPYRIGHTS file for copyright information.
+
+;----------------------------
+;libcroco/cr-additional-sel.h
+;----------------------------
+cr_additional_sel_append
+cr_additional_sel_destroy
+cr_additional_sel_dump
+cr_additional_sel_new
+cr_additional_sel_new_with_type
+cr_additional_sel_one_to_string
+cr_additional_sel_prepend
+cr_additional_sel_set_attr_sel
+cr_additional_sel_set_class_name
+cr_additional_sel_set_id_name
+cr_additional_sel_set_pseudo
+cr_additional_sel_to_string
+
+;----------------------
+;libcroco/cr-attr-sel.h
+;----------------------
+cr_attr_sel_append_attr_sel
+cr_attr_sel_destroy
+cr_attr_sel_dump
+cr_attr_sel_new
+cr_attr_sel_prepend_attr_sel
+cr_attr_sel_to_string
+
+;---------------------
+;libcroco/cr-cascade.h
+;---------------------
+cr_cascade_destroy
+cr_cascade_get_sheet
+cr_cascade_new
+cr_cascade_ref
+cr_cascade_set_sheet
+cr_cascade_unref
+
+;-------------------------
+;libcroco/cr-declaration.h
+;-------------------------
+cr_declaration_append
+cr_declaration_append2
+cr_declaration_destroy
+cr_declaration_dump
+cr_declaration_dump_one
+cr_declaration_get_by_prop_name
+cr_declaration_get_from_list
+cr_declaration_list_to_string
+cr_declaration_list_to_string2
+cr_declaration_new
+cr_declaration_nr_props
+cr_declaration_parse_from_buf
+cr_declaration_parse_list_from_buf
+cr_declaration_prepend
+cr_declaration_ref
+cr_declaration_to_string
+cr_declaration_unlink
+cr_declaration_unref
+
+;-------------------------
+;libcroco/cr-doc-handler.h
+;-------------------------
+cr_doc_handler_associate_a_parser
+cr_doc_handler_destroy
+cr_doc_handler_get_ctxt
+cr_doc_handler_get_result
+cr_doc_handler_new
+cr_doc_handler_ref
+cr_doc_handler_set_ctxt
+cr_doc_handler_set_default_sac_handler
+cr_doc_handler_set_result
+cr_doc_handler_unref
+
+;-------------------------
+;libcroco/cr-enc-handler.h
+;-------------------------
+cr_enc_handler_convert_input
+cr_enc_handler_get_instance
+cr_enc_handler_resolve_enc_alias
+
+;-------------------
+;libcroco/cr-fonts.h
+;-------------------
+cr_font_family_append
+cr_font_family_destroy
+cr_font_family_new
+cr_font_family_prepend
+cr_font_family_set_name
+cr_font_family_to_string
+cr_font_size_adjust_destroy
+cr_font_size_adjust_new
+cr_font_size_adjust_to_string
+cr_font_size_clear
+cr_font_size_copy
+cr_font_size_destroy
+cr_font_size_get_larger_predefined_font_size
+cr_font_size_get_smaller_predefined_font_size
+cr_font_size_is_predefined_absolute_font_size
+cr_font_size_is_set_to_inherit
+cr_font_size_new
+cr_font_size_set_absolute_font_size
+cr_font_size_set_predefined_absolute_font_size
+cr_font_size_set_relative_font_size
+cr_font_size_set_to_inherit
+cr_font_size_to_string
+cr_font_stretch_to_string
+cr_font_style_to_string
+cr_font_variant_to_string
+cr_font_weight_get_bolder
+cr_font_weight_to_string
+
+;-------------------
+;libcroco/cr-input.h
+;-------------------
+cr_input_consume_char
+cr_input_consume_chars
+cr_input_consume_white_spaces
+cr_input_destroy
+cr_input_end_of_input
+cr_input_get_byte_addr
+cr_input_get_column_num
+cr_input_get_cur_pos
+cr_input_get_cur_byte_addr
+cr_input_get_cur_index
+cr_input_get_end_of_file
+cr_input_get_end_of_line
+cr_input_get_line_num
+cr_input_get_nb_bytes_left
+cr_input_get_parsing_location
+cr_input_increment_col_num
+cr_input_increment_line_num
+cr_input_new_from_buf
+cr_input_new_from_uri
+cr_input_peek_byte
+cr_input_peek_byte2
+cr_input_peek_char
+cr_input_read_byte
+cr_input_read_char
+cr_input_ref
+cr_input_seek_index
+cr_input_set_column_num
+cr_input_set_cur_index
+cr_input_set_cur_pos
+cr_input_set_end_of_file
+cr_input_set_end_of_line
+cr_input_set_line_num
+cr_input_unref
+
+;-----------------
+;libcroco/cr-num.h
+;-----------------
+cr_num_copy
+cr_num_destroy
+cr_num_dup
+cr_num_is_fixed_length
+cr_num_new
+cr_num_new_with_val
+cr_num_set
+cr_num_to_string
+
+;-----------------------
+;libcroco/cr-om-parser.h
+;-----------------------
+cr_om_parser_destroy
+cr_om_parser_new
+cr_om_parser_parse_buf
+cr_om_parser_parse_file
+cr_om_parser_parse_paths_to_cascade
+cr_om_parser_simply_parse_buf
+cr_om_parser_simply_parse_file
+cr_om_parser_simply_parse_paths_to_cascade
+
+;--------------------
+;libcroco/cr-parser.h
+;--------------------
+cr_parser_destroy
+cr_parser_get_sac_handler
+cr_parser_get_tknzr
+cr_parser_get_use_core_grammar
+cr_parser_get_parsing_location
+cr_parser_new
+cr_parser_new_from_buf
+cr_parser_new_from_file
+cr_parser_new_from_input
+cr_parser_parse
+cr_parser_parse_buf
+cr_parser_parse_charset
+cr_parser_parse_declaration
+cr_parser_parse_expr
+cr_parser_parse_file
+cr_parser_parse_font_face
+cr_parser_parse_import
+cr_parser_parse_media
+cr_parser_parse_page
+cr_parser_parse_prio
+cr_parser_parse_ruleset
+cr_parser_parse_statement_core
+cr_parser_parse_term
+cr_parser_set_default_sac_handler
+cr_parser_set_sac_handler
+cr_parser_set_use_core_grammar
+cr_parser_set_tknzr
+cr_parser_try_to_skip_spaces_and_comments
+
+;------------------------------
+;libcroco/cr-parsing-location.h
+;------------------------------
+cr_parsing_location_copy
+cr_parsing_location_destroy
+cr_parsing_location_dump
+cr_parsing_location_init
+cr_parsing_location_new
+cr_parsing_location_to_string
+
+;-----------------------
+;libcroco/cr-prop-list.h
+;-----------------------
+cr_prop_list_append
+cr_prop_list_append2
+cr_prop_list_destroy
+cr_prop_list_get_decl
+cr_prop_list_get_next
+cr_prop_list_get_prev
+cr_prop_list_get_prop
+cr_prop_list_lookup_prop
+cr_prop_list_prepend
+cr_prop_list_prepend2
+cr_prop_list_set_decl
+cr_prop_list_set_prop
+cr_prop_list_unlink
+
+;--------------------
+;libcroco/cr-pseudo.h
+;--------------------
+cr_pseudo_destroy
+cr_pseudo_dump
+cr_pseudo_new
+cr_pseudo_to_string
+
+;-----------------
+;libcroco/cr-rgb.h
+;-----------------
+cr_rgb_compute_from_percentage
+cr_rgb_copy
+cr_rgb_destroy
+cr_rgb_dump
+cr_rgb_is_set_to_inherit
+cr_rgb_is_set_to_transparent
+cr_rgb_new
+cr_rgb_new_with_vals
+cr_rgb_parse_from_buf
+cr_rgb_set
+cr_rgb_set_from_hex_str
+cr_rgb_set_from_name
+cr_rgb_set_from_rgb
+cr_rgb_set_from_term
+cr_rgb_set_to_inherit
+cr_rgb_set_to_transparent
+cr_rgb_to_string
+
+;----------------------
+;libcroco/cr-selector.h
+;----------------------
+cr_selector_append
+cr_selector_append_simple_sel
+cr_selector_destroy
+cr_selector_dump
+cr_selector_new
+cr_selector_parse_from_buf
+cr_selector_prepend
+cr_selector_ref
+cr_selector_to_string
+cr_selector_unref
+
+;---------------------
+;libcroco/cr-sel-eng.h
+;---------------------
+cr_sel_eng_destroy
+cr_sel_eng_get_matched_properties_from_cascade
+cr_sel_eng_get_matched_rulesets
+cr_sel_eng_get_matched_style
+cr_sel_eng_get_pseudo_class_selector_handler
+cr_sel_eng_matches_node
+cr_sel_eng_new
+cr_sel_eng_register_pseudo_class_sel_handler
+cr_sel_eng_unregister_all_pseudo_class_sel_handlers
+cr_sel_eng_unregister_pseudo_class_sel_handler
+
+;------------------------
+;libcroco/cr-simple-sel.h
+;------------------------
+cr_simple_sel_append_simple_sel
+cr_simple_sel_compute_specificity
+cr_simple_sel_destroy
+cr_simple_sel_dump
+;cr_simple_sel_dump_attr_sel_list ;no implementation!
+cr_simple_sel_new
+cr_simple_sel_one_to_string
+cr_simple_sel_prepend_simple_sel
+cr_simple_sel_to_string
+
+;-----------------------
+;libcroco/cr-statement.h
+;-----------------------
+cr_statement_append
+cr_statement_at_charset_rule_get_charset
+cr_statement_at_charset_rule_parse_from_buf
+cr_statement_at_charset_rule_set_charset
+cr_statement_at_font_face_rule_add_decl
+cr_statement_at_font_face_rule_get_decls
+cr_statement_at_font_face_rule_set_decls
+cr_statement_at_import_rule_get_imported_sheet
+cr_statement_at_import_rule_get_url
+cr_statement_at_import_rule_parse_from_buf
+cr_statement_at_import_rule_set_imported_sheet
+cr_statement_at_import_rule_set_url
+cr_statement_at_media_get_from_list
+cr_statement_at_media_nr_rules
+cr_statement_at_media_rule_parse_from_buf
+cr_statement_at_page_rule_get_declarations
+;cr_statement_at_page_rule_get_sel ;no implementation!
+cr_statement_at_page_rule_parse_from_buf
+cr_statement_at_page_rule_set_declarations
+;cr_statement_at_page_rule_set_sel ;no implementation!
+cr_statement_destroy
+cr_statement_does_buf_parses_against_core
+cr_statement_dump
+cr_statement_dump_charset
+cr_statement_dump_font_face_rule
+cr_statement_dump_import_rule
+cr_statement_dump_media_rule
+cr_statement_dump_page
+cr_statement_dump_ruleset
+cr_statement_font_face_rule_parse_from_buf
+cr_statement_get_from_list
+cr_statement_get_parent_sheet
+cr_statement_list_to_string
+cr_statement_new_at_charset_rule
+cr_statement_new_at_font_face_rule
+cr_statement_new_at_import_rule
+cr_statement_new_at_media_rule
+cr_statement_new_at_page_rule
+cr_statement_new_ruleset
+cr_statement_nr_rules
+cr_statement_parse_from_buf
+cr_statement_prepend
+cr_statement_ruleset_append_decl
+cr_statement_ruleset_append_decl2
+cr_statement_ruleset_get_declarations
+cr_statement_ruleset_set_decl_list
+cr_statement_ruleset_get_sel_list
+cr_statement_ruleset_parse_from_buf
+cr_statement_ruleset_set_sel_list
+cr_statement_set_parent_sheet
+cr_statement_to_string
+cr_statement_unlink
+
+;--------------------
+;libcroco/cr-string.h
+;--------------------
+cr_string_destroy
+cr_string_dup
+cr_string_dup2
+cr_string_new
+cr_string_new_from_gstring
+cr_string_new_from_string
+cr_string_peek_raw_str
+cr_string_peek_raw_str_len
+
+;------------------------
+;libcroco/cr-stylesheet.h
+;------------------------
+cr_stylesheet_destroy
+cr_stylesheet_dump
+cr_stylesheet_new
+cr_stylesheet_nr_rules
+cr_stylesheet_ref
+cr_stylesheet_statement_get_from_list
+cr_stylesheet_to_string
+cr_stylesheet_unref
+
+;-------------------
+;libcroco/cr-style.h
+;-------------------
+cr_style_border_style_to_string
+cr_style_copy
+cr_style_destroy
+cr_style_display_type_to_string
+cr_style_dup
+cr_style_float_type_to_string
+cr_style_new
+cr_style_num_prop_val_to_string
+cr_style_position_type_to_string
+;cr_style_propagate_from_parent ;no implementation!
+cr_style_ref
+cr_style_resolve_inherited_properties
+cr_style_rgb_prop_val_to_string
+cr_style_set_props_to_default_values
+cr_style_set_props_to_initial_values
+cr_style_set_style_from_decl
+cr_style_to_string
+cr_style_unref
+cr_style_white_space_type_to_string
+
+;------------------
+;libcroco/cr-term.h
+;------------------
+cr_term_append_term
+cr_term_destroy
+cr_term_dump
+cr_term_get_from_list
+cr_term_new
+cr_term_nr_values
+cr_term_one_to_string
+cr_term_parse_expression_from_buf
+cr_term_prepend_term
+cr_term_ref
+cr_term_set_function
+cr_term_set_hash
+cr_term_set_ident
+cr_term_set_number
+cr_term_set_rgb
+cr_term_set_string
+cr_term_set_uri
+cr_term_to_string
+cr_term_unref
+
+;-------------------
+;libcroco/cr-tknzr.h
+;-------------------
+cr_tknzr_consume_chars
+cr_tknzr_destroy
+cr_tknzr_get_cur_byte_addr
+cr_tknzr_get_cur_pos
+cr_tknzr_get_input
+cr_tknzr_get_nb_bytes_left
+cr_tknzr_get_next_token
+cr_tknzr_get_parsing_location
+cr_tknzr_new
+cr_tknzr_new_from_buf
+cr_tknzr_new_from_uri
+cr_tknzr_parse_token
+cr_tknzr_peek_byte
+cr_tknzr_peek_byte2
+cr_tknzr_peek_char
+cr_tknzr_read_byte
+cr_tknzr_read_char
+cr_tknzr_ref
+cr_tknzr_seek_index
+cr_tknzr_set_cur_pos
+cr_tknzr_set_input
+cr_tknzr_unget_token
+cr_tknzr_unref
+
+;-------------------
+;libcroco/cr-token.h
+;-------------------
+cr_token_destroy
+cr_token_new
+cr_token_set_angle
+cr_token_set_atkeyword
+cr_token_set_bc
+cr_token_set_bo
+cr_token_set_cbc
+cr_token_set_cbo
+cr_token_set_cdc
+cr_token_set_cdo
+cr_token_set_charset_sym
+cr_token_set_comment
+cr_token_set_dashmatch
+cr_token_set_delim
+cr_token_set_dimen
+cr_token_set_ems
+cr_token_set_exs
+cr_token_set_font_face_sym
+cr_token_set_freq
+cr_token_set_function
+cr_token_set_hash
+cr_token_set_important_sym
+cr_token_set_import_sym
+cr_token_set_includes
+cr_token_set_ident
+cr_token_set_length
+cr_token_set_media_sym
+cr_token_set_number
+cr_token_set_page_sym
+cr_token_set_pc
+cr_token_set_percentage
+cr_token_set_po
+cr_token_set_rgb
+cr_token_set_s
+cr_token_set_semicolon
+cr_token_set_string
+cr_token_set_time
+;cr_token_set_unicoderange ;commented out in the header!
+cr_token_set_uri
+
+;-------------------
+;libcroco/cr-utils.h
+;-------------------
+cr_utils_dump_n_chars
+cr_utils_dump_n_chars2
+cr_utils_dup_glist_of_cr_string
+cr_utils_dup_glist_of_string
+cr_utils_is_hexa_char
+cr_utils_is_newline
+cr_utils_is_nonascii
+cr_utils_is_white_space
+cr_utils_read_char_from_utf8_buf
+cr_utils_ucs1_str_len_as_utf8
+cr_utils_ucs1_str_to_utf8
+cr_utils_ucs1_to_utf8
+cr_utils_ucs4_str_len_as_utf8
+cr_utils_ucs4_str_to_utf8
+cr_utils_ucs4_to_utf8
+cr_utils_utf8_str_len_as_ucs4
+cr_utils_utf8_to_ucs1
+cr_utils_utf8_to_ucs4
+cr_utils_utf8_str_len_as_ucs1
+cr_utils_utf8_str_to_ucs1
+cr_utils_utf8_str_to_ucs4 \ No newline at end of file
diff --git a/src/3rdparty/libcroco/tests/CMakeLists.txt b/src/3rdparty/libcroco/tests/CMakeLists.txt
new file mode 100644
index 0000000..1ffb908
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/CMakeLists.txt
@@ -0,0 +1,69 @@
+set(testprogs
+ test0
+ test1
+ test2
+ test3
+ test4
+ test5
+ test6
+ test7
+ test8
+)
+
+foreach(source ${testprogs})
+ add_executable(${source} ${source}-main.c cr-test-utils.c cr-test-utils.h)
+
+ target_include_directories(${source}
+ PRIVATE
+ ${CMAKE_SOURCE_DIR}/src
+ ${CMAKE_BINARY_DIR}/src
+ ${GLIB_INCLUDE_DIRS}
+ ${LIBXML_INCLUDE_DIRS}
+ )
+
+ target_link_libraries(${source}
+ croco_LIB
+ )
+endforeach()
+
+if(1)
+ # Run each test separately
+
+ set(testscripts
+ test-functional-notation.sh
+ test-lots-of-comments.sh
+ test-parsing-location.sh
+ test-prop-ident.sh
+ test-sel-child-class.sh
+ test-several-media.sh
+ test-unknown-at-rule2.sh
+ test-unknown-at-rule.sh
+ )
+
+ add_test(NAME cleantest
+ COMMAND ${CMAKE_SOURCE_DIR}/tests/testctl cleanup
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ )
+
+ foreach(source ${testprogs} ${testscripts})
+ add_test(NAME ${source}
+ COMMAND ${CMAKE_SOURCE_DIR}/tests/testctl run --test-and-report ${source}
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ )
+ set_tests_properties(${source} PROPERTIES DEPENDS "cleantest")
+ endforeach()
+else()
+ # Run all tests at once
+ add_test(NAME all-tests
+ COMMAND ${CMAKE_SOURCE_DIR}/tests/testctl run
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ )
+endif()
+
+get_property(test_names DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY TESTS)
+set_property(TEST ${test_names} PROPERTY ENVIRONMENT
+ "TEST_OUT_DIR=${CMAKE_CURRENT_BINARY_DIR}"
+ "TEST_SOURCE_DIR=${CMAKE_SOURCE_DIR}/tests"
+ "TEST_INPUTS_DIR=${CMAKE_SOURCE_DIR}/tests/test-inputs"
+ "CSSLINT=${CMAKE_BINARY_DIR}/csslint/csslint"
+)
diff --git a/src/3rdparty/libcroco/tests/Makefile.am b/src/3rdparty/libcroco/tests/Makefile.am
new file mode 100644
index 0000000..666eff8
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/Makefile.am
@@ -0,0 +1,36 @@
+SUBDIRS = test-inputs test-output-refs
+EXTRA_DIST = testctl vg.supp global-vars.sh.in valgrind-version.sh \
+test-prop-ident.sh test-unknown-at-rule.sh test-unknown-at-rule2.sh \
+test-several-media.sh
+
+
+#the list of all possible tests goes here.
+
+EXTRALDFLAGS = $(CROCO_LIBS)
+testprogs=test0 test1 test2 test3 test4 test5 test6 test7 test8
+noinst_PROGRAMS = $(testprogs)
+test0_SOURCES = test0-main.c
+test0_LDFLAGS = $(EXTRALDFLAGS)
+test1_SOURCES = test1-main.c
+test1_LDFLAGS = $(EXTRALDFLAGS)
+test2_SOURCES = test2-main.c cr-test-utils.c cr-test-utils.h
+test2_LDFLAGS = $(EXTRALDFLAGS)
+test3_SOURCES = test3-main.c cr-test-utils.c cr-test-utils.h
+test3_LDFLAGS = $(EXTRALDFLAGS)
+test4_SOURCES = test4-main.c cr-test-utils.c cr-test-utils.h
+test4_LDFLAGS = $(EXTRALDFLAGS)
+test5_SOURCES = test5-main.c cr-test-utils.c cr-test-utils.h
+test5_LDFLAGS = $(EXTRALDFLAGS)
+test6_SOURCES = test6-main.c cr-test-utils.c cr-test-utils.h
+test6_LDFLAGS = $(EXTRALDFLAGS)
+test7_SOURCES = test7-main.c cr-test-utils.c cr-test-utils.h
+test7_LDFLAGS = $(EXTRALDFLAGS)
+test8_SOURCES = test8-main.c
+test8_LDFLAGS = $(EXTRALDFLAGS)
+
+croco_lib = $(top_builddir)/src/@CROCO_LIB@
+LDADD = $(croco_lib)
+
+AM_CPPFLAGS = -I$(top_srcdir)/intl -I$(top_srcdir)/src -I$(top_builddir)/src
+
+AM_CFLAGS = -I. $(CROCO_CFLAGS)
diff --git a/src/3rdparty/libcroco/tests/README-description.txt b/src/3rdparty/libcroco/tests/README-description.txt
new file mode 100644
index 0000000..a81336f
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/README-description.txt
@@ -0,0 +1,125 @@
+This file describes the tests present in the libcroro tests directory.
+=====================================================================
+
+Initial author: Dodji Seketeli <dodji@seketeli.org>
+
+Each entry of this file is orgnised as follows:
+
+"""""""""""""""""""""""""""""""""""""""""""""""""
+binary: name-of-the-test-binary-file
+
+source-file: name-of-the-test-source-file
+
+purpose: purpose of the test.
+
+description: description of the test
+"""""""""""""""""""""""""""""""""""""""""""""""""
+
+And, in the words of RMS, happy hacking !
+
+ Dodji
+##################################################################
+
+
+"""""""""""""""""""""""""""""""""""""""""""""""""
+binary: test0
+
+source-file: test0-main.c
+
+purpose: Tests the cr_input_read_byte() method of the CRInput class.
+
+description: opens the file located at the path in parameter and
+loads it into an input stream using the cr_input_new_from_uri()
+method of the CRInput class.
+Then, reads the bytes from the input stream using the cr_input_read_byte()
+method and dumps each byte read to stdout.
+Note that the input file must be encoded in utf8.
+
+"""""""""""""""""""""""""""""""""""""""""""""""""
+
+
+"""""""""""""""""""""""""""""""""""""""""""""""""
+binary: test1
+
+source-file: test1-main.c
+
+purpose: Test the read_char() method of the CRInput class.
+
+description: opens the file located at the path in parameter and
+loads it into an input stream using the cr_input_new_from_uri()
+method of the CRInput class.
+Then, reads characters from the input stream using the cr_input_read_char()
+method and dumps each character on stdout.
+Note that the input file must be encoded in utf8.
+"""""""""""""""""""""""""""""""""""""""""""""""""
+
+"""""""""""""""""""""""""""""""""""""""""""""""""
+binary: test2
+
+source-file: test2-main.c
+
+purpose: tests the sac api of the parser.
+
+description: it loads the file located at the path given
+in argument, instantiates a sac parser, set document
+handlers and parses the file.
+The doc handlers simply dump the name name of the callback
+which is being called and some basic additional information.
+"""""""""""""""""""""""""""""""""""""""""""""""""
+
+"""""""""""""""""""""""""""""""""""""""""""""""""
+binary: test3
+
+source-file: test3-main.c
+
+purpose: Test the SAC api core css grammar parsing
+
+description: it loads the file located at the path given
+in argument, instantiates a sac parser, set document
+handlers and parses the file using the css2 core syntax.
+The doc handlers simply dump the name name of the callback
+which is being called and some basic additional information.
+Here, the goal is that nothing is dump on screen because
+during the parsing using the core grammar syntax, no callback
+should be called.
+"""""""""""""""""""""""""""""""""""""""""""""""""
+
+"""""""""""""""""""""""""""""""""""""""""""""""""
+binary: test4
+
+source-file: test4-main.c
+
+purpose: tests the cssom parser interface (cr-om-parser.c)
+
+description: parses the file located at the path given in
+parameter and dumps the result of the parsing (the object model)
+on stdout.
+"""""""""""""""""""""""""""""""""""""""""""""""""
+
+"""""""""""""""""""""""""""""""""""""""""""""""""
+binary: test5
+
+source-file: test5-main.c
+
+purpose: tests the selector cr-sel-eng.c basic functionalities.
+
+description: parses an in memory xml document hardwired in the
+test5-main.c file; parses the stylesheet given in parameter to
+the test5 binary.
+Walks down the xml document tree and runs the selector engine
+on each xml document node to get the css rule that matches it.
+Displays a report that basically say: "this xml node was matched
+by this set of css rules"
+"""""""""""""""""""""""""""""""""""""""""""""""""
+
+"""""""""""""""""""""""""""""""""""""""""""""""""
+binary: test6
+
+source-file: test6-main.c
+
+purpose: tests the "in memory" css2 parsing capabilities. (cr_om_parser_parse_buf)
+
+
+description: parses an "in memory" hardwired css2 stylesheet
+and dumps it on stdout.
+""""""""""""""""""""""""""""""""""""""""""""""""" \ No newline at end of file
diff --git a/src/3rdparty/libcroco/tests/cr-test-utils.c b/src/3rdparty/libcroco/tests/cr-test-utils.c
new file mode 100644
index 0000000..9435ef7
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/cr-test-utils.c
@@ -0,0 +1,59 @@
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <string.h>
+#include "cr-test-utils.h"
+
+/**
+ *Parses the command line.
+ *@param a_argc the argc parameter of the main routine.
+ *@param the argv parameter of the main routine.
+ *@param a_options out parameter the parsed options.
+ */
+void
+cr_test_utils_parse_cmd_line (int a_argc, char **a_argv,
+ struct Options *a_options)
+{
+ int i = 0;
+
+ g_return_if_fail (a_options);
+
+ memset (a_options, 0, sizeof (struct Options));
+
+ for (i = 1; i < a_argc; i++) {
+ if (a_argv[i][0] != '-')
+ break;
+
+ if (!strcmp (a_argv[i], "-h")
+ || !strcmp (a_argv[i], "--help")) {
+ a_options->display_help = TRUE;
+ }
+ if (!strcmp (a_argv[i], "--about")) {
+ a_options->display_about = TRUE;
+ }
+ }
+
+ if (i >= a_argc) {
+ /*No file parameter where given */
+ a_options->files_list = NULL;
+ } else {
+ a_options->files_list = &a_argv[i];
+ }
+}
diff --git a/src/3rdparty/libcroco/tests/cr-test-utils.h b/src/3rdparty/libcroco/tests/cr-test-utils.h
new file mode 100644
index 0000000..9219b93
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/cr-test-utils.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ *$Id$
+ */
+#ifndef __CR_TEST_UTILS_H__
+#define __CR_TEST_UTILS_H__
+
+#include <stdio.h>
+#include <glib.h>
+
+/**
+ *The options data structure.
+ *The variable of this data structure are set
+ *during the parsing the command line by the
+ *parse_command_line() function.
+ */
+struct Options
+{
+ gboolean display_help ;
+ gboolean display_about ;
+ gchar ** files_list ;
+};
+
+
+void
+cr_test_utils_parse_cmd_line (int a_argc, char **a_argv,
+ struct Options *a_options) ;
+
+#endif /*__CR_TEST_UTILS_H__*/
diff --git a/src/3rdparty/libcroco/tests/global-vars.sh.in b/src/3rdparty/libcroco/tests/global-vars.sh.in
new file mode 100644
index 0000000..e291459
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/global-vars.sh.in
@@ -0,0 +1,10 @@
+TEST_INPUTS_DIR=$HERE_DIR/test-inputs
+CSSLINT=$HERE_DIR/../csslint/.libs/csslint-@LIBCROCO_MAJOR_VERSION@.@LIBCROCO_MINOR_VERSION@
+if ! test -x $CSSLINT ; then
+ echo "Aarg Could not find an executable csslint. I was looking for $CSSLINT"
+ echo $
+fi
+
+if ! test x"$VALGRIND" = x ; then
+ CSSLINT="$VALGRIND $CSSLINT"
+fi
diff --git a/src/3rdparty/libcroco/tests/test-functional-notation.sh b/src/3rdparty/libcroco/tests/test-functional-notation.sh
new file mode 100755
index 0000000..2860092
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-functional-notation.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+test -z "$CSSLINT" && . ./global-test-vars.sh
+
+$CSSLINT $TEST_INPUTS_DIR/functional-notation.css
diff --git a/src/3rdparty/libcroco/tests/test-inputs/Makefile.am b/src/3rdparty/libcroco/tests/test-inputs/Makefile.am
new file mode 100644
index 0000000..3c93d8f
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/Makefile.am
@@ -0,0 +1,16 @@
+EXTRA_DIST= prop-vendor-ident.css \
+test0.1.css \
+test1.css \
+test2.1.css \
+test2.2.css \
+test2.css \
+test3.1.css \
+test3.2.css \
+test3.css \
+test4.1.css \
+test4.2.css \
+test5.1.css \
+unknown-at-rule2.css \
+unknown-at-rule.css \
+several-media.css
+
diff --git a/src/3rdparty/libcroco/tests/test-inputs/functional-notation.css b/src/3rdparty/libcroco/tests/test-inputs/functional-notation.css
new file mode 100644
index 0000000..cd80f18
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/functional-notation.css
@@ -0,0 +1,2 @@
+foo { bar: attr(width, length, calc(70% - 5px)) }
+foo {bar: attr(x,y) }
diff --git a/src/3rdparty/libcroco/tests/test-inputs/lots-of-comments.css b/src/3rdparty/libcroco/tests/test-inputs/lots-of-comments.css
new file mode 100644
index 0000000..87a6e4a
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/lots-of-comments.css
@@ -0,0 +1,198 @@
+
+
+@charset "utf8";
+
+/********************************************
+ * Parsing location information of the @charset rule
+ ********************************************/
+ /*@charset*/
+ /*line:1 column:1 byte offset:0 */
+ /*utf8*/
+ /*line:1 column:10 byte offset:9 */
+
+@import url("http://pouet.com") screen, paper, aural;
+
+/*****************************************************
+ *Parsing location information for the @import rule
+ ******************************************************/
+
+ /*@import*/
+ /*line:3 column:1 byte offset:19 */
+
+ /*http://pouet.com*/
+ /*line:3 column:13 byte offset:31 */
+
+ /*screen*/
+ /*line:3 column:33 byte offset:51 */
+
+ /*paper*/
+ /*line:3 column:41 byte offset:59 */
+
+ /*aural*/
+ /*line:3 column:48 byte offset:66 */
+
+@page coin :pseudo-page
+
+ /*@page*/
+ /*line:5 column:1 byte offset:75 */
+ /*coin*/
+ /*line:5 column:7 byte offset:81 */
+ /*pseudo-page*/
+ /*line:5 column:13 byte offset:87 */
+
+{
+
+
+page-prop0 : page-val0;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*page-prop0*/
+ /*line:6 column:7 byte offset:107 */
+ /*page-val0*/
+ /*line:6 column:19 byte offset:119 */
+
+
+page-prop1 : page-val1;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*page-prop1*/
+ /*line:7 column:7 byte offset:137 */
+ /*page-val1*/
+ /*line:7 column:19 byte offset:149 */
+}
+@media paper, aural
+ /*@media*/
+ /*line:10 column:1 byte offset:164 */
+ /*paper*/
+ /*line:10 column:8 byte offset:171 */
+ /*aural*/
+ /*line:10 column:15 byte offset:178 */
+
+{
+x {
+/************************************************
+ *Parsing location information of the selector
+ ************************************************/
+/*x*/
+/*line:11 column:5 byte offset:190 */
+ /*x*/
+ /*line:11 column:5 byte offset:190 */
+
+
+foo : fooval;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*foo*/
+ /*line:12 column:7 byte offset:200 */
+ /*fooval*/
+ /*line:12 column:12 byte offset:205 */
+
+
+bar : barval;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*bar*/
+ /*line:13 column:7 byte offset:220 */
+ /*barval*/
+ /*line:13 column:12 byte offset:225 */
+ }
+
+}
+@font-face {
+/******************************************************
+ Parsing location information for the @font-face rule
+ ******************************************************/
+
+ /*@font-face*/
+ /*line:17 column:1 byte offset:243 */
+
+
+font-prop1 : font1;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*font-prop1*/
+ /*line:18 column:2 byte offset:257 */
+ /*font1*/
+ /*line:18 column:14 byte offset:269 */
+
+
+font-prop2 : font2;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*font-prop2*/
+ /*line:19 column:2 byte offset:278 */
+ /*font2*/
+ /*line:19 column:14 byte offset:290 */
+}
+x>y[attr="val"].class#tatati z+toto {
+/************************************************
+ *Parsing location information of the selector
+ ************************************************/
+/*x*/
+/*line:21 column:1 byte offset:300 */
+ /*x*/
+ /*line:21 column:1 byte offset:300 */
+/*y[attr="val"].class#tatati*/
+/*line:21 column:5 byte offset:304 */
+ /*y*/
+ /*line:21 column:5 byte offset:304 */
+
+ /*[attr="val"]*/
+ /*line:21 column:6 byte offset:305 */
+
+ /*.class*/
+ /*line:21 column:17 byte offset:316 */
+
+ /*#tatati*/
+ /*line:21 column:22 byte offset:321 */
+/*z*/
+/*line:21 column:30 byte offset:329 */
+ /*z*/
+ /*line:21 column:30 byte offset:329 */
+/*toto*/
+/*line:21 column:34 byte offset:333 */
+ /*toto*/
+ /*line:21 column:34 byte offset:333 */
+
+
+prop1 : function(a);
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*prop1*/
+ /*line:22 column:2 byte offset:340 */
+ /*function(a)*/
+ /*line:22 column:9 byte offset:347 */
+
+
+prop2 : val2;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*prop2*/
+ /*line:23 column:2 byte offset:362 */
+ /*val2*/
+ /*line:23 column:9 byte offset:369 */
+ }
diff --git a/src/3rdparty/libcroco/tests/test-inputs/parsing-location.css b/src/3rdparty/libcroco/tests/test-inputs/parsing-location.css
new file mode 100644
index 0000000..f760b07
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/parsing-location.css
@@ -0,0 +1,26 @@
+@charset "utf8" ;
+
+@import url("http://pouet.com") screen, paper, aural ;
+@import url(http://pouet.com) screen2, paper2, aural2 ;
+
+@page coin :pseudo-page {
+ page-prop0: page-val0 ;
+ page-prop1: page-val1 ;
+}
+
+@media paper, aural {
+ x {
+ foo: fooval ;
+ bar: barval ;
+ }
+}
+
+@font-face {
+ font-prop1: font1 ;
+ font-prop2: font2 ;
+}
+x > y[attr=val].class#tatati z + toto{
+ prop1: function(a) ;
+ prop2: val2
+}
+
diff --git a/src/3rdparty/libcroco/tests/test-inputs/prop-vendor-ident.css b/src/3rdparty/libcroco/tests/test-inputs/prop-vendor-ident.css
new file mode 100644
index 0000000..f7aa8b5
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/prop-vendor-ident.css
@@ -0,0 +1,3 @@
+:-foo-pseudo {
+ -foo-bar-prop: -foobar-value
+}
diff --git a/src/3rdparty/libcroco/tests/test-inputs/sel-child-class.css b/src/3rdparty/libcroco/tests/test-inputs/sel-child-class.css
new file mode 100644
index 0000000..a6ea36b
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/sel-child-class.css
@@ -0,0 +1 @@
+body > div p.process { color: aqua; }
diff --git a/src/3rdparty/libcroco/tests/test-inputs/sel-child-class.xml b/src/3rdparty/libcroco/tests/test-inputs/sel-child-class.xml
new file mode 100644
index 0000000..ee5e23d
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/sel-child-class.xml
@@ -0,0 +1,10 @@
+<test>
+ <body>
+ <div>
+ <div>
+ <p class="process">This should be aqua</p>
+ </div>
+ </div>
+ </body>
+</test>
+
diff --git a/src/3rdparty/libcroco/tests/test-inputs/several-media.css b/src/3rdparty/libcroco/tests/test-inputs/several-media.css
new file mode 100644
index 0000000..79dc336
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/several-media.css
@@ -0,0 +1,10 @@
+@media screen {
+a:link { text-decoration: none; }
+div { width: 50%; }
+}
+
+@media print {
+a { color: red; }
+div { width: 57%; }
+}
+
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test0.1.css b/src/3rdparty/libcroco/tests/test-inputs/test0.1.css
new file mode 100644
index 0000000..f8e842e
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test0.1.css
@@ -0,0 +1,258 @@
+body {
+ margin : 0px 0px 20px 0px;
+ height : 100%;
+ background : #FFF
+}
+
+A {
+ color : #003366;
+ text-decoration : underline
+}
+
+A:link {
+ color : #003366;
+ text-decoration : underline
+}
+
+A:visited {
+ color : #003366;
+ text-decoration : underline
+}
+
+A:active {
+ color : #999999
+}
+
+A:hover {
+ color : #999999
+}
+
+h1, h2, h3 {
+ margin : 0px;
+ padding : 0px
+}
+
+#banner {
+ font-family : palatino, georgia, verdana, arial, sans-serif;
+ color : #333;
+ top:0;
+ font-size : normal;
+ font-weight : normal;
+}
+
+#banner a, #banner a:link, #banner a:visited, #banner a:active, #banner a:hover {
+ font-family : verdana, arial, sans-serif;
+ font-size : xx-large;
+ color : #333;
+ text-decoration : none
+}
+
+.description {
+ font-family : verdana, arial, sans-serif;
+ color : #333;
+ font-size : small;
+ text-transform : none
+}
+
+#content {
+ position : absolute;
+ background : #FFF;
+ top: 20%;
+ left: 20%;
+ border : 1px solid #FFF
+}
+
+#container {
+ background : #FFF;
+ border : 1px solid #FFF
+}
+
+#links {
+ padding : 15px;
+ border : 1px solid #FFF;
+ width : 200px
+}
+
+.blog {
+ padding : 20px;
+ background : #FFF
+}
+
+.blogbody {
+ font-family : verdana, arial, sans-serif;
+ color : #333;
+ font-size : small;
+ font-weight : normal;
+ background : #FFF;
+ line-height : 150%
+}
+
+.blogbody a, .blogbody a:link, .blogbody a:visited, .blogbody a:active, .blogbody a:hover {
+ font-weight : normal;
+ text-decoration : underline
+}
+
+.title {
+ font-family : verdana, arial, sans-serif;
+ font-size : medium;
+ color : #666
+}
+
+.date {
+ font-family : verdana, arial, serif;
+ font-size : large;
+ color : #333;
+ border-bottom : 1px solid #999;
+ margin-bottom : 10px;
+ font-weight : bold
+}
+
+.posted {
+ font-family : verdana, arial, sans-serif;
+ font-size : x-small;
+ color : #000000;
+ margin-bottom : 25px
+}
+
+.calendar {
+ font-family : verdana, arial, sans-serif;
+ color : #333;
+ font-size : x-small;
+ font-weight : normal;
+ background : #FFF;
+ line-height : 140%;
+ padding : 2px;
+ text-align : left
+}
+
+.calendarhead {
+ font-family : palatino, georgia, times new roman, serif;
+ color : #666600;
+ font-size : small;
+ font-weight : normal;
+ padding : 2px;
+ letter-spacing : 0.3em;
+ background : #FFF;
+ text-transform : uppercase;
+ text-align : left
+}
+
+.side {
+ font-family : verdana, arial, sans-serif;
+ color : #333;
+ font-size : x-small;
+ font-weight : normal;
+ background : #FFF;
+ line-height : 140%;
+ padding : 2px
+}
+
+#menubar {
+ font-family : verdana, arial, sans-serif;
+ color : #333;
+ font-size : small;
+ font-weight : normal;
+ position:absolute;
+ top:20%;
+ padding: 2px;
+ letter-spacing : 0.1em;
+ background : #FFF;
+ text-transform : uppercase
+}
+
+.syndicate {
+ font-family : verdana, arial, sans-serif;
+ font-size : xx-small;
+ line-height : 140%;
+ padding : 2px;
+ margin-top : 15px;
+ background : #FFF
+}
+
+.powered {
+ font-family : verdana, arial, sans-serif;
+ color : #666;
+ font-size : x-small;
+ line-height : 140%;
+ text-transform : uppercase;
+ padding : 2px;
+ margin-top : 50px;
+ letter-spacing : 0.2em;
+ background : #FFF
+}
+
+.comments-body {
+ font-family : verdana, arial, sans-serif;
+ color : #666;
+ font-size : small;
+ font-weight : normal;
+ background : #FFF;
+ line-height : 140%;
+ padding-bottom : 10px;
+ padding-top : 10px;
+ border-bottom : 1px dotted #999
+}
+
+.comments-post {
+ font-family : verdana, arial, sans-serif;
+ color : #666;
+ font-size : x-small;
+ font-weight : normal;
+ background : #FFF
+}
+
+.trackback-url {
+ font-family : verdana, arial, sans-serif;
+ color : #666;
+ font-size : small;
+ font-weight : normal;
+ background : #FFF;
+ line-height : 140%;
+ padding : 5px;
+ border : 1px dotted #999
+}
+
+.trackback-body {
+ font-family : verdana, arial, sans-serif;
+ color : #666;
+ font-size : small;
+ font-weight : normal;
+ background : #FFF;
+ line-height : 140%;
+ padding-bottom : 10px;
+ padding-top : 10px;
+ border-bottom : 1px dotted #999
+}
+
+.trackback-post {
+ font-family : verdana, arial, sans-serif;
+ color : #666;
+ font-size : x-small;
+ font-weight : normal;
+ background : #FFF
+}
+
+.comments-head {
+ font-family : verdana, arial, sans-serif;
+ font-size : small;
+ color : #666;
+ border-bottom : 1px solid #999;
+ margin-top : 20px;
+ font-weight : bold;
+ background : #FFF
+}
+
+#banner-commentspop {
+ font-family : verdana, arial, sans-serif;
+ color : #FFF;
+ font-size : large;
+ font-weight : bold;
+ border-left : 1px solid #FFF;
+ border-right : 1px solid #FFF;
+ border-top : 1px solid #FFF;
+ background : #003366;
+ padding-left : 15px;
+ padding-right : 15px;
+ padding-top : 5px;
+ padding-bottom : 5px
+}
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test1.css b/src/3rdparty/libcroco/tests/test-inputs/test1.css
new file mode 100644
index 0000000..b03c8a4
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test1.css
@@ -0,0 +1,316 @@
+body {
+
+ background-color: #E5E5E5;
+
+ scrollbar-face-color: #CCCCCC;
+
+ scrollbar-highlight-color: #FFFFFF;
+
+ scrollbar-shadow-color: #CCCCCC;
+
+ scrollbar-3dlight-color: #D1D7DC;
+
+ scrollbar-arrow-color: #000000;
+
+ scrollbar-track-color: #FFFFFF;
+
+ scrollbar-darkshadow-color: #000000;
+
+}
+
+
+
+font, th, td, p {
+
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+
+ font-size: 11px;
+
+}
+
+
+
+h1, h2 { font-size: 11px; color: #000000; font-weight: bold; }
+
+
+
+a:link, a:active, a:visited { color: #000000; }
+
+
+
+a:hover { color: #CC0000; text-decoration: underline; }
+
+
+
+hr { height: 0px; border: solid #CCCCCC 0px; border-top-width: 1px; }
+
+
+
+small { font-size: 10px; }
+
+
+
+input, textarea, select {
+
+ font: normal 11px Verdana, Arial, Helvetica, sans-serif;
+
+ color: #000000;
+
+ border-color: #000000;
+
+}
+
+
+
+input { text-indent: 2px; }
+
+
+
+
+input.post, textarea.post, select {
+
+ background-color: #FFFFFF;
+
+}
+
+
+
+
+th {
+
+ font-size: 11px; color: #CCCCCC; font-weight: bold;
+
+ background-color: #000000; height: 25px;
+
+ background-image: url(/~wiceyto/test/templates/blacknwhite/images/cellpic3.gif);
+
+}
+
+
+
+
+.fontspec, .tablefont {
+
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+
+ font-size: 11px;
+
+}
+
+
+
+.navbartext, .navbarfont {
+
+ font-size: 11px; color: #000000; font-weight: bold;
+
+}
+
+
+
+.navbartext a, .navbarfont a {
+
+ color: #000000; font-weight: bold; text-decoration: none;
+
+}
+
+
+
+.navbartext a:hover, .navbarfont a:hover {
+
+ color: #CC0000; text-decoration: none;
+
+}
+
+
+
+.tablespec, .guestbook { background-color: #FFFFFF; border: 2px #000000 solid; }
+
+.tablespec th, .tablespec td { color: #000000; background-color: #CCCCCC; }
+
+.tablespec th { background-image: none; }
+
+
+
+.messageblock {
+
+ border: dashed 1px;
+
+ margin-right: 4em; margin-left: 4em;
+
+ padding: 3em;
+
+}
+
+
+
+/* $MessageOpenCode - the body of text of the posts */
+
+.messagebody { font-size: 12px; line-height: 18px; }
+
+.messagebody a { color: #000000; text-decoration: underline; }
+
+.messagebody a:hover { color: #CC0000; text-decoration: underline; }
+
+
+
+
+.newcode { font-size: 11px; color: #CC0000; font-weight: bold; }
+
+.admincode { font-size: 11px; color: #990000; font-style: bold; }
+
+
+
+
+.bodyline { background-color: #FFFFFF; border: 1px #000000 solid; }
+
+
+
+
+.quote, .code {
+
+ background-color: #FAFAFA; border: #D1D7DC; border-style: solid;
+
+ border-top-width: 1px; border-right-width: 1px;
+
+ border-bottom-width: 1px; border-left-width: 1px;
+
+}
+
+
+
+.quote {
+
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+
+ font-size: 11px;
+
+ color: #444444; line-height: 125%;
+
+}
+
+
+
+.code {
+
+ font-family: Courier, 'Courier New', sans-serif;
+
+ font-size: 11px;
+
+ color: #CC0000;
+
+}
+
+
+
+
+input.button {
+
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+
+ font-size: 11px;
+
+ color: #000000;
+
+ background-color: #FFFFFF;
+
+}
+
+
+
+/* Format button rollover help line. Actually it's a text box
+
+ set to the same color as the background so no one will know. */
+
+.helpline { background-color: #CCCCCC; border-style: none; }
+
+
+
+/* additional table cell colors and backgrounds */
+
+td.row2 { background-color: #CCCCCC; }
+
+td.row1 { background-color: #CCCCCC; }
+
+td.row3 { background-color: #D1D7DC; }
+
+
+
+/* additional general text */
+
+.gen { font-size: 12px; }
+
+.genmed { font-size: 11px; }
+
+.gensmall { font-size: 10px; }
+
+.gen, .genmed, .gensmall { color: #000000; }
+
+a.gen, a.genmed, a.gensmall { color: #000000; text-decoration: none; }
+
+a.gen:hover, a.genmed:hover, a.gensmall:hover { color: #CC0000; text-decoration: underline; }
+
+
+
+/* import fancy styles. For IE only. NS4.x doesn't use the @import function */
+
+@import url("/your.site/webbbs/themes/formIE.css");
+
+
+
+/* END of blacknwhite.css */
+
+
+
+
+
+
+
+/* Appendix.2-2: Example fancy styles CSS file
+
+Paste these into a text file and save as formIE.css */
+
+
+
+/* Fancy form styles for IE */
+
+
+
+input, textarea, select {
+
+border-top-width : 1px;
+
+border-right-width : 1px;
+
+border-bottom-width : 1px;
+
+border-left-width : 1px;
+
+}
+
+
+
+input { text-indent : 2px; }
+
+
+
+input.button {
+
+border-top-width : 1px;
+
+border-right-width : 1px;
+
+border-bottom-width : 1px;
+
+border-left-width : 1px;
+
+}
+
+
+
+.postbody { line-height: 18px}
+
+.magic {
+ margin-left: -20px;
+}
+
+/* END of formIE.css */
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test2.1.css b/src/3rdparty/libcroco/tests/test-inputs/test2.1.css
new file mode 100644
index 0000000..ba447fb
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test2.1.css
@@ -0,0 +1,47 @@
+
+/*simple Attribute set selectors*/
+s1[foo] {prop1 : "\53 tring"}
+
+/* line break is invalid */
+s2[foo] {prop1 : "
+tring"}
+
+/*simple exact attribute selector, simple ruleset*/
+s3[foo="warning"] {prop1 : value1}
+
+/**
+ *"space separated value list"
+ *attribute selector, simple ruleset
+ */
+s4[foo~="warning"] {prop1 :value1}
+
+/**
+ *"hyphen separated value list" attribute selector,
+ * simple ruleset
+ */
+
+ /*simple class selector, simple ruleset*/
+ s5.warning {prop1 : value}
+
+ E#myid {prop1 : value1}
+
+
+/*below are tests that we know are working*/
+
+/*simple ident pseudo class selector, simple ruleset test*/
+S6:first-child {prop1 : value1 ; prop2 : value2}
+
+/*function pseudo class selector, simple ruleset test*/
+S7:lang(c) {prop1 : value1}
+
+/*Adjacent selectors, simple ruleset test*/
+S8 + s2 {prop1: value1}
+
+/* quoted strings */
+.quotedstrings {
+ -test-string1: "foo'bar";
+ -test-string2: 'foo\'bar';
+ -test-string3: 'foo"bar';
+ -test-string4: "foo\"bar";
+ -test-string5: 'foo\\bar';
+}
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test2.2.css b/src/3rdparty/libcroco/tests/test-inputs/test2.2.css
new file mode 100644
index 0000000..0a58bbe
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test2.2.css
@@ -0,0 +1,686 @@
+p.commentsbody {
+ border-left-style: solid;
+ border-width: 1px;
+ border-color: rgb(0, 0, 0);
+ padding-left: 10px;
+ margin-right: 20px;
+ text-align: justify;
+}
+
+* {
+ font-family: Verdana, Arial, Helvetica, sans-serif, monospace;
+}
+
+body {
+ background: #606060;
+ color: #000000;
+}
+
+a:link {
+ color: #0000FF;
+ background: transparent;
+ text-decoration: none;
+}
+
+a:visited {
+ color: #990099;
+ background: transparent;
+ text-decoration: none;
+}
+
+
+a:active {
+ color: #000000;
+ background: #ADD8E6;
+ text-decoration: none;
+}
+
+
+h1.rubrique_info {
+ color: #990033;
+ margin: 0px 0px 0px 0px;
+ padding: 0em;
+ border: 0px;
+ font-size: 12px;
+}
+
+
+h1.connexe {
+ font-size: 12px;
+ padding: 0em;
+ margin: 0px 0px 0px 0px;
+ color: #990033;
+}
+
+a.rubrique_infolink {
+ text-decoration: none;
+}
+
+ul.rubrique_infoul {
+ display: inline;
+ list-style-type: square;
+}
+ul.rubrique_infoul * {
+ width: 100%;
+}
+li.rubrique_infoul {
+ margin-left: 15px;
+}
+h1 {
+ color: #990033;
+}
+
+div.main {
+ background: white;
+ color: #000000;
+ margin-left: 5px;
+ margin-right: 5px;
+ border: 1px black solid;
+ text-align: left;
+ font-size: 12px;
+}
+div.lsfnbanner {
+ margin-left: 150px;
+ margin-right: 170px;
+ border-top: none;
+ padding-left: 10px;
+ padding-right: 10px;
+ border-bottom: 1px black solid;
+ border-right: 1px black solid;
+ border-left: 1px black solid;
+ text-align: left;
+ font-size: 11px;
+ padding-top: 2px;
+ background-color: #eeeae6;
+}
+div.footer {
+ padding-top: 5px;
+ padding-bottom: 3px;
+ border-top: 1px black solid;
+ border-left: 1px black solid;
+ border-right: 1px black solid;
+ text-align: left;
+ font-size: 9px;
+ background: #dcdff4;
+ width: 600px;
+ margin-top: 40px;
+ margin-left: 20px;
+}
+div.footer p {
+ margin-left: 10px;
+ margin-top: 2px;
+ margin-bottom: 2px;
+}
+
+a.lsfnlink:link,a.lsfnlink:visited,a.lsfnlink:active {
+ text-decoration: none;
+ color: #333333;
+ font-size: 10px;
+}
+a.lsfnlink:hover {
+ text-decoration: underline;
+ color: black;
+}
+div.menubartop {
+ margin-bottom: 10px;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 0px;
+ font-size: 13px;
+}
+div.smallmenubar {
+ background: white;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ font-weight:bold;
+ font-size: 10px;
+ text-align: right;
+}
+div.menuevent {
+ float: left;
+ width: 350px;
+ font-size: 11px;
+ text-align: left;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ padding-left: 10px;
+ font-weight: bold;
+ margin: 0px;
+}
+div.menubar {
+ background: #cac2a8;
+ border-top: 1px black solid;
+ border-bottom: 1px black solid;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 3px;
+ padding-bottom: 2px;
+ font-weight:bold;
+ font-size: 13px;
+}
+div.menubar a {
+ text-decoration: none;
+}
+div.menudate {
+ float: left;
+ width: 130px;
+ padding-top: 5px;
+}
+div.menuaccroche {
+ margin-left: 30px;
+ float: left;
+ text-decoration: underline;
+ font-size: 14px;
+}
+div.menusearch {
+ float: right;
+ text-align: right;
+ padding-top: 5px;
+ width: 170px;
+}
+div.menusearch p {
+ margin: 0px 0px 0px 0px;
+}
+.searchinput {
+ border: solid 1px black;
+}
+a#menulinkselect {
+ color: #ed7e00;
+}
+
+div.leftbox {
+ width: 200px;
+ float: left;
+ padding-left: 5px;
+ padding-right: 5px;
+ padding-bottom: 5px;
+ border-right: 1px black solid;
+ border-bottom: 1px black solid;
+ background: white;
+ margin-bottom: 10px;
+}
+div.leftbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.leftbox h2 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.leftbox ul {
+ list-style-type: square;
+ margin-bottom: 10px;
+ margin-left: 0em;
+ padding-left: 0em;
+}
+div.leftbox li {
+ margin-left: 10px;
+}
+
+div.rightbox {
+ width: 150px;
+ float: right;
+ padding-top: 10px;
+ padding-left: 5px;
+ padding-right: 15px;
+ padding-bottom: 5px;
+ border-left: 1px black solid;
+ border-bottom: 1px black solid;
+ text-align: left;
+}
+div.newjournaldiv {
+ text-align: justify;
+ margin-left: 10%;
+ font-size: 12px;
+ width: 600px;
+}
+div.newjournaldiv p {
+ margin-bottom: 0px;
+ margin-top: 20px;
+}
+div.journaldiv {
+ margin-left: 0px;
+ margin-right: 0px;
+ margin-top: 20px;
+ margin-bottom: 20px;
+ border: 1px black solid;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ padding-right: 10px;
+ padding-left: 10px;
+ background-color: #eef;
+}
+div.journaldiv p {
+ margin-top: 10px;
+ margin-bottom: 0px;
+}
+div.journaldiv h1 {
+ color: #990033;
+ font-size: 14px;
+ margin: 0px;
+}
+div.journaldiv h2 {
+ font-size: 10px;
+ margin: 0px;
+}
+div.tipdiv {
+ margin-left: 220px;
+ margin-right: 50px;
+ margin-top: 20px;
+ padding-top: 5px;
+ padding-right: 10px;
+ padding-left: 10px;
+ text-align: justify;
+ background-color: #eee;
+ border: black solid 1px;
+}
+div.tipdiv h1 {
+ font-weight: bold;
+ font-size: 14px;
+ color: black;
+ margin-top: 0px;
+ margin-bottom: 20px;
+}
+div.tipdiv h2 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 12px;
+ margin: 0px;
+}
+
+div.newsdiv {
+ margin-left: 220px;
+ margin-right: 180px;
+ margin-top: 10px;
+ margin-bottom: 20px;
+ text-align: justify;
+}
+div.newsdiv h1 {
+ font-weight: bold;
+ font-size: 14px;
+ margin: 0px;
+}
+div.newsdiv h2 {
+ font-weight: normal;
+ font-size: 12px;
+ margin: 0px;
+}
+div.newsdiv h3 {
+ font-weight: normal;
+ font-size: 12px;
+ margin-bottom: 20px;
+}
+div.objdiv {
+ margin-left: 220px;
+ margin-right: 20px;
+ margin-top: 10px;
+ margin-bottom: 20px;
+}
+
+h1.newstitle {
+ text-align: left;
+ font-size: 14px;
+ margin: 0px 0px 0px 0px;
+ color: black;
+}
+div.titlediv {
+ border-top: solid #cac2a8 2px;
+ margin-top: 20px;
+ background-color: #eeeae6;
+ padding-left: 10px;
+ font-size: 11px;
+}
+div.bodydiv {
+ border: solid #9e9784 1px;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 10px;
+ padding-bottom: 5px;
+ margin-top: 2px;
+ text-align: justify;
+}
+
+div.comments {
+ padding: 10px;
+ border-top: solid 2px #d37537;
+ border-bottom: solid 2px #d37537;
+ margin-top: 20px;
+ margin-bottom: 10px;
+ background-color: #cacaca;
+ font-size: 12px;
+ line-height: 1.3em;
+}
+
+p.commentsbody {
+ border-left-style: solid;
+ border-width: 1px;
+ border-color: rgb(0, 0, 0);
+ padding-left: 10px;
+ text-align: justify;
+ margin-right: 20px;
+}
+
+div.commentsreply {
+ margin-left: 220px;
+ text-align: center;
+ margin-top: 50px;
+}
+
+ul.commentsul {
+ list-style-type: none;
+ margin-bottom: 10px;
+ margin-left: 1.25em;
+ padding-left: 0em;
+ border-left: 1px solid black;
+}
+ul.commentsli {
+ margin: 10px;
+}
+div.comments li {
+ margin-top: 20px;
+ margin-left: 2px;
+}
+
+div.comments h1 {
+ font-size: 12px;
+ color: black;
+ margin: 0px 20px 3px 0px;
+ background-color: rgb(226, 226, 226);
+ padding-left: 1px;
+ font-weight: none;
+}
+
+div.articlediv {
+ padding-left: 20px;
+ padding-right: 20px;
+ padding-top: 10px;
+ padding-bottom: 20px;
+ margin-right: 10px;
+ margin-left: 220px;
+ border: solid 1px black;
+ margin-top: 10px;
+ text-align: justify;
+ background-color: #E2E2E2;
+}
+img {
+ border: 0px;
+}
+div.sectionimg {
+ float: left;
+ margin-right: 10px;
+ margin-top: 5px;
+}
+p.hautpage {
+ margin-top: 20px;
+ margin-bottom: 20px;
+ margin-left: 10px;
+}
+div.leftcol {
+ width: 202px;
+ width: 202px;
+ float: left;
+ padding: 0px;
+}
+div.logodiv {
+ border-right: 1px black solid;
+ border-bottom: 1px black solid;
+ padding: 0px;
+ line-height: 0px
+}
+div.loginbox {
+ margin-left: 4px;
+ border: solid #a59f8b 1px;
+ margin-top: 2px;
+ padding: 5px;
+ background-color: #fff2e8;
+ font-size: 10px;
+}
+div.loginbox p {
+ margin: 0px;
+ padding: 0px;
+}
+div.loginbox ul {
+ margin-left: 10px;
+ margin-top: 0px;
+ margin-bottom: 0px;
+ padding: 0px;
+ list-style-type: none;
+}
+div.loginbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.loginbox h2 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.loginbox h3 {
+ margin-top: 0px;
+ margin-bottom: 5px;
+ font-size: 12px;
+}
+div.polldivtitle {
+ margin-bottom: 1px;
+ background-color: #cac2a8;
+ margin-left: 4px;
+ margin-top: 15px;
+ padding-left: 5px;
+ font-size: 10px;
+ border-top: solid #a59f8b 1px;
+ border-bottom: solid #a59f8b 1px;
+ text-transform: uppercase;
+}
+div.polldiv {
+ margin-left: 4px;
+ border: 1px #a59f8b solid;
+ margin-top: 0px;
+ padding: 5px;
+ background: #fff2e8;
+}
+div.polldiv p {
+margin: 5px; padding: 0px;
+}
+div.polldiv ul {
+ margin-left: 5px;
+ margin-top: 0px;
+ margin-bottom: 10px;
+ padding: 0px;
+ list-style-type: none;
+}
+div.otherboxtitle {
+ margin-bottom: 2px;
+ background-color: #e3dabc;
+ margin-left: 4px;
+ margin-top: 15px;
+ padding-left: 5px;
+ padding-top: 2px;
+ font-size: 11px;
+ border-top: solid #777364 1px;
+ border-bottom: solid #777364 1px;
+ text-transform: uppercase;
+ font-weight: bold;
+}
+div.otherbox {
+ margin-left: 4px;
+ border: 1px #a59f8b solid;
+ margin-top: 0px;
+ padding: 5px;
+ text-align: justify;
+ background: #fff2e8;
+ font-size: 10px;
+}
+div.otherbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.otherbox h2 {
+ font-weight: bold;
+ font-size: 11px;
+ margin: 0px;
+}
+div.otherbox p {
+ margin-top: 5px;
+ margin-bottom: 10px;
+}
+div.rightlogo {
+ width: 90px;
+ float: right;
+ margin-right: 0px;
+ padding-top: 0px;
+ padding-left: 0px;
+ padding-bottom: 0px;
+}
+div.centraldiv {
+ margin-left: 220px;
+ margin-right: 10px;
+ margin-bottom: 20px;
+ margin-top: 10px;
+}
+div.centraldiv h1 {
+ font-weight: bold;
+ font-size: 14px;
+ margin: 0px;
+}
+div.centraldiv h2 {
+ font-weight: normal;
+ font-size: 12px;
+ margin: 0px;
+}
+div.centraldiv h3 {
+ font-weight: normal;
+ font-size: 12px;
+ margin-bottom: 20px;
+}
+div.centralinfo {
+ position:relative;
+ height:160px;
+}
+div.lefttopbox {
+ position:relative;
+ padding-left: 5px;
+ padding-right: 5px;
+ padding-top: 5px;
+ border: 1px #a59f8b solid;
+ text-align: justify;
+ background: #fff2e8;
+ font-size: 12px;
+ width: 47%;
+ float: left;
+}
+div.lefttopbox p {
+ margin-top: 5px; margin-bottom: 10px;
+}
+div.lefttopbox h1 {
+ font-size: 13px;
+ font-weight: bold;
+ margin: 0px;
+ text-align: right;
+}
+div.lefttopbox h2 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.lefttopbox h3 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.righttopbox {
+ position:relative;
+ border: 1px #a59f8b solid;
+ background: white;
+ padding: 5px;
+ text-align: justify;
+ font-size: 12px;
+ width: 47%;
+ float: right;
+}
+div.righttopbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.righttopbox h2 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.boardindex {
+ text-align: justify;
+ font-size: 11px;
+ padding: 10px;
+ margin-left: 20px;
+ margin-right: 20px;
+}
+a.boardindex:link,a.boardindex:visited,a.boardindex:active {
+ text-decoration:none;
+ color: red;
+}
+div.boardleftmsg {
+ float: left;
+ margin-top: 3px;
+}
+div.boardrightmsg {
+ margin-left: 130px;
+ margin-top: 3px;
+ padding-left: 5px;
+}
+div.journalbody {
+ margin-left: 40px;
+ margin-top: 40px;
+}
+div.journalbody h1 {
+ font-size: 15px;
+ font-weight: bold;
+}
+div.journalbody p {
+ margin-bottom: 20px;
+}
+.formulaire {
+ border: solid 1px black;
+font-size: 12px;
+background-color: #eef;
+color: #000000;
+}
+.newcomments {
+ color: red;
+ font-weight: bold;
+}
+div.commentsreplythanks {
+ margin-left: 100px;
+ margin-top: 50px;
+ margin-right: 100px;
+ background-color: #eee;
+ border: black solid 1px;
+ padding: 10px;
+}
+div.archivediv {
+ margin-right: 20px;
+}
+.archivedate {
+ color:#f30;
+}
+.archivelink {
+ font-size: 14px;
+ font-weight: bold;
+ text-decoration: underline;
+}
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test2.css b/src/3rdparty/libcroco/tests/test-inputs/test2.css
new file mode 100644
index 0000000..2442048
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test2.css
@@ -0,0 +1,9 @@
+
+/*simple selector and simple rulset test*/
+S1 {prop1 : value1}
+
+/*Simple selector list and simple ruleset test*/
+s1,s2 {color: black ; background: white}
+
+/*descendants and child selector list, simple ruleset test*/
+s1 s2, S3 > s4 {prop1 : value1 ; prop2 : value2}
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test3.1.css b/src/3rdparty/libcroco/tests/test-inputs/test3.1.css
new file mode 100644
index 0000000..9c53843
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test3.1.css
@@ -0,0 +1,36 @@
+S1:lang(c) {prop1 : value1}
+
+/*simple Attribute set selectors*/
+s1[foo] {prop1 : value1}
+
+/*simple exact attribute selector, simple ruleset*/
+s1[foo="warning"] {prop1 : value1}
+
+/**
+ *"space separated value list"
+ *attribute selector, simple ruleset
+ */
+s1[foo~="warning"] {prop1 :value1}
+
+/**
+ *"hyphen separated value list" attribute selector,
+ * simple ruleset
+ */
+
+ /*simple class selector, simple ruleset*/
+ s1.warning {prop1 : value}
+
+ E#myid {prop1 : value1}
+
+
+/*below are tests that we know are working*/
+
+/*simple ident pseudo class selector, simple ruleset test*/
+S1:first-child {prop1 : value1 ; prop2 : value2}
+
+/*function pseudo class selector, simple ruleset test => merdoie*/
+S1:lang(c) {prop1 : value1}
+
+/*Adjacent selectors, simple ruleset test*/
+S1 + s2 {prop1: value1}
+
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test3.2.css b/src/3rdparty/libcroco/tests/test-inputs/test3.2.css
new file mode 100644
index 0000000..2857fc4
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test3.2.css
@@ -0,0 +1,693 @@
+h1.rubrique_info {
+ color: #990033;
+ margin: 0px 0px 0px 0px;
+ padding: 0em;
+ border: 0px;
+ font-size: 12px;
+}
+
+* {
+ font-family: Verdana, Arial, Helvetica, sans-serif, monospace;
+}
+
+body {
+ background: #606060;
+ color: #000000;
+}
+
+a:link {
+ color: #0000FF;
+ background: transparent;
+ text-decoration: none;
+}
+
+a:visited {
+ color: #990099;
+ background: transparent;
+ text-decoration: none;
+}
+
+
+a:active {
+ color: #000000;
+ background: #ADD8E6;
+ text-decoration: none;
+}
+
+
+h1.rubrique_info {
+ color: #990033;
+ margin: 0px 0px 0px 0px;
+ padding: 0em;
+ border: 0px;
+ font-size: 12px;
+}
+
+/*
+h1.connexe {
+ font-size: 12px;
+ padding: 0em;
+ margin: 0px 0px 0px 0px;
+ color: #990033;
+}
+
+
+a.rubrique_infolink {
+ text-decoration: none;
+}
+
+
+ul.rubrique_infoul {
+ display: inline;
+ list-style-type: square;
+}
+
+
+ul.rubrique_infoul * {
+ width: 100%;
+}
+
+li.rubrique_infoul {
+ margin-left: 15px;
+}
+h1 {
+ color: #990033;
+}
+
+div.main {
+ background: white;
+ color: #000000;
+ margin-left: 5px;
+ margin-right: 5px;
+ border: 1px black solid;
+ text-align: left;
+ font-size: 12px;
+}
+div.lsfnbanner {
+ margin-left: 150px;
+ margin-right: 170px;
+ border-top: none;
+ padding-left: 10px;
+ padding-right: 10px;
+ border-bottom: 1px black solid;
+ border-right: 1px black solid;
+ border-left: 1px black solid;
+ text-align: left;
+ font-size: 11px;
+ padding-top: 2px;
+ background-color: #eeeae6;
+}
+div.footer {
+ padding-top: 5px;
+ padding-bottom: 3px;
+ border-top: 1px black solid;
+ border-left: 1px black solid;
+ border-right: 1px black solid;
+ text-align: left;
+ font-size: 9px;
+ background: #dcdff4;
+ width: 600px;
+ margin-top: 40px;
+ margin-left: 20px;
+}
+div.footer p {
+ margin-left: 10px;
+ margin-top: 2px;
+ margin-bottom: 2px;
+}
+
+a.lsfnlink:link,a.lsfnlink:visited,a.lsfnlink:active {
+ text-decoration: none;
+ color: #333333;
+ font-size: 10px;
+}
+a.lsfnlink:hover {
+ text-decoration: underline;
+ color: black;
+}
+div.menubartop {
+ margin-bottom: 10px;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 0px;
+ font-size: 13px;
+}
+div.smallmenubar {
+ background: white;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ font-weight:bold;
+ font-size: 10px;
+ text-align: right;
+}
+
+div.menuevent {
+ float: left;
+ width: 350px;
+ font-size: 11px;
+ text-align: left;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ padding-left: 10px;
+ font-weight: bold;
+ margin: 0px;
+}
+div.menubar {
+ background: #cac2a8;
+ border-top: 1px black solid;
+ border-bottom: 1px black solid;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 3px;
+ padding-bottom: 2px;
+ font-weight:bold;
+ font-size: 13px;
+}
+div.menubar a {
+ text-decoration: none;
+}
+div.menudate {
+ float: left;
+ width: 130px;
+ padding-top: 5px;
+}
+div.menuaccroche {
+ margin-left: 30px;
+ float: left;
+ text-decoration: underline;
+ font-size: 14px;
+}
+div.menusearch {
+ float: right;
+ text-align: right;
+ padding-top: 5px;
+ width: 170px;
+}
+div.menusearch p {
+ margin: 0px 0px 0px 0px;
+}
+.searchinput {
+ border: solid 1px black;
+}
+a#menulinkselect {
+ color: #ed7e00;
+}
+
+div.leftbox {
+ width: 200px;
+ float: left;
+ padding-left: 5px;
+ padding-right: 5px;
+ padding-bottom: 5px;
+ border-right: 1px black solid;
+ border-bottom: 1px black solid;
+ background: white;
+ margin-bottom: 10px;
+}
+div.leftbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.leftbox h2 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.leftbox ul {
+ list-style-type: square;
+ margin-bottom: 10px;
+ margin-left: 0em;
+ padding-left: 0em;
+}
+div.leftbox li {
+ margin-left: 10px;
+}
+
+div.rightbox {
+ width: 150px;
+ float: right;
+ padding-top: 10px;
+ padding-left: 5px;
+ padding-right: 15px;
+ padding-bottom: 5px;
+ border-left: 1px black solid;
+ border-bottom: 1px black solid;
+ text-align: left;
+}
+div.newjournaldiv {
+ text-align: justify;
+ margin-left: 10%;
+ font-size: 12px;
+ width: 600px;
+}
+div.newjournaldiv p {
+ margin-bottom: 0px;
+ margin-top: 20px;
+}
+div.journaldiv {
+ margin-left: 0px;
+ margin-right: 0px;
+ margin-top: 20px;
+ margin-bottom: 20px;
+ border: 1px black solid;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ padding-right: 10px;
+ padding-left: 10px;
+ background-color: #eef;
+}
+div.journaldiv p {
+ margin-top: 10px;
+ margin-bottom: 0px;
+}
+div.journaldiv h1 {
+ color: #990033;
+ font-size: 14px;
+ margin: 0px;
+}
+div.journaldiv h2 {
+ font-size: 10px;
+ margin: 0px;
+}
+div.tipdiv {
+ margin-left: 220px;
+ margin-right: 50px;
+ margin-top: 20px;
+ padding-top: 5px;
+ padding-right: 10px;
+ padding-left: 10px;
+ text-align: justify;
+ background-color: #eee;
+ border: black solid 1px;
+}
+div.tipdiv h1 {
+ font-weight: bold;
+ font-size: 14px;
+ color: black;
+ margin-top: 0px;
+ margin-bottom: 20px;
+}
+div.tipdiv h2 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 12px;
+ margin: 0px;
+}
+
+div.newsdiv {
+ margin-left: 220px;
+ margin-right: 180px;
+ margin-top: 10px;
+ margin-bottom: 20px;
+ text-align: justify;
+}
+div.newsdiv h1 {
+ font-weight: bold;
+ font-size: 14px;
+ margin: 0px;
+}
+div.newsdiv h2 {
+ font-weight: normal;
+ font-size: 12px;
+ margin: 0px;
+}
+div.newsdiv h3 {
+ font-weight: normal;
+ font-size: 12px;
+ margin-bottom: 20px;
+}
+div.objdiv {
+ margin-left: 220px;
+ margin-right: 20px;
+ margin-top: 10px;
+ margin-bottom: 20px;
+}
+
+h1.newstitle {
+ text-align: left;
+ font-size: 14px;
+ margin: 0px 0px 0px 0px;
+ color: black;
+}
+div.titlediv {
+ border-top: solid #cac2a8 2px;
+ margin-top: 20px;
+ background-color: #eeeae6;
+ padding-left: 10px;
+ font-size: 11px;
+}
+div.bodydiv {
+ border: solid #9e9784 1px;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 10px;
+ padding-bottom: 5px;
+ margin-top: 2px;
+ text-align: justify;
+}
+
+div.comments {
+ padding: 10px;
+ border-top: solid 2px #d37537;
+ border-bottom: solid 2px #d37537;
+ margin-top: 20px;
+ margin-bottom: 10px;
+ background-color: #cacaca;
+ font-size: 12px;
+ line-height: 1.3em;
+}
+
+p.commentsbody {
+ border-left-style: solid;
+ border-width: 1px;
+ border-color: rgb(0, 0, 0);
+ padding-left: 10px;
+ text-align: justify;
+ margin-right: 20px;
+}
+
+div.commentsreply {
+ margin-left: 220px;
+ text-align: center;
+ margin-top: 50px;
+}
+
+ul.commentsul {
+ list-style-type: none;
+ margin-bottom: 10px;
+ margin-left: 1.25em;
+ padding-left: 0em;
+ border-left: 1px solid black;
+}
+ul.commentsli {
+ margin: 10px;
+}
+div.comments li {
+ margin-top: 20px;
+ margin-left: 2px;
+}
+
+div.comments h1 {
+ font-size: 12px;
+ color: black;
+ margin: 0px 20px 3px 0px;
+ background-color: rgb(226, 226, 226);
+ padding-left: 1px;
+ font-weight: none;
+}
+
+div.articlediv {
+ padding-left: 20px;
+ padding-right: 20px;
+ padding-top: 10px;
+ padding-bottom: 20px;
+ margin-right: 10px;
+ margin-left: 220px;
+ border: solid 1px black;
+ margin-top: 10px;
+ text-align: justify;
+ background-color: #E2E2E2;
+}
+img {
+ border: 0px;
+}
+div.sectionimg {
+ float: left;
+ margin-right: 10px;
+ margin-top: 5px;
+}
+p.hautpage {
+ margin-top: 20px;
+ margin-bottom: 20px;
+ margin-left: 10px;
+}
+div.leftcol {
+ width: 202px;
+ width: 202px;
+ float: left;
+ padding: 0px;
+}
+div.logodiv {
+ border-right: 1px black solid;
+ border-bottom: 1px black solid;
+ padding: 0px;
+ line-height: 0px
+}
+div.loginbox {
+ margin-left: 4px;
+ border: solid #a59f8b 1px;
+ margin-top: 2px;
+ padding: 5px;
+ background-color: #fff2e8;
+ font-size: 10px;
+}
+div.loginbox p {
+ margin: 0px;
+ padding: 0px;
+}
+div.loginbox ul {
+ margin-left: 10px;
+ margin-top: 0px;
+ margin-bottom: 0px;
+ padding: 0px;
+ list-style-type: none;
+}
+div.loginbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.loginbox h2 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.loginbox h3 {
+ margin-top: 0px;
+ margin-bottom: 5px;
+ font-size: 12px;
+}
+div.polldivtitle {
+ margin-bottom: 1px;
+ background-color: #cac2a8;
+ margin-left: 4px;
+ margin-top: 15px;
+ padding-left: 5px;
+ font-size: 10px;
+ border-top: solid #a59f8b 1px;
+ border-bottom: solid #a59f8b 1px;
+ text-transform: uppercase;
+}
+div.polldiv {
+ margin-left: 4px;
+ border: 1px #a59f8b solid;
+ margin-top: 0px;
+ padding: 5px;
+ background: #fff2e8;
+}
+div.polldiv p {
+margin: 5px; padding: 0px;
+}
+div.polldiv ul {
+ margin-left: 5px;
+ margin-top: 0px;
+ margin-bottom: 10px;
+ padding: 0px;
+ list-style-type: none;
+}
+div.otherboxtitle {
+ margin-bottom: 2px;
+ background-color: #e3dabc;
+ margin-left: 4px;
+ margin-top: 15px;
+ padding-left: 5px;
+ padding-top: 2px;
+ font-size: 11px;
+ border-top: solid #777364 1px;
+ border-bottom: solid #777364 1px;
+ text-transform: uppercase;
+ font-weight: bold;
+}
+div.otherbox {
+ margin-left: 4px;
+ border: 1px #a59f8b solid;
+ margin-top: 0px;
+ padding: 5px;
+ text-align: justify;
+ background: #fff2e8;
+ font-size: 10px;
+}
+div.otherbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.otherbox h2 {
+ font-weight: bold;
+ font-size: 11px;
+ margin: 0px;
+}
+div.otherbox p {
+ margin-top: 5px;
+ margin-bottom: 10px;
+}
+div.rightlogo {
+ width: 90px;
+ float: right;
+ margin-right: 0px;
+ padding-top: 0px;
+ padding-left: 0px;
+ padding-bottom: 0px;
+}
+div.centraldiv {
+ margin-left: 220px;
+ margin-right: 10px;
+ margin-bottom: 20px;
+ margin-top: 10px;
+}
+div.centraldiv h1 {
+ font-weight: bold;
+ font-size: 14px;
+ margin: 0px;
+}
+div.centraldiv h2 {
+ font-weight: normal;
+ font-size: 12px;
+ margin: 0px;
+}
+div.centraldiv h3 {
+ font-weight: normal;
+ font-size: 12px;
+ margin-bottom: 20px;
+}
+div.centralinfo {
+ position:relative;
+ height:160px;
+}
+div.lefttopbox {
+ position:relative;
+ padding-left: 5px;
+ padding-right: 5px;
+ padding-top: 5px;
+ border: 1px #a59f8b solid;
+ text-align: justify;
+ background: #fff2e8;
+ font-size: 12px;
+ width: 47%;
+ float: left;
+}
+div.lefttopbox p {
+ margin-top: 5px; margin-bottom: 10px;
+}
+div.lefttopbox h1 {
+ font-size: 13px;
+ font-weight: bold;
+ margin: 0px;
+ text-align: right;
+}
+div.lefttopbox h2 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.lefttopbox h3 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.righttopbox {
+ position:relative;
+ border: 1px #a59f8b solid;
+ background: white;
+ padding: 5px;
+ text-align: justify;
+ font-size: 12px;
+ width: 47%;
+ float: right;
+}
+div.righttopbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.righttopbox h2 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.boardindex {
+ text-align: justify;
+ font-size: 11px;
+ padding: 10px;
+ margin-left: 20px;
+ margin-right: 20px;
+}
+a.boardindex:link,a.boardindex:visited,a.boardindex:active {
+ text-decoration:none;
+ color: red;
+}
+div.boardleftmsg {
+ float: left;
+ margin-top: 3px;
+}
+div.boardrightmsg {
+ margin-left: 130px;
+ margin-top: 3px;
+ padding-left: 5px;
+}
+div.journalbody {
+ margin-left: 40px;
+ margin-top: 40px;
+}
+div.journalbody h1 {
+ font-size: 15px;
+ font-weight: bold;
+}
+div.journalbody p {
+ margin-bottom: 20px;
+}
+
+.formulaire {
+ border: solid 1px black;
+font-size: 12px;
+background-color: #eef;
+color: #000000;
+}
+.newcomments {
+ color: red;
+ font-weight: bold;
+}
+div.commentsreplythanks {
+ margin-left: 100px;
+ margin-top: 50px;
+ margin-right: 100px;
+ background-color: #eee;
+ border: black solid 1px;
+ padding: 10px;
+}
+div.archivediv {
+ margin-right: 20px;
+}
+.archivedate {
+ color:#f30;
+}
+.archivelink {
+ font-size: 14px;
+ font-weight: bold;
+ text-decoration: underline;
+}
+*/ \ No newline at end of file
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test3.css b/src/3rdparty/libcroco/tests/test-inputs/test3.css
new file mode 100644
index 0000000..2442048
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test3.css
@@ -0,0 +1,9 @@
+
+/*simple selector and simple rulset test*/
+S1 {prop1 : value1}
+
+/*Simple selector list and simple ruleset test*/
+s1,s2 {color: black ; background: white}
+
+/*descendants and child selector list, simple ruleset test*/
+s1 s2, S3 > s4 {prop1 : value1 ; prop2 : value2}
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test4.1.css b/src/3rdparty/libcroco/tests/test-inputs/test4.1.css
new file mode 100644
index 0000000..01bd9d4
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test4.1.css
@@ -0,0 +1,682 @@
+* {
+ font-family: Verdana, Arial, Helvetica, sans-serif, monospace !important;
+}
+
+tutu:class1:class2 {
+ test:ok ;
+}
+
+body {
+ background: #606060;
+ color: #000000;
+}
+
+
+a:link {
+ color: #0000FF;
+ background: transparent;
+ text-decoration: none;
+}
+
+
+a:visited {
+ color: #990099;
+ background: transparent;
+ text-decoration: none;
+}
+
+
+a:active {
+ color: #000000;
+ background: #ADD8E6;
+ text-decoration: none;
+}
+
+h1.rubrique_info {
+ color: #990033;
+ margin: 0px 0px 0px 0px;
+ padding: 0.4em;
+ border: 0px;
+ font-size: 12px;
+}
+h1.connexe {
+ font-size: 12px;
+ padding: 0.9em;
+ margin: 0px 0px 0px 0px;
+ color: #990033;
+}
+
+a.rubrique_infolink {
+ text-decoration: none;
+}
+
+ul.rubrique_infoul {
+ display: inline;
+ list-style-type: square;
+}
+ul.rubrique_infoul * {
+ width: 100%;
+}
+li.rubrique_infoul {
+ margin-left: 15px;
+}
+h1 {
+ color: #990033;
+}
+
+div.main {
+ background: white;
+ color: #000000;
+ margin-left: 5px;
+ margin-right: 5px;
+ border: 1px black solid;
+ text-align: left;
+ font-size: 12px;
+}
+div.lsfnbanner {
+ margin-left: 150px;
+ margin-right: 170px;
+ border-top: none;
+ padding-left: 10px;
+ padding-right: 10px;
+ border-bottom: 1px black solid;
+ border-right: 1px black solid;
+ border-left: 1px black solid;
+ text-align: left;
+ font-size: 11px;
+ padding-top: 2px;
+ background-color: #eeeae6;
+}
+div.footer {
+ padding-top: 5px;
+ padding-bottom: 3px;
+ border-top: 1px black solid;
+ border-left: 1px black solid;
+ border-right: 1px black solid;
+ text-align: left;
+ font-size: 9px;
+ background: #dcdff4;
+ width: 600px;
+ margin-top: 40px;
+ margin-left: 20px;
+}
+div.footer p {
+ margin-left: 10px;
+ margin-top: 2px;
+ margin-bottom: 2px;
+}
+
+a.lsfnlink:link,a.lsfnlink:visited,a.lsfnlink:active {
+ text-decoration: none;
+ color: #333333;
+ font-size: 10px;
+}
+a.lsfnlink:hover {
+ text-decoration: underline;
+ color: black;
+}
+div.menubartop {
+ margin-bottom: 10px;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 0px;
+ font-size: 13px;
+}
+div.smallmenubar {
+ background: white;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ font-weight:bold;
+ font-size: 10px;
+ text-align: right;
+}
+div.menuevent {
+ float: left;
+ width: 350px;
+ font-size: 11px;
+ text-align: left;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ padding-left: 10px;
+ font-weight: bold;
+ margin: 0px;
+}
+div.menubar {
+ background: #cac2a8;
+ border-top: 1px black solid;
+ border-bottom: 1px black solid;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 3px;
+ padding-bottom: 2px;
+ font-weight:bold;
+ font-size: 13px;
+}
+div.menubar a {
+ text-decoration: none;
+}
+div.menudate {
+ float: left;
+ width: 130px;
+ padding-top: 5px;
+}
+div.menuaccroche {
+ margin-left: 30px;
+ float: left;
+ text-decoration: underline;
+ font-size: 14px;
+}
+div.menusearch {
+ float: right;
+ text-align: right;
+ padding-top: 5px;
+ width: 170px;
+}
+div.menusearch p {
+ margin: 0px 0px 0px 0px;
+}
+.searchinput {
+ border: solid 1px black;
+}
+a#menulinkselect {
+ color: #ed7e00;
+}
+
+div.leftbox {
+ width: 200px;
+ float: left;
+ padding-left: 5px;
+ padding-right: 5px;
+ padding-bottom: 5px;
+ border-right: 1px black solid;
+ border-bottom: 1px black solid;
+ background: white;
+ margin-bottom: 10px;
+}
+div.leftbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.leftbox h2 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.leftbox ul {
+ list-style-type: square;
+ margin-bottom: 10px;
+ margin-left: 0.3em;
+ padding-left: 0.2em;
+}
+div.leftbox li {
+ margin-left: 10px;
+}
+
+div.rightbox {
+ width: 150px;
+ float: right;
+ padding-top: 10px;
+ padding-left: 5px;
+ padding-right: 15px;
+ padding-bottom: 5px;
+ border-left: 1px black solid;
+ border-bottom: 1px black solid;
+ text-align: left;
+}
+div.newjournaldiv {
+ text-align: justify;
+ margin-left: 10%;
+ font-size: 12px;
+ width: 600px;
+}
+div.newjournaldiv p {
+ margin-bottom: 0px;
+ margin-top: 20px;
+}
+div.journaldiv {
+ margin-left: 0px;
+ margin-right: 0px;
+ margin-top: 20px;
+ margin-bottom: 20px;
+ border: 1px black solid;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ padding-right: 10px;
+ padding-left: 10px;
+ background-color: #eef;
+}
+div.journaldiv p {
+ margin-top: 10px;
+ margin-bottom: 0px;
+}
+div.journaldiv h1 {
+ color: #990033;
+ font-size: 14px;
+ margin: 0px;
+}
+div.journaldiv h2 {
+ font-size: 10px;
+ margin: 0px;
+}
+div.tipdiv {
+ margin-left: 220px;
+ margin-right: 50px;
+ margin-top: 20px;
+ padding-top: 5px;
+ padding-right: 10px;
+ padding-left: 10px;
+ text-align: justify;
+ background-color: #eee;
+ border: black solid 1px;
+}
+div.tipdiv h1 {
+ font-weight: bold;
+ font-size: 14px;
+ color: black;
+ margin-top: 0px;
+ margin-bottom: 20px;
+}
+div.tipdiv h2 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 12px;
+ margin: 0px;
+}
+
+div.newsdiv {
+ margin-left: 220px;
+ margin-right: 180px;
+ margin-top: 10px;
+ margin-bottom: 20px;
+ text-align: justify;
+}
+div.newsdiv h1 {
+ font-weight: bold;
+ font-size: 14px;
+ margin: 0px;
+}
+div.newsdiv h2 {
+ font-weight: normal;
+ font-size: 12px;
+ margin: 0px;
+}
+div.newsdiv h3 {
+ font-weight: normal;
+ font-size: 12px;
+ margin-bottom: 20px;
+}
+div.objdiv {
+ margin-left: 220px;
+ margin-right: 20px;
+ margin-top: 10px;
+ margin-bottom: 20px;
+}
+
+h1.newstitle {
+ text-align: left;
+ font-size: 14px;
+ margin: 0px 0px 0px 0px;
+ color: black;
+}
+div.titlediv {
+ border-top: solid #cac2a8 2px;
+ margin-top: 20px;
+ background-color: #eeeae6;
+ padding-left: 10px;
+ font-size: 11px;
+}
+div.bodydiv {
+ border: solid #9e9784 1px;
+ padding-left: 10px;
+ padding-right: 10px;
+ padding-top: 10px;
+ padding-bottom: 5px;
+ margin-top: 2px;
+ text-align: justify;
+}
+
+div.comments {
+ padding: 10px;
+ border-top: solid 2px #d37537;
+ border-bottom: solid 2px #d37537;
+ margin-top: 20px;
+ margin-bottom: 10px;
+ background-color: #cacaca;
+ font-size: 12px;
+ line-height: 1.3em;
+}
+
+
+p.commentsbody {
+ border-left-style: solid;
+ border-width: 1px;
+ border-color: rgb(0, 0, 0);
+ padding-left: 10px;
+ text-align: justify;
+ margin-right: 20px;
+}
+
+
+div.commentsreply {
+ margin-left: 220px;
+ text-align: center;
+ margin-top: 50px;
+}
+
+ul.commentsul {
+ list-style-type: none;
+ margin-bottom: 10px;
+ margin-left: 1.25em;
+ padding-left: 0em;
+ border-left: 1px solid black;
+}
+ul.commentsli {
+ margin: 10px;
+}
+div.comments li {
+ margin-top: 20px;
+ margin-left: 2px;
+}
+
+div.comments h1 {
+ font-size: 12px;
+ color: black;
+ margin: 0px 20px 3px 0px;
+ background-color: rgb(226, 226, 226);
+ padding-left: 1px;
+ font-weight: none;
+}
+
+div.articlediv {
+ padding-left: 20px;
+ padding-right: 20px;
+ padding-top: 10px;
+ padding-bottom: 20px;
+ margin-right: 10px;
+ margin-left: 220px;
+ border: solid 1px black;
+ margin-top: 10px;
+ text-align: justify;
+ background-color: #E2E2E2;
+}
+img {
+ border: 0px;
+}
+div.sectionimg {
+ float: left;
+ margin-right: 10px;
+ margin-top: 5px;
+}
+p.hautpage {
+ margin-top: 20px;
+ margin-bottom: 20px;
+ margin-left: 10px;
+}
+div.leftcol {
+ width: 202px;
+ width: 202px;
+ float: left;
+ padding: 0px;
+}
+div.logodiv {
+ border-right: 1px black solid;
+ border-bottom: 1px black solid;
+ padding: 0px;
+ line-height: 0px
+}
+div.loginbox {
+ margin-left: 4px;
+ border: solid #a59f8b 1px;
+ margin-top: 2px;
+ padding: 5px;
+ background-color: #fff2e8;
+ font-size: 10px;
+}
+div.loginbox p {
+ margin: 0px;
+ padding: 0px;
+}
+div.loginbox ul {
+ margin-left: 10px;
+ margin-top: 0px;
+ margin-bottom: 0px;
+ padding: 0px;
+ list-style-type: none;
+}
+div.loginbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.loginbox h2 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.loginbox h3 {
+ margin-top: 0px;
+ margin-bottom: 5px;
+ font-size: 12px;
+}
+div.polldivtitle {
+ margin-bottom: 1px;
+ background-color: #cac2a8;
+ margin-left: 4px;
+ margin-top: 15px;
+ padding-left: 5px;
+ font-size: 10px;
+ border-top: solid #a59f8b 1px;
+ border-bottom: solid #a59f8b 1px;
+ text-transform: uppercase;
+}
+div.polldiv {
+ margin-left: 4px;
+ border: 1px #a59f8b solid;
+ margin-top: 0px;
+ padding: 5px;
+ background: #fff2e8;
+}
+div.polldiv p {
+margin: 5px; padding: 0px;
+}
+div.polldiv ul {
+ margin-left: 5px;
+ margin-top: 0px;
+ margin-bottom: 10px;
+ padding: 0px;
+ list-style-type: none;
+}
+div.otherboxtitle {
+ margin-bottom: 2px;
+ background-color: #e3dabc;
+ margin-left: 4px;
+ margin-top: 15px;
+ padding-left: 5px;
+ padding-top: 2px;
+ font-size: 11px;
+ border-top: solid #777364 1px;
+ border-bottom: solid #777364 1px;
+ text-transform: uppercase;
+ font-weight: bold;
+}
+div.otherbox {
+ margin-left: 4px;
+ border: 1px #a59f8b solid;
+ margin-top: 0px;
+ padding: 5px;
+ text-align: justify;
+ background: #fff2e8;
+ font-size: 10px;
+}
+div.otherbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.otherbox h2 {
+ font-weight: bold;
+ font-size: 11px;
+ margin: 0px;
+}
+div.otherbox p {
+ margin-top: 5px;
+ margin-bottom: 10px;
+}
+div.rightlogo {
+ width: 90px;
+ float: right;
+ margin-right: 0px;
+ padding-top: 0px;
+ padding-left: 0px;
+ padding-bottom: 0px;
+}
+div.centraldiv {
+ margin-left: 220px;
+ margin-right: 10px;
+ margin-bottom: 20px;
+ margin-top: 10px;
+}
+div.centraldiv h1 {
+ font-weight: bold;
+ font-size: 14px;
+ margin: 0px;
+}
+div.centraldiv h2 {
+ font-weight: normal;
+ font-size: 12px;
+ margin: 0px;
+}
+div.centraldiv h3 {
+ font-weight: normal;
+ font-size: 12px;
+ margin-bottom: 20px;
+}
+div.centralinfo {
+ position:relative;
+ height:160px;
+}
+div.lefttopbox {
+ position:relative;
+ padding-left: 5px;
+ padding-right: 5px;
+ padding-top: 5px;
+ border: 1px #a59f8b solid;
+ text-align: justify;
+ background: #fff2e8;
+ font-size: 12px;
+ width: 47%;
+ float: left;
+}
+div.lefttopbox p {
+ margin-top: 5px; margin-bottom: 10px;
+}
+div.lefttopbox h1 {
+ font-size: 13px;
+ font-weight: bold;
+ margin: 0px;
+ text-align: right;
+}
+div.lefttopbox h2 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.lefttopbox h3 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.righttopbox {
+ position:relative;
+ border: 1px #a59f8b solid;
+ background: white;
+ padding: 5px;
+ text-align: justify;
+ font-size: 12px;
+ width: 47%;
+ float: right;
+}
+div.righttopbox h1 {
+ text-transform: uppercase;
+ font-weight: bold;
+ color: #ed7e00;
+ font-size: 10px;
+ margin: 0px;
+}
+div.righttopbox h2 {
+ font-weight: bold;
+ font-size: 12px;
+ margin: 0px;
+}
+div.boardindex {
+ text-align: justify;
+ font-size: 11px;
+ padding: 10px;
+ margin-left: 20px;
+ margin-right: 20px;
+}
+a.boardindex:link,a.boardindex:visited,a.boardindex:active {
+ text-decoration:none;
+ color: red;
+}
+div.boardleftmsg {
+ float: left;
+ margin-top: 3px;
+}
+div.boardrightmsg {
+ margin-left: 130px;
+ margin-top: 3px;
+ padding-left: 5px;
+}
+div.journalbody {
+ margin-left: 40px;
+ margin-top: 40px;
+}
+div.journalbody h1 {
+ font-size: 15px;
+ font-weight: bold;
+}
+div.journalbody p {
+ margin-bottom: 20px;
+}
+.formulaire {
+ border: solid 1px black;
+font-size: 12px;
+background-color: #eef;
+color: #000000;
+}
+.newcomments {
+ color: red;
+ font-weight: bold;
+}
+div.commentsreplythanks {
+ margin-left: 100px;
+ margin-top: 50px;
+ margin-right: 100px;
+ background-color: #eee;
+ border: black solid 1px;
+ padding: 10px;
+}
+div.archivediv {
+ margin-right: 20px;
+}
+.archivedate {
+ color:#f30;
+}
+.archivelink {
+ font-size: 14px;
+ font-weight: bold;
+ text-decoration: underline;
+}
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test4.2.css b/src/3rdparty/libcroco/tests/test-inputs/test4.2.css
new file mode 100644
index 0000000..2dafbef
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test4.2.css
@@ -0,0 +1,24 @@
+@charset "ISO-8859-1" ;
+
+@import url("http://www.yahoo.com/css") print , screen ;
+
+@font-face {
+ font-family: "Robson Celtic";
+ src: url("http://site/fonts/rob-celt")
+}
+
+
+
+@page left:one-two {
+ margin: 10pt;
+ border:none
+}
+
+@media print , screen , projection {
+ H1 { font-family: "Robson Celtic", serif }
+
+ P {
+ background: black ;
+ foreground: white ;
+ }
+}
diff --git a/src/3rdparty/libcroco/tests/test-inputs/test5.1.css b/src/3rdparty/libcroco/tests/test-inputs/test5.1.css
new file mode 100644
index 0000000..26c3627
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/test5.1.css
@@ -0,0 +1,14 @@
+.class5 {prop8: val8}
+#id6 {prop9: val9}
+[attr4|=val4] {prop7: val7}
+[attr3~=val3_2] {prop6: val6}
+[attr2=val2] {prop5: val5}
+:first-child {first-child-prop: first-child-value}
+:lang(fr) {lang-prop: lang-value}
+E2[attr2=val2] {prop8: val8}
+E0 {prop0: val0}
+E0+E1{pro1:val1}
+E1 E1-1 {prop2: val2}
+E1 > E1-1 {prop3: val3}
+document E1-1 {prop4: val4}
+
diff --git a/src/3rdparty/libcroco/tests/test-inputs/unknown-at-rule.css b/src/3rdparty/libcroco/tests/test-inputs/unknown-at-rule.css
new file mode 100644
index 0000000..7680999
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/unknown-at-rule.css
@@ -0,0 +1,3 @@
+@namespace url(http://www.w3.org/1999/xhtml); /* set default namespace
+to
+HTML */ \ No newline at end of file
diff --git a/src/3rdparty/libcroco/tests/test-inputs/unknown-at-rule2.css b/src/3rdparty/libcroco/tests/test-inputs/unknown-at-rule2.css
new file mode 100644
index 0000000..0c4a191
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-inputs/unknown-at-rule2.css
@@ -0,0 +1,3 @@
+@namespace url(http://www.w3.org/1999/xhtml); dummyrule { } /* set
+default
+namespace to HTML */ \ No newline at end of file
diff --git a/src/3rdparty/libcroco/tests/test-lots-of-comments.sh b/src/3rdparty/libcroco/tests/test-lots-of-comments.sh
new file mode 100755
index 0000000..f2eae9b
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-lots-of-comments.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+test -z "$CSSLINT" && . ./global-test-vars.sh
+
+$CSSLINT $TEST_INPUTS_DIR/lots-of-comments.css
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/Makefile.am b/src/3rdparty/libcroco/tests/test-output-refs/Makefile.am
new file mode 100644
index 0000000..b113e7f
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/Makefile.am
@@ -0,0 +1,16 @@
+EXTRA_DIST=test0.1.css.out \
+test1.css.out \
+test2.1.css.out \
+test2.2.css.out \
+test2.css.out \
+test3.1.css.out \
+test3.2.css.out \
+test3.css.out \
+test4.1.css.out \
+test4.2.css.out \
+test6.out \
+test-prop-ident.out \
+test-unknown-at-rule.out \
+test-unknown-at-rule2.out \
+test-several-media.out \
+test5.1.css.out
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test-functional-notation.out b/src/3rdparty/libcroco/tests/test-output-refs/test-functional-notation.out
new file mode 100644
index 0000000..7fa05fd
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test-functional-notation.out
@@ -0,0 +1,7 @@
+foo {
+ bar : attr(width, length, calc(70% -5px))
+}
+
+foo {
+ bar : attr(x, y)
+}
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test-lots-of-comments.out b/src/3rdparty/libcroco/tests/test-output-refs/test-lots-of-comments.out
new file mode 100644
index 0000000..59b08ef
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test-lots-of-comments.out
@@ -0,0 +1,26 @@
+@charset "utf8" ;
+
+@import url("http://pouet.com")screen, paper, aural ;
+
+@page coin :pseudo-page {
+ page-prop0 : page-val0;
+ page-prop1 : page-val1
+}
+
+
+@media paper, aural {
+ x {
+ foo : fooval;
+ bar : barval
+ }
+}
+
+@font-face {
+ font-prop1 : font1;
+ font-prop2 : font2
+}
+
+x>y[attr="val"].class#tatati z+toto {
+ prop1 : function(a);
+ prop2 : val2
+}
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test-parsing-location.out b/src/3rdparty/libcroco/tests/test-output-refs/test-parsing-location.out
new file mode 100644
index 0000000..7be4584
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test-parsing-location.out
@@ -0,0 +1,219 @@
+
+
+@charset "utf8";
+
+/********************************************
+ * Parsing location information of the @charset rule
+ ********************************************/
+ /*@charset*/
+ /*line:1 column:1 byte offset:0 */
+ /*utf8*/
+ /*line:1 column:10 byte offset:9 */
+
+@import url("http://pouet.com") screen, paper, aural;
+
+/*****************************************************
+ *Parsing location information for the @import rule
+ ******************************************************/
+
+ /*@import*/
+ /*line:3 column:1 byte offset:19 */
+
+ /*http://pouet.com*/
+ /*line:3 column:9 byte offset:27 */
+
+ /*screen*/
+ /*line:3 column:33 byte offset:51 */
+
+ /*paper*/
+ /*line:3 column:41 byte offset:59 */
+
+ /*aural*/
+ /*line:3 column:48 byte offset:66 */
+
+@import url("http://pouet.com") screen2, paper2, aural2;
+
+/*****************************************************
+ *Parsing location information for the @import rule
+ ******************************************************/
+
+ /*@import*/
+ /*line:4 column:1 byte offset:74 */
+
+ /*http://pouet.com*/
+ /*line:4 column:9 byte offset:82 */
+
+ /*screen2*/
+ /*line:4 column:31 byte offset:104 */
+
+ /*paper2*/
+ /*line:4 column:40 byte offset:113 */
+
+ /*aural2*/
+ /*line:4 column:48 byte offset:121 */
+
+@page coin :pseudo-page
+
+ /*@page*/
+ /*line:6 column:1 byte offset:131 */
+ /*coin*/
+ /*line:6 column:7 byte offset:137 */
+ /*pseudo-page*/
+ /*line:6 column:13 byte offset:143 */
+
+{
+
+
+page-prop0 : page-val0;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*page-prop0*/
+ /*line:7 column:7 byte offset:163 */
+ /*page-val0*/
+ /*line:7 column:19 byte offset:175 */
+
+
+page-prop1 : page-val1;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*page-prop1*/
+ /*line:8 column:7 byte offset:193 */
+ /*page-val1*/
+ /*line:8 column:19 byte offset:205 */
+}
+@media paper, aural
+ /*@media*/
+ /*line:11 column:1 byte offset:220 */
+ /*paper*/
+ /*line:11 column:8 byte offset:227 */
+ /*aural*/
+ /*line:11 column:15 byte offset:234 */
+
+{
+x {
+/************************************************
+ *Parsing location information of the selector
+ ************************************************/
+/*x*/
+/*line:12 column:5 byte offset:246 */
+ /*x*/
+ /*line:12 column:5 byte offset:246 */
+
+
+foo : fooval;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*foo*/
+ /*line:13 column:7 byte offset:256 */
+ /*fooval*/
+ /*line:13 column:12 byte offset:261 */
+
+
+bar : barval;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*bar*/
+ /*line:14 column:7 byte offset:276 */
+ /*barval*/
+ /*line:14 column:12 byte offset:281 */
+ }
+
+}
+@font-face {
+/******************************************************
+ Parsing location information for the @font-face rule
+ ******************************************************/
+
+ /*@font-face*/
+ /*line:18 column:1 byte offset:299 */
+
+
+font-prop1 : font1;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*font-prop1*/
+ /*line:19 column:2 byte offset:313 */
+ /*font1*/
+ /*line:19 column:14 byte offset:325 */
+
+
+font-prop2 : font2;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*font-prop2*/
+ /*line:20 column:2 byte offset:334 */
+ /*font2*/
+ /*line:20 column:14 byte offset:346 */
+}
+x>y[attr="val"].class#tatati z+toto {
+/************************************************
+ *Parsing location information of the selector
+ ************************************************/
+/*x*/
+/*line:22 column:1 byte offset:356 */
+ /*x*/
+ /*line:22 column:1 byte offset:356 */
+/*y[attr="val"].class#tatati*/
+/*line:22 column:5 byte offset:360 */
+ /*y*/
+ /*line:22 column:5 byte offset:360 */
+
+ /*[attr="val"]*/
+ /*line:22 column:6 byte offset:361 */
+
+ /*.class*/
+ /*line:22 column:17 byte offset:372 */
+
+ /*#tatati*/
+ /*line:22 column:22 byte offset:377 */
+/*z*/
+/*line:22 column:30 byte offset:385 */
+ /*z*/
+ /*line:22 column:30 byte offset:385 */
+/*toto*/
+/*line:22 column:34 byte offset:389 */
+ /*toto*/
+ /*line:22 column:34 byte offset:389 */
+
+
+prop1 : function(a);
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*prop1*/
+ /*line:23 column:2 byte offset:396 */
+ /*function(a)*/
+ /*line:23 column:9 byte offset:403 */
+
+
+prop2 : val2;
+
+
+/************************************************
+ *Parsing location information of the property
+ ************************************************/
+ /*prop2*/
+ /*line:24 column:2 byte offset:418 */
+ /*val2*/
+ /*line:24 column:9 byte offset:425 */
+ }
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test-prop-ident.out b/src/3rdparty/libcroco/tests/test-output-refs/test-prop-ident.out
new file mode 100644
index 0000000..149e8f5
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test-prop-ident.out
@@ -0,0 +1,3 @@
+:-foo-pseudo {
+ -foo-bar-prop : -foobar-value
+}
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test-sel-child-class.out b/src/3rdparty/libcroco/tests/test-output-refs/test-sel-child-class.out
new file mode 100644
index 0000000..aadd508
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test-sel-child-class.out
@@ -0,0 +1,4 @@
+Properties of xml element p are:
+ color : aqua
+=====================
+
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test-several-media.out b/src/3rdparty/libcroco/tests/test-output-refs/test-several-media.out
new file mode 100644
index 0000000..4b3cbdd
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test-several-media.out
@@ -0,0 +1,17 @@
+@media screen {
+ a:link {
+ text-decoration : none
+ }
+ div {
+ width : 50%
+ }
+}
+
+@media print {
+ a {
+ color : red
+ }
+ div {
+ width : 57%
+ }
+}
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test-unknown-at-rule.out b/src/3rdparty/libcroco/tests/test-output-refs/test-unknown-at-rule.out
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test-unknown-at-rule.out
@@ -0,0 +1 @@
+
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test-unknown-at-rule2.out b/src/3rdparty/libcroco/tests/test-output-refs/test-unknown-at-rule2.out
new file mode 100644
index 0000000..a356a7d
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test-unknown-at-rule2.out
@@ -0,0 +1,2 @@
+dummyrule {
+}
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test0.1.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test0.1.css.out
new file mode 100644
index 0000000..16475bd
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test0.1.css.out
@@ -0,0 +1 @@
+9811110012132123103232109971141031051103258324811212032481121203250481121203248112120591032321041011051031041163258324948483759103232989799107103114111117110100325832357070701012510106532123103232991111081111143258323548485151545459103232116101120116451001019911111497116105111110325832117110100101114108105110101101251010655810810511010732123103232991111081111143258323548485151545459103232116101120116451001019911111497116105111110325832117110100101114108105110101101251010655811810511510511610110032123103232991111081111143258323548485151545459103232116101120116451001019911111497116105111110325832117110100101114108105110101101251010655897991161051181013212310323299111108111114325832355757575757571012510106558104111118101114321231032329911110811111432583235575757575757101251010104494432104504432104513212310323210997114103105110325832481121205910323211297100100105110103325832481121201012510103598971101101011143212310323210211111011645102971091051081213258321129710897116105110111443210310111111410310597443211810111410097110974432971141059710844321159711011545115101114105102591032329911110811111432583235515151591032321161111125848591032321021111101164511510512210132583211011111410997108591032321021111101164511910110510310411632583211011111410997108591012510103598971101101011143297443235989711011010111432975810810511010744323598971101101011143297581181051151051161011004432359897110110101114329758979911610511810144323598971101101011143297581041111181011143212310323210211111011645102971091051081213258321181011141009711097443297114105971084432115971101154511510111410510259103232102111110116451151051221013258321201204510897114103101591032329911110811111432583235515151591032321161011201164510010199111114971161051111103258321101111101011012510104610010111599114105112116105111110321231032321021111101164510297109105108121325832118101114100971109744329711410597108443211597110115451151011141051025910323299111108111114325832355151515910323210211111011645115105122101325832115109971081085910323211610112011645116114971101151021111141093258321101111101011012510103599111110116101110116321231032321121111151051161051111103258329798115111108117116101591032329897991071031141111171101003258323570707059103232116111112583250483759321032321081011021165832504837591032329811111410010111432583249112120321151111081051003235707070101251010359911111011697105110101114321231032329897991071031141111171101003258323570707059103232981111141001011143258324911212032115111108105100323570707010125101035108105110107115321231032321129710010010511010332583249531121205910323298111114100101114325832491121203211511110810510032357070705910323211910510011610432583250484811212010125101046981081111033212310323211297100100105110103325832504811212059103232989799107103114111117110100325832357070701012510104698108111103981111001213212310323210211111011645102971091051081213258321181011141009711097443297114105971084432115971101154511510111410510259103232991111081111143258323551515159103232102111110116451151051221013258321151099710810859103232102111110116451191011051031041163258321101111141099710859103232989799107103114111117110100325832357070705910323210810511010145104101105103104116325832495348371012510104698108111103981111001213297443246981081111039811110012132975810810511010744324698108111103981111001213297581181051151051161011004432469810811110398111100121329758979911610511810144324698108111103981111001213297581041111181011143212310323210211111011645119101105103104116325832110111114109971085910323211610112011645100101991111149711610511111032583211711010010111410810511010110125101046116105116108101321231032321021111101164510297109105108121325832118101114100971109744329711410597108443211597110115451151011141051025910323210211111011645115105122101325832109101100105117109591032329911110811111432583235545454101251010461009711610132123103232102111110116451029710910510812132583211810111410097110974432971141059710844321151011141051025910323210211111011645115105122101325832108971141031015910323299111108111114325832355151515910323298111114100101114459811111611611110932583249112120321151111081051003235575757591032321099711410310511045981111161161111093258324948112120591032321021111101164511910110510310411632583298111108100101251010461121111151161011003212310323210211111011645102971091051081213258321181011141009711097443297114105971084432115971101154511510111410510259103232102111110116451151051221013258321204511510997108108591032329911110811111432583235484848484848591032321099711410310511045981111161161111093258325053112120101251010469997108101110100971143212310323210211111011645102971091051081213258321181011141009711097443297114105971084432115971101154511510111410510259103232991111081111143258323551515159103232102111110116451151051221013258321204511510997108108591032321021111101164511910110510310411632583211011111410997108591032329897991071031141111171101003258323570707059103232108105110101451041011051031041163258324952483759103232112971001001051101033258325011212059103232116101120116459710810510311032583210810110211610125101046999710810111010097114104101971003212310323210211111011645102971091051081213258321129710897116105110111443210310111111410310597443211610510910111532110101119321141111099711044321151011141051025910323299111108111114325832355454545448485910323210211111011645115105122101325832115109971081085910323210211111011645119101105103104116325832110111114109971085910323211297100100105110103325832501121205910323210810111611610111445115112979910511010332583248465110110959103232989799107103114111117110100325832357070705910323211610112011645116114971101151021111141093258321171121121011149997115101591032321161011201164597108105103110325832108101102116101251010461151051001013212310323210211111011645102971091051081213258321181011141009711097443297114105971084432115971101154511510111410510259103232991111081111143258323551515159103232102111110116451151051221013258321204511510997108108591032321021111101164511910110510310411632583211011111410997108591032329897991071031141111171101003258323570707059103232108105110101451041011051031041163258324952483759103232112971001001051101033258325011212010125101035109101110117989711432123103232102111110116451029710910510812132583211810111410097110974432971141059710844321159711011545115101114105102591032329911110811111432583235515151591032321021111101164511510512210132583211510997108108591032321021111101164511910110510310411632583211011111410997108591032321121111151051161051111105897981151111081171161015910323211611111258504837591032321129710010010511010358325011212059103232108101116116101114451151129799105110103325832484649101109591032329897991071031141111171101003258323570707059103232116101120116451161149711011510211111410932583211711211210111499971151011012510104611512111010010599971161013212310323210211111011645102971091051081213258321181011141009711097443297114105971084432115971101154511510111410510259103232102111110116451151051221013258321201204511510997108108591032321081051101014510410110510310411632583249524837591032321129710010010511010332583250112120591032321099711410310511045116111112325832495311212059103232989799107103114111117110100325832357070701012510104611211111910111410110032123103232102111110116451029710910510812132583211810111410097110974432971141059710844321159711011545115101114105102591032329911110811111432583235545454591032321021111101164511510512210132583212045115109971081085910323210810511010145104101105103104116325832495248375910323211610112011645116114971101151021111141093258321171121121011149997115101591032321129710010010511010332583250112120591032321099711410310511045116111112325832534811212059103232108101116116101114451151129799105110103325832484650101109591032329897991071031141111171101003258323570707010125101046991111091091011101161154598111100121321231032321021111101164510297109105108121325832118101114100971109744329711410597108443211597110115451151011141051025910323299111108111114325832355454545910323210211111011645115105122101325832115109971081085910323210211111011645119101105103104116325832110111114109971085910323298979910710311411111711010032583235707070591032321081051101014510410110510310411632583249524837591032321129710010010511010345981111161161111093258324948112120591032321129710010010511010345116111112325832494811212059103232981111141001011144598111116116111109325832491121203210011111611610110032355757571012510104699111109109101110116115451121111151163212310323210211111011645102971091051081213258321181011141009711097443297114105971084432115971101154511510111410510259103232991111081111143258323554545459103232102111110116451151051221013258321204511510997108108591032321021111101164511910110510310411632583211011111410997108591032329897991071031141111171101003258323570707010125101046116114979910798979910745117114108321231032321021111101164510297109105108121325832118101114100971109744329711410597108443211597110115451151011141051025910323299111108111114325832355454545910323210211111011645115105122101325832115109971081085910323210211111011645119101105103104116325832110111114109971085910323298979910710311411111711010032583235707070591032321081051101014510410110510310411632583249524837591032321129710010010511010332583253112120591032329811111410010111432583249112120321001111161161011003235575757101251010461161149799107989799107459811110012132123103232102111110116451029710910510812132583211810111410097110974432971141059710844321159711011545115101114105102591032329911110811111432583235545454591032321021111101164511510512210132583211510997108108591032321021111101164511910110510310411632583211011111410997108591032329897991071031141111171101003258323570707059103232108105110101451041011051031041163258324952483759103232112971001001051101034598111116116111109325832494811212059103232112971001001051101034511611111232583249481121205910323298111114100101114459811111611611110932583249112120321001111161161011003235575757101251010461161149799107989799107451121111151163212310323210211111011645102971091051081213258321181011141009711097443297114105971084432115971101154511510111410510259103232991111081111143258323554545459103232102111110116451151051221013258321204511510997108108591032321021111101164511910110510310411632583211011111410997108591032329897991071031141111171101003258323570707010125101046991111091091011101161154510410197100321231032321021111101164510297109105108121325832118101114100971109744329711410597108443211597110115451151011141051025910323210211111011645115105122101325832115109971081085910323299111108111114325832355454545910323298111114100101114459811111611611110932583249112120321151111081051003235575757591032321099711410310511045116111112325832504811212059103232102111110116451191011051031041163258329811110810059103232989799107103114111117110100325832357070701012510103598971101101011144599111109109101110116115112111112321231032321021111101164510297109105108121325832118101114100971109744329711410597108443211597110115451151011141051025910323299111108111114325832357070705910323210211111011645115105122101325832108971141031015910323210211111011645119101105103104116325832981111081005910323298111114100101114451081011021163258324911212032115111108105100323570707059103232981111141001011144511410510310411632583249112120321151111081051003235707070591032329811111410010111445116111112325832491121203211511110810510032357070705910323298979910710311411111711010032583235484851515454591032321129710010010511010345108101102116325832495311212059103232112971001001051101034511410510310411632583249531121205910323211297100100105110103451161111123258325311212059103232112971001001051101034598111116116111109325832531121201012510 \ No newline at end of file
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test1.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test1.css.out
new file mode 100644
index 0000000..b03c8a4
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test1.css.out
@@ -0,0 +1,316 @@
+body {
+
+ background-color: #E5E5E5;
+
+ scrollbar-face-color: #CCCCCC;
+
+ scrollbar-highlight-color: #FFFFFF;
+
+ scrollbar-shadow-color: #CCCCCC;
+
+ scrollbar-3dlight-color: #D1D7DC;
+
+ scrollbar-arrow-color: #000000;
+
+ scrollbar-track-color: #FFFFFF;
+
+ scrollbar-darkshadow-color: #000000;
+
+}
+
+
+
+font, th, td, p {
+
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+
+ font-size: 11px;
+
+}
+
+
+
+h1, h2 { font-size: 11px; color: #000000; font-weight: bold; }
+
+
+
+a:link, a:active, a:visited { color: #000000; }
+
+
+
+a:hover { color: #CC0000; text-decoration: underline; }
+
+
+
+hr { height: 0px; border: solid #CCCCCC 0px; border-top-width: 1px; }
+
+
+
+small { font-size: 10px; }
+
+
+
+input, textarea, select {
+
+ font: normal 11px Verdana, Arial, Helvetica, sans-serif;
+
+ color: #000000;
+
+ border-color: #000000;
+
+}
+
+
+
+input { text-indent: 2px; }
+
+
+
+
+input.post, textarea.post, select {
+
+ background-color: #FFFFFF;
+
+}
+
+
+
+
+th {
+
+ font-size: 11px; color: #CCCCCC; font-weight: bold;
+
+ background-color: #000000; height: 25px;
+
+ background-image: url(/~wiceyto/test/templates/blacknwhite/images/cellpic3.gif);
+
+}
+
+
+
+
+.fontspec, .tablefont {
+
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+
+ font-size: 11px;
+
+}
+
+
+
+.navbartext, .navbarfont {
+
+ font-size: 11px; color: #000000; font-weight: bold;
+
+}
+
+
+
+.navbartext a, .navbarfont a {
+
+ color: #000000; font-weight: bold; text-decoration: none;
+
+}
+
+
+
+.navbartext a:hover, .navbarfont a:hover {
+
+ color: #CC0000; text-decoration: none;
+
+}
+
+
+
+.tablespec, .guestbook { background-color: #FFFFFF; border: 2px #000000 solid; }
+
+.tablespec th, .tablespec td { color: #000000; background-color: #CCCCCC; }
+
+.tablespec th { background-image: none; }
+
+
+
+.messageblock {
+
+ border: dashed 1px;
+
+ margin-right: 4em; margin-left: 4em;
+
+ padding: 3em;
+
+}
+
+
+
+/* $MessageOpenCode - the body of text of the posts */
+
+.messagebody { font-size: 12px; line-height: 18px; }
+
+.messagebody a { color: #000000; text-decoration: underline; }
+
+.messagebody a:hover { color: #CC0000; text-decoration: underline; }
+
+
+
+
+.newcode { font-size: 11px; color: #CC0000; font-weight: bold; }
+
+.admincode { font-size: 11px; color: #990000; font-style: bold; }
+
+
+
+
+.bodyline { background-color: #FFFFFF; border: 1px #000000 solid; }
+
+
+
+
+.quote, .code {
+
+ background-color: #FAFAFA; border: #D1D7DC; border-style: solid;
+
+ border-top-width: 1px; border-right-width: 1px;
+
+ border-bottom-width: 1px; border-left-width: 1px;
+
+}
+
+
+
+.quote {
+
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+
+ font-size: 11px;
+
+ color: #444444; line-height: 125%;
+
+}
+
+
+
+.code {
+
+ font-family: Courier, 'Courier New', sans-serif;
+
+ font-size: 11px;
+
+ color: #CC0000;
+
+}
+
+
+
+
+input.button {
+
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+
+ font-size: 11px;
+
+ color: #000000;
+
+ background-color: #FFFFFF;
+
+}
+
+
+
+/* Format button rollover help line. Actually it's a text box
+
+ set to the same color as the background so no one will know. */
+
+.helpline { background-color: #CCCCCC; border-style: none; }
+
+
+
+/* additional table cell colors and backgrounds */
+
+td.row2 { background-color: #CCCCCC; }
+
+td.row1 { background-color: #CCCCCC; }
+
+td.row3 { background-color: #D1D7DC; }
+
+
+
+/* additional general text */
+
+.gen { font-size: 12px; }
+
+.genmed { font-size: 11px; }
+
+.gensmall { font-size: 10px; }
+
+.gen, .genmed, .gensmall { color: #000000; }
+
+a.gen, a.genmed, a.gensmall { color: #000000; text-decoration: none; }
+
+a.gen:hover, a.genmed:hover, a.gensmall:hover { color: #CC0000; text-decoration: underline; }
+
+
+
+/* import fancy styles. For IE only. NS4.x doesn't use the @import function */
+
+@import url("/your.site/webbbs/themes/formIE.css");
+
+
+
+/* END of blacknwhite.css */
+
+
+
+
+
+
+
+/* Appendix.2-2: Example fancy styles CSS file
+
+Paste these into a text file and save as formIE.css */
+
+
+
+/* Fancy form styles for IE */
+
+
+
+input, textarea, select {
+
+border-top-width : 1px;
+
+border-right-width : 1px;
+
+border-bottom-width : 1px;
+
+border-left-width : 1px;
+
+}
+
+
+
+input { text-indent : 2px; }
+
+
+
+input.button {
+
+border-top-width : 1px;
+
+border-right-width : 1px;
+
+border-bottom-width : 1px;
+
+border-left-width : 1px;
+
+}
+
+
+
+.postbody { line-height: 18px}
+
+.magic {
+ margin-left: -20px;
+}
+
+/* END of formIE.css */
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test2.1.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test2.1.css.out
new file mode 100644
index 0000000..4874e68
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test2.1.css.out
@@ -0,0 +1,173 @@
+***************
+start_document
+***************
+
+***************
+start_selector
+s1[foo]
+***************
+
+***************
+property
+prop1: 'String'
+***************
+
+***************
+end_selector
+s1[foo]
+***************
+
+***************
+start_selector
+s2[foo]
+***************
+
+***************
+start_selector
+s3[foo="warning"]
+***************
+
+***************
+property
+prop1: value1
+***************
+
+***************
+end_selector
+s3[foo="warning"]
+***************
+
+***************
+start_selector
+s4[foo~="warning"]
+***************
+
+***************
+property
+prop1: value1
+***************
+
+***************
+end_selector
+s4[foo~="warning"]
+***************
+
+***************
+start_selector
+s5.warning
+***************
+
+***************
+property
+prop1: value
+***************
+
+***************
+end_selector
+s5.warning
+***************
+
+***************
+start_selector
+E#myid
+***************
+
+***************
+property
+prop1: value1
+***************
+
+***************
+end_selector
+E#myid
+***************
+
+***************
+start_selector
+S6:first-child
+***************
+
+***************
+property
+prop1: value1
+***************
+
+***************
+property
+prop2: value2
+***************
+
+***************
+end_selector
+S6:first-child
+***************
+
+***************
+start_selector
+S7:lang(c)
+***************
+
+***************
+property
+prop1: value1
+***************
+
+***************
+end_selector
+S7:lang(c)
+***************
+
+***************
+start_selector
+S8+s2
+***************
+
+***************
+property
+prop1: value1
+***************
+
+***************
+end_selector
+S8+s2
+***************
+
+***************
+start_selector
+.quotedstrings
+***************
+
+***************
+property
+-test-string1: "foo'bar"
+***************
+
+***************
+property
+-test-string2: "foo'bar"
+***************
+
+***************
+property
+-test-string3: 'foo"bar'
+***************
+
+***************
+property
+-test-string4: 'foo"bar'
+***************
+
+***************
+property
+-test-string5: 'foo\\bar'
+***************
+
+***************
+end_selector
+.quotedstrings
+***************
+
+***************
+end_document
+***************
+
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test2.2.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test2.2.css.out
new file mode 100644
index 0000000..f0d631a
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test2.2.css.out
@@ -0,0 +1,3328 @@
+***************
+start_document
+***************
+
+***************
+start_selector
+p.commentsbody
+***************
+
+***************
+property
+border-left-style: solid
+***************
+
+***************
+property
+border-width: 1px
+***************
+
+***************
+property
+border-color: rgb(0, 0, 0)
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+margin-right: 20px
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+end_selector
+p.commentsbody
+***************
+
+***************
+start_selector
+*
+***************
+
+***************
+property
+font-family: Verdana, Arial, Helvetica, sans-serif, monospace
+***************
+
+***************
+end_selector
+*
+***************
+
+***************
+start_selector
+body
+***************
+
+***************
+property
+background: #606060
+***************
+
+***************
+property
+color: #000000
+***************
+
+***************
+end_selector
+body
+***************
+
+***************
+start_selector
+a:link
+***************
+
+***************
+property
+color: #0000FF
+***************
+
+***************
+property
+background: transparent
+***************
+
+***************
+property
+text-decoration: none
+***************
+
+***************
+end_selector
+a:link
+***************
+
+***************
+start_selector
+a:visited
+***************
+
+***************
+property
+color: #990099
+***************
+
+***************
+property
+background: transparent
+***************
+
+***************
+property
+text-decoration: none
+***************
+
+***************
+end_selector
+a:visited
+***************
+
+***************
+start_selector
+a:active
+***************
+
+***************
+property
+color: #000000
+***************
+
+***************
+property
+background: #ADD8E6
+***************
+
+***************
+property
+text-decoration: none
+***************
+
+***************
+end_selector
+a:active
+***************
+
+***************
+start_selector
+h1.rubrique_info
+***************
+
+***************
+property
+color: #990033
+***************
+
+***************
+property
+margin: 0px 0px 0px 0px
+***************
+
+***************
+property
+padding: 0em
+***************
+
+***************
+property
+border: 0px
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+end_selector
+h1.rubrique_info
+***************
+
+***************
+start_selector
+h1.connexe
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+padding: 0em
+***************
+
+***************
+property
+margin: 0px 0px 0px 0px
+***************
+
+***************
+property
+color: #990033
+***************
+
+***************
+end_selector
+h1.connexe
+***************
+
+***************
+start_selector
+a.rubrique_infolink
+***************
+
+***************
+property
+text-decoration: none
+***************
+
+***************
+end_selector
+a.rubrique_infolink
+***************
+
+***************
+start_selector
+ul.rubrique_infoul
+***************
+
+***************
+property
+display: inline
+***************
+
+***************
+property
+list-style-type: square
+***************
+
+***************
+end_selector
+ul.rubrique_infoul
+***************
+
+***************
+start_selector
+ul.rubrique_infoul *
+***************
+
+***************
+property
+width: 100%
+***************
+
+***************
+end_selector
+ul.rubrique_infoul *
+***************
+
+***************
+start_selector
+li.rubrique_infoul
+***************
+
+***************
+property
+margin-left: 15px
+***************
+
+***************
+end_selector
+li.rubrique_infoul
+***************
+
+***************
+start_selector
+h1
+***************
+
+***************
+property
+color: #990033
+***************
+
+***************
+end_selector
+h1
+***************
+
+***************
+start_selector
+div.main
+***************
+
+***************
+property
+background: white
+***************
+
+***************
+property
+color: #000000
+***************
+
+***************
+property
+margin-left: 5px
+***************
+
+***************
+property
+margin-right: 5px
+***************
+
+***************
+property
+border: 1px black solid
+***************
+
+***************
+property
+text-align: left
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+end_selector
+div.main
+***************
+
+***************
+start_selector
+div.lsfnbanner
+***************
+
+***************
+property
+margin-left: 150px
+***************
+
+***************
+property
+margin-right: 170px
+***************
+
+***************
+property
+border-top: none
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+padding-right: 10px
+***************
+
+***************
+property
+border-bottom: 1px black solid
+***************
+
+***************
+property
+border-right: 1px black solid
+***************
+
+***************
+property
+border-left: 1px black solid
+***************
+
+***************
+property
+text-align: left
+***************
+
+***************
+property
+font-size: 11px
+***************
+
+***************
+property
+padding-top: 2px
+***************
+
+***************
+property
+background-color: #eeeae6
+***************
+
+***************
+end_selector
+div.lsfnbanner
+***************
+
+***************
+start_selector
+div.footer
+***************
+
+***************
+property
+padding-top: 5px
+***************
+
+***************
+property
+padding-bottom: 3px
+***************
+
+***************
+property
+border-top: 1px black solid
+***************
+
+***************
+property
+border-left: 1px black solid
+***************
+
+***************
+property
+border-right: 1px black solid
+***************
+
+***************
+property
+text-align: left
+***************
+
+***************
+property
+font-size: 9px
+***************
+
+***************
+property
+background: #dcdff4
+***************
+
+***************
+property
+width: 600px
+***************
+
+***************
+property
+margin-top: 40px
+***************
+
+***************
+property
+margin-left: 20px
+***************
+
+***************
+end_selector
+div.footer
+***************
+
+***************
+start_selector
+div.footer p
+***************
+
+***************
+property
+margin-left: 10px
+***************
+
+***************
+property
+margin-top: 2px
+***************
+
+***************
+property
+margin-bottom: 2px
+***************
+
+***************
+end_selector
+div.footer p
+***************
+
+***************
+start_selector
+a.lsfnlink:link, a.lsfnlink:visited, a.lsfnlink:active
+***************
+
+***************
+property
+text-decoration: none
+***************
+
+***************
+property
+color: #333333
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+end_selector
+a.lsfnlink:link, a.lsfnlink:visited, a.lsfnlink:active
+***************
+
+***************
+start_selector
+a.lsfnlink:hover
+***************
+
+***************
+property
+text-decoration: underline
+***************
+
+***************
+property
+color: black
+***************
+
+***************
+end_selector
+a.lsfnlink:hover
+***************
+
+***************
+start_selector
+div.menubartop
+***************
+
+***************
+property
+margin-bottom: 10px
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+padding-right: 10px
+***************
+
+***************
+property
+padding-top: 0px
+***************
+
+***************
+property
+font-size: 13px
+***************
+
+***************
+end_selector
+div.menubartop
+***************
+
+***************
+start_selector
+div.smallmenubar
+***************
+
+***************
+property
+background: white
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+padding-right: 10px
+***************
+
+***************
+property
+padding-top: 0px
+***************
+
+***************
+property
+padding-bottom: 0px
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+property
+text-align: right
+***************
+
+***************
+end_selector
+div.smallmenubar
+***************
+
+***************
+start_selector
+div.menuevent
+***************
+
+***************
+property
+float: left
+***************
+
+***************
+property
+width: 350px
+***************
+
+***************
+property
+font-size: 11px
+***************
+
+***************
+property
+text-align: left
+***************
+
+***************
+property
+padding-top: 0px
+***************
+
+***************
+property
+padding-bottom: 0px
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.menuevent
+***************
+
+***************
+start_selector
+div.menubar
+***************
+
+***************
+property
+background: #cac2a8
+***************
+
+***************
+property
+border-top: 1px black solid
+***************
+
+***************
+property
+border-bottom: 1px black solid
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+padding-right: 10px
+***************
+
+***************
+property
+padding-top: 3px
+***************
+
+***************
+property
+padding-bottom: 2px
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+font-size: 13px
+***************
+
+***************
+end_selector
+div.menubar
+***************
+
+***************
+start_selector
+div.menubar a
+***************
+
+***************
+property
+text-decoration: none
+***************
+
+***************
+end_selector
+div.menubar a
+***************
+
+***************
+start_selector
+div.menudate
+***************
+
+***************
+property
+float: left
+***************
+
+***************
+property
+width: 130px
+***************
+
+***************
+property
+padding-top: 5px
+***************
+
+***************
+end_selector
+div.menudate
+***************
+
+***************
+start_selector
+div.menuaccroche
+***************
+
+***************
+property
+margin-left: 30px
+***************
+
+***************
+property
+float: left
+***************
+
+***************
+property
+text-decoration: underline
+***************
+
+***************
+property
+font-size: 14px
+***************
+
+***************
+end_selector
+div.menuaccroche
+***************
+
+***************
+start_selector
+div.menusearch
+***************
+
+***************
+property
+float: right
+***************
+
+***************
+property
+text-align: right
+***************
+
+***************
+property
+padding-top: 5px
+***************
+
+***************
+property
+width: 170px
+***************
+
+***************
+end_selector
+div.menusearch
+***************
+
+***************
+start_selector
+div.menusearch p
+***************
+
+***************
+property
+margin: 0px 0px 0px 0px
+***************
+
+***************
+end_selector
+div.menusearch p
+***************
+
+***************
+start_selector
+.searchinput
+***************
+
+***************
+property
+border: solid 1px black
+***************
+
+***************
+end_selector
+.searchinput
+***************
+
+***************
+start_selector
+a#menulinkselect
+***************
+
+***************
+property
+color: #ed7e00
+***************
+
+***************
+end_selector
+a#menulinkselect
+***************
+
+***************
+start_selector
+div.leftbox
+***************
+
+***************
+property
+width: 200px
+***************
+
+***************
+property
+float: left
+***************
+
+***************
+property
+padding-left: 5px
+***************
+
+***************
+property
+padding-right: 5px
+***************
+
+***************
+property
+padding-bottom: 5px
+***************
+
+***************
+property
+border-right: 1px black solid
+***************
+
+***************
+property
+border-bottom: 1px black solid
+***************
+
+***************
+property
+background: white
+***************
+
+***************
+property
+margin-bottom: 10px
+***************
+
+***************
+end_selector
+div.leftbox
+***************
+
+***************
+start_selector
+div.leftbox h1
+***************
+
+***************
+property
+text-transform: uppercase
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+color: #ed7e00
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.leftbox h1
+***************
+
+***************
+start_selector
+div.leftbox h2
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.leftbox h2
+***************
+
+***************
+start_selector
+div.leftbox ul
+***************
+
+***************
+property
+list-style-type: square
+***************
+
+***************
+property
+margin-bottom: 10px
+***************
+
+***************
+property
+margin-left: 0em
+***************
+
+***************
+property
+padding-left: 0em
+***************
+
+***************
+end_selector
+div.leftbox ul
+***************
+
+***************
+start_selector
+div.leftbox li
+***************
+
+***************
+property
+margin-left: 10px
+***************
+
+***************
+end_selector
+div.leftbox li
+***************
+
+***************
+start_selector
+div.rightbox
+***************
+
+***************
+property
+width: 150px
+***************
+
+***************
+property
+float: right
+***************
+
+***************
+property
+padding-top: 10px
+***************
+
+***************
+property
+padding-left: 5px
+***************
+
+***************
+property
+padding-right: 15px
+***************
+
+***************
+property
+padding-bottom: 5px
+***************
+
+***************
+property
+border-left: 1px black solid
+***************
+
+***************
+property
+border-bottom: 1px black solid
+***************
+
+***************
+property
+text-align: left
+***************
+
+***************
+end_selector
+div.rightbox
+***************
+
+***************
+start_selector
+div.newjournaldiv
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+property
+margin-left: 10%
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+width: 600px
+***************
+
+***************
+end_selector
+div.newjournaldiv
+***************
+
+***************
+start_selector
+div.newjournaldiv p
+***************
+
+***************
+property
+margin-bottom: 0px
+***************
+
+***************
+property
+margin-top: 20px
+***************
+
+***************
+end_selector
+div.newjournaldiv p
+***************
+
+***************
+start_selector
+div.journaldiv
+***************
+
+***************
+property
+margin-left: 0px
+***************
+
+***************
+property
+margin-right: 0px
+***************
+
+***************
+property
+margin-top: 20px
+***************
+
+***************
+property
+margin-bottom: 20px
+***************
+
+***************
+property
+border: 1px black solid
+***************
+
+***************
+property
+padding-top: 5px
+***************
+
+***************
+property
+padding-bottom: 5px
+***************
+
+***************
+property
+padding-right: 10px
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+background-color: #eef
+***************
+
+***************
+end_selector
+div.journaldiv
+***************
+
+***************
+start_selector
+div.journaldiv p
+***************
+
+***************
+property
+margin-top: 10px
+***************
+
+***************
+property
+margin-bottom: 0px
+***************
+
+***************
+end_selector
+div.journaldiv p
+***************
+
+***************
+start_selector
+div.journaldiv h1
+***************
+
+***************
+property
+color: #990033
+***************
+
+***************
+property
+font-size: 14px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.journaldiv h1
+***************
+
+***************
+start_selector
+div.journaldiv h2
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.journaldiv h2
+***************
+
+***************
+start_selector
+div.tipdiv
+***************
+
+***************
+property
+margin-left: 220px
+***************
+
+***************
+property
+margin-right: 50px
+***************
+
+***************
+property
+margin-top: 20px
+***************
+
+***************
+property
+padding-top: 5px
+***************
+
+***************
+property
+padding-right: 10px
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+property
+background-color: #eee
+***************
+
+***************
+property
+border: black solid 1px
+***************
+
+***************
+end_selector
+div.tipdiv
+***************
+
+***************
+start_selector
+div.tipdiv h1
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+font-size: 14px
+***************
+
+***************
+property
+color: black
+***************
+
+***************
+property
+margin-top: 0px
+***************
+
+***************
+property
+margin-bottom: 20px
+***************
+
+***************
+end_selector
+div.tipdiv h1
+***************
+
+***************
+start_selector
+div.tipdiv h2
+***************
+
+***************
+property
+text-transform: uppercase
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+color: #ed7e00
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.tipdiv h2
+***************
+
+***************
+start_selector
+div.newsdiv
+***************
+
+***************
+property
+margin-left: 220px
+***************
+
+***************
+property
+margin-right: 180px
+***************
+
+***************
+property
+margin-top: 10px
+***************
+
+***************
+property
+margin-bottom: 20px
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+end_selector
+div.newsdiv
+***************
+
+***************
+start_selector
+div.newsdiv h1
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+font-size: 14px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.newsdiv h1
+***************
+
+***************
+start_selector
+div.newsdiv h2
+***************
+
+***************
+property
+font-weight: normal
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.newsdiv h2
+***************
+
+***************
+start_selector
+div.newsdiv h3
+***************
+
+***************
+property
+font-weight: normal
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+margin-bottom: 20px
+***************
+
+***************
+end_selector
+div.newsdiv h3
+***************
+
+***************
+start_selector
+div.objdiv
+***************
+
+***************
+property
+margin-left: 220px
+***************
+
+***************
+property
+margin-right: 20px
+***************
+
+***************
+property
+margin-top: 10px
+***************
+
+***************
+property
+margin-bottom: 20px
+***************
+
+***************
+end_selector
+div.objdiv
+***************
+
+***************
+start_selector
+h1.newstitle
+***************
+
+***************
+property
+text-align: left
+***************
+
+***************
+property
+font-size: 14px
+***************
+
+***************
+property
+margin: 0px 0px 0px 0px
+***************
+
+***************
+property
+color: black
+***************
+
+***************
+end_selector
+h1.newstitle
+***************
+
+***************
+start_selector
+div.titlediv
+***************
+
+***************
+property
+border-top: solid #cac2a8 2px
+***************
+
+***************
+property
+margin-top: 20px
+***************
+
+***************
+property
+background-color: #eeeae6
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+font-size: 11px
+***************
+
+***************
+end_selector
+div.titlediv
+***************
+
+***************
+start_selector
+div.bodydiv
+***************
+
+***************
+property
+border: solid #9e9784 1px
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+padding-right: 10px
+***************
+
+***************
+property
+padding-top: 10px
+***************
+
+***************
+property
+padding-bottom: 5px
+***************
+
+***************
+property
+margin-top: 2px
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+end_selector
+div.bodydiv
+***************
+
+***************
+start_selector
+div.comments
+***************
+
+***************
+property
+padding: 10px
+***************
+
+***************
+property
+border-top: solid 2px #d37537
+***************
+
+***************
+property
+border-bottom: solid 2px #d37537
+***************
+
+***************
+property
+margin-top: 20px
+***************
+
+***************
+property
+margin-bottom: 10px
+***************
+
+***************
+property
+background-color: #cacaca
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+line-height: 1.3em
+***************
+
+***************
+end_selector
+div.comments
+***************
+
+***************
+start_selector
+p.commentsbody
+***************
+
+***************
+property
+border-left-style: solid
+***************
+
+***************
+property
+border-width: 1px
+***************
+
+***************
+property
+border-color: rgb(0, 0, 0)
+***************
+
+***************
+property
+padding-left: 10px
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+property
+margin-right: 20px
+***************
+
+***************
+end_selector
+p.commentsbody
+***************
+
+***************
+start_selector
+div.commentsreply
+***************
+
+***************
+property
+margin-left: 220px
+***************
+
+***************
+property
+text-align: center
+***************
+
+***************
+property
+margin-top: 50px
+***************
+
+***************
+end_selector
+div.commentsreply
+***************
+
+***************
+start_selector
+ul.commentsul
+***************
+
+***************
+property
+list-style-type: none
+***************
+
+***************
+property
+margin-bottom: 10px
+***************
+
+***************
+property
+margin-left: 1.25em
+***************
+
+***************
+property
+padding-left: 0em
+***************
+
+***************
+property
+border-left: 1px solid black
+***************
+
+***************
+end_selector
+ul.commentsul
+***************
+
+***************
+start_selector
+ul.commentsli
+***************
+
+***************
+property
+margin: 10px
+***************
+
+***************
+end_selector
+ul.commentsli
+***************
+
+***************
+start_selector
+div.comments li
+***************
+
+***************
+property
+margin-top: 20px
+***************
+
+***************
+property
+margin-left: 2px
+***************
+
+***************
+end_selector
+div.comments li
+***************
+
+***************
+start_selector
+div.comments h1
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+color: black
+***************
+
+***************
+property
+margin: 0px 20px 3px 0px
+***************
+
+***************
+property
+background-color: rgb(226, 226, 226)
+***************
+
+***************
+property
+padding-left: 1px
+***************
+
+***************
+property
+font-weight: none
+***************
+
+***************
+end_selector
+div.comments h1
+***************
+
+***************
+start_selector
+div.articlediv
+***************
+
+***************
+property
+padding-left: 20px
+***************
+
+***************
+property
+padding-right: 20px
+***************
+
+***************
+property
+padding-top: 10px
+***************
+
+***************
+property
+padding-bottom: 20px
+***************
+
+***************
+property
+margin-right: 10px
+***************
+
+***************
+property
+margin-left: 220px
+***************
+
+***************
+property
+border: solid 1px black
+***************
+
+***************
+property
+margin-top: 10px
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+property
+background-color: #E2E2E2
+***************
+
+***************
+end_selector
+div.articlediv
+***************
+
+***************
+start_selector
+img
+***************
+
+***************
+property
+border: 0px
+***************
+
+***************
+end_selector
+img
+***************
+
+***************
+start_selector
+div.sectionimg
+***************
+
+***************
+property
+float: left
+***************
+
+***************
+property
+margin-right: 10px
+***************
+
+***************
+property
+margin-top: 5px
+***************
+
+***************
+end_selector
+div.sectionimg
+***************
+
+***************
+start_selector
+p.hautpage
+***************
+
+***************
+property
+margin-top: 20px
+***************
+
+***************
+property
+margin-bottom: 20px
+***************
+
+***************
+property
+margin-left: 10px
+***************
+
+***************
+end_selector
+p.hautpage
+***************
+
+***************
+start_selector
+div.leftcol
+***************
+
+***************
+property
+width: 202px
+***************
+
+***************
+property
+width: 202px
+***************
+
+***************
+property
+float: left
+***************
+
+***************
+property
+padding: 0px
+***************
+
+***************
+end_selector
+div.leftcol
+***************
+
+***************
+start_selector
+div.logodiv
+***************
+
+***************
+property
+border-right: 1px black solid
+***************
+
+***************
+property
+border-bottom: 1px black solid
+***************
+
+***************
+property
+padding: 0px
+***************
+
+***************
+property
+line-height: 0px
+***************
+
+***************
+end_selector
+div.logodiv
+***************
+
+***************
+start_selector
+div.loginbox
+***************
+
+***************
+property
+margin-left: 4px
+***************
+
+***************
+property
+border: solid #a59f8b 1px
+***************
+
+***************
+property
+margin-top: 2px
+***************
+
+***************
+property
+padding: 5px
+***************
+
+***************
+property
+background-color: #fff2e8
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+end_selector
+div.loginbox
+***************
+
+***************
+start_selector
+div.loginbox p
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+property
+padding: 0px
+***************
+
+***************
+end_selector
+div.loginbox p
+***************
+
+***************
+start_selector
+div.loginbox ul
+***************
+
+***************
+property
+margin-left: 10px
+***************
+
+***************
+property
+margin-top: 0px
+***************
+
+***************
+property
+margin-bottom: 0px
+***************
+
+***************
+property
+padding: 0px
+***************
+
+***************
+property
+list-style-type: none
+***************
+
+***************
+end_selector
+div.loginbox ul
+***************
+
+***************
+start_selector
+div.loginbox h1
+***************
+
+***************
+property
+text-transform: uppercase
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+color: #ed7e00
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.loginbox h1
+***************
+
+***************
+start_selector
+div.loginbox h2
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.loginbox h2
+***************
+
+***************
+start_selector
+div.loginbox h3
+***************
+
+***************
+property
+margin-top: 0px
+***************
+
+***************
+property
+margin-bottom: 5px
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+end_selector
+div.loginbox h3
+***************
+
+***************
+start_selector
+div.polldivtitle
+***************
+
+***************
+property
+margin-bottom: 1px
+***************
+
+***************
+property
+background-color: #cac2a8
+***************
+
+***************
+property
+margin-left: 4px
+***************
+
+***************
+property
+margin-top: 15px
+***************
+
+***************
+property
+padding-left: 5px
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+property
+border-top: solid #a59f8b 1px
+***************
+
+***************
+property
+border-bottom: solid #a59f8b 1px
+***************
+
+***************
+property
+text-transform: uppercase
+***************
+
+***************
+end_selector
+div.polldivtitle
+***************
+
+***************
+start_selector
+div.polldiv
+***************
+
+***************
+property
+margin-left: 4px
+***************
+
+***************
+property
+border: 1px #a59f8b solid
+***************
+
+***************
+property
+margin-top: 0px
+***************
+
+***************
+property
+padding: 5px
+***************
+
+***************
+property
+background: #fff2e8
+***************
+
+***************
+end_selector
+div.polldiv
+***************
+
+***************
+start_selector
+div.polldiv p
+***************
+
+***************
+property
+margin: 5px
+***************
+
+***************
+property
+padding: 0px
+***************
+
+***************
+end_selector
+div.polldiv p
+***************
+
+***************
+start_selector
+div.polldiv ul
+***************
+
+***************
+property
+margin-left: 5px
+***************
+
+***************
+property
+margin-top: 0px
+***************
+
+***************
+property
+margin-bottom: 10px
+***************
+
+***************
+property
+padding: 0px
+***************
+
+***************
+property
+list-style-type: none
+***************
+
+***************
+end_selector
+div.polldiv ul
+***************
+
+***************
+start_selector
+div.otherboxtitle
+***************
+
+***************
+property
+margin-bottom: 2px
+***************
+
+***************
+property
+background-color: #e3dabc
+***************
+
+***************
+property
+margin-left: 4px
+***************
+
+***************
+property
+margin-top: 15px
+***************
+
+***************
+property
+padding-left: 5px
+***************
+
+***************
+property
+padding-top: 2px
+***************
+
+***************
+property
+font-size: 11px
+***************
+
+***************
+property
+border-top: solid #777364 1px
+***************
+
+***************
+property
+border-bottom: solid #777364 1px
+***************
+
+***************
+property
+text-transform: uppercase
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+end_selector
+div.otherboxtitle
+***************
+
+***************
+start_selector
+div.otherbox
+***************
+
+***************
+property
+margin-left: 4px
+***************
+
+***************
+property
+border: 1px #a59f8b solid
+***************
+
+***************
+property
+margin-top: 0px
+***************
+
+***************
+property
+padding: 5px
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+property
+background: #fff2e8
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+end_selector
+div.otherbox
+***************
+
+***************
+start_selector
+div.otherbox h1
+***************
+
+***************
+property
+text-transform: uppercase
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+color: #ed7e00
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.otherbox h1
+***************
+
+***************
+start_selector
+div.otherbox h2
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+font-size: 11px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.otherbox h2
+***************
+
+***************
+start_selector
+div.otherbox p
+***************
+
+***************
+property
+margin-top: 5px
+***************
+
+***************
+property
+margin-bottom: 10px
+***************
+
+***************
+end_selector
+div.otherbox p
+***************
+
+***************
+start_selector
+div.rightlogo
+***************
+
+***************
+property
+width: 90px
+***************
+
+***************
+property
+float: right
+***************
+
+***************
+property
+margin-right: 0px
+***************
+
+***************
+property
+padding-top: 0px
+***************
+
+***************
+property
+padding-left: 0px
+***************
+
+***************
+property
+padding-bottom: 0px
+***************
+
+***************
+end_selector
+div.rightlogo
+***************
+
+***************
+start_selector
+div.centraldiv
+***************
+
+***************
+property
+margin-left: 220px
+***************
+
+***************
+property
+margin-right: 10px
+***************
+
+***************
+property
+margin-bottom: 20px
+***************
+
+***************
+property
+margin-top: 10px
+***************
+
+***************
+end_selector
+div.centraldiv
+***************
+
+***************
+start_selector
+div.centraldiv h1
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+font-size: 14px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.centraldiv h1
+***************
+
+***************
+start_selector
+div.centraldiv h2
+***************
+
+***************
+property
+font-weight: normal
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.centraldiv h2
+***************
+
+***************
+start_selector
+div.centraldiv h3
+***************
+
+***************
+property
+font-weight: normal
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+margin-bottom: 20px
+***************
+
+***************
+end_selector
+div.centraldiv h3
+***************
+
+***************
+start_selector
+div.centralinfo
+***************
+
+***************
+property
+position: relative
+***************
+
+***************
+property
+height: 160px
+***************
+
+***************
+end_selector
+div.centralinfo
+***************
+
+***************
+start_selector
+div.lefttopbox
+***************
+
+***************
+property
+position: relative
+***************
+
+***************
+property
+padding-left: 5px
+***************
+
+***************
+property
+padding-right: 5px
+***************
+
+***************
+property
+padding-top: 5px
+***************
+
+***************
+property
+border: 1px #a59f8b solid
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+property
+background: #fff2e8
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+width: 47%
+***************
+
+***************
+property
+float: left
+***************
+
+***************
+end_selector
+div.lefttopbox
+***************
+
+***************
+start_selector
+div.lefttopbox p
+***************
+
+***************
+property
+margin-top: 5px
+***************
+
+***************
+property
+margin-bottom: 10px
+***************
+
+***************
+end_selector
+div.lefttopbox p
+***************
+
+***************
+start_selector
+div.lefttopbox h1
+***************
+
+***************
+property
+font-size: 13px
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+property
+text-align: right
+***************
+
+***************
+end_selector
+div.lefttopbox h1
+***************
+
+***************
+start_selector
+div.lefttopbox h2
+***************
+
+***************
+property
+text-transform: uppercase
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+color: #ed7e00
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.lefttopbox h2
+***************
+
+***************
+start_selector
+div.lefttopbox h3
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.lefttopbox h3
+***************
+
+***************
+start_selector
+div.righttopbox
+***************
+
+***************
+property
+position: relative
+***************
+
+***************
+property
+border: 1px #a59f8b solid
+***************
+
+***************
+property
+background: white
+***************
+
+***************
+property
+padding: 5px
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+width: 47%
+***************
+
+***************
+property
+float: right
+***************
+
+***************
+end_selector
+div.righttopbox
+***************
+
+***************
+start_selector
+div.righttopbox h1
+***************
+
+***************
+property
+text-transform: uppercase
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+color: #ed7e00
+***************
+
+***************
+property
+font-size: 10px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.righttopbox h1
+***************
+
+***************
+start_selector
+div.righttopbox h2
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+margin: 0px
+***************
+
+***************
+end_selector
+div.righttopbox h2
+***************
+
+***************
+start_selector
+div.boardindex
+***************
+
+***************
+property
+text-align: justify
+***************
+
+***************
+property
+font-size: 11px
+***************
+
+***************
+property
+padding: 10px
+***************
+
+***************
+property
+margin-left: 20px
+***************
+
+***************
+property
+margin-right: 20px
+***************
+
+***************
+end_selector
+div.boardindex
+***************
+
+***************
+start_selector
+a.boardindex:link, a.boardindex:visited, a.boardindex:active
+***************
+
+***************
+property
+text-decoration: none
+***************
+
+***************
+property
+color: red
+***************
+
+***************
+end_selector
+a.boardindex:link, a.boardindex:visited, a.boardindex:active
+***************
+
+***************
+start_selector
+div.boardleftmsg
+***************
+
+***************
+property
+float: left
+***************
+
+***************
+property
+margin-top: 3px
+***************
+
+***************
+end_selector
+div.boardleftmsg
+***************
+
+***************
+start_selector
+div.boardrightmsg
+***************
+
+***************
+property
+margin-left: 130px
+***************
+
+***************
+property
+margin-top: 3px
+***************
+
+***************
+property
+padding-left: 5px
+***************
+
+***************
+end_selector
+div.boardrightmsg
+***************
+
+***************
+start_selector
+div.journalbody
+***************
+
+***************
+property
+margin-left: 40px
+***************
+
+***************
+property
+margin-top: 40px
+***************
+
+***************
+end_selector
+div.journalbody
+***************
+
+***************
+start_selector
+div.journalbody h1
+***************
+
+***************
+property
+font-size: 15px
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+end_selector
+div.journalbody h1
+***************
+
+***************
+start_selector
+div.journalbody p
+***************
+
+***************
+property
+margin-bottom: 20px
+***************
+
+***************
+end_selector
+div.journalbody p
+***************
+
+***************
+start_selector
+.formulaire
+***************
+
+***************
+property
+border: solid 1px black
+***************
+
+***************
+property
+font-size: 12px
+***************
+
+***************
+property
+background-color: #eef
+***************
+
+***************
+property
+color: #000000
+***************
+
+***************
+end_selector
+.formulaire
+***************
+
+***************
+start_selector
+.newcomments
+***************
+
+***************
+property
+color: red
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+end_selector
+.newcomments
+***************
+
+***************
+start_selector
+div.commentsreplythanks
+***************
+
+***************
+property
+margin-left: 100px
+***************
+
+***************
+property
+margin-top: 50px
+***************
+
+***************
+property
+margin-right: 100px
+***************
+
+***************
+property
+background-color: #eee
+***************
+
+***************
+property
+border: black solid 1px
+***************
+
+***************
+property
+padding: 10px
+***************
+
+***************
+end_selector
+div.commentsreplythanks
+***************
+
+***************
+start_selector
+div.archivediv
+***************
+
+***************
+property
+margin-right: 20px
+***************
+
+***************
+end_selector
+div.archivediv
+***************
+
+***************
+start_selector
+.archivedate
+***************
+
+***************
+property
+color: #f30
+***************
+
+***************
+end_selector
+.archivedate
+***************
+
+***************
+start_selector
+.archivelink
+***************
+
+***************
+property
+font-size: 14px
+***************
+
+***************
+property
+font-weight: bold
+***************
+
+***************
+property
+text-decoration: underline
+***************
+
+***************
+end_selector
+.archivelink
+***************
+
+***************
+end_document
+***************
+
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test2.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test2.css.out
new file mode 100644
index 0000000..f989353
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test2.css.out
@@ -0,0 +1,63 @@
+***************
+start_document
+***************
+
+***************
+start_selector
+S1
+***************
+
+***************
+property
+prop1: value1
+***************
+
+***************
+end_selector
+S1
+***************
+
+***************
+start_selector
+s1, s2
+***************
+
+***************
+property
+color: black
+***************
+
+***************
+property
+background: white
+***************
+
+***************
+end_selector
+s1, s2
+***************
+
+***************
+start_selector
+s1 s2, S3>s4
+***************
+
+***************
+property
+prop1: value1
+***************
+
+***************
+property
+prop2: value2
+***************
+
+***************
+end_selector
+s1 s2, S3>s4
+***************
+
+***************
+end_document
+***************
+
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test3.1.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test3.1.css.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test3.1.css.out
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test3.2.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test3.2.css.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test3.2.css.out
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test3.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test3.css.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test3.css.out
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test4.1.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test4.1.css.out
new file mode 100644
index 0000000..95aa7b7
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test4.1.css.out
@@ -0,0 +1,766 @@
+* {
+ font-family : Verdana, Arial, Helvetica, sans-serif, monospace !important
+}
+
+tutu:class1:class2 {
+ test : ok
+}
+
+body {
+ background : #606060;
+ color : #000000
+}
+
+a:link {
+ color : #0000FF;
+ background : transparent;
+ text-decoration : none
+}
+
+a:visited {
+ color : #990099;
+ background : transparent;
+ text-decoration : none
+}
+
+a:active {
+ color : #000000;
+ background : #ADD8E6;
+ text-decoration : none
+}
+
+h1.rubrique_info {
+ color : #990033;
+ margin : 0px 0px 0px 0px;
+ padding : 0.4em;
+ border : 0px;
+ font-size : 12px
+}
+
+h1.connexe {
+ font-size : 12px;
+ padding : 0.9em;
+ margin : 0px 0px 0px 0px;
+ color : #990033
+}
+
+a.rubrique_infolink {
+ text-decoration : none
+}
+
+ul.rubrique_infoul {
+ display : inline;
+ list-style-type : square
+}
+
+ul.rubrique_infoul * {
+ width : 100%
+}
+
+li.rubrique_infoul {
+ margin-left : 15px
+}
+
+h1 {
+ color : #990033
+}
+
+div.main {
+ background : white;
+ color : #000000;
+ margin-left : 5px;
+ margin-right : 5px;
+ border : 1px black solid;
+ text-align : left;
+ font-size : 12px
+}
+
+div.lsfnbanner {
+ margin-left : 150px;
+ margin-right : 170px;
+ border-top : none;
+ padding-left : 10px;
+ padding-right : 10px;
+ border-bottom : 1px black solid;
+ border-right : 1px black solid;
+ border-left : 1px black solid;
+ text-align : left;
+ font-size : 11px;
+ padding-top : 2px;
+ background-color : #eeeae6
+}
+
+div.footer {
+ padding-top : 5px;
+ padding-bottom : 3px;
+ border-top : 1px black solid;
+ border-left : 1px black solid;
+ border-right : 1px black solid;
+ text-align : left;
+ font-size : 9px;
+ background : #dcdff4;
+ width : 600px;
+ margin-top : 40px;
+ margin-left : 20px
+}
+
+div.footer p {
+ margin-left : 10px;
+ margin-top : 2px;
+ margin-bottom : 2px
+}
+
+a.lsfnlink:link, a.lsfnlink:visited, a.lsfnlink:active {
+ text-decoration : none;
+ color : #333333;
+ font-size : 10px
+}
+
+a.lsfnlink:hover {
+ text-decoration : underline;
+ color : black
+}
+
+div.menubartop {
+ margin-bottom : 10px;
+ padding-left : 10px;
+ padding-right : 10px;
+ padding-top : 0px;
+ font-size : 13px
+}
+
+div.smallmenubar {
+ background : white;
+ padding-left : 10px;
+ padding-right : 10px;
+ padding-top : 0px;
+ padding-bottom : 0px;
+ font-weight : bold;
+ font-size : 10px;
+ text-align : right
+}
+
+div.menuevent {
+ float : left;
+ width : 350px;
+ font-size : 11px;
+ text-align : left;
+ padding-top : 0px;
+ padding-bottom : 0px;
+ padding-left : 10px;
+ font-weight : bold;
+ margin : 0px
+}
+
+div.menubar {
+ background : #cac2a8;
+ border-top : 1px black solid;
+ border-bottom : 1px black solid;
+ padding-left : 10px;
+ padding-right : 10px;
+ padding-top : 3px;
+ padding-bottom : 2px;
+ font-weight : bold;
+ font-size : 13px
+}
+
+div.menubar a {
+ text-decoration : none
+}
+
+div.menudate {
+ float : left;
+ width : 130px;
+ padding-top : 5px
+}
+
+div.menuaccroche {
+ margin-left : 30px;
+ float : left;
+ text-decoration : underline;
+ font-size : 14px
+}
+
+div.menusearch {
+ float : right;
+ text-align : right;
+ padding-top : 5px;
+ width : 170px
+}
+
+div.menusearch p {
+ margin : 0px 0px 0px 0px
+}
+
+.searchinput {
+ border : solid 1px black
+}
+
+a#menulinkselect {
+ color : #ed7e00
+}
+
+div.leftbox {
+ width : 200px;
+ float : left;
+ padding-left : 5px;
+ padding-right : 5px;
+ padding-bottom : 5px;
+ border-right : 1px black solid;
+ border-bottom : 1px black solid;
+ background : white;
+ margin-bottom : 10px
+}
+
+div.leftbox h1 {
+ text-transform : uppercase;
+ font-weight : bold;
+ color : #ed7e00;
+ font-size : 10px;
+ margin : 0px
+}
+
+div.leftbox h2 {
+ font-weight : bold;
+ font-size : 12px;
+ margin : 0px
+}
+
+div.leftbox ul {
+ list-style-type : square;
+ margin-bottom : 10px;
+ margin-left : 0.3em;
+ padding-left : 0.2em
+}
+
+div.leftbox li {
+ margin-left : 10px
+}
+
+div.rightbox {
+ width : 150px;
+ float : right;
+ padding-top : 10px;
+ padding-left : 5px;
+ padding-right : 15px;
+ padding-bottom : 5px;
+ border-left : 1px black solid;
+ border-bottom : 1px black solid;
+ text-align : left
+}
+
+div.newjournaldiv {
+ text-align : justify;
+ margin-left : 10%;
+ font-size : 12px;
+ width : 600px
+}
+
+div.newjournaldiv p {
+ margin-bottom : 0px;
+ margin-top : 20px
+}
+
+div.journaldiv {
+ margin-left : 0px;
+ margin-right : 0px;
+ margin-top : 20px;
+ margin-bottom : 20px;
+ border : 1px black solid;
+ padding-top : 5px;
+ padding-bottom : 5px;
+ padding-right : 10px;
+ padding-left : 10px;
+ background-color : #eef
+}
+
+div.journaldiv p {
+ margin-top : 10px;
+ margin-bottom : 0px
+}
+
+div.journaldiv h1 {
+ color : #990033;
+ font-size : 14px;
+ margin : 0px
+}
+
+div.journaldiv h2 {
+ font-size : 10px;
+ margin : 0px
+}
+
+div.tipdiv {
+ margin-left : 220px;
+ margin-right : 50px;
+ margin-top : 20px;
+ padding-top : 5px;
+ padding-right : 10px;
+ padding-left : 10px;
+ text-align : justify;
+ background-color : #eee;
+ border : black solid 1px
+}
+
+div.tipdiv h1 {
+ font-weight : bold;
+ font-size : 14px;
+ color : black;
+ margin-top : 0px;
+ margin-bottom : 20px
+}
+
+div.tipdiv h2 {
+ text-transform : uppercase;
+ font-weight : bold;
+ color : #ed7e00;
+ font-size : 12px;
+ margin : 0px
+}
+
+div.newsdiv {
+ margin-left : 220px;
+ margin-right : 180px;
+ margin-top : 10px;
+ margin-bottom : 20px;
+ text-align : justify
+}
+
+div.newsdiv h1 {
+ font-weight : bold;
+ font-size : 14px;
+ margin : 0px
+}
+
+div.newsdiv h2 {
+ font-weight : normal;
+ font-size : 12px;
+ margin : 0px
+}
+
+div.newsdiv h3 {
+ font-weight : normal;
+ font-size : 12px;
+ margin-bottom : 20px
+}
+
+div.objdiv {
+ margin-left : 220px;
+ margin-right : 20px;
+ margin-top : 10px;
+ margin-bottom : 20px
+}
+
+h1.newstitle {
+ text-align : left;
+ font-size : 14px;
+ margin : 0px 0px 0px 0px;
+ color : black
+}
+
+div.titlediv {
+ border-top : solid #cac2a8 2px;
+ margin-top : 20px;
+ background-color : #eeeae6;
+ padding-left : 10px;
+ font-size : 11px
+}
+
+div.bodydiv {
+ border : solid #9e9784 1px;
+ padding-left : 10px;
+ padding-right : 10px;
+ padding-top : 10px;
+ padding-bottom : 5px;
+ margin-top : 2px;
+ text-align : justify
+}
+
+div.comments {
+ padding : 10px;
+ border-top : solid 2px #d37537;
+ border-bottom : solid 2px #d37537;
+ margin-top : 20px;
+ margin-bottom : 10px;
+ background-color : #cacaca;
+ font-size : 12px;
+ line-height : 1.3em
+}
+
+p.commentsbody {
+ border-left-style : solid;
+ border-width : 1px;
+ border-color : rgb(0, 0, 0);
+ padding-left : 10px;
+ text-align : justify;
+ margin-right : 20px
+}
+
+div.commentsreply {
+ margin-left : 220px;
+ text-align : center;
+ margin-top : 50px
+}
+
+ul.commentsul {
+ list-style-type : none;
+ margin-bottom : 10px;
+ margin-left : 1.25em;
+ padding-left : 0em;
+ border-left : 1px solid black
+}
+
+ul.commentsli {
+ margin : 10px
+}
+
+div.comments li {
+ margin-top : 20px;
+ margin-left : 2px
+}
+
+div.comments h1 {
+ font-size : 12px;
+ color : black;
+ margin : 0px 20px 3px 0px;
+ background-color : rgb(226, 226, 226);
+ padding-left : 1px;
+ font-weight : none
+}
+
+div.articlediv {
+ padding-left : 20px;
+ padding-right : 20px;
+ padding-top : 10px;
+ padding-bottom : 20px;
+ margin-right : 10px;
+ margin-left : 220px;
+ border : solid 1px black;
+ margin-top : 10px;
+ text-align : justify;
+ background-color : #E2E2E2
+}
+
+img {
+ border : 0px
+}
+
+div.sectionimg {
+ float : left;
+ margin-right : 10px;
+ margin-top : 5px
+}
+
+p.hautpage {
+ margin-top : 20px;
+ margin-bottom : 20px;
+ margin-left : 10px
+}
+
+div.leftcol {
+ width : 202px;
+ width : 202px;
+ float : left;
+ padding : 0px
+}
+
+div.logodiv {
+ border-right : 1px black solid;
+ border-bottom : 1px black solid;
+ padding : 0px;
+ line-height : 0px
+}
+
+div.loginbox {
+ margin-left : 4px;
+ border : solid #a59f8b 1px;
+ margin-top : 2px;
+ padding : 5px;
+ background-color : #fff2e8;
+ font-size : 10px
+}
+
+div.loginbox p {
+ margin : 0px;
+ padding : 0px
+}
+
+div.loginbox ul {
+ margin-left : 10px;
+ margin-top : 0px;
+ margin-bottom : 0px;
+ padding : 0px;
+ list-style-type : none
+}
+
+div.loginbox h1 {
+ text-transform : uppercase;
+ font-weight : bold;
+ color : #ed7e00;
+ font-size : 10px;
+ margin : 0px
+}
+
+div.loginbox h2 {
+ font-weight : bold;
+ font-size : 12px;
+ margin : 0px
+}
+
+div.loginbox h3 {
+ margin-top : 0px;
+ margin-bottom : 5px;
+ font-size : 12px
+}
+
+div.polldivtitle {
+ margin-bottom : 1px;
+ background-color : #cac2a8;
+ margin-left : 4px;
+ margin-top : 15px;
+ padding-left : 5px;
+ font-size : 10px;
+ border-top : solid #a59f8b 1px;
+ border-bottom : solid #a59f8b 1px;
+ text-transform : uppercase
+}
+
+div.polldiv {
+ margin-left : 4px;
+ border : 1px #a59f8b solid;
+ margin-top : 0px;
+ padding : 5px;
+ background : #fff2e8
+}
+
+div.polldiv p {
+ margin : 5px;
+ padding : 0px
+}
+
+div.polldiv ul {
+ margin-left : 5px;
+ margin-top : 0px;
+ margin-bottom : 10px;
+ padding : 0px;
+ list-style-type : none
+}
+
+div.otherboxtitle {
+ margin-bottom : 2px;
+ background-color : #e3dabc;
+ margin-left : 4px;
+ margin-top : 15px;
+ padding-left : 5px;
+ padding-top : 2px;
+ font-size : 11px;
+ border-top : solid #777364 1px;
+ border-bottom : solid #777364 1px;
+ text-transform : uppercase;
+ font-weight : bold
+}
+
+div.otherbox {
+ margin-left : 4px;
+ border : 1px #a59f8b solid;
+ margin-top : 0px;
+ padding : 5px;
+ text-align : justify;
+ background : #fff2e8;
+ font-size : 10px
+}
+
+div.otherbox h1 {
+ text-transform : uppercase;
+ font-weight : bold;
+ color : #ed7e00;
+ font-size : 10px;
+ margin : 0px
+}
+
+div.otherbox h2 {
+ font-weight : bold;
+ font-size : 11px;
+ margin : 0px
+}
+
+div.otherbox p {
+ margin-top : 5px;
+ margin-bottom : 10px
+}
+
+div.rightlogo {
+ width : 90px;
+ float : right;
+ margin-right : 0px;
+ padding-top : 0px;
+ padding-left : 0px;
+ padding-bottom : 0px
+}
+
+div.centraldiv {
+ margin-left : 220px;
+ margin-right : 10px;
+ margin-bottom : 20px;
+ margin-top : 10px
+}
+
+div.centraldiv h1 {
+ font-weight : bold;
+ font-size : 14px;
+ margin : 0px
+}
+
+div.centraldiv h2 {
+ font-weight : normal;
+ font-size : 12px;
+ margin : 0px
+}
+
+div.centraldiv h3 {
+ font-weight : normal;
+ font-size : 12px;
+ margin-bottom : 20px
+}
+
+div.centralinfo {
+ position : relative;
+ height : 160px
+}
+
+div.lefttopbox {
+ position : relative;
+ padding-left : 5px;
+ padding-right : 5px;
+ padding-top : 5px;
+ border : 1px #a59f8b solid;
+ text-align : justify;
+ background : #fff2e8;
+ font-size : 12px;
+ width : 47%;
+ float : left
+}
+
+div.lefttopbox p {
+ margin-top : 5px;
+ margin-bottom : 10px
+}
+
+div.lefttopbox h1 {
+ font-size : 13px;
+ font-weight : bold;
+ margin : 0px;
+ text-align : right
+}
+
+div.lefttopbox h2 {
+ text-transform : uppercase;
+ font-weight : bold;
+ color : #ed7e00;
+ font-size : 10px;
+ margin : 0px
+}
+
+div.lefttopbox h3 {
+ font-weight : bold;
+ font-size : 12px;
+ margin : 0px
+}
+
+div.righttopbox {
+ position : relative;
+ border : 1px #a59f8b solid;
+ background : white;
+ padding : 5px;
+ text-align : justify;
+ font-size : 12px;
+ width : 47%;
+ float : right
+}
+
+div.righttopbox h1 {
+ text-transform : uppercase;
+ font-weight : bold;
+ color : #ed7e00;
+ font-size : 10px;
+ margin : 0px
+}
+
+div.righttopbox h2 {
+ font-weight : bold;
+ font-size : 12px;
+ margin : 0px
+}
+
+div.boardindex {
+ text-align : justify;
+ font-size : 11px;
+ padding : 10px;
+ margin-left : 20px;
+ margin-right : 20px
+}
+
+a.boardindex:link, a.boardindex:visited, a.boardindex:active {
+ text-decoration : none;
+ color : red
+}
+
+div.boardleftmsg {
+ float : left;
+ margin-top : 3px
+}
+
+div.boardrightmsg {
+ margin-left : 130px;
+ margin-top : 3px;
+ padding-left : 5px
+}
+
+div.journalbody {
+ margin-left : 40px;
+ margin-top : 40px
+}
+
+div.journalbody h1 {
+ font-size : 15px;
+ font-weight : bold
+}
+
+div.journalbody p {
+ margin-bottom : 20px
+}
+
+.formulaire {
+ border : solid 1px black;
+ font-size : 12px;
+ background-color : #eef;
+ color : #000000
+}
+
+.newcomments {
+ color : red;
+ font-weight : bold
+}
+
+div.commentsreplythanks {
+ margin-left : 100px;
+ margin-top : 50px;
+ margin-right : 100px;
+ background-color : #eee;
+ border : black solid 1px;
+ padding : 10px
+}
+
+div.archivediv {
+ margin-right : 20px
+}
+
+.archivedate {
+ color : #f30
+}
+
+.archivelink {
+ font-size : 14px;
+ font-weight : bold;
+ text-decoration : underline
+} \ No newline at end of file
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test4.2.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test4.2.css.out
new file mode 100644
index 0000000..b67ae23
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test4.2.css.out
@@ -0,0 +1,24 @@
+@charset "ISO-8859-1" ;
+
+@import url("http://www.yahoo.com/css")print, screen ;
+
+@font-face {
+ font-family : 'Robson Celtic';
+ src : url(http://site/fonts/rob-celt)
+}
+
+@page left :one-two {
+ margin : 10pt;
+ border : none
+}
+
+
+@media print, screen, projection {
+ H1 {
+ font-family : 'Robson Celtic', serif
+ }
+ P {
+ background : black;
+ foreground : white
+ }
+} \ No newline at end of file
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test5.1.css.out b/src/3rdparty/libcroco/tests/test-output-refs/test5.1.css.out
new file mode 100644
index 0000000..2f0bc54
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test5.1.css.out
@@ -0,0 +1,105 @@
+'''''''''''''''''''''''''
+xml start element: document
+
+ :first-child {
+ first-child-prop : first-child-value
+ }
+
+xml end element: document
+'''''''''''''''''''''''''
+'''''''''''''''''''''''''
+xml start element: E0
+
+ :first-child {
+ first-child-prop : first-child-value
+ }
+ E0 {
+ prop0 : val0
+ }
+
+xml end element: E0
+'''''''''''''''''''''''''
+'''''''''''''''''''''''''
+xml start element: E1
+
+ E0+E1 {
+ pro1 : val1
+ }
+
+xml end element: E1
+'''''''''''''''''''''''''
+'''''''''''''''''''''''''
+xml start element: E1-1
+
+ :first-child {
+ first-child-prop : first-child-value
+ }
+ E1 E1-1 {
+ prop2 : val2
+ }
+ E1>E1-1 {
+ prop3 : val3
+ }
+ document E1-1 {
+ prop4 : val4
+ }
+
+xml end element: E1-1
+'''''''''''''''''''''''''
+'''''''''''''''''''''''''
+xml start element: E2
+
+ [attr2="val2"] {
+ prop5 : val5
+ }
+ E2[attr2="val2"] {
+ prop8 : val8
+ }
+
+xml end element: E2
+'''''''''''''''''''''''''
+'''''''''''''''''''''''''
+xml start element: E3
+
+ [attr3~="val3_2"] {
+ prop6 : val6
+ }
+
+xml end element: E3
+'''''''''''''''''''''''''
+'''''''''''''''''''''''''
+xml start element: E4
+
+ [attr4|="val4"] {
+ prop7 : val7
+ }
+
+xml end element: E4
+'''''''''''''''''''''''''
+'''''''''''''''''''''''''
+xml start element: E5
+
+ .class5 {
+ prop8 : val8
+ }
+
+xml end element: E5
+'''''''''''''''''''''''''
+'''''''''''''''''''''''''
+xml start element: E6
+
+ #id6 {
+ prop9 : val9
+ }
+
+xml end element: E6
+'''''''''''''''''''''''''
+'''''''''''''''''''''''''
+xml start element: E7
+
+ :lang(fr) {
+ lang-prop : lang-value
+ }
+
+xml end element: E7
+'''''''''''''''''''''''''
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test6.out b/src/3rdparty/libcroco/tests/test-output-refs/test6.out
new file mode 100644
index 0000000..cdc81db
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test6.out
@@ -0,0 +1,8 @@
+.str0 {
+ stroke : #007844;
+ stroke-width : 44
+}
+
+.fil0 {
+ fill : url(#id0)
+} \ No newline at end of file
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test7.out b/src/3rdparty/libcroco/tests/test-output-refs/test7.out
new file mode 100644
index 0000000..21d10d7
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test7.out
@@ -0,0 +1,43 @@
+.exp1n1 {
+ stroke-width : 4000000
+}
+
+.exp1n2 {
+ stroke-width : 4000000
+}
+
+.exp1n3 {
+ stroke-width : 4000000
+}
+
+.exp2n1 {
+ stroke-width : 0.000004
+}
+
+.exp2n2 {
+ stroke-width : 0.000004
+}
+
+.exp3n1 {
+ stroke-width : 4000000em
+}
+
+.exp3n2 {
+ stroke-width : 4000000ex
+}
+
+.exp3n3 {
+ stroke-width : 4000000in
+}
+
+.exp4n1 {
+ stroke-width : 31400
+}
+
+.exp4n2 {
+ stroke-width : 0.000314
+}
+
+.e4n2 {
+ stroke-width : 0.000024
+}
diff --git a/src/3rdparty/libcroco/tests/test-output-refs/test8.out b/src/3rdparty/libcroco/tests/test-output-refs/test8.out
new file mode 100644
index 0000000..9e25188
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-output-refs/test8.out
@@ -0,0 +1,15 @@
+****************
+Parsing 'foo'
+foo
+****************
+Parsing 'foo,bar'
+foo, bar
+****************
+Parsing 'foo , bar '
+foo, bar
+****************
+Parsing 'foo > bar'
+foo>bar
+****************
+Parsing '.foo .bar'
+.foo.bar
diff --git a/src/3rdparty/libcroco/tests/test-parsing-location.sh b/src/3rdparty/libcroco/tests/test-parsing-location.sh
new file mode 100755
index 0000000..4d7af34
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-parsing-location.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+test -z "$CSSLINT" && . ./global-test-vars.sh
+
+$CSSLINT --dump-location $TEST_INPUTS_DIR/parsing-location.css
diff --git a/src/3rdparty/libcroco/tests/test-prop-ident.sh b/src/3rdparty/libcroco/tests/test-prop-ident.sh
new file mode 100755
index 0000000..31e6127
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-prop-ident.sh
@@ -0,0 +1,5 @@
+#! /bin/sh
+
+test -z "$CSSLINT" && . ./global-test-vars.sh
+
+$CSSLINT "$TEST_INPUTS_DIR"/prop-vendor-ident.css
diff --git a/src/3rdparty/libcroco/tests/test-sel-child-class.sh b/src/3rdparty/libcroco/tests/test-sel-child-class.sh
new file mode 100755
index 0000000..ebfbb96
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-sel-child-class.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+test -z "$CSSLINT" && . ./global-test-vars.sh
+
+$CSSLINT -e --user-sheet $TEST_INPUTS_DIR/sel-child-class.css --xml $TEST_INPUTS_DIR/sel-child-class.xml --xpath /test/body/div/div/p
diff --git a/src/3rdparty/libcroco/tests/test-several-media.sh b/src/3rdparty/libcroco/tests/test-several-media.sh
new file mode 100755
index 0000000..c0a0c9d
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-several-media.sh
@@ -0,0 +1,5 @@
+#! /bin/sh
+
+test -z "$CSSLINT" && . ./global-test-vars.sh
+
+$CSSLINT "$TEST_INPUTS_DIR"/several-media.css
diff --git a/src/3rdparty/libcroco/tests/test-unknown-at-rule.sh b/src/3rdparty/libcroco/tests/test-unknown-at-rule.sh
new file mode 100755
index 0000000..08ceff6
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-unknown-at-rule.sh
@@ -0,0 +1,5 @@
+#! /bin/sh
+
+test -z "$CSSLINT" && . ./global-test-vars.sh
+
+$CSSLINT "$TEST_INPUTS_DIR"/unknown-at-rule.css
diff --git a/src/3rdparty/libcroco/tests/test-unknown-at-rule2.sh b/src/3rdparty/libcroco/tests/test-unknown-at-rule2.sh
new file mode 100755
index 0000000..fe58731
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test-unknown-at-rule2.sh
@@ -0,0 +1,5 @@
+#! /bin/sh
+
+test -z "$CSSLINT" && . ./global-test-vars.sh
+
+$CSSLINT "$TEST_INPUTS_DIR"/unknown-at-rule2.css
diff --git a/src/3rdparty/libcroco/tests/test0-main.c b/src/3rdparty/libcroco/tests/test0-main.c
new file mode 100644
index 0000000..993c983
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test0-main.c
@@ -0,0 +1,203 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ *$Id$
+ */
+
+#include <stdio.h>
+#include "cr-input.h"
+#include "string.h"
+
+/**
+ *@file
+ *Some test facilities for the #CRInput class.
+ */
+
+/**
+ *The options data structure.
+ *The variable of this data structure are set
+ *during the parsing the command line by the
+ *parse_command_line() function.
+ */
+struct Options {
+ gboolean display_help;
+ gboolean display_about;
+ gchar **files_list;
+};
+
+static void
+ display_help (char *prg_name);
+
+static void
+ display_about (char *prg_name);
+
+static void
+ parse_command_line (int a_argc, char **a_argv, struct Options *a_options);
+
+static enum CRStatus
+ test_cr_input_read_byte (guchar * a_file_uri);
+
+/**
+ *Displays the usage of the test
+ *facility.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_help (char *prg_name)
+{
+ g_print ("\n\n");
+ g_print ("usage: %s <file-to-parse>\n", prg_name);
+ g_print ("\t <file-to-parse>: the file to parse\n");
+ g_print ("\n\n");
+ g_print ("This test just reads the file byte per byte\nand sends each byte to stdout\n");
+ g_print ("\n\n");
+}
+
+/**
+ *Displays the about text.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_about (char *prg_name)
+{
+ g_print ("\n\n");
+ g_print ("%s is a libcroco CRInput class test program.\n", prg_name);
+ g_print ("It should run on GNU compliants systems.\n");
+ g_print ("\n\n");
+ g_print ("Initial author: Dodji Seketeli <dodji@seketeli.org>.\n");
+ g_print ("\n\n");
+}
+
+/**
+ *Parses the command line and updates an abstract "options" data structure.
+ *@param a_argc the argc variable passed to the main function by the OS.
+ *@param a_argv the argv variable passed to the main function by the OS.
+ *@param a_options out parameter. The abstraction of the parsed the options.
+ */
+static void
+parse_command_line (int a_argc, char **a_argv, struct Options *a_options)
+{
+ int i = 0;
+
+ g_return_if_fail (a_options);
+
+ memset (a_options, 0, sizeof (struct Options));
+
+ for (i = 1; i < a_argc; i++) {
+ if (a_argv[i][0] != '-')
+ break;
+
+ if (!strcmp (a_argv[i], "-h")
+ || !strcmp (a_argv[i], "--help")) {
+ a_options->display_help = TRUE;
+ }
+ if (!strcmp (a_argv[i], "--about")) {
+ a_options->display_about = TRUE;
+ }
+ }
+
+ if (i >= a_argc) {
+ /*No file parameter where given */
+ a_options->files_list = NULL;
+ } else {
+ a_options->files_list = &a_argv[i];
+ }
+}
+
+/**
+ *The test of the cr_input_read_byte() method.
+ *Reads the each byte of a_file_uri using the
+ *cr_input_read_byte() method. Each byte is send to
+ *stdout.
+ *@param a_file_uri the file to read.
+ *@return CR_OK upon successful completion of the
+ *function, an error code otherwise.
+ */
+static enum CRStatus
+test_cr_input_read_byte (guchar * a_file_uri)
+{
+ enum CRStatus status = CR_OK;
+ CRInput *input = NULL;
+ guchar byte = 0;
+ guint c = 0;
+
+ g_return_val_if_fail (a_file_uri, CR_BAD_PARAM_ERROR);
+
+ input = cr_input_new_from_uri ((const gchar *) a_file_uri, CR_UTF_8);
+
+ if (!input) {
+ cr_utils_trace_debug ("Input Stream creation failed.");
+ return CR_ERROR;
+ }
+
+ for (status = CR_OK; status == CR_OK;) {
+ status = cr_input_read_byte (input, &byte);
+
+ if (status == CR_OK) {
+ c = byte;
+ printf ("%d", c);
+ fflush (stdout);
+ }
+ }
+
+ if (status == CR_END_OF_INPUT_ERROR) {
+ status = CR_OK;
+ }
+
+ cr_input_destroy (input);
+ input = NULL;
+
+ return status;
+}
+
+/**
+ *The entry point of the testing routine.
+ */
+int
+main (int argc, char **argv)
+{
+ struct Options options;
+
+ parse_command_line (argc, argv, &options);
+
+ if (options.display_help == TRUE) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ if (options.display_about == TRUE) {
+ display_about (argv[0]);
+ return 0;
+ }
+
+ if (options.files_list == NULL) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ test_cr_input_read_byte ((guchar *) options.files_list[0]);
+
+ return 0;
+}
diff --git a/src/3rdparty/libcroco/tests/test1-main.c b/src/3rdparty/libcroco/tests/test1-main.c
new file mode 100644
index 0000000..1c5f127
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test1-main.c
@@ -0,0 +1,197 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * See COPYRIGHTS file for copyright information
+ */
+
+#include <stdio.h>
+#include "cr-input.h"
+#include "string.h"
+
+/**
+ *@file
+ *Some test facilities for the #CRInput class.
+ */
+
+/**
+ *The options data structure.
+ *The variable of this data structure are set
+ *during the parsing the command line by the
+ *parse_command_line() function.
+ */
+struct Options {
+ gboolean display_help;
+ gboolean display_about;
+ gchar **files_list;
+};
+
+static void
+ display_help (char *prg_name);
+
+static void
+ display_about (char *prg_name);
+
+static void
+ parse_command_line (int a_argc, char **a_argv, struct Options *a_options);
+
+static enum CRStatus
+ test_cr_input_read_char (guchar * a_file_uri);
+
+/**
+ *Displays the usage of the test
+ *facility.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_help (char *prg_name)
+{
+ g_print ("\n\n");
+ g_print ("usage: %s <file-to-parse>\n", prg_name);
+ g_print ("\t <file-to-parse>: the file to parse\n");
+ g_print ("\n\n");
+ g_print ("This test just reads the file character per character\nand sends each character to stdout\n");
+ g_print ("\n\n");
+}
+
+/**
+ *Displays the about text.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_about (char *prg_name)
+{
+ g_print ("\n\n");
+ g_print ("%s is a libcroco CRInput class test program.\n", prg_name);
+ g_print ("It should run on GNU compliants systems.\n");
+ g_print ("\n\n");
+ g_print ("Initial author: Dodji Seketeli <dodji@seketeli.org>.\n");
+ g_print ("\n\n");
+}
+
+/**
+ *Parses the command line and updates an abstract "options" data structure.
+ *@param a_argc the argc variable passed to the main function by the OS.
+ *@param a_argv the argv variable passed to the main function by the OS.
+ *@param a_options out parameter. The abstraction of the parsed the options.
+ */
+static void
+parse_command_line (int a_argc, char **a_argv, struct Options *a_options)
+{
+ int i = 0;
+
+ g_return_if_fail (a_options);
+
+ memset (a_options, 0, sizeof (struct Options));
+
+ for (i = 1; i < a_argc; i++) {
+ if (a_argv[i][0] != '-')
+ break;
+
+ if (!strcmp (a_argv[i], "-h")
+ || !strcmp (a_argv[i], "--help")) {
+ a_options->display_help = TRUE;
+ }
+ if (!strcmp (a_argv[i], "--about")) {
+ a_options->display_about = TRUE;
+ }
+ }
+
+ if (i >= a_argc) {
+ /*No file parameter where given */
+ a_options->files_list = NULL;
+ } else {
+ a_options->files_list = &a_argv[i];
+ }
+}
+
+/**
+ *The test of the cr_input_read_byte() method.
+ *Reads the each byte of a_file_uri using the
+ *cr_input_read_byte() method. Each byte is send to
+ *stdout.
+ *@param a_file_uri the file to read.
+ *@return CR_OK upon successful completion of the
+ *function, an error code otherwise.
+ */
+enum CRStatus
+test_cr_input_read_char (guchar * a_file_uri)
+{
+ enum CRStatus status = CR_OK;
+ CRInput *input = NULL;
+ guint32 c = 0;
+
+ g_return_val_if_fail (a_file_uri, CR_BAD_PARAM_ERROR);
+
+ input = cr_input_new_from_uri ((const gchar *) a_file_uri, CR_UTF_8);
+
+ if (!input) {
+ cr_utils_trace_debug ("Input Stream creation failed.");
+ return CR_ERROR;
+ }
+
+ for (status = CR_OK; status == CR_OK;) {
+ status = cr_input_read_char (input, &c);
+
+ if (status == CR_OK) {
+ printf ("%c", c);
+ fflush (stdout);
+ }
+ }
+
+ if (status == CR_END_OF_INPUT_ERROR) {
+ status = CR_OK;
+ }
+
+ cr_input_destroy (input);
+ input = NULL;
+
+ return status;
+}
+
+/**
+ *The entry point of the testing routine.
+ */
+int
+main (int argc, char **argv)
+{
+ struct Options options;
+
+ parse_command_line (argc, argv, &options);
+
+ if (options.display_help == TRUE) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ if (options.display_about == TRUE) {
+ display_about (argv[0]);
+ return 0;
+ }
+
+ if (options.files_list == NULL) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ test_cr_input_read_char ((guchar *) options.files_list[0]);
+
+ return 0;
+}
diff --git a/src/3rdparty/libcroco/tests/test2-main.c b/src/3rdparty/libcroco/tests/test2-main.c
new file mode 100644
index 0000000..5268ed3
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test2-main.c
@@ -0,0 +1,564 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms
+ * of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the
+ * GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "cr-test-utils.h"
+#include "cr-parser.h"
+
+/**
+ *@file
+ *Some test facilities for the #CRParser class.
+ */
+
+CRDocHandler *gv_test_handler = { 0 };
+
+static void
+ display_help (char *prg_name);
+
+static void
+ display_about (char *prg_name);
+
+static enum CRStatus
+ test_cr_parser_parse (guchar * a_file_uri);
+
+/**
+ *Displays the usage of the test
+ *facility.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_help (char *prg_name)
+{
+ fprintf (stdout, "\n\n");
+ fprintf (stdout, "usage: %s <file-to-parse>\n", prg_name);
+ fprintf (stdout, "\t <file-to-parse>: the file to parse\n");
+ fprintf (stdout, "\n\n");
+ fprintf (stdout, "Tests the cr_parser_parse () method.\n");
+ fprintf (stdout, "Returns OK if the status is CR_OK, KO otherwise\n");
+ fprintf (stdout, "\n\n");
+}
+
+/**
+ *Displays the about text.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_about (char *prg_name)
+{
+ fprintf (stdout, "\n\n");
+ fprintf (stdout, "%s is a libcroco CRParser class test program.\n",
+ prg_name);
+ fprintf (stdout, "It should run on GNU compliants systems.\n");
+ fprintf (stdout, "\n\n");
+ fprintf (stdout,
+ "Initial author: Dodji Seketeli <dodji@seketeli.org>.\n");
+ fprintf (stdout, "\n\n");
+}
+
+/***************************
+ *Some SAC document handlers
+ *for TEST PURPOSES.
+ ***************************/
+
+static void
+test_start_document (CRDocHandler * a_handler)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "start_document\n");
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_end_document (CRDocHandler * a_handler)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "end_document\n");
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_import_style (CRDocHandler * a_handler,
+ GList * a_media_list,
+ CRString * a_uri,
+ CRString * a_uri_default_ns,
+ CRParsingLocation *a_location)
+{
+ (void) a_uri;
+
+ g_return_if_fail (a_handler) ;
+
+ fprintf (stdout, "****************\n");
+ fprintf (stdout, "import_style\n");
+
+ if (a_media_list) {
+ GList *cur = NULL;
+
+ fprintf (stdout, "\nmedia list:\n");
+ fprintf (stdout, "-------------\n");
+
+ for (cur = a_media_list; cur; cur = cur->next) {
+ if (cur->data) {
+ gchar *str =
+ g_strndup
+ (((CRString *) cur->data)->stryng->str,
+ ((CRString *) cur->data)->stryng->len);
+
+ if (str) {
+ fprintf (stdout, "%s\n", str);
+ g_free (str);
+ str = NULL;
+ }
+ }
+ }
+
+ fprintf (stdout, "\ndefault namespace:\n");
+ fprintf (stdout, "--------------------\n");
+
+ if (a_uri_default_ns) {
+ guchar *str = (guchar *) cr_string_dup2
+ (a_uri_default_ns) ;
+ if (str) {
+ fprintf (stdout, "%s\n", str);
+ g_free (str);
+ str = NULL;
+ }
+ }
+ }
+
+ fprintf (stdout, "******************\n\n");
+ a_uri = NULL; /*keep compiler happy */
+}
+
+static void
+test_namespace_declaration (CRDocHandler * a_handler,
+ CRString * a_prefix,
+ CRString * a_uri,
+ CRParsingLocation *a_location)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "namespace_declaration:\n");
+
+ if (a_prefix) {
+ gchar *prefix = NULL;
+
+ prefix = cr_string_dup2 (a_prefix) ;
+ if (prefix) {
+ fprintf (stdout, "prefix: %s\n", prefix);
+ g_free (prefix);
+ prefix = NULL;
+ }
+ }
+ if (a_uri) {
+ gchar *uri = NULL;
+
+ uri = cr_string_dup2 (a_uri) ;
+ if (uri) {
+ fprintf (stdout, "uri: %s\n", uri);
+ g_free (uri);
+ uri = NULL;
+ }
+ }
+ fprintf (stdout, "\n");
+
+ fprintf (stdout, "***************\n\n");
+
+}
+
+static void
+test_comment (CRDocHandler * a_handler,
+ CRString * a_comment)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "comment:\n");
+ if (a_comment) {
+ gchar *comment = NULL;
+
+ comment = cr_string_dup2 (a_comment);
+
+ if (comment) {
+ fprintf (stdout, "\n/*----------------------\n");
+ fprintf (stdout, "%s\n", comment);
+ fprintf (stdout, "-------------------------*/\n");
+ g_free (comment);
+ comment = NULL;
+ }
+ }
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_start_selector (CRDocHandler * a_handler,
+ CRSelector * a_selector_list)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "start_selector\n");
+
+ if (a_selector_list) {
+ cr_selector_dump (a_selector_list, stdout);
+ fprintf (stdout, "\n");
+ }
+
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_end_selector (CRDocHandler * a_handler,
+ CRSelector * a_selector_list)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "end_selector\n");
+
+ if (a_selector_list) {
+ cr_selector_dump (a_selector_list, stdout);
+ fprintf (stdout, "\n");
+ }
+
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_property (CRDocHandler * a_handler,
+ CRString * a_name,
+ CRTerm * a_expr,
+ gboolean a_important)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "property\n");
+
+ if (a_name
+ && a_name->stryng
+ && a_name->stryng->str) {
+ gchar *name = g_strndup
+ (a_name->stryng->str,
+ a_name->stryng->len);
+
+ if (name) {
+ fprintf (stdout, "%s", name);
+ }
+ if (a_expr) {
+ fprintf (stdout, ": ");
+ cr_term_dump (a_expr, stdout);
+ }
+ if (name) {
+ g_free (name);
+ name = NULL;
+ }
+ fprintf (stdout, "\n");
+ }
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_start_font_face (CRDocHandler * a_handler,
+ CRParsingLocation *a_location)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "start_font_face\n");
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_end_font_face (CRDocHandler * a_handler)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "end_font_face\n");
+ fprintf (stdout, "***************\n\n");
+
+}
+
+static void
+test_start_media (CRDocHandler * a_handler,
+ GList * a_media_list,
+ CRParsingLocation *a_location)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "start_media\n");
+
+ if (a_media_list) {
+ GList *cur = NULL;
+ gchar *medium = NULL;
+
+ for (cur = a_media_list; cur; cur = cur->next) {
+ if (cur->data == NULL)
+ continue;
+ medium = cr_string_dup2
+ ((CRString *) cur->data);
+ if (medium == NULL)
+ continue;
+ fprintf (stdout, "medium: %s\n", medium);
+ if (medium) {
+ g_free (medium);
+ medium = NULL;
+ }
+ }
+ }
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_end_media (CRDocHandler * a_handler,
+ GList * a_media_list)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "end_media\n");
+
+ if (a_media_list) {
+ GList *cur = NULL;
+ gchar *medium = NULL;
+
+ for (cur = a_media_list; cur; cur = cur->next) {
+ if (cur->data == NULL)
+ continue;
+
+ medium = g_strndup (((CRString *) cur->data)->stryng->str,
+ ((CRString *) cur->data)->stryng->len);
+ if (medium == NULL)
+ continue;
+ fprintf (stdout, "medium: %s\n", medium);
+ if (medium) {
+ g_free (medium);
+ medium = NULL;
+ }
+ }
+ }
+
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_start_page (CRDocHandler * a_handler,
+ CRString * a_name,
+ CRString * a_pseudo_page,
+ CRParsingLocation *a_location)
+{
+ gchar *name = NULL,
+ *pseudo_page = NULL;
+
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "start_page\n");
+
+ if (a_name) {
+ name = cr_string_dup2 (a_name) ;
+ }
+ if (a_pseudo_page) {
+ pseudo_page = cr_string_dup2 (a_pseudo_page);
+ }
+ if (name) {
+ fprintf (stdout, "%s", name);
+ }
+ if (pseudo_page) {
+ fprintf (stdout, ": %s\n", pseudo_page);
+ }
+ fprintf (stdout, "***************\n\n");
+ if (name) {
+ g_free (name);
+ name = NULL;
+ }
+ if (pseudo_page) {
+ g_free (pseudo_page);
+ pseudo_page = NULL;
+ }
+}
+
+static void
+test_end_page (CRDocHandler * a_handler,
+ CRString * a_name,
+ CRString * a_pseudo_page)
+{
+ gchar *name = NULL,
+ *pseudo_page = NULL;
+
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "end_page\n");
+
+ if (a_name) {
+ name = cr_string_dup2 (a_name) ;
+ }
+ if (a_pseudo_page) {
+ pseudo_page = cr_string_dup2 (a_pseudo_page) ;
+ }
+ if (name) {
+ fprintf (stdout, "%s", name);
+ }
+ if (pseudo_page) {
+ fprintf (stdout, ": %s\n", pseudo_page);
+
+ }
+ fprintf (stdout, "***************\n\n");
+ if (name) {
+ g_free (name);
+ name = NULL;
+ }
+ if (pseudo_page) {
+ g_free (pseudo_page);
+ pseudo_page = NULL;
+ }
+}
+
+static void
+test_ignorable_at_rule (CRDocHandler * a_handler,
+ CRString * a_name)
+{
+ gchar *name = NULL;
+
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "*********************\n");
+ fprintf (stdout, "ignorable_at_rule\n");
+
+ if (a_name) {
+ name = cr_string_dup2 (a_name);
+ }
+ if (name) {
+ fprintf (stdout, "%s\n", name);
+ }
+ fprintf (stdout, "*********************\n\n");
+}
+
+static void
+init_test_sac_handler (CRDocHandler * a_handler)
+{
+ a_handler->start_document = test_start_document;
+ a_handler->end_document = test_end_document;
+ a_handler->import_style = test_import_style;
+ a_handler->namespace_declaration = test_namespace_declaration;
+ a_handler->comment = test_comment;
+ a_handler->start_selector = test_start_selector;
+ a_handler->end_selector = test_end_selector;
+ a_handler->property = test_property;
+ a_handler->start_font_face = test_start_font_face;
+ a_handler->end_font_face = test_end_font_face;
+ a_handler->start_media = test_start_media;
+ a_handler->end_media = test_end_media;
+ a_handler->start_page = test_start_page;
+ a_handler->end_page = test_end_page;
+ a_handler->ignorable_at_rule = test_ignorable_at_rule;
+}
+
+/***************************
+ *END of TEST SAC document
+ *handlers.
+ ***************************/
+
+/**
+ *The test of the cr_input_read_byte() method.
+ *Reads the each byte of a_file_uri using the
+ *cr_input_read_byte() method. Each byte is send to
+ *stdout.
+ *@param a_file_uri the file to read.
+ *@return CR_OK upon successful completion of the
+ *function, an error code otherwise.
+ */
+static enum CRStatus
+test_cr_parser_parse (guchar * a_file_uri)
+{
+ enum CRStatus status = CR_OK;
+ CRParser *parser = NULL;
+
+ g_return_val_if_fail (a_file_uri, CR_BAD_PARAM_ERROR);
+
+ gv_test_handler = cr_doc_handler_new ();
+ init_test_sac_handler (gv_test_handler);
+
+ parser = cr_parser_new (NULL);
+
+ status = cr_parser_set_sac_handler (parser, gv_test_handler);
+
+ if (status != CR_OK) {
+ cr_parser_destroy (parser);
+ g_return_val_if_fail (status == CR_OK, CR_ERROR);
+ }
+
+ status = cr_parser_parse_file (parser, a_file_uri, CR_ASCII);
+
+ cr_parser_destroy (parser);
+
+ gv_test_handler = NULL;
+
+ return status;
+}
+
+/**
+ *The entry point of the testing routine.
+ */
+int
+main (int argc, char **argv)
+{
+ struct Options options;
+ enum CRStatus status = CR_OK;
+
+ cr_test_utils_parse_cmd_line (argc, argv, &options);
+
+ if (options.display_help == TRUE) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ if (options.display_about == TRUE) {
+ display_about (argv[0]);
+ return 0;
+ }
+
+ if (options.files_list == NULL) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ status = test_cr_parser_parse ((guchar *) options.files_list[0]);
+
+ if (status != CR_OK) {
+ fprintf (stdout, "KO\n");
+ }
+
+ return 0;
+}
diff --git a/src/3rdparty/libcroco/tests/test3-main.c b/src/3rdparty/libcroco/tests/test3-main.c
new file mode 100644
index 0000000..1979778
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test3-main.c
@@ -0,0 +1,545 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyright information.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "cr-test-utils.h"
+#include "cr-parser.h"
+
+/**
+ *@file
+ *Some test facilities for the #CRParser class.
+ */
+
+CRDocHandler *gv_test_handler = { 0 };
+
+static void display_help (char *prg_name);
+
+static void display_about (char *prg_name);
+
+static enum CRStatus test_cr_parser_parse (guchar * a_file_uri);
+
+/**
+ *Displays the usage of the test
+ *facility.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_help (char *prg_name)
+{
+ fprintf (stdout, "\n\n");
+ fprintf (stdout, "usage: %s <file-to-parse>\n", prg_name);
+ fprintf (stdout, "\t <file-to-parse>: the file to parse\n");
+ fprintf (stdout, "\n\n");
+ fprintf (stdout, "Tests the cr_parser_parse () method.\n");
+ fprintf (stdout, "Tests the parsing following the css core syntax\n");
+ fprintf (stdout, "Returns OK if the status is CR_OK, KO otherwise\n");
+ fprintf (stdout, "\n\n");
+}
+
+/**
+ *Displays the about text.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_about (char *prg_name)
+{
+ fprintf (stdout, "\n\n");
+ fprintf (stdout, "%s is a libcroco CRParser class test program.\n",
+ prg_name);
+ fprintf (stdout, "It should run on GNU compliants systems.\n");
+ fprintf (stdout, "\n\n");
+ fprintf (stdout,
+ "Initial author: Dodji Seketeli <dodji@seketeli.org>.\n");
+ fprintf (stdout, "\n\n");
+}
+
+/***************************
+ *Some SAC document handlers
+ *for TEST PURPOSES.
+ ***************************/
+
+static void
+test_start_document (CRDocHandler * a_handler)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "start_document\n");
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_end_document (CRDocHandler * a_handler)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "end_document\n");
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_import_style (CRDocHandler * a_handler,
+ GList * a_media_list, CRString * a_uri,
+ CRString * a_uri_default_ns,
+ CRParsingLocation *a_location)
+{
+ g_return_if_fail (a_handler);
+
+ (void) a_uri;
+
+ fprintf (stdout, "****************\n");
+ fprintf (stdout, "import_style\n");
+
+ if (a_media_list) {
+ GList *cur = NULL;
+
+ fprintf (stdout, "\nmedia list:\n");
+ fprintf (stdout, "-------------\n");
+
+ for (cur = a_media_list; cur; cur = cur->next) {
+ if (cur->data) {
+ gchar *str =
+ cr_string_dup2 ((CRString *) cur->data);
+ if (str) {
+ fprintf (stdout, "%s\n", str);
+ g_free (str);
+ str = NULL;
+ }
+ }
+ }
+ fprintf (stdout, "\ndefault namespace:\n");
+ fprintf (stdout, "--------------------\n");
+
+ if (a_uri_default_ns) {
+ gchar *str = cr_string_dup2 (a_uri_default_ns) ;
+ if (str) {
+ fprintf (stdout, "%s\n", str);
+ g_free (str);
+ str = NULL;
+ }
+ }
+ }
+
+ fprintf (stdout, "******************\n\n");
+ a_uri = NULL; /*keep compiler happy */
+}
+
+static void
+test_namespace_declaration (CRDocHandler * a_handler,
+ CRString * a_prefix,
+ CRString * a_uri,
+ CRParsingLocation *a_location)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "namespace_declaration:\n");
+
+ if (a_prefix) {
+ gchar *prefix = NULL;
+
+ prefix = cr_string_dup2 (a_prefix);
+ if (prefix) {
+ fprintf (stdout, "prefix: %s\n", prefix);
+ g_free (prefix);
+ prefix = NULL;
+ }
+ }
+
+ if (a_uri) {
+ gchar *uri = NULL;
+ uri = cr_string_dup2 (a_uri) ;
+ if (uri) {
+ fprintf (stdout, "uri: %s\n", uri);
+ g_free (uri);
+ uri = NULL;
+ }
+ }
+ fprintf (stdout, "\n");
+
+ fprintf (stdout, "***************\n\n");
+
+}
+
+static void
+test_comment (CRDocHandler * a_handler,
+ CRString * a_comment)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "comment:\n");
+
+ if (a_comment) {
+ gchar *comment = NULL;
+
+ comment = cr_string_dup2 (a_comment);
+
+ if (comment) {
+ fprintf (stdout, "\n/*----------------------\n");
+ fprintf (stdout, "%s\n", comment);
+ fprintf (stdout, "-------------------------*/\n");
+ g_free (comment);
+ comment = NULL;
+ }
+ }
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_start_selector (CRDocHandler * a_handler,
+ CRSelector * a_selector_list)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "start_selector\n");
+
+ if (a_selector_list) {
+ cr_selector_dump (a_selector_list, stdout);
+ fprintf (stdout, "\n");
+ }
+
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_end_selector (CRDocHandler * a_handler,
+ CRSelector * a_selector_list)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "end_selector\n");
+
+ if (a_selector_list) {
+ cr_selector_dump (a_selector_list, stdout);
+ fprintf (stdout, "\n");
+ }
+
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_property (CRDocHandler * a_handler, CRString * a_name,
+ CRTerm * a_expr, gboolean a_important)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "property\n");
+
+ if (a_name) {
+ gchar *name = cr_string_dup2 (a_name);
+ if (name) {
+ fprintf (stdout, "%s", name);
+ }
+ if (a_expr) {
+ fprintf (stdout, ": ");
+ cr_term_dump (a_expr, stdout);
+ }
+ if (name) {
+ g_free (name);
+ name = NULL;
+ }
+ fprintf (stdout, "\n");
+ }
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_start_font_face (CRDocHandler * a_handler,
+ CRParsingLocation *a_location)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "start_font_face\n");
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_end_font_face (CRDocHandler * a_handler)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "end_font_face\n");
+ fprintf (stdout, "***************\n\n");
+
+}
+
+static void
+test_start_media (CRDocHandler * a_handler,
+ GList * a_media_list,
+ CRParsingLocation *a_location)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "start_media\n");
+
+ if (a_media_list) {
+ GList *cur = NULL;
+ gchar *medium = NULL;
+
+ for (cur = a_media_list; cur; cur = cur->next) {
+ if (cur->data == NULL)
+ continue;
+ medium = cr_string_dup2 ((CRString *) cur->data);
+ if (medium == NULL)
+ continue;
+ fprintf (stdout, "medium: %s\n", medium);
+ if (medium) {
+ g_free (medium);
+ medium = NULL;
+ }
+ }
+ }
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_end_media (CRDocHandler * a_handler,
+ GList * a_media_list)
+{
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "end_media\n");
+
+ if (a_media_list) {
+ GList *cur = NULL;
+ gchar *medium = NULL;
+
+ for (cur = a_media_list; cur; cur = cur->next) {
+ if (cur->data == NULL)
+ continue;
+ medium = cr_string_dup2 ((CRString *) cur->data);
+ if (medium == NULL)
+ continue;
+ fprintf (stdout, "medium: %s\n", medium);
+ if (medium) {
+ g_free (medium);
+ medium = NULL;
+ }
+ }
+ }
+ fprintf (stdout, "***************\n\n");
+}
+
+static void
+test_start_page (CRDocHandler * a_handler,
+ CRString * a_name,
+ CRString * a_pseudo_page,
+ CRParsingLocation *a_location)
+{
+ gchar *name = NULL,
+ *pseudo_page = NULL;
+
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "start_page\n");
+
+ if (a_name) {
+ name = cr_string_dup2 (a_name);
+ }
+ if (a_pseudo_page) {
+ pseudo_page = cr_string_dup2 (a_pseudo_page);
+ }
+ if (name) {
+ fprintf (stdout, "%s", name);
+ }
+ if (pseudo_page) {
+ fprintf (stdout, ": %s\n", pseudo_page);
+ }
+ fprintf (stdout, "***************\n\n");
+ if (name) {
+ g_free (name);
+ name = NULL;
+ }
+ if (pseudo_page) {
+ g_free (pseudo_page);
+ pseudo_page = NULL;
+ }
+}
+
+static void
+test_end_page (CRDocHandler * a_handler,
+ CRString * a_name,
+ CRString * a_pseudo_page)
+{
+ gchar *name = NULL,
+ *pseudo_page = NULL;
+
+ g_return_if_fail (a_handler);
+ fprintf (stdout, "***************\n");
+ fprintf (stdout, "end_page\n");
+
+ if (a_name) {
+ name = cr_string_dup2 (a_name);
+ }
+ if (a_pseudo_page) {
+ pseudo_page = cr_string_dup2 (a_pseudo_page) ;
+ }
+ if (name) {
+ fprintf (stdout, "%s", name);
+ }
+ if (pseudo_page) {
+ fprintf (stdout, ": %s\n", pseudo_page);
+
+ }
+ fprintf (stdout, "***************\n\n");
+ if (name) {
+ g_free (name);
+ name = NULL;
+ }
+ if (pseudo_page) {
+ g_free (pseudo_page);
+ pseudo_page = NULL;
+ }
+}
+
+static void
+test_ignorable_at_rule (CRDocHandler * a_handler,
+ CRString * a_name)
+{
+ gchar *name = NULL;
+
+ g_return_if_fail (a_handler);
+
+ fprintf (stdout, "*********************\n");
+ fprintf (stdout, "ignorable_at_rule\n");
+
+ if (a_name) {
+ name = cr_string_dup2 (a_name);
+ }
+ if (name) {
+ fprintf (stdout, "%s\n", name);
+ }
+ fprintf (stdout, "*********************\n\n");
+}
+
+static void
+init_test_sac_handler (CRDocHandler * a_handler)
+{
+ a_handler->start_document = test_start_document;
+ a_handler->end_document = test_end_document;
+ a_handler->import_style = test_import_style;
+ a_handler->namespace_declaration = test_namespace_declaration;
+ a_handler->comment = test_comment;
+ a_handler->start_selector = test_start_selector;
+ a_handler->end_selector = test_end_selector;
+ a_handler->property = test_property;
+ a_handler->start_font_face = test_start_font_face;
+ a_handler->end_font_face = test_end_font_face;
+ a_handler->start_media = test_start_media;
+ a_handler->end_media = test_end_media;
+ a_handler->start_page = test_start_page;
+ a_handler->end_page = test_end_page;
+ a_handler->ignorable_at_rule = test_ignorable_at_rule;
+}
+
+/***************************
+ *END of TEST SAC document
+ *handlers.
+ ***************************/
+
+/**
+ *The test of the cr_input_read_byte() method.
+ *Reads the each byte of a_file_uri using the
+ *cr_input_read_byte() method. Each byte is send to
+ *stdout.
+ *@param a_file_uri the file to read.
+ *@return CR_OK upon successful completion of the
+ *function, an error code otherwise.
+ */
+static enum CRStatus
+test_cr_parser_parse (guchar * a_file_uri)
+{
+ enum CRStatus status = CR_OK;
+ CRParser *parser = NULL;
+
+ g_return_val_if_fail (a_file_uri, CR_BAD_PARAM_ERROR);
+
+ gv_test_handler = cr_doc_handler_new ();
+ init_test_sac_handler (gv_test_handler);
+
+ parser = cr_parser_new (NULL);
+
+ status = cr_parser_set_sac_handler (parser, gv_test_handler);
+
+ if (status != CR_OK) {
+ cr_parser_destroy (parser);
+ g_return_val_if_fail (status == CR_OK, CR_ERROR);
+ }
+
+ status = cr_parser_set_use_core_grammar (parser, TRUE);
+ status = cr_parser_parse_file (parser, a_file_uri, CR_ASCII);
+
+ cr_parser_destroy (parser);
+
+ gv_test_handler = NULL;
+
+ return status;
+}
+
+/**
+ *The entry point of the testing routine.
+ */
+int
+main (int argc, char **argv)
+{
+ struct Options options;
+ enum CRStatus status = CR_OK;
+
+ cr_test_utils_parse_cmd_line (argc, argv, &options);
+
+ if (options.display_help == TRUE) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ if (options.display_about == TRUE) {
+ display_about (argv[0]);
+ return 0;
+ }
+
+ if (options.files_list == NULL) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ status = test_cr_parser_parse ((guchar *) options.files_list[0]);
+
+ if (status != CR_OK) {
+ fprintf (stdout, "KO\n");
+ }
+
+ return 0;
+}
diff --git a/src/3rdparty/libcroco/tests/test4-main.c b/src/3rdparty/libcroco/tests/test4-main.c
new file mode 100644
index 0000000..5cca6ef
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test4-main.c
@@ -0,0 +1,435 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Author: Dodji Seketeli
+ * See COPYRIGHTS file for copyrights information.
+ */
+
+
+#include "cr-test-utils.h"
+#include "libcroco.h"
+
+/**
+ *@file
+ *Some test facilities for the #CROMParser class.
+ */
+
+CRDocHandler *gv_test_handler = { 0 };
+
+const guchar *gv_term_buf = (const guchar *) "106";
+
+const guchar *gv_decl_buf = (const guchar *) "toto: tutu, tata";
+
+const guchar *gv_decl_list_buf = (const guchar *) "toto: titi; prop1:val1 ; prop2:val2;";
+
+const guchar *gv_ruleset_buf = (const guchar *) "s1 > s2 {toto: tutu, tata} ";
+
+const guchar *gv_at_media_buf =
+ (const guchar *) "@media print, toto {" " BODY { font-size: 10pt }" " }";
+
+const guchar *gv_at_page_buf = (const guchar *) "@page { size :8.5in 11in; margin: 2cm }";
+
+const guchar *gv_at_charset_buf = (const guchar *) "@charset \"ISO-8859-1\" ; ";
+
+const guchar *gv_at_font_face_buf =
+ (const guchar *) "@font-face {"
+ " font-family: \"Robson Celtic\";"
+ " src: url(\"http://site/fonts/rob-celt\")" "}";
+
+const guchar *gv_at_import_buf = (const guchar *) "@import \"subs.css\";";
+
+static void display_help (char *prg_name);
+
+static void display_about (char *prg_name);
+
+static enum CRStatus test_cr_parser_parse (guchar * a_file_uri);
+
+/**
+ *Displays the usage of the test
+ *facility.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_help (char *prg_name)
+{
+ g_print ("\n\n");
+ g_print ("usage: %s <file-to-parse>\n", prg_name);
+ g_print ("\t <file-to-parse>: the file to parse\n");
+ g_print ("\n\n");
+ g_print ("Tests the cr_parser_parse () method.\n");
+ g_print ("Tests the parsing following the css core syntax\n");
+ g_print ("Returns OK if the status is CR_OK, KO otherwise\n");
+ g_print ("\n\n");
+}
+
+/**
+ *Displays the about text.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_about (char *prg_name)
+{
+ g_print ("\n\n");
+ g_print ("%s is a libcroco CROMParser class test program.\n",
+ prg_name);
+ g_print ("%s Parses a file and builds a CSS object model", prg_name);
+ g_print ("It should run on GNU compliants systems.\n");
+ g_print ("\n\n");
+ g_print ("Initial author: Dodji Seketeli <dodji@seketeli.org>.\n");
+ g_print ("\n\n");
+}
+
+/**
+ *The test of the cr_input_read_byte() method.
+ *Reads the each byte of a_file_uri using the
+ *cr_input_read_byte() method. Each byte is send to
+ *stdout.
+ *@param a_file_uri the file to read.
+ *@return CR_OK upon successful completion of the
+ *function, an error code otherwise.
+ */
+static enum CRStatus
+test_cr_parser_parse (guchar * a_file_uri)
+{
+ enum CRStatus status = CR_OK;
+ CROMParser *parser = NULL;
+ CRStyleSheet *stylesheet = NULL;
+
+ g_return_val_if_fail (a_file_uri, CR_BAD_PARAM_ERROR);
+
+ parser = cr_om_parser_new (NULL);
+ status = cr_om_parser_parse_file (parser, a_file_uri, CR_ASCII,
+ &stylesheet);
+ if (status == CR_OK && stylesheet) {
+ cr_stylesheet_dump (stylesheet, stdout);
+ cr_stylesheet_destroy (stylesheet);
+ }
+ cr_om_parser_destroy (parser);
+
+ return status;
+}
+
+static enum CRStatus
+test_cr_statement_at_page_rule_parse_from_buf (void)
+{
+ CRStatement *stmt = NULL ;
+
+ stmt = cr_statement_at_page_rule_parse_from_buf
+ (gv_at_page_buf, CR_UTF_8) ;
+ if (!stmt) {
+ return CR_ERROR ;
+ }
+ cr_statement_destroy (stmt) ;
+ return CR_OK ;
+}
+
+static enum CRStatus
+test_cr_term_parse_expression_from_buf (void)
+{
+ guchar *tmp_str = NULL;
+ CRTerm *term = NULL;
+
+ term = cr_term_parse_expression_from_buf (gv_term_buf, CR_UTF_8);
+
+ if (!term)
+ return CR_ERROR;
+ tmp_str = cr_term_to_string (term);
+ if (term) {
+ cr_term_destroy (term);
+ term = NULL;
+ }
+ if (tmp_str) {
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+ return CR_OK;
+}
+
+static enum CRStatus
+test_cr_declaration_parse (void)
+{
+ gchar *tmp_str = NULL;
+ CRDeclaration *decl = NULL;
+
+ decl = cr_declaration_parse_from_buf (NULL, gv_decl_buf, CR_UTF_8);
+ if (!decl)
+ return CR_ERROR;
+ tmp_str = cr_declaration_to_string (decl, 2);
+
+ if (decl) {
+ cr_declaration_destroy (decl);
+ }
+
+ if (tmp_str) {
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+
+ return CR_OK;
+}
+
+static enum CRStatus
+test_cr_declaration_parse_list (void)
+{
+ GString *str = NULL;
+ gchar *tmp_str = NULL;
+ CRDeclaration *decl = NULL,
+ *cur_decl = NULL;
+
+ decl = cr_declaration_parse_list_from_buf (gv_decl_list_buf,
+ CR_UTF_8);
+ if (!decl)
+ return CR_ERROR;
+ str = g_string_new (NULL);
+ for (cur_decl = decl; cur_decl; cur_decl = cur_decl->next) {
+ tmp_str = cr_declaration_to_string (cur_decl, 2);
+ if (tmp_str) {
+ g_string_append_printf (str, "%s;", tmp_str);
+ g_free (tmp_str);
+ tmp_str = NULL;
+ }
+
+ }
+ if (decl) {
+ cr_declaration_destroy (decl);
+ }
+
+ if (str) {
+ g_string_free (str, TRUE);
+ str = NULL;
+ }
+
+ return CR_OK;
+}
+
+static enum CRStatus
+test_cr_statement_ruleset_parse (void)
+{
+ CRStatement *stmt = NULL;
+
+ stmt = cr_statement_ruleset_parse_from_buf (gv_ruleset_buf, CR_UTF_8);
+ g_return_val_if_fail (stmt, CR_ERROR);
+
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ }
+ return CR_OK;
+}
+
+static enum CRStatus
+test_cr_statement_at_media_rule_parse (void)
+{
+ CRStatement *stmt = NULL;
+
+ stmt = cr_statement_at_media_rule_parse_from_buf (gv_at_media_buf,
+ CR_UTF_8);
+ g_return_val_if_fail (stmt, CR_ERROR);
+
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ }
+
+ return CR_OK;
+}
+
+
+static enum CRStatus
+test_cr_statement_at_charset_rule_parse (void)
+{
+ CRStatement *stmt = NULL;
+
+ stmt = cr_statement_at_charset_rule_parse_from_buf (gv_at_charset_buf,
+ CR_UTF_8);
+ g_return_val_if_fail (stmt, CR_ERROR);
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ }
+
+ return CR_OK;
+}
+
+static enum CRStatus
+test_cr_statement_font_face_rule_parse_from_buf (void)
+{
+ CRStatement *stmt = NULL;
+
+ stmt = cr_statement_font_face_rule_parse_from_buf
+ (gv_at_font_face_buf, CR_UTF_8);
+ g_return_val_if_fail (stmt, CR_ERROR);
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ }
+
+ return CR_OK;
+}
+
+static enum CRStatus
+test_cr_statement_at_import_rule_parse_from_buf (void)
+{
+ CRStatement *stmt = NULL;
+
+ stmt = cr_statement_at_import_rule_parse_from_buf (gv_at_import_buf,
+ CR_UTF_8);
+ g_return_val_if_fail (stmt, CR_ERROR);
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ }
+
+ return CR_OK;
+}
+
+static enum CRStatus
+test_cr_statement_parse_from_buf (void)
+{
+ CRStatement *stmt = NULL;
+
+ stmt = cr_statement_parse_from_buf (gv_ruleset_buf, CR_UTF_8);
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ } else {
+ return CR_ERROR;
+ }
+ stmt = cr_statement_parse_from_buf (gv_at_media_buf, CR_UTF_8);
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ } else {
+ return CR_ERROR;
+ }
+ stmt = cr_statement_parse_from_buf (gv_at_page_buf, CR_UTF_8);
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ } else {
+ return CR_ERROR;
+ }
+ stmt = cr_statement_parse_from_buf (gv_at_charset_buf, CR_UTF_8);
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ } else {
+ return CR_ERROR;
+ }
+ stmt = cr_statement_parse_from_buf (gv_at_font_face_buf, CR_UTF_8);
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ } else {
+ return CR_ERROR;
+ }
+ stmt = cr_statement_parse_from_buf (gv_at_import_buf, CR_UTF_8);
+ if (stmt) {
+ cr_statement_destroy (stmt);
+ stmt = NULL;
+ } else {
+ return CR_ERROR;
+ }
+
+ return CR_OK;
+}
+
+/**
+ *The entry point of the testing routine.
+ */
+int
+main (int argc, char **argv)
+{
+ struct Options options;
+ enum CRStatus status = CR_OK;
+
+ status = test_cr_term_parse_expression_from_buf ();
+ if (status != CR_OK) {
+ g_print ("\ntest \"cr_term_parse_expression_from_buf failed\"");
+ }
+ status = test_cr_declaration_parse ();
+ if (status != CR_OK) {
+ g_print ("\n test \"cr_declaration_parse() failed\"\n");
+ }
+
+ status = test_cr_declaration_parse_list ();
+ if (status != CR_OK) {
+ g_print ("\ntest cr_declaration_parse_list() failed\n");
+ }
+ status = test_cr_statement_ruleset_parse ();
+ if (status != CR_OK) {
+ g_print ("\ntest cr_statement_ruleset_parse() failed\n");
+ }
+
+ status = test_cr_statement_at_media_rule_parse ();
+ if (status != CR_OK) {
+ g_print ("\ntest cr_statement_at_media_rule_parse() failed\n");
+ }
+ test_cr_statement_at_page_rule_parse_from_buf ();
+ if (status != CR_OK) {
+ g_print ("\ntest cr_statement_at_page_rule_parse() failed\n");
+ return 0;
+ }
+
+ status = test_cr_statement_at_charset_rule_parse ();
+ if (status != CR_OK) {
+ g_print ("\ntest cr_statement_at_charset_rule_parse() failed\n");
+ }
+
+ status = test_cr_statement_font_face_rule_parse_from_buf ();
+ if (status != CR_OK) {
+ g_print ("\ntest cr_statement_font_face_rule_parse_from_buf() failed\n");
+ }
+
+ test_cr_statement_at_import_rule_parse_from_buf ();
+ if (status != CR_OK) {
+ g_print ("\ntest cr_statement_at_import_rule() failed\n");
+ }
+
+ status = test_cr_statement_parse_from_buf ();
+ if (status != CR_OK) {
+ g_print ("\ntest cr_statement_parse_from_buf() failed\n");
+ }
+
+ cr_test_utils_parse_cmd_line (argc, argv, &options);
+
+ if (options.display_help == TRUE) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ if (options.display_about == TRUE) {
+ display_about (argv[0]);
+ return 0;
+ }
+
+ if (options.files_list == NULL) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ status = test_cr_parser_parse ((guchar *) options.files_list[0]);
+ if (status != CR_OK) {
+ g_print ("\nKO\n");
+ }
+
+ return 0;
+}
diff --git a/src/3rdparty/libcroco/tests/test5-main.c b/src/3rdparty/libcroco/tests/test5-main.c
new file mode 100644
index 0000000..b10d0b8
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test5-main.c
@@ -0,0 +1,255 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include "cr-test-utils.h"
+#include "cr-libxml-node-iface.h"
+#include "libcroco.h"
+
+#include <libxml/tree.h>
+#include <string.h>
+
+/**
+ *@file
+ *Some test facilities for the #CRParser class.
+ */
+
+CRDocHandler *gv_test_handler = { 0 };
+
+const guchar *xml_content =
+ (const guchar *) "<document>"
+ "<E0>text0</E0> "
+ "<E1><E1-1>text1</E1-1></E1>"
+ "<E2 attr2=\"val2\">text2</E2>"
+ "<E3 attr3=\"val3_1 val3_2 val3_3\">text3</E3>"
+ "<E4 attr4=\"val4_1-val4_2-val4_3\">text4</E4>"
+ "<E5 class=\"class5\">text5</E5>"
+ "<E6 id=\"id6\">text6</E6>"
+ "<E7 lang=\"fr\">text7</E7>" "</document>";
+
+static void
+ display_help (char *prg_name);
+
+static void
+ display_about (char *prg_name);
+static enum CRStatus
+ test_sel_eng (guchar * a_file_uri);
+
+static void
+ walk_xml_tree_and_lookup_rules (CRSelEng * a_sel_eng,
+ CRStyleSheet * a_sheet, xmlNode * a_node);
+
+/**
+ *Displays the usage of the test
+ *facility.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_help (char *prg_name)
+{
+ g_print ("\n\n");
+ g_print ("usage: %s <file-to-parse>\n", prg_name);
+ g_print ("\t <file-to-parse>: the file to parse\n");
+ g_print ("\n\n");
+ g_print ("Test the selection engine");
+ g_print ("Returns OK if the status is CR_OK, KO otherwise\n");
+ g_print ("\n\n");
+}
+
+/**
+ *Displays the about text.
+ *@param a_argc the argc variable passed to the main function.
+ *@param a_argv the argv variable passed to the main function.
+ */
+static void
+display_about (char *prg_name)
+{
+ g_print ("\n\n");
+ g_print ("%s is a libcroco CROMParser class test program.\n",
+ prg_name);
+ g_print ("%s Parses a file and builds a CSS object model", prg_name);
+ g_print ("It should run on GNU compliants systems.\n");
+ g_print ("\n\n");
+ g_print ("Initial author: Dodji Seketeli <dodji@seketeli.org>.\n");
+ g_print ("\n\n");
+}
+
+static void
+walk_xml_tree_and_lookup_rules (CRSelEng * a_sel_eng,
+ CRStyleSheet * a_sheet, xmlNode * a_node)
+{
+ CRStatement **stmts_tab = NULL;
+ gulong tab_len = 0,
+ i = 0;
+ enum CRStatus status = CR_OK;
+
+ xmlNode *cur_node = a_node;
+
+ for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
+ status = cr_sel_eng_get_matched_rulesets
+ (a_sel_eng, a_sheet, cur_node, &stmts_tab, &tab_len);
+
+ if (status == CR_OK && tab_len) {
+ g_print ("'''''''''''''''''''''''''\n");
+ g_print ("xml start element: %s\n", cur_node->name);
+
+ for (i = 0; i < tab_len; i++) {
+ if (stmts_tab[i]) {
+ g_print ("\n");
+ cr_statement_dump (stmts_tab[i],
+ stdout, 2);
+ }
+ }
+ g_print ("\n\nxml end element: %s\n", cur_node->name);
+ g_print ("'''''''''''''''''''''''''\n");
+ }
+
+ if (stmts_tab) {
+ g_free (stmts_tab);
+ stmts_tab = NULL;
+ }
+ if (cur_node->children) {
+ walk_xml_tree_and_lookup_rules
+ (a_sel_eng, a_sheet, cur_node->children);
+ }
+ }
+}
+
+/**
+ *The test of the cr_input_read_byte() method.
+ *Reads the each byte of a_file_uri using the
+ *cr_input_read_byte() method. Each byte is send to
+ *stdout.
+ *@param a_file_uri the file to read.
+ *@return CR_OK upon successful completion of the
+ *function, an error code otherwise.
+ */
+static enum CRStatus
+test_sel_eng (guchar * a_file_uri)
+{
+ enum CRStatus status = CR_OK;
+ CROMParser *parser = NULL;
+ CRStyleSheet *stylesheet = NULL;
+ xmlDoc *xml_doc = NULL;
+ xmlNode *cur_node = NULL;
+ CRSelEng *selection_engine = NULL;
+
+ g_return_val_if_fail (a_file_uri, CR_BAD_PARAM_ERROR);
+
+ parser = cr_om_parser_new (NULL);
+ status = cr_om_parser_parse_file (parser, a_file_uri, CR_ASCII,
+ &stylesheet);
+ if (status != CR_OK || !stylesheet) {
+ cr_utils_trace_info ("Could not parse xml content");
+ goto error;
+ }
+
+ xml_doc = xmlParseMemory ((const char *) xml_content, strlen ((const char *) xml_content));
+ if (!xml_doc) {
+ cr_utils_trace_info ("Could not parse xml content");
+ goto error;
+
+ }
+
+ selection_engine = cr_sel_eng_new (&cr_libxml_node_iface);
+
+ cur_node = xml_doc->children;
+
+ walk_xml_tree_and_lookup_rules (selection_engine,
+ stylesheet, cur_node);
+
+ if (parser) {
+ cr_om_parser_destroy (parser);
+ parser = NULL;
+ }
+
+ if (xml_doc) {
+ xmlFreeDoc (xml_doc);
+ xml_doc = NULL;
+ }
+
+ if (stylesheet) {
+ cr_stylesheet_destroy (stylesheet);
+ stylesheet = NULL;
+ }
+ if (selection_engine) {
+ cr_sel_eng_destroy (selection_engine) ;
+ selection_engine = NULL ;
+ }
+ xmlCleanupParser ();
+ return status;
+
+ error:
+
+ if (parser) {
+ cr_om_parser_destroy (parser);
+ parser = NULL;
+ }
+
+ if (xml_doc) {
+ xmlFreeDoc (xml_doc);
+ xml_doc = NULL;
+ }
+
+ if (stylesheet) {
+ cr_stylesheet_destroy (stylesheet);
+ stylesheet = NULL;
+ }
+
+ xmlCleanupParser ();
+ return CR_ERROR;
+}
+
+/**
+ *The entry point of the testing routine.
+ */
+int
+main (int argc, char **argv)
+{
+ struct Options options;
+ enum CRStatus status = CR_OK;
+
+ cr_test_utils_parse_cmd_line (argc, argv, &options);
+
+ if (options.display_help == TRUE) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ if (options.display_about == TRUE) {
+ display_about (argv[0]);
+ return 0;
+ }
+
+ if (options.files_list == NULL) {
+ display_help (argv[0]);
+ return 0;
+ }
+
+ status = test_sel_eng ((guchar *) options.files_list[0]);
+
+ if (status != CR_OK) {
+ g_print ("\nKO\n");
+ }
+
+ return 0;
+}
diff --git a/src/3rdparty/libcroco/tests/test6-main.c b/src/3rdparty/libcroco/tests/test6-main.c
new file mode 100644
index 0000000..4372c5d
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test6-main.c
@@ -0,0 +1,84 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms
+ * of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the
+ * GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ *$Id$
+ */
+
+#include <string.h>
+#include "libcroco.h"
+#include "cr-test-utils.h"
+
+const guchar *gv_cssbuf =
+ (const guchar *) ".str0 {stroke:#007844;stroke-width:44}" ".fil0 {fill:url(#id0)}";
+
+static enum CRStatus
+ test_cr_parser_parse (void);
+
+/**
+ *The test of the cr_input_read_byte() method.
+ *Reads the each byte of a_file_uri using the
+ *cr_input_read_byte() method. Each byte is send to
+ *stdout.
+ *@param a_file_uri the file to read.
+ *@return CR_OK upon successful completion of the
+ *function, an error code otherwise.
+ */
+static enum CRStatus
+test_cr_parser_parse (void)
+{
+ enum CRStatus status = CR_OK;
+ CROMParser *parser = NULL;
+ CRStyleSheet *stylesheet = NULL;
+
+ parser = cr_om_parser_new (NULL);
+ status = cr_om_parser_parse_buf (parser, (guchar *) gv_cssbuf,
+ strlen ((const char *) gv_cssbuf),
+ CR_ASCII, &stylesheet);
+
+ if (status == CR_OK && stylesheet) {
+ cr_stylesheet_dump (stylesheet, stdout);
+ cr_stylesheet_destroy (stylesheet);
+ }
+ cr_om_parser_destroy (parser);
+
+ return status;
+}
+
+/**
+ *The entry point of the testing routine.
+ */
+int
+main (int argc, char **argv)
+{
+ enum CRStatus status = CR_OK;
+
+ status = test_cr_parser_parse ();
+
+ if (status != CR_OK) {
+ g_print ("\nKO\n");
+ }
+
+ return 0;
+}
diff --git a/src/3rdparty/libcroco/tests/test7-main.c b/src/3rdparty/libcroco/tests/test7-main.c
new file mode 100644
index 0000000..f740bea
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test7-main.c
@@ -0,0 +1,95 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2002-2003 Dodji Seketeli <dodji@seketeli.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms
+ * of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the
+ * GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <string.h>
+#include "libcroco.h"
+#include "cr-test-utils.h"
+
+const guchar *gv_cssbuf =
+ (const guchar *) ".exp1n1 {stroke-width:4E6}"
+ ".exp1n2 {stroke-width:4e6}"
+ ".exp1n3 {stroke-width:4e+6}"
+ ".exp2n1 {stroke-width:4E-6}"
+ ".exp2n2 {stroke-width:4e-6}"
+ ".exp3n1 {stroke-width:4e6em}"
+ ".exp3n2 {stroke-width:4e6ex}"
+ ".exp3n3 {stroke-width:4e6in}"
+ ".exp4n1 {stroke-width:3.14e4}"
+ ".exp4n2 {stroke-width:3.14e-4}"
+ ".e4n2 {stroke-width:.24e-4}"
+ ".e4n3 {stroke-width:1.e1}"; // This one should be ignored
+
+static enum CRStatus
+ test_cr_parser_parse (void);
+
+/**
+ *The test of the cr_input_read_byte() method.
+ *Reads the each byte of a_file_uri using the
+ *cr_input_read_byte() method. Each byte is send to
+ *stdout.
+ *@param a_file_uri the file to read.
+ *@return CR_OK upon successful completion of the
+ *function, an error code otherwise.
+ */
+static enum CRStatus
+test_cr_parser_parse (void)
+{
+ enum CRStatus status = CR_OK;
+ CROMParser *parser = NULL;
+ CRStyleSheet *stylesheet = NULL;
+
+ parser = cr_om_parser_new (NULL);
+ status = cr_om_parser_parse_buf (parser, (guchar *) gv_cssbuf,
+ strlen ((const char *) gv_cssbuf),
+ CR_ASCII, &stylesheet);
+
+ if (status == CR_OK && stylesheet) {
+ cr_stylesheet_dump (stylesheet, stdout);
+ // Adding this because my test editor adds a newline character
+ // at the last line, whereas cr_stylesheet_dump doesn't, which
+ // results in a diff error/warning.
+ printf("\n");
+ cr_stylesheet_destroy (stylesheet);
+ }
+ cr_om_parser_destroy (parser);
+
+ return status;
+}
+
+/**
+ *The entry point of the testing routine.
+ */
+int
+main (int argc, char **argv)
+{
+ enum CRStatus status = CR_OK;
+
+ status = test_cr_parser_parse ();
+
+ if (status != CR_OK) {
+ g_print ("\nKO\n");
+ }
+
+ return 0;
+}
diff --git a/src/3rdparty/libcroco/tests/test8-main.c b/src/3rdparty/libcroco/tests/test8-main.c
new file mode 100644
index 0000000..b57c2e4
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/test8-main.c
@@ -0,0 +1,44 @@
+/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset:8 -*- */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * Copyright (C) 2022 Thomas Holder
+ *
+ * SPDX-License-Identifier: GPL-2.1-or-later
+ */
+
+#include "libcroco.h"
+#include <stdio.h>
+
+int
+main (int argc, char **argv)
+{
+ unsigned i = 0;
+ CRSelector *selector;
+
+ char const *selector_strings[] = {
+ // must not have leading whitespace!?
+ "foo", "foo,bar", "foo , bar ", "foo > bar", ".foo .bar",
+ };
+
+ for (i = 0; i < G_N_ELEMENTS (selector_strings); ++i) {
+ printf ("****************\n");
+ printf ("Parsing '%s'\n", selector_strings[i]);
+
+ selector = cr_selector_parse_from_buf (
+ (guchar const *) selector_strings[i], CR_UTF_8);
+
+ if (!selector) {
+ printf ("is NULL\n");
+ } else {
+ cr_selector_dump (selector, stdout);
+ cr_selector_unref (selector);
+ printf ("\n");
+ }
+ }
+
+ return 0;
+}
+
+// vi:sw=8:expandtab
diff --git a/src/3rdparty/libcroco/tests/testctl b/src/3rdparty/libcroco/tests/testctl
new file mode 100755
index 0000000..205112b
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/testctl
@@ -0,0 +1,462 @@
+#! /bin/sh
+
+#####################################
+#This script just runs the tests of
+#libcroco, saves their result, diff them
+#against a set of reference results and
+#displays OK/KO.
+#To use it as a tester, the best way is
+#just to run 'testctl run' and see the result.
+####################################
+
+#the directory that contains the tests sources is:
+#$TEST_SOURCE_DIR. User can set this var in the environment
+#before calling this script. Otherwise, we set it to a default value
+if test x$TEST_SOURCE_DIR = x ; then
+ TEST_SOURCE_DIR=`dirname "$0"`
+fi
+
+#the directory that contains the test outputs is:
+#$TEST_OUT_DIR
+#User can set this var in the environment before
+#calling this script. Otherwise, we set it to a default value.
+if test x$TEST_OUT_DIR = x ; then
+ TEST_OUT_DIR=tests
+fi
+
+if [ -d "$TEST_OUT_DIR/.libs" ]; then
+ TEST_BIN_DIR="$TEST_OUT_DIR/.libs"
+else
+ TEST_BIN_DIR="$TEST_OUT_DIR"
+fi
+
+#the list of tests to be run
+TEST_PROG_LIST=
+
+#the test input dirs.
+TEST_INPUT_DIR=test-inputs
+
+#the reference test output dirs.
+TEST_OUT_REF_DIR=test-output-refs
+
+#temporary test result dir
+TEST_OUTPUT_DIR=test-outputs
+
+ERROR_REPORT_FILE=tests-error.log
+COMMAND_LIST=
+COMMAND=
+if test x$RUN_VALGRIND = x ; then
+ RUN_VALGRIND=no
+else
+ RUN_VALGRIND=yes
+fi
+if test "x$CHECKER" = "x" ; then
+ CHECKER="valgrind --tool=memcheck"
+fi
+
+VALGRIND_LOGS_DIR=valgrind-logs
+VALGRIND=
+TEST_PROG=
+EGREP="grep -E"
+
+DIFF=`which diff`
+if test "empty$DIFF" = "empty" ; then
+ echo "You don't have the diff program installed"
+ echo "Please, install is first"
+fi
+
+display_usage ()
+{
+ echo ""
+ echo "usage: $0 [general options] <command> [command option]"
+ echo ""
+ echo "where general options are:"
+ echo "===================="
+ echo "-h|--help displays this help"
+ echo ""
+ echo "commands are:"
+ echo "=============="
+ echo "run run the tests and display their result"
+ echo "ref run the tests but saves their output as a reference"
+ echo "cleanup removes the tmp directories that may have been created"
+ echo ""
+ echo "run command options:"
+ echo "--valgrind runs the test using valgrind"
+ echo "--testprog <test program>"
+}
+
+parse_command_line ()
+{
+ if test "empty$1" = "empty" ; then
+ display_usage ;
+ exit -1
+ fi
+
+ while true ; do
+ arg=$1
+
+ if test "empty$arg" = "empty" ; then
+ break ;
+ fi
+
+ case "$arg" in
+ -h|--help)
+ display_usage $@
+ exit 0
+ ;;
+
+ -*)
+ echo "$0: unknown option: $arg"
+ display_usage $@
+ exit 0
+ ;;
+
+ run|ref|cleanup)
+ COMMAND_LIST=$arg
+ REMAINING_ARGS=$@
+ echo "REMAINING_ARGS=$REMAINING_ARGS"
+ break ;
+ ;;
+
+ *)
+ display_usage $@
+ exit 0
+ ;;
+ esac
+ done
+}
+
+
+#builds the list of available test functions.
+build_tests_list ()
+{
+ for TEST_PROG in "$TEST_SOURCE_DIR"/test*.sh "$TEST_OUT_DIR"/test?; do
+ TEST_PROG=`basename $TEST_PROG`
+ echo "run test: $TEST_PROG"
+ TEST_PROG_LIST="$TEST_PROG_LIST $TEST_PROG"
+ done
+}
+
+#runs a test programs.
+#usage run_test_prog <test-name> <reference> <display-on-stdout>
+#where "test-name" is the name of the test program to run
+#"reference" is a boolean value: yes/no. (the string "yes" or the string no)
+#if yes, means that the output of the test is to be saved as a reference.
+#if no, means that the output of the test is to be saved as a result of a test.
+run_test_prog ()
+{
+ TEST_PROG="$1"
+ REFERENCE="$2"
+ DISPLAY_ON_STDOUT="$3"
+ OUTPUT_DIR=
+ OUTPUT_SUFFIX=
+ TEST_INPUT_LIST=
+ VALGRIND_OPTIONS="--error-limit=no --num-callers=100 --logfile=$TEST_OUT_DIR/$VALGRIND_LOGS_DIR/$TEST_PROG-valgrind.log --leak-check=yes --show-reachable=yes --quiet --suppressions=$TEST_SOURCE_DIR/vg.supp"
+ if test x$RUN_VALGRIND = xno ; then
+ VALGRIND=
+ else
+ if ! test -x "$TEST_SOURCE_DIR"/valgrind-version.sh ; then
+ echo "Argh! Could not find file $TEST_SOURCE_DIR/valgrind-version.sh"
+ exit -1 ;
+ fi
+ version=`"$TEST_SOURCE_DIR"/valgrind-version.sh`
+ if ! test "x$version" = "xokay" ; then
+ echo "You must install a valgrind version greater than 2.1.1"
+ echo "version=$version"
+ exit -1
+ fi
+ if test "x$CHECKER" = "x" ; then
+ VALGRIND=`which valgrind`
+ if test "x$VALGRIND" = x ; then
+ echo "Could not find valgrind in your path"
+ else
+ VALGRIND="$VALGRIND $VALGRIND_OPTIONS"
+ echo "Gonna run the tests with valgrind, using the following options: $VALGRIND_OPTIONS"
+ fi
+ else
+ VALGRIND="$CHECKER $VALGRIND_OPTIONS"
+ echo "Gonna run the tests with valgrind, using the cmd line: $VALGRIND"
+ fi
+ fi
+ export VALGRIND
+ case "$TEST_PROG" in
+ *.sh) is_shell_script=yes ;;
+ *) is_shell_script=no ;;
+ esac
+
+ if ! test -d "$TEST_OUT_DIR/$VALGRIND_LOGS_DIR" ; then
+ mkdir "$TEST_OUT_DIR/$VALGRIND_LOGS_DIR"
+ fi
+
+ for TEST_INPUT in `ls -1 "$TEST_SOURCE_DIR/$TEST_INPUT_DIR" | $EGREP "^${TEST_PROG}"'[.0-9]+css$'` ; do
+ TEST_INPUT_LIST="$TEST_INPUT_LIST $TEST_INPUT"
+ done
+
+ if test "$REFERENCE" = "yes" ; then
+ OUTPUT_DIR="$TEST_SOURCE_DIR/$TEST_OUT_REF_DIR"
+ OUTPUT_SUFFIX=.out
+ else
+ OUTPUT_DIR="$TEST_OUT_DIR/$TEST_OUTPUT_DIR"
+ OUTPUT_SUFFIX=.out
+ if test ! -d "$OUTPUT_DIR" ; then
+ echo "creating tmp directory $OUTPUT_DIR ..."
+ mkdir "$OUTPUT_DIR"
+ echo "done"
+ fi
+ fi
+
+ if test "empty$TEST_INPUT_LIST" != "empty" ; then
+ for TEST_INPUT in $TEST_INPUT_LIST ; do
+ TEST_INPUT_NAME=`basename $TEST_INPUT .sh`
+ if test "$DISPLAY_ON_STDOUT" = "yes" ; then
+ echo "###############################################"
+ echo "launching $VALGRIND $TEST_PROG $TEST_SOURCE_DIR/$TEST_INPUT_DIR/$TEST_INPUT"....
+ echo "###############################################"
+ if test x$is_shell_script = xyes ; then
+ "$TEST_SOURCE_DIR/$TEST_PROG" "$TEST_SOURCE_DIR/$TEST_INPUT_DIR/$TEST_INPUT"
+ else
+ $VALGRIND "$TEST_BIN_DIR/$TEST_PROG" "$TEST_SOURCE_DIR/$TEST_INPUT_DIR/$TEST_INPUT"
+ fi
+ echo "###############################################"
+ echo "done"
+ echo "###############################################"
+ echo ""
+ else
+ echo "executing $VALGRIND $TEST_PROG $TEST_SOURCE_DIR/$TEST_INPUT_DIR/$TEST_INPUT > $OUTPUT_DIR/${TEST_INPUT_NAME}${OUTPUT_SUFFIX} ..."
+ $VALGRIND "$TEST_BIN_DIR/$TEST_PROG" "$TEST_SOURCE_DIR/$TEST_INPUT_DIR/$TEST_INPUT" > "$OUTPUT_DIR/${TEST_INPUT_NAME}${OUTPUT_SUFFIX}"
+ echo "done"
+ fi
+ done
+ else
+ if test "$DISPLAY_ON_STDOUT" = "yes" ; then
+ echo "####################################################"
+ echo "launching $VALGRIND $TEST_PROG ..."
+ echo "####################################################"
+ if test x$is_shell_script = xyes ; then
+ "$TEST_SOURCE_DIR/$TEST_PROG"
+ else
+ $VALGRIND "$TEST_BIN_DIR/$TEST_PROG"
+ fi
+ echo "####################################################"
+ echo "done"
+ echo "####################################################"
+ echo ""
+ else
+ TEST_INPUT_NAME=`basename "$TEST_PROG" .sh`
+ echo "executing $VALGRIND $TEST_PROG > $OUTPUT_DIR/${TEST_PROG}${OUTPUT_SUFFIX} ..."
+ if test x$is_shell_script = xyes ; then
+ "$TEST_SOURCE_DIR/$TEST_PROG" > "$OUTPUT_DIR/${TEST_INPUT_NAME}${OUTPUT_SUFFIX}"
+ else
+ $VALGRIND "$TEST_BIN_DIR/$TEST_PROG" > "$OUTPUT_DIR/${TEST_INPUT_NAME}${OUTPUT_SUFFIX}"
+ fi
+ echo "done"
+ fi
+ fi
+ unset VALGRIND
+}
+
+cleanup_tests ()
+{
+ if test -d "$TEST_OUT_DIR/$TEST_OUTPUT_DIR" ; then
+ echo "removing $TEST_OUT_DIR/$TEST_OUTPUT_DIR/*"
+ rm -rf "$TEST_OUT_DIR/$TEST_OUTPUT_DIR"
+ rm -rf "$TEST_OUT_DIR/$VALGRIND_LOGS_DIR"
+ fi
+ if test -f "$TEST_OUT_DIR/$ERROR_REPORT_FILE" ; then
+ rm "$TEST_OUT_DIR/$ERROR_REPORT_FILE"
+ fi
+ return 0
+}
+
+run_test_report ()
+{
+ code=0
+ diff -ur --exclude='*CVS*' --exclude='*cvs*' --exclude='Makefile*' --exclude=.arch-ids "$TEST_SOURCE_DIR/$TEST_OUT_REF_DIR" "$TEST_OUT_DIR/$TEST_OUTPUT_DIR" > "$TEST_OUT_DIR/tmpdiff.$$"
+ NB_DIFF=`wc -l < "$TEST_OUT_DIR/tmpdiff.$$"`
+
+ if test "$NB_DIFF" -eq 0 ; then
+ echo "/////////////ALL THE TESTS ARE OK :) //////////////////"
+ rm "$TEST_OUT_DIR/tmpdiff.$$"
+ else
+ echo "SOME TESTS ARE KO :("
+ mv "$TEST_OUT_DIR/tmpdiff.$$" "$TEST_OUT_DIR/$ERROR_REPORT_FILE"
+ echo "See $TEST_OUT_DIR/$ERROR_REPORT_FILE to see what's going on"
+ code=1
+ fi
+
+ ###################
+ #Valgrind errors #
+ ###################
+ memleaks=no
+ for vg_log in `find "$TEST_OUT_DIR/$VALGRIND_LOGS_DIR" -name '*-valgrind.log*' -print` ; do
+ if test -s "$vg_log" ; then
+ leaks=`cat "$vg_log" | grep -i leak | grep -v no`
+ errors=`cat "$vg_log" | grep -w Invalid`
+ if test "x$leaks" = "x" -a "x$errors" = "x" ; then
+ rm -f "$vg_log" ;
+ else
+ echo "valgrind reported some memory leaks/corruptions in $vg_log"
+ memleaks=yes
+ fi
+ else
+ rm "$vg_log"
+ fi
+ done
+ if test "x$RUN_VALGRIND" = "xyes" ; then
+ if test "x$memleaks" = "xno" ; then
+ echo "Oh, YESSSSSS!, VALGRIND DID NOT DETECT ANY MEMLEAK !! You can go have a beer."
+ else
+ echo "Please report these leaks by sending the valgrind logs to the authors of libcroco."
+ code=2
+ fi
+ fi
+ return $code
+}
+
+run_test_report_single ()
+{
+ TEST_BASE=`basename "$1" .sh`
+ code=0
+ for reffile in "$TEST_SOURCE_DIR/$TEST_OUT_REF_DIR/$TEST_BASE".*; do
+ outfile="$TEST_OUT_DIR/$TEST_OUTPUT_DIR/`basename "$reffile"`"
+ diff -u "$reffile" "$outfile" || code=1
+ done
+ if [ $code -ne 0 ]; then
+ echo "TEST $TEST_BASE IS KO :("
+ fi
+ return $code
+}
+
+############################
+#Executes the "run" command along with
+#its command options.
+#For the sake of safety checking
+############################
+execute_run_cmd ()
+{
+ args=$@
+ test_and_report=no
+
+ if test "$1" != "run" ; then
+ echo "internal error: first argument should be \'run\'"
+ return
+ fi
+ shift
+
+ while true ; do
+ cur_arg=$1
+ echo "cur_arg=$cur_arg"
+
+ case $cur_arg in
+ --valgrind)
+ RUN_VALGRIND=yes
+ shift
+ ;;
+
+ "--testprog")
+ shift
+ if test "empty$1" = "empty" ; then
+ echo "--testprog should be followed by a prog name"
+ display_usage
+ exit
+ fi
+ TEST_PROG=$1
+ echo "TEST_PROG=$TEST_PROG"
+ shift
+ ;;
+
+ "--test-and-report")
+ test_and_report=yes
+ shift
+ TEST_PROG="$1"
+ shift
+ if test -z "$TEST_PROG"; then
+ echo "--test-and-report must be followed by a prog name"
+ exit
+ fi
+ ;;
+
+ *)
+ break
+ ;;
+ esac
+ done
+
+ if test "empty$TEST_PROG" = "empty"; then
+
+ cleanup_tests
+
+ build_tests_list ;
+ if test "empty$TEST_PROG_LIST" = "empty" ; then
+ echo "could not find any test to run"
+ exit
+ fi
+
+ for TEST in $TEST_PROG_LIST ; do
+ run_test_prog "$TEST" no no;
+ done
+ run_test_report ;
+ elif test "$test_and_report" = "yes"; then
+ run_test_prog "$TEST_PROG"
+ run_test_report_single "$TEST_PROG"
+ else
+ #run the test and display result on stdout
+ run_test_prog "$TEST_PROG" no yes ;
+ fi
+}
+
+##############################
+#Analyzes a command string "<command> [command option]"
+#and runs the necessary commands.
+#
+#Must be called with the command line
+#starting with a command name.
+#all the previous general argument must
+#have been stripped away.
+#############################
+execute_command ()
+{
+ arg="$1" ;
+
+ case "$arg" in
+
+ run)
+ execute_run_cmd "$@"
+ ;;
+
+ ref)
+ build_tests_list ;
+ if test "empty$TEST_PROG_LIST" = "empty" ; then
+ echo "could not find any test to run"
+ exit
+ fi
+
+ for TEST in $TEST_PROG_LIST ; do
+ run_test_prog "$TEST" yes no;
+ done
+ ;;
+
+ cleanup)
+ cleanup_tests
+ ;;
+
+ *)
+ echo "unknown command"
+ exit ;
+ esac
+
+}
+
+main ()
+{
+ parse_command_line $@
+
+ if test "empty$COMMAND_LIST" = "empty" ; then
+ echo "no test command to execute"
+ exit
+ fi
+
+ execute_command $REMAINING_ARGS
+}
+
+main $@
diff --git a/src/3rdparty/libcroco/tests/valgrind-version.sh b/src/3rdparty/libcroco/tests/valgrind-version.sh
new file mode 100755
index 0000000..55cbfc2
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/valgrind-version.sh
@@ -0,0 +1,48 @@
+#! /bin/sh
+
+valgrind=`which valgrind`
+awk=`which awk`
+if test "x$valgrind" = "x" ; then
+ echo "valgrind-not-present" ;
+ exit ;
+fi
+
+
+valgrind_version=`$valgrind --version`
+if test "x$valgrind_version" = x ; then
+ echo "not-present" ;
+ exit
+fi
+
+if test "x$awk" = x ; then
+ echo "awk-not-present"
+ exit
+fi
+
+string_version=`echo $valgrind_version | $awk -F '-' '{print $2}'`
+
+if test "x$string_version" = "x" ; then
+ echo "valgrind-version-unknown"
+ exit
+fi
+
+major=`echo $string_version | $awk -F '.' '{print $1}'`
+minor=`echo $string_version | $awk -F '.' '{print $2}'`
+micro=`echo $string_version | $awk -F '.' '{print $3}'`
+
+version=`expr $major \* 10000 + $minor \* 100 + $micro`
+
+if test "x$version" = "x" ; then
+ echo "valgrind-version-unknown"
+ exit ;
+fi
+
+if test "$version" -ge "20101" ; then
+ echo "okay"
+ exit ;
+else
+ echo "valgrind-version-lower"
+ exit ;
+fi
+
+
diff --git a/src/3rdparty/libcroco/tests/valgrind.log b/src/3rdparty/libcroco/tests/valgrind.log
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/valgrind.log
diff --git a/src/3rdparty/libcroco/tests/vg b/src/3rdparty/libcroco/tests/vg
new file mode 100755
index 0000000..b1f2c00
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/vg
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+###
+#
+###
+
+OUTPUT_FILE=valgrind.log
+VG=`which valgrind`
+VG_OPTIONS="-q --num-callers=100 --leak-check=yes --show-reachable=yes"
+
+#Some sanity checks
+if test "empty$VG" = "empty" ; then
+ echo "You should install valgrind and set it binary into your"
+ echo "\$PATH env variable"
+ echo "go to http://developer.kde.org/~sewardj/ to download valgrind"
+ exit
+fi
+
+
+if test "empty$1" != "empty" ; then
+ OUTPUT_FILE="$1".vg
+fi
+
+exec $VG $VG_OPTIONS $@ 2>"$OUTPUT_FILE" \ No newline at end of file
diff --git a/src/3rdparty/libcroco/tests/vg.supp b/src/3rdparty/libcroco/tests/vg.supp
new file mode 100644
index 0000000..5a3d109
--- /dev/null
+++ b/src/3rdparty/libcroco/tests/vg.supp
@@ -0,0 +1,57 @@
+{
+ g_print_ALLOC_LEAK
+ Memcheck:Leak
+ fun:malloc
+ fun:realloc
+ fun:g_realloc
+ fun:g_array_maybe_expand
+ fun:g_array_set_size
+ fun:g_static_private_set
+ fun:g_get_charset
+ fun:g_print
+}
+
+{
+ g_slist_prepend_LEAK
+ Memcheck:Leak
+ fun:calloc
+ fun:g_malloc0
+ fun:g_allocator_new
+ fun:_g_slist_alloc
+ fun:g_slist_prepend
+}
+
+{
+ g_print_CONVERT_LEAK
+ Memcheck:Leak
+ fun:malloc
+ obj:*libc-2.3.3.so
+ fun:iconv_open
+ fun:try_conversion
+ fun:g_iconv_open
+ fun:open_converter
+ fun:g_convert
+ fun:g_convert_with_fallback
+ fun:strdup_convert
+ fun:g_print
+}
+
+{
+ g_string_new_CHUNCK_LEAK
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_mem_chunk_new
+ fun:g_string_sized_new
+ fun:g_string_new
+}
+
+{
+ g_list_prepend_LEAK
+ Memcheck:Leak
+ fun:calloc
+ fun:g_malloc0
+ fun:g_allocator_new
+ fun:_g_list_alloc
+ fun:g_list_prepend
+}
diff --git a/src/3rdparty/libcroco/win32/Makefile-newvs.am b/src/3rdparty/libcroco/win32/Makefile-newvs.am
new file mode 100644
index 0000000..3a91862
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/Makefile-newvs.am
@@ -0,0 +1,55 @@
+# Centralized autotools file
+# Create the Visual Studio 2012/2013/2015 project files
+# from the Visual Studio 2010 project files
+
+# This autotools file, from GLib, can be used in other projects
+# that have Visual Studio build support.
+
+# Author: Fan, Chun-wei
+# November 05, 2012
+
+# MSVC_BASE_VER: Baseline MSVC 201x version to copy/process project files from (100 for 2010, 120 for 2013)
+# MSVC_BASE_VER_LONG: Long Version of baseline Visual Studio 201x version (2010, 2012, 2013, 14, 15)
+# MSVC_BASE_TOOLSET: Use if baseline MSVC toolset is not in the form v$(MSVC_BASE_VER)0, meaning v$(MSVC_BASE_TOOLSET)
+# MSVC_VER_LONG: Long Version of target Visual Studio (2012, 2013, 14 and so on)
+# MSVC_VER: Short Version of target Visual Studio (110 for 2012, 120 for 2013, 140 for 2015, 141 for 2017)
+# MSVC_TOOLSET: Use if target MSVC toolsett is not in the form v $(MSVC_VER)0, meaning v$(MSVC_TOOLSET)
+
+if MSVC_BASE_NO_TOOLSET_SET
+MSVC_BASE_TOOLSET = $(MSVC_BASE_VER)0
+endif
+
+if MSVC_NO_TOOLSET_SET
+MSVC_TOOLSET = $(MSVC_VER)0
+endif
+
+%.sln:
+ sed 's/11\.00/12\.00/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp
+ sed 's/$(MSVC_BASE_VER_LONG)/$(MSVC_VER_LONG)/g' < $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp > $(top_builddir)/win32/vs$(MSVC_VER)/$@
+ rm $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp
+
+%.txt:
+ sed 's/vs$(MSVC_BASE_VER)/vs$(MSVC_VER)/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp
+ sed 's/VS$(MSVC_BASE_VER)/VS$(MSVC_VER)/g' < $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp > $(top_builddir)/win32/vs$(MSVC_VER)/$@
+ rm $(top_builddir)/win32/vs$(MSVC_VER)/$@.tmp
+
+%.vcxproj:
+ if test -e $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@; then \
+ sed 's/v$(MSVC_BASE_TOOLSET)/v$(MSVC_TOOLSET)/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \
+ else \
+ sed 's/v$(MSVC_BASE_TOOLSET)/v$(MSVC_TOOLSET)/g' < $(top_builddir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \
+ fi
+
+%.props: $(top_builddir)/win32/vs$(MSVC_BASE_VER)/Makefile
+ if test -e $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@; then \
+ sed 's/<VSVer>$(MSVC_BASE_VER)<\/VSVer>/<VSVer>$(MSVC_VER)<\/VSVer>/g' < $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \
+ else \
+ sed 's/<VSVer>$(MSVC_BASE_VER)<\/VSVer>/<VSVer>$(MSVC_VER)<\/VSVer>/g' < $(top_builddir)/win32/vs$(MSVC_BASE_VER)/$@ > $(top_builddir)/win32/vs$(MSVC_VER)/$@; \
+ fi
+
+%.vcxproj.filters:
+ if test -e $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@; then \
+ cp $(top_srcdir)/win32/vs$(MSVC_BASE_VER)/$@ $(top_builddir)/win32/vs$(MSVC_VER)/$@; \
+ else \
+ cp $(top_builddir)/win32/vs$(MSVC_BASE_VER)/$@ $(top_builddir)/win32/vs$(MSVC_VER)/$@; \
+ fi
diff --git a/src/3rdparty/libcroco/win32/Makefile.am b/src/3rdparty/libcroco/win32/Makefile.am
new file mode 100644
index 0000000..d3cb159
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/Makefile.am
@@ -0,0 +1,22 @@
+#This file is part of The Croco Library
+#This program is free software; you can redistribute it and/or
+#modify it under the terms of version 2.1 of the GNU Lesser General Public
+#License as published by the Free Software Foundation.
+
+#This program is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#GNU General Public License for more details.
+
+#You should have received a copy of the GNU Lesser General Public License
+#along with this program; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+#USA
+
+#Author: Fan, Chun-wei
+#See COPYRIGHTS file for copyright information.
+
+SUBDIRS = vs9 vs10 vs11 vs12 vs14 vs15 vs16
+
+EXTRA_DIST = crocopc.py pc_base.py replace.py
+
diff --git a/src/3rdparty/libcroco/win32/Makefile.msvcproj b/src/3rdparty/libcroco/win32/Makefile.msvcproj
new file mode 100644
index 0000000..5224ba0
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/Makefile.msvcproj
@@ -0,0 +1,153 @@
+# Author: Fan, Chun-wei
+# Common Autotools file used to generate Visual Studio 2008+
+# Projects from their templates
+
+# This autotools file, from GLib, can be used in other projects
+# that have Visual Studio build support.
+
+# * Input variables:
+#
+# MSVCPROJS - List of Projects that should be generated
+#
+# * Simple tutorial
+#
+# Add this to Makefile.am where your library/program is built:
+# include <this Makefile.msvcproj>
+# MSVCPROJS = YourProject (can be multiple projects in a single srcdir)
+# YourProject_FILES = $(libyourlib_1_0_SOURCES)
+# YourProject_EXCLUDES = ... # list of sources to exclude, separated by '|', wildcards allowed; use random unused value if none
+# (the following 3 lines if headers need to be installed)
+# YourProject_HEADERS_DIR = $(libyourlibincludedir)
+# YourProject_HEADERS_INST = $(libyourlib_1_0_HEADERS)
+# YourProject_HEADERS_EXCLUDES = ... # <list of headers to exclude from installation, separated by '|', wildcards allowed; use random unused value if none>
+#
+# dist-hook: \ # (or add to it if it is already there, note the vs9 items will also call the vs10 items in the process)
+# $(top_builddir)/win32/vs9/YourProject.vcproj \
+# $(top_builddir)/win32/vs9/YourProject.headers # if headers need to be installed
+#
+# --or, if Visual Studio 2013 or later is required--
+# dist-hook: \ # (or add to it if it is already there, this does -not- call other vs items in the process)
+# $(top_builddir)/win32/vs12/YourProject.vcxproj \
+# $(top_builddir)/win32/vs12/YourProject.vs12.headers # if headers need to be installed
+
+# Private functions
+
+## Transform the MSVC project filename (no filename extensions) to something which can reference through a variable
+## without automake/make complaining, eg Gtk-2.0 -> Gtk_2_0
+_proj_name=$(subst /,_,$(subst -,_,$(subst .,_,$(1))))
+_proj_path_raw:=$(subst $(abs_top_srcdir),,$(abs_srcdir))
+_proj_path=$(subst /,\\,$(_proj_path_raw))
+_proj_subdir_int=$(subst \\\\,\\,\\$(_proj_path)\\)
+_proj_subdir=$(subst \\.\\,\\,$(_proj_subdir_int))
+
+_proj_files_raw=$(subst /,\\,$($(_proj_name)_FILES))
+_proj_files=$(subst $(srcdir)\\,,$(subst $(builddir)\\,,$(subst $(top_builddir)\\$(_proj_path)\\,\\,$(_proj_files_raw))))
+_proj_filters=$($(_proj_name)_EXCLUDES)
+
+_proj_headers_raw=$(subst /,\\,$($(_proj_name)_HEADERS_INST))
+_proj_headers=$(subst $(srcdir)\\,,$(subst $(builddir)\\,,$(subst $(top_builddir)\\$(_proj_path)\\,\\,$(_proj_headers_raw))))
+_proj_headers_excludes=$($(_proj_name)_HEADERS_EXCLUDES)
+
+_headers_dest_posix=$(subst $(includedir),,$($(_proj_name)_HEADERS_DIR))
+_headers_destdir=$(subst /,\\,$(_headers_dest_posix))
+
+#
+# Creates Visual Studio 2008/2010 projects from items passed in from autotools files
+# $(1) - Base Name of the MSVC project files (outputs)
+#
+
+define msvcproj-builder
+
+$(top_builddir)/win32/vs10/$(1).vcxproj: $(top_builddir)/win32/vs9/$(1).vcproj
+$(top_builddir)/win32/vs10/$(1).vcxproj.filters: $(top_builddir)/win32/vs9/$(1).vcproj
+$(1).sourcefiles: $(top_builddir)/win32/vs9/$(1).vcproj
+$(1).vs10.sourcefiles: $(top_builddir)/win32/vs9/$(1).vcproj
+$(1).vs10.sourcefiles.filters: $(top_builddir)/win32/vs9/$(1).vcproj
+
+$(top_builddir)/win32/vs9/$(1).vcproj: Makefile
+ -$(RM) $(top_builddir)/win32/vs9/$(1).vcproj
+ -$(RM) $(top_builddir)/win32/vs10/$(1).vcxproj
+ -$(RM) $(top_builddir)/win32/vs10/$(1).vcxproj.filters
+ -$(RM) $(top_builddir)/win32/vs11/$(1).vcxproj
+ -$(RM) $(top_builddir)/win32/vs11/$(1).vcxproj.filters
+ -$(RM) $(top_builddir)/win32/vs12/$(1).vcxproj
+ -$(RM) $(top_builddir)/win32/vs12/$(1).vcxproj.filters
+ -$(RM) $(top_builddir)/win32/vs14/$(1).vcxproj
+ -$(RM) $(top_builddir)/win32/vs14/$(1).vcxproj.filters
+
+
+ for F in $(_proj_files); do \
+ case $$$$F in \
+ $(_proj_filters)) \
+ ;; \
+ *.c|*.cpp|*.cc|*.cxx) \
+ echo ' <File RelativePath="..\..'$(_proj_subdir)$$$$F'" />' >>$(1).sourcefiles && \
+ echo ' <ClCompile Include="..\..'$(_proj_subdir)$$$$F'" />' >>$(1).vs10.sourcefiles && \
+ echo ' <ClCompile Include="..\..'$(_proj_subdir)$$$$F'"><Filter>Source Files</Filter></ClCompile>' >>$(1).vs10.sourcefiles.filters \
+ ;; \
+ esac; \
+ done
+
+
+ $(CPP) -P - <$(top_srcdir)/win32/vs9/$(1).vcprojin >$(top_builddir)/win32/vs9/$(1).vcproj
+ $(CPP) -P - <$(top_srcdir)/win32/vs10/$(1).vcxprojin >$(top_builddir)/win32/vs10/$(1).vcxproj
+ $(CPP) -P - <$(top_srcdir)/win32/vs10/$(1).vcxproj.filtersin >$(top_builddir)/win32/vs10/$(1).vcxproj.filters
+ $(RM) $(1).sourcefiles
+ $(RM) $(1).vs10.sourcefiles
+ $(RM) $(1).vs10.sourcefiles.filters
+
+$(top_builddir)/win32/vs10/$(1).vs10.headers: $(top_builddir)/win32/vs9/$(1).headers
+
+$(top_builddir)/win32/vs9/$(1).headers: Makefile
+ -$(RM) $(top_builddir)/win32/vs9/$(1).headers
+ -$(RM) $(top_builddir)/win32/vs10/$(1).vs10.headers
+
+ for F in $(_proj_headers); do \
+ case $$$$F in \
+ $(_proj_headers_excludes)) \
+ ;; \
+ *.h|*.hpp|*.hh|*.hxx) \
+ echo 'copy ..\..'$(_proj_subdir)$$$$F' $$$$(CopyDir)\include'$(_headers_destdir)'\'$$$$F'&#x0D;&#x0A;' >>$(top_builddir)/win32/vs9/$(1).headers && \
+ echo 'copy ..\..'$(_proj_subdir)$$$$F' $$$$(CopyDir)\include'$(_headers_destdir)'\'$$$$F >>$(top_builddir)/win32/vs10/$(1).vs10.headers \
+ ;; \
+ esac; \
+ done
+
+$(top_builddir)/win32/vs12/$(1).vcxproj.filters: $(top_builddir)/win32/vs12/$(1).vcxproj
+
+$(top_builddir)/win32/vs12/$(1).vcxproj: Makefile
+ -$(RM) $(top_builddir)/win32/vs14/$(1).vcxproj
+ -$(RM) $(top_builddir)/win32/vs14/$(1).vcxproj.filters
+
+ for F in $(_proj_files); do \
+ case $$$$F in \
+ $(_proj_filters)) \
+ ;; \
+ *.c|*.cpp|*.cc|*.cxx) \
+ echo ' <ClCompile Include="..\..'$(_proj_subdir)$$$$F'" />' >>$(1).vs12.sourcefiles && \
+ echo ' <ClCompile Include="..\..'$(_proj_subdir)$$$$F'"><Filter>Source Files</Filter></ClCompile>' >>$(1).vs12.sourcefiles.filters \
+ ;; \
+ esac; \
+ done
+
+ $(CPP) -P - <$(top_srcdir)/win32/vs12/$(1).vcxprojin >$(top_builddir)/win32/vs12/$(1).vcxproj
+ $(CPP) -P - <$(top_srcdir)/win32/vs12/$(1).vcxproj.filtersin >$(top_builddir)/win32/vs12/$(1).vcxproj.filters
+ $(RM) $(1).vs12.sourcefiles
+ $(RM) $(1).vs12.sourcefiles.filters
+
+$(top_builddir)/win32/vs12/$(1).vs12.headers: Makefile
+ -$(RM) $(top_builddir)/win32/vs12/$(1).vs12.headers
+
+ for F in $(_proj_headers); do \
+ case $$$$F in \
+ $(_proj_headers_excludes)) \
+ ;; \
+ *.h|*.hpp|*.hh|*.hxx) \
+ echo 'copy ..\..'$(_proj_subdir)$$$$F' $$$$(CopyDir)\include'$(_headers_destdir)'\'$$$$F >>$(top_builddir)/win32/vs12/$(1).vs12.headers \
+ ;; \
+ esac; \
+ done
+
+endef
+
+$(foreach proj,$(MSVCPROJS),$(eval $(call msvcproj-builder,$(proj))))
diff --git a/src/3rdparty/libcroco/win32/crocopc.py b/src/3rdparty/libcroco/win32/crocopc.py
new file mode 100644
index 0000000..9263ac4
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/crocopc.py
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+#
+# Utility script to generate .pc files for GLib
+# for Visual Studio builds, to be used for
+# building introspection files
+
+# Author: Fan, Chun-wei
+# Date: March 10, 2016
+
+import os
+import sys
+
+from replace import replace_multi
+from pc_base import BasePCItems
+
+def main(argv):
+ base_pc = BasePCItems()
+
+ base_pc.setup(argv)
+ croco_version = base_pc.version.split('.')
+ pkg_replace_items = {'@LIBCROCO_MAJOR_VERSION@': croco_version[0],
+ '@LIBCROCO_MINOR_VERSION@': croco_version[1]}
+
+ pkg_replace_items.update(base_pc.base_replace_items)
+
+ # Generate libcroco-x.y.pc
+ replace_multi(base_pc.top_srcdir + '/libcroco.pc.in',
+ base_pc.srcdir + '/libcroco-' + croco_version[0] +
+ '.' + croco_version[1] + '.pc',
+ pkg_replace_items)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/src/3rdparty/libcroco/win32/pc_base.py b/src/3rdparty/libcroco/win32/pc_base.py
new file mode 100644
index 0000000..f7976e8
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/pc_base.py
@@ -0,0 +1,124 @@
+#!/usr/bin/python
+#
+# Simple utility script to generate the basic info
+# needed in a .pc (pkg-config) file, used especially
+# for introspection purposes
+
+# This can be used in various projects where
+# there is the need to generate .pc files,
+# and is copied from GLib's $(srcroot)/win32
+
+# Author: Fan, Chun-wei
+# Date: March 10, 2016
+
+import os
+import sys
+import argparse
+
+class BasePCItems:
+ def __init__(self):
+ self.base_replace_items = {}
+ self.exec_prefix = ''
+ self.includedir = ''
+ self.libdir = ''
+ self.prefix = ''
+ self.srcdir = os.path.dirname(__file__)
+ self.top_srcdir = self.srcdir + '\\..'
+ self.version = ''
+
+ def setup(self, argv, parser=None):
+ if parser is None:
+ parser = argparse.ArgumentParser(description='Setup basic .pc file info')
+ parser.add_argument('--prefix', help='prefix of the installed library',
+ required=True)
+ parser.add_argument('--exec-prefix',
+ help='prefix of the installed programs, \
+ if different from the prefix')
+ parser.add_argument('--includedir',
+ help='includedir of the installed library, \
+ if different from ${prefix}/include')
+ parser.add_argument('--libdir',
+ help='libdir of the installed library, \
+ if different from ${prefix}/lib')
+ parser.add_argument('--version', help='Version of the package',
+ required=True)
+ args = parser.parse_args()
+
+ self.version = args.version
+
+ # check whether the prefix and exec_prefix are valid
+ if not os.path.exists(args.prefix):
+ raise SystemExit('Specified prefix \'%s\' is invalid' % args.prefix)
+
+ # use absolute paths for prefix
+ self.prefix = os.path.abspath(args.prefix).replace('\\','/')
+
+ # check and setup the exec_prefix
+ if getattr(args, 'exec_prefix', None) is None:
+ exec_prefix_use_shorthand = True
+ self.exec_prefix = '${prefix}'
+ else:
+ if args.exec_prefix.startswith('${prefix}'):
+ exec_prefix_use_shorthand = True
+ input_exec_prefix = args.prefix + args.exec_prefix[len('${prefix}'):]
+ else:
+ exec_prefix_use_shorthand = False
+ input_exec_prefix = args.exec_prefix
+ if not os.path.exists(input_exec_prefix):
+ raise SystemExit('Specified exec_prefix \'%s\' is invalid' %
+ args.exec_prefix)
+ if exec_prefix_use_shorthand is True:
+ self.exec_prefix = args.exec_prefix.replace('\\','/')
+ else:
+ self.exec_prefix = os.path.abspath(input_exec_prefix).replace('\\','/')
+
+ # check and setup the includedir
+ if getattr(args, 'includedir', None) is None:
+ self.includedir = '${prefix}/include'
+ else:
+ if args.includedir.startswith('${prefix}'):
+ includedir_use_shorthand = True
+ input_includedir = args.prefix + args.includedir[len('${prefix}'):]
+ else:
+ if args.includedir.startswith('${exec_prefix}'):
+ includedir_use_shorthand = True
+ input_includedir = input_exec_prefix + args.includedir[len('${exec_prefix}'):]
+ else:
+ includedir_use_shorthand = False
+ input_includedir = args.includedir
+ if not os.path.exists(input_includedir):
+ raise SystemExit('Specified includedir \'%s\' is invalid' %
+ args.includedir)
+ if includedir_use_shorthand is True:
+ self.includedir = args.includedir.replace('\\','/')
+ else:
+ self.includedir = os.path.abspath(input_includedir).replace('\\','/')
+
+ # check and setup the libdir
+ if getattr(args, 'libdir', None) is None:
+ self.libdir = '${prefix}/lib'
+ else:
+ if args.libdir.startswith('${prefix}'):
+ libdir_use_shorthand = True
+ input_libdir = args.prefix + args.libdir[len('${prefix}'):]
+ else:
+ if args.libdir.startswith('${exec_prefix}'):
+ libdir_use_shorthand = True
+ input_libdir = input_exec_prefix + args.libdir[len('${exec_prefix}'):]
+ else:
+ libdir_use_shorthand = False
+ input_libdir = args.libdir
+ if not os.path.exists(input_libdir):
+ raise SystemExit('Specified libdir \'%s\' is invalid' %
+ args.libdir)
+ if libdir_use_shorthand is True:
+ self.libdir = args.libdir.replace('\\','/')
+ else:
+ self.libdir = os.path.abspath(input_libdir).replace('\\','/')
+
+ # setup dictionary for replacing items in *.pc.in
+ self.base_replace_items.update({'@VERSION@': self.version})
+ self.base_replace_items.update({'@prefix@': self.prefix})
+ self.base_replace_items.update({'@exec_prefix@': self.exec_prefix})
+ self.base_replace_items.update({'@libdir@': self.libdir})
+ self.base_replace_items.update({'@includedir@': self.includedir})
diff --git a/src/3rdparty/libcroco/win32/replace.py b/src/3rdparty/libcroco/win32/replace.py
new file mode 100644
index 0000000..3aeceb1
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/replace.py
@@ -0,0 +1,115 @@
+#!/usr/bin/python
+#
+# Simple utility script to manipulate
+# certain types of strings in a file
+
+# This can be used in various projects where
+# there is the need to replace strings in files,
+# and is copied from GLib's $(srcroot)/win32
+
+# Author: Fan, Chun-wei
+# Date: September 03, 2014
+
+import os
+import sys
+import re
+import string
+import argparse
+
+valid_actions = ['remove-prefix',
+ 'replace-var',
+ 'replace-str',
+ 'remove-str']
+
+def open_file(filename, mode):
+ if sys.version_info[0] < 3:
+ return open(filename, mode=mode)
+ else:
+ return open(filename, mode=mode, encoding='utf-8')
+
+def replace_multi(src, dest, replace_items):
+ with open_file(src, 'r') as s:
+ with open_file(dest, 'w') as d:
+ for line in s:
+ replace_dict = dict((re.escape(key), value) \
+ for key, value in replace_items.items())
+ replace_pattern = re.compile("|".join(replace_dict.keys()))
+ d.write(replace_pattern.sub(lambda m: \
+ replace_dict[re.escape(m.group(0))], line))
+
+def replace(src, dest, instring, outstring):
+ replace_item = {instring: outstring}
+ replace_multi(src, dest, replace_item)
+
+def check_required_args(args, params):
+ for param in params:
+ if getattr(args, param, None) is None:
+ raise SystemExit('%s: error: --%s argument is required' % (__file__, param))
+
+def warn_ignored_args(args, params):
+ for param in params:
+ if getattr(args, param, None) is not None:
+ print('%s: warning: --%s argument is ignored' % (__file__, param))
+
+def main(argv):
+
+ parser = argparse.ArgumentParser(description='Process strings in a file.')
+ parser.add_argument('-a',
+ '--action',
+ help='Action to carry out. Can be one of:\n'
+ 'remove-prefix\n'
+ 'replace-var\n'
+ 'replace-str\n'
+ 'remove-str',
+ choices=valid_actions)
+ parser.add_argument('-i', '--input', help='Input file')
+ parser.add_argument('-o', '--output', help='Output file')
+ parser.add_argument('--instring', help='String to replace or remove')
+ parser.add_argument('--var', help='Autotools variable name to replace')
+ parser.add_argument('--outstring',
+ help='New String to replace specified string or variable')
+ parser.add_argument('--removeprefix', help='Prefix of string to remove')
+
+ args = parser.parse_args()
+
+ input_string = ''
+ output_string = ''
+
+ # We must have action, input, output for all operations
+ check_required_args(args, ['action','input','output'])
+
+ # Build the arguments by the operation that is to be done,
+ # to be fed into replace()
+
+ # Get rid of prefixes from a string
+ if args.action == 'remove-prefix':
+ check_required_args(args, ['instring','removeprefix'])
+ warn_ignored_args(args, ['outstring','var'])
+ input_string = args.removeprefix + args.instring
+ output_string = args.instring
+
+ # Replace an m4-style variable (those surrounded by @...@)
+ if args.action == 'replace-var':
+ check_required_args(args, ['var','outstring'])
+ warn_ignored_args(args, ['instring','removeprefix'])
+ input_string = '@' + args.var + '@'
+ output_string = args.outstring
+
+ # Replace a string
+ if args.action == 'replace-str':
+ check_required_args(args, ['instring','outstring'])
+ warn_ignored_args(args, ['var','removeprefix'])
+ input_string = args.instring
+ output_string = args.outstring
+
+ # Remove a string
+ if args.action == 'remove-str':
+ check_required_args(args, ['instring'])
+ warn_ignored_args(args, ['var','outstring','removeprefix'])
+ input_string = args.instring
+ output_string = ''
+
+ replace(args.input, args.output, input_string, output_string)
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/src/3rdparty/libcroco/win32/vs10/Makefile.am b/src/3rdparty/libcroco/win32/vs10/Makefile.am
new file mode 100644
index 0000000..fcdd2f8
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/Makefile.am
@@ -0,0 +1,48 @@
+#This file is part of The Croco Library
+#This program is free software; you can redistribute it and/or
+#modify it under the terms of version 2.1 of the GNU Lesser General Public
+#License as published by the Free Software Foundation.
+
+#This program is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#GNU General Public License for more details.
+
+#You should have received a copy of the GNU Lesser General Public License
+#along with this program; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+#USA
+
+#Author: Fan, Chun-wei
+#See COPYRIGHTS file for copyright information.
+
+GENERATED_ITEMS = \
+ croco.vcxproj \
+ croco.vcxproj.filters \
+ croco-install.props \
+ croco-version-paths.props
+
+EXTRA_DIST = \
+ croco.vcxprojin \
+ croco.vcxproj.filtersin \
+ csslint.vcxproj \
+ csslint.vcxproj.filters \
+ croco-install.vcxproj \
+ croco-install.vcxproj.filters \
+ libcroco.sln \
+ croco-build-defines.props \
+ croco-gen-srcs.props \
+ croco-install.propsin \
+ croco-version-paths.props.in \
+ $(GENERATED_ITEMS)
+
+croco-install.props: $(top_srcdir)/win32/vs10/croco-install.propsin croco.vs10.headers
+ -$(RM) $(top_builddir)/win32/vs11/croco-install.props
+ -$(RM) $(top_builddir)/win32/vs12/croco-install.props
+ -$(RM) $(top_builddir)/win32/vs14/croco-install.props
+ -$(RM) $(top_builddir)/win32/vs15/croco-install.props
+ $(CPP) -P - <$(top_srcdir)/win32/vs10/croco-install.propsin > $@
+ rm croco.vs10.headers
+
+DISTCLEANFILES = $(GENERATED_ITEMS)
+
diff --git a/src/3rdparty/libcroco/win32/vs10/croco-build-defines.props b/src/3rdparty/libcroco/win32/vs10/croco-build-defines.props
new file mode 100644
index 0000000..f02e467
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/croco-build-defines.props
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ImportGroup Label="PropertySheets">
+ <Import Project="croco-version-paths.props" />
+ </ImportGroup>
+ <PropertyGroup>
+ <_PropertySheetDisplayName>crocobuilddefinesprops</_PropertySheetDisplayName>
+ <OutDir>$(SolutionDir)$(Configuration)\$(PlatformName)\bin\</OutDir>
+ <IntDir>$(SolutionDir)$(Configuration)\$(PlatformName)\obj\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\..\src;..\..;$(GlibEtcInstallRoot)\include\glib-2.0;$(GlibEtcInstallRoot)\lib\glib-2.0\include;$(GlibEtcInstallRoot)\include\libxml2;$(GlibEtcInstallRoot)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>HAVE_CONFIG_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ForcedIncludeFiles>msvc_recommended_pragmas.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <AdditionalOptions>/d2Zi+ %(AdditionalOptions)</AdditionalOptions>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>libxml2.lib;glib-2.0.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(GlibEtcInstallRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions Condition="'$(VisualStudioVersion)|$(Platform)'=='11.0|x64'">/HIGHENTROPYVA %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalOptions Condition="'$(VisualStudioVersion)|$(Platform)'=='12.0|x64'">/HIGHENTROPYVA %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalOptions Condition="'$(VisualStudioVersion)|$(Platform)'=='14.0|x64'">/HIGHENTROPYVA %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalOptions Condition="'$(VisualStudioVersion)|$(Platform)'=='15.0|x64'">/HIGHENTROPYVA %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalOptions Condition="'$(VisualStudioVersion)|$(Platform)'=='16.0|x64'">/HIGHENTROPYVA %(AdditionalOptions)</AdditionalOptions>
+ </Link>
+ </ItemDefinitionGroup>
+</Project>
diff --git a/src/3rdparty/libcroco/win32/vs10/croco-gen-srcs.props b/src/3rdparty/libcroco/win32/vs10/croco-gen-srcs.props
new file mode 100644
index 0000000..83f7d30
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/croco-gen-srcs.props
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ImportGroup Label="PropertySheets">
+ <Import Project="croco-build-defines.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros">
+ <CopyConfigH>copy ..\..\config.h.win32 ..\..\config.h</CopyConfigH>
+ <GenerateLibCrocoDef>
+echo EXPORTS &gt; $(DefDir)libcroco.def
+
+cl /EP ..\..\src\libcroco.symbols &gt;&gt; $(DefDir)libcroco.def
+ </GenerateLibCrocoDef>
+ </PropertyGroup>
+ <PropertyGroup>
+ <_PropertySheetDisplayName>crocogensrcsprops</_PropertySheetDisplayName>
+ </PropertyGroup>
+ <ItemGroup>
+ <BuildMacro Include="CopyConfigH">
+ <Value>$(CopyConfigH)</Value>
+ </BuildMacro>
+ <BuildMacro Include="GenerateLibCrocoDef">
+ <Value>$(GenerateLibCrocoDef)</Value>
+ </BuildMacro>
+ </ItemGroup>
+</Project>
diff --git a/src/3rdparty/libcroco/win32/vs10/croco-install.propsin b/src/3rdparty/libcroco/win32/vs10/croco-install.propsin
new file mode 100644
index 0000000..ccce87e
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/croco-install.propsin
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ImportGroup Label="PropertySheets">
+ <Import Project="croco-build-defines.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros">
+ <BinDir>$(SolutionDir)$(Configuration)\$(Platform)\bin</BinDir>
+ <LibCrocoDoInstall>
+mkdir $(CopyDir)
+mkdir $(CopyDir)\bin
+copy $(BinDir)\$(LibCrocoDllPrefix)croco$(LibCrocoDllSuffix).dll $(CopyDir)\bin
+copy $(BinDir)\$(LibCrocoDllPrefix)croco$(LibCrocoDllSuffix).pdb $(CopyDir)\bin
+copy $(BinDir)\csslint.exe $(CopyDir)\bin
+copy $(BinDir)\csslint.pdb $(CopyDir)\bin
+
+mkdir $(CopyDir)\include\libcroco-$(ApiVersion)\libcroco
+#include "croco.vs10.headers"
+
+mkdir $(CopyDir)\lib\pkgconfig
+copy $(BinDir)\croco-$(ApiVersion).lib $(CopyDir)\lib
+copy ..\libcroco-$(ApiVersion).pc $(CopyDir)\lib\pkgconfig
+ </LibCrocoDoInstall>
+ <LibcrocoPCFiles>..\libcroco-$(ApiVersion).pc</LibcrocoPCFiles>
+ <LibcrocoGenPC>(if not exist $(CopyDir) mkdir $(CopyDir)) &amp; (if exist $(PythonPath)\python.exe $(PythonPath)\python.exe ..\crocopc.py --prefix=$(CopyDir) --version=$(CrocoMajorVersion).$(CrocoMinorVersion).$(CrocoMicroVersion))</LibcrocoGenPC>
+ </PropertyGroup>
+ <PropertyGroup>
+ <_PropertySheetDisplayName>crocoinstallprops</_PropertySheetDisplayName>
+ </PropertyGroup>
+ <ItemGroup>
+ <BuildMacro Include="BinDir">
+ <Value>$(BinDir)</Value>
+ </BuildMacro>
+ <BuildMacro Include="LibCrocoDoInstall">
+ <Value>$(LibCrocoDoInstall)</Value>
+ </BuildMacro>
+ <BuildMacro Include="LibcrocoPCFiles">
+ <Value>$(LibcrocoPCFiles)</Value>
+ </BuildMacro>
+ <BuildMacro Include="LibcrocoGenPC">
+ <Value>$(LibcrocoGenPC)</Value>
+ </BuildMacro>
+ </ItemGroup>
+</Project>
diff --git a/src/3rdparty/libcroco/win32/vs10/croco-install.vcxproj b/src/3rdparty/libcroco/win32/vs10/croco-install.vcxproj
new file mode 100644
index 0000000..0cda335
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/croco-install.vcxproj
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{00702787-1566-484D-991F-4E7E459BB909}</ProjectGuid>
+ <RootNamespace>crocoinstall</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-install.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-install.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-install.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-install.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <OutDir Condition="'$(Configuration)'=='Debug'">$(GlibEtcInstallRoot)\</OutDir>
+ <ExtensionsToDeleteOnClean Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <OutDir Condition="'$(Configuration)'=='Release'">$(GlibEtcInstallRoot)\</OutDir>
+ <ExtensionsToDeleteOnClean Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="..\..\libcroco.pc.in">
+ <Message Condition="'$(Configuration)'=='Debug'">Generating .pc files...</Message>
+ <Command Condition="'$(Configuration)'=='Debug'">$(LibcrocoGenPC)</Command>
+ <Outputs Condition="'$(Configuration)'=='Debug'">$(LibcrocoPCFiles);%(Outputs)</Outputs>
+ <Message Condition="'$(Configuration)'=='Release'">Generating .pc files...</Message>
+ <Command Condition="'$(Configuration)'=='Release'">$(LibcrocoGenPC)</Command>
+ <Outputs Condition="'$(Configuration)'=='Release'">$(LibcrocoPCFiles);%(Outputs)</Outputs>
+ </CustomBuild>
+ <CustomBuild Include="..\..\config.h.win32">
+ <Message Condition="'$(Configuration)'=='Debug'">Installing Build Results...</Message>
+ <AdditionalInputs Condition="'$(Configuration)'=='Debug'">$(LibcrocoPCFiles)</AdditionalInputs>
+ <Command Condition="'$(Configuration)'=='Debug'">$(LibCrocoDoInstall)</Command>
+ <Outputs Condition="'$(Configuration)'=='Debug'">blah;%(Outputs)</Outputs>
+ <Message Condition="'$(Configuration)'=='Release'">Installing Build Results...</Message>
+ <AdditionalInputs Condition="'$(Configuration)'=='Release'">$(LibcrocoPCFiles)</AdditionalInputs>
+ <Command Condition="'$(Configuration)'=='Release'">$(LibCrocoDoInstall)</Command>
+ <Outputs Condition="'$(Configuration)'=='Release'">blah;%(Outputs)</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="croco.vcxproj">
+ <Project>{4afe9f9b-7f78-41a8-b066-c7ca89938aba}</Project>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ <ProjectReference Include="csslint.vcxproj">
+ <Project>{345080b1-9c5b-44b8-98d7-7381d50f3e13}</Project>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/src/3rdparty/libcroco/win32/vs10/croco-install.vcxproj.filters b/src/3rdparty/libcroco/win32/vs10/croco-install.vcxproj.filters
new file mode 100644
index 0000000..9386b54
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/croco-install.vcxproj.filters
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="..\..\config.h.win32"><Filter>Resource Files</Filter></CustomBuild>
+ <CustomBuild Include="..\..\libcroco.pc.in"><Filter>Resource Files</Filter></CustomBuild>
+ </ItemGroup>
+</Project>
diff --git a/src/3rdparty/libcroco/win32/vs10/croco-version-paths.props.in b/src/3rdparty/libcroco/win32/vs10/croco-version-paths.props.in
new file mode 100644
index 0000000..eb4000f
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/croco-version-paths.props.in
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup Label="UserMacros">
+ <CrocoMajorVersion>@LIBCROCO_MAJOR_VERSION@</CrocoMajorVersion>
+ <CrocoMinorVersion>@LIBCROCO_MINOR_VERSION@</CrocoMinorVersion>
+ <CrocoMicroVersion>@LIBCROCO_MICRO_VERSION@</CrocoMicroVersion>
+ <ApiVersion>$(CrocoMajorVersion).$(CrocoMinorVersion)</ApiVersion>
+ <VSVer>10</VSVer>
+ <GlibEtcInstallRoot>$(SolutionDir)\..\..\..\vs$(VSVer)\$(Platform)</GlibEtcInstallRoot>
+ <CopyDir>$(GlibEtcInstallRoot)</CopyDir>
+ <DefDir>$(SolutionDir)$(Configuration)\$(PlatformName)\obj\$(ProjectName)\</DefDir>
+ <LibCrocoLibtoolCompatibleDllPrefix>lib</LibCrocoLibtoolCompatibleDllPrefix>
+ <LibCrocoLibtoolCompatibleDllSuffix>-$(ApiVersion)-0</LibCrocoLibtoolCompatibleDllSuffix>
+ <LibCrocoSeparateVSDllPrefix />
+ <LibCrocoSeparateVSDllSuffix>-$(ApiVersion)-vs$(VSVer)</LibCrocoSeparateVSDllSuffix>
+ <LibCrocoDllPrefix>$(LibCrocoSeparateVSDllPrefix)</LibCrocoDllPrefix>
+ <LibCrocoDllSuffix>$(LibCrocoSeparateVSDllSuffix)</LibCrocoDllSuffix>
+ <PythonPath>c:\python34</PythonPath>
+ </PropertyGroup>
+ <PropertyGroup>
+ <_PropertySheetDisplayName>crocoversionpathsprops</_PropertySheetDisplayName>
+ </PropertyGroup>
+ <ItemGroup>
+ <BuildMacro Include="CrocoMajorVersion">
+ <Value>$(CrocoMajorVersion)</Value>
+ </BuildMacro>
+ <BuildMacro Include="CrocoMinorVersion">
+ <Value>$(CrocoMinorVersion)</Value>
+ </BuildMacro>
+ <BuildMacro Include="CrocoMicroVersion">
+ <Value>$(CrocoMicroVersion)</Value>
+ </BuildMacro>
+ <BuildMacro Include="ApiVersion">
+ <Value>$(ApiVersion)</Value>
+ </BuildMacro>
+ <BuildMacro Include="VSVer">
+ <Value>$(VSVer)</Value>
+ </BuildMacro>
+ <BuildMacro Include="GlibEtcInstallRoot">
+ <Value>$(GlibEtcInstallRoot)</Value>
+ </BuildMacro>
+ <BuildMacro Include="CopyDir">
+ <Value>$(CopyDir)</Value>
+ </BuildMacro>
+ <BuildMacro Include="DefDir">
+ <Value>$(DefDir)</Value>
+ </BuildMacro>
+ <BuildMacro Include="LibCrocoLibtoolCompatibleDllPrefix">
+ <Value>$(LibCrocoLibtoolCompatibleDllPrefix)</Value>
+ </BuildMacro>
+ <BuildMacro Include="LibCrocoLibtoolCompatibleDllSuffix">
+ <Value>$(LibCrocoLibtoolCompatibleDllSuffix)</Value>
+ </BuildMacro>
+ <BuildMacro Include="LibCrocoSeparateVSDllPrefix">
+ <Value>$(LibCrocoSeparateVSDllPrefix)</Value>
+ </BuildMacro>
+ <BuildMacro Include="LibCrocoSeparateVSDllSuffix">
+ <Value>$(LibCrocoSeparateVSDllSuffix)</Value>
+ </BuildMacro>
+ <BuildMacro Include="LibCrocoDllPrefix">
+ <Value>$(LibCrocoDllPrefix)</Value>
+ </BuildMacro>
+ <BuildMacro Include="LibCrocoDllSuffix">
+ <Value>$(LibCrocoDllSuffix)</Value>
+ </BuildMacro>
+ <BuildMacro Include="PythonPath">
+ <Value>$(PythonPath)</Value>
+ </BuildMacro>
+ </ItemGroup>
+</Project>
diff --git a/src/3rdparty/libcroco/win32/vs10/croco.vcxproj.filtersin b/src/3rdparty/libcroco/win32/vs10/croco.vcxproj.filtersin
new file mode 100644
index 0000000..4cce25f
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/croco.vcxproj.filtersin
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Sources">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Headers">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+#include "croco.vs10.sourcefiles.filters"
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="..\..\config.h.win32"><Filter>Resource Files</Filter></CustomBuild>
+ <CustomBuild Include="..\..\src\libcroco.symbols"><Filter>Resource Files</Filter></CustomBuild>
+ </ItemGroup>
+</Project>
diff --git a/src/3rdparty/libcroco/win32/vs10/croco.vcxprojin b/src/3rdparty/libcroco/win32/vs10/croco.vcxprojin
new file mode 100644
index 0000000..e81481b
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/croco.vcxprojin
@@ -0,0 +1,222 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}</ProjectGuid>
+ <RootNamespace>libcroco</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v100</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v100</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-gen-srcs.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-gen-srcs.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-gen-srcs.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-gen-srcs.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <LinkIncremental Condition="'$(Configuration)'=='Debug'">true</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)'=='Release'">false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <ForcedIncludeFiles>%(ForcedIncludeFiles)</ForcedIncludeFiles>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).dll</OutputFile>
+ <ModuleDefinitionFile>$(IntDir)libcroco.def</ModuleDefinitionFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <ImportLibrary>$(TargetDir)$(ProjectName)-$(ApiVersion).lib</ImportLibrary>
+ <ProgramDatabaseFile>$(TargetDir)$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).pdb</ProgramDatabaseFile>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ForcedIncludeFiles>%(ForcedIncludeFiles)</ForcedIncludeFiles>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).dll</OutputFile>
+ <ModuleDefinitionFile>$(IntDir)libcroco.def</ModuleDefinitionFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <ImportLibrary>$(TargetDir)$(ProjectName)-$(ApiVersion).lib</ImportLibrary>
+ <ProgramDatabaseFile>$(TargetDir)$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).pdb</ProgramDatabaseFile>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ForcedIncludeFiles>%(ForcedIncludeFiles)</ForcedIncludeFiles>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).dll</OutputFile>
+ <ModuleDefinitionFile>$(IntDir)libcroco.def</ModuleDefinitionFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <ImportLibrary>$(TargetDir)$(ProjectName)-$(ApiVersion).lib</ImportLibrary>
+ <ProgramDatabaseFile>$(TargetDir)$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).pdb</ProgramDatabaseFile>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ForcedIncludeFiles>%(ForcedIncludeFiles)</ForcedIncludeFiles>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).dll</OutputFile>
+ <ModuleDefinitionFile>$(IntDir)libcroco.def</ModuleDefinitionFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <ImportLibrary>$(TargetDir)$(ProjectName)-$(ApiVersion).lib</ImportLibrary>
+ <ProgramDatabaseFile>$(TargetDir)$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).pdb</ProgramDatabaseFile>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+#include "croco.vs10.sourcefiles"
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="..\..\config.h.win32">
+ <Message Condition="'$(Configuration)'=='Debug'">Copying config.h from config.h.win32...</Message>
+ <Command Condition="'$(Configuration)'=='Debug'">$(CopyConfigH)</Command>
+ <Outputs Condition="'$(Configuration)'=='Debug'">..\..\config.h;%(Outputs)</Outputs>
+ <Message Condition="'$(Configuration)'=='Release'">Copying config.h from config.h.win32...</Message>
+ <Command Condition="'$(Configuration)'=='Release'">$(CopyConfigH)</Command>
+ <Outputs Condition="'$(Configuration)'=='Release'">..\..\config.h;%(Outputs)</Outputs>
+ </CustomBuild>
+ <CustomBuild Include="..\..\src\libcroco.symbols">
+ <Message Condition="'$(Configuration)'=='Debug'">Generating libcroco.def...</Message>
+ <Command Condition="'$(Configuration)'=='Debug'">$(GenerateLibCrocoDef)</Command>
+ <Outputs Condition="'$(Configuration)'=='Debug'">$(IntDir)\libcroco.def;%(Outputs)</Outputs>
+ <Message Condition="'$(Configuration)'=='Release'">Generating libcroco.def...</Message>
+ <Command Condition="'$(Configuration)'=='Release'">$(GenerateLibCrocoDef)</Command>
+ <Outputs Condition="'$(Configuration)'=='Release'">$(IntDir)\libcroco.def;%(Outputs)</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/src/3rdparty/libcroco/win32/vs10/csslint.vcxproj b/src/3rdparty/libcroco/win32/vs10/csslint.vcxproj
new file mode 100644
index 0000000..452aa4a
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/csslint.vcxproj
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{345080B1-9C5B-44B8-98D7-7381D50F3E13}</ProjectGuid>
+ <RootNamespace>csslint</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-build-defines.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-build-defines.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-build-defines.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="croco-build-defines.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <LinkIncremental Condition="'$(Configuration)'=='Debug'">true</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)'=='Release'">false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Midl>
+ <TargetEnvironment>X64</TargetEnvironment>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\csslint\csslint.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="croco.vcxproj">
+ <Project>{4afe9f9b-7f78-41a8-b066-c7ca89938aba}</Project>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/src/3rdparty/libcroco/win32/vs10/csslint.vcxproj.filters b/src/3rdparty/libcroco/win32/vs10/csslint.vcxproj.filters
new file mode 100644
index 0000000..1145315
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/csslint.vcxproj.filters
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Sources">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\csslint\csslint.c">
+ <Filter>Sources</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
diff --git a/src/3rdparty/libcroco/win32/vs10/libcroco.sln b/src/3rdparty/libcroco/win32/vs10/libcroco.sln
new file mode 100644
index 0000000..2077ef1
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs10/libcroco.sln
@@ -0,0 +1,46 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "croco", "croco.vcxproj", "{4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "csslint", "csslint.vcxproj", "{345080B1-9C5B-44B8-98D7-7381D50F3E13}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "croco-install", "croco-install.vcxproj", "{00702787-1566-484D-991F-4E7E459BB909}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Debug|Win32.ActiveCfg = Debug|Win32
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Debug|Win32.Build.0 = Debug|Win32
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Debug|x64.ActiveCfg = Debug|x64
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Debug|x64.Build.0 = Debug|x64
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Release|Win32.ActiveCfg = Release|Win32
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Release|Win32.Build.0 = Release|Win32
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Release|x64.ActiveCfg = Release|x64
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Release|x64.Build.0 = Release|x64
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Debug|Win32.ActiveCfg = Debug|Win32
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Debug|Win32.Build.0 = Debug|Win32
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Debug|x64.ActiveCfg = Debug|x64
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Debug|x64.Build.0 = Debug|x64
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Release|Win32.ActiveCfg = Release|Win32
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Release|Win32.Build.0 = Release|Win32
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Release|x64.ActiveCfg = Release|x64
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Release|x64.Build.0 = Release|x64
+ {00702787-1566-484D-991F-4E7E459BB909}.Debug|Win32.ActiveCfg = Debug|Win32
+ {00702787-1566-484D-991F-4E7E459BB909}.Debug|Win32.Build.0 = Debug|Win32
+ {00702787-1566-484D-991F-4E7E459BB909}.Debug|x64.ActiveCfg = Debug|x64
+ {00702787-1566-484D-991F-4E7E459BB909}.Debug|x64.Build.0 = Debug|x64
+ {00702787-1566-484D-991F-4E7E459BB909}.Release|Win32.ActiveCfg = Release|Win32
+ {00702787-1566-484D-991F-4E7E459BB909}.Release|Win32.Build.0 = Release|Win32
+ {00702787-1566-484D-991F-4E7E459BB909}.Release|x64.ActiveCfg = Release|x64
+ {00702787-1566-484D-991F-4E7E459BB909}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/3rdparty/libcroco/win32/vs11/Makefile.am b/src/3rdparty/libcroco/win32/vs11/Makefile.am
new file mode 100644
index 0000000..b5f9ea9
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs11/Makefile.am
@@ -0,0 +1,39 @@
+# This file is part of The Croco Library
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+# Author: Fan, Chun-wei
+# See COPYRIGHTS file for copyright information.
+
+EXTRA_DIST = \
+ libcroco.sln \
+ croco.vcxproj \
+ croco.vcxproj.filters \
+ csslint.vcxproj \
+ csslint.vcxproj.filters \
+ croco-install.vcxproj \
+ croco-install.vcxproj.filters \
+ croco-build-defines.props \
+ croco-gen-srcs.props \
+ croco-install.props \
+ croco-version-paths.props
+
+DISTCLEANFILES = $(EXTRA_DIST)
+
+MSVC_BASE_VER = 10
+MSVC_BASE_VER_LONG = 2010
+MSVC_VER = 11
+MSVC_VER_LONG = 2012
+
+include $(top_srcdir)/win32/Makefile-newvs.am
diff --git a/src/3rdparty/libcroco/win32/vs12/Makefile.am b/src/3rdparty/libcroco/win32/vs12/Makefile.am
new file mode 100644
index 0000000..a3d6db1
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs12/Makefile.am
@@ -0,0 +1,39 @@
+# This file is part of The Croco Library
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+# Author: Fan, Chun-wei
+# See COPYRIGHTS file for copyright information.
+
+EXTRA_DIST = \
+ libcroco.sln \
+ croco.vcxproj \
+ croco.vcxproj.filters \
+ csslint.vcxproj \
+ csslint.vcxproj.filters \
+ croco-install.vcxproj \
+ croco-install.vcxproj.filters \
+ croco-build-defines.props \
+ croco-gen-srcs.props \
+ croco-install.props \
+ croco-version-paths.props
+
+DISTCLEANFILES = $(EXTRA_DIST)
+
+MSVC_BASE_VER = 10
+MSVC_BASE_VER_LONG = 2010
+MSVC_VER = 12
+MSVC_VER_LONG = 2013
+
+include $(top_srcdir)/win32/Makefile-newvs.am
diff --git a/src/3rdparty/libcroco/win32/vs14/Makefile.am b/src/3rdparty/libcroco/win32/vs14/Makefile.am
new file mode 100644
index 0000000..d68e3bf
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs14/Makefile.am
@@ -0,0 +1,39 @@
+# This file is part of The Croco Library
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+# Author: Fan, Chun-wei
+# See COPYRIGHTS file for copyright information.
+
+EXTRA_DIST = \
+ libcroco.sln \
+ croco.vcxproj \
+ croco.vcxproj.filters \
+ csslint.vcxproj \
+ csslint.vcxproj.filters \
+ croco-install.vcxproj \
+ croco-install.vcxproj.filters \
+ croco-build-defines.props \
+ croco-gen-srcs.props \
+ croco-install.props \
+ croco-version-paths.props
+
+DISTCLEANFILES = $(EXTRA_DIST)
+
+MSVC_BASE_VER = 10
+MSVC_BASE_VER_LONG = 2010
+MSVC_VER = 14
+MSVC_VER_LONG = 14
+
+include $(top_srcdir)/win32/Makefile-newvs.am
diff --git a/src/3rdparty/libcroco/win32/vs15/Makefile.am b/src/3rdparty/libcroco/win32/vs15/Makefile.am
new file mode 100644
index 0000000..0a4afa0
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs15/Makefile.am
@@ -0,0 +1,40 @@
+# This file is part of The Croco Library
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+# Author: Fan, Chun-wei
+# See COPYRIGHTS file for copyright information.
+
+EXTRA_DIST = \
+ libcroco.sln \
+ croco.vcxproj \
+ croco.vcxproj.filters \
+ csslint.vcxproj \
+ csslint.vcxproj.filters \
+ croco-install.vcxproj \
+ croco-install.vcxproj.filters \
+ croco-build-defines.props \
+ croco-gen-srcs.props \
+ croco-install.props \
+ croco-version-paths.props
+
+DISTCLEANFILES = $(EXTRA_DIST)
+
+MSVC_BASE_VER = 10
+MSVC_BASE_VER_LONG = 2010
+MSVC_VER = 15
+MSVC_VER_LONG = 15
+MSVC_TOOLSET = 141
+
+include $(top_srcdir)/win32/Makefile-newvs.am
diff --git a/src/3rdparty/libcroco/win32/vs16/Makefile.am b/src/3rdparty/libcroco/win32/vs16/Makefile.am
new file mode 100644
index 0000000..a622c19
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs16/Makefile.am
@@ -0,0 +1,40 @@
+# This file is part of The Croco Library
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+# Author: Fan, Chun-wei
+# See COPYRIGHTS file for copyright information.
+
+EXTRA_DIST = \
+ libcroco.sln \
+ croco.vcxproj \
+ croco.vcxproj.filters \
+ csslint.vcxproj \
+ csslint.vcxproj.filters \
+ croco-install.vcxproj \
+ croco-install.vcxproj.filters \
+ croco-build-defines.props \
+ croco-gen-srcs.props \
+ croco-install.props \
+ croco-version-paths.props
+
+DISTCLEANFILES = $(EXTRA_DIST)
+
+MSVC_BASE_VER = 10
+MSVC_BASE_VER_LONG = 2010
+MSVC_VER = 16
+MSVC_VER_LONG = 16
+MSVC_TOOLSET = 142
+
+include $(top_srcdir)/win32/Makefile-newvs.am
diff --git a/src/3rdparty/libcroco/win32/vs9/Makefile.am b/src/3rdparty/libcroco/win32/vs9/Makefile.am
new file mode 100644
index 0000000..9128036
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs9/Makefile.am
@@ -0,0 +1,39 @@
+#This file is part of The Croco Library
+#This program is free software; you can redistribute it and/or
+#modify it under the terms of version 2.1 of the GNU Lesser General Public
+#License as published by the Free Software Foundation.
+
+#This program is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#GNU General Public License for more details.
+
+#You should have received a copy of the GNU Lesser General Public License
+#along with this program; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+#USA
+
+#Author: Fan, Chun-wei
+#See COPYRIGHTS file for copyright information.
+
+GENERATED_ITEMS = \
+ croco.vcproj \
+ croco-install.vsprops \
+ croco-version-paths.vsprops
+
+EXTRA_DIST = \
+ croco.vcprojin \
+ csslint.vcproj \
+ croco-install.vcproj \
+ libcroco.sln \
+ croco-build-defines.vsprops \
+ croco-gen-srcs.vsprops \
+ croco-install.vspropsin \
+ croco-version-paths.vsprops.in \
+ $(GENERATED_ITEMS)
+
+croco-install.vsprops: $(top_srcdir)/win32/vs9/croco-install.vspropsin croco.headers
+ $(CPP) -P - <$(top_srcdir)/win32/vs9/croco-install.vspropsin >$@
+ rm croco.headers
+
+DISTCLEANFILES = $(GENERATED_ITEMS)
diff --git a/src/3rdparty/libcroco/win32/vs9/croco-build-defines.vsprops b/src/3rdparty/libcroco/win32/vs9/croco-build-defines.vsprops
new file mode 100644
index 0000000..a081b7b
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs9/croco-build-defines.vsprops
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="crocobuilddefinesprops"
+ InheritedPropertySheets=".\croco-version-paths.vsprops"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)\$(PlatformName)\obj\$(ProjectName)"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src;..\..;$(GlibEtcInstallRoot)\include\glib-2.0;$(GlibEtcInstallRoot)\lib\glib-2.0\include;$(GlibEtcInstallRoot)\include\libxml2;$(GlibEtcInstallRoot)\include"
+ PreprocessorDefinitions="HAVE_CONFIG_H"
+ ForcedIncludeFiles="msvc_recommended_pragmas.h"
+ AdditionalOptions="/MP"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="libxml2.lib glib-2.0.lib"
+ AdditionalLibraryDirectories="$(GlibEtcInstallRoot)\lib"
+ />
+</VisualStudioPropertySheet>
diff --git a/src/3rdparty/libcroco/win32/vs9/croco-gen-srcs.vsprops b/src/3rdparty/libcroco/win32/vs9/croco-gen-srcs.vsprops
new file mode 100644
index 0000000..5be8fe7
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs9/croco-gen-srcs.vsprops
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="crocogensrcsprops"
+ InheritedPropertySheets=".\croco-build-defines.vsprops"
+ >
+ <UserMacro
+ Name="CopyConfigH"
+ Value="copy ..\..\config.h.win32 ..\..\config.h"
+ />
+ <UserMacro
+ Name="GenerateLibCrocoDef"
+ Value="
+echo EXPORTS &gt; $(DefDir)\libcroco.def&#x0D;&#x0A;
+cl /EP ..\..\src\libcroco.symbols &gt;&gt; $(DefDir)\libcroco.def&#x0D;&#x0A;
+ "
+ />
+</VisualStudioPropertySheet>
diff --git a/src/3rdparty/libcroco/win32/vs9/croco-install.vcproj b/src/3rdparty/libcroco/win32/vs9/croco-install.vcproj
new file mode 100644
index 0000000..a48547c
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs9/croco-install.vcproj
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="big5"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="croco-install"
+ ProjectGUID="{00702787-1566-484D-991F-4E7E459BB909}"
+ RootNamespace="crocoinstall"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(GlibEtcInstallRoot)"
+ ConfigurationType="10"
+ InheritedPropertySheets=".\croco-install.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(LibCrocoDoInstall)"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(GlibEtcInstallRoot)"
+ InheritedPropertySheets=".\croco-install.vsprops"
+ ConfigurationType="10"
+ CharacterSet="2"
+ DeleteExtensionsOnClean=""
+ >
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(LibCrocoDoInstall)"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(GlibEtcInstallRoot)"
+ ConfigurationType="10"
+ InheritedPropertySheets=".\croco-install.vsprops"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(LibCrocoDoInstall)"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(GlibEtcInstallRoot)"
+ InheritedPropertySheets=".\croco-install.vsprops"
+ ConfigurationType="10"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ DeleteExtensionsOnClean=""
+ >
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(LibCrocoDoInstall)"
+ />
+ </Configuration>
+ </Configurations>
+ <Files>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File RelativePath="..\..\libcroco.pc.in">
+ <FileConfiguration Name="Debug|Win32">
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating .pc files..."
+ CommandLine="$(LibcrocoGenPC)"
+ Outputs="..\libcroco-0.6.pc"
+ />
+ </FileConfiguration>
+ <FileConfiguration Name="Release|Win32">
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating .pc files..."
+ CommandLine="$(LibcrocoGenPC)"
+ Outputs="..\libcroco-0.6.pc"
+ />
+ </FileConfiguration>
+ <FileConfiguration Name="Debug|x64">
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating .pc files..."
+ CommandLine="$(LibcrocoGenPC)"
+ Outputs="..\libcroco-0.6.pc"
+ />
+ </FileConfiguration>
+ <FileConfiguration Name="Release|x64">
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating .pc files..."
+ CommandLine="$(LibcrocoGenPC)"
+ Outputs="..\libcroco-0.6.pc"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/3rdparty/libcroco/win32/vs9/croco-install.vspropsin b/src/3rdparty/libcroco/win32/vs9/croco-install.vspropsin
new file mode 100644
index 0000000..63a8afb
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs9/croco-install.vspropsin
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="crocoinstallprops"
+ InheritedPropertySheets=".\croco-build-defines.vsprops"
+ >
+ <UserMacro
+ Name="LibCrocoDoInstall"
+ Value="
+mkdir $(GlibEtcInstallRoot)&#x0D;&#x0A;
+mkdir $(GlibEtcInstallRoot)\bin&#x0D;&#x0A;
+copy $(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\$(LibCrocoDllPrefix)croco$(LibCrocoDllSuffix).dll $(CopyDir)\bin&#x0D;&#x0A;
+copy $(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\$(LibCrocoDllPrefix)croco$(LibCrocoDllSuffix).pdb $(CopyDir)\bin&#x0D;&#x0A;
+copy $(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\csslint.exe $(CopyDir)\bin&#x0D;&#x0A;
+copy $(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\csslint.pdb $(CopyDir)\bin&#x0D;&#x0A;
+
+mkdir $(CopyDir)\lib\pkgconfig&#x0D;&#x0A;
+copy ..\libcroco-$(ApiVersion).pc $(CopyDir)\lib\pkgconfig&#x0D;&#x0A;
+
+mkdir $(CopyDir)\include\libcroco-$(ApiVersion)\libcroco&#x0D;&#x0A;
+#include "croco.headers"
+
+mkdir $(CopyDir)\lib&#x0D;&#x0A;
+copy $(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\croco-$(ApiVersion).lib $(CopyDir)\lib&#x0D;&#x0A;
+"
+ />
+ <UserMacro
+ Name="LibcrocoGenPC"
+ Value="(if not exist $(CopyDir) mkdir $(CopyDir)) &amp; (if exist $(PythonPath)\python.exe $(PythonPath)\python.exe ..\crocopc.py --prefix=$(CopyDir) --version=$(CrocoMajorVersion).$(CrocoMinorVersion).$(CrocoMicroVersion))"
+ />
+</VisualStudioPropertySheet>
diff --git a/src/3rdparty/libcroco/win32/vs9/croco-version-paths.vsprops.in b/src/3rdparty/libcroco/win32/vs9/croco-version-paths.vsprops.in
new file mode 100644
index 0000000..d03f5e8
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs9/croco-version-paths.vsprops.in
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="crocoversionpathsprops"
+ >
+ <UserMacro
+ Name="CrocoMajorVersion"
+ Value="@LIBCROCO_MAJOR_VERSION@"
+ />
+ <UserMacro
+ Name="CrocoMinorVersion"
+ Value="@LIBCROCO_MINOR_VERSION@"
+ />
+ <UserMacro
+ Name="CrocoMicroVersion"
+ Value="@LIBCROCO_MICRO_VERSION@"
+ />
+ <UserMacro
+ Name="ApiVersion"
+ Value="$(CrocoMajorVersion).$(CrocoMinorVersion)"
+ />
+ <UserMacro
+ Name="VSVer"
+ Value="9"
+ />
+ <UserMacro
+ Name="GlibEtcInstallRoot"
+ Value="$(SolutionDir)\..\..\..\vs$(VSVer)\$(PlatformName)"
+ />
+ <UserMacro
+ Name="CopyDir"
+ Value="$(GlibEtcInstallRoot)"
+ />
+ <UserMacro
+ Name="DefDir"
+ Value="$(SolutionDir)$(ConfigurationName)\$(PlatformName)\obj\$(ProjectName)"
+ />
+ <UserMacro
+ Name="LibCrocoLibtoolCompatibleDllPrefix"
+ Value="lib"
+ />
+ <UserMacro
+ Name="LibCrocoLibtoolCompatibleDllSuffix"
+ Value="-$(ApiVersion)-0"
+ />
+ <UserMacro
+ Name="LibCrocoSeparateVSDllPrefix"
+ Value=""
+ />
+ <UserMacro
+ Name="LibCrocoSeparateVSDllSuffix"
+ Value="-$(ApiVersion)-vs$(VSVer)"
+ />
+ <!-- Change these two to LibCrocoLibtoolCompatibleDllPrefix and
+ LibCrocoLibtoolCompatibleDllSuffix if that is what you want -->
+ <UserMacro
+ Name="LibCrocoDllPrefix"
+ Value="$(LibCrocoSeparateVSDllPrefix)"
+ />
+ <UserMacro
+ Name="LibCrocoDllSuffix"
+ Value="$(LibCrocoSeparateVSDllSuffix)"
+ />
+ <UserMacro
+ Name="PythonPath"
+ Value="c:\python27"
+ />
+</VisualStudioPropertySheet>
diff --git a/src/3rdparty/libcroco/win32/vs9/croco.vcprojin b/src/3rdparty/libcroco/win32/vs9/croco.vcprojin
new file mode 100644
index 0000000..82df5a8
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs9/croco.vcprojin
@@ -0,0 +1,273 @@
+<?xml version="1.0" encoding="big5"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="croco"
+ ProjectGUID="{4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}"
+ RootNamespace="libcroco"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ InheritedPropertySheets=".\croco-gen-srcs.vsprops"
+ ConfigurationType="2"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="_DEBUG"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ ForcedIncludeFiles=""
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies=""
+ OutputFile="$(OutDir)\$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).dll"
+ LinkIncremental="2"
+ ModuleDefinitionFile="$(IntDir)\libcroco.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ ImportLibrary="$(TargetDir)$(ProjectName)-$(ApiVersion).lib"
+ TargetMachine="1"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ InheritedPropertySheets=".\croco-gen-srcs.vsprops"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ PreprocessorDefinitions=""
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ ForcedIncludeFiles=""
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies=""
+ OutputFile="$(OutDir)\$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).dll"
+ LinkIncremental="1"
+ ModuleDefinitionFile="$(IntDir)\libcroco.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ ImportLibrary="$(TargetDir)$(ProjectName)-$(ApiVersion).lib"
+ TargetMachine="1"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ InheritedPropertySheets=".\croco-gen-srcs.vsprops"
+ ConfigurationType="2"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="_DEBUG"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ ForcedIncludeFiles=""
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies=""
+ OutputFile="$(OutDir)\$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).dll"
+ LinkIncremental="2"
+ ModuleDefinitionFile="$(IntDir)\libcroco.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ ImportLibrary="$(TargetDir)$(ProjectName)-$(ApiVersion).lib"
+ TargetMachine="17"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ InheritedPropertySheets=".\croco-gen-srcs.vsprops"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ PreprocessorDefinitions=""
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ ForcedIncludeFiles=""
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies=""
+ OutputFile="$(OutDir)\$(LibCrocoDllPrefix)$(ProjectName)$(LibCrocoDllSuffix).dll"
+ LinkIncremental="1"
+ ModuleDefinitionFile="$(IntDir)\libcroco.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ ImportLibrary="$(TargetDir)$(ProjectName)-$(ApiVersion).lib"
+ TargetMachine="17"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Sources"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+#include "croco.sourcefiles"
+ </Filter>
+ <Filter
+ Name="Headers"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File RelativePath="..\..\config.h.win32">
+ <FileConfiguration Name="Debug|Win32">
+ <Tool Name="VCCustomBuildTool"
+ Description="Copying config.h from config.h.win32..."
+ CommandLine="$(CopyConfigH)"
+ Outputs="..\..\config.h"
+ />
+ </FileConfiguration>
+ <FileConfiguration Name="Release|Win32">
+ <Tool Name="VCCustomBuildTool"
+ Description="Copying config.h from config.h.win32..."
+ CommandLine="$(CopyConfigH)"
+ Outputs="..\..\config.h"
+ />
+ </FileConfiguration>
+ <FileConfiguration Name="Debug|x64">
+ <Tool Name="VCCustomBuildTool"
+ Description="Copying config.h from config.h.win32..."
+ CommandLine="$(CopyConfigH)"
+ Outputs="..\..\config.h"
+ />
+ </FileConfiguration>
+ <FileConfiguration Name="Release|x64">
+ <Tool Name="VCCustomBuildTool"
+ Description="Copying config.h from config.h.win32..."
+ CommandLine="$(CopyConfigH)"
+ Outputs="..\..\config.h"
+ />
+ </FileConfiguration>
+ </File>
+ <File RelativePath="..\..\src\libcroco.symbols">
+ <FileConfiguration Name="Debug|Win32">
+ <Tool Name="VCCustomBuildTool"
+ Description="Generating libcroco.def..."
+ CommandLine="$(GenerateLibCrocoDef)"
+ Outputs="$(IntDir)\libcroco.def"
+ />
+ </FileConfiguration>
+ <FileConfiguration Name="Release|Win32">
+ <Tool Name="VCCustomBuildTool"
+ Description="Generating libcroco.def..."
+ CommandLine="$(GenerateLibCrocoDef)"
+ Outputs="$(IntDir)\libcroco.def"
+ />
+ </FileConfiguration>
+ <FileConfiguration Name="Debug|x64">
+ <Tool Name="VCCustomBuildTool"
+ Description="Generating libcroco.def..."
+ CommandLine="$(GenerateLibCrocoDef)"
+ Outputs="$(IntDir)\libcroco.def"
+ />
+ </FileConfiguration>
+ <FileConfiguration Name="Release|x64">
+ <Tool Name="VCCustomBuildTool"
+ Description="Generating libcroco.def..."
+ CommandLine="$(GenerateLibCrocoDef)"
+ Outputs="$(IntDir)\libcroco.def"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/3rdparty/libcroco/win32/vs9/csslint.vcproj b/src/3rdparty/libcroco/win32/vs9/csslint.vcproj
new file mode 100644
index 0000000..20ede16
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs9/csslint.vcproj
@@ -0,0 +1,189 @@
+<?xml version="1.0" encoding="big5"?>
+<!--
+This file is part of The Croco Library
+This program is free software; you can redistribute it and/or
+modify it under the terms of version 2.1 of the GNU Lesser General Public
+License as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+USA
+
+Author: Fan, Chun-wei
+See COPYRIGHTS file for copyright information.
+-->
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="csslint"
+ ProjectGUID="{345080B1-9C5B-44B8-98D7-7381D50F3E13}"
+ RootNamespace="csslint"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ InheritedPropertySheets=".\croco-build-defines.vsprops"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies=""
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ InheritedPropertySheets=".\croco-build-defines.vsprops"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies=""
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ InheritedPropertySheets=".\croco-build-defines.vsprops"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="_DEBUG"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies=""
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="17"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ InheritedPropertySheets=".\croco-build-defines.vsprops"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies=""
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="17"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Sources"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File RelativePath="..\..\csslint\csslint.c" />
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/3rdparty/libcroco/win32/vs9/libcroco.sln b/src/3rdparty/libcroco/win32/vs9/libcroco.sln
new file mode 100644
index 0000000..71e1b2f
--- /dev/null
+++ b/src/3rdparty/libcroco/win32/vs9/libcroco.sln
@@ -0,0 +1,53 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "croco", "croco.vcproj", "{4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "csslint", "csslint.vcproj", "{345080B1-9C5B-44B8-98D7-7381D50F3E13}"
+ ProjectSection(ProjectDependencies) = postProject
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA} = {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "croco-install", "croco-install.vcproj", "{00702787-1566-484D-991F-4E7E459BB909}"
+ ProjectSection(ProjectDependencies) = postProject
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA} = {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13} = {345080B1-9C5B-44B8-98D7-7381D50F3E13}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Debug|Win32.ActiveCfg = Debug|Win32
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Debug|Win32.Build.0 = Debug|Win32
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Debug|x64.ActiveCfg = Debug|x64
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Debug|x64.Build.0 = Debug|x64
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Release|Win32.ActiveCfg = Release|Win32
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Release|Win32.Build.0 = Release|Win32
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Release|x64.ActiveCfg = Release|x64
+ {4AFE9F9B-7F78-41A8-B066-C7CA89938ABA}.Release|x64.Build.0 = Release|x64
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Debug|Win32.ActiveCfg = Debug|Win32
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Debug|Win32.Build.0 = Debug|Win32
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Debug|x64.ActiveCfg = Debug|x64
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Debug|x64.Build.0 = Debug|x64
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Release|Win32.ActiveCfg = Release|Win32
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Release|Win32.Build.0 = Release|Win32
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Release|x64.ActiveCfg = Release|x64
+ {345080B1-9C5B-44B8-98D7-7381D50F3E13}.Release|x64.Build.0 = Release|x64
+ {00702787-1566-484D-991F-4E7E459BB909}.Debug|Win32.ActiveCfg = Debug|Win32
+ {00702787-1566-484D-991F-4E7E459BB909}.Debug|Win32.Build.0 = Debug|Win32
+ {00702787-1566-484D-991F-4E7E459BB909}.Debug|x64.ActiveCfg = Debug|x64
+ {00702787-1566-484D-991F-4E7E459BB909}.Debug|x64.Build.0 = Debug|x64
+ {00702787-1566-484D-991F-4E7E459BB909}.Release|Win32.ActiveCfg = Release|Win32
+ {00702787-1566-484D-991F-4E7E459BB909}.Release|Win32.Build.0 = Release|Win32
+ {00702787-1566-484D-991F-4E7E459BB909}.Release|x64.ActiveCfg = Release|x64
+ {00702787-1566-484D-991F-4E7E459BB909}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/3rdparty/libdepixelize/CMakeLists.txt b/src/3rdparty/libdepixelize/CMakeLists.txt
new file mode 100644
index 0000000..8c7df77
--- /dev/null
+++ b/src/3rdparty/libdepixelize/CMakeLists.txt
@@ -0,0 +1,24 @@
+
+set(libdepixelize_SRC
+ kopftracer2011.cpp
+
+ # -------
+ # Headers
+ kopftracer2011.h
+ splines.h
+
+ priv/branchless.h
+ priv/colorspace.h
+ priv/curvature.h
+ priv/homogeneoussplines.h
+ priv/integral.h
+ priv/iterator.h
+ priv/optimization-kopf2011.h
+ priv/pixelgraph.h
+ priv/point.h
+ priv/simplifiedvoronoi.h
+ priv/splines-kopf2011.h
+)
+
+add_inkscape_lib(depixelize_LIB "${libdepixelize_SRC}")
+target_link_libraries(depixelize_LIB PUBLIC 2Geom::2geom) \ No newline at end of file
diff --git a/src/3rdparty/libdepixelize/README b/src/3rdparty/libdepixelize/README
new file mode 100644
index 0000000..1f9c0fd
--- /dev/null
+++ b/src/3rdparty/libdepixelize/README
@@ -0,0 +1,7 @@
+Libdepixelize pixelart tracing library.
+
+This code must be kept in sync with our "upstream" project
+https://gitlab.com/inkscape/devel/libdepixelize
+
+Any change must first (or in parallel) be submitted to the upstream project
+and ideally be tested there, independently of Inkscape.
diff --git a/src/3rdparty/libdepixelize/kopftracer2011.cpp b/src/3rdparty/libdepixelize/kopftracer2011.cpp
new file mode 100644
index 0000000..96784b1
--- /dev/null
+++ b/src/3rdparty/libdepixelize/kopftracer2011.cpp
@@ -0,0 +1,665 @@
+/* This file is part of the libdepixelize project
+ Copyright (C) 2013 Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.com>
+
+ GNU Lesser General Public License Usage
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2.1 of the License, or (at your
+ option) any later version.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+ GNU General Public License Usage
+ Alternatively, this library may be used under the terms of the GNU General
+ Public License as published by the Free Software Foundation, either version
+ 2 of the License, or (at your option) any later version.
+ You should have received a copy of the GNU General Public License along with
+ this library. If not, see <http://www.gnu.org/licenses/>.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <glibmm.h>
+
+#include <algorithm>
+#include "kopftracer2011.h"
+#include "priv/colorspace.h"
+#include "priv/homogeneoussplines.h"
+#include "priv/branchless.h"
+#include "priv/splines-kopf2011.h"
+#include "priv/iterator.h"
+
+#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
+#include <glibmm/datetime.h>
+#include <iostream>
+#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
+
+namespace Tracer {
+namespace Heuristics {
+
+int curves(const PixelGraph &graph, PixelGraph::const_iterator a,
+ PixelGraph::const_iterator b);
+bool islands(PixelGraph::const_iterator a, PixelGraph::const_iterator b);
+
+struct SparsePixels
+{
+ enum Diagonal {
+ /**
+ * From (first) the top left corner to (second) the bottom right.
+ */
+ MAIN_DIAGONAL = 0,
+ /**
+ * From (first) the top right to (second) the bottom left.
+ */
+ SECONDARY_DIAGONAL = 1
+ };
+
+ typedef std::pair<PixelGraph::const_iterator, PixelGraph::const_iterator>
+ Edge;
+ typedef std::pair<Edge, int> EdgeWeight;
+
+ void operator()(const PixelGraph &graph, unsigned radius);
+
+ static bool similar_colors(PixelGraph::const_iterator n,
+ const guint8 (&a)[4], const guint8 (&b)[4]);
+
+ /*
+ * Precondition: Must be filled according to Diagonal enum.
+ */
+ EdgeWeight diagonals[2];
+};
+
+} // namespace Heuristics
+
+Splines Kopf2011::to_voronoi(const std::string &filename,
+ const Options &options)
+{
+ return to_voronoi(Gdk::Pixbuf::create_from_file(filename), options);
+}
+
+Splines Kopf2011::to_voronoi(const Glib::RefPtr<Gdk::Pixbuf const> &buf,
+ const Options &options)
+{
+#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
+ SimplifiedVoronoi<Precision, false> voronoi
+ = _voronoi<Precision, false>(buf, options);
+
+ Glib::DateTime profiling_info[2];
+ profiling_info[0] = Glib::DateTime::create_now_utc();
+
+ Splines ret(voronoi);
+
+ profiling_info[1] = Glib::DateTime::create_now_utc();
+ std::cerr << "Tracer::Splines construction time: "
+ << profiling_info[1].difference(profiling_info[0])
+ << std::endl;
+
+ return ret;
+#else // LIBDEPIXELIZE_PROFILE_KOPF2011
+ return Splines(_voronoi<Precision, false>(buf, options));
+#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
+}
+
+Splines Kopf2011::to_grouped_voronoi(const std::string &filename,
+ const Options &options)
+{
+ return to_grouped_voronoi(Gdk::Pixbuf::create_from_file(filename), options);
+}
+
+Splines Kopf2011::to_grouped_voronoi(const Glib::RefPtr<Gdk::Pixbuf const> &buf,
+ const Options &options)
+{
+#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
+ SimplifiedVoronoi<Precision, false> voronoi
+ = _voronoi<Precision, false>(buf, options);
+
+ Glib::DateTime profiling_info[2];
+ profiling_info[0] = Glib::DateTime::create_now_utc();
+
+ HomogeneousSplines<Precision> splines(voronoi);
+
+#else // LIBDEPIXELIZE_PROFILE_KOPF2011
+ HomogeneousSplines<Precision> splines(_voronoi<Precision, false>
+ (buf, options));
+#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
+
+#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
+ profiling_info[1] = Glib::DateTime::create_now_utc();
+ std::cerr << "Tracer::HomogeneousSplines<" << typeid(Precision).name()
+ << ">(Tracer::SimplifiedVoronoi<" << typeid(Precision).name()
+ << ",false>) construction time: "
+ << profiling_info[1].difference(profiling_info[0])
+ << std::endl;
+ profiling_info[0] = Glib::DateTime::create_now_utc();
+#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
+
+ for ( HomogeneousSplines<Precision>::iterator it = splines.begin(),
+ end = splines.end() ; it != end ; ++it ) {
+ for ( HomogeneousSplines<Precision>::Polygon::points_iter
+ it2 = it->vertices.begin(), end2 = it->vertices.end()
+ ; it2 != end2 ; ++it2 ) {
+ it2->smooth = false;
+ }
+ for ( HomogeneousSplines<Precision>::Polygon::holes_iter
+ it2 = it->holes.begin(), end2 = it->holes.end()
+ ; it2 != end2 ; ++it2 ) {
+ for ( HomogeneousSplines<Precision>::Polygon::points_iter
+ it3 = it2->begin(), end3 = it2->end()
+ ; it3 != end3 ; ++it3 ) {
+ it3->smooth = false;
+ }
+ }
+ }
+
+#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
+ profiling_info[1] = Glib::DateTime::create_now_utc();
+ std::cerr << "Tracer::Kopf2011::to_grouped_voronoi internal work time: "
+ << profiling_info[1].difference(profiling_info[0])
+ << std::endl;
+ profiling_info[0] = Glib::DateTime::create_now_utc();
+
+ Splines ret(splines, false, options.nthreads);
+
+ profiling_info[1] = Glib::DateTime::create_now_utc();
+ std::cerr << "Tracer::Splines construction time: "
+ << profiling_info[1].difference(profiling_info[0])
+ << std::endl;
+
+ return ret;
+#else // LIBDEPIXELIZE_PROFILE_KOPF2011
+ return Splines(splines, false, options.nthreads);
+#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
+}
+
+Splines Kopf2011::to_splines(const std::string &filename,
+ const Options &options)
+{
+ return to_splines(Gdk::Pixbuf::create_from_file(filename), options);
+}
+
+Splines Kopf2011::to_splines(const Glib::RefPtr<Gdk::Pixbuf const> &buf,
+ const Options &options)
+{
+#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
+ SimplifiedVoronoi<Precision, true> voronoi
+ = _voronoi<Precision, true>(buf, options);
+
+ Glib::DateTime profiling_info[2];
+ profiling_info[0] = Glib::DateTime::create_now_utc();
+
+ HomogeneousSplines<Precision> splines(voronoi);
+
+ profiling_info[1] = Glib::DateTime::create_now_utc();
+ std::cerr << "Tracer::HomogeneousSplines<" << typeid(Precision).name()
+ << "> construction time: "
+ << profiling_info[1].difference(profiling_info[0])
+ << std::endl;
+
+ profiling_info[0] = Glib::DateTime::create_now_utc();
+
+ Splines ret(splines, options.optimize, options.nthreads);
+
+ profiling_info[1] = Glib::DateTime::create_now_utc();
+ std::cerr << "Tracer::Splines construction time: "
+ << profiling_info[1].difference(profiling_info[0])
+ << std::endl;
+
+ return ret;
+#else // LIBDEPIXELIZE_PROFILE_KOPF2011
+ HomogeneousSplines<Precision> splines(_voronoi<Precision, true>
+ (buf, options));
+ return Splines(splines, options.optimize, options.nthreads);
+#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
+}
+
+template<class T, bool adjust_splines>
+SimplifiedVoronoi<T, adjust_splines>
+Kopf2011::_voronoi(const Glib::RefPtr<Gdk::Pixbuf const> &buf,
+ const Options &options)
+{
+#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
+ Glib::DateTime profiling_info[2];
+ profiling_info[0] = Glib::DateTime::create_now_utc();
+#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
+
+ PixelGraph graph(buf);
+
+#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
+ profiling_info[1] = Glib::DateTime::create_now_utc();
+ std::cerr << "Tracer::PixelGraph creation time: "
+ << profiling_info[1].difference(profiling_info[0]) << std::endl;
+#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
+
+ // gdk-pixbuf2 already checks if image size is meaningful, but asserts state
+ // preconditions and will be useful if gdk-pixbuf is replaced later
+ assert(graph.width() > 0);
+ assert(graph.height() > 0);
+
+#ifndef NDEBUG
+ graph.checkConsistency();
+#endif
+
+#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
+ profiling_info[0] = Glib::DateTime::create_now_utc();
+#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
+
+ // This step could be part of the initialization of PixelGraph
+ // and decrease the necessary number of passes
+ graph.connectAllNeighbors();
+
+#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
+ profiling_info[1] = Glib::DateTime::create_now_utc();
+ std::cerr << "Tracer::PixelGraph::connectAllNeighbors() time: "
+ << profiling_info[1].difference(profiling_info[0]) << std::endl;
+#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
+
+#ifndef NDEBUG
+ graph.checkConsistency();
+#endif
+
+#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
+ profiling_info[0] = Glib::DateTime::create_now_utc();
+#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
+
+ // This step can't be part of PixelGraph initilization without adding some
+ // cache misses due to random access patterns that might be injected
+ _disconnect_neighbors_with_dissimilar_colors(graph);
+
+#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
+ profiling_info[1] = Glib::DateTime::create_now_utc();
+ std::cerr << "Tracer::Kopf2011::"
+ "_disconnect_neighbors_with_dissimilar_colors(Tracer::PixelGraph) time: "
+ << profiling_info[1].difference(profiling_info[0]) << std::endl;
+#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
+
+#ifndef NDEBUG
+ graph.checkConsistency();
+#endif
+
+#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
+ profiling_info[0] = Glib::DateTime::create_now_utc();
+#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
+
+ {
+ // edges_safe and edges_unsafe must be executed in separate.
+ // Otherwise, there will be colateral effects due to misassumption about
+ // the data being read.
+ PixelGraph::EdgePairContainer edges = graph.crossingEdges();
+
+#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
+ profiling_info[1] = Glib::DateTime::create_now_utc();
+ std::cerr << "Tracer::PixelGraph::crossingEdges() time: "
+ << profiling_info[1].difference(profiling_info[0]) << std::endl;
+ profiling_info[0] = Glib::DateTime::create_now_utc();
+#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
+
+ _remove_crossing_edges_safe(edges);
+
+#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
+ profiling_info[1] = Glib::DateTime::create_now_utc();
+ std::cerr << "Tracer::Kopf2011::_remove_crossing_edges_safe"
+ "(Tracer::PixelGraph) time: "
+ << profiling_info[1].difference(profiling_info[0])
+ << std::endl;
+#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
+
+#ifndef NDEBUG
+ graph.checkConsistency();
+#endif
+
+#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
+ profiling_info[0] = Glib::DateTime::create_now_utc();
+#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
+
+ _remove_crossing_edges_unsafe(graph, edges, options);
+ }
+
+#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
+ profiling_info[1] = Glib::DateTime::create_now_utc();
+ std::cerr << "Tracer::Kopf2011::_remove_crossing_edges_unsafe"
+ "(Tracer::PixelGraph) time: "
+ << profiling_info[1].difference(profiling_info[0]) << std::endl;
+#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
+
+#ifndef NDEBUG
+ graph.checkConsistency();
+#endif
+
+ assert(graph.crossingEdges().size() == 0);
+
+#ifdef LIBDEPIXELIZE_PROFILE_KOPF2011
+ profiling_info[0] = Glib::DateTime::create_now_utc();
+
+ SimplifiedVoronoi<T, adjust_splines> ret(graph);
+
+ profiling_info[1] = Glib::DateTime::create_now_utc();
+ std::cerr << "Tracer::SimplifiedVoronoi<" << typeid(T).name() << ','
+ << (adjust_splines ? "true" : "false")
+ << ">(Tracer::PixelGraph) construction time: "
+ << profiling_info[1].difference(profiling_info[0]) << std::endl;
+
+ return ret;
+#else // LIBDEPIXELIZE_PROFILE_KOPF2011
+ return SimplifiedVoronoi<T, adjust_splines>(graph);
+#endif // LIBDEPIXELIZE_PROFILE_KOPF2011
+}
+
+// TODO: move this function (plus connectAllNeighbors) to PixelGraph constructor
+inline void
+Kopf2011::_disconnect_neighbors_with_dissimilar_colors(PixelGraph &graph)
+{
+ using colorspace::similar_colors;
+ for ( PixelGraph::iterator it = graph.begin(), end = graph.end() ; it != end
+ ; ++it ) {
+ if ( it->adj.top )
+ it->adj.top = similar_colors(it->rgba, (it - graph.width())->rgba);
+ if ( it->adj.topright ) {
+ it->adj.topright
+ = similar_colors(it->rgba, (it - graph.width() + 1)->rgba);
+ }
+ if ( it->adj.right )
+ it->adj.right = similar_colors(it->rgba, (it + 1)->rgba);
+ if ( it->adj.bottomright ) {
+ it->adj.bottomright
+ = similar_colors(it->rgba, (it + graph.width() + 1)->rgba);
+ }
+ if ( it->adj.bottom ) {
+ it->adj.bottom
+ = similar_colors(it->rgba, (it + graph.width())->rgba);
+ }
+ if ( it->adj.bottomleft ) {
+ it->adj.bottomleft
+ = similar_colors(it->rgba, (it + graph.width() - 1)->rgba);
+ }
+ if ( it->adj.left )
+ it->adj.left = similar_colors(it->rgba, (it - 1)->rgba);
+ if ( it->adj.topleft ) {
+ it->adj.topleft = similar_colors(it->rgba,
+ (it - graph.width() - 1)->rgba);
+ }
+ }
+}
+
+/**
+ * This method removes crossing edges if the 2x2 block is fully connected.
+ *
+ * In this case the two diagonal connections can be safely removed without
+ * affecting the final result.
+ */
+template<class T>
+void Kopf2011::_remove_crossing_edges_safe(T &container)
+{
+ for ( typename T::reverse_iterator it = container.rbegin(),
+ end = container.rend() ; it != end ; ) {
+ /* A | B
+ --+--
+ C | D */
+ PixelGraph::iterator a = it->first.first;
+ PixelGraph::iterator b = it->second.first;
+ PixelGraph::iterator c = it->second.second;
+ PixelGraph::iterator d = it->first.second;
+
+ if ( !a->adj.right || !a->adj.bottom || !b->adj.bottom
+ || !c->adj.right ) {
+ ++it;
+ continue;
+ }
+
+ // main diagonal
+ a->adj.bottomright = 0;
+ d->adj.topleft = 0;
+
+ // secondary diagonal
+ b->adj.bottomleft = 0;
+ c->adj.topright = 0;
+
+ // base iterator is always past one
+ typename T::iterator current = --(it.base());
+ ++it;
+ container.erase(current);
+ }
+}
+
+/**
+ * This method removes crossing edges using the heuristics.
+ */
+template<class T>
+void Kopf2011::_remove_crossing_edges_unsafe(PixelGraph &graph, T &edges,
+ const Options &options)
+{
+ std::vector< std::pair<int, int> > weights(edges.size(),
+ std::make_pair(0, 0));
+
+ // Compute weights
+ for ( typename T::size_type i = 0 ; i != edges.size() ; ++i ) {
+ /* A | B
+ --+--
+ C | D */
+ PixelGraph::iterator a = edges[i].first.first;
+ PixelGraph::iterator b = edges[i].second.first;
+ PixelGraph::iterator c = edges[i].second.second;
+ PixelGraph::iterator d = edges[i].first.second;
+
+ // Curves heuristic
+ weights[i].first += Heuristics::curves(graph, a, d)
+ * options.curvesMultiplier;
+ weights[i].second += Heuristics::curves(graph, b, c)
+ * options.curvesMultiplier;
+
+ // Islands heuristic
+ weights[i].first += Heuristics::islands(a, d) * options.islandsWeight;
+ weights[i].second += Heuristics::islands(b, c) * options.islandsWeight;
+
+ // Sparse pixels heuristic
+ using Heuristics::SparsePixels;
+ SparsePixels sparse_pixels;
+
+ sparse_pixels.diagonals[SparsePixels::MAIN_DIAGONAL].first
+ = edges[i].first;
+ sparse_pixels.diagonals[SparsePixels::SECONDARY_DIAGONAL].first
+ = edges[i].second;
+
+ sparse_pixels(graph, options.sparsePixelsRadius);
+
+ weights[i].first
+ += sparse_pixels.diagonals[SparsePixels::MAIN_DIAGONAL].second
+ * options.sparsePixelsMultiplier;
+ weights[i].second
+ += sparse_pixels.diagonals[SparsePixels::SECONDARY_DIAGONAL].second
+ * options.sparsePixelsMultiplier;
+ }
+
+ // Remove edges with lower weight
+ for ( typename T::size_type i = 0 ; i != edges.size() ; ++i ) {
+ /* A | B
+ --+--
+ C | D */
+ PixelGraph::iterator a = edges[i].first.first;
+ PixelGraph::iterator b = edges[i].second.first;
+ PixelGraph::iterator c = edges[i].second.second;
+ PixelGraph::iterator d = edges[i].first.second;
+
+ if ( weights[i].first > weights[i].second ) {
+ b->adj.bottomleft = 0;
+ c->adj.topright = 0;
+ } else if ( weights[i].first < weights[i].second ) {
+ a->adj.bottomright = 0;
+ d->adj.topleft = 0;
+ } else {
+ a->adj.bottomright = 0;
+ b->adj.bottomleft = 0;
+ c->adj.topright = 0;
+ d->adj.topleft = 0;
+ }
+ }
+
+ edges.clear();
+}
+
+inline int Heuristics::curves(const PixelGraph &graph,
+ PixelGraph::const_iterator a,
+ PixelGraph::const_iterator b)
+{
+ int count = 1;
+ ToPtr<PixelGraph::Node> to_ptr;
+ ToIter<PixelGraph::Node> to_iter(graph.begin());
+
+ // b -> a
+ // and then a -> b
+ for ( int i = 0 ; i != 2 ; ++i ) {
+ PixelGraph::const_iterator it = i ? a : b;
+ PixelGraph::const_iterator prev = i ? b : a;
+ int local_count = 0;
+
+ // Used to avoid inifinite loops in circular-like edges
+ const PixelGraph::const_iterator initial = it;
+
+ while ( it->adjsize() == 2 ) {
+ ++local_count;
+
+ // Iterate to next
+ {
+ // There are only two values that won't be zero'ed
+ // and one of them has the same value of prev
+ guintptr aux = (it->adj.top
+ * guintptr(to_ptr(graph.nodeTop(it))))
+ + (it->adj.topright
+ * guintptr(to_ptr(graph.nodeTopRight(it))))
+ + (it->adj.right
+ * guintptr(to_ptr(graph.nodeRight(it))))
+ + (it->adj.bottomright
+ * guintptr(to_ptr(graph.nodeBottomRight(it))))
+ + (it->adj.bottom
+ * guintptr(to_ptr(graph.nodeBottom(it))))
+ + (it->adj.bottomleft
+ * guintptr(to_ptr(graph.nodeBottomLeft(it))))
+ + (it->adj.left
+ * guintptr(to_ptr(graph.nodeLeft(it))))
+ + (it->adj.topleft
+ * guintptr(to_ptr(graph.nodeTopLeft(it))))
+ - guintptr(to_ptr(prev));
+ prev = it;
+ it = to_iter(reinterpret_cast<PixelGraph::Node const*>(aux));
+ }
+
+ // Break infinite loops
+ if ( it == initial )
+ return local_count;
+ }
+ count += local_count;
+ }
+
+ return count;
+}
+
+inline void Heuristics::SparsePixels::operator ()(const PixelGraph &graph,
+ unsigned radius)
+{
+ if ( !graph.width() || !graph.height() )
+ return;
+
+ // Clear weights
+ for ( int i = 0 ; i != 2 ; ++i )
+ diagonals[i].second = 0;
+
+ if ( !radius )
+ return;
+
+ // Fix radius/bounds
+ {
+ unsigned x = graph.toX(diagonals[MAIN_DIAGONAL].first.first);
+ unsigned y = graph.toY(diagonals[MAIN_DIAGONAL].first.first);
+ unsigned displace = radius - 1;
+
+ {
+ unsigned minor = std::min(x, y);
+
+ if ( displace > minor ) {
+ displace = minor;
+ radius = displace + 1;
+ }
+ }
+
+ displace = radius;
+
+ if ( x + displace >= unsigned(graph.width()) ) {
+ displace = unsigned(graph.width()) - x - 1;
+ radius = displace;
+ }
+
+ if ( y + displace >= unsigned(graph.height()) ) {
+ displace = unsigned(graph.height()) - y - 1;
+ radius = displace;
+ }
+ }
+
+ if ( !radius )
+ return;
+
+ // Iterate over nodes and count them
+ {
+ PixelGraph::const_iterator it = diagonals[MAIN_DIAGONAL].first.first;
+ for ( unsigned i = radius - 1 ; i ; --i )
+ it = graph.nodeTopLeft(it);
+
+ bool invert = false;
+ for ( unsigned i = 0 ; i != 2 * radius ; ++i ) {
+ for ( unsigned j = 0 ; j != 2 * radius ; ++j ) {
+ for ( int k = 0 ; k != 2 ; ++k ) {
+ diagonals[k].second
+ += similar_colors(it, diagonals[k].first.first->rgba,
+ diagonals[k].first.second->rgba);
+ }
+ it = (invert ? graph.nodeLeft(it) : graph.nodeRight(it));
+ }
+ it = (invert ? graph.nodeRight(it) : graph.nodeLeft(it));
+
+
+ invert = !invert;
+ it = graph.nodeBottom(it);
+ }
+ }
+
+ int minor = std::min(diagonals[0].second, diagonals[1].second);
+ for ( int i = 0 ; i != 2 ; ++i )
+ diagonals[i].second -= minor;
+ std::swap(diagonals[0].second, diagonals[1].second);
+}
+
+inline bool
+Heuristics::SparsePixels::similar_colors(PixelGraph::const_iterator n,
+ const guint8 (&a)[4],
+ const guint8 (&b)[4])
+{
+ using colorspace::similar_colors;
+ return similar_colors(n->rgba, a) || similar_colors(n->rgba, b);
+}
+
+inline bool Heuristics::islands(PixelGraph::const_iterator a,
+ PixelGraph::const_iterator b)
+{
+ if ( a->adjsize() == 1 || b->adjsize() == 1 )
+ return true;
+
+ return false;
+}
+
+} // namespace Tracer
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/libdepixelize/kopftracer2011.h b/src/3rdparty/libdepixelize/kopftracer2011.h
new file mode 100644
index 0000000..c60d0a6
--- /dev/null
+++ b/src/3rdparty/libdepixelize/kopftracer2011.h
@@ -0,0 +1,150 @@
+/* This file is part of the libdepixelize project
+ Copyright (C) 2013 Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.com>
+
+ GNU Lesser General Public License Usage
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2.1 of the License, or (at your
+ option) any later version.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+ GNU General Public License Usage
+ Alternatively, this library may be used under the terms of the GNU General
+ Public License as published by the Free Software Foundation, either version
+ 2 of the License, or (at your option) any later version.
+ You should have received a copy of the GNU General Public License along with
+ this library. If not, see <http://www.gnu.org/licenses/>.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+*/
+
+#ifndef LIBDEPIXELIZE_TRACER_KOPFTRACER2011_H
+#define LIBDEPIXELIZE_TRACER_KOPFTRACER2011_H
+
+#include <string>
+
+#include <glibmm.h>
+// Contains exception definitions
+#include <glibmm/fileutils.h>
+#include <gdkmm/pixbuf.h>
+#include "splines.h"
+
+namespace Tracer {
+
+class PixelGraph;
+
+class Kopf2011
+{
+public:
+ struct Options
+ {
+ enum Defaults {
+ CURVES_MULTIPLIER = 1,
+ ISLANDS_WEIGHT = 5,
+ SPARSE_PIXELS_MULTIPLIER = 1,
+ SPARSE_PIXELS_RADIUS = 4
+ };
+
+ Options() :
+ curvesMultiplier(CURVES_MULTIPLIER),
+ islandsWeight(ISLANDS_WEIGHT),
+ sparsePixelsMultiplier(SPARSE_PIXELS_MULTIPLIER),
+ sparsePixelsRadius(SPARSE_PIXELS_RADIUS),
+ optimize(true),
+ nthreads(1)
+ {}
+
+ // Heuristics
+ double curvesMultiplier;
+ int islandsWeight;
+ double sparsePixelsMultiplier;
+ unsigned sparsePixelsRadius;
+
+ // Other options
+ bool optimize;
+ int nthreads;
+ };
+
+ /**
+ * # Exceptions
+ *
+ * \p options.optimize and options.nthreads will be ignored
+ *
+ * Glib::FileError
+ * Gdk::PixbufError
+ */
+ static Splines to_voronoi(const std::string &filename,
+ const Options &options = Options());
+
+ /*
+ * \p options.optimize and options.nthreads will be ignored
+ */
+ static Splines to_voronoi(const Glib::RefPtr<Gdk::Pixbuf const> &buf,
+ const Options &options = Options());
+
+ /**
+ * # Exceptions
+ *
+ * \p options.optimize and options.nthreads will be ignored
+ *
+ * Glib::FileError
+ * Gdk::PixbufError
+ */
+ static Splines to_grouped_voronoi(const std::string &filename,
+ const Options &options = Options());
+
+ /*
+ * \p options.optimize and options.nthreads will be ignored
+ */
+ static Splines to_grouped_voronoi(const Glib::RefPtr<Gdk::Pixbuf const> &buf,
+ const Options &options = Options());
+
+ /**
+ * # Exceptions
+ *
+ * Glib::FileError
+ * Gdk::PixbufError
+ */
+ static Splines to_splines(const std::string &filename,
+ const Options &options = Options());
+
+ static Splines to_splines(const Glib::RefPtr<Gdk::Pixbuf const> &buf,
+ const Options &options = Options());
+
+private:
+ typedef Geom::Coord Precision;
+
+ template<class T, bool adjust_splines>
+ static SimplifiedVoronoi<T, adjust_splines>
+ _voronoi(const Glib::RefPtr<Gdk::Pixbuf const> &buf,
+ const Options &options);
+
+ static void _disconnect_neighbors_with_dissimilar_colors(PixelGraph &graph);
+
+ // here, T/template is only used as an easy way to not expose internal
+ // symbols
+ template<class T>
+ static void _remove_crossing_edges_safe(T &container);
+ template<class T>
+ static void _remove_crossing_edges_unsafe(PixelGraph &graph, T &edges,
+ const Options &options);
+};
+
+} // namespace Tracer
+
+#endif // LIBDEPIXELIZE_TRACER_KOPFTRACER2011_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/libdepixelize/priv/branchless.h b/src/3rdparty/libdepixelize/priv/branchless.h
new file mode 100644
index 0000000..487a968
--- /dev/null
+++ b/src/3rdparty/libdepixelize/priv/branchless.h
@@ -0,0 +1,58 @@
+/* This file is part of the libdepixelize project
+ Copyright (C) 2013 Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.com>
+
+ GNU Lesser General Public License Usage
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2.1 of the License, or (at your
+ option) any later version.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+ GNU General Public License Usage
+ Alternatively, this library may be used under the terms of the GNU General
+ Public License as published by the Free Software Foundation, either version
+ 2 of the License, or (at your option) any later version.
+ You should have received a copy of the GNU General Public License along with
+ this library. If not, see <http://www.gnu.org/licenses/>.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+*/
+
+#ifndef LIBDEPIXELIZE_TRACER_BRANCHLESS_H
+#define LIBDEPIXELIZE_TRACER_BRANCHLESS_H
+
+namespace Tracer {
+
+/**
+ * Branch misprediction proof operations
+ */
+namespace branchless {
+
+/*
+ * All modern processors optimize the branch to a conditional move
+ */
+template<class T>
+T first_if(T first, T second, bool cond)
+{
+ return cond ? first : second;
+}
+
+} // namespace branchless
+} // namespace Tracer {
+
+#endif // LIBDEPIXELIZE_TRACER_BRANCHLESS_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/libdepixelize/priv/colorspace.h b/src/3rdparty/libdepixelize/priv/colorspace.h
new file mode 100644
index 0000000..4982630
--- /dev/null
+++ b/src/3rdparty/libdepixelize/priv/colorspace.h
@@ -0,0 +1,111 @@
+/* This file is part of the libdepixelize project
+ Copyright (C) 2013 Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.com>
+
+ GNU Lesser General Public License Usage
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2.1 of the License, or (at your
+ option) any later version.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+ GNU General Public License Usage
+ Alternatively, this library may be used under the terms of the GNU General
+ Public License as published by the Free Software Foundation, either version
+ 2 of the License, or (at your option) any later version.
+ You should have received a copy of the GNU General Public License along with
+ this library. If not, see <http://www.gnu.org/licenses/>.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+*/
+
+#ifndef LIBDEPIXELIZE_TRACER_YUV_H
+#define LIBDEPIXELIZE_TRACER_YUV_H
+
+#include <glib.h>
+
+namespace Tracer {
+namespace colorspace {
+
+/**
+ * The same algorithm used in hqx filter
+ */
+inline void rgb2yuv(guint8 r, guint8 g, guint8 b,
+ guint8 &y, guint8 &u, guint8 &v)
+{
+ y = 0.299 * r + 0.587 * g + 0.114 * b;
+ u = guint16(-0.169 * r - 0.331 * g + 0.5 * b) + 128;
+ v = guint16(0.5 * r - 0.419 * g - 0.081 * b) + 128;
+}
+
+inline void rgb2yuv(const guint8 rgb[], guint8 yuv[])
+{
+ rgb2yuv(rgb[0], rgb[1], rgb[2], yuv[0], yuv[1], yuv[2]);
+}
+
+inline bool same_color(const guint8 (&a)[4], const guint8 (&b)[4])
+{
+ return (a[0] == b[0]
+ && a[1] == b[1]
+ && a[2] == b[2]
+ && a[3] == b[3]);
+}
+
+inline bool dissimilar_colors(const guint8 a[], const guint8 b[])
+{
+ // C uses row-major order, so
+ // A[2][3] = { {1, 2, 3}, {4, 5, 6} } = {1, 2, 3, 4, 5, 6}
+ guint8 yuv[2][3];
+ rgb2yuv(a, yuv[0]);
+ rgb2yuv(b, yuv[1]);
+
+ // Magic numbers taken from hqx algorithm
+ // Only used to describe the level of tolerance
+ return abs(yuv[0][0] - yuv[1][0]) > 0x30
+ || abs(yuv[0][1] - yuv[1][1]) > 7
+ || abs(yuv[0][2] - yuv[1][2]) > 6;
+}
+
+inline bool similar_colors(const guint8 a[], const guint8 b[])
+{
+ return !dissimilar_colors(a, b);
+}
+
+inline bool shading_edge(const guint8 a[], const guint8 b[])
+{
+ // C uses row-major order, so
+ // A[2][3] = { {1, 2, 3}, {4, 5, 6} } = {1, 2, 3, 4, 5, 6}
+ guint8 yuv[2][3];
+ rgb2yuv(a, yuv[0]);
+ rgb2yuv(b, yuv[1]);
+
+ // Magic numbers taken from Kopf-Lischinski algorithm
+ // Only used to describe the level of tolerance
+ return abs(yuv[0][0] - yuv[1][0]) <= 100
+ && abs(yuv[0][1] - yuv[1][1]) <= 100
+ && abs(yuv[0][2] - yuv[1][2]) <= 100;
+}
+
+inline bool contour_edge(const guint8 a[], const guint8 b[])
+{
+ return !shading_edge(a, b);
+}
+
+} // namespace colorspace
+} // namespace Tracer
+
+#endif // LIBDEPIXELIZE_TRACER_YUV_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/libdepixelize/priv/curvature.h b/src/3rdparty/libdepixelize/priv/curvature.h
new file mode 100644
index 0000000..3a1af41
--- /dev/null
+++ b/src/3rdparty/libdepixelize/priv/curvature.h
@@ -0,0 +1,115 @@
+/* This file is part of the libdepixelize project
+ Copyright (C) 2013 Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.com>
+
+ GNU Lesser General Public License Usage
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2.1 of the License, or (at your
+ option) any later version.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+ GNU General Public License Usage
+ Alternatively, this library may be used under the terms of the GNU General
+ Public License as published by the Free Software Foundation, either version
+ 2 of the License, or (at your option) any later version.
+ You should have received a copy of the GNU General Public License along with
+ this library. If not, see <http://www.gnu.org/licenses/>.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+*/
+
+#ifndef LIBDEPIXELIZE_TRACER_CURVATURE_H
+#define LIBDEPIXELIZE_TRACER_CURVATURE_H
+
+#include "point.h"
+#include <cmath>
+
+namespace Tracer {
+
+/**
+ * Curvature function for a quadratic Bézier curve where the points are know.
+ * Its main use is to numerically integrate the curvature function and then
+ * smooth the B-Splines generated by the Kopf-Lischinski algorithm.
+ */
+template<class T>
+struct Curvature
+{
+ Curvature(Point<T> p0, Point<T> c1, Point<T> p2) :
+ p0(p0), c1(c1), p2(p2)
+ {}
+
+ T operator()(T t) const;
+
+ /**
+ * The derivative of x
+ */
+ T xPrime(T t) const;
+
+ /**
+ * The derivative of y
+ */
+ T yPrime(T t) const;
+
+ /**
+ * The second derivative of x
+ */
+ T xPrimePrime() const;
+
+ /**
+ * The second derivative of y
+ */
+ T yPrimePrime() const;
+
+ Point<T> p0, c1, p2;
+};
+
+template<class T>
+T Curvature<T>::operator()(T t) const
+{
+ T num = xPrime(t) * yPrimePrime() - yPrime(t) * xPrimePrime();
+ T den = std::pow(xPrime(t) * xPrime(t) + yPrime(t) * yPrime(t), T(3) / 2);
+ return num / den;
+}
+
+template<class T>
+T Curvature<T>::xPrime(T t) const
+{
+ return (1-t)*2*(c1.x-p0.x) + t*2*(p2.x-c1.x);
+}
+
+template<class T>
+T Curvature<T>::yPrime(T t) const
+{
+ return (1-t)*2*(c1.y-p0.y) + t*2*(p2.y-c1.y);
+}
+
+template<class T>
+T Curvature<T>::xPrimePrime() const
+{
+ return 2 * (p2.x - 2*c1.x + p0.x);
+}
+
+template<class T>
+T Curvature<T>::yPrimePrime() const
+{
+ return 2 * (p2.y - 2*c1.y + p0.y);
+}
+
+} // namespace Tracer
+
+#endif // LIBDEPIXELIZE_TRACER_CURVATURE_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/libdepixelize/priv/homogeneoussplines.h b/src/3rdparty/libdepixelize/priv/homogeneoussplines.h
new file mode 100644
index 0000000..6c4894d
--- /dev/null
+++ b/src/3rdparty/libdepixelize/priv/homogeneoussplines.h
@@ -0,0 +1,472 @@
+/* This file is part of the libdepixelize project
+ Copyright (C) 2013 Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.com>
+
+ GNU Lesser General Public License Usage
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2.1 of the License, or (at your
+ option) any later version.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+ GNU General Public License Usage
+ Alternatively, this library may be used under the terms of the GNU General
+ Public License as published by the Free Software Foundation, either version
+ 2 of the License, or (at your option) any later version.
+ You should have received a copy of the GNU General Public License along with
+ this library. If not, see <http://www.gnu.org/licenses/>.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+*/
+
+#ifndef LIBDEPIXELIZE_TRACER_HOMOGENEOUSSPLINES_H
+#define LIBDEPIXELIZE_TRACER_HOMOGENEOUSSPLINES_H
+
+#include "simplifiedvoronoi.h"
+#include "point.h"
+#include <algorithm>
+#include <utility>
+
+namespace Tracer {
+
+template<typename T>
+class HomogeneousSplines
+{
+public:
+ struct Polygon
+ {
+ typedef std::vector< Point<T> > Points;
+ typedef typename Points::iterator points_iter;
+ typedef typename Points::const_iterator const_points_iter;
+ typedef typename std::vector<Points>::iterator holes_iter;
+ typedef typename std::vector<Points>::const_iterator const_holes_iter;
+
+ Polygon() {}
+ Polygon(const guint8 (&rgba)[4])
+ {
+ for ( int i = 0 ; i != 4 ; ++i )
+ this->rgba[i] = rgba[i];
+ }
+
+ std::vector< Point<T> > vertices;
+
+ /**
+ * It may be benefited from C++11 move references.
+ */
+ std::vector< std::vector< Point<T> > > holes;
+
+ guint8 rgba[4];
+ };
+
+ typedef typename std::vector<Polygon>::iterator iterator;
+ typedef typename std::vector<Polygon>::const_iterator const_iterator;
+ typedef typename std::vector<Polygon>::size_type size_type;
+
+ template<bool adjust_splines>
+ HomogeneousSplines(const SimplifiedVoronoi<T, adjust_splines> &voronoi);
+
+ // Iterators
+ iterator begin()
+ {
+ return _polygons.begin();
+ }
+
+ const_iterator begin() const
+ {
+ return _polygons.begin();
+ }
+
+ iterator end()
+ {
+ return _polygons.end();
+ }
+
+ const_iterator end() const
+ {
+ return _polygons.end();
+ }
+
+ size_type size() const
+ {
+ return _polygons.size();
+ }
+
+ int width() const
+ {
+ return _width;
+ }
+
+ int height() const
+ {
+ return _height;
+ }
+
+private:
+ typedef std::vector< Point<T> > Points;
+ typedef typename Points::iterator points_iter;
+ typedef typename Points::const_iterator points_citer;
+ typedef typename Points::reverse_iterator points_riter;
+ typedef typename Points::const_reverse_iterator points_criter;
+
+ typedef std::pair<points_iter, points_iter> points_range;
+ typedef std::pair<points_citer, points_citer> points_crange;
+
+ struct CommonEdge
+ {
+ bool ok; //< share an edge
+ Points *dst;
+ const Points *src;
+
+ // the interval is closed on both ends
+ // different from [begin, end) STL style
+ points_iter dst_begin, dst_end;
+ points_citer src_begin, src_end;
+ };
+
+ struct SelfCommonEdge
+ {
+ bool ok; //< share an edge
+
+ // Greater range. The one that should be erased from the vector.
+ points_riter grt_begin, grt_end;
+
+ // Smaller range. The one that should be used to create a new vector.
+ points_riter sml_begin, sml_end;
+ };
+
+ /**
+ * Return ok == true if they share an edge (more than one point).
+ */
+ CommonEdge _common_edge(Points &dst, const Points &src);
+
+ /**
+ * Return ok == true if they share an edge (more than one point).
+ *
+ * - [dst_begin, dst_end) will contain the hole polygon
+ * - [src_begin, src_end) will contain the range to be erased
+ *
+ * It's required to do the search in backward order.
+ */
+ SelfCommonEdge _common_edge(Points &points, points_riter it);
+
+ /*!
+ * Add polygon represented by \p common_edge.src to \p common_edge.dst.
+ */
+ void _polygon_union(CommonEdge common_edge);
+
+ /**
+ * Weird recursive function created to solve the complex problem to fill
+ * polygons holes without the need to store temporaries on the heap nor
+ * changing requirements to some data type that don't invalidate iterators
+ * that point before the current element (maybe I'll write some poetry about
+ * the problem someday).
+ */
+ void _fill_holes(std::vector<Points> &holes, points_iter region_begin,
+ points_iter region_end);
+
+ std::vector<Polygon> _polygons;
+ int _width;
+ int _height;
+};
+
+template<class T>
+template<bool adjust_splines>
+HomogeneousSplines<T>::HomogeneousSplines(const SimplifiedVoronoi<T,
+ adjust_splines> &voronoi) :
+ _width(voronoi.width()),
+ _height(voronoi.height())
+{
+ //if (!voronoi.size())
+ // return;
+ using colorspace::same_color;
+
+ typedef typename SimplifiedVoronoi<T, adjust_splines>::const_iterator
+ voronoi_citer;
+
+ // Identify visible edges (group polygons with the same color)
+ for ( voronoi_citer cell_it = voronoi.begin(), cell_end = voronoi.end()
+ ; cell_it != cell_end ; ++cell_it ) {
+ bool found = false;
+ for ( iterator polygon_it = _polygons.begin(),
+ polygon_end = _polygons.end()
+ ; polygon_it != polygon_end ; ++polygon_it ) {
+ if ( same_color(polygon_it->rgba, cell_it->rgba) ) {
+ CommonEdge common_edge = _common_edge(polygon_it->vertices,
+ cell_it->vertices);
+ if ( common_edge.ok ) {
+ _polygon_union(common_edge);
+ found = true;
+
+ for ( iterator polygon2_it = polygon_it + 1
+ ; polygon2_it != polygon_end ; ++polygon2_it ) {
+ if ( same_color(polygon_it->rgba, polygon2_it->rgba) ) {
+ CommonEdge common_edge2
+ = _common_edge(polygon_it->vertices,
+ polygon2_it->vertices);
+ if ( common_edge2.ok ) {
+ _polygon_union(common_edge2);
+ _polygons.erase(polygon2_it);
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+ }
+ }
+ if ( !found ) {
+ Polygon polygon(cell_it->rgba);
+ polygon.vertices = cell_it->vertices;
+ _polygons.insert(_polygons.end(), polygon);
+ }
+ }
+
+ // Find polygons with holes and fix them
+ // This iteration runs such complex time-consuming algorithm, but each
+ // polygon has an independent result. They wouldn't even need to share/sync
+ // results and the only waste would be a join at the end of the for.
+ for ( typename std::vector<Polygon>::iterator it = _polygons.begin(),
+ end = _polygons.end() ; it != end ; ++it ) {
+ SelfCommonEdge ce = _common_edge(it->vertices, it->vertices.rbegin());
+ while ( ce.ok ) {
+ _fill_holes(it->holes, ce.sml_end.base(), ce.sml_begin.base());
+ it->vertices.erase(ce.grt_end.base() + 1, ce.grt_begin.base());
+ ce = _common_edge(it->vertices, ce.grt_end);
+ }
+ }
+}
+
+// it can infinite loop if points of both entities are equal,
+// but this shouldn't happen if user has only access to Kopf2011 interface
+template<class T>
+typename HomogeneousSplines<T>::CommonEdge
+HomogeneousSplines<T>::_common_edge(Points &dst, const Points &src)
+{
+ // It's an edge, then the points are closer together. After we find the
+ // first point, there is no need for check against all points of the src
+ // a second time
+
+ const points_iter dst_begin = dst.begin();
+ const points_iter dst_end = dst.end();
+
+ const points_citer src_begin = src.begin();
+ const points_citer src_end = src.end();
+
+ for ( points_iter it = dst_begin ; it != dst_end ; ++it ) {
+ points_citer src_it = std::find(src_begin, src_end, *it);
+
+ if ( src_it == src_end )
+ continue;
+
+ points_iter dst_common_edge_begin = it;
+ points_citer src_common_edge_end = src_it;
+
+ // iterate until find the beginning of the common edge range
+ while ( *dst_common_edge_begin == *src_common_edge_end ) {
+ if ( dst_common_edge_begin == dst_begin )
+ dst_common_edge_begin = dst_end - 1;
+ else
+ --dst_common_edge_begin;
+
+ ++src_common_edge_end;
+ if ( src_common_edge_end == src_end )
+ src_common_edge_end = src_begin;
+ }
+
+ // fix {dst_begin, src_end} range
+ ++dst_common_edge_begin;
+ if ( dst_common_edge_begin == dst_end )
+ dst_common_edge_begin = dst_begin;
+
+ if ( src_common_edge_end == src_begin )
+ src_common_edge_end = src_end - 1;
+ else
+ --src_common_edge_end;
+
+ points_iter dst_common_edge_end = it;
+ points_citer src_common_edge_begin = src_it;
+
+ // find the end of the common edge range
+ while ( *dst_common_edge_end == *src_common_edge_begin ) {
+ ++dst_common_edge_end;
+ if ( dst_common_edge_end == dst_end )
+ dst_common_edge_end = dst_begin;
+
+ if ( src_common_edge_begin == src_begin )
+ src_common_edge_begin = src_end - 1;
+ else
+ --src_common_edge_begin;
+ }
+
+ // fix {dst_end, src_begin} range
+ if ( dst_common_edge_end == dst_begin )
+ dst_common_edge_end = dst_end - 1;
+ else
+ --dst_common_edge_end;
+
+ ++src_common_edge_begin;
+ if ( src_common_edge_begin == src_end )
+ src_common_edge_begin = src_begin;
+
+ CommonEdge ret;
+
+ // if only one point in common
+ if ( dst_common_edge_begin == dst_common_edge_end )
+ continue;
+
+ ret.ok = true;
+
+ ret.dst = &dst;
+ ret.dst_begin = dst_common_edge_begin;
+ ret.dst_end = dst_common_edge_end;
+
+ ret.src = &src;
+ ret.src_begin = src_common_edge_begin;
+ ret.src_end = src_common_edge_end;
+
+ return ret;
+ }
+
+ CommonEdge ret;
+ ret.ok = false;
+ return ret;
+}
+
+template<class T>
+typename HomogeneousSplines<T>::SelfCommonEdge
+HomogeneousSplines<T>::_common_edge(Points &points, points_riter it)
+{
+ SelfCommonEdge ret;
+
+ ret.grt_end = points.rend();
+
+ for ( ; it != ret.grt_end ; ++it ) {
+ ret.sml_end = std::find(it + 1, ret.grt_end, *it);
+
+ if ( ret.sml_end == ret.grt_end )
+ continue;
+
+ ret.grt_begin = it;
+ ret.grt_end = ret.sml_end + 1;
+
+ ret.sml_begin = it;
+
+ while ( *ret.sml_begin == *ret.sml_end ) {
+ ++ret.sml_begin;
+ --ret.sml_end;
+ }
+
+ --ret.sml_begin;
+ ++ret.sml_end;
+ ++ret.sml_end;
+
+ ret.ok = true;
+ return ret;
+ }
+
+ ret.ok = false;
+ return ret;
+}
+
+template<class T>
+void HomogeneousSplines<T>::_polygon_union(CommonEdge common_edge)
+{
+ Points &dst = *common_edge.dst;
+ const Points &src = *common_edge.src;
+
+ // the rotated cell must be inserted before (dst.begin() + index)
+ typename Points::difference_type index;
+
+ // first, we remove the common edge in dst
+ if ( common_edge.dst_begin < common_edge.dst_end ) {
+ // common edge is in the middle of dst
+
+ index = dst.erase(common_edge.dst_begin,
+ common_edge.dst_end + 1) - dst.begin();
+ } else {
+ // common edge cross the end of dst
+
+ dst.erase(common_edge.dst_begin, dst.end());
+ dst.erase(dst.begin(), common_edge.dst_end);
+ index = dst.end() - dst.begin();
+ }
+
+ // second, we copy src points to polygon
+ if ( common_edge.src_begin < common_edge.src_end ) {
+ // common edge is in the middle of src
+
+ const typename Points::difference_type nfirstinserted
+ = src.end() - common_edge.src_end;
+ const typename Points::difference_type nsecondinserted
+ = 1 + (common_edge.src_begin - src.begin());
+
+ dst.reserve(dst.size() + nfirstinserted + nsecondinserted);
+
+ dst.insert(dst.begin() + index, common_edge.src_end, src.end());
+
+ dst.insert(dst.begin() + index + nfirstinserted,
+ src.begin(), common_edge.src_begin + 1);
+ } else {
+ // common edge cross the end of src
+
+ dst.reserve(dst.size() + 1
+ + (common_edge.src_begin - common_edge.src_end));
+
+ dst.insert(dst.begin() + index,
+ common_edge.src_end, common_edge.src_begin + 1);
+ }
+}
+
+// The following piece of code is so evil that you could end up invoking an
+// ancient beast if you proceed to read it, but I'll be able to explain it in
+// the form of some video (text is not so representative as an image).
+template<class T>
+void HomogeneousSplines<T>::_fill_holes(std::vector<Points> &holes,
+ points_iter region_begin,
+ points_iter region_end)
+{
+ // the exact location might not always be back and iterators will be
+ // invalidated after some insertions, then the index is required
+ const typename std::vector<Points>::size_type hole_index = holes.size();
+ holes.resize(hole_index + 1);
+
+ for ( points_iter it = region_begin + 1 ; it != region_end ; ++it ) {
+ points_iter res = std::find(it + 1, region_end, *it);
+ if ( res == region_end )
+ continue;
+
+ holes[hole_index].insert(holes[hole_index].end(), region_begin,
+ it);
+ region_begin = res;
+
+ do {
+ ++it;
+ --res;
+ } while ( *it == *res );
+ _fill_holes(holes, it - 1, res + 2);
+
+ it = region_begin;
+ }
+
+ holes[hole_index].insert(holes[hole_index].end(), region_begin,
+ region_end - 1);
+}
+
+} // namespace Tracer
+
+#endif // LIBDEPIXELIZE_TRACER_HOMOGENEOUSSPLINES_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/libdepixelize/priv/integral.h b/src/3rdparty/libdepixelize/priv/integral.h
new file mode 100644
index 0000000..fc1a49f
--- /dev/null
+++ b/src/3rdparty/libdepixelize/priv/integral.h
@@ -0,0 +1,61 @@
+/* This file is part of the libdepixelize project
+ Copyright (C) 2013 Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.com>
+
+ GNU Lesser General Public License Usage
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2.1 of the License, or (at your
+ option) any later version.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+ GNU General Public License Usage
+ Alternatively, this library may be used under the terms of the GNU General
+ Public License as published by the Free Software Foundation, either version
+ 2 of the License, or (at your option) any later version.
+ You should have received a copy of the GNU General Public License along with
+ this library. If not, see <http://www.gnu.org/licenses/>.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+*/
+
+#ifndef LIBDEPIXELIZE_TRACER_INTEGRAL_H
+#define LIBDEPIXELIZE_TRACER_INTEGRAL_H
+
+#include <2geom/coord.h>
+
+namespace Tracer {
+
+/**
+ * Compute the integral numerically using Gaussian Quadrature rule with
+ * \p samples number of samples.
+ */
+template<class T, class F>
+Geom::Coord integral(F f, T begin, T end, unsigned samples)
+{
+ T ret = 0;
+ const T width = (end - begin) / samples;
+
+ for ( unsigned i = 0 ; i != samples ; ++i )
+ ret += width * f(begin + width * (i + .5));
+
+ return ret;
+}
+
+} // namespace Tracer
+
+#endif // LIBDEPIXELIZE_TRACER_INTEGRAL_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/libdepixelize/priv/iterator.h b/src/3rdparty/libdepixelize/priv/iterator.h
new file mode 100644
index 0000000..7caa9bf
--- /dev/null
+++ b/src/3rdparty/libdepixelize/priv/iterator.h
@@ -0,0 +1,123 @@
+/* This file is part of the libdepixelize project
+ Copyright (C) 2013 Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.com>
+
+ GNU Lesser General Public License Usage
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2.1 of the License, or (at your
+ option) any later version.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+ GNU General Public License Usage
+ Alternatively, this library may be used under the terms of the GNU General
+ Public License as published by the Free Software Foundation, either version
+ 2 of the License, or (at your option) any later version.
+ You should have received a copy of the GNU General Public License along with
+ this library. If not, see <http://www.gnu.org/licenses/>.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+*/
+
+#ifndef LIBDEPIXELIZE_TRACER_ITERATOR_H
+#define LIBDEPIXELIZE_TRACER_ITERATOR_H
+
+#include <vector>
+#include <iterator>
+
+namespace Tracer {
+
+template<typename T>
+const T *to_ptr(typename std::vector<T>::const_iterator it)
+{
+ return &*it;
+}
+
+template<typename T>
+T *to_ptr(typename std::vector<T>::iterator it)
+{
+ return &*it;
+}
+
+template<typename T>
+typename std::vector<T>::const_iterator to_iterator(T const *ptr,
+ typename std::vector<T>
+ ::const_iterator begin)
+{
+ typedef typename std::vector<T>::const_iterator It;
+ typedef typename std::iterator_traits<It>::difference_type difference_type;
+ difference_type idx = ptr - to_ptr<T>(begin);
+ return begin + idx;
+}
+
+template<typename T>
+typename std::vector<T>::iterator to_iterator(T *ptr,
+ typename std::vector<T>::iterator
+ begin)
+{
+ typedef typename std::vector<T>::iterator It;
+ typedef typename std::iterator_traits<It>::difference_type difference_type;
+ difference_type idx = ptr - to_ptr<T>(begin);
+ return begin + idx;
+}
+
+template<typename T>
+class ToIter
+{
+public:
+ typedef typename std::vector<T>::const_iterator const_iterator;
+ typedef typename std::vector<T>::iterator iterator;
+
+ ToIter(const_iterator begin) :
+ begin(begin)
+ {}
+
+ const_iterator operator()(T const *ptr) const
+ {
+ return to_iterator<T>(ptr, begin);
+ }
+
+ iterator operator()(T *ptr) const
+ {
+ return to_iterator<T>(ptr, begin);
+ }
+
+private:
+ typename std::vector<T>::const_iterator begin;
+};
+
+template<typename T>
+class ToPtr
+{
+public:
+ typedef typename std::vector<T>::const_iterator const_iterator;
+ typedef typename std::vector<T>::iterator iterator;
+
+ const T *operator()(const_iterator it) const
+ {
+ return to_ptr<T>(it);
+ }
+
+ T *operator()(iterator it) const
+ {
+ return to_ptr<T>(it);
+ }
+};
+
+} // namespace Tracer
+
+#endif // LIBDEPIXELIZE_TRACER_ITERATOR_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/libdepixelize/priv/optimization-kopf2011.h b/src/3rdparty/libdepixelize/priv/optimization-kopf2011.h
new file mode 100644
index 0000000..0c9011c
--- /dev/null
+++ b/src/3rdparty/libdepixelize/priv/optimization-kopf2011.h
@@ -0,0 +1,263 @@
+/* This file is part of the libdepixelize project
+ Copyright (C) 2013 Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.com>
+
+ GNU Lesser General Public License Usage
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2.1 of the License, or (at your
+ option) any later version.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+ GNU General Public License Usage
+ Alternatively, this library may be used under the terms of the GNU General
+ Public License as published by the Free Software Foundation, either version
+ 2 of the License, or (at your option) any later version.
+ You should have received a copy of the GNU General Public License along with
+ this library. If not, see <http://www.gnu.org/licenses/>.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+*/
+
+#ifndef LIBDEPIXELIZE_TRACER_OPTIMIZATION_KOPF2011_H
+#define LIBDEPIXELIZE_TRACER_OPTIMIZATION_KOPF2011_H
+
+#include "curvature.h"
+#include "integral.h"
+#include <cmath>
+#include <limits>
+
+namespace Tracer {
+
+/**
+ * m is angular coeficient
+ */
+template<class T>
+bool is_valid_border_m(T a)
+{
+ if ( a < 0 )
+ a *= -1;
+
+ // TODO: alternative behaviour if has no infinity
+ return a == std::numeric_limits<T>::infinity()
+ || a == 3 || a == 1;
+}
+
+/**
+ * Return true if the four points are considered a border.
+ */
+template<class T>
+bool is_border(const Point<T> (&points)[4])
+{
+ T dy[2];
+ T dx[2];
+ T m[2];
+ if ( points[1].y == points[2].y ) {
+ dy[0] = points[1].y - points[0].y;
+ dy[1] = points[3].y - points[2].y;
+
+ dx[0] = points[1].x - points[0].x;
+ dx[1] = points[3].x - points[2].x;
+
+ m[0] = dy[0] / dx[0];
+ m[1] = dy[1] / dx[1];
+ } else if ( points[1].x == points[2].x ) {
+ // It's easier to have a unified logic, then we'll fake dx and dy
+ dy[0] = points[1].x - points[0].x;
+ dy[1] = points[3].x - points[2].x;
+
+ dx[0] = points[1].y - points[0].y;
+ dx[1] = points[3].y - points[2].y;
+
+ m[0] = dy[0] / dx[0];
+ m[1] = dy[1] / dx[1];
+ } else {
+ return false;
+ }
+
+ return m[0] == -m[1] && is_valid_border_m(m[0]);
+}
+
+template<class T>
+typename std::vector< Point<T> >::iterator
+skip1visible(typename std::vector< Point<T> >::iterator it,
+ typename std::vector< Point<T> >::iterator end)
+{
+ for ( ++it ; it != end ; ++it ) {
+ if ( it->visible )
+ return it;
+ }
+ return end;
+}
+
+/**
+ * Return how many elements should be skipped.
+ */
+template<class T>
+typename std::vector< Point<T> >::difference_type
+border_detection(typename std::vector< Point<T> >::iterator it,
+ typename std::vector< Point<T> >::iterator end)
+{
+ typename std::vector< Point<T> >::iterator begin = it;
+
+ if ( end - it < 4 )
+ return 0;
+
+ Point<T> last[4];
+ typename std::vector< Point<T> >::iterator prev = it;
+
+ for ( int i = 0 ; i != 4 ; ++i ) {
+ if ( it == end )
+ return 0;
+ last[i] = *it;
+ prev = it;
+ it = skip1visible<T>(it, end);
+ }
+
+ if ( !is_border(last) )
+ return 0;
+
+ if ( it == end )
+ return prev - begin;
+
+ bool got_another = false;
+ for ( it = skip1visible<T>(it, end) ; it != end
+ ; it = skip1visible<T>(it, end) ) {
+ if ( !got_another ) {
+ last[0] = last[2];
+ last[1] = last[3];
+ last[2] = *it;
+
+ got_another = true;
+ continue;
+ }
+ last[3] = *it;
+
+ if ( !is_border(last) )
+ return prev - begin;
+ prev = it;
+ }
+
+ return prev - begin;
+}
+
+template<class T>
+T smoothness_energy(Point<T> c0, Point<T> c1, Point<T> c2)
+{
+ Point<T> p0 = midpoint(c0, c1);
+ Point<T> p2 = midpoint(c1, c2);
+ Curvature<T> cur(p0, c1, p2);
+
+ return std::abs(integral<T>(cur, 0, 1, 16));
+}
+
+template<class T>
+T positional_energy(Point<T> guess, Point<T> initial)
+{
+ using std::pow;
+
+ return pow(pow(guess.x - initial.x, 2)
+ + pow(guess.y - initial.y, 2), 2);
+}
+
+/**
+ * Kopf-Lischinski simple relaxation procedure: a random new offset position
+ * within a small radius around its current location.
+ *
+ * The small radius is not revealed. I chose the empirically determined value of
+ * 0.125. New tests can give a better value for "small". I believe this value
+ * showed up because the optimization sharply penalize larger deviations.
+ */
+template<class T>
+Point<T> optimization_guess(Point<T> p)
+{
+ // See the value explanation in the function documentation.
+ T radius = 0.125;
+
+ T d[] = {
+ (T(std::rand()) / RAND_MAX) * radius * 2 - radius,
+ (T(std::rand()) / RAND_MAX) * radius * 2 - radius
+ };
+
+ return p + Point<T>(d[0], d[1]);
+}
+
+template<class T>
+std::vector< Point<T> > optimize(const std::vector< Point<T> > &path)
+{
+ typedef std::vector< Point<T> > Path;
+
+ Path ret = path;
+
+ /* The number of vertices not constrained by optimization */
+ unsigned n = 0;
+
+ /* Values chosen by test
+ * TODO: make values configurable via function parameters. */
+ const unsigned iterations = 4;
+ const unsigned nguess_per_iteration = 4;
+
+ for ( unsigned i = 0 ; i != iterations ; ++i ) {
+ n = 0;
+
+ /* This iteration bounds is not something to worry about, because the
+ * smallest path has size 4. */
+ for ( typename Path::size_type j = 0 ; j != ret.size() ; ++j ) {
+ Point<T> prev = ( j == 0 ) ? ret.back() : ret[j-1];
+ Point<T> next = ( j + 1 == ret.size() ) ? ret.front() : ret[j+1] ;
+
+ if ( !ret[j].visible || !ret[j].smooth )
+ continue;
+
+ {
+ typename Path::iterator it = ret.begin() + j;
+ typename Path::difference_type skip
+ = border_detection<T>(it, ret.end());
+ j += skip;
+ if ( j == ret.size() )
+ break;
+ }
+
+ ++n;
+
+ for ( unsigned k = 0 ; k != nguess_per_iteration ; ++k ) {
+ Point<T> guess = optimization_guess(ret[j]);
+
+ T s = smoothness_energy(prev, guess, next);
+ T p = positional_energy(guess, path[j]);
+
+ T e = s + p;
+
+ T prev_e = smoothness_energy(prev, ret[j], next)
+ + positional_energy(ret[j], path[j]);
+
+ if ( prev_e > e ) {
+ // We don't want to screw other metadata, then we manually
+ // assign the new coords
+ ret[j].x = guess.x;
+ ret[j].y = guess.y;
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+} // namespace Tracer
+
+#endif // LIBDEPIXELIZE_TRACER_OPTIMIZATION_KOPF2011_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/libdepixelize/priv/pixelgraph.h b/src/3rdparty/libdepixelize/priv/pixelgraph.h
new file mode 100644
index 0000000..a6e0f1a
--- /dev/null
+++ b/src/3rdparty/libdepixelize/priv/pixelgraph.h
@@ -0,0 +1,555 @@
+/* This file is part of the libdepixelize project
+ Copyright (C) 2013 Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.com>
+
+ GNU Lesser General Public License Usage
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2.1 of the License, or (at your
+ option) any later version.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+ GNU General Public License Usage
+ Alternatively, this library may be used under the terms of the GNU General
+ Public License as published by the Free Software Foundation, either version
+ 2 of the License, or (at your option) any later version.
+ You should have received a copy of the GNU General Public License along with
+ this library. If not, see <http://www.gnu.org/licenses/>.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+*/
+
+#ifndef LIBDEPIXELIZE_TRACER_PIXELGRAPH_H
+#define LIBDEPIXELIZE_TRACER_PIXELGRAPH_H
+
+#include <gdkmm/pixbuf.h>
+#include <vector>
+#include <cassert>
+#include <utility>
+
+namespace Tracer {
+
+class PixelGraph
+{
+public:
+ class Node
+ {
+ public:
+ /*
+ * Hamming weight of \p adj
+ */
+ unsigned adjsize() const
+ {
+ unsigned all[8] = {
+ adj.top,
+ adj.topright,
+ adj.right,
+ adj.bottomright,
+ adj.bottom,
+ adj.bottomleft,
+ adj.left,
+ adj.topleft
+ };
+ return all[0] + all[1] + all[2] + all[3]
+ + all[4] + all[5] + all[6] + all[7];
+ }
+
+ guint8 rgba[4];
+ // Nodes pointing from this
+ struct Adj
+ {
+ unsigned top: 1;
+ unsigned topright: 1;
+ unsigned right: 1;
+ unsigned bottomright: 1;
+ unsigned bottom: 1;
+ unsigned bottomleft: 1;
+ unsigned left: 1;
+ unsigned topleft: 1;
+ } adj;
+ };
+
+ typedef std::vector<Node>::iterator iterator;
+ typedef std::vector<Node>::const_iterator const_iterator;
+ typedef std::vector<Node>::reverse_iterator reverse_iterator;
+ typedef std::vector<Node>::const_reverse_iterator const_reverse_iterator;
+
+ typedef std::pair<iterator, iterator> Edge;
+ typedef std::pair<Edge, Edge> EdgePair;
+ typedef std::vector<EdgePair> EdgePairContainer;
+
+ class ColumnView
+ {
+ public:
+ ColumnView(std::vector<Node> &nodes, int width, int column) :
+ _nodes(nodes), _width(width), _column(column)
+ {}
+
+ Node &operator[](int line);
+
+ private:
+ std::vector<Node> &_nodes;
+ const int _width;
+ const int _column;
+ };
+
+ PixelGraph(Glib::RefPtr<Gdk::Pixbuf const> pixbuf);
+
+ void checkConsistency();
+
+ /**
+ * It'll let you access the nodes using the syntax:
+ *
+ * graph[x][y]
+ *
+ * Where x is the column and y is the line.
+ */
+ ColumnView operator[](int column);
+
+ // Iterators
+ iterator begin()
+ {
+ return _nodes.begin();
+ }
+
+ const_iterator begin() const
+ {
+ return _nodes.begin();
+ }
+
+ iterator end()
+ {
+ return _nodes.end();
+ }
+
+ const_iterator end() const
+ {
+ return _nodes.end();
+ }
+
+ reverse_iterator rbegin()
+ {
+ return _nodes.rbegin();
+ }
+
+ const_reverse_iterator rbegin() const
+ {
+ return _nodes.rbegin();
+ }
+
+ reverse_iterator rend()
+ {
+ return _nodes.rend();
+ }
+
+ const_reverse_iterator rend() const
+ {
+ return _nodes.rend();
+ }
+
+ size_t size() const
+ {
+ return _nodes.size();
+ }
+
+ int width() const
+ {
+ return _width;
+ }
+
+ int height() const
+ {
+ return _height;
+ }
+
+ // Algorithms
+ void connectAllNeighbors();
+ EdgePairContainer crossingEdges();
+
+ int toX(const_iterator n) const
+ {
+ return (&*n - &_nodes[0]) % _width;
+ }
+
+ int toY(const_iterator n) const
+ {
+ return (&*n - &_nodes[0]) / _width;
+ }
+
+ iterator nodeTop(iterator n)
+ {
+ return n - _width;
+ }
+
+ iterator nodeBottom(iterator n)
+ {
+ return n + _width;
+ }
+
+ iterator nodeLeft(iterator n)
+ {
+ return n - 1;
+ }
+
+ iterator nodeRight(iterator n)
+ {
+ return n + 1;
+ }
+
+ iterator nodeTopLeft(iterator n)
+ {
+ return n - _width - 1;
+ }
+
+ iterator nodeTopRight(iterator n)
+ {
+ return n - _width + 1;
+ }
+
+ iterator nodeBottomLeft(iterator n)
+ {
+ return n + _width - 1;
+ }
+
+ iterator nodeBottomRight(iterator n)
+ {
+ return n + _width + 1;
+ }
+
+ const_iterator nodeTop(const_iterator n) const
+ {
+ return n - _width;
+ }
+
+ const_iterator nodeBottom(const_iterator n) const
+ {
+ return n + _width;
+ }
+
+ const_iterator nodeLeft(const_iterator n) const
+ {
+ return n - 1;
+ }
+
+ const_iterator nodeRight(const_iterator n) const
+ {
+ return n + 1;
+ }
+
+ const_iterator nodeTopLeft(const_iterator n) const
+ {
+ return n - _width - 1;
+ }
+
+ const_iterator nodeTopRight(const_iterator n) const
+ {
+ return n - _width + 1;
+ }
+
+ const_iterator nodeBottomLeft(const_iterator n) const
+ {
+ return n + _width - 1;
+ }
+
+ const_iterator nodeBottomRight(const_iterator n) const
+ {
+ return n + _width + 1;
+ }
+
+private:
+ PixelGraph(const PixelGraph&);
+
+ int _width;
+ int _height;
+
+ // The data representation follows the image data pattern from gdk-pixbuf.
+ //
+ // Quoting:
+ // "Image data in a pixbuf is stored in memory in uncompressed, packed
+ // format. Rows in the image are stored top to bottom, and in each row
+ // pixels are stored from left to right. There may be padding at the end of
+ // a row."
+ //
+ // Differently, _nodes don't put padding among rows.
+ std::vector<Node> _nodes;
+};
+
+inline PixelGraph::PixelGraph(Glib::RefPtr<Gdk::Pixbuf const> pixbuf) :
+ _width(pixbuf->get_width()),
+ _height(pixbuf->get_height()),
+ _nodes(size_t(_width) * _height)
+{
+ if ( !_width || !_height )
+ return;
+
+ // Initialize the graph using the pixels' color data
+ guint8 const *pixels = pixbuf->get_pixels();
+ Node *dest = &_nodes[0];
+ const int n_channels = pixbuf->get_n_channels();
+ const int rowpadding = pixbuf->get_rowstride() - _width * n_channels;
+
+ if ( n_channels == 4 ) {
+ for ( int i = 0 ; i != _height ; ++i ) {
+ for ( int j = 0 ; j != _width ; ++j ) {
+ for ( int k = 0 ; k != 4 ; ++k )
+ dest->rgba[k] = pixels[k];
+ {
+ dest->adj.top = 0;
+ dest->adj.topright = 0;
+ dest->adj.right = 0;
+ dest->adj.bottomright = 0;
+ dest->adj.bottom = 0;
+ dest->adj.bottomleft = 0;
+ dest->adj.left = 0;
+ dest->adj.topleft = 0;
+ }
+ pixels += n_channels;
+ ++dest;
+ }
+ pixels += rowpadding;
+ }
+ } else {
+ assert(n_channels == 3);
+ for ( int i = 0 ; i != _height ; ++i ) {
+ for ( int j = 0 ; j != _width ; ++j ) {
+ for ( int k = 0 ; k != 3 ; ++k )
+ dest->rgba[k] = pixels[k];
+ dest->rgba[3] = '\xFF';
+ {
+ dest->adj.top = 0;
+ dest->adj.topright = 0;
+ dest->adj.right = 0;
+ dest->adj.bottomright = 0;
+ dest->adj.bottom = 0;
+ dest->adj.bottomleft = 0;
+ dest->adj.left = 0;
+ dest->adj.topleft = 0;
+ }
+ pixels += n_channels;
+ ++dest;
+ }
+ pixels += rowpadding;
+ }
+ }
+}
+
+inline void PixelGraph::checkConsistency()
+{
+ PixelGraph::Node *it = &_nodes.front();
+ for ( int i = 0 ; i != _height ; ++i ) {
+ for ( int j = 0 ; j != _width ; ++j, ++it ) {
+ if ( it->adj.top )
+ assert((it - _width)->adj.bottom);
+ if ( it->adj.topright )
+ assert((it - _width + 1)->adj.bottomleft);
+ if ( it->adj.right )
+ assert((it + 1)->adj.left);
+ if ( it->adj.bottomright )
+ assert((it + _width + 1)->adj.topleft);
+ if ( it->adj.bottom )
+ assert((it + _width)->adj.top);
+ if ( it->adj.bottomleft )
+ assert((it + _width - 1)->adj.topright);
+ if ( it->adj.left )
+ assert((it - 1)->adj.right);
+ if ( it->adj.topleft )
+ assert((it - _width - 1)->adj.bottomright);
+ }
+ }
+}
+
+inline PixelGraph::ColumnView PixelGraph::operator[](int column)
+{
+ return ColumnView(_nodes, _width, column);
+}
+
+inline void PixelGraph::connectAllNeighbors()
+{
+ // ...the "center" nodes first...
+ if ( _width > 2 && _height > 2 ) {
+ iterator it = nodeBottomRight(begin()); // [1][1]
+ for ( int i = 1 ; i != _height - 1 ; ++i ) {
+ for ( int j = 1 ; j != _width - 1 ; ++j ) {
+ it->adj.top = 1;
+ it->adj.topright = 1;
+ it->adj.right = 1;
+ it->adj.bottomright = 1;
+ it->adj.bottom = 1;
+ it->adj.bottomleft = 1;
+ it->adj.left = 1;
+ it->adj.topleft = 1;
+
+ it = nodeRight(it);
+ }
+ // After the previous loop, 'it' is pointing to the last node from
+ // the row.
+ // Go south, then first node in the row (increment 'it' by 1)
+ // Go to the second node in the line (increment 'it' by 1)
+ it += 2;
+ }
+ }
+
+ // ...then the "top" nodes...
+ if ( _width > 2 ) {
+ Node *it = &_nodes[1];
+ if ( _height > 1 ) {
+ for ( int i = 1 ; i != _width - 1 ; ++i ) {
+ it->adj.right = 1;
+ it->adj.bottomright = 1;
+ it->adj.bottom = 1;
+ it->adj.bottomleft = 1;
+ it->adj.left = 1;
+
+ ++it;
+ }
+ } else {
+ for ( int i = 1 ; i != _width - 1 ; ++i ) {
+ it->adj.right = 1;
+ it->adj.left = 1;
+
+ ++it;
+ }
+ }
+ }
+
+ // ...then the "bottom" nodes...
+ if ( _width > 2 && _height > 1 ) {
+ Node *it = &((*this)[1][_height - 1]);
+ for ( int i = 1 ; i != _width - 1 ; ++i ) {
+ it->adj.left = 1;
+ it->adj.topleft = 1;
+ it->adj.top = 1;
+ it->adj.topright = 1;
+ it->adj.right = 1;
+
+ ++it;
+ }
+ }
+
+ // ...then the "left" nodes...
+ if ( _height > 2 ) {
+ iterator it = nodeBottom(begin()); // [0][1]
+ if ( _width > 1 ) {
+ for ( int i = 1 ; i != _height - 1 ; ++i ) {
+ it->adj.top = 1;
+ it->adj.topright = 1;
+ it->adj.right = 1;
+ it->adj.bottomright = 1;
+ it->adj.bottom = 1;
+
+ it = nodeBottom(it);
+ }
+ } else {
+ for ( int i = 1 ; i != _height - 1 ; ++i ) {
+ it->adj.top = 1;
+ it->adj.bottom = 1;
+
+ it = nodeBottom(it);
+ }
+ }
+ }
+
+ // ...then the "right" nodes...
+ if ( _height > 2 && _width > 1 ) {
+ iterator it = nodeBottom(begin() + _width - 1);// [_width - 1][1]
+ for ( int i = 1 ; i != _height - 1 ; ++i ) {
+ it->adj.bottom = 1;
+ it->adj.bottomleft = 1;
+ it->adj.left = 1;
+ it->adj.topleft = 1;
+ it->adj.top = 1;
+
+ it = nodeBottom(it);
+ }
+ }
+
+ // ...and the 4 corner nodes
+ {
+ Node *const top_left = &(*this)[0][0];
+
+ if ( _width > 1 )
+ top_left->adj.right = 1;
+
+ if ( _width > 1 && _height > 1 )
+ top_left->adj.bottomright = 1;
+
+ if ( _height > 1 )
+ top_left->adj.bottom = 1;
+ }
+ if ( _width > 1 ) {
+ Node *const top_right = &(*this)[_width - 1][0];
+
+ if ( _height > 1 ) {
+ top_right->adj.bottom = 1;
+ top_right->adj.bottomleft = 1;
+ }
+
+ top_right->adj.left = 1;
+ }
+ if ( _height > 1 ) {
+ Node *const down_left = &(*this)[0][_height - 1];
+ down_left->adj.top = 1;
+
+ if ( _width > 1 ) {
+ down_left->adj.topright = 1;
+ down_left->adj.right = 1;
+ }
+ }
+ if ( _width > 1 && _height > 1 ) {
+ Node *const down_right = &(*this)[_width - 1][_height - 1];
+ down_right->adj.left = 1;
+ down_right->adj.topleft = 1;
+ down_right->adj.top = 1;
+ }
+}
+
+PixelGraph::EdgePairContainer PixelGraph::crossingEdges()
+{
+ EdgePairContainer ret;
+
+ if ( width() < 2 || height() < 2 )
+ return ret;
+
+ // Iterate over the graph, 2x2 blocks at time
+ PixelGraph::iterator it = begin();
+ for (int i = 0 ; i != height() - 1 ; ++i, ++it ) {
+ for ( int j = 0 ; j != width() - 1 ; ++j, ++it ) {
+ EdgePair diagonals(
+ Edge(it, nodeBottomRight(it)),
+ Edge(nodeRight(it), nodeBottom(it)));
+
+ // Check if there are crossing edges
+ if ( !diagonals.first.first->adj.bottomright
+ || !diagonals.second.first->adj.bottomleft ) {
+ continue;
+ }
+
+ ret.push_back(diagonals);
+ }
+ }
+
+ return ret;
+}
+
+inline PixelGraph::Node &PixelGraph::ColumnView::operator[](int line)
+{
+ return _nodes[line * _width + _column];
+}
+
+} // namespace Tracer
+
+#endif // LIBDEPIXELIZE_TRACER_PIXELGRAPH_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/libdepixelize/priv/point.h b/src/3rdparty/libdepixelize/priv/point.h
new file mode 100644
index 0000000..53babd9
--- /dev/null
+++ b/src/3rdparty/libdepixelize/priv/point.h
@@ -0,0 +1,112 @@
+/* This file is part of the libdepixelize project
+ Copyright (C) 2013 Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.com>
+
+ GNU Lesser General Public License Usage
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2.1 of the License, or (at your
+ option) any later version.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+ GNU General Public License Usage
+ Alternatively, this library may be used under the terms of the GNU General
+ Public License as published by the Free Software Foundation, either version
+ 2 of the License, or (at your option) any later version.
+ You should have received a copy of the GNU General Public License along with
+ this library. If not, see <http://www.gnu.org/licenses/>.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+*/
+
+#ifndef LIBDEPIXELIZE_TRACER_POINT_H
+#define LIBDEPIXELIZE_TRACER_POINT_H
+
+namespace Tracer {
+
+template<class T>
+struct Point
+{
+ Point() : smooth(false), visible(true) {}
+ Point(T x, T y) : smooth(false), visible(true), x(x), y(y) {}
+ Point(T x, T y, bool smooth) : smooth(smooth), visible(true), x(x), y(y) {}
+
+ Point operator+(const Point &rhs) const
+ {
+ return Point(x + rhs.x, y + rhs.y);
+ }
+
+ Point operator/(T foo) const
+ {
+ return Point(x / foo, y / foo);
+ }
+
+ Point invisible() const
+ {
+ Point p = *this;
+ p.visible = false;
+ return p;
+ }
+
+ bool smooth;
+
+ /**
+ * By default, all points are visible, but the poor amount of information
+ * that B-Splines (libdepixelize-specific) allows us to represent forces us
+ * to create additional points. But... these additional points don't need to
+ * be visible.
+ */
+ bool visible;
+
+ T x, y;
+};
+
+template<class T>
+Point<T> midpoint(const Point<T> &a, const Point<T> &b)
+{
+ return Point<T>((a.x + b.x) / 2, (a.y + b.y) / 2);
+}
+
+template<class T>
+bool operator==(const Point<T> &lhs, const Point<T> &rhs)
+{
+ return
+ /*
+ * Will make a better job identifying which points can be eliminated by
+ * cells union.
+ */
+#ifndef LIBDEPIXELIZE_IS_VERY_WELL_TESTED
+ lhs.smooth == rhs.smooth &&
+#endif // LIBDEPIXELIZE_IS_VERY_WELL_TESTED
+ lhs.x == rhs.x && lhs.y == rhs.y;
+}
+
+template<class T>
+bool weakly_equal(const Point<T> &a, const Point<T> &b)
+{
+ return a.x == b.x && a.y == b.y;
+}
+
+template<class T>
+Geom::Point to_geom_point(Point<T> p)
+{
+ return Geom::Point(p.x, p.y);
+}
+
+} // namespace Tracer
+
+#endif // LIBDEPIXELIZE_TRACER_POINT_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/libdepixelize/priv/simplifiedvoronoi.h b/src/3rdparty/libdepixelize/priv/simplifiedvoronoi.h
new file mode 100644
index 0000000..84feab0
--- /dev/null
+++ b/src/3rdparty/libdepixelize/priv/simplifiedvoronoi.h
@@ -0,0 +1,1707 @@
+/* This file is part of the libdepixelize project
+ Copyright (C) 2013 Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.com>
+
+ GNU Lesser General Public License Usage
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2.1 of the License, or (at your
+ option) any later version.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+ GNU General Public License Usage
+ Alternatively, this library may be used under the terms of the GNU General
+ Public License as published by the Free Software Foundation, either version
+ 2 of the License, or (at your option) any later version.
+ You should have received a copy of the GNU General Public License along with
+ this library. If not, see <http://www.gnu.org/licenses/>.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+*/
+
+#ifndef LIBDEPIXELIZE_TRACER_SIMPLIFIEDVORONOI_H
+#define LIBDEPIXELIZE_TRACER_SIMPLIFIEDVORONOI_H
+
+#include "pixelgraph.h"
+#include "colorspace.h"
+#include "point.h"
+#include "branchless.h"
+
+namespace Tracer {
+
+template<typename T, bool adjust_splines>
+class SimplifiedVoronoi
+{
+public:
+ /**
+ * The "smooth" attribute of each vertex is only accurate if edge is
+ * visible. This decision was made because invisible edges will disappear
+ * during polygon-union, the next phase of Kopf-Lischinski.
+ */
+ struct Cell
+ {
+ // There may not exist more than 8 vertices per cell and a
+ // "small vector optimization" could improve the performance
+ // by avoiding memory fragmentation. Serious testing is needed.
+
+ // The vertices are filled in clockwise order
+ std::vector< Point<T> > vertices;
+ guint8 rgba[4];
+ };
+
+ typedef typename std::vector<Cell>::iterator iterator;
+ typedef typename std::vector<Cell>::const_iterator const_iterator;
+ typedef typename std::vector<Cell>::reverse_iterator reverse_iterator;
+
+ typedef typename std::vector<Cell>::const_reverse_iterator
+ const_reverse_iterator;
+
+ /*
+ It will work correctly if no crossing-edges are present.
+ */
+ SimplifiedVoronoi(const PixelGraph &graph);
+
+ // Iterators
+ iterator begin()
+ {
+ return _cells.begin();
+ }
+
+ const_iterator begin() const
+ {
+ return _cells.begin();
+ }
+
+ iterator end()
+ {
+ return _cells.end();
+ }
+
+ const_iterator end() const
+ {
+ return _cells.end();
+ }
+
+ reverse_iterator rbegin()
+ {
+ return _cells.rbegin();
+ }
+
+ const_reverse_iterator rbegin() const
+ {
+ return _cells.rbegin();
+ }
+
+ reverse_iterator rend()
+ {
+ return _cells.rend();
+ }
+
+ const_reverse_iterator rend() const
+ {
+ return _cells.rend();
+ }
+
+ size_t size() const
+ {
+ return _cells.size();
+ }
+
+ int width() const
+ {
+ return _width;
+ }
+
+ int height() const
+ {
+ return _height;
+ }
+
+private:
+#ifdef LIBDEPIXELIZE_VERY_TYPE_SAFE
+ typedef void (*PointTransform)(Point<T> &p, T dx, T dy);
+ typedef bool (*NodeTransform)(PixelGraph::const_iterator);
+#endif // LIBDEPIXELIZE_VERY_TYPE_SAFE
+
+ /**
+ * Output is translated by -.5 in each axis. This function fixes this error.
+ */
+ static Point<T> _adjust(Point<T> p)
+ {
+ return Point<T>(p.x + .5, p.y + .5);
+ }
+
+ /**
+ * Output is translated by -.5 in each axis. This function fixes this error.
+ */
+ static Point<T> _adjust(Point<T> p, bool smooth)
+ {
+ return Point<T>(p.x + .5, p.y + .5, smooth);
+ }
+
+ void _complexTopLeft(const PixelGraph &graph,
+ PixelGraph::const_iterator graph_it,
+ Cell *const cells_it, int x, int y);
+ void _complexTopRight(const PixelGraph &graph,
+ PixelGraph::const_iterator graph_it,
+ Cell *const cells_it, int x, int y);
+ void _complexBottomRight(const PixelGraph &graph,
+ PixelGraph::const_iterator graph_it,
+ Cell *const cells_it, int x, int y);
+ void _complexBottomLeft(const PixelGraph &graph,
+ PixelGraph::const_iterator graph_it,
+ Cell *const cells_it, int x, int y);
+
+ static void _complexTopLeftTransform(Point<T> &p, T dx, T dy);
+ static void _complexTopRightTransform(Point<T> &p, T dx, T dy);
+ static void _complexBottomRightTransform(Point<T> &p, T dx, T dy);
+ static void _complexBottomLeftTransform(Point<T> &p, T dx, T dy);
+
+ static bool _complexTopLeftTransformTop(PixelGraph::const_iterator graph_it);
+ static bool _complexTopLeftTransformTopRight(PixelGraph::const_iterator graph_it);
+ static bool _complexTopLeftTransformRight(PixelGraph::const_iterator graph_it);
+ static bool _complexTopLeftTransformBottomRight(PixelGraph::const_iterator graph_it);
+ static bool _complexTopLeftTransformBottom(PixelGraph::const_iterator graph_it);
+ static bool _complexTopLeftTransformBottomLeft(PixelGraph::const_iterator graph_it);
+ static bool _complexTopLeftTransformLeft(PixelGraph::const_iterator graph_it);
+ static bool _complexTopLeftTransformTopLeft(PixelGraph::const_iterator graph_it);
+
+ static bool _complexTopRightTransformTop(PixelGraph::const_iterator graph_it);
+ static bool _complexTopRightTransformTopRight(PixelGraph::const_iterator graph_it);
+ static bool _complexTopRightTransformRight(PixelGraph::const_iterator graph_it);
+ static bool _complexTopRightTransformBottomRight(PixelGraph::const_iterator graph_it);
+ static bool _complexTopRightTransformBottom(PixelGraph::const_iterator graph_it);
+ static bool _complexTopRightTransformBottomLeft(PixelGraph::const_iterator graph_it);
+ static bool _complexTopRightTransformLeft(PixelGraph::const_iterator graph_it);
+ static bool _complexTopRightTransformTopLeft(PixelGraph::const_iterator graph_it);
+
+ static bool _complexBottomRightTransformTop(PixelGraph::const_iterator graph_it);
+ static bool _complexBottomRightTransformTopRight(PixelGraph::const_iterator graph_it);
+ static bool _complexBottomRightTransformRight(PixelGraph::const_iterator graph_it);
+ static bool _complexBottomRightTransformBottomRight(PixelGraph::const_iterator graph_it);
+ static bool _complexBottomRightTransformBottom(PixelGraph::const_iterator graph_it);
+ static bool _complexBottomRightTransformBottomLeft(PixelGraph::const_iterator graph_it);
+ static bool _complexBottomRightTransformLeft(PixelGraph::const_iterator graph_it);
+ static bool _complexBottomRightTransformTopLeft(PixelGraph::const_iterator graph_it);
+
+ static bool _complexBottomLeftTransformTop(PixelGraph::const_iterator graph_it);
+ static bool _complexBottomLeftTransformTopRight(PixelGraph::const_iterator graph_it);
+ static bool _complexBottomLeftTransformRight(PixelGraph::const_iterator graph_it);
+ static bool _complexBottomLeftTransformBottomRight(PixelGraph::const_iterator graph_it);
+ static bool _complexBottomLeftTransformBottom(PixelGraph::const_iterator graph_it);
+ static bool _complexBottomLeftTransformBottomLeft(PixelGraph::const_iterator graph_it);
+ static bool _complexBottomLeftTransformLeft(PixelGraph::const_iterator graph_it);
+ static bool _complexBottomLeftTransformTopLeft(PixelGraph::const_iterator graph_it);
+
+ /*
+ * The memory layout assumed goes like this (with a_it being the current
+ * iterated element):
+ *
+ * (a_it) | (b_it)
+ * -------+-------
+ * (c_it) | (d_it)
+ *
+ * If you want to use it with another directions (topleft, topright, ...)
+ * **DO NOT** invert x or y axis, because the insertion order will go mad.
+ *
+ * The idea behind this abstraction is to rotate the iterators, then the
+ * insertion order will be preserved.
+ *
+ * The initial value of all nodes that will be inserted is {x, y}. All
+ * changes to this node **MUST** occur through \p transform or _adjust.
+ *
+ * Some maintainers may like this function because they will handle a
+ * code base 4 times smaller and bugs will be MUCH MUCH difficult to hide.
+ *
+ * Some maintainers may go mad because the level extra level of
+ * abstraction.
+ *
+ * "All problems in computer science can be solved by another level of
+ * indirection, except for the problem of too many layers of indirection."
+ * -- David J. Wheeler
+ */
+#ifndef LIBDEPIXELIZE_VERY_TYPE_SAFE
+ template<class PointTransform, class NodeTransform>
+#endif // LIBDEPIXELIZE_VERY_TYPE_SAFE
+ void _genericComplexBottomRight(PixelGraph::const_iterator a_it,
+ PixelGraph::const_iterator b_it,
+ PixelGraph::const_iterator c_it,
+ PixelGraph::const_iterator d_it,
+ Cell *const cells_it, int x, int y,
+ PointTransform transform,
+ NodeTransform top,
+ NodeTransform topright,
+ NodeTransform right,
+ NodeTransform bottomright,
+ NodeTransform bottom,
+ NodeTransform bottomleft,
+ NodeTransform left,
+ NodeTransform topleft);
+
+ int _width;
+ int _height;
+ std::vector<Cell> _cells;
+};
+
+template<class T, bool adjust_splines>
+SimplifiedVoronoi<T, adjust_splines>
+::SimplifiedVoronoi(const PixelGraph &graph) :
+ _width(graph.width()),
+ _height(graph.height()),
+ _cells(graph.size())
+{
+ if (!graph.size())
+ return;
+
+ /*
+ * The insertion order of cells is not a big deal. Here I just follow
+ * the order of PixelGraph arrangement.
+ */
+
+ // ...the "center" cells first...
+ if ( _width > 2 && _height > 2 ) {
+ PixelGraph::const_iterator graph_it = graph.begin() + _width + 1;
+ Cell *cells_it = &_cells.front() + _width + 1;
+
+ for ( int i = 1 ; i != _height - 1 ; ++i ) {
+ for ( int j = 1 ; j != _width - 1 ; ++j, ++graph_it, ++cells_it ) {
+ for ( int k = 0 ; k != 4 ; ++k )
+ cells_it->rgba[k] = graph_it->rgba[k];
+ // Top-left
+ _complexTopLeft(graph, graph_it, cells_it, j, i);
+
+ // Top-right
+ _complexTopRight(graph, graph_it, cells_it, j, i);
+
+ // Bottom-right
+ _complexBottomRight(graph, graph_it, cells_it, j, i);
+
+ // Bottom-left
+ _complexBottomLeft(graph, graph_it, cells_it, j, i);
+ }
+ // After the previous loop, 'it' is pointing to the last cell from
+ // the row.
+ // Go south, then first node in the row (increment 'it' by 1)
+ // Go to the second node in the line (increment 'it' by 1)
+ graph_it += 2;
+ cells_it += 2;
+ }
+ }
+
+ // ...then the "top" cells...
+ if ( _width > 2 ) {
+ PixelGraph::const_iterator graph_it = graph.begin() + 1;
+ Cell *cells_it = &_cells.front() + 1;
+
+ if ( _height > 1 ) {
+ for ( int i = 1 ; i != _width - 1 ; ++i, ++graph_it, ++cells_it ) {
+ for ( int j = 0 ; j != 4 ; ++j )
+ cells_it->rgba[j] = graph_it->rgba[j];
+
+ // Top-left
+ cells_it->vertices.push_back(Point<T>(i, 0, false));
+
+ // Top-right
+ cells_it->vertices.push_back(Point<T>(i + 1, 0, false));
+
+ // Bottom-right
+ _complexBottomRight(graph, graph_it, cells_it, i, 0);
+
+ // Bottom-left
+ _complexBottomLeft(graph, graph_it, cells_it, i, 0);
+ }
+ } else {
+ for ( int i = 1 ; i != _width - 1 ; ++i, ++graph_it, ++cells_it ) {
+ for ( int j = 0 ; j != 4 ; ++j )
+ cells_it->rgba[j] = graph_it->rgba[j];
+
+ // Top-left
+ cells_it->vertices.push_back(Point<T>(i, 0, false));
+
+ // Top-right
+ cells_it->vertices.push_back(Point<T>(i + 1, 0, false));
+
+ // Bottom-right
+ cells_it->vertices.push_back(Point<T>(i + 1, 1, false));
+
+ // Bottom-left
+ cells_it->vertices.push_back(Point<T>(i, 1, false));
+ }
+ }
+ }
+
+ // ...then the "bottom" cells...
+ if ( _width > 2 && _height > 1 ) {
+ // Node *it = &((*this)[1][_height - 1]);
+ PixelGraph::const_iterator graph_it
+ = graph.begin() + (_height - 1) * _width + 1;
+ Cell *cells_it = &_cells.front() + (_height - 1) * _width + 1;
+
+ for ( int i = 1 ; i != _width - 1 ; ++i, ++graph_it, ++cells_it ) {
+ for ( int j = 0 ; j != 4 ; ++j )
+ cells_it->rgba[j] = graph_it->rgba[j];
+
+ // Top-left
+ _complexTopLeft(graph, graph_it, cells_it, i, _height - 1);
+
+ // Top-right
+ _complexTopRight(graph, graph_it, cells_it, i, _height - 1);
+
+ // Bottom-right
+ cells_it->vertices.push_back(Point<T>(i + 1, _height, false));
+
+ // Bottom-left
+ cells_it->vertices.push_back(Point<T>(i, _height, false));
+ }
+ }
+
+ // ...then the "left" cells...
+ if ( _height > 2 ) {
+ PixelGraph::const_iterator graph_it = graph.begin() + _width;
+ Cell *cells_it = &_cells.front() + _width;
+
+ if ( _width > 1 ) {
+ for ( int i = 1 ; i != _height - 1 ; ++i) {
+ for ( int j = 0 ; j != 4 ; ++j )
+ cells_it->rgba[j] = graph_it->rgba[j];
+
+ // Top-left
+ cells_it->vertices.push_back(Point<T>(0, i, false));
+
+ // Top-right
+ _complexTopRight(graph, graph_it, cells_it, 0, i);
+
+ // Bottom-right
+ _complexBottomRight(graph, graph_it, cells_it, 0, i);
+
+ // Bottom-left
+ cells_it->vertices.push_back(Point<T>(0, i + 1, false));
+
+ graph_it += _width;
+ cells_it += _width;
+ }
+ } else {
+ for ( int i = 1 ; i != _height - 1 ; ++i) {
+ for ( int j = 0 ; j != 4 ; ++j )
+ cells_it->rgba[j] = graph_it->rgba[j];
+
+ // Top-left
+ cells_it->vertices.push_back(Point<T>(0, i, false));
+
+ // Top-right
+ cells_it->vertices.push_back(Point<T>(1, i, false));
+
+ // Bottom-right
+ cells_it->vertices.push_back(Point<T>(1, i, false));
+
+ // Bottom-left
+ cells_it->vertices.push_back(Point<T>(0, i + 1, false));
+
+ graph_it += _width;
+ cells_it += _width;
+ }
+ }
+ }
+
+ // ...then the "right" cells...
+ if ( _height > 2 && _width > 1 ) {
+ PixelGraph::const_iterator graph_it = graph.begin() + 2 * _width - 1;
+ Cell *cells_it = &_cells.front() + 2 * _width - 1;
+
+ for ( int i = 1 ; i != _height - 1 ; ++i ) {
+ for ( int j = 0 ; j != 4 ; ++j )
+ cells_it->rgba[j] = graph_it->rgba[j];
+
+ // Top-left
+ _complexTopLeft(graph, graph_it, cells_it, _width - 1, i);
+
+ // Top-right
+ cells_it->vertices.push_back(Point<T>(_width, i, false));
+
+ // Bottom-right
+ cells_it->vertices.push_back(Point<T>(_width, i + 1, false));
+
+ // Bottom-left
+ _complexBottomLeft(graph, graph_it, cells_it, _width - 1, i);
+
+ graph_it += _width;
+ cells_it += _width;
+ }
+ }
+
+ // ...and the 4 corner nodes
+ // top-left
+ {
+ PixelGraph::const_iterator graph_it = graph.begin();
+ Cell *cells_it = &_cells.front();
+
+ for ( int i = 0 ; i != 4 ; ++i )
+ cells_it->rgba[i] = graph_it->rgba[i];
+
+ // Top-left
+ cells_it->vertices.push_back(Point<T>(0, 0, false));
+
+ // Top-right
+ cells_it->vertices.push_back(Point<T>(1, 0, false));
+
+ // Bottom-right
+ if ( _width > 1 && _height > 1 )
+ _complexBottomRight(graph, graph_it, cells_it, 0, 0);
+ else
+ cells_it->vertices.push_back(Point<T>(1, 1, false));
+
+ // Bottom-left
+ cells_it->vertices.push_back(Point<T>(0, 1, false));
+ }
+
+ // top-right
+ if ( _width > 1 ) {
+ PixelGraph::const_iterator graph_it = graph.begin() + _width - 1;
+ Cell *cells_it = &_cells.front() + _width - 1;
+
+ for ( int i = 0 ; i != 4 ; ++i )
+ cells_it->rgba[i] = graph_it->rgba[i];
+
+ // Top-left
+ cells_it->vertices.push_back(Point<T>(_width - 1, 0, false));
+
+ // Top-right
+ cells_it->vertices.push_back(Point<T>(_width, 0, false));
+
+ // Bottom-right
+ cells_it->vertices.push_back(Point<T>(_width, 1, false));
+
+ // Bottom-left
+ if ( _height > 1 )
+ _complexBottomLeft(graph, graph_it, cells_it, _width - 1, 0);
+ else
+ cells_it->vertices.push_back(Point<T>(_width - 1, 1, false));
+ }
+
+ // bottom-left
+ if ( _height > 1 ) {
+ PixelGraph::const_iterator graph_it
+ = graph.begin() + (_height - 1) * _width;
+ Cell *cells_it = &_cells.front() + (_height - 1) * _width;
+
+ for ( int i = 0 ; i != 4 ; ++i )
+ cells_it->rgba[i] = graph_it->rgba[i];
+
+ // Top-left
+ cells_it->vertices.push_back(Point<T>(0, _height - 1, false));
+
+ // Top-right
+ if ( _width > 1)
+ _complexTopRight(graph, graph_it, cells_it, 0, _height - 1);
+ else
+ cells_it->vertices.push_back(Point<T>(1, _height - 1, false));
+
+ // Bottom-right
+ cells_it->vertices.push_back(Point<T>(1, _height, false));
+
+ // Bottom-left
+ cells_it->vertices.push_back(Point<T>(0, _height, false));
+ }
+
+ // bottom-right
+ if ( _width > 1 && _height > 1 ) {
+ PixelGraph::const_iterator graph_it = --graph.end();
+ Cell *cells_it = &_cells.back();
+
+ for ( int i = 0 ; i != 4 ; ++i )
+ cells_it->rgba[i] = graph_it->rgba[i];
+
+ // Top-left
+ _complexTopLeft(graph, graph_it, cells_it, _width - 1, _height - 1);
+
+ // Top-right
+ cells_it->vertices.push_back(Point<T>(_width, _height - 1, false));
+
+ // Bottom-right
+ cells_it->vertices.push_back(Point<T>(_width, _height, false));
+
+ // Bottom-left
+ cells_it->vertices.push_back(Point<T>(_width - 1, _height, false));
+ }
+}
+
+template<class T, bool adjust_splines> void
+SimplifiedVoronoi<T, adjust_splines>
+::_complexTopLeft(const PixelGraph &graph,
+ PixelGraph::const_iterator graph_it, Cell *const cells_it,
+ int x, int y)
+{
+ _genericComplexBottomRight(graph_it,
+ graph.nodeLeft(graph_it),
+ graph.nodeTop(graph_it),
+ graph.nodeTopLeft(graph_it),
+ cells_it, x, y,
+ &SimplifiedVoronoi::_complexTopLeftTransform,
+ &SimplifiedVoronoi::_complexTopLeftTransformTop,
+ &SimplifiedVoronoi::_complexTopLeftTransformTopRight,
+ &SimplifiedVoronoi::_complexTopLeftTransformRight,
+ &SimplifiedVoronoi::_complexTopLeftTransformBottomRight,
+ &SimplifiedVoronoi::_complexTopLeftTransformBottom,
+ &SimplifiedVoronoi::_complexTopLeftTransformBottomLeft,
+ &SimplifiedVoronoi::_complexTopLeftTransformLeft,
+ &SimplifiedVoronoi::_complexTopLeftTransformTopLeft);
+}
+
+template<class T, bool adjust_splines> void
+SimplifiedVoronoi<T, adjust_splines>
+::_complexTopRight(const PixelGraph &graph,
+ PixelGraph::const_iterator graph_it, Cell *const cells_it,
+ int x, int y)
+{
+ _genericComplexBottomRight(graph_it,
+ graph.nodeTop(graph_it),
+ graph.nodeRight(graph_it),
+ graph.nodeTopRight(graph_it),
+ cells_it, x, y,
+ &SimplifiedVoronoi::_complexTopRightTransform,
+ &SimplifiedVoronoi::_complexTopRightTransformTop,
+ &SimplifiedVoronoi::_complexTopRightTransformTopRight,
+ &SimplifiedVoronoi::_complexTopRightTransformRight,
+ &SimplifiedVoronoi::_complexTopRightTransformBottomRight,
+ &SimplifiedVoronoi::_complexTopRightTransformBottom,
+ &SimplifiedVoronoi::_complexTopRightTransformBottomLeft,
+ &SimplifiedVoronoi::_complexTopRightTransformLeft,
+ &SimplifiedVoronoi::_complexTopRightTransformTopLeft);
+}
+
+template<class T, bool adjust_splines> void
+SimplifiedVoronoi<T, adjust_splines>
+::_complexBottomRight(const PixelGraph &graph,
+ PixelGraph::const_iterator graph_it, Cell *const cells_it,
+ int x, int y)
+{
+ _genericComplexBottomRight(graph_it,
+ graph.nodeRight(graph_it),
+ graph.nodeBottom(graph_it),
+ graph.nodeBottomRight(graph_it),
+ cells_it, x, y,
+ &SimplifiedVoronoi::_complexBottomRightTransform,
+ &SimplifiedVoronoi::_complexBottomRightTransformTop,
+ &SimplifiedVoronoi::_complexBottomRightTransformTopRight,
+ &SimplifiedVoronoi::_complexBottomRightTransformRight,
+ &SimplifiedVoronoi::_complexBottomRightTransformBottomRight,
+ &SimplifiedVoronoi::_complexBottomRightTransformBottom,
+ &SimplifiedVoronoi::_complexBottomRightTransformBottomLeft,
+ &SimplifiedVoronoi::_complexBottomRightTransformLeft,
+ &SimplifiedVoronoi::_complexBottomRightTransformTopLeft);
+}
+
+template<class T, bool adjust_splines> void
+SimplifiedVoronoi<T, adjust_splines>
+::_complexBottomLeft(const PixelGraph &graph,
+ PixelGraph::const_iterator graph_it, Cell *const cells_it,
+ int x, int y)
+{
+ _genericComplexBottomRight(graph_it,
+ graph.nodeBottom(graph_it),
+ graph.nodeLeft(graph_it),
+ graph.nodeBottomLeft(graph_it),
+ cells_it, x, y,
+ &SimplifiedVoronoi::_complexBottomLeftTransform,
+ &SimplifiedVoronoi::_complexBottomLeftTransformTop,
+ &SimplifiedVoronoi::_complexBottomLeftTransformTopRight,
+ &SimplifiedVoronoi::_complexBottomLeftTransformRight,
+ &SimplifiedVoronoi::_complexBottomLeftTransformBottomRight,
+ &SimplifiedVoronoi::_complexBottomLeftTransformBottom,
+ &SimplifiedVoronoi::_complexBottomLeftTransformBottomLeft,
+ &SimplifiedVoronoi::_complexBottomLeftTransformLeft,
+ &SimplifiedVoronoi::_complexBottomLeftTransformTopLeft);
+}
+
+template<class T, bool adjust_splines> void
+SimplifiedVoronoi<T, adjust_splines>
+::_complexTopLeftTransform(Point<T> &p, T dx, T dy)
+{
+ p.x -= dx;
+ p.y -= dy;
+}
+
+template<class T, bool adjust_splines> void
+SimplifiedVoronoi<T, adjust_splines>
+::_complexTopRightTransform(Point<T> &p, T dx, T dy)
+{
+ p.x += dy;
+ p.y -= dx;
+}
+
+template<class T, bool adjust_splines> void
+SimplifiedVoronoi<T, adjust_splines>
+::_complexBottomRightTransform(Point<T> &p, T dx, T dy)
+{
+ p.x += dx;
+ p.y += dy;
+}
+
+template<class T, bool adjust_splines> void
+SimplifiedVoronoi<T, adjust_splines>
+::_complexBottomLeftTransform(Point<T> &p, T dx, T dy)
+{
+ p.x -= dy;
+ p.y += dx;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexTopLeftTransformTop(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.bottom;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexTopLeftTransformTopRight(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.bottomleft;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexTopLeftTransformRight(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.left;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexTopLeftTransformBottomRight(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.topleft;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexTopLeftTransformBottom(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.top;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexTopLeftTransformBottomLeft(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.topright;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexTopLeftTransformLeft(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.right;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexTopLeftTransformTopLeft(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.bottomright;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexTopRightTransformTop(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.left;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexTopRightTransformTopRight(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.topleft;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexTopRightTransformRight(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.top;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexTopRightTransformBottomRight(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.topright;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexTopRightTransformBottom(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.right;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexTopRightTransformBottomLeft(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.bottomright;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexTopRightTransformLeft(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.bottom;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexTopRightTransformTopLeft(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.bottomleft;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexBottomRightTransformTop(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.top;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexBottomRightTransformTopRight(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.topright;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexBottomRightTransformRight(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.right;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexBottomRightTransformBottomRight(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.bottomright;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexBottomRightTransformBottom(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.bottom;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexBottomRightTransformBottomLeft(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.bottomleft;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexBottomRightTransformLeft(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.left;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexBottomRightTransformTopLeft(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.topleft;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexBottomLeftTransformTop(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.right;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexBottomLeftTransformTopRight(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.bottomright;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexBottomLeftTransformRight(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.bottom;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexBottomLeftTransformBottomRight(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.bottomleft;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexBottomLeftTransformBottom(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.left;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexBottomLeftTransformBottomLeft(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.topleft;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexBottomLeftTransformLeft(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.top;
+}
+
+template<class T, bool adjust_splines>
+bool SimplifiedVoronoi<T, adjust_splines>
+::_complexBottomLeftTransformTopLeft(PixelGraph::const_iterator graph_it)
+{
+ return graph_it->adj.topright;
+}
+
+template<class T, bool adjust_splines>
+#ifndef LIBDEPIXELIZE_VERY_TYPE_SAFE
+template<class PointTransform, class NodeTransform>
+#endif // LIBDEPIXELIZE_VERY_TYPE_SAFE
+void
+SimplifiedVoronoi<T, adjust_splines>
+::_genericComplexBottomRight(PixelGraph::const_iterator a_it,
+ PixelGraph::const_iterator b_it,
+ PixelGraph::const_iterator c_it,
+ PixelGraph::const_iterator d_it,
+ Cell *const cells_it, int x, int y,
+ PointTransform transform,
+ NodeTransform,
+ NodeTransform topright,
+ NodeTransform right,
+ NodeTransform bottomright,
+ NodeTransform bottom,
+ NodeTransform bottomleft,
+ NodeTransform,
+ NodeTransform topleft)
+{
+ using colorspace::contour_edge;
+ using colorspace::same_color;
+
+ const Point<T> initial(x, y);
+
+ /*
+ * The insertion order of points within the cell is very important. You must
+ * follow current practice: Clockwise order.
+ */
+
+ if ( bottomright(a_it) ) {
+ // this and bottom-right are connected
+
+ bool smooth[2] = {
+ ( same_color(a_it->rgba, d_it->rgba)
+ || same_color(a_it->rgba, b_it->rgba)
+ || same_color(b_it->rgba, d_it->rgba) ),
+ ( same_color(a_it->rgba, d_it->rgba)
+ || same_color(a_it->rgba, c_it->rgba)
+ || same_color(c_it->rgba, d_it->rgba) )
+ };
+
+ Point<T> borderMid = initial;
+ {
+ transform(borderMid, 1, 1);
+ borderMid = midpoint(initial, borderMid);
+ }
+
+ Point<T> vertices[2] = {initial, initial};
+ {
+ transform(vertices[0], 1, 0);
+ vertices[0] = _adjust(midpoint(borderMid, vertices[0]), smooth[0]);
+
+ transform(vertices[1], 0, 1);
+ vertices[1] = _adjust(midpoint(borderMid, vertices[1]), smooth[1]);
+ }
+
+ if ( !smooth[0] && adjust_splines ) {
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_1ST_IS_INVISIBLE
+ cells_it->vertices.push_back(vertices[0].invisible());
+#else
+ cells_it->vertices.push_back(vertices[0]);
+#endif
+ {
+ Point<T> another = vertices[0];
+ transform(another,
+ - ( 0.1875
+ - ( topright(a_it) - topleft(b_it) ) * 0.1875 ),
+ // y
+ - ( 0.5625
+ - ( topright(a_it) + topleft(b_it) ) * 0.1875 ));
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_2ND_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertices[0];
+ transform(another,
+ - ( 0.0625
+ - ( topright(a_it) - topleft(b_it) ) * 0.0625 ),
+ // y
+ - ( 0.1875
+ - ( topright(a_it) + topleft(b_it) ) * 0.0625) );
+ another.smooth = true;
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_3RD_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertices[0];
+ transform(another,
+ 0.1875
+ - ( bottomright(b_it) + topright(d_it) ) * 0.0625,
+ // y
+ 0.0625
+ + ( bottomright(b_it) - topright(d_it) ) * 0.0625);
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_4TH_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ transform(vertices[0],
+ 0.0625
+ + ( topright(a_it) - topright(d_it) - topleft(b_it)
+ - bottomright(b_it) ) * 0.03125,
+ // y
+ - ( 0.0625
+ + ( topright(d_it) - topright(a_it)
+ - topleft(b_it) - bottomright(b_it) )
+ * 0.03125 ));
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_5TH_IS_INVISIBLE
+ vertices[0].visible = false;
+#endif
+ }
+ }
+
+ cells_it->vertices.push_back(vertices[0]);
+
+ if ( !smooth[1] && adjust_splines ) {
+ {
+ Point<T> another = vertices[1];
+ transform(another,
+ - ( 0.0625
+ + ( bottomleft(d_it) - bottomleft(a_it)
+ - topleft(c_it) - bottomright(c_it) )
+ * 0.03125 ),
+ // y
+ 0.0625
+ + ( bottomleft(a_it) - bottomleft(d_it)
+ - topleft(c_it) - bottomright(c_it) ) * 0.03125);
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_1ST_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertices[1];
+ transform(another,
+ 0.0625
+ + ( bottomright(c_it) - bottomleft(d_it) ) * 0.0625,
+ // y
+ 0.1875
+ - ( bottomright(c_it) + bottomleft(d_it) ) * 0.0625);
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_2ND_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertices[1];
+ transform(another,
+ - ( 0.1875
+ - ( bottomleft(a_it) + topleft(c_it) )
+ * 0.0625 ),
+ // y
+ - ( 0.0625
+ - ( bottomleft(a_it) - topleft(c_it) )
+ * 0.0625 ));
+ another.smooth = true;
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_3RD_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertices[1];
+ transform(another,
+ - ( 0.5625
+ - ( bottomleft(a_it) + topleft(c_it) )
+ * 0.1875 ),
+ // y
+ - ( 0.1875
+ - ( bottomleft(a_it) - topleft(c_it) )
+ * 0.1875 ));
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_4TH_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_5TH_IS_INVISIBLE
+ vertices[1].visible = false;
+#endif
+ }
+
+ cells_it->vertices.push_back(vertices[1]);
+ } else if ( bottomleft(b_it) ) {
+ // right and bottom are connected
+
+ Point<T> vertex = initial;
+ transform(vertex, 1, 1);
+ vertex = _adjust(midpoint(midpoint(initial, vertex), initial), true);
+ cells_it->vertices.push_back(vertex);
+ } else {
+ // Connections don't affect the shape of this squared-like
+ // pixel
+
+ Point<T> vertex = initial;
+ transform(vertex, 1, 1);
+ vertex = _adjust(midpoint(initial, vertex));
+
+ // compute smoothness
+ if ( right(a_it) && adjust_splines ) {
+ // this and right are connected
+
+ if ( !right(c_it) && !( bottom(a_it) && bottom(b_it) ) ) {
+ // bottom and bottom-right are disconnected
+
+ bool foreign_is_contour = contour_edge(c_it->rgba, d_it->rgba);
+ bool twin_is_contour = contour_edge(b_it->rgba, d_it->rgba);
+ bool another_is_contour = contour_edge(a_it->rgba, c_it->rgba);
+
+ if ( another_is_contour + twin_is_contour
+ + foreign_is_contour == 2 ) {
+ vertex.smooth = !foreign_is_contour;
+
+ if ( !vertex.smooth ) {
+ if ( another_is_contour ) {
+ {
+ Point<T> another = vertex;
+ T amount = 0.125
+ - ( ( bottomright(c_it) + topleft(c_it) )
+ * 0.03125 );
+ transform(another, - amount, amount);
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_1ST_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertex;
+ T amount = 0.0625 * bottomright(c_it);
+ transform(another, amount, 0.25 - amount);
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_2ND_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertex;
+ T amount = 0.0625 * topleft(c_it);
+ transform(another, - ( 0.25 - amount ),
+ - amount);
+ another.smooth = true;
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_3RD_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertex;
+ T amount = 0.1875 * topleft(c_it);
+ transform(another, - ( 0.75 - amount ),
+ - amount);
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_4TH_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_5TH_IS_INVISIBLE
+ vertex.visible = false;
+#endif
+ } else if ( twin_is_contour ) {
+ T amount = 0.125
+ - ( ( bottomleft(d_it) + topright(d_it) )
+ * 0.03125 );
+ transform(vertex, amount, amount);
+ }
+ } else if ( !same_color(a_it->rgba, b_it->rgba) ) {
+ vertex.smooth = false;
+ // This is the same code of the if ( special )
+ // I REALLY NEED lambdas to improve this code without
+ // creating yet another interface that takes a million
+ // of function parameters and keep code locality
+ {
+ Point<T> another = vertex;
+ T amount = 0.03125;
+ transform(another,
+ amount
+ * ( topleft(c_it) - topright(d_it)
+ + bottomleft(a_it) - bottomright(b_it) ),
+ // y
+ - amount
+ * ( topleft(c_it) + topright(d_it)
+ - bottomleft(a_it) - bottomright(b_it) ));
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_1ST_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertex;
+ T amount = 0.0625;
+ transform(another,
+ 0.25 - amount
+ * ( topright(d_it) + bottomright(b_it) ),
+ // y
+ - amount
+ * ( topright(d_it) - bottomright(b_it) ));
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_2ND_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertex;
+ T amount = 0.0625;
+ transform(another,
+ - ( 0.25 - amount
+ * ( topleft(c_it) + bottomleft(a_it) ) ),
+ // y
+ - amount
+ * ( topleft(c_it) - bottomleft(a_it) ));
+ another.smooth = true;
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_3RD_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertex;
+ T amount = 0.1875;
+ transform(another,
+ - ( 0.75 - amount
+ * ( topleft(c_it) + bottomleft(a_it) ) ),
+ // y
+ - amount
+ * ( topleft(c_it) - bottomleft(a_it) ));
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_4TH_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_5TH_IS_INVISIBLE
+ vertex.visible = false;
+#endif
+ }
+ } else {
+ // {this, right} is the pair with the angle
+ // closest to 180 degrees
+ vertex.smooth = same_color(a_it->rgba, b_it->rgba);
+ }
+ } else {
+ // there might be 2-color, then vertex.smooth = true
+
+ // or it might be 1-color and doesn't matter,
+ // because the current node will disappear
+ vertex.smooth
+ = same_color(a_it->rgba, b_it->rgba)
+ + same_color(a_it->rgba, c_it->rgba)
+ + same_color(d_it->rgba, b_it->rgba)
+ + same_color(d_it->rgba, c_it->rgba) == 2;
+ }
+ } else if ( bottom(a_it) && adjust_splines ) {
+ // this and bottom are connected
+
+ if ( !bottom(b_it) && !( right(a_it) && right(c_it) ) ) {
+ // right and bottom-right are disconnected
+
+ bool foreign_is_contour = contour_edge(b_it->rgba, d_it->rgba);
+ bool twin_is_contour = contour_edge(c_it->rgba, d_it->rgba);
+ bool another_is_contour = contour_edge(a_it->rgba, b_it->rgba);
+
+ if ( another_is_contour + twin_is_contour
+ + foreign_is_contour == 2 ) {
+ vertex.smooth = !foreign_is_contour;
+
+ if ( !vertex.smooth ) {
+ if ( another_is_contour ) {
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_1ST_IS_INVISIBLE
+ cells_it->vertices.push_back(vertex.invisible());
+#else
+ cells_it->vertices.push_back(vertex);
+#endif
+ {
+ Point<T> another = vertex;
+ T amount = 0.1875 * topleft(b_it);
+ transform(another, - amount,
+ - ( 0.75 - amount ));
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_2ND_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertex;
+ T amount = 0.0625 * topleft(b_it);
+ transform(another, - amount,
+ - ( 0.25 - amount ));
+ another.smooth = true;
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_3RD_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertex;
+ T amount = 0.0625 * bottomright(b_it);
+ transform(another, 0.25 - amount, amount);
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_4TH_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ T amount = 0.125
+ - (bottomright(b_it) + topleft(b_it))
+ * 0.03125;
+ transform(vertex, amount, - amount);
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_5TH_IS_INVISIBLE
+ vertex.visible = false;
+#endif
+ }
+ } else if ( twin_is_contour ) {
+ T amount = 0.125
+ - ( ( topright(d_it) + bottomleft(d_it) )
+ * 0.03125 );
+ transform(vertex, amount, amount);
+ }
+ } else if ( !same_color(a_it->rgba, c_it->rgba) ) {
+ vertex.smooth = false;
+ // This is the same code of the if ( special )
+ // I REALLY NEED lambdas to improve this code without
+ // creating yet another interface that takes a million
+ // of function parameters and keep code locality
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_1ST_IS_INVISIBLE
+ cells_it->vertices.push_back(vertex.invisible());
+#else
+ cells_it->vertices.push_back(vertex);
+#endif
+ {
+ Point<T> another = vertex;
+ T amount = 0.1875;
+ transform(another,
+ - ( topleft(b_it) - topright(a_it) ) * amount,
+ // y
+ - ( 0.75
+ - ( topleft(b_it) + topright(a_it) )
+ * amount ));
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_2ND_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertex;
+ T amount = 0.0625;
+ transform(another,
+ - ( topleft(b_it) - topright(a_it) ) * amount,
+ // y
+ - ( 0.25
+ - ( topleft(b_it) + topright(a_it) )
+ * amount ));
+ another.smooth = true;
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_3RD_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertex;
+ T amount = 0.0625;
+ transform(another, - amount
+ * ( bottomleft(d_it) - bottomright(c_it) ),
+ // y
+ 0.25 - amount
+ * ( bottomleft(d_it) + bottomright(c_it) ));
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_4TH_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ transform(vertex,
+ - ( topleft(b_it) + bottomleft(d_it)
+ - topright(a_it) - bottomright(c_it) )
+ * 0.03125,
+ // y
+ ( topleft(b_it) - bottomleft(d_it)
+ + topright(a_it) - bottomright(c_it) )
+ * 0.03125);
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_5TH_IS_INVISIBLE
+ vertex.visible = false;
+#endif
+ }
+ }
+ } else {
+ // {this, bottom} is the pair with the angle
+ // closest to 180 degrees
+ vertex.smooth = same_color(a_it->rgba, c_it->rgba);
+ }
+ } else {
+ // there might be 2-color, then vertex.smooth = true
+
+ // or it might be 1-color and doesn't matter,
+ // because the current node will disappear
+ vertex.smooth
+ = same_color(a_it->rgba, c_it->rgba)
+ + same_color(a_it->rgba, b_it->rgba)
+ + same_color(d_it->rgba, b_it->rgba)
+ + same_color(d_it->rgba, c_it->rgba) == 2;
+ }
+ } else if ( bottom(b_it) && adjust_splines ) {
+ // right and bottom-right are connected
+
+ bool special = false;
+
+ bool foreign_is_contour = contour_edge(c_it->rgba, d_it->rgba);
+
+ // the neighbor similar in 90° feature
+ bool similar_neighbor_is_contour
+ = contour_edge(a_it->rgba, c_it->rgba);
+
+ if ( contour_edge(a_it->rgba, b_it->rgba)
+ + similar_neighbor_is_contour
+ + foreign_is_contour == 2 ) {
+ vertex.smooth = !foreign_is_contour;
+
+ if ( !vertex.smooth ) {
+ if ( similar_neighbor_is_contour ) {
+ {
+ Point<T> another = vertex;
+ T amount = 0.125
+ - ( topleft(c_it) + bottomright(c_it) )
+ * 0.03125;
+ transform(another, - amount, amount);
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_1ST_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertex;
+ T amount = 0.0625 * bottomright(c_it);
+ transform(another, amount, 0.25 - amount);
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_2ND_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertex;
+ T amount = 0.0625 * topleft(c_it);
+ transform(another, - ( 0.25 - amount ), - amount);
+ another.smooth = true;
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_3RD_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertex;
+ T amount = 0.1875 * topleft(c_it);
+ transform(another, - ( 0.75 - amount ), - amount);
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_4TH_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_5TH_IS_INVISIBLE
+ vertex.visible = false;
+#endif
+ } else {
+ special = true;
+ }
+ }
+ } else {
+ // {right, bottom-right} is the pair with the
+ // angle closest to 180 degrees
+ vertex.smooth = false;
+
+ special = true;
+ }
+
+ if ( special ) {
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_1ST_IS_INVISIBLE
+ cells_it->vertices.push_back(vertex.invisible());
+#else
+ cells_it->vertices.push_back(vertex);
+#endif
+ {
+ Point<T> another = vertex;
+ T amount = 0.1875;
+ transform(another,
+ - ( topleft(b_it) - topright(a_it) ) * amount,
+ // y
+ - ( 0.75
+ - ( topleft(b_it) + topright(a_it) )
+ * amount ));
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_2ND_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertex;
+ T amount = 0.0625;
+ transform(another,
+ - ( topleft(b_it) - topright(a_it) ) * amount,
+ // y
+ - ( 0.25
+ - ( topleft(b_it) + topright(a_it) )
+ * amount ));
+ another.smooth = true;
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_3RD_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertex;
+ T amount = 0.0625;
+ transform(another, - amount
+ * ( bottomleft(d_it) - bottomright(c_it) ),
+ // y
+ 0.25 - amount
+ * ( bottomleft(d_it) + bottomright(c_it) ));
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_4TH_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ transform(vertex,
+ - ( topleft(b_it) + bottomleft(d_it)
+ - topright(a_it) - bottomright(c_it) )
+ * 0.03125,
+ // y
+ ( topleft(b_it) - bottomleft(d_it)
+ + topright(a_it) - bottomright(c_it) )
+ * 0.03125);
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_5TH_IS_INVISIBLE
+ vertex.visible = false;
+#endif
+ }
+ }
+ } else if ( right(c_it) && adjust_splines ) {
+ // bottom and bottom-right are connected
+
+ bool special = false;
+
+ bool foreign_is_contour = contour_edge(b_it->rgba, d_it->rgba);
+
+ // the neighbor similar in 90° feature
+ bool similar_neighbor_is_contour
+ = contour_edge(a_it->rgba, b_it->rgba);
+
+ if ( contour_edge(a_it->rgba, c_it->rgba)
+ + similar_neighbor_is_contour
+ + foreign_is_contour == 2 ) {
+ vertex.smooth = !foreign_is_contour;
+
+ if ( !vertex.smooth ) {
+ if ( similar_neighbor_is_contour ) {
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_1ST_IS_INVISIBLE
+ cells_it->vertices.push_back(vertex.invisible());
+#else
+ cells_it->vertices.push_back(vertex);
+#endif
+ {
+ Point<T> another = vertex;
+ T amount = 0.1875 * topleft(b_it);
+ transform(another, - amount, - ( 0.75 - amount ));
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_2ND_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertex;
+ T amount = 0.0625 * topleft(b_it);
+ transform(another, - amount, - ( 0.25 - amount ));
+ another.smooth = true;
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_3RD_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertex;
+ T amount = 0.0625 * bottomright(b_it);
+ transform(another, 0.25 - amount, amount);
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_4TH_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ T amount = 0.125
+ - 0.03125 * (topleft(b_it) + bottomright(b_it));
+ transform(vertex, amount, - amount);
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_5TH_IS_INVISIBLE
+ vertex.visible = false;
+#endif
+ }
+ } else {
+ special = true;
+ }
+ }
+ } else {
+ // {bottom, bottom-right} is the pair with the
+ // angle closest to 180 degrees
+ vertex.smooth = false;
+
+ special = true;
+ }
+
+ if ( special ) {
+ {
+ Point<T> another = vertex;
+ T amount = 0.03125;
+ transform(another,
+ amount
+ * ( topleft(c_it) - topright(d_it)
+ + bottomleft(a_it) - bottomright(b_it) ),
+ // y
+ - amount
+ * ( topleft(c_it) + topright(d_it)
+ - bottomleft(a_it) - bottomright(b_it) ));
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_1ST_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertex;
+ T amount = 0.0625;
+ transform(another,
+ 0.25 - amount
+ * ( topright(d_it) + bottomright(b_it) ),
+ // y
+ - amount
+ * ( topright(d_it) - bottomright(b_it) ));
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_2ND_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertex;
+ T amount = 0.0625;
+ transform(another,
+ - ( 0.25 - amount
+ * ( topleft(c_it) + bottomleft(a_it) ) ),
+ // y
+ - amount
+ * ( topleft(c_it) - bottomleft(a_it) ));
+ another.smooth = true;
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_3RD_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+ {
+ Point<T> another = vertex;
+ T amount = 0.1875;
+ transform(another,
+ - ( 0.75 - amount
+ * ( topleft(c_it) + bottomleft(a_it) ) ),
+ // y
+ - amount
+ * ( topleft(c_it) - bottomleft(a_it) ));
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_4TH_IS_INVISIBLE
+ cells_it->vertices.push_back(another.invisible());
+#else
+ cells_it->vertices.push_back(another);
+#endif
+ }
+#ifdef LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES_5TH_IS_INVISIBLE
+ vertex.visible = false;
+#endif
+ }
+ } else {
+ // there is a 4-color pattern, where the current node
+ // won't be smooth
+ vertex.smooth = false;
+ }
+
+ cells_it->vertices.push_back(vertex);
+ }
+}
+
+} // namespace Tracer
+
+#endif // LIBDEPIXELIZE_TRACER_SIMPLIFIEDVORONOI_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/libdepixelize/priv/splines-kopf2011.h b/src/3rdparty/libdepixelize/priv/splines-kopf2011.h
new file mode 100644
index 0000000..c3da58c
--- /dev/null
+++ b/src/3rdparty/libdepixelize/priv/splines-kopf2011.h
@@ -0,0 +1,167 @@
+/* This file is part of the libdepixelize project
+ Copyright (C) 2013 Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.com>
+
+ GNU Lesser General Public License Usage
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2.1 of the License, or (at your
+ option) any later version.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+ GNU General Public License Usage
+ Alternatively, this library may be used under the terms of the GNU General
+ Public License as published by the Free Software Foundation, either version
+ 2 of the License, or (at your option) any later version.
+ You should have received a copy of the GNU General Public License along with
+ this library. If not, see <http://www.gnu.org/licenses/>.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+*/
+
+#ifndef LIBDEPIXELIZE_TRACER_SPLINES_KOPF2011_H
+#define LIBDEPIXELIZE_TRACER_SPLINES_KOPF2011_H
+
+#include "../splines.h"
+#include "homogeneoussplines.h"
+#include "optimization-kopf2011.h"
+
+namespace Tracer {
+
+/**
+ * Maybe the pass-by-value and then move idiom should be more efficient. But all
+ * this is inlinable and we're not even in C++11 yet.
+ */
+template<class T>
+Geom::Path worker_helper(const std::vector< Point<T> > &source1, bool optimize)
+{
+ typedef Geom::LineSegment Line;
+ typedef Geom::QuadraticBezier Quad;
+ typedef typename std::vector< Point<T> >::const_iterator iterator;
+
+ std::vector< Point<T> > source;
+
+ if ( optimize )
+ source = Tracer::optimize(source1);
+ else
+ source = source1;
+
+ iterator it = source.begin();
+ Point<T> prev = source.back();
+ Geom::Path ret(to_geom_point(midpoint(prev, *it)));
+
+ for ( iterator end = source.end() ; it != end ; ++it ) {
+#if LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES
+ // remove redundant points
+ if ( !it->visible ) {
+ prev = *it;
+ continue;
+ }
+#endif // LIBDEPIXELIZE_ENABLE_EXPERIMENTAL_FEATURES
+
+ if ( !prev.visible ) {
+ Geom::Point middle = to_geom_point(midpoint(prev, *it));
+ if ( ret.finalPoint() != middle ) {
+ // All generated invisible points are straight lines
+ ret.appendNew<Line>(middle);
+ }
+ }
+
+ Point<T> next = (it + 1 == end) ? source.front() : *(it + 1);
+ Point<T> middle = midpoint(*it, next);
+
+ if ( !it->smooth ) {
+ ret.appendNew<Line>(to_geom_point(*it));
+ ret.appendNew<Line>(to_geom_point(middle));
+ } else {
+ ret.appendNew<Quad>(to_geom_point(*it), to_geom_point(middle));
+ }
+
+ prev = *it;
+ }
+
+ return ret;
+}
+
+/**
+ * It should be used by worker threads. Convert only one object.
+ */
+template<class T>
+void worker(const typename HomogeneousSplines<T>::Polygon &source,
+ Splines::Path &dest, bool optimize)
+{
+ //dest.pathVector.reserve(source.holes.size() + 1);
+
+ for ( int i = 0 ; i != 4 ; ++i )
+ dest.rgba[i] = source.rgba[i];
+
+ dest.pathVector.push_back(worker_helper(source.vertices, optimize));
+
+ for ( typename std::vector< std::vector< Point<T> > >::const_iterator
+ it = source.holes.begin(), end = source.holes.end()
+ ; it != end ; ++it ) {
+ dest.pathVector.push_back(worker_helper(*it, optimize));
+ }
+}
+
+template<typename T, bool adjust_splines>
+Splines::Splines(const SimplifiedVoronoi<T, adjust_splines> &diagram) :
+ _width(diagram.width()),
+ _height(diagram.height())
+{
+ _paths.reserve(diagram.size());
+
+ for ( typename SimplifiedVoronoi<T, adjust_splines>::const_iterator
+ it = diagram.begin() , end = diagram.end() ; it != end ; ++it ) {
+ Path path;
+
+ path.pathVector
+ .push_back(Geom::Path(to_geom_point(it->vertices.front())));
+
+ for ( typename std::vector< Point<T> >::const_iterator
+ it2 = ++it->vertices.begin(), end2 = it->vertices.end()
+ ; it2 != end2 ; ++it2 ) {
+ path.pathVector.back()
+ .appendNew<Geom::LineSegment>(Geom::Point(it2->x, it2->y));
+ }
+
+ for ( int i = 0 ; i != 4 ; ++i )
+ path.rgba[i] = it->rgba[i];
+
+ _paths.push_back(path);
+ }
+}
+
+template<class T>
+Splines::Splines(const HomogeneousSplines<T> &homogeneousSplines,
+ bool optimize, int /*nthreads*/) :
+ _paths(homogeneousSplines.size()),
+ _width(homogeneousSplines.width()),
+ _height(homogeneousSplines.height())
+{
+ // TODO: It should be threaded
+ iterator paths_it = begin();
+ for ( typename HomogeneousSplines<T>::const_iterator
+ it = homogeneousSplines.begin(), end = homogeneousSplines.end()
+ ; it != end ; ++it, ++paths_it ) {
+ worker<T>(*it, *paths_it, optimize);
+ }
+}
+
+} // namespace Tracer
+
+#endif // LIBDEPIXELIZE_TRACER_SPLINES_KOPF2011_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/libdepixelize/splines.h b/src/3rdparty/libdepixelize/splines.h
new file mode 100644
index 0000000..b06ba8b
--- /dev/null
+++ b/src/3rdparty/libdepixelize/splines.h
@@ -0,0 +1,120 @@
+/* This file is part of the libdepixelize project
+ Copyright (C) 2013 Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.com>
+
+ GNU Lesser General Public License Usage
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2.1 of the License, or (at your
+ option) any later version.
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+ GNU General Public License Usage
+ Alternatively, this library may be used under the terms of the GNU General
+ Public License as published by the Free Software Foundation, either version
+ 2 of the License, or (at your option) any later version.
+ You should have received a copy of the GNU General Public License along with
+ this library. If not, see <http://www.gnu.org/licenses/>.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+*/
+
+#ifndef LIBDEPIXELIZE_TRACER_SPLINES_H
+#define LIBDEPIXELIZE_TRACER_SPLINES_H
+
+#include <2geom/pathvector.h>
+#include <glib.h>
+
+namespace Tracer {
+
+template<typename T, bool adjust_splines = true>
+class SimplifiedVoronoi;
+
+template<typename T>
+class HomogeneousSplines;
+
+class Splines
+{
+public:
+ struct Path
+ {
+ /**
+ * It may be benefited from C++11 move references.
+ */
+ Geom::PathVector pathVector;
+
+ guint8 rgba[4];
+ };
+
+ typedef std::vector<Path>::iterator iterator;
+ typedef std::vector<Path>::const_iterator const_iterator;
+
+ Splines() /* = default */ {}
+
+ template<typename T, bool adjust_splines>
+ Splines(const SimplifiedVoronoi<T, adjust_splines> &simplifiedVoronoi);
+
+ /**
+ * There are two levels of optimization. The first level only removes
+ * redundant points of colinear points. The second level uses the
+ * Kopf-Lischinski optimization. The first level is always enabled.
+ * The second level is enabled using \p optimize.
+ */
+ template<typename T>
+ Splines(const HomogeneousSplines<T> &homogeneousSplines, bool optimize,
+ int nthreads);
+
+ // Iterators
+ iterator begin()
+ {
+ return _paths.begin();
+ }
+
+ const_iterator begin() const
+ {
+ return _paths.begin();
+ }
+
+ iterator end()
+ {
+ return _paths.end();
+ }
+
+ const_iterator end() const
+ {
+ return _paths.end();
+ }
+
+ int width() const
+ {
+ return _width;
+ }
+
+ int height() const
+ {
+ return _height;
+ }
+
+private:
+ std::vector<Path> _paths;
+ int _width;
+ int _height;
+};
+
+} // namespace Tracer
+
+#endif // LIBDEPIXELIZE_TRACER_SPLINES_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/3rdparty/libuemf/CMakeLists.txt b/src/3rdparty/libuemf/CMakeLists.txt
new file mode 100644
index 0000000..9e6b689
--- /dev/null
+++ b/src/3rdparty/libuemf/CMakeLists.txt
@@ -0,0 +1,30 @@
+
+set(libuemf_SRC
+ symbol_convert.c
+ uemf.c
+ uemf_endian.c
+ uemf_print.c
+ uemf_safe.c
+ uemf_utf.c
+ uwmf.c
+ uwmf_endian.c
+ uwmf_print.c
+ upmf.c
+ upmf_print.c
+
+ # -------
+ # Headers
+ symbol_convert.h
+ uemf.h
+ uemf_endian.h
+ uemf_print.h
+ uemf_safe.h
+ uemf_utf.h
+ uwmf.h
+ uwmf_endian.h
+ uwmf_print.h
+ upmf.h
+ upmf_print.h
+)
+
+add_inkscape_lib(uemf_LIB "${libuemf_SRC}")
diff --git a/src/3rdparty/libuemf/README b/src/3rdparty/libuemf/README
new file mode 100644
index 0000000..4d66bbe
--- /dev/null
+++ b/src/3rdparty/libuemf/README
@@ -0,0 +1,567 @@
+Overview:
+
+libUEMF is a portable C99 implementation for reading/writing Enhanced Metafile (EMF),
+Enhanced Metafile Format Plus (PMF), and Windows Metafile (WMF) files. libUEMF
+avoids collisions with Microsoft defined functions and values, so portable programs
+which use it and have a Windows version, do not require any conditional logic to
+separate the native GDI support from the WMF/EMF/PMF support proviced by libUEMF. To
+accomplish this libUEMF does not implement GDI calls. Instead, for each WMR/EMR/PMR
+record type, and each object type incorporated into such a record, it provides
+corresponding *_set, *_print, and *_swap functions. For PMF and WMF there are also
+*_get functions, see below. For example, for the U_EMRBITBLT record there are
+corresponding functions: U_EMRBITBLT_set, U_EMRBITBLT_print, and U_EMRBITBLT_swap. A
+few additional functions are provided for assembling the EMF in memory, debugging, and
+converting the EMF file to/from Little Endian representation. (EMF files' internal
+data representation is always Little Endian.)
+
+This code has been tested on 32 bit Ubuntu (LE), 32 bit Mingw, 64 bit CentOS, and 64
+bit Solaris (BE).
+
+libUEMF is released under the GPL 2 license, read the file 'COPYING' for more information
+
+Version 0.2.8, released May 13, 2020.
+
+To report bugs or provide feedback send email to David Mathog, mathog@caltech.edu.
+
+--------------------------------------------------------------------------------------------
+Sources:
+
+EMF file Record structure information has been derived from Mingw, Wine, and libEMF
+header files, and from Microsoft's EMF Information pdf, release date March 28,2012,
+link from here:
+
+ http://msdn2.microsoft.com/en-us/library/cc230514.aspx
+
+If the direct link fails the document may be found
+by searching the web for: "[MS-EMF]: Enhanced Metafile Format".
+
+WMF file Record structure information is from some of the same sources, as well as:
+ http://msdn2.microsoft.com/en-us/library/250370.aspx
+
+If the direct link fails the document may be found
+by searching the web for: "[MS-WMF]: Windows Metafile Format"
+
+EMF+ file Record structure is from many helpful responses from Microsoft documentation support
+and from:
+ http://msdn.microsoft.com/en-us/library/cc230724.aspx
+
+If the direct link fails the document may be found
+by searching the web for: "[MS-EMFPLUS]: Enhanced Metafile Format Plus Extensions"
+
+
+Files:
+
+README This file.
+
+CMakeLists.txt Build instructions for cmake on linux. Not tested on OS X or
+ Windows.
+
+COPYING GPL V2 license file.
+
+DOXYFILE Doxygen configuration file, for generating documentation from the source files.
+
+testbuild.sh Small bash script to build all programs. Modify as needed for target platform.
+
+testit.sh Small bash script that generates all test files and compares
+ them with referencess supplied. This script should be edited
+ to match your test system before it is run!
+
+uemf.c Contains the *_set functions needed to construct an EMF file.
+ Also contains auxilliary functions for debugging and constructing
+ EMF files in memory.
+
+uemf.h Definitions and structures for EMF records and objects.
+ Prototypes for *_set and construction functions.
+
+uemf_print.c Contains the *_print functions needed to print the contents of EMF records and objects.
+
+uemf_print.h Prototypes for *_print functions.
+
+uemf_endian.c Contains the *_swap functions needed to rearrange bytes between Big and Little Endian.
+ U_emf_endian() is the only function here that user could should call.
+
+uemf_endian.h Prototype for U_emf_endian() and definitions for Endian type of the local machine.
+
+uemf_safe.c Contains the *_safe functions for EMF records, which verify that all
+ offsets and counts stay within the declared size of a record. Also checks that
+ core record sizes are sane. U_emf_record_safe() is the only _safe function which
+ user code should call directly, and then ONLY after a previous call to
+ U_emf_record_sizeok(), which is in the endian file.
+
+uemf_safe.h Prototype for U_emf_record_safe().
+ .
+upmf.c Contains the *_set and *_get functions needed to construct or read an EMF+ file.
+ Also contains auxilliary functions for debugging and constructing
+ EMF+ files in memory.
+
+upmf.h Definitions and structures for EMF+ records and objects.
+ Prototypes for *_set, *_get and construction functions.
+
+upmf_print.c Contains the *_print functions needed to print the contents of EMF+ records and objects.
+
+upmf_print.h Prototypes for *_print functions.
+
+
+uwmf.c Contains the *_set and *_get functions needed to construct or read a WMF file.
+ Also contains auxilliary functions for debugging and constructing
+ WMF files in memory.
+
+uwmf.h Definitions and structures for WMF records and objects.
+ Prototypes for *_set, *_get and construction functions.
+
+uwmf_print.c Contains the *_print functions needed to print the contents of WMF records and objects.
+
+uwmf_print.h Prototypes for *_print functions.
+
+uwmf_endian.c Contains the *_swap functions needed to rearrange bytes between Big and Little Endian.
+ U_wmf_endian() is the only function here that user could should call.
+
+uwmf_endian.h Prototype for U_wmf_endian() and definitions for Endian type of the local machine.
+
+
+testbed_emf.c Program used for testing emf functions in libUEMF. Run it like: testbed_emf flags.
+ Run with no argument to see what the bit flag values are.
+ It creates a test file "test_libuemf.emf" which should be identical to
+ test_libuemf_ref.emf. (This file cannot be imported from EMF into PowerPoint
+ because it contains dotted lines. Use "testbed_emf 1" to generate a file without
+ any dotted lines. )
+
+testbed_pmf.c Program used for testing EMF+ functions in libUEMF. Similar to testbed_emf.
+
+testbed_wmf.c Program used for testing wmf functions in libUEMF. Similar to testbed_emf.
+
+test_mapmodes_emf.c
+ Program used for testing emf functions in libUEMF. Generates one test file
+ in each MAPMODE, MM_TEXT through MM_ANISOTROPIC, optionally with offsets to the
+ bounds and with particular Viewport origin. (Bounds offset + Viewport Origin
+ sets the Window origin.)
+
+test_mapmodes_wmf.c
+ Program used for testing wmf functions in libUEMF. Similar to test_mapmodes_emf.
+
+reademf.c Utility that that reads an EMF file and emits its contents in text form.
+ Also processes EMF+ files.
+ Run it like: reademf target_file.emf
+
+readwmf.c Utility that that reads an WMF file and emits its contents in text form.
+ Run it like: reademf target_file.wmf
+
+cutemf.c Utility for removing specific records from an EMF file.
+ Run it like: cutemf '2,10,12...13' src_file.emf dst_file.emf
+
+pmfdual2single.c Utility for reducing dual-mode EMF+ file to single mode. Removes all
+ nonessential EMF records.
+ Run it like: pmfdual2single dual_mode.emf single_mode.emf
+
+
+test_libuemf_ref.emf
+ Example output from: testbed_emf 0
+test_libuemf_p_ref.emf
+ Example output from: testbed_pmf 0
+test_libuemf_ref30.emf
+ Example output from: testbed_emf 4
+test_libuemf_ref.wmf
+ Example output from: testbed_wmf 0
+
+test_libuemf_ref_emf.txt
+ Example output from: reademf test_libuemf_ref.emf
+test_libuemf_ref_wmf.txt
+ Example output from: readwmf test_libuemf_ref.wmf
+
+test_mm_<modes>_ref.emf
+ Example output from: test_mapmodes_emf -vX 2000 -vY 1000
+
+emf-inout.cpp,example
+emf-inout.h.example
+emf-print.cpp.example
+emf-print.h.example
+ Example code from Inkscape, demonstrates how to integrate libUEMF with another program.
+
+--------------------------------------------------------------------------------------------
+How to Build:
+
+In Linux/Unix like environments build and install a shared library and the test and tool
+programs:
+ cd <TOP_DIRECTORY>
+ #modify the destination in CMakeLists.txt if /usr/local is not acceptable
+ mkdir build
+ cd build
+ make
+ make install
+ cd ..
+ ./testit.sh
+ rm -rf build
+
+ For simple development work use testbuild.sh to make debug versions without the shared
+ library.
+
+ (Sparc)[ Solaris 8 and 9 are Big Endian, and to work around some minor incompatibilities with more recent systems,
+ assuming gcc is installed in /opt/csw and PATH is set correctly to use it]
+ export CLIBS="-lm -L/opt/csw/lib -liconv"
+ export CFLAGS="-DSOL8 -DWORDS_BIGENDIAN -std=c99 -pedantic -Wall -g"
+
+ (win32) [This uses _wfopen() instead of fopen(), with filename translation from UTF-8 to
+ UTF-16LE. This will allow file opens to utilize unicode names. If WIN32 is omitted on Windows
+ file names must be all ASCII. This works in mingw.] Then compile with:
+
+ export CLIBS="-lm -liconv"
+ export CFLAGS="-DWIN32 -std=c99 -pedantic -Wall -g"
+
+ gcc $CFLAGS -o cutemf cutemf.c uemf.c uemf_endian.c uemf_utf.c $CLIBS
+ gcc $CFLAGS -o pmfdual2single pmfdual2single.c uemf.c uemf_endian.c uemf_utf.c upmf.c $CLIBS
+ gcc $CFLAGS -o reademf reademf.c uemf.c uemf_endian.c uemf_safe.c uemf_print.c uemf_utf.c upmf.c upmf_print.c $CLIBS
+ gcc $CFLAGS -o readwmf readwmf.c uemf.c uemf_endian.c uemf_safe.c uemf_print.c uemf_utf.c upmf.c upmf_print.c uwmf.c uwmf_endian.c uwmf_print.c $CLIBS
+ gcc $CFLAGS -o testbed_emf testbed_emf.c uemf.c uemf_endian.c uemf_safe.c uemf_print.c uemf_utf.c upmf.c upmf_print.c $CLIBS
+ gcc $CFLAGS -o testbed_pmf testbed_pmf.c uemf.c uemf_endian.c uemf_safe.c uemf_utf.c upmf.c $CLIBS
+ gcc $CFLAGS -o testbed_wmf testbed_wmf.c uemf.c uemf_endian.c uemf_safe.c uemf_print.c uemf_utf.c upmf.c upmf_print.c uwmf.c uwmf_endian.c $CLIBS
+ gcc $CFLAGS -o test_mapmodes_emf test_mapmodes_emf.c uemf.c uemf_endian.c uemf_safe.c uemf_print.c uemf_utf.c upmf.c upmf_print.c $CLIBS
+
+Extra debugging on linux may be enabled in testbed for use under Valgrind. To build that way do instead:
+
+ gcc -std=c99 -pedantic -Wall -g -DU_VALGRIND -o testbed_emf testbed_emf.c uemf.c uemf_endian.c uemf_print.c uemf_utf.c -lm
+
+
+and then compile as above for linux.
+
+
+Dependencies:
+ libiconv (if not built into your compiler)
+ libpng (in the Inkscape examples)
+
+--------------------------------------------------------------------------------------------
+Testing
+
+All modules must also compile without warning under the more restrictive:
+
+ ls -1 *.c \
+ | extract -fmt 'gcc -Werror=format-security -Wall -Wformat -Wformat-security -W -Wno-pointer-sign -O2 -c -o deleteme.o [1,]' \
+ | execinput
+
+--------------------------------------------------------------------------------------------
+Using libUEMF:
+
+To write an EMF file the code first runs two initialization functions: emf_start() and htable_create().
+Then a U_EMRHEADER record is created. This and all subsequent records are appended to the EMF file in
+memory with emf_append(). Whichever other EMR records are desired are also added. The last EMR record
+added must be the single instance of U_EMREOF. Then the code calls emf_finish(), emf_free(), and
+htable_free(). Conversion of byte order on Big Endian machines to Little Endian is carried out
+automatically in emf_finish(), if it is required.
+
+To input an EMF file it is is opened and the data read into a buffer in memory with emf_readdata(). On a
+Big Endian machine this will also swap machine dependent byte orders as needed. At that point end user code
+generally has to do something with the data in each record. The simplest case is to just print it, as shown
+in reademf.c. More typically it must map the operations into its own graphics model, as shown in the
+emf32*.*.example files from Inkscape. Basically the processing program needs to enter a loop, processing
+one record at a time, pulling the record size and type from the first two uint32_t values present in each
+record. It then enters a switch statement with one case for each EMR record type. Each case: statement
+will generally define a pointer to that type of data object. Accessing the data from that pointer is
+illustrated in the code for the corresponding *_print function.
+
+While libUEMF implements _print and _swap functions for all supported EMR records, end user code would
+never call any of these directly. Instead it should either pass a single EMR record
+to U_emf_onerec_print() (see reademf.c) or the entire completed EMF file in memory buffer to U_emf_endian()
+(see testbed.c).
+
+WMF support is similar, except the functions are wmf_start(), wmf_readdata(), and so forth. It is a good
+idea to separate end user WMF and EMF generating code into different modules, in order to avoid accidentally
+writing EMR records to a WMF file and vice versa. WHile EMF objects are aligned in memory and so may be
+accessed using the supplied structs, the ones for WMF files are not usually aligned and so must be accessed
+using the supplied *_get functions. (The difference may not be evident on an x86 platform, but on RISC directly
+trying to access objects in memory will result in access violations.)
+
+Things to be aware of in EMF files:
+
+The usual idea when employing a graphics file type like EMF is to copy a description of the objects in a
+drawing from one program to another. Many of the record types in an EMF file can be thought of as objects,
+they are lines or shapes or bitmaps or text. However, Microsoft's GDI implements binary and ternary raster
+operations (see the descriptions in uemf.h) and most of these operations are not object like, instead they
+combine things on the drawing surface. (There is in each case a copy operation which is object like.)
+Consequently, EMF files which use these other raster operations are not particularly easy to import as
+graphic objects. For instance, when PowerPoint rotates an image and saves it in an EMF the result is not
+a single rotated image object. Instead there is an image containing the rotated image, which is followed by
+masking operations to make the regions outside of the image transparent. There appears to be no standard
+for when and where these subsequent operations will be applied. That is, there is no equivalent of
+"begin path" and "end path" to delineate the start and end of such a compound operation. So a program
+reading such a file has no easy way of figuring out which previous object is being modified by a subsequent
+raster operation. The testbed program provided in this package generates a region which applies all
+binary raster operations in vertical slices to two images. The expected result appears in Windows "Preview",
+but if that region is imported into PowerPoint and converted to objects within that program the result looks
+nothing like what Preview shows.
+
+Support for U_EMREXTTEXTOUTW is much more common than for U_EMRSMALLTEXT. The latter is easier to use,
+since it does not require a Dx array for each text string, but the objects will not import into PowerPoint,
+for instance.
+
+There are two types of dotted/dashed lines. The first uses a set of predefined flags to set the pattern
+and the latter is end user user defined. Both are restricted to lines of width 1. These built in types are
+problematic as key applications cannot handle them properly. PowerPoint cannot convert either type to its
+internal object format. The first form loses the pattern and comes through as solid lines. The second type
+is toxic - even a single dotted line of the second type will prevent the entire EMF from being converted.
+The safest choice is to avoid these patterned line styles entirely. Convert all dots and dashes to separate
+line draws before writing those into the EMF file. libUEMF has no problem reading these records, so code
+should accept them for input.
+
+As with most graphics file formats there is no single object representation of a complex text string (varying
+font size, super/sub script, bold, italic,.etc.). Such text must be decomposed into multiple text strings,
+each with its own formatting. It is unlikely that a subsequent program reading these records from the EMF
+will be able to reassemble them back into a single complex text string.
+
+If a font used in an EMF file is not present on both the sending and receiving systems text will not look the
+same on both. Font substitution is usually silent in most programs, so it may not be evident why the text looks
+a little odd. However, if text is simple, that is, consists of just one line of text without size, color,
+or other changes, then it will look approximately correct after font substitution.
+
+Things to be aware of in WMF files:
+
+WMF graphics are quite limited when compared to EMF graphics. When reading a WMF file it is essential that
+end user code always create a specified object, even if that object is just a placeholder with no real
+function. If any "create" operation presented by the WMF file is not handled then the object indices used
+further along in the WMF file will be off, with very bad results! WMF "regions" are not supported by libUEMF,
+however, if an operation creates regions, this type of placeholder must still be created.
+
+In theory WMF supports mapmodes other than Anisotropic. However, since many programs do not handle
+these other modes it is strongly suggested that any WMF files generated use Anisotropic. For this
+reason there is no test_mapmodes_wmf program - windows XP preview did not show anything when WMF
+files in the other modes were produced. With no positive control there was no way to verify that they
+were valid.
+
+Things to be aware of in EMF+ files:
+
+EMF+ files are usually stored in files with an ".emf" file extension. In this package EMF+ programs,
+functions, and definitions use PMF or PMR to distinguish them from the EMF and WMF material. ("EMF+"
+is not an allowed variable or function name in C.) Dual mode EMF+ files contain both EMF and
+EMF+ records. HOWEVER, those generated by PowerPoint are defective in that they drop all text
+information from the drawing in the EMF+ representation. There is no simple way to line up the
+EMF and EMF+ records in their representations to determine which ones correspond to which drawing
+object. So it is generally not possible to see which elements are represented in both
+representations, or which are missing in one representation. The example file generated by this library
+has only EMF+ records plus the few EMF records needed to wrap them.
+
+Text in EMF+ is placed not from the baseline, as in EMF, but from the upper left corner of the Em square.
+Use the utility function U_PMR_drawstring() to draw text onto a baseline. Font
+substitutions result in badly placed text because even fonts that look similar on the screen may have
+different font metrics. Specifically, font substitutions look worse in EMF+ files than they do
+in EMF files. There is no way to embed fonts, or their font information in the EMF+ file.
+Consequently the text representation within an EMF+ file is not very portable between systems - it will
+only render correctly if the second system has all of the fonts used in the document. The testbed_pmf.c
+program contains some metrics for common fonts which may be used with U_PMR_drawstring()
+to accurately place text.
+
+
+
+--------------------------------------------------------------------------------------------
+History
+
+ (Note, version numbers in files represent the libUEMF release where it was last modified, so not
+ all files will show the same version numbers in each release.)
+
+0.2.8 2020-05-13
+ Fixed warnings from newer compilers.
+ Fixed truncation of one string in testbed outputs files,
+ from 32 to 31 bytes (seen on CentOS 8 with gcc 8.3.1
+ but not CentOS 7 with gcc 4.8.5)
+0.2.7 2019-10-10
+ Added CMakeLists.txt for linux.
+ Added cmake instructions in README.
+ Fixed typo in README build instructions.
+ Error checking added to testit.sh.
+ Increased max records in cutemf from 10K to 10M.
+0.2.6 2019-03-21
+ Fixed typo in upmf.c discovered by David Binderman.
+0.2.5 2017-01-03
+ Fixed a misplaced paren in uemf.h (thanks to Tavmjong Bah for noticing it)
+ Added more U_SIZE_* definitions in uemf.h for "cores" of record types with final
+ variable length arrays, such as U_SIZE_EMRNAMEDESCAPE
+ Removed redundant U_SIZE_BITMAPINFOHEADER definition from uwmf.h
+0.2.4 2016-01-26
+ Record EXTSELECTCLIPRGN is supposed to be valid when the RgnDataSize is 0 if the RegionMode
+ is "COPY". Modified safe and print routines so that they would handle this situation.
+ U_PMR_DrawDriverstring seen for the first time and it crashed reademf. Reason, there was a spurious
+ "Tension" value in the structure, which offset values in the record.
+0.2.3 2015-05-28
+ Fixed an assortment of warnings and a couple of bugs flagged by clang static analysis.
+0.2.2 2015-04-28
+ Added lu_crc32 sums to record information in print statements. Affects only reademf and readwmf.
+ The point of this exercise is to enable the detection of differences in binary fields
+ which are not expanded by the print functions. This (re)uses code from Alexander Peslyak.
+ lu_ in name because crc32 conflicts with other libraries, like png.
+ Minor changes to some wmf function parameter types.
+ Minor changes to upmf.c so that it compiles cleanly with clang.
+ Restrict IS_MEM_UNSAFE 2nd parameter to be int or larger and test for negative values.
+ Updated the examples from Inkscape.
+
+0.2.1 2015-04-23
+ Bug in safety check on EMREXTCREATEFONTINDIRECTW because it had alternative "standard" record sizes.
+ Changed warnings on unimplemented EMF record types encounterd in swap or safe from stdout to stderr.
+ Added memory checking for WMF polyline and polygon records, for the variable part and some others.
+ Note: U_WMRCREATEREGION_get does not check that the variable part stays within the record. Current
+ implementation seems to be broken since it does not show up in XP preview.
+0.2.0 2015-03-20
+ Added UEMF _safe functions to better handle corrupt records, where variable sizes fields might
+ have been specified to read past the end of memory. These are records with offsets, arrays
+ with counts, and bitmaps. Also any record which specifies a size smaller than the minimum
+ for that record type.
+ Added similar code for EMF+.
+ These changed the API so the minor version number was bumped by 1.
+
+0.1.18 2015-01-15
+ Pierre-Francois Carpentier sent some EMF examples which used U_EMR_EXTSELECTCLIPRGN, which had
+ not previously been encountered and showed that the handling of regions was broken.
+ Added tests for U_EMRFILLRGN, U_EMRFRAMERGN, U_EMRFRAMERGN, U_EMREXTSELECTCLIPRGN to testbed_emf.
+
+0.1.18 2014-04-28
+ Fixed typo in testbed_wmf.c. "include,include" in one place should have been
+ "exclude,exclude".
+
+0.1.17 2014-04-25
+ Added text clipping tests to testbed_emf.c, testbed_wmf.c, and testbed_pmf.c.
+ Added option to omit clipping tests in testbed's.
+
+0.1.16 2014-04-14
+ Fixed bug in U_WMRRESTOREDC_set.
+ Added clipping tests to testbed_wmf.c.
+
+0.1.15 2014-04-04
+ Changed record flags for U_EMRSELECTCLIPPATH record, it consumes a path but does not ALTER (which
+ forced a premature draw.)
+ Added U_EMROFFSETCLIPRGN test to testbed_emf.c.
+ Changed location on dist drawing where clipping appears.
+
+0.1.14 2014-03-27
+ Fixed bug, in U_PMF_RECTN_set() in upmf.c. Never tested.
+ Fixed a few potential bugs in upmf.c if a null pointer was passed for
+ certain function arguments. (Previously unhandled cases.)
+ Fixed bug, operations setting variables that are never read along those
+ execution paths: upmf_print.c, uemf.c, uwmf.c, uemf_endian.cm upmf.c.
+ Fixed potential (but very unlikely) memory leaks in upmf.c and uemf_utf.c.
+ Added test of U_PMF_RECTN_set to testbed_pmf.c.
+ Changed U_wmr_names() and U_wmr_escnames() to const char* (from char*).
+ Changed method for suppressing unused parameter warnings.
+
+
+0.1.13 2014-03-21
+ Fixed bug, cutemf was messing up the object count (pens, brushes, etc.).
+ Added cutemf can now take ranges of lines.
+ Added testbed_emf generates clipping records for rect and path (but not region).
+
+0.1.12 2014-02-14
+ Documentation change, U_WMRCREATEPATTERNBRUSH is obsolete.
+ Changed wmf_finish() so that it accurately reflects the largest number of objects used,
+ previously it showed the number of appends, which was much larger.
+
+0.1.11 2014-01-29
+ Fixed bug in uwmf.c (wrong minimum record size on U_WMRTEXTOUT)
+ Fixed bug in uwmf.c (U_WMRCREATEPATTERNBRUSH not right)
+ Fixed bug in uwmf_print.c (U_WMRTEXTOUT_print, x,y were reversed)
+ Added error handling to uemf_utf.c for cases where src is a null pointer.
+ Added a test of createpatternbrush to testlib_wmf
+
+0.1.10 2014-01-14
+ Slight changes in documentation for uemf.h.
+ Fixed typo in uemf_endian.c.
+ Fixed a tiny bug in uemf.c (if memory allocation failed a struct would have
+ been deleted before the struct itself.
+
+0.1.9 2013-12-02
+ Added U_PMF_DASHEDLINEDATA_set3 (dot/dash pattern from bits in a uint32_t).
+ Finally was able to make linear gradient gradientfill records work. Updated
+ testbed_emf.c to include that.
+
+0.1.8 2013-11-28
+ Fixed a bug in U_PMF_REGIONNODEPATH_print(), returned size was 4 too small.
+ Changed formatting of U_PMF_REGIONNODECHILDNODES_print() output to improve readability
+ of nested region structures in reademf.
+
+0.1.7 2013-11-20
+ Added EMF+ support.
+ Converted U_RGA and similar from defines to functions, because the method being used
+ in the define (from C99) was not exactly compatible with C++ compilation.
+ Fixed error in test_mapmodes_emf.c where truncation float to integer was used where round
+ have been, resulting in an off by 1 error on some platforms.
+ Eliminated PU_W* pointers.
+ Cleaned up Doxygen comments.
+
+0.1.6. 2013-04-18
+ Added tests which vary background mode, background color, and text color.
+ Slight modification to testit.sh.
+ Updated example files.
+
+0.1.5. 2013-02-13
+ Added missing parameter for WMF RESTOREDC_set/get.
+ Replaced all sizeof() in uwmf.c that referred to UWMF structures with their
+ U_SIZE_* equivalents.
+ Added DIB related WMF _get functions. (Which were missing). These are U_BITMAPCOREHEADER_get,
+ U_BITMAPINFOHEADER_get, wget_dib_params
+ Added const where appropriate to wmf _get functions.
+ Added comprehensive cap,join,miter tests to testbeds.
+ Fixed bug in gradient4_swap().
+ Fixed bug in emr_arc_points_common(), used vector where unit vectors were
+ needed, sometimes flipped direction for arcs/chords.
+ Fixed bug in U_WMFTEXTOUT_get().
+ Changed all dst->Dst and src->Src as call variables in WMF code.
+ Denigrated htable_*() for emf, these become emf_htable_*(), to match naming convention
+ used for wmf_table_*().
+0.1.4 2013-02-04
+ Added code to handle DIB formats that use clrUsed=0 to mean "maximum number of color entries",
+ this showed up in several places, including uemf.c and uemf_print.c.
+ Added some labels to test drawings, slightly rearranged image section, added
+ PNG and JPG image tests and clrUsed=0 images.
+ Modified uemf_endian.c to suppress some compiler warnings.
+ Changed get_DIB_params to return the Compression enumeration.
+ Fixed a typo in uwmf_print.c.
+0.1.3 2013-01-29 Add modes to EMF test programs that changes worldtransform, so
+ that the resulting test files will exercise rotation transforms.
+ Added flags indication for testbed programs.
+ Added test for ROUNDRECT records. Swapped argument orders for those _get/_set operations.
+0.1.2 2013-01-25 Fixed bug revealed by newer gcc on Solaris, assignment of aligned 32 bit to unaligned
+ 16 bit segfaulted.
+0.1.1 2013-01-24 Fixed a few compiler warnings under g++, mostly having to do
+ with signed unsigned comparisons. Eliminated
+ an unused variable from wmf_finish and two stray lines from U_WMRHEADER_set.
+ Cleaned up doxygen comments.
+0.1.0 2013-01-09 Added WMF functions.
+ Simplified print functions. Changed output format of reademf slightly,
+ from U_EMRXXX to U_EMR_XXX - easier to read the new way.
+0.0.11 2012-12-04 Moved UTF and related functions out of uemf.c uemf.h and into uemf_utf.c uemf_utf.h.
+0.0.10 2012-11-28 Discovered that not enough space was being allocated for some UTF conversions. To be
+ safe need 4 bytes per glyph + 1 for UTF-8.
+0.0.9 2012-09-26 Some "uninitialized variable warnings" for certain versions of
+ gcc. These were, as far as I could tell, all spurious, but to quiet them
+ the variables in question were all initialized to 0.
+ Fixed header related print/swap functions - depending on what type of header there
+ could be an access violation.
+ Fixed U_Utf16leToUtf8, could leak memory if the conversion failed.
+ Fixed sections which were not testing for all types of EMF headers.
+ Added RGBA_to_RGBA() so that extractions of subsets of bitmaps (offset, different size)
+ can be handled.
+ Added cutemf. Utility to remove records from an EMF file.
+ Added test_mapmodes. Program to generate test files in each MAPMODE.
+ Added test_mm_(mode)_ref.emf files. These are reference for:
+ test_mapmodes -vX 2000 -vY 1000
+
+0.0.8 2012-09-10 Fixed bug in htable_insert, failed to celear newly added table
+ slots. Fixed test for EMR_GRADIENTFILL triangle mode (rectangle still produces toxic EMF files.)
+ Fixed bug in gradientfill_swap on Solaris.
+
+0.0.7 2012-08-30 Added/fixed tests for hatched, DIB, and mono strokes.
+ Corrected error in U_EMREXTCREATEPEN_set.
+
+0.0.6 2012-08-21 Added/fixed tests for hatched, DIB, and mono fills.
+
+0.0.5 2012-08-08 Minor changes to uemf.c to suppress compiler warnings. Fixed
+ one bug in SET_CB_FROM_PXBMI macro (which was not triggered in testbed
+ because all images were the same size).
+
+0.0.4 2012-07-25 More tests in testbed.c. Found and fixed bugs in
+ U_POLYPOLYLINE and U_POLYPOLYGON related code.
+
+0.0.3 2012-07-24 Warnings related to printing size_t on 64 bit Linux. Correct
+ fix is to use "zd", but gcc -std=c99 does not support that on Solaris 9,
+ the only available big endian system. So use cast or the size_t to (int)
+ and stick with %d format specifier. This should be OK as the sizes involved
+ should not be all that large.
+
+ Bug in core9 affecting U_EMRARC_swap(), and related, on Big Endian.
+
+0.0.2 2012-07-12 first release
+
diff --git a/src/3rdparty/libuemf/symbol_convert.c b/src/3rdparty/libuemf/symbol_convert.c
new file mode 100644
index 0000000..6a919fc
--- /dev/null
+++ b/src/3rdparty/libuemf/symbol_convert.c
@@ -0,0 +1,1008 @@
+/** @file
+ * @brief Windows-only Enhanced Metafile input and output.
+ */
+/* Authors:
+ * David mathog <mathog@caltech.edu>
+ *
+ * Copyright (C) 2012 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ *
+ * References:
+ * see unicode-convert.h
+ *
+ * v1.4 08/21/2012 Changed this so that the incoming routines use uint32_t and the outgoing use uint16_t. This gets rid
+ * of wchar_t, which was different sizes on windows/linux, and required lots of ifdef's elsewhere in the code.
+ * v1.3 04/03/2012 Bullets were a problem. Symbol bullet -> Times New Roman Bullet looks OK, but
+ * it looked bad going the other way. Changed mapping Symbol bullet to 2219 (Bullet operator, math
+ * symbol.) That way Symbol bullet can map in and out, while other font bullet an remain in that
+ * font's bullet glyph.
+ * v1.2 03/26/2012 Introduced bug into SingleUnicodeToNon repaired.
+ * v1.1 03/25/2012 Changed ampersand mapping on Wingdings (to avoid normal Ampersand mapping
+ * to Wingdings ampersand when not intended. Fixed access bugs for when no conversion is
+ * mapped in UnicodeToNon and SingleUnicodeToNon
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include "symbol_convert.h"
+
+
+static bool hold_symb=0; // if any of these change, (re)generate the map table
+static bool hold_wing=0;
+static bool hold_zdng=0;
+static bool hold_pua=0;
+static unsigned char *from_unicode=NULL;
+static unsigned char *to_font=NULL;
+
+/* The following tables were created from the files
+ adobe-dingbats.enc.gz
+ adobe-symbol.enc.gz
+ adobe-standard.enc.gz
+
+ which came as part of the X11-font-encodings rpm on Mandriva 2010.
+ The original source for the data must have been Adobe.
+ Some also from:
+ ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/ADOBE/symbol.txt
+ http://www.csn.ul.ie/~caolan/wingdings/proposal/
+ www.renderx.com/Tests/zapf-dingbats.pdf
+
+ The intent is as follows:
+
+ on conversion from ASCII/extended -> Unicode use the appropriate table for
+ the font and change font + code (symbol, zapf dingbats, wingdings).
+ Going the other way, set up two transfer tables,
+ the first is unicode -> 0-FF values, and the seond is unicode -> cvt_to_font.
+ These tables are filled dingbats, wingdings, then symbols, so with the rightmost one getting
+ precedence if both contain the symbol.
+
+ Whereever possible do NOT map two input characters to the same output character, use a slightly
+ off character if it is somewhat close and disambiguates.
+
+v 1.0.0 14-MAR-2012, David Mathog
+
+*/
+
+static unsigned int wingdings_convert[256]={
+ 0xFFFD, // 0x00 no replacement
+ 0xFFFD, // 0x01 no replacement
+ 0xFFFD, // 0x02 no replacement
+ 0xFFFD, // 0x03 no replacement
+ 0xFFFD, // 0x04 no replacement
+ 0xFFFD, // 0x05 no replacement
+ 0xFFFD, // 0x06 no replacement
+ 0xFFFD, // 0x07 no replacement
+ 0xFFFD, // 0x08 no replacement
+ 0xFFFD, // 0x09 no replacement
+ 0xFFFD, // 0x0A no replacement
+ 0xFFFD, // 0x0B no replacement
+ 0xFFFD, // 0x0C no replacement
+ 0xFFFD, // 0x0D no replacement
+ 0xFFFD, // 0x0E no replacement
+ 0xFFFD, // 0x0F no replacement
+ 0xFFFD, // 0x10 no replacement
+ 0xFFFD, // 0x11 no replacement
+ 0xFFFD, // 0x12 no replacement
+ 0xFFFD, // 0x13 no replacement
+ 0xFFFD, // 0x14 no replacement
+ 0xFFFD, // 0x15 no replacement
+ 0xFFFD, // 0x16 no replacement
+ 0xFFFD, // 0x17 no replacement
+ 0xFFFD, // 0x18 no replacement
+ 0xFFFD, // 0x19 no replacement
+ 0xFFFD, // 0x1A no replacement
+ 0xFFFD, // 0x1B no replacement
+ 0xFFFD, // 0x1C no replacement
+ 0xFFFD, // 0x1D no replacement
+ 0xFFFD, // 0x1E no replacement
+ 0xFFFD, // 0x1F no replacement
+ 0x0020, // 0x20 SPACE
+ 0x270E, // 0x21 LOWER RIGHT PENCIL (close, but not exact)
+ 0x2702, // 0x22 BLACK SCISSORS
+ 0x2701, // 0x23 UPPER BLADE SCISSORS
+ 0xFFFD, // 0x24 no replacement
+ 0xFFFD, // 0x25 no replacement
+ 0xFFFD, // 0x26 no replacement
+ 0xFFFD, // 0x27 no replacement
+ 0x260E, // 0x28 BLACK TELEPHONE
+ 0x2706, // 0x29 TELEPHONE LOCATION SIGN (close, but not exact)
+ 0x2709, // 0x2A ENVELOPE
+ 0x2709, // 0x2B ENVELOPE (close, but not exact)
+ 0xFFFD, // 0x2C no replacement
+ 0xFFFD, // 0x2D no replacement
+ 0xFFFD, // 0x2E no replacement
+ 0xFFFD, // 0x2F no replacement
+ 0xFFFD, // 0x30 no replacement
+ 0xFFFD, // 0x31 no replacement
+ 0xFFFD, // 0x32 no replacement
+ 0xFFFD, // 0x33 no replacement
+ 0xFFFD, // 0x34 no replacement
+ 0xFFFD, // 0x35 no replacement
+ 0x231B, // 0x36 HOURGLASS
+ 0x2328, // 0x37 KEYBOARD
+ 0xFFFD, // 0x38 no replacement
+ 0xFFFD, // 0x39 no replacement
+ 0xFFFD, // 0x3A no replacement
+ 0xFFFD, // 0x3B no replacement
+ 0xFFFD, // 0x3C no replacement
+ 0xFFFD, // 0x3D no replacement
+ 0x2707, // 0x3E TAPE DRIVE
+ 0x270D, // 0x3F WRITING HAND
+ 0x270D, // 0x40 WRITING HAND (close, but not exact)
+ 0x270C, // 0x41 VICTORY HAND
+ 0xFFFD, // 0x42 3 FINGER UP HAND (no replacement)
+ 0xFFFD, // 0x43 THUMBS UP HAND (no replacement)
+ 0xFFFD, // 0x44 THUMBS DOWN HAND (no replacement)
+ 0x261C, // 0x45 WHITE LEFT POINTING INDEX
+ 0x261E, // 0x46 WHITE RIGHT POINTING INDEX
+ 0x261D, // 0x47 WHITE UP POINTING INDEX
+ 0x261F, // 0x48 WHITE DOWN POINTING INDEX
+ 0xFFFD, // 0x49 OPEN HAND (no replacement)
+ 0x263A, // 0x4A WHITE SMILING FACE
+ 0x263A, // 0x4B WHITE SMILING FACE (close, but not exact)
+ 0x2639, // 0x4C WHITE FROWNING FACE
+ 0xFFFD, // 0x4D BOMB (no replacement. 1F4A3)
+ 0x2620, // 0x4E SKULL AND CROSSBONES
+ 0x2690, // 0x4F WHITE FLAG (not exact)
+ 0x2691, // 0x50 WHITE PENANT (use BLACK FLAG)
+ 0x2708, // 0x51 AIRPLANE
+ 0x263C, // 0x52 WHITE SUN WITH RAYS (close, but not exact)
+ 0x2602, // 0x53 RAINDROP (use UMBRELLA)
+ 0x2744, // 0x54 SNOWFLAKE
+ 0x271D, // 0x55 WHITE LATIN CROSS (use BLACK CROSS)
+ 0x271E, // 0x56 SHADOWED WHITE LATIN CROSS
+ 0x271F, // 0x57 CELTIC CROSS (use OUTLINED LATIN CROSS)
+ 0x2720, // 0x58 MALTESE CROSS
+ 0x2721, // 0x59 STAR OF DAVID
+ 0x262A, // 0x5A STAR AND CRESCENT
+ 0x262F, // 0x5B YIN YANG
+ 0x0950, // 0x5C DEVANGARI OM CORRECT|CLOSE: Perhaps PROPOSE SACRED OM ?
+ 0x2638, // 0x5D WHEEL OF DHARMA
+ 0x2648, // 0x5E ARIES
+ 0x2649, // 0x5F TAURUS
+ 0x264A, // 0x60 GEMINI
+ 0x264B, // 0x61 CANCER
+ 0x264C, // 0x62 LEO
+ 0x264D, // 0x63 VIRGO
+ 0x264E, // 0x64 LIBRA
+ 0x264F, // 0x65 SCORPIUS
+ 0x2650, // 0x66 SAGITTARIUS
+ 0x2651, // 0x67 CAPRICORN
+ 0x2652, // 0x68 AQUARIUS
+ 0x2653, // 0x69 PISCES
+ 0xFFFD, // 0x6A LOWER CASE AMPERSAND)?) (no replacement)
+ 0xFF06, // 0x6B AMPERSAND (use FULL WIDTH AMPERSAND, close, but not exact. Do NOT use 0026, or it maps normal Ampersands to Wingdings Ampersand)
+ 0x25CF, // 0x6C BLACK CIRCLE
+ 0x274D, // 0x6D SHADOWED WHITE CIRCLE (close, but not exact)
+ 0x25A0, // 0x6E BLACK SQUARE
+ 0x25A3, // 0x6F WHITE SQUARE IN BLACK RECTANGLE (use BLACK SQUSRE in WHITE SQUARE)
+ 0x25A1, // 0x70 WHITE SQUARE (close, but not exact)
+ 0x2751, // 0x71 LOWER RIGHT SHADOWED WHITE SQUARE
+ 0x2752, // 0x72 UPPER RIGHT SHADOWED WHITE SQUARE
+ 0x25CA, // 0x73 LOZENGE (close, but not exact)
+ 0x25CA, // 0x74 LOZENGE (close, but not exact)
+ 0x25C6, // 0x75 BLACK DIAMOND
+ 0x2756, // 0x76 BLACK DIAMOND MINUS WHITE X
+ 0x25C6, // 0x77 BLACK DIAMOND (close, but not exact)
+ 0x2327, // 0x78 X IN A RECTANGLE BOX
+ 0x2353, // 0x79 APL FUNCTIONAL SYMBOL QUAD UP CARET(close, but not exact)
+ 0x2318, // 0x7A PLACE OF INTEREST SIGN
+ 0x2740, // 0x7B WHITE FLORETTE (close, but not exact)
+ 0x273F, // 0x7C BLACK FLORETTE (close, but not exact)
+ 0x275D, // 0x7D HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT
+ 0x275E, // 0x7E HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT
+ 0xFFFD, // 0x7F unused
+ 0x24EA, // 0x80 CIRCLED DIGIT ZERO
+ 0x2460, // 0x81 CIRCLED DIGIT ONE
+ 0x2461, // 0x82 CIRCLED DIGIT TWO
+ 0x2462, // 0x83 CIRCLED DIGIT THREE
+ 0x2463, // 0x84 CIRCLED DIGIT FOUR
+ 0x2464, // 0x85 CIRCLED DIGIT FIVE
+ 0x2465, // 0x86 CIRCLED DIGIT SIX
+ 0x2466, // 0x87 CIRCLED DIGIT SEVEN
+ 0x2467, // 0x88 CIRCLED DIGIT EIGHT
+ 0x2468, // 0x89 CIRCLED DIGIT NINE
+ 0x2469, // 0x8A CIRCLED NUMBER TEN
+ 0xFFFD, // 0x8B no replacement
+ 0x2776, // 0x8C DINGBAT NEGATIVE CIRCLED DIGIT ONE
+ 0x2777, // 0x8D DINGBAT NEGATIVE CIRCLED DIGIT TWO
+ 0x2778, // 0x8E DINGBAT NEGATIVE CIRCLED DIGIT THREE
+ 0x2779, // 0x8F DINGBAT NEGATIVE CIRCLED DIGIT FOUR
+ 0x277A, // 0x90 DINGBAT NEGATIVE CIRCLED DIGIT FIVE
+ 0x277B, // 0x91 DINGBAT NEGATIVE CIRCLED DIGIT SIX
+ 0x277C, // 0x92 DINGBAT NEGATIVE CIRCLED DIGIT SEVEN
+ 0x277D, // 0x93 DINGBAT NEGATIVE CIRCLED DIGIT EIGHT
+ 0x277E, // 0x94 DINGBAT NEGATIVE CIRCLED DIGIT NINE
+ 0x277F, // 0x95 DINGBAT NEGATIVE CIRCLED NUMBER TEN
+ 0xFFFD, // 0x96 ROTATED FLORAL HEART BULLET (no good replacement)
+ 0xFFFD, // 0x97 REVERSED ROTATED FLORAL HEART BULLET (no good replacement)
+ 0xFFFD, // 0x98 REVERSED ROTATED FLORAL HEART BULLET (no good replacement)
+ 0xFFFD, // 0x99 ROTATED FLORAL HEART BULLET (no good replacement)
+ 0xFFFD, // 0x9A ROTATED FLORAL HEART BULLET (no good replacement)
+ 0xFFFD, // 0x9B REVERSED ROTATED FLORAL HEART BULLET (no good replacement)
+ 0xFFFD, // 0x9C REVERSED ROTATED FLORAL HEART BULLET (no good replacement)
+ 0xFFFD, // 0x9D ROTATED FLORAL HEART BULLET (no good replacement)
+ 0x2219, // 0x9E BULLET (use BULLET operator, so normal font BULLET will not convert to Symbol BULLET)
+ 0x25CF, // 0x9F BLACK CIRCLE (close, but not exact)
+ 0x25AA, // 0xA0 BLACK VERY SMALL SQUARE
+ 0x26AA, // 0xA1 WHITE CIRCLE (use MEDIUM WHITE CIRCLE)
+ 0x25CB, // 0xA2 HEAVY WHITE CIRCLE (use WHITE CIRCLE)
+ 0x25CD, // 0xA3 HEAVIEST CIRCLE (use CIRCLE WITH VERTICAL FILL)
+ 0x25C9, // 0xA4 CIRCLE WITH A CENTRAL DOT (close, dot much bigger)
+ 0x25CE, // 0xA5 BULLSEYE
+ 0x274D, // 0xA6 SHADOWED WHITE CIRCLE (close, but not exact)
+ 0xFFED, // 0xA7 BLACK SMALL SQUARE
+ 0x2610, // 0xA8 WHITE SQUARE (close, but not exact, different fro 25A1)
+ 0xFFFD, // 0xA9 no replacement
+ 0x2726, // 0xAA BLACK FOUR POINTED STAR MAYBE
+ 0x2605, // 0xAB BLACK STAR
+ 0x2736, // 0xAC SIX POINTED BLACK STAR
+ 0x2737, // 0xAD EIGHT POINTED RECTILINEAR BLACK STAR
+ 0x2738, // 0xAE TWELVE POINTED BLACK STAR
+ 0x2735, // 0xAF EIGHT POINTED PINWHEEL STAR
+ 0xFFFD, // 0xB0 no replacement
+ 0xFFFD, // 0xB1 no replacement
+ 0x2727, // 0xB2 WHITE FOUR POINTED STAR
+ 0x2726, // 0xB3 ROTATED WHITE FOUR POINTED STAR (use BLACK FOUR POINTED STAR)
+ 0xFFFD, // 0xB4 REPLACEMENT CHARACTER (close, but not exact)
+ 0x272A, // 0xB5 CIRCLED WHITE STAR
+ 0x2730, // 0xB6 SHADOWED WHITE STAR
+ 0xFFFD, // 0xB7 ANALOG CLOCK 1 (no replacement)
+ 0xFFFD, // 0xB8 ANALOG CLOCK 2 (no replacement)
+ 0xFFFD, // 0xB9 ANALOG CLOCK 3 (no replacement)
+ 0xFFFD, // 0xBA ANALOG CLOCK 4 (no replacement)
+ 0xFFFD, // 0xBB ANALOG CLOCK 5 (no replacement)
+ 0xFFFD, // 0xBC ANALOG CLOCK 6 (no replacement)
+ 0xFFFD, // 0xBD ANALOG CLOCK 7 (no replacement)
+ 0xFFFD, // 0xBE ANALOG CLOCK 8 (no replacement)
+ 0xFFFD, // 0xBF ANALOG CLOCK 9 (no replacement)
+ 0xFFFD, // 0xC0 ANALOG CLOCK 10 (no replacement)
+ 0xFFFD, // 0xC1 ANALOG CLOCK 11 (no replacement)
+ 0xFFFD, // 0xC2 ANALOG CLOCK 12 (no replacement)
+ 0x21B2, // 0xC3 TURN ARROW DOWN AND LEFT (Meaning close, shape differs)
+ 0x21B3, // 0xC4 TURN ARROW DOWN AND RIGHT (Meaning close, shape differs)
+ 0x21B0, // 0xC5 TURN ARROW UP AND LEFT (Meaning close, shape differs)
+ 0x21B1, // 0xC6 TURN ARROW UP AND RIGHT (Meaning close, shape differs)
+ 0x2B11, // 0xC7 TURN ARROW LEFT AND UP (Meaning close, shape differs)
+ 0x2B0F, // 0xC8 TURN ARROW RIGHT AND UP (Meaning close, shape differs)
+ 0x2B10, // 0xC9 TURN ARROW LEFT AND DOWN (Meaning close, shape differs)
+ 0x2B0E, // 0xCA TURN ARROW RIGHT AND DOWN (Meaning close, shape differs)
+ 0xFFFD, // 0xCB no replacement
+ 0xFFFD, // 0xCC no replacement
+ 0xFFFD, // 0xCD no replacement
+ 0xFFFD, // 0xCE no replacement
+ 0xFFFD, // 0xCF no replacement
+ 0xFFFD, // 0xD0 no replacement
+ 0xFFFD, // 0xD1 no replacement
+ 0xFFFD, // 0xD2 no replacement
+ 0xFFFD, // 0xD3 no replacement
+ 0xFFFD, // 0xD4 no replacement
+ 0x232B, // 0xD5 ERASE TO THE LEFT
+ 0x2326, // 0xD6 ERASE TO THE RIGHT
+ 0x25C0, // 0xD7 THREE-D LIGHTED LEFT ARROWHEAD (Use BLACK LEFT TRIANGLE)
+ 0x25B6, // 0xD8 THREE-D LIGHTED RIGHT ARROWHEAD (Use BLACK RIGHT TRIANGLE, 27A2 is exact but has no other directions)
+ 0x25B2, // 0xD9 THREE-D LIGHTED UP ARROWHEAD (Use BLACK UP TRIANGLE)
+ 0x25BC, // 0xDA THREE-D LIGHTED DOWN ARROWHEAD (Use BLACK DOWN TRIANGLE)
+ 0xFFFD, // 0xDB no replacement
+ 0x27B2, // 0xDC CIRCLED HEAVY WHITE RIGHTWARDS ARROW
+ 0xFFFD, // 0xDD no replacement
+ 0xFFFD, // 0xDE no replacement
+ 0x2190, // 0xDF LEFT ARROW
+ 0x2192, // 0xE0 RIGHT ARROW
+ 0x2191, // 0xE1 UP ARROW
+ 0x2193, // 0xE2 DOWN ARROW
+ 0x2196, // 0xE3 UPPER LEFT ARROW
+ 0x2197, // 0xE4 UPPER RIGHT ARROW
+ 0x2199, // 0xE5 LOWER LEFT ARROW
+ 0x2198, // 0xE6 LOWER RIGHT ARROW
+ 0x2B05, // 0xE7 HEAVY LEFT BLACK ARROW (same as regular BLACK ARROW)
+ 0x2B08, // 0xE8 HEAVY RIGHT BLACK ARROW (same as regular BLACK ARROW)
+ 0x2B06, // 0xE9 HEAVY UP BLACK ARROW (no equiv BLACK ARROW)
+ 0x2B07, // 0xEA HEAVY DOWN BLACK ARROW (same as regular BLACK ARROW)
+ 0x2B09, // 0xEB HEAVY UPPER LEFT BLACK ARROW same as regular BLACK ARROW)
+ 0x2B08, // 0xEC HEAVY UPPER RIGHT BLACK ARROW same as regular BLACK ARROW)
+ 0x2B0B, // 0xED HEAVY LOWER LEFT BLACK ARROW (same as regular BLACK ARROW)
+ 0x2B0A, // 0xEE HEAVY LOWER RIGHT BLACK ARROW (same as regular BLACK ARROW)
+ 0x21E6, // 0xEF LEFTWARDS WHITE ARROW
+ 0x21E8, // 0xF0 RIGHTWARDS WHITE ARROW
+ 0x21E7, // 0xF1 UPWARDS WHITE ARROW
+ 0x21E9, // 0xF2 DOWNWARDS WHITE ARROW
+ 0x21D4, // 0xF3 LEFT RIGHT DOUBLE ARROW
+ 0x21D5, // 0xF4 UP DOWN DOUBLE ARROW
+ 0x21D6, // 0xF5 NORTH WEST DOUBLE ARROW (close, but not exact)
+ 0x21D7, // 0xF6 NORTH EAST DOUBLE ARROW (close, but not exact)
+ 0x21D9, // 0xF7 SOUTH WEST DOUBLE ARROW (close, but not exact)
+ 0x21D8, // 0xF8 SOUTH EAST DOUBLE ARROW (close, but not exact)
+ 0xFFFD, // 0xF9 no replacement
+ 0xFFFD, // 0xFA no replacement
+ 0x2717, // 0xFB BALLOT X
+ 0x2713, // 0xFC CHECK MARK
+ 0x2612, // 0xFD BALLOT BOX WITH X
+ 0x2611, // 0xFE BALLOT BOX WITH CHECK
+ 0xFFFD // 0xFF no replacement
+};
+
+/* characters from zapf dingbat font, conversion to a unicode font. Change both the
+ code and the font on conversion. These are untested as the development machine did
+ not have the font installed. */
+static unsigned int dingbats_convert[256]={
+ 0xFFFD, // 0x00 no replacement
+ 0xFFFD, // 0x01 no replacement
+ 0xFFFD, // 0x02 no replacement
+ 0xFFFD, // 0x03 no replacement
+ 0xFFFD, // 0x04 no replacement
+ 0xFFFD, // 0x05 no replacement
+ 0xFFFD, // 0x06 no replacement
+ 0xFFFD, // 0x07 no replacement
+ 0xFFFD, // 0x08 no replacement
+ 0xFFFD, // 0x09 no replacement
+ 0xFFFD, // 0x0A no replacement
+ 0xFFFD, // 0x0B no replacement
+ 0xFFFD, // 0x0C no replacement
+ 0xFFFD, // 0x0D no replacement
+ 0xFFFD, // 0x0E no replacement
+ 0xFFFD, // 0x0F no replacement
+ 0xFFFD, // 0x10 no replacement
+ 0xFFFD, // 0x11 no replacement
+ 0xFFFD, // 0x12 no replacement
+ 0xFFFD, // 0x13 no replacement
+ 0xFFFD, // 0x14 no replacement
+ 0xFFFD, // 0x15 no replacement
+ 0xFFFD, // 0x16 no replacement
+ 0xFFFD, // 0x17 no replacement
+ 0xFFFD, // 0x18 no replacement
+ 0xFFFD, // 0x19 no replacement
+ 0xFFFD, // 0x1A no replacement
+ 0xFFFD, // 0x1B no replacement
+ 0xFFFD, // 0x1C no replacement
+ 0xFFFD, // 0x1D no replacement
+ 0xFFFD, // 0x1E no replacement
+ 0xFFFD, // 0x1F no replacement
+ 0x0020, // 0x20 SPACE
+ 0x2701, // 0x21 UPPER BLADE SCISSORS
+ 0x2702, // 0x22 BLACK SCISSORS
+ 0x2703, // 0x23 LOWER BLADE SCISSORS
+ 0x2704, // 0x24 WHITE SCISSORS
+ 0x260E, // 0x25 BLACK TELEPHONE
+ 0x2706, // 0x26 TELEPHONE LOCATION SIGN
+ 0x2707, // 0x27 TAPE DRIVE
+ 0x2708, // 0x28 AIRPLANE
+ 0x2709, // 0x29 ENVELOPE
+ 0x261B, // 0x2A BLACK RIGHT POINTING INDEX
+ 0x261E, // 0x2B WHITE RIGHT POINTING INDEX
+ 0x270C, // 0x2C VICTORY HAND
+ 0x270D, // 0x2D WRITING HAND
+ 0x270E, // 0x2E LOWER RIGHT PENCIL
+ 0x270F, // 0x2F PENCIL
+ 0x2710, // 0x30 UPPER RIGHT PENCIL
+ 0x2711, // 0x31 WHITE NIB
+ 0x2712, // 0x32 BLACK NIB
+ 0x2713, // 0x33 CHECK MARK
+ 0x2714, // 0x34 HEAVY CHECK MARK
+ 0x2715, // 0x35 MULTIPLICATION X
+ 0x2716, // 0x36 HEAVY MULTIPLICATION X
+ 0x2717, // 0x37 BALLOT X
+ 0x2718, // 0x38 HEAVY BALLOT X
+ 0x2719, // 0x39 OUTLINED GREEK CROSS
+ 0x271A, // 0x3A HEAVY GREEK CROSS
+ 0x271B, // 0x3B OPEN CENTRE CROSS
+ 0x271C, // 0x3C HEAVY OPEN CENTRE CROSS
+ 0x271D, // 0x3D LATIN CROSS
+ 0x271E, // 0x3E SHADOWED WHITE LATIN CROSS
+ 0x271F, // 0x3F OUTLINED LATIN CROSS
+ 0x2720, // 0x40 MALTESE CROSS
+ 0x2721, // 0x41 STAR OF DAVID
+ 0x2722, // 0x42 FOUR TEARDROP-SPOKED ASTERISK
+ 0x2723, // 0x43 FOUR BALLOON-SPOKED ASTERISK
+ 0x2724, // 0x44 HEAVY FOUR BALLOON-SPOKED ASTERISK
+ 0x2725, // 0x45 FOUR CLUB-SPOKED ASTERISK
+ 0x2726, // 0x46 BLACK FOUR POINTED STAR
+ 0x2727, // 0x47 WHITE FOUR POINTED STAR
+ 0x2605, // 0x48 BLACK STAR
+ 0x2729, // 0x49 STRESS OUTLINED WHITE STAR
+ 0x272A, // 0x4A CIRCLED WHITE STAR
+ 0x272B, // 0x4B OPEN CENTRE BLACK STAR
+ 0x272C, // 0x4C BLACK CENTRE WHITE STAR
+ 0x272D, // 0x4D OUTLINED BLACK STAR
+ 0x272E, // 0x4E HEAVY OUTLINED BLACK STAR
+ 0x272F, // 0x4F PINWHEEL STAR
+ 0x2730, // 0x50 SHADOWED WHITE STAR
+ 0x2731, // 0x51 HEAVY ASTERISK
+ 0x2732, // 0x52 OPEN CENTRE ASTERISK
+ 0x2733, // 0x53 EIGHT SPOKED ASTERISK
+ 0x2734, // 0x54 EIGHT POINTED BLACK STAR
+ 0x2735, // 0x55 EIGHT POINTED PINWHEEL STAR
+ 0x2736, // 0x56 SIX POINTED BLACK STAR
+ 0x2737, // 0x57 EIGHT POINTED RECTILINEAR BLACK STAR
+ 0x2738, // 0x58 HEAVY EIGHT POINTED RECTILINEAR BLACK STAR
+ 0x2739, // 0x59 TWELVE POINTED BLACK STAR
+ 0x273A, // 0x5A SIXTEEN POINTED ASTERISK
+ 0x273B, // 0x5B TEARDROP-SPOKED ASTERISK
+ 0x273C, // 0x5C OPEN CENTRE TEARDROP-SPOKED ASTERISK
+ 0x273D, // 0x5D HEAVY TEARDROP-SPOKED ASTERISK
+ 0x273E, // 0x5E SIX PETALLED BLACK AND WHITE FLORETTE
+ 0x273F, // 0x5F BLACK FLORETTE
+ 0x2740, // 0x60 WHITE FLORETTE
+ 0x2741, // 0x61 EIGHT PETALLED OUTLINED BLACK FLORETTE
+ 0x2742, // 0x62 CIRCLED OPEN CENTRE EIGHT POINTED STAR
+ 0x2743, // 0x63 HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK
+ 0x2744, // 0x64 SNOWFLAKE
+ 0x2745, // 0x65 TIGHT TRIFOLIATE SNOWFLAKE
+ 0x2746, // 0x66 HEAVY CHEVRON SNOWFLAKE
+ 0x2747, // 0x67 SPARKLE
+ 0x2748, // 0x68 HEAVY SPARKLE
+ 0x2749, // 0x69 BALLOON-SPOKED ASTERISK
+ 0x274A, // 0x6A EIGHT TEARDROP-SPOKED PROPELLER ASTERISK
+ 0x274B, // 0x6B HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK
+ 0x25CF, // 0x6C BLACK CIRCLE
+ 0x274D, // 0x6D SHADOWED WHITE CIRCLE
+ 0x25A0, // 0x6E BLACK SQUARE
+ 0x274F, // 0x6F LOWER RIGHT DROP-SHADOWED WHITE SQUARE
+ 0x2750, // 0x70 UPPER RIGHT DROP-SHADOWED WHITE SQUARE
+ 0x2751, // 0x71 LOWER RIGHT SHADOWED WHITE SQUARE
+ 0x2752, // 0x72 UPPER RIGHT SHADOWED WHITE SQUARE
+ 0x25B2, // 0x73 BLACK UP-POINTING TRIANGLE
+ 0x25BC, // 0x74 BLACK DOWN-POINTING TRIANGLE
+ 0x25C6, // 0x75 BLACK DIAMOND
+ 0x2756, // 0x76 BLACK DIAMOND MINUS WHITE X
+ 0x25D7, // 0x77 RIGHT HALF BLACK CIRCLE
+ 0x2758, // 0x78 LIGHT VERTICAL BAR
+ 0x2759, // 0x79 MEDIUM VERTICAL BAR
+ 0x275A, // 0x7A HEAVY VERTICAL BAR
+ 0x275B, // 0x7B HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT
+ 0x275C, // 0x7C HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT
+ 0x275D, // 0x7D HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT
+ 0x275E, // 0x7E HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT
+ 0xFFFD, // 0x7F no replacement
+ 0xF8D7, // 0x80 MEDIUM LEFT PARENTHESIS ORNAMENT
+ 0xF8D8, // 0x81 MEDIUM RIGHT PARENTHESIS ORNAMENT
+ 0xF8D9, // 0x82 MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT
+ 0xF8DA, // 0x83 MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT
+ 0xF8DB, // 0x84 MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT
+ 0xF8DC, // 0x85 MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT
+ 0xF8DD, // 0x86 HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT
+ 0xF8DE, // 0x87 HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT
+ 0xF8DF, // 0x88 HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT
+ 0xF8E0, // 0x89 HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT
+ 0xF8E1, // 0x8A LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT
+ 0xF8E2, // 0x8B LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT
+ 0xF8E3, // 0x8C MEDIUM LEFT CURLY BRACKET ORNAMENT
+ 0xF8E4, // 0x8D MEDIUM RIGHT CURLY BRACKET ORNAMENT
+ 0xFFFD, // 0x8E no replacement
+ 0xFFFD, // 0x8F no replacement
+ 0xFFFD, // 0x90 no replacement
+ 0xFFFD, // 0x91 no replacement
+ 0xFFFD, // 0x92 no replacement
+ 0xFFFD, // 0x93 no replacement
+ 0xFFFD, // 0x94 no replacement
+ 0xFFFD, // 0x95 no replacement
+ 0xFFFD, // 0x96 no replacement
+ 0xFFFD, // 0x97 no replacement
+ 0xFFFD, // 0x98 no replacement
+ 0xFFFD, // 0x99 no replacement
+ 0xFFFD, // 0x9A no replacement
+ 0xFFFD, // 0x9B no replacement
+ 0xFFFD, // 0x9C no replacement
+ 0xFFFD, // 0x9D no replacement
+ 0xFFFD, // 0x9E no replacement
+ 0xFFFD, // 0x9F no replacement
+ 0xFFFD, // 0xA0 no replacement
+ 0x2761, // 0xA1 CURVED STEM PARAGRAPH SIGN ORNAMENT
+ 0x2762, // 0xA2 HEAVY EXCLAMATION MARK ORNAMENT
+ 0x2763, // 0xA3 HEAVY HEART EXCLAMATION MARK ORNAMENT
+ 0x2764, // 0xA4 HEAVY BLACK HEART
+ 0x2765, // 0xA5 ROTATED HEAVY BLACK HEART BULLET
+ 0x2766, // 0xA6 FLORAL HEART
+ 0x2767, // 0xA7 ROTATED FLORAL HEART BULLET
+ 0x2663, // 0xA8 BLACK CLUB SUIT
+ 0x2666, // 0xA9 BLACK DIAMOND SUIT
+ 0x2665, // 0xAA BLACK HEART SUIT
+ 0x2660, // 0xAB BLACK SPADE SUIT
+ 0x2460, // 0xAC CIRCLED DIGIT ONE
+ 0x2461, // 0xAD CIRCLED DIGIT TWO
+ 0x2462, // 0xAE CIRCLED DIGIT THREE
+ 0x2463, // 0xAF CIRCLED DIGIT FOUR
+ 0x2464, // 0xB0 CIRCLED DIGIT FIVE
+ 0x2465, // 0xB1 CIRCLED DIGIT SIX
+ 0x2466, // 0xB2 CIRCLED DIGIT SEVEN
+ 0x2467, // 0xB3 CIRCLED DIGIT EIGHT
+ 0x2468, // 0xB4 CIRCLED DIGIT NINE
+ 0x2469, // 0xB5 CIRCLED NUMBER TEN
+ 0x2776, // 0xB6 DINGBAT NEGATIVE CIRCLED DIGIT ONE
+ 0x2777, // 0xB7 DINGBAT NEGATIVE CIRCLED DIGIT TWO
+ 0x2778, // 0xB8 DINGBAT NEGATIVE CIRCLED DIGIT THREE
+ 0x2779, // 0xB9 DINGBAT NEGATIVE CIRCLED DIGIT FOUR
+ 0x277A, // 0xBA DINGBAT NEGATIVE CIRCLED DIGIT FIVE
+ 0x277B, // 0xBB DINGBAT NEGATIVE CIRCLED DIGIT SIX
+ 0x277C, // 0xBC DINGBAT NEGATIVE CIRCLED DIGIT SEVEN
+ 0x277D, // 0xBD DINGBAT NEGATIVE CIRCLED DIGIT EIGHT
+ 0x277E, // 0xBE DINGBAT NEGATIVE CIRCLED DIGIT NINE
+ 0x277F, // 0xBF DINGBAT NEGATIVE CIRCLED NUMBER TEN
+ 0x2780, // 0xC0 DINGBAT CIRCLED SANS-SERIF DIGIT ONE
+ 0x2781, // 0xC1 DINGBAT CIRCLED SANS-SERIF DIGIT TWO
+ 0x2782, // 0xC2 DINGBAT CIRCLED SANS-SERIF DIGIT THREE
+ 0x2783, // 0xC3 DINGBAT CIRCLED SANS-SERIF DIGIT FOUR
+ 0x2784, // 0xC4 DINGBAT CIRCLED SANS-SERIF DIGIT FIVE
+ 0x2785, // 0xC5 DINGBAT CIRCLED SANS-SERIF DIGIT SIX
+ 0x2786, // 0xC6 DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN
+ 0x2787, // 0xC7 DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT
+ 0x2788, // 0xC8 DINGBAT CIRCLED SANS-SERIF DIGIT NINE
+ 0x2789, // 0xC9 DINGBAT CIRCLED SANS-SERIF NUMBER TEN
+ 0x278A, // 0xCA DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE
+ 0x278B, // 0xCB DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO
+ 0x278C, // 0xCC DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE
+ 0x278D, // 0xCD DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR
+ 0x278E, // 0xCE DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE
+ 0x278F, // 0xCF DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX
+ 0x2790, // 0xD0 DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN
+ 0x2791, // 0xD1 DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT
+ 0x2792, // 0xD2 DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE
+ 0x2793, // 0xD3 DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN
+ 0x2794, // 0xD4 HEAVY WIDE-HEADED RIGHTWARDS ARROW
+ 0x2192, // 0xD5 RIGHTWARDS ARROW
+ 0x2194, // 0xD6 LEFT RIGHT ARROW
+ 0x2195, // 0xD7 UP DOWN ARROW
+ 0x2798, // 0xD8 HEAVY SOUTH EAST ARROW
+ 0x2799, // 0xD9 HEAVY RIGHTWARDS ARROW
+ 0x279A, // 0xDA HEAVY NORTH EAST ARROW
+ 0x279B, // 0xDB DRAFTING POINT RIGHTWARDS ARROW
+ 0x279C, // 0xDC HEAVY ROUND-TIPPED RIGHTWARDS ARROW
+ 0x279D, // 0xDD TRIANGLE-HEADED RIGHTWARDS ARROW
+ 0x279E, // 0xDE HEAVY TRIANGLE-HEADED RIGHTWARDS ARROW
+ 0x279F, // 0xDF DASHED TRIANGLE-HEADED RIGHTWARDS ARROW
+ 0x27A0, // 0xE0 HEAVY DASHED TRIANGLE-HEADED RIGHTWARDS ARROW
+ 0x27A1, // 0xE1 BLACK RIGHTWARDS ARROW
+ 0x27A2, // 0xE2 THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD
+ 0x27A3, // 0xE3 THREE-D BOTTOM-LIGHTED RIGHTWARDS ARROWHEAD
+ 0x27A4, // 0xE4 BLACK RIGHTWARDS ARROWHEAD
+ 0x27A5, // 0xE5 HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW
+ 0x27A6, // 0xE6 HEAVY BLACK CURVED UPWARDS AND RIGHTWARDS ARROW
+ 0x27A7, // 0xE7 SQUAT BLACK RIGHTWARDS ARROW
+ 0x27A8, // 0xE8 HEAVY CONCAVE-POINTED BLACK RIGHTWARDS ARROW
+ 0x27A9, // 0xE9 RIGHT-SHADED WHITE RIGHTWARDS ARROW
+ 0x27AA, // 0xEA LEFT-SHADED WHITE RIGHTWARDS ARROW
+ 0x27AB, // 0xEB BACK-TILTED SHADOWED WHITE RIGHTWARDS ARROW
+ 0x27AC, // 0xEC FRONT-TILTED SHADOWED WHITE RIGHTWARDS ARROW
+ 0x27AD, // 0xED HEAVY LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW
+ 0x27AE, // 0xEE HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW
+ 0x27AF, // 0xEF NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW
+ 0xFFFD, // 0xF0 no replacement
+ 0x27B1, // 0xF1 NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW
+ 0x27B2, // 0xF2 CIRCLED HEAVY WHITE RIGHTWARDS ARROW
+ 0x27B3, // 0xF3 WHITE-FEATHERED RIGHTWARDS ARROW
+ 0x27B4, // 0xF4 BLACK-FEATHERED SOUTH EAST ARROW
+ 0x27B5, // 0xF5 BLACK-FEATHERED RIGHTWARDS ARROW
+ 0x27B6, // 0xF6 BLACK-FEATHERED NORTH EAST ARROW
+ 0x27B7, // 0xF7 HEAVY BLACK-FEATHERED SOUTH EAST ARROW
+ 0x27B8, // 0xF8 HEAVY BLACK-FEATHERED RIGHTWARDS ARROW
+ 0x27B9, // 0xF9 HEAVY BLACK-FEATHERED NORTH EAST ARROW
+ 0x27BA, // 0xFA TEARDROP-BARBED RIGHTWARDS ARROW
+ 0x27BB, // 0xFB HEAVY TEARDROP-SHANKED RIGHTWARDS ARROW
+ 0x27BC, // 0xFC WEDGE-TAILED RIGHTWARDS ARROW
+ 0x27BD, // 0xFD HEAVY WEDGE-TAILED RIGHTWARDS ARROW
+ 0x27BE, // 0xFE OPEN-OUTLINED RIGHTWARDS ARROW
+ 0xFFFD // 0xFF no replacement
+};
+
+/* characters from symbol font, conversion to a unicode font. Change both the
+ code and the font on conversion. */
+static unsigned int symbol_convert[256]={
+ 0xFFFD, // 0x00 no replacement
+ 0xFFFD, // 0x01 no replacement
+ 0xFFFD, // 0x02 no replacement
+ 0xFFFD, // 0x03 no replacement
+ 0xFFFD, // 0x04 no replacement
+ 0xFFFD, // 0x05 no replacement
+ 0xFFFD, // 0x06 no replacement
+ 0xFFFD, // 0x07 no replacement
+ 0xFFFD, // 0x08 no replacement
+ 0xFFFD, // 0x09 no replacement
+ 0xFFFD, // 0x0A no replacement
+ 0xFFFD, // 0x0B no replacement
+ 0xFFFD, // 0x0C no replacement
+ 0xFFFD, // 0x0D no replacement
+ 0xFFFD, // 0x0E no replacement
+ 0xFFFD, // 0x0F no replacement
+ 0xFFFD, // 0x10 no replacement
+ 0xFFFD, // 0x11 no replacement
+ 0xFFFD, // 0x12 no replacement
+ 0xFFFD, // 0x13 no replacement
+ 0xFFFD, // 0x14 no replacement
+ 0xFFFD, // 0x15 no replacement
+ 0xFFFD, // 0x16 no replacement
+ 0xFFFD, // 0x17 no replacement
+ 0xFFFD, // 0x18 no replacement
+ 0xFFFD, // 0x19 no replacement
+ 0xFFFD, // 0x1A no replacement
+ 0xFFFD, // 0x1B no replacement
+ 0xFFFD, // 0x1C no replacement
+ 0xFFFD, // 0x1D no replacement
+ 0xFFFD, // 0x1E no replacement
+ 0xFFFD, // 0x1F no replacement
+ 0x0020, // 0x20 SPACE
+ 0x0021, // 0x21 EXCLAMATION MARK
+ 0x2200, // 0x22 FOR ALL
+ 0x0023, // 0x23 NUMBER SIGN
+ 0x2203, // 0x24 THERE EXISTS
+ 0x0025, // 0x25 PERCENT SIGN
+ 0x0026, // 0x26 AMPERSAND
+ 0x220B, // 0x27 CONTAINS AS MEMBER
+ 0x0028, // 0x28 OPENING PARENTHESIS
+ 0x0029, // 0x29 CLOSING PARENTHESIS
+ 0x2217, // 0x2A ASTERISK OPERATOR
+ 0x002B, // 0x2B PLUS SIGN
+ 0x002C, // 0x2C COMMA
+ 0x2212, // 0x2D MINUS SIGN
+ 0x002E, // 0x2E PERIOD
+ 0x002F, // 0x2F SLASH
+ 0x0030, // 0x30 DIGIT ZERO
+ 0x0031, // 0x31 DIGIT ONE
+ 0x0032, // 0x32 DIGIT TWO
+ 0x0033, // 0x33 DIGIT THREE
+ 0x0034, // 0x34 DIGIT FOUR
+ 0x0035, // 0x35 DIGIT FIVE
+ 0x0036, // 0x36 DIGIT SIX
+ 0x0037, // 0x37 DIGIT SEVEN
+ 0x0038, // 0x38 DIGIT EIGHT
+ 0x0039, // 0x39 DIGIT NINE
+ 0x003A, // 0x3A COLON
+ 0x003B, // 0x3B SEMICOLON
+ 0x003C, // 0x3C LESS-THAN SIGN
+ 0x003D, // 0x3D EQUALS SIGN
+ 0x003E, // 0x3E GREATER-THAN SIGN
+ 0x003F, // 0x3F QUESTION MARK
+ 0x2245, // 0x40 APPROXIMATELY EQUAL TO
+ 0x0391, // 0x41 GREEK CAPITAL LETTER ALPHA
+ 0x0392, // 0x42 GREEK CAPITAL LETTER BETA
+ 0x03A7, // 0x43 GREEK CAPITAL LETTER CHI
+ 0x0394, // 0x44 GREEK CAPITAL LETTER DELTA
+ 0x0395, // 0x45 GREEK CAPITAL LETTER EPSILON
+ 0x03A6, // 0x46 GREEK CAPITAL LETTER PHI
+ 0x0393, // 0x47 GREEK CAPITAL LETTER GAMMA
+ 0x0397, // 0x48 GREEK CAPITAL LETTER ETA
+ 0x0399, // 0x49 GREEK CAPITAL LETTER IOTA
+ 0x03D1, // 0x4A GREEK SMALL LETTER SCRIPT THETA
+ 0x039A, // 0x4B GREEK CAPITAL LETTER KAPPA
+ 0x039B, // 0x4C GREEK CAPITAL LETTER LAMBDA
+ 0x039C, // 0x4D GREEK CAPITAL LETTER MU
+ 0x039D, // 0x4E GREEK CAPITAL LETTER NU
+ 0x039F, // 0x4F GREEK CAPITAL LETTER OMICRON
+ 0x03A0, // 0x50 GREEK CAPITAL LETTER PI
+ 0x0398, // 0x51 GREEK CAPITAL LETTER THETA
+ 0x03A1, // 0x52 GREEK CAPITAL LETTER RHO
+ 0x03A3, // 0x53 GREEK CAPITAL LETTER SIGMA
+ 0x03A4, // 0x54 GREEK CAPITAL LETTER TAU
+ 0x03A5, // 0x55 GREEK CAPITAL LETTER UPSILON
+ 0x03C2, // 0x56 GREEK SMALL LETTER FINAL SIGMA
+ 0x03A9, // 0x57 GREEK CAPITAL LETTER OMEGA
+ 0x039E, // 0x58 GREEK CAPITAL LETTER XI
+ 0x03A8, // 0x59 GREEK CAPITAL LETTER PSI
+ 0x0396, // 0x5A GREEK CAPITAL LETTER ZETA
+ 0x005B, // 0x5B OPENING SQUARE BRACKET
+ 0x2234, // 0x5C THEREFORE
+ 0x005D, // 0x5D CLOSING SQUARE BRACKET
+ 0x22A5, // 0x5E UP TACK
+ 0x005F, // 0x5F SPACING UNDERSCORE
+ 0x203E, // 0x60 SPACING OVERSCORE
+ 0x03B1, // 0x61 GREEK SMALL LETTER ALPHA
+ 0x03B2, // 0x62 GREEK SMALL LETTER BETA
+ 0x03C7, // 0x63 GREEK SMALL LETTER CHI
+ 0x03B4, // 0x64 GREEK SMALL LETTER DELTA
+ 0x03B5, // 0x65 GREEK SMALL LETTER EPSILON
+ 0x03C6, // 0x66 GREEK SMALL LETTER PHI
+ 0x03B3, // 0x67 GREEK SMALL LETTER GAMMA
+ 0x03B7, // 0x68 GREEK SMALL LETTER ETA
+ 0x03B9, // 0x69 GREEK SMALL LETTER IOTA
+ 0x03D5, // 0x6A GREEK SMALL LETTER SCRIPT PHI
+ 0x03BA, // 0x6B GREEK SMALL LETTER KAPPA
+ 0x03BB, // 0x6C GREEK SMALL LETTER LAMBDA
+ 0x03BC, // 0x6D GREEK SMALL LETTER MU
+ 0x03BD, // 0x6E GREEK SMALL LETTER NU
+ 0x03BF, // 0x6F GREEK SMALL LETTER OMICRON
+ 0x03C0, // 0x70 GREEK SMALL LETTER PI
+ 0x03B8, // 0x71 GREEK SMALL LETTER THETA
+ 0x03C1, // 0x72 GREEK SMALL LETTER RHO
+ 0x03C3, // 0x73 GREEK SMALL LETTER SIGMA
+ 0x03C4, // 0x74 GREEK SMALL LETTER TAU
+ 0x03C5, // 0x75 GREEK SMALL LETTER UPSILON
+ 0x03D6, // 0x76 GREEK SMALL LETTER OMEGA PI
+ 0x03C9, // 0x77 GREEK SMALL LETTER OMEGA
+ 0x03BE, // 0x78 GREEK SMALL LETTER XI
+ 0x03C8, // 0x79 GREEK SMALL LETTER PSI
+ 0x03B6, // 0x7A GREEK SMALL LETTER ZETA
+ 0x007B, // 0x7B OPENING CURLY BRACKET
+ 0x007C, // 0x7C VERTICAL BAR
+ 0x007D, // 0x7D CLOSING CURLY BRACKET
+ 0x223C, // 0x7E TILDE OPERATOR
+ 0xFFFD, // 0x7F no replacement
+ 0xFFFD, // 0x80 no replacement
+ 0xFFFD, // 0x81 no replacement
+ 0xFFFD, // 0x82 no replacement
+ 0xFFFD, // 0x83 no replacement
+ 0xFFFD, // 0x84 no replacement
+ 0xFFFD, // 0x85 no replacement
+ 0xFFFD, // 0x86 no replacement
+ 0xFFFD, // 0x87 no replacement
+ 0xFFFD, // 0x88 no replacement
+ 0xFFFD, // 0x89 no replacement
+ 0xFFFD, // 0x8A no replacement
+ 0xFFFD, // 0x8B no replacement
+ 0xFFFD, // 0x8C no replacement
+ 0xFFFD, // 0x8D no replacement
+ 0xFFFD, // 0x8E no replacement
+ 0xFFFD, // 0x8F no replacement
+ 0xFFFD, // 0x90 no replacement
+ 0xFFFD, // 0x91 no replacement
+ 0xFFFD, // 0x92 no replacement
+ 0xFFFD, // 0x93 no replacement
+ 0xFFFD, // 0x94 no replacement
+ 0xFFFD, // 0x95 no replacement
+ 0xFFFD, // 0x96 no replacement
+ 0xFFFD, // 0x97 no replacement
+ 0xFFFD, // 0x98 no replacement
+ 0xFFFD, // 0x99 no replacement
+ 0xFFFD, // 0x9A no replacement
+ 0xFFFD, // 0x9B no replacement
+ 0xFFFD, // 0x9C no replacement
+ 0xFFFD, // 0x9D no replacement
+ 0xFFFD, // 0x9E no replacement
+ 0xFFFD, // 0x9F no replacement
+ 0x20AC, // 0xA0 EURO SIGN
+ 0x03D2, // 0xA1 GREEK CAPITAL LETTER UPSILON HOOK
+ 0x2032, // 0xA2 PRIME
+ 0x2264, // 0xA3 LESS THAN OR EQUAL TO
+ 0x2044, // 0xA4 FRACTION SLASH
+ 0x221E, // 0xA5 INFINITY
+ 0x0192, // 0xA6 LATIN SMALL LETTER SCRIPT F
+ 0x2663, // 0xA7 BLACK CLUB SUIT
+ 0x2666, // 0xA8 BLACK DIAMOND SUIT
+ 0x2665, // 0xA9 BLACK HEART SUIT
+ 0x2660, // 0xAA BLACK SPADE SUIT
+ 0x2194, // 0xAB LEFT RIGHT ARROW
+ 0x2190, // 0xAC LEFT ARROW
+ 0x2191, // 0xAD UP ARROW
+ 0x2192, // 0xAE RIGHT ARROW
+ 0x2193, // 0xAF DOWN ARROW
+ 0x00B0, // 0xB0 DEGREE SIGN
+ 0x00B1, // 0xB1 PLUS-OR-MINUS SIGN
+ 0x2033, // 0xB2 DOUBLE PRIME
+ 0x2265, // 0xB3 GREATER THAN OR EQUAL TO
+ 0x00D7, // 0xB4 MULTIPLICATION SIGN
+ 0x221D, // 0xB5 PROPORTIONAL TO
+ 0x2202, // 0xB6 PARTIAL DIFFERENTIAL
+ 0x2219, // 0xB7 BULLET (use BULLET operator, so normal font BULLET will not convert to Symbol BULLET)
+ 0x00F7, // 0xB8 DIVISION SIGN
+ 0x2260, // 0xB9 NOT EQUAL TO
+ 0x2261, // 0xBA IDENTICAL TO
+ 0x2248, // 0xBB ALMOST EQUAL TO
+ 0x2026, // 0xBC HORIZONTAL ELLIPSIS
+ 0xF8E6, // 0xBD VERTICAL ARROW EXTENDER
+ 0xF8E7, // 0xBE HORIZONTAL ARROW EXTENDER
+ 0x21B5, // 0xBF DOWN ARROW WITH CORNER LEFT
+ 0x2135, // 0xC0 FIRST TRANSFINITE CARDINAL
+ 0x2111, // 0xC1 BLACK-LETTER I
+ 0x211C, // 0xC2 BLACK-LETTER R
+ 0x2118, // 0xC3 SCRIPT P
+ 0x2297, // 0xC4 CIRCLED TIMES
+ 0x2295, // 0xC5 CIRCLED PLUS
+ 0x2205, // 0xC6 EMPTY SET
+ 0x2229, // 0xC7 INTERSECTION
+ 0x222A, // 0xC8 UNION
+ 0x2283, // 0xC9 SUPERSET OF
+ 0x2287, // 0xCA SUPERSET OF OR EQUAL TO
+ 0x2284, // 0xCB NOT A SUBSET OF
+ 0x2282, // 0xCC SUBSET OF
+ 0x2286, // 0xCD SUBSET OF OR EQUAL TO
+ 0x2208, // 0xCE ELEMENT OF
+ 0x2209, // 0xCF NOT AN ELEMENT OF
+ 0x2220, // 0xD0 ANGLE
+ 0x2207, // 0xD1 NABLA
+ 0x00AE, // 0xD2 REGISTERED TRADE MARK SIGN
+ 0x00A9, // 0xD3 COPYRIGHT SIGN
+ 0x2122, // 0xD4 TRADEMARK
+ 0x220F, // 0xD5 N-ARY PRODUCT
+ 0x221A, // 0xD6 SQUARE ROOT
+ 0x22C5, // 0xD7 DOT OPERATOR
+ 0x00AC, // 0xD8 NOT SIGN
+ 0x2227, // 0xD9 LOGICAL AND
+ 0x2228, // 0xDA LOGICAL OR
+ 0x21D4, // 0xDB LEFT RIGHT DOUBLE ARROW
+ 0x21D0, // 0xDC LEFT DOUBLE ARROW
+ 0x21D1, // 0xDD UP DOUBLE ARROW
+ 0x21D2, // 0xDE RIGHT DOUBLE ARROW
+ 0x21D3, // 0xDF DOWN DOUBLE ARROW
+ 0x25CA, // 0xE0 LOZENGE
+ 0x2329, // 0xE1 BRA
+ 0x00AE, // 0xE2 REGISTERED TRADE MARK SIGN
+ 0x00A9, // 0xE3 COPYRIGHT SIGN
+ 0x2122, // 0xE4 TRADEMARK
+ 0x2211, // 0xE5 N-ARY SUMMATION
+ 0x239B, // 0xE6 LEFT PAREN TOP
+ 0x239C, // 0xE7 LEFT PAREN EXTENDER
+ 0x239D, // 0xE8 LEFT PAREN BOTTOM
+ 0x23A1, // 0xE9 LEFT SQUARE BRACKET TOP
+ 0x23A2, // 0xEA LEFT SQUARE BRACKET EXTENDER
+ 0x23A3, // 0xEB LEFT SQUARE BRACKET BOTTOM
+ 0x23A7, // 0xEC LEFT CURLY BRACKET TOP
+ 0x23A8, // 0xED LEFT CURLY BRACKET MID
+ 0x23A9, // 0xEE LEFT CURLY BRACKET BOTTOM
+ 0x23AA, // 0xEF CURLY BRACKET EXTENDER
+ 0xFFFD, // 0xF0 no replacement
+ 0x232A, // 0xF1 KET
+ 0x222B, // 0xF2 INTEGRAL
+ 0x2320, // 0xF3 TOP HALF INTEGRAL
+ 0x23AE, // 0xF4 INTEGRAL EXTENDER
+ 0x2321, // 0xF5 BOTTOM HALF INTEGRAL
+ 0x239E, // 0xF6 RIGHT PAREN TOP
+ 0x239F, // 0xF7 RIGHT PAREN EXTENDER
+ 0x23A0, // 0xF8 RIGHT PAREN BOTTOM
+ 0x23A4, // 0xF9 RIGHT SQUARE BRACKET TOP
+ 0x23A5, // 0xFA RIGHT SQUARE BRACKET EXTENDER
+ 0x23A6, // 0xFB RIGHT SQUARE BRACKET BOTTOM
+ 0x23AB, // 0xFC RIGHT CURLY BRACKET TOP
+ 0x23AC, // 0xFD RIGHT CURLY BRACKET MID
+ 0x23AD, // 0xFE RIGHT CURLY BRACKET BOTTOM
+ 0xFFFD // 0xFF no replacement
+};
+
+/* Use this for debugging */
+#include <stdio.h>
+void UC_log_message(char *text){
+FILE *fp;
+ fp=fopen("c:/temp/debug.txt","a");
+ fprintf(fp,"%s",text);
+ fclose(fp);
+}
+
+
+//if any character is in the MS private use area (F020 through F0FF) subtract F000, for use with Symbol and Wingdings* from older software
+void msdepua (uint32_t *text)
+{
+ while(*text){
+ if(*text >= 0xF020 && *text <= 0xF0FF){ *text -= 0xF000; }
+ text++;
+ }
+}
+
+//move characters up to MS private use area (F020 through F0FF)
+void msrepua (uint16_t *text)
+{
+ while(*text){
+ if(*text >= 0x20 && *text <= 0xFF){ *text += 0xF000; }
+ text++;
+ }
+}
+
+// Returns the font classification code
+int isNon(char *font){
+int retval;
+ if(!strcmp(font,"Symbol")){
+ retval=CVTSYM;
+ }
+ else if(!strcmp(font,"Wingdings")){
+ retval=CVTWDG;
+ }
+ else if(!strcmp(font,"ZapfDingbats")){
+ retval=CVTZDG;
+ }
+ else {
+ retval=CVTNON;
+ }
+ return retval;
+}
+
+// Returns the font name, given the classification code, or NULL
+// The returned value must NOT be free'd
+char *FontName(int code){
+char *cptr;
+static char name_symbol[]="Symbol";
+static char name_wingdings[]="Wingdings";
+static char name_zapfdingbats[]="ZapfDingbats";
+ switch(code){
+ case CVTSYM: cptr=&name_symbol[0]; break;
+ case CVTWDG: cptr=&name_wingdings[0]; break;
+ case CVTZDG: cptr=&name_zapfdingbats[0]; break;
+ default: cptr=NULL; break;
+ }
+ return(cptr);
+}
+
+
+// Goes through the uint32_t string converting as needed.
+int NonToUnicode(uint32_t *text, char *font){
+int retval;
+unsigned int *convert_from=NULL;
+ retval=isNon(font);
+ switch(retval){
+ case CVTSYM: convert_from=symbol_convert; break;
+ case CVTWDG: convert_from=wingdings_convert; break;
+ case CVTZDG: convert_from=dingbats_convert; break;
+ default: return(retval); //no conversion
+ }
+ while(*text){
+ if(*text > 0xFF){ *text = 0xFFFD; } // out of range
+ else { *text = convert_from[*text]; }
+ text++;
+ }
+ return(retval);
+}
+
+//returns 1 if tables are defines for UnicodeToNon translation
+int CanUTN(void){
+ if(from_unicode)return(1);
+ return(0);
+}
+
+//translates from Unicode to some non unicode font until the target font changes.
+//A target font change is like symbol -> wingdings, or symbol -> no translation
+//returns the number of characters changed in ecount
+//returns the enum value for the destination value in edest
+void UnicodeToNon(uint16_t *text, int *ecount, int *edest){
+int count=0;
+unsigned char target=0;
+ if(to_font){
+ if(text && (target=to_font[*text])){ //There is actually something here to convert
+ while(*text && target==to_font[*text]){
+ *text=from_unicode[*text] + (hold_pua ? 0xF000 : 0 );
+ text++;
+ count++;
+ }
+ }
+ *ecount=count;
+ *edest=target;
+ }
+ else { // no translation tables, so change nothing and return
+ *ecount=0;
+ *edest=CVTNON;
+ }
+}
+
+//Indicates the type of translation for a single character, Unicode to some non unicode
+//returns the enum value for the destination value.
+//If no translation tables are defined returns CVTNON (no conversions)
+int SingleUnicodeToNon(uint16_t text){
+ if(to_font){return(to_font[text]); }
+ else { return(CVTNON); }
+}
+
+void table_filler(unsigned int *src, int code){
+unsigned int i;
+ for(i=0;i<0x100;i++){
+ if(src[i] == 0xFFFD)continue; /* no mapping Unicode -> nonUnicode */
+ if(src[i] == i)continue; /* no remapping of spaces back to spaces, for instance */
+ from_unicode[src[i]] = i;
+ to_font[src[i]] = code;
+ }
+}
+
+//possibly (re)generate the tables
+void TableGen(bool new_symb,bool new_wing, bool new_zdng, bool new_pua){
+int i;
+ if(hold_symb != new_symb || hold_wing != new_wing
+ || hold_zdng != new_zdng || hold_pua != new_pua ){ // must (re)generate tables
+ if(!from_unicode){ // create arrays
+ from_unicode = (unsigned char *) calloc(0x10000,sizeof(unsigned char));
+ to_font = (unsigned char *) calloc(0x10000,sizeof(unsigned char));
+ // should check here for malloc error
+ }
+ hold_symb = new_symb;
+ hold_wing = new_wing;
+ hold_zdng = new_zdng;
+ hold_pua = new_pua;
+ for(i=0;i<0x10000;i++){ from_unicode[i] = to_font[i] = 0; }
+ if(hold_zdng)table_filler(&dingbats_convert[0],CVTZDG);
+ if(hold_wing)table_filler(&wingdings_convert[0],CVTWDG);
+ if(hold_symb)table_filler(&symbol_convert[0],CVTSYM);
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/3rdparty/libuemf/symbol_convert.h b/src/3rdparty/libuemf/symbol_convert.h
new file mode 100644
index 0000000..ac17950
--- /dev/null
+++ b/src/3rdparty/libuemf/symbol_convert.h
@@ -0,0 +1,51 @@
+/** @file
+ * @brief Enhanced Metafile Input/Output
+ */
+/* Authors:
+ * David Mathog <mathog@caltech.edu>
+ *
+ * Copyright (C) 2012 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef SEEN_UNICODE_CONVERT_H
+#define SEEN_UNICODE_CONVERT_H
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+ enum cvt_to_font {CVTNON, CVTSYM, CVTZDG, CVTWDG};
+
+ void msdepua(uint32_t *text); //translate down from Microsoft Private Use Area
+ void msrepua(uint16_t *text); //translate up to Microsoft Private Use Area
+ int isNon(char *font); //returns one of the cvt_to_font enum values
+ char *FontName(int code); //returns the font name (or NULL) given the enum code
+ int NonToUnicode(uint32_t *text, char *font); //nonunicode to Unicode translation
+ int CanUTN(void); // 1 if tables exist for UnicodeToNon translation
+ int SingleUnicodeToNon(uint16_t text); //retuns the enum value for this translation
+ void UnicodeToNon(uint16_t *text, int *ecount, int *edest); //translate Unicode to NonUnicode
+ void TableGen(bool symb, bool wing, bool zdng, bool pua);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SEEN_UNICODE_CONVERT_H */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
+
+
diff --git a/src/3rdparty/libuemf/uemf.c b/src/3rdparty/libuemf/uemf.c
new file mode 100644
index 0000000..fa7689b
--- /dev/null
+++ b/src/3rdparty/libuemf/uemf.c
@@ -0,0 +1,5606 @@
+/**
+ @file uemf.c
+
+ @brief Functions for manipulating EMF files and structures.
+
+ [U_EMR]_set all take data and return a pointer to memory holding the constructed record.
+ The size of that record is also returned in recsize.
+ It is also in the second int32 in the record, but may have been byte swapped and so not usable.
+ If something goes wrong a NULL pointer is returned and recsize is set to 0.
+
+ Compile with "U_VALGRIND" defined defined to enable code which lets valgrind check each record for
+ uninitialized data.
+
+ Compile with "SOL8" defined for Solaris 8 or 9 (Sparc).
+*/
+
+/*
+File: uemf.c
+Version: 0.0.31
+Date: 26-JAN-2016
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2016 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <iconv.h>
+#include <wchar.h>
+#include <errno.h>
+#include <string.h>
+#include <limits.h> // for INT_MAX, INT_MIN
+#include <math.h> // for U_ROUND()
+#include <stddef.h> /* for offsetof() macro */
+#if 0
+#include <windef.h> //Not actually used, looking for collisions
+#include <winnt.h> //Not actually used, looking for collisions
+#include <wingdi.h> //Not actually used, looking for collisions
+#endif
+#include "uemf.h"
+
+//! \cond
+/* one prototype from uemf_endian. Put it here because end user should never need to see it, so
+not in uemf.h or uemf_endian.h */
+void U_swap2(void *ul, unsigned int count);
+//! \endcond
+
+/**
+ \brief Look up the name of the EMR record by type. Returns U_EMR_INVALID if out of range.
+
+ \return name of the EMR record, "U_EMR_INVALID" if out of range.
+ \param idx EMR record type.
+
+*/
+char *U_emr_names(unsigned int idx){
+ if(idx<U_EMR_MIN || idx > U_EMR_MAX){ idx = 0; }
+ static char *U_EMR_NAMES[U_EMR_MAX+1]={
+ "U_EMR_INVALID",
+ "U_EMR_HEADER",
+ "U_EMR_POLYBEZIER",
+ "U_EMR_POLYGON",
+ "U_EMR_POLYLINE",
+ "U_EMR_POLYBEZIERTO",
+ "U_EMR_POLYLINETO",
+ "U_EMR_POLYPOLYLINE",
+ "U_EMR_POLYPOLYGON",
+ "U_EMR_SETWINDOWEXTEX",
+ "U_EMR_SETWINDOWORGEX",
+ "U_EMR_SETVIEWPORTEXTEX",
+ "U_EMR_SETVIEWPORTORGEX",
+ "U_EMR_SETBRUSHORGEX",
+ "U_EMR_EOF",
+ "U_EMR_SETPIXELV",
+ "U_EMR_SETMAPPERFLAGS",
+ "U_EMR_SETMAPMODE",
+ "U_EMR_SETBKMODE",
+ "U_EMR_SETPOLYFILLMODE",
+ "U_EMR_SETROP2",
+ "U_EMR_SETSTRETCHBLTMODE",
+ "U_EMR_SETTEXTALIGN",
+ "U_EMR_SETCOLORADJUSTMENT",
+ "U_EMR_SETTEXTCOLOR",
+ "U_EMR_SETBKCOLOR",
+ "U_EMR_OFFSETCLIPRGN",
+ "U_EMR_MOVETOEX",
+ "U_EMR_SETMETARGN",
+ "U_EMR_EXCLUDECLIPRECT",
+ "U_EMR_INTERSECTCLIPRECT",
+ "U_EMR_SCALEVIEWPORTEXTEX",
+ "U_EMR_SCALEWINDOWEXTEX",
+ "U_EMR_SAVEDC",
+ "U_EMR_RESTOREDC",
+ "U_EMR_SETWORLDTRANSFORM",
+ "U_EMR_MODIFYWORLDTRANSFORM",
+ "U_EMR_SELECTOBJECT",
+ "U_EMR_CREATEPEN",
+ "U_EMR_CREATEBRUSHINDIRECT",
+ "U_EMR_DELETEOBJECT",
+ "U_EMR_ANGLEARC",
+ "U_EMR_ELLIPSE",
+ "U_EMR_RECTANGLE",
+ "U_EMR_ROUNDRECT",
+ "U_EMR_ARC",
+ "U_EMR_CHORD",
+ "U_EMR_PIE",
+ "U_EMR_SELECTPALETTE",
+ "U_EMR_CREATEPALETTE",
+ "U_EMR_SETPALETTEENTRIES",
+ "U_EMR_RESIZEPALETTE",
+ "U_EMR_REALIZEPALETTE",
+ "U_EMR_EXTFLOODFILL",
+ "U_EMR_LINETO",
+ "U_EMR_ARCTO",
+ "U_EMR_POLYDRAW",
+ "U_EMR_SETARCDIRECTION",
+ "U_EMR_SETMITERLIMIT",
+ "U_EMR_BEGINPATH",
+ "U_EMR_ENDPATH",
+ "U_EMR_CLOSEFIGURE",
+ "U_EMR_FILLPATH",
+ "U_EMR_STROKEANDFILLPATH",
+ "U_EMR_STROKEPATH",
+ "U_EMR_FLATTENPATH",
+ "U_EMR_WIDENPATH",
+ "U_EMR_SELECTCLIPPATH",
+ "U_EMR_ABORTPATH",
+ "U_EMR_UNDEF69",
+ "U_EMR_COMMENT",
+ "U_EMR_FILLRGN",
+ "U_EMR_FRAMERGN",
+ "U_EMR_INVERTRGN",
+ "U_EMR_PAINTRGN",
+ "U_EMR_EXTSELECTCLIPRGN",
+ "U_EMR_BITBLT",
+ "U_EMR_STRETCHBLT",
+ "U_EMR_MASKBLT",
+ "U_EMR_PLGBLT",
+ "U_EMR_SETDIBITSTODEVICE",
+ "U_EMR_STRETCHDIBITS",
+ "U_EMR_EXTCREATEFONTINDIRECTW",
+ "U_EMR_EXTTEXTOUTA",
+ "U_EMR_EXTTEXTOUTW",
+ "U_EMR_POLYBEZIER16",
+ "U_EMR_POLYGON16",
+ "U_EMR_POLYLINE16",
+ "U_EMR_POLYBEZIERTO16",
+ "U_EMR_POLYLINETO16",
+ "U_EMR_POLYPOLYLINE16",
+ "U_EMR_POLYPOLYGON16",
+ "U_EMR_POLYDRAW16",
+ "U_EMR_CREATEMONOBRUSH",
+ "U_EMR_CREATEDIBPATTERNBRUSHPT",
+ "U_EMR_EXTCREATEPEN",
+ "U_EMR_POLYTEXTOUTA",
+ "U_EMR_POLYTEXTOUTW",
+ "U_EMR_SETICMMODE",
+ "U_EMR_CREATECOLORSPACE",
+ "U_EMR_SETCOLORSPACE",
+ "U_EMR_DELETECOLORSPACE",
+ "U_EMR_GLSRECORD",
+ "U_EMR_GLSBOUNDEDRECORD",
+ "U_EMR_PIXELFORMAT",
+ "U_EMR_DRAWESCAPE",
+ "U_EMR_EXTESCAPE",
+ "U_EMR_UNDEF107",
+ "U_EMR_SMALLTEXTOUT",
+ "U_EMR_FORCEUFIMAPPING",
+ "U_EMR_NAMEDESCAPE",
+ "U_EMR_COLORCORRECTPALETTE",
+ "U_EMR_SETICMPROFILEA",
+ "U_EMR_SETICMPROFILEW",
+ "U_EMR_ALPHABLEND",
+ "U_EMR_SETLAYOUT",
+ "U_EMR_TRANSPARENTBLT",
+ "U_EMR_UNDEF117",
+ "U_EMR_GRADIENTFILL",
+ "U_EMR_SETLINKEDUFIS",
+ "U_EMR_SETTEXTJUSTIFICATION",
+ "U_EMR_COLORMATCHTOTARGETW",
+ "U_EMR_CREATECOLORSPACEW"
+ };
+ return(U_EMR_NAMES[idx]);
+}
+
+
+
+/* **********************************************************************************************
+These definitions are for code pieces that are used many times in the following implementation. These
+definitions are not needed in end user code, so they are here rather than in uemf.h.
+*********************************************************************************************** */
+
+//! @cond
+
+// this one may also be used A=Msk,B=MskBmi and F=cbMsk
+#define SET_CB_FROM_PXBMI(A,B,C,D,E,F) /* A=Px, B=Bmi, C=cbImage, D=cbImage4, E=cbBmi, F=cbPx */ \
+ if(A){\
+ if(!B)return(NULL); /* size is derived from U_BITMAPINFO, but NOT from its size field, go figure*/ \
+ C = F;\
+ D = UP4(C); /* pixel array might not be a multiples of 4 bytes*/ \
+ E = sizeof(U_BITMAPINFOHEADER) + 4 * get_real_color_count((const char *) &(B->bmiHeader)); /* bmiheader + colortable*/ \
+ }\
+ else { C = 0; D = 0; E=0; }
+
+// variable "off" must be declared in the function
+
+#define APPEND_PXBMISRC(A,B,C,D,E,F,G) /* A=record, B=U_EMR,C=cbBmi, D=Bmi, E=Px, F=cbImage, G=cbImage4 */ \
+ if(C){\
+ memcpy(A + off, D, C);\
+ ((B *) A)->offBmiSrc = off;\
+ ((B *) A)->cbBmiSrc = C;\
+ off += C;\
+ memcpy(A + off, E, F);\
+ ((B *) A)->offBitsSrc = off;\
+ ((B *) A)->cbBitsSrc = F;\
+ if(G - F){ \
+ off += F;\
+ memset(A + off, 0, G - F); \
+ }\
+ }\
+ else {\
+ ((B *) A)->offBmiSrc = 0;\
+ ((B *) A)->cbBmiSrc = 0;\
+ ((B *) A)->offBitsSrc = 0;\
+ ((B *) A)->cbBitsSrc = 0;\
+ }
+
+// variable "off" must be declared in the function
+
+#define APPEND_MSKBMISRC(A,B,C,D,E,F,G) /* A=record, B=U_EMR*,C=cbMskBmi, D=MskBmi, E=Msk, F=cbMskImage, G=cbMskImage4 */ \
+ if(C){\
+ memcpy(A + off, D, C);\
+ ((B *) A)->offBmiMask = off;\
+ ((B *) A)->cbBmiMask = C;\
+ off += C;\
+ memcpy(A + off, Msk, F);\
+ ((B *) A)->offBitsMask = off;\
+ ((B *) A)->cbBitsMask = F;\
+ if(G - F){ memset(A + off, 0, G - F); }\
+ }\
+ else {\
+ ((B *) A)->offBmiMask = 0;\
+ ((B *) A)->cbBmiMask = 0;\
+ ((B *) A)->offBitsMask = 0;\
+ ((B *) A)->cbBitsMask = 0;\
+ }
+
+//! @endcond
+
+/* **********************************************************************************************
+These functions are used for development and debugging and should be be includied in production code.
+*********************************************************************************************** */
+
+/**
+ \brief Debugging utility, used with valgrind to find uninitialized values. Not for use in production code.
+ \param buf memory area to examine !
+ \param size length in bytes of buf!
+*/
+int memprobe(
+ const void *buf,
+ size_t size
+ ){
+ int sum=0;
+ char *ptr=(char *)buf;
+ for(;size;size--,ptr++){ sum += *ptr; } // read all bytes, trigger valgrind warning if any uninitialized
+ return(sum);
+}
+
+/**
+ \brief Dump an EMFHANDLES structure. Not for use in production code.
+ \param string Text to output before dumping eht structure
+ \param handle Handle
+ \param eht EMFHANDLES structure to dump
+*/
+void dumpeht(
+ char *string,
+ unsigned int *handle,
+ EMFHANDLES *eht
+ ){
+ uint32_t i;
+ printf("%s\n",string);
+ printf("sptr: %d peak: %d top: %d\n",eht->sptr,eht->peak,eht->top);
+ if(handle){
+ printf("handle: %d \n",*handle);
+ }
+ for(i=0;i<=5;i++){
+ printf("table[%d]: %d\n",i,eht->table[i]);
+ }
+ for(i=1;i<=5;i++){
+ printf("stack[%d]: %d\n",i,eht->stack[i]);
+ }
+}
+
+/* **********************************************************************************************
+These functions are used for Image conversions and other
+utility operations. Character type conversions are in uemf_utf.c
+*********************************************************************************************** */
+
+/**
+ \brief Make up an approximate dx array to pass to emrtext_set(), based on character height and weight.
+
+ Take abs. value of character height, get width by multiplying by 0.6, and correct weight
+ approximately, with formula (measured on screen for one text line of Arial).
+ Caller is responsible for free() on the returned pointer.
+
+ \return pointer to dx array
+ \param height character height (absolute value will be used)
+ \param weight LF_Weight Enumeration (character weight)
+ \param members Number of entries to put into dx
+
+*/
+uint32_t *dx_set(
+ int32_t height,
+ uint32_t weight,
+ uint32_t members
+ ){
+ uint32_t i, width, *dx;
+ dx = (uint32_t *) malloc(members * sizeof(uint32_t));
+ if(dx){
+ if(U_FW_DONTCARE == weight)weight=U_FW_NORMAL;
+ width = (uint32_t) U_ROUND(((float) (height > 0 ? height : -height)) * 0.6 * (0.00024*(float) weight + 0.904));
+ for ( i = 0; i < members; i++ ){ dx[i] = width; }
+ }
+ return(dx);
+}
+
+/**
+ \brief Look up the properties (a bit map) of a type of EMR record.
+ Bits that may be set are defined in "Draw Properties" in uemf.h, they are U_DRAW_NOTEMPTY, etc..
+
+ \return bitmap of EMR record properties, or U_EMR_INVALID on error or release of all memory
+ \param type EMR record type. If U_EMR_INVALID release memory. (There is no U_EMR_INVALID EMR record type)
+
+*/
+uint32_t emr_properties(uint32_t type){
+ static uint32_t *table=NULL;
+ uint32_t result = U_EMR_INVALID; // initialized to indicate an error (on a lookup) or nothing (on a memory release)
+ if(type == U_EMR_INVALID){
+ if(table)free(table);
+ table=NULL;
+ }
+ else if(type>=1 && type<U_EMR_MAX){
+ if(!table){
+ table = (uint32_t *) malloc(sizeof(uint32_t)*(1 + U_EMR_MAX));
+ if(!table)return(result);
+ // 0x80 0x40 0x20 0x10 0x08 0x04 0x02 0x01
+ // Path properties (U_DRAW_*) TEXT ALTERS ONLYTO VISIBLE
+ // PATH FORCE CLOSED NOTEMPTY
+ table[ 0] = 0x00; // Does not map to any EMR record
+ table[ 1] = 0x80; // U_EMRHEADER 1 0 0 0 0 0 0 0
+ table[ 2] = 0x83; // U_EMRPOLYBEZIER 1 0 0 0 0 0 1 1
+ table[ 3] = 0x87; // U_EMRPOLYGON 1 0 0 0 0 1 1 1
+ table[ 4] = 0x83; // U_EMRPOLYLINE 1 0 0 0 0 0 1 1
+ table[ 5] = 0x8B; // U_EMRPOLYBEZIERTO 1 0 0 0 1 0 1 1
+ table[ 6] = 0x8B; // U_EMRPOLYLINETO 1 0 0 0 1 0 1 1
+ table[ 7] = 0x83; // U_EMRPOLYPOLYLINE 1 0 0 0 0 0 1 1
+ table[ 8] = 0x87; // U_EMRPOLYPOLYGON 1 0 0 0 0 1 1 1
+ table[ 9] = 0xA0; // U_EMRSETWINDOWEXTEX 1 0 1 0 0 0 0 0
+ table[ 10] = 0xA0; // U_EMRSETWINDOWORGEX 1 0 1 0 0 0 0 0
+ table[ 11] = 0xA0; // U_EMRSETVIEWPORTEXTEX 1 0 1 0 0 0 0 0
+ table[ 12] = 0xA0; // U_EMRSETVIEWPORTORGEX 1 0 1 0 0 0 0 0
+ table[ 13] = 0xA0; // U_EMRSETBRUSHORGEX 1 0 1 0 0 0 0 0
+ table[ 14] = 0x82; // U_EMREOF 1 0 1 0 0 0 0 0 Force out any pending draw
+ table[ 15] = 0x82; // U_EMRSETPIXELV 1 0 0 0 0 0 1 0
+ table[ 16] = 0xA0; // U_EMRSETMAPPERFLAGS 1 0 1 0 0 0 0 0
+ table[ 17] = 0xA0; // U_EMRSETMAPMODE 1 0 1 0 0 0 0 0
+ table[ 18] = 0x20; // U_EMRSETBKMODE 0 0 1 0 0 0 0 0
+ table[ 19] = 0xA0; // U_EMRSETPOLYFILLMODE 1 0 1 0 0 0 0 0
+ table[ 20] = 0xA0; // U_EMRSETROP2 1 0 1 0 0 0 0 0
+ table[ 21] = 0xA0; // U_EMRSETSTRETCHBLTMODE 1 0 1 0 0 0 0 0
+ table[ 22] = 0x20; // U_EMRSETTEXTALIGN 0 0 1 0 0 0 0 0
+ table[ 23] = 0xA0; // U_EMRSETCOLORADJUSTMENT 1 0 1 0 0 0 0 0
+ table[ 24] = 0x20; // U_EMRSETTEXTCOLOR 0 0 1 0 0 0 0 0
+ table[ 25] = 0x20; // U_EMRSETBKCOLOR 0 0 1 0 0 0 0 0
+ table[ 26] = 0xA0; // U_EMROFFSETCLIPRGN 1 0 1 0 0 0 0 0
+ table[ 27] = 0x89; // U_EMRMOVETOEX 1 0 0 0 1 0 0 1
+ table[ 28] = 0xA0; // U_EMRSETMETARGN 1 0 1 0 0 0 0 0
+ table[ 29] = 0xA0; // U_EMREXCLUDECLIPRECT 1 0 1 0 0 0 0 0
+ table[ 30] = 0xA0; // U_EMRINTERSECTCLIPRECT 1 0 1 0 0 0 0 0
+ table[ 31] = 0xA0; // U_EMRSCALEVIEWPORTEXTEX 1 0 1 0 0 0 0 0
+ table[ 32] = 0xA0; // U_EMRSCALEWINDOWEXTEX 1 0 1 0 0 0 0 0
+ table[ 33] = 0xA0; // U_EMRSAVEDC 1 0 1 0 0 0 0 0
+ table[ 34] = 0xA0; // U_EMRRESTOREDC 1 0 1 0 0 0 0 0
+ table[ 35] = 0xA0; // U_EMRSETWORLDTRANSFORM 1 0 1 0 0 0 0 0
+ table[ 36] = 0xA0; // U_EMRMODIFYWORLDTRANSFORM 1 0 1 0 0 0 0 0
+ table[ 37] = 0x20; // U_EMRSELECTOBJECT 0 0 1 0 0 0 0 0
+ table[ 38] = 0x20; // U_EMRCREATEPEN 0 0 1 0 0 0 0 0
+ table[ 39] = 0x20; // U_EMRCREATEBRUSHINDIRECT 0 0 1 0 0 0 0 0
+ table[ 40] = 0x20; // U_EMRDELETEOBJECT 0 0 1 0 0 0 0 0
+ table[ 41] = 0x83; // U_EMRANGLEARC 1 0 0 0 0 0 1 1
+ table[ 42] = 0x87; // U_EMRELLIPSE 1 0 0 0 0 1 1 1
+ table[ 43] = 0x87; // U_EMRRECTANGLE 1 0 0 0 0 1 1 1
+ table[ 44] = 0x87; // U_EMRROUNDRECT 1 0 0 0 0 1 1 1
+ table[ 45] = 0x83; // U_EMRARC 1 0 0 0 0 0 1 1
+ table[ 46] = 0x87; // U_EMRCHORD 1 0 0 0 0 1 1 1
+ table[ 47] = 0x87; // U_EMRPIE 1 0 0 0 0 1 1 1
+ table[ 48] = 0xA0; // U_EMRSELECTPALETTE 1 0 1 0 0 0 0 0
+ table[ 49] = 0xA0; // U_EMRCREATEPALETTE 1 0 1 0 0 0 0 0
+ table[ 50] = 0xA0; // U_EMRSETPALETTEENTRIES 1 0 1 0 0 0 0 0
+ table[ 51] = 0xA0; // U_EMRRESIZEPALETTE 1 0 1 0 0 0 0 0
+ table[ 52] = 0xA0; // U_EMRREALIZEPALETTE 1 0 1 0 0 0 0 0
+ table[ 53] = 0x82; // U_EMREXTFLOODFILL 1 0 0 0 0 0 1 0
+ table[ 54] = 0x8B; // U_EMRLINETO 1 0 0 0 1 0 1 1
+ table[ 55] = 0x8B; // U_EMRARCTO 1 0 0 0 1 0 1 1
+ table[ 56] = 0x83; // U_EMRPOLYDRAW 1 0 0 0 0 0 1 1
+ table[ 57] = 0xA0; // U_EMRSETARCDIRECTION 1 0 1 0 0 0 0 0
+ table[ 58] = 0xA0; // U_EMRSETMITERLIMIT 1 0 1 0 0 0 0 0
+ table[ 59] = 0xE0; // U_EMRBEGINPATH 1 1 1 0 0 0 0 0
+ table[ 60] = 0x80; // U_EMRENDPATH 1 0 0 0 0 0 0 0
+ table[ 61] = 0x84; // U_EMRCLOSEFIGURE 1 0 0 0 0 1 0 0
+ table[ 62] = 0x94; // U_EMRFILLPATH 1 0 0 1 0 1 0 0
+ table[ 63] = 0x94; // U_EMRSTROKEANDFILLPATH 1 0 0 1 0 1 0 0
+ table[ 64] = 0x90; // U_EMRSTROKEPATH 1 0 0 1 0 0 0 0
+ table[ 65] = 0xA0; // U_EMRFLATTENPATH 1 0 1 0 0 0 0 0
+ table[ 66] = 0xA0; // U_EMRWIDENPATH 1 0 1 0 0 0 0 0
+ table[ 67] = 0x80; // U_EMRSELECTCLIPPATH 1 0 0 0 0 0 0 0 consumes the path, draws nothing
+ table[ 68] = 0xA0; // U_EMRABORTPATH 1 0 1 0 0 0 0 0
+ table[ 69] = 0xA0; // U_EMRUNDEF69 1 0 1 0 0 0 0 0
+ table[ 70] = 0x00; // U_EMRCOMMENT 0 0 0 0 0 0 0 0
+ table[ 71] = 0x82; // U_EMRFILLRGN 1 0 0 0 0 0 1 0
+ table[ 72] = 0x82; // U_EMRFRAMERGN 1 0 0 0 0 0 1 0
+ table[ 73] = 0x82; // U_EMRINVERTRGN 1 0 0 0 0 0 1 0
+ table[ 74] = 0x82; // U_EMRPAINTRGN 1 0 0 0 0 0 1 0
+ table[ 75] = 0xA0; // U_EMREXTSELECTCLIPRGN 1 0 1 0 0 0 0 0
+ table[ 76] = 0x82; // U_EMRBITBLT 1 0 0 0 0 0 1 0
+ table[ 77] = 0x82; // U_EMRSTRETCHBLT 1 0 0 0 0 0 1 0
+ table[ 78] = 0x82; // U_EMRMASKBLT 1 0 0 0 0 0 1 0
+ table[ 79] = 0x82; // U_EMRPLGBLT 1 0 0 0 0 0 1 0
+ table[ 80] = 0xA0; // U_EMRSETDIBITSTODEVICE 1 0 1 0 0 0 0 0
+ table[ 81] = 0xA0; // U_EMRSTRETCHDIBITS 1 0 1 0 0 0 0 0
+ table[ 82] = 0x20; // U_EMREXTCREATEFONTINDIRECTW 0 0 1 0 0 0 0 0
+ table[ 83] = 0x02; // U_EMREXTTEXTOUTA 0 0 0 0 0 0 1 0
+ table[ 84] = 0x02; // U_EMREXTTEXTOUTW 0 0 0 0 0 0 1 0
+ table[ 85] = 0x83; // U_EMRPOLYBEZIER16 1 0 0 0 0 0 1 1
+ table[ 86] = 0x83; // U_EMRPOLYGON16 1 0 0 0 0 0 1 1
+ table[ 87] = 0x83; // U_EMRPOLYLINE16 1 0 0 0 0 0 1 1
+ table[ 88] = 0x8B; // U_EMRPOLYBEZIERTO16 1 0 0 0 1 0 1 1
+ table[ 89] = 0x8B; // U_EMRPOLYLINETO16 1 0 0 0 1 0 1 1
+ table[ 90] = 0x83; // U_EMRPOLYPOLYLINE16 1 0 0 0 0 0 1 1
+ table[ 91] = 0x87; // U_EMRPOLYPOLYGON16 1 0 0 0 0 1 1 1
+ table[ 92] = 0x83; // U_EMRPOLYDRAW16 1 0 0 0 0 0 1 1
+ table[ 93] = 0x80; // U_EMRCREATEMONOBRUSH 1 0 0 0 0 0 0 0 Not selected yet, so no change in drawing conditions
+ table[ 94] = 0x80; // U_EMRCREATEDIBPATTERNBRUSHPT 1 0 0 0 0 0 0 0 "
+ table[ 95] = 0x00; // U_EMREXTCREATEPEN 0 0 0 0 0 0 0 0 "
+ table[ 96] = 0x02; // U_EMRPOLYTEXTOUTA 0 0 0 0 0 0 1 0
+ table[ 97] = 0x02; // U_EMRPOLYTEXTOUTW 0 0 0 0 0 0 1 0
+ table[ 98] = 0xA0; // U_EMRSETICMMODE 1 0 1 0 0 0 0 0
+ table[ 99] = 0xA0; // U_EMRCREATECOLORSPACE 1 0 1 0 0 0 0 0
+ table[100] = 0xA0; // U_EMRSETCOLORSPACE 1 0 1 0 0 0 0 0
+ table[101] = 0xA0; // U_EMRDELETECOLORSPACE 1 0 1 0 0 0 0 0
+ table[102] = 0xA0; // U_EMRGLSRECORD 1 0 1 0 0 0 0 0
+ table[103] = 0xA0; // U_EMRGLSBOUNDEDRECORD 1 0 1 0 0 0 0 0
+ table[104] = 0xA0; // U_EMRPIXELFORMAT 1 0 1 0 0 0 0 0
+ table[105] = 0xA0; // U_EMRDRAWESCAPE 1 0 1 0 0 0 0 0
+ table[106] = 0xA0; // U_EMREXTESCAPE 1 0 1 0 0 0 0 0
+ table[107] = 0xA0; // U_EMRUNDEF107 1 0 1 0 0 0 0 0
+ table[108] = 0x02; // U_EMRSMALLTEXTOUT 0 0 0 0 0 0 1 0
+ table[109] = 0xA0; // U_EMRFORCEUFIMAPPING 1 0 1 0 0 0 0 0
+ table[110] = 0xA0; // U_EMRNAMEDESCAPE 1 0 1 0 0 0 0 0
+ table[111] = 0xA0; // U_EMRCOLORCORRECTPALETTE 1 0 1 0 0 0 0 0
+ table[112] = 0xA0; // U_EMRSETICMPROFILEA 1 0 1 0 0 0 0 0
+ table[113] = 0xA0; // U_EMRSETICMPROFILEW 1 0 1 0 0 0 0 0
+ table[114] = 0x82; // U_EMRALPHABLEND 1 0 0 0 0 0 1 0
+ table[115] = 0xA0; // U_EMRSETLAYOUT 1 0 1 0 0 0 0 0
+ table[116] = 0x82; // U_EMRTRANSPARENTBLT 1 0 0 0 0 0 1 0
+ table[117] = 0xA0; // U_EMRUNDEF117 1 0 1 0 0 0 0 0
+ table[118] = 0x82; // U_EMRGRADIENTFILL 1 0 1 0 0 0 1 0
+ table[119] = 0xA0; // U_EMRSETLINKEDUFIS 1 0 1 0 0 0 0 0
+ table[120] = 0x20; // U_EMRSETTEXTJUSTIFICATION 0 0 1 0 0 0 0 0
+ table[121] = 0xA0; // U_EMRCOLORMATCHTOTARGETW 1 0 1 0 0 0 0 0
+ table[122] = 0xA0; // U_EMRCREATECOLORSPACEW 1 0 1 0 0 0 0 0
+ }
+ result = table[type];
+ }
+ return(result);
+}
+
+/**
+ \brief Derive from bounding rect, start and end radials, for arc, chord, or pie, the center, start, and end points, and the bounding rectangle.
+
+ \return 0 on success, other values on errors.
+ \param rclBox bounding rectangle
+ \param ArcStart start of arc
+ \param ArcEnd end of arc
+ \param f1 1 if rotation angle >= 180, else 0
+ \param f2 Rotation direction, 1 if counter clockwise, else 0
+ \param center Center coordinates
+ \param start Start coordinates (point on the ellipse defined by rect)
+ \param end End coordinates (point on the ellipse defined by rect)
+ \param size W,H of the x,y axes of the bounding rectangle.
+*/
+int emr_arc_points_common(
+ PU_RECTL rclBox,
+ PU_POINTL ArcStart,
+ PU_POINTL ArcEnd,
+ int *f1,
+ int f2,
+ PU_PAIRF center,
+ PU_PAIRF start,
+ PU_PAIRF end,
+ PU_PAIRF size
+ ){
+ U_PAIRF estart; // EMF start position, defines a radial
+ U_PAIRF eend; // EMF end position, defines a radial
+ U_PAIRF vec_estart; // define a unit vector from the center to estart
+ U_PAIRF vec_eend; // define a unit vector from the center to eend
+ U_PAIRF radii; // x,y radii of ellipse
+ U_PAIRF ratio; // intermediate value
+ float scale, cross;
+ center->x = ((float)(rclBox->left + rclBox->right ))/2.0;
+ center->y = ((float)(rclBox->top + rclBox->bottom))/2.0;
+ size->x = (float)(rclBox->right - rclBox->left );
+ size->y = (float)(rclBox->bottom - rclBox->top );
+ estart.x = (float)(ArcStart->x);
+ estart.y = (float)(ArcStart->y);
+ eend.x = (float)(ArcEnd->x);
+ eend.y = (float)(ArcEnd->y);
+ radii.x = size->x/2.0;
+ radii.y = size->y/2.0;
+
+ vec_estart.x = (estart.x - center->x); // initial vector, not unit length
+ vec_estart.y = (estart.y - center->y);
+ scale = sqrt(vec_estart.x*vec_estart.x + vec_estart.y*vec_estart.y);
+ if(!scale)return(1); // bogus record, has start at center
+ vec_estart.x /= scale; // now a unit vector
+ vec_estart.y /= scale;
+
+ vec_eend.x = (eend.x - center->x); // initial vector, not unit length
+ vec_eend.y = (eend.y - center->y);
+ scale = sqrt(vec_eend.x*vec_eend.x + vec_eend.y*vec_eend.y);
+ if(!scale)return(2); // bogus record, has end at center
+ vec_eend.x /= scale; // now a unit vector
+ vec_eend.y /= scale;
+
+
+ // Find the intersection of the vectors with the ellipse. With no loss of generality
+ // we can translate the ellipse to the origin, then we just need to find tu (t a factor, u the unit vector)
+ // that also satisfies (x/Rx)^2 + (y/Ry)^2 = 1. x is t*(ux), y is t*(uy), where ux,uy are the x,y components
+ // of the unit vector. Substituting gives:
+ // (t*(ux)/Rx)^2 + (t*(uy)/Ry)^2 = 1
+ // t^2 = 1/( (ux/Rx)^2 + (uy/Ry)^2 )
+ // t = sqrt(1/( (ux/Rx)^2 + (uy/Ry)^2 ))
+
+ ratio.x = vec_estart.x/radii.x;
+ ratio.y = vec_estart.y/radii.y;
+ ratio.x *= ratio.x; // we only use the square
+ ratio.y *= ratio.y;
+ scale = 1.0/sqrt(ratio.x + ratio.y);
+ start->x = center->x + scale * vec_estart.x;
+ start->y = center->y + scale * vec_estart.y;
+
+ ratio.x = vec_eend.x/radii.x;
+ ratio.y = vec_eend.y/radii.y;
+ ratio.x *= ratio.x; // we only use the square
+ ratio.y *= ratio.y;
+ scale = 1.0/sqrt(ratio.x + ratio.y);
+ end->x = center->x + scale * vec_eend.x;
+ end->y = center->y + scale * vec_eend.y;
+
+ //lastly figure out if the swept angle is >180 degrees or not, based on the direction of rotation
+ //and the two unit vectors.
+
+ cross = vec_estart.x * vec_eend.y - vec_estart.y * vec_eend.x;
+ if(!f2){ // counter clockwise rotation
+ if(cross >=0){ *f1 = 1; }
+ else { *f1 = 0; }
+ }
+ else {
+ if(cross >=0){ *f1 = 0; }
+ else { *f1 = 1; }
+ }
+
+
+ return(0);
+}
+
+/**
+ \brief Derive from an EMF arc, chord, or pie the center, start, and end points, and the bounding rectangle.
+
+ \return 0 on success, other values on errors.
+ \param record U_EMRPIE, U_EMRCHORD, or _EMRARC record
+ \param f1 1 if rotation angle >= 180, else 0
+ \param f2 Rotation direction, 1 if counter clockwise, else 0
+ \param center Center coordinates
+ \param start Start coordinates (point on the ellipse defined by rect)
+ \param end End coordinates (point on the ellipse defined by rect)
+ \param size W,H of the x,y axes of the bounding rectangle.
+*/
+int emr_arc_points(
+ PU_ENHMETARECORD record,
+ int *f1,
+ int f2,
+ PU_PAIRF center,
+ PU_PAIRF start,
+ PU_PAIRF end,
+ PU_PAIRF size
+ ){
+ PU_EMRARC pEmr = (PU_EMRARC) (record);
+ return emr_arc_points_common(&(pEmr->rclBox), &(pEmr->ptlStart), &(pEmr->ptlEnd), f1, f2, center, start, end, size );
+}
+
+/**
+ \brief Convert a U_RGBA 32 bit pixmap to one of many different types of DIB pixmaps.
+
+ Conversions to formats using color tables assume that the color table can hold every color
+ in the input image. If that assumption is false then the conversion will fail. Conversion
+ from 8 bit color to N bit colors (N<8) do so by shifting the appropriate number of bits.
+
+ \return 0 on success, other values on errors.
+ \param px DIB pixel array
+ \param cbPx DIB pixel array size in bytes
+ \param ct DIB color table
+ \param numCt DIB color table number of entries
+ \param rgba_px U_RGBA pixel array (32 bits)
+ \param w Width of pixel array
+ \param h Height of pixel array
+ \param stride Row stride of input pixel array in bytes
+ \param colortype DIB BitCount Enumeration
+ \param use_ct If true use color table (only for 1-16 bit DIBs).
+ \param invert If DIB rows are in opposite order from RGBA rows
+*/
+int RGBA_to_DIB(
+ char **px,
+ uint32_t *cbPx,
+ PU_RGBQUAD *ct,
+ int *numCt,
+ const char *rgba_px,
+ int w,
+ int h,
+ int stride,
+ uint32_t colortype,
+ int use_ct,
+ int invert
+ ){
+ int bs;
+ int pad;
+ int i,j,k;
+ int istart, iend, iinc;
+ uint8_t r,g,b,a,tmp8;
+ char *pxptr;
+ const char *rptr;
+ int found;
+ int usedbytes;
+ U_RGBQUAD color;
+ PU_RGBQUAD lct;
+ int32_t index;
+
+ *px=NULL;
+ *ct=NULL;
+ *numCt=0;
+ *cbPx=0;
+ // sanity checking
+ if(!w || !h || !stride || !colortype || !rgba_px)return(1);
+ if(use_ct && colortype >= U_BCBM_COLOR16)return(2); //color tables not used above 16 bit pixels
+ if(!use_ct && colortype < U_BCBM_COLOR16)return(3); //color tables mandatory for < 16 bit
+
+ bs = colortype/8;
+ if(bs<1){
+ usedbytes = (w*colortype + 7)/8; // width of line in fully and partially occupied bytes
+ }
+ else {
+ usedbytes = w*bs;
+ }
+ pad = UP4(usedbytes) - usedbytes; // DIB rows must be aligned on 4 byte boundaries, they are padded at the end to accomplish this.;
+ *cbPx = h * (usedbytes + pad); // Rows must start on a 4 byte boundary!
+ *px = (char *) malloc(*cbPx);
+ if(!px)return(4);
+ if(use_ct){
+ *numCt = 1<< colortype;
+ if(*numCt >w*h)*numCt=w*h;
+ lct = (PU_RGBQUAD) malloc(*numCt * sizeof(U_RGBQUAD));
+ if(!lct)return(5);
+ *ct = lct;
+ }
+
+ if(invert){
+ istart = h-1;
+ iend = -1;
+ iinc = -1;
+ }
+ else {
+ istart = 0;
+ iend = h;
+ iinc = 1;
+ }
+
+ found = 0;
+ tmp8 = 0;
+ pxptr = *px;
+ for(i=istart; i!=iend; i+=iinc){
+ rptr= rgba_px + i*stride;
+ for(j=0; j<w; j++){
+ r = *rptr++;
+ g = *rptr++;
+ b = *rptr++;
+ a = *rptr++;
+ if(use_ct){
+ color = U_BGRA(r,g,b,a); // color has order in memory: b,g,r,a, same as EMF+ ARGB
+ index = -1;
+ for(lct = *ct, k=0; k<found; k++,lct++){ // Is this color in the table (VERY inefficient if there are a lot of colors!!!)
+ if(*(uint32_t *)lct != *(uint32_t *) &color)continue;
+ index =k;
+ break;
+ }
+ if(index==-1){ // add a color
+ found++;
+ if(found > *numCt){ // More colors found than are supported by the color table
+ free(*ct);
+ free(*px);
+ *numCt=0;
+ *cbPx=0;
+ return(6);
+ }
+ index = found - 1;
+ *lct = color;
+ }
+ switch(colortype){
+ case U_BCBM_MONOCHROME: // 2 colors. bmiColors array has two entries
+ tmp8 = tmp8 >> 1; // This seems wrong, as it fills from the top of each byte. But it works.
+ tmp8 |= index << 7;
+ if(!((j+1) % 8)){
+ *pxptr++ = tmp8;
+ tmp8 = 0;
+ }
+ break;
+ case U_BCBM_COLOR4: // 2^4 colors. bmiColors array has 16 entries
+ tmp8 = tmp8 << 4;
+ tmp8 |= index;
+ if(!((j+1) % 2)){
+ *pxptr++ = tmp8;
+ tmp8 = 0;
+ }
+ break;
+ case U_BCBM_COLOR8: // 2^8 colors. bmiColors array has 256 entries
+ tmp8 = index;
+ *pxptr++ = tmp8;
+ break;
+ case U_BCBM_COLOR16: // 2^16 colors. (Several different color methods))
+ case U_BCBM_COLOR24: // 2^24 colors. bmiColors is not used. Pixels are U_RGBTRIPLE.
+ case U_BCBM_COLOR32: // 2^32 colors. bmiColors is not used. Pixels are U_RGBQUAD.
+ case U_BCBM_EXPLICIT: // Derinved from JPG or PNG compressed image or ?
+ default:
+ return(7); // This should not be possible, but might happen with memory corruption
+ }
+ }
+ else {
+ switch(colortype){
+ case U_BCBM_COLOR16: // 2^16 colors. (Several different color methods))
+ b /= 8; g /= 8; r /= 8;
+ // Do it in this way so that the bytes are always stored Little Endian
+ tmp8 = b;
+ tmp8 |= g<<5; // least significant 3 bits of green
+ *pxptr++ = tmp8;
+ tmp8 = g>>3; // most significant 2 bits of green (there are only 5 bits of data)
+ tmp8 |= r<<2;
+ *pxptr++ = tmp8;
+ break;
+ case U_BCBM_COLOR24: // 2^24 colors. bmiColors is not used. Pixels are U_RGBTRIPLE.
+ *pxptr++ = b;
+ *pxptr++ = g;
+ *pxptr++ = r;
+ break;
+ case U_BCBM_COLOR32: // 2^32 colors. bmiColors is not used. Pixels are U_RGBQUAD.
+ *pxptr++ = b;
+ *pxptr++ = g;
+ *pxptr++ = r;
+ *pxptr++ = a;
+ break;
+ case U_BCBM_MONOCHROME: // 2 colors. bmiColors array has two entries
+ case U_BCBM_COLOR4: // 2^4 colors. bmiColors array has 16 entries
+ case U_BCBM_COLOR8: // 2^8 colors. bmiColors array has 256 entries
+ case U_BCBM_EXPLICIT: // Derinved from JPG or PNG compressed image or ?
+ default:
+ return(7); // This should not be possible, but might happen with memory corruption
+ }
+ }
+ }
+ if( use_ct && colortype == U_BCBM_MONOCHROME && (j % 8) ){
+ *pxptr++ = tmp8; // Write last few indices
+ tmp8 = 0;
+ }
+ if( use_ct && colortype == U_BCBM_COLOR4 && (j % 2) ){
+ *pxptr++ = tmp8; // Write last few indices
+ tmp8 = 0;
+ }
+ if(pad){
+ memset(pxptr,0,pad); // not strictly necessary, but set all bytes so that we can find important unset ones with valgrind
+ pxptr += pad;
+ }
+ }
+ return(0);
+}
+
+/**
+ \brief Get the actual number of colors in the color table from the BitMapInfoHeader.
+ \return Number of entries in the color table.
+ \param Bmih char * pointer to the U_BITMAPINFOHEADER
+
+ BitmapInfoHeader may list 0 for some types which implies the maximum value.
+ If the image is big enough, that is set by the bit count, as in 256 for an 8
+ bit image.
+ If the image is smaller it is set by width * height.
+ Note, this may be called by WMF code, so it is not safe to assume the data is aligned.
+*/
+int get_real_color_count(
+ const char *Bmih
+ ){
+ int Colors, BitCount, Width, Height;
+ uint32_t utmp4;
+ uint16_t utmp2;
+ int32_t tmp4;
+ char *cBmih = (char *) Bmih;
+ memcpy(&utmp4, cBmih + offsetof(U_BITMAPINFOHEADER,biClrUsed), 4); Colors = utmp4;
+ memcpy(&utmp2, cBmih + offsetof(U_BITMAPINFOHEADER,biBitCount), 2); BitCount = utmp2;
+ memcpy(&tmp4, cBmih + offsetof(U_BITMAPINFOHEADER,biWidth), 4); Width = tmp4;
+ memcpy(&tmp4, cBmih + offsetof(U_BITMAPINFOHEADER,biHeight), 4); Height = tmp4;
+ return(get_real_color_icount(Colors, BitCount, Width, Height));
+}
+
+/**
+ \brief Get the actual number of colors in the color table from the ClrUsed, BitCount, Width, and Height.
+ \return Number of entries in the color table.
+ \param Colors Number of colors in the table.
+ \param BitCount BitCount Enumeration
+ \param Width bitmap width
+ \param Height bitmap height
+*/
+int get_real_color_icount(
+ int Colors,
+ int BitCount,
+ int Width,
+ int Height
+ ){
+ int area = Width * Height;
+ if(area < 0){ area = -area; } /* Height might be negative */
+ if(Colors == 0){
+ if( BitCount == U_BCBM_MONOCHROME){ Colors = 2; }
+ else if(BitCount == U_BCBM_COLOR4 ){ Colors = 16; }
+ else if(BitCount == U_BCBM_COLOR8 ){ Colors = 256; }
+ if(Colors > area){ Colors = area; }
+ }
+ return(Colors);
+}
+
+
+/**
+ \brief Get the DIB parameters from the BMI of the record for use by DBI_to_RGBA()
+
+ \return BI_Compression Enumeration. For anything other than U_BI_RGB values other than px may not be valid.
+ \param record pointer to EMR record that has a U_BITMAPINFO and bitmap
+ \param offBitsSrc Offset to the bitmap
+ \param offBmiSrc Offset to the U_BITMAPINFO
+ \param px pointer to DIB pixel array in pEmr
+ \param ct pointer to DIB color table in pEmr
+ \param numCt DIB color table number of entries, for PNG or JPG returns the number of bytes in the image
+ \param width Width of pixel array
+ \param height Height of pixel array (always returned as a positive number)
+ \param colortype DIB BitCount Enumeration
+ \param invert If DIB rows are in opposite order from RGBA rows
+*/
+int get_DIB_params(
+ const char *record,
+ uint32_t offBitsSrc,
+ uint32_t offBmiSrc,
+ const char **px,
+ const U_RGBQUAD **ct,
+ uint32_t *numCt,
+ uint32_t *width,
+ uint32_t *height,
+ uint32_t *colortype,
+ uint32_t *invert
+ ){
+ uint32_t bic;
+ PU_BITMAPINFO Bmi = (PU_BITMAPINFO)(record + offBmiSrc);
+ PU_BITMAPINFOHEADER Bmih = &(Bmi->bmiHeader);
+ /* if biCompression is not U_BI_RGB some or all of the following might not hold real values */
+ bic = Bmih->biCompression;
+ *width = Bmih->biWidth;
+ *colortype = Bmih->biBitCount;
+ if(Bmih->biHeight < 0){
+ *height = -Bmih->biHeight;
+ *invert = 1;
+ }
+ else {
+ *height = Bmih->biHeight;
+ *invert = 0;
+ }
+ if(bic == U_BI_RGB){
+ *numCt = get_real_color_count((const char *) Bmih);
+ if( numCt){ *ct = (PU_RGBQUAD) ((char *)Bmi + sizeof(U_BITMAPINFOHEADER)); }
+ else { *ct = NULL; }
+ }
+ else if(bic == U_BI_BITFIELDS){ /* to date only encountered once, for 32 bit, from PPT*/
+ *numCt = 0;
+ *ct = NULL;
+ bic = U_BI_RGB; /* there seems to be no difference, at least for the 32 bit images */
+ }
+ else {
+ *numCt = Bmih->biSizeImage;
+ *ct = NULL;
+ }
+ *px = record + offBitsSrc;
+ return(bic);
+}
+
+/**
+ \brief Convert one of many different types of DIB pixmaps to an RGBA 32 bit pixmap.
+
+ \return 0 on success, other values on errors.
+ \param px DIB pixel array
+ \param ct DIB color table
+ \param numCt DIB color table number of entries
+ \param rgba_px U_RGBA pixel array (32 bits), created by this routine, caller must free.
+ \param w Width of pixel array in the record
+ \param h Height of pixel array in the record
+ \param colortype DIB BitCount Enumeration
+ \param use_ct Kept for symmetry with RGBA_to_DIB, should be set to numCt
+ \param invert If DIB rows are in opposite order from RGBA rows
+*/
+int DIB_to_RGBA(
+ const char *px,
+ const U_RGBQUAD *ct,
+ int numCt,
+ char **rgba_px,
+ int w,
+ int h,
+ uint32_t colortype,
+ int use_ct,
+ int invert
+ ){
+ uint32_t cbRgba_px;
+ int stride;
+ int bs;
+ int pad;
+ int i,j;
+ int istart, iend, iinc;
+ uint8_t r,g,b,a,tmp8;
+ const char *pxptr;
+ char *rptr;
+ int usedbytes;
+ U_RGBQUAD color;
+ int32_t index;
+
+ // sanity checking
+ if(!w || !h || !colortype || !px)return(1);
+ if(use_ct && colortype >= U_BCBM_COLOR16)return(2); //color tables not used above 16 bit pixels
+ if(!use_ct && colortype < U_BCBM_COLOR16)return(3); //color tables mandatory for < 16 bit
+ if(use_ct && !numCt)return(4); //color table not adequately described
+
+ stride = w * 4;
+ cbRgba_px = stride * h;
+ bs = colortype/8;
+ if(bs<1){
+ usedbytes = (w*colortype + 7)/8; // width of line in fully and partially occupied bytes
+ }
+ else {
+ usedbytes = w*bs;
+ }
+ pad = UP4(usedbytes) - usedbytes; // DIB rows must be aligned on 4 byte boundaries, they are padded at the end to accomplish this.;
+ *rgba_px = (char *) malloc(cbRgba_px);
+ if(!rgba_px)return(4);
+
+ if(invert){
+ istart = h-1;
+ iend = -1;
+ iinc = -1;
+ }
+ else {
+ istart = 0;
+ iend = h;
+ iinc = 1;
+ }
+
+ pxptr = px;
+ tmp8 = 0; // silences a compiler warning, tmp8 always sets when j=0, so never used uninitialized
+ for(i=istart; i!=iend; i+=iinc){
+ rptr= *rgba_px + i*stride;
+ for(j=0; j<w; j++){
+ if(use_ct){
+ switch(colortype){
+ case U_BCBM_MONOCHROME: // 2 colors. bmiColors array has two entries
+ if(!(j % 8)){ tmp8 = *pxptr++; }
+ index = 0x80 & tmp8; // This seems wrong, as lowest position is top bit, but it works.
+ index = index >> 7;
+ tmp8 = tmp8 << 1;
+ break;
+ case U_BCBM_COLOR4: // 2^4 colors. bmiColors array has 16 entries
+ if(!(j % 2)){ tmp8 = *pxptr++; }
+ index = 0xF0 & tmp8;
+ index = index >> 4;
+ tmp8 = tmp8 << 4;
+ break;
+ case U_BCBM_COLOR8: // 2^8 colors. bmiColors array has 256 entries
+ index = (uint8_t) *pxptr++;;
+ break;
+ case U_BCBM_COLOR16: // 2^16 colors. (Several different color methods))
+ case U_BCBM_COLOR24: // 2^24 colors. bmiColors is not used. Pixels are U_RGBTRIPLE.
+ case U_BCBM_COLOR32: // 2^32 colors. bmiColors is not used. Pixels are U_RGBQUAD.
+ case U_BCBM_EXPLICIT: // Derinved from JPG or PNG compressed image or ?
+ default:
+ return(7); // This should not be possible, but might happen with memory corruption
+ }
+ color = ct[index];
+ b = U_BGRAGetB(color);
+ g = U_BGRAGetG(color);
+ r = U_BGRAGetR(color);
+ a = U_BGRAGetA(color);
+ }
+ else {
+ switch(colortype){
+ case U_BCBM_COLOR16: // 2^16 colors. (Several different color methods))
+ // Do it in this way because the bytes are always stored Little Endian
+ tmp8 = *pxptr++;
+ b = (0x1F & tmp8) <<3; // 5 bits of b into the top 5 of 8
+ g = tmp8 >> 5; // least significant 3 bits of green
+ tmp8 = *pxptr++;
+ r = (0x7C & tmp8) << 1; // 5 bits of r into the top 5 of 8
+ g |= (0x3 & tmp8) << 3; // most significant 2 bits of green (there are only 5 bits of data)
+ g = g << 3; // restore intensity (have lost 3 bits of accuracy)
+ a = 0;
+ break;
+ case U_BCBM_COLOR24: // 2^24 colors. bmiColors is not used. Pixels are U_RGBTRIPLE.
+ b = *pxptr++;
+ g = *pxptr++;
+ r = *pxptr++;
+ a = 0;
+ break;
+ case U_BCBM_COLOR32: // 2^32 colors. bmiColors is not used. Pixels are U_RGBQUAD.
+ b = *pxptr++;
+ g = *pxptr++;
+ r = *pxptr++;
+ a = *pxptr++;
+ break;
+ case U_BCBM_MONOCHROME: // 2 colors. bmiColors array has two entries
+ case U_BCBM_COLOR4: // 2^4 colors. bmiColors array has 16 entries
+ case U_BCBM_COLOR8: // 2^8 colors. bmiColors array has 256 entries
+ case U_BCBM_EXPLICIT: // Derinved from JPG or PNG compressed image or ?
+ default:
+ return(7); // This should not be possible, but might happen with memory corruption
+ }
+ }
+ *rptr++ = r;
+ *rptr++ = g;
+ *rptr++ = b;
+ *rptr++ = a;
+ }
+ for(j=0; j<pad; j++){ pxptr++; } // DIB rows are all 4 byte aligned
+ }
+ return(0);
+}
+
+/**
+ \brief Extract a subset of an RGBA bitmap array.
+ Frees the incoming bitmap array IF a subset is extracted, otherwise it is left alone.
+ If the entire array is extracted it just returns the incoming pointer.
+ If the subset requested is partially outside of the bitmap the region is clipped to the
+ bitmap boundaries and extracted. This seems to be a (very) grey area in EMF files, and
+ even different Microsoft applications do not always do the same thing. For instance,
+ XP Preview gives some different images for EMR_BITBLT records than does the "import image"
+ (but not unpacked) view in PowerPoint. Since all of these states are probably best viewed
+ as undefined or errors we can only try to do something reasonable and not blow up when
+ encountering one.
+
+ \return Pointer to the sub array on success, NULL otherwise.
+ \param rgba_px U_RGBA pixel array (32 bits), created by this routine, caller must free.
+ \param w Width of pixel array in the record
+ \param h Height of pixel array in the record
+ \param sl start left position in the pixel array in the record to start extracting
+ \param st start top position in the pixel array in the record to start extracting
+ \param eew Width of pixel array to extract
+ \param eeh Height of pixel array to extract
+*/
+char *RGBA_to_RGBA(
+ char *rgba_px,
+ int w,
+ int h,
+ int sl,
+ int st,
+ int *eew,
+ int *eeh
+ ){
+ int i;
+ char *sub;
+ char *sptr;
+ int ew = *eew;
+ int eh = *eeh;
+
+ // sanity checking
+ if(w<=0 || h<=0 || ew<=0 || eh<=0 || !rgba_px)return(NULL);
+
+ if(sl>w || st >h)return(NULL); // This is hopeless, the start point is outside of the array.
+ if(sl<0){
+ if(sl+ew<=0)return(NULL); // This is hopeless, the start point is outside of the array.
+ ew += sl;
+ sl = 0;
+ }
+ if(st<0){
+ if(st+eh<=0)return(NULL); // This is hopeless, the start point is outside of the array.
+ eh += st;
+ st = 0;
+ }
+ if(sl+ew > w)ew=w-sl;
+ if(st+eh > h)eh=h-st;
+ if(!sl && !st && (ew == w) && (eh == h)){
+ sub = rgba_px;
+ }
+ else {
+ sptr = sub = malloc(ew*eh*4);
+ if(!sub)return(NULL);
+ for(i=st; i<st+eh; i++){
+ memcpy(sptr,rgba_px + i*w*4 + sl*4,4*ew);
+ sptr += 4*ew;
+ }
+ free(rgba_px);
+ }
+ *eeh = eh;
+ *eew = ew;
+ return(sub);
+ }
+
+
+/* **********************************************************************************************
+These functions are for setting up, appending to, and then tearing down an EMF structure, including
+writing the final data structure out to a file.
+*********************************************************************************************** */
+
+/**
+ \brief Duplicate an EMR record.
+ \param emr record to duplicate
+*/
+char *emr_dup(
+ const char *emr
+ ){
+ char *dup;
+ int irecsize;
+
+ if(!emr)return(NULL);
+ irecsize = ((PU_EMR)emr)->nSize;
+ dup=malloc(irecsize);
+ if(dup){ memcpy(dup,emr,irecsize); }
+ return(dup);
+}
+
+
+/**
+ \brief Start constructing an emf in memory. Supply the file name and initial size.
+ \return 0 for success, >=0 for failure.
+ \param name EMF filename (will be opened)
+ \param initsize Initialize EMF in memory to hold this many bytes
+ \param chunksize When needed increase EMF in memory by this number of bytes
+ \param et EMF in memory
+
+
+*/
+int emf_start(
+ const char *name,
+ const uint32_t initsize,
+ const uint32_t chunksize,
+ EMFTRACK **et
+ ){
+ FILE *fp;
+ EMFTRACK *etl=NULL;
+
+ if(initsize < 1)return(1);
+ if(chunksize < 1)return(2);
+ if(!name)return(3);
+ etl = (EMFTRACK *) malloc(sizeof(EMFTRACK));
+ if(!etl)return(4);
+ etl->buf = malloc(initsize); // no need to zero the memory
+ if(!etl->buf){
+ free(etl);
+ return(5);
+ }
+ fp=emf_fopen(name,U_WRITE);
+ if(!fp){
+ free(etl->buf);
+ free(etl);
+ return(6);
+ }
+ etl->fp = fp;
+ etl->allocated = initsize;
+ etl->used = 0;
+ etl->records = 0;
+ etl->PalEntries = 0;
+ etl->chunk = chunksize;
+ *et=etl;
+ return(0);
+}
+
+/**
+ \brief Finalize the emf in memory and write it to the file.
+ \return 0 on success, >=1 on failure
+ \param et EMF in memory
+ \param eht EMF handle table (peak handle number needed)
+*/
+int emf_finish(
+ EMFTRACK *et,
+ EMFHANDLES *eht
+ ){
+ U_EMRHEADER *record;
+
+ if(!et->fp)return(1); // This could happen if something stomps on memory, otherwise should be caught in emf_start
+
+ // Set the header fields which were unknown up until this point
+
+ record = (U_EMRHEADER *)et->buf;
+ record->nBytes = et->used;
+ record->nRecords = et->records;
+ record->nHandles = eht->peak + 1;
+ record->nPalEntries = et->PalEntries;
+
+#if U_BYTE_SWAP
+ //This is a Big Endian machine, EMF data must be Little Endian
+ U_emf_endian(et->buf,et->used,1);
+#endif
+
+ if(1 != fwrite(et->buf,et->used,1,et->fp))return(2);
+ (void) fclose(et->fp);
+ et->fp=NULL;
+ return(0);
+}
+
+/**
+ \brief Release memory for an emf structure in memory. Call this after emf_finish().
+ \return 0 on success, >=1 on failure
+ \param et EMF in memory
+*/
+int emf_free(
+ EMFTRACK **et
+ ){
+ EMFTRACK *etl;
+ if(!et)return(1);
+ etl=*et;
+ if(!etl)return(2);
+ free(etl->buf);
+ free(etl);
+ *et=NULL;
+ return(0);
+}
+
+/**
+ \brief wrapper for fopen, works on any platform
+ \return 0 on success, >=1 on failure
+ \param filename file to open (either ASCII or UTF-8)
+ \param mode U_READ or U_WRITE (these map to "rb" and "wb")
+*/
+FILE *emf_fopen(
+ const char *filename,
+ const int mode
+ ){
+ FILE *fp = NULL;
+#ifdef WIN32
+ uint16_t *fn16;
+ uint16_t *md16;
+ if(mode == U_READ){ md16 = U_Utf8ToUtf16le("rb", 0, NULL); }
+ else { md16 = U_Utf8ToUtf16le("wb", 0, NULL); }
+ fn16 = U_Utf8ToUtf16le(filename, 0, NULL);
+ fp = _wfopen(fn16,md16);
+ free(fn16);
+ free(md16);
+#else
+ if(mode == U_READ){ fp = fopen(filename,"rb"); }
+ else { fp = fopen(filename,"wb"); }
+#endif
+ return(fp);
+}
+
+/**
+ \brief Retrieve contents of an EMF file by name.
+ \return 0 on success, >=1 on failure
+ \param filename Name of file to open, including the path
+ \param contents Contents of the file. Buffer must be free()'d by caller.
+ \param length Number of bytes in Contents
+*/
+int emf_readdata(
+ const char *filename,
+ char **contents,
+ size_t *length
+ ){
+ FILE *fp;
+ int status=0;
+
+ *contents=NULL;
+ fp=emf_fopen(filename,U_READ);
+ if(!fp){ status = 1; }
+ else {
+ // read the entire file into memory
+ fseek(fp, 0, SEEK_END); // move to end
+ *length = ftell(fp);
+ rewind(fp);
+ *contents = (char *) malloc(*length);
+ if(!*contents){
+ status = 2;
+ }
+ else {
+ size_t inbytes = fread(*contents,*length,1,fp);
+ if(inbytes != 1){
+ free(*contents);
+ status = 3;
+ }
+ else {
+#if U_BYTE_SWAP
+ //This is a Big Endian machine, EMF data is Little Endian
+ U_emf_endian(*contents,*length,0); // LE to BE
+#endif
+ }
+ }
+ fclose(fp);
+ }
+ return(status);
+}
+
+
+/**
+ \brief Append an EMF record to an emf in memory. This may reallocate buf memory.
+ \return 0 for success, >=1 for failure.
+ \param rec Record to append to EMF in memory
+ \param et EMF in memory
+ \param freerec If true, free rec after append
+*/
+int emf_append(
+ U_ENHMETARECORD *rec,
+ EMFTRACK *et,
+ int freerec
+ ){
+ size_t deficit;
+
+#ifdef U_VALGRIND
+ printf("\nbefore \n");
+ printf(" probe %d\n",memprobe(rec, U_EMRSIZE(rec)));
+ printf("after \n");
+#endif
+ if(!rec)return(1);
+ if(!et)return(2);
+ if(rec->nSize + et->used > et->allocated){
+ deficit = rec->nSize + et->used - et->allocated;
+ if(deficit < et->chunk)deficit = et->chunk;
+ et->allocated += deficit;
+ et->buf = realloc(et->buf,et->allocated);
+ if(!et->buf)return(3);
+ }
+ memcpy(et->buf + et->used, rec, rec->nSize);
+ et->used += rec->nSize;
+ et->records++;
+ if(rec->iType == U_EMR_EOF){ et->PalEntries = ((U_EMREOF *)rec)->cbPalEntries; }
+ if(freerec){ free(rec); }
+ return(0);
+}
+
+/**
+ \brief Create a handle table. Entries filled with 0 are empty, entries >0 hold a handle.
+ \return 0 for success, >=1 for failure.
+ \param initsize Initialize with space for this number of handles
+ \param chunksize When needed increase space by this number of handles
+ \param eht EMF handle table
+*/
+int emf_htable_create(
+ uint32_t initsize,
+ uint32_t chunksize,
+ EMFHANDLES **eht
+ ){
+ EMFHANDLES *ehtl;
+ unsigned int i;
+
+ if(initsize<1)return(1);
+ if(chunksize<1)return(2);
+ ehtl = (EMFHANDLES *) malloc(sizeof(EMFHANDLES));
+ if(!ehtl)return(3);
+ ehtl->table = malloc(initsize * sizeof(uint32_t));
+ if(!ehtl->table){
+ free(ehtl);
+ return(4);
+ }
+ ehtl->stack = malloc(initsize * sizeof(uint32_t));
+ if(!ehtl->stack){
+ free(ehtl->table);
+ free(ehtl);
+ return(5);
+ }
+ memset(ehtl->table , 0, initsize * sizeof(uint32_t)); // zero all slots in the table
+ for(i=1; i<initsize; i++){ehtl->stack[i]=i;} // preset the stack
+ ehtl->allocated = initsize;
+ ehtl->chunk = chunksize;
+ ehtl->table[0] = 0; // This slot isn't actually ever used
+ ehtl->stack[0] = 0; // This stack position isn't actually ever used
+ ehtl->peak = 1;
+ ehtl->sptr = 1;
+ ehtl->top = 0;
+ *eht = ehtl;
+ return(0);
+}
+
+/**
+ \brief Delete an entry from the handle table. Move it back onto the stack. The specified slot is filled with a 0.
+ \return 0 for success, >=1 for failure.
+ \param ih handle
+ \param eht EMF handle table
+
+*/
+int emf_htable_delete(
+ uint32_t *ih,
+ EMFHANDLES *eht
+ ){
+ if(!eht)return(1);
+ if(!eht->table)return(2);
+ if(!eht->stack)return(3);
+ if(*ih < 1)return(4); // invalid handle
+ if(!eht->table[*ih])return(5); // requested table position was not in use
+ eht->table[*ih]=0; // remove handle from table
+ while(eht->top>0 && !eht->table[eht->top]){ // adjust top
+ eht->top--;
+ }
+ eht->sptr--; // adjust stack
+ eht->stack[eht->sptr]=*ih; // place handle on stack
+ *ih=0; // invalidate handle variable, so a second delete will of it is not possible
+ return(0);
+}
+
+/**
+ \brief Returns the index of the first free slot.
+ Call realloc() if needed. The slot is set to handle (indicates occupied) and the peak value is adjusted.
+ \return 0 for success, >=1 for failure.
+ \param ih handle
+ \param eht EMF handle table
+*/
+int emf_htable_insert(
+ uint32_t *ih,
+ EMFHANDLES *eht
+ ){
+ unsigned int i;
+ size_t newsize;
+
+ if(!eht)return(1);
+ if(!eht->table)return(2);
+ if(!eht->stack)return(3);
+ if(!ih)return(4);
+ if(eht->sptr >= eht->allocated - 1){ // need to reallocate
+ newsize=eht->allocated + eht->chunk;
+ eht->table = realloc(eht->table,newsize * sizeof(uint32_t));
+ if(!eht->table)return(5);
+ memset(&eht->table[eht->allocated] , 0, eht->chunk * sizeof(uint32_t)); // zero all NEW slots in the table
+
+ eht->stack = realloc(eht->stack,newsize * sizeof(uint32_t));
+ if(!eht->stack)return(6);
+ for(i=eht->allocated; i<newsize;i++){ eht->stack[i] = i; } // init all NEW slots in the stack
+ eht->allocated = newsize;
+ }
+ *ih = eht->stack[eht->sptr]; // handle that is inserted
+ if(eht->table[*ih])return(7);
+ eht->table[*ih] = *ih; // handle goes into preexisting (but zero) slot in table
+ eht->stack[eht->sptr] = 0;
+ if(*ih > eht->top){ eht->top = *ih; }
+ if(eht->sptr > eht->peak){ eht->peak = eht->sptr; }
+ eht->sptr++; // next available handle
+ return(0);
+}
+
+/**
+ \brief Free all memory in an htable. Sets the pointer to NULL.
+ \return 0 for success, >=1 for failure.
+ \param eht EMF handle table
+*/
+int emf_htable_free(
+ EMFHANDLES **eht
+ ){
+ EMFHANDLES *ehtl;
+ if(!eht)return(1);
+ ehtl = *eht;
+ if(!ehtl)return(2);
+ if(!ehtl->table)return(3);
+ if(!ehtl->stack)return(4);
+ free(ehtl->table);
+ free(ehtl->stack);
+ free(ehtl);
+ *eht=NULL;
+ return(0);
+}
+
+/* **********************************************************************************************
+These functions create standard structures used in the EMR records.
+*********************************************************************************************** */
+
+
+/**
+ \brief Set up fields for an EMR_HEADER from the physical device's width and height in mm and dots per millimeter.
+ Typically this is something like 216,279,47.244 (Letter paper, 1200 DPI = 47.244 DPmm)
+ \return 0 for success, >=1 for failure.
+ \param xmm Device width in millimeters
+ \param ymm Device height in millimeters
+ \param dpmm Dots per millimeter
+ \param szlDev Device size structure in pixels
+ \param szlMm Device size structure in mm
+*/
+int device_size(
+ const int xmm,
+ const int ymm,
+ const float dpmm,
+ U_SIZEL *szlDev,
+ U_SIZEL *szlMm
+ ){
+ if(xmm < 0 || ymm < 0 || dpmm < 0)return(1);
+ szlDev->cx = U_ROUND((float) xmm * dpmm);
+ szlDev->cy = U_ROUND((float) ymm * dpmm);;
+ szlMm->cx = xmm;
+ szlMm->cy = ymm;
+ return(0);
+}
+
+/**
+ \brief Set up fields for an EMR_HEADER for drawing by physical size in mm and dots per millimeter.
+ Technically rclBounds is supposed to be the extent of the drawing within the EMF, but libUEMF has no way
+ of knowing this since it never actually draws anything. Instead this is set to the full drawing size.
+ Coordinates are inclusive inclusive, so 297 -> 0,29699.
+ \return 0 for success, >=1 for failure.
+ \param xmm Drawing width in millimeters
+ \param ymm Drawing height in millimeters
+ \param dpmm Dots per millimeter
+ \param rclBounds Drawing size structure in pixels
+ \param rclFrame Drawing size structure in mm
+*/
+int drawing_size(
+ const int xmm,
+ const int ymm,
+ const float dpmm,
+ U_RECTL *rclBounds,
+ U_RECTL *rclFrame
+ ){
+ if(xmm < 0 || ymm < 0 || dpmm < 0)return(1);
+ rclBounds->left = 0;
+ rclBounds->top = 0;
+ rclBounds->right = U_ROUND((float) xmm * dpmm) - 1; // because coordinate system is 0,0 in upper left, N,M in lower right
+ rclBounds->bottom = U_ROUND((float) ymm * dpmm) - 1;
+ rclFrame->left = 0;
+ rclFrame->top = 0;
+ rclFrame->right = U_ROUND((float) xmm * 100.) - 1;
+ rclFrame->bottom = U_ROUND((float) ymm * 100.) - 1;
+ return(0);
+}
+
+/**
+ \brief Set a U_COLORREF value from separate R,G,B values.
+ \param red Red component
+ \param green Green component
+ \param blue Blue component
+
+*/
+U_COLORREF colorref3_set(
+ uint8_t red,
+ uint8_t green,
+ uint8_t blue
+ ){
+ U_COLORREF cr = (U_COLORREF){red , green, blue, 0};
+ return(cr);
+}
+
+/**
+ \brief Set a U_COLORREF value from separate R,G,B, and Reserved values.
+ \param red Red component
+ \param green Green component
+ \param blue Blue component
+ \param Reserved Reserved component
+
+*/
+U_COLORREF colorref4_set(
+ uint8_t red,
+ uint8_t green,
+ uint8_t blue,
+ uint8_t Reserved
+ ){
+ U_COLORREF cr = (U_COLORREF){red , green, blue, Reserved};
+ return(cr);
+}
+
+/**
+ \brief Set a U_RGBQUAD value from separate R,G,B, Reserved values.
+ \param red Red component
+ \param green Green component
+ \param blue Blue component
+ \param reserved Reserved component
+
+*/
+U_RGBQUAD rgbquad_set(
+ uint8_t red,
+ uint8_t green,
+ uint8_t blue,
+ uint8_t reserved
+ ){
+ U_RGBQUAD cr = (U_RGBQUAD){blue , green, red, reserved};
+ return(cr);
+}
+
+/**
+ \brief Set rect and rectl objects from Upper Left and Lower Right corner points.
+ \param ul upper left corner of rectangle
+ \param lr lower right corner of rectangle
+*/
+U_RECTL rectl_set(
+ U_POINTL ul,
+ U_POINTL lr
+ ){
+ U_RECTL rct;
+ rct.left = ul.x;
+ rct.top = ul.y;
+ rct.right = lr.x;
+ rct.bottom = lr.y;
+ return(rct);
+}
+
+/**
+ \brief Set rect and rectl objects from Upper Left and Lower Right corner points.
+ \param array array of rectangles
+ \param index array entry to fill, numbered from 0
+ \param ul upper left corner of rectangle
+ \param lr lower right corner of rectangle
+*/
+void rectli_set(
+ PU_RECTL array,
+ int index,
+ U_POINTL ul,
+ U_POINTL lr
+ ){
+ PU_RECTL rct = &(array[index]);
+ rct->left = ul.x;
+ rct->top = ul.y;
+ rct->right = lr.x;
+ rct->bottom = lr.y;
+}
+
+/**
+ \brief Set sizel objects with X,Y values.
+ \param x X coordinate
+ \param y Y coordinate
+*/
+U_SIZEL sizel_set(
+ int32_t x,
+ int32_t y
+ ){
+ U_SIZEL sz;
+ sz.cx = x;
+ sz.cy = y;
+ return(sz);
+}
+
+/**
+ \brief Set pointl objects with X,Y values.
+ \param x X coordinate
+ \param y Y coordinate
+*/
+U_POINTL point32_set(
+ int32_t x,
+ int32_t y
+ ){
+ U_POINTL pt;
+ pt.x = x;
+ pt.y = y;
+ return(pt);
+}
+
+/**
+ \brief Set point16 objects with 16 bit X,Y values.
+ \param x X coordinate
+ \param y Y coordinate
+*/
+U_POINT16 point16_set(
+ int16_t x,
+ int16_t y
+ ){
+ U_POINT16 pt;
+ pt.x = x;
+ pt.y = y;
+ return(pt);
+}
+
+/**
+ \brief Find the bounding rectangle from a polyline of a given width.
+ \param count number of points in the polyline
+ \param pts the polyline
+ \param width width of drawn line
+
+*/
+U_RECT findbounds(
+ uint32_t count,
+ PU_POINT pts,
+ uint32_t width
+ ){
+ U_RECT rect={INT32_MAX, INT32_MAX, INT32_MIN, INT32_MIN };
+ unsigned int i;
+
+ for(i=0; i<count;i++,pts++){
+ if ( pts->x < rect.left ) rect.left = pts->x;
+ if ( pts->x > rect.right ) rect.right = pts->x;
+ if ( pts->y < rect.top ) rect.top = pts->y;
+ if ( pts->y > rect.bottom ) rect.bottom = pts->y;
+ }
+ if(width > 0){
+ rect.left -= width;
+ rect.right += width;
+ rect.top += width;
+ rect.bottom -= width;
+ }
+ return(rect);
+}
+
+/**
+ \brief Find the bounding rectangle from a polyline of a given width.
+ \param count number of points in the polyline
+ \param pts the polyline
+ \param width width of drawn line
+
+*/
+U_RECT findbounds16(
+ uint32_t count,
+ PU_POINT16 pts,
+ uint32_t width
+ ){
+ U_RECT rect={INT16_MAX, INT16_MAX, INT16_MIN, INT16_MIN };
+ unsigned int i;
+
+ for(i=0; i<count;i++,pts++){
+ if ( pts->x < rect.left ) rect.left = pts->x;
+ if ( pts->x > rect.right ) rect.right = pts->x;
+ if ( pts->y < rect.top ) rect.top = pts->y;
+ if ( pts->y > rect.bottom ) rect.bottom = pts->y;
+ }
+ if(width > 0){
+ rect.left -= width;
+ rect.right += width;
+ rect.top += width;
+ rect.bottom -= width;
+ }
+ return(rect);
+}
+/**
+ \brief Construct a U_LOGBRUSH structure.
+ \return U_LOGBRUSH structure
+ \param lbStyle LB_Style Enumeration
+ \param lbColor Brush color
+ \param lbHatch HatchStyle Enumertaion
+*/
+U_LOGBRUSH logbrush_set(
+ uint32_t lbStyle,
+ U_COLORREF lbColor,
+ int32_t lbHatch
+ ){
+ U_LOGBRUSH lb;
+ lb.lbStyle = lbStyle;
+ lb.lbColor = lbColor;
+ lb.lbHatch = lbHatch;
+ return(lb);
+}
+
+/**
+ \brief Construct a U_XFORM structure.
+ \return U_XFORM structure
+ \param eM11 Rotation Matrix element
+ \param eM12 Rotation Matrix element
+ \param eM21 Rotation Matrix element
+ \param eM22 Rotation Matrix element
+ \param eDx Translation element
+ \param eDy Translation element
+*/
+U_XFORM xform_set(
+ U_FLOAT eM11,
+ U_FLOAT eM12,
+ U_FLOAT eM21,
+ U_FLOAT eM22,
+ U_FLOAT eDx,
+ U_FLOAT eDy
+ ){
+ U_XFORM xform;
+ xform.eM11 = eM11;
+ xform.eM12 = eM12;
+ xform.eM21 = eM21;
+ xform.eM22 = eM22;
+ xform.eDx = eDx;
+ xform.eDy = eDy;
+ return(xform);
+}
+
+/**
+ \brief Construct a U_XFORM structure.
+ \return U_XFORM structure
+ \param scale Scale factor
+ \param ratio Ratio of minor axis/major axis
+ \param rot Rotation angle in degrees, positive is counter clockwise from the x axis.
+ \param axisrot Angle in degrees defining the major axis before rotation, positive is counter clockwise from the x axis.
+ \param eDx Translation element
+ \param eDy Translation element
+
+ Operation is:
+ 1 Conformal map of points based on scale, axis rotation, and axis ratio,
+ 2. Apply rotation
+ 3. Apply offset
+*/
+U_XFORM xform_alt_set(
+ U_FLOAT scale,
+ U_FLOAT ratio,
+ U_FLOAT rot,
+ U_FLOAT axisrot,
+ U_FLOAT eDx,
+ U_FLOAT eDy
+ ){
+ U_XFORM xform;
+ U_MAT2X2 mat1, mat2;
+ // angles are in degrees, must be in radians
+ rot *= (2.0 * U_PI)/360.0;
+ axisrot *= -(2.0 * U_PI)/360.0;
+ mat1.M11 = cos(rot); // set up the rotation matrix
+ mat1.M12 = -sin(rot);
+ mat1.M21 = sin(rot);
+ mat1.M22 = cos(rot);
+ if(ratio!=1.0){ // set scale/ellipticity matrix
+ mat2.M11 = scale*( cos(axisrot)*cos(axisrot) + ratio*sin(axisrot)*sin(axisrot) );
+ mat2.M12 = mat2.M21 = scale*( sin(axisrot)*cos(axisrot) * (1.0 - ratio) );
+ mat2.M22 = scale*( sin(axisrot)*sin(axisrot) + ratio*cos(axisrot)*cos(axisrot) );
+ }
+ else { // when the ratio is 1.0 then the major axis angle is ignored and only scale matters
+ mat2.M11 = scale;
+ mat2.M12 = 0.0;
+ mat2.M21 = 0.0;
+ mat2.M22 = scale;
+ }
+ xform.eM11 = mat2.M11 * mat1.M11 + mat2.M12 * mat1.M21;
+ xform.eM12 = mat2.M11 * mat1.M12 + mat2.M12 * mat1.M22;;
+ xform.eM21 = mat2.M21 * mat1.M11 + mat2.M22 * mat1.M21;
+ xform.eM22 = mat2.M21 * mat1.M12 + mat2.M22 * mat1.M22;
+ xform.eDx = eDx;
+ xform.eDy = eDy;
+ return(xform);
+}
+
+
+/**
+ \brief Construct a U_LOGCOLORSPACEA structure.
+ \return U_LOGCOLORSPACEA structure
+ \param lcsCSType LCS_CSType Enumeration
+ \param lcsIntent LCS_Intent Enumeration
+ \param lcsEndpoints CIE XYZ color space endpoints
+ \param lcsGammaRGB Gamma For RGB
+ \param lcsFilename Could name an external color profile file, otherwise empty string
+*/
+U_LOGCOLORSPACEA logcolorspacea_set(
+ int32_t lcsCSType,
+ int32_t lcsIntent,
+ U_CIEXYZTRIPLE lcsEndpoints,
+ U_LCS_GAMMARGB lcsGammaRGB,
+ char *lcsFilename
+ ){
+ U_LOGCOLORSPACEA lcsa;
+ lcsa.lcsSignature = U_LCS_SIGNATURE;
+ lcsa.lcsVersion = U_LCS_SIGNATURE;
+ lcsa.lcsSize = sizeof(U_LOGCOLORSPACEA);
+ lcsa.lcsCSType = lcsCSType;
+ lcsa.lcsIntent = lcsIntent;
+ lcsa.lcsEndpoints = lcsEndpoints;
+ lcsa.lcsGammaRGB = lcsGammaRGB;
+ strncpy(lcsa.lcsFilename,lcsFilename,U_MAX_PATH);
+ lcsa.lcsFilename[U_MAX_PATH-1] = '\0';
+ return(lcsa);
+}
+
+/**
+
+ \brief Construct a U_LOGCOLORSPACEW structure.
+ \return U_LOGCOLORSPACEW structure
+ \param lcsCSType LCS_CSType Enumeration
+ \param lcsIntent LCS_Intent Enumeration
+ \param lcsEndpoints CIE XYZ color space endpoints
+ \param lcsGammaRGB Gamma For RGB
+ \param lcsFilename Could name an external color profile file, otherwise empty string
+*/
+U_LOGCOLORSPACEW logcolorspacew_set(
+ int32_t lcsCSType,
+ int32_t lcsIntent,
+ U_CIEXYZTRIPLE lcsEndpoints,
+ U_LCS_GAMMARGB lcsGammaRGB,
+ uint16_t *lcsFilename
+ ){
+ U_LOGCOLORSPACEW lcsa;
+ lcsa.lcsSignature = U_LCS_SIGNATURE;
+ lcsa.lcsVersion = U_LCS_SIGNATURE;
+ lcsa.lcsSize = sizeof(U_LOGCOLORSPACEW);
+ lcsa.lcsCSType = lcsCSType;
+ lcsa.lcsIntent = lcsIntent;
+ lcsa.lcsEndpoints = lcsEndpoints;
+ lcsa.lcsGammaRGB = lcsGammaRGB;
+ wchar16strncpypad(lcsa.lcsFilename,lcsFilename,U_MAX_PATH);
+ lcsa.lcsFilename[U_MAX_PATH-1] = '\0';
+ return(lcsa);
+}
+
+/**
+
+ \brief Construct a U_PANOSE structure.
+ \return U_PANOSE structure
+ \param bFamilyType FamilyType Enumeration
+ \param bSerifStyle SerifType Enumeration
+ \param bWeight Weight Enumeration
+ \param bProportion Proportion Enumeration
+ \param bContrast Contrast Enumeration
+ \param bStrokeVariation StrokeVariation Enumeration
+ \param bArmStyle ArmStyle Enumeration
+ \param bLetterform Letterform Enumeration
+ \param bMidline Midline Enumeration
+ \param bXHeight XHeight Enumeration
+*/
+U_PANOSE panose_set(
+ uint8_t bFamilyType,
+ uint8_t bSerifStyle,
+ uint8_t bWeight,
+ uint8_t bProportion,
+ uint8_t bContrast,
+ uint8_t bStrokeVariation,
+ uint8_t bArmStyle,
+ uint8_t bLetterform,
+ uint8_t bMidline,
+ uint8_t bXHeight
+ ){
+ U_PANOSE panose;
+ panose.bFamilyType = bFamilyType;
+ panose.bSerifStyle = bSerifStyle;
+ panose.bWeight = bWeight;
+ panose.bProportion = bProportion;
+ panose.bContrast = bContrast;
+ panose.bStrokeVariation = bStrokeVariation;
+ panose.bArmStyle = bArmStyle;
+ panose.bLetterform = bLetterform;
+ panose.bMidline = bMidline;
+ panose.bXHeight = bXHeight;
+ return(panose);
+}
+
+/**
+ \brief Construct a U_LOGFONT structure.
+ \return U_LOGFONT structure
+ \param lfHeight Height in Logical units
+ \param lfWidth Average Width in Logical units
+ \param lfEscapement Angle in 0.1 degrees betweem escapement vector and X axis
+ \param lfOrientation Angle in 0.1 degrees between baseline and X axis
+ \param lfWeight LF_Weight Enumeration
+ \param lfItalic Italics: 0 or 1
+ \param lfUnderline Underline: 0 or 1
+ \param lfStrikeOut Strikeout: 0 or 1
+ \param lfCharSet LF_CharSet Enumeration
+ \param lfOutPrecision LF_OutPrecision Enumeration
+ \param lfClipPrecision LF_ClipPrecision Enumeration
+ \param lfQuality LF_Quality Enumeration
+ \param lfPitchAndFamily LF_PitchAndFamily Enumeration
+ \param lfFaceName Name of font. truncates at U_LF_FACESIZE, smaller must be null terminated
+
+*/
+U_LOGFONT logfont_set(
+ int32_t lfHeight,
+ int32_t lfWidth,
+ int32_t lfEscapement,
+ int32_t lfOrientation,
+ int32_t lfWeight,
+ uint8_t lfItalic,
+ uint8_t lfUnderline,
+ uint8_t lfStrikeOut,
+ uint8_t lfCharSet,
+ uint8_t lfOutPrecision,
+ uint8_t lfClipPrecision,
+ uint8_t lfQuality,
+ uint8_t lfPitchAndFamily,
+ uint16_t *lfFaceName
+ ){
+ U_LOGFONT lf;
+ lf.lfHeight = lfHeight;
+ lf.lfWidth = lfWidth;
+ lf.lfEscapement = lfEscapement;
+ lf.lfOrientation = lfOrientation;
+ lf.lfWeight = lfWeight;
+ lf.lfItalic = lfItalic;
+ lf.lfUnderline = lfUnderline;
+ lf.lfStrikeOut = lfStrikeOut;
+ lf.lfCharSet = lfCharSet;
+ lf.lfOutPrecision = lfOutPrecision;
+ lf.lfClipPrecision = lfClipPrecision;
+ lf.lfQuality = lfQuality;
+ lf.lfPitchAndFamily = lfPitchAndFamily;
+ wchar16strncpypad(lf.lfFaceName, lfFaceName, U_LF_FACESIZE); // pad this one as the intial structure was not set to zero
+ lf.lfFaceName[U_LF_FACESIZE-1] = '\0';
+ return(lf);
+}
+
+
+/**
+ \brief Construct a U_LOGFONT_PANOSE structure.
+ \return U_LOGFONT_PANOSE structure
+ \param elfLogFont Basic font attributes
+ \param elfFullName Font full name, truncates at U_LF_FULLFACESIZE, smaller must be null terminated
+ \param elfStyle Font style, truncates at U_LF_FULLFACESIZE, smaller must be null terminated
+ \param elfStyleSize Font hinting starting at this point size, if 0, starts at Height
+ \param elfPanose Panose Object. If all zero, it is ignored.
+*/
+U_LOGFONT_PANOSE logfont_panose_set(
+ U_LOGFONT elfLogFont,
+ uint16_t *elfFullName,
+ uint16_t *elfStyle,
+ uint32_t elfStyleSize,
+ U_PANOSE elfPanose
+ ){
+ U_LOGFONT_PANOSE lfp;
+ memset(&lfp,0,sizeof(U_LOGFONT_PANOSE)); // all fields zero unless needed. Many should be ignored or must be 0.
+ wchar16strncpy(lfp.elfFullName, elfFullName, U_LF_FULLFACESIZE);
+ lfp.elfFullName[U_LF_FULLFACESIZE-1] = '\0';
+ wchar16strncpy(lfp.elfStyle, elfStyle, U_LF_FACESIZE);
+ lfp.elfStyle[U_LF_FACESIZE-1] = '\0';
+ lfp.elfLogFont = elfLogFont;
+ lfp.elfStyleSize = elfStyleSize;
+ lfp.elfPanose = elfPanose;
+ return(lfp);
+}
+
+/**
+ \brief Construct a U_BITMAPINFOHEADER structure.
+ \return U_BITMAPINFOHEADER structure
+ \param biWidth Bitmap width in pixels
+ \param biHeight Bitmap height in pixels
+ \param biPlanes Planes (must be 1)
+ \param biBitCount BitCount Enumeration
+ \param biCompression BI_Compression Enumeration
+ \param biSizeImage Size in bytes of image
+ \param biXPelsPerMeter X Resolution in pixels/meter
+ \param biYPelsPerMeter Y Resolution in pixels/meter
+ \param biClrUsed Number of bmciColors in U_BITMAPCOREINFO
+ \param biClrImportant Number of bmciColors needed (0 means all).
+*/
+U_BITMAPINFOHEADER bitmapinfoheader_set(
+ int32_t biWidth,
+ int32_t biHeight,
+ uint16_t biPlanes,
+ uint16_t biBitCount,
+ uint32_t biCompression,
+ uint32_t biSizeImage,
+ int32_t biXPelsPerMeter,
+ int32_t biYPelsPerMeter,
+ U_NUM_RGBQUAD biClrUsed,
+ uint32_t biClrImportant
+ ){
+ U_BITMAPINFOHEADER Bmi;
+ Bmi.biSize = sizeof(U_BITMAPINFOHEADER);
+ Bmi.biWidth = biWidth;
+ Bmi.biHeight = biHeight;
+ Bmi.biPlanes = biPlanes;
+ Bmi.biBitCount = biBitCount;
+ Bmi.biCompression = biCompression;
+ Bmi.biSizeImage = biSizeImage;
+ Bmi.biXPelsPerMeter = biXPelsPerMeter;
+ Bmi.biYPelsPerMeter = biYPelsPerMeter;
+ Bmi.biClrUsed = biClrUsed;
+ Bmi.biClrImportant = biClrImportant;
+ return(Bmi);
+}
+
+
+/**
+ \brief Allocate and construct a U_BITMAPINFO structure.
+ \return Pointer to a U_BITMAPINFO structure
+ \param BmiHeader Geometry and pixel properties
+ \param BmiColors Color table (must be NULL for some values of BmiHeader->biBitCount)
+*/
+PU_BITMAPINFO bitmapinfo_set(
+ U_BITMAPINFOHEADER BmiHeader,
+ PU_RGBQUAD BmiColors
+ ){
+ char *record;
+ int irecsize;
+ int cbColors, cbColors4, off;
+
+ cbColors = 4*get_real_color_count((char *) &BmiHeader);
+ cbColors4 = UP4(cbColors);
+ irecsize = sizeof(U_BITMAPINFOHEADER) + cbColors4;
+ record = malloc(irecsize);
+ if(record){
+ memcpy(record, &BmiHeader, sizeof(U_BITMAPINFOHEADER));
+ if(cbColors){
+ off = sizeof(U_BITMAPINFOHEADER);
+ memcpy(record + off, BmiColors, cbColors);
+ off += cbColors;
+ if(cbColors4 - cbColors){ memset(record + off, 0, cbColors4 - cbColors); }
+ }
+ }
+ return((PU_BITMAPINFO) record);
+}
+
+/**
+ \brief Allocate and construct a U_EXTLOGPEN structure.
+ \return pointer to U_EXTLOGPEN structure, or NULL on error
+ \param elpPenStyle PenStyle Enumeration
+ \param elpWidth Width in logical units (elpPenStyle & U_PS_GEOMETRIC) or 1 (pixel)
+ \param elpBrushStyle LB_Style Enumeration
+ \param elpColor Pen color
+ \param elpHatch HatchStyle Enumeration
+ \param elpNumEntries Count of StyleEntry array
+ \param elpStyleEntry Array of StyleEntry (For user specified dot/dash patterns)
+*/
+PU_EXTLOGPEN extlogpen_set(
+ uint32_t elpPenStyle,
+ uint32_t elpWidth,
+ uint32_t elpBrushStyle,
+ U_COLORREF elpColor,
+ int32_t elpHatch,
+ U_NUM_STYLEENTRY elpNumEntries,
+ U_STYLEENTRY *elpStyleEntry
+ ){
+ int irecsize,szSyleArray;
+ char *record;
+
+ if(elpNumEntries){
+ if(!elpStyleEntry)return(NULL);
+ szSyleArray = elpNumEntries * sizeof(U_STYLEENTRY);
+ irecsize = sizeof(U_EXTLOGPEN) + szSyleArray - sizeof(U_STYLEENTRY); // first one is in the record
+ }
+ else {
+ szSyleArray = 0;
+ irecsize = sizeof(U_EXTLOGPEN);
+ }
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EXTLOGPEN) record)->elpPenStyle = elpPenStyle;
+ ((PU_EXTLOGPEN) record)->elpWidth = elpWidth;
+ ((PU_EXTLOGPEN) record)->elpBrushStyle = elpBrushStyle;
+ ((PU_EXTLOGPEN) record)->elpColor = elpColor;
+ ((PU_EXTLOGPEN) record)->elpHatch = elpHatch;
+ ((PU_EXTLOGPEN) record)->elpNumEntries = elpNumEntries;
+ if(elpNumEntries){ memcpy(((PU_EXTLOGPEN) record)->elpStyleEntry,elpStyleEntry,szSyleArray); }
+ else { memset(((PU_EXTLOGPEN) record)->elpStyleEntry,0,sizeof(U_STYLEENTRY)); } // not used, but this stops valgrind warnings
+ }
+ return((PU_EXTLOGPEN) record);
+}
+
+/**
+ \brief Construct a U_LOGPEN structure.
+ \return U_LOGPEN structure
+ \param lopnStyle PenStyle Enumeration
+ \param lopnWidth Width of pen set by X, Y is ignored
+ \param lopnColor Pen color value
+
+*/
+U_LOGPEN logpen_set(
+ uint32_t lopnStyle,
+ U_POINT lopnWidth,
+ U_COLORREF lopnColor
+ ){
+ U_LOGPEN lp;
+ lp.lopnStyle = lopnStyle;
+ lp.lopnWidth = lopnWidth;
+ lp.lopnColor = lopnColor;
+ return(lp);
+}
+
+/**
+ \brief Construct a U_LOGPLTNTRY structure.
+ \return U_LOGPLTNTRY structure
+ \param peReserved Ignore
+ \param peRed Palette entry Red Intensity
+ \param peGreen Palette entry Green Intensity
+ \param peBlue Palette entry Blue Intensity
+*/
+U_LOGPLTNTRY logpltntry_set(
+ uint8_t peReserved,
+ uint8_t peRed,
+ uint8_t peGreen,
+ uint8_t peBlue
+ ){
+ U_LOGPLTNTRY lpny;
+ lpny.peReserved = peReserved;
+ lpny.peRed = peRed;
+ lpny.peGreen = peGreen;
+ lpny.peBlue = peBlue;
+ return(lpny);
+}
+
+/**
+ \brief Allocate and construct a U_LOGPALETTE structure.
+ \return pointer to U_LOGPALETTE structure, or NULL on error.
+ \param palNumEntries Number of U_LOGPLTNTRY objects
+ \param palPalEntry array, PC_Entry Enumeration
+*/
+PU_LOGPALETTE logpalette_set(
+ U_NUM_LOGPLTNTRY palNumEntries,
+ PU_LOGPLTNTRY *palPalEntry
+ ){
+ PU_LOGPALETTE record;
+ int cbPalArray,irecsize;
+
+ if(palNumEntries == 0 || !palPalEntry)return(NULL);
+ cbPalArray = palNumEntries * sizeof(U_LOGPLTNTRY);
+ irecsize = sizeof(U_LOGPALETTE) + cbPalArray - sizeof(U_LOGPLTNTRY);
+ record = (PU_LOGPALETTE) malloc(irecsize);
+ if(irecsize){
+ record->palVersion = U_LP_VERSION;
+ record->palNumEntries = palNumEntries;
+ memcpy(record->palPalEntry,palPalEntry,cbPalArray);
+ }
+ return(record);
+}
+
+/**
+ \brief Construct a U_RGNDATAHEADER structure.
+ \return U_RGNDATAHEADER structure
+ \param nCount Number of rectangles in region
+ \param rclBounds Region bounds
+*/
+U_RGNDATAHEADER rgndataheader_set(
+ U_NUM_RECTL nCount,
+ U_RECTL rclBounds
+ ){
+ U_RGNDATAHEADER rdh;
+ rdh.dwSize = U_RDH_OBJSIZE;
+ rdh.iType = U_RDH_RECTANGLES;
+ rdh.nCount = nCount;
+ rdh.nRgnSize = nCount * sizeof(U_RECTL); // Size in bytes of rectangle array
+ rdh.rclBounds = rclBounds;
+ return(rdh);
+}
+
+/**
+ \brief Allocate and construct a U_RGNDATA structure.
+ \return pointer to U_RGNDATA structure, or NULL on error.
+ \param rdh Data description
+ \param Buffer Array of U_RECTL elements
+*/
+PU_RGNDATA rgndata_set(
+ U_RGNDATAHEADER rdh,
+ PU_RECTL Buffer
+ ){
+ char *record;
+ int irecsize;
+ int szRgnArray,off;
+
+ if(!Buffer || !rdh.nCount || !rdh.nRgnSize)return(NULL);
+ szRgnArray = rdh.nRgnSize; // size of the U_RECTL array
+ irecsize = sizeof(U_RGNDATA) + szRgnArray - sizeof(U_RECTL); // core + array - overlap
+ record = malloc(irecsize);
+ if(record){
+ memcpy(record, &rdh, sizeof(U_RGNDATAHEADER));
+ off = sizeof(U_RGNDATAHEADER);
+ memcpy(record + off, Buffer, szRgnArray);
+ }
+ return((PU_RGNDATA) record);
+}
+
+/**
+ \brief Construct a U_COLORADJUSTMENT structure.
+ \return U_COLORADJUSTMENT structure
+ \param Size Size of this structure in bytes
+ \param Flags ColorAdjustment Enumeration
+ \param IlluminantIndex Illuminant Enumeration
+ \param RedGamma Red Gamma correction (range:2500:65000, 10000 is no correction)
+ \param GreenGamma Green Gamma correction (range:2500:65000, 10000 is no correction)
+ \param BlueGamma Blue Gamma correction (range:2500:65000, 10000 is no correction)
+ \param ReferenceBlack Values less than this are black (range:0:4000)
+ \param ReferenceWhite Values more than this are white (range:6000:10000)
+ \param Contrast Contrast adjustment (range:-100:100, 0 is no correction)
+ \param Brightness Brightness adjustment (range:-100:100, 0 is no correction)
+ \param Colorfulness Colorfulness adjustment (range:-100:100, 0 is no correction)
+ \param RedGreenTint Tine adjustment (range:-100:100, 0 is no correction)
+*/
+U_COLORADJUSTMENT coloradjustment_set(
+ uint16_t Size,
+ uint16_t Flags,
+ uint16_t IlluminantIndex,
+ uint16_t RedGamma,
+ uint16_t GreenGamma,
+ uint16_t BlueGamma,
+ uint16_t ReferenceBlack,
+ uint16_t ReferenceWhite,
+ int16_t Contrast,
+ int16_t Brightness,
+ int16_t Colorfulness,
+ int16_t RedGreenTint
+ ){
+ U_COLORADJUSTMENT ca;
+ ca.caSize = Size;
+ ca.caFlags = Flags;
+ ca.caIlluminantIndex = IlluminantIndex;
+ ca.caRedGamma = U_MNMX(RedGamma, U_RGB_GAMMA_MIN, U_RGB_GAMMA_MAX);
+ ca.caGreenGamma = U_MNMX(GreenGamma, U_RGB_GAMMA_MIN, U_RGB_GAMMA_MAX);
+ ca.caBlueGamma = U_MNMX(BlueGamma, U_RGB_GAMMA_MIN, U_RGB_GAMMA_MAX);
+ // Next one is different to eliminate compiler warning - U_R_B_MIN is 0 and unsigned
+ ca.caReferenceBlack = U_MAX( ReferenceBlack, U_REFERENCE_BLACK_MAX);
+ ca.caReferenceWhite = U_MNMX(ReferenceWhite, U_REFERENCE_WHITE_MIN, U_REFERENCE_WHITE_MAX);
+ ca.caContrast = U_MNMX(Contrast, U_COLOR_ADJ_MIN, U_COLOR_ADJ_MAX);
+ ca.caBrightness = U_MNMX(Brightness, U_COLOR_ADJ_MIN, U_COLOR_ADJ_MAX);
+ ca.caColorfulness = U_MNMX(Colorfulness, U_COLOR_ADJ_MIN, U_COLOR_ADJ_MAX);
+ ca.caRedGreenTint = U_MNMX(RedGreenTint, U_COLOR_ADJ_MIN, U_COLOR_ADJ_MAX);
+ return(ca);
+}
+
+/**
+ \brief Construct a U_PIXELFORMATDESCRIPTOR structure.
+ \return U_PIXELFORMATDESCRIPTOR structure
+ \param dwFlags PFD_dwFlags Enumeration
+ \param iPixelType PFD_iPixelType Enumeration
+ \param cColorBits RGBA: total bits per pixel
+ \param cRedBits Red bits per pixel
+ \param cRedShift Red shift to data bits
+ \param cGreenBits Green bits per pixel
+ \param cGreenShift Green shift to data bits
+ \param cBlueBits Blue bits per pixel
+ \param cBlueShift Blue shift to data bits
+ \param cAlphaBits Alpha bits per pixel
+ \param cAlphaShift Alpha shift to data bits
+ \param cAccumBits Accumulator buffer, total bitplanes
+ \param cAccumRedBits Red accumulator buffer bitplanes
+ \param cAccumGreenBits Green accumulator buffer bitplanes
+ \param cAccumBlueBits Blue accumulator buffer bitplanes
+ \param cAccumAlphaBits Alpha accumulator buffer bitplanes
+ \param cDepthBits Depth of Z-buffer
+ \param cStencilBits Depth of stencil buffer
+ \param cAuxBuffers Depth of auxilliary buffers (not supported)
+ \param iLayerType PFD_iLayerType Enumeration, may be ignored
+ \param bReserved Bits 0:3/4:7 are number of Overlay/Underlay planes
+ \param dwLayerMask may be ignored
+ \param dwVisibleMask color or index of underlay plane
+ \param dwDamageMask may be ignored
+*/
+U_PIXELFORMATDESCRIPTOR pixelformatdescriptor_set(
+ uint32_t dwFlags,
+ uint8_t iPixelType,
+ uint8_t cColorBits,
+ uint8_t cRedBits,
+ uint8_t cRedShift,
+ uint8_t cGreenBits,
+ uint8_t cGreenShift,
+ uint8_t cBlueBits,
+ uint8_t cBlueShift,
+ uint8_t cAlphaBits,
+ uint8_t cAlphaShift,
+ uint8_t cAccumBits,
+ uint8_t cAccumRedBits,
+ uint8_t cAccumGreenBits,
+ uint8_t cAccumBlueBits,
+ uint8_t cAccumAlphaBits,
+ uint8_t cDepthBits,
+ uint8_t cStencilBits,
+ uint8_t cAuxBuffers,
+ uint8_t iLayerType,
+ uint8_t bReserved,
+ uint32_t dwLayerMask,
+ uint32_t dwVisibleMask,
+ uint32_t dwDamageMask
+ ){
+ U_PIXELFORMATDESCRIPTOR pfd;
+ pfd.nSize = sizeof(U_PIXELFORMATDESCRIPTOR);
+ pfd.nVersion = 1;
+ pfd.dwFlags = dwFlags;
+ pfd.iPixelType = iPixelType;
+ pfd.cColorBits = cColorBits;
+ pfd.cRedBits = cRedBits;
+ pfd.cRedShift = cRedShift;
+ pfd.cGreenBits = cGreenBits;
+ pfd.cGreenShift = cGreenShift;
+ pfd.cBlueBits = cBlueBits;
+ pfd.cBlueShift = cBlueShift;
+ pfd.cAlphaBits = cAlphaBits;
+ pfd.cAlphaShift = cAlphaShift;
+ pfd.cAccumBits = cAccumBits;
+ pfd.cAccumRedBits = cAccumRedBits;
+ pfd.cAccumGreenBits = cAccumGreenBits;
+ pfd.cAccumBlueBits = cAccumBlueBits;
+ pfd.cAccumAlphaBits = cAccumAlphaBits;
+ pfd.cDepthBits = cDepthBits;
+ pfd.cStencilBits = cStencilBits;
+ pfd.cAuxBuffers = cAuxBuffers;
+ pfd.iLayerType = iLayerType;
+ pfd.bReserved = bReserved;
+ pfd.dwLayerMask = dwLayerMask;
+ pfd.dwVisibleMask = dwVisibleMask;
+ pfd.dwDamageMask = dwDamageMask;
+ return(pfd);
+}
+
+/**
+ \brief Allocate and create a U_EMRTEXT structure followed by its variable pieces via a char* pointer.
+ Dx cannot be NULL, if the calling program has no appropriate values call dx_set() first.
+ \return char* pointer to U_EMRTEXT structure followed by its variable pieces, or NULL on error
+ \param ptlReference String start coordinates
+ \param NumString Number of characters in string, does NOT include a terminator
+ \param cbChar Number of bytes per character
+ \param String String to write
+ \param fOptions ExtTextOutOptions Enumeration
+ \param rcl (Optional, when fOptions & 7) grayed/clipping/opaque rectangle
+ \param Dx Character spacing array from the start of the RECORD
+*/
+char *emrtext_set(
+ U_POINTL ptlReference,
+ U_NUM_STR NumString,
+ uint32_t cbChar,
+ void *String,
+ uint32_t fOptions,
+ U_RECTL rcl,
+ uint32_t *Dx
+ ){
+ int irecsize,cbDxArray,cbString4,cbString,off;
+ char *record;
+ uint32_t *loffDx;
+
+ if(!String)return(NULL);
+ if(!Dx)return(NULL);
+ cbString = cbChar * NumString; // size of the string in bytes
+ cbString4 = UP4(cbString); // size of the string buffer
+ cbDxArray = sizeof(uint32_t)*NumString; // size of Dx array storage
+ if(fOptions & U_ETO_PDY)cbDxArray += cbDxArray; // of the Dx buffer, here do both X and Y coordinates
+ irecsize = sizeof(U_EMRTEXT) + sizeof(uint32_t) + cbString4 + cbDxArray; // core structure + offDx + string buf + dx buf
+ if(!(fOptions & U_ETO_NO_RECT)){ irecsize += sizeof(U_RECTL); } // plus variable U_RECTL, when it is present
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMRTEXT)record)->ptlReference = ptlReference;
+ ((PU_EMRTEXT)record)->nChars = NumString;
+ // pick up ((PU_EMRTEXT)record)->offString later
+ ((PU_EMRTEXT)record)->fOptions = fOptions;
+ off = sizeof(U_EMRTEXT); // location where variable pieces will start to be written
+ if(!(fOptions & U_ETO_NO_RECT)){ // variable field, may or may not be present
+ memcpy(record + off,&rcl, sizeof(U_RECTL));
+ off += sizeof(U_RECTL);
+ }
+ loffDx = (uint32_t *)(record + off); // offDx will go here, but we do not know with what value yet
+ off += sizeof(uint32_t);
+ memcpy(record + off,String,cbString); // copy the string data to its buffer
+ ((PU_EMRTEXT)record)->offString = off; // now save offset in the structure
+ off += cbString;
+ if(cbString < cbString4){
+ memset(record+off,0,cbString4-cbString); // keeps valgrind happy (initialize padding after string)
+ off += cbString4-cbString;
+ }
+ memcpy(record + off, Dx, cbDxArray); // copy the Dx data to its buffer
+ *loffDx = off; // now save offDx to the structure
+ }
+ return(record);
+}
+
+
+
+/* **********************************************************************************************
+These functions are simpler or more convenient ways to generate the specified types of EMR records.
+Each should be called in preference to the underlying "base" EMR function.
+*********************************************************************************************** */
+
+
+/**
+ \brief Allocate and construct a U_EMRCOMMENT structure with a UTF8 string.
+ A U_EMRCOMMENT contains application specific data, and that may include contain null characters. This function may be used when the
+ comment only incluces UT8 text.
+ \return pointer to U_EMRCOMMENT structure, or NULL on error.
+ \param string UTF8 string to store in the comment
+
+
+*/
+char *textcomment_set(
+ const char *string
+ ){
+ if(!string)return(NULL);
+ return(U_EMRCOMMENT_set(1 + strlen(string),string));
+}
+
+/**
+ \brief Allocate and construct a U_EMRDELETEOBJECT structure and also delete the requested object from the table.
+ Use this function instead of calling U_EMRDELETEOBJECT_set() directly.
+ \return pointer to U_EMRDELETEOBJECT structure, or NULL on error.
+ \param ihObject Pointer to handle to delete. This value is set to 0 if the function succeeds.
+ \param eht EMF handle table
+
+ Note that calling this function should always be conditional on the specifed object being defined. It is easy to
+ write a program where deleteobject_set() is called in a sequence where, at the time, we know that ihObject is defined.
+ Then a later modification, possibly quite far away in the code, causes it to be undefined. That distant change will
+ result in a failure when this function reutrns. That problem cannot be handled here because the only values which
+ may be returned are a valid U_EMRDELETEOBJECT record or a NULL, and other errors could result in the NULL.
+ So the object must be checked before the call.
+*/
+char *deleteobject_set(
+ uint32_t *ihObject,
+ EMFHANDLES *eht
+ ){
+ uint32_t saveObject=*ihObject;
+ if(emf_htable_delete(ihObject,eht))return(NULL); // invalid handle or other problem, cannot be deleted
+ return(U_EMRDELETEOBJECT_set(saveObject));
+}
+
+/**
+ \brief Allocate and construct a U_EMRSELECTOBJECT structure, checks that the handle specified is one that can actually be selected.
+ Use this function instead of calling U_EMRSELECTOBJECT_set() directly.
+ \return pointer to U_EMRSELECTOBJECT structure, or NULL on error.
+ \param ihObject handle to select
+ \param eht EMF handle table
+*/
+char *selectobject_set(
+ uint32_t ihObject,
+ EMFHANDLES *eht
+ ){
+ if(!(U_STOCK_OBJECT & ihObject)){ // not a stock object, those go straight through
+ if(ihObject > eht->top)return(NULL); // handle this high is not in the table
+ if(!eht->table[ihObject])return(NULL); // handle is not in the table, so not active, so cannot be selected
+ }
+ return(U_EMRSELECTOBJECT_set(ihObject));
+}
+
+/**
+ \brief Allocate and construct a U_EMREXTCREATEPEN structure, create a handle and return it.
+ Use this function instead of calling U_EMREXTCREATEPEN_set() directly.
+ \return pointer to U_EMREXTCREATEPEN structure, or NULL on error.
+ \param ihPen handle to be used by new object
+ \param eht EMF handle table
+ \param Bmi bitmapbuffer
+ \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
+ \param Px pixel array (NULL if cbPx == 0)
+ \param elp Pen parameters (Size is Variable!!!!)
+*/
+char *extcreatepen_set(
+ uint32_t *ihPen,
+ EMFHANDLES *eht,
+ PU_BITMAPINFO Bmi,
+ const uint32_t cbPx,
+ char *Px,
+ PU_EXTLOGPEN elp
+ ){
+ if(emf_htable_insert(ihPen, eht))return(NULL);
+ return(U_EMREXTCREATEPEN_set(*ihPen, Bmi, cbPx, Px, elp ));
+}
+
+/**
+ \brief Allocate and construct a U_EMRCREATEPEN structure, create a handle and returns it
+ Use this function instead of calling U_EMRCREATEPEN_set() directly.
+ \return pointer to U_EMRCREATEPEN structure, or NULL on error.
+ \param ihPen handle to be used by new object
+ \param eht EMF handle table
+ \param lopn Pen parameters
+*/
+char *createpen_set(
+ uint32_t *ihPen,
+ EMFHANDLES *eht,
+ U_LOGPEN lopn
+ ){
+ if(emf_htable_insert(ihPen, eht))return(NULL);
+ return(U_EMRCREATEPEN_set(*ihPen, lopn));
+}
+
+/**
+ \brief Allocate and construct a U_EMRCREATEBRUSHINDIRECT structure, create a handle and returns it
+ Use this function instead of calling U_EMRCREATEBRUSHINDIRECT_set() directly.
+ \return pointer to U_EMRCREATEBRUSHINDIRECT structure, or NULL on error.
+ \param ihBrush handle to be used by new object
+ \param eht EMF handle table
+ \param lb Brush parameters
+*/
+char *createbrushindirect_set(
+ uint32_t *ihBrush,
+ EMFHANDLES *eht,
+ U_LOGBRUSH lb
+ ){
+ if(emf_htable_insert(ihBrush, eht))return(NULL);
+ return(U_EMRCREATEBRUSHINDIRECT_set(*ihBrush, lb));
+}
+
+/**
+ \brief Allocate and construct a U_EMRCREATEDIBPATTERNBRUSHPT_set structure, create a handle and returns it
+ Use this function instead of calling U_EMRCREATEDIBPATTERNBRUSHPT_set() directly.
+ \return pointer to U_EMRCREATEDIBPATTERNBRUSHPT_set structure, or NULL on error.
+ \param ihBrush handle to be used by new object
+ \param eht EMF handle table
+ \param iUsage DIBColors enumeration
+ \param Bmi Bitmap info
+ \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
+ \param Px (Optional) bitmapbuffer (pixel array section )
+*/
+char *createdibpatternbrushpt_set(
+ uint32_t *ihBrush,
+ EMFHANDLES *eht,
+ const uint32_t iUsage,
+ PU_BITMAPINFO Bmi,
+ const uint32_t cbPx,
+ const char *Px
+
+ ){
+ if(emf_htable_insert(ihBrush, eht))return(NULL);
+ return(U_EMRCREATEDIBPATTERNBRUSHPT_set(*ihBrush, iUsage, Bmi, cbPx, Px));
+}
+
+/**
+ \brief Allocate and construct a U_EMRCREATEMONOBRUSH_set structure, create a handle and returns it
+ Use this function instead of calling U_EMRCREATEMONOBRUSH_set() directly.
+ \return pointer to U_EMRCREATEMONOBRUSH_set structure, or NULL on error.
+ \param ihBrush handle to be used by new object
+ \param eht EMF handle table
+ \param iUsage DIBColors enumeration
+ \param Bmi Bitmap info
+ \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
+ \param Px (Optional) bitmapbuffer (pixel array section )
+*/
+char *createmonobrush_set(
+ uint32_t *ihBrush,
+ EMFHANDLES *eht,
+ const uint32_t iUsage,
+ PU_BITMAPINFO Bmi,
+ const uint32_t cbPx,
+ const char *Px
+
+ ){
+ if(emf_htable_insert(ihBrush, eht))return(NULL);
+ return(U_EMRCREATEMONOBRUSH_set(*ihBrush, iUsage, Bmi, cbPx, Px));
+}
+
+
+/**
+ \brief Allocate and construct a U_EMRCREATECOLORSPACE structure, create a handle and returns it
+ Use this function instead of calling U_EMRCREATECOLORSPACE_set() directly.
+ \return pointer to U_EMRCREATECOLORSPACE structure, or NULL on error.
+ \param ihCS ColorSpace handle, will be created and returned
+ \param eht Pointer to structure holding all EMF handles
+ \param lcs ColorSpace parameters
+*/
+char *createcolorspace_set(
+ uint32_t *ihCS,
+ EMFHANDLES *eht,
+ U_LOGCOLORSPACEA lcs
+ ){
+ if(emf_htable_insert(ihCS, eht))return(NULL);
+ return(U_EMRCREATECOLORSPACE_set(*ihCS,lcs));
+}
+
+/**
+ \brief Allocate and construct a U_EMRCREATECOLORSPACEW structure, create a handle and returns it
+ Use this function instead of calling U_EMRCREATECOLORSPACEW_set() directly.
+ \return pointer to U_EMRCREATECOLORSPACEW structure, or NULL on error.
+ \param ihCS ColorSpace handle, will be created and returned
+ \param eht Pointer to structure holding all EMF handles
+ \param lcs ColorSpace parameters
+ \param dwFlags If low bit set Data is present
+ \param cbData Number of bytes of theData field.
+ \param Data (Optional, dwFlags & 1) color profile data
+*/
+char *createcolorspacew_set(
+ uint32_t *ihCS,
+ EMFHANDLES *eht,
+ U_LOGCOLORSPACEW lcs,
+ uint32_t dwFlags,
+ U_CBDATA cbData,
+ uint8_t *Data
+ ){
+ if(emf_htable_insert(ihCS, eht))return(NULL);
+ return(U_EMRCREATECOLORSPACEW_set(*ihCS, lcs, dwFlags, cbData, Data));
+}
+
+/**
+ \brief Allocate and construct a U_EMREXTCREATEFONTINDIRECTW structure, create a handle and returns it
+ Use this function instead of calling U_EMREXTCREATEFONTINDIRECTW_set() directly.
+ \return pointer to U_EMREXTCREATEFONTINDIRECTW structure, or NULL on error.
+ \param ihFont Font handle, will be created and returned
+ \param eht Pointer to structure holding all EMF handles
+ \param elf Pointer to Font parameters asPU_LOGFONT
+ \param elfw Pointer to Font parameters as U_LOGFONT_PANOSE
+*/
+char *extcreatefontindirectw_set(
+ uint32_t *ihFont,
+ EMFHANDLES *eht,
+ const char *elf,
+ const char *elfw
+ ){
+ if(emf_htable_insert(ihFont, eht))return(NULL);
+ return(U_EMREXTCREATEFONTINDIRECTW_set(*ihFont, elf, elfw));
+}
+
+/**
+ \brief Allocate and construct a U_EMRCREATEPALETTE structure, create a handle and returns it
+ Use this function instead of calling U_EMRCREATEPALETTE_set() directly.
+ \return pointer to U_EMRCREATEPALETTE structure, or NULL on error.
+ \param ihPal Palette handle, will be created and returned
+ \param eht Pointer to structure holding all EMF handles
+ \param lgpl PaletteFont parameters
+*/
+char *createpalette_set(
+ uint32_t *ihPal,
+ EMFHANDLES *eht,
+ U_LOGPALETTE lgpl
+ ){
+ if(emf_htable_insert(ihPal, eht))return(NULL);
+ return(U_EMRCREATEPALETTE_set(*ihPal, lgpl));
+}
+
+/**
+ \brief Allocate and construct a U_EMRSETPALETTEENTRIES structure, create a handle and returns it
+ Use this function instead of calling U_EMRSETPALETTEENTRIES_set() directly.
+ \return pointer to U_EMRSETPALETTEENTRIES structure, or NULL on error.
+ \param ihPal Palette handle, will be created and returned
+ \param eht Pointer to structure holding all EMF handles
+ \param iStart First Palette entry in selected object to set
+ \param cEntries Number of Palette entries in selected object to set
+ \param aPalEntries Values to set with
+*/
+char *setpaletteentries_set(
+ uint32_t *ihPal,
+ EMFHANDLES *eht,
+ const uint32_t iStart,
+ const U_NUM_LOGPLTNTRY cEntries,
+ const PU_LOGPLTNTRY aPalEntries
+ ){
+ if(emf_htable_insert(ihPal, eht))return(NULL);
+ return(U_EMRSETPALETTEENTRIES_set(*ihPal, iStart, cEntries, aPalEntries));
+}
+
+/**
+ \brief Allocate and construct a U_EMRFILLRGN structure, create a handle and returns it
+ Use this function instead of calling U_EMRFILLRGN_set() directly.
+ \return pointer to U_EMRFILLRGN structure, or NULL on error.
+ \param ihBrush Brush handle, will be created and returned
+ \param eht Pointer to structure holding all EMF handles
+ \param rclBounds Bounding rectangle in device units
+ \param RgnData Pointer to a U_RGNDATA structure
+*/
+char *fillrgn_set(
+ uint32_t *ihBrush,
+ EMFHANDLES *eht,
+ const U_RECTL rclBounds,
+ const PU_RGNDATA RgnData
+ ){
+ if(emf_htable_insert(ihBrush, eht))return(NULL);
+ return(U_EMRFILLRGN_set(rclBounds, *ihBrush, RgnData));
+}
+
+/**
+ \brief Allocate and construct a U_EMRFRAMERGN structure, create a handle and returns it
+ Use this function instead of calling U_EMRFRAMERGN_set() directly.
+ \return pointer to U_EMRFRAMERGN structure, or NULL on error.
+ \param ihBrush Brush handle, will be created and returned
+ \param eht Pointer to structure holding all EMF handles
+ \param rclBounds Bounding rectangle in device units
+ \param szlStroke W & H of Brush stroke
+ \param RgnData Pointer to a U_RGNDATA structure
+*/
+char *framergn_set(
+ uint32_t *ihBrush,
+ EMFHANDLES *eht,
+ const U_RECTL rclBounds,
+ const U_SIZEL szlStroke,
+ const PU_RGNDATA RgnData
+ ){
+ if(emf_htable_insert(ihBrush, eht))return(NULL);
+ return(U_EMRFRAMERGN_set(rclBounds, *ihBrush, szlStroke, RgnData));
+}
+
+/**
+ \brief Allocate and construct an array of U_POINT objects which has been subjected to a U_XFORM
+ \returns pointer to an array of U_POINT structures.
+ \param points pointer to the source U_POINT structures
+ \param count number of members in points
+ \param xform U_XFORM to apply
+
+ May also be used to modify U_RECT by doubling the count and casting the pointer.
+*/
+PU_POINT points_transform(PU_POINT points, int count, U_XFORM xform){
+ PU_POINT newpts;
+ int i;
+ float x,y;
+ newpts = (PU_POINT) malloc(count * sizeof(U_POINT));
+ for(i=0; i<count; i++){
+ x = (float) points[i].x;
+ y = (float) points[i].y;
+ newpts[i].x = U_ROUND(x * xform.eM11 + y * xform.eM21 + xform.eDx);
+ newpts[i].y = U_ROUND(x * xform.eM12 + y * xform.eM22 + xform.eDy);
+ }
+ return(newpts);
+}
+
+/**
+ \brief Allocate and construct an array of U_POINT16 objects which has been subjected to a U_XFORM
+ \returns pointer to an array of U_POINT16 structures.
+ \param points pointer to the source U_POINT16 structures
+ \param count number of members in points
+ \param xform U_XFORM to apply
+
+ Transformed src points {x0,y0} appear at {x0*xscale + x, y0*yscale + y}
+*/
+PU_POINT16 point16_transform(PU_POINT16 points, int count, U_XFORM xform){
+ PU_POINT16 newpts;
+ int i;
+ float x,y;
+ newpts = (PU_POINT16) malloc(count * sizeof(U_POINT16));
+ for(i=0; i<count; i++){
+ x = (float) points[i].x;
+ y = (float) points[i].y;
+ newpts[i].x = U_ROUND(x * xform.eM11 + y * xform.eM21 + xform.eDx);
+ newpts[i].y = U_ROUND(x * xform.eM12 + y * xform.eM22 + xform.eDy);
+ }
+ return(newpts);
+}
+
+/**
+ \brief Allocate and construct an array of U_TRIVERTEX objects which has been subjected to a U_XFORM
+ \returns pointer to an array of U_TRIVERTEX structures.
+ \param tv pointer to the source U_TRIVERTEX structures
+ \param count number of members in points
+ \param xform U_XFORM to apply
+
+ Transformed Trivertex points {x0,y0} appear at {x0*xscale + x, y0*yscale + y}
+*/
+PU_TRIVERTEX trivertex_transform(PU_TRIVERTEX tv, int count, U_XFORM xform){
+ PU_TRIVERTEX newtvs;
+ int i;
+ float x,y;
+ newtvs = (PU_TRIVERTEX) malloc(count * sizeof(U_TRIVERTEX));
+ for(i=0; i<count; i++){
+ x = (float) tv[i].x;
+ y = (float) tv[i].y;
+ newtvs[i] = tv[i];
+ newtvs[i].x = U_ROUND(x * xform.eM11 + y * xform.eM21 + xform.eDx);
+ newtvs[i].y = U_ROUND(x * xform.eM12 + y * xform.eM22 + xform.eDy);
+ }
+ return(newtvs);
+}
+
+/**
+ \brief Allocate and construct an array of U_POINT objects from a set of U_POINT16 objects
+ \returns pointer to an array of U_POINT structures.
+ \param points pointer to the source U_POINT16 structures
+ \param count number of members in points
+
+*/
+PU_POINT point16_to_point(PU_POINT16 points, int count){
+ PU_POINT newpts;
+ int i;
+ newpts = (PU_POINT) malloc(count * sizeof(U_POINT));
+ for(i=0; i<count; i++){
+ newpts[i].x = points[i].x;
+ newpts[i].y = points[i].y;
+ }
+ return(newpts);
+}
+
+/**
+ \brief Allocate and construct an array of U_POINT16 objects from a set of U_POINT objects
+ \returns pointer to an array of U_POINT16 structures.
+ \param points pointer to the source U_POINT structures
+ \param count number of members in points
+
+ If a coordinate is out of range it saturates at boundary.
+*/
+PU_POINT16 point_to_point16(PU_POINT points, int count){
+ PU_POINT16 newpts;
+ int i;
+ newpts = (PU_POINT16) malloc(count * sizeof(U_POINT16));
+ for(i=0; i<count; i++){
+ newpts[i].x = U_MNMX(points[i].x, INT16_MIN, INT16_MAX);
+ newpts[i].y = U_MNMX(points[i].y, INT16_MIN, INT16_MAX);
+ }
+ return(newpts);
+}
+
+// hide these from Doxygen
+//! @cond
+/* **********************************************************************************************
+These functions contain shared code used by various U_EMR*_set functions. These should NEVER be called
+by end user code and to further that end prototypes are NOT provided and they are hidden from Doxygen.
+
+
+ These are (mostly) ordered by U_EMR_* index number.
+ For all _set functions the caller must eventually call free() on the returned pointer.
+
+ CORE1(uint32_t iType, U_RECTL rclBounds, const uint32_t cptl, const U_POINTL *points){
+ CORE2(uint32_t iType, U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,const uint32_t cptl, const U_POINTL *points){
+ CORE3(uint32_t iType, uint32_t iMode){ (generic 1 uint)
+ CORE4(uint32_t iType, U_RECTL rclBox){
+ CORE5(uint32_t iType){ (generic noargs)
+ CORE6(uint32_t iType, U_RECTL rclBounds, const uint32_t cpts, const U_POINT16 *points){ (16bit form of CORE1)
+ CORE7(uint32_t iType, U_PAIR pair){
+ CORE8(uint32_t iType, U_RECTL rclBounds, uint32_t iGraphicsMode, U_FLOAT exScale, U_FLOAT eyScale, PU_EMRTEXT emrtext){
+ CORE9(uint32_t iType, U_RECTL rclBox, U_POINTL ptlStart, U_POINTL ptlEnd){
+ CORE10(uint32_t iType, U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,const uint32_t cpts, const U_POINT16 *points){ (16bit form of CORE2)
+ CORE11(uint32_t iType, PU_RGNDATA RgnData){
+ CORE12(uint32_t iType, uint32_t ihBrush, uint32_t iUsage, PU_BITMAPINFO Bmi){
+ CORE13(uint32_t iType, U_RECTL rclBounds, U_POINTL Dest, U_POINTL cDest,
+ U_POINTL Src, U_POINTL cSrc, U_XFORM xformSrc, U_COLORREF crBkColorSrc, uint32_t iUsageSrc,
+ uint32_t Data, PU_BITMAPINFO Bmi);
+*********************************************************************************************** */
+
+
+// Functions with the same form starting with U_EMRPOLYBEZIER_set
+char *U_EMR_CORE1_set(uint32_t iType, U_RECTL rclBounds, const uint32_t cptl, const U_POINTL *points){
+ char *record;
+ int cbPoints;
+ int irecsize;
+
+ cbPoints = sizeof(U_POINTL)*cptl;
+ irecsize = sizeof(U_EMRPOLYBEZIER) + cbPoints - sizeof(U_POINTL); // First instance is in struct
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = iType;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRPOLYBEZIER) record)->rclBounds = rclBounds;
+ ((PU_EMRPOLYBEZIER) record)->cptl = cptl;
+ memcpy(((PU_EMRPOLYBEZIER) record)->aptl,points,cbPoints);
+ }
+ return(record);
+}
+
+// Functions with the same form starting with U_EMR_POLYPOLYLINE
+char *U_EMR_CORE2_set(uint32_t iType, U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,const uint32_t cptl, const U_POINTL *points){
+ char *record;
+ int cbPolys,cbPoints,off;
+ int irecsize;
+
+ cbPoints = sizeof(U_POINTL)*cptl;
+ cbPolys = sizeof(uint32_t)*nPolys;
+ irecsize = sizeof(U_EMRPOLYPOLYLINE) + cbPoints + cbPolys - sizeof(uint32_t); // First instance of each is in struct
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = iType;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRPOLYPOLYLINE) record)->rclBounds = rclBounds;
+ ((PU_EMRPOLYPOLYLINE) record)->nPolys = nPolys;
+ ((PU_EMRPOLYPOLYLINE) record)->cptl = cptl;
+ memcpy(((PU_EMRPOLYPOLYLINE) record)->aPolyCounts,aPolyCounts,cbPolys);
+ off = sizeof(U_EMRPOLYPOLYLINE) - 4 + cbPolys;
+ memcpy(record + off,points,cbPoints);
+ }
+ return(record);
+}
+
+// Functions with the same form starting with U_EMR_SETMAPMODE_set
+char *U_EMR_CORE3_set(uint32_t iType, uint32_t iMode){
+ char *record;
+ int irecsize;
+
+ irecsize = sizeof(U_EMRSETMAPMODE);
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = iType;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRSETMAPMODE)record)->iMode = iMode;
+ }
+ return(record);
+}
+
+// Functions taking a single U_RECT or U_RECTL, starting with U_EMRELLIPSE_set, also U_EMRFILLPATH,
+char *U_EMR_CORE4_set(uint32_t iType, U_RECTL rclBox){
+ char *record;
+ int irecsize;
+
+ irecsize = sizeof(U_EMRELLIPSE);
+ record = malloc(irecsize);
+ memset(record,0,irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = iType;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRELLIPSE)record)->rclBox = rclBox; // bounding rectangle in logical units
+ }
+ return(record);
+}
+
+// Functions with the same form starting with U_EMRSETMETARGN_set
+char *U_EMR_CORE5_set(uint32_t iType){
+ char *record;
+ int irecsize = 8;
+
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = iType;
+ ((PU_EMR) record)->nSize = irecsize;
+ }
+ return(record);
+}
+
+// Functions with the same form starting with U_EMRPOLYBEZIER16_set
+char *U_EMR_CORE6_set(uint32_t iType, U_RECTL rclBounds, const uint32_t cpts, const U_POINT16 *points){
+ char *record;
+ int cbPoints,cbPoints4,off;
+ int irecsize;
+
+ cbPoints = sizeof(U_POINT16)*cpts;
+ cbPoints4 = UP4(cbPoints);
+ off = sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_NUM_POINT16); // offset to the start of the variable region
+ irecsize = off + cbPoints4; // First instance is in struct
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = iType;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRPOLYBEZIER16) record)->rclBounds = rclBounds;
+ ((PU_EMRPOLYBEZIER16) record)->cpts = cpts;
+ memcpy(record + off, points, cbPoints);
+ if(cbPoints < cbPoints4){
+ off += cbPoints;
+ memset(record + off, 0, cbPoints4 - cbPoints);
+ }
+ }
+ return(record);
+}
+
+
+// Functions that take a single struct argument which contains two uint32_t, starting with U_EMRSETWINDOWEXTEX_set
+// these all pass two 32 bit ints and are cast by the caller to U_PAIR
+char *U_EMR_CORE7_set(uint32_t iType, U_PAIR pair){
+ char *record;
+ int irecsize = sizeof(U_EMRGENERICPAIR);
+
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = iType;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRGENERICPAIR)record)->pair = pair;
+ }
+ return(record);
+}
+
+// For U_EMREXTTEXTOUTA and U_EMREXTTEXTOUTW
+char *U_EMR_CORE8_set(
+ uint32_t iType,
+ U_RECTL rclBounds, // Bounding rectangle in device units
+ uint32_t iGraphicsMode, // Graphics mode Enumeration
+ U_FLOAT exScale, // scale to 0.01 mm units ( only if iGraphicsMode & GM_COMPATIBLE)
+ U_FLOAT eyScale, // scale to 0.01 mm units ( only if iGraphicsMode & GM_COMPATIBLE)
+ PU_EMRTEXT emrtext // Text parameters
+ ){
+ char *record;
+ int irecsize,cbString,cbString4,cbDx,cbEmrtext,cbEmrtextAll;
+ uint32_t *loffDx;
+ int csize;
+
+ if( iType == U_EMR_EXTTEXTOUTA){ csize = 1; } // how many bytes per character
+ else if(iType == U_EMR_EXTTEXTOUTW){ csize = 2; }
+ else { return(NULL); }
+
+ cbString = csize * emrtext->nChars;
+ cbString4 = UP4(cbString); // size of the string buffer
+ cbEmrtext = sizeof(U_EMRTEXT); // size of the constant part of the U_EMRTEXT structure
+ if(!(emrtext->fOptions & U_ETO_NO_RECT)){ cbEmrtext += sizeof(U_RECTL); } // plus the variable U_RECTL, when it is present
+ cbDx = emrtext->nChars * sizeof(int32_t); // size of Dx buffer
+ if(emrtext->fOptions & U_ETO_PDY)cbDx += cbDx; // size of Dx buffer when both x and y offsets are used
+ cbEmrtextAll = cbEmrtext + sizeof(uint32_t) + cbString4 + cbDx; // structure (+- rect) + offDx + string buf + dx buf + offDx
+
+ /* adjust offset fields in emrtext to match the EMRTEXTOUT* field, currently they match EMRTEXT.
+ This works because the variable pieces have all been moved outside of the U_EMRTEXT and U_EMRTEXTOUTA strutures.
+ */
+ ((PU_EMRTEXT)emrtext)->offString += sizeof(U_EMREXTTEXTOUTA) - sizeof(U_EMRTEXT); // adjust offString
+ loffDx = (uint32_t *)((char *)emrtext + cbEmrtext);
+ *loffDx += sizeof(U_EMREXTTEXTOUTA) - sizeof(U_EMRTEXT);
+
+ // final record size is: U_EMREXTTEXTOUTA (includes constant part of U_EMRTEXT) + U_RECTL (if present) + offDx + dx buffer + string buffer
+ irecsize = sizeof(U_EMREXTTEXTOUTA) + cbEmrtextAll - sizeof(U_EMRTEXT); // do not count core emrtext strcture twice
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = iType;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMREXTTEXTOUTA) record)->iGraphicsMode = iGraphicsMode;
+ ((PU_EMREXTTEXTOUTA) record)->rclBounds = rclBounds;
+ ((PU_EMREXTTEXTOUTA) record)->exScale = exScale;
+ ((PU_EMREXTTEXTOUTA) record)->eyScale = eyScale;
+ // copy the adjusted U_EMRTEXT into the emrtext part of the full record..
+ memcpy(&(((PU_EMREXTTEXTOUTA) record)->emrtext), emrtext, cbEmrtextAll);
+ }
+ return(record);
+}
+
+// Functions that take a rect and a pair of points, starting with U_EMRARC_set
+char *U_EMR_CORE9_set(uint32_t iType, U_RECTL rclBox, U_POINTL ptlStart, U_POINTL ptlEnd){
+ char *record;
+ int irecsize = sizeof(U_EMRARC);
+
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = iType;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRARC) record)->rclBox = rclBox;
+ ((PU_EMRARC) record)->ptlStart = ptlStart;
+ ((PU_EMRARC) record)->ptlEnd = ptlEnd;
+ }
+ return(record);
+}
+
+// Functions with the same form starting with U_EMR_POLYPOLYLINE16
+char *U_EMR_CORE10_set(uint32_t iType, U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,const uint32_t cpts, const U_POINT16 *points){
+ char *record;
+ int cbPoints,cbPolys,off;
+ int irecsize;
+
+ cbPolys = sizeof(uint32_t)*nPolys;
+ cbPoints = sizeof(U_POINT16)*cpts;
+ irecsize = sizeof(U_EMRPOLYPOLYLINE16) + cbPoints + cbPolys - sizeof(uint32_t); // First instance of each is in struct
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = iType;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRPOLYPOLYLINE16) record)->rclBounds = rclBounds;
+ ((PU_EMRPOLYPOLYLINE16) record)->nPolys = nPolys;
+ ((PU_EMRPOLYPOLYLINE16) record)->cpts = cpts;
+ memcpy(((PU_EMRPOLYPOLYLINE16) record)->aPolyCounts,aPolyCounts,cbPolys);
+ off = sizeof(U_EMRPOLYPOLYLINE16) - 4 + cbPolys;
+ memcpy(record + off,points,cbPoints);
+ }
+ return(record);
+}
+
+// common code for U_EMRINVERTRGN and U_EMRPAINTRGN,
+char *U_EMR_CORE11_set(uint32_t iType, PU_RGNDATA RgnData){
+ char *record;
+ int irecsize;
+ int cbRgns,cbRgns4,rds,rds4,off;
+
+ if(!RgnData)return(NULL);
+ cbRgns = ((PU_RGNDATAHEADER) RgnData)->nRgnSize;
+ cbRgns4 = UP4(cbRgns);
+ rds = sizeof(U_RGNDATAHEADER) + cbRgns;
+ rds4 = UP4(rds);
+ irecsize = sizeof(U_EMRINVERTRGN) - sizeof(U_RECTL) + cbRgns4; // core + array - overlap of one rectL
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = iType;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRINVERTRGN) record)->rclBounds = ((PU_RGNDATAHEADER) RgnData)->rclBounds;
+ ((PU_EMRINVERTRGN) record)->cbRgnData = rds;
+ off = sizeof(U_EMRINVERTRGN) - sizeof(U_RGNDATA);
+ memcpy(record + off, RgnData, rds);
+ off += rds;
+ if(rds < rds4){ memset(record + off,0, rds4 - rds); } // clear any unused bytes
+ }
+ return(record);
+}
+
+
+// common code for U_EMRCREATEMONOBRUSH_set and U_EMRCREATEDIBPATTERNBRUSHPT_set,
+char *U_EMR_CORE12_set(
+ uint32_t iType,
+ uint32_t ihBrush, // Index to place object in EMF object table (this entry must not yet exist)
+ uint32_t iUsage, // DIBcolors Enumeration
+ PU_BITMAPINFO Bmi, // (Optional) bitmapbuffer (U_BITMAPINFO + pixel array)
+ const uint32_t cbPx, // Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
+ const char *Px // (Optional) bitmapbuffer (pixel array section )
+ ){
+ char *record;
+ int irecsize;
+ int cbImage,cbImage4,cbBmi,off;
+
+ SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
+
+ irecsize = sizeof(U_EMRCREATEMONOBRUSH) + cbBmi + cbImage4;
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = iType;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRCREATEMONOBRUSH) record)->ihBrush = ihBrush;
+ ((PU_EMRCREATEMONOBRUSH) record)->iUsage = iUsage;
+ if(cbBmi){
+ off = sizeof(U_EMRCREATEMONOBRUSH);
+ memcpy(record + off, Bmi, cbBmi);
+ ((PU_EMRCREATEMONOBRUSH) record)->offBmi = off;
+ ((PU_EMRCREATEMONOBRUSH) record)->cbBmi = cbBmi;
+ off += cbBmi;
+ memcpy(record + off, Px, cbPx);
+ ((PU_EMRCREATEMONOBRUSH) record)->offBits = off;
+ ((PU_EMRCREATEMONOBRUSH) record)->cbBits = cbImage;
+ }
+ else {
+ ((PU_EMRCREATEMONOBRUSH) record)->offBmi = 0;
+ ((PU_EMRCREATEMONOBRUSH) record)->cbBmi = 0;
+ ((PU_EMRCREATEMONOBRUSH) record)->offBits = 0;
+ ((PU_EMRCREATEMONOBRUSH) record)->cbBits = 0;
+ }
+ }
+ return(record);
+}
+
+// common code for U_EMRBLEND_set and U_EMRTRANSPARENTBLT_set,
+char *U_EMR_CORE13_set(
+ uint32_t iType,
+ U_RECTL rclBounds, // Bounding rectangle in device units
+ U_POINTL Dest, // Destination UL corner in logical units
+ U_POINTL cDest, // Destination width in logical units
+ U_POINTL Src, // Source UL corner in logical units
+ U_POINTL cSrc, // Src W & H in logical units
+ U_XFORM xformSrc, // Transform to apply to source
+ U_COLORREF crBkColorSrc, // Background color
+ uint32_t iUsageSrc, // DIBcolors Enumeration
+ uint32_t Data, // The meaning and type of this field varies, but it is always 4 bytes
+ const PU_BITMAPINFO Bmi, // (Optional) bitmapbuffer (U_BITMAPINFO section)
+ const uint32_t cbPx, // Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
+ char *Px // (Optional) bitmapbuffer (pixel array section )
+ ){
+ char *record;
+ int irecsize;
+ int cbImage,cbImage4,cbBmi,off;
+
+ SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
+
+ irecsize = sizeof(U_EMRALPHABLEND) + cbBmi + cbImage4;
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = iType;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRALPHABLEND) record)->rclBounds = rclBounds;
+ ((PU_EMRALPHABLEND) record)->Dest = Dest;
+ ((PU_EMRALPHABLEND) record)->cDest = cDest;
+ ((PU_EMRALPHABLEND) record)->Blend = *((PU_BLEND)&Data);
+ ((PU_EMRALPHABLEND) record)->Src = Src;
+ ((PU_EMRALPHABLEND) record)->xformSrc = xformSrc;
+ ((PU_EMRALPHABLEND) record)->crBkColorSrc = crBkColorSrc;
+ ((PU_EMRALPHABLEND) record)->iUsageSrc = iUsageSrc;
+ off = sizeof(U_EMRALPHABLEND);
+ APPEND_PXBMISRC(record, U_EMRALPHABLEND, cbBmi, Bmi, Px, cbImage, cbImage4);
+ ((PU_EMRALPHABLEND) record)->cSrc = cSrc;
+ }
+ return(record);
+}
+//! @endcond
+
+/* **********************************************************************************************
+These are the core EMR functions, each creates a particular type of record.
+All return these records via a char* pointer, which is NULL if the call failed.
+They are listed in order by the corresponding U_EMR_* index number.
+*********************************************************************************************** */
+
+// U_EMRHEADER_set 1
+
+/**
+ \brief Allocate and construct a U_EMRHEADER record.
+ \return pointer to U_EMRHEADER record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param rclFrame Bounding rectangle in 0.01 mm units
+ \param pfmtDesc Pointer to a PixelFormatDescriptor
+ \param nDesc number of characters in Description, will include first three '\0'
+ \param Description Description, formatted like: text1\0text2\0\0
+ \param szlDevice Reference device size in pixels
+ \param szlMillimeters Reference device size in 0.01 mm
+ \param bOpenGL nonZero if OpenGL commands are included
+*/
+char *U_EMRHEADER_set(
+ const U_RECTL rclBounds,
+ const U_RECTL rclFrame,
+ U_PIXELFORMATDESCRIPTOR* const pfmtDesc,
+ U_CBSTR nDesc,
+ uint16_t* const Description,
+ const U_SIZEL szlDevice,
+ const U_SIZEL szlMillimeters,
+ const uint32_t bOpenGL
+ ){
+
+ char *record;
+ int cbPFD,cbDesc,cbDesc4;
+ uint32_t off;
+ int irecsize;
+
+ if(pfmtDesc){ cbPFD = sizeof(U_PIXELFORMATDESCRIPTOR); }
+ else { cbPFD = 0; }
+ if(Description){ cbDesc = 2*nDesc; } // also copy the terminator. Size is in bytes
+ else { cbDesc = 0; }
+ cbDesc4 = UP4(cbDesc);
+ irecsize = sizeof(U_EMRHEADER) + cbPFD + cbDesc4;
+ record = malloc(irecsize);
+ if(record){
+ off = sizeof(U_EMRHEADER);
+ ((PU_EMR) record)->iType = U_EMR_HEADER;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRHEADER) record)->rclBounds = rclBounds;
+ ((PU_EMRHEADER) record)->rclFrame = rclFrame;
+ ((PU_EMRHEADER) record)->dSignature = U_ENHMETA_SIGNATURE;
+ ((PU_EMRHEADER) record)->nVersion = U_ENHMETA_VERSION;
+ ((PU_EMRHEADER) record)->nBytes = 0; // Not known yet
+ ((PU_EMRHEADER) record)->nRecords = 0; // Not known yet
+ ((PU_EMRHEADER) record)->nHandles = 0; // Not known yet
+ ((PU_EMRHEADER) record)->sReserved = 0; // Must be 0
+ ((PU_EMRHEADER) record)->nDescription = nDesc;
+ ((PU_EMRHEADER) record)->offDescription = 0; // may change below
+ ((PU_EMRHEADER) record)->nPalEntries = 0; // Not known yet
+ ((PU_EMRHEADER) record)->szlDevice = szlDevice;
+ ((PU_EMRHEADER) record)->szlMillimeters = szlMillimeters;
+ ((PU_EMRHEADER) record)->cbPixelFormat = cbPFD;
+ ((PU_EMRHEADER) record)->offPixelFormat = 0; // may change below
+ ((PU_EMRHEADER) record)->bOpenGL = bOpenGL;
+ ((PU_EMRHEADER) record)->szlMicrometers.cx = szlMillimeters.cx*1000;
+ ((PU_EMRHEADER) record)->szlMicrometers.cy = szlMillimeters.cy*1000;
+ if(cbDesc4){
+ ((PU_EMRHEADER) record)->offDescription = off;
+ memcpy(record + off, Description, cbDesc);
+ off += cbDesc;
+ if(cbDesc < cbDesc4)memset(record + off,0,cbDesc4-cbDesc); // clear any unused bytes
+ off += cbDesc4 - cbDesc;
+ }
+ if(cbPFD){
+ ((PU_EMRHEADER) record)->offPixelFormat = off;
+ memcpy(record+off,pfmtDesc,cbPFD);
+ }
+ }
+ return(record);
+}
+
+// U_EMRPOLYBEZIER_set 2
+/**
+ \brief Allocate and construct a U_EMR_POLYBEZIER record.
+ \return pointer to U_EMR_POLYBEZIER record, or NULL on error.
+ \param rclBounds bounding rectangle in device units
+ \param cptl Number of points to draw
+ \param points array of points
+*/
+char *U_EMRPOLYBEZIER_set(
+ const U_RECTL rclBounds,
+ const uint32_t cptl,
+ const U_POINTL *points
+ ){
+ return(U_EMR_CORE1_set(U_EMR_POLYBEZIER, rclBounds, cptl, points));
+}
+
+// U_EMRPOLYGON_set 3
+/**
+ \brief Allocate and construct a U_EMR_POLYGON record.
+ \return pointer to U_EMR_POLYGON record, or NULL on error.
+ \param rclBounds bounding rectangle in device units
+ \param cptl Number of points to draw
+ \param points array of points
+*/
+char *U_EMRPOLYGON_set(
+ const U_RECTL rclBounds,
+ const uint32_t cptl,
+ const U_POINTL *points
+ ){
+ return(U_EMR_CORE1_set(U_EMR_POLYGON, rclBounds, cptl, points));
+}
+
+// U_EMRPOLYLINE_set 4
+/**
+ \brief Allocate and construct a U_EMR_POLYLINE record.
+ \return pointer to U_EMR_POLYLINE record, or NULL on error.
+ \param rclBounds bounding rectangle in device units
+ \param cptl Number of points to draw
+ \param points array of points
+*/
+char *U_EMRPOLYLINE_set(
+ const U_RECTL rclBounds,
+ const uint32_t cptl,
+ const U_POINTL *points
+ ){
+ return(U_EMR_CORE1_set(U_EMR_POLYLINE, rclBounds, cptl, points));
+}
+
+// U_EMRPOLYBEZIERTO_set 5
+/**
+ \brief Allocate and construct a U_EMR_POLYBEZIERTO record.
+ \return pointer to U_EMR_POLYBEZIERTO record, or NULL on error.
+ \param rclBounds bounding rectangle in device units
+ \param cptl Number of points to draw
+ \param points array of points
+*/
+char *U_EMRPOLYBEZIERTO_set(
+ const U_RECTL rclBounds,
+ const uint32_t cptl,
+ const U_POINTL *points
+ ){
+ return(U_EMR_CORE1_set(U_EMR_POLYBEZIERTO, rclBounds, cptl, points));
+}
+
+// U_EMRPOLYLINETO_set 6
+/**
+ \brief Allocate and construct a U_EMR_POLYLINETO record.
+ \return pointer to U_EMR_POLYLINETO record, or NULL on error.
+ \param rclBounds bounding rectangle in device units
+ \param cptl Number of points to draw
+ \param points array of points
+*/
+char *U_EMRPOLYLINETO_set(
+ const U_RECTL rclBounds,
+ const uint32_t cptl,
+ const U_POINTL *points
+ ){
+ return(U_EMR_CORE1_set(U_EMR_POLYLINETO, rclBounds, cptl, points));
+}
+
+// U_EMRPOLYPOLYLINE_set 7
+/**
+ \brief Allocate and construct a U_EMR_POLYPOLYLINE record.
+ \return pointer to U_EMR_POLYPOLYLINE record, or NULL on error.
+ \param rclBounds bounding rectangle in device units
+ \param nPolys Number of elements in aPolyCounts
+ \param aPolyCounts Number of points in each poly (sequential)
+ \param cptl Total number of points (over all poly)
+ \param points array of points
+*/
+char *U_EMRPOLYPOLYLINE_set(
+ const U_RECTL rclBounds,
+ const uint32_t nPolys,
+ const uint32_t *aPolyCounts,
+ const uint32_t cptl,
+ const U_POINTL *points
+ ){
+ return(U_EMR_CORE2_set(U_EMR_POLYPOLYLINE, rclBounds, nPolys, aPolyCounts,cptl, points));
+}
+
+// U_EMRPOLYPOLYGON_set 8
+/**
+ \brief Allocate and construct a U_EMR_POLYPOLYGON record.
+ \return pointer to U_EMR_POLYPOLYGON record, or NULL on error.
+ \param rclBounds bounding rectangle in device units
+ \param nPolys Number of elements in aPolyCounts
+ \param aPolyCounts Number of points in each poly (sequential)
+ \param cptl Total number of points (over all poly)
+ \param points array of points
+*/
+char *U_EMRPOLYPOLYGON_set(
+ const U_RECTL rclBounds,
+ const uint32_t nPolys,
+ const uint32_t *aPolyCounts,
+ const uint32_t cptl,
+ const U_POINTL *points
+ ){
+ return(U_EMR_CORE2_set(U_EMR_POLYPOLYGON, rclBounds, nPolys, aPolyCounts,cptl, points));
+}
+
+// U_EMRSETWINDOWEXTEX_set 9
+/**
+ \brief Allocate and construct a U_EMR_SETWINDOWEXTEX record.
+ \return pointer to U_EMR_SETWINDOWEXTEX record, or NULL on error.
+ \param szlExtent H & V extent in logical units
+*/
+char *U_EMRSETWINDOWEXTEX_set(
+ const U_SIZEL szlExtent
+ ){
+ U_PAIR temp;
+ temp.x = szlExtent.cx;
+ temp.y = szlExtent.cy;
+ return(U_EMR_CORE7_set(U_EMR_SETWINDOWEXTEX, temp));
+}
+
+// U_EMRSETWINDOWORGEX_set 10
+/**
+ \brief Allocate and construct a U_EMR_SETWINDOWORGEX record.
+ \return pointer to U_EMR_SETWINDOWORGEX record, or NULL on error.
+ \param ptlOrigin H & V origin in logical units
+*/
+char *U_EMRSETWINDOWORGEX_set(
+ const U_POINTL ptlOrigin
+ ){
+ return(U_EMR_CORE7_set(U_EMR_SETWINDOWORGEX, ptlOrigin)); // U_PAIR and U_POINTL are the same thing
+}
+
+// U_EMRSETVIEWPORTEXTEX_set 11
+/**
+ \brief Allocate and construct a U_EMR_SETVIEWPORTEXTEX record.
+ \return pointer to U_EMR_SETVIEWPORTEXTEX record, or NULL on error.
+ \param szlExtent H & V extent in logical units
+*/
+char *U_EMRSETVIEWPORTEXTEX_set(
+ const U_SIZEL szlExtent
+ ){
+ U_PAIR temp;
+ temp.x = szlExtent.cx;
+ temp.y = szlExtent.cy;
+ return(U_EMR_CORE7_set(U_EMR_SETVIEWPORTEXTEX, temp));
+}
+
+// U_EMRSETVIEWPORTORGEX_set 12
+/**
+ \brief Allocate and construct a U_EMR_SETVIEWPORTORGEX record.
+ \return pointer to U_EMR_SETVIEWPORTORGEX record, or NULL on error.
+ \param ptlOrigin H & V origin in logical units
+*/
+char *U_EMRSETVIEWPORTORGEX_set(
+ const U_POINTL ptlOrigin
+ ){
+ return(U_EMR_CORE7_set(U_EMR_SETVIEWPORTORGEX, ptlOrigin)); // U_PAIR and U_POINTL are the same thing
+}
+
+// U_EMRSETBRUSHORGEX_set 13
+/**
+ \brief Allocate and construct a U_EMR_SETBRUSHORGEX record.
+ \return pointer to U_EMR_SETBRUSHORGEX record, or NULL on error.
+ \param ptlOrigin H & V origin in logical units
+*/
+char *U_EMRSETBRUSHORGEX_set(
+ const U_POINTL ptlOrigin
+ ){
+ return(U_EMR_CORE7_set(U_EMR_SETBRUSHORGEX, *((PU_PAIR) & ptlOrigin)));
+}
+
+// U_EMREOF_set 14
+/**
+ \brief Allocate and construct a U_EMR_EOF record.
+ \return pointer to U_EMR_EOF record, or NULL on error.
+ \param cbPalEntries Number of palette entries
+ \param PalEntries (optional) array of PalEntries
+ \param et tracking information, needed for nSizeLast calculation
+*/
+char *U_EMREOF_set(
+ const U_CBPLENTRIES cbPalEntries,
+ const PU_LOGPLTNTRY PalEntries,
+ EMFTRACK *et
+ ){
+ char *record;
+ char *ptr;
+ int irecsize;
+ int cbPals; // space allocated for Palette Entries
+ uint32_t off;
+
+ if(cbPalEntries && !PalEntries)return(NULL);
+ if(!et)return(NULL);
+ cbPals = cbPalEntries * sizeof(U_LOGPLTNTRY);
+ irecsize = sizeof(U_EMREOF) + cbPals + sizeof(uint32_t); //invariant core, variable palette, palette byte count
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_EOF;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMREOF) record)->cbPalEntries = cbPalEntries;
+ ((PU_EMREOF) record)->offPalEntries = 0; // May be changed below
+ off = sizeof(U_EMREOF); //start of the variable region
+ if(cbPals){
+ ((PU_EMREOF) record)->offPalEntries = off;
+ memcpy(record+off,PalEntries,cbPals);
+ off += cbPals;
+ }
+ ptr = record + off;
+ *(uint32_t *)ptr = irecsize + et->used; // EMREOF nSizeLast field, not at a fixed position, cannot be accessed by field name
+ }
+ et->PalEntries = cbPalEntries;
+ return(record);
+}
+
+
+// U_EMRSETPIXELV_set 15
+/**
+ \brief Allocate and construct a U_EMR_SETPIXELV record.
+ \return pointer to U_EMR_SETPIXELV record, or NULL on error.
+ \param ptlPixel Pixel coordinates (logical)
+ \param crColor Pixel color
+*/
+char *U_EMRSETPIXELV_set(
+ const U_POINTL ptlPixel,
+ const U_COLORREF crColor
+ ){
+ char *record;
+ int irecsize;
+
+ irecsize = sizeof(U_EMRSETPIXELV);
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_SETPIXELV;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRSETPIXELV)record)->ptlPixel = ptlPixel;
+ ((PU_EMRSETPIXELV)record)->crColor = crColor;
+ }
+ return(record);
+}
+
+
+// U_EMRSETMAPPERFLAGS_set 16
+/**
+ \brief Allocate and construct a U_EMR_SETMAPPERFLAGS record.
+ \return pointer to U_EMR_SETMAPPERFLAGS record, or NULL on error.
+*/
+char *U_EMRSETMAPPERFLAGS_set(void){
+ char *record;
+ int irecsize;
+
+ irecsize = sizeof(U_EMRSETMAPPERFLAGS);
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_SETMAPPERFLAGS;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRSETMAPPERFLAGS)record)->dwFlags = 1;
+ }
+ return(record);
+}
+
+// U_EMRSETMAPMODE_set 17
+/**
+ \brief Allocate and construct a U_EMR_SETMAPMODE record.
+ \return pointer to U_EMR_SETMAPMODE record, or NULL on error.
+ \param iMode MapMode Enumeration
+*/
+char *U_EMRSETMAPMODE_set(
+ const uint32_t iMode
+ ){
+ return(U_EMR_CORE3_set(U_EMR_SETMAPMODE, iMode));
+}
+
+// U_EMRSETBKMODE_set 18
+/**
+ \brief Allocate and construct a U_EMR_SETBKMODE record.
+ \return pointer to U_EMR_SETBKMODE record, or NULL on error.
+ \param iMode BackgroundMode Enumeration
+*/
+char *U_EMRSETBKMODE_set(
+ const uint32_t iMode
+ ){
+ return(U_EMR_CORE3_set(U_EMR_SETBKMODE, iMode));
+}
+
+// U_EMRSETPOLYFILLMODE_set 19
+/**
+ \brief Allocate and construct a U_EMR_SETPOLYFILLMODE record.
+ \return pointer to U_EMR_SETPOLYFILLMODE record, or NULL on error.
+ \param iMode PolygonFillMode Enumeration
+*/
+char *U_EMRSETPOLYFILLMODE_set(
+ const uint32_t iMode
+ ){
+ return(U_EMR_CORE3_set(U_EMR_SETPOLYFILLMODE, iMode));
+}
+
+// U_EMRSETROP2_set 20
+/**
+ \brief Allocate and construct a U_EMR_SETROP2 record.
+ \return pointer to U_EMR_SETROP2 record, or NULL on error.
+ \param iMode RasterOperation2 Enumeration
+*/
+char *U_EMRSETROP2_set(
+ const uint32_t iMode
+ ){
+ return(U_EMR_CORE3_set(U_EMR_SETROP2, iMode));
+}
+
+// U_EMRSETSTRETCHBLTMODE_set 21
+/**
+ \brief Allocate and construct a U_EMR_SETSTRETCHBLTMODE record.
+ \return pointer to U_EMR_SETSTRETCHBLTMODE record, or NULL on error.
+ \param iMode StretchMode Enumeration
+*/
+char *U_EMRSETSTRETCHBLTMODE_set(
+ const uint32_t iMode
+ ){
+ return(U_EMR_CORE3_set(U_EMR_SETSTRETCHBLTMODE, iMode));
+}
+
+// U_EMRSETTEXTALIGN_set 22
+/**
+ \brief Allocate and construct a U_EMR_SETTEXTALIGN record.
+ \return pointer to U_EMR_SETTEXTALIGN record, or NULL on error.
+ \param iMode TextAlignment Enumeration
+*/
+char *U_EMRSETTEXTALIGN_set(
+ const uint32_t iMode
+ ){
+ return(U_EMR_CORE3_set(U_EMR_SETTEXTALIGN, iMode));
+}
+
+// U_EMRSETCOLORADJUSTMENT_set 23
+/**
+ \brief Allocate and construct a U_EMR_SETCOLORADJUSTMENT record.
+ \return pointer to U_EMR_SETCOLORADJUSTMENT record, or NULL on error.
+ \param ColorAdjustment Color Adjustment
+*/
+char *U_EMRSETCOLORADJUSTMENT_set(
+ const U_COLORADJUSTMENT ColorAdjustment
+ ){
+ char *record;
+ int irecsize;
+
+ irecsize = sizeof(U_EMRSETCOLORADJUSTMENT);
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_SETCOLORADJUSTMENT;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRSETCOLORADJUSTMENT) record)->ColorAdjustment = ColorAdjustment;
+ }
+ return(record);
+}
+
+// U_EMRSETTEXTCOLOR_set 24
+/**
+ \brief Allocate and construct a U_EMR_SETTEXTCOLOR record.
+ \return pointer to U_EMR_SETTEXTCOLOR record, or NULL on error.
+ \param crColor Text Color
+*/
+char *U_EMRSETTEXTCOLOR_set(
+ const U_COLORREF crColor
+ ){
+ return(U_EMR_CORE3_set(U_EMR_SETTEXTCOLOR, *(uint32_t *) &crColor));
+}
+
+// U_EMRSETBKCOLOR_set 25
+/**
+ \brief Allocate and construct a U_EMR_SETBKCOLOR record.
+ \return pointer to U_EMR_SETBKCOLOR record, or NULL on error.
+ \param crColor Background Color
+*/
+char *U_EMRSETBKCOLOR_set(
+ const U_COLORREF crColor
+ ){
+ return(U_EMR_CORE3_set(U_EMR_SETBKCOLOR, *(uint32_t *) &crColor));
+}
+
+// U_EMROFFSETCLIPRGN_set 26
+/**
+ \brief Allocate and construct a U_EMR_OFFSETCLIPRGN record.
+ \return pointer to U_EMR_OFFSETCLIPRGN record, or NULL on error.
+ \param ptl Clipping region
+*/
+char *U_EMROFFSETCLIPRGN_set(
+ const U_POINTL ptl
+ ){
+ return(U_EMR_CORE7_set(U_EMR_OFFSETCLIPRGN, ptl));
+}
+
+// U_EMRMOVETOEX_set 27
+/**
+ \brief Allocate and construct a U_EMR_MOVETOEX record.
+ \return pointer to U_EMR_MOVETOEX record, or NULL on error.
+ \param ptl Point coordinates
+*/
+char *U_EMRMOVETOEX_set(
+ const U_POINTL ptl
+ ){
+ return(U_EMR_CORE7_set(U_EMR_MOVETOEX, ptl));
+}
+
+// U_EMRSETMETARGN_set 28
+/**
+ \brief Allocate and construct a U_EMR_SETMETARGN record.
+ \return pointer to U_EMR_SETMETARGN record, or NULL on error.
+*/
+char *U_EMRSETMETARGN_set(void){
+ return(U_EMR_CORE5_set(U_EMR_SETMETARGN));
+}
+
+// U_EMREXCLUDECLIPRECT_set 29
+/**
+ \brief Allocate and construct a U_EMR_EXCLUDECLIPRECT record.
+ \return pointer to U_EMR_EXCLUDECLIPRECT record, or NULL on error.
+ \param rclClip Clipping Region
+*/
+char *U_EMREXCLUDECLIPRECT_set(
+ const U_RECTL rclClip
+ ){
+ return(U_EMR_CORE4_set(U_EMR_EXCLUDECLIPRECT,rclClip));
+}
+
+// U_EMRINTERSECTCLIPRECT_set 30
+/**
+ \brief Allocate and construct a U_EMR_INTERSECTCLIPRECT record.
+ \return pointer to U_EMR_INTERSECTCLIPRECT record, or NULL on error.
+ \param rclClip Clipping Region
+*/
+char *U_EMRINTERSECTCLIPRECT_set(
+ const U_RECTL rclClip
+ ){
+ return(U_EMR_CORE4_set(U_EMR_INTERSECTCLIPRECT,rclClip));
+}
+
+// U_EMRSCALEVIEWPORTEXTEX_set 31
+/**
+ \brief Allocate and construct a U_EMR_SCALEVIEWPORTEXTEX record.
+ \return pointer to U_EMR_SCALEVIEWPORTEXTEX record, or NULL on error.
+ \param xNum Horizontal multiplier (!=0)
+ \param xDenom Horizontal divisor (!=0)
+ \param yNum Vertical multiplier (!=0)
+ \param yDenom Vertical divisor (!=0)
+*/
+char *U_EMRSCALEVIEWPORTEXTEX_set(
+ const int32_t xNum,
+ const int32_t xDenom,
+ const int32_t yNum,
+ const int32_t yDenom
+ ){
+ return(U_EMR_CORE4_set(U_EMR_SCALEVIEWPORTEXTEX,(U_RECTL){xNum,xDenom,yNum,yDenom}));
+}
+
+
+// U_EMRSCALEWINDOWEXTEX_set 32
+/**
+ \brief Allocate and construct a U_EMR_SCALEWINDOWEXTEX record.
+ \return pointer to U_EMR_SCALEWINDOWEXTEX record, or NULL on error.
+ \param xNum Horizontal multiplier (!=0)
+ \param xDenom Horizontal divisor (!=0)
+ \param yNum Vertical multiplier (!=0)
+ \param yDenom Vertical divisor (!=0)
+*/
+char *U_EMRSCALEWINDOWEXTEX_set(
+ const int32_t xNum,
+ const int32_t xDenom,
+ const int32_t yNum,
+ const int32_t yDenom
+ ){
+ return(U_EMR_CORE4_set(U_EMR_SCALEWINDOWEXTEX,(U_RECTL){xNum,xDenom,yNum,yDenom}));
+}
+
+// U_EMRSAVEDC_set 33
+/**
+ \brief Allocate and construct a U_EMR_SAVEDC record.
+ \return pointer to U_EMR_SAVEDC record, or NULL on error.
+*/
+char *U_EMRSAVEDC_set(void){
+ return(U_EMR_CORE5_set(U_EMR_SAVEDC));
+}
+
+// U_EMRRESTOREDC_set 34
+/**
+ \brief Allocate and construct a U_EMR_RESTOREDC record.
+ \return pointer to U_EMR_RESTOREDC record, or NULL on error.
+ \param iRelative DC to restore. -1 is preceding
+*/
+char *U_EMRRESTOREDC_set(
+ const int32_t iRelative
+ ){
+ return(U_EMR_CORE3_set(U_EMR_RESTOREDC, (uint32_t) iRelative));
+}
+
+// U_EMRSETWORLDTRANSFORM_set 35
+/**
+ \brief Allocate and construct a U_EMR_SETWORLDTRANSFORM record.
+ \return pointer to U_EMR_SETWORLDTRANSFORM record, or NULL on error.
+ \param xform Transform to use
+*/
+char *U_EMRSETWORLDTRANSFORM_set(
+ const U_XFORM xform
+ ){
+ char *record;
+ int irecsize;
+
+ irecsize = sizeof(U_EMRSETWORLDTRANSFORM);
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_SETWORLDTRANSFORM;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRSETWORLDTRANSFORM) record)->xform = xform;
+ }
+ return(record);
+}
+
+// U_EMRMODIFYWORLDTRANSFORM_set 36
+/**
+ \brief Allocate and construct a U_EMR_MODIFYWORLDTRANSFORM record.
+ \return pointer to U_EMR_MODIFYWORLDTRANSFORM record, or NULL on error.
+ \param xform Transform to use
+ \param iMode ModifyWorldTransformMode Enumeration
+*/
+char *U_EMRMODIFYWORLDTRANSFORM_set(
+ const U_XFORM xform,
+ const uint32_t iMode
+ ){
+ char *record;
+ int irecsize;
+
+ irecsize = sizeof(U_EMRMODIFYWORLDTRANSFORM);
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_MODIFYWORLDTRANSFORM;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRMODIFYWORLDTRANSFORM) record)->xform = xform;
+ ((PU_EMRMODIFYWORLDTRANSFORM) record)->iMode = iMode;
+ }
+ return(record);
+}
+
+// U_EMRSELECTOBJECT_set 37
+/**
+ \brief Allocate and construct a U_EMR_SELECTOBJECT record.
+ Use selectobject_set() instead of calling this function directly.
+ \return pointer to U_EMR_SELECTOBJECT record, or NULL on error.
+ \param ihObject Number of a stock or created object
+*/
+char *U_EMRSELECTOBJECT_set(
+ const uint32_t ihObject
+ ){
+ char *record;
+ int irecsize;
+
+ irecsize = sizeof(U_EMRSELECTOBJECT);
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_SELECTOBJECT;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRSELECTOBJECT) record)->ihObject = ihObject; // Index of object to SELECT
+ }
+ return(record);
+}
+
+// U_EMRCREATEPEN_set 38
+/**
+ \brief Allocate and construct a U_EMR_CREATEPEN record.
+ Use createpen_set() instead of calling this function directly.
+ \return pointer to U_EMR_CREATEPEN record, or NULL on error.
+ \param ihPen Handle of created pen
+ \param lopn U_LOGPEN structure describing this pen
+*/
+char *U_EMRCREATEPEN_set(
+ const uint32_t ihPen,
+ const U_LOGPEN lopn
+ ){
+ char *record;
+ int irecsize=sizeof(U_EMRCREATEPEN);
+
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_CREATEPEN;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRCREATEPEN) record)->ihPen = ihPen;
+ ((PU_EMRCREATEPEN) record)->lopn = lopn;
+ }
+ return(record);
+}
+
+// U_EMRCREATEBRUSHINDIRECT_set 39
+/**
+ \brief Allocate and construct a U_EMR_CREATEBRUSHINDIRECT record.
+ Use createbrushindirect_set() instead of calling this function directly.
+ \return pointer to U_EMR_CREATEBRUSHINDIRECT record, or NULL on error.
+ \param ihBrush Index to place object in EMF object table (this entry must not yet exist)
+ \param lb Brush properties
+*/
+char *U_EMRCREATEBRUSHINDIRECT_set(
+ const uint32_t ihBrush,
+ const U_LOGBRUSH lb
+ ){
+ char *record;
+ int irecsize;
+
+ irecsize = sizeof(U_EMRCREATEBRUSHINDIRECT);
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_CREATEBRUSHINDIRECT;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRCREATEBRUSHINDIRECT) record)->ihBrush = ihBrush; // Index to place object in EMF object table (this entry must not yet exist)
+ ((PU_EMRCREATEBRUSHINDIRECT) record)->lb = lb;
+ }
+ return(record);
+}
+
+// U_EMRDELETEOBJECT_set 40
+/**
+ \brief Allocate and construct a U_EMR_DELETEOBJECT record.
+ Use deleteobject_set() instead of calling this function directly.
+ \return pointer to U_EMR_DELETEOBJECT record, or NULL on error.
+ \param ihObject Number of a stock or created object
+*/
+char *U_EMRDELETEOBJECT_set(
+ const uint32_t ihObject
+ ){
+ char *record;
+ int irecsize;
+
+ irecsize = sizeof(U_EMRDELETEOBJECT);
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_DELETEOBJECT;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRDELETEOBJECT) record)->ihObject = ihObject; // Index of object to DELETE
+ }
+ return(record);
+}
+
+// U_EMRANGLEARC_set 41
+/**
+ \brief Allocate and construct a U_EMR_ANGLEARC record.
+ \return pointer to U_EMR_ANGLEARC record, or NULL on error.
+ \param ptlCenter Center in logical units
+ \param nRadius Radius in logical units
+ \param eStartAngle Starting angle in degrees (counter clockwise from x axis)
+ \param eSweepAngle Sweep angle in degrees
+*/
+char *U_EMRANGLEARC_set(
+ const U_POINTL ptlCenter,
+ const uint32_t nRadius,
+ const U_FLOAT eStartAngle,
+ const U_FLOAT eSweepAngle
+ ){
+ char *record;
+ int irecsize;
+
+ irecsize = sizeof(U_EMRANGLEARC);
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_ANGLEARC;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRANGLEARC) record)->ptlCenter = ptlCenter;
+ ((PU_EMRANGLEARC) record)->nRadius = nRadius;
+ ((PU_EMRANGLEARC) record)->eStartAngle = eStartAngle;
+ ((PU_EMRANGLEARC) record)->eSweepAngle = eSweepAngle;
+ }
+ return(record);
+}
+
+// U_EMRELLIPSE_set 42
+/**
+ \brief Allocate and construct a U_EMR_ELLIPSE record.
+ \return pointer to U_EMR_ELLIPSE record, or NULL on error.
+ \param rclBox bounding rectangle in logical units
+*/
+char *U_EMRELLIPSE_set(
+ const U_RECTL rclBox
+ ){
+ return(U_EMR_CORE4_set(U_EMR_ELLIPSE,rclBox));
+}
+
+// U_EMRRECTANGLE_set 43
+/**
+ \brief Allocate and construct a U_EMR_RECTANGLE record.
+ \return pointer to U_EMR_RECTANGLE record, or NULL on error.
+ \param rclBox bounding rectangle in logical units
+*/
+char *U_EMRRECTANGLE_set(
+ const U_RECTL rclBox
+ ){
+ return(U_EMR_CORE4_set(U_EMR_RECTANGLE,rclBox));
+}
+
+// U_EMRROUNDRECT_set 44
+/**
+ \brief Allocate and construct a U_EMR_ROUNDRECT record.
+ \return pointer to U_EMR_ROUNDRECT record, or NULL on error.
+ \param rclBox bounding rectangle in logical units
+ \param szlCorner W & H in logical units of ellipse used to round corner
+*/
+char *U_EMRROUNDRECT_set(
+ const U_RECTL rclBox,
+ const U_SIZEL szlCorner
+ ){
+ char *record;
+ int irecsize;
+
+ irecsize = sizeof(U_EMRROUNDRECT);
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_ROUNDRECT;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRROUNDRECT) record)->rclBox = rclBox;
+ ((PU_EMRROUNDRECT) record)->szlCorner = szlCorner;
+ }
+ return(record);
+}
+
+// U_EMRARC_set 45
+/**
+ \brief Allocate and construct a U_EMR_ARC record.
+ \return pointer to U_EMR_ARC record, or NULL on error.
+ \param rclBox bounding rectangle in logical units
+ \param ptlStart Start point in logical units
+ \param ptlEnd End point in logical units
+*/
+char *U_EMRARC_set(
+ const U_RECTL rclBox,
+ const U_POINTL ptlStart,
+ const U_POINTL ptlEnd
+ ){
+ return(U_EMR_CORE9_set(U_EMR_ARC,rclBox, ptlStart, ptlEnd));
+}
+
+// U_EMRCHORD_set 46
+/**
+ \brief Allocate and construct a U_EMR_CHORD record.
+ \return pointer to U_EMR_CHORD record, or NULL on error.
+ \param rclBox bounding rectangle in logical units
+ \param ptlStart Start point in logical units
+ \param ptlEnd End point in logical units
+*/
+char *U_EMRCHORD_set(
+ const U_RECTL rclBox,
+ const U_POINTL ptlStart,
+ const U_POINTL ptlEnd
+ ){
+ return(U_EMR_CORE9_set(U_EMR_CHORD,rclBox, ptlStart, ptlEnd));
+}
+
+// U_EMRPIE_set 47
+/**
+ \brief Allocate and construct a U_EMR_PIE record.
+ \return pointer to U_EMR_PIE record, or NULL on error.
+ \param rclBox bounding rectangle in logical units
+ \param ptlStart Start point in logical units
+ \param ptlEnd End point in logical units
+*/
+char *U_EMRPIE_set(
+ const U_RECTL rclBox,
+ const U_POINTL ptlStart,
+ const U_POINTL ptlEnd
+ ){
+ return(U_EMR_CORE9_set(U_EMR_PIE,rclBox, ptlStart, ptlEnd));
+}
+
+// U_EMRSELECTPALETTE_set 48
+/**
+ \brief Allocate and construct a U_EMR_SELECTPALETTE record.
+ \return pointer to U_EMR_SELECTPALETTE record, or NULL on error.
+ \param ihPal Index of a Palette object in the EMF object table
+*/
+char *U_EMRSELECTPALETTE_set(
+ const uint32_t ihPal
+ ){
+ return(U_EMR_CORE3_set(U_EMR_SELECTPALETTE, ihPal));
+}
+
+// U_EMRCREATEPALETTE_set 49
+/**
+ \brief Allocate and construct a U_EMR_CREATEPALETTE record.
+ Use createpalette_set() instead of calling this function directly.
+ \return pointer to U_EMR_CREATEPALETTE record, or NULL on error.
+ \param ihPal Index to place object in EMF object table (this entry must not yet exist)
+ \param lgpl Palette properties
+*/
+char *U_EMRCREATEPALETTE_set(
+ const uint32_t ihPal,
+ const U_LOGPALETTE lgpl
+ ){
+ char *record;
+ int irecsize;
+
+ irecsize = sizeof(U_EMRCREATEPALETTE);
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_CREATEPALETTE;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRCREATEPALETTE) record)->ihPal = ihPal;
+ ((PU_EMRCREATEPALETTE) record)->lgpl = lgpl;
+ }
+ return(record);
+}
+
+// U_EMRSETPALETTEENTRIES_set 50
+/**
+ \brief Allocate and construct a U_EMR_SETPALETTEENTRIES record.
+ Use setpaletteentries_set() instead of calling this function directly.
+ \return pointer to U_EMR_SETPALETTEENTRIES record, or NULL on error.
+ \param ihPal Index of a Palette object in the EMF object table
+ \param iStart First Palette entry in selected object to set
+ \param cEntries Number of Palette entries in selected object to set
+ \param aPalEntries Values to set with
+*/
+char *U_EMRSETPALETTEENTRIES_set(
+ const uint32_t ihPal,
+ const uint32_t iStart,
+ const U_NUM_LOGPLTNTRY cEntries,
+ const PU_LOGPLTNTRY aPalEntries
+ ){
+ char *record;
+ int irecsize;
+ int cbPals;
+
+ if(!aPalEntries)return(NULL);
+ cbPals = cEntries * sizeof(U_LOGPLTNTRY);
+ irecsize = sizeof(U_EMRSETPALETTEENTRIES) + cbPals - sizeof(U_LOGPLTNTRY);
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_SETPALETTEENTRIES;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRSETPALETTEENTRIES) record)->ihPal = ihPal;
+ ((PU_EMRSETPALETTEENTRIES) record)->iStart = iStart;
+ ((PU_EMRSETPALETTEENTRIES) record)->cEntries = cEntries;
+ memcpy(((PU_EMRSETPALETTEENTRIES) record)->aPalEntries, aPalEntries,cbPals);
+ }
+ return(record);
+}
+
+// U_EMRRESIZEPALETTE_set 51
+/**
+ \brief Allocate and construct a U_EMR_RESIZEPALETTE record.
+ \return pointer to U_EMR_RESIZEPALETTE record, or NULL on error.
+ \param ihPal Index of a Palette object in the EMF object table
+ \param cEntries Number to expand or truncate the Palette entry list to
+*/
+char *U_EMRRESIZEPALETTE_set(
+ const uint32_t ihPal,
+ const uint32_t cEntries
+ ){
+ return(U_EMR_CORE7_set(U_EMR_RESIZEPALETTE, (U_PAIR){ihPal,cEntries}));
+}
+
+// U_EMRREALIZEPALETTE_set 52
+/**
+ \brief Allocate and construct a U_EMR_REALIZEPALETTE record.
+ \return pointer to U_EMR_REALIZEPALETTE record, or NULL on error.
+*/
+char *U_EMRREALIZEPALETTE_set(void){
+ return(U_EMR_CORE5_set(U_EMR_REALIZEPALETTE));
+}
+
+// U_EMREXTFLOODFILL_set 53
+/**
+ \brief Allocate and construct a U_EMR_EXTFLOODFILL record.
+ \return pointer to U_EMR_EXTFLOODFILL record, or NULL on error.
+ \param ptlStart Start point in logical units
+ \param crColor Color to fill with
+ \param iMode FloodFill Enumeration
+*/
+char *U_EMREXTFLOODFILL_set(
+ const U_POINTL ptlStart,
+ const U_COLORREF crColor,
+ const uint32_t iMode
+ ){
+ char *record;
+ int irecsize;
+
+ irecsize = sizeof(U_EMREXTFLOODFILL);
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_EXTFLOODFILL;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMREXTFLOODFILL) record)->ptlStart = ptlStart;
+ ((PU_EMREXTFLOODFILL) record)->crColor = crColor;
+ ((PU_EMREXTFLOODFILL) record)->iMode = iMode;
+ }
+ return(record);
+}
+
+// U_EMRLINETO_set 54
+/**
+ \brief Allocate and construct a U_EMR_LINETO record.
+ \return pointer to U_EMR_LINETO record, or NULL on error.
+ \param ptl Point coordinates
+*/
+char *U_EMRLINETO_set(
+ const U_POINTL ptl
+ ){
+ return(U_EMR_CORE7_set(U_EMR_LINETO, ptl));
+}
+
+// U_EMRARCTO_set 55
+/**
+ \brief Allocate and construct a U_EMR_ARCTO record.
+ \return pointer to U_EMR_ARCTO record, or NULL on error.
+ \param rclBox bounding rectangle in logical units
+ \param ptlStart Start point in logical units
+ \param ptlEnd End point in logical units
+
+ Note that the draw begins with a line from the current point to ptlStart, which is
+ not indicated in the Microsoft EMF documentation for this record.
+*/
+char *U_EMRARCTO_set(
+ U_RECTL rclBox,
+ U_POINTL ptlStart,
+ U_POINTL ptlEnd
+ ){
+ return(U_EMR_CORE9_set(U_EMR_ARCTO,rclBox, ptlStart, ptlEnd));
+}
+
+// U_EMRPOLYDRAW_set 56
+/**
+ \brief Allocate and construct a U_EMR_POLYDRAW record.
+ \return pointer to U_EMR_POLYDRAW record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param cptl Number of U_POINTL objects
+ \param aptl Array of U_POINTL objects
+ \param abTypes Array of Point Enumeration
+*/
+char *U_EMRPOLYDRAW_set(
+ const U_RECTL rclBounds,
+ const U_NUM_POINTL cptl,
+ const U_POINTL *aptl,
+ const uint8_t *abTypes
+ ){
+ char *record;
+ int irecsize;
+ int cbPoints, cbAbTypes, cbAbTypes4, off;
+
+ if(!cptl || !aptl || !abTypes)return(NULL);
+ cbPoints = cptl * sizeof(U_POINTL); // space for aptl
+ cbAbTypes = cptl; // number of abTypes (same array size, 1 byte each)
+ cbAbTypes4 = UP4(cbAbTypes); // space for abTypes
+ irecsize = sizeof(U_EMRPOLYDRAW) + cbPoints + cbAbTypes4 - sizeof(U_POINTL) - 1;
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_POLYDRAW;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRPOLYDRAW) record)->rclBounds = rclBounds;
+ ((PU_EMRPOLYDRAW) record)->cptl = cptl;
+ off = sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(uint32_t); // offset to first variable part
+ memcpy(record+off,aptl,cbPoints);
+ off += cbPoints;
+ memcpy(record+off,abTypes,cbAbTypes);
+ off += cbAbTypes;
+ if(cbAbTypes4 > cbAbTypes){ memset(record+off,0,cbAbTypes4-cbAbTypes); } // keeps valgrind happy (initialize padding after byte array)
+ }
+ return(record);
+}
+
+// U_EMRSETARCDIRECTION_set 57
+/**
+ \brief Allocate and construct a U_EMR_SETARCDIRECTION record.
+ \return pointer to U_EMR_SETARCDIRECTION record, or NULL on error.
+ \param iArcDirection ArcDirection Enumeration
+*/
+char *U_EMRSETARCDIRECTION_set(
+ const uint32_t iArcDirection
+ ){
+ return(U_EMR_CORE3_set(U_EMR_SETARCDIRECTION, iArcDirection));
+}
+
+// U_EMRSETMITERLIMIT_set 58
+/**
+ \brief Allocate and construct a U_EMR_SETMITERLIMIT record.
+ \return pointer to U_EMR_SETMITERLIMIT record, or NULL on error.
+ \param eMiterLimit MapMode Enumeration
+*/
+char *U_EMRSETMITERLIMIT_set(
+ const uint32_t eMiterLimit
+ ){
+ return(U_EMR_CORE3_set(U_EMR_SETMITERLIMIT, eMiterLimit));
+}
+
+
+// U_EMRBEGINPATH_set 59
+/**
+ \brief Allocate and construct a U_EMR_BEGINPATH record.
+ \return pointer to U_EMR_BEGINPATH record, or NULL on error.
+*/
+char *U_EMRBEGINPATH_set(void){
+ return(U_EMR_CORE5_set(U_EMR_BEGINPATH));
+}
+
+// U_EMRENDPATH_set 60
+/**
+ \brief Allocate and construct a U_EMR_ENDPATH record.
+ \return pointer to U_EMR_ENDPATH record, or NULL on error.
+*/
+char *U_EMRENDPATH_set(void){
+ return(U_EMR_CORE5_set(U_EMR_ENDPATH));
+}
+
+// U_EMRCLOSEFIGURE_set 61
+/**
+ \brief Allocate and construct a U_EMR_CLOSEFIGURE record.
+ \return pointer to U_EMR_CLOSEFIGURE record, or NULL on error.
+*/
+char *U_EMRCLOSEFIGURE_set(void){
+ return(U_EMR_CORE5_set(U_EMR_CLOSEFIGURE));
+}
+
+// U_EMRFILLPATH_set 62
+/**
+ \brief Allocate and construct a U_EMR_FILLPATH record.
+ \return pointer to U_EMR_FILLPATH record, or NULL on error.
+ \param rclBox Bounding rectangle in device units
+
+ U_EMR_FILLPATH closes the open figure before filling.
+*/
+char *U_EMRFILLPATH_set(
+ const U_RECTL rclBox
+ ){
+ return(U_EMR_CORE4_set(U_EMR_FILLPATH,rclBox));
+}
+
+// U_EMRSTROKEANDFILLPATH_set 63
+/**
+ \brief Allocate and construct a U_EMR_STROKEANDFILLPATH record.
+ \return pointer to U_EMR_STROKEANDFILLPATH record, or NULL on error.
+ \param rclBox Bounding rectangle in device units
+
+ U_EMR_STROKEANDFILLPATH closes the open figure before filling and stroking.
+ There appears to be no way to fill an open path while stroking it, as any one
+ of U_EMRFILLPATH, U_EMRSTROKEPATH, or U_EMRSTROKEANDFILEPATH will "use up" the path,
+*/
+char *U_EMRSTROKEANDFILLPATH_set(
+ const U_RECTL rclBox
+ ){
+ return(U_EMR_CORE4_set(U_EMR_STROKEANDFILLPATH,rclBox));
+}
+
+// U_EMRSTROKEPATH_set 64
+/**
+ \brief Allocate and construct a U_EMR_STROKEPATH record.
+ \return pointer to U_EMR_STROKEPATH record, or NULL on error.
+ \param rclBox Bounding rectangle in device units
+
+ U_EMR_STROKEPATH does NOT close the open figure before stroking it.
+*/
+char *U_EMRSTROKEPATH_set(
+ const U_RECTL rclBox
+ ){
+ return(U_EMR_CORE4_set(U_EMR_STROKEPATH,rclBox));
+}
+
+// U_EMRFLATTENPATH_set 65
+/**
+ \brief Allocate and construct a U_EMR_FLATTENPATH record.
+ \return pointer to U_EMR_FLATTENPATH record, or NULL on error.
+*/
+char *U_EMRFLATTENPATH_set(void){
+ return(U_EMR_CORE5_set(U_EMR_FLATTENPATH));
+}
+
+// U_EMRWIDENPATH_set 66
+/**
+ \brief Allocate and construct a U_EMR_WIDENPATH record.
+ \return pointer to U_EMR_WIDENPATH record, or NULL on error.
+*/
+char *U_EMRWIDENPATH_set(void){
+ return(U_EMR_CORE5_set(U_EMR_WIDENPATH));
+}
+
+// U_EMRSELECTCLIPPATH_set 67
+/**
+ \brief Allocate and construct a U_EMR_SELECTCLIPPATH record.
+ \return pointer to U_EMR_SELECTCLIPPATH record, or NULL on error.
+ \param iMode RegionMode Enumeration
+*/
+char *U_EMRSELECTCLIPPATH_set(
+ const uint32_t iMode
+ ){
+ return(U_EMR_CORE3_set(U_EMR_SELECTCLIPPATH, iMode));
+}
+
+// U_EMRABORTPATH_set 68
+/**
+ \brief Allocate and construct a U_EMR_ABORTPATH record.
+ \return pointer to U_EMR_ABORTPATH record, or NULL on error.
+*/
+char *U_EMRABORTPATH_set(void){
+ return(U_EMR_CORE5_set(U_EMR_ABORTPATH));
+}
+
+// U_EMRUNDEF69 69
+
+// U_EMRCOMMENT_set 70 Comment (any binary data, interpretation is program specific)
+/**
+ \brief Allocate and construct a U_EMR_COMMENT record.
+ \return pointer to U_EMR_COMMENT record, or NULL on error.
+ \param cbData Number of bytes in comment
+ \param Data Comment (any binary data, interpretation is program specific)
+*/
+char *U_EMRCOMMENT_set(
+ const U_CBDATA cbData,
+ const char *Data
+ ){
+ char *record;
+ unsigned int cbData4;
+ int irecsize;
+
+ cbData4 = UP4(cbData);
+ irecsize = sizeof(U_EMR) + sizeof(U_CBDATA) + cbData4;
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_COMMENT;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRCOMMENT) record)->cbData = cbData;
+ memcpy(record + irecsize - cbData4,Data,cbData);
+ if(cbData4 > cbData)memset(record + irecsize - cbData4 + cbData,0,cbData4-cbData); // clear any unused bytes
+ }
+ return(record);
+}
+
+// U_EMRFILLRGN_set 71
+/**
+ \brief Allocate and construct a U_EMR_FILLRGN record.
+ Use fillrgn_set() instead of calling this function directly.
+ \return pointer to U_EMR_FILLRGN record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param ihBrush Index of a Brush object in the EMF object table
+ \param RgnData Pointer to a U_RGNDATA structure
+*/
+char *U_EMRFILLRGN_set(
+ const U_RECTL rclBounds,
+ const uint32_t ihBrush,
+ const PU_RGNDATA RgnData
+ ){
+ char *record;
+ int irecsize;
+ int cbRgns,cbRgns4,rds,rds4,off;
+
+ if(!RgnData)return(NULL);
+ cbRgns = ((PU_RGNDATAHEADER) RgnData)->nRgnSize;
+ cbRgns4 = UP4(cbRgns);
+ rds = sizeof(U_RGNDATAHEADER) + cbRgns;
+ rds4 = UP4(rds);
+ irecsize = sizeof(U_EMRFILLRGN) - sizeof(U_RECTL) + cbRgns4; // core + array - overlap of one rectL
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_FILLRGN;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRFILLRGN) record)->rclBounds = rclBounds;
+ ((PU_EMRFILLRGN) record)->cbRgnData = rds;
+ ((PU_EMRFILLRGN) record)->ihBrush = ihBrush;
+ off = sizeof(U_EMRFILLRGN) - sizeof(U_RGNDATA);
+ memcpy(record + off, RgnData, rds);
+ off += rds;
+ if(rds < rds4){ memset(record + off,0, rds4 - rds); } // clear any unused bytes
+ }
+ return(record);
+}
+
+// U_EMRFRAMERGN_set 72
+/**
+ \brief Allocate and construct a U_EMR_FRAMERGN record.
+ Use framegrn_set() instead of calling this function directly.
+ \return pointer to U_EMR_FRAMERGN record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param ihBrush Index of a Brush object in the EMF object table
+ \param szlStroke W & H of Brush stroke
+ \param RgnData Pointer to a U_RGNDATA structure
+*/
+char *U_EMRFRAMERGN_set(
+ const U_RECTL rclBounds,
+ const uint32_t ihBrush,
+ const U_SIZEL szlStroke,
+ const PU_RGNDATA RgnData
+ ){
+ char *record;
+ int irecsize;
+ int cbRgns,cbRgns4,rds,rds4,off;
+
+ if(!RgnData)return(NULL);
+ cbRgns = ((PU_RGNDATAHEADER) RgnData)->nRgnSize;
+ cbRgns4 = UP4(cbRgns);
+ rds = sizeof(U_RGNDATAHEADER) + cbRgns;
+ rds4 = UP4(rds);
+ irecsize = sizeof(U_EMRFRAMERGN) - sizeof(U_RECTL) + cbRgns4; // core + array - overlap of one rectL
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_FRAMERGN;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRFRAMERGN) record)->rclBounds = rclBounds;
+ ((PU_EMRFRAMERGN) record)->cbRgnData = rds;
+ ((PU_EMRFRAMERGN) record)->ihBrush = ihBrush;
+ ((PU_EMRFRAMERGN) record)->szlStroke = szlStroke;
+ off = sizeof(U_EMRFRAMERGN) - sizeof(U_RGNDATA);
+ memcpy(record + off, RgnData, rds);
+ off += rds;
+ if(rds < rds4){ memset(record + off,0, rds4 - rds); } // clear any unused bytes
+ }
+ return(record);
+}
+
+// U_EMRINVERTRGN_set 73
+/**
+ \brief Allocate and construct a U_EMR_INVERTRGN record.
+ \return pointer to U_EMR_INVERTRGN record, or NULL on error.
+ \param RgnData Variable size U_RGNDATA structure
+*/
+char *U_EMRINVERTRGN_set(
+ const PU_RGNDATA RgnData
+ ){
+ return(U_EMR_CORE11_set(U_EMR_INVERTRGN, RgnData));
+}
+
+// U_EMRPAINTRGN_set 74
+/**
+ \brief Allocate and construct a U_EMR_PAINTRGN record.
+ \return pointer to U_EMR_PAINTRGN record, or NULL on error.
+ \param RgnData Variable size U_RGNDATA structure
+*/
+char *U_EMRPAINTRGN_set(
+ const PU_RGNDATA RgnData
+ ){
+ return(U_EMR_CORE11_set(U_EMR_PAINTRGN, RgnData));
+}
+
+// U_EMREXTSELECTCLIPRGN_set 75
+/**
+ \brief Allocate and construct a U_EMR_EXTSELECTCLIPRGN record.
+ \return pointer to U_EMR_EXTSELECTCLIPRGN or NULL on error.
+ \param iMode RegionMode Enumeration
+ \param RgnData Variable size U_RGNDATA structure
+*/
+char *U_EMREXTSELECTCLIPRGN_set(
+ const uint32_t iMode,
+ const PU_RGNDATA RgnData
+ ){
+ char *record;
+ int irecsize;
+ int cbRgns,cbRgns4,rds,rds4,off;
+
+ if(!RgnData)return(NULL);
+ cbRgns = ((PU_RGNDATAHEADER) RgnData)->nRgnSize;
+ cbRgns4 = UP4(cbRgns);
+ rds = sizeof(U_RGNDATAHEADER) + cbRgns;
+ rds4 = UP4(rds);
+ irecsize = sizeof(U_EMREXTSELECTCLIPRGN) - sizeof(U_RECTL) + cbRgns4; // core + array - overlap of one rectL
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_EXTSELECTCLIPRGN;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMREXTSELECTCLIPRGN) record)->cbRgnData = rds;
+ ((PU_EMREXTSELECTCLIPRGN) record)->iMode = iMode;
+ off = sizeof(U_EMREXTSELECTCLIPRGN) - sizeof(U_RGNDATA);
+ memcpy(record + off, RgnData, rds);
+ off += rds;
+ if(rds < rds4){ memset(record + off,0, rds4 - rds); } // clear any unused bytes
+ }
+ return(record);
+}
+
+// U_EMRBITBLT_set 76
+/**
+ \brief Allocate and construct a U_EMR_BITBLT record.
+ \return pointer to U_EMR_BITBLT record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param Dest Destination UL corner in logical units
+ \param cDest Destination width in logical units
+ \param Src Source rectangle UL corner in logical units
+ \param xformSrc Source bitmap transform (world to page coordinates)
+ \param crBkColorSrc Source bitmap background color
+ \param iUsageSrc DIBcolors Enumeration
+ \param dwRop Ternary Raster Operation enumeration
+ \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section)
+ \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
+ \param Px (Optional) bitmapbuffer (pixel array section )
+*/
+char *U_EMRBITBLT_set(
+ const U_RECTL rclBounds,
+ const U_POINTL Dest,
+ const U_POINTL cDest,
+ const U_POINTL Src,
+ const U_XFORM xformSrc,
+ const U_COLORREF crBkColorSrc,
+ const uint32_t iUsageSrc,
+ const uint32_t dwRop,
+ const PU_BITMAPINFO Bmi,
+ const uint32_t cbPx,
+ char *Px
+ ){
+ char *record;
+ int irecsize;
+ int cbImage,cbImage4,cbBmi,off;
+
+ SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
+ irecsize = sizeof(U_EMRBITBLT) + cbBmi + cbImage4;
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_BITBLT;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRBITBLT) record)->rclBounds = rclBounds;
+ ((PU_EMRBITBLT) record)->Dest = Dest;
+ ((PU_EMRBITBLT) record)->cDest = cDest;
+ ((PU_EMRBITBLT) record)->dwRop = dwRop;
+ ((PU_EMRBITBLT) record)->Src = Src;
+ ((PU_EMRBITBLT) record)->xformSrc = xformSrc;
+ ((PU_EMRBITBLT) record)->crBkColorSrc = crBkColorSrc;
+ ((PU_EMRBITBLT) record)->iUsageSrc = iUsageSrc;
+ off = sizeof(U_EMRBITBLT);
+ APPEND_PXBMISRC(record, U_EMRBITBLT, cbBmi, Bmi, Px, cbImage, cbImage4);
+ }
+ return(record);
+}
+
+// U_EMRSTRETCHBLT_set 77
+/**
+ \brief Allocate and construct a U_EMR_STRETCHBLT record.
+ \return pointer to U_EMR_STRETCHBLT record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param Dest Destination UL corner in logical units
+ \param cDest Destination width in logical units
+ \param Src Source UL corner in logical units
+ \param cSrc Src W & H in logical units
+ \param xformSrc Transform to apply to source
+ \param crBkColorSrc Background color
+ \param iUsageSrc DIBcolors Enumeration
+ \param dwRop Ternary Raster Operation enumeration
+ \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section)
+ \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
+ \param Px (Optional) bitmapbuffer (pixel array section )
+*/
+char *U_EMRSTRETCHBLT_set(
+ const U_RECTL rclBounds,
+ const U_POINTL Dest,
+ const U_POINTL cDest,
+ const U_POINTL Src,
+ const U_POINTL cSrc,
+ const U_XFORM xformSrc,
+ const U_COLORREF crBkColorSrc,
+ const uint32_t iUsageSrc,
+ const uint32_t dwRop,
+ const PU_BITMAPINFO Bmi,
+ const uint32_t cbPx,
+ char *Px
+ ){
+ char *record;
+ int irecsize;
+ int cbImage,cbImage4,cbBmi,off;
+
+ SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
+
+ irecsize = sizeof(U_EMRSTRETCHBLT) + cbBmi + cbImage4;
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_STRETCHBLT;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRSTRETCHBLT) record)->rclBounds = rclBounds;
+ ((PU_EMRSTRETCHBLT) record)->Dest = Dest;
+ ((PU_EMRSTRETCHBLT) record)->cDest = cDest;
+ ((PU_EMRSTRETCHBLT) record)->dwRop = dwRop;
+ ((PU_EMRSTRETCHBLT) record)->Src = Src;
+ ((PU_EMRSTRETCHBLT) record)->xformSrc = xformSrc;
+ ((PU_EMRSTRETCHBLT) record)->crBkColorSrc = crBkColorSrc;
+ ((PU_EMRSTRETCHBLT) record)->iUsageSrc = iUsageSrc;
+ off = sizeof(U_EMRSTRETCHBLT);
+ APPEND_PXBMISRC(record, U_EMRSTRETCHBLT, cbBmi, Bmi, Px, cbImage, cbImage4);
+ ((PU_EMRSTRETCHBLT) record)->cSrc = cSrc;
+ }
+ return(record);
+}
+
+// U_EMRMASKBLT_set 78
+/**
+ \brief Allocate and construct a U_EMR_MASKBLT record.
+ \return pointer to U_EMR_MASKBLT record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param Dest Destination UL corner in logical units
+ \param cDest Destination width in logical units
+ \param Src Source UL corner in logical units
+ \param xformSrc Transform to apply to source
+ \param crBkColorSrc Background color
+ \param iUsageSrc DIBcolors Enumeration
+ \param Mask Mask UL corner in logical units
+ \param iUsageMask DIBcolors Enumeration
+ \param dwRop Ternary Raster Operation enumeration
+ \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section)
+ \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
+ \param Px (Optional) bitmapbuffer (pixel array section )
+ \param MskBmi (Optional) bitmapbuffer (U_BITMAPINFO section)
+ \param cbMsk Size in bytes of mask array (row stride * height, there may be some padding at the end of each row)
+ \param Msk (Optional) bitmapbuffer (mask section )
+*/
+char *U_EMRMASKBLT_set(
+ const U_RECTL rclBounds,
+ const U_POINTL Dest,
+ const U_POINTL cDest,
+ const U_POINTL Src,
+ const U_XFORM xformSrc,
+ const U_COLORREF crBkColorSrc,
+ const uint32_t iUsageSrc,
+ const U_POINTL Mask,
+ const uint32_t iUsageMask,
+ const uint32_t dwRop,
+ const PU_BITMAPINFO Bmi,
+ const uint32_t cbPx,
+ char *Px,
+ const PU_BITMAPINFO MskBmi,
+ const uint32_t cbMsk,
+ char *Msk
+ ){
+ char *record;
+ int irecsize;
+ int cbImage,cbImage4,cbBmi,cbMskImage,cbMskImage4,cbMskBmi,off;
+
+ SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
+ SET_CB_FROM_PXBMI(Msk,MskBmi,cbMskImage,cbMskImage4,cbMskBmi,cbMsk);
+
+ irecsize = sizeof(U_EMRMASKBLT) + cbBmi + cbImage4 + cbMskBmi + cbMskImage4;
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_MASKBLT;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRMASKBLT) record)->rclBounds = rclBounds;
+ ((PU_EMRMASKBLT) record)->Dest = Dest;
+ ((PU_EMRMASKBLT) record)->cDest = cDest;
+ ((PU_EMRMASKBLT) record)->dwRop = dwRop;
+ ((PU_EMRMASKBLT) record)->Src = Src;
+ ((PU_EMRMASKBLT) record)->xformSrc = xformSrc;
+ ((PU_EMRMASKBLT) record)->crBkColorSrc = crBkColorSrc;
+ ((PU_EMRMASKBLT) record)->iUsageSrc = iUsageSrc;
+ ((PU_EMRMASKBLT) record)->Mask = Mask;
+ ((PU_EMRMASKBLT) record)->iUsageMask = iUsageMask;
+ off = sizeof(U_EMRMASKBLT);
+ APPEND_PXBMISRC(record, U_EMRMASKBLT, cbBmi, Bmi, Px, cbImage, cbImage4);
+ APPEND_MSKBMISRC(record, U_EMRMASKBLT, cbMskBmi, MskBmi, Msk, cbMskImage, cbMskImage4);
+ }
+ return(record);
+}
+
+// U_EMRPLGBLT_set 79
+
+/**
+ \brief Allocate and construct a U_EMRPLGBLT record.
+ \return U_EMRPLGBLT record.
+ \param rclBounds Bounding rectangle in device units
+ \param aptlDst Defines parallelogram, UL, UR, LL corners, LR is derived (3 points)
+ \param Src Source UL corner in logical units
+ \param cSrc Source width in logical units
+ \param xformSrc Transform to apply to source
+ \param crBkColorSrc Background color
+ \param iUsageSrc DIBcolors Enumeration
+ \param Mask Mask UL corner in logical units
+ \param iUsageMask DIBcolors Enumeration
+ \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section)
+ \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
+ \param Px (Optional) bitmapbuffer (pixel array section )
+ \param MskBmi (Optional) bitmapbuffer (U_BITMAPINFO section)
+ \param cbMsk Size in bytes of mask array (row stride * height, there may be some padding at the end of each row)
+ \param Msk (Optional) bitmapbuffer (mask section )
+*/
+char *U_EMRPLGBLT_set(
+ const U_RECTL rclBounds,
+ const PU_POINTL aptlDst,
+ const U_POINTL Src,
+ const U_POINTL cSrc,
+ const U_XFORM xformSrc,
+ const U_COLORREF crBkColorSrc,
+ const uint32_t iUsageSrc,
+ const U_POINTL Mask,
+ const uint32_t iUsageMask,
+ const PU_BITMAPINFO Bmi,
+ const uint32_t cbPx,
+ char *Px,
+ const PU_BITMAPINFO MskBmi,
+ const uint32_t cbMsk,
+ char *Msk
+ ){
+ char *record;
+ int irecsize;
+ int cbImage,cbImage4,cbBmi,cbMskImage,cbMskImage4,cbMskBmi,off;
+
+ SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
+ SET_CB_FROM_PXBMI(Msk,MskBmi,cbMskImage,cbMskImage4,cbMskBmi,cbMsk);
+
+ irecsize = sizeof(U_EMRPLGBLT) + cbBmi + cbImage4 + cbMskBmi + cbMskImage4;
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_PLGBLT;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRPLGBLT) record)->rclBounds = rclBounds;
+ memcpy(((PU_EMRPLGBLT) record)->aptlDst,aptlDst,3*sizeof(U_POINTL));
+ ((PU_EMRPLGBLT) record)->Src = Src;
+ ((PU_EMRPLGBLT) record)->cSrc = cSrc;
+ ((PU_EMRPLGBLT) record)->xformSrc = xformSrc;
+ ((PU_EMRPLGBLT) record)->crBkColorSrc = crBkColorSrc;
+ ((PU_EMRPLGBLT) record)->iUsageSrc = iUsageSrc;
+ ((PU_EMRPLGBLT) record)->Mask = Mask;
+ ((PU_EMRPLGBLT) record)->iUsageMask = iUsageMask;
+ off = sizeof(U_EMRPLGBLT);
+ APPEND_PXBMISRC(record, U_EMRPLGBLT, cbBmi, Bmi, Px, cbImage, cbImage4);
+ APPEND_MSKBMISRC(record, U_EMRPLGBLT, cbMskBmi, MskBmi, Msk, cbMskImage, cbMskImage4);
+ }
+ return(record);
+}
+
+// U_EMRSETDIBITSTODEVICE_set 80
+/**
+ \brief Allocate and construct a U_EMR_SETDIBITSTODEVICE record.
+ \return pointer to U_EMR_SETDIBITSTODEVICE record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param Dest Destination UL corner in logical units
+ \param Src Source UL corner in logical units
+ \param cSrc Source W & H in logical units
+ \param iUsageSrc DIBColors Enumeration
+ \param iStartScan First scan line
+ \param cScans Number of scan lines
+ \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section)
+ \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
+ \param Px (Optional) bitmapbuffer (pixel array section )
+*/
+char *U_EMRSETDIBITSTODEVICE_set(
+ const U_RECTL rclBounds,
+ const U_POINTL Dest,
+ const U_POINTL Src,
+ const U_POINTL cSrc,
+ const uint32_t iUsageSrc,
+ const uint32_t iStartScan,
+ const uint32_t cScans,
+ const PU_BITMAPINFO Bmi,
+ const uint32_t cbPx,
+ char *Px
+ ){
+ char *record;
+ int irecsize;
+ int cbImage,cbImage4,cbBmi,off;
+
+ SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
+
+ irecsize = sizeof(U_EMRSETDIBITSTODEVICE) + cbBmi + cbImage4;
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_SETDIBITSTODEVICE;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRSETDIBITSTODEVICE) record)->rclBounds = rclBounds;
+ ((PU_EMRSETDIBITSTODEVICE) record)->Dest = Dest;
+ ((PU_EMRSETDIBITSTODEVICE) record)->Src = Src;
+ ((PU_EMRSETDIBITSTODEVICE) record)->cSrc = cSrc;
+ ((PU_EMRSETDIBITSTODEVICE) record)->iUsageSrc = iUsageSrc;
+ ((PU_EMRSETDIBITSTODEVICE) record)->iStartScan = iStartScan;
+ ((PU_EMRSETDIBITSTODEVICE) record)->cScans = cScans;
+ off = sizeof(U_EMRSETDIBITSTODEVICE);
+ APPEND_PXBMISRC(record, U_EMRSETDIBITSTODEVICE, cbBmi, Bmi, Px, cbImage, cbImage4);
+ }
+ return(record);
+}
+
+// U_EMRSTRETCHDIBITS_set 81
+/**
+ \brief Allocate and construct a U_EMR_EMRSTRETCHDIBITS record.
+ \return pointer to U_EMR_EMRSTRETCHDIBITS record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param Dest Destination UL corner in logical units
+ \param cDest Destination W & H in logical units
+ \param Src Source UL corner in logical units
+ \param cSrc Source W & H in logical units
+ \param iUsageSrc DIBColors Enumeration
+ \param dwRop RasterOPeration Enumeration
+ \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section)
+ \param cbPx Size in bytes of pixel array (row STRIDE * height, there may be some padding at the end of each row)
+ \param Px (Optional) bitmapbuffer (pixel array section )
+*/
+char *U_EMRSTRETCHDIBITS_set(
+ const U_RECTL rclBounds,
+ const U_POINTL Dest,
+ const U_POINTL cDest,
+ const U_POINTL Src,
+ const U_POINTL cSrc,
+ const uint32_t iUsageSrc,
+ const uint32_t dwRop,
+ const PU_BITMAPINFO Bmi,
+ const uint32_t cbPx,
+ char *Px
+ ){
+ char *record;
+ int irecsize;
+ int cbImage,cbImage4,cbBmi,off;
+
+ SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
+
+ irecsize = sizeof(U_EMRSTRETCHDIBITS) + cbBmi + cbImage4;
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_STRETCHDIBITS;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRSTRETCHDIBITS) record)->rclBounds = rclBounds;
+ ((PU_EMRSTRETCHDIBITS) record)->Dest = Dest;
+ ((PU_EMRSTRETCHDIBITS) record)->Src = Src;
+ ((PU_EMRSTRETCHDIBITS) record)->cSrc = cSrc;
+ ((PU_EMRSTRETCHDIBITS) record)->iUsageSrc = iUsageSrc;
+ ((PU_EMRSTRETCHDIBITS) record)->dwRop = dwRop;
+ ((PU_EMRSTRETCHDIBITS) record)->cDest = cDest;
+ off = sizeof(U_EMRSTRETCHDIBITS);
+ APPEND_PXBMISRC(record, U_EMRSTRETCHDIBITS, cbBmi, Bmi, Px, cbImage, cbImage4);
+ }
+ return(record);
+}
+
+// U_EMREXTCREATEFONTINDIRECTW_set 82
+/**
+ \brief Allocate and construct a U_EMR_EXTCREATEFONTINDIRECTW record.
+ Use extcreatefontindirectw_set() instead of calling this function directly.
+ \return pointer to U_EMR_EXTCREATEFONTINDIRECTW record, or NULL on error.
+ \param ihFont Index of the font in the EMF object table
+ \param elf Font parameters as U_LOGFONT
+ \param elfw Font parameters as U_LOGFONT_PANOSE
+*/
+char *U_EMREXTCREATEFONTINDIRECTW_set(
+ const uint32_t ihFont,
+ const char * elf,
+ const char * elfw
+ ){
+ char *record;
+ const char *cptr;
+ int irecsize;
+ int cbLf,off;
+
+ if((elf && elfw) || (!elf && !elfw))return(NULL); // ONE only must be passed
+ if(elf){ cbLf = sizeof(U_LOGFONT); cptr = elf; }
+ else { cbLf = sizeof(U_LOGFONT_PANOSE); cptr = elfw; }
+
+ irecsize = sizeof(U_EMR) + sizeof(uint32_t) + cbLf;
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_EXTCREATEFONTINDIRECTW;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMREXTCREATEFONTINDIRECTW) record)->ihFont = ihFont;
+ off = sizeof(U_EMR) + sizeof(uint32_t);
+ memcpy(record + off, cptr, cbLf); // No need to add padding for either structure
+ }
+ return(record);
+}
+
+// U_EMREXTTEXTOUTA_set 83
+/**
+ \brief Allocate and construct a U_EMR_EXTTEXTOUTA record.
+ \return pointer to U_EMR_EXTTEXTOUTA record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param iGraphicsMode Graphics mode Enumeration
+ \param exScale scale to 0.01 mm units ( only if iGraphicsMode & GM_COMPATIBLE)
+ \param eyScale scale to 0.01 mm units ( only if iGraphicsMode & GM_COMPATIBLE)
+ \param emrtext Text parameters
+*/
+char *U_EMREXTTEXTOUTA_set(
+ const U_RECTL rclBounds,
+ const uint32_t iGraphicsMode,
+ const U_FLOAT exScale,
+ const U_FLOAT eyScale,
+ const PU_EMRTEXT emrtext
+ ){
+ return(U_EMR_CORE8_set(U_EMR_EXTTEXTOUTA,rclBounds, iGraphicsMode, exScale, eyScale,emrtext));
+}
+
+// U_EMREXTTEXTOUTW_set 84
+/**
+ \brief Allocate and construct a U_EMR_EXTTEXTOUTW record.
+ \return pointer to U_EMR_EXTTEXTOUTW record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param iGraphicsMode Graphics mode Enumeration
+ \param exScale scale to 0.01 mm units ( only if iGraphicsMode & GM_COMPATIBLE)
+ \param eyScale scale to 0.01 mm units ( only if iGraphicsMode & GM_COMPATIBLE)
+ \param emrtext Text parameters
+*/
+char *U_EMREXTTEXTOUTW_set(
+ const U_RECTL rclBounds,
+ const uint32_t iGraphicsMode,
+ const U_FLOAT exScale,
+ const U_FLOAT eyScale,
+ const PU_EMRTEXT emrtext
+ ){
+ return(U_EMR_CORE8_set(U_EMR_EXTTEXTOUTW,rclBounds, iGraphicsMode, exScale, eyScale,emrtext));
+}
+
+// U_EMRPOLYBEZIER16_set 85
+/**
+ \brief Allocate and construct a U_EMR_POLYBEZIER16 record.
+ \return pointer to U_EMR_POLYBEZIER16 record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param cpts Number of POINT16 in array
+ \param points Array of POINT16
+*/
+char *U_EMRPOLYBEZIER16_set(
+ const U_RECTL rclBounds,
+ const uint32_t cpts,
+ const U_POINT16 *points
+ ){
+ return(U_EMR_CORE6_set(U_EMR_POLYBEZIER16, rclBounds, cpts, points));
+}
+
+// U_EMRPOLYGON16_set 86
+/**
+ \brief Allocate and construct a U_EMR_POLYGON16 record.
+ \return pointer to U_EMR_POLYGON16 record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param cpts Number of POINT16 in array
+ \param points Array of POINT16
+*/
+char *U_EMRPOLYGON16_set(
+ const U_RECTL rclBounds,
+ const uint32_t cpts,
+ const U_POINT16 *points
+ ){
+ return(U_EMR_CORE6_set(U_EMR_POLYGON16, rclBounds, cpts, points));
+}
+
+// U_EMRPOLYLINE16_set 87
+/**
+ \brief Allocate and construct a U_EMR_POLYLINE16 record.
+ \return pointer to U_EMR_POLYLINE16 record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param cpts Number of POINT16 in array
+ \param points Array of POINT16
+*/
+char *U_EMRPOLYLINE16_set(
+ const U_RECTL rclBounds,
+ const uint32_t cpts,
+ const U_POINT16 *points
+ ){
+ return(U_EMR_CORE6_set(U_EMR_POLYLINE16, rclBounds, cpts, points));
+}
+
+// U_EMRPOLYBEZIERTO16_set 88
+/**
+ \brief Allocate and construct a U_EMR_POLYBEZIERTO record.
+ \return pointer to U_EMR_POLYBEZIERTO record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param cpts Number of POINT16 in array
+ \param points Array of POINT16
+*/
+char *U_EMRPOLYBEZIERTO16_set(
+ const U_RECTL rclBounds,
+ const uint32_t cpts,
+ const U_POINT16 *points
+ ){
+ return(U_EMR_CORE6_set(U_EMR_POLYBEZIERTO16, rclBounds, cpts, points));
+}
+
+// U_EMRPOLYLINETO16_set 89
+/**
+ \brief Allocate and construct a U_EMR_POLYLINETO record.
+ \return pointer to U_EMR_POLYLINETO record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param cpts Number of POINT16 in array
+ \param points Array of POINT16
+*/
+char *U_EMRPOLYLINETO16_set(
+ const U_RECTL rclBounds,
+ const uint32_t cpts,
+ const U_POINT16 *points
+ ){
+ return(U_EMR_CORE6_set(U_EMR_POLYLINETO16, rclBounds, cpts, points));
+}
+
+// U_EMRPOLYPOLYLINE16_set 90
+/**
+ \brief Allocate and construct a U_EMR_POLYPOLYLINE16 record.
+ \return pointer to U_EMR_POLYPOLYLINE16 record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param nPolys Number of elements in aPolyCounts
+ \param aPolyCounts Number of points in each poly (sequential)
+ \param cpts Number of POINT16 in array
+ \param points Array of POINT16
+*/
+char *U_EMRPOLYPOLYLINE16_set(
+ const U_RECTL rclBounds,
+ const uint32_t nPolys,
+ const uint32_t *aPolyCounts,
+ const uint32_t cpts,
+ const U_POINT16 *points
+ ){
+ return(U_EMR_CORE10_set(U_EMR_POLYPOLYLINE16, rclBounds, nPolys, aPolyCounts,cpts, points));
+}
+
+// U_EMRPOLYPOLYGON16_set 91
+/**
+ \brief Allocate and construct a U_EMR_POLYPOLYGON16 record.
+ \return pointer to U_EMR_POLYPOLYGON16 record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param nPolys Number of elements in aPolyCounts
+ \param aPolyCounts Number of points in each poly (sequential)
+ \param cpts Number of POINT16 in array
+ \param points Array of POINT16
+*/
+char *U_EMRPOLYPOLYGON16_set(
+ const U_RECTL rclBounds,
+ const uint32_t nPolys,
+ const uint32_t *aPolyCounts,
+ const uint32_t cpts,
+ const U_POINT16 *points
+ ){
+ return(U_EMR_CORE10_set(U_EMR_POLYPOLYGON16, rclBounds, nPolys, aPolyCounts,cpts, points));
+}
+
+
+// U_EMRPOLYDRAW16_set 92
+/**
+ \brief Allocate and construct a U_EMR_POLYDRAW16 record.
+ \return pointer to U_EMR_POLYDRAW16 record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param cpts Number of U_POINTL objects
+ \param aptl Array of U_POINTL objects
+ \param abTypes Array of Point Enumeration
+*/
+char *U_EMRPOLYDRAW16_set(
+ const U_RECTL rclBounds,
+ const U_NUM_POINT16 cpts,
+ const U_POINT16 *aptl,
+ const uint8_t *abTypes
+ ){
+ char *record;
+ int irecsize;
+ int cbPoints, cbAbTypes, cbAbTypes4, off;
+
+ if(!cpts || !aptl || !abTypes)return(NULL);
+ cbPoints = cpts * sizeof(U_POINT16); // space for aptl
+ cbAbTypes = cpts; // number of abTypes (same array size, 1 byte each)
+ cbAbTypes4 = UP4(cbAbTypes); // space for abTypes
+ irecsize = sizeof(U_EMRPOLYDRAW16) + cbPoints + cbAbTypes4 - sizeof(U_POINT16) - 1;
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_POLYDRAW16;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRPOLYDRAW16) record)->rclBounds = rclBounds;
+ ((PU_EMRPOLYDRAW16) record)->cpts = cpts;
+ off = sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(uint32_t); // offset to first variable part
+ memcpy(record+off,aptl,cbPoints);
+ off += cbPoints;
+ memcpy(record+off,abTypes,cbAbTypes);
+ off += cbAbTypes;
+ if(cbAbTypes4 > cbAbTypes){ memset(record+off,0,cbAbTypes4-cbAbTypes); } // keeps valgrind happy (initialize padding after byte array)
+ }
+ return(record);
+}
+
+// U_EMRCREATEMONOBRUSH_set 93
+/**
+ \brief Allocate and construct a U_EMR_CREATEMONOBRUSH record.
+ \return pointer to U_EMR_CREATEMONOBRUSH record, or NULL on error.
+ \param ihBrush Index to place object in EMF object table (this entry must not yet exist)
+ \param iUsage DIBcolors Enumeration
+ \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO + pixel array)
+ \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
+ \param Px (Optional) bitmapbuffer (pixel array section )
+*/
+char *U_EMRCREATEMONOBRUSH_set(
+ const uint32_t ihBrush,
+ const uint32_t iUsage,
+ const PU_BITMAPINFO Bmi,
+ const uint32_t cbPx,
+ const char *Px
+ ){
+ return(U_EMR_CORE12_set(U_EMR_CREATEMONOBRUSH,ihBrush,iUsage,Bmi,cbPx,Px));
+}
+
+// U_EMRCREATEDIBPATTERNBRUSHPT_set 94
+/**
+ \brief Allocate and construct a U_EMR_CREATEDIBPATTERNBRUSHPT record.
+ Use createdibpatternbrushpt_set() instead of calling this function directly.
+ \return pointer to U_EMR_CREATEDIBPATTERNBRUSHPT record, or NULL on error.
+ \param ihBrush Index to place object in EMF object table (this entry must not yet exist)
+ \param iUsage DIBcolors Enumeration
+ \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO + pixel array)
+ \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
+ \param Px (Optional) bitmapbuffer (pixel array section )
+*/
+char *U_EMRCREATEDIBPATTERNBRUSHPT_set(
+ const uint32_t ihBrush,
+ const uint32_t iUsage,
+ const PU_BITMAPINFO Bmi,
+ const uint32_t cbPx,
+ const char *Px
+ ){
+ return(U_EMR_CORE12_set(U_EMR_CREATEDIBPATTERNBRUSHPT,ihBrush,iUsage,Bmi,cbPx,Px));
+}
+
+
+// U_EMREXTCREATEPEN_set 95
+/**
+ \brief Allocate and construct a U_EMR_EXTCREATEPEN record.
+ Use extcreatepen_set() instead of calling this function directly.
+ \return pointer to U_EMR_EXTCREATEPEN record, or NULL on error.
+ \param ihPen ihPen Index to place object in EMF object table (this entry must not yet exist)
+ \param Bmi Bmi bitmapbuffer
+ \param cbPx cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
+ \param Px Px pixel array (NULL if cbPx == 0)
+ \param elp elp Pen parameters (Size is Variable!!!!)
+*/
+char *U_EMREXTCREATEPEN_set(
+ const uint32_t ihPen,
+ const PU_BITMAPINFO Bmi,
+ const uint32_t cbPx,
+ char *Px,
+ const PU_EXTLOGPEN elp
+ ){
+ char *record;
+ int cbImage,cbImage4,cbBmi,off;
+ int irecsize,cbStyleArray,cbElp;
+
+ if(!elp)return(NULL);
+
+ SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
+
+ cbStyleArray = elp->elpNumEntries * sizeof(U_STYLEENTRY); // space actually used by penstyle entries
+ // EXTLOGPEN is already included in EMREXTCREATEPEN, including the possibly unused first penstyle entry
+ if(cbStyleArray){
+ cbElp = sizeof(U_EXTLOGPEN) + cbStyleArray - sizeof(U_STYLEENTRY); // space actually used by elp
+ irecsize = sizeof(U_EMREXTCREATEPEN) + cbBmi + cbImage4 + cbStyleArray - sizeof(U_STYLEENTRY);
+ }
+ else {
+ cbElp = sizeof(U_EXTLOGPEN); // first U_STYLEENTRY is present but unused
+ irecsize = sizeof(U_EMREXTCREATEPEN) + cbBmi + cbImage4;
+ }
+ record = malloc(irecsize);
+
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_EXTCREATEPEN;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMREXTCREATEPEN) record)->ihPen = ihPen;
+ memcpy(&(((PU_EMREXTCREATEPEN) record)->elp),elp,cbElp);
+ if(cbStyleArray){
+ off = sizeof(U_EMREXTCREATEPEN) + cbStyleArray - sizeof(U_STYLEENTRY);
+ }
+ else {
+ off = sizeof(U_EMREXTCREATEPEN);
+ }
+ // Cannot use APPEND_PXBMISRC here because there is no "Src" in the field names
+ if(cbBmi){
+ memcpy(record + off, Bmi, cbBmi);
+ ((PU_EMREXTCREATEPEN) record)->offBmi = off;
+ ((PU_EMREXTCREATEPEN) record)->cbBmi = cbBmi;
+ off += cbBmi;
+ memcpy(record + off, Px, cbImage);
+ ((PU_EMREXTCREATEPEN) record)->offBits = off;
+ ((PU_EMREXTCREATEPEN) record)->cbBits = cbImage;
+ off += cbImage;
+ if(cbImage4 - cbImage){ memset(record + off, 0, cbImage4 - cbImage); }
+ }
+ else {
+ ((PU_EMREXTCREATEPEN) record)->cbBmi = 0;
+ ((PU_EMREXTCREATEPEN) record)->offBmi = 0;
+ ((PU_EMREXTCREATEPEN) record)->cbBits = 0;
+ ((PU_EMREXTCREATEPEN) record)->offBits = 0;
+ }
+ }
+ return(record);
+}
+
+// U_EMRPOLYTEXTOUTA_set 96 NOT IMPLEMENTED, denigrated after Windows NT
+// U_EMRPOLYTEXTOUTW_set 97 NOT IMPLEMENTED, denigrated after Windows NT
+
+// U_EMRSETICMMODE_set 98
+/**
+ \brief Allocate and construct a U_EMR_SETICMMODE record.
+ \return pointer to U_EMR_SETICMMODE record, or NULL on error.
+ \param iMode ICMMode Enumeration
+*/
+char *U_EMRSETICMMODE_set(
+ const uint32_t iMode
+ ){
+ return(U_EMR_CORE3_set(U_EMR_SETICMMODE, iMode));
+}
+
+// U_EMRCREATECOLORSPACE_set 99
+/**
+ \brief Allocate and construct a U_EMR_CREATECOLORSPACE record.
+ Use createcolorspace_set() instead of calling this function directly.
+ \return pointer to U_EMR_CREATECOLORSPACE record, or NULL on error.
+ \param ihCS Index to place object in EMF object table (this entry must not yet exist)
+ \param lcs ColorSpace parameters
+*/
+char *U_EMRCREATECOLORSPACE_set(
+ const uint32_t ihCS,
+ const U_LOGCOLORSPACEA lcs
+ ){
+ char *record;
+ int irecsize;
+
+ irecsize = sizeof(U_EMRCREATECOLORSPACE);
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_CREATECOLORSPACE;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRCREATECOLORSPACE) record)->ihCS = ihCS;
+ ((PU_EMRCREATECOLORSPACE) record)->lcs = lcs;
+ }
+ return(record);
+}
+
+// U_EMRSETCOLORSPACE_set 100
+/**
+ \brief Allocate and construct a U_EMR_SETCOLORSPACE record.
+ \return pointer to U_EMR_SETCOLORSPACE record, or NULL on error.
+ \param ihCS Index of object in EMF object table
+*/
+char *U_EMRSETCOLORSPACE_set(
+ const uint32_t ihCS
+ ){
+ return(U_EMR_CORE3_set(U_EMR_SETCOLORSPACE, ihCS));
+}
+
+// U_EMRDELETECOLORSPACE_set 101
+/**
+ \brief Allocate and construct a U_EMR_DELETECOLORSPACE record.
+ \return pointer to U_EMR_DELETECOLORSPACE record, or NULL on error.
+ \param ihCS Index of object in EMF object table
+*/
+char *U_EMRDELETECOLORSPACE_set(
+ const uint32_t ihCS
+ ){
+ return(U_EMR_CORE3_set(U_EMR_DELETECOLORSPACE, ihCS));
+}
+
+// U_EMRGLSRECORD_set 102 Not implemented
+// U_EMRGLSBOUNDEDRECORD_set 103 Not implemented
+// U_EMRPIXELFORMAT_set 104
+/**
+ \brief Allocate and construct a U_EMR_PIXELFORMAT record.
+ \return pointer to U_EMR_PIXELFORMAT record, or NULL on error.
+ \param pfd PixelFormatDescriptor
+*/
+char *U_EMRPIXELFORMAT_set(
+ const U_PIXELFORMATDESCRIPTOR pfd
+ ){
+ char *record;
+ int irecsize;
+
+ irecsize = sizeof(U_EMRPIXELFORMAT);
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_PIXELFORMAT;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRPIXELFORMAT) record)->pfd = pfd;
+ }
+ return(record);
+}
+// U_EMRDRAWESCAPE_set 105 Not implemented
+// U_EMREXTESCAPE_set 106 Not implemented
+// U_EMRUNDEF107_set 107 Not implemented
+
+// U_EMRSMALLTEXTOUT_set 108
+/**
+ \brief Allocate and construct a U_EMR_SMALLTEXTOUT record.
+ \return pointer to U_EMR_SMALLTEXTOUT record, or NULL on error.
+ \param Dest Where to draw the text
+ \param cChars Characters in TextString (not null terminated)
+ \param fuOptions ExtTextOutOptions Enumeration
+ \param iGraphicsMode GraphicsMode Enumeration
+ \param exScale scale on X axis
+ \param eyScale scale on Y axis
+ \param rclBounds OPTIONAL Bounding rectangle (absent when: fuOPtions & ETO_NO_U_RECT)
+ \param TextString text to output (fuOptions & ETO_SMALL_CHARS ? 8 bit : 16 bit)
+*/
+char *U_EMRSMALLTEXTOUT_set(
+ const U_POINTL Dest,
+ const U_NUM_STR cChars,
+ const uint32_t fuOptions,
+ const uint32_t iGraphicsMode,
+ const U_FLOAT exScale,
+ const U_FLOAT eyScale,
+ const U_RECTL rclBounds,
+ const char *TextString
+ ){
+ char *record;
+ int irecsize,cbString,cbString4,cbRectl,off;
+ int csize;
+
+ if( fuOptions & U_ETO_SMALL_CHARS ){ csize = 1; } // how many bytes per character
+ else { csize = 2; }
+ cbString = csize * cChars; // filled contents of the string buffer
+ cbString4 = UP4(cbString); // size of the variable string buffer
+ if(fuOptions & U_ETO_NO_RECT){ cbRectl = 0; } // size of the optional U_RECTL field
+ else { cbRectl = sizeof(U_RECTL); }
+
+ irecsize = sizeof(U_EMRSMALLTEXTOUT) + cbString4 + cbRectl;
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_SMALLTEXTOUT;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRSMALLTEXTOUT) record)->Dest = Dest;
+ ((PU_EMRSMALLTEXTOUT) record)->cChars = cChars;
+ ((PU_EMRSMALLTEXTOUT) record)->fuOptions = fuOptions;
+ ((PU_EMRSMALLTEXTOUT) record)->iGraphicsMode = iGraphicsMode;
+ ((PU_EMRSMALLTEXTOUT) record)->exScale = exScale;
+ ((PU_EMRSMALLTEXTOUT) record)->eyScale = eyScale;
+ off = sizeof(U_EMRSMALLTEXTOUT); //offset to the start of the variable fields
+ if(cbRectl){
+ memcpy(record + off, &rclBounds, cbRectl);
+ off += cbRectl;
+ }
+ memcpy(record + off, TextString, cbString);
+ if(cbString < cbString4){
+ off += cbString;
+ memset(record + off, 0, cbString4 - cbString);
+ }
+ }
+ return(record);
+}
+
+// U_EMRFORCEUFIMAPPING_set 109 Not implemented
+// U_EMRNAMEDESCAPE_set 110 Not implemented
+// U_EMRCOLORCORRECTPALETTE_set 111 Not implemented
+// U_EMRSETICMPROFILEA_set 112 Not implemented
+// U_EMRSETICMPROFILEW_set 113 Not implemented
+
+// U_EMRALPHABLEND_set 114
+/**
+ \brief Allocate and construct a U_EMR_ALPHABLEND record.
+ \return pointer to U_EMR_ALPHABLEND record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param Dest Destination UL corner in logical units
+ \param cDest Destination width in logical units
+ \param Src Source UL corner in logical units
+ \param cSrc Src W & H in logical units
+ \param xformSrc Transform to apply to source
+ \param crBkColorSrc Background color
+ \param iUsageSrc DIBcolors Enumeration
+ \param Blend Blend function
+ \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section)
+ \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
+ \param Px (Optional) bitmapbuffer (pixel array section )
+*/
+char *U_EMRALPHABLEND_set(
+ const U_RECTL rclBounds,
+ const U_POINTL Dest,
+ const U_POINTL cDest,
+ const U_POINTL Src,
+ const U_POINTL cSrc,
+ const U_XFORM xformSrc,
+ const U_COLORREF crBkColorSrc,
+ const uint32_t iUsageSrc,
+ const U_BLEND Blend,
+ const PU_BITMAPINFO Bmi,
+ const uint32_t cbPx,
+ char *Px
+ ){
+ return(U_EMR_CORE13_set(U_EMR_ALPHABLEND,rclBounds,Dest,cDest,Src,cSrc,xformSrc,crBkColorSrc,iUsageSrc,*((uint32_t *) &Blend),Bmi,cbPx,Px));
+}
+
+// U_EMRSETLAYOUT_set 115
+/**
+ \brief Allocate and construct a U_EMR_SETLAYOUT record.
+ \return pointer to U_EMR_SETLAYOUT record, or NULL on error.
+ \param iMode Mirroring Enumeration
+*/
+char *U_EMRSETLAYOUT_set(uint32_t iMode){
+ return(U_EMR_CORE3_set(U_EMR_SETLAYOUT, iMode));
+}
+
+// U_EMRTRANSPARENTBLT_set 116
+/**
+ \brief Allocate and construct a U_EMR_TRANSPARENTBLT record.
+ \return pointer to U_EMR_TRANSPARENTBLT record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param Dest Destination UL corner in logical units
+ \param cDest Destination width in logical units
+ \param Src Source UL corner in logical units
+ \param cSrc Src W & H in logical units
+ \param xformSrc Transform to apply to source
+ \param crBkColorSrc Background color
+ \param iUsageSrc DIBcolors Enumeration
+ \param TColor Bitmap color to be treated as transparent
+ \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section)
+ \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
+ \param Px (Optional) bitmapbuffer (pixel array section )
+*/
+char *U_EMRTRANSPARENTBLT_set(
+ const U_RECTL rclBounds,
+ const U_POINTL Dest,
+ const U_POINTL cDest,
+ const U_POINTL Src,
+ const U_POINTL cSrc,
+ const U_XFORM xformSrc,
+ const U_COLORREF crBkColorSrc,
+ const uint32_t iUsageSrc,
+ const uint32_t TColor,
+ const PU_BITMAPINFO Bmi,
+ const uint32_t cbPx,
+ char *Px
+ ){
+ return(U_EMR_CORE13_set(U_EMR_TRANSPARENTBLT,rclBounds,Dest,cDest,Src,cSrc,xformSrc,crBkColorSrc,iUsageSrc,TColor,Bmi,cbPx,Px));
+}
+// U_EMRUNDEF117_set 117 Not implemented
+// U_EMRGRADIENTFILL_set 118
+/**
+ \brief Allocate and construct a U_EMR_TRANSPARENTBLT record.
+ \return pointer to U_EMR_TRANSPARENTBLT record, or NULL on error.
+ \param rclBounds Bounding rectangle in device units
+ \param nTriVert Number of TriVertex objects in TriVert
+ \param nGradObj Number of gradient triangle/rectangle objects
+ \param ulMode Gradientfill Enumeration (determines Triangle/Rectangle)
+ \param TriVert Array of TriVertex objects
+ \param GradObj Array of gradient objects (each has 2 [rect] or 3 [triangle] indices into TriVert array)
+
+There is an MS documentation or library problem for this record, as the size of the GradObj must always be set
+as if it was an array of U_GRADIENT3 objects for both rect and triangle. For horizontal and vertical gradients
+this means that there will be unused bytes at the end of the record. This is not what the documentation says,
+but it is how MS's libraries work.
+
+*/
+char *U_EMRGRADIENTFILL_set(
+ const U_RECTL rclBounds,
+ const U_NUM_TRIVERTEX nTriVert,
+ const U_NUM_GRADOBJ nGradObj,
+ const uint32_t ulMode,
+ const PU_TRIVERTEX TriVert,
+ const uint32_t *GradObj
+ ){
+ char *record;
+ unsigned int cbTriVert,cbGradObj,off;
+ unsigned int cbGradObjAlloc; /* larger than cbGradObj, because of problem described above */
+ int irecsize;
+
+ cbTriVert = sizeof(U_TRIVERTEX) * nTriVert; // all of the cb's will be a multiple of 4 bytes
+ if( ulMode == U_GRADIENT_FILL_TRIANGLE){ cbGradObj = sizeof(U_GRADIENT3) * nGradObj; }
+ else if(ulMode == U_GRADIENT_FILL_RECT_H ||
+ ulMode == U_GRADIENT_FILL_RECT_V){ cbGradObj = sizeof(U_GRADIENT4) * nGradObj; }
+ else { return(NULL); }
+ cbGradObjAlloc = sizeof(U_GRADIENT3) * nGradObj;
+
+ irecsize = sizeof(U_EMRGRADIENTFILL) + cbTriVert + cbGradObjAlloc;
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_GRADIENTFILL;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRGRADIENTFILL) record)->rclBounds = rclBounds;
+ ((PU_EMRGRADIENTFILL) record)->nTriVert = nTriVert;
+ ((PU_EMRGRADIENTFILL) record)->nGradObj = nGradObj;
+ ((PU_EMRGRADIENTFILL) record)->ulMode = ulMode;
+ off = sizeof(U_EMRGRADIENTFILL); // offset to TriVert field
+ memcpy(record + off, TriVert, cbTriVert);
+ off += cbTriVert;
+ memcpy(record + off, GradObj, cbGradObj);
+ off += cbGradObj;
+ if(cbGradObjAlloc > cbGradObj){
+ memset(record+off,0,cbGradObjAlloc - cbGradObj);
+ }
+ }
+ return(record);
+}
+
+// U_EMRSETLINKEDUFIS_set 119 Not implemented
+// U_EMRSETTEXTJUSTIFICATION_set 120 Not implemented (denigrated)
+// U_EMRCOLORMATCHTOTARGETW_set 121 Not implemented
+
+// U_EMRCREATECOLORSPACEW_set 122
+/**
+ \brief Allocate and construct a U_EMR_CREATECOLORSPACEW record.
+ Use createcolorspacew_set() instead of calling this function directly.
+ \return pointer to U_EMR_CREATECOLORSPACEW record, or NULL on error.
+ \param ihCS Index to place object in EMF object table (this entry must not yet exist)
+ \param lcs ColorSpace parameters
+ \param dwFlags If low bit set Data is present
+ \param cbData Number of bytes of theData field.
+ \param Data (Optional, dwFlags & 1) color profile data
+*/
+char *U_EMRCREATECOLORSPACEW_set(
+ const uint32_t ihCS,
+ const U_LOGCOLORSPACEW lcs,
+ const uint32_t dwFlags,
+ const U_CBDATA cbData,
+ const uint8_t *Data
+ ){
+ char *record;
+ unsigned int cbData4,off;
+ int irecsize;
+
+ cbData4 = UP4(cbData); // buffer to hold Data
+ irecsize = sizeof(U_EMRCREATECOLORSPACEW) + cbData4;
+ record = malloc(irecsize);
+ if(record){
+ ((PU_EMR) record)->iType = U_EMR_CREATECOLORSPACEW;
+ ((PU_EMR) record)->nSize = irecsize;
+ ((PU_EMRCREATECOLORSPACEW) record)->ihCS = ihCS;
+ ((PU_EMRCREATECOLORSPACEW) record)->lcs = lcs;
+ ((PU_EMRCREATECOLORSPACEW) record)->dwFlags = dwFlags;
+ ((PU_EMRCREATECOLORSPACEW) record)->cbData = cbData;
+ off = sizeof(U_EMR) + sizeof(uint32_t) + sizeof(U_LOGCOLORSPACEW) + sizeof(uint32_t) + sizeof(U_CBDATA); // offset to Data field
+ memcpy(record + off, Data, cbData);
+ if(cbData < cbData4){
+ off += cbData;
+ memset(record + off,0,cbData4-cbData);
+ }
+ }
+ return(record);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/3rdparty/libuemf/uemf.h b/src/3rdparty/libuemf/uemf.h
new file mode 100644
index 0000000..3a51e39
--- /dev/null
+++ b/src/3rdparty/libuemf/uemf.h
@@ -0,0 +1,3653 @@
+/**
+ @file uemf.h
+
+ @brief Structures, definitions, and function prototypes for EMF files.
+
+ EMF file Record structure information has been derived from Mingw, Wine, and libEMF header files, and from
+ Microsoft's EMF Information pdf, release date March 28,2012, link from here:
+
+ http://msdn2.microsoft.com/en-us/library/cc230514.aspx
+
+ If the direct link fails the document may be found
+ by searching for: "[MS-EMF]: Enhanced Metafile Format"
+
+*/
+
+/** \mainpage libUEMF overview
+\section ov Overview
+Microsoft's WMF, EMF, and EMF+ metafile types are supported. In each case functions are provided for reading, constructing, writing, and printing
+metafile records. The methods used to do that differ somewhat between metafiles, and the simplest
+way to get started is to have a look at the example programs provided. The WMF, EMF, and EMF+ structs and functions are
+marked with U_WMF, U_EMF, U_PMF and U_WMR, U_EMR, and U_PMR prefixes. (PMF because "+" is a reserved character
+in many contexts, so U_EMF+NAME would be a problem.) Please be aware that normally both EMF and EMF+ files have the ".emf"
+file extension, and that it is very common for such files to contain both an EMF and an EMF+ representation of the
+drawing.
+
+\section example_sec Example Programs
+testbed_emf.c Creates an EMF file test_libuemf.emf.\n
+testbed_wmf.c Creates a WMF file test_libuemf.wmf.\n
+testbed_pmf.c Creates an EMF+ file test_libuemf_p.emf.\n
+reademf.c Reads an EMF or EMF+ file and emits a text summary of its records.\n
+readwmf.c Reads a WMF file and emits a text summary of its records.\n
+emf-inout.cpp.example Example code from Inkscape to convert graphics from EMF to SVG.\n
+emf-print.cpp.example Example code from Inkscape to print a drawing to EMF.\n
+wmf-inout.cpp.example Example code from Inkscape to convert graphics from WMF to SVG.\n
+wmf-print.cpp.example Example code from Inkscape to print a drawing to WMF.
+
+\section doxy_limits Documentation issues
+There are currently some unresolved issues with Doxygen that result in some structs
+not being "defined". This comes up when several different types of structs have the same
+layout. When this occurs the first one listed on the "typedef struct" is defined but all the
+others will only be shown under "typedef struct" referring to the first one. This is why
+clicking on U_RECTL in a function parameter jumps to a typedef struct page, why U_RECTL is shown
+as plain text here, but U_RECT is shown as a link here, and clicking on it jumps directly
+to its structure definition.
+
+An additional issue is that the Enumeration names used in WMF are different from those
+used in EMF, even when the values are either identical or differ only slightly, and no method
+has been found yet to link one to the other in Doxygen. At present the only way to look up
+these WMF enumerations is by referencing the following table:
+
+ EMF WMF WMF Manual
+ EMF Binary Raster Operation Enumeration BinaryRasterOperation Enumeration 2.1.1.2
+ EMF Bitcount Enumeration BitCount Enumeration 2.1.1.3
+ EMF LB_Style Enumeration BrushStyle Enumeration 2.1.1.4
+ EMF LF_CharSet Enumeration CharacterSet Enumeration 2.1.1.5
+ EMF DIBColors Enumeration ColorUsage Enumeration [has 1 extra value] 2.1.1.6
+ EMF BI_Compression Enumeration Compression Enumeration [has 3 extra values] 2.1.1.7
+ - FamilyFont Enumeration 2.1.1.8
+ EMF FloodFill Enumeration FloodFill Enumeration 2.1.1.9
+ EMF LF_Quality Enumeration FontQuality Enumeration 2.1.1.10
+ EMF LCS_Intent Enumeration GamutMappingIntent Enumeration 2.1.1.11
+ EMF HatchStyle Enumeration HatchStyle Enumeration 2.1.1.12
+ EMF Mirroring Enumeration LayoutEnumeration 2.1.1.13
+ - LogicalColorSpace Enumeration 2.1.1.14
+ EMF Profile Enumeration LogicalColorSpaceV5 Enumeration 2.1.1.15
+ EMF MapMode Enumeration MapModeEnumeration 2.1.1.16
+ - MetaFilesEscape Enumeration 2.1.1.17
+ - MetafileType Enumeration 2.1.1.18
+ - MetafileVersion Enumeration 2.1.1.19
+ EMF BackgroundMode Enumeration MixModeEnumeration 2.1.1.20
+ EMF LF_OutPrecision Enumeration OutPrecision Enumeration 2.1.1.21
+ - PaletteEntryFlag Enumeration 2.1.1.22
+ EMF PenStyle Enumeration PenStyle Enumeration [not values >0xFFFF] 2.1.1.23
+ - PitchFont Enumeration 2.1.1.24
+ EMF PolygonFillMode Enumeration PolyFillMode Enumeration [first 2 only] 2.1.1.25
+ - PostScriptCap Enumeration 2.1.1.26
+ - PostScriptClipping Enumeration 2.1.1.27
+ - PostFeatureSetting Enumeration 2.1.1.28
+ - PostScrioptJoin Enumeration 2.1.1.29
+ EMF StretchMode Enumeration StretchMode Enumeration 2.1.1.30
+ EMF Ternary Raster Operation Enumeration TernaryRasterOperation Enumeration 2.1.1.31
+ EMF LF_ClipPrecision Enumeration ClipPrecision Flags 2.1.2.1
+ EMF ExtTextOutOptions Enumeration ExtTextOutOptions Flags [subset] 2.1.2.2
+ EMF TextAlignment Enumeration TextAlignment Enumeration 2.1.2.3
+ EMF TextAlignment Enumeration VertialTextAlignment Enumeration 2.1.2.4
+ EMF LF_PitchAndFamily Enumeration PitchAndFamily Enumerations 2.2.2.14
+
+\section refs Reference documentation
+
+ Manual Date Link
+ EMF 3/28/2012 http://msdn2.microsoft.com/en-us/library/cc230514.aspx
+ EMF+ 7/5/2012 http://msdn.microsoft.com/en-us/library/cc230724.aspx
+ WMF 7/5/2012 http://msdn2.microsoft.com/en-us/library/cc250370.aspx
+*/
+
+/*
+File: uemf.h
+Version: 0.0.34
+Date: 03-JAN-2017
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2017 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifndef _UEMF_
+#define _UEMF_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include "uemf_utf.h"
+#include "uemf_endian.h"
+
+
+/** \cond */
+// ***********************************************************************************
+// defines not placed yet
+
+#define U_PAN_CULTURE_LATIN 0
+
+#define U_SYSPAL_ERROR 0
+#define U_SYSPAL_STATIC 1
+#define U_SYSPAL_NOSTATIC 2
+
+#define U_ELF_VENDOR_SIZE 4
+
+#define UNUSED_PARAMETER(x) (void)(x)
+/** \endcond */
+
+// ***************************************************************************
+/** \defgroup U_EMF_Miscellaneous_values EMF Miscellaneous Values
+ @{
+*/
+#define U_NONE 0 //!< Generic for nothing selected for all flag fields
+#define U_PI 3.14159265358979323846 //!< pi
+#define U_READ 1 //!< open file as "rb"
+#define U_WRITE 0 //!< open file as "wb"
+#define U_DV_SGNTR 0x08007664 //!< For U_DESIGNVECTOR Signature field
+#define U_LP_VERSION 0x0300 //!< For U_LOGPALETTE palVersion field
+#define U_RDH_RECTANGLES 1 //!< For U_RGNDATAHEADER iType field
+#define U_RDH_OBJSIZE 0x20 //!< For U_RGNDATAHEADER dwSIze field
+#define U_RGB_GAMMA_MIN (uint16_t)02500 //!< For U_COLORADJUSTMENT ca[Red|Green|Blue]Gamma fields
+#define U_RGB_GAMMA_MAX (uint16_t)65000 //!< For U_COLORADJUSTMENT ca[Red|Green|Blue]Gamma fields
+#define U_REFERENCE_WHITE_MIN (uint16_t)6000 //!< For U_COLORADJUSTMENT caReferenceWhite field
+#define U_REFERENCE_WHITE_MAX (uint16_t)10000 //!< For U_COLORADJUSTMENT caReferenceWhite field
+#define U_REFERENCE_BLACK_MIN (uint16_t)0 //!< For U_COLORADJUSTMENT caReferenceBlack field
+#define U_REFERENCE_BLACK_MAX (uint16_t)4000 //!< For U_COLORADJUSTMENT caReferenceBlack field
+#define U_COLOR_ADJ_MIN ((int16_t)-100) //!< For U_COLORADJUSTMENT ca[Contrast|Brightness|Colorfulness|RedGreenTint] fields
+#define U_COLOR_ADJ_MAX (int16_t) 100 //!< For U_COLORADJUSTMENT ca[Contrast|Brightness|Colorfulness|RedGreenTint] fields
+#define U_MAX_PATH 1024 //!< longest path name for a file
+#define U_LCS_SIGNATURE 0x50534F43 //!< logColorSpace Signature
+#define U_LCS_VERSION 0x400 //!< logColorSpace Version
+#define U_REC_FREE 1 //!< use with emf_append
+#define U_REC_KEEP 0 //!< use with emf_append
+#define U_ROW_ORDER_INVERT 1 //!< For RGBA_to_DIB, invert row order in DIB relative to pixel array
+#define U_ROW_ORDER_SAME 0 //!< For RGBA_to_DIB, same row order in DIB as in pixel array
+#define U_CT_NO 0 //!< For RGBA_to_DIB, do not use color table
+#define U_CT_BGRA 1 //!< For RGBA_to_DIB, use color table (16 bits or less only) BGRA colors, compatible with EMF+ ARGB
+#define U_CT_ARGB 1 //!< For RGBA_to_DIB, use color table (16 bits or less only) BGRA colors, compatible with EMF+ ARGB
+#define U_EMR_COMMENT_SPOOLFONTDEF 0x544F4E46 //!< For U_EMRCOMMENT record that is U_EMR_COMMENT_SPOOL, comment holds font definition informtion.
+/** Solaris 8 has problems with round/roundf, just use this everywhere */
+#define U_ROUND(A) ( (A) > 0 ? floor((A)+0.5) : ( (A) < 0 ? -floor(-(A)+0.5) : (A) ) )
+
+#define MAKE_MIN_PTR(A,B) ( A < B ? A : B)
+/* IS_MEM_UNSAFE takes 3 parameters:
+ A start address of a block of allocated memory
+ B offset into this block starting at A
+ C address of final byte of a block of allocated memory.
+ Returns
+ 1 if B cannot be an int or size_t
+ 1 if C > A
+ 1 if A+B is not in the range A to C, inclusive
+ 0 otherwise.
+ B may be an int, an unsigned int, or a size_t. An int can be negative,
+ which is obviously wrong, but testing for that means that the size
+ of B cannot be more than INT_MAX/2. Accept that limitation since
+ no reasonable EMF record or file should ever be that large.
+ If B is a uint16_t gcc complains about the first test.
+ This Macro must not be used where B needs more than 32 bits!
+*/
+#define IS_MEM_UNSAFE(A,B,C) ( (sizeof(B) < sizeof(int) || (int)(B) < 0) ? 1 : ((int8_t *)(A) > (int8_t *)(C) ? 1 : ((int8_t *)(C) - (int8_t *)(A) >= (int)(B) ? 0 : 1 ))) //!< Return 1 when a region of memory starting at A of B bytes extends beyond pointer C
+
+/** @} */
+
+
+typedef float U_FLOAT; //!< 32 bit float
+
+typedef uint32_t U_CBBITS; //!< Count of Bytes in object at corresponding U_OFF*
+typedef uint32_t U_CBBITSMSK; //!< Count of Bytes in object at corresponding U_OFF*
+typedef uint32_t U_CBBITSSRC; //!< Count of Bytes in object at corresponding U_OFF*
+typedef uint32_t U_CBBMI; //!< Count of Bytes in object at corresponding U_OFF*
+typedef uint32_t U_CBBMIMSK; //!< Count of Bytes in object at corresponding U_OFF*
+typedef uint32_t U_CBBMISRC; //!< Count of Bytes in object at corresponding U_OFF*
+typedef uint32_t U_CBDATA; //!< Count of Bytes in object at corresponding U_OFF*
+typedef uint32_t U_CBNAME; //!< Count of Bytes in object at corresponding U_OFF*
+typedef uint32_t U_CBPLENTRIES; //!< Count of Bytes in object at corresponding U_OFF*
+typedef uint32_t U_CBPXLFMT; //!< Count of Bytes in object at corresponding U_OFF*
+typedef uint32_t U_CBRGNDATA; //!< Count of Bytes in object at corresponding U_OFF*
+typedef uint32_t U_CBSTR; //!< Count of Bytes in an 8 or 16 bit string
+
+typedef uint32_t U_OFFBITS; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct)
+typedef uint32_t U_OFFBITSMSK; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct)
+typedef uint32_t U_OFFBITSSRC; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct)
+typedef uint32_t U_OFFBMI; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct)
+typedef uint32_t U_OFFBMIMSK; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct)
+typedef uint32_t U_OFFBMISRC; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct)
+typedef uint32_t U_OFFDATA; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct)
+typedef uint32_t U_OFFDESC; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct)
+typedef uint32_t U_OFFDX; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct)
+typedef uint32_t U_OFFPLENTRIES; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct)
+typedef uint32_t U_OFFPXLFMT; //!< Byte offset to TYPE, always measured from the start of the RECORD (not the struct)
+typedef uint32_t U_OFFSTR; //!< Byte offset to string of either 8 or 16 bit characters
+typedef uint8_t U_DATA; //!< any binary sort of data, not otherwise classified.
+
+// "Types" For array components in structures, where not otherwise defined as a structure
+typedef uint32_t U_FNTAXES; //!< Font Axes For U_DESIGNVECTOR
+typedef uint32_t U_STYLEENTRY; //!< StyleEntry For U_EXTLOGPEN
+typedef uint32_t U_POLYCOUNTS; //!< aPolyCounts For U_EMRPOLYPOLYLINE etc.
+
+// "Counts" for array components in structures
+typedef uint32_t U_NUM_FNTAXES; //!< Number of U_FNTAXES
+typedef uint32_t U_NUM_LOGPLTNTRY; //!< Number of U_LOGPLTENTRY
+typedef uint32_t U_NUM_RECTL; //!< Number of U_RECTL
+typedef uint32_t U_NUM_POINTL; //!< Number of U_POINTL
+typedef uint32_t U_NUM_POINT16; //!< Number of U_POINT16
+typedef uint32_t U_NUM_STYLEENTRY; //!< Number of U_STYLEENTRY
+typedef uint32_t U_NUM_POLYCOUNTS; //!< Number of U_POLYCOUNTS
+typedef uint32_t U_NUM_EMRTEXT; //!< Number of U_EMRTEXT
+typedef uint32_t U_NUM_STR; //!< Number of 8 or 16 bit characters in string
+typedef uint32_t U_NUM_TRIVERTEX; //!< Number of U_TRIVERTEX
+typedef uint32_t U_NUM_GRADOBJ; //!< Number of U_GRADIENT4 OR U_GRADIENT3 (determined at run time)
+typedef uint32_t U_NUM_RGBQUAD; //!< Number of U_RGBQUAD (in bmciColors in U_BITMAPCOREINFO)
+
+
+
+/* ************************ WMF pieces used in EMF or EMF+ ****************************** */
+
+/** \defgroup U_EMF_EMRSETROP2_iMode_Qualifiers EMF Binary Raster Operation Enumeration
+
+ For U_EMRSETROP2 iMode field
+ Microsoft name: Binary Raster Operation Enumeration
+ WMF manual 2.1.1.2
+
+ These codes specify:
+ 1. an order of operands (composed of various orders and combinations of: Dest, Pen)
+ (There are 2, hence "Binary Raster Operation")
+ 2. an order of operators to apply to the operands (composed of Not, Xor, Or, And)
+ Only a few of the more common operations are provided here.
+
+ The default is U_R2_COPYPEN. If this value is changed to something else all subsequenty
+ draw operations will use the altered logic. For instance, if it is set to U_R2_BLACK and
+ a red rectangle is drawn it will appear as a black rectangle.
+
+ @{
+*/
+#define U_R2_BLACK 1 //!< BLACK
+#define U_R2_NOTMERGEPEN 2 //!< NOTMERGEPEN
+#define U_R2_MASKNOTPEN 3 //!< MASKNOTPEN
+#define U_R2_NOTCOPYPEN 4 //!< NOTCOPYPEN
+#define U_R2_MASKPENNOT 5 //!< MASKPENNOT
+#define U_R2_NOT 6 //!< NOT
+#define U_R2_XORPEN 7 //!< XORPEN
+#define U_R2_NOTMASKPEN 8 //!< NOTMASKPEN
+#define U_R2_MASKPEN 9 //!< MASKPEN
+#define U_R2_NOTXORPEN 10 //!< NOTXORPEN
+#define U_R2_NOP 11 //!< NOP
+#define U_R2_MERGENOTPEN 12 //!< MERGENOTPEN
+#define U_R2_COPYPEN 13 //!< COPYPEN
+#define U_R2_MERGEPENNOT 14 //!< MERGEPENNOT
+#define U_R2_MERGEPEN 15 //!< MERGEPEN
+#define U_R2_WHITE 16 //!< WHITE
+#define U_R2_LAST 16 //!< LAST
+/** @} */
+
+/** \defgroup U_EMF_BITMAPINFOHEADER_biBitCount_Qualifiers EMF BitCount Enumeration
+ For U_BITMAPINFOHEADER biBitCount field.
+ Microsoft name: Bitcount Enumeration
+ WMF manual 2.1.1.3
+ @{
+*/
+#define U_BCBM_EXPLICIT 0 //!< Derived from JPG or PNG compressed image or ?
+#define U_BCBM_MONOCHROME 1 //!< 2 colors. bmiColors array has two entries
+#define U_BCBM_COLOR4 4 //!< 2^4 colors. bmiColors array has 16 entries
+#define U_BCBM_COLOR8 8 //!< 2^8 colors. bmiColors array has 256 entries
+#define U_BCBM_COLOR16 16 //!< 2^16 colors. bmiColors is not used. Pixels are 5 bits B,G,R with 1 unused bit
+#define U_BCBM_COLOR24 24 //!< 2^24 colors. bmiColors is not used. Pixels are U_RGBTRIPLE.
+#define U_BCBM_COLOR32 32 //!< 2^32 colors. bmiColors is not used. Pixels are U_RGBQUAD. Also use for EMF+ ARGB
+/** @} */
+
+/** \defgroup U_EMF_BITMAPINFOHEADER_biCompression_Qualifiers EMF BI_Compression Enumeration
+ For U_BITMAPINFOHEADER biCompression field
+ Microsoft name: Compression Enumeration
+ WMF manual 2.1.1.7
+ @{
+*/
+#define U_BI_UNKNOWN -1 //!< not defined in EMF standard, not to be used in EMF files
+#define U_BI_RGB 0 //!< Supported by libUEMF
+#define U_BI_RLE8 1 //!< NOT supported by libUEMF
+#define U_BI_RLE4 2 //!< NOT supported by libUEMF
+#define U_BI_BITFIELDS 3 //!< Supported by libUEMF
+#define U_BI_JPEG 4 //!< Supported by libUEMF
+#define U_BI_PNG 5 //!< Supported by libUEMF
+/** @} */
+
+/** \defgroup U_EMF_LOGCOLORSPACE_lcsIntent_Qualifiers EMF LCS_Intent Enumeration
+ For U_LOGCOLORSPACEA/U_LOGCOLORSPACEW lcsIntent field
+ Microsoft name: LCS_Intent Enumeration
+ WMF manual 2.1.1.11
+ @{
+*/
+#define U_LCS_GM_BUSINESS 0x00000001L //!< BUSINESS
+#define U_LCS_GM_GRAPHICS 0x00000002L //!< GRAPHICS
+#define U_LCS_GM_IMAGES 0x00000004L //!< IMAGES
+#define U_LCS_GM_ABS_COLORIMETRIC 0x00000008L //!< ABS_COLORIMETRIC
+/** @} */
+
+/** \defgroup U_EMF_LOGCOLORSPACE_lcsCSType_Qualifiers EMF LCS_CSType Enumeration
+ For U_LOGCOLORSPACEA/U_LOGCOLORSPACEW lcsCSType field
+ Microsoft name: LCS_CSType Enumeration
+ WMF manual 2.1.1.14
+ @{
+*/
+#define U_LCS_CALIBRATED_RGB 0x00000000L //!< CALIBRATED_RGB
+#define U_LCS_DEVICE_RGB 0x00000001L //!< DEVICE_RGB
+#define U_LCS_DEVICE_CMYK 0x00000002L //!< DEVICE_CMYK
+/** @} */
+
+/** \defgroup U_EMF_EMR_dwROP_Qualifiers EMF Ternary Raster Operation enumeration
+
+ For U_EMR* dwROP fields.
+ Microsoft name: Ternary Raster Operation enumeration
+ WMF manual 2.1.1.31
+
+ These codes specify:
+ 1. an order of operands (composed of various orders and combinations of: Dest, Src, Pen)
+ (There are 3, hence "Ternary Raster Operation")
+ 2. an order of operators to apply to the operands (composed of Not, Xor, Or, And)
+ Only a few of the more common operations are provided here.
+ When the Operation does not use a Src operand the corresponding source bitmap may be
+ omitted from the record.
+
+ For more details see:
+ http://wiki.winehq.org/TernaryRasterOps
+
+
+ @{
+*/
+#define U_SRCCOPY 0x00cc0020 //!< SRCCOPY
+#define U_SRCPAINT 0x00ee0086 //!< SRCPAINT
+#define U_SRCAND 0x008800c6 //!< SRCAND
+#define U_SRCINVERT 0x00660046 //!< SRCINVERT
+#define U_SRCERASE 0x00440328 //!< SRCERASE
+#define U_NOTSRCCOPY 0x00330008 //!< NOTSRCCOPY
+#define U_NOTSRCERASE 0x001100a6 //!< NOTSRCERASE
+#define U_MERGECOPY 0x00c000ca //!< MERGECOPY
+#define U_MERGEPAINT 0x00bb0226 //!< MERGEPAINT
+#define U_PATCOPY 0x00f00021 //!< PATCOPY
+#define U_PATPAINT 0x00fb0a09 //!< PATPAINT
+#define U_PATINVERT 0x005a0049 //!< PATINVERT
+#define U_DSTINVERT 0x00550009 //!< DSTINVERT
+#define U_BLACKNESS 0x00000042 //!< BLACKNESS
+#define U_WHITENESS 0x00ff0062 //!< WHITENESS
+#define U_NOOP 0x00aa0029 //!< Many GDI programs end with a bitblt with this ROP == "D". Seems to work like flush()
+#define U_NOMIRRORBITMAP 0x80000000 //!< If bit set, disable horizontal reflection of bitmap.
+/** @} */
+
+/** \defgroup U_EMF_EMRSETTEXTALIGN_iMode_Qualifiers EMF TextAlignment Enumeration
+ For U_EMRSETTEXTALIGN iMode field
+ Microsoft name: TextAlignment Enumeration
+ WMF Manual 2.1.2.3
+ WMF Manual 2.1.2.4
+
+ Recall that EMF coordinates have UL closest to {0,0}, LR is below and to the right of UL and so has LARGER
+ {x,y} coordinates. In the following "TOP" is on the horizontal line defined by LR, as it has larger y coordinates,
+ which when viewing the EMF file, would actually be on the BOTTOM of the bounding rectangle. Similarly, left and right
+ are reversed.
+
+ Microsoft documentation (WMF manual, section 2.1.2.3) says that the text starts on certain edges of the bounding rectangle.
+ That is apparently not true, whether the bounding rectangle is {0,0,-1,-1}, which is effectively no bounding rectangle,
+ or if a valid bounding rectangle is specified. In all cases the text (in Windows XP Preview) starts, has center at, or ends
+ at the center point. Vertical offsets seem to be defined analogously, but with respect to the height of the font. The bounding
+ rectangle defined for the U_EMRTEXT record appears to be ignored.
+
+ Microsoft documentation (EMF manual,section 2.2.5) says that the same rectangle is used for "clipping or opaquing" by ExtTextOutA/W.
+ That does not seem to occur either.
+
+ @{
+*/
+// Horizontal text flags
+#define U_TA_DEFAULT 0x00 //!< default alignment
+#define U_TA_NOUPDATECP 0x00 //!< Reference point does not move
+#define U_TA_UPDATECP 0x01 //!< Reference point moves to end of next text drawn.
+#define U_TA_LEFT 0x00 //!< Reference point is on left edge of bounding rectangle
+#define U_TA_RIGHT 0x02 //!< Reference point is on right edge of bounding rectangle
+#define U_TA_CENTER 0x06 //!< Reference point is on center vertical line of bounding rectangle
+#define U_TA_TOP 0x00 //!< Reference point is on top edge of bounding rectangle
+#define U_TA_BOTTOM 0x08 //!< Reference point is on bottom edge of bounding rectangle
+#define U_TA_BASEBIT 0x10 //!< Reference point is on baseline of text if this bit is set, for 0x10 <-> 0x18
+#define U_TA_BASELINE 0x18 //!< Reference point is on baseline of text
+#define U_TA_RTLREADING 0x100 //!< Set for Right to Left languages like Hebrew and Arabic
+#define U_TA_MASK U_TA_BASELINE+U_TA_CENTER+U_TA_UPDATECP+U_TA_RTLREADING //!< Mask for these bits
+// Vertical text flags
+#define U_VTA_BASELINE U_TA_BASELINE //!< same meaning, but for vertical text
+#define U_VTA_LEFT U_TA_BOTTOM //!< same meaning, but for vertical text
+#define U_VTA_RIGHT U_TA_TOP //!< same meaning, but for vertical text
+#define U_VTA_CENTER U_TA_CENTER //!< same meaning, but for vertical text
+#define U_VTA_BOTTOM U_TA_RIGHT //!< same meaning, but for vertical text
+#define U_VTA_TOP U_TA_LEFT //!< same meaning, but for vertical text
+/** @} */
+
+/** WMF manual 2.2.2.3
+ \brief For U_BITMAPINFO bmiHeader field
+
+ Microsoft name: BITMAPINFOHEADER Object
+*/
+typedef struct {
+ uint32_t biSize; //!< Structure size in bytes
+ int32_t biWidth; //!< Bitmap width in pixels
+ int32_t biHeight; //!< Bitmap height in pixels, may be negative.
+ //!< abs(biHeight) is bitmap height
+ //!< bitmap may appear in two orientations:
+ //!< biHeight > 0 origin is LL corner, may be compressed, this is height after decompression.
+ //!< biHeight < 0 origin is UL corner, may not be compressed
+ uint16_t biPlanes; //!< Planes (must be 1)
+ uint16_t biBitCount; //!< BitCount Enumeration (determines number of RBG colors)
+ uint32_t biCompression; //!< BI_Compression Enumeration
+ uint32_t biSizeImage; //!< Image size in bytes or 0 = "default size (calculated from geometry?)"
+ int32_t biXPelsPerMeter; //!< X Resolution in pixels/meter
+ int32_t biYPelsPerMeter; //!< Y Resolution in pixels/meter
+ U_NUM_RGBQUAD biClrUsed; //!< Number of bmciColors in U_BITMAPINFO/U_BITMAPCOREINFO that are used by the bitmap
+ uint32_t biClrImportant; //!< Number of bmciColors needed (0 means all).
+} U_BITMAPINFOHEADER,
+ *PU_BITMAPINFOHEADER; //!< WMF manual 2.2.2.3
+#define U_SIZE_BITMAPINFOHEADER (sizeof(U_BITMAPINFOHEADER))
+
+/** WMF manual 2.2.2.6
+ \brief For U_CIEXYZTRIPLE (all) fields
+
+ Microsoft name: CIEXYZ Object
+*/
+typedef struct {
+ int32_t ciexyzX; //!< CIE color space X component
+ int32_t ciexyzY; //!< CIE color space Y component
+ int32_t ciexyzZ; //!< CIE color space Z component
+} U_CIEXYZ,
+ *PU_CIEXYZ; //!< WMF manual 2.2.2.6
+
+/** WMF manual 2.2.2.7
+ \brief For U_LOGCOLORSPACEA and U_LOGCOLORSPACEW lcsEndpints field
+
+ defines a CIE colorspace.
+ Microsoft name: CIEXYZTRIPLE Object
+
+*/
+typedef struct {
+ U_CIEXYZ ciexyzRed; //!< CIE XYZ coord of red endpoint of colorspace
+ U_CIEXYZ ciexyzGreen; //!< CIE XYZ coord of green endpoint of colorspace
+ U_CIEXYZ ciexyzBlue; //!< CIE XYZ coord of blue endpoint of colorspace
+} U_CIEXYZTRIPLE,
+ *PU_CIEXYZTRIPLE; //!< WMF manual 2.2.2.7
+
+/** WMF manual 2.2.2.8
+ \brief For U_BITMAPINFO crColor field
+
+ NOTE that the color order is RGB reserved, flipped around from the preceding.
+ Microsoft name: COLORREF Object
+*/
+typedef struct {
+ uint8_t Red; //!< Red color (0-255)
+ uint8_t Green; //!< Green color (0-255)
+ uint8_t Blue; //!< Blue color (0-255)
+ uint8_t Reserved; //!< Not used
+} U_COLORREF,
+ *PU_COLORREF; //!< WMF manual 2.2.2.8
+
+/** WMF manual 2.2.2.11
+ \brief For U_LCS_GAMMARGB lcsGamma* fields
+
+ Microsoft name:(unknown)
+*/
+typedef struct {
+ unsigned ignoreHi :8; //!< not used
+ unsigned intPart :8; //!< integer part
+ unsigned fracPart :8; //!< fraction part
+ unsigned ignoreLo :8; //!< not used
+} U_LCS_GAMMA,
+ *PU_LCS_GAMMA; //!< WMF manual 2.2.2.11
+
+/** WMF manual 2.2.2.11
+ \brief For U_LOGCOLORSPACEA and U_LOGCOLORSPACEW lcsGammaRGB field
+
+ Microsoft name:(unknown)
+*/
+typedef struct {
+ U_LCS_GAMMA lcsGammaRed; //!< Red Gamma
+ U_LCS_GAMMA lcsGammaGreen; //!< Green Gamma
+ U_LCS_GAMMA lcsGammaBlue; //!< Blue Gamma
+} U_LCS_GAMMARGB,
+ *PU_LCS_GAMMARGB; //!< WMF manual 2.2.2.11
+
+/** WMF manual 2.2.2.11
+ \brief For U_EMRCREATECOLORSPACE lcs field
+
+ Microsoft name: LOGCOLORSPACEA Object
+*/
+typedef struct {
+ uint32_t lcsSignature; //!< must be U_LCS_SIGNATURE
+ uint32_t lcsVersion; //!< must be U_LCS_VERSION
+ uint32_t lcsSize; //!< Size in bytes of this structure
+ int32_t lcsCSType; //!< LCS_CSType Enumeration
+ int32_t lcsIntent; //!< LCS_Intent Enumeration
+ U_CIEXYZTRIPLE lcsEndpoints; //!< CIE XYZ color space endpoints
+ U_LCS_GAMMARGB lcsGammaRGB; //!< Gamma For RGB
+ char lcsFilename[U_MAX_PATH]; //!< Names an external color profile file, otherwise empty string
+} U_LOGCOLORSPACEA,
+ *PU_LOGCOLORSPACEA; //!< WMF manual 2.2.2.11
+
+/** WMF manual 2.2.2.12
+ \brief For U_EMRCREATECOLORSPACEW lcs field
+
+ Microsoft name: LOGCOLORSPACEW Object
+*/
+typedef struct {
+ uint32_t lcsSignature; //!< must be U_LCS_SIGNATURE
+ uint32_t lcsVersion; //!< must be U_LCS_VERSION
+ uint32_t lcsSize; //!< Size in bytes of this structure
+ int32_t lcsCSType; //!< lcsCSType Enumeration
+ int32_t lcsIntent; //!< lcsIntent Enumeration
+ U_CIEXYZTRIPLE lcsEndpoints; //!< CIE XYZ color space endpoints
+ U_LCS_GAMMARGB lcsGammaRGB; //!< Gamma For RGB
+ uint16_t lcsFilename[U_MAX_PATH]; //!< Could name an external color profile file, otherwise empty string
+} U_LOGCOLORSPACEW,
+ *PU_LOGCOLORSPACEW; //!< WMF manual 2.2.2.12
+
+/** WMF manual 2.2.2.15
+ \brief Used for any generic pair of uint32_t
+
+ Microsoft name: POINTL Object
+*/
+typedef struct {
+ int32_t x; //!< X value
+ int32_t y; //!< Y value
+} U_PAIR,
+ U_POINT, //!< WMF manual 2.2.2.15
+ U_POINTL, //!< WMF manual 2.2.2.15
+ *PU_PAIR, //!< WMF manual 2.2.2.15
+ *PU_POINT, //!< WMF manual 2.2.2.15
+ *PU_POINTL; //!< WMF manual 2.2.2.15
+
+
+/** WMF manual 2.2.2.16
+ \brief Point type for 16 bit EMR drawing functions.
+
+ Microsoft name: POINTS Object.
+ Microsoft name: POINTS16 Object.
+*/
+typedef struct {
+ int16_t x; //!< X size (16 bit)
+ int16_t y; //!< Y size (16 bit)
+} U_POINT16,
+ *PU_POINT16; //!< WMF manual 2.2.2.16
+
+/** WMF manual 2.2.2.19
+ \brief Coordinates of the upper left, lower right corner.
+
+ Note that the coordinate system is 0,0 in the upper left corner
+ of the screen an N,M in the lower right corner.
+ Microsoft name: RECTL Object
+*/
+typedef struct {
+ int32_t left; //!< left coordinate
+ int32_t top; //!< top coordinate
+ int32_t right; //!< right coordinate
+ int32_t bottom; //!< bottom coordinate
+} U_RECT,
+ U_RECTL, //!< WMF manual 2.2.2.19
+ *PU_RECT, //!< WMF manual 2.2.2.19
+ *PU_RECTL; //!< WMF manual 2.2.2.19
+
+/** WMF manual 2.2.2.20
+ \brief For U_BITMAPINFO bmiColors field
+
+ NOTE that the color order is BGR, even though the name is RGB!
+ Microsoft name: RGBQUAD Object
+*/
+typedef struct {
+ uint8_t Blue; //!< Blue color (0-255)
+ uint8_t Green; //!< Green color (0-255)
+ uint8_t Red; //!< Red color (0-255)
+ uint8_t Reserved; //!< Not used
+} U_RGBQUAD,
+ *PU_RGBQUAD; //!< WMF manual 2.2.2.20
+
+#define U_RCL_DEF (U_RECTL){0,0,-1,-1} //!< Use this when no bounds are needed.
+
+/** WMF manual 2.2.2.22
+ \brief Pair of values indicating x and y sizes.
+
+ Microsoft name: SIZE Object
+ Microsoft name: SIZEL Object
+*/
+typedef struct {
+ int32_t cx; //!< X size
+ int32_t cy; //!< Y size
+} U_SIZE,
+ U_SIZEL, //!< WMF manual 2.2.2.22
+ *PU_SIZE, //!< WMF manual 2.2.2.22
+ *PU_SIZEL; //!< WMF manual 2.2.2.22
+
+
+
+/* ************************ EMF or common to EMF and EMF+ ****************************** */
+
+// ***********************************************************************************
+// Value enumerations and other predefined constants, alphabetical order by group
+
+
+/** \defgroup U_EMF_FONT_STRUCT_WIDTHS EMF Font name and style widths in characters
+ For U_LOGFONT and U_LOGFONT_PANOSE,
+ @{
+*/
+#define U_LF_FACESIZE 32 //!< U_LOGFONT lfFaceName and U_LOGFONT_PANOSE elfStyle fields maximum width
+#define U_LF_FULLFACESIZE 64 //!< U_LOGFONT_PANOSE elfFullName field maximum width
+/** @} */
+
+/** \defgroup U_EMF_EMR_Qualifiers EMF RecordType Enumeration
+ (RecordType Enumeration, EMF manual 2.1.1 )
+ For U_EMR iType field
+ EMF manual 2.1.1
+ @{
+*/
+#define U_EMR_HEADER 1 //!< U_EMRHEADER record
+#define U_EMR_POLYBEZIER 2 //!< U_EMRPOLYBEZIER record
+#define U_EMR_POLYGON 3 //!< U_EMRPOLYGON record
+#define U_EMR_POLYLINE 4 //!< U_EMRPOLYLINE record
+#define U_EMR_POLYBEZIERTO 5 //!< U_EMRPOLYBEZIERTO record
+#define U_EMR_POLYLINETO 6 //!< U_EMRPOLYLINETO record
+#define U_EMR_POLYPOLYLINE 7 //!< U_EMRPOLYPOLYLINE record
+#define U_EMR_POLYPOLYGON 8 //!< U_EMRPOLYPOLYGON record
+#define U_EMR_SETWINDOWEXTEX 9 //!< U_EMRSETWINDOWEXTEX record
+#define U_EMR_SETWINDOWORGEX 10 //!< U_EMRSETWINDOWORGEX record
+#define U_EMR_SETVIEWPORTEXTEX 11 //!< U_EMRSETVIEWPORTEXTEX record
+#define U_EMR_SETVIEWPORTORGEX 12 //!< U_EMRSETVIEWPORTORGEX record
+#define U_EMR_SETBRUSHORGEX 13 //!< U_EMRSETBRUSHORGEX record
+#define U_EMR_EOF 14 //!< U_EMREOF record
+#define U_EMR_SETPIXELV 15 //!< U_EMRSETPIXELV record
+#define U_EMR_SETMAPPERFLAGS 16 //!< U_EMRSETMAPPERFLAGS record
+#define U_EMR_SETMAPMODE 17 //!< U_EMRSETMAPMODE record
+#define U_EMR_SETBKMODE 18 //!< U_EMRSETBKMODE record
+#define U_EMR_SETPOLYFILLMODE 19 //!< U_EMRSETPOLYFILLMODE record
+#define U_EMR_SETROP2 20 //!< U_EMRSETROP2 record
+#define U_EMR_SETSTRETCHBLTMODE 21 //!< U_EMRSETSTRETCHBLTMODE record
+#define U_EMR_SETTEXTALIGN 22 //!< U_EMRSETTEXTALIGN record
+#define U_EMR_SETCOLORADJUSTMENT 23 //!< U_EMRSETCOLORADJUSTMENT record
+#define U_EMR_SETTEXTCOLOR 24 //!< U_EMRSETTEXTCOLOR record
+#define U_EMR_SETBKCOLOR 25 //!< U_EMRSETBKCOLOR record
+#define U_EMR_OFFSETCLIPRGN 26 //!< U_EMROFFSETCLIPRGN record
+#define U_EMR_MOVETOEX 27 //!< U_EMRMOVETOEX record
+#define U_EMR_SETMETARGN 28 //!< U_EMRSETMETARGN record
+#define U_EMR_EXCLUDECLIPRECT 29 //!< U_EMREXCLUDECLIPRECT record
+#define U_EMR_INTERSECTCLIPRECT 30 //!< U_EMRINTERSECTCLIPRECT record
+#define U_EMR_SCALEVIEWPORTEXTEX 31 //!< U_EMRSCALEVIEWPORTEXTEX record
+#define U_EMR_SCALEWINDOWEXTEX 32 //!< U_EMRSCALEWINDOWEXTEX record
+#define U_EMR_SAVEDC 33 //!< U_EMRSAVEDC record
+#define U_EMR_RESTOREDC 34 //!< U_EMRRESTOREDC record
+#define U_EMR_SETWORLDTRANSFORM 35 //!< U_EMRSETWORLDTRANSFORM record
+#define U_EMR_MODIFYWORLDTRANSFORM 36 //!< U_EMRMODIFYWORLDTRANSFORM record
+#define U_EMR_SELECTOBJECT 37 //!< U_EMRSELECTOBJECT record
+#define U_EMR_CREATEPEN 38 //!< U_EMRCREATEPEN record
+#define U_EMR_CREATEBRUSHINDIRECT 39 //!< U_EMRCREATEBRUSHINDIRECT record
+#define U_EMR_DELETEOBJECT 40 //!< U_EMRDELETEOBJECT record
+#define U_EMR_ANGLEARC 41 //!< U_EMRANGLEARC record
+#define U_EMR_ELLIPSE 42 //!< U_EMRELLIPSE record
+#define U_EMR_RECTANGLE 43 //!< U_EMRRECTANGLE record
+#define U_EMR_ROUNDRECT 44 //!< U_EMRROUNDRECT record
+#define U_EMR_ARC 45 //!< U_EMRARC record
+#define U_EMR_CHORD 46 //!< U_EMRCHORD record
+#define U_EMR_PIE 47 //!< U_EMRPIE record
+#define U_EMR_SELECTPALETTE 48 //!< U_EMRSELECTPALETTE record
+#define U_EMR_CREATEPALETTE 49 //!< U_EMRCREATEPALETTE record
+#define U_EMR_SETPALETTEENTRIES 50 //!< U_EMRSETPALETTEENTRIES record
+#define U_EMR_RESIZEPALETTE 51 //!< U_EMRRESIZEPALETTE record
+#define U_EMR_REALIZEPALETTE 52 //!< U_EMRREALIZEPALETTE record
+#define U_EMR_EXTFLOODFILL 53 //!< U_EMREXTFLOODFILL record
+#define U_EMR_LINETO 54 //!< U_EMRLINETO record
+#define U_EMR_ARCTO 55 //!< U_EMRARCTO record
+#define U_EMR_POLYDRAW 56 //!< U_EMRPOLYDRAW record
+#define U_EMR_SETARCDIRECTION 57 //!< U_EMRSETARCDIRECTION record
+#define U_EMR_SETMITERLIMIT 58 //!< U_EMRSETMITERLIMIT record
+#define U_EMR_BEGINPATH 59 //!< U_EMRBEGINPATH record
+#define U_EMR_ENDPATH 60 //!< U_EMRENDPATH record
+#define U_EMR_CLOSEFIGURE 61 //!< U_EMRCLOSEFIGURE record
+#define U_EMR_FILLPATH 62 //!< U_EMRFILLPATH record
+#define U_EMR_STROKEANDFILLPATH 63 //!< U_EMRSTROKEANDFILLPATH record
+#define U_EMR_STROKEPATH 64 //!< U_EMRSTROKEPATH record
+#define U_EMR_FLATTENPATH 65 //!< U_EMRFLATTENPATH record
+#define U_EMR_WIDENPATH 66 //!< U_EMRWIDENPATH record
+#define U_EMR_SELECTCLIPPATH 67 //!< U_EMRSELECTCLIPPATH record
+#define U_EMR_ABORTPATH 68 //!< U_EMRABORTPATH record
+#define U_EMR_UNDEF69 69 //!< U_EMRUNDEF69 record
+#define U_EMR_COMMENT 70 //!< U_EMRCOMMENT record
+#define U_EMR_FILLRGN 71 //!< U_EMRFILLRGN record
+#define U_EMR_FRAMERGN 72 //!< U_EMRFRAMERGN record
+#define U_EMR_INVERTRGN 73 //!< U_EMRINVERTRGN record
+#define U_EMR_PAINTRGN 74 //!< U_EMRPAINTRGN record
+#define U_EMR_EXTSELECTCLIPRGN 75 //!< U_EMREXTSELECTCLIPRGN record
+#define U_EMR_BITBLT 76 //!< U_EMRBITBLT record
+#define U_EMR_STRETCHBLT 77 //!< U_EMRSTRETCHBLT record
+#define U_EMR_MASKBLT 78 //!< U_EMRMASKBLT record
+#define U_EMR_PLGBLT 79 //!< U_EMRPLGBLT record
+#define U_EMR_SETDIBITSTODEVICE 80 //!< U_EMRSETDIBITSTODEVICE record
+#define U_EMR_STRETCHDIBITS 81 //!< U_EMRSTRETCHDIBITS record
+#define U_EMR_EXTCREATEFONTINDIRECTW 82 //!< U_EMREXTCREATEFONTINDIRECTW record
+#define U_EMR_EXTTEXTOUTA 83 //!< U_EMREXTTEXTOUTA record
+#define U_EMR_EXTTEXTOUTW 84 //!< U_EMREXTTEXTOUTW record
+#define U_EMR_POLYBEZIER16 85 //!< U_EMRPOLYBEZIER16 record
+#define U_EMR_POLYGON16 86 //!< U_EMRPOLYGON16 record
+#define U_EMR_POLYLINE16 87 //!< U_EMRPOLYLINE16 record
+#define U_EMR_POLYBEZIERTO16 88 //!< U_EMRPOLYBEZIERTO16 record
+#define U_EMR_POLYLINETO16 89 //!< U_EMRPOLYLINETO16 record
+#define U_EMR_POLYPOLYLINE16 90 //!< U_EMRPOLYPOLYLINE16 record
+#define U_EMR_POLYPOLYGON16 91 //!< U_EMRPOLYPOLYGON16 record
+#define U_EMR_POLYDRAW16 92 //!< U_EMRPOLYDRAW16 record
+#define U_EMR_CREATEMONOBRUSH 93 //!< U_EMRCREATEMONOBRUSH record
+#define U_EMR_CREATEDIBPATTERNBRUSHPT 94 //!< U_EMRCREATEDIBPATTERNBRUSHPT record
+#define U_EMR_EXTCREATEPEN 95 //!< U_EMREXTCREATEPEN record
+#define U_EMR_POLYTEXTOUTA 96 //!< U_EMRPOLYTEXTOUTA record
+#define U_EMR_POLYTEXTOUTW 97 //!< U_EMRPOLYTEXTOUTW record
+#define U_EMR_SETICMMODE 98 //!< U_EMRSETICMMODE record
+#define U_EMR_CREATECOLORSPACE 99 //!< U_EMRCREATECOLORSPACE record
+#define U_EMR_SETCOLORSPACE 100 //!< U_EMRSETCOLORSPACE record
+#define U_EMR_DELETECOLORSPACE 101 //!< U_EMRDELETECOLORSPACE record
+#define U_EMR_GLSRECORD 102 //!< U_EMRGLSRECORD record
+#define U_EMR_GLSBOUNDEDRECORD 103 //!< U_EMRGLSBOUNDEDRECORD record
+#define U_EMR_PIXELFORMAT 104 //!< U_EMRPIXELFORMAT record
+#define U_EMR_DRAWESCAPE 105 //!< U_EMRDRAWESCAPE record
+#define U_EMR_EXTESCAPE 106 //!< U_EMREXTESCAPE record
+#define U_EMR_UNDEF107 107 //!< U_EMRUNDEF107 record
+#define U_EMR_SMALLTEXTOUT 108 //!< U_EMRSMALLTEXTOUT record
+#define U_EMR_FORCEUFIMAPPING 109 //!< U_EMRFORCEUFIMAPPING record
+#define U_EMR_NAMEDESCAPE 110 //!< U_EMRNAMEDESCAPE record
+#define U_EMR_COLORCORRECTPALETTE 111 //!< U_EMRCOLORCORRECTPALETTE record
+#define U_EMR_SETICMPROFILEA 112 //!< U_EMRSETICMPROFILEA record
+#define U_EMR_SETICMPROFILEW 113 //!< U_EMRSETICMPROFILEW record
+#define U_EMR_ALPHABLEND 114 //!< U_EMRALPHABLEND record
+#define U_EMR_SETLAYOUT 115 //!< U_EMRSETLAYOUT record
+#define U_EMR_TRANSPARENTBLT 116 //!< U_EMRTRANSPARENTBLT record
+#define U_EMR_UNDEF117 117 //!< U_EMRUNDEF117 record
+#define U_EMR_GRADIENTFILL 118 //!< U_EMRGRADIENTFILL record
+#define U_EMR_SETLINKEDUFIS 119 //!< U_EMRSETLINKEDUFIS record
+#define U_EMR_SETTEXTJUSTIFICATION 120 //!< U_EMRSETTEXTJUSTIFICATION record
+#define U_EMR_COLORMATCHTOTARGETW 121 //!< U_EMRCOLORMATCHTOTARGETW record
+#define U_EMR_CREATECOLORSPACEW 122 //!< U_EMRCREATECOLORSPACEW record
+
+#define U_EMR_MIN 1 //!< Minimum U_EMR_ value.
+#define U_EMR_MAX 122 //!< Maximum U_EMR_ value. Not much beyond 104 is implemented
+
+#define U_EMR_INVALID 0xFFFFFFFF //!< Not any valid U_EMF_ value
+/** @} */
+
+
+/** \defgroup U_EMF_DRAW_PROPERTIES EMF draw properties
+ Used in emr_properties() and wmr_properties. These are the bit definitions.
+ @{
+*/
+#define U_DRAW_NOTEMPTY 0x001 //!< Path has at least a MOVETO in it
+#define U_DRAW_VISIBLE 0x002 //!< Path has at least a LINE in it
+#define U_DRAW_CLOSED 0x004 //!< Path has been closed
+#define U_DRAW_ONLYTO 0x008 //!< Path so far contains only *TO operations
+#define U_DRAW_FORCE 0x010 //!< Path MUST be drawn
+#define U_DRAW_ALTERS 0x020 //!< Alters draw parameters (pen, brush, coordinates...)
+#define U_DRAW_PATH 0x040 //!< An explicit path is being used (with a BEGIN and END)
+#define U_DRAW_TEXT 0x080 //!< Current record forces all pending text to be drawn first.
+#define U_DRAW_OBJECT 0x100 //!< Creates an Object (only used in WMF)
+#define U_DRAW_NOFILL 0x200 //!< Object is not fillable (lines and arc, only used in WMF)
+
+/** @} */
+/** \defgroup U_EMF_EMRSETARCDIRECTION_Qualifiers EMF ArcDirection Enumeration
+ For U_EMRSETARCDIRECTION iArcDirection field
+ Microsoft name: ArcDirection Enumeration
+ EMF manual 2.1.2
+ @{
+*/
+#define U_AD_COUNTERCLOCKWISE 1 //!< Draw arc counterclockwise.
+#define U_AD_CLOCKWISE 2 //!< Draw arc clockwise.
+/** @} */
+
+/** \defgroup U_EMF_PANOSE_bArmStyle_Qualifiers EMF ArmStyle Enumeration
+ For U_PANOSE bArmStyle field
+ Microsoft name: ArmStyle Enumeration
+ EMF manual 2.1.3
+ @{
+*/
+#define U_PAN_STRAIGHT_ARMS_HORZ 2 //!< straight arms horizontal
+#define U_PAN_STRAIGHT_ARMS_WEDGE 3 //!< straight arms wedge
+#define U_PAN_STRAIGHT_ARMS_VERT 4 //!< straight arms vertical
+#define U_PAN_STRAIGHT_ARMS_SINGLE_SERIF 5 //!< straight arms singleserif
+#define U_PAN_STRAIGHT_ARMS_DOUBLE_SERIF 6 //!< straight arms doubleserif
+#define U_PAN_BENT_ARMS_HORZ 7 //!< bent arms horizontal
+#define U_PAN_BENT_ARMS_WEDGE 8 //!< bent arms wedge
+#define U_PAN_BENT_ARMS_VERT 9 //!< bent arms vertical
+#define U_PAN_BENT_ARMS_SINGLE_SERIF 10 //!< bent arms singleserif
+#define U_PAN_BENT_ARMS_DOUBLE_SERIF 11 //!< bent arms doubleserif
+/** @} */
+
+/** \defgroup U_EMF_EMRSETBKMODE_iMode_Qualifiers EMF BackgroundMode enumeration
+ For U_EMRSETBKMODE iMode field
+ Microsoft name: BackgroundMode enumeration
+ EMF manual 2.1.4
+ @{
+*/
+#define U_TRANSPARENT 1 //!< Transparent background mode
+#define U_OPAQUE 2 //!< Opaque background mode
+/** @} */
+
+/** \defgroup U_EMF_COLORADJUSTMENT_caFlags_Qualifiers EMF ColorAdjustment Enumeration
+ For U_COLORADJUSTMENT caFlags field
+ Microsoft name: ColorAdjustment Enumeration
+ EMF manual 2.1.5
+ @{
+*/
+#define U_CA_NEGATIVE 0x0001 //!< display Negative of image
+#define U_CA_LOG_FILTER 0x0002 //!< display Logarithmi filter of image
+/** @} */
+
+/** \defgroup U_EMF_EMRCOLORMATCHTOTARGETW_dwFlags_Qualifiers EMF ColorMatchToTarget Enumeration
+ For U_EMRCOLORMATCHTOTARGETW dwFlags field
+ Microsoft name: ColorMatchToTarget Enumeration
+ EMF manual 2.1.6
+ @{
+*/
+#define U_COLORMATCHTOTARGET_NOTEMBEDDED 0 //!< Color match profile is not embedded in metafile
+#define U_COLORMATCHTOTARGET_EMBEDDED 1 //!< Color match profile is embedded in metafile
+/** @} */
+
+/** \defgroup U_EMF_EMRCOLORMATCHTOTARGETW_dwAction_Qualifiers EMF ColorSpace Enumeration
+ For U_EMRCOLORMATCHTOTARGETW dwAction field
+ Microsoft name: ColorSpace Enumeration
+ EMF manual 2.1.7
+ @{
+*/
+#define U_CS_ENABLE 1 //!< Enable color proofing.
+#define U_CS_DISABLE 2 //!< Disable color proofing.
+#define U_CS_DELETE_TRANSFORM 3 //!< Disable proofing and delete color transform.
+/** @} */
+
+/** \defgroup U_EMF_PANOSE_common_Qualifiers EMF PanoseCommon Enumeration
+ Used by all PAN_* enumerations, but only defined once here.
+ See also U_PAN_ALL1 after the U_PANOSE structure
+ @{
+*/
+#define U_PAN_ANY 0 //!< Any (for any type of Panose enumeration)
+#define U_PAN_NO_FIT 1 //!< No fit (for any type of Panose enumeration)
+/** @} */
+
+/** \defgroup U_EMF_PANOSE_bContrast_Qualifiers EMF Contrast Enumeration
+ For U_PANOSE bContrast field
+ Microsoft name: Contrast Enumeration
+ EMF manual 2.1.8
+ @{
+*/
+#define U_PAN_CONTRAST_NONE 2 //!< None
+#define U_PAN_CONTRAST_VERY_LOW 3 //!< Very low
+#define U_PAN_CONTRAST_LOW 4 //!< Low
+#define U_PAN_CONTRAST_MEDIUM_LOW 5 //!< Medium low
+#define U_PAN_CONTRAST_MEDIUM 6 //!< Medium
+#define U_PAN_CONTRAST_MEDIUM_HIGH 7 //!< Medium high
+#define U_PAN_CONTRAST_HIGH 8 //!< High
+#define U_PAN_CONTRAST_VERY_HIGH 9 //!< Very high
+/** @} */
+
+/** \defgroup U_EMF_DIBITS_iUsageSrc_Qualifiers EMF DIBColors Enumeration
+ For U_EMRSETDIBITSTODEIVCE and U_EMRSTRETCHDIBITS iUsageSrc fields.
+ Microsoft name: DIBColors Enumeration
+ EMF manual 2.1.9
+ @{
+*/
+#define U_DIB_RGB_COLORS 0 //!< color table contains colors
+#define U_DIB_PAL_COLORS 1 //!< color table contains 16 bit indices into logical palette
+#define U_DIB_PAL_INDICES 2 //!< no color table, pixel values are indices into logical palette
+/** @} */
+
+/** \defgroup U_EMF_EMR_COMMENT_PUBLIC EMF EMRComment Enumeration
+ For U_EMRCOMMENT_PUBLIC pcIdent fields
+ Microsoft name: EMRComment Enumeration
+ EMF manual 2.1.10
+ @{
+*/
+#define U_EMR_COMMENT_WINDOWS_METAFILE 0x80000001 //!< Comment contains WMF
+#define U_EMR_COMMENT_BEGINGROUP 0x00000002 //!< Comment begins group of EMF records
+#define U_EMR_COMMENT_ENDGROUP 0x00000003 //!< Comment ends group of EMF records
+#define U_EMR_COMMENT_MULTIFORMATS 0x40000004 //!< Comment contains some other representation of drawing
+#define U_EMR_COMMENT_UNICODE_STRING 0x00000040 //!< Reserved
+#define U_EMR_COMMENT_UNICODE_END 0x00000080 //!< Reserved
+/** @} */
+
+/** \defgroup U_EMF_EMRTEXT_foptions_Qualifiers EMF ExtTextOutOptions Enumeration
+ For U_EMRTEXT foptions field
+ Microsoft name: ExtTextOutOptions Enumeration
+ EMF manual 2.1.11
+ @{
+*/
+#define U_ETO_NONE 0x00000000 //!< None
+#define U_ETO_GRAYED 0x00000001 //!< Grayed
+#define U_ETO_OPAQUE 0x00000002 //!< Fill rectangle with background color.
+#define U_ETO_CLIPPED 0x00000004 //!< Clip text to rectangle.
+#define U_ETO_GLYPH_INDEX 0x00000010 //!< Characters are glyph indices for the font.
+#define U_ETO_RTLREADING 0x00000080 //!< Right to left text.
+#define U_ETO_NO_RECT 0x00000100 //!< No bounding rectangle is specified.
+#define U_ETO_SMALL_CHARS 0x00000200 //!< 8 bit characters instead of 16 bit. For EMRSMALLTEXTOUT ONLY, does not affect EMRTEXTOUTA or EMRTEXTOUTW
+#define U_ETO_NUMERICSLOCAL 0x00000400 //!< Show numbers for the current locale.
+#define U_ETO_NUMERICSLATIN 0x00000800 //!< Show numbers using European digits.
+#define U_ETO_IGNORELANGUAGE 0x00001000 //!< Process Right to Left languages exactly as specified in the metafile.
+#define U_ETO_PDY 0x00002000 //!< Both horizontal and vertical displacements are provided.
+#define U_ETO_REVERSE_INDEX_MAP 0x00010000 //!< Reverse_index_map
+/** @} */
+
+/** \defgroup U_EMF_PANOSE_bFamilyType_Qualifiers EMF FamilyType Enumeration
+ For U_PANOSE bFamilyType field
+ Microsoft name: FamilyType Enumeration
+ EMF manual 2.1.12
+ @{
+*/
+#define U_PAN_FAMILY_TEXT_DISPLAY 2 //!< Text display
+#define U_PAN_FAMILY_SCRIPT 3 //!< Script
+#define U_PAN_FAMILY_DECORATIVE 4 //!< Decorative
+#define U_PAN_FAMILY_PICTORIAL 5 //!< Pictorial
+/** @} */
+
+/** \defgroup U_EMF_EMREXTFLOODFILL_iMode_Qualifiers EMF FloodFill Enumeration
+ For U_EMREXTFLOODFILL iMode field
+ Microsoft name: FloodFill Enumeration
+ EMF manual 2.1.13
+ @{
+*/
+#define U_FLOODFILLBORDER 0x00000000 //!< Color specified must be the same as the border - brush fill stops at this color
+#define U_FLOODFILLSURFACE 0x00000001 //!< Color specified must be different from the border - brush fills only this color
+/** @} */
+
+/** \defgroup U_EMF_DESIGNVECTOR_Signature_Qualifiers EMF Signature Enumeration
+ For U_DESIGNVECTOR Signature field
+ Microsoft name: Signature Enumeration
+ EMF manual 2.1.14
+ @{
+*/
+#define U_ENHMETA_SIGNATURE 0x464D4520 //!< "EMF" signature also for U_EMRHEADER dSignature field.
+#define U_EPS_SIGNATURE 0x46535045 //!< "FSPE" signature, indicates encapsulated postscript.
+/** @} */
+
+/** \defgroup U_EMF_EMRGRADIENTFILL_ulMode_Qualifiers EMF GradientFill Enumeration
+ For U_EMRGRADIENTFILL ulMode field
+ Microsoft name: GradientFill Enumeration
+ EMF manual 2.1.15
+ @{
+*/
+#define U_GRADIENT_FILL_RECT_H 0x00000000 //!< Gradient is left to right.
+#define U_GRADIENT_FILL_RECT_V 0x00000001 //!< Grident is top to bottom.
+#define U_GRADIENT_FILL_TRIANGLE 0x00000002 //!< Gradient is between 3 vertices of a triangle.
+/** @} */
+
+/** \defgroup U_EMF_EMREXTTEXTOUT_iGraphicsMode_Qualifiers EMF GraphicsMode Enumeration
+ For U_EMREXTTEXTOUTA/U_EMREXTTEXTOUTW and all other iGraphicsMode fields
+ Microsoft name: GraphicsMode Enumeration
+ EMF manual 2.1.16
+ @{
+*/
+#define U_GM_COMPATIBLE 1 //!< TrueType text ignores world to device transform except for Scale. Arcs ignore transform
+#define U_GM_ADVANCED 2 //!< TrueType text and Arcs must conform to all of world to device transform.
+#define U_GM_LAST 2 //!< Number of GraphicsMode Enumeration entries.
+/** @} */
+
+/** \defgroup U_EMF_LOGBRUSH_lbHatch_Qualifiers EMF HatchStyle Enumeration
+ For U_LOGBRUSH lbHatch field
+ Microsoft name: HatchStyle Enumeration
+ EMF manual 2.1.17
+ @{
+*/
+#define U_HS_HORIZONTAL 0 //!< Horizontal.
+#define U_HS_VERTICAL 1 //!< Vertical.
+#define U_HS_FDIAGONAL 2 //!< Forward diagonal.
+#define U_HS_BDIAGONAL 3 //!< Back diagonal.
+#define U_HS_CROSS 4 //!< Cross.
+#define U_HS_DIAGCROSS 5 //!< Diagonal cross.
+#define U_HS_SOLIDCLR 6 //!< Solid color.
+#define U_HS_DITHEREDCLR 7 //!< Dithered color.
+#define U_HS_SOLIDTEXTCLR 8 //!< Solid text color.
+#define U_HS_DITHEREDTEXTCLR 9 //!< Dithered text color.
+#define U_HS_SOLIDBKCLR 10 //!< Solid background color.
+#define U_HS_DITHEREDBKCLR 11 //!< Dithered background color.
+/** @} */
+
+/** \defgroup U_EMF_EMRSETICMMODE_iMode_Qualifiers EMF ICMMode Enumeration
+ For EMF U_EMR_SETICMMODE iMode field
+ Microsoft name: ICMMode Enumeration
+ EMF manual 2.1.18
+ @{
+*/
+#define U_ICM_OFF 1 //!< Off
+#define U_ICM_ON 2 //!< On
+#define U_ICM_QUERY 3 //!< Query
+/** @} */
+
+/** \defgroup U_EMF_COLORADJUSTMENT_caIlluminantIndex_Qualifiers EMF Illuminant Enumeration
+ For U_COLORADJUSTMENT caIlluminantIndex field
+ Microsoft name: Illuminant Enumeration
+ EMF manual 2.1.19
+ @{
+*/
+#define U_ILLUMINANT_DEVICE_DEFAULT 0 //!< Device default
+#define U_ILLUMINANT_A 1 //!< A
+#define U_ILLUMINANT_B 2 //!< B
+#define U_ILLUMINANT_C 3 //!< C
+#define U_ILLUMINANT_D50 4 //!< D50
+#define U_ILLUMINANT_D55 5 //!< D55
+#define U_ILLUMINANT_D65 6 //!< D65
+#define U_ILLUMINANT_D75 7 //!< D75
+#define U_ILLUMINANT_F2 8 //!< F2
+#define U_ILLUMINANT_MAX_INDEX ILLUMINANT_F2 //!< Max index
+#define U_ILLUMINANT_TUNGSTEN ILLUMINANT_A //!< Tungsten
+#define U_ILLUMINANT_DAYLIGHT ILLUMINANT_C //!< Daylight
+#define U_ILLUMINANT_FLUORESCENT ILLUMINANT_F2 //!< Fluorescent
+#define U_ILLUMINANT_NTSC ILLUMINANT_C //!< NTSC
+/** @} */
+
+/** \defgroup U_EMF_PANOSE_bLetterForm_Qualifiers EMF Letterform Enumeration
+ For U_PANOSE bLetterForm field
+ Microsoft name: Letterform Enumeration
+ EMF manual 2.1.20
+ @{
+*/
+#define U_PAN_LETT_NORMAL_COMPACT 2 //!< Normal compact
+#define U_PAN_LETT_NORMAL_WEIGHTED 3 //!< Normal weighted
+#define U_PAN_LETT_NORMAL_BOXED 4 //!< Normal boxed
+#define U_PAN_LETT_NORMAL_FLATTENED 5 //!< Normal flattened
+#define U_PAN_LETT_NORMAL_ROUNDED 6 //!< Normal rounded
+#define U_PAN_LETT_NORMAL_OFF_CENTER 7 //!< Normal off center
+#define U_PAN_LETT_NORMAL_SQUARE 8 //!< Normal square
+#define U_PAN_LETT_OBLIQUE_COMPACT 9 //!< Oblique compact
+#define U_PAN_LETT_OBLIQUE_WEIGHTED 10 //!< Oblique weighted
+#define U_PAN_LETT_OBLIQUE_BOXED 11 //!< Oblique boxed
+#define U_PAN_LETT_OBLIQUE_FLATTENED 12 //!< Oblique flattened
+#define U_PAN_LETT_OBLIQUE_ROUNDED 13 //!< Oblique rounded
+#define U_PAN_LETT_OBLIQUE_OFF_CENTER 14 //!< Oblique off center
+#define U_PAN_LETT_OBLIQUE_SQUARE 15 //!< Oblique square
+/** @} */
+
+/** \defgroup U_EMF_EMRSETMAPMODE_iMode_Qualifiers EMF MapMode Enumeration
+ For U_EMRSETMAPMODE iMode field
+ Microsoft name: MapMode Enumeration
+ EMF manual 2.1.21
+ @{
+*/
+#define U_MM_TEXT 1 //!< Text
+#define U_MM_LOMETRIC 2 //!< Low metric
+#define U_MM_HIMETRIC 3 //!< Hig hmetric
+#define U_MM_LOENGLISH 4 //!< Low English
+#define U_MM_HIENGLISH 5 //!< High English
+#define U_MM_TWIPS 6 //!< Twips
+#define U_MM_ISOTROPIC 7 //!< Isotropic
+#define U_MM_ANISOTROPIC 8 //!< Anisotropic
+#define U_MM_MIN U_MM_TEXT //!< smallest enumeration
+#define U_MM_MAX U_MM_ANISOTROPIC //!< largest enumeration
+#define U_MM_MAX_FIXEDSCALE U_MM_TWIPS //!< alternate definition
+/** @} */
+
+/** \defgroup U_EMF_MF_version EMF MetafileVersion Enumeration
+ For U_EMR_COMMENTS_METAFILE version field
+ Microsoft name: MetafileVersion Enumeration
+ EMF manual 2.1.22
+ @{
+*/
+#define U_ENHMETA_VERSION 0x00010000 //!< U_EMRHEADER nVersion field
+/** @} */
+
+/** \defgroup U_EMF_PANOSE_bMidline_Qualifiers EMF MidLine Enumeration
+ For U_PANOSE bMidline field
+ Microsoft name: MidLine Enumeration
+ EMF manual 2.1.23
+ @{
+*/
+#define U_PAN_MIDLINE_STANDARD_TRIMMED 2 //!< Midline standard trimmed
+#define U_PAN_MIDLINE_STANDARD_POINTED 3 //!< Midline standard pointed
+#define U_PAN_MIDLINE_STANDARD_SERIFED 4 //!< Midline standard serifed
+#define U_PAN_MIDLINE_HIGH_TRIMMED 5 //!< Midline high trimmed
+#define U_PAN_MIDLINE_HIGH_POINTED 6 //!< Midline high pointed
+#define U_PAN_MIDLINE_HIGH_SERIFED 7 //!< Midline high serifed
+#define U_PAN_MIDLINE_CONSTANT_TRIMMED 8 //!< Midline constant trimmed
+#define U_PAN_MIDLINE_CONSTANT_POINTED 9 //!< Midline constant pointed
+#define U_PAN_MIDLINE_CONSTANT_SERIFED 10 //!< Midline constant serifed
+#define U_PAN_MIDLINE_LOW_TRIMMED 11 //!< Midline low trimmed
+#define U_PAN_MIDLINE_LOW_POINTED 12 //!< Midline low pointed
+#define U_PAN_MIDLINE_LOW_SERIFED 13 //!< Midline low serifed
+/** @} */
+
+/** \defgroup U_EMF_EMRMODIFYWORLDTRANSFORM_iMode_Qualifiers EMF ModifyWorldTransformMode Enumeration
+ For U_EMRMODIFYWORLDTRANSFORM iMode
+ Microsoft name: ModifyWorldTransformMode Enumeration
+ EMF manual 2.1.24
+ @{
+*/
+#define U_MWT_IDENTITY 1 //!< Transform is identity.
+#define U_MWT_LEFTMULTIPLY 2 //!< Left multiply transform.
+#define U_MWT_RIGHTMULTIPLY 3 //!< Right multiply transform.
+#define U_MWT_MIN U_MWT_IDENTITY //!< smallest enumeration.
+#define U_MWT_MAX U_MWT_RIGHTMULTIPLY //!< largest enumeration.
+/** @} */
+
+/** \defgroup U_EMF_LOGPEN_elpPenStyle_Qualifiers EMF PenStyle Enumeration
+ For U_LOGPEN lopnStyle and U_EXTLOGPEN elpPenStyle fields
+ Microsoft name: PenStyle Enumeration
+ EMF manual 2.1.25
+ @{
+*/
+#define U_PS_SOLID 0x00000000 //!< Solid line.
+#define U_PS_DASH 0x00000001 //!< Dashed line. This only works when NO other U_PS is set. Line width is minimum no matter what pen is set to.
+#define U_PS_DOT 0x00000002 //!< Dotted line. This only works when NO other U_PS is set. Line width is minimum no matter what pen is set to.
+#define U_PS_DASHDOT 0x00000003 //!< Dash-Dot line. This only works when NO other U_PS is set. Line width is minimum no matter what pen is set to.
+#define U_PS_DASHDOTDOT 0x00000004 //!< Dash-Dot-Dot line. This only works when NO other U_PS is set. Line width is minimum no matter what pen is set to.
+#define U_PS_NULL 0x00000005 //!< Invisible line.
+#define U_PS_INSIDEFRAME 0x00000006 //!< Draw line around drawing, then shrink drawing to fit within line taking its width into account.
+#define U_PS_USERSTYLE 0x00000007 //!< User defined.
+#define U_PS_ALTERNATE 0x00000008 //!< Every other pixel is drawn.
+#define U_PS_STYLE_MASK 0x0000000f //!< Mask to select just the preceding line type fields.
+
+#define U_PS_ENDCAP_ROUND 0x00000000 //!< Round end cap. Only with U_PS_GEOMETRIC
+#define U_PS_ENDCAP_SQUARE 0x00000100 //!< Square end cap. Only with U_PS_GEOMETRIC
+#define U_PS_ENDCAP_FLAT 0x00000200 //!< Flat end cap. Only with U_PS_GEOMETRIC
+#define U_PS_ENDCAP_MASK 0x00000f00 //!< Mask to select just the preceding ENDCAP fields.
+
+#define U_PS_JOIN_ROUND 0x00000000 //!< Rounded join. Only with U_PS_GEOMETRIC
+#define U_PS_JOIN_BEVEL 0x00001000 //!< Beveled join. Only with U_PS_GEOMETRIC
+#define U_PS_JOIN_MITER 0x00002000 //!< Mitered join. Only with U_PS_GEOMETRIC
+#define U_PS_JOIN_MASK 0x0000f000 //!< Mask to select just the preceding JOIN fields.
+
+#define U_PS_COSMETIC 0x00000000 //!< width may only be 1 pixel. (If set higher it is still drawn as 1).
+#define U_PS_GEOMETRIC 0x00010000 //!< width may be >1 pixel, but style may only be U_PS_SOLID or U_PS_NULL.
+#define U_PS_TYPE_MASK 0x000f0000 //!< Mask to select just the preceding TYPE fields.
+/** @} */
+/** \defgroup U_EMF_EMRPOLY_iMode_Qualifiers EMF Point Enumeration
+ For U_EMRPOLYDRAW and U_EMRPOLAYDRAW16 abTypes fields.
+ Microsoft name: Point Enumeration
+ EMF manual 2.1.26
+ @{
+*/
+#define U_PT_CLOSEFIGURE 0x0001 //!< Close figure
+#define U_PT_LINETO 0x0002 //!< Line to
+#define U_PT_BEZIERTO 0x0004 //!< Bezier to
+#define U_PT_MOVETO 0x0006 //!< Move to
+/** @} */
+
+/** \defgroup U_EMF_EMRSETPOLYFILLMODE_iMode_Qualifiers EMF PolygonFillMode Enumeration
+ For U_EMRSETPOLYFILLMODE iMode field
+ Microsoft name: PolygonFillMode Enumeration
+ EMF manual 2.1.27
+ @{
+*/
+#define U_ALTERNATE 1 //!< Alternate
+#define U_WINDING 2 //!< Winding
+#define U_POLYFILL_LAST 2 //!< Polyfill last
+/** @} */
+
+/** \defgroup U_EMF_PANOSE_bProportion_Qualifiers EMF Proportion Enumeration
+ For U_PANOSE bProportion field
+ Microsoft name: Proportion Enumeration
+ EMF manual 2.1.28
+ @{
+*/
+#define U_PAN_PROP_OLD_STYLE 2 //!< Old style
+#define U_PAN_PROP_MODERN 3 //!< Modern
+#define U_PAN_PROP_EVEN_WIDTH 4 //!< Even width
+#define U_PAN_PROP_EXPANDED 5 //!< Expanded
+#define U_PAN_PROP_CONDENSED 6 //!< Condensed
+#define U_PAN_PROP_VERY_EXPANDED 7 //!< Very expanded
+#define U_PAN_PROP_VERY_CONDENSED 8 //!< Very condensed
+#define U_PAN_PROP_MONOSPACED 9 //!< Monospaced
+/** @} */
+
+/** \defgroup U_EMF_EMRSELECTCLIP_iMode_Qualifiers EMF RegionMode Enumeration
+ For U_EMRSELECTCLIPPATH and U_EMREXTSELECTCLIPRGN iMode field
+ Microsoft name: RegionMode Enumeration
+ EMF manual 2.1.29
+ @{
+*/
+#define U_RGN_NONE 0 //!< not part of EMF standard, may be used by others
+#define U_RGN_AND 1 //!< Region becomes intersection of existing region and new region.
+#define U_RGN_OR 2 //!< Region becomes union of existing region and new region.
+#define U_RGN_XOR 3 //!< Region becomes XOR of existing and new regions.
+#define U_RGN_DIFF 4 //!< Region becomes part of existing region not in new region.
+#define U_RGN_COPY 5 //!< Region becomes new region.
+#define U_RGN_MIN U_RGN_AND //!< smallest enumeration.
+#define U_RGN_MAX U_RGN_COPY //!< largest enumeration.
+/** @} */
+
+/** \defgroup U_EMF_PANOSE_bSerifStyle_Qualifiers EMF SerifType Enumeration
+ For U_PANOSE bSerifStyle field
+ Microsoft name: SerifType Enumeration
+ EMF manual 2.1.30
+ @{
+*/
+#define U_PAN_SERIF_COVE 2 //!< Serif cove
+#define U_PAN_SERIF_OBTUSE_COVE 3 //!< Serif obtuse cove
+#define U_PAN_SERIF_SQUARE_COVE 4 //!< Serif square cove
+#define U_PAN_SERIF_OBTUSE_SQUARE_COVE 5 //!< Serif obtuse square cove
+#define U_PAN_SERIF_SQUARE 6 //!< Serif square
+#define U_PAN_SERIF_THIN 7 //!< Serif thin
+#define U_PAN_SERIF_BONE 8 //!< Serif bone
+#define U_PAN_SERIF_EXAGGERATED 9 //!< Serif exaggerated
+#define U_PAN_SERIF_TRIANGLE 10 //!< Serif triangle
+#define U_PAN_SERIF_NORMAL_SANS 11 //!< Serif normal sans
+#define U_PAN_SERIF_OBTUSE_SANS 12 //!< Serif obtuse sans
+#define U_PAN_SERIF_PERP_SANS 13 //!< Serif perp sans
+#define U_PAN_SERIF_FLARED 14 //!< Serif flared
+#define U_PAN_SERIF_ROUNDED 15 //!< Serif rounded
+/** @} */
+
+/** \defgroup U_EMF_EMRSELECTOBJECT_ihObject_Qualifiers EMF StockObject Enumeration
+ For U_EMRSELECTOBJECT ihObject field.
+ Microsoft name: StockObject Enumeration
+ EMF manual 2.1.31
+ @{
+*/
+#define U_STOCK_OBJECT 0x80000000 //!< Stock object
+#define U_WHITE_BRUSH 0x80000000 //!< White brush
+#define U_LTGRAY_BRUSH 0x80000001 //!< Ltgray brush
+#define U_GRAY_BRUSH 0x80000002 //!< Gray brush
+#define U_DKGRAY_BRUSH 0x80000003 //!< Dkgray brush
+#define U_BLACK_BRUSH 0x80000004 //!< Black brush
+#define U_NULL_BRUSH 0x80000005 //!< Null brush
+#define U_HOLLOW_BRUSH 0x80000005 //!< Hollow brush
+#define U_WHITE_PEN 0x80000006 //!< White pen
+#define U_BLACK_PEN 0x80000007 //!< Black pen
+#define U_NULL_PEN 0x80000008 //!< Null pen
+#define U_OEM_FIXED_FONT 0x8000000A //!< Oem fixed font
+#define U_ANSI_FIXED_FONT 0x8000000B //!< Ansi fixed font
+#define U_ANSI_VAR_FONT 0x8000000C //!< Ansi var font
+#define U_SYSTEM_FONT 0x8000000D //!< System font
+#define U_DEVICE_DEFAULT_FONT 0x8000000E //!< Device default font
+#define U_DEFAULT_PALETTE 0x8000000F //!< Default palette
+#define U_SYSTEM_FIXED_FONT 0x80000010 //!< System fixed font
+#define U_DEFAULT_GUI_FONT 0x80000011 //!< Default GUI font
+#define U_STOCK_LAST 0x80000011 //!< Stock last
+/** @} */
+
+/** \defgroup U_EMF_EMRSETSTRETCHBLTMODE_iMode_Qualifiers EMF StretchMode Enumeration
+ For EMF U_EMRSETSTRETCHBLTMODE iMode field
+ Microsoft name: StretchMode Enumeration
+ EMF manual 2.1.32 and footnote 52 on page 297
+ @{
+*/
+#define U_BLACKONWHITE 1 //!< AND the destination and source pixels.
+#define U_WHITEONBLACK 2 //!< OR the destination and source pixels.
+#define U_COLORONCOLOR 3 //!< Replace the destination pixels with the source pixels.
+#define U_HALFTONE 4 //!< Replace a block of destination pixels with a half-tone representation of the source pixel.
+#define U_MAXSTRETCHBLTMODE 4 //!< largest enumeration.
+#define U_STRETCH_ANDSCANS 1 //!< AND the destination and source pixels.
+#define U_STRETCH_ORSCANS 2 //!< OR the destination and source pixels.
+#define U_STRETCH_DELETESCANS 3 //!< Replace the destination pixels with the source pixels.
+#define U_STRETCH_HALFTONE 4 //!< Replace a block of destination pixels with a half-tone representation of the source pixel.
+/** @} */
+
+/** \defgroup U_EMF_PANOSE_bStrokeVariation_Qualifiers EMF StrokeVariation Enumeration
+ For U_PANOSE bStrokeVariation field
+ Microsoft name: StrokeVariation Enumeration
+ EMF manual 2.1.33
+ @{
+*/
+#define U_PAN_STROKE_GRADUAL_DIAG 2 //!< Gradual diagonal.
+#define U_PAN_STROKE_GRADUAL_TRAN 3 //!< Gradual transitional.
+#define U_PAN_STROKE_GRADUAL_VERT 4 //!< Gradual vertical.
+#define U_PAN_STROKE_GRADUAL_HORZ 5 //!< Gradual horizontal.
+#define U_PAN_STROKE_RAPID_VERT 6 //!< Rapid vertical.
+#define U_PAN_STROKE_RAPID_HORZ 7 //!< Rapid horizontal.
+#define U_PAN_STROKE_INSTANT_VERT 8 //!< Instant vertical.
+/** @} */
+
+/** \defgroup U_EMF_PANOSE_bWeight_Qualifiers EMF Weight Enumeration
+ For U_PANOSE bWeight field
+ EMF manual 2.1.34
+ @{
+*/
+#define U_PAN_WEIGHT_VERY_LIGHT 2 //!< Very light
+#define U_PAN_WEIGHT_LIGHT 3 //!< Light
+#define U_PAN_WEIGHT_THIN 4 //!< Thin
+#define U_PAN_WEIGHT_BOOK 5 //!< Book
+#define U_PAN_WEIGHT_MEDIUM 6 //!< Medium
+#define U_PAN_WEIGHT_DEMI 7 //!< Demi
+#define U_PAN_WEIGHT_BOLD 8 //!< Bold
+#define U_PAN_WEIGHT_HEAVY 9 //!< Heavy
+#define U_PAN_WEIGHT_BLACK 10 //!< Black
+#define U_PAN_WEIGHT_NORD 11 //!< Nord
+/** @} */
+
+/** \defgroup U_EMF_PANOSE_bXHeight_Qualifiers EMF XHeight Enumeration
+ For U_PANOSE bXHeight field
+ EMF manual 2.1.35
+ @{
+*/
+#define U_PAN_XHEIGHT_CONSTANT_SMALL 2 //!< Constant small
+#define U_PAN_XHEIGHT_CONSTANT_STANDARD 3 //!< Constant standard
+#define U_PAN_XHEIGHT_CONSTANT_LARGE 4 //!< Constant large
+#define U_PAN_XHEIGHT_DUCKING_SMALL 5 //!< Ducking small
+#define U_PAN_XHEIGHT_DUCKING_STANDARD 6 //!< Ducking standard
+#define U_PAN_XHEIGHT_DUCKING_LARGE 7 //!< Ducking large
+/** @} */
+
+/** \defgroup U_EMF_LOGFONT_lfWeight_Qualifiers EMF LF_Weight Enumeration
+ For U_LOGFONT lfWeight field
+ EMF manual 2.2.13, footnote 61 (on page 297)
+ @{
+*/
+#define U_FW_DONTCARE 0 //!< Don't care
+#define U_FW_THIN 100 //!< Thin
+#define U_FW_EXTRALIGHT 200 //!< Extra light
+#define U_FW_ULTRALIGHT 200 //!< Ultra light
+#define U_FW_LIGHT 300 //!< Light
+#define U_FW_NORMAL 400 //!< Normal
+#define U_FW_REGULAR 400 //!< Regular
+#define U_FW_MEDIUM 500 //!< Medium
+#define U_FW_SEMIBOLD 600 //!< Semibold
+#define U_FW_DEMIBOLD 600 //!< Demibold
+#define U_FW_BOLD 700 //!< Bold
+#define U_FW_EXTRABOLD 800 //!< Extrabold
+#define U_FW_ULTRABOLD 800 //!< Ultrabold
+#define U_FW_HEAVY 900 //!< Heavy
+#define U_FW_BLACK 900 //!< Black
+/** @} */
+
+/** \defgroup U_EMF_LOGFONT_lfItalic_Qualifiers EMF LF_Italic Enumeration
+ For U_LOGFONT lfItalic field
+ Microsoft name: LF_Italic Enumeration
+ EMF manual 2.2.13
+ @{
+*/
+#define U_FW_NOITALIC 0 //!< Do not use italics.
+#define U_FW_ITALIC 1 //!< Use italics.
+/** @} */
+
+/** \defgroup U_EMF_LOGFONT_lfunderline_Qualifiers EMF LF_Underline Enumeration
+ For U_LOGFONT lfunderline field
+ Microsoft name: LF_Underline Enumeration
+ EMF manual 2.2.13
+ @{
+*/
+#define U_FW_NOUNDERLINE 0 //!< Do not use underline.
+#define U_FW_UNDERLINE 1 //!< Use underline.
+/** @} */
+
+/** \defgroup U_EMF_LOGFONT_lfStrikeOut_Qualifiers EMF LF_StrikeOut Enumeration
+ For U_LOGFONT lfStrikeOut field
+ EMF manual 2.2.13
+ @{
+*/
+#define U_FW_NOSTRIKEOUT 0 //!< Do not use strikeout.
+#define U_FW_STRIKEOUT 1 //!< Use strikeout.
+/** @} */
+
+/** \defgroup U_EMF_LOGFONT_lfCharSet_Qualifiers EMF LF_CharSet Enumeration
+ For U_LOGFONT lfCharSet field
+ EMF manual 2.2.13 & WMF manual 2.1.15
+ @{
+*/
+#define U_ANSI_CHARSET (uint8_t)0 //!< CP1252, ansi-0, iso8859-{1,15}
+#define U_DEFAULT_CHARSET (uint8_t)1 //!< Default character set.
+#define U_SYMBOL_CHARSET (uint8_t)2 //!< Symbol character set.
+#define U_SHIFTJIS_CHARSET (uint8_t)128 //!< CP932
+#define U_HANGEUL_CHARSET (uint8_t)129 //!< CP949, ksc5601.1987-0
+#define U_HANGUL_CHARSET U_HANGEUL_CHARSET //!< CP949, ksc5601.1987-0
+#define U_GB2312_CHARSET (uint8_t)134 //!< CP936, gb2312.1980-0
+#define U_CHINESEBIG5_CHARSET (uint8_t)136 //!< CP950, big5.et-0
+#define U_GREEK_CHARSET (uint8_t)161 //!< CP1253
+#define U_TURKISH_CHARSET (uint8_t)162 //!< CP1254, -iso8859-9
+#define U_HEBREW_CHARSET (uint8_t)177 //!< CP1255, -iso8859-8
+#define U_ARABIC_CHARSET (uint8_t)178 //!< CP1256, -iso8859-6
+#define U_BALTIC_CHARSET (uint8_t)186 //!< CP1257, -iso8859-13
+#define U_RUSSIAN_CHARSET (uint8_t)204 //!< CP1251, -iso8859-5
+#define U_EE_CHARSET (uint8_t)238 //!< CP1250, -iso8859-2
+#define U_EASTEUROPE_CHARSET U_EE_CHARSET //!< CP1250, -iso8859-2
+#define U_THAI_CHARSET (uint8_t)222 //!< CP874, iso8859-11, tis620
+#define U_JOHAB_CHARSET (uint8_t)130 //!< korean (johab) CP1361
+#define U_MAC_CHARSET (uint8_t)77 //!< Macintosh character set.
+#define U_OEM_CHARSET (uint8_t)255 //!< OEM character set.
+#define U_VISCII_CHARSET (uint8_t)240 //!< viscii1.1-1
+#define U_TCVN_CHARSET (uint8_t)241 //!< tcvn-0
+#define U_KOI8_CHARSET (uint8_t)242 //!< koi8-{r,u,ru}
+#define U_ISO3_CHARSET (uint8_t)243 //!< iso8859-3
+#define U_ISO4_CHARSET (uint8_t)244 //!< iso8859-4
+#define U_ISO10_CHARSET (uint8_t)245 //!< iso8859-10
+#define U_CELTIC_CHARSET (uint8_t)246 //!< iso8859-14
+/** @} */
+
+/** \defgroup U_EMF_LOGFONT_lfOutPrecision_Qualifiers EMF LF_OutPrecision Enumeration
+ For U_LOGFONT lfOutPrecision field
+ EMF manual 2.2.13 & WMF manual 2.1.1.21
+ @{
+*/
+#define U_OUT_DEFAULT_PRECIS 0 //!< Default precision
+#define U_OUT_STRING_PRECIS 1 //!< String precision
+#define U_OUT_CHARACTER_PRECIS 2 //!< Character precision
+#define U_OUT_STROKE_PRECIS 3 //!< Stroke precision
+#define U_OUT_TT_PRECIS 4 //!< Tt precision
+#define U_OUT_DEVICE_PRECIS 5 //!< Device precision
+#define U_OUT_RASTER_PRECIS 6 //!< Raster precision
+#define U_OUT_TT_ONLY_PRECIS 7 //!< Tt_only precision
+#define U_OUT_OUTLINE_PRECIS 8 //!< Outline precision
+/** @} */
+
+/** \defgroup U_EMF_LOGFONT_lfClipPrecision_Qualifiers EMF LF_ClipPrecision Enumeration
+ For U_LOGFONT lfClipPrecision field
+ EMF manual 2.2.13 & WMF manual 2.1.2.1
+ @{
+*/
+#define U_CLIP_DEFAULT_PRECIS 0x00 //!< Use default clipping precision.
+#define U_CLIP_CHARACTER_PRECIS 0x01 //!< Use character clipping precision
+#define U_CLIP_STROKE_PRECIS 0x02 //!< (Source documentation is vague about what this means.)
+#define U_CLIP_MASK 0x0F //!< MASK for bits in preceding.
+#define U_CLIP_LH_ANGLES 0x10 //!< Set: font rotation by coordinate system, Clear: device fonts (only) rotate counterclockwise.
+#define U_CLIP_TT_ALWAYS 0x20 //!< Reserved.
+#define U_CLIP_EMBEDDED 0x80 //!< Font embedding is required. (Method for doing so is not documented in EMF or WMF.)
+/** @} */
+
+/** \defgroup U_EMF_LOGFONT_lfQuality_Qualifiers EMF LF_Quality Enumeration
+ For For U_LOGFONT lfQuality field
+ EMF manual 2.2.13 & WMF manual 2.1.1.10
+ @{
+*/
+#define U_DEFAULT_QUALITY 0 //!< Default quality
+#define U_DRAFT_QUALITY 1 //!< Draft quality
+#define U_PROOF_QUALITY 2 //!< Proof quality
+#define U_NONANTIALIASED_QUALITY 3 //!< Nonantialiased quality
+#define U_ANTIALIASED_QUALITY 4 //!< Antialiased quality
+/** @} */
+
+/** \defgroup U_EMF_LOGFONT_lfPitchAndFamily_Qualifiers EMF LF_PitchAndFamily Enumeration
+ For U_LOGFONT lfPitchAndFamily field
+ EMF manual 2.2.13 & WMF manual 2.2.2.14
+ @{
+*/
+#define U_DEFAULT_PITCH 0x00 //!< Default pitch
+#define U_FIXED_PITCH 0x01 //!< Fixed pitch
+#define U_VARIABLE_PITCH 0x02 //!< Variable pitch
+#define U_MONO_FONT 0x08 //!< Mono font
+#define U_FF_DONTCARE 0x00 //!< Font family don't care
+#define U_FF_ROMAN 0x10 //!< Font family Roman
+#define U_FF_SWISS 0x20 //!< Font family Swiss
+#define U_FF_MODERN 0x30 //!< Font family Modern
+#define U_FF_SCRIPT 0x40 //!< Font family Script
+#define U_FF_DECORATIVE 0x50 //!< Font family Decorative
+/** @} */
+
+/** \defgroup U_EMF_LOGBRUSH_lbStyle_Qualifiers EMF LB_Style Enumeration
+ For U_LOGBRUSH lbStyle field
+ EMF manual 2.2.20
+ @{
+*/
+#define U_BS_SOLID 0 //!< Solid brush.
+#define U_BS_NULL 1 //!< Null brush.
+#define U_BS_HOLLOW 1 //!< Hollow brush.
+#define U_BS_HATCHED 2 //!< Hatched brush.
+#define U_BS_PATTERN 3 //!< Pattern brush.
+#define U_BS_INDEXED 4 //!< Indexed brush.
+#define U_BS_DIBPATTERN 5 //!< Dibpattern brush.
+#define U_BS_DIBPATTERNPT 6 //!< Dibpatternpt brush.
+#define U_BS_PATTERN8X8 7 //!< Pattern 8x8 brush.
+#define U_BS_DIBPATTERN8X8 8 //!< Dibpattern 8x8 brush.
+#define U_BS_MONOPATTERN 9 //!< Monopattern brush.
+/** @} */
+
+/** \defgroup U_EMF_PANOSE_index EMF PanoseIndex Enumeration
+ Fositions of each field in U_PANOSE structure.
+ Microsoft name: (none)
+ EMF manual 2.2.21
+ @{
+*/
+#define U_PAN_FAMILYTYPE_INDEX 0 //!< Familytype index
+#define U_PAN_SERIFSTYLE_INDEX 1 //!< Serifstyle index
+#define U_PAN_WEIGHT_INDEX 2 //!< Weight index
+#define U_PAN_PROPORTION_INDEX 3 //!< Proportion index
+#define U_PAN_CONTRAST_INDEX 4 //!< Contrast index
+#define U_PAN_STROKEVARIATION_INDEX 5 //!< Strokevariation index
+#define U_PAN_ARMSTYLE_INDEX 6 //!< Armstyle index
+#define U_PAN_LETTERFORM_INDEX 7 //!< Letterform index
+#define U_PAN_MIDLINE_INDEX 8 //!< Midline index
+#define U_PAN_XHEIGHT_INDEX 9 //!< Xheight index
+#define U_PAN_COUNT 10 //!< Count
+/** @} */
+
+
+/** \defgroup U_EMF_PIXELFORMATDESCRIPTOR_iLayerType_Qualifiers EMF PFD_iLayerType Enumeration
+ For U_PIXELFORMATDESCRIPTOR iLayerType field
+ Microsoft name: (none)
+ EMF manual 2.2.22
+ @{
+*/
+#define U_PFD_MAIN_PLANE 0 //!< Main plane
+#define U_PFD_OVERLAY_PLANE 1 //!< Overlay plane
+#define U_PFD_UNDERLAY_PLANE (-1) //!< Underlay plane
+/** @} */
+
+/** \defgroup U_EMF_PIXELFORMATDESCRIPTOR_iPixelType_Qualifiers EMF PFD_iPixelType Enumeration
+ For U_PIXELFORMATDESCRIPTOR iPixelType field
+ Microsoft name: (none)
+ EMF manual 2.2.22
+ @{
+*/
+#define U_PFD_TYPE_RGBA 0 //!< Pixel contains an RGBA value.
+#define U_PFD_TYPE_COLORINDEX 1 //!< Pixel contains an index into the color table.
+/** @} */
+
+/** \defgroup U_EMF_PIXELFORMATDESCRIPTOR_dwFlags_Qualifiers EMF PFD_dwFlags Enumeration
+ For U_PIXELFORMATDESCRIPTOR dwFlags field
+ EMF manual 2.2.22
+ @{
+*/
+#define U_PFD_DOUBLEBUFFER 0x00000001 //!< Doublebuffer
+#define U_PFD_STEREO 0x00000002 //!< Stereo
+#define U_PFD_DRAW_TO_WINDOW 0x00000004 //!< Draw to window
+#define U_PFD_DRAW_TO_BITMAP 0x00000008 //!< Draw to bitmap
+#define U_PFD_SUPPORT_GDI 0x00000010 //!< Support gdi
+#define U_PFD_SUPPORT_OPENGL 0x00000020 //!< Support opengl
+#define U_PFD_GENERIC_FORMAT 0x00000040 //!< Generic format
+#define U_PFD_NEED_PALETTE 0x00000080 //!< Need palette
+#define U_PFD_NEED_SYSTEM_PALETTE 0x00000100 //!< Need system palette
+#define U_PFD_SWAP_EXCHANGE 0x00000200 //!< Swap exchange
+#define U_PFD_SWAP_COPY 0x00000400 //!< Swap copy
+#define U_PFD_SWAP_LAYER_BUFFERS 0x00000800 //!< Swap layer buffers
+#define U_PFD_GENERIC_ACCELERATED 0x00001000 //!< Generic accelerated
+/** @} */
+
+/** \defgroup U_EMF_EMRCOMMENT_TYPES EMF Comment record types
+ For U_EMRCOMMENT_* cIdent fields
+ EMF manual 2.3.3
+ @{
+*/
+#define U_EMR_COMMENT_PUBLIC 0x43494447 //!< Public comment.
+#define U_EMR_COMMENT_SPOOL 0x00000000 //!< Spool comment.
+#define U_EMR_COMMENT_EMFPLUSRECORD 0x2B464D45 //!< EMF+ record comment.
+/** @} */
+
+/** \defgroup U_EMF_EMRSETLAYOUT_iMode_Qualifiers EMF Mirroring Enumeration
+ For U_EMRSETLAYOUT iMode field
+ EMF manual 2.3.11.17
+ @{
+*/
+#define U_LAYOUT_LTR 0x00000000 //!< Left to right lsyout.
+#define U_LAYOUT_RTL 0x00000001 //!< Right to left layout.
+#define U_LAYOUT_BITMAPORIENTATIONPRESERVED 0x00000008 //!< Do not flip bitmaps if layout is right to left.
+/** @} */
+
+
+/** \defgroup U_EMF_BLEND_Op_Qualifiers EMF Blend Enumeration
+ For U_BLEND Op field
+ @{
+*/
+#define U_AC_SRC_GLOBAL 0 //!< Global
+#define U_AC_SRC_CONST 0 //!< Const
+#define U_AC_SRC_ALPHA 1 //!< Alpha
+/** @} */
+
+
+// ***************************************************************************
+// Macros
+
+/** \defgroup U_EMF_Common_macros EMF Common Macros
+ @{
+*/
+// Note, many of these were originally defined using C99 (type){val,val,val} format, but that turned out to
+// have incompatibilities with C++, so use functions as the basis to avoid this.
+
+// Set/Get for U_RGBQUAD Colors, which are stored in byte order: {B,G,R,A}.
+// These are used in EMF structures and the byte order must be the same in memory or on disk.
+#define U_BGR(r,g,b) rgbquad_set(r, g, b, 0) //!< Set any BGR color with an {r,g,b} triplet
+#define U_BGRA(r,g,b,a) rgbquad_set(r, g, b, a) //!< Set any BGRA color with an {r,g,b,a} quad
+#define U_WHITE U_BGR(255,255,255) //!< Set BGR white.
+#define U_BLACK U_BGR(0,0,0) //!< Set BGR black.
+#define U_BGRAGetR(rgb) (rgb.Red ) //!< Color BGR Red.
+#define U_BGRAGetG(rgb) (rgb.Green ) //!< Color BGR Green.
+#define U_BGRAGetB(rgb) (rgb.Blue ) //!< Color BGR Blue.
+#define U_BGRAGetA(rgb) (rgb.Reserved) //!< Color BGRA A/reserved
+
+
+// Set/Get for U_COLORREF Color, which are stored in byte order:: {R,G,B,A}.
+// These are used in EMF structures and the byte order must be the same in memory or on disk.
+// These MAY be used in PNG and other libraries if these enforce byte order in memory, otherwise
+// U_swap4 may need to also be employed.
+//
+
+#define colorref_set colorref3_set //!< Most frequent usage is 3 colors, so set the unqualified one to that
+#define U_RGB(r,g,b) colorref3_set(r, g, b) //!< Set any RGB color with an {r,g,b} triplet
+#define U_RGBA(r,g,b,a) colorref4_set(r, g, b, a) //!< Set any RGBA color with an {r,g,b,a} quad
+#define U_RGBAGetR(rgb) (rgb.Red ) //!< Color RGB Red.
+#define U_RGBAGetG(rgb) (rgb.Green ) //!< Color RGB Green
+#define U_RGBAGetB(rgb) (rgb.Blue ) //!< Color RGB Blue
+#define U_RGBAGetA(rgb) (rgb.Reserved) //!< Color RGBA A/reserved
+
+// color type conversions
+#define U_RGB2BGR(rgb) U_BGR(U_RGBAGetR(rgb),U_RGBAGetG(rgb),U_RGBAGetB(rgb)) //!< Set any BGR color from an RGB color
+#define U_BGR2RGB(rgb) U_RGB(U_BGRAGetR(rgb),U_BGRAGetG(rgb),U_BGRAGetB(rgb)) //!< Set any RGB color from an BGR color
+#define U_RGBA2BGRA(rgb) U_BGRA(U_RGBAGetR(rgb),U_RGBAGetG(rgb),U_RGBAGetB(rgb),U_RGBAGetA(rgb)} //!< Set any BGRA color from an RGBA color
+#define U_BGRA2RGBA(rgb) U_RGBA(U_BGRAGetR(rgb),U_BGRAGetG(rgb),U_BGRAGetB(rgb),U_BGRAGetA(rgb)} //!< Set any RGBA color from an BGRA color
+
+// Color CMYK Get/Set Macros
+#define U_CMYK(c,m,y,k)\
+ ((COLOREF)((((uint8_t)(k)|((uint16_t)((uint8_t)(y))<<8))|(((uint32_t)(uint8_t)(m))<<16))|(((uint32_t)(uint8_t)(c))<<24))) \
+ //!< Color CMYK Set Macro.
+#define U_GetKValue(cmyk) ((uint8_t) (cmyk) ) //!< Color CMYK Get K Macro.
+#define U_GetYValue(cmyk) ((uint8_t) ((cymk) >> 8)) //!< Color CMYK Get Y Macro.
+#define U_GetMValue(cmyk) ((uint8_t) ((cymk) >> 16)) //!< Color CMYK Get M Macro.
+#define U_GetCValue(cmyk) ((uint8_t) ((cymk) >> 24)) //!< Color CMYK Get C Macro.
+
+// Other macros
+#define U_Gamma(A) (A < U_RGB_GAMMA_MIN ? U_RGB_GAMMA_MIN : (A > U_RGB_GAMMA_MAX ? U_RGB_GAMMA_MAX: A)) \
+ //!< Gamma set Macro (enforce range).
+#define U_PM(A,B) ((A)<-(B)?-(B):((A)>(B)?(B):(A))) //!< Plus/Minus Range Macro (B must be postitive!).
+#define U_MNMX(A,B,C) ((A)<(B)?(B):((A)>(C)?(C):(A))) //!< Min/Max Range Macro (B <= A <= C).
+#define U_MIN(A,B) ((A)>(B)?(B):(A)) //!< Minimum of A,B
+#define U_MAX(A,B) ((A)>(B)?(A):(B)) //!< Maximum of A,B
+
+// basic EMR macros.
+#define U_EMRTYPE(A) (((PU_EMR)A)->iType) //!< Get iType from U_EMR* record
+#define U_EMRSIZE(A) (((PU_EMR)A)->nSize) //!< Get nSize from U_EMR* record
+
+// Utility macros
+#define UP4(A) (4 * ((A + 3 ) / 4)) //!< Round up to nearest multiple of 4
+
+/** @} */
+
+/** Any generic pair of floats.
+
+ Microsoft name: (none)
+*/
+typedef struct {
+ float x; //!< X value
+ float y; //!< Y value
+} U_PAIRF,
+ *PU_PAIRF; //!< Any generic pair of floats. Microsoft name: (none)
+
+
+/* ************************************************************
+ EMF structures OTHER than those corresponding to complete U_EMR_* records
+ ************************************************************ */
+
+/**
+ \brief For U_POINT28_4 x and y fields.
+
+ EMF manual 2.2.1, Microsoft name: BitFIX28_4 Object.
+*/
+typedef struct {
+ signed IntValue :28; //!< Signed integral bit field
+ unsigned FracValue :4; //!< Unsigned integral bit field
+} U_BITFIX28_4,
+ *PU_BITFIX28_4; //!< EMF manual 2.2.1
+
+/**
+ \brief For U_EMRSETOLORADJUSTMENT ColorAdjustment field
+
+ EMF manual 2.2.2, Microsoft name: ColorAdjustment Object
+
+ Note, range constants are: RGB_GAMMA_[MIN|MAX],REFERENCE_[WHITE|BLACK]_[MIN|MAX],COLOR_ADJ_[MIN|MAX]
+*/
+typedef struct {
+ uint16_t caSize; //!< Size of this structure in bytes
+ uint16_t caFlags; //!< ColorAdjustment Enumeration
+ uint16_t caIlluminantIndex; //!< Illuminant Enumeration
+ uint16_t caRedGamma; //!< Red Gamma correction (range:2500:65000, 10000 is no correction)
+ uint16_t caGreenGamma; //!< Green Gamma correction (range:2500:65000, 10000 is no correction)
+ uint16_t caBlueGamma; //!< Blue Gamma correction (range:2500:65000, 10000 is no correction)
+ uint16_t caReferenceBlack; //!< Values less than this are black (range:0:4000)
+ uint16_t caReferenceWhite; //!< Values more than this are white (range:6000:10000)
+ int16_t caContrast; //!< Contrast adjustment (range:-100:100, 0 is no correction)
+ int16_t caBrightness; //!< Brightness adjustment (range:-100:100, 0 is no correction)
+ int16_t caColorfulness; //!< Colorfulness adjustment (range:-100:100, 0 is no correction)
+ int16_t caRedGreenTint; //!< Tine adjustment (range:-100:100, 0 is no correction)
+} U_COLORADJUSTMENT,
+ *PU_COLORADJUSTMENT; //!< EMF manual 2.2.2
+
+/** EMF manual 2.2.3
+ \brief For ? (not implemented yet)
+
+ Microsoft name: DesignVector Object
+*/
+typedef struct {
+ uint32_t Signature; //!< Must be 0x08007664 (AKA: DV_SGNTR)
+ U_NUM_FNTAXES NumAxes; //!< Number of elements in Values, 0-16
+ U_FNTAXES Values[1]; //!< Optional. Array of font axes for opentype font
+} U_DESIGNVECTOR,
+ *PU_DESIGNVECTOR; //!< EMF manual 2.2.3
+#define U_SIZE_DESIGNVECTOR (sizeof(uint32_t) + sizeof(U_NUM_FNTAXES))
+
+/**
+ \brief For U_EMR_COMMENT_MULTIFORMATS record, where an array of these is used
+
+ EMF manual 2.2.4, Microsoft name: EmrFormat Object
+*/
+typedef struct {
+ uint32_t signature; //!< FormatSignature Enumeration
+ uint32_t nVersion; //!< Must be 1 if signature is EPS, else ignored
+ U_CBDATA cbData; //!< Data size in bytes
+ U_OFFDATA offData; //!< Offset in bytes to the Data from the start of the RECORD
+} U_EMRFORMAT,
+ *PU_EMRFORMAT; //!< EMF manual 2.2.4
+
+/**
+
+ \brief For U_EMR[POLY]EXTTEXTOUT[A|W] emrtext field
+
+ EMF manual 2.2.5, Microsoft name: EmrText Object
+
+ Differs from implementation in Mingw and Wine in that the core struct has a fixed size.
+ Optional and movable components must be handled with offsets.
+ Following invariant core there may/must be:
+
+ U_RECTL rcl; (Optional, absent when fOptions & U_ETO_NO_RECT) grayed/clipping/opaque rectangle
+
+ U_OFFDX offDx; (required) but position isn't static. Offset in bytes to the character spacing array measured
+ from the start of the RECORD, NOT from the start of this structure.
+
+ The order of the next two may be reversed, they are found from their offsets.
+
+ char string (required) String buffer holding nChars (padded to a multiple of 4 bytes in length).
+
+ uint32_t Dx[1] (required) character spacing, array with one entry per glyph.
+*/
+typedef struct {
+ U_POINTL ptlReference; //!< String start coordinates
+ U_NUM_STR nChars; //!< Number of characters in the string
+ U_OFFSTR offString; //!< Offset in bytes to the string from the start of the RECORD
+ uint32_t fOptions; //!< ExtTextOutOptions Enumeration
+} U_EMRTEXT,
+ *PU_EMRTEXT; //!< EMF manual 2.2.5
+
+/**
+ \brief For U_EPS_DATA Points field
+
+ EMF manual 2.2.23, Microsoft name: Point28_4 Object, out of order, needed for 2.2.6
+*/
+typedef struct {
+ U_BITFIX28_4 x; //!< X coordinate
+ U_BITFIX28_4 y; //!< Y coordinate
+} U_POINT28_4,
+ *PU_POINT28_4; //!< EMF manual 2.2.23
+
+/**
+ \brief For embedding EPS in EMF via U_EMRFORMAT offData array in U_EMR_COMMENT_MULTIFORMATS
+
+ EMF manual 2.2.6, Microsoft name: EpsData Object
+*/
+typedef struct {
+ uint32_t sizeData; //!< Size in bytes of this object
+ uint32_t version; //!< Must be 1
+ U_POINT28_4 Points[3]; //!< Defines parallelogram, UL, UR, LL corners, LR is derived.
+ U_RECTL PostScriptData; //!< Record may include optional clipping/opaque rectangle
+} U_EPS_DATA,
+ *PU_EPS_DATA; //!< EMF manual 2.2.6
+
+/**
+ \brief For GRADIENT_[TRIANGLE|U_RECT]
+
+ EMF manual 2.2.26, Microsoft name: TriVertex Object, out of order, needed for 2.2.7
+*/
+typedef struct {
+ int32_t x; //!< X coord
+ int32_t y; //!< Y coord
+ uint16_t Red; //!< Red component
+ uint16_t Green; //!< Green component
+ uint16_t Blue; //!< Bule component
+ uint16_t Alpha; //!< Alpha Transparency
+} U_TRIVERTEX,
+ *PU_TRIVERTEX; //!< EMF manual 2.2.26
+
+/**
+ \brief For U_EMRGRADIENTFILL GradObj field
+
+ EMF manual 2.2.7, Microsoft name: GradientRectangle Object
+*/
+typedef struct {
+ uint32_t UpperLeft; //!< Index of UL corner in an array of U_TRIVERTEX objects
+ uint32_t LowerRight; //!< Index of LR corner in an array of U_TRIVERTEX objects
+} U_GRADIENT4,
+ *PU_GRADIENT4; //!< EMF manual 2.2.7
+
+/**
+ \brief For U_EMRGRADIENTFILL GradObj field
+
+ EMF manual 2.2.8, Microsoft name: GradientTriangle Object
+
+ Gradient object notes. The next two structures are used to define the shape with reference to an existing array
+ of points stored in an array of TriVertex objects in the U_EMRGRADIENTFILL record. The tricky part
+ is that these two structures are different sizes. In some implementations (MingW) the array is cast to uint32_t
+ and basically the cast is then ignored. For libUEMF we leave this out of the structure entirely and get to it with offsets.
+*/
+typedef struct {
+ uint32_t Vertex1; //!< Index of Vertex1 in an array of U_TRIVERTEX objects
+ uint32_t Vertex2; //!< Index of Vertex2 in an array of U_TRIVERTEX objects
+ uint32_t Vertex3; //!< Index of Vertex3 in an array of U_TRIVERTEX objects
+} U_GRADIENT3,
+ *PU_GRADIENT3; //!< EMF manual 2.2.8
+
+//Microsoft name: Header object, EMF manual 2.2.9 defined below with record structs
+//Microsoft name: HeaderExtension1 object, EMF manual 2.2.10 defined below with record structs
+//Microsoft name: HeaderExtension1 object, EMF manual 2.2.11 defined below with record structs
+
+/**
+ \brief For U_EMRCREATEBRUSHINDIRECT lb field
+
+ EMF manual 2.2.12, Microsoft name: LogBrushEx Object
+*/
+typedef struct { //!< In MS documentation this is LogBrushEx Object
+ uint32_t lbStyle; //!< LB_Style Enumeration
+ U_COLORREF lbColor; //!< Brush color
+ uint32_t lbHatch; //!< HatchStyle Enumeration
+} U_LOGBRUSH,
+ U_PATTERN, //!< EMF manual 2.2.12
+ *PU_LOGBRUSH, //!< EMF manual 2.2.12
+ *PU_PATTERN; //!< EMF manual 2.2.12
+
+/**
+ \brief For U_LOGFONT elfLogFont field
+
+ EMF manual 2.2.13, Microsoft name: LogFont Object
+*/
+typedef struct {
+ int32_t lfHeight; //!< Height in Logical units
+ int32_t lfWidth; //!< Average Width in Logical units
+ int32_t lfEscapement; //!< Angle in 0.1 degrees betweem escapement vector and X axis
+ int32_t lfOrientation; //!< Angle in 0.1 degrees between baseline and X axis
+ int32_t lfWeight; //!< LF_Weight Enumeration
+ uint8_t lfItalic; //!< LF_Italic Enumeration
+ uint8_t lfUnderline; //!< LF_Underline Enumeration
+ uint8_t lfStrikeOut; //!< LF_StrikeOut Enumeration
+ uint8_t lfCharSet; //!< LF_CharSet Enumeration
+ uint8_t lfOutPrecision; //!< LF_OutPrecision Enumeration
+ uint8_t lfClipPrecision; //!< LF_ClipPrecision Enumeration
+ uint8_t lfQuality; //!< LF_Quality Enumeration
+ uint8_t lfPitchAndFamily; //!< LF_PitchAndFamily Enumeration
+ uint16_t lfFaceName[U_LF_FACESIZE]; //!< Name of font. If <U_LF_FACESIZE chars must be null terminated
+} U_LOGFONT,
+ *PU_LOGFONT; //!< EMF manual 2.2.13
+
+// Microsoft name: LogFontEx Object (not implemented) EMF manual 2.2.14
+// Microsoft name: LogFontExDv Object (not implemented) EMF manual 2.2.15
+
+/**
+ \brief For U_LOGFONT_PANOSE elfPanose field
+
+ EMF manual 2.2.21, Microsoft name: Panose Object
+*/
+// out of order, needed for 2.2.16
+typedef struct {
+ uint8_t bFamilyType; //!< FamilyType Enumeration
+ uint8_t bSerifStyle; //!< SerifType Enumeration
+ uint8_t bWeight; //!< Weight Enumeration
+ uint8_t bProportion; //!< Proportion Enumeration
+ uint8_t bContrast; //!< Contrast Enumeration
+ uint8_t bStrokeVariation; //!< StrokeVariation Enumeration
+ uint8_t bArmStyle; //!< ArmStyle Enumeration
+ uint8_t bLetterform; //!< Letterform Enumeration
+ uint8_t bMidline; //!< Midline Enumeration
+ uint8_t bXHeight; //!< XHeight Enumeration
+} U_PANOSE,
+ *PU_PANOSE; //!< EMF manual 2.2.21
+
+#define U_PAN_ALL0 (U_PANOSE){0,0,0,0,0,0,0,0,0,0} //!< all U_PAN_ANY, have not seen this in an EMF file
+#define U_PAN_ALL1 (U_PANOSE){1,1,1,1,1,1,1,1,1,1} //!< all U_PAN_NO_FIT, this is what createfont() would have made
+
+/**
+ \brief For U_EMREXTCREATEFONTINDIRECTW elfw field
+
+ EMF manual 2.2.16, Microsoft name: LogFontPanose Object
+*/
+typedef struct {
+ U_LOGFONT elfLogFont; //!< Basic font attributes
+ uint16_t elfFullName[U_LF_FULLFACESIZE]; //!< Font full name
+ uint16_t elfStyle[U_LF_FACESIZE]; //!< Font style (if <U_LF_FACESIZE characters, null terminate string)
+ uint32_t elfVersion; //!< Ignore
+ uint32_t elfStyleSize; //!< Font hinting starting at this point size, if 0, starts at Height
+ uint32_t elfMatch; //!< Ignore
+ uint32_t elfReserved; //!< Must be 0, Ignore
+ uint8_t elfVendorId[U_ELF_VENDOR_SIZE]; //!< Ignore
+ uint32_t elfCulture; //!< Must be 0, Ignore
+ U_PANOSE elfPanose; //!< Panose Object. If all zero, it is ignored.
+ uint16_t elfPadding; //!< Ignore
+} U_LOGFONT_PANOSE,
+ *PU_LOGFONT_PANOSE; //!< EMF manual 2.2.16
+
+/**
+ \brief For U_LOGPALETTE palPalEntry field(s)
+
+ EMF manual 2.2.18, Microsoft name: LogPaletteEntry Object
+*/
+// out of order, needed for 2.2.17
+typedef struct {
+ uint8_t peReserved; //!< Ignore
+ uint8_t peRed; //!< Palette entry Red Intensity
+ uint8_t peGreen; //!< Palette entry Green Intensity
+ uint8_t peBlue; //!< Palette entry Blue Intensity
+} U_LOGPLTNTRY,
+ *PU_LOGPLTNTRY; //!< EMF manual 2.2.18
+
+/**
+ \brief For U_EMRCREATEPALETTE lgpl field
+
+ EMF manual 2.2.17, Microsoft name: LogPalette Object
+
+*/
+typedef struct {
+ uint16_t palVersion; //!< Must be 0x0300 (AKA: U_LP_VERSION)
+ uint16_t palNumEntries; //!< Number of U_LOGPLTNTRY objects
+ U_LOGPLTNTRY palPalEntry[1]; //!< PC_Entry Enumeration
+} U_LOGPALETTE,
+ *PU_LOGPALETTE; //!< EMF manual 2.2.17
+#define U_SIZE_LOGPALETTE (2*sizeof(uint16_t))
+
+// Microsoft name: LogPaletteEntry Object, EMF manual 2.2.18, defined above, before 2.2.17
+
+/**
+ \brief For U_EMRCREATEPEN lopn field
+
+ EMF manual 2.2.19, Microsoft name: LogPen Object
+*/
+typedef struct {
+ uint32_t lopnStyle; //!< PenStyle Enumeration
+ U_POINT lopnWidth; //!< Width of pen set by X, Y is ignored
+ U_COLORREF lopnColor; //!< Pen color value
+} U_LOGPEN,
+ *PU_LOGPEN; //!< EMF manual 2.2.19
+
+// Microsoft name: LogPenEx Object (not implemented) EMF manual 2.2.20
+// Microsoft name: Panose Object, EMF manual 2.2.21, defined above, before 2.2.16
+
+/**
+ \brief For U_EMRPIXELFORMAT pfd field
+
+ EMF manual 2.2.22, Microsoft name: PixelFormatDescriptor Object
+*/
+typedef struct {
+ uint16_t nSize; //!< Structure size in bytes
+ uint16_t nVersion; //!< must be 1
+ uint32_t dwFlags; //!< PFD_dwFlags Enumeration
+ uint8_t iPixelType; //!< PFD_iPixelType Enumeration
+ uint8_t cColorBits; //!< RGBA: total bits per pixel
+ uint8_t cRedBits; //!< Red bits per pixel
+ uint8_t cRedShift; //!< Red shift to data bits
+ uint8_t cGreenBits; //!< Green bits per pixel
+ uint8_t cGreenShift; //!< Green shift to data bits
+ uint8_t cBlueBits; //!< Blue bits per pixel
+ uint8_t cBlueShift; //!< Blue shift to data bits
+ uint8_t cAlphaBits; //!< Alpha bits per pixel
+ uint8_t cAlphaShift; //!< Alpha shift to data bits
+ uint8_t cAccumBits; //!< Accumulator buffer, total bitplanes
+ uint8_t cAccumRedBits; //!< Red accumulator buffer bitplanes
+ uint8_t cAccumGreenBits; //!< Green accumulator buffer bitplanes
+ uint8_t cAccumBlueBits; //!< Blue accumulator buffer bitplanes
+ uint8_t cAccumAlphaBits; //!< Alpha accumulator buffer bitplanes
+ uint8_t cDepthBits; //!< Depth of Z-buffer
+ uint8_t cStencilBits; //!< Depth of stencil buffer
+ uint8_t cAuxBuffers; //!< Depth of auxilliary buffers (not supported)
+ uint8_t iLayerType; //!< PFD_iLayerType Enumeration, may be ignored
+ uint8_t bReserved; //!< Bits 0:3/4:7 are number of Overlay/Underlay planes
+ uint32_t dwLayerMask; //!< may be ignored
+ uint32_t dwVisibleMask; //!< color or index of underlay plane
+ uint32_t dwDamageMask; //!< may be ignored
+} U_PIXELFORMATDESCRIPTOR,
+ *PU_PIXELFORMATDESCRIPTOR; //!< EMF manual 2.2.22
+
+// Microsoft name: Point28_4 Object. EMF manual 2.2.23, defined above, before 2.2.6
+
+/**
+ \brief For U_RGNDATA rdb field
+
+ EMF manual 2.2.25, Microsoft name: RegionDataHeader Object (RGNDATAHEADER)
+*/
+// out of order, needed for 2.2.24
+typedef struct {
+ uint32_t dwSize; //!< Size in bytes, must be 0x20 (AKA: U_RDH_OBJSIZE)
+ uint32_t iType; //!< Must be 1 (AKA: U_RDH_RECTANGLES)
+ U_NUM_RECTL nCount; //!< Number of rectangles in region
+ uint32_t nRgnSize; //!< Size in bytes of rectangle buffer
+ U_RECTL rclBounds; //!< Region bounds
+} U_RGNDATAHEADER,
+ *PU_RGNDATAHEADER; //!< EMF manual 2.2.25
+#define U_SIZE_RGNDATAHEADER (sizeof(U_RGNDATAHEADER))
+
+/**
+ \brief For U_EMRFILLRGN RgnData field(s)
+
+ EMF manual 2.2.24, Microsoft name: RegionData Object
+
+*/
+typedef struct {
+ U_RGNDATAHEADER rdh; //!< Data description
+ U_RECTL Buffer[1]; //!< Array of U_RECTL elements
+} U_RGNDATA,
+ *PU_RGNDATA; //!< EMF manual 2.2.24
+#define U_SIZE_RGNDATA U_SIZE_RGNDATAHEADER
+
+// Microsoft name: RegionDataHeader Object. EMF manual 2.2.25, defined above, before 2.2.24
+// Microsoft name: TriVertex Object. EMF manual 2.2.26, defined above, before 2.2.7
+// Microsoft name: UniversalFontId Object. EMF manual 2.2.27 (not implemented)
+
+/**
+ \brief For U_EMR[FILLRGN|STRETCHBLT|MASKBLT|PLGBLT] xformSrc field
+
+ EMF manual 2.2.28, Microsoft name: Xform Object
+*/
+typedef struct {
+ U_FLOAT eM11; //!< Matrix element M11
+ U_FLOAT eM12; //!< Matrix element M12
+ U_FLOAT eM21; //!< Matrix element M21
+ U_FLOAT eM22; //!< Matrix element M22
+ U_FLOAT eDx; //!< X offset in logical units
+ U_FLOAT eDy; //!< Y offset in logical units
+} U_XFORM ,
+ *PU_XFORM; //!< EMF manual 2.2.28
+
+/**
+ \brief For U_EMREXTCREATEPEN lopn field
+
+ EMF manual 2.2.20, Microsoft name: LogPenEx Object
+*/
+typedef struct {
+ uint32_t elpPenStyle; //!< PenStyle Enumeration
+ uint32_t elpWidth; //!< Width in logical units (elpPenStyle & U_PS_GEOMETRIC) or 1 (pixel)
+ uint32_t elpBrushStyle; //!< LB_Style Enumeration
+ U_COLORREF elpColor; //!< Pen color
+ uint32_t elpHatch; //!< HatchStyle Enumeration
+ U_NUM_STYLEENTRY elpNumEntries; //!< Count of StyleEntry array
+ U_STYLEENTRY elpStyleEntry[1]; //!< Array of StyleEntry (For user specified dot/dash patterns)
+} U_EXTLOGPEN,
+ *PU_EXTLOGPEN; //!< EMF manual 2.2.20
+#define U_SIZE_EXTLOGPEN (sizeof(U_EXTLOGPEN) - sizeof(U_STYLEENTRY)) // there may not be any style entries
+
+/**
+ \brief For U_EMR_* OffBmi* fields
+
+ WMF Manual 2.2.2.9, Microsoft name: (none).
+
+ Description of a Bitmap which in some cases is a Device Independent Bitmap (DIB)
+*/
+typedef struct {
+ U_BITMAPINFOHEADER bmiHeader; //!< Geometry and pixel properties
+ U_RGBQUAD bmiColors[1]; //!< Color table. 24 bit images do not use color table values.
+} U_BITMAPINFO,
+ *PU_BITMAPINFO; //!< WMF Manual 2.2.2.9
+#define U_SIZE_BITMAPINFO U_SIZE_BITMAPINFOHEADER
+
+/**
+ \brief U_EMRALPHABLEND Blend field
+
+ EMF Manual 2.3.1.1, Microsoft name: BLENDFUNCTION field of EMR_ALPHABLEND record.
+*/
+typedef struct {
+ uint8_t Operation; //!< Must be 0
+ uint8_t Flags; //!< Must be 0
+ uint8_t Global; //!< Alpha for whole thing if Op is U_AC_SRC_GLOBAL (AKA U_AC_SRC_GLOBAL)
+ uint8_t Op; //!< Blend Enumeration
+} U_BLEND,
+ *PU_BLEND; //!< EMF Manual 2.3.1.1
+#
+
+/**
+ General form of an EMF record.
+ Microsoft name: ENHMETARECORD Object
+ For generic cast of other U_EMR_* records
+*/
+typedef struct {
+ uint32_t iType; //!< Type of EMR record
+ uint32_t nSize; //!< Size of entire record in bytes (multiple of 4).
+ uint32_t dParm[1]; //!< Data in record
+} U_ENHMETARECORD,
+ *PU_ENHMETARECORD; //!< General form of an EMF record.
+#define U_SIZE_ENHMETARECORD (2*sizeof(uint32_t))
+
+/** First two fields of all EMF records,
+ First two fields of all EMF+ records (1 or more within an EMF comment)
+ For accessing iType and nSize files in all U_EMR* records
+ Microsoft name: EMR Object
+*/
+typedef struct {
+ uint32_t iType; //!< Type of EMR record
+ uint32_t nSize; //!< Size of entire record in bytes (multiple of 4).
+} U_EMR,
+ *PU_EMR; //!< First two fields of all EMF records,
+
+/** Generic EMR record with two 32 bit values.
+ Microsoft name: (none)
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_PAIR pair; //!< pair of 32 bit values
+} U_EMRGENERICPAIR,
+ *PU_EMRGENERICPAIR; //!< Generic EMR record with two 32 bit values. Microsoft name: (none)
+
+
+
+
+// ***********************************************************************************
+// The following have U_EMR_# records. They are ordered by their record index, not by EMF manual position.
+
+// records which are documented but not implemented
+#define U_SIZE_EMRNOTIMPLEMENTED 2048
+
+/* Index 1 */
+/**
+ \brief The first U_ENHMETARECORD record in the metafile.
+
+ EMF manual 2.2.9, Microsoft name: Header object, HeaderExtension1 object, HeaderExtension2 object
+
+ Microsoft names instead: Header, HeaderExtension1, and HeaderExtension2 objects. These are
+ used nowhere else, so they are combined here, along with the first two fields which were not listed in the Header.
+
+ Note also that three fields in this file (nBytes, nRecords, nHandles) must be (re)set after the entire EMF
+ is constructed, since typically they are not known until then. bOpenGL may or may not be knowable when this
+ header is written.
+
+ Note also that rclBounds and rclFrame are supposed to be the region bounding the drawn content within the
+ EMF. This is generally smaller than the size from szlDevice. However, since libUEMF does not actually draw
+ anything it has no way of knowing what these values are. Instead when it creates a header it sets these to
+ match the szl* fields.
+
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+ U_RECTL rclFrame; //!< Bounding rectangle in 0.01 mm units
+ uint32_t dSignature; //!< FormatSignature Enumeration (must be U_ENHMETA_SIGNATURE)
+ uint32_t nVersion; //!< Must be U_ENHMETA_VERSION (0x00010000)
+ uint32_t nBytes; //!< Length in bytes of the Metafile
+ uint32_t nRecords; //!< Records in the Metafile
+ uint16_t nHandles; //!< Number of graphics objects used in the Metafile
+ uint16_t sReserved; //!< Must be 0
+ uint32_t nDescription; //!< Characters in the Description field, 0 if no description
+ uint32_t offDescription; //!< Offset in bytes to optional UTF-16BE string Description field
+ uint32_t nPalEntries; //!< Number of Palette entries (in U_EMR_EOF record).
+ U_SIZEL szlDevice; //!< Reference device size in pixels
+ U_SIZEL szlMillimeters; //!< Reference device size in 0.01 mm
+ /** Fields for winver >= win95 */
+ U_CBPXLFMT cbPixelFormat; //!< Size in bytes of PixelFormatDescriptor, 0 if no PFD
+ U_OFFPXLFMT offPixelFormat; //!< Offset in bytes to optional PixelFormatDescriptor from the start of the RECORD, 0 if no PFD
+ uint32_t bOpenGL; //!< nonZero if OpenGL commands are included
+ /** Fields for winver >= win98 */
+ U_SIZEL szlMicrometers; //!< Size of the display device in micrometer
+} U_EMRHEADER,
+ *PU_EMRHEADER; //!< EMF manual 2.2.9
+#define U_SIZE_EMRHEADER sizeof(U_EMRHEADER) // modern EMF files, for _really_ old ones the _MIN size applies
+#define U_SIZE_EMRHEADER_MIN (U_SIZE_EMRHEADER - sizeof(U_CBPXLFMT) - sizeof(U_OFFPXLFMT) - sizeof(uint32_t) - sizeof(U_SIZEL))
+
+/* Index 2,3,4,5,6 */
+/** EMF manual 2.3.5.16
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< bounding rectangle in device units
+ U_NUM_POINTL cptl; //!< Number of points to draw
+ U_POINTL aptl[1]; //!< array of points
+} U_EMRPOLYBEZIER,
+ U_EMRPOLYGON, //!< EMF manual 2.3.5.22
+ U_EMRPOLYLINE, //!< EMF manual 2.3.5.24
+ U_EMRPOLYBEZIERTO, //!< EMF manual 2.3.5.18
+ U_EMRPOLYLINETO, //!< EMF manual 2.3.5.26
+ *PU_EMRPOLYBEZIER, //!< EMF manual 2.3.5.16
+ *PU_EMRPOLYGON, //!< EMF manual 2.3.5.22
+ *PU_EMRPOLYLINE, //!< EMF manual 2.3.5.24
+ *PU_EMRPOLYBEZIERTO, //!< EMF manual 2.3.5.18
+ *PU_EMRPOLYLINETO; //!< EMF manual 2.3.5.26
+
+#define U_SIZE_EMRPOLYBEZIER (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_NUM_POINTL) )
+#define U_SIZE_EMRPOLYGON U_SIZE_EMRPOLYBEZIER
+#define U_SIZE_EMRPOLYLINE U_SIZE_EMRPOLYBEZIER
+#define U_SIZE_EMRPOLYBEZIERTO U_SIZE_EMRPOLYBEZIER
+#define U_SIZE_EMRPOLYLINETO U_SIZE_EMRPOLYBEZIER
+/* Index 7,8 */
+/** EMF manual 2.3.5.30
+
+ After this struct the record also contains an array of points:\n
+ U_POINTL aptl[1];
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< bounding rectangle in device units
+ U_NUM_POLYCOUNTS nPolys; //!< Number of elements in aPolyCounts
+ U_NUM_POINTL cptl; //!< Total number of points (over all poly)
+ U_POLYCOUNTS aPolyCounts[1]; //!< Number of points in each poly (sequential)
+} U_EMRPOLYPOLYLINE,
+ U_EMRPOLYPOLYGON, //!< EMF manual 2.3.5.28
+ *PU_EMRPOLYPOLYLINE, //!< EMF manual 2.3.5.30
+ *PU_EMRPOLYPOLYGON; //!< EMF manual 2.3.5.28
+#define U_SIZE_EMRPOLYPOLYLINE (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_NUM_POLYCOUNTS) + sizeof(U_NUM_POINTL))
+#define U_SIZE_EMRPOLYPOLYGON U_SIZE_EMRPOLYPOLYLINE
+
+/* Index 9,11 (numbers interleave with next one) */
+/** EMF manual 2.3.11.30
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_SIZEL szlExtent; //!< H & V extent in logical units
+} U_EMRSETWINDOWEXTEX,
+ U_EMRSETVIEWPORTEXTEX, //!< EMF manual manual 2.3.11.28
+ *PU_EMRSETWINDOWEXTEX, //!< EMF manual manual 2.3.11.30
+ *PU_EMRSETVIEWPORTEXTEX; //!< EMF manual manual 2.3.11.28
+#define U_SIZE_EMRSETWINDOWEXTEX (sizeof(U_EMRSETWINDOWEXTEX ))
+#define U_SIZE_EMRSETVIEWPORTEXTEX (sizeof(U_EMRSETVIEWPORTEXTEX))
+
+/* Index 10,12,13 */
+/** EMF manual 2.3.11.31
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_POINTL ptlOrigin; //!< H & V origin in logical units
+} U_EMRSETWINDOWORGEX,
+ U_EMRSETVIEWPORTORGEX, //!< EMF manual 2.3.11.29
+ U_EMRSETBRUSHORGEX, //!< EMF manual 2.3.11.12
+ *PU_EMRSETWINDOWORGEX, //!< EMF manual 2.3.11.31
+ *PU_EMRSETVIEWPORTORGEX, //!< EMF manual 2.3.11.29
+ *PU_EMRSETBRUSHORGEX; //!< EMF manual 2.3.11.12
+#define U_SIZE_EMRSETWINDOWORGEX (sizeof(U_EMRSETWINDOWORGEX ))
+#define U_SIZE_EMRSETVIEWPORTORGEX (sizeof(U_EMRSETVIEWPORTORGEX))
+#define U_SIZE_EMRSETBRUSHORGEX (sizeof(U_EMRSETBRUSHORGEX ))
+
+/* Index 14 */
+/** EMF manual 3.2.4.1
+
+This is a very odd structure because the nSizeLast follows an optional variable size field. Consequently
+even though nSizeLast has a name it cannot actually be accessed by it! Following the core structure
+appear these fields:\n
+
+ U_LOGPLTNTRY PalEntries[1]; Record may include optional array of PalEntries
+
+ uint32_t nSizeLast; Mandatory, but position isn't fixed. Must have same value as emr.nSize in header record
+
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_CBPLENTRIES cbPalEntries; //!< Number of palette entries
+ U_OFFPLENTRIES offPalEntries; //!< Offset in bytes to array of palette entries
+} U_EMREOF,
+ *PU_EMREOF; //!< EMF manual 3.2.4.1
+#define U_SIZE_EMREOF (sizeof(U_EMREOF))
+
+/* Index 15 */
+/** EMF manual 2.3.5.36
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_POINTL ptlPixel; //!< Pixel coordinates (logical)
+ U_COLORREF crColor; //!< Pixel color
+} U_EMRSETPIXELV,
+ *PU_EMRSETPIXELV; //!< EMF manual 2.3.5.36
+#define U_SIZE_EMRSETPIXELV (sizeof(U_EMRSETPIXELV))
+
+/* Index 16 */
+/** EMF manual 2.3.11.20
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t dwFlags; //!< must be 1
+} U_EMRSETMAPPERFLAGS,
+ *PU_EMRSETMAPPERFLAGS; //!< EMF manual 2.3.11.20
+#define U_SIZE_EMRSETMAPPERFLAGS (sizeof(U_EMRSETMAPPERFLAGS))
+
+/* Index 17,18,19,20,21,22,67,98,115
+*/
+/** EMF manual 2.3.11.19 MapMode enumeration
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t iMode; //!< enumeration varies with type
+} U_EMRSETMAPMODE,
+ U_EMRSETBKMODE, //!< EMF manual 2.3.11.11 BackgroundMode Enumeration
+ U_EMRSETPOLYFILLMODE, //!< EMF manual 2.3.11.22 PolygonFillMode Enumeration
+ U_EMRSETROP2, //!< EMF manual 2.3.11.23 Binary Raster Operation Enumeration
+ U_EMRSETSTRETCHBLTMODE, //!< EMF manual 2.3.11.24 StretchMode Enumeration
+ U_EMRSETTEXTALIGN, //!< EMF manual 2.3.11.25 TextAlignment enumeration
+ U_EMRSELECTCLIPPATH, //!< EMF manual 2.3.2.5 RegionMode Enumeration
+ U_EMRSETICMMODE, //!< EMF manual 2.3.11.14 ICMMode Enumeration
+ U_EMRSETLAYOUT, //!< EMF manual 2.3.11.17 Mirroring Enumeration
+ *PU_EMRSETMAPMODE, //!< EMF manual 2.3.11.19 MapMode enumeration
+ *PU_EMRSETBKMODE, //!< EMF manual 2.3.11.11 BackgroundMode Enumeration
+ *PU_EMRSETPOLYFILLMODE, //!< EMF manual 2.3.11.22 PolygonFillMode Enumeration
+ *PU_EMRSETROP2, //!< EMF manual 2.3.11.23 Binary Raster Operation Enumeration
+ *PU_EMRSETSTRETCHBLTMODE, //!< EMF manual 2.3.11.24 StretchMode Enumeration
+ *PU_EMRSETTEXTALIGN, //!< EMF manual 2.3.11.25 TextAlignment enumeration
+ *PU_EMRSELECTCLIPPATH, //!< EMF manual 2.3.2.5 RegionMode Enumeration
+ *PU_EMRSETICMMODE, //!< EMF manual 2.3.11.14 ICMMode Enumeration
+ *PU_EMRSETLAYOUT; //!< EMF manual 2.3.11.17 Mirroring Enumeration
+
+#define U_SIZE_EMRSETMAPMODE (sizeof(U_EMRSETMAPMODE ))
+#define U_SIZE_EMRSETBKMODE (sizeof(U_EMRSETBKMODE ))
+#define U_SIZE_EMRSETPOLYFILLMODE (sizeof(U_EMRSETPOLYFILLMODE ))
+#define U_SIZE_EMRSETROP2 (sizeof(U_EMRSETROP2 ))
+#define U_SIZE_EMRSETSTRETCHBLTMODE (sizeof(U_EMRSETSTRETCHBLTMODE))
+#define U_SIZE_EMRSETTEXTALIGN (sizeof(U_EMRSETTEXTALIGN ))
+#define U_SIZE_EMRSELECTCLIPPATH (sizeof(U_EMRSELECTCLIPPATH ))
+#define U_SIZE_EMRSETICMMODE (sizeof(U_EMRSETICMMODE ))
+#define U_SIZE_EMRSETLAYOUT (sizeof(U_EMRSETLAYOUT ))
+
+/* Index 23 */
+/** EMF manual 2.3.11.13
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_COLORADJUSTMENT ColorAdjustment; //!< Color Adjustment
+} U_EMRSETCOLORADJUSTMENT,
+ *PU_EMRSETCOLORADJUSTMENT; //!< EMF manual 2.3.11.13
+#define U_SIZE_EMRSETCOLORADJUSTMENT (sizeof(U_EMRSETCOLORADJUSTMENT))
+
+/* Index 24, 25 */
+/** EMF manual 2.3.11.26
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_COLORREF crColor; //!< Color
+} U_EMRSETTEXTCOLOR,
+ U_EMRSETBKCOLOR, //!< EMF manual 2.3.11.10
+ *PU_EMRSETTEXTCOLOR, //!< EMF manual 2.3.11.26
+ *PU_EMRSETBKCOLOR; //!< EMF manual 2.3.11.10
+#define U_SIZE_EMRSETTEXTCOLOR (sizeof(U_EMRSETTEXTCOLOR))
+#define U_SIZE_EMRSETBKCOLOR (sizeof(U_EMRSETBKCOLOR ))
+
+/* Index 26 */
+/** EMF manual 2.3.2.4
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_POINTL ptlOffset; //!< Clipping region
+} U_EMROFFSETCLIPRGN,
+ *PU_EMROFFSETCLIPRGN; //!< EMF manual 2.3.2.4
+#define U_SIZE_EMROFFSETCLIPRGN (sizeof(U_EMROFFSETCLIPRGN))
+
+/* Index 27, 54 */
+/**
+EMF manual 2.3.11.4
+EMF manual 2.3.5.13
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_POINTL ptl; //!< Point coordinates
+} U_EMRMOVETOEX,
+ U_EMRLINETO, //!< EMF manual 2.3.5.13
+ *PU_EMRMOVETOEX, //!< EMF manual 2.3.11.4
+ *PU_EMRLINETO; //!< EMF manual 2.3.5.13
+#define U_SIZE_EMRMOVETOEX (sizeof(U_EMRMOVETOEX))
+#define U_SIZE_EMRLINETO (sizeof(U_EMRLINETO ))
+
+/* Index 28,33,52,59,60,61,65,66,68 */
+/** EMF manual 2.3.2
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+}
+ U_EMRSETMETARGN,
+ U_EMRSAVEDC, //!< EMF manual 2.3.11
+ U_EMRREALIZEPALETTE, //!< EMF manual 2.3.10
+ U_EMRBEGINPATH, //!< EMF manual 2.3.10
+ U_EMRENDPATH, //!< EMF manual 2.3.10
+ U_EMRCLOSEFIGURE, //!< EMF manual 2.3.10
+ U_EMRFLATTENPATH, //!< EMF manual 2.3.10
+ U_EMRWIDENPATH, //!< EMF manual 2.3.10
+ U_EMRABORTPATH, //!< EMF manual 2.3.10
+ *PU_EMRSETMETARGN, //!< EMF manual 2.3.2
+ *PU_EMRSAVEDC, //!< EMF manual 2.3.11
+ *PU_EMRREALIZEPALETTE, //!< EMF manual 2.3.10
+ *PU_EMRBEGINPATH, //!< EMF manual 2.3.10
+ *PU_EMRENDPATH, //!< EMF manual 2.3.10
+ *PU_EMRCLOSEFIGURE, //!< EMF manual 2.3.10
+ *PU_EMRFLATTENPATH, //!< EMF manual 2.3.10
+ *PU_EMRWIDENPATH, //!< EMF manual 2.3.10
+ *PU_EMRABORTPATH; //!< EMF manual 2.3.10
+#define U_SIZE_EMRSETMETARGN (sizeof(U_EMRSETMETARGN ))
+#define U_SIZE_EMRSAVEDC (sizeof(U_EMRSAVEDC ))
+#define U_SIZE_EMRREALIZEPALETTE (sizeof(U_EMRREALIZEPALETTE))
+#define U_SIZE_EMRBEGINPATH (sizeof(U_EMRBEGINPATH ))
+#define U_SIZE_EMRENDPATH (sizeof(U_EMRENDPATH ))
+#define U_SIZE_EMRCLOSEFIGURE (sizeof(U_EMRCLOSEFIGURE ))
+#define U_SIZE_EMRFLATTENPATH (sizeof(U_EMRFLATTENPATH ))
+#define U_SIZE_EMRWIDENPATH (sizeof(U_EMRWIDENPATH ))
+#define U_SIZE_EMRABORTPATH (sizeof(U_EMRABORTPATH ))
+
+/* Index 29,30 */
+/** EMF manual 2.3.2.1
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclClip; //!< Clipping Region
+} U_EMREXCLUDECLIPRECT,
+ U_EMRINTERSECTCLIPRECT, //!< EMF manual 2.3.2.3
+ *PU_EMREXCLUDECLIPRECT, //!< EMF manual 2.3.2.1
+ *PU_EMRINTERSECTCLIPRECT; //!< EMF manual 2.3.2.3
+#define U_SIZE_EMREXCLUDECLIPRECT (sizeof(U_EMREXCLUDECLIPRECT ))
+#define U_SIZE_EMRINTERSECTCLIPRECT (sizeof(U_EMRINTERSECTCLIPRECT ))
+
+/* Index 31,32 */
+/** EMF manual 2.3.11.7
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ int32_t xNum; //!< Horizontal multiplier (!=0)
+ int32_t xDenom; //!< Horizontal divisor (!=0)
+ int32_t yNum; //!< Vertical multiplier (!=0)
+ int32_t yDenom; //!< Vertical divisor (!=0)
+} U_EMRSCALEVIEWPORTEXTEX,
+ U_EMRSCALEWINDOWEXTEX, //!< EMF manual 2.3.11.8
+ *PU_EMRSCALEVIEWPORTEXTEX, //!< EMF manual 2.3.11.7
+ *PU_EMRSCALEWINDOWEXTEX; //!< EMF manual 2.3.11.8
+#define U_SIZE_EMRSCALEVIEWPORTEXTEX (sizeof(U_EMRSCALEVIEWPORTEXTEX))
+#define U_SIZE_EMRSCALEWINDOWEXTEX (sizeof(U_EMRSCALEWINDOWEXTEX ))
+
+/* Index 33 (see 28) */
+
+/* Index 34 */
+/** EMF manual 2.3.11.6
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ int32_t iRelative; //!< DC to restore. -1 is preceding
+} U_EMRRESTOREDC,
+ *PU_EMRRESTOREDC; //!< EMF manual 2.3.11.6
+#define U_SIZE_EMRRESTOREDC (sizeof(U_EMRRESTOREDC))
+
+/* Index 35 */
+/** EMF manual 2.3.12.2
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_XFORM xform; //!< Transform
+} U_EMRSETWORLDTRANSFORM,
+ *PU_EMRSETWORLDTRANSFORM; //!< EMF manual 2.3.12.2
+#define U_SIZE_EMRSETWORLDTRANSFORM (sizeof(U_EMRSETWORLDTRANSFORM))
+
+/* Index 36 */
+/** EMF manual 2.3.12.1
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_XFORM xform; //!< Transform
+ uint32_t iMode; //!< ModifyWorldTransformMode Enumeration
+} U_EMRMODIFYWORLDTRANSFORM,
+ *PU_EMRMODIFYWORLDTRANSFORM; //!< EMF manual 2.3.12.1
+#define U_SIZE_EMRMODIFYWORLDTRANSFORM (sizeof(U_EMRMODIFYWORLDTRANSFORM))
+
+/* Index 37,40 */
+/** EMF manual 2.3.8.3
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t ihObject; //!< Number of a stock or created object
+} U_EMRDELETEOBJECT,
+ U_EMRSELECTOBJECT, //!< EMF manual 2.3.8.5
+ *PU_EMRDELETEOBJECT, //!< EMF manual 2.3.8.3
+ *PU_EMRSELECTOBJECT; //!< EMF manual 2.3.8.5
+#define U_SIZE_EMRDELETEOBJECT (sizeof(U_EMRDELETEOBJECT))
+#define U_SIZE_EMRSELECTOBJECT (sizeof(U_EMRSELECTOBJECT))
+
+/* Index 38 */
+/** EMF manual 2.3.7.7
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t ihPen; //!< Index to place object in EMF object table (this entry must not yet exist)
+ U_LOGPEN lopn; //!< Pen properties
+} U_EMRCREATEPEN,
+ *PU_EMRCREATEPEN; //!< EMF manual 2.3.7.7
+#define U_SIZE_EMRCREATEPEN (sizeof(U_EMRCREATEPEN))
+
+/* Index 39 */
+/** EMF manual 2.3.7.1
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t ihBrush; //!< Index to place object in EMF object table (this entry must not yet exist)
+ U_LOGBRUSH lb; //!< Brush properties
+} U_EMRCREATEBRUSHINDIRECT,
+ *PU_EMRCREATEBRUSHINDIRECT; //!< EMF manual 2.3.7.1
+#define U_SIZE_EMRCREATEBRUSHINDIRECT (sizeof(U_EMRCREATEBRUSHINDIRECT))
+
+/* Index 40 see 37 */
+
+/* Index 41 */
+/** EMF manual 2.3.5.1
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_POINTL ptlCenter; //!< Center in logical units
+ uint32_t nRadius; //!< Radius in logical units
+ U_FLOAT eStartAngle; //!< Starting angle in degrees (counter clockwise from x axis)
+ U_FLOAT eSweepAngle; //!< Sweep angle in degrees
+} U_EMRANGLEARC,
+ *PU_EMRANGLEARC; //!< EMF manual 2.3.5.1
+#define U_SIZE_EMRANGLEARC (sizeof(U_EMRANGLEARC))
+
+/* Index 42,43 */
+/** EMF manual 2.3.5.5
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBox; //!< bounding rectangle in logical units
+} U_EMRELLIPSE,
+ U_EMRRECTANGLE, //!< EMF manual 2.3.5.5
+ *PU_EMRELLIPSE, //!< EMF manual 2.3.5.5
+ *PU_EMRRECTANGLE; //!< EMF manual 2.3.5.34
+#define U_SIZE_EMRELLIPSE (sizeof(U_EMRELLIPSE ))
+#define U_SIZE_EMRRECTANGLE (sizeof(U_EMRRECTANGLE))
+
+/* Index 44 */
+/** EMF manual 2.3.5.35
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBox; //!< bounding rectangle in logical units
+ U_SIZEL szlCorner; //!< W & H in logical units of ellipse used to round corner
+} U_EMRROUNDRECT,
+ *PU_EMRROUNDRECT; //!< EMF manual 2.3.5.35
+#define U_SIZE_EMRROUNDRECT (sizeof(U_EMRROUNDRECT))
+
+/* Index 45, 46 ,47, 55 */
+/** EMF manual 2.3.5.2
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBox; //!< bounding rectangle in logical units
+ U_POINTL ptlStart; //!< Start point in logical units
+ U_POINTL ptlEnd; //!< End point in logical units
+} U_EMRARC,
+ U_EMRCHORD, //!< EMF manual 2.3.5.4
+ U_EMRPIE, //!< EMF manual 2.3.5.15
+ U_EMRARCTO, //!< EMF manual 2.3.5.3
+ *PU_EMRARC, //!< EMF manual 2.3.5.2
+ *PU_EMRCHORD, //!< EMF manual 2.3.5.4
+ *PU_EMRPIE, //!< EMF manual 2.3.5.15
+ *PU_EMRARCTO; //!< EMF manual 2.3.5.3
+#define U_SIZE_EMRARC (sizeof(U_EMRARC ))
+#define U_SIZE_EMRCHORD (sizeof(U_EMRCHORD))
+#define U_SIZE_EMRPIE (sizeof(U_EMRPIE ))
+#define U_SIZE_EMRARCTO (sizeof(U_EMRARCTO))
+
+/* Index 48 */
+/** EMF manual 2.3.8.6
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t ihPal; //!< Index of a Palette object in the EMF object table
+} U_EMRSELECTPALETTE,
+ *PU_EMRSELECTPALETTE; //!< EMF manual 2.3.8.6
+#define U_SIZE_EMRSELECTPALETTE (sizeof(U_EMRSELECTPALETTE))
+
+/* Index 49 */
+/** EMF manual 2.3.7.6
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t ihPal; //!< Index to place object in EMF object table (this entry must not yet exist)
+ U_LOGPALETTE lgpl; //!< Palette properties (variable size)
+} U_EMRCREATEPALETTE,
+ *PU_EMRCREATEPALETTE; //!< EMF manual 2.3.7.6
+#define U_SIZE_EMRCREATEPALETTE (sizeof(U_EMR) + sizeof(uint32_t) + U_SIZE_LOGPALETTE)
+
+/* Index 50 */
+/** EMF manual 2.3.8.8
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t ihPal; //!< Index of a Palette object in the EMF object table
+ uint32_t iStart; //!< First Palette entry in selected object to set
+ U_NUM_LOGPLTNTRY cEntries; //!< Number of Palette entries in selected object to set
+ U_LOGPLTNTRY aPalEntries[1]; //!< Values to set with
+} U_EMRSETPALETTEENTRIES,
+ *PU_EMRSETPALETTEENTRIES; //!< EMF manual 2.3.8.8
+#define U_SIZE_EMRSETPALETTEENTRIES (sizeof(U_EMR) + 2*sizeof(uint32_t) + sizeof(U_NUM_LOGPLTNTRY))
+
+/* Index 51 */
+/** EMF manual 2.3.8.4
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t ihPal; //!< Index of a Palette object in the EMF object table
+ uint32_t cEntries; //!< Number to expand or truncate the Palette entry list to.
+} U_EMRRESIZEPALETTE,
+ *PU_EMRRESIZEPALETTE; //!< EMF manual 2.3.8.4
+#define U_SIZE_EMRRESIZEPALETTE (sizeof(U_EMRRESIZEPALETTE))
+
+/* Index 52 (see 28) */
+
+/* Index 53 */
+/** EMF manual 2.3.5.6
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_POINTL ptlStart; //!< Start point in logical units
+ U_COLORREF crColor; //!< Color to fill with
+ uint32_t iMode; //!< FloodFill Enumeration
+} U_EMREXTFLOODFILL,
+ *PU_EMREXTFLOODFILL; //!< EMF manual 2.3.5.6
+#define U_SIZE_EMREXTFLOODFILL (sizeof(U_EMREXTFLOODFILL))
+
+/* Index 54 (see 27) */
+
+/* Index 55 (see 45) */
+
+/* Index 56 */
+/** EMF manual 2.3.5.20
+
+ followed by
+ uint8_t abTypes[1]; //!< Array of Point Enumeration
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+ U_NUM_POINTL cptl; //!< Number of U_POINTL objects
+ U_POINTL aptl[1]; //!< Array of U_POINTL objects
+} U_EMRPOLYDRAW,
+ *PU_EMRPOLYDRAW; //!< EMF manual 2.3.5.20
+#define U_SIZE_EMRPOLYDRAW (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_NUM_POINTL))
+
+/* Index 57 */
+/** EMF manual 2.3.11.9
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t iArcDirection; //!< ArcDirection Enumeration
+} U_EMRSETARCDIRECTION,
+ *PU_EMRSETARCDIRECTION; //!< EMF manual 2.3.11.9
+#define U_SIZE_EMRSETARCDIRECTION (sizeof(U_EMRSETARCDIRECTION))
+
+/* Index 58 */
+/** EMF manual 2.3.11.21
+
+IMPORTANT!!!! The Microsoft structure uses a float for the miterlimit but the EMF file record
+uses an unsigned int. The latter form is used in this structure.
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t eMiterLimit; //!< Miter limit (max value of mitered length / line width)
+} U_EMRSETMITERLIMIT,
+ *PU_EMRSETMITERLIMIT; //!< EMF manual 2.3.11.21
+#define U_SIZE_EMRSETMITERLIMIT (sizeof(U_EMRSETMITERLIMIT))
+
+/* Index 59,60,61 (see 28) */
+
+/* Index 62,63,64 */
+/** EMF manual 2.3.5.9
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+} U_EMRFILLPATH,
+ U_EMRSTROKEANDFILLPATH, //!< EMF manual 2.3.5.38
+ U_EMRSTROKEPATH, //!< EMF manual 2.3.5.39
+ *PU_EMRFILLPATH, //!< EMF manual 2.3.5.9
+ *PU_EMRSTROKEANDFILLPATH, //!< EMF manual 2.3.5.38
+ *PU_EMRSTROKEPATH; //!< EMF manual 2.3.5.39
+#define U_SIZE_EMRFILLPATH (sizeof(U_EMRFILLPATH ))
+#define U_SIZE_EMRSTROKEANDFILLPATH (sizeof(U_EMRSTROKEANDFILLPATH))
+#define U_SIZE_EMRSTROKEPATH (sizeof(U_EMRSTROKEPATH ))
+
+/* Index 65,66 (see 28) */
+/* Index 67 (see 17) */
+/* Index 68 (see 28) */
+/* Index 69 (not a defined U_EMR record type ) */
+
+
+/* Index 70 */
+/** EMF manual 2.3.3.1
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_CBDATA cbData; //!< Number of bytes in comment
+ uint8_t Data[1]; //!< Comment (any binary data, interpretation is program specific)
+} U_EMRCOMMENT,
+ *PU_EMRCOMMENT; //!< EMF manual 2.3.3.1, AKA GDICOMMENT
+#define U_SIZE_EMRCOMMENT (sizeof(U_EMR) + sizeof(U_CBDATA))
+
+/* variant comment types */
+/** EMF manual 2.3.3.2
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_CBDATA cbData; //!< Number of bytes in comment
+ uint32_t cIdent; //!< Comment identifier, must be U_EMR_COMMENT_EMFPLUSRECORD
+ uint8_t Data[1]; //!< EMF Plus record
+} U_EMRCOMMENT_EMFPLUS,
+ *PU_EMRCOMMENT_EMFPLUS; //!< EMF manual 2.3.3.2, EMF Plus comment
+#define U_SIZE_EMRCOMMENT_EMFPLUS (sizeof(U_EMR) + sizeof(U_CBDATA) + sizeof(uint32_t))
+
+/** EMF manual 2.3.3.3
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_CBDATA cbData; //!< Number of bytes in comment
+ uint32_t cIdent; //!< Comment identifier, must be U_EMR_COMMENT_SPOOL
+ uint32_t esrIdent; //!< EMFSpoolRecordIdentifier, may be U_EMR_COMMENT_SPOOLFONTDEF
+ uint8_t Data[1]; //!< EMF Spool records
+} U_EMRCOMMENT_SPOOL,
+ *PU_EMRCOMMENT_SPOOL; //!< EMF manual 2.3.3.3, EMF Spool comment
+#define U_SIZE_EMRCOMMENT_SPOOL (sizeof(U_EMR) + sizeof(U_CBDATA) + 2*sizeof(uint32_t))
+
+/** EMF manual 2.3.3.4
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_CBDATA cbData; //!< Number of bytes in comment
+ uint32_t cIdent; //!< Comment identifier, must be U_EMR_COMMENT_PUBLIC
+ uint32_t pcIdent; //!< Public Comment Identifier, from EMRComment Enumeration
+ uint8_t Data[1]; //!< Public comment data
+} U_EMRCOMMENT_PUBLIC,
+ *PU_EMRCOMMENT_PUBLIC; //!< EMF manual 2.3.3.4, EMF Public comment
+#define U_SIZE_EMRCOMMENT_PUBLIC (sizeof(U_EMR) + sizeof(U_CBDATA) + 2*sizeof(uint32_t))
+
+/* Index 71 */
+/** EMF manual 2.3.5.10
+ followed by a variable number of U_RECTLs
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+ U_CBRGNDATA cbRgnData; //!< Size in bytes of Region data
+ uint32_t ihBrush; //!< Index of a Brush object in the EMF object table
+ U_RGNDATA RgnData[1]; //!< Variable size U_RGNDATA structure
+} U_EMRFILLRGN,
+ *PU_EMRFILLRGN; //!< EMF manual 2.3.5.10
+#define U_SIZE_EMRFILLRGN (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_CBRGNDATA) + sizeof(uint32_t))
+
+/* Index 72 */
+/** EMF manual 2.3.5.11
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+ U_CBRGNDATA cbRgnData; //!< Size in bytes of Region data
+ uint32_t ihBrush; //!< Index of a Brush object in the EMF object table
+ U_SIZEL szlStroke; //!< W & H of Brush stroke
+ U_RGNDATA RgnData[1]; //!< Variable size U_RGNDATA structure
+} U_EMRFRAMERGN,
+ *PU_EMRFRAMERGN; //!< EMF manual 2.3.5.11
+#define U_SIZE_EMRFRAMERGN (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_CBRGNDATA) + sizeof(uint32_t) + sizeof(U_SIZEL))
+
+/* Index 73,74 */
+/** EMF manual 2.3.11.3
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+ U_CBRGNDATA cbRgnData; //!< Size in bytes of Region data
+ U_RGNDATA RgnData[1]; //!< Variable size U_RGNDATA structure
+} U_EMRINVERTRGN,
+ U_EMRPAINTRGN, //!< EMF manual 2.3.5.14
+ *PU_EMRINVERTRGN, //!< EMF manual 2.3.11.3
+ *PU_EMRPAINTRGN; //!< EMF manual 2.3.5.14
+#define U_SIZE_EMRINVERTRGN (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_CBRGNDATA))
+#define U_SIZE_EMRPAINTRGN U_SIZE_EMRINVERTRGN
+
+/* Index 75 */
+/** EMF manual 2.3.2.2
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_CBRGNDATA cbRgnData; //!< Size in bytes of Region data
+ uint32_t iMode; //!< RegionMode Enumeration
+ U_RGNDATA RgnData[1]; //!< Variable size U_RGNDATA structure
+} U_EMREXTSELECTCLIPRGN,
+ *PU_EMREXTSELECTCLIPRGN; //!< EMF manual 2.3.2.2
+#define U_SIZE_EMREXTSELECTCLIPRGN (sizeof(U_EMR) + sizeof(U_CBRGNDATA) + sizeof(uint32_t))
+
+/* Index 76 */
+/** EMF manual 2.3.1.2
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+ U_POINTL Dest; //!< Destination UL corner in logical units
+ U_POINTL cDest; //!< Destination width in logical units
+ uint32_t dwRop; //!< Ternary Raster Operation enumeration
+ U_POINTL Src; //!< Source retangle UL corner in logical units
+ U_XFORM xformSrc; //!< Source bitmap transform (world to page coordinates)
+ U_COLORREF crBkColorSrc; //!< Source bitmap background color
+ uint32_t iUsageSrc; //!< DIBcolors Enumeration
+ U_OFFBMISRC offBmiSrc; //!< Offset in bytes to U_BITMAPINFO (within bitmapbuffer)
+ U_CBBMISRC cbBmiSrc; //!< Size in bytes of U_BITMAPINFO
+ U_OFFBITSSRC offBitsSrc; //!< Offset in bytes to the bitmap (within bitmapbuffer)
+ U_CBBITS cbBitsSrc; //!< Size in bytes of bitmap
+ //!< Record may include optional bitmapbuffer
+} U_EMRBITBLT,
+ *PU_EMRBITBLT; //!< EMF manual 2.3.1.2
+#define U_SIZE_EMRBITBLT (sizeof(U_EMRBITBLT))
+
+/* Index 77 */
+/** EMF manual 2.3.1.6
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+ U_POINTL Dest; //!< Destination UL corner in logical units
+ U_POINTL cDest; //!< Destination width in logical units
+ uint32_t dwRop; //!< Ternary Raster Operation enumeration
+ U_POINTL Src; //!< Source UL corner in logical units
+ U_XFORM xformSrc; //!< Transform to apply to source
+ U_COLORREF crBkColorSrc; //!< Background color
+ uint32_t iUsageSrc; //!< DIBcolors Enumeration
+ U_OFFBMISRC offBmiSrc; //!< Offset in bytes to U_BITMAPINFO (within bitmapbuffer)
+ U_CBBMISRC cbBmiSrc; //!< Size in bytes of U_BITMAPINFO
+ U_OFFBITSSRC offBitsSrc; //!< Offset in bytes to the bitmap (within bitmapbuffer)
+ U_CBBITS cbBitsSrc; //!< Size in bytes of bitmap
+ U_POINTL cSrc; //!< Src W & H in logical units
+ //!< Record may include optional bitmapbuffer
+} U_EMRSTRETCHBLT,
+ *PU_EMRSTRETCHBLT; //!< EMF manual 2.3.1.6
+#define U_SIZE_EMRSTRETCHBLT (sizeof(U_EMRSTRETCHBLT))
+
+/* Index 78 */
+/** EMF manual 2.3.1.3
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+ U_POINTL Dest; //!< Destination UL corner in logical units
+ U_POINTL cDest; //!< Destination width in logical units
+ uint32_t dwRop; //!< Ternary Raster Operation enumeration
+ U_POINTL Src; //!< Source UL corner in logical units
+ U_XFORM xformSrc; //!< Transform to apply to source
+ U_COLORREF crBkColorSrc; //!< Background color
+ uint32_t iUsageSrc; //!< DIBcolors Enumeration
+ U_OFFBMISRC offBmiSrc; //!< Offset in bytes to U_BITMAPINFO (within srcbitmapbuffer)
+ U_CBBMISRC cbBmiSrc; //!< Size in bytes of U_BITMAPINFO
+ U_OFFBITSSRC offBitsSrc; //!< Offset in bytes to the src bitmap (within srcbitmapbuffer)
+ U_CBBITS cbBitsSrc; //!< Size in bytes of src bitmap
+ U_POINTL Mask; //!< Mask UL corner in logical units
+ uint32_t iUsageMask; //!< DIBcolors Enumeration
+ U_OFFBMIMSK offBmiMask; //!< Offset in bytes to U_BITMAPINFO (within maskbitmapbuffer)
+ U_CBBMIMSK cbBmiMask; //!< Size in bytes of U_BITMAPINFO
+ U_OFFBITSMSK offBitsMask; //!< Offset in bytes to the mask bitmap (within maskbitmapbuffer)
+ U_CBBITSMSK cbBitsMask; //!< Size in bytes of bitmap
+ //!< Record may include optional Source and mask bitmapbuffers
+} U_EMRMASKBLT,
+ *PU_EMRMASKBLT; //!< EMF manual 2.3.1.3
+#define U_SIZE_EMRMASKBLT (sizeof(U_EMRMASKBLT))
+
+/* Index 79 */
+/** EMF manual 2.3.1.4
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+ U_POINTL aptlDst[3]; //!< Defines parallelogram, UL, UR, LL corners, LR is derived.
+ U_POINTL Src; //!< Source UL corner in logical units
+ U_POINTL cSrc; //!< Src W & H in logical units
+ U_XFORM xformSrc; //!< Transform to apply to source
+ U_COLORREF crBkColorSrc; //!< Background color
+ uint32_t iUsageSrc; //!< DIBcolors Enumeration
+ U_OFFBMISRC offBmiSrc; //!< Offset in bytes to U_BITMAPINFO (within srcbitmapbuffer)
+ U_CBBMISRC cbBmiSrc; //!< Size in bytes of U_BITMAPINFO
+ U_OFFBITSSRC offBitsSrc; //!< Offset in bytes to the src bitmap (within srcbitmapbuffer)
+ U_CBBITS cbBitsSrc; //!< Size in bytes of src bitmap
+ U_POINTL Mask; //!< Mask UL corner in logical units
+ uint32_t iUsageMask; //!< DIBcolors Enumeration
+ U_OFFBMIMSK offBmiMask; //!< Offset in bytes to U_BITMAPINFO (within maskbitmapbuffer)
+ U_CBBMIMSK cbBmiMask; //!< Size in bytes of U_BITMAPINFO
+ U_OFFBITSMSK offBitsMask; //!< Offset in bytes to the mask bitmap (within maskbitmapbuffer)
+ U_CBBITSMSK cbBitsMask; //!< Size in bytes of bitmap
+ //!< Record may include optional Source and mask bitmapbuffers
+} U_EMRPLGBLT,
+ *PU_EMRPLGBLT; //!< EMF manual 2.3.1.4
+#define U_SIZE_EMRPLGBLT (sizeof(U_EMRPLGBLT))
+
+/* Index 80 */
+/** EMF manual 2.3.1.5
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+ U_POINTL Dest; //!< Destination UL corner in logical units
+ U_POINTL Src; //!< Source LL corner in logical units
+ U_POINTL cSrc; //!< Src W & H in logical units
+ U_OFFBMISRC offBmiSrc; //!< Offset in bytes to U_BITMAPINFO (within bitmapbuffer)
+ U_CBBMISRC cbBmiSrc; //!< Size in bytes of U_BITMAPINFO
+ U_OFFBITSSRC offBitsSrc; //!< Offset in bytes to bitmap
+ U_CBBITS cbBitsSrc; //!< Size in bytes of bitmap
+ uint32_t iUsageSrc; //!< DIBColors Enumeration
+ uint32_t iStartScan; //!< First scan line
+ uint32_t cScans; //!< Number of scan lines
+ //!< Record may includes optional bitmapbuffer
+} U_EMRSETDIBITSTODEVICE,
+ *PU_EMRSETDIBITSTODEVICE; //!< EMF manual 2.3.1.5
+#define U_SIZE_EMRSETDIBITSTODEVICE (sizeof(U_EMRSETDIBITSTODEVICE))
+
+/* Index 81 */
+/** EMF manual 2.3.1.7
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+ U_POINTL Dest; //!< Destination UL corner in logical units
+ U_POINTL Src; //!< Source UL corner in logical units
+ U_POINTL cSrc; //!< Source W & H in logical units
+ U_OFFBMISRC offBmiSrc; //!< Offset in bytes to U_BITMAPINFO (within bitmapbuffer)
+ U_CBBMISRC cbBmiSrc; //!< Size in bytes of U_BITMAPINFO
+ U_OFFBITSSRC offBitsSrc; //!< Offset in bytes to bitmap
+ U_CBBITS cbBitsSrc; //!< Size in bytes of bitmap
+ uint32_t iUsageSrc; //!< DIBColors Enumeration
+ uint32_t dwRop; //!< Ternary Raster Operation enumeration
+ U_POINTL cDest; //!< Destination W & H in logical units
+ //!< Record may includes optional bitmapbuffer
+} U_EMRSTRETCHDIBITS,
+ *PU_EMRSTRETCHDIBITS; //!< EMF manual 2.3.1.7
+#define U_SIZE_EMRSTRETCHDIBITS (sizeof(U_EMRSTRETCHDIBITS))
+
+/* Index 82 */
+/** EMF manual 2.3.7.8
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t ihFont; //!< Index of the font in the EMF object table
+ U_LOGFONT_PANOSE elfw; //!< Font parameters, either U_LOGFONT or U_LOGFONT_PANOSE, the latter is bigger so use that type here
+} U_EMREXTCREATEFONTINDIRECTW,
+ *PU_EMREXTCREATEFONTINDIRECTW; //!< EMF manual 2.3.7.8
+#define U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT_PANOSE (sizeof(U_EMR) + 4 + sizeof(U_LOGFONT_PANOSE))
+#define U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT (sizeof(U_EMR) + 4 + sizeof(U_LOGFONT))
+
+/* Index 83,84 */
+/** EMF manual 2.3.5.7
+
+Variable and optional fields may follow core structure in record:\n
+
+ U_RECTL rcl; absent when fOptions & U_ETO_NO_RECT) grayed/clipping/opaque rectangle
+
+ U_OFFDX offDx; (required) Offset in bytes to the character spacing array from the start of the RECORD
+
+ uint32_t Dx (optional) character spacing array (Required, but position is not static.)
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+ uint32_t iGraphicsMode; //!< GraphicsMode Enumeration
+ U_FLOAT exScale; //!< scale to 0.01 mm units ( only if iGraphicsMode & U_GM_COMPATIBLE)
+ U_FLOAT eyScale; //!< scale to 0.01 mm units ( only if iGraphicsMode & U_GM_COMPATIBLE)
+ U_EMRTEXT emrtext; //!< Text parameters
+} U_EMREXTTEXTOUTA,
+ U_EMREXTTEXTOUTW, //!< EMF manual 2.3.5.8
+ *PU_EMREXTTEXTOUTA, //!< EMF manual 2.3.5.7
+ *PU_EMREXTTEXTOUTW; //!< EMF manual 2.3.5.8
+#define U_SIZE_EMREXTTEXTOUTA (sizeof(U_EMREXTTEXTOUTA))
+#define U_SIZE_EMREXTTEXTOUTW (sizeof(U_EMREXTTEXTOUTW))
+
+/* Index 85,86,87,88,89 */
+/** EMF manual 2.3.5.17
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+ U_NUM_POINT16 cpts; //!< Number of POINT16 in array
+ U_POINT16 apts[1]; //!< Array of POINT16
+} U_EMRPOLYBEZIER16,
+ U_EMRPOLYGON16, //!< EMF manual 2.3.5.23
+ U_EMRPOLYLINE16, //!< EMF manual 2.3.5.25
+ U_EMRPOLYBEZIERTO16, //!< EMF manual 2.3.5.19
+ U_EMRPOLYLINETO16, //!< EMF manual 2.3.5.27
+ *PU_EMRPOLYBEZIER16, //!< EMF manual 2.3.5.17
+ *PU_EMRPOLYGON16, //!< EMF manual 2.3.5.23
+ *PU_EMRPOLYLINE16, //!< EMF manual 2.3.5.25
+ *PU_EMRPOLYBEZIERTO16, //!< EMF manual 2.3.5.19
+ *PU_EMRPOLYLINETO16; //!< EMF manual 2.3.5.27
+#define U_SIZE_EMRPOLYBEZIER16 (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_NUM_POINT16))
+#define U_SIZE_EMRPOLYGON16 U_SIZE_EMRPOLYBEZIER16
+#define U_SIZE_EMRPOLYLINE16 U_SIZE_EMRPOLYBEZIER16
+#define U_SIZE_EMRPOLYBEZIERTO16 U_SIZE_EMRPOLYBEZIER16
+#define U_SIZE_EMRPOLYLINETO16 U_SIZE_EMRPOLYBEZIER16
+/* Index 90,91 */
+/** EMF manual 2.3.5.31
+
+ followed by
+ U_POINT16 apts[1]; //!< array of point16
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+ U_NUM_POLYCOUNTS nPolys; //!< Number of elements in aPolyCounts
+ U_NUM_POINT16 cpts; //!< Total number of points (over all poly)
+ U_POLYCOUNTS aPolyCounts[1]; //!< Number of points in each poly (sequential)
+} U_EMRPOLYPOLYLINE16,
+ U_EMRPOLYPOLYGON16, //!< EMF manual 2.3.5.29
+ *PU_EMRPOLYPOLYLINE16, //!< EMF manual 2.3.5.31
+ *PU_EMRPOLYPOLYGON16; //!< EMF manual 2.3.5.29
+#define U_SIZE_EMRPOLYPOLYLINE16 (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_NUM_POLYCOUNTS) + sizeof(U_NUM_POINT16))
+#define U_SIZE_EMRPOLYPOLYGON16 U_SIZE_EMRPOLYPOLYLINE16
+
+/* Index 92 */
+/** EMF manual 2.3.5.21
+
+ followed by
+ uint8_t abTypes[1]; //!< Array of Point Enumeration
+
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+ U_NUM_POINT16 cpts; //!< Total number of points (over all poly)
+ U_POINT16 apts[1]; //!< array of points
+} U_EMRPOLYDRAW16,
+ *PU_EMRPOLYDRAW16; //!< EMF manual 2.3.5.21
+#define U_SIZE_EMRPOLYDRAW16 (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_NUM_POINT16))
+
+/* Index 93 */
+/** EMF manual 2.3.7.5
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t ihBrush; //!< Index to place object in EMF object table (this entry must not yet exist)
+ uint32_t iUsage; //!< DIBcolors Enumeration
+ U_OFFBMI offBmi; //!< Offset in bytes to U_BITMAPINFO (within DIBbitmapbuffer)
+ U_CBBMI cbBmi; //!< Size in bytes of U_BITMAPINFO
+ U_OFFBITS offBits; //!< Offset in bytes to the DIB bitmap data (within DIBbitmapbuffer
+ U_CBBITS cbBits; //!< Size in bytes of DIB bitmap
+ //!< Record may include optional DIB bitmapbuffer
+} U_EMRCREATEMONOBRUSH,
+ *PU_EMRCREATEMONOBRUSH; //!< EMF manual 2.3.7.5
+#define U_SIZE_EMRCREATEMONOBRUSH (sizeof(U_EMRCREATEMONOBRUSH))
+
+/* Index 94 */
+/** EMF manual 2.3.7.4
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t ihBrush; //!< Index to place object in EMF object table (this entry must not yet exist)
+ uint32_t iUsage; //!< DIBcolors Enumeration
+ U_OFFBMI offBmi; //!< Offset in bytes to U_BITMAPINFO (within DIB bitmapbuffer)
+ U_CBBMI cbBmi; //!< Size in bytes of U_BITMAPINFO
+ U_OFFBITS offBits; //!< Offset in bytes to the DIB bitmap data (within DIB bitmapbuffer
+ U_CBBITS cbBits; //!< Size in bytes of DIB bitmap
+ //!< Record may include optional DIB bitmapbuffer
+} U_EMRCREATEDIBPATTERNBRUSHPT,
+ *PU_EMRCREATEDIBPATTERNBRUSHPT; //!< EMF manual 2.3.7.4
+#define U_SIZE_EMRCREATEDIBPATTERNBRUSHPT (sizeof(U_EMRCREATEDIBPATTERNBRUSHPT))
+
+/* Index 95 */
+/** EMF manual 2.3.7.9
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t ihPen; //!< Index to place object in EMF object table (this entry must not yet exist)
+ U_OFFBMI offBmi; //!< Offset in bytes to U_BITMAPINFO (within DIB bitmapbuffer)
+ U_CBBMI cbBmi; //!< Size in bytes of U_BITMAPINFO
+ U_OFFBITS offBits; //!< Offset in bytes to the DIB bitmap data (within DIB bitmapbuffer
+ U_CBBITS cbBits; //!< Size in bytes of DIB bitmap
+ U_EXTLOGPEN elp; //!< Pen parameters (Size is Variable!!!!)
+ //!< Record may include optional DIB bitmap
+} U_EMREXTCREATEPEN,
+ *PU_EMREXTCREATEPEN; //!< EMF manual 2.3.7.9
+#define U_SIZE_EMREXTCREATEPEN (sizeof(U_EMREXTCREATEPEN) - sizeof(U_EXTLOGPEN) + U_SIZE_EXTLOGPEN)
+
+/* Index 96.97 */
+/** EMF manual 2.3.5.32
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+ uint32_t iGraphicsMode; //!< GraphicsMode Enumeration
+ U_FLOAT exScale; //!< scale to 0.01 mm units ( only if iGraphicsMode & U_GM_COMPATIBLE)
+ U_FLOAT eyScale; //!< scale to 0.01 mm units ( only if iGraphicsMode & U_GM_COMPATIBLE)
+ U_NUM_EMRTEXT cStrings; //!< Number of U_EMRTEXT in array
+ U_EMRTEXT emrtext[1]; //!< Text parameters
+} U_EMRPOLYTEXTOUTA,
+ U_EMRPOLYTEXTOUTW, //!< EMF manual 2.3.5.33
+ *PU_EMRPOLYTEXTOUTA, //!< EMF manual 2.3.5.32
+ *PU_EMRPOLYTEXTOUTW; //!< EMF manual 2.3.5.33
+#define U_SIZE_EMRPOLYTEXTOUTA (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(uint32_t) + 2*sizeof(U_FLOAT) + sizeof(U_NUM_EMRTEXT))
+#define U_SIZE_EMRPOLYTEXTOUTW U_SIZE_EMRPOLYTEXTOUTA
+
+/* Index 98 (see 17) */
+
+/* Index 99 */
+/** EMF manual 2.3.7.2
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t ihCS; //!< Index to place object in EMF object table (this entry must not yet exist)
+ U_LOGCOLORSPACEA lcs; //!< ColorSpace parameters
+} U_EMRCREATECOLORSPACE,
+ *PU_EMRCREATECOLORSPACE; //!< EMF manual 2.3.7.2
+#define U_SIZE_EMRCREATECOLORSPACE (sizeof(U_EMRCREATECOLORSPACE))
+
+/* Index 100,101 */
+/** EMF manual 2.3.8.2
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t ihCS; //!< Index of object in EMF object table
+} U_EMRDELETECOLORSPACE,
+ U_EMRSETCOLORSPACE, //!< EMF manual 2.3.8.7
+ *PU_EMRDELETECOLORSPACE, //!< EMF manual 2.3.8.2
+ *PU_EMRSETCOLORSPACE; //!< EMF manual 2.3.8.7
+#define U_SIZE_EMRDELETECOLORSPACE (sizeof(U_EMRDELETECOLORSPACE))
+#define U_SIZE_EMRSETCOLORSPACE (sizeof(U_EMRSETCOLORSPACE ))
+
+/* Index 102 */
+/** EMF manual 2.3.9.2
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_CBDATA cbData; //!< Size of OpenGL data in bytes
+ U_DATA Data[1]; //!< OpenGL data
+} U_EMRGLSRECORD,
+ *PU_EMRGLSRECORD; //!< EMF manual 2.3.9.2
+#define U_SIZE_EMRGLSRECORD (sizeof(U_EMR) + sizeof(U_CBDATA))
+
+/* Index 103 */
+/** EMF manual 2.3.9.1
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+ U_CBDATA cbData; //!< Size of OpenGL data in bytes
+ U_DATA Data[1]; //!< OpenGL data
+} U_EMRGLSBOUNDEDRECORD,
+ *PU_EMRGLSBOUNDEDRECORD; //!< EMF manual 2.3.9.1
+#define U_SIZE_EMRGLSBOUNDEDRECORD (sizeof(U_EMR) + sizeof(U_RECTL) + sizeof(U_CBDATA))
+
+/* Index 104 */
+/** EMF manual 2.3.11.5
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_PIXELFORMATDESCRIPTOR pfd; //!< PixelFormatDescriptor
+} U_EMRPIXELFORMAT,
+ *PU_EMRPIXELFORMAT; //!< EMF manual 2.3.11.5
+#define U_SIZE_EMRPIXELFORMAT (sizeof(U_EMRPIXELFORMAT))
+
+/* Index 105 */
+/** EMF manual 2.3.6.1
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_CBDATA cjIn; //!< Number of bytes to send to printer driver
+ U_DATA Data[1]; //!< Data to send
+} U_EMRDRAWESCAPE,
+ *PU_EMRDRAWESCAPE; //!< EMF manual 2.3.6.1
+#define U_SIZE_EMRDRAWESCAPE (sizeof(U_EMR) + sizeof(U_CBDATA))
+
+/* Index 106 */
+/** EMF manual 2.3.6.2
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_CBDATA cjIn; //!< Number of bytes to send to printer driver
+ U_DATA Data[1]; //!< Data to send
+} U_EMREXTESCAPE,
+ *PU_EMREXTESCAPE; //!< EMF manual 2.3.6.2
+#define U_SIZE_EMREXTESCAPE (sizeof(U_EMR) + sizeof(U_CBDATA))
+
+/* Index 107 (not implemented ) */
+
+/* Index 108 */
+/** EMF manual 2.3.5.37
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_POINTL Dest; //!< Where to draw the text
+ U_NUM_STR cChars; //!< Characters in TextString (not null terminated)
+ uint32_t fuOptions; //!< ExtTextOutOptions Enumeration
+ uint32_t iGraphicsMode; //!< GraphicsMode Enumeration
+ U_FLOAT exScale; //!< scale on X axis
+ U_FLOAT eyScale; //!< scale on Y axis
+//!< the tail end of this record is variable.
+//!< U_RECTL rclBounds; Record may include optional Bounding rectangle (absent when: fuOPtions & ETO_NO_U_RECT)
+//!< uint32_t TextString; text to output (fuOptions & ETO_SMALL_CHARS ? 8 bit : 16 bit)
+} U_EMRSMALLTEXTOUT,
+ *PU_EMRSMALLTEXTOUT; //!< EMF manual 2.3.5.37
+#define U_SIZE_EMRSMALLTEXTOUT (sizeof(U_EMRSMALLTEXTOUT))
+
+/* Index 109 (not implemented )
+EMF manual 2.3.11.2
+*/
+
+/* Index 110 */
+/** EMF manual 2.3.6.3
+
+ followed by
+ uint8_t Data[1]; //!< Data for printer driver
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_CBDATA cbDriver; //!< Number of bytes in driver name (note, BYTES, not CHARACTERS)
+ U_CBDATA cbData; //!< Number of bytes in data
+ uint16_t Driver[1]; //!< Driver name in uint16_t characters, null terminated
+} U_EMRNAMEDESCAPE,
+ *PU_EMRNAMEDESCAPE; //!< EMF manual 2.3.6.3
+#define U_SIZE_EMRNAMEDESCAPE (sizeof(U_EMR) + 2*sizeof(U_CBDATA))
+
+/* Index 111-113 (not implemented )
+ EMF manual 2.3.8.1
+ EMF manual 2.3.11.15
+ EMF manual 2.3.11.16
+*/
+
+/* Index 114 */
+/** EMF manual 2.3.1.1
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+ U_POINTL Dest; //!< Destination UL corner in logical units
+ U_POINTL cDest; //!< Destination W & H in logical units
+ U_BLEND Blend; //!< Blend Function
+ U_POINTL Src; //!< Source UL corner in logical units
+ U_XFORM xformSrc; //!< Transform to apply to source
+ U_COLORREF crBkColorSrc; //!< Background color
+ uint32_t iUsageSrc; //!< DIBcolors Enumeration
+ U_OFFBMISRC offBmiSrc; //!< Offset in bytes to U_BITMAPINFO (within bitmapbuffer)
+ U_CBBMISRC cbBmiSrc; //!< Size in bytes of U_BITMAPINFO
+ U_OFFBITSSRC offBitsSrc; //!< Offset in bytes to the bitmap (within bitmapbuffer)
+ U_CBBITS cbBitsSrc; //!< Size in bytes of bitmap
+ U_POINTL cSrc; //!< Source W & H in logical units
+ //!< Record may include optional DIB bitmap
+} U_EMRALPHABLEND,
+ *PU_EMRALPHABLEND; //!< EMF manual 2.3.1.1
+#define U_SIZE_EMRALPHABLEND (sizeof(U_EMRALPHABLEND))
+
+/* Index 115 (see 17) */
+
+/* Index 116 */
+/** EMF manual 2.3.1.8
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+ U_POINTL Dest; //!< Destination UL corner in logical units
+ U_POINTL cDest; //!< Destination W & H in logical units
+ uint32_t TColor; //!< Bitmap color to be treated as transparent
+ U_POINTL Src; //!< Source UL corner in logical units
+ U_XFORM xformSrc; //!< Transform to apply to source
+ U_COLORREF crBkColorSrc; //!< Background color
+ uint32_t iUsageSrc; //!< DIBcolors Enumeration
+ U_OFFBMISRC offBmiSrc; //!< Offset in bytes to U_BITMAPINFO (within bitmapbuffer)
+ U_CBBMISRC cbBmiSrc; //!< Size in bytes of U_BITMAPINFO
+ U_OFFBITSSRC offBitsSrc; //!< Offset in bytes to the bitmap (within bitmapbuffer)
+ U_CBBITS cbBitsSrc; //!< Size in bytes of bitmap
+ U_POINTL cSrc; //!< Source W & H in logical units
+ //!< Record may includes optional bitmapbuffer
+} U_EMRTRANSPARENTBLT,
+ *PU_EMRTRANSPARENTBLT; //!< EMF manual 2.3.1.8
+#define U_SIZE_EMRTRANSPARENTBLT (sizeof(U_EMRTRANSPARENTBLT))
+
+/* Index 117 (not a defined U_EMR record type ) */
+
+/* Index 118 */
+/** EMF manual 2.3.5.12
+
+ followed by
+ U_TRIVERTEX TriVert[1]; Array of TriVertex objects
+ uint32_t GradObj[1]; Array of gradient objects (each has 2 or 3 indices into TriVert array)
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ U_RECTL rclBounds; //!< Bounding rectangle in device units
+ U_NUM_TRIVERTEX nTriVert; //!< Number of TriVertex objects
+ U_NUM_GRADOBJ nGradObj; //!< Number of gradient triangle/rectangle objects
+ uint32_t ulMode; //!< Gradientfill Enumeration (determines Triangle/Rectangle)
+} U_EMRGRADIENTFILL,
+ *PU_EMRGRADIENTFILL; //!< EMF manual 2.3.5.12
+#define U_SIZE_EMRGRADIENTFILL (sizeof(U_EMRGRADIENTFILL))
+
+/* Index 119,120 (not implemented )
+EMF manual 2.3.11.18
+EMF manual 2.3.11.27
+*/
+
+/* Index 121 */
+/** EMF manual 2.3.11.1
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t dwAction; //!< ColorSpace Enumeration
+ uint32_t dwFlags; //!< ColorMatchToTarget Enumeration
+ U_CBNAME cbName; //!< Number of bytes in UTF16 name of the color profile
+ U_CBDATA cbData; //!< Number of bytes of the target profile
+ uint8_t Data[1]; //!< Data of size cbName+cbData: Name in UTF16 then color profile data
+} U_EMRCOLORMATCHTOTARGETW,
+ *PU_EMRCOLORMATCHTOTARGETW; //!< EMF manual 2.3.11.1
+#define U_SIZE_EMRCOLORMATCHTOTARGETW (sizeof(U_EMR) + 2*sizeof(uint32_t) + sizeof(U_CBNAME) + sizeof(U_CBDATA))
+
+/* Index 122 */
+/** EMF manual 2.3.7.3
+*/
+typedef struct {
+ U_EMR emr; //!< U_EMR
+ uint32_t ihCS; //!< Index of the logical color space object in the EMF object table
+ U_LOGCOLORSPACEW lcs; //!< Description of the color profile
+ uint32_t dwFlags; //!< If low bit set Data is present
+ U_CBDATA cbData; //!< Number of bytes of theData field.
+ uint8_t Data[1]; //!< (Optional, dwFlags & 1) color profile data
+} U_EMRCREATECOLORSPACEW,
+ *PU_EMRCREATECOLORSPACEW; //!< EMF manual 2.3.7.3
+#define U_SIZE_EMRCREATECOLORSPACEW (sizeof(U_EMR) + 2*sizeof(uint32_t) + sizeof(U_LOGCOLORSPACEW) + sizeof(U_CBDATA))
+
+// records which are not documented, so we have no idea what to do with them
+#define U_SIZE_EMRUNDEFINED 2048
+
+// ************************************************************************************************
+// Utility function structures
+
+/**
+ Storage for keeping track of properties of the growing EMF file as records are added.
+*/
+typedef struct {
+ FILE *fp; //!< Open file
+ size_t allocated; //!< Size of the buffer
+ size_t used; //!< Amount consumed
+ uint32_t records; //!< Number of records already contained
+ uint16_t ignore; //!< size padding,not used
+ uint32_t PalEntries; //!< Number of PalEntries (set from U_EMREOF)
+ uint32_t chunk; //!< Number of bytes to add when more space is needed
+ char *buf; //!< Buffer for constructing the EMF in memory
+} EMFTRACK;
+
+/**
+ The various create functions need a place to put their handles, these are stored in the table below.
+ We don't actually do anything much with these handles, that is up to whatever program finally plays back the EMF, but
+ we do need to keep track of the numbers so that they are not accidentally reused. This structure is used for that,
+ and all *_set functions that touch a handle reference it.
+
+ Stock objects are not used in this limited model, so libUEMF cannot detect if a handle is still in use. Nor can it
+ tell when a handle has been deselected (by selecting another handle for the same type of graphic object, and thus
+ made deleteable). End user code must keep track of this for itself.
+*/
+typedef struct {
+ uint32_t *table; //!< Array Buffer for constructing the EMF in memory
+ uint32_t *stack; //!< handles are either on the stack or in the table
+ size_t allocated; //!< Slots in the buffer
+ size_t chunk; //!< Number to add if a realloc is required
+ uint32_t sptr; //!< Pointer to next available handle in the stack
+ uint32_t top; //!< Highest slot occupied (currently)
+ uint32_t peak; //!< Highest slot occupied (ever)
+} EMFHANDLES;
+
+/**
+ 2 x 2 matrix, used by xform_alt_set() function.
+*/
+typedef struct {
+ double M11; //!< Matrix element 1,1
+ double M12; //!< Matrix element 1,2
+ double M21; //!< Matrix element 2,1
+ double M22; //!< Matrix element 2,2
+} U_MAT2X2,
+ *PU_MAT2X2; //!< 2 x 2 matrix, used by xform_alt_set() function.
+
+// ************************************************************************************************
+// Prototypes
+
+//! \cond
+int memprobe(const void *buf, size_t size);
+void wchar8show(const char *src);
+void wchar16show(const uint16_t *src);
+void wchar32show(const uint32_t *src);
+void wchartshow(const wchar_t *src);
+void dumpeht(char *string, unsigned int *handle, EMFHANDLES *eht);
+
+
+char *U_emr_names(unsigned int idx);
+uint32_t *dx_set(int32_t height, uint32_t weight, uint32_t members);
+uint32_t emr_properties(uint32_t type);
+int emr_arc_points(PU_ENHMETARECORD record, int *f1, int f2, PU_PAIRF center, PU_PAIRF start, PU_PAIRF end, PU_PAIRF size);
+int emr_arc_points_common(PU_RECTL rclBox, PU_POINTL ArcStart, PU_POINTL ArcEnd,
+ int *f1, int f2, PU_PAIRF center, PU_PAIRF start, PU_PAIRF end, PU_PAIRF size);
+int get_real_color_count(const char *Bmih);
+int get_real_color_icount(int Colors, int BitCount, int Width, int Height);
+int RGBA_to_DIB(char **px, uint32_t *cbPx, PU_RGBQUAD *ct, int *numCt,
+ const char *rgba_px, int w, int h, int stride, uint32_t colortype, int use_ct, int invert);
+int get_DIB_params( const char *record, uint32_t offBitsSrc, uint32_t offBmiSrc,
+ const char **px, const U_RGBQUAD **ct, uint32_t *numCt,
+ uint32_t *width, uint32_t *height, uint32_t *colortype, uint32_t *invert );
+int DIB_to_RGBA(const char *px, const U_RGBQUAD *ct, int numCt,
+ char **rgba_px, int w, int h, uint32_t colortype, int use_ct, int invert);
+char *RGBA_to_RGBA(char *rgba_px, int w, int h, int sl, int st, int *ew, int *eh);
+
+int device_size(const int xmm, const int ymm, const float dpmm, U_SIZEL *szlDev, U_SIZEL *szlMm);
+int drawing_size(const int xmm, const int yum, const float dpmm, U_RECTL *rclBounds, U_RECTL *rclFrame);
+
+int emf_start(const char *name, const uint32_t initsize, const uint32_t chunksize, EMFTRACK **et);
+int emf_finish(EMFTRACK *et, EMFHANDLES *eht);
+int emf_free(EMFTRACK **et);
+int emf_append(U_ENHMETARECORD *rec, EMFTRACK *et, int freerec);
+int emf_readdata(const char *filename, char **contents, size_t *length);
+FILE *emf_fopen(const char *filename, const int mode);
+
+
+/* use these instead*/
+int emf_htable_create(uint32_t initsize, uint32_t chunksize, EMFHANDLES **eht);
+int emf_htable_delete(uint32_t *ih, EMFHANDLES *eht);
+int emf_htable_insert(uint32_t *ih, EMFHANDLES *eht);
+int emf_htable_free(EMFHANDLES **eht);
+/* Deprecated forms */
+#define htable_create emf_htable_create
+#define htable_delete emf_htable_delete
+#define htable_insert emf_htable_insert
+#define htable_free emf_htable_free
+
+U_RECTL rectl_set(U_POINTL ul, U_POINTL lr);
+void rectli_set(PU_RECTL array, int index, U_POINTL ul, U_POINTL lr);
+U_SIZEL sizel_set(int32_t x, int32_t y);
+U_POINTL point32_set(int32_t x, int32_t y);
+#define point_set point32_set
+#define pointl_set point32_set
+U_POINT16 point16_set(int16_t x, int16_t y);
+U_PANOSE panose_set(uint8_t bFamilyType, uint8_t bSerifStyle, uint8_t bWeight, uint8_t bProportion,
+ uint8_t bContrast, uint8_t bStrokeVariation, uint8_t bArmStyle, uint8_t bLetterform,
+ uint8_t bMidline, uint8_t bXHeight );
+U_COLORREF colorref3_set(uint8_t red, uint8_t green, uint8_t blue);
+U_COLORREF colorref4_set(uint8_t red, uint8_t green, uint8_t blue, uint8_t reserved);
+U_RGBQUAD rgbquad_set(uint8_t red,uint8_t green, uint8_t blue, uint8_t reserved);
+U_LOGBRUSH logbrush_set(uint32_t lbStyle, U_COLORREF lbColor, int32_t lbHatch);
+U_XFORM xform_set(U_FLOAT eM11, U_FLOAT eM12, U_FLOAT eM21, U_FLOAT eM22, U_FLOAT eDx, U_FLOAT eDy);
+U_XFORM xform_alt_set(U_FLOAT scale, U_FLOAT ratio, U_FLOAT rot, U_FLOAT axisrot, U_FLOAT eDx, U_FLOAT eDy);
+U_LOGPEN logpen_set( uint32_t lopnStyle, U_POINT lopnWidth, U_COLORREF lopnColor );
+PU_EXTLOGPEN extlogpen_set(uint32_t elpPenStyle, uint32_t elpWidth, uint32_t elpBrushStyle,
+ U_COLORREF elpColor, int32_t elpHatch, U_NUM_STYLEENTRY elpNumEntries, U_STYLEENTRY *elpStyleEntry );
+U_LOGFONT_PANOSE logfont_panose_set(U_LOGFONT elfLogFont, uint16_t *elfFullName,
+ uint16_t *elfStyle, uint32_t elfStyleSize, U_PANOSE elfPanose);
+U_LOGFONT logfont_set( int32_t lfHeight, int32_t lfWidth, int32_t lfEscapement, int32_t lfOrientation,
+ int32_t lfWeight, uint8_t lfItalic, uint8_t lfUnderline, uint8_t lfStrikeOut,
+ uint8_t lfCharSet, uint8_t lfOutPrecision, uint8_t lfClipPrecision,
+ uint8_t lfQuality, uint8_t lfPitchAndFamily, uint16_t *lfFaceName);
+char *emrtext_set(U_POINTL ptlReference, U_NUM_STR NumString, uint32_t cbChar, void *String, uint32_t fOptions, U_RECTL rcl, uint32_t *Dx);
+U_LOGPLTNTRY logpltntry_set(uint8_t peReserved,uint8_t peRed,uint8_t peGreen,uint8_t peBlue);
+PU_LOGPALETTE logpalette_set(U_NUM_LOGPLTNTRY palNumEntries,PU_LOGPLTNTRY *palPalEntry);
+U_RGNDATAHEADER rgndataheader_set( U_NUM_RECTL nCount, U_RECTL rcBound);
+PU_RGNDATA rgndata_set( U_RGNDATAHEADER rdh, PU_RECTL Buffer);
+U_BITMAPINFOHEADER bitmapinfoheader_set(int32_t biWidth, int32_t biHeight,
+ uint16_t biPlanes, uint16_t biBitCount, uint32_t biCompression,
+ uint32_t biSizeImage, int32_t biXPelsPerMeter,
+ int32_t biYPelsPerMeter, U_NUM_RGBQUAD biClrUsed, uint32_t biClrImportant);
+PU_BITMAPINFO bitmapinfo_set(U_BITMAPINFOHEADER BmiHeader, PU_RGBQUAD BmiColors);
+U_LOGCOLORSPACEA logcolorspacea_set(int32_t lcsCSType, int32_t lcsIntent,
+ U_CIEXYZTRIPLE lcsEndpoints, U_LCS_GAMMARGB lcsGammaRGB, char *lcsFilename);
+U_LOGCOLORSPACEW logcolorspacew_set(int32_t lcsCSType, int32_t lcsIntent,
+ U_CIEXYZTRIPLE lcsEndpoints, U_LCS_GAMMARGB lcsGammaRGB, uint16_t *lcsFilename);
+U_COLORADJUSTMENT coloradjustment_set(uint16_t Size, uint16_t Flags, uint16_t IlluminantIndex,
+ uint16_t RedGamma, uint16_t GreenGamma, uint16_t BlueGamma,
+ uint16_t ReferenceBlack, uint16_t ReferenceWhite,
+ int16_t Contrast, int16_t Brightness, int16_t Colorfulness, int16_t RedGreenTint);
+U_PIXELFORMATDESCRIPTOR pixelformatdescriptor_set( uint32_t dwFlags, uint8_t iPixelType, uint8_t cColorBits,
+ uint8_t cRedBits, uint8_t cRedShift,
+ uint8_t cGreenBits, uint8_t cGreenShift,
+ uint8_t cBlueBits, uint8_t cBlueShift,
+ uint8_t cAlphaBits, uint8_t cAlphaShift,
+ uint8_t cAccumBits, uint8_t cAccumRedBits, uint8_t cAccumGreenBits, uint8_t cAccumBlueBits,
+ uint8_t cAccumAlphaBits, uint8_t cDepthBits, uint8_t cStencilBits,
+ uint8_t cAuxBuffers, uint8_t iLayerType, uint8_t bReserved, uint32_t dwLayerMask,
+ uint32_t dwVisibleMask, uint32_t dwDamageMask);
+
+PU_POINT points_transform(PU_POINT points, int count, U_XFORM xform);
+PU_POINT16 point16_transform(PU_POINT16 points, int count, U_XFORM xform);
+PU_TRIVERTEX trivertex_transform(PU_TRIVERTEX tv, int count, U_XFORM xform);
+PU_POINT point16_to_point(PU_POINT16 points, int count);
+PU_POINT16 point_to_point16(PU_POINT points, int count);
+
+U_RECT findbounds(uint32_t count, PU_POINT pts, uint32_t width);
+U_RECT findbounds16(uint32_t count, PU_POINT16 pts, uint32_t width);
+char *emr_dup(const char *emr);
+
+char *textcomment_set(const char *string);
+
+// These generate the handle and then call the underlying function
+char *deleteobject_set(uint32_t *ihObject, EMFHANDLES *eht);
+char *selectobject_set(uint32_t ihObject, EMFHANDLES *eht);
+char *createpen_set(uint32_t *ihPen, EMFHANDLES *eht, U_LOGPEN lopn );
+char *extcreatepen_set(uint32_t *ihPen, EMFHANDLES *eht,
+ PU_BITMAPINFO Bmi, const uint32_t cbPx, char *Px, PU_EXTLOGPEN elp);
+char *createbrushindirect_set(uint32_t *ihBrush, EMFHANDLES *eht, U_LOGBRUSH lb );
+char *createdibpatternbrushpt_set(uint32_t *ihBrush, EMFHANDLES *eht, uint32_t iUsage,
+ PU_BITMAPINFO Bmi, const uint32_t cbPx, const char *Px);
+char *createmonobrush_set(uint32_t *ihBrush, EMFHANDLES *eht, uint32_t iUsage,
+ PU_BITMAPINFO Bmi, const uint32_t cbPx, const char *Px);
+char *extcreatefontindirectw_set(uint32_t *ihFont, EMFHANDLES *eht, const char *elf, const char *elfw);
+char *createpalette_set(uint32_t *ihPal, EMFHANDLES *eht, U_LOGPALETTE lgpl);
+char *setpaletteentries_set(uint32_t *ihPal, EMFHANDLES *eht, uint32_t iStart, U_NUM_LOGPLTNTRY cEntries, PU_LOGPLTNTRY aPalEntries);
+char *fillrgn_set(uint32_t *ihBrush, EMFHANDLES *eht, U_RECTL rclBounds,PU_RGNDATA RgnData);
+char *framergn_set(uint32_t *ihBrush, EMFHANDLES *eht, U_RECTL rclBounds, U_SIZEL szlStroke, PU_RGNDATA RgnData);
+char *createcolorspace_set(uint32_t *ihCS, EMFHANDLES *eht, U_LOGCOLORSPACEA lcs);
+char *createcolorspacew_set(uint32_t *ihCS, EMFHANDLES *eht, U_LOGCOLORSPACEW lcs, uint32_t dwFlags, U_CBDATA cbData, uint8_t *Data);
+
+char *U_EMRHEADER_set( const U_RECTL rclBounds, const U_RECTL rclFrame, U_PIXELFORMATDESCRIPTOR* const pfmtDesc,
+ U_CBSTR nDesc, uint16_t* const Description, const U_SIZEL szlDevice, const U_SIZEL szlMillimeters,
+ const uint32_t bOpenGL);
+char *U_EMRPOLYBEZIER_set( const U_RECTL rclBounds, const uint32_t count, const U_POINTL *points);
+char *U_EMRPOLYGON_set( const U_RECTL rclBounds, const uint32_t count, const U_POINTL *points);
+char *U_EMRPOLYLINE_set( const U_RECTL rclBounds, const uint32_t count, const U_POINTL *points);
+char *U_EMRPOLYBEZIERTO_set(const U_RECTL rclBounds, const uint32_t count, const U_POINTL *points);
+char *U_EMRPOLYLINETO_set( const U_RECTL rclBounds, const uint32_t count, const U_POINTL *points);
+
+char *U_EMRPOLYPOLYLINE_set(const U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,
+ const uint32_t cptl, const U_POINTL *points);
+char *U_EMRPOLYPOLYGON_set(const U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,
+ const uint32_t cptl, const U_POINTL *points);
+char *U_EMRSETWINDOWEXTEX_set(const U_SIZEL szlExtent);
+char *U_EMRSETWINDOWORGEX_set(const U_POINTL ptlOrigin);
+char *U_EMRSETVIEWPORTEXTEX_set(const U_SIZEL szlExtent);
+char *U_EMRSETVIEWPORTORGEX_set(const U_POINTL ptlOrigin);
+char *U_EMRSETBRUSHORGEX_set(const U_POINTL ptlOrigin);
+char *U_EMREOF_set(const U_CBPLENTRIES cbPalEntries, const PU_LOGPLTNTRY PalEntries, EMFTRACK *et);
+char *U_EMRSETPIXELV_set(const U_POINTL ptlPixel, const U_COLORREF crColor);
+char *U_EMRSETMAPPERFLAGS_set(void);
+char *U_EMRSETMAPMODE_set(const uint32_t iMode);
+char *U_EMRSETBKMODE_set(const uint32_t iMode);
+char *U_EMRSETPOLYFILLMODE_set(const uint32_t iMode);
+char *U_EMRSETROP2_set(const uint32_t iMode);
+char *U_EMRSETSTRETCHBLTMODE_set(const uint32_t iMode);
+char *U_EMRSETTEXTALIGN_set(const uint32_t iMode);
+char *U_EMRSETCOLORADJUSTMENT_set(const U_COLORADJUSTMENT ColorAdjustment);
+char *U_EMRSETTEXTCOLOR_set(const U_COLORREF crColor);
+char *U_EMRSETBKCOLOR_set(const U_COLORREF crColor);
+char *U_EMROFFSETCLIPRGN_set(const U_POINTL ptl);
+char *U_EMRMOVETOEX_set(const U_POINTL ptl);
+char *U_EMRSETMETARGN_set(void);
+char *U_EMREXCLUDECLIPRECT_set(const U_RECTL rclClip);
+char *U_EMRINTERSECTCLIPRECT_set(const U_RECTL rclClip);
+char *U_EMRSCALEVIEWPORTEXTEX_set(const int32_t xNum, const int32_t xDenom, const int32_t yNum, const int32_t yDenom);
+char *U_EMRSCALEWINDOWEXTEX_set(const int32_t xNum, const int32_t xDenom, const int32_t yNum, const int32_t yDenom);
+char *U_EMRSAVEDC_set(void);
+char *U_EMRRESTOREDC_set(const int32_t iRelative);
+char *U_EMRSETWORLDTRANSFORM_set(const U_XFORM xform);
+char *U_EMRMODIFYWORLDTRANSFORM_set(const U_XFORM xform, const uint32_t iMode);
+char *U_EMRSELECTOBJECT_set(const uint32_t ihObject); // better to call selectobject_set()
+char *U_EMRCREATEPEN_set(const uint32_t ihPen, const U_LOGPEN lopn );
+char *U_EMRCREATEBRUSHINDIRECT_set(const uint32_t ihBrush, const U_LOGBRUSH lb);
+char *U_EMRDELETEOBJECT_set(const uint32_t ihObject); // better to call deleteobject_set()
+char *U_EMRANGLEARC_set(const U_POINTL ptlCenter, const uint32_t nRadius, const U_FLOAT eStartAngle, const U_FLOAT eSweepAngle);
+char *U_EMRELLIPSE_set(const U_RECTL rclBox);
+char *U_EMRRECTANGLE_set(const U_RECTL rclBox);
+char *U_EMRROUNDRECT_set(const U_RECTL rclBox, const U_SIZEL szlCorner);
+char *U_EMRARC_set(const U_RECTL rclBox, const U_POINTL ptlStart, const U_POINTL ptlEnd);
+char *U_EMRCHORD_set(const U_RECTL rclBox, const U_POINTL ptlStart, const U_POINTL ptlEnd);
+char *U_EMRPIE_set(const U_RECTL rclBox, const U_POINTL ptlStart, const U_POINTL ptlEnd);
+char *U_EMRSELECTPALETTE_set(const uint32_t ihPal);
+char *U_EMRCREATEPALETTE_set(const uint32_t ihPal, const U_LOGPALETTE lgpl);
+char *U_EMRSETPALETTEENTRIES_set(const uint32_t ihPal, const uint32_t iStart, const U_NUM_LOGPLTNTRY cEntries, const PU_LOGPLTNTRY aPalEntries);
+char *U_EMRRESIZEPALETTE_set(const uint32_t ihPal, const uint32_t cEntries);
+char *U_EMRREALIZEPALETTE_set(void);
+char *U_EMREXTFLOODFILL_set(const U_POINTL ptlStart, const U_COLORREF crColor, const uint32_t iMode);
+char *U_EMRLINETO_set(const U_POINTL ptl);
+char *U_EMRARCTO_set(const U_RECTL rclBox, const U_POINTL ptlStart, const U_POINTL ptlEnd);
+char *U_EMRPOLYDRAW_set(const U_RECTL rclBounds,const U_NUM_POINTL cptl,const U_POINTL *aptl,const uint8_t *abTypes);
+char *U_EMRSETARCDIRECTION_set(const uint32_t iArcDirection);
+char *U_EMRSETMITERLIMIT_set(const uint32_t eMiterLimit);
+char *U_EMRBEGINPATH_set(void);
+char *U_EMRENDPATH_set(void);
+char *U_EMRCLOSEFIGURE_set(void);
+char *U_EMRFILLPATH_set(const U_RECTL rclBox);
+char *U_EMRSTROKEANDFILLPATH_set(const U_RECTL rclBox);
+char *U_EMRSTROKEPATH_set(const U_RECTL rclBox);
+char *U_EMRFLATTENPATH_set(void);
+char *U_EMRWIDENPATH_set(void);
+char *U_EMRSELECTCLIPPATH_set(const uint32_t iMode);
+char *U_EMRABORTPATH_set(void);
+// EMR_ENDEF69
+char *U_EMRCOMMENT_set(const U_CBDATA cbData, const char *Data);
+char *U_EMRFILLRGN_set(const U_RECTL rclBounds, const uint32_t ihBrush, const PU_RGNDATA RgnData);
+char *U_EMRFRAMERGN_set(const U_RECTL rclBounds, const uint32_t ihBrush, const U_SIZEL szlStroke, const PU_RGNDATA RgnData);
+char *U_EMRINVERTRGN_set(const PU_RGNDATA RgnData);
+char *U_EMRPAINTRGN_set(const PU_RGNDATA RgnData);
+char *U_EMREXTSELECTCLIPRGN_set(const uint32_t iMode, const PU_RGNDATA RgnData);
+char *U_EMRBITBLT_set(const U_RECTL rclBounds, const U_POINTL Dest, const U_POINTL cDest,
+ const U_POINTL Src, const U_XFORM xformSrc, const U_COLORREF crBkColorSrc,
+ const uint32_t iUsageSrc, const uint32_t dwRop,
+ const PU_BITMAPINFO Bmi, const uint32_t cbPx, char *Px);
+char *U_EMRSTRETCHBLT_set(U_RECTL rclBounds, U_POINTL Dest, U_POINTL cDest,
+ const U_POINTL Src, const U_POINTL cSrc, const U_XFORM xformSrc, const U_COLORREF crBkColorSrc, const uint32_t iUsageSrc,
+ const uint32_t dwRop,
+ const PU_BITMAPINFO Bmi, const uint32_t cbPx, char *Px);
+char *U_EMRMASKBLT_set(U_RECTL rclBounds, U_POINTL Dest, U_POINTL cDest,
+ const U_POINTL Src, const U_XFORM xformSrc, const U_COLORREF crBkColorSrc, const uint32_t iUsageSrc,
+ const U_POINTL Mask, const uint32_t iUsageMask,
+ const uint32_t dwRop,
+ const PU_BITMAPINFO Bmi, const uint32_t cbPx, char *Px,
+ const PU_BITMAPINFO BmiMsk, const uint32_t cbMsk, char *Msk);
+char *U_EMRPLGBLT_set(const U_RECTL rclBounds, const PU_POINTL aptlDst,
+ const U_POINTL Src, const U_POINTL cSrc, const U_XFORM xformSrc, const U_COLORREF crBkColorSrc, const uint32_t iUsageSrc,
+ const U_POINTL Mask, const uint32_t iUsageMask,
+ const PU_BITMAPINFO Bmi, const uint32_t cbPx, char *Px,
+ const PU_BITMAPINFO BmiMsk, const uint32_t cbMsk, char *Msk);
+char *U_EMRSETDIBITSTODEVICE_set(const U_RECTL rclBounds, const U_POINTL Dest,
+ const U_POINTL Src, const U_POINTL cSrc, const uint32_t iUsageSrc,
+ const uint32_t iStartScan, const uint32_t cScans,
+ const PU_BITMAPINFO Bmi, const uint32_t cbPx, char *Px);
+char *U_EMRSTRETCHDIBITS_set(const U_RECTL rclBounds, const U_POINTL Dest, const U_POINTL cDest,
+ const U_POINTL Src, const U_POINTL cSrc, const uint32_t iUsageSrc,
+ const uint32_t dwRop,
+ const PU_BITMAPINFO Bmi, const uint32_t cbPx, char *Px);
+char *U_EMREXTCREATEFONTINDIRECTW_set( uint32_t ihFont, const char *elf, const char *elfw);
+char *U_EMREXTTEXTOUTA_set(U_RECTL rclBounds, uint32_t iGraphicsMode, U_FLOAT exScale, U_FLOAT eyScale, PU_EMRTEXT emrtext);
+char *U_EMREXTTEXTOUTW_set(U_RECTL rclBounds, uint32_t iGraphicsMode, U_FLOAT exScale, U_FLOAT eyScale, PU_EMRTEXT emrtext);
+char *U_EMRPOLYBEZIER16_set(const U_RECTL rclBounds, const uint32_t cpts, const U_POINT16 *points);
+char *U_EMRPOLYGON16_set(const U_RECTL rclBounds, const uint32_t cpts, const U_POINT16 *points);
+char *U_EMRPOLYLINE16_set(const U_RECTL rclBounds, const uint32_t cpts, const U_POINT16 *points);
+char *U_EMRPOLYBEZIERTO16_set(const U_RECTL rclBounds, const uint32_t cpts, const U_POINT16 *points);
+char *U_EMRPOLYLINETO16_set(const U_RECTL rclBounds, const uint32_t cpts, const U_POINT16 *points);
+char *U_EMRPOLYPOLYLINE16_set(const U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,const uint32_t cpts, const U_POINT16 *points);
+char *U_EMRPOLYPOLYGON16_set(const U_RECTL rclBounds, const uint32_t nPolys, const uint32_t *aPolyCounts,const uint32_t cpts, const U_POINT16 *points);
+char *U_EMRPOLYDRAW16_set(const U_RECTL rclBounds,const U_NUM_POINT16 cpts, const U_POINT16 *aptl, const uint8_t *abTypes);
+char *U_EMRCREATEMONOBRUSH_set(const uint32_t ihBrush, const uint32_t iUsage,
+ const PU_BITMAPINFO Bmi, const uint32_t cbPx, const char *Px);
+char *U_EMRCREATEDIBPATTERNBRUSHPT_set(const uint32_t ihBrush, const uint32_t iUsage,
+ const PU_BITMAPINFO Bmi, const uint32_t cbPx, const char *Px);
+char *U_EMREXTCREATEPEN_set(const uint32_t ihPen, const PU_BITMAPINFO Bmi, const uint32_t cbPx, char *Px, const PU_EXTLOGPEN elp );
+// U_EMRPOLYTEXTOUTA_set 96 NOT IMPLEMENTED, denigrated after Windows NT
+// U_EMRPOLYTEXTOUTW_set 97 NOT IMPLEMENTED, denigrated after Windows NT
+char *U_EMRSETICMMODE_set(const uint32_t iMode);
+char *U_EMRCREATECOLORSPACE_set(const uint32_t ihCS, const U_LOGCOLORSPACEA lcs);
+char *U_EMRSETCOLORSPACE_set(const uint32_t ihCS );
+char *U_EMRDELETECOLORSPACE_set(const uint32_t ihCS);
+// U_EMRGLSRECORD_set 102 Not implemented
+// U_EMRGLSBOUNDEDRECORD_set 103 Not implemented
+char *U_EMRPIXELFORMAT_set(const U_PIXELFORMATDESCRIPTOR pfd);
+char *U_EMRSMALLTEXTOUT_set(const U_POINTL Dest, const U_NUM_STR cChars, const uint32_t fuOptions, const uint32_t iGraphicsMode,
+ const U_FLOAT exScale, const U_FLOAT eyScale, const U_RECTL rclBounds, const char *TextString);
+// U_EMRDRAWESCAPE_set 105 Not implemented
+// U_EMREXTESCAPE_set 106 Not implemented
+// U_EMRUNDEF107_set 107 Not implemented
+// U_EMRSMALLTEXTOUT_set 108
+// U_EMRFORCEUFIMAPPING_set 109 Not implemented
+// U_EMRNAMEDESCAPE_set 110 Not implemented
+// U_EMRCOLORCORRECTPALETTE_set 111 Not implemented
+// U_EMRSETICMPROFILEA_set 112 Not implemented
+// U_EMRSETICMPROFILEW_set 113 Not implemented
+
+
+char *U_EMRALPHABLEND_set(const U_RECTL rclBounds, const U_POINTL Dest, const U_POINTL cDest,
+ const U_POINTL Src, const U_POINTL cSrc, const U_XFORM xformSrc,
+ const U_COLORREF crBkColorSrc, const uint32_t iUsageSrc,
+ const U_BLEND Blend,
+ const PU_BITMAPINFO Bmi, const uint32_t cbPx, char *Px);
+char *U_EMRSETLAYOUT_set(const uint32_t iMode);
+char *U_EMRTRANSPARENTBLT_set(const U_RECTL rclBounds, const U_POINTL Dest, const U_POINTL cDest,
+ const U_POINTL Src, const U_POINTL cSrc, const U_XFORM xformSrc,
+ const U_COLORREF crBkColorSrc, const uint32_t iUsageSrc, const uint32_t TColor,
+ const PU_BITMAPINFO Bmi, const uint32_t cbPx, char *Px);
+// U_EMRUNDEF117_set 117 Not implemented
+char *U_EMRGRADIENTFILL_set(const U_RECTL rclBounds, const U_NUM_TRIVERTEX nTriVert, const U_NUM_GRADOBJ nGradObj,
+ const uint32_t ulMode, const PU_TRIVERTEX TriVert, const uint32_t *GradObj );
+// U_EMRSETLINKEDUFIS_set 119 Not implemented
+// U_EMRSETTEXTJUSTIFICATION_set 120 Not implemented (denigrated)
+// U_EMRCOLORMATCHTOTARGETW_set 121 Not implemented
+char *U_EMRCREATECOLORSPACEW_set(const uint32_t ihCS, const U_LOGCOLORSPACEW lcs, const uint32_t dwFlags,
+ const U_CBDATA cbData, const uint8_t *Data);
+
+//! \endcond
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UEMF_ */
diff --git a/src/3rdparty/libuemf/uemf_endian.c b/src/3rdparty/libuemf/uemf_endian.c
new file mode 100644
index 0000000..f746553
--- /dev/null
+++ b/src/3rdparty/libuemf/uemf_endian.c
@@ -0,0 +1,2270 @@
+/**
+ @file uemf_endian.c
+
+ @brief Functions for converting EMF records between Big Endian and Little Endian byte orders.
+
+ EMF files use Little Endian order.
+ On a Big Endian machine the data must be converted to/from Little Endian when it is writen to/read from a file.
+ On a Little Endian machine no conversion is required, but it is good to be able to test the routines on either platform.
+ When "torev" is true these routines convert from the native byte order to the reverse.
+ When "torev" is false these routines convert from the reverse byte order to the native.
+ Routines that do not use that variable swap byte order, and the way in which they do so does not depend
+ on the native byte order.
+
+ The only function here which should be called directly is U_emf_endian(), and then,except for testing purposes, only on a BE machine.
+
+ Many variables are initialized to zero even though they will always be set because
+ some versions of gcc give spurious "may be used uninitialized" warnings otherwise.
+*/
+
+/*
+File: uemf_endian.c
+Version: 0.0.21
+Date: 23-APR-2015
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2015 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "uemf.h"
+#include "uemf_endian.h"
+
+// hide almost everuything in here from Doxygen
+//! \cond
+
+/* **********************************************************************************************
+ These functions convert standard objects used in the EMR records.
+*********************************************************************************************** */
+
+void U_swap2(void *ul, unsigned int count){
+ uint8_t ctmp;
+ uint8_t *cl = (uint8_t *) ul;
+ for(; count; count--,cl+=2){
+ ctmp = *cl;
+ *cl = *(cl+1);
+ *(cl+1) = ctmp;
+ }
+}
+
+/* Note: U_swap4 is also used by uwmf_endian.c, in cases where the 32 bit data is not aligned on a 4 byte boundary */
+void U_swap4(void *ul, unsigned int count){
+ uint8_t ctmp;
+ uint8_t *cl = (uint8_t *) ul;
+ for(; count; count--,cl+=4){
+ ctmp = *(cl+0);
+ *(cl+0) = *(cl+3);
+ *(cl+3) = ctmp;
+ ctmp = *(cl+1);
+ *(cl+1) = *(cl+2);
+ *(cl+2) = ctmp;
+ }
+}
+
+/**
+ U_COLORREF and U_RGBQUAD do NOT need to be swapped, they are always stored in memory in the proper order.
+*/
+
+/**
+ \brief Convert rect and rectl objects from Upper Left and Lower Right corner points.
+ \param rect U_RECTL object
+ \param count number to convert
+*/
+void rectl_swap(
+ PU_RECTL rect,
+ unsigned int count
+ ){
+ U_swap4(rect,4*count);
+}
+
+/**
+ \brief Convert a U_SIZEL object.
+ \param sz U_SizeL object
+ \param count number to convert
+*/
+void sizel_swap(
+ PU_SIZEL sz,
+ unsigned int count
+ ){
+ U_swap4(sz,2*count);
+}
+
+/**
+ \brief Convert a U_POINTL object
+ \param pt U_POINTL object
+ \param count number to convert
+*/
+void pointl_swap(
+ PU_POINTL pt,
+ unsigned int count
+ ){
+ U_swap4(pt,2*count);
+}
+
+/**
+ \brief Convert a U_POINT16 object
+ \param pt U_POINT16 object
+ \param count number to convert
+*/
+void point16_swap(
+ PU_POINT16 pt,
+ unsigned int count
+ ){
+ U_swap2(pt,2*count);
+}
+
+
+
+/**
+ \brief Convert a U_TRIVERTEX object.
+ \param tv U_TRIVERTEX object.
+ \param count number to convert
+*/
+void trivertex_swap(
+ PU_TRIVERTEX tv,
+ unsigned int count
+ ){
+ for(;count; count--, tv++){
+ U_swap4(tv,2); /* x,y */
+ U_swap2(&(tv->Red),4); /* Red, Green, Blue, Alpha */
+ }
+}
+
+/**
+ \brief Convert a U_GRADIENT3 object.
+ \param tv U_GRADIENT3 object.
+ \param count number to convert
+*/
+void gradient3_swap(
+ PU_GRADIENT3 g3,
+ unsigned int count
+ ){
+ U_swap4(g3,3*count);
+}
+
+/**
+ \brief Convert a U_GRADIENT4 object.
+ \param tv U_GRADIENT4 object.
+ \param count number to convert
+*/
+void gradient4_swap(
+ PU_GRADIENT4 g4,
+ unsigned int count
+ ){
+ U_swap4(g4,2*count); //a gradient4 object has 2 int4's, NOT 4!
+}
+
+/**
+ \brief Convert a U_LOGBRUSH object.
+ \param lb U_LOGBRUSH object.
+*/
+void logbrush_swap(
+ PU_LOGBRUSH lb
+ ){
+ U_swap4(&(lb->lbStyle),1); // lbStyle
+ // ordered bytes: lbColor
+ U_swap4(&(lb->lbHatch),1); // lbHatch
+}
+
+/**
+ \brief Convert a U_XFORM object.
+ \param xform U_XFORM object
+*/
+void xform_swap(
+ PU_XFORM xform
+ ){
+ U_swap4(xform,6);
+}
+
+
+/**
+ \brief Convert a U_CIEXYZTRIPLE object
+ \param cie3 U_CIEXYZTRIPLE object
+*/
+void ciexyztriple_swap(
+ PU_CIEXYZTRIPLE cie3
+ ){
+ U_swap4(cie3,9);
+}
+/**
+ \brief Convert a U_LOGCOLORSPACEA object.
+ \param lcsa U_LOGCOLORSPACEA object
+*/
+void logcolorspacea_swap(
+ PU_LOGCOLORSPACEA lcsa
+ ){
+ U_swap4(lcsa,5); // lcsSignature lcsVersion lcsSize lcsCSType lcsIntent
+ ciexyztriple_swap(&(lcsa->lcsEndpoints));
+ // ordered bytes: lcsGammaRGB
+ // ordered bytes: lcsFilename
+}
+
+/**
+
+ \brief Convert a U_LOGCOLORSPACEW object.
+ \param lcsa U_LOGCOLORSPACEW object
+*/
+void logcolorspacew_swap(
+ PU_LOGCOLORSPACEW lcsa
+ ){
+ U_swap4(lcsa,5); // lcsSignature lcsVersion lcsSize lcsCSType lcsIntent
+ ciexyztriple_swap(&(lcsa->lcsEndpoints));
+ // ordered bytes: lcsGammaRGB
+ // UTF-16LE, already in order: lcsFilename
+}
+
+
+/**
+ \brief Convert a U_LOGFONT object.
+ \param lf U_LOGFONT object
+*/
+void logfont_swap(
+ PU_LOGFONT lf
+ ){
+ U_swap4(lf,5); // lfHeight lfWidth lfEscapement lfOrientation lfWeight
+ // ordered bytes: lfItalic lfUnderline lfStrikeOut lfCharSet lfOutPrecision lfClipPrecision lfQuality lfPitchAndFamily
+ // UTF16-LE, already in order
+}
+
+/**
+ \brief Convert a U_LOGFONT_PANOSE object.
+ \return U_LOGFONT_PANOSE object
+*/
+void logfont_panose_swap(
+ PU_LOGFONT_PANOSE lfp
+ ){
+ logfont_swap(&(lfp->elfLogFont)); // elfLogFont
+ // UTF-16LE, already in order: elfFullName
+ // UTF-16LE, already in order: elfStyle
+ U_swap4(&(lfp->elfVersion),4); // elfVersion elfStyleSize elfMatch elfReserved
+ // ordered bytes: elfVendorId
+ U_swap4(&(lfp->elfCulture),1); // elfCulture
+ // ordered bytes: elfPanose
+}
+
+/**
+ \brief Convert a U_BITMAPINFOHEADER object.
+ \param Bmi U_BITMAPINFOHEADER object
+*/
+void bitmapinfoheader_swap(
+ PU_BITMAPINFOHEADER Bmi
+ ){
+ U_swap4(Bmi,3); // biSize biWidth biHeight
+ U_swap2(&(Bmi->biPlanes),2); // biPlanes biBitCount
+ U_swap4(&(Bmi->biCompression),6); // biCompression biSizeImage biXPelsPerMeter biYPelsPerMeter biClrUsed biClrImportant
+}
+
+
+/**
+ \brief Convert a Pointer to a U_BITMAPINFO object.
+ \param Bmi Pointer to a U_BITMAPINFO object
+*/
+void bitmapinfo_swap(
+ const char *Bmi
+ ){
+ PU_BITMAPINFO pBmi = (PU_BITMAPINFO)Bmi;
+ bitmapinfoheader_swap(&(pBmi->bmiHeader)); // bmIHeader
+ // ordered bytes: bmiColors
+}
+
+/**
+ \brief Swap the ordered bytes in a DIB and verify that the sizes are OK
+
+ \return 1 on success, 0 on failure
+ \param record EMF record that contains a DIB pixel array
+ \param iUsage DIBcolors Enumeration
+ \param offBmi offset from the start of the record to the start of the bitmapinfo structure
+ \param cbBmi declared space for the bitmapinfo structure in the record
+ \param offBits offset from the start of the record to the start of the bitmap
+ \param cbBits declared space for the bitmap in the record (amount used may be less than this)
+ \param blimit one byte past the end of the record.
+ \param torev 1 for native to reversed, 0 for reversed to native
+
+ This method can only test DIBs that hold Microsoft's various bitmap types. PNG or JPG is just a bag
+ of bytes, and there is no possible way to derive from the known width and height how big it should be.
+*/
+int DIB_swap(
+ const char *record,
+ uint32_t iUsage,
+ uint32_t offBmi,
+ uint32_t cbBmi,
+ uint32_t offBits,
+ uint32_t cbBits,
+ const char *blimit,
+ int torev
+ ){
+ int dibparams = U_BI_UNKNOWN; // type of image not yet determined
+ const char *px = NULL; // DIB pixels
+ const U_RGBQUAD *ct = NULL; // DIB color table
+ int bs;
+ int usedbytes;
+
+ if(!cbBmi)return(1); // No DIB in a record where it is optional
+ if(IS_MEM_UNSAFE(record, offBmi + cbBmi, blimit))return(0);
+ if(cbBits && IS_MEM_UNSAFE(record, offBits + cbBits, blimit))return(0);
+ if(iUsage == U_DIB_RGB_COLORS){
+ uint32_t width, height, colortype, numCt, invert; // these values will be set in get_DIB_params
+ // next call returns pointers and values, but allocates no memory
+ if(torev){
+ dibparams = get_DIB_params(record, offBits, offBmi, &px, (const U_RGBQUAD **) &ct,
+ &numCt, &width, &height, &colortype, &invert);
+ }
+ bitmapinfo_swap(record + offBmi); // byte ordered fields in bitmapinfo
+ if(!torev){
+ dibparams = get_DIB_params(record, offBits, offBmi, &px, (const U_RGBQUAD **) &ct,
+ &numCt, &width, &height, &colortype, &invert);
+ }
+
+ // sanity checking
+ if(numCt && colortype >= U_BCBM_COLOR16)return(0); //color tables not used above 16 bit pixels
+ if(!numCt && colortype < U_BCBM_COLOR16)return(0); //color tables mandatory for < 16 bit
+
+ if(dibparams ==U_BI_RGB){
+ // this is the only DIB type where we can calculate how big it should be when stored in the EMF file
+ bs = colortype/8;
+ if(bs<1){
+ usedbytes = (width*colortype + 7)/8; // width of line in fully and partially occupied bytes
+ }
+ else {
+ usedbytes = width*bs;
+ }
+ if(IS_MEM_UNSAFE(record+offBits, usedbytes, blimit))return(0);
+ }
+ }
+ else {
+ bitmapinfo_swap(record + offBmi);
+ }
+ return(1);
+}
+
+/**
+ \brief Convert a pointer to a U_EXTLOGPEN object.
+ \param elp PU_EXTLOGPEN object
+ \param blimit one byte past the end of the record
+*/
+int extlogpen_swap(
+ PU_EXTLOGPEN elp,
+ const char *blimit,
+ int torev
+ ){
+ int count=0;
+ U_swap4(elp,3); // elpPenStyle elpWidth elpBrushStyle
+ // ordered bytes: elpColor
+ if(torev){
+ count = elp->elpNumEntries;
+ }
+ U_swap4(&(elp->elpHatch),2); // elpHatch elpNumEntries
+ if(!torev){
+ count = elp->elpNumEntries;
+ }
+ if(IS_MEM_UNSAFE(&(elp->elpStyleEntry), count*4, blimit))return(0);
+ U_swap4(&(elp->elpStyleEntry),count); // elpStyleEntry[]
+ return(1);
+}
+
+/**
+ \brief Convert a U_LOGPEN object.
+ \param lp U_LOGPEN object
+
+*/
+void logpen_swap(
+ PU_LOGPEN lp
+ ){
+ U_swap4(lp,1); // lopnStyle
+ pointl_swap(&(lp->lopnWidth),1); // lopnWidth
+ // ordered bytes: lopnColor
+}
+
+
+/**
+ \brief Convert a pointer to a U_LOGPALETTE object.
+ \param lp Pointer to a U_LOGPALETTE object.
+*/
+void logpalette_swap(
+ PU_LOGPALETTE lp
+ ){
+ U_swap2(lp,2); // palVersion palNumEntries
+ // ordered bytes: palPalEntry[]
+}
+
+/**
+ \brief Convert a U_RGNDATAHEADER object.
+ \param rdh U_RGNDATAHEADER object
+*/
+void rgndataheader_swap(
+ PU_RGNDATAHEADER rdh
+ ){
+ U_swap4(rdh,4); // dwSize iType nCount nRgnSize
+ rectl_swap(&(rdh->rclBounds),1); // rclBounds
+}
+
+/**
+ \return 1 on success, 0 on failure
+ \brief Convert a pointer to a U_RGNDATA object.
+ \param rd pointer to a U_RGNDATA object.
+ \param cbRgnData size of the U_RGNDATA object.
+*/
+int rgndata_swap(
+ PU_RGNDATA rd,
+ int cbRgnData,
+ int torev
+ ){
+ int count = 0;
+ if(torev){
+ count = rd->rdh.nCount;
+ }
+ rgndataheader_swap(&(rd->rdh));
+ if(!torev){
+ count = rd->rdh.nCount;
+ }
+ if(4*count + (int)sizeof(U_RGNDATAHEADER) > cbRgnData)return(0);
+ U_swap4(rd->Buffer,4*count);
+ return(1);
+}
+
+/**
+ \brief Convert a U_COLORADJUSTMENT object.
+ \param ca U_COLORADJUSTMENT object.
+*/
+void coloradjustment_swap(
+ PU_COLORADJUSTMENT ca
+ ){
+ U_swap2(ca,12); // caSize caFlags caIlluminantIndex caRedGamma caGreenGamma caBlueGamma caReferenceBlack caReferenceWhite caContrast caBrightness caColorfulness caRedGreenTint
+}
+
+/**
+ \brief Convert a pointer to a U_PIXELFORMATDESCRIPTOR object.
+ \param pfd pointer to a U_PIXELFORMATDESCRIPTOR object.
+*/
+void pixelformatdescriptor_swap(
+ PU_PIXELFORMATDESCRIPTOR pfd
+ ){
+ U_swap2(pfd,2); // nSize nVersion
+ U_swap4(&(pfd->dwFlags),1); // dwFlags
+ // ordered bytes: iPixelType cColorBits cRedBits cRedShift cGreenBits cGreenShift cBlueBits cBlueShift cAlphaBits cAlphaShift cAccumBits cAccumRedBits cAccumGreenBits cAccumBlueBits cAccumAlphaBits cDepthBits cStencilBits cAuxBuffers iLayerType bReserved
+ U_swap4(&(pfd->dwLayerMask),3); // dwLayerMask dwVisibleMask dwDamageMask
+}
+
+/**
+ \brief Convert a Pointer to a U_EMRTEXT record
+ \param pemt Pointer to a U_EMRTEXT record
+ \param record Pointer to the start of the record which contains this U_EMRTEXT
+ \param blimit one byte past the end of the record.
+ \param torev 1 for native to reversed, 0 for reversed to native
+*/
+int emrtext_swap(
+ PU_EMRTEXT pemt,
+ char *record,
+ const char *blimit,
+ int torev
+ ){
+ int off;
+ uint32_t count=0;
+ uint32_t offDx=0;
+ uint32_t fOptions=0;
+ pointl_swap(&(pemt->ptlReference),1); // ptlReference
+ if(torev){
+ count = pemt->nChars;
+ fOptions = pemt->fOptions;
+ }
+ U_swap4(&(pemt->nChars),3); // nChars offString fOptions
+ if(!torev){
+ count = pemt->nChars;
+ fOptions = pemt->fOptions;
+ }
+ off = sizeof(U_EMRTEXT);
+ if(!(fOptions & U_ETO_NO_RECT)){
+ if(IS_MEM_UNSAFE(pemt, sizeof(U_RECTL), blimit))return(0);
+ rectl_swap((PU_RECTL)((char *)pemt + off),1); // optional rectangle
+ off+=sizeof(U_RECTL);
+ }
+ if(torev){
+ offDx = *(uint32_t *)((char *)pemt +off);
+ }
+ // ordered bytes OR UTF16-LE: the string at offString
+ if(IS_MEM_UNSAFE(pemt, off + 4, blimit))return(0);
+ U_swap4(((char *)pemt+off),1); // offDx
+ if(!torev){
+ offDx = *(uint32_t *)((char *)pemt +off);
+ }
+ if(IS_MEM_UNSAFE(record, count*4, blimit))return(0);
+ U_swap4((record + offDx),count); // Dx[], offset with respect to the Record, NOT the object
+ return(1);
+}
+
+
+
+/* **********************************************************************************************
+These functions contain shared code used by various U_EMR*_swap functions. These should NEVER be called
+by end user code and to further that end prototypes are NOT provided and they are hidden from Doxygen.
+
+
+ These all have this form:
+
+ void core1_swap(char *record, int torev){
+
+ but some do not actually use torev.
+
+
+
+*********************************************************************************************** */
+
+// all core*_swap call this, U_EMRSETMARGN_swap and some others all it directly
+// numbered as core5 to be consistent with uemf.c, but must appear before the others as there is no prototype
+int core5_swap(char *record, int torev){
+ UNUSED_PARAMETER(torev);
+ if(!record)return(0);
+ PU_EMR pEmr = (PU_EMR)(record);
+ U_swap4(pEmr,2); // iType nSize
+ return(1);
+}
+
+// Functions with the same form starting with U_EMRPOLYBEZIER_swap
+int core1_swap(char *record, int torev){
+ int count=0;
+ const char *blimit = NULL;
+ PU_EMRPOLYLINETO pEmr = (PU_EMRPOLYLINETO) (record);
+ if(torev){
+ count = pEmr->cptl;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(!core5_swap(record, torev))return(0);
+ rectl_swap(&(pEmr->rclBounds),1 ); // rclBounds
+ U_swap4(&(pEmr->cptl),1); // cptl
+ if(!torev){
+ count = pEmr->cptl;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(IS_MEM_UNSAFE((pEmr->aptl), count*sizeof(U_POINTL), blimit))return(0);
+ pointl_swap((pEmr->aptl),count); // aptl[]
+ return(1);
+}
+
+// Functions with the same form starting with U_EMRPOLYPOLYLINE_swap
+int core2_swap(char *record, int torev){
+ int count=0;
+ int nPolys=0;
+ const char *blimit = NULL;
+ PU_EMRPOLYPOLYLINE pEmr = (PU_EMRPOLYPOLYLINE) (record);
+ if(torev){
+ count = pEmr->cptl;
+ nPolys = pEmr->nPolys;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(!core5_swap(record, torev))return(0);
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ U_swap4(&(pEmr->nPolys),2); // nPolys cptl
+ if(!torev){
+ count = pEmr->cptl;
+ nPolys = pEmr->nPolys;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(IS_MEM_UNSAFE((pEmr->aPolyCounts), nPolys*4, blimit))return(0);
+ U_swap4(pEmr->aPolyCounts,nPolys); // aPolyCounts[]
+ record += sizeof(U_EMRPOLYPOLYLINE) - 4 + sizeof(uint32_t)* nPolys;
+ if(IS_MEM_UNSAFE(record, count*sizeof(U_POINTL), blimit))return(0);
+ pointl_swap((PU_POINT)(record), count); // paptl[]
+ return(1);
+}
+
+
+// Functions with the same form starting with U_EMRSETMAPMODE_swap
+int core3_swap(char *record, int torev){
+ PU_EMRSETMAPMODE pEmr = (PU_EMRSETMAPMODE)(record);
+ if(!core5_swap(record, torev))return(0);
+ U_swap4(&(pEmr->iMode),1); // iMode
+ return(1);
+}
+
+// Functions taking a single U_RECT or U_RECTL, starting with U_EMRELLIPSE_swap, also U_EMRFILLPATH_swap,
+int core4_swap(char *record, int torev){
+ PU_EMRELLIPSE pEmr = (PU_EMRELLIPSE)( record);
+ if(!core5_swap(record, torev))return(0);
+ rectl_swap(&(pEmr->rclBox),1); // rclBox
+ return(1);
+}
+
+// Functions with the same form starting with U_EMRPOLYBEZIER16_swap
+int core6_swap(char *record, int torev){
+ int count=0;
+ const char *blimit = NULL;
+ PU_EMRPOLYBEZIER16 pEmr = (PU_EMRPOLYBEZIER16) (record);
+ if(torev){
+ count = pEmr->cpts;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(!core5_swap(record, torev))return(0);
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ U_swap4(&(pEmr->cpts),1); // cpts
+ if(!torev){
+ count = pEmr->cpts;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(IS_MEM_UNSAFE((pEmr->apts), count*sizeof(U_POINT16), blimit))return(0);
+ point16_swap((pEmr->apts),count); // apts[]
+ return(1);
+}
+
+
+// Records with the same form starting with U_EMRSETWINDOWEXTEX_swap, that is, all with two uint32_t values after the emr
+int core7_swap(char *record, int torev){
+ PU_EMRGENERICPAIR pEmr = (PU_EMRGENERICPAIR) (record);
+ if(!core5_swap(record, torev))return(0);
+ U_swap4(&(pEmr->pair),2);
+ return(1);
+}
+
+// For U_EMREXTTEXTOUTA and U_EMREXTTEXTOUTW, type=0 for the first one
+int core8_swap(char *record, int torev){
+ const char *blimit = NULL;
+ PU_EMREXTTEXTOUTA pEmr = (PU_EMREXTTEXTOUTA) (record);
+ if(torev){
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(!core5_swap(record, torev))return(0);
+ U_swap4(&(pEmr->iGraphicsMode),1); // iGraphicsMode
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ U_swap4(&(pEmr->exScale),2); // exScale eyScale
+ if(!torev){
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(!emrtext_swap(&(pEmr->emrtext),record,blimit,torev))return(0);
+ return(1);
+}
+
+// Functions that take a rect and a pair of points, starting with U_EMRARC_swap
+int core9_swap(char *record, int torev){
+ PU_EMRARC pEmr = (PU_EMRARC) (record);
+ if(!core5_swap(record, torev))return(0);
+ rectl_swap(&(pEmr->rclBox),1); // rclBox
+ U_swap4(&(pEmr->ptlStart),4); // ptlStart ptlEnd
+ return(1);
+}
+
+// Functions with the same form starting with U_EMRPOLYPOLYLINE16_swap
+int core10_swap(char *record, int torev){
+ int count=0;
+ int nPolys=0;
+ const char *blimit = NULL;
+ PU_EMRPOLYPOLYLINE16 pEmr = (PU_EMRPOLYPOLYLINE16) (record);
+ if(torev){
+ count = pEmr->cpts;
+ nPolys = pEmr->nPolys;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(!core5_swap(record, torev))return(0);
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ U_swap4(&(pEmr->nPolys),2); // nPolys cpts
+ if(!torev){
+ count = pEmr->cpts;
+ nPolys = pEmr->nPolys;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(IS_MEM_UNSAFE((pEmr->aPolyCounts), nPolys*4, blimit))return(0);
+ U_swap4(pEmr->aPolyCounts,nPolys); // aPolyCounts[]
+ record += sizeof(U_EMRPOLYPOLYLINE16) - 4 + sizeof(uint32_t)* nPolys;
+ if(IS_MEM_UNSAFE(record, count*sizeof(U_POINT16), blimit))return(0);
+ point16_swap((PU_POINT16)(record), count); // apts[]
+ return(1);
+}
+
+// Functions with the same form starting with U_EMRINVERTRGN_swap and U_EMRPAINTRGN_swap,
+int core11_swap(char *record, int torev){
+ int cbRgnData=0;
+ const char *blimit = NULL;
+ PU_EMRINVERTRGN pEmr = (PU_EMRINVERTRGN)(record);
+ if(torev){
+ cbRgnData= pEmr->cbRgnData;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(!core5_swap(record, torev))return(0);
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ U_swap4(&(pEmr->cbRgnData),1); // cbRgnData
+ if(!torev){
+ cbRgnData= pEmr->cbRgnData;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0);
+ return(rgndata_swap(pEmr->RgnData, cbRgnData, torev));
+}
+
+
+// common code for U_EMRCREATEMONOBRUSH_swap and U_EMRCREATEDIBPATTERNBRUSHPT_swap,
+int core12_swap(char *record, int torev){
+ const char *blimit = NULL;
+ U_OFFBMI offBmi = 0;
+ U_CBBMI cbBmi = 0;
+ U_OFFBITS offBits = 0;
+ U_CBBITS cbBits = 0;
+ uint32_t iUsage = 0;
+ PU_EMRCREATEMONOBRUSH pEmr = (PU_EMRCREATEMONOBRUSH) (record);
+ if(torev){
+ offBmi = pEmr->offBmi;
+ cbBmi = pEmr->cbBmi;
+ offBits = pEmr->offBits;
+ cbBits = pEmr->cbBits;
+ iUsage = pEmr->iUsage;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsage, offBmi, cbBmi, offBits, cbBits, blimit, torev))return(0);
+ }
+ if(!core5_swap(record, torev))return(0);
+ U_swap4(&(pEmr->ihBrush),6); // ihBrush iUsage offBmi cbBmi offBits cbBits
+ if(!torev){
+ offBmi = pEmr->offBmi;
+ cbBmi = pEmr->cbBmi;
+ offBits = pEmr->offBits;
+ cbBits = pEmr->cbBits;
+ iUsage = pEmr->iUsage;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsage, offBmi, cbBmi, offBits, cbBits, blimit, torev))return(0);
+ }
+ // ordered bytes: bitmap (including 16 bit 5bit/channel color mode, which is done bytewise).
+ return(1);
+}
+
+// common code for U_EMRALPHABLEND_swap and U_EMRTRANSPARENTBLT_swap,
+int core13_swap(char *record, int torev){
+ const char *blimit = NULL;
+ U_OFFBMISRC offBmiSrc = 0;
+ U_CBBMISRC cbBmiSrc = 0;
+ U_OFFBITSSRC offBitsSrc = 0;
+ U_CBBITSSRC cbBitsSrc = 0;
+ uint32_t iUsageSrc = 0;
+ PU_EMRALPHABLEND pEmr = (PU_EMRALPHABLEND) (record);
+ if(torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ }
+ if(!core5_swap(record, torev))return(0);
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ pointl_swap(&(pEmr->Dest),2); // Dest cDest
+ pointl_swap(&(pEmr->Dest),2); // Dest cDest
+ // ordered bytes: Blend
+ pointl_swap(&(pEmr->Src),2); // Src
+ xform_swap( &(pEmr->xformSrc)); // xformSrc
+ // ordered bytes: crBkColorSrc
+ U_swap4(&(pEmr->iUsageSrc),5); // iUsageSrc offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc
+ if(!torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ }
+ // ordered bytes: bitmap (including 16 bit 5bit/channel color mode, which is done bytewise).
+ return(1);
+}
+
+/* **********************************************************************************************
+These are the core EMR_swap functions, each converts a particular type of record.
+All operate in place on the chunk of memory holding that record.
+Some of these have offsets or counts which, if corrupt or evil would result in access outside
+ the record. These cases return a status value of 0 if that happens, 1 on success. Other
+ records which do not have these issues do not return a status value.
+They are listed in order by the corresponding U_EMR_* index number.
+*********************************************************************************************** */
+
+/**
+ All of the record level (hidden) functions have this form:
+ \brief Convert a pointer to a U_EMR_whatever record which has not been implemented.
+ \param record pointer to a buffer holding the EMR record
+ \param torev 1 for native to reversed, 0 for reversed to native
+*/
+int U_EMRNOTIMPLEMENTED_swap(char *record, int torev){
+ fprintf(stderr,"EMF WARNING: could not swap data bytes on record because that type has not been implemented!\n");
+ return(core5_swap(record, torev));
+}
+
+// U_EMRHEADER 1
+int U_EMRHEADER_swap(char *record, int torev){
+ int nDesc,offDesc,nSize,cbPix,offPix;
+ nDesc = offDesc = nSize = cbPix = offPix = 0;
+ PU_EMRHEADER pEmr = (PU_EMRHEADER)(record);
+ if(torev){
+ nSize = pEmr->emr.nSize;
+ nDesc = pEmr->nDescription;
+ offDesc = pEmr->offDescription;
+ }
+ if(!core5_swap(record, torev))return(0);
+ rectl_swap(&(pEmr->rclBounds),2); // rclBounds rclFrame
+ U_swap4(&(pEmr->dSignature), 4); // dSignature nVersion nBytes nRecords
+ U_swap2(&(pEmr->nHandles), 2); // nHandlessReserved
+ U_swap4(&(pEmr->nDescription), 3); // nDescription offDescription nPalEntries
+ if(!torev){
+ nSize = pEmr->emr.nSize;
+ nDesc = pEmr->nDescription;
+ offDesc = pEmr->offDescription;
+ }
+ // UTF16-LE Description
+ sizel_swap(&(pEmr->szlDevice), 2); // szlDevice szlMillimeters
+ if((nDesc && (offDesc >= 100)) ||
+ (!offDesc && nSize >= 100)
+ ){
+ if(torev){
+ cbPix = pEmr->cbPixelFormat;
+ offPix = pEmr->offPixelFormat;
+ }
+ U_swap4(&(pEmr->cbPixelFormat), 2); // cbPixelFormat offPixelFormat
+ U_swap4(&(pEmr->bOpenGL), 1); // bOpenGL
+ if(!torev){
+ cbPix = pEmr->cbPixelFormat;
+ offPix = pEmr->offPixelFormat;
+ }
+ if(cbPix)pixelformatdescriptor_swap( (PU_PIXELFORMATDESCRIPTOR) (record + pEmr->offPixelFormat));
+ if((nDesc && (offDesc >= 108)) ||
+ (cbPix && (offPix >=108)) ||
+ (!offDesc && !cbPix && nSize >= 108)
+ ){
+ sizel_swap(&(pEmr->szlMicrometers), 1); // szlMicrometers
+ }
+ }
+ return(1);
+}
+
+// U_EMRPOLYBEZIER 2
+int U_EMRPOLYBEZIER_swap(char *record, int torev){
+ return(core1_swap(record, torev));
+}
+
+// U_EMRPOLYGON 3
+int U_EMRPOLYGON_swap(char *record, int torev){
+ return(core1_swap(record, torev));
+}
+
+
+// U_EMRPOLYLINE 4
+int U_EMRPOLYLINE_swap(char *record, int torev){
+ return(core1_swap(record, torev));
+}
+
+// U_EMRPOLYBEZIERTO 5
+int U_EMRPOLYBEZIERTO_swap(char *record, int torev){
+ return(core1_swap(record, torev));
+}
+
+// U_EMRPOLYLINETO 6
+int U_EMRPOLYLINETO_swap(char *record, int torev){
+ return(core1_swap(record, torev));
+}
+
+// U_EMRPOLYPOLYLINE 7
+int U_EMRPOLYPOLYLINE_swap(char *record, int torev){
+ return(core2_swap(record, torev));
+}
+
+// U_EMRPOLYPOLYGON 8
+int U_EMRPOLYPOLYGON_swap(char *record, int torev){
+ return(core2_swap(record, torev));
+}
+
+// U_EMRSETWINDOWEXTEX 9
+int U_EMRSETWINDOWEXTEX_swap(char *record, int torev){
+ return(core7_swap(record, torev));
+}
+
+// U_EMRSETWINDOWORGEX 10
+int U_EMRSETWINDOWORGEX_swap(char *record, int torev){
+ return(core7_swap(record, torev));
+}
+
+// U_EMRSETVIEWPORTEXTEX 11
+int U_EMRSETVIEWPORTEXTEX_swap(char *record, int torev){
+ return(core7_swap(record, torev));
+}
+
+// U_EMRSETVIEWPORTORGEX 12
+int U_EMRSETVIEWPORTORGEX_swap(char *record, int torev){
+ return(core7_swap(record, torev));
+}
+
+// U_EMRSETBRUSHORGEX 13
+int U_EMRSETBRUSHORGEX_swap(char *record, int torev){
+ return(core7_swap(record, torev));
+}
+
+// U_EMREOF 14
+int U_EMREOF_swap(char *record, int torev){
+ int off=0;
+ int cbPalEntries=0;
+ const char *blimit = NULL;
+ PU_EMREOF pEmr = (PU_EMREOF)(record);
+ if(torev){
+ blimit = record + pEmr->emr.nSize;
+ cbPalEntries = pEmr->cbPalEntries;
+ }
+ if(!core5_swap(record, torev))return(0);
+ U_swap4(&(pEmr->cbPalEntries),2); // cbPalEntries offPalEntries
+ if(!torev){
+ blimit = record + pEmr->emr.nSize;
+ cbPalEntries = pEmr->cbPalEntries;
+ }
+ if(cbPalEntries){
+ if(IS_MEM_UNSAFE(record, pEmr->offPalEntries + 2*2, blimit))return(0); // 2 16 bit values in U_LOGPALLETE
+ logpalette_swap( (PU_LOGPALETTE)(record + pEmr->offPalEntries));
+ // U_LOGPLTNTRY values in pallette are ordered data
+ }
+ off = sizeof(U_EMREOF) + 4 * cbPalEntries;
+ if(IS_MEM_UNSAFE(record, off + 4, blimit))return(0);
+ U_swap4(record + off,1); // nSizeLast
+ return(1);
+}
+
+
+// U_EMRSETPIXELV 15
+int U_EMRSETPIXELV_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
+ PU_EMRSETPIXELV pEmr = (PU_EMRSETPIXELV)(record);
+ pointl_swap(&(pEmr->ptlPixel),1); // ptlPixel
+ // ordered bytes: crColor
+ return(1);
+}
+
+
+// U_EMRSETMAPPERFLAGS 16
+int U_EMRSETMAPPERFLAGS_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
+ PU_EMRSETMAPPERFLAGS pEmr = (PU_EMRSETMAPPERFLAGS)(record);
+ U_swap4(&(pEmr->dwFlags),1); // dwFlags
+ return(1);
+}
+
+
+// U_EMRSETMAPMODE 17
+int U_EMRSETMAPMODE_swap(char *record, int torev){
+ return(core3_swap(record, torev));
+}
+
+// U_EMRSETBKMODE 18
+int U_EMRSETBKMODE_swap(char *record, int torev){
+ return(core3_swap(record, torev));
+}
+
+// U_EMRSETPOLYFILLMODE 19
+int U_EMRSETPOLYFILLMODE_swap(char *record, int torev){
+ return(core3_swap(record, torev));
+}
+
+// U_EMRSETROP2 20
+int U_EMRSETROP2_swap(char *record, int torev){
+ return(core3_swap(record, torev));
+}
+
+// U_EMRSETSTRETCHBLTMODE 21
+int U_EMRSETSTRETCHBLTMODE_swap(char *record, int torev){
+ return(core3_swap(record, torev));
+}
+
+// U_EMRSETTEXTALIGN 22
+int U_EMRSETTEXTALIGN_swap(char *record, int torev){
+ return(core3_swap(record, torev));
+}
+
+// U_EMRSETCOLORADJUSTMENT 23
+int U_EMRSETCOLORADJUSTMENT_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
+ PU_EMRSETCOLORADJUSTMENT pEmr = (PU_EMRSETCOLORADJUSTMENT)(record);
+ coloradjustment_swap(&(pEmr->ColorAdjustment));
+ return(1);
+}
+
+// U_EMRSETTEXTCOLOR 24
+int U_EMRSETTEXTCOLOR_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
+ // ordered bytes: crColor
+ return(1);
+}
+
+// U_EMRSETBKCOLOR 25
+int U_EMRSETBKCOLOR_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
+ // ordered bytes: crColor
+ return(1);
+}
+
+// U_EMROFFSETCLIPRGN 26
+int U_EMROFFSETCLIPRGN_swap(char *record, int torev){
+ return(core7_swap(record, torev));
+}
+
+// U_EMRMOVETOEX 27
+int U_EMRMOVETOEX_swap(char *record, int torev){
+ return(core7_swap(record, torev));
+}
+
+// U_EMRSETMETARGN 28
+int U_EMRSETMETARGN_swap(char *record, int torev){
+ return(core5_swap(record, torev));
+}
+
+// U_EMREXCLUDECLIPRECT 29
+int U_EMREXCLUDECLIPRECT_swap(char *record, int torev){
+ return(core4_swap(record, torev));
+}
+
+// U_EMRINTERSECTCLIPRECT 30
+int U_EMRINTERSECTCLIPRECT_swap(char *record, int torev){
+ return(core4_swap(record, torev));
+}
+
+// U_EMRSCALEVIEWPORTEXTEX 31
+int U_EMRSCALEVIEWPORTEXTEX_swap(char *record, int torev){
+ return(core4_swap(record, torev));
+}
+
+// U_EMRSCALEWINDOWEXTEX 32
+int U_EMRSCALEWINDOWEXTEX_swap(char *record, int torev){
+ return(core4_swap(record, torev));
+}
+
+// U_EMRSAVEDC 33
+int U_EMRSAVEDC_swap(char *record, int torev){
+ return(core5_swap(record, torev));
+}
+
+// U_EMRRESTOREDC 34
+int U_EMRRESTOREDC_swap(char *record, int torev){
+ return(core3_swap(record, torev));
+}
+
+// U_EMRSETWORLDTRANSFORM 35
+int U_EMRSETWORLDTRANSFORM_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
+ PU_EMRSETWORLDTRANSFORM pEmr = (PU_EMRSETWORLDTRANSFORM)(record);
+ xform_swap(&(pEmr->xform));
+ return(1);
+}
+
+// U_EMRMODIFYWORLDTRANSFORM 36
+int U_EMRMODIFYWORLDTRANSFORM_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
+ PU_EMRMODIFYWORLDTRANSFORM pEmr = (PU_EMRMODIFYWORLDTRANSFORM)(record);
+ xform_swap(&(pEmr->xform)); // xform
+ U_swap4(&(pEmr->iMode),1); // iMode
+ return(1);
+}
+
+// U_EMRSELECTOBJECT 37
+int U_EMRSELECTOBJECT_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
+ PU_EMRSELECTOBJECT pEmr = (PU_EMRSELECTOBJECT)(record);
+ U_swap4(&(pEmr->ihObject),1); // ihObject
+ return(1);
+}
+
+// U_EMRCREATEPEN 38
+int U_EMRCREATEPEN_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
+ PU_EMRCREATEPEN pEmr = (PU_EMRCREATEPEN)(record);
+ U_swap4(&(pEmr->ihPen),1); // ihPen
+ logpen_swap(&(pEmr->lopn)); // lopn
+ return(1);
+}
+
+// U_EMRCREATEBRUSHINDIRECT 39
+int U_EMRCREATEBRUSHINDIRECT_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
+ PU_EMRCREATEBRUSHINDIRECT pEmr = (PU_EMRCREATEBRUSHINDIRECT)(record);
+ U_swap4(&(pEmr->ihBrush),1); // ihBrush
+ logbrush_swap(&(pEmr->lb)); // lb
+ return(1);
+}
+
+// U_EMRDELETEOBJECT 40
+int U_EMRDELETEOBJECT_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
+ PU_EMRDELETEOBJECT pEmr = (PU_EMRDELETEOBJECT)(record);
+ U_swap4(&(pEmr->ihObject),1); // ihObject
+ return(1);
+}
+
+// U_EMRANGLEARC 41
+int U_EMRANGLEARC_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
+ PU_EMRANGLEARC pEmr = (PU_EMRANGLEARC)(record);
+ pointl_swap(&(pEmr->ptlCenter),1); // ptlCenter
+ U_swap4(&(pEmr->nRadius),3); // nRadius eStartAngle eSweepAngle
+ return(1);
+}
+
+// U_EMRELLIPSE 42
+int U_EMRELLIPSE_swap(char *record, int torev){
+ return(core4_swap(record, torev));
+}
+
+// U_EMRRECTANGLE 43
+int U_EMRRECTANGLE_swap(char *record, int torev){
+ return(core4_swap(record, torev));
+}
+
+// U_EMRROUNDRECT 44
+int U_EMRROUNDRECT_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
+ PU_EMRROUNDRECT pEmr = (PU_EMRROUNDRECT)(record);
+ rectl_swap(&(pEmr->rclBox),1); // rclBox
+ sizel_swap(&(pEmr->szlCorner), 1); // szlCorner
+ return(1);
+}
+
+// U_EMRARC 45
+int U_EMRARC_swap(char *record, int torev){
+ return(core9_swap(record, torev));
+}
+
+// U_EMRCHORD 46
+int U_EMRCHORD_swap(char *record, int torev){
+ return(core9_swap(record, torev));
+}
+
+// U_EMRPIE 47
+int U_EMRPIE_swap(char *record, int torev){
+ return(core9_swap(record, torev));
+}
+
+// U_EMRSELECTPALETTE 48
+int U_EMRSELECTPALETTE_swap(char *record, int torev){
+ return(core3_swap(record, torev));
+}
+
+// U_EMRCREATEPALETTE 49
+int U_EMRCREATEPALETTE_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
+ PU_EMRCREATEPALETTE pEmr = (PU_EMRCREATEPALETTE)(record);
+ U_swap4(&(pEmr->ihPal),1); // ihPal
+ logpalette_swap( (PU_LOGPALETTE)&(pEmr->lgpl) ); // lgpl
+ return(1);
+}
+
+// U_EMRSETPALETTEENTRIES 50
+int U_EMRSETPALETTEENTRIES_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
+ PU_EMRSETPALETTEENTRIES pEmr = (PU_EMRSETPALETTEENTRIES)(record);
+ U_swap4(&(pEmr->ihPal),3); // ihPal iStart cEntries
+ // ordered bytes: aPalEntries[]
+ return(1);
+}
+
+// U_EMRRESIZEPALETTE 51
+int U_EMRRESIZEPALETTE_swap(char *record, int torev){
+ return(core7_swap(record, torev));
+}
+
+// U_EMRREALIZEPALETTE 52
+int U_EMRREALIZEPALETTE_swap(char *record, int torev){
+ return(core5_swap(record, torev));
+}
+
+// U_EMREXTFLOODFILL 53
+int U_EMREXTFLOODFILL_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
+ PU_EMREXTFLOODFILL pEmr = (PU_EMREXTFLOODFILL)(record);
+ pointl_swap(&(pEmr->ptlStart),1); // ptlStart
+ // ordered bytes: crColor
+ U_swap4(&(pEmr->iMode),1); // iMode
+ return(1);
+}
+
+// U_EMRLINETO 54
+int U_EMRLINETO_swap(char *record, int torev){
+ return(core7_swap(record, torev));
+}
+
+// U_EMRARCTO 55
+int U_EMRARCTO_swap(char *record, int torev){
+ return(core9_swap(record, torev));
+}
+
+// U_EMRPOLYDRAW 56
+int U_EMRPOLYDRAW_swap(char *record, int torev){
+ int count=0;
+ const char *blimit = NULL;
+ PU_EMRPOLYDRAW pEmr = (PU_EMRPOLYDRAW)(record);
+
+ if(torev){
+ count = pEmr->cptl;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(!core5_swap(record, torev))return(0);
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ U_swap4(&(pEmr->cptl),1); // cptl
+ if(!torev){
+ count = pEmr->cptl;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(IS_MEM_UNSAFE((pEmr->aptl), count*sizeof(U_POINTL), blimit))return(0);
+ pointl_swap(pEmr->aptl,count); // aptl[]
+ // single byte data abTypes
+ return(1);
+}
+
+// U_EMRSETARCDIRECTION 57
+int U_EMRSETARCDIRECTION_swap(char *record, int torev){
+ return(core3_swap(record, torev));
+}
+
+// U_EMRSETMITERLIMIT 58
+int U_EMRSETMITERLIMIT_swap(char *record, int torev){
+ return(core3_swap(record, torev));
+}
+
+
+// U_EMRBEGINPATH 59
+int U_EMRBEGINPATH_swap(char *record, int torev){
+ return(core5_swap(record, torev));
+}
+
+// U_EMRENDPATH 60
+int U_EMRENDPATH_swap(char *record, int torev){
+ return(core5_swap(record, torev));
+}
+
+// U_EMRCLOSEFIGURE 61
+int U_EMRCLOSEFIGURE_swap(char *record, int torev){
+ return(core5_swap(record, torev));
+}
+
+// U_EMRFILLPATH 62
+int U_EMRFILLPATH_swap(char *record, int torev){
+ return(core4_swap(record, torev));
+}
+
+// U_EMRSTROKEANDFILLPATH 63
+int U_EMRSTROKEANDFILLPATH_swap(char *record, int torev){
+ return(core4_swap(record, torev));
+}
+
+// U_EMRSTROKEPATH 64
+int U_EMRSTROKEPATH_swap(char *record, int torev){
+ return(core4_swap(record, torev));
+}
+
+// U_EMRFLATTENPATH 65
+int U_EMRFLATTENPATH_swap(char *record, int torev){
+ return(core5_swap(record, torev));
+}
+
+// U_EMRWIDENPATH 66
+int U_EMRWIDENPATH_swap(char *record, int torev){
+ return(core5_swap(record, torev));
+}
+
+// U_EMRSELECTCLIPPATH 67
+int U_EMRSELECTCLIPPATH_swap(char *record, int torev){
+ return(core3_swap(record, torev));
+}
+
+// U_EMRABORTPATH 68
+int U_EMRABORTPATH_swap(char *record, int torev){
+ return(core5_swap(record, torev));
+}
+
+// U_EMRUNDEF69 69
+#define U_EMRUNDEF69_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
+
+// U_EMRCOMMENT 70 Comment (any binary data, interpretation is program specific)
+int U_EMRCOMMENT_swap(char *record, int torev){
+ int cbData = 0;
+ const char *blimit = NULL;
+ PU_EMRCOMMENT pEmr = (PU_EMRCOMMENT)(record);
+ if(torev){
+ cbData = pEmr->cbData;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(!core5_swap(record, torev))return(0);
+ U_swap4(&(pEmr->cbData),1); // cbData
+ if(!torev){
+ cbData = pEmr->cbData;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(IS_MEM_UNSAFE(record, cbData + sizeof(U_SIZE_EMRCOMMENT), blimit))return(0);
+ // program specific data, presumably byte ordered, otherwise, not portable
+ return(1);
+}
+
+// U_EMRFILLRGN 71
+int U_EMRFILLRGN_swap(char *record, int torev){
+ int cbRgnData=0;
+ const char *blimit = NULL;
+ PU_EMRFILLRGN pEmr = (PU_EMRFILLRGN)(record);
+ if(torev){
+ cbRgnData= pEmr->cbRgnData;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(!core5_swap(record, torev))return(0);
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ U_swap4(&(pEmr->cbRgnData),2); // cbRgnData ihBrush
+ if(!torev){
+ cbRgnData= pEmr->cbRgnData;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0);
+ return(rgndata_swap(pEmr->RgnData, cbRgnData, torev));
+}
+
+// U_EMRFRAMERGN 72
+int U_EMRFRAMERGN_swap(char *record, int torev){
+ int cbRgnData=0;
+ const char *blimit = NULL;
+ PU_EMRFRAMERGN pEmr = (PU_EMRFRAMERGN)(record);
+ if(torev){
+ cbRgnData= pEmr->cbRgnData;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(!core5_swap(record, torev))return(0);
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ U_swap4(&(pEmr->cbRgnData),2); // cbRgnData ihBrush
+ sizel_swap(&(pEmr->szlStroke), 1); // szlStroke
+ if(!torev){
+ cbRgnData= pEmr->cbRgnData;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0);
+ return(rgndata_swap(pEmr->RgnData, cbRgnData, torev));
+}
+
+// U_EMRINVERTRGN 73
+int U_EMRINVERTRGN_swap(char *record, int torev){
+ return(core11_swap(record, torev));
+}
+
+// U_EMRPAINTRGN 74
+int U_EMRPAINTRGN_swap(char *record, int torev){
+ return(core11_swap(record, torev));
+}
+
+// U_EMREXTSELECTCLIPRGN 75
+int U_EMREXTSELECTCLIPRGN_swap(char *record, int torev){
+ int cbRgnData=0;
+ const char *blimit = NULL;
+ PU_EMREXTSELECTCLIPRGN pEmr = (PU_EMREXTSELECTCLIPRGN)(record);
+ if(torev){
+ cbRgnData= pEmr->cbRgnData;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(!core5_swap(record, torev))return(0);
+ U_swap4(&(pEmr->cbRgnData),2); // cbRgnData iMode
+ if(!torev){
+ cbRgnData= pEmr->cbRgnData;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0);
+ return(rgndata_swap(pEmr->RgnData, cbRgnData, torev));
+}
+
+// U_EMRBITBLT 76
+int U_EMRBITBLT_swap(char *record, int torev){
+ const char *blimit = NULL;
+ U_OFFBMISRC offBmiSrc = 0;
+ U_CBBMISRC cbBmiSrc = 0;
+ U_OFFBITSSRC offBitsSrc = 0;
+ U_CBBITSSRC cbBitsSrc = 0;
+ uint32_t iUsageSrc = 0;
+ PU_EMRBITBLT pEmr = (PU_EMRBITBLT) (record);
+ if(torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ }
+ if(!core5_swap(record, torev))return(0);
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ pointl_swap(&(pEmr->Dest),2); // Dest cDest
+ U_swap4(&(pEmr->dwRop),1); // dwRop
+ pointl_swap(&(pEmr->Src),1); // Src
+ xform_swap(&(pEmr->xformSrc)); // xformSrc
+ // ordered bytes: crBkColorSrc
+ U_swap4(&(pEmr->iUsageSrc),5); // iUsageSrc offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc
+ if(!torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ }
+ // ordered bytes: bitmap (including 16 bit 5bit/channel color mode, which is done bytewise).
+ return(1);
+}
+
+// U_EMRSTRETCHBLT 77
+int U_EMRSTRETCHBLT_swap(char *record, int torev){
+ const char *blimit = NULL;
+ U_OFFBMISRC offBmiSrc = 0;
+ U_CBBMISRC cbBmiSrc = 0;
+ U_OFFBITSSRC offBitsSrc = 0;
+ U_CBBITSSRC cbBitsSrc = 0;
+ uint32_t iUsageSrc = 0;
+ PU_EMRSTRETCHBLT pEmr = (PU_EMRSTRETCHBLT) (record);
+ if(torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ }
+ if(!core5_swap(record, torev))return(0);
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ pointl_swap(&(pEmr->Dest),2); // Dest cDest
+ U_swap4(&(pEmr->dwRop),1); // dwRop
+ pointl_swap(&(pEmr->Src),1); // Src
+ xform_swap(&(pEmr->xformSrc)); // xformSrc
+ // ordered bytes: crBkColorSrc
+ U_swap4(&(pEmr->iUsageSrc),5); // iUsageSrc offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc
+ pointl_swap(&(pEmr->cSrc),1); // cSrc
+ if(!torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ }
+ // ordered bytes: bitmap (including 16 bit 5bit/channel color mode, which is done bytewise).
+ return(1);
+}
+
+// U_EMRMASKBLT 78
+int U_EMRMASKBLT_swap(char *record, int torev){
+ const char *blimit = NULL;
+ U_OFFBMISRC offBmiSrc = 0;
+ U_CBBMISRC cbBmiSrc = 0;
+ U_OFFBITSSRC offBitsSrc = 0;
+ U_CBBITSSRC cbBitsSrc = 0;
+ uint32_t iUsageSrc = 0;
+ U_OFFBMIMSK offBmiMask = 0;
+ U_CBBMIMSK cbBmiMask = 0;
+ U_OFFBITSMSK offBitsMask = 0;
+ U_CBBITSMSK cbBitsMask = 0;
+ uint32_t iUsageMask = 0;
+ PU_EMRMASKBLT pEmr = (PU_EMRMASKBLT) (record);
+ if(torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ offBmiMask = pEmr->offBmiMask;
+ cbBmiMask = pEmr->cbBmiMask;
+ offBitsMask = pEmr->offBitsMask;
+ cbBitsMask = pEmr->cbBitsMask;
+ iUsageMask = pEmr->iUsageMask;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ if(!DIB_swap(record, iUsageMask, offBmiMask, cbBmiMask, offBitsMask, cbBitsMask, blimit, torev))return(0);
+ }
+ if(!core5_swap(record, torev))return(0);
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ pointl_swap(&(pEmr->Dest),2); // Dest cDest
+ U_swap4(&(pEmr->dwRop),1); // dwRop
+ pointl_swap(&(pEmr->Src),1); // Src
+ xform_swap(&(pEmr->xformSrc)); // xformSrc
+ // ordered bytes: crBkColorSrc
+ U_swap4(&(pEmr->iUsageSrc),5); // iUsageSrc offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc
+ pointl_swap(&(pEmr->Mask),1); // Mask
+ U_swap4(&(pEmr->iUsageMask),5); // iUsageMask offBmiMask cbBmiMask offBitsMask cbBitsMask
+ if(!torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ offBmiMask = pEmr->offBmiMask;
+ cbBmiMask = pEmr->cbBmiMask;
+ offBitsMask = pEmr->offBitsMask;
+ cbBitsMask = pEmr->cbBitsMask;
+ iUsageMask = pEmr->iUsageMask;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ if(!DIB_swap(record, iUsageMask, offBmiMask, cbBmiMask, offBitsMask, cbBitsMask, blimit, torev))return(0);
+ }
+ return(1);
+}
+
+// U_EMRPLGBLT 79
+int U_EMRPLGBLT_swap(char *record, int torev){
+ const char *blimit = NULL;
+ U_OFFBMISRC offBmiSrc = 0;
+ U_CBBMISRC cbBmiSrc = 0;
+ U_OFFBITSSRC offBitsSrc = 0;
+ U_CBBITSSRC cbBitsSrc = 0;
+ uint32_t iUsageSrc = 0;
+ U_OFFBMIMSK offBmiMask = 0;
+ U_CBBMIMSK cbBmiMask = 0;
+ U_OFFBITSMSK offBitsMask = 0;
+ U_CBBITSMSK cbBitsMask = 0;
+ uint32_t iUsageMask = 0;
+ PU_EMRPLGBLT pEmr = (PU_EMRPLGBLT) (record);
+ if(torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ offBmiMask = pEmr->offBmiMask;
+ cbBmiMask = pEmr->cbBmiMask;
+ offBitsMask = pEmr->offBitsMask;
+ cbBitsMask = pEmr->cbBitsMask;
+ iUsageMask = pEmr->iUsageMask;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ if(!DIB_swap(record, iUsageMask, offBmiMask, cbBmiMask, offBitsMask, cbBitsMask, blimit, torev))return(0);
+ }
+ if(!core5_swap(record, torev))return(0);
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ pointl_swap(pEmr->aptlDst,3); // aptlDst[]
+ pointl_swap(&(pEmr->Src),2); // Src cSrc
+ xform_swap(&(pEmr->xformSrc)); // xformSrc
+ // ordered bytes: crBkColorSrc
+ U_swap4(&(pEmr->iUsageSrc),5); // iUsageSrc offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc
+ pointl_swap(&(pEmr->Mask),1); // Mask
+ U_swap4(&(pEmr->iUsageMask),5); // iUsageMask offBmiMask cbBmiMask offBitsMask cbBitsMask
+ if(!torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ offBmiMask = pEmr->offBmiMask;
+ cbBmiMask = pEmr->cbBmiMask;
+ offBitsMask = pEmr->offBitsMask;
+ cbBitsMask = pEmr->cbBitsMask;
+ iUsageMask = pEmr->iUsageMask;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ if(!DIB_swap(record, iUsageMask, offBmiMask, cbBmiMask, offBitsMask, cbBitsMask, blimit, torev))return(0);
+ }
+ return(1);
+}
+
+// U_EMRSETDIBITSTODEVICE 80
+int U_EMRSETDIBITSTODEVICE_swap(char *record, int torev){
+ const char *blimit = NULL;
+ U_OFFBMISRC offBmiSrc = 0;
+ U_CBBMISRC cbBmiSrc = 0;
+ U_OFFBITSSRC offBitsSrc = 0;
+ U_CBBITSSRC cbBitsSrc = 0;
+ uint32_t iUsageSrc = 0;
+ PU_EMRSETDIBITSTODEVICE pEmr = (PU_EMRSETDIBITSTODEVICE) (record);
+ if(torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ }
+ if(!core5_swap(record, torev))return(0);
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ pointl_swap(&(pEmr->Dest),1); // Dest
+ pointl_swap(&(pEmr->Src),2); // Src cSrc
+ U_swap4(&(pEmr->offBmiSrc),7); // offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc iUsageSrc iStartScan cScans
+ if(!torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ }
+ return(1);
+}
+
+// U_EMRSTRETCHDIBITS 81
+int U_EMRSTRETCHDIBITS_swap(char *record, int torev){
+ const char *blimit = NULL;
+ U_OFFBMISRC offBmiSrc = 0;
+ U_CBBMISRC cbBmiSrc = 0;
+ U_OFFBITSSRC offBitsSrc = 0;
+ U_CBBITSSRC cbBitsSrc = 0;
+ uint32_t iUsageSrc = 0;
+ PU_EMRSTRETCHDIBITS pEmr = (PU_EMRSTRETCHDIBITS) (record);
+ if(torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ }
+ if(!core5_swap(record, torev))return(0);
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ pointl_swap(&(pEmr->Dest),1); // Dest
+ pointl_swap(&(pEmr->Src),2); // Src cSrc
+ U_swap4(&(pEmr->offBmiSrc),6); // offBmiSrc cbBmiSrc offBitsSrc cbBitsSrc iUsageSrc dwRop
+ pointl_swap(&(pEmr->cDest),1); // cDest
+ if(!torev){
+ offBmiSrc = pEmr->offBmiSrc;
+ cbBmiSrc = pEmr->cbBmiSrc;
+ offBitsSrc = pEmr->offBitsSrc;
+ cbBitsSrc = pEmr->cbBitsSrc;
+ iUsageSrc = pEmr->iUsageSrc;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit, torev))return(0);
+ }
+ return(1);
+}
+
+// U_EMREXTCREATEFONTINDIRECTW 82
+int U_EMREXTCREATEFONTINDIRECTW_swap(char *record, int torev){
+ int nSize = 0;
+ PU_EMREXTCREATEFONTINDIRECTW pEmr = (PU_EMREXTCREATEFONTINDIRECTW) (record);
+ if(torev){
+ nSize = pEmr->emr.nSize;
+ }
+ if(!core5_swap(record, torev))return(0);
+ U_swap4(&(pEmr->ihFont),1); // ihFont
+ if(!torev){
+ nSize = pEmr->emr.nSize;
+ }
+ if(nSize == U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT_PANOSE){
+ logfont_panose_swap(&(pEmr->elfw));
+ }
+ else { // logfont or logfontExDv (which starts with logfont, which can be swapped, and the rest is already in byte order
+ logfont_swap( (PU_LOGFONT) &(pEmr->elfw));
+ }
+ return(1);
+}
+
+// U_EMREXTTEXTOUTA 83
+int U_EMREXTTEXTOUTA_swap(char *record, int torev){
+ return(core8_swap(record, torev));
+}
+
+// U_EMREXTTEXTOUTW 84
+int U_EMREXTTEXTOUTW_swap(char *record, int torev){
+ return(core8_swap(record, torev));
+}
+
+// U_EMRPOLYBEZIER16 85
+/**
+ \brief Convert a pointer to a U_EMR_POLYBEZIER16 record.
+ \param record pointer to a buffer holding the EMR record
+*/
+int U_EMRPOLYBEZIER16_swap(char *record, int torev){
+ return(core6_swap(record, torev));
+}
+
+// U_EMRPOLYGON16 86
+int U_EMRPOLYGON16_swap(char *record, int torev){
+ return(core6_swap(record, torev));
+}
+
+// U_EMRPOLYLINE16 87
+int U_EMRPOLYLINE16_swap(char *record, int torev){
+ return(core6_swap(record, torev));
+}
+
+// U_EMRPOLYBEZIERTO16 88
+int U_EMRPOLYBEZIERTO16_swap(char *record, int torev){
+ return(core6_swap(record, torev));
+}
+
+// U_EMRPOLYLINETO16 89
+/**
+ \brief Convert a pointer to a U_EMR_POLYLINETO16 record.
+ \param record pointer to a buffer holding the EMR record
+*/
+int U_EMRPOLYLINETO16_swap(char *record, int torev){
+ return(core6_swap(record, torev));
+}
+
+// U_EMRPOLYPOLYLINE16 90
+int U_EMRPOLYPOLYLINE16_swap(char *record, int torev){
+ return(core10_swap(record, torev));
+}
+
+// U_EMRPOLYPOLYGON16 91
+int U_EMRPOLYPOLYGON16_swap(char *record, int torev){
+ return(core10_swap(record, torev));
+}
+
+
+// U_EMRPOLYDRAW16 92
+int U_EMRPOLYDRAW16_swap(char *record, int torev){
+ int count=0;
+ const char *blimit = NULL;
+ PU_EMRPOLYDRAW16 pEmr = (PU_EMRPOLYDRAW16)(record);
+ if(torev){
+ count = pEmr->cpts;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(!core5_swap(record, torev))return(0);
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ U_swap4(&(pEmr->cpts),1); // cpts
+ if(!torev){
+ count = pEmr->cpts;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(IS_MEM_UNSAFE((pEmr->apts), count*sizeof(U_POINT16), blimit))return(0);
+ point16_swap(pEmr->apts,count); // apts[]
+ // single byte data abTypes
+ return(1);
+}
+
+// U_EMRCREATEMONOBRUSH 93
+int U_EMRCREATEMONOBRUSH_swap(char *record, int torev){
+ return(core12_swap(record, torev));
+}
+
+// U_EMRCREATEDIBPATTERNBRUSHPT_swap 94
+int U_EMRCREATEDIBPATTERNBRUSHPT_swap(char *record, int torev){
+ return(core12_swap(record, torev));
+}
+
+
+// U_EMREXTCREATEPEN 95
+int U_EMREXTCREATEPEN_swap(char *record, int torev){
+ const char *blimit = NULL;
+ U_OFFBMI offBmi = 0;
+ U_CBBMI cbBmi = 0;
+ U_OFFBITS offBits = 0;
+ U_CBBITS cbBits = 0;
+ PU_EMREXTCREATEPEN pEmr = (PU_EMREXTCREATEPEN)(record);
+ if(torev){
+ offBmi = pEmr->offBmi;
+ cbBmi = pEmr->cbBmi;
+ offBits = pEmr->offBits;
+ cbBits = pEmr->cbBits;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, U_DIB_RGB_COLORS, offBmi, cbBmi, offBits, cbBits, blimit, torev))return(0);
+ }
+ if(!core5_swap(record, torev))return(0);
+ U_swap4(&(pEmr->ihPen),5); // ihPen offBmi cbBmi offBits cbBits
+ if(!torev){
+ offBmi = pEmr->offBmi;
+ cbBmi = pEmr->cbBmi;
+ offBits = pEmr->offBits;
+ cbBits = pEmr->cbBits;
+ blimit = record + pEmr->emr.nSize;
+ if(!DIB_swap(record, U_DIB_RGB_COLORS, offBmi, cbBmi, offBits, cbBits, blimit, torev))return(0);
+ }
+ return(extlogpen_swap((PU_EXTLOGPEN) &(pEmr->elp), blimit, torev));
+}
+
+// U_EMRPOLYTEXTOUTA 96 NOT IMPLEMENTED, denigrated after Windows NT
+#define U_EMRPOLYTEXTOUTA_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
+// U_EMRPOLYTEXTOUTW 97 NOT IMPLEMENTED, denigrated after Windows NT
+#define U_EMRPOLYTEXTOUTW_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
+
+// U_EMRSETICMMODE 98
+int U_EMRSETICMMODE_swap(char *record, int torev){
+ return(core3_swap(record, torev));
+}
+
+// U_EMRCREATECOLORSPACE 99
+int U_EMRCREATECOLORSPACE_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
+ PU_EMRCREATECOLORSPACE pEmr = (PU_EMRCREATECOLORSPACE)(record);
+ U_swap4(&(pEmr->ihCS),1); // ihCS
+ logcolorspacea_swap(&(pEmr->lcs)); // lcs
+ return(1);
+}
+
+// U_EMRSETCOLORSPACE 100
+int U_EMRSETCOLORSPACE_swap(char *record, int torev){
+ return(core3_swap(record, torev));
+}
+
+// U_EMRDELETECOLORSPACE 101
+int U_EMRDELETECOLORSPACE_swap(char *record, int torev){
+ return(core3_swap(record, torev));
+}
+
+// U_EMRGLSRECORD 102 Not implemented
+#define U_EMRGLSRECORD_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
+// U_EMRGLSBOUNDEDRECORD 103 Not implemented
+#define U_EMRGLSBOUNDEDRECORD_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
+
+// U_EMRPIXELFORMAT 104
+int U_EMRPIXELFORMAT_swap(char *record, int torev){
+ if(!core5_swap(record, torev))return(0);
+ PU_EMRPIXELFORMAT pEmr = (PU_EMRPIXELFORMAT)(record);
+ pixelformatdescriptor_swap(&(pEmr->pfd)); // pfd
+ return(1);
+}
+
+// U_EMRDRAWESCAPE 105 Not implemented
+#define U_EMRDRAWESCAPE_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
+// U_EMREXTESCAPE 106 Not implemented
+#define U_EMREXTESCAPE_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
+// U_EMRUNDEF107 107 Not implemented
+#define U_EMRUNDEF107_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
+
+// U_EMRSMALLTEXTOUT 108
+int U_EMRSMALLTEXTOUT_swap(char *record, int torev){
+ int roff=sizeof(U_EMRSMALLTEXTOUT); // offset to the start of the variable fields
+ int fuOptions = 0;
+ int cChars = 0;
+ const char *blimit = NULL;
+ PU_EMRSMALLTEXTOUT pEmr = (PU_EMRSMALLTEXTOUT)(record);
+ if(torev){
+ fuOptions = pEmr->fuOptions;
+ cChars = pEmr->cChars;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(!core5_swap(record, torev))return(0);
+ pointl_swap(&(pEmr->Dest),1); // Dest
+ U_swap4(&(pEmr->cChars),5); // cChars fuOptions iGraphicsMode exScale eyScale
+ if(!torev){
+ fuOptions = pEmr->fuOptions;
+ cChars = pEmr->cChars;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(!(fuOptions & U_ETO_NO_RECT)){
+ if(IS_MEM_UNSAFE(record, roff + sizeof(U_RECTL), blimit))return(0);
+ rectl_swap( (PU_RECTL) (record + roff),1); // rclBounds
+ }
+ if(IS_MEM_UNSAFE(record, roff + sizeof(U_RECTL) + cChars, blimit))return(0);
+ // ordered bytes or UTF16-LE TextString
+ return(1);
+}
+
+// U_EMRFORCEUFIMAPPING 109 Not implemented
+#define U_EMRFORCEUFIMAPPING_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
+// U_EMRNAMEDESCAPE 110 Not implemented
+#define U_EMRNAMEDESCAPE_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
+// U_EMRCOLORCORRECTPALETTE 111 Not implemented
+#define U_EMRCOLORCORRECTPALETTE_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
+// U_EMRSETICMPROFILEA 112 Not implemented
+#define U_EMRSETICMPROFILEA_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
+// U_EMRSETICMPROFILEW 113 Not implemented
+#define U_EMRSETICMPROFILEW_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
+
+// U_EMRALPHABLEND 114
+int U_EMRALPHABLEND_swap(char *record, int torev){
+ return(core13_swap(record, torev));
+}
+
+// U_EMRSETLAYOUT 115
+int U_EMRSETLAYOUT_swap(char *record, int torev){
+ return(core3_swap(record, torev));
+}
+
+// U_EMRTRANSPARENTBLT 116
+int U_EMRTRANSPARENTBLT_swap(char *record, int torev){
+ return(core13_swap(record, torev));
+}
+
+
+// U_EMRUNDEF117 117 Not implemented
+#define U_EMRUNDEF117_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
+// U_EMRGRADIENTFILL 118
+int U_EMRGRADIENTFILL_swap(char *record, int torev){
+ int nTriVert=0;
+ int nGradObj=0;
+ int ulMode=0;
+ const char *blimit = NULL;
+ PU_EMRGRADIENTFILL pEmr = (PU_EMRGRADIENTFILL)(record);
+ if(torev){
+ nTriVert = pEmr->nTriVert;
+ nGradObj = pEmr->nGradObj;
+ ulMode = pEmr->ulMode;
+ blimit = record + pEmr->emr.nSize;
+ }
+ if(!core5_swap(record, torev))return(0);
+ rectl_swap(&(pEmr->rclBounds),1); // rclBounds
+ U_swap4(&(pEmr->nTriVert),3); // nTriVert nGradObj ulMode
+ if(!torev){
+ nTriVert = pEmr->nTriVert;
+ nGradObj = pEmr->nGradObj;
+ ulMode = pEmr->ulMode;
+ blimit = record + pEmr->emr.nSize;
+ }
+ record += sizeof(U_EMRGRADIENTFILL);
+ if(IS_MEM_UNSAFE(record, nTriVert*sizeof(U_TRIVERTEX), blimit))return(0);
+ if(nTriVert){
+ trivertex_swap((PU_TRIVERTEX)(record),nTriVert); // TriVert[]
+ }
+ record += nTriVert * sizeof(U_TRIVERTEX);
+ if(nGradObj){
+ if( ulMode == U_GRADIENT_FILL_TRIANGLE){
+ if(IS_MEM_UNSAFE(record, nGradObj*sizeof(U_GRADIENT3), blimit))return(0);
+ gradient3_swap((PU_GRADIENT3)(record), nGradObj); // GradObj[]
+ }
+ else if(ulMode == U_GRADIENT_FILL_RECT_H || ulMode == U_GRADIENT_FILL_RECT_V){
+ if(IS_MEM_UNSAFE(record, nGradObj*sizeof(U_GRADIENT4), blimit))return(0);
+ gradient4_swap((PU_GRADIENT4)(record), nGradObj); // GradObj[]
+ }
+ }
+ return(1);
+}
+
+// U_EMRSETLINKEDUFIS 119 Not implemented
+#define U_EMRSETLINKEDUFIS_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
+// U_EMRSETTEXTJUSTIFICATION120 Not implemented (denigrated)
+#define U_EMRSETTEXTJUSTIFICATION_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
+// U_EMRCOLORMATCHTOTARGETW 121 Not implemented
+#define U_EMRCOLORMATCHTOTARGETW_swap(A,B) U_EMRNOTIMPLEMENTED_swap(A,B) //!< Not implemented.
+
+// U_EMRCREATECOLORSPACEW 122
+int U_EMRCREATECOLORSPACEW_swap(char *record, int torev){
+ PU_EMRCREATECOLORSPACEW pEmr = (PU_EMRCREATECOLORSPACEW)(record);
+ if(!core5_swap(record, torev))return(0);
+ U_swap4(&(pEmr->ihCS),1); // ihCS
+ logcolorspacew_swap(&(pEmr->lcs)); // lcs
+ U_swap4(&(pEmr->dwFlags),2); // dwFlags cbData
+ // ordered bytes: Data
+ return(1);
+}
+
+//! \endcond
+
+/**
+ \brief Checks the declared size of a record for consistency
+ \return 0 on failure, 1 on success
+ \param record pointer to the start of the EMF record in memory
+ \param blimit pointer to one byte after the EMF record in memory
+ \param nSize number of bytes in the record, read from the record
+ \param iType type of the record, read from the record
+ \param torev 1 for native to reversed, 0 for reversed to native
+
+ Normally this would be called immediately after reading the data from a file.
+ Verifies that the declared size is consistent with this type of record.
+*/
+int U_emf_record_sizeok(const char *record, const char *blimit, uint32_t *nSize, uint32_t *iType, int torev){
+ uint32_t rsize=0;
+ if(!nSize || !iType)return(0); // programming error
+
+ /* Check that COMMON data in record can be touched without an access violation. If it cannot be
+ this is either a corrupt EMF or one engineered to cause a buffer overflow. Pointer math
+ could wrap so check both sides of the range, and fail any indications of such a wrap.
+ */
+ if(IS_MEM_UNSAFE(record, sizeof(U_EMR), blimit))return(0);
+
+ PU_ENHMETARECORD pEmr = (PU_ENHMETARECORD)(record);
+ *iType = pEmr->iType;
+ *nSize = pEmr->nSize;
+ if(!torev){
+ U_swap4(iType,1);
+ U_swap4(nSize,1);
+ }
+
+ /* Check that the FULL record size is OK, abort if not. */
+ if(IS_MEM_UNSAFE(record, *nSize, blimit))return(0);
+
+ switch (*iType)
+ {
+ // next line, ancient EMF files used a smaller header, to be safe, test for that
+ case U_EMR_HEADER: rsize = U_SIZE_EMRHEADER_MIN; break;
+ case U_EMR_POLYBEZIER: rsize = U_SIZE_EMRPOLYBEZIER; break;
+ case U_EMR_POLYGON: rsize = U_SIZE_EMRPOLYGON; break;
+ case U_EMR_POLYLINE: rsize = U_SIZE_EMRPOLYLINE; break;
+ case U_EMR_POLYBEZIERTO: rsize = U_SIZE_EMRPOLYBEZIERTO; break;
+ case U_EMR_POLYLINETO: rsize = U_SIZE_EMRPOLYLINETO; break;
+ case U_EMR_POLYPOLYLINE: rsize = U_SIZE_EMRPOLYPOLYLINE; break;
+ case U_EMR_POLYPOLYGON: rsize = U_SIZE_EMRPOLYPOLYGON; break;
+ case U_EMR_SETWINDOWEXTEX: rsize = U_SIZE_EMRSETWINDOWEXTEX; break;
+ case U_EMR_SETWINDOWORGEX: rsize = U_SIZE_EMRSETWINDOWORGEX; break;
+ case U_EMR_SETVIEWPORTEXTEX: rsize = U_SIZE_EMRSETVIEWPORTEXTEX; break;
+ case U_EMR_SETVIEWPORTORGEX: rsize = U_SIZE_EMRSETVIEWPORTORGEX; break;
+ case U_EMR_SETBRUSHORGEX: rsize = U_SIZE_EMRSETBRUSHORGEX; break;
+ case U_EMR_EOF: rsize = U_SIZE_EMREOF; break;
+ case U_EMR_SETPIXELV: rsize = U_SIZE_EMRSETPIXELV; break;
+ case U_EMR_SETMAPPERFLAGS: rsize = U_SIZE_EMRSETMAPPERFLAGS; break;
+ case U_EMR_SETMAPMODE: rsize = U_SIZE_EMRSETMAPMODE; break;
+ case U_EMR_SETBKMODE: rsize = U_SIZE_EMRSETBKMODE; break;
+ case U_EMR_SETPOLYFILLMODE: rsize = U_SIZE_EMRSETPOLYFILLMODE; break;
+ case U_EMR_SETROP2: rsize = U_SIZE_EMRSETROP2; break;
+ case U_EMR_SETSTRETCHBLTMODE: rsize = U_SIZE_EMRSETSTRETCHBLTMODE; break;
+ case U_EMR_SETTEXTALIGN: rsize = U_SIZE_EMRSETTEXTALIGN; break;
+ case U_EMR_SETCOLORADJUSTMENT: rsize = U_SIZE_EMRSETCOLORADJUSTMENT; break;
+ case U_EMR_SETTEXTCOLOR: rsize = U_SIZE_EMRSETTEXTCOLOR; break;
+ case U_EMR_SETBKCOLOR: rsize = U_SIZE_EMRSETBKCOLOR; break;
+ case U_EMR_OFFSETCLIPRGN: rsize = U_SIZE_EMROFFSETCLIPRGN; break;
+ case U_EMR_MOVETOEX: rsize = U_SIZE_EMRMOVETOEX; break;
+ case U_EMR_SETMETARGN: rsize = U_SIZE_EMRSETMETARGN; break;
+ case U_EMR_EXCLUDECLIPRECT: rsize = U_SIZE_EMREXCLUDECLIPRECT; break;
+ case U_EMR_INTERSECTCLIPRECT: rsize = U_SIZE_EMRINTERSECTCLIPRECT; break;
+ case U_EMR_SCALEVIEWPORTEXTEX: rsize = U_SIZE_EMRSCALEVIEWPORTEXTEX; break;
+ case U_EMR_SCALEWINDOWEXTEX: rsize = U_SIZE_EMRSCALEWINDOWEXTEX; break;
+ case U_EMR_SAVEDC: rsize = U_SIZE_EMRSAVEDC; break;
+ case U_EMR_RESTOREDC: rsize = U_SIZE_EMRRESTOREDC; break;
+ case U_EMR_SETWORLDTRANSFORM: rsize = U_SIZE_EMRSETWORLDTRANSFORM; break;
+ case U_EMR_MODIFYWORLDTRANSFORM: rsize = U_SIZE_EMRMODIFYWORLDTRANSFORM; break;
+ case U_EMR_SELECTOBJECT: rsize = U_SIZE_EMRSELECTOBJECT; break;
+ case U_EMR_CREATEPEN: rsize = U_SIZE_EMRCREATEPEN; break;
+ case U_EMR_CREATEBRUSHINDIRECT: rsize = U_SIZE_EMRCREATEBRUSHINDIRECT; break;
+ case U_EMR_DELETEOBJECT: rsize = U_SIZE_EMRDELETEOBJECT; break;
+ case U_EMR_ANGLEARC: rsize = U_SIZE_EMRANGLEARC; break;
+ case U_EMR_ELLIPSE: rsize = U_SIZE_EMRELLIPSE; break;
+ case U_EMR_RECTANGLE: rsize = U_SIZE_EMRRECTANGLE; break;
+ case U_EMR_ROUNDRECT: rsize = U_SIZE_EMRROUNDRECT; break;
+ case U_EMR_ARC: rsize = U_SIZE_EMRARC; break;
+ case U_EMR_CHORD: rsize = U_SIZE_EMRCHORD; break;
+ case U_EMR_PIE: rsize = U_SIZE_EMRPIE; break;
+ case U_EMR_SELECTPALETTE: rsize = U_SIZE_EMRSELECTPALETTE; break;
+ case U_EMR_CREATEPALETTE: rsize = U_SIZE_EMRCREATEPALETTE; break;
+ case U_EMR_SETPALETTEENTRIES: rsize = U_SIZE_EMRSETPALETTEENTRIES; break;
+ case U_EMR_RESIZEPALETTE: rsize = U_SIZE_EMRRESIZEPALETTE; break;
+ case U_EMR_REALIZEPALETTE: rsize = U_SIZE_EMRREALIZEPALETTE; break;
+ case U_EMR_EXTFLOODFILL: rsize = U_SIZE_EMREXTFLOODFILL; break;
+ case U_EMR_LINETO: rsize = U_SIZE_EMRLINETO; break;
+ case U_EMR_ARCTO: rsize = U_SIZE_EMRARCTO; break;
+ case U_EMR_POLYDRAW: rsize = U_SIZE_EMRPOLYDRAW; break;
+ case U_EMR_SETARCDIRECTION: rsize = U_SIZE_EMRSETARCDIRECTION; break;
+ case U_EMR_SETMITERLIMIT: rsize = U_SIZE_EMRSETMITERLIMIT; break;
+ case U_EMR_BEGINPATH: rsize = U_SIZE_EMRBEGINPATH; break;
+ case U_EMR_ENDPATH: rsize = U_SIZE_EMRENDPATH; break;
+ case U_EMR_CLOSEFIGURE: rsize = U_SIZE_EMRCLOSEFIGURE; break;
+ case U_EMR_FILLPATH: rsize = U_SIZE_EMRFILLPATH; break;
+ case U_EMR_STROKEANDFILLPATH: rsize = U_SIZE_EMRSTROKEANDFILLPATH; break;
+ case U_EMR_STROKEPATH: rsize = U_SIZE_EMRSTROKEPATH; break;
+ case U_EMR_FLATTENPATH: rsize = U_SIZE_EMRFLATTENPATH; break;
+ case U_EMR_WIDENPATH: rsize = U_SIZE_EMRWIDENPATH; break;
+ case U_EMR_SELECTCLIPPATH: rsize = U_SIZE_EMRSELECTCLIPPATH; break;
+ case U_EMR_ABORTPATH: rsize = U_SIZE_EMRABORTPATH; break;
+ case U_EMR_UNDEF69: rsize = U_SIZE_EMRUNDEFINED; break;
+ case U_EMR_COMMENT: rsize = U_SIZE_EMRCOMMENT; break;
+ case U_EMR_FILLRGN: rsize = U_SIZE_EMRFILLRGN; break;
+ case U_EMR_FRAMERGN: rsize = U_SIZE_EMRFRAMERGN; break;
+ case U_EMR_INVERTRGN: rsize = U_SIZE_EMRINVERTRGN; break;
+ case U_EMR_PAINTRGN: rsize = U_SIZE_EMRPAINTRGN; break;
+ case U_EMR_EXTSELECTCLIPRGN: rsize = U_SIZE_EMREXTSELECTCLIPRGN; break;
+ case U_EMR_BITBLT: rsize = U_SIZE_EMRBITBLT; break;
+ case U_EMR_STRETCHBLT: rsize = U_SIZE_EMRSTRETCHBLT; break;
+ case U_EMR_MASKBLT: rsize = U_SIZE_EMRMASKBLT; break;
+ case U_EMR_PLGBLT: rsize = U_SIZE_EMRPLGBLT; break;
+ case U_EMR_SETDIBITSTODEVICE: rsize = U_SIZE_EMRSETDIBITSTODEVICE; break;
+ case U_EMR_STRETCHDIBITS: rsize = U_SIZE_EMRSTRETCHDIBITS; break;
+ case U_EMR_EXTCREATEFONTINDIRECTW: rsize = U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT; break;
+ case U_EMR_EXTTEXTOUTA: rsize = U_SIZE_EMREXTTEXTOUTA; break;
+ case U_EMR_EXTTEXTOUTW: rsize = U_SIZE_EMREXTTEXTOUTW; break;
+ case U_EMR_POLYBEZIER16: rsize = U_SIZE_EMRPOLYBEZIER16; break;
+ case U_EMR_POLYGON16: rsize = U_SIZE_EMRPOLYGON16; break;
+ case U_EMR_POLYLINE16: rsize = U_SIZE_EMRPOLYLINE16; break;
+ case U_EMR_POLYBEZIERTO16: rsize = U_SIZE_EMRPOLYBEZIERTO16; break;
+ case U_EMR_POLYLINETO16: rsize = U_SIZE_EMRPOLYLINETO16; break;
+ case U_EMR_POLYPOLYLINE16: rsize = U_SIZE_EMRPOLYPOLYLINE16; break;
+ case U_EMR_POLYPOLYGON16: rsize = U_SIZE_EMRPOLYPOLYGON16; break;
+ case U_EMR_POLYDRAW16: rsize = U_SIZE_EMRPOLYDRAW16; break;
+ case U_EMR_CREATEMONOBRUSH: rsize = U_SIZE_EMRCREATEMONOBRUSH; break;
+ case U_EMR_CREATEDIBPATTERNBRUSHPT: rsize = U_SIZE_EMRCREATEDIBPATTERNBRUSHPT; break;
+ case U_EMR_EXTCREATEPEN: rsize = U_SIZE_EMREXTCREATEPEN; break;
+ case U_EMR_POLYTEXTOUTA: rsize = U_SIZE_EMRPOLYTEXTOUTA; break;
+ case U_EMR_POLYTEXTOUTW: rsize = U_SIZE_EMRPOLYTEXTOUTW; break;
+ case U_EMR_SETICMMODE: rsize = U_SIZE_EMRSETICMMODE; break;
+ case U_EMR_CREATECOLORSPACE: rsize = U_SIZE_EMRCREATECOLORSPACE; break;
+ case U_EMR_SETCOLORSPACE: rsize = U_SIZE_EMRSETCOLORSPACE; break;
+ case U_EMR_DELETECOLORSPACE: rsize = U_SIZE_EMRDELETECOLORSPACE; break;
+ case U_EMR_GLSRECORD: rsize = U_SIZE_EMRGLSRECORD; break;
+ case U_EMR_GLSBOUNDEDRECORD: rsize = U_SIZE_EMRGLSBOUNDEDRECORD; break;
+ case U_EMR_PIXELFORMAT: rsize = U_SIZE_EMRPIXELFORMAT; break;
+ case U_EMR_DRAWESCAPE: rsize = U_SIZE_EMRDRAWESCAPE; break;
+ case U_EMR_EXTESCAPE: rsize = U_SIZE_EMREXTESCAPE; break;
+ case U_EMR_UNDEF107: rsize = U_SIZE_EMRUNDEFINED; break;
+ case U_EMR_SMALLTEXTOUT: rsize = U_SIZE_EMRSMALLTEXTOUT; break;
+// case U_EMR_FORCEUFIMAPPING: rsize = U_SIZE_EMRFORCEUFIMAPPING; break;
+ case U_EMR_NAMEDESCAPE: rsize = U_SIZE_EMRNAMEDESCAPE; break;
+// case U_EMR_COLORCORRECTPALETTE: rsize = U_SIZE_EMRCOLORCORRECTPALETTE; break;
+// case U_EMR_SETICMPROFILEA: rsize = U_SIZE_EMRSETICMPROFILEA; break;
+// case U_EMR_SETICMPROFILEW: rsize = U_SIZE_EMRSETICMPROFILEW; break;
+ case U_EMR_ALPHABLEND: rsize = U_SIZE_EMRALPHABLEND; break;
+ case U_EMR_SETLAYOUT: rsize = U_SIZE_EMRSETLAYOUT; break;
+ case U_EMR_TRANSPARENTBLT: rsize = U_SIZE_EMRTRANSPARENTBLT; break;
+ case U_EMR_UNDEF117: rsize = U_SIZE_EMRUNDEFINED; break;
+ case U_EMR_GRADIENTFILL: rsize = U_SIZE_EMRGRADIENTFILL; break;
+// case U_EMR_SETLINKEDUFIS: rsize = U_SIZE_EMRSETLINKEDUFIS; break;
+// case U_EMR_SETTEXTJUSTIFICATION: rsize = U_SIZE_EMRSETTEXTJUSTIFICATION; break;
+ case U_EMR_COLORMATCHTOTARGETW: rsize = U_SIZE_EMRCOLORMATCHTOTARGETW; break;
+ case U_EMR_CREATECOLORSPACEW: rsize = U_SIZE_EMRCREATECOLORSPACEW; break;
+ default: rsize = U_SIZE_EMRNOTIMPLEMENTED; break;
+ } //end of switch
+ // record's declared size must be more than the minimum size for this type of record
+ if(*nSize < rsize){
+ return(0);
+ }
+ return(1);
+}
+
+
+/**
+ \brief Convert an entire EMF in memory from Big Endian to Little Endian.
+ \return 0 on failure, 1 on success
+ \param contents pointer to the buffer holding the entire EMF in memory
+ \param length number of bytes in the buffer
+ \param torev 1 for native to reversed, 0 for reversed to native
+
+ Normally this would be called immediately before writing the data to a file
+ or immediately after reading the data from a file.
+*/
+int U_emf_endian(char *contents, size_t length, int torev){
+ uint32_t off;
+ uint32_t OK, recnum, iType;
+ char *record;
+ const char *blimit = contents + length; /* should never wrap since it describes a structure in memory */
+ int rstatus=1;
+
+ record = contents;
+ OK = 1;
+ off = 0;
+ recnum = 0;
+ while(OK){
+
+ if(!U_emf_record_sizeok(record, blimit, &off, &iType, torev)){
+ return(0);
+ }
+
+ switch (iType)
+ {
+ case U_EMR_HEADER: rstatus=U_EMRHEADER_swap(record, torev); break;
+ case U_EMR_POLYBEZIER: rstatus=U_EMRPOLYBEZIER_swap(record, torev); break;
+ case U_EMR_POLYGON: rstatus=U_EMRPOLYGON_swap(record, torev); break;
+ case U_EMR_POLYLINE: rstatus=U_EMRPOLYLINE_swap(record, torev); break;
+ case U_EMR_POLYBEZIERTO: rstatus=U_EMRPOLYBEZIERTO_swap(record, torev); break;
+ case U_EMR_POLYLINETO: rstatus=U_EMRPOLYLINETO_swap(record, torev); break;
+ case U_EMR_POLYPOLYLINE: rstatus=U_EMRPOLYPOLYLINE_swap(record, torev); break;
+ case U_EMR_POLYPOLYGON: rstatus=U_EMRPOLYPOLYGON_swap(record, torev); break;
+ case U_EMR_SETWINDOWEXTEX: rstatus=U_EMRSETWINDOWEXTEX_swap(record, torev); break;
+ case U_EMR_SETWINDOWORGEX: rstatus=U_EMRSETWINDOWORGEX_swap(record, torev); break;
+ case U_EMR_SETVIEWPORTEXTEX: rstatus=U_EMRSETVIEWPORTEXTEX_swap(record, torev); break;
+ case U_EMR_SETVIEWPORTORGEX: rstatus=U_EMRSETVIEWPORTORGEX_swap(record, torev); break;
+ case U_EMR_SETBRUSHORGEX: rstatus=U_EMRSETBRUSHORGEX_swap(record, torev); break;
+ case U_EMR_EOF:
+ rstatus=U_EMREOF_swap(record, torev);
+ OK = 0; /* Exit triggered here */
+ break;
+ case U_EMR_SETPIXELV: rstatus=U_EMRSETPIXELV_swap(record, torev); break;
+ case U_EMR_SETMAPPERFLAGS: rstatus=U_EMRSETMAPPERFLAGS_swap(record, torev); break;
+ case U_EMR_SETMAPMODE: rstatus=U_EMRSETMAPMODE_swap(record, torev); break;
+ case U_EMR_SETBKMODE: rstatus=U_EMRSETBKMODE_swap(record, torev); break;
+ case U_EMR_SETPOLYFILLMODE: rstatus=U_EMRSETPOLYFILLMODE_swap(record, torev); break;
+ case U_EMR_SETROP2: rstatus=U_EMRSETROP2_swap(record, torev); break;
+ case U_EMR_SETSTRETCHBLTMODE: rstatus=U_EMRSETSTRETCHBLTMODE_swap(record, torev); break;
+ case U_EMR_SETTEXTALIGN: rstatus=U_EMRSETTEXTALIGN_swap(record, torev); break;
+ case U_EMR_SETCOLORADJUSTMENT: rstatus=U_EMRSETCOLORADJUSTMENT_swap(record, torev); break;
+ case U_EMR_SETTEXTCOLOR: rstatus=U_EMRSETTEXTCOLOR_swap(record, torev); break;
+ case U_EMR_SETBKCOLOR: rstatus=U_EMRSETBKCOLOR_swap(record, torev); break;
+ case U_EMR_OFFSETCLIPRGN: rstatus=U_EMROFFSETCLIPRGN_swap(record, torev); break;
+ case U_EMR_MOVETOEX: rstatus=U_EMRMOVETOEX_swap(record, torev); break;
+ case U_EMR_SETMETARGN: rstatus=U_EMRSETMETARGN_swap(record, torev); break;
+ case U_EMR_EXCLUDECLIPRECT: rstatus=U_EMREXCLUDECLIPRECT_swap(record, torev); break;
+ case U_EMR_INTERSECTCLIPRECT: rstatus=U_EMRINTERSECTCLIPRECT_swap(record, torev); break;
+ case U_EMR_SCALEVIEWPORTEXTEX: rstatus=U_EMRSCALEVIEWPORTEXTEX_swap(record, torev); break;
+ case U_EMR_SCALEWINDOWEXTEX: rstatus=U_EMRSCALEWINDOWEXTEX_swap(record, torev); break;
+ case U_EMR_SAVEDC: rstatus=U_EMRSAVEDC_swap(record, torev); break;
+ case U_EMR_RESTOREDC: rstatus=U_EMRRESTOREDC_swap(record, torev); break;
+ case U_EMR_SETWORLDTRANSFORM: rstatus=U_EMRSETWORLDTRANSFORM_swap(record, torev); break;
+ case U_EMR_MODIFYWORLDTRANSFORM: rstatus=U_EMRMODIFYWORLDTRANSFORM_swap(record, torev); break;
+ case U_EMR_SELECTOBJECT: rstatus=U_EMRSELECTOBJECT_swap(record, torev); break;
+ case U_EMR_CREATEPEN: rstatus=U_EMRCREATEPEN_swap(record, torev); break;
+ case U_EMR_CREATEBRUSHINDIRECT: rstatus=U_EMRCREATEBRUSHINDIRECT_swap(record, torev); break;
+ case U_EMR_DELETEOBJECT: rstatus=U_EMRDELETEOBJECT_swap(record, torev); break;
+ case U_EMR_ANGLEARC: rstatus=U_EMRANGLEARC_swap(record, torev); break;
+ case U_EMR_ELLIPSE: rstatus=U_EMRELLIPSE_swap(record, torev); break;
+ case U_EMR_RECTANGLE: rstatus=U_EMRRECTANGLE_swap(record, torev); break;
+ case U_EMR_ROUNDRECT: rstatus=U_EMRROUNDRECT_swap(record, torev); break;
+ case U_EMR_ARC: rstatus=U_EMRARC_swap(record, torev); break;
+ case U_EMR_CHORD: rstatus=U_EMRCHORD_swap(record, torev); break;
+ case U_EMR_PIE: rstatus=U_EMRPIE_swap(record, torev); break;
+ case U_EMR_SELECTPALETTE: rstatus=U_EMRSELECTPALETTE_swap(record, torev); break;
+ case U_EMR_CREATEPALETTE: rstatus=U_EMRCREATEPALETTE_swap(record, torev); break;
+ case U_EMR_SETPALETTEENTRIES: rstatus=U_EMRSETPALETTEENTRIES_swap(record, torev); break;
+ case U_EMR_RESIZEPALETTE: rstatus=U_EMRRESIZEPALETTE_swap(record, torev); break;
+ case U_EMR_REALIZEPALETTE: rstatus=U_EMRREALIZEPALETTE_swap(record, torev); break;
+ case U_EMR_EXTFLOODFILL: rstatus=U_EMREXTFLOODFILL_swap(record, torev); break;
+ case U_EMR_LINETO: rstatus=U_EMRLINETO_swap(record, torev); break;
+ case U_EMR_ARCTO: rstatus=U_EMRARCTO_swap(record, torev); break;
+ case U_EMR_POLYDRAW: rstatus=U_EMRPOLYDRAW_swap(record, torev); break;
+ case U_EMR_SETARCDIRECTION: rstatus=U_EMRSETARCDIRECTION_swap(record, torev); break;
+ case U_EMR_SETMITERLIMIT: rstatus=U_EMRSETMITERLIMIT_swap(record, torev); break;
+ case U_EMR_BEGINPATH: rstatus=U_EMRBEGINPATH_swap(record, torev); break;
+ case U_EMR_ENDPATH: rstatus=U_EMRENDPATH_swap(record, torev); break;
+ case U_EMR_CLOSEFIGURE: rstatus=U_EMRCLOSEFIGURE_swap(record, torev); break;
+ case U_EMR_FILLPATH: rstatus=U_EMRFILLPATH_swap(record, torev); break;
+ case U_EMR_STROKEANDFILLPATH: rstatus=U_EMRSTROKEANDFILLPATH_swap(record, torev); break;
+ case U_EMR_STROKEPATH: rstatus=U_EMRSTROKEPATH_swap(record, torev); break;
+ case U_EMR_FLATTENPATH: rstatus=U_EMRFLATTENPATH_swap(record, torev); break;
+ case U_EMR_WIDENPATH: rstatus=U_EMRWIDENPATH_swap(record, torev); break;
+ case U_EMR_SELECTCLIPPATH: rstatus=U_EMRSELECTCLIPPATH_swap(record, torev); break;
+ case U_EMR_ABORTPATH: rstatus=U_EMRABORTPATH_swap(record, torev); break;
+ case U_EMR_UNDEF69: rstatus=U_EMRUNDEF69_swap(record, torev); break;
+ case U_EMR_COMMENT: rstatus=U_EMRCOMMENT_swap(record, torev); break;
+ case U_EMR_FILLRGN: rstatus=U_EMRFILLRGN_swap(record, torev); break;
+ case U_EMR_FRAMERGN: rstatus=U_EMRFRAMERGN_swap(record, torev); break;
+ case U_EMR_INVERTRGN: rstatus=U_EMRINVERTRGN_swap(record, torev); break;
+ case U_EMR_PAINTRGN: rstatus=U_EMRPAINTRGN_swap(record, torev); break;
+ case U_EMR_EXTSELECTCLIPRGN: rstatus=U_EMREXTSELECTCLIPRGN_swap(record, torev);break;
+ case U_EMR_BITBLT: rstatus=U_EMRBITBLT_swap(record, torev); break;
+ case U_EMR_STRETCHBLT: rstatus=U_EMRSTRETCHBLT_swap(record, torev); break;
+ case U_EMR_MASKBLT: rstatus=U_EMRMASKBLT_swap(record, torev); break;
+ case U_EMR_PLGBLT: rstatus=U_EMRPLGBLT_swap(record, torev); break;
+ case U_EMR_SETDIBITSTODEVICE: rstatus=U_EMRSETDIBITSTODEVICE_swap(record, torev); break;
+ case U_EMR_STRETCHDIBITS: rstatus=U_EMRSTRETCHDIBITS_swap(record, torev); break;
+ case U_EMR_EXTCREATEFONTINDIRECTW: rstatus=U_EMREXTCREATEFONTINDIRECTW_swap(record, torev); break;
+ case U_EMR_EXTTEXTOUTA: rstatus=U_EMREXTTEXTOUTA_swap(record, torev); break;
+ case U_EMR_EXTTEXTOUTW: rstatus=U_EMREXTTEXTOUTW_swap(record, torev); break;
+ case U_EMR_POLYBEZIER16: rstatus=U_EMRPOLYBEZIER16_swap(record, torev); break;
+ case U_EMR_POLYGON16: rstatus=U_EMRPOLYGON16_swap(record, torev); break;
+ case U_EMR_POLYLINE16: rstatus=U_EMRPOLYLINE16_swap(record, torev); break;
+ case U_EMR_POLYBEZIERTO16: rstatus=U_EMRPOLYBEZIERTO16_swap(record, torev); break;
+ case U_EMR_POLYLINETO16: rstatus=U_EMRPOLYLINETO16_swap(record, torev); break;
+ case U_EMR_POLYPOLYLINE16: rstatus=U_EMRPOLYPOLYLINE16_swap(record, torev); break;
+ case U_EMR_POLYPOLYGON16: rstatus=U_EMRPOLYPOLYGON16_swap(record, torev); break;
+ case U_EMR_POLYDRAW16: rstatus=U_EMRPOLYDRAW16_swap(record, torev); break;
+ case U_EMR_CREATEMONOBRUSH: rstatus=U_EMRCREATEMONOBRUSH_swap(record, torev); break;
+ case U_EMR_CREATEDIBPATTERNBRUSHPT: rstatus=U_EMRCREATEDIBPATTERNBRUSHPT_swap(record, torev); break;
+ case U_EMR_EXTCREATEPEN: rstatus=U_EMREXTCREATEPEN_swap(record, torev); break;
+ case U_EMR_POLYTEXTOUTA: rstatus=U_EMRPOLYTEXTOUTA_swap(record, torev); break;
+ case U_EMR_POLYTEXTOUTW: rstatus=U_EMRPOLYTEXTOUTW_swap(record, torev); break;
+ case U_EMR_SETICMMODE: rstatus=U_EMRSETICMMODE_swap(record, torev); break;
+ case U_EMR_CREATECOLORSPACE: rstatus=U_EMRCREATECOLORSPACE_swap(record, torev); break;
+ case U_EMR_SETCOLORSPACE: rstatus=U_EMRSETCOLORSPACE_swap(record, torev); break;
+ case U_EMR_DELETECOLORSPACE: rstatus=U_EMRDELETECOLORSPACE_swap(record, torev); break;
+ case U_EMR_GLSRECORD: rstatus=U_EMRGLSRECORD_swap(record, torev); break;
+ case U_EMR_GLSBOUNDEDRECORD: rstatus=U_EMRGLSBOUNDEDRECORD_swap(record, torev); break;
+ case U_EMR_PIXELFORMAT: rstatus=U_EMRPIXELFORMAT_swap(record, torev); break;
+ case U_EMR_DRAWESCAPE: rstatus=U_EMRDRAWESCAPE_swap(record, torev); break;
+ case U_EMR_EXTESCAPE: rstatus=U_EMREXTESCAPE_swap(record, torev); break;
+ case U_EMR_UNDEF107: rstatus=U_EMRUNDEF107_swap(record, torev); break;
+ case U_EMR_SMALLTEXTOUT: rstatus=U_EMRSMALLTEXTOUT_swap(record, torev); break;
+ case U_EMR_FORCEUFIMAPPING: rstatus=U_EMRFORCEUFIMAPPING_swap(record, torev); break;
+ case U_EMR_NAMEDESCAPE: rstatus=U_EMRNAMEDESCAPE_swap(record, torev); break;
+ case U_EMR_COLORCORRECTPALETTE: rstatus=U_EMRCOLORCORRECTPALETTE_swap(record, torev); break;
+ case U_EMR_SETICMPROFILEA: rstatus=U_EMRSETICMPROFILEA_swap(record, torev); break;
+ case U_EMR_SETICMPROFILEW: rstatus=U_EMRSETICMPROFILEW_swap(record, torev); break;
+ case U_EMR_ALPHABLEND: rstatus=U_EMRALPHABLEND_swap(record, torev); break;
+ case U_EMR_SETLAYOUT: rstatus=U_EMRSETLAYOUT_swap(record, torev); break;
+ case U_EMR_TRANSPARENTBLT: rstatus=U_EMRTRANSPARENTBLT_swap(record, torev); break;
+ case U_EMR_UNDEF117: rstatus=U_EMRUNDEF117_swap(record, torev); break;
+ case U_EMR_GRADIENTFILL: rstatus=U_EMRGRADIENTFILL_swap(record, torev); break;
+ case U_EMR_SETLINKEDUFIS: rstatus=U_EMRSETLINKEDUFIS_swap(record, torev); break;
+ case U_EMR_SETTEXTJUSTIFICATION: rstatus=U_EMRSETTEXTJUSTIFICATION_swap(record, torev); break;
+ case U_EMR_COLORMATCHTOTARGETW: rstatus=U_EMRCOLORMATCHTOTARGETW_swap(record, torev); break;
+ case U_EMR_CREATECOLORSPACEW: rstatus=U_EMRCREATECOLORSPACEW_swap(record, torev); break;
+ default: rstatus=U_EMRNOTIMPLEMENTED_swap(record, torev); break;
+ } //end of switch
+ if(!rstatus){
+ return(rstatus);
+ }
+ record += off;
+ recnum++;
+ } //end of while
+
+ return(1);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/3rdparty/libuemf/uemf_endian.h b/src/3rdparty/libuemf/uemf_endian.h
new file mode 100644
index 0000000..9dbcec4
--- /dev/null
+++ b/src/3rdparty/libuemf/uemf_endian.h
@@ -0,0 +1,59 @@
+/**
+ @file uemf_endian.h
+
+ @brief Defintions and prototype for function for converting EMF records between Big Endian and Little Endian byte orders.
+*/
+
+/*
+File: uemf_endian.h
+Version: 0.0.4
+Date: 24-MAR-2015
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2015 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifndef _UEMF_ENDIAN_
+#define _UEMF_ENDIAN_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \defgroup U_Endian Byte order identification
+
+ There is no way for the preprocessor, in general, to figure out endianness. So the command line must define
+ WORDS_BIGENDIAN for a big endian machine. Otherwise we assume is is little endian. If it is something
+ else this code won't work in any case.
+
+ @{
+*/
+
+#ifdef WORDS_BIGENDIAN
+#define U_BYTE_SWAP 1 //!< byte swapping into metafile is required
+#define U_IS_BE 1 //!< this machine is big endian
+#define U_IS_LE 0 //!< this machine is not little endian
+#else
+#define U_BYTE_SWAP 0 //!< byte swapping into metafile is not required
+#define U_IS_BE 0 //!< this machine is not big endian
+#define U_IS_LE 1 //!< this machine is little endian
+#endif
+
+#define U_XE 0 //!< do not rearrange endian for target
+#define U_LE 1 //!< target is Little Endian
+#define U_BE 2 //!< target is Big Endian
+#define U_RP 4 //!< replicate first instance
+#define U_XX 0xFF //!< may be used to terminate a list of these target entries
+/** @} */
+
+//! \cond
+// prototypes
+int U_emf_endian(char *contents, size_t length, int torev);
+int U_emf_record_sizeok(const char *record, const char *blimit, uint32_t *nSize, uint32_t *iType, int torev);
+//! \endcond
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UEMF_ENDIAN_ */
diff --git a/src/3rdparty/libuemf/uemf_print.c b/src/3rdparty/libuemf/uemf_print.c
new file mode 100644
index 0000000..74fa5ae
--- /dev/null
+++ b/src/3rdparty/libuemf/uemf_print.c
@@ -0,0 +1,2704 @@
+/**
+ @file uemf_print.c
+
+ @brief Functions for printing EMF records
+*/
+
+/*
+File: uemf_print.c
+Version: 0.0.22
+Date: 12-MAY-2020
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2020 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h> /* for offsetof() macro */
+#include <string.h>
+#include "uemf.h"
+#include "upmf_print.h"
+#include "uemf_safe.h"
+
+//! \cond
+#define UNUSED(x) (void)(x)
+/* This bit of code is used all over the place, so reduce it to a DEFINITION */
+#define IF_MEM_UNSAFE_PRINT_AND_RETURN(A,B,C) if(IS_MEM_UNSAFE(A,B,C)){printf(" record corruption HERE\n"); return; }
+
+/* one needed prototype */
+void U_swap4(void *ul, unsigned int count);
+//! \endcond
+
+/**
+ \brief calculate a CRC32 value for record
+ \returns CRC32 value calculated for record
+ \param record pointer to the first byte
+ \param Size number of bytes in the record
+
+Code based on example crc32b here:
+ http://www.hackersdelight.org/hdcodetxt/crc.c.txt
+*/
+uint32_t lu_crc32(const char *record, uint32_t Size){
+ const unsigned char *message = (const unsigned char *)record;
+ uint32_t i, j;
+ uint32_t crc, mask;
+
+ crc = 0xFFFFFFFF;
+ for(i=0;i<Size;i++){ // over all bytes
+ crc = crc ^ *message++;
+ for (j = 0; j < 8; j++) { // over all bits
+ mask = -(crc & 1);
+ crc = (crc >> 1) ^ (0xEDB88320 & mask);
+ }
+ }
+ return ~crc;
+}
+
+/**
+ \brief Print some number of hex bytes
+ \param buf pointer to the first byte
+ \param num number of bytes
+*/
+void hexbytes_print(uint8_t *buf,unsigned int num){
+ for(; num; num--,buf++){
+ printf("%2.2X",*buf);
+ }
+}
+
+
+/* **********************************************************************************************
+ These functions print standard objects used in the EMR records.
+ The low level ones do not append EOL.
+*********************************************************************************************** */
+
+
+
+/**
+ \brief Print a U_COLORREF object.
+ \param color U_COLORREF object
+*/
+void colorref_print(
+ U_COLORREF color
+ ){
+ printf("{%u,%u,%u} ",color.Red,color.Green,color.Blue);
+}
+
+
+/**
+ \brief Print a U_RGBQUAD object.
+ \param color U_RGBQUAD object
+*/
+void rgbquad_print(
+ U_RGBQUAD color
+ ){
+ printf("{%u,%u,%u,%u} ",color.Blue,color.Green,color.Red,color.Reserved);
+}
+
+/**
+ \brief Print rect and rectl objects from Upper Left and Lower Right corner points.
+ \param rect U_RECTL object
+*/
+void rectl_print(
+ U_RECTL rect
+ ){
+ printf("{%d,%d,%d,%d} ",rect.left,rect.top,rect.right,rect.bottom);
+}
+
+/**
+ \brief Print a U_SIZEL object.
+ \param sz U_SizeL object
+*/
+void sizel_print(
+ U_SIZEL sz
+ ){
+ printf("{%d,%d} ",sz.cx ,sz.cy);
+}
+
+/**
+ \brief Print a U_POINTL object
+ \param pt U_POINTL object
+*/
+void pointl_print(
+ U_POINTL pt
+ ){
+ printf("{%d,%d} ",pt.x ,pt.y);
+}
+
+/**
+ \brief Print a pointer to a U_POINT16 object
+ \param pt pointer to a U_POINT16 object
+ Warning - WMF data may contain unaligned U_POINT16, do not call
+ this routine with a pointer to such data!
+*/
+void point16_print(
+ U_POINT16 pt
+ ){
+ printf("{%d,%d} ",pt.x ,pt.y);
+}
+
+/**
+ \brief Print a U_LCS_GAMMA object
+ \param lg U_LCS_GAMMA object
+*/
+void lcs_gamma_print(
+ U_LCS_GAMMA lg
+ ){
+ uint8_t tmp;
+ tmp = lg.ignoreHi; printf("ignoreHi:%u ",tmp);
+ tmp = lg.intPart ; printf("intPart :%u ",tmp);
+ tmp = lg.fracPart; printf("fracPart:%u ",tmp);
+ tmp = lg.ignoreLo; printf("ignoreLo:%u ",tmp);
+}
+
+/**
+ \brief Print a U_LCS_GAMMARGB object
+ \param lgr U_LCS_GAMMARGB object
+*/
+void lcs_gammargb_print(
+ U_LCS_GAMMARGB lgr
+ ){
+ printf("lcsGammaRed:"); lcs_gamma_print(lgr.lcsGammaRed );
+ printf("lcsGammaGreen:"); lcs_gamma_print(lgr.lcsGammaGreen);
+ printf("lcsGammaBlue:"); lcs_gamma_print(lgr.lcsGammaBlue );
+}
+
+/**
+ \brief Print a U_TRIVERTEX object.
+ \param tv U_TRIVERTEX object.
+*/
+void trivertex_print(
+ U_TRIVERTEX tv
+ ){
+ printf("{{%d,%d},{%u,%u,%u,%u}} ",tv.x,tv.y,tv.Red,tv.Green,tv.Blue,tv.Alpha);
+}
+
+/**
+ \brief Print a U_GRADIENT3 object.
+ \param g3 U_GRADIENT3 object.
+*/
+void gradient3_print(
+ U_GRADIENT3 g3
+ ){
+ printf("{%u,%u,%u} ",g3.Vertex1,g3.Vertex2,g3.Vertex3);
+}
+
+/**
+ \brief Print a U_GRADIENT4 object.
+ \param g4 U_GRADIENT4 object.
+*/
+void gradient4_print(
+ U_GRADIENT4 g4
+ ){
+ printf("{%u,%u} ",g4.UpperLeft,g4.LowerRight);
+}
+
+/**
+ \brief Print a U_LOGBRUSH object.
+ \param lb U_LOGBRUSH object.
+*/
+void logbrush_print(
+ U_LOGBRUSH lb
+ ){
+ printf("lbStyle:0x%8.8X ", lb.lbStyle);
+ printf("lbColor:"); colorref_print(lb.lbColor);
+ printf("lbHatch:0x%8.8X ", lb.lbHatch);
+}
+
+/**
+ \brief Print a U_XFORM object.
+ \param xform U_XFORM object
+*/
+void xform_print(
+ U_XFORM xform
+ ){
+ printf("{%f,%f.%f,%f,%f,%f} ",xform.eM11,xform.eM12,xform.eM21,xform.eM22,xform.eDx,xform.eDy);
+}
+
+/**
+ \brief Print a U_CIEXYZ object
+ \param ciexyz U_CIEXYZ object
+*/
+void ciexyz_print(
+ U_CIEXYZ ciexyz
+ ){
+ printf("{%d,%d.%d} ",ciexyz.ciexyzX,ciexyz.ciexyzY,ciexyz.ciexyzZ);
+
+}
+
+/**
+ \brief Print a U_CIEXYZTRIPLE object
+ \param cie3 U_CIEXYZTRIPLE object
+*/
+void ciexyztriple_print(
+ U_CIEXYZTRIPLE cie3
+ ){
+ printf("{Red:"); ciexyz_print(cie3.ciexyzRed );
+ printf(", Green:"); ciexyz_print(cie3.ciexyzGreen);
+ printf(", Blue:"); ciexyz_print(cie3.ciexyzBlue );
+ printf("} ");
+}
+/**
+ \brief Print a U_LOGCOLORSPACEA object.
+ \param lcsa U_LOGCOLORSPACEA object
+*/
+void logcolorspacea_print(
+ U_LOGCOLORSPACEA lcsa
+ ){
+ printf("lcsSignature:%u ",lcsa.lcsSignature);
+ printf("lcsVersion:%u ", lcsa.lcsVersion );
+ printf("lcsSize:%u ", lcsa.lcsSize );
+ printf("lcsCSType:%d ", lcsa.lcsCSType );
+ printf("lcsIntent:%d ", lcsa.lcsIntent );
+ printf("lcsEndpoints:"); ciexyztriple_print(lcsa.lcsEndpoints);
+ printf("lcsGammaRGB: "); lcs_gammargb_print(lcsa.lcsGammaRGB );
+ printf("filename:%s ", lcsa.lcsFilename );
+}
+
+/**
+
+ \brief Print a U_LOGCOLORSPACEW object.
+ \param lcsa U_LOGCOLORSPACEW object
+*/
+void logcolorspacew_print(
+ U_LOGCOLORSPACEW lcsa
+ ){
+ char *string;
+ printf("lcsSignature:%d ",lcsa.lcsSignature);
+ printf("lcsVersion:%d ", lcsa.lcsVersion );
+ printf("lcsSize:%d ", lcsa.lcsSize );
+ printf("lcsCSType:%d ", lcsa.lcsCSType );
+ printf("lcsIntent:%d ", lcsa.lcsIntent );
+ printf("lcsEndpoints:"); ciexyztriple_print(lcsa.lcsEndpoints);
+ printf("lcsGammaRGB: "); lcs_gammargb_print(lcsa.lcsGammaRGB );
+ string = U_Utf16leToUtf8(lcsa.lcsFilename, U_MAX_PATH, NULL);
+ printf("filename:%s ", string );
+ free(string);
+}
+
+/**
+ \brief Print a U_PANOSE object.
+ \param panose U_PANOSE object
+*/
+void panose_print(
+ U_PANOSE panose
+ ){
+ printf("bFamilyType:%u ", panose.bFamilyType );
+ printf("bSerifStyle:%u ", panose.bSerifStyle );
+ printf("bWeight:%u ", panose.bWeight );
+ printf("bProportion:%u ", panose.bProportion );
+ printf("bContrast:%u ", panose.bContrast );
+ printf("bStrokeVariation:%u ",panose.bStrokeVariation);
+ printf("bArmStyle:%u ", panose.bArmStyle );
+ printf("bLetterform:%u ", panose.bLetterform );
+ printf("bMidline:%u ", panose.bMidline );
+ printf("bXHeight:%u ", panose.bXHeight );
+}
+
+/**
+ \brief Print a U_LOGFONT object.
+ \param lf U_LOGFONT object
+*/
+void logfont_print(
+ U_LOGFONT lf
+ ){
+ char *string;
+ printf("lfHeight:%d ", lf.lfHeight );
+ printf("lfWidth:%d ", lf.lfWidth );
+ printf("lfEscapement:%d ", lf.lfEscapement );
+ printf("lfOrientation:%d ", lf.lfOrientation );
+ printf("lfWeight:%d ", lf.lfWeight );
+ printf("lfItalic:0x%2.2X ", lf.lfItalic );
+ printf("lfUnderline:0x%2.2X ", lf.lfUnderline );
+ printf("lfStrikeOut:0x%2.2X ", lf.lfStrikeOut );
+ printf("lfCharSet:0x%2.2X ", lf.lfCharSet );
+ printf("lfOutPrecision:0x%2.2X ", lf.lfOutPrecision );
+ printf("lfClipPrecision:0x%2.2X ", lf.lfClipPrecision );
+ printf("lfQuality:0x%2.2X ", lf.lfQuality );
+ printf("lfPitchAndFamily:0x%2.2X ", lf.lfPitchAndFamily);
+ string = U_Utf16leToUtf8(lf.lfFaceName, U_LF_FACESIZE, NULL);
+ printf("lfFaceName:%s ", string );
+ free(string);
+}
+
+/**
+ \brief Print a U_LOGFONT_PANOSE object.
+ \return U_LOGFONT_PANOSE object
+*/
+void logfont_panose_print(
+ U_LOGFONT_PANOSE lfp
+ ){
+ char *string;
+ printf("elfLogFont:"); logfont_print(lfp.elfLogFont);
+ string = U_Utf16leToUtf8(lfp.elfFullName, U_LF_FULLFACESIZE, NULL);
+ printf("elfFullName:%s ", string );
+ free(string);
+ string = U_Utf16leToUtf8(lfp.elfStyle, U_LF_FACESIZE, NULL);
+ printf("elfStyle:%s ", string );
+ free(string);
+ printf("elfVersion:%u " ,lfp.elfVersion );
+ printf("elfStyleSize:%u " ,lfp.elfStyleSize);
+ printf("elfMatch:%u " ,lfp.elfMatch );
+ printf("elfReserved:%u " ,lfp.elfReserved );
+ printf("elfVendorId:"); hexbytes_print((uint8_t *)lfp.elfVendorId,U_ELF_VENDOR_SIZE); printf(" ");
+ printf("elfCulture:%u " ,lfp.elfCulture );
+ printf("elfPanose:"); panose_print(lfp.elfPanose);
+}
+
+/**
+ \brief Print a pointer to U_BITMAPINFOHEADER object.
+
+ This may be called indirectly from WMF _print routines, where problems could occur
+ if the data was passed as the struct or a pointer to the struct, as the struct may not
+ be aligned in memory.
+
+ \returns Actual number of color table entries.
+ \param Bmih pointer to a U_BITMAPINFOHEADER object
+*/
+int bitmapinfoheader_print(
+ const char *Bmih
+ ){
+ uint32_t utmp4;
+ int32_t tmp4;
+ int16_t tmp2;
+ int Colors, BitCount, Width, Height, RealColors;
+
+ /* DIB from a WMF may not be properly aligned on a 4 byte boundary, will be aligned on a 2 byte boundary */
+
+ memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biSize), 4); printf("biSize:%u " ,utmp4 );
+ memcpy(&tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biWidth), 4); printf("biWidth:%d " ,tmp4 );
+ Width = tmp4;
+ memcpy(&tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biHeight), 4); printf("biHeight:%d " ,tmp4 );
+ Height = tmp4;
+ memcpy(&tmp2, Bmih + offsetof(U_BITMAPINFOHEADER,biPlanes), 2); printf("biPlanes:%u " ,tmp2 );
+ memcpy(&tmp2, Bmih + offsetof(U_BITMAPINFOHEADER,biBitCount), 2); printf("biBitCount:%u " ,tmp2 );
+ BitCount = tmp2;
+ memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biCompression), 4); printf("biCompression:%u " ,utmp4 );
+ memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biSizeImage), 4); printf("biSizeImage:%u " ,utmp4 );
+ memcpy(&tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biXPelsPerMeter), 4); printf("biXPelsPerMeter:%d " ,tmp4 );
+ memcpy(&tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biYPelsPerMeter), 4); printf("biYPelsPerMeter:%d " ,tmp4 );
+ memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biClrUsed), 4); printf("biClrUsed:%u " ,utmp4 );
+ Colors = utmp4;
+ memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biClrImportant), 4); printf("biClrImportant:%u " ,utmp4 );
+ RealColors = get_real_color_icount(Colors, BitCount, Width, Height);
+ printf("ColorEntries:%d ",RealColors);
+ return(RealColors);
+}
+
+
+/**
+ \brief Print a Pointer to a U_BITMAPINFO object.
+ \param Bmi Pointer to a U_BITMAPINFO object
+ \param blimit Pointer to the first byte after after this record
+ This may be called from WMF _print routines, where problems could occur
+ if the data was passed as the struct or a pointer to the struct, as the struct may not
+ be aligned in memory.
+*/
+void bitmapinfo_print(
+ const char *Bmi,
+ const char *blimit
+ ){
+ int i,k;
+ int ClrUsed;
+ U_RGBQUAD BmiColor;
+ printf("BmiHeader: ");
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(Bmi, offsetof(U_BITMAPINFO,bmiHeader) + sizeof(U_BITMAPINFOHEADER), blimit);
+ ClrUsed = bitmapinfoheader_print(Bmi + offsetof(U_BITMAPINFO,bmiHeader));
+ if(ClrUsed){
+ k= offsetof(U_BITMAPINFO,bmiColors);
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(Bmi, offsetof(U_BITMAPINFO,bmiColors) + ClrUsed*sizeof(U_RGBQUAD), blimit);
+ for(i=0; i<ClrUsed; i++, k+= sizeof(U_RGBQUAD)){
+ memcpy(&BmiColor, Bmi+k, sizeof(U_RGBQUAD));
+ printf("%d:",i); rgbquad_print(BmiColor);
+ }
+ }
+}
+
+/**
+ \brief Print a U_BLEND object.
+ \param blend a U_BLEND object
+*/
+void blend_print(
+ U_BLEND blend
+ ){
+ printf("Operation:%u " ,blend.Operation);
+ printf("Flags:%u " ,blend.Flags );
+ printf("Global:%u " ,blend.Global );
+ printf("Op:%u " ,blend.Op );
+}
+
+/**
+ \brief Print a pointer to a U_EXTLOGPEN object.
+ \param elp PU_EXTLOGPEN object
+*/
+void extlogpen_print(
+ PU_EXTLOGPEN elp
+ ){
+ unsigned int i;
+ U_STYLEENTRY *elpStyleEntry;
+ printf("elpPenStyle:0x%8.8X " ,elp->elpPenStyle );
+ printf("elpWidth:%u " ,elp->elpWidth );
+ printf("elpBrushStyle:0x%8.8X " ,elp->elpBrushStyle);
+ printf("elpColor"); colorref_print(elp->elpColor);
+ printf("elpHatch:%d " ,elp->elpHatch );
+ printf("elpNumEntries:%u " ,elp->elpNumEntries);
+ if(elp->elpNumEntries){
+ printf("elpStyleEntry:");
+ elpStyleEntry = (uint32_t *) elp->elpStyleEntry;
+ for(i=0;i<elp->elpNumEntries;i++){
+ printf("%d:%u ",i,elpStyleEntry[i]);
+ }
+ }
+}
+
+/**
+ \brief Print a U_LOGPEN object.
+ \param lp U_LOGPEN object
+
+*/
+void logpen_print(
+ U_LOGPEN lp
+ ){
+ printf("lopnStyle:0x%8.8X " ,lp.lopnStyle );
+ printf("lopnWidth:"); pointl_print( lp.lopnWidth );
+ printf("lopnColor:"); colorref_print(lp.lopnColor );
+}
+
+/**
+ \brief Print a U_LOGPLTNTRY object.
+ \param lpny Ignore U_LOGPLTNTRY object.
+*/
+void logpltntry_print(
+ U_LOGPLTNTRY lpny
+ ){
+ printf("peReserved:%u " ,lpny.peReserved );
+ printf("peRed:%u " ,lpny.peRed );
+ printf("peGreen:%u " ,lpny.peGreen );
+ printf("peBlue:%u " ,lpny.peBlue );
+}
+
+/**
+ \brief Print a pointer to a U_LOGPALETTE object.
+ \param lp Pointer to a U_LOGPALETTE object.
+*/
+void logpalette_print(
+ PU_LOGPALETTE lp
+ ){
+ int i;
+ PU_LOGPLTNTRY palPalEntry;
+ printf("palVersion:%u ", lp->palVersion );
+ printf("palNumEntries:%u ", lp->palNumEntries );
+ if(lp->palNumEntries){
+ palPalEntry = (PU_LOGPLTNTRY) &(lp->palPalEntry);
+ for(i=0;i<lp->palNumEntries;i++){
+ printf("%d:",i); logpltntry_print(palPalEntry[i]);
+ }
+ }
+}
+
+/**
+ \brief Print a U_RGNDATAHEADER object.
+ \param rdh U_RGNDATAHEADER object
+*/
+void rgndataheader_print(
+ U_RGNDATAHEADER rdh
+ ){
+ printf("dwSize:%u ", rdh.dwSize );
+ printf("iType:%u ", rdh.iType );
+ printf("nCount:%u ", rdh.nCount );
+ printf("nRgnSize:%u ", rdh.nRgnSize );
+ printf("rclBounds:"); rectl_print(rdh.rclBounds );
+}
+
+/**
+ \brief Print a pointer to a U_RGNDATA object.
+ \param rd pointer to a U_RGNDATA object.
+ \param limit pointer that sets upper limit for data examination
+*/
+void rgndata_print(
+ PU_RGNDATA rd,
+ const char *blimit
+ ){
+ unsigned int i;
+ PU_RECTL rects;
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(rd, sizeof(U_RGNDATAHEADER), blimit);
+ printf("rdh: "); rgndataheader_print(rd->rdh ); printf(" rects: ");
+ if(rd->rdh.nCount){
+ rects = (PU_RECTL) &(rd->Buffer);
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(rects, rd->rdh.nCount * sizeof(U_RECTL), blimit);
+ for(i=0;i<rd->rdh.nCount;i++){
+ printf("%d:",i); rectl_print(rects[i]);
+ }
+ }
+}
+
+/**
+ \brief Print a U_COLORADJUSTMENT object.
+ \param ca U_COLORADJUSTMENT object.
+*/
+void coloradjustment_print(
+ U_COLORADJUSTMENT ca
+ ){
+ printf("caSize:%u " ,ca.caSize );
+ printf("caFlags:0x%4.4X " ,ca.caFlags );
+ printf("caIlluminantIndex:%u " ,ca.caIlluminantIndex);
+ printf("caRedGamma:%u " ,ca.caRedGamma );
+ printf("caGreenGamma:%u " ,ca.caGreenGamma );
+ printf("caBlueGamma:%u " ,ca.caBlueGamma );
+ printf("caReferenceBlack:%u " ,ca.caReferenceBlack );
+ printf("caReferenceWhite:%u " ,ca.caReferenceWhite );
+ printf("caContrast:%d " ,ca.caContrast );
+ printf("caBrightness:%d " ,ca.caBrightness );
+ printf("caColorfulness:%d " ,ca.caColorfulness );
+ printf("caRedGreenTint:%d " ,ca.caRedGreenTint );
+}
+
+/**
+ \brief Print a U_PIXELFORMATDESCRIPTOR object.
+ \param pfd U_PIXELFORMATDESCRIPTOR object
+*/
+void pixelformatdescriptor_print(
+ U_PIXELFORMATDESCRIPTOR pfd
+ ){
+ printf("nSize:%u " ,pfd.nSize );
+ printf("nVersion:%u " ,pfd.nVersion );
+ printf("dwFlags:0x%8.8X " ,pfd.dwFlags );
+ printf("iPixelType:%u " ,pfd.iPixelType );
+ printf("cColorBits:%u " ,pfd.cColorBits );
+ printf("cRedBits:%u " ,pfd.cRedBits );
+ printf("cRedShift:%u " ,pfd.cRedShift );
+ printf("cGreenBits:%u " ,pfd.cGreenBits );
+ printf("cGreenShift:%u " ,pfd.cGreenShift );
+ printf("cBlueBits:%u " ,pfd.cBlueBits );
+ printf("cBlueShift:%u " ,pfd.cBlueShift );
+ printf("cAlphaBits:%u " ,pfd.cAlphaBits );
+ printf("cAlphaShift:%u " ,pfd.cAlphaShift );
+ printf("cAccumBits:%u " ,pfd.cAccumBits );
+ printf("cAccumRedBits:%u " ,pfd.cAccumRedBits );
+ printf("cAccumGreenBits:%u " ,pfd.cAccumGreenBits );
+ printf("cAccumBlueBits:%u " ,pfd.cAccumBlueBits );
+ printf("cAccumAlphaBits:%u " ,pfd.cAccumAlphaBits );
+ printf("cDepthBits:%u " ,pfd.cDepthBits );
+ printf("cStencilBits:%u " ,pfd.cStencilBits );
+ printf("cAuxBuffers:%u " ,pfd.cAuxBuffers );
+ printf("iLayerType:%u " ,pfd.iLayerType );
+ printf("bReserved:%u " ,pfd.bReserved );
+ printf("dwLayerMask:%u " ,pfd.dwLayerMask );
+ printf("dwVisibleMask:%u " ,pfd.dwVisibleMask );
+ printf("dwDamageMask:%u " ,pfd.dwDamageMask );
+}
+
+/**
+ \brief Print a Pointer to a U_EMRTEXT record
+ \param emt Pointer to a U_EMRTEXT record
+ \param record Pointer to the start of the record which contains this U_ERMTEXT
+ \param blimit Pointer to the first byte after after this record
+ \param type 0 for 8 bit character, anything else for 16
+*/
+void emrtext_print(
+ const char *emt,
+ const char *record,
+ const char *blimit,
+ int type
+ ){
+ unsigned int i,off;
+ char *string;
+ PU_EMRTEXT pemt = (PU_EMRTEXT) emt;
+ // constant part
+ printf("ptlReference:"); pointl_print(pemt->ptlReference);
+ printf("nChars:%u " ,pemt->nChars );
+ printf("offString:%u " ,pemt->offString );
+ if(pemt->offString){
+ if(!type){
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(record, pemt->offString + pemt->nChars*sizeof(char), blimit);
+ printf("string8:<%s> ",record + pemt->offString);
+ }
+ else {
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(record, pemt->offString + pemt->nChars*2*sizeof(char), blimit);
+ string = U_Utf16leToUtf8((uint16_t *)(record + pemt->offString), pemt->nChars, NULL);
+ printf("string16:<%s> ",string);
+ free(string);
+ }
+ }
+ printf("fOptions:0x%8.8X " ,pemt->fOptions );
+ off = sizeof(U_EMRTEXT);
+ if(!(pemt->fOptions & U_ETO_NO_RECT)){
+ printf("rcl"); rectl_print( *((U_RECTL *)(emt+off)) );
+ off += sizeof(U_RECTL);
+ }
+ printf("offDx:%u " , *((U_OFFDX *)(emt+off)) ); off = *(U_OFFDX *)(emt+off);
+ printf("Dx:");
+ for(i=0; i<pemt->nChars; i++, off+=sizeof(uint32_t)){
+ printf("%d:", *((uint32_t *)(record+off)) );
+ }
+}
+
+
+
+
+// hide these from Doxygen
+//! @cond
+/* **********************************************************************************************
+These functions contain shared code used by various U_EMR*_print functions. These should NEVER be called
+by end user code and to further that end prototypes are NOT provided and they are hidden from Doxygen.
+
+
+ These are (mostly) ordered by U_EMR_* index number.
+
+ The exceptions:
+ void core3_print(const char *name, const char *label, const char *contents)
+ void core7_print(const char *name, const char *field1, const char *field2, const char *contents)
+ void core8_print(const char *name, const char *contents, int type)
+
+
+*********************************************************************************************** */
+
+
+// Functions with the same form starting with U_EMRPOLYBEZIER_print
+void core1_print(const char *name, const char *contents){
+ unsigned int i;
+ UNUSED(name);
+ PU_EMRPOLYLINETO pEmr = (PU_EMRPOLYLINETO) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRPOLYBEZIER)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
+ printf(" cptl: %d\n",pEmr->cptl );
+ printf(" Points: ");
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(pEmr->aptl, pEmr->cptl*sizeof(U_POINTL), blimit);
+ for(i=0;i<pEmr->cptl; i++){
+ printf("[%d]:",i); pointl_print(pEmr->aptl[i]);
+ }
+ printf("\n");
+}
+
+// Functions with the same form starting with U_EMRPOLYPOLYLINE_print
+void core2_print(const char *name, const char *contents){
+ unsigned int i;
+ UNUSED(name);
+ PU_EMRPOLYPOLYGON pEmr = (PU_EMRPOLYPOLYGON) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRPOLYPOLYGON)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
+ printf(" nPolys: %d\n",pEmr->nPolys );
+ printf(" cptl: %d\n",pEmr->cptl );
+ printf(" Counts: ");
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(pEmr->aPolyCounts, pEmr->nPolys*sizeof(U_POLYCOUNTS), blimit);
+ for(i=0;i<pEmr->nPolys; i++){
+ printf(" [%d]:%d ",i,pEmr->aPolyCounts[i] );
+ }
+ printf("\n");
+ PU_POINTL paptl = (PU_POINTL)((char *)pEmr->aPolyCounts + sizeof(uint32_t)* pEmr->nPolys);
+ printf(" Points: ");
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(paptl, pEmr->cptl*sizeof(U_POINTL), blimit);
+ for(i=0;i<pEmr->cptl; i++){
+ printf(" [%d]:",i); pointl_print(paptl[i]);
+ }
+ printf("\n");
+}
+
+
+// Functions with the same form starting with U_EMRSETMAPMODE_print
+void core3_print(const char *name, const char *label, const char *contents){
+ UNUSED(name);
+ /* access violation is impossible for these because there are no counts or offsets */
+ PU_EMRSETMAPMODE pEmr = (PU_EMRSETMAPMODE)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSETMAPMODE)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ if(!strcmp(label,"crColor:")){
+ printf(" %-15s ",label); colorref_print(*(U_COLORREF *)&(pEmr->iMode)); printf("\n");
+ }
+ else if(!strcmp(label,"iMode:")){
+ printf(" %-15s 0x%8.8X\n",label,pEmr->iMode );
+ }
+ else {
+ printf(" %-15s %d\n",label,pEmr->iMode );
+ }
+}
+
+// Functions taking a single U_RECT or U_RECTL, starting with U_EMRELLIPSE_print, also U_EMRFILLPATH_print,
+void core4_print(const char *name, const char *contents){
+ UNUSED(name);
+ PU_EMRELLIPSE pEmr = (PU_EMRELLIPSE)( contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRELLIPSE)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ printf(" rclBox: "); rectl_print(pEmr->rclBox); printf("\n");
+}
+
+// Functions with the same form starting with U_EMRPOLYBEZIER16_print
+void core6_print(const char *name, const char *contents){
+ UNUSED(name);
+ unsigned int i;
+ PU_EMRPOLYBEZIER16 pEmr = (PU_EMRPOLYBEZIER16) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRPOLYBEZIER16)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
+ printf(" cpts: %d\n",pEmr->cpts );
+ printf(" Points: ");
+ PU_POINT16 papts = (PU_POINT16)(&(pEmr->apts));
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(papts, pEmr->cpts*sizeof(U_POINT16), blimit);
+ for(i=0; i<pEmr->cpts; i++){
+ printf(" [%d]:",i); point16_print(papts[i]);
+ }
+ printf("\n");
+}
+
+
+// Records with the same form starting with U_EMRSETWINDOWEXTEX_print
+// CAREFUL, in the _set equivalents all functions with two uint32_t values are mapped here, and member names differ, consequently
+// print routines must supply the names of the two arguments. These cannot be null. If the second one is
+// empty the values are printed as a pair {x,y}, otherwise each is printed with its own label on a separate line.
+void core7_print(const char *name, const char *field1, const char *field2, const char *contents){
+ UNUSED(name);
+ PU_EMRGENERICPAIR pEmr = (PU_EMRGENERICPAIR) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRGENERICPAIR)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ if(*field2){
+ printf(" %-15s %d\n",field1,pEmr->pair.x);
+ printf(" %-15s %d\n",field2,pEmr->pair.y);
+ }
+ else {
+ printf(" %-15s {%d,%d}\n",field1,pEmr->pair.x,pEmr->pair.y);
+ }
+}
+
+// For U_EMREXTTEXTOUTA and U_EMREXTTEXTOUTW, type=0 for the first one
+void core8_print(const char *name, const char *contents, int type){
+ UNUSED(name);
+ PU_EMREXTTEXTOUTA pEmr = (PU_EMREXTTEXTOUTA) (contents);
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" iGraphicsMode: %u\n",pEmr->iGraphicsMode );
+ printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
+ printf(" exScale: %f\n",pEmr->exScale );
+ printf(" eyScale: %f\n",pEmr->eyScale );
+ printf(" emrtext: ");
+ emrtext_print(contents + sizeof(U_EMREXTTEXTOUTA) - sizeof(U_EMRTEXT),contents,blimit,type);
+ printf("\n");
+}
+
+// Functions that take a rect and a pair of points, starting with U_EMRARC_print
+void core9_print(const char *name, const char *contents){
+ UNUSED(name);
+ PU_EMRARC pEmr = (PU_EMRARC) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRARC)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ printf(" rclBox: "); rectl_print(pEmr->rclBox); printf("\n");
+ printf(" ptlStart: "); pointl_print(pEmr->ptlStart); printf("\n");
+ printf(" ptlEnd: "); pointl_print(pEmr->ptlEnd); printf("\n");
+}
+
+// Functions with the same form starting with U_EMRPOLYPOLYLINE16_print
+void core10_print(const char *name, const char *contents){
+ UNUSED(name);
+ unsigned int i;
+ PU_EMRPOLYPOLYLINE16 pEmr = (PU_EMRPOLYPOLYLINE16) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRPOLYPOLYLINE16)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
+ printf(" nPolys: %d\n",pEmr->nPolys );
+ printf(" cpts: %d\n",pEmr->cpts );
+ printf(" Counts: ");
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(&(pEmr->aPolyCounts), pEmr->nPolys*sizeof(U_POLYCOUNTS), blimit);
+ for(i=0;i<pEmr->nPolys; i++){
+ printf(" [%d]:%d ",i,pEmr->aPolyCounts[i] );
+ }
+ printf("\n");
+ printf(" Points: ");
+ PU_POINT16 papts = (PU_POINT16)((char *)pEmr->aPolyCounts + pEmr->nPolys*sizeof(U_POLYCOUNTS) );
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(papts, pEmr->cpts*sizeof(U_POINT16), blimit);
+ for(i=0; i<pEmr->cpts; i++){
+ printf(" [%d]:",i); point16_print(papts[i]);
+ }
+ printf("\n");
+
+}
+
+// Functions with the same form starting with U_EMRINVERTRGN_print and U_EMRPAINTRGN_print,
+void core11_print(const char *name, const char *contents){
+ UNUSED(name);
+ PU_EMRINVERTRGN pEmr = (PU_EMRINVERTRGN) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRINVERTRGN)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
+ printf(" cbRgnData: %d\n",pEmr->cbRgnData);
+ printf(" RegionData:");
+ const char *minptr = MAKE_MIN_PTR(((const char *) &pEmr->RgnData + pEmr->cbRgnData),blimit);
+ rgndata_print(pEmr->RgnData, minptr);
+ printf("\n");
+}
+
+
+// common code for U_EMRCREATEMONOBRUSH_print and U_EMRCREATEDIBPATTERNBRUSHPT_print,
+void core12_print(const char *name, const char *contents){
+ UNUSED(name);
+ PU_EMRCREATEMONOBRUSH pEmr = (PU_EMRCREATEMONOBRUSH) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRCREATEMONOBRUSH)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" ihBrush: %u\n",pEmr->ihBrush );
+ printf(" iUsage : %u\n",pEmr->iUsage );
+ printf(" offBmi : %u\n",pEmr->offBmi );
+ printf(" cbBmi : %u\n",pEmr->cbBmi );
+ if(pEmr->cbBmi){
+ printf(" bitmap:");
+ bitmapinfo_print(contents + pEmr->offBmi, blimit);
+ printf("\n");
+ }
+ printf(" offBits: %u\n",pEmr->offBits );
+ printf(" cbBits : %u\n",pEmr->cbBits );
+}
+
+// common code for U_EMRALPHABLEND_print and U_EMRTRANSPARENTBLT_print,
+void core13_print(const char *name, const char *contents){
+ UNUSED(name);
+ PU_EMRALPHABLEND pEmr = (PU_EMRALPHABLEND) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRALPHABLEND)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
+ printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n");
+ printf(" cDest: "); pointl_print(pEmr->cDest); printf("\n");
+ printf(" Blend: "); blend_print(pEmr->Blend); printf("\n");
+ printf(" Src: "); pointl_print(pEmr->Src); printf("\n");
+ printf(" xformSrc: "); xform_print( pEmr->xformSrc); printf("\n");
+ printf(" crBkColorSrc: "); colorref_print( pEmr->crBkColorSrc); printf("\n");
+ printf(" iUsageSrc: %u\n",pEmr->iUsageSrc );
+ printf(" offBmiSrc: %u\n",pEmr->offBmiSrc );
+ printf(" cbBmiSrc: %u\n",pEmr->cbBmiSrc );
+ if(pEmr->cbBmiSrc){
+ printf(" bitmap:");
+ bitmapinfo_print(contents + pEmr->offBmiSrc, blimit);
+ printf("\n");
+ }
+ printf(" offBitsSrc: %u\n",pEmr->offBitsSrc );
+ printf(" cbBitsSrc: %u\n",pEmr->cbBitsSrc );
+}
+//! @endcond
+
+/* **********************************************************************************************
+These are the core EMR functions, each creates a particular type of record.
+All return these records via a char* pointer, which is NULL if the call failed.
+They are listed in order by the corresponding U_EMR_* index number.
+*********************************************************************************************** */
+
+/**
+ \brief Print a pointer to a U_EMR_whatever record which has not been implemented.
+ \param name name of this type of record
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRNOTIMPLEMENTED_print(const char *name, const char *contents){
+ UNUSED(name);
+ UNUSED(contents);
+ printf(" Not Implemented!\n");
+}
+
+// U_EMRHEADER 1
+/**
+ \brief Print a pointer to a U_EMR_HEADER record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRHEADER_print(const char *contents){
+ char *string;
+ int p1len;
+
+ PU_EMRHEADER pEmr = (PU_EMRHEADER)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRHEADER)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
+ printf(" rclFrame: "); rectl_print( pEmr->rclFrame); printf("\n");
+ printf(" dSignature: 0x%8.8X\n", pEmr->dSignature );
+ printf(" nVersion: 0x%8.8X\n", pEmr->nVersion );
+ printf(" nBytes: %d\n", pEmr->nBytes );
+ printf(" nRecords: %d\n", pEmr->nRecords );
+ printf(" nHandles: %d\n", pEmr->nHandles );
+ printf(" sReserved: %d\n", pEmr->sReserved );
+ printf(" nDescription: %d\n", pEmr->nDescription );
+ printf(" offDescription: %d\n", pEmr->offDescription);
+ if(pEmr->offDescription){
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, pEmr->offDescription + pEmr->nDescription*2*sizeof(char), blimit);
+ string = U_Utf16leToUtf8((uint16_t *)((char *) pEmr + pEmr->offDescription), pEmr->nDescription, NULL);
+ printf(" Desc. A: %s\n",string);
+ free(string);
+ p1len = 2 + 2*wchar16len((uint16_t *)((char *) pEmr + pEmr->offDescription));
+ string = U_Utf16leToUtf8((uint16_t *)((char *) pEmr + pEmr->offDescription + p1len), pEmr->nDescription, NULL);
+ printf(" Desc. B: %s\n",string);
+ free(string);
+ }
+ printf(" nPalEntries: %d\n", pEmr->nPalEntries );
+ printf(" szlDevice: {%d,%d} \n", pEmr->szlDevice.cx,pEmr->szlDevice.cy);
+ printf(" szlMillimeters: {%d,%d} \n", pEmr->szlMillimeters.cx,pEmr->szlMillimeters.cy);
+ if((pEmr->nDescription && (pEmr->offDescription >= 100)) ||
+ (!pEmr->offDescription && pEmr->emr.nSize >= 100)
+ ){
+ printf(" cbPixelFormat: %d\n", pEmr->cbPixelFormat );
+ printf(" offPixelFormat: %d\n", pEmr->offPixelFormat);
+ if(pEmr->cbPixelFormat){
+ printf(" PFD:");
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, pEmr->offPixelFormat + sizeof(U_PIXELFORMATDESCRIPTOR), blimit);
+ pixelformatdescriptor_print( *(PU_PIXELFORMATDESCRIPTOR) (contents + pEmr->offPixelFormat));
+ printf("\n");
+ }
+ printf(" bOpenGL: %d\n",pEmr->bOpenGL );
+ if((pEmr->nDescription && (pEmr->offDescription >= 108)) ||
+ (pEmr->cbPixelFormat && (pEmr->offPixelFormat >=108)) ||
+ (!pEmr->offDescription && !pEmr->cbPixelFormat && pEmr->emr.nSize >= 108)
+ ){
+ printf(" szlMicrometers: {%d,%d} \n", pEmr->szlMicrometers.cx,pEmr->szlMicrometers.cy);
+ }
+ }
+}
+
+// U_EMRPOLYBEZIER 2
+/**
+ \brief Print a pointer to a U_EMR_POLYBEZIER record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRPOLYBEZIER_print(const char *contents){
+ core1_print("U_EMRPOLYBEZIER", contents);
+}
+
+// U_EMRPOLYGON 3
+/**
+ \brief Print a pointer to a U_EMR_POLYGON record.
+ \param contents pointer to a buffer holding all EMR records
+ */
+void U_EMRPOLYGON_print(const char *contents){
+ core1_print("U_EMRPOLYGON", contents);
+}
+
+
+// U_EMRPOLYLINE 4
+/**
+ \brief Print a pointer to a U_EMR_POLYLINE record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRPOLYLINE_print(const char *contents){
+ core1_print("U_EMRPOLYLINE", contents);
+}
+
+// U_EMRPOLYBEZIERTO 5
+/**
+ \brief Print a pointer to a U_EMR_POLYBEZIERTO record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRPOLYBEZIERTO_print(const char *contents){
+ core1_print("U_EMRPOLYBEZIERTO", contents);
+}
+
+// U_EMRPOLYLINETO 6
+/**
+ \brief Print a pointer to a U_EMR_POLYLINETO record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRPOLYLINETO_print(const char *contents){
+ core1_print("U_EMRPOLYLINETO", contents);
+}
+
+// U_EMRPOLYPOLYLINE 7
+/**
+ \brief Print a pointer to a U_EMR_POLYPOLYLINE record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRPOLYPOLYLINE_print(const char *contents){
+ core2_print("U_EMRPOLYPOLYLINE", contents);
+}
+
+// U_EMRPOLYPOLYGON 8
+/**
+ \brief Print a pointer to a U_EMR_POLYPOLYGON record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRPOLYPOLYGON_print(const char *contents){
+ core2_print("U_EMRPOLYPOLYGON", contents);
+}
+
+// U_EMRSETWINDOWEXTEX 9
+/**
+ \brief Print a pointer to a U_EMR_SETWINDOWEXTEX record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETWINDOWEXTEX_print(const char *contents){
+ core7_print("U_EMRSETWINDOWEXTEX", "szlExtent:","",contents);
+}
+
+// U_EMRSETWINDOWORGEX 10
+/**
+ \brief Print a pointer to a U_EMR_SETWINDOWORGEX record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETWINDOWORGEX_print(const char *contents){
+ core7_print("U_EMRSETWINDOWORGEX", "ptlOrigin:","",contents);
+}
+
+// U_EMRSETVIEWPORTEXTEX 11
+/**
+ \brief Print a pointer to a U_EMR_SETVIEWPORTEXTEX record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETVIEWPORTEXTEX_print(const char *contents){
+ core7_print("U_EMRSETVIEWPORTEXTEX", "szlExtent:","",contents);
+}
+
+// U_EMRSETVIEWPORTORGEX 12
+/**
+ \brief Print a pointer to a U_EMR_SETVIEWPORTORGEX record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETVIEWPORTORGEX_print(const char *contents){
+ core7_print("U_EMRSETVIEWPORTORGEX", "ptlOrigin:","",contents);
+}
+
+// U_EMRSETBRUSHORGEX 13
+/**
+ \brief Print a pointer to a U_EMR_SETBRUSHORGEX record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETBRUSHORGEX_print(const char *contents){
+ core7_print("U_EMRSETBRUSHORGEX", "ptlOrigin:","",contents);
+}
+
+// U_EMREOF 14
+/**
+ \brief Print a pointer to a U_EMR_EOF record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMREOF_print(const char *contents){
+ PU_EMREOF pEmr = (PU_EMREOF)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMREOF)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ printf(" cbPalEntries: %u\n", pEmr->cbPalEntries );
+ printf(" offPalEntries: %u\n", pEmr->offPalEntries);
+ if(pEmr->cbPalEntries){
+ printf(" PE:");
+ logpalette_print( (PU_LOGPALETTE)(contents + pEmr->offPalEntries));
+ printf("\n");
+ }
+}
+
+
+// U_EMRSETPIXELV 15
+/**
+ \brief Print a pointer to a U_EMR_SETPIXELV record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETPIXELV_print(const char *contents){
+ PU_EMRSETPIXELV pEmr = (PU_EMRSETPIXELV)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSETPIXELV)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ printf(" ptlPixel: "); pointl_print( pEmr->ptlPixel); printf("\n");
+ printf(" crColor: "); colorref_print(pEmr->crColor); printf("\n");
+}
+
+
+// U_EMRSETMAPPERFLAGS 16
+/**
+ \brief Print a pointer to a U_EMR_SETMAPPERFLAGS record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETMAPPERFLAGS_print(const char *contents){
+ PU_EMRSETMAPPERFLAGS pEmr = (PU_EMRSETMAPPERFLAGS)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSETMAPPERFLAGS)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ printf(" dwFlags: 0x%8.8X\n",pEmr->dwFlags);
+}
+
+
+// U_EMRSETMAPMODE 17
+/**
+ \brief Print a pointer to a U_EMR_SETMAPMODE record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETMAPMODE_print(const char *contents){
+ core3_print("U_EMRSETMAPMODE", "iMode:", contents);
+}
+
+// U_EMRSETBKMODE 18
+/**
+ \brief Print a pointer to a U_EMR_SETBKMODE record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETBKMODE_print(const char *contents){
+ core3_print("U_EMRSETBKMODE", "iMode:", contents);
+}
+
+// U_EMRSETPOLYFILLMODE 19
+/**
+ \brief Print a pointer to a U_EMR_SETPOLYFILLMODE record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETPOLYFILLMODE_print(const char *contents){
+ core3_print("U_EMRSETPOLYFILLMODE", "iMode:", contents);
+}
+
+// U_EMRSETROP2 20
+/**
+ \brief Print a pointer to a U_EMR_SETROP2 record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETROP2_print(const char *contents){
+ core3_print("U_EMRSETROP2", "dwRop:", contents);
+}
+
+// U_EMRSETSTRETCHBLTMODE 21
+/**
+ \brief Print a pointer to a U_EMR_SETSTRETCHBLTMODE record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETSTRETCHBLTMODE_print(const char *contents){
+ core3_print("U_EMRSETSTRETCHBLTMODE", "iMode:", contents);
+}
+
+// U_EMRSETTEXTALIGN 22
+/**
+ \brief Print a pointer to a U_EMR_SETTEXTALIGN record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETTEXTALIGN_print(const char *contents){
+ core3_print("U_EMRSETTEXTALIGN", "iMode:", contents);
+}
+
+// U_EMRSETCOLORADJUSTMENT 23
+/**
+ \brief Print a pointer to a U_EMR_SETCOLORADJUSTMENT record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETCOLORADJUSTMENT_print(const char *contents){
+ PU_EMRSETCOLORADJUSTMENT pEmr = (PU_EMRSETCOLORADJUSTMENT)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSETCOLORADJUSTMENT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ printf(" ColorAdjustment:");
+ coloradjustment_print(pEmr->ColorAdjustment);
+ printf("\n");
+}
+
+// U_EMRSETTEXTCOLOR 24
+/**
+ \brief Print a pointer to a U_EMR_SETTEXTCOLOR record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETTEXTCOLOR_print(const char *contents){
+ core3_print("U_EMRSETTEXTCOLOR", "crColor:", contents);
+}
+
+// U_EMRSETBKCOLOR 25
+/**
+ \brief Print a pointer to a U_EMR_SETBKCOLOR record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETBKCOLOR_print(const char *contents){
+ core3_print("U_EMRSETBKCOLOR", "crColor:", contents);
+}
+
+// U_EMROFFSETCLIPRGN 26
+/**
+ \brief Print a pointer to a U_EMR_OFFSETCLIPRGN record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMROFFSETCLIPRGN_print(const char *contents){
+ core7_print("U_EMROFFSETCLIPRGN", "ptl:","",contents);
+}
+
+// U_EMRMOVETOEX 27
+/**
+ \brief Print a pointer to a U_EMR_MOVETOEX record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRMOVETOEX_print(const char *contents){
+ core7_print("U_EMRMOVETOEX", "ptl:","",contents);
+}
+
+// U_EMRSETMETARGN 28
+/**
+ \brief Print a pointer to a U_EMR_SETMETARGN record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETMETARGN_print(const char *contents){
+ UNUSED(contents);
+}
+
+// U_EMREXCLUDECLIPRECT 29
+/**
+ \brief Print a pointer to a U_EMR_EXCLUDECLIPRECT record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMREXCLUDECLIPRECT_print(const char *contents){
+ core4_print("U_EMREXCLUDECLIPRECT", contents);
+}
+
+// U_EMRINTERSECTCLIPRECT 30
+/**
+ \brief Print a pointer to a U_EMR_INTERSECTCLIPRECT record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRINTERSECTCLIPRECT_print(const char *contents){
+ core4_print("U_EMRINTERSECTCLIPRECT", contents);
+}
+
+// U_EMRSCALEVIEWPORTEXTEX 31
+/**
+ \brief Print a pointer to a U_EMR_SCALEVIEWPORTEXTEX record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSCALEVIEWPORTEXTEX_print(const char *contents){
+ core4_print("U_EMRSCALEVIEWPORTEXTEX", contents);
+}
+
+
+// U_EMRSCALEWINDOWEXTEX 32
+/**
+ \brief Print a pointer to a U_EMR_SCALEWINDOWEXTEX record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSCALEWINDOWEXTEX_print(const char *contents){
+ core4_print("U_EMRSCALEWINDOWEXTEX", contents);
+}
+
+// U_EMRSAVEDC 33
+/**
+ \brief Print a pointer to a U_EMR_SAVEDC record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSAVEDC_print(const char *contents){
+ UNUSED(contents);
+}
+
+// U_EMRRESTOREDC 34
+/**
+ \brief Print a pointer to a U_EMR_RESTOREDC record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRRESTOREDC_print(const char *contents){
+ core3_print("U_EMRRESTOREDC", "iRelative:", contents);
+}
+
+// U_EMRSETWORLDTRANSFORM 35
+/**
+ \brief Print a pointer to a U_EMR_SETWORLDTRANSFORM record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETWORLDTRANSFORM_print(const char *contents){
+ PU_EMRSETWORLDTRANSFORM pEmr = (PU_EMRSETWORLDTRANSFORM)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSETWORLDTRANSFORM)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ printf(" xform:");
+ xform_print(pEmr->xform);
+ printf("\n");
+}
+
+// U_EMRMODIFYWORLDTRANSFORM 36
+/**
+ \brief Print a pointer to a U_EMR_MODIFYWORLDTRANSFORM record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRMODIFYWORLDTRANSFORM_print(const char *contents){
+ PU_EMRMODIFYWORLDTRANSFORM pEmr = (PU_EMRMODIFYWORLDTRANSFORM)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRMODIFYWORLDTRANSFORM)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ printf(" xform:");
+ xform_print(pEmr->xform);
+ printf("\n");
+ printf(" iMode: %u\n", pEmr->iMode );
+}
+
+// U_EMRSELECTOBJECT 37
+/**
+ \brief Print a pointer to a U_EMR_SELECTOBJECT record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSELECTOBJECT_print(const char *contents){
+ PU_EMRSELECTOBJECT pEmr = (PU_EMRSELECTOBJECT)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSELECTOBJECT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ if(pEmr->ihObject & U_STOCK_OBJECT){
+ printf(" StockObject: 0x%8.8X\n", pEmr->ihObject );
+ }
+ else {
+ printf(" ihObject: %u\n", pEmr->ihObject );
+ }
+}
+
+// U_EMRCREATEPEN 38
+/**
+ \brief Print a pointer to a U_EMR_CREATEPEN record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRCREATEPEN_print(const char *contents){
+ PU_EMRCREATEPEN pEmr = (PU_EMRCREATEPEN)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRCREATEPEN)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ printf(" ihPen: %u\n", pEmr->ihPen );
+ printf(" lopn: "); logpen_print(pEmr->lopn); printf("\n");
+}
+
+// U_EMRCREATEBRUSHINDIRECT 39
+/**
+ \brief Print a pointer to a U_EMR_CREATEBRUSHINDIRECT record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRCREATEBRUSHINDIRECT_print(const char *contents){
+ PU_EMRCREATEBRUSHINDIRECT pEmr = (PU_EMRCREATEBRUSHINDIRECT)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRCREATEBRUSHINDIRECT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ printf(" ihBrush: %u\n", pEmr->ihBrush );
+ printf(" lb: "); logbrush_print(pEmr->lb); printf("\n");
+}
+
+// U_EMRDELETEOBJECT 40
+/**
+ \brief Print a pointer to a U_EMR_DELETEOBJECT record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRDELETEOBJECT_print(const char *contents){
+ PU_EMRDELETEOBJECT pEmr = (PU_EMRDELETEOBJECT)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRDELETEOBJECT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ printf(" ihObject: %u\n", pEmr->ihObject );
+}
+
+// U_EMRANGLEARC 41
+/**
+ \brief Print a pointer to a U_EMR_ANGLEARC record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRANGLEARC_print(const char *contents){
+ PU_EMRANGLEARC pEmr = (PU_EMRANGLEARC)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRANGLEARC)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ printf(" ptlCenter: "), pointl_print(pEmr->ptlCenter ); printf("\n");
+ printf(" nRadius: %u\n", pEmr->nRadius );
+ printf(" eStartAngle: %f\n", pEmr->eStartAngle );
+ printf(" eSweepAngle: %f\n", pEmr->eSweepAngle );
+}
+
+// U_EMRELLIPSE 42
+/**
+ \brief Print a pointer to a U_EMR_ELLIPSE record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRELLIPSE_print(const char *contents){
+ core4_print("U_EMRELLIPSE", contents);
+}
+
+// U_EMRRECTANGLE 43
+/**
+ \brief Print a pointer to a U_EMR_RECTANGLE record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRRECTANGLE_print(const char *contents){
+ core4_print("U_EMRRECTANGLE", contents);
+}
+
+// U_EMRROUNDRECT 44
+/**
+ \brief Print a pointer to a U_EMR_ROUNDRECT record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRROUNDRECT_print(const char *contents){
+ PU_EMRROUNDRECT pEmr = (PU_EMRROUNDRECT)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRROUNDRECT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ printf(" rclBox: "), rectl_print(pEmr->rclBox ); printf("\n");
+ printf(" szlCorner: "), sizel_print(pEmr->szlCorner ); printf("\n");
+}
+
+// U_EMRARC 45
+/**
+ \brief Print a pointer to a U_EMR_ARC record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRARC_print(const char *contents){
+ core9_print("U_EMRARC", contents);
+}
+
+// U_EMRCHORD 46
+/**
+ \brief Print a pointer to a U_EMR_CHORD record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRCHORD_print(const char *contents){
+ core9_print("U_EMRCHORD", contents);
+}
+
+// U_EMRPIE 47
+/**
+ \brief Print a pointer to a U_EMR_PIE record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRPIE_print(const char *contents){
+ core9_print("U_EMRPIE", contents);
+}
+
+// U_EMRSELECTPALETTE 48
+/**
+ \brief Print a pointer to a U_EMR_SELECTPALETTE record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSELECTPALETTE_print(const char *contents){
+ core3_print("U_EMRSELECTPALETTE", "ihPal:", contents);
+}
+
+// U_EMRCREATEPALETTE 49
+/**
+ \brief Print a pointer to a U_EMR_CREATEPALETTE record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRCREATEPALETTE_print(const char *contents){
+ PU_EMRCREATEPALETTE pEmr = (PU_EMRCREATEPALETTE)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRCREATEPALETTE)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ printf(" ihPal: %u\n",pEmr->ihPal);
+ printf(" lgpl: "), logpalette_print( (PU_LOGPALETTE)&(pEmr->lgpl) ); printf("\n");
+}
+
+// U_EMRSETPALETTEENTRIES 50
+/**
+ \brief Print a pointer to a U_EMR_SETPALETTEENTRIES record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETPALETTEENTRIES_print(const char *contents){
+ unsigned int i;
+ PU_EMRSETPALETTEENTRIES pEmr = (PU_EMRSETPALETTEENTRIES)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSETPALETTEENTRIES)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" ihPal: %u\n",pEmr->ihPal);
+ printf(" iStart: %u\n",pEmr->iStart);
+ printf(" cEntries: %u\n",pEmr->cEntries);
+ if(pEmr->cEntries){
+ printf(" PLTEntries:");
+ PU_LOGPLTNTRY aPalEntries = (PU_LOGPLTNTRY) &(pEmr->aPalEntries);
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(aPalEntries, pEmr->cEntries*sizeof(U_LOGPLTNTRY), blimit);
+ for(i=0; i<pEmr->cEntries; i++){
+ printf("%d:",i); logpltntry_print(aPalEntries[i]);
+ }
+ printf("\n");
+ }
+}
+
+// U_EMRRESIZEPALETTE 51
+/**
+ \brief Print a pointer to a U_EMR_RESIZEPALETTE record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRRESIZEPALETTE_print(const char *contents){
+ core7_print("U_EMRRESIZEPALETTE", "ihPal:","cEntries",contents);
+}
+
+// U_EMRREALIZEPALETTE 52
+/**
+ \brief Print a pointer to a U_EMR_REALIZEPALETTE record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRREALIZEPALETTE_print(const char *contents){
+ UNUSED(contents);
+}
+
+// U_EMREXTFLOODFILL 53
+/**
+ \brief Print a pointer to a U_EMR_EXTFLOODFILL record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMREXTFLOODFILL_print(const char *contents){
+ PU_EMREXTFLOODFILL pEmr = (PU_EMREXTFLOODFILL)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMREXTFLOODFILL)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ printf(" ptlStart: "); pointl_print(pEmr->ptlStart); printf("\n");
+ printf(" crColor: "); colorref_print(pEmr->crColor); printf("\n");
+ printf(" iMode: %u\n",pEmr->iMode);
+}
+
+// U_EMRLINETO 54
+/**
+ \brief Print a pointer to a U_EMR_LINETO record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRLINETO_print(const char *contents){
+ core7_print("U_EMRLINETO", "ptl:","",contents);
+}
+
+// U_EMRARCTO 55
+/**
+ \brief Print a pointer to a U_EMR_ARCTO record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRARCTO_print(const char *contents){
+ core9_print("U_EMRARCTO", contents);
+}
+
+// U_EMRPOLYDRAW 56
+/**
+ \brief Print a pointer to a U_EMR_POLYDRAW record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRPOLYDRAW_print(const char *contents){
+ unsigned int i;
+ PU_EMRPOLYDRAW pEmr = (PU_EMRPOLYDRAW)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRPOLYDRAW)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
+ printf(" cptl: %d\n",pEmr->cptl );
+ printf(" Points: ");
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(pEmr->aptl, pEmr->cptl*sizeof(U_POINTL), blimit);
+ for(i=0;i<pEmr->cptl; i++){
+ printf(" [%d]:",i);
+ pointl_print(pEmr->aptl[i]);
+ }
+ printf("\n");
+ printf(" Types: ");
+ const char *abTypes = (const char *) pEmr->aptl + pEmr->cptl*sizeof(U_POINTL);
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(abTypes, pEmr->cptl, blimit);
+ for(i=0;i<pEmr->cptl; i++){
+ printf(" [%d]:%u ",i,((uint8_t *)abTypes)[i]);
+ }
+ printf("\n");
+}
+
+// U_EMRSETARCDIRECTION 57
+/**
+ \brief Print a pointer to a U_EMR_SETARCDIRECTION record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETARCDIRECTION_print(const char *contents){
+ core3_print("U_EMRSETARCDIRECTION","arcDirection:", contents);
+}
+
+// U_EMRSETMITERLIMIT 58
+/**
+ \brief Print a pointer to a U_EMR_SETMITERLIMIT record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETMITERLIMIT_print(const char *contents){
+ core3_print("U_EMRSETMITERLIMIT", "eMiterLimit:", contents);
+}
+
+
+// U_EMRBEGINPATH 59
+/**
+ \brief Print a pointer to a U_EMR_BEGINPATH record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRBEGINPATH_print(const char *contents){
+ UNUSED(contents);
+}
+
+// U_EMRENDPATH 60
+/**
+ \brief Print a pointer to a U_EMR_ENDPATH record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRENDPATH_print(const char *contents){
+ UNUSED(contents);
+}
+
+// U_EMRCLOSEFIGURE 61
+/**
+ \brief Print a pointer to a U_EMR_CLOSEFIGURE record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRCLOSEFIGURE_print(const char *contents){
+ UNUSED(contents);
+}
+
+// U_EMRFILLPATH 62
+/**
+ \brief Print a pointer to a U_EMR_FILLPATH record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRFILLPATH_print(const char *contents){
+ core4_print("U_EMRFILLPATH", contents);
+}
+
+// U_EMRSTROKEANDFILLPATH 63
+/**
+ \brief Print a pointer to a U_EMR_STROKEANDFILLPATH record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSTROKEANDFILLPATH_print(const char *contents){
+ core4_print("U_EMRSTROKEANDFILLPATH", contents);
+}
+
+// U_EMRSTROKEPATH 64
+/**
+ \brief Print a pointer to a U_EMR_STROKEPATH record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSTROKEPATH_print(const char *contents){
+ core4_print("U_EMRSTROKEPATH", contents);
+}
+
+// U_EMRFLATTENPATH 65
+/**
+ \brief Print a pointer to a U_EMR_FLATTENPATH record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRFLATTENPATH_print(const char *contents){
+ UNUSED(contents);
+}
+
+// U_EMRWIDENPATH 66
+/**
+ \brief Print a pointer to a U_EMR_WIDENPATH record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRWIDENPATH_print(const char *contents){
+ UNUSED(contents);
+}
+
+// U_EMRSELECTCLIPPATH 67
+/**
+ \brief Print a pointer to a U_EMR_SELECTCLIPPATH record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSELECTCLIPPATH_print(const char *contents){
+ core3_print("U_EMRSELECTCLIPPATH", "iMode:", contents);
+}
+
+// U_EMRABORTPATH 68
+/**
+ \brief Print a pointer to a U_EMR_ABORTPATH record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRABORTPATH_print(const char *contents){
+ UNUSED(contents);
+}
+
+// U_EMRUNDEF69 69
+#define U_EMRUNDEF69_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRUNDEF69",A) //!< Not implemented.
+
+// U_EMRCOMMENT 70 Comment (any binary data, interpretation is program specific)
+/**
+ \brief Print a pointer to a U_EMR_COMMENT record.
+ \param contents pointer to a location in memory holding the comment record
+ \param off offset in bytes to the first byte in this record (needed for EMF+ record printing)
+
+ EMF+ records, if any, are stored in EMF comment records.
+*/
+void U_EMRCOMMENT_print(const char *contents, size_t off){
+ char *string;
+ char *src;
+ uint32_t cIdent,cIdent2,cbData;
+ size_t loff;
+ int recsize;
+ static int recnum=0;
+
+ PU_EMRCOMMENT pEmr = (PU_EMRCOMMENT)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRCOMMENT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+
+ /* There are several different types of comments */
+
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, sizeof(U_EMRCOMMENT), blimit);
+ cbData = pEmr->cbData;
+ printf(" cbData: %d\n",cbData );
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, sizeof(U_EMR) + sizeof(U_CBDATA) + cbData, blimit);
+ src = (char *)&(pEmr->Data); // default
+ if(cbData >= 4){
+ /* Since the comment is just a big bag of bytes the emf endian code cannot safely touch
+ any of its payload. This is the only record type with that limitation. So the record
+ may appear at this stage with the wrong endianness. Try to determine
+ what the contents are even if more byte swapping is required. */
+ cIdent = *(uint32_t *)(src);
+ if(U_BYTE_SWAP){ U_swap4(&(cIdent),1); }
+ if( cIdent == U_EMR_COMMENT_PUBLIC ){
+ printf(" cIdent: Public\n");
+ PU_EMRCOMMENT_PUBLIC pEmrp = (PU_EMRCOMMENT_PUBLIC) pEmr;
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, sizeof(U_EMRCOMMENT_PUBLIC), blimit);
+ cIdent2 = pEmrp->pcIdent;
+ if(U_BYTE_SWAP){ U_swap4(&(cIdent2),1); }
+ printf(" pcIdent: 0x%8.8x\n",cIdent2);
+ src = (char *)&(pEmrp->Data);
+ cbData -= 8;
+ }
+ else if(cIdent == U_EMR_COMMENT_SPOOL ){
+ printf(" cIdent: Spool\n");
+ PU_EMRCOMMENT_SPOOL pEmrs = (PU_EMRCOMMENT_SPOOL) pEmr;
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, sizeof(U_EMRCOMMENT_SPOOL), blimit);
+ cIdent2 = pEmrs->esrIdent;
+ if(U_BYTE_SWAP){ U_swap4(&(cIdent2),1); }
+ printf(" esrIdent: 0x%8.8x\n",cIdent2);
+ src = (char *)&(pEmrs->Data);
+ cbData -= 8;
+ }
+ else if(cIdent == U_EMR_COMMENT_EMFPLUSRECORD){
+ printf(" cIdent: EMF+\n");
+ PU_EMRCOMMENT_EMFPLUS pEmrpl = (PU_EMRCOMMENT_EMFPLUS) pEmr;
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, sizeof(U_EMRCOMMENT_EMFPLUS), blimit);
+ src = (char *)&(pEmrpl->Data);
+ loff = 16; /* Header size of the header part of an EMF+ comment record */
+ while(loff < cbData + 12){ // EMF+ records may not fill the entire comment, cbData value includes cIdent, but not U_EMR or cbData
+ recsize = U_pmf_onerec_print(src, blimit, recnum, loff + off);
+ if(recsize==0){ break; }
+ else if(recsize<0){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ loff += recsize;
+ src += recsize;
+ recnum++;
+ }
+ return;
+ }
+ else {
+ printf(" cIdent: not (Public or Spool or EMF+)\n");
+ }
+ }
+ if(cbData){ // The data may not be printable, but try it just in case
+ string = malloc(cbData + 1);
+ (void)strncpy(string, src, cbData);
+ string[cbData] = '\0'; // it might not be terminated - it might not even be text!
+ printf(" Data: <%s>\n",string);
+ free(string);
+ }
+}
+
+// U_EMRFILLRGN 71
+/**
+ \brief Print a pointer to a U_EMR_FILLRGN record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRFILLRGN_print(const char *contents){
+ PU_EMRFILLRGN pEmr = (PU_EMRFILLRGN)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRFILLRGN)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
+ printf(" cbRgnData: %u\n",pEmr->cbRgnData);
+ printf(" ihBrush: %u\n",pEmr->ihBrush);
+ const char *minptr = MAKE_MIN_PTR(((const char *) &pEmr->RgnData + pEmr->cbRgnData + sizeof(U_RGNDATAHEADER)),blimit);
+ printf(" RegionData: "); rgndata_print(pEmr->RgnData, minptr); printf("\n");
+}
+
+// U_EMRFRAMERGN 72
+/**
+ \brief Print a pointer to a U_EMR_FRAMERGN record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRFRAMERGN_print(const char *contents){
+ PU_EMRFRAMERGN pEmr = (PU_EMRFRAMERGN)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRFRAMERGN)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" rclBounds: "); rectl_print(pEmr->rclBounds); printf("\n");
+ printf(" cbRgnData: %u\n",pEmr->cbRgnData);
+ printf(" ihBrush: %u\n",pEmr->ihBrush);
+ printf(" szlStroke: "), sizel_print(pEmr->szlStroke ); printf("\n");
+ const char *minptr = MAKE_MIN_PTR(((const char *) &pEmr->RgnData + pEmr->cbRgnData),blimit);
+ printf(" RegionData: "); rgndata_print(pEmr->RgnData, minptr); printf("\n");
+}
+
+// U_EMRINVERTRGN 73
+/**
+ \brief Print a pointer to a U_EMR_INVERTRGN record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRINVERTRGN_print(const char *contents){
+ core11_print("U_EMRINVERTRGN", contents);
+}
+
+// U_EMRPAINTRGN 74
+/**
+ \brief Print a pointer to a U_EMR_PAINTRGN record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRPAINTRGN_print(const char *contents){
+ core11_print("U_EMRPAINTRGN", contents);
+}
+
+// U_EMREXTSELECTCLIPRGN 75
+/**
+ \brief Print a pointer to a U_EMR_EXTSELECTCLIPRGN record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMREXTSELECTCLIPRGN_print(const char *contents){
+ PU_EMREXTSELECTCLIPRGN pEmr = (PU_EMREXTSELECTCLIPRGN) (contents);
+ if(pEmr->emr.nSize < U_SIZE_EMREXTSELECTCLIPRGN){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" cbRgnData: %u\n",pEmr->cbRgnData);
+ printf(" iMode: %u\n",pEmr->iMode);
+ if(pEmr->iMode == U_RGN_COPY && !pEmr->cbRgnData){
+ printf(" RegionData: none (Clip region becomes NULL)\n");
+ }
+ else {
+ const char *minptr = MAKE_MIN_PTR(((const char *) &pEmr->RgnData + pEmr->cbRgnData),blimit);
+ printf(" RegionData: "); rgndata_print(pEmr->RgnData, minptr); printf("\n");
+ }
+
+}
+
+// U_EMRBITBLT 76
+/**
+ \brief Print a pointer to a U_EMR_BITBLT record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRBITBLT_print(const char *contents){
+ PU_EMRBITBLT pEmr = (PU_EMRBITBLT) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRBITBLT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
+ printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n");
+ printf(" cDest: "); pointl_print(pEmr->cDest); printf("\n");
+ printf(" dwRop : 0x%8.8X\n", pEmr->dwRop );
+ printf(" Src: "); pointl_print(pEmr->Src); printf("\n");
+ printf(" xformSrc: "); xform_print( pEmr->xformSrc); printf("\n");
+ printf(" crBkColorSrc: "); colorref_print( pEmr->crBkColorSrc); printf("\n");
+ printf(" iUsageSrc: %u\n", pEmr->iUsageSrc );
+ printf(" offBmiSrc: %u\n", pEmr->offBmiSrc );
+ printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc );
+ if(pEmr->cbBmiSrc){
+ printf(" bitmap: ");
+ bitmapinfo_print(contents + pEmr->offBmiSrc, blimit);
+ printf("\n");
+ }
+ printf(" offBitsSrc: %u\n", pEmr->offBitsSrc );
+ printf(" cbBitsSrc: %u\n", pEmr->cbBitsSrc );
+}
+
+// U_EMRSTRETCHBLT 77
+/**
+ \brief Print a pointer to a U_EMR_STRETCHBLT record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSTRETCHBLT_print(const char *contents){
+ PU_EMRSTRETCHBLT pEmr = (PU_EMRSTRETCHBLT) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSTRETCHBLT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
+ printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n");
+ printf(" cDest: "); pointl_print(pEmr->cDest); printf("\n");
+ printf(" dwRop : 0x%8.8X\n", pEmr->dwRop );
+ printf(" Src: "); pointl_print(pEmr->Src); printf("\n");
+ printf(" xformSrc: "); xform_print( pEmr->xformSrc); printf("\n");
+ printf(" crBkColorSrc: "); colorref_print( pEmr->crBkColorSrc); printf("\n");
+ printf(" iUsageSrc: %u\n", pEmr->iUsageSrc );
+ printf(" offBmiSrc: %u\n", pEmr->offBmiSrc );
+ printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc );
+ if(pEmr->cbBmiSrc){
+ printf(" bitmap: ");
+ bitmapinfo_print(contents + pEmr->offBmiSrc, blimit);
+ printf("\n");
+ }
+ printf(" offBitsSrc: %u\n", pEmr->offBitsSrc );
+ printf(" cbBitsSrc: %u\n", pEmr->cbBitsSrc );
+ printf(" cSrc: "); pointl_print(pEmr->cSrc); printf("\n");
+}
+
+// U_EMRMASKBLT 78
+/**
+ \brief Print a pointer to a U_EMR_MASKBLT record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRMASKBLT_print(const char *contents){
+ PU_EMRMASKBLT pEmr = (PU_EMRMASKBLT) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRMASKBLT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
+ printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n");
+ printf(" cDest: "); pointl_print(pEmr->cDest); printf("\n");
+ printf(" dwRop : 0x%8.8X\n", pEmr->dwRop );
+ printf(" Src: "); pointl_print(pEmr->Src); printf("\n");
+ printf(" xformSrc: "); xform_print( pEmr->xformSrc); printf("\n");
+ printf(" crBkColorSrc: "); colorref_print( pEmr->crBkColorSrc); printf("\n");
+ printf(" iUsageSrc: %u\n", pEmr->iUsageSrc );
+ printf(" offBmiSrc: %u\n", pEmr->offBmiSrc );
+ printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc );
+ if(pEmr->cbBmiSrc){
+ printf(" Src bitmap: ");
+ bitmapinfo_print(contents + pEmr->offBmiSrc, blimit);
+ printf("\n");
+ }
+ printf(" offBitsSrc: %u\n", pEmr->offBitsSrc );
+ printf(" cbBitsSrc: %u\n", pEmr->cbBitsSrc );
+ printf(" Mask: "); pointl_print(pEmr->Mask); printf("\n");
+ printf(" iUsageMask: %u\n", pEmr->iUsageMask );
+ printf(" offBmiMask: %u\n", pEmr->offBmiMask );
+ printf(" cbBmiMask: %u\n", pEmr->cbBmiMask );
+ if(pEmr->cbBmiMask){
+ printf(" Mask bitmap: ");
+ bitmapinfo_print(contents + pEmr->offBmiMask, blimit);
+ printf("\n");
+ }
+ printf(" offBitsMask: %u\n", pEmr->offBitsMask );
+ printf(" cbBitsMask: %u\n", pEmr->cbBitsMask );
+}
+
+// U_EMRPLGBLT 79
+/**
+ \brief Print a pointer to a U_EMR_PLGBLT record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRPLGBLT_print(const char *contents){
+ PU_EMRPLGBLT pEmr = (PU_EMRPLGBLT) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRPLGBLT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
+ printf(" aptlDst(UL): "); pointl_print(pEmr->aptlDst[0]); printf("\n");
+ printf(" aptlDst(UR): "); pointl_print(pEmr->aptlDst[1]); printf("\n");
+ printf(" aptlDst(LL): "); pointl_print(pEmr->aptlDst[2]); printf("\n");
+ printf(" Src: "); pointl_print(pEmr->Src); printf("\n");
+ printf(" cSrc: "); pointl_print(pEmr->cSrc); printf("\n");
+ printf(" xformSrc: "); xform_print( pEmr->xformSrc); printf("\n");
+ printf(" crBkColorSrc: "); colorref_print( pEmr->crBkColorSrc); printf("\n");
+ printf(" iUsageSrc: %u\n", pEmr->iUsageSrc );
+ printf(" offBmiSrc: %u\n", pEmr->offBmiSrc );
+ printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc );
+ if(pEmr->cbBmiSrc){
+ printf(" Src bitmap: ");
+ bitmapinfo_print(contents + pEmr->offBmiSrc, blimit);
+ printf("\n");
+ }
+ printf(" offBitsSrc: %u\n", pEmr->offBitsSrc );
+ printf(" cbBitsSrc: %u\n", pEmr->cbBitsSrc );
+ printf(" Mask: "); pointl_print(pEmr->Mask); printf("\n");
+ printf(" iUsageMsk: %u\n", pEmr->iUsageMask );
+ printf(" offBmiMask: %u\n", pEmr->offBmiMask );
+ printf(" cbBmiMask: %u\n", pEmr->cbBmiMask );
+ if(pEmr->cbBmiMask){
+ printf(" Mask bitmap: ");
+ bitmapinfo_print(contents + pEmr->offBmiMask, blimit);
+ printf("\n");
+ }
+ printf(" offBitsMask: %u\n", pEmr->offBitsMask );
+ printf(" cbBitsMask: %u\n", pEmr->cbBitsMask );
+}
+
+// U_EMRSETDIBITSTODEVICE 80
+/**
+ \brief Print a pointer to a U_EMRSETDIBITSTODEVICE record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETDIBITSTODEVICE_print(const char *contents){
+ PU_EMRSETDIBITSTODEVICE pEmr = (PU_EMRSETDIBITSTODEVICE) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSETDIBITSTODEVICE)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
+ printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n");
+ printf(" Src: "); pointl_print(pEmr->Src); printf("\n");
+ printf(" cSrc: "); pointl_print(pEmr->cSrc); printf("\n");
+ printf(" offBmiSrc: %u\n", pEmr->offBmiSrc );
+ printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc );
+ if(pEmr->cbBmiSrc){
+ printf(" Src bitmap: ");
+ bitmapinfo_print(contents + pEmr->offBmiSrc, blimit);
+ printf("\n");
+ }
+ printf(" offBitsSrc: %u\n", pEmr->offBitsSrc );
+ printf(" cbBitsSrc: %u\n", pEmr->cbBitsSrc );
+ printf(" iUsageSrc: %u\n", pEmr->iUsageSrc );
+ printf(" iStartScan: %u\n", pEmr->iStartScan );
+ printf(" cScans : %u\n", pEmr->cScans );
+}
+
+// U_EMRSTRETCHDIBITS 81
+/**
+ \brief Print a pointer to a U_EMR_STRETCHDIBITS record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSTRETCHDIBITS_print(const char *contents){
+ PU_EMRSTRETCHDIBITS pEmr = (PU_EMRSTRETCHDIBITS) (contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSTRETCHDIBITS)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
+ printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n");
+ printf(" Src: "); pointl_print(pEmr->Src); printf("\n");
+ printf(" cSrc: "); pointl_print(pEmr->cSrc); printf("\n");
+ printf(" offBmiSrc: %u\n", pEmr->offBmiSrc );
+ printf(" cbBmiSrc: %u\n", pEmr->cbBmiSrc );
+ if(pEmr->cbBmiSrc){
+ printf(" Src bitmap: ");
+ bitmapinfo_print(contents + pEmr->offBmiSrc, blimit);
+ printf("\n");
+ }
+ printf(" offBitsSrc: %u\n", pEmr->offBitsSrc );
+ printf(" cbBitsSrc: %u\n", pEmr->cbBitsSrc );
+ printf(" iUsageSrc: %u\n", pEmr->iUsageSrc );
+ printf(" dwRop : 0x%8.8X\n", pEmr->dwRop );
+ printf(" cDest: "); pointl_print(pEmr->cDest); printf("\n");
+}
+
+// U_EMREXTCREATEFONTINDIRECTW_print 82
+/**
+ \brief Print a pointer to a U_EMR_EXTCREATEFONTINDIRECTW record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMREXTCREATEFONTINDIRECTW_print(const char *contents){
+ PU_EMREXTCREATEFONTINDIRECTW pEmr = (PU_EMREXTCREATEFONTINDIRECTW) (contents);
+ if(pEmr->emr.nSize < U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT){ // smallest variant
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" ihFont: %u\n",pEmr->ihFont );
+ printf(" Font: ");
+ if(pEmr->emr.nSize == U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT_PANOSE){ // holds logfont_panose
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(&(pEmr->elfw), sizeof(U_PANOSE), blimit);
+ logfont_panose_print(pEmr->elfw);
+ }
+ else { // holds logfont or logfontExDv. The latter isn't supported but it starts with logfont, so use that
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(&(pEmr->elfw), sizeof(U_LOGFONT), blimit);
+ logfont_print( *(PU_LOGFONT) &(pEmr->elfw));
+ }
+ printf("\n");
+}
+
+// U_EMREXTTEXTOUTA 83
+/**
+ \brief Print a pointer to a U_EMR_EXTTEXTOUTA record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMREXTTEXTOUTA_print(const char *contents){
+ core8_print("U_EMREXTTEXTOUTA", contents, 0);
+}
+
+// U_EMREXTTEXTOUTW 84
+/**
+ \brief Print a pointer to a U_EMR_EXTTEXTOUTW record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMREXTTEXTOUTW_print(const char *contents){
+ core8_print("U_EMREXTTEXTOUTW", contents, 1);
+}
+
+// U_EMRPOLYBEZIER16 85
+/**
+ \brief Print a pointer to a U_EMR_POLYBEZIER16 record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRPOLYBEZIER16_print(const char *contents){
+ core6_print("U_EMRPOLYBEZIER16", contents);
+}
+
+// U_EMRPOLYGON16 86
+/**
+ \brief Print a pointer to a U_EMR_POLYGON16 record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRPOLYGON16_print(const char *contents){
+ core6_print("U_EMRPOLYGON16", contents);
+}
+
+// U_EMRPOLYLINE16 87
+/**
+ \brief Print a pointer to a U_EMR_POLYLINE16 record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRPOLYLINE16_print(const char *contents){
+ core6_print("U_EMRPOLYLINE16", contents);
+}
+
+// U_EMRPOLYBEZIERTO16 88
+/**
+ \brief Print a pointer to a U_EMR_POLYBEZIERTO16 record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRPOLYBEZIERTO16_print(const char *contents){
+ core6_print("U_EMRPOLYBEZIERTO16", contents);
+}
+
+// U_EMRPOLYLINETO16 89
+/**
+ \brief Print a pointer to a U_EMR_POLYLINETO16 record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRPOLYLINETO16_print(const char *contents){
+ core6_print("U_EMRPOLYLINETO16", contents);
+}
+
+// U_EMRPOLYPOLYLINE16 90
+/**
+ \brief Print a pointer to a U_EMR_POLYPOLYLINE16 record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRPOLYPOLYLINE16_print(const char *contents){
+ core10_print("U_EMRPOLYPOLYLINE16", contents);
+}
+
+// U_EMRPOLYPOLYGON16 91
+/**
+ \brief Print a pointer to a U_EMR_POLYPOLYGON16 record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRPOLYPOLYGON16_print(const char *contents){
+ core10_print("U_EMRPOLYPOLYGON16", contents);
+}
+
+
+// U_EMRPOLYDRAW16 92
+/**
+ \brief Print a pointer to a U_EMR_POLYDRAW16 record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRPOLYDRAW16_print(const char *contents){
+ unsigned int i;
+ PU_EMRPOLYDRAW16 pEmr = (PU_EMRPOLYDRAW16)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRPOLYDRAW16)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
+ printf(" cpts: %d\n",pEmr->cpts );
+ printf(" Points: ");
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(pEmr->apts, pEmr->cpts*sizeof(U_POINT16), blimit);
+ for(i=0;i<pEmr->cpts; i++){
+ printf(" [%d]:",i);
+ point16_print(pEmr->apts[i]);
+ }
+ printf("\n");
+ printf(" Types: ");
+ const char *abTypes = (const char *) pEmr->apts + pEmr->cpts*sizeof(U_POINT16);
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(abTypes, pEmr->cpts, blimit);
+ for(i=0;i<pEmr->cpts; i++){
+ printf(" [%d]:%u ",i,((uint8_t *)abTypes)[i]);
+ }
+ printf("\n");
+}
+
+// U_EMRCREATEMONOBRUSH 93
+/**
+ \brief Print a pointer to a U_EMR_CREATEMONOBRUSH record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRCREATEMONOBRUSH_print(const char *contents){
+ core12_print("U_EMRCREATEMONOBRUSH", contents);
+}
+
+// U_EMRCREATEDIBPATTERNBRUSHPT_print 94
+/**
+ \brief Print a pointer to a U_EMR_CREATEDIBPATTERNBRUSHPT record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRCREATEDIBPATTERNBRUSHPT_print(const char *contents){
+ core12_print("U_EMRCREATEDIBPATTERNBRUSHPT", contents);
+}
+
+
+// U_EMREXTCREATEPEN 95
+/**
+ \brief Print a pointer to a U_EMR_EXTCREATEPEN record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMREXTCREATEPEN_print(const char *contents){
+ PU_EMREXTCREATEPEN pEmr = (PU_EMREXTCREATEPEN)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMREXTCREATEPEN)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" ihPen: %u\n", pEmr->ihPen );
+ printf(" offBmi: %u\n", pEmr->offBmi );
+ printf(" cbBmi: %u\n", pEmr->cbBmi );
+ if(pEmr->cbBmi){
+ printf(" bitmap: ");
+ bitmapinfo_print(contents + pEmr->offBmi, blimit);
+ printf("\n");
+ }
+ printf(" offBits: %u\n", pEmr->offBits );
+ printf(" cbBits: %u\n", pEmr->cbBits );
+ printf(" elp: "); extlogpen_print((PU_EXTLOGPEN) &(pEmr->elp)); printf("\n");
+}
+
+// U_EMRPOLYTEXTOUTA 96 NOT IMPLEMENTED, denigrated after Windows NT
+#define U_EMRPOLYTEXTOUTA_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRPOLYTEXTOUTA",A) //!< Not implemented.
+// U_EMRPOLYTEXTOUTW 97 NOT IMPLEMENTED, denigrated after Windows NT
+#define U_EMRPOLYTEXTOUTW_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRPOLYTEXTOUTW",A) //!< Not implemented.
+
+// U_EMRSETICMMODE 98
+/**
+ \brief Print a pointer to a U_EMR_SETICMMODE record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETICMMODE_print(const char *contents){
+ core3_print("U_EMRSETICMMODE", "iMode:", contents);
+}
+
+// U_EMRCREATECOLORSPACE 99
+/**
+ \brief Print a pointer to a U_EMR_CREATECOLORSPACE record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRCREATECOLORSPACE_print(const char *contents){
+ PU_EMRCREATECOLORSPACE pEmr = (PU_EMRCREATECOLORSPACE)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRCREATECOLORSPACE)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ printf(" ihCS: %u\n", pEmr->ihCS );
+ printf(" ColorSpace: "); logcolorspacea_print(pEmr->lcs); printf("\n");
+}
+
+// U_EMRSETCOLORSPACE 100
+/**
+ \brief Print a pointer to a U_EMR_SETCOLORSPACE record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETCOLORSPACE_print(const char *contents){
+ core3_print("U_EMRSETCOLORSPACE", "ihCS:", contents);
+}
+
+// U_EMRDELETECOLORSPACE 101
+/**
+ \brief Print a pointer to a U_EMR_DELETECOLORSPACE record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRDELETECOLORSPACE_print(const char *contents){
+ core3_print("U_EMRDELETECOLORSPACE", "ihCS:", contents);
+}
+
+// U_EMRGLSRECORD 102 Not implemented
+#define U_EMRGLSRECORD_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRGLSRECORD",A) //!< Not implemented.
+// U_EMRGLSBOUNDEDRECORD 103 Not implemented
+#define U_EMRGLSBOUNDEDRECORD_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRGLSBOUNDEDRECORD",A) //!< Not implemented.
+
+// U_EMRPIXELFORMAT 104
+/**
+ \brief Print a pointer to a U_EMR_PIXELFORMAT record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRPIXELFORMAT_print(const char *contents){
+ PU_EMRPIXELFORMAT pEmr = (PU_EMRPIXELFORMAT)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRPIXELFORMAT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(&(pEmr->pfd), sizeof(U_PIXELFORMATDESCRIPTOR), blimit);
+ printf(" Pfd: "); pixelformatdescriptor_print(pEmr->pfd); printf("\n");
+}
+
+// U_EMRDRAWESCAPE 105 Not implemented
+#define U_EMRDRAWESCAPE_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRDRAWESCAPE",A) //!< Not implemented.
+// U_EMREXTESCAPE 106 Not implemented
+#define U_EMREXTESCAPE_print(A) U_EMRNOTIMPLEMENTED_print("U_EMREXTESCAPE",A) //!< Not implemented.
+// U_EMRUNDEF107 107 Not implemented
+#define U_EMRUNDEF107_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRUNDEF107",A) //!< Not implemented.
+
+// U_EMRSMALLTEXTOUT 108
+/**
+ \brief Print a pointer to a U_EMR_SMALLTEXTOUT record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSMALLTEXTOUT_print(const char *contents){
+ int roff;
+ char *string;
+ PU_EMRSMALLTEXTOUT pEmr = (PU_EMRSMALLTEXTOUT)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRSMALLTEXTOUT)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" Dest: "); pointl_print(pEmr->Dest); printf("\n");
+ printf(" cChars: %u\n", pEmr->cChars );
+ printf(" fuOptions: 0x%8.8X\n", pEmr->fuOptions );
+ printf(" iGraphicsMode: 0x%8.8X\n", pEmr->iGraphicsMode );
+ printf(" exScale: %f\n", pEmr->exScale );
+ printf(" eyScale: %f\n", pEmr->eyScale );
+ roff = sizeof(U_EMRSMALLTEXTOUT); //offset to the start of the variable fields
+ if(!(pEmr->fuOptions & U_ETO_NO_RECT)){
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, roff, blimit);
+ printf(" rclBounds: "); rectl_print( *(PU_RECTL) (contents + roff)); printf("\n");
+ roff += sizeof(U_RECTL);
+ }
+ if(pEmr->fuOptions & U_ETO_SMALL_CHARS){
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, roff + pEmr->cChars*sizeof(char), blimit);
+ printf(" Text8: <%.*s>\n",pEmr->cChars,contents+roff); /* May not be null terminated */
+ }
+ else {
+ string = U_Utf16leToUtf8((uint16_t *)(contents+roff), pEmr->cChars, NULL);
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, roff + pEmr->cChars*2*sizeof(char), blimit);
+ printf(" Text16: <%s>\n",contents+roff);
+ free(string);
+ }
+}
+
+// U_EMRFORCEUFIMAPPING 109 Not implemented
+#define U_EMRFORCEUFIMAPPING_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRFORCEUFIMAPPING",A) //!< Not implemented.
+// U_EMRNAMEDESCAPE 110 Not implemented
+#define U_EMRNAMEDESCAPE_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRNAMEDESCAPE",A) //!< Not implemented.
+// U_EMRCOLORCORRECTPALETTE 111 Not implemented
+#define U_EMRCOLORCORRECTPALETTE_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRCOLORCORRECTPALETTE",A) //!< Not implemented.
+// U_EMRSETICMPROFILEA 112 Not implemented
+#define U_EMRSETICMPROFILEA_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRSETICMPROFILEA",A) //!< Not implemented.
+// U_EMRSETICMPROFILEW 113 Not implemented
+#define U_EMRSETICMPROFILEW_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRSETICMPROFILEW",A) //!< Not implemented.
+
+// U_EMRALPHABLEND 114
+/**
+ \brief Print a pointer to a U_EMR_ALPHABLEND record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRALPHABLEND_print(const char *contents){
+ core13_print("U_EMRALPHABLEND", contents);
+}
+
+// U_EMRSETLAYOUT 115
+/**
+ \brief Print a pointer to a U_EMR_SETLAYOUT record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRSETLAYOUT_print(const char *contents){
+ core3_print("U_EMRSETLAYOUT", "iMode:", contents);
+}
+
+// U_EMRTRANSPARENTBLT 116
+/**
+ \brief Print a pointer to a U_EMR_TRANSPARENTBLT record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRTRANSPARENTBLT_print(const char *contents){
+ core13_print("U_EMRTRANSPARENTBLT", contents);
+}
+
+// U_EMRUNDEF117 117 Not implemented
+#define U_EMRUNDEF117_print(A) U_EMRNOTIMPLEMENTED_print("U_EMRUNDEF117",A) //!< Not implemented.
+// U_EMRGRADIENTFILL 118
+/**
+ \brief Print a pointer to a U_EMR_GRADIENTFILL record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRGRADIENTFILL_print(const char *contents){
+ unsigned int i;
+ PU_EMRGRADIENTFILL pEmr = (PU_EMRGRADIENTFILL)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRGRADIENTFILL)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" rclBounds: "); rectl_print( pEmr->rclBounds); printf("\n");
+ printf(" nTriVert: %u\n", pEmr->nTriVert );
+ printf(" nGradObj: %u\n", pEmr->nGradObj );
+ printf(" ulMode: %u\n", pEmr->ulMode );
+ contents += sizeof(U_EMRGRADIENTFILL);
+ if(pEmr->nTriVert){
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, pEmr->nTriVert*sizeof(U_TRIVERTEX), blimit);
+ printf(" TriVert: ");
+ for(i=0; i<pEmr->nTriVert; i++, contents+=sizeof(U_TRIVERTEX)){
+ trivertex_print(*(PU_TRIVERTEX)(contents));
+ }
+ printf("\n");
+ }
+ if(pEmr->nGradObj){
+ printf(" GradObj: ");
+ if( pEmr->ulMode == U_GRADIENT_FILL_TRIANGLE){
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, pEmr->nGradObj*sizeof(U_GRADIENT3), blimit);
+ for(i=0; i<pEmr->nGradObj; i++, contents+=sizeof(U_GRADIENT3)){
+ gradient3_print(*(PU_GRADIENT3)(contents));
+ }
+ }
+ else if(pEmr->ulMode == U_GRADIENT_FILL_RECT_H ||
+ pEmr->ulMode == U_GRADIENT_FILL_RECT_V){
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, pEmr->nGradObj*sizeof(U_GRADIENT4), blimit);
+ for(i=0; i<pEmr->nGradObj; i++, contents+=sizeof(U_GRADIENT4)){
+ gradient4_print(*(PU_GRADIENT4)(contents));
+ }
+ }
+ else { printf("invalid ulMode value!"); }
+ printf("\n");
+ }
+}
+
+// U_EMRSETLINKEDUFIS 119 Not implemented
+#define U_EMRSETLINKEDUFIS_print(A) U_EMRNOTIMPLEMENTED_print("U_EMR_SETLINKEDUFIS",A) //!< Not implemented.
+// U_EMRSETTEXTJUSTIFICATION120 Not implemented (denigrated)
+#define U_EMRSETTEXTJUSTIFICATION_print(A) U_EMRNOTIMPLEMENTED_print("U_EMR_SETTEXTJUSTIFICATION",A) //!< Not implemented.
+// U_EMRCOLORMATCHTOTARGETW 121 Not implemented
+#define U_EMRCOLORMATCHTOTARGETW_print(A) U_EMRNOTIMPLEMENTED_print("U_EMR_COLORMATCHTOTARGETW",A) //!< Not implemented.
+
+// U_EMRCREATECOLORSPACEW 122
+/**
+ \brief Print a pointer to a U_EMR_CREATECOLORSPACEW record.
+ \param contents pointer to a buffer holding all EMR records
+*/
+void U_EMRCREATECOLORSPACEW_print(const char *contents){
+ unsigned int i;
+ PU_EMRCREATECOLORSPACEW pEmr = (PU_EMRCREATECOLORSPACEW)(contents);
+ if(pEmr->emr.nSize < sizeof(U_EMRCREATECOLORSPACEW)){
+ printf(" record corruption HERE\n");
+ return;
+ }
+ const char *blimit = contents + pEmr->emr.nSize;
+ printf(" ihCS: %u\n", pEmr->ihCS );
+ printf(" ColorSpace: "); logcolorspacew_print(pEmr->lcs); printf("\n");
+ printf(" dwFlags: 0x%8.8X\n", pEmr->dwFlags );
+ printf(" cbData: %u\n", pEmr->cbData );
+ printf(" Data(hexvalues):");
+ if(pEmr->dwFlags & 1){
+ IF_MEM_UNSAFE_PRINT_AND_RETURN(contents, pEmr->cbData, blimit);
+ for(i=0; i<pEmr->cbData; i++){
+ printf("[%d]:%2.2X ",i,pEmr->Data[i]);
+ }
+ }
+ printf("\n");
+}
+
+/**
+ \brief Print any record in an emf
+ \returns record length for a normal record, 0 for EMREOF, -1 for a bad record
+ \param contents pointer to a buffer holding all EMR records
+ \param blimit pointer to the byte after the last byte in the buffer holding all EMR records
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+int U_emf_onerec_print(const char *contents, const char *blimit, int recnum, size_t off){
+ PU_ENHMETARECORD lpEMFR = (PU_ENHMETARECORD)(contents + off);
+ uint32_t nSize;
+ uint32_t iType;
+ const char *record = contents + off;
+
+ if(record < contents)return(-1); // offset wrapped
+
+ /* Check that COMMON data in record can be touched without an access violation. If it cannot be
+ this is either a corrupt EMF or one engineered to cause a buffer overflow. Pointer math
+ could wrap so check both sides of the range.
+ */
+ if(!U_emf_record_sizeok(record, blimit, &nSize, &iType, 1))return(-1);
+
+ uint32_t crc;
+#if U_BYTE_SWAP
+ //This is a Big Endian machine, EMF crc values must be calculated on Little Endian form
+ char *swapbuf=malloc(nSize);
+ if(!swapbuf)return(-1);
+ memcpy(swapbuf,record,nSize);
+ U_emf_endian(swapbuf,nSize,1); // BE to LE
+ crc=lu_crc32(swapbuf,nSize);
+ free(swapbuf);
+#else
+ crc=lu_crc32(record,nSize);
+#endif
+ printf("%-30srecord:%5d type:%-4d offset:%8d rsize:%8d crc32:%8.8X\n",
+ U_emr_names(iType),recnum,iType,(int) off,nSize,crc);
+
+ fflush(stdout);
+
+ /* print the record header before checking further.
+ Note if this is a corrupt record, but continue anyway.
+ The _print routines will stop at the actual problem and print another corrupt message.
+ */
+ if(!U_emf_record_safe(record)){printf("WARNING: Corrupt record. Emitting fields above the problem.\n");}
+
+ switch (lpEMFR->iType)
+ {
+ case U_EMR_HEADER: U_EMRHEADER_print(record); break;
+ case U_EMR_POLYBEZIER: U_EMRPOLYBEZIER_print(record); break;
+ case U_EMR_POLYGON: U_EMRPOLYGON_print(record); break;
+ case U_EMR_POLYLINE: U_EMRPOLYLINE_print(record); break;
+ case U_EMR_POLYBEZIERTO: U_EMRPOLYBEZIERTO_print(record); break;
+ case U_EMR_POLYLINETO: U_EMRPOLYLINETO_print(record); break;
+ case U_EMR_POLYPOLYLINE: U_EMRPOLYPOLYLINE_print(record); break;
+ case U_EMR_POLYPOLYGON: U_EMRPOLYPOLYGON_print(record); break;
+ case U_EMR_SETWINDOWEXTEX: U_EMRSETWINDOWEXTEX_print(record); break;
+ case U_EMR_SETWINDOWORGEX: U_EMRSETWINDOWORGEX_print(record); break;
+ case U_EMR_SETVIEWPORTEXTEX: U_EMRSETVIEWPORTEXTEX_print(record); break;
+ case U_EMR_SETVIEWPORTORGEX: U_EMRSETVIEWPORTORGEX_print(record); break;
+ case U_EMR_SETBRUSHORGEX: U_EMRSETBRUSHORGEX_print(record); break;
+ case U_EMR_EOF: U_EMREOF_print(record); nSize=0; break;
+ case U_EMR_SETPIXELV: U_EMRSETPIXELV_print(record); break;
+ case U_EMR_SETMAPPERFLAGS: U_EMRSETMAPPERFLAGS_print(record); break;
+ case U_EMR_SETMAPMODE: U_EMRSETMAPMODE_print(record); break;
+ case U_EMR_SETBKMODE: U_EMRSETBKMODE_print(record); break;
+ case U_EMR_SETPOLYFILLMODE: U_EMRSETPOLYFILLMODE_print(record); break;
+ case U_EMR_SETROP2: U_EMRSETROP2_print(record); break;
+ case U_EMR_SETSTRETCHBLTMODE: U_EMRSETSTRETCHBLTMODE_print(record); break;
+ case U_EMR_SETTEXTALIGN: U_EMRSETTEXTALIGN_print(record); break;
+ case U_EMR_SETCOLORADJUSTMENT: U_EMRSETCOLORADJUSTMENT_print(record); break;
+ case U_EMR_SETTEXTCOLOR: U_EMRSETTEXTCOLOR_print(record); break;
+ case U_EMR_SETBKCOLOR: U_EMRSETBKCOLOR_print(record); break;
+ case U_EMR_OFFSETCLIPRGN: U_EMROFFSETCLIPRGN_print(record); break;
+ case U_EMR_MOVETOEX: U_EMRMOVETOEX_print(record); break;
+ case U_EMR_SETMETARGN: U_EMRSETMETARGN_print(record); break;
+ case U_EMR_EXCLUDECLIPRECT: U_EMREXCLUDECLIPRECT_print(record); break;
+ case U_EMR_INTERSECTCLIPRECT: U_EMRINTERSECTCLIPRECT_print(record); break;
+ case U_EMR_SCALEVIEWPORTEXTEX: U_EMRSCALEVIEWPORTEXTEX_print(record); break;
+ case U_EMR_SCALEWINDOWEXTEX: U_EMRSCALEWINDOWEXTEX_print(record); break;
+ case U_EMR_SAVEDC: U_EMRSAVEDC_print(record); break;
+ case U_EMR_RESTOREDC: U_EMRRESTOREDC_print(record); break;
+ case U_EMR_SETWORLDTRANSFORM: U_EMRSETWORLDTRANSFORM_print(record); break;
+ case U_EMR_MODIFYWORLDTRANSFORM: U_EMRMODIFYWORLDTRANSFORM_print(record); break;
+ case U_EMR_SELECTOBJECT: U_EMRSELECTOBJECT_print(record); break;
+ case U_EMR_CREATEPEN: U_EMRCREATEPEN_print(record); break;
+ case U_EMR_CREATEBRUSHINDIRECT: U_EMRCREATEBRUSHINDIRECT_print(record); break;
+ case U_EMR_DELETEOBJECT: U_EMRDELETEOBJECT_print(record); break;
+ case U_EMR_ANGLEARC: U_EMRANGLEARC_print(record); break;
+ case U_EMR_ELLIPSE: U_EMRELLIPSE_print(record); break;
+ case U_EMR_RECTANGLE: U_EMRRECTANGLE_print(record); break;
+ case U_EMR_ROUNDRECT: U_EMRROUNDRECT_print(record); break;
+ case U_EMR_ARC: U_EMRARC_print(record); break;
+ case U_EMR_CHORD: U_EMRCHORD_print(record); break;
+ case U_EMR_PIE: U_EMRPIE_print(record); break;
+ case U_EMR_SELECTPALETTE: U_EMRSELECTPALETTE_print(record); break;
+ case U_EMR_CREATEPALETTE: U_EMRCREATEPALETTE_print(record); break;
+ case U_EMR_SETPALETTEENTRIES: U_EMRSETPALETTEENTRIES_print(record); break;
+ case U_EMR_RESIZEPALETTE: U_EMRRESIZEPALETTE_print(record); break;
+ case U_EMR_REALIZEPALETTE: U_EMRREALIZEPALETTE_print(record); break;
+ case U_EMR_EXTFLOODFILL: U_EMREXTFLOODFILL_print(record); break;
+ case U_EMR_LINETO: U_EMRLINETO_print(record); break;
+ case U_EMR_ARCTO: U_EMRARCTO_print(record); break;
+ case U_EMR_POLYDRAW: U_EMRPOLYDRAW_print(record); break;
+ case U_EMR_SETARCDIRECTION: U_EMRSETARCDIRECTION_print(record); break;
+ case U_EMR_SETMITERLIMIT: U_EMRSETMITERLIMIT_print(record); break;
+ case U_EMR_BEGINPATH: U_EMRBEGINPATH_print(record); break;
+ case U_EMR_ENDPATH: U_EMRENDPATH_print(record); break;
+ case U_EMR_CLOSEFIGURE: U_EMRCLOSEFIGURE_print(record); break;
+ case U_EMR_FILLPATH: U_EMRFILLPATH_print(record); break;
+ case U_EMR_STROKEANDFILLPATH: U_EMRSTROKEANDFILLPATH_print(record); break;
+ case U_EMR_STROKEPATH: U_EMRSTROKEPATH_print(record); break;
+ case U_EMR_FLATTENPATH: U_EMRFLATTENPATH_print(record); break;
+ case U_EMR_WIDENPATH: U_EMRWIDENPATH_print(record); break;
+ case U_EMR_SELECTCLIPPATH: U_EMRSELECTCLIPPATH_print(record); break;
+ case U_EMR_ABORTPATH: U_EMRABORTPATH_print(record); break;
+ case U_EMR_UNDEF69: U_EMRUNDEF69_print(record); break;
+ case U_EMR_COMMENT: U_EMRCOMMENT_print(record, off); break;
+ case U_EMR_FILLRGN: U_EMRFILLRGN_print(record); break;
+ case U_EMR_FRAMERGN: U_EMRFRAMERGN_print(record); break;
+ case U_EMR_INVERTRGN: U_EMRINVERTRGN_print(record); break;
+ case U_EMR_PAINTRGN: U_EMRPAINTRGN_print(record); break;
+ case U_EMR_EXTSELECTCLIPRGN: U_EMREXTSELECTCLIPRGN_print(record); break;
+ case U_EMR_BITBLT: U_EMRBITBLT_print(record); break;
+ case U_EMR_STRETCHBLT: U_EMRSTRETCHBLT_print(record); break;
+ case U_EMR_MASKBLT: U_EMRMASKBLT_print(record); break;
+ case U_EMR_PLGBLT: U_EMRPLGBLT_print(record); break;
+ case U_EMR_SETDIBITSTODEVICE: U_EMRSETDIBITSTODEVICE_print(record); break;
+ case U_EMR_STRETCHDIBITS: U_EMRSTRETCHDIBITS_print(record); break;
+ case U_EMR_EXTCREATEFONTINDIRECTW: U_EMREXTCREATEFONTINDIRECTW_print(record); break;
+ case U_EMR_EXTTEXTOUTA: U_EMREXTTEXTOUTA_print(record); break;
+ case U_EMR_EXTTEXTOUTW: U_EMREXTTEXTOUTW_print(record); break;
+ case U_EMR_POLYBEZIER16: U_EMRPOLYBEZIER16_print(record); break;
+ case U_EMR_POLYGON16: U_EMRPOLYGON16_print(record); break;
+ case U_EMR_POLYLINE16: U_EMRPOLYLINE16_print(record); break;
+ case U_EMR_POLYBEZIERTO16: U_EMRPOLYBEZIERTO16_print(record); break;
+ case U_EMR_POLYLINETO16: U_EMRPOLYLINETO16_print(record); break;
+ case U_EMR_POLYPOLYLINE16: U_EMRPOLYPOLYLINE16_print(record); break;
+ case U_EMR_POLYPOLYGON16: U_EMRPOLYPOLYGON16_print(record); break;
+ case U_EMR_POLYDRAW16: U_EMRPOLYDRAW16_print(record); break;
+ case U_EMR_CREATEMONOBRUSH: U_EMRCREATEMONOBRUSH_print(record); break;
+ case U_EMR_CREATEDIBPATTERNBRUSHPT: U_EMRCREATEDIBPATTERNBRUSHPT_print(record); break;
+ case U_EMR_EXTCREATEPEN: U_EMREXTCREATEPEN_print(record); break;
+ case U_EMR_POLYTEXTOUTA: U_EMRPOLYTEXTOUTA_print(record); break;
+ case U_EMR_POLYTEXTOUTW: U_EMRPOLYTEXTOUTW_print(record); break;
+ case U_EMR_SETICMMODE: U_EMRSETICMMODE_print(record); break;
+ case U_EMR_CREATECOLORSPACE: U_EMRCREATECOLORSPACE_print(record); break;
+ case U_EMR_SETCOLORSPACE: U_EMRSETCOLORSPACE_print(record); break;
+ case U_EMR_DELETECOLORSPACE: U_EMRDELETECOLORSPACE_print(record); break;
+ case U_EMR_GLSRECORD: U_EMRGLSRECORD_print(record); break;
+ case U_EMR_GLSBOUNDEDRECORD: U_EMRGLSBOUNDEDRECORD_print(record); break;
+ case U_EMR_PIXELFORMAT: U_EMRPIXELFORMAT_print(record); break;
+ case U_EMR_DRAWESCAPE: U_EMRDRAWESCAPE_print(record); break;
+ case U_EMR_EXTESCAPE: U_EMREXTESCAPE_print(record); break;
+ case U_EMR_UNDEF107: U_EMRUNDEF107_print(record); break;
+ case U_EMR_SMALLTEXTOUT: U_EMRSMALLTEXTOUT_print(record); break;
+ case U_EMR_FORCEUFIMAPPING: U_EMRFORCEUFIMAPPING_print(record); break;
+ case U_EMR_NAMEDESCAPE: U_EMRNAMEDESCAPE_print(record); break;
+ case U_EMR_COLORCORRECTPALETTE: U_EMRCOLORCORRECTPALETTE_print(record); break;
+ case U_EMR_SETICMPROFILEA: U_EMRSETICMPROFILEA_print(record); break;
+ case U_EMR_SETICMPROFILEW: U_EMRSETICMPROFILEW_print(record); break;
+ case U_EMR_ALPHABLEND: U_EMRALPHABLEND_print(record); break;
+ case U_EMR_SETLAYOUT: U_EMRSETLAYOUT_print(record); break;
+ case U_EMR_TRANSPARENTBLT: U_EMRTRANSPARENTBLT_print(record); break;
+ case U_EMR_UNDEF117: U_EMRUNDEF117_print(record); break;
+ case U_EMR_GRADIENTFILL: U_EMRGRADIENTFILL_print(record); break;
+ case U_EMR_SETLINKEDUFIS: U_EMRSETLINKEDUFIS_print(record); break;
+ case U_EMR_SETTEXTJUSTIFICATION: U_EMRSETTEXTJUSTIFICATION_print(record); break;
+ case U_EMR_COLORMATCHTOTARGETW: U_EMRCOLORMATCHTOTARGETW_print(record); break;
+ case U_EMR_CREATECOLORSPACEW: U_EMRCREATECOLORSPACEW_print(record); break;
+ default: U_EMRNOTIMPLEMENTED_print("?",record); break;
+ } //end of switch
+ return(nSize);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/3rdparty/libuemf/uemf_print.h b/src/3rdparty/libuemf/uemf_print.h
new file mode 100644
index 0000000..088a8a3
--- /dev/null
+++ b/src/3rdparty/libuemf/uemf_print.h
@@ -0,0 +1,177 @@
+/**
+ @file uemf_print.h
+
+ @brief Prototypes for functions for printing records from EMF files.
+*/
+
+/*
+File: uemf_print.h
+Version: 0.0.9
+Date: 21-MAY-2015
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2015 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifndef _UEMF_PRINT_
+#define _UEMF_PRINT_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//! \cond
+/* prototypes for miscellaneous */
+uint32_t lu_crc32(const char *record, uint32_t Size);
+
+/* prototypes for objects used in EMR records */
+void hexbytes_print(uint8_t *buf,unsigned int num);
+void colorref_print(U_COLORREF color);
+void rgbquad_print(U_RGBQUAD color);
+void rectl_print(U_RECTL rect);
+void sizel_print(U_SIZEL sz);
+void pointl_print(U_POINTL pt);
+void point16_print(U_POINT16 pt);
+void lcs_gamma_print(U_LCS_GAMMA lg);
+void lcs_gammargb_print(U_LCS_GAMMARGB lgr);
+void trivertex_print(U_TRIVERTEX tv);
+void gradient3_print(U_GRADIENT3 g3);
+void gradient4_print(U_GRADIENT4 g4);
+void logbrush_print(U_LOGBRUSH lb);
+void xform_print(U_XFORM xform);
+void ciexyz_print(U_CIEXYZ ciexyz);
+void ciexyztriple_print(U_CIEXYZTRIPLE cie3);
+void logcolorspacea_print(U_LOGCOLORSPACEA lcsa);
+void logcolorspacew_print(U_LOGCOLORSPACEW lcsa);
+void panose_print(U_PANOSE panose);
+void logfont_print(U_LOGFONT lf);
+void logfont_panose_print(U_LOGFONT_PANOSE lfp);
+void bitmapinfoheader_print(const char *Bmih);
+void bitmapinfo_print(const char *Bmi, const char *blimit);
+void blend_print(U_BLEND blend);
+void extlogpen_print(const PU_EXTLOGPEN elp);
+void logpen_print(U_LOGPEN lp);
+void logpltntry_print(U_LOGPLTNTRY lpny);
+void logpalette_print(const PU_LOGPALETTE lp);
+void rgndataheader_print(U_RGNDATAHEADER rdh);
+void rgndata_print(const PU_RGNDATA rd, const char *blimit);
+void coloradjustment_print(U_COLORADJUSTMENT ca);
+void pixelformatdescriptor_print(U_PIXELFORMATDESCRIPTOR pfd);
+void emrtext_print(const char *emt, const char *record, const char *blimit, int type);
+
+/* prototypes for EMR records */
+void U_EMRNOTIMPLEMENTED_print(const char *name, const char *contents, int recnum, int off);
+void U_EMRHEADER_print(const char *contents);
+void U_EMRPOLYBEZIER_print(const char *contents);
+void U_EMRPOLYGON_print(const char *contents);
+void U_EMRPOLYLINE_print(const char *contents);
+void U_EMRPOLYBEZIERTO_print(const char *contents);
+void U_EMRPOLYLINETO_print(const char *contents);
+void U_EMRPOLYPOLYLINE_print(const char *contents);
+void U_EMRPOLYPOLYGON_print(const char *contents);
+void U_EMRSETWINDOWEXTEX_print(const char *contents);
+void U_EMRSETWINDOWORGEX_print(const char *contents);
+void U_EMRSETVIEWPORTEXTEX_print(const char *contents);
+void U_EMRSETVIEWPORTORGEX_print(const char *contents);
+void U_EMRSETBRUSHORGEX_print(const char *contents);
+void U_EMREOF_print(const char *contents);
+void U_EMRSETPIXELV_print(const char *contents);
+void U_EMRSETMAPPERFLAGS_print(const char *contents);
+void U_EMRSETMAPMODE_print(const char *contents);
+void U_EMRSETBKMODE_print(const char *contents);
+void U_EMRSETPOLYFILLMODE_print(const char *contents);
+void U_EMRSETROP2_print(const char *contents);
+void U_EMRSETSTRETCHBLTMODE_print(const char *contents);
+void U_EMRSETTEXTALIGN_print(const char *contents);
+void U_EMRSETCOLORADJUSTMENT_print(const char *contents);
+void U_EMRSETTEXTCOLOR_print(const char *contents);
+void U_EMRSETBKCOLOR_print(const char *contents);
+void U_EMROFFSETCLIPRGN_print(const char *contents);
+void U_EMRMOVETOEX_print(const char *contents);
+void U_EMRSETMETARGN_print(const char *contents);
+void U_EMREXCLUDECLIPRECT_print(const char *contents);
+void U_EMRINTERSECTCLIPRECT_print(const char *contents);
+void U_EMRSCALEVIEWPORTEXTEX_print(const char *contents);
+void U_EMRSCALEWINDOWEXTEX_print(const char *contents);
+void U_EMRSAVEDC_print(const char *contents);
+void U_EMRRESTOREDC_print(const char *contents);
+void U_EMRSETWORLDTRANSFORM_print(const char *contents);
+void U_EMRMODIFYWORLDTRANSFORM_print(const char *contents);
+void U_EMRSELECTOBJECT_print(const char *contents);
+void U_EMRCREATEPEN_print(const char *contents);
+void U_EMRCREATEBRUSHINDIRECT_print(const char *contents);
+void U_EMRDELETEOBJECT_print(const char *contents);
+void U_EMRANGLEARC_print(const char *contents);
+void U_EMRELLIPSE_print(const char *contents);
+void U_EMRRECTANGLE_print(const char *contents);
+void U_EMRROUNDRECT_print(const char *contents);
+void U_EMRARC_print(const char *contents);
+void U_EMRCHORD_print(const char *contents);
+void U_EMRPIE_print(const char *contents);
+void U_EMRSELECTPALETTE_print(const char *contents);
+void U_EMRCREATEPALETTE_print(const char *contents);
+void U_EMRSETPALETTEENTRIES_print(const char *contents);
+void U_EMRRESIZEPALETTE_print(const char *contents);
+void U_EMRREALIZEPALETTE_print(const char *contents);
+void U_EMREXTFLOODFILL_print(const char *contents);
+void U_EMRLINETO_print(const char *contents);
+void U_EMRARCTO_print(const char *contents);
+void U_EMRPOLYDRAW_print(const char *contents);
+void U_EMRSETARCDIRECTION_print(const char *contents);
+void U_EMRSETMITERLIMIT_print(const char *contents);
+void U_EMRBEGINPATH_print(const char *contents);
+void U_EMRENDPATH_print(const char *contents);
+void U_EMRCLOSEFIGURE_print(const char *contents);
+void U_EMRFILLPATH_print(const char *contents);
+void U_EMRSTROKEANDFILLPATH_print(const char *contents);
+void U_EMRSTROKEPATH_print(const char *contents);
+void U_EMRFLATTENPATH_print(const char *contents);
+void U_EMRWIDENPATH_print(const char *contents);
+void U_EMRSELECTCLIPPATH_print(const char *contents);
+void U_EMRABORTPATH_print(const char *contents);
+void U_EMRCOMMENT_print(const char *contents, size_t off);
+void U_EMRFILLRGN_print(const char *contents);
+void U_EMRFRAMERGN_print(const char *contents);
+void U_EMRINVERTRGN_print(const char *contents);
+void U_EMRPAINTRGN_print(const char *contents);
+void U_EMREXTSELECTCLIPRGN_print(const char *contents);
+void U_EMRBITBLT_print(const char *contents);
+void U_EMRSTRETCHBLT_print(const char *contents);
+void U_EMRMASKBLT_print(const char *contents);
+void U_EMRPLGBLT_print(const char *contents);
+void U_EMRSETDIBITSTODEVICE_print(const char *contents);
+void U_EMRSTRETCHDIBITS_print(const char *contents);
+void U_EMREXTCREATEFONTINDIRECTW_print(const char *contents);
+void U_EMREXTTEXTOUTA_print(const char *contents);
+void U_EMREXTTEXTOUTW_print(const char *contents);
+void U_EMRPOLYBEZIER16_print(const char *contents);
+void U_EMRPOLYGON16_print(const char *contents);
+void U_EMRPOLYLINE16_print(const char *contents);
+void U_EMRPOLYBEZIERTO16_print(const char *contents);
+void U_EMRPOLYLINETO16_print(const char *contents);
+void U_EMRPOLYPOLYLINE16_print(const char *contents);
+void U_EMRPOLYPOLYGON16_print(const char *contents);
+void U_EMRPOLYDRAW16_print(const char *contents);
+void U_EMRCREATEMONOBRUSH_print(const char *contents);
+void U_EMRCREATEDIBPATTERNBRUSHPT_print(const char *contents);
+void U_EMREXTCREATEPEN_print(const char *contents);
+void U_EMRSETICMMODE_print(const char *contents);
+void U_EMRCREATECOLORSPACE_print(const char *contents);
+void U_EMRSETCOLORSPACE_print(const char *contents);
+void U_EMRDELETECOLORSPACE_print(const char *contents);
+void U_EMRPIXELFORMAT_print(const char *contents);
+void U_EMRSMALLTEXTOUT_print(const char *contents);
+void U_EMRALPHABLEND_print(const char *contents);
+void U_EMRSETLAYOUT_print(const char *contents);
+void U_EMRTRANSPARENTBLT_print(const char *contents);
+void U_EMRGRADIENTFILL_print(const char *contents);
+void U_EMRCREATECOLORSPACEW_print(const char *contents);
+int U_emf_onerec_print(const char *contents, char *blimit, int recnum, int off);
+//! \endcond
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UEMF_PRINT_ */
diff --git a/src/3rdparty/libuemf/uemf_safe.c b/src/3rdparty/libuemf/uemf_safe.c
new file mode 100644
index 0000000..a3e0502
--- /dev/null
+++ b/src/3rdparty/libuemf/uemf_safe.c
@@ -0,0 +1,1204 @@
+/**
+ @file uemf_safe.c
+
+ @brief Functions for checking EMF records for memory issues.
+
+ EMF records come in a variety of sizes, and some types have variable sizes.
+ These functions check the record types and report if there are any issues
+ that could cause a memory access problem. All counts and offsets are examined
+ and the data structure checked so that no referenced byte is outside of the
+ declared size of the record.
+
+ Many variables are initialized to zero even though they will always be set because
+ some versions of gcc give spurious "may be used uninitialized" warnings otherwise.
+*/
+
+/*
+File: uemf_safe.c
+Version: 0.0.5
+Date: 26-JAN-2016
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2016 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h> /* for offsetof() macro */
+#include "uemf.h"
+#include "uemf_endian.h" // for u_emf_record_sizeok
+
+// hide almost everuything in here from Doxygen
+//! \cond
+
+/**
+ \brief Test a U_EXTLOGPEN object.
+ \param elp PU_EXTLOGPEN object
+ \param blimit one byte past the end of the record
+*/
+int extlogpen_safe(
+ PU_EXTLOGPEN elp,
+ const char *blimit
+ ){
+ int count=elp->elpNumEntries;
+ if(IS_MEM_UNSAFE(&(elp->elpStyleEntry), count*4, blimit))return(0);
+ return(1);
+}
+
+/**
+ \brief Test a U_EMRTEXT record
+ \param pemt Pointer to a U_EMRTEXT record
+ \param record Pointer to the start of the record which contains this U_EMRTEXT
+ \param blimit one byte past the end of the record.
+*/
+int emrtext_safe(
+ PU_EMRTEXT pemt,
+ const char *record,
+ const char *blimit
+ ){
+ int off;
+ uint32_t count = pemt->nChars;
+ uint32_t fOptions = pemt->fOptions;
+ uint32_t offDx = 0;
+ off = sizeof(U_EMRTEXT);
+ if(!(fOptions & U_ETO_NO_RECT)){
+ if(IS_MEM_UNSAFE(pemt, sizeof(U_RECTL), blimit))return(0);
+ off+=sizeof(U_RECTL);
+ }
+ offDx = *(uint32_t *)((char *)pemt +off);
+ if(IS_MEM_UNSAFE(pemt, off + 4, blimit))return(0);
+ if(IS_MEM_UNSAFE(record, offDx + count*4, blimit))return(0);
+ return(1);
+}
+
+/**
+ \return 1 on success, 0 on failure
+ \brief Test a U_RGNDATA object.
+ \param rd pointer to a U_RGNDATA object.
+ \param cbRgnData size of the U_RGNDATA object.
+*/
+int rgndata_safe(
+ PU_RGNDATA rd,
+ int cbRgnData
+ ){
+ int count = rd->rdh.nCount;
+ if(4*count + (int)sizeof(U_RGNDATAHEADER) > cbRgnData)return(0);
+ return(1);
+}
+
+
+/**
+ \return 1 on success, 0 on failure
+ \brief Test a U_BITMAPINFO object.
+ \param Bmi pointer to a U_BITMAPINFO object.
+ \param blimit one byte past the end of the record.
+*/
+int bitmapinfo_safe(
+ const char *Bmi,
+ const char *blimit
+ ){
+ int ClrUsed;
+ if(IS_MEM_UNSAFE(Bmi, offsetof(U_BITMAPINFO,bmiHeader) + sizeof(U_BITMAPINFOHEADER), blimit))return(0);
+ ClrUsed = get_real_color_count(Bmi + offsetof(U_BITMAPINFO,bmiHeader));
+ if(ClrUsed && IS_MEM_UNSAFE(Bmi, offsetof(U_BITMAPINFO,bmiColors) + ClrUsed*sizeof(U_RGBQUAD), blimit))return(0);
+ return(1);
+}
+
+/**
+ \brief Check that the bitmap in the specified DIB is compatible with the record size
+
+ \return 1 on success, 0 on failure
+ \param record EMF record that contains a DIB pixel array
+ \param iUsage DIBcolors Enumeration
+ \param offBmi offset from the start of the record to the start of the bitmapinfo structure
+ \param cbBmi declared space for the bitmapinfo structure in the record
+ \param offBits offset from the start of the record to the start of the bitmap
+ \param cbBits declared space for the bitmap in the record (amount used may be less than this)
+ \param blimit one byte past the end of the record.
+
+ This method can only test DIBs that hold Microsoft's various bitmap types. PNG or JPG is just a bag
+ of bytes, and there is no possible way to derive from the known width and height how big it should be.
+*/
+int DIB_safe(
+ const char *record,
+ uint32_t iUsage,
+ uint32_t offBmi,
+ uint32_t cbBmi,
+ uint32_t offBits,
+ uint32_t cbBits,
+ const char *blimit
+ ){
+ int dibparams = U_BI_UNKNOWN; // type of image not yet determined
+ const char *px = NULL; // DIB pixels
+ const U_RGBQUAD *ct = NULL; // DIB color table
+ int bs;
+ int usedbytes;
+
+ if(!cbBmi)return(1); // No DIB in a record where it is optional
+ if(IS_MEM_UNSAFE(record, offBmi + cbBmi, blimit))return(0);
+ if(!bitmapinfo_safe(record + offBmi, blimit))return(0); // checks the number of colors
+ if(cbBits && IS_MEM_UNSAFE(record, offBits + cbBits, blimit))return(0);
+ if(iUsage == U_DIB_RGB_COLORS){
+ uint32_t width, height, colortype, numCt, invert; // these values will be set in get_DIB_params
+ // next call returns pointers and values, but allocates no memory
+ dibparams = get_DIB_params(record, offBits, offBmi, &px, (const U_RGBQUAD **) &ct,
+ &numCt, &width, &height, &colortype, &invert);
+
+ // sanity checking
+ if(numCt && colortype >= U_BCBM_COLOR16)return(0); //color tables not used above 16 bit pixels
+ if(!numCt && colortype < U_BCBM_COLOR16)return(0); //color tables mandatory for < 16 bit
+
+ if(dibparams ==U_BI_RGB){
+ // this is the only DIB type where we can calculate how big it should be when stored in the EMF file
+ bs = colortype/8;
+ if(bs<1){
+ usedbytes = (width*colortype + 7)/8; // width of line in fully and partially occupied bytes
+ }
+ else {
+ usedbytes = width*bs;
+ }
+ if(IS_MEM_UNSAFE(record+offBits, usedbytes, blimit))return(0);
+ }
+ }
+ return(1);
+}
+
+
+/* **********************************************************************************************
+These functions contain shared code used by various U_EMR*_safe functions. These should NEVER be called
+by end user code and to further that end prototypes are NOT provided and they are hidden from Doxygen.
+
+
+ These all have this form:
+
+ void core1_safe(const char *record){
+
+ but some do not actually use torev.
+
+
+
+*********************************************************************************************** */
+
+// all core*_safe call this, U_EMRSETMARGN_safe and some others all it directly
+// numbered as core5 to be consistent with uemf.c, but must appear before the others as there is no prototype
+// sizeof(U_ENHMETARECORD) bytes in the record
+int core5_safe(const char *record, int minSize){
+ PU_EMR pEmr = (PU_EMR)(record);
+ if((int) pEmr->nSize < minSize)return(0);
+ return(1);
+}
+
+// Functions with the same form starting with U_EMRPOLYBEZIER_safe
+int core1_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRPOLYLINETO))return(0);
+ PU_EMRPOLYLINETO pEmr = (PU_EMRPOLYLINETO) (record);
+ int count=pEmr->cptl;
+ const char *blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(pEmr->aptl, count*sizeof(U_POINTL), blimit))return(0);
+ return(1);
+}
+
+// Functions with the same form starting with U_EMRPOLYPOLYLINE_safe
+int core2_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRPOLYPOLYLINE))return(0);
+ PU_EMRPOLYPOLYLINE pEmr = (PU_EMRPOLYPOLYLINE) (record);
+ int count = pEmr->cptl;
+ int nPolys = pEmr->nPolys;
+ const char * blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(pEmr->aPolyCounts, nPolys*4, blimit))return(0);
+ record += sizeof(U_EMRPOLYPOLYLINE) - 4 + sizeof(uint32_t)* nPolys;
+ if(IS_MEM_UNSAFE(record, count*sizeof(U_POINTL), blimit))return(0);
+ return(1);
+}
+
+
+// Functions with the same form starting with U_EMRSETMAPMODE_safe
+int core3_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRSETMAPMODE))return(0);
+ return(1);
+}
+
+// Functions taking a single U_RECT or U_RECTL, starting with U_EMRELLIPSE_safe, also U_EMRFILLPATH_safe,
+int core4_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRELLIPSE))return(0);
+ return(1);
+}
+
+// Functions with the same form starting with U_EMRPOLYBEZIER16_safe
+int core6_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRPOLYBEZIER16))return(0);
+ PU_EMRPOLYBEZIER16 pEmr = (PU_EMRPOLYBEZIER16) (record);
+ int count=pEmr->cpts;
+ const char *blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(pEmr->apts, count*sizeof(U_POINT16), blimit))return(0);
+ return(1);
+}
+
+
+// Records with the same form starting with U_EMRSETWINDOWEXTEX_safe, that is, all with two uint32_t values after the emr
+int core7_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRSETWINDOWEXTEX))return(0);
+ return(1);
+}
+
+// For U_EMREXTTEXTOUTA and U_EMREXTTEXTOUTW, type=0 for the first one
+int core8_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMREXTTEXTOUTA))return(0);
+ PU_EMREXTTEXTOUTA pEmr = (PU_EMREXTTEXTOUTA) (record);
+ const char *blimit = record + pEmr->emr.nSize;
+ if(!emrtext_safe(&(pEmr->emrtext),record,blimit))return(0);
+ return(1);
+}
+
+// Functions that take a rect and a pair of points, starting with U_EMRARC_safe
+int core9_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRARC))return(0);
+ return(1);
+}
+
+// Functions with the same form starting with U_EMRPOLYPOLYLINE16_safe
+int core10_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRPOLYPOLYLINE16))return(0);
+ PU_EMRPOLYPOLYLINE16 pEmr = (PU_EMRPOLYPOLYLINE16) (record);
+ int count = pEmr->cpts;
+ int nPolys = pEmr->nPolys;
+ const char *blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(pEmr->aPolyCounts, nPolys*4, blimit))return(0);
+ record += sizeof(U_EMRPOLYPOLYLINE16) - 4 + sizeof(uint32_t)* nPolys;
+ if(IS_MEM_UNSAFE(record, count*sizeof(U_POINT16), blimit))return(0);
+ return(1);
+}
+
+// Functions with the same form starting with U_EMRINVERTRGN_safe and U_EMRPAINTRGN_safe,
+int core11_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRINVERTRGN))return(0);
+ PU_EMRINVERTRGN pEmr = (PU_EMRINVERTRGN)(record);
+ int cbRgnData = pEmr->cbRgnData;
+ const char *blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0);
+ return(rgndata_safe(pEmr->RgnData, cbRgnData));
+}
+
+
+// common code for U_EMRCREATEMONOBRUSH_safe and U_EMRCREATEDIBPATTERNBRUSHPT_safe,
+int core12_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRCREATEMONOBRUSH))return(0);
+ PU_EMRCREATEMONOBRUSH pEmr = (PU_EMRCREATEMONOBRUSH) (record);
+ const char *blimit = record + pEmr->emr.nSize;
+ U_OFFBMI offBmi = pEmr->offBmi;
+ U_CBBMI cbBmi = pEmr->cbBmi;
+ U_OFFBITS offBits = pEmr->offBits;
+ U_CBBITS cbBits = pEmr->cbBits;
+ uint32_t iUsage = pEmr->iUsage;
+ return(DIB_safe(record, iUsage, offBmi, cbBmi, offBits, cbBits, blimit));
+}
+
+// common code for U_EMRALPHABLEND_safe and U_EMRTRANSPARENTBLT_safe,
+int core13_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRALPHABLEND))return(0);
+ PU_EMRALPHABLEND pEmr = (PU_EMRALPHABLEND) (record);
+ const char *blimit = record + pEmr->emr.nSize;
+ U_OFFBMISRC offBmiSrc = pEmr->offBmiSrc;
+ U_CBBMISRC cbBmiSrc = pEmr->cbBmiSrc;
+ U_OFFBITSSRC offBitsSrc = pEmr->offBitsSrc;
+ U_CBBITS cbBitsSrc = pEmr->cbBitsSrc;
+ uint32_t iUsageSrc = pEmr->iUsageSrc;
+ return(DIB_safe(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit));
+}
+
+/* **********************************************************************************************
+These are the core EMR_safe functions, each converts a particular type of record.
+All operate in place on the chunk of memory holding that record.
+Some of these have offsets or counts which, if corrupt or evil would result in access outside
+ the record. These cases return a status value of 0 if that happens, 1 on success. Other
+ records which do not have these issues do not return a status value.
+They are listed in order by the corresponding U_EMR_* index number.
+*********************************************************************************************** */
+
+/**
+ All of the record level (hidden) functions have this form:
+ \brief Convert a pointer to a U_EMR_whatever record which has not been implemented.
+ \param record pointer to a buffer holding the EMR record
+ \param torev 1 for native to reversed, 0 for reversed to native
+*/
+int U_EMRNOTIMPLEMENTED_safe(const char *record){
+ fprintf(stderr,"EMF WARNING: could not safety check record because that type has not been implemented!\n");
+ return(core5_safe(record, sizeof(U_EMR)));
+}
+
+// U_EMRHEADER 1
+int U_EMRHEADER_safe(const char *record){
+ // use _MIN form so that it accepts very old EMF files
+ return(core5_safe(record, U_SIZE_EMRHEADER_MIN));
+}
+
+// U_EMRPOLYBEZIER 2
+int U_EMRPOLYBEZIER_safe(const char *record){
+ return(core1_safe(record));
+}
+
+// U_EMRPOLYGON 3
+int U_EMRPOLYGON_safe(const char *record){
+ return(core1_safe(record));
+}
+
+// U_EMRPOLYLINE 4
+int U_EMRPOLYLINE_safe(const char *record){
+ return(core1_safe(record));
+}
+
+// U_EMRPOLYBEZIERTO 5
+int U_EMRPOLYBEZIERTO_safe(const char *record){
+ return(core1_safe(record));
+}
+
+// U_EMRPOLYLINETO 6
+int U_EMRPOLYLINETO_safe(const char *record){
+ return(core1_safe(record));
+}
+
+// U_EMRPOLYPOLYLINE 7
+int U_EMRPOLYPOLYLINE_safe(const char *record){
+ return(core2_safe(record));
+}
+
+// U_EMRPOLYPOLYGON 8
+int U_EMRPOLYPOLYGON_safe(const char *record){
+ return(core2_safe(record));
+}
+
+// U_EMRSETWINDOWEXTEX 9
+int U_EMRSETWINDOWEXTEX_safe(const char *record){
+ return(core7_safe(record));
+}
+
+// U_EMRSETWINDOWORGEX 10
+int U_EMRSETWINDOWORGEX_safe(const char *record){
+ return(core7_safe(record));
+}
+
+// U_EMRSETVIEWPORTEXTEX 11
+int U_EMRSETVIEWPORTEXTEX_safe(const char *record){
+ return(core7_safe(record));
+}
+
+// U_EMRSETVIEWPORTORGEX 12
+int U_EMRSETVIEWPORTORGEX_safe(const char *record){
+ return(core7_safe(record));
+}
+
+// U_EMRSETBRUSHORGEX 13
+int U_EMRSETBRUSHORGEX_safe(const char *record){
+ return(core7_safe(record));
+}
+
+// U_EMREOF 14
+int U_EMREOF_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMREOF))return(0);
+ PU_EMREOF pEmr = (PU_EMREOF)(record);
+ const char *blimit = record + pEmr->emr.nSize;
+ int cbPalEntries=pEmr->cbPalEntries;
+ if(cbPalEntries){
+ if(IS_MEM_UNSAFE(record, pEmr->offPalEntries + 2*2, blimit))return(0);// 2 16 bit values in U_LOGPALLETE
+ }
+ int off = sizeof(U_EMREOF) + 4 * cbPalEntries;
+ if(IS_MEM_UNSAFE(record, off + 4, blimit))return(0);
+ return(1);
+}
+
+
+// U_EMRSETPIXELV 15
+int U_EMRSETPIXELV_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRSETPIXELV));
+
+}
+
+
+// U_EMRSETMAPPERFLAGS 16
+int U_EMRSETMAPPERFLAGS_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRSETMAPPERFLAGS));
+}
+
+
+// U_EMRSETMAPMODE 17
+int U_EMRSETMAPMODE_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRSETBKMODE 18
+int U_EMRSETBKMODE_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRSETPOLYFILLMODE 19
+int U_EMRSETPOLYFILLMODE_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRSETROP2 20
+int U_EMRSETROP2_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRSETSTRETCHBLTMODE 21
+int U_EMRSETSTRETCHBLTMODE_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRSETTEXTALIGN 22
+int U_EMRSETTEXTALIGN_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRSETCOLORADJUSTMENT 23
+int U_EMRSETCOLORADJUSTMENT_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRSETCOLORADJUSTMENT));
+}
+
+// U_EMRSETTEXTCOLOR 24
+int U_EMRSETTEXTCOLOR_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRSETTEXTCOLOR));
+}
+
+// U_EMRSETBKCOLOR 25
+int U_EMRSETBKCOLOR_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRSETBKCOLOR));
+}
+
+// U_EMROFFSETCLIPRGN 26
+int U_EMROFFSETCLIPRGN_safe(const char *record){
+ return(core7_safe(record));
+}
+
+// U_EMRMOVETOEX 27
+int U_EMRMOVETOEX_safe(const char *record){
+ return(core7_safe(record));
+}
+
+// U_EMRSETMETARGN 28
+int U_EMRSETMETARGN_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRSETMETARGN));
+}
+
+// U_EMREXCLUDECLIPRECT 29
+int U_EMREXCLUDECLIPRECT_safe(const char *record){
+ return(core4_safe(record));
+}
+
+// U_EMRINTERSECTCLIPRECT 30
+int U_EMRINTERSECTCLIPRECT_safe(const char *record){
+ return(core4_safe(record));
+}
+
+// U_EMRSCALEVIEWPORTEXTEX 31
+int U_EMRSCALEVIEWPORTEXTEX_safe(const char *record){
+ return(core4_safe(record));
+}
+
+// U_EMRSCALEWINDOWEXTEX 32
+int U_EMRSCALEWINDOWEXTEX_safe(const char *record){
+ return(core4_safe(record));
+}
+
+// U_EMRSAVEDC 33
+int U_EMRSAVEDC_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRSAVEDC));
+}
+
+// U_EMRRESTOREDC 34
+int U_EMRRESTOREDC_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRSETWORLDTRANSFORM 35
+int U_EMRSETWORLDTRANSFORM_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRSETWORLDTRANSFORM));
+}
+
+// U_EMRMODIFYWORLDTRANSFORM 36
+int U_EMRMODIFYWORLDTRANSFORM_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRMODIFYWORLDTRANSFORM));
+}
+
+// U_EMRSELECTOBJECT 37
+int U_EMRSELECTOBJECT_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRSELECTOBJECT));
+}
+
+// U_EMRCREATEPEN 38
+int U_EMRCREATEPEN_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRCREATEPEN));
+}
+
+// U_EMRCREATEBRUSHINDIRECT 39
+int U_EMRCREATEBRUSHINDIRECT_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRCREATEBRUSHINDIRECT));
+}
+
+// U_EMRDELETEOBJECT 40
+int U_EMRDELETEOBJECT_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRDELETEOBJECT));
+
+}
+
+// U_EMRANGLEARC 41
+int U_EMRANGLEARC_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRANGLEARC));
+}
+
+// U_EMRELLIPSE 42
+int U_EMRELLIPSE_safe(const char *record){
+ return(core4_safe(record));
+}
+
+// U_EMRRECTANGLE 43
+int U_EMRRECTANGLE_safe(const char *record){
+ return(core4_safe(record));
+}
+
+// U_EMRROUNDRECT 44
+int U_EMRROUNDRECT_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRROUNDRECT));
+}
+
+// U_EMRARC 45
+int U_EMRARC_safe(const char *record){
+ return(core9_safe(record));
+}
+
+// U_EMRCHORD 46
+int U_EMRCHORD_safe(const char *record){
+ return(core9_safe(record));
+}
+
+// U_EMRPIE 47
+int U_EMRPIE_safe(const char *record){
+ return(core9_safe(record));
+}
+
+// U_EMRSELECTPALETTE 48
+int U_EMRSELECTPALETTE_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRCREATEPALETTE 49
+int U_EMRCREATEPALETTE_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRCREATEPALETTE));
+}
+
+// U_EMRSETPALETTEENTRIES 50
+int U_EMRSETPALETTEENTRIES_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRSETPALETTEENTRIES));
+}
+
+// U_EMRRESIZEPALETTE 51
+int U_EMRRESIZEPALETTE_safe(const char *record){
+ return(core7_safe(record));
+}
+
+// U_EMRREALIZEPALETTE 52
+int U_EMRREALIZEPALETTE_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRREALIZEPALETTE));
+}
+
+// U_EMREXTFLOODFILL 53
+int U_EMREXTFLOODFILL_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMREXTFLOODFILL));
+}
+
+// U_EMRLINETO 54
+int U_EMRLINETO_safe(const char *record){
+ return(core7_safe(record));
+}
+
+// U_EMRARCTO 55
+int U_EMRARCTO_safe(const char *record){
+ return(core9_safe(record));
+}
+
+// U_EMRPOLYDRAW 56
+int U_EMRPOLYDRAW_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRPOLYDRAW))return(0);
+ PU_EMRPOLYDRAW pEmr = (PU_EMRPOLYDRAW)(record);
+ int count = pEmr->cptl;
+ const char *blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(pEmr->aptl, count*sizeof(U_POINTL), blimit))return(0);
+ return(1);
+}
+
+// U_EMRSETARCDIRECTION 57
+int U_EMRSETARCDIRECTION_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRSETMITERLIMIT 58
+int U_EMRSETMITERLIMIT_safe(const char *record){
+ return(core3_safe(record));
+}
+
+
+// U_EMRBEGINPATH 59
+int U_EMRBEGINPATH_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRBEGINPATH));
+}
+
+// U_EMRENDPATH 60
+int U_EMRENDPATH_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRENDPATH));
+}
+
+// U_EMRCLOSEFIGURE 61
+int U_EMRCLOSEFIGURE_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRCLOSEFIGURE));
+}
+
+// U_EMRFILLPATH 62
+int U_EMRFILLPATH_safe(const char *record){
+ return(core4_safe(record));
+}
+
+// U_EMRSTROKEANDFILLPATH 63
+int U_EMRSTROKEANDFILLPATH_safe(const char *record){
+ return(core4_safe(record));
+}
+
+// U_EMRSTROKEPATH 64
+int U_EMRSTROKEPATH_safe(const char *record){
+ return(core4_safe(record));
+}
+
+// U_EMRFLATTENPATH 65
+int U_EMRFLATTENPATH_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRFLATTENPATH));
+}
+
+// U_EMRWIDENPATH 66
+int U_EMRWIDENPATH_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRWIDENPATH));
+}
+
+// U_EMRSELECTCLIPPATH 67
+int U_EMRSELECTCLIPPATH_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRABORTPATH 68
+int U_EMRABORTPATH_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRABORTPATH));
+}
+
+// U_EMRUNDEF69 69
+#define U_EMRUNDEF69_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+
+// U_EMRCOMMENT 70 Comment (any binary data, interpretation is program specific)
+int U_EMRCOMMENT_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRCOMMENT))return(0);
+ PU_EMRCOMMENT pEmr = (PU_EMRCOMMENT)(record);
+ int cbData = pEmr->cbData;
+ const char *blimit =record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(record, cbData + sizeof(U_SIZE_EMRCOMMENT), blimit))return(0);
+ return(1);
+}
+
+// U_EMRFILLRGN 71
+int U_EMRFILLRGN_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRFILLRGN))return(0);
+ PU_EMRFILLRGN pEmr = (PU_EMRFILLRGN)(record);
+ int cbRgnData = pEmr->cbRgnData;
+ const char *blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0);
+ return(rgndata_safe(pEmr->RgnData, cbRgnData));
+}
+
+// U_EMRFRAMERGN 72
+int U_EMRFRAMERGN_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRFRAMERGN))return(0);
+ PU_EMRFRAMERGN pEmr = (PU_EMRFRAMERGN)(record);
+ int cbRgnData = pEmr->cbRgnData;
+ const char *blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0);
+ return(rgndata_safe(pEmr->RgnData, cbRgnData));
+}
+
+// U_EMRINVERTRGN 73
+int U_EMRINVERTRGN_safe(const char *record){
+ return(core11_safe(record));
+}
+
+// U_EMRPAINTRGN 74
+int U_EMRPAINTRGN_safe(const char *record){
+ return(core11_safe(record));
+}
+
+// U_EMREXTSELECTCLIPRGN 75
+int U_EMREXTSELECTCLIPRGN_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMREXTSELECTCLIPRGN))return(0);
+ PU_EMREXTSELECTCLIPRGN pEmr = (PU_EMREXTSELECTCLIPRGN)(record);
+ int cbRgnData = pEmr->cbRgnData;
+ /* data size can be 0 with COPY mode, it means clear the clip region. */
+ if(pEmr->iMode == U_RGN_COPY && !cbRgnData)return(1);
+ const char *blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(pEmr->RgnData, cbRgnData, blimit))return(0);
+ return(rgndata_safe(pEmr->RgnData, cbRgnData));
+}
+
+// U_EMRBITBLT 76
+int U_EMRBITBLT_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRBITBLT))return(0);
+ PU_EMRBITBLT pEmr = (PU_EMRBITBLT) (record);
+ const char *blimit = record + pEmr->emr.nSize;
+ U_OFFBMISRC offBmiSrc = pEmr->offBmiSrc;
+ U_CBBMISRC cbBmiSrc = pEmr->cbBmiSrc;
+ U_OFFBITSSRC offBitsSrc = pEmr->offBitsSrc;
+ U_CBBITS cbBitsSrc = pEmr->cbBitsSrc;
+ uint32_t iUsageSrc = pEmr->iUsageSrc;
+ return(DIB_safe(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit));
+}
+
+// U_EMRSTRETCHBLT 77
+int U_EMRSTRETCHBLT_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRSTRETCHBLT))return(0);
+ PU_EMRBITBLT pEmr = (PU_EMRBITBLT) (record);
+ const char *blimit = record + pEmr->emr.nSize;
+ U_OFFBMISRC offBmiSrc = pEmr->offBmiSrc;
+ U_CBBMISRC cbBmiSrc = pEmr->cbBmiSrc;
+ U_OFFBITSSRC offBitsSrc = pEmr->offBitsSrc;
+ U_CBBITS cbBitsSrc = pEmr->cbBitsSrc;
+ uint32_t iUsageSrc = pEmr->iUsageSrc;
+ return(DIB_safe(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit));
+}
+
+// U_EMRMASKBLT 78
+int U_EMRMASKBLT_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRMASKBLT))return(0);
+ PU_EMRMASKBLT pEmr = (PU_EMRMASKBLT) (record);
+ const char *blimit = record + pEmr->emr.nSize;
+ U_OFFBMISRC offBmiSrc = pEmr->offBmiSrc;
+ U_CBBMISRC cbBmiSrc = pEmr->cbBmiSrc;
+ U_OFFBMIMSK offBmiMask = pEmr->offBmiMask;
+ U_CBBMIMSK cbBmiMask = pEmr->cbBmiMask;
+ U_OFFBITSSRC offBitsSrc = pEmr->offBitsSrc;
+ U_CBBITSSRC cbBitsSrc = pEmr->cbBitsSrc;
+ U_OFFBITSMSK offBitsMask = pEmr->offBitsMask;
+ U_CBBITSMSK cbBitsMask = pEmr->cbBitsMask;
+ uint32_t iUsageSrc = pEmr->iUsageSrc;
+ uint32_t iUsageMask = pEmr->iUsageMask;
+ if(!DIB_safe(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit))return(0);
+ return(DIB_safe(record, iUsageMask, offBmiMask, cbBmiMask, offBitsMask, cbBitsMask, blimit));
+}
+
+// U_EMRPLGBLT 79
+int U_EMRPLGBLT_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRPLGBLT))return(0);
+ PU_EMRPLGBLT pEmr = (PU_EMRPLGBLT) (record);
+ const char *blimit = record + pEmr->emr.nSize;
+ U_OFFBMISRC offBmiSrc = pEmr->offBmiSrc;
+ U_CBBMISRC cbBmiSrc = pEmr->cbBmiSrc;
+ U_OFFBMIMSK offBmiMask = pEmr->offBmiMask;
+ U_CBBMIMSK cbBmiMask = pEmr->cbBmiMask;
+ U_OFFBITSSRC offBitsSrc = pEmr->offBitsSrc;
+ U_CBBITSSRC cbBitsSrc = pEmr->cbBitsSrc;
+ U_OFFBITSMSK offBitsMask = pEmr->offBitsMask;
+ U_CBBITSMSK cbBitsMask = pEmr->cbBitsMask;
+ uint32_t iUsageSrc = pEmr->iUsageSrc;
+ uint32_t iUsageMask = pEmr->iUsageMask;
+ if(!DIB_safe(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit))return(0);
+ return(DIB_safe(record, iUsageMask, offBmiMask, cbBmiMask, offBitsMask, cbBitsMask, blimit));
+}
+
+// U_EMRSETDIBITSTODEVICE 80
+int U_EMRSETDIBITSTODEVICE_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRSETDIBITSTODEVICE))return(0);
+ PU_EMRSETDIBITSTODEVICE pEmr = (PU_EMRSETDIBITSTODEVICE) (record);
+ const char *blimit = record + pEmr->emr.nSize;
+ U_OFFBMISRC offBmiSrc = pEmr->offBmiSrc;
+ U_CBBMISRC cbBmiSrc = pEmr->cbBmiSrc;
+ U_OFFBITSSRC offBitsSrc = pEmr->offBitsSrc;
+ U_CBBITSSRC cbBitsSrc = pEmr->cbBitsSrc;
+ uint32_t iUsageSrc = pEmr->iUsageSrc;
+ return(DIB_safe(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit));
+}
+
+// U_EMRSTRETCHDIBITS 81
+int U_EMRSTRETCHDIBITS_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRSTRETCHDIBITS))return(0);
+ PU_EMRSTRETCHDIBITS pEmr = (PU_EMRSTRETCHDIBITS) (record);
+ const char *blimit = record + pEmr->emr.nSize;
+ U_OFFBMISRC offBmiSrc = pEmr->offBmiSrc;
+ U_CBBMISRC cbBmiSrc = pEmr->cbBmiSrc;
+ U_OFFBITSSRC offBitsSrc = pEmr->offBitsSrc;
+ U_CBBITSSRC cbBitsSrc = pEmr->cbBitsSrc;
+ uint32_t iUsageSrc = pEmr->iUsageSrc;
+ return(DIB_safe(record, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, blimit));
+}
+
+// U_EMREXTCREATEFONTINDIRECTW 82
+int U_EMREXTCREATEFONTINDIRECTW_safe(const char *record){
+ /* Panose or logfont, LogFontExDv is not supported. Test smallest to largest */
+ if(core5_safe(record, U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT))return(1);
+ return(core5_safe(record, U_SIZE_EMREXTCREATEFONTINDIRECTW_LOGFONT_PANOSE));
+}
+
+// U_EMREXTTEXTOUTA 83
+int U_EMREXTTEXTOUTA_safe(const char *record){
+ return(core8_safe(record));
+}
+
+// U_EMREXTTEXTOUTW 84
+int U_EMREXTTEXTOUTW_safe(const char *record){
+ return(core8_safe(record));
+}
+
+// U_EMRPOLYBEZIER16 85
+/**
+ \brief Convert a pointer to a U_EMR_POLYBEZIER16 record.
+ \param record pointer to a buffer holding the EMR record
+*/
+int U_EMRPOLYBEZIER16_safe(const char *record){
+ return(core6_safe(record));
+}
+
+// U_EMRPOLYGON16 86
+int U_EMRPOLYGON16_safe(const char *record){
+ return(core6_safe(record));
+}
+
+// U_EMRPOLYLINE16 87
+int U_EMRPOLYLINE16_safe(const char *record){
+ return(core6_safe(record));
+}
+
+// U_EMRPOLYBEZIERTO16 88
+int U_EMRPOLYBEZIERTO16_safe(const char *record){
+ return(core6_safe(record));
+}
+
+// U_EMRPOLYLINETO16 89
+/**
+ \brief Convert a pointer to a U_EMR_POLYLINETO16 record.
+ \param record pointer to a buffer holding the EMR record
+*/
+int U_EMRPOLYLINETO16_safe(const char *record){
+ return(core6_safe(record));
+}
+
+// U_EMRPOLYPOLYLINE16 90
+int U_EMRPOLYPOLYLINE16_safe(const char *record){
+ return(core10_safe(record));
+}
+
+// U_EMRPOLYPOLYGON16 91
+int U_EMRPOLYPOLYGON16_safe(const char *record){
+ return(core10_safe(record));
+}
+
+
+// U_EMRPOLYDRAW16 92
+int U_EMRPOLYDRAW16_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRPOLYDRAW16))return(0);
+ PU_EMRPOLYDRAW16 pEmr = (PU_EMRPOLYDRAW16)(record);
+ int count = pEmr->cpts;
+ const char *blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(pEmr->apts, count*sizeof(U_POINT16), blimit))return(0);
+ return(1);
+}
+
+// U_EMRCREATEMONOBRUSH 93
+int U_EMRCREATEMONOBRUSH_safe(const char *record){
+ return(core12_safe(record));
+}
+
+// U_EMRCREATEDIBPATTERNBRUSHPT_safe 94
+int U_EMRCREATEDIBPATTERNBRUSHPT_safe(const char *record){
+ return(core12_safe(record));
+}
+
+
+// U_EMREXTCREATEPEN 95
+int U_EMREXTCREATEPEN_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMREXTCREATEPEN))return(0);
+ PU_EMREXTCREATEPEN pEmr = (PU_EMREXTCREATEPEN)(record);
+ const char *blimit = record + pEmr->emr.nSize;
+ U_OFFBMI offBmi = pEmr->offBmi;
+ U_CBBMI cbBmi = pEmr->cbBmi;
+ U_OFFBITS offBits = pEmr->offBits;
+ U_CBBITS cbBits = pEmr->cbBits;
+ if(!DIB_safe(record, U_DIB_RGB_COLORS, offBmi, cbBmi, offBits, cbBits, blimit))return(0);
+ return(extlogpen_safe((PU_EXTLOGPEN) &(pEmr->elp), blimit));
+}
+
+// U_EMRPOLYTEXTOUTA 96 NOT IMPLEMENTED, denigrated after Windows NT
+#define U_EMRPOLYTEXTOUTA_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMRPOLYTEXTOUTW 97 NOT IMPLEMENTED, denigrated after Windows NT
+#define U_EMRPOLYTEXTOUTW_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+
+// U_EMRSETICMMODE 98
+int U_EMRSETICMMODE_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRCREATECOLORSPACE 99
+int U_EMRCREATECOLORSPACE_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRCREATECOLORSPACE));
+}
+
+// U_EMRSETCOLORSPACE 100
+int U_EMRSETCOLORSPACE_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRDELETECOLORSPACE 101
+int U_EMRDELETECOLORSPACE_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRGLSRECORD 102 Not implemented
+#define U_EMRGLSRECORD_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMRGLSBOUNDEDRECORD 103 Not implemented
+#define U_EMRGLSBOUNDEDRECORD_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+
+// U_EMRPIXELFORMAT 104
+int U_EMRPIXELFORMAT_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRPIXELFORMAT));
+}
+
+// U_EMRDRAWESCAPE 105 Not implemented
+#define U_EMRDRAWESCAPE_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMREXTESCAPE 106 Not implemented
+#define U_EMREXTESCAPE_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMRUNDEF107 107 Not implemented
+#define U_EMRUNDEF107_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+
+// U_EMRSMALLTEXTOUT 108
+int U_EMRSMALLTEXTOUT_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRSMALLTEXTOUT))return(0);
+ PU_EMRSMALLTEXTOUT pEmr = (PU_EMRSMALLTEXTOUT)(record);
+ int roff=sizeof(U_EMRSMALLTEXTOUT); // offset to the start of the variable fields
+ int fuOptions = pEmr->fuOptions;
+ int cChars = pEmr->cChars;
+ const char *blimit = record + pEmr->emr.nSize;
+ if(!(fuOptions & U_ETO_NO_RECT)){
+ if(IS_MEM_UNSAFE(record, roff + sizeof(U_RECTL), blimit))return(0);
+ }
+ if(IS_MEM_UNSAFE(record, roff + sizeof(U_RECTL) + cChars, blimit))return(0);
+ return(1);
+}
+
+// U_EMRFORCEUFIMAPPING 109 Not implemented
+#define U_EMRFORCEUFIMAPPING_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMRNAMEDESCAPE 110 Not implemented
+#define U_EMRNAMEDESCAPE_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMRCOLORCORRECTPALETTE 111 Not implemented
+#define U_EMRCOLORCORRECTPALETTE_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMRSETICMPROFILEA 112 Not implemented
+#define U_EMRSETICMPROFILEA_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMRSETICMPROFILEW 113 Not implemented
+#define U_EMRSETICMPROFILEW_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+
+// U_EMRALPHABLEND 114
+int U_EMRALPHABLEND_safe(const char *record){
+ return(core13_safe(record));
+}
+
+// U_EMRSETLAYOUT 115
+int U_EMRSETLAYOUT_safe(const char *record){
+ return(core3_safe(record));
+}
+
+// U_EMRTRANSPARENTBLT 116
+int U_EMRTRANSPARENTBLT_safe(const char *record){
+ return(core13_safe(record));
+}
+
+
+// U_EMRUNDEF117 117 Not implemented
+#define U_EMRUNDEF117_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMRGRADIENTFILL 118
+int U_EMRGRADIENTFILL_safe(const char *record){
+ if(!core5_safe(record, U_SIZE_EMRGRADIENTFILL))return(0);
+ PU_EMRGRADIENTFILL pEmr = (PU_EMRGRADIENTFILL)(record);
+ int nTriVert = pEmr->nTriVert;
+ int nGradObj = pEmr->nGradObj;
+ int ulMode = pEmr->ulMode;
+ const char *blimit = record + pEmr->emr.nSize;
+ if(IS_MEM_UNSAFE(record, nTriVert*sizeof(U_TRIVERTEX), blimit))return(0);
+ record += nTriVert * sizeof(U_TRIVERTEX);
+ if(nGradObj){
+ if( ulMode == U_GRADIENT_FILL_TRIANGLE){
+ if(IS_MEM_UNSAFE(record, nGradObj*sizeof(U_GRADIENT3), blimit))return(0);
+ }
+ else if(ulMode == U_GRADIENT_FILL_RECT_H || ulMode == U_GRADIENT_FILL_RECT_V){
+ if(IS_MEM_UNSAFE(record, nGradObj*sizeof(U_GRADIENT4), blimit))return(0);
+ }
+ }
+ return(1);
+}
+
+// U_EMRSETLINKEDUFIS 119 Not implemented
+#define U_EMRSETLINKEDUFIS_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMRSETTEXTJUSTIFICATION120 Not implemented (denigrated)
+#define U_EMRSETTEXTJUSTIFICATION_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+// U_EMRCOLORMATCHTOTARGETW 121 Not implemented
+#define U_EMRCOLORMATCHTOTARGETW_safe(A) U_EMRNOTIMPLEMENTED_safe(A) //!< Not implemented.
+
+// U_EMRCREATECOLORSPACEW 122
+int U_EMRCREATECOLORSPACEW_safe(const char *record){
+ return(core5_safe(record, U_SIZE_EMRCREATECOLORSPACEW));
+}
+
+//! \endcond
+
+/**
+ \brief Test an EMF record in memory from Big Endian to Little Endian.
+ \return 0 on failure, 1 on success
+ \param record pointer to the EMF record in memory
+
+ Normally this would be called immediately after reading a record from a file
+ and having called U_emf_record_sizeok().
+ It is NOT safe to call this routine without first calling U_emf_record_sizeok)()!
+ If the file has been converted from one endian to another calling this routine is
+ not necessary, because those routines also perform these checks.
+*/
+int U_emf_record_safe(const char *record){
+ int rstatus=1;
+
+ if(!record)return(0); // programming error
+
+ switch (U_EMRTYPE(record))
+ {
+ case U_EMR_HEADER: rstatus=U_EMRHEADER_safe(record); break;
+ case U_EMR_POLYBEZIER: rstatus=U_EMRPOLYBEZIER_safe(record); break;
+ case U_EMR_POLYGON: rstatus=U_EMRPOLYGON_safe(record); break;
+ case U_EMR_POLYLINE: rstatus=U_EMRPOLYLINE_safe(record); break;
+ case U_EMR_POLYBEZIERTO: rstatus=U_EMRPOLYBEZIERTO_safe(record); break;
+ case U_EMR_POLYLINETO: rstatus=U_EMRPOLYLINETO_safe(record); break;
+ case U_EMR_POLYPOLYLINE: rstatus=U_EMRPOLYPOLYLINE_safe(record); break;
+ case U_EMR_POLYPOLYGON: rstatus=U_EMRPOLYPOLYGON_safe(record); break;
+ case U_EMR_SETWINDOWEXTEX: rstatus=U_EMRSETWINDOWEXTEX_safe(record); break;
+ case U_EMR_SETWINDOWORGEX: rstatus=U_EMRSETWINDOWORGEX_safe(record); break;
+ case U_EMR_SETVIEWPORTEXTEX: rstatus=U_EMRSETVIEWPORTEXTEX_safe(record); break;
+ case U_EMR_SETVIEWPORTORGEX: rstatus=U_EMRSETVIEWPORTORGEX_safe(record); break;
+ case U_EMR_SETBRUSHORGEX: rstatus=U_EMRSETBRUSHORGEX_safe(record); break;
+ case U_EMR_EOF: rstatus=U_EMREOF_safe(record); break;
+ case U_EMR_SETPIXELV: rstatus=U_EMRSETPIXELV_safe(record); break;
+ case U_EMR_SETMAPPERFLAGS: rstatus=U_EMRSETMAPPERFLAGS_safe(record); break;
+ case U_EMR_SETMAPMODE: rstatus=U_EMRSETMAPMODE_safe(record); break;
+ case U_EMR_SETBKMODE: rstatus=U_EMRSETBKMODE_safe(record); break;
+ case U_EMR_SETPOLYFILLMODE: rstatus=U_EMRSETPOLYFILLMODE_safe(record); break;
+ case U_EMR_SETROP2: rstatus=U_EMRSETROP2_safe(record); break;
+ case U_EMR_SETSTRETCHBLTMODE: rstatus=U_EMRSETSTRETCHBLTMODE_safe(record); break;
+ case U_EMR_SETTEXTALIGN: rstatus=U_EMRSETTEXTALIGN_safe(record); break;
+ case U_EMR_SETCOLORADJUSTMENT: rstatus=U_EMRSETCOLORADJUSTMENT_safe(record); break;
+ case U_EMR_SETTEXTCOLOR: rstatus=U_EMRSETTEXTCOLOR_safe(record); break;
+ case U_EMR_SETBKCOLOR: rstatus=U_EMRSETBKCOLOR_safe(record); break;
+ case U_EMR_OFFSETCLIPRGN: rstatus=U_EMROFFSETCLIPRGN_safe(record); break;
+ case U_EMR_MOVETOEX: rstatus=U_EMRMOVETOEX_safe(record); break;
+ case U_EMR_SETMETARGN: rstatus=U_EMRSETMETARGN_safe(record); break;
+ case U_EMR_EXCLUDECLIPRECT: rstatus=U_EMREXCLUDECLIPRECT_safe(record); break;
+ case U_EMR_INTERSECTCLIPRECT: rstatus=U_EMRINTERSECTCLIPRECT_safe(record); break;
+ case U_EMR_SCALEVIEWPORTEXTEX: rstatus=U_EMRSCALEVIEWPORTEXTEX_safe(record); break;
+ case U_EMR_SCALEWINDOWEXTEX: rstatus=U_EMRSCALEWINDOWEXTEX_safe(record); break;
+ case U_EMR_SAVEDC: rstatus=U_EMRSAVEDC_safe(record); break;
+ case U_EMR_RESTOREDC: rstatus=U_EMRRESTOREDC_safe(record); break;
+ case U_EMR_SETWORLDTRANSFORM: rstatus=U_EMRSETWORLDTRANSFORM_safe(record); break;
+ case U_EMR_MODIFYWORLDTRANSFORM: rstatus=U_EMRMODIFYWORLDTRANSFORM_safe(record); break;
+ case U_EMR_SELECTOBJECT: rstatus=U_EMRSELECTOBJECT_safe(record); break;
+ case U_EMR_CREATEPEN: rstatus=U_EMRCREATEPEN_safe(record); break;
+ case U_EMR_CREATEBRUSHINDIRECT: rstatus=U_EMRCREATEBRUSHINDIRECT_safe(record); break;
+ case U_EMR_DELETEOBJECT: rstatus=U_EMRDELETEOBJECT_safe(record); break;
+ case U_EMR_ANGLEARC: rstatus=U_EMRANGLEARC_safe(record); break;
+ case U_EMR_ELLIPSE: rstatus=U_EMRELLIPSE_safe(record); break;
+ case U_EMR_RECTANGLE: rstatus=U_EMRRECTANGLE_safe(record); break;
+ case U_EMR_ROUNDRECT: rstatus=U_EMRROUNDRECT_safe(record); break;
+ case U_EMR_ARC: rstatus=U_EMRARC_safe(record); break;
+ case U_EMR_CHORD: rstatus=U_EMRCHORD_safe(record); break;
+ case U_EMR_PIE: rstatus=U_EMRPIE_safe(record); break;
+ case U_EMR_SELECTPALETTE: rstatus=U_EMRSELECTPALETTE_safe(record); break;
+ case U_EMR_CREATEPALETTE: rstatus=U_EMRCREATEPALETTE_safe(record); break;
+ case U_EMR_SETPALETTEENTRIES: rstatus=U_EMRSETPALETTEENTRIES_safe(record); break;
+ case U_EMR_RESIZEPALETTE: rstatus=U_EMRRESIZEPALETTE_safe(record); break;
+ case U_EMR_REALIZEPALETTE: rstatus=U_EMRREALIZEPALETTE_safe(record); break;
+ case U_EMR_EXTFLOODFILL: rstatus=U_EMREXTFLOODFILL_safe(record); break;
+ case U_EMR_LINETO: rstatus=U_EMRLINETO_safe(record); break;
+ case U_EMR_ARCTO: rstatus=U_EMRARCTO_safe(record); break;
+ case U_EMR_POLYDRAW: rstatus=U_EMRPOLYDRAW_safe(record); break;
+ case U_EMR_SETARCDIRECTION: rstatus=U_EMRSETARCDIRECTION_safe(record); break;
+ case U_EMR_SETMITERLIMIT: rstatus=U_EMRSETMITERLIMIT_safe(record); break;
+ case U_EMR_BEGINPATH: rstatus=U_EMRBEGINPATH_safe(record); break;
+ case U_EMR_ENDPATH: rstatus=U_EMRENDPATH_safe(record); break;
+ case U_EMR_CLOSEFIGURE: rstatus=U_EMRCLOSEFIGURE_safe(record); break;
+ case U_EMR_FILLPATH: rstatus=U_EMRFILLPATH_safe(record); break;
+ case U_EMR_STROKEANDFILLPATH: rstatus=U_EMRSTROKEANDFILLPATH_safe(record); break;
+ case U_EMR_STROKEPATH: rstatus=U_EMRSTROKEPATH_safe(record); break;
+ case U_EMR_FLATTENPATH: rstatus=U_EMRFLATTENPATH_safe(record); break;
+ case U_EMR_WIDENPATH: rstatus=U_EMRWIDENPATH_safe(record); break;
+ case U_EMR_SELECTCLIPPATH: rstatus=U_EMRSELECTCLIPPATH_safe(record); break;
+ case U_EMR_ABORTPATH: rstatus=U_EMRABORTPATH_safe(record); break;
+ case U_EMR_UNDEF69: rstatus=U_EMRUNDEF69_safe(record); break;
+ case U_EMR_COMMENT: rstatus=U_EMRCOMMENT_safe(record); break;
+ case U_EMR_FILLRGN: rstatus=U_EMRFILLRGN_safe(record); break;
+ case U_EMR_FRAMERGN: rstatus=U_EMRFRAMERGN_safe(record); break;
+ case U_EMR_INVERTRGN: rstatus=U_EMRINVERTRGN_safe(record); break;
+ case U_EMR_PAINTRGN: rstatus=U_EMRPAINTRGN_safe(record); break;
+ case U_EMR_EXTSELECTCLIPRGN: rstatus=U_EMREXTSELECTCLIPRGN_safe(record); break;
+ case U_EMR_BITBLT: rstatus=U_EMRBITBLT_safe(record); break;
+ case U_EMR_STRETCHBLT: rstatus=U_EMRSTRETCHBLT_safe(record); break;
+ case U_EMR_MASKBLT: rstatus=U_EMRMASKBLT_safe(record); break;
+ case U_EMR_PLGBLT: rstatus=U_EMRPLGBLT_safe(record); break;
+ case U_EMR_SETDIBITSTODEVICE: rstatus=U_EMRSETDIBITSTODEVICE_safe(record); break;
+ case U_EMR_STRETCHDIBITS: rstatus=U_EMRSTRETCHDIBITS_safe(record); break;
+ case U_EMR_EXTCREATEFONTINDIRECTW: rstatus=U_EMREXTCREATEFONTINDIRECTW_safe(record); break;
+ case U_EMR_EXTTEXTOUTA: rstatus=U_EMREXTTEXTOUTA_safe(record); break;
+ case U_EMR_EXTTEXTOUTW: rstatus=U_EMREXTTEXTOUTW_safe(record); break;
+ case U_EMR_POLYBEZIER16: rstatus=U_EMRPOLYBEZIER16_safe(record); break;
+ case U_EMR_POLYGON16: rstatus=U_EMRPOLYGON16_safe(record); break;
+ case U_EMR_POLYLINE16: rstatus=U_EMRPOLYLINE16_safe(record); break;
+ case U_EMR_POLYBEZIERTO16: rstatus=U_EMRPOLYBEZIERTO16_safe(record); break;
+ case U_EMR_POLYLINETO16: rstatus=U_EMRPOLYLINETO16_safe(record); break;
+ case U_EMR_POLYPOLYLINE16: rstatus=U_EMRPOLYPOLYLINE16_safe(record); break;
+ case U_EMR_POLYPOLYGON16: rstatus=U_EMRPOLYPOLYGON16_safe(record); break;
+ case U_EMR_POLYDRAW16: rstatus=U_EMRPOLYDRAW16_safe(record); break;
+ case U_EMR_CREATEMONOBRUSH: rstatus=U_EMRCREATEMONOBRUSH_safe(record); break;
+ case U_EMR_CREATEDIBPATTERNBRUSHPT: rstatus=U_EMRCREATEDIBPATTERNBRUSHPT_safe(record); break;
+ case U_EMR_EXTCREATEPEN: rstatus=U_EMREXTCREATEPEN_safe(record); break;
+ case U_EMR_POLYTEXTOUTA: rstatus=U_EMRPOLYTEXTOUTA_safe(record); break;
+ case U_EMR_POLYTEXTOUTW: rstatus=U_EMRPOLYTEXTOUTW_safe(record); break;
+ case U_EMR_SETICMMODE: rstatus=U_EMRSETICMMODE_safe(record); break;
+ case U_EMR_CREATECOLORSPACE: rstatus=U_EMRCREATECOLORSPACE_safe(record); break;
+ case U_EMR_SETCOLORSPACE: rstatus=U_EMRSETCOLORSPACE_safe(record); break;
+ case U_EMR_DELETECOLORSPACE: rstatus=U_EMRDELETECOLORSPACE_safe(record); break;
+ case U_EMR_GLSRECORD: rstatus=U_EMRGLSRECORD_safe(record); break;
+ case U_EMR_GLSBOUNDEDRECORD: rstatus=U_EMRGLSBOUNDEDRECORD_safe(record); break;
+ case U_EMR_PIXELFORMAT: rstatus=U_EMRPIXELFORMAT_safe(record); break;
+ case U_EMR_DRAWESCAPE: rstatus=U_EMRDRAWESCAPE_safe(record); break;
+ case U_EMR_EXTESCAPE: rstatus=U_EMREXTESCAPE_safe(record); break;
+ case U_EMR_UNDEF107: rstatus=U_EMRUNDEF107_safe(record); break;
+ case U_EMR_SMALLTEXTOUT: rstatus=U_EMRSMALLTEXTOUT_safe(record); break;
+ case U_EMR_FORCEUFIMAPPING: rstatus=U_EMRFORCEUFIMAPPING_safe(record); break;
+ case U_EMR_NAMEDESCAPE: rstatus=U_EMRNAMEDESCAPE_safe(record); break;
+ case U_EMR_COLORCORRECTPALETTE: rstatus=U_EMRCOLORCORRECTPALETTE_safe(record); break;
+ case U_EMR_SETICMPROFILEA: rstatus=U_EMRSETICMPROFILEA_safe(record); break;
+ case U_EMR_SETICMPROFILEW: rstatus=U_EMRSETICMPROFILEW_safe(record); break;
+ case U_EMR_ALPHABLEND: rstatus=U_EMRALPHABLEND_safe(record); break;
+ case U_EMR_SETLAYOUT: rstatus=U_EMRSETLAYOUT_safe(record); break;
+ case U_EMR_TRANSPARENTBLT: rstatus=U_EMRTRANSPARENTBLT_safe(record); break;
+ case U_EMR_UNDEF117: rstatus=U_EMRUNDEF117_safe(record); break;
+ case U_EMR_GRADIENTFILL: rstatus=U_EMRGRADIENTFILL_safe(record); break;
+ case U_EMR_SETLINKEDUFIS: rstatus=U_EMRSETLINKEDUFIS_safe(record); break;
+ case U_EMR_SETTEXTJUSTIFICATION: rstatus=U_EMRSETTEXTJUSTIFICATION_safe(record); break;
+ case U_EMR_COLORMATCHTOTARGETW: rstatus=U_EMRCOLORMATCHTOTARGETW_safe(record); break;
+ case U_EMR_CREATECOLORSPACEW: rstatus=U_EMRCREATECOLORSPACEW_safe(record); break;
+ default: rstatus=U_EMRNOTIMPLEMENTED_safe(record); break;
+ } //end of switch
+ return(rstatus);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/3rdparty/libuemf/uemf_safe.h b/src/3rdparty/libuemf/uemf_safe.h
new file mode 100644
index 0000000..0c9e3cc
--- /dev/null
+++ b/src/3rdparty/libuemf/uemf_safe.h
@@ -0,0 +1,32 @@
+/**
+ @file uemf_safe.h
+
+ @brief Defintions and prototype for function for converting EMF records between Big Endian and Little Endian byte orders.
+*/
+
+/*
+File: uemf_endian.h
+Version: 0.0.2
+Date: 26-MAR-2015
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2015 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifndef _UEMF_SAFE_
+#define _UEMF_SAFE_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// prototypes
+int U_emf_record_safe(const char *record);
+int bitmapinfo_safe(const char *Bmi, const char *blimit);
+//! \endcond
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UEMF_SAFE_ */
diff --git a/src/3rdparty/libuemf/uemf_utf.c b/src/3rdparty/libuemf/uemf_utf.c
new file mode 100644
index 0000000..5c65078
--- /dev/null
+++ b/src/3rdparty/libuemf/uemf_utf.c
@@ -0,0 +1,720 @@
+/**
+ @file uemf_utf.c
+
+ @brief Functions for manipulating UTF and various types of text.
+
+
+ Compile with "U_VALGRIND" defined defined to enable code which lets valgrind check each record for
+ uninitialized data.
+
+ Compile with "SOL8" defined for Solaris 8 or 9 (Sparc).
+*/
+
+/*
+File: uemf_utf.c
+Version: 0.0.5
+Date: 29-JAN-2014
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2014 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <iconv.h>
+#include <wchar.h>
+#include <errno.h>
+#include <string.h>
+#include <limits.h> // for INT_MAX, INT_MIN
+#include <math.h> // for U_ROUND()
+#include "uemf_utf.h"
+
+//! \cond
+/* Prototypes for functions used here and defined in uemf_endian.c, but which are not supposed
+to be used in end user code. */
+
+void U_swap2(void *ul, unsigned int count);
+//! \endcond
+
+/* ******************************************************************************************** */
+
+/** \cond */
+/* iconv() has a funny cast on some older systems, on most recent ones
+ it is just char **. This tries to work around the issue. If you build this
+ on another funky system this code may need to be modified, or define ICONV_CAST
+ on the compile line(but it may be tricky).
+*/
+#if _LIBICONV_VERSION == 0x0109
+# define ICONV_CAST (const char **)
+#endif // _LIBICONV_VERSION 0x0109
+#ifdef SOL8
+# define ICONV_CAST (const char **)
+#endif //SOL8
+#if !defined(ICONV_CAST)
+# define ICONV_CAST (char **)
+#endif //ICONV_CAST
+/** \endcond */
+
+/* **********************************************************************************************
+These functions are used for development and debugging and should be be includied in production code.
+*********************************************************************************************** */
+
+/**
+ \brief Dump a UTF8 string. Not for use in production code.
+ \param src string to examine
+*/
+void wchar8show(
+ const char *src
+ ){
+ if(!src){
+ printf("char show <NULL>\n");
+ }
+ else {
+ printf("char show\n");
+ size_t srclen = 0;
+ while(*src){ printf("%d %d %x\n",(int) srclen,*src,*src); srclen++; src++; }
+ }
+}
+
+/**
+ \brief Dump a UTF16 string. Not for use in production code.
+ \param src string to examine
+*/
+void wchar16show(
+ const uint16_t *src
+ ){
+ if(!src){
+ printf("uint16_t show <NULL>\n");
+ }
+ else {
+ printf("uint16_t show\n");
+ size_t srclen = 0;
+ while(*src){ printf("%d %d %x\n",(int) srclen,*src,*src); srclen++; src++; }
+ }
+}
+
+/**
+ \brief Dump a UTF32 string. Not for use in production code.
+*/
+void wchar32show(
+ const uint32_t *src
+ ){
+ if(!src){
+ printf("uint32_t show <NULL>\n");
+ }
+ else {
+ printf("uint32_t show\n");
+ size_t srclen = 0;
+ while(*src){ printf("%d %d %x\n",(int) srclen,*src,*src); srclen++; src++; }
+ }
+}
+
+/**
+ \brief Dump a wchar_t string. Not for use in production code.
+ \param src string to examine
+*/
+void wchartshow(
+ const wchar_t *src
+ ){
+ uint32_t val;
+ if(!src){
+ printf("wchar_t show <NULL>\n");
+ }
+ else {
+ printf("wchar_t show\n");
+ size_t srclen = 0;
+ if(!src)return;
+ while(*src){
+ val = *src; // because *src is wchar_t is not strictly an integer type, can cause warnings on next line
+ printf("%d %d %x\n",(int) srclen,val,val);
+ srclen++;
+ src++;
+ }
+ }
+}
+
+/* **********************************************************************************************
+These functions are used for character type conversions, Image conversions, and other
+utility operations
+*********************************************************************************************** */
+
+/**
+ \brief Find the number of (storage) characters in a 16 bit character string, not including terminator.
+ \param src string to examine
+*/
+size_t wchar16len(
+ const uint16_t *src
+ ){
+ size_t srclen = 0;
+ if(src){
+ while(*src){ srclen++; src++; }
+ }
+ return(srclen);
+}
+
+/**
+ \brief Find the number of (storage) characters in a 32 bit character string, not including terminator.
+ \param src string to examine
+*/
+size_t wchar32len(
+ const uint32_t *src
+ ){
+ size_t srclen = 0;
+ if(src){
+ while(*src){ srclen++; src++; }
+ }
+ return(srclen);
+}
+
+/**
+ \brief Strncpy for wchar16 (UTF16).
+ \param dst destination (already allocated)
+ \param src source
+ \param nchars number of characters to copy
+*/
+void wchar16strncpy(
+ uint16_t *dst,
+ const uint16_t *src,
+ size_t nchars
+ ){
+ if(src){
+ for(;nchars;nchars--,dst++,src++){
+ *dst = *src;
+ if(!*src)break;
+ }
+ }
+}
+
+/**
+ \brief Fill the output string with N characters, if the input string is shorter than N, pad with nulls.
+ \param dst destination (already allocated)
+ \param src source
+ \param nchars number of characters to copy
+
+*/
+void wchar16strncpypad(
+ uint16_t *dst,
+ const uint16_t *src,
+ size_t nchars
+ ){
+ if(src){
+ for(;*src && nchars;nchars--,dst++,src++){ *dst = *src; }
+ for(;nchars;nchars--,dst++){ *dst = 0; } // Pad the remainder
+ }
+}
+
+/* For the following converstion functions, remember that iconv() modifies ALL of its parameters,
+ so save a pointer to the destination buffer!!!!
+ It isn't clear that terminators are being
+ copied properly, so be sure allocated space is a bit larger and cleared.
+*/
+
+/**
+ \brief Convert a UTF32LE string to a UTF16LE string.
+ \returns pointer to new string or NULL if it fails
+ \param src wchar_t string to convert
+ \param max number of characters to convert, if 0, until terminator
+ \param len number of characters in new string, NOT including terminator
+*/
+uint16_t *U_Utf32leToUtf16le(
+ const uint32_t *src,
+ size_t max,
+ size_t *len
+ ){
+ char *dst,*dst2;
+ char *src2 = (char *) src;
+ size_t srclen,dstlen,status;
+
+ if(!src)return(NULL);
+ if(max){ srclen = 4*max; }
+ else { srclen = 4 + 4*wchar32len(src); } //include terminator, length in BYTES
+
+ dstlen = 2 + srclen; // this will always work, but may waste space
+ dst2 = dst = calloc(dstlen,1); // so there will be at least one terminator
+ if(dst){
+ iconv_t conv = iconv_open("UTF-16LE", "UTF-32LE");
+ if ( conv == (iconv_t) -1){
+ free(dst2);
+ dst2=NULL;
+ }
+ else {
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1){
+ free(dst2);
+ dst2 = NULL;
+ }
+ else if(len){
+ *len=wchar16len((uint16_t *)dst2);
+ }
+ }
+ }
+ return((uint16_t *)dst2);
+}
+
+/**
+ \brief Convert a UTF16LE string to a UTF32LE string.
+ \return pointer to new string or NULL if it fails
+ \param src UTF16LE string to convert
+ \param max number of characters to convert, if 0, until terminator
+ \param len number of characters in new string, NOT including terminator
+*/
+uint32_t *U_Utf16leToUtf32le(
+ const uint16_t *src,
+ size_t max,
+ size_t *len
+ ){
+ char *dst,*dst2;
+ char *src2 = (char *) src;
+ size_t srclen,dstlen,status;
+
+ if(!src)return(NULL);
+ if(max){ srclen = 2*max; }
+ else { srclen = 2*wchar16len(src)+2; } // include terminator, length in BYTES
+ dstlen = 2*(2 + srclen); // This should always work
+ dst2 = dst = calloc(dstlen,1);
+ if(dst){
+ iconv_t conv = iconv_open("UTF-32LE", "UTF-16LE");
+ if ( conv == (iconv_t) -1){
+ free(dst2);
+ dst2=NULL;
+ }
+ else {
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1){
+ free(dst2);
+ dst2 = NULL;
+ }
+ else if(len){
+ *len=wchar32len((uint32_t *)dst2);
+ }
+ }
+ }
+ return((uint32_t *) dst2);
+}
+
+/**
+ \brief Convert a Latin1 string to a UTF32LE string.
+ \return pointer to new string or NULL if it fails
+ \param src Latin1 string to convert
+ \param max number of characters to convert, if 0, until terminator
+ \param len number of characters in new string, NOT including terminator
+
+
+ U_EMR_EXTTEXTOUTA records are "8 bit ASCII". In theory that is ASCII in an 8
+ bit character, but numerous applications store Latin1 in them, and some
+ _may_ store UTF-8 in them. Since very vew Latin1 strings are valid UTF-8 strings,
+ call U_Utf8ToUtf32le first, and if it fails, then call this function.
+*/
+uint32_t *U_Latin1ToUtf32le(
+ const char *src,
+ size_t max,
+ size_t *len
+ ){
+ char *dst,*dst2;
+ char *src2 = (char *) src;
+ size_t srclen,dstlen,status;
+
+ if(!src)return(NULL);
+ if(max){ srclen = max; }
+ else { srclen = strlen(src)+1; } // include terminator, length in BYTES
+ dstlen = sizeof(uint32_t)*(1 + srclen); // This should always work but might waste some space
+ dst2 = dst = calloc(dstlen,1);
+ if(dst){
+ iconv_t conv = iconv_open("UTF-32LE", "LATIN1");
+ if ( conv == (iconv_t) -1){
+ free(dst2);
+ dst2=NULL;
+ }
+ else {
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1){
+ free(dst2);
+ dst2 = NULL;
+ }
+ else if(len){
+ *len=wchar32len((uint32_t *)dst2);
+ }
+ }
+ }
+ return((uint32_t *) dst2);
+}
+
+/**
+ \brief Convert a UTF8 string to a UTF32LE string.
+ \return pointer to new string or NULL if it fails
+ \param src UTF8 string to convert
+ \param max number of characters to convert, if 0, until terminator
+ \param len number of characters in new string, NOT including terminator
+*/
+uint32_t *U_Utf8ToUtf32le(
+ const char *src,
+ size_t max,
+ size_t *len
+ ){
+ char *dst,*dst2;
+ char *src2 = (char *) src;
+ size_t srclen,dstlen,status;
+
+ if(!src)return(NULL);
+ if(max){ srclen = max; }
+ else { srclen = strlen(src)+1; } // include terminator, length in BYTES
+ dstlen = sizeof(uint32_t)*(1 + srclen); // This should always work but might waste some space
+ dst2 = dst = calloc(dstlen,1);
+ if(dst){
+ iconv_t conv = iconv_open("UTF-32LE", "UTF-8");
+ if ( conv == (iconv_t) -1){
+ free(dst2);
+ dst2=NULL;
+ }
+ else {
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1){
+ free(dst2);
+ dst2 = NULL;
+ }
+ else if(len){
+ *len=wchar32len((uint32_t *)dst2);
+ }
+ }
+ }
+ return((uint32_t *) dst2);
+}
+
+/**
+ \brief Convert a UTF32LE string to a UTF8 string.
+ \return pointer to new string or NULL if it fails
+ \param src wchar_t string to convert
+ \param max number of characters to convert, if 0, until terminator
+ \param len number of characters in new string, NOT including terminator
+*/
+char *U_Utf32leToUtf8(
+ const uint32_t *src,
+ size_t max,
+ size_t *len
+ ){
+ char *dst,*dst2;
+ char *src2 = (char *) src;
+ size_t srclen,dstlen,status;
+
+ if(!src)return(NULL);
+ if(max){ srclen = 4*max; }
+ else { srclen = 4*(1 + wchar32len(src)); } //include terminator, length in BYTES
+ dstlen = 1 + srclen; // This should always work but might waste some space
+ dst2 = dst = calloc(dstlen,1);
+ if(dst){
+ iconv_t conv = iconv_open("UTF-8", "UTF-32LE");
+ if ( conv == (iconv_t) -1){
+ free(dst2);
+ dst2=NULL;
+ }
+ else {
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1){
+ free(dst2);
+ dst2 = NULL;
+ }
+ else if(len){
+ *len=strlen(dst2);
+ }
+ }
+ }
+ return(dst2);
+}
+
+/**
+ \brief Convert a UTF-8 string to a UTF16-LE string.
+ \return pointer to new string or NULL if it fails
+ \param src UTF8 string to convert
+ \param max number of characters to convert, if 0, until terminator
+ \param len number of characters in new string, NOT including terminator
+*/
+uint16_t *U_Utf8ToUtf16le(
+ const char *src,
+ size_t max,
+ size_t *len
+ ){
+ char *dst,*dst2;
+ char *src2 = (char *) src;
+ size_t srclen,dstlen,status;
+
+ if(!src)return(NULL);
+ if(max){ srclen = max; }
+ else { srclen = strlen(src)+1; } // include terminator, length in BYTES
+ dstlen = 2 * (1 + srclen); // this will always work, but may waste space
+ dst2 = dst =calloc(dstlen,1); // so there will always be a terminator
+ if(dst){
+ iconv_t conv = iconv_open("UTF-16LE", "UTF-8");
+ if ( conv == (iconv_t) -1){
+ free(dst2);
+ dst2=NULL;
+ }
+ else {
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1){
+ free(dst2);
+ dst2 = NULL;
+ }
+ else if(len){
+ *len=wchar16len((uint16_t *)dst2);
+ }
+ }
+ }
+ return((uint16_t *)dst2);
+}
+
+/**
+ \brief Convert a UTF16LE string to a UTF8 string.
+ \return pointer to new UTF8 string or NULL if it fails
+ \param src UTF16LE string to convert
+ \param max number of characters to convert, if 0, until terminator
+ \param len number of characters in new string, NOT including terminator
+*/
+char *U_Utf16leToUtf8(
+ const uint16_t *src,
+ size_t max,
+ size_t *len
+ ){
+ char *dst, *dst2;
+ char *src2 = (char *) src;
+ size_t srclen,dstlen,status;
+
+ if(!src)return(NULL);
+ if(max){ srclen = 2*max; }
+ else { srclen = 2*(1 +wchar16len(src)); } //include terminator, length in BYTES
+ dstlen = 1 + 2*srclen; // this will always work, but may waste space
+ // worst case is all glyphs (==max) need 4 UTF-8 encoded bytes + terminator.
+ dst2 = dst = (char *) calloc(dstlen,1);
+ if(dst){
+ iconv_t conv = iconv_open("UTF-8", "UTF-16LE");
+ if ( conv == (iconv_t) -1){
+ free(dst2);
+ dst2=NULL;
+ }
+ else {
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1){
+ free(dst2);
+ dst2 = NULL;
+ }
+ else if(len){
+ *len=strlen(dst2);
+ dst = dst2;
+ dst2 = U_strdup(dst); // make a string of exactly the right size
+ free(dst); // free the one which was probably too big
+ }
+ }
+ }
+ return(dst2);
+}
+
+/**
+ \brief Convert a UTF16LE string to a LATIN1 string.
+ \return pointer to new UTF8 string or NULL if it fails
+ \param src UTF16LE string to convert
+ \param max number of characters to convert, if 0, until terminator
+ \param len number of characters in new string, NOT including terminator
+*/
+char *U_Utf16leToLatin1(
+ const uint16_t *src,
+ size_t max,
+ size_t *len
+ ){
+ char *dst, *dst2;
+ char *src2 = (char *) src;
+ size_t srclen,dstlen,status;
+
+ if(!src)return(NULL);
+ if(max){ srclen = 2*max; }
+ else { srclen = 2*(1 +wchar16len(src)); } //include terminator, length in BYTES
+ dstlen = 1 + srclen; // this will always work as latin1 is always 1 byte/character
+ dst2 = dst = (char *) calloc(dstlen,1);
+ if(dst){
+ iconv_t conv = iconv_open("LATIN1//TRANSLIT", "UTF-16LE");
+ if ( conv == (iconv_t) -1){
+ free(dst2);
+ dst2=NULL;
+ }
+ else {
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1){
+ free(dst2);
+ dst2 = NULL;
+ }
+ else if(len){
+ *len=strlen(dst2);
+ dst = dst2;
+ dst2 = U_strdup(dst); // make a string of exactly the right size
+ free(dst); // free the one which was probably too big
+ }
+ }
+ }
+ return(dst2);
+}
+/**
+ \brief Put a single 16 bit character into UTF-16LE form.
+
+ Used in conjunction with U_Utf16leEdit(), because the character
+ representation would otherwise be dependent on machine Endianness.
+
+ \return UTF16LE representation of the character.
+ \param src 16 bit character
+
+*/
+uint16_t U_Utf16le(const uint16_t src){
+ uint16_t dst=src;
+#if U_BYTE_SWAP
+ U_swap2(&dst,1);
+#endif
+ return(dst);
+}
+
+/**
+ \brief Convert a UTF8 string to a Latin1 string.
+ \return pointer to new string or NULL if it fails
+ \param src Latin1 string to convert
+ \param max number of characters to convert, if 0, until terminator
+ \param len number of characters in new string, NOT including terminator
+
+
+ WMF uses latin1, others UTF-8, only some utf-8 can be converted to latin1.
+
+*/
+char *U_Utf8ToLatin1(
+ const char *src,
+ size_t max,
+ size_t *len
+ ){
+ char *dst,*dst2;
+ char *src2 = (char *) src;
+ size_t srclen,dstlen,status;
+ if(max){ srclen = max; }
+ else { srclen = strlen(src)+1; } // include terminator, length in BYTES
+ dstlen = (1 + srclen); // This should always work but might waste some space
+ dst2 = dst = calloc(dstlen,1);
+ if(dst){
+ iconv_t conv = iconv_open("LATIN1//TRANSLIT", "UTF-8"); // translate what can be, fill in with something close for the rest
+ if ( conv == (iconv_t) -1){
+ free(dst2);
+ dst2=NULL;
+ }
+ else {
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1){
+ free(dst2);
+ dst2 = NULL;
+ }
+ else if(len){
+ *len=strlen(dst2);
+ }
+ }
+ }
+ return((char *) dst2);
+}
+
+/**
+ \brief Convert a Latin1 string to a UTF8 string.
+ \return pointer to new string or NULL if it fails
+ \param src Latin1 string to convert
+ \param max number of characters to convert, if 0, until terminator
+ \param len number of characters in new string, NOT including terminator
+
+
+ WMF uses latin1, others UTF-8, all Latin1 should be able to convert to utf-8.
+
+*/
+char *U_Latin1ToUtf8(
+ const char *src,
+ size_t max,
+ size_t *len
+ ){
+ char *dst,*dst2;
+ char *src2 = (char *) src;
+ size_t srclen,dstlen,status;
+ if(max){ srclen = max; }
+ else { srclen = strlen(src)+1; } // include terminator, will waste some space
+ dstlen = (1 + 2*srclen); // This should always work because all latin1 convert to 1 or 2 byte UTF8, it might waste some space
+ dst2 = dst = calloc(dstlen,1);
+ if(dst){
+ iconv_t conv = iconv_open("UTF-8", "LATIN1"); // everything should translate
+ if ( conv == (iconv_t) -1){
+ free(dst2);
+ dst2=NULL;
+ }
+ else {
+ status = iconv(conv, ICONV_CAST &src2, &srclen, &dst, &dstlen);
+ iconv_close(conv);
+ if(status == (size_t) -1){
+ free(dst2);
+ dst2 = NULL;
+ }
+ else if(len){
+ *len=strlen(dst2);
+ }
+ }
+ }
+ return((char *) dst2);
+}
+
+/**
+ \brief Single character replacement in a UTF-16LE string.
+
+ Used solely for the Description field which contains
+ embedded nulls, which makes it difficult to manipulate. Use some other character and then swap it.
+
+ \return number of substitutions, or -1 if src is not defined
+ \param src UTF16LE string to edit
+ \param find character to replace
+ \param replace replacestitute character
+
+*/
+int U_Utf16leEdit(
+ uint16_t *src,
+ uint16_t find,
+ uint16_t replace
+ ){
+ int count=0;
+ if(!src)return(-1);
+ while(*src){
+ if(*src == find){ *src = replace; count++; }
+ src++;
+ }
+ return(count);
+}
+
+/**
+ \brief strdup for when strict C99 compliance is enforced
+ \returns duplicate string or NULL on error
+ \param s string to duplicate
+*/
+char *U_strdup(const char *s){
+ char *news=NULL;
+ size_t slen;
+ if(s){
+ slen = strlen(s) + 1; //include the terminator!
+ news = malloc(slen);
+ if(news){
+ memcpy(news,s,slen);
+ }
+ }
+ return(news);
+
+}
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/3rdparty/libuemf/uemf_utf.h b/src/3rdparty/libuemf/uemf_utf.h
new file mode 100644
index 0000000..68452b6
--- /dev/null
+++ b/src/3rdparty/libuemf/uemf_utf.h
@@ -0,0 +1,55 @@
+/**
+ @file uemf_utf.h
+
+ @brief Prototypes for functions that manipulate UTF and various types of text.
+
+*/
+
+/*
+File: uemf_utf.h
+Version: 0.0.1
+Date: 04-DEC-2012
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2012 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifndef _UEMF_UTF_
+#define _UEMF_UTF_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "uemf_endian.h"
+
+void wchar8show(const char *src);
+void wchar16show(const uint16_t *src);
+void wchar32show(const uint32_t *src);
+void wchartshow(const wchar_t *src);
+
+size_t wchar16len(const uint16_t *src);
+size_t wchar32len(const uint32_t *src);
+void wchar16strncpy(uint16_t *dst, const uint16_t *src, size_t nchars);
+void wchar16strncpypad(uint16_t *dst, const uint16_t *src, size_t nchars);
+uint16_t *U_Utf8ToUtf16le( const char *src, size_t max, size_t *len );
+uint32_t *U_Utf8ToUtf32le( const char *src, size_t max, size_t *len );
+uint32_t *U_Latin1ToUtf32le( const char *src, size_t max, size_t *len );
+uint16_t *U_Utf32leToUtf16le( const uint32_t *src, size_t max, size_t *len );
+char *U_Utf32leToUtf8( const uint32_t *src, size_t max, size_t *len );
+uint32_t *U_Utf16leToUtf32le( const uint16_t *src, size_t max, size_t *len );
+char *U_Utf16leToUtf8( const uint16_t *src, size_t max, size_t *len );
+char *U_Utf16leToLatin1( const uint16_t *src, size_t max, size_t *len );
+char *U_Utf8ToLatin1( const char *src, size_t max, size_t *len );
+char *U_Latin1ToUtf8( const char *src, size_t max, size_t *len );
+uint16_t U_Utf16le(const uint16_t src);
+int U_Utf16leEdit( uint16_t *src, uint16_t find, uint16_t replace );
+char *U_strdup(const char *s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UEMF_UTF_ */
diff --git a/src/3rdparty/libuemf/upmf.c b/src/3rdparty/libuemf/upmf.c
new file mode 100644
index 0000000..20a87ae
--- /dev/null
+++ b/src/3rdparty/libuemf/upmf.c
@@ -0,0 +1,8661 @@
+/**
+ @file upmf.c
+
+ @brief Functions for manipulating EMF+ files and structures.
+
+ EMF+ is much more object based than is EMF or WMF, so the U_PMR_*_set and most U_PMF_*_set functions
+ return a pointer to a PseudoObject. PseudoObjects are structs that contain a data field to hold the
+ object in EMF+ file byte order, size information, and some type information. This is sufficient to allow
+ complex records to be built up from the various sorts of nested objects which they normally contain.
+ If something goes wrong a NULL pointer is returned and recsize is set to 0.
+
+ EMF+ does not use a separate set of endian functions, _get and _set routines convert from/to
+ the EMF+ file byte order on the fly.
+
+ WARNING: Microsoft's EMF+ documentation is little-endian for everything EXCEPT
+ bitfields, which are big-endian. See EMF+ manual section 1.3.2
+ That documentation also uses 0 as the MOST significant bit, N-1 as the least.
+ This code is little-endian throughout, and 0 is the LEAST significant bit
+
+*/
+
+/*
+File: upmf.c
+Version: 0.0.13
+Date: 21-MAR-2019
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2019 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <iconv.h>
+#include <wchar.h>
+#include <errno.h>
+#include <string.h>
+#include <limits.h> // for INT_MAX, INT_MIN
+#include <math.h> // for sin, cos, tan2, use U_ROUND() instead of roundf()
+#include <stddef.h> /* for offsetof() macro */
+#if 0
+#include <windef.h> //Not actually used, looking for collisions
+#include <winnt.h> //Not actually used, looking for collisions
+#include <wingdi.h> //Not actually used, looking for collisions
+#endif
+#include "upmf.h" // includes uemf.h
+#include "uemf_endian.h" // for U_swap* functions
+
+//! \cond
+
+/// things Doxygen should not process
+/* remove this after debugging is completed */
+void dumphex(uint8_t *buf,unsigned int num){
+ for(; num; num--,buf++){
+ printf("%2.2X",*buf);
+ }
+}
+
+
+/* Prototypes for functions used here and defined in uemf_endian.c, but which are not supposed
+to be used in end user code. */
+
+void U_swap2(void *ul, unsigned int count);
+void U_swap4(void *ul, unsigned int count);
+//! \endcond
+
+/**
+ \brief Utility function for writing one or more EMF+ records in a PseudoObject to the EMF output file
+ \return 1 on success, 0 on error.
+ \param po U_PSEUDO_OBJ to write, it is deleted after it is written
+ \param sum U_PSEUDO_OBJ to use for scratch space
+ \param et EMFTRACK used to write records to EMF file
+*/
+int U_PMR_write(U_PSEUDO_OBJ *po, U_PSEUDO_OBJ *sum, EMFTRACK *et){
+ char *rec;
+ int status = 0;
+ sum->Used = 0; /* clean it out, retaining allocated memory */
+ sum = U_PO_append(sum, "EMF+", 4); /* indicates that this comment holds an EMF+ record */
+ if(!sum)goto end;
+ sum = U_PO_append(sum, po->Data, po->Used); /* the EMF+ record itself */
+ if(!sum)goto end;
+ U_PO_free(&po); /* delete the PseudoObject */
+ rec = U_EMRCOMMENT_set(sum->Used, sum->Data); /* stuff it into the EMF comment */
+ if(!emf_append((PU_ENHMETARECORD)rec, et, 1))goto end; /* write it to the EMF file, delete the record, check status */
+ status = 1;
+end:
+ return(status);
+}
+
+/**
+ \brief Utility function to draw a line.
+ \return 1 on success, 0 on error.
+ \param PenID Index of U_PMF_PEN object to use in the EMF+ object table (0-63, inclusive)
+ \param PathID Index of U_PMF_PATH object to use in the EMF+ object table (0-63, inclusive)
+ \param Start U_PMF_POINTF coordinates of start of line.
+ \param End U_PMF_POINTF coordinates of end of line.
+ \param Dashed Set if the line is dashed, clear if it is not.
+ \param sum PseudoObject used for scratch space
+ \param et EMFTRACK used to write records to EMF file
+
+*/
+int U_PMR_drawline(uint32_t PenID, uint32_t PathID, U_PMF_POINTF Start, U_PMF_POINTF End, int Dashed, U_PSEUDO_OBJ *sum, EMFTRACK *et){
+ U_DPSEUDO_OBJ *dpath;
+ U_PSEUDO_OBJ *poPath;
+ U_PSEUDO_OBJ *po;
+ int status=0;
+ int PTP_value = ( Dashed ? U_PTP_DashMode : U_PTP_None);
+ dpath = U_PATH_create(0, NULL, 0, 0); /* create an empty path*/
+ if(dpath){
+ if(U_PATH_moveto(dpath, Start, PTP_value) && U_PATH_lineto(dpath, End, PTP_value)){
+ poPath = U_PMF_PATH_set2(U_PMF_GRAPHICSVERSIONOBJ_set(2), dpath);
+ if(poPath){
+ po = U_PMR_OBJECT_PO_set(PathID, poPath);
+ U_PO_free(&poPath);
+ if(po){
+ U_PMR_write(po, sum, et);
+ po = U_PMR_DRAWPATH_set(PathID, PenID);
+ if(po){
+ U_PMR_write(po, sum, et);
+ status = 1;
+ }
+ }
+ }
+ }
+ U_DPO_free(&dpath);
+ }
+ return(status);
+}
+
+/**
+ \brief Utility function for drawing strings onto the baseline in one call.
+ \return 1 on success, 0 on error.
+ \param string Text to draw in UTF-8 format
+ \param Vpos StringAlignment Enumeration. Always drawn on baseline, but using one of these three modes.
+ \param FontID Index of U_PMF_FONT object to use in the EMF+ object table (0-63, inclusive)
+ \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive)
+ \param FormatID index of U_PMF_STRINGFORMAT object to use in the EMF+ Object Table.
+ \param Sfs StringFormat structure. Ignored values: StringAlignment, LineAlign, Flags
+ \param FontName Name of font to draw with
+ \param Height Height of font in pixels (positive)
+ \param fip U_FontInfoParams (ascent, descent, and so forth)
+ \param FontFlags FontStyle Flags
+ \param x X position in pixels of left side of EM box of first character
+ \param y Y position in pixels of baseline of first character
+ \param sum PseudoObject used for scratch space
+ \param et EMFTRACK used to write records to EMF file
+
+ EMF+ manual 2.3.4.14, Microsoft name: EmfPlusDrawString Record, Index 0x1C
+
+ For most fonts Ascent and Descent are used to adjust the bounding box to properly position the
+ baseline. Some fonts, like Verdana, are strange and they position the baseline on the bottom of
+ the bounding box if that box has the same height as the font. For those fonts specify 0.0 for
+ both Ascent and Descent.
+*/
+int U_PMR_drawstring( const char *string, int Vpos, uint32_t FontID, const U_PSEUDO_OBJ *BrushID, uint32_t FormatID,
+ U_PMF_STRINGFORMAT Sfs, const char *FontName, U_FLOAT Height, U_FontInfoParams *fip, uint32_t FontFlags,
+ U_FLOAT x, U_FLOAT y, U_PSEUDO_OBJ *sum, EMFTRACK *et){
+ U_PSEUDO_OBJ *po;
+ U_PSEUDO_OBJ *poSF;
+ U_PSEUDO_OBJ *poFont;
+ U_PSEUDO_OBJ *poRect;
+ U_FLOAT rx,ry,rw,rh,rd;
+ uint16_t *UFontName;
+ uint16_t *Text16;
+ int slen;
+ int status = 0;
+ double aval, dval;
+
+ Sfs.Flags = U_SF_NoFitBlackBox + U_SF_NoClip;
+
+ if(Vpos < U_SA_Near || Vpos > U_SA_Far)return(0);
+ Sfs.StringAlignment = U_SA_Near; // Horizontal
+ Sfs.LineAlign = Vpos; // Vertical
+
+ UFontName = U_Utf8ToUtf16le(FontName, 0, NULL);
+ slen = strlen(FontName);
+ poFont = U_PMF_FONT_set(U_PMF_GRAPHICSVERSIONOBJ_set(2), Height, U_UT_World, FontFlags, slen, UFontName);
+ if(poFont){
+ po = U_PMR_OBJECT_PO_set(FontID, poFont); /* font to use */
+ if(po){
+ U_PMR_write(po, sum, et);
+
+ poSF = U_PMF_STRINGFORMAT_set(&Sfs, NULL);
+ if(poSF){
+ po = U_PMR_OBJECT_PO_set(FormatID, poSF);
+ U_PO_free(&poSF);
+ if(po){
+ U_PMR_write(po, sum, et);
+
+ rw = 4*Height*slen; /* This could probably be any value */
+ rh = Height;
+ rx = x;
+ if(fip->LineGap > -fip->Descent){ aval = fip->yMax; } // sylfaen, palatino
+ else { aval = fip->Ascent; } // others
+ if(fip->LineGap && (fip->LineGap < -fip->Descent)){ dval = ((double) (fip->Descent - fip->LineGap)) / ((double) fip->EmSize); } //shruti and some others
+ else { dval = ((double) fip->Descent ) / ((double) fip->EmSize); }
+ switch(Vpos){
+ case U_SA_Near:
+ rd = Height * aval / ((double) fip->EmSize);
+ break;
+ case U_SA_Center:
+ rd = 0.5 * ( Height * aval / ((double) fip->EmSize) + Height * ( 1.0 + dval));
+ break;
+ case U_SA_Far:
+ rd = Height * ( 1.0 + dval);
+ break;
+ }
+ ry = y - rd; /* draw from upper left corner, which is shifted to put baseline on y */
+ poRect = U_PMF_RECTF4_set(rx, ry, rw, rh);
+#if 0
+(void) U_PMR_drawline(OBJ_PEN_BLACK_1,OBJ_PATH_1, (U_PMF_POINTF){x-100, ry}, (U_PMF_POINTF){x+100, ry}, 0, sum, et);
+(void) U_PMR_drawline(OBJ_PEN_BLACK_1,OBJ_PATH_1, (U_PMF_POINTF){x-100, ry+rh}, (U_PMF_POINTF){x+100, ry+rh}, 0, sum, et);
+(void) U_PMR_drawline(OBJ_PEN_BLACK_1,OBJ_PATH_1, (U_PMF_POINTF){x-100, ry}, (U_PMF_POINTF){x-100, ry + Height * (double) fip->Ascent / ((double) fip->EmSize)}, 0, sum, et);
+(void) U_PMR_drawline(OBJ_PEN_BLACK_1,OBJ_PATH_1, (U_PMF_POINTF){x- 90, ry}, (U_PMF_POINTF){x- 90, ry - Height * (double) fip->Descent / ((double) fip->EmSize)}, 0, sum, et);
+(void) U_PMR_drawline(OBJ_PEN_BLACK_1,OBJ_PATH_1, (U_PMF_POINTF){x- 80, ry}, (U_PMF_POINTF){x- 80, ry + Height * (double) fip->yMax / ((double) fip->EmSize)}, 0, sum, et);
+(void) U_PMR_drawline(OBJ_PEN_BLACK_1,OBJ_PATH_1, (U_PMF_POINTF){x- 70, ry}, (U_PMF_POINTF){x- 70, ry - Height * (double) fip->yMin / ((double) fip->EmSize)}, 0, sum, et);
+(void) U_PMR_drawline(OBJ_PEN_BLACK_1,OBJ_PATH_1, (U_PMF_POINTF){x- 60, ry}, (U_PMF_POINTF){x- 60, ry + Height * (double) fip->LineGap / ((double) fip->EmSize)}, 0, sum, et);
+(void) U_PMR_drawline(OBJ_PEN_BLACK_1,OBJ_PATH_1, (U_PMF_POINTF){x- 50, ry}, (U_PMF_POINTF){x- 50, ry + Height * ( 1.0 - (((double) (fip->LineGap - fip->Descent)) / ((double) fip->EmSize)) )}, 0, sum, et);
+#endif
+
+ Text16 = U_Utf8ToUtf16le(string, 0, NULL);
+ slen = strlen(string);
+ po = U_PMR_DRAWSTRING_set(FontID, BrushID, FormatID, slen, poRect, Text16);
+ if(po){
+ U_PMR_write(po, sum, et);
+ status = 1; /* Success!!! */
+ }
+ U_PO_free(&poRect);
+ free(Text16);
+ }
+ }
+ }
+ U_PO_free(&poFont);
+ }
+ free(UFontName);
+ return(status);
+}
+
+/**
+ \brief Allocate and construct an array of U_POINT16 objects from a set of U_PMF_POINTF objects, endianness in and out is LE
+ \returns pointer to an array of U_POINT16 structures.
+ \param points pointer to the source U_POINT structures
+ \param count number of members in points
+
+ If a coordinate is out of range it saturates at boundary.
+*/
+U_PMF_POINT *POINTF_To_POINT16_LE(U_PMF_POINTF *points, int count){
+ U_PMF_POINT *newpts;
+ U_PMF_POINTF ptfl;
+ int i;
+ newpts = (U_PMF_POINT *) malloc(count * sizeof(U_PMF_POINT));
+
+ for(i=0; i<count; i++){
+ memcpy(&ptfl, &(points[i]), 8);
+ if(U_BYTE_SWAP){ U_swap4(&ptfl,2); } /* on BE platforms swap going in and coming out */
+ newpts[i].X = U_MNMX(ptfl.X, INT16_MIN, INT16_MAX);
+ newpts[i].Y = U_MNMX(ptfl.Y, INT16_MIN, INT16_MAX);
+ if(U_BYTE_SWAP){ U_swap2(&(newpts[i]),2); }
+ }
+ return(newpts);
+}
+
+/**
+ \brief Look up the name of the EMR+ record by type. Returns U_EMR_INVALID if out of range.
+
+ \return name of the PMR record, "U_EMR_INVALID" if out of range.
+ \param idx PMR record type WITHOUT the U_PMR_RECFLAG bit.
+
+*/
+char *U_pmr_names(unsigned int idx){
+ if(idx<U_PMR_MIN || idx > U_PMR_MAX){ idx = 0; }
+ static char *U_PMR_NAMES[U_PMR_MAX+1]={
+ "U_PMR_INVALID",
+ "U_PMR_Header",
+ "U_PMR_EndOfFile",
+ "U_PMR_Comment",
+ "U_PMR_GetDC",
+ "U_PMR_MultiFormatStart",
+ "U_PMR_MultiFormatSection",
+ "U_PMR_MultiFormatEnd",
+ "U_PMR_Object",
+ "U_PMR_Clear",
+ "U_PMR_FillRects",
+ "U_PMR_DrawRects",
+ "U_PMR_FillPolygon",
+ "U_PMR_DrawLines",
+ "U_PMR_FillEllipse",
+ "U_PMR_DrawEllipse",
+ "U_PMR_FillPie",
+ "U_PMR_DrawPie",
+ "U_PMR_DrawArc",
+ "U_PMR_FillRegion",
+ "U_PMR_FillPath",
+ "U_PMR_DrawPath",
+ "U_PMR_FillClosedCurve",
+ "U_PMR_DrawClosedCurve",
+ "U_PMR_DrawCurve",
+ "U_PMR_DrawBeziers",
+ "U_PMR_DrawImage",
+ "U_PMR_DrawImagePoints",
+ "U_PMR_DrawString",
+ "U_PMR_SetRenderingOrigin",
+ "U_PMR_SetAntiAliasMode",
+ "U_PMR_SetTextRenderingHint",
+ "U_PMR_SetTextContrast",
+ "U_PMR_SetInterpolationMode",
+ "U_PMR_SetPixelOffsetMode",
+ "U_PMR_SetCompositingMode",
+ "U_PMR_SetCompositingQuality",
+ "U_PMR_Save",
+ "U_PMR_Restore",
+ "U_PMR_BeginContainer",
+ "U_PMR_BeginContainerNoParams",
+ "U_PMR_EndContainer",
+ "U_PMR_SetWorldTransform",
+ "U_PMR_ResetWorldTransform",
+ "U_PMR_MultiplyWorldTransform",
+ "U_PMR_TranslateWorldTransform",
+ "U_PMR_ScaleWorldTransform",
+ "U_PMR_RotateWorldTransform",
+ "U_PMR_SetPageTransform",
+ "U_PMR_ResetClip",
+ "U_PMR_SetClipRect",
+ "U_PMR_SetClipPath",
+ "U_PMR_SetClipRegion",
+ "U_PMR_OffsetClip",
+ "U_PMR_DrawDriverstring",
+ "U_PMR_StrokeFillPath",
+ "U_PMR_SerializableObject",
+ "U_PMR_SetTSGraphics",
+ "U_PMR_SetTSClip"
+ };
+ return(U_PMR_NAMES[idx]);
+}
+
+/**
+ \brief Convert from PseudoObject OID to ObjectType enumeration.
+ \returns OT value on success, 0 if no match
+ \param OID PseudoObject OID (based on EMF+ manual chapter number. )
+
+ Only OTs that may be stored in the EMF+ object table are supported.
+*/
+
+int U_OID_To_OT(uint32_t OID){
+ int otype;
+ if( OID==U_PMF_BRUSH_OID ){ otype = U_OT_Brush; }
+ else if(OID==U_PMF_PEN_OID ){ otype = U_OT_Pen; }
+ else if(OID==U_PMF_PATH_OID ){ otype = U_OT_Path; }
+ else if(OID==U_PMF_REGION_OID ){ otype = U_OT_Region; }
+ else if(OID==U_PMF_IMAGE_OID ){ otype = U_OT_Image; }
+ else if(OID==U_PMF_FONT_OID ){ otype = U_OT_Font; }
+ else if(OID==U_PMF_STRINGFORMAT_OID ){ otype = U_OT_StringFormat; }
+ else if(OID==U_PMF_IMAGEATTRIBUTES_OID){ otype = U_OT_ImageAttributes; }
+ else if(OID==U_PMF_CUSTOMLINECAP_OID ){ otype = U_OT_CustomLineCap; }
+ else { otype = U_OT_Invalid; }
+ return(otype);
+}
+
+/**
+ \brief Convert from PseudoObject OID to BrushType enumeration.
+ \returns BT value on success, -1 if no match
+ \param OID PseudoObject OID (based on EMF+ manual chapter number. )
+
+ Only OIDs that map to BT's are supported.
+*/
+
+int U_OID_To_BT(uint32_t OID){
+ int otype;
+ if( OID==U_PMF_HATCHBRUSHDATA_OID ){ otype = U_BT_HatchFill; }
+ else if(OID==U_PMF_LINEARGRADIENTBRUSHDATA_OID ){ otype = U_BT_LinearGradient; }
+ else if(OID==U_PMF_PATHGRADIENTBRUSHDATA_OID ){ otype = U_BT_PathGradient; }
+ else if(OID==U_PMF_SOLIDBRUSHDATA_OID ){ otype = U_BT_SolidColor; }
+ else if(OID==U_PMF_TEXTUREBRUSHDATA_OID ){ otype = U_BT_TextureFill; }
+ else { otype = -1; }
+ return(otype);
+}
+
+/**
+ \brief Convert from PseudoObject OID to CustomLineCapDataType Enumeration.
+ \returns BT value on success, -1 if no match
+ \param OID PseudoObject OID (based on EMF+ manual chapter number. )
+
+ Only OIDs that map to CLCDT's are supported.
+*/
+
+int U_OID_To_CLCDT(uint32_t OID){
+ int otype;
+ if( OID==U_PMF_CUSTOMLINECAPDATA_OID ){ otype = U_CLCDT_Default; }
+ else if(OID==U_PMF_CUSTOMLINECAPARROWDATA_OID ){ otype = U_CLCDT_AdjustableArrow; }
+ else { otype = -1; }
+ return(otype);
+}
+
+/**
+ \brief Convert from PseudoObject OID to ImageDataType Enumeration.
+ \returns BT value on success, -1 if no match
+ \param OID PseudoObject OID (based on EMF+ manual chapter number. )
+
+ Only OIDs that map to IDT's are supported.
+*/
+
+int U_OID_To_IDT(uint32_t OID){
+ int otype;
+ if( OID==U_PMF_BITMAP_OID ){ otype = U_IDT_Bitmap; }
+ else if(OID==U_PMF_METAFILE_OID ){ otype = U_IDT_Metafile; }
+ else { otype = -1; }
+ return(otype);
+}
+
+/**
+ \brief Convert from PseudoObject OID to RegionNodeDataType Enumeration.
+ \returns BT value on success, -1 if no match
+ \param OID PseudoObject OID (based on EMF+ manual chapter number. )
+
+ Only OIDs that map to RNDT's are supported.
+*/
+
+int U_OID_To_RNDT(uint32_t OID){
+ int otype;
+ if( OID==U_PMF_REGIONNODECHILDNODES_OID ){ otype = U_RNDT_Kids; } /* there are 5 types, which must be specified separately */
+ else if(OID==U_PMF_RECTF_OID ){ otype = U_RNDT_Rect; }
+ else if(OID==U_PMF_REGIONNODEPATH_OID ){ otype = U_RNDT_Path; }
+ else { otype = -1; }
+ return(otype);
+}
+
+/**
+ \brief Append data to an U_OBJ_ACCUM structure.
+ \param oa pointer to the U_OBJ_ACCUM structure
+ \param data data to add
+ \param size bytes in data
+ \param Type object type
+ \param Id Object ID
+ \returns 0 on success, !0 on error. -1 on Type change, -2 on Id change
+
+ Safe to test for Id, Type changes by calling with size=0.
+*/
+int U_OA_append(U_OBJ_ACCUM *oa, const char *data, int size, int Type, int Id){
+ int tail;
+ if(!oa)return(2);
+ if(oa->used){
+ if(oa->Type != Type)return(-1);
+ if(oa->Id != Id)return(-2);
+ }
+ tail = oa->used;
+ if(oa->used + size >= oa->space){
+ oa->space += size;
+ char *newaccum = (char *) realloc(oa->accum, oa->space);
+ if(!newaccum){
+ oa->space -= size; /* put it back the way it was */
+ return(1);
+ }
+ oa->accum = newaccum;
+ }
+ memcpy(oa->accum + tail,data,size);
+ oa->used += size;
+ oa->Type = Type;
+ oa->Id = Id;
+ return(0);
+}
+
+
+/**
+ \brief Clear an U_OBJ_ACCUM structure. Accumulated storage is retained.
+ \param oa pointer to the U_OBJ_ACCUM structure
+ \returns 0 on success, !0 on error.
+*/
+int U_OA_clear(U_OBJ_ACCUM *oa){
+ if(!oa)return(2);
+ oa->used=0;
+ /* Type and Id may be ignored as they are reset on the first append */
+ return(0);
+}
+
+/**
+ \brief Release an U_OBJ_ACCUM structure. Accumulated storage is free'd.
+ \param oa pointer to the U_OBJ_ACCUM structure
+ \returns 0 on success, !0 on error.
+*/
+int U_OA_release(U_OBJ_ACCUM *oa){
+ if(!oa)return(2);
+ oa->used=0;
+ oa->space = 0;
+ if(oa->accum)free(oa->accum);
+ oa->accum=NULL;
+ return(0);
+}
+
+/**
+ \brief Create and set an U_PSEUDO_OBJ
+ \returns pointer to the U_PSEUDO_OBJ, NULL on error
+ \param Data Data to copy into the PseudoObject's data. If NULL, space is allocated, but is cleared instead of filled.
+ \param Size Number of bytes to allocate for Data (may be >Use if padding is present)
+ \param Use Number of data bytes in Data (whether or not Data is actually copied)
+ \param Type Type numbers are from manual section: 1.2.3.47 -> 0x01020347
+
+ If Data is NULL and Size is 0 an empty PseudoObject is created. One byte of storage
+ is allocated for Data, Size is set to 1, and Used to 0.
+
+ If Data is NULL and Size is !0 a zero filled PseudoObject is created.
+
+ If Data is !Null and Size is !0 a data filled PseudoObject is created.
+*/
+U_PSEUDO_OBJ *U_PO_create(char *Data, size_t Size, size_t Use, uint32_t Type){
+ if(Use>Size)return(NULL);
+ size_t tSize = (Size ? Size : 1);
+ U_PSEUDO_OBJ *po = (U_PSEUDO_OBJ *)malloc(sizeof(U_PSEUDO_OBJ));
+ if(po){
+ po->Data = malloc(tSize);
+ if(po->Data){
+ po->Size = tSize;
+ po->Used = Use;
+ po->Type = Type;
+ if(Data){ memcpy(po->Data, Data, Use); } /* if Use < Size uninitialized bytes will be present! */
+ else { memset(po->Data, 0, tSize); }
+ }
+ else {
+ free(po);
+ po=NULL;
+ }
+ }
+ return(po);
+}
+
+/**
+ \brief Append data to a U_PSEUDO_OBJ object and return it
+ \returns pointer to the U_PSEUDO_OBJ object, NULL on error
+ \param po PseudoObject to append to. Cannot be NULL.
+ \param Data Data to copy into the PseudoObject's data. If NULL, space is allocated (if necessary) and cleared instead of filled.
+ \param Size Number of data bytes in Data
+*/
+U_PSEUDO_OBJ *U_PO_append(U_PSEUDO_OBJ *po, const char *Data, size_t Size){
+ /* po cannot be NULL,as in U_PO_po_append(), because there would be no way to determine the TYPE of the resulting PO */
+ if(po){
+ if(!po->Data || po->Used + Size > po->Size){
+ po->Size = po->Used + Size;
+ char *newData = realloc(po->Data, po->Size);
+ if(!newData){
+ po->Size -= Size; /* put it back the way it was*/
+ po=NULL; /* skip the rest of the actions, does not affect po in caller */
+ }
+ else {
+ po->Data = newData;
+ }
+ }
+ if(po){ /* po->Data ready to append new data */
+ if(Data){ memcpy(po->Data + po->Used, Data, Size); }
+ else { memset(po->Data + po->Used, 0, Size); }
+ po->Used += Size;
+ }
+ }
+ return(po);
+}
+
+/**
+ \brief Append data to a U_PSEUDO_OBJ object and return it
+ \returns pointer to the U_PSEUDO_OBJ object, NULL on error
+ \param po PseudoObject to append to. May be NULL.
+ \param Src PseudoObject to append.
+ \param StripE Set: leading Elements in Src->Data is not copied, Clear: it is copied.
+*/
+U_PSEUDO_OBJ *U_PO_po_append(U_PSEUDO_OBJ *po, U_PSEUDO_OBJ *Src, int StripE){
+ if(!Src){ return(NULL); }
+ if((StripE && (Src->Used == 4)) || !Src->Used){ return(po); } /* appending nothing is not an error */
+ char *Data = Src->Data;
+ size_t Size = Src->Used; /* append only what is used */
+ U_PSEUDO_OBJ *ipo = po;
+ if(StripE){ Size -= 4; }
+ if(!ipo){
+ ipo = U_PO_create(NULL, 0, 0, Src->Type); /* create an empty pseudoobject */
+ }
+ if(ipo){
+ if(!ipo->Data || ipo->Used + Size > ipo->Size){
+ ipo->Size = ipo->Used + Size;
+ char *newData = realloc(ipo->Data, ipo->Size);
+ if(!newData){
+ if(ipo != po)U_PO_free(&ipo);
+ }
+ else {
+ ipo->Data = newData;
+ }
+ }
+ if(ipo){
+ if(Data){
+ if(StripE){ memcpy(ipo->Data + ipo->Used, Data + 4, Size); } /* Size is already 4 less, skip the leading Elements value */
+ else { memcpy(ipo->Data + ipo->Used, Data, Size); } /* copy everything */
+ }
+ else { memset(ipo->Data + ipo->Used, 0, Size); } /* set everything */
+ ipo->Used += Size;
+ }
+ }
+ return(ipo);
+}
+
+/**
+ \brief Free an U_PSEUDO_OBJ structure. All associated memory is released.
+ \param po Address of a pointer to the U_PSEUDO_OBJ structure, Pointer is set to NULL.
+ \returns 1 on success, 0 on error.
+*/
+int U_PO_free(U_PSEUDO_OBJ **po){
+ if(!po)return(0);
+ if(!*po)return(1);
+ if((*po)->Data)free((*po)->Data);
+ free(*po);
+ *po=NULL;
+ return(1);
+}
+
+/** \brief create a PseudoObject with data in the correct byte order for an EMF+ file.
+ \returns The PseudoObject on success, NULL on error.
+
+ \param Type the type of the PseudoObject that is created. Allowed values are in U_PID_Values.
+ \param List an array of U_SERIAL_DESC structures containing the data to store.
+
+ The U_PMF_SERIAL_set() function should not ever be called directly by end user code.
+
+ Each U_SERIAL_DESC element in List consists of Data fields and a description of that data. List is terminated
+ by the first U_SERIAL_DESC element having a TE value of U_XX.
+
+ Data fields: an array of a basic type of Units bytes repeated Reps times with the target byte order
+ described in TE.
+
+ Ptrs: Address of the first byte of the data fields.
+
+ Units: Number of bytes of in each data field unit
+
+ Reps: Number of repeats of the unit in data fields.
+ If a Ptr is NULL, and Units*Reps is not zero, then Units*Reps 0x00 bytes are stored.
+ If a Ptr is NULL, and Units*Reps is zero, this U_SERIAL_DESC is ignored.
+ if a Ptr is NOT NULL, and Units * Reps is not zero, then the data is stored in the indicated byte order.
+ If a Ptr is NOT NULL, and Units or Reps is zero an error is signaled.
+
+ TE: (Target Endian) the byte order in which to store each unit of a data field as defined in U_Endian.
+ Byte swapping is only enabled when Units is 2 or 4. In addition to the byte order values U_XE, U_LE,
+ and U_BE, and the array terminator U_XX, the value may also be U_RP. U_RP means there is only a
+ single unit in the data fields, but it is to be copied to the target Reps times. That is, the data
+ was passed in with a form of run length encoding.
+
+ Creates an empty PseudoObject if all pointers are NULL and all sizes are zero.
+ */
+U_PSEUDO_OBJ *U_PMF_SERIAL_set(uint32_t Type, const U_SERIAL_DESC *List){
+ U_PSEUDO_OBJ *po=NULL;
+ size_t Total=0;
+ size_t FSize;
+ char *cptr;
+ char *hptr;
+ const U_SERIAL_DESC *lptr;
+ if(!List)return(NULL);
+ for(lptr=List; lptr->TE != U_XX; lptr++){
+ FSize = lptr->Units * lptr->Reps;
+ if(!FSize && lptr->Ptr)return(po);
+ Total += FSize;
+ }
+ po = U_PO_create(NULL, Total, Total, Type);
+ if(po){
+ cptr = po->Data;
+ for(lptr=List; lptr->TE != U_XX; lptr++){
+ FSize = lptr->Units * lptr->Reps;
+ if(FSize){ /* Ptr is not NULL, that would have been detected already */
+ hptr = cptr;
+ if(lptr->TE & U_RP){ U_PMF_REPCPY_DSTSHIFT(&cptr, lptr->Ptr, lptr->Units, lptr->Reps); }
+ else { U_PMF_MEMCPY_DSTSHIFT(&cptr, lptr->Ptr, FSize); }
+ if(((lptr->TE & U_LE) && U_IS_BE) || ((lptr->TE & U_BE) && U_IS_LE)){
+ if(lptr->Units==2){ U_swap2(hptr,lptr->Reps); }
+ else if(lptr->Units==4){ U_swap4(hptr,lptr->Reps); }
+ }
+ }
+ }
+ }
+ return(po);
+}
+
+/**
+ \brief Create U_DPSEUDO_OBJ's for the Points and Types of a path
+ \param Elements Number of elements in Points. May be zero, which creates an empty path.
+ \param Points Array of U_PMF_POINTF values.
+ \param First Apply to first point, unsigned byte, lower 4 bits hold the PathPointType flag upper 4 bits hold the PathPointType enumeration. Must have U_PPT_Start set.
+ \param Others Apply to all other points, unsigned byte, lower 4 bits hold the PathPointType flag upper 4 bits hold the PathPointType enumeration. Must have U_PPT_Line or U_PPT_Bezier set.
+ \returns pointer to the DU_PSEUDO_OBJ object, NULL on error
+*/
+U_DPSEUDO_OBJ *U_PATH_create(int Elements, const U_PMF_POINTF *Points, uint8_t First, uint8_t Others){
+ if(Elements){
+ if(!Points){ return(NULL); }
+ if( (First & U_PPT_MASK) != U_PPT_Start ){ return(NULL); }
+ if(!(Others & U_PPT_Bezier)){ return(NULL); } /* will pass if either line or bezier is set */
+ }
+
+ U_DPSEUDO_OBJ *Path = (U_DPSEUDO_OBJ *)calloc(sizeof(U_DPSEUDO_OBJ),1); /* make poTypes and poPoints NULL */
+ const U_SERIAL_DESC List[] = { {NULL,0,0,U_XX} };
+ if(Path){
+ Path->Elements = Elements;
+ Path->poPoints = U_PMF_SERIAL_set(U_PMF_RAW_OID, List); /* Empty PO to hold points as raw data */
+ if(!Elements){
+ Path->poTypes = U_PMF_SERIAL_set(U_PMF_RAW_OID, List); /* Empty PO to hold types as raw data */
+ }
+ else {
+ Path->poPoints = U_PO_append(Path->poPoints, (char *)Points, Elements*sizeof(U_PMF_POINTF));
+ if(Path->poPoints){
+ U_PSEUDO_OBJ *tpo = U_PMF_PATHPOINTTYPE_set2(Elements, First | U_PPT_Start, Others); /* PO holding types, has leading Elements value */
+ Path->poTypes = U_PO_po_append(NULL, tpo, U_PMF_DROP_ELEMENTS); /* remove the leading Elements value*/
+ U_PO_free(&tpo);
+ if(!Path->poTypes){ U_PO_free(&Path->poPoints); }
+ }
+ if(!Path->poPoints){ U_DPO_free(&Path); }
+ }
+ }
+ return(Path);
+}
+
+/**
+ \brief Free U_DPSEUDO_OBJ's
+ \returns 1 on success, 0 on error.
+*/
+int U_DPO_free(U_DPSEUDO_OBJ **dpo){
+ if(!dpo){ return(0); }
+ if(!*dpo){ return(1); }
+ U_DPSEUDO_OBJ *kpo = *dpo;
+ if(kpo->poPoints){ U_PO_free(&kpo->poPoints); }
+ if(kpo->poTypes){ U_PO_free(&kpo->poTypes); }
+ free(*dpo);
+ *dpo=NULL;
+ return(1);
+}
+
+/**
+ \brief Clear U_DPSEUDO_OBJ's. Memory is retained, Elements and Used values are set to 0.
+ \returns 1 on success, 0 on error.
+
+ It is much more efficient to clear a DPO and reuse it than to free that DPO and create another.
+*/
+int U_DPO_clear(U_DPSEUDO_OBJ *dpo){
+ if(!dpo){ return(0); }
+ if(dpo->poPoints){ dpo->poPoints->Used = 0; }
+ if(dpo->poTypes){ dpo->poTypes->Used = 0; }
+ dpo->Elements = 0;
+ return(1);
+}
+
+/**
+ \brief Append a "moveto" point to a path
+ \param Path Address of a DoublePseudoObject holding the path to append to.
+ \param Point Point to move to.
+ \param Flags Flags may be (U_PTP_None, U_PTP_DashMode, U_PTP_PathMarker, U_PTP_NoBit, U_PTP_CloseSubpath)
+ \returns 1 on success, 0 on error.
+*/
+int U_PATH_moveto(U_DPSEUDO_OBJ *Path, U_PMF_POINTF Point, uint8_t Flags){
+ if(!Path){ return(0); }
+ U_PSEUDO_OBJ *tpo;
+ U_PSEUDO_OBJ *tpo2;
+ uint8_t Type = (Flags & U_PTP_NotClose) | U_PPT_Start;
+
+ tpo = U_PMF_POINTF_set(1, &Point);
+ if(!tpo){ return(0); }
+ tpo2 = U_PO_po_append(Path->poPoints, tpo, U_PMF_DROP_ELEMENTS);
+ U_PO_free(&tpo);
+ if(!tpo2)return(0);
+ Path->poPoints = tpo2;
+
+
+ tpo = U_PMF_PATHPOINTTYPE_set(1, &Type);
+ if(!tpo){ return(0); }
+ tpo2= U_PO_po_append(Path->poTypes, tpo, U_PMF_DROP_ELEMENTS);
+ U_PO_free(&tpo);
+ if(!tpo2)return(0);
+ Path->poTypes = tpo2;
+
+ Path->Elements++;
+ return(1);
+}
+
+/**
+ \brief Append a "lineto" point to a path
+ \param Path Address of a DoublePseudoObject holding the path to append to.
+ \param Point U_PMF_POINTF point to draw to.
+ \param Flags Flags may be (U_PTP_None, U_PTP_DashMode, U_PTP_PathMarker, U_PTP_NoBit, U_PTP_CloseSubpath)
+ \returns 1 on success, 0 on error.
+*/
+int U_PATH_lineto(U_DPSEUDO_OBJ *Path, U_PMF_POINTF Point, uint8_t Flags){
+ if(!Path || !Path->Elements){ return(0); } /* must be at least one point to extend from */
+ if(Path->poTypes->Data[Path->Elements - 1] & U_PTP_CloseSubpath){ return(0); } /* cannot extend a closed subpath */
+ U_PSEUDO_OBJ *tpo;
+ U_PSEUDO_OBJ *tpo2;
+ uint8_t Type = (Flags & U_PTP_NotClose) | U_PPT_Line;
+ tpo = U_PMF_POINTF_set(1, &Point);
+ if(!tpo){ return(0); }
+ tpo2 = U_PO_po_append(Path->poPoints, tpo, U_PMF_DROP_ELEMENTS);
+ U_PO_free(&tpo);
+ if(!tpo2)return(0);
+ Path->poPoints = tpo2;
+
+
+ tpo = U_PMF_PATHPOINTTYPE_set(1, &Type);
+ if(!tpo){ return(0); }
+ tpo2 = U_PO_po_append(Path->poTypes, tpo, U_PMF_DROP_ELEMENTS);
+ U_PO_free(&tpo);
+ if(!tpo2)return(0);
+ Path->poTypes = tpo2;
+
+ Path->Elements++;
+ return(1);
+}
+
+/**
+ \brief Set the closepath bit in the last point
+ \param Path Address of a DoublePseudoObject holding the path to act upon.
+ \returns 1 on success, 0 on error.
+*/
+int U_PATH_closepath(U_DPSEUDO_OBJ *Path){
+ if(!Path || !Path->poTypes){ return(0); }
+ uint32_t Elements = Path->Elements;
+ uint8_t *Type = (uint8_t *)(Path->poTypes->Data) + Elements - 1;
+ if(*Type & U_PPT_Start){ return(0); } /* single point closed path makes no sense */
+ *Type = *Type | U_PTP_CloseSubpath;
+ return(1);
+}
+
+/**
+ \brief Append a "polylineto" set of point to a path
+ \param Path Address of a DoublePseudoObject holding the path to append to.
+ \param Elements number of Points and Flags
+ \param Points Line points.
+ \param Flags Flags (U_PTP_None, U_PTP_DashMode, U_PTP_PathMarker, U_PTP_NoBit, but NOT U_PTP_CloseSubpath)
+ \param StartSeg If set, use U_PPT_Start PathPointType enumeration for first point, otherwise use U_PPT_Line.
+ \returns 1 on success, 0 on error.
+*/
+int U_PATH_polylineto(U_DPSEUDO_OBJ *Path, uint32_t Elements, const U_PMF_POINTF *Points, uint8_t Flags, uint8_t StartSeg){
+ if(!Path || !Points){ return(0); }
+ if(!Elements){ return(1); } /* harmless - do nothing */
+ U_PSEUDO_OBJ *tpo;
+ U_PSEUDO_OBJ *tpo2;
+ uint8_t First, Others;
+
+ tpo = U_PMF_POINTF_set(Elements, Points);
+ tpo2 = U_PO_po_append(Path->poPoints, tpo, U_PMF_DROP_ELEMENTS);
+ U_PO_free(&tpo);
+ if(!tpo2)return(0);
+ Path->poPoints = tpo2;
+
+ if(StartSeg){ First = (Flags & U_PTP_NotClose) | U_PPT_Start; }
+ else { First = (Flags & U_PTP_NotClose) | U_PPT_Line; }
+ Others = (Flags & U_PTP_NotClose) | U_PPT_Line;
+ tpo = U_PMF_PATHPOINTTYPE_set2(Elements, First, Others);
+ if(!tpo){ return(0); }
+ tpo2 = U_PO_po_append(Path->poTypes, tpo, U_PMF_DROP_ELEMENTS);
+ U_PO_free(&tpo);
+ if(!tpo2)return(0);
+ Path->poTypes = tpo2;
+
+ Path->Elements += Elements;
+ return(1);
+}
+
+
+/**
+ \brief Append a "polybezierto" set of point to a path
+ \param Path Address of a DoublePseudoObject holding the path to append to.
+ \param Elements number of Points
+ \param Points Bezier points. Optional starting point, then N sets of 3, example: [P1] (Q12A Q12B P2) (Q23A Q23B P3).
+ \param Flags Flags (U_PTP_None, U_PTP_DashMode, U_PTP_PathMarker, U_PTP_NoBit, but NOT U_PTP_CloseSubpath)
+ \param StartSeg If set, use U_PPT_Start PathPointType enumeration for first point, otherwise use U_PPT_Bezier.
+ \returns 1 on success, 0 on error.
+
+ If Start is set Elements must be 1 + multiple of 3. Ie, P1 Q12A Q12B P2 Q23A Q23B P3
+
+ If Start is clear Elements must be a multiple of 3. Ie, (P1, already in path) Q12A Q12B P2 Q23A Q23B P3
+*/
+int U_PATH_polybezierto(U_DPSEUDO_OBJ *Path, uint32_t Elements, const U_PMF_POINTF *Points, uint8_t Flags, uint8_t StartSeg){
+ if(!Path || !Points){ return(0); }
+ if(!Elements){
+ if(StartSeg){ return(0); } /* cannot have both a NEW segment and ZERO points */
+ else{ return(1); } /* harmless - do nothing */
+ }
+ if(StartSeg && ((Elements - 1) % 3)){ return(0); } /* new segment must be 1 + N*3 points */
+ if(!StartSeg && (Elements % 3)){ return(0); } /* extend segment must be N*3 points */
+ U_PSEUDO_OBJ *tpo;
+ U_PSEUDO_OBJ *tpo2;
+ uint8_t First, Others;
+
+ tpo = U_PMF_POINTF_set(Elements, Points);
+ tpo2 = U_PO_po_append(Path->poPoints, tpo, U_PMF_DROP_ELEMENTS);
+ U_PO_free(&tpo);
+ if(!tpo2)return(0);
+ Path->poPoints = tpo2;
+
+ if(StartSeg){ First = (Flags & U_PTP_NotClose) | U_PPT_Start; }
+ else { First = (Flags & U_PTP_NotClose) | U_PPT_Bezier; }
+ Others = (Flags & U_PTP_NotClose) | U_PPT_Bezier;
+ tpo = U_PMF_PATHPOINTTYPE_set2(Elements, First, Others);
+ if(!tpo){ return(0); }
+ tpo2 = U_PO_po_append(Path->poTypes, tpo, U_PMF_DROP_ELEMENTS);
+ U_PO_free(&tpo);
+ if(!tpo2)return(0);
+ Path->poTypes = tpo2;
+
+ Path->Elements += Elements;
+ return(1);
+}
+
+/**
+ \brief Append a "polygon" set of points to a path.
+ \param Path Address of a DoublePseudoObject holding the path to append to.
+ \param Elements number of Points and Flags
+ \param Points Line points.
+ \param Flags Flags (U_PTP_None, U_PTP_DashMode, U_PTP_PathMarker, U_PTP_NoBit, but NOT U_PTP_CloseSubpath)
+ \returns 1 on success, 0 on error.
+*/
+int U_PATH_polygon(U_DPSEUDO_OBJ *Path, uint32_t Elements, const U_PMF_POINTF *Points, uint8_t Flags){
+ int status = U_PATH_polylineto(Path, Elements, Points, Flags, U_SEG_NEW);
+ if(status){
+ status = U_PATH_closepath(Path);
+ }
+ return(status);
+}
+
+//! \cond
+// These are not exposed in the API
+/* Parameterized Ellipse coordinates */
+U_PMF_POINTF U_eparam(U_FLOAT a, U_FLOAT b, U_PMF_POINTF *center, double Ang, double Theta){
+ U_PMF_POINTF point;
+ point.X = center->X + a*cos(Theta)*cos(Ang) - b*sin(Theta)*sin(Ang);
+ point.Y = center->Y + a*sin(Theta)*cos(Ang) + b*cos(Theta)*sin(Ang);
+ return(point);
+}
+
+/* Parameterized Ellipse derivative */
+U_PMF_POINTF U_eparam2(U_FLOAT a, U_FLOAT b, double Ang, double Theta){
+ U_PMF_POINTF point;
+ point.X = -a*cos(Theta)*sin(Ang) - b*sin(Theta)*cos(Ang);
+ point.Y = -a*sin(Theta)*sin(Ang) + b*cos(Theta)*cos(Ang);
+ return(point);
+}
+
+double U_aparam(double Ang1, double Ang2){
+ double Alpha;
+ double t2;
+ t2 = tan((Ang2 - Ang1)/2.0);
+ t2 *= t2;
+ Alpha = sin(Ang2 - Ang1) * (sqrt(4 + 3*t2) -1.0)/3.0;
+ return(Alpha);
+}
+
+/* Parameterized Bezier point Q1 or Q2 derivative */
+U_PMF_POINTF U_qparam(double Alpha, double a, double b, U_PMF_POINTF *Point, double Ang, double Theta, int mode){
+ U_PMF_POINTF Q, Prime;
+ Prime = U_eparam2(a,b,Ang,Theta);
+ if(mode==1){ /* Q1, anything else is Q2*/
+ Q.X = Point->X + Alpha * Prime.X;
+ Q.Y = Point->Y + Alpha * Prime.Y;
+ }
+ else {
+ Q.X = Point->X - Alpha * Prime.X;
+ Q.Y = Point->Y - Alpha * Prime.Y;
+ }
+ return(Q);
+}
+//! \endcond
+
+/**
+ \brief Append an "arcto" set of points to a path (Bezier points are calculated, and these are appended
+ \param Path Address of a pointer to the U_PSEUDO_OBJ that holds points
+ \param Start Start angle, >=0.0, degrees clockwise from 3:00
+ \param Sweep Sweep angle, -360<= angle <=360, degrees clockwise from Start
+ \param Rot Rotation angle to apply to coordinate system (Start and Rect), positive is degrees clockwise
+ \param Rect U_PMF_RECTF that defines the bounding rectangle.
+ \param Flags Flags (U_PTP_None, U_PTP_DashMode, U_PTP_PathMarker, U_PTP_NoBit, but NOT U_PTP_CloseSubpath)
+ \param StartSeg If set, the arc starts a new segment, if clear, continue the existing segment. Starting a new segment does not automatically apply U_PATH_closepath to the existing path.
+ \returns 1 on success, 0 on error.
+
+ Based on Luc Maisonobe's work, http://www.spaceroots.org/documents/ellipse/
+*/
+int U_PATH_arcto(U_DPSEUDO_OBJ *Path, U_FLOAT Start, U_FLOAT Sweep, U_FLOAT Rot, U_PMF_RECTF *Rect, uint8_t Flags, int StartSeg){
+ U_PMF_POINTF Bz[3];
+ U_PMF_POINTF Center;
+ U_PMF_POINTF P1,P2;
+ double a, b;
+ int done = 0;
+ int fpoint = 0;
+ double L1, L2; /* These are degrees CounterClockwise from 3:00 */
+ double Ang1, Ang2; /* These are parametric angles, derived from L1, L2*/
+ double Alpha; /* Dimensionless number used for Q1, Q2 */
+ double Theta; /* Rot in radians */
+ double Slop; /* do not let rounding errors cause spurious end points */
+ if(!Path){ return(0); }
+ if((Sweep > 360.0) || (Sweep < -360.0)){ return(0); }
+ /* Start should be between 0 and 360 degrees, but it does not really matter because sin, and cos will accept anything */
+ /* the sign on Sweep and Start is correct bacause LM's derivation has y positive up, but GDI+ has y positive down. */
+ a = Rect->Width/2.0;
+ b = Rect->Height/2.0;
+ if(!a || !b){ return(0); }
+ Center.X = Rect->X + a;
+ Center.Y = Rect->Y + b;
+ /* convert to radians */
+ Start = (2.0 * U_PI * Start)/360.0;
+ Sweep = (2.0 * U_PI * Sweep)/360.0;
+ Theta = (2.0 * U_PI * Rot )/360.0;
+ Slop = Sweep/100000.0;
+ L1 = Start;
+
+ while(!done){
+ if(Sweep < 0){
+ L2 = L1 - U_PI/2.0;
+ if(L2 <= Sweep + Start - Slop){ L2 = Sweep + Start; done = 1; }
+ else {done = 0; }
+ }
+ else {
+ L2 = L1 + U_PI/2.0;
+ if(L2 >= Sweep + Start + Slop){ L2 = Sweep + Start; done = 1; }
+ else {done = 0; }
+ }
+ Ang1 = atan2(sin(L1)/b, cos(L1)/a);
+ Ang2 = atan2(sin(L2)/b, cos(L2)/a);
+ Alpha = U_aparam(Ang1, Ang2);
+ P1 = U_eparam(a, b, &Center, Ang1, Theta); /* P1 */
+ P2 = U_eparam(a, b, &Center, Ang2, Theta); /* P2 */
+ Bz[0] = U_qparam(Alpha, a, b, &P1, Ang1, Theta, 1); /* Q1 */
+ Bz[1] = U_qparam(Alpha, a, b, &P2, Ang2, Theta, 2); /* Q2 */
+ Bz[2] = P2;
+ if(!fpoint){
+ if(StartSeg){ U_PATH_moveto(Path, P1, Flags); }
+ else { U_PATH_lineto(Path, P1, Flags); }
+ fpoint = 1;
+ }
+ U_PATH_polybezierto(Path, 3, Bz, Flags, U_SEG_OLD );
+ L1 = L2;
+ }
+ return(1);
+}
+
+/**
+ \brief Allocate and construct an array of U_PMF_POINTF objects which have been subjected to a U_XFORM
+ \returns pointer to an array of U_PMF_POINTF structures.
+ \param points pointer to the source U_PMF_POINTF structures
+ \param count number of members in points
+ \param xform U_XFORM to apply
+
+*/
+U_PMF_POINTF *pointfs_transform(U_PMF_POINTF *points, int count, U_XFORM xform){
+ U_PMF_POINTF *newpts=NULL;;
+ int i;
+ float X,Y;
+ newpts = (U_PMF_POINTF *) malloc(count * sizeof(U_PMF_POINTF));
+ if(newpts){
+ for(i=0; i<count; i++){
+ X = points[i].X;
+ Y = points[i].Y;
+ newpts[i].X = U_ROUND(X * xform.eM11 + Y * xform.eM21 + xform.eDx);
+ newpts[i].Y = U_ROUND(X * xform.eM12 + Y * xform.eM22 + xform.eDy);
+ }
+ }
+ return(newpts);
+}
+
+/**
+ \brief Allocate and construct an array of U_PMF_RECTF objects which have been subjected to a U_XFORM
+ \returns pointer to an array of U_PMF_RECTF structures.
+ \param Rects pointer to the source U_PMF_RECTF structures
+ \param Count number of members in Rects
+ \param Xform U_XFORM to apply. Rotation is ignored, only translation is applied.
+
+*/
+U_PMF_RECTF *rectfs_transform(U_PMF_RECTF *Rects, int Count, U_XFORM Xform){
+ U_PMF_RECTF *newRects;
+ int i;
+ newRects = (U_PMF_RECTF *) malloc(Count * sizeof(U_PMF_RECTF));
+ if(newRects){
+ for(i=0; i<Count; i++){
+ newRects[i].X = U_ROUND(Rects[i].X + Xform.eDx);
+ newRects[i].Y = U_ROUND(Rects[i].Y + Xform.eDy);
+ newRects[i].Width = U_ROUND(Rects[i].Width);
+ newRects[i].Height = U_ROUND(Rects[i].Height);
+ }
+ }
+ return(newRects);
+}
+
+/**
+ \brief Utility function calculate the transformation matrix needed to make a gradient run precisely corner to corner of a rectangle
+ \param Angle Rotation in degrees clockwise of the gradient. 0 is horizontal gradient.
+ \param w Width of the rectangle
+ \param h Height of the rectangle
+ \param x X coordinate of upper left corner of rectangle
+ \param y Y coordinate of upper left corner of rectangle
+ \param Periods Periods of gradient corner to corner. 1.0 is one, corner to corner.
+ \return Transformation matrix. All values are zero if Periods, w, or h are less than or equal to zero.
+*/
+U_PMF_TRANSFORMMATRIX tm_for_gradrect(U_FLOAT Angle, U_FLOAT w, U_FLOAT h, U_FLOAT x, U_FLOAT y, U_FLOAT Periods){
+//! \cond
+#define CLOSE_TO_IS_REALLY_ZERO(A) ((A) > 1.0e-10 || (A) < -1.0e-10 ? (A) : 0.0) //! \hideinitializer
+//! \endcond
+ U_PMF_TRANSFORMMATRIX tm;
+ double dang = Angle * 2*U_PI /360.0;
+ double scale;
+ double cd,sd;
+ if((Periods <=0.0) || (w <= 0.0) || (h <= 0.0)){
+ tm.m11 = tm.m12 = tm.m21 = tm.m22 = tm.dX = tm.dY = 0.0;
+ }
+ else {
+ /*
+ scale is gradient period divided by w
+ The scale value sets the gradient period to match exactly with the inscribed (w,h) rectangle
+ in the direction specified by the angle.
+ The numberator of scale is the max of the four dot product values of the rotated X basis unit vector with (w,h),
+ with each of the vectors {w,h}, {-w,h}, {-w,-h}, {w,h}. Those vectors run from each corner in turn
+ to the opposite corner. The one most parallel to the rotated unit vector will have both terms positive.
+
+ Trig results like cos(pi/2) are not stable between platforms due to minor differences in the
+ implementation. Detect these and make them zero, which then allows binary comparison of output files.
+ Otherwise the binary comparisons between platforms would fail because of a bunch of insignificant digits.
+ */
+ cd = CLOSE_TO_IS_REALLY_ZERO(cos(dang));
+ sd = CLOSE_TO_IS_REALLY_ZERO(sin(dang));
+ scale = (w*fabs(cd) + h*fabs(sd))/(w*Periods);
+ tm.m11 = scale * cd;
+ tm.m12 = -scale * sd;
+ tm.m21 = scale * sd;
+ tm.m22 = scale * cd;
+ /* offset is to one corner of the square, depending on which quadrant the rotation selects. */
+ if(cos(dang)>=0){
+ tm.dX = x;
+ if(sin(dang)>=0){tm.dY = y + h; } // LL corner
+ else { tm.dY = y; } // UL corner
+ }
+ else {
+ tm.dX = x + w;
+ if(sin(dang)>=0){ tm.dY = y + h; } // LR corner
+ else { tm.dY = y; } // UR corner
+ }
+ }
+ return tm;
+#undef CLOSE_TO_IS_REALLY_ZERO
+}
+/**
+ \brief Create a U_PSEUDO_OBJ containing a U_PMR_FILLPATH and U_PMR_DRAWPATH records.
+ \returns pointer to U_PSEUDO_OBJ or NULL on error.
+ \param PathID U_PMF_PATH object in the EMF+ object table (0-63, inclusive)
+ \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+ \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive)
+*/
+U_PSEUDO_OBJ *U_PMR_drawfill(uint32_t PathID, uint32_t PenID, const U_PSEUDO_OBJ *BrushID){
+ U_PSEUDO_OBJ *po = U_PMR_FILLPATH_set(PathID, BrushID);
+ if(po){
+ U_PSEUDO_OBJ *tpo = U_PMR_DRAWPATH_set(PathID, PenID);
+ po = U_PO_po_append(po, tpo, U_PMF_KEEP_ELEMENTS);
+ U_PO_free(&tpo);
+ }
+ return(po);
+}
+
+
+
+/**
+ \brief Extract a single data field from a source.
+ \returns 1 on success, 0 on error.
+ \param Src where the data is coming from. It is incremented by the number of bytes retrieved.
+ \param Dst where the data will be stored. This must either be NULL (in which case the Src
+ is advanced and nothing is stored, or it must be allocated to Reps * Units bytes!!!!
+ \param Units number of bytes in each unit of the data field
+ \param Reps number of repeats of units in the data field.
+ If a Ptr is NULL, then Units*Reps 0 bytes are stored.
+ If a Ptr is NOT NULL, and Units or Reps, is zero an error is signaled.
+ If a Ptr is NULL and Units*Reps is 0, nothing happens.
+ \param SE logical (Source Endian). Only relevant for Sizes of 2 or 4
+ Indicates when Bytes may need to be rearranged when they are retrieved.
+ U_XE no change (this is used when the data has already been set to the proper orientation or it is not known)
+ U_LE source is Little Endian
+ U_BE source is Big Endian.
+ U_XX error
+
+*/
+int U_PMF_SERIAL_get(const char **Src, void *Dst, size_t Units, size_t Reps, int SE){
+ if(!Src || !*Src || SE == U_XX){ return(0); }
+ U_PMF_MEMCPY_SRCSHIFT(Dst, Src, Units * Reps);
+ if(!Dst){ return(1); } /* "fake" get, no data was retrieved, so we are done */
+ if(SE == U_XE){ return(1); }
+ if(SE == U_LE && U_IS_LE){ return(1); }
+ if(SE == U_BE && U_IS_BE){ return(1); }
+ /* need to swap */
+ if( Units==2){ U_swap2(Dst,Reps); }
+ else if(Units==4){ U_swap4(Dst,Reps); }
+ return(1);
+}
+
+/**
+ \brief Conditionally extract an array of data from a source, allocating space to hold it.
+ \returns 1 on success, 0 on error.
+ \param Src where the data is coming from. It is incremented by the number of bytes retrieved.
+ \param Dst Caller must free. Where the pointer to the data will be stored. Reps * Units bytes will be allocated,
+ \param Units number of bytes in each unit of the data field
+ \param Reps number of repeats of units in the data field.
+ If a Ptr is NULL, then Units*Reps 0 bytes are stored.
+ If a Ptr is NOT NULL, and Units or Reps, is zero an error is signaled.
+ If a Ptr is NULL and Units*Reps is 0, nothing happens.
+ \param SE logical (Source Endian). Only relevant for Sizes of 2 or 4
+ Indicates when Bytes may need to be rearranged when they are retrieved.
+ U_XE no change (this is used when the data has already been set to the proper orientation or it is not known)
+ U_LE source is Little Endian
+ U_BE source is Big Endian.
+ U_XX error
+ \param Cond Store the data into *Dst if true, set *Dst to NULL otherwise.
+
+*/
+int U_PMF_SERIAL_array_copy_get(const char **Src, void **Dst, size_t Units, size_t Reps, int SE, int Cond){
+ if(!Src || !*Src || !Dst || SE == U_XX){ return(0); }
+ if(!Cond){
+ *Src += Units * Reps;
+ *Dst = NULL;
+ return(1);
+ }
+ *Dst = malloc(Units * Reps);
+ if(!*Dst){ return(1); } /* "fake" get, no data was retrieved, so we are done */
+ U_PMF_MEMCPY_SRCSHIFT(*Dst, Src, Units * Reps);
+ if(SE == U_XE){ return(1); }
+ if(SE == U_LE && U_IS_LE){ return(1); }
+ if(SE == U_BE && U_IS_BE){ return(1); }
+ /* need to swap */
+ if( Units==2){ U_swap2(*Dst,Reps); }
+ else if(Units==4){ U_swap4(*Dst,Reps); }
+ return(1);
+}
+
+
+
+/**
+ \brief Calculate the length in bytes of a relative path object composed of U_PMF_INTEGER7 and U_PMF_INTER15 values
+ \return >=0 length == success, <0 error
+ \param contents Start of a relative path consisting of int7 and int15 X,Y pairs.
+ \param Elements number of relative X,Y pairs in the object
+*/
+int U_PMF_LEN_REL715(const char *contents, int Elements){
+ int length=0;
+ Elements *= 2; /* N pairs = 2N values */
+ for( ; Elements; Elements--){
+ /* X or Y value */
+ if(*contents & U_TEST_INT7){ contents +=2; length +=2; } //int15
+ else { contents +=1; length +=1; } //int7
+ }
+ return(length);
+}
+
+/**
+ \brief Calculate the length in bytes of objects which are a 4 byte Count followed by Count * float bytes
+ \return >=0 length == success, <0 error
+ Object types whose size may be derived with this function are:
+ U_PMF_COMPOUNDLINEDATA
+ U_PMF_DASHEDLINEDATA
+*/
+int U_PMF_LEN_FLOATDATA(const char *contents){
+ int Size;
+ U_PMF_SERIAL_get(&contents, &Size, 4, 1, U_LE);
+ Size = 4*Size + 4;
+ return(Size);
+}
+
+/**
+ \brief Calculate the length in bytes of objects which are a 4 byte count followed by count bytes
+ \return >=0 length == success, <0 error
+ Object types whose size may be derived with this function are:
+ U_PMF_BOUNDARYPATHDATA
+ U_PMF_BOUNDARYPOINTDATA
+ U_PMF_CUSTOMSTARTCAPDATA
+ U_PMF_PATH
+ U_PMF_LINEPATH
+ U_PMF_REGIONNODEPATH
+*/
+int U_PMF_LEN_BYTEDATA(const char *contents){
+ int Size;
+ U_PMF_SERIAL_get(&contents, &Size, 4, 1, U_LE);
+ Size += 4;
+ return(Size);
+}
+
+/**
+ \brief Create a string containing the curly bracket form of the 16 byte GUID value
+ \return number of bytes in record, 0 on error
+ \param GUID pointer to the 16 unsigned bytes
+ \return string in curly bracket form.
+ http://msdn.microsoft.com/en-us/library/cc230316.aspx
+
+ Text form is Data1-Data2-Data3-Data4, the first 3 are stored as little endian integers, the last as a string (big endian).
+*/
+char *U_PMF_CURLYGUID_set(uint8_t *GUID){
+ char *string=malloc(64);
+ if(string){
+ sprintf(string,"{%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X}",
+ GUID[3],GUID[2],GUID[1],GUID[0],
+ GUID[5],GUID[4],
+ GUID[7],GUID[6],
+ GUID[8],GUID[9],
+ GUID[10],GUID[11],GUID[12],GUID[13],GUID[14],GUID[15]
+ );
+ }
+ return(string);
+}
+
+/**
+ \brief Identify a known curly GUID
+ \param string Curly GUID form.
+ \return EmageEffects Enumerator
+
+ EMF+ manual 2.1.3.1, Microsoft name: ImageEffects Identifier
+*/
+int U_PMF_KNOWNCURLYGUID_set(const char *string){
+ int status;
+ if( !strcmp(string,"{633C80A4-1843-482B-9EF2-BE2834C5FDD4}")){ status = U_IEE_BlurEffectGuid; }
+ else if(!strcmp(string,"{D3A1DBE1-8EC4-4C17-9F4C-EA97AD1C343D}")){ status = U_IEE_BrightnessContrastEffectGuid; }
+ else if(!strcmp(string,"{537E597D-251E-48DA-9664-29CA496B70F8}")){ status = U_IEE_ColorBalanceEffectGuid; }
+ else if(!strcmp(string,"{DD6A0022-58E4-4A67-9D9B-D48EB881A53D}")){ status = U_IEE_ColorCurveEffectGuid; }
+ else if(!strcmp(string,"{A7CE72A9-0F7F-40D7-B3CC-D0C02D5C3212}")){ status = U_IEE_ColorLookupTableEffectGuid; }
+ else if(!strcmp(string,"{718F2615-7933-40E3-A511-5F68FE14DD74}")){ status = U_IEE_ColorMatrixEffectGuid; }
+ else if(!strcmp(string,"{8B2DD6C3-EB07-4D87-A5F0-7108E26A9C5F}")){ status = U_IEE_HueSaturationLightnessEffectGuid;}
+ else if(!strcmp(string,"{99C354EC-2A31-4F3A-8C34-17A803B33A25}")){ status = U_IEE_LevelsEffectGuid; }
+ else if(!strcmp(string,"{74D29D05-69A4-4266-9549-3CC52836B632}")){ status = U_IEE_RedEyeCorrectionEffectGuid; }
+ else if(!strcmp(string,"{63CBF3EE-C526-402C-8F71-62C540BF5142}")){ status = U_IEE_SharpenEffectGuid; }
+ else if(!strcmp(string,"{1077AF00-2848-4441-9489-44AD4C2D7A2C}")){ status = U_IEE_TintEffectGuid; }
+ else { status = U_IEE_Unknown; }
+ return(status);
+}
+
+/** \brief Load a GUID from text format into EMF+ file binary format.
+ \param string Curly GUID as text, minus the barckets and dashes.
+ \return GUID in EMF+ file binary format.
+
+
+This accepts a string that is 16 bytes long = 32 characters hex (no dash spaces or brackets) as text.
+Text form is; Data1|Data2|Data3|Data4, first three are stored as little endian integers of 4,2,2 bytes, respectively,
+last is stored like a string (big endian), after conversion from text hex to binary.
+
+This function is not normally called by end user code.
+*/
+uint8_t *U_LOAD_GUID(char *string){
+ uint32_t Data1,tData2,tData3,tByte;
+ uint16_t Data2,Data3;
+ char *Data4 = string + 16;
+ uint8_t *hold = malloc(16);
+ char *lf = (char *) hold;
+ int i;
+ if(hold){
+ Data1=tData2=tData3=0;
+ if(3 != sscanf(string + 0,"%8X",&Data1) +
+ sscanf(string + 8,"%4X",&tData2) +
+ sscanf(string + 12,"%4X",&tData3)){
+ free(hold);
+ hold = NULL;
+ goto bye;
+ }
+ Data2=tData2;
+ Data3=tData3;
+ U_PMF_MEMCPY_DSTSHIFT(&lf, &Data1, 4);
+ U_PMF_MEMCPY_DSTSHIFT(&lf, &Data2, 2);
+ U_PMF_MEMCPY_DSTSHIFT(&lf, &Data3, 2);
+ if(U_IS_BE){ /* these fields are stored little endian */
+ U_swap4(hold,1);
+ U_swap2(hold+4,2);
+ }
+ /* remainder is converted byte by byte and stored in that order */
+ for(i=0;i<8;i++,Data4+=2,lf++){
+ if(1 != sscanf(Data4,"%2X",&tByte)){
+ free(hold);
+ hold = NULL;
+ goto bye;
+ }
+ *lf=tByte;
+ }
+ }
+bye:
+ return(hold);
+}
+
+/**
+ \brief Generate the 16 byte form from OID of the ImageEffects Identifier
+ \param OID OID of the ImageEffects Identifier
+ \return pointer to 16 byte buffer holding the long GUID binary form, or NULL on error.
+
+ EMF+ manual 2.1.3.1, Microsoft name: ImageEffects Identifier
+*/
+uint8_t *U_OID_To_GUID(uint32_t OID){
+ uint8_t *lf = NULL;
+ if( OID == U_PMF_IE_BLUR_OID ){ lf = U_LOAD_GUID("633C80A41843482B9EF2BE2834C5FDD4"); }
+ else if(OID == U_PMF_IE_BRIGHTNESSCONTRAST_OID ){ lf = U_LOAD_GUID("D3A1DBE18EC44C179F4CEA97AD1C343D"); }
+ else if(OID == U_PMF_IE_COLORBALANCE_OID ){ lf = U_LOAD_GUID("537E597D251E48DA966429CA496B70F8"); }
+ else if(OID == U_PMF_IE_COLORCURVE_OID ){ lf = U_LOAD_GUID("DD6A002258E44A679D9BD48EB881A53D"); }
+ else if(OID == U_PMF_IE_COLORLOOKUPTABLE_OID ){ lf = U_LOAD_GUID("A7CE72A90F7F40D7B3CCD0C02D5C3212"); }
+ else if(OID == U_PMF_IE_COLORMATRIX_OID ){ lf = U_LOAD_GUID("718F2615793340E3A5115F68FE14DD74"); }
+ else if(OID == U_PMF_IE_HUESATURATIONLIGHTNESS_OID){ lf = U_LOAD_GUID("8B2DD6C3EB074D87A5F07108E26A9C5F"); }
+ else if(OID == U_PMF_IE_LEVELS_OID ){ lf = U_LOAD_GUID("99C354EC2A314F3A8C3417A803B33A25"); }
+ else if(OID == U_PMF_IE_REDEYECORRECTION_OID ){ lf = U_LOAD_GUID("74D29D0569A4426695493CC52836B632"); }
+ else if(OID == U_PMF_IE_SHARPEN_OID ){ lf = U_LOAD_GUID("63CBF3EEC526402C8F7162C540BF5142"); }
+ else if(OID == U_PMF_IE_TINT_OID ){ lf = U_LOAD_GUID("1077AF0028484441948944AD4C2D7A2C"); }
+ return(lf);
+}
+
+/**
+ \brief copy data and shift source pointer by the amount of data moved
+ \param Dst Destination in memory
+ \param Src Source in memory
+ \param Size Number of bytes to move
+*/
+void U_PMF_MEMCPY_SRCSHIFT(void *Dst, const char **Src, size_t Size){
+ if(Dst)memcpy(Dst, *Src, Size);
+ *Src += Size;
+}
+
+/**
+ \brief copy data and shift destination pointer by the amount of data moved
+ \param Dst Destination in memory (this must not be NULL)
+ \param Src Source in memory (if this is NULL, fill with that many zero bytes instead)
+ \param Size Number of bytes to move
+*/
+void U_PMF_MEMCPY_DSTSHIFT(char **Dst, const void *Src, size_t Size){
+ if(Src){ memcpy(*Dst, Src, Size); }
+ else { memset(*Dst, 0, Size); }
+ *Dst += Size;
+}
+
+/**
+ \brief Copy the single instance at Src repeatedly to Dst.
+ \param Dst Destination in memory
+ \param Src Source in memory (if this is NULL, fill with that many zero bytes instead)
+ \param Size number of bytes in single instance that is template.
+ \param Reps Number of instances of the template to opy
+*/
+void U_PMF_REPCPY_DSTSHIFT(char **Dst, const void *Src, size_t Size, size_t Reps){
+ for(;Reps;Reps--){
+ if(Src){ memcpy(*Dst, Src, Size); }
+ else { memset(*Dst, 0, Size); }
+ *Dst += Size;
+ }
+}
+
+/**
+ \brief save pointer to data and shift source pointer by the amount of data moved
+ \param Dst Destination in memory
+ \param Src Source in memory or NULL. If NULL Dst is set to NULL.
+ \param Size Number of bytes to move
+*/
+void U_PMF_PTRSAV_SHIFT(const char **Dst, const char **Src, size_t Size){
+ if(*Src){
+ if(Dst)*Dst = *Src;
+ *Src += Size;
+ }
+ else {
+ if(Dst)*Dst = NULL;
+ }
+}
+
+/**
+ \brief save pointer to data and shift source pointer by the amount of data moved
+ \return 1 on sucess, 0 on error
+ \param Dst Destination in memory
+ \param Src Source in memory or NULL. If NULL Dst is set to NULL.
+ \param Doit Assign if true, otherwise, set to NULL
+*/
+int U_PMF_PTRSAV_COND(const char **Dst, const char *Src, int Doit){
+ if(!Dst){ return(0); }
+ if(Src && Doit){ *Dst = Src; }
+ else { *Dst = NULL; }
+ return(1);
+}
+/*
+
+ =====================================================================================
+ start of U_PMF_*_get() functions
+
+*/
+
+/**
+ \brief Get the 16 bit unsigned Flags field from a header.
+ \param contents Record from which to extract data, will be incremented by header size.
+ \return Flags field
+
+ In many records the only value needed from the header is Flags. Rather than mapping
+ the entire Header and returning it, in these instances this function may be called to
+ just get this one value.
+*/
+uint16_t U_PMF_HEADERFLAGS_get(const char *contents){
+ uint16_t Flags;
+ const char *cptr = contents + offsetof(U_PMF_CMN_HDR,Flags);
+ U_PMF_SERIAL_get(&cptr, &Flags, 2, 1, U_LE); /* EMF+ manual documents it as BE, but this code implements it as LE*/
+ return(Flags);
+}
+
+/**
+ \brief Retrieve whichever header fields are requested. NULL pointers do not retrieve.
+ \param contents Record from which to extract data, will be incremented by header size.
+ \param Type Record type
+ \param Flags Record flags
+ \param Size Records size
+ \param Datasize Data size
+ \return 1 on success, 0 on failure.
+*/
+int U_PMF_HEADERFIELDS_get(const char *contents,
+ uint16_t *Type, uint16_t *Flags, uint32_t *Size, uint32_t *Datasize){
+ if(!contents){ return(0); }
+ U_PMF_SERIAL_get(&contents, Type, 2, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Flags, 2, 1, U_LE); /* EMF+ manual documents it as BE, but this code implements it as LE*/
+ U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Datasize, 4, 1, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get the entire EMF+ record header.
+ \param contents Record from which to extract data, will be offset by header size.
+ \param Header Location to store data (may be NULL)
+ \returns 1
+ If Header is Null, nothing is stored but contents is still offset.
+*/
+int U_PMF_CMN_HDR_get(const char **contents, U_PMF_CMN_HDR *Header){
+ if(!contents || !*contents){ return(0); }
+ if(Header){
+ U_PMF_SERIAL_get(contents, &(Header->Type), 2, 1, U_LE);
+ U_PMF_SERIAL_get(contents, &(Header->Flags), 2, 1, U_LE); /* EMF+ manual documents it as BE, but this code implements it as LE*/
+ U_PMF_SERIAL_get(contents, &(Header->Size), 4, 1, U_LE);
+ U_PMF_SERIAL_get(contents, &(Header->DataSize), 4, 1, U_LE);
+ }
+ else {
+ *contents += sizeof(U_PMF_CMN_HDR);
+ }
+ return(1);
+}
+
+/**
+ \brief return the size in bytes of the EMF+ record
+ \param contents Record from which to extract data, will not be modified.
+ \returns size, or 0 if contents is Null
+*/
+int U_PMF_RECORD_SIZE_get(const char *contents){
+ if(!contents){ return(0); }
+ int Size;
+ const char *from = contents + 4;
+ U_PMF_SERIAL_get(&from, &Size, 4, 1, U_LE);
+ return(Size);
+}
+
+/**
+ \brief Return the size of a PenData object from an EMF+ record.
+ \param PenData Address in memory where the PenData object starts.
+ \returns size of the object in bytes
+*/
+int U_PMF_LEN_PENDATA(const char *PenData){
+ uint32_t Flags;
+ int length=12; /* Flags, Unit, Width */
+ U_PMF_SERIAL_get(&PenData, &Flags, 4, 1, U_LE);
+ PenData += 8; /* skip Unit and Width */
+ length += U_PMF_LEN_OPTPENDATA(PenData, Flags);
+ return(length);
+}
+
+/**
+ \brief Return the size of an OptPenData object from an EMF+ record.
+ \param PenData Address in memory where the PenData object starts.
+ \param Flags PenData Flags that indicate which fields are present.
+ \returns size of the object in bytes
+*/
+int U_PMF_LEN_OPTPENDATA(const char *PenData, uint32_t Flags){
+ int length=0;
+ if(Flags & U_PD_Transform){ length += sizeof(U_PMF_TRANSFORMMATRIX); }
+ if(Flags & U_PD_StartCap){ length += sizeof(int32_t); }
+ if(Flags & U_PD_EndCap){ length += sizeof(int32_t); }
+ if(Flags & U_PD_Join){ length += sizeof(uint32_t); }
+ if(Flags & U_PD_MiterLimit){ length += sizeof(U_FLOAT); }
+ if(Flags & U_PD_LineStyle){ length += sizeof(int32_t); }
+ if(Flags & U_PD_DLCap){ length += sizeof(int32_t); }
+ if(Flags & U_PD_DLOffset){ length += sizeof(int32_t); }
+ if(Flags & U_PD_DLData){ length += U_PMF_LEN_FLOATDATA(PenData + length); }
+ if(Flags & U_PD_NonCenter){ length += sizeof(int32_t); }
+ if(Flags & U_PD_CLData){ length += U_PMF_LEN_FLOATDATA(PenData + length); }
+ if(Flags & U_PD_CustomStartCap){ length += U_PMF_LEN_BYTEDATA(PenData + length); }
+ if(Flags & U_PD_CustomEndCap){ length += U_PMF_LEN_BYTEDATA(PenData + length); }
+ return(length);
+}
+
+/**
+ \brief Create and set a U_PMF_BRUSH PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Version EmfPlusGraphicsVersion object
+ \param Bd U_PSEUDO_OBJ containing one of the 5 types of Brush data
+
+ EMF+ manual 2.2.1.1, Microsoft name: EmfPlusBrush Object
+*/
+U_PSEUDO_OBJ *U_PMF_BRUSH_set(uint32_t Version, const U_PSEUDO_OBJ *Bd){
+ if(!Bd){ return(NULL); }
+ int32_t Type = U_OID_To_BT(Bd->Type);
+ if(Type < 0){ return(NULL); }
+ const U_SERIAL_DESC List[] = {
+ {&Version, 4, 1, U_LE},
+ {&Type, 4, 1, U_LE},
+ {Bd->Data, Bd->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_BRUSH_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_CUSTOMLINECAP PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Version EmfPlusGraphicsVersion object
+ \param Ld U_PSEUDO_OBJ containing one of the 2 types of Linecap data
+
+ EMF+ manual 2.2.1.2, Microsoft name: EmfPlusCustomLineCap Object
+*/
+U_PSEUDO_OBJ *U_PMF_CUSTOMLINECAP_set(uint32_t Version, const U_PSEUDO_OBJ *Ld){
+ if(!Ld){ return(NULL); }
+ int32_t Type = U_OID_To_CLCDT(Ld->Type);
+ if(Type<0){ return(NULL); }
+ const U_SERIAL_DESC List[] = {
+ {&Version, 4, 1, U_LE},
+ {&Type, 4, 1, U_LE},
+ {Ld->Data, Ld->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_CUSTOMLINECAP_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_FONT PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Version EmfPlusGraphicsVersion object
+ \param EmSize em size in units of SizeUnit
+ \param SizeUnit UnitType enumeration
+ \param FSFlags FontStyle flags
+ \param Length Number of Unicode Characters in FamilyName
+ \param Font Unicode (UTF-16LE) fontname
+
+ EMF+ manual 2.2.1.3, Microsoft name: EmfPlusFont Object
+*/
+U_PSEUDO_OBJ *U_PMF_FONT_set(uint32_t Version, U_FLOAT EmSize, uint32_t SizeUnit,
+ int32_t FSFlags, uint32_t Length, const uint16_t *Font){
+ uint32_t cbFont = 2 * wchar16len(Font); /* this need not be 2*Length parameter */
+ uint32_t pad = (0x3 & cbFont ? 2 : 0);
+ const U_SERIAL_DESC List[] = {
+ {&Version, 4, 1, U_LE},
+ {&EmSize, 4, 1, U_LE},
+ {&SizeUnit,4, 1, U_LE},
+ {&FSFlags, 4, 1, U_LE},
+ {NULL, 4, 1, U_LE}, /* NULL is for Reserved field */
+ {&Length, 4, 1, U_LE},
+ {Font, cbFont, 1, U_LE},
+ {NULL, pad, (pad ? 1 : 0), (pad ? U_XE : U_XX)}, /* Entire record must be a multiple of 4 */
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_FONT_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_IMAGE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Version EmfPlusGraphicsVersion object
+ \param Id U_PSEUDO_OBJ containing one of the 2 types of image data
+
+ EMF+ manual 2.2.1.4, Microsoft name: EmfPlusImage Object
+*/
+U_PSEUDO_OBJ *U_PMF_IMAGE_set(uint32_t Version, const U_PSEUDO_OBJ *Id){
+ if(!Id){ return(NULL); }
+ int32_t Type = U_OID_To_IDT(Id->Type);
+ if(Type<0){ return(NULL);}
+ const U_SERIAL_DESC List[] = {
+ {&Version, 4, 1, U_LE},
+ {&Type, 4, 1, U_LE},
+ {Id->Data, Id->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IMAGE_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_IMAGEATTRIBUTES PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Version EmfPlusGraphicsVersion object
+ \param WrapMode WrapMode object
+ \param ClampColor EmfPlusARGB object
+ \param ObjectClamp ObjectClamp Identifiers
+
+ EMF+ manual 2.2.1.5, Microsoft name: EmfPlusImageAttributes Object
+*/
+U_PSEUDO_OBJ *U_PMF_IMAGEATTRIBUTES_set(uint32_t Version, uint32_t WrapMode, uint32_t ClampColor, uint32_t ObjectClamp){
+ uint32_t Reserved=0;
+ const U_SERIAL_DESC List[] = {
+ {&Version, 4, 1, U_LE},
+ {&Reserved, 4, 1, U_LE},
+ {&WrapMode, 4, 1, U_LE},
+ {&ClampColor, 4, 1, U_LE},
+ {&ObjectClamp, 4, 1, U_LE},
+ {&Reserved, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IMAGEATTRIBUTES_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_PATH PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Version EmfPlusGraphicsVersion object
+ \param Points U_PSEUDO_OBJ containing array of points (of type PMFPointR, PMFPoint, or PMFPointF, determined by U_PPF_P and U_PPF_C bits in Flags)
+ \param Types U_PSEUDO_OBJ containing array of types (U_PMF_PATHPOINTTYPE or U_PMF_PATHPOINTTYPERLE, determined by U_PPF_R big in Flags)
+
+ EMF+ manual 2.2.1.6, Microsoft name: EmfPlusPath Object
+*/
+U_PSEUDO_OBJ *U_PMF_PATH_set(uint32_t Version, const U_PSEUDO_OBJ *Points, const U_PSEUDO_OBJ *Types){
+ int ctype, RelAbs, rtype;
+ int pad;
+ if(Points){
+ if( Points->Type == U_PMF_POINTR_OID){ RelAbs = 1; ctype = 0; }
+ else if(Points->Type == (U_PMF_POINT_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 1; }
+ else if(Points->Type == (U_PMF_POINTF_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 0; }
+ else { return(NULL); }
+ }
+ else { return(NULL); }
+ if(Types){
+ if( Types->Type == (U_PMF_PATHPOINTTYPERLE_OID | U_PMF_ARRAY_OID)){ rtype = 1; }
+ else if(Types->Type == (U_PMF_PATHPOINTTYPE_OID | U_PMF_ARRAY_OID)){ rtype = 0; }
+ else { return(NULL); }
+ }
+ else { return(NULL); }
+ uint16_t Flags = (rtype ? U_PPF_R : 0) | (ctype ? U_PPF_C : 0)| (RelAbs ? U_PPF_P : 0);
+ pad = (0x3 & (Points->Used + Types->Used));
+ if(pad){ pad = 4 - pad; }
+ const U_SERIAL_DESC List[] = {
+ {&Version, 4, 1, U_LE },
+ {Points->Data, 4, 1, U_XE }, /* Elements from Points */
+ {&Flags, 2, 1, U_LE },
+ {NULL, 2, 1, U_LE }, /* Reserved field */
+ {Points->Data + 4, Points->Used - 4, 1, U_XE }, /* omit Points Elements */
+ {Types->Data +4, Types->Used - 4, 1, U_XE }, /* omit Types Elements */
+ {NULL, pad, (pad ? 1 : 0), (pad ? U_XE : U_XX)}, /* if no padding is needed the Units will be zero and nothing will happen */
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PATH_OID, List);
+ return(po);
+}
+
+
+/**
+ \brief Create and set a U_PMF_PATH PseudoObject that uses U_PMF_POINTF coordinates
+ \return Pointer to PseudoObject, NULL on error
+ \param Version EmfPlusGraphicsVersion object
+ \param Path U_DPSEUDO_OBJ containing a path.
+
+ EMF+ manual 2.2.1.6, Microsoft name: EmfPlusPath Object
+*/
+U_PSEUDO_OBJ *U_PMF_PATH_set2(uint32_t Version, const U_DPSEUDO_OBJ *Path){
+ if(!Path || !Path->Elements){ return(NULL); }
+ uint16_t Flags = 0;
+ int pad = (0x3 & Path->Elements);
+ if(pad){ pad = 4 - pad; }
+ const U_SERIAL_DESC List[] = {
+ {&Version, 4, 1, U_LE },
+ {&Path->Elements, 4, 1, U_LE },
+ {&Flags, 2, 1, U_LE },
+ {NULL, 2, 1, U_LE }, /* Reserved field */
+ {Path->poPoints->Data, 4, 2*Path->Elements,U_XE }, /* raw OID, so no leading Elements to omit */
+ {Path->poTypes->Data, 1, Path->Elements, U_XE }, /* raw OID, so no leading Elements to omit */
+ {NULL, pad, (pad ? 1 : 0), (pad ? U_XE : U_XX)}, /* if no padding is needed the Units will be zero and nothing will happen */
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PATH_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_PATH PseudoObject that uses U_PMF_POINT (int 16) coordinates
+ \return Pointer to PseudoObject, NULL on error
+ \param Version EmfPlusGraphicsVersion object
+ \param Path U_DPSEUDO_OBJ containing a path.
+
+ EMF+ manual 2.2.1.6, Microsoft name: EmfPlusPath Object
+*/
+U_PSEUDO_OBJ *U_PMF_PATH_set3(uint32_t Version, const U_DPSEUDO_OBJ *Path){
+ if(!Path || !Path->Elements){return(NULL); }
+ uint16_t Flags = U_PPF_C;
+ int pad = (0x3 & Path->Elements);
+ if(pad){ pad = 4 - pad; }
+ U_PMF_POINT *Points16 = POINTF_To_POINT16_LE((U_PMF_POINTF *)Path->poPoints->Data, Path->Elements);
+ if(!Points16){ return(NULL); }
+ const U_SERIAL_DESC List[] = {
+ {&Version, 4, 1, U_LE },
+ {&Path->Elements, 4, 1, U_LE },
+ {&Flags, 2, 1, U_LE },
+ {NULL, 2, 1, U_LE }, /* Reserved field */
+ {Points16, 2, 2*Path->Elements,U_XE }, /* raw data, so no leading Elements to omit */
+ {Path->poTypes->Data, 1, Path->Elements, U_XE }, /* raw data, so no leading Elements to omit */
+ {NULL, pad, (pad ? 1 : 0), (pad ? U_XE : U_XX)}, /* if no padding is needed the Units will be zero and nothing will happen */
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PATH_OID, List);
+ free(Points16);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_PEN PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Version EmfPlusGraphicsVersion object
+ \param PenData U_PSEUDO_OBJ containing U_PMF_PENDATA object
+ \param Brush U_PSEUDO_OBJ containing U_PMF_BRUSH object
+
+ EMF+ manual 2.2.1.7, Microsoft name: EmfPlusPen Object
+*/
+U_PSEUDO_OBJ *U_PMF_PEN_set(uint32_t Version, const U_PSEUDO_OBJ *PenData, const U_PSEUDO_OBJ *Brush){
+ if(!PenData || (PenData->Type != U_PMF_PENDATA_OID)){ return(NULL); }
+ if(!Brush || (Brush->Type != U_PMF_BRUSH_OID) ){ return(NULL); }
+ const U_SERIAL_DESC List[] = {
+ {&Version, 4, 1, U_LE},
+ {NULL, 4, 1, U_LE},
+ {PenData->Data, PenData->Used, 1, U_XE},
+ {Brush->Data, Brush->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PEN_OID, List);
+ return(po);
+}
+
+
+/**
+ \brief Create and set a U_PMF_REGION PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Version EmfPlusGraphicsVersion object
+ \param Count Number of CHILD nodes. This is one less than the total number of U_PMF_REGIONNODE objects in Nodes.
+ \param Nodes U_PSEUDO_OBJ containing U_PMF_REGIONNODE object (Nodes defining region, may be a single element or a binary tree)
+
+ EMF+ manual 2.2.1.8, Microsoft name: EmfPlusRegion Object
+*/
+U_PSEUDO_OBJ *U_PMF_REGION_set(uint32_t Version, uint32_t Count, const U_PSEUDO_OBJ *Nodes){
+ if(!Nodes || Nodes->Type != U_PMF_REGIONNODE_OID)return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {&Version, 4, 1, U_LE},
+ {&Count, 4, 1, U_LE},
+ {Nodes->Data, Nodes->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_REGION_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_STRINGFORMAT PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Sfs pointer to U_PMF_STRINGFORMAT structure, with no variable part
+ \param Sfd (optional) U_PSEUDO_OBJ containing U_PMF_STRINGFORMATDATA object
+
+ EMF+ manual 2.2.1.9, Microsoft name: EmfPlusStringFormat Object
+*/
+U_PSEUDO_OBJ *U_PMF_STRINGFORMAT_set(U_PMF_STRINGFORMAT *Sfs, const U_PSEUDO_OBJ *Sfd){
+ if(!Sfs){ return(NULL); }
+ if(Sfd){
+ if((!Sfs->TabStopCount && !Sfs->RangeCount) || (Sfd->Type != U_PMF_STRINGFORMATDATA_OID))return(NULL);
+ }
+ else {
+ if(Sfs->TabStopCount || Sfs->RangeCount)return(NULL);
+ }
+ const U_SERIAL_DESC List[] = {
+ {&Sfs->Version, 4, 1, U_LE},
+ {&Sfs->Flags, 4, 1, U_LE},
+ {&Sfs->Language, 4, 1, U_LE},
+ {&Sfs->StringAlignment, 4, 1, U_LE},
+ {&Sfs->LineAlign, 4, 1, U_LE},
+ {&Sfs->DigitSubstitution, 4, 1, U_LE},
+ {&Sfs->DigitLanguage, 4, 1, U_LE},
+ {&Sfs->FirstTabOffset, 4, 1, U_LE},
+ {&Sfs->HotkeyPrefix, 4, 1, U_LE},
+ {&Sfs->LeadingMargin, 4, 1, U_LE},
+ {&Sfs->TrailingMargin, 4, 1, U_LE},
+ {&Sfs->Tracking, 4, 1, U_LE},
+ {&Sfs->Trimming, 4, 1, U_LE},
+ {&Sfs->TabStopCount, 4, 1, U_LE},
+ {&Sfs->RangeCount, 4, 1, U_LE},
+ {(Sfd ? Sfd->Data : NULL), (Sfd ? Sfd->Used : 0), 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_STRINGFORMAT_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a PMF_4NUM PseudoObject (used for BrushID's)
+ \return Pointer to PseudoObject, NULL on error
+ \param BrushID U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive)
+
+*/
+U_PSEUDO_OBJ *U_PMF_4NUM_set(uint32_t BrushID){
+ if(BrushID>63){ return(NULL); }
+ const U_SERIAL_DESC List[] = {
+ {&BrushID, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_4NUM_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_ARGB PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Alpha Alpha (0-255)
+ \param Red Red color (0-255)
+ \param Green Green color (0-255)
+ \param Blue Blue color (0-255)
+
+ EMF+ manual 2.2.2.1, Microsoft name: EmfPlusARGB Object
+*/
+U_PSEUDO_OBJ *U_PMF_ARGB_set(uint8_t Alpha, uint8_t Red, uint8_t Green, uint8_t Blue){
+ const U_SERIAL_DESC List[] = {
+ {&Blue, 1, 1, U_XE},
+ {&Green, 1, 1, U_XE},
+ {&Red, 1, 1, U_XE},
+ {&Alpha, 1, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_ARGB_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set an Array of U_PMF_ARGB valus in a PseudoObject
+ \return Pointer to PseudoObject containing the count, followed by the array of colors, NULL on error
+ \param Count Number of entries in Colors
+ \param Colors Array of ARGB values
+
+ EMF+ manual 2.2.2.1, Microsoft name: EmfPlusARGB Object
+*/
+U_PSEUDO_OBJ *U_PMF_ARGBN_set(uint32_t Count, U_PMF_ARGB *Colors){
+ const U_SERIAL_DESC List[] = {
+ {&Count, 4, 1, U_LE},
+ {Colors, 4, Count, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_ARGB_OID | U_PMF_ARRAY_OID, List);
+ return(po);
+}
+
+/**
+ \brief Set a U_PMF_ARGB object
+ \return Object
+ \param Alpha Alpha (0-255)
+ \param Red Red color (0-255)
+ \param Green Green color (0-255)
+ \param Blue Blue color (0-255)
+
+ EMF+ manual 2.2.2.1, Microsoft name: EmfPlusARGB Object
+*/
+U_PMF_ARGB U_PMF_ARGBOBJ_set(uint8_t Alpha, uint8_t Red, uint8_t Green, uint8_t Blue){
+ U_PMF_ARGB argb;
+ char *ptr = (char *) &argb;
+ U_PMF_MEMCPY_DSTSHIFT(&ptr, &Blue, 1);
+ U_PMF_MEMCPY_DSTSHIFT(&ptr, &Green, 1);
+ U_PMF_MEMCPY_DSTSHIFT(&ptr, &Red, 1);
+ U_PMF_MEMCPY_DSTSHIFT(&ptr, &Alpha, 1);
+ return(argb);
+}
+
+/**
+ \brief Create and set a U_PMF_BITMAP PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Bs pointer to U_PMF_BITMAP structure, with no variable part
+ \param Bm U_PSEUDO_OBJ containing an U_PMF_BITMAPDATA or U_PMF_COMPRESSEDIMAGE object
+
+ EMF+ manual 2.2.2.2, Microsoft name: EmfPlusBitmap Object
+*/
+U_PSEUDO_OBJ *U_PMF_BITMAP_set(const U_PMF_BITMAP *Bs, const U_PSEUDO_OBJ *Bm){
+ if(!Bs)return(NULL);
+ if(Bm->Type != U_PMF_BITMAPDATA_OID &&
+ Bm->Type != U_PMF_COMPRESSEDIMAGE_OID )return(NULL);
+ uint32_t Pad = UP4(Bm->Used) - Bm->Used; /* undocumented padding, must be present for at least PNG */
+ const U_SERIAL_DESC List[] = {
+ {Bs, 4, 5, U_LE},
+ {Bm->Data, Bm->Used, 1, U_XE},
+ {NULL, (Pad ? Pad : 0), (Pad ? 1 : 0), U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_BITMAP_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_BITMAPDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Ps (optional) U_PSEUDO_OBJ containing a U_PMF_PALETTE structure
+ \param cbBm Bytes in Bm
+ \param Bm An array of bytes, meaning depends on fields in U_PMF_BITMAP object and the PixelFormat enumeration.
+
+ EMF+ manual 2.2.2.3, Microsoft name: EmfPlusBitmapData Object
+*/
+U_PSEUDO_OBJ *U_PMF_BITMAPDATA_set( const U_PSEUDO_OBJ *Ps, int cbBm, const char *Bm){
+ if(Ps && (Ps->Type != U_PMF_PALETTE_OID))return(NULL);
+ if(!Bm && cbBm)return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {(Ps ? Ps->Data : NULL), (Ps ? Ps->Used : 0), (Ps ? 1 : 0), U_LE},
+ {Bm, cbBm, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_BITMAPDATA_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_BLENDCOLORS PseudoObject
+ \return Pointer to PseudoObject, NULL on Positions and Colors
+ \param Elements number of elements in Positions, must agree with the number of Colors.
+ \param Positions positions along gradient line. The first position MUST be 0.0 and the last MUST be 1.0.
+ \param Colors U_PSEUDO_OBJ containing an array of U_PMF_ARGB objects: object colors at positions on gradient line
+
+ EMF+ manual 2.2.2.4, Microsoft name: EmfPlusBlendColors Object
+*/
+U_PSEUDO_OBJ *U_PMF_BLENDCOLORS_set(uint32_t Elements, const U_FLOAT *Positions, const U_PSEUDO_OBJ *Colors){
+ if(!Colors || !Positions || Colors->Type != (U_PMF_ARGB_OID | U_PMF_ARRAY_OID)){ return(NULL); }
+ uint32_t CElements = (Colors->Used - 4)/4;
+ if(CElements != Elements){ return(NULL); }
+ const U_SERIAL_DESC List[] = {
+ {&CElements, 4, 1, U_LE},
+ {Positions, 4, CElements, U_LE},
+ {Colors->Data + 4, Colors->Used - 4, 1, U_XE}, /* omit Elements part of this PseudoObject */
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_BLENDCOLORS_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_BLENDCOLORS PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Elements members in osition, inluding Start and End (0.0 - 1.0)
+ \param StartColor Start Color (U_PMF_ARGB)
+ \param EndColor End Color (U_PMF_ARGB)
+
+ EMF+ manual 2.2.2.5, Microsoft name: EmfPlusBlendFactors Object
+
+
+ Positions always start at 0.0 and always end at 1.0. It is not well documented but other
+ start and end values generally do not work.
+*/
+U_PSEUDO_OBJ *U_PMF_BLENDCOLORS_linear_set(uint32_t Elements, U_PMF_ARGB StartColor, U_PMF_ARGB EndColor){
+ double dP,dR,dG,dB,dA,P,R,G,B,A;
+ U_FLOAT StartPos = 0.0;
+ U_FLOAT EndPos = 1.0;
+ U_FLOAT *Positions;
+ U_FLOAT *pP;
+ U_PMF_ARGB *Colors;
+ U_PMF_ARGB *pC;
+ unsigned int i;
+ if(Elements <= 2 ){ return(NULL); }
+ pP = Positions = (U_FLOAT *)malloc(Elements *sizeof(U_FLOAT));
+ if(!Positions){ return(NULL); }
+ pC = Colors = (U_PMF_ARGB *)malloc(Elements *sizeof(U_PMF_ARGB));
+ if(!Colors){
+ free(Positions);
+ return(NULL);
+ }
+ dP = (EndPos - StartPos )/(float)(Elements - 1);
+ dB = ((double)EndColor.Blue - (double)StartColor.Blue )/(double)(Elements - 1);
+ dG = ((double)EndColor.Green - (double)StartColor.Green)/(double)(Elements - 1);
+ dR = ((double)EndColor.Red - (double)StartColor.Red )/(double)(Elements - 1);
+ dA = ((double)EndColor.Alpha - (double)StartColor.Alpha)/(double)(Elements - 1);
+ P = StartPos;
+ B = StartColor.Blue;
+ G = StartColor.Green;
+ R = StartColor.Red;
+ A = StartColor.Alpha;
+ for(i=0;i<Elements;i++,pC++,pP++){ /* hopefully the rounding errors are not a problem, used doubles to minimize that */
+ *pP = P;
+ P += dP;
+ *pC = (U_PMF_ARGB){B,G,R,A};
+ B += dB;
+ G += dG;
+ R += dR;
+ A += dA;
+ }
+ U_PSEUDO_OBJ *poColors = U_PMF_ARGBN_set(Elements, Colors);
+ U_PSEUDO_OBJ *po = U_PMF_BLENDCOLORS_set(Elements, Positions, poColors);
+ U_PO_free(&poColors);
+ free(Positions);
+ free(Colors);
+ return(po);
+}
+
+
+/**
+ \brief Create and set a U_PMF_BLENDFACTORS PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Elements members in each array
+ \param Positions positions along gradient line. The first position MUST be 0.0 and the last MUST be 1.0.
+ \param Factors blending factors, 0.0->1.0 values, inclusive
+
+ EMF+ manual 2.2.2.5, Microsoft name: EmfPlusBlendFactors Object
+*/
+U_PSEUDO_OBJ *U_PMF_BLENDFACTORS_set(uint32_t Elements, const U_FLOAT *Positions, const U_FLOAT *Factors){
+ if(!Positions || !Factors)return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {&Elements, 4, 1, U_LE},
+ {Positions, 4, Elements, U_LE},
+ {Factors, 4, Elements, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_BLENDFACTORS_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_BLENDFACTORS PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Elements members in osition, inluding Start and End (0.0 - 1.0)
+ \param StartFactor Start Factor (0.0 - 1.0)
+ \param EndFactor End Factor (0.0 - 1.0)
+
+ EMF+ manual 2.2.2.5, Microsoft name: EmfPlusBlendFactors Object
+
+
+ Positions always start at 0.0 and always end at 1.0. It is not well documented but other
+ start and end values generally do not work.
+*/
+U_PSEUDO_OBJ *U_PMF_BLENDFACTORS_linear_set(uint32_t Elements, U_FLOAT StartFactor, U_FLOAT EndFactor){
+ double dP,dF,P,F;
+ U_FLOAT StartPos = 0.0;
+ U_FLOAT EndPos = 1.0;
+ U_FLOAT *Positions;
+ U_FLOAT *Factors;
+ U_FLOAT *pP;
+ U_FLOAT *pF;
+ unsigned int i;
+ if(Elements <= 2 ){ return(NULL); }
+ pP = Positions = (U_FLOAT *)malloc(Elements *sizeof(U_FLOAT));
+ if(!Positions){ return(NULL); }
+ pF = Factors = (U_FLOAT *)malloc(Elements *sizeof(U_FLOAT));
+ if(!Factors){
+ free(Positions);
+ return(NULL);
+ }
+ dP = (EndPos - StartPos )/(float)(Elements - 1);
+ dF = (EndFactor - StartFactor)/(float)(Elements - 1);
+ P = StartPos;
+ F = StartFactor;
+ for(i=0;i<Elements;i++){ /* hopefully the rounding errors are not a problem, used doubles to minimize that */
+ *pP++ = P; P += dP;
+ *pF++ = F; F += dF;
+ }
+ U_PSEUDO_OBJ *po = U_PMF_BLENDFACTORS_set(Elements, Positions, Factors);
+ free(Positions);
+ free(Factors);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_BOUNDARYPATHDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Path U_PSEUDO_OBJ containing U_PMF_PATH object
+
+ EMF+ manual 2.2.2.6, Microsoft name: EmfPlusBoundaryPathData Object
+*/
+U_PSEUDO_OBJ *U_PMF_BOUNDARYPATHDATA_set(const U_PSEUDO_OBJ *Path){
+ if(!Path || Path->Type != U_PMF_PATH_OID)return(NULL);
+ /* PO Used is size_t, might be 8 bytes, value in record must be 4 bytes */
+ uint32_t Used = Path->Used;
+ const U_SERIAL_DESC List[] = {
+ {&Used, 4, 1, U_LE},
+ {Path->Data, Path->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_BOUNDARYPATHDATA_OID, List);
+ return(po);
+}
+
+
+/**
+ \brief Create and set a U_PMF_BOUNDARYPOINTDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Elements members in each array
+ \param Points array of U_PMF_POINTF
+
+ EMF+ manual 2.2.2.7, Microsoft name: EmfPlusBoundaryPointData Object
+*/
+U_PSEUDO_OBJ *U_PMF_BOUNDARYPOINTDATA_set(uint32_t Elements, const U_PMF_POINTF *Points){
+ if(!Points)return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {&Elements, 4, 1, U_LE},
+ {Points, 4, 2*Elements,U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_BOUNDARYPOINTDATA_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_CHARACTERRANGE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param First First position in range
+ \param Length Range length
+
+ EMF+ manual 2.2.2.8, Microsoft name: EmfPlusCharacterRange Object
+*/
+U_PSEUDO_OBJ *U_PMF_CHARACTERRANGE_set(int32_t First, int32_t Length){
+ const U_SERIAL_DESC List[] = {
+ {&First, 4, 1, U_LE},
+ {&Length, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_CHARACTERRANGE_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_COMPOUNDLINEDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Elements Members in Widths
+ \param Widths Array of U_FLOAT Line or gap widths (0.0 <-> 1.0, fraction of total line width )
+
+ EMF+ manual 2.2.2.9, Microsoft name: EmfPlusCompoundLineData Object
+*/
+U_PSEUDO_OBJ *U_PMF_COMPOUNDLINEDATA_set(int32_t Elements, const char *Widths){
+ if(!Widths)return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {&Elements ,4, 1, U_LE},
+ {Widths, 4, Elements,U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_COMPOUNDLINEDATA_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_COMPRESSEDIMAGE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param cbImage Bytes in Image
+ \param Image Stored image in one of the supported formats (GIF, PNG, etc.).
+
+ EMF+ manual 2.2.2.10, Microsoft name: EmfPlusCompressedImage Object
+*/
+U_PSEUDO_OBJ *U_PMF_COMPRESSEDIMAGE_set(int32_t cbImage, const char *Image){
+ if(!cbImage || !Image)return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {Image, cbImage, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_COMPRESSEDIMAGE_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_CUSTOMENDCAPDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Clc U_PSEUDO_OBJ containing a U_PMF_CUSTOMLINECAP object
+
+ EMF+ manual 2.2.2.11, Microsoft name: EmfPlusCustomEndCapData Object
+*/
+U_PSEUDO_OBJ *U_PMF_CUSTOMENDCAPDATA_set(const U_PSEUDO_OBJ *Clc){
+ if(!Clc || Clc->Type != U_PMF_CUSTOMLINECAP_OID)return(NULL);
+ /* PO Used is size_t, might be 8 bytes, value in record must be 4 bytes */
+ uint32_t Used = Clc->Used;
+ const U_SERIAL_DESC List[] = {
+ {&Used, 4, 1, U_LE},
+ {Clc->Data, Clc->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_CUSTOMENDCAPDATA_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_CUSTOMLINECAPARROWDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Width Arrow cap width (is multiplied by line width before draw)
+ \param Height Arrow cap length (is multiplied by line width before draw)
+ \param MiddleInset Pixels between outer edge and filled region
+ \param FillState If set, fill, otherwise, only border
+ \param StartCap LineCap enumeration (type of cap)
+ \param EndCap LineCap enumeration
+ \param Join LineJoin enumeration
+ \param MiterLimit Maximum (miter length / line width)
+ \param WidthScale Scale for U_PMF_CUSTOMLINECAP object
+
+ EMF+ manual 2.2.2.12, Microsoft name: EmfPlusCustomLineCapArrowData Object
+*/
+U_PSEUDO_OBJ *U_PMF_CUSTOMLINECAPARROWDATA_set(U_FLOAT Width, U_FLOAT Height,
+ U_FLOAT MiddleInset, uint32_t FillState, uint32_t StartCap, uint32_t EndCap, uint32_t Join,
+ U_FLOAT MiterLimit, U_FLOAT WidthScale
+ ){
+ const U_SERIAL_DESC List[] = {
+ {&Width, 4, 1, U_LE},
+ {&Height ,4, 1, U_LE},
+ {&MiddleInset, 4, 1, U_LE},
+ {&FillState, 4, 1, U_LE},
+ {&StartCap, 4, 1, U_LE},
+ {&EndCap, 4, 1, U_LE},
+ {&Join, 4, 1, U_LE},
+ {&MiterLimit, 4, 1, U_LE},
+ {&WidthScale, 4, 1, U_LE},
+ {NULL, 8, 2, U_LE}, /* FillHotSpots and LineHotSpots */
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_CUSTOMLINECAPARROWDATA_OID, List);
+ return(po);
+}
+
+
+/**
+ \brief Create and set a U_PMF_CUSTOMLINECAPDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Flags CustomLineCapData flags
+ \param Cap LineCap enumeration (type of cap)
+ \param Inset Distance line cap start -> line end
+ \param StartCap LineCap enumeration
+ \param EndCap LineCap enumeration
+ \param Join LineJoin enumeration
+ \param MiterLimit Maximum (miter length / line width)
+ \param WidthScale Scale for U_PMF_CUSTOMLINECAP object
+ \param Clcod U_PSEUDO_OBJ containing a U_PMF_CUSTOMLINECAPOPTIONALDATA object
+
+ EMF+ manual 2.2.2.13, Microsoft name: EmfPlusCustomLineCapData Object
+*/
+U_PSEUDO_OBJ *U_PMF_CUSTOMLINECAPDATA_set(uint32_t Flags, uint32_t Cap,
+ U_FLOAT Inset, uint32_t StartCap, uint32_t EndCap,
+ uint32_t Join, U_FLOAT MiterLimit, U_FLOAT WidthScale,
+ const U_PSEUDO_OBJ *Clcod
+ ){
+ if(!Clcod || Clcod->Type != U_PMF_CUSTOMLINECAPOPTIONALDATA_OID)return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {&Flags, 4, 1, U_LE},
+ {&Cap, 4, 1, U_LE},
+ {&Inset, 4, 1, U_LE},
+ {&StartCap, 4, 1, U_LE},
+ {&EndCap, 4, 1, U_LE},
+ {&Join, 4, 1, U_LE},
+ {&MiterLimit, 4, 1, U_LE},
+ {&WidthScale, 4, 1, U_LE},
+ {NULL, 8, 2, U_LE}, /* FillHotSpots and LineHotSpots */
+ {Clcod->Data, Clcod->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_CUSTOMLINECAPDATA_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_CUSTOMLINECAPOPTIONALDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Fill U_PSEUDO_OBJ containing a U_PMF_FILLPATHOBJ object (optional)
+ \param Line U_PSEUDO_OBJ containing a U_PMF_LINEPATH object (optional)
+
+ EMF+ manual 2.2.2.14, Microsoft name: EmfPlusCustomLineCapOptionalData Object
+*/
+U_PSEUDO_OBJ *U_PMF_CUSTOMLINECAPOPTIONALDATA_set(const U_PSEUDO_OBJ *Fill, const U_PSEUDO_OBJ *Line){
+ if(Fill && (Fill->Type != U_PMF_FILLPATHOBJ_OID))return(NULL);
+ if(Line && (Line->Type != U_PMF_LINEPATH_OID))return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {(Fill ? Fill->Data : NULL), (Fill ? Fill->Used : 0), 1, U_XE},
+ {(Line ? Line->Data : NULL), (Line ? Line->Used : 0), 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_CUSTOMLINECAPOPTIONALDATA_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_CUSTOMSTARTCAPDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Clc U_PSEUDO_OBJ containing a U_PMF_CUSTOMLINECAPDATA object
+
+ EMF+ manual 2.2.2.15, Microsoft name: EmfPlusCustomStartCapData Object
+*/
+U_PSEUDO_OBJ *U_PMF_CUSTOMSTARTCAPDATA_set(const U_PSEUDO_OBJ *Clc){
+ if(!Clc || Clc->Type != U_PMF_CUSTOMLINECAP_OID)return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {Clc->Data, Clc->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_CUSTOMSTARTCAPDATA_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_DASHEDLINEDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Elements Members in Lengths
+ \param Lengths Array of U_FLOAT holding lengths of dashes and spaces.
+
+ EMF+ manual 2.2.2.16, Microsoft name: EmfPlusDashedLineData Object
+*/
+U_PSEUDO_OBJ *U_PMF_DASHEDLINEDATA_set(int32_t Elements, const U_FLOAT *Lengths){
+ if(!Lengths)return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {&Elements, 4, 1, U_LE},
+ {Lengths, 4, Elements, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_DASHEDLINEDATA_OID, List);
+ return(po);
+}
+
+/**
+ \brief Utility function to create and set a U_PMF_DASHEDLINEDATA PseudoObject from one of a predefined set of patterns
+ \return Pointer to PseudoObject, NULL on error
+ \param Unit Length of the repeat unit
+ \param StdPat Members in Lengths
+
+ EMF+ manual 2.2.2.16, Microsoft name: EmfPlusDashedLineData Object
+*/
+U_PSEUDO_OBJ *U_PMF_DASHEDLINEDATA_set2(U_FLOAT Unit, int StdPat){
+ uint32_t Elements;
+ uint8_t *p;
+ U_FLOAT SubUnit;
+ U_FLOAT Lengths[8]; /* This is the most dash/spaces that will be needed*/
+ int i;
+ /* Dot = 1, Dash = 2; Long = 3, 0 = terminate pattern */
+ uint8_t SB[U_DD_Types][5] =
+ {
+ {0,0,0,0,0}, // Solid
+ {2,0,0,0,0}, // Dash
+ {2,2,0,0,0}, // DashDash
+ {2,2,2,0,0}, // DashDashDash
+ {2,2,2,2,0}, // DashDashDashDash
+ {1,0,0,0,0}, // Dot
+ {1,1,0,0,0}, // DotDot
+ {1,1,1,0,0}, // DotDotDot
+ {1,1,1,1,0}, // DotDotDotDot
+ {2,1,0,0,0}, // DashDot
+ {2,2,1,0,0}, // DashDashDot
+ {2,2,1,1,0}, // DashDashDotDot
+ {2,2,2,1,0}, // DashDashDashDot
+ {2,1,1,0,0}, // DashDotDot
+ {2,1,1,1,0}, // DashDotDotDot
+ {2,1,2,1,0}, // DashDotDashDot
+ {3,0,0,0,0}, // Long
+ {3,3,0,0,0}, // LongLong
+ {3,3,3,0,0}, // LongLongLong
+ {3,3,3,3,0}, // LongLongLongLong
+ {3,1,0,0,0}, // LongDot
+ {3,3,1,0,0}, // LongLongDot
+ {3,3,1,1,0}, // LongLongDotDot
+ {3,3,3,1,0}, // LongLongLongDot
+ {3,1,1,0,0}, // LongDotDot
+ {3,1,1,1,0}, // LongDotDotDot
+ {3,1,3,1,0} // LongDotLongDot
+ };
+ if(Unit <= 0 ){ return(NULL); }
+ if((StdPat <= 0) || (StdPat > U_DD_LongDotLongDot)){ return(NULL); }
+ p = &(SB[StdPat][0]);
+ for(Elements = 0; *p; p++, Elements++){}
+ SubUnit = Unit/((U_FLOAT) Elements);
+ Elements *= 2;
+ p = &(SB[StdPat][0]);
+ for(i=0; *p; p++){
+ switch(*p){
+ case 0: break;
+ case 1: /* dot */
+ Lengths[i++] = SubUnit * 0.125;
+ Lengths[i++] = SubUnit * 0.875;
+ break;
+ case 2: /* dash */
+ Lengths[i++] = SubUnit * 0.5;
+ Lengths[i++] = SubUnit * 0.5;
+ break;
+ case 3: /* long */
+ Lengths[i++] = SubUnit * 0.75;
+ Lengths[i++] = SubUnit * 0.25;
+ break;
+ }
+ }
+
+ U_PSEUDO_OBJ *po = U_PMF_DASHEDLINEDATA_set(Elements, Lengths);
+ return(po);
+}
+
+/**
+ \brief Utility function to create and set a U_PMF_DASHEDLINEDATA PseudoObject from the bits that are set in a uint32_t
+ \return Pointer to PseudoObject, NULL on error
+ \param Unit Length of the repeat unit
+ \param BitPat uint32_t holding the bit pattern, the lowest order bit MUST be set and the highest order MUST be clear.
+
+ Make a line with a dot/dash pattern defined by the bits in the BitPat value. If a bit is set it is drawn,
+ if clear it is not. Every bit drawn has length Unit/32, and consecutive drawn bits are merged together.
+ The lowest order bit is the first bit that may be drawn, the highest the last.
+
+ Example: if the integer has value 0x13 the pattern produced will be:
+ 0 -> 2*unit/32 drawn
+ 2*unit/32 -> 5*unit/32 not drawn
+ 5*unit/32 -> 6*unit/32 drawn
+ 6*unit/32 -> unit not drawn
+
+ EMF+ manual 2.2.2.16, Microsoft name: EmfPlusDashedLineData Object
+*/
+U_PSEUDO_OBJ *U_PMF_DASHEDLINEDATA_set3(U_FLOAT Unit, uint32_t BitPat){
+ uint32_t Elements=0;
+ U_FLOAT SubUnit = Unit/32.0;
+ U_FLOAT Lengths[32]; /* This is the most dash/spaces that will be needed*/
+ if(!(0x00000001 & BitPat))return(NULL); /* Pattern must start with a drawn segment, this bit must be set */
+ if( 0x80000000 & BitPat )return(NULL); /* Pattern must end with an undrawn segment, this bit must be clear */
+ int i=0;
+ int k;
+ int lastType=1;
+ int newType=0;
+ uint32_t j=1;
+ Lengths[0]=0;
+ for(k=0; k<32; k++, j=j<<1){
+ if(j & BitPat){
+ if(!lastType){
+ newType=1;
+ }
+ }
+ else {
+ if(lastType){
+ newType=1;
+ }
+ }
+ if(newType){
+ i++;
+ Lengths[i]=0;
+ Elements++;
+ lastType = !lastType;
+ newType = 0;
+ }
+ Lengths[i] += SubUnit;
+ }
+ Elements = i+1;
+
+ U_PSEUDO_OBJ *po = U_PMF_DASHEDLINEDATA_set(Elements, Lengths);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_FILLPATHOBJ PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Path U_PSEUDO_OBJ containing a U_PMF_PATH object
+
+ EMF+ manual 2.2.2.17, Microsoft name: EmfPlusFillPath Object
+*/
+U_PSEUDO_OBJ *U_PMF_FILLPATHOBJ_set(const U_PSEUDO_OBJ *Path){
+ if(!Path || (Path->Type != U_PMF_PATH_OID))return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {Path->Data, Path->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_FILLPATHOBJ_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_FOCUSSCALEDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param ScaleX value 0.0 <-> 1.0
+ \param ScaleY value 0.0 <-> 1.0
+
+ EMF+ manual 2.2.2.18, Microsoft name: EmfPlusFocusScaleData Object
+*/
+U_PSEUDO_OBJ *U_PMF_FOCUSSCALEDATA_set(U_FLOAT ScaleX, U_FLOAT ScaleY){
+ uint32_t tmp = 2;
+ const U_SERIAL_DESC List[] = {
+ {&tmp, 4, 1, U_LE},
+ {&ScaleX, 4, 1, U_LE},
+ {&ScaleY, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_FOCUSSCALEDATA_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_GRAPHICSVERSION object (Signature always set to 0xDBC01)
+ \return Pointer to PseudoObject, NULL on error
+ \param GrfVersion GraphicsVersion enumeration
+
+ EMF+ manual 2.2.2.19, Microsoft name: EmfPlusGraphicsVersion Object
+*/
+U_PSEUDO_OBJ *U_PMF_GRAPHICSVERSION_set(int GrfVersion){
+ uint32_t tmp;
+ tmp = U_GFVR_PMF << 12; /* signature, can only have this value */
+ tmp |= (GrfVersion & U_GFVR_MASKLO);
+ const U_SERIAL_DESC List[] = {
+ {&tmp, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_GRAPHICSVERSION_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_GRAPHICSVERSION object Structure (Signature always set to 0xDBC01)
+ \return U_PMF_GRAPHICSVERSION
+ \param GrfVersion GraphicsVersion enumeration
+
+ EMF+ manual 2.2.2.19, Microsoft name: EmfPlusGraphicsVersion Object
+*/
+U_PMF_GRAPHICSVERSION U_PMF_GRAPHICSVERSIONOBJ_set(int GrfVersion){
+ uint32_t tmp;
+ tmp = U_GFVR_PMF << 12; /* signature, can only have this value */
+ tmp |= (GrfVersion & U_GFVR_MASKLO);
+ return(tmp);
+}
+
+
+/**
+ \brief Create and set a U_PMF_HATCHBRUSHDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Style HatchStyle enumeration
+ \param Fg U_PSEUDO_OBJ containing a U_ARGB object, Foreground hatch pattern line color
+ \param Bg U_PSEUDO_OBJ containing a U_ARGB object, Background hatch pattern line color
+
+ EMF+ manual 2.2.2.20, Microsoft name: EmfPlusHatchBrushData Object
+*/
+U_PSEUDO_OBJ *U_PMF_HATCHBRUSHDATA_set(uint32_t Style, const U_PSEUDO_OBJ *Fg, const U_PSEUDO_OBJ *Bg){
+ if(!Fg ||(Fg->Type != U_PMF_ARGB_OID))return(NULL);
+ if(!Bg ||(Bg->Type != U_PMF_ARGB_OID))return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {&Style, 4, 1, U_LE},
+ {Fg->Data, Fg->Used, 1, U_XE},
+ {Bg->Data, Bg->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_HATCHBRUSHDATA_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_INTEGER7 PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Value 7 bit signed integer (stored in an integer, range 63 <-> -64, inclusive)
+
+ EMF+ manual 2.2.2.21, Microsoft name: EmfPlusInteger7 Object
+*/
+U_PSEUDO_OBJ *U_PMF_INTEGER7_set(int Value){
+ uint8_t utmp;
+ if(Value < -64 || Value > 63)return(NULL);
+ utmp = U_MASK_INT7 & *(unsigned int *)&Value;
+ U_PSEUDO_OBJ *po = U_PO_create((char *)&utmp, 1, 1, U_PMF_INTEGER7_OID); /* simple method is OK, no possibility of Endian issues */
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_INTEGER15 PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Value 15 bit signed integer (stored in an integer, range 32677 <-> -32678, inclusive)
+
+ EMF+ manual 2.2.2.22, Microsoft name: EmfPlusInteger15 Object
+*/
+U_PSEUDO_OBJ *U_PMF_INTEGER15_set(int Value){
+ uint16_t utmp;
+ if(Value < -32678 || Value > 32677)return(NULL);
+ utmp = U_TEST_INT15 | (U_MASK_INT15 & *(unsigned int *)&Value);
+ const U_SERIAL_DESC List[] = {
+ {&utmp, 2, 1, U_BE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_INTEGER15_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_LANGUAGEIDENTIFIER value in 4 byte unsigned int, in NATIVE byte order
+ \return LID value in least significant two bytes and 0 in most significant two bytes.
+ \param SubLId Example: code for USA
+ \param PriLId Example: code for English
+
+ EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier Object
+*/
+U_PMF_LANGUAGEIDENTIFIER U_PMF_LANGUAGEIDENTIFIEROBJ_set(int SubLId, int PriLId){
+ U_PMF_LANGUAGEIDENTIFIER utmp32;
+ utmp32 = ((SubLId & U_FF_MASK_SUBLID) << U_FF_SHFT_SUBLID) | ((PriLId & U_FF_MASK_PRILID) << U_FF_SHFT_PRILID);
+ return(utmp32);
+}
+
+/**
+ \brief Create and set a U_PMF_LANGUAGEIDENTIFIER PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param LId Language Identifier as produced by U_PMF_LANGUAGEIDENTIFIEROBJ_set().
+
+ EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier Object
+*/
+U_PSEUDO_OBJ *U_PMF_LANGUAGEIDENTIFIER_set(U_PMF_LANGUAGEIDENTIFIER LId){
+ uint16_t utmp16;
+ utmp16 = (LId & U_FF_MASK_LID) << U_FF_SHFT_LID;
+ const U_SERIAL_DESC List[] = {
+ {&utmp16, 2, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_LANGUAGEIDENTIFIER_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_LINEARGRADIENTBRUSHDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Lgbd U_PMF_LINEARGRADIENTBRUSHDATA object (constant part)
+ \param Lgbod U_PSEUDO_OBJ containing a U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA object (variable part of a U_PMF_LINEARGRADIENTBRUSHDATA object)
+
+
+ EMF+ manual 2.2.2.24, Microsoft name: EmfPlusLinearGradientBrushData Object
+*/
+U_PSEUDO_OBJ *U_PMF_LINEARGRADIENTBRUSHDATA_set(const U_PMF_LINEARGRADIENTBRUSHDATA *Lgbd, const U_PSEUDO_OBJ *Lgbod){
+ if(!Lgbd || !Lgbod || (Lgbod->Type != U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_OID))return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {Lgbd, 4, 6, U_LE},
+ {&(Lgbd->StartColor), 4, 2, U_XE},
+ {&(Lgbd->StartColor), 4, 2, U_XE}, /* repeat the start/end colors. Supposedly reserved. */
+// {NULL, 4, 2, U_LE}, /* zero fill the two Reserved fields, no matter what is passed in */
+ {(Lgbod->Used ? Lgbod->Data : NULL), Lgbod->Used, 1, U_XE}, /* optional Data can exist and Used can be zero, SERIAL_set would throw an error on that */
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_LINEARGRADIENTBRUSHDATA_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Flags Bits are set that indicate which of the following were included. The caller must clear before passing it in.
+ \param Tm (optional) U_PSEUDO_OBJ containing a U_PMF_TRANSFORMMATRIX object
+ \param Bc (optional) U_PSEUDO_OBJ containing a U_PMF_BLENDCOLORS object or NULL
+ \param BfH (optional) U_PSEUDO_OBJ containing a U_PMF_BLENDFACTORS (H) object or NULL
+ \param BfV (optional) U_PSEUDO_OBJ containing a U_PMF_BLENDFACTORS (V) object or NULL (WARNING, GDI+ defines this field but does not render it. DO NOT USE.)
+
+
+ EMF+ manual 2.2.2.25, Microsoft name: EmfPlusLinearGradientBrushOptionalData Object
+
+
+ The rectangular gradients repeat in a tiled pattern. Tm can rotate and offset the gradient within each tile.
+ The gradient wraps when it is offset.
+
+*/
+U_PSEUDO_OBJ *U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_set(uint32_t *Flags, const U_PSEUDO_OBJ *Tm,
+ const U_PSEUDO_OBJ *Bc, const U_PSEUDO_OBJ *BfH, const U_PSEUDO_OBJ *BfV){
+ if(!Flags )return(NULL);
+ if(Tm && (Tm->Type != U_PMF_TRANSFORMMATRIX_OID))return(NULL);
+ if(Bc && (Bc->Type != U_PMF_BLENDCOLORS_OID) )return(NULL);
+ if(BfH && (BfH->Type != U_PMF_BLENDFACTORS_OID) )return(NULL);
+ if(BfV && (BfV->Type != U_PMF_BLENDFACTORS_OID) )return(NULL);
+ if(Bc && (BfH || BfV) )return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {(Tm ? Tm->Data : NULL), (Tm ? Tm->Used : 0), 1, U_XE},
+ {(Bc ? Bc->Data : NULL), (Bc ? Bc->Used : 0), 1, U_XE},
+ {(BfH ? BfH->Data : NULL), (BfH ? BfH->Used : 0), 1, U_XE},
+ {(BfV ? BfV->Data : NULL), (BfV ? BfV->Used : 0), 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_OID, List);
+ if(Tm ){ *Flags |= U_BD_Transform; }
+ if(Bc ){ *Flags |= U_BD_PresetColors; }
+ if(BfH){ *Flags |= U_BD_BlendFactorsH; }
+ if(BfV){ *Flags |= U_BD_BlendFactorsV; }
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_LINEPATH PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Path U_PSEUDO_OBJ containing a U_PMF_PATH object
+
+
+ EMF+ manual 2.2.2.26, Microsoft name: EmfPlusLinePath Object
+*/
+U_PSEUDO_OBJ *U_PMF_LINEPATH_set(const U_PSEUDO_OBJ *Path){
+ if(!Path || (Path->Type != U_PMF_PATH_OID))return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {&Path->Data, Path->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_LINEPATH_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_METAFILE object (NOT SUPPORTED!)
+ \return Null
+
+
+ EMF+ manual 2.2.2.27, Microsoft name: EmfPlusMetafile Object
+*/
+U_PSEUDO_OBJ *U_PMF_METAFILE_set(void){
+ return(NULL);
+}
+
+/**
+ \brief Create and set a U_PMF_PALETTE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Flags PaletteStyle flags
+ \param Elements Members in Lengths
+ \param Pd Array of U_PMF_ARGB holding colors of palettes. (Palette Data)
+
+ EMF+ manual 2.2.2.28, Microsoft name: EmfPlusPalette Object
+*/
+U_PSEUDO_OBJ *U_PMF_PALETTE_set(uint32_t Flags, uint32_t Elements, const U_PMF_ARGB *Pd){
+ if(!Pd)return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {&Flags, 4, 1, U_LE},
+ {&Elements, 4, 1, U_LE},
+ {Pd, 4, Elements, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PALETTE_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_PATHGRADIENTBRUSHDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Flags PaletteStyle flags
+ \param WrapMode WrapMode enumeration
+ \param CenterColor U_PMF_ARGB Center color
+ \param Center Center coordinates
+ \param Gradient U_PSEUDO_OBJ containing an Array of U_PMF_ARGB holding colors of Gradient
+ \param Boundary U_PSEUDO_OBJ containing a U_PMF_BOUNDARYPATHDATA or U_PMF_BOUNDARYPOINTDATA object. (Boundary Data)
+ \param Data variable part of U_PMF_LINEARGRADIENTBRUSHDATA, exact composition depends on Flags
+
+ EMF+ manual 2.2.2.29, Microsoft name: EmfPlusPathGradientBrushData Object
+*/
+U_PSEUDO_OBJ *U_PMF_PATHGRADIENTBRUSHDATA_set(uint32_t Flags, int32_t WrapMode, U_PMF_ARGB CenterColor,
+ U_PMF_POINTF Center,
+ const U_PSEUDO_OBJ *Gradient, const U_PSEUDO_OBJ *Boundary, const U_PSEUDO_OBJ *Data){
+ if( (Flags & U_BD_Path) && (!Boundary || (Boundary->Type != U_PMF_BOUNDARYPATHDATA_OID)))return(NULL);
+ if(!(Flags & U_BD_Path) && (!Boundary || (Boundary->Type != U_PMF_BOUNDARYPOINTDATA_OID)))return(NULL);
+ if(!Gradient || (Gradient->Type != (U_PMF_ARGB_OID | U_PMF_ARRAY_OID)))return(NULL);
+ if(!(Flags & U_BD_Transform) &&
+ !(Flags & U_BD_PresetColors) &&
+ !(Flags & U_BD_BlendFactorsH) &&
+ !(Flags & U_BD_FocusScales) &&
+ (!Data || (Data->Type != U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_OID)))return(NULL);
+
+ const U_SERIAL_DESC List[] = {
+ {&Flags, 4, 1, U_LE},
+ {&WrapMode, 4, 1, U_LE},
+ {&CenterColor, 4, 1, U_XE},
+ {&Center.X, 4, 2, U_LE},
+ {Gradient->Data, Gradient->Used, 1, U_XE}, /* includes Elements */
+ {Boundary->Data, Boundary->Used, 1, U_XE},
+ {(Data ? Data->Data : NULL), (Data ? Data->Used : 0), 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PATHGRADIENTBRUSHDATA_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_PATHGRADIENTBRUSHOPTIONALDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Flags PaletteStyle flags
+ \param Tm U_PSEUDO_OBJ containing a U_PMF_TRANSFORMMATRIX. (Transformation matrix)
+ \param Pd U_PSEUDO_OBJ containing a U_PMF_BLENDCOLORS or U_PMF_BLENDFACTORS object. (Pattern Data)
+ \param Fsd U_PSEUDO_OBJ containing a U_PMF_FOCUSSSCALEDATA object. (Focus Scale Data)
+
+ EMF+ manual 2.2.2.30, Microsoft name: EmfPlusPathGradientBrushOptionalData Object
+*/
+U_PSEUDO_OBJ *U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_set(uint32_t Flags,
+ const U_PSEUDO_OBJ *Tm, const U_PSEUDO_OBJ *Pd, const U_PSEUDO_OBJ *Fsd){
+ if(Tm && (Tm->Type != U_PMF_TRANSFORMMATRIX_OID))return(NULL);
+ if(Pd && !(Flags & (U_BD_PresetColors | U_BD_BlendFactorsH)))return(NULL);
+ if( (Flags & U_BD_PresetColors) && ((Flags & U_BD_BlendFactorsH) || !Pd || (Pd->Type != U_PMF_BLENDCOLORS_OID) ))return(NULL);
+ if( (Flags & U_BD_BlendFactorsH) && ((Flags & U_BD_PresetColors) || !Pd || (Pd->Type != U_PMF_BLENDFACTORS_OID)))return(NULL);
+ if(Fsd && !(Flags & U_BD_FocusScales))return(NULL);
+ if( (Flags & U_BD_FocusScales) && (!Fsd || (Fsd->Type != U_PMF_BLENDCOLORS_OID) ))return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {(Tm ? Tm->Data : NULL), (Tm ? Tm->Used : 0), 1, U_XE},
+ {(Pd ? Pd->Data : NULL), (Pd ? Pd->Used : 0), 1, U_XE},
+ {(Fsd ? Fsd->Data : NULL), (Fsd ? Fsd->Used : 0), 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set an ARRAY of U_PMF_PATHPOINTTYPE objects
+ \return Pointer to PseudoObject, NULL on error
+ \param Elements Number of entries in Flags and Enumerations
+ \param Ppt Array of unsigned bytes, lower 4 bits hold the PathPointType flag upper 4 bits hold the PathPointType enumeration.
+
+ EMF+ manual 2.2.2.31, Microsoft name: EmfPlusPathPointType Object
+*/
+U_PSEUDO_OBJ *U_PMF_PATHPOINTTYPE_set(uint32_t Elements, const uint8_t *Ppt){
+ if(!Elements || !Ppt)return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {&Elements, 4, 1, U_LE},
+ {Ppt, 1, Elements, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PATHPOINTTYPE_OID | U_PMF_ARRAY_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set an ARRAY of U_PMF_PATHPOINTTYPE objects, with a preceding Elements count
+ \return Pointer to PseudoObject, NULL on error
+ \param Elements Number of elements to add. First is added once and Others Elements-1 times.
+ \param First Apply to first point, unsigned byte, lower 4 bits hold the PathPointType flag upper 4 bits hold the PathPointType enumeration.
+ \param Others Apply to all other points, unsigned byte, lower 4 bits hold the PathPointType flag upper 4 bits hold the PathPointType enumeration.
+
+ EMF+ manual 2.2.2.31, Microsoft name: EmfPlusPathPointType Object
+*/
+U_PSEUDO_OBJ *U_PMF_PATHPOINTTYPE_set2(uint32_t Elements, uint8_t First, uint8_t Others){
+ if(!Elements)return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {&Elements, 4, 1, U_XE},
+ {&First, 1, 1, U_XE},
+ {&Others, 1, Elements-1, U_RP}, /* replicate the one value N-1 times */
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PATHPOINTTYPE_OID | U_PMF_ARRAY_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set an ARRAY of U_PMF_PATHPOINTTYPERLE objects
+ \return Pointer to PseudoObject containing first the number of elements, then an array of U_PMF_PATHPOINTTYPERLE, NULL on error
+ \param Elements Number of entries in the arrays
+ \param Bz Array of unsigned bytes, if not zero, element has Bezier bit set
+ \param RL Array of unsigned bytes, Run lengths.
+ \param Ppte Array of unsigned bytes, PathPointType enumerations.
+
+ EMF+ manual 2.2.2.32, Microsoft name: EmfPlusPathPointTypeRLE Object
+*/
+U_PSEUDO_OBJ *U_PMF_PATHPOINTTYPERLE_set(uint32_t Elements, const uint8_t *Bz, const uint8_t *RL, const uint8_t *Ppte){
+ uint8_t utmp;
+ if(!Bz || !RL || !Ppte)return(NULL);
+ /* allocate space in the structure but put no data in */
+ U_PSEUDO_OBJ *po = U_PO_create(NULL, 4 + 2*Elements, 0, U_PMF_PATHPOINTTYPERLE_OID | U_PMF_ARRAY_OID);
+ U_PSEUDO_OBJ *holdpo = po;
+ if(po){
+ U_PSEUDO_OBJ *poi = U_PMF_4NUM_set(Elements);
+ if(!poi)goto end;
+ po = U_PO_append(po, poi->Data, poi->Used);
+ U_PO_free(&poi);
+ if(!po)goto end;
+
+ for( ;Elements; Elements--, Bz++, RL++, Ppte++){
+ po = U_PO_append(po, (char *)Ppte, 1);
+ if(!po)goto end;
+
+ if(*RL > 0x3F) goto end; /* run length too big for field */
+
+ utmp = (*Bz ? 1 : 0) | ((*RL & 0x3F)<<2); /* bit 1 is not used and is set to 0 */
+ po = U_PO_append(po, (char *)&utmp, 1);
+ if(!po)goto end;
+ }
+ }
+end:
+ if(!po)U_PO_free(&holdpo);
+ return(holdpo);
+}
+
+/**
+ \brief Create and set a U_PMF_PENDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Unit UnitType enumeration
+ \param Width Width in units set by Unit
+ \param Pod U_PSEUDO_OBJ containing first the PenData flags then a U_PMF_PENOPTIONALDATA object (the second part
+ may be an empty if Flags is 0)
+
+
+ EMF+ manual 2.2.2.33, Microsoft name: EmfPlusPenData Object
+*/
+U_PSEUDO_OBJ *U_PMF_PENDATA_set(uint32_t Unit, U_FLOAT Width, const U_PSEUDO_OBJ *Pod){
+ if(Pod && ((Pod->Type != U_PMF_PENOPTIONALDATA_OID) || Pod->Used < 4))return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {(Pod ? Pod->Data : NULL), 4, 1, U_XE}, /* the Flags field, clear if no optional data */
+ {&Unit, 4, 1, U_LE},
+ {&Width, 4, 1, U_LE},
+ /* next is the (optional) U_PMF_PENOPTIONALDATA part or a terminator */
+ {(Pod ? Pod->Data + 4 : NULL), (Pod ? Pod->Used - 4 : 0), (Pod ? 1 : 0), (Pod ? U_XE : U_XX)},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PENDATA_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_PENOPTIONALDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error. Returned PO contains first the Flags, then the PO proper.
+ \param Flags Determines which of the values are stored.
+ \param Tm U_PSEUDO_OBJ containing a U_PMF_TRANSFORMMATRIX object (Transformation matrix)
+ \param StartCap LineCapType enumeration
+ \param EndCap LineCapType enumeration
+ \param Join LineJoinType enumeration
+ \param MiterLimit Maximum (miter length / line width)
+ \param Style LineStyle enumeration
+ \param DLCap DashedLineCapType enumeration
+ \param DLOffset Distance line start to first dash start
+ \param DLData U_PSEUDO_OBJ containing a U_PMF_DASHEDLINEDATA object Dash and space widths
+ \param PenAlignment PenAlignment enumeration
+ \param CmpndLineData U_PSEUDO_OBJ containing a U_PMF_COMPOUNDLINEDATA object Compount Line (parallel lines drawn instead of one)
+ \param CSCapData U_PSEUDO_OBJ containing a U_PMF_CUSTOMSTARTCAPDATA object Custom start cap
+ \param CECapData U_PSEUDO_OBJ containing a U_PMF_CUSTOMENDCAPDATA object Custom end cap
+
+
+ EMF+ manual 2.2.2.34, Microsoft name: EmfPlusPenOptionalData Object
+*/
+U_PSEUDO_OBJ *U_PMF_PENOPTIONALDATA_set(uint32_t Flags, U_PSEUDO_OBJ *Tm, int32_t StartCap, int32_t EndCap, uint32_t Join,
+ U_FLOAT MiterLimit, int32_t Style, int32_t DLCap, U_FLOAT DLOffset,
+ U_PSEUDO_OBJ *DLData, int32_t PenAlignment, U_PSEUDO_OBJ *CmpndLineData, U_PSEUDO_OBJ *CSCapData,
+ U_PSEUDO_OBJ *CECapData
+ ){
+
+ if((Flags & U_PD_Transform) && (!Tm || (Tm->Type != U_PMF_TRANSFORMMATRIX_OID)) )return(NULL);
+ if((Flags & U_PD_DLData) && (!DLData || (DLData->Type != U_PMF_DASHEDLINEDATA_OID)) )return(NULL);
+ if((Flags & U_PD_CLData) && (!CmpndLineData || (CmpndLineData->Type != U_PMF_COMPOUNDLINEDATA_OID)) )return(NULL);
+ if((Flags & U_PD_CustomStartCap) && (!CSCapData || (CSCapData->Type != U_PMF_CUSTOMSTARTCAPDATA_OID)))return(NULL);
+ if((Flags & U_PD_CustomEndCap) && (!CECapData || (CECapData->Type != U_PMF_CUSTOMENDCAPDATA_OID)) )return(NULL);
+
+ /* prepend the Flags field to the PseudoObject proper */
+ const U_SERIAL_DESC List[] = {
+ {&Flags, 4, 1, U_LE},
+ {((Flags & U_PD_Transform) ? Tm->Data : NULL), ((Flags & U_PD_Transform) ? Tm->Used : 0), 1, U_XE},
+ {((Flags & U_PD_StartCap ) ? (char *)&StartCap : NULL), ((Flags & U_PD_StartCap ) ? 4 : 0), 1, U_LE},
+ {((Flags & U_PD_EndCap ) ? (char *)&EndCap : NULL), ((Flags & U_PD_EndCap ) ? 4 : 0), 1, U_LE},
+ {((Flags & U_PD_Join ) ? (char *)&Join : NULL), ((Flags & U_PD_Join ) ? 4 : 0), 1, U_LE},
+ {((Flags & U_PD_MiterLimit ) ? (char *)&MiterLimit : NULL), ((Flags & U_PD_MiterLimit ) ? 4 : 0), 1, U_LE},
+ {((Flags & U_PD_LineStyle ) ? (char *)&Style : NULL), ((Flags & U_PD_LineStyle ) ? 4 : 0), 1, U_LE},
+ {((Flags & U_PD_DLCap ) ? (char *)&DLCap : NULL), ((Flags & U_PD_DLCap ) ? 4 : 0), 1, U_LE},
+ {((Flags & U_PD_DLOffset ) ? (char *)&DLOffset : NULL), ((Flags & U_PD_DLOffset ) ? 4 : 0), 1, U_LE},
+ {((Flags & U_PD_DLData ) ? DLData->Data : NULL), ((Flags & U_PD_DLData ) ? DLData->Used : 0), 1, U_XE},
+ {((Flags & U_PD_NonCenter ) ? (char *)&PenAlignment : NULL), ((Flags & U_PD_NonCenter ) ? 4 : 0), 1, U_LE},
+ {((Flags & U_PD_CLData ) ? CmpndLineData->Data : NULL), ((Flags & U_PD_CLData ) ? CmpndLineData->Used : 0), 1, U_XE},
+ {((Flags & U_PD_CustomStartCap) ? CSCapData->Data : NULL), ((Flags & U_PD_CustomStartCap) ? CSCapData->Used : 0), 1, U_XE},
+ {((Flags & U_PD_CustomEndCap ) ? CECapData->Data : NULL), ((Flags & U_PD_CustomEndCap ) ? CECapData->Used : 0), 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_PENOPTIONALDATA_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set an ARRAY of U_PMF_POINT objects
+ \return Pointer to PseudoObject, NULL on error
+ \param Elements Number of pairs of points in Coords
+ \param Coords Array of X,Y pairs.
+
+ EMF+ manual 2.2.2.35, Microsoft name: EmfPlusPoint Object
+*/
+U_PSEUDO_OBJ *U_PMF_POINT_set(uint32_t Elements, const U_PMF_POINT *Coords){
+ if(!Elements || !Coords)return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {&Elements, 4, 1, U_LE},
+ { Coords, 2, 2*Elements, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_POINT_OID | U_PMF_ARRAY_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set an ARRAY of U_PMF_POINTF objects, with a leading Elements value
+ \return Pointer to PseudoObject, NULL on error
+ \param Elements Number of pairs of points in Coords
+ \param Coords Array of X,Y pairs.
+
+ EMF+ manual 2.2.2.36, Microsoft name: EmfPlusPointF Object
+*/
+U_PSEUDO_OBJ *U_PMF_POINTF_set(uint32_t Elements, const U_PMF_POINTF *Coords){
+ if(!Elements || !Coords)return(NULL);
+ const U_SERIAL_DESC List[] = {
+ {&Elements, 4, 1, U_LE},
+ {Coords, 4, 2*Elements, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_POINTF_OID | U_PMF_ARRAY_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set an ARRAY of U_PMF_POINTR objects
+ \return Pointer to PseudoObject, NULL on error
+ \param Elements Number of pairs of points in Coords
+ \param Coords Array of X,Y pairs. These are absolute coordinates, they are converted to Relative here.
+
+ EMF+ manual 2.2.2.37, Microsoft name: EmfPlusPointR Object
+*/
+U_PSEUDO_OBJ *U_PMF_POINTR_set(uint32_t Elements, const U_PMF_POINTF *Coords){
+ int X,Y;
+ U_FLOAT Xf,Yf;
+ U_PSEUDO_OBJ *poi;
+ /* Worst case scenario it is 4 bytes per coord, plus the count */
+ U_PSEUDO_OBJ *po = U_PO_create(NULL, 4 + 4*Elements, 0, U_PMF_POINTR_OID); /* not exactly an array, so no U_PMF_ARRAY_OID */
+ U_PSEUDO_OBJ *holdpo = po;
+ if(!po)goto end;
+
+ poi = U_PMF_4NUM_set(Elements);
+ po = U_PO_append(po, poi->Data, poi->Used);
+ U_PO_free(&poi);
+ if(!po)goto end;
+
+ for(Xf = Yf = 0.0 ;Elements; Elements--, Coords++){
+ Xf = U_ROUND(Coords->X) - Xf;
+ Yf = U_ROUND(Coords->Y) - Yf;
+ X = ( Xf >= UINT16_MAX ? UINT16_MAX : ( Xf <= INT16_MIN ? INT16_MIN : Xf));
+ Y = ( Yf >= UINT16_MAX ? UINT16_MAX : ( Yf <= INT16_MIN ? INT16_MIN : Yf));
+ Xf = U_ROUND(Coords->X);
+ Yf = U_ROUND(Coords->Y);
+
+ /* this is not a very efficient method, too much mucking around with memory */
+
+ poi = U_PMF_INTEGER7_set(X);
+ if(!poi)poi = U_PMF_INTEGER15_set(X); /* This one must work because of the range checking, above */
+ po = U_PO_append(po, poi->Data, poi->Used);
+ U_PO_free(&poi);
+ if(!po)goto end;
+
+ poi = U_PMF_INTEGER7_set(Y);
+ if(!poi)poi = U_PMF_INTEGER15_set(Y); /* This one must work because of the range checking, above */
+ po = U_PO_append(po, poi->Data, poi->Used);
+ U_PO_free(&poi);
+ if(!po)goto end;
+ }
+ /* Because the values stored were some unpredictable combination of 1 and 2 bytes, the last byte may not end
+ on a 4 byte boundary. Make it do so by padding with up to 3 zero bytes. */
+
+ int residual;
+ residual = 3 & po->Used;
+ if(residual){
+ po = U_PO_append(po, NULL, (4 - residual));
+ if(!po)goto end;
+ }
+
+end:
+ if(!po)U_PO_free(&holdpo);
+ return(holdpo);
+}
+
+/**
+ \brief Create and set a U_PMF_RECT object
+ \return Pointer to PseudoObject, NULL on error
+ \param X UL X value
+ \param Y UL Y value
+ \param Width Width
+ \param Height Height
+
+ EMF+ manual 2.2.2.38, Microsoft name: EmfPlusRect Object
+*/
+U_PSEUDO_OBJ *U_PMF_RECT4_set(int16_t X, int16_t Y, int16_t Width, int16_t Height){
+ const U_SERIAL_DESC List[] = {
+ {&X, 2, 1, U_LE},
+ {&Y, 2, 1, U_LE},
+ {&Width, 2, 1, U_LE},
+ {&Height, 2, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_RECT_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_RECT object
+ \return Pointer to PseudoObject, NULL on error
+ \param Rect U_PMF_RECT structures
+
+ EMF+ manual 2.2.2.38, Microsoft name: EmfPlusRect Object
+*/
+U_PSEUDO_OBJ *U_PMF_RECT_set(U_PMF_RECT *Rect){
+ const U_SERIAL_DESC List[] = {
+ {Rect, 2, 4, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_RECT_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set an array of U_PMF_RECT objects in a PseudoObject
+ \return Pointer to PseudoObject, NULL on error. PseudoObject contains Elements followed by the array of U_PMF_RECT objects.
+ \param Elements Number of elements in Rects
+ \param Rects Array of U_PMF_RECT structures
+
+ EMF+ manual 2.2.2.38, Microsoft name: EmfPlusRect Object
+*/
+U_PSEUDO_OBJ *U_PMF_RECTN_set(uint32_t Elements, U_PMF_RECT *Rects){
+ if(!Rects){ return(NULL); }
+ uint32_t count = Elements;
+ U_SERIAL_DESC *List = (U_SERIAL_DESC *) malloc((Elements + 2) * sizeof(U_SERIAL_DESC));
+ U_SERIAL_DESC *Lptr = List;
+ if(!List){ return(NULL); }
+ *Lptr++ = (U_SERIAL_DESC){&Elements, 4, 1, U_LE};
+ for(; count; count--, Lptr++, Rects++){
+ *Lptr = (U_SERIAL_DESC){Rects, 2, 4, U_LE};
+ }
+ *Lptr = (U_SERIAL_DESC){NULL,0,0,U_XX};
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_RECT_OID | U_PMF_ARRAY_OID, List);
+ free(List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_RECTF object in a PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param X UL X value
+ \param Y UL Y value
+ \param Width Width
+ \param Height Height
+
+ EMF+ manual 2.2.2.39, Microsoft name: EmfPlusRectF Object
+*/
+U_PSEUDO_OBJ *U_PMF_RECTF4_set(U_FLOAT X, U_FLOAT Y, U_FLOAT Width, U_FLOAT Height){
+ const U_SERIAL_DESC List[] = {
+ {&X, 4, 1, U_LE},
+ {&Y, 4, 1, U_LE},
+ {&Width, 4, 1, U_LE},
+ {&Height, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_RECTF_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_RECTF object in a PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Rect U_PMF_RECTF structure
+
+ EMF+ manual 2.2.2.39, Microsoft name: EmfPlusRectF Object
+*/
+U_PSEUDO_OBJ *U_PMF_RECTF_set(U_PMF_RECTF *Rect){
+ const U_SERIAL_DESC List[] = {
+ {Rect, 4, 4, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_RECTF_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set an array of U_PMF_RECTF objects in a PseudoObject
+ \return Pointer to PseudoObject, NULL on error. PseudoObject contains Elements followed by the array of U_PMF_RECTF objects.
+ \param Elements Number of elements in Rects
+ \param Rects Array of U_PMF_RECTF structures
+
+ EMF+ manual 2.2.2.39, Microsoft name: EmfPlusRectF Object
+*/
+U_PSEUDO_OBJ *U_PMF_RECTFN_set(uint32_t Elements, U_PMF_RECTF *Rects){
+ if(!Rects){ return(NULL); }
+ uint32_t count = Elements;
+ U_SERIAL_DESC *List = (U_SERIAL_DESC *) malloc((Elements + 2) * sizeof(U_SERIAL_DESC));
+ U_SERIAL_DESC *Lptr = List;
+ if(!List){ return(NULL); }
+ *Lptr++ = (U_SERIAL_DESC){&Elements, 4, 1, U_LE};
+ for(; count; count--, Lptr++, Rects++){
+ *Lptr = (U_SERIAL_DESC){Rects, 4, 4, U_LE};
+ }
+ *Lptr = (U_SERIAL_DESC){NULL,0,0,U_XX};
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_RECTF_OID | U_PMF_ARRAY_OID, List);
+ free(List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_REGIONNODE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Type RegionNodeDataType Enumeration
+ \param Rnd (optional) U_PSEUDO_OBJ containing a U_PMF_REGIONNODEPATH, U_PMF_RECTF, or U_PMF_REGIONNODECHILDNODES object (Region Node Data)
+
+
+ EMF+ manual 2.2.2.40, Microsoft name: EmfPlusRegionNode Object
+*/
+U_PSEUDO_OBJ *U_PMF_REGIONNODE_set(int32_t Type, const U_PSEUDO_OBJ *Rnd){
+ int32_t pType;
+ /* make sure that the type of Rnd agrees with Type */
+ if(Rnd){
+ pType = U_OID_To_RNDT(Rnd->Type);
+ if( pType < 0){ return(NULL); }
+ if((pType > 0) && (pType != Type)){ return(NULL); }
+ if((pType == 0) &&
+ (
+ (Type < U_RNDT_And) ||
+ (Type > U_RNDT_Complement)
+ )
+ ){ return(NULL); }
+ if((Type == U_RNDT_Rect) && (Rnd->Type != U_PMF_RECTF_OID)){ return(NULL); }
+ if((Type == U_RNDT_Path) && (Rnd->Type != U_PMF_REGIONNODEPATH_OID)){ return(NULL); }
+
+ }
+ else { /* only U_RNDT_Empty and U_RNDT_Infinite do not have data */
+ if((Type != U_RNDT_Empty) ||
+ (Type != U_RNDT_Infinite) ){ return(NULL); }
+ }
+
+
+ const U_SERIAL_DESC List[] = {
+ {&Type, 4, 1, U_LE},
+ {(Rnd ? Rnd->Data : NULL), (Rnd ? Rnd->Used : 0), 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_REGIONNODE_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_REGIONNODECHILDNODES PseudoObject
+ \return Pointer to PseudoObject containing a U_PMF_REGIONNODECHILDNODES_OID object, NULL on error
+ \param Left U_PSEUDO_OBJ containing a U_PMF_REGIONNODE object
+ \param Right U_PSEUDO_OBJ containing a U_PMF_REGIONNODE object
+
+
+ EMF+ manual 2.2.2.41, Microsoft name: EmfPlusRegionNodeChildNodes Object
+*/
+U_PSEUDO_OBJ *U_PMF_REGIONNODECHILDNODES_set(const U_PSEUDO_OBJ *Left, const U_PSEUDO_OBJ *Right){
+ if(!Left || (Left->Type != U_PMF_REGIONNODE_OID)){ return(NULL); }
+ if(!Right || (Right->Type != U_PMF_REGIONNODE_OID)){ return(NULL); }
+
+ const U_SERIAL_DESC List[] = {
+ {Left->Data, Left->Used, 1, U_XE},
+ {Right->Data, Right->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_REGIONNODECHILDNODES_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_REGIONNODEPATH PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Path U_PSEUDO_OBJ containing a U_PMF_PATH object
+
+
+ EMF+ manual 2.2.2.42, Microsoft name: EmfPlusRegionNodePath Object
+*/
+U_PSEUDO_OBJ *U_PMF_REGIONNODEPATH_set(const U_PSEUDO_OBJ *Path){
+ if(!Path || (Path->Type != U_PMF_PATH_OID)){ return(NULL); }
+ /* PO Used is size_t, might be 8 bytes, value in record must be 4 bytes */
+ uint32_t Used = Path->Used;
+
+ const U_SERIAL_DESC List[] = {
+ {&Used, 4, 1, U_LE},
+ {Path->Data, Path->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_REGIONNODEPATH_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_SOLIDBRUSHDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Color U_PSEUDO_OBJ containing a U_PMF_ARGB object
+
+
+ EMF+ manual 2.2.2.43, Microsoft name: EmfPlusSolidBrushData Object
+*/
+U_PSEUDO_OBJ *U_PMF_SOLIDBRUSHDATA_set(const U_PSEUDO_OBJ *Color){
+ if(!Color || (Color->Type != U_PMF_ARGB_OID)){ return(NULL); }
+
+ const U_SERIAL_DESC List[] = {
+ {Color->Data, Color->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_SOLIDBRUSHDATA_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_STRINGFORMATDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param TabStopCount Entries in TabStop array
+ \param TabStops (optional) Array of tabstop locations
+ \param Ranges (optional) U_PSEUDO_OBJ containing an array of U_PMF_CHARACTERRANGE objects
+
+
+ EMF+ manual 2.2.2.44, Microsoft name: EmfPlusStringFormatData Object
+*/
+U_PSEUDO_OBJ *U_PMF_STRINGFORMATDATA_set(uint32_t TabStopCount, U_FLOAT *TabStops, const U_PSEUDO_OBJ *Ranges){
+ if(Ranges && (Ranges->Type != (U_PMF_CHARACTERRANGE_OID | U_PMF_ARRAY_OID))){ return(NULL); }
+
+ const U_SERIAL_DESC List[] = {
+ {TabStops, TabStopCount*4, 1, U_LE},
+ {(Ranges ? Ranges->Data : NULL), (Ranges ? Ranges->Used : 0), 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_STRINGFORMATDATA_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_TEXTUREBRUSHDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Flags BrushData flags
+ \param WrapMode WrapMode enumeration
+ \param Tbod U_PSEUDO_OBJ containing an U_PMF_TEXTUREBRUSHOPTIONALDATA object
+
+
+ EMF+ manual 2.2.2.45, Microsoft name: EmfPlusTextureBrushData Object
+*/
+U_PSEUDO_OBJ *U_PMF_TEXTUREBRUSHDATA_set(uint32_t Flags, uint32_t WrapMode, const U_PSEUDO_OBJ *Tbod){
+ if(Flags & ~U_BD_MASKB){ return(NULL); } /* a bit was set that is not supported for this record */
+ if(WrapMode > U_WM_Clamp){ return(NULL); }
+ if(!Tbod || (Tbod->Type != (U_PMF_TEXTUREBRUSHOPTIONALDATA_OID))){ return(NULL); }
+
+ const U_SERIAL_DESC List[] = {
+ {&Flags, 4, 1, U_LE},
+ {&WrapMode, 4, 1, U_LE},
+ {Tbod->Data, Tbod->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_TEXTUREBRUSHDATA_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_TEXTUREBRUSHOPTIONALDATA PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Tm (optional) U_PSEUDO_OBJ containing an U_PMF_TRANSFORMMATRIX object
+ \param Image (optional) U_PSEUDO_OBJ containing an U_PMF_IMAGE object
+
+
+ EMF+ manual 2.2.2.46, Microsoft name: EmfPlusTextureBrushOptionalData Object
+*/
+U_PSEUDO_OBJ *U_PMF_TEXTUREBRUSHOPTIONALDATA_set(const U_PSEUDO_OBJ *Tm, const U_PSEUDO_OBJ *Image){
+ if(Tm && (Tm->Type != (U_PMF_TRANSFORMMATRIX_OID))){ return(NULL); }
+ if(Image && (Image->Type != (U_PMF_IMAGE_OID))){ return(NULL); }
+
+ const U_SERIAL_DESC List[] = {
+ {(Tm ? Tm->Data : NULL), (Tm ? Tm->Used : 0), 1, U_XE},
+ {(Image ? Image->Data : NULL), (Image ? Image->Used : 0), 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_TEXTUREBRUSHOPTIONALDATA_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_TRANSFORMMATRIX PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Tm U_PMF_TRANSFORMMATRIX_ object
+
+
+ EMF+ manual 2.2.2.47, Microsoft name: EmfPlusTransformMatrix Object
+*/
+U_PSEUDO_OBJ *U_PMF_TRANSFORMMATRIX_set(U_PMF_TRANSFORMMATRIX *Tm){
+ if(!Tm){ return(NULL); }
+
+ const U_SERIAL_DESC List[] = {
+ {Tm, 4, 6, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_TRANSFORMMATRIX_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_IE_BLUR PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Radius Blur radius in pixels
+ \param ExpandEdge 1: expand bitmap by Radius; 0: bitmap size unchanged
+
+
+ EMF+ manual 2.2.3.1, Microsoft name: BlurEffect Object
+*/
+U_PSEUDO_OBJ *U_PMF_IE_BLUR_set(U_FLOAT Radius, uint32_t ExpandEdge){
+
+ const U_SERIAL_DESC List[] = {
+ {&Radius, 4, 1, U_LE},
+ {&ExpandEdge, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_BLUR_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_IE_BRIGHTNESSCONTRAST PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Brightness -255 to 255, 0 is unchanged, positive increases, negative decreases
+ \param Contrast -100 to 100, 0 is unchanged, positive increases, negative decreases
+
+
+ EMF+ manual 2.2.3.2, Microsoft name: BrightnessContrastEffect Object
+*/
+U_PSEUDO_OBJ *U_PMF_IE_BRIGHTNESSCONTRAST_set(int32_t Brightness, int32_t Contrast){
+
+ const U_SERIAL_DESC List[] = {
+ {&Brightness, 4, 1, U_LE},
+ {&Contrast, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_BRIGHTNESSCONTRAST_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_IE_COLORBALANCE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param CyanRed -100 to 100, 0 is unchanged, positive increases Red & decreases Cyan, negative is opposite
+ \param MagentaGreen -100 to 100, 0 is unchanged, positive increases Green & decreases Magenta, negative is opposite
+ \param YellowBlue -100 to 100, 0 is unchanged, positive increases Blue & decreases Yellow, negative is opposite
+
+
+ EMF+ manual 2.2.3.3, Microsoft name: ColorBalanceEffect Object
+*/
+U_PSEUDO_OBJ *U_PMF_IE_COLORBALANCE_set(int32_t CyanRed, int32_t MagentaGreen, int32_t YellowBlue){
+
+ const U_SERIAL_DESC List[] = {
+ {&CyanRed, 4, 1, U_LE},
+ {&MagentaGreen, 4, 1, U_LE},
+ {&YellowBlue, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_COLORBALANCE_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_IE_COLORCURVE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Adjust CurveAdjustment enumeration
+ \param Channel CurveChannel enumeration
+ \param Intensity adjustment to apply. "Adjust" determines what field this is and range values.
+
+
+ EMF+ manual 2.2.3.4, Microsoft name: ColorCurveEffect Object
+*/
+U_PSEUDO_OBJ *U_PMF_IE_COLORCURVE_set(uint32_t Adjust, uint32_t Channel, int32_t Intensity){
+
+ const U_SERIAL_DESC List[] = {
+ {&Adjust, 4, 1, U_LE},
+ {&Channel, 4, 1, U_LE},
+ {&Intensity, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_COLORCURVE_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_IE_COLORLOOKUPTABLE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param BLUT Blue color lookup table
+ \param GLUT Green color lookup table
+ \param RLUT Red color lookup table
+ \param ALUT Alpha color lookup table
+
+
+
+ EMF+ manual 2.2.3.5, Microsoft name: ColorLookupTableEffect Object.
+ All tables have 256 entries.
+*/
+U_PSEUDO_OBJ *U_PMF_IE_COLORLOOKUPTABLE_set(const uint8_t *BLUT, const uint8_t *GLUT, const uint8_t *RLUT, const uint8_t *ALUT){
+ if(!BLUT || !GLUT || !RLUT || !ALUT)return(NULL);
+
+ const U_SERIAL_DESC List[] = {
+ {BLUT, 1, 256, U_XE},
+ {GLUT, 1, 256, U_XE},
+ {RLUT, 1, 256, U_XE},
+ {ALUT, 1, 256, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_COLORLOOKUPTABLE_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_IE_COLORMATRIX PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Matrix 5 x 5 color transformation matrix, First 4 rows are [{4 multiplier values},0.0] for R,G,B,A, last Row is [{4 color translation valuess}, 1.0]
+
+
+ EMF+ manual 2.2.3.6, Microsoft name: ColorMatrixEffect Object
+*/
+U_PSEUDO_OBJ *U_PMF_IE_COLORMATRIX_set(const U_FLOAT *Matrix){
+ if(!Matrix)return(NULL);
+
+ const U_SERIAL_DESC List[] = {
+ {Matrix, 4, 25, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_COLORMATRIX_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_IE_HUESATURATIONLIGHTNESS PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Hue -180 to 180, 0 is unchanged
+ \param Saturation -100 to 100, 0 is unchanged
+ \param Lightness -100 to 100, 0 is unchanged
+
+
+ EMF+ manual 2.2.3.7, Microsoft name: HueSaturationLightnessEffect Object
+*/
+U_PSEUDO_OBJ *U_PMF_IE_HUESATURATIONLIGHTNESS_set(int32_t Hue, int32_t Saturation, int32_t Lightness){
+
+ const U_SERIAL_DESC List[] = {
+ {&Hue, 4, 1, U_LE},
+ {&Saturation, 4, 1, U_LE},
+ {&Lightness, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_HUESATURATIONLIGHTNESS_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_IE_LEVELS PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Highlight 0 to 100, 100 is unchanged
+ \param Midtone -100 to 0, 0 is unchanged
+ \param Shadow 0 to 100, 0 is unchanged
+
+
+ EMF+ manual 2.2.3.8, Microsoft name: LevelsEffect Object
+*/
+U_PSEUDO_OBJ *U_PMF_IE_LEVELS_set(int32_t Highlight, int32_t Midtone, int32_t Shadow){
+
+ const U_SERIAL_DESC List[] = {
+ {&Highlight, 4, 1, U_LE},
+ {&Midtone, 4, 1, U_LE},
+ {&Shadow, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_LEVELS_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_IE_REDEYECORRECTION PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Elements Number of members in Rects
+ \param Rects Array of U_RECTL rectangular area(s) to apply red eye correction
+
+
+ EMF+ manual 2.2.3.9, Microsoft name: RedEyeCorrectionEffect Object
+*/
+U_PSEUDO_OBJ *U_PMF_IE_REDEYECORRECTION_set(uint32_t Elements, const U_RECTL *Rects){
+ if(!Elements || !Rects){return(NULL);}
+
+ const U_SERIAL_DESC List[] = {
+ {&Elements, 4, 1, U_LE},
+ {Rects, 4*4, Elements,U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_REDEYECORRECTION_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_IE_SHARPEN PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Radius Sharpening radius in pixels
+ \param Sharpen 0 to 100, 0 is unchanged
+
+
+ EMF+ manual 2.2.3.10, Microsoft name: SharpenEffect Object
+*/
+U_PSEUDO_OBJ *U_PMF_IE_SHARPEN_set(U_FLOAT Radius, int32_t Sharpen){
+
+ const U_SERIAL_DESC List[] = {
+ {&Radius, 4, 1, U_LE},
+ {&Sharpen, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_SHARPEN_OID, List);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMF_IE_TINT PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Hue -180 to 180, [positive==clockwise] rotation in degrees starting from blue
+ \param Amount -100 [add black] to 100[add white], 0 is unchanged. Change in hue on specified axis
+
+
+ EMF+ manual 2.2.3.11, Microsoft name: TintEffect Object
+*/
+U_PSEUDO_OBJ *U_PMF_IE_TINT_set(const int32_t Hue, const int32_t Amount){
+
+ const U_SERIAL_DESC List[] = {
+ {&Hue, 4, 1, U_LE},
+ {&Amount, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMF_IE_TINT_OID, List);
+ return(po);
+}
+
+//! \cond
+/* internal routine, not part of the API.
+ Returns a PseudoObject containing a U_PMR_CMN_HDR_OID object.
+ The type is something like U_PMR_OFFSETCLIP (the record type, NOT the U_PMR_OFFSETCLIP_OID PseudoObject Type!).
+ The U_PMR_RECFLAG bit is added both in the data and in the Type of the PseudoObject.
+ If that bit is already set no harm, no foul.
+*/
+
+U_PSEUDO_OBJ *U_PMR_CMN_HDR_set(uint32_t Type, uint16_t Flags, uint32_t DataSize){
+
+ uint32_t Size = 12 + UP4(DataSize); /* The header itself is always 12, PMR records must be a multiple of 4 */
+ Type |= U_PMR_RECFLAG;
+ uint16_t utmp16 = Type;
+ const U_SERIAL_DESC List[] = {
+ {&utmp16, 2, 1, U_LE},
+ {&Flags, 2, 1, U_LE}, /* Microsoft EMF+ manual is BE, but this field in this implementation is LE */
+ {&Size, 4, 1, U_LE},
+ {&DataSize, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_CMN_HDR_OID, List);
+ return(po);
+}
+//! \endcond
+
+
+/**
+ \brief Create and set a U_PMR_STROKEFILLPATH PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+
+
+ EMF+ manual mentioned in 2.1.1.1, not otherwise documented, Microsoft name: EmfPlusStrokeFillPath Record, Index 0x37
+
+ "This record closes any open figures in a path, strokes the outline of
+ the path by using the current pen, and fills its interior by using the current brush."
+
+*/
+U_PSEUDO_OBJ *U_PMR_STROKEFILLPATH_set(void){
+ int Size = 0;
+ uint16_t utmp16 = 0;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_STROKEFILLPATH,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_STROKEFILLPATH_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_OFFSETCLIP PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param dX horizontal translation offset to apply to clipping region
+ \param dY vertical translation offset to apply to clipping region
+
+
+ EMF+ manual 2.3.1.1, Microsoft name: EmfPlusOffsetClip Record, Index 0x35
+*/
+U_PSEUDO_OBJ *U_PMR_OFFSETCLIP_set(U_FLOAT dX, U_FLOAT dY){
+ int Size = 2*4;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_OFFSETCLIP,0,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {&dX, 4, 1, U_LE},
+ {&dY, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_OFFSETCLIP_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_RESETCLIP PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+
+
+ EMF+ manual 2.3.1.2, Microsoft name: EmfPlusResetClip Record, Index 0x31
+*/
+U_PSEUDO_OBJ *U_PMR_RESETCLIP_set(void){
+ int Size = 0;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_RESETCLIP,0,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_RESETCLIP_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_SETCLIPPATH PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param CMenum CombineMode enumeration..
+ \param PathID U_PMF_PATH object in the EMF+ object table (0-63, inclusive)
+
+
+ EMF+ manual 2.3.1.3, Microsoft name: EmfPlusSetClipPath Record, Index 0x33
+*/
+U_PSEUDO_OBJ *U_PMR_SETCLIPPATH_set(uint32_t PathID, uint32_t CMenum){
+ if(PathID>63)return(NULL);
+ int Size=0;
+ uint16_t utmp16 = ((PathID & U_FF_MASK_OID8) << U_FF_SHFT_OID8) | ((CMenum & U_FF_MASK_CM4) << U_FF_SHFT_CM4);
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETCLIPPATH,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETCLIPPATH_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_SETCLIPRECT PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param CMenum CombineMode enumeration..
+ \param Rect U_PSEUDO_OBJ containing an U_PMF_RECTF object or an array of U_PMF_RECTF objects (the first is used)
+
+
+ EMF+ manual 2.3.1.4, Microsoft name: EmfPlusSetClipRect Record, Index 0x32
+*/
+U_PSEUDO_OBJ *U_PMR_SETCLIPRECT_set(uint32_t CMenum, const U_PSEUDO_OBJ *Rect){
+ int Size=4*4;
+ const char *start;
+ uint16_t utmp16 = ((CMenum & U_FF_MASK_CM4) << U_FF_SHFT_CM4);
+ if(Rect){
+ if( Rect->Type == U_PMF_RECTF_OID){
+ start = Rect->Data;
+ }
+ else if(Rect->Type == (U_PMF_RECTF_OID | U_PMF_ARRAY_OID)){
+ start = Rect->Data + 4;
+ }
+ else { return(0); }
+ }
+ else { return(0); }
+
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETCLIPRECT,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {start, 4, 4, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETCLIPRECT_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_SETCLIPREGION PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param PathID U_PMF_PATH object in the EMF+ object table (0-63, inclusive)
+ \param CMenum CombineMode enumeration..
+
+
+ EMF+ manual 2.3.1.5, Microsoft name: EmfPlusSetClipRegion Record, Index 0x34
+*/
+U_PSEUDO_OBJ *U_PMR_SETCLIPREGION_set(uint32_t PathID, uint32_t CMenum){
+ if(PathID>63)return(NULL);
+ int Size=0;
+ uint16_t utmp16 = ((PathID & U_FF_MASK_OID8) << U_FF_SHFT_OID8) | ((CMenum & U_FF_MASK_CM4) << U_FF_SHFT_CM4);
+
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETCLIPREGION,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETCLIPREGION_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_COMMENT PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param cbData Number of bytes in Data, must be a multiple of 4
+ \param Data Private data, may be anything. Stored in PseudoObject without adjusting byte order.
+
+
+ EMF+ manual 2.3.2.1, Microsoft name: EmfPlusComment Record, Index 0x03
+*/
+U_PSEUDO_OBJ *U_PMR_COMMENT_set(size_t cbData, const void *Data){
+ if(UP4(cbData) != cbData){ return(NULL); }
+ if(cbData && !Data){ return(NULL); }
+ int Size=cbData;
+
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_COMMENT,0,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {Data, cbData, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_COMMENT_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_ENDOFFILE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+
+
+ EMF+ manual 2.3.3.1, Microsoft name: EmfPlusEndOfFile Record, Index 0x02
+*/
+U_PSEUDO_OBJ *U_PMR_ENDOFFILE_set(void){
+ int Size=0;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_ENDOFFILE,0,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_ENDOFFILE_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_GETDC PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+
+
+ EMF+ manual 2.3.3.2, Microsoft name: EmfPlusGetDC Record, Index 0x04
+*/
+U_PSEUDO_OBJ *U_PMR_GETDC_set(void){
+ int Size=0;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_GETDC,0,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_GETDC_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_HEADER PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param IsDual set = Dual-mode file, clear= EMF+ only file.
+ \param IsVideo set = video device, clear= printer. Ignore all other bits.
+ \param Version U_PSEUDO_OBJ containing a U_PMF_GRAPHICSVERSION object
+ \param LogicalDpiX Horizontal resolution reference device in DPI
+ \param LogicalDpiY Vertical resolution reference device in DPI
+
+
+ EMF+ manual 2.3.3.3, Microsoft name: EmfPlusHeader Record, Index 0x01
+*/
+U_PSEUDO_OBJ *U_PMR_HEADER_set(int IsDual, int IsVideo, const U_PSEUDO_OBJ *Version,
+ uint32_t LogicalDpiX, uint32_t LogicalDpiY){
+ if(!Version || (Version->Type != U_PMF_GRAPHICSVERSION_OID)){ return(NULL); }
+ int Size=Version->Used + 3*4;
+ uint16_t utmp16 = (IsDual ? U_PPF_DM : 0);
+ uint32_t Flags = (IsVideo ? U_PPF_VIDEO : 0);
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_HEADER,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {Version->Data, Version->Used, 1, U_XE},
+ {&Flags, 4, 1, U_LE},
+ {&LogicalDpiX, 4, 1, U_LE},
+ {&LogicalDpiY, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_HEADER_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_CLEAR PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Color U_PSEUDO_OBJ containing a U_PMF_ARGB object.
+
+
+
+ EMF+ manual 2.3.4.1, Microsoft name: EmfPlusClear Record, Index 0x09
+
+ Erase everything preceding, set background ARGB to Color.
+*/
+U_PSEUDO_OBJ *U_PMR_CLEAR_set(const U_PSEUDO_OBJ *Color){
+ if(!Color || (Color->Type != U_PMF_ARGB_OID)){ return(NULL); }
+ int Size=Color->Used;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_CLEAR,0,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {Color->Data, Color->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_CLEAR_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_DRAWARC PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+ \param Start Start angle, >=0.0, degrees clockwise from 3:00
+ \param Sweep Sweep angle, -360<= angle <=360, degrees clockwise from Start
+ \param Rect U_PSEUDO_OBJ containing a U_PMF_RECT or U_PMF_RECTF object
+
+
+ EMF+ manual 2.3.4.2, Microsoft name: EmfPlusDrawArc Record, Index 0x12
+*/
+U_PSEUDO_OBJ *U_PMR_DRAWARC_set(uint32_t PenID, U_FLOAT Start, U_FLOAT Sweep, const U_PSEUDO_OBJ *Rect){
+ int ctype;
+ if(PenID>63)return(NULL);
+ if(!Rect){ return(NULL); }
+ else {
+ if( Rect->Type == U_PMF_RECT_OID ){ ctype = 1; }
+ else if(Rect->Type == U_PMF_RECTF_OID){ ctype = 0; }
+ else { return(NULL); }
+ }
+ int Size = 2*4 + Rect->Used;
+ uint16_t utmp16 = (ctype ? U_PPF_C : 0) | (PenID & U_FF_MASK_OID8) << U_FF_SHFT_OID8;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWARC,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {&Start, 4, 1, U_LE},
+ {&Sweep, 4, 1, U_LE},
+ {Rect->Data, Rect->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWARC_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_DRAWBEZIERS PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+ \param Points U_PSEUDO_OBJ containing first Elements, then a U_PMF_POINT, U_PMF_POINTR or U_PMF_POINTF object
+
+
+ EMF+ manual 2.3.4.3, Microsoft name: EmfPlusDrawBeziers Record, Index 0x19
+*/
+U_PSEUDO_OBJ *U_PMR_DRAWBEZIERS_set(uint32_t PenID, const U_PSEUDO_OBJ *Points){
+ int ctype, RelAbs;
+ if(PenID>63)return(NULL);
+ if(Points){
+ if( Points->Type == U_PMF_POINTR_OID){ RelAbs = 1; ctype = 0; }
+ else if(Points->Type == (U_PMF_POINT_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 1; }
+ else if(Points->Type == (U_PMF_POINTF_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 0; }
+ else { return(NULL); }
+ }
+ else { return(NULL); }
+ int Size = Points->Used;
+ uint16_t utmp16 = (ctype ? U_PPF_C : 0) | (RelAbs ? U_PPF_P : 0) |(PenID & U_FF_MASK_OID8) << U_FF_SHFT_OID8;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWBEZIERS,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {Points->Data, Points->Used, 1, U_XE}, /* Includes Elements */
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWBEZIERS_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_DRAWCLOSEDCURVE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+ \param Tension Controls splines, 0 is straight line, >0 is curved
+ \param Points U_PSEUDO_OBJ containing a U_PMF_POINT, U_PMF_POINTR or U_PMF_POINTF object
+
+
+ EMF+ manual 2.3.4.4, Microsoft name: EmfPlusDrawClosedCurve Record, Index 0x17
+
+ Curve is a cardinal spline.
+
+ References sent by MS support:
+
+ http://alvyray.com/Memos/CG/Pixar/spline77.pdf
+
+ http://msdn.microsoft.com/en-us/library/4cf6we5y(v=vs.110).aspx
+
+
+*/
+U_PSEUDO_OBJ *U_PMR_DRAWCLOSEDCURVE_set(uint32_t PenID, U_FLOAT Tension, const U_PSEUDO_OBJ *Points){
+ int ctype, RelAbs;
+ if(PenID>63)return(NULL);
+ if(Points){
+ if( Points->Type == U_PMF_POINTR_OID){ RelAbs = 1; ctype = 0; }
+ else if(Points->Type == (U_PMF_POINT_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 1; }
+ else if(Points->Type == (U_PMF_POINTF_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 0; }
+ else { return(NULL); }
+ }
+ else { return(NULL); }
+ int Size = 4 + Points->Used;
+ uint16_t utmp16 = (ctype ? U_PPF_C : 0) | (RelAbs ? U_PPF_P : 0) |(PenID & U_FF_MASK_OID8) << U_FF_SHFT_OID8;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWCLOSEDCURVE,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {&Tension, 4, 1, U_LE},
+ {Points->Data, Points->Used, 1, U_XE}, /* includes Elements*/
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWCLOSEDCURVE_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_DRAWCURVE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+ \param Tension Controls splines, 0 is straight line, >0 is curved
+ \param Offset The starting point in the list of points, 0 is first.
+ \param NSegs Number of segments to draw. Starting at Offset go NSegs straight lines, must not run out of points..
+ \param Points U_PSEUDO_OBJ containing an element count then a series of U_PMF_POINT or U_PMF_POINTF object
+
+
+ EMF+ manual 2.3.4.5, Microsoft name: EmfPlusDrawCurve Record, Index 0x18
+
+ Curve is a cardinal spline, using doubled terminator points to generate curves for the terminal segments.
+
+ References sent by MS support:
+
+ http://alvyray.com/Memos/CG/Pixar/spline77.pdf
+
+ http://msdn.microsoft.com/en-us/library/4cf6we5y(v=vs.110).aspx
+
+*/
+U_PSEUDO_OBJ *U_PMR_DRAWCURVE_set(uint32_t PenID, U_FLOAT Tension, uint32_t Offset, uint32_t NSegs, const U_PSEUDO_OBJ *Points){
+ int ctype;
+ if(PenID>63)return(NULL);
+ if(!Points){ return(NULL); }
+ if(!NSegs){ return(NULL); }
+ else {
+ if( Points->Type == (U_PMF_POINT_OID | U_PMF_ARRAY_OID)){ ctype = 1; }
+ else if(Points->Type == (U_PMF_POINTF_OID | U_PMF_ARRAY_OID)){ ctype = 0; }
+ else { return(NULL); }
+ }
+ uint32_t Elements = (Points->Used - 4)/(ctype ? 4 : 8); /* This way do not need to worry about byte order */
+ if(Offset + NSegs + 1 > Elements){ return(NULL); }
+ int Size = 3*4 + Points->Used;
+ uint16_t utmp16 = (ctype ? U_PPF_C : 0) |(PenID & U_FF_MASK_OID8) << U_FF_SHFT_OID8;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWCURVE,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {&Tension, 4, 1, U_LE},
+ {&Offset, 4, 1, U_LE},
+ {&NSegs, 4, 1, U_LE},
+ {Points->Data, Points->Used, 1, U_XE}, /* Elements, points */
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWCURVE_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_DRAWDRIVERSTRING PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param FontID U_PMF_FONT object in the EMF+ object table (0-63, inclusive)
+ \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive)
+ \param DSOFlags DriverStringOptions flags
+ \param HasMatrix If 1 record contains a TransformMatrix field, if 0 it does not.
+ \param GlyphCount The number of Elements in Glyphs, must agree with the number of elements in Points.
+ \param Glyphs If U_DSO_CmapLookup is set in DSOFlags this is an array of UTF16LE characters, otherwise, it is an array of indices into the U_PMF_FONT object indexed by Object_ID in flags.
+ \param Points U_PSEUDO_OBJ containing a U_PMF_POINTF object
+ \param Tm U_PSEUDO_OBJ containing a U_PMF_TRANSFORMMATRIX object. Apply to Glyphs & Positions. Present if HasMatrix is 1
+
+
+ EMF+ manual 2.3.4.6, Microsoft name: EmfPlusDrawDriverString Record, Index 0x36
+*/
+U_PSEUDO_OBJ *U_PMR_DRAWDRIVERSTRING_set(uint32_t FontID, const U_PSEUDO_OBJ *BrushID,
+ uint32_t DSOFlags, uint32_t HasMatrix, uint32_t GlyphCount,
+ const uint16_t *Glyphs, const U_PSEUDO_OBJ *Points, const U_PSEUDO_OBJ *Tm){
+ int btype;
+ if(FontID>63){ return(NULL); }
+ if(!Glyphs){ return(NULL); }
+ if(!Points || (Points->Type != (U_PMF_POINTF_OID | U_PMF_ARRAY_OID))){ return(NULL); }
+ uint32_t Elements = (Points->Used -4)/4;
+ if(GlyphCount != Elements){ return(NULL); }
+ if(BrushID){
+ if( BrushID->Used != 4){ return(NULL); }
+ else if( BrushID->Type == U_PMF_ARGB_OID){ btype = 1; }
+ else if( BrushID->Type == U_PMF_4NUM_OID){ btype = 0; }
+ else { return(NULL); }
+ }
+ else { return(NULL); }
+ int Size = 4 + BrushID->Used + 3*4 + Elements*2 + (Points->Used - 4);
+ if(HasMatrix){
+ if(!Tm){ return(NULL); }
+ else if(Tm->Type != (U_PMF_TRANSFORMMATRIX_OID)){ return(NULL); }
+ Size += Tm->Used;
+ }
+ uint16_t utmp16 = (btype ? U_PPF_B : 0) |(FontID & U_FF_MASK_OID8) << U_FF_SHFT_OID8;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWDRIVERSTRING,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data,ph->Used, 1, U_XE},
+ {BrushID->Data, BrushID->Used, 1, U_XE},
+ {&DSOFlags, 4, 1, U_LE},
+ {&HasMatrix, 4, 1, U_LE},
+ {&Elements, 4, 1, U_LE},
+ {Glyphs, 2, Elements, U_LE},
+ {Points->Data + 4, Points->Used - 4, 1, U_XE}, /* omit Elements */
+ {(HasMatrix ? Tm->Data : NULL), (HasMatrix ? Tm->Used : 0), 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWDRIVERSTRING_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_DRAWELLIPSE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+ \param Rect U_PSEUDO_OBJ containing a U_PMF_RECT or U_PMF_RECTF object
+
+
+ EMF+ manual 2.3.4.7, Microsoft name: EmfPlusDrawEllipse Record, Index 0x0F
+*/
+U_PSEUDO_OBJ *U_PMR_DRAWELLIPSE_set(uint32_t PenID, const U_PSEUDO_OBJ *Rect){
+ if(PenID>63)return(NULL);
+ int ctype;
+ if(!Rect){ return(NULL); }
+ else {
+ if( Rect->Type == U_PMF_RECT_OID ){ ctype = 1; }
+ else if(Rect->Type == U_PMF_RECTF_OID){ ctype = 0; }
+ else { return(NULL); }
+ }
+ int Size = Rect->Used;
+ uint16_t utmp16 = (ctype ? U_PPF_C : 0) | (PenID & U_FF_MASK_OID8) << U_FF_SHFT_OID8;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWELLIPSE,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {Rect->Data, Rect->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWELLIPSE_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_DRAWIMAGE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param ImgID U_PMF_IMAGE object in the EMF+ object table (0-63, inclusive)
+ \param ImgAttrID index of a U_PMF_IMAGEATTRIBUTES object in the object table
+ \param SrcUnit UnitType enumeration
+ \param SrcRect U_PSEUDO_OBJ containing a U_PMF_RECTF object, Source region of image
+ \param DstRect U_PSEUDO_OBJ containing a U_PMF_RECT or U_PMF_RECTF object
+
+
+ EMF+ manual 2.3.4.8, Microsoft name: EmfPlusDrawImage Record, Index 0x1A
+*/
+U_PSEUDO_OBJ *U_PMR_DRAWIMAGE_set(uint32_t ImgID,
+ int32_t ImgAttrID, int32_t SrcUnit, const U_PSEUDO_OBJ *SrcRect, const U_PSEUDO_OBJ *DstRect){
+ int ctype;
+ if(ImgID>63)return(NULL);
+ if(!SrcRect || (SrcRect->Type != U_PMF_RECTF_OID)){ return(NULL); }
+ if(!DstRect){ return(NULL); }
+ else {
+ if( DstRect->Type == U_PMF_RECT_OID ){ ctype = 1; }
+ else if(DstRect->Type == U_PMF_RECTF_OID){ ctype = 0; }
+ else { return(NULL); }
+ }
+ int Size = 2*4 + SrcRect->Used + DstRect->Used;
+ uint16_t utmp16 = (ctype ? U_PPF_C : 0) | (ImgID & U_FF_MASK_OID8) << U_FF_SHFT_OID8;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWIMAGE,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {&ImgAttrID, 4, 1, U_LE},
+ {&SrcUnit, 4, 1, U_LE},
+ {SrcRect->Data, SrcRect->Used, 1, U_XE},
+ {DstRect->Data, DstRect->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWIMAGE_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_DRAWIMAGEPOINTS PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param ImgID U_PMF_IMAGE object in the EMF+ object table (0-63, inclusive)
+ \param etype Set: effect from previous U_PMR_SERIALIZABLEOBJECT record will be applied; Clear: no effect applied
+ \param ImgAttrID index of a U_PMF_IMAGEATTRIBUTES object in the object table
+ \param SrcUnit UnitType enumeration
+ \param SrcRect U_PSEUDO_OBJ containing a U_PMF_RECTF object, Source region of image
+ \param Points U_PSEUDO_OBJ containing an array of 3 (U_PMF_POINT, U_PMF_POINTF, or U_PMF_POINTF) objects. These points are the UL, UR, and LL vertices of a parallelogram.
+
+
+ EMF+ manual 2.3.4.9, Microsoft name: EmfPlusDrawImagePoints Record, Index 0x1B
+
+
+ WARNING! Windows XP Preview does not show filter effects, whether or not U_PPF_E is set. They are visible if the EMF+
+ file is inserted as an image into PowerPoint.
+*/
+U_PSEUDO_OBJ *U_PMR_DRAWIMAGEPOINTS_set(uint32_t ImgID, int etype,
+ int32_t ImgAttrID, int32_t SrcUnit, const U_PSEUDO_OBJ *SrcRect,
+ const U_PSEUDO_OBJ *Points){
+ int ctype, RelAbs;
+ if(ImgID>63){ return(NULL); }
+ if(!SrcRect || (SrcRect->Type != U_PMF_RECTF_OID)){ return(NULL); }
+ if(Points){
+ if( Points->Type == U_PMF_POINTR_OID){ RelAbs = 1; ctype = 0; }
+ else if(Points->Type == (U_PMF_POINT_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 1; }
+ else if(Points->Type == (U_PMF_POINTF_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 0; }
+ else { return(NULL); }
+ }
+ else { return(NULL); }
+ int Size = 2*4 + SrcRect->Used + Points->Used;
+ uint16_t utmp16 = (ctype ? U_PPF_C : 0) | (etype ? U_PPF_E : 0) | (RelAbs ? U_PPF_P : 0) | (ImgID & U_FF_MASK_OID8) << U_FF_SHFT_OID8;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWIMAGEPOINTS,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {&ImgAttrID, 4, 1, U_LE},
+ {&SrcUnit, 4, 1, U_LE},
+ {SrcRect->Data, SrcRect->Used, 1, U_XE},
+ {Points->Data, Points->Used, 1, U_XE}, /* includes Elements*/
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWIMAGEPOINTS_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_DRAWLINES PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+ \param dtype Set: path must be closed, Clear: path is open
+ \param Points U_PSEUDO_OBJ containing an array of 3 U_PMF_POINT, U_PMF_POINTR, or U_PMF_POINTF objects
+
+
+ EMF+ manual 2.3.4.10, Microsoft name: EmfPlusDrawLines Record, Index 0x0D
+*/
+U_PSEUDO_OBJ *U_PMR_DRAWLINES_set(uint32_t PenID, int dtype, const U_PSEUDO_OBJ *Points){
+ int ctype, RelAbs;
+ if(PenID>63){ return(NULL); }
+ if(Points){
+ if( Points->Type == U_PMF_POINTR_OID){ RelAbs = 1; ctype = 0; }
+ else if(Points->Type == (U_PMF_POINT_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 1; }
+ else if(Points->Type == (U_PMF_POINTF_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 0; }
+ else { return(NULL); }
+ }
+ else { return(NULL); }
+ int Size = Points->Used;
+ uint16_t utmp16 = (ctype ? U_PPF_C : 0) | (dtype ? U_PPF_D : 0) | (RelAbs ? U_PPF_P : 0) | (PenID & U_FF_MASK_OID8) << U_FF_SHFT_OID8;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWLINES,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {Points->Data, Points->Used, 1, U_XE}, /* includes Elements */
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWLINES_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_DRAWPATH PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param PathID U_PMF_PATH object in the EMF+ object table (0-63, inclusive)
+ \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+
+
+ EMF+ manual 2.3.4.11, Microsoft name: EmfPlusDrawPath Record, Index 0x15
+*/
+U_PSEUDO_OBJ *U_PMR_DRAWPATH_set(uint32_t PathID, uint32_t PenID){
+ if(PathID>63)return(NULL);
+ if(PenID>63)return(NULL);
+ int Size = 4;
+ uint16_t utmp16 = (PathID & U_FF_MASK_OID8) << U_FF_SHFT_OID8;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWPATH,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {&PenID, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWPATH_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_DRAWPIE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+ \param Start Start angle, >=0.0, degrees clockwise from 3:00
+ \param Sweep Sweep angle, -360<= angle <=360, degrees clockwise from Start
+ \param Rect U_PSEUDO_OBJ containing a U_PMF_RECT or U_PMF_RECTF object
+
+
+ EMF+ manual 2.3.4.12, Microsoft name: EmfPlusDrawPie Record, Index 0x0D
+*/
+U_PSEUDO_OBJ *U_PMR_DRAWPIE_set(uint32_t PenID,
+ U_FLOAT Start, U_FLOAT Sweep, const U_PSEUDO_OBJ *Rect){
+ int ctype;
+ if(PenID>63)return(NULL);
+ if(!Rect){ return(NULL); }
+ else {
+ if( Rect->Type == U_PMF_RECT_OID ){ ctype = 1; }
+ else if(Rect->Type == U_PMF_RECTF_OID){ ctype = 0; }
+ else { return(NULL); }
+ }
+ int Size = 2*4 + Rect->Used;
+ uint16_t utmp16 = (ctype ? U_PPF_C : 0) | (PenID & U_FF_MASK_OID8) << U_FF_SHFT_OID8;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWPIE,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {&Start, 4, 1, U_LE},
+ {&Sweep, 4, 1, U_LE},
+ {Rect->Data, Rect->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWPIE_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_DRAWRECTS PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+ \param Rects U_PSEUDO_OBJ containing 1 rect OR a count N follwed by N rects. Rects may be either U_PMF_RECT or U_PMF_RECTF
+
+
+ EMF+ manual 2.3.4.13, Microsoft name: EmfPlusDrawRects Record, Index 0x0B
+*/
+U_PSEUDO_OBJ *U_PMR_DRAWRECTS_set(uint32_t PenID, const U_PSEUDO_OBJ *Rects){
+ int ctype;
+ int just1;
+ uint32_t Elements=1; /* only used when a single rect is passed in, not an array, not even an array with one member*/
+ if(PenID>63){ return(NULL); }
+ if(Rects){
+ if( (Rects->Type & U_PMF_MASK_OID) == U_PMF_RECT_OID ){ ctype = 1; }
+ else if( (Rects->Type & U_PMF_MASK_OID) == U_PMF_RECTF_OID){ ctype = 0; }
+ else { return(NULL); }
+ }
+ else { return(NULL); }
+ just1 = (Rects->Type & U_PMF_ARRAY_OID ? 0 : 1);
+ int Size = Rects->Used + (just1 ? 4 : 0); /* Elements in Rects for array, not for single */
+ uint16_t utmp16 = (ctype ? U_PPF_C : 0)| (PenID & U_FF_MASK_OID8) << U_FF_SHFT_OID8;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWRECTS,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {(just1 ? (char *)&Elements : NULL), (just1 ? 4: 0), 1, U_LE}, /* element count if a single Rect was passed in, empty otherwise */
+ {Rects->Data, Rects->Used, 1, U_XE}, /* Elements + Array, already stored in Rects, if an array was passed in, just rect if a single */
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWRECTS_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_DRAWSTRING PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param FontID U_PMF_FONT object in the EMF+ object table (0-63, inclusive)
+ \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive)
+ \param FormatID U_PMF_STRINGFORMAT object in EMF+ Object Table.
+ \param Length Number of characters in the string.
+ \param Rect U_PSEUDO_OBJ containing a U_PMF_RECTF object, string's bounding box
+ \param Text Array of UFT-16LE unicode characters.
+
+
+ EMF+ manual 2.3.4.14, Microsoft name: EmfPlusDrawString Record, Index 0x1C
+*/
+U_PSEUDO_OBJ *U_PMR_DRAWSTRING_set(uint32_t FontID, const U_PSEUDO_OBJ *BrushID,
+ uint32_t FormatID, uint32_t Length, const U_PSEUDO_OBJ *Rect, const uint16_t *Text){
+ int btype;
+ if(FontID>63){ return(NULL); }
+ if(!Length){ return(NULL); }
+ else if (!Text){ return(NULL); }
+ if(!Rect || Rect->Type != U_PMF_RECTF_OID){ return(NULL); }
+ if(BrushID){
+ if( BrushID->Used != 4){ return(NULL); }
+ else if( BrushID->Type == U_PMF_ARGB_OID){ btype = 1; }
+ else if( BrushID->Type == U_PMF_4NUM_OID){ btype = 0; }
+ else { return(NULL); }
+ }
+ else { return(NULL); }
+ int Size = BrushID->Used + 2*4 + Rect->Used +2*Length;
+ uint16_t utmp16 = (btype ? U_PPF_B : 0)| (FontID & U_FF_MASK_OID8) << U_FF_SHFT_OID8;
+ uint32_t pad = (0x1 & Length ? 2 : 0);
+ Size+=pad;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_DRAWSTRING,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {BrushID->Data, BrushID->Used, 1, U_XE},
+ {&FormatID, 4, 1, U_LE},
+ {&Length, 4, 1, U_LE},
+ {Rect->Data, Rect->Used, 1, U_XE},
+ {Text, 2*Length, 1, U_XE},
+ {NULL, pad, (pad ? 1 : 0), (pad ? U_XE : U_XX)}, /* Entire record must be a multiple of 4 */
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_DRAWSTRING_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_FILLCLOSEDCURVE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param ftype If U_WINDING use winding fill, else use fill
+ \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive)
+ \param Tension Controls splines, 0 is straight line, >0 is curved
+ \param Points U_PSEUDO_OBJ containing a U_PMF_POINT, U_PMF_POINTR or U_PMF_POINTF object
+
+
+ EMF+ manual 2.3.4.15, Microsoft name: EmfPlusFillClosedCurve Record, Index 0x16
+*/
+U_PSEUDO_OBJ *U_PMR_FILLCLOSEDCURVE_set(int ftype, U_FLOAT Tension, const U_PSEUDO_OBJ *BrushID, const U_PSEUDO_OBJ *Points){
+ int btype, ctype, RelAbs;
+ int Size=0;
+ if(BrushID){
+ if( BrushID->Used != 4){ return(NULL); }
+ else if( BrushID->Type == U_PMF_ARGB_OID){ btype = 1; }
+ else if( BrushID->Type == U_PMF_4NUM_OID){ btype = 0; }
+ else { return(NULL); }
+ }
+ else { return(NULL); }
+ if(Points){
+ if( Points->Type == U_PMF_POINTR_OID){ RelAbs = 1; ctype = 0; }
+ else if(Points->Type == (U_PMF_POINT_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 1; }
+ else if(Points->Type == (U_PMF_POINTF_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 0; }
+ else { return(NULL); }
+ }
+ else { return(NULL); }
+ Size = BrushID->Used + 4 + Points->Used;
+ uint16_t utmp16 = (btype ? U_PPF_B : 0) | (ctype ? U_PPF_C : 0) |((ftype == U_WINDING) ? U_PPF_F : 0) |(RelAbs ? U_PPF_P : 0);
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_FILLCLOSEDCURVE,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {BrushID->Data, BrushID->Used, 1, U_XE},
+ {&Tension, 4, 1, U_LE},
+ {Points->Data, Points->Used, 1, U_XE}, /* includes Elements */
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_FILLCLOSEDCURVE_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_FILLELLIPSE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive)
+ \param Rect U_PSEUDO_OBJ containing a U_PMF_RECT or U_PMF_RECTF object
+
+
+ EMF+ manual 2.3.4.16, Microsoft name: EmfPlusFillEllipse Record, Index 0x0E
+*/
+U_PSEUDO_OBJ *U_PMR_FILLELLIPSE_set(const U_PSEUDO_OBJ *BrushID, const U_PSEUDO_OBJ *Rect){
+ int btype, ctype;
+ if(BrushID){
+ if( BrushID->Used != 4){ return(NULL); }
+ else if( BrushID->Type == U_PMF_ARGB_OID){ btype = 1; }
+ else if( BrushID->Type == U_PMF_4NUM_OID){ btype = 0; }
+ else { return(NULL); }
+ }
+ else { return(NULL); }
+ if(Rect){
+ if( Rect->Type == U_PMF_RECT_OID ){ ctype = 1; }
+ else if(Rect->Type == U_PMF_RECTF_OID){ ctype = 0; }
+ else { return(NULL); }
+ }
+ else { return(NULL); }
+ int Size = BrushID->Used + Rect->Used;
+ uint16_t utmp16 = (btype ? U_PPF_B : 0) | (ctype ? U_PPF_C : 0);
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_FILLELLIPSE,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {BrushID->Data, BrushID->Used, 1, U_XE},
+ {Rect->Data, Rect->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_FILLELLIPSE_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_FILLPATH PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param PathID U_PMF_PATH object in the EMF+ object table (0-63, inclusive)
+ \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive)
+
+
+ EMF+ manual 2.3.4.17, Microsoft name: EmfPlusFillPath Record, Index 0x14
+*/
+U_PSEUDO_OBJ *U_PMR_FILLPATH_set(uint32_t PathID, const U_PSEUDO_OBJ *BrushID){
+ int btype;
+ int Size=0;
+ if(PathID>63)return(NULL);
+ if(BrushID){
+ if( BrushID->Used != 4){ return(NULL); }
+ else if( BrushID->Type == U_PMF_ARGB_OID){ btype = 1; }
+ else if( BrushID->Type == U_PMF_4NUM_OID){ btype = 0; }
+ else { return(NULL); }
+ }
+ else { return(NULL); }
+ Size = BrushID->Used;
+ uint16_t utmp16 = (btype ? U_PPF_B : 0) | (PathID & U_FF_MASK_OID8) << U_FF_SHFT_OID8 ;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_FILLPATH,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {BrushID->Data, BrushID->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_FILLPATH_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_FILLPIE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Start Start angle, >=0.0, degrees clockwise from 3:00
+ \param Sweep Sweep angle, -360<= angle <=360, degrees clockwise from Start
+ \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive)
+ \param Rect U_PSEUDO_OBJ containing a U_PMF_RECT or U_PMF_RECTF object
+
+
+ EMF+ manual 2.3.4.18, Microsoft name: EmfPlusFillPie Record, Index 0x10
+*/
+U_PSEUDO_OBJ *U_PMR_FILLPIE_set(U_FLOAT Start, U_FLOAT Sweep, const U_PSEUDO_OBJ *BrushID, const U_PSEUDO_OBJ *Rect){
+ int btype, ctype;
+ if(BrushID){
+ if( BrushID->Used != 4){ return(NULL); }
+ else if( BrushID->Type == U_PMF_ARGB_OID){ btype = 1; }
+ else if( BrushID->Type == U_PMF_4NUM_OID){ btype = 0; }
+ else { return(NULL); }
+ }
+ else { return(NULL); }
+ if(!Rect){ return(NULL); }
+ else {
+ if( Rect->Type == U_PMF_RECT_OID ){ ctype = 1; }
+ else if(Rect->Type == U_PMF_RECTF_OID){ ctype = 0; }
+ else { return(NULL); }
+ }
+ int Size = BrushID->Used + 2*4 + Rect->Used;
+ uint16_t utmp16 = (btype ? U_PPF_B : 0) | (ctype ? U_PPF_C : 0);
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_FILLPIE,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {BrushID->Data, BrushID->Used, 1, U_XE},
+ {&Start, 4, 1, U_LE},
+ {&Sweep, 4, 1, U_LE},
+ {Rect->Data, Rect->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_FILLPIE_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_FILLPOLYGON PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive)
+ \param Points U_PSEUDO_OBJ containing an array of 3 U_PMF_POINT, U_PMF_POINTR, or U_PMF_POINTF objects
+
+
+ EMF+ manual 2.3.4.19, Microsoft name: EmfPlusFillPolygon Record, Index 0x0C
+*/
+U_PSEUDO_OBJ *U_PMR_FILLPOLYGON_set(const U_PSEUDO_OBJ *BrushID, const U_PSEUDO_OBJ *Points){
+ int btype, ctype, RelAbs;
+ if(BrushID){
+ if( BrushID->Used != 4){ return(NULL); }
+ else if( BrushID->Type == U_PMF_ARGB_OID){ btype = 1; }
+ else if( BrushID->Type == U_PMF_4NUM_OID){ btype = 0; }
+ else { return(NULL); }
+ }
+ else { return(NULL); }
+ if(Points){
+ if( Points->Type == U_PMF_POINTR_OID){ RelAbs = 1; ctype = 0; }
+ else if(Points->Type == (U_PMF_POINT_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 1; }
+ else if(Points->Type == (U_PMF_POINTF_OID | U_PMF_ARRAY_OID)){ RelAbs = 0; ctype = 0; }
+ else { return(NULL); }
+ }
+ else { return(NULL); }
+ int Size = BrushID->Used + Points->Used;
+ uint16_t utmp16 = (btype ? U_PPF_B : 0) | (ctype ? U_PPF_C : 0) |(RelAbs ? U_PPF_P : 0);
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_FILLPOLYGON,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {BrushID->Data, BrushID->Used, 1, U_XE},
+ {Points->Data, Points->Used, 1, U_XE}, /* includes Elements */
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_FILLPOLYGON_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_FILLRECTS PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive)
+ \param Rects U_PSEUDO_OBJ containing 1 rect OR a count N followed by N rects. Rects may be either U_PMF_RECT or U_PMF_RECTF
+
+
+ EMF+ manual 2.3.4.20, Microsoft name: EmfPlusFillRects Record, Index 0x0A
+*/
+U_PSEUDO_OBJ *U_PMR_FILLRECTS_set(const U_PSEUDO_OBJ *BrushID, const U_PSEUDO_OBJ *Rects){
+ int btype, ctype;
+ int just1;
+ uint32_t Elements=1; /* only used when a single rect is passed in, not an array, not even an array with one member*/
+ if(BrushID){
+ if( BrushID->Used != 4){ return(NULL); }
+ else if( BrushID->Type == U_PMF_ARGB_OID){ btype = 1; }
+ else if( BrushID->Type == U_PMF_4NUM_OID){ btype = 0; }
+ else { return(NULL); }
+ }
+ else { return(NULL); }
+ if(Rects){
+ if( (Rects->Type & U_PMF_MASK_OID) == U_PMF_RECT_OID ){ ctype = 1; }
+ else if( (Rects->Type & U_PMF_MASK_OID) == U_PMF_RECTF_OID){ ctype = 0; }
+ else { return(NULL); }
+ }
+ else { return(NULL); }
+ just1 = (Rects->Type & U_PMF_ARRAY_OID ? 0 : 1);
+ int Size = BrushID->Used + Rects->Used + (just1 ? 4 : 0); /* Elements in Rects for array, not for single */
+ uint16_t utmp16 = (btype ? U_PPF_B : 0)|(ctype ? U_PPF_C : 0);
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_FILLRECTS,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {BrushID->Data, BrushID->Used, 1, U_XE},
+ {(just1 ? (char *)&Elements : NULL), (just1 ? 4: 0), 1, U_LE}, /* element count if a single Rect was passed in, empty otherwise */
+ {Rects->Data, Rects->Used, 1, U_XE}, /* Elements + Array, already stored in Rects, if an array was passed in, just rect if a single */
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_FILLRECTS_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_FILLREGION PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param RgnID U_PMF_REGION object in the EMF+ object table (0-63, inclusive)
+ \param BrushID U_PSEUDO_OBJ containing a U_PMF_ARGB or a U_PMF_4NUM. Color or U_PMF_BRUSH object in the EMF+ object table (0-63, inclusive)
+
+
+ EMF+ manual 2.3.4.21, Microsoft name: EmfPlusFillRegion Record, Index 0x13
+*/
+U_PSEUDO_OBJ *U_PMR_FILLREGION_set(uint32_t RgnID, const U_PSEUDO_OBJ *BrushID){
+ int btype;
+ if(BrushID){
+ if( BrushID->Used != 4){ return(NULL); }
+ else if( BrushID->Type == U_PMF_ARGB_OID){ btype = 1; }
+ else if( BrushID->Type == U_PMF_4NUM_OID){ btype = 0; }
+ else { return(NULL); }
+ }
+ else { return(NULL); }
+ int Size = BrushID->Used;
+ uint16_t utmp16 = (btype ? U_PPF_B : 0) | (RgnID & U_FF_MASK_OID8) << U_FF_SHFT_OID8;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_FILLREGION,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {BrushID->Data, BrushID->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_FILLREGION_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_OBJECT PseudoObject from another PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param ObjID Index for this object in the EMF+ object table (0-63, inclusive)
+ \param Po U_PSEUDO_OBJ containing an object type that may be stored in the EMF+ object table
+*/
+U_PSEUDO_OBJ *U_PMR_OBJECT_PO_set(uint32_t ObjID, U_PSEUDO_OBJ *Po){
+ if(!Po){ return(NULL); }
+ int otype = U_OID_To_OT(Po->Type); /* This will return 0 if the type is not valid for an object */
+ if(!otype){ return(NULL); }
+ U_PSEUDO_OBJ *po = U_PMR_OBJECT_set(ObjID, otype, 0, 0, Po->Used, Po->Data); /* 0,0 = rec. not continued, TSize value (ignored) */
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_OBJECT PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param ObjID Index for this object in the EMF+ object table (0-63, inclusive)
+ \param otype ObjectType enumeration for this Object
+ \param ntype Set: object definition continues in next record; Clear: this is the sole object definition record
+ \param TSize If ntype is set the total number of data bytes split across multiple records. If ntype is clear, it is ignored.
+ \param cbData Object's data size, in bytes.
+ \param Data Object's data. Type from otype.
+
+
+ EMF+ manual 2.3.5.1, Microsoft name: EmfPlusObject Record, Index 0x13
+
+ Normally this is only called by U_PMR_OBJECT_PO_set().
+
+ U_PMR_OBJECT records can only hold a maximum of 65020 bytes of data. If the object is larger than that
+ then multiple U_PMR_OBJECT records are created, one after the other. If this
+ happens each record has cbData following ph, and the ntype flag is set. If all of the data is less than 65020
+ then cbData is NOT entered following ph, and the ntype flag is clear.
+
+ Call initially in all cases with ntype clear and TSize = 0. If the record needs to be fragmented
+ the function will call itself recursively to do so.
+
+*/
+U_PSEUDO_OBJ *U_PMR_OBJECT_set(uint32_t ObjID, int otype, int ntype, uint32_t TSize, size_t cbData, const char *Data){
+ uint32_t CSize;
+ int Pad = UP4(TSize) - TSize;
+ if((otype < U_OT_Brush) || (otype > U_OT_CustomLineCap)){ return(NULL); }
+ if(ntype && (cbData > U_OBJRECLIM)){ return(NULL); }
+ if(!Data || !cbData){ return(NULL); }
+ U_PSEUDO_OBJ *po;
+
+ if(!ntype && !TSize && (cbData > U_OBJRECLIM)){
+ ntype = 1;
+ TSize = cbData;
+ po = U_PO_create(NULL, TSize + 16 * (1 + (TSize/cbData)), 0, U_PMR_OBJECT_OID);
+ if(po){
+ while(cbData){
+ CSize = (cbData > U_OBJRECLIM ? U_OBJRECLIM : cbData);
+ U_PSEUDO_OBJ *pot = U_PMR_OBJECT_set(ObjID, otype, ntype, TSize, CSize, Data);
+ if(!pot)break;
+ U_PSEUDO_OBJ *newpo = U_PO_po_append(po, pot, U_PMF_KEEP_ELEMENTS);
+ U_PO_free(&pot);
+ if(!newpo)break;
+ po = newpo;
+ Data += U_OBJRECLIM;
+ cbData -= CSize;
+ }
+ if(cbData){ /* some error */
+ U_PO_free(&po);
+ }
+ }
+ }
+ else {
+ /* Send in DataSize, U_PMR_CMN_HDR_set will adjust Header Size with 1-3 pad bytes if needed */
+ uint16_t utmp16 = otype << 8 | (ntype ? U_PPF_N : 0) | (ObjID & U_FF_MASK_OID8) << U_FF_SHFT_OID8;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_OBJECT,utmp16,cbData + (ntype ? 4 : 0));
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE },
+ {(ntype ? &TSize : NULL), (ntype ? 4 : 0), (ntype ? 1 : 0), U_LE },
+ {Data, cbData, 1, U_XE },
+ {NULL, (Pad ? Pad : 0), (Pad ? 1 : 0), (Pad ? U_XE : U_XX)}, /* Either 1-3 pad bytes or a terminator */
+ {NULL,0,0,U_XX} /* terminator, possibly a second in the list, which is harmless */
+ };
+ po = U_PMF_SERIAL_set(U_PMR_OBJECT_OID, List);
+ U_PO_free(&ph);
+ }
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_SERIALIZABLEOBJECT PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Siepb U_PSEUDO_OBJ containing a "Serialized image effects parameter block". One of the ImageEffects objects.
+
+ EMF+ manual 2.3.5.2, Microsoft name: EmfPlusSerializableObject Record, Index 0x38
+
+
+ This sets an ImageEffect in the renderer, which will be applied to the next EmfPlusDrawImagePoints
+ record that is encountered. The image effect is "consumed" by that EmfPlusDrawImagePoints record, resetting
+ the renderer to its original state.\n
+
+ WARNING! Windows XP Preview does not show filter effects, whether or not U_PPF_E is set. They are visible if the EMF+
+ file is inserted as an image into PowerPoint.
+
+*/
+U_PSEUDO_OBJ *U_PMR_SERIALIZABLEOBJECT_set(const U_PSEUDO_OBJ *Siepb){
+ if(!Siepb){ return(NULL); }
+ uint8_t *GUID = U_OID_To_GUID(Siepb->Type);
+ if(!GUID){ return(NULL); }
+ /* PO Used is size_t, might be 8 bytes, value in record must be 4 bytes */
+ uint32_t Used = Siepb->Used;
+ int Size = 16 + 4 + Siepb->Used;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SERIALIZABLEOBJECT,0,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {GUID, 16, 1, U_XE},
+ {&Used, 4, 1, U_LE},
+ {Siepb->Data, Siepb->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SERIALIZABLEOBJECT_OID, List);
+ U_PO_free(&ph);
+ free(GUID);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_SETANTIALIASMODE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param SMenum SmoothingMode enumeration
+ \param aatype Set: anti-aliasing on; Clear: anti-aliasing off
+
+
+ EMF+ manual 2.3.6.1, Microsoft name: EmfPlusSetAntiAliasMode Record, Index 0x1E
+*/
+U_PSEUDO_OBJ *U_PMR_SETANTIALIASMODE_set(int SMenum, int aatype){
+ int Size = 0;
+ uint16_t utmp16 = (aatype ? U_PPF_AA : 0) | (SMenum & U_FF_MASK_AA)<<U_FF_SHFT_AA;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETANTIALIASMODE,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETANTIALIASMODE_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_SETCOMPOSITINGMODE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param CMenum CompositingMode enumeration
+
+
+ EMF+ manual 2.3.6.2, Microsoft name: EmfPlusSetCompositingMode Record, Index 0x23
+*/
+U_PSEUDO_OBJ *U_PMR_SETCOMPOSITINGMODE_set(int CMenum){
+ int Size = 0;
+ uint16_t utmp16 = (CMenum & U_FF_MASK_CM)<<U_FF_SHFT_CM;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETCOMPOSITINGMODE,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETCOMPOSITINGMODE_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_SETCOMPOSITINGQUALITY PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param CQenum CompositingQuality enumeration
+
+
+ EMF+ manual 2.3.6.3, Microsoft name: EmfPlusSetCompositingQuality Record, Index 0x24
+*/
+U_PSEUDO_OBJ *U_PMR_SETCOMPOSITINGQUALITY_set(int CQenum){
+ int Size = 0;
+ uint16_t utmp16 = (CQenum & U_FF_MASK_CQ)<<U_FF_SHFT_CQ;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETCOMPOSITINGQUALITY,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETCOMPOSITINGQUALITY_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_SETINTERPOLATIONMODE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param IMenum InterpolationMode enumeration
+
+
+ EMF+ manual 2.3.6.4, Microsoft name: EmfPlusSetInterpolationMode Record, Index 0x21
+*/
+U_PSEUDO_OBJ *U_PMR_SETINTERPOLATIONMODE_set(int IMenum){
+ int Size = 0;
+ uint16_t utmp16 = (IMenum & U_FF_MASK_IM)<<U_FF_SHFT_IM;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETINTERPOLATIONMODE,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETINTERPOLATIONMODE_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_SETPIXELOFFSETMODE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param POMenum PixelOffsetMode enumeration
+
+
+ EMF+ manual 2.3.6.5, Microsoft name: EmfPlusSetPixelOffsetMode Record, Index 0x22
+*/
+U_PSEUDO_OBJ *U_PMR_SETPIXELOFFSETMODE_set(int POMenum){
+ int Size = 0;
+ uint16_t utmp16 = (POMenum & U_FF_MASK_PxOffM) << U_FF_SHFT_PxOffM;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETPIXELOFFSETMODE,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETPIXELOFFSETMODE_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_SETRENDERINGORIGIN PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param X X coordinate of rendering origin.
+ \param Y Y coordinate of rendering origin.
+
+
+ EMF+ manual 2.3.6.6, Microsoft name: EmfPlusSetRenderingOrigin Record, Index 0x1D
+*/
+U_PSEUDO_OBJ *U_PMR_SETRENDERINGORIGIN_set(int32_t X, int32_t Y){
+ int Size = 2*4;
+ uint16_t utmp16 = 0;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETRENDERINGORIGIN,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {&X, 4, 1, U_LE},
+ {&Y, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETRENDERINGORIGIN_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_SETTEXTCONTRAST PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param TGC Text Gamma correction value (x 1000).
+
+
+ EMF+ manual 2.3.6.7, Microsoft name: EmfPlusSetTextContrast Record, Index 0x20
+*/
+U_PSEUDO_OBJ *U_PMR_SETTEXTCONTRAST_set(int TGC){
+ int Size = 0;
+ uint16_t utmp16 = (TGC & U_FF_MASK_TGC) << U_FF_SHFT_TGC;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETTEXTCONTRAST,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETTEXTCONTRAST_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_SETTEXTRENDERINGHINT PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param TRHenum TextRenderingHint enumeration
+
+
+ EMF+ manual 2.3.6.8, Microsoft name: EmfPlusSetTextRenderingHint Record, Index 0x1F
+*/
+U_PSEUDO_OBJ *U_PMR_SETTEXTRENDERINGHINT_set(int TRHenum){
+ int Size = 0;
+ uint16_t utmp16 = (TRHenum & U_FF_MASK_TRH) << U_FF_SHFT_TRH;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETTEXTRENDERINGHINT,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETTEXTRENDERINGHINT_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_BEGINCONTAINER PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param UTenum UnitType enumeration
+ \param DstRect a U_PSEUDO_OBJ containing a U_PMF_RECTF object. with SrcRect specifies a transformation
+ \param SrcRect a U_PSEUDO_OBJ containing a U_PMF_RECTF object. with DstRect specifies a transformation
+ \param StackID EMF+ Object Stack Index to use for this graphics container
+
+
+ EMF+ manual 2.3.7.1, Microsoft name: EmfPlusBeginContainer Record, Index 0x27
+*/
+U_PSEUDO_OBJ *U_PMR_BEGINCONTAINER_set(int UTenum, U_PSEUDO_OBJ *DstRect, U_PSEUDO_OBJ *SrcRect, uint32_t StackID){
+ if(UTenum < U_UT_World || UTenum > U_UT_Millimeter){ return(NULL); }
+ if(!DstRect || (DstRect->Type != U_PMF_RECTF_OID)){ return(NULL); }
+ if(!SrcRect || (SrcRect->Type != U_PMF_RECTF_OID)){ return(NULL); }
+ int Size = DstRect->Used + SrcRect->Used + 4;
+ uint16_t utmp16 = (UTenum & U_FF_MASK_UT) << U_FF_SHFT_UT;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_BEGINCONTAINER,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {DstRect->Data, DstRect->Used, 1, U_XE},
+ {SrcRect->Data, SrcRect->Used, 1, U_XE},
+ {&StackID, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_BEGINCONTAINER_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_BEGINCONTAINERNOPARAMS PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param StackID EMF+ Object Stack Index to use for this graphics container
+
+
+ EMF+ manual 2.3.7.2, Microsoft name: EmfPlusBeginContainerNoParams Record, Index 0x28
+*/
+U_PSEUDO_OBJ *U_PMR_BEGINCONTAINERNOPARAMS_set(int StackID){
+ int Size = 4;
+ uint16_t utmp16 = 0;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_BEGINCONTAINERNOPARAMS,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {&StackID, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_BEGINCONTAINERNOPARAMS_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_ENDCONTAINER PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param StackID EMF+ Object Stack Index to use for this graphics container
+
+
+ EMF+ manual 2.3.7.3, Microsoft name: EmfPlusEndContainer Record, Index 0x29
+*/
+U_PSEUDO_OBJ *U_PMR_ENDCONTAINER_set(int StackID){
+ int Size = 4;
+ uint16_t utmp16 = 0;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_ENDCONTAINER,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {&StackID, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_ENDCONTAINER_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_RESTORE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param StackID EMF+ Graphics State Stack to restore from. Must have been put on the GSS with a U_PMR_SAVE.
+
+
+ EMF+ manual 2.3.7.4, Microsoft name: EmfPlusRestore Record, Index 0x26
+*/
+U_PSEUDO_OBJ *U_PMR_RESTORE_set(int StackID){
+ int Size = 4;
+ uint16_t utmp16 = 0;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_RESTORE,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {&StackID, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_RESTORE_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_SAVE PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param StackID EMF+ Graphics State Stack to restore from. Must have been put on the GSS with a U_PMR_SAVE.
+
+
+ EMF+ manual 2.3.7.5, Microsoft name: EmfPlusSave Record, Index 0x25
+*/
+U_PSEUDO_OBJ *U_PMR_SAVE_set(int StackID){
+ int Size = 4;
+ uint16_t utmp16 = 0;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SAVE,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {&StackID, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SAVE_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_SETTSCLIP PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Rects a U_PSEUDO_OBJ containing an array of U_PMF_RECT or U_PMF_RECTF objects.
+
+
+ EMF+ manual 2.3.8.1, Microsoft name: EmfPlusSetTSClip Record, Index 0x3A
+*/
+U_PSEUDO_OBJ *U_PMR_SETTSCLIP_set(U_PSEUDO_OBJ *Rects){
+ int ctype;
+ uint32_t Elements;
+ if(Rects){
+ if( Rects->Type == (U_PMF_RECT_OID | U_PMF_ARRAY_OID)){ ctype = 1; Elements = (Rects->Used - 4)/8; }
+ else if(Rects->Type == (U_PMF_RECTF_OID | U_PMF_ARRAY_OID)){ ctype = 0; Elements = (Rects->Used - 4)/16; }
+ else { return(NULL); }
+ }
+ else { return(NULL); }
+ int Size = Rects->Used; /* Rects includes Elements */
+ uint16_t utmp16 = (ctype ? U_PPF_K : 0) | (Elements & U_FF_MASK_TSC) << U_FF_SHFT_TSC;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETTSCLIP,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {Rects->Data, Rects->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETTSCLIP_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_SETTSGRAPHICS PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param vgatype Set: Palette is VGA basic colors; Clear: Palette is ???
+ \param Tsg A U_PMF_SETTSGRAPHICS object
+ \param Palette (optional) a U_PSEUDO_OBJ containing a U_PMF_PALETTE object.
+
+
+ EMF+ manual 2.3.8.2, Microsoft name: EmfPlusSetTSGraphics Record, Index 0x39
+*/
+U_PSEUDO_OBJ *U_PMR_SETTSGRAPHICS_set(int vgatype, U_PMF_SETTSGRAPHICS *Tsg, U_PSEUDO_OBJ *Palette){
+ if(!Tsg){ return(NULL); }
+ int Size = sizeof(U_PMF_SETTSGRAPHICS) + (Palette ? Palette->Used : 0);
+ uint16_t utmp16 = (vgatype ? U_PPF_VGA : 0) | (Palette ? U_PPF_PP : 0) ;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETTSGRAPHICS,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {&(Tsg->AntiAliasMode), 1, 1, U_XE},
+ {&(Tsg->TextRenderHint), 1, 1, U_XE},
+ {&(Tsg->CompositingMode), 1, 1, U_XE},
+ {&(Tsg->CompositingQuality), 1, 1, U_XE},
+ {&(Tsg->RenderOriginX), 2, 1, U_LE},
+ {&(Tsg->RenderOriginY), 2, 1, U_LE},
+ {&(Tsg->TextContrast), 2, 1, U_LE},
+ {&(Tsg->FilterType), 1, 1, U_XE},
+ {&(Tsg->PixelOffset), 1, 1, U_XE},
+ {&(Tsg->WorldToDevice), 4, 6, U_LE},
+ {(Palette ? Palette->Data : NULL), (Palette ? Palette->Used: 0), 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETTSGRAPHICS_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_MULTIPLYWORLDTRANSFORM PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param xmtype Set: Post multiply; Clear: Pre multiply
+ \param Tm a U_PSEUDO_OBJ containing a U_PMF_TRANSFORMMATRIX. (Transformation matrix)
+
+
+ EMF+ manual 2.3.9.1, Microsoft name: EmfPlusMultiplyWorldTransform Record, Index 0x2C
+*/
+U_PSEUDO_OBJ *U_PMR_MULTIPLYWORLDTRANSFORM_set(int xmtype, U_PSEUDO_OBJ *Tm){
+ if(!Tm || (Tm->Type != U_PMF_TRANSFORMMATRIX_OID)){ return(NULL); }
+ int Size = Tm->Used;
+ uint16_t utmp16 = (xmtype ? U_PPF_XM : 0);
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_MULTIPLYWORLDTRANSFORM,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {Tm->Data, Tm->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_MULTIPLYWORLDTRANSFORM_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_RESETWORLDTRANSFORM PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+
+
+ EMF+ manual 2.3.9.2, Microsoft name: EmfPlusResetWorldTransform Record, Index 0x2B
+*/
+U_PSEUDO_OBJ *U_PMR_RESETWORLDTRANSFORM_set(void){
+ int Size = 0;
+ uint16_t utmp16 = 0;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_RESETWORLDTRANSFORM,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_RESETWORLDTRANSFORM_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_ROTATEWORLDTRANSFORM PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param xmtype Set: Post multiply; Clear: Pre multiply
+ \param Angle Rotation angle, in degrees
+
+
+ EMF+ manual 2.3.9.3, Microsoft name: EmfPlusRotateWorldTransform Record, Index 0x2F
+*/
+U_PSEUDO_OBJ *U_PMR_ROTATEWORLDTRANSFORM_set(int xmtype, U_FLOAT Angle){
+ int Size = 4;
+ uint16_t utmp16 = (xmtype ? U_PPF_XM : 0);
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_ROTATEWORLDTRANSFORM,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {&Angle, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_ROTATEWORLDTRANSFORM_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_SCALEWORLDTRANSFORM PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param xmtype Set: Post multiply; Clear: Pre multiply
+ \param X Scale in X
+ \param Y Scale in Y
+
+ EMF+ manual 2.3.9.4, Microsoft name: EmfPlusScaleWorldTransform Record, Index 0x2E
+*/
+U_PSEUDO_OBJ *U_PMR_SCALEWORLDTRANSFORM_set(int xmtype, U_FLOAT X, U_FLOAT Y){
+ int Size = 2*4;
+ uint16_t utmp16 = (xmtype ? U_PPF_XM : 0);
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SCALEWORLDTRANSFORM,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {&X, 4, 1, U_LE},
+ {&Y, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SCALEWORLDTRANSFORM_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_SETPAGETRANSFORM PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param PUenum Page Unit, in UnitType enumeration
+ \param Scale Scale factor to convert page space to device space
+
+
+
+ EMF+ manual 2.3.9.5, Microsoft name: EmfPlusSetPageTransform Record, Index 0x30
+
+ Defines Page Space -> Device Space transformation
+*/
+U_PSEUDO_OBJ *U_PMR_SETPAGETRANSFORM_set(int PUenum, U_FLOAT Scale){
+ int Size = 4;
+ uint16_t utmp16 = (PUenum & U_FF_MASK_PU) << U_FF_SHFT_PU;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETPAGETRANSFORM,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {&Scale, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETPAGETRANSFORM_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_SETWORLDTRANSFORM PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param Tm a U_PSEUDO_OBJ containing a U_PMF_TRANSFORMMATRIX. (Transformation matrix)
+
+
+
+ EMF+ manual 2.3.9.6, Microsoft name: EmfPlusSetWorldTransform Record, Index 0x2A
+
+ Defines World Space -> Page Space transformation
+*/
+U_PSEUDO_OBJ *U_PMR_SETWORLDTRANSFORM_set(U_PSEUDO_OBJ *Tm){
+ if(!Tm || (Tm->Type != U_PMF_TRANSFORMMATRIX_OID)){ return(NULL); }
+ int Size = Tm->Used;
+ uint16_t utmp16 = 0;
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_SETWORLDTRANSFORM,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {Tm->Data, Tm->Used, 1, U_XE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_SETWORLDTRANSFORM_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/**
+ \brief Create and set a U_PMR_TRANSLATEWORLDTRANSFORM PseudoObject
+ \return Pointer to PseudoObject, NULL on error
+ \param xmtype Set: Post multiply; Clear: Pre multiply
+ \param Dx X offset
+ \param Dy Y offset
+
+
+ EMF+ manual 2.3.9.7, Microsoft name: EmfPlusTranslateWorldTransform Record, Index 0x2D
+*/
+U_PSEUDO_OBJ *U_PMR_TRANSLATEWORLDTRANSFORM_set(int xmtype, U_FLOAT Dx, U_FLOAT Dy){
+ int Size = 2*4;
+ uint16_t utmp16 = (xmtype ? U_PPF_XM : 0);
+ U_PSEUDO_OBJ *ph = U_PMR_CMN_HDR_set(U_PMR_TRANSLATEWORLDTRANSFORM,utmp16,Size);
+ const U_SERIAL_DESC List[] = {
+ {ph->Data, ph->Used, 1, U_XE},
+ {&Dx, 4, 1, U_LE},
+ {&Dy, 4, 1, U_LE},
+ {NULL,0,0,U_XX}
+ };
+ U_PSEUDO_OBJ *po = U_PMF_SERIAL_set(U_PMR_TRANSLATEWORLDTRANSFORM_OID, List);
+ U_PO_free(&ph);
+ return(po);
+}
+
+/*
+
+ end of U_PMF_*_set() functions
+ =====================================================================================
+ start of U_PMF_*_get() functions
+
+ These functions all take a blimit value so that they can check if the data description in the fields
+ they process extend beyond the end of the record.
+
+*/
+
+
+//! \cond
+/* core _get functions, not accessed outside of this routine */
+
+/* get copies of up to 0-6 consecutive 4 byte values and a pointer to the rest */
+int U_PMF_CORE1_get(const char *contents, void *v1, void *v2, void *v3, void *v4, void *v5, void *v6, const char **vR){
+ if(v1){ U_PMF_MEMCPY_SRCSHIFT(v1, &contents, 4);
+ if(v2){ U_PMF_MEMCPY_SRCSHIFT(v2, &contents, 4);
+ if(v3){ U_PMF_MEMCPY_SRCSHIFT(v3, &contents, 4);
+ if(v4){ U_PMF_MEMCPY_SRCSHIFT(v4, &contents, 4);
+ if(v5){ U_PMF_MEMCPY_SRCSHIFT(v5, &contents, 4);
+ if(v6){ U_PMF_MEMCPY_SRCSHIFT(v6, &contents, 4); }}}}}}
+ if(vR){ *vR = contents; }
+ return(1);
+}
+//! \endcond
+
+
+/**
+ \brief Get data from a U_PMF_BRUSH object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Version EmfPlusGraphicsVersion object
+ \param Type BrushType Enumeration
+ \param Data one of the 5 types of Brush data
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.1.1, Microsoft name: EmfPlusBrush Object
+
+ Caller must check Data for possible memory access violations.
+*/
+int U_PMF_BRUSH_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data, const char *blimit){
+ if(!contents || !Version || !Type || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents,sizeof(U_PMF_BRUSH), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Type, 4, 1, U_LE);
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_CUSTOMLINECAP object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Version EmfPlusGraphicsVersion object
+ \param Type CustomLineCapData Enumeration
+ \param Data one of the 2 types of Linecap data
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.1.2, Microsoft name: EmfPlusCustomLineCap Object
+
+ Caller must check Data for possible memory access violations.
+*/
+int U_PMF_CUSTOMLINECAP_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data, const char *blimit){
+ if(!contents || !Version || !Type || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_CUSTOMLINECAP), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Type, 4, 1, U_LE);
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_FONT object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Version EmfPlusGraphicsVersion object
+ \param EmSize em size in units of SizeUnit
+ \param SizeUnit UnitType enumeration
+ \param FSFlags FontStyle flags
+ \param Length Number of Unicode Characters in FamilyName
+ \param Data Unicode (UTF-16LE) name of font family
+
+ EMF+ manual 2.2.1.3, Microsoft name: EmfPlusFont Object
+
+ Caller must check Data for possible memory access violations.
+*/
+int U_PMF_FONT_get(const char *contents, uint32_t *Version, U_FLOAT *EmSize, uint32_t *SizeUnit,
+ int32_t *FSFlags, uint32_t *Length, const char **Data, const char *blimit){
+ if(!contents || !Version || !EmSize || !SizeUnit || !FSFlags || !Length || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_FONT), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, EmSize, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, SizeUnit, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, FSFlags, 4, 1, U_LE);
+ contents += 4; /* Reserved field, which is ignored */
+ U_PMF_SERIAL_get(&contents, Length, 4, 1, U_LE);
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ return(1);
+}
+
+
+/**
+ \brief Get data from a U_PMF_IMAGE object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Version EmfPlusGraphicsVersion object
+ \param Type ImageDataType Enumeration
+ \param Data one of the 2 types of image data
+
+ EMF+ manual 2.2.1.4, Microsoft name: EmfPlusImage Object
+
+ Caller must check Data for possible memory access violations.
+*/
+int U_PMF_IMAGE_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data, const char *blimit){
+ if(!contents || !Version || !Type || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IMAGE), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Type, 4, 1, U_LE);
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_IMAGEATTRIBUTES object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Version EmfPlusGraphicsVersion object
+ \param WrapMode WrapMode object
+ \param ClampColor EmfPlusARGB object
+ \param ObjectClamp ObjectClamp Identifiers
+
+ EMF+ manual 2.2.1.5, Microsoft name: EmfPlusImageAttributes Object
+*/
+int U_PMF_IMAGEATTRIBUTES_get(const char *contents, uint32_t *Version, uint32_t *WrapMode, uint32_t *ClampColor,
+ uint32_t *ObjectClamp, const char *blimit){
+ if(!contents || !Version || !WrapMode || !ClampColor || !ObjectClamp || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IMAGEATTRIBUTES), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE);
+ contents += 4; /* Skip Reserved 1*/
+ U_PMF_SERIAL_get(&contents, WrapMode, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, ClampColor, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, ObjectClamp,4, 1, U_LE);
+ /* Skip Reserved 2*/
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_PATH object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Version EmfPlusGraphicsVersion object
+ \param Count Number of points and point types in this object
+ \param Flags PathPoint Flags
+ \param Points array of points type PMFPointR, PMFPoint, or PMFPointF
+ \param Types array of U_PMF_PATHPOINTTYPERLE and/or U_PMF_PATHPOINTTYPE
+
+ EMF+ manual 2.2.1.6, Microsoft name: EmfPlusPath Object
+
+ Caller must check Types for possible memory access violations if type can be U_PMF_PATHPOINTTYPERLE.
+*/
+int U_PMF_PATH_get(const char *contents, uint32_t *Version, uint32_t *Count, uint16_t *Flags,
+ const char **Points, const char **Types, const char *blimit){
+ if(!contents || !Version || !Count || !Flags || !Points || !Types || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_PATH), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Count, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Flags, 2, 1, U_LE);
+ contents+=2; /* reserved */
+ uint32_t sizeP, sizeT;
+ if(*Flags & U_PPF_P){
+ sizeP = U_PMF_LEN_REL715(contents,*Count); //DEBUG
+ printf("DEBUG U_PMF_PATH_get count:%d LENREL715:%d\n",*Count,sizeP);fflush(stdout);
+ }
+ else if(*Flags & U_PPF_C){ sizeP = *Count * sizeof(U_PMF_POINT); }
+ else { sizeP = *Count * sizeof(U_PMF_POINTF); }
+ if(IS_MEM_UNSAFE(contents, sizeP, blimit))return(0);
+ U_PMF_PTRSAV_SHIFT(Points, &contents, 0);
+ contents += sizeP;
+ /* this limit is correct if there are only U_PMF_PATHPOINTTYPE PointTypes, it is a lower bound if
+ there can also be U_PMF_PATHPOINTTYPERLE */
+ sizeT = *Count * sizeof(U_PMF_PATHPOINTTYPE);
+ if(IS_MEM_UNSAFE(contents, sizeT, blimit))return(0);
+ U_PMF_PTRSAV_SHIFT(Types, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_PEN object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Version EmfPlusGraphicsVersion object
+ \param Type must be zero
+ \param PenData Pen description
+ \param Brush Brush Description
+
+ EMF+ manual 2.2.1.7, Microsoft name: EmfPlusPen Object
+
+ Caller must check Brush and PenData for possible memory access violations.
+*/
+int U_PMF_PEN_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **PenData, const char **Brush, const char *blimit){
+ if(!contents || !Type || !PenData || !Brush || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_PEN), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Type, 4, 1, U_LE);
+ U_PMF_PTRSAV_SHIFT(PenData, &contents, 0);
+ *Brush = *PenData + U_PMF_LEN_PENDATA(*PenData);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_REGION object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Version EmfPlusGraphicsVersion object
+ \param Count Number of CHILD nodes. This is one less than the total number of U_PMF_REGIONNODE objects in Nodes.
+ \param Nodes Nodes defining region
+
+ EMF+ manual 2.2.1.8, Microsoft name: EmfPlusRegion Object
+*/
+int U_PMF_REGION_get(const char *contents, uint32_t *Version, uint32_t *Count, const char **Nodes, const char *blimit){
+ if(!contents || !Version || !Count || !Nodes || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_REGION), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Count, 4, 1, U_LE);
+ U_PMF_PTRSAV_SHIFT(Nodes, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_STRINGFORMAT object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Sfs pointer to U_PMF_STRINGFORMAT structure, with no variable part
+ \param Data pointer to variable part
+
+ EMF+ manual 2.2.1.9, Microsoft name: EmfPlusStringFormat Object
+*/
+int U_PMF_STRINGFORMAT_get(const char *contents, U_PMF_STRINGFORMAT *Sfs, const char **Data, const char *blimit){
+ if(!contents || !Sfs || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_STRINGFORMAT), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Sfs, 4, 15, U_LE);
+ *Data = contents;
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_ARGB object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Blue Blue color (0-255)
+ \param Green Green color (0-255)
+ \param Red Red color (0-255)
+ \param Alpha Alpha (0-255)
+
+ EMF+ manual 2.2.2.1, Microsoft name: EmfPlusARGB Object
+*/
+int U_PMF_ARGB_get(const char *contents, uint8_t *Blue, uint8_t *Green, uint8_t *Red, uint8_t *Alpha, const char *blimit){
+ if(!contents || !Blue || !Green || !Red || !Alpha || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_ARGB), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Blue, 1, 1, U_XE);
+ U_PMF_SERIAL_get(&contents, Green, 1, 1, U_XE);
+ U_PMF_SERIAL_get(&contents, Red, 1, 1, U_XE);
+ U_PMF_SERIAL_get(&contents, Alpha, 1, 1, U_XE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_BITMAP object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Bs pointer to U_PMF_BITMAP structure, with no variable part
+ \param Data pointer to variable part
+
+ EMF+ manual 2.2.2.2, Microsoft name: EmfPlusBitmap Object
+
+ Caller must check Data for possible memory access violations.
+*/
+int U_PMF_BITMAP_get(const char *contents, U_PMF_BITMAP *Bs, const char **Data, const char *blimit){
+ if(!contents || !Bs || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_BITMAP), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Bs, 4, 5, U_LE); // width, height, stride, pixelformat, type
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0); // bitmapdata
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_BITMAPDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Ps pointer to U_PMF_PALETTE structure, with no variable part
+ \param Colors Color part of U_PMF_PALETTE object
+ \param Data An array of bytes, meaning depends on fields in U_PMF_BITMAP object and the PixelFormat enumeration.
+
+ EMF+ manual 2.2.2.3, Microsoft name: EmfPlusBitmapData Object
+
+ Caller must check Data for possible memory access violations.
+*/
+int U_PMF_BITMAPDATA_get(const char *contents, U_PMF_PALETTE *Ps, const char **Colors, const char **Data, const char *blimit){
+ if(!contents || !Ps || !Colors || !Data || !blimit){ return(0); }
+ /* this structure is entirely optional */
+ if(IS_MEM_UNSAFE(contents, 4*2, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Ps, 4, 2, U_LE);
+ U_PMF_PTRSAV_SHIFT(Colors, &contents, Ps->Elements * sizeof(U_PMF_ARGB));
+ /* difficult to know how big the actual bitmap will be, just return the pointer to it untested */
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_BLENDCOLORS object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Elements Number of members in Positions and Colors
+ \param Positions Caller must free. Pointer to memory holding positions along gradient line.
+ \param Colors Caller must NOT free memory, Pointer to memory holding colors at positions on gradient line.
+
+ EMF+ manual 2.2.2.4, Microsoft name: EmfPlusBlendColors Object
+*/
+int U_PMF_BLENDCOLORS_get(const char *contents, uint32_t *Elements, U_FLOAT **Positions, const char **Colors, const char *blimit){
+ if(!contents || !Positions || !Colors || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_BLENDCOLORS), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ if(IS_MEM_UNSAFE(contents, *Elements * 4, blimit))return(0);
+ if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)Positions, 4, *Elements, U_LE,1)){ return(0); }
+ U_PMF_PTRSAV_SHIFT(Colors, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_BLENDFACTORS object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Elements members in each array
+ \param Positions Caller must free. Pointer to memory holding positions along gradient line.
+ \param Factors Caller must free. Pointer to memory holding blending factors, 0.0->1.0 values, inclusive along gradient line.
+
+ EMF+ manual 2.2.2.5, Microsoft name: EmfPlusBlendFactors Object
+*/
+int U_PMF_BLENDFACTORS_get(const char *contents, uint32_t *Elements, U_FLOAT **Positions, U_FLOAT **Factors, const char *blimit){
+ if(!contents || !Elements || !Positions || !Factors || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_BLENDFACTORS), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ if(IS_MEM_UNSAFE(contents, *Elements * 4 * 2, blimit))return(0);
+ if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)Positions, 4, *Elements, U_LE, 1)){ return(0); }
+ if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)Factors, 4, *Elements, U_LE, 1)){
+ free(*Positions);
+ return(0);
+ }
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_BOUNDARYPATHDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Size bytes in Data
+ \param Data boundary of the brush
+
+ EMF+ manual 2.2.2.6, Microsoft name: EmfPlusBoundaryPathData Object
+
+ Caller must check Data for possible memory access violations.
+*/
+int U_PMF_BOUNDARYPATHDATA_get(const char *contents, int32_t *Size, const char **Data, const char *blimit){
+ if(!contents || !Size || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_BOUNDARYPATHDATA), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE);
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_BOUNDARYPOINTDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Elements Members in Points
+ \param Points Caller must free. Pointer to memory holding points along gradient line. Boundary of the brush.
+
+ EMF+ manual 2.2.2.7, Microsoft name: EmfPlusBoundaryPointData Object
+*/
+int U_PMF_BOUNDARYPOINTDATA_get(const char *contents, int32_t *Elements, U_PMF_POINTF **Points, const char *blimit){
+ if(!contents || !Elements || !Points || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_BOUNDARYPOINTDATA), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ if(IS_MEM_UNSAFE(contents, *Elements * 2, blimit))return(0);
+ if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)Points, 4, *Elements * 2, U_LE, 1)){ return(0); }
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_CHARACTERRANGE object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param First First position in range
+ \param Length Range length
+
+ EMF+ manual 2.2.2.8, Microsoft name: EmfPlusCharacterRange Object
+*/
+int U_PMF_CHARACTERRANGE_get(const char *contents, int32_t *First, int32_t *Length, const char *blimit){
+ if(!contents || !First || !Length || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_CHARACTERRANGE), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, First, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Length, 4, 1, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_COMPOUNDLINEDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Elements Members in the array
+ \param Widths Caller must free. Pointer to memory holding Line or gap widths (0.0 <-> 1.0, fraction of total line width ).
+
+ EMF+ manual 2.2.2.9, Microsoft name: EmfPlusCompoundLineData Object
+*/
+int U_PMF_COMPOUNDLINEDATA_get(const char *contents, int32_t *Elements, U_FLOAT **Widths, const char *blimit){
+ if(!contents || !Elements || !Widths || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_COMPOUNDLINEDATA), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ if(IS_MEM_UNSAFE(contents, *Elements * sizeof(U_FLOAT), blimit))return(0);
+ *Widths = (U_FLOAT *)malloc(*Elements * sizeof(U_FLOAT));
+ if(!*Widths){ return(0); }
+ U_PMF_SERIAL_get(&contents, *Widths, 4, *Elements, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_COMPRESSEDIMAGE object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Data Stored image in one of the supported formats.
+
+ EMF+ manual 2.2.2.10, Microsoft name: EmfPlusCompressedImage Object
+
+
+ This function does not do anything useful, but it is included so that all objects have a corresponding _get().
+
+ Caller must check Data for possible memory access violations.
+*/
+int U_PMF_COMPRESSEDIMAGE_get(const char *contents, const char **Data, const char *blimit){
+ if(!contents || !Data || !blimit){ return(0); }
+ if(contents >= blimit)return(0);
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_CUSTOMENDCAPDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Size Bytes in Data
+ \param Data Description of linecap
+
+ EMF+ manual 2.2.2.11, Microsoft name: EmfPlusCustomEndCapData Object
+
+ Caller must check Data for possible memory access violations.
+*/
+int U_PMF_CUSTOMENDCAPDATA_get(const char *contents, int32_t *Size, const char **Data, const char *blimit){
+ if(!contents || !Size || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_CUSTOMENDCAPDATA), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE);
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_CUSTOMLINECAPARROWDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Ccad pointer to U_PMF_CUSTOMLINECAPARROWDATA structure
+
+ EMF+ manual 2.2.2.12, Microsoft name: EmfPlusCustomLineCapArrowData Object
+*/
+int U_PMF_CUSTOMLINECAPARROWDATA_get(const char *contents, U_PMF_CUSTOMLINECAPARROWDATA *Ccad, const char *blimit){
+ if(!contents || !Ccad || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_CUSTOMLINECAPARROWDATA), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Ccad, 4, 13, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_CUSTOMLINECAPDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Clcd pointer to U_PMF_CUSTOMLINECAPDATA structure, with no variable part
+ \param Data variable part of U_PMF_CUSTOMLINECAPDATA
+
+ EMF+ manual 2.2.2.13, Microsoft name: EmfPlusCustomLineCapData Object
+
+ Caller must check Data for possible memory access violations.
+*/
+int U_PMF_CUSTOMLINECAPDATA_get(const char *contents, U_PMF_CUSTOMLINECAPDATA *Clcd, const char **Data, const char *blimit){
+ if(!contents || !Clcd || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_CUSTOMLINECAPDATA), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Clcd, 4, 12, U_LE);
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_CUSTOMLINECAPOPTIONALDATA object
+ \return on success 3,5, or 7 (for varying combinations of data present) or 1 (no data is present), 0 on error
+ \param contents Record from which to extract data
+ \param Flags bits set to indicate the presence of FillData and/or LineData
+ \param FillData Path to fill (optional)
+ \param LineData Path to stroke (optional)
+
+ EMF+ manual 2.2.2.14, Microsoft name: EmfPlusCustomLineCapOptionalData Object
+
+ Caller must check LineData for possible memory access violations.
+*/
+int U_PMF_CUSTOMLINECAPOPTIONALDATA_get(const char *contents, uint32_t Flags, const char **FillData, const char **LineData, const char *blimit){
+ uint32_t length;
+ int status = 1;
+ if(!contents || !*FillData || !*LineData || !blimit){ return(0); }
+ /* this structure is entirely optional */
+ if(Flags & U_CLCD_FillPath){
+ if(!FillData){ return(0); }
+ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, &length, 4, 1, U_LE);
+ if(IS_MEM_UNSAFE(contents, length, blimit))return(0);
+ contents -= 4; /* undo the unneeded shift from preceding */
+ U_PMF_PTRSAV_SHIFT(FillData, &contents, 4 + length);
+ status += 2;
+ }
+ else { *FillData = NULL; }
+
+ if(Flags & U_CLCD_LinePath){
+ if(!LineData){ return(0); }
+ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, &length, 4, 1, U_LE);
+ if(IS_MEM_UNSAFE(contents, length, blimit))return(0);
+ contents -= 4; /* undo the unneeded shift from preceding */
+ U_PMF_PTRSAV_SHIFT(LineData, &contents, 0);
+ status += 4;
+ }
+ else { *LineData = NULL; }
+ return(status);
+}
+
+/**
+ \brief Get data from a U_PMF_CUSTOMSTARTCAPDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Size Bytes in Data
+ \param Data Description of linecap
+
+ EMF+ manual 2.2.2.15, Microsoft name: EmfPlusCustomStartCapData Object
+
+ Caller must check Data for possible memory access violations.
+*/
+int U_PMF_CUSTOMSTARTCAPDATA_get(const char *contents, int32_t *Size, const char **Data, const char *blimit){
+ if(!contents || !Size || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_CUSTOMSTARTCAPDATA), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE);
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_DASHEDLINEDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Elements Members in the array
+ \param Lengths Caller must free. Pointer to memory holding lengths of dashes and spaces.
+
+ EMF+ manual 2.2.2.16, Microsoft name: EmfPlusDashedLineData Object
+*/
+int U_PMF_DASHEDLINEDATA_get(const char *contents, int32_t *Elements, U_FLOAT **Lengths, const char *blimit){
+ if(!contents || !Elements || !Lengths || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_DASHEDLINEDATA), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ if(IS_MEM_UNSAFE(contents, *Elements * sizeof(U_FLOAT), blimit))return(0);
+ *Lengths = (U_FLOAT *)malloc(*Elements * sizeof(U_FLOAT));
+ if(!*Lengths){ return(0); }
+ U_PMF_SERIAL_get(&contents, *Lengths, 4, *Elements, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_FILLPATHOBJ object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Size Bytes in Data
+ \param Data Path specification
+
+ EMF+ manual 2.2.2.17, Microsoft name: EmfPlusFillPath Object
+
+ Caller must check Data for possible memory access violations.
+*/
+int U_PMF_FILLPATHOBJ_get(const char *contents, int32_t *Size, const char **Data, const char *blimit){
+ if(!contents || !Size || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_FILLPATHO), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE);
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_FOCUSSCALEDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Count must be 2
+ \param ScaleX value 0.0 <-> 1.0
+ \param ScaleY value 0.0 <-> 1.0
+
+ EMF+ manual 2.2.2.18, Microsoft name: EmfPlusFocusScaleData Object
+*/
+int U_PMF_FOCUSSCALEDATA_get(const char *contents, uint32_t *Count, U_FLOAT *ScaleX, U_FLOAT *ScaleY, const char *blimit){
+ if(!contents || !Count || !ScaleX || !ScaleY || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_FOCUSSCALEDATA), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Count, 4, 1, U_LE);
+ if(*Count != 2){ return(0); }
+ U_PMF_SERIAL_get(&contents, ScaleX, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, ScaleY, 4, 1, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_GRAPHICSVERSION object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Signature Must be U_GFVR_PMF (0xDBC01)
+ \param GrfVersion GraphicsVersion enumeration
+
+ EMF+ manual 2.2.2.19, Microsoft name: EmfPlusGraphicsVersion Object
+*/
+int U_PMF_GRAPHICSVERSION_get(const char *contents, int *Signature, int *GrfVersion, const char *blimit){
+ uint32_t tmp;
+ if(!contents || !Signature || !GrfVersion || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_GRAPHICSVERSION), blimit))return(0);
+ memcpy(&tmp, contents, 4);
+ *Signature = tmp >> 12;
+ *GrfVersion = tmp & U_GFVR_MASKLO;
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_HATCHBRUSHDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Style HatchStyle enumeration
+ \param Foreground Hatch pattern line color
+ \param Background Hatch pattern bkground color
+
+ EMF+ manual 2.2.2.20, Microsoft name: EmfPlusHatchBrushData Object
+*/
+int U_PMF_HATCHBRUSHDATA_get(const char *contents, uint32_t *Style, U_PMF_ARGB *Foreground, U_PMF_ARGB *Background, const char *blimit){
+ if(!contents || !Style || !Foreground || !Background || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_HATCHBRUSHDATA), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Style, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Foreground, 4, 1, U_XE);
+ U_PMF_SERIAL_get(&contents, Background, 4, 1, U_XE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_INTEGER7 object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Value 7 bit signed integer (stored in an integer)
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.21, Microsoft name: EmfPlusInteger7 Object
+*/
+int U_PMF_INTEGER7_get(const char **contents, U_FLOAT *Value, const char *blimit){
+ uint8_t tmp;
+ if(!contents || !*contents || !Value || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(*contents, 1, blimit))return(0); /* past end of buffer */
+ if(**contents & U_TEST_INT7)return(0); /* this bit must be 0 in this object type */
+ U_PMF_SERIAL_get(contents, &tmp, 1, 1, U_XE);
+ if(tmp & U_SIGN_INT7){
+ tmp |= U_TEST_INT7; /* now it has the bit pattern of a signed int8_t */
+ *Value = *(int8_t *)&tmp;
+ }
+ else {
+ *Value = tmp;
+ }
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_INTEGER15 object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Value 15 bit signed integer (stored in an integer)
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.22, Microsoft name: EmfPlusInteger15 Object
+*/
+int U_PMF_INTEGER15_get(const char **contents, U_FLOAT *Value, const char *blimit){
+ if(!contents || !*contents || !Value || !blimit){ return(0); }
+ uint16_t tmp;
+ if(IS_MEM_UNSAFE(*contents, 2, blimit))return(0); /* past end of buffer */
+ if(!(**contents & U_TEST_INT7))return(0); /* this bit must be 1 in this object type */
+ U_PMF_SERIAL_get(contents, &tmp, 2, 1, U_BE);
+ tmp &= U_MASK_INT15; /* drop the 7/15 flag from the most significant bit */
+ if(tmp & U_SIGN_INT15){
+ tmp |= U_TEST_INT15; /* now it has the bit pattern of a signed int16_t */
+ *Value = *(int16_t *)&tmp;
+ }
+ else {
+ *Value = tmp;
+ }
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_LANGUAGEIDENTIFIER object
+ \return 1 on success, 0 on error
+ \param LId U_PMF_LANGUAGEIDENTIFIER from which to extract data
+ \param SubLId Example: code for USA
+ \param PriLId Example: code for English
+
+
+
+ EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier Object
+
+ This type is defined as 16 bits in the manual section, but it is only ever used as part of a 32 bit field!
+*/
+int U_PMF_LANGUAGEIDENTIFIER_get(U_PMF_LANGUAGEIDENTIFIER LId, int *SubLId, int *PriLId){
+ if(!SubLId || !PriLId){ return(0); }
+ *SubLId = (LId >> U_FF_SHFT_SUBLID ) & U_FF_MASK_SUBLID;
+ *PriLId = (LId >> U_FF_SHFT_PRILID ) & U_FF_MASK_PRILID;
+ /* 16 bits above that are not used */
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_LINEARGRADIENTBRUSHDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Lgbd U_PMF_LINEARGRADIENTBRUSHDATA structure, with no variable part
+ \param Data variable part of U_PMF_LINEARGRADIENTBRUSHDATA
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.24, Microsoft name: EmfPlusLinearGradientBrushData Object
+
+ Caller must check Data for possible memory access violations.
+*/
+int U_PMF_LINEARGRADIENTBRUSHDATA_get(const char *contents, U_PMF_LINEARGRADIENTBRUSHDATA *Lgbd, const char **Data, const char *blimit){
+ if(!contents || !Lgbd || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_LINEARGRADIENTBRUSHDATA), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Lgbd, 4, 6, U_LE); /* Flags, WrapMode, RectF*/
+ U_PMF_SERIAL_get(&contents, &(Lgbd->StartColor), 4, 4, U_XE); /* StartColor, EndColor, Reserved1 & 2 */
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Flags BrushData flags - indicates which of the following date fields are present.
+ \param Tm Transformation matrix
+ \param Bc U_PMF_BLENDCOLORS object or NULL
+ \param BfH U_PMF_BLENDFACTORS (H) object or NULL
+ \param BfV U_PMF_BLENDFACTORS (V) object or NULL (WARNING, GDI+ defines this field but does not render it. DO NOT USE.)
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.25, Microsoft name: EmfPlusLinearGradientBrushOptionalData Object
+
+*/
+int U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_get(const char *contents, uint32_t Flags, U_PMF_TRANSFORMMATRIX *Tm,
+ const char **Bc, const char **BfH, const char **BfV, const char *blimit){
+ uint32_t Elements;
+ if(!contents || !Tm|| !Bc || !BfH || !BfV || !blimit){ return(0); }
+ /* all of the fields are optional! */
+ *Bc = *BfH = *BfV = NULL;
+ if(Flags & U_BD_Transform){
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_ROTMATRIX), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Tm, 4, 6, U_LE);
+ }
+ if(Flags & U_BD_PresetColors){
+ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, &Elements, 4, 1, U_LE); /* starts with a 4 byte count*/
+ if(IS_MEM_UNSAFE(contents, Elements * ( sizeof(U_FLOAT) + sizeof(U_PMF_ARGB)), blimit))return(0);
+ contents-=4; /* back up to the front of the count, as it is part of the data field */
+ U_PMF_PTRSAV_SHIFT(Bc, &contents, 0);
+ }
+ else if(Flags & U_BD_BlendFactorsH){
+ U_PMF_SERIAL_get(&contents, &Elements, 4, 1, U_LE); /* starts with a 4 byte count*/
+ if(IS_MEM_UNSAFE(contents, Elements * 2 * sizeof(U_FLOAT), blimit))return(0);
+ contents-=4; /* back up to the front of the count, as it is part of the data field */
+ U_PMF_PTRSAV_SHIFT(BfH, &contents, 4 + (Elements * 2 * sizeof(U_FLOAT))); /* 4 byte count + 2 * 4bytes * Elements */
+ if(Flags & U_BD_BlendFactorsV){
+ if(IS_MEM_UNSAFE(contents, Elements * 2 * sizeof(U_FLOAT), blimit))return(0);
+ U_PMF_PTRSAV_SHIFT(BfV, &contents, 0);
+ }
+ }
+ else if(Flags & U_BD_BlendFactorsV){
+ U_PMF_SERIAL_get(&contents, &Elements, 4, 1, U_LE); /* starts with a 4 byte count*/
+ if(IS_MEM_UNSAFE(contents, Elements * 2 * sizeof(U_FLOAT), blimit))return(0);
+ contents-=4; /* back up to the front of the count, as it is part of the data field */
+ U_PMF_PTRSAV_SHIFT(BfV, &contents, 0);
+ }
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_LINEPATH object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Size Bytes in Data
+ \param Data Outline path
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.26, Microsoft name: EmfPlusLinePath Object
+
+ Caller must check Data for possible memory access violations.
+*/
+int U_PMF_LINEPATH_get(const char *contents, int32_t *Size, const char **Data, const char *blimit){
+ if(!contents || !Size || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_LINEPATH), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE);
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_METAFILE object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Type
+ \param Size Bytes in Data
+ \param Data Various types of data, like an EMF metafile, WMF metafile, another EMF+ metafile
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.27, Microsoft name: EmfPlusMetafile Object
+
+ Caller must check Data for possible memory access violations.
+*/
+int U_PMF_METAFILE_get(const char *contents, uint32_t *Type, uint32_t *Size, const char **Data, const char *blimit){
+ if(!contents || !Type || !Size || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_METAFILE), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, &Type, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, &Size, 4, 1, U_LE);
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_PALETTE object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Flags PaletteStyle flags
+ \param Elements Members in the array
+ \param Colors Palette data (array of colors)
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.28, Microsoft name: EmfPlusPalette Object
+*/
+int U_PMF_PALETTE_get(const char *contents, uint32_t *Flags, uint32_t *Elements, const char **Colors, const char *blimit){
+ if(!contents || !Flags || !Elements || !Colors || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_PALETTE), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, &Flags, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, &Elements, 4, 1, U_LE);
+ if(IS_MEM_UNSAFE(contents, *Elements*sizeof(U_RGBQUAD), blimit))return(0);
+ U_PMF_PTRSAV_SHIFT(Colors, &contents, 0);
+ return(1);
+
+}
+
+/**
+ \brief Get data from a U_PMF_PATHGRADIENTBRUSHDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Pgbd constant part of U_PMF_PATHGRADIENTBRUSHDATA object
+ \param Gradient variable part of U_PMF_LINEARGRADIENTBRUSHDATA, Color Gradient with Elements members
+ \param Boundary variable part of U_PMF_LINEARGRADIENTBRUSHDATA, U_PMF_BOUNDARYPATHDATA object if BrushDataPath bit set in Flag, else U_PMF_BOUNDARYPOINTDATA object
+ \param Data variable part of U_PMF_LINEARGRADIENTBRUSHDATA, exact composition depends on Flags
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.29, Microsoft name: EmfPlusPathGradientBrushData Object
+
+ Caller must check Data for possible memory access violations.
+
+*/
+int U_PMF_PATHGRADIENTBRUSHDATA_get(const char *contents, U_PMF_PATHGRADIENTBRUSHDATA *Pgbd, const char **Gradient,
+ const char **Boundary, const char **Data, const char *blimit){
+ if(!contents || !Pgbd || !Gradient || !Boundary || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_PATHGRADIENTBRUSHDATA), blimit))return(0);
+ uint32_t Size;
+ U_PMF_SERIAL_get(&contents, Pgbd, 4, 2, U_LE); /* Flags and WrapMode*/
+ U_PMF_SERIAL_get(&contents, &(Pgbd->CenterColor), 4, 1, U_XE);
+ U_PMF_SERIAL_get(&contents, &(Pgbd->Center), 4, 3, U_LE); /* Center and Elements */
+ if(IS_MEM_UNSAFE(contents, Pgbd->Elements * sizeof(U_PMF_ARGB), blimit))return(0);
+ U_PMF_PTRSAV_SHIFT(Gradient, &contents, Pgbd->Elements * sizeof(U_PMF_ARGB));
+ U_PMF_PTRSAV_SHIFT(Boundary, &contents, 0);
+ U_PMF_SERIAL_get(&contents, &Size, 4, 1, U_LE); /* The first 4 bytes of the Boundary are always a size */
+ if(Pgbd->Flags & U_BD_Path){ contents += Size; } // U_PMF_BOUNDARYPATHDATA
+ else { contents += Size*2*sizeof(U_FLOAT); } // U_PMF_BOUNDARYPOINTDATA
+ if(Pgbd->Flags & (U_BD_Transform |U_BD_PresetColors | U_BD_BlendFactorsH| U_BD_FocusScales)){ // optional data present
+ if(contents >= blimit)return(0); // the size is variable but this must still hold
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ }
+ else { *Data = NULL; } // no optional data present
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_PATHGRADIENTBRUSHOPTIONALDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Flags bits set to indicate the presence of FillData and/or LineData
+ \param Matrix Transformation matrix
+ \param Pattern Blend Pattern
+ \param Data Focus scales for the brush
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.30, Microsoft name: EmfPlusPathGradientBrushOptionalData Object
+*/
+int U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_get(const char *contents, uint32_t Flags, U_PMF_TRANSFORMMATRIX *Matrix,
+ const char **Pattern, const char **Data, const char *blimit){
+ int varsize;
+ if(!contents || !Flags || !Matrix || !Pattern || !Data || !blimit){ return(0); }
+ /* this structure is entirely optional */
+ if(Flags & U_BD_Transform){
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_TRANSFORMMATRIX), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Matrix, 4, 6, U_LE);
+ }
+ if(Flags & (U_BD_PresetColors | U_BD_BlendFactorsH)){
+ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ uint32_t Elements;
+ U_PMF_SERIAL_get(&contents, &Elements, 4, 1, U_LE);
+ contents -= 4;
+ varsize=(Elements * 4 * (Flags & U_BD_BlendFactorsH ? 2 :1));
+ if(IS_MEM_UNSAFE(contents, varsize, blimit))return(0);
+ U_PMF_PTRSAV_SHIFT(Pattern, &contents, varsize);
+ }
+ else { *Pattern=NULL; }
+ if(Flags & U_BD_FocusScales){
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_FOCUSSCALEDATA), blimit))return(0);
+ U_PMF_PTRSAV_SHIFT(Data, &contents, sizeof(U_PMF_FOCUSSCALEDATA));
+ }
+ else { *Data=NULL; }
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_PATHPOINTTYPE object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Flags PathPointType flags
+ \param Type PathPointType enumeration
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.31, Microsoft name: EmfPlusPathPointType Object
+
+ Note: order of 4bit fields appears to be shown in the LE column, not as
+ documented in the BE column.
+*/
+int U_PMF_PATHPOINTTYPE_get(const char *contents, int *Flags, int *Type, const char *blimit){
+ if(!contents || !Flags || !Type || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, 1, blimit))return(0);
+ uint8_t tmp;
+ memcpy(&tmp, contents, 1);
+ *Flags =(tmp & U_PTP_MASK) >> U_PTP_SHIFT;
+ *Type = (tmp & U_PPT_MASK);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_PATHPOINTTYPERLE object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Bezier Set: Bezier curve, Clear: straight line
+ \param RL Run Length
+ \param Ppt PathPointType enumeration
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.32, Microsoft name: EmfPlusPathPointTypeRLE Object
+*/
+int U_PMF_PATHPOINTTYPERLE_get(const char *contents, int *Bezier, int *RL, int *Ppt, const char *blimit){
+ if(!contents || !Bezier || !RL || !Ppt || !blimit){ return(0); }
+ uint16_t tmp;
+ if(IS_MEM_UNSAFE(contents, 2, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, &tmp, 2, 1, U_LE);
+ *Bezier = tmp & U_PPF_BZ;
+ *RL = (tmp >> U_FF_SHFT_RL) & U_FF_MASK_RL;
+ *Ppt = (tmp >> U_FF_SHFT_PPT) & U_FF_MASK_PPT;
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_PENDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Flags PenData flags
+ \param Unit UnitType enumeration
+ \param Width Width in units set by Unit
+ \param Data Optional pen data, exact composition depends on Flags
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.33, Microsoft name: EmfPlusPenData Object
+*/
+int U_PMF_PENDATA_get(const char *contents, uint32_t *Flags, uint32_t *Unit, U_FLOAT *Width, const char **Data, const char *blimit){
+ if(!contents || !Flags || !Unit || !Width || !Data || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, 3*4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Flags, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Unit, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Width, 4, 1, U_LE);
+ if(contents >= blimit)return(0); // variable data will extend farther, but this much at least must be true
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_PENOPTIONALDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Flags; PenData Flags - indicated which of the many fields are present.
+ \param Matrix; Transformation matrix
+ \param StartCap LineCapType enumeration
+ \param EndCap LineCapType enumeration
+ \param Join LineJoinType enumeration
+ \param MiterLimit Maximum (miter length / line width)
+ \param Style LineStyle enumeration
+ \param DLCap DashedLineCapType enumeration
+ \param DLOffset Distance line start to first dash start
+ \param DLData Dash and space widths
+ \param Alignment PenAlignment enumeration
+ \param CmpndLineData Compount Line (parallel lines drawn instead of one)
+ \param CSCapData Custom start cap
+ \param CECapData Custom end cap
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.34, Microsoft name: EmfPlusPenOptionalData Object
+
+ This object consists of a large number of optional and or variable values, which
+ are returned, or not, depending on bits in Flags.
+*/
+int U_PMF_PENOPTIONALDATA_get(
+ const char *contents,
+ uint32_t Flags, // determines which fields are filled
+ U_PMF_TRANSFORMMATRIX *Matrix,
+ int32_t *StartCap,
+ int32_t *EndCap,
+ uint32_t *Join,
+ U_FLOAT *MiterLimit,
+ int32_t *Style,
+ int32_t *DLCap,
+ U_FLOAT *DLOffset,
+ const char **DLData,
+ int32_t *Alignment,
+ const char **CmpndLineData,
+ const char **CSCapData,
+ const char **CECapData,
+ const char *blimit){
+ if(!contents ||
+ !Flags || !Matrix || !StartCap || !EndCap ||
+ !Join || !MiterLimit || !Style || !DLCap ||
+ !DLOffset || !DLData || !Alignment || !CmpndLineData ||
+ !CSCapData || !CECapData || !blimit){ return(0); }
+
+ if(Flags & U_PD_Transform){ if(IS_MEM_UNSAFE(contents, 4*6, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Matrix, 4, 6, U_LE);
+ }
+ if(Flags & U_PD_StartCap){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, StartCap, 4, 1, U_LE);
+ }
+ if(Flags & U_PD_EndCap){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, EndCap, 4, 1, U_LE);
+ }
+ if(Flags & U_PD_Join){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Join, 4, 1, U_LE);
+ }
+ if(Flags & U_PD_MiterLimit){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, MiterLimit, 4, 1, U_LE);
+ }
+ if(Flags & U_PD_LineStyle){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Style, 4, 1, U_LE);
+ }
+ if(Flags & U_PD_DLCap){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, DLCap, 4, 1, U_LE);
+ }
+ if(Flags & U_PD_DLOffset){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, DLOffset, 4, 1, U_LE);
+ }
+ if(Flags & U_PD_DLData){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ if(IS_MEM_UNSAFE(contents, U_PMF_LEN_FLOATDATA(contents), blimit))return(0);
+ U_PMF_PTRSAV_SHIFT( DLData, &contents, U_PMF_LEN_FLOATDATA(contents));
+ }
+ if(Flags & U_PD_NonCenter){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Alignment, 4, 1, U_LE); }
+ if(Flags & U_PD_CLData){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ if(IS_MEM_UNSAFE(contents, U_PMF_LEN_FLOATDATA(contents), blimit))return(0);
+ U_PMF_PTRSAV_SHIFT( CmpndLineData, &contents, U_PMF_LEN_FLOATDATA(contents));
+ }
+ if(Flags & U_PD_CustomStartCap){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ if(IS_MEM_UNSAFE(contents, U_PMF_LEN_BYTEDATA(contents), blimit))return(0);
+ U_PMF_PTRSAV_SHIFT( CSCapData, &contents, U_PMF_LEN_BYTEDATA(contents));
+ }
+ if(Flags & U_PD_CustomEndCap){ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ if(IS_MEM_UNSAFE(contents, U_PMF_LEN_BYTEDATA(contents), blimit))return(0);
+ U_PMF_PTRSAV_SHIFT( CECapData, &contents, U_PMF_LEN_BYTEDATA(contents));
+ }
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_POINT object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data. On return position is offset by sizeof(U_PMF_POINT).
+ \param X X coordinate
+ \param Y Y coordinate
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.35, Microsoft name: EmfPlusPoint Object
+*/
+int U_PMF_POINT_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, const char *blimit){
+ if(!contents || !X || !Y || !blimit){ return(0); }
+ int16_t tmp;
+ if(IS_MEM_UNSAFE(*contents, 2*2, blimit))return(0);
+ U_PMF_SERIAL_get(contents, &tmp, 2, 1, U_LE); *X = tmp;
+ U_PMF_SERIAL_get(contents, &tmp, 2, 1, U_LE); *Y = tmp;
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_POINTF object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data. On return position is offset by sizeof(U_PMF_POINTF).
+ \param X X coordinate
+ \param Y Y coordinate
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.36, Microsoft name: EmfPlusPointF Object
+*/
+int U_PMF_POINTF_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, const char *blimit){
+ if(!contents || !X || !Y || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(*contents, 4*2, blimit))return(0);
+ U_PMF_SERIAL_get(contents, X, 4, 1, U_LE);
+ U_PMF_SERIAL_get(contents, Y, 4, 1, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_POINTR object
+ \return size in bytes traversed on success, 0 on error
+ \param contents Record from which to extract data. On return position is offset by returned size.
+ \param X X coordinate
+ \param Y Y coordinate
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.37, Microsoft name: EmfPlusPointR Object
+*/
+int U_PMF_POINTR_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, const char *blimit){
+ if(!contents || !*contents || !X || !Y || !blimit){ return(0); }
+ int size=0;
+
+ if( U_PMF_INTEGER7_get( contents, X, blimit)){ size +=1; }
+ else if(U_PMF_INTEGER15_get(contents, X, blimit)){ size +=2; }
+ else { return(0); }
+
+ if( U_PMF_INTEGER7_get( contents, Y, blimit)){ size +=1; }
+ else if(U_PMF_INTEGER15_get(contents, Y, blimit)){ size +=2; }
+ else { return(0); }
+
+ return(size);
+}
+
+/**
+ \brief Get data from a variable POINTS object, which may be U_PMF_POINTS, U_PMF_POINTF, or U_PMF_POINTR.
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Flags Record flags (bits U_PPF_C and U_PPF_P are referenced)
+ \param Elements Number of points to retrieve.
+ \param Points Caller must free. Array of U_PMF_POINTF coordinates.
+ \param blimit one byte past the end of data
+
+ This function should never be called directly by end user code.
+*/
+int U_PMF_VARPOINTS_get(const char *contents, uint16_t Flags, int Elements, U_PMF_POINTF **Points, const char *blimit){
+ int status = 0;
+ if(!contents || !Points || !Elements || !blimit){ return(status); }
+ U_PMF_POINTF *pts = (U_PMF_POINTF *)malloc(Elements * sizeof(U_PMF_POINTF));
+ if(!pts){ return(status); }
+ *Points = pts;
+ U_FLOAT XF, YF;
+ U_FLOAT XFS, YFS;
+
+ if(Flags & U_PPF_P){
+ for(XFS = YFS = 0.0; Elements; Elements--, pts++){
+ if(!U_PMF_POINTR_get(&contents, &XF, &YF, blimit))return(0); /* this should never happen */
+ XFS += XF; /* position relative to previous point, first point is always 0,0 */
+ YFS += YF;
+ pts->X = XFS;
+ pts->Y = YFS;
+ }
+ }
+ else if(Flags & U_PPF_C){
+ for(XF = YF = 0.0; Elements; Elements--, pts++){
+ if(!U_PMF_POINT_get(&contents, &XF, &XF, blimit))break; /* this should never happen */
+ pts->X = XF;
+ pts->Y = YF;
+ }
+ }
+ else {
+ for(XF = YF = 0.0; Elements; Elements--, pts++){
+ (void) U_PMF_POINTF_get(&contents, &XF, &YF, blimit);
+ pts->X = XF;
+ pts->Y = YF;
+ }
+ }
+ if(Elements){ /* some error in the preceding */
+ free(*Points);
+ *Points = NULL;
+ }
+ else {
+ status = 1;
+ }
+ return(status);
+}
+
+/**
+ \brief Get data from a U_PMF_RECT object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param X UL X value
+ \param Y UL Y value
+ \param Width Width
+ \param Height Height
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.38, Microsoft name: EmfPlusRect Object
+*/
+int U_PMF_RECT_get(const char **contents, int16_t *X, int16_t *Y, int16_t *Width, int16_t *Height, const char *blimit){
+ if(!contents || !X || !Y|| !Width || !Height){ return(0); }
+ if(IS_MEM_UNSAFE(*contents, 2*4, blimit))return(0);
+ U_PMF_SERIAL_get(contents, X, 2, 1, U_LE);
+ U_PMF_SERIAL_get(contents, Y, 2, 1, U_LE);
+ U_PMF_SERIAL_get(contents, Width, 2, 1, U_LE);
+ U_PMF_SERIAL_get(contents, Height, 2, 1, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_RECTF object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param X UL X value
+ \param Y UL Y value
+ \param Width Width
+ \param Height Height
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.39, Microsoft name: EmfPlusRectF Object
+*/
+int U_PMF_RECTF_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, U_FLOAT *Width, U_FLOAT *Height, const char *blimit){
+ if(!contents || !X || !Y|| !Width || !Height){ return(0); }
+ if(IS_MEM_UNSAFE(*contents, 4*4, blimit))return(0);
+ U_PMF_SERIAL_get(contents, X, 4, 1, U_LE);
+ U_PMF_SERIAL_get(contents, Y, 4, 1, U_LE);
+ U_PMF_SERIAL_get(contents, Width, 4, 1, U_LE);
+ U_PMF_SERIAL_get(contents, Height, 4, 1, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a variable RECTS object, which may be U_PMF_RECT or U_PMF_RECTF
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Flags Record flags (bit U_PPF_C is referenced)
+ \param Elements Number of rects to retrieve.
+ \param Rects Caller must free. Array of U_PMF_RECTF coordinates.
+ \param blimit one byte past the end of data
+
+ Rects in record may be either U_PMF_RECT or U_PMF_RECTF, but this function always
+ returns U_PMF_RECTF
+*/
+int U_PMF_VARRECTS_get(const char **contents, uint16_t Flags, int Elements, U_PMF_RECTF **Rects, const char *blimit){
+ int16_t X16, Y16, Width, Height;
+ if(!contents || !*contents || !Rects || !blimit){ return(0); }
+ U_PMF_RECTF *rts = (U_PMF_RECTF *)malloc(Elements * sizeof(U_PMF_RECTF));
+ if(!rts){
+ *Rects = NULL;
+ return(0);
+ }
+
+ *Rects = rts;
+ if(Flags & U_PPF_C){
+ if(IS_MEM_UNSAFE(*contents, Elements*sizeof(U_PMF_RECT), blimit)){
+ free(rts);
+ return(0);
+ }
+ }
+ else {
+ if(IS_MEM_UNSAFE(*contents, Elements*sizeof(U_PMF_RECT), blimit)){
+ free(rts);
+ return(0);
+ }
+ }
+ for(; Elements; Elements--, rts++){
+ if(Flags & U_PPF_C){
+ (void) U_PMF_RECT_get(contents, &X16, &Y16, &Width, &Height, blimit);
+ rts->X = X16;
+ rts->Y = Y16;
+ rts->Width = Width;
+ rts->Height = Height;
+ }
+ else {
+ (void) U_PMF_RECTF_get(contents, &(rts->X), &(rts->Y), &(rts->Width), &(rts->Height), blimit);
+ }
+ }
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_REGIONNODE object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Type RegionNodeDataType
+ \param Data Depending on Type: U_PMF_REGIONNODEPATH, U_PMF_RECTF, or U_PMF_REGIONNODECHILDNODES
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.40, Microsoft name: EmfPlusRegionNode Object
+
+ Caller must check Data for possible memory access violations.
+*/
+int U_PMF_REGIONNODE_get(const char *contents, uint32_t *Type, const char **Data, const char *blimit){
+ if(!contents || !Type || !Data || !blimit){ return(0); }
+ /* Important! This only checks the constant part, the caller must check that returned data doesn't exceed blimit */
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_REGIONNODE), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Type, 4, 1, U_LE);
+ if(contents >= blimit)return(0); // returned Data is variable size, this much at least must be true
+ U_PMF_PTRSAV_COND(Data, contents, !(*Type == U_RNDT_Empty || *Type == U_RNDT_Infinite ));
+ return(1);
+}
+
+/**
+ There is no U_PMF_REGIONNODECHILDNODES_get!
+
+ The Region object is recursive allowing U_PMF_REGIONNODECHILDNODES ->
+ U_PMF_REGIONNODE -> U_PMF_REGIONNODECHILDNODES etc.
+ So the data stored in each node must be handled as the tree is followed recursively.
+
+ See U_PMF_REGIONNODECHILDNODES_print() and U_PMF_REGIONNODE_print() for an example.
+
+
+ EMF+ manual 2.2.2.41, Microsoft name: EmfPlusRegionNodeChildNodes Object
+*/
+
+/**
+ \brief Get data from a U_PMF_REGIONNODEPATH object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Size Bytes in Data
+ \param Data Boundary of region node
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.42, Microsoft name: EmfPlusRegionNodePath Object
+*/
+int U_PMF_REGIONNODEPATH_get(const char *contents, int32_t *Size, const char **Data, const char *blimit){
+ if(!contents || !Size || !Data || !blimit){ return(0); }
+ /* Important! This only checks the constant part, the caller must check that returned data doesn't exceed blimit */
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_REGIONNODEPATH), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE);
+ if(contents >= blimit)return(0); // returned Data is variable size, this much at least must be true
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_SOLIDBRUSHDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Color Color of brush
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.43, Microsoft name: EmfPlusSolidBrushData Object
+*/
+int U_PMF_SOLIDBRUSHDATA_get(const char *contents, U_PMF_ARGB *Color, const char *blimit){
+ if(!contents || !Color || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_SOLIDBRUSHDATA), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Color, 4, 1, U_XE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_STRINGFORMATDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param TabStopCount Entries in TabStop array
+ \param RangeCount Entries in CharRange array
+ \param TabStops Array of tabstop locations
+ \param CharRange Array of character ranges in the text
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.44, Microsoft name: EmfPlusStringFormatData Object
+*/
+int U_PMF_STRINGFORMATDATA_get(const char *contents, uint32_t TabStopCount, uint32_t RangeCount,
+ const U_FLOAT **TabStops, const U_PMF_CHARACTERRANGE **CharRange, const char *blimit){
+ if(!contents || !TabStops|| !CharRange || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, (TabStopCount + 2*RangeCount)*4, blimit))return(0);
+ *TabStops = NULL;
+ if(TabStopCount > 0){ U_PMF_SERIAL_get(&contents, TabStops, 4, TabStopCount, U_LE); }
+ *CharRange = NULL;
+ if(RangeCount > 0){ U_PMF_SERIAL_get(&contents, CharRange, 4, 2*RangeCount, U_LE); }
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_TEXTUREBRUSHDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Flags BrushData flags
+ \param WrapMode WrapMode enumeration
+ \param Data Optional texture data
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.45, Microsoft name: EmfPlusTextureBrushData Object
+
+ Caller must check Data for possible memory access violations.
+*/
+int U_PMF_TEXTUREBRUSHDATA_get(const char *contents, uint32_t *Flags, int32_t *WrapMode, const char **Data, const char *blimit){
+ if(!contents || !Flags || !WrapMode || !Data || !blimit){ return(0); }
+ /* Important! This only checks the constant part, the caller must check that returned data doesn't exceed blimit */
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_TEXTUREBRUSHDATA), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Flags, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, WrapMode, 4, 1, U_LE);
+ if(contents >= blimit)return(0); // returned Data is variable size, this much at least must be true
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_TEXTUREBRUSHOPTIONALDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param HasImage True if this object has an Image
+ \param Matrix Transformation matrix, NULL if Flag BrushDataTransform is not set.
+ \param Image Image that contains the texture.
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.46, Microsoft name: EmfPlusTextureBrushOptionalData Object
+
+ Caller must check Image for possible memory access violations.
+*/
+int U_PMF_TEXTUREBRUSHOPTIONALDATA_get(const char *contents, int HasImage, U_PMF_TRANSFORMMATRIX *Matrix,
+ const char **Image, const char *blimit){
+ if(!contents || !Image || !blimit){ return(0); }
+ if(Matrix){
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_TRANSFORMMATRIX), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Matrix, 4, 6, U_LE);
+ }
+ if(HasImage){
+ if(contents >= blimit)return(0); // returned Data is variable size, this much at least must be true
+ U_PMF_PTRSAV_COND(Image, contents, HasImage);
+ }
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_TRANSFORMMATRIX object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Matrix Transformation matrix, present if Flag BrushDataTransform is set.
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.47, Microsoft name: EmfPlusTransformMatrix Object
+*/
+int U_PMF_TRANSFORMMATRIX_get(const char *contents, U_PMF_TRANSFORMMATRIX *Matrix, const char *blimit){
+ if(!contents || !Matrix || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_TRANSFORMMATRIX), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Matrix, 4, 6, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_IE_BLUR object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Radius Blur radius in pixels
+ \param ExpandEdge 1: expand bitmap by Radius; 0: bitmap size unchanged
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.3.1, Microsoft name: BlurEffect Object
+*/
+int U_PMF_IE_BLUR_get(const char *contents, U_FLOAT *Radius, uint32_t *ExpandEdge, const char *blimit){
+ if(!contents || !Radius || !ExpandEdge || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_BLUR), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Radius, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, ExpandEdge, 4, 1, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_IE_BRIGHTNESSCONTRAST object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Brightness -255 to 255, 0 is unchanged, positive increases, negative decreases
+ \param Contrast -100 to 100, 0 is unchanged, positive increases, negative decreases
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.3.2, Microsoft name: BrightnessContrastEffect Object
+*/
+int U_PMF_IE_BRIGHTNESSCONTRAST_get(const char *contents, int32_t *Brightness, int32_t *Contrast, const char *blimit){
+ if(!contents || !Brightness || !Contrast || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_BRIGHTNESSCONTRAST), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Brightness, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Contrast, 4, 1, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_IE_COLORBALANCE object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param CyanRed -100 to 100, 0 is unchanged, positive increases Red & decreases Cyan, negative is opposite
+ \param MagentaGreen -100 to 100, 0 is unchanged, positive increases Green & decreases Magenta, negative is opposite
+ \param YellowBlue -100 to 100, 0 is unchanged, positive increases Blue & decreases Yellow, negative is opposite
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.3.3, Microsoft name: ColorBalanceEffect Object
+*/
+int U_PMF_IE_COLORBALANCE_get(const char *contents, int32_t *CyanRed, int32_t *MagentaGreen, int32_t *YellowBlue, const char *blimit){
+ if(!contents || !CyanRed || !MagentaGreen || !YellowBlue || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_COLORBALANCE), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, CyanRed, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, MagentaGreen, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, YellowBlue, 4, 1, U_LE);
+ return(1);
+}
+
+
+/**
+ \brief Get data from a U_PMF_IE_COLORCURVE object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Adjust CurveAdjustment enumeration
+ \param Channel CurveChannel enumeration
+ \param Intensity adjustment to apply. "Adjust" determines what field this is and range values.
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.3.4, Microsoft name: ColorCurveEffect Object
+*/
+int U_PMF_IE_COLORCURVE_get(const char *contents, uint32_t *Adjust, uint32_t *Channel, int32_t *Intensity, const char *blimit){
+ if(!contents || !Adjust || !Channel || !Intensity || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_COLORCURVE), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Adjust, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Channel, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Intensity, 4, 1, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_IE_COLORLOOKUPTABLE object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param BLUT Blue color lookup table
+ \param GLUT Green color lookup table
+ \param RLUT Red color lookup table
+ \param ALUT Alpha color lookup table
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.3.5, Microsoft name: ColorLookupTableEffect Object
+*/
+int U_PMF_IE_COLORLOOKUPTABLE_get(const char *contents,
+ const uint8_t **BLUT, const uint8_t **GLUT, const uint8_t **RLUT, const uint8_t **ALUT, const char *blimit){
+ if(!contents || !BLUT || !GLUT || !RLUT || !ALUT || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_COLORLOOKUPTABLE) + 4 * 256, blimit))return(0);
+ U_PMF_PTRSAV_SHIFT((const char **)BLUT, &contents, 256);
+ U_PMF_PTRSAV_SHIFT((const char **)GLUT, &contents, 256);
+ U_PMF_PTRSAV_SHIFT((const char **)RLUT, &contents, 256);
+ U_PMF_PTRSAV_SHIFT((const char **)ALUT, &contents, 256);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_IE_COLORMATRIX object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Matrix 5 x 5 color transformation matrix, First 4 rows are [{4 multiplier values},0.0] for R,G,B,A, last Row is [{4 color translation valuess}, 1.0]
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.3.6, Microsoft name: ColorMatrixEffect Object
+*/
+int U_PMF_IE_COLORMATRIX_get(const char *contents, U_PMF_IE_COLORMATRIX *Matrix, const char *blimit){
+ if(!contents || !Matrix || !blimit){ return(0); }
+ /* Important! This only checks the constant part, the caller must check that returned data doesn't exceed blimit */
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_COLORMATRIX), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Matrix, 4, 5*5, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_IE_HUESATURATIONLIGHTNESS object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Hue -180 to 180, 0 is unchanged
+ \param Saturation -100 to 100, 0 is unchanged
+ \param Lightness -100 to 100, 0 is unchanged
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.3.7, Microsoft name: HueSaturationLightnessEffect Object
+*/
+int U_PMF_IE_HUESATURATIONLIGHTNESS_get(const char *contents, int32_t *Hue, int32_t *Saturation, int32_t *Lightness, const char *blimit){
+ if(!contents || !Hue || !Saturation || !Lightness || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_HUESATURATIONLIGHTNESS), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Hue, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Saturation, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Lightness, 4, 1, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_IE_LEVELS object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Highlight 0 to 100, 100 is unchanged
+ \param Midtone -100 to 100, 0 is unchanged
+ \param Shadow 0 to 100, 0 is unchanged
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.3.8, Microsoft name: LevelsEffect Object
+*/
+int U_PMF_IE_LEVELS_get(const char *contents, int32_t *Highlight, int32_t *Midtone, int32_t *Shadow, const char *blimit){
+ if(!contents || !Highlight || !Midtone || !Shadow || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_LEVELS), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Highlight, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Midtone, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Shadow, 4, 1, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_IE_REDEYECORRECTION object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Elements Number of members in Rects
+ \param Rects Caller must free. Pointer to memory holding an array of U_RECTL.
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.3.9, Microsoft name: RedEyeCorrectionEffect Object
+*/
+int U_PMF_IE_REDEYECORRECTION_get(const char *contents, int32_t *Elements, U_RECTL **Rects, const char *blimit){
+ if(!contents || !Elements || !Rects || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_REDEYECORRECTION), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ if(IS_MEM_UNSAFE(contents, *Elements * 4, blimit))return(0);
+ *Rects = (U_RECTL *) malloc(*Elements * sizeof(U_RECTL));
+ if(!*Rects){ return(0); }
+ U_PMF_SERIAL_get(&contents, *Rects, 4, *Elements * 4, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_IE_SHARPEN object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Radius Sharpening radius in pixels
+ \param Sharpen 0 to 100, 0 is unchanged
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.3.10, Microsoft name: SharpenEffect Object
+*/
+int U_PMF_IE_SHARPEN_get(const char *contents, U_FLOAT *Radius, int32_t *Sharpen, const char *blimit){
+ if(!contents || !Radius || !Sharpen || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_SHARPEN), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Radius, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Sharpen, 4, 1, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMF_IE_TINT object
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Hue -180 to 180, [positive==clockwise] rotation in degrees starting from blue
+ \param Amount -100 [add black] to 100[add white], 0 is unchanged. Change in hue on specified axis
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.3.11, Microsoft name: TintEffect Object
+*/
+int U_PMF_IE_TINT_get(const char *contents, int32_t *Hue, int32_t *Amount, const char *blimit){
+ if(!contents || !Hue || !Amount || !blimit){ return(0); }
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_IE_TINT), blimit))return(0);
+ U_PMF_SERIAL_get(&contents, Hue, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Amount, 4, 1, U_LE);
+ return(1);
+}
+
+/*
+
+ end of U_PMF_*_get() functions
+ =====================================================================================
+ start of U_PMR_*_get() functions
+
+ These functions all assume that the size field in the common EMF+ header has already
+ been checked, so that the extent the record claims exists in the data read in for the file.
+ Consequently none of them takes a blimit parameter. They generate a new one from the
+ header size field and contents if needed.
+
+*/
+
+int U_PMR_common_stack_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID){
+ if(!contents || !StackID){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_RESTORE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ U_PMF_SERIAL_get(&contents, StackID, 4, 1, U_LE);
+ return(1);
+}
+
+/* for records that have a type but no associated flag bits or data */
+int U_PMR_common_header_get(const char *contents, U_PMF_CMN_HDR *Header){
+ /* memory access safe, only uses the common header */
+ if(!contents){ return(0); }
+ U_PMF_CMN_HDR_get(&contents, Header);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_OFFSETCLIP record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header (ignore flags)
+ \param dX horizontal translation offset to apply to clipping region
+ \param dY vertical translation offset to apply to clipping region
+
+ EMF+ manual 2.3.1.1, Microsoft name: EmfPlusOffsetClip Record, Index 0x35
+*/
+int U_PMR_OFFSETCLIP_get(const char *contents, U_PMF_CMN_HDR *Header,
+ U_FLOAT *dX, U_FLOAT *dY){
+ if(!contents){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_OFFSETCLIP))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ U_PMF_SERIAL_get(&contents, dX, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, dY, 4, 1, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_RESETCLIP record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header (ignore flags)
+
+ EMF+ manual 2.3.1.2, Microsoft name: EmfPlusResetClip Record, Index 0x31
+*/
+int U_PMR_RESETCLIP_get(const char *contents, U_PMF_CMN_HDR *Header){
+ if(!contents){ return(0); }
+ U_PMF_CMN_HDR_get(&contents, Header);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_SETCLIPPATH record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param CMenum CombineMode enumeration..
+ \param PathID U_PMF_PATH object in the EMF+ object table (0-63, inclusive)
+
+ EMF+ manual 2.3.1.3, Microsoft name: EmfPlusSetClipPath Record, Index 0x33
+*/
+int U_PMR_SETCLIPPATH_get(const char *contents, U_PMF_CMN_HDR *Header,
+ uint32_t *PathID, int *CMenum){
+ if(!contents || !PathID || !CMenum){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SETCLIPPATH))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *CMenum = (lclHeader.Flags >> U_FF_SHFT_CM4) & U_FF_MASK_CM4;
+ *PathID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_SETCLIPRECT record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header (ignore flags)
+ \param CMenum Combine mode enumeration.
+ \param Rect Rectangle used with CombineMode enumeration from Header.Flags
+
+ EMF+ manual 2.3.1.4, Microsoft name: EmfPlusSetClipRect Record, Index 0x32
+*/
+int U_PMR_SETCLIPRECT_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int *CMenum,
+ U_PMF_RECTF *Rect){
+ if(!contents || !CMenum || !Rect ){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SETCLIPRECT))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *CMenum = (lclHeader.Flags >> U_FF_SHFT_CM4) & U_FF_MASK_CM4;
+ U_PMF_SERIAL_get(&contents, Rect, 4, 4, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_SETCLIPREGION record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param CMenum CombineMode enumeration..
+ \param PathID U_PMF_PATH object in the EMF+ object table (0-63, inclusive)
+
+ EMF+ manual 2.3.1.5, Microsoft name: EmfPlusSetClipRegion Record, Index 0x34
+*/
+int U_PMR_SETCLIPREGION_get(const char *contents, U_PMF_CMN_HDR *Header,
+ uint32_t *PathID, int *CMenum){
+ if(!contents || !PathID || !CMenum){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SETCLIPREGION))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *CMenum = (lclHeader.Flags >> U_FF_SHFT_CM4) & U_FF_MASK_CM4;
+ *PathID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_COMMENT record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header (ignore flags)
+ \param Data Private data, may be anything
+
+ EMF+ manual 2.3.2.1, Microsoft name: EmfPlusComment Record, Index 0x03
+
+ Caller must check Data for possible memory access violations.
+*/
+int U_PMR_COMMENT_get(const char *contents, U_PMF_CMN_HDR *Header,
+ const char **Data){
+ if(!contents || !Data){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_COMMENT))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_ENDOFFILE record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header (ignore flags)
+
+ EMF+ manual 2.3.3.1, Microsoft name: EmfPlusEndOfFile Record, Index 0x02
+*/
+int U_PMR_ENDOFFILE_get(const char *contents, U_PMF_CMN_HDR *Header){
+ if(!contents){ return(0); }
+ U_PMF_CMN_HDR_get(&contents, Header);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_GETDC record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header (ignore flags)
+
+ EMF+ manual 2.3.3.2, Microsoft name: EmfPlusGetDC Record, Index 0x04
+*/
+int U_PMR_GETDC_get(const char *contents, U_PMF_CMN_HDR *Header){
+ if(!contents){ return(0); }
+ U_PMF_CMN_HDR_get(&contents, Header);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_HEADER record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header (ignore flags)
+ \param Version EmfPlusGraphicsVersion object
+ \param IsDual set = Dual-mode file, clear= EMF+ only file.
+ \param IsVideo set = video device, clear= printer. Ignore all other bits.
+ \param LogicalDpiX Horizontal resolution reference device in DPI
+ \param LogicalDpiY Vertical resolution reference device in DPI
+
+ EMF+ manual 2.3.3.3, Microsoft name: EmfPlusHeader Record, Index 0x01
+*/
+int U_PMR_HEADER_get(const char *contents, U_PMF_CMN_HDR *Header,
+ U_PMF_GRAPHICSVERSION *Version, int *IsDual, int *IsVideo, uint32_t *LogicalDpiX, uint32_t *LogicalDpiY){
+ if(!contents || !Version || !IsDual || !IsVideo || !LogicalDpiX || !LogicalDpiY){ return(0); }
+ uint32_t tmp;
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_HEADER))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *IsDual = (lclHeader.Flags & U_PPF_DM ? 1 : 0 );
+ U_PMF_SERIAL_get(&contents, Version, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, &tmp, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, LogicalDpiX, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, LogicalDpiY, 4, 1, U_LE);
+ *IsVideo = (tmp & U_PPF_VIDEO ? 1 : 0 );
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_CLEAR record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header (ignore flags)
+ \param Color Erase everything preceding, set background ARGB color.
+
+ EMF+ manual 2.3.4.1, Microsoft name: EmfPlusClear Record, Index 0x09
+*/
+int U_PMR_CLEAR_get(const char *contents, U_PMF_CMN_HDR *Header,
+ U_PMF_ARGB *Color){
+ if(!contents || !Color){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_CLEAR))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ U_PMF_SERIAL_get(&contents, Color, 4, 1, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_DRAWARC record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+ \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates
+ \param Start Start angle, >=0.0, degrees clockwise from 3:00
+ \param Sweep Sweep angle, -360<= angle <=360, degrees clockwise from Start
+ \param Rect Caller must free. Bounding rectangle. Coordinate type set by ctype.
+
+ EMF+ manual 2.3.4.2, Microsoft name: EmfPlusDrawArc Record, Index 0x12
+*/
+int U_PMR_DRAWARC_get(const char *contents, U_PMF_CMN_HDR *Header,
+ uint32_t *PenID, int *ctype,
+ U_FLOAT *Start, U_FLOAT *Sweep,
+ U_PMF_RECTF *Rect){
+ if(!contents || !PenID || !ctype || !Start || !Sweep || !Rect){ return(0); }
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWARC))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
+ U_PMF_SERIAL_get(&contents, Start, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Sweep, 4, 1, U_LE);
+ U_PMF_RECTF *Rects = NULL;
+ if(!U_PMF_VARRECTS_get(&contents, lclHeader.Flags, 1, &Rects, blimit))return(0);
+ memcpy(Rect,Rects,sizeof(U_PMF_RECTF));
+ free(Rects);
+ return(1);
+}
+
+
+/**
+ \brief Get data from a U_PMR_DRAWBEZIERS record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+ \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates
+ \param RelAbs Set: Coordinates are relative; Clear: Coordinates are absolute and their type is set by ctype
+ \param Elements Number of members in the Data array
+ \param Points Caller must free. Array of U_POINT_F = Sequence of points to connect. Coordinate type set by ctype and RelAbs.
+
+ EMF+ manual 2.3.4.3, Microsoft name: EmfPlusDrawBeziers Record, Index 0x19
+*/
+int U_PMR_DRAWBEZIERS_get(const char *contents, U_PMF_CMN_HDR *Header,
+ uint32_t *PenID, int *ctype, int *RelAbs,
+ uint32_t *Elements,
+ U_PMF_POINTF **Points){
+ if(!contents || !PenID || !ctype || !RelAbs || !Elements || !Points){ return(0); }
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWBEZIERS))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *RelAbs = (lclHeader.Flags & U_PPF_P ? 1 : 0 );
+ *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
+ U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ int status = U_PMF_VARPOINTS_get(contents, lclHeader.Flags, *Elements, Points, blimit );
+ return(status);
+}
+
+/**
+ \brief Get data from a U_PMR_DRAWCLOSEDCURVE record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+ \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates
+ \param RelAbs Set: Coordinates are relative; Clear: Coordinates are absolute and their type is set by ctype
+ \param Tension Controls splines, 0 is straight line, >0 is curved
+ \param Elements Number of members in the Data array
+ \param Points Caller must free. Array of U_POINT_F = Sequence of points to connect. Coordinate type set by ctype and RelAbs.
+
+ EMF+ manual 2.3.4.4, Microsoft name: EmfPlusDrawClosedCurve Record, Index 0x17
+*/
+int U_PMR_DRAWCLOSEDCURVE_get(const char *contents, U_PMF_CMN_HDR *Header,
+ uint32_t *PenID, int *ctype, int *RelAbs,
+ U_FLOAT *Tension, uint32_t *Elements,
+ U_PMF_POINTF **Points){
+ if(!contents || !PenID || !ctype || !RelAbs || !Tension || !Elements || !Points){ return(0); }
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWCLOSEDCURVE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *RelAbs = (lclHeader.Flags & U_PPF_P ? 1 : 0 );
+ *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
+ U_PMF_SERIAL_get(&contents, Tension, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ U_PMF_VARPOINTS_get(contents, lclHeader.Flags, *Elements, Points, blimit);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_DRAWCURVE record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+ \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates
+ \param Tension Controls splines, 0 is straight line, >0 is curved
+ \param Offset Element in Points that is the spline's starting point
+ \param NSegs Number of segments
+ \param Elements Number of members in Data array
+ \param Points Caller must free. Array of U_POINT_F = Sequence of points to connect. Coordinate type set by ctype and RelAbs.
+
+ EMF+ manual 2.3.4.5, Microsoft name: EmfPlusDrawCurve Record, Index 0x18
+*/
+int U_PMR_DRAWCURVE_get(const char *contents, U_PMF_CMN_HDR *Header,
+ uint32_t *PenID, int *ctype,
+ U_FLOAT *Tension, uint32_t *Offset, uint32_t *NSegs, uint32_t *Elements,
+ U_PMF_POINTF **Points){
+ if(!contents || !PenID || !ctype || !Tension || !Offset || !NSegs || !Elements || !Points){ return(0); }
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWCURVE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
+ U_PMF_SERIAL_get(&contents, Tension, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Offset, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, NSegs, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ U_PMF_VARPOINTS_get(contents, lclHeader.Flags, *Elements, Points, blimit);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_DRAWDRIVERSTRING record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param FontID U_PMF_FONT object in the EMF+ object table (0-63, inclusive)
+ \param btype Set: BrushID is an U_PFM_ARGB; Clear: index of U_PMF_BRUSH object in EMF+ object table.
+ \param BrushID Color or index of U_PMF_BRUSH object in the EMF+ object table, depends on Flags bit0
+ \param DSOFlags DriverStringOptions flags
+ \param HasMatrix If 1 record contains a TransformMatrix field, if 0 it does not.
+ \param Elements Number of members in Glyphs and Positions array
+ \param Glyphs Caller must free. If U_DSO_CmapLookup is set in DSOFlags this is an array of UTF16LE characters, otherwise, it is an array of indices into the U_PMF_FONT object indexed by Object_ID in flags.
+ \param Points Caller must free. Coordinates of each member of Glyphs. U_DSO_RealizedAdvance set in DSOFlags Relative then positions are calculated relative to the first glyph which is stored in Positions, otherwise, all glyph positions are stored in Positions.
+ \param Matrix Caller must free. Transformation to apply to Glyphs & Positions. Present if HasMatrix is 1
+
+ EMF+ manual 2.3.4.6, Microsoft name: EmfPlusDrawDriverString Record, Index 0x36
+*/
+int U_PMR_DRAWDRIVERSTRING_get(const char *contents, U_PMF_CMN_HDR *Header,
+ uint32_t *FontID, int *btype,
+ uint32_t *BrushID, uint32_t *DSOFlags, uint32_t *HasMatrix, uint32_t *Elements,
+ uint16_t **Glyphs, U_PMF_POINTF **Points, U_PMF_TRANSFORMMATRIX **Matrix){
+ if(!contents || !FontID || !btype || !BrushID ||
+ !DSOFlags || !HasMatrix || !Elements || !Glyphs || !Points || !Matrix){ return(0); }
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWDRIVERSTRING))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 );
+ *FontID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
+ U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */
+ U_PMF_SERIAL_get(&contents, DSOFlags, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, HasMatrix, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ if(IS_MEM_UNSAFE(contents, *Elements*2 + *Elements*2*4 + 24, blimit))return(0);
+ if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)Glyphs, 2, *Elements, U_LE, (*DSOFlags & U_DSO_CmapLookup))){ return(0); }
+ if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)Points, 4, *Elements *2, U_LE, (*DSOFlags & U_DSO_RealizedAdvance))){ return(0); }
+ if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)Matrix, 4, 6, U_LE, (*HasMatrix))){ return(0); }
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_DRAWELLIPSE record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+ \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates
+ \param Rect Caller must free. Bounding rectangle. Coordinate type set by ctype.
+
+ EMF+ manual 2.3.4.7, Microsoft name: EmfPlusDrawEllipse Record, Index 0x0F
+*/
+int U_PMR_DRAWELLIPSE_get(const char *contents, U_PMF_CMN_HDR *Header,
+ uint32_t *PenID, int *ctype,
+ U_PMF_RECTF *Rect){
+ if(!contents || !PenID || !ctype || !Rect){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWELLIPSE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
+ U_PMF_SERIAL_get(&contents, Rect, 4, 4, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_DRAWIMAGE record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param ImgID U_PMF_IMAGE object in the EMF+ object table (0-63, inclusive)
+ \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates
+ \param ImgAttrID index of a U_PMF_IMAGEATTRIBUTES object in the object table
+ \param SrcUnit UnitType enumeration
+ \param SrcRect Region of image
+ \param DstRect Destination rectangle for image. Coordinate type set by ctype.
+
+ EMF+ manual 2.3.4.8, Microsoft name: EmfPlusDrawImage Record, Index 0x1A
+*/
+int U_PMR_DRAWIMAGE_get(const char *contents, U_PMF_CMN_HDR *Header,
+ uint32_t *ImgID, int *ctype,
+ uint32_t *ImgAttrID, int32_t *SrcUnit, U_PMF_RECTF *SrcRect,
+ U_PMF_RECTF *DstRect){
+ if(!contents || !ImgID || !ctype || !ImgAttrID || !SrcUnit || !SrcRect || !DstRect){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWIMAGE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *ImgID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
+ U_PMF_SERIAL_get(&contents, ImgAttrID, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, SrcUnit, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, SrcRect, 4, 4, U_LE);
+ U_PMF_SERIAL_get(&contents, DstRect, 4, 4, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_DRAWIMAGEPOINTS record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param ImgID U_PMF_IMAGE object in the EMF+ object table (0-63, inclusive)
+ \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates
+ \param etype Set: effect from previous U_PMR_SERIALIZABLEOBJECT record will be applied; Clear: no effect applied
+ \param RelAbs Set: Data is relative, Clear: if it is absolute
+ \param ImgAttrID EmfPlusImageAttributes object
+ \param SrcUnit UnitType enumeration
+ \param SrcRect Region of image
+ \param Elements Number of members in Points, must be 3
+ \param Points Caller must free. 3 points of a parallelogram.. Coordinate type set by ctype and RelAbs.
+
+ EMF+ manual 2.3.4.9, Microsoft name: EmfPlusDrawImagePoints Record, Index 0x1B
+*/
+int U_PMR_DRAWIMAGEPOINTS_get(const char *contents, U_PMF_CMN_HDR *Header,
+ uint32_t *ImgID, int *ctype, int *etype, int *RelAbs,
+ uint32_t *ImgAttrID, int32_t *SrcUnit, U_PMF_RECTF *SrcRect, uint32_t *Elements,
+ U_PMF_POINTF **Points){
+ if(!contents || !ImgID || !ctype || !etype || !RelAbs || !ImgAttrID || !SrcUnit || !Elements || !Points){ return(0); }
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWIMAGEPOINTS))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *etype = (lclHeader.Flags & U_PPF_E ? 1 : 0 );
+ *RelAbs = (lclHeader.Flags & U_PPF_P ? 1 : 0 );
+ *ImgID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
+ U_PMF_SERIAL_get(&contents, ImgAttrID, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, SrcUnit, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, SrcRect, 4, 4, U_LE);
+ U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ U_PMF_VARPOINTS_get(contents, lclHeader.Flags, *Elements, Points, blimit);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_DRAWLINES record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+ \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates
+ \param dtype Set: path must be closed, Clear: path is open
+ \param RelAbs Set: Coordinates are relative; Clear: Coordinates are absolute and their type is set by ctype
+ \param Elements Number of members in Points
+ \param Points Caller must free. Array of U_POINT_F = Sequence of points to connect. Coordinate type set by ctype and RelAbs.
+
+ EMF+ manual 2.3.4.10, Microsoft name: EmfPlusDrawLines Record, Index 0x0D
+*/
+int U_PMR_DRAWLINES_get(const char *contents, U_PMF_CMN_HDR *Header,
+ uint32_t *PenID, int *ctype, int *dtype, int *RelAbs,
+ uint32_t *Elements,
+ U_PMF_POINTF **Points){
+ if(!contents || !PenID || !ctype || !dtype || !RelAbs || !Elements || !Points){ return(0); }
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWLINES))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *dtype = (lclHeader.Flags & U_PPF_D ? 1 : 0 );
+ *RelAbs = (lclHeader.Flags & U_PPF_P ? 1 : 0 );
+ *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
+ U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ U_PMF_VARPOINTS_get(contents, lclHeader.Flags, *Elements, Points, blimit);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_DRAWPATH record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param PathID U_PMF_PATH object in the EMF+ object table (0-63, inclusive)
+ \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+
+ EMF+ manual 2.3.4.11, Microsoft name: EmfPlusDrawPath Record, Index 0x15
+*/
+int U_PMR_DRAWPATH_get(const char *contents, U_PMF_CMN_HDR *Header,
+ uint32_t *PathID, uint32_t *PenID){
+ if(!contents || !PathID || !PenID){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWPATH))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *PathID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
+ U_PMF_SERIAL_get(&contents, PenID, 4, 1, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_DRAWPIE record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+ \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates
+ \param Start Start angle, >=0.0, degrees clockwise from 3:00
+ \param Sweep Sweep angle, -360<= angle <=360, degrees clockwise from Start
+ \param Rect Caller must free. Bounding rectangle. Coordinate type set by ctype.
+
+ EMF+ manual 2.3.4.12, Microsoft name: EmfPlusDrawPie Record, Index 0x0D
+*/
+int U_PMR_DRAWPIE_get(const char *contents, U_PMF_CMN_HDR *Header,
+ uint32_t *PenID, int *ctype,
+ U_FLOAT *Start, U_FLOAT *Sweep,
+ U_PMF_RECTF *Rect){
+ if(!contents || !PenID || !ctype || !Start || !Sweep || !Rect){ return(0); }
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWPIE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
+ U_PMF_SERIAL_get(&contents, Start, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Sweep, 4, 1, U_LE);
+ U_PMF_RECTF *Rects = NULL;
+ if(!U_PMF_VARRECTS_get(&contents, lclHeader.Flags, 1, &Rects, blimit))return(0);
+ memcpy(Rect,Rects,sizeof(U_PMF_RECTF));
+ free(Rects);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_DRAWRECTS record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param PenID U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+ \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates
+ \param Elements Number of members in Rects
+ \param Rects Caller must free. Array of U_PMF_RECTF rectangles to draw.
+
+ EMF+ manual 2.3.4.13, Microsoft name: EmfPlusDrawRects Record, Index 0x0B
+
+ Rects in record may be either U_PMF_RECT or U_PMF_RECTF, but this function always
+ returns U_PMF_RECTF
+*/
+int U_PMR_DRAWRECTS_get(const char *contents, U_PMF_CMN_HDR *Header,
+ uint32_t *PenID, int *ctype,
+ uint32_t *Elements,
+ U_PMF_RECTF **Rects){
+ if(!contents || !PenID || !Elements || !Rects){ return(0); }
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWPIE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *PenID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ U_PMF_VARRECTS_get(&contents, lclHeader.Flags, *Elements, Rects, blimit);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_DRAWSTRING record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param FontID U_PMF_FONT object in the EMF+ object table (0-63, inclusive)
+ \param btype Set: BrushID is an U_PFM_ARGB; Clear: index of U_PMF_BRUSH object in EMF+ object table.
+ \param BrushID Color or index of U_PMF_BRUSH object in the EMF+ object table, depending on btype.
+ \param FormatID U_PMF_STRINGFORMAT object in EMF+ Object Table.
+ \param Elements Number of characters in the string.
+ \param Rect String's bounding box.
+ \param String Caller must free. Array of UFT-16LE unicode characters.
+
+ EMF+ manual 2.3.4.14, Microsoft name: EmfPlusDrawString Record, Index 0x1C
+*/
+int U_PMR_DRAWSTRING_get(const char *contents, U_PMF_CMN_HDR *Header,
+ uint32_t *FontID, int *btype,
+ uint32_t *BrushID, uint32_t *FormatID, uint32_t *Elements, U_PMF_RECTF *Rect,
+ uint16_t **String){
+ if(!contents || !FontID || !btype || !BrushID || !FormatID || !Elements || !String){ return(0); }
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWPIE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 );
+ *FontID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
+ U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */
+ U_PMF_SERIAL_get(&contents, FormatID, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Rect, 4, 4, U_LE);
+ if(IS_MEM_UNSAFE(contents, *Elements * 2, blimit))return(0);
+ if(!U_PMF_SERIAL_array_copy_get(&contents, (void **)String, 2, *Elements, U_XE, 1)){ return(0); }
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_FILLCLOSEDCURVE record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param btype Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table.
+ \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates
+ \param ftype Set: winding fill; Clear: alternate fill
+ \param RelAbs Set: Coordinates are relative; Clear: Coordinates are absolute and their type is set by ctype
+ \param BrushID Color or index of U_PMF_BRUSH object in the EMF+ object table, depending on btype.
+ \param Tension Controls splines, 0 is straight line, >0 is curved
+ \param Elements Number of members in Points
+ \param Points Caller must free. Array of U_POINT_F = Sequence of points to connect. Coordinate type set by ctype and RelAbs.
+
+ EMF+ manual 2.3.4.15, Microsoft name: EmfPlusFillClosedCurve Record, Index 0x16
+*/
+int U_PMR_FILLCLOSEDCURVE_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int *btype, int *ctype, int *ftype, int *RelAbs,
+ uint32_t *BrushID, U_FLOAT *Tension, uint32_t *Elements,
+ U_PMF_POINTF **Points){
+ if(!contents || !btype || !ctype || !ftype || !RelAbs || !BrushID || !Tension || !Elements || !Points){ return(0); }
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWLINES))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 );
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *ftype = (lclHeader.Flags & U_PPF_F ? 1 : 0 );
+ *RelAbs = (lclHeader.Flags & U_PPF_P ? 1 : 0 );
+ U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */
+ U_PMF_SERIAL_get(&contents, Tension, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ U_PMF_VARPOINTS_get(contents, lclHeader.Flags, *Elements, Points, blimit);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_FILLELLIPSE record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param btype Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table.
+ \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates
+ \param BrushID Color or index of U_PMF_BRUSH object in the EMF+ object table, depending on btype.
+ \param Rect Caller must free. Bounding box for elliptical pie segment being drawn. Coordinate type set by ctype.
+
+ EMF+ manual 2.3.4.16, Microsoft name: EmfPlusFillEllipse Record, Index 0x0E
+*/
+int U_PMR_FILLELLIPSE_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int *btype, int *ctype,
+ uint32_t *BrushID,
+ U_PMF_RECTF *Rect){
+ if(!contents || !btype || !ctype || !BrushID || !Rect){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_FILLELLIPSE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 );
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */
+ U_PMF_SERIAL_get(&contents, Rect, 4, 4, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_FILLPATH record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param btype Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table.
+ \param PathID U_PMF_PATH object in the EMF+ object table (0-63, inclusive)
+ \param BrushID Color or index of U_PMF_BRUSH object in the EMF+ object table, depending on btype.
+
+ EMF+ manual 2.3.4.17, Microsoft name: EmfPlusFillPath Record, Index 0x14
+
+ Note: U_PMF_FILLPATHOBJ is the object, U_PMF_FILLPATH is the file record
+*/
+int U_PMR_FILLPATH_get(const char *contents, U_PMF_CMN_HDR *Header,
+ uint32_t *PathID, int *btype,
+ uint32_t *BrushID){
+ if(!contents || !PathID || !btype || !BrushID){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_FILLPATH))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 );
+ *PathID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
+ U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_FILLPIE record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param btype Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table.
+ \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates
+ \param BrushID Color or index of U_PMF_BRUSH object in the EMF+ object table, depending on btype.
+ \param Start Start angle, >=0.0, degrees clockwise from 3:00
+ \param Sweep Sweep angle, -360<= angle <=360, degrees clockwise from Start
+ \param Rect Bounding box for elliptical pie segment being filled. Coordinate type set by ctype.
+
+ EMF+ manual 2.3.4.18, Microsoft name: EmfPlusFillPie Record, Index 0x10
+*/
+int U_PMR_FILLPIE_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int *btype, int *ctype,
+ uint32_t *BrushID, U_FLOAT *Start, U_FLOAT *Sweep,
+ U_PMF_RECTF *Rect){
+ if(!contents || !btype || !ctype || !BrushID || !Start || !Sweep || !Rect){ return(0); }
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_FILLPIE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 );
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */
+ U_PMF_SERIAL_get(&contents, Start, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Sweep, 4, 1, U_LE);
+ U_PMF_RECTF *Rects = NULL;
+ if(!U_PMF_VARRECTS_get(&contents, lclHeader.Flags, 1, &Rects, blimit))return(0);
+ memcpy(Rect,Rects,sizeof(U_PMF_RECTF));
+ free(Rects);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_FILLPOLYGON record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param btype Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table.
+ \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates
+ \param RelAbs Set: U_PMF_PathPointTypeRLE and/or U_PMF_PathPointType objects; Clear: only U_PMF_PathPointType
+ \param BrushID Color or index of U_PMF_BRUSH object in the EMF+ object table, depending on btype.
+ \param Elements Number of members in Data.
+ \param Points Sequence of points to connect with line segments. Coordinate type set by ctype and RelAbs.
+
+ EMF+ manual 2.3.4.19, Microsoft name: EmfPlusFillPolygon Record, Index 0x0C
+*/
+int U_PMR_FILLPOLYGON_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int *btype, int *ctype, int *RelAbs,
+ uint32_t *BrushID, uint32_t *Elements,
+ U_PMF_POINTF **Points){
+ if(!contents || !btype || !ctype || !RelAbs || !BrushID || !Elements || !Points){ return(0); }
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_DRAWLINES))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 );
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *RelAbs = (lclHeader.Flags & U_PPF_R ? 1 : 0 );
+ U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */
+ U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ U_PMF_VARPOINTS_get(contents, lclHeader.Flags, *Elements, Points, blimit);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_FILLRECTS record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param btype Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table.
+ \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates
+ \param BrushID Color or index of U_PMF_BRUSH object in the EMF+ object table, depending on btype.
+ \param Elements Number of members in Data.
+ \param Rects Caller must free. Array of U_PMF_RECTF rectangles to draw.
+
+ EMF+ manual 2.3.4.20, Microsoft name: EmfPlusFillRects Record, Index 0x0A
+
+ EMF+ files have been encountered where BrushID must be a color, because it has a value like FFFF0000 but
+ the flags are set wrong, so that U_PPF_B is not set. Detect these by BrushID >63 for btype=0 and correct.
+ If the opposite problem occurs it cannot be reliably detected, so it cannot be corrected.
+
+ Rects in record may be either U_PMF_RECT or U_PMF_RECTF, but this function always
+ returns U_PMF_RECTF
+*/
+int U_PMR_FILLRECTS_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int *btype, int *ctype,
+ uint32_t *BrushID, uint32_t *Elements,
+ U_PMF_RECTF **Rects){
+ if(!contents || !btype || !ctype || !BrushID || !Elements || !Rects){ return(0); }
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_FILLRECTS))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 );
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */
+ U_PMF_SERIAL_get(&contents, Elements, 4, 1, U_LE);
+ U_PMF_VARRECTS_get(&contents, lclHeader.Flags, *Elements, Rects, blimit);
+ /* correct btype, if necessary, for invalid EMF+ input */
+ if((*BrushID > 63) & !*btype)*btype=1;
+ return(1);
+}
+
+
+/**
+ \brief Get data from a U_PMR_FILLREGION record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param RgnID U_PMF_REGION object in the EMF+ object table (0-63, inclusive)
+ \param btype Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table.
+ \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates
+ \param BrushID Color or index of U_PMF_BRUSH object in the EMF+ object table, depending on btype.
+
+ EMF+ manual 2.3.4.21, Microsoft name: EmfPlusFillRegion Record, Index 0x13
+*/
+int U_PMR_FILLREGION_get(const char *contents, U_PMF_CMN_HDR *Header,
+ uint32_t *RgnID, int *btype, int *ctype,
+ uint32_t *BrushID){
+ if(!contents || !RgnID || !btype || !ctype || !BrushID){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_FILLREGION))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *btype = (lclHeader.Flags & U_PPF_B ? 1 : 0 );
+ *ctype = (lclHeader.Flags & U_PPF_C ? 1 : 0 );
+ *RgnID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
+ U_PMF_SERIAL_get(&contents, BrushID, 4, 1, (*btype ? U_XE : U_LE)); /* color is not byte swapped, ID integer is */
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_OBJECT record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param ObjID Index for this object in the EMF+ object table (0-63, inclusive)
+ \param otype ObjectType enumeration
+ \param ntype Set: object definition continue bit is set
+ \param TSize If ntype is set, holds the total number of data bytes split across multiple records. If ntype is clear, has no meaning.
+ \param Data Object's data. Type from otype.
+
+ EMF+ manual 2.3.5.1, Microsoft name: EmfPlusObject Record, Index 0x13
+
+ Caller must check Data for possible memory access violations.
+
+ OTHER NOTES:
+ All objects are to be stored in the same table and retrieved by index.
+ Documentation indicates that this table contains only 64 slots, although the index
+ field which references it can code for values 0-127.
+ If a new object has the same index as an existing object the old one is deleted and
+ the new one goes into its storage slot.
+ The continuation bit (U_PPF_N) is documented as indicating that the object is continued into
+ the next record. Examination of emf+ records in emf files produced by PowerPoint 2003
+ show that changing the ObjID also serves as a continued record terminator, and that it apparently
+ overrides the value for the continue bit. That is, even though the preceding records said
+ that it was continued, the change of ObjID terminates that preceding record without adding
+ any more data to it. In one example the sequential emf+ records were:
+ ObjID type size continue
+ 0 5 65008 Y
+ 0 5 65008 Y
+ 0 5 63104 Y
+ 1 8 24 N
+ A DrawImagePoints record followed that referenced ObjID 0.
+ Examination of the records with continue set showed that data in each
+ was preceded by a uint32_t size value equivalent to the size of the
+ data that had been split across multiple records, in this case
+ 0x0002F254 = 193108. It is not clear at present if this size value
+ will also be present at the end of a continued series that terminates
+ by not using the continue bit, rather than changing the ObjID.
+*/
+int U_PMR_OBJECT_get(const char *contents, U_PMF_CMN_HDR *Header,
+ uint32_t *ObjID, int *otype, int *ntype, uint32_t *TSize,
+ const char **Data){
+ if(!contents || !ObjID || !otype || !ntype || !Data){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_OBJECT))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *ntype = (lclHeader.Flags & U_PPF_N ? 1 : 0 );
+ *ObjID = (lclHeader.Flags >> U_FF_SHFT_OID8) & U_FF_MASK_OID8;
+ *otype = (lclHeader.Flags >> U_FF_SHFT_OT) & U_FF_MASK_OT;
+ if(*ntype){ U_PMF_SERIAL_get(&contents, TSize, 4, 1, U_LE); }
+ else { *TSize = 0; }
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_SERIALIZABLEOBJECT record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param GUID ImageEffects identifier.
+ \param Size Bytes in Data.
+ \param Data "Serialized image effects parameter block". One of the ImageEffects objects.
+
+ EMF+ manual 2.3.5.2, Microsoft name: EmfPlusSerializableObject Record, Index 0x38
+
+ Caller must check Data for possible memory access violations.
+*/
+int U_PMR_SERIALIZABLEOBJECT_get(const char *contents, U_PMF_CMN_HDR *Header,
+ uint8_t *GUID, uint32_t *Size,
+ const char **Data){
+ if(!contents || !GUID || !Size || !Data){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SERIALIZABLEOBJECT))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ U_PMF_SERIAL_get(&contents, GUID, 1, 16, U_XE);
+ U_PMF_SERIAL_get(&contents, Size, 4, 1, U_LE);
+ U_PMF_PTRSAV_SHIFT(Data, &contents, 0);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_SETANTIALIASMODE record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param SMenum SmoothingMode enumeration
+ \param aatype Set: anti-aliasing on; Clear: anti-aliasing off
+
+ EMF+ manual 2.3.6.1, Microsoft name: EmfPlusSetAntiAliasMode Record, Index 0x1E
+*/
+int U_PMR_SETANTIALIASMODE_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int *SMenum, int *aatype){
+ if(!contents || !SMenum || !aatype){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SETANTIALIASMODE))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *aatype = (lclHeader.Flags & U_PPF_AA ? 1 : 0 );
+ *SMenum = (lclHeader.Flags >> U_FF_SHFT_AA) & U_FF_MASK_AA;
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_SETCOMPOSITINGMODE record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param CMenum CompositingMode enumeration
+
+ EMF+ manual 2.3.6.2, Microsoft name: EmfPlusSetCompositingMode Record, Index 0x23
+*/
+int U_PMR_SETCOMPOSITINGMODE_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int *CMenum){
+ /* memory access safe, only uses the common header */
+ if(!contents || !CMenum){ return(0); }
+ uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
+ *CMenum = (Flags >> U_FF_SHFT_CM) & U_FF_MASK_CM;
+ U_PMF_CMN_HDR_get(&contents, Header);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_SETCOMPOSITINGQUALITY record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param CQenum CompositingQuality enumeration
+
+ EMF+ manual 2.3.6.3, Microsoft name: EmfPlusSetCompositingQuality Record, Index 0x24
+*/
+int U_PMR_SETCOMPOSITINGQUALITY_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int *CQenum){
+ /* memory access safe, only uses the common header */
+ if(!contents || !CQenum){ return(0); }
+ uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
+ *CQenum = (Flags >> U_FF_SHFT_CQ) & U_FF_MASK_CQ;
+ U_PMF_CMN_HDR_get(&contents, Header);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_SETINTERPOLATIONMODE record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param IMenum InterpolationMode enumeration
+
+ EMF+ manual 2.3.6.4, Microsoft name: EmfPlusSetInterpolationMode Record, Index 0x21
+*/
+int U_PMR_SETINTERPOLATIONMODE_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int *IMenum){
+ /* memory access safe, only uses the common header */
+ if(!contents || !IMenum){ return(0); }
+ uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
+ *IMenum = (Flags >> U_FF_SHFT_IM) & U_FF_MASK_IM;
+ U_PMF_CMN_HDR_get(&contents, Header);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_SETPIXELOFFSETMODE record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param POMenum PixelOffsetMode enumeration.
+
+ EMF+ manual 2.3.6.5, Microsoft name: EmfPlusSetPixelOffsetMode Record, Index 0x22
+*/
+int U_PMR_SETPIXELOFFSETMODE_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int *POMenum){
+ /* memory access safe, only uses the common header */
+ if(!contents || !POMenum){ return(0); }
+ uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
+ *POMenum = (Flags >> U_FF_SHFT_PxOffM) & U_FF_MASK_PxOffM;
+ U_PMF_CMN_HDR_get(&contents, Header);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_SETRENDERINGORIGIN record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header.
+ \param X X coordinate of rendering origin.
+ \param Y Y coordinate of rendering origin.
+
+ EMF+ manual 2.3.6.6, Microsoft name: EmfPlusSetRenderingOrigin Record, Index 0x1D
+*/
+int U_PMR_SETRENDERINGORIGIN_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int32_t *X, int32_t *Y){
+ if(!contents || !X || !Y){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ if(!U_PMF_CMN_HDR_get(&contents, &lclHeader))return(0);
+ if(lclHeader.Size < sizeof(U_PMF_SETRENDERINGORIGIN))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ U_PMF_SERIAL_get(&contents, X, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Y, 4, 1, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_SETTEXTCONTRAST record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header.
+ \param TGC Text Gamma correction value (x 1000).
+
+ EMF+ manual 2.3.6.7, Microsoft name: EmfPlusSetTextContrast Record, Index 0x20
+*/
+int U_PMR_SETTEXTCONTRAST_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int *TGC){
+ /* memory access safe, only uses the common header */
+ if(!contents || !TGC){ return(0); }
+ uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
+ *TGC = (Flags >> U_FF_SHFT_TGC) & U_FF_MASK_TGC;
+ U_PMF_CMN_HDR_get(&contents, Header);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_SETTEXTRENDERINGHINT record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header.
+ \param TRHenum TextRenderingHint enumeration
+
+ EMF+ manual 2.3.6.8, Microsoft name: EmfPlusSetTextRenderingHint Record, Index 0x1F
+*/
+int U_PMR_SETTEXTRENDERINGHINT_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int *TRHenum){
+ /* memory access safe, only uses the common header */
+ if(!contents || !TRHenum){ return(0); }
+ uint16_t Flags = U_PMF_HEADERFLAGS_get(contents);
+ *TRHenum = (Flags >> U_FF_SHFT_TRH) & U_FF_MASK_TRH;
+ U_PMF_CMN_HDR_get(&contents, Header);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_BEGINCONTAINER record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param UTenum UnitType enumeration
+ \param DstRect with SrcRect specifies a transformation
+ \param SrcRect with DstRect specifies a transformation
+ \param StackID EMF+ Object Stack Index to use for this graphics container
+
+ EMF+ manual 2.3.7.1, Microsoft name: EmfPlusBeginContainer Record, Index 0x27
+*/
+int U_PMR_BEGINCONTAINER_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int *UTenum,
+ U_PMF_RECTF *DstRect, U_PMF_RECTF *SrcRect, uint32_t *StackID){
+ if(!contents || !UTenum || !DstRect || !SrcRect || !StackID){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SETCLIPREGION))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *UTenum = (lclHeader.Flags >> U_FF_SHFT_UT) & U_FF_MASK_UT;
+ U_PMF_SERIAL_get(&contents, DstRect, 4, 4, U_LE);
+ U_PMF_SERIAL_get(&contents, SrcRect, 4, 4, U_LE);
+ U_PMF_SERIAL_get(&contents, StackID, 4, 1, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_BEGINCONTAINERNOPARAMS record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param StackID EMF+ Object Stack Index to use for this graphics container
+
+ EMF+ manual 2.3.7.2, Microsoft name: EmfPlusBeginContainerNoParams Record, Index 0x28
+*/
+int U_PMR_BEGINCONTAINERNOPARAMS_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID){
+ return(U_PMR_common_stack_get(contents, Header, StackID));
+}
+
+/**
+ \brief Get data from a U_PMR_ENDCONTAINER record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param StackID EMF+ Object Stack Index of this graphics container
+
+ EMF+ manual 2.3.7.3, Microsoft name: EmfPlusEndContainer Record, Index 0x29
+*/
+int U_PMR_ENDCONTAINER_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID){
+ return(U_PMR_common_stack_get(contents, Header, StackID));
+}
+
+/**
+ \brief Get data from a U_PMR_RESTORE record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param StackID State (level) to restore from the EMF+ Graphics Stack. Must have been put on the GS with a U_PMR_SAVE.
+
+ EMF+ manual 2.3.7.4, Microsoft name: EmfPlusRestore Record, Index 0x26
+*/
+int U_PMR_RESTORE_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID){
+ return(U_PMR_common_stack_get(contents, Header, StackID));
+}
+
+/**
+ \brief Get data from a U_PMR_SAVE record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param StackID State (level) to save.on the EMF+ Graphics Stack
+
+ EMF+ manual 2.3.7.5, Microsoft name: EmfPlusSave Record, Index 0x25
+*/
+int U_PMR_SAVE_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID){
+ return(U_PMR_common_stack_get(contents, Header, StackID));
+}
+
+/**
+ \brief Get data from a U_PMR_SETTSCLIP record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param ctype Set: int16_t coordinates; Clear: U_FLOAT coordinates
+ \param Elements Number of members in Data.
+ \param Rects Caller must free. Array of rectangles to draw. Coordinate type set by ctype.
+
+ EMF+ manual 2.3.8.1, Microsoft name: EmfPlusSetTSClip Record, Index 0x3A
+*/
+int U_PMR_SETTSCLIP_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int *ctype, uint32_t *Elements,
+ U_PMF_RECTF **Rects){
+ if(!contents || !ctype || !Elements || !Rects){ return(0); }
+
+ const char *blimit = contents;
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SETTSCLIP))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+ blimit += lclHeader.Size;
+
+ *ctype = (lclHeader.Flags & U_PPF_K ? 1 : 0 );
+ *Elements = (lclHeader.Flags >> U_FF_SHFT_TSC) & U_FF_MASK_TSC;
+ U_PMF_VARRECTS_get(&contents, lclHeader.Flags, *Elements, Rects, blimit);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_SETTSGRAPHICS record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param vgatype Set: Palette is VGA basic colors; Clear: Palette is ???
+ \param pptype Set: Palette is present; Clear: Palette is absent.
+ \param AntiAliasMode SmoothingMode enumeration
+ \param TextRenderHint TextRenderingHint enumeration
+ \param CompositingMode CompositingMode enumeration
+ \param CompositingQuality CompositingQuality enumeration
+ \param RenderOriginX Origin X for halftoning and dithering
+ \param RenderOriginY Origin Y for halftoning and dithering
+ \param TextContrast Gamma correction, range 0 to 12
+ \param FilterType FilterType enumeraton
+ \param PixelOffset PixelOffsetMode enumeration
+ \param WorldToDevice world to device transform
+ \param Data Palette (optional)
+
+ EMF+ manual 2.3.8.2, Microsoft name: EmfPlusSetTSGraphics Record, Index 0x39
+
+ Caller must check Data for possible memory access violations.
+*/
+int U_PMR_SETTSGRAPHICS_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int *vgatype, int *pptype,
+ uint8_t *AntiAliasMode, uint8_t *TextRenderHint, uint8_t *CompositingMode, uint8_t *CompositingQuality,
+ int16_t *RenderOriginX, int16_t *RenderOriginY, uint16_t *TextContrast, uint8_t *FilterType,
+ uint8_t *PixelOffset, U_PMF_TRANSFORMMATRIX *WorldToDevice,
+ const char **Data){
+ if(!contents || !vgatype || !pptype ||
+ !AntiAliasMode || !TextRenderHint || !CompositingMode || !CompositingQuality ||
+ !RenderOriginX || !RenderOriginY || !TextContrast || !FilterType ||
+ !PixelOffset || !WorldToDevice || !Data){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SETTSGRAPHICS))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *vgatype = (lclHeader.Flags & U_PPF_VGA ? 1 : 0 );
+ *pptype = (lclHeader.Flags & U_PPF_PP ? 1 : 0 );
+ U_PMF_SERIAL_get(&contents, AntiAliasMode, 1, 1, U_XE);
+ U_PMF_SERIAL_get(&contents, TextRenderHint, 1, 1, U_XE);
+ U_PMF_SERIAL_get(&contents, CompositingMode, 1, 1, U_XE);
+ U_PMF_SERIAL_get(&contents, CompositingQuality, 1, 1, U_XE);
+ U_PMF_SERIAL_get(&contents, RenderOriginX, 2, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, RenderOriginY, 2, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, TextContrast, 2, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, FilterType, 1, 1, U_XE);
+ U_PMF_SERIAL_get(&contents, WorldToDevice, 4, 6, U_LE);
+ U_PMF_PTRSAV_COND(Data, contents, *pptype);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_MULTIPLYWORLDTRANSFORM record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param xmtype Set: Post multiply; Clear: Pre multiply
+ \param Matrix Transformation matrix
+
+ EMF+ manual 2.3.9.1, Microsoft name: EmfPlusMultiplyWorldTransform Record, Index 0x2C
+*/
+int U_PMR_MULTIPLYWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int *xmtype,
+ U_PMF_TRANSFORMMATRIX *Matrix){
+ if(!contents || !xmtype || !Matrix){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_MULTIPLYWORLDTRANSFORM))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *xmtype = (lclHeader.Flags & U_PPF_XM ? 1 : 0 );
+ U_PMF_SERIAL_get(&contents, Matrix, 4, 6, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_RESETWORLDTRANSFORM record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+
+ EMF+ manual 2.3.9.2, Microsoft name: EmfPlusResetWorldTransform Record, Index 0x2B
+*/
+int U_PMR_RESETWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header){
+ return( U_PMR_common_header_get(contents,Header));
+}
+
+/**
+ \brief Get data from a U_PMR_ROTATEWORLDTRANSFORM record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param xmtype Set: Post multiply; Clear: Pre multiply
+ \param Angle Rotation angle, in degrees
+
+ EMF+ manual 2.3.9.3, Microsoft name: EmfPlusRotateWorldTransform Record, Index 0x2F
+*/
+int U_PMR_ROTATEWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int *xmtype,
+ U_FLOAT *Angle){
+ if(!contents || !xmtype || !Angle){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_ROTATEWORLDTRANSFORM))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *xmtype = (lclHeader.Flags & U_PPF_XM ? 1 : 0 );
+ U_PMF_SERIAL_get(&contents, Angle, 4, 1, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_SCALEWORLDTRANSFORM record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param xmtype Set: Post multiply; Clear: Pre multiply.
+ \param Sx X scale factor.
+ \param Sy Y scale factor.
+
+ EMF+ manual 2.3.9.4, Microsoft name: EmfPlusScaleWorldTransform Record, Index 0x2E
+*/
+int U_PMR_SCALEWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int *xmtype,
+ U_FLOAT *Sx, U_FLOAT *Sy){
+ if(!contents || !xmtype || !Sx || !Sy){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SCALEWORLDTRANSFORM))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *xmtype = (lclHeader.Flags & U_PPF_XM ? 1 : 0 );
+ U_PMF_SERIAL_get(&contents, Sx, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Sy, 4, 1, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_SETPAGETRANSFORM record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param PUenum Page Unit, UnitType enumeration
+ \param Scale Scale factor to convert page space to device space
+
+ EMF+ manual 2.3.9.5, Microsoft name: EmfPlusSetPageTransform Record, Index 0x30
+*/
+int U_PMR_SETPAGETRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int *PUenum,
+ U_FLOAT *Scale){
+ if(!contents || !PUenum || !Scale){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SETPAGETRANSFORM))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *PUenum = (lclHeader.Flags >> U_FF_SHFT_PU) & U_FF_MASK_PU;
+ U_PMF_SERIAL_get(&contents, Scale, 4, 1, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_SETWORLDTRANSFORM record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param Matrix Transformation matrix
+
+ EMF+ manual 2.3.9.6, Microsoft name: EmfPlusSetWorldTransform Record, Index 0x2A
+*/
+int U_PMR_SETWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header,
+ U_PMF_TRANSFORMMATRIX *Matrix){
+ if(!contents || !Matrix){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_SETWORLDTRANSFORM))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ U_PMF_SERIAL_get(&contents, Matrix, 4, 6, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_TRANSLATEWORLDTRANSFORM record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header
+ \param xmtype Set: Post multiply; Clear: Pre multiply
+ \param Dx X offset
+ \param Dy Y offset
+
+ EMF+ manual 2.3.9.7, Microsoft name: EmfPlusTranslateWorldTransform Record, Index 0x2D
+*/
+int U_PMR_TRANSLATEWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header,
+ int *xmtype,
+ U_FLOAT *Dx, U_FLOAT *Dy){
+ if(!contents || !xmtype || !Dx || !Dy){ return(0); }
+
+ U_PMF_CMN_HDR lclHeader;
+ U_PMF_CMN_HDR_get(&contents, &lclHeader);
+ if(lclHeader.Size < sizeof(U_PMF_TRANSLATEWORLDTRANSFORM))return(0);
+ if(Header){ memcpy(Header,&lclHeader,sizeof(U_PMF_CMN_HDR)); }
+
+ *xmtype = (lclHeader.Flags & U_PPF_XM ? 1 : 0 );
+ U_PMF_SERIAL_get(&contents, Dx, 4, 1, U_LE);
+ U_PMF_SERIAL_get(&contents, Dy, 4, 1, U_LE);
+ return(1);
+}
+
+/**
+ \brief Get data from a U_PMR_STROKEFILLPATH record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header (ignore flags)
+
+
+ EMF+ manual mentioned in 2.1.1.1, not otherwise documented, Microsoft name: EmfPlusStrokeFillPath Record, Index 0x37
+
+ "This record closes any open figures in a path, strokes the outline of
+ the path by using the current pen, and fills its interior by using the current brush."
+*/
+int U_PMR_STROKEFILLPATH_get(const char *contents, U_PMF_CMN_HDR *Header){
+ return( U_PMR_common_header_get(contents,Header));
+}
+
+/**
+ \brief Get data from a U_PMR_MULTIFORMATSTART record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header (ignore flags)
+
+ EMF+ manual mentioned in 2.1.1.1, reserved, not otherwise documented, Microsoft name: EmfPlusMultiFormatStart Record, Index 0x05
+*/
+int U_PMR_MULTIFORMATSTART_get(const char *contents, U_PMF_CMN_HDR *Header){
+ return( U_PMR_common_header_get(contents,Header));
+}
+
+/**
+ \brief Get data from a U_PMR_MULTIFORMATSECTION record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header (ignore flags)
+
+ EMF+ manual mentioned in 2.1.1.1, reserved, not otherwise documented, Microsoft name: EmfPlusMultiFormatSection Record, Index 0x06
+*/
+int U_PMR_MULTIFORMATSECTION_get(const char *contents, U_PMF_CMN_HDR *Header){
+ return( U_PMR_common_header_get(contents,Header));
+}
+
+/**
+ \brief Get data from a U_PMR_MULTIFORMATEND record
+ \return 1 on success, 0 on error
+ \param contents Record from which to extract data
+ \param Header Common header (ignore flags)
+
+ EMF+ manual mentioned in 2.1.1.1, reserved, not otherwise documented, Microsoft name: EmfPlusMultiFormatEnd Record, Index 0x06
+*/
+int U_PMR_MULTIFORMATEND_get(const char *contents, U_PMF_CMN_HDR *Header){
+ return( U_PMR_common_header_get(contents,Header));
+}
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/3rdparty/libuemf/upmf.h b/src/3rdparty/libuemf/upmf.h
new file mode 100644
index 0000000..c793746
--- /dev/null
+++ b/src/3rdparty/libuemf/upmf.h
@@ -0,0 +1,3178 @@
+/**
+ @file upmf.h
+
+ @brief Structures, definitions, and function prototypes for EMF+ files.
+
+ EMF+ file Record structure derived from Microsoft's EMF+ Information pdf, releade date July 5,2012, link from
+ here:
+
+ http://msdn.microsoft.com/en-us/library/cc230724.aspx
+
+ If the direct link fails the document may be found
+ by searching for: "[MS-EMFPLUS]: Enhanced Metafile Format Plus Extensions "
+
+ EMR records and structures are EMF or common with EMF+
+ PMR records and structures are specific to EMF+
+
+ Using PMF instead of EMF+ because "+" is a problem in symbol names.
+
+ *****************************************************************************************
+ * WARNING: Microsoft's EMF+ documentation is little-endian for everything EXCEPT *
+ * bitfields, which are big-endian. See section 1.3.2 *
+ * That documentation also uses 0 as the MOST significant bit, N-1 as the least. *
+ * This code is little-endian throughout, and 0 is the LEAST significant bit *
+ *****************************************************************************************
+
+*/
+
+/*
+File: upmf.h
+Version: 0.0.6
+Date: 13-MAY-2020
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2020 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifndef _UPMF_
+#define _UPMF_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "uemf.h"
+
+
+/** \defgroup U_PMF_PMF_Misc PMF Miscellaneous defines
+ @{
+*/
+#define U_PMF_DROP_ELEMENTS 1 //!< Remove leading Elements value from data.
+#define U_PMF_KEEP_ELEMENTS 0 //!< Retain leading Elements value from data.
+
+#define U_SEG_NEW 1 //!< start a new segment in the path
+#define U_SEG_OLD 0 //!< continue the old (current) segment in the path
+
+#define U_FILTER_APPLY 1 //!< With U_PMR_DRAWIMAGEPOINTS_set, use whatever filter has been set up up.
+#define U_FILTER_IGNORE 0 //!< With U_PMR_DRAWIMAGEPOINTS_set, ignore whatever filter has been set up up.
+#define U_OBJRECLIM 65020 //!< Longest U_PMR_OBJECT that GDI+ will process
+ // used 9728 to test fragmenting of emitted object records
+
+/** @} */
+
+/** \defgroup U_PMF_DD_ PMF "standard" custom Dash Dot patterns for lines.
+
+ U_DD_DASH, U_DD_DOT, U_DD_DASHDOT, and U_DD_DASHDOTDOT are the only ones with corresponding
+ standard EMF and EMF+ dash/dot patterns.
+
+ These values are used to tell U_PMF_DASHEDLINEDATA_set2() to create one of 27 custom line patterns.
+ Other custom line patterns may be created using U_PMF_DASHEDLINEDATA_set(), but this provides an easier
+ way to get the same result if one of these patterns is acceptable.
+
+ The length is divided by 2X the number of elements, so dashdash has twice as many
+ dashes of half the length as just dash.
+
+ Dot is 1/8 of (sub)unit length
+ Dash is 1/2 of (sub)unit length
+ Long is 3/4 of (sub)unit length
+ Example: DotDot has (sub)unit length 1/2, so each dot will be 1/16 of unit length.
+
+ @{
+*/
+#define U_DD_Solid 0 //!< Solid line.
+#define U_DD_Dash 1 //!< Dash line.
+#define U_DD_DashDash 2 //!< Dash Dash line.
+#define U_DD_DashDashDash 3 //!< Dash Dash Dash line.
+#define U_DD_DashDashDashDash 4 //!< Dash Dash Dash Dash line.
+#define U_DD_Dot 5 //!< Dot line.
+#define U_DD_DotDot 6 //!< Dot Dot line.
+#define U_DD_DotDotDot 7 //!< Dot Dot Dot line.
+#define U_DD_DotDotDotDot 8 //!< Dot Dot Dot Dot line.
+#define U_DD_DashDot 9 //!< Dash Dot line.
+#define U_DD_DashDashDot 10 //!< Dash Dash Dot line.
+#define U_DD_DashDashDotDot 11 //!< Dash Dash Dot Dot line.
+#define U_DD_DashDashDashDot 12 //!< Dash Dash Das hDot line.
+#define U_DD_DashDotDot 13 //!< Dash Dot Dot line.
+#define U_DD_DashDotDotDot 14 //!< Dash Dot Dot Dot line.
+#define U_DD_DashDotDashDot 15 //!< Dash Dot Dash Dot line.
+#define U_DD_Long 16 //!< Long line.
+#define U_DD_LongLong 17 //!< Long Long line.
+#define U_DD_LongLongLong 18 //!< Long Long Long line.
+#define U_DD_LongLongLongLong 19 //!< Long Long Long Long line.
+#define U_DD_LongDot 20 //!< Long Dot line.
+#define U_DD_LongLongDot 21 //!< Long Long Dot line.
+#define U_DD_LongLongDotDot 22 //!< Long Long Dot Dot line.
+#define U_DD_LongLongLongDot 23 //!< Long Long Long Dot line.
+#define U_DD_LongDotDot 24 //!< Long Dot Dot line.
+#define U_DD_LongDotDotDot 25 //!< Long Dot Dot Dot line.
+#define U_DD_LongDotLongDot 26 //!< Long Dot Long Dot line.
+#define U_DD_Types 27 //!< Types
+
+/** @} */
+
+
+/** \defgroup U_PMF_PMR_Qualifiers PMF RecordType Enumeration
+ EMF+ manual 2.1.1.1, Microsoft name: RecordType Enumeration
+ @{
+*/
+#define U_PMR_HEADER 0x0001 //!< U_PMRHeader record
+#define U_PMR_ENDOFFILE 0x0002 //!< U_PMREndOfFile record
+#define U_PMR_COMMENT 0x0003 //!< U_PMRComment record
+#define U_PMR_GETDC 0x0004 //!< U_PMRGetDC record
+#define U_PMR_MULTIFORMATSTART 0x0005 //!< U_PMRMultiFormatStart record
+#define U_PMR_MULTIFORMATSECTION 0x0006 //!< U_PMRMultiFormatSection record
+#define U_PMR_MULTIFORMATEND 0x0007 //!< U_PMRMultiFormatEnd record
+#define U_PMR_OBJECT 0x0008 //!< U_PMRObject record
+#define U_PMR_CLEAR 0x0009 //!< U_PMRClear record
+#define U_PMR_FILLRECTS 0x000A //!< U_PMRFillRects record
+#define U_PMR_DRAWRECTS 0x000B //!< U_PMRDrawRects record
+#define U_PMR_FILLPOLYGON 0x000C //!< U_PMRFillPolygon record
+#define U_PMR_DRAWLINES 0x000D //!< U_PMRDrawLines record
+#define U_PMR_FILLELLIPSE 0x000E //!< U_PMRFillEllipse record
+#define U_PMR_DRAWELLIPSE 0x000F //!< U_PMRDrawEllipse record
+#define U_PMR_FILLPIE 0x0010 //!< U_PMRFillPie record
+#define U_PMR_DRAWPIE 0x0011 //!< U_PMRDrawPie record
+#define U_PMR_DRAWARC 0x0012 //!< U_PMRDrawArc record
+#define U_PMR_FILLREGION 0x0013 //!< U_PMRFillRegion record
+#define U_PMR_FILLPATH 0x0014 //!< U_PMRFillPath record
+#define U_PMR_DRAWPATH 0x0015 //!< U_PMRDrawPath record
+#define U_PMR_FILLCLOSEDCURVE 0x0016 //!< U_PMRFillClosedCurve record
+#define U_PMR_DRAWCLOSEDCURVE 0x0017 //!< U_PMRDrawClosedCurve record
+#define U_PMR_DRAWCURVE 0x0018 //!< U_PMRDrawCurve record
+#define U_PMR_DRAWBEZIERS 0x0019 //!< U_PMRDrawBeziers record
+#define U_PMR_DRAWIMAGE 0x001A //!< U_PMRDrawImage record
+#define U_PMR_DRAWIMAGEPOINTS 0x001B //!< U_PMRDrawImagePoints record
+#define U_PMR_DRAWSTRING 0x001C //!< U_PMRDrawString record
+#define U_PMR_SETRENDERINGORIGIN 0x001D //!< U_PMRSetRenderingOrigin record
+#define U_PMR_SETANTIALIASMODE 0x001E //!< U_PMRSetAntiAliasMode record
+#define U_PMR_SETTEXTRENDERINGHINT 0x001F //!< U_PMRSetTextRenderingHint record
+#define U_PMR_SETTEXTCONTRAST 0x0020 //!< U_PMRSetTextContrast record
+#define U_PMR_SETINTERPOLATIONMODE 0x0021 //!< U_PMRSetInterpolationMode record
+#define U_PMR_SETPIXELOFFSETMODE 0x0022 //!< U_PMRSetPixelOffsetMode record
+#define U_PMR_SETCOMPOSITINGMODE 0x0023 //!< U_PMRSetCompositingMode record
+#define U_PMR_SETCOMPOSITINGQUALITY 0x0024 //!< U_PMRSetCompositingQuality record
+#define U_PMR_SAVE 0x0025 //!< U_PMRSave record
+#define U_PMR_RESTORE 0x0026 //!< U_PMRRestore record
+#define U_PMR_BEGINCONTAINER 0x0027 //!< U_PMRBeginContainer record
+#define U_PMR_BEGINCONTAINERNOPARAMS 0x0028 //!< U_PMRBeginContainerNoParams record
+#define U_PMR_ENDCONTAINER 0x0029 //!< U_PMREndContainer record
+#define U_PMR_SETWORLDTRANSFORM 0x002A //!< U_PMRSetWorldTransform record
+#define U_PMR_RESETWORLDTRANSFORM 0x002B //!< U_PMRResetWorldTransform record
+#define U_PMR_MULTIPLYWORLDTRANSFORM 0x002C //!< U_PMRMultiplyWorldTransform record
+#define U_PMR_TRANSLATEWORLDTRANSFORM 0x002D //!< U_PMRTranslateWorldTransform record
+#define U_PMR_SCALEWORLDTRANSFORM 0x002E //!< U_PMRScaleWorldTransform record
+#define U_PMR_ROTATEWORLDTRANSFORM 0x002F //!< U_PMRRotateWorldTransform record
+#define U_PMR_SETPAGETRANSFORM 0x0030 //!< U_PMRSetPageTransform record
+#define U_PMR_RESETCLIP 0x0031 //!< U_PMRResetClip record
+#define U_PMR_SETCLIPRECT 0x0032 //!< U_PMRSetClipRect record
+#define U_PMR_SETCLIPPATH 0x0033 //!< U_PMRSetClipPath record
+#define U_PMR_SETCLIPREGION 0x0034 //!< U_PMRSetClipRegion record
+#define U_PMR_OFFSETCLIP 0x0035 //!< U_PMROffsetClip record
+#define U_PMR_DRAWDRIVERSTRING 0x0036 //!< U_PMRDrawDriverstring record
+#define U_PMR_STROKEFILLPATH 0x0037 //!< U_PMRStrokeFillPath record
+#define U_PMR_SERIALIZABLEOBJECT 0x0038 //!< U_PMRSerializableObject record
+#define U_PMR_SETTSGRAPHICS 0x0039 //!< U_PMRSetTSGraphics record
+#define U_PMR_SETTSCLIP 0x003A //!< U_PMRSetTSClip record
+#define U_PMR_RECFLAG 0x4000 //!< In EMF+ files the type is one of the above + this flag
+#define U_PMR_TYPE_MASK 0x003F //!< mask for EMF+ types
+#define U_PMR_MIN 1 //!< Minimum U_PMR_ value.
+#define U_PMR_MAX 58 //!< Maximum U_PMR_ value.
+
+/** @} */
+
+/** \defgroup U_PMF_PID_Values PMF Identifiers for PseudoObjects
+ These are used by the *_set routines to identify types of PseudoObject.
+ Note that records are U_PMR_*_OID and other objects are U_PMF_*_OID
+ The numbers are derived from the EMF+ manual sections, as in 2.2.1.3 become
+ 02020103. Numbers 40000000 and up are not derived from manual setions.
+ @{
+*/
+#define U_UNDEFINED_OID 0x00000000 //!< Undefined PseudoObject
+#define U_PMF_BRUSH_OID 0x02020101 //!< PMF_BRUSH PseudoObject type.
+#define U_PMF_CUSTOMLINECAP_OID 0x02020102 //!< PMF_CUSTOMLINECAP PseudoObject type.
+#define U_PMF_FONT_OID 0x02020103 //!< PMF_FONT PseudoObject type.
+#define U_PMF_IMAGE_OID 0x02020104 //!< PMF_IMAGE PseudoObject type.
+#define U_PMF_IMAGEATTRIBUTES_OID 0x02020105 //!< PMF_IMAGEATTRIBUTES PseudoObject type.
+#define U_PMF_PATH_OID 0x02020106 //!< PMF_PATH PseudoObject type.
+#define U_PMF_PEN_OID 0x02020107 //!< PMF_PEN PseudoObject type.
+#define U_PMF_REGION_OID 0x02020108 //!< PMF_REGION PseudoObject type.
+#define U_PMF_STRINGFORMAT_OID 0x02020109 //!< PMF_STRINGFORMAT PseudoObject type.
+#define U_PMF_ARGB_OID 0x02020201 //!< PMF_ARGB PseudoObject type.
+#define U_PMF_BITMAP_OID 0x02020202 //!< PMF_BITMAP PseudoObject type.
+#define U_PMF_BITMAPDATA_OID 0x02020203 //!< PMF_BITMAPDATA PseudoObject type.
+#define U_PMF_BLENDCOLORS_OID 0x02020204 //!< PMF_BLENDCOLORS PseudoObject type.
+#define U_PMF_BLENDFACTORS_OID 0x02020205 //!< PMF_BLENDFACTORS PseudoObject type.
+#define U_PMF_BOUNDARYPATHDATA_OID 0x02020206 //!< PMF_BOUNDARYPATHDATA PseudoObject type.
+#define U_PMF_BOUNDARYPOINTDATA_OID 0x02020207 //!< PMF_BOUNDARYPOINTDATA PseudoObject type.
+#define U_PMF_CHARACTERRANGE_OID 0x02020208 //!< PMF_CHARACTERRANGE PseudoObject type.
+#define U_PMF_COMPOUNDLINEDATA_OID 0x02020209 //!< PMF_COMPOUNDLINEDATA PseudoObject type.
+#define U_PMF_COMPRESSEDIMAGE_OID 0x02020210 //!< PMF_COMPRESSEDIMAGE PseudoObject type.
+#define U_PMF_CUSTOMENDCAPDATA_OID 0x02020211 //!< PMF_CUSTOMENDCAPDATA PseudoObject type.
+#define U_PMF_CUSTOMLINECAPARROWDATA_OID 0x02020212 //!< PMF_CUSTOMLINECAPARROWDATA PseudoObject type.
+#define U_PMF_CUSTOMLINECAPDATA_OID 0x02020213 //!< PMF_CUSTOMLINECAPDATA PseudoObject type.
+#define U_PMF_CUSTOMLINECAPOPTIONALDATA_OID 0x02020214 //!< PMF_CUSTOMLINECAPOPTIONALDATA PseudoObject type.
+#define U_PMF_CUSTOMSTARTCAPDATA_OID 0x02020215 //!< PMF_CUSTOMSTARTCAPDATA PseudoObject type.
+#define U_PMF_DASHEDLINEDATA_OID 0x02020216 //!< PMF_DASHEDLINEDATA PseudoObject type.
+#define U_PMF_FILLPATHOBJ_OID 0x02020217 //!< PMF_FILLPATHOBJ PseudoObject type.
+#define U_PMF_FOCUSSCALEDATA_OID 0x02020218 //!< PMF_FOCUSSCALEDATA PseudoObject type.
+#define U_PMF_GRAPHICSVERSION_OID 0x02020219 //!< PMF_GRAPHICSVERSION PseudoObject type.
+#define U_PMF_HATCHBRUSHDATA_OID 0x02020220 //!< PMF_HATCHBRUSHDATA PseudoObject type.
+#define U_PMF_INTEGER7_OID 0x02020221 //!< PMF_INTEGER7 PseudoObject type.
+#define U_PMF_INTEGER15_OID 0x02020222 //!< PMF_INTEGER15 PseudoObject type.
+#define U_PMF_LANGUAGEIDENTIFIER_OID 0x02020223 //!< PMF_LANGUAGEIDENTIFIER PseudoObject type.
+#define U_PMF_LINEARGRADIENTBRUSHDATA_OID 0x02020224 //!< PMF_LINEARGRADIENTBRUSHDATA PseudoObject type.
+#define U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_OID 0x02020225 //!< PMF_LINEARGRADIENTBRUSHOPTIONALDATA PseudoObject type.
+#define U_PMF_LINEPATH_OID 0x02020226 //!< PMF_LINEPATH PseudoObject type.
+#define U_PMF_METAFILE_OID 0x02020227 //!< PMF_METAFILE PseudoObject type.
+#define U_PMF_PALETTE_OID 0x02020228 //!< PMF_PALETTE PseudoObject type.
+#define U_PMF_PATHGRADIENTBRUSHDATA_OID 0x02020229 //!< PMF_PATHGRADIENTBRUSHDATA PseudoObject type.
+#define U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_OID 0x02020230 //!< PMF_PATHGRADIENTBRUSHOPTIONALDATA PseudoObject type.
+#define U_PMF_PATHPOINTTYPE_OID 0x02020231 //!< PMF_PATHPOINTTYPE PseudoObject type.
+#define U_PMF_PATHPOINTTYPERLE_OID 0x02020232 //!< PMF_PATHPOINTTYPERLE PseudoObject type.
+#define U_PMF_PENDATA_OID 0x02020233 //!< PMF_PENDATA PseudoObject type.
+#define U_PMF_PENOPTIONALDATA_OID 0x02020234 //!< PMF_PENOPTIONALDATA PseudoObject type.
+#define U_PMF_POINT_OID 0x02020235 //!< PMF_POINT PseudoObject type.
+#define U_PMF_POINTF_OID 0x02020236 //!< PMF_POINTF PseudoObject type.
+#define U_PMF_POINTR_OID 0x02020237 //!< PMF_POINTR PseudoObject type.
+#define U_PMF_RECT_OID 0x02020238 //!< PMF_RECT PseudoObject type.
+#define U_PMF_RECTF_OID 0x02020239 //!< PMF_RECTF PseudoObject type.
+#define U_PMF_REGIONNODE_OID 0x02020240 //!< PMF_REGIONNODE PseudoObject type.
+#define U_PMF_REGIONNODECHILDNODES_OID 0x02020241 //!< PMF_REGIONNODECHILDNODES PseudoObject type.
+#define U_PMF_REGIONNODEPATH_OID 0x02020242 //!< PMF_REGIONNODEPATH PseudoObject type.
+#define U_PMF_SOLIDBRUSHDATA_OID 0x02020243 //!< PMF_SOLIDBRUSHDATA PseudoObject type.
+#define U_PMF_STRINGFORMATDATA_OID 0x02020244 //!< PMF_STRINGFORMATDATA PseudoObject type.
+#define U_PMF_TEXTUREBRUSHDATA_OID 0x02020245 //!< PMF_TEXTUREBRUSHDATA PseudoObject type.
+#define U_PMF_TEXTUREBRUSHOPTIONALDATA_OID 0x02020246 //!< PMF_TEXTUREBRUSHOPTIONALDATA PseudoObject type.
+#define U_PMF_TRANSFORMMATRIX_OID 0x02020247 //!< PMF_TRANSFORMMATRIX PseudoObject type.
+#define U_PMF_IE_BLUR_OID 0x02020301 //!< PMF_IE_BLUR PseudoObject type.
+#define U_PMF_IE_BRIGHTNESSCONTRAST_OID 0x02020302 //!< PMF_IE_BRIGHTNESSCONTRAST PseudoObject type.
+#define U_PMF_IE_COLORBALANCE_OID 0x02020303 //!< PMF_IE_COLORBALANCE PseudoObject type.
+#define U_PMF_IE_COLORCURVE_OID 0x02020304 //!< PMF_IE_COLORCURVE PseudoObject type.
+#define U_PMF_IE_COLORLOOKUPTABLE_OID 0x02020305 //!< PMF_IE_COLORLOOKUPTABLE PseudoObject type.
+#define U_PMF_IE_COLORMATRIX_OID 0x02020306 //!< PMF_IE_COLORMATRIX PseudoObject type.
+#define U_PMF_IE_HUESATURATIONLIGHTNESS_OID 0x02020307 //!< PMF_IE_HUESATURATIONLIGHTNESS PseudoObject type.
+#define U_PMF_IE_LEVELS_OID 0x02020308 //!< PMF_IE_LEVELS PseudoObject type.
+#define U_PMF_IE_REDEYECORRECTION_OID 0x02020309 //!< PMF_IE_REDEYECORRECTION PseudoObject type.
+#define U_PMF_IE_SHARPEN_OID 0x02020310 //!< PMF_IE_SHARPEN PseudoObject type.
+#define U_PMF_IE_TINT_OID 0x02020311 //!< PMF_IE_TINT PseudoObject type.
+#define U_PMR_STROKEFILLPATH_OID 0x02010101 //!< PMR_STROKEFILLPATH PseudoObject type. (Mentioned in passing here).
+#define U_PMR_OFFSETCLIP_OID 0x02030101 //!< PMR_OFFSETCLIP PseudoObject type.
+#define U_PMR_RESETCLIP_OID 0x02030102 //!< PMR_RESETCLIP PseudoObject type.
+#define U_PMR_SETCLIPPATH_OID 0x02030103 //!< PMR_SETCLIPPATH PseudoObject type.
+#define U_PMR_SETCLIPRECT_OID 0x02030104 //!< PMR_SETCLIPRECT PseudoObject type.
+#define U_PMR_SETCLIPREGION_OID 0x02030105 //!< PMR_SETCLIPREGION PseudoObject type.
+#define U_PMR_COMMENT_OID 0x02030201 //!< PMR_COMMENT PseudoObject type.
+#define U_PMR_ENDOFFILE_OID 0x02030301 //!< PMR_ENDOFFILE PseudoObject type.
+#define U_PMR_GETDC_OID 0x02030302 //!< PMR_GETDC PseudoObject type.
+#define U_PMR_HEADER_OID 0x02030303 //!< PMR_HEADER PseudoObject type.
+#define U_PMR_CLEAR_OID 0x02030401 //!< PMR_CLEAR PseudoObject type.
+#define U_PMR_DRAWARC_OID 0x02030402 //!< PMR_DRAWARC PseudoObject type.
+#define U_PMR_DRAWBEZIERS_OID 0x02030403 //!< PMR_DRAWBEZIERS PseudoObject type.
+#define U_PMR_DRAWCLOSEDCURVE_OID 0x02030404 //!< PMR_DRAWCLOSEDCURVE PseudoObject type.
+#define U_PMR_DRAWCURVE_OID 0x02030405 //!< PMR_DRAWCURVE PseudoObject type.
+#define U_PMR_DRAWDRIVERSTRING_OID 0x02030406 //!< PMR_DRAWDRIVERSTRING PseudoObject type.
+#define U_PMR_DRAWELLIPSE_OID 0x02030407 //!< PMR_DRAWELLIPSE PseudoObject type.
+#define U_PMR_DRAWIMAGE_OID 0x02030408 //!< PMR_DRAWIMAGE PseudoObject type.
+#define U_PMR_DRAWIMAGEPOINTS_OID 0x02030409 //!< PMR_DRAWIMAGEPOINTS PseudoObject type.
+#define U_PMR_DRAWLINES_OID 0x02030410 //!< PMR_DRAWLINES PseudoObject type.
+#define U_PMR_DRAWPATH_OID 0x02030411 //!< PMR_DRAWPATH PseudoObject type.
+#define U_PMR_DRAWPIE_OID 0x02030412 //!< PMR_DRAWPIE PseudoObject type.
+#define U_PMR_DRAWRECTS_OID 0x02030413 //!< PMR_DRAWRECTS PseudoObject type.
+#define U_PMR_DRAWSTRING_OID 0x02030414 //!< PMR_DRAWSTRING PseudoObject type.
+#define U_PMR_FILLCLOSEDCURVE_OID 0x02030415 //!< PMR_FILLCLOSEDCURVE PseudoObject type.
+#define U_PMR_FILLELLIPSE_OID 0x02030416 //!< PMR_FILLELLIPSE PseudoObject type.
+#define U_PMR_FILLPATH_OID 0x02030417 //!< PMR_FILLPATH PseudoObject type.
+#define U_PMR_FILLPIE_OID 0x02030418 //!< PMR_FILLPIE PseudoObject type.
+#define U_PMR_FILLPOLYGON_OID 0x02030419 //!< PMR_FILLPOLYGON PseudoObject type.
+#define U_PMR_FILLRECTS_OID 0x02030420 //!< PMR_FILLRECTS PseudoObject type.
+#define U_PMR_FILLREGION_OID 0x02030421 //!< PMR_FILLREGION PseudoObject type.
+#define U_PMR_OBJECT_OID 0x02030501 //!< PMR_OBJECT PseudoObject type.
+#define U_PMR_SERIALIZABLEOBJECT_OID 0x02030502 //!< PMR_SERIALIZABLEOBJECT PseudoObject type.
+#define U_PMR_SETANTIALIASMODE_OID 0x02030601 //!< PMR_SETANTIALIASMODE PseudoObject type.
+#define U_PMR_SETCOMPOSITINGMODE_OID 0x02030602 //!< PMR_SETCOMPOSITINGMODE PseudoObject type.
+#define U_PMR_SETCOMPOSITINGQUALITY_OID 0x02030603 //!< PMR_SETCOMPOSITINGQUALITY PseudoObject type.
+#define U_PMR_SETINTERPOLATIONMODE_OID 0x02030604 //!< PMR_SETINTERPOLATIONMODE PseudoObject type.
+#define U_PMR_SETPIXELOFFSETMODE_OID 0x02030605 //!< PMR_SETPIXELOFFSETMODE PseudoObject type.
+#define U_PMR_SETRENDERINGORIGIN_OID 0x02030606 //!< PMR_SETRENDERINGORIGIN PseudoObject type.
+#define U_PMR_SETTEXTCONTRAST_OID 0x02030607 //!< PMR_SETTEXTCONTRAST PseudoObject type.
+#define U_PMR_SETTEXTRENDERINGHINT_OID 0x02030608 //!< PMR_SETTEXTRENDERINGHINT PseudoObject type.
+#define U_PMR_BEGINCONTAINER_OID 0x02030701 //!< PMR_BEGINCONTAINER PseudoObject type.
+#define U_PMR_BEGINCONTAINERNOPARAMS_OID 0x02030702 //!< PMR_BEGINCONTAINERNOPARAMS PseudoObject type.
+#define U_PMR_ENDCONTAINER_OID 0x02030703 //!< PMR_ENDCONTAINER PseudoObject type.
+#define U_PMR_RESTORE_OID 0x02030704 //!< PMR_RESTORE PseudoObject type.
+#define U_PMR_SAVE_OID 0x02030705 //!< PMR_SAVE PseudoObject type.
+#define U_PMR_SETTSCLIP_OID 0x02030801 //!< PMR_SETTSCLIP PseudoObject type.
+#define U_PMR_SETTSGRAPHICS_OID 0x02030802 //!< PMR_SETTSGRAPHICS PseudoObject type.
+#define U_PMR_MULTIPLYWORLDTRANSFORM_OID 0x02030901 //!< PMR_MULTIPLYWORLDTRANSFORM PseudoObject type.
+#define U_PMR_RESETWORLDTRANSFORM_OID 0x02030902 //!< PMR_RESETWORLDTRANSFORM PseudoObject type.
+#define U_PMR_ROTATEWORLDTRANSFORM_OID 0x02030903 //!< PMR_ROTATEWORLDTRANSFORM PseudoObject type.
+#define U_PMR_SCALEWORLDTRANSFORM_OID 0x02030904 //!< PMR_SCALEWORLDTRANSFORM PseudoObject type.
+#define U_PMR_SETPAGETRANSFORM_OID 0x02030905 //!< PMR_SETPAGETRANSFORM PseudoObject type.
+#define U_PMR_SETWORLDTRANSFORM_OID 0x02030906 //!< PMR_SETWORLDTRANSFORM PseudoObject type.
+#define U_PMR_TRANSLATEWORLDTRANSFORM_OID 0x02030907 //!< PMR_TRANSLATEWORLDTRANSFORM PseudoObject type.
+#define U_PMR_TRANSLATEWORLDTRANSFORM_OID 0x02030907 //!< PMR_TRANSLATEWORLDTRANSFORM PseudoObject type.
+#define U_PMR_CMN_HDR_OID 0x40000000 //!< PMR_CMN_HDR PseudoObject type.
+#define U_PMF_4NUM_OID 0x40000001 //!< PMF_4NUM PseudoObject type. PseudoObject contains a 4 unsigned int in EMF+ file byte order, used in some contexts to indicate an object index number..
+#define U_PMF_RAW_OID 0x40000002 //!< PMF_RAW PseudoObject type. Raw data: no preceding elements, data has native endianness.
+#define U_PMF_ARRAY_OID 0x80000000 //!< PMF_ARRAY PseudoObject type modifier. PseudoObject contains an array of the data type revealed when this bit is cleared.
+#define U_PMF_MASK_OID 0x7FFFFFFF //!< PMF_MASK. Select PseudoObject data type without regard to PMF_ARRAY.
+
+/** @} */
+
+
+/** \defgroup U_PMF_BDT_ PMF BitmapDataType Enumeration
+ For
+ EMF+ manual 2.1.1.2, Microsoft name: BitmapDataType Enumeration (U_BDT_*)
+ @{
+*/
+#define U_BDT_Pixel 0x00 //!< Data is a bitmap.
+#define U_BDT_Compressed 0x01 //!< Data is a compressed bitmap (like a PNG).
+/** @} */
+
+/** \defgroup U_PMF_BT_ PMF BrushType Enumeration
+ For
+ EMF+ manual 2.1.1.3, Microsoft name: BrushType Enumeration (U_BT_*)
+ @{
+*/
+#define U_BT_SolidColor 0x00 //!< Solid Color brush.
+#define U_BT_HatchFill 0x01 //!< Hatch Fill brush.
+#define U_BT_TextureFill 0x02 //!< Texture Fill brush.
+#define U_BT_PathGradient 0x03 //!< Path Gradient brush.
+#define U_BT_LinearGradient 0x04 //!< Linear Gradient brush.
+/** @} */
+
+/** \defgroup U_PMF_CM_ PMF CombineMode Enumeration
+ For
+ EMF+ manual 2.1.1.4, Microsoft name: CombineMode Enumeration (U_CM_*)
+ @{
+*/
+#define U_CM_Replace 0x00 //!< Region becomes new region.
+#define U_CM_Intersect 0x01 //!< Region becomes intersection of existing region and new region.
+#define U_CM_Union 0x02 //!< Region becomes union of existing and new regions.
+#define U_CM_XOR 0x03 //!< Region becomes XOR of existing and new regions.
+#define U_CM_Exclude 0x04 //!< Region becomes part of existing region not in new region.
+#define U_CM_Complement 0x05 //!< Region becomes part of new region not in existing region.
+/** @} */
+
+/** \defgroup U_PMF_CMS_ PMF CompositingMode Enumeration
+ For
+ EMF+ manual 2.1.1.5, Microsoft name: CompositingMode Enumeration (U_CMS_* [S==Source])
+ @{
+*/
+#define U_CMS_Over 0x00 //!< Source is alpha blends with destination.
+#define U_CMS_Copy 0x01 //!< Source over writes destination.
+/** @} */
+
+/** \defgroup U_PMF_CQ_ PMF CompositingQuality Enumeration
+ For
+ EMF+ manual 2.1.1.6, Microsoft name: CompositingQuality Enumeration (U_CQ_*)
+ @{
+*/
+#define U_CQ_Default 0x01 //!< Default compositing quality
+#define U_CQ_HighSpeed 0x02 //!< High Speed compositing quality
+#define U_CQ_HighQuality 0x03 //!< High Quality compositing quality
+#define U_CQ_GammaCorrected 0x04 //!< Gamma Corrected compositing quality
+#define U_CQ_AssumeLinear 0x05 //!< Assume Linear compositing quality
+/** @} */
+
+/** \defgroup U_PMF_CA_ PMF CurveAdjustments Enumeration
+ For
+ EMF+ manual 2.1.1.7, Microsoft name: CurveAdjustments Enumeration (U_CA_*)
+ @{
+*/
+#define U_CA_Exposure 0x00 //!< Exposure color curve adjustment
+#define U_CA_Density 0x01 //!< Density color curve adjustment
+#define U_CA_Contrast 0x02 //!< Contrast color curve adjustment
+#define U_CA_Highlight 0x03 //!< Highlight color curve adjustment
+#define U_CA_Shadow 0x04 //!< Shadow color curve adjustment
+#define U_CA_Midtone 0x05 //!< Midtone color curve adjustment
+#define U_CA_WhiteSaturation 0x06 //!< White Saturation color curve adjustment
+#define U_CA_BlackSaturation 0x07 //!< Black Saturation color curve adjustment
+/** @} */
+
+/** \defgroup U_PMF_CC_ PMF CurveChannel Enumeration
+ For
+ EMF+ manual 2.1.1.8, Microsoft name: CurveChannel Enumeration (U_CC_*)
+ @{
+*/
+#define U_CC_All 0x00 //!< All color channels
+#define U_CC_Red 0x01 //!< Red color channel
+#define U_CC_Green 0x02 //!< Green color channel
+#define U_CC_Blue 0x03 //!< Blue color channel
+/** @} */
+
+/** \defgroup U_PMF_CLCDT_ PMF CustomLineCapDataType Enumeration
+ For
+ EMF+ manual 2.1.1.9, Microsoft name: CustomLineCapDataType Enumeration (U_CLCDT_*)
+ @{
+*/
+#define U_CLCDT_Default 0x00 //!< Default custom line cap
+#define U_CLCDT_AdjustableArrow 0x01 //!< Adjustable Arrow custom line cap
+/** @} */
+
+/** \defgroup U_PMF_DLCT_ PMF DashedLineCapType Enumeration
+ For
+ EMF+ manual 2.1.1.10, Microsoft name: DashedLineCapType Enumeration (U_DLCT_*)
+ @{
+*/
+#define U_DLCT_Flat 0x00 //!< Flat dashed line cap
+#define U_DLCT_Round 0x02 //!< Round dashed line cap
+#define U_DLCT_Triangle 0x03 //!< Triangle dashed line cap
+/** @} */
+
+/** \defgroup U_PMF_FT_ PMF FilterType Enumeration
+ For
+ EMF+ manual 2.1.1.11, Microsoft name: FilterType Enumeration (U_FT_*)
+ @{
+*/
+#define U_FT_None 0x00 //!< No filtering
+#define U_FT_Point 0x01 //!< Point filtering
+#define U_FT_Linear 0x02 //!< Linear filtering
+#define U_FT_Triangle 0x03 //!< Triangle filtering
+#define U_FT_Box 0x04 //!< Box filtering
+#define U_FT_PyramidalQuad 0x06 //!< Pyramidal Quad filtering
+#define U_FT_GaussianQuad 0x07 //!< Gaussian Quad filtering
+/** @} */
+
+/** \defgroup U_PMF_GV_ PMF GraphicsVersion Enumeration
+ For
+ EMF+ manual 2.1.1.12, Microsoft name: GraphicsVersion Enumeration (U_GV_*)
+ @{
+*/
+#define U_GV_1 0x01 //!< 1 graphics version
+#define U_GV_1_1 0x02 //!< 1.1 graphics version
+/** @} */
+
+/** \defgroup U_PMF_HSP_ PMF HatchStyle Enumeration
+ For
+ EMF+ manual 2.1.1.13, Microsoft name: HatchStyle Enumeration (U_HSP_* [U_HS_ already used for EMF])
+ @{
+*/
+#define U_HSP_Horizontal 0x00000000 //!< Horizontal
+#define U_HSP_Vertical 0x00000001 //!< Vertical
+#define U_HSP_ForwardDiagonal 0x00000002 //!< Forward Diagonal
+#define U_HSP_BackwardDiagonal 0x00000003 //!< Backward Diagonal
+#define U_HSP_LargeGrid 0x00000004 //!< Large Grid
+#define U_HSP_DiagonalCross 0x00000005 //!< Diagonal Cross
+#define U_HSP_05Percent 0x00000006 //!< 05 Percent
+#define U_HSP_10Percent 0x00000007 //!< 10 Percent
+#define U_HSP_20Percent 0x00000008 //!< 20 Percent
+#define U_HSP_25Percent 0x00000009 //!< 25 Percent
+#define U_HSP_30Percent 0x0000000A //!< 30 Percent
+#define U_HSP_40Percent 0x0000000B //!< 40 Percent
+#define U_HSP_50Percent 0x0000000C //!< 50 Percent
+#define U_HSP_60Percent 0x0000000D //!< 60 Percent
+#define U_HSP_70Percent 0x0000000E //!< 70 Percent
+#define U_HSP_75Percent 0x0000000F //!< 75 Percent
+#define U_HSP_80Percent 0x00000010 //!< 80 Percent
+#define U_HSP_90Percent 0x00000011 //!< 90 Percent
+#define U_HSP_LightDownwardDiagonal 0x00000012 //!< Light Downward Diagonal
+#define U_HSP_LightUpwardDiagonal 0x00000013 //!< Light Upward Diagonal
+#define U_HSP_DarkDownwardDiagonal 0x00000014 //!< Dark Downward Diagonal
+#define U_HSP_DarkUpwardDiagonal 0x00000015 //!< Dark Upward Diagonal
+#define U_HSP_WideDownwardDiagonal 0x00000016 //!< Wide Downward Diagonal
+#define U_HSP_WideUpwardDiagonal 0x00000017 //!< Wide Upward Diagonal
+#define U_HSP_LightVertical 0x00000018 //!< Light Vertical
+#define U_HSP_LightHorizontal 0x00000019 //!< Light Horizontal
+#define U_HSP_NarrowVertical 0x0000001A //!< Narrow Vertical
+#define U_HSP_NarrowHorizontal 0x0000001B //!< Narrow Horizontal
+#define U_HSP_DarkVertical 0x0000001C //!< Dark Vertical
+#define U_HSP_DarkHorizontal 0x0000001D //!< Dark Horizontal
+#define U_HSP_DashedDownwardDiagonal 0x0000001E //!< Dashed Downward Diagonal
+#define U_HSP_DashedUpwardDiagonal 0x0000001F //!< Dashed Upward Diagonal
+#define U_HSP_DashedHorizontal 0x00000020 //!< Dashed Horizontal
+#define U_HSP_DashedVertical 0x00000021 //!< Dashed Vertical
+#define U_HSP_SmallConfetti 0x00000022 //!< Small Confetti
+#define U_HSP_LargeConfetti 0x00000023 //!< LargeC onfetti
+#define U_HSP_ZigZag 0x00000024 //!< Zig Zag
+#define U_HSP_Wave 0x00000025 //!< Wave
+#define U_HSP_DiagonalBrick 0x00000026 //!< Diagonal Brick
+#define U_HSP_HorizontalBrick 0x00000027 //!< Horizontal Brick
+#define U_HSP_Weave 0x00000028 //!< Weave
+#define U_HSP_Plaid 0x00000029 //!< Plaid
+#define U_HSP_Divot 0x0000002A //!< Divot
+#define U_HSP_DottedGrid 0x0000002B //!< DottedGrid
+#define U_HSP_DottedDiamond 0x0000002C //!< DottedDiamond
+#define U_HSP_Shingle 0x0000002D //!< Shingle
+#define U_HSP_Trellis 0x0000002E //!< Trellis
+#define U_HSP_Sphere 0x0000002F //!< Sphere
+#define U_HSP_SmallGrid 0x00000030 //!< Small Grid
+#define U_HSP_SmallCheckerBoard 0x00000031 //!< Small Checker Board
+#define U_HSP_LargeCheckerBoard 0x00000032 //!< Large Checker Board
+#define U_HSP_OutlinedDiamond 0x00000033 //!< Outlined Diamond
+#define U_HSP_SolidDiamond 0x00000034 //!< Solid Diamond
+/** @} */
+
+/** \defgroup U_PMF_HKP_ PMF HotkeyPrefix Enumeration
+ For
+ EMF+ manual 2.1.1.14, Microsoft name: HotkeyPrefix Enumeration (U_HKP_*)
+ @{
+*/
+#define U_HKP_None 0x00 //!< No hot key prefix
+#define U_HKP_Show 0x01 //!< Show hot key prefix
+#define U_HKP_Hide 0x02 //!< Hide hot key prefix
+/** @} */
+
+/** \defgroup U_PMF_IDT_ PMF ImageDataType Enumeration
+ For
+ EMF+ manual 2.1.1.15, Microsoft name: ImageDataType Enumeration (U_IDT_*)
+ @{
+*/
+#define U_IDT_Unknown 0x00 //!< Unknown image data type
+#define U_IDT_Bitmap 0x01 //!< Bitmap image data type
+#define U_IDT_Metafile 0x02 //!< Metafile image data type
+/** @} */
+
+/** \defgroup U_PMF_IM_ PMF InterpolationMode Enumeration
+ For
+ EMF+ manual 2.1.1.16, Microsoft name: InterpolationMode Enumeration (U_IM_*)
+ @{
+*/
+#define U_IM_Default 0x00 //!< Default interpolation mode
+#define U_IM_LowQuality 0x01 //!< Low Quality interpolation mode
+#define U_IM_HighQuality 0x02 //!< High Quality interpolation mode
+#define U_IM_Bilinear 0x03 //!< Bilinear interpolation mode
+#define U_IM_Bicubic 0x04 //!< Bicubic interpolation mode
+#define U_IM_NearestNeighbor 0x05 //!< Nearest Neighbor interpolation mode
+#define U_IM_HighQualityBilinear 0x06 //!< High Quality Bilinear interpolation mode
+#define U_IM_HighQualityBicubic 0x07 //!< High Quality Bicubic interpolation mode
+/** @} */
+
+/** \defgroup U_PMF_LID_ PMF LanguageIdentifier Enumeration
+ For
+ EMF+ manual 2.1.1.17, Microsoft name: LanguageIdentifier Enumeration (U_LID_*)
+ @{
+*/
+#define U_LID_LANG_NEUTRAL 0x0000 //!< LANG_NEUTRAL
+#define U_LID_zh_CHS 0x0004 //!< zh_CHS
+#define U_LID_LANG_INVARIANT 0x007F //!< LANG_INVARIANT
+#define U_LID_LANG_NEUTRAL_USER_DEFAULT 0x0400 //!< LANG_NEUTRAL_USER_DEFAULT
+#define U_LID_ar_SA 0x0401 //!< ar_SA
+#define U_LID_bg_BG 0x0402 //!< bg_BG
+#define U_LID_ca_ES 0x0403 //!< ca_ES
+#define U_LID_zh_CHT 0x0404 //!< zh_CHT
+#define U_LID_cs_CZ 0x0405 //!< cs_CZ
+#define U_LID_da_DK 0x0406 //!< da_DK
+#define U_LID_de_DE 0x0407 //!< de_DE
+#define U_LID_el_GR 0x0408 //!< el_GR
+#define U_LID_en_US 0x0409 //!< en_US
+#define U_LID_es_Tradnl_ES 0x040A //!< es_Tradnl_ES
+#define U_LID_fi_FI 0x040B //!< fi_FI
+#define U_LID_fr_FR 0x040C //!< fr_FR
+#define U_LID_he_IL 0x040D //!< he_IL
+#define U_LID_hu_HU 0x040E //!< hu_HU
+#define U_LID_is_IS 0x040F //!< is_IS
+#define U_LID_it_IT 0x0410 //!< it_IT
+#define U_LID_ja_JA 0x0411 //!< ja_JA
+#define U_LID_ko_KR 0x0412 //!< ko_KR
+#define U_LID_nl_NL 0x0413 //!< nl_NL
+#define U_LID_nb_NO 0x0414 //!< nb_NO
+#define U_LID_pl_PL 0x0415 //!< pl_PL
+#define U_LID_pt_BR 0x0416 //!< pt_BR
+#define U_LID_rm_CH 0x0417 //!< rm_CH
+#define U_LID_ro_RO 0x0418 //!< ro_RO
+#define U_LID_ru_RU 0x0419 //!< ru_RU
+#define U_LID_hr_HR 0x041A //!< hr_HR
+#define U_LID_sk_SK 0x041B //!< sk_SK
+#define U_LID_sq_AL 0x041C //!< sq_AL
+#define U_LID_sv_SE 0x041D //!< sv_SE
+#define U_LID_th_TH 0x041E //!< th_TH
+#define U_LID_tr_TR 0x041F //!< tr_TR
+#define U_LID_ur_PK 0x0420 //!< ur_PK
+#define U_LID_id_ID 0x0421 //!< id_ID
+#define U_LID_uk_UA 0x0422 //!< uk_UA
+#define U_LID_be_BY 0x0423 //!< be_BY
+#define U_LID_sl_SI 0x0424 //!< sl_SI
+#define U_LID_et_EE 0x0425 //!< et_EE
+#define U_LID_lv_LV 0x0426 //!< lv_LV
+#define U_LID_lt_LT 0x0427 //!< lt_LT
+#define U_LID_tg_TJ 0x0428 //!< tg_TJ
+#define U_LID_fa_IR 0x0429 //!< fa_IR
+#define U_LID_vi_VN 0x042A //!< vi_VN
+#define U_LID_hy_AM 0x042B //!< hy_AM
+#define U_LID_az_Latn_AZ 0x042C //!< az_Latn_AZ
+#define U_LID_eu_ES 0x042D //!< eu_ES
+#define U_LID_wen_DE 0x042E //!< wen_DE
+#define U_LID_mk_MK 0x042F //!< mk_MK
+#define U_LID_st_ZA 0x0430 //!< st_ZA
+#define U_LID_tn_ZA 0x0432 //!< tn_ZA
+#define U_LID_xh_ZA 0x0434 //!< xh_ZA
+#define U_LID_zu_ZA 0x0435 //!< zu_ZA
+#define U_LID_af_ZA 0x0436 //!< af_ZA
+#define U_LID_ka_GE 0x0437 //!< ka_GE
+#define U_LID_fa_FA 0x0438 //!< fa_FA
+#define U_LID_hi_IN 0x0439 //!< hi_IN
+#define U_LID_mt_MT 0x043A //!< mt_MT
+#define U_LID_se_NO 0x043B //!< se_NO
+#define U_LID_ga_GB 0x043C //!< ga_GB
+#define U_LID_ms_MY 0x043E //!< ms_MY
+#define U_LID_kk_KZ 0x043F //!< kk_KZ
+#define U_LID_ky_KG 0x0440 //!< ky_KG
+#define U_LID_sw_KE 0x0441 //!< sw_KE
+#define U_LID_tk_TM 0x0442 //!< tk_TM
+#define U_LID_uz_Latn_UZ 0x0443 //!< uz_Latn_UZ
+#define U_LID_tt_Ru 0x0444 //!< tt_Ru
+#define U_LID_bn_IN 0x0445 //!< bn_IN
+#define U_LID_pa_IN 0x0446 //!< pa_IN
+#define U_LID_gu_IN 0x0447 //!< gu_IN
+#define U_LID_or_IN 0x0448 //!< or_IN
+#define U_LID_ta_IN 0x0449 //!< ta_IN
+#define U_LID_te_IN 0x044A //!< te_IN
+#define U_LID_kn_IN 0x044B //!< kn_IN
+#define U_LID_ml_IN 0x044C //!< ml_IN
+#define U_LID_as_IN 0x044D //!< as_IN
+#define U_LID_mr_IN 0x044E //!< mr_IN
+#define U_LID_sa_IN 0x044F //!< sa_IN
+#define U_LID_mn_MN 0x0450 //!< mn_MN
+#define U_LID_bo_CN 0x0451 //!< bo_CN
+#define U_LID_cy_GB 0x0452 //!< cy_GB
+#define U_LID_km_KH 0x0453 //!< km_KH
+#define U_LID_lo_LA 0x0454 //!< lo_LA
+#define U_LID_gl_ES 0x0456 //!< gl_ES
+#define U_LID_kok_IN 0x0457 //!< kok_IN
+#define U_LID_sd_IN 0x0459 //!< sd_IN
+#define U_LID_syr_SY 0x045A //!< syr_SY
+#define U_LID_si_LK 0x045B //!< si_LK
+#define U_LID_iu_Cans_CA 0x045D //!< iu_Cans_CA
+#define U_LID_am_ET 0x045E //!< am_ET
+#define U_LID_ne_NP 0x0461 //!< ne_NP
+#define U_LID_fy_NL 0x0462 //!< fy_NL
+#define U_LID_ps_AF 0x0463 //!< ps_AF
+#define U_LID_fil_PH 0x0464 //!< fil_PH
+#define U_LID_div_MV 0x0465 //!< div_MV
+#define U_LID_ha_Latn_NG 0x0468 //!< ha_Latn_NG
+#define U_LID_yo_NG 0x046A //!< yo_NG
+#define U_LID_quz_BO 0x046B //!< quz_BO
+#define U_LID_nzo_ZA 0x046C //!< nzo_ZA
+#define U_LID_ba_RU 0x046D //!< ba_RU
+#define U_LID_lb_LU 0x046E //!< lb_LU
+#define U_LID_kl_GL 0x046F //!< kl_GL
+#define U_LID_ig_NG 0x0470 //!< ig_NG
+#define U_LID_so_SO 0x0477 //!< so_SO
+#define U_LID_ii_CN 0x0478 //!< ii_CN
+#define U_LID_arn_CL 0x047A //!< arn_CL
+#define U_LID_moh_CA 0x047C //!< moh_CA
+#define U_LID_br_FR 0x047E //!< br_FR
+#define U_LID_ug_CN 0x0480 //!< ug_CN
+#define U_LID_ mi_NZ 0x0481 //!< mi_NZ
+#define U_LID_oc_FR 0x0482 //!< oc_FR
+#define U_LID_co_FR 0x0483 //!< co_FR
+#define U_LID_gsw_FR 0x0484 //!< gsw_FR
+#define U_LID_sah_RU 0x0485 //!< sah_RU
+#define U_LID_qut_GT 0x0486 //!< qut_GT
+#define U_LID_rw_RW 0x0487 //!< rw_RW
+#define U_LID_wo_SN 0x0488 //!< wo_SN
+#define U_LID_gbz_AF 0x048C //!< gbz_AF
+#define U_LID_LANG_NEUTRAL_SYS_DEFAULT 0x0800 //!< LANG_NEUTRAL_SYS_DEFAULT
+#define U_LID_ar_IQ 0x0801 //!< ar_IQ
+#define U_LID_zh_CN 0x0804 //!< zh_CN
+#define U_LID_de_CH 0x0807 //!< de_CH
+#define U_LID_en_GB 0x0809 //!< en_GB
+#define U_LID_es_MX 0x080A //!< es_MX
+#define U_LID_fr_BE 0x080C //!< fr_BE
+#define U_LID_it_CH 0x0810 //!< it_CH
+#define U_LID_ko_Johab_KR 0x0812 //!< ko_Johab_KR
+#define U_LID_nl_BE 0x0813 //!< nl_BE
+#define U_LID_nn_NO 0x0814 //!< nn_NO
+#define U_LID_pt_PT 0x0816 //!< pt_PT
+#define U_LID_sr_Latn_SP 0x081A //!< sr_Latn_SP
+#define U_LID_sv_FI 0x081D //!< sv_FI
+#define U_LID_ur_IN 0x0820 //!< ur_IN
+#define U_LID_lt_C_LT 0x0827 //!< lt_C_LT
+#define U_LID_az_Cyrl_AZ 0x082C //!< az_Cyrl_AZ
+#define U_LID_wee_DE 0x082E //!< wee_DE
+#define U_LID_se_SE 0x083B //!< se_SE
+#define U_LID_ga_IE 0x083C //!< ga_IE
+#define U_LID_ms_BN 0x083E //!< ms_BN
+#define U_LID_uz_Cyrl_UZ 0x0843 //!< uz_Cyrl_UZ
+#define U_LID_bn_BD 0x0845 //!< bn_BD
+#define U_LID_mn_Mong_CN 0x0850 //!< mn_Mong_CN
+#define U_LID_sd_PK 0x0859 //!< sd_PK
+#define U_LID_iu_Latn_CA 0x085D //!< iu_Latn_CA
+#define U_LID_tzm_Latn_DZ 0x085F //!< tzm_Latn_DZ
+#define U_LID_quz_EC 0x086B //!< quz_EC
+#define U_LID_LANG_NEUTRAL_CUSTOM_DEFAULT 0x0C00 //!< LANG_NEUTRAL_CUSTOM_DEFAULT
+#define U_LID_ar_EG 0x0C01 //!< ar_EG
+#define U_LID_zh_HK 0x0C04 //!< zh_HK
+#define U_LID_de_AT 0x0C07 //!< de_AT
+#define U_LID_en_AU 0x0C09 //!< en_AU
+#define U_LID_es_ES 0x0C0A //!< es_ES
+#define U_LID_fr_CA 0x0C0C //!< fr_CA
+#define U_LID_sr_Cyrl_CS 0x0C1A //!< sr_Cyrl_CS
+#define U_LID_se_FI 0x0C3B //!< se_FI
+#define U_LID_quz_PE 0x0C6B //!< quz_PE
+#define U_LID_LANG_NEUTRAL_CUSTOM 0x1000 //!< LANG_NEUTRAL_CUSTOM
+#define U_LID_ar_LY 0x1001 //!< ar_LY
+#define U_LID_zh_SG 0x1004 //!< zh_SG
+#define U_LID_de_LU 0x1007 //!< de_LU
+#define U_LID_en_CA 0x1009 //!< en_CA
+#define U_LID_es_GT 0x100A //!< es_GT
+#define U_LID_fr_CH 0x100C //!< fr_CH
+#define U_LID_hr_BA 0x101A //!< hr_BA
+#define U_LID_smj_NO 0x103B //!< smj_NO
+#define U_LID_LANG_NEUTRAL_CUSTOM_DEFAULT_MUI 0x1400 //!< LANG_NEUTRAL_CUSTOM_DEFAULT_MUI
+#define U_LID_ar_DZ 0x1401 //!< ar_DZ
+#define U_LID_zh_MO 0x1404 //!< zh_MO
+#define U_LID_de_LI 0x1407 //!< de_LI
+#define U_LID_en_NZ 0x1409 //!< en_NZ
+#define U_LID_es_CR 0x140A //!< es_CR
+#define U_LID_fr_LU 0x140C //!< fr_LU
+#define U_LID_bs_Latn_BA 0x141A //!< bs_Latn_BA
+#define U_LID_smj_SE 0x143B //!< smj_SE
+#define U_LID_ar_MA 0x1801 //!< ar_MA
+#define U_LID_en_IE 0x1809 //!< en_IE
+#define U_LID_es_PA 0x180A //!< es_PA
+#define U_LID_ar_MC 0x180C //!< ar_MC
+#define U_LID_sr_Latn_BA 0x181A //!< sr_Latn_BA
+#define U_LID_sma_NO 0x183B //!< sma_NO
+#define U_LID_ar_TN 0x1C01 //!< ar_TN
+#define U_LID_en_ZA 0x1C09 //!< en_ZA
+#define U_LID_es_DO 0x1C0A //!< es_DO
+#define U_LID_sr_Cyrl_BA 0x1C1A //!< sr_Cyrl_BA
+#define U_LID_sma_SE 0x1C3B //!< sma_SE
+#define U_LID_ar_OM 0x2001 //!< ar_OM
+#define U_LID_el_2_GR 0x2008 //!< el_2_GR
+#define U_LID_en_JM 0x2009 //!< en_JM
+#define U_LID_es_VE 0x200A //!< es_VE
+#define U_LID_bs_Cyrl_BA 0x201A //!< bs_Cyrl_BA
+#define U_LID_sms_FI 0x203B //!< sms_FI
+#define U_LID_ar_YE 0x2401 //!< ar_YE
+#define U_LID_ar_029 0x2409 //!< ar_029
+#define U_LID_es_CO 0x240A //!< es_CO
+#define U_LID_smn_FI 0x243B //!< smn_FI
+#define U_LID_ar_SY 0x2801 //!< ar_SY
+#define U_LID_en_BZ 0x2809 //!< en_BZ
+#define U_LID_es_PE 0x280A //!< es_PE
+#define U_LID_ar_JO 0x2C01 //!< ar_JO
+#define U_LID_en_TT 0x2C09 //!< en_TT
+#define U_LID_es_AR 0x2C0A //!< es_AR
+#define U_LID_ar_LB 0x3001 //!< ar_LB
+#define U_LID_en_ZW 0x3009 //!< en_ZW
+#define U_LID_es_EC 0x300A //!< es_EC
+#define U_LID_ar_KW 0x3401 //!< ar_KW
+#define U_LID_en_PH 0x3409 //!< en_PH
+#define U_LID_es_CL 0x340A //!< es_CL
+#define U_LID_ar_AE 0x3801 //!< ar_AE
+#define U_LID_es_UY 0x380A //!< es_UY
+#define U_LID_ar_BH 0x3C01 //!< ar_BH
+#define U_LID_es_PY 0x3C0A //!< es_PY
+#define U_LID_ar_QA 0x4001 //!< ar_QA
+#define U_LID_en_IN 0x4009 //!< en_IN
+#define U_LID_es_BO 0x400A //!< es_BO
+#define U_LID_en_MY 0x4409 //!< en_MY
+#define U_LID_es_SV 0x440A //!< es_SV
+#define U_LID_en_SG 0x4809 //!< en_SG
+#define U_LID_es_HN 0x480A //!< es_HN
+#define U_LID_es_NI 0x4C0A //!< es_NI
+#define U_LID_es_PR 0x500A //!< es_PR
+#define U_LID_es_US 0x540A //!< es_US
+#define U_LID_zh_Hant 0x7C04 //!< zh_Hant
+#define U_LID_SEC_MASK 0xFB00 //!< Mask for region part of LID
+#define U_LID_PRI_MASK 0x03FF //!< MASK for languagepart of LID
+/** @} */
+
+/** \defgroup U_PMF_LCT_ PMF LineCapType Enumeration
+ For
+ EMF+ manual 2.1.1.18, Microsoft name: LineCapType Enumeration (U_LCT_*)
+ @{
+*/
+#define U_LCT_Flat 0x00 //!< Flat line cap
+#define U_LCT_Square 0x01 //!< Square line cap
+#define U_LCT_Round 0x02 //!< Round line cap
+#define U_LCT_Triangle 0x03 //!< Triangle line cap
+#define U_LCT_NoAnchor 0x10 //!< No Anchor line cap
+#define U_LCT_SquareAnchor 0x11 //!< Square Anchor line cap
+#define U_LCT_RoundAnchor 0x12 //!< Round Anchor line cap
+#define U_LCT_DiamondAnchor 0x13 //!< Diamond Anchor line cap
+#define U_LCT_ArrowAnchor 0x14 //!< Arrow Anchor line cap
+#define U_LCT_AnchorMask 0xF0 //!< Ancho rMask line cap
+#define U_LCT_Custom 0xFF //!< Custom line cap
+/** @} */
+
+/** \defgroup U_PMF_LJT_ PMF LineJoinType Enumeration
+ For
+ EMF+ manual 2.1.1.19, Microsoft name: LineJoinType Enumeration (U_LJT_*)
+ @{
+*/
+#define U_LJT_Miter 0x00 //!< Miter line join
+#define U_LJT_Bevel 0x01 //!< Bevel line join
+#define U_LJT_Round 0x02 //!< Round line join
+#define U_LJT_MiterClipped 0x03 //!< Miter Clipped line join
+/** @} */
+
+/** \defgroup U_PMF_LS_ PMF LineStyle Enumeration
+ For
+ EMF+ manual 2.1.1.20, Microsoft name: LineStyle Enumeration (U_LS_*)
+ @{
+*/
+#define U_LS_Solid 0x00 //!< Solid line
+#define U_LS_Dash 0x01 //!< Dashed line
+#define U_LS_Dot 0x02 //!< Dotted line
+#define U_LS_DashDot 0x03 //!< Dash Dot line
+#define U_LS_DashDotDot 0x04 //!< Dash Dot Dot line
+#define U_LS_Custom 0x05 //!< Custom line
+/** @} */
+
+/** \defgroup U_PMF_MDT_ PMF MetafileDataType Enumeration
+ For
+ EMF+ manual 2.1.1.21, Microsoft name: MetafileDataType Enumeration (U_MDT_*)
+ @{
+*/
+#define U_MDT_Wmf 0x01 //!< WMF metafile
+#define U_MDT_WmfPlaceable 0x02 //!< WMF placeable metafile
+#define U_MDT_Emf 0x03 //!< EMF metafile
+#define U_MDT_EmfPlusOnly 0x04 //!< EMF+ single mode metafile
+#define U_MDT_EmfPlusDual 0x05 //!< EMF+ dual mode metafile
+/** @} */
+
+/** \defgroup U_PMF_OT_ PMF ObjectType Enumeration
+ For
+ EMF+ manual 2.1.1.22, Microsoft name: ObjectType Enumeration (U_OT_*)
+ @{
+*/
+#define U_OT_Invalid 0x00 //!< Invalid object
+#define U_OT_Brush 0x01 //!< Brush object
+#define U_OT_Pen 0x02 //!< Pen object
+#define U_OT_Path 0x03 //!< Path object
+#define U_OT_Region 0x04 //!< Region object
+#define U_OT_Image 0x05 //!< Image object
+#define U_OT_Font 0x06 //!< Font object
+#define U_OT_StringFormat 0x07 //!< StringFormat object
+#define U_OT_ImageAttributes 0x08 //!< ImageAttributes object
+#define U_OT_CustomLineCap 0x09 //!< CustomLineCap object
+/** @} */
+
+/** \defgroup U_PMF_PPT_ PMF PathPointType Enumeration
+ For
+ EMF+ manual 2.1.1.23, Microsoft name: PathPointType Enumeration (U_PPT_*)
+ @{
+*/
+#define U_PPT_Start 0x00 //!< Start of path
+#define U_PPT_Line 0x01 //!< Line path
+#define U_PPT_Bezier 0x03 //!< Bezier path
+#define U_PPT_MASK 0x0F //!< MASK for bits in flag
+/** @} */
+
+/** \defgroup U_PMF_PA_ PMF PenAlignment Enumeration
+ For
+ EMF+ manual 2.1.1.24, Microsoft name: PenAlignment Enumeration (U_PA_*)
+ @{
+*/
+#define U_PA_Center 0x00 //!< Center pen alignment
+#define U_PA_Inset 0x01 //!< Inset pen alignment
+#define U_PA_Left 0x02 //!< Left pen alignment
+#define U_PA_Outset 0x03 //!< Outset pen alignment
+#define U_PA_Right 0x04 //!< Right pen alignment
+/** @} */
+
+/** \defgroup U_PMF_PF_ PMF PixelFormat Enumeration
+ For U_PMF_BITMAP PxFormat field
+ EMF+ manual 2.1.1.25, Microsoft name: PixelFormat Enumeration (U_PF_*)
+
+ Bitmap for this 32 bit value is:
+ 0-9 ignored
+ 10 Set: 32 bit ARGB; Clear: !32 bit ARGB
+ 11 Set: 16 bits/channel; Clear: !16 bits
+ 12 Set: colors premultiplied by alpha; Clear: !premultiplied
+ 13 Set: has Alpha; Clear: !has Alpha
+ 14 Set: Windows GDI supports; Clear: !Windows GDI supports
+ 15 Set: uses LUT; Clear !uses LUT
+ 16-23 = total number of BITS per pixel
+ 24-31 = pixel format enumeration index (0->15)
+ @{
+*/
+#define U_PF_Undefined 0x00000000 //!< undefined Pixel Format
+#define U_PF_1bppIndexed 0x00030101 //!< monochrome with LUT
+#define U_PF_4bppIndexed 0x00030402 //!< 4 bit with LUT
+#define U_PF_8bppIndexed 0x00030803 //!< 8 bit with LUT
+#define U_PF_16bppGrayScale 0x00101004 //!< 16 bits grey values
+#define U_PF_16bppRGB555 0x00021005 //!< 16 bit RGB values (5,5,5,(1 ignored))
+#define U_PF_16bppRGB565 0x00021006 //!< 16 bit RGB values (5,6,5)
+#define U_PF_16bppARGB1555 0x00061007 //!< 16 bit ARGB values (1 alpha, 5,5,5 colors)
+#define U_PF_24bppRGB 0x00021808 //!< 24 bit RGB values (8,8.8)
+#define U_PF_32bppRGB 0x00022009 //!< 32 bit RGB value (8,8,8,(8 ignored))
+#define U_PF_32bppARGB 0x0026200A //!< 32 bit ARGB values (8 alpha,8,8,8)
+#define U_PF_32bppPARGB 0x000E200B //!< 32 bit PARGB values (8,8,8,8, but RGB already multiplied by A)
+#define U_PF_48bppRGB 0x0010300C //!< 48 bit RGB (16,16,16)
+#define U_PF_64bppARGB 0x0034400D //!< 64 bit ARGB (16 alpha, 16,16,16)
+#define U_PF_64bppPARGB 0x001A400E //!< 64 bit PARGB (16,16,16,16, but RGB already multiplied by A)
+/** @} */
+
+/** \defgroup U_PMF_POM_ PMF PixelOffsetMode Enumeration
+ For
+ EMF+ manual 2.1.1.26, Microsoft name: PixelOffsetMode Enumeration (U_POM_*)
+ @{
+*/
+#define U_POM_Default 0x00 //!< center at {0.0,0.0}
+#define U_POM_HighSpeed 0x01 //!< center at {0.0,0.0}
+#define U_POM_HighQuality 0x02 //!< center at {0.5,0.5}
+#define U_POM_None 0x03 //!< center at {0.0,0.0}
+#define U_POM_Half 0x04 //!< center at {0.5,0.5}
+/** @} */
+
+/** \defgroup U_PMF_RNDT_ PMF RegionNodeDataType Enumeration
+ For
+ EMF+ manual 2.1.1.27, Microsoft name: RegionNodeDataType Enumeration (U_RNDT_*)
+ @{
+*/
+#define U_RNDT_Kids 0x00000000 //!< One of the next 5 is to be applied
+#define U_RNDT_And 0x00000001 //!< AND the child nodes
+#define U_RNDT_Or 0x00000002 //!< OR the child nodes
+#define U_RNDT_Xor 0x00000003 //!< XOR the child nodes
+#define U_RNDT_Exclude 0x00000004 //!< Part of 1st child node not in 2nd child node
+#define U_RNDT_Complement 0x00000005 //!< Part of 2nd child node not in 1st child node
+#define U_RNDT_Rect 0x10000000 //!< Child node is a rectangle
+#define U_RNDT_Path 0x10000001 //!< Child node is a path
+#define U_RNDT_Empty 0x10000002 //!< Child node is empty
+#define U_RNDT_Infinite 0x10000003 //!< Child node has infinite extent (?)
+/** @} */
+
+/** \defgroup U_PMF_SM_ PMF SmoothingMode Enumeration
+ For
+ EMF+ manual 2.1.1.28, Microsoft name: SmoothingMode Enumeration (U_SM_*)
+ @{
+*/
+#define U_SM_Default 0x00 //!< Default smoothing
+#define U_SM_HighSpeed 0x01 //!< High Speed smoothing
+#define U_SM_HighQuality 0x02 //!< High Quality smoothing
+#define U_SM_None 0x03 //!< No smoothing
+#define U_SM_AntiAlias8x4 0x04 //!< Anti Alias 8x4 smoothing
+#define U_SM_AntiAlias8x8 0x05 //!< Anti Alias 8x8 smoothing
+/** @} */
+
+/** \defgroup U_PMF_SA_ PMF StringAlignment Enumeration
+ For
+ EMF+ manual 2.1.1.29, Microsoft name: StringAlignment Enumeration (U_SA_*)
+
+ Note, that unlike EMF these are with respect to the bounding rectangle, not to a single point. So
+ to draw centered text, for instance, U_SA_Center must be used, and the bounding rectangle must also be
+ centered.
+
+ For horizontal positioning of L->R text Near is all the way left in the box, Far is all the way right,
+ and Center puts the center of the text in the center of the box.
+
+ For vertical positioning things are a little strange. Near is a certain distance down from the top, Far is a
+ certain distance up from the bottom, and center puts the center of the text in the center of the box. The
+ "certain distance" is not specified in the EMF+ documentation. See the function U_PMR_drawstring() for an
+ implementation that places text on the baseline.
+ @{
+*/
+#define U_SA_Near 0x00 //!< Position near
+#define U_SA_Center 0x01 //!< Position center
+#define U_SA_Far 0x02 //!< Position far
+/** @} */
+
+/** \defgroup U_PMF_SDS_ PMF StringDigitSubstitution Enumeration
+ For
+ EMF+ manual 2.1.1.30, Microsoft name: StringDigitSubstitution Enumeration (U_SDS_*)
+ @{
+*/
+#define U_SDS_User 0x00 //!< Digit substitution is set by implementation
+#define U_SDS_None 0x01 //!< No Digit substitution
+#define U_SDS_National 0x02 //!< Digit substitution by official locale
+#define U_SDS_Traditional 0x03 //!< Digit substitution by traditional locale
+/** @} */
+
+/** \defgroup U_PMF_ST_ PMF StringTrimming Enumeration
+ For
+ EMF+ manual 2.1.1.31, Microsoft name: StringTrimming Enumeration (U_ST_*)
+ @{
+*/
+#define U_ST_None 0x00 //!< no string trimming
+#define U_ST_Character 0x01 //!< Trim at Character
+#define U_ST_Word 0x02 //!< Trim at Word
+#define U_ST_EllipsisCharacter 0x03 //!< Trim at Ellipsis Character
+#define U_ST_EllipsisWord 0x04 //!< Trim at Ellipsis Word
+#define U_ST_EllipsisPath 0x05 //!< Trim at Ellipsis Path
+/** @} */
+
+/** \defgroup U_PMF_TRH_ PMF TextRenderingHint Enumeration
+ For
+ EMF+ manual 2.1.1.32, Microsoft name: TextRenderingHint Enumeration (U_TRH_*)
+ @{
+*/
+#define U_TRH_SystemDefault 0x00 //!< System Default
+#define U_TRH_SingleBitPerPixelGridFit 0x01 //!< Single Bit Per Pixel Grid Fit
+#define U_TRH_SingleBitPerPixel 0x02 //!< Single Bit Per Pixel
+#define U_TRH_AntialiasGridFit 0x03 //!< Antialias Grid Fit
+#define U_TRH_Antialias 0x04 //!< Antialias
+#define U_TRH_ClearTypeGridFit 0x05 //!< ClearType Grid Fit
+/** @} */
+
+/** \defgroup U_PMF_UT_ PMF UnitType Enumeration
+ For
+ EMF+ manual 2.1.1.33, Microsoft name: UnitType Enumeration (U_UT_*)
+ @{
+*/
+#define U_UT_World 0x00 //!< World units
+#define U_UT_Display 0x01 //!< Display units
+#define U_UT_Pixel 0x02 //!< Pixel units
+#define U_UT_Point 0x03 //!< Point units
+#define U_UT_Inch 0x04 //!< Inch units
+#define U_UT_Document 0x05 //!< Document units
+#define U_UT_Millimeter 0x06 //!< Millimeter units
+/** @} */
+
+/** \defgroup U_PMF_WM_ PMF WrapMode Enumeration
+ For
+ EMF+ manual 2.1.1.34, Microsoft name: WrapMode Enumeration (U_WM_*)
+ @{
+*/
+#define U_WM_Tile 0x00000000 //!< Tile
+#define U_WM_TileFlipX 0x00000001 //!< Reverse horizontally then tile
+#define U_WM_TileFlipY 0x00000002 //!< Reverse vertically then tile
+#define U_WM_TileFlipXY 0x00000003 //!< Reverse horizontally and vertically then tile
+#define U_WM_Clamp 0x00000004 //!< Clamp pattern to the object boundary
+/** @} */
+
+/** \defgroup U_PMF_BD_ PMF BrushData Flags
+ For
+ EMF+ manual 2.1.2.1, Microsoft name: BrushData Flags (U_BD_*)
+
+ Bit flags allowed in brush object types. Each bit indicates a type of object which is included.
+ There are 5 brush types abbreviated A through E, and each uses a subset of the
+ BrushData Flags, as summarized in the following table:
+
+ Bits Brush____Type EMF+ Manual
+ used Abbrev. Name
+ 5 A U_PMF_LINEARGRADIENTBRUSHDATA 2.2.2.24
+ 6 B U_PMF_PATHGRADIENTBRUSHDATA 2.2.2.29
+ 3 C U_PMF_TEXTUREBRUSHDATA 2.2.2.45
+ 0 D U_PMF_HATCHBRUSHDATA 2.2.2.20
+ 0 E U_PMF_SOLIDBRUSHDATA 2.2.2.45
+ @{
+*/
+#define U_BD_None 0x0000 //!< no bits set
+#define U_BD_Path 0x0001 //!< Path, in {B}
+#define U_BD_Transform 0x0002 //!< Transform in {ABC}
+#define U_BD_PresetColors 0x0004 //!< PresetColors in {AB}
+#define U_BD_BlendFactorsH 0x0008 //!< BlendFactorsH in {AB}
+#define U_BD_BlendFactorsV 0x0010 //!< BlendFactorsV in {A} - Note, not actually implemented in GDI+.
+#define U_BD_NoBit 0x0020 //!< unused bit
+#define U_BD_FocusScales 0x0040 //!< Focus Scales in {B}
+#define U_BD_IsGammaCorrected 0x0080 //!< GammaCorrected in {ABC}
+#define U_BD_DoNotTransform 0x0100 //!< Ignore world to device transform in {C}
+#define U_BD_MASKA 0x009E //!< all bits that MAY be set in A
+#define U_BD_MASKB 0x00CF //!< all bits that MAY be set in B
+#define U_BD_MASKC 0x0182 //!< all bits that MAY be set in C
+/** @} */
+
+/** \defgroup U_PMF_CLCD_ PMF CustomLineCapData Flags
+ For
+ EMF+ manual 2.1.2.2, Microsoft name: CustomLineCapData Flags (U_CLCD_*)
+ @{
+*/
+#define U_CLCD_None 0x00 //!< no bits set
+#define U_CLCD_FillPath 0x01 //!< Fill Path
+#define U_CLCD_LinePath 0x02 //!< Line Path
+/** @} */
+
+/** \defgroup U_PMF_DSO_ PMF DriverStringOptions Flags
+ For
+ EMF+ manual 2.1.2.3, Microsoft name: DriverStringOptions Flags (U_DSO_*)
+ @{
+*/
+#define U_DSO_None 0x00 //!< no bits set
+#define U_DSO_CmapLookup 0x01 //!< Set: value is a Unicode character; Clear: value is an index into Glyph table in a font
+#define U_DSO_Vertical 0x02 //!< Set: draw string verically; Clear: draw horizontally
+#define U_DSO_RealizedAdvance 0x04 /**< Set: U_PMF_DRAWDRIVERSTRING Positions field specifies only position of first of Glyphs field,
+ with the rest calculated from font information; Clear: Positions specifies coordinates for each Glyphs member.*/
+#define U_DSO_LimitSubpixel 0x08 //!< Set: use less memory to cache anti-aliased glyphs; Clear: use more
+/** @} */
+
+/** \defgroup U_PMF_FS_ PMF FontStyle Flags
+ For
+ EMF+ manual 2.1.2.4, Microsoft name: FontStyle Flags (U_FS_*)
+# @{
+*/
+#define U_FS_None 0x00 //!< no bits set
+#define U_FS_Bold 0x01 //!< Bold
+#define U_FS_Italic 0x02 //!< Italic
+#define U_FS_Underline 0x04 //!< Underline
+#define U_FS_Strikeout 0x08 //!< Strikeout
+/** @} */
+
+/** \defgroup U_PMF_PLTS_ PMF PaletteStyle Flags
+ For
+ EMF+ manual 2.1.2.5, Microsoft name: PaletteStyle Flags (U_PLTS_*)
+ @{
+*/
+#define U_PLTS_None 0x00 //!< no bits set
+#define U_PLTS_HasAlpha 0x01 //!< Has Alpha
+#define U_PLTS_GrayScale 0x02 //!< Gray Scale
+#define U_PLTS_Halftone 0x04 //!< Halftone
+/** @} */
+
+/** \defgroup U_PMF_PTP_ PMF PathPointType Flags
+ For
+ EMF+ manual 2.1.2.6, Microsoft name: PathPointType Flags (U_PTP_*)
+ @{
+*/
+#define U_PTP_None 0x00 //!< no bits set
+#define U_PTP_DashMode 0x10 //!< Dash Mode
+#define U_PTP_PathMarker 0x20 //!< Path Marker
+#define U_PTP_NoBit 0x40 //!< unused bit
+#define U_PTP_CloseSubpath 0x80 //!< CloseSubpath
+#define U_PTP_NotClose 0x70 //!< Everything but close
+#define U_PTP_MASK 0xF0 //!< Everything
+#define U_PTP_SHIFT 4 //!< offset to this bitfield
+/** @} */
+
+/** \defgroup U_PMF_PD_ PMF PenData Flags
+ For
+ EMF+ manual 2.1.2.7, Microsoft name: PenData Flags (U_PD_*)
+
+If bit is set the corresponding object must be specfied in the OptionalData field
+
+ @{
+*/
+#define U_PD_None 0x0000 //!< no bits set
+#define U_PD_Transform 0x0001 //!< Transform
+#define U_PD_StartCap 0x0002 //!< Start Cap
+#define U_PD_EndCap 0x0004 //!< End Cap
+#define U_PD_Join 0x0008 //!< Join
+#define U_PD_MiterLimit 0x0010 //!< Miter Limit
+#define U_PD_LineStyle 0x0020 //!< Line Style
+#define U_PD_DLCap 0x0040 //!< Dashed Line Cap
+#define U_PD_DLOffset 0x0080 //!< Dashed Line Offset
+#define U_PD_DLData 0x0100 //!< Dashed Line Data
+#define U_PD_NonCenter 0x0200 //!< Alignment must be specified with optinal data
+#define U_PD_CLData 0x0400 //!< Compound Line Data
+#define U_PD_CustomStartCap 0x0800 //!< Custom Start Cap
+#define U_PD_CustomEndCap 0x1000 //!< Custom End Cap
+/** @} */
+
+/** \defgroup U_PMF_SF_ PMF StringFormat Flags
+ For EmfPlusStringFormat
+ EMF+ manual 2.1.2.8, Microsoft name: StringFormat Flags (U_SF_*)
+ @{
+*/
+#define U_SF_None 0x00000000 //!< no bits set
+#define U_SF_DirectionRightToLeft 0x00000001 //!< text Right to Left
+#define U_SF_DirectionVertical 0x00000002 //!< text Left to Right
+#define U_SF_NoFitBlackBox 0x00000004 //!< text not restricted to layout bbox
+#define U_SF_NoBit4 0x00000008 //!< unused bit
+#define U_SF_NoBit5 0x00000010 //!< unused bit
+#define U_SF_DisplayFormatControl 0x00000020 //!< control codes display as "representative" glyphs
+#define U_SF_NoBit7 0x00000040 //!< unused bit
+#define U_SF_NoBit8 0x00000080 //!< unused bit
+#define U_SF_NoBit9 0x00000100 //!< unused bit
+#define U_SF_NoBit10 0x00000200 //!< unused bit
+#define U_SF_NoFontFallback 0x00000400 //!< show as missing glyph if not in font
+#define U_SF_MeasureTrailingSpaces 0x00000800 //!< trailing spaces included in line length
+#define U_SF_NoWrap 0x00001000 //!< text does not wrap
+#define U_SF_LineLimit 0x00002000 //!< emit whole lines if not clipped
+#define U_SF_NoClip 0x00004000 //!< text is not clipped
+#define U_SF_BypassGDI 0x80000000 //!< use implementation specific text rendering instead of GDI
+/** @} */
+
+/** \defgroup U_PMF_IE_ PMF ImageEffects Identifiers
+ For
+ EMF+ manual 2.1.3.1, Microsoft name: ImageEffects Identifiers (U_IE_*)
+ @{
+*/
+#define U_IE_BlurEffectGuid "{633C80A4-1843-482B-9EF2-BE2834C5FDD4}" //!< Blur Effect
+#define U_IE_BrightnessContrastEffectGuid "{D3A1DBE1-8EC4-4C17-9F4C-EA97AD1C343D}" //!< Brightness Contrast Effect
+#define U_IE_ColorBalanceEffectGuid "{537E597D-251E-48DA-9664-29CA496B70F8}" //!< Color Balance Effect
+#define U_IE_ColorCurveEffectGuid "{DD6A0022-58E4-4A67-9D9B-D48EB881A53D}" //!< Color Curve Effect
+#define U_IE_ColorLookupTableEffectGuid "{A7CE72A9-0F7F-40D7-B3CC-D0C02D5C3212}" //!< Color Lookup Table Effect
+#define U_IE_ColorMatrixEffectGuid "{718F2615-7933-40E3-A511-5F68FE14DD74}" //!< Color Matrix Effect
+#define U_IE_HueSaturationLightnessEffectGuid "{8B2DD6C3-EB07-4D87-A5F0-7108E26A9C5F}" //!< Hue Saturation Lightness Effect
+#define U_IE_LevelsEffectGuid "{99C354EC-2A31-4F3A-8C34-17A803B33A25}" //!< Levels Effect
+#define U_IE_RedEyeCorrectionEffectGuid "{74D29D05-69A4-4266-9549-3CC52836B632}" //!< Red Eye Correction Effect
+#define U_IE_SharpenEffectGuid "{63CBF3EE-C526-402C-8F71-62C540BF5142}" //!< Sharpen Effect
+#define U_IE_TintEffectGuid "{1077AF00-2848-4441-9489-44AD4C2D7A2C}" //!< Tint Effect
+/** @} */
+
+/** \defgroup U_PMF_IEE_ PMF ImageEffects Enumerators
+ based on U_IE_
+ These may be used by a parser to set up for a switch() statement.
+ @{
+*/
+#define U_IEE_Unknown 0 //!< none of the following
+#define U_IEE_BlurEffectGuid 1 //!< Blur Effect
+#define U_IEE_BrightnessContrastEffectGuid 2 //!< Brightness Contrast Effect
+#define U_IEE_ColorBalanceEffectGuid 3 //!< Color Balance Effect
+#define U_IEE_ColorCurveEffectGuid 4 //!< Color Curve Effect
+#define U_IEE_ColorLookupTableEffectGuid 5 //!< Color Lookup Table Effect
+#define U_IEE_ColorMatrixEffectGuid 6 //!< Color Matrix Effect
+#define U_IEE_HueSaturationLightnessEffectGuid 7 //!< Hue Saturation Lightness Effect
+#define U_IEE_LevelsEffectGuid 8 //!< Levels Effect
+#define U_IEE_RedEyeCorrectionEffectGuid 9 //!< Red Eye Correction Effect
+#define U_IEE_SharpenEffectGuid 10 //!< Sharpen Effect
+#define U_IEE_TintEffectGuid 11 //!< Tint Effect
+/** @} */
+
+/** \defgroup U_PMF_OC_ PMF ObjectClamp Identifiers
+ For U_PMF_IMAGEATTRIBUTES ObjectClamp field
+ EMF+ manual 2.2.1.5, Microsoft name: ImageEffects Identifiers (U_OC_*)
+ @{
+*/
+#define U_OC_Rect 0x00 //!< Clamp object to rectangle.
+#define U_OC_Bitmap 0x01 //!< Clamp object to bitmap.
+/** @} */
+
+/** \defgroup U_PMF_PPF_ PMF PathPoint Flags
+ For U_PMF_PATH Flags field
+ For U_PMF_CMN_HDR Flags field
+ EMF+ manual 2.2.1.6, Microsoft name: PathPoint Flags (U_PPF_*)
+ For U_PMF_CMN_HDR Flags the bits are scattered all over the EMF+ manual.
+ NOTE: bitfields in manual are BIG endian and MSB 0.
+ This code reads the 16 bit flag field as LITTLE endian and uses LSB 0.
+ The values shown are AFTER the data has been read into a uint16_t and the byte order set
+ appropriately.
+ All of these come out of a 16 bit field.
+ @{
+*/
+#define U_PPF_B 0x8000 //!< 15 Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table.
+#define U_PPF_BZ 0x8000 //!< 15 Set: Points are on a Bezier curve; Clear: Points are on a line
+#define U_PPF_N 0x8000 //!< 15 Set: object definition continues in next record; Clear: this is the final object definition record
+#define U_PPF_K 0x8000 //!< 15 Set: int16_t coordinates; Clear: use U_FLOAT coordinates
+#define U_PPF_C 0x4000 //!< 14 Set: int16_t coordinates; Clear: use U_FLOAT coordinates
+#define U_PPF_XM 0x2000 //!< 13 Set: Post multiply matrix; Clear: Pre multiply matrix
+#define U_PPF_F 0x2000 //!< 13 Set: winding fill; Clear: alternate fill
+#define U_PPF_E 0x2000 //!< 13 Set: effect from previous U_PMF_SERIALIZABLEOBJECT record will be applied,; Clear: no effect applied
+#define U_PPF_R 0x1000 //!< 12 Set: U_PMF_PathPointTypeRLE and/or U_PMF_PathPointType objects; Clear: only U_PMF_PathPointType
+#define U_PPF_P 0x0800 //!< 11 Set: relative coordinates; Clear absolute coordinates
+#define U_PPF_D 0x0400 //!< 10 Set: draw path closed; Clear: draw path open
+#define U_PPF_VGA 0x0002 //!< 1 Set: Palette is VGA basic colors; Clear: Palette is ???
+#define U_PPF_PP 0x0001 //!< 0 Set: Palette field is present; Clear: Palette field is absent
+#define U_PPF_DM 0x0001 //!< 0 Set: Dual-mode file; Clear: EMF+ only file
+#define U_PPF_AA 0x0001 //!< 0 Set: anti-aliasing on; Clear: anti-aliasing off
+#define U_PPF_VIDEO 0x0001 //!< 0 Set: reference device is video display; Clear: reference devis is printer
+/** @} */
+
+/** \defgroup U_PMF_FF_ PMF Masks and offsets for 16 bit flag fields
+ Documenting the OBSERVED positions of fields in 16 bit flag integers
+ after they have been read in Little Ended from files.
+
+ Note, some of these are used in more than one record type, only a single reference is provided
+ @{
+*/
+
+#define U_FF_MASK_SUBLID 0x003F //!< EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier
+#define U_FF_SHFT_SUBLID 0x000A //!< EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier
+#define U_FF_MASK_PRILID 0x03FF //!< EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier
+#define U_FF_SHFT_PRILID 0x0000 //!< EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier
+#define U_FF_MASK_LID 0xFFFF //!< EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier
+#define U_FF_SHFT_LID 0x0000 //!< EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier
+#define U_FF_MASK_RL 0x003F //!< EMF+ manual 2.2.2.32, Microsoft name: EmfPlusPathPointTypeRLE
+#define U_FF_SHFT_RL 0x0008 //!< EMF+ manual 2.2.2.32, Microsoft name: EmfPlusPathPointTypeRLE
+#define U_FF_MASK_PPT 0x00FF //!< EMF+ manual 2.2.2.32, Microsoft name: EmfPlusPathPointTypeRLE
+#define U_FF_SHFT_PPT 0x0000 //!< EMF+ manual 2.2.2.32, Microsoft name: EmfPlusPathPointTypeRLE
+/* the next one is used most places an object ID is specified */
+#define U_FF_MASK_OID8 0x00FF //!< EMF+ manual 2.3.1.3, Microsoft name: EmfPlusSetClipPath
+#define U_FF_SHFT_OID8 0x0000 //!< EMF+ manual 2.3.1.3, Microsoft name: EmfPlusSetClipPath
+#define U_FF_MASK_CM4 0x000F //!< EMF+ manual 2.3.1.3, Microsoft name: EmfPlusSetClipPath
+#define U_FF_SHFT_CM4 0x0008 //!< EMF+ manual 2.3.1.3, Microsoft name: EmfPlusSetClipPath
+#define U_FF_MASK_OT 0x003F //!< EMF+ manual 2.3.5.1, Microsoft name: EmfPlusObject
+#define U_FF_SHFT_OT 0x0008 //!< EMF+ manual 2.3.5.1, Microsoft name: EmfPlusObject
+#define U_FF_MASK_AA 0x007F //!< EMF+ manual 2.3.6.1, Microsoft name: EmfPlusSetAntiAliasMode
+#define U_FF_SHFT_AA 0x0001 //!< EMF+ manual 2.3.6.1, Microsoft name: EmfPlusSetAntiAliasMode
+#define U_FF_MASK_CM 0x00FF //!< EMF+ manual 2.3.6.2, Microsoft name: EmfPlusSetCompositingMode
+#define U_FF_SHFT_CM 0x0000 //!< EMF+ manual 2.3.6.2, Microsoft name: EmfPlusSetCompositingMode
+#define U_FF_MASK_CQ 0x00FF //!< EMF+ manual 2.3.6.3, Microsoft name: EmfPlusSetCompositingQuality
+#define U_FF_SHFT_CQ 0x0000 //!< EMF+ manual 2.3.6.3, Microsoft name: EmfPlusSetCompositingQuality
+#define U_FF_MASK_IM 0x00FF //!< EMF+ manual 2.3.6.4, Microsoft name: EmfPlusSetInterpolationMode
+#define U_FF_SHFT_IM 0x0000 //!< EMF+ manual 2.3.6.4, Microsoft name: EmfPlusSetInterpolationMode
+#define U_FF_MASK_PxOffM 0x00FF //!< EMF+ manual 2.3.6.5, Microsoft name: EmfPlusSetPixelOffsetMode
+#define U_FF_SHFT_PxOffM 0x0000 //!< EMF+ manual 2.3.6.5, Microsoft name: EmfPlusSetPixelOffsetMode
+#define U_FF_MASK_TGC 0x0FFF //!< EMF+ manual 2.3.6.7, Microsoft name: EmfPlusSetTextContrast
+#define U_FF_SHFT_TGC 0x0000 //!< EMF+ manual 2.3.6.7, Microsoft name: EmfPlusSetTextContrast
+#define U_FF_MASK_TRH 0x00FF //!< EMF+ manual 2.3.6.8, Microsoft name: EmfPlusSetTextRenderingHint
+#define U_FF_SHFT_TRH 0x0000 //!< EMF+ manual 2.3.6.8, Microsoft name: EmfPlusSetTextRenderingHint
+#define U_FF_MASK_UT 0x00FF //!< EMF+ manual 2.3.7.1, Microsoft name: EmfPlusBeginContainer
+#define U_FF_SHFT_UT 0x0008 //!< EMF+ manual 2.3.7.1, Microsoft name: EmfPlusBeginContainer
+#define U_FF_MASK_TSC 0x7FFF //!< EMF+ manual 2.3.8.1, Microsoft name: EmfPlusSetTSClip
+#define U_FF_SHFT_TSC 0x0000 //!< EMF+ manual 2.3.8.1, Microsoft name: EmfPlusSetTSClip
+#define U_FF_MASK_PU 0x00FF //!< EMF+ manual 2.3.9.5, Microsoft name: EmfPlusSetPageTransform
+#define U_FF_SHFT_PU 0x0000 //!< EMF+ manual 2.3.9.5, Microsoft name: EmfPlusSetPageTransform
+/** @} */
+
+
+/** \defgroup U_PMF_GFVR_ PMF MetafileSignature
+ For U_PMF_GRAPHICSVERSION Signature field
+ EMF+ manual 2.2.2.19, Microsoft name: (none) (U_GFVR_*)
+ @{
+*/
+#define U_GFVR_PMF 0x000DBC01 //!< indicates an EMF+ metafile
+#define U_GFVR_MASKHI 0xFFFFF000 //!< mask for the signature bit field (20 bits)
+#define U_GFVR_MASKLO 0x00000FFF //!< mask for the version bit field (12 bits)
+/** @} */
+
+/** \defgroup U_PMF_XM_ PMF Matrix Multiplication Enumerator
+ For U_PMF_RotateWorldTransform and others
+ EMF+ manual 2.3.9.3, Microsoft name: (none) (U_XM_*)
+ @{
+*/
+#define U_XM_PostX 1 //!< Post Multiply change to current Transformation Matrix
+#define U_XM_PreX 0 //!< Pre Multiply change to current Transformation Matrix
+/** @} */
+
+
+/* Utility objects, not defined in EMF+ spec */
+
+/** @brief Used to accumulate data for objects continued over multiple records.
+ see EMF+ manual 2.3.5.1
+*/
+typedef struct {
+ char *accum; /**< data accumulates here */
+ uint32_t space; /**< bytes allocated */
+ uint32_t used; /**< bytes in use */
+ int Type; /**< ObjectType enumeration */
+ int Id; /**< Object ID */
+} U_OBJ_ACCUM;
+
+/** @brief Holds EMF+ objects and records in EMF+ file format byte order.
+*/
+typedef struct {
+ char *Data; /**< Buffer that hold's the PseudoObject's data */
+ size_t Size; /**< Number of bytes allocated in Data (may be >Used if padding is present) */
+ size_t Used; /**< Number of data bytes that are stored in Data */
+ uint32_t Type; /**< Type numbers are from manual section: 1.2.3.4 -> 10203040 */
+} U_PSEUDO_OBJ;
+
+/** @brief DoublePseudoObject holds pairs of PseudoObjects. Used for constructing paths along with their types.
+ The data stored in the PsuedoObjects maintains LittleEndian-ness, as expected in the final file.
+ The type is U_RAW_OID, and there is no elements count at the beginning of Data
+*/
+typedef struct {
+ uint32_t Elements; /**< Element count, applies to both PseudoObjects */
+ U_PSEUDO_OBJ *poPoints; /**< Points in path */
+ U_PSEUDO_OBJ *poTypes; /**< Types of points in path */
+} U_DPSEUDO_OBJ;
+
+/** @brief Serializer description records.
+
+An array of these are passed to U_PMF_SERIAL_set() to construct EMF+ objects from their component parts.
+The U_PMF_SERIAL_set() function should not ever be called directly by end user code.
+*/
+typedef struct {
+ const void *Ptr; /**< Pointer to the first byte of the data field.
+ Each data field is an array of a basic type of Units
+ bytes repeated Reps times */
+ size_t Units; /**< Number of bytes in each unit of each data field. */
+ size_t Reps; /**< Number of repeats of Units in each data field. */
+ int TE; /**< (Target Endian). Only relevant for Units of 2 or 4*/
+} U_SERIAL_DESC;
+
+/** @brief FontInfoParams hold font information that is needed by U_PMR_drawstring so that it can
+ place text on the baseline. This must be extracted from the font file using
+ an appropriate utility. (See testbed_pmf.c for a table of these values for some
+ common fonts.)
+*/
+typedef struct {
+ char *name; /**< Font name (like "Arial") */
+ int Ascent; /**< in Font units (positive) */
+ int Descent; /**< in Font units (negative) */
+ int LineGap; /**< in Font units (positive) */
+ int EmSize; /**< Y extent of Em square, usually 2048 */
+ int yMax; /**< in Font units (positive) */
+ int yMin; /**< in Font units (negative) */
+} U_FontInfoParams;
+
+
+
+/* EMF+ objects */
+
+/** @brief EMF+ manual 2.2.1.1, Microsoft name: EmfPlusBrush Object
+
+variable part of object follows structure:
+ uint32_t Data[]; // one of the 5 types of Brush data (2.2.2 20, 24, 29, 43, or 45)
+*/
+typedef struct {
+ uint32_t Version; //!< EmfPlusGraphicsVersion object
+ uint32_t Type; //!< BrushType Enumeration
+} U_PMF_BRUSH;
+
+/** @brief EMF+ manual 2.2.1.2, Microsoft name: EmfPlusCustomLineCap Object */
+typedef struct {
+/*@{*/
+ uint32_t Version; //!< EmfPlusGraphicsVersion object
+ uint32_t Type; //!< BrushType Enumeration
+/* variable part of object, not part of structure
+ uint32_t Data[]; //!< one of the 2 types of Linecap data (2.2.2 12, 13)
+*/
+/*@}*/
+} U_PMF_CUSTOMLINECAP;
+
+/** @brief EMF+ manual 2.2.1.3, Microsoft name: EmfPlusFont Object */
+typedef struct {
+/*@{*/
+ uint32_t Version; //!< EmfPlusGraphicsVersion object
+ U_FLOAT EmSize; //!< em size in units of SizeUnit
+ uint32_t SizeUnit; //!< UnitType enumeration
+ int32_t FSFlags; //!< FontStyle flags
+ uint32_t Reserved; //!< ignored
+ uint32_t Length; //!< Number of Unicode Characters in FamilyName
+/* variable part of object, not part of structure
+ uint16_t FamilyName[]; //!< Unicode (UTF-16LE) name of font family
+*/
+/*@}*/
+} U_PMF_FONT;
+
+/** @brief EMF+ manual 2.2.1.4, Microsoft name: EmfPlusImage Object */
+typedef struct {
+/*@{*/
+ uint32_t Version; //!< EmfPlusGraphicsVersion object
+ uint32_t Type; //!< ImageDataType Enumeration
+/* variable part of object, not part of structure
+ uint32_t Data[]; //!< one of the 2 types of image data (2.2.2 2 or 27)
+*/
+/*@}*/
+} U_PMF_IMAGE;
+
+/** @brief EMF+ manual 2.2.2.1, Microsoft name: EmfPlusARGB Object, out of order, needed for 2.2.1.5 */
+typedef struct {
+/*@{*/
+ uint8_t Blue; //!< Blue color (0-255)
+ uint8_t Green; //!< Green color (0-255)
+ uint8_t Red; //!< Red color (0-255)
+ uint8_t Alpha; //!< Alpha (0-255)
+/*@}*/
+} U_PMF_ARGB;
+
+/** @brief EMF+ manual 2.2.1.5, Microsoft name: EmfPlusImageAttributes Object */
+typedef struct {
+ /*@{*/
+ uint32_t Version; //!< EmfPlusGraphicsVersion object
+ uint32_t Reserved1; //!< ignored
+ uint32_t WrapMode; //!< WrapMode object
+ U_PMF_ARGB ClampColor; //!< EmfPlusARGB object
+ int32_t ObjectClamp; //!< ObjectClamp Identifiers
+ uint32_t Reserved2; //!< ignored
+/*@}*/
+} U_PMF_IMAGEATTRIBUTES;
+
+/** @brief EMF+ manual 2.2.1.6, Microsoft name: EmfPlusPath Object */
+typedef struct {
+/*@{*/
+ uint32_t Version; //!< EmfPlusGraphicsVersion object
+ uint32_t Count; //!< points and point types in this object
+ uint16_t Flags; //!< PathPoint Flags
+/* variable part of object, not part of structure
+ points array of points like:
+ U_PPF_P U_PPF_C Type
+ 1 x U_PMF_POINTR
+ 0 1 U_PMF_POINT
+ 0 0 U_PMF_POINTF
+ types array of:.
+ U_PPF_R Type
+ 1 U_PMF_PATHPOINTTYPERLE and/or U_PMF_PATHPOINTTYPE
+ 0 U_PMF_PathPointType (only)
+ alignment padding up to 3 bytes
+*/
+/*@}*/
+} U_PMF_PATH;
+
+/** @brief EMF+ manual 2.2.1.7, Microsoft name: EmfPlusPen Object */
+
+typedef struct {
+ uint32_t Version; //!< EmfPlusGraphicsVersion object
+ uint32_t type; //!< must be zero
+/* variable part of object, not part of structure
+ U_PMF_PENDATA pen
+ U_PMF_BRUSH brush
+*/
+} U_PMF_PEN;
+
+/** @brief EMF+ manual 2.2.2.40, Microsoft name: EmfPlusRegionNode Object, out of order, needed for 2.2.1.8 */
+typedef struct {
+ uint32_t Type; //!< RegionNodeDataType
+/* variable part of object, not part of structure, will be absent in object for some types
+ data data is a tree made up of some combination of these objects
+ U_PMF_REGIONNODEPATH 2.2.2.42 terminal node
+ U_PMF_RECTF 2.2.2.39 terminal node
+ U_PMF_REGIONNODECHILDNODES 2.2.2.41 non-terminal node
+*/
+} U_PMF_REGIONNODE;
+
+/** @brief EMF+ manual 2.2.1.8, Microsoft name: EmfPlusRegion Object */
+typedef struct {
+ uint32_t Version; //!< EmfPlusGraphicsVersion object
+ uint32_t Elements; //!< Number of members in Nodes array
+/* variable part of object, not part of structure, will be absent in object for some types
+ U_PMF_REGIONNODE Nodes[1]; //!< Nodes defining region
+*/
+} U_PMF_REGION;
+
+/** @brief EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier Object, out of order, needed for 2.2.1.9
+
+Bit fields are not used in structs in this implementation, these are serialized/deserialized in
+the corresponding routines. Bitfields in the FILE (LITTLE endian here, manual uses BIG endian) are:
+ int SubLId : 6; Example: code for USA
+ int PriLId : 10; Example: code for English
+
+This type is defined as 16 bits in the manual section, but it is only ever used as part of a 32 bit field!
+*/
+typedef uint32_t U_PMF_LANGUAGEIDENTIFIER;
+
+/** @brief EMF+ manual 2.2.1.9, Microsoft name: EmfPlusStringFormat Object */
+typedef struct {
+ uint32_t Version; //!< EmfPlusGraphicsVersion object
+ uint32_t Flags; //!< StringFormat flags
+ U_PMF_LANGUAGEIDENTIFIER
+ Language; //!< String's Language
+ uint32_t StringAlignment; //!< StringAlignment enumeration.
+ uint32_t LineAlign; //!< StringAlignment enumeration.
+ uint32_t DigitSubstitution; //!< StringDigitSubstitution enumeration
+ U_PMF_LANGUAGEIDENTIFIER
+ DigitLanguage; //!< Digit's Language (overrides Language, above)
+ U_FLOAT FirstTabOffset; //!< the number of spaces to the first tab stop.
+ int32_t HotkeyPrefix; //!< HotkeyPrefix enumeration
+ U_FLOAT LeadingMargin; //!< space before starting position (text) of a string
+ U_FLOAT TrailingMargin; //!< space after last position (text) of a string
+ U_FLOAT Tracking; //!< horizontal space alotted per character/font specification per character
+ uint32_t Trimming; //!< StringTrimming enumeration
+ uint32_t TabStopCount; //!< Number of tab stops in data field.
+ uint32_t RangeCount; //!< Number of U_PMF_CHARACTERRANGE objects in data field.
+/* variable part of object, not part of structure.
+ U_PMF_STRINGFORMATDATA data
+
+ Note that U_PMF_STRINGFORMATDATA has no struct as it is entirely variable
+ and the size of the two fields in it are specified by the two preceding fields in this object type.
+*/
+} U_PMF_STRINGFORMAT;
+
+/** U_PMF_ARGB EMF+ manual 2.2.2.1, Microsoft name: EmfPlusARGB Object, defined above, before 2.2.1.6*/
+
+/** @brief EMF+ manual 2.2.2.2, Microsoft name: EmfPlusBitmap Object */
+typedef struct {
+ int32_t Width; //!< Width in pixels
+ int32_t Height; //!< Height in pixels
+ int32_t Stride; //!< length in bytes of 1 scan line (multiple of 4)
+ uint32_t PxFormat; //!< PixelFormat enumeration
+ uint32_t Type; //!< BitmapDataType enumeration (section 2.1.1.2).
+/* variable part of object, not part of structure.
+ (various types) BitmapData //!< is either an U_PMF_BITMAPDATA or U_PMF_COMPRESSEDIMAGE object
+*/
+} U_PMF_BITMAP;
+
+/** U_PMF_BITMAPDATA EMF+ manual 2.2.2.3, Microsoft name: EmfPlusBitmapData Object
+U_PMF_BITMAPDATA is an entirely variable object, there is no corresponding struct. It consists of
+
+ Colors U_PMF_PALETTE object
+ PixelData An array of bytes, meaning depends on fields in U_PMF_BITMAP object and the PixelFormat enumeration.
+
+*/
+
+/** @brief EMF+ manual 2.2.2.4, Microsoft name: EmfPlusBlendColors Object
+ For Pattern field of U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA
+*/
+typedef struct {
+ uint32_t Elements; //!< members in each array
+/* variable part of object, not part of structure.
+ U_FLOAT Positions //!< positions along gradient line. The first position MUST be 0.0 and the last MUST be 1.0.
+ U_PMF_ARGB Colors //!< colors at positions on gradient line
+*/
+} U_PMF_BLENDCOLORS;
+
+/** @brief EMF+ manual 2.2.2.5, Microsoft name: EmfPlusBlendFactors Object */
+typedef struct {
+ uint32_t Elements; //!< Members in each array
+/* variable part of object, not part of structure.
+ U_FLOAT Positions //!< positions along gradient line. The first position MUST be 0.0 and the last MUST be 1.0.
+ U_FLOAT Factors //!< blending factors, 0.0->1.0 values, inclusive
+*/
+} U_PMF_BLENDFACTORS;
+
+/** @brief EMF+ manual 2.2.2.6, Microsoft name: EmfPlusBoundaryPathData Object */
+typedef struct {
+ int32_t Size; //!< Bytes in Data
+/* variable part of object, not part of structure.
+ U_PMF_PATH Data //!< Boundary of the brush
+*/
+} U_PMF_BOUNDARYPATHDATA;
+
+/** @brief EMF+ manual 2.2.2.7, Microsoft name: EmfPlusBoundaryPointData Object */
+typedef struct {
+ int32_t Elements; //!< Members in the array
+/* variable part of object, not part of structure.
+ U_PMF_POINTF Points //!< Boundary of the brush
+*/
+} U_PMF_BOUNDARYPOINTDATA;
+
+/** @brief EMF+ manual 2.2.2.8, Microsoft name: EmfPlusCharacterRange Object */
+typedef struct {
+ int32_t First; //!< First position in range
+ int32_t Length; //!< Range length
+} U_PMF_CHARACTERRANGE;
+
+/** @brief EMF+ manual 2.2.2.9, Microsoft name: EmfPlusCompoundLineData Object
+Compound lines are pens that draw several parallel lines at once. The data here
+alternates (sub)line width (as fraction of total width and gaps (also as fraction
+of total width).
+*/
+typedef struct {
+ int32_t Elements; //!< Members in the array
+/* variable part of object, not part of structure.
+ U_FLOAT Data //!< Line or gap width (0.0 <-> 1.0, fraction of total line width )
+*/
+} U_PMF_COMPOUNDLINEDATA;
+
+/** @brief EMF+ manual 2.2.2.10, Microsoft name: EmfPlusCompressedImage Object
+Holds an EXIF, GIF, JFIF, PNG, or TIFF image.
+ For U_PMF_BITMAP BitmapData field
+
+ object has no assocated struct!
+ U_PMF_COMPRESSEDIMAGE
+*/
+
+/** @brief EMF+ manual 2.2.2.11, Microsoft name: EmfPlusCustomEndCapData Object */
+typedef struct {
+ int32_t Size; //!< Bytes in Data
+/* variable part of object, not part of structure.
+ U_PMF_CUSTOMLINECAP Data //!< Description of linecap
+*/
+} U_PMF_CUSTOMENDCAPDATA;
+
+/** @brief EMF+ manual 2.2.2.12, Microsoft name: EmfPlusCustomLineCapArrowData Object */
+typedef struct {
+ U_FLOAT Width; //!< Arrow cap width (is multiplied by line width before draw)
+ U_FLOAT Height; //!< Arrow cap length (is multiplied by line width before draw)
+ U_FLOAT MiddleInset; //!< Pixels between outer edge and filled region
+ uint32_t FillState; //!< If set, fill, otherwise, only border
+ uint32_t StartCap; //!< LineCap enumeration (type of cap)
+ uint32_t EndCap; //!< LineCap enumeration
+ uint32_t Join; //!< LineJoin enumeration
+ U_FLOAT MiterLimit; //!< Maximum (miter length / line width)
+ U_FLOAT WidthScale; //!< Scale for U_PMF_CUSTOMLINECAP object
+ U_FLOAT FillHotSpot[2]; //!< must be 0.0, 0.0
+ U_FLOAT LineHotSpot[2]; //!< must be 0.0, 0.0
+} U_PMF_CUSTOMLINECAPARROWDATA;
+
+/** @brief EMF+ manual 2.2.2.13, Microsoft name: EmfPlusCustomLineCapData Object */
+typedef struct {
+ uint32_t Flags; //!< CustomLineCapData flags
+ uint32_t Cap; //!< LineCap enumeration (type of cap)
+ U_FLOAT Inset; //!< Distance line cap start -> line end
+ uint32_t StartCap; //!< LineCap enumeration
+ uint32_t EndCap; //!< LineCap enumeration
+ uint32_t Join; //!< LineJoin enumeration
+ U_FLOAT MiterLimit; //!< Maximum (miter length / line width)
+ U_FLOAT WidthScale; //!< Scale for U_PMF_CUSTOMLINECAP object
+ U_FLOAT FillHotSpot[2]; //!< must be 0.0, 0.0
+ U_FLOAT LineHotSpot[2]; //!< must be 0.0, 0.0
+/* variable part of object, not part of structure.
+ U_PMF_CUSTOMLINECAPOPTIONALDATA Data //!< meaning determined by Flags
+*/
+} U_PMF_CUSTOMLINECAPDATA;
+
+/** U_PMF_CUSTOMLINECAPOPTIONALDATA EMF+ manual 2.2.2.14, Microsoft name: EmfPlusCustomLineCapOptionalData Object
+
+ object has no assocated struct!
+
+ U_PMF_FILLPATHO FillData; //!< path to fill (optional)
+ U_PMF_LINEPATH LineData; //!< path to stroke (optional)
+*/
+
+/** @brief EMF+ manual 2.2.2.15, Microsoft name: EmfPlusCustomStartCapData Object */
+typedef struct {
+ int32_t Size; //!< Bytes in Data
+/* variable part of object, not part of structure.
+ U_PMF_CUSTOMLINECAP Data //!< Description of linecap
+*/
+} U_PMF_CUSTOMSTARTCAPDATA;
+
+/** @brief EMF+ manual 2.2.2.16, Microsoft name: EmfPlusDashedLineData Object */
+typedef struct {
+ int32_t Elements; //!< Elements in Data
+/* variable part of object, not part of structure.
+ U_FLOAT Data; //!< Array of lengths of dashes and spaces
+*/
+} U_PMF_DASHEDLINEDATA;
+
+/** @brief EMF+ manual 2.2.2.17, Microsoft name: EmfPlusFillPath Object
+Note: U_PMF_FILLPATHOBJ is the object, U_PMF_FILLPATH is the file record
+*/
+
+typedef struct {
+ int32_t Size; //!< Bytes in Data
+/* variable part of object, not part of structure.
+ U_PMF_PATH Data; //!< Path specification
+*/
+} U_PMF_FILLPATHO;
+
+/** @brief EMF+ manual 2.2.2.18, Microsoft name: EmfPlusFocusScaleData Object
+ for U_PMF_PATHGRADIENTBRUSHOPTIONALDATA data field
+
+Used with path gradient brushes. May be used to expand the center color
+of a gradient, which would otherwise only be found at the center point.
+The expanded area is the width, height X scale factor, but in no case
+less than 1 pixel.
+
+*/
+typedef struct {
+ uint32_t Count; //!< must be 2
+ U_FLOAT ScaleX; //!< value 0.0 <-> 1.0
+ U_FLOAT ScaleY; //!< value 0.0 <-> 1.0
+} U_PMF_FOCUSSCALEDATA;
+
+/** @brief EMF+ manual 2.2.2.19, Microsoft name: EmfPlusGraphicsVersion Object
+
+Bit fields are not used in structs in this implementation, these are serialized/deserialized in
+the corresponding routines. Bitfields in the FILE (LITTLE endian here, manual uses BIG endian) are:
+ unsigned int GrfVersion : 12; GraphicsVersion enumeration
+ unsigned int Signature : 20; Must be U_GFVR_PMF (0xDBC01)
+ @{
+*/
+typedef uint32_t U_PMF_GRAPHICSVERSION; //!< EMF+ manual 2.2.2.19, Microsoft name: EmfPlusGraphicsVersion Object
+/** @} */
+
+/** @brief EMF+ manual 2.2.2.20, Microsoft name: EmfPlusHatchBrushData Object */
+typedef struct {
+ uint32_t Style; //!< HatchStyle enumeration
+ U_PMF_ARGB Foreground; //!< Hatch pattern line color
+ U_PMF_ARGB Background; //!< Hatch pattern bkground color
+} U_PMF_HATCHBRUSHDATA;
+
+/** \defgroup U_PMF_Int7 PMF 7 bit signed integer
+ @brief EMF+ manual 2.2.2.21, Microsoft name: EmfPlusInteger7 Object
+
+ bit 7 U_INT7 Clear in Integer7 objects
+ bits 0-6 7 bit signed integer value
+ @{
+*/
+#define U_TEST_INT7 0x80 //!< This bit is clear in Integer7 objects.
+#define U_SIGN_INT7 0x40 //!< Sign bit on an Integer7 object.
+#define U_MASK_INT7 0x7F //!< xMask to retrieve integer7 bits.
+/** @} */
+
+/** \defgroup U_PMF_Int15 PMF 15 bit signed integer
+ @brief EMF+ manual 2.2.2.22, Microsoft name: EmfPlusInteger15 Object
+
+ bit 15 U_INT15 Set in Integer15 objects
+ bits 0-15 15 bit signed integer value
+
+ This is the one data type that really does seem to be stored into the file in Big Endian order.
+ It has to be this way because the bit that determines if data is int7 or int15 must be in the first byte
+ the parser sees, and that byte is the high order byte.
+ @{
+*/
+#define U_TEST_INT15 0x8000 //!< This bit is set in Integer15 objects.
+#define U_SIGN_INT15 0x4000 //!< Sign bit on an Integer15 object.
+#define U_MASK_INT15 0x7FFF //!< Mask to retrieve integer15 bits.
+/** @} */
+
+/* EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier Object, defined above, before 2.2.1.9 */
+
+/** @brief EMF+ manual 2.2.2.39, Microsoft name: EmfPlusRectF Object, out of order, needed for 2.2.2.24 */
+typedef struct {
+ U_FLOAT X; //!< UL X value
+ U_FLOAT Y; //!< UL Y value
+ U_FLOAT Width; //!< Width
+ U_FLOAT Height; //!< Height
+} U_PMF_RECTF;
+
+/** @brief EMF+ manual 2.2.2.24, Microsoft name: EmfPlusLinearGradientBrushData Object
+Manual says that Reserved1 and Reserved2 must be ignored. In practice if Reserved1 is not set to StartColor
+and Reserved2 is not set to EndColor, then XP Preview will not display the gradient.
+*/
+typedef struct {
+ uint32_t Flags; //!< BrushData flags
+ int32_t WrapMode; //!< WrapMode enumeration
+ U_PMF_RECTF RectF; //!< UL=start, LR=end of gradient
+ U_PMF_ARGB StartColor; //!< Gradient start color
+ U_PMF_ARGB EndColor; //!< Gradient end color
+ uint32_t Reserved1; //!< ignore
+ uint32_t Reserved2; //!< ignore
+/* variable part of object, not part of structure.
+ U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA data; //!< presence and meaning depend on Flags field
+*/
+} U_PMF_LINEARGRADIENTBRUSHDATA;
+
+/** @brief EMF+ manual 2.2.2.47, Microsoft name: EmfPlusTransformMatrix Object, out of order, needed for 2.2.2.25 */
+typedef struct {
+ U_FLOAT m11; //!< Rotation matrix m11 element
+ U_FLOAT m12; //!< Rotation matrix m12 element
+ U_FLOAT m21; //!< Rotation matrix m21 element
+ U_FLOAT m22; //!< Rotation matrix m22 element
+ U_FLOAT dX; //!< Translation in X
+ U_FLOAT dY; //!< Translation in Y
+} U_PMF_TRANSFORMMATRIX;
+
+/** NOT DOCUMENTED. Encountered in actual EmfPlusLinearGradientBrushOptionalData Object made by PowerPoint 2003. This
+ structure is needed for the next. */
+typedef struct {
+ U_FLOAT m11; //!< Rotation matrix m11 element
+ U_FLOAT m12; //!< Rotation matrix m12 element
+ U_FLOAT m21; //!< Rotation matrix m21 element
+ U_FLOAT m22; //!< Rotation matrix m22 element
+} U_PMF_ROTMATRIX;
+
+/** @brief EMF+ manual 2.2.2.25, Microsoft name: EmfPlusLinearGradientBrushOptionalData Object
+ For U_PMF_LINEARGRADIENTBRUSHDATA data field
+*/
+/* Entire object is variable and not part of a structure! U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA
+ U_PMF_ROTMATRIX Matrix; //!< Rotation matrix, Manuals says that this should be Transformation matrix, but last two values are missing
+ (various) pattern; //!< Presence and meaning depend on Flags field, see below
+
+ Flag values
+ U_BD_PresetColors U_BD_BlendFactorsH U_BD_BlendFactorsV pattern(s) present?
+ 0 0 0 none
+ 1 0 0 U_PMF_BLENDCOLORS
+ 0 1 0 U_PMF_BLENDFACTORS
+ 0 0 1 U_PMF_BLENDFACTORS
+ 0 1 1 U_PMF_BLENDFACTORS, U_PMF_BLENDFACTORS
+*/
+
+/** @brief EMF+ manual 2.2.2.26, Microsoft name: EmfPlusLinePath Object */
+typedef struct {
+ int32_t Size; //!< Bytes in Data
+/* variable part of object, not part of structure.
+ U_PMF_PATH Data; //!< Outline path
+*/
+} U_PMF_LINEPATH;
+
+/** @brief EMF+ manual 2.2.2.27, Microsoft name: EmfPlusMetafile Object */
+typedef struct {
+ uint32_t Type; //!< MetaFileDatatype enumeration
+ uint32_t Size; //!< Bytes in Data
+/* variable part of object, not part of structure.
+ U_PMF_IMAGE Data; //!< Various types of data, like an EMF metafile, WMF metafile, another EMF+ metafile
+*/
+} U_PMF_METAFILE;
+
+/** @brief EMF+ manual 2.2.2.28, Microsoft name: EmfPlusPalette Object */
+typedef struct {
+ uint32_t Flags; //!< PaletteStyle flags
+ uint32_t Elements; //!< elements in Data
+/* variable part of object, not part of structure.
+ U_PMF_ARGB Data; //!< Palette data (array of colors)
+*/
+} U_PMF_PALETTE;
+
+/** @brief EMF+ manual 2.2.2.36, Microsoft name: EmfPlusPointF Object, out of order, needed for 2.2.2.29 */
+typedef struct {
+ U_FLOAT X; //!< UL X value
+ U_FLOAT Y; //!< UL Y value
+} U_PMF_POINTF;
+
+/** @brief EMF+ manual 2.2.2.29, Microsoft name: EmfPlusPathGradientBrushData Object */
+typedef struct {
+ uint32_t Flags; //!< BrushData flags
+ int32_t WrapMode; //!< WrapMode enumeration
+ U_PMF_ARGB CenterColor; //!< Gradient center color
+ U_PMF_POINTF Center; //!< Center coordinates
+ uint32_t Elements; //!< Number of elements in gradient (not counting center)
+/* variable part of object, not part of structure.
+ U_PMF_ARGB Gradient; //!< Color Gradient with Elements members
+ (varies) Boundary; //!< U_PMF_BOUNDARYPATHDATA object if BrushDataPath bit set in Flag, else U_PMF_BOUNDARYPOINTDATA object
+ U_PMF_GRADIENTBRUSHOPTIONALDATA data; //!< exact composition depends on Flags
+*/
+} U_PMF_PATHGRADIENTBRUSHDATA;
+
+/** EMF+ manual 2.2.2.30, Microsoft name: EmfPlusPathGradientBrushOptionalData Object
+ for U_PMF_PATHGRADIENTNBRUSHDATA data field
+*/
+/* Entire thing is variable or optional.
+typedef struct {
+ U_PMF_TRANSFORMMATRIX Matrix; //!< Optional Transformation matrix
+ U_PMF_BLENDCOLORS Pattern; //!< presence and meaning depend on Flags field
+ Flag values
+ U_BD_PresetColors U_BD_BlendFactorsH pattern?
+ 0 0 none
+ 1 0 U_PMF_BLENDCOLORS
+ 0 1 U_PMF_BLENDFACTORS
+ U_PMF_FOCUSSSCALEDATA data //!< Present if U_BD_FocusScales bit set in Flags in U_PMF_PATHGRADIENTNBRUSHDATA object
+} U_PMF_PATHGRADIENTBRUSHOPTIONALDATA;
+*/
+
+/** \defgroup U_PMF_PPTYPE PMF Path Point Types
+ @brief EMF+ manual 2.2.2.31, Microsoft name: EmfPlusPathPointType Object
+
+Bitfields in the FILE (LITTLE endian here, manual uses BIG endian) are:
+ bits 4-7 PathPointType flags
+ bits 0-3 PathPointType enumeration
+ @{
+*/
+typedef uint8_t U_PMF_PATHPOINTTYPE; //!< EMF+ manual 2.2.2.31, Microsoft name: EmfPlusPathPointType Object
+/** @} */
+
+/** \defgroup U_PMF_PPTYPERLE PMF Run Length Encoded Path Point Types
+ @brief EMF+ manual 2.2.2.32, Microsoft name: EmfPlusPathPointTypeRLE Object
+
+U_PMF_PATHPOINTTYPERLE fields specify point types in a path where the path is Run Length Encoded.
+Bit fields are not used in structs in this implementation, these are serialized/deserialized in
+the corresponding routines. Bitfields in the FILE (LITTLE endian here, manual uses BIG endian) are:
+ bit 15 Set: Bezier curve; Clear: straight line
+ bit 14 ignored
+ bits 8-13 Run count
+ bits 0-7 PathPointType enumeration
+ @{
+*/
+typedef uint16_t U_PMF_PATHPOINTTYPERLE; //!< EMF+ manual 2.2.2.32, Microsoft name: EmfPlusPathPointTypeRLE Object
+/** @} */
+
+/** @brief EMF+ manual 2.2.2.33, Microsoft name: EmfPlusPenData Object
+
+Variable part of object follows structure:
+ U_PMF_PENOPTIONALDATA data; Optional pen data, exact composition depends on Flags
+*/
+typedef struct {
+ uint32_t Flags; //!< PenData flags
+ uint32_t Unit; //!< UnitType enumeration
+ U_FLOAT Width; //!< Width in units set by Unit
+} U_PMF_PENDATA;
+
+/** @brief EMF+ manual 2.2.2.34, Microsoft name: EmfPlusPenOptionalData Object
+
+Every part of this object is variable or optional, there is no corresponding struct
+
+ Present if Flag What is it
+ U_PMF_TRANSFORMMATRIX Matrix //!< U_PD_Transform Transformation matrix
+ int32_t StartCap //!< U_PD_StartCap LineCapType enumeration
+ int32_t EndCap //!< U_PD_EndCap LineCapType enumeration
+ uint32_t Join //!< U_PD_Join LineJoinType enumeration
+ U_FLOAT MiterLimit //!< U_PD_MiterLimit Maximum (miter length / line width)
+ int32_t Style //!< U_PD_LineStyle LineStyle enumeration
+ int32_t DLCap //!< U_PD_DLCap DashedLineCapType enumeration
+ U_FLOAT DLOffset //!< U_PD_DLOffset Distance line start to first dash start
+ U_PMF_DASHEDLINEDATA DLData //!< U_PD_DLData Dash and space widths
+ int32_t PenAlignment //!< U_PD_NonCenter PenAlignment enumeration
+ U_PMF_COMPOUNDLINEDATA CLData //!< U_PD_CompoundLineData Compount Line (parallel lines drawn instead of one)
+ U_PMF_CUSTOMSTARTCAPDATA CSCapData //!< U_PD_CustomStartCap Custom start cap
+ U_PMF_CUSTOMENDCAPDATA CECapData //!< U_PD_CustomEndCap Custom end cap
+ */
+
+/** @brief EMF+ manual 2.2.2.35, Microsoft name: EmfPlusPoint Object */
+typedef struct {
+ int16_t X; //!< X coordinate
+ int16_t Y; //!< Y coordinate
+} U_PMF_POINT;
+
+/** U_PMF_POINTF EMF+ manual 2.2.2.36, Microsoft name: EmfPlusPointF Object, defined above, before 2.2.2.29 */
+
+/** U_PMF_POINTR EMF+ manual 2.2.2.37, Microsoft name: EmfPlusPointR Object
+ For U_PMF_DRAWBEZIERS data field (optionally).
+ Both parts of this object are variable, there is no corresponding struct.
+ Any combination of the two allowed types of integer is valid.
+
+ (varies) X; //!< U_PMF_INTEGER7 or U_PMF_INTEGER15
+ (varies) Y; //!< U_PMF_INTEGER7 or U_PMF_INTEGER15
+
+*/
+
+/** @brief EMF+ manual 2.2.2.38, Microsoft name: EmfPlusRect Object */
+typedef struct {
+ int16_t X; //!< UL X value
+ int16_t Y; //!< UL Y value
+ int16_t Width; //!< Width
+ int16_t Height; //!< Height
+} U_PMF_RECT;
+
+/** U_PMF_RECTF EMF+ manual 2.2.2.39, Microsoft name: EmfPlusRectF Object, defined above, before 2.2.2.24 */
+
+/** U_PMF_REGIONNODE EMF+ manual 2.2.2.40, Microsoft name: EmfPlusRegionNode Object, defined above, before 2.2.1.8 */
+
+/** U_PMF_REGIONNODECHILDNODES EMF+ manual 2.2.2.41, Microsoft name: EmfPlusRegionNodeChildNodes Object
+ For U_PMF_REGIONNODE data field (optionally).
+ Both parts of this object are variable, there is no corresponding struct.
+ U_PMF_REGIONNODE Left; //!< Left child
+ U_PMF_REGIONNODE Right; //!< Right child
+*/
+
+/** @brief EMF+ manual 2.2.2.42, Microsoft name: EmfPlusRegionNodePath Object */
+typedef struct {
+ int32_t Size; //!< Bytes in Data
+/* variable part of object, not part of structure.
+ U_PMF_PATH Data; //!< Boundary of region node
+*/
+} U_PMF_REGIONNODEPATH;
+
+/** @brief EMF+ manual 2.2.2.43, Microsoft name: EmfPlusSolidBrushData Object
+ For U_PMF_BRUSH data field (one type of brush)
+*/
+typedef struct {
+ U_PMF_ARGB Color; //!< Color of brush
+} U_PMF_SOLIDBRUSHDATA;
+
+/** U_PMF_STRINGFORMATDATA EMF+ manual 2.2.2.44, Microsoft name: EmfPlusStringFormatData Object
+ Both parts of this object are variable and optional, there is no corresponding struct
+ U_FLOAT TabStops[]; //!< Array of tabstop locations
+ U_PMF_CHARACTERRANGE CharRange[]; //!< Array of character ranges in the text
+*/
+
+/** @brief EMF+ manual 2.2.2.45, Microsoft name: EmfPlusTextureBrushData Object */
+typedef struct {
+ uint32_t Flags; //!< BrushData flags
+ int32_t WrapMode; //!< WrapMode enumeration
+/* variable part of object, not part of structure.
+ U_PMF_TEXTUREBRUSHOPTIONALDATA data; //!< Optional texture data
+*/
+} U_PMF_TEXTUREBRUSHDATA;
+
+/** U_PMF_TEXTUREBRUSHOPTIONALDATA EMF+ manual 2.2.2.46, Microsoft name: EmfPlusTextureBrushOptionalData Object
+
+Every part of this object is variable or optional, there is no corresponding struct
+
+ U_PMF_TRANSFORMMATRIX Matrix; Transformation matrix, present if Flag BrushDataTransform is set.
+ U_PMF_IMAGE Image Image that contains the texture. Present if the PMR record that includes this object still has space
+ for an U_PMF_IMAGE after all the other variable and optional data
+ within it has been accounted for.
+*/
+
+/** U_PMF_TRANSFORMMATRIX EMF+ manual 2.2.2.47, Microsoft name: EmfPlusTransformMatrix Object, defined above, before 2.2.2.25 */
+
+/** common structure present at the beginning of all(*) EMF+ records */
+typedef struct {
+ uint16_t Type; //!< Recordtype enumeration (what this record is)
+ uint16_t Flags; //!< Flags (meaning varies by record type)
+ uint32_t Size; //!< Bytes in record, including this struct (will be a multiple of 4)
+ uint32_t DataSize; //!< Bytes of data that follow, may not be a multiple of 4.
+} U_PMF_CMN_HDR;
+
+/** These are the Image Effect Objects 2.2.3.* They specify parameters for "filters" that may be applied to bitmaps. */
+
+/** @brief EMF+ manual 2.2.3.1, Microsoft name: BlurEffect Object */
+typedef struct {
+ U_FLOAT Radius; //!< Blur radius in pixels
+ uint32_t ExpandEdge; //!< 1: expand bitmap by Radius; 0: bitmap size unchanged
+} U_PMF_IE_BLUR;
+
+
+/** @brief EMF+ manual 2.2.3.2, Microsoft name: BrightnessContrastEffect Object */
+typedef struct {
+ int32_t Brightness; //!< -255 to 255, 0 is unchanged, positive increases, negative decreases
+ int32_t Contrast; //!< -100 to 100, 0 is unchanged, positive increases, negative decreases
+} U_PMF_IE_BRIGHTNESSCONTRAST;
+
+/** @brief EMF+ manual 2.2.3.3, Microsoft name: ColorBalanceEffect Object */
+typedef struct {
+ int32_t CyanRed; //!< -100 to 100, 0 is unchanged, positive increases Red & decreases Cyan, negative is opposite
+ int32_t MagentaGreen; //!< -100 to 100, 0 is unchanged, positive increases Green & decreases Magenta, negative is opposite
+ int32_t YellowBlue; //!< -100 to 100, 0 is unchanged, positive increases Blue & decreases Yellow, negative is opposite
+} U_PMF_IE_COLORBALANCE;
+
+/** @brief EMF+ manual 2.2.3.4, Microsoft name: ColorCurveEffect Object
+ Adjust Range
+ Exposure -255 to 255, 0 is unchanged
+ Density -255 to 255, 0 is unchanged
+ Contrast -100 to 100, 0 is unchanged
+ Highlight -100 to 100, 0 is unchanged
+ Shadow -100 to 100, 0 is unchanged
+ WhiteSaturation 0 to 255
+ BlackSaturation 0 to 255
+*/
+typedef struct {
+ uint32_t Adjust; //!< CurveAdjustment enumeration
+ uint32_t Channel; //!< CurveChannel enumeration
+ int32_t Intensity; //!< adjustment to apply. "Adjust" determines what field this is and range values.
+} U_PMF_IE_COLORCURVE;
+
+/** @brief EMF+ manual 2.2.3.5, Microsoft name: ColorLookupTableEffect Object */
+typedef struct {
+ uint8_t BLUT[256]; //!< Blue color lookup table
+ uint8_t GLUT[256]; //!< Green color lookup table
+ uint8_t RLUT[256]; //!< Red color lookup table
+ uint8_t ALUT[256]; //!< Alpha color lookup table
+} U_PMF_IE_COLORLOOKUPTABLE;
+
+/** @brief EMF+ manual 2.2.3.6, Microsoft name: ColorMatrixEffect Object */
+typedef struct {
+ U_FLOAT M[5][5]; //!< 5 x 5 color transformation matrix, First 4 rows are [{4 multiplier values},0.0] for R,G,B,A, last Row is [{4 color translation valuess}, 1.0]
+} U_PMF_IE_COLORMATRIX;
+
+/** @brief EMF+ manual 2.2.3.7, Microsoft name: HueSaturationLightnessEffect Object */
+typedef struct {
+ int32_t Hue; //!< -180 to 180, 0 is unchanged
+ int32_t Saturation; //!< -100 to 100, 0 is unchanged
+ int32_t Lightness; //!< -100 to 100, 0 is unchanged
+} U_PMF_IE_HUESATURATIONLIGHTNESS;
+
+/** @brief EMF+ manual 2.2.3.8, Microsoft name: LevelsEffect Object */
+typedef struct {
+ int32_t Highlight; //!< 0 to 100, 100 is unchanged
+ int32_t Midtone; //!< -100 to 100, 0 is unchanged
+ int32_t Shadow; //!< 0 to 100, 0 is unchanged
+} U_PMF_IE_LEVELS;
+
+/** @brief EMF+ manual 2.2.3.9, Microsoft name: RedEyeCorrectionEffect Object */
+typedef struct {
+ int32_t Elements; //!< Number of members in Rects
+/* variable part of object, not included in structure
+ U_RECTL Rects[]; //!< Array of rectangular area(s) to apply red eye correction
+*/
+} U_PMF_IE_REDEYECORRECTION;
+
+/** @brief EMF+ manual 2.2.3.10, Microsoft name: SharpenEffect Object */
+typedef struct {
+ U_FLOAT Radius; //!< Sharpening radius in pixels
+ int32_t Sharpen; //!< 0 to 100, 0 is unchanged
+} U_PMF_IE_SHARPEN;
+
+/** @brief EMF+ manual 2.2.3.11, Microsoft name: TintEffect Object */
+typedef struct {
+ int32_t Hue; //!< -180 to 180, [positive==clockwise] rotation in degrees starting from blue
+ int32_t Amount; //!< -100 [add black] to 100[add white], 0 is unchanged. Change in hue on specified axis
+} U_PMF_IE_TINT;
+
+/* ************************** EMF+ Records ******************************** */
+
+/** @brief EMF+ manual 2.3.1.1, Microsoft name: EmfPlusOffsetClip Record, Index 0x35 */
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header (ignore flags)
+ U_FLOAT dX; //!< horizontal translation offset to apply to clipping region
+ U_FLOAT dY; //!< vertical translation offset to apply to clipping region
+} U_PMF_OFFSETCLIP;
+
+/** @brief U_PMF_RESETCLIP EMF+ manual 2.3.1.2, Microsoft name: EmfPlusResetClip Record, Index 0x31 */
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header (ignore flags)
+} U_PMF_RESETCLIP;
+
+/** @brief EMF+ manual 2.3.1.3, Microsoft name: EmfPlusSetClipPath Record, Index 0x33
+
+flags (LITTLE endian here, manual uses BIG endian)
+ bits 8-11 CombineMode enumeration
+ bits 0-7 Index of an U_PMF_PATH object in the EMF+ object table (0-63, inclusive)
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+} U_PMF_SETCLIPPATH;
+
+/** @brief EMF+ manual 2.3.1.4, Microsoft name: EmfPlusSetClipRect Record, Index 0x32
+
+flags (LITTLE endian here, manual uses BIG endian)
+ bits 8-11 CombineMode enumeration
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ U_PMF_RECTF Rect; //!< Rectangle used with CombineMode enumeration from Header.Flags
+} U_PMF_SETCLIPRECT;
+
+/** @brief EMF+ manual 2.3.1.5, Microsoft name: EmfPlusSetClipRegion Record, Index 0x34
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bits 12-15 CombineMode enumeration
+ bits 0-7 Index of an U_PMF_REGION object in the EMF+ object table (0-63, inclusive)
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+} U_PMF_SETCLIPREGION;
+
+/** @brief EMF+ manual 2.3.2.1, Microsoft name: EmfPlusComment Record, Index 0x03
+
+ variable part of record, not included in structure
+ char data[]; //!< Private data, may be anything
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero)
+} U_PMF_COMMENT;
+
+/** @brief EMF+ manual 2.3.3.1, Microsoft name: EmfPlusEndOfFile Record, Index 0x02 */
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero)
+} U_PMF_ENDOFFILE;
+
+/** @brief EMF+ manual 2.3.3.2, Microsoft name: EmfPlusGetDC Record, Index 0x04 */
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero)
+} U_PMF_GETDC;
+
+/** @brief EMF+ manual 2.3.3.3, Microsoft name: EmfPlusHeader Record, Index 0x01
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 0 Set indicates "dual mode" EMF+
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero)
+ U_PMF_GRAPHICSVERSION Version; //!< EmfPlusGraphicsVersion object
+ uint32_t EmfPlusFlags; //!< Reference device 0 bit: set = video device, clear= printer. Ignore all other bits.
+ uint32_t LogicalDpiX; //!< Horizontal resolution reference device in DPI
+ uint32_t LogicalDpiY; //!< Vertical resolution reference device in DPI
+} U_PMF_HEADER;
+
+/** @brief EMF+ manual 2.3.4.1, Microsoft name: EmfPlusClear Record, Index 0x09 */
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero)
+ U_PMF_ARGB Color; //!< Erase everything preceding, set background ARGB color.
+} U_PMF_CLEAR;
+
+/** @brief EMF+ manual 2.3.4.2, Microsoft name: EmfPlusDrawArc Record, Index 0x12
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 9 U_PPF_C Set: Rect is U_PMF_RECT; Clear: Rect is U_PMF_RECTF
+ bits 0-7 Index of an U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ U_FLOAT Start; //!< Start angle, >=0.0, degrees clockwise from 3:00
+ U_FLOAT Sweep; //!< Sweep angle, -360<= angle <=360, degrees clockwise from Start
+/* variable part of record, not included in structure
+ U_RECT or U_RECTF Rect; //!< Bounding box for elliptical arc being drawn.
+*/
+} U_PMF_DRAWARC;
+
+/** @brief EMF+ manual 2.3.4.3, Microsoft name: EmfPlusDrawBeziers Record, Index 0x19
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 9 U_PPF_C Set: int16_t coordinates; Clear: U_FLOAT coordinates (IGNORE if bit 4 is set)
+ bit 12 U_PPF_P Set: Coordinates are relative; Clear: they are absolute
+ bits 0-7 Index of an U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+
+ bit1 bit4 Type of Data
+ 1 0 U_EMF_POINT
+ 0 0 U_EMF_POINTF
+ 0 1 U_EMF_POINTR
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ uint32_t Elements; //!< Number of members in the Points array
+/*
+ variable part of record, not included in structure
+ (varies) Points; //!< Points, for type see table above
+*/
+} U_PMF_DRAWBEZIERS;
+
+/** @brief EMF+ manual 2.3.4.4, Microsoft name: EmfPlusDrawClosedCurve Record, Index 0x17
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 9 U_PPF_C Set: int16_t coordinates; Clear: U_FLOAT coordinates (IGNORE if bit 4 is set)
+ bit 12 U_PPF_P Set: Coordinates are relative; Clear: they are absolute
+ bits 0-7 Index of an U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+
+ bit1 bit4 Type of Data
+ 1 0 U_EMF_POINT
+ 0 0 U_EMF_POINTF
+ 0 1 U_EMF_POINTR
+
+Curve is a cardinal spline.
+References sent by MS support:
+
+http://alvyray.com/Memos/CG/Pixar/spline77.pdf
+http://msdn.microsoft.com/en-us/library/4cf6we5y(v=vs.110).aspx
+
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ U_FLOAT Tension; //!< Controls splines, 0 is straight line, >0 is curved
+/*
+ variable part of record, not included in structure
+ (varies) Points; //!< Points, for type see table above
+*/
+} U_PMF_DRAWCLOSEDCURVE;
+
+/** @brief EMF+ manual 2.3.4.5, Microsoft name: EmfPlusDrawCurve Record, Index 0x18
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 9 U_PPF_C Set: int16_t coordinates; Clear: U_FLOAT coordinates (IGNORE if bit 4 is set)
+ bits 0-7 Index of an U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+
+ bit1 Type of Data
+ 1 U_EMF_POINT
+ 0 U_EMF_POINTF
+
+Curve is a cardinal spline, using doubled terminator points to generate curves for the terminal segments.
+References sent by MS support:
+
+http://alvyray.com/Memos/CG/Pixar/spline77.pdf
+http://msdn.microsoft.com/en-us/library/4cf6we5y(v=vs.110).aspx
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ U_FLOAT Tension; //!< Controls splines, 0 is straight line, >0 is curved
+ uint32_t Offset; //!< Element in Points that is the spline's starting point
+ uint32_t NSegs; //!< Number of segments
+ uint32_t Elements; //!< Number of members in Points array
+/*
+ variable part of record, not included in structure
+ (varies) Points; //!< Points, for type see table above
+*/
+} U_PMF_DRAWCURVE;
+
+/** @brief EMF+ manual 2.3.4.6, Microsoft name: EmfPlusDrawDriverString Record, Index 0x36
+
+ flags (LITTLE endian here, manual uses BIG endian)
+. bit 15 U_PPF_B Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table
+ bits 0-7 Index of an U_PMF_FONT object in the EMF+ object table (0-63, inclusive)
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ uint32_t BrushID; //!< Color or index to Brush object, depends on Flags bit0
+ uint32_t DSOFlags; //!< DriverStringOptions flags
+ uint32_t HasMatrix; //!< If 1 record contains a TransformMatrix field, if 0 it does not.
+ uint32_t Elements; //!< Number of members in Glyphs and Positions array
+/*
+ variable part of record, not included in structure
+ uint16_t Glyphs; //!< If U_DSO_CmapLookup is set in DSOFlags this is an array
+ of UTF16LE characters, otherwise, it is an array of indices into the U_PMF_FONT
+ object indexed by Object_ID in flags.
+ U_PMF_POINTF Positions; //!< Coordinates of each member of Glyphs. U_DSO_RealizedAdvance set in DSOFlags
+ Relative then positions are calculated relative to the first glyph which is stored
+ in Positions, otherwise, all glyph positions are stored in Positions.
+ U_PMF_TRANSFORMMATRIX Matrix; //!< Transformation to apply to Glyphs & Positions. Present if HasMatrix is 1
+*/
+} U_PMF_DRAWDRIVERSTRING;
+
+/** @brief EMF+ manual 2.3.4.7, Microsoft name: EmfPlusDrawEllipse Record, Index 0x0F
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 9 U_PPF_C Set: Rect is U_PMF_RECT; Clear: Rect is U_PMF_RECTF
+ bits 0-7 Index of an U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+/*
+ variable part of record, not included in structure
+ (varies) Rect; //!< Bounding rectangle, data type set by bit1 of Header.Flags
+*/
+} U_PMF_DRAWELLIPSE;
+
+/** @brief EMF+ manual 2.3.4.8, Microsoft name: EmfPlusDrawImage Record, Index 0x1A
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 9 U_PPF_C Set: DstRect is U_PMF_RECT; Clear: DstRect is U_PMF_RECTF
+ bits 0-7 Index of an U_PMF_Image object in the EMF+ object table (0-63, inclusive)
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ uint32_t ImgAttrID; //!< EmfPlusImageAttributes object
+ int32_t SrcUnit; //!< UnitType enumeration
+ U_PMF_RECTF SrcRect; //!< Region of image
+/*
+ variable part of record, not included in structure
+ (varies) DstRect; //!< Destination rectangle for image. Type controlled by bit1 of Header.Flags
+*/
+} U_PMF_DRAWIMAGE;
+
+/** @brief EMF+ manual 2.3.4.9, Microsoft name: EmfPlusDrawImagePoints Record, Index 0x1B
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 14 U_PPF_C Set: Points is U_PMF_POINT; Clear: Points is U_PMF_POINTF
+ bit 13 U_PPF_E Set: effect from previous U_PMF_SERIALIZABLEOBJECT record will be applied; Clear: no effect applied
+ bit 11 U_PPF_P Set: Points has relative coordinates; Clear: Points has absolute coordinates
+ bits 0-7 Index of an U_PMF_Image object in the EMF+ object table (0-63, inclusive)
+
+ bit1 bit4 Type of Data
+ 1 0 U_EMF_POINT
+ 0 0 U_EMF_POINTF
+ 0 1 U_EMF_POINTR
+
+ WARNING! Windows XP Preview does not show filter effects, whether or not U_PPF_E is set. They are visible if the EMF+
+ file is inserted as an image into PowerPoint.
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ uint32_t ImgAttrID; //!< EmfPlusImageAttributes object
+ int32_t SrcUnit; //!< UnitType enumeration
+ U_PMF_RECTF SrcRect; //!< Region of image
+ uint32_t Elements; //!< Number of members in Points, must be 3
+/*
+ variable part of record, not included in structure
+ (varies) Points; //!< 3 points of a parallelogram. Type from bit1 and bit4 of Header.Flags, see table above
+*/
+} U_PMF_DRAWIMAGEPOINTS;
+
+/** @brief EMF+ manual 2.3.4.10, Microsoft name: EmfPlusDrawLines Record, Index 0x0D
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 9 U_PPF_C Set: Points is U_PMF_POINT; Clear: Points is U_PMF_POINTF
+ bit 10 U_PPF_D Set: close shape by connecting last point to first; Clear: leave path open
+ bit 12 U_PPF_P Set: Points has relative coordinates; Clear: Points has absolute coordinates
+ bits 0-7 Index of an U_PMF_Image object in the EMF+ object table (0-63, inclusive)
+
+ bit1 bit4 Type of Data
+ 1 0 U_EMF_POINT
+ 0 0 U_EMF_POINTF
+ 0 1 U_EMF_POINTR
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ uint32_t Elements; //!< Number of members in Points
+/*
+ variable part of record, not included in structure
+ (varies) Points; //!< Sequence of points to connect with line segments. Type from bit1 and bit4 of Header.Flags, see table above
+*/
+} U_PMF_DRAWLINES;
+
+/** @brief EMF+ manual 2.3.4.11, Microsoft name: EmfPlusDrawPath Record, Index 0x15
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bits 0-7 Index of an U_PMF_PATH object in the EMF+ object table (0-63, inclusive)
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ uint32_t PenID; //!< U_PMF_PEN object in the EMF+ object table (0-63, inclusive)
+} U_PMF_DRAWPATH;
+
+/** @brief EMF+ manual 2.3.4.12, Microsoft name: EmfPlusDrawPie Record, Index 0x0D
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 9 U_PPF_C Set: Rect is U_PMF_RECT; Clear: Rect is U_PMF_RECTF
+ bits 0-7 Index of an U_PMF_Pen object in the EMF+ object table (0-63, inclusive)
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ U_FLOAT Start; //!< Start angle, >=0.0, degrees clockwise from 3:00
+ U_FLOAT Sweep; //!< Sweep angle, -360<= angle <=360, degrees clockwise from Start
+/*
+ variable part of record, not included in structure
+ U_RECT or U_RECTF Rect; //!< Bounding box for elliptical pie segment being drawn. Type from bit1 of Header.Flags, see above
+*/
+} U_PMF_DRAWPIE;
+
+/** @brief EMF+ manual 2.3.4.13, Microsoft name: EmfPlusDrawRects Record, Index 0x0B
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 9 U_PPF_C Set: Rect is U_PMF_RECT; Clear: Rect is U_PMF_RECTF
+ bits 0-7 Index of an U_PMF_Pen object in the EMF+ object table (0-63, inclusive)
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ uint32_t Elements; //!< Number of members in Rects
+/*
+ variable part of record, not included in structure
+ U_RECT or U_RECTF Rects; //!< Array of rectangles to draw. Type from bit1 of Header.Flags, see above
+*/
+} U_PMF_DRAWRECTS;
+
+/** @brief EMF+ manual 2.3.4.14, Microsoft name: EmfPlusDrawString Record, Index 0x1C
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 15 U_PPF_B Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table.
+ bits 0-7 Index of an U_PMF_FONT object in the EMF+ object table (0-63, inclusive)
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ uint32_t BrushID; //!< Color or index to Brush object, depends on Flags bit0
+ uint32_t FormatID; //!< U_PMF_STRINGFORMAT object in EMF+ Object Table.
+ uint32_t Length; //!< Number of characters in the string.
+ U_PMF_RECTF Rect; //!< String's bounding box.
+/*
+ variable part of record, not included in structure
+ uint16_t String; //!< Array of UFT-16LE unicode characters.
+*/
+} U_PMF_DRAWSTRING;
+
+/** @brief EMF+ manual 2.3.4.15, Microsoft name: EmfPlusFillClosedCurve Record, Index 0x16
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 15 U_PPF_B Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table.
+ bit 9 U_PPF_C Set: Points is U_PMF_POINT; Clear: Points is U_PMF_POINTF
+ bit 10 U_PPF_F Set: winding fill; Clear: alternate fill
+ bit 12 U_PPF_P Set: Points has relative coordinates; Clear: Points has absolute coordinates
+
+ bit1 bit4 Type of Data
+ 1 0 U_EMF_POINT
+ 0 0 U_EMF_POINTF
+ 0 1 U_EMF_POINTR
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ uint32_t BrushID; //!< Color or index to Brush object, depends on Header.Flags bit0
+ U_FLOAT Tension; //!< Controls splines, 0 is straight line, >0 is curved
+ uint32_t Elements; //!< Number of members in Points
+/*
+ variable part of record, not included in structure
+ (varies) Points; //!< Sequence of points to connect. Type from bit1 and bit4 of Header.Flags, see table above
+*/
+} U_PMF_FILLCLOSEDCURVE;
+
+/** @brief EMF+ manual 2.3.4.16, Microsoft name: EmfPlusFillEllipse Record, Index 0x0E
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 15 U_PPF_B Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table.
+ bit 9 U_PPF_C Set: Rect is U_PMF_RECT; Clear: Rect is U_PMF_RECTF
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ uint32_t BrushID; //!< Color or index to Brush object, depends on Header.Flags bit0
+/*
+ variable part of record, not included in structure
+ U_RECT or U_RECTF Rect; //!< Bounding box for elliptical pie segment being drawn. Type from bit1 of Header.Flags, see above
+*/
+} U_PMF_FILLELLIPSE;
+
+/** @brief EMF+ manual 2.3.4.17, Microsoft name: EmfPlusFillPath Record, Index 0x14
+Note: U_PMF_FILLPATHOBJ is the object, U_PMF_FILLPATH is the file record
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 15 U_PPF_B Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table.
+ bits 0-7 Index of an U_PMF_PATH object in the EMF+ object table (0-63, inclusive)
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ uint32_t BrushID; //!< Color or index to Brush object, depends on Header.Flags bit0
+} U_PMF_FILLPATH;
+
+/** @brief EMF+ manual 2.3.4.18, Microsoft name: EmfPlusFillPie Record, Index 0x10
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 15 U_PPF_B Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table.
+ bit 9 U_PPF_C Set: Rect is U_PMF_RECT; Clear: Rect is U_PMF_RECTF
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ uint32_t BrushID; //!< Color or index to Brush object, depends on Header.Flags bit0
+ U_FLOAT Start; //!< Start angle, >=0.0, degrees clockwise from 3:00
+ U_FLOAT Sweep; //!< Sweep angle, -360<= angle <=360, degrees clockwise from Start
+/*
+ variable part of record, not included in structure
+ U_RECT or U_RECTF Rect; //!< Bounding box for elliptical pie segment being filled. Type from bit1 of Header.Flags, see above
+*/
+} U_PMF_FILLPIE;
+
+/** @brief EMF+ manual 2.3.4.19, Microsoft name: EmfPlusFillPolygon Record, Index 0x0C
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 15 U_PPF_B Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table.
+ bit 9 U_PPF_C Set: Points is U_PMF_POINT; Clear: Points is U_PMF_POINTF
+ bit 12 U_PPF_P Set: Points has relative coordinates; Clear: Points has absolute coordinates
+
+ bit1 bit4 Type of Data
+ 1 0 U_EMF_POINT
+ 0 0 U_EMF_POINTF
+ 0 1 U_EMF_POINTR
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ uint32_t BrushID; //!< Color or index to Brush object, depends on Header.Flags bit0
+ uint32_t Elements; //!< Number of members in Points
+/*
+ variable part of record, not included in structure
+ (varies) Points; //!< Sequence of points to connect with line segments. Type from bit1 and bit4 of Header.Flags, see table above
+*/
+} U_PMF_FILLPOLYGON;
+
+/** @brief EMF+ manual 2.3.4.20, Microsoft name: EmfPlusFillRects Record, Index 0x0A
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 15 U_PPF_B Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table.
+ bit 9 U_PPF_C Set: Rect is U_PMF_RECT; Clear: Rect is U_PMF_RECTF
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ uint32_t BrushID; //!< Color or index to Brush object, depends on Header.Flags bit0
+ uint32_t Elements; //!< Number of members in Rects
+/*
+ variable part of record, not included in structure
+ U_RECT or U_RECTF Rects; //!< Array of rectangles to draw. Type from bit1 of Header.Flags, see above
+*/
+} U_PMF_FILLRECTS;
+
+/** @brief EMF+ manual 2.3.4.21, Microsoft name: EmfPlusFillRegion Record, Index 0x13
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 15 U_PPF_B Set: BrushID is an U_PFM_ARGB; Clear: is index of U_PMF_BRUSH object in EMF+ object table.
+ bits 0-7 Index of an U_PMF_REGION object in the EMF+ object table (0-63, inclusive)
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ uint32_t BrushID; //!< Color or index to Brush object, depends on Header.Flags bit0
+} U_PMF_FILLREGION;
+
+/** @brief EMF+ manual 2.3.5.1, Microsoft name: EmfPlusObject Record, Index 0x13
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 15 U_PPF_N Set: object definition continues in next record; Clear: this is the final object definition record
+ bits 8-14 Type of object being created, ObjectType enumeration
+ bits 0-7 Index of an U_PMF_REGION object in the EMF+ object table (0-63, inclusive)
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+/*
+ variable part of record, not included in structure
+ uint8_t Data; //!< Object's data. Type from bits1-7 and bits8-15 of Header.Flags, see above
+*/
+} U_PMF_OBJECT;
+
+/** @brief EMF+ manual 2.3.5.2, Microsoft name: EmfPlusSerializableObject Record, Index 0x38
+
+ WARNING! Windows XP Preview does not show filter effects, whether or not U_PPF_E is set. They are visible if the EMF+
+ file is inserted as an image into PowerPoint.
+
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero)
+ uint8_t GUID[16]; //!< ImageEffects identifier. Composed of Data1[4]-Data2[2]-Data3[2]-Data4[8]
+ //!< Data1-Data3 are stored as little endian integers. Data4 is stored big endian (like a string)
+ uint32_t Size; //!< Bytes in Data.
+/*
+ variable part of record, not included in structure
+ uint8_t Data; //!< "Serialized image effects parameter block". One of the ImageEffects objects.
+*/
+} U_PMF_SERIALIZABLEOBJECT;
+
+/** @brief EMF+ manual 2.3.6.1, Microsoft name: EmfPlusSetAntiAliasMode Record, Index 0x1E
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bits 7-1 SmoothingMode enumeration
+ bit 0 U_PPF_AA Set: anti-aliasing on; Clear: anti-aliasing off
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+} U_PMF_SETANTIALIASMODE;
+
+/** @brief EMF+ manual 2.3.6.2, Microsoft name: EmfPlusSetCompositingMode Record, Index 0x23
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bits 0-7 CompositingMode enumeration
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+} U_PMF_SETCOMPOSITINGMODE;
+
+/** @brief EMF+ manual 2.3.6.3, Microsoft name: EmfPlusSetCompositingQuality Record, Index 0x24
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bits 0-7 CompositingQuality enumeration
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+} U_PMF_SETCOMPOSITINGQUALITY;
+
+/** @brief EMF+ manual 2.3.6.4, Microsoft name: EmfPlusSetInterpolationMode Record, Index 0x21
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bits 0-7 InterpolationMode enumeration
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+} U_PMF_SETINTERPOLATIONMODE;
+
+/** @brief EMF+ manual 2.3.6.5, Microsoft name: EmfPlusSetPixelOffsetMode Record, Index 0x22
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bits 0-7 PixelOffsetMode enumeration
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+} U_PMF_SETPIXELOFFSETMODE;
+
+/** @brief EMF+ manual 2.3.6.6, Microsoft name: EmfPlusSetRenderingOrigin Record, Index 0x1D */
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero)
+ int32_t X; //!< X coordinate of rendering origin
+ int32_t Y; //!< Y coordinate of rendering origin
+} U_PMF_SETRENDERINGORIGIN;
+
+/** @brief EMF+ manual 2.3.6.7, Microsoft name: EmfPlusSetTextContrast Record, Index 0x20
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bits 12-0 1000 x Gamma correction value. Range 1000-2200 = gamma 1.0-2.2
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+} U_PMF_SETTEXTCONTRAST;
+
+/** @brief EMF+ manual 2.3.6.8, Microsoft name: EmfPlusSetTextRenderingHint Record, Index 0x1F
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bits 0-7 TextRenderingHint enumeration
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+} U_PMF_SETTEXTRENDERINGHINT;
+
+/** @brief EMF+ manual 2.3.7.1, Microsoft name: EmfPlusBeginContainer Record, Index 0x27
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bits 8-15 UnitType enumeration
+ bits 0-7 (all zero)
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ U_PMF_RECTF DstRect; //!< with SrcRect specifies a transformation
+ U_PMF_RECTF SrcRect; //!< with DstRect specifies a transformation
+ uint32_t Index; //!< Index to apply to this graphics container
+} U_PMF_BEGINCONTAINER;
+
+/** @brief EMF+ manual 2.3.7.2, Microsoft name: EmfPlusBeginContainerNoParams Record, Index 0x28 */
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero)
+ uint32_t Index; //!< Index to apply to this graphics container
+} U_PMF_BEGINCONTAINERNOPARAMS;
+
+/** @brief EMF+ manual 2.3.7.3, Microsoft name: EmfPlusEndContainer Record, Index 0x29 */
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero)
+ uint32_t Index; //!< Index of container being closed, from U_PMF_BEGINCONTAINERNOPARAMS or U_PMF_BEGINCONTAINER
+} U_PMF_ENDCONTAINER;
+
+/** @brief EMF+ manual 2.3.7.4, Microsoft name: EmfPlusRestore Record, Index 0x26 */
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero)
+ uint32_t Index; //!< Index of Graphics State being restored, from U_PMF_SAVE
+} U_PMF_RESTORE;
+
+/** @brief EMF+ manual 2.3.7.5, Microsoft name: EmfPlusSave Record, Index 0x25 */
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero)
+ uint32_t Index; //!< Index of Graphics State being saved
+} U_PMF_SAVE;
+
+/** @brief EMF+ manual 2.3.8.1, Microsoft name: EmfPlusSetTSClip Record, Index 0x3A
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 15 U_PPF_K Set: Rect is U_PMF_RECT; Clear: Rect is U_PMF_RECTF
+ bits 14-0 Number of rectangles in Rects field
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+/*
+ variable part of record, not included in structure
+ U_RECT or U_RECTF Rects; //!< Array of rectangles to draw. Type from bit0 of Header.Flags, see above
+*/
+} U_PMF_SETTSCLIP;
+
+/** @brief EMF+ manual 2.3.8.2, Microsoft name: EmfPlusSetTSGraphics Record, Index 0x39
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 1 U_PPF_VGA Set: Palette is VGA basic colors; Clear: Palette is a U_PMF_PALETTE object.
+ bit 0 U_PPF_PP Set: Palette field is present; Clear: Palette field is absent
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ uint8_t AntiAliasMode; //!< SmoothingMode enumeration
+ uint8_t TextRenderHint; //!< TextRenderingHint enumeration
+ uint8_t CompositingMode; //!< CompositingMode enumeration
+ uint8_t CompositingQuality; //!< CompositingQuality enumeration
+ int16_t RenderOriginX; //!< Origin X for halftoning and dithering
+ int16_t RenderOriginY; //!< Origin Y for halftoning and dithering
+ uint16_t TextContrast; //!< Gamma correction, range 0 to 12
+ uint8_t FilterType; //!< FilterType enumeraton
+ uint8_t PixelOffset; //!< PixelOffsetMode enumeration
+ U_PMF_TRANSFORMMATRIX WorldToDevice; //!< world to device transform
+/*
+ optional part of record, not included in structure
+ U_PMF_PALETTE Palette; //!< Present if bit15 of Header.Flags is set
+*/
+} U_PMF_SETTSGRAPHICS;
+
+/** @brief EMF+ manual 2.3.9.1, Microsoft name: EmfPlusMultiplyWorldTransform Record, Index 0x2C
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 13 U_PPF_XM Set: Post multiply; Clear: Pre multiply
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ U_PMF_TRANSFORMMATRIX Matrix; //!< Transformation matrix
+} U_PMF_MULTIPLYWORLDTRANSFORM;
+
+/** @brief EMF+ manual 2.3.9.2, Microsoft name: EmfPlusResetWorldTransform Record, Index 0x2B
+Sets transformation matrix to identity matrix.
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero)
+} U_PMF_RESETWORLDTRANSFORM;
+
+/** @brief EMF+ manual 2.3.9.3, Microsoft name: EmfPlusRotateWorldTransform Record, Index 0x2F
+ Construct transformation matrix from Angle:
+ sin(Angle) cos(Angle) 0
+ cos(Angle) -sin(Angle) 0
+ Multiply this against current world space transform, result becomes new world space transform.
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 13 U_PPF_XM Set: Post multiply; Clear: Pre multiply
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ U_FLOAT Angle; //!< Rotation angle, in degrees
+} U_PMF_ROTATEWORLDTRANSFORM;
+
+/** @brief EMF+ manual 2.3.9.4, Microsoft name: EmfPlusScaleWorldTransform Record, Index 0x2E
+ Construct transformation matrix:
+ Sx 0 0
+ 0 Sy 0
+ Multiply this against current world space transform, result becomes new world space transform.
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 13 U_PPF_XM Set: Post multiply; Clear: Pre multiply
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ U_FLOAT Sx; //!< X scale factor
+ U_FLOAT Sy; //!< Y scale factor
+} U_PMF_SCALEWORLDTRANSFORM;
+
+/** @brief EMF+ manual 2.3.9.5, Microsoft name: EmfPlusSetPageTransform Record, Index 0x30
+ flags (LITTLE endian here, manual uses BIG endian)
+ bits 0-7 UnitType enumeration
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ U_FLOAT Scale; //!< Scale factor to convert page space to device space
+} U_PMF_SETPAGETRANSFORM;
+
+
+/** @brief EMF+ manual 2.3.9.6, Microsoft name: EmfPlusSetWorldTransform Record, Index 0x2A */
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header (ignore flags and set to zero)
+ U_PMF_TRANSFORMMATRIX Matrix; //!< Transformation matrix
+} U_PMF_SETWORLDTRANSFORM;
+
+/** @brief EMF+ manual 2.3.9.7, Microsoft name: EmfPlusTranslateWorldTransform Record, Index 0x2D
+ Construct transformation matrix:
+ 1 0 Dx
+ 0 1 Dy
+ Multiply this against current world space transform, result becomes new world space transform.
+
+ flags (LITTLE endian here, manual uses BIG endian)
+ bit 13 U_PPF_XM Set: Post multiply; Clear: Pre multiply
+*/
+typedef struct {
+ U_PMF_CMN_HDR Header; //!< Common header
+ U_FLOAT Dx; //!< X offset
+ U_FLOAT Dy; //!< Y offset
+} U_PMF_TRANSLATEWORLDTRANSFORM;
+
+//! \cond
+
+/* EMF+ prototypes (helper functions) */
+int U_PMR_write(U_PSEUDO_OBJ *po, U_PSEUDO_OBJ *sum, EMFTRACK *et);
+int U_PMR_drawline(uint32_t PenID, uint32_t PathID, U_PMF_POINTF Start, U_PMF_POINTF End, int Dashed, U_PSEUDO_OBJ *sum, EMFTRACK *et);
+int U_PMR_drawstring( const char *string, int Vpos, uint32_t FontID, const U_PSEUDO_OBJ *BrushID, uint32_t FormatID,
+ U_PMF_STRINGFORMAT Sfs, const char *FontName, U_FLOAT Height, U_FontInfoParams *fip, uint32_t FontFlags,
+ U_FLOAT x, U_FLOAT y, U_PSEUDO_OBJ *sum, EMFTRACK *et);
+U_PMF_POINT *POINTF_To_POINT16_LE(U_PMF_POINTF *points, int count);
+int U_PMF_LEN_REL715(const char *contents, int Elements);
+int U_PMF_LEN_FLOATDATA(const char *contents);
+int U_PMF_LEN_BYTEDATA(const char *contents);
+int U_PMF_LEN_PENDATA(const char *PenData);
+int U_PMF_LEN_OPTPENDATA(const char *PenData, uint32_t Flags);
+char *U_PMF_CURLYGUID_set(uint8_t *GUID);
+int U_PMF_KNOWNCURLYGUID_set(const char *string);
+void U_PMF_MEMCPY_SRCSHIFT(void *Dst, const char **Src, size_t Size);
+void U_PMF_MEMCPY_DSTSHIFT(char **Dst, const void *Src, size_t Size);
+void U_PMF_REPCPY_DSTSHIFT(char **Dst, const void *Src, size_t Size, size_t Reps);
+void U_PMF_PTRSAV_SHIFT(const char **Dst, const char **Src, size_t Size);
+uint16_t U_PMF_HEADERFLAGS_get(const char *contents);
+int U_PMF_RECORD_SIZE_get(const char *contents);
+int U_PMF_CMN_HDR_get(const char **contents, U_PMF_CMN_HDR *Header);
+int U_OID_To_OT(uint32_t OID);
+int U_OID_To_BT(uint32_t OID);
+int U_OID_To_CLCDT(uint32_t OID);
+int U_OID_To_IDT(uint32_t OID);
+int U_OID_To_RNDT(uint32_t OID);
+uint8_t *U_OID_To_GUID(uint32_t OID);
+int U_OA_append(U_OBJ_ACCUM *oa, const char *data, int size, int Type, int Id);
+int U_OA_clear(U_OBJ_ACCUM *oa);
+int U_OA_release(U_OBJ_ACCUM *oa);
+U_PSEUDO_OBJ *U_PO_create(char *Data, size_t Size, size_t Use, uint32_t Type);
+U_PSEUDO_OBJ *U_PO_append(U_PSEUDO_OBJ *po, const char *Data, size_t Size);
+U_PSEUDO_OBJ *U_PO_po_append(U_PSEUDO_OBJ *po, U_PSEUDO_OBJ *src, int StripE);
+int U_PO_free(U_PSEUDO_OBJ **po);
+U_DPSEUDO_OBJ *U_PATH_create(int Elements, const U_PMF_POINTF *Points, uint8_t First, uint8_t Others);
+int U_DPO_free(U_DPSEUDO_OBJ **dpo);
+int U_DPO_clear(U_DPSEUDO_OBJ *dpo);
+int U_PATH_moveto(U_DPSEUDO_OBJ *path, U_PMF_POINTF Point, uint8_t Flags);
+int U_PATH_lineto(U_DPSEUDO_OBJ *path, U_PMF_POINTF Point, uint8_t Flags);
+int U_PATH_closepath(U_DPSEUDO_OBJ *path);
+int U_PATH_polylineto(U_DPSEUDO_OBJ *path, uint32_t Elements, const U_PMF_POINTF *Points, uint8_t Flags, uint8_t StartSeg);
+int U_PATH_polybezierto(U_DPSEUDO_OBJ *path, uint32_t Elements, const U_PMF_POINTF *Points, uint8_t Flags, uint8_t StartSeg);
+int U_PATH_polygon(U_DPSEUDO_OBJ *Path, uint32_t Elements, const U_PMF_POINTF *Points, uint8_t Flags);
+int U_PATH_arcto(U_DPSEUDO_OBJ *Path, U_FLOAT Start, U_FLOAT Sweep, U_FLOAT Rot, U_PMF_RECTF *Rect, uint8_t Flags, int StartSeg);
+U_PMF_POINTF *pointfs_transform(U_PMF_POINTF *points, int count, U_XFORM xform);
+U_PMF_RECTF *rectfs_transform(U_PMF_RECTF *rects, int count, U_XFORM xform);
+U_PMF_TRANSFORMMATRIX tm_for_gradrect(U_FLOAT Angle, U_FLOAT w, U_FLOAT h, U_FLOAT x, U_FLOAT y, U_FLOAT Periods);
+U_PSEUDO_OBJ *U_PMR_drawfill(uint32_t PathID, uint32_t PenID, const U_PSEUDO_OBJ *BrushID);
+
+
+char *U_pmr_names(unsigned int idx);
+
+/* EMF+ prototypes (objects_set) */
+
+U_PSEUDO_OBJ *U_PMF_BRUSH_set(uint32_t Version, const U_PSEUDO_OBJ *po);
+U_PSEUDO_OBJ *U_PMF_CUSTOMLINECAP_set(uint32_t Version, const U_PSEUDO_OBJ *po);
+U_PSEUDO_OBJ *U_PMF_FONT_set(uint32_t Version, U_FLOAT EmSize, uint32_t SizeUnit,
+ int32_t FSFlags, uint32_t Length, const uint16_t *Font);
+U_PSEUDO_OBJ *U_PMF_IMAGE_set(uint32_t Version, const U_PSEUDO_OBJ *po);
+U_PSEUDO_OBJ *U_PMF_IMAGEATTRIBUTES_set(uint32_t Version, uint32_t WrapMode, uint32_t ClampColor, uint32_t ObjectClamp);
+U_PSEUDO_OBJ *U_PMF_PATH_set(uint32_t Version, const U_PSEUDO_OBJ *Points, const U_PSEUDO_OBJ *Types);
+U_PSEUDO_OBJ *U_PMF_PATH_set2(uint32_t Version, const U_DPSEUDO_OBJ *Path);
+U_PSEUDO_OBJ *U_PMF_PATH_set3(uint32_t Version, const U_DPSEUDO_OBJ *Path);
+U_PSEUDO_OBJ *U_PMF_PEN_set(uint32_t Version, const U_PSEUDO_OBJ *PenData, const U_PSEUDO_OBJ *Brush);
+U_PSEUDO_OBJ *U_PMF_REGION_set(uint32_t Version, uint32_t Count, const U_PSEUDO_OBJ *Nodes);
+U_PSEUDO_OBJ *U_PMF_STRINGFORMAT_set(U_PMF_STRINGFORMAT *Sfs, const U_PSEUDO_OBJ *Sfd);
+U_PSEUDO_OBJ *U_PMF_4NUM_set(uint32_t BrushID);
+U_PSEUDO_OBJ *U_PMF_ARGB_set(uint8_t Alpha, uint8_t Red, uint8_t Green, uint8_t Blue);
+U_PSEUDO_OBJ *U_PMF_ARGBN_set(uint32_t Count, U_PMF_ARGB *Colors);
+U_PMF_ARGB U_PMF_ARGBOBJ_set(uint8_t Alpha, uint8_t Red, uint8_t Green, uint8_t Blue);
+U_PSEUDO_OBJ *U_PMF_BITMAP_set(const U_PMF_BITMAP *Bs, const U_PSEUDO_OBJ *Bm);
+U_PSEUDO_OBJ *U_PMF_BITMAPDATA_set( const U_PSEUDO_OBJ *Ps, int cbBm, const char *Bm);
+U_PSEUDO_OBJ *U_PMF_BLENDCOLORS_set(uint32_t Elements, const U_FLOAT *Positions, const U_PSEUDO_OBJ *Colors);
+U_PSEUDO_OBJ *U_PMF_BLENDCOLORS_linear_set(uint32_t Elements,U_PMF_ARGB StartColor, U_PMF_ARGB EndColor);
+U_PSEUDO_OBJ *U_PMF_BLENDFACTORS_set(uint32_t Elements, const U_FLOAT *Positions, const U_FLOAT *Factors);
+U_PSEUDO_OBJ *U_PMF_BLENDFACTORS_linear_set(uint32_t Elements, U_FLOAT StartFactor, U_FLOAT EndFactor);
+U_PSEUDO_OBJ *U_PMF_BOUNDARYPATHDATA_set(const U_PSEUDO_OBJ *Path);
+U_PSEUDO_OBJ *U_PMF_BOUNDARYPOINTDATA_set(uint32_t Elements, const U_PMF_POINTF *Points);
+U_PSEUDO_OBJ *U_PMF_CHARACTERRANGE_set(int32_t First, int32_t Length);
+U_PSEUDO_OBJ *U_PMF_COMPOUNDLINEDATA_set(int32_t Elements, const char *Widths);
+U_PSEUDO_OBJ *U_PMF_COMPRESSEDIMAGE_set(int32_t cbImage, const char *Image);
+U_PSEUDO_OBJ *U_PMF_CUSTOMENDCAPDATA_set(const U_PSEUDO_OBJ *Clc);
+U_PSEUDO_OBJ *U_PMF_CUSTOMLINECAPARROWDATA_set(U_FLOAT Width, U_FLOAT Height,
+ U_FLOAT MiddleInset, uint32_t FillState, uint32_t StartCap, uint32_t EndCap, uint32_t Join,
+ U_FLOAT MiterLimit, U_FLOAT WidthScale);
+U_PSEUDO_OBJ *U_PMF_CUSTOMLINECAPDATA_set(uint32_t Flags, uint32_t Cap,
+ U_FLOAT Inset, uint32_t StartCap, uint32_t EndCap,
+ uint32_t Join, U_FLOAT MiterLimit, U_FLOAT WidthScale,
+ const U_PSEUDO_OBJ *Clcod);
+U_PSEUDO_OBJ *U_PMF_CUSTOMLINECAPOPTIONALDATA_set(const U_PSEUDO_OBJ *Fill, const U_PSEUDO_OBJ *Line);
+U_PSEUDO_OBJ *U_PMF_CUSTOMSTARTCAPDATA_set(const U_PSEUDO_OBJ *Clc);
+U_PSEUDO_OBJ *U_PMF_DASHEDLINEDATA_set(int32_t Elements, const U_FLOAT *Lengths);
+U_PSEUDO_OBJ *U_PMF_DASHEDLINEDATA_set2(U_FLOAT Unit, int StdPat);
+U_PSEUDO_OBJ *U_PMF_DASHEDLINEDATA_set3(U_FLOAT Unit, uint32_t BitPat);
+U_PSEUDO_OBJ *U_PMF_FILLPATHOBJ_set(const U_PSEUDO_OBJ *Path);
+U_PSEUDO_OBJ *U_PMF_FOCUSSCALEDATA_set(U_FLOAT ScaleX, U_FLOAT ScaleY);
+U_PSEUDO_OBJ *U_PMF_GRAPHICSVERSION_set(int GrfVersion);
+U_PMF_GRAPHICSVERSION U_PMF_GRAPHICSVERSIONOBJ_set(int GrfVersion);
+U_PSEUDO_OBJ *U_PMF_HATCHBRUSHDATA_set(uint32_t Style, const U_PSEUDO_OBJ *Fg, const U_PSEUDO_OBJ *Bg);
+U_PSEUDO_OBJ *U_PMF_INTEGER7_set(int value);
+U_PSEUDO_OBJ *U_PMF_INTEGER15_set(int value);
+U_PMF_LANGUAGEIDENTIFIER U_PMF_LANGUAGEIDENTIFIEROBJ_set(int SubLId, int PriLId);
+U_PSEUDO_OBJ *U_PMF_LANGUAGEIDENTIFIER_set(U_PMF_LANGUAGEIDENTIFIER LId);
+U_PSEUDO_OBJ *U_PMF_LINEARGRADIENTBRUSHDATA_set(const U_PMF_LINEARGRADIENTBRUSHDATA *Lgbd, const U_PSEUDO_OBJ *Lgbod);
+U_PSEUDO_OBJ *U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_set(uint32_t *Flags, const U_PSEUDO_OBJ *Tm, const U_PSEUDO_OBJ *Bc, const U_PSEUDO_OBJ *BfH, const U_PSEUDO_OBJ *BfV);
+U_PSEUDO_OBJ *U_PMF_LINEPATH_set(const U_PSEUDO_OBJ *Path);
+U_PSEUDO_OBJ *U_PMF_METAFILE_set(void);
+U_PSEUDO_OBJ *U_PMF_PALETTE_set(uint32_t Flags, uint32_t Elements, const U_PMF_ARGB *Pd);
+U_PSEUDO_OBJ *U_PMF_PATHGRADIENTBRUSHDATA_set(uint32_t Flags, int32_t WrapMode, U_PMF_ARGB CenterColor,
+ U_PMF_POINTF Center, const U_PSEUDO_OBJ *Gradient, const U_PSEUDO_OBJ *Boundary, const U_PSEUDO_OBJ *Data);
+U_PSEUDO_OBJ *U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_set(uint32_t Flags,
+ const U_PSEUDO_OBJ *Tm, const U_PSEUDO_OBJ *Pd, const U_PSEUDO_OBJ *Fsd);
+U_PSEUDO_OBJ *U_PMF_PATHPOINTTYPE_set(uint32_t Elements, const uint8_t *Ppt);
+U_PSEUDO_OBJ *U_PMF_PATHPOINTTYPE_set2(uint32_t Elements, uint8_t Start, uint8_t Others);
+U_PSEUDO_OBJ *U_PMF_PATHPOINTTYPERLE_set(uint32_t Elements, const uint8_t *Bz, const uint8_t *RL, const uint8_t *Ppte);
+U_PSEUDO_OBJ *U_PMF_PENDATA_set(uint32_t Unit, U_FLOAT Width, const U_PSEUDO_OBJ *Pod);
+U_PSEUDO_OBJ *U_PMF_PENOPTIONALDATA_set(uint32_t Flags, U_PSEUDO_OBJ *Tm, int32_t StartCap, int32_t EndCap, uint32_t Join,
+ U_FLOAT MiterLimit, int32_t Style, int32_t DLCap, U_FLOAT DLOffset,
+ U_PSEUDO_OBJ *DLData, int32_t PenAlignment, U_PSEUDO_OBJ *CmpndLineData, U_PSEUDO_OBJ *CSCapData,
+ U_PSEUDO_OBJ *CECapData);
+U_PSEUDO_OBJ *U_PMF_POINT_set(uint32_t Elements, const U_PMF_POINT *Coords);
+U_PSEUDO_OBJ *U_PMF_POINTF_set(uint32_t Elements, const U_PMF_POINTF *Coords);
+U_PSEUDO_OBJ *U_PMF_POINTR_set(uint32_t Elements, const U_PMF_POINTF *Coords);
+U_PSEUDO_OBJ *U_PMF_RECT4_set(int16_t X, int16_t Y, int16_t Width, int16_t Height);
+U_PSEUDO_OBJ *U_PMF_RECT_set(U_PMF_RECT *Rect);
+U_PSEUDO_OBJ *U_PMF_RECTN_set(uint32_t Elements, U_PMF_RECT *Rects);
+U_PSEUDO_OBJ *U_PMF_RECTF4_set(U_FLOAT X, U_FLOAT Y, U_FLOAT Width, U_FLOAT Height);
+U_PSEUDO_OBJ *U_PMF_RECTF_set(U_PMF_RECTF *Rect);
+U_PSEUDO_OBJ *U_PMF_RECTFN_set(uint32_t Elements, U_PMF_RECTF *Rects);
+U_PSEUDO_OBJ *U_PMF_REGIONNODE_set(int32_t Type, const U_PSEUDO_OBJ *Rnd);
+U_PSEUDO_OBJ *U_PMF_REGIONNODECHILDNODES_set(const U_PSEUDO_OBJ *Left, const U_PSEUDO_OBJ *Right);
+U_PSEUDO_OBJ *U_PMF_REGIONNODEPATH_set(const U_PSEUDO_OBJ *Path);
+U_PSEUDO_OBJ *U_PMF_SOLIDBRUSHDATA_set(const U_PSEUDO_OBJ *Color);
+U_PSEUDO_OBJ *U_PMF_STRINGFORMATDATA_set(uint32_t TabStopCount, U_FLOAT *TabStops, const U_PSEUDO_OBJ *Ranges);
+U_PSEUDO_OBJ *U_PMF_TEXTUREBRUSHDATA_set(uint32_t Flags, uint32_t WrapMode, const U_PSEUDO_OBJ *Tbod);
+U_PSEUDO_OBJ *U_PMF_TEXTUREBRUSHOPTIONALDATA_set(const U_PSEUDO_OBJ *Tm, const U_PSEUDO_OBJ *Image);
+U_PSEUDO_OBJ *U_PMF_TRANSFORMMATRIX_set(U_PMF_TRANSFORMMATRIX *Tm);
+U_PSEUDO_OBJ *U_PMF_IE_BLUR_set(U_FLOAT Radius, uint32_t ExpandEdge);
+U_PSEUDO_OBJ *U_PMF_IE_BRIGHTNESSCONTRAST_set(int32_t Brightness, int32_t Contrast);
+U_PSEUDO_OBJ *U_PMF_IE_COLORBALANCE_set(int32_t CyanRed, int32_t MagentaGreen, int32_t YellowBlue);
+U_PSEUDO_OBJ *U_PMF_IE_COLORCURVE_set(uint32_t Adjust, uint32_t Channel, int32_t Intensity);
+U_PSEUDO_OBJ *U_PMF_IE_COLORLOOKUPTABLE_set(const uint8_t *BLUT, const uint8_t *GLUT, const uint8_t *RLUT, const uint8_t *ALUT);
+U_PSEUDO_OBJ *U_PMF_IE_COLORMATRIX_set(const U_FLOAT *Matrix);
+U_PSEUDO_OBJ *U_PMF_IE_HUESATURATIONLIGHTNESS_set(int32_t Hue, int32_t Saturation, int32_t Lightness);
+U_PSEUDO_OBJ *U_PMF_IE_LEVELS_set(int32_t Highlight, int32_t Midtone, int32_t Shadow);
+U_PSEUDO_OBJ *U_PMF_IE_REDEYECORRECTION_set(uint32_t Elements, const U_RECTL *rects);
+U_PSEUDO_OBJ *U_PMF_IE_SHARPEN_set(U_FLOAT Radius, int32_t Sharpen);
+U_PSEUDO_OBJ *U_PMF_IE_TINT_set(int32_t Hue, int32_t Amount);
+U_PSEUDO_OBJ *U_PMR_SERIALIZABLEOBJECT_set(const U_PSEUDO_OBJ *Siepb);
+
+/* EMF+ prototypes (records_set) */
+
+U_PSEUDO_OBJ *U_PMR_OFFSETCLIP_set(U_FLOAT dX, U_FLOAT dY);
+U_PSEUDO_OBJ *U_PMR_RESETCLIP_set(void);
+U_PSEUDO_OBJ *U_PMR_SETCLIPPATH_set(uint32_t PathID, uint32_t CMenum);
+U_PSEUDO_OBJ *U_PMR_SETCLIPRECT_set(uint32_t CMenum, const U_PSEUDO_OBJ *Rect);
+U_PSEUDO_OBJ *U_PMR_SETCLIPREGION_set(uint32_t PathID, uint32_t CMenum);
+U_PSEUDO_OBJ *U_PMR_COMMENT_set(size_t cbData, const void *Data);
+U_PSEUDO_OBJ *U_PMR_ENDOFFILE_set(void);
+U_PSEUDO_OBJ *U_PMR_GETDC_set(void);
+U_PSEUDO_OBJ *U_PMR_HEADER_set(int IsDual, int IsVideo, const U_PSEUDO_OBJ *Version,
+ uint32_t LogicalDpiX, uint32_t LogicalDpiY);
+U_PSEUDO_OBJ *U_PMR_CLEAR_set(const U_PSEUDO_OBJ *Color);
+U_PSEUDO_OBJ *U_PMR_DRAWARC_set(uint32_t PenID, U_FLOAT Start, U_FLOAT Sweep, const U_PSEUDO_OBJ *Rect);
+U_PSEUDO_OBJ *U_PMR_DRAWBEZIERS_set(uint32_t PenID, const U_PSEUDO_OBJ *Points);
+U_PSEUDO_OBJ *U_PMR_DRAWCLOSEDCURVE_set(uint32_t PenID, U_FLOAT Tension, const U_PSEUDO_OBJ *Points);
+U_PSEUDO_OBJ *U_PMR_DRAWCURVE_set(uint32_t PenID, U_FLOAT Tension,uint32_t Offset, uint32_t NSegs, const U_PSEUDO_OBJ *Points);
+U_PSEUDO_OBJ *U_PMR_DRAWDRIVERSTRING_set(uint32_t FontID, const U_PSEUDO_OBJ *BrushID,
+ uint32_t DSOFlags, uint32_t HasMatrix, uint32_t GlyphCount,
+ const uint16_t *Glyphs, const U_PSEUDO_OBJ *Points, const U_PSEUDO_OBJ *Tm);
+U_PSEUDO_OBJ *U_PMR_DRAWELLIPSE_set(uint32_t PenID, const U_PSEUDO_OBJ *Rect);
+U_PSEUDO_OBJ *U_PMR_DRAWIMAGE_set(uint32_t ImgID, int32_t ImgAttrID, int32_t SrcUnit, const U_PSEUDO_OBJ *SrcRect, const U_PSEUDO_OBJ *DstRect);
+U_PSEUDO_OBJ *U_PMR_DRAWIMAGEPOINTS_set(uint32_t ImgID, int etype, int32_t ImgAttrID, int32_t SrcUnit, const U_PSEUDO_OBJ *SrcRect, const U_PSEUDO_OBJ *Points);
+U_PSEUDO_OBJ *U_PMR_DRAWLINES_set(uint32_t PenID, int dtype, const U_PSEUDO_OBJ *Points);
+U_PSEUDO_OBJ *U_PMR_DRAWPATH_set(uint32_t PathID, uint32_t PenID);
+U_PSEUDO_OBJ *U_PMR_DRAWPIE_set(uint32_t PenID, U_FLOAT Start, U_FLOAT Sweep, const U_PSEUDO_OBJ *Rect);
+U_PSEUDO_OBJ *U_PMR_DRAWRECTS_set(uint32_t PenID, const U_PSEUDO_OBJ *Rects);
+U_PSEUDO_OBJ *U_PMR_DRAWSTRING_set(uint32_t FontID, const U_PSEUDO_OBJ *BrushID,
+ uint32_t FormatID, uint32_t Length, const U_PSEUDO_OBJ *Rect, const uint16_t *Text);
+U_PSEUDO_OBJ *U_PMR_FILLCLOSEDCURVE_set(int ftype, U_FLOAT Tension, const U_PSEUDO_OBJ * BrushID, const U_PSEUDO_OBJ *Points);
+U_PSEUDO_OBJ *U_PMR_FILLELLIPSE_set(const U_PSEUDO_OBJ * BrushID, const U_PSEUDO_OBJ *Rect);
+U_PSEUDO_OBJ *U_PMR_FILLPATH_set(uint32_t PathID, const U_PSEUDO_OBJ * BrushID);
+U_PSEUDO_OBJ *U_PMR_FILLPIE_set(U_FLOAT Start, U_FLOAT Sweep, const U_PSEUDO_OBJ *BrushID, const U_PSEUDO_OBJ *Rect);
+U_PSEUDO_OBJ *U_PMR_FILLPOLYGON_set(const U_PSEUDO_OBJ *BrushID, const U_PSEUDO_OBJ *Points);
+U_PSEUDO_OBJ *U_PMR_FILLRECTS_set(const U_PSEUDO_OBJ *BrushID, const U_PSEUDO_OBJ *Rects);
+U_PSEUDO_OBJ *U_PMR_FILLREGION_set(uint32_t RgnID, const U_PSEUDO_OBJ *BrushID);
+U_PSEUDO_OBJ *U_PMR_OBJECT_PO_set(uint32_t ObjID, U_PSEUDO_OBJ *Po);
+U_PSEUDO_OBJ *U_PMR_OBJECT_set(uint32_t ObjID, int otype, int ntype, uint32_t TSize, size_t cbData, const char *Data);
+U_PSEUDO_OBJ *U_PMR_SETANTIALIASMODE_set(int SMenum, int aatype);
+U_PSEUDO_OBJ *U_PMR_SETCOMPOSITINGMODE_set(int CMenum);
+U_PSEUDO_OBJ *U_PMR_SETCOMPOSITINGQUALITY_set(int CQenum);
+U_PSEUDO_OBJ *U_PMR_SETINTERPOLATIONMODE_set(int IMenum);
+U_PSEUDO_OBJ *U_PMR_SETPIXELOFFSETMODE_set(int POMenum);
+U_PSEUDO_OBJ *U_PMR_SETRENDERINGORIGIN_set(int32_t X, int32_t Y);
+U_PSEUDO_OBJ *U_PMR_SETTEXTCONTRAST_set(int GC);
+U_PSEUDO_OBJ *U_PMR_SETTEXTRENDERINGHINT_set(int TRHenum);
+U_PSEUDO_OBJ *U_PMR_BEGINCONTAINER_set(int UTenum, U_PSEUDO_OBJ *DstRect, U_PSEUDO_OBJ *SrcRect, uint32_t StackID);
+U_PSEUDO_OBJ *U_PMR_BEGINCONTAINERNOPARAMS_set(int StackID);
+U_PSEUDO_OBJ *U_PMR_ENDCONTAINER_set(int StackID);
+U_PSEUDO_OBJ *U_PMR_RESTORE_set(int StackID);
+U_PSEUDO_OBJ *U_PMR_SAVE_set(int StackID);
+U_PSEUDO_OBJ *U_PMR_SETTSCLIP_set(U_PSEUDO_OBJ *Rects);
+U_PSEUDO_OBJ *U_PMR_SETTSGRAPHICS_set(int vgatype, U_PMF_SETTSGRAPHICS *Tsg, U_PSEUDO_OBJ *Palette);
+U_PSEUDO_OBJ *U_PMR_MULTIPLYWORLDTRANSFORM_set(int xmtype, U_PSEUDO_OBJ *Tm);
+U_PSEUDO_OBJ *U_PMR_RESETWORLDTRANSFORM_set(void);
+U_PSEUDO_OBJ *U_PMR_ROTATEWORLDTRANSFORM_set(int xmtype, U_FLOAT Angle);
+U_PSEUDO_OBJ *U_PMR_SCALEWORLDTRANSFORM_set(int xmtype, U_FLOAT X, U_FLOAT Y);
+U_PSEUDO_OBJ *U_PMR_SETPAGETRANSFORM_set(int PUenum, U_FLOAT Sale);
+U_PSEUDO_OBJ *U_PMR_SETWORLDTRANSFORM_set(U_PSEUDO_OBJ *Tm);
+U_PSEUDO_OBJ *U_PMR_TRANSLATEWORLDTRANSFORM_set(int xmtype, U_FLOAT Dx, U_FLOAT Dy);
+U_PSEUDO_OBJ *U_PMR_STROKEFILLPATH_set(void);
+
+
+
+
+/* EMF+ prototypes (objects_get) */
+
+int U_PMF_BRUSH_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data, const char *blimit);
+int U_PMF_CUSTOMLINECAP_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data, const char *blimit);
+int U_PMF_FONT_get(const char *contents, uint32_t *Version, U_FLOAT *EmSize, uint32_t *SizeUnit, int32_t *FSFlags, uint32_t *Length, const char **Data, const char *blimit);
+int U_PMF_IMAGE_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **Data, const char *blimit);
+int U_PMF_IMAGEATTRIBUTES_get(const char *contents, uint32_t *Version, uint32_t *WrapMode, uint32_t *ClampColor, uint32_t *ObjectClamp, const char *blimit);
+int U_PMF_PATH_get(const char *contents, uint32_t *Version, uint32_t *Count, uint16_t *Flags, const char **Points, const char **Types, const char *blimit);
+int U_PMF_PEN_get(const char *contents, uint32_t *Version, uint32_t *Type, const char **PenData, const char **Brush, const char *blimit);
+int U_PMF_REGION_get(const char *contents, uint32_t *Version, uint32_t *Count, const char **Nodes, const char *blimit);
+int U_PMF_STRINGFORMAT_get(const char *contents, U_PMF_STRINGFORMAT *Sfs, const char **Data, const char *blimit);
+int U_PMF_ARGB_get(const char *contents, uint8_t *Blue, uint8_t *Green, uint8_t *Red, uint8_t *Alpha, const char *blimit);
+int U_PMF_BITMAP_get(const char *contents, U_PMF_BITMAP *Bs, const char **Data, const char *blimit);
+int U_PMF_BITMAPDATA_get(const char *contents, U_PMF_PALETTE *Ps, const char **Colors, const char **Data, const char *blimit);
+int U_PMF_BLENDCOLORS_get(const char *contents, uint32_t *Elements, U_FLOAT **Positions, const char **Colors, const char *blimit);
+int U_PMF_BLENDFACTORS_get(const char *contents, uint32_t *Elements, U_FLOAT **Positions, U_FLOAT **Factors, const char *blimit);
+int U_PMF_BOUNDARYPATHDATA_get(const char *contents, int32_t *Size, const char **Data, const char *blimit);
+int U_PMF_BOUNDARYPOINTDATA_get(const char *contents, int32_t *Elements, U_PMF_POINTF **Points, const char *blimit);
+int U_PMF_CHARACTERRANGE_get(const char *contents, int32_t *First, int32_t *Length, const char *blimit);
+int U_PMF_COMPOUNDLINEDATA_get(const char *contents, int32_t *Elements, U_FLOAT **Widths, const char *blimit);
+int U_PMF_COMPRESSEDIMAGE_get(const char *contents, const char **Data, const char *blimit);
+int U_PMF_CUSTOMENDCAPDATA_get(const char *contents, int32_t *Size, const char **Data, const char *blimit);
+int U_PMF_CUSTOMLINECAPARROWDATA_get(const char *contents, U_PMF_CUSTOMLINECAPARROWDATA *Ccad, const char *blimit);
+int U_PMF_CUSTOMLINECAPDATA_get(const char *contents, U_PMF_CUSTOMLINECAPDATA *Clcd, const char **Data, const char *blimit);
+int U_PMF_CUSTOMLINECAPOPTIONALDATA_get(const char *contents, uint32_t Flags, const char **FillData, const char **LineData, const char *blimit);
+int U_PMF_CUSTOMSTARTCAPDATA_get(const char *contents, int32_t *Size, const char **Data, const char *blimit);
+int U_PMF_DASHEDLINEDATA_get(const char *contents, int32_t *Elements, U_FLOAT **Lengths, const char *blimit);
+int U_PMF_FILLPATHOBJ_get(const char *contents, int32_t *Size, const char **Data, const char *blimit);
+int U_PMF_FOCUSSCALEDATA_get(const char *contents, uint32_t *Count, U_FLOAT *ScaleX, U_FLOAT *ScaleY, const char *blimit);
+int U_PMF_GRAPHICSVERSION_get(const char *contents, int *Signature, int *GrfVersion, const char *blimit);
+int U_PMF_HATCHBRUSHDATA_get(const char *contents, uint32_t *Style, U_PMF_ARGB *Foreground, U_PMF_ARGB *Background, const char *blimit);
+int U_PMF_INTEGER7_get(const char **contents, U_FLOAT *Value, const char *blimit);
+int U_PMF_INTEGER15_get(const char **contents, U_FLOAT *Value, const char *blimit);
+int U_PMF_LANGUAGEIDENTIFIER_get(U_PMF_LANGUAGEIDENTIFIER LId, int *SubLId, int *PriLId);
+int U_PMF_LINEARGRADIENTBRUSHDATA_get(const char *contents, U_PMF_LINEARGRADIENTBRUSHDATA *Lgbd, const char **Data, const char *blimit);
+int U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_get(const char *contents, uint32_t Flags, U_PMF_TRANSFORMMATRIX *Tm, const char **Bc, const char **BfH, const char **BfV, const char *blimit);
+int U_PMF_LINEPATH_get(const char *contents, int32_t *Size, const char **Data, const char *blimit);
+int U_PMF_METAFILE_get(const char *contents, uint32_t *Type, uint32_t *Size, const char **Data, const char *blimit);
+int U_PMF_PALETTE_get(const char *contents, uint32_t *Flags, uint32_t *Elements, const char **Data, const char *blimit);
+int U_PMF_PATHGRADIENTBRUSHDATA_get(const char *contents, U_PMF_PATHGRADIENTBRUSHDATA *Pgbd, const char **Gradient, const char **Boundary, const char **Data, const char *blimit);
+int U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_get(const char *contents, uint32_t Flags, U_PMF_TRANSFORMMATRIX *Matrix, const char **Pattern, const char **Data, const char *blimit);
+int U_PMF_PATHPOINTTYPE_get(const char *contents, int *Flags, int *Type, const char *blimit);
+int U_PMF_PATHPOINTTYPERLE_get(const char *contents, int *Bezier, int *RL, int *Ppt, const char *blimit);
+int U_PMF_PENDATA_get(const char *contents, uint32_t *Flags, uint32_t *Unit, U_FLOAT *Width, const char **Data, const char *blimit);
+int U_PMF_PENOPTIONALDATA_get(const char *contents, uint32_t Flags, U_PMF_TRANSFORMMATRIX *Matrix,
+ int32_t *StartCap, int32_t *EndCap, uint32_t *Join, U_FLOAT *MiterLimit, int32_t *Style, int32_t *DLCap, U_FLOAT *DLOffset,
+ const char **DLData, int32_t *Alignment, const char **CmpndLineData, const char **CSCapData, const char **CECapData, const char *blimit);
+int U_PMF_POINT_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, const char *blimit);
+int U_PMF_POINTF_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, const char *blimit);
+int U_PMF_POINTR_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, const char *blimit);
+int U_PMF_RECT_get(const char **contents, int16_t *X, int16_t *Y, int16_t *Width, int16_t *Height, const char *blimit);
+int U_PMF_RECTF_get(const char **contents, U_FLOAT *X, U_FLOAT *Y, U_FLOAT *Width, U_FLOAT *Height, const char *blimit);
+int U_PMF_REGIONNODE_get(const char *contents, uint32_t *Type, const char **Data, const char *blimit);
+/* There is no U_PMF_REGIONNODECHILDNODES_get, see the note in upmf.c */
+int U_PMF_REGIONNODEPATH_get(const char *contents, int32_t *Size, const char **Data, const char *blimit);
+int U_PMF_SOLIDBRUSHDATA_get(const char *contents, U_PMF_ARGB *Color, const char *blimit);
+int U_PMF_STRINGFORMATDATA_get(const char *contents, uint32_t TabStopCount, uint32_t RangeCount,
+ const U_FLOAT **TabStops, const U_PMF_CHARACTERRANGE **CharRange, const char *blimit);
+int U_PMF_TEXTUREBRUSHDATA_get(const char *contents, uint32_t *Flags, int32_t *WrapMode, const char **Data, const char *blimit);
+int U_PMF_TEXTUREBRUSHOPTIONALDATA_get(const char *contents, int HasImage, U_PMF_TRANSFORMMATRIX *Matrix, const char **Image, const char *blimit);
+int U_PMF_TRANSFORMMATRIX_get(const char *contents, U_PMF_TRANSFORMMATRIX *Matrix, const char *blimit);
+int U_PMF_IE_BLUR_get(const char *contents, U_FLOAT *Radius, uint32_t *ExpandEdge, const char *blimit);
+int U_PMF_IE_BRIGHTNESSCONTRAST_get(const char *contents, int32_t *Brightness, int32_t *Contrast, const char *blimit);
+int U_PMF_IE_COLORBALANCE_get(const char *contents, int32_t *CyanRed, int32_t *MagentaGreen, int32_t *YellowBlue, const char *blimit);
+int U_PMF_IE_COLORCURVE_get(const char *contents, uint32_t *Adjust, uint32_t *Channel, int32_t *Intensity, const char *blimit);
+int U_PMF_IE_COLORLOOKUPTABLE_get(const char *contents,
+ const uint8_t **BLUT, const uint8_t **GLUT, const uint8_t **RLUT, const uint8_t **ALUT, const char *blimit);
+int U_PMF_IE_COLORMATRIX_get(const char *contents, U_PMF_IE_COLORMATRIX *Matrix, const char *blimit);
+int U_PMF_IE_HUESATURATIONLIGHTNESS_get(const char *contents, int32_t *Hue, int32_t *Saturation, int32_t *Lightness, const char *blimit);
+int U_PMF_IE_LEVELS_get(const char *contents, int32_t *Highlight, int32_t *Midtone, int32_t *Shadow, const char *blimit);
+int U_PMF_IE_REDEYECORRECTION_get(const char *contents, int32_t *Elements, U_RECTL **Rects, const char *blimit);
+int U_PMF_IE_SHARPEN_get(const char *contents, U_FLOAT *Radius, int32_t *Sharpen, const char *blimit);
+int U_PMF_IE_TINT_get(const char *contents, int32_t *Hue, int32_t *Amount, const char *blimit);
+
+/* EMF+ prototypes (records_get) */
+
+int U_PMR_OFFSETCLIP_get(const char *contents, U_PMF_CMN_HDR *Header, U_FLOAT *dX, U_FLOAT *dY);
+int U_PMR_RESETCLIP_get(const char *contents, U_PMF_CMN_HDR *Header);
+int U_PMR_SETCLIPPATH_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PathID, int *CMenum);
+int U_PMR_SETCLIPRECT_get(const char *contents, U_PMF_CMN_HDR *Header, int *CMenum, U_PMF_RECTF *Rect);
+int U_PMR_SETCLIPREGION_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PathID, int *CMenum);
+int U_PMR_COMMENT_get(const char *contents, U_PMF_CMN_HDR *Header, const char **Data);
+int U_PMR_ENDOFFILE_get(const char *contents, U_PMF_CMN_HDR *Header);
+int U_PMR_GETDC_get(const char *contents, U_PMF_CMN_HDR *Header);
+int U_PMR_HEADER_get(const char *contents, U_PMF_CMN_HDR *Header, U_PMF_GRAPHICSVERSION *Version, int *IsDual, int *IsVideo, uint32_t *LogicalDpiX, uint32_t *LogicalDpiY);
+int U_PMR_CLEAR_get(const char *contents, U_PMF_CMN_HDR *Header, U_PMF_ARGB *Color);
+int U_PMR_DRAWARC_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PenID, int *ctype, U_FLOAT *Start, U_FLOAT *Sweep, U_PMF_RECTF *Rect);
+int U_PMR_DRAWBEZIERS_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PenID, int *ctype, int *RelAbs, uint32_t *Elements, U_PMF_POINTF **Points);
+int U_PMR_DRAWCLOSEDCURVE_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PenID, int *ctype, int *RelAbs, U_FLOAT *Tension, uint32_t *Elements, U_PMF_POINTF **Points);
+int U_PMR_DRAWCURVE_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PenID, int *ctype, U_FLOAT *Tension, uint32_t *Offset, uint32_t *NSegs, uint32_t *Elements, U_PMF_POINTF **Points);
+int U_PMR_DRAWDRIVERSTRING_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *FontID, int *btype, uint32_t *BrushID, uint32_t *DSOFlags, uint32_t *HasMatrix, uint32_t *Elements, uint16_t **Glyphs, U_PMF_POINTF **Points, U_PMF_TRANSFORMMATRIX **Matrix);
+int U_PMR_DRAWELLIPSE_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PenID, int *ctype, U_PMF_RECTF *Rect);
+int U_PMR_DRAWIMAGE_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *ImgID, int *ctype, uint32_t *ImgAttrID, int32_t *SrcUnit, U_PMF_RECTF *SrcRect, U_PMF_RECTF *DstRect);
+int U_PMR_DRAWIMAGEPOINTS_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *ImgID, int *ctype, int *etype, int *RelAbs, uint32_t *ImgAttrID, int32_t *SrcUnit, U_PMF_RECTF *SrcRect, uint32_t *Elements, U_PMF_POINTF **Points);
+int U_PMR_DRAWLINES_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PenID, int *ctype, int *dtype, int *RelAbs, uint32_t *Elements, U_PMF_POINTF **Points);
+int U_PMR_DRAWPATH_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PathID, uint32_t *PenID);
+int U_PMR_DRAWPIE_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PenID, int *ctype, U_FLOAT *Start, U_FLOAT *Sweep, U_PMF_RECTF *Rect);
+int U_PMR_DRAWRECTS_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PenID, int *ctype, uint32_t *Elements, U_PMF_RECTF **Rects);
+int U_PMR_DRAWSTRING_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *FontID, int *btype, uint32_t *BrushID, uint32_t *FormatID, uint32_t *Elements, U_PMF_RECTF *Rect, uint16_t **String);
+int U_PMR_FILLCLOSEDCURVE_get(const char *contents, U_PMF_CMN_HDR *Header, int *btype, int *ctype, int *ftype, int *RelAbs, uint32_t *BrushID, U_FLOAT *Tension, uint32_t *Elements, U_PMF_POINTF **Points);
+int U_PMR_FILLELLIPSE_get(const char *contents, U_PMF_CMN_HDR *Header, int *btype, int *ctype, uint32_t *BrushID, U_PMF_RECTF *Rect);
+int U_PMR_FILLPATH_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *PathID, int *btype, uint32_t *BrushID);
+int U_PMR_FILLPIE_get(const char *contents, U_PMF_CMN_HDR *Header, int *btype, int *ctype, uint32_t *BrushID, U_FLOAT *Start, U_FLOAT *Sweep, U_PMF_RECTF *Rect);
+int U_PMR_FILLPOLYGON_get(const char *contents, U_PMF_CMN_HDR *Header, int *btype, int *ctype, int *RelAbs, uint32_t *BrushID, uint32_t *Elements, U_PMF_POINTF **Points);
+int U_PMR_FILLRECTS_get(const char *contents, U_PMF_CMN_HDR *Header, int *btype, int *ctype, uint32_t *BrushID, uint32_t *Elements, U_PMF_RECTF **Rects);
+int U_PMR_FILLREGION_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *RgnID, int *btype, int *ctype, uint32_t *BrushID);
+int U_PMR_OBJECT_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *ObjID, int *otype, int *ntype, uint32_t *TSize, const char **Data);
+int U_PMR_SERIALIZABLEOBJECT_get(const char *contents, U_PMF_CMN_HDR *Header, uint8_t *GUID, uint32_t *Size, const char **Data);
+int U_PMR_SETANTIALIASMODE_get(const char *contents, U_PMF_CMN_HDR *Header, int *SMenum, int *aatype);
+int U_PMR_SETCOMPOSITINGMODE_get(const char *contents, U_PMF_CMN_HDR *Header, int *CMenum);
+int U_PMR_SETCOMPOSITINGQUALITY_get(const char *contents, U_PMF_CMN_HDR *Header, int *CQenum);
+int U_PMR_SETINTERPOLATIONMODE_get(const char *contents, U_PMF_CMN_HDR *Header, int *IMenum);
+int U_PMR_SETPIXELOFFSETMODE_get(const char *contents, U_PMF_CMN_HDR *Header, int *POMenum);
+int U_PMR_SETRENDERINGORIGIN_get(const char *contents, U_PMF_CMN_HDR *Header, int32_t *X, int32_t *Y);
+int U_PMR_SETTEXTCONTRAST_get(const char *contents, U_PMF_CMN_HDR *Header, int *TGC);
+int U_PMR_SETTEXTRENDERINGHINT_get(const char *contents, U_PMF_CMN_HDR *Header, int *TRHenum);
+int U_PMR_BEGINCONTAINER_get(const char *contents, U_PMF_CMN_HDR *Header, int *UTenum, U_PMF_RECTF *DstRect, U_PMF_RECTF *SrcRect, uint32_t *StackID);
+int U_PMR_BEGINCONTAINERNOPARAMS_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID);
+int U_PMR_ENDCONTAINER_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID);
+int U_PMR_RESTORE_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID);
+int U_PMR_SAVE_get(const char *contents, U_PMF_CMN_HDR *Header, uint32_t *StackID);
+int U_PMR_SETTSCLIP_get(const char *contents, U_PMF_CMN_HDR *Header, int *ctype, uint32_t *Elements, U_PMF_RECTF **Rects);
+int U_PMR_SETTSGRAPHICS_get(const char *contents, U_PMF_CMN_HDR *Header, int *vgatype, int *pptype, uint8_t *AntiAliasMode, uint8_t *TextRenderHint, uint8_t *CompositingMode, uint8_t *CompositingQuality, int16_t *RenderOriginX, int16_t *RenderOriginY, uint16_t *TextContrast, uint8_t *FilterType, uint8_t *PixelOffset, U_PMF_TRANSFORMMATRIX *WorldToDevice, const char **Data);
+int U_PMR_MULTIPLYWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header, int *xmtype, U_PMF_TRANSFORMMATRIX *Matrix);
+int U_PMR_RESETWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header);
+int U_PMR_ROTATEWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header, int *xmtype, U_FLOAT *Angle);
+int U_PMR_SCALEWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header, int *xmtype, U_FLOAT *Sx, U_FLOAT *Sy);
+int U_PMR_SETPAGETRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header, int *PUenum, U_FLOAT *Scale);
+int U_PMR_SETWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header, U_PMF_TRANSFORMMATRIX *Matrix);
+int U_PMR_TRANSLATEWORLDTRANSFORM_get(const char *contents, U_PMF_CMN_HDR *Header, int *xmtype, U_FLOAT *Dx, U_FLOAT *Dy);
+int U_PMR_STROKEFILLPATH_get(const char *contents, U_PMF_CMN_HDR *Header);
+int U_PMR_MULTIFORMATSTART_get(const char *contents, U_PMF_CMN_HDR *Header);
+int U_PMR_MULTIFORMATSECTION_get(const char *contents, U_PMF_CMN_HDR *Header);
+int U_PMR_MULTIFORMATEND_get(const char *contents, U_PMF_CMN_HDR *Header);
+//! \endcond
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UPMF_ */
diff --git a/src/3rdparty/libuemf/upmf_print.c b/src/3rdparty/libuemf/upmf_print.c
new file mode 100644
index 0000000..69fad36
--- /dev/null
+++ b/src/3rdparty/libuemf/upmf_print.c
@@ -0,0 +1,3400 @@
+/**
+ @file upmf_print.c
+
+ @brief Functions for printing EMF records
+*/
+
+/*
+File: upmf_print.c
+Version: 0.0.8
+Date: 26-JAN-2016
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2016 David Mathog and California Institute of Technology (Caltech)
+*/
+
+/* compiler options:
+
+-DNOBRUSH causes brush objects to be treated as pen objects. PowerPoint 2003 and 2010 define pen objects
+as brush objects, and this is one way to see their structure even though they are misidentified.
+This option should only be used for tiny test files, consisting of just line objects.
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h> /* for offsetof() macro */
+#include <string.h>
+#include "upmf_print.h"
+#include "uemf_print.h"
+#include "uemf_safe.h"
+
+
+//! \cond
+
+#define UNUSED(x) (void)(x) //! Please ignore - Doxygen simply insisted on including this
+
+/*
+ this function is not visible in the API. Print "data" for one of the many records that has none.
+*/
+int U_PMR_NODATAREC_print(const char *contents){
+ U_PMF_CMN_HDR Header;
+ int status = U_PMR_RESETCLIP_get(contents,&Header); /* One of many possibilities */
+ if(status)status = Header.Size;
+ return(status);
+}
+
+/*
+ this function is not visible in the API. Common routine used by many functions that draw points.
+*/
+void U_PMF_VARPOINTS_print(const char **contents, int Flags, uint32_t Elements, const char *blimit){
+ unsigned int i;
+ U_FLOAT Xpos, Ypos;
+
+ if( Flags & U_PPF_P){ printf(" + Points(Relative):"); }
+ else if(Flags & U_PPF_C){ printf(" + Points(Int16):"); }
+ else { printf(" + Points(Float):"); }
+ for(Xpos = Ypos = i = 0; i<Elements; i++){
+ printf(" %d:",i);
+ if( Flags & U_PPF_P){ (void) U_PMF_POINTR_print(contents, &Xpos, &Ypos, blimit); }
+ else if(Flags & U_PPF_C){ (void) U_PMF_POINT_print(contents, blimit); }
+ else { (void) U_PMF_POINTF_print(contents, blimit); }
+ }
+#if 0
+int residual;
+uintptr_t holdptr = (uintptr_t) *contents;
+ residual = holdptr & 0x3;
+ if(residual){ *contents += (4-residual); }
+printf("DEBUG U_PMF_VARPOINTS_print residual:%d *contents:%p\n",residual,*contents);fflush(stdout);
+#endif
+ printf("\n");
+}
+
+/*
+ this function is not visible in the API. Common routine used by many functions that draw points.
+*/
+void U_PMF_VARPOINTF_S_print(U_PMF_POINTF *Points, uint32_t Elements){
+ unsigned int i;
+ printf(" + Points:");
+ for(i=0; i<Elements; i++, Points++){
+ printf(" %d:",i);
+ (void) U_PMF_POINTF_S_print(Points);
+ }
+ printf("\n");
+}
+
+/*
+ this function is not visible in the API. Common routine used by many functions that draw rectangles.
+*/
+int U_PMF_VARRECTF_S_print(U_PMF_RECTF *Rects, uint32_t Elements){
+ if(!Elements)return(0);
+ if(Elements == 1){ printf(" Rect(Float):"); }
+ else { printf(" Rects(Float):"); }
+ while(1){
+ U_PMF_RECTF_S_print(Rects++);
+ Elements--;
+ if(!Elements)break;
+ printf(" ");
+ }
+ return(1);
+}
+
+/*
+ this function is not visible in the API. Common routine used by many functions.
+*/
+int U_PMF_VARBRUSHID_print(int btype, uint32_t BrushID){
+ if(btype){
+ printf(" Color:");
+ (void) U_PMF_ARGB_print((char *)&(BrushID));
+ }
+ else {
+ printf(" BrushID:%u",BrushID);
+ }
+ return(1);
+}
+//! \endcond
+
+/**
+ \brief Print any EMF+ record
+ \returns record length for a normal record, 0 for EMREOF or , -1 for a bad record
+ \param contents pointer to a buffer holding this EMF+ record
+ \param blimit one byte after this EMF+ record
+ \param recnum EMF number of this record in contents
+ \param off Offset from the beginning of the EMF+ file to the start of this record.
+*/
+int U_pmf_onerec_print(const char *contents, const char *blimit, int recnum, int off){
+ int status;
+ int rstatus;
+ static U_OBJ_ACCUM ObjCont={NULL,0,0,0,0}; /* for keeping track of object continuation. These may
+ be split across multiple EMF Comment records */
+ U_PMF_CMN_HDR Header;
+ const char *contemp = contents;
+
+ /* Check that COMMON header data in record can be touched without an access violation. If it cannot be
+ this is either a corrupt EMF or one engineered to cause a buffer overflow. Pointer math
+ could wrap so check both sides of the range.
+ */
+ if(IS_MEM_UNSAFE(contents, sizeof(U_PMF_CMN_HDR), blimit))return(-1);
+ if(!U_PMF_CMN_HDR_get(&contemp, &Header)){return(-1);}
+
+ int type = Header.Type & U_PMR_TYPE_MASK; /* strip the U_PMR_RECFLAG bit, leaving the indexable part */
+ if(type < U_PMR_MIN || type > U_PMR_MAX)return(-1); /* unknown EMF+ record type */
+ status = U_PMF_CMN_HDR_print(contents, Header, recnum, off); /* EMF+ part */
+
+ /* Buggy EMF+ can set the continue bit and then do something else. In that case, force out the pending
+ Object. Side effect - clears the pending object. */
+ if((type != U_PMR_OBJECT) && (ObjCont.used > 0)){
+ U_PMR_OBJECT_print(contents, blimit, &ObjCont, 1);
+ }
+
+ /* Check that the record size is OK, abort if not. */
+ if(Header.Size < sizeof(U_PMF_CMN_HDR) ||
+ IS_MEM_UNSAFE(contents, Header.Size, blimit))return(-1);
+
+ switch(type){
+ case (U_PMR_HEADER): rstatus = U_PMR_HEADER_print(contents); break;
+ case (U_PMR_ENDOFFILE): rstatus = U_PMR_ENDOFFILE_print(contents);
+ U_OA_release(&ObjCont); break;
+ case (U_PMR_COMMENT): rstatus = U_PMR_COMMENT_print(contents); break;
+ case (U_PMR_GETDC): rstatus = U_PMR_GETDC_print(contents); break;
+ case (U_PMR_MULTIFORMATSTART): rstatus = U_PMR_MULTIFORMATSTART_print(contents); break;
+ case (U_PMR_MULTIFORMATSECTION): rstatus = U_PMR_MULTIFORMATSECTION_print(contents); break;
+ case (U_PMR_MULTIFORMATEND): rstatus = U_PMR_MULTIFORMATEND_print(contents); break;
+ case (U_PMR_OBJECT): rstatus = U_PMR_OBJECT_print(contents,blimit,&ObjCont,0); break;
+ case (U_PMR_CLEAR): rstatus = U_PMR_CLEAR_print(contents); break;
+ case (U_PMR_FILLRECTS): rstatus = U_PMR_FILLRECTS_print(contents); break;
+ case (U_PMR_DRAWRECTS): rstatus = U_PMR_DRAWRECTS_print(contents); break;
+ case (U_PMR_FILLPOLYGON): rstatus = U_PMR_FILLPOLYGON_print(contents); break;
+ case (U_PMR_DRAWLINES): rstatus = U_PMR_DRAWLINES_print(contents); break;
+ case (U_PMR_FILLELLIPSE): rstatus = U_PMR_FILLELLIPSE_print(contents); break;
+ case (U_PMR_DRAWELLIPSE): rstatus = U_PMR_DRAWELLIPSE_print(contents); break;
+ case (U_PMR_FILLPIE): rstatus = U_PMR_FILLPIE_print(contents); break;
+ case (U_PMR_DRAWPIE): rstatus = U_PMR_DRAWPIE_print(contents); break;
+ case (U_PMR_DRAWARC): rstatus = U_PMR_DRAWARC_print(contents); break;
+ case (U_PMR_FILLREGION): rstatus = U_PMR_FILLREGION_print(contents); break;
+ case (U_PMR_FILLPATH): rstatus = U_PMR_FILLPATH_print(contents); break;
+ case (U_PMR_DRAWPATH): rstatus = U_PMR_DRAWPATH_print(contents); break;
+ case (U_PMR_FILLCLOSEDCURVE): rstatus = U_PMR_FILLCLOSEDCURVE_print(contents); break;
+ case (U_PMR_DRAWCLOSEDCURVE): rstatus = U_PMR_DRAWCLOSEDCURVE_print(contents); break;
+ case (U_PMR_DRAWCURVE): rstatus = U_PMR_DRAWCURVE_print(contents); break;
+ case (U_PMR_DRAWBEZIERS): rstatus = U_PMR_DRAWBEZIERS_print(contents); break;
+ case (U_PMR_DRAWIMAGE): rstatus = U_PMR_DRAWIMAGE_print(contents); break;
+ case (U_PMR_DRAWIMAGEPOINTS): rstatus = U_PMR_DRAWIMAGEPOINTS_print(contents); break;
+ case (U_PMR_DRAWSTRING): rstatus = U_PMR_DRAWSTRING_print(contents); break;
+ case (U_PMR_SETRENDERINGORIGIN): rstatus = U_PMR_SETRENDERINGORIGIN_print(contents); break;
+ case (U_PMR_SETANTIALIASMODE): rstatus = U_PMR_SETANTIALIASMODE_print(contents); break;
+ case (U_PMR_SETTEXTRENDERINGHINT): rstatus = U_PMR_SETTEXTRENDERINGHINT_print(contents); break;
+ case (U_PMR_SETTEXTCONTRAST): rstatus = U_PMR_SETTEXTCONTRAST_print(contents); break;
+ case (U_PMR_SETINTERPOLATIONMODE): rstatus = U_PMR_SETINTERPOLATIONMODE_print(contents); break;
+ case (U_PMR_SETPIXELOFFSETMODE): rstatus = U_PMR_SETPIXELOFFSETMODE_print(contents); break;
+ case (U_PMR_SETCOMPOSITINGMODE): rstatus = U_PMR_SETCOMPOSITINGMODE_print(contents); break;
+ case (U_PMR_SETCOMPOSITINGQUALITY): rstatus = U_PMR_SETCOMPOSITINGQUALITY_print(contents); break;
+ case (U_PMR_SAVE): rstatus = U_PMR_SAVE_print(contents); break;
+ case (U_PMR_RESTORE): rstatus = U_PMR_RESTORE_print(contents); break;
+ case (U_PMR_BEGINCONTAINER): rstatus = U_PMR_BEGINCONTAINER_print(contents); break;
+ case (U_PMR_BEGINCONTAINERNOPARAMS): rstatus = U_PMR_BEGINCONTAINERNOPARAMS_print(contents); break;
+ case (U_PMR_ENDCONTAINER): rstatus = U_PMR_ENDCONTAINER_print(contents); break;
+ case (U_PMR_SETWORLDTRANSFORM): rstatus = U_PMR_SETWORLDTRANSFORM_print(contents); break;
+ case (U_PMR_RESETWORLDTRANSFORM): rstatus = U_PMR_RESETWORLDTRANSFORM_print(contents); break;
+ case (U_PMR_MULTIPLYWORLDTRANSFORM): rstatus = U_PMR_MULTIPLYWORLDTRANSFORM_print(contents); break;
+ case (U_PMR_TRANSLATEWORLDTRANSFORM): rstatus = U_PMR_TRANSLATEWORLDTRANSFORM_print(contents); break;
+ case (U_PMR_SCALEWORLDTRANSFORM): rstatus = U_PMR_SCALEWORLDTRANSFORM_print(contents); break;
+ case (U_PMR_ROTATEWORLDTRANSFORM): rstatus = U_PMR_ROTATEWORLDTRANSFORM_print(contents); break;
+ case (U_PMR_SETPAGETRANSFORM): rstatus = U_PMR_SETPAGETRANSFORM_print(contents); break;
+ case (U_PMR_RESETCLIP): rstatus = U_PMR_RESETCLIP_print(contents); break;
+ case (U_PMR_SETCLIPRECT): rstatus = U_PMR_SETCLIPRECT_print(contents); break;
+ case (U_PMR_SETCLIPPATH): rstatus = U_PMR_SETCLIPPATH_print(contents); break;
+ case (U_PMR_SETCLIPREGION): rstatus = U_PMR_SETCLIPREGION_print(contents); break;
+ case (U_PMR_OFFSETCLIP): rstatus = U_PMR_OFFSETCLIP_print(contents); break;
+ case (U_PMR_DRAWDRIVERSTRING): rstatus = U_PMR_DRAWDRIVERSTRING_print(contents); break;
+ case (U_PMR_STROKEFILLPATH): rstatus = U_PMR_STROKEFILLPATH_print(contents); break;
+ case (U_PMR_SERIALIZABLEOBJECT): rstatus = U_PMR_SERIALIZABLEOBJECT_print(contents); break;
+ case (U_PMR_SETTSGRAPHICS): rstatus = U_PMR_SETTSGRAPHICS_print(contents); break;
+ case (U_PMR_SETTSCLIP): rstatus = U_PMR_SETTSCLIP_print(contents); break;
+ }
+ if(!rstatus)status=-1;
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_CMN_HDR object
+ \return number of bytes in record, 0 on error
+ \param contents pointer to a buffer holding this EMF+ record
+ \param Header Header of the record
+ \param precnum EMF+ record number in file.
+ \param off Offset in file to the start of this EMF+ record.
+ common structure present at the beginning of all(*) EMF+ records
+*/
+int U_PMF_CMN_HDR_print(const char *contents, U_PMF_CMN_HDR Header, int precnum, int off){
+ printf(" %-29srec+:%5d type:%X offset:%8d rsize:%8u dsize:%8u flags:%4.4X crc32:%8.8X\n",
+ U_pmr_names(Header.Type &U_PMR_TYPE_MASK),precnum, Header.Type,off,Header.Size,Header.DataSize,Header.Flags,
+ lu_crc32(contents,Header.Size));
+ return((int) Header.Size);
+}
+
+/**
+ \brief Print data from a an array of uint8_t values
+ \return 1
+ \param Start Text to lead array data
+ \param Array uint8_t array of data passed as char *
+ \param Elements Number of elements in Array
+ \param End Text to follow array data
+*/
+int U_PMF_UINT8_ARRAY_print(const char *Start, const uint8_t *Array, int Elements, char *End){
+ if(Start)printf("%s",Start);
+ for(; Elements--; Array++){ printf(" %u", *Array); }
+ if(End)printf("%s",End);
+ return(1);
+}
+
+/**
+ \brief Print value of an BrushType Enumeration
+ \returns record 1 on sucess, 0 on error
+ \param otype Value to print.
+ EMF+ manual 2.1.1.3, Microsoft name: BrushType Enumeration
+*/
+int U_PMF_BRUSHTYPEENUMERATION_print(int otype){
+ int status=1;
+ switch(otype){
+ case U_BT_SolidColor: printf("SolidColor"); break;
+ case U_BT_HatchFill: printf("HatchFill"); break;
+ case U_BT_TextureFill: printf("TextureFill"); break;
+ case U_BT_PathGradient: printf("PathGradient"); break;
+ case U_BT_LinearGradient: printf("LinearGradient"); break;
+ default: status=0; printf("INVALID(%d)",otype); break;
+ }
+ return(status);
+}
+
+/**
+ \brief Print value of an BrushType Enumeration
+ \returns record 1 on sucess, 0 on error
+ \param otype Value to print.
+ EMF+ manual 2.1.1.4, Microsoft name: BrushType Enumeration
+*/
+int U_PMF_COMBINEMODEENUMERATION_print(int otype){
+ int status=1;
+ switch(otype){
+ case U_CM_Replace: printf("Replace" ); break;
+ case U_CM_Intersect: printf("Intersect" ); break;
+ case U_CM_Union: printf("Union" ); break;
+ case U_CM_XOR: printf("XOR" ); break;
+ case U_CM_Exclude: printf("Exclude" ); break;
+ case U_CM_Complement: printf("Complement"); break;
+ default: status=0; printf("INVALID(%d)",otype); break;
+ }
+ return(status);
+}
+
+/**
+ \brief Print value of a HatchStyle Enumeration
+ \returns record 1 on sucess, 0 on error
+ \param hstype Value to print.
+ EMF+ manual 2.1.1.13, Microsoft name: HatchStyle Enumeration
+*/
+int U_PMF_HATCHSTYLEENUMERATION_print(int hstype){
+ int status=1;
+ switch(hstype){
+ case U_HSP_Horizontal: printf("Horizontal"); break;
+ case U_HSP_Vertical: printf("Vertical"); break;
+ case U_HSP_ForwardDiagonal: printf("ForwardDiagonal"); break;
+ case U_HSP_BackwardDiagonal: printf("BackwardDiagonal"); break;
+ case U_HSP_LargeGrid: printf("LargeGrid"); break;
+ case U_HSP_DiagonalCross: printf("DiagonalCross"); break;
+ case U_HSP_05Percent: printf("05Percent"); break;
+ case U_HSP_10Percent: printf("10Percent"); break;
+ case U_HSP_20Percent: printf("20Percent"); break;
+ case U_HSP_25Percent: printf("25Percent"); break;
+ case U_HSP_30Percent: printf("30Percent"); break;
+ case U_HSP_40Percent: printf("40Percent"); break;
+ case U_HSP_50Percent: printf("50Percent"); break;
+ case U_HSP_60Percent: printf("60Percent"); break;
+ case U_HSP_70Percent: printf("70Percent"); break;
+ case U_HSP_75Percent: printf("75Percent"); break;
+ case U_HSP_80Percent: printf("80Percent"); break;
+ case U_HSP_90Percent: printf("90Percent"); break;
+ case U_HSP_LightDownwardDiagonal: printf("LightDownwardDiagonal"); break;
+ case U_HSP_LightUpwardDiagonal: printf("LightUpwardDiagonal"); break;
+ case U_HSP_DarkDownwardDiagonal: printf("DarkDownwardDiagonal"); break;
+ case U_HSP_DarkUpwardDiagonal: printf("DarkUpwardDiagonal"); break;
+ case U_HSP_WideDownwardDiagonal: printf("WideDownwardDiagonal"); break;
+ case U_HSP_WideUpwardDiagonal: printf("WideUpwardDiagonal"); break;
+ case U_HSP_LightVertical: printf("LightVertical"); break;
+ case U_HSP_LightHorizontal: printf("LightHorizontal"); break;
+ case U_HSP_NarrowVertical: printf("NarrowVertical"); break;
+ case U_HSP_NarrowHorizontal: printf("NarrowHorizontal"); break;
+ case U_HSP_DarkVertical: printf("DarkVertical"); break;
+ case U_HSP_DarkHorizontal: printf("DarkHorizontal"); break;
+ case U_HSP_DashedDownwardDiagonal: printf("DashedDownwardDiagonal"); break;
+ case U_HSP_DashedUpwardDiagonal: printf("DashedUpwardDiagonal"); break;
+ case U_HSP_DashedHorizontal: printf("DashedHorizontal"); break;
+ case U_HSP_DashedVertical: printf("DashedVertical"); break;
+ case U_HSP_SmallConfetti: printf("SmallConfetti"); break;
+ case U_HSP_LargeConfetti: printf("LargeConfetti"); break;
+ case U_HSP_ZigZag: printf("ZigZag"); break;
+ case U_HSP_Wave: printf("Wave"); break;
+ case U_HSP_DiagonalBrick: printf("DiagonalBrick"); break;
+ case U_HSP_HorizontalBrick: printf("HorizontalBrick"); break;
+ case U_HSP_Weave: printf("Weave"); break;
+ case U_HSP_Plaid: printf("Plaid"); break;
+ case U_HSP_Divot: printf("Divot"); break;
+ case U_HSP_DottedGrid: printf("DottedGrid"); break;
+ case U_HSP_DottedDiamond: printf("DottedDiamond"); break;
+ case U_HSP_Shingle: printf("Shingle"); break;
+ case U_HSP_Trellis: printf("Trellis"); break;
+ case U_HSP_Sphere: printf("Sphere"); break;
+ case U_HSP_SmallGrid: printf("SmallGrid"); break;
+ case U_HSP_SmallCheckerBoard: printf("SmallCheckerBoard"); break;
+ case U_HSP_LargeCheckerBoard: printf("LargeCheckerBoard"); break;
+ case U_HSP_OutlinedDiamond: printf("OutlinedDiamond"); break;
+ case U_HSP_SolidDiamond: printf("SolidDiamond"); break;
+ default: status=0; printf("INVALID(%d)",hstype); break;
+ }
+ return(status);
+}
+
+/**
+ \brief Print value of an ObjectType Enumeration
+ \returns record 1 on sucess, 0 on error
+ \param otype Value to print.
+ EMF+ manual 2.1.1.22, Microsoft name: ObjectType Enumeration
+*/
+int U_PMF_OBJECTTYPEENUMERATION_print(int otype){
+ int status=1;
+ switch(otype){
+ case U_OT_Invalid: printf("Invalid"); break;
+ case U_OT_Brush: printf("Brush"); break;
+ case U_OT_Pen: printf("Pen"); break;
+ case U_OT_Path: printf("Path"); break;
+ case U_OT_Region: printf("Region"); break;
+ case U_OT_Image: printf("Image"); break;
+ case U_OT_Font: printf("Font"); break;
+ case U_OT_StringFormat: printf("StringFormat"); break;
+ case U_OT_ImageAttributes: printf("ImageAttributes"); break;
+ case U_OT_CustomLineCap: printf("CustomLineCap"); break;
+ default:
+ status=0; printf("INVALID(%d)",otype); break;
+ }
+ return(status);
+}
+
+/**
+ \brief Print value of a U_PMF_PATHPOINTTYPE_ENUM object
+ \return 1
+ \param Type Value to print
+ EMF+ manual 2.1.1.23, Microsoft name: PathPointType Enumeration
+*/
+int U_PMF_PATHPOINTTYPE_ENUM_print(int Type){
+ switch(Type & U_PPT_MASK){
+ case U_PPT_Start : printf("Start"); break;
+ case U_PPT_Line : printf("Line"); break;
+ case U_PPT_Bezier: printf("Bezier"); break;
+ default: printf("INVALID(%d)",Type); break;
+ }
+ return(1);
+}
+
+/**
+ \brief Print data from a PixelFormat Enumeration value
+ \return 1 always
+ \param pfe A PixelFormat Enumeration value
+ EMF+ manual 2.1.1.25, Microsoft name: PixelFormat Enumeration (U_PF_*)
+*/
+int U_PMF_PX_FMT_ENUM_print(int pfe){
+ uint8_t idx;
+ printf(" + PxFmtEnum: ");
+ printf(" 32Bit:%c", (pfe & 1<< 9 ? 'Y' : 'N'));
+ printf(" 16Bit:%c", (pfe & 1<<10 ? 'Y' : 'N'));
+ printf(" PreAlpha:%c", (pfe & 1<<11 ? 'Y' : 'N'));
+ printf(" Alpha:%c", (pfe & 1<<12 ? 'Y' : 'N'));
+ printf(" GDI:%c", (pfe & 1<<13 ? 'Y' : 'N'));
+ printf(" LUT:%c", (pfe & 1<<14 ? 'Y' : 'N'));
+ printf(" BitsPerPx:%u", (pfe >> 16) & 0xFF);
+ idx = pfe >> 24;
+ printf(" Type:%u(",idx);
+ switch(idx){
+ case 0: printf("undefined"); break;
+ case 1: printf("monochrome with LUT"); break;
+ case 2: printf("4 bit with LUT"); break;
+ case 3: printf("8 bit with LUT"); break;
+ case 4: printf("16 bits grey values"); break;
+ case 5: printf("16 bit RGB values (5,5,5,(1 ignored))"); break;
+ case 6: printf("16 bit RGB values (5,6,5)"); break;
+ case 7: printf("16 bit ARGB values (1 alpha, 5,5,5 colors)"); break;
+ case 8: printf("24 bit RGB values (8,8.8)"); break;
+ case 9: printf("32 bit RGB value (8,8,8,(8 ignored))"); break;
+ case 10: printf("32 bit ARGB values (8 alpha,8,8,8)"); break;
+ case 11: printf("32 bit PARGB values (8,8,8,8, but RGB already multiplied by A)"); break;
+ case 12: printf("48 bit RGB (16,16,16)"); break;
+ case 13: printf("64 bit ARGB (16 alpha, 16,16,16)"); break;
+ case 14: printf("64 bit PARGB (16,16,16,16, but RGB already multiplied by A)"); break;
+ default: printf("INVALID(%d)",idx); break;
+ }
+ printf(")");
+ return(1);
+}
+
+/**
+ \brief Print as text a RegionNodeDataType Enumeration
+ \return 1
+ \param Type RegionNodeDataType Enumeration
+ EMF+ manual 2.1.1.27, Microsoft name: RegionNodeDataType Enumeration (U_RNDT_*)
+*/
+int U_PMF_NODETYPE_print(int Type){
+ if( Type == U_RNDT_And ){ printf("And" ); }
+ else if(Type == U_RNDT_Or ){ printf("Or" ); }
+ else if(Type == U_RNDT_Xor ){ printf("Xor" ); }
+ else if(Type == U_RNDT_Exclude ){ printf("Exclude" ); }
+ else if(Type == U_RNDT_Complement){ printf("Complement"); }
+ else if(Type == U_RNDT_Rect ){ printf("Rect" ); }
+ else if(Type == U_RNDT_Path ){ printf("Path" ); }
+ else if(Type == U_RNDT_Empty ){ printf("Empty" ); }
+ else if(Type == U_RNDT_Infinite ){ printf("Infinite" ); }
+ else { printf("Undefined" ); return(0); }
+ return(1);
+}
+
+/**
+ \brief Print data from a U_PMF_BRUSH object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.1.1, Microsoft name: EmfPlusBrush Object
+*/
+int U_PMF_BRUSH_print(const char *contents, const char *blimit){
+ uint32_t Version, Type;
+ const char *Data;
+ int status = U_PMF_BRUSH_get(contents, &Version, &Type, &Data, blimit);
+ if(status){
+ printf(" + Brush:");
+ (void) U_PMF_GRAPHICSVERSION_memsafe_print((char *)&Version);;
+ printf(" Type:%X(",Type);
+ (void) U_PMF_BRUSHTYPEENUMERATION_print(Type);
+ printf(")");
+ switch(Type){
+ case U_BT_SolidColor:
+ status = U_PMF_ARGB_print(Data);
+ break;
+ case U_BT_HatchFill:
+ printf("\n");
+ status = U_PMF_HATCHBRUSHDATA_print(Data, blimit);
+ break;
+ case U_BT_TextureFill:
+ printf("\n");
+ status = U_PMF_TEXTUREBRUSHDATA_print(Data, blimit);
+ break;
+ case U_BT_PathGradient:
+ printf("\n");
+ status = U_PMF_PATHGRADIENTBRUSHDATA_print(Data, blimit);
+ break;
+ case U_BT_LinearGradient:
+ printf("\n");
+ status = U_PMF_LINEARGRADIENTBRUSHDATA_print(Data, blimit);
+ break;
+ default:
+ status = 0;
+ }
+ printf("\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_CUSTOMLINECAP object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param Which A string which is either "Start" or "End".
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.1.2, Microsoft name: EmfPlusCustomLineCap Object
+*/
+int U_PMF_CUSTOMLINECAP_print(const char *contents, const char *Which, const char *blimit){
+ uint32_t Version, Type;
+ const char *Data;
+ int status = U_PMF_CUSTOMLINECAP_get(contents, &Version, &Type, &Data, blimit);
+
+ if(status){
+ printf(" + %sLineCap:",Which);
+ (void) U_PMF_GRAPHICSVERSION_memsafe_print((char *)&Version);;
+ printf(", Type %X\n",Type);
+ switch(Type){
+ case U_CLCDT_Default:
+ status = U_PMF_CUSTOMLINECAPDATA_print(Data, blimit);
+ break;
+ case U_CLCDT_AdjustableArrow:
+ status = U_PMF_CUSTOMLINECAPARROWDATA_print(Data, blimit);
+ break;
+ default:
+ status = 0;
+ }
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_FONT object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.1.3, Microsoft name: EmfPlusFont Object
+*/
+int U_PMF_FONT_print(const char *contents, const char *blimit){
+ uint32_t Version, SizeUnit, Length;
+ U_FLOAT EmSize;
+ int32_t FSFlags;
+ const char *Data;
+ char *string;
+ int status = U_PMF_FONT_get(contents, &Version, &EmSize, &SizeUnit, &FSFlags, &Length, &Data, blimit);
+ if(status){
+ printf(" + Font:");
+ (void) U_PMF_GRAPHICSVERSION_memsafe_print((char *)&Version);;
+ printf(" EmSize:%f ", EmSize );
+ printf(" SizeUnit:%d ",SizeUnit);
+ printf(" FSFlags:%d ", FSFlags );
+ printf(" Length:%d", Length );
+ string = U_Utf16leToUtf8((uint16_t *)Data, Length, NULL);
+ if(string){
+ printf(" Family:<%s>\n",string);
+ free(string);
+ }
+ else {
+ printf(" Family:<>\n");
+ }
+ }
+ return(status);
+}
+
+
+/**
+ \brief Print data from a U_PMF_IMAGE object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.1.4, Microsoft name: EmfPlusImage Object
+*/
+int U_PMF_IMAGE_print(const char *contents, const char *blimit){
+ uint32_t Version, Type;
+ const char *Data;
+ int status = U_PMF_IMAGE_get(contents, &Version, &Type, &Data, blimit);
+ if(status){
+ printf(" + Image:");
+ (void) U_PMF_GRAPHICSVERSION_memsafe_print((char *)&Version);;
+ printf(" Type:%X\n",Type);
+ switch(Type){
+ case U_IDT_Unknown:
+ printf(" + Unknown Image Type\n");
+ break;
+ case U_IDT_Bitmap:
+ status = U_PMF_BITMAP_print(Data, blimit);
+ break;
+ case U_IDT_Metafile:
+ status = U_PMF_METAFILE_print(Data, blimit);
+ break;
+ default:
+ status = 0;
+ }
+ }
+ return(status);
+}
+
+
+/**
+ \brief Print data from a U_PMF_IMAGEATTRIBUTES object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.1.5, Microsoft name: EmfPlusImageAttributes Object
+*/
+int U_PMF_IMAGEATTRIBUTES_print(const char *contents, const char *blimit){
+ uint32_t Version, WrapMode, ClampColor, ObjectClamp;
+ int status = U_PMF_IMAGEATTRIBUTES_get(contents, &Version, &WrapMode, &ClampColor, &ObjectClamp, blimit);
+
+ if(status){
+ printf(" + Image Attributes: ");
+ (void) U_PMF_GRAPHICSVERSION_memsafe_print((char *)&Version);;
+ printf(" WrapMode:%X", WrapMode);
+ printf(" ClampColor:%X", ClampColor);
+ printf(" ObjectClamp:%X\n", ObjectClamp);
+ }
+ return(status);
+}
+
+
+
+/**
+ \brief Print data from a U_PMF_PATH object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.1.6, Microsoft name: EmfPlusPath Object
+*/
+int U_PMF_PATH_print(const char *contents, const char *blimit){
+ unsigned int i, pos;
+ uint32_t Version, Count;
+ uint16_t Flags;
+ const char *Points;
+ const char *Types;
+ int status = U_PMF_PATH_get(contents, &Version, &Count, &Flags, &Points, &Types, blimit);
+ if(status){
+ printf(" + Path: Version:%X Count:%d Flags:%X\n",Version, Count, Flags);
+
+ /* Points part */
+ U_PMF_VARPOINTS_print(&Points, Flags, Count, blimit);
+
+ /* Types part */
+ printf(" + Types:");
+ pos = 0;
+ for(i=0; i<Count; i++){
+ /* EMF+ manual says that the first of these two cases can actually contain either type
+ of PATHPOINT, but it does not say how the program is supposed to figure out which record
+ is which type. */
+ if(Flags & U_PPF_R){
+ printf(" %u:",pos);
+ pos += U_PMF_PATHPOINTTYPERLE_print(Types, blimit);
+ Types+=2;
+ }
+ else {
+ printf(" %d:",i);
+ (void) U_PMF_PATHPOINTTYPE_print(Types, blimit);
+ Types++;
+ }
+ }
+ printf("\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_PEN object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.2.1.7, Microsoft name: EmfPlusPen Object
+*/
+int U_PMF_PEN_print(const char *contents, const char *blimit){
+ uint32_t Version, Type;
+ const char *PenData;
+ const char *Brush;
+ int status = U_PMF_PEN_get(contents, &Version, &Type, &PenData, &Brush, blimit);
+ if(status){
+ printf(" + Pen: Version:%X Type:%d\n",Version,Type);
+ (void) U_PMF_PENDATA_print(PenData, blimit);
+ (void) U_PMF_BRUSH_print(Brush, blimit);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_REGION object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.1.8, Microsoft name: EmfPlusRegion Object
+*/
+int U_PMF_REGION_print(const char *contents, const char *blimit){
+ uint32_t Version, Count;
+ const char *Nodes;
+ int status = U_PMF_REGION_get(contents, &Version, &Count, &Nodes, blimit);
+ if(status){
+ printf(" + ");
+ (void) U_PMF_GRAPHICSVERSION_memsafe_print((char *)&Version);;
+ printf(" ChildNodes:%d",Count);
+ (void) U_PMF_REGIONNODE_print(Nodes, 1, blimit); /* 1 == top level*/
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_STRINGFORMAT object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.1.9, Microsoft name: EmfPlusStringFormat Object
+*/
+int U_PMF_STRINGFORMAT_print(const char *contents, const char *blimit){
+ U_PMF_STRINGFORMAT Sfs;
+ const char *Data;
+ int status = U_PMF_STRINGFORMAT_get(contents, &Sfs, &Data, blimit);
+ if(status){
+ printf(" + StringFormat: ");
+ printf(" Version:%X", Sfs.Version );
+ printf(" Flags:%X", Sfs.Flags );
+ printf(" Language"); (void) U_PMF_LANGUAGEIDENTIFIER_print(Sfs.Language);
+ printf(" StringAlignment:%X", Sfs.StringAlignment );
+ printf(" LineAlign:%X", Sfs.LineAlign );
+ printf(" DigitSubstitution:%X",Sfs.DigitSubstitution);
+ printf(" DigitLanguage"); (void) U_PMF_LANGUAGEIDENTIFIER_print(Sfs.DigitLanguage);
+ printf(" FirstTabOffset:%f", Sfs.FirstTabOffset );
+ printf(" HotkeyPrefix:%d", Sfs.HotkeyPrefix );
+ printf(" LeadingMargin:%f", Sfs.LeadingMargin );
+ printf(" TrailingMargin:%f", Sfs.TrailingMargin );
+ printf(" Tracking:%f", Sfs.Tracking );
+ printf(" Trimming:%X", Sfs.Trimming );
+ printf(" TabStopCount:%u", Sfs.TabStopCount );
+ printf(" RangeCount:%u", Sfs.RangeCount );
+ (void) U_PMF_STRINGFORMATDATA_print(Data, Sfs.TabStopCount, Sfs.RangeCount, blimit);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_ARGB object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+
+ Does not accept a blimit value.
+ EMF+ manual 2.2.2.1, Microsoft name: EmfPlusARGB Object
+*/
+int U_PMF_ARGB_print(const char *contents){
+ uint8_t Blue, Green, Red, Alpha;
+ int status = U_PMF_ARGB_get(contents, &Blue, &Green, &Red, &Alpha, contents + sizeof(U_RGBQUAD));
+ if(status){
+ printf(" RGBA{%2.2X,%2.2X,%2.2X,%2.2X}", Red, Green, Blue, Alpha);
+ }
+ return(status);
+}
+
+
+/**
+ \brief Print data from a U_PMF_BITMAP object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.2, Microsoft name: EmfPlusBitmap Object
+*/
+int U_PMF_BITMAP_print(const char *contents, const char *blimit){
+ U_PMF_BITMAP Bs;
+ const char *Data;
+ int status = U_PMF_BITMAP_get(contents, &Bs, &Data, blimit);
+ if(status){
+ printf(" + Bitmap: Width:%d Height:%d Stride:%d\n",Bs.Width, Bs.Height, Bs.Stride);
+ U_PMF_PX_FMT_ENUM_print(Bs.PxFormat);
+ switch(Bs.Type){
+ case 0: printf(" Type:MSBitmap\n"); break;
+ case 1: printf(" Type:(PNG|JPG|GIF|EXIF|TIFF)\n"); break;
+ default: printf(" Type:INVALID(%d)\n",Bs.Type); break;
+ }
+ /* Pixel data is never shown - it could easily swamp the output for even a smallish picture */
+ }
+ return(status);
+}
+
+
+/**
+ \brief Print data from a U_PMF_BITMAPDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.3, Microsoft name: EmfPlusBitmapData Object
+*/
+int U_PMF_BITMAPDATA_print(const char *contents, const char *blimit){
+ unsigned int i;
+ U_PMF_PALETTE Ps;
+ const char *Colors;
+ const char *Data;
+ int status = U_PMF_BITMAPDATA_get(contents, &Ps, &Colors, &Data, blimit);
+ if(status){
+ status = 0;
+ printf(" BMData: Flags:%X, Elements:%u Colors:", Ps.Flags, Ps.Elements);
+ for(i=0; i<Ps.Elements; i++, Colors+=sizeof(U_PMF_ARGB)){
+ (void) U_PMF_ARGB_print(Colors);
+ }
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_BLENDCOLORS object
+ \return size in bytes on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.4, Microsoft name: EmfPlusBlendColors Object
+*/
+int U_PMF_BLENDCOLORS_print(const char *contents, const char *blimit){
+ unsigned int i;
+ uint32_t Elements;
+ U_FLOAT *Positions;
+ const char *Colors;
+ int status = U_PMF_BLENDCOLORS_get(contents, &Elements, &Positions, &Colors, blimit);
+ if(status){
+ printf(" + BlendColors: Entries:%d (entry,pos,color): ", Elements);
+ for(i=0; i<Elements; i++){
+ printf(" (%d,%f,", i, Positions[i]);
+ (void) U_PMF_ARGB_print(Colors);
+ Colors += sizeof(U_PMF_ARGB);
+ printf(")");
+ }
+ status = sizeof(uint32_t) + Elements*sizeof(U_FLOAT) + Elements*sizeof(U_PMF_ARGB);
+ free(Positions);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_BLENDFACTORS object
+ \return size on success, 0 on error
+ \param type Type of BlendFactors, usually H or V
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.5, Microsoft name: EmfPlusBlendFactors Object
+*/
+int U_PMF_BLENDFACTORS_print(const char *contents, const char *type, const char *blimit){
+ unsigned int i;
+ uint32_t Elements;
+ U_FLOAT *Positions;
+ U_FLOAT *Factors;
+ int status = U_PMF_BLENDFACTORS_get(contents, &Elements, &Positions, &Factors, blimit);
+ if(status){
+ printf(" + BlendFactors%s: Entries:%d (entry,pos,factor): ",type, Elements);
+ for(i=0; i<Elements; i++){
+ printf(" (%d,%f,%f)", i, Positions[i],Factors[i]);
+ }
+ status = sizeof(uint32_t) + Elements*2*sizeof(U_FLOAT);
+ free(Positions);
+ free(Factors);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_BOUNDARYPATHDATA object
+ \return size on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.6, Microsoft name: EmfPlusBoundaryPathData Object
+*/
+int U_PMF_BOUNDARYPATHDATA_print(const char *contents, const char * blimit){
+ int32_t Size;
+ const char *Data;
+ int status = U_PMF_BOUNDARYPATHDATA_get(contents, &Size, &Data, blimit);
+ if(status){
+ printf(" + BoundaryPathData: Size:%d\n",Size);
+ (void) U_PMF_PATH_print(Data, blimit);
+ }
+ return(status);
+}
+
+
+/**
+ \brief Print data from a U_PMF_BOUNDARYPOINTDATA object
+ \return size on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.7, Microsoft name: EmfPlusBoundaryPointData Object
+*/
+int U_PMF_BOUNDARYPOINTDATA_print(const char *contents, const char *blimit){
+ int32_t Elements;
+ U_PMF_POINTF *Points;
+ int status = U_PMF_BOUNDARYPOINTDATA_get(contents, &Elements, &Points, blimit);
+ if(status){
+ printf(" + BoundaryPointData: Elements:%u\n",Elements);
+ U_PMF_VARPOINTF_S_print(Points, Elements);
+ free(Points);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_CHARACTERRANGE object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.8, Microsoft name: EmfPlusCharacterRange Object
+*/
+int U_PMF_CHARACTERRANGE_print(const char *contents, const char *blimit){
+ int32_t First, Length;
+ int status = U_PMF_CHARACTERRANGE_get(contents, &First, &Length, blimit);
+ if(status){
+ printf(" {%d,%d}",First,Length);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_DASHEDLINEDATA object
+ \return 1 on success, 0 on error
+ \param blimit one byte past the end of data
+ \param contents Record from which to print data
+ EMF+ manual 2.2.2.9, Microsoft name: EmfPlusCompoundLineData Object
+*/
+int U_PMF_COMPOUNDLINEDATA_print(const char *contents, const char *blimit){
+ int32_t Elements;
+ U_FLOAT *Widths;
+ U_FLOAT *hold;
+ int status = U_PMF_COMPOUNDLINEDATA_get(contents, &Elements, &Widths, blimit);
+ if(status){
+ printf(" + CompoundLineData: Elements:%u {",Elements);
+ Elements--;
+ for(hold=Widths; Elements; Elements--,Widths++){ printf("%f, ",*Widths); }
+ printf("%f}",*Widths);
+ free(hold);
+ printf("\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_COMPRESSEDIMAGE object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.10, Microsoft name: EmfPlusCompressedImage Object
+
+ This function does not do anything useful, but it is included so that all objects have a corresponding _get().
+*/
+int U_PMF_COMPRESSEDIMAGE_print(const char *contents, const char *blimit){
+ const char *Data;
+ int status = U_PMF_COMPRESSEDIMAGE_get(contents, &Data, blimit);
+ if(status){
+ printf("CompressedImage:\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_CUSTOMENDCAPDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.11, Microsoft name: EmfPlusCustomEndCapData Object
+*/
+int U_PMF_CUSTOMENDCAPDATA_print(const char *contents, const char *blimit){
+ int32_t Size;
+ const char *Data;
+ int status = U_PMF_CUSTOMENDCAPDATA_get(contents, &Size, &Data, blimit);
+ if(status){
+ printf(" + CustomEndCap: Size:%d\n",Size);
+ (void) U_PMF_CUSTOMLINECAP_print(Data, "End", blimit);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_CUSTOMLINECAPARROWDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.12, Microsoft name: EmfPlusCustomLineCapArrowData Object
+*/
+int U_PMF_CUSTOMLINECAPARROWDATA_print(const char *contents, const char *blimit){
+ U_PMF_CUSTOMLINECAPARROWDATA Ccad;
+ int status = U_PMF_CUSTOMLINECAPARROWDATA_get(contents, &Ccad, blimit);
+ if(status){
+ printf("CustomLineCapArrowData: ");
+ printf(" Width:%f", Ccad.Width );
+ printf(" Height:%f", Ccad.Height );
+ printf(" MiddleInset:%f", Ccad.MiddleInset );
+ printf(" FillState:%u", Ccad.FillState );
+ printf(" StartCap:%X", Ccad.StartCap );
+ printf(" EndCap:%X", Ccad.EndCap );
+ printf(" Join:%X", Ccad.Join );
+ printf(" MiterLimit:%f", Ccad.MiterLimit );
+ printf(" WidthScale:%f", Ccad.WidthScale );
+ printf(" FillHotSpot:{%f,%f}",Ccad.FillHotSpot[0],Ccad.FillHotSpot[1]);
+ printf(" LineHotSpot:{%f,%f}",Ccad.LineHotSpot[0],Ccad.LineHotSpot[1]);
+ printf("\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_CUSTOMLINECAPDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.13, Microsoft name: EmfPlusCustomLineCapData Object
+*/
+int U_PMF_CUSTOMLINECAPDATA_print(const char *contents, const char *blimit){
+ U_PMF_CUSTOMLINECAPDATA Clcd;
+ const char *Data;
+ int status = U_PMF_CUSTOMLINECAPDATA_get(contents, &Clcd, &Data, blimit);
+ if(status){
+ printf(" + CustomLineCapData: ");
+ printf(" Flags:%X", Clcd.Flags );
+ printf(" Cap:%X", Clcd.Cap );
+ printf(" Inset:%f", Clcd.Inset );
+ printf(" StartCap:%X", Clcd.StartCap );
+ printf(" EndCap:%X", Clcd.EndCap );
+ printf(" Join:%X", Clcd.Join );
+ printf(" MiterLimit:%f", Clcd.MiterLimit );
+ printf(" WidthScale:%f", Clcd.WidthScale );
+ printf(" FillHotSpot:{%f,%f}",Clcd.FillHotSpot[0],Clcd.FillHotSpot[1]);
+ printf(" LineHotSpot:{%f,%f}\n",Clcd.LineHotSpot[0],Clcd.LineHotSpot[1]);
+ (void) U_PMF_CUSTOMLINECAPOPTIONALDATA_print(Data, Clcd.Flags, blimit);
+ /* preceding line always emits an EOL */
+ }
+ return(status);
+}
+
+
+/**
+ \brief Print data from a U_PMF_CUSTOMLINECAPOPTIONALDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param Flags CustomLineCapData Flags
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.14, Microsoft name: EmfPlusCustomLineCapOptionalData Object
+*/
+int U_PMF_CUSTOMLINECAPOPTIONALDATA_print(const char *contents, uint32_t Flags, const char *blimit){
+ const char *FillData;
+ const char *LineData;
+ int status = U_PMF_CUSTOMLINECAPOPTIONALDATA_get(contents, Flags, &FillData, &LineData, blimit);
+ if(status){ /* True even if there is nothing in it! */
+ printf(" + CustomLineCapOptionalData:");
+ if(FillData || LineData){
+ if(FillData){ (void) U_PMF_FILLPATHOBJ_print(FillData, blimit); }
+ if(LineData){ (void) U_PMF_LINEPATH_print(LineData, blimit); }
+ }
+ else {
+ printf("None");
+ }
+ }
+ if(status<=1){ printf("\n"); }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_CUSTOMSTARTCAPDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.15, Microsoft name: EmfPlusCustomStartCapData Object
+*/
+int U_PMF_CUSTOMSTARTCAPDATA_print(const char *contents, const char *blimit){
+ int32_t Size;
+ const char *Data;
+ int status = U_PMF_CUSTOMSTARTCAPDATA_get(contents, &Size, &Data, blimit);
+ if(status){
+ printf(" + CustomStartCap: Size:%d ",Size);
+ (void) U_PMF_CUSTOMLINECAP_print(Data, "Start", blimit);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_DASHEDLINEDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.16, Microsoft name: EmfPlusDashedLineData Object
+*/
+int U_PMF_DASHEDLINEDATA_print(const char *contents, const char *blimit){
+ int32_t Elements;
+ U_FLOAT *Lengths;
+ U_FLOAT *hold;
+ int status = U_PMF_DASHEDLINEDATA_get(contents, &Elements, &Lengths, blimit);
+ if(status){
+ printf(" DashedLineData: Elements:%u {",Elements);
+ Elements--;
+ for(hold=Lengths; Elements; Elements--, Lengths++){ printf("%f, ", *Lengths); }
+ printf("%f}", *Lengths);
+ free(hold);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_FILLPATHOBJ object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.17, Microsoft name: EmfPlusFillPath Object
+*/
+int U_PMF_FILLPATHOBJ_print(const char *contents, const char * blimit){
+ int32_t Size;
+ const char *Data;
+ int status = U_PMF_FILLPATHOBJ_get(contents, &Size, &Data, blimit);
+ if(status){
+ printf(" FillPathObj: Size:%d\n",Size);
+ if(Size){ (void) U_PMF_PATH_print(Data, blimit); }
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_FOCUSSCALEDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.18, Microsoft name: EmfPlusFocusScaleData Object
+*/
+int U_PMF_FOCUSSCALEDATA_print(const char *contents, const char *blimit){
+ uint32_t Count;
+ U_FLOAT ScaleX, ScaleY;
+ int status = U_PMF_FOCUSSCALEDATA_get(contents, &Count, &ScaleX, &ScaleY, blimit);
+ if(status){
+ printf(" FocusScaleData: Count:%d ScaleX:%f ScaleY:%f ",Count,ScaleX,ScaleY);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_GRAPHICSVERSION object already known to be memory safe
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.2.2.19, Microsoft name: EmfPlusGraphicsVersion Object
+
+ In this module the only time a U_PMF_GRAPHICSVERSION is printed is after it
+ has already been copied into a safe memory structure. This routine fakes up
+ a blimit for the general routine.
+
+*/
+int U_PMF_GRAPHICSVERSION_memsafe_print(const char *contents){
+ const char *blimit = contents + sizeof(U_PMF_GRAPHICSVERSION);
+ return(U_PMF_GRAPHICSVERSION_print(contents, blimit));
+}
+
+/**
+ \brief Print data from a U_PMF_GRAPHICSVERSION object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.19, Microsoft name: EmfPlusGraphicsVersion Object
+*/
+int U_PMF_GRAPHICSVERSION_print(const char *contents, const char *blimit){
+ int Signature,GrfVersion;
+ int status = U_PMF_GRAPHICSVERSION_get(contents, &Signature, &GrfVersion, blimit);
+ if(status){
+ printf(" MetaFileSig:%X",Signature );
+ printf(" GraphicsVersion:%X", GrfVersion);
+ }
+ return(status);
+}
+
+
+/**
+ \brief Print data from a U_PMF_HATCHBRUSHDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit One byte past the last record in memory.
+ EMF+ manual 2.2.2.20, Microsoft name: EmfPlusHatchBrushData Object
+*/
+int U_PMF_HATCHBRUSHDATA_print(const char *contents, const char *blimit){
+ uint32_t Style;
+ U_PMF_ARGB Foreground, Background;
+ int status = U_PMF_HATCHBRUSHDATA_get(contents, &Style, &Foreground, &Background, blimit);
+ if(status){
+ printf(" + HBdata: Style:%u(",Style);
+ U_PMF_HATCHSTYLEENUMERATION_print(Style);
+ printf(") FG:{");
+ (void) U_PMF_ARGB_print((char *)&Foreground);
+ printf("} BG:{");
+ (void) U_PMF_ARGB_print((char *)&Background);
+ printf("}");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_LANGUAGEIDENTIFIER object
+ \return 1 on success, 0 on error
+ \param LId Record from which to print data
+ EMF+ manual 2.2.2.23, Microsoft name: EmfPlusLanguageIdentifier Object
+*/
+int U_PMF_LANGUAGEIDENTIFIER_print(U_PMF_LANGUAGEIDENTIFIER LId){
+ int SubLId, PriLId;
+ int status = U_PMF_LANGUAGEIDENTIFIER_get(LId, &SubLId, &PriLId);
+ if(status){ /* do it the hard way just to verify that the preceding call works, OK to just print LId directly */
+ printf("{%4.4X}",U_PMF_LANGUAGEIDENTIFIEROBJ_set(SubLId, PriLId));
+ }
+ return(status);
+}
+
+
+
+/**
+ \brief Print data from a U_PMF_LINEARGRADIENTBRUSHDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit One byte past the last record in memory.
+ EMF+ manual 2.2.2.24, Microsoft name: EmfPlusLinearGradientBrushData Object
+*/
+int U_PMF_LINEARGRADIENTBRUSHDATA_print(const char *contents, const char *blimit){
+ U_PMF_LINEARGRADIENTBRUSHDATA Lgbd;
+ const char *Data;
+ int status = U_PMF_LINEARGRADIENTBRUSHDATA_get(contents, &Lgbd, &Data, blimit);
+ if(status){
+ printf(" + LinearGradientBrushData: Flags:%X WrapMode:%d Rect:",Lgbd.Flags, Lgbd.WrapMode);
+ (void) U_PMF_RECTF_S_print(&(Lgbd.RectF));
+ printf(" StartColor:");
+ (void) U_PMF_ARGB_print((char *)&(Lgbd.StartColor));
+ printf(" EndColor:");
+ (void) U_PMF_ARGB_print((char *)&(Lgbd.EndColor));
+ /* Technically these are to be ignored, in practice they must be colors with the same value as the preceding 2*/
+ printf(" Reserved1:");
+ (void) U_PMF_ARGB_print((char *)&(Lgbd.Reserved1));
+ printf(" Reserved2:");
+ (void) U_PMF_ARGB_print((char *)&(Lgbd.Reserved2));
+ printf("\n");
+ (void) U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_print(Data, Lgbd.Flags, blimit);
+ }
+ return(status);
+}
+
+
+
+/**
+ \brief Print data from a U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param BDFlag Describes optional values in contents
+ \param blimit One byte past the last record in memory.
+ EMF+ manual 2.2.2.25, Microsoft name: EmfPlusLinearGradientBrushOptionalData Object
+*/
+int U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_print(const char *contents, int BDFlag, const char *blimit){
+ U_PMF_TRANSFORMMATRIX Tm;
+ const char *Bc;
+ const char *BfH;
+ const char *BfV;
+ int None=1;
+ printf(" + LinearGradientBrushOptionalData: ");
+ int status = U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_get(contents, BDFlag, &Tm, &Bc, &BfH, &BfV, blimit);
+ if(status){
+ if(BDFlag & U_BD_Transform){
+ U_PMF_TRANSFORMMATRIX2_print(&Tm);
+ None=0;
+ }
+ if(Bc){
+ printf("\n");
+ (void) U_PMF_BLENDCOLORS_print(Bc, blimit);
+ None=0;
+ }
+ if(BfH){
+ printf("\n");
+ (void) U_PMF_BLENDFACTORS_print(BfH,"H", blimit);
+ None=0;
+ }
+ if(BfV){
+ printf("\n");
+ (void) U_PMF_BLENDFACTORS_print(BfV,"V", blimit);
+ None=0;
+ }
+ if(None){
+ printf("(none)");
+ }
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_LINEPATH object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.26, Microsoft name: EmfPlusLinePath Object
+*/
+int U_PMF_LINEPATH_print(const char *contents, const char * blimit){
+ int32_t Size;
+ const char *Data;
+ int status = U_PMF_LINEPATH_get(contents, &Size, &Data, blimit);
+ if(status){
+ printf(" LinePath: Size:%d\n", Size);
+ (void) U_PMF_PATH_print(Data, blimit);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_METAFILE object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.27, Microsoft name: EmfPlusMetafile Object
+*/
+int U_PMF_METAFILE_print(const char *contents, const char * blimit){
+ uint32_t Type;
+ uint32_t Size;
+ const char *Data;
+ int status = U_PMF_METAFILE_get(contents, &Type, &Size, &Data, blimit);
+ if(status){
+ printf(" MetaFile: Type:%X Size:%d",Type, Size);
+ /* embedded metafiles are not handled beyond this*/
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_PALETTE object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.28, Microsoft name: EmfPlusPalette Object
+*/
+int U_PMF_PALETTE_print(const char *contents, const char *blimit){
+ unsigned int i;
+ uint32_t Flags;
+ uint32_t Elements;
+ const char *Data;
+ int status = U_PMF_PALETTE_get(contents, &Flags, &Elements, &Data, blimit);
+ if(status){
+ printf(" Palette: Flags:%X Elements:%u Colors:",Flags, Elements);
+ for(i=0; i<Elements; i++){
+ (void) U_PMF_ARGB_print(Data);
+ Data += sizeof(U_PMF_ARGB);
+ }
+ printf("\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_PATHGRADIENTBRUSHDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.29, Microsoft name: EmfPlusPathGradientBrushData Object
+*/
+int U_PMF_PATHGRADIENTBRUSHDATA_print(const char *contents, const char *blimit){
+ U_PMF_PATHGRADIENTBRUSHDATA Pgbd;
+ const char *Gradient;
+ const char *Boundary;
+ const char *Data=NULL;
+ unsigned int i;
+ int status = U_PMF_PATHGRADIENTBRUSHDATA_get(contents, &Pgbd, &Gradient, &Boundary, &Data, blimit);
+ if(status){
+ printf(" + PathGradientBrushData: Flags:%X WrapMode:%d, CenterColor:",Pgbd.Flags, Pgbd.WrapMode);
+ (void) U_PMF_ARGB_print((char *)&(Pgbd.CenterColor));
+ printf(" Center:");
+ (void) U_PMF_POINTF_S_print(&(Pgbd.Center));
+ printf(" Elements:%u\n",Pgbd.Elements);
+ if(Pgbd.Elements){
+ printf(" + SurroundingColor: ");
+ for(i=Pgbd.Elements; i; i--, Gradient+=4){
+ (void) U_PMF_ARGB_print(Gradient);
+ }
+ printf("\n");
+ }
+ if(Pgbd.Flags & U_BD_Path){
+ (void) U_PMF_BOUNDARYPATHDATA_print(Boundary, blimit);
+ }
+ else {
+ (void) U_PMF_BOUNDARYPOINTDATA_print(Boundary, blimit);
+ }
+ (void) U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_print(Data, Pgbd.Flags, blimit);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_PATHGRADIENTBRUSHOPTIONALDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param BDFlag Describes optional values in contents
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.30, Microsoft name: EmfPlusPathGradientBrushOptionalData Object
+*/
+int U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_print(const char *contents, int BDFlag, const char *blimit){
+ if(BDFlag & (U_BD_Transform | U_BD_PresetColors | U_BD_BlendFactorsH | U_BD_FocusScales)){
+ printf(" + PathGradientBrushOptionalData: ");
+ }
+ if(BDFlag & U_BD_Transform){
+ U_PMF_TRANSFORMMATRIX_print(contents, blimit);
+ contents += sizeof(U_PMF_TRANSFORMMATRIX);
+ }
+ if(BDFlag & U_BD_PresetColors){ /* If this is present, BlendFactorsH will not be */
+ contents += U_PMF_BLENDCOLORS_print(contents, blimit);
+ }
+ if(BDFlag & U_BD_BlendFactorsH){/* If this is present, U_BD_PresetColors will not be */
+ contents += U_PMF_BLENDFACTORS_print(contents,"", blimit);
+ }
+ if(BDFlag & U_BD_FocusScales){
+ contents += U_PMF_BLENDFACTORS_print(contents,"", blimit);
+ U_PMF_FOCUSSCALEDATA_print(contents, blimit);
+ }
+ return(1);
+}
+
+/**
+ \brief Print data from a U_PMF_PATHPOINTTYPE object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.31, Microsoft name: EmfPlusPathPointType Object
+*/
+int U_PMF_PATHPOINTTYPE_print(const char *contents, const char *blimit){
+ int Flags, Type;
+ int status = U_PMF_PATHPOINTTYPE_get(contents, &Flags, &Type, blimit);
+ if(status){
+ printf("{Flags:%X Type:",Flags);
+ (void) U_PMF_PATHPOINTTYPE_ENUM_print(Type);
+ printf("}");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_PATHPOINTTYPERLE object
+ \return Number of elements in the run, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.32, Microsoft name: EmfPlusPathPointTypeRLE Object
+*/
+int U_PMF_PATHPOINTTYPERLE_print(const char *contents, const char *blimit){
+ int Bezier, Elements, Type;
+ int status = U_PMF_PATHPOINTTYPERLE_get(contents, &Bezier, &Elements, &Type, blimit);
+ if(status){
+ status = Elements;
+ printf(" PathPointTypeRLE: Bezier:%c Elements:%u, Type: ",(Bezier ? 'Y' : 'N'), Elements);
+ (void) U_PMF_PATHPOINTTYPE_ENUM_print(Type);
+ printf("\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_PATHPOINTTYPERLE object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.33, Microsoft name: EmfPlusPenData Object
+*/
+int U_PMF_PENDATA_print(const char *contents, const char *blimit){
+ uint32_t Flags, Unit;
+ U_FLOAT Width;
+ const char *Data;
+ int status = U_PMF_PENDATA_get(contents, &Flags, &Unit, &Width, &Data, blimit);
+ if(status){
+ printf(" + Pendata: Flags:%X Unit:%X Width:%f",Flags, Unit, Width);
+ (void) U_PMF_PENOPTIONALDATA_print(Data, Flags, blimit); /* prints a new line at end */
+ }
+ return(status);
+}
+
+
+
+/**
+ \brief Print data from a U_PMF_PENOPTIONALDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ \param Flags PenData Flags that determine which optionaldata fields are present in the record.
+
+ EMF+ manual 2.2.2.34, Microsoft name: EmfPlusPenOptionalData Object
+*/
+int U_PMF_PENOPTIONALDATA_print(const char *contents, int Flags, const char *blimit){
+ U_PMF_TRANSFORMMATRIX Matrix;
+ int32_t StartCap;
+ int32_t EndCap;
+ uint32_t Join;
+ U_FLOAT MiterLimit;
+ int32_t Style;
+ int32_t DLCap;
+ U_FLOAT DLOffset;
+ const char *DLData;
+ int32_t Alignment;
+ const char *CmpndLineData;
+ const char *CSCapData;
+ const char *CECapData;
+ int status = U_PMF_PENOPTIONALDATA_get(
+ contents,
+ Flags, // determines which fields are filled
+ &Matrix,
+ &StartCap,
+ &EndCap,
+ &Join,
+ &MiterLimit,
+ &Style,
+ &DLCap,
+ &DLOffset,
+ &DLData,
+ &Alignment,
+ &CmpndLineData,
+ &CSCapData,
+ &CECapData,
+ blimit);
+ if(status){
+ if(Flags & U_PD_Transform){ (void) U_PMF_TRANSFORMMATRIX2_print(&Matrix);}
+ if(Flags & U_PD_StartCap){ printf(" StartCap:%d", StartCap );}
+ if(Flags & U_PD_EndCap){ printf(" EndCap:%d", EndCap );}
+ if(Flags & U_PD_Join){ printf(" Join:%X", Join );}
+ if(Flags & U_PD_MiterLimit){ printf(" MiterLimit:%f", MiterLimit );}
+ if(Flags & U_PD_LineStyle){ printf(" Style:%X", Style );}
+ if(Flags & U_PD_DLCap){ printf(" DLCap:%X", DLCap );}
+ if(Flags & U_PD_DLOffset){ printf(" DLOffset:%f", DLOffset );}
+ if(Flags & U_PD_DLData){ (void) U_PMF_DASHEDLINEDATA_print(DLData, blimit );}
+ if(Flags & U_PD_NonCenter){ printf(" Alignment:%d", Alignment );}
+ if(Flags & (U_PD_Transform | U_PD_StartCap | U_PD_EndCap |
+ U_PD_Join | U_PD_MiterLimit | U_PD_LineStyle |
+ U_PD_DLCap | U_PD_DLOffset |U_PD_DLData |U_PD_NonCenter)){ printf("\n"); }
+ if(Flags & U_PD_CLData){ (void) U_PMF_COMPOUNDLINEDATA_print(CmpndLineData, blimit); }
+ if(Flags & U_PD_CustomStartCap){ (void) U_PMF_CUSTOMSTARTCAPDATA_print(CSCapData, blimit); }
+ if(Flags & U_PD_CustomEndCap){ (void) U_PMF_CUSTOMENDCAPDATA_print(CECapData, blimit); }
+ }
+ return(status);
+}
+/**
+ \brief Print data from a U_PMF_POINT object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.35, Microsoft name: EmfPlusPoint Object
+*/
+int U_PMF_POINT_print(const char **contents, const char *blimit){
+ U_FLOAT X, Y;
+ int status = U_PMF_POINT_get(contents, &X, &Y, blimit);
+ if(status){
+ printf("{%f,%f}", X, Y);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_POINT Structure
+ \return 1 on success, 0 on error
+ \param Point U_PMF_POINT Structure to print
+ EMF+ manual 2.2.2.35, Microsoft name: EmfPlusPoint Object
+*/
+int U_PMF_POINT_S_print(U_PMF_POINT *Point){\
+ if(!Point){ return(0); }
+ printf("{%d,%d}", Point->X, Point->Y);
+ return(1);
+}
+
+/**
+ \brief Print data from a U_PMF_POINTF object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.36, Microsoft name: EmfPlusPointF Object
+*/
+int U_PMF_POINTF_print(const char **contents, const char *blimit){
+ U_FLOAT X, Y;
+ int status = U_PMF_POINTF_get(contents, &X, &Y, blimit);
+ if(status){
+ printf("{%f,%f}", X, Y);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_POINTF Structure
+ \return 1 on success, 0 on error
+ \param Point U_PMF_POINTF Structure to print
+ EMF+ manual 2.2.2.36, Microsoft name: EmfPlusPointF Object
+*/
+int U_PMF_POINTF_S_print(U_PMF_POINTF *Point){
+ if(!Point){ return(0); }
+ printf("{%f,%f}", Point->X, Point->Y);
+ return(1);
+}
+
+/**
+ \brief Print data from a U_PMF_POINTR object
+ \return bytes traversed on success, 0 on error
+ \param contents Pointer to next data to print
+ \param Xpos X coordinate for current point
+ \param Ypos Y coordinate for current point
+ \param blimit one byte past the end of data
+
+ On each call the next relative offset is extracted, the current
+ coordinates are modified with that offset, and the pointer is
+ advanced to the next data point.
+
+ EMF+ manual 2.2.2.37, Microsoft name: EmfPlusPointR Object
+*/
+int U_PMF_POINTR_print(const char **contents, U_FLOAT *Xpos, U_FLOAT *Ypos, const char *blimit){
+ U_FLOAT X, Y;
+ int status = U_PMF_POINTR_get(contents, &X, &Y, blimit);
+ *Xpos += X;
+ *Ypos += Y;
+ if(status){
+ printf("{%f,%f(%f,%f)}", *Xpos, *Ypos, X, Y);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_RECT object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.38, Microsoft name: EmfPlusRect Object
+*/
+int U_PMF_RECT_print(const char **contents, const char *blimit){
+ int16_t X, Y, Width, Height;
+ int status = U_PMF_RECT_get(contents, &X, &Y, &Width, &Height, blimit);
+ if(status){
+ printf("{UL{%d,%d},WH{%d,%d}}", X, Y, Width, Height);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_RECT Structure
+ \return 1 on success, 0 on error
+ \param Rect U_PMF_RECT structure
+ EMF+ manual 2.2.2.39, Microsoft name: EmfPlusRectF Object
+*/
+int U_PMF_RECT_S_print(U_PMF_RECT *Rect){
+ printf("{UL{%d,%d},WH{%d,%d}}", Rect->X, Rect->Y, Rect->Width, Rect->Height);
+ return(1);
+}
+
+/**
+ \brief Print data from a U_PMF_RECTF object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.39, Microsoft name: EmfPlusRectF Object
+*/
+int U_PMF_RECTF_print(const char **contents, const char *blimit){
+ U_FLOAT X, Y, Width, Height;
+ int status = U_PMF_RECTF_get(contents, &X, &Y, &Width, &Height, blimit);
+ if(status){
+ printf("{UL{%f,%f},WH{%f,%f}}", X, Y, Width, Height);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_RECTF Structure
+ \return 1 on success, 0 on error
+ \param Rect U_PMF_RECTF Structure
+ EMF+ manual 2.2.2.39, Microsoft name: EmfPlusRectF Object
+*/
+int U_PMF_RECTF_S_print(U_PMF_RECTF *Rect){
+ printf("{UL{%f,%f},WH{%f,%f}}", Rect->X, Rect->Y, Rect->Width, Rect->Height);
+ return(1);
+}
+
+/**
+ \brief Print data from a U_PMF_REGIONNODE object
+ \return size on success, 0 on error
+ \param contents Record from which to print data
+ \param Level Tree level. This routine is recursive and could go down many levels. 1 is the top, >1 are child nodes.
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.40, Microsoft name: EmfPlusRegionNode Object
+*/
+int U_PMF_REGIONNODE_print(const char *contents, int Level, const char *blimit){
+ int len=4; /* Type will always be present */
+ uint32_t Type;
+ const char *Data;
+ int status = U_PMF_REGIONNODE_get(contents, &Type, &Data, blimit);
+ if(status){
+ printf("\n + RegionNode(Level:%d) { Type:%X(",Level,Type);
+ U_PMF_NODETYPE_print(Type);
+ printf(")");
+ if(Type >= U_RNDT_And && Type <= U_RNDT_Complement){
+ len += U_PMF_REGIONNODECHILDNODES_print(Data, Level+1, blimit);
+ }
+ else if(Type == U_RNDT_Rect){
+ len += sizeof(U_PMF_RECTF);
+ (void) U_PMF_RECTF_print(&Data, blimit);
+ printf("\n");
+ }
+ else if(Type == U_RNDT_Path){
+ len += U_PMF_REGIONNODEPATH_print(Data, blimit);
+ }
+ /* U_RNDT_Empty and U_RNDT_Infinite do not change the length */
+ else if(Type == U_RNDT_Empty ){ printf(" Empty" ); }
+ else if(Type == U_RNDT_Infinite ){ printf(" Infinite" ); }
+ printf(" + RegionNode(Level:%d) }",Level);
+ status = len; /* length of data + length of type */
+ }
+ printf("\n");
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_REGIONNODECHILDNODES object
+ \return size on success, 0 on error
+ \param contents Record from which to print data
+ \param Level Tree level. This routine is recursive and could go down many levels. 1 is the top, >1 are child nodes.
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.41, Microsoft name: EmfPlusRegionNodeChildNodes Object
+*/
+int U_PMF_REGIONNODECHILDNODES_print(const char *contents, int Level, const char *blimit){
+ uint32_t size,rsize;
+ printf(" RegionNodeChildNodes:\n");
+ printf(" + RNCN__Left(Level:%d) {", Level);
+ size = U_PMF_REGIONNODE_print(contents, Level, blimit);
+ printf(" + RNCN__Left(Level:%d) },\n", Level);
+ if(size){
+ contents += size;
+ printf(" + RNCN_Right(Level:%d) {", Level);
+ rsize = U_PMF_REGIONNODE_print(contents, Level, blimit);
+ size += rsize;
+ printf(" + RNCN_Right(Level:%d) },\n",Level);
+ }
+ return(size);
+}
+
+/**
+ \brief Print data from a U_PMF_REGIONNODEPATH object
+ \return Size of data on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.42, Microsoft name: EmfPlusRegionNodePath Object
+*/
+int U_PMF_REGIONNODEPATH_print(const char *contents, const char * blimit){
+ int32_t Size;
+ const char *Data;
+ int status = U_PMF_REGIONNODEPATH_get(contents, &Size, &Data, blimit);
+ if(status){
+ printf(" RegionNodePath: \n");
+ (void) U_PMF_PATH_print(Data, blimit);
+ status = Size + 4; /* data sizee + the 4 bytes encoding the size */
+ }
+ return(status);
+}
+
+
+/**
+ \brief Print data from a U_PMF_SOLIDBRUSHDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.43, Microsoft name: EmfPlusSolidBrushData Object
+*/
+int U_PMF_SOLIDBRUSHDATA_print(const char *contents, const char *blimit){
+ U_PMF_ARGB Color;
+ int status = U_PMF_SOLIDBRUSHDATA_get(contents, &Color, blimit);
+ if(status){
+ printf(" SolidBrushData: ");
+ (void) U_PMF_ARGB_print((char *) &Color);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_STRINGFORMATDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param TabStopCount Entries in TabStop array
+ \param RangeCount Entries in CharRange array
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.44, Microsoft name: EmfPlusStringFormatData Object
+*/
+int U_PMF_STRINGFORMATDATA_print(const char *contents, uint32_t TabStopCount, uint32_t RangeCount, const char *blimit){
+ const U_FLOAT *TabStops;
+ const U_PMF_CHARACTERRANGE *CharRange;
+ int status = U_PMF_STRINGFORMATDATA_get(contents, TabStopCount, RangeCount, &TabStops, &CharRange, blimit);
+ if(status){
+ printf(" SFdata: TabStopCount:%u RangeCount:%u\n", TabStopCount, RangeCount);
+
+ printf(" Tabstops:");
+ for(; TabStopCount; TabStopCount--,TabStops++){ printf(" %f",*TabStops); }
+ printf("\n");
+
+ printf(" CharRange:");
+ for(; RangeCount; RangeCount--,CharRange++){ printf(" {%d,%d}",CharRange->First,CharRange->Length); }
+ printf("\n");
+
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_TEXTUREBRUSHDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.45, Microsoft name: EmfPlusTextureBrushData Object
+*/
+int U_PMF_TEXTUREBRUSHDATA_print(const char *contents, const char *blimit){
+ uint32_t Flags;
+ int32_t WrapMode;
+ const char *Data;
+ int status = U_PMF_TEXTUREBRUSHDATA_get(contents, &Flags, &WrapMode, &Data, blimit);
+ if(status){
+ printf(" + TBdata: Flags:%X WrapMode:%d", Flags, WrapMode);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_TEXTUREBRUSHOPTIONALDATA object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param HasMatrix True if the record contains a matrix.
+ \param HasImage True if the record contains an image.
+ \param blimit one byte past the end of data
+
+ EMF+ manual 2.2.2.46, Microsoft name: EmfPlusTextureBrushOptionalData Object
+*/
+int U_PMF_TEXTUREBRUSHOPTIONALDATA_print(const char *contents, int HasMatrix, int HasImage, const char *blimit){
+ U_PMF_TRANSFORMMATRIX Matrix;
+ U_PMF_TRANSFORMMATRIX *pMatrix;
+ const char *Image;
+ if(HasMatrix){ pMatrix = &Matrix; }
+ else { pMatrix = NULL; }
+ int status = U_PMF_TEXTUREBRUSHOPTIONALDATA_get(contents, HasImage, pMatrix, &Image, blimit);
+ if(status){
+ printf(" + TBOptdata: Image:%c", (HasImage ? 'Y' : 'N'));
+ (void) U_PMF_TRANSFORMMATRIX2_print(&Matrix);
+ (void) U_PMF_IMAGE_print(Image, blimit);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_TRANSFORMMATRIX object stored in file byte order.
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.2.47, Microsoft name: EmfPlusTransformMatrix Object
+*/
+int U_PMF_TRANSFORMMATRIX_print(const char *contents, const char *blimit){
+ U_PMF_TRANSFORMMATRIX Tm;
+ int status = U_PMF_TRANSFORMMATRIX_get(contents, &Tm, blimit);
+ if(status){
+ U_PMF_TRANSFORMMATRIX2_print(&Tm);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_TRANSFORMMATRIX structure
+ \return 1 on success, 0 on error
+ \param Tm U_PMF_TRANSFORMMATRIX structure
+ EMF+ manual 2.2.2.47, Microsoft name: EmfPlusTransformMatrix Object
+*/
+int U_PMF_TRANSFORMMATRIX2_print(U_PMF_TRANSFORMMATRIX *Tm){
+ if(Tm){
+ printf(" Matrix:{%f,%f,%f,%f,%f,%f}", Tm->m11, Tm->m12, Tm->m21, Tm->m22, Tm->dX, Tm->dY);
+ }
+ else {
+ printf(" Matrix:(None)");
+ }
+ return(1);
+}
+
+/**
+ \brief Print data from a U_PMF_ROTMATRIX object
+ \return 1 on success, 0 on error
+ \param Rm U_PMF_ROTMATRIX object
+ NOT DOCUMENTED, like EMF+ manual 2.2.2.47, Microsoft name: EmfPlusTransformMatrix Object, but missing offset values
+*/
+int U_PMF_ROTMATRIX2_print(U_PMF_ROTMATRIX *Rm){
+ printf(" Matrix:{%f,%f,%f,%f}", Rm->m11, Rm->m12, Rm->m21, Rm->m22);
+ return(1);
+}
+
+/**
+ \brief Print data from a U_PMF_IE_BLUR object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.3.1, Microsoft name: BlurEffect Object
+*/
+int U_PMF_IE_BLUR_print(const char *contents, const char *blimit){
+ U_FLOAT Radius;
+ uint32_t ExpandEdge;
+ int status = U_PMF_IE_BLUR_get(contents, &Radius, &ExpandEdge, blimit);
+ if(status){
+ printf("BlurEffect Radius:%f ExpandEdge:%u\n", Radius, ExpandEdge);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_IE_BRIGHTNESSCONTRAST object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.3.2, Microsoft name: BrightnessContrastEffect Object
+*/
+int U_PMF_IE_BRIGHTNESSCONTRAST_print(const char *contents, const char *blimit){
+ int32_t Brightness, Contrast;
+ int status = U_PMF_IE_BRIGHTNESSCONTRAST_get(contents, &Brightness, &Contrast, blimit);
+ if(status){
+ printf("BrightnessContrastEffect Brightness:%d Contrast:%d\n", Brightness, Contrast);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_IE_COLORBALANCE object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.3.3, Microsoft name: ColorBalanceEffect Object
+*/
+int U_PMF_IE_COLORBALANCE_print(const char *contents, const char *blimit){
+ int32_t CyanRed, MagentaGreen, YellowBlue;
+ int status = U_PMF_IE_COLORBALANCE_get(contents, &CyanRed, &MagentaGreen, &YellowBlue, blimit);
+ if(status){
+ printf("ColorBalanceEffect CyanRed:%d MagentaGreen:%d YellowBlue:%d\n", CyanRed, MagentaGreen, YellowBlue);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_IE_COLORCURVE object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.3.4, Microsoft name: ColorCurveEffect Object
+*/
+int U_PMF_IE_COLORCURVE_print(const char *contents, const char *blimit){
+ uint32_t Adjust, Channel;
+ int32_t Intensity;
+ int status = U_PMF_IE_COLORCURVE_get(contents, &Adjust, &Channel, &Intensity, blimit);
+ if(status){
+ printf("ColorBalanceEffect Adjust:%u Channel:%u Intensity:%d\n", Adjust, Channel, Intensity);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_IE_COLORLOOKUPTABLE object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.3.5, Microsoft name: ColorLookupTableEffect Object
+*/
+int U_PMF_IE_COLORLOOKUPTABLE_print(const char *contents, const char *blimit){
+ const uint8_t *BLUT, *GLUT, *RLUT, *ALUT;
+ int status = U_PMF_IE_COLORLOOKUPTABLE_get(contents, &BLUT, &GLUT, &RLUT, &ALUT, blimit);
+ if(status){
+ printf("ColorLookupTableEffect \n");
+ U_PMF_UINT8_ARRAY_print(" BLUT:", BLUT, 256, "\n");
+ U_PMF_UINT8_ARRAY_print(" GLUT:", GLUT, 256, "\n");
+ U_PMF_UINT8_ARRAY_print(" RLUT:", RLUT, 256, "\n");
+ U_PMF_UINT8_ARRAY_print(" ALUT:", ALUT, 256, "\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_IE_COLORMATRIX object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.3.6, Microsoft name: ColorMatrixEffect Object
+*/
+int U_PMF_IE_COLORMATRIX_print(const char *contents, const char *blimit){
+ U_PMF_IE_COLORMATRIX Matrix;
+ int i,j;
+ int status = U_PMF_IE_COLORMATRIX_get(contents, &Matrix, blimit);
+ if(status){
+ printf("ColorMatrixEffect\n");
+ for(i=0;i<5;i++){
+ printf(" {");
+ for(j=0;j<4;i++){ printf("%f,",Matrix.M[i][j]); }
+ printf("%f}",Matrix.M[i][j]);
+ }
+ printf("\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_IE_HUESATURATIONLIGHTNESS object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.3.7, Microsoft name: HueSaturationLightnessEffect Object
+*/
+int U_PMF_IE_HUESATURATIONLIGHTNESS_print(const char *contents, const char *blimit){
+ int32_t Hue, Saturation, Lightness;
+ int status = U_PMF_IE_HUESATURATIONLIGHTNESS_get(contents, &Hue, &Saturation, &Lightness, blimit);
+ if(status){
+ printf("HueSaturationLightnessEffect Hue:%d Saturation:%d Lightness:%d\n", Hue, Saturation, Lightness);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_IE_LEVELS object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.3.8, Microsoft name: LevelsEffect Object
+*/
+int U_PMF_IE_LEVELS_print(const char *contents, const char *blimit){
+ int32_t Highlight, Midtone, Shadow;
+ int status = U_PMF_IE_LEVELS_get(contents, &Highlight, &Midtone, &Shadow, blimit);
+ if(status){
+ printf("LevelEffect Highlight:%d Midtone:%d Shadow:%d\n", Highlight, Midtone, Shadow);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_IE_REDEYECORRECTION object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.3.9, Microsoft name: RedEyeCorrectionEffect Object
+*/
+int U_PMF_IE_REDEYECORRECTION_print(const char *contents, const char *blimit){
+ int32_t Elements;
+ U_RECTL *Rects;
+ int status = U_PMF_IE_REDEYECORRECTION_get(contents, &Elements, &Rects, blimit);
+ if(status){
+ printf("RedEyeCorrectionEffect Elements:%u", Elements);
+ for(; Elements; Elements--, Rects++){
+ printf(" ");
+ rectl_print(*Rects);
+ }
+ printf("\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_IE_SHARPEN object
+ \return 1 on success, 0 on error
+ \param blimit one byte past the end of data
+ \param contents Record from which to print data
+ EMF+ manual 2.2.3.10, Microsoft name: SharpenEffect Object
+*/
+int U_PMF_IE_SHARPEN_print(const char *contents, const char *blimit){
+ U_FLOAT Radius;
+ int32_t Sharpen;
+ int status = U_PMF_IE_SHARPEN_get(contents, &Radius, &Sharpen, blimit);
+ if(status){
+ printf("SharpenEffect Radius:%f Sharpen:%u\n", Radius, Sharpen);
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMF_IE_TINT object
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit one byte past the end of data
+ EMF+ manual 2.2.3.11, Microsoft name: TintEffect Object
+*/
+int U_PMF_IE_TINT_print(const char *contents, const char *blimit){
+ int32_t Hue, Amount;
+ int status = U_PMF_IE_TINT_get(contents, &Hue, &Amount, blimit);
+ if(status){
+ printf("TintEffect Hue:%d Amount:%d\n", Hue, Amount);
+ }
+ return(status);
+}
+
+/* ***************************************************************************************** */
+/* EMF+ records, the EMF+ record header is printed separately, these print the contents only */
+/* ***************************************************************************************** */
+
+
+/**
+ \brief Print data from a U_PMR_OFFSETCLIP record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.1.1, Microsoft name: EmfPlusOffsetClip Record, Index 0x35
+*/
+int U_PMR_OFFSETCLIP_print(const char *contents){
+ U_PMF_CMN_HDR Header;
+ U_FLOAT dX,dY;
+ int status = U_PMR_OFFSETCLIP_get(contents, &Header, &dX, &dY);
+ if(status){
+ printf(" + dx:%f dy:%f\n",dX,dY);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_OFFSETCLIP record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.1.2, Microsoft name: EmfPlusResetClip Record, Index 0x31
+*/
+int U_PMR_RESETCLIP_print(const char *contents){
+ return(U_PMR_NODATAREC_print(contents));
+}
+
+/**
+ \brief Print data from a U_PMR_SETCLIPPATH record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.1.3, Microsoft name: EmfPlusSetClipPath Record, Index 0x33
+*/
+int U_PMR_SETCLIPPATH_print(const char *contents){
+ int CMenum;
+ uint32_t PathID;
+ int status = U_PMR_SETCLIPPATH_get(contents, NULL, &PathID, &CMenum);
+ if(status){
+ printf(" + PathID:%u CMenum:%d\n",PathID,CMenum);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_SETCLIPRECT record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.1.4, Microsoft name: EmfPlusSetClipRect Record, Index 0x32
+*/
+int U_PMR_SETCLIPRECT_print(const char *contents){
+ int CMenum;
+ U_PMF_RECTF Rect;
+ int status = U_PMR_SETCLIPRECT_get(contents, NULL, &CMenum, &Rect);
+ if(status){
+ printf(" + CMenum:%d(", CMenum);
+ U_PMF_COMBINEMODEENUMERATION_print(CMenum);
+ printf(") Rect:");
+ U_PMF_RECTF_S_print(&Rect);
+ printf("\n");
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_SETCLIPREGION record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.1.5, Microsoft name: EmfPlusSetClipRegion Record, Index 0x34
+*/
+int U_PMR_SETCLIPREGION_print(const char *contents){
+ int CMenum;
+ uint32_t PathID;
+ int status = U_PMR_SETCLIPREGION_get(contents, NULL, &PathID, &CMenum);
+ if(status){
+ printf(" + PathID:%u CMenum:%d(",PathID, CMenum);
+ U_PMF_COMBINEMODEENUMERATION_print(CMenum);
+ printf(")\n");
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+
+/**
+ \brief Print data from a U_PMR_COMMENT record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.2.1, Microsoft name: EmfPlusComment Record, Index 0x03
+*/
+int U_PMR_COMMENT_print(const char *contents){
+ U_PMF_CMN_HDR Header;
+ const char *Data;
+ unsigned int i=0;
+ int status = U_PMR_COMMENT_get(contents, &Header, &Data);
+ if(status){
+ const char *blimit = contents + Header.Size;
+ if(IS_MEM_UNSAFE(Data, Header.DataSize, blimit)){
+ printf(" corrupt record\n");
+ return(0);
+ }
+ /* try to print it, but only ASCII, bail on anything that is not ASCII */
+ printf(" + Data:");
+ for(i=0; i< Header.DataSize; i++,Data++){
+ if(!*Data)break;
+ if(*(unsigned const char *)Data <128){ printf("%c",*Data); }
+ else { break; }
+ }
+ printf("\n");
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_ENDOFFILE record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.3.1, Microsoft name: EmfPlusEndOfFile Record, Index 0x02
+*/
+int U_PMR_ENDOFFILE_print(const char *contents){
+ return(U_PMR_NODATAREC_print(contents));
+}
+
+/**
+ \brief Print data from a U_PMR_ENDOFFILE record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.3.2, Microsoft name: EmfPlusGetDC Record, Index 0x04
+*/
+int U_PMR_GETDC_print(const char *contents){
+ return(U_PMR_NODATAREC_print(contents));
+}
+
+/**
+ \brief Print data from a U_PMR_HEADER record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.3.3, Microsoft name: EmfPlusHeader Record, Index 0x01
+*/
+int U_PMR_HEADER_print(const char *contents){
+ U_PMF_GRAPHICSVERSION Version;
+ int IsDual, IsVideo;
+ uint32_t LogicalDpiX, LogicalDpiY;
+ int status = U_PMR_HEADER_get(contents, NULL, &Version, &IsDual, &IsVideo, &LogicalDpiX, &LogicalDpiY);
+ if(status){
+ /* try to print it, but only ASCII, bail on anything that is not ASCII */
+ printf(" + ");
+ (void) U_PMF_GRAPHICSVERSION_memsafe_print((char *)&Version);;
+ printf(" IsDual:%c IsVideo:%d LogicalDpiX,y:{%u,%u}\n",(IsDual ? 'Y' : 'N'),IsVideo,LogicalDpiX, LogicalDpiY);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_CLEAR record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.4.1, Microsoft name: EmfPlusClear Record, Index 0x09
+*/
+int U_PMR_CLEAR_print(const char *contents){
+ U_PMF_ARGB Color;
+ int status = U_PMR_CLEAR_get(contents, NULL, &Color);
+ if(status){
+ /* try to print it, but only ASCII, bail on anything that is not ASCII */
+ printf(" + Color:");
+ (void) U_PMF_ARGB_print((char *) &Color);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_DRAWARC record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.4.2, Microsoft name: EmfPlusDrawArc Record, Index 0x12
+*/
+int U_PMR_DRAWARC_print(const char *contents){
+ uint32_t PenID;
+ int ctype;
+ U_FLOAT Start, Sweep;
+ U_PMF_RECTF Rect;
+ int status = U_PMR_DRAWARC_get(contents, NULL, &PenID, &ctype, &Start, &Sweep, &Rect);
+ if(status){
+ printf(" + PenID:%u ctype:%d Start:%f Sweep:%f Rect:", PenID,ctype,Start,Sweep);
+ (void) U_PMF_VARRECTF_S_print(&Rect, 1);
+ printf("\n");
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_DRAWBEZIERS record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.4.3, Microsoft name: EmfPlusDrawBeziers Record, Index 0x19
+*/
+int U_PMR_DRAWBEZIERS_print(const char *contents){
+ uint32_t PenID;
+ int ctype, RelAbs;
+ uint32_t Elements;
+ U_PMF_POINTF *Points;
+ int status = U_PMR_DRAWBEZIERS_get(contents, NULL, &PenID, &ctype, &RelAbs, &Elements, &Points);
+ if(status){
+ printf(" + PenIdx:%u ctype:%d RelAbs:%d Elements:%u\n", PenID, ctype, RelAbs, Elements);
+ U_PMF_VARPOINTF_S_print(Points, Elements);
+ free(Points);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_DRAWCLOSEDCURVE record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+
+ Curve is a cardinal spline.
+ References sent by MS support:
+ http://alvyray.com/Memos/CG/Pixar/spline77.pdf
+ http://msdn.microsoft.com/en-us/library/4cf6we5y(v=vs.110).aspx
+
+ EMF+ manual 2.3.4.4, Microsoft name: EmfPlusDrawClosedCurve Record, Index 0x17
+*/
+int U_PMR_DRAWCLOSEDCURVE_print(const char *contents){
+ uint32_t PenID;
+ int ctype, RelAbs;
+ U_FLOAT Tension;
+ uint32_t Elements;
+ U_PMF_POINTF *Points;
+ int status = U_PMR_DRAWCLOSEDCURVE_get(contents, NULL, &PenID, &ctype, &RelAbs, &Tension, &Elements, &Points);
+ if(status){
+ printf(" + PenID:%u ctype:%d RelAbs:%d Tension:%f\n", PenID, ctype, RelAbs, Tension);
+ U_PMF_VARPOINTF_S_print(Points, Elements);
+ free(Points);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_DRAWCURVE record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+
+ Curve is a cardinal spline, using doubled terminator points to generate curves for the terminal segments.
+ References sent by MS support:
+ http://alvyray.com/Memos/CG/Pixar/spline77.pdf
+ http://msdn.microsoft.com/en-us/library/4cf6we5y(v=vs.110).aspx
+
+ EMF+ manual 2.3.4.5, Microsoft name: EmfPlusDrawCurve Record, Index 0x18
+*/
+int U_PMR_DRAWCURVE_print(const char *contents){
+ uint32_t PenID;
+ int ctype;
+ U_FLOAT Tension;
+ uint32_t Offset, NSegs, Elements;
+ U_PMF_POINTF *Points;
+ int status = U_PMR_DRAWCURVE_get(contents, NULL, &PenID, &ctype, &Tension, &Offset, &NSegs, &Elements, &Points);
+ if(status){
+ printf(" + PenID:%u ctype:%d Tension:%f Offset:%u NSegs:%u Elements:%u\n", PenID, ctype, Tension, Offset, NSegs, Elements);
+ U_PMF_VARPOINTF_S_print(Points, Elements);
+ free(Points);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_DRAWDRIVERSTRING record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.4.6, Microsoft name: EmfPlusDrawDriverString Record, Index 0x36
+*/
+int U_PMR_DRAWDRIVERSTRING_print(const char *contents){
+ unsigned int i;
+ uint32_t FontID;
+ int btype;
+ uint32_t BrushID, DSOFlags, HasMatrix, Elements;
+ uint16_t *Glyphs;
+ uint16_t *GlyphsIter;
+ U_PMF_POINTF *Points;
+ U_PMF_TRANSFORMMATRIX *Matrix;
+ int status = U_PMR_DRAWDRIVERSTRING_get(contents, NULL, &FontID, &btype,
+ &BrushID, &DSOFlags, &HasMatrix, &Elements,&Glyphs, &Points, &Matrix);
+ if(status){
+ printf(" + FontID:%u btype:%d BrushID:%u DSOFlags:%X Elements:%u\n", FontID,btype, BrushID, DSOFlags, Elements);
+
+ printf(" + Glyphs:");
+ if(*Glyphs){
+ for(GlyphsIter=Glyphs, i=0; i<Elements;i++, GlyphsIter++){ printf(" %u",*GlyphsIter); }
+ free(Glyphs);
+ }
+ else {
+ printf("(none)");
+ }
+ printf("\n");
+
+ printf(" + Positions:\n");
+ if(Points){
+ U_PMF_VARPOINTF_S_print(Points, Elements);
+ free(Points);
+ }
+ else {
+ printf("(none)\n");
+ }
+
+ if(Matrix){
+ printf(" + ");
+ U_PMF_TRANSFORMMATRIX2_print(Matrix);
+ free(Matrix);
+ printf("\n");
+ }
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_DRAWELLIPSE record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.4.7, Microsoft name: EmfPlusDrawEllipse Record, Index 0x0F
+*/
+int U_PMR_DRAWELLIPSE_print(const char *contents){
+ uint32_t PenID;
+ int ctype;
+ U_PMF_RECTF Rect;
+ int status = U_PMR_DRAWELLIPSE_get(contents, NULL, &PenID, &ctype, &Rect);
+ if(status){
+ printf(" + PenID:%u ctype:%d", PenID,ctype);
+ (void) U_PMF_VARRECTF_S_print(&Rect, 1);
+ printf("\n");
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_DRAWIMAGE record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.4.8, Microsoft name: EmfPlusDrawImage Record, Index 0x1A
+*/
+int U_PMR_DRAWIMAGE_print(const char *contents){
+ uint32_t ImgID, ImgAttrID;
+ int ctype;
+ int32_t SrcUnit;
+ U_PMF_RECTF SrcRect;
+ U_PMF_RECTF DstRect;
+ int status = U_PMR_DRAWIMAGE_get(contents, NULL, &ImgID, &ctype, &ImgAttrID, &SrcUnit, &SrcRect, &DstRect);
+ if(status){
+ printf(" + ImgID:%u ctype:%d ImgAttrID:%u SrcUnit:%d SrcRect:", ImgID, ctype, ImgAttrID, SrcUnit);
+ (void) U_PMF_RECTF_S_print(&SrcRect);
+ printf(" DstRect:");
+ (void) U_PMF_RECTF_S_print(&DstRect);
+ printf("\n");
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_DRAWIMAGEPOINTS record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.4.9, Microsoft name: EmfPlusDrawImagePoints Record, Index 0x1B
+*/
+int U_PMR_DRAWIMAGEPOINTS_print(const char *contents){
+ uint32_t ImgID, ImgAttrID;
+ int ctype, etype, RelAbs;
+ int32_t SrcUnit;
+ U_PMF_RECTF SrcRect;
+ uint32_t Elements;
+ U_PMF_POINTF *Points;
+ int status = U_PMR_DRAWIMAGEPOINTS_get(contents, NULL, &ImgID, &ctype, &etype, &RelAbs,
+ &ImgAttrID, &SrcUnit, &SrcRect, &Elements, &Points);
+ if(status){
+ printf(" + ImgID:%u ctype:%d etype:%d ImgAttrID:%u SrcUnit:%d Elements:%u SrcRect:",
+ ImgID, ctype, etype, ImgAttrID, SrcUnit, Elements);
+ (void) U_PMF_RECTF_S_print(&SrcRect);
+ printf("\n");
+ U_PMF_VARPOINTF_S_print(Points, Elements);
+ free(Points);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+
+/**
+ \brief Print data from a U_PMR_DRAWLINES record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.4.10, Microsoft name: EmfPlusDrawLines Record, Index 0x0D
+*/
+int U_PMR_DRAWLINES_print(const char *contents){
+ uint32_t PenIdx;
+ int ctype, dtype, RelAbs;
+ uint32_t Elements;
+ U_PMF_POINTF *Points;
+ int status = U_PMR_DRAWLINES_get(contents, NULL, &PenIdx, &ctype, &dtype, &RelAbs, &Elements, &Points);
+ if(status){
+ printf(" + PenIdx:%d ctype:%d dtype:%d RelAbs:%d\n", PenIdx,ctype,dtype,RelAbs);
+ U_PMF_VARPOINTF_S_print(Points, Elements);
+ free(Points);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_DRAWPATH record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.4.11, Microsoft name: EmfPlusDrawPath Record, Index 0x15
+*/
+int U_PMR_DRAWPATH_print(const char *contents){
+ uint32_t PathIdx, PenIdx;
+ int status = U_PMR_DRAWPATH_get(contents, NULL, &PathIdx, &PenIdx);
+ if(status){
+ printf(" + PathIdx:%d PenIdx:%d\n", PathIdx, PenIdx);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_DRAWPIE record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.4.12, Microsoft name: EmfPlusDrawPie Record, Index 0x0D
+*/
+int U_PMR_DRAWPIE_print(const char *contents){
+ uint32_t PenID;
+ int ctype;
+ U_FLOAT Start, Sweep;
+ U_PMF_RECTF Rect;
+ int status = U_PMR_DRAWPIE_get(contents, NULL, &PenID, &ctype, &Start, &Sweep, &Rect);
+ if(status){
+ printf(" + PenID:%u ctype:%d Start:%f Sweep:%f Rect:", PenID,ctype,Start,Sweep);
+ (void) U_PMF_VARRECTF_S_print(&Rect, 1);
+ printf("\n");
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_DRAWRECTS record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.4.13, Microsoft name: EmfPlusDrawRects Record, Index 0x0B
+*/
+int U_PMR_DRAWRECTS_print(const char *contents){
+ uint32_t PenID;
+ int ctype;
+ uint32_t Elements;
+ U_PMF_RECTF *Rects=NULL;
+ U_PMF_CMN_HDR hdr;
+ int status = U_PMR_DRAWRECTS_get(contents, &hdr, &PenID, &ctype, &Elements, &Rects);
+ if(status){
+ printf(" + PenID:%u ctype:%d Elements:%u Rect:", PenID,ctype,Elements);
+ (void) U_PMF_VARRECTF_S_print(Rects, Elements);
+ printf("\n");
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ if(Rects)free(Rects);
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_DRAWSTRING record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.4.14, Microsoft name: EmfPlusDrawString Record, Index 0x1C
+*/
+int U_PMR_DRAWSTRING_print(const char *contents){
+ char *String8=NULL;
+ uint32_t FontID, BrushID, FormatID, Length;
+ int btype;
+ U_PMF_RECTF Rect;
+ uint16_t *String16;
+ int status = U_PMR_DRAWSTRING_get(contents, NULL, &FontID, &btype,
+ &BrushID, &FormatID, &Length, &Rect, &String16);
+ if(status){
+ printf(" + FontID:%u StringFormatID:%u btype:%d Length:%u Rect:", FontID, FormatID, btype, Length);
+ (void) U_PMF_RECTF_S_print(&Rect);
+ (void) U_PMF_VARBRUSHID_print(btype, BrushID);
+ if(String16){
+ String8 = U_Utf16leToUtf8(String16, Length, NULL);
+ free(String16);
+ if(String8){
+ printf(" String(as_UTF8):<%s>\n",String8);
+ free(String8);
+ }
+ }
+ else {
+ printf(" String(as_UTF8):(none)\n");
+ }
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_FILLCLOSEDCURVE record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.4.15, Microsoft name: EmfPlusFillClosedCurve Record, Index 0x16
+*/
+int U_PMR_FILLCLOSEDCURVE_print(const char *contents){
+ uint32_t BrushID;
+ int btype, ctype, ftype, RelAbs;
+ U_FLOAT Tension;
+ uint32_t Elements;
+ U_PMF_POINTF *Points;
+ int status = U_PMR_FILLCLOSEDCURVE_get(contents, NULL, &btype, &ctype, &ftype, &RelAbs,
+ &BrushID, &Tension, &Elements, &Points);
+ if(status){
+ printf(" + btype:%d ctype:%d ftype:%d RelAbs:%d Elements:%u",
+ btype, ctype, ftype, RelAbs, Elements);
+ (void) U_PMF_VARBRUSHID_print(btype, BrushID);
+ printf("\n");
+ U_PMF_VARPOINTF_S_print(Points, Elements);
+ free(Points);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+
+/**
+ \brief Print data from a U_PMR_FILLELLIPSE record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.4.16, Microsoft name: EmfPlusFillEllipse Record, Index 0x0E
+*/
+int U_PMR_FILLELLIPSE_print(const char *contents){
+ int btype, ctype;
+ uint32_t BrushID;
+ U_PMF_RECTF Rect;
+ int status = U_PMR_FILLELLIPSE_get(contents, NULL, &btype, &ctype, &BrushID, &Rect);
+ if(status){
+ printf(" + btype:%d ctype:%d",btype,ctype);
+ (void) U_PMF_VARBRUSHID_print(btype, BrushID);
+ (void) U_PMF_VARRECTF_S_print(&Rect, 1);
+ printf("\n");
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_FILLPATH record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.4.17, Microsoft name: EmfPlusFillPath Record, Index 0x14
+*/
+int U_PMR_FILLPATH_print(const char *contents){
+ int btype;
+ uint32_t PathID, BrushID;
+ int status = U_PMR_FILLPATH_get(contents, NULL, &PathID, &btype, &BrushID);
+ if(status){
+ printf(" + PathID:%u btype:%d",PathID, btype);
+ (void) U_PMF_VARBRUSHID_print(btype, BrushID);
+ printf("\n");
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_FILLPIE record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.4.18, Microsoft name: EmfPlusFillPie Record, Index 0x10
+*/
+int U_PMR_FILLPIE_print(const char *contents){
+ int btype, ctype;
+ U_FLOAT Start, Sweep;
+ uint32_t BrushID;
+ U_PMF_RECTF Rect;
+ int status = U_PMR_FILLPIE_get(contents, NULL, &btype, &ctype, &BrushID, &Start, &Sweep, &Rect);
+ if(status){
+ printf(" + btype:%d ctype:%d",btype,ctype);
+ (void) U_PMF_VARBRUSHID_print(btype, BrushID);
+ (void) U_PMF_VARRECTF_S_print(&Rect, 1);
+ printf("\n");
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_FILLPOLYGON record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.4.19, Microsoft name: EmfPlusFillPolygon Record, Index 0x0C
+*/
+int U_PMR_FILLPOLYGON_print(const char *contents){
+ int btype, ctype, RelAbs;
+ uint32_t BrushID, Elements;
+ U_PMF_POINTF *Points;
+ int status = U_PMR_FILLPOLYGON_get(contents, NULL, &btype, &ctype, &RelAbs, &BrushID, &Elements, &Points);
+ if(status){
+ printf(" + btype:%d ctype:%d RelAbs:%d Elements:%u",btype,ctype,RelAbs,Elements);
+ (void) U_PMF_VARBRUSHID_print(btype, BrushID);
+ printf("\n");
+ U_PMF_VARPOINTF_S_print(Points, Elements);
+ free(Points);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_FILLRECTS record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.4.20, Microsoft name: EmfPlusFillRects Record, Index 0x0A
+*/
+int U_PMR_FILLRECTS_print(const char *contents){
+ int btype, ctype;
+ uint32_t BrushID, Elements;
+ U_PMF_RECTF *Rects;
+ U_PMF_CMN_HDR hdr;
+ int status = U_PMR_FILLRECTS_get(contents, &hdr, &btype,&ctype, &BrushID, &Elements, &Rects);
+ if(status){
+ printf(" + btype:%d ctype:%d Elements:%u",btype,ctype,Elements);
+ (void) U_PMF_VARBRUSHID_print(btype, BrushID);
+ (void) U_PMF_VARRECTF_S_print(Rects, Elements);
+ free(Rects);
+ printf("\n");
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_FILLREGION record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.4.21, Microsoft name: EmfPlusFillRegion Record, Index 0x13
+*/
+int U_PMR_FILLREGION_print(const char *contents){
+ uint32_t RgnID, BrushID;
+ int btype, ctype;
+ int status = U_PMR_FILLREGION_get(contents, NULL, &RgnID, &btype, &ctype, &BrushID);
+ if(status){
+ printf(" + RgnID:%u btype:%d ctype:%d", RgnID, btype, ctype);
+ (void) U_PMF_VARBRUSHID_print(btype, BrushID);
+ printf("\n");
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_OBJECT record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ \param blimit One byte past the last record in memory.
+ \param ObjCont Structure that holds accumulated object.
+ \param term Flag used when an abnormal termination of a series of continuation records is encountered.
+ EMF+ manual 2.3.5.1, Microsoft name: EmfPlusObject Record, Index 0x13
+
+ This is the ONLY EMF+ record type which needs an explicit blimit passed in. Since it glues
+ together multiple records, and calls itself recursively, the initial caller cannot determine
+ that all of the sizes will be OK from the first record's header.
+*/
+int U_PMR_OBJECT_print(const char *contents, const char *blimit, U_OBJ_ACCUM *ObjCont, int term){
+ U_PMF_CMN_HDR Header;
+ uint32_t ObjID;
+ int otype, ntype;
+ uint32_t TSize;
+ const char *Data;
+ int ttype,status;
+
+//int k; const char *cptr; for(cptr=contents, k=0; k<608;k++,cptr++){ printf("%3.3d %2.2X\n",k,*(uint8_t*)cptr); }; fflush(stdout);
+
+ /* Continued records are a pain. Each contains the total size of the continued object in the first 4 bytes
+ of data. When the total hits that then then the record is complete, even though the continuation bit will
+ still be set on that last record. Check for this and then print the terminated continued series.
+ */
+
+ if(term){ /* mode for handling unexpected end of accumulated object */
+ if(ObjCont->used == 0)return(0); /* no continued object pending */
+ printf(" + START Forced Termination of Accumulating object Bytes:%u ObjID:%u DeclaredType:%d(",
+ ObjCont->used, ObjCont->Id, ObjCont->Type);
+ U_PMF_OBJECTTYPEENUMERATION_print(ObjCont->Type);
+ ttype = ObjCont->Type & 0x3F;
+ printf(")\n");
+ status = 1;
+ }
+ else {
+ status = U_PMR_OBJECT_get(contents, &Header, &ObjID, &otype, &ntype, &TSize, &Data);
+ /* In a corrupt EMF+ file we might hit a new type of record before all the continuation records
+ expected have been found. If that happens terminate whatever we have accumulated so far, and then go on
+ to emit the new (unexpected) record. */
+ if(IS_MEM_UNSAFE(contents, Header.Size, blimit))return(0);
+ if(!status){
+ printf(" corrupt record\n");
+ return(status);
+ }
+ if((ObjCont->used > 0) && (U_OA_append(ObjCont, NULL, 0, otype, ObjID) < 0)){
+ U_PMR_OBJECT_print(contents, blimit, ObjCont, 1);
+ }
+ printf(" + ObjID:%u ObjType:%d(", ObjID, otype);
+ U_PMF_OBJECTTYPEENUMERATION_print(otype);
+ printf(") ntype:%d", ntype);
+ printf(" ContinueD:%c",( ObjCont->used ? 'Y' : 'N'));
+ printf(" ContinueB:%c",( ntype ? 'Y' : 'N'));
+ if(ntype){
+ U_OA_append(ObjCont, Data, Header.DataSize - 4, otype, ObjID); // The total byte count is not added to the object
+ printf(" TotalSize:%u",TSize);
+ printf(" Accumulated:%u",ObjCont->used);
+ }
+ else {
+ U_OA_append(ObjCont, Data, Header.DataSize, otype, ObjID); // The total byte count is not added to the object
+ }
+ printf("\n");
+ if(ntype && ObjCont->used < TSize)return(status);
+ /* preceding terminates any continued series for >= accumulated bytes */
+ ttype = otype;
+ }
+ if(status){
+ blimit = ObjCont->accum + ObjCont->used; /* more restrictive blimit, just to end of object */
+ switch(ttype){
+ case U_OT_Brush: (void) U_PMF_BRUSH_print(ObjCont->accum, blimit); break;
+ case U_OT_Pen: (void) U_PMF_PEN_print(ObjCont->accum, blimit); break;
+ case U_OT_Path: (void) U_PMF_PATH_print(ObjCont->accum, blimit); break;
+ case U_OT_Region: (void) U_PMF_REGION_print(ObjCont->accum, blimit); break;
+ case U_OT_Image: (void) U_PMF_IMAGE_print(ObjCont->accum, blimit); break;
+ case U_OT_Font: (void) U_PMF_FONT_print(ObjCont->accum, blimit); break;
+ case U_OT_StringFormat: (void) U_PMF_STRINGFORMAT_print(ObjCont->accum, blimit); break;
+ case U_OT_ImageAttributes: (void) U_PMF_IMAGEATTRIBUTES_print(ObjCont->accum, blimit); break;
+ case U_OT_CustomLineCap: (void) U_PMF_CUSTOMLINECAP_print(ObjCont->accum,"", blimit); break;
+ case U_OT_Invalid:
+ default:
+ printf("INVALID OBJECT TYPE!!!!\n");
+ break;
+ }
+ U_OA_clear(ObjCont);
+ }
+ if(term)printf(" + END Forced Termination of Accumulating object\n");
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_SERIALIZABLEOBJECT record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.5.2, Microsoft name: EmfPlusSerializableObject Record, Index 0x38
+*/
+int U_PMR_SERIALIZABLEOBJECT_print(const char *contents){
+ uint8_t GUID[16];
+ uint32_t Size;
+ const char *Data;
+ char *string=NULL;
+ int iee;
+ int status = U_PMR_SERIALIZABLEOBJECT_get(contents, NULL, &GUID[0], &Size, &Data);
+ if(status){
+ string = U_PMF_CURLYGUID_set(&GUID[0]);
+ if(string){
+ printf(" + GUID:%s Size:%u",string,Size);
+ iee = U_PMF_KNOWNCURLYGUID_set(string); /* overwrites string with short text form */
+ printf("\n + Effect:");
+ free(string);
+ switch(iee){
+ case U_IEE_Unknown: printf("(undefined)\n"); break;
+ case U_IEE_BlurEffectGuid: U_PMF_IE_BLUR_print(Data, Data + sizeof(U_PMF_IE_BLUR)); break;
+ case U_IEE_BrightnessContrastEffectGuid: U_PMF_IE_BRIGHTNESSCONTRAST_print(Data, Data + sizeof(U_PMF_IE_BRIGHTNESSCONTRAST)); break;
+ case U_IEE_ColorBalanceEffectGuid: U_PMF_IE_COLORBALANCE_print(Data, Data + sizeof(U_PMF_IE_COLORBALANCE)); break;
+ case U_IEE_ColorCurveEffectGuid: U_PMF_IE_COLORCURVE_print(Data, Data + sizeof(U_PMF_IE_COLORCURVE)); break;
+ case U_IEE_ColorLookupTableEffectGuid: U_PMF_IE_COLORLOOKUPTABLE_print(Data, Data + sizeof(U_PMF_IE_COLORLOOKUPTABLE)); break;
+ case U_IEE_ColorMatrixEffectGuid: U_PMF_IE_COLORMATRIX_print(Data, Data + sizeof(U_PMF_IE_COLORMATRIX)); break;
+ case U_IEE_HueSaturationLightnessEffectGuid: U_PMF_IE_HUESATURATIONLIGHTNESS_print(Data, Data + sizeof(U_PMF_IE_HUESATURATIONLIGHTNESS)); break;
+ case U_IEE_LevelsEffectGuid: U_PMF_IE_LEVELS_print(Data, Data + sizeof(U_PMF_IE_LEVELS)); break;
+ case U_IEE_RedEyeCorrectionEffectGuid: U_PMF_IE_REDEYECORRECTION_print(Data, Data + sizeof(U_PMF_IE_REDEYECORRECTION)); break;
+ case U_IEE_SharpenEffectGuid: U_PMF_IE_SHARPEN_print(Data, Data + sizeof(U_PMF_IE_SHARPEN)); break;
+ case U_IEE_TintEffectGuid: U_PMF_IE_TINT_print(Data, Data + sizeof(U_PMF_IE_TINT)); break;
+ }
+ }
+ else {
+ printf(" + GUID:ERROR Size:%u\n",Size);
+ }
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_SETANTIALIASMODE record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.6.1, Microsoft name: EmfPlusSetAntiAliasMode Record, Index 0x1E
+*/
+int U_PMR_SETANTIALIASMODE_print(const char *contents){
+ int SMenum, aatype;
+ int status = U_PMR_SETANTIALIASMODE_get(contents, NULL, &SMenum, &aatype);
+ if(status){
+ printf(" + SMenum:%d AntiAlias:%c\n",SMenum,(aatype ? 'Y' : 'N'));
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_SETCOMPOSITINGMODE record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.6.2, Microsoft name: EmfPlusSetCompositingMode Record, Index 0x23
+*/
+int U_PMR_SETCOMPOSITINGMODE_print(const char *contents){
+ int CMenum;
+ int status = U_PMR_SETCOMPOSITINGMODE_get(contents, NULL, &CMenum);
+ if(status){
+ printf(" + CMenum:%d\n",CMenum);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_SETCOMPOSITINGQUALITY record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.6.3, Microsoft name: EmfPlusSetCompositingQuality Record, Index 0x24
+*/
+int U_PMR_SETCOMPOSITINGQUALITY_print(const char *contents){
+ int CQenum;
+ int status = U_PMR_SETCOMPOSITINGQUALITY_get(contents, NULL, &CQenum);
+ if(status){
+ printf(" + CQenum:%d\n",CQenum);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_SETINTERPOLATIONMODE record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.6.4, Microsoft name: EmfPlusSetInterpolationMode Record, Index 0x21
+*/
+int U_PMR_SETINTERPOLATIONMODE_print(const char *contents){
+ int IMenum;
+ int status = U_PMR_SETINTERPOLATIONMODE_get(contents, NULL, &IMenum);
+ if(status){
+ printf(" + IMenum:%d\n",IMenum);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_SETPIXELOFFSETMODE record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.6.5, Microsoft name: EmfPlusSetPixelOffsetMode Record, Index 0x22
+*/
+int U_PMR_SETPIXELOFFSETMODE_print(const char *contents){
+ int POMenum;
+ int status = U_PMR_SETPIXELOFFSETMODE_get(contents, NULL, &POMenum);
+ if(status){
+ printf(" + POMenum:%d\n",POMenum);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_SETRENDERINGORIGIN record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.6.6, Microsoft name: EmfPlusSetRenderingOrigin Record, Index 0x1D
+*/
+int U_PMR_SETRENDERINGORIGIN_print(const char *contents){
+ int32_t X, Y;
+ int status = U_PMR_SETRENDERINGORIGIN_get(contents, NULL, &X, &Y);
+ if(status){
+ printf(" + X:%d Y:%d\n", X, Y);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_SETTEXTCONTRAST record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.6.7, Microsoft name: EmfPlusSetTextContrast Record, Index 0x20
+*/
+int U_PMR_SETTEXTCONTRAST_print(const char *contents){
+ int GC;
+ int status = U_PMR_SETTEXTCONTRAST_get(contents, NULL, &GC);
+ if(status){
+ printf(" + GC:%d\n", GC);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_SETTEXTRENDERINGHINT record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.6.8, Microsoft name: EmfPlusSetTextRenderingHint Record, Index 0x1F
+*/
+int U_PMR_SETTEXTRENDERINGHINT_print(const char *contents){
+ int TRHenum;
+ int status = U_PMR_SETTEXTRENDERINGHINT_get(contents, NULL, &TRHenum);
+ if(status){
+ printf(" + TRHenum:%d\n",TRHenum);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_BEGINCONTAINER record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.7.1, Microsoft name: EmfPlusBeginContainer Record, Index 0x27
+*/
+int U_PMR_BEGINCONTAINER_print(const char *contents){
+ int UTenum;
+ U_PMF_RECTF DstRect, SrcRect;
+ uint32_t StackID;
+ int status = U_PMR_BEGINCONTAINER_get(contents, NULL, &UTenum, &DstRect, &SrcRect, &StackID);
+ if(status){
+ printf(" + UTenum:%d",UTenum);
+ printf(" DstRect:"); (void) U_PMF_RECTF_S_print(&DstRect);
+ printf(" SrcRect:"); (void) U_PMF_RECTF_S_print(&SrcRect);
+ printf(" StackID:%u\n", StackID);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_BEGINCONTAINERNOPARAMS record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.7.2, Microsoft name: EmfPlusBeginContainerNoParams Record, Index 0x28
+*/
+int U_PMR_BEGINCONTAINERNOPARAMS_print(const char *contents){
+ uint32_t StackID;
+ int status = U_PMR_BEGINCONTAINERNOPARAMS_get(contents, NULL, &StackID);
+ if(status){
+ printf(" + StackID:%u\n", StackID);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_ENDCONTAINER record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.7.3, Microsoft name: EmfPlusEndContainer Record, Index 0x29
+*/
+int U_PMR_ENDCONTAINER_print(const char *contents){
+ uint32_t StackID;
+ int status = U_PMR_ENDCONTAINER_get(contents, NULL, &StackID);
+ if(status){
+ printf(" + StackID:%u\n", StackID);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_RESTORE record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.7.4, Microsoft name: EmfPlusRestore Record, Index 0x26
+*/
+int U_PMR_RESTORE_print(const char *contents){
+ uint32_t StackID;
+ int status = U_PMR_RESTORE_get(contents, NULL, &StackID);
+ if(status){
+ printf(" + StackID:%u\n", StackID);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_SAVE record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.7.5, Microsoft name: EmfPlusSave Record, Index 0x25
+*/
+int U_PMR_SAVE_print(const char *contents){
+ uint32_t StackID;
+ int status = U_PMR_SAVE_get(contents, NULL, &StackID);
+ if(status){
+ printf(" + StackID:%u\n", StackID);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_SETTSCLIP record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.8.1, Microsoft name: EmfPlusSetTSClip Record, Index 0x3A
+*/
+int U_PMR_SETTSCLIP_print(const char *contents){
+ int ctype;
+ uint32_t Elements;
+ U_PMF_RECTF *Rects;
+ int status = U_PMR_SETTSCLIP_get(contents, NULL, &ctype, &Elements, &Rects);
+ if(status){
+ printf(" + ctype:%d Elements:%u",ctype,Elements);
+ (void) U_PMF_VARRECTF_S_print(Rects, Elements);
+ free(Rects);
+ printf("\n");
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_SETTSGRAPHICS record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.8.2, Microsoft name: EmfPlusSetTSGraphics Record, Index 0x39
+*/
+int U_PMR_SETTSGRAPHICS_print(const char *contents){
+ int vgatype, pptype;
+ uint8_t AntiAliasMode, TextRenderHint, CompositingMode, CompositingQuality, FilterType, PixelOffset;
+ int16_t RenderOriginX, RenderOriginY;
+ uint16_t TextContrast;
+ U_PMF_TRANSFORMMATRIX WorldToDevice;
+ const char *Data;
+ int status = U_PMR_SETTSGRAPHICS_get(contents, NULL,
+ &vgatype, &pptype,
+ &AntiAliasMode, &TextRenderHint, &CompositingMode, &CompositingQuality,
+ &RenderOriginX, &RenderOriginY, &TextContrast, &FilterType,
+ &PixelOffset, &WorldToDevice, &Data);
+ if(status){
+ const char *blimit = contents + status;
+ printf(" + vgatype:%d pptype:%u",vgatype,pptype);
+ printf(" AntiAliasMode:%u TextRenderHint:%u CompositingMode:%u CompositingQuality:%u",
+ AntiAliasMode, TextRenderHint, CompositingMode, CompositingQuality);
+ printf(" RenderOriginX:%d RenderOriginY:%d",RenderOriginX, RenderOriginY);
+ printf(" TextContrast:%u",TextContrast);
+ printf(" WorldToDevice:");
+ U_PMF_TRANSFORMMATRIX2_print(&WorldToDevice);
+ if(pptype && !U_PMF_PALETTE_print(Data, blimit))return(0);
+ printf("\n");
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+
+/**
+ \brief Print data from a U_PMR_MULTIPLYWORLDTRANSFORM record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.9.1, Microsoft name: EmfPlusMultiplyWorldTransform Record, Index 0x2C
+*/
+int U_PMR_MULTIPLYWORLDTRANSFORM_print(const char *contents){
+ int xmtype;
+ U_PMF_TRANSFORMMATRIX Matrix;
+ int status = U_PMR_MULTIPLYWORLDTRANSFORM_get(contents, NULL, &xmtype, &Matrix);
+ if(status){
+ printf(" + xmtype:%d Multiply:%s",xmtype,(xmtype ? "Post" : "Pre"));
+ U_PMF_TRANSFORMMATRIX2_print(&Matrix);
+ printf("\n");
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_RESETWORLDTRANSFORM record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.9.2, Microsoft name: EmfPlusResetWorldTransform Record, Index 0x2B
+*/
+int U_PMR_RESETWORLDTRANSFORM_print(const char *contents){
+ return(U_PMR_NODATAREC_print(contents));
+}
+
+/**
+ \brief Print data from a U_PMR_ROTATEWORLDTRANSFORM record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.9.3, Microsoft name: EmfPlusRotateWorldTransform Record, Index 0x2F
+*/
+int U_PMR_ROTATEWORLDTRANSFORM_print(const char *contents){
+ int xmtype;
+ U_FLOAT Angle;
+ int status = U_PMR_ROTATEWORLDTRANSFORM_get(contents, NULL, &xmtype, &Angle);
+ if(status){
+ printf(" + xmtype:%d Multiply:%s Angle:%f\n",xmtype,(xmtype ? "Post" : "Pre"), Angle);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_SCALEWORLDTRANSFORM record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.9.4, Microsoft name: EmfPlusScaleWorldTransform Record, Index 0x2E
+*/
+int U_PMR_SCALEWORLDTRANSFORM_print(const char *contents){
+ int xmtype;
+ U_FLOAT Sx, Sy;
+ int status = U_PMR_SCALEWORLDTRANSFORM_get(contents, NULL, &xmtype, &Sx, &Sy);
+ if(status){
+ printf(" + xmtype:%d Multiply:%s ScaleX:%f ScaleY:%f\n",xmtype,(xmtype ? "Post" : "Pre"), Sx, Sy);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_SETPAGETRANSFORM record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.9.5, Microsoft name: EmfPlusSetPageTransform Record, Index 0x30
+*/
+int U_PMR_SETPAGETRANSFORM_print(const char *contents){
+ int UTenum;
+ U_FLOAT Scale;
+ int status = U_PMR_SETPAGETRANSFORM_get(contents, NULL, &UTenum, &Scale);
+ if(status){
+ printf(" + UTenum:%d Scale:%f\n",UTenum, Scale);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_SETWORLDTRANSFORM record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.9.6, Microsoft name: EmfPlusSetWorldTransform Record, Index 0x2A
+*/
+int U_PMR_SETWORLDTRANSFORM_print(const char *contents){
+ U_PMF_TRANSFORMMATRIX Matrix;
+ int status = U_PMR_SETWORLDTRANSFORM_get(contents, NULL, &Matrix);
+ if(status){
+ printf(" + ");
+ U_PMF_TRANSFORMMATRIX2_print(&Matrix);
+ printf("\n");
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+/**
+ \brief Print data from a U_PMR_TRANSLATEWORLDTRANSFORM record
+ \return size of record in bytes on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual 2.3.9.7, Microsoft name: EmfPlusTranslateWorldTransform Record, Index 0x2D
+*/
+int U_PMR_TRANSLATEWORLDTRANSFORM_print(const char *contents){
+ int xmtype;
+ U_FLOAT Dx, Dy;
+ int status = U_PMR_TRANSLATEWORLDTRANSFORM_get(contents, NULL, &xmtype, &Dx, &Dy);
+ if(status){
+ printf(" + xmtype:%d Multiply:%s TranslateX:%f TranlateY:%f\n",xmtype,(xmtype ? "Post" : "Pre"), Dx, Dy);
+ }
+ else {
+ printf(" corrupt record\n");
+ }
+ return(status);
+}
+
+
+/**
+ \brief Print data from a U_PMR_STROKEFILLPATH record
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+*/
+int U_PMR_STROKEFILLPATH_print(const char *contents){
+ return(U_PMR_NODATAREC_print(contents));
+}
+
+/**
+ \brief Print data from a U_PMR_MULTIFORMATSTART record
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual mentioned in 2.1.1.1, reserved, not otherwise documented, Microsoft name: EmfPlusMultiFormatStart Record, Index 0x05
+*/
+int U_PMR_MULTIFORMATSTART_print(const char *contents){
+ return(U_PMR_NODATAREC_print(contents));
+}
+
+/**
+ \brief Print data from a U_PMR_MULTIFORMATSECTION record
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual mentioned in 2.1.1.1, reserved, not otherwise documented, Microsoft name: EmfPlusMultiFormatSection Record, Index 0x06
+*/
+int U_PMR_MULTIFORMATSECTION_print(const char *contents){
+ return(U_PMR_NODATAREC_print(contents));
+}
+
+/**
+ \brief Print data from a U_PMR_MULTIFORMATEND record
+ \return 1 on success, 0 on error
+ \param contents Record from which to print data
+ EMF+ manual mentioned in 2.1.1.1, reserved, not otherwise documented, Microsoft name: EmfPlusMultiFormatEnd Record, Index 0x06
+*/
+int U_PMR_MULTIFORMATEND_print(const char *contents){
+ return(U_PMR_NODATAREC_print(contents));
+}
+
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/3rdparty/libuemf/upmf_print.h b/src/3rdparty/libuemf/upmf_print.h
new file mode 100644
index 0000000..a253744
--- /dev/null
+++ b/src/3rdparty/libuemf/upmf_print.h
@@ -0,0 +1,181 @@
+/**
+ @file upmf_print.h
+
+ @brief Prototypes for functions for printing records from EMF files.
+*/
+
+/*
+File: upmf_print.h
+Version: 0.0.5
+Date: 28-APR-2015
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2015 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifndef _UPMF_PRINT_
+#define _UPMF_PRINT_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "upmf.h" /* includes uemf.h */
+
+/* prototypes for simple types and enums used in PMR records */
+int U_PMF_CMN_HDR_print(const char *contents, U_PMF_CMN_HDR Header, int precnum, int off);
+int U_PMF_UINT8_ARRAY_print(const char *Start, const uint8_t *Array, int Elements, char *End);
+int U_PMF_BRUSHTYPEENUMERATION_print(int otype);
+int U_PMF_HATCHSTYLEENUMERATION_print(int hstype);
+int U_PMF_OBJECTTYPEENUMERATION_print(int otype);
+int U_PMF_PATHPOINTTYPE_ENUM_print(int Type);
+int U_PMF_PX_FMT_ENUM_print(int pfe);
+int U_PMF_NODETYPE_print(int Type);
+
+/* prototypes for objects used in PMR records */
+int U_PMF_BRUSH_print(const char *contents, const char *blimit);
+int U_PMF_CUSTOMLINECAP_print(const char *contents, const char *Which, const char *blimit);
+int U_PMF_FONT_print(const char *contents, const char *blimit);
+int U_PMF_IMAGE_print(const char *contents, const char *blimit);
+int U_PMF_IMAGEATTRIBUTES_print(const char *contents, const char *blimit);
+int U_PMF_PATH_print(const char *contents, const char *blimit);
+int U_PMF_PEN_print(const char *contents, const char *blimit);
+int U_PMF_REGION_print(const char *contents, const char *blimit);
+int U_PMF_STRINGFORMAT_print(const char *contents, const char *blimit);
+int U_PMF_ARGB_print(const char *contents);
+int U_PMF_BITMAP_print(const char *contents, const char *blimit);
+int U_PMF_BITMAPDATA_print(const char *contents, const char *blimit);
+int U_PMF_BLENDCOLORS_print(const char *contents, const char *blimit);
+int U_PMF_BLENDFACTORS_print(const char *contents, const char *type, const char *blimit);
+int U_PMF_BOUNDARYPATHDATA_print(const char *contents, const char *blimit);
+int U_PMF_BOUNDARYPOINTDATA_print(const char *contents, const char *blimit);
+int U_PMF_CHARACTERRANGE_print(const char *contents, const char *blimit);
+int U_PMF_COMPOUNDLINEDATA_print(const char *contents, const char *blimit);
+int U_PMF_COMPRESSEDIMAGE_print(const char *contents, const char *blimit);
+int U_PMF_CUSTOMENDCAPDATA_print(const char *contents, const char *blimit);
+int U_PMF_CUSTOMLINECAPARROWDATA_print(const char *contents, const char *blimit);
+int U_PMF_CUSTOMLINECAPDATA_print(const char *contents, const char *blimit);
+int U_PMF_CUSTOMLINECAPOPTIONALDATA_print(const char *contents, uint32_t Flags, const char *blimit);
+int U_PMF_CUSTOMSTARTCAPDATA_print(const char *contents, const char *blimit);
+int U_PMF_DASHEDLINEDATA_print(const char *contents, const char *blimit);
+int U_PMF_FILLPATHOBJ_print(const char *contents, const char *blimit);
+int U_PMF_FOCUSSCALEDATA_print(const char *contents, const char *blimit);
+int U_PMF_GRAPHICSVERSION_memsafe_print(const char *contents);
+int U_PMF_GRAPHICSVERSION_print(const char *contents, const char *blimit);
+int U_PMF_HATCHBRUSHDATA_print(const char *contents, const char *blimit);
+int U_PMF_LANGUAGEIDENTIFIER_print(U_PMF_LANGUAGEIDENTIFIER LId);
+int U_PMF_LINEARGRADIENTBRUSHDATA_print(const char *contents, const char *blimit);
+int U_PMF_LINEARGRADIENTBRUSHOPTIONALDATA_print(const char *contents, int BDFlag, const char *blimit);
+int U_PMF_LINEPATH_print(const char *contents, const char *blimit);
+int U_PMF_METAFILE_print(const char *contents, const char *blimit);
+int U_PMF_PALETTE_print(const char *contents, const char *blimit);
+int U_PMF_PATHGRADIENTBRUSHDATA_print(const char *contents, const char *blimit);
+int U_PMF_PATHGRADIENTBRUSHOPTIONALDATA_print(const char *contents, int BDFlag, const char *blimit);
+int U_PMF_PATHPOINTTYPE_print(const char *contents, const char *blimit);
+int U_PMF_PATHPOINTTYPERLE_print(const char *contents, const char *blimit);
+int U_PMF_PENDATA_print(const char *contents, const char *blimit);
+int U_PMF_PENOPTIONALDATA_print(const char *contents, int Flags, const char *blimit);
+int U_PMF_POINT_print(const char **contents, const char *blimit);
+int U_PMF_POINTF_print(const char **contents, const char *blimit);
+int U_PMF_POINTR_print(const char **contents, U_FLOAT *Xpos, U_FLOAT *Ypos, const char *blimit);
+int U_PMF_POINT_S_print(U_PMF_POINT *Point);
+int U_PMF_POINTF_S_print(U_PMF_POINTF *Point);
+int U_PMF_RECT_print(const char **contents, const char *blimit);
+int U_PMF_RECTF_print(const char **contents, const char *blimit);
+int U_PMF_RECT_S_print(U_PMF_RECT *Rect);
+int U_PMF_RECTF_S_print(U_PMF_RECTF *Rect);
+int U_PMF_REGIONNODE_print(const char *contents, int Level, const char *blimit);
+int U_PMF_REGIONNODECHILDNODES_print(const char *contents, int Level, const char *blimit);
+int U_PMF_REGIONNODEPATH_print(const char *contents, const char *blimit);
+int U_PMF_SOLIDBRUSHDATA_print(const char *contents, const char *blimit);
+int U_PMF_STRINGFORMATDATA_print(const char *contents, uint32_t TabStopCount, uint32_t RangeCount, const char *blimit);
+int U_PMF_TEXTUREBRUSHDATA_print(const char *contents, const char *blimit);
+int U_PMF_TEXTUREBRUSHOPTIONALDATA_print(const char *contents, int HasMatrix, int HasImage, const char *blimit);
+int U_PMF_TRANSFORMMATRIX_print(const char *contents, const char *blimit);
+int U_PMF_TRANSFORMMATRIX2_print(U_PMF_TRANSFORMMATRIX *Matrix);
+int U_PMF_ROTMATRIX2_print(U_PMF_ROTMATRIX *Matrix);
+int U_PMF_IE_BLUR_print(const char *contents, const char *blimit);
+int U_PMF_IE_BRIGHTNESSCONTRAST_print(const char *contents, const char *blimit);
+int U_PMF_IE_COLORBALANCE_print(const char *contents, const char *blimit);
+int U_PMF_IE_COLORCURVE_print(const char *contents, const char *blimit);
+int U_PMF_IE_COLORLOOKUPTABLE_print(const char *contents, const char *blimit);
+int U_PMF_IE_COLORMATRIX_print(const char *contents, const char *blimit);
+int U_PMF_IE_HUESATURATIONLIGHTNESS_print(const char *contents, const char *blimit);
+int U_PMF_IE_LEVELS_print(const char *contents, const char *blimit);
+int U_PMF_IE_REDEYECORRECTION_print(const char *contents, const char *blimit);
+int U_PMF_IE_SHARPEN_print(const char *contents, const char *blimit);
+int U_PMF_IE_TINT_print(const char *contents, const char *blimit);
+
+/* prototypes for PMR records */
+int U_PMR_OFFSETCLIP_print(const char *contents);
+int U_PMR_RESETCLIP_print(const char *contents);
+int U_PMR_SETCLIPPATH_print(const char *contents);
+int U_PMR_SETCLIPRECT_print(const char *contents);
+int U_PMR_SETCLIPREGION_print(const char *contents);
+int U_PMR_COMMENT_print(const char *contents);
+int U_PMR_ENDOFFILE_print(const char *contents);
+int U_PMR_GETDC_print(const char *contents);
+int U_PMR_HEADER_print(const char *contents);
+int U_PMR_CLEAR_print(const char *contents);
+int U_PMR_DRAWARC_print(const char *contents);
+int U_PMR_DRAWBEZIERS_print(const char *contents);
+int U_PMR_DRAWCLOSEDCURVE_print(const char *contents);
+int U_PMR_DRAWCURVE_print(const char *contents);
+int U_PMR_DRAWDRIVERSTRING_print(const char *contents);
+int U_PMR_DRAWELLIPSE_print(const char *contents);
+int U_PMR_DRAWIMAGE_print(const char *contents);
+int U_PMR_DRAWIMAGEPOINTS_print(const char *contents);
+int U_PMR_DRAWLINES_print(const char *contents);
+int U_PMR_DRAWPATH_print(const char *contents);
+int U_PMR_DRAWPIE_print(const char *contents);
+int U_PMR_DRAWRECTS_print(const char *contents);
+int U_PMR_DRAWSTRING_print(const char *contents);
+int U_PMR_FILLCLOSEDCURVE_print(const char *contents);
+int U_PMR_FILLELLIPSE_print(const char *contents);
+int U_PMR_FILLPATH_print(const char *contents);
+int U_PMR_FILLPIE_print(const char *contents);
+int U_PMR_FILLPOLYGON_print(const char *contents);
+int U_PMR_FILLRECTS_print(const char *contents);
+int U_PMR_FILLREGION_print(const char *contents);
+int U_PMR_OBJECT_print(const char *contents, const char *blimit, U_OBJ_ACCUM *ObjCont, int term);
+int U_PMR_SERIALIZABLEOBJECT_print(const char *contents);
+int U_PMR_SETANTIALIASMODE_print(const char *contents);
+int U_PMR_SETCOMPOSITINGMODE_print(const char *contents);
+int U_PMR_SETCOMPOSITINGQUALITY_print(const char *contents);
+int U_PMR_SETINTERPOLATIONMODE_print(const char *contents);
+int U_PMR_SETPIXELOFFSETMODE_print(const char *contents);
+int U_PMR_SETRENDERINGORIGIN_print(const char *contents);
+int U_PMR_SETTEXTCONTRAST_print(const char *contents);
+int U_PMR_SETTEXTRENDERINGHINT_print(const char *contents);
+int U_PMR_BEGINCONTAINER_print(const char *contents);
+int U_PMR_BEGINCONTAINERNOPARAMS_print(const char *contents);
+int U_PMR_ENDCONTAINER_print(const char *contents);
+int U_PMR_RESTORE_print(const char *contents);
+int U_PMR_SAVE_print(const char *contents);
+int U_PMR_SETTSCLIP_print(const char *contents);
+int U_PMR_SETTSGRAPHICS_print(const char *contents);
+int U_PMR_MULTIPLYWORLDTRANSFORM_print(const char *contents);
+int U_PMR_RESETWORLDTRANSFORM_print(const char *contents);
+int U_PMR_ROTATEWORLDTRANSFORM_print(const char *contents);
+int U_PMR_SCALEWORLDTRANSFORM_print(const char *contents);
+int U_PMR_SETPAGETRANSFORM_print(const char *contents);
+int U_PMR_SETWORLDTRANSFORM_print(const char *contents);
+int U_PMR_TRANSLATEWORLDTRANSFORM_print(const char *contents);
+int U_PMR_STROKEFILLPATH_print(const char *contents); /* not documented */
+int U_PMR_MULTIFORMATSTART_print(const char *contents); /* last of reserved but not used */
+int U_PMR_MULTIFORMATSECTION_print(const char *contents); /* last of reserved but not used */
+int U_PMR_MULTIFORMATEND_print(const char *contents); /* last of reserved but not used */
+
+int U_pmf_onerec_print(const char *contents, const char *blimit, int recnum, int off);
+
+
+
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UPMF_PRINT_ */
diff --git a/src/3rdparty/libuemf/uwmf.c b/src/3rdparty/libuemf/uwmf.c
new file mode 100644
index 0000000..50e4075
--- /dev/null
+++ b/src/3rdparty/libuemf/uwmf.c
@@ -0,0 +1,7039 @@
+/**
+ @file uwmf.c
+
+ @brief Functions for manipulating WMF files and structures.
+
+ [U_WMR*]_set all take data and return a pointer to memory holding the constructed record.
+ If something goes wrong a NULL pointer is returned.
+ [U_WMR*]_get takes a pointer to memory and returns the length of that record as well
+ as the values from it (in the provided fields, passed by reference.)
+ If something goes wrong, a size of 0 is returned.
+
+ The _set material comes first, then all of the _get material.
+
+ Compile with "U_VALGRIND" defined defined to enable code which lets valgrind check each record for
+ uninitialized data.
+
+ Compile with "SOL8" defined for Solaris 8 or 9 (Sparc).
+*/
+
+/*
+File: uwmf.c
+Version: 0.0.17
+Date: 28-MAR-2015
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2014 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h> /* for offsetof() */
+#include <string.h>
+#include <iconv.h>
+#include <wchar.h>
+#include <errno.h>
+#include <string.h>
+#include <limits.h> // for INT_MAX, INT_MIN
+#include <math.h> // for U_ROUND()
+#if 0
+#include <windef.h> //Not actually used, looking for collisions
+#include <winnt.h> //Not actually used, looking for collisions
+#include <wingdi.h> //Not actually used, looking for collisions
+#endif
+#include "uwmf.h"
+#include "uwmf_endian.h"
+#include "uemf_safe.h"
+
+/**
+ \brief Look up the full numeric type of a WMR record by type.
+
+ \return Full numeric value for this type of WMR record, Returns 0xFFFFFFFF if out of range.
+ \param idx WMR record type.
+
+*/
+uint32_t U_wmr_values(int idx){
+ int ret;
+ int U_WMR_VALUES[256]={
+ 0x0000, //!< U_WMR_EOF
+ 0x0201, //!< U_WMR_SETBKCOLOR
+ 0x0102, //!< U_WMR_SETBKMODE
+ 0x0103, //!< U_WMR_SETMAPMODE
+ 0x0104, //!< U_WMR_SETROP2
+ 0x0105, //!< U_WMR_SETRELABS
+ 0x0106, //!< U_WMR_SETPOLYFILLMODE
+ 0x0107, //!< U_WMR_SETSTRETCHBLTMODE
+ 0x0108, //!< U_WMR_SETTEXTCHAREXTRA
+ 0x0209, //!< U_WMR_SETTEXTCOLOR
+ 0x020A, //!< U_WMR_SETTEXTJUSTIFICATION
+ 0x020B, //!< U_WMR_SETWINDOWORG
+ 0x020C, //!< U_WMR_SETWINDOWEXT
+ 0x020D, //!< U_WMR_SETVIEWPORTORG
+ 0x020E, //!< U_WMR_SETVIEWPORTEXT
+ 0x020F, //!< U_WMR_OFFSETWINDOWORG
+ 0x0410, //!< U_WMR_SCALEWINDOWEXT
+ 0x0211, //!< U_WMR_OFFSETVIEWPORTORG
+ 0x0412, //!< U_WMR_SCALEVIEWPORTEXT
+ 0x0213, //!< U_WMR_LINETO
+ 0x0214, //!< U_WMR_MOVETO
+ 0x0415, //!< U_WMR_EXCLUDECLIPRECT
+ 0x0416, //!< U_WMR_INTERSECTCLIPRECT
+ 0x0817, //!< U_WMR_ARC
+ 0x0418, //!< U_WMR_ELLIPSE
+ 0x0419, //!< U_WMR_FLOODFILL
+ 0x081A, //!< U_WMR_PIE
+ 0x041B, //!< U_WMR_RECTANGLE
+ 0x061C, //!< U_WMR_ROUNDRECT
+ 0x061D, //!< U_WMR_PATBLT
+ 0x001E, //!< U_WMR_SAVEDC
+ 0x041F, //!< U_WMR_SETPIXEL
+ 0x0220, //!< U_WMR_OFFSETCLIPRGN
+ 0x0521, //!< U_WMR_TEXTOUT
+ 0x0922, //!< U_WMR_BITBLT
+ 0x0B23, //!< U_WMR_STRETCHBLT
+ 0x0324, //!< U_WMR_POLYGON
+ 0x0325, //!< U_WMR_POLYLINE
+ 0x0626, //!< U_WMR_ESCAPE
+ 0x0127, //!< U_WMR_RESTOREDC
+ 0x0228, //!< U_WMR_FILLREGION
+ 0x0429, //!< U_WMR_FRAMEREGION
+ 0x012A, //!< U_WMR_INVERTREGION
+ 0x012B, //!< U_WMR_PAINTREGION
+ 0x012C, //!< U_WMR_SELECTCLIPREGION
+ 0x012D, //!< U_WMR_SELECTOBJECT
+ 0x012E, //!< U_WMR_SETTEXTALIGN
+ 0x062F, //!< U_WMR_DRAWTEXT
+ 0x0830, //!< U_WMR_CHORD
+ 0x0231, //!< U_WMR_SETMAPPERFLAGS
+ 0x0A32, //!< U_WMR_EXTTEXTOUT
+ 0x0D33, //!< U_WMR_SETDIBTODEV
+ 0x0234, //!< U_WMR_SELECTPALETTE
+ 0x0035, //!< U_WMR_REALIZEPALETTE
+ 0x0436, //!< U_WMR_ANIMATEPALETTE
+ 0x0037, //!< U_WMR_SETPALENTRIES
+ 0x0538, //!< U_WMR_POLYPOLYGON
+ 0x0139, //!< U_WMR_RESIZEPALETTE
+ 0x003A, //!< U_WMR_3A
+ 0x003B, //!< U_WMR_3B
+ 0x003C, //!< U_WMR_3C
+ 0x003D, //!< U_WMR_3D
+ 0x003E, //!< U_WMR_3E
+ 0x003F, //!< U_WMR_3F
+ 0x0940, //!< U_WMR_DIBBITBLT
+ 0x0B41, //!< U_WMR_DIBSTRETCHBLT
+ 0x0142, //!< U_WMR_DIBCREATEPATTERNBRUSH
+ 0x0F43, //!< U_WMR_STRETCHDIB
+ 0x0044, //!< U_WMR_44
+ 0x0045, //!< U_WMR_45
+ 0x0046, //!< U_WMR_46
+ 0x0047, //!< U_WMR_47
+ 0x0548, //!< U_WMR_EXTFLOODFILL
+ 0x0049, //!< U_WMR_49
+ 0x004A, //!< U_WMR_4A
+ 0x004B, //!< U_WMR_4B
+ 0x014C, //!< U_WMR_4C
+ 0x014D, //!< U_WMR_4D
+ 0x004E, //!< U_WMR_4E
+ 0x004F, //!< U_WMR_4F
+ 0x0050, //!< U_WMR_50
+ 0x0051, //!< U_WMR_51
+ 0x0052, //!< U_WMR_52
+ 0x0053, //!< U_WMR_53
+ 0x0054, //!< U_WMR_54
+ 0x0055, //!< U_WMR_55
+ 0x0056, //!< U_WMR_56
+ 0x0057, //!< U_WMR_57
+ 0x0058, //!< U_WMR_58
+ 0x0059, //!< U_WMR_59
+ 0x005A, //!< U_WMR_5A
+ 0x005B, //!< U_WMR_5B
+ 0x005C, //!< U_WMR_5C
+ 0x005D, //!< U_WMR_5D
+ 0x005E, //!< U_WMR_5E
+ 0x005F, //!< U_WMR_5F
+ 0x0060, //!< U_WMR_60
+ 0x0061, //!< U_WMR_61
+ 0x0062, //!< U_WMR_62
+ 0x0063, //!< U_WMR_63
+ 0x0064, //!< U_WMR_64
+ 0x0065, //!< U_WMR_65
+ 0x0066, //!< U_WMR_66
+ 0x0067, //!< U_WMR_67
+ 0x0068, //!< U_WMR_68
+ 0x0069, //!< U_WMR_69
+ 0x006A, //!< U_WMR_6A
+ 0x006B, //!< U_WMR_6B
+ 0x006C, //!< U_WMR_6C
+ 0x006D, //!< U_WMR_6D
+ 0x006E, //!< U_WMR_6E
+ 0x006F, //!< U_WMR_6F
+ 0x0070, //!< U_WMR_70
+ 0x0071, //!< U_WMR_71
+ 0x0072, //!< U_WMR_72
+ 0x0073, //!< U_WMR_73
+ 0x0074, //!< U_WMR_74
+ 0x0075, //!< U_WMR_75
+ 0x0076, //!< U_WMR_76
+ 0x0077, //!< U_WMR_77
+ 0x0078, //!< U_WMR_78
+ 0x0079, //!< U_WMR_79
+ 0x007A, //!< U_WMR_7A
+ 0x007B, //!< U_WMR_7B
+ 0x007C, //!< U_WMR_7C
+ 0x007D, //!< U_WMR_7D
+ 0x007E, //!< U_WMR_7E
+ 0x007F, //!< U_WMR_7F
+ 0x0080, //!< U_WMR_80
+ 0x0081, //!< U_WMR_81
+ 0x0082, //!< U_WMR_82
+ 0x0083, //!< U_WMR_83
+ 0x0084, //!< U_WMR_84
+ 0x0085, //!< U_WMR_85
+ 0x0086, //!< U_WMR_86
+ 0x0087, //!< U_WMR_87
+ 0x0088, //!< U_WMR_88
+ 0x0089, //!< U_WMR_89
+ 0x008A, //!< U_WMR_8A
+ 0x008B, //!< U_WMR_8B
+ 0x008C, //!< U_WMR_8C
+ 0x008D, //!< U_WMR_8D
+ 0x008E, //!< U_WMR_8E
+ 0x008F, //!< U_WMR_8F
+ 0x0090, //!< U_WMR_90
+ 0x0091, //!< U_WMR_91
+ 0x0092, //!< U_WMR_92
+ 0x0093, //!< U_WMR_93
+ 0x0094, //!< U_WMR_94
+ 0x0095, //!< U_WMR_95
+ 0x0096, //!< U_WMR_96
+ 0x0097, //!< U_WMR_97
+ 0x0098, //!< U_WMR_98
+ 0x0099, //!< U_WMR_99
+ 0x009A, //!< U_WMR_9A
+ 0x009B, //!< U_WMR_9B
+ 0x009C, //!< U_WMR_9C
+ 0x009D, //!< U_WMR_9D
+ 0x009E, //!< U_WMR_9E
+ 0x009F, //!< U_WMR_9F
+ 0x00A0, //!< U_WMR_A0
+ 0x00A1, //!< U_WMR_A1
+ 0x00A2, //!< U_WMR_A2
+ 0x00A3, //!< U_WMR_A3
+ 0x00A4, //!< U_WMR_A4
+ 0x00A5, //!< U_WMR_A5
+ 0x00A6, //!< U_WMR_A6
+ 0x00A7, //!< U_WMR_A7
+ 0x00A8, //!< U_WMR_A8
+ 0x00A9, //!< U_WMR_A9
+ 0x00AA, //!< U_WMR_AA
+ 0x00AB, //!< U_WMR_AB
+ 0x00AC, //!< U_WMR_AC
+ 0x00AD, //!< U_WMR_AD
+ 0x00AE, //!< U_WMR_AE
+ 0x00AF, //!< U_WMR_AF
+ 0x00B0, //!< U_WMR_B0
+ 0x00B1, //!< U_WMR_B1
+ 0x00B2, //!< U_WMR_B2
+ 0x00B3, //!< U_WMR_B3
+ 0x00B4, //!< U_WMR_B4
+ 0x00B5, //!< U_WMR_B5
+ 0x00B6, //!< U_WMR_B6
+ 0x00B7, //!< U_WMR_B7
+ 0x00B8, //!< U_WMR_B8
+ 0x00B9, //!< U_WMR_B9
+ 0x00BA, //!< U_WMR_BA
+ 0x00BB, //!< U_WMR_BB
+ 0x00BC, //!< U_WMR_BC
+ 0x00BD, //!< U_WMR_BD
+ 0x00BE, //!< U_WMR_BE
+ 0x00BF, //!< U_WMR_BF
+ 0x00C0, //!< U_WMR_C0
+ 0x00C1, //!< U_WMR_C1
+ 0x00C2, //!< U_WMR_C2
+ 0x00C3, //!< U_WMR_C3
+ 0x00C4, //!< U_WMR_C4
+ 0x00C5, //!< U_WMR_C5
+ 0x00C6, //!< U_WMR_C6
+ 0x00C7, //!< U_WMR_C7
+ 0x00C8, //!< U_WMR_C8
+ 0x00C9, //!< U_WMR_C9
+ 0x00CA, //!< U_WMR_CA
+ 0x00CB, //!< U_WMR_CB
+ 0x00CC, //!< U_WMR_CC
+ 0x00CD, //!< U_WMR_CD
+ 0x00CE, //!< U_WMR_CE
+ 0x00CF, //!< U_WMR_CF
+ 0x00D0, //!< U_WMR_D0
+ 0x00D1, //!< U_WMR_D1
+ 0x00D2, //!< U_WMR_D2
+ 0x00D3, //!< U_WMR_D3
+ 0x00D4, //!< U_WMR_D4
+ 0x00D5, //!< U_WMR_D5
+ 0x00D6, //!< U_WMR_D6
+ 0x00D7, //!< U_WMR_D7
+ 0x00D8, //!< U_WMR_D8
+ 0x00D9, //!< U_WMR_D9
+ 0x00DA, //!< U_WMR_DA
+ 0x00DB, //!< U_WMR_DB
+ 0x00DC, //!< U_WMR_DC
+ 0x00DD, //!< U_WMR_DD
+ 0x00DE, //!< U_WMR_DE
+ 0x00DF, //!< U_WMR_DF
+ 0x00E0, //!< U_WMR_E0
+ 0x00E1, //!< U_WMR_E1
+ 0x00E2, //!< U_WMR_E2
+ 0x00E3, //!< U_WMR_E3
+ 0x00E4, //!< U_WMR_E4
+ 0x00E5, //!< U_WMR_E5
+ 0x00E6, //!< U_WMR_E6
+ 0x00E7, //!< U_WMR_E7
+ 0x00E8, //!< U_WMR_E8
+ 0x00E9, //!< U_WMR_E9
+ 0x00EA, //!< U_WMR_EA
+ 0x00EB, //!< U_WMR_EB
+ 0x00EC, //!< U_WMR_EC
+ 0x00ED, //!< U_WMR_ED
+ 0x00EE, //!< U_WMR_EE
+ 0x00EF, //!< U_WMR_EF
+ 0x01F0, //!< U_WMR_DELETEOBJECT
+ 0x00F1, //!< U_WMR_F1
+ 0x00F2, //!< U_WMR_F2
+ 0x00F3, //!< U_WMR_F3
+ 0x00F4, //!< U_WMR_F4
+ 0x00F5, //!< U_WMR_F5
+ 0x00F6, //!< U_WMR_F6
+ 0x00F7, //!< U_WMR_CREATEPALETTE
+ 0x00F8, //!< U_WMR_CREATEBRUSH
+ 0x01F9, //!< U_WMR_CREATEPATTERNBRUSH
+ 0x02FA, //!< U_WMR_CREATEPENINDIRECT
+ 0x02FB, //!< U_WMR_CREATEFONTINDIRECT
+ 0x02FC, //!< U_WMR_CREATEBRUSHINDIRECT
+ 0x02FD, //!< U_WMR_CREATEBITMAPINDIRECT
+ 0x06FE, //!< U_WMR_CREATEBITMAP
+ 0x06FF //!< U_WMR_CREATEREGION
+ };
+ if(idx<U_WMR_MIN || idx > U_WMR_MAX){ ret = 0xFFFFFFFF; }
+ else { ret = U_WMR_VALUES[idx]; }
+ return(ret);
+}
+
+/**
+ \brief Look up the name of the WMR record by type. Returns U_WMR_INVALID if out of range.
+
+ \return name of the WMR record, "U_WMR_INVALID" if out of range.
+ \param idx WMR record type.
+
+*/
+const char *U_wmr_names(int idx){
+ int ret;
+ static const char *U_WMR_NAMES[257]={
+ "U_WMR_EOF",
+ "U_WMR_SETBKCOLOR",
+ "U_WMR_SETBKMODE",
+ "U_WMR_SETMAPMODE",
+ "U_WMR_SETROP2",
+ "U_WMR_SETRELABS",
+ "U_WMR_SETPOLYFILLMODE",
+ "U_WMR_SETSTRETCHBLTMODE",
+ "U_WMR_SETTEXTCHAREXTRA",
+ "U_WMR_SETTEXTCOLOR",
+ "U_WMR_SETTEXTJUSTIFICATION",
+ "U_WMR_SETWINDOWORG",
+ "U_WMR_SETWINDOWEXT",
+ "U_WMR_SETVIEWPORTORG",
+ "U_WMR_SETVIEWPORTEXT",
+ "U_WMR_OFFSETWINDOWORG",
+ "U_WMR_SCALEWINDOWEXT",
+ "U_WMR_OFFSETVIEWPORTORG",
+ "U_WMR_SCALEVIEWPORTEXT",
+ "U_WMR_LINETO",
+ "U_WMR_MOVETO",
+ "U_WMR_EXCLUDECLIPRECT",
+ "U_WMR_INTERSECTCLIPRECT",
+ "U_WMR_ARC",
+ "U_WMR_ELLIPSE",
+ "U_WMR_FLOODFILL",
+ "U_WMR_PIE",
+ "U_WMR_RECTANGLE",
+ "U_WMR_ROUNDRECT",
+ "U_WMR_PATBLT",
+ "U_WMR_SAVEDC",
+ "U_WMR_SETPIXEL",
+ "U_WMR_OFFSETCLIPRGN",
+ "U_WMR_TEXTOUT",
+ "U_WMR_BITBLT",
+ "U_WMR_STRETCHBLT",
+ "U_WMR_POLYGON",
+ "U_WMR_POLYLINE",
+ "U_WMR_ESCAPE",
+ "U_WMR_RESTOREDC",
+ "U_WMR_FILLREGION",
+ "U_WMR_FRAMEREGION",
+ "U_WMR_INVERTREGION",
+ "U_WMR_PAINTREGION",
+ "U_WMR_SELECTCLIPREGION",
+ "U_WMR_SELECTOBJECT",
+ "U_WMR_SETTEXTALIGN",
+ "U_WMR_DRAWTEXT",
+ "U_WMR_CHORD",
+ "U_WMR_SETMAPPERFLAGS",
+ "U_WMR_EXTTEXTOUT",
+ "U_WMR_SETDIBTODEV",
+ "U_WMR_SELECTPALETTE",
+ "U_WMR_REALIZEPALETTE",
+ "U_WMR_ANIMATEPALETTE",
+ "U_WMR_SETPALENTRIES",
+ "U_WMR_POLYPOLYGON",
+ "U_WMR_RESIZEPALETTE",
+ "U_WMR_3A",
+ "U_WMR_3B",
+ "U_WMR_3C",
+ "U_WMR_3D",
+ "U_WMR_3E",
+ "U_WMR_3F",
+ "U_WMR_DIBBITBLT",
+ "U_WMR_DIBSTRETCHBLT",
+ "U_WMR_DIBCREATEPATTERNBRUSH",
+ "U_WMR_STRETCHDIB",
+ "U_WMR_44",
+ "U_WMR_45",
+ "U_WMR_46",
+ "U_WMR_47",
+ "U_WMR_EXTFLOODFILL",
+ "U_WMR_49",
+ "U_WMR_4A",
+ "U_WMR_4B",
+ "U_WMR_4C",
+ "U_WMR_4D",
+ "U_WMR_4E",
+ "U_WMR_4F",
+ "U_WMR_50",
+ "U_WMR_51",
+ "U_WMR_52",
+ "U_WMR_53",
+ "U_WMR_54",
+ "U_WMR_55",
+ "U_WMR_56",
+ "U_WMR_57",
+ "U_WMR_58",
+ "U_WMR_59",
+ "U_WMR_5A",
+ "U_WMR_5B",
+ "U_WMR_5C",
+ "U_WMR_5D",
+ "U_WMR_5E",
+ "U_WMR_5F",
+ "U_WMR_60",
+ "U_WMR_61",
+ "U_WMR_62",
+ "U_WMR_63",
+ "U_WMR_64",
+ "U_WMR_65",
+ "U_WMR_66",
+ "U_WMR_67",
+ "U_WMR_68",
+ "U_WMR_69",
+ "U_WMR_6A",
+ "U_WMR_6B",
+ "U_WMR_6C",
+ "U_WMR_6D",
+ "U_WMR_6E",
+ "U_WMR_6F",
+ "U_WMR_70",
+ "U_WMR_71",
+ "U_WMR_72",
+ "U_WMR_73",
+ "U_WMR_74",
+ "U_WMR_75",
+ "U_WMR_76",
+ "U_WMR_77",
+ "U_WMR_78",
+ "U_WMR_79",
+ "U_WMR_7A",
+ "U_WMR_7B",
+ "U_WMR_7C",
+ "U_WMR_7D",
+ "U_WMR_7E",
+ "U_WMR_7F",
+ "U_WMR_80",
+ "U_WMR_81",
+ "U_WMR_82",
+ "U_WMR_83",
+ "U_WMR_84",
+ "U_WMR_85",
+ "U_WMR_86",
+ "U_WMR_87",
+ "U_WMR_88",
+ "U_WMR_89",
+ "U_WMR_8A",
+ "U_WMR_8B",
+ "U_WMR_8C",
+ "U_WMR_8D",
+ "U_WMR_8E",
+ "U_WMR_8F",
+ "U_WMR_90",
+ "U_WMR_91",
+ "U_WMR_92",
+ "U_WMR_93",
+ "U_WMR_94",
+ "U_WMR_95",
+ "U_WMR_96",
+ "U_WMR_97",
+ "U_WMR_98",
+ "U_WMR_99",
+ "U_WMR_9A",
+ "U_WMR_9B",
+ "U_WMR_9C",
+ "U_WMR_9D",
+ "U_WMR_9E",
+ "U_WMR_9F",
+ "U_WMR_A0",
+ "U_WMR_A1",
+ "U_WMR_A2",
+ "U_WMR_A3",
+ "U_WMR_A4",
+ "U_WMR_A5",
+ "U_WMR_A6",
+ "U_WMR_A7",
+ "U_WMR_A8",
+ "U_WMR_A9",
+ "U_WMR_AA",
+ "U_WMR_AB",
+ "U_WMR_AC",
+ "U_WMR_AD",
+ "U_WMR_AE",
+ "U_WMR_AF",
+ "U_WMR_B0",
+ "U_WMR_B1",
+ "U_WMR_B2",
+ "U_WMR_B3",
+ "U_WMR_B4",
+ "U_WMR_B5",
+ "U_WMR_B6",
+ "U_WMR_B7",
+ "U_WMR_B8",
+ "U_WMR_B9",
+ "U_WMR_BA",
+ "U_WMR_BB",
+ "U_WMR_BC",
+ "U_WMR_BD",
+ "U_WMR_BE",
+ "U_WMR_BF",
+ "U_WMR_C0",
+ "U_WMR_C1",
+ "U_WMR_C2",
+ "U_WMR_C3",
+ "U_WMR_C4",
+ "U_WMR_C5",
+ "U_WMR_C6",
+ "U_WMR_C7",
+ "U_WMR_C8",
+ "U_WMR_C9",
+ "U_WMR_CA",
+ "U_WMR_CB",
+ "U_WMR_CC",
+ "U_WMR_CD",
+ "U_WMR_CE",
+ "U_WMR_CF",
+ "U_WMR_D0",
+ "U_WMR_D1",
+ "U_WMR_D2",
+ "U_WMR_D3",
+ "U_WMR_D4",
+ "U_WMR_D5",
+ "U_WMR_D6",
+ "U_WMR_D7",
+ "U_WMR_D8",
+ "U_WMR_D9",
+ "U_WMR_DA",
+ "U_WMR_DB",
+ "U_WMR_DC",
+ "U_WMR_DD",
+ "U_WMR_DE",
+ "U_WMR_DF",
+ "U_WMR_E0",
+ "U_WMR_E1",
+ "U_WMR_E2",
+ "U_WMR_E3",
+ "U_WMR_E4",
+ "U_WMR_E5",
+ "U_WMR_E6",
+ "U_WMR_E7",
+ "U_WMR_E8",
+ "U_WMR_E9",
+ "U_WMR_EA",
+ "U_WMR_EB",
+ "U_WMR_EC",
+ "U_WMR_ED",
+ "U_WMR_EE",
+ "U_WMR_EF",
+ "U_WMR_DELETEOBJECT",
+ "U_WMR_F1",
+ "U_WMR_F2",
+ "U_WMR_F3",
+ "U_WMR_F4",
+ "U_WMR_F5",
+ "U_WMR_F6",
+ "U_WMR_CREATEPALETTE",
+ "U_WMR_CREATEBRUSH",
+ "U_WMR_CREATEPATTERNBRUSH",
+ "U_WMR_CREATEPENINDIRECT",
+ "U_WMR_CREATEFONTINDIRECT",
+ "U_WMR_CREATEBRUSHINDIRECT",
+ "U_WMR_CREATEBITMAPINDIRECT",
+ "U_WMR_CREATEBITMAP",
+ "U_WMR_CREATEREGION"
+ };
+ if(idx<U_WMR_MIN || idx > U_WMR_MAX){ ret = 256; }
+ else { ret = idx; }
+ return(U_WMR_NAMES[ret]);
+}
+
+/**
+ \brief Text description of Escape record type.
+ \return name of the WMR record, "UNKNOWN_ESCAPE" if out of range.
+ \param idx Escape record type.
+*/
+const char *U_wmr_escnames(int idx){
+ const char *name;
+ if(idx>=1 && idx <= 0x0023){
+ switch(idx){
+ case 0x0001: name = "NEWFRAME"; break;
+ case 0x0002: name = "ABORTDOC"; break;
+ case 0x0003: name = "NEXTBAND"; break;
+ case 0x0004: name = "SETCOLORTABLE"; break;
+ case 0x0005: name = "GETCOLORTABLE"; break;
+ case 0x0006: name = "FLUSHOUT"; break;
+ case 0x0007: name = "DRAFTMODE"; break;
+ case 0x0008: name = "QUERYESCSUPPORT"; break;
+ case 0x0009: name = "SETABORTPROC"; break;
+ case 0x000A: name = "STARTDOC"; break;
+ case 0x000B: name = "ENDDOC"; break;
+ case 0x000C: name = "GETPHYSPAGESIZE"; break;
+ case 0x000D: name = "GETPRINTINGOFFSET"; break;
+ case 0x000E: name = "GETSCALINGFACTOR"; break;
+ case 0x000F: name = "META_ESCAPE_ENHANCED_METAFILE"; break;
+ case 0x0010: name = "SETPENWIDTH"; break;
+ case 0x0011: name = "SETCOPYCOUNT"; break;
+ case 0x0012: name = "SETPAPERSOURCE"; break;
+ case 0x0013: name = "PASSTHROUGH"; break;
+ case 0x0014: name = "GETTECHNOLOGY"; break;
+ case 0x0015: name = "SETLINECAP"; break;
+ case 0x0016: name = "SETLINEJOIN"; break;
+ case 0x0017: name = "SETMITERLIMIT"; break;
+ case 0x0018: name = "BANDINFO"; break;
+ case 0x0019: name = "DRAWPATTERNRECT"; break;
+ case 0x001A: name = "GETVECTORPENSIZE"; break;
+ case 0x001B: name = "GETVECTORBRUSHSIZE"; break;
+ case 0x001C: name = "ENABLEDUPLEX"; break;
+ case 0x001D: name = "GETSETPAPERBINS"; break;
+ case 0x001E: name = "GETSETPRINTORIENT"; break;
+ case 0x001F: name = "ENUMPAPERBINS"; break;
+ case 0x0020: name = "SETDIBSCALING"; break;
+ case 0x0021: name = "EPSPRINTING"; break;
+ case 0x0022: name = "ENUMPAPERMETRICS"; break;
+ case 0x0023: name = "GETSETPAPERMETRICS"; break;
+ }
+ }
+ else if(idx == 0x0025){ name = "POSTSCRIPT_DATA"; }
+ else if(idx == 0x0026){ name = "POSTSCRIPT_IGNORE"; }
+ else if(idx == 0x002A){ name = "GETDEVICEUNITS"; }
+ else if(idx == 0x0100){ name = "GETEXTENDEDTEXTMETRICS"; }
+ else if(idx == 0x0102){ name = "GETPAIRKERNTABLE"; }
+ else if(idx == 0x0200){ name = "EXTTEXTOUT"; }
+ else if(idx == 0x0201){ name = "GETFACENAME"; }
+ else if(idx == 0x0202){ name = "DOWNLOADFACE"; }
+ else if(idx == 0x0801){ name = "METAFILE_DRIVER"; }
+ else if(idx == 0x0C01){ name = "QUERYDIBSUPPORT"; }
+ else if(idx == 0x1000){ name = "BEGIN_PATH"; }
+ else if(idx == 0x1001){ name = "CLIP_TO_PATH"; }
+ else if(idx == 0x1002){ name = "END_PATH"; }
+ else if(idx == 0x100E){ name = "OPEN_CHANNEL"; }
+ else if(idx == 0x100F){ name = "DOWNLOADHEADER"; }
+ else if(idx == 0x1010){ name = "CLOSE_CHANNEL"; }
+ else if(idx == 0x1013){ name = "POSTSCRIPT_PASSTHROUGH"; }
+ else if(idx == 0x1014){ name = "ENCAPSULATED_POSTSCRIPT";}
+ else if(idx == 0x1015){ name = "POSTSCRIPT_IDENTIFY"; }
+ else if(idx == 0x1016){ name = "POSTSCRIPT_INJECTION"; }
+ else if(idx == 0x1017){ name = "CHECKJPEGFORMAT"; }
+ else if(idx == 0x1018){ name = "CHECKPNGFORMAT"; }
+ else if(idx == 0x1019){ name = "GET_PS_FEATURESETTING"; }
+ else if(idx == 0x101A){ name = "MXDC_ESCAPE"; }
+ else if(idx == 0x11D8){ name = "SPCLPASSTHROUGH2"; }
+ else { name = "UNKNOWN_ESCAPE"; }
+ return(name);
+}
+
+//! \cond
+/* one prototype from uwmf_endian. Put it here because end user should never need to see it, so
+not in uemf.h or uwmf_endian.h */
+void U_swap2(void *ul, unsigned int count);
+
+/**
+ \brief Check that the bitmap in the specified packed DIB is compatible with the record size
+
+ \return 1 on success, 0 on failure
+ \param record EMF record that contains a DIB pixel array
+ \param blimit one byte past the end of the record.
+
+ This method can only test DIBs that hold Microsoft's various bitmap types. PNG or JPG is just a bag
+ of bytes, and there is no possible way to derive from the known width and height how big it should be.
+
+ This should not be called directly by end user code.
+*/
+int packed_DIB_safe(
+ const char *record,
+ const char *blimit
+ ){
+ int dibparams = U_BI_UNKNOWN; // type of image not yet determined
+ const char *px = NULL; // DIB pixels
+ const U_RGBQUAD *ct = NULL; // DIB color table
+ int bs;
+ int usedbytes;
+
+ if(!bitmapinfo_safe(record, blimit))return(0); // this DIB has issues with colors fitting into the record
+ uint32_t numCt; // these values will be set in get_DIB_params
+ int32_t width, height, colortype, invert; // these values will be set in get_DIB_params
+ // next call returns pointers and values, but allocates no memory
+ dibparams = wget_DIB_params(record, &px, (const U_RGBQUAD **) &ct, &numCt, &width, &height, &colortype, &invert);
+ // sanity checking
+ if(numCt && colortype >= U_BCBM_COLOR16)return(0); //color tables not used above 16 bit pixels
+ if(!numCt && colortype < U_BCBM_COLOR16)return(0); //color tables mandatory for < 16 bit
+
+ if(dibparams ==U_BI_RGB){
+ // this is the only DIB type where we can calculate how big it should be when stored in the WMF file
+ bs = colortype/8;
+ if(bs<1){
+ usedbytes = (width*colortype + 7)/8; // width of line in fully and partially occupied bytes
+ }
+ else {
+ usedbytes = width*bs;
+ }
+ if(IS_MEM_UNSAFE(px, usedbytes, blimit))return(0);
+ }
+ return(1);
+}
+
+//! \endcond
+
+/**
+ \brief Derive from bounding box and start and end arc, for WMF arc, chord, or pie records, the center, start, and end points, and the bounding rectangle.
+
+ \return 0 on success, other values on errors.
+ \param rclBox16 Bounding box of Arc
+ \param ArcStart16 Coordinates for Start of Arc
+ \param ArcEnd16 Coordinates for End of Arc
+ \param f1 1 if rotation angle >= 180, else 0
+ \param f2 Rotation direction, 1 if counter clockwise, else 0
+ \param center Center coordinates
+ \param start Start coordinates (point on the ellipse defined by rect)
+ \param end End coordinates (point on the ellipse defined by rect)
+ \param size W,H of the x,y axes of the bounding rectangle.
+*/
+int wmr_arc_points(
+ U_RECT16 rclBox16,
+ U_POINT16 ArcStart16,
+ U_POINT16 ArcEnd16,
+ int *f1,
+ int f2,
+ U_PAIRF *center,
+ U_PAIRF *start,
+ U_PAIRF *end,
+ U_PAIRF *size
+ ){
+ U_RECTL rclBox;
+ U_POINTL ArcStart,ArcEnd;
+ rclBox.left = rclBox16.left;
+ rclBox.top = rclBox16.top;
+ rclBox.right = rclBox16.right;
+ rclBox.bottom = rclBox16.bottom;
+ ArcStart.x = ArcStart16.x;
+ ArcStart.y = ArcStart16.y;
+ ArcEnd.x = ArcEnd16.x;
+ ArcEnd.y = ArcEnd16.y;
+ return emr_arc_points_common(&rclBox, &ArcStart, &ArcEnd, f1, f2, center, start, end, size);
+}
+
+/**
+ \brief A U_RECT16 may have its values swapped, L<->R and T<->B, this extracts the leftmost as left, and so forth.
+ \param rc U_RECT156 binary contents of an WMF file
+ \param left the leftmost of rc.left and rc.right
+ \param top the topmost of rc.top and rc.bottom
+ \param right the rightmost of rc.left and rc.right
+ \param bottom the bottommost of rc.top and rc.bottom
+*/
+void U_sanerect16(U_RECT16 rc, double *left, double *top, double *right, double *bottom){
+ if(rc.left < rc.right) { *left = rc.left; *right = rc.right; }
+ else { *left = rc.right; *right = rc.left; }
+ if(rc.top < rc.bottom){ *top = rc.top; *bottom = rc.bottom; }
+ else{ *top = rc.bottom; *bottom = rc.top; }
+}
+
+/* **********************************************************************************************
+These definitions are for code pieces that are used many times in the following implementation. These
+definitions are not needed in end user code, so they are here rather than in uwmf.h.
+*********************************************************************************************** */
+
+/**
+ \brief Get record size in bytes from U_WMR* record, which may not be aligned
+ \return number of bytes in record.
+*/
+uint32_t U_wmr_size(const U_METARECORD *record){
+ uint32_t Size16;
+ memcpy(&Size16,record, 4);
+ return(2*Size16);
+}
+
+//! \cond should never be called directly
+#define SET_CB_FROM_PXBMI(A,B,C,D,E,F) /* A=Px, B=Bmi, C=cbImage, D=cbImage4, E=cbBmi, F=cbPx */ \
+ if(A){\
+ if(!B)return(NULL); /* size is derived from U_BITMAPINFO, but NOT from its size field, go figure*/ \
+ C = F;\
+ D = UP4(C); /* pixel array might not be a multiples of 4 bytes*/ \
+ E = U_SIZE_BITMAPINFOHEADER + 4 * get_real_color_count((char *)&(B->bmiHeader)); /* bmiheader + colortable*/ \
+ }\
+ else { C = 0; D = 0; E=0; }
+//! \endcond
+
+/**
+ \brief Create and return a U_FONT structure.
+ \return pointer to the created U_FONT structure.
+ \param Height Height in Logical units
+ \param Width Average Width in Logical units
+ \param Escapement Angle in 0.1 degrees betweem escapement vector and X axis
+ \param Orientation Angle in 0.1 degrees between baseline and X axis
+ \param Weight LF_Weight Enumeration
+ \param Italic LF_Italic Enumeration
+ \param Underline LF_Underline Enumeration
+ \param StrikeOut LF_StrikeOut Enumeration
+ \param CharSet LF_CharSet Enumeration
+ \param OutPrecision LF_OutPrecision Enumeration
+ \param ClipPrecision LF_ClipPrecision Enumeration
+ \param Quality LF_Quality Enumeration
+ \param PitchAndFamily LF_PitchAndFamily Enumeration
+ \param FaceName Name of font. ANSI Latin1, null terminated.
+*/
+U_FONT *U_FONT_set(
+ int16_t Height, //!< Height in Logical units
+ int16_t Width, //!< Average Width in Logical units
+ int16_t Escapement, //!< Angle in 0.1 degrees betweem escapement vector and X axis
+ int16_t Orientation, //!< Angle in 0.1 degrees between baseline and X axis
+ int16_t Weight, //!< LF_Weight Enumeration
+ uint8_t Italic, //!< LF_Italic Enumeration
+ uint8_t Underline, //!< LF_Underline Enumeration
+ uint8_t StrikeOut, //!< LF_StrikeOut Enumeration
+ uint8_t CharSet, //!< LF_CharSet Enumeration
+ uint8_t OutPrecision, //!< LF_OutPrecision Enumeration
+ uint8_t ClipPrecision, //!< LF_ClipPrecision Enumeration
+ uint8_t Quality, //!< LF_Quality Enumeration
+ uint8_t PitchAndFamily, //!< LF_PitchAndFamily Enumeration
+ char *FaceName //!< Name of font. ANSI Latin1, null terminated.
+ ){
+ U_FONT *font;
+ int slen = 1 + strlen(FaceName); /* include terminator */
+ if(slen & 1)slen++; /* storage length even */
+ font = (U_FONT *) calloc(1,slen + U_SIZE_FONT_CORE); /* use calloc to auto fill in terminating '\0'*/
+ if(font){
+ font->Height = Height;
+ font->Width = Width;
+ font->Escapement = Escapement;
+ font->Orientation = Orientation;
+ font->Weight = Weight;
+ font->Italic = Italic;
+ font->Underline = Underline;
+ font->StrikeOut = StrikeOut;
+ font->CharSet = CharSet;
+ font->OutPrecision = OutPrecision;
+ font->ClipPrecision = ClipPrecision;
+ font->Quality = Quality;
+ font->PitchAndFamily = PitchAndFamily;
+ strcpy((char *)&font->FaceName, FaceName);
+ }
+ return(font);
+}
+
+/**
+ \brief Create and return a U_PLTENTRY structure.
+ \return the created U_PLTENTRY structure.
+ \param Color Color for the U_PLTENTRY
+*/
+U_PLTNTRY U_PLTNTRY_set(U_COLORREF Color){
+ U_PLTNTRY pe;
+ pe.Value = Color.Reserved;
+ pe.Blue = Color.Blue;
+ pe.Green = Color.Green;
+ pe.Red = Color.Red;
+ return(pe);
+}
+
+/**
+ \brief Create and return a U_PALETTE structure.
+ \return pointer to the created U_PALETTE structure.
+ \param Start Either 0x0300 or an offset into the Palette table
+ \param NumEntries Number of U_LOGPLTNTRY objects
+ \param PalEntries Pointer to array of PaletteEntry Objects
+*/
+U_PALETTE *U_PLTENTRY_set(
+ uint16_t Start, //!< Either 0x0300 or an offset into the Palette table
+ uint16_t NumEntries, //!< Number of U_LOGPLTNTRY objects
+ U_PLTNTRY *PalEntries //!< Pointer to array of PaletteEntry Objects
+ ){
+ U_PALETTE *Palette = NULL;
+ if(NumEntries){
+ Palette = malloc(4 + 4*NumEntries);
+ if(Palette){
+ Palette->Start = Start;
+ Palette->NumEntries = NumEntries;
+ memcpy(&Palette->PalEntries, PalEntries, NumEntries*4);
+ }
+ }
+ return(Palette);
+}
+
+/**
+ \brief Create and return a U_PEN structure.
+ \return the created U_PEN structure.
+ \param Style PenStyle Enumeration
+ \param Width Width of Pen
+ \param Color Pen Color.
+*/
+U_PEN U_PEN_set(
+ uint16_t Style, //!< PenStyle Enumeration
+ uint16_t Width, //!< Width of Pen
+ U_COLORREF Color //!< Pen Color.
+ ){
+ U_PEN p;
+ p.Style = Style;
+ p.Widthw[0] = Width;
+ p.Widthw[1] = 0; /* ignored */
+ p.Color.Red = Color.Red;
+ p.Color.Green = Color.Green;
+ p.Color.Blue = Color.Blue;
+ p.Color.Reserved = Color.Reserved;
+ return(p);
+}
+
+/**
+ \brief Create and return a U_RECT16 structure from Upper Left and Lower Right corner points.
+ \param ul upper left corner of rectangle
+ \param lr lower right corner of rectangle
+*/
+U_RECT16 U_RECT16_set(
+ U_POINT16 ul,
+ U_POINT16 lr
+ ){
+ U_RECT16 rect;
+ rect.left = ul.x;
+ rect.top = ul.y;
+ rect.right = lr.x;
+ rect.bottom = lr.y;
+ return(rect);
+}
+
+/**
+ \brief Create and return a U_BITMAP16 structure
+ \return pointer to the U_BITMAP16 structure, or NULL on failure
+ \param Type bitmap Type (not described at all in the WMF PDF)
+ \param Width bitmap width in pixels.
+ \param Height bitmap height in scan lines.
+ \param LineN each array line in Bits is a multiple of this (4 for a DIB)
+ \param BitsPixel number of adjacent color bits on each plane (R bits + G bits + B bits ????)
+ \param Bits bitmap pixel data. Bytes contained = (((Width * BitsPixel + 15) >> 4) << 1) * Height
+*/
+U_BITMAP16 *U_BITMAP16_set(
+ const int16_t Type,
+ const int16_t Width,
+ const int16_t Height,
+ const int16_t LineN,
+ const uint8_t BitsPixel,
+ const char *Bits
+ ){
+ U_BITMAP16 *bm16;
+ uint32_t irecsize;
+ int cbBits,iHeight;
+ int usedbytes;
+ int16_t WidthBytes; // total bytes per scan line (used and padding).
+
+ usedbytes = (Width * BitsPixel + 7)/8; // width of line in fully and partially occupied bytes
+ WidthBytes = (LineN * ((usedbytes + (LineN - 1) ) / LineN)); // Account for padding required by line alignment in the pixel array
+
+ iHeight = (Height < 0 ? -Height : Height); /* DIB can use a negative height, but it does not look like a Bitmap16 object can */
+ cbBits = WidthBytes * iHeight;
+ if(!Bits || cbBits<=0)return(NULL);
+ irecsize = U_SIZE_BITMAP16 + cbBits;
+ bm16 = (U_BITMAP16 *) malloc(irecsize);
+ if(bm16){
+ bm16->Type = Type;
+ bm16->Width = Width;
+ bm16->Height = iHeight;
+ bm16->WidthBytes = WidthBytes;
+ bm16->Planes = 1;
+ bm16->BitsPixel = BitsPixel;
+ memcpy((char *)bm16 + U_SIZE_BITMAP16,Bits,cbBits);
+ }
+ return(bm16);
+}
+
+/**
+ \brief Create and return a U_SCAN structure
+ \return U_SCAN structure
+ \param count Number of entries in the ScanLines array
+ \param top Y coordinate of the top scanline
+ \param bottom Y coordinate of the bottom scanline
+ \param ScanLines Array of 16 bit left/right pairs, array has 2*count entries
+*/
+U_SCAN *U_SCAN_set(
+ uint16_t count, //!< Number of entries in the ScanLines array
+ uint16_t top, //!< Y coordinate of the top scanline
+ uint16_t bottom, //!< Y coordinate of the bottom scanline
+ uint16_t *ScanLines //!< Array of 16 bit left/right pairs, array has 2*count entries
+ ){
+ U_SCAN *scan=NULL;
+ int size = 6 + count*4;
+ scan = malloc(size);
+ if(scan){
+ scan->count = count;
+ scan->top = top;
+ scan->bottom = bottom;
+ memcpy(&scan->ScanLines,ScanLines,4*count);
+ }
+ return(scan);
+}
+
+/**
+ \brief Create and return a U_REGION structure
+ \return pointer to created U_REGION structure or NULL on error
+ \param Size aScans in bytes + regions size in bytes (size of this header plus all U_SCAN objects?)
+ \param sCount number of scan objects in region (docs say scanlines, but then no way to add sizes)
+ \param sMax largest number of points in any scan
+ \param sRect bounding rectangle
+ \param aScans series of U_SCAN objects to append. This is also an array of uint16_t, but should be handled as a bunch of U_SCAN objects tightly packed into the buffer.
+*/
+U_REGION *U_REGION_set(
+ int16_t Size, //!< aScans in bytes + regions size in bytes (size of this header plus all U_SCAN objects?)
+ int16_t sCount, //!< number of scan objects in region (docs say scanlines, but then no way to add sizes)
+ int16_t sMax, //!< largest number of points in any scan
+ U_RECT16 sRect, //!< bounding rectangle
+ uint16_t *aScans //!< series of U_SCAN objects to append. This is also an array of uint16_t, but should be handled as a bunch of U_SCAN objects tightly packed into the buffer.
+ ){
+ U_REGION *region=NULL;
+ char *psc;
+ int scansize,i,off;
+ psc = (char *)aScans;
+ for(scansize=i=0; i<sCount; i++){
+ off = 6 + 4*(((U_SCAN *)psc)->count);
+ scansize += off;
+ psc += off;
+ }
+ region = malloc(U_SIZE_REGION + scansize);
+ if(region){
+ region->ignore1 = 0;
+ region->Type = 0x0006;
+ region->ignore2 = 0;
+ region->Size = Size;
+ region->sCount = sCount;
+ region->sMax = sMax;
+ region->sRect = sRect;
+ memcpy(&region->aScans,aScans,scansize);
+ }
+ return(region);
+}
+
+
+/**
+ \brief Create and return a U_WLOGBRUSH structure.
+ \return the created U_WLOGBRUSH structure.
+ \param Style BrushStyle Enumeration
+ \param Color Brush Color value
+ \param Hatch HatchStyle Enumeration
+*/
+U_WLOGBRUSH U_WLOGBRUSH_set(
+ uint16_t Style, //!< BrushStyle Enumeration
+ U_COLORREF Color, //!< Brush Color value
+ uint16_t Hatch //!< HatchStyle Enumeration
+ ){
+ U_WLOGBRUSH lb;
+ lb.Style = Style;
+ lb.Color.Red = Color.Red;
+ lb.Color.Green = Color.Green;
+ lb.Color.Blue = Color.Blue;
+ lb.Color.Reserved = Color.Reserved;
+ lb.Hatch = Hatch;
+ return(lb);
+}
+
+
+/**
+ \brief Create and return a U_PAIRF structure.
+ \return pointer to the created U_PAIRF structure.
+ \param x x value
+ \param y y value
+*/
+U_PAIRF *U_PAIRF_set(
+ float x, //!< x value
+ float y //!< y value
+ ){
+ U_PAIRF *pf=malloc(U_SIZE_PAIRF);
+ if(pf){
+ pf->x = x;
+ pf->y = y;
+ }
+ return(pf);
+}
+
+/* **********************************************************************************************
+These functions are used for Image conversions and other
+utility operations. Character type conversions are in uwmf_utf.c
+*********************************************************************************************** */
+
+/**
+ \brief Calculate the int16_t checksum of the buffer for the number of positions specified. This is XOR of all values.
+ \return checksum
+ \param buf array of uint16_t values
+ \param count number of members in buf
+
+*/
+int16_t U_16_checksum(int16_t *buf, int count){
+ int16_t result=0;
+ for(;count;count--){
+ result ^= *buf++;
+ }
+ return(result);
+}
+
+/**
+ \brief Dump a WMFHANDLES structure. Not for use in production code.
+ \param string Text to output before dumping eht structure
+ \param handle Handle
+ \param wht WMFHANDLES structure to dump
+*/
+void dumpwht(
+ char *string,
+ unsigned int *handle,
+ WMFHANDLES *wht
+ ){
+ uint32_t i;
+ printf("%s\n",string);
+ printf("lo: %d hi: %d peak: %d\n", wht->lolimit, wht->hilimit, wht->peak);
+ if(handle){
+ printf("handle: %d \n",*handle);
+ }
+ for(i=0;i<=5;i++){
+ printf("table[%d]: %d\n",i,wht->table[i]);
+ }
+}
+
+/**
+ \brief Make up an approximate dx array to pass to U_WMREXTTEXTOUT_set(), based on character height and weight.
+
+ Take abs. value of character height, get width by multiplying by 0.6, and correct weight
+ approximately, with formula (measured on screen for one text line of Arial).
+ Caller is responsible for free() on the returned pointer.
+
+ \return pointer to dx array
+ \param height character height (absolute value will be used)
+ \param weight LF_Weight Enumeration (character weight)
+ \param members Number of entries to put into dx
+
+*/
+int16_t *dx16_set(
+ int32_t height,
+ uint32_t weight,
+ uint32_t members
+ ){
+ uint32_t i, width;
+ int16_t *dx;
+ dx = (int16_t *) malloc(members * sizeof(int16_t));
+ if(dx){
+ if(U_FW_DONTCARE == weight)weight=U_FW_NORMAL;
+ width = (uint32_t) U_ROUND(((float) (height > 0 ? height : -height)) * 0.6 * (0.00024*(float) weight + 0.904));
+ for ( i = 0; i < members; i++ ){ dx[i] = (width > INT16_MAX ? INT16_MAX : width); }
+ }
+ return(dx);
+}
+/**
+ \brief Look up the properties (a bit map) of a type of WMR record.
+ Bits that may be set are defined in "Draw Properties" in uemf.h, they are U_DRAW_NOTEMPTY, etc..
+ \return bitmap of WMR record properties, or U_WMR_INVALID on error or release of all memory.
+ \param type WMR record type. If U_WMR_INVALID release memory. (There is no U_WMR_INVALID WMR record type)
+
+*/
+uint32_t U_wmr_properties(uint32_t type){
+ static uint32_t *table=NULL;
+ uint32_t result = U_WMR_INVALID; // initialized to indicate an error (on a lookup) or nothing (on a memory release)
+ if(type == U_WMR_INVALID){
+ if(table)free(table);
+ table=NULL;
+ }
+ else if(type<=U_WMR_MAX){ // type is uint so always >=0, no need to test U_WMR_MIN, which is 0.
+ if(!table){
+ table = (uint32_t *) malloc(sizeof(uint32_t)*(1 + U_WMR_MAX));
+ if(!table)return(result);
+ // 0x200 0x100 0x80 0x40 0x20 0x10 0x08 0x04 0x02 0x01
+ // properties (U_DRAW_*) TEXT ALTERS ONLYTO VISIBLE
+ // NOFILL OBJECT PATH FORCE CLOSED NOTEMPTY
+ // Record Type
+ table[0x00] = 0x0A0; // U_WMREOF 0 0 1 0 1 0 0 0 0 0 Force out any pending draw
+ table[0x01] = 0x020; // U_WMRSETBKCOLOR 0 0 0 0 1 0 0 0 0 0
+ table[0x02] = 0x020; // U_WMRSETBKMODE 0 0 0 0 1 0 0 0 0 0
+ table[0x03] = 0x0A0; // U_WMRSETMAPMODE 0 0 1 0 1 0 0 0 0 0
+ table[0x04] = 0x0A0; // U_WMRSETROP2 0 0 1 0 1 0 0 0 0 0
+ table[0x05] = 0x000; // U_WMRSETRELABS 0 0 0 0 0 0 0 0 0 0 No idea what this is supposed to do
+ table[0x06] = 0x0A0; // U_WMRSETPOLYFILLMODE 0 0 1 0 1 0 0 0 0 0
+ table[0x07] = 0x0A0; // U_WMRSETSTRETCHBLTMODE 0 0 1 0 1 0 0 0 0 0
+ table[0x08] = 0x000; // U_WMRSETTEXTCHAREXTRA 0 0 0 0 0 0 0 0 0 0
+ table[0x09] = 0x020; // U_WMRSETTEXTCOLOR 0 0 0 0 1 0 0 0 0 0
+ table[0x0A] = 0x020; // U_WMRSETTEXTJUSTIFICATION 0 0 0 0 1 0 0 0 0 0
+ table[0x0B] = 0x0A0; // U_WMRSETWINDOWORG 0 0 1 0 1 0 0 0 0 0
+ table[0x0C] = 0x0A0; // U_WMRSETWINDOWEXT 0 0 1 0 1 0 0 0 0 0
+ table[0x0D] = 0x0A0; // U_WMRSETVIEWPORTORG 0 0 1 0 1 0 0 0 0 0
+ table[0x0E] = 0x0A0; // U_WMRSETVIEWPORTEXT 0 0 1 0 1 0 0 0 0 0
+ table[0x0F] = 0x000; // U_WMROFFSETWINDOWORG 0 0 0 0 0 0 0 0 0 0
+ table[0x10] = 0x000; // U_WMRSCALEWINDOWEXT 0 0 0 0 0 0 0 0 0 0
+ table[0x11] = 0x0A0; // U_WMROFFSETVIEWPORTORG 0 0 1 0 1 0 0 0 0 0
+ table[0x12] = 0x0A0; // U_WMRSCALEVIEWPORTEXT 0 0 1 0 1 0 0 0 0 0
+ table[0x13] = 0x28B; // U_WMRLINETO 1 0 1 0 0 0 1 0 1 1
+ table[0x14] = 0x289; // U_WMRMOVETO 1 0 1 0 0 0 1 0 0 1
+ table[0x15] = 0x0A0; // U_WMREXCLUDECLIPRECT 0 0 1 0 1 0 0 0 0 0
+ table[0x16] = 0x0A0; // U_WMRINTERSECTCLIPRECT 0 0 1 0 1 0 0 0 0 0
+ table[0x17] = 0x283; // U_WMRARC 1 0 1 0 0 0 0 0 1 1
+ table[0x18] = 0x087; // U_WMRELLIPSE 0 0 1 0 0 0 0 1 1 1
+ table[0x19] = 0x082; // U_WMRFLOODFILL 0 0 1 0 0 0 0 0 1 0
+ table[0x1A] = 0x087; // U_WMRPIE 0 0 1 0 0 0 0 1 1 1
+ table[0x1B] = 0x087; // U_WMRRECTANGLE 0 0 1 0 0 0 0 1 1 1
+ table[0x1C] = 0x087; // U_WMRROUNDRECT 0 0 1 0 0 0 0 1 1 1
+ table[0x1D] = 0x000; // U_WMRPATBLT 0 0 1 0 0 0 0 1 1 1
+ table[0x1E] = 0x0A0; // U_WMRSAVEDC 0 0 1 0 1 0 0 0 0 0
+ table[0x1F] = 0x082; // U_WMRSETPIXEL 0 0 1 0 0 0 0 0 1 0
+ table[0x20] = 0x0A0; // U_WMROFFSETCLIPRGN 0 0 1 0 1 0 0 0 0 0
+ table[0x21] = 0x002; // U_WMRTEXTOUT 0 0 0 0 0 0 0 0 1 0
+ table[0x22] = 0x082; // U_WMRBITBLT 0 0 1 0 0 0 0 0 1 0
+ table[0x23] = 0x082; // U_WMRSTRETCHBLT 0 0 1 0 0 0 0 0 1 0
+ table[0x24] = 0x083; // U_WMRPOLYGON 0 0 1 0 0 0 0 0 1 1
+ table[0x25] = 0x283; // U_WMRPOLYLINE 1 0 1 0 0 0 0 0 1 1
+ table[0x26] = 0x0A0; // U_WMRESCAPE 0 0 1 0 1 0 0 0 0 0
+ table[0x27] = 0x0A0; // U_WMRRESTOREDC 0 0 1 0 1 0 0 0 0 0
+ table[0x28] = 0x082; // U_WMRFILLREGION 0 0 1 0 0 0 0 0 1 0
+ table[0x29] = 0x082; // U_WMRFRAMEREGION 0 0 1 0 0 0 0 0 1 0
+ table[0x2A] = 0x082; // U_WMRINVERTREGION 0 0 1 0 0 0 0 0 1 0
+ table[0x2B] = 0x082; // U_WMRPAINTREGION 0 0 1 0 0 0 0 0 1 0
+ table[0x2C] = 0x0A0; // U_WMRSELECTCLIPREGION 0 0 1 0 1 0 0 0 0 0
+ table[0x2D] = 0x020; // U_WMRSELECTOBJECT 0 0 0 0 1 0 0 0 0 0
+ table[0x2E] = 0x020; // U_WMRSETTEXTALIGN 0 0 0 0 1 0 0 0 0 0
+ table[0x2F] = 0x002; // U_WMRDRAWTEXT 0 0 0 0 0 0 0 0 1 0 no idea what this is supposed to do
+ table[0x30] = 0x087; // U_WMRCHORD 0 0 1 0 0 0 0 1 1 1
+ table[0x31] = 0x0A0; // U_WMRSETMAPPERFLAGS 0 0 1 0 1 0 0 0 0 0
+ table[0x32] = 0x002; // U_WMREXTTEXTOUT 0 0 0 0 0 0 0 0 1 0
+ table[0x33] = 0x000; // U_WMRSETDIBTODEV 0 0 0 0 0 0 0 0 0 0
+ table[0x34] = 0x0A0; // U_WMRSELECTPALETTE 0 0 1 0 1 0 0 0 0 0
+ table[0x35] = 0x0A0; // U_WMRREALIZEPALETTE 0 0 1 0 1 0 0 0 0 0
+ table[0x36] = 0x0A0; // U_WMRANIMATEPALETTE 0 0 1 0 1 0 0 0 0 0
+ table[0x37] = 0x0A0; // U_WMRSETPALENTRIES 0 0 1 0 1 0 0 0 0 0
+ table[0x38] = 0x087; // U_WMRPOLYPOLYGON 0 0 1 0 0 0 0 1 1 1
+ table[0x39] = 0x0A0; // U_WMRRESIZEPALETTE 0 0 1 0 1 0 0 0 0 0
+ table[0x3A] = 0x000; // U_WMR3A 0 0 0 0 0 0 0 0 0 0
+ table[0x3B] = 0x000; // U_WMR3B 0 0 0 0 0 0 0 0 0 0
+ table[0x3C] = 0x000; // U_WMR3C 0 0 0 0 0 0 0 0 0 0
+ table[0x3D] = 0x000; // U_WMR3D 0 0 0 0 0 0 0 0 0 0
+ table[0x3E] = 0x000; // U_WMR3E 0 0 0 0 0 0 0 0 0 0
+ table[0x3F] = 0x000; // U_WMR3F 0 0 0 0 0 0 0 0 0 0
+ table[0x40] = 0x0A0; // U_WMRDIBBITBLT 0 0 1 0 1 0 0 0 0 0
+ table[0x41] = 0x0A0; // U_WMRDIBSTRETCHBLT 0 0 1 0 1 0 0 0 0 0
+ table[0x42] = 0x080; // U_WMRDIBCREATEPATTERNBRUSH 0 0 1 0 0 0 0 0 0 0 Not selected yet, so no change in drawing conditions
+ table[0x43] = 0x0A0; // U_WMRSTRETCHDIB 0 0 1 0 1 0 0 0 0 0
+ table[0x44] = 0x000; // U_WMR44 0 0 0 0 0 0 0 0 0 0
+ table[0x45] = 0x000; // U_WMR45 0 0 0 0 0 0 0 0 0 0
+ table[0x46] = 0x000; // U_WMR46 0 0 0 0 0 0 0 0 0 0
+ table[0x47] = 0x000; // U_WMR47 0 0 0 0 0 0 0 0 0 0
+ table[0x48] = 0x082; // U_WMREXTFLOODFILL 0 0 1 0 0 0 0 0 1 0
+ table[0x49] = 0x000; // U_WMR49 0 0 0 0 0 0 0 0 0 0
+ table[0x4A] = 0x000; // U_WMR4A 0 0 0 0 0 0 0 0 0 0
+ table[0x4B] = 0x000; // U_WMR4B 0 0 0 0 0 0 0 0 0 0
+ table[0x4C] = 0x000; // U_WMR4C 0 0 0 0 0 0 0 0 0 0
+ table[0x4D] = 0x000; // U_WMR4D 0 0 0 0 0 0 0 0 0 0
+ table[0x4E] = 0x000; // U_WMR4E 0 0 0 0 0 0 0 0 0 0
+ table[0x4F] = 0x000; // U_WMR4F 0 0 0 0 0 0 0 0 0 0
+ table[0x50] = 0x000; // U_WMR50 0 0 0 0 0 0 0 0 0 0
+ table[0x51] = 0x000; // U_WMR51 0 0 0 0 0 0 0 0 0 0
+ table[0x52] = 0x000; // U_WMR52 0 0 0 0 0 0 0 0 0 0
+ table[0x53] = 0x000; // U_WMR53 0 0 0 0 0 0 0 0 0 0
+ table[0x54] = 0x000; // U_WMR54 0 0 0 0 0 0 0 0 0 0
+ table[0x55] = 0x000; // U_WMR55 0 0 0 0 0 0 0 0 0 0
+ table[0x56] = 0x000; // U_WMR56 0 0 0 0 0 0 0 0 0 0
+ table[0x57] = 0x000; // U_WMR57 0 0 0 0 0 0 0 0 0 0
+ table[0x58] = 0x000; // U_WMR58 0 0 0 0 0 0 0 0 0 0
+ table[0x59] = 0x000; // U_WMR59 0 0 0 0 0 0 0 0 0 0
+ table[0x5A] = 0x000; // U_WMR5A 0 0 0 0 0 0 0 0 0 0
+ table[0x5B] = 0x000; // U_WMR5B 0 0 0 0 0 0 0 0 0 0
+ table[0x5C] = 0x000; // U_WMR5C 0 0 0 0 0 0 0 0 0 0
+ table[0x5D] = 0x000; // U_WMR5D 0 0 0 0 0 0 0 0 0 0
+ table[0x5E] = 0x000; // U_WMR5E 0 0 0 0 0 0 0 0 0 0
+ table[0x5F] = 0x000; // U_WMR5F 0 0 0 0 0 0 0 0 0 0
+ table[0x60] = 0x000; // U_WMR60 0 0 0 0 0 0 0 0 0 0
+ table[0x61] = 0x000; // U_WMR61 0 0 0 0 0 0 0 0 0 0
+ table[0x62] = 0x000; // U_WMR62 0 0 0 0 0 0 0 0 0 0
+ table[0x63] = 0x000; // U_WMR63 0 0 0 0 0 0 0 0 0 0
+ table[0x64] = 0x000; // U_WMR64 0 0 0 0 0 0 0 0 0 0
+ table[0x65] = 0x000; // U_WMR65 0 0 0 0 0 0 0 0 0 0
+ table[0x66] = 0x000; // U_WMR66 0 0 0 0 0 0 0 0 0 0
+ table[0x67] = 0x000; // U_WMR67 0 0 0 0 0 0 0 0 0 0
+ table[0x68] = 0x000; // U_WMR68 0 0 0 0 0 0 0 0 0 0
+ table[0x69] = 0x000; // U_WMR69 0 0 0 0 0 0 0 0 0 0
+ table[0x6A] = 0x000; // U_WMR6A 0 0 0 0 0 0 0 0 0 0
+ table[0x6B] = 0x000; // U_WMR6B 0 0 0 0 0 0 0 0 0 0
+ table[0x6C] = 0x000; // U_WMR6C 0 0 0 0 0 0 0 0 0 0
+ table[0x6D] = 0x000; // U_WMR6D 0 0 0 0 0 0 0 0 0 0
+ table[0x6E] = 0x000; // U_WMR6E 0 0 0 0 0 0 0 0 0 0
+ table[0x6F] = 0x000; // U_WMR6F 0 0 0 0 0 0 0 0 0 0
+ table[0x70] = 0x000; // U_WMR70 0 0 0 0 0 0 0 0 0 0
+ table[0x71] = 0x000; // U_WMR71 0 0 0 0 0 0 0 0 0 0
+ table[0x72] = 0x000; // U_WMR72 0 0 0 0 0 0 0 0 0 0
+ table[0x73] = 0x000; // U_WMR73 0 0 0 0 0 0 0 0 0 0
+ table[0x74] = 0x000; // U_WMR74 0 0 0 0 0 0 0 0 0 0
+ table[0x75] = 0x000; // U_WMR75 0 0 0 0 0 0 0 0 0 0
+ table[0x76] = 0x000; // U_WMR76 0 0 0 0 0 0 0 0 0 0
+ table[0x77] = 0x000; // U_WMR77 0 0 0 0 0 0 0 0 0 0
+ table[0x78] = 0x000; // U_WMR78 0 0 0 0 0 0 0 0 0 0
+ table[0x79] = 0x000; // U_WMR79 0 0 0 0 0 0 0 0 0 0
+ table[0x7A] = 0x000; // U_WMR7A 0 0 0 0 0 0 0 0 0 0
+ table[0x7B] = 0x000; // U_WMR7B 0 0 0 0 0 0 0 0 0 0
+ table[0x7C] = 0x000; // U_WMR7C 0 0 0 0 0 0 0 0 0 0
+ table[0x7D] = 0x000; // U_WMR7D 0 0 0 0 0 0 0 0 0 0
+ table[0x7E] = 0x000; // U_WMR7E 0 0 0 0 0 0 0 0 0 0
+ table[0x7F] = 0x000; // U_WMR7F 0 0 0 0 0 0 0 0 0 0
+ table[0x80] = 0x000; // U_WMR80 0 0 0 0 0 0 0 0 0 0
+ table[0x81] = 0x000; // U_WMR81 0 0 0 0 0 0 0 0 0 0
+ table[0x82] = 0x000; // U_WMR82 0 0 0 0 0 0 0 0 0 0
+ table[0x83] = 0x000; // U_WMR83 0 0 0 0 0 0 0 0 0 0
+ table[0x84] = 0x000; // U_WMR84 0 0 0 0 0 0 0 0 0 0
+ table[0x85] = 0x000; // U_WMR85 0 0 0 0 0 0 0 0 0 0
+ table[0x86] = 0x000; // U_WMR86 0 0 0 0 0 0 0 0 0 0
+ table[0x87] = 0x000; // U_WMR87 0 0 0 0 0 0 0 0 0 0
+ table[0x88] = 0x000; // U_WMR88 0 0 0 0 0 0 0 0 0 0
+ table[0x89] = 0x000; // U_WMR89 0 0 0 0 0 0 0 0 0 0
+ table[0x8A] = 0x000; // U_WMR8A 0 0 0 0 0 0 0 0 0 0
+ table[0x8B] = 0x000; // U_WMR8B 0 0 0 0 0 0 0 0 0 0
+ table[0x8C] = 0x000; // U_WMR8C 0 0 0 0 0 0 0 0 0 0
+ table[0x8D] = 0x000; // U_WMR8D 0 0 0 0 0 0 0 0 0 0
+ table[0x8E] = 0x000; // U_WMR8E 0 0 0 0 0 0 0 0 0 0
+ table[0x8F] = 0x000; // U_WMR8F 0 0 0 0 0 0 0 0 0 0
+ table[0x90] = 0x000; // U_WMR90 0 0 0 0 0 0 0 0 0 0
+ table[0x91] = 0x000; // U_WMR91 0 0 0 0 0 0 0 0 0 0
+ table[0x92] = 0x000; // U_WMR92 0 0 0 0 0 0 0 0 0 0
+ table[0x93] = 0x000; // U_WMR93 0 0 0 0 0 0 0 0 0 0
+ table[0x94] = 0x000; // U_WMR94 0 0 0 0 0 0 0 0 0 0
+ table[0x95] = 0x000; // U_WMR95 0 0 0 0 0 0 0 0 0 0
+ table[0x96] = 0x000; // U_WMR96 0 0 0 0 0 0 0 0 0 0
+ table[0x97] = 0x000; // U_WMR97 0 0 0 0 0 0 0 0 0 0
+ table[0x98] = 0x000; // U_WMR98 0 0 0 0 0 0 0 0 0 0
+ table[0x99] = 0x000; // U_WMR99 0 0 0 0 0 0 0 0 0 0
+ table[0x9A] = 0x000; // U_WMR9A 0 0 0 0 0 0 0 0 0 0
+ table[0x9B] = 0x000; // U_WMR9B 0 0 0 0 0 0 0 0 0 0
+ table[0x9C] = 0x000; // U_WMR9C 0 0 0 0 0 0 0 0 0 0
+ table[0x9D] = 0x000; // U_WMR9D 0 0 0 0 0 0 0 0 0 0
+ table[0x9E] = 0x000; // U_WMR9E 0 0 0 0 0 0 0 0 0 0
+ table[0x9F] = 0x000; // U_WMR9F 0 0 0 0 0 0 0 0 0 0
+ table[0xA0] = 0x000; // U_WMRA0 0 0 0 0 0 0 0 0 0 0
+ table[0xA1] = 0x000; // U_WMRA1 0 0 0 0 0 0 0 0 0 0
+ table[0xA2] = 0x000; // U_WMRA2 0 0 0 0 0 0 0 0 0 0
+ table[0xA3] = 0x000; // U_WMRA3 0 0 0 0 0 0 0 0 0 0
+ table[0xA4] = 0x000; // U_WMRA4 0 0 0 0 0 0 0 0 0 0
+ table[0xA5] = 0x000; // U_WMRA5 0 0 0 0 0 0 0 0 0 0
+ table[0xA6] = 0x000; // U_WMRA6 0 0 0 0 0 0 0 0 0 0
+ table[0xA7] = 0x000; // U_WMRA7 0 0 0 0 0 0 0 0 0 0
+ table[0xA8] = 0x000; // U_WMRA8 0 0 0 0 0 0 0 0 0 0
+ table[0xA9] = 0x000; // U_WMRA9 0 0 0 0 0 0 0 0 0 0
+ table[0xAA] = 0x000; // U_WMRAA 0 0 0 0 0 0 0 0 0 0
+ table[0xAB] = 0x000; // U_WMRAB 0 0 0 0 0 0 0 0 0 0
+ table[0xAC] = 0x000; // U_WMRAC 0 0 0 0 0 0 0 0 0 0
+ table[0xAD] = 0x000; // U_WMRAD 0 0 0 0 0 0 0 0 0 0
+ table[0xAE] = 0x000; // U_WMRAE 0 0 0 0 0 0 0 0 0 0
+ table[0xAF] = 0x000; // U_WMRAF 0 0 0 0 0 0 0 0 0 0
+ table[0xB0] = 0x000; // U_WMRB0 0 0 0 0 0 0 0 0 0 0
+ table[0xB1] = 0x000; // U_WMRB1 0 0 0 0 0 0 0 0 0 0
+ table[0xB2] = 0x000; // U_WMRB2 0 0 0 0 0 0 0 0 0 0
+ table[0xB3] = 0x000; // U_WMRB3 0 0 0 0 0 0 0 0 0 0
+ table[0xB4] = 0x000; // U_WMRB4 0 0 0 0 0 0 0 0 0 0
+ table[0xB5] = 0x000; // U_WMRB5 0 0 0 0 0 0 0 0 0 0
+ table[0xB6] = 0x000; // U_WMRB6 0 0 0 0 0 0 0 0 0 0
+ table[0xB7] = 0x000; // U_WMRB7 0 0 0 0 0 0 0 0 0 0
+ table[0xB8] = 0x000; // U_WMRB8 0 0 0 0 0 0 0 0 0 0
+ table[0xB9] = 0x000; // U_WMRB9 0 0 0 0 0 0 0 0 0 0
+ table[0xBA] = 0x000; // U_WMRBA 0 0 0 0 0 0 0 0 0 0
+ table[0xBB] = 0x000; // U_WMRBB 0 0 0 0 0 0 0 0 0 0
+ table[0xBC] = 0x000; // U_WMRBC 0 0 0 0 0 0 0 0 0 0
+ table[0xBD] = 0x000; // U_WMRBD 0 0 0 0 0 0 0 0 0 0
+ table[0xBE] = 0x000; // U_WMRBE 0 0 0 0 0 0 0 0 0 0
+ table[0xBF] = 0x000; // U_WMRBF 0 0 0 0 0 0 0 0 0 0
+ table[0xC0] = 0x000; // U_WMRC0 0 0 0 0 0 0 0 0 0 0
+ table[0xC1] = 0x000; // U_WMRC1 0 0 0 0 0 0 0 0 0 0
+ table[0xC2] = 0x000; // U_WMRC2 0 0 0 0 0 0 0 0 0 0
+ table[0xC3] = 0x000; // U_WMRC3 0 0 0 0 0 0 0 0 0 0
+ table[0xC4] = 0x000; // U_WMRC4 0 0 0 0 0 0 0 0 0 0
+ table[0xC5] = 0x000; // U_WMRC5 0 0 0 0 0 0 0 0 0 0
+ table[0xC6] = 0x000; // U_WMRC6 0 0 0 0 0 0 0 0 0 0
+ table[0xC7] = 0x000; // U_WMRC7 0 0 0 0 0 0 0 0 0 0
+ table[0xC8] = 0x000; // U_WMRC8 0 0 0 0 0 0 0 0 0 0
+ table[0xC9] = 0x000; // U_WMRC9 0 0 0 0 0 0 0 0 0 0
+ table[0xCA] = 0x000; // U_WMRCA 0 0 0 0 0 0 0 0 0 0
+ table[0xCB] = 0x000; // U_WMRCB 0 0 0 0 0 0 0 0 0 0
+ table[0xCC] = 0x000; // U_WMRCC 0 0 0 0 0 0 0 0 0 0
+ table[0xCD] = 0x000; // U_WMRCD 0 0 0 0 0 0 0 0 0 0
+ table[0xCE] = 0x000; // U_WMRCE 0 0 0 0 0 0 0 0 0 0
+ table[0xCF] = 0x000; // U_WMRCF 0 0 0 0 0 0 0 0 0 0
+ table[0xD0] = 0x000; // U_WMRD0 0 0 0 0 0 0 0 0 0 0
+ table[0xD1] = 0x000; // U_WMRD1 0 0 0 0 0 0 0 0 0 0
+ table[0xD2] = 0x000; // U_WMRD2 0 0 0 0 0 0 0 0 0 0
+ table[0xD3] = 0x000; // U_WMRD3 0 0 0 0 0 0 0 0 0 0
+ table[0xD4] = 0x000; // U_WMRD4 0 0 0 0 0 0 0 0 0 0
+ table[0xD5] = 0x000; // U_WMRD5 0 0 0 0 0 0 0 0 0 0
+ table[0xD6] = 0x000; // U_WMRD6 0 0 0 0 0 0 0 0 0 0
+ table[0xD7] = 0x000; // U_WMRD7 0 0 0 0 0 0 0 0 0 0
+ table[0xD8] = 0x000; // U_WMRD8 0 0 0 0 0 0 0 0 0 0
+ table[0xD9] = 0x000; // U_WMRD9 0 0 0 0 0 0 0 0 0 0
+ table[0xDA] = 0x000; // U_WMRDA 0 0 0 0 0 0 0 0 0 0
+ table[0xDB] = 0x000; // U_WMRDB 0 0 0 0 0 0 0 0 0 0
+ table[0xDC] = 0x000; // U_WMRDC 0 0 0 0 0 0 0 0 0 0
+ table[0xDD] = 0x000; // U_WMRDD 0 0 0 0 0 0 0 0 0 0
+ table[0xDE] = 0x000; // U_WMRDE 0 0 0 0 0 0 0 0 0 0
+ table[0xDF] = 0x000; // U_WMRDF 0 0 0 0 0 0 0 0 0 0
+ table[0xE0] = 0x000; // U_WMRE0 0 0 0 0 0 0 0 0 0 0
+ table[0xE1] = 0x000; // U_WMRE1 0 0 0 0 0 0 0 0 0 0
+ table[0xE2] = 0x000; // U_WMRE2 0 0 0 0 0 0 0 0 0 0
+ table[0xE3] = 0x000; // U_WMRE3 0 0 0 0 0 0 0 0 0 0
+ table[0xE4] = 0x000; // U_WMRE4 0 0 0 0 0 0 0 0 0 0
+ table[0xE5] = 0x000; // U_WMRE5 0 0 0 0 0 0 0 0 0 0
+ table[0xE6] = 0x000; // U_WMRE6 0 0 0 0 0 0 0 0 0 0
+ table[0xE7] = 0x000; // U_WMRE7 0 0 0 0 0 0 0 0 0 0
+ table[0xE8] = 0x000; // U_WMRE8 0 0 0 0 0 0 0 0 0 0
+ table[0xE9] = 0x000; // U_WMRE9 0 0 0 0 0 0 0 0 0 0
+ table[0xEA] = 0x000; // U_WMREA 0 0 0 0 0 0 0 0 0 0
+ table[0xEB] = 0x000; // U_WMREB 0 0 0 0 0 0 0 0 0 0
+ table[0xEC] = 0x000; // U_WMREC 0 0 0 0 0 0 0 0 0 0
+ table[0xED] = 0x000; // U_WMRED 0 0 0 0 0 0 0 0 0 0
+ table[0xEE] = 0x000; // U_WMREE 0 0 0 0 0 0 0 0 0 0
+ table[0xEF] = 0x000; // U_WMREF 0 0 0 0 0 0 0 0 0 0
+ table[0xF0] = 0x020; // U_WMRDELETEOBJECT 0 0 0 0 1 0 0 0 0 0
+ table[0xF1] = 0x000; // U_WMRF1 0 0 0 0 0 0 0 0 0 0
+ table[0xF2] = 0x000; // U_WMRF2 0 0 0 0 0 0 0 0 0 0
+ table[0xF3] = 0x000; // U_WMRF3 0 0 0 0 0 0 0 0 0 0
+ table[0xF4] = 0x000; // U_WMRF4 0 0 0 0 0 0 0 0 0 0
+ table[0xF5] = 0x000; // U_WMRF5 0 0 0 0 0 0 0 0 0 0
+ table[0xF6] = 0x000; // U_WMRF6 0 0 0 0 0 0 0 0 0 0
+ table[0xF7] = 0x120; // U_WMRCREATEPALETTE 0 1 0 0 1 0 0 0 0 0 Not selected yet, so no change in drawing conditions
+ table[0xF8] = 0x120; // U_WMRCREATEBRUSH 0 1 0 0 1 0 0 0 0 0 "
+ table[0xF9] = 0x120; // U_WMRCREATEPATTERNBRUSH 0 1 0 0 1 0 0 0 0 0 "
+ table[0xFA] = 0x120; // U_WMRCREATEPENINDIRECT 0 1 0 0 1 0 0 0 0 0 "
+ table[0xFB] = 0x120; // U_WMRCREATEFONTINDIRECT 0 1 0 0 1 0 0 0 0 0 "
+ table[0xFC] = 0x120; // U_WMRCREATEBRUSHINDIRECT 0 1 0 0 1 0 0 0 0 0 "
+ table[0xFD] = 0x020; // U_WMRCREATEBITMAPINDIRECT 0 0 0 0 1 0 0 0 0 0 "
+ table[0xFE] = 0x020; // U_WMRCREATEBITMAP 0 0 0 0 1 0 0 0 0 0 "
+ table[0xFF] = 0x120; // U_WMRCREATEREGION 0 1 0 0 1 0 0 0 0 0 "
+ }
+ result = table[type];
+ }
+ return(result);
+}
+
+/* **********************************************************************************************
+These functions are for setting up, appending to, and then tearing down an WMF structure, including
+writing the final data structure out to a file.
+*********************************************************************************************** */
+
+/**
+ \brief Duplicate an WMR record.
+ \param wmr record to duplicate
+*/
+char *wmr_dup(
+ const char *wmr
+ ){
+ char *dup;
+ uint32_t irecsize;
+
+ if(!wmr)return(NULL);
+ memcpy(&irecsize,wmr,4); /* Size16_4 field is at offset 0 */
+ irecsize *= 2;
+ dup=malloc(irecsize);
+ if(dup){ memcpy(dup,wmr,irecsize); }
+ return(dup);
+}
+
+
+/* some of these functions are identical to the emf ones, handled by defines in uemf.h,use the emf versions */
+
+/**
+ \brief Start constructing an wmf in memory. Supply the file name and initial size.
+ \return 0 for success, >=0 for failure.
+ \param name WMF filename (will be opened)
+ \param initsize Initialize WMF in memory to hold this many bytes
+ \param chunksize When needed increase WMF in memory by this number of bytes
+ \param wt WMF in memory
+
+
+*/
+int wmf_start(
+ const char *name,
+ const uint32_t initsize,
+ const uint32_t chunksize,
+ WMFTRACK **wt
+ ){
+ FILE *fp;
+ WMFTRACK *wtl=NULL;
+
+ if(initsize < 1)return(1);
+ if(chunksize < 1)return(2);
+ if(!name)return(3);
+ wtl = (WMFTRACK *) malloc(sizeof(WMFTRACK));
+ if(!wtl)return(4);
+ wtl->buf = malloc(initsize); // no need to zero the memory
+ if(!wtl->buf){
+ free(wtl);
+ return(5);
+ }
+ fp=wmf_fopen(name,U_WRITE);
+ if(!fp){
+ free(wtl->buf);
+ free(wtl);
+ return(6);
+ }
+ wtl->fp = fp;
+ wtl->allocated = initsize;
+ wtl->used = 0;
+ wtl->records = 0;
+ wtl->PalEntries = 0;
+ wtl->chunk = chunksize;
+ wtl->largest = 0; /* only used by WMF */
+ wtl->sumObjects = 0; /* only used by WMF */
+ (void) wmf_highwater(U_HIGHWATER_CLEAR);
+ *wt=wtl;
+ return(0);
+}
+
+/**
+ \brief Release memory for an wmf structure in memory. Call this after wmf_finish().
+ \return 0 on success, >=1 on failure
+ \param wt WMF in memory
+ Renamed to uwmf_free to avoid conflict with libwmf
+*/
+int uwmf_free(
+ WMFTRACK **wt
+ ){
+ WMFTRACK *wtl;
+ if(!wt)return(1);
+ wtl=*wt;
+ if(!wtl)return(2);
+ free(wtl->buf);
+ free(wtl);
+ *wt=NULL;
+ (void)wmf_highwater(U_HIGHWATER_CLEAR);
+ return(0);
+}
+
+/**
+ \brief Finalize the emf in memory and write it to the file.
+ \return 0 on success, >=1 on failure
+ \param wt WMF in memory
+*/
+int wmf_finish(
+ WMFTRACK *wt
+ ){
+ char *record;
+ int off;
+ uint32_t tmp;
+ uint16_t tmp16;
+
+ if(!wt->fp)return(1); // This could happen if something stomps on memory, otherwise should be caught in wmf_start
+
+ // Set the header fields which were unknown up until this point
+
+
+ if(((U_WMRPLACEABLE *) wt->buf)->Key == 0x9AC6CDD7){ off = U_SIZE_WMRPLACEABLE; }
+ else { off = 0; }
+
+ record = (wt->buf + off);
+ tmp = (wt->used)/2;
+ memcpy(record + offsetof(U_WMRHEADER,Sizew), &tmp, 4); /* 16 bit words in file. not aligned */
+ tmp = (wt->largest)/2;
+ memcpy(record + offsetof(U_WMRHEADER,maxSize), &tmp, 4); /* 16 bit words in largest record, not aligned */
+ uint32_t maxobj = wmf_highwater(U_HIGHWATER_READ);
+ if(maxobj > UINT16_MAX)return(3);
+ tmp16 = maxobj;
+ memcpy(record + offsetof(U_WMRHEADER,nObjects), &tmp16, 2); /* Total number of brushes, pens, and other graphics objects defined in this file */
+
+#if U_BYTE_SWAP
+ //This is a Big Endian machine, WMF data must be Little Endian
+ U_wmf_endian(wt->buf,wt->used,1,0); // BE to LE, entire file
+#endif
+
+ (void) U_wmr_properties(U_WMR_INVALID); /* force the release of the lookup table memory, returned value is irrelevant */
+ if(1 != fwrite(wt->buf,wt->used,1,wt->fp))return(2);
+ (void) fclose(wt->fp);
+ wt->fp=NULL;
+ return(0);
+}
+
+/**
+ \brief Retrieve contents of an WMF file by name.
+ \return 0 on success, >=1 on failure
+ \param filename Name of file to open, including the path
+ \param contents Contents of the file. Buffer must be free()'d by caller.
+ \param length Number of bytes in Contents
+*/
+int wmf_readdata(
+ const char *filename,
+ char **contents,
+ size_t *length
+ ){
+ FILE *fp;
+ int status=0;
+
+ *contents=NULL;
+ fp=wmf_fopen(filename,U_READ);
+ if(!fp){ status = 1; }
+ else {
+ // read the entire file into memory
+ fseek(fp, 0, SEEK_END); // move to end
+ *length = ftell(fp);
+ rewind(fp);
+ *contents = (char *) malloc(*length);
+ if(!*contents){
+ status = 2;
+ }
+ else {
+ size_t inbytes = fread(*contents,*length,1,fp);
+ if(inbytes != 1){
+ free(*contents);
+ status = 3;
+ }
+ else {
+#if U_BYTE_SWAP
+ //This is a Big Endian machine, WMF data is Little Endian
+ U_wmf_endian(*contents,*length,0,0); // LE to BE, entire file
+#endif
+ }
+ }
+ fclose(fp);
+ }
+ return(status);
+}
+
+/**
+ \brief Append an WMF record to a wmf in memory. This may reallocate buf memory.
+ \return 0 for success, >=1 for failure.
+ \param rec Record to append to WMF in memory
+ \param wt WMF in memory
+ \param freerec If true, free rec after append
+*/
+int wmf_append(
+ U_METARECORD *rec,
+ WMFTRACK *wt,
+ int freerec
+ ){
+ size_t deficit;
+ uint32_t wp;
+ uint32_t size;
+
+ size = U_wmr_size(rec);
+#ifdef U_VALGRIND
+ printf("\nbefore \n");
+ printf(" probe %d\n",memprobe(rec, size));
+ printf("after \n");
+#endif
+ if(!rec)return(1);
+ if(!wt)return(2);
+ if(size + wt->used > wt->allocated){
+ deficit = size + wt->used - wt->allocated;
+ if(deficit < wt->chunk)deficit = wt->chunk;
+ wt->allocated += deficit;
+ wt->buf = realloc(wt->buf,wt->allocated);
+ if(!wt->buf)return(3);
+ }
+ memcpy(wt->buf + wt->used, rec, size);
+ wt->used += size;
+ wt->records++;
+ if(wt->largest < size)wt->largest=size;
+ /* does the record create an object: brush, font, palette, pen, or region ?
+ Following EOF properties comes back as U_WMR_INVALID */
+ wp = U_wmr_properties(U_WMRTYPE(rec));
+ if((wp != U_WMR_INVALID) && (U_DRAW_OBJECT & wp))wt->sumObjects++;
+ if(freerec){ free(rec); }
+ return(0);
+}
+
+/**
+ \brief Append an WMF header to a wmf in memory. This may reallocate buf memory.
+ WMF header is not a normal record, method used to figure out its size is different.
+ \return 0 for success, >=1 for failure.
+ \param rec header to append to WMF in memory
+ \param wt WMF in memory
+ \param freerec If true, free rec after append
+*/
+int wmf_header_append(
+ U_METARECORD *rec,
+ WMFTRACK *wt,
+ int freerec
+ ){
+ size_t deficit;
+ unsigned int hsize;
+
+ hsize = (((U_WMRPLACEABLE *) rec)->Key == 0x9AC6CDD7 ? U_SIZE_WMRHEADER + U_SIZE_WMRPLACEABLE: U_SIZE_WMRHEADER);
+
+#ifdef U_VALGRIND
+ printf("\nbefore \n");
+ printf(" probe %d\n",memprobe(rec, hsize));
+ printf("after \n");
+#endif
+ if(!rec)return(1);
+ if(!wt)return(2);
+ if(U_wmr_size(rec) + wt->used > wt->allocated){
+ deficit = hsize + wt->used - wt->allocated;
+ if(deficit < wt->chunk)deficit = wt->chunk;
+ wt->allocated += deficit;
+ wt->buf = realloc(wt->buf,wt->allocated);
+ if(!wt->buf)return(3);
+ }
+ memcpy(wt->buf + wt->used, rec, hsize);
+ wt->used += hsize;
+ /* do NOT increment records count, this is not strictly a record */
+ if(wt->largest < hsize)wt->largest=hsize;
+ if(freerec){ free(rec); }
+ return(0);
+}
+
+/**
+ \brief Keep track of the largest number used.
+ \return The largest object number used.
+ \param setval U_HIGHWATER_READ only return value, U_HIGHWATER_CLEAR also set value to 0, anything else, set to this if higher than stored.
+*/
+int wmf_highwater(uint32_t setval){
+ static uint32_t value=0;
+ uint32_t retval;
+ if(setval == U_HIGHWATER_READ){
+ retval = value;
+ }
+ else if(setval == U_HIGHWATER_CLEAR){
+ retval = value;
+ value = 0;
+ }
+ else {
+ if(setval > value)value = setval;
+ retval = value;
+ }
+ return(retval);
+}
+
+/**
+ \brief Create a handle table. Entries filled with 0 are empty, entries >0 hold a handle.
+ \return 0 for success, >=1 for failure.
+ \param initsize Initialize with space for this number of handles
+ \param chunksize When needed increase space by this number of handles
+ \param wht WMF handle table
+*/
+int wmf_htable_create(
+ uint32_t initsize,
+ uint32_t chunksize,
+ WMFHANDLES **wht
+ ){
+ WMFHANDLES *whtl;
+
+ if(initsize<1)return(1);
+ if(chunksize<1)return(2);
+ whtl = (WMFHANDLES *) malloc(sizeof(WMFHANDLES));
+ if(!whtl)return(3);
+ whtl->table = malloc(initsize * sizeof(uint32_t));
+ if(!whtl->table){
+ free(whtl);
+ return(4);
+ }
+ memset(whtl->table , 0, initsize * sizeof(uint32_t)); // zero all slots in the table
+ whtl->allocated = initsize;
+ whtl->chunk = chunksize;
+ whtl->table[0] = 0; // This slot isn't actually ever used
+ whtl->lolimit = 1; // first available table entry
+ whtl->hilimit = 0; // no entries in the table yet.
+ whtl->peak = 0; // no entries in the table ever
+ *wht = whtl;
+ return(0);
+}
+
+/**
+ \brief Delete an entry from the handle table. Move it back onto the stack. The specified slot is filled with a 0.
+ \return 0 for success, >=1 for failure.
+ \param ih handle
+ \param wht WMF handle table
+
+*/
+int wmf_htable_delete(
+ uint32_t *ih,
+ WMFHANDLES *wht
+ ){
+ if(!wht)return(1);
+ if(!wht->table)return(2);
+ if(*ih < 1)return(4); // invalid handle
+ if(!wht->table[*ih])return(5); // requested table position was not in use
+ wht->table[*ih]=0; // remove handle from table
+ while(wht->hilimit>0 && !wht->table[wht->hilimit]){ // adjust hilimit
+ wht->hilimit--;
+ }
+ if(*ih < wht->lolimit)wht->lolimit = *ih; // adjust lolimit
+ *ih=0; // invalidate handle variable, so a second delete will of it is not possible
+ return(0);
+}
+
+/**
+ \brief Returns the index of the first free slot.
+ Call realloc() if needed. The slot is set to handle (indicates occupied) and the peak value is adjusted.
+ \return 0 for success, >=1 for failure.
+ \param ih handle
+ \param wht WMF handle table
+*/
+int wmf_htable_insert(
+ uint32_t *ih,
+ WMFHANDLES *wht
+ ){
+ size_t newsize;
+
+ if(!wht)return(1);
+ if(!wht->table)return(2);
+ if(!ih)return(4);
+ if(wht->lolimit >= wht->allocated - 1){ // need to reallocate
+ newsize=wht->allocated + wht->chunk;
+ wht->table = realloc(wht->table,newsize * sizeof(uint32_t));
+ if(!wht->table)return(5);
+ memset(&wht->table[wht->allocated] , 0, wht->chunk * sizeof(uint32_t)); // zero all NEW slots in the table
+ wht->allocated = newsize;
+ }
+ *ih = wht->lolimit; // handle that is inserted in first available slot
+ wht->table[*ih] = *ih; // handle goes into preexisting (but zero) slot in table, handle number is the same as the slot number
+ if(*ih > wht->hilimit){
+ wht->hilimit = *ih;
+ (void) wmf_highwater(wht->hilimit);
+ }
+ if(*ih > wht->peak){
+ wht->peak = *ih;
+ }
+ /* Find the next available slot, it will be at least one higher than the present position, and will have a zero in it. */
+ wht->lolimit++;
+ while(wht->lolimit<= wht->hilimit && wht->table[wht->lolimit]){ wht->lolimit++; }
+ return(0);
+}
+
+/**
+ \brief Free all memory in an htable. Sets the pointer to NULL.
+ \return 0 for success, >=1 for failure.
+ \param wht WMF handle table
+*/
+int wmf_htable_free(
+ WMFHANDLES **wht
+ ){
+ WMFHANDLES *whtl;
+ if(!wht)return(1);
+ whtl = *wht;
+ if(!whtl)return(2);
+ if(!whtl->table)return(3);
+ free(whtl->table);
+ free(whtl);
+ *wht=NULL;
+ return(0);
+}
+
+
+/* **********************************************************************************************
+These functions create standard structures used in the WMR records.
+*********************************************************************************************** */
+
+// hide these from Doxygen
+//! \cond
+/* **********************************************************************************************
+These functions contain shared code used by various U_WMR*_print functions. These should NEVER be called
+by end user code and to further that end prototypes are NOT provided and they are hidden from Doxygen.
+*********************************************************************************************** */
+
+/* These definitons only used here */
+#define U_SIZE_WMR_NOARGS 6
+#define U_SIZE_WMR_1ARG16 8
+#define U_SIZE_WMR_2ARG16 10
+#define U_SIZE_WMR_3ARG16 12
+#define U_SIZE_WMR_4ARG16 14
+#define U_SIZE_WMR_5ARG16 16
+#define U_SIZE_WMR_6ARG16 18
+#define U_SIZE_WMR_8ARG16 22
+
+char *U_WMRCORENONE_set(char *string){
+ printf("unimplemented creator for:%s\n",string);
+ return(NULL);
+}
+
+void U_WMRCORE_SETRECHEAD(char *record, uint32_t irecsize, int iType){
+ uint32_t Size16;
+ Size16 = irecsize/2;
+ memcpy(record,&Size16,4); /*Size16_4 is at offset 0 in the record */
+ ((U_METARECORD *) record)->iType = iType;
+ ((U_METARECORD *) record)->xb = U_WMR_XB_FROM_TYPE(iType);
+}
+
+/* records that have no arguments */
+char *U_WMRCORE_NOARGS_set(
+ int iType
+){
+ char *record=NULL;
+ uint32_t irecsize;
+ irecsize = U_SIZE_METARECORD;
+ record = malloc(irecsize);
+ if(record)U_WMRCORE_SETRECHEAD(record,irecsize,iType);
+ return(record);
+}
+
+
+/* records like U_WMRFLOODFILL and others. all args are optional, Color is not */
+char *U_WMRCORE_1U16_CRF_2U16_set(
+ int iType,
+ uint16_t *arg1,
+ U_COLORREF Color,
+ uint16_t *arg2,
+ uint16_t *arg3
+){
+ char *record=NULL;
+ uint32_t irecsize,off;
+ irecsize = U_SIZE_METARECORD + U_SIZE_COLORREF;
+ if(arg1)irecsize+=2;
+ if(arg2)irecsize+=2;
+ if(arg3)irecsize+=2;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,iType);
+ off = U_SIZE_METARECORD;
+ if(arg1){ memcpy(record + off, arg1, 2); off+=2; }
+ memcpy(record + off, &Color, 4); off+=4;
+ if(arg2){ memcpy(record + off, arg2, 2); off+=2; }
+ if(arg3){ memcpy(record + off, arg3, 2); }
+ }
+ return(record);
+}
+
+/* records that have a single uint16_t argument like U_WMRSETMAPMODE
+ May also be used with int16_t with appropriate casts */
+char *U_WMRCORE_1U16_set(
+ int iType,
+ uint16_t arg1
+){
+ char *record=NULL;
+ uint32_t irecsize,off;
+ irecsize = U_SIZE_WMR_1ARG16;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,iType);
+ off = U_SIZE_METARECORD;
+ memcpy(record+off,&arg1,2);
+ }
+ return(record);
+}
+
+/* records that have two uint16_t arguments like U_WMRSETBKMODE
+ May also be used with int16_t with appropriate casts */
+char *U_WMRCORE_2U16_set(
+ int iType,
+ uint16_t arg1,
+ uint16_t arg2
+){
+ char *record=NULL;
+ uint32_t irecsize,off;
+ irecsize = U_SIZE_WMR_2ARG16;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,iType);
+ off = U_SIZE_METARECORD;
+ memcpy(record+off,&arg1,2); off+=2;
+ memcpy(record+off,&arg2,2);
+ }
+ return(record);
+}
+
+/* records that have four uint16_t arguments like U_WMRSCALEWINDOWEXT
+ May also be used with int16_t with appropriate casts */
+char *U_WMRCORE_4U16_set(
+ int iType,
+ uint16_t arg1,
+ uint16_t arg2,
+ uint16_t arg3,
+ uint16_t arg4
+){
+ char *record=NULL;
+ uint32_t irecsize, off;
+ irecsize = U_SIZE_WMR_4ARG16;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,iType);
+ off = U_SIZE_METARECORD;
+ memcpy(record+off,&arg1,2); off+=2;
+ memcpy(record+off,&arg2,2); off+=2;
+ memcpy(record+off,&arg3,2); off+=2;
+ memcpy(record+off,&arg4,2);
+ }
+ return(record);
+}
+
+/* records that have five uint16_t arguments like U_WMRCREATEPENINDIRECT
+ May also be used with int16_t with appropriate casts */
+char *U_WMRCORE_5U16_set(
+ int iType,
+ uint16_t arg1,
+ uint16_t arg2,
+ uint16_t arg3,
+ uint16_t arg4,
+ uint16_t arg5
+){
+ char *record=NULL;
+ uint32_t irecsize, off;
+ irecsize = U_SIZE_WMR_5ARG16;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,iType);
+ off = U_SIZE_METARECORD;
+ memcpy(record+off,&arg1,2); off+=2;
+ memcpy(record+off,&arg2,2); off+=2;
+ memcpy(record+off,&arg3,2); off+=2;
+ memcpy(record+off,&arg4,2); off+=2;
+ memcpy(record+off,&arg5,2);
+ }
+ return(record);
+}
+
+/* records that have size uint16_t arguments like U_ROUNDREC
+ May also be used with int16_t with appropriate casts */
+char *U_WMRCORE_6U16_set(
+ int iType,
+ uint16_t arg1,
+ uint16_t arg2,
+ uint16_t arg3,
+ uint16_t arg4,
+ uint16_t arg5,
+ uint16_t arg6
+){
+ char *record=NULL;
+ uint32_t irecsize, off;
+ irecsize = U_SIZE_WMR_6ARG16;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,iType);
+ off = U_SIZE_METARECORD;
+ memcpy(record+off,&arg1,2); off+=2;
+ memcpy(record+off,&arg2,2); off+=2;
+ memcpy(record+off,&arg3,2); off+=2;
+ memcpy(record+off,&arg4,2); off+=2;
+ memcpy(record+off,&arg5,2); off+=2;
+ memcpy(record+off,&arg6,2);
+ }
+ return(record);
+}
+
+/* records that have eight uint16_t arguments like U_WMRARC
+ May also be used with int16_t with appropriate casts */
+char *U_WMRCORE_8U16_set(
+ int iType,
+ uint16_t arg1,
+ uint16_t arg2,
+ uint16_t arg3,
+ uint16_t arg4,
+ uint16_t arg5,
+ uint16_t arg6,
+ uint16_t arg7,
+ uint16_t arg8
+){
+ char *record=NULL;
+ uint32_t irecsize, off;
+ irecsize = U_SIZE_WMR_8ARG16;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,iType);
+ off = U_SIZE_METARECORD;
+ memcpy(record+off,&arg1,2); off+=2;
+ memcpy(record+off,&arg2,2); off+=2;
+ memcpy(record+off,&arg3,2); off+=2;
+ memcpy(record+off,&arg4,2); off+=2;
+ memcpy(record+off,&arg5,2); off+=2;
+ memcpy(record+off,&arg6,2); off+=2;
+ memcpy(record+off,&arg7,2); off+=2;
+ memcpy(record+off,&arg8,2);
+ }
+ return(record);
+}
+
+/* records that have
+ arg1 an (optional) (u)int16
+ arg2 an (optional( (u)int16
+ N16 number of (u)int16_t cells in array. may be zero
+ array of N16 (u)int16_t cells (or any structure that is 2N bytes in size), should be NULL if N16 is 0.
+ like U_WMRCREATEBRUSHINDIRECT with arg1=arg2=NULL
+*/
+char *U_WMRCORE_2U16_N16_set(
+ int iType,
+ const uint16_t *arg1,
+ const uint16_t *arg2,
+ const uint16_t N16,
+ const void *array
+ ){
+ char *record=NULL;
+ uint32_t irecsize, off;
+ irecsize = U_SIZE_METARECORD + N16*2;
+ if(arg1)irecsize += 2;
+ if(arg2)irecsize += 2;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,iType);
+ off = U_SIZE_METARECORD;
+ if(arg1){ memcpy(record+off,arg1,2); off+=2; }
+ if(arg2){ memcpy(record+off,arg2,2); off+=2; }
+ if(N16){ memcpy(record+off,array,2*N16); }
+ }
+ return(record);
+}
+
+
+
+/* records that set a U_PALETTE , then a count and then a uint16_t list like U_WMRANIMATEPALETTE
+ May also be used with int16_t with appropriate casts */
+char *U_WMRCORE_PALETTE_set(
+ int iType,
+ const U_PALETTE *Palette
+){
+ char *record=NULL;
+ uint32_t irecsize, off, nPE;
+ nPE = 4*Palette->NumEntries;
+ if(!nPE)return(NULL); /* What would it mean to load an empty palette??? */
+ irecsize = U_SIZE_METARECORD + 2 + 2 + nPE;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,iType);
+ off = U_SIZE_METARECORD;
+ memcpy(record+off, &Palette->Start, 2); off+=2;
+ memcpy(record+off, &Palette->NumEntries, 2); off+=2;
+ memcpy(record+off, &Palette->PalEntries, nPE);
+ }
+ return(record);
+}
+
+//! \endcond
+
+/* **********************************************************************************************
+These functions are simpler or more convenient ways to generate the specified types of WMR records.
+Each should be called in preference to the underlying "base" WMR function.
+*********************************************************************************************** */
+
+
+/**
+ \brief Allocate and construct a U_WMRDELETEOBJECT record and also delete the requested object from the table.
+ Use this function instead of calling U_WMRDELETEOBJECT_set() directly.
+ Object Pointer in WMF (caller) is 0->N, but in htable it is 1->N+1, make that correction here.
+ \return pointer to the U_WMRDELETEOBJECT record, or NULL on error.
+ \param ihObject Pointer to handle to delete. This value is set to 0xFFFFFFFF if the function succeeds.
+ \param wht WMF handle table
+
+ Note that calling this function should always be conditional on the specifed object being defined. It is easy to
+ write a program where deleteobject_set() is called in a sequence where, at the time, we know that ihObject is defined.
+ Then a later modification, possibly quite far away in the code, causes it to be undefined. That distant change will
+ result in a failure when this function reutrns. That problem cannot be handled here because the only values which
+ may be returned are a valid U_WMRDELETEOBJECT record or a NULL, and other errors could result in the NULL.
+ So the object must be checked before the call.
+*/
+char *wdeleteobject_set(
+ uint32_t *ihObject,
+ WMFHANDLES *wht
+ ){
+ uint32_t saveObject=*ihObject; /* caller 0->N */
+ *ihObject += 1; /* caller 0->N --> 1->N+1 table*/
+ if(wmf_htable_delete(ihObject,wht))return(NULL); /* invalid handle or other problem, cannot be deleted */
+ *ihObject = 0xFFFFFFFF; /* EMF would have set to 0, but 0 is an allowed index in WMF */
+ return(U_WMRDELETEOBJECT_set(saveObject)); /* caller 0->N */
+}
+
+/**
+ \brief Allocate and construct a U_WMRSELECTOBJECT record, checks that the handle specified is one that can actually be selected.
+ Use this function instead of calling U_WMRSELECTOBJECT_set() directly.
+ Object Pointer in WMF (caller) is 0->N, so is record, so no correction to 1->N+1 needed here.
+ \return pointer to the U_WMRSELECTOBJECT record, or NULL on error.
+ \param ihObject handle to select
+ \param wht WMF handle table
+*/
+char *wselectobject_set(
+ uint32_t ihObject,
+ WMFHANDLES *wht
+ ){
+ /* WMF has no stock objects! */
+ if(ihObject > wht->hilimit)return(NULL); // handle this high is not in the table
+ /* caller uses 0->N, table uses 1->N+1 */
+ if(!wht->table[ihObject+1])return(NULL); // handle is not in the table, so cannot be selected
+ /* file uses 0->N */
+ return(U_WMRSELECTOBJECT_set(ihObject));
+}
+
+/**
+ \brief Allocate and construct a U_WMRCREATEPENINDIRECT record, create a handle and returns it
+ Use this function instead of calling U_WMRCREATEPENINDIRECT_set() directly.
+ Object Pointer in WMF (caller) is 0->N, but in htable it is 1->N+1, make that correction here.
+ \return pointer to the U_WMRCREATEPENINDIRECT record, or NULL on error.
+ \param ihPen handle to be used by new object
+ \param wht WMF handle table
+ \param pen Pen parameters (U_PEN)
+*/
+char *wcreatepenindirect_set(
+ uint32_t *ihPen,
+ WMFHANDLES *wht,
+ U_PEN pen
+ ){
+ if(wmf_htable_insert(ihPen, wht))return(NULL);
+ *ihPen -= 1; /* 1->N+1 --> 0->N */
+ return(U_WMRCREATEPENINDIRECT_set(pen));
+}
+
+/**
+ \brief Allocate and construct a U_WMRCREATEBRUSHINDIRECT record, create a handle and returns it
+ Use this function instead of calling U_WMRCREATEBRUSHINDIRECT_set() directly.
+ Object Pointer in WMF (caller) is 0->N, but in htable it is 1->N+1, make that correction here.
+ \return pointer to the U_WMRCREATEBRUSHINDIRECT record, or NULL on error.
+ \param ihBrush handle to be used by new object
+ \param wht WMF handle table
+ \param lb Brush parameters
+*/
+char *wcreatebrushindirect_set(
+ uint32_t *ihBrush,
+ WMFHANDLES *wht,
+ U_WLOGBRUSH lb
+ ){
+ if(wmf_htable_insert(ihBrush, wht))return(NULL);
+ *ihBrush -= 1; /* 1->N+1 --> 0->N */
+ return(U_WMRCREATEBRUSHINDIRECT_set(lb));
+}
+
+/**
+ \brief Allocate and construct a U_WMRDIBCREATEPATTERNBRUSH record from a DIB.
+ Use this function instead of calling U_WMRDIBCREATEPATTERNBRUSH_set() directly.
+ \return pointer to the U_WMRDIBCREATEPATTERNBRUSH record, or NULL on error.
+ \param ihBrush handle to be used by new object
+ \param wht WMF handle table
+ \param iUsage DIBColors enumeration
+ \param Bmi Bitmap info
+ \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row)
+ \param Px (Optional) bitmapbuffer (pixel array section )
+*/
+char *wcreatedibpatternbrush_srcdib_set(
+ uint32_t *ihBrush,
+ WMFHANDLES *wht,
+ const uint32_t iUsage,
+ const U_BITMAPINFO *Bmi,
+ const uint32_t cbPx,
+ const char *Px
+
+ ){
+ if(wmf_htable_insert(ihBrush, wht))return(NULL);
+ *ihBrush -= 1; /* 1->N+1 --> 0->N */
+ return(U_WMRDIBCREATEPATTERNBRUSH_set(U_BS_DIBPATTERNPT, iUsage, Bmi, cbPx, Px,NULL));
+}
+
+/**
+ \brief Allocate and construct a U_WMRDIBCREATEPATTERNBRUSH record from a U_BITMAP16 object.
+ Use this function instead of calling U_WMRDIBCREATEPATTERNBRUSH_set() directly.
+ \return pointer to the U_WMRDIBCREATEPATTERNBRUSH record, or NULL on error.
+ \param ihBrush handle to be used by new object
+ \param wht WMF handle table
+ \param iUsage DIBColors enumeration
+ \param Bm16 Pointer to a Bitmap16 object
+*/
+char *wcreatedibpatternbrush_srcbm16_set(
+ uint32_t *ihBrush,
+ WMFHANDLES *wht,
+ const uint32_t iUsage,
+ const U_BITMAP16 *Bm16
+ ){
+ if(wmf_htable_insert(ihBrush, wht))return(NULL);
+ *ihBrush -= 1; /* 1->N+1 --> 0->N */
+ return(U_WMRDIBCREATEPATTERNBRUSH_set(U_BS_PATTERN, iUsage, NULL, 0, NULL, Bm16));
+}
+
+/**
+ \brief Allocate and construct a U_WMRCREATEPATTERNBRUSH record, create a handle and returns it
+ Use this function instead of calling U_WMRCREATEPATTERNBRUSH_set() directly.
+ WARNING - U_WMRCREATEPATTERNBRUSH has been declared obsolete and application support is spotty -
+ use U_WMRDIBCREATEPATTERNBRUSH instead.
+ \return pointer to the U_WMRCREATEPATTERNBRUSH record, or NULL on error.
+ \param ihBrush handle to be used by new object
+ \param wht WMF handle table
+ \param Bm16 Pointer to a Bitmap16 structure (only first 10 bytes are used).
+ \param Pattern Pointer to a byte array described by Bm16. (Pattern may be a pointer to the BM16 Bits field.)
+*/
+char *wcreatepatternbrush_set(
+ uint32_t *ihBrush,
+ WMFHANDLES *wht,
+ U_BITMAP16 *Bm16,
+ char *Pattern
+ ){
+ if(wmf_htable_insert(ihBrush, wht))return(NULL);
+ *ihBrush -= 1; /* 1->N+1 --> 0->N */
+ return(U_WMRCREATEPATTERNBRUSH_set(Bm16, Pattern));
+}
+
+/**
+ \brief Allocate and construct a U_WMRCREATEFONTINDIRECT record, create a handle and returns it
+ Use this function instead of calling U_WMRCREATEFONTINDIRECT_set() directly.
+ Object Pointer in WMF (caller) is 0->N, but in htable it is 1->N+1, make that correction here.
+ \return pointer to the U_WMRCREATEFONTINDIRECT record, or NULL on error.
+ \param ihFont Font handle, will be created and returned
+ \param wht Pointer to structure holding all WMF handles
+ \param uf Pointer to Font parameters as U_FONT *
+*/
+char *wcreatefontindirect_set(
+ uint32_t *ihFont,
+ WMFHANDLES *wht,
+ U_FONT *uf
+ ){
+ if(wmf_htable_insert(ihFont, wht))return(NULL);
+ *ihFont -= 1; /* 1->N+1 --> 0->N */
+ return(U_WMRCREATEFONTINDIRECT_set(uf));
+}
+
+/**
+ \brief Allocate and construct a U_WMRCREATEPALETTE record, create a handle and returns it
+ Use this function instead of calling U_WMRCREATEPALETTE_set() directly.
+ Object Pointer in WMF (caller) is 0->N, but in htable it is 1->N+1, make that correction here.
+ \return pointer to the U_WMRCREATEPALETTE record, or NULL on error.
+ \param ihPal Palette handle, will be created and returned
+ \param wht Pointer to structure holding all WMF handles
+ \param up Palette parameters
+*/
+char *wcreatepalette_set(
+ uint32_t *ihPal,
+ WMFHANDLES *wht,
+ U_PALETTE *up
+ ){
+ if(wmf_htable_insert(ihPal, wht))return(NULL);
+ *ihPal -= 1; /* 1->N+1 --> 0->N */
+ return(U_WMRCREATEPALETTE_set(up));
+}
+
+/**
+ \brief Allocate and construct a U_WMRSETPALENTRIES record, create a handle and returns it
+ Use this function instead of calling U_WMRSETPALENTRIES_set() directly.
+ Object Pointer in WMF (caller) is 0->N, but in htable it is 1->N+1, make that correction here.
+ \return pointer to the U_WMRSETPALENTRIES record, or NULL on error.
+ \param ihPal Palette handle, will be created and returned
+ \param wht Pointer to structure holding all WMF handles
+ \param Palettes Values to set with
+*/
+char *wsetpaletteentries_set(
+ uint32_t *ihPal,
+ WMFHANDLES *wht,
+ const U_PALETTE *Palettes
+ ){
+ if(wmf_htable_insert(ihPal, wht))return(NULL);
+ *ihPal -= 1; /* 1->N+1 --> 0->N */
+ return(U_WMRSETPALENTRIES_set(Palettes));
+}
+
+/**
+ \brief Allocate and construct a U_WMRCREATEREGION record, create a handle and returns it
+ Use this function instead of calling U_WMRCREATEREGION() directly.
+ Object Pointer in WMF (caller) is 0->N, but in htable it is 1->N+1, make that correction here.
+ \return pointer to the U_REGIONS record, or NULL on error.
+ \param ihReg Region handle, will be created and returned
+ \param wht Pointer to structure holding all WMF handles
+ \param Region Values to set with
+*/
+char *wcreateregion_set(
+ uint32_t *ihReg,
+ WMFHANDLES *wht,
+ const U_REGION *Region
+ ){
+ if(wmf_htable_insert(ihReg, wht))return(NULL);
+ *ihReg -= 1; /* 1->N+1 --> 0->N */
+ return(U_WMRCREATEREGION_set(Region));
+}
+/* A few escape functions are implemented, just those that set a state or a single value */
+
+/**
+ \brief Allocate and construct the specified U_WMRESCAPE structure, create a handle and returns it
+ Use this function instead of calling U_WMRESCAPE_set() directly.
+ \return pointer to the U_WMRESCAPE structure, or NULL on error.
+*/
+char *wbegin_path_set(void){
+ return(U_WMRESCAPE_set(U_MFE_BEGIN_PATH,0,NULL));
+}
+
+/**
+ \brief Allocate and construct the specified U_WMRESCAPE structure, create a handle and returns it
+ Use this function instead of calling U_WMRESCAPE_set() directly.
+ \return pointer to the U_WMRESCAPE structure, or NULL on error.
+*/
+char *wend_path_set(void){
+ return(U_WMRESCAPE_set(U_MFE_END_PATH,0,NULL));
+}
+
+/**
+ \brief Allocate and construct the specified U_WMRESCAPE structure, create a handle and returns it
+ Use this function instead of calling U_WMRESCAPE_set() directly.
+ \return pointer to the U_WMRESCAPE structure, or NULL on error.
+ \param Type PostScriptCap Enumeration, anything else is an error
+*/
+char *wlinecap_set(
+ int32_t Type
+ ){
+ char *record =NULL;
+ if(Type == U_WPS_CAP_NOTSET ||
+ Type == U_WPS_CAP_FLAT ||
+ Type == U_WPS_CAP_ROUND ||
+ Type == U_WPS_CAP_SQUARE){ record = U_WMRESCAPE_set(U_MFE_SETLINECAP,4,&Type); }
+ return(record);
+}
+
+/**
+ \brief Allocate and construct the specified U_WMRESCAPE structure, create a handle and returns it
+ Use this function instead of calling U_WMRESCAPE_set() directly.
+ \return pointer to the U_WMRESCAPE structure, or NULL on error.
+ \param Type PostScriptCap Enumeration, anything else is an error
+*/
+char *wlinejoin_set(
+ int32_t Type
+ ){
+ char *record =NULL;
+ if(Type == U_WPS_JOIN_NOTSET ||
+ Type == U_WPS_JOIN_MITER ||
+ Type == U_WPS_JOIN_ROUND ||
+ Type == U_WPS_JOIN_BEVEL){ record = U_WMRESCAPE_set(U_MFE_SETLINEJOIN,4,&Type); }
+ return(record);
+}
+
+/**
+ \brief Allocate and construct the specified U_WMRESCAPE structure, create a handle and returns it
+ Use this function instead of calling U_WMRESCAPE_set() directly.
+ \return pointer to the U_WMRESCAPE structure, or NULL on error.
+ \param limit PostScriptCap Enumeration, anything else is an error
+*/
+char *wmiterlimit_set(
+ int32_t limit
+ ){
+ return(U_WMRESCAPE_set(U_MFE_SETMITERLIMIT,4,&limit));
+}
+
+/* **********************************************************************************************
+These are the core WMR functions, each creates a particular type of record.
+All return these records via a char* pointer, which is NULL if the call failed.
+They are listed in order by the corresponding U_WMR_* index number.
+*********************************************************************************************** */
+
+/**
+ \brief Set up fields for a (placeable) WMR_HEADER. Most of the fields are blank and are not set until all is written.
+ Typically values are something like (8.5,11.0), 1440 (Letter paper, 1440 DPI).
+ The scaled paper size must fit in the range 0<->32767 inclusive, because it must be represented by a signed 16bit number.
+ If the size + dpi result in out of range values a failure will result.
+ \return pointer to the WMF header record, or NULL on failure
+ \param size Pointer to page size (if NULL, not a placeable header) in inches. Values must be positive and scaled
+ \param dpi Logical units/inch. If 0 defaults to 1440.
+*/
+char *U_WMRHEADER_set(
+ U_PAIRF *size,
+ unsigned int dpi
+ ){
+ char *record=NULL;
+ uint32_t irecsize,off;
+ double xmax,ymax;
+ int16_t xm16,ym16;
+ irecsize = (size ? U_SIZE_WMRHEADER + U_SIZE_WMRPLACEABLE : U_SIZE_WMRHEADER);
+ record = calloc(1,irecsize); /* most will be zero*/
+ off = 0;
+ if(record){
+ if(size){ /* placeable */
+ if(!dpi)dpi=1440;
+ xmax = U_ROUND((double) size->x * (double) dpi);
+ ymax = U_ROUND((double) size->y * (double) dpi);
+ if(xmax < 0 || ymax < 0 || xmax > 32767 || ymax > 32767){
+ free(record);
+ return(NULL);
+ }
+ xm16 = xmax;
+ ym16 = ymax;
+ ((U_WMRPLACEABLE *) record)->Key = 0x9AC6CDD7;
+ ((U_WMRPLACEABLE *) record)->HWmf = 0; /* Manual says number of 16 bit words in record, but all WMF examples had it as 0 */
+ ((U_WMRPLACEABLE *) record)->Dst.left = 0;
+ ((U_WMRPLACEABLE *) record)->Dst.top = 0;
+ ((U_WMRPLACEABLE *) record)->Dst.right = xm16;
+ ((U_WMRPLACEABLE *) record)->Dst.bottom = ym16;
+ ((U_WMRPLACEABLE *) record)->Inch = dpi;
+ ((U_WMRPLACEABLE *) record)->Reserved = 0;
+ ((U_WMRPLACEABLE *) record)->Checksum = U_16_checksum((int16_t *)record,10);
+ off = U_SIZE_WMRPLACEABLE;
+ }
+ ((U_WMRHEADER *) (record + off))->iType = 1;
+ ((U_WMRHEADER *) (record + off))->version = U_METAVERSION300;
+ ((U_WMRHEADER *) (record + off))->Size16w = U_SIZE_WMRHEADER/2;
+ }
+ return(record);
+}
+
+
+/**
+ \brief Allocate and construct a U_WMREOF record
+ \return pointer to the U_WMREOF record, or NULL on error.
+*/
+char *U_WMREOF_set(void){
+ return U_WMRCORE_NOARGS_set(U_WMR_EOF);
+}
+
+/**
+ \brief Create and return a U_WMRSETBKCOLOR record
+ \return pointer to the U_WMRSETBKCOLOR record, or NULL on error
+ \param Color Background Color.
+*/
+char *U_WMRSETBKCOLOR_set(U_COLORREF Color){
+ return U_WMRCORE_1U16_CRF_2U16_set(U_WMR_SETBKCOLOR,NULL,Color,NULL,NULL);
+}
+
+/**
+ \brief Create and return a U_WMRSETBKMODE record
+ \return pointer to the U_WMRSETBKMODE record, or NULL on error
+ \param Mode MixMode Enumeration
+*/
+char *U_WMRSETBKMODE_set(uint16_t Mode){
+ return U_WMRCORE_2U16_set(U_WMR_SETBKMODE, Mode, 0);
+}
+
+/**
+ \brief Create and return a U_WMRSETMAPMODE record
+ \return pointer to the U_WMRSETMAPMODE record, or NULL on error
+ \param Mode MapMode Enumeration
+*/
+char *U_WMRSETMAPMODE_set(uint16_t Mode){
+ return U_WMRCORE_1U16_set(U_WMR_SETMAPMODE, Mode);
+}
+
+/**
+ \brief Create and return a U_WMRSETROP2 record
+ \return pointer to the U_WMRSETROP2 record, or NULL on error
+ \param Mode Binary Raster Operation Enumeration
+*/
+char *U_WMRSETROP2_set(uint16_t Mode){
+ return U_WMRCORE_2U16_set(U_WMR_SETROP2, Mode, 0);
+}
+
+/**
+ \brief Allocate and construct a U_WMRSETRELABS record
+ \return pointer to the U_WMRSETRELABS record, or NULL on error.
+*/
+char *U_WMRSETRELABS_set(void){
+ return U_WMRCORE_NOARGS_set(U_WMR_SETRELABS);
+}
+
+/**
+ \brief Create and return a U_WMRSETPOLYFILLMODE record
+ \return pointer to the U_WMRSETPOLYFILLMODE record, or NULL on error
+ \param Mode PolyFillMode Enumeration
+*/
+char *U_WMRSETPOLYFILLMODE_set(uint16_t Mode){
+ return U_WMRCORE_2U16_set(U_WMR_SETPOLYFILLMODE, Mode, 0);
+}
+
+/**
+ \brief Create and return a U_WMRSETSTRETCHBLTMODE record
+ \return pointer to the U_WMRSETSTRETCHBLTMODE record, or NULL on error
+ \param Mode StretchMode Enumeration
+*/
+char *U_WMRSETSTRETCHBLTMODE_set(uint16_t Mode){
+ return U_WMRCORE_2U16_set(U_WMR_SETSTRETCHBLTMODE, Mode, 0);
+}
+
+/**
+ \brief Create and return a U_WMRSETTEXTCHAREXTRA record
+ \return pointer to the U_WMRSETTEXTCHAREXTRA record, or NULL on error
+ \param Mode Extra space in logical units to add to each character
+*/
+char *U_WMRSETTEXTCHAREXTRA_set(uint16_t Mode){
+ return U_WMRCORE_1U16_set(U_WMR_SETTEXTCHAREXTRA, Mode);
+}
+
+/**
+ \brief Create and return a U_WMRSETTEXTCOLOR record
+ \return pointer to the U_WMRSETTEXTCOLOR record, or NULL on error
+ \param Color Text Color.
+*/
+char *U_WMRSETTEXTCOLOR_set(U_COLORREF Color){
+ return U_WMRCORE_1U16_CRF_2U16_set(U_WMR_SETTEXTCOLOR,NULL,Color,NULL,NULL);
+}
+
+/**
+ \brief Create and return a U_WMRSETTEXTJUSTIFICATION record
+ \return pointer to the U_WMRSETTEXTJUSTIFICATION record, or NULL on error
+ \param Count Number of space characters in the line.
+ \param Extra Number of extra space characters to add to the line.
+*/
+char *U_WMRSETTEXTJUSTIFICATION_set(uint16_t Count, uint16_t Extra){
+ return U_WMRCORE_2U16_set(U_WMR_SETBKMODE, Count, Extra);
+}
+
+/**
+ \brief Create and return a U_WMRSETWINDOWORG record
+ \return pointer to the U_WMRSETWINDOWORG record, or NULL on error
+ \param coord Window Origin.
+*/
+char *U_WMRSETWINDOWORG_set(U_POINT16 coord){
+ return U_WMRCORE_2U16_set(U_WMR_SETWINDOWORG, U_U16(coord.y), U_U16(coord.x));
+}
+
+/**
+ \brief Create and return a U_WMRSETWINDOWEXT record
+ \return pointer to the U_WMRSETWINDOWEXT record, or NULL on error
+ \param extent Window Extent.
+*/
+char *U_WMRSETWINDOWEXT_set(U_POINT16 extent){
+ return U_WMRCORE_2U16_set(U_WMR_SETWINDOWEXT, U_U16(extent.y), U_U16(extent.x));
+}
+
+/**
+ \brief Create and return a U_WMRSETVIEWPORTORG record
+ \return pointer to the U_WMRSETVIEWPORTORG record, or NULL on error
+ \param coord Viewport Origin.
+*/
+char *U_WMRSETVIEWPORTORG_set(U_POINT16 coord){
+ return U_WMRCORE_2U16_set(U_WMR_SETVIEWPORTORG, U_U16(coord.y), U_U16(coord.x));
+}
+
+/**
+ \brief Create and return a U_WMRSETVIEWPORTEXT record
+ \return pointer to the U_WMRSETVIEWPORTEXT record, or NULL on error
+ \param extent Viewport Extent.
+*/
+char *U_WMRSETVIEWPORTEXT_set(U_POINT16 extent){
+ return U_WMRCORE_2U16_set(U_WMR_SETWINDOWEXT, U_U16(extent.y), U_U16(extent.x));
+}
+
+/**
+ \brief Create and return a U_WMROFFSETWINDOWORG record
+ \return pointer to the U_WMROFFSETWINDOWORG record, or NULL on error
+ \param offset Window offset in device units.
+*/
+char *U_WMROFFSETWINDOWORG_set(U_POINT16 offset){
+ return U_WMRCORE_2U16_set(U_WMR_OFFSETWINDOWORG, U_U16(offset.y), U_U16(offset.x));
+}
+
+/**
+ \brief Create and return a U_WMRSCALEWINDOWEXT record
+ \return pointer to the U_WMRSCALEWINDOWEXT record, or NULL on error
+ \param Denom {X,Y} denominators.
+ \param Num {X,Y} numerators.
+*/
+char *U_WMRSCALEWINDOWEXT_set(U_POINT16 Denom, U_POINT16 Num){
+ return U_WMRCORE_4U16_set(U_WMR_SCALEWINDOWEXT, U_U16(Denom.y), U_U16(Num.y), U_U16(Denom.x), U_U16(Num.x));
+}
+
+/**
+ \brief Create and return a U_WMROFFSETVIEWPORTORG record
+ \return pointer to the U_WMROFFSETVIEWPORTORG record, or NULL on error
+ \param offset Viewport offset in device units.
+*/
+char *U_WMROFFSETVIEWPORTORG_set(U_POINT16 offset){
+ return U_WMRCORE_2U16_set(U_WMR_OFFSETVIEWPORTORG, U_U16(offset.y), U_U16(offset.x));
+}
+
+/**
+ \brief Create and return a U_WMRSCALEVIEWPORTEXT record
+ \return pointer to the U_WMRSCALEVIEWPORTEXT record, or NULL on error
+ \param Denom {X,Y} denominators.
+ \param Num {X,Y} numerators.
+*/
+char *U_WMRSCALEVIEWPORTEXT_set(U_POINT16 Denom, U_POINT16 Num){
+ return U_WMRCORE_4U16_set(U_WMR_SCALEVIEWPORTEXT, U_U16(Denom.y), U_U16(Num.y), U_U16(Denom.x), U_U16(Num.x));
+}
+
+/**
+ \brief Create and return a U_WMRLINETO record
+ \return pointer to the U_WMRLINETO record, or NULL on error
+ \param coord Draw line to {X,Y}.
+*/
+char *U_WMRLINETO_set(U_POINT16 coord){
+ return U_WMRCORE_2U16_set(U_WMR_LINETO, U_U16(coord.y), U_U16(coord.x));
+}
+
+/**
+ \brief Create and return a U_WMRMOVETO record
+ \return pointer to the U_WMRMOVETO record, or NULL on error
+ \param coord Move to {X,Y}.
+*/
+char *U_WMRMOVETO_set(U_POINT16 coord){
+ return U_WMRCORE_2U16_set(U_WMR_MOVETO, U_U16(coord.y), U_U16(coord.x));
+}
+
+/**
+ \brief Create and return a U_WMREXCLUDECLIPRECT record
+ \return pointer to the U_WMREXCLUDECLIPRECT record, or NULL on error
+ \param rect Exclude rect from clipping region.
+*/
+char *U_WMREXCLUDECLIPRECT_set(U_RECT16 rect){
+ return U_WMRCORE_4U16_set(
+ U_WMR_EXCLUDECLIPRECT,
+ U_U16(rect.bottom),
+ U_U16(rect.right),
+ U_U16(rect.top),
+ U_U16(rect.left)
+ );
+}
+
+/**
+ \brief Create and return a U_WMRINTERSECTCLIPRECT record
+ \return pointer to the U_WMRINTERSECTCLIPRECT record, or NULL on error
+ \param rect Clipping region is intersection of existing clipping region with rect.
+*/
+char *U_WMRINTERSECTCLIPRECT_set(U_RECT16 rect){
+ return U_WMRCORE_4U16_set(
+ U_WMR_INTERSECTCLIPRECT,
+ U_U16(rect.bottom),
+ U_U16(rect.right),
+ U_U16(rect.top),
+ U_U16(rect.left)
+ );
+}
+
+/**
+ \brief Create and return a U_WMRARC record
+ \return pointer to the U_WMRARC record, or NULL on error
+ \param StartArc Start of Arc
+ \param EndArc End of Arc
+ \param rect Bounding rectangle.
+*/
+char *U_WMRARC_set(U_POINT16 StartArc, U_POINT16 EndArc, U_RECT16 rect){
+ return U_WMRCORE_8U16_set(
+ U_WMR_ARC,
+ U_U16(EndArc.y),
+ U_U16(EndArc.x),
+ U_U16(StartArc.y),
+ U_U16(StartArc.x),
+ U_U16(rect.bottom),
+ U_U16(rect.right),
+ U_U16(rect.top),
+ U_U16(rect.left)
+ );
+}
+
+/**
+ \brief Create and return a U_WMRELLIPSE record
+ \return pointer to the U_WMRELLIPSE record, or NULL on error
+ \param rect Bounding rectangle for Ellipse.
+*/
+char *U_WMRELLIPSE_set(U_RECT16 rect){
+ return U_WMRCORE_4U16_set(
+ U_WMR_ELLIPSE,
+ U_U16(rect.bottom),
+ U_U16(rect.right),
+ U_U16(rect.top),
+ U_U16(rect.left)
+ );
+}
+
+/**
+ \brief Create and return a U_WMRFLOODFILL record
+ \return pointer to the U_WMRFLOODFILL record, or NULL on error
+ \param Mode FloodFill Enumeration.
+ \param Color Color to Fill with.
+ \param coord Location to start fill.
+*/
+char *U_WMRFLOODFILL_set(uint16_t Mode, U_COLORREF Color, U_POINT16 coord){
+ return U_WMRCORE_1U16_CRF_2U16_set(
+ U_WMR_FLOODFILL,
+ &Mode,
+ Color,
+ U_P16(coord.y),
+ U_P16(coord.x)
+ );
+}
+
+/**
+ \brief Create and return a U_WMRPIE record
+ \return pointer to the U_WMRPIE record, or NULL on error
+ \param Radial1 Start of Pie
+ \param Radial2 End of Pie
+ \param rect Bounding rectangle.
+*/
+char *U_WMRPIE_set(U_POINT16 Radial1, U_POINT16 Radial2, U_RECT16 rect){
+ return U_WMRCORE_8U16_set(
+ U_WMR_PIE,
+ U_U16(Radial2.y),
+ U_U16(Radial2.x),
+ U_U16(Radial1.y),
+ U_U16(Radial1.x),
+ U_U16(rect.bottom),
+ U_U16(rect.right),
+ U_U16(rect.top),
+ U_U16(rect.left)
+ );
+}
+
+/**
+ \brief Create and return a U_WMRRECTANGLE record
+ \return pointer to the U_WMRRECTANGLE record, or NULL on error
+ \param rect Boundaries.
+*/
+char *U_WMRRECTANGLE_set(U_RECT16 rect){
+ return U_WMRCORE_4U16_set(
+ U_WMR_RECTANGLE,
+ U_U16(rect.bottom),
+ U_U16(rect.right),
+ U_U16(rect.top),
+ U_U16(rect.left)
+ );
+}
+
+/**
+ \brief Create and return a U_WMRROUNDRECT record
+ \return pointer to the U_WMRROUNDRECT record, or NULL on error
+ \param Width Horizontal rounding length.
+ \param Height Vertical rounding length.
+ \param rect Boundaries.
+*/
+char *U_WMRROUNDRECT_set(int16_t Width, int16_t Height, U_RECT16 rect){
+ return U_WMRCORE_6U16_set(
+ U_WMR_ROUNDRECT,
+ U_U16(Height),
+ U_U16(Width),
+ U_U16(rect.bottom),
+ U_U16(rect.right),
+ U_U16(rect.top),
+ U_U16(rect.left)
+ );
+}
+
+/**
+ \brief Allocate and construct a U_WMRPATBLT record.
+ \return pointer to the U_WMRPATBLT record, or NULL on error.
+ \param Dst Destination UL corner in logical units
+ \param cwh W & H for Dst and Src in logical units
+ \param dwRop3 RasterOPeration Enumeration
+*/
+char *U_WMRPATBLT_set(
+ U_POINT16 Dst,
+ U_POINT16 cwh,
+ uint32_t dwRop3
+ ){
+ char *record=NULL;
+ uint32_t irecsize;
+ U_WMRPATBLT *pmr;
+
+ irecsize = U_SIZE_WMRPATBLT;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_PATBLT);
+ pmr = (U_WMRPATBLT *) record;
+ memcpy(pmr->rop3w, &dwRop3, 4);
+ pmr->Height = cwh.y;
+ pmr->Width = cwh.x;
+ pmr->yDst = Dst.y;
+ pmr->xDst = Dst.x;
+ }
+ return(record);
+}
+
+/**
+ \brief Allocate and construct a U_WMRSAVEDC record
+ \return pointer to the U_WMRSAVEDC record, or NULL on error.
+*/
+char *U_WMRSAVEDC_set(void){
+ return U_WMRCORE_NOARGS_set(U_WMR_SAVEDC);
+}
+
+/**
+ \brief Allocate and construct a U_WMRSETPIXEL record
+ \return pointer to the U_WMRSETPIXEL record, or NULL on error.
+ \param Color U_COLORREF color of the pixel
+ \param Coord U_POINT16 coordinates of the pixel
+*/
+char *U_WMRSETPIXEL_set(U_COLORREF Color, U_POINT16 Coord){
+ return U_WMRCORE_1U16_CRF_2U16_set(
+ U_WMR_SETPIXEL,
+ NULL,
+ Color,
+ U_P16(Coord.y),
+ U_P16(Coord.x)
+ );
+}
+
+/**
+ \brief Allocate and construct a U_WMROFFSETCLIPRGN record
+ \return pointer to the U_WMROFFSETCLIPRGN record, or NULL on error.
+ \param offset U_POINT16 x,y offset to apply to the clipping region.
+*/
+char *U_WMROFFSETCLIPRGN_set(U_POINT16 offset){
+ return U_WMRCORE_2U16_set(U_WMR_OFFSETCLIPRGN, U_U16(offset.y), U_U16(offset.x));
+}
+
+/**
+ \brief Allocate and construct a U_WMRTEXTOUT record.
+ \return pointer to the U_WMRTEXTOUT record, or NULL on error.
+ \param Dst Destinationin logical units
+ \param string Null terminated string to write. The terminator is NOT placed in the record!
+*/
+char *U_WMRTEXTOUT_set(U_POINT16 Dst, char *string){
+ char *record=NULL;
+ uint32_t irecsize,off;
+ int L2;
+ int16_t Length;
+ irecsize = 2 + U_SIZE_METARECORD + 4; /* core + length + Dst */
+ Length = strlen(string);
+ L2 = ( Length & 1 ? Length + 1 : Length);
+ irecsize += L2;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_TEXTOUT);
+ off = U_SIZE_METARECORD;
+ memcpy(record+off,&Length,2); off+=2;
+ memcpy(record+off,string,Length); off+=Length;
+ if(Length!=L2){
+ memset(record+off,0,1); off+=1;
+ }
+ memcpy(record+off,&Dst.y,2); off+=2;
+ memcpy(record+off,&Dst.x,2);
+ }
+ return(record);
+}
+
+/**
+ \brief Allocate and construct a U_WMRBITBLT record.
+ Note that unlike U_EMRBITBLT there is no scaling available - the Src and Dst
+ rectangles must be the same size.
+ \return pointer to the U_WMRBITBLT record, or NULL on error.
+ \param Dst Destination UL corner in logical units
+ \param cwh W & H for Dst and Src in logical units
+ \param Src Source UL corner in logical units
+ \param dwRop3 RasterOPeration Enumeration
+ \param Bm16 (Optional) bitmap16 object
+*/
+char *U_WMRBITBLT_set(
+ U_POINT16 Dst,
+ U_POINT16 cwh,
+ U_POINT16 Src,
+ uint32_t dwRop3,
+ const U_BITMAP16 *Bm16
+ ){
+ char *record=NULL;
+ uint32_t irecsize;
+ int cbBm16,cbBm164,off;
+ U_WMRBITBLT_PX *pmr_px;
+ U_WMRBITBLT_NOPX *pmr_nopx;
+
+ if(Bm16){
+ cbBm16 = U_SIZE_BITMAP16 + (((Bm16->Width * Bm16->BitsPixel + 15) >> 4) << 1) * Bm16->Height;
+ cbBm164 = UP4(cbBm16);
+ irecsize = U_SIZE_WMRBITBLT_PX + cbBm164;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_BITBLT);
+ pmr_px = (U_WMRBITBLT_PX *) record;
+ memcpy(pmr_px->rop3w, &dwRop3, 4);
+ pmr_px->ySrc = Src.y;
+ pmr_px->xSrc = Src.x;
+ pmr_px->Height = cwh.y;
+ pmr_px->Width = cwh.x;
+ pmr_px->yDst = Dst.y;
+ pmr_px->xDst = Dst.x;
+ off = U_SIZE_WMRBITBLT_PX;
+ memcpy(record + off, Bm16, cbBm16); off += cbBm16;
+ if(cbBm164 - cbBm16)memset(record+off,0,cbBm164 - cbBm16);
+ }
+ }
+ else {
+ irecsize = U_SIZE_WMRBITBLT_NOPX;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_BITBLT);
+ pmr_nopx = (U_WMRBITBLT_NOPX *) record;
+ memcpy(pmr_nopx->rop3w, &dwRop3, 4);
+ pmr_nopx->ySrc = Src.y;
+ pmr_nopx->xSrc = Src.x;
+ pmr_nopx->Height = cwh.y;
+ pmr_nopx->Width = cwh.x;
+ pmr_nopx->ignore = 0;
+ pmr_nopx->yDst = Dst.y;
+ pmr_nopx->xDst = Dst.x;
+ }
+ }
+ return(record);
+}
+
+/**
+ \brief Allocate and construct a U_WMRSTRETCHBLT record.
+ \return pointer to the U_WMRSTRETCHBLT record, or NULL on error.
+ \param Dst Destination UL corner in logical units
+ \param cDst Destination W & H in logical units
+ \param Src Source UL corner in logical units
+ \param cSrc Source W & H in logical units
+ \param dwRop3 RasterOPeration Enumeration
+ \param Bm16 (Optional) bitmap16 object
+*/
+char *U_WMRSTRETCHBLT_set(
+ U_POINT16 Dst,
+ U_POINT16 cDst,
+ U_POINT16 Src,
+ U_POINT16 cSrc,
+ uint32_t dwRop3,
+ const U_BITMAP16 *Bm16
+ ){
+ char *record=NULL;
+ uint32_t irecsize;
+ int cbBm16,cbBm164,off;
+ U_WMRSTRETCHBLT_PX *pmr_px;
+ U_WMRSTRETCHBLT_NOPX *pmr_nopx;
+
+ if(Bm16){
+ cbBm16 = U_SIZE_BITMAP16 + (((Bm16->Width * Bm16->BitsPixel + 15) >> 4) << 1) * Bm16->Height;
+ cbBm164 = UP4(cbBm16);
+ irecsize = U_SIZE_WMRSTRETCHBLT_PX + cbBm164;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_STRETCHBLT);
+ pmr_px = (U_WMRSTRETCHBLT_PX *) record;
+ memcpy(pmr_px->rop3w, &dwRop3, 4);
+ pmr_px->hSrc = cSrc.y;
+ pmr_px->wSrc = cSrc.x;
+ pmr_px->ySrc = Src.y;
+ pmr_px->xSrc = Src.x;
+ pmr_px->hDst = cDst.y;
+ pmr_px->wDst = cDst.x;
+ pmr_px->yDst = Dst.y;
+ pmr_px->xDst = Dst.x;
+ off = U_SIZE_WMRSTRETCHBLT_PX;
+ memcpy(record + off, Bm16, cbBm16); off += cbBm16;
+ if(cbBm164 - cbBm16)memset(record+off,0,cbBm164 - cbBm16);
+ }
+ }
+ else {
+ irecsize = U_SIZE_WMRSTRETCHBLT_NOPX;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_STRETCHBLT);
+ pmr_nopx = (U_WMRSTRETCHBLT_NOPX *) record;
+ memcpy(pmr_nopx->rop3w, &dwRop3, 4);
+ pmr_nopx->hSrc = cSrc.y;
+ pmr_nopx->wSrc = cSrc.x;
+ pmr_nopx->ySrc = Src.y;
+ pmr_nopx->xSrc = Src.x;
+ pmr_nopx->ignore = 0;
+ pmr_nopx->hDst = cDst.y;
+ pmr_nopx->wDst = cDst.x;
+ pmr_nopx->yDst = Dst.y;
+ pmr_nopx->xDst = Dst.x;
+ }
+ }
+ return(record);
+}
+
+/**
+ \brief Allocate and construct a U_WMRPOLYGON record.
+ \return pointer to the U_WMRPOLYGON record, or NULL on error.
+ \param Length Number of points in the Polygon
+ \param Data Array of Length points
+*/
+char *U_WMRPOLYGON_set(uint16_t Length, const U_POINT16 *Data){
+ return U_WMRCORE_2U16_N16_set(U_WMR_POLYGON, NULL, &Length, 2*Length, Data);
+}
+
+/**
+ \brief Allocate and construct a U_WMRPOLYLINE record.
+ \return pointer to the U_WMRPOLYLINE record, or NULL on error.
+ \param Length Number of points in the Polyline
+ \param Data Array of Length points
+*/
+char *U_WMRPOLYLINE_set(uint16_t Length, const U_POINT16 *Data){
+ return U_WMRCORE_2U16_N16_set(U_WMR_POLYLINE, NULL, &Length, 2*Length, Data);
+}
+
+/**
+ \brief Allocate and construct a U_WMRESCAPE record.
+ WARNING! Only three Escape record types are fully supported: SETLINECAP, SETLINEJOIN, SETMITERLIMIT.
+ Even these should not be set here directly, instead use the wsetlinecap_set(), wsetlinejoin_set(),
+ or wsetmiterlimit_set() functions.
+ Escape records created with this function, with the exception of the three named above, will not have
+ the byte orders in Data adjusted automatically. The user code must set Data to be little endian no
+ matter what the endianness of the current platform where the user code is running.
+ \return pointer to the U_WMRESCAPE record, or NULL on error.
+ \param Escape Escape function
+ \param Length Bytes in the Data
+ \param Data Array of Length bytes
+*/
+char *U_WMRESCAPE_set(uint16_t Escape, uint16_t Length, const void *Data){
+ return U_WMRCORE_2U16_N16_set(U_WMR_ESCAPE, &Escape, &Length, Length/2, Data);
+}
+
+/**
+ \brief Allocate and construct a U_WMRRESTOREDC record
+ \return pointer to the U_WMRRESTOREDC record, or NULL on error.
+ \param DC Drawing Context to restore. (negative is relative to current, positive is absolute)
+*/
+char *U_WMRRESTOREDC_set(int16_t DC){
+ return U_WMRCORE_1U16_set(U_WMR_RESTOREDC, DC);
+}
+
+/**
+ \brief Allocate and construct a U_WMRFILLREGION record.
+ \return pointer to the U_WMRFILLREGION record, or NULL on error.
+ \param Region Region to fill
+ \param Brush Brush to fill with
+*/
+char *U_WMRFILLREGION_set(uint16_t Region, uint16_t Brush){
+ return U_WMRCORE_2U16_set(U_WMR_FILLREGION, Region, Brush);
+}
+
+/**
+ \brief Allocate and construct a U_WMRFRAMEREGION record.
+ \return pointer to the U_WMRFRAMEREGION record, or NULL on error.
+ \param Region Index of region to frame in object table
+ \param Brush Index of brush to use in frame in object table
+ \param Height in logical units (of frame)
+ \param Width in logical units (of frame)
+*/
+char *U_WMRFRAMEREGION_set(uint16_t Region, uint16_t Brush, int16_t Height, int16_t Width){
+ return U_WMRCORE_4U16_set(U_WMR_FRAMEREGION, Region, Brush, U_U16(Height), U_U16(Width));
+}
+
+/**
+ \brief Allocate and construct a U_WMRINVERTREGION record.
+ \return pointer to the U_WMRINVERTREGION record, or NULL on error.
+ \param Region Index of region to invert.
+*/
+char *U_WMRINVERTREGION_set(uint16_t Region){
+ return U_WMRCORE_1U16_set(U_WMR_INVERTREGION, Region);
+}
+
+/**
+ \brief Allocate and construct a U_WMRPAINTREGION record.
+ \return pointer to the U_WMRPAINTREGION record, or NULL on error.
+ \param Region Index of region to paint with the current Brush.
+*/
+char *U_WMRPAINTREGION_set(uint16_t Region){
+ return U_WMRCORE_1U16_set(U_WMR_PAINTREGION, Region);
+}
+
+/**
+ \brief Allocate and construct a U_WMRSELECTCLIPREGION record.
+ \return pointer to the U_WMRSELECTCLIPREGION record, or NULL on error.
+ \param Region Index of region to become clipping region..
+*/
+char *U_WMRSELECTCLIPREGION_set(uint16_t Region){
+ return U_WMRCORE_1U16_set(U_WMR_SELECTCLIPREGION, Region);
+}
+
+/**
+ \brief Allocate and construct a U_WMRSELECTOBJECT record.
+ \return pointer to the U_WMRSELECTOBJECT record, or NULL on error.
+ \param object Index of object which is made active.
+*/
+char *U_WMRSELECTOBJECT_set(uint16_t object){
+ return U_WMRCORE_1U16_set(U_WMR_SELECTOBJECT, object);
+}
+
+/**
+ \brief Allocate and construct a U_WMRSETTEXTALIGN record.
+ \return pointer to the U_WMRSETTEXTALIGN record, or NULL on error.
+ \param Mode TextAlignment Enumeration.
+*/
+char *U_WMRSETTEXTALIGN_set(uint16_t Mode){
+ return U_WMRCORE_2U16_set(U_WMR_SETTEXTALIGN, Mode, 0);
+}
+
+/** in GDI and Wine, not in WMF manual..
+*/
+ char *U_WMRDRAWTEXT_set(void){
+ return U_WMRCORENONE_set("U_WMRDRAWTEXT");
+}
+
+/**
+ \brief Create and return a U_WMRCHORD record
+ \return pointer to the U_WMRCHORD record, or NULL on error
+ \param Radial1 Start of Chord
+ \param Radial2 End of Chord
+ \param rect Bounding rectangle.
+*/
+char *U_WMRCHORD_set(U_POINT16 Radial1, U_POINT16 Radial2, U_RECT16 rect){
+ return U_WMRCORE_8U16_set(
+ U_WMR_CHORD,
+ U_U16(Radial2.y),
+ U_U16(Radial2.x),
+ U_U16(Radial1.y),
+ U_U16(Radial1.x),
+ U_U16(rect.bottom),
+ U_U16(rect.right),
+ U_U16(rect.top),
+ U_U16(rect.left)
+ );
+}
+
+/**
+ \brief Allocate and construct a U_WMRSETMAPPERFLAGS record.
+ \return pointer to the U_WMRSETMAPPERFLAGS record, or NULL on error.
+ \param Mode If 1 bit set font mapper selects only matching aspect fonts.
+*/
+char *U_WMRSETMAPPERFLAGS_set(uint32_t Mode){
+ return U_WMRCORE_2U16_set(U_WMR_SETMAPPERFLAGS, 0xFFFF & Mode, Mode>>16);
+}
+
+/**
+ \brief Allocate and construct a U_WMREXTTEXTOUT record.
+ \return pointer to the U_WMREXTTEXTOUT record, or NULL on error.
+ \param Dst {X,Y} coordinates where the string is to be written.
+ \param Length Stringlength in bytes
+ \param Opts ExtTextOutOptions Flags
+ \param string String to write (Latin1 encoding)
+ \param dx Kerning information. Must have same number of entries as Length.
+ \param rect Used when when U_ETO_OPAQUE or U_ETO_CLIPPED bits are set in Opts
+*/
+char *U_WMREXTTEXTOUT_set(U_POINT16 Dst, int16_t Length, uint16_t Opts,
+ const char *string, int16_t *dx, U_RECT16 rect){
+
+ char *record=NULL;
+ uint32_t irecsize,off;
+ int slen;
+ irecsize = U_SIZE_METARECORD + 8; /* 8 = y,x,Length,Opts*/
+ slen = ( Length & 1 ? Length + 1 : Length);
+ irecsize += slen;
+ if(dx)irecsize += 2*Length;
+ if(Opts & (U_ETO_OPAQUE | U_ETO_CLIPPED)){
+ irecsize += U_SIZE_RECT16;
+ }
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_EXTTEXTOUT);
+ off = U_SIZE_METARECORD;
+ memcpy(record+off,&Dst.y,2); off+=2;
+ memcpy(record+off,&Dst.x,2); off+=2;
+ memcpy(record+off,&Length,2); off+=2;
+ memcpy(record+off,&Opts,2); off+=2;
+ if(Opts & (U_ETO_OPAQUE | U_ETO_CLIPPED)){
+ memcpy(record+off,&rect.bottom,2); off+=2;
+ memcpy(record+off,&rect.right, 2); off+=2;
+ memcpy(record+off,&rect.top, 2); off+=2;
+ memcpy(record+off,&rect.left, 2); off+=2;
+ }
+ memcpy(record+off,string,strlen(string)); off+=Length;
+ if(Length!=slen){
+ memset(record+off,0,1); off+=1;
+ }
+ if(dx){
+ memcpy(record+off,dx,2*Length);
+ }
+ }
+ return(record);
+}
+
+/**
+ \brief Allocate and construct a U_WMRSETDIBTODEV record
+ \return pointer to the U_WMRSETDIBTODEV record, or NULL on error.
+*/
+char *U_WMRSETDIBTODEV_set(void){
+ return U_WMRCORENONE_set("U_WMRSETDIBTODEV");
+}
+
+/**
+ \brief Allocate and construct a U_WMRSELECTPALETTE record
+ \return pointer to the U_WMRSELECTPALETTE record, or NULL on error.
+ \param Palette Index of Palette to make active.
+*/
+char *U_WMRSELECTPALETTE_set(uint16_t Palette){
+ return U_WMRCORE_1U16_set(U_WMR_SELECTPALETTE, Palette);
+}
+
+/**
+ \brief Allocate and construct a U_WMRREALIZEPALETTE record
+ \return pointer to the U_WMRREALIZEPALETTE record, or NULL on error.
+*/
+char *U_WMRREALIZEPALETTE_set(void){
+ return U_WMRCORE_NOARGS_set(U_WMR_REALIZEPALETTE);
+}
+
+/**
+ \brief Allocate and construct a U_WMRSETPALENTRIES record
+ \return pointer to the U_WMRSETPALENTRIES record, or NULL on error.
+ \param Palette Redefines a set of RGB values for the current active Palette.
+*/
+char *U_WMRANIMATEPALETTE_set(U_PALETTE *Palette){
+ return U_WMRCORE_PALETTE_set(U_WMR_ANIMATEPALETTE, Palette);
+}
+
+/**
+ \brief Allocate and construct a U_WMRSETPALENTRIES record
+ \return pointer to the U_WMRSETPALENTRIES record, or NULL on error.
+ \param Palette Defines a set of RGB values for the current active Palette.
+*/
+char *U_WMRSETPALENTRIES_set(const U_PALETTE *Palette){
+ return U_WMRCORE_PALETTE_set(U_WMR_SETPALENTRIES, Palette);
+}
+
+/**
+ \brief Allocate and construct a U_WMR_POLYPOLYGON record.
+ \return pointer to the U_WMR_POLYPOLYGON record, or NULL on error.
+ \param nPolys Number of elements in aPolyCounts
+ \param aPolyCounts Number of points in each poly (sequential)
+ \param Points array of points
+*/
+char *U_WMRPOLYPOLYGON_set(
+ const uint16_t nPolys,
+ const uint16_t *aPolyCounts,
+ const U_POINT16 *Points
+ ){
+ char *record;
+ uint32_t irecsize;
+ int i,cbPolys,cbPoints,off;
+
+ cbPolys = sizeof(uint16_t)*nPolys;
+ for(i=cbPoints=0; i<nPolys; i++){ cbPoints += U_SIZE_POINT16*aPolyCounts[i]; }
+
+ if(nPolys==0 || cbPoints==0)return(NULL);
+
+ irecsize = U_SIZE_METARECORD + 2 + cbPolys + cbPoints; /* core WMR + nPolys + two array sizes in bytes */
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_POLYPOLYGON);
+ off = U_SIZE_METARECORD;
+ memcpy(record + off, &nPolys, 2); off+=2;
+ memcpy(record + off, aPolyCounts, cbPolys); off+=cbPolys;
+ memcpy(record + off, Points, cbPoints);
+ }
+ return(record);
+}
+
+/**
+ \brief Allocate and construct a U_WMRRESIZEPALETTE record
+ \return pointer to the U_WMRRESIZEPALETTE record, or NULL on error.
+ \param Palette Changes the size of the currently active Palette.
+*/
+char *U_WMRRESIZEPALETTE_set(uint16_t Palette){
+ return U_WMRCORE_1U16_set(U_WMR_RESIZEPALETTE, Palette);
+}
+
+//! \cond
+char *U_WMR3A_set(void){
+ return U_WMRCORENONE_set("U_WMR3A");
+}
+
+char *U_WMR3B_set(void){
+ return U_WMRCORENONE_set("U_WMR3B");
+}
+
+char *U_WMR3C_set(void){
+ return U_WMRCORENONE_set("U_WMR3C");
+}
+
+char *U_WMR3D_set(void){
+ return U_WMRCORENONE_set("U_WMR3D");
+}
+
+char *U_WMR3E_set(void){
+ return U_WMRCORENONE_set("U_WMR3E");
+}
+
+char *U_WMR3F_set(void){
+ return U_WMRCORENONE_set("U_WMR3F");
+}
+//! \endcond
+
+// U_WMRDIBBITBLT_set
+/**
+ \brief Allocate and construct a U_WMRDIBITBLT record.
+ \return pointer to the U_WMRDIBITBLT record, or NULL on error.
+ \param Dst Destination UL corner in logical units
+ \param Src Source UL corner in logical units
+ \param cwh W & H in logical units of Src and Dst
+ \param dwRop3 RasterOPeration Enumeration
+ \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section)
+ \param cbPx Size in bytes of pixel array (row STRIDE * height, there may be some padding at the end of each row)
+ \param Px (Optional) bitmapbuffer (pixel array section )
+*/
+char *U_WMRDIBBITBLT_set(
+ U_POINT16 Dst,
+ U_POINT16 cwh,
+ U_POINT16 Src,
+ uint32_t dwRop3,
+ const U_BITMAPINFO *Bmi,
+ uint32_t cbPx,
+ const char *Px
+ ){
+ char *record=NULL;
+ uint32_t irecsize;
+ int cbImage,cbImage4,cbBmi,off;
+ U_WMRDIBBITBLT_PX *pmr_px;
+ U_WMRDIBBITBLT_NOPX *pmr_nopx;
+
+
+ if(Px && Bmi){
+ SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
+ irecsize = U_SIZE_WMRDIBBITBLT_PX + cbBmi + cbImage4;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_DIBBITBLT);
+ pmr_px = (U_WMRDIBBITBLT_PX *) record;
+ memcpy(pmr_px->rop3w, &dwRop3, 4);
+ pmr_px->ySrc = Src.y;
+ pmr_px->xSrc = Src.x;
+ pmr_px->Height = cwh.y;
+ pmr_px->Width = cwh.x;
+ pmr_px->yDst = Dst.y;
+ pmr_px->xDst = Dst.x;
+ off = U_SIZE_WMRDIBBITBLT_PX;
+ memcpy(record + off, Bmi, cbBmi); off += cbBmi;
+ memcpy(record + off, Px, cbPx); off += cbPx;
+ if(cbImage4 - cbImage)memset(record+off,0,cbImage4 - cbImage);
+ }
+ }
+ else if(!Px && !Bmi){
+ irecsize = U_SIZE_WMRDIBBITBLT_NOPX;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_DIBBITBLT);
+ pmr_nopx = (U_WMRDIBBITBLT_NOPX *) record;
+ memcpy(pmr_nopx->rop3w, &dwRop3, 4);
+ pmr_nopx->ySrc = Src.y;
+ pmr_nopx->xSrc = Src.x;
+ pmr_nopx->ignore = 0;
+ pmr_nopx->Height = cwh.y;
+ pmr_nopx->Width = cwh.x;
+ pmr_nopx->yDst = Dst.y;
+ pmr_nopx->xDst = Dst.x;
+ }
+ }
+ return(record);
+}
+
+/**
+ \brief Allocate and construct a U_WMRSTRETCHDIB record.
+ \return pointer to the U_WMRSTRETCHDIB record, or NULL on error.
+ \param Dst Destination UL corner in logical units
+ \param cDst Destination W & H in logical units
+ \param Src Source UL corner in logical units
+ \param cSrc Source W & H in logical units
+ \param dwRop3 RasterOPeration Enumeration
+ \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section)
+ \param cbPx Size in bytes of pixel array (row STRIDE * height, there may be some padding at the end of each row)
+ \param Px (Optional) bitmapbuffer (pixel array section )
+*/
+char *U_WMRDIBSTRETCHBLT_set(
+ U_POINT16 Dst,
+ U_POINT16 cDst,
+ U_POINT16 Src,
+ U_POINT16 cSrc,
+ uint32_t dwRop3,
+ const U_BITMAPINFO *Bmi,
+ uint32_t cbPx,
+ const char *Px
+ ){
+ char *record=NULL;
+ uint32_t irecsize;
+ int cbImage,cbImage4,cbBmi,off;
+ U_WMRDIBSTRETCHBLT_PX *pmr_px;
+ U_WMRDIBSTRETCHBLT_NOPX *pmr_nopx;
+ if(Px && Bmi){
+ SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
+ irecsize = U_SIZE_WMRDIBSTRETCHBLT_PX + cbBmi + cbImage4;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_DIBSTRETCHBLT);
+ pmr_px = (U_WMRDIBSTRETCHBLT_PX *) record;
+ memcpy(pmr_px->rop3w, &dwRop3, 4);
+ pmr_px->hSrc = cSrc.y;
+ pmr_px->wSrc = cSrc.x;
+ pmr_px->ySrc = Src.y;
+ pmr_px->xSrc = Src.x;
+ pmr_px->hDst = cDst.y;
+ pmr_px->wDst = cDst.x;
+ pmr_px->yDst = Dst.y;
+ pmr_px->xDst = Dst.x;
+ off = U_SIZE_WMRDIBSTRETCHBLT_PX;
+ memcpy(record + off, Bmi, cbBmi); off += cbBmi;
+ memcpy(record + off, Px, cbPx); off += cbPx;
+ if(cbImage4 - cbImage)memset(record+off,0,cbImage4 - cbImage);
+ }
+ }
+ else if(!Px && !Bmi){
+ irecsize = U_SIZE_WMRDIBSTRETCHBLT_NOPX;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_DIBSTRETCHBLT);
+ pmr_nopx = (U_WMRDIBSTRETCHBLT_NOPX *) record;
+ memcpy(pmr_nopx->rop3w, &dwRop3, 4);
+ pmr_nopx->hSrc = cSrc.y;
+ pmr_nopx->wSrc = cSrc.x;
+ pmr_nopx->ySrc = Src.y;
+ pmr_nopx->xSrc = Src.x;
+ pmr_nopx->ignore = 0;
+ pmr_nopx->hDst = cDst.y;
+ pmr_nopx->wDst = cDst.x;
+ pmr_nopx->yDst = Dst.y;
+ pmr_nopx->xDst = Dst.x;
+ }
+ }
+ return(record);
+}
+
+/**
+ \brief Allocate and construct a U_WMRDIBCREATEPATTERNBRUSH record.
+ Accepts an image as either a DIB (Bmi/CbPx/Px defined) or a Bitmap16 (Bm16 defined).
+ \return pointer to the U_WMRDIBCREATEPATTERNBRUSH record, or NULL on error.
+ \param Style BrushStyle Enumeration
+ \param iUsage DIBcolors Enumeration
+ \param Bm16 pointer to U_BITMAP16 object for Style U_BS_PATTERN only
+ \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row), for use with Bmi
+ \param Px bitmap buffer, for use with Bmi
+ \param Bmi pointer to U_BITMAPINFO for all Style OTHER than U_BS_PATTERN
+*/
+char *U_WMRDIBCREATEPATTERNBRUSH_set(
+ const uint16_t Style,
+ const uint16_t iUsage,
+ const U_BITMAPINFO *Bmi,
+ const uint32_t cbPx,
+ const char *Px,
+ const U_BITMAP16 *Bm16
+ ){
+ char *record=NULL;
+ uint32_t irecsize;
+ int cbImage,cbImage4,cbBmi,cbBm16,cbBm164,off;
+
+ if(Style==U_BS_PATTERN && Bm16){
+ cbBm16 = U_SIZE_BITMAP16 + (((Bm16->Width * Bm16->BitsPixel + 15) >> 4) << 1) * Bm16->Height;
+ cbBm164 = UP4(cbBm16);
+ irecsize = U_SIZE_WMRDIBCREATEPATTERNBRUSH + cbBm164;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_DIBCREATEPATTERNBRUSH);
+ off = U_SIZE_METARECORD;
+ memcpy(record + off, &Style, 2); off+=2;
+ memcpy(record + off, &iUsage, 2); off+=2;
+ memcpy(record + off, Bm16, cbBm16); off += cbBm16;
+ if(cbBm164 - cbBm16)memset(record+off,0,cbBm164 - cbBm16);
+ }
+ }
+ else if(Bmi && Px){
+ SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
+ irecsize = U_SIZE_WMRDIBCREATEPATTERNBRUSH + cbBmi + cbImage4;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_DIBCREATEPATTERNBRUSH);
+ off = U_SIZE_METARECORD;
+ memcpy(record + off, &Style, 2); off+=2;
+ memcpy(record + off, &iUsage, 2); off+=2;
+ memcpy(record + off, Bmi, cbBmi); off += cbBmi;
+ memcpy(record + off, Px, cbImage); off += cbImage;
+ if(cbImage4 - cbImage)memset(record + off, 0, cbImage4 - cbImage);
+ }
+ }
+ return(record);
+}
+
+/**
+ \brief Allocate and construct a U_WMRSTRETCHDIB record.
+ \return pointer to the U_WMRSTRETCHDIB record, or NULL on error.
+ \param Dst Destination UL corner in logical units
+ \param cDst Destination W & H in logical units
+ \param Src Source UL corner in logical units
+ \param cSrc Source W & H in logical units
+ \param cUsage DIBColors Enumeration
+ \param dwRop3 RasterOPeration Enumeration
+ \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section)
+ \param cbPx Size in bytes of pixel array (row STRIDE * height, there may be some padding at the end of each row)
+ \param Px (Optional) bitmapbuffer (pixel array section )
+*/
+char *U_WMRSTRETCHDIB_set(
+ U_POINT16 Dst,
+ U_POINT16 cDst,
+ U_POINT16 Src,
+ U_POINT16 cSrc,
+ uint16_t cUsage,
+ uint32_t dwRop3,
+ const U_BITMAPINFO *Bmi,
+ uint32_t cbPx,
+ const char *Px
+ ){
+ char *record;
+ uint32_t irecsize;
+ int cbImage,cbImage4,cbBmi,off;
+ U_WMRSTRETCHDIB *pmr;
+
+ SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx);
+
+ irecsize = U_SIZE_WMRSTRETCHDIB + cbBmi + cbImage4;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_STRETCHDIB);
+ pmr = (U_WMRSTRETCHDIB *) record;
+ memcpy(pmr->rop3w, &dwRop3, 4);
+ pmr->cUsage = cUsage;
+ pmr->hSrc = cSrc.y;
+ pmr->wSrc = cSrc.x;
+ pmr->ySrc = Src.y;
+ pmr->xSrc = Src.x;
+ pmr->hDst = cDst.y;
+ pmr->wDst = cDst.x;
+ pmr->yDst = Dst.y;
+ pmr->xDst = Dst.x;
+ off = U_SIZE_WMRSTRETCHDIB;
+ if(cbBmi){
+ memcpy(record + off, Bmi, cbBmi); off += cbBmi;
+ memcpy(record + off, Px, cbPx); off += cbPx;
+ if(cbImage4 - cbImage)memset(record+off,0,cbImage4 - cbImage);
+ }
+ }
+ return(record);
+}
+
+//! \cond
+char *U_WMR44_set(void){
+ return U_WMRCORENONE_set("U_WMR44");
+}
+
+char *U_WMR45_set(void){
+ return U_WMRCORENONE_set("U_WMR45");
+}
+
+char *U_WMR46_set(void){
+ return U_WMRCORENONE_set("U_WMR46");
+}
+
+char *U_WMR47_set(void){
+ return U_WMRCORENONE_set("U_WMR47");
+}
+//! \endcond
+
+/**
+ \brief Create and return a U_WMREXTFLOODFILL record
+ \return pointer to the U_WMREXTFLOODFILL record, or NULL on error
+ \param Mode FloodFill Enumeration.
+ \param Color Color to Fill with.
+ \param coord Location to start fill.
+*/
+char *U_WMREXTFLOODFILL_set(uint16_t Mode, U_COLORREF Color, U_POINT16 coord){
+ return U_WMRCORE_1U16_CRF_2U16_set(
+ U_WMR_EXTFLOODFILL,
+ &Mode,
+ Color,
+ U_P16(coord.y),
+ U_P16(coord.x)
+ );
+}
+
+//! \cond
+char *U_WMR49_set(void){
+ return U_WMRCORENONE_set("U_WMR49");
+}
+
+char *U_WMR4A_set(void){
+ return U_WMRCORENONE_set("U_WMR4A");
+}
+
+char *U_WMR4B_set(void){
+ return U_WMRCORENONE_set("U_WMR4B");
+}
+
+char *U_WMR4C_set(void){
+ return U_WMRCORENONE_set("U_WMRRESETDOC");
+}
+
+char *U_WMR4D_set(void){
+ return U_WMRCORENONE_set("U_WMRSTARTDOC");
+}
+
+char *U_WMR4E_set(void){
+ return U_WMRCORENONE_set("U_WMR4E");
+}
+
+char *U_WMR4F_set(void){
+ return U_WMRCORENONE_set("U_WMRSTARTPAGE");
+}
+
+char *U_WMR50_set(void){
+ return U_WMRCORENONE_set("U_WMRENDPAGE");
+}
+
+char *U_WMR51_set(void){
+ return U_WMRCORENONE_set("U_WMR51");
+}
+
+char *U_WMRABORTDOC_set(void){
+ return U_WMRCORENONE_set("U_WMRABORTDOC");
+}
+
+char *U_WMR53_set(void){
+ return U_WMRCORENONE_set("U_WMR53");
+}
+
+char *U_WMR54_set(void){
+ return U_WMRCORENONE_set("U_WMR54");
+}
+
+char *U_WMR55_set(void){
+ return U_WMRCORENONE_set("U_WMR55");
+}
+
+char *U_WMR56_set(void){
+ return U_WMRCORENONE_set("U_WMR56");
+}
+
+char *U_WMR57_set(void){
+ return U_WMRCORENONE_set("U_WMR57");
+}
+
+char *U_WMR58_set(void){
+ return U_WMRCORENONE_set("U_WMR58");
+}
+
+char *U_WMR59_set(void){
+ return U_WMRCORENONE_set("U_WMR59");
+}
+
+char *U_WMR5A_set(void){
+ return U_WMRCORENONE_set("U_WMR5A");
+}
+
+char *U_WMR5B_set(void){
+ return U_WMRCORENONE_set("U_WMR5B");
+}
+
+char *U_WMR5C_set(void){
+ return U_WMRCORENONE_set("U_WMR5C");
+}
+
+char *U_WMR5D_set(void){
+ return U_WMRCORENONE_set("U_WMR5D");
+}
+
+char *U_WMR5E_set(void){
+ return U_WMRCORENONE_set("U_WMRENDDOC");
+}
+
+char *U_WMR5F_set(void){
+ return U_WMRCORENONE_set("U_WMR5F");
+}
+
+char *U_WMR60_set(void){
+ return U_WMRCORENONE_set("U_WMR60");
+}
+
+char *U_WMR61_set(void){
+ return U_WMRCORENONE_set("U_WMR61");
+}
+
+char *U_WMR62_set(void){
+ return U_WMRCORENONE_set("U_WMR62");
+}
+
+char *U_WMR63_set(void){
+ return U_WMRCORENONE_set("U_WMR63");
+}
+
+char *U_WMR64_set(void){
+ return U_WMRCORENONE_set("U_WMR64");
+}
+
+char *U_WMR65_set(void){
+ return U_WMRCORENONE_set("U_WMR65");
+}
+
+char *U_WMR66_set(void){
+ return U_WMRCORENONE_set("U_WMR66");
+}
+
+char *U_WMR67_set(void){
+ return U_WMRCORENONE_set("U_WMR67");
+}
+
+char *U_WMR68_set(void){
+ return U_WMRCORENONE_set("U_WMR68");
+}
+
+char *U_WMR69_set(void){
+ return U_WMRCORENONE_set("U_WMR69");
+}
+
+char *U_WMR6A_set(void){
+ return U_WMRCORENONE_set("U_WMR6A");
+}
+
+char *U_WMR6B_set(void){
+ return U_WMRCORENONE_set("U_WMR6B");
+}
+
+char *U_WMR6C_set(void){
+ return U_WMRCORENONE_set("U_WMR6C");
+}
+
+char *U_WMR6D_set(void){
+ return U_WMRCORENONE_set("U_WMR6D");
+}
+
+char *U_WMR6E_set(void){
+ return U_WMRCORENONE_set("U_WMR6E");
+}
+
+char *U_WMR6F_set(void){
+ return U_WMRCORENONE_set("U_WMR6F");
+}
+
+char *U_WMR70_set(void){
+ return U_WMRCORENONE_set("U_WMR70");
+}
+
+char *U_WMR71_set(void){
+ return U_WMRCORENONE_set("U_WMR71");
+}
+
+char *U_WMR72_set(void){
+ return U_WMRCORENONE_set("U_WMR72");
+}
+
+char *U_WMR73_set(void){
+ return U_WMRCORENONE_set("U_WMR73");
+}
+
+char *U_WMR74_set(void){
+ return U_WMRCORENONE_set("U_WMR74");
+}
+
+char *U_WMR75_set(void){
+ return U_WMRCORENONE_set("U_WMR75");
+}
+
+char *U_WMR76_set(void){
+ return U_WMRCORENONE_set("U_WMR76");
+}
+
+char *U_WMR77_set(void){
+ return U_WMRCORENONE_set("U_WMR77");
+}
+
+char *U_WMR78_set(void){
+ return U_WMRCORENONE_set("U_WMR78");
+}
+
+char *U_WMR79_set(void){
+ return U_WMRCORENONE_set("U_WMR79");
+}
+
+char *U_WMR7A_set(void){
+ return U_WMRCORENONE_set("U_WMR7A");
+}
+
+char *U_WMR7B_set(void){
+ return U_WMRCORENONE_set("U_WMR7B");
+}
+
+char *U_WMR7C_set(void){
+ return U_WMRCORENONE_set("U_WMR7C");
+}
+
+char *U_WMR7D_set(void){
+ return U_WMRCORENONE_set("U_WMR7D");
+}
+
+char *U_WMR7E_set(void){
+ return U_WMRCORENONE_set("U_WMR7E");
+}
+
+char *U_WMR7F_set(void){
+ return U_WMRCORENONE_set("U_WMR7F");
+}
+
+char *U_WMR80_set(void){
+ return U_WMRCORENONE_set("U_WMR80");
+}
+
+char *U_WMR81_set(void){
+ return U_WMRCORENONE_set("U_WMR81");
+}
+
+char *U_WMR82_set(void){
+ return U_WMRCORENONE_set("U_WMR82");
+}
+
+char *U_WMR83_set(void){
+ return U_WMRCORENONE_set("U_WMR83");
+}
+
+char *U_WMR84_set(void){
+ return U_WMRCORENONE_set("U_WMR84");
+}
+
+char *U_WMR85_set(void){
+ return U_WMRCORENONE_set("U_WMR85");
+}
+
+char *U_WMR86_set(void){
+ return U_WMRCORENONE_set("U_WMR86");
+}
+
+char *U_WMR87_set(void){
+ return U_WMRCORENONE_set("U_WMR87");
+}
+
+char *U_WMR88_set(void){
+ return U_WMRCORENONE_set("U_WMR88");
+}
+
+char *U_WMR89_set(void){
+ return U_WMRCORENONE_set("U_WMR89");
+}
+
+char *U_WMR8A_set(void){
+ return U_WMRCORENONE_set("U_WMR8A");
+}
+
+char *U_WMR8B_set(void){
+ return U_WMRCORENONE_set("U_WMR8B");
+}
+
+char *U_WMR8C_set(void){
+ return U_WMRCORENONE_set("U_WMR8C");
+}
+
+char *U_WMR8D_set(void){
+ return U_WMRCORENONE_set("U_WMR8D");
+}
+
+char *U_WMR8E_set(void){
+ return U_WMRCORENONE_set("U_WMR8E");
+}
+
+char *U_WMR8F_set(void){
+ return U_WMRCORENONE_set("U_WMR8F");
+}
+
+char *U_WMR90_set(void){
+ return U_WMRCORENONE_set("U_WMR90");
+}
+
+char *U_WMR91_set(void){
+ return U_WMRCORENONE_set("U_WMR91");
+}
+
+char *U_WMR92_set(void){
+ return U_WMRCORENONE_set("U_WMR92");
+}
+
+char *U_WMR93_set(void){
+ return U_WMRCORENONE_set("U_WMR93");
+}
+
+char *U_WMR94_set(void){
+ return U_WMRCORENONE_set("U_WMR94");
+}
+
+char *U_WMR95_set(void){
+ return U_WMRCORENONE_set("U_WMR95");
+}
+
+char *U_WMR96_set(void){
+ return U_WMRCORENONE_set("U_WMR96");
+}
+
+char *U_WMR97_set(void){
+ return U_WMRCORENONE_set("U_WMR97");
+}
+
+char *U_WMR98_set(void){
+ return U_WMRCORENONE_set("U_WMR98");
+}
+
+char *U_WMR99_set(void){
+ return U_WMRCORENONE_set("U_WMR99");
+}
+
+char *U_WMR9A_set(void){
+ return U_WMRCORENONE_set("U_WMR9A");
+}
+
+char *U_WMR9B_set(void){
+ return U_WMRCORENONE_set("U_WMR9B");
+}
+
+char *U_WMR9C_set(void){
+ return U_WMRCORENONE_set("U_WMR9C");
+}
+
+char *U_WMR9D_set(void){
+ return U_WMRCORENONE_set("U_WMR9D");
+}
+
+char *U_WMR9E_set(void){
+ return U_WMRCORENONE_set("U_WMR9E");
+}
+
+char *U_WMR9F_set(void){
+ return U_WMRCORENONE_set("U_WMR9F");
+}
+
+char *U_WMRA0_set(void){
+ return U_WMRCORENONE_set("U_WMRA0");
+}
+
+char *U_WMRA1_set(void){
+ return U_WMRCORENONE_set("U_WMRA1");
+}
+
+char *U_WMRA2_set(void){
+ return U_WMRCORENONE_set("U_WMRA2");
+}
+
+char *U_WMRA3_set(void){
+ return U_WMRCORENONE_set("U_WMRA3");
+}
+
+char *U_WMRA4_set(void){
+ return U_WMRCORENONE_set("U_WMRA4");
+}
+
+char *U_WMRA5_set(void){
+ return U_WMRCORENONE_set("U_WMRA5");
+}
+
+char *U_WMRA6_set(void){
+ return U_WMRCORENONE_set("U_WMRA6");
+}
+
+char *U_WMRA7_set(void){
+ return U_WMRCORENONE_set("U_WMRA7");
+}
+
+char *U_WMRA8_set(void){
+ return U_WMRCORENONE_set("U_WMRA8");
+}
+
+char *U_WMRA9_set(void){
+ return U_WMRCORENONE_set("U_WMRA9");
+}
+
+char *U_WMRAA_set(void){
+ return U_WMRCORENONE_set("U_WMRAA");
+}
+
+char *U_WMRAB_set(void){
+ return U_WMRCORENONE_set("U_WMRAB");
+}
+
+char *U_WMRAC_set(void){
+ return U_WMRCORENONE_set("U_WMRAC");
+}
+
+char *U_WMRAD_set(void){
+ return U_WMRCORENONE_set("U_WMRAD");
+}
+
+char *U_WMRAE_set(void){
+ return U_WMRCORENONE_set("U_WMRAE");
+}
+
+char *U_WMRAF_set(void){
+ return U_WMRCORENONE_set("U_WMRAF");
+}
+
+char *U_WMRB0_set(void){
+ return U_WMRCORENONE_set("U_WMRB0");
+}
+
+char *U_WMRB1_set(void){
+ return U_WMRCORENONE_set("U_WMRB1");
+}
+
+char *U_WMRB2_set(void){
+ return U_WMRCORENONE_set("U_WMRB2");
+}
+
+char *U_WMRB3_set(void){
+ return U_WMRCORENONE_set("U_WMRB3");
+}
+
+char *U_WMRB4_set(void){
+ return U_WMRCORENONE_set("U_WMRB4");
+}
+
+char *U_WMRB5_set(void){
+ return U_WMRCORENONE_set("U_WMRB5");
+}
+
+char *U_WMRB6_set(void){
+ return U_WMRCORENONE_set("U_WMRB6");
+}
+
+char *U_WMRB7_set(void){
+ return U_WMRCORENONE_set("U_WMRB7");
+}
+
+char *U_WMRB8_set(void){
+ return U_WMRCORENONE_set("U_WMRB8");
+}
+
+char *U_WMRB9_set(void){
+ return U_WMRCORENONE_set("U_WMRB9");
+}
+
+char *U_WMRBA_set(void){
+ return U_WMRCORENONE_set("U_WMRBA");
+}
+
+char *U_WMRBB_set(void){
+ return U_WMRCORENONE_set("U_WMRBB");
+}
+
+char *U_WMRBC_set(void){
+ return U_WMRCORENONE_set("U_WMRBC");
+}
+
+char *U_WMRBD_set(void){
+ return U_WMRCORENONE_set("U_WMRBD");
+}
+
+char *U_WMRBE_set(void){
+ return U_WMRCORENONE_set("U_WMRBE");
+}
+
+char *U_WMRBF_set(void){
+ return U_WMRCORENONE_set("U_WMRBF");
+}
+
+char *U_WMRC0_set(void){
+ return U_WMRCORENONE_set("U_WMRC0");
+}
+
+char *U_WMRC1_set(void){
+ return U_WMRCORENONE_set("U_WMRC1");
+}
+
+char *U_WMRC2_set(void){
+ return U_WMRCORENONE_set("U_WMRC2");
+}
+
+char *U_WMRC3_set(void){
+ return U_WMRCORENONE_set("U_WMRC3");
+}
+
+char *U_WMRC4_set(void){
+ return U_WMRCORENONE_set("U_WMRC4");
+}
+
+char *U_WMRC5_set(void){
+ return U_WMRCORENONE_set("U_WMRC5");
+}
+
+char *U_WMRC6_set(void){
+ return U_WMRCORENONE_set("U_WMRC6");
+}
+
+char *U_WMRC7_set(void){
+ return U_WMRCORENONE_set("U_WMRC7");
+}
+
+char *U_WMRC8_set(void){
+ return U_WMRCORENONE_set("U_WMRC8");
+}
+
+char *U_WMRC9_set(void){
+ return U_WMRCORENONE_set("U_WMRC9");
+}
+
+char *U_WMRCA_set(void){
+ return U_WMRCORENONE_set("U_WMRCA");
+}
+
+char *U_WMRCB_set(void){
+ return U_WMRCORENONE_set("U_WMRCB");
+}
+
+char *U_WMRCC_set(void){
+ return U_WMRCORENONE_set("U_WMRCC");
+}
+
+char *U_WMRCD_set(void){
+ return U_WMRCORENONE_set("U_WMRCD");
+}
+
+char *U_WMRCE_set(void){
+ return U_WMRCORENONE_set("U_WMRCE");
+}
+
+char *U_WMRCF_set(void){
+ return U_WMRCORENONE_set("U_WMRCF");
+}
+
+char *U_WMRD0_set(void){
+ return U_WMRCORENONE_set("U_WMRD0");
+}
+
+char *U_WMRD1_set(void){
+ return U_WMRCORENONE_set("U_WMRD1");
+}
+
+char *U_WMRD2_set(void){
+ return U_WMRCORENONE_set("U_WMRD2");
+}
+
+char *U_WMRD3_set(void){
+ return U_WMRCORENONE_set("U_WMRD3");
+}
+
+char *U_WMRD4_set(void){
+ return U_WMRCORENONE_set("U_WMRD4");
+}
+
+char *U_WMRD5_set(void){
+ return U_WMRCORENONE_set("U_WMRD5");
+}
+
+char *U_WMRD6_set(void){
+ return U_WMRCORENONE_set("U_WMRD6");
+}
+
+char *U_WMRD7_set(void){
+ return U_WMRCORENONE_set("U_WMRD7");
+}
+
+char *U_WMRD8_set(void){
+ return U_WMRCORENONE_set("U_WMRD8");
+}
+
+char *U_WMRD9_set(void){
+ return U_WMRCORENONE_set("U_WMRD9");
+}
+
+char *U_WMRDA_set(void){
+ return U_WMRCORENONE_set("U_WMRDA");
+}
+
+char *U_WMRDB_set(void){
+ return U_WMRCORENONE_set("U_WMRDB");
+}
+
+char *U_WMRDC_set(void){
+ return U_WMRCORENONE_set("U_WMRDC");
+}
+
+char *U_WMRDD_set(void){
+ return U_WMRCORENONE_set("U_WMRDD");
+}
+
+char *U_WMRDE_set(void){
+ return U_WMRCORENONE_set("U_WMRDE");
+}
+
+char *U_WMRDF_set(void){
+ return U_WMRCORENONE_set("U_WMRDF");
+}
+
+char *U_WMRE0_set(void){
+ return U_WMRCORENONE_set("U_WMRE0");
+}
+
+char *U_WMRE1_set(void){
+ return U_WMRCORENONE_set("U_WMRE1");
+}
+
+char *U_WMRE2_set(void){
+ return U_WMRCORENONE_set("U_WMRE2");
+}
+
+char *U_WMRE3_set(void){
+ return U_WMRCORENONE_set("U_WMRE3");
+}
+
+char *U_WMRE4_set(void){
+ return U_WMRCORENONE_set("U_WMRE4");
+}
+
+char *U_WMRE5_set(void){
+ return U_WMRCORENONE_set("U_WMRE5");
+}
+
+char *U_WMRE6_set(void){
+ return U_WMRCORENONE_set("U_WMRE6");
+}
+
+char *U_WMRE7_set(void){
+ return U_WMRCORENONE_set("U_WMRE7");
+}
+
+char *U_WMRE8_set(void){
+ return U_WMRCORENONE_set("U_WMRE8");
+}
+
+char *U_WMRE9_set(void){
+ return U_WMRCORENONE_set("U_WMRE9");
+}
+
+char *U_WMREA_set(void){
+ return U_WMRCORENONE_set("U_WMREA");
+}
+
+char *U_WMREB_set(void){
+ return U_WMRCORENONE_set("U_WMREB");
+}
+
+char *U_WMREC_set(void){
+ return U_WMRCORENONE_set("U_WMREC");
+}
+
+char *U_WMRED_set(void){
+ return U_WMRCORENONE_set("U_WMRED");
+}
+
+char *U_WMREE_set(void){
+ return U_WMRCORENONE_set("U_WMREE");
+}
+
+char *U_WMREF_set(void){
+ return U_WMRCORENONE_set("U_WMREF");
+}
+//! \endcond
+
+/**
+ \brief Create and return a U_WMRDELETEOBJECT record
+ \return pointer to the U_WMRDELETEOBJECT record, or NULL on error
+ \param object Index of object to delete.
+*/
+char *U_WMRDELETEOBJECT_set(uint16_t object){
+ return U_WMRCORE_1U16_set(U_WMR_DELETEOBJECT, object);
+}
+
+//! \cond
+char *U_WMRF1_set(void){
+ return U_WMRCORENONE_set("U_WMRF1");
+}
+
+char *U_WMRF2_set(void){
+ return U_WMRCORENONE_set("U_WMRF2");
+}
+
+char *U_WMRF3_set(void){
+ return U_WMRCORENONE_set("U_WMRF3");
+}
+
+char *U_WMRF4_set(void){
+ return U_WMRCORENONE_set("U_WMRF4");
+}
+
+char *U_WMRF5_set(void){
+ return U_WMRCORENONE_set("U_WMRF5");
+}
+
+char *U_WMRF6_set(void){
+ return U_WMRCORENONE_set("U_WMRF6");
+}
+//! \endcond
+
+/**
+ \brief Create and return a U_WMRCREATEPALETTE record
+ \return pointer to the U_WMRCREATEPALETTE record, or NULL on error
+ \param Palette Create a Palette object.
+*/
+char *U_WMRCREATEPALETTE_set(U_PALETTE *Palette){
+ return U_WMRCORE_PALETTE_set(U_WMR_CREATEPALETTE, Palette);
+}
+
+//! \cond
+char *U_WMRF8_set(void){
+ return U_WMRCORENONE_set("U_WMRF8");
+}
+//! \endcond
+
+/**
+ \brief Allocate and construct a U_WMRCREATEPATTERNBRUSH record.
+ WARNING - U_WMRCREATEPATTERNBRUSH has been declared obsolete and application support is spotty -
+ use U_WMRDIBCREATEPATTERNBRUSH instead.
+ \return pointer to the U_WMRCREATEPATTERNBRUSH record, or NULL on error.
+ \param Bm16 Pointer to a Bitmap16 Object, only the first 10 bytes are used.
+ \param Pattern byte array pattern, described by Bm16, for brush
+*/
+char *U_WMRCREATEPATTERNBRUSH_set(
+ U_BITMAP16 *Bm16,
+ char *Pattern
+ ){
+ char *record;
+ uint32_t irecsize,off,cbPat;
+ if(!Bm16 || !Pattern)return(NULL);
+
+ cbPat = (((Bm16->Width * Bm16->BitsPixel + 15) >> 4) << 1) * Bm16->Height;
+ irecsize = U_SIZE_METARECORD + 14 + 18 + cbPat; /* core WMR + truncated Bm16 + 18 spaces bytes + pattern */
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_CREATEPATTERNBRUSH);
+ off = U_SIZE_METARECORD;
+ memcpy(record + off, Bm16, 14); off+=14; /* Truncated bitmap16 object, last 4 bytes are to be ignored*/
+ memset(record + off, 0, 18); off+=18; /* 18 bytes of zero, which are ignored */
+ memcpy(record + off, Pattern, cbPat); /* The pattern array */
+ }
+ return(record);
+}
+
+/**
+ \brief Allocate and construct a U_WMRCREATEPENINDIRECT record.
+ \return pointer to the U_WMRCREATEPENINDIRECT record, or NULL on error.
+ \param pen Parameters of the pen object to create.
+*/
+char *U_WMRCREATEPENINDIRECT_set(U_PEN pen){
+ return U_WMRCORE_2U16_N16_set(U_WMR_CREATEPENINDIRECT, NULL, NULL, U_SIZE_PEN/2, &pen);
+}
+
+/**
+ \brief Allocate and construct a U_WMRCREATEFONTINDIRECT record.
+ \return pointer to the U_WMRCREATEFONTINDIRECT record, or NULL on error.
+ \param font Parameters of the font object to create.
+*/
+char *U_WMRCREATEFONTINDIRECT_set(U_FONT *font){
+ char *record=NULL;
+ uint32_t irecsize,off,flen;
+ flen = 1 + strlen((char *)font->FaceName); /* include the null terminator in the count */
+ if(flen & 1) flen++; /* make the allocation end line up at an even byte */
+ irecsize = U_SIZE_METARECORD + U_SIZE_FONT_CORE + flen;
+ record = calloc(1,irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_CREATEFONTINDIRECT);
+ off = U_SIZE_METARECORD;
+ memcpy(record+off,font,U_SIZE_FONT_CORE + flen);
+ }
+ return(record);
+}
+
+/**
+ \brief Allocate and construct a U_WMRCREATEBRUSHINDIRECT record.
+ \return pointer to the U_WMRCREATEBRUSHINDIRECT record, or NULL on error.
+ \param brush Parameters of the brush object to create.
+*/
+char *U_WMRCREATEBRUSHINDIRECT_set(U_WLOGBRUSH brush){
+ return U_WMRCORE_2U16_N16_set(U_WMR_CREATEBRUSHINDIRECT, NULL, NULL, U_SIZE_WLOGBRUSH/2, &brush);
+}
+
+/** in GDI and Wine, not in WMF manual.
+*/
+char *U_WMRCREATEBITMAPINDIRECT_set(void){
+ return U_WMRCORENONE_set("U_WMRCREATEBITMAPINDIRECT");
+}
+
+/** in GDI and Wine, not in WMF manual.
+*/
+ char *U_WMRCREATEBITMAP_set(void){
+ return U_WMRCORENONE_set("U_WMRCREATEBITMAP");
+}
+
+/**
+ \brief Allocate and construct a U_WMRCREATEREGION record.
+ \return pointer to the U_WMRCREATEREGION record, or NULL on error.
+ \param region Parameters of the region object to create.
+*/
+char *U_WMRCREATEREGION_set(const U_REGION *region){
+ char *record=NULL;
+ uint32_t irecsize,off;
+ irecsize = U_SIZE_METARECORD + region->Size;
+ record = malloc(irecsize);
+ if(record){
+ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_CREATEREGION);
+ off = U_SIZE_METARECORD;
+ memcpy(record+off,region,region->Size);
+ }
+ return(record);
+}
+
+
+/* all of the *_set are above, all of the *_get are below */
+
+/* **********************************************************************************************
+These functions are used for Image conversions and other
+utility operations. Character type conversions are in uwmf_utf.c
+*********************************************************************************************** */
+
+
+/**
+ \brief Make up an approximate dx array to pass to U_WMREXTTEXTOUT_get(), based on character height and weight.
+
+ Take abs. value of character height, get width by multiplying by 0.6, and correct weight
+ approximately, with formula (measured on screen for one text line of Arial).
+ Caller is responsible for free() on the returned pointer.
+
+ \return pointer to dx array
+ \param height character height (absolute value will be used)
+ \param weight LF_Weight Enumeration (character weight)
+ \param members Number of entries to put into dx
+
+*/
+int16_t *dx16_get(
+ int32_t height,
+ uint32_t weight,
+ uint32_t members
+ ){
+ uint32_t i, width;
+ int16_t *dx;
+ dx = (int16_t *) malloc(members * sizeof(int16_t));
+ if(dx){
+ if(U_FW_DONTCARE == weight)weight=U_FW_NORMAL;
+ width = (uint32_t) U_ROUND(((float) (height > 0 ? height : -height)) * 0.6 * (0.00024*(float) weight + 0.904));
+ for ( i = 0; i < members; i++ ){ dx[i] = (width > INT16_MAX ? INT16_MAX : width); }
+ }
+ return(dx);
+}
+
+/**
+ \brief Return the size of a WMF record, or 0 if it is found to be invalid.
+ A valid record will have a size that does not cause it to extend
+ beyond the end of data in memory.
+ A valid record will not be smaller than the smallest possible WMF record.
+ \return size of the record in bytes, 0 on failure
+ \param contents record to extract data from
+ \param blimit one byte past the last WMF record in memory.
+*/
+size_t U_WMRRECSAFE_get(
+ const char *contents,
+ const char *blimit
+ ){
+ size_t size=0;
+ uint32_t Size16;
+ memcpy(&Size16, contents + offsetof(U_METARECORD,Size16_4), 4);
+ size = 2*Size16;
+ /* Record is not self consistent - described size past the end of WMF in memory */
+ if(size < U_SIZE_METARECORD || IS_MEM_UNSAFE(contents, size, blimit))size=0;
+ return(size);
+}
+
+
+/* **********************************************************************************************
+These functions create standard structures used in the WMR records.
+*********************************************************************************************** */
+
+// hide these from Doxygen
+//! \cond
+/* **********************************************************************************************
+These functions contain shared code used by various U_WMR*_get functions. These should NEVER be called
+by end user code and to further that end prototypes are NOT provided and they are hidden from Doxygen.
+*********************************************************************************************** */
+
+int U_WMRCORENONE_get(char *string){
+ printf("unimplemented creator for:%s\n",string);
+ return(0);
+}
+
+/* Returns the record size in bytes for a valid record, or 0 for an invalid record.
+ A valid record's size is at least as large as the minimum size passed in through minsize.
+ Use U_WMRRECSAFE_get() to check if the record extends too far in memory.
+*/
+int U_WMRCORE_RECSAFE_get(
+ const char *contents,
+ int minsize
+){
+ int size=0;
+ uint32_t Size16;
+ memcpy(&Size16, contents + offsetof(U_METARECORD,Size16_4),4);
+ size = 2*Size16;
+ if(size < minsize)size=0;
+ return(size);
+}
+
+
+/* records like U_WMRFLOODFILL and others. all args are optional, Color is not */
+int U_WMRCORE_1U16_CRF_2U16_get(
+ const char *contents,
+ uint16_t *arg1,
+ U_COLORREF *Color,
+ uint16_t *arg2,
+ uint16_t *arg3
+ ){
+ int size = 0;
+ int off = U_SIZE_METARECORD;
+ if(arg1){ memcpy(arg1, contents + off, 2); off+=2; size+=2;}
+ memcpy(Color, contents + off, 4); off+=4; size+=4;
+ if(arg2){ memcpy(arg2, contents + off, 2); off+=2; size+=2;}
+ if(arg3){ memcpy(arg3, contents + off, 2); size+=2;}
+ return(size);
+}
+
+/* records that have a single uint16_t argument like U_WMRSETMAPMODE
+ May also be used with int16_t with appropriate casts */
+int U_WMRCORE_1U16_get(
+ const char *contents,
+ int minsize,
+ uint16_t *arg1
+ ){
+ int size = U_WMRCORE_RECSAFE_get(contents, minsize);
+ int off = U_SIZE_METARECORD;
+ if(!size)return(0);
+ memcpy(arg1, contents + off, 2);
+ return(size);
+}
+
+/* records that have two uint16_t arguments like U_WMRSETBKMODE
+ May also be used with int16_t with appropriate casts */
+int U_WMRCORE_2U16_get(
+ const char *contents,
+ int minsize,
+ uint16_t *arg1,
+ uint16_t *arg2
+ ){
+ int size = U_WMRCORE_RECSAFE_get(contents, minsize);
+ int off = U_SIZE_METARECORD;
+ memcpy(arg1, contents + off, 2); off+=2;
+ memcpy(arg2, contents + off, 2);
+ return(size);
+}
+
+/* records that have four uint16_t arguments like U_WMRSCALEWINDOWEXT
+ May also be used with int16_t with appropriate casts */
+int U_WMRCORE_4U16_get(
+ const char *contents,
+ int minsize,
+ uint16_t *arg1,
+ uint16_t *arg2,
+ uint16_t *arg3,
+ uint16_t *arg4
+ ){
+ int size = U_WMRCORE_RECSAFE_get(contents, minsize);
+ int off = U_SIZE_METARECORD;
+ if(!size)return(0);
+ memcpy(arg1, contents + off, 2); off+=2;
+ memcpy(arg2, contents + off, 2); off+=2;
+ memcpy(arg3, contents + off, 2); off+=2;
+ memcpy(arg4, contents + off, 2);
+ return(size);
+}
+
+/* records that have five uint16_t arguments like U_WMRCREATEPENINDIRECT
+ May also be used with int16_t with appropriate casts */
+int U_WMRCORE_5U16_get(
+ const char *contents,
+ int minsize,
+ uint16_t *arg1,
+ uint16_t *arg2,
+ uint16_t *arg3,
+ uint16_t *arg4,
+ uint16_t *arg5
+ ){
+ int size = U_WMRCORE_RECSAFE_get(contents, minsize);
+ int off = U_SIZE_METARECORD;
+ if(!size)return(0);
+ memcpy(arg1, contents + off, 2); off+=2;
+ memcpy(arg2, contents + off, 2); off+=2;
+ memcpy(arg3, contents + off, 2); off+=2;
+ memcpy(arg4, contents + off, 2); off+=2;
+ memcpy(arg5, contents + off, 2);
+ return(size);
+}
+
+/* records that have six uint16_t arguments like U_ROUNDREC
+ May also be used with int16_t with appropriate casts */
+int U_WMRCORE_6U16_get(
+ const char *contents,
+ int minsize,
+ uint16_t *arg1,
+ uint16_t *arg2,
+ uint16_t *arg3,
+ uint16_t *arg4,
+ uint16_t *arg5,
+ uint16_t *arg6
+ ){
+ int size = U_WMRCORE_RECSAFE_get(contents, minsize);
+ int off = U_SIZE_METARECORD;
+ if(!size)return(0);
+ memcpy(arg1, contents + off, 2); off+=2;
+ memcpy(arg2, contents + off, 2); off+=2;
+ memcpy(arg3, contents + off, 2); off+=2;
+ memcpy(arg4, contents + off, 2); off+=2;
+ memcpy(arg5, contents + off, 2); off+=2;
+ memcpy(arg6, contents + off, 2);
+ return(size);
+}
+
+/* records that have eight uint16_t arguments like U_WMRARC
+ May also be used with int16_t with appropriate casts */
+int U_WMRCORE_8U16_get(
+ const char *contents,
+ int minsize,
+ uint16_t *arg1,
+ uint16_t *arg2,
+ uint16_t *arg3,
+ uint16_t *arg4,
+ uint16_t *arg5,
+ uint16_t *arg6,
+ uint16_t *arg7,
+ uint16_t *arg8
+ ){
+ int size = U_WMRCORE_RECSAFE_get(contents, minsize);
+ int off = U_SIZE_METARECORD;
+ if(!size)return(0);
+ memcpy(arg1, contents + off, 2); off+=2;
+ memcpy(arg2, contents + off, 2); off+=2;
+ memcpy(arg3, contents + off, 2); off+=2;
+ memcpy(arg4, contents + off, 2); off+=2;
+ memcpy(arg5, contents + off, 2); off+=2;
+ memcpy(arg6, contents + off, 2); off+=2;
+ memcpy(arg7, contents + off, 2); off+=2;
+ memcpy(arg8, contents + off, 2);
+ return(size);
+}
+
+/* records that have
+ arg1 an (optional) (u)int16
+ arg2 an (optional( (u)int16
+ array of data cells or just a bunch of data. Passed as a char because the structures in the WMF in memory may
+ not be aligned properly for those structures. Caller has to take them apart - carefully.
+ like U_WMRCREATEBRUSHINDIRECT with arg1=arg2=NULL
+*/
+int U_WMRCORE_2U16_N16_get(
+ const char *contents,
+ int minsize,
+ uint16_t *arg1,
+ uint16_t *arg2,
+ const char **array
+ ){
+ int size = U_WMRCORE_RECSAFE_get(contents, minsize);
+ int off = U_SIZE_METARECORD;
+ if(!size)return(0);
+ if(arg1){ memcpy(arg1, contents + off, 2); off+=2; }
+ if(arg2){ memcpy(arg2, contents + off, 2); off+=2; }
+ *array = (contents + off);
+ return(size);
+}
+
+
+
+/* records that get a U_PALETTE like U_WMRANIMATEPALETTE. Fills in the first two fields of U_PALETTE only, and returns
+ returns a separateepointer to the PalEntries[] array. This pointer is most likely not aligned with the data.
+ */
+int U_WMRCORE_PALETTE_get(
+ const char *contents,
+ int minsize,
+ U_PALETTE *Palette,
+ const char **PalEntries
+ ){
+ int size = U_WMRCORE_RECSAFE_get(contents, minsize);
+ if(!size)return(0);
+ contents += offsetof(U_WMRANIMATEPALETTE, Palette);
+ memset(Palette, 0, (U_SIZE_PALETTE));
+ memcpy(Palette, contents, (U_SIZE_PALETTE));
+ *PalEntries = (contents + offsetof(U_PALETTE, PalEntries));
+ return(size);
+}
+
+//! \endcond
+
+/**
+ \brief Return parameters from a bitmapcoreheader.
+ All are returned as 32 bit integers, regardless of their internal representation.
+
+ \param BmiCh char * pointer to a U_BITMAPCOREHEADER. Note, data may not be properly aligned.
+ \param Size size of the coreheader in bytes
+ \param Width; Width of pixel array
+ \param Height; Height of pixel array
+ \param BitCount Pixel Format (BitCount Enumeration)
+*/
+void U_BITMAPCOREHEADER_get(
+ const char *BmiCh,
+ uint32_t *Size,
+ int32_t *Width,
+ int32_t *Height,
+ int32_t *BitCount
+ ){
+ uint32_t utmp4;
+ uint16_t utmp2;
+ memcpy(&utmp4, BmiCh + offsetof(U_BITMAPCOREHEADER,Size_4), 4); *Size = utmp4;
+ memcpy(&utmp2, BmiCh + offsetof(U_BITMAPCOREHEADER,Width), 2); *Width = utmp2;
+ memcpy(&utmp2, BmiCh + offsetof(U_BITMAPCOREHEADER,Height), 2); *Height = utmp2;
+ memcpy(&utmp2, BmiCh + offsetof(U_BITMAPCOREHEADER,BitCount), 2); *BitCount = utmp2;
+}
+
+/**
+ \brief Return parameters from a bitinfoheader.
+ All are returned as 32 bit integers, regardless of their internal representation.
+
+ \param Bmih char * pointer to a U_BITMAPINFOHEADER. Note, data may not be properly aligned.
+ \param Size Structure size in bytes
+ \param Width Bitmap width in pixels
+ \param Height Bitmap height in pixels, may be negative.
+ \param Planes Planes (must be 1)
+ \param BitCount BitCount Enumeration (determines number of RBG colors)
+ \param Compression BI_Compression Enumeration
+ \param SizeImage Image size in bytes or 0 = "default size (calculated from geometry?)"
+ \param XPelsPerMeter X Resolution in pixels/meter
+ \param YPelsPerMeter Y Resolution in pixels/meter
+ \param ClrUsed Number of bmciColors in U_BITMAPINFO/U_BITMAPCOREINFO that are used by the bitmap
+ \param ClrImportant Number of bmciColors needed (0 means all).
+
+
+*/
+void U_BITMAPINFOHEADER_get(
+ const char *Bmih,
+ uint32_t *Size,
+ int32_t *Width,
+ int32_t *Height,
+ uint32_t *Planes,
+ uint32_t *BitCount,
+ uint32_t *Compression,
+ uint32_t *SizeImage,
+ int32_t *XPelsPerMeter,
+ int32_t *YPelsPerMeter,
+ uint32_t *ClrUsed,
+ uint32_t *ClrImportant
+ ){
+ int32_t tmp4;
+ uint32_t utmp4;
+ uint16_t utmp2;
+
+ memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biSize ), 4); *Size = utmp4;
+ memcpy( &tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biWidth ), 4); *Width = tmp4;
+ memcpy( &tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biHeight ), 4); *Height = tmp4;
+ memcpy(&utmp2, Bmih + offsetof(U_BITMAPINFOHEADER,biPlanes ), 2); *Planes = utmp2;
+ memcpy(&utmp2, Bmih + offsetof(U_BITMAPINFOHEADER,biBitCount ), 2); *BitCount = utmp2;
+ memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biCompression ), 4); *Compression = utmp4;
+ memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biSizeImage ), 4); *SizeImage = utmp4;
+ memcpy( &tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biXPelsPerMeter), 4); *XPelsPerMeter = tmp4;
+ memcpy( &tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biYPelsPerMeter), 4); *YPelsPerMeter = tmp4;
+ memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biClrUsed ), 4); *ClrUsed = utmp4;
+ memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biClrImportant ), 4); *ClrImportant = utmp4;
+}
+
+/**
+ \brief Assume a packed DIB and get the parameters from it, use by DBI_to_RGBA()
+
+ \return BI_Compression Enumeration. For anything other than U_BI_RGB values other than px may not be valid.
+ \param dib pointer to the start of the DIB in the record
+ \param px pointer to DIB pixel array
+ \param ct pointer to DIB color table
+ \param numCt DIB color table number of entries, for PNG or JPG returns the number of bytes in the image
+ \param width Width of pixel array
+ \param height Height of pixel array (always returned as a positive number)
+ \param colortype DIB BitCount Enumeration
+ \param invert If DIB rows are in opposite order from RGBA rows
+*/
+int wget_DIB_params(
+ const char *dib,
+ const char **px,
+ const U_RGBQUAD **ct,
+ uint32_t *numCt,
+ int32_t *width,
+ int32_t *height,
+ int32_t *colortype,
+ int32_t *invert
+ ){
+ uint32_t bic;
+ uint32_t Size;
+ bic = U_BI_RGB; // this information is not in the coreheader;
+ U_BITMAPCOREHEADER_get(dib, &Size, width, height, colortype);
+ if(Size != 0xC ){ //BitmapCoreHeader
+ /* if biCompression is not U_BI_RGB some or all of the following might not hold real values.
+ Ignore most of the information returned from the bitmapinfoheader.
+ */
+ uint32_t uig4;
+ int32_t ig4;
+ U_BITMAPINFOHEADER_get(dib, &uig4, width, height,&uig4, (uint32_t *) colortype, &bic, &uig4, &ig4, &ig4, &uig4, &uig4);
+ }
+ if(*height < 0){
+ *height = -*height;
+ *invert = 1;
+ }
+ else {
+ *invert = 0;
+ }
+ *px = dib + U_SIZE_BITMAPINFOHEADER;
+ if(bic == U_BI_RGB){
+ *numCt = get_real_color_count(dib);
+ if(*numCt){
+ *ct = (U_RGBQUAD *) (dib + U_SIZE_BITMAPINFOHEADER);
+ *px += U_SIZE_COLORREF * (*numCt);
+ }
+ else { *ct = NULL; }
+ }
+ else {
+ memcpy(numCt, dib + offsetof(U_BITMAPINFOHEADER,biSizeImage), 4);
+ *ct = NULL;
+ }
+ return(bic);
+}
+
+
+
+/* **********************************************************************************************
+These are the core WMR functions, each extracts data from a particular type of record.
+In general routines fill in structures which have been passed in by the caller, and zero them
+if that (optional) structure is not present.
+Because the WMF records may not be aligned they are generally copied into the supplied
+ aligned structs, so that the caller may retrieve fields with the usual sorts of
+ structure operations: Struct.field or (*Struct)->field.
+A few routines return pointers to data regions in the record.
+They are listed in order by the corresponding U_WMR_* index number.
+*********************************************************************************************** */
+
+/**
+ \brief Get data from a (placeable) WMR_HEADER.
+ \return size of the record in bytes, 0 on failure
+ \param contents record to extract data from
+ \param blimit one byte past the last WMF record in memory.
+ \param Placeable U_WMRPLACEABLE data, if any
+ \param Header U_WMRHEADER data, if any
+*/
+int wmfheader_get(
+ const char *contents,
+ const char *blimit,
+ U_WMRPLACEABLE *Placeable,
+ U_WMRHEADER *Header
+ ){
+ uint32_t Key;
+ int size=0;
+ if(!contents || !Placeable || !Header || !blimit)return(0);
+ if(IS_MEM_UNSAFE(contents, 4, blimit))return(0);
+ memcpy(&Key, contents + offsetof(U_WMRPLACEABLE,Key), 4);
+ if(Key == 0x9AC6CDD7){
+ size += U_SIZE_WMRPLACEABLE;
+ if(IS_MEM_UNSAFE(contents, size, blimit))return(0);
+ memcpy(Placeable, contents, U_SIZE_WMRPLACEABLE);
+ contents += U_SIZE_WMRPLACEABLE;
+ }
+ else {
+ memset(Placeable, 0, U_SIZE_WMRPLACEABLE);
+ }
+ if(IS_MEM_UNSAFE(contents, size + U_SIZE_WMRHEADER, blimit))return(0);
+ size += 2* (*(uint16_t *)(contents + offsetof(U_WMRHEADER,Size16w)));
+ if(IS_MEM_UNSAFE(contents, size, blimit))return(0);
+ memcpy(Header, contents, U_SIZE_WMRHEADER);
+ return(size);
+}
+
+
+/**
+ \brief Get data from a U_WMREOF record
+ \return size of record in bytes, or 0 on error
+ \param contents record to extract data from
+*/
+int U_WMREOF_get(
+ const char *contents
+ ){
+ return(U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMREOF)));
+}
+
+/**
+ \brief Retrieve values from a U_WMRSETBKCOLOR record
+ \return length of the U_WMRSETBKCOLOR record, or NULL on error
+ \param contents record to extract data from
+ \param Color Background Color.
+*/
+int U_WMRSETBKCOLOR_get(
+ const char *contents,
+ U_COLORREF *Color
+ ){
+ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSETBKCOLOR));
+ if(!size)return(0);
+ memcpy(Color,contents + offsetof(U_WMRSETBKCOLOR,Color),U_SIZE_COLORREF);
+ return(size);
+}
+
+/**
+ \brief Retrieve values from a U_WMRSETBKMODE record
+ \return length of the U_WMRSETBKMODE record, or NULL on error
+ \param contents record to extract data from
+ \param Mode MixMode Enumeration
+*/
+int U_WMRSETBKMODE_get(
+ const char *contents,
+ uint16_t *Mode
+ ){
+ return(U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSETBKMODE), Mode));
+}
+
+/**
+ \brief Retrieve values from a U_WMRSETMAPMODE record
+ \return length of the U_WMRSETMAPMODE record, or NULL on error
+ \param contents record to extract data from
+ \param Mode MapMode Enumeration
+*/
+int U_WMRSETMAPMODE_get(
+ const char *contents,
+ uint16_t *Mode
+ ){
+ return(U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSETMAPMODE), Mode));
+}
+
+/**
+ \brief Retrieve values from a U_WMRSETROP2 record
+ \return length of the U_WMRSETROP2 record, or NULL on error
+ \param contents record to extract data from
+ \param Mode Binary Raster Operation Enumeration
+*/
+int U_WMRSETROP2_get(
+ const char *contents,
+ uint16_t *Mode
+ ){
+ return(U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSETROP2), Mode));
+}
+
+/**
+ \brief Get data from a U_WMRSETRELABS record
+ \return length of the U_WMRSETRELABS record in bytes, or 0 on error
+ \param contents record to extract data from
+*/
+int U_WMRSETRELABS_get(
+ const char *contents
+ ){
+ return(U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSETRELABS)));
+}
+
+/**
+ \brief Retrieve values from a U_WMRSETPOLYFILLMODE record
+ \return length of the U_WMRSETPOLYFILLMODE record, or NULL on error
+ \param contents record to extract data from
+ \param Mode PolyFillMode Enumeration
+*/
+int U_WMRSETPOLYFILLMODE_get(
+ const char *contents,
+ uint16_t *Mode
+ ){
+ return(U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSETPOLYFILLMODE), Mode));
+}
+
+/**
+ \brief Retrieve values from a U_WMRSETSTRETCHBLTMODE record
+ \return length of the U_WMRSETSTRETCHBLTMODE record, or NULL on error
+ \param contents record to extract data from
+ \param Mode StretchMode Enumeration
+*/
+int U_WMRSETSTRETCHBLTMODE_get(
+ const char *contents,
+ uint16_t *Mode
+ ){
+ return(U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSETSTRETCHBLTMODE), Mode));
+}
+
+/**
+ \brief Retrieve values from a U_WMRSETTEXTCHAREXTRA record
+ \return length of the U_WMRSETTEXTCHAREXTRA record, or NULL on error
+ \param contents record to extract data from
+ \param Mode Extra space in logical units to add to each character
+*/
+int U_WMRSETTEXTCHAREXTRA_get(
+ const char *contents,
+ uint16_t *Mode
+ ){
+ return(U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSETTEXTCHAREXTRA), Mode));
+}
+
+/**
+ \brief Retrieve values from a U_WMRSETTEXTCOLOR record
+ \return length of the U_WMRSETTEXTCOLOR record, or NULL on error
+ \param contents record to extract data from
+ \param Color Text Color.
+*/
+int U_WMRSETTEXTCOLOR_get(
+ const char *contents,
+ U_COLORREF *Color
+ ){
+ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSETTEXTCOLOR));
+ if(!size)return(0);
+ memcpy(Color,contents + offsetof(U_WMRSETTEXTCOLOR,Color),U_SIZE_COLORREF);
+ return(size);
+}
+
+/**
+ \brief Retrieve values from a U_WMRSETTEXTJUSTIFICATION record
+ \return length of the U_WMRSETTEXTJUSTIFICATION record, or NULL on error
+ \param contents record to extract data from
+ \param Count Number of space characters in the line.
+ \param Extra Number of extra space characters to add to the line.
+*/
+int U_WMRSETTEXTJUSTIFICATION_get(
+ const char *contents,
+ uint16_t *Count,
+ uint16_t *Extra
+ ){
+ return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMRSETTEXTJUSTIFICATION), Count, Extra));
+}
+
+/**
+ \brief Retrieve values from a U_WMRSETWINDOWORG record
+ \return length of the U_WMRSETWINDOWORG record, or NULL on error
+ \param contents record to extract data from
+ \param coord Window Origin.
+*/
+int U_WMRSETWINDOWORG_get(
+ const char *contents,
+ U_POINT16 * coord
+ ){
+ return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMRSETWINDOWORG), U_P16(coord->y), U_P16(coord->x)));
+}
+
+/**
+ \brief Retrieve values from a U_WMRSETWINDOWEXT record
+ \return length of the U_WMRSETWINDOWEXT record, or NULL on error
+ \param contents record to extract data from
+ \param extent Window Extent.
+*/
+int U_WMRSETWINDOWEXT_get(
+ const char *contents,
+ U_POINT16 * extent
+ ){
+ return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMRSETWINDOWEXT), U_P16(extent->y), U_P16(extent->x)));
+}
+
+/**
+ \brief Retrieve values from a U_WMRSETVIEWPORTORG record
+ \return length of the U_WMRSETVIEWPORTORG record, or NULL on error
+ \param contents record to extract data from
+ \param coord Viewport Origin.
+*/
+int U_WMRSETVIEWPORTORG_get(
+ const char *contents,
+ U_POINT16 * coord
+ ){
+ return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMRSETVIEWPORTORG), U_P16(coord->y), U_P16(coord->x)));
+
+}
+
+/**
+ \brief Retrieve values from a U_WMRSETVIEWPORTEXT record
+ \return length of the U_WMRSETVIEWPORTEXT record, or NULL on error
+ \param contents record to extract data from
+ \param extent Viewport Extent.
+*/
+int U_WMRSETVIEWPORTEXT_get(
+ const char *contents,
+ U_POINT16 * extent
+ ){
+ return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMRSETVIEWPORTEXT), U_P16(extent->y), U_P16(extent->x)));
+}
+
+/**
+ \brief Retrieve values from a U_WMROFFSETWINDOWORG record
+ \return length of the U_WMROFFSETWINDOWORG record, or NULL on error
+ \param contents record to extract data from
+ \param offset Window offset in device units.
+*/
+int U_WMROFFSETWINDOWORG_get(
+ const char *contents,
+ U_POINT16 * offset
+ ){
+ return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMROFFSETWINDOWORG), U_P16(offset->y), U_P16(offset->x)));
+}
+
+/**
+ \brief Retrieve values from a U_WMRSCALEWINDOWEXT record
+ \return length of the U_WMRSCALEWINDOWEXT record, or NULL on error
+ \param contents record to extract data from
+ \param Denom {X,Y} denominators.
+ \param Num {X,Y} numerators.
+*/
+int U_WMRSCALEWINDOWEXT_get(
+ const char *contents,
+ U_POINT16 * Denom,
+ U_POINT16 * Num
+ ){
+ return(U_WMRCORE_4U16_get(contents, (U_SIZE_WMRSCALEWINDOWEXT), U_P16(Denom->y), U_P16(Denom->x), U_P16(Num->y), U_P16(Num->x)));
+}
+
+/**
+ \brief Retrieve values from a U_WMROFFSETVIEWPORTORG record
+ \return length of the U_WMROFFSETVIEWPORTORG record, or NULL on error
+ \param contents record to extract data from
+ \param offset Viewport offset in device units.
+*/
+int U_WMROFFSETVIEWPORTORG_get(
+ const char *contents,
+ U_POINT16 * offset
+ ){
+ return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMROFFSETVIEWPORTORG), U_P16(offset->y), U_P16(offset->x)));
+}
+
+/**
+ \brief Retrieve values from a U_WMRSCALEVIEWPORTEXT record
+ \return length of the U_WMRSCALEVIEWPORTEXT record, or NULL on error
+ \param contents record to extract data from
+ \param Denom {X,Y} denominators.
+ \param Num {X,Y} numerators.
+*/
+int U_WMRSCALEVIEWPORTEXT_get(
+ const char *contents,
+ U_POINT16 * Denom,
+ U_POINT16 * Num
+ ){
+ return(U_WMRCORE_4U16_get(contents, (U_SIZE_WMRSCALEVIEWPORTEXT), U_P16(Denom->y), U_P16(Denom->x), U_P16(Num->y), U_P16(Num->x)));
+}
+
+/**
+ \brief Retrieve values from a U_WMRLINETO record
+ \return length of the U_WMRLINETO record, or NULL on error
+ \param contents record to extract data from
+ \param coord Draw line to {X,Y}.
+*/
+int U_WMRLINETO_get(
+ const char *contents,
+ U_POINT16 * coord
+ ){
+ return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMRLINETO), U_P16(coord->y), U_P16(coord->x)));
+}
+
+/**
+ \brief Retrieve values from a U_WMRMOVETO record
+ \return length of the U_WMRMOVETO record, or NULL on error
+ \param contents record to extract data from
+ \param coord Move to {X,Y}.
+*/
+int U_WMRMOVETO_get(
+ const char *contents,
+ U_POINT16 * coord
+ ){
+ return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMRMOVETO), U_P16(coord->y), U_P16(coord->x)));
+}
+
+/**
+ \brief Retrieve values from a U_WMREXCLUDECLIPRECT record
+ \return length of the U_WMREXCLUDECLIPRECT record, or NULL on error
+ \param contents record to extract data from
+ \param rect Exclude rect from clipping region.
+*/
+int U_WMREXCLUDECLIPRECT_get(
+ const char *contents,
+ U_RECT16 *rect
+ ){
+ return(U_WMRCORE_4U16_get(contents, (U_SIZE_WMREXCLUDECLIPRECT), U_P16(rect->bottom), U_P16(rect->right), U_P16(rect->top), U_P16(rect->left)));
+}
+
+/**
+ \brief Retrieve values from a U_WMRINTERSECTCLIPRECT record
+ \return length of the U_WMRINTERSECTCLIPRECT record, or NULL on error
+ \param contents record to extract data from
+ \param rect Clipping region is intersection of existing clipping region with rect.
+*/
+int U_WMRINTERSECTCLIPRECT_get(
+ const char *contents,
+ U_RECT16 *rect
+ ){
+ return(U_WMRCORE_4U16_get(contents, (U_SIZE_WMRINTERSECTCLIPRECT), U_P16(rect->bottom), U_P16(rect->right), U_P16(rect->top), U_P16(rect->left)));
+}
+
+/**
+ \brief Retrieve values from a U_WMRARC record
+ \return length of the U_WMRARC record, or NULL on error
+ \param contents record to extract data from
+ \param StartArc Start of Arc
+ \param EndArc End of Arc
+ \param rect Bounding rectangle.
+*/
+int U_WMRARC_get(
+ const char *contents,
+ U_POINT16 *StartArc,
+ U_POINT16 *EndArc,
+ U_RECT16 *rect
+ ){
+ return U_WMRCORE_8U16_get(
+ contents,
+ (U_SIZE_WMRARC),
+ U_P16(EndArc->y),
+ U_P16(EndArc->x),
+ U_P16(StartArc->y),
+ U_P16(StartArc->x),
+ U_P16(rect->bottom),
+ U_P16(rect->right),
+ U_P16(rect->top),
+ U_P16(rect->left)
+ );
+}
+
+/**
+ \brief Retrieve values from a U_WMRELLIPSE record
+ \return length of the U_WMRELLIPSE record, or NULL on error
+ \param contents record to extract data from
+ \param rect Bounding rectangle for Ellipse.
+*/
+int U_WMRELLIPSE_get(
+ const char *contents,
+ U_RECT16 *rect
+ ){
+ return U_WMRCORE_4U16_get(
+ contents,
+ (U_SIZE_WMRELLIPSE),
+ U_P16(rect->bottom),
+ U_P16(rect->right),
+ U_P16(rect->top),
+ U_P16(rect->left)
+ );
+}
+
+/**
+ \brief Retrieve values from a U_WMRFLOODFILL record
+ \return length of the U_WMRFLOODFILL record, or NULL on error
+ \param contents record to extract data from
+ \param Mode FloodFill Enumeration.
+ \param Color Color to Fill with.
+ \param coord Location to start fill.
+*/
+int U_WMRFLOODFILL_get(
+ const char *contents,
+ uint16_t *Mode,
+ U_COLORREF *Color,
+ U_POINT16 *coord
+ ){
+ return U_WMRCORE_1U16_CRF_2U16_get(
+ contents,
+ Mode,
+ Color,
+ U_P16(coord->y),
+ U_P16(coord->x)
+ );
+}
+
+/**
+ \brief Retrieve values from a U_WMRPIE record
+ \return length of the U_WMRPIE record, or NULL on error
+ \param contents record to extract data from
+ \param Radial1 Start of Pie
+ \param Radial2 End of Pie
+ \param rect Bounding rectangle.
+*/
+int U_WMRPIE_get(
+ const char *contents,
+ U_POINT16 *Radial1,
+ U_POINT16 *Radial2,
+ U_RECT16 *rect
+ ){
+ return U_WMRCORE_8U16_get(
+ contents,
+ (U_SIZE_WMRPIE),
+ U_P16(Radial2->y),
+ U_P16(Radial2->x),
+ U_P16(Radial1->y),
+ U_P16(Radial1->x),
+ U_P16(rect->bottom),
+ U_P16(rect->right),
+ U_P16(rect->top),
+ U_P16(rect->left)
+ );
+}
+
+/**
+ \brief Retrieve values from a U_WMRRECTANGLE record
+ \return length of the U_WMRRECTANGLE record, or NULL on error
+ \param contents record to extract data from
+ \param rect Boundaries.
+*/
+int U_WMRRECTANGLE_get(
+ const char *contents,
+ U_RECT16 *rect
+ ){
+ return U_WMRCORE_4U16_get(
+ contents,
+ (U_SIZE_WMRRECTANGLE),
+ U_P16(rect->bottom),
+ U_P16(rect->right),
+ U_P16(rect->top),
+ U_P16(rect->left)
+ );
+}
+
+/**
+ \brief Retrieve values from a U_WMRROUNDRECT record
+ \return length of the U_WMRROUNDRECT record, or NULL on error
+ \param contents record to extract data from
+ \param Width Horizontal rounding length.
+ \param Height Vertical rounding length.
+ \param rect Boundaries.
+*/
+int U_WMRROUNDRECT_get(
+ const char *contents,
+ int16_t *Width,
+ int16_t *Height,
+ U_RECT16 *rect
+ ){
+ return U_WMRCORE_6U16_get(
+ contents,
+ (U_SIZE_WMRROUNDRECT),
+ U_PP16(Height),
+ U_PP16(Width),
+ U_P16(rect->bottom),
+ U_P16(rect->right),
+ U_P16(rect->top),
+ U_P16(rect->left)
+ );
+}
+
+/**
+ \brief Get data from a U_WMRPATBLT record.
+ \return length of the U_WMRPATBLT record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Dst Destination UL corner in logical units
+ \param cwh W & H for Dst and Src in logical units
+ \param dwRop3 RasterOPeration Enumeration
+*/
+int U_WMRPATBLT_get(
+ const char *contents,
+ U_POINT16 * Dst,
+ U_POINT16 * cwh,
+ uint32_t *dwRop3
+ ){
+ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRPATBLT));
+ if(!size)return(0);
+ memcpy(dwRop3, ( contents + offsetof(U_WMRPATBLT, rop3w)), 4);
+ cwh->y = *(int16_t *)( contents + offsetof(U_WMRPATBLT, Height ));
+ cwh->x = *(int16_t *)( contents + offsetof(U_WMRPATBLT, Width ));
+ Dst->y = *(int16_t *)( contents + offsetof(U_WMRPATBLT, yDst ));
+ Dst->x = *(int16_t *)( contents + offsetof(U_WMRPATBLT, xDst ));
+ return(size);
+}
+
+/**
+ \brief Get data from a U_WMRSAVEDC record
+ \return length of the U_WMRSAVEDC record in bytes, or 0 on error
+ \param contents record to extract data from
+*/
+int U_WMRSAVEDC_get(
+ const char *contents
+ ){
+ return(U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSAVEDC)));
+}
+
+/**
+ \brief Get data from a U_WMRSETPIXEL record
+ \return length of the U_WMRSETPIXEL record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Color pointer to a U_COLORREF variable where the color will be stored.
+ \param Coord pointer to a U_POINT16 variable where the coordinates will be stored.
+*/
+int U_WMRSETPIXEL_get(
+ const char *contents,
+ U_COLORREF *Color,
+ U_POINT16 *Coord){
+ return U_WMRCORE_1U16_CRF_2U16_get(
+ contents,
+ NULL,
+ Color,
+ U_P16(Coord->y),
+ U_P16(Coord->x)
+ );
+}
+
+/**
+ \brief Get data from a U_WMROFFSETCLIPRGN record
+ \return length of the U_WMROFFSETCLIPRGN record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param offset pointer to a U_POINT16 variable where the x,y offsets will be stored.
+*/
+int U_WMROFFSETCLIPRGN_get(
+ const char *contents,
+ U_POINT16 *offset
+ ){
+ return U_WMRCORE_2U16_get(contents, (U_SIZE_WMROFFSETCLIPRGN), U_P16(offset->y), U_P16(offset->x));
+}
+
+/**
+ \brief Get data from a U_WMRTEXTOUT record
+ \return length of the U_WMRTEXTOUT record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Dst coordinates where text will be written
+ \param Length Number of characters in string.
+ \param string Pointer to string in WMF buffer in memory. This text is generally NOT null terminated!!!
+*/
+int U_WMRTEXTOUT_get(
+ const char *contents,
+ U_POINT16 * Dst,
+ int16_t *Length,
+ const char **string
+ ){
+ int16_t L2;
+ int off;
+ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRTEXTOUT));
+ if(!size)return(0);
+ *Length = *(int16_t *)(contents + offsetof(U_WMRTEXTOUT, Length));
+ *string = contents + offsetof(U_WMRTEXTOUT, String); /* May not be null terminated!!! */
+ L2 = *Length;
+ if(L2 & 1)L2++;
+ off = U_SIZE_METARECORD + 2 + L2;
+ memcpy(&Dst->y, contents + off, 2); off+=2;
+ memcpy(&Dst->x, contents + off, 2);
+ return(size);
+}
+
+/**
+ \brief Get data from a U_WMRBITBLT record.
+ Note that unlike U_EMRBITBLT there is no scaling available - the Src and Dst
+ rectangles must be the same size.
+ \return length of the U_WMRBITBLT record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Dst Destination UL corner in logical units
+ \param cwh W & H for Dst and Src in logical units
+ \param Src Source UL corner in logical units
+ \param dwRop3 RasterOPeration Enumeration
+ \param Bm16 bitmap16 object (fields in it are all 0 if no bitmap is used)
+ \param px pointer to bitmap in memory, or NULL if not used
+*/
+int U_WMRBITBLT_get(
+ const char *contents,
+ U_POINT16 * Dst,
+ U_POINT16 * cwh,
+ U_POINT16 * Src,
+ uint32_t *dwRop3,
+ U_BITMAP16 *Bm16,
+ const char **px
+ ){
+ uint8_t xb;
+ uint32_t size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRBITBLT_NOPX));
+ if(!size)return(0);
+ xb = *(uint8_t *)( contents + offsetof(U_METARECORD, xb));
+ if(U_TEST_NOPXB(size,xb)){ /* no bitmap */
+ memcpy(dwRop3, ( contents + offsetof(U_WMRBITBLT_NOPX, rop3w)), 4);
+ Src->y = *(int16_t *)( contents + offsetof(U_WMRBITBLT_NOPX, ySrc ));
+ Src->x = *(int16_t *)( contents + offsetof(U_WMRBITBLT_NOPX, xSrc ));
+ cwh->y = *(int16_t *)( contents + offsetof(U_WMRBITBLT_NOPX, Height ));
+ cwh->x = *(int16_t *)( contents + offsetof(U_WMRBITBLT_NOPX, Width ));
+ Dst->y = *(int16_t *)( contents + offsetof(U_WMRBITBLT_NOPX, yDst ));
+ Dst->x = *(int16_t *)( contents + offsetof(U_WMRBITBLT_NOPX, xDst ));
+ memset(Bm16, 0, U_SIZE_BITMAP16);
+ *px = NULL;
+ }
+ else { /* yes bitmap */
+ memcpy(dwRop3, ( contents + offsetof(U_WMRBITBLT_PX, rop3w)), 4);
+ Src->y = *(int16_t *)( contents + offsetof(U_WMRBITBLT_PX, ySrc ));
+ Src->x = *(int16_t *)( contents + offsetof(U_WMRBITBLT_PX, xSrc ));
+ cwh->y = *(int16_t *)( contents + offsetof(U_WMRBITBLT_PX, Height ));
+ cwh->x = *(int16_t *)( contents + offsetof(U_WMRBITBLT_PX, Width ));
+ Dst->y = *(int16_t *)( contents + offsetof(U_WMRBITBLT_PX, yDst ));
+ Dst->x = *(int16_t *)( contents + offsetof(U_WMRBITBLT_PX, xDst ));
+ memcpy(Bm16, ( contents + offsetof(U_WMRBITBLT_PX, bitmap)), U_SIZE_BITMAP16);
+ *px = ( contents + offsetof(U_WMRBITBLT_PX, bitmap) + U_SIZE_BITMAP16);
+ }
+ return(size);
+}
+
+/**
+ \brief Get data from a U_WMRSTRETCHBLT record.
+ \return length of the U_WMRSTRETCHBLT record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Dst Destination UL corner in logical units
+ \param cDst Destination W & H in logical units
+ \param Src Source UL corner in logical units
+ \param cSrc Source W & H in logical units
+ \param dwRop3 RasterOPeration Enumeration
+ \param Bm16 bitmap16 object (fields in it are all 0 if no bitmap is used)
+ \param px pointer to bitmap in memory, or NULL if not used
+*/
+int U_WMRSTRETCHBLT_get(
+ const char *contents,
+ U_POINT16 * Dst,
+ U_POINT16 * cDst,
+ U_POINT16 * Src,
+ U_POINT16 * cSrc,
+ uint32_t *dwRop3,
+ U_BITMAP16 *Bm16,
+ const char **px
+ ){
+ uint8_t xb;
+ uint32_t size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSTRETCHBLT_NOPX));
+ if(!size)return(0);
+ xb = *(uint8_t *)( contents + offsetof(U_METARECORD, xb));
+ if(U_TEST_NOPXB(size,xb)){ /* no bitmap */
+ memcpy(dwRop3, ( contents + offsetof(U_WMRSTRETCHBLT_NOPX, rop3w)), 4);
+ cSrc->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, hSrc ));
+ cSrc->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, wSrc ));
+ Src->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, ySrc ));
+ Src->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, xSrc ));
+ cDst->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, hDst ));
+ cDst->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, wDst ));
+ Dst->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, yDst ));
+ Dst->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, xDst ));
+ memset(Bm16, 0, U_SIZE_BITMAP16);
+ *px = NULL;
+ }
+ else { /* yes bitmap */
+ memcpy(dwRop3, ( contents + offsetof(U_WMRSTRETCHBLT_PX, rop3w)), 4);
+ cSrc->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, hSrc ));
+ cSrc->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, wSrc ));
+ Src->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, ySrc ));
+ Src->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, xSrc ));
+ cDst->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, hDst ));
+ cDst->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, wDst ));
+ Dst->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, yDst ));
+ Dst->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, xDst ));
+ memcpy(Bm16, ( contents + offsetof(U_WMRSTRETCHBLT_PX, bitmap)), U_SIZE_BITMAP16);
+ *px = ( contents + offsetof(U_WMRSTRETCHBLT_PX, bitmap) + U_SIZE_BITMAP16);
+ }
+ return(size);
+}
+
+/**
+ \brief Get data from a U_WMRPOLYGON record.
+ \return length of the U_WMRPOLYGON record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Length Number of points in the Polygon
+ \param Data pointer to array of U_POINT16 in memory. Pointer may not be aligned properly for structures.
+*/
+int U_WMRPOLYGON_get(
+ const char *contents,
+ uint16_t *Length,
+ const char **Data
+ ){
+ int size = U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRPOLYGON), NULL, Length, Data);
+ if(size){
+ int iLength = (*Length)*sizeof(U_POINT16);
+ if(IS_MEM_UNSAFE(*Data, iLength, contents+size))return(0);
+ }
+ return size;
+}
+
+/**
+ \brief Get data from a U_WMRPOLYLINE record.
+ \return length of the U_WMRPOLYLINE record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Length Number of points in the Polyline
+ \param Data pointer to array of U_POINT16 in memory. Pointer may not be aligned properly for structures.
+*/
+int U_WMRPOLYLINE_get(
+ const char *contents,
+ uint16_t *Length,
+ const char **Data
+ ){
+ int size = U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRPOLYGON), NULL, Length, Data);
+ if(size){
+ int iLength = (*Length)*sizeof(U_POINT16);
+ if(IS_MEM_UNSAFE(*Data, iLength, contents+size))return(0);
+ }
+ return size;
+}
+
+/**
+ \brief Get data from a U_WMRESCAPE record.
+ WARNING! Only three Escape record types are fully supported: SETLINECAP, SETLINEJOIN, SETMITERLIMIT.
+ Even these should not be set here directly, instead use the wsetlinecap_get(), wsetlinejoin_get(),
+ or wsetmiterlimit_get() functions.
+ Escape records created with this function, with the exception of the three named above, will not have
+ the byte orders in Data adjusted automatically. The user code must set Data to be little endian no
+ matter what the endianness of the current platform where the user code is running.
+ \return length of the U_WMRESCAPE record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Escape Escape function
+ \param Length Bytes in the Data
+ \param Data Array of Length bytes
+*/
+int U_WMRESCAPE_get(
+ const char *contents,
+ uint16_t *Escape,
+ uint16_t *Length,
+ const char **Data
+ ){
+ int size = U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRESCAPE), Escape, Length, Data);
+ if(size){
+ int iLength=*Length;
+ if(IS_MEM_UNSAFE(*Data, iLength, contents+size))return(0);
+ }
+ return size;
+}
+
+/**
+ \brief Get data from a U_WMRRESTOREDC record
+ \return length of the U_WMRRESTOREDC record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param DC DC to restore (relative if negative, absolute if positive)
+*/
+int U_WMRRESTOREDC_get(
+ const char *contents,
+ int16_t *DC
+ ){
+ return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRRESTOREDC), (uint16_t *)DC); // signed, but it is just a memcpy, so this works
+}
+
+/**
+ \brief Get data from a U_WMRFILLREGION record.
+ \return length of the U_WMRFILLREGION record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Region Region to fill
+ \param Brush Brush to fill with
+*/
+int U_WMRFILLREGION_get(
+ const char *contents,
+ uint16_t *Region,
+ uint16_t *Brush
+ ){
+ return U_WMRCORE_2U16_get(contents, (U_SIZE_WMRFILLREGION), Region, Brush);
+}
+
+/**
+ \brief Get data from a U_WMRFRAMEREGION record.
+ \return length of the U_WMRFRAMEREGION record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Region Index of region to frame in object table
+ \param Brush Index of brush to use in frame in object table
+ \param Height in logical units (of frame)
+ \param Width in logical units (of frame)
+*/
+int U_WMRFRAMEREGION_get(
+ const char *contents,
+ uint16_t *Region,
+ uint16_t *Brush,
+ int16_t *Height,
+ int16_t *Width
+ ){
+ return U_WMRCORE_4U16_get(contents, (U_SIZE_WMRFRAMEREGION), Region, Brush, U_PP16(Height), U_PP16(Width));
+}
+
+/**
+ \brief Get data from a U_WMRINVERTREGION record.
+ \return length of the U_WMRINVERTREGION record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Region Index of region to invert.
+*/
+int U_WMRINVERTREGION_get(
+ const char *contents,
+ uint16_t *Region
+ ){
+ return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRINVERTREGION), Region);
+}
+
+/**
+ \brief Get data from a U_WMRPAINTREGION record.
+ \return length of the U_WMRPAINTREGION record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Region Index of region to paint with the current Brush.
+*/
+int U_WMRPAINTREGION_get(
+ const char *contents,
+ uint16_t *Region
+ ){
+ return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRPAINTREGION), Region);
+}
+
+/**
+ \brief Get data from a U_WMRSELECTCLIPREGION record.
+ \return length of the U_WMRSELECTCLIPREGION record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Region Index of region to become clipping region..
+*/
+int U_WMRSELECTCLIPREGION_get(
+ const char *contents,
+ uint16_t *Region
+ ){
+ return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSELECTCLIPREGION), Region);
+
+}
+
+/**
+ \brief Get data from a U_WMRSELECTOBJECT record.
+ \return length of the U_WMRSELECTOBJECT record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Object Index of object which is made active.
+*/
+int U_WMRSELECTOBJECT_get(
+ const char *contents,
+ uint16_t *Object
+ ){
+ return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSELECTOBJECT), Object);
+}
+
+/**
+ \brief Get data from a U_WMRSETTEXTALIGN record.
+ \return length of the U_WMRSETTEXTALIGN record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Mode TextAlignment Enumeration.
+*/
+int U_WMRSETTEXTALIGN_get(
+ const char *contents,
+ uint16_t *Mode
+ ){
+ return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSETTEXTALIGN), Mode);
+}
+
+/** in GDI and Wine, not in WMF manual.
+*/
+int U_WMRDRAWTEXT_get(void){ /* in Wine, not in WMF PDF. */
+ return U_WMRCORENONE_get("U_WMRDRAWTEXT");
+}
+
+/**
+ \brief Retrieve values from a U_WMRCHORD record
+ \return length of the U_WMRCHORD record, or NULL on error
+ \param contents record to extract data from
+ \param Radial1 Start of Chord
+ \param Radial2 End of Chord
+ \param rect Bounding rectangle.
+*/
+int U_WMRCHORD_get(
+ const char *contents,
+ U_POINT16 *Radial1,
+ U_POINT16 *Radial2,
+ U_RECT16 *rect
+ ){
+ return U_WMRCORE_8U16_get(
+ contents,
+ (U_SIZE_WMRCHORD),
+ U_P16(Radial2->y),
+ U_P16(Radial2->x),
+ U_P16(Radial1->y),
+ U_P16(Radial1->x),
+ U_P16(rect->bottom),
+ U_P16(rect->right),
+ U_P16(rect->top),
+ U_P16(rect->left)
+ );
+}
+
+/**
+ \brief Get data from a U_WMRSETMAPPERFLAGS record.
+ \return length of the U_WMRSETMAPPERFLAGS record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Mode If 1 bit set font mapper selects only matching aspect fonts.
+*/
+int U_WMRSETMAPPERFLAGS_get(
+ const char *contents,
+ uint32_t *Mode
+ ){
+ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSETMAPPERFLAGS));
+ if(!size)return(0);
+ memcpy(Mode, contents + U_SIZE_METARECORD, 4);
+ return(size);
+}
+
+/**
+ \brief Get data from a U_WMREXTTEXTOUT record.
+ \return length of the U_WMREXTTEXTOUT record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Dst {X,Y} coordinates where the string is to be written.
+ \param Length Stringlength in bytes
+ \param Opts ExtTextOutOptions Flags
+ \param string String to write (Latin1 encoding)
+ \param dx Kerning information. Must have same number of entries as Length.
+ \param rect Used when when U_ETO_OPAQUE or U_ETO_CLIPPED bits are set in Opts
+*/
+int U_WMREXTTEXTOUT_get(
+ const char *contents,
+ U_POINT16 * Dst,
+ int16_t *Length,
+ uint16_t *Opts,
+ const char **string,
+ const int16_t **dx,
+ U_RECT16 *rect
+ ){
+ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMREXTTEXTOUT));
+ int off = U_SIZE_METARECORD;
+ if(!size)return(0);
+ Dst->y = *(int16_t *)( contents + offsetof(U_WMREXTTEXTOUT, y ));
+ Dst->x = *(int16_t *)( contents + offsetof(U_WMREXTTEXTOUT, x ));
+ *Length = *(int16_t *)( contents + offsetof(U_WMREXTTEXTOUT, Length ));
+ *Opts = *(uint16_t *)(contents + offsetof(U_WMREXTTEXTOUT, Opts ));
+ off = U_SIZE_WMREXTTEXTOUT;
+ if(*Opts & (U_ETO_OPAQUE | U_ETO_CLIPPED)){ memcpy(rect, (contents + off), U_SIZE_RECT16); off += U_SIZE_RECT16; }
+ else { memset(rect, 0, U_SIZE_RECT16); }
+ *string = (contents + off);
+ off += 2*((*Length +1)/2);
+ if(*Length){ *dx = (int16_t *)(contents + off); }
+ else { *dx = NULL; }
+ return(size);
+}
+
+/**
+ \brief Get data from a U_WMRSETDIBTODEV record
+ \return length of the U_WMRSETDIBTODEV record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Dst UL corner of Dst rect in logical units
+ \param cwh Width and Height in logical units
+ \param Src UL corner of Src rect in logical units
+ \param cUsage ColorUsage enumeration
+ \param ScanCount Number of scan lines in Src
+ \param StartScan First Scan line in Src
+ \param dib DeviceIndependentBitmap object
+*/
+int U_WMRSETDIBTODEV_get(
+ const char *contents,
+ U_POINT16 * Dst,
+ U_POINT16 * cwh,
+ U_POINT16 * Src,
+ uint16_t *cUsage,
+ uint16_t *ScanCount,
+ uint16_t *StartScan,
+ const char **dib
+ ){
+ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSETDIBTODEV));
+ if(!size)return(0);
+ *cUsage = *(uint16_t *)(contents + offsetof(U_WMRSETDIBTODEV, cUsage ));
+ *ScanCount = *(uint16_t *)(contents + offsetof(U_WMRSETDIBTODEV, ScanCount ));
+ *StartScan = *(uint16_t *)(contents + offsetof(U_WMRSETDIBTODEV, StartScan ));
+ Src->y = *(int16_t *)( contents + offsetof(U_WMRSETDIBTODEV, ySrc ));
+ Src->x = *(int16_t *)( contents + offsetof(U_WMRSETDIBTODEV, xSrc ));
+ cwh->y = *(int16_t *)( contents + offsetof(U_WMRSETDIBTODEV, Height ));
+ cwh->x = *(int16_t *)( contents + offsetof(U_WMRSETDIBTODEV, Width ));
+ Dst->y = *(int16_t *)( contents + offsetof(U_WMRSETDIBTODEV, yDst ));
+ Dst->x = *(int16_t *)( contents + offsetof(U_WMRSETDIBTODEV, xDst ));
+ *dib = ( contents + offsetof(U_WMRSETDIBTODEV, dib ));
+ if(!packed_DIB_safe(*dib, *dib+size))return(0);
+ return(size);
+}
+
+/**
+ \brief Get data from a U_WMRSELECTPALETTE record
+ \return length of the U_WMRSELECTPALETTE record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Palette Index of Palette to make active.
+*/
+int U_WMRSELECTPALETTE_get(
+ const char *contents,
+ uint16_t *Palette
+ ){
+ return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSELECTPALETTE), Palette);
+}
+
+/**
+ \brief Get data from a U_WMRREALIZEPALETTE record
+ \return length of the U_WMRREALIZEPALETTE record in bytes, or 0 on error
+ \param contents record to extract data from
+*/
+int U_WMRREALIZEPALETTE_get(
+ const char *contents
+ ){
+ return U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRREALIZEPALETTE));
+}
+
+/**
+ \brief Get data from a U_WMRSETPALENTRIES record
+ \return length of the U_WMRSETPALENTRIES record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Palette Redefines a set of RGB values for the current active Palette.
+ \param PalEntries Array of Palette Entries
+*/
+int U_WMRANIMATEPALETTE_get(
+ const char *contents,
+ U_PALETTE *Palette,
+ const char **PalEntries
+ ){
+ return U_WMRCORE_PALETTE_get(contents, (U_SIZE_WMRANIMATEPALETTE), Palette, PalEntries);
+}
+
+/**
+ \brief Get data from a U_WMRSETPALENTRIES record
+ \return length of the U_WMRSETPALENTRIES record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Palette Defines a set of RGB values for the current active Palette.
+ \param PalEntries Array of Palette Entries
+*/
+int U_WMRSETPALENTRIES_get(
+ const char *contents,
+ U_PALETTE *Palette,
+ const char **PalEntries
+ ){
+ return U_WMRCORE_PALETTE_get(contents, (U_SIZE_WMRSETPALENTRIES), Palette, PalEntries);
+}
+
+/**
+ \brief Get data from a U_WMR_POLYPOLYGON record.
+ \return length of the U_WMR_POLYPOLYGON record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param nPolys Number of elements in aPolyCounts
+ \param aPolyCounts Number of points in each poly (sequential)
+ \param Points pointer to array of U_POINT16 in memory. Probably not aligned.
+*/
+int U_WMRPOLYPOLYGON_get(
+ const char *contents,
+ uint16_t *nPolys,
+ const uint16_t **aPolyCounts,
+ const char **Points
+ ){
+ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRPOLYPOLYGON));
+ if(!size)return(0);
+ contents += offsetof(U_WMRPOLYPOLYGON, PPolygon);
+ memcpy(nPolys, contents + offsetof(U_POLYPOLYGON, nPolys), 2);
+ *aPolyCounts = (uint16_t *)(contents + offsetof(U_POLYPOLYGON, aPolyCounts));
+ *Points = (contents + offsetof(U_POLYPOLYGON, aPolyCounts) + *nPolys*2);
+ return(size);
+}
+
+/**
+ \brief Get data from a U_WMRRESIZEPALETTE record
+ \return length of the U_WMRRESIZEPALETTE record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Palette Changes the size of the currently active Palette.
+*/
+int U_WMRRESIZEPALETTE_get(
+ const char *contents,
+ uint16_t *Palette
+ ){
+ return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRRESIZEPALETTE), Palette);
+}
+
+//! \cond
+int U_WMR3A_get(void){
+ return U_WMRCORENONE_get("U_WMR3A");
+}
+
+int U_WMR3B_get(void){
+ return U_WMRCORENONE_get("U_WMR3B");
+}
+
+int U_WMR3C_get(void){
+ return U_WMRCORENONE_get("U_WMR3C");
+}
+
+int U_WMR3D_get(void){
+ return U_WMRCORENONE_get("U_WMR3D");
+}
+
+int U_WMR3E_get(void){
+ return U_WMRCORENONE_get("U_WMR3E");
+}
+
+int U_WMR3F_get(void){
+ return U_WMRCORENONE_get("U_WMR3F");
+}
+//! \endcond
+
+// U_WMRDIBBITBLT_get
+/**
+ \brief Get data from a U_WMRDIBITBLT record.
+ \return length of the U_WMRDIBITBLT record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Dst Destination UL corner in logical units
+ \param Src Source UL corner in logical units
+ \param cwh W & H in logical units of Src and Dst
+ \param dwRop3 RasterOPeration Enumeration
+ \param dib pointer to dib in WMF in memory. Most likely not aligned.
+*/
+int U_WMRDIBBITBLT_get(
+ const char *contents,
+ U_POINT16 * Dst,
+ U_POINT16 * cwh,
+ U_POINT16 * Src,
+ uint32_t *dwRop3,
+ const char **dib
+ ){
+ uint8_t xb;
+ uint32_t size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRDIBBITBLT_NOPX));
+ if(!size)return(0);
+ xb = *(uint8_t *)( contents + offsetof(U_METARECORD, xb));
+ if(U_TEST_NOPXB(size,xb)){ /* no bitmap */
+ memcpy(dwRop3, ( contents + offsetof(U_WMRDIBBITBLT_NOPX, rop3w)), 4);
+ Src->y = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_NOPX, ySrc ));
+ Src->x = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_NOPX, xSrc ));
+ cwh->y = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_NOPX, Height ));
+ cwh->x = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_NOPX, Width ));
+ Dst->y = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_NOPX, yDst ));
+ Dst->x = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_NOPX, xDst ));
+ *dib = NULL;
+ }
+ else { /* yes bitmap */
+ memcpy(dwRop3, ( contents + offsetof(U_WMRDIBBITBLT_PX, rop3w)), 4);
+ Src->y = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_PX, ySrc ));
+ Src->x = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_PX, xSrc ));
+ cwh->y = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_PX, Height ));
+ cwh->x = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_PX, Width ));
+ Dst->y = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_PX, yDst ));
+ Dst->x = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_PX, xDst ));
+ *dib = ( contents + offsetof(U_WMRDIBBITBLT_PX, dib ));
+ if(!packed_DIB_safe(*dib, *dib+size))return(0);
+ }
+ return(size);
+}
+
+/**
+ \brief Get data from a U_WMRSTRETCHDIB record.
+ \return length of the U_WMRSTRETCHDIB record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Dst Destination UL corner in logical units
+ \param cDst Destination W & H in logical units
+ \param Src Source UL corner in logical units
+ \param cSrc Source W & H in logical units
+ \param dwRop3 RasterOPeration Enumeration
+ \param dib pointer to dib in WMF in memory. Most likely not aligned.
+*/
+int U_WMRDIBSTRETCHBLT_get(
+ const char *contents,
+ U_POINT16 * Dst,
+ U_POINT16 * cDst,
+ U_POINT16 * Src,
+ U_POINT16 * cSrc,
+ uint32_t *dwRop3,
+ const char **dib
+ ){
+ uint8_t xb;
+ uint32_t size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRDIBSTRETCHBLT_NOPX));
+ if(!size)return(0);
+ xb = *(uint8_t *)( contents + offsetof(U_METARECORD, xb));
+ if(U_TEST_NOPXB(size,xb)){ /* no bitmap */
+ memcpy(dwRop3 , ( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, rop3w)), 4);
+ Src->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, ySrc ));
+ Src->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, xSrc ));
+ cSrc->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, hSrc ));
+ cSrc->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, wSrc ));
+ Dst->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, yDst ));
+ Dst->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, xDst ));
+ cDst->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, hDst ));
+ cDst->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, wDst ));
+ *dib = NULL;
+ }
+ else { /* yes bitmap */
+ memcpy(dwRop3 , ( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, rop3w)), 4);
+ Src->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, ySrc ));
+ Src->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, xSrc ));
+ cSrc->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, hSrc ));
+ cSrc->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, wSrc ));
+ Dst->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, yDst ));
+ Dst->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, xDst ));
+ cDst->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, hDst ));
+ cDst->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, wDst ));
+ *dib = ( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, dib ));
+ if(!packed_DIB_safe(*dib, *dib+size))return(0);
+ }
+ return(size);
+}
+
+/**
+ \brief Get data from a U_WMRDIBCREATEPATTERNBRUSH record.
+ Returns an image as either a DIB (Bmi/CbPx/Px defined) or a Bitmap16 (Bm16 defined).
+ WARNING - U_WMRCREATEPATTERNBRUSH has been declared obsolete and application support is spotty -
+ this function is still valid though, for those instances where old WMF input files are encountered.
+ \return length of the U_WMRDIBCREATEPATTERNBRUSH record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Style BrushStyle Enumeration
+ \param cUsage DIBcolors Enumeration
+ \param Bm16 pointer to a U_BITMAP16 in WMF in memory. Most likely not aligned. NULL if dib is used instead.
+ \param dib pointer to a dib in WMF in memory. Most likely not aligned. NULL if Bm16 is used instead.
+ */
+int U_WMRDIBCREATEPATTERNBRUSH_get(
+ const char *contents,
+ uint16_t *Style,
+ uint16_t *cUsage,
+ const char **Bm16,
+ const char **dib
+ ){
+ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRDIBCREATEPATTERNBRUSH));
+ if(!size)return(0);
+
+ *Style = *(uint16_t *)(contents + offsetof(U_WMRDIBCREATEPATTERNBRUSH, Style ));
+ *cUsage = *(uint16_t *)(contents + offsetof(U_WMRDIBCREATEPATTERNBRUSH, cUsage ));
+ if(*Style == U_BS_PATTERN){
+ *Bm16 = (contents + offsetof(U_WMRDIBCREATEPATTERNBRUSH, Src));
+ *dib = NULL;
+ /* The WMF spec says that Style == U_BS_PATTERN _SHOULD_ be a bitmap16.
+ However there are instances when it is actually a DIB. U_WMRDIBCREATEPATTERNBRUSH_get
+ tries to detect this by looking for bogus values when the BM16 is interpreted as such,
+ and if it finds them, then it returns a dib instead.
+ */
+ U_BITMAP16 TmpBm16;
+ memcpy(&TmpBm16, *Bm16, U_SIZE_BITMAP16);
+ if(TmpBm16.Width <= 0 || TmpBm16.Height <= 0 || TmpBm16.Planes != 1 || TmpBm16.BitsPixel == 0){
+ *Bm16 = NULL;
+ *dib = (contents + offsetof(U_WMRDIBCREATEPATTERNBRUSH, Src));
+ if(!packed_DIB_safe(*dib, *dib+size))return(0);
+ }
+ }
+ else { /* from DIB */
+ *Bm16 = NULL;
+ *dib = (contents + offsetof(U_WMRDIBCREATEPATTERNBRUSH, Src));
+ if(!packed_DIB_safe(*dib, *dib+size))return(0);
+ }
+ return(size);
+}
+
+/**
+ \brief Get data from a U_WMRSTRETCHDIB record.
+ \return length of the U_WMRSTRETCHDIB record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Dst Destination UL corner in logical units
+ \param cDst Destination W & H in logical units
+ \param Src Source UL corner in logical units
+ \param cSrc Source W & H in logical units
+ \param cUsage DIBColors Enumeration
+ \param dwRop3 RasterOPeration Enumeration
+ \param dib (Optional) device independent bitmap
+*/
+int U_WMRSTRETCHDIB_get(
+ const char *contents,
+ U_POINT16 * Dst,
+ U_POINT16 * cDst,
+ U_POINT16 * Src,
+ U_POINT16 * cSrc,
+ uint16_t *cUsage,
+ uint32_t *dwRop3,
+ const char **dib
+ ){
+ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSTRETCHDIB));
+ if(!size)return(0);
+
+ memcpy(dwRop3, ( contents + offsetof(U_WMRSTRETCHDIB, rop3w)), 4);
+ *cUsage = *(uint16_t *)( contents + offsetof(U_WMRSTRETCHDIB, cUsage ));
+ cSrc->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, hSrc ));
+ cSrc->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, wSrc ));
+ Src->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, ySrc ));
+ Src->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, xSrc ));
+ cDst->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, hDst ));
+ cDst->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, wDst ));
+ Dst->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, yDst ));
+ Dst->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, xDst ));
+ *dib = ( contents + offsetof(U_WMRSTRETCHDIB, dib ));
+ if(!packed_DIB_safe(*dib, *dib+size))return(0);
+ return(size);
+}
+
+//! \cond
+int U_WMR44_get(void){
+ return U_WMRCORENONE_get("U_WMR44");
+}
+
+int U_WMR45_get(void){
+ return U_WMRCORENONE_get("U_WMR45");
+}
+
+int U_WMR46_get(void){
+ return U_WMRCORENONE_get("U_WMR46");
+}
+
+int U_WMR47_get(void){
+ return U_WMRCORENONE_get("U_WMR47");
+}
+//! \endcond
+
+/**
+ \brief Retrieve values from a U_WMREXTFLOODFILL record
+ \return length of the U_WMREXTFLOODFILL record, or NULL on error
+ \param contents record to extract data from
+ \param Mode FloodFill Enumeration.
+ \param Color Color to Fill with.
+ \param coord Location to start fill.
+*/
+int U_WMREXTFLOODFILL_get(
+ const char *contents,
+ uint16_t *Mode,
+ U_COLORREF *Color,
+ U_POINT16 * coord
+ ){
+ return U_WMRCORE_1U16_CRF_2U16_get(
+ contents,
+ Mode,
+ Color,
+ U_P16(coord->y),
+ U_P16(coord->x)
+ );
+}
+
+//! \cond
+int U_WMR49_get(void){
+ return U_WMRCORENONE_get("U_WMR49");
+}
+
+int U_WMR4A_get(void){
+ return U_WMRCORENONE_get("U_WMR4A");
+}
+
+int U_WMR4B_get(void){
+ return U_WMRCORENONE_get("U_WMR4B");
+}
+
+int U_WMR4C_get(void){
+ return U_WMRCORENONE_get("U_WMRRESETDOC");
+}
+
+int U_WMR4D_get(void){
+ return U_WMRCORENONE_get("U_WMRSTARTDOC");
+}
+
+int U_WMR4E_get(void){
+ return U_WMRCORENONE_get("U_WMR4E");
+}
+
+int U_WMR4F_get(void){
+ return U_WMRCORENONE_get("U_WMRSTARTPAGE");
+}
+
+int U_WMR50_get(void){
+ return U_WMRCORENONE_get("U_WMRENDPAGE");
+}
+
+int U_WMR51_get(void){
+ return U_WMRCORENONE_get("U_WMR51");
+}
+
+int U_WMRABORTDOC_get(void){
+ return U_WMRCORENONE_get("U_WMRABORTDOC");
+}
+
+int U_WMR53_get(void){
+ return U_WMRCORENONE_get("U_WMR53");
+}
+
+int U_WMR54_get(void){
+ return U_WMRCORENONE_get("U_WMR54");
+}
+
+int U_WMR55_get(void){
+ return U_WMRCORENONE_get("U_WMR55");
+}
+
+int U_WMR56_get(void){
+ return U_WMRCORENONE_get("U_WMR56");
+}
+
+int U_WMR57_get(void){
+ return U_WMRCORENONE_get("U_WMR57");
+}
+
+int U_WMR58_get(void){
+ return U_WMRCORENONE_get("U_WMR58");
+}
+
+int U_WMR59_get(void){
+ return U_WMRCORENONE_get("U_WMR59");
+}
+
+int U_WMR5A_get(void){
+ return U_WMRCORENONE_get("U_WMR5A");
+}
+
+int U_WMR5B_get(void){
+ return U_WMRCORENONE_get("U_WMR5B");
+}
+
+int U_WMR5C_get(void){
+ return U_WMRCORENONE_get("U_WMR5C");
+}
+
+int U_WMR5D_get(void){
+ return U_WMRCORENONE_get("U_WMR5D");
+}
+
+int U_WMR5E_get(void){
+ return U_WMRCORENONE_get("U_WMRENDDOC");
+}
+
+int U_WMR5F_get(void){
+ return U_WMRCORENONE_get("U_WMR5F");
+}
+
+int U_WMR60_get(void){
+ return U_WMRCORENONE_get("U_WMR60");
+}
+
+int U_WMR61_get(void){
+ return U_WMRCORENONE_get("U_WMR61");
+}
+
+int U_WMR62_get(void){
+ return U_WMRCORENONE_get("U_WMR62");
+}
+
+int U_WMR63_get(void){
+ return U_WMRCORENONE_get("U_WMR63");
+}
+
+int U_WMR64_get(void){
+ return U_WMRCORENONE_get("U_WMR64");
+}
+
+int U_WMR65_get(void){
+ return U_WMRCORENONE_get("U_WMR65");
+}
+
+int U_WMR66_get(void){
+ return U_WMRCORENONE_get("U_WMR66");
+}
+
+int U_WMR67_get(void){
+ return U_WMRCORENONE_get("U_WMR67");
+}
+
+int U_WMR68_get(void){
+ return U_WMRCORENONE_get("U_WMR68");
+}
+
+int U_WMR69_get(void){
+ return U_WMRCORENONE_get("U_WMR69");
+}
+
+int U_WMR6A_get(void){
+ return U_WMRCORENONE_get("U_WMR6A");
+}
+
+int U_WMR6B_get(void){
+ return U_WMRCORENONE_get("U_WMR6B");
+}
+
+int U_WMR6C_get(void){
+ return U_WMRCORENONE_get("U_WMR6C");
+}
+
+int U_WMR6D_get(void){
+ return U_WMRCORENONE_get("U_WMR6D");
+}
+
+int U_WMR6E_get(void){
+ return U_WMRCORENONE_get("U_WMR6E");
+}
+
+int U_WMR6F_get(void){
+ return U_WMRCORENONE_get("U_WMR6F");
+}
+
+int U_WMR70_get(void){
+ return U_WMRCORENONE_get("U_WMR70");
+}
+
+int U_WMR71_get(void){
+ return U_WMRCORENONE_get("U_WMR71");
+}
+
+int U_WMR72_get(void){
+ return U_WMRCORENONE_get("U_WMR72");
+}
+
+int U_WMR73_get(void){
+ return U_WMRCORENONE_get("U_WMR73");
+}
+
+int U_WMR74_get(void){
+ return U_WMRCORENONE_get("U_WMR74");
+}
+
+int U_WMR75_get(void){
+ return U_WMRCORENONE_get("U_WMR75");
+}
+
+int U_WMR76_get(void){
+ return U_WMRCORENONE_get("U_WMR76");
+}
+
+int U_WMR77_get(void){
+ return U_WMRCORENONE_get("U_WMR77");
+}
+
+int U_WMR78_get(void){
+ return U_WMRCORENONE_get("U_WMR78");
+}
+
+int U_WMR79_get(void){
+ return U_WMRCORENONE_get("U_WMR79");
+}
+
+int U_WMR7A_get(void){
+ return U_WMRCORENONE_get("U_WMR7A");
+}
+
+int U_WMR7B_get(void){
+ return U_WMRCORENONE_get("U_WMR7B");
+}
+
+int U_WMR7C_get(void){
+ return U_WMRCORENONE_get("U_WMR7C");
+}
+
+int U_WMR7D_get(void){
+ return U_WMRCORENONE_get("U_WMR7D");
+}
+
+int U_WMR7E_get(void){
+ return U_WMRCORENONE_get("U_WMR7E");
+}
+
+int U_WMR7F_get(void){
+ return U_WMRCORENONE_get("U_WMR7F");
+}
+
+int U_WMR80_get(void){
+ return U_WMRCORENONE_get("U_WMR80");
+}
+
+int U_WMR81_get(void){
+ return U_WMRCORENONE_get("U_WMR81");
+}
+
+int U_WMR82_get(void){
+ return U_WMRCORENONE_get("U_WMR82");
+}
+
+int U_WMR83_get(void){
+ return U_WMRCORENONE_get("U_WMR83");
+}
+
+int U_WMR84_get(void){
+ return U_WMRCORENONE_get("U_WMR84");
+}
+
+int U_WMR85_get(void){
+ return U_WMRCORENONE_get("U_WMR85");
+}
+
+int U_WMR86_get(void){
+ return U_WMRCORENONE_get("U_WMR86");
+}
+
+int U_WMR87_get(void){
+ return U_WMRCORENONE_get("U_WMR87");
+}
+
+int U_WMR88_get(void){
+ return U_WMRCORENONE_get("U_WMR88");
+}
+
+int U_WMR89_get(void){
+ return U_WMRCORENONE_get("U_WMR89");
+}
+
+int U_WMR8A_get(void){
+ return U_WMRCORENONE_get("U_WMR8A");
+}
+
+int U_WMR8B_get(void){
+ return U_WMRCORENONE_get("U_WMR8B");
+}
+
+int U_WMR8C_get(void){
+ return U_WMRCORENONE_get("U_WMR8C");
+}
+
+int U_WMR8D_get(void){
+ return U_WMRCORENONE_get("U_WMR8D");
+}
+
+int U_WMR8E_get(void){
+ return U_WMRCORENONE_get("U_WMR8E");
+}
+
+int U_WMR8F_get(void){
+ return U_WMRCORENONE_get("U_WMR8F");
+}
+
+int U_WMR90_get(void){
+ return U_WMRCORENONE_get("U_WMR90");
+}
+
+int U_WMR91_get(void){
+ return U_WMRCORENONE_get("U_WMR91");
+}
+
+int U_WMR92_get(void){
+ return U_WMRCORENONE_get("U_WMR92");
+}
+
+int U_WMR93_get(void){
+ return U_WMRCORENONE_get("U_WMR93");
+}
+
+int U_WMR94_get(void){
+ return U_WMRCORENONE_get("U_WMR94");
+}
+
+int U_WMR95_get(void){
+ return U_WMRCORENONE_get("U_WMR95");
+}
+
+int U_WMR96_get(void){
+ return U_WMRCORENONE_get("U_WMR96");
+}
+
+int U_WMR97_get(void){
+ return U_WMRCORENONE_get("U_WMR97");
+}
+
+int U_WMR98_get(void){
+ return U_WMRCORENONE_get("U_WMR98");
+}
+
+int U_WMR99_get(void){
+ return U_WMRCORENONE_get("U_WMR99");
+}
+
+int U_WMR9A_get(void){
+ return U_WMRCORENONE_get("U_WMR9A");
+}
+
+int U_WMR9B_get(void){
+ return U_WMRCORENONE_get("U_WMR9B");
+}
+
+int U_WMR9C_get(void){
+ return U_WMRCORENONE_get("U_WMR9C");
+}
+
+int U_WMR9D_get(void){
+ return U_WMRCORENONE_get("U_WMR9D");
+}
+
+int U_WMR9E_get(void){
+ return U_WMRCORENONE_get("U_WMR9E");
+}
+
+int U_WMR9F_get(void){
+ return U_WMRCORENONE_get("U_WMR9F");
+}
+
+int U_WMRA0_get(void){
+ return U_WMRCORENONE_get("U_WMRA0");
+}
+
+int U_WMRA1_get(void){
+ return U_WMRCORENONE_get("U_WMRA1");
+}
+
+int U_WMRA2_get(void){
+ return U_WMRCORENONE_get("U_WMRA2");
+}
+
+int U_WMRA3_get(void){
+ return U_WMRCORENONE_get("U_WMRA3");
+}
+
+int U_WMRA4_get(void){
+ return U_WMRCORENONE_get("U_WMRA4");
+}
+
+int U_WMRA5_get(void){
+ return U_WMRCORENONE_get("U_WMRA5");
+}
+
+int U_WMRA6_get(void){
+ return U_WMRCORENONE_get("U_WMRA6");
+}
+
+int U_WMRA7_get(void){
+ return U_WMRCORENONE_get("U_WMRA7");
+}
+
+int U_WMRA8_get(void){
+ return U_WMRCORENONE_get("U_WMRA8");
+}
+
+int U_WMRA9_get(void){
+ return U_WMRCORENONE_get("U_WMRA9");
+}
+
+int U_WMRAA_get(void){
+ return U_WMRCORENONE_get("U_WMRAA");
+}
+
+int U_WMRAB_get(void){
+ return U_WMRCORENONE_get("U_WMRAB");
+}
+
+int U_WMRAC_get(void){
+ return U_WMRCORENONE_get("U_WMRAC");
+}
+
+int U_WMRAD_get(void){
+ return U_WMRCORENONE_get("U_WMRAD");
+}
+
+int U_WMRAE_get(void){
+ return U_WMRCORENONE_get("U_WMRAE");
+}
+
+int U_WMRAF_get(void){
+ return U_WMRCORENONE_get("U_WMRAF");
+}
+
+int U_WMRB0_get(void){
+ return U_WMRCORENONE_get("U_WMRB0");
+}
+
+int U_WMRB1_get(void){
+ return U_WMRCORENONE_get("U_WMRB1");
+}
+
+int U_WMRB2_get(void){
+ return U_WMRCORENONE_get("U_WMRB2");
+}
+
+int U_WMRB3_get(void){
+ return U_WMRCORENONE_get("U_WMRB3");
+}
+
+int U_WMRB4_get(void){
+ return U_WMRCORENONE_get("U_WMRB4");
+}
+
+int U_WMRB5_get(void){
+ return U_WMRCORENONE_get("U_WMRB5");
+}
+
+int U_WMRB6_get(void){
+ return U_WMRCORENONE_get("U_WMRB6");
+}
+
+int U_WMRB7_get(void){
+ return U_WMRCORENONE_get("U_WMRB7");
+}
+
+int U_WMRB8_get(void){
+ return U_WMRCORENONE_get("U_WMRB8");
+}
+
+int U_WMRB9_get(void){
+ return U_WMRCORENONE_get("U_WMRB9");
+}
+
+int U_WMRBA_get(void){
+ return U_WMRCORENONE_get("U_WMRBA");
+}
+
+int U_WMRBB_get(void){
+ return U_WMRCORENONE_get("U_WMRBB");
+}
+
+int U_WMRBC_get(void){
+ return U_WMRCORENONE_get("U_WMRBC");
+}
+
+int U_WMRBD_get(void){
+ return U_WMRCORENONE_get("U_WMRBD");
+}
+
+int U_WMRBE_get(void){
+ return U_WMRCORENONE_get("U_WMRBE");
+}
+
+int U_WMRBF_get(void){
+ return U_WMRCORENONE_get("U_WMRBF");
+}
+
+int U_WMRC0_get(void){
+ return U_WMRCORENONE_get("U_WMRC0");
+}
+
+int U_WMRC1_get(void){
+ return U_WMRCORENONE_get("U_WMRC1");
+}
+
+int U_WMRC2_get(void){
+ return U_WMRCORENONE_get("U_WMRC2");
+}
+
+int U_WMRC3_get(void){
+ return U_WMRCORENONE_get("U_WMRC3");
+}
+
+int U_WMRC4_get(void){
+ return U_WMRCORENONE_get("U_WMRC4");
+}
+
+int U_WMRC5_get(void){
+ return U_WMRCORENONE_get("U_WMRC5");
+}
+
+int U_WMRC6_get(void){
+ return U_WMRCORENONE_get("U_WMRC6");
+}
+
+int U_WMRC7_get(void){
+ return U_WMRCORENONE_get("U_WMRC7");
+}
+
+int U_WMRC8_get(void){
+ return U_WMRCORENONE_get("U_WMRC8");
+}
+
+int U_WMRC9_get(void){
+ return U_WMRCORENONE_get("U_WMRC9");
+}
+
+int U_WMRCA_get(void){
+ return U_WMRCORENONE_get("U_WMRCA");
+}
+
+int U_WMRCB_get(void){
+ return U_WMRCORENONE_get("U_WMRCB");
+}
+
+int U_WMRCC_get(void){
+ return U_WMRCORENONE_get("U_WMRCC");
+}
+
+int U_WMRCD_get(void){
+ return U_WMRCORENONE_get("U_WMRCD");
+}
+
+int U_WMRCE_get(void){
+ return U_WMRCORENONE_get("U_WMRCE");
+}
+
+int U_WMRCF_get(void){
+ return U_WMRCORENONE_get("U_WMRCF");
+}
+
+int U_WMRD0_get(void){
+ return U_WMRCORENONE_get("U_WMRD0");
+}
+
+int U_WMRD1_get(void){
+ return U_WMRCORENONE_get("U_WMRD1");
+}
+
+int U_WMRD2_get(void){
+ return U_WMRCORENONE_get("U_WMRD2");
+}
+
+int U_WMRD3_get(void){
+ return U_WMRCORENONE_get("U_WMRD3");
+}
+
+int U_WMRD4_get(void){
+ return U_WMRCORENONE_get("U_WMRD4");
+}
+
+int U_WMRD5_get(void){
+ return U_WMRCORENONE_get("U_WMRD5");
+}
+
+int U_WMRD6_get(void){
+ return U_WMRCORENONE_get("U_WMRD6");
+}
+
+int U_WMRD7_get(void){
+ return U_WMRCORENONE_get("U_WMRD7");
+}
+
+int U_WMRD8_get(void){
+ return U_WMRCORENONE_get("U_WMRD8");
+}
+
+int U_WMRD9_get(void){
+ return U_WMRCORENONE_get("U_WMRD9");
+}
+
+int U_WMRDA_get(void){
+ return U_WMRCORENONE_get("U_WMRDA");
+}
+
+int U_WMRDB_get(void){
+ return U_WMRCORENONE_get("U_WMRDB");
+}
+
+int U_WMRDC_get(void){
+ return U_WMRCORENONE_get("U_WMRDC");
+}
+
+int U_WMRDD_get(void){
+ return U_WMRCORENONE_get("U_WMRDD");
+}
+
+int U_WMRDE_get(void){
+ return U_WMRCORENONE_get("U_WMRDE");
+}
+
+int U_WMRDF_get(void){
+ return U_WMRCORENONE_get("U_WMRDF");
+}
+
+int U_WMRE0_get(void){
+ return U_WMRCORENONE_get("U_WMRE0");
+}
+
+int U_WMRE1_get(void){
+ return U_WMRCORENONE_get("U_WMRE1");
+}
+
+int U_WMRE2_get(void){
+ return U_WMRCORENONE_get("U_WMRE2");
+}
+
+int U_WMRE3_get(void){
+ return U_WMRCORENONE_get("U_WMRE3");
+}
+
+int U_WMRE4_get(void){
+ return U_WMRCORENONE_get("U_WMRE4");
+}
+
+int U_WMRE5_get(void){
+ return U_WMRCORENONE_get("U_WMRE5");
+}
+
+int U_WMRE6_get(void){
+ return U_WMRCORENONE_get("U_WMRE6");
+}
+
+int U_WMRE7_get(void){
+ return U_WMRCORENONE_get("U_WMRE7");
+}
+
+int U_WMRE8_get(void){
+ return U_WMRCORENONE_get("U_WMRE8");
+}
+
+int U_WMRE9_get(void){
+ return U_WMRCORENONE_get("U_WMRE9");
+}
+
+int U_WMREA_get(void){
+ return U_WMRCORENONE_get("U_WMREA");
+}
+
+int U_WMREB_get(void){
+ return U_WMRCORENONE_get("U_WMREB");
+}
+
+int U_WMREC_get(void){
+ return U_WMRCORENONE_get("U_WMREC");
+}
+
+int U_WMRED_get(void){
+ return U_WMRCORENONE_get("U_WMRED");
+}
+
+int U_WMREE_get(void){
+ return U_WMRCORENONE_get("U_WMREE");
+}
+
+int U_WMREF_get(void){
+ return U_WMRCORENONE_get("U_WMREF");
+}
+//! \endcond
+
+/**
+ \brief Get data from a U_WMRDELETEOBJECT record.
+ \return length of the U_WMRDELETEOBJECT record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Object Index of object which is made active.
+*/
+int U_WMRDELETEOBJECT_get(
+ const char *contents,
+ uint16_t *Object
+ ){
+ return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRDELETEOBJECT), Object);
+}
+
+//! \cond
+int U_WMRF1_get(void){
+ return U_WMRCORENONE_get("U_WMRF1");
+}
+
+int U_WMRF2_get(void){
+ return U_WMRCORENONE_get("U_WMRF2");
+}
+
+int U_WMRF3_get(void){
+ return U_WMRCORENONE_get("U_WMRF3");
+}
+
+int U_WMRF4_get(void){
+ return U_WMRCORENONE_get("U_WMRF4");
+}
+
+int U_WMRF5_get(void){
+ return U_WMRCORENONE_get("U_WMRF5");
+}
+
+int U_WMRF6_get(void){
+ return U_WMRCORENONE_get("U_WMRF6");
+}
+//! \endcond
+
+/**
+ \brief Retrieve values from a U_WMRCREATEPALETTE record
+ \return length of the U_WMRCREATEPALETTE record, or NULL on error
+ \param contents record to extract data from
+ \param Palette Create a Palette object.
+ \param PalEntries Array of Palette Entries
+*/
+int U_WMRCREATEPALETTE_get(
+ const char *contents,
+ U_PALETTE *Palette,
+ const char **PalEntries
+ ){
+ return U_WMRCORE_PALETTE_get(contents, (U_SIZE_WMRCREATEPALETTE), Palette, PalEntries);
+}
+
+//! \cond
+int U_WMRF8_get(void){
+ return U_WMRCORENONE_get("U_WMRF8");
+}
+//! \endcond
+
+/**
+ \brief Get data from a U_WMRCREATEPATTERNBRUSH record.
+ Warning - application support for U_WMRCREATEPATTERNBRUSH is spotty, better to use U_WMRDIBCREATEPATTERNBRUSH.
+ \return length of the U_WMRCREATEPATTERNBRUSH record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Bm16 truncated Bitmap16 structure from record, only tge first 14 bytes hold data.
+ \param pasize Number of bytes in Pattern
+ \param Pattern byte array pattern, described by Bm16, for brush
+*/
+int U_WMRCREATEPATTERNBRUSH_get(
+ const char *contents,
+ U_BITMAP16 *Bm16,
+ int *pasize,
+ const char **Pattern
+ ){
+ int off = U_SIZE_METARECORD;
+ /* size in next one is
+ 6 (core header) + 14 (truncated bitmap16) + 18 bytes reserved + 2 bytes (at least) for data */
+ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_METARECORD + 14 + 18 + 2));
+ if(!size)return(0);
+ memset(Bm16, 0, U_SIZE_BITMAP16);
+ /* BM16 is truncated in this record type to 14 bytes, last 4 bytes must be ignored, so they are not even copied */
+ memcpy(Bm16, contents + off, 10);
+ *pasize = (((Bm16->Width * Bm16->BitsPixel + 15) >> 4) << 1) * Bm16->Height;
+ off += 32; /* skip [14 bytes of truncated bitmap16 object and 18 bytes of reserved */
+ *Pattern = (contents + off);
+ return(size);
+}
+
+/**
+ \brief Get data from a U_WMRCREATEPENINDIRECT record.
+ \return length of the U_WMRCREATEPENINDIRECT record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param pen pointer to a U_PEN object to fill.
+*/
+int U_WMRCREATEPENINDIRECT_get(
+ const char *contents,
+ U_PEN *pen
+ ){
+ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRCREATEPENINDIRECT));
+ if(!size)return(0);
+ memcpy(pen, contents + offsetof(U_WMRCREATEPENINDIRECT, pen), U_SIZE_PEN);
+ return(size);
+}
+
+/**
+ \brief Get data from a U_WMRCREATEFONTINDIRECT record.
+ \return length of the U_WMRCREATEFONTINDIRECT record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param font pointer to array of U_FONT structure in memory. Pointer may not be aligned properly for structure.
+*/
+int U_WMRCREATEFONTINDIRECT_get(
+ const char *contents,
+ const char **font
+ ){
+ int size = U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRCREATEFONTINDIRECT), NULL, NULL, font);
+ if(size){
+ if(IS_MEM_UNSAFE(*font, U_SIZE_FONT_CORE, contents+size))return(0);
+ if(contents + size - *font > U_SIZE_FONT_CORE + 32)return(0); // font name must fit in a 32 bit field
+ }
+ return size;
+}
+
+/**
+ \brief Get data from a U_WMRCREATEBRUSHINDIRECT record.
+ \return length of the U_WMRCREATEBRUSHINDIRECT record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param brush pointer to U_WLOGBRUSH structure in memory. Pointer may not be aligned properly for structure.
+*/
+int U_WMRCREATEBRUSHINDIRECT_get(
+ const char *contents,
+ const char **brush
+ ){
+ // U_SIZE_WMRCREATEBRUSHINDIRECT is everything, no variable part, so the test below is sufficient
+ return U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRCREATEBRUSHINDIRECT), NULL, NULL, brush);
+}
+
+/** in GDI and Wine, not in WMF manual.
+*/
+int U_WMRCREATEBITMAPINDIRECT_get(void){
+ return U_WMRCORENONE_get("U_WMRCREATEBITMAPINDIRECT");
+}
+
+/** in GDI and Wine, not in WMF manual.
+*/
+int U_WMRCREATEBITMAP_get(void){
+ return U_WMRCORENONE_get("U_WMRCREATEBITMAP");
+}
+
+/**
+ \brief Get data from a U_WMRCREATEREGION record.
+ \return length of the U_WMRCREATEREGION record in bytes, or 0 on error
+ \param contents record to extract data from
+ \param Region pointer to U_REGION structure in memory. Pointer may not be aligned properly for structure.
+
+ Caller must check at the returned Region does not extend outside of the record!
+*/
+int U_WMRCREATEREGION_get(
+ const char *contents,
+ const char **Region
+ ){
+ return U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRCREATEREGION), NULL, NULL, Region);
+}
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/3rdparty/libuemf/uwmf.h b/src/3rdparty/libuemf/uwmf.h
new file mode 100644
index 0000000..529232c
--- /dev/null
+++ b/src/3rdparty/libuemf/uwmf.h
@@ -0,0 +1,2677 @@
+/**
+ @file uwmf.h
+
+ @brief Structures, definitions, and function prototypes for WMF files.
+
+ WMF file Record structure information has been derived from Mingw and Wine header files, and from
+ Microsoft's WMF Information pdf, release date July 5,2012, link from here:
+
+ http://msdn2.microsoft.com/en-us/library/cc250370.aspx
+
+ If the direct link fails the document may be found
+ by searching for: "[MS-WMF]: Windows Metafile Format"
+
+ *********************************** IMPORTANT!!! **********************************************
+ WMF is a 16 bit file type that has some 32 bit integers embedded in it. In
+ a few cases these 32 bit fields are not aligned in the structures defined in uwmf.h, but
+ in most cases they are. So when creating the individual WMF records the functions in
+ uwmf.c can usually use a regular assignment operation for the 32 bit fields. However, once the
+ records are part of a WMF file in memory there is no guaranty that any 32 bit type will be correctly
+ aligned. Similarly, many WMF structures contain embedded other structures which would "naturally"
+ be passed by pointer, but since their alignment may not be what malloc() would have created for that
+ type, the outcome of that operation is not defined by the C standard. (Per Eric Sosman, section
+ 6.3.2.3p7 of the standard.)
+
+ For this reason, the _print, _swap and any read operations must pass structures with unknown alignment
+ as a (char *), and pull out the data using memcpy() or some equivalent
+ that will not segfault when it tries to read a 32 bit value that is not aligned
+ on a 4 byte boundary. Failure to do so will result in nonportable code. You have been warned!
+
+ Problem areas:
+ The Size16_4 field of all WMF records may NOT be assumed to 4 byte aligned.
+ DIB's U_BITMAPINFOHEADER 32 bit fields may not be aligned.
+ *********************************** IMPORTANT!!! **********************************************
+
+*/
+
+/*
+File: uwmf.h
+Version: 0.0.13
+Date: 26-JAN-2016
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2016 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifndef _UWMF_
+#define _UWMF_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include "uemf.h" /* many structures/defs in common, pull in the EMF ones as a basis */
+#include "uemf_utf.h"
+#include "uwmf_endian.h"
+
+
+/** HighWater Enumeration not in WMF manual
+ @{
+*/
+#define U_HIGHWATER_READ 0x00000000 //!< nondestructive read of highwater value
+#define U_HIGHWATER_CLEAR 0xFFFFFFFF //!< destructive read, value is reset to 0
+/** @} */
+
+
+
+
+// ***********************************************************************************
+// Value Enumerations and other predefined constants, alphabetical order by group
+
+/* RecordType Enumeration WMF manual 2.1.1.1 */
+/** WMF manual 2.1.1.1
+ \brief WMR Record types
+*/
+enum U_WMR_TYPES{
+ U_WMR_EOF, //!< 0x0000 U_WMREOF record
+ U_WMR_SETBKCOLOR, //!< 0x0201 U_WMRSETBKCOLOR record
+ U_WMR_SETBKMODE, //!< 0x0102 U_WMRSETBKMODE record
+ U_WMR_SETMAPMODE, //!< 0x0103 U_WMRSETMAPMODE record
+ U_WMR_SETROP2, //!< 0x0104 U_WMRSETROP2 record
+ U_WMR_SETRELABS, //!< 0x0105 U_WMRSETRELABS record
+ U_WMR_SETPOLYFILLMODE, //!< 0x0106 U_WMRSETPOLYFILLMODE record
+ U_WMR_SETSTRETCHBLTMODE, //!< 0x0107 U_WMRSETSTRETCHBLTMODE record
+ U_WMR_SETTEXTCHAREXTRA, //!< 0x0108 U_WMRSETTEXTCHAREXTRA record
+ U_WMR_SETTEXTCOLOR, //!< 0x0209 U_WMRSETTEXTCOLOR record
+ U_WMR_SETTEXTJUSTIFICATION, //!< 0x020A U_WMRSETTEXTJUSTIFICATION record
+ U_WMR_SETWINDOWORG, //!< 0x020B U_WMRSETWINDOWORG record
+ U_WMR_SETWINDOWEXT, //!< 0x020C U_WMRSETWINDOWEXT record
+ U_WMR_SETVIEWPORTORG, //!< 0x020D U_WMRSETVIEWPORTORG record
+ U_WMR_SETVIEWPORTEXT, //!< 0x020E U_WMRSETVIEWPORTEXT record
+ U_WMR_OFFSETWINDOWORG, //!< 0x020F U_WMROFFSETWINDOWORG record
+ U_WMR_SCALEWINDOWEXT, //!< 0x0410 U_WMRSCALEWINDOWEXT record
+ U_WMR_OFFSETVIEWPORTORG, //!< 0x0211 U_WMROFFSETVIEWPORTORG record
+ U_WMR_SCALEVIEWPORTEXT, //!< 0x0412 U_WMRSCALEVIEWPORTEXT record
+ U_WMR_LINETO, //!< 0x0213 U_WMRLINETO record
+ U_WMR_MOVETO, //!< 0x0214 U_WMRMOVETO record
+ U_WMR_EXCLUDECLIPRECT, //!< 0x0415 U_WMREXCLUDECLIPRECT record
+ U_WMR_INTERSECTCLIPRECT, //!< 0x0416 U_WMRINTERSECTCLIPRECT record
+ U_WMR_ARC, //!< 0x0817 U_WMRARC record
+ U_WMR_ELLIPSE, //!< 0x0418 U_WMRELLIPSE record
+ U_WMR_FLOODFILL, //!< 0x0419 U_WMRFLOODFILL record
+ U_WMR_PIE, //!< 0x081A U_WMRPIE record
+ U_WMR_RECTANGLE, //!< 0x041B U_WMRRECTANGLE record
+ U_WMR_ROUNDRECT, //!< 0x061C U_WMRROUNDRECT record
+ U_WMR_PATBLT, //!< 0x061D U_WMRPATBLT record
+ U_WMR_SAVEDC, //!< 0x001E U_WMRSAVEDC record
+ U_WMR_SETPIXEL, //!< 0x041F U_WMRSETPIXEL record
+ U_WMR_OFFSETCLIPRGN, //!< 0x0220 U_WMROFFSETCLIPRGN record
+ U_WMR_TEXTOUT, //!< 0x0521 U_WMRTEXTOUT record
+ U_WMR_BITBLT, //!< 0x0922 U_WMRBITBLT record
+ U_WMR_STRETCHBLT, //!< 0x0B23 U_WMRSTRETCHBLT record
+ U_WMR_POLYGON, //!< 0x0324 U_WMRPOLYGON record
+ U_WMR_POLYLINE, //!< 0x0325 U_WMRPOLYLINE record
+ U_WMR_ESCAPE, //!< 0x0626 U_WMRESCAPE record
+ U_WMR_RESTOREDC, //!< 0x0127 U_WMRRESTOREDC record
+ U_WMR_FILLREGION, //!< 0x0228 U_WMRFILLREGION record
+ U_WMR_FRAMEREGION, //!< 0x0429 U_WMRFRAMEREGION record
+ U_WMR_INVERTREGION, //!< 0x012A U_WMRINVERTREGION record
+ U_WMR_PAINTREGION, //!< 0x012B U_WMRPAINTREGION record
+ U_WMR_SELECTCLIPREGION, //!< 0x012C U_WMRSELECTCLIPREGION record
+ U_WMR_SELECTOBJECT, //!< 0x012D U_WMRSELECTOBJECT record
+ U_WMR_SETTEXTALIGN, //!< 0x012E U_WMRSETTEXTALIGN record
+ U_WMR_DRAWTEXT, //!< 0x062F U_WMRDRAWTEXT record
+ U_WMR_CHORD, //!< 0x0830 U_WMRCHORD record
+ U_WMR_SETMAPPERFLAGS, //!< 0x0231 U_WMRSETMAPPERFLAGS record
+ U_WMR_EXTTEXTOUT, //!< 0x0A32 U_WMREXTTEXTOUT record
+ U_WMR_SETDIBTODEV, //!< 0x0D33 U_WMRSETDIBTODEV record
+ U_WMR_SELECTPALETTE, //!< 0x0234 U_WMRSELECTPALETTE record
+ U_WMR_REALIZEPALETTE, //!< 0x0035 U_WMRREALIZEPALETTE record
+ U_WMR_ANIMATEPALETTE, //!< 0x0436 U_WMRANIMATEPALETTE record
+ U_WMR_SETPALENTRIES, //!< 0x0037 U_WMRSETPALENTRIES record
+ U_WMR_POLYPOLYGON, //!< 0x0538 U_WMRPOLYPOLYGON record
+ U_WMR_RESIZEPALETTE, //!< 0x0139 U_WMRRESIZEPALETTE record
+ U_WMR_3A, //!< 0x003A U_WMR3A record
+ U_WMR_3B, //!< 0x003B U_WMR3B record
+ U_WMR_3C, //!< 0x003C U_WMR3C record
+ U_WMR_3D, //!< 0x003D U_WMR3D record
+ U_WMR_3E, //!< 0x003E U_WMR3E record
+ U_WMR_3F, //!< 0x003F U_WMR3F record
+ U_WMR_DIBBITBLT, //!< 0x0940 U_WMRDIBBITBLT record
+ U_WMR_DIBSTRETCHBLT, //!< 0x0B41 U_WMRDIBSTRETCHBLT record
+ U_WMR_DIBCREATEPATTERNBRUSH, //!< 0x0142 U_WMRDIBCREATEPATTERNBRUSH record
+ U_WMR_STRETCHDIB, //!< 0x0F43 U_WMRSTRETCHDIB record
+ U_WMR_44, //!< 0x0044 U_WMR44 record
+ U_WMR_45, //!< 0x0045 U_WMR45 record
+ U_WMR_46, //!< 0x0046 U_WMR46 record
+ U_WMR_47, //!< 0x0047 U_WMR47 record
+ U_WMR_EXTFLOODFILL, //!< 0x0548 U_WMREXTFLOODFILL record
+ U_WMR_49, //!< 0x0049 U_WMR49 record
+ U_WMR_4A, //!< 0x004A U_WMR4A record
+ U_WMR_4B, //!< 0x004B U_WMR4B record
+ U_WMR_4C, //!< 0x014C U_WMR4C record
+ U_WMR_4D, //!< 0x014D U_WMR4D record
+ U_WMR_4E, //!< 0x004E U_WMR4E record
+ U_WMR_4F, //!< 0x004F U_WMR4F record
+ U_WMR_50, //!< 0x0050 U_WMR50 record
+ U_WMR_51, //!< 0x0051 U_WMR51 record
+ U_WMR_52, //!< 0x0052 U_WMR52 record
+ U_WMR_53, //!< 0x0053 U_WMR53 record
+ U_WMR_54, //!< 0x0054 U_WMR54 record
+ U_WMR_55, //!< 0x0055 U_WMR55 record
+ U_WMR_56, //!< 0x0056 U_WMR56 record
+ U_WMR_57, //!< 0x0057 U_WMR57 record
+ U_WMR_58, //!< 0x0058 U_WMR58 record
+ U_WMR_59, //!< 0x0059 U_WMR59 record
+ U_WMR_5A, //!< 0x005A U_WMR5A record
+ U_WMR_5B, //!< 0x005B U_WMR5B record
+ U_WMR_5C, //!< 0x005C U_WMR5C record
+ U_WMR_5D, //!< 0x005D U_WMR5D record
+ U_WMR_5E, //!< 0x005E U_WMR5E record
+ U_WMR_5F, //!< 0x005F U_WMR5F record
+ U_WMR_60, //!< 0x0060 U_WMR60 record
+ U_WMR_61, //!< 0x0061 U_WMR61 record
+ U_WMR_62, //!< 0x0062 U_WMR62 record
+ U_WMR_63, //!< 0x0063 U_WMR63 record
+ U_WMR_64, //!< 0x0064 U_WMR64 record
+ U_WMR_65, //!< 0x0065 U_WMR65 record
+ U_WMR_66, //!< 0x0066 U_WMR66 record
+ U_WMR_67, //!< 0x0067 U_WMR67 record
+ U_WMR_68, //!< 0x0068 U_WMR68 record
+ U_WMR_69, //!< 0x0069 U_WMR69 record
+ U_WMR_6A, //!< 0x006A U_WMR6A record
+ U_WMR_6B, //!< 0x006B U_WMR6B record
+ U_WMR_6C, //!< 0x006C U_WMR6C record
+ U_WMR_6D, //!< 0x006D U_WMR6D record
+ U_WMR_6E, //!< 0x006E U_WMR6E record
+ U_WMR_6F, //!< 0x006F U_WMR6F record
+ U_WMR_70, //!< 0x0070 U_WMR70 record
+ U_WMR_71, //!< 0x0071 U_WMR71 record
+ U_WMR_72, //!< 0x0072 U_WMR72 record
+ U_WMR_73, //!< 0x0073 U_WMR73 record
+ U_WMR_74, //!< 0x0074 U_WMR74 record
+ U_WMR_75, //!< 0x0075 U_WMR75 record
+ U_WMR_76, //!< 0x0076 U_WMR76 record
+ U_WMR_77, //!< 0x0077 U_WMR77 record
+ U_WMR_78, //!< 0x0078 U_WMR78 record
+ U_WMR_79, //!< 0x0079 U_WMR79 record
+ U_WMR_7A, //!< 0x007A U_WMR7A record
+ U_WMR_7B, //!< 0x007B U_WMR7B record
+ U_WMR_7C, //!< 0x007C U_WMR7C record
+ U_WMR_7D, //!< 0x007D U_WMR7D record
+ U_WMR_7E, //!< 0x007E U_WMR7E record
+ U_WMR_7F, //!< 0x007F U_WMR7F record
+ U_WMR_80, //!< 0x0080 U_WMR80 record
+ U_WMR_81, //!< 0x0081 U_WMR81 record
+ U_WMR_82, //!< 0x0082 U_WMR82 record
+ U_WMR_83, //!< 0x0083 U_WMR83 record
+ U_WMR_84, //!< 0x0084 U_WMR84 record
+ U_WMR_85, //!< 0x0085 U_WMR85 record
+ U_WMR_86, //!< 0x0086 U_WMR86 record
+ U_WMR_87, //!< 0x0087 U_WMR87 record
+ U_WMR_88, //!< 0x0088 U_WMR88 record
+ U_WMR_89, //!< 0x0089 U_WMR89 record
+ U_WMR_8A, //!< 0x008A U_WMR8A record
+ U_WMR_8B, //!< 0x008B U_WMR8B record
+ U_WMR_8C, //!< 0x008C U_WMR8C record
+ U_WMR_8D, //!< 0x008D U_WMR8D record
+ U_WMR_8E, //!< 0x008E U_WMR8E record
+ U_WMR_8F, //!< 0x008F U_WMR8F record
+ U_WMR_90, //!< 0x0090 U_WMR90 record
+ U_WMR_91, //!< 0x0091 U_WMR91 record
+ U_WMR_92, //!< 0x0092 U_WMR92 record
+ U_WMR_93, //!< 0x0093 U_WMR93 record
+ U_WMR_94, //!< 0x0094 U_WMR94 record
+ U_WMR_95, //!< 0x0095 U_WMR95 record
+ U_WMR_96, //!< 0x0096 U_WMR96 record
+ U_WMR_97, //!< 0x0097 U_WMR97 record
+ U_WMR_98, //!< 0x0098 U_WMR98 record
+ U_WMR_99, //!< 0x0099 U_WMR99 record
+ U_WMR_9A, //!< 0x009A U_WMR9A record
+ U_WMR_9B, //!< 0x009B U_WMR9B record
+ U_WMR_9C, //!< 0x009C U_WMR9C record
+ U_WMR_9D, //!< 0x009D U_WMR9D record
+ U_WMR_9E, //!< 0x009E U_WMR9E record
+ U_WMR_9F, //!< 0x009F U_WMR9F record
+ U_WMR_A0, //!< 0x00A0 U_WMRA0 record
+ U_WMR_A1, //!< 0x00A1 U_WMRA1 record
+ U_WMR_A2, //!< 0x00A2 U_WMRA2 record
+ U_WMR_A3, //!< 0x00A3 U_WMRA3 record
+ U_WMR_A4, //!< 0x00A4 U_WMRA4 record
+ U_WMR_A5, //!< 0x00A5 U_WMRA5 record
+ U_WMR_A6, //!< 0x00A6 U_WMRA6 record
+ U_WMR_A7, //!< 0x00A7 U_WMRA7 record
+ U_WMR_A8, //!< 0x00A8 U_WMRA8 record
+ U_WMR_A9, //!< 0x00A9 U_WMRA9 record
+ U_WMR_AA, //!< 0x00AA U_WMRAA record
+ U_WMR_AB, //!< 0x00AB U_WMRAB record
+ U_WMR_AC, //!< 0x00AC U_WMRAC record
+ U_WMR_AD, //!< 0x00AD U_WMRAD record
+ U_WMR_AE, //!< 0x00AE U_WMRAE record
+ U_WMR_AF, //!< 0x00AF U_WMRAF record
+ U_WMR_B0, //!< 0x00B0 U_WMRB0 record
+ U_WMR_B1, //!< 0x00B1 U_WMRB1 record
+ U_WMR_B2, //!< 0x00B2 U_WMRB2 record
+ U_WMR_B3, //!< 0x00B3 U_WMRB3 record
+ U_WMR_B4, //!< 0x00B4 U_WMRB4 record
+ U_WMR_B5, //!< 0x00B5 U_WMRB5 record
+ U_WMR_B6, //!< 0x00B6 U_WMRB6 record
+ U_WMR_B7, //!< 0x00B7 U_WMRB7 record
+ U_WMR_B8, //!< 0x00B8 U_WMRB8 record
+ U_WMR_B9, //!< 0x00B9 U_WMRB9 record
+ U_WMR_BA, //!< 0x00BA U_WMRBA record
+ U_WMR_BB, //!< 0x00BB U_WMRBB record
+ U_WMR_BC, //!< 0x00BC U_WMRBC record
+ U_WMR_BD, //!< 0x00BD U_WMRBD record
+ U_WMR_BE, //!< 0x00BE U_WMRBE record
+ U_WMR_BF, //!< 0x00BF U_WMRBF record
+ U_WMR_C0, //!< 0x00C0 U_WMRC0 record
+ U_WMR_C1, //!< 0x00C1 U_WMRC1 record
+ U_WMR_C2, //!< 0x00C2 U_WMRC2 record
+ U_WMR_C3, //!< 0x00C3 U_WMRC3 record
+ U_WMR_C4, //!< 0x00C4 U_WMRC4 record
+ U_WMR_C5, //!< 0x00C5 U_WMRC5 record
+ U_WMR_C6, //!< 0x00C6 U_WMRC6 record
+ U_WMR_C7, //!< 0x00C7 U_WMRC7 record
+ U_WMR_C8, //!< 0x00C8 U_WMRC8 record
+ U_WMR_C9, //!< 0x00C9 U_WMRC9 record
+ U_WMR_CA, //!< 0x00CA U_WMRCA record
+ U_WMR_CB, //!< 0x00CB U_WMRCB record
+ U_WMR_CC, //!< 0x00CC U_WMRCC record
+ U_WMR_CD, //!< 0x00CD U_WMRCD record
+ U_WMR_CE, //!< 0x00CE U_WMRCE record
+ U_WMR_CF, //!< 0x00CF U_WMRCF record
+ U_WMR_D0, //!< 0x00D0 U_WMRD0 record
+ U_WMR_D1, //!< 0x00D1 U_WMRD1 record
+ U_WMR_D2, //!< 0x00D2 U_WMRD2 record
+ U_WMR_D3, //!< 0x00D3 U_WMRD3 record
+ U_WMR_D4, //!< 0x00D4 U_WMRD4 record
+ U_WMR_D5, //!< 0x00D5 U_WMRD5 record
+ U_WMR_D6, //!< 0x00D6 U_WMRD6 record
+ U_WMR_D7, //!< 0x00D7 U_WMRD7 record
+ U_WMR_D8, //!< 0x00D8 U_WMRD8 record
+ U_WMR_D9, //!< 0x00D9 U_WMRD9 record
+ U_WMR_DA, //!< 0x00DA U_WMRDA record
+ U_WMR_DB, //!< 0x00DB U_WMRDB record
+ U_WMR_DC, //!< 0x00DC U_WMRDC record
+ U_WMR_DD, //!< 0x00DD U_WMRDD record
+ U_WMR_DE, //!< 0x00DE U_WMRDE record
+ U_WMR_DF, //!< 0x00DF U_WMRDF record
+ U_WMR_E0, //!< 0x00E0 U_WMRE0 record
+ U_WMR_E1, //!< 0x00E1 U_WMRE1 record
+ U_WMR_E2, //!< 0x00E2 U_WMRE2 record
+ U_WMR_E3, //!< 0x00E3 U_WMRE3 record
+ U_WMR_E4, //!< 0x00E4 U_WMRE4 record
+ U_WMR_E5, //!< 0x00E5 U_WMRE5 record
+ U_WMR_E6, //!< 0x00E6 U_WMRE6 record
+ U_WMR_E7, //!< 0x00E7 U_WMRE7 record
+ U_WMR_E8, //!< 0x00E8 U_WMRE8 record
+ U_WMR_E9, //!< 0x00E9 U_WMRE9 record
+ U_WMR_EA, //!< 0x00EA U_WMREA record
+ U_WMR_EB, //!< 0x00EB U_WMREB record
+ U_WMR_EC, //!< 0x00EC U_WMREC record
+ U_WMR_ED, //!< 0x00ED U_WMRED record
+ U_WMR_EE, //!< 0x00EE U_WMREE record
+ U_WMR_EF, //!< 0x00EF U_WMREF record
+ U_WMR_DELETEOBJECT, //!< 0x01F0 U_WMRDELETEOBJECT record
+ U_WMR_F1, //!< 0x00F1 U_WMRF1 record
+ U_WMR_F2, //!< 0x00F2 U_WMRF2 record
+ U_WMR_F3, //!< 0x00F3 U_WMRF3 record
+ U_WMR_F4, //!< 0x00F4 U_WMRF4 record
+ U_WMR_F5, //!< 0x00F5 U_WMRF5 record
+ U_WMR_F6, //!< 0x00F6 U_WMRF6 record
+ U_WMR_CREATEPALETTE, //!< 0x00F7 U_WMRCREATEPALETTE record
+ U_WMR_F8 , //!< 0x00F8 U_WMRF8 record
+ U_WMR_CREATEPATTERNBRUSH, //!< 0x01F9 U_WMRCREATEPATTERNBRUSH record
+ U_WMR_CREATEPENINDIRECT, //!< 0x02FA U_WMRCREATEPENINDIRECT record
+ U_WMR_CREATEFONTINDIRECT, //!< 0x02FB U_WMRCREATEFONTINDIRECT record
+ U_WMR_CREATEBRUSHINDIRECT, //!< 0x02FC U_WMRCREATEBRUSHINDIRECT record
+ U_WMR_CREATEBITMAPINDIRECT, //!< 0x02FD U_WMRCREATEBITMAPINDIRECT record
+ U_WMR_CREATEBITMAP, //!< 0x06FE U_WMRCREATEBITMAP record
+ U_WMR_CREATEREGION, //!< 0x06FF U_WMRCREATEREGION record
+};
+#define U_WMR_MIN 0 //!< Minimum U_WMR_ value.
+#define U_WMR_MAX 255 //!< Maximum U_WMR_ value.
+#define U_WMR_MASK 0xFF //!< Mask for enumerator (lower) byte
+#define U_WMR_INVALID 0xFFFFFFFF //!< Indicates "Not a valid U_WMR_* value"
+
+
+/** BinaryRasterOperation Enumeration WMF manual 2.1.1.2
+
+ Same as U_EMF_EMRSETROP2 in uemf.h
+*/
+
+/** BitCount Enumeration WMF manual 2.1.1.3
+ \defgroup U_WMF_AltBitCount_Qualifiers WMF Alternate names for the values under EMF Bitcount Enumeration in uemf.h
+ @{
+*/
+#define BI_BITCOUNT_0 U_BCBM_EXPLICIT //!< Derived from JPG or PNG compressed image or ?
+#define BI_BITCOUNT_1 U_BCBM_MONOCHROME //!< 2 colors. bmiColors array has two entries
+#define BI_BITCOUNT_2 U_BCBM_COLOR4 //!< 2^4 colors. bmiColors array has 16 entries
+#define BI_BITCOUNT_3 U_BCBM_COLOR8 //!< 2^8 colors. bmiColors array has 256 entries
+#define BI_BITCOUNT_4 U_BCBM_COLOR16 //!< 2^16 colors. bmiColors is not used. Pixels are 5 bits B,G,R with 1 unused bit
+#define BI_BITCOUNT_5 U_BCBM_COLOR24 //!< 2^24 colors. bmiColors is not used. Pixels are U_RGBTRIPLE.
+#define BI_BITCOUNT_6 U_BCBM_COLOR32 //!< 2^32 colors. bmiColors is not used. Pixels are U_RGBQUAD.
+/** @} */
+
+/* BrushStyle Enumeration WMF manual 2.1.1.4
+ Same as "EMF LB_Style Enumeration" in uemf.h
+*/
+
+/* CharacterSet Enumeration WMF manual 2.1.1.5
+ Same as "EMF LF_CharSet Enumeration" in uemf.h
+*/
+
+/** ColorUsage Enumeration WMF manual 2.1.1.6
+ For cUsage fields in various DIB related records.
+ \defgroup U_WMF_Extra_iUsageSrc_Qualifiers WMF Extra DIBColors Enumeration
+ WMF is the same as "EMF DIBColors Enumeration" in uemf.h, except it also supports
+ this one extra value.
+ @{
+*/
+#define U_DIB_PAL_INDICES 2 //!< No color table, pixels are logical palette indices.
+/** @} */
+
+/** Compression Enumeration WMF manual 2.1.1.7
+ Same as "EMF BI_Compression Enumeration" in uemf.h with these additions
+ \defgroup U_WMF_EXTRA_BITMAPINFOHEADER_biCompression_Qualifiers WMF Extra BI_Compression Enumerations, none are implemented
+ @{
+*/
+#define U_BI_CMYK 0x000B //!< CMYK uncompressed
+#define U_BI_CMYKRLE8 0x000C //!< CMYK RLE8 compression
+#define U_BI_CMYKRLE4 = 0x000D //!< CMYK RLE4 compression
+/** @} */
+
+/* FamilyFont Enumeration WMF manual 2.1.1.8
+ Only used in a PitchAndFamily object, defined there
+*/
+
+/* FloodFill Enumeration WMF manual 2.1.1.9
+ Same as "EMF FloodFill Enumeration" in uemf.h
+*/
+
+/* FontQuality Enumeration WMF manual 2.1.1.10
+ Same as "EMF LF_Quality Enumeration" in uemf.h
+*/
+
+/* GamutMappingIntent Enumeration WMF manual 2.1.1.11
+ Same as "EMF LCS_Intent Enumeration" in uemf.h
+*/
+
+/* HatchStyle Enumeration WMF manual 2.1.1.12
+ Same as "EMF HatchStyle Enumeration" in uemf.h
+*/
+
+/* Layout Enumeration WMF manual 2.1.1.13
+ Same as "EMF Mirroring Enumeration" in uemf.h
+*/
+
+/** LogicalColorSpace Enumeration WMF manual 2.1.1.14
+ Not used presently, applies in BitmapV4Header
+ @{
+*/
+/* U_LCS_CALIBRATED_RGB is defined in uemf.h under LCS_CSType Enumeration, WMF manual also defines it, but do not replicate define.
+#define U_LCS_CALIBRATED_RGB 0x00000000 //!< calibrated RGB
+*/
+#define U_LCS_sRGB 0x73524742 //!< ASCII for "sRGB"
+#define U_LCS_WINDOWS_COLOR_SPACE 0x57696E20 //!< ASCII for "Win "
+/** @} */
+
+/* LogicalColorSpaceV5 Enumeration WMF manual 2.1.1.15
+ Same as "EMF Profile Enumeration" in uemf.h
+*/
+
+/* MapMode Enumeration WMF manual 2.1.1.16
+ Same as "EMF MapMode Enumeration" in uemf.h
+*/
+
+/** MetaFilesEscape Enumeration WMF manual 2.1.1.17
+ \defgroup U_WMF_MFEscape_Qualifiers WMF Metafile Escape record types
+ For U_WMRESCAPE eFunc field
+ @{
+*/
+#define U_MFE_NEWFRAME 0x0001 //!< NEWFRAME escape type
+#define U_MFE_ABORTDOC 0x0002 //!< ABORTDOC escape type
+#define U_MFE_NEXTBAND 0x0003 //!< NEXTBAND escape type
+#define U_MFE_SETCOLORTABLE 0x0004 //!< SETCOLORTABLE escape type
+#define U_MFE_GETCOLORTABLE 0x0005 //!< GETCOLORTABLE escape type
+#define U_MFE_FLUSHOUT 0x0006 //!< FLUSHOUT escape type
+#define U_MFE_DRAFTMODE 0x0007 //!< DRAFTMODE escape type
+#define U_MFE_QUERYESCSUPPORT 0x0008 //!< QUERYESCSUPPORT escape type
+#define U_MFE_SETABORTPROC 0x0009 //!< SETABORTPROC escape type
+#define U_MFE_STARTDOC 0x000A //!< STARTDOC escape type
+#define U_MFE_ENDDOC 0x000B //!< ENDDOC escape type
+#define U_MFE_GETPHYSPAGESIZE 0x000C //!< GETPHYSPAGESIZE escape type
+#define U_MFE_GETPRINTINGOFFSET 0x000D //!< GETPRINTINGOFFSET escape type
+#define U_MFE_GETSCALINGFACTOR 0x000E //!< GETSCALINGFACTOR escape type
+#define U_MFE_META_ESCAPE_ENHANCED_METAFILE 0x000F //!< META_ESCAPE_ENHANCED_METAFILE escape type
+#define U_MFE_SETPENWIDTH 0x0010 //!< SETPENWIDTH escape type
+#define U_MFE_SETCOPYCOUNT 0x0011 //!< SETCOPYCOUNT escape type
+#define U_MFE_SETPAPERSOURCE 0x0012 //!< SETPAPERSOURCE escape type
+#define U_MFE_PASSTHROUGH 0x0013 //!< PASSTHROUGH escape type
+#define U_MFE_GETTECHNOLOGY 0x0014 //!< GETTECHNOLOGY escape type
+#define U_MFE_SETLINECAP 0x0015 //!< SETLINECAP escape type
+#define U_MFE_SETLINEJOIN 0x0016 //!< SETLINEJOIN escape type
+#define U_MFE_SETMITERLIMIT 0x0017 //!< SETMITERLIMIT escape type
+#define U_MFE_BANDINFO 0x0018 //!< BANDINFO escape type
+#define U_MFE_DRAWPATTERNRECT 0x0019 //!< DRAWPATTERNRECT escape type
+#define U_MFE_GETVECTORPENSIZE 0x001A //!< GETVECTORPENSIZE escape type
+#define U_MFE_GETVECTORBRUSHSIZE 0x001B //!< GETVECTORBRUSHSIZE escape type
+#define U_MFE_ENABLEDUPLEX 0x001C //!< ENABLEDUPLEX escape type
+#define U_MFE_GETSETPAPERBINS 0x001D //!< GETSETPAPERBINS escape type
+#define U_MFE_GETSETPRINTORIENT 0x001E //!< GETSETPRINTORIENT escape type
+#define U_MFE_ENUMPAPERBINS 0x001F //!< ENUMPAPERBINS escape type
+#define U_MFE_SETDIBSCALING 0x0020 //!< SETDIBSCALING escape type
+#define U_MFE_EPSPRINTING 0x0021 //!< EPSPRINTING escape type
+#define U_MFE_ENUMPAPERMETRICS 0x0022 //!< ENUMPAPERMETRICS escape type
+#define U_MFE_GETSETPAPERMETRICS 0x0023 //!< GETSETPAPERMETRICS escape type
+#define U_MFE_POSTSCRIPT_DATA 0x0025 //!< POSTSCRIPT_DATA escape type
+#define U_MFE_POSTSCRIPT_IGNORE 0x0026 //!< POSTSCRIPT_IGNORE escape type
+#define U_MFE_GETDEVICEUNITS 0x002A //!< GETDEVICEUNITS escape type
+#define U_MFE_GETEXTENDEDTEXTMETRICS 0x0100 //!< GETEXTENDEDTEXTMETRICS escape type
+#define U_MFE_GETPAIRKERNTABLE 0x0102 //!< GETPAIRKERNTABLE escape type
+#define U_MFE_EXTTEXTOUT 0x0200 //!< EXTTEXTOUT escape type
+#define U_MFE_GETFACENAME 0x0201 //!< GETFACENAME escape type
+#define U_MFE_DOWNLOADFACE 0x0202 //!< DOWNLOADFACE escape type
+#define U_MFE_METAFILE_DRIVER 0x0801 //!< METAFILE_DRIVER escape type
+#define U_MFE_QUERYDIBSUPPORT 0x0C01 //!< QUERYDIBSUPPORT escape type
+#define U_MFE_BEGIN_PATH 0x1000 //!< BEGIN_PATH escape type
+#define U_MFE_CLIP_TO_PATH 0x1001 //!< CLIP_TO_PATH escape type
+#define U_MFE_END_PATH 0x1002 //!< END_PATH escape type
+#define U_MFE_OPEN_CHANNEL 0x100E //!< OPEN_CHANNEL escape type
+#define U_MFE_DOWNLOADHEADER 0x100F //!< DOWNLOADHEADER escape type
+#define U_MFE_CLOSE_CHANNEL 0x1010 //!< CLOSE_CHANNEL escape type
+#define U_MFE_POSTSCRIPT_PASSTHROUGH 0x1013 //!< POSTSCRIPT_PASSTHROUGH escape type
+#define U_MFE_ENCAPSULATED_POSTSCRIPT 0x1014 //!< ENCAPSULATED_POSTSCRIPT escape type
+#define U_MFE_POSTSCRIPT_IDENTIFY 0x1015 //!< POSTSCRIPT_IDENTIFY escape type
+#define U_MFE_POSTSCRIPT_INJECTION 0x1016 //!< POSTSCRIPT_INJECTION escape type
+#define U_MFE_CHECKJPEGFORMAT 0x1017 //!< CHECKJPEGFORMAT escape type
+#define U_MFE_CHECKPNGFORMAT 0x1018 //!< CHECKPNGFORMAT escape type
+#define U_MFE_GET_PS_FEATURESETTING 0x1019 //!< GET_PS_FEATURESETTING escape type
+#define U_MFE_MXDC_ESCAPE 0x101A //!< MXDC_ESCAPE escape type
+#define U_MFE_SPCLPASSTHROUGH2 0x11D8 //!< SPCLPASSTHROUGH2 escape type
+/** @} */
+
+/** MetafileType Enumeration WMF manual 2.1.1.18
+ @{
+*/
+#define U_MEMORYMETAFILE 0x0001 //!< memory metafile (never used by libUWMF)
+#define U_DISKMETAFILE 0x0002 //!< disk metafile (always used by libUWMF)
+/** @} */
+
+/** MetafileVersion Enumeration WMF manual 2.1.1.19
+ @{
+*/
+
+#define U_METAVERSION100 0x0100 //!< DIBs not allowed
+#define U_METAVERSION300 0x0300 //!< DIBs allowed
+/** @} */
+
+/* MixMode Enumeration WMF manual 2.1.1.20
+ Same as "EMF BackgroundMode Enumeration" in uemf.h
+*/
+
+/* OutPrecision Enumeration WMF manual 2.1.1.21
+ Same as "EMF LF_OutPrecision Enumeration" in uemf.h
+*/
+
+/** PaletteEntryFlag Enumeration WMF manual 2.1.1.22
+ @{
+*/
+#define U_PC_RESERVED 0x01 //!< used for animation
+#define U_PC_EXPLICIT 0x02 //!< low order word is palette index
+#define U_PC_NOCOLLAPSE 0x04 //!< store as new color in palette, do not match to existing color
+/** @} */
+
+/** PenStyle Enumeration WMF manual 2.1.1.23
+ Same as "EMF PenStyle Enumeration" in uemf.h,
+ EXCEPT no values >0xFFFF are used, in particular there is no U_PS_GEOMETRIC (ie, all are U_PS_COSMETIC).
+ Apparently because there is no U_PS_GEOMETRIC, U_PS_JOIN* and U_PS_ENDCAP* are also ignored by XP SP3 Preview
+ (which defaults to a rounded cap) and PowerPoint 2003 (which defaults to square cap). The behavior
+ was the same when escape records for JOIN and ENDCAP are used. Bottom line, WMF line formatting seems
+ to be very hit and miss from application to application.
+*/
+
+/* PitchFont Enumeration WMF manual 2.1.1.24
+ These are only used in PitchAndFamily object, defined there.
+*/
+
+/* PolyFillMode Enumeration WMF manual 2.1.1.25
+ These are the first two emtries in "EMF PolygonFillMode Enumeration" in uemf.h
+
+*/
+
+/** PostScriptCap Enumeration WMF manual 2.1.1.26
+ These are used in Escape Cap
+ @{
+*/
+#define U_WPS_CAP_NOTSET -2
+#define U_WPS_CAP_FLAT 0
+#define U_WPS_CAP_ROUND 1
+#define U_WPS_CAP_SQUARE 2
+/** @} */
+
+/* PostScriptClipping Enumeration WMF manual 2.1.1.27
+ PostFeatureSetting Enumeration WMF manual 2.1.1.28
+
+ These are used by postscript drivers, not supported by libUWEMF.
+*/
+
+/** PostScrioptJoin Enumeration WMF manual 2.1.1.29
+ These are used in Escape Cap
+ @{
+*/
+#define U_WPS_JOIN_NOTSET -2
+#define U_WPS_JOIN_MITER 0
+#define U_WPS_JOIN_ROUND 1
+#define U_WPS_JOIN_BEVEL 2
+/** @} */
+
+/* StretchMode Enumeration WMF manual 2.1.1.30
+ Same as "EMF StretchMode Enumeration" in uemf.h
+
+*/
+
+/* TernaryRasterOperation Enumeration WMF manual 2.1.1.31
+ Same as "EMF Ternary Raster Operation Enumeration" in uemf.h
+ Only partially supported in libUWMF.h
+*/
+
+/* ClipPrecision Flags WMF manual 2.1.2.1
+ Same as "EMF LF_ClipPrecision Enumeration" in uemf.h
+*/
+
+/* ExtTextOutOptions Flags WMF manual 2.1.2.2
+ These are a subset of "EMF ExtTextOutOptions Enumeration" in uemf.h
+
+ Not defined for WMF: U_ETO_NONE, U_ETO_GRAYED, U_ETO_NORECT,
+ U_ETO_SMALL_CHARS,U_ETO_IGNORELANGUAGE,U_ETO_REVERSE_INDEX_MAP
+
+ Defined for WMF: U_ETO_OPAQUE, U_ETO_CLIPPED, U_ETO_GLYPH_INDEX,
+ U_ETO_RTLREADING,_ETO_NUMERICSLOCAL,U_ETO_NUMERICSLATIN,
+ U_ETO_PDY
+*/
+
+/* TextAlignment Enumeration WMF manual 2.1.2.3
+ VertialTextAlignment Enumeration WMF manual 2.1.2.4
+ These are both in "EMF TextAlignment Enumeration" in uemf.h
+*/
+
+
+
+// ***************************************************************************
+// Miscellaneous Values
+/* TextAlignmentMode Flags WMF manual 2.1.2.3
+ VerticalTextAlignmentMode Flags WMF manual 2.1.2.4
+ Same as "EMF TextAlignment Enumeration" in uemf.h
+*/
+
+/** \defgroup U_WMF_MinimumRecord_sizes WMF Size in bytes of core record types.
+
+ The size of the object/record is USUALLY not the same
+ as the sizeof() of the corresponding struct, so in general it is unsafe to use sizeof() with this code.
+
+ Always use the U_SIZE_x instead!!!!
+
+ Note that some records may actually be much, much longer than their minimum size as they include strings,
+ bitmaps, and such.
+
+ Documentation for each value is:
+ + = same as struct size
+ or
+ X = different from struct size
+ followed by
+ Number (sizeof(struct) == size of the struct in bytes.)
+
+ @{
+*/
+#define U_SIZE_PAIRF 8 /**< + 8 this might be different on 64 bit platform */
+#define U_SIZE_COLORREF 4 /**< + 4 */
+#define U_SIZE_BRUSH 8 /**< + 8 */
+#define U_SIZE_FONT 19 /**< X 20 */
+#define U_SIZE_FONT_CORE 18 /**< X 20 Like U_FONT, but minus the FaceName part */
+#define U_SIZE_PLTNTRY 4 /**< + 4 */
+#define U_SIZE_PALETTE 8 /**< + 8 */
+#define U_SIZE_PEN 10 /**< + 10 */
+#define U_SIZE_POINT16 4 /**< + 4 */
+#define U_SIZE_RECT16 8 /**< + 8 */
+#define U_SIZE_REGION 20 /**< X 22 20 is minums the variable part */
+#define U_SIZE_BITMAP16 10 /**< + 10 */
+#define U_SIZE_BITMAPCOREHEADER 12 /**< + 12 */
+// also defined in uemf.h, avoid redefining. Same value in both places, of course.
+// # define U_SIZE_BITMAPINFOHEADER 40 /**< + 40 */
+#define U_SIZE_BITMAPV4HEADER 108 /**< ? 108 not tested */
+#define U_SIZE_BITMAPV5HEADER 124 /**< ? 124 not tested */
+#define U_SIZE_WLOGBRUSH 8 /**< + 8 */
+#define U_SIZE_POLYPOLYGON 4 /**< + 4 */
+#define U_SIZE_SCAN 8 /**< + 8 */
+#define U_SIZE_METARECORD 6 /**< X 8 */
+#define U_SIZE_WMRPLACEABLE 22 /**< X 24 */
+#define U_SIZE_WMRHEADER 18 /**< X 20 */
+#define U_SIZE_WMREOF 6 /**< X 8 */
+#define U_SIZE_WMRSETRELABS 6 /**< X 8 */
+#define U_SIZE_WMRSAVEDC 6 /**< X 8 */
+#define U_SIZE_WMRRESTOREDC 8 /**< * 8 */
+#define U_SIZE_WMRREALIZEPALETTE 6 /**< X 8 */
+#define U_SIZE_WMRSETBKCOLOR 10 /**< X 12 */
+#define U_SIZE_WMRSETTEXTCOLOR 10 /**< X 12 */
+#define U_SIZE_WMRSETBKMODE 8 /**< X 12 last 2 bytes are optional */
+#define U_SIZE_WMRSETROP2 8 /**< X 12 last 2 bytes are optional */
+#define U_SIZE_WMRSETPOLYFILLMODE 8 /**< X 12 last 2 bytes are optional */
+#define U_SIZE_WMRSETSTRETCHBLTMODE 8 /**< X 12 last 2 bytes are optional */
+#define U_SIZE_WMRSETTEXTALIGN 8 /**< X 12 last 2 bytes are optional */
+#define U_SIZE_WMRSETMAPMODE 8 /**< + 8 */
+#define U_SIZE_WMRSETTEXTCHAREXTRA 8 /**< + 8 */
+#define U_SIZE_WMRSETTEXTJUSTIFICATION 10 /**< X 12 */
+#define U_SIZE_WMRSETWINDOWORG 10 /**< X 12 */
+#define U_SIZE_WMRSETWINDOWEXT 10 /**< X 12 */
+#define U_SIZE_WMRSETVIEWPORTORG 10 /**< X 12 */
+#define U_SIZE_WMRSETVIEWPORTEXT 10 /**< X 12 */
+#define U_SIZE_WMROFFSETWINDOWORG 10 /**< X 12 */
+#define U_SIZE_WMROFFSETVIEWPORTORG 10 /**< X 12 */
+#define U_SIZE_WMRLINETO 10 /**< X 12 */
+#define U_SIZE_WMRMOVETO 10 /**< X 12 */
+#define U_SIZE_WMROFFSETCLIPRGN 10 /**< X 12 */
+#define U_SIZE_WMRSCALEWINDOWEXT 14 /**< X 16 */
+#define U_SIZE_WMRSCALEVIEWPORTEXT 14 /**< X 16 */
+#define U_SIZE_WMREXCLUDECLIPRECT 14 /**< X 16 */
+#define U_SIZE_WMRINTERSECTCLIPRECT 14 /**< X 16 */
+#define U_SIZE_WMRARC 22 /**< X 24 */
+#define U_SIZE_WMRELLIPSE 14 /**< X 16 */
+#define U_SIZE_WMRRECTANGLE 14 /**< X 16 */
+#define U_SIZE_WMRFLOODFILL 16 /**< + 16 */
+#define U_SIZE_WMREXTFLOODFILL 16 /**< + 16 */
+#define U_SIZE_WMRSETPIXEL 14 /**< X 16 */
+#define U_SIZE_WMRPIE 22 /**< X 24 */
+#define U_SIZE_WMRCHORD 22 /**< X 24 */
+#define U_SIZE_WMRROUNDRECT 18 /**< X 20 */
+#define U_SIZE_WMRPATBLT 18 /**< X 20 */
+#define U_SIZE_WMRTEXTOUT 8 /**< X 12 (not including String,y,x) */
+#define U_SIZE_WMRBITBLT_NOPX 24 /**< + 24 */
+#define U_SIZE_WMRBITBLT_PX 22 /**< X 32 */
+#define U_SIZE_WMRSTRETCHBLT_NOPX 28 /**< + 28 */
+#define U_SIZE_WMRSTRETCHBLT_PX 26 /**< X 36 */
+#define U_SIZE_WMRPOLYGON 10 /**< X 12 */
+#define U_SIZE_WMRPOLYLINE 10 /**< X 12 */
+#define U_SIZE_WMRESCAPE 10 /**< X 12 Data field could be completely absent */
+#define U_SIZE_WMRFILLREGION 10 /**< X 12 */
+#define U_SIZE_WMRFRAMEREGION 14 /**< X 16 */
+#define U_SIZE_WMRINVERTREGION 8 /**< + 8 */
+#define U_SIZE_WMRPAINTREGION 8 /**< + 8 */
+#define U_SIZE_WMRSELECTCLIPREGION 8 /**< + 8 */
+#define U_SIZE_WMRSELECTOBJECT 8 /**< + 8 */
+#define U_SIZE_WMRSELECTPALETTE 8 /**< + 8 */
+#define U_SIZE_WMRRESIZEPALETTE 8 /**< + 8 */
+#define U_SIZE_WMRDELETEOBJECT 8 /**< + 8 */
+#define U_SIZE_WMRDRAWTEXT 6 /**< X 8 */
+#define U_SIZE_WMRCREATEBITMAPINDIRECT 6 /**< X 8 */
+#define U_SIZE_WMRCREATEBITMAP 6 /**< X 8 */
+#define U_SIZE_WMRSETMAPPERFLAGS 10 /**< X 12 */
+#define U_SIZE_WMREXTTEXTOUT 14 /**< X 16 */
+#define U_SIZE_WMRSETDIBTODEV 22 /**< X 28 */
+#define U_SIZE_WMRANIMATEPALETTE 14 /**< X 16 */
+#define U_SIZE_WMRSETPALENTRIES 14 /**< X 16 */
+#define U_SIZE_WMRCREATEPALETTE 14 /**< X 16 */
+#define U_SIZE_WMRPOLYPOLYGON 10 /**< X 12 */
+#define U_SIZE_WMRDIBBITBLT_NOPX 24 /**< + 24 */
+#define U_SIZE_WMRDIBBITBLT_PX 22 /**< X 24 */
+#define U_SIZE_WMRDIBSTRETCHBLT_NOPX 28 /**< + 28 */
+#define U_SIZE_WMRDIBSTRETCHBLT_PX 26 /**< X 28 */
+#define U_SIZE_WMRDIBCREATEPATTERNBRUSH 10 /**< X 12 */
+#define U_SIZE_WMRSTRETCHDIB 28 /**< X 32 */
+#define U_SIZE_WMRCREATEPATTERNBRUSH 6 /**< X 8 */
+#define U_SIZE_WMRCREATEPENINDIRECT 16 /**< + 16 */
+#define U_SIZE_WMRCREATEFONTINDIRECT 26 /**< X 28 */
+#define U_SIZE_WMRCREATEBRUSHINDIRECT 14 /**< X 16 */
+#define U_SIZE_WMRCREATEREGION 26 /**< X 28 */
+#define U_SIZE_WMRCREATEREGION_CORE 24 /**< X 28 Like U_SIZE_WMRCREATEREGION minus the variable part */
+/** @} */
+
+
+// ***************************************************************************
+// Macros
+
+/** \defgroup U_WMF_Common_macros WMF Common Macros
+Because Size16_4 may not be aligned no tests should dereference it directly from a pointer.
+in NOPX tests cast causes uint8_t to promote to uint32_t, without it c++ compiler complains about
+comparison of int with unsigned int
+ @{
+*/
+#define U_TEST_NOPX2(A,B) (A == (uint32_t) (B + 3)) //!< A is Size16_4 (extracted and aligned), B = xb true if no bitmap associated with the structure, used with some BLT records.
+#define U_TEST_NOPXB(A,B) (A/2 == (uint32_t) (B + 3)) //!< A is Size16_4 (extracted and aligned)*2, B = xb, true if no bitmap associated with the structure, used with some BLT records.
+#define U_WMRTYPE(A) (((U_METARECORD *)A)->iType) //!< Get iType from U_WMR* record.
+#define U_WMRXB(A) (((U_METARECORD *)A)->xb) //!< Get xb from U_WMR* record.
+#define U_WMR_XB_FROM_TYPE(A) ((uint8_t) (U_wmr_values(A)>>8)) //!< Get xb from type value.
+#define U_U16(A) (*(uint16_t *)&A) //!< interpret a 16 bit type as uint16_t.
+#define U_P16(A) ( (uint16_t *)&A) //!< pass any 16 bit type as a pointer to a uint16_t.
+#define U_PP16(A) ( (uint16_t *) A) //!< pass any pointer to a 16 bit type as a pointer to a uint16_t.
+
+/** @} */
+
+/* ************************************************************
+ WMF structures OTHER than those corresponding to complete U_WMR_* records
+ ************************************************************ */
+
+/** Brush Object WMF manual 2.2.1.1
+
+ Documentation is muddy, bColor and bHatch fields have different meanings depending on
+ the value of bStyle. Unclear if bHatch bytes are present in some cases from the
+ documentation.
+
+ style Color Data
+ U_BS_SOLID ColorRef Object Not used (bytes present???)
+ U_BS_NULL ignored ignored (bytes present???).
+ U_BS_PATTERN ignored Bitmap16 object holding patern
+ U_BS_DIBPATTERNPT ColorUsage Enum DIB object
+ U_BS_HATCHED ColorRef Object HatchStyle Enumeration
+*/
+typedef struct {
+ uint16_t Style; //!< BrushStyle Enumeration
+ U_COLORREF Color; //!< Brush Color value, 32 bit value is not aligned.
+ uint8_t Data[1]; //!< Brush pattern information, variable size and format
+} U_BRUSH;
+
+
+/** Font Object WMF manual 2.2.1.2
+ Warning, only pass by pointer, passing by value will will truncate in Facename!
+*/
+typedef struct {
+ int16_t Height; //!< Height in Logical units
+ int16_t Width; //!< Average Width in Logical units
+ int16_t Escapement; //!< Angle in 0.1 degrees betweem escapement vector and X axis
+ int16_t Orientation; //!< Angle in 0.1 degrees between baseline and X axis
+ int16_t Weight; //!< LF_Weight Enumeration
+ uint8_t Italic; //!< LF_Italic Enumeration
+ uint8_t Underline; //!< LF_Underline Enumeration
+ uint8_t StrikeOut; //!< LF_StrikeOut Enumeration
+ uint8_t CharSet; //!< LF_CharSet Enumeration
+ uint8_t OutPrecision; //!< LF_OutPrecision Enumeration
+ uint8_t ClipPrecision; //!< LF_ClipPrecision Enumeration
+ uint8_t Quality; //!< LF_Quality Enumeration
+ uint8_t PitchAndFamily; //!< LF_PitchAndFamily Enumeration
+ uint8_t FaceName[1]; //!< Name of font. ANSI Latin1, null terminated.
+} U_FONT;
+
+/** PaletteEntry Object WMF manual 2.2.2.13
+ Note, NOT compatiable with U_LOGPLTNTRY
+ Out of PDF order because needed for next struture.
+*/
+typedef struct {
+ uint8_t Value; //!< 0 or PaletteEntryFlag Enumeration
+ uint8_t Blue; //!< Palette entry Blue Intensity
+ uint8_t Green; //!< Palette entry Green Intensity
+ uint8_t Red; //!< Palette entry Red Intensity
+} U_PLTNTRY;
+
+/** Palette Object WMF manual 2.2.1.3
+ NOT Same as "EMF LogPalette Object" in uemf.h because Palette Entries have reversed colors.
+ Values for palVersion are expanded
+
+ Start must be 0x0300 (as for EMF) with U_WMRCREATEPALETTE but is an offset
+ for U_WMRSETPALENTRIES and U_ANIMATEPALETTE
+*/
+typedef struct {
+ uint16_t Start; //!< Either 0x0300 or an offset into the Palette table
+ uint16_t NumEntries; //!< Number of U_LOGPLTNTRY objects
+ U_PLTNTRY PalEntries[1]; //!< Array of PaletteEntry Objects
+} U_PALETTE;
+
+/** Pen Object WMF manual 2.2.1.4
+*/
+typedef struct {
+ uint16_t Style; //!< PenStyle Enumeration
+ uint16_t Widthw[2]; //!< reassemble/store the Pen Width in object dimensions using Widthw, the 32 bit value is not aligned
+ U_COLORREF Color; //!< Pen Color, the 32 bit value is not aligned.
+} U_PEN;
+
+/** Rect Object WMF manual 2.2.2.18
+ \brief Coordinates of the upper left, lower right corner.
+ Note that the coordinate system is 0,0 in the upper left corner
+ of the screen an N,M in the lower right corner.
+ Microsoft name: RECT Object COLLIDES with EMF Rect Object.
+
+ This one is out of order because it is needed early.
+*/
+typedef struct {
+ int16_t left; //!< left coordinate
+ int16_t top; //!< top coordinate
+ int16_t right; //!< right coordinate
+ int16_t bottom; //!< bottom coordinate
+} U_RECT16;
+
+#define U_RCL16_DEF (U_RECT16){0,0,-1,-1} //!< Use this when no bounds are needed.
+
+/** Region Object WMF manual 2.2.1.5
+*/
+typedef struct {
+ uint16_t ignore1; //!< unused value
+ uint16_t Type; //!< must be 0x0006.
+ uint16_t ignore2; //!< unused value
+ int16_t Size; //!< aScans in bytes + regions size in bytes (size of this header plus all U_SCAN objects?)
+ int16_t sCount; //!< number of scanlines in region
+ int16_t sMax; //!< largest number of points in any scan
+ U_RECT16 sRect; //!< bounding rectangle
+ uint16_t aScans[1]; //!< series of appended U_SCAN objects
+} U_REGION;
+
+/** Bitmap16 Object WMF manual 2.2.2.1
+
+ The U_BITMAP16 core is always followed by
+ uint8_t Bits[1]; //!< bitmap pixel data. Bytes contained = (((Width * BitsPixel + 15) >> 4) << 1) * Height
+ Note that in U_WMRCREATEPATTERNBRUSH Bits is always [4].
+
+*/
+typedef struct {
+ int16_t Type; //!< "bitmap type" MS PDF does not define this field beyond this.
+ int16_t Width; //!< bitmap width in pixels.
+ int16_t Height; //!< bitmap height in scan lines.
+ int16_t WidthBytes; //!< bytes per scan line.
+ uint8_t Planes; //!< must be 1.
+ uint8_t BitsPixel; //!< number of adjacent color bits on each plane (R bits + G bits + B bits ????)
+} U_BITMAP16;
+
+/** BitmapCoreHeader Object WMF manual 2.2.2.2
+*/
+typedef struct {
+ uint16_t Size_4[2]; //!< size of U_BITMAPCOREHEADER in bytes.
+ uint16_t Width; //!< DIB width in pixels.
+ uint16_t Height; //!< DIB height in pixels.
+ uint16_t Planes; //!< must be 1
+ uint16_t BitCount; //!< Pixel Format (BitCount Enumeration)
+} U_BITMAPCOREHEADER;
+
+
+/** BitmapInfoHeader Object WMF manual 2.2.2.3
+ Same as "EMF BITMAPINFOHEADER Object" in uemf.h
+ use U_BITMAPINFOHEADER
+*/
+
+//! \cond
+/** BitmapV4Header Object WMF manual 2.2.2.4
+*/
+typedef struct {
+ uint32_t bV4Size;
+ int32_t bV4Width;
+ int32_t bV4Height;
+ uint16_t bV4Planes;
+ uint16_t bV4BitCount;
+ uint32_t bV4Compression;
+ uint32_t bV4SizeImage;
+ int32_t bV4XPelsPerMeter;
+ int32_t bV4YPelsPerMeter;
+ uint32_t bV4ClrUsed;
+ uint32_t bV4ClrImportant;
+ uint32_t bV4RedMask;
+ uint32_t bV4GreenMask;
+ uint32_t bV4BlueMask;
+ uint32_t bV4AlphaMask;
+ uint32_t bV4CSType;
+ U_CIEXYZTRIPLE bV4EndPoints;
+ uint32_t bV4GammaRed;
+ uint32_t bV4GammaGreen;
+ uint32_t bV4GammaBlue;
+} U_BITMAPV4HEADER; //!< For ?
+
+
+/** BitmapV5Header Object WMF manual 2.2.2.5
+*/
+typedef struct {
+ uint32_t bV5Size;
+ int32_t bV5Width;
+ int32_t bV5Height;
+ uint16_t bV5Planes;
+ uint16_t bV5BitCount;
+ uint32_t bV5Compression;
+ uint32_t bV5SizeImage;
+ int32_t bV5XPelsPerMeter;
+ int32_t bV5YPelsPerMeter;
+ uint32_t bV5ClrUsed;
+ uint32_t bV5ClrImportant;
+ uint32_t bV5RedMask;
+ uint32_t bV5GreenMask;
+ uint32_t bV5BlueMask;
+ uint32_t bV5AlphaMask;
+ uint32_t bV5CSType;
+ U_CIEXYZTRIPLE bV5Endpoints;
+ uint32_t bV5GammaRed;
+ uint32_t bV5GammaGreen;
+ uint32_t bV5GammaBlue;
+ uint32_t bV5Intent;
+ uint32_t bV5ProfileData;
+ uint32_t bV5ProfileSize;
+ uint32_t bV5Reserved;
+} U_BITMAPV5HEADER; //!< For ?
+//! \endcond
+
+
+
+/** CIEXYZ Object WMF manual 2.2.2.6
+ Same as "EMF CIEXYZ Object" in uemf.h
+*/
+
+/** CIEXYZTriple Object WMF manual 2.2.2.7
+ Same as "EMF CIEXYZTRIPLE Object" in uemf.h
+*/
+
+/** ColorRef Object WMF manual 2.2.2.8
+ Same as "EMF COLORREF Object" in uemf.h
+*/
+
+/** DeviceIndependentBitmap Object WMF manual 2.2.2.9
+This "object" has an organization, but not one that can be easily expressed with a C struct. It consists of
+three parts, all of which have variable size:
+
+ DIBHeaderInfo BitmapCoreHeader or BitmapInfoHeader Object
+ Colors Array of RGBQuad Objects or uint16_t that make a color table, as determined from the DIBHeaderInfo field.
+ BitMapBuffer Array of bytes containing the image.
+
+*/
+
+/** WLogBrush Object WMF manual 2.2.2.10
+ Not compatible with EMF LogBrush object!
+
+ style Color Hatch
+ U_BS_SOLID ColorRef Object Not used (bytes present???)
+ U_BS_NULL ignored ignored (bytes present???).
+ U_BS_PATTERN ignored not used (Action is not strictly defined)
+ U_BS_DIBPATTERN ignored not used (Action is not strictly defined)
+ U_BS_DIBPATTERNPT ignored not used (Action is not strictly defined)
+ U_BS_HATCHED ColorRef Object HatchStyle Enumeration
+*/
+typedef struct {
+ uint16_t Style; //!< BrushStyle Enumeration
+ U_COLORREF Color; //!< Brush Color value, 32 bit value is not aligned.
+ uint16_t Hatch; //!< HatchStyle Enumeration
+} U_WLOGBRUSH;
+
+/* LogColorSpace Object WMF manual 2.2.2.11
+ Same as "EMF LOGCOLORSPACEA Object" in uemf.h
+ use U_LOGCOLORSPACEA
+*/
+
+/* LogColorSpaceW Object WMF manual 2.2.2.12
+ Same as "EMF LOGCOLORSPACEW Object" in uemf.h
+ use U_LOGCOLORSPACEW
+*/
+
+
+/* PaletteEntry Object WMF manual 2.2.2.13
+ moved up before Palette Object */
+
+/* PitchAndFamily Enumerations WMF manual 2.2.2.14
+ Same as "EMF LF_PitchAndFamily Enumeration" in uemf.h
+*/
+
+/* PointL Object WMF manual 2.2.2.15
+ Same as "EMF Point Object" in uemf.h
+*/
+
+/* PointS Object WMF manual 2.2.2.16
+ Same as "EMF POINTS Object" in uemf.h
+*/
+
+/* PolyPolygon Object WMF manual 2.2.2.17 */
+/** WMF manual 2.2.2.17
+
+ There is an array "aPoints" of uint16_t after aPolyCounts that holds the coordinates.
+
+ Presumably it is in order [x1,y1],[x2,y2],etc. The documentation does not say, it might have
+ y then x.
+
+ aPoints starts at aPolyCounts[nPolys]
+*/
+typedef struct {
+ uint16_t nPolys; //!< Number of polygons
+ uint16_t aPolyCounts[1]; //!< Number of points in each polygon (sequential)
+} U_POLYPOLYGON;
+
+/* Rect Object WMF manual 2.2.2.18
+ This one is out of order, had to be created much earlier than this
+*/
+
+/* RectL Object WMF manual 2.2.2.19
+ Same as "EMF RECT Object" in uemf.h
+*/
+
+/* RGBQuad Object WMF manual 2.2.2.20
+ Same as "EMF RGBQUAD Object" in uemf.h
+*/
+
+/** Scan Object WMF manual 2.2.2.21 */
+/** WMF manual 2.2.2.21
+
+ Mandatory field "count2" must follow ScanLines, but it cannot be placed into the struct because
+ ScanLines has variable size. "count2" is
+ an uint16_t value which must have the same value as count.
+*/
+typedef struct {
+ uint16_t count; //!< Number of entries in the ScanLines array
+ uint16_t top; //!< Y coordinate of the top scanline
+ uint16_t bottom; //!< Y coordinate of the bottom scanline
+ uint16_t ScanLines[1]; //!< Array of 16 bit left/right pairs
+} U_SCAN;
+
+/** SizeL Object WMF manual 2.2.2.22
+ Same as "EMF SIZEL Object" in uemf.h
+*/
+
+
+/** First three fields of MOST WMF records (not WMR_HEADER and WMR_PLACEABLE!)
+
+ This Sshould only used for accessing size and type fields.
+ It is NOT used as a prefix like U_EMR in uemf.h because it may cause alignment issues.
+ Microsoft name: WMF Object
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+} U_METARECORD;
+
+/** WMF manual 2.3.2.3 META_PLACEABLE
+ If present this must immediately precede the header.
+ It is not enumerated as an WMR record type.
+ This only ever occurs at the start of a WMF file, so the two uint32_t values will always be aligned.
+*/
+typedef struct {
+ uint32_t Key; //!< MUST be 0x9AC6CDD7
+ uint16_t HWmf; //!< 0. (Always. Manual says total number of 16bit words in record, but no examples found like that)
+ U_RECT16 Dst; //!< Destination bounding box in logical units
+ uint16_t Inch; //!< Logical units/inch (convention if not specified: 1440 logical units/inch)
+ uint32_t Reserved; //!< must be 0
+ uint16_t Checksum; //!< Checksum of preceding 10 16 bit values
+} U_WMRPLACEABLE;
+
+/** WMF manual 2.3.2.2 META_HEADER
+*/
+typedef struct {
+ uint8_t iType; //!< RecordType Enumeration, must be 1
+ uint8_t xb; //!< Extra high order byte associated with record type
+ uint16_t Size16w; //!< Total number of 16bit words in record
+ uint16_t version; //!< Metafile version Enumeration
+ uint16_t Sizew[2]; //!< reassemble/store the Size (16 bit words in entire file) using Sizew, the 32 bit value is not aligned
+ uint16_t nObjects; //!< Total number of brushes, pens, and other graphics objects defined in this file
+ uint32_t maxSize; //!< Largest record in file, in number of 16bit words (This uint32_t is aligned)
+ uint16_t nMembers; //!< Unused, should be 0
+} U_WMRHEADER;
+
+
+// ***********************************************************************************
+// The following structures correspond to U_WMR_# records
+
+/* Index 00 U_WMREOF WMF manual 2.3.2.1 META_EOF */
+/** WMF manual 2.3.2.1 META_EOF
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+} U_WMREOF,
+ U_WMRSETRELABS, //!< WMF manual 2.3.5.21
+ U_WMRSAVEDC, //!< WMF manual 2.3.5.11
+ U_WMRREALIZEPALETTE; //!< WMF manual 2.3.5.8
+
+/* Index 01 U_WMRSETBKCOLOR WMF manual 2.3.5.14 */
+/** WMF manual 2.3.5.14
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ U_COLORREF Color; //!< Color value, the 32 bit value is not aligned.
+} U_WMRSETBKCOLOR,
+ U_WMRSETTEXTCOLOR; //!< WMF manual 2.3.5.26
+
+/* Index 02 U_WMRSETBKMODE WMF manual 2.3.5.15 */
+/** WMF manual 2.3.5.15
+mode = MixMode Enumeration.
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ uint16_t Mode; //!< Various Enumeraton.
+ uint16_t Reserved; //!< Ignore (ALSO OPTIONAL - FIELD MAY NOT BE PRESENT!!!!)
+} U_WMRSETBKMODE,
+ U_WMRSETPOLYFILLMODE, //!< WMF manual 2.3.5.20 Mode = PolyFillMode Enumeration.
+ U_WMRSETROP2, //!< WMF manual 2.3.5.22 Binary Raster Operation Enumeration.
+ U_WMRSETSTRETCHBLTMODE, //!< WMF manual 2.3.5.23 Mode = StretchMode Enumeration
+ U_WMRSETTEXTALIGN; //!< WMF manual 2.3.5.24 Mode = TextAlignment Enumeration.
+
+/* Index 03 U_WMRSETMAPMODE WMF manual 2.3.5.17 */
+/** WMF manual 2.3.5.17
+Mode = MapMode Enumeration.
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ uint16_t Mode; //!< Various Enumeraton and other
+} U_WMRSETMAPMODE,
+ U_WMRSETTEXTCHAREXTRA; //!< WMF manual 2.3.5.25, Mode = Extra space in logical units to add to each character
+
+/* Index 04 U_WMRSETROP2 WMF manual 2.3.5.22 See Index 02 */
+
+/* Index 05 U_WMRSETRELABS WMF manual 2.3.5.21 See Index 00*/
+
+/* Index 06 U_WMRSETPOLYFILLMODE WMF manual 2.3.5.20 See Index 02
+ Index 07 U_WMRSETSTRETCHBLTMODE WMF manual 2.3.5.23 */
+
+/* Index 08 U_WMRSETTEXTCHAREXTRA WMF manual 2.3.5.25 See Index 03*/
+
+/* Index 09 U_WMRSETTEXTCOLOR WMF manual 2.3.5.26 see Index 01 */
+
+/* Index 0A U_WMRSETTEXTJUSTIFICATION WMF manual 2.3.5.27 */
+/** WMF manual 2.3.5.27
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ uint16_t Count; //!< Number of space characters in the line
+ uint16_t Extra; //!< Number of extra space characters to add to the line
+} U_WMRSETTEXTJUSTIFICATION;
+
+/* Index 0B U_WMRSETWINDOWORG WMF manual 2.3.5.31
+ Index 0C U_WMRSETWINDOWEXT WMF manual 2.3.5.30
+ Index 0D U_WMRSETVIEWPORTORG WMF manual 2.3.5.29
+ Index 0E U_WMRSETVIEWPORTEXT WMF manual 2.3.5.28
+ Index 0F U_WMROFFSETWINDOWORG WMF manual 2.3.5.7
+ Index 0F U_WMROFFSETVIEWPORTORG WMF manual 2.3.5.6
+ Index 13 U_WMRLINETO WMF manual 2.3.3.10
+ Index 14 U_WMRMOVETO WMF manual 2.3.3.4
+ Index 20 U_WMROFFSETCLIPRGN WMF manual 2.3.5.5
+*/
+/** WMF manual 2.3.5.31
+Window X,Y origin
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ int16_t y; //!< Y value (note order!)
+ int16_t x; //!< X value
+} U_WMRSETWINDOWORG,
+ U_WMRSETWINDOWEXT, //!< WMF manual 2.3.5.30, Window X,Y extent
+ U_WMRSETVIEWPORTORG, //!< WMF manual 2.3.5.29, Viewport X,Y origin
+ U_WMRSETVIEWPORTEXT, //!< WMF manual 2.3.5.28, Viewport X,Y extent
+ U_WMROFFSETWINDOWORG, //!< WMF manual 2.3.5.7, Window X,Y offset in device units
+ U_WMROFFSETVIEWPORTORG, //!< WMF manual 2.3.5.6, Viewport X,Y offset in device units
+ U_WMRLINETO, //!< WMF manual 2.3.3.10, Endpoint X,Y in logical units
+ U_WMRMOVETO, //!< WMF manual 2.3.3.4, Destination X,Y in logical units
+ U_WMROFFSETCLIPRGN; //!< WMF manual 2.3.5.5, Y offset in logical units
+
+/* Index 10 U_WMRSCALEWINDOWEXT WMF manual 2.3.5.13
+ Index 12 U_WMRSCALEVIEWPORTEXT WMF manual 2.3.5.12
+*/
+/** WMF manual 2.3.5.13
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ int16_t yDenom; //!< Y denominator
+ int16_t yNum; //!< Y numerator
+ int16_t xDenom; //!< X denominator
+ int16_t xNum; //!< X numerator
+} U_WMRSCALEWINDOWEXT,
+ U_WMRSCALEVIEWPORTEXT; //!< WMF manual 2.3.5.12
+
+/* Index 11 U_WMROFFSETVIEWPORTORG WMF manual 2.3.5.6 see Index 0B */
+
+/* Index 12 U_WMRSCALEVIEWPORTEXT WMF manual 2.3.5.12 see Index 10 */
+
+/* Index 13 U_WMRLINETO WMF manual 2.3.3.10 see index 0B
+ Index 14 U_WMRMOVETO WMF manual 2.3.5.4 */
+
+/* Index 15 U_WMREXCLUDECLIPRECT WMF manual 2.3.5.2
+ Index 16 U_WMRINTERSECTCLIPRECT WMF manual 2.3.5.3
+*/
+/** WMF manual 2.3.5.2
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ int16_t Bottom; //!< Coordinates in logical units
+ int16_t Right; //!< Coordinates in logical units
+ int16_t Top; //!< Coordinates in logical units
+ int16_t Left; //!< Coordinates in logical units
+} U_WMREXCLUDECLIPRECT,
+ U_WMRINTERSECTCLIPRECT; //!< WMF manual 2.3.5.3
+
+/* Index 17 U_WMRARC WMF manual 2.3.3.1 */
+/** WMF manual 2.3.3.1
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ int16_t yEndArc; //!< Coordinates in logical units
+ int16_t xEndArc; //!< Coordinates in logical units
+ int16_t yStartArc; //!< Coordinates in logical units
+ int16_t xStartArc; //!< Coordinates in logical units
+ int16_t Bottom; //!< Coordinates in logical units
+ int16_t Right; //!< Coordinates in logical units
+ int16_t Top; //!< Coordinates in logical units
+ int16_t Left; //!< Coordinates in logical units
+} U_WMRARC;
+
+/* Index 18 U_WMRELLIPSE WMF manual 2.3.3.3
+ Index 1B U_WMRRECTANGLE WMF manual 2.3.3.17
+*/
+/** WMF manual 2.3.3.3
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ int16_t Bottom; //!< Coordinates in logical units
+ int16_t Right; //!< Coordinates in logical units
+ int16_t Top; //!< Coordinates in logical units
+ int16_t Left; //!< Coordinates in logical units
+} U_WMRELLIPSE,
+ U_WMRRECTANGLE; //!< WMF manual 2.3.3.17
+
+/* Index 19 U_WMRFLOODFILL WMF manual 2.3.3.7
+ Index 48 U_WMREXTFLOODFILL WMF manual 2.3.3.4
+*/
+/** WMF manual 2.3.3.7
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ int16_t Mode; //!< FloodFill Enumeration
+ U_COLORREF Color; //!< Color
+ int16_t y; //!< Y
+ int16_t x; //!< X
+} U_WMRFLOODFILL,
+ U_WMREXTFLOODFILL; //!< WMF manual 2.3.3.7
+
+/* Index 1A U_WMRPIE WMF manual 2.3.3.13
+ Index 30 U_WMRCHORD WMF manual 2.3.3.2
+*/
+/** WMF manual 2.3.3.13
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ int16_t yRadial2; //!< in logical units
+ int16_t xRadial2; //!< in logical units
+ int16_t yRadial1; //!< in logical units
+ int16_t xRadial1; //!< in logical units
+ int16_t Bottom; //!< in logical units
+ int16_t Right; //!< in logical units
+ int16_t Top; //!< in logical units
+ int16_t Left; //!< in logical units
+} U_WMRPIE,
+ U_WMRCHORD; //!< WMF manual 2.3.3.2
+
+/* Index 1B U_WMRRECTANGLE WMF manual 2.3.3.17 See Index 18 */
+
+/* Index 1C U_WMRROUNDRECT WMF manual 2.3.3.18 */
+/** WMF manual 2.3.3.18
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ int16_t Height; //!< in logical units (rounded corner)
+ int16_t Width; //!< in logical units (rounded corner)
+ int16_t Bottom; //!< in logical units
+ int16_t Right; //!< in logical units
+ int16_t Top; //!< in logical units
+ int16_t Left; //!< in logical units
+} U_WMRROUNDRECT;
+
+/* Index 1D U_WMRPATBLT WMF manual 2.3.3.12
+*/
+/** WMF manual 2.3.3.12
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ uint16_t rop3w[2]; //!< reassemble/store the rop3 Ternary raster operation using rop3w, as the 32 bit value is not aligned
+ int16_t Height; //!< in logical units (of Rect to Fill)
+ int16_t Width; //!< in logical units (of Rect to Fill)
+ int16_t yDst; //!< in logical units (UL corner to fill)
+ int16_t xDst; //!< in logical units (UL corner to fill)
+} U_WMRPATBLT;
+
+/* Index 1E U_WMRSAVEDC WMF manual 2.3.5.11 See Index 00*/
+
+/* Index 1F U_WMRSETPIXEL WMF manual 2.3.3.19 */
+/** WMF manual 2.3.3.19
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ U_COLORREF Color; //!< Color
+ int16_t y; //!< Y
+ int16_t x; //!< X
+} U_WMRSETPIXEL;
+
+/* Index 20 U_WMROFFSETCLIPRGN WMF manual 2.3.5.5 See Index 0B*/
+
+/* Index 21 U_WMRTEXTOUT WMF manual 2.3.3.20
+*/
+/** WMF manual 2.3.3.20
+Also part of the record, following String, and so at variable positions:
+
+int16_t y; start position
+
+int16_t x; start position
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ int16_t Length; //!< Stringlength in bytes
+ uint8_t String; //!< String to write, storage area must be 2n bytes.
+} U_WMRTEXTOUT;
+
+/* Index 22 U_WMRBITBLT WMF manual 2.3.1.1
+*/
+/** WMF manual 2.3.1.1
+
+ This is a variable structure the core/invariant part extends to xSrc.
+
+ if RecordSize == ((xb) + 3) then there is no bitmap and use the _NOPX form, otherwise use the _PX form
+ Use Macro U_TEST_NOPX2
+
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ uint16_t rop3w[2]; //!< reassemble/store the Ternary raster operation rop3 value using rop3w, the 32 bit value is not aligned.
+ int16_t ySrc; //!< in logical units (UL corner of Src rect)
+ int16_t xSrc; //!< in logical units (UL corner of Src rect)
+ int16_t ignore; //!< ignore
+ int16_t Height; //!< in logical units (of Src and Dst rects)
+ int16_t Width; //!< in logical units (of Src and Dst rects)
+ int16_t yDst; //!< in logical units (UL corner of Dst rect)
+ int16_t xDst; //!< in logical units (UL corner of Dst rect)
+} U_WMRBITBLT_NOPX;
+
+/** WMF manual 2.3.1.1
+
+ This is a variable structure the core/invariant part extends to xSrc.
+
+ if RecordSize == ((xb) + 3) then there is no bitmap and use the _NOPX form, otherwise use the _PX form
+ Use Macro U_TEST_NOPX2
+
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ uint16_t rop3w[2]; //!< reassemble/store the Ternary raster operation rop3 value using rop3w, the 32 bit value is not aligned.
+ int16_t ySrc; //!< in logical units (UL corner of Src rect)
+ int16_t xSrc; //!< in logical units (UL corner of Src rect)
+ int16_t Height; //!< in logical units (of Src and Dst rects)
+ int16_t Width; //!< in logical units (of Src and Dst rects)
+ int16_t yDst; //!< in logical units (UL corner of Dst rect)
+ int16_t xDst; //!< in logical units (UL corner of Dst rect)
+ U_BITMAP16 bitmap; //!< Src bitmap
+} U_WMRBITBLT_PX;
+
+
+/* Index 23 U_WMRSTRETCHBLT WMF manual 2.3.1.5 */
+/** WMF manual 2.3.1.5
+
+ This is a variable structure the core/invariant part extends to xSrc.
+
+ if RecordSize == ((xb) + 3) then there is no bitmap and use the _NOPX form, otherwise use the _PX form
+ Use Macro U_TEST_NOPX2.
+*/
+
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ uint16_t rop3w[2]; //!< reassemble/store the Ternary raster operation rop3 value using rop3w, the 32 bit value is not aligned.
+ int16_t hSrc; //!< Height in logical units of Src rect
+ int16_t wSrc; //!< Wdith in logical units of Dst rect
+ int16_t ySrc; //!< in logical units (UL corner of Src rect)
+ int16_t xSrc; //!< in logical units (UL corner of Src rect)
+ int16_t ignore; //!< ignored
+ int16_t hDst; //!< Height in logical units of Dst rect
+ int16_t wDst; //!< Wdith in logical units of Dst rect
+ int16_t yDst; //!< in logical units (UL corner of Dst rect)
+ int16_t xDst; //!< in logical units (UL corner of Dst rect)
+} U_WMRSTRETCHBLT_NOPX;
+
+
+/* Index 23 U_WMRSTRETCHBLT WMF manual 2.3.1.5 */
+/** WMF manual 2.3.1.5
+
+ This is a variable structure the core/invariant part extends to xSrc.
+
+ if RecordSize == ((xb) + 3) then there is no bitmap and use the _NOPX form, otherwise use the _PX form
+ Use Macro U_TEST_NOPX2.
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ uint16_t rop3w[2]; //!< reassemble/store the Ternary raster operation rop3 value using rop3w, the 32 bit value is not aligned.
+ int16_t hSrc; //!< Height in logical units of Src rect
+ int16_t wSrc; //!< Wdith in logical units of Dst rect
+ int16_t ySrc; //!< in logical units (UL corner of Src rect)
+ int16_t xSrc; //!< in logical units (UL corner of Src rect)
+ int16_t hDst; //!< Height in logical units of Dst rect
+ int16_t wDst; //!< Wdith in logical units of Dst rect
+ int16_t yDst; //!< in logical units (UL corner of Dst rect)
+ int16_t xDst; //!< in logical units (UL corner of Dst rect)
+ U_BITMAP16 bitmap; //!< Src bitmap
+} U_WMRSTRETCHBLT_PX;
+
+/* Index 24 U_WMRPOLYGON WMF manual 2.3.3.15
+ Index 25 U_WMRPOLYLINE WMF manual 2.3.3.14
+*/
+/** WMF manual 2.3.3.15
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ int16_t nPoints; //!< Number of points in aPoints
+ U_POINT16 aPoints[1]; //!< Array of points
+} U_WMRPOLYGON,
+ U_WMRPOLYLINE; //!< WMF manual 2.3.3.14
+
+/* Index 26 U_WMRESCAPE WMF manual 2.3.6.1 */
+/** WMF manual 2.3.6.1
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ uint16_t eFunc; //!< Escape function
+ uint16_t nBytes; //!< bytes in the data array
+ uint8_t Data[1]; //!< data array
+} U_WMRESCAPE;
+
+/* Index 27 U_WMRRESTOREDC WMF manual 2.3.5.10 */
+/** WMF manual 2.3.5.10
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ int16_t DC; //!< DC to restore (negative is relative to current, positive is absolute)
+} U_WMRRESTOREDC;
+
+/* Index 28 U_WMRFILLREGION WMF manual 2.3.3.6 */
+/** WMF manual 2.3.3.6
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ uint16_t Region; //!< Index of region to fill in object table
+ uint16_t Brush; //!< Index of brush to use in object table
+} U_WMRFILLREGION;
+
+/* Index 29 U_WMRFRAMEREGION WMF manual 2.3.3.8 */
+/** WMF manual 2.3.3.8
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ uint16_t Region; //!< Index of region to frame in object table
+ uint16_t Brush; //!< Index of brush to use in frame in object table
+ int16_t Height; //!< in logical units (of frame)
+ int16_t Width; //!< in logical units (of frame)
+} U_WMRFRAMEREGION;
+
+/* Index 2A U_WMRINVERTREGION WMF manual 2.3.3.9
+ Index 2B U_WMRPAINTREGION WMF manual 2.3.3.11
+ Index 2C U_WMRSELECTCLIPREGION WMF manual 2.3.4.9
+ Index 2D U_WMRSELECTOBJECT WMF manual 2.3.4.10
+ Index 34 U_WMRSELECTPALETTE WMF manual 2.3.4.11
+ Index 39 U_WMRRESIZEPALETTE WMF manual 2.3.5.9
+ Index F0 U_WMRDELETEOBJECT WMF manual 2.3.4.7
+*/
+/** WMF manual 2.3.3.9
+invert region
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ uint16_t index; //!< (usually) index of region/object in object table
+} U_WMRINVERTREGION,
+ U_WMRPAINTREGION, //!< WMF manual 2.3.3.11, paint region
+ U_WMRSELECTCLIPREGION, //!< WMF manual 2.3.4.9, select as clip region
+ U_WMRSELECTOBJECT, //!< WMF manual 2.3.4.10, select object
+ U_WMRSELECTPALETTE, //!< WMF manual 2.3.4.11, select palette object
+ U_WMRRESIZEPALETTE, //!< WMF manual 2.3.5.9, resize the system palette to "index"
+ U_WMRDELETEOBJECT; //!< WMF manual 2.3.4.7, delete object
+
+/* Index 2E U_WMRSETTEXTALIGN WMF manual 2.3.5.24 See Index 02 */
+
+/* Index 2F U_WMRDRAWTEXT in GDI and Wine, not documented in WMF manual.
+ Index FE U_WMRCREATEBITMAP in GDI and Wine, not documented in WMF manual.
+ Index FD U_WMRCREATEBITMAPINDIRECT in GDI and Wine, not documented in WMF manual.
+
+ no documentation found, this part of these records, at least, must be correct */
+/** in GDI and Wine, not documented in WMF manual.
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+} U_WMRDRAWTEXT,
+ U_WMRCREATEBITMAPINDIRECT, //!< in GDI and Wine, not documented in WMF manual.
+ U_WMRCREATEBITMAP; //!< in GDI and Wine, not documented in WMF manual.
+
+/* Index 30 U_WMRCHORD WMF manual 2.3.3.2 See Index 1A */
+
+/* Index 31 U_WMRSETMAPPERFLAGS WMF manual 2.3.5.18 */
+/** WMF manual 2.3.5.18
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ uint16_t valuew[2]; //!< if 1 bit set font mapper selects only matching aspect fonts. reassemble/store the value using valuew, the 32 bit value is not aligned.
+} U_WMRSETMAPPERFLAGS;
+
+/* Index 32 U_WMREXTTEXTOUT WMF manual 2.3.3.5
+*/
+/** WMF manual 2.3.3.5
+
+ Variable size record. Optional fields which follow the struct fields are:
+
+ U_RECT16 Rect; Only present when U_ETO_OPAQUE or U_ETO_CLIPPED bits are set in Opts
+ uint8_t String; String to write, storage area must be 2n bytes.
+ int16_t Dx; Kerning information. Must have same number of entries as Length.
+ Dx is present when
+ 2*Size16_4[2] -14 - 2*((Length + 1)/2)) - 8*(Opts & (U_ETO_OPAQUE | U_ETO_CLIPPED)) == 2*Length
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ int16_t y; //!< in logical units (draw point)
+ int16_t x; //!< in logical units (draw point)
+ int16_t Length; //!< Stringlength in bytes
+ uint16_t Opts; //!< ExtTextOutOptions Flags
+} U_WMREXTTEXTOUT;
+
+/* Index 33 U_WMRSETDIBTODEV WMF manual 2.3.1.4 */
+/** WMF manual 2.3.1.4
+
+ Constant part of record is shown. It is followed by a DeviceIndependentBitmap Object
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ uint16_t cUsage; //!< ColorUsage Enumeration
+ uint16_t ScanCount; //!< Number of scan lines in Src
+ uint16_t StartScan; //!< First Scan line in Src
+ int16_t ySrc; //!< in logical units (UL corner of Src rect)
+ int16_t xSrc; //!< in logical units (UL corner of Src rect)
+ int16_t Height; //!< in logical units (of Src and Dst)
+ int16_t Width; //!< in logical units (of Src and Dst)
+ int16_t yDst; //!< in logical units (UL corner of Dst rect)
+ int16_t xDst; //!< in logical units (UL corner of Dst rect)
+ uint8_t dib[1]; //!< DeviceIndependentBitmap object
+} U_WMRSETDIBTODEV;
+
+/* Index 34 U_WMRSELECTPALETTE WMF manual 2.3.4.11 See Index 2A */
+
+/* Index 35 U_WMRREALIZEPALETTE WMF manual 2.3.5.8 See Index 00 */
+
+/* Index 36 U_WMRANIMATEPALETTE WMF manual 2.3.5.1
+ Index 37 U_WMRSETPALENTRIES WMF manual 2.3.5.19
+ Index F7 U_WMRCREATEPALETTE WMF manual 2.3.4.3
+*/
+/** WMF manual 2.3.5.1
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ U_PALETTE Palette; //!< Palette object
+} U_WMRANIMATEPALETTE,
+ U_WMRSETPALENTRIES, //!< WMF manual 2.3.5.19
+ U_WMRCREATEPALETTE; //!< WMF manual 2.3.4.3
+
+/* Index 38 U_WMRPOLYPOLYGON WMF manual 2.3.3.16 */
+/** WMF manual 2.3.3.16
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ U_POLYPOLYGON PPolygon; //!< PolyPolygon object (size is variable!)
+} U_WMRPOLYPOLYGON;
+
+/* Index 39 U_WMRRESIZEPALETTE WMF manual 2.3.5.9 See Index 2A */
+
+/* Index 40 U_WMRDIBBITBLT WMF manual 2.3.1.2
+*/
+/** WMF manual 2.3.1.2
+
+ The PX form is a variable structure the core/invariant part extends to xDst, and that is
+ followed by a DeviceInvariantBitmap object which starts at "dib".
+ The NOPX form is a constant structure.
+
+ if RecordSize == ((xb) + 3) then there is no bitmap and use the _NOPX form, otherwise use the _PX form
+ Use Macro U_TEST_NOPX2.
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ uint16_t rop3w[2]; //!< reassemble/store the Ternary raster operation rop3 value using rop3w, the 32 bit value is not aligned.
+ int16_t ySrc; //!< in logical units (UL corner of Src rect)
+ int16_t xSrc; //!< in logical units (UL corner of Src rect)
+ uint16_t ignore; //!< ignore
+ int16_t Height; //!< in logical units (of Src and Dst)
+ int16_t Width; //!< in logical units (of Src and Dst)
+ int16_t yDst; //!< in logical units (UL corner of Dst rect)
+ int16_t xDst; //!< in logical units (UL corner of Dst rect)
+} U_WMRDIBBITBLT_NOPX;
+
+/** WMF manual 2.3.1.2
+
+ The PX form is a variable structure the core/invariant part extends to xDst, and that is
+ followed by a DeviceInvariantBitmap object which starts at "dib".
+ The NOPX form is a constant structure.
+
+ if RecordSize == ((xb) + 3) then there is no bitmap and use the _NOPX form, otherwise use the _PX form
+ Use Macro U_TEST_NOPX2.
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ uint16_t rop3w[2]; //!< reassemble/store the Ternary raster operation rop3 value using rop3w, the 32 bit value is not aligned.
+ int16_t ySrc; //!< in logical units (UL corner of Src rect)
+ int16_t xSrc; //!< in logical units (UL corner of Src rect)
+ int16_t Height; //!< in logical units (of Src and Dst)
+ int16_t Width; //!< in logical units (of Src and Dst)
+ int16_t yDst; //!< in logical units (UL corner of Dst rect)
+ int16_t xDst; //!< in logical units (UL corner of Dst rect)
+ uint8_t dib[1]; //!< DeviceIndependentBitmap object
+} U_WMRDIBBITBLT_PX;
+
+/* Index 41 U_WMRDIBSTRETCHBLT WMF manual 2.3.1.3 */
+/** WMF manual 2.3.1.3
+
+ The PX form is a variable structure the core/invariant part extends to xDst, and that is
+ followed by a DeviceInvariantBitmap object which starts at "dib".
+ The NOPX form is a constant structure.
+
+ if RecordSize == ((xb) + 3) then there is no bitmap and use the _NOPX form, otherwise use the _PX form
+ Use Macro U_TEST_NOPX2.
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ uint16_t rop3w[2]; //!< reassemble/store the Ternary raster operation rop3 value using rop3w, the 32 bit value is not aligned.
+ int16_t hSrc; //!< in logical units (of Src)
+ int16_t wSrc; //!< in logical units (of Src)
+ int16_t ySrc; //!< in logical units (UL corner of Src rect)
+ int16_t xSrc; //!< in logical units (UL corner of Src rect)
+ uint16_t ignore; //!< ignore
+ int16_t hDst; //!< in logical units (of Dst)
+ int16_t wDst; //!< in logical units (of Dst)
+ int16_t yDst; //!< in logical units (UL corner of Dst rect)
+ int16_t xDst; //!< in logical units (UL corner of Dst rect)
+} U_WMRDIBSTRETCHBLT_NOPX;
+
+/** WMF manual 2.3.1.3
+
+ The PX form is a variable structure the core/invariant part extends to xDst, and that is
+ followed by a DeviceInvariantBitmap object which starts at "dib".
+ The NOPX form is a constant structure.
+
+ if RecordSize == ((xb) + 3) then there is no bitmap and use the _NOPX form, otherwise use the _PX form
+ Use Macro U_TEST_NOPX2.
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ uint16_t rop3w[2]; //!< reassemble/store the Ternary raster operation rop3 value using rop3w, the 32 bit value is not aligned.
+ int16_t hSrc; //!< in logical units (of Src)
+ int16_t wSrc; //!< in logical units (of Src)
+ int16_t ySrc; //!< in logical units (UL corner of Src rect)
+ int16_t xSrc; //!< in logical units (UL corner of Src rect)
+ int16_t hDst; //!< in logical units (of Dst)
+ int16_t wDst; //!< in logical units (of Dst)
+ int16_t yDst; //!< in logical units (UL corner of Dst rect)
+ int16_t xDst; //!< in logical units (UL corner of Dst rect)
+ uint8_t dib[1]; //!< DeviceIndependentBitmap object
+} U_WMRDIBSTRETCHBLT_PX;
+
+
+/* Index 42 U_WMRDIBCREATEPATTERNBRUSH WMF manual 2.3.4.8
+*/
+/** WMF manual 2.3.4.8
+
+ style cUsage Brush created
+ U_BS_SOLID like U_BS_DIBPATTERNPT
+ U_BS_NULL like U_BS_DIBPATTERNPT
+ U_BS_HATCHED like U_BS_DIBPATTERNPT
+ U_BS_DIBPATTERNPT ColorUsage enumer. U_BS_DIBPATTERNPT brush from DIB in Src
+ U_BS_PATTERN ColorUsage enumer. U_BS_PATTERN brush from Bitmap16 object in Src
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ uint16_t Style; //!< BrushStyle Enumeration
+ uint16_t cUsage; //!< See table above
+ uint8_t Src[1]; //!< DeviceIndependentBitmap or Bitmap16 object
+} U_WMRDIBCREATEPATTERNBRUSH;
+
+/* Index 43 U_WMRSTRETCHDIB WMF manual 2.3.1.6 */
+/** WMF manual 2.3.1.6
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ uint16_t rop3w[2]; //!< reassemble/store the Ternary raster operation rop3 value using rop3w, the 32 bit value is not aligned.
+ uint16_t cUsage; //!< ColorUsage Enumeration
+ int16_t hSrc; //!< in logical units (of Src)
+ int16_t wSrc; //!< in logical units (of Src)
+ int16_t ySrc; //!< in logical units (UL corner of Src rect)
+ int16_t xSrc; //!< in logical units (UL corner of Src rect)
+ int16_t hDst; //!< in logical units (of Dst)
+ int16_t wDst; //!< in logical units (of Dst)
+ int16_t yDst; //!< in logical units (UL corner of Dst rect)
+ int16_t xDst; //!< in logical units (UL corner of Dst rect)
+ uint8_t dib[1]; //!< DeviceIndependentBitmap object
+} U_WMRSTRETCHDIB;
+
+/* Index 48 U_WMREXTFLOODFILL WMF manual 2.3.3.4 See Index 19*/
+/* Index 4C U_WMR4C */
+/* Index 4D U_WMR4D */
+/* Index 4F U_WMR4F */
+/* Index 50 U_WMR50 */
+/* Index 52 U_WMR52 */
+/* Index 5E U_WMR5E */
+/* Index 5F U_WMR5F */
+/* Index 60 U_WMR60 */
+/* Index 61 U_WMR61 */
+/* Index 62 U_WMR62 */
+/* Index 63 U_WMR63 */
+/* Index 64 U_WMR64 */
+/* Index 65 U_WMR65 */
+/* Index 66 U_WMR66 */
+/* Index 67 U_WMR67 */
+/* Index 68 U_WMR68 */
+/* Index 69 U_WMR69 */
+/* Index 6A U_WMR6A */
+/* Index 6B U_WMR6B */
+/* Index 6C U_WMR6C */
+/* Index 6D U_WMR6D */
+/* Index 6E U_WMR6E */
+/* Index 6F U_WMR6F */
+/* Index 70 U_WMR70 */
+/* Index 71 U_WMR71 */
+/* Index 72 U_WMR72 */
+/* Index 73 U_WMR73 */
+/* Index 74 U_WMR74 */
+/* Index 75 U_WMR75 */
+/* Index 76 U_WMR76 */
+/* Index 77 U_WMR77 */
+/* Index 78 U_WMR78 */
+/* Index 79 U_WMR79 */
+/* Index 7A U_WMR7A */
+/* Index 7B U_WMR7B */
+/* Index 7C U_WMR7C */
+/* Index 7D U_WMR7D */
+/* Index 7E U_WMR7E */
+/* Index 7F U_WMR7F */
+/* Index 80 U_WMR80 */
+/* Index 81 U_WMR81 */
+/* Index 82 U_WMR82 */
+/* Index 83 U_WMR83 */
+/* Index 84 U_WMR84 */
+/* Index 85 U_WMR85 */
+/* Index 86 U_WMR86 */
+/* Index 87 U_WMR87 */
+/* Index 88 U_WMR88 */
+/* Index 89 U_WMR89 */
+/* Index 8A U_WMR8A */
+/* Index 8B U_WMR8B */
+/* Index 8C U_WMR8C */
+/* Index 8D U_WMR8D */
+/* Index 8E U_WMR8E */
+/* Index 8F U_WMR8F */
+/* Index 90 U_WMR90 */
+/* Index 91 U_WMR91 */
+/* Index 92 U_WMR92 */
+/* Index 93 U_WMR93 */
+/* Index 94 U_WMR94 */
+/* Index 95 U_WMR95 */
+/* Index 96 U_WMR96 */
+/* Index 97 U_WMR97 */
+/* Index 98 U_WMR98 */
+/* Index 99 U_WMR99 */
+/* Index 9A U_WMR9A */
+/* Index 9B U_WMR9B */
+/* Index 9C U_WMR9C */
+/* Index 9D U_WMR9D */
+/* Index 9E U_WMR9E */
+/* Index 9F U_WMR9F */
+/* Index A0 U_WMRA0 */
+/* Index A1 U_WMRA1 */
+/* Index A2 U_WMRA2 */
+/* Index A3 U_WMRA3 */
+/* Index A4 U_WMRA4 */
+/* Index A5 U_WMRA5 */
+/* Index A6 U_WMRA6 */
+/* Index A7 U_WMRA7 */
+/* Index A8 U_WMRA8 */
+/* Index A9 U_WMRA9 */
+/* Index AA U_WMRAA */
+/* Index AB U_WMRAB */
+/* Index AC U_WMRAC */
+/* Index AD U_WMRAD */
+/* Index AE U_WMRAE */
+/* Index AF U_WMRAF */
+/* Index B0 U_WMRB0 */
+/* Index B1 U_WMRB1 */
+/* Index B2 U_WMRB2 */
+/* Index B3 U_WMRB3 */
+/* Index B4 U_WMRB4 */
+/* Index B5 U_WMRB5 */
+/* Index B6 U_WMRB6 */
+/* Index B7 U_WMRB7 */
+/* Index B8 U_WMRB8 */
+/* Index B9 U_WMRB9 */
+/* Index BA U_WMRBA */
+/* Index BB U_WMRBB */
+/* Index BC U_WMRBC */
+/* Index BD U_WMRBD */
+/* Index BE U_WMRBE */
+/* Index BF U_WMRBF */
+/* Index C0 U_WMRC0 */
+/* Index C1 U_WMRC1 */
+/* Index C2 U_WMRC2 */
+/* Index C3 U_WMRC3 */
+/* Index C4 U_WMRC4 */
+/* Index C5 U_WMRC5 */
+/* Index C6 U_WMRC6 */
+/* Index C7 U_WMRC7 */
+/* Index C8 U_WMRC8 */
+/* Index C9 U_WMRC9 */
+/* Index CA U_WMRCA */
+/* Index CB U_WMRCB */
+/* Index CC U_WMRCC */
+/* Index CD U_WMRCD */
+/* Index CE U_WMRCE */
+/* Index CF U_WMRCF */
+/* Index D0 U_WMRD0 */
+/* Index D1 U_WMRD1 */
+/* Index D2 U_WMRD2 */
+/* Index D3 U_WMRD3 */
+/* Index D4 U_WMRD4 */
+/* Index D5 U_WMRD5 */
+/* Index D6 U_WMRD6 */
+/* Index D7 U_WMRD7 */
+/* Index D8 U_WMRD8 */
+/* Index D9 U_WMRD9 */
+/* Index DA U_WMRDA */
+/* Index DB U_WMRDB */
+/* Index DC U_WMRDC */
+/* Index DD U_WMRDD */
+/* Index DE U_WMRDE */
+/* Index DF U_WMRDF */
+/* Index E0 U_WMRE0 */
+/* Index E1 U_WMRE1 */
+/* Index E2 U_WMRE2 */
+/* Index E3 U_WMRE3 */
+/* Index E4 U_WMRE4 */
+/* Index E5 U_WMRE5 */
+/* Index E6 U_WMRE6 */
+/* Index E7 U_WMRE7 */
+/* Index E8 U_WMRE8 */
+/* Index E9 U_WMRE9 */
+/* Index EA U_WMREA */
+/* Index EB U_WMREB */
+/* Index EC U_WMREC */
+/* Index ED U_WMRED */
+/* Index EE U_WMREE */
+/* Index EF U_WMREF */
+/* Index F0 U_WMRDELETEOBJECT WMF manual 2.3.4.7 See Index 2A */
+/* Index F1 U_WMRF1 */
+/* Index F2 U_WMRF2 */
+/* Index F3 U_WMRF3 */
+/* Index F4 U_WMRF4 */
+/* Index F5 U_WMRF5 */
+
+/* Index F7 U_WMRCREATEPALETTE WMF manual 2.3.4.3 See Index 36*/
+
+/* Index F8 U_WMRF8 */
+/* Index F9 U_WMRCREATEPATTERNBRUSH WMF manual 2.3.4.4 */
+/** WMF manual 2.3.4.4
+
+ WARNING - U_WMRCREATEPATTERNBRUSH has been declared obsolete and application support is spotty -
+ use U_WMRDIBCREATEPATTERNBRUSH instead.
+
+ This record is peculiar...
+
+ After the core structure there is:
+
+ A truncated U_BITMAP16. Only the first 14 bytes are present, and the last 4 bytes (bits section) are ignored.
+ 18 zero bytes (reserved)
+ A pattern. The pattern is a byte array whose size is set by the fields in the U_BITMAP16 structure as follows:
+
+ (((Width * BitsPixel + 15) >> 4) << 1) * Height
+
+ brush created has style U_BS_PATTERN.
+
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+} U_WMRCREATEPATTERNBRUSH;
+
+/* Index FA U_WMRCREATEPENINDIRECT WMF manual 2.3.4.5 */
+/** WMF manual 2.3.4.5
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ U_PEN pen; //!< Pen Object
+} U_WMRCREATEPENINDIRECT;
+
+/* Index FB U_WMRCREATEFONTINDIRECT WMF manual 2.3.4.2 */
+/** WMF manual 2.3.4.2
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ U_FONT font; //!< Font Object
+} U_WMRCREATEFONTINDIRECT;
+
+/* Index FC U_WMRCREATEBRUSHINDIRECT WMF manual 2.3.4.1 */
+/** WMF manual 2.3.4.1
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ U_WLOGBRUSH brush; //!< WLogBrush Object
+} U_WMRCREATEBRUSHINDIRECT;
+
+/* Index FD U_WMRCREATEBITMAPINDIRECT in GDI and Wine, not in WMF manual, see index 2F */
+
+/* Index FE U_WMRCREATEBITMAP in GDI and Wine, not in WMF manual, see index 2F */
+
+/* Index FF U_WMRCREATEREGION WMF manual 2.3.4.6 */
+/** WMF manual 2.3.4.6
+*/
+typedef struct {
+ uint16_t Size16_4[2]; //!< Total number of 16bit words in record
+ uint8_t iType; //!< RecordType Enumeration
+ uint8_t xb; //!< Extra high order byte associated with record type
+ U_REGION region; //!< Region Object
+} U_WMRCREATEREGION;
+
+
+
+// ************************************************************************************************
+// Utility function structures
+
+/**
+ Storage for keeping track of properties of the growing WMF file as records are added.
+*/
+typedef struct {
+ FILE *fp; //!< Open file
+ size_t allocated; //!< Size of the buffer
+ size_t used; //!< Amount consumed
+ uint32_t records; //!< Number of records already contained
+ uint16_t ignore; //!< size padding,not used
+ uint32_t PalEntries; //!< Number of PalEntries (set from U_EMREOF)
+ uint32_t chunk; //!< Number of bytes to add when more space is needed
+ char *buf; //!< Buffer for constructing the EMF in memory
+ uint32_t largest; //!< Largest record size, in bytes (used by WMF, not by EMF)
+ uint32_t sumObjects; //!< Number of objects appended (used by WMF, not by EMF) [ also see wmf_highwater() ]
+} WMFTRACK;
+
+/**
+ The various create functions need a place to put their handles, these are stored in the table below.
+ We don't actually do anything much with these handles, that is up to whatever program finally plays back the WMF, but
+ we do need to keep track of the numbers so that they are not accidentally reused. (Also WMF files have rules
+ about how object handles must be numbered, for instance, the lowest possible number must always be used. These
+ are different from EMF object handles.) This structure is used for staying in conformance with these rules.
+
+ There are no stock objects in WMF files.
+*/
+typedef struct {
+ uint32_t *table; //!< Array Buffer for constructing the WMF in memory
+ size_t allocated; //!< Slots in the buffer
+ size_t chunk; //!< Number to add if a realloc is required
+ uint32_t lolimit; //!< Lowest unoccupied table slot, may be a hole created by a deleteobject.
+ uint32_t hilimit; //!< Highest table slot occupied (currently)
+ uint32_t peak; //!< Highest table slot occupied (ever)
+} WMFHANDLES;
+
+//! \cond
+// ************************************************************************************************
+// Prototypes (_set first, then _get)
+char *wmr_dup(const char *wmr);
+int wmf_start(const char *name, uint32_t initsize, uint32_t chunksize, WMFTRACK **wt);
+int uwmf_free(WMFTRACK **wt);
+int wmf_finish(WMFTRACK *wt);
+int wmf_append(U_METARECORD *rec, WMFTRACK *wt, int freerec);
+int wmf_header_append(U_METARECORD *rec,WMFTRACK *et, int freerec);
+int wmf_readdata(const char *filename, char **contents, size_t*length);
+#define wmf_fopen emf_fopen
+int wmf_highwater(uint32_t setval);
+int wmf_htable_create(uint32_t initsize, uint32_t chunksize, WMFHANDLES **wht);
+int wmf_htable_delete(uint32_t *ih, WMFHANDLES *wht);
+int wmf_htable_insert(uint32_t *ih, WMFHANDLES *wht);
+int wmf_htable_free(WMFHANDLES **wht);
+int16_t U_16_checksum(int16_t *buf, int count);
+int16_t *dx16_set( int32_t height, uint32_t weight, uint32_t members);
+uint32_t U_wmr_properties(uint32_t type);
+
+uint32_t U_wmr_size(const U_METARECORD *record);
+uint32_t U_wmr_values(int idx);
+const char *U_wmr_names(int idx);
+const char *U_wmr_escnames(int idx);
+
+void U_sanerect16(U_RECT16 rc, double *left, double *top, double *right, double *bottom);
+
+
+U_FONT *U_FONT_set(int16_t Height, int16_t Width, int16_t Escapement, int16_t Orientation,
+ int16_t Weight, uint8_t Italic, uint8_t Underline, uint8_t StrikeOut,
+ uint8_t CharSet, uint8_t OutPrecision, uint8_t ClipPrecision,
+ uint8_t Quality, uint8_t PitchAndFamily, char *FaceName);
+U_PLTNTRY U_PLTNTRY_set(U_COLORREF Color);
+U_PALETTE *U_PLTENTRY_set(uint16_t Start, uint16_t NumEntries, U_PLTNTRY *Entries);
+U_PEN U_PEN_set(uint16_t Style, uint16_t Width, U_COLORREF Color);
+U_RECT16 U_RECT16_set(U_POINT16 ul,U_POINT16 lr);
+U_BITMAP16 *U_BITMAP16_set(const int16_t Type, const int16_t Width, const int16_t Height,
+ const int16_t LineN, const uint8_t BitsPixel, const char *Bits);
+U_SCAN *U_SCAN_set(uint16_t count, uint16_t top, uint16_t bottom, uint16_t *ScanLines);
+U_REGION *U_REGION_set(int16_t Size, int16_t sCount, int16_t sMax, U_RECT16 sRect, uint16_t *aScans);
+U_WLOGBRUSH U_WLOGBRUSH_set(uint16_t Style, U_COLORREF Color, uint16_t Hatch);
+U_PAIRF *U_PAIRF_set(float x, float y);
+
+char *wdeleteobject_set(uint32_t *ihObject, WMFHANDLES *wht);
+char *wselectobject_set(uint32_t ihObject, WMFHANDLES *wht );
+char *wcreatepenindirect_set(uint32_t *ihPen, WMFHANDLES *wht, U_PEN pen);
+char *wcreatebrushindirect_set(uint32_t *ihBrush, WMFHANDLES *wht, U_WLOGBRUSH lb);
+char *wcreatedibpatternbrush_srcdib_set(uint32_t *ihBrush, WMFHANDLES *wht,
+ uint32_t iUsage, const U_BITMAPINFO *Bmi, uint32_t cbPx, const char *Px);
+char *wcreatedibpatternbrush_srcbm16_set(uint32_t *ihBrush, WMFHANDLES *wht,
+ uint32_t iUsage, const U_BITMAP16 *Bm16);
+char *wcreatepatternbrush_set(uint32_t *ihBrush, WMFHANDLES *wht, U_BITMAP16 *Bm16, char *Pattern);
+char *wcreatefontindirect_set(uint32_t *ihFont, WMFHANDLES *wht, U_FONT *uf);
+char *wcreatepalette_set(uint32_t *ihPal, WMFHANDLES *wht, U_PALETTE *up);
+char *wsetpaletteentries_set(uint32_t *ihPal, WMFHANDLES *wht, const U_PALETTE *Palletes);
+char *wcreateregion_set(uint32_t *ihReg, WMFHANDLES *wht, const U_REGION *Region);
+char *wbegin_path_set(void);
+char *wend_path_set(void);
+char *wlinecap_set(int32_t Type);
+char *wlinejoin_set(int32_t Type);
+char *wmiterlimit_set(int32_t limit);
+
+
+char *U_WMRHEADER_set(U_PAIRF *size,unsigned int dpi);
+char *U_WMREOF_set(void);
+char *U_WMRSETBKCOLOR_set(U_COLORREF Color);
+char *U_WMRSETBKMODE_set(uint16_t Mode);
+char *U_WMRSETMAPMODE_set(uint16_t Mode);
+char *U_WMRSETROP2_set(uint16_t Mode);
+char *U_WMRSETRELABS_set(void);
+char *U_WMRSETPOLYFILLMODE_set(uint16_t Mode);
+char *U_WMRSETSTRETCHBLTMODE_set(uint16_t Mode);
+char *U_WMRSETTEXTCHAREXTRA_set(uint16_t Mode);
+char *U_WMRSETTEXTCOLOR_set(U_COLORREF Color);
+char *U_WMRSETTEXTJUSTIFICATION_set(uint16_t Count, uint16_t Extra);
+char *U_WMRSETWINDOWORG_set(U_POINT16 coord);
+char *U_WMRSETWINDOWEXT_set(U_POINT16 extent);
+char *U_WMRSETVIEWPORTORG_set(U_POINT16 coord);
+char *U_WMRSETVIEWPORTEXT_set(U_POINT16 extent);
+char *U_WMROFFSETWINDOWORG_set(U_POINT16 offset);
+char *U_WMRSCALEWINDOWEXT_set(U_POINT16 Denom, U_POINT16 Num);
+char *U_WMROFFSETVIEWPORTORG_set(U_POINT16 offset);
+char *U_WMRSCALEVIEWPORTEXT_set(U_POINT16 Denom, U_POINT16 Num);
+char *U_WMRLINETO_set(U_POINT16 coord);
+char *U_WMRMOVETO_set(U_POINT16 coord);
+char *U_WMREXCLUDECLIPRECT_set(U_RECT16 rect);
+char *U_WMRINTERSECTCLIPRECT_set(U_RECT16 rect);
+char *U_WMRARC_set(U_POINT16 StartArc, U_POINT16 EndArc, U_RECT16 rect);
+char *U_WMRELLIPSE_set(U_RECT16 rect);
+char *U_WMRFLOODFILL_set(uint16_t Mode, U_COLORREF Color, U_POINT16 coord);
+char *U_WMRPIE_set(U_POINT16 Radial1, U_POINT16 Radial2, U_RECT16 rect);
+char *U_WMRRECTANGLE_set(U_RECT16 rect);
+char *U_WMRROUNDRECT_set(int16_t Width, int16_t Height, U_RECT16 rect);
+char *U_WMRPATBLT_set(U_POINT16 Dst, U_POINT16 cwh, uint32_t dwRop3);
+char *U_WMRSAVEDC_set(void);
+char *U_WMRSETPIXEL_set(U_COLORREF Color, U_POINT16 coord);
+char *U_WMROFFSETCLIPRGN_set(U_POINT16 offset);
+char *U_WMRTEXTOUT_set(U_POINT16 Dst, char *string);
+char *U_WMRBITBLT_set(U_POINT16 Dst, U_POINT16 cwh, U_POINT16 Src,
+ uint32_t dwRop3, const U_BITMAP16 *Bm16);
+char *U_WMRSTRETCHBLT_set(U_POINT16 Dst, U_POINT16 cDst, U_POINT16 Src,
+ U_POINT16 cSrc, uint32_t dwRop3, const U_BITMAP16 *Bm16);
+char *U_WMRPOLYGON_set(uint16_t Length, const U_POINT16 * Data);
+char *U_WMRPOLYLINE_set(uint16_t Length, const U_POINT16 * Data);
+char *U_WMRESCAPE_set(uint16_t Escape, uint16_t Length, const void *Data);
+char *U_WMRRESTOREDC_set(int16_t DC);
+char *U_WMRFILLREGION_set(uint16_t Region, uint16_t Brush);
+char *U_WMRFRAMEREGION_set(uint16_t Region, uint16_t Brush, int16_t Height, int16_t Width);
+char *U_WMRINVERTREGION_set(uint16_t Region);
+char *U_WMRPAINTREGION_set(uint16_t Region);
+char *U_WMRSELECTCLIPREGION_set(uint16_t Region);
+char *U_WMRSELECTOBJECT_set(uint16_t object);
+char *U_WMRSETTEXTALIGN_set(uint16_t Mode);
+char *U_WMRDRAWTEXT_set(void); /* in GDI and Wine, not in WMF manual. */
+char *U_WMRCHORD_set(U_POINT16 Radial1, U_POINT16 Radial2, U_RECT16 rect);
+char *U_WMRSETMAPPERFLAGS_set(uint32_t Mode);
+char *U_WMREXTTEXTOUT_set(U_POINT16 Dst, int16_t Length, uint16_t Opts, const char *string, int16_t *dx, U_RECT16 rect);
+char *U_WMRSETDIBTODEV_set(void);
+char *U_WMRSELECTPALETTE_set(uint16_t Palette);
+char *U_WMRREALIZEPALETTE_set(void);
+char *U_WMRANIMATEPALETTE_set(U_PALETTE *Palette);
+char *U_WMRSETPALENTRIES_set(const U_PALETTE *Palette);
+char *U_WMRPOLYPOLYGON_set(const uint16_t, const uint16_t *aPolyCounts, const U_POINT16 * points);
+char *U_WMRRESIZEPALETTE_set(uint16_t Palette);
+char *U_WMR3A_set(void);
+char *U_WMR3B_set(void);
+char *U_WMR3C_set(void);
+char *U_WMR3D_set(void);
+char *U_WMR3E_set(void);
+char *U_WMR3F_set(void);
+char *U_WMRDIBBITBLT_set(U_POINT16 Dst, U_POINT16 cwh, U_POINT16 Src,
+ uint32_t dwRop3, const U_BITMAPINFO * Bmi, uint32_t cbPx, const char *Px);
+char *U_WMRDIBSTRETCHBLT_set(U_POINT16 Dst, U_POINT16 cDst, U_POINT16 Src,
+ U_POINT16 cSrc, uint32_t dwRop3, const U_BITMAPINFO *Bmi, uint32_t cbPx, const char *Px);
+char *U_WMRDIBCREATEPATTERNBRUSH_set(const uint16_t Style, const uint16_t iUsage,
+ const U_BITMAPINFO *Bmi, uint32_t cbPx, const char *Px, const U_BITMAP16 *Bm16);
+char *U_WMRSTRETCHDIB_set(U_POINT16 Dest, U_POINT16 cDest, U_POINT16 Src, U_POINT16 cSrc,
+ const uint16_t cUsage, uint32_t dwRop3, const U_BITMAPINFO *Bmi, uint32_t cbPx, const char *Px);
+char *U_WMR44_set(void);
+char *U_WMR45_set(void);
+char *U_WMR46_set(void);
+char *U_WMR47_set(void);
+char *U_WMREXTFLOODFILL_set(uint16_t Mode, U_COLORREF Color, U_POINT16 coord);
+char *U_WMR49_set(void);
+char *U_WMR4A_set(void);
+char *U_WMR4B_set(void);
+char *U_WMR4C_set(void);
+char *U_WMR4D_set(void);
+char *U_WMR4E_set(void);
+char *U_WMR4F_set(void);
+char *U_WMR50_set(void);
+char *U_WMR51_set(void);
+char *U_WMRABORTDOC_set(void);
+char *U_WMR53_set(void);
+char *U_WMR54_set(void);
+char *U_WMR55_set(void);
+char *U_WMR56_set(void);
+char *U_WMR57_set(void);
+char *U_WMR58_set(void);
+char *U_WMR59_set(void);
+char *U_WMR5A_set(void);
+char *U_WMR5B_set(void);
+char *U_WMR5C_set(void);
+char *U_WMR5D_set(void);
+char *U_WMR5E_set(void);
+char *U_WMR5F_set(void);
+char *U_WMR60_set(void);
+char *U_WMR61_set(void);
+char *U_WMR62_set(void);
+char *U_WMR63_set(void);
+char *U_WMR64_set(void);
+char *U_WMR65_set(void);
+char *U_WMR66_set(void);
+char *U_WMR67_set(void);
+char *U_WMR68_set(void);
+char *U_WMR69_set(void);
+char *U_WMR6A_set(void);
+char *U_WMR6B_set(void);
+char *U_WMR6C_set(void);
+char *U_WMR6D_set(void);
+char *U_WMR6E_set(void);
+char *U_WMR6F_set(void);
+char *U_WMR70_set(void);
+char *U_WMR71_set(void);
+char *U_WMR72_set(void);
+char *U_WMR73_set(void);
+char *U_WMR74_set(void);
+char *U_WMR75_set(void);
+char *U_WMR76_set(void);
+char *U_WMR77_set(void);
+char *U_WMR78_set(void);
+char *U_WMR79_set(void);
+char *U_WMR7A_set(void);
+char *U_WMR7B_set(void);
+char *U_WMR7C_set(void);
+char *U_WMR7D_set(void);
+char *U_WMR7E_set(void);
+char *U_WMR7F_set(void);
+char *U_WMR80_set(void);
+char *U_WMR81_set(void);
+char *U_WMR82_set(void);
+char *U_WMR83_set(void);
+char *U_WMR84_set(void);
+char *U_WMR85_set(void);
+char *U_WMR86_set(void);
+char *U_WMR87_set(void);
+char *U_WMR88_set(void);
+char *U_WMR89_set(void);
+char *U_WMR8A_set(void);
+char *U_WMR8B_set(void);
+char *U_WMR8C_set(void);
+char *U_WMR8D_set(void);
+char *U_WMR8E_set(void);
+char *U_WMR8F_set(void);
+char *U_WMR90_set(void);
+char *U_WMR91_set(void);
+char *U_WMR92_set(void);
+char *U_WMR93_set(void);
+char *U_WMR94_set(void);
+char *U_WMR95_set(void);
+char *U_WMR96_set(void);
+char *U_WMR97_set(void);
+char *U_WMR98_set(void);
+char *U_WMR99_set(void);
+char *U_WMR9A_set(void);
+char *U_WMR9B_set(void);
+char *U_WMR9C_set(void);
+char *U_WMR9D_set(void);
+char *U_WMR9E_set(void);
+char *U_WMR9F_set(void);
+char *U_WMRA0_set(void);
+char *U_WMRA1_set(void);
+char *U_WMRA2_set(void);
+char *U_WMRA3_set(void);
+char *U_WMRA4_set(void);
+char *U_WMRA5_set(void);
+char *U_WMRA6_set(void);
+char *U_WMRA7_set(void);
+char *U_WMRA8_set(void);
+char *U_WMRA9_set(void);
+char *U_WMRAA_set(void);
+char *U_WMRAB_set(void);
+char *U_WMRAC_set(void);
+char *U_WMRAD_set(void);
+char *U_WMRAE_set(void);
+char *U_WMRAF_set(void);
+char *U_WMRB0_set(void);
+char *U_WMRB1_set(void);
+char *U_WMRB2_set(void);
+char *U_WMRB3_set(void);
+char *U_WMRB4_set(void);
+char *U_WMRB5_set(void);
+char *U_WMRB6_set(void);
+char *U_WMRB7_set(void);
+char *U_WMRB8_set(void);
+char *U_WMRB9_set(void);
+char *U_WMRBA_set(void);
+char *U_WMRBB_set(void);
+char *U_WMRBC_set(void);
+char *U_WMRBD_set(void);
+char *U_WMRBE_set(void);
+char *U_WMRBF_set(void);
+char *U_WMRC0_set(void);
+char *U_WMRC1_set(void);
+char *U_WMRC2_set(void);
+char *U_WMRC3_set(void);
+char *U_WMRC4_set(void);
+char *U_WMRC5_set(void);
+char *U_WMRC6_set(void);
+char *U_WMRC7_set(void);
+char *U_WMRC8_set(void);
+char *U_WMRC9_set(void);
+char *U_WMRCA_set(void);
+char *U_WMRCB_set(void);
+char *U_WMRCC_set(void);
+char *U_WMRCD_set(void);
+char *U_WMRCE_set(void);
+char *U_WMRCF_set(void);
+char *U_WMRD0_set(void);
+char *U_WMRD1_set(void);
+char *U_WMRD2_set(void);
+char *U_WMRD3_set(void);
+char *U_WMRD4_set(void);
+char *U_WMRD5_set(void);
+char *U_WMRD6_set(void);
+char *U_WMRD7_set(void);
+char *U_WMRD8_set(void);
+char *U_WMRD9_set(void);
+char *U_WMRDA_set(void);
+char *U_WMRDB_set(void);
+char *U_WMRDC_set(void);
+char *U_WMRDD_set(void);
+char *U_WMRDE_set(void);
+char *U_WMRDF_set(void);
+char *U_WMRE0_set(void);
+char *U_WMRE1_set(void);
+char *U_WMRE2_set(void);
+char *U_WMRE3_set(void);
+char *U_WMRE4_set(void);
+char *U_WMRE5_set(void);
+char *U_WMRE6_set(void);
+char *U_WMRE7_set(void);
+char *U_WMRE8_set(void);
+char *U_WMRE9_set(void);
+char *U_WMREA_set(void);
+char *U_WMREB_set(void);
+char *U_WMREC_set(void);
+char *U_WMRED_set(void);
+char *U_WMREE_set(void);
+char *U_WMREF_set(void);
+char *U_WMRDELETEOBJECT_set(uint16_t object);
+char *U_WMRF1_set(void);
+char *U_WMRF2_set(void);
+char *U_WMRF3_set(void);
+char *U_WMRF4_set(void);
+char *U_WMRF5_set(void);
+char *U_WMRF6_set(void);
+char *U_WMRCREATEPALETTE_set(U_PALETTE *Palette);
+char *U_WMRF8_set(void);
+char *U_WMRCREATEPATTERNBRUSH_set(U_BITMAP16 *Bm16, char *Pattern);
+char *U_WMRCREATEPENINDIRECT_set(U_PEN pen);
+char *U_WMRCREATEFONTINDIRECT_set(U_FONT *font);
+char *U_WMRCREATEBRUSHINDIRECT_set(U_WLOGBRUSH brush);
+char *U_WMRCREATEBITMAPINDIRECT_set(void); /* in GDI and Wine, not in WMF manual. */
+char *U_WMRCREATEBITMAP_set(void); /* in GDI and Wine, not in WMF manual. */
+char *U_WMRCREATEREGION_set(const U_REGION *region);
+
+int16_t *dx16_get( int32_t height, uint32_t weight, uint32_t members);
+size_t U_WMRRECSAFE_get(const char *contents, const char *blimit);
+int wmfheader_get(const char *contents, const char *blimit, U_WMRPLACEABLE *Placeable, U_WMRHEADER *Header);
+int wmr_arc_points(U_RECT16 rclBox, U_POINT16 ArcStart, U_POINT16 ArcEnd,
+ int *f1, int f2, U_PAIRF *center, U_PAIRF *start, U_PAIRF *end, U_PAIRF *size );
+void U_BITMAPINFOHEADER_get(const char *Bmih, uint32_t *Size, int32_t *Width, int32_t *Height,
+ uint32_t *Planes, uint32_t *BitCount, uint32_t *Compression, uint32_t *SizeImage,
+ int32_t *XPelsPerMeter, int32_t *YPelsPerMeter, uint32_t *ClrUsed, uint32_t *ClrImportant);
+void U_BITMAPCOREHEADER_get(const char *BmiCh, uint32_t *Size, int32_t *Width, int32_t *Height, int32_t *BitCount);
+int wget_DIB_params(const char *dib, const char **px, const U_RGBQUAD **ct, uint32_t *numCt,
+ int32_t *width, int32_t *height, int32_t *colortype, int32_t *invert);
+int U_WMREOF_get(const char *contents);
+int U_WMRSETBKCOLOR_get(const char *contents, U_COLORREF *Color);
+int U_WMRSETBKMODE_get(const char *contents, uint16_t *Mode);
+int U_WMRSETMAPMODE_get(const char *contents, uint16_t *Mode);
+int U_WMRSETROP2_get(const char *contents, uint16_t *Mode);
+int U_WMRSETRELABS_get(const char *contents);
+int U_WMRSETPOLYFILLMODE_get(const char *contents, uint16_t *Mode);
+int U_WMRSETSTRETCHBLTMODE_get(const char *contents, uint16_t *Mode);
+int U_WMRSETTEXTCHAREXTRA_get(const char *contents, uint16_t *Mode);
+int U_WMRSETTEXTCOLOR_get(const char *contents, U_COLORREF *Color);
+int U_WMRSETTEXTJUSTIFICATION_get(const char *contents, uint16_t *Count, uint16_t *Extra);
+int U_WMRSETWINDOWORG_get(const char *contents, U_POINT16 * coord);
+int U_WMRSETWINDOWEXT_get(const char *contents, U_POINT16 * extent);
+int U_WMRSETVIEWPORTORG_get(const char *contents, U_POINT16 * coord);
+int U_WMRSETVIEWPORTEXT_get(const char *contents, U_POINT16 * extent);
+int U_WMROFFSETWINDOWORG_get(const char *contents, U_POINT16 * offset);
+int U_WMRSCALEWINDOWEXT_get(const char *contents, U_POINT16 * Denom, U_POINT16 * Num);
+int U_WMROFFSETVIEWPORTORG_get(const char *contents, U_POINT16 * offset);
+int U_WMRSCALEVIEWPORTEXT_get(const char *contents, U_POINT16 * Denom, U_POINT16 * Num);
+int U_WMRLINETO_get(const char *contents, U_POINT16 * coord);
+int U_WMRMOVETO_get(const char *contents, U_POINT16 * coord);
+int U_WMREXCLUDECLIPRECT_get(const char *contents, U_RECT16 * rect);
+int U_WMRINTERSECTCLIPRECT_get(const char *contents, U_RECT16 * rect);
+int U_WMRARC_get(const char *contents, U_POINT16 * StartArc, U_POINT16 * EndArc, U_RECT16 * rect);
+int U_WMRELLIPSE_get(const char *contents, U_RECT16 * rect);
+int U_WMRFLOODFILL_get(const char *contents, uint16_t *Mode, U_COLORREF *Color, U_POINT16 * coord);
+int U_WMRPIE_get(const char *contents, U_POINT16 * Radial1, U_POINT16 * Radial2, U_RECT16 * rect);
+int U_WMRRECTANGLE_get(const char *contents, U_RECT16 * rect);
+int U_WMRROUNDRECT_get(const char *contents, int16_t *Width, int16_t *Height, U_RECT16 * rect);
+int U_WMRPATBLT_get(const char *contents, U_POINT16 * Dst, U_POINT16 * cwh, uint32_t *dwRop3);
+int U_WMRSAVEDC_get(const char *contents);
+int U_WMRSETPIXEL_get(const char *contents, U_COLORREF *Color, U_POINT16 * coord);
+int U_WMROFFSETCLIPRGN_get(const char *contents, U_POINT16 * offset);
+int U_WMRTEXTOUT_get(const char *contents, U_POINT16 * Dst, int16_t *Length, const char **string);
+int U_WMRBITBLT_get(const char *contents, U_POINT16 * Dst, U_POINT16 * cwh, U_POINT16 * Src, uint32_t *dwRop3, U_BITMAP16 *Bm16, const char **px);
+int U_WMRSTRETCHBLT_get(const char *contents, U_POINT16 * Dst, U_POINT16 * cDst, U_POINT16 * Src, U_POINT16 * cSrc, uint32_t *dwRop3, U_BITMAP16 *Bm16, const char **px);
+int U_WMRPOLYGON_get(const char *contents, uint16_t *Length, const char **Data);
+int U_WMRPOLYLINE_get(const char *contents, uint16_t *Length, const char **Data);
+int U_WMRESCAPE_get(const char *contents, uint16_t *Escape, uint16_t *Length, const char **Data);
+int U_WMRRESTOREDC_get(const char *contents, int16_t *DC);
+int U_WMRFILLREGION_get(const char *contents, uint16_t *Region, uint16_t *Brush);
+int U_WMRFRAMEREGION_get(const char *contents, uint16_t *Region, uint16_t *Brush, int16_t *Height, int16_t *Width);
+int U_WMRINVERTREGION_get(const char *contents, uint16_t *Region);
+int U_WMRPAINTREGION_get(const char *contents, uint16_t *Region);
+int U_WMRSELECTCLIPREGION_get(const char *contents, uint16_t *Region);
+int U_WMRSELECTOBJECT_get(const char *contents, uint16_t *Object);
+int U_WMRSETTEXTALIGN_get(const char *contents, uint16_t *Mode);
+int U_WMRDRAWTEXT_get(void); /* in GDI and Wine, not in WMF manual. */
+int U_WMRCHORD_get(const char *contents, U_POINT16 * Radial1, U_POINT16 * Radial2, U_RECT16 * rect);
+int U_WMRSETMAPPERFLAGS_get(const char *contents, uint32_t *Mode);
+int U_WMREXTTEXTOUT_get(const char *contents, U_POINT16 * Dst, int16_t *Length, uint16_t *Opts, const char **string, const int16_t **dx, U_RECT16 * rect);
+int U_WMRSETDIBTODEV_get(const char *contents, U_POINT16 * Dst, U_POINT16 * cwh, U_POINT16 * Src, uint16_t *cUsage, uint16_t *ScanCount, uint16_t *StartScan, const char **dib);
+int U_WMRSELECTPALETTE_get(const char *contents, uint16_t *Palette);
+int U_WMRREALIZEPALETTE_get(const char *contents);
+int U_WMRANIMATEPALETTE_get(const char *contents, U_PALETTE *Palette, const char **PalEntries);
+int U_WMRSETPALENTRIES_get(const char *contents, U_PALETTE *Palette, const char **PalEntries);
+int U_WMRPOLYPOLYGON_get(const char *contents, uint16_t *nPolys, const uint16_t **aPolyCounts, const char **Points);
+int U_WMRRESIZEPALETTE_get(const char *contents, uint16_t *Palette);
+int U_WMR3A_get(void);
+int U_WMR3B_get(void);
+int U_WMR3C_get(void);
+int U_WMR3D_get(void);
+int U_WMR3E_get(void);
+int U_WMR3F_get(void);
+int U_WMRDIBBITBLT_get(const char *contents, U_POINT16 * Dst, U_POINT16 * cwh, U_POINT16 * Src, uint32_t *dwRop3, const char **dib);
+int U_WMRDIBSTRETCHBLT_get(const char *contents, U_POINT16 * Dst, U_POINT16 * cDst, U_POINT16 * Src, U_POINT16 * cSrc, uint32_t *dwRop3, const char **dib);
+int U_WMRDIBCREATEPATTERNBRUSH_get(const char *contents, uint16_t *Style, uint16_t *cUsage, const char **Bm16, const char **dib);
+int U_WMRSTRETCHDIB_get(const char *contents, U_POINT16 * Dst, U_POINT16 * cDst, U_POINT16 * Src, U_POINT16 * cSrc, uint16_t *cUsage, uint32_t *dwRop3, const char **dib);
+int U_WMR44_get(void);
+int U_WMR45_get(void);
+int U_WMR46_get(void);
+int U_WMR47_get(void);
+int U_WMREXTFLOODFILL_get(const char *contents, uint16_t *Mode, U_COLORREF *Color, U_POINT16 * coord);
+int U_WMR49_get(void);
+int U_WMR4A_get(void);
+int U_WMR4B_get(void);
+int U_WMR4C_get(void);
+int U_WMR4D_get(void);
+int U_WMR4E_get(void);
+int U_WMR4F_get(void);
+int U_WMR50_get(void);
+int U_WMR51_get(void);
+int U_WMRABORTDOC_get(void);
+int U_WMR53_get(void);
+int U_WMR54_get(void);
+int U_WMR55_get(void);
+int U_WMR56_get(void);
+int U_WMR57_get(void);
+int U_WMR58_get(void);
+int U_WMR59_get(void);
+int U_WMR5A_get(void);
+int U_WMR5B_get(void);
+int U_WMR5C_get(void);
+int U_WMR5D_get(void);
+int U_WMR5E_get(void);
+int U_WMR5F_get(void);
+int U_WMR60_get(void);
+int U_WMR61_get(void);
+int U_WMR62_get(void);
+int U_WMR63_get(void);
+int U_WMR64_get(void);
+int U_WMR65_get(void);
+int U_WMR66_get(void);
+int U_WMR67_get(void);
+int U_WMR68_get(void);
+int U_WMR69_get(void);
+int U_WMR6A_get(void);
+int U_WMR6B_get(void);
+int U_WMR6C_get(void);
+int U_WMR6D_get(void);
+int U_WMR6E_get(void);
+int U_WMR6F_get(void);
+int U_WMR70_get(void);
+int U_WMR71_get(void);
+int U_WMR72_get(void);
+int U_WMR73_get(void);
+int U_WMR74_get(void);
+int U_WMR75_get(void);
+int U_WMR76_get(void);
+int U_WMR77_get(void);
+int U_WMR78_get(void);
+int U_WMR79_get(void);
+int U_WMR7A_get(void);
+int U_WMR7B_get(void);
+int U_WMR7C_get(void);
+int U_WMR7D_get(void);
+int U_WMR7E_get(void);
+int U_WMR7F_get(void);
+int U_WMR80_get(void);
+int U_WMR81_get(void);
+int U_WMR82_get(void);
+int U_WMR83_get(void);
+int U_WMR84_get(void);
+int U_WMR85_get(void);
+int U_WMR86_get(void);
+int U_WMR87_get(void);
+int U_WMR88_get(void);
+int U_WMR89_get(void);
+int U_WMR8A_get(void);
+int U_WMR8B_get(void);
+int U_WMR8C_get(void);
+int U_WMR8D_get(void);
+int U_WMR8E_get(void);
+int U_WMR8F_get(void);
+int U_WMR90_get(void);
+int U_WMR91_get(void);
+int U_WMR92_get(void);
+int U_WMR93_get(void);
+int U_WMR94_get(void);
+int U_WMR95_get(void);
+int U_WMR96_get(void);
+int U_WMR97_get(void);
+int U_WMR98_get(void);
+int U_WMR99_get(void);
+int U_WMR9A_get(void);
+int U_WMR9B_get(void);
+int U_WMR9C_get(void);
+int U_WMR9D_get(void);
+int U_WMR9E_get(void);
+int U_WMR9F_get(void);
+int U_WMRA0_get(void);
+int U_WMRA1_get(void);
+int U_WMRA2_get(void);
+int U_WMRA3_get(void);
+int U_WMRA4_get(void);
+int U_WMRA5_get(void);
+int U_WMRA6_get(void);
+int U_WMRA7_get(void);
+int U_WMRA8_get(void);
+int U_WMRA9_get(void);
+int U_WMRAA_get(void);
+int U_WMRAB_get(void);
+int U_WMRAC_get(void);
+int U_WMRAD_get(void);
+int U_WMRAE_get(void);
+int U_WMRAF_get(void);
+int U_WMRB0_get(void);
+int U_WMRB1_get(void);
+int U_WMRB2_get(void);
+int U_WMRB3_get(void);
+int U_WMRB4_get(void);
+int U_WMRB5_get(void);
+int U_WMRB6_get(void);
+int U_WMRB7_get(void);
+int U_WMRB8_get(void);
+int U_WMRB9_get(void);
+int U_WMRBA_get(void);
+int U_WMRBB_get(void);
+int U_WMRBC_get(void);
+int U_WMRBD_get(void);
+int U_WMRBE_get(void);
+int U_WMRBF_get(void);
+int U_WMRC0_get(void);
+int U_WMRC1_get(void);
+int U_WMRC2_get(void);
+int U_WMRC3_get(void);
+int U_WMRC4_get(void);
+int U_WMRC5_get(void);
+int U_WMRC6_get(void);
+int U_WMRC7_get(void);
+int U_WMRC8_get(void);
+int U_WMRC9_get(void);
+int U_WMRCA_get(void);
+int U_WMRCB_get(void);
+int U_WMRCC_get(void);
+int U_WMRCD_get(void);
+int U_WMRCE_get(void);
+int U_WMRCF_get(void);
+int U_WMRD0_get(void);
+int U_WMRD1_get(void);
+int U_WMRD2_get(void);
+int U_WMRD3_get(void);
+int U_WMRD4_get(void);
+int U_WMRD5_get(void);
+int U_WMRD6_get(void);
+int U_WMRD7_get(void);
+int U_WMRD8_get(void);
+int U_WMRD9_get(void);
+int U_WMRDA_get(void);
+int U_WMRDB_get(void);
+int U_WMRDC_get(void);
+int U_WMRDD_get(void);
+int U_WMRDE_get(void);
+int U_WMRDF_get(void);
+int U_WMRE0_get(void);
+int U_WMRE1_get(void);
+int U_WMRE2_get(void);
+int U_WMRE3_get(void);
+int U_WMRE4_get(void);
+int U_WMRE5_get(void);
+int U_WMRE6_get(void);
+int U_WMRE7_get(void);
+int U_WMRE8_get(void);
+int U_WMRE9_get(void);
+int U_WMREA_get(void);
+int U_WMREB_get(void);
+int U_WMREC_get(void);
+int U_WMRED_get(void);
+int U_WMREE_get(void);
+int U_WMREF_get(void);
+int U_WMRDELETEOBJECT_get(const char *contents, uint16_t *Object);
+int U_WMRF1_get(void);
+int U_WMRF2_get(void);
+int U_WMRF3_get(void);
+int U_WMRF4_get(void);
+int U_WMRF5_get(void);
+int U_WMRF6_get(void);
+int U_WMRCREATEPALETTE_get(const char *contents, U_PALETTE *Palette, const char **PalEntries);
+int U_WMRF8_get(void);
+int U_WMRCREATEPATTERNBRUSH_get(const char *contents, U_BITMAP16 *Bm16, int *pasize, const char **Pattern);
+int U_WMRCREATEPENINDIRECT_get(const char *contents, U_PEN *pen);
+int U_WMRCREATEFONTINDIRECT_get(const char *contents, const char **font);
+int U_WMRCREATEBRUSHINDIRECT_get(const char *contents, const char **brush);
+int U_WMRCREATEBITMAPINDIRECT_get(void);
+int U_WMRCREATEBITMAP_get(void);
+int U_WMRCREATEREGION_get(const char *contents, const char **Region);
+//! \endcond
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UWMF_ */
diff --git a/src/3rdparty/libuemf/uwmf_endian.c b/src/3rdparty/libuemf/uwmf_endian.c
new file mode 100644
index 0000000..7a047c2
--- /dev/null
+++ b/src/3rdparty/libuemf/uwmf_endian.c
@@ -0,0 +1,1774 @@
+/**
+ @file uwmf_endian.c
+
+ @brief Functions for converting WMF records between Big Endian and Little Endian byte orders.
+*/
+
+/*
+File: uwmf_endian.c
+Version: 0.1.5
+Date: 28-MAY-2015
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2015 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h> /* for offsetof() */
+#include <string.h>
+#include "uwmf.h"
+#include "uwmf_endian.h"
+
+// hide almost everything in this file from Doxygen
+//! \cond
+/* Prototypes for functions used here and defined in uemf_endian.c, but which are not supposed
+to be used in end user code. */
+
+void U_swap2(void *ul, unsigned int count);
+void U_swap4(void *ul, unsigned int count);
+void bitmapinfo_swap(char *Bmi);
+
+/* **********************************************************************************************
+ These functions Swap standard objects used in the WMR records.
+ The low level ones do not append EOL.
+*********************************************************************************************** */
+
+/**
+ \brief Swap U_BITMAP16 object
+ \param b U_BITMAP16 object
+*/
+void bitmap16_swap(
+ char *b
+ ){
+ U_swap2(b,4); /* Type, Width, Height, WidthBytes */
+ /* Planes and BitsPixel are bytes, so no swap needed */
+ /* Bits[] pixel data should already be in order */
+}
+
+/**
+ \brief Swap a U_BRUSH object.
+ \param b U_BRUSH object.
+ style bColor bHatch
+ U_BS_SOLID ColorRef Object Not used (bytes present???)
+ U_BS_NULL ignored ignored (bytes present???).
+ U_BS_PATTERN ignored Bitmap16 object holding patern
+ U_BS_DIBPATTERNPT ColorUsage Enum DIB object
+ U_BS_HATCHED ColorRef Object HatchStyle Enumeration
+*/
+void brush_swap(
+ char *b,
+ int torev
+ ){
+ int Style;
+ if(torev){ Style = *(uint16_t *)(b + offsetof(U_BRUSH,Style)); }
+ U_swap2(b + offsetof(U_BRUSH,Style),1);
+ if(!torev){ Style = *(uint16_t *)(b + offsetof(U_BRUSH,Style)); }
+ /* Color is already in the right order */
+ switch(Style){
+ case U_BS_SOLID:
+ /* no/ignored data field */
+ break;
+ case U_BS_NULL:
+ /* no/ignored data field */
+ break;
+ case U_BS_PATTERN:
+ bitmap16_swap(b + offsetof(U_BRUSH,Data));
+ break;
+ case U_BS_DIBPATTERNPT:
+ bitmapinfo_swap(b + offsetof(U_BRUSH,Data));
+ break;
+ case U_BS_HATCHED:
+ /* no/ignored data field */
+ break;
+ }
+}
+
+/**
+ \brief Swap a U_FONT object from pointer.
+ \param lf U_FONT object
+*/
+void font_swap(
+ char *f
+ ){
+ U_swap2(f + offsetof(U_FONT,Height),5); /*Height, Width, Escapement, Orientation, Weight */
+ /* Other fields are single bytes */
+}
+
+/**
+ \brief Swap a pointer to a U_PALETTE object.
+ \param lp Pointer to a U_PALETTE object.
+*/
+void palette_swap(
+ char *p
+ ){
+ U_swap2(p + offsetof(U_PALETTE,Start),2); /* Start, NumEntries*/
+ /* PalEntries[1] is byte ordered, so no need to swap */
+}
+
+/**
+ \brief Swap a U_PEN object.
+ \param p U_PEN object
+*/
+void pen_swap(
+ char *p
+ ){
+ U_swap2(p + offsetof(U_PEN,Style),3); /* Style,Widthw[0],Widthw[1] */
+ /* Color already in order */
+}
+
+/* there are no
+ void rect16_ltrb_swap()
+ void rect16_brtl_swap()
+because rectangles are swapped using U_swap2 as an array of 4 int16 values.
+*/
+
+
+/**
+ \brief Swap U_REGION object
+ \param rect U_REGION object
+ \param torev
+ PARTIAL IMPLEMENTATION
+*/
+void region_swap(
+ char *reg,
+ int torev
+ ){
+ int Size;
+ if(torev){ Size = *(int16_t *)(reg + offsetof(U_REGION,Size)); }
+ U_swap2(reg,10); /* ignore1 through sRrect*/
+ if(!torev){ Size = *(int16_t *)(reg + offsetof(U_REGION,Size)); }
+ U_swap2(reg + U_SIZE_REGION, (Size - U_SIZE_REGION)/2); /* aScans */
+}
+
+
+/**
+ \brief Swap U_BITMAPCOREHEADER object
+ \param ch U_BITMAPCOREHEADER object
+*/
+void bitmapcoreheader_swap(
+ char *ch
+ ){
+ U_swap4(ch + offsetof(U_BITMAPCOREHEADER,Size_4), 1); /* Size_4, may not be aligned */
+ U_swap2(ch + offsetof(U_BITMAPCOREHEADER,Width),4); /* Width, Height, Planes, BitCount, */
+}
+
+/** LogBrushW Object WMF PDF 2.2.2.10
+ \brief Swap a U_WLOGBRUSH object.
+ \param lb U_WLOGBRUSH object.
+
+ style Color Hatch
+ U_BS_SOLID ColorRef Object Not used (bytes present???)
+ U_BS_NULL ignored ignored (bytes present???).
+ U_BS_PATTERN ignored not used (Action is not strictly defined)
+ U_BS_DIBPATTERN ignored not used (Action is not strictly defined)
+ U_BS_DIBPATTERNPT ignored not used (Action is not strictly defined)
+ U_BS_HATCHED ColorRef Object HatchStyle Enumeration
+*/
+void wlogbrush_swap(
+ char *lb
+ ){
+ U_swap2(lb + offsetof(U_WLOGBRUSH,Style),1);
+ /* Color is already in order */
+ U_swap2(lb + offsetof(U_WLOGBRUSH,Hatch),1);
+}
+
+/**
+ \brief Swap U_POLYPOLY object from pointer
+ \param pp PU_POLYPOLY object
+*/
+void polypolygon_swap(
+ char *pp,
+ int torev
+ ){
+ int i,totPoints;
+ uint16_t nPolys;
+ uint16_t *aPolyCounts;
+ if(torev){ nPolys = *(uint16_t *)(pp + offsetof(U_POLYPOLYGON, nPolys)); }
+ U_swap2(pp + offsetof(U_POLYPOLYGON, nPolys),1);
+ if(!torev){ nPolys = *(uint16_t *)(pp + offsetof(U_POLYPOLYGON, nPolys)); }
+ aPolyCounts = (uint16_t *)(pp + offsetof(U_POLYPOLYGON, aPolyCounts));
+ if(torev){
+ for(totPoints=0,i=0;i<nPolys; i++){ totPoints += aPolyCounts[i]; }
+ }
+ U_swap2(aPolyCounts,nPolys);
+ if(!torev){
+ for(totPoints=0,i=0;i<nPolys; i++){ totPoints += aPolyCounts[i]; }
+ }
+ U_swap2(&(aPolyCounts[nPolys]),2*totPoints); /* 2 coords/ point */
+}
+
+/**
+ \brief Swap U_SCAN object
+ \param pp U_SCAN object
+*/
+void scan_swap(
+ char *sc,
+ int torev
+ ){
+ int count;
+ if(torev){ count = *(uint16_t *)sc; }
+ U_swap2(sc,3); /*count, top, bottom */
+ if(!torev){ count = *(uint16_t *)sc; }
+ U_swap2(sc + offsetof(U_SCAN,ScanLines),count);
+}
+
+/**
+ \brief Swap a summary of a DIB header
+ A DIB header in an WMF may be either a BitmapCoreHeader or BitmapInfoHeader.
+ \param dh void pointer to DIB header
+*/
+void dibheader_swap(
+ char *dh,
+ int torev
+ ){
+ int Size;
+ memcpy(&Size, dh, 4); /* may not be aligned */
+ if(!torev)U_swap4(&Size,1);
+ if(Size == 0xC){
+ bitmapcoreheader_swap(dh);
+ }
+ else {
+ bitmapinfo_swap(dh);
+ }
+}
+
+/**
+ \brief Swap WMF header object
+ \param head uint8_t pointer to header
+ \returns size of entire header structure
+
+ If the header is preceded by a placeable struture, Swap that as well.
+*/
+int wmfheader_swap(
+ char *contents,
+ int torev
+ ){
+ uint32_t Key,Size16w;
+ int size=0;
+ Key=*(uint32_t *)(contents + offsetof(U_WMRPLACEABLE,Key));
+ if(!torev)U_swap4(&Key,1);
+ if(Key == 0x9AC6CDD7){
+ U_swap4(contents + offsetof(U_WMRPLACEABLE,Key ),1);
+ U_swap2(contents + offsetof(U_WMRPLACEABLE,HWmf ),1);
+ U_swap2(contents + offsetof(U_WMRPLACEABLE,Dst ),4);
+ U_swap2(contents + offsetof(U_WMRPLACEABLE,Inch ),1);
+ U_swap4(contents + offsetof(U_WMRPLACEABLE,Reserved),1);
+ U_swap2(contents + offsetof(U_WMRPLACEABLE,Checksum),1);
+ contents += U_SIZE_WMRPLACEABLE;
+ size += U_SIZE_WMRPLACEABLE;
+ }
+ if(torev){ Size16w = *(uint16_t *)(contents + offsetof(U_WMRHEADER,Size16w)); }
+ U_swap2(contents + offsetof(U_WMRHEADER,Size16w),2);/* Size16w, Version */
+ if(!torev){ Size16w = *(uint16_t *)(contents + offsetof(U_WMRHEADER,Size16w)); }
+ U_swap4(contents + offsetof(U_WMRHEADER,Sizew ),1);/* Sizew */
+ U_swap2(contents + offsetof(U_WMRHEADER,nObjects),1);/* nObjects */
+ U_swap4(contents + offsetof(U_WMRHEADER,maxSize ),1);/* maxSize */
+ U_swap2(contents + offsetof(U_WMRHEADER,nMembers),1);/* nMembers */
+ size += 2*Size16w;
+ return(size);
+}
+
+
+
+/* **********************************************************************************************
+These functions contain shared code used by various U_WMR*_Swap functions. These should NEVER be called
+by end user code and to further that end prototypes are NOT provided and they are hidden from Doxygen.
+*********************************************************************************************** */
+
+/* Size16 EVERY record type should call this, directly or indirectly*/
+void U_WMRCORE_SIZE16_swap(char *record, int torev){
+ UNUSED_PARAMETER(torev);
+ U_swap4(record, 1); /* Size16_4 is at offset 0 in U_METARECORD */
+}
+
+
+/* Size16, move to data, Single 32bit followed by array of N16 U_POINT16 */
+void U_WMRCORE_U32_N16_swap(char *record, int N16, int torev){
+ int off=U_SIZE_METARECORD;
+ U_WMRCORE_SIZE16_swap(record, torev);
+ U_swap4(record + off, 1); off+=4;
+ U_swap2(record + off, N16);
+}
+
+/* Single 16bit nPoints followed by array of nPoints U_POINT16 */
+void U_WMRCORE_U16_N16_swap(char *record, int torev){
+ int nPoints;
+ U_WMRCORE_SIZE16_swap(record, torev);
+ if(torev){ nPoints = *(uint16_t *)(record + offsetof(U_WMRPOLYGON,nPoints)); }
+ U_swap2(record + offsetof(U_WMRPOLYGON,nPoints), 1);
+ if(!torev){ nPoints = *(uint16_t *)(record + offsetof(U_WMRPOLYGON,nPoints)); }
+ U_swap2(record + offsetof(U_WMRPOLYGON,aPoints), 2*nPoints);
+}
+
+/* all records that specify palette objects */
+void U_WMRCORE_PALETTE_swap(char *record, int torev){
+ UNUSED_PARAMETER(torev);
+ U_WMRCORE_SIZE16_swap(record, torev);
+ palette_swap(record + offsetof(U_WMRANIMATEPALETTE,Palette));
+}
+
+/* all records that have N int16 values, unconditionally swapped */
+void U_WMRCORE_N16_swap(char *record, int N16, int torev){
+ U_WMRCORE_SIZE16_swap(record, torev);
+ U_swap2(record+U_SIZE_METARECORD, N16);
+}
+
+
+/* like floodfill */
+void U_WMRCORE_U16_CR_2U16_swap(char *record, int torev){
+ int off = U_SIZE_METARECORD;
+ U_WMRCORE_SIZE16_swap(record, torev);
+ U_swap2(record+off, 1); off += 2 + sizeof(U_COLORREF);
+ U_swap2(record+off, 2);
+}
+
+/* **********************************************************************************************
+These are the core WMR functions, each creates a particular type of record.
+All return these records via a char* pointer, which is NULL if the call failed.
+They are listed in order by the corresponding U_EMR_* index number.
+*********************************************************************************************** */
+
+/**
+ \brief Swap a pointer to a U_WMR_whatever record which has not been implemented.
+ \param name name of this type of record
+ \param contents pointer to a buffer holding all EMR records
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+void U_WMRNOTIMPLEMENTED_swap(char *record, int torev){
+ U_WMRCORE_SIZE16_swap(record, torev);
+}
+
+void U_WMREOF_swap(char *record, int torev){
+ U_WMRCORE_SIZE16_swap(record, torev);
+}
+
+void U_WMRSETBKCOLOR_swap(char *record, int torev){
+ U_WMRCORE_SIZE16_swap(record, torev);
+}
+
+void U_WMRSETBKMODE_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,1,torev);
+}
+
+void U_WMRSETMAPMODE_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,1,torev);
+}
+
+void U_WMRSETROP2_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,1,torev);
+}
+
+void U_WMRSETRELABS_swap(char *record, int torev){
+ U_WMRCORE_SIZE16_swap(record, torev);
+}
+
+void U_WMRSETPOLYFILLMODE_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,1,torev);
+}
+
+void U_WMRSETSTRETCHBLTMODE_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,1,torev);
+}
+
+void U_WMRSETTEXTCHAREXTRA_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,1,torev);
+}
+
+void U_WMRSETTEXTCOLOR_swap(char *record, int torev){
+ U_WMRCORE_SIZE16_swap(record, torev);
+}
+
+void U_WMRSETTEXTJUSTIFICATION_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,2,torev);
+}
+
+void U_WMRSETWINDOWORG_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,2,torev);
+}
+
+void U_WMRSETWINDOWEXT_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,2,torev);
+}
+
+void U_WMRSETVIEWPORTORG_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,2,torev);
+}
+
+void U_WMRSETVIEWPORTEXT_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,2,torev);
+}
+
+void U_WMROFFSETWINDOWORG_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,2,torev);
+}
+
+void U_WMRSCALEWINDOWEXT_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,4,torev);
+}
+
+void U_WMROFFSETVIEWPORTORG_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,2,torev);
+}
+
+void U_WMRSCALEVIEWPORTEXT_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,4,torev);
+}
+
+void U_WMRLINETO_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,2,torev);
+}
+
+void U_WMRMOVETO_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,2,torev);
+}
+
+void U_WMREXCLUDECLIPRECT_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,4,torev);
+}
+
+void U_WMRINTERSECTCLIPRECT_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,4,torev);
+}
+
+void U_WMRARC_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record, 8, torev);
+}
+
+void U_WMRELLIPSE_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,4,torev);
+}
+
+void U_WMRFLOODFILL_swap(char *record, int torev){
+ U_WMRCORE_U16_CR_2U16_swap(record, torev);
+}
+
+void U_WMRPIE_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record, 8, torev);
+}
+
+void U_WMRRECTANGLE_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,4,torev);
+}
+
+void U_WMRROUNDRECT_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,6,torev);
+}
+
+void U_WMRPATBLT_swap(char *record, int torev){
+ U_WMRCORE_U32_N16_swap(record,4,torev);
+}
+
+void U_WMRSAVEDC_swap(char *record, int torev){
+ U_WMRCORE_SIZE16_swap(record, torev);
+}
+
+void U_WMRSETPIXEL_swap(char *record, int torev){
+ int off = U_SIZE_METARECORD + sizeof(U_COLORREF);
+ U_WMRCORE_SIZE16_swap(record, torev);
+ U_swap2(record+off, 2);
+}
+
+void U_WMROFFSETCLIPRGN_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,2,torev);
+}
+
+void U_WMRTEXTOUT_swap(char *record, int torev){
+ int L2;
+ if(torev){ L2 = *(int16_t *)(record + U_SIZE_METARECORD); } /* Length field */
+ U_WMRCORE_N16_swap(record,1,torev); /* Length */
+ if(!torev){ L2 = *(int16_t *)(record + U_SIZE_METARECORD); } /* Length field */
+ /* string is in bytes, do not swap that */
+ U_swap2(record + U_SIZE_WMRTEXTOUT + L2, 2); /* y,x */
+}
+
+void U_WMRBITBLT_swap(char *record, int torev){
+ uint32_t Size16;
+ uint8_t xb;
+ memcpy(&Size16, record + offsetof(U_METARECORD,Size16_4), 4);
+ if(!torev)U_swap4(&Size16,1);
+ xb = *(uint8_t *)(record + offsetof(U_METARECORD,xb));
+ if(U_TEST_NOPX2(Size16,xb)){ /* no bitmap */
+ U_WMRCORE_U32_N16_swap(record,7,torev);
+ }
+ else { /* yes bitmap */
+ U_WMRCORE_U32_N16_swap(record,6,torev);
+ bitmap16_swap(record + offsetof(U_WMRBITBLT_PX,bitmap));
+ }
+}
+
+void U_WMRSTRETCHBLT_swap(char *record, int torev){
+ uint32_t Size16;
+ uint8_t xb;
+ memcpy(&Size16, record + offsetof(U_METARECORD,Size16_4), 4);
+ if(!torev)U_swap4(&Size16,1);
+ xb = *(uint8_t *)(record + offsetof(U_METARECORD,xb));
+ if(U_TEST_NOPX2(Size16,xb)){ /* no bitmap */
+ U_WMRCORE_U32_N16_swap(record,9,torev);
+ }
+ else { /* yes bitmap */
+ U_WMRCORE_U32_N16_swap(record,8,torev);
+ bitmap16_swap(record + offsetof(U_WMRSTRETCHBLT_PX,bitmap));
+ }
+}
+
+void U_WMRPOLYGON_swap(char *record, int torev){
+ U_WMRCORE_U16_N16_swap(record, torev);
+}
+
+void U_WMRPOLYLINE_swap(char *record, int torev){
+ U_WMRCORE_U16_N16_swap(record, torev);
+}
+
+void U_WMRESCAPE_swap(char *record, int torev){
+ uint16_t eFunc;
+
+ if(torev){ eFunc = *(uint16_t *)(record + offsetof(U_WMRESCAPE,eFunc)); }
+ U_WMRCORE_N16_swap(record,2,torev);
+ if(!torev){ eFunc = *(uint16_t *)(record + offsetof(U_WMRESCAPE,eFunc)); }
+ /* Handle data swapping for three types only, anything else end user code must handle */
+ if((eFunc == U_MFE_SETLINECAP) || (eFunc == U_MFE_SETLINEJOIN) || (eFunc == U_MFE_SETMITERLIMIT)){
+ U_swap4(record + offsetof(U_WMRESCAPE, Data),1);
+ }
+}
+
+void U_WMRRESTOREDC_swap(char *record, int torev){
+ U_WMRCORE_SIZE16_swap(record, torev);
+}
+
+void U_WMRFILLREGION_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,2,torev);
+}
+
+void U_WMRFRAMEREGION_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,4,torev);
+}
+
+void U_WMRINVERTREGION_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,1,torev);
+}
+
+void U_WMRPAINTREGION_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,1,torev);
+}
+
+void U_WMRSELECTCLIPREGION_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,1,torev);
+}
+
+void U_WMRSELECTOBJECT_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,1,torev);
+}
+
+void U_WMRSETTEXTALIGN_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,1,torev);
+}
+
+void U_WMRDRAWTEXT_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRCHORD_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record, 8, torev);
+}
+
+void U_WMRSETMAPPERFLAGS_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,1,torev);
+}
+
+void U_WMREXTTEXTOUT_swap(char *record, int torev){
+ int off,Length,Len2,Opts;
+ U_swap4(record + offsetof(U_WMREXTTEXTOUT,Size16_4),1);
+ if(torev){
+ Length = *(int16_t *)( record + offsetof(U_WMREXTTEXTOUT,Length));
+ Opts = *(uint16_t *)(record + offsetof(U_WMREXTTEXTOUT,Opts));
+ }
+ U_swap2(record + offsetof(U_WMREXTTEXTOUT,y), 4); /* y,x,Length,Opts*/
+ if(!torev){
+ Length = *(int16_t *)( record + offsetof(U_WMREXTTEXTOUT,Length));
+ Opts = *(uint16_t *)(record + offsetof(U_WMREXTTEXTOUT,Opts));
+ }
+ off = U_SIZE_WMREXTTEXTOUT;
+ if(Opts & (U_ETO_OPAQUE | U_ETO_CLIPPED)){
+ U_swap2(record + off,4); off += 8;
+ }
+ Len2 = (Length & 1 ? Length + 1 : Length);
+ off += Len2; /* no need to swap string, it is a byte array */
+ U_swap2(record+off,Length); /* swap the dx array */
+}
+
+void U_WMRSETDIBTODEV_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record, 9, torev);
+ dibheader_swap(record + offsetof(U_WMRSETDIBTODEV,dib), torev);
+}
+
+void U_WMRSELECTPALETTE_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,1,torev);
+}
+
+void U_WMRREALIZEPALETTE_swap(char *record, int torev){
+ U_WMRCORE_SIZE16_swap(record, torev);
+}
+
+void U_WMRANIMATEPALETTE_swap(char *record, int torev){
+ U_WMRCORE_PALETTE_swap(record, torev);
+}
+
+void U_WMRSETPALENTRIES_swap(char *record, int torev){
+ U_WMRCORE_PALETTE_swap(record, torev);
+}
+
+void U_WMRPOLYPOLYGON_swap(char *record, int torev){
+ U_WMRCORE_SIZE16_swap(record, torev);
+ polypolygon_swap(record + offsetof(U_WMRPOLYPOLYGON,PPolygon), torev);
+}
+
+void U_WMRRESIZEPALETTE_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,1,torev);
+}
+
+void U_WMR3A_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR3B_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR3C_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR3D_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR3E_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR3F_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRDIBBITBLT_swap(char *record, int torev){
+ uint32_t Size16;
+ uint8_t xb;
+ memcpy(&Size16, record + offsetof(U_METARECORD,Size16_4), 4);
+ if(!torev)U_swap4(&Size16,1);
+ xb = *(uint8_t *)(record + offsetof(U_METARECORD,xb));
+ if(U_TEST_NOPX2(Size16,xb)){ /* no bitmap */
+ U_WMRCORE_U32_N16_swap(record,7,torev);
+ }
+ else { /* yes bitmap */
+ U_WMRCORE_U32_N16_swap(record,6,torev);
+ dibheader_swap(record + offsetof(U_WMRDIBBITBLT_PX,dib), torev);
+ }
+}
+
+void U_WMRDIBSTRETCHBLT_swap(char *record, int torev){
+ uint32_t Size16;
+ uint8_t xb;
+ memcpy(&Size16, record + offsetof(U_METARECORD,Size16_4), 4);
+ if(!torev)U_swap4(&Size16,1);
+ xb = *(uint8_t *)(record + offsetof(U_METARECORD,xb));
+ if(U_TEST_NOPX2(Size16,xb)){ /* no bitmap */
+ U_WMRCORE_U32_N16_swap(record,9,torev);
+ }
+ else { /* yes bitmap */
+ U_WMRCORE_U32_N16_swap(record,8,torev);
+ dibheader_swap(record + offsetof(U_WMRDIBSTRETCHBLT_PX,dib), torev);
+ }
+}
+
+void U_WMRDIBCREATEPATTERNBRUSH_swap(char *record, int torev){
+ int Style;
+ if(torev){ Style = *(uint16_t *)(record + offsetof(U_WMRDIBCREATEPATTERNBRUSH,Style)); }
+ U_WMRCORE_N16_swap(record,2,torev); /* Style and cUsage */
+ if(!torev){ Style = *(uint16_t *)(record + offsetof(U_WMRDIBCREATEPATTERNBRUSH,Style)); }
+ if(Style == U_BS_PATTERN){
+ bitmap16_swap(record + offsetof(U_WMRDIBCREATEPATTERNBRUSH,Src));
+ }
+ else {
+ dibheader_swap(record + offsetof(U_WMRDIBCREATEPATTERNBRUSH,Src), torev);
+ }
+}
+
+void U_WMRSTRETCHDIB_swap(char *record, int torev){
+ UNUSED_PARAMETER(torev);
+ U_WMRCORE_U32_N16_swap(record,9,torev);
+ dibheader_swap(record + offsetof(U_WMRSTRETCHDIB,dib), torev);
+}
+
+void U_WMR44_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR45_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR46_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR47_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMREXTFLOODFILL_swap(char *record, int torev){
+ U_WMRCORE_U16_CR_2U16_swap(record, torev);
+}
+
+void U_WMR49_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR4A_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR4B_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR4C_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR4D_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR4E_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR4F_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR50_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR51_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR52_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR53_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR54_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR55_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR56_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR57_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR58_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR59_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR5A_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR5B_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR5C_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR5D_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR5E_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR5F_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR60_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR61_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR62_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR63_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR64_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR65_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR66_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR67_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR68_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR69_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR6A_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR6B_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR6C_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR6D_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR6E_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR6F_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR70_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR71_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR72_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR73_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR74_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR75_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR76_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR77_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR78_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR79_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR7A_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR7B_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR7C_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR7D_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR7E_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR7F_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR80_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR81_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR82_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR83_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR84_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR85_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR86_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR87_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR88_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR89_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR8A_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR8B_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR8C_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR8D_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR8E_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR8F_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR90_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR91_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR92_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR93_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR94_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR95_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR96_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR97_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR98_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR99_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR9A_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR9B_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR9C_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR9D_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR9E_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMR9F_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRA0_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRA1_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRA2_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRA3_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRA4_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRA5_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRA6_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRA7_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRA8_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRA9_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRAA_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRAB_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRAC_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRAD_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRAE_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRAF_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRB0_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRB1_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRB2_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRB3_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRB4_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRB5_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRB6_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRB7_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRB8_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRB9_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRBA_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRBB_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRBC_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRBD_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRBE_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRBF_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRC0_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRC1_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRC2_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRC3_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRC4_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRC5_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRC6_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRC7_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRC8_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRC9_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRCA_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRCB_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRCC_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRCD_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRCE_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRCF_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRD0_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRD1_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRD2_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRD3_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRD4_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRD5_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRD6_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRD7_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRD8_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRD9_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRDA_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRDB_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRDC_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRDD_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRDE_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRDF_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRE0_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRE1_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRE2_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRE3_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRE4_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRE5_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRE6_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRE7_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRE8_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRE9_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMREA_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMREB_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMREC_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRED_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMREE_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMREF_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRDELETEOBJECT_swap(char *record, int torev){
+ U_WMRCORE_N16_swap(record,1,torev);
+}
+
+void U_WMRF1_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRF2_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRF3_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRF4_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRF5_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRF6_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRCREATEPALETTE_swap(char *record, int torev){
+ U_WMRCORE_PALETTE_swap(record, torev);
+}
+
+void U_WMRF8_swap(char *record, int torev){
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRCREATEPATTERNBRUSH_swap(char *record, int torev){
+ U_WMRCORE_SIZE16_swap(record, torev);
+ bitmap16_swap(record + U_SIZE_METARECORD);
+ /* pattern array byte order already correct? */
+}
+
+void U_WMRCREATEPENINDIRECT_swap(char *record, int torev){
+ U_WMRCORE_SIZE16_swap(record, torev);
+ pen_swap(record + offsetof(U_WMRCREATEPENINDIRECT,pen));
+}
+
+void U_WMRCREATEFONTINDIRECT_swap(char *record, int torev){
+ U_WMRCORE_SIZE16_swap(record, torev);
+ font_swap(record + offsetof(U_WMRCREATEFONTINDIRECT,font));
+}
+
+void U_WMRCREATEBRUSHINDIRECT_swap(char *record, int torev){
+ U_WMRCORE_SIZE16_swap(record, torev);
+ wlogbrush_swap(record + offsetof(U_WMRCREATEBRUSHINDIRECT,brush));
+}
+
+void U_WMRCREATEBITMAPINDIRECT_swap(char *record, int torev){ /* in Wine, not in WMF PDF */
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRCREATEBITMAP_swap(char *record, int torev){ /* in Wine, not in WMF PDF */
+ U_WMRNOTIMPLEMENTED_swap(record, torev);
+}
+
+void U_WMRCREATEREGION_swap(char *record, int torev){
+ U_WMRCORE_SIZE16_swap(record, torev);
+ region_swap(record + offsetof(U_WMRCREATEREGION,region), torev);
+}
+//! \endcond
+
+/**
+ \brief Convert an entire WMF in memory from Big Endian to Little Endian (or vice versa).
+ \return 0 on failure, 1 on success
+ \param contents pointer to the buffer holding the entire EMF in memory
+ \param length number of bytes in the buffer
+ \param torev 1 for native to reversed, 0 for reversed to native
+ \param onerec 1 if this is operating on a single record instead of an entire file
+
+ Normally this would be called immediately before writing the data to a file
+ or immediately after reading the data from a file.
+*/
+int U_wmf_endian(char *contents, size_t length, int torev, int onerec){
+ size_t off=0;
+ uint32_t OK, Size16;
+ uint8_t iType;
+ char *record;
+ int recnum;
+ int offset=0;
+
+ record = contents;
+ if(!onerec){
+ off = wmfheader_swap(record,torev); fflush(stdout); /* WMF header is not a normal record, handle it separately */
+ record += off;
+ offset = off;
+ }
+ OK = 1;
+ recnum = 1; /* used when debugging */
+
+ while(OK){
+ if(record > contents + length){ return(0); } // this is most likely a corrupt WMF
+
+ memcpy(&Size16, record + offsetof(U_METARECORD,Size16_4), 4); /* This may not be aligned */
+ if(!torev){ U_swap4(&Size16,1); }
+ iType = *(uint8_t *)(record + offsetof(U_METARECORD,iType));
+
+//printf("DEBUG U_wmf_endian before switch record:%d offset:%d type:%d name:%s Size16:%d\n",recnum,offset,iType,U_wmr_names(iType),Size16);fflush(stdout);
+ switch (iType)
+ {
+ case U_WMR_EOF: U_WMREOF_swap(record, torev); OK=0; break;
+ case U_WMR_SETBKCOLOR: U_WMRSETBKCOLOR_swap(record, torev); break;
+ case U_WMR_SETBKMODE: U_WMRSETBKMODE_swap(record, torev); break;
+ case U_WMR_SETMAPMODE: U_WMRSETMAPMODE_swap(record, torev); break;
+ case U_WMR_SETROP2: U_WMRSETROP2_swap(record, torev); break;
+ case U_WMR_SETRELABS: U_WMRSETRELABS_swap(record, torev); break;
+ case U_WMR_SETPOLYFILLMODE: U_WMRSETPOLYFILLMODE_swap(record, torev); break;
+ case U_WMR_SETSTRETCHBLTMODE: U_WMRSETSTRETCHBLTMODE_swap(record, torev); break;
+ case U_WMR_SETTEXTCHAREXTRA: U_WMRSETTEXTCHAREXTRA_swap(record, torev); break;
+ case U_WMR_SETTEXTCOLOR: U_WMRSETTEXTCOLOR_swap(record, torev); break;
+ case U_WMR_SETTEXTJUSTIFICATION: U_WMRSETTEXTJUSTIFICATION_swap(record, torev); break;
+ case U_WMR_SETWINDOWORG: U_WMRSETWINDOWORG_swap(record, torev); break;
+ case U_WMR_SETWINDOWEXT: U_WMRSETWINDOWEXT_swap(record, torev); break;
+ case U_WMR_SETVIEWPORTORG: U_WMRSETVIEWPORTORG_swap(record, torev); break;
+ case U_WMR_SETVIEWPORTEXT: U_WMRSETVIEWPORTEXT_swap(record, torev); break;
+ case U_WMR_OFFSETWINDOWORG: U_WMROFFSETWINDOWORG_swap(record, torev); break;
+ case U_WMR_SCALEWINDOWEXT: U_WMRSCALEWINDOWEXT_swap(record, torev); break;
+ case U_WMR_OFFSETVIEWPORTORG: U_WMROFFSETVIEWPORTORG_swap(record, torev); break;
+ case U_WMR_SCALEVIEWPORTEXT: U_WMRSCALEVIEWPORTEXT_swap(record, torev); break;
+ case U_WMR_LINETO: U_WMRLINETO_swap(record, torev); break;
+ case U_WMR_MOVETO: U_WMRMOVETO_swap(record, torev); break;
+ case U_WMR_EXCLUDECLIPRECT: U_WMREXCLUDECLIPRECT_swap(record, torev); break;
+ case U_WMR_INTERSECTCLIPRECT: U_WMRINTERSECTCLIPRECT_swap(record, torev); break;
+ case U_WMR_ARC: U_WMRARC_swap(record, torev); break;
+ case U_WMR_ELLIPSE: U_WMRELLIPSE_swap(record, torev); break;
+ case U_WMR_FLOODFILL: U_WMRFLOODFILL_swap(record, torev); break;
+ case U_WMR_PIE: U_WMRPIE_swap(record, torev); break;
+ case U_WMR_RECTANGLE: U_WMRRECTANGLE_swap(record, torev); break;
+ case U_WMR_ROUNDRECT: U_WMRROUNDRECT_swap(record, torev); break;
+ case U_WMR_PATBLT: U_WMRPATBLT_swap(record, torev); break;
+ case U_WMR_SAVEDC: U_WMRSAVEDC_swap(record, torev); break;
+ case U_WMR_SETPIXEL: U_WMRSETPIXEL_swap(record, torev); break;
+ case U_WMR_OFFSETCLIPRGN: U_WMROFFSETCLIPRGN_swap(record, torev); break;
+ case U_WMR_TEXTOUT: U_WMRTEXTOUT_swap(record, torev); break;
+ case U_WMR_BITBLT: U_WMRBITBLT_swap(record, torev); break;
+ case U_WMR_STRETCHBLT: U_WMRSTRETCHBLT_swap(record, torev); break;
+ case U_WMR_POLYGON: U_WMRPOLYGON_swap(record, torev); break;
+ case U_WMR_POLYLINE: U_WMRPOLYLINE_swap(record, torev); break;
+ case U_WMR_ESCAPE: U_WMRESCAPE_swap(record, torev); break;
+ case U_WMR_RESTOREDC: U_WMRRESTOREDC_swap(record, torev); break;
+ case U_WMR_FILLREGION: U_WMRFILLREGION_swap(record, torev); break;
+ case U_WMR_FRAMEREGION: U_WMRFRAMEREGION_swap(record, torev); break;
+ case U_WMR_INVERTREGION: U_WMRINVERTREGION_swap(record, torev); break;
+ case U_WMR_PAINTREGION: U_WMRPAINTREGION_swap(record, torev); break;
+ case U_WMR_SELECTCLIPREGION: U_WMRSELECTCLIPREGION_swap(record, torev); break;
+ case U_WMR_SELECTOBJECT: U_WMRSELECTOBJECT_swap(record, torev); break;
+ case U_WMR_SETTEXTALIGN: U_WMRSETTEXTALIGN_swap(record, torev); break;
+ case U_WMR_DRAWTEXT: U_WMRDRAWTEXT_swap(record, torev); break;
+ case U_WMR_CHORD: U_WMRCHORD_swap(record, torev); break;
+ case U_WMR_SETMAPPERFLAGS: U_WMRSETMAPPERFLAGS_swap(record, torev); break;
+ case U_WMR_EXTTEXTOUT: U_WMREXTTEXTOUT_swap(record, torev); break;
+ case U_WMR_SETDIBTODEV: U_WMRSETDIBTODEV_swap(record, torev); break;
+ case U_WMR_SELECTPALETTE: U_WMRSELECTPALETTE_swap(record, torev); break;
+ case U_WMR_REALIZEPALETTE: U_WMRREALIZEPALETTE_swap(record, torev); break;
+ case U_WMR_ANIMATEPALETTE: U_WMRANIMATEPALETTE_swap(record, torev); break;
+ case U_WMR_SETPALENTRIES: U_WMRSETPALENTRIES_swap(record, torev); break;
+ case U_WMR_POLYPOLYGON: U_WMRPOLYPOLYGON_swap(record, torev); break;
+ case U_WMR_RESIZEPALETTE: U_WMRRESIZEPALETTE_swap(record, torev); break;
+ case U_WMR_3A: U_WMR3A_swap(record, torev); break;
+ case U_WMR_3B: U_WMR3B_swap(record, torev); break;
+ case U_WMR_3C: U_WMR3C_swap(record, torev); break;
+ case U_WMR_3D: U_WMR3D_swap(record, torev); break;
+ case U_WMR_3E: U_WMR3E_swap(record, torev); break;
+ case U_WMR_3F: U_WMR3F_swap(record, torev); break;
+ case U_WMR_DIBBITBLT: U_WMRDIBBITBLT_swap(record, torev); break;
+ case U_WMR_DIBSTRETCHBLT: U_WMRDIBSTRETCHBLT_swap(record, torev); break;
+ case U_WMR_DIBCREATEPATTERNBRUSH: U_WMRDIBCREATEPATTERNBRUSH_swap(record, torev); break;
+ case U_WMR_STRETCHDIB: U_WMRSTRETCHDIB_swap(record, torev); break;
+ case U_WMR_44: U_WMR44_swap(record, torev); break;
+ case U_WMR_45: U_WMR45_swap(record, torev); break;
+ case U_WMR_46: U_WMR46_swap(record, torev); break;
+ case U_WMR_47: U_WMR47_swap(record, torev); break;
+ case U_WMR_EXTFLOODFILL: U_WMREXTFLOODFILL_swap(record, torev); break;
+ case U_WMR_49: U_WMR49_swap(record, torev); break;
+ case U_WMR_4A: U_WMR4A_swap(record, torev); break;
+ case U_WMR_4B: U_WMR4B_swap(record, torev); break;
+ case U_WMR_4C: U_WMR4C_swap(record, torev); break;
+ case U_WMR_4D: U_WMR4D_swap(record, torev); break;
+ case U_WMR_4E: U_WMR4E_swap(record, torev); break;
+ case U_WMR_4F: U_WMR4F_swap(record, torev); break;
+ case U_WMR_50: U_WMR50_swap(record, torev); break;
+ case U_WMR_51: U_WMR51_swap(record, torev); break;
+ case U_WMR_52: U_WMR52_swap(record, torev); break;
+ case U_WMR_53: U_WMR53_swap(record, torev); break;
+ case U_WMR_54: U_WMR54_swap(record, torev); break;
+ case U_WMR_55: U_WMR55_swap(record, torev); break;
+ case U_WMR_56: U_WMR56_swap(record, torev); break;
+ case U_WMR_57: U_WMR57_swap(record, torev); break;
+ case U_WMR_58: U_WMR58_swap(record, torev); break;
+ case U_WMR_59: U_WMR59_swap(record, torev); break;
+ case U_WMR_5A: U_WMR5A_swap(record, torev); break;
+ case U_WMR_5B: U_WMR5B_swap(record, torev); break;
+ case U_WMR_5C: U_WMR5C_swap(record, torev); break;
+ case U_WMR_5D: U_WMR5D_swap(record, torev); break;
+ case U_WMR_5E: U_WMR5E_swap(record, torev); break;
+ case U_WMR_5F: U_WMR5F_swap(record, torev); break;
+ case U_WMR_60: U_WMR60_swap(record, torev); break;
+ case U_WMR_61: U_WMR61_swap(record, torev); break;
+ case U_WMR_62: U_WMR62_swap(record, torev); break;
+ case U_WMR_63: U_WMR63_swap(record, torev); break;
+ case U_WMR_64: U_WMR64_swap(record, torev); break;
+ case U_WMR_65: U_WMR65_swap(record, torev); break;
+ case U_WMR_66: U_WMR66_swap(record, torev); break;
+ case U_WMR_67: U_WMR67_swap(record, torev); break;
+ case U_WMR_68: U_WMR68_swap(record, torev); break;
+ case U_WMR_69: U_WMR69_swap(record, torev); break;
+ case U_WMR_6A: U_WMR6A_swap(record, torev); break;
+ case U_WMR_6B: U_WMR6B_swap(record, torev); break;
+ case U_WMR_6C: U_WMR6C_swap(record, torev); break;
+ case U_WMR_6D: U_WMR6D_swap(record, torev); break;
+ case U_WMR_6E: U_WMR6E_swap(record, torev); break;
+ case U_WMR_6F: U_WMR6F_swap(record, torev); break;
+ case U_WMR_70: U_WMR70_swap(record, torev); break;
+ case U_WMR_71: U_WMR71_swap(record, torev); break;
+ case U_WMR_72: U_WMR72_swap(record, torev); break;
+ case U_WMR_73: U_WMR73_swap(record, torev); break;
+ case U_WMR_74: U_WMR74_swap(record, torev); break;
+ case U_WMR_75: U_WMR75_swap(record, torev); break;
+ case U_WMR_76: U_WMR76_swap(record, torev); break;
+ case U_WMR_77: U_WMR77_swap(record, torev); break;
+ case U_WMR_78: U_WMR78_swap(record, torev); break;
+ case U_WMR_79: U_WMR79_swap(record, torev); break;
+ case U_WMR_7A: U_WMR7A_swap(record, torev); break;
+ case U_WMR_7B: U_WMR7B_swap(record, torev); break;
+ case U_WMR_7C: U_WMR7C_swap(record, torev); break;
+ case U_WMR_7D: U_WMR7D_swap(record, torev); break;
+ case U_WMR_7E: U_WMR7E_swap(record, torev); break;
+ case U_WMR_7F: U_WMR7F_swap(record, torev); break;
+ case U_WMR_80: U_WMR80_swap(record, torev); break;
+ case U_WMR_81: U_WMR81_swap(record, torev); break;
+ case U_WMR_82: U_WMR82_swap(record, torev); break;
+ case U_WMR_83: U_WMR83_swap(record, torev); break;
+ case U_WMR_84: U_WMR84_swap(record, torev); break;
+ case U_WMR_85: U_WMR85_swap(record, torev); break;
+ case U_WMR_86: U_WMR86_swap(record, torev); break;
+ case U_WMR_87: U_WMR87_swap(record, torev); break;
+ case U_WMR_88: U_WMR88_swap(record, torev); break;
+ case U_WMR_89: U_WMR89_swap(record, torev); break;
+ case U_WMR_8A: U_WMR8A_swap(record, torev); break;
+ case U_WMR_8B: U_WMR8B_swap(record, torev); break;
+ case U_WMR_8C: U_WMR8C_swap(record, torev); break;
+ case U_WMR_8D: U_WMR8D_swap(record, torev); break;
+ case U_WMR_8E: U_WMR8E_swap(record, torev); break;
+ case U_WMR_8F: U_WMR8F_swap(record, torev); break;
+ case U_WMR_90: U_WMR90_swap(record, torev); break;
+ case U_WMR_91: U_WMR91_swap(record, torev); break;
+ case U_WMR_92: U_WMR92_swap(record, torev); break;
+ case U_WMR_93: U_WMR93_swap(record, torev); break;
+ case U_WMR_94: U_WMR94_swap(record, torev); break;
+ case U_WMR_95: U_WMR95_swap(record, torev); break;
+ case U_WMR_96: U_WMR96_swap(record, torev); break;
+ case U_WMR_97: U_WMR97_swap(record, torev); break;
+ case U_WMR_98: U_WMR98_swap(record, torev); break;
+ case U_WMR_99: U_WMR99_swap(record, torev); break;
+ case U_WMR_9A: U_WMR9A_swap(record, torev); break;
+ case U_WMR_9B: U_WMR9B_swap(record, torev); break;
+ case U_WMR_9C: U_WMR9C_swap(record, torev); break;
+ case U_WMR_9D: U_WMR9D_swap(record, torev); break;
+ case U_WMR_9E: U_WMR9E_swap(record, torev); break;
+ case U_WMR_9F: U_WMR9F_swap(record, torev); break;
+ case U_WMR_A0: U_WMRA0_swap(record, torev); break;
+ case U_WMR_A1: U_WMRA1_swap(record, torev); break;
+ case U_WMR_A2: U_WMRA2_swap(record, torev); break;
+ case U_WMR_A3: U_WMRA3_swap(record, torev); break;
+ case U_WMR_A4: U_WMRA4_swap(record, torev); break;
+ case U_WMR_A5: U_WMRA5_swap(record, torev); break;
+ case U_WMR_A6: U_WMRA6_swap(record, torev); break;
+ case U_WMR_A7: U_WMRA7_swap(record, torev); break;
+ case U_WMR_A8: U_WMRA8_swap(record, torev); break;
+ case U_WMR_A9: U_WMRA9_swap(record, torev); break;
+ case U_WMR_AA: U_WMRAA_swap(record, torev); break;
+ case U_WMR_AB: U_WMRAB_swap(record, torev); break;
+ case U_WMR_AC: U_WMRAC_swap(record, torev); break;
+ case U_WMR_AD: U_WMRAD_swap(record, torev); break;
+ case U_WMR_AE: U_WMRAE_swap(record, torev); break;
+ case U_WMR_AF: U_WMRAF_swap(record, torev); break;
+ case U_WMR_B0: U_WMRB0_swap(record, torev); break;
+ case U_WMR_B1: U_WMRB1_swap(record, torev); break;
+ case U_WMR_B2: U_WMRB2_swap(record, torev); break;
+ case U_WMR_B3: U_WMRB3_swap(record, torev); break;
+ case U_WMR_B4: U_WMRB4_swap(record, torev); break;
+ case U_WMR_B5: U_WMRB5_swap(record, torev); break;
+ case U_WMR_B6: U_WMRB6_swap(record, torev); break;
+ case U_WMR_B7: U_WMRB7_swap(record, torev); break;
+ case U_WMR_B8: U_WMRB8_swap(record, torev); break;
+ case U_WMR_B9: U_WMRB9_swap(record, torev); break;
+ case U_WMR_BA: U_WMRBA_swap(record, torev); break;
+ case U_WMR_BB: U_WMRBB_swap(record, torev); break;
+ case U_WMR_BC: U_WMRBC_swap(record, torev); break;
+ case U_WMR_BD: U_WMRBD_swap(record, torev); break;
+ case U_WMR_BE: U_WMRBE_swap(record, torev); break;
+ case U_WMR_BF: U_WMRBF_swap(record, torev); break;
+ case U_WMR_C0: U_WMRC0_swap(record, torev); break;
+ case U_WMR_C1: U_WMRC1_swap(record, torev); break;
+ case U_WMR_C2: U_WMRC2_swap(record, torev); break;
+ case U_WMR_C3: U_WMRC3_swap(record, torev); break;
+ case U_WMR_C4: U_WMRC4_swap(record, torev); break;
+ case U_WMR_C5: U_WMRC5_swap(record, torev); break;
+ case U_WMR_C6: U_WMRC6_swap(record, torev); break;
+ case U_WMR_C7: U_WMRC7_swap(record, torev); break;
+ case U_WMR_C8: U_WMRC8_swap(record, torev); break;
+ case U_WMR_C9: U_WMRC9_swap(record, torev); break;
+ case U_WMR_CA: U_WMRCA_swap(record, torev); break;
+ case U_WMR_CB: U_WMRCB_swap(record, torev); break;
+ case U_WMR_CC: U_WMRCC_swap(record, torev); break;
+ case U_WMR_CD: U_WMRCD_swap(record, torev); break;
+ case U_WMR_CE: U_WMRCE_swap(record, torev); break;
+ case U_WMR_CF: U_WMRCF_swap(record, torev); break;
+ case U_WMR_D0: U_WMRD0_swap(record, torev); break;
+ case U_WMR_D1: U_WMRD1_swap(record, torev); break;
+ case U_WMR_D2: U_WMRD2_swap(record, torev); break;
+ case U_WMR_D3: U_WMRD3_swap(record, torev); break;
+ case U_WMR_D4: U_WMRD4_swap(record, torev); break;
+ case U_WMR_D5: U_WMRD5_swap(record, torev); break;
+ case U_WMR_D6: U_WMRD6_swap(record, torev); break;
+ case U_WMR_D7: U_WMRD7_swap(record, torev); break;
+ case U_WMR_D8: U_WMRD8_swap(record, torev); break;
+ case U_WMR_D9: U_WMRD9_swap(record, torev); break;
+ case U_WMR_DA: U_WMRDA_swap(record, torev); break;
+ case U_WMR_DB: U_WMRDB_swap(record, torev); break;
+ case U_WMR_DC: U_WMRDC_swap(record, torev); break;
+ case U_WMR_DD: U_WMRDD_swap(record, torev); break;
+ case U_WMR_DE: U_WMRDE_swap(record, torev); break;
+ case U_WMR_DF: U_WMRDF_swap(record, torev); break;
+ case U_WMR_E0: U_WMRE0_swap(record, torev); break;
+ case U_WMR_E1: U_WMRE1_swap(record, torev); break;
+ case U_WMR_E2: U_WMRE2_swap(record, torev); break;
+ case U_WMR_E3: U_WMRE3_swap(record, torev); break;
+ case U_WMR_E4: U_WMRE4_swap(record, torev); break;
+ case U_WMR_E5: U_WMRE5_swap(record, torev); break;
+ case U_WMR_E6: U_WMRE6_swap(record, torev); break;
+ case U_WMR_E7: U_WMRE7_swap(record, torev); break;
+ case U_WMR_E8: U_WMRE8_swap(record, torev); break;
+ case U_WMR_E9: U_WMRE9_swap(record, torev); break;
+ case U_WMR_EA: U_WMREA_swap(record, torev); break;
+ case U_WMR_EB: U_WMREB_swap(record, torev); break;
+ case U_WMR_EC: U_WMREC_swap(record, torev); break;
+ case U_WMR_ED: U_WMRED_swap(record, torev); break;
+ case U_WMR_EE: U_WMREE_swap(record, torev); break;
+ case U_WMR_EF: U_WMREF_swap(record, torev); break;
+ case U_WMR_DELETEOBJECT: U_WMRDELETEOBJECT_swap(record, torev); break;
+ case U_WMR_F1: U_WMRF1_swap(record, torev); break;
+ case U_WMR_F2: U_WMRF2_swap(record, torev); break;
+ case U_WMR_F3: U_WMRF3_swap(record, torev); break;
+ case U_WMR_F4: U_WMRF4_swap(record, torev); break;
+ case U_WMR_F5: U_WMRF5_swap(record, torev); break;
+ case U_WMR_F6: U_WMRF6_swap(record, torev); break;
+ case U_WMR_CREATEPALETTE: U_WMRCREATEPALETTE_swap(record, torev); break;
+ case U_WMR_F8: U_WMRF8_swap(record, torev); break;
+ case U_WMR_CREATEPATTERNBRUSH: U_WMRCREATEPATTERNBRUSH_swap(record, torev); break;
+ case U_WMR_CREATEPENINDIRECT: U_WMRCREATEPENINDIRECT_swap(record, torev); break;
+ case U_WMR_CREATEFONTINDIRECT: U_WMRCREATEFONTINDIRECT_swap(record, torev); break;
+ case U_WMR_CREATEBRUSHINDIRECT: U_WMRCREATEBRUSHINDIRECT_swap(record, torev); break;
+ case U_WMR_CREATEBITMAPINDIRECT: U_WMRCREATEBITMAPINDIRECT_swap(record, torev); break;
+ case U_WMR_CREATEBITMAP: U_WMRCREATEBITMAP_swap(record, torev); break;
+ case U_WMR_CREATEREGION: U_WMRCREATEREGION_swap(record, torev); break;
+ default: U_WMRNOTIMPLEMENTED_swap(record, torev); break;
+ } //end of switch
+ if(onerec)break;
+ record += 2*Size16;
+ offset += 2*Size16;
+ recnum++;
+ } //end of while
+ return(1);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/3rdparty/libuemf/uwmf_endian.h b/src/3rdparty/libuemf/uwmf_endian.h
new file mode 100644
index 0000000..6ce7f19
--- /dev/null
+++ b/src/3rdparty/libuemf/uwmf_endian.h
@@ -0,0 +1,34 @@
+/**
+ @file uwmf_endian.h
+
+ @brief Prototypes for functions for converting WMF records between Big Endian and Little Endian
+*/
+
+/*
+File: uwmf_endian.h
+Version: 0.0.3
+Date: 28-APR-2015
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2015 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifndef _UWMF_ENDIAN_
+#define _UWMF_ENDIAN_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "uemf_endian.h"
+
+//! \cond
+// prototypes
+int U_wmf_endian(char *contents, size_t length, int torev, int onerec);
+//! \endcond
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UWMF_ENDIAN_ */
diff --git a/src/3rdparty/libuemf/uwmf_print.c b/src/3rdparty/libuemf/uwmf_print.c
new file mode 100644
index 0000000..d6d1b58
--- /dev/null
+++ b/src/3rdparty/libuemf/uwmf_print.c
@@ -0,0 +1,1635 @@
+/**
+ @file uwmf_print.c
+
+ @brief Functions for printing WMF records
+*/
+
+/*
+File: uwmf_print.c
+Version: 0.0.6
+Date: 21-MAY-2015
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2015 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h> /* for offsetof() macro */
+#include <string.h>
+#include "uwmf_print.h"
+
+//! \cond
+
+#define UNUSED(x) (void)(x)
+
+/* **********************************************************************************************
+ These functions print standard objects used in the WMR records.
+ The low level ones do not append EOL.
+*********************************************************************************************** */
+
+/* many of these are implemented in uemf_print.c and not replicated here */
+
+
+
+/**
+ \brief Print a U_BRUSH object.
+ \param b U_BRUSH object.
+ style bColor bHatch
+ U_BS_SOLID ColorRef Object Not used (bytes present???)
+ U_BS_NULL ignored ignored (bytes present???).
+ U_BS_PATTERN ignored Bitmap16 object holding patern
+ U_BS_DIBPATTERNPT ColorUsage Enum DIB object
+ U_BS_HATCHED ColorRef Object HatchStyle Enumeration
+*/
+void brush_print(
+ U_BRUSH b
+ ){
+ uint16_t hatch;
+ U_COLORREF Color;
+ switch(b.Style){
+ case U_BS_SOLID:
+ memcpy(&Color, &b.Color, sizeof(U_COLORREF));
+ printf("Color:"); colorref_print(Color);
+ break;
+ case U_BS_NULL:
+ printf("Null");
+ break;
+ case U_BS_PATTERN:
+ printf("Pattern:(not shown)");
+ break;
+ case U_BS_DIBPATTERNPT:
+ printf("DIBPattern:(not shown)");
+ break;
+ case U_BS_HATCHED:
+ memcpy(&hatch, b.Data, 2);
+ printf("Hatch:0x%4.4X ", hatch);
+ break;
+ }
+}
+
+/**
+ \brief Print a U_FONT object from a char *pointer.
+ The U_FONT struct object may not be properly aligned, but all of the fields within it will
+ OK for alignment.
+ \param font U_FONT object (as a char * pointer)
+*/
+void font_print(
+ const char *font
+ ){
+ printf("Height:%d ", *(int16_t *)(font + offsetof(U_FONT,Height )));
+ printf("Width:%d ", *(int16_t *)(font + offsetof(U_FONT,Width )));
+ printf("Escapement:%d ", *(int16_t *)(font + offsetof(U_FONT,Escapement )));
+ printf("Orientation:%d ", *(int16_t *)(font + offsetof(U_FONT,Orientation )));
+ printf("Weight:%d ", *(int16_t *)(font + offsetof(U_FONT,Weight )));
+ printf("Italic:0x%2.2X ", *(uint8_t *)(font + offsetof(U_FONT,Italic )));
+ printf("Underline:0x%2.2X ", *(uint8_t *)(font + offsetof(U_FONT,Underline )));
+ printf("StrikeOut:0x%2.2X ", *(uint8_t *)(font + offsetof(U_FONT,StrikeOut )));
+ printf("CharSet:0x%2.2X ", *(uint8_t *)(font + offsetof(U_FONT,CharSet )));
+ printf("OutPrecision:0x%2.2X ", *(uint8_t *)(font + offsetof(U_FONT,OutPrecision )));
+ printf("ClipPrecision:0x%2.2X ", *(uint8_t *)(font + offsetof(U_FONT,ClipPrecision )));
+ printf("Quality:0x%2.2X ", *(uint8_t *)(font + offsetof(U_FONT,Quality )));
+ printf("PitchAndFamily:0x%2.2X ", *(uint8_t *)(font + offsetof(U_FONT,PitchAndFamily)));
+ printf("FaceName:%s ", (font + offsetof(U_FONT,FaceName )));
+}
+
+
+/**
+ \brief Print a U_PLTNTRY object.
+ \param pny U_PLTNTRY object.
+*/
+void pltntry_print(
+ U_PLTNTRY pny
+ ){
+ printf("Value:%u ", pny.Value);
+ printf("Red:%u ", pny.Red );
+ printf("Green:%u ", pny.Green);
+ printf("Blue:%u ", pny.Blue );
+}
+
+
+/**
+ \brief Print a pointer to a U_PALETTE object.
+ \param p Pointer to a U_PALETTE object
+ \param PalEntries Array of Palette Entries
+*/
+void palette_print(
+ const U_PALETTE *p,
+ const char *PalEntries
+ ){
+ int i;
+ U_PLTNTRY pny;
+
+ printf("Start:%X ", p->Start );
+ printf("NumEntries:%u ",p->NumEntries );
+ if(p->NumEntries && PalEntries){
+ for(i=0; i < p->NumEntries; i++, PalEntries += sizeof(U_PLTNTRY)){
+ memcpy(&pny, PalEntries, sizeof(U_PLTNTRY));
+ printf("%d:",i); pltntry_print(pny);
+ }
+ }
+}
+
+/**
+ \brief Print a U_PEN object.
+ \param p U_PEN object
+ uint16_t Style; //!< PenStyle Enumeration
+ uint16_t Width; //!< Pen Width in object dimensions
+ uint16_t unused; //!< unused
+ union {
+ U_COLORREF Color; //!< Pen color (NOT aligned on 4n byte boundary!)
+ uint16_t Colorw[2]; //!< reassemble/store the Color value using these, NOT Color.
+ };
+*/
+void pen_print(
+ U_PEN p
+ ){
+ U_COLORREF Color;
+ printf("Style:0x%8.8X " ,p.Style );
+ printf("Width:%u " ,p.Widthw[0] );
+ memcpy(&Color, &p.Color, sizeof(U_COLORREF));
+ printf("Color"); colorref_print(Color);
+}
+
+/**
+ \brief Print U_RECT16 object
+ Prints in order left, top, right, bottom
+ \param rect U_RECT16 object
+*/
+void rect16_ltrb_print(
+ U_RECT16 rect
+ ){
+ printf("LTRB{%d,%d,%d,%d} ",rect.left,rect.top,rect.right,rect.bottom);
+}
+
+/**
+ \brief Print U_RECT16 object
+ Some WMF rects use the order bottom, right, top, left. These are passed in using
+ the same structure as for a normal U_RECT16 so:
+ position holds
+ left bottom
+ top right
+ right top
+ bottom left
+ This is used by WMR_RECTANGLE and many others.
+ \param rect U_RECT16 object
+*/
+void rect16_brtl_print(
+ U_RECT16 rect
+ ){
+ printf("BRTL{%d,%d,%d,%d} ",rect.bottom,rect.right,rect.top,rect.left);
+}
+
+
+
+/**
+ \brief Print U_REGION object from a char * pointer.
+ \param region U_REGION object
+*/
+void region_print(
+ const char *region
+ ){
+ U_RECT16 rect16;
+ printf("Type:%d ", *(uint16_t *)(region + offsetof(U_REGION,Type )));
+ printf("Size:%d ", *( int16_t *)(region + offsetof(U_REGION,Size )));
+ printf("sCount:%d ",*( int16_t *)(region + offsetof(U_REGION,sCount)));
+ printf("sMax:%d ", *( int16_t *)(region + offsetof(U_REGION,sMax )));
+ memcpy(&rect16, (region + offsetof(U_REGION,sRect )), sizeof(U_RECT16));
+ printf("sRect: "); rect16_ltrb_print(rect16);
+}
+
+
+/**
+ \brief Print U_BITMAP16 object
+ \param b U_BITMAP16 object
+*/
+void bitmap16_print(
+ U_BITMAP16 b
+ ){
+ printf("Type:%d ", b.Type );
+ printf("Width:%d ", b.Width );
+ printf("Height:%d ", b.Height );
+ printf("WidthBytes:%d ", b.WidthBytes);
+ printf("Planes:%d ", b.Planes );
+ printf("BitsPixel:%d ", b.BitsPixel );
+ printf("BitsBytes:%d ", (((b.Width * b.BitsPixel + 15) >> 4) << 1) * b.Height );
+}
+
+/**
+ \brief Print U_BITMAPCOREHEADER object
+ \param ch U_BITMAPCOREHEADER object
+*/
+void bitmapcoreheader_print(
+ U_BITMAPCOREHEADER ch
+ ){
+ uint32_t Size;
+ memcpy(&Size, &(ch.Size_4), 4); /* will be aligned, but is in two pieces */
+ printf("Size:%d ", Size);
+ printf("Width:%d ", ch.Width);
+ printf("Height:%d ", ch.Height);
+ printf("Planes:%d ", ch.Planes);
+ printf("BitCount:%d ", ch.BitCount);
+}
+
+/** LogBrushW Object WMF PDF 2.2.2.10
+ \brief Print a U_LOGBRUSHW object.
+ \param lb U_LOGBRUSHW object.
+
+ style Color Hatch
+ U_BS_SOLID ColorRef Object Not used (bytes present???)
+ U_BS_NULL ignored ignored (bytes present???).
+ U_BS_PATTERN ignored not used (Action is not strictly defined)
+ U_BS_DIBPATTERN ignored not used (Action is not strictly defined)
+ U_BS_DIBPATTERNPT ignored not used (Action is not strictly defined)
+ U_BS_HATCHED ColorRef Object HatchStyle Enumeration
+*/
+void wlogbrush_print(
+ const char *lb
+ ){
+ U_COLORREF Color;
+ uint16_t Style = *(uint16_t *)(lb + offsetof(U_WLOGBRUSH,Style));
+ uint16_t Hatch = *(uint16_t *)(lb + offsetof(U_WLOGBRUSH,Hatch));
+ memcpy(&Color, lb + offsetof(U_WLOGBRUSH,Color), sizeof(U_COLORREF));
+ printf("Style:0x%4.4X ",Style);
+ switch(Style){
+ case U_BS_SOLID:
+ printf("Color:"); colorref_print(Color);
+ break;
+ case U_BS_NULL:
+ printf("Null");
+ break;
+ case U_BS_PATTERN:
+ printf("Pattern:(not implemented)");
+ break;
+ case U_BS_DIBPATTERN:
+ printf("DIBPattern:(not implemented)");
+ break;
+ case U_BS_DIBPATTERNPT:
+ printf("DIBPatternPt:(not implemented)");
+ break;
+ case U_BS_HATCHED:
+ printf("Color:"); colorref_print(Color);
+ printf("Hatch:0x%4.4X ", Hatch);
+ break;
+ }
+}
+
+
+/**
+ \brief Print U_POLYPOLY object from pointer
+ \param nPolys Number of elements in aPolyCounts
+ \param aPolyCounts Number of points in each poly (sequential)
+ \param Points pointer to array of U_POINT16 in memory. Probably not aligned.
+*/
+void polypolygon_print(
+ uint16_t nPolys,
+ const uint16_t *aPolyCounts,
+ const char *Points
+ ){
+ int i,j;
+ U_POINT16 pt;
+ for(i=0; i<nPolys; i++, aPolyCounts++){
+ printf(" Polygon[%d]: ",i);
+ for(j=0; j < *aPolyCounts; j++, Points += sizeof(U_POINT16)){
+ memcpy(&pt, Points, sizeof(U_POINT16)); /* may not be aligned */
+ point16_print(pt);
+ }
+ }
+}
+
+/**
+ \brief Print U_SCAN object
+ \param sc U_SCAN object
+*/
+void scan_print(
+ U_SCAN sc
+ ){
+ printf("Count:%d ", sc.count);
+ printf("Top:%d ", sc.top);
+ printf("Bottom:%d ", sc.bottom);
+ printf("data:(not shown)");
+}
+
+/**
+ \brief Print a summary of a DIB header
+ \param dh void pointer to DIB header
+ A DIB header in an WMF may be either a BitmapCoreHeader or BitmapInfoHeader.
+*/
+void dibheader_print(const char *dh, const char *blimit){
+ uint32_t Size;
+ memcpy(&Size, dh, 4); /* may not be aligned */
+ if(Size == 0xC ){
+ printf("(BitmapCoreHeader) ");
+ U_BITMAPCOREHEADER bmch;
+ memcpy(&bmch, dh, sizeof(U_BITMAPCOREHEADER)); /* may not be aligned */
+ bitmapcoreheader_print(bmch);
+ }
+ else {
+ printf(" (BitmapInfoHeader) ");
+ bitmapinfo_print(dh, blimit); /* may not be aligned, called routine must handle it */
+ }
+}
+
+/**
+ \brief Print WMF header object
+ \returns size of entire header structure
+ \param contents pointer to the first byte in the buffer holding the entire WMF file in memory
+ \param blimit pointer to the byte after the last byte in contents
+
+ If the header is preceded by a placeable struture, print that as well.
+*/
+int wmfheader_print(
+ const char *contents,
+ const char *blimit
+ ){
+ U_WMRPLACEABLE Placeable;
+ U_WMRHEADER Header;
+ int size = wmfheader_get(contents, blimit, &Placeable, &Header);
+ uint32_t utmp4;
+ U_RECT16 rect16;
+ uint32_t Key;
+ memcpy(&Key, contents + offsetof(U_WMRPLACEABLE,Key), 4);
+ if(Placeable.Key == 0x9AC6CDD7){
+ printf("WMF, Placeable: ");
+ printf("HWmf:%u ", Placeable.HWmf);
+ memcpy(&rect16, &(Placeable.Dst), sizeof(U_RECT16));
+ printf("Box:"); rect16_ltrb_print(rect16);
+ printf("Inch:%u ", Placeable.Inch);
+ printf("Checksum:%d ", Placeable.Checksum);
+ printf("Calculated_Checksum:%d\n",U_16_checksum((int16_t *)contents,10));
+ }
+ else {
+ printf("WMF, Not Placeable\n");
+ }
+ printf(" RecType:%d\n", Header.iType);
+ printf(" 16bit words in record:%d\n", Header.Size16w);
+ printf(" Version:%d\n", Header.version);
+ memcpy(&utmp4, &(Header.Sizew),4);
+ printf(" 16bit words in file:%d\n",utmp4);
+ printf(" Objects:%d\n", Header.nObjects);
+ memcpy(&utmp4, &(Header.maxSize),4);
+ printf(" Largest Record:%d\n", utmp4);
+ printf(" nMembers:%d\n", Header.nMembers);
+
+ return(size);
+}
+
+
+
+/* **********************************************************************************************
+These functions contain shared code used by various U_WMR*_print functions. These should NEVER be called
+by end user code and to further that end prototypes are NOT provided and they are hidden from Doxygen.
+*********************************************************************************************** */
+
+
+void wcore_points_print(uint16_t nPoints, const char *aPoints){
+ int i;
+ U_POINT16 pt;
+ printf(" Points: ");
+ for(i=0;i<nPoints; i++){
+ memcpy(&pt, aPoints + i*4, sizeof(U_POINT16)); /* aPoints U_POINT16 structure may not be aligned, so copy it out */
+ printf("[%d]:",i); point16_print(pt);
+ }
+ printf("\n");
+}
+
+
+
+/* **********************************************************************************************
+These are the core WMR functions, each creates a particular type of record.
+All return these records via a char* pointer, which is NULL if the call failed.
+They are listed in order by the corresponding U_WMR_* index number.
+*********************************************************************************************** */
+
+/**
+ \brief Print a pointer to a U_WMR_whatever record which has not been implemented.
+ \param contents pointer to a buffer holding a WMR record
+*/
+void U_WMRNOTIMPLEMENTED_print(const char *contents){
+ UNUSED(contents);
+ printf(" Not Implemented!\n");
+}
+
+void U_WMREOF_print(const char *contents){
+ UNUSED(contents);
+}
+
+void U_WMRSETBKCOLOR_print(const char *contents){
+ U_COLORREF Color;
+ int size = U_WMRSETBKCOLOR_get(contents, &Color);
+ if(size>0){
+ printf(" %-15s ","Color:"); colorref_print(Color); printf("\n");
+ }
+}
+
+void U_WMRSETBKMODE_print(const char *contents){
+ uint16_t iMode;
+ int size = U_WMRSETBKMODE_get(contents, &iMode);
+ if(size>0){
+ printf(" %-15s 0x%4.4X\n","iMode:", iMode);
+ }
+}
+
+void U_WMRSETMAPMODE_print(const char *contents){
+ uint16_t iMode;
+ int size = U_WMRSETMAPMODE_get(contents, &iMode);
+ if(size>0){
+ printf(" %-15s 0x%4.4X\n","iMode:", iMode);
+ }
+}
+
+void U_WMRSETROP2_print(const char *contents){
+ uint16_t iMode;
+ int size = U_WMRSETROP2_get(contents, &iMode);
+ if(size>0){
+ printf(" %-15s 0x%4.4X\n","iMode:", iMode);
+ }
+}
+
+void U_WMRSETRELABS_print(const char *contents){
+ UNUSED(contents);
+ /* This record type has only the common 6 bytes, so nothing (else) to print */
+}
+
+void U_WMRSETPOLYFILLMODE_print(const char *contents){
+ uint16_t iMode;
+ int size = U_WMRSETPOLYFILLMODE_get(contents, &iMode);
+ if(size>0){
+ printf(" %-15s 0x%4.4X\n","iMode:", iMode);
+ }
+}
+
+void U_WMRSETSTRETCHBLTMODE_print(const char *contents){
+ uint16_t iMode;
+ int size = U_WMRSETSTRETCHBLTMODE_get(contents, &iMode);
+ if(size>0){
+ printf(" %-15s 0x%4.4X\n","iMode:", iMode);
+ }
+}
+
+void U_WMRSETTEXTCHAREXTRA_print(const char *contents){
+ uint16_t iMode;
+ int size = U_WMRSETTEXTCHAREXTRA_get(contents, &iMode);
+ if(size>0){
+ printf(" %-15s 0x%4.4X\n","iMode:", iMode);
+ }
+}
+
+void U_WMRSETTEXTCOLOR_print(const char *contents){
+ U_COLORREF Color;
+ int size = U_WMRSETTEXTCOLOR_get(contents, &Color);
+ if(size>0){
+ printf(" %-15s ","Color:"); colorref_print(Color); printf("\n");
+ }
+}
+
+void U_WMRSETTEXTJUSTIFICATION_print(const char *contents){
+ uint16_t Count;
+ uint16_t Extra;
+ int size = U_WMRSETTEXTJUSTIFICATION_get(contents, &Count, &Extra);
+ if(size){
+ printf(" %-15s %d\n","Count", Count);
+ printf(" %-15s %d\n","Extra", Extra);
+ }
+}
+
+void U_WMRSETWINDOWORG_print(const char *contents){
+ U_POINT16 coord;
+ int size = U_WMRSETWINDOWORG_get(contents, &coord);
+ if(size){
+ printf(" %-15s {%d,%d}\n","X,Y",coord.x, coord.y);
+ }
+}
+
+void U_WMRSETWINDOWEXT_print(const char *contents){
+ U_POINT16 coord;
+ int size = U_WMRSETWINDOWEXT_get(contents, &coord);
+ if(size){
+ printf(" %-15s {%d,%d}\n","W,H",coord.x, coord.y);
+ }
+}
+
+void U_WMRSETVIEWPORTORG_print(const char *contents){
+ U_POINT16 coord;
+ int size = U_WMRSETVIEWPORTORG_get(contents, &coord);
+ if(size){
+ printf(" %-15s {%d,%d}\n","X,Y",coord.x, coord.y);
+ }
+}
+
+void U_WMRSETVIEWPORTEXT_print(const char *contents){
+ U_POINT16 coord;
+ int size = U_WMRSETVIEWPORTEXT_get(contents, &coord);
+ if(size){
+ printf(" %-15s {%d,%d}\n","W,H",coord.x, coord.y);
+ }
+}
+
+void U_WMROFFSETWINDOWORG_print(const char *contents){
+ U_POINT16 coord;
+ int size = U_WMROFFSETWINDOWORG_get(contents, &coord);
+ if(size){
+ printf(" %-15s {%d,%d}\n","X,Y",coord.x, coord.y);
+ }
+}
+
+void U_WMRSCALEWINDOWEXT_print(const char *contents){
+ U_POINT16 Denom, Num;
+ int size = U_WMRSCALEWINDOWEXT_get(contents, &Denom, &Num);
+ if(size > 0){
+ printf(" yDenom:%d\n", Denom.y);
+ printf(" yNum:%d\n", Num.y );
+ printf(" xDenom:%d\n", Denom.x);
+ printf(" xNum:%d\n", Num.x );
+ }
+}
+
+void U_WMROFFSETVIEWPORTORG_print(const char *contents){
+ U_POINT16 coord;
+ int size = U_WMROFFSETVIEWPORTORG_get(contents, &coord);
+ if(size){
+ printf(" %-15s {%d,%d}\n","X,Y",coord.x, coord.y);
+ }
+}
+
+void U_WMRSCALEVIEWPORTEXT_print(const char *contents){
+ U_POINT16 Denom, Num;
+ int size = U_WMRSCALEVIEWPORTEXT_get(contents, &Denom, &Num);
+ if(size > 0){
+ printf(" yDenom:%d\n", Denom.y);
+ printf(" yNum:%d\n", Num.y );
+ printf(" xDenom:%d\n", Denom.x);
+ printf(" xNum:%d\n", Num.x );
+ }
+}
+
+void U_WMRLINETO_print(const char *contents){
+ U_POINT16 coord;
+ int size = U_WMRLINETO_get(contents, &coord);
+ if(size){
+ printf(" %-15s {%d,%d}\n","X,Y",coord.x, coord.y);
+ }
+}
+
+void U_WMRMOVETO_print(const char *contents){
+ U_POINT16 coord;
+ int size = U_WMRMOVETO_get(contents, &coord);
+ if(size > 0){
+ printf(" %-15s {%d,%d}\n","X,Y",coord.x, coord.y);
+ }
+}
+
+void U_WMREXCLUDECLIPRECT_print(const char *contents){
+ U_RECT16 rect16;
+ int size = U_WMREXCLUDECLIPRECT_get(contents, &rect16);
+ if(size > 0){
+ printf(" Rect:");
+ rect16_ltrb_print(rect16);
+ printf("\n");
+ }
+}
+
+void U_WMRINTERSECTCLIPRECT_print(const char *contents){
+ U_RECT16 rect16;
+ int size = U_WMRINTERSECTCLIPRECT_get(contents, &rect16);
+ if(size > 0){
+ printf(" Rect:");
+ rect16_ltrb_print(rect16);
+ printf("\n");
+ }
+}
+
+void U_WMRARC_print(const char *contents){
+ U_POINT16 StartArc, EndArc;
+ U_RECT16 rect16;
+ int size = U_WMRARC_get(contents, &StartArc, &EndArc, &rect16);
+ if(size > 0){
+ printf(" yRadial2:%d\n", EndArc.y);
+ printf(" xRadial2:%d\n", EndArc.x);
+ printf(" yRadial1:%d\n", StartArc.y);
+ printf(" xRadial1:%d\n", StartArc.x);
+ printf(" Rect:"); rect16_ltrb_print(rect16); printf("\n");
+ }
+}
+
+void U_WMRELLIPSE_print(const char *contents){
+ U_RECT16 rect16;
+ int size = U_WMRELLIPSE_get(contents, &rect16);
+ if(size > 0){
+ printf(" Rect:");
+ rect16_ltrb_print(rect16);
+ printf("\n");
+ }
+}
+
+void U_WMRFLOODFILL_print(const char *contents){
+ uint16_t Mode;
+ U_COLORREF Color;
+ U_POINT16 coord;
+ int size = U_WMRFLOODFILL_get(contents, &Mode, &Color, &coord);
+ if(size > 0){
+ printf(" Mode 0x%4.4X\n", Mode);
+ printf(" Color:"); colorref_print(Color); printf("\n");
+ printf(" X,Y {%d,%d}\n", coord.x, coord.y);
+ }
+}
+
+void U_WMRPIE_print(const char *contents){
+ U_POINT16 StartArc, EndArc;
+ U_RECT16 rect16;
+ int size = U_WMRPIE_get(contents, &StartArc, &EndArc, &rect16);
+ if(size > 0){
+ printf(" yRadial2:%d\n", EndArc.y);
+ printf(" xRadial2:%d\n", EndArc.x);
+ printf(" yRadial1:%d\n", StartArc.y);
+ printf(" xRadial1:%d\n", StartArc.x);
+ printf(" Rect:"); rect16_ltrb_print(rect16); printf("\n");
+ }
+}
+
+void U_WMRRECTANGLE_print(const char *contents){
+ U_RECT16 rect16;
+ int size = U_WMRRECTANGLE_get(contents, &rect16);
+ if(size > 0){
+ printf(" Rect:");
+ rect16_ltrb_print(rect16);
+ printf("\n");
+ }
+}
+
+void U_WMRROUNDRECT_print(const char *contents){
+ int16_t Height, Width;
+ U_RECT16 rect16;
+ int size = U_WMRROUNDRECT_get(contents, &Width, &Height, &rect16);
+ if(size > 0){
+ printf(" Width:%d\n", Width);
+ printf(" Height:%d\n", Height);
+ printf(" Rect:");
+ rect16_ltrb_print(rect16);
+ printf("\n");
+ }
+}
+
+void U_WMRPATBLT_print(const char *contents){
+ uint32_t dwRop3;
+ U_POINT16 Dst;
+ U_POINT16 cwh;
+ int size = U_WMRPATBLT_get(contents, &Dst, &cwh, &dwRop3);
+ if(size > 0){
+ printf(" Rop3:%8.8X\n", dwRop3 );
+ printf(" W,H:%d,%d\n", cwh.x, cwh.y );
+ printf(" Dst X,Y:{%d,%d}\n", Dst.x, Dst.y );
+ }
+}
+
+void U_WMRSAVEDC_print(const char *contents){
+ UNUSED(contents);
+ /* This record type has only the common 6 bytes, so nothing (else) to print */
+}
+
+void U_WMRSETPIXEL_print(const char *contents){
+ U_COLORREF Color;
+ U_POINT16 coord;
+ int size = U_WMRSETPIXEL_get(contents, &Color, &coord);
+ if(size > 0){
+ printf(" Color:"); colorref_print(Color); printf("\n");
+ printf(" X,Y {%d,%d}\n", coord.x, coord.y);
+ }
+}
+
+void U_WMROFFSETCLIPRGN_print(const char *contents){
+ U_POINT16 coord;
+ int size = U_WMROFFSETCLIPRGN_get(contents, &coord);
+ if(size > 0){
+ printf(" %-15s {%d,%d}\n","X,Y",coord.x, coord.y);
+ }
+}
+
+void U_WMRTEXTOUT_print(const char *contents){
+ int16_t Length;
+ const char *string;
+ U_POINT16 Dst;
+ int size = U_WMRTEXTOUT_get(contents, &Dst, &Length, &string);
+ if(size > 0){
+ printf(" X,Y:{%d,%d}\n", Dst.x,Dst.y);
+ printf(" Length:%d\n", Length);
+ printf(" String:<%.*s>\n", Length, string); /* May not be null terminated */
+ }
+}
+
+void U_WMRBITBLT_print(const char *contents){
+ uint32_t dwRop3;
+ U_POINT16 Dst, Src, cwh;
+ U_BITMAP16 Bm16;
+ const char *px;
+ int size = U_WMRBITBLT_get(contents, &Dst, &cwh, &Src, &dwRop3, &Bm16, &px);
+ if(size > 0){
+ printf(" Rop3:%8.8X\n", dwRop3 );
+ printf(" Src X,Y:{%d,%d}\n", Src.x, Src.y);
+ printf(" W,H:%d,%d\n", cwh.x, cwh.y);
+ printf(" Dst X,Y:{%d,%d}\n", Dst.x, Dst.y);
+ if(px){ printf(" Bitmap16:"); bitmap16_print(Bm16); printf("\n"); }
+ else { printf(" Bitmap16: none\n"); }
+ }
+}
+
+void U_WMRSTRETCHBLT_print(const char *contents){
+ uint32_t dwRop3;
+ U_POINT16 Dst, Src, cDst, cSrc;
+ U_BITMAP16 Bm16;
+ const char *px;
+ int size = U_WMRSTRETCHBLT_get(contents, &Dst, &cDst, &Src, &cSrc, &dwRop3, &Bm16, &px);
+ if(size > 0){
+ printf(" Rop3:%8.8X\n", dwRop3 );
+ printf(" Src W,H:%d,%d\n", cSrc.x, cSrc.y);
+ printf(" Src X,Y:{%d,%d}\n", Src.x, Src.y );
+ printf(" Dst W,H:%d,%d\n", cDst.x, cDst.y);
+ printf(" Dst X,Y:{%d,%d}\n", Dst.x, Dst.y );
+ if(px){ printf(" Bitmap16:"); bitmap16_print(Bm16); printf("\n"); }
+ else { printf(" Bitmap16: none\n"); }
+ }
+}
+
+void U_WMRPOLYGON_print(const char *contents){
+ uint16_t Length;
+ const char *Data;
+ int size = U_WMRPOLYGON_get(contents, &Length, &Data);
+ if(size > 0){
+ wcore_points_print(Length, Data);
+ }
+}
+
+void U_WMRPOLYLINE_print(const char *contents){
+ uint16_t Length;
+ const char *Data;
+ int size = U_WMRPOLYLINE_get(contents, &Length, &Data);
+ if(size > 0){
+ wcore_points_print(Length, Data);
+ }
+}
+
+void U_WMRESCAPE_print(const char *contents){
+ uint32_t utmp4;
+ uint16_t Escape;
+ uint16_t Length;
+ const char *Data;
+ int size = U_WMRESCAPE_get(contents, &Escape, &Length, &Data);
+ if(size > 0){
+ printf(" EscType:%s\n",U_wmr_escnames(Escape));
+ printf(" nBytes:%d\n",Length);
+ if((Escape == U_MFE_SETLINECAP) || (Escape == U_MFE_SETLINEJOIN) || (Escape == U_MFE_SETMITERLIMIT)){
+ memcpy(&utmp4, Data ,4);
+ printf(" Data:%d\n", utmp4);
+ }
+ else {
+ printf(" Data: (not shown)\n");
+ }
+ }
+}
+
+void U_WMRRESTOREDC_print(const char *contents){
+ UNUSED(contents);
+ /* This record type has only the common 6 bytes, so nothing (else) to print */
+}
+
+void U_WMRFILLREGION_print(const char *contents){
+ uint16_t Region;
+ uint16_t Brush;
+ int size = U_WMRFILLREGION_get(contents, &Region, &Brush);
+ if(size > 0){
+ printf(" %-15s %d\n","Region", Region);
+ printf(" %-15s %d\n","Brush", Brush);
+ }
+}
+
+void U_WMRFRAMEREGION_print(const char *contents){
+ uint16_t Region;
+ uint16_t Brush;
+ int16_t Height;
+ int16_t Width;
+ int size = U_WMRFRAMEREGION_get(contents, &Region, &Brush, &Height, &Width);
+ if(size > 0){
+ printf(" Region:%d\n",Region);
+ printf(" Brush:%d\n", Brush );
+ printf(" Height:%d\n",Height);
+ printf(" Width:%d\n", Width );
+ }
+}
+
+void U_WMRINVERTREGION_print(const char *contents){
+ uint16_t Region;
+ int size = U_WMRSETTEXTALIGN_get(contents, &Region);
+ if(size > 0){
+ printf(" %-15s %d\n","Region:", Region);
+ }
+}
+
+void U_WMRPAINTREGION_print(const char *contents){
+ uint16_t Region;
+ int size = U_WMRPAINTREGION_get(contents, &Region);
+ if(size>0){
+ printf(" %-15s %d\n","Region:", Region);
+ }
+}
+
+void U_WMRSELECTCLIPREGION_print(const char *contents){
+ uint16_t Region;
+ int size = U_WMRSELECTCLIPREGION_get(contents, &Region);
+ if(size>0){
+ printf(" %-15s %d\n","Region:", Region);
+ }
+}
+
+void U_WMRSELECTOBJECT_print(const char *contents){
+ uint16_t Object;
+ int size = U_WMRSELECTOBJECT_get(contents, &Object);
+ if(size>0){
+ printf(" %-15s %d\n","Object:", Object);
+ }
+}
+
+void U_WMRSETTEXTALIGN_print(const char *contents){
+ uint16_t iMode;
+ int size = U_WMRSETTEXTALIGN_get(contents, &iMode);
+ if(size>0){
+ printf(" %-15s 0x%4.4X\n","iMode:", iMode);
+ }
+}
+
+#define U_WMRDRAWTEXT_print U_WMRNOTIMPLEMENTED_print
+
+void U_WMRCHORD_print(const char *contents){
+ U_POINT16 StartArc, EndArc;
+ U_RECT16 rect16;
+ int size = U_WMRCHORD_get(contents, &StartArc, &EndArc, &rect16);
+ if(size > 0){
+ printf(" yRadial2:%d\n", EndArc.y);
+ printf(" xRadial2:%d\n", EndArc.x);
+ printf(" yRadial1:%d\n", StartArc.y);
+ printf(" xRadial1:%d\n", StartArc.x);
+ printf(" Rect:"); rect16_ltrb_print(rect16); printf("\n");
+ }
+}
+
+void U_WMRSETMAPPERFLAGS_print(const char *contents){
+ uint32_t Flags4;
+ int size = U_WMRSETMAPPERFLAGS_get(contents, &Flags4);
+ if(size > 0){
+ printf(" %-15s 0x%8.8X\n","Flags4:", Flags4);
+ }
+}
+
+void U_WMREXTTEXTOUT_print(const char *contents){
+ U_RECT16 rect16;
+ U_POINT16 Dst;
+ int16_t Length;
+ uint16_t Opts;
+ const int16_t *dx;
+ const char *string;
+ int i;
+ int size = U_WMREXTTEXTOUT_get(contents, &Dst, &Length, &Opts, &string, &dx, &rect16);
+ if(size > 0){
+ printf(" X,Y:{%d,%d}\n", Dst.x, Dst.y);
+ printf(" Length:%d\n", Length );
+ printf(" Opts:%4.4X\n", Opts );
+ if(Opts & (U_ETO_OPAQUE | U_ETO_CLIPPED)){
+ printf(" Rect:"); rect16_ltrb_print(rect16); printf("\n");
+ }
+ printf(" String:<%.*s>\n",Length, string);
+ printf(" Dx:");
+ for(i=0; i<Length; i++,dx++){ printf("%d:", *dx ); }
+ printf("\n");
+ }
+}
+
+void U_WMRSETDIBTODEV_print(const char *contents){
+ uint16_t cUsage;
+ uint16_t ScanCount;
+ uint16_t StartScan;
+ U_POINT16 Dst;
+ U_POINT16 cwh;
+ U_POINT16 Src;
+ const char *dib;
+ int size = U_WMRSETDIBTODEV_get(contents, &Dst, &cwh, &Src, &cUsage, &ScanCount, &StartScan, &dib);
+ if(size > 0){
+ printf(" cUsage:%d\n", cUsage );
+ printf(" ScanCount:%d\n", ScanCount );
+ printf(" StartScan:%d\n", StartScan );
+ printf(" Src X,Y:{%d,%d}\n", Src.x, Src.y );
+ printf(" W,H:%d,%d\n", cwh.x, cwh.y );
+ printf(" Dst X,Y:{%d,%d}\n", Dst.x, Dst.y );
+ printf(" DIB:"); dibheader_print(dib, dib+size); printf("\n");
+ }
+}
+
+void U_WMRSELECTPALETTE_print(const char *contents){
+ uint16_t Palette;
+ int size = U_WMRSELECTPALETTE_get(contents, &Palette);
+ if(size > 0){
+ printf(" %-15s %d\n","Palette:", Palette);
+ }
+}
+
+void U_WMRREALIZEPALETTE_print(const char *contents){
+ UNUSED(contents);
+ /* This record type has only the common 6 bytes, so nothing (else) to print */
+}
+
+void U_WMRANIMATEPALETTE_print(const char *contents){
+ U_PALETTE Palette;
+ const char *PalEntries;
+ int size = U_WMRANIMATEPALETTE_get(contents, &Palette, &PalEntries);
+ if(size > 0){
+ printf(" Palette:"); palette_print(&Palette, PalEntries); printf("\n");
+
+ }
+}
+
+void U_WMRSETPALENTRIES_print(const char *contents){
+ U_PALETTE Palette;
+ const char *PalEntries;
+ int size = U_WMRSETPALENTRIES_get(contents, &Palette, &PalEntries);
+ if(size > 0){
+ printf(" Palette:"); palette_print(&Palette, PalEntries); printf("\n");
+ }
+}
+
+void U_WMRPOLYPOLYGON_print(const char *contents){
+ uint16_t nPolys;
+ const uint16_t *aPolyCounts;
+ const char *Points;
+ int size = U_WMRPOLYPOLYGON_get(contents, &nPolys, &aPolyCounts, &Points);
+ if(size > 0){
+ printf(" Polygons:"); polypolygon_print(nPolys, aPolyCounts, Points); printf("\n");
+ }
+}
+
+void U_WMRRESIZEPALETTE_print(const char *contents){
+ uint16_t Palette;
+ int size = U_WMRSELECTCLIPREGION_get(contents, &Palette);
+ if(size>0){
+ printf(" %-15s %d\n","Palette:", Palette);
+ }
+}
+
+#define U_WMR3A_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR3B_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR3C_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR3D_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR3E_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR3F_print U_WMRNOTIMPLEMENTED_print
+
+void U_WMRDIBBITBLT_print(const char *contents){
+ U_POINT16 Dst, cwh, Src;
+ uint32_t dwRop3;
+ const char *dib;
+ int size = U_WMRDIBBITBLT_get(contents, &Dst, &cwh, &Src, &dwRop3, &dib);
+ if(size > 0){
+ printf(" Rop3:%8.8X\n", dwRop3 );
+ printf(" Src X,Y:{%d,%d}\n", Src.x, Src.x );
+ printf(" W,H:%d,%d\n", cwh.x, cwh.y );
+ printf(" Dst X,Y:{%d,%d}\n", Dst.x, Dst.y );
+ if(dib){ printf(" DIB:"); dibheader_print(dib, dib+size); printf("\n"); }
+ else { printf(" DIB: none\n"); }
+ }
+}
+
+void U_WMRDIBSTRETCHBLT_print(const char *contents){
+ U_POINT16 Dst, cDst, Src, cSrc;
+ uint32_t dwRop3;
+ const char *dib;
+ int size = U_WMRDIBSTRETCHBLT_get(contents, &Dst, &cDst, &Src, &cSrc, &dwRop3, &dib);
+ if(size > 0){
+ printf(" Rop3:%8.8X\n", dwRop3 );
+ printf(" Src W,H:%d,%d\n", cSrc.x, cSrc.y );
+ printf(" Src X,Y:{%d,%d}\n", Src.x, Src.x );
+ printf(" Dst W,H:%d,%d\n", cDst.x, cDst.y );
+ printf(" Dst X,Y:{%d,%d}\n", Dst.x, Dst.y );
+ if(dib){ printf(" DIB:"); dibheader_print(dib, dib+size); printf("\n"); }
+ else { printf(" DIB: none\n"); }
+ }
+}
+
+void U_WMRDIBCREATEPATTERNBRUSH_print(const char *contents){
+ uint16_t Style, cUsage;
+ const char *TBm16;
+ const char *dib;
+ int size = U_WMRDIBCREATEPATTERNBRUSH_get(contents, &Style, &cUsage, &TBm16, &dib);
+ if(size > 0){
+ U_BITMAP16 Bm16;
+ printf(" Style:%d\n", Style );
+ printf(" cUsage:%d\n", cUsage);
+ if(TBm16){
+ memcpy(&Bm16, TBm16, U_SIZE_BITMAP16);
+ printf(" Src:Bitmap16:"); bitmap16_print(Bm16); printf("\n");
+ }
+ else { /* from DIB */
+ printf(" Src:DIB:"); dibheader_print(dib, dib+size); printf("\n");
+ }
+ }
+}
+
+void U_WMRSTRETCHDIB_print(const char *contents){
+ U_POINT16 Dst, cDst, Src, cSrc;
+ uint32_t dwRop3;
+ uint16_t cUsage;
+ const char *dib;
+ int size = U_WMRSTRETCHDIB_get(contents, &Dst, &cDst, &Src, &cSrc, &cUsage, &dwRop3, &dib);
+ if(size > 0){
+ printf(" Rop3:%8.8X\n", dwRop3 );
+ printf(" cUsage:%d\n", cUsage );
+ printf(" Src W,H:%d,%d\n", cSrc.x, cSrc.y );
+ printf(" Src X,Y:{%d,%d}\n", Src.x, Src.x );
+ printf(" Dst W,H:%d,%d\n", cDst.x, cDst.y );
+ printf(" Dst X,Y:{%d,%d}\n", Dst.x, Dst.y );
+ if(dib){ printf(" DIB:"); dibheader_print(dib, dib+size); printf("\n"); }
+ else { printf(" DIB: none\n"); }
+ }
+}
+
+#define U_WMR44_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR45_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR46_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR47_print U_WMRNOTIMPLEMENTED_print
+
+void U_WMREXTFLOODFILL_print(const char *contents){
+ uint16_t Mode;
+ U_COLORREF Color;
+ U_POINT16 coord;
+ int size = U_WMREXTFLOODFILL_get(contents, &Mode, &Color, &coord);
+ if(size > 0){
+ printf(" Mode 0x%4.4X\n", Mode);
+ printf(" Color:"); colorref_print(Color); printf("\n");
+ printf(" X,Y {%d,%d}\n", coord.x, coord.y);
+ }
+}
+
+#define U_WMR49_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR4A_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR4B_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR4C_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR4D_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR4E_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR4F_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR50_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR51_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR52_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR53_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR54_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR55_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR56_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR57_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR58_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR59_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR5A_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR5B_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR5C_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR5D_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR5E_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR5F_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR60_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR61_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR62_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR63_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR64_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR65_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR66_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR67_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR68_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR69_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR6A_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR6B_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR6C_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR6D_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR6E_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR6F_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR70_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR71_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR72_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR73_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR74_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR75_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR76_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR77_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR78_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR79_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR7A_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR7B_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR7C_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR7D_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR7E_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR7F_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR80_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR81_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR82_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR83_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR84_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR85_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR86_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR87_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR88_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR89_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR8A_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR8B_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR8C_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR8D_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR8E_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR8F_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR90_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR91_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR92_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR93_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR94_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR95_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR96_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR97_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR98_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR99_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR9A_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR9B_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR9C_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR9D_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR9E_print U_WMRNOTIMPLEMENTED_print
+#define U_WMR9F_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRA0_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRA1_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRA2_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRA3_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRA4_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRA5_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRA6_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRA7_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRA8_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRA9_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRAA_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRAB_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRAC_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRAD_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRAE_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRAF_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRB0_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRB1_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRB2_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRB3_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRB4_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRB5_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRB6_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRB7_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRB8_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRB9_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRBA_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRBB_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRBC_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRBD_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRBE_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRBF_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRC0_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRC1_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRC2_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRC3_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRC4_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRC5_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRC6_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRC7_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRC8_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRC9_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRCA_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRCB_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRCC_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRCD_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRCE_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRCF_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRD0_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRD1_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRD2_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRD3_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRD4_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRD5_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRD6_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRD7_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRD8_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRD9_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRDA_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRDB_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRDC_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRDD_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRDE_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRDF_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRE0_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRE1_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRE2_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRE3_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRE4_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRE5_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRE6_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRE7_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRE8_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRE9_print U_WMRNOTIMPLEMENTED_print
+#define U_WMREA_print U_WMRNOTIMPLEMENTED_print
+#define U_WMREB_print U_WMRNOTIMPLEMENTED_print
+#define U_WMREC_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRED_print U_WMRNOTIMPLEMENTED_print
+#define U_WMREE_print U_WMRNOTIMPLEMENTED_print
+#define U_WMREF_print U_WMRNOTIMPLEMENTED_print
+
+void U_WMRDELETEOBJECT_print(const char *contents){
+ uint16_t Object;
+ int size = U_WMRDELETEOBJECT_get(contents, &Object);
+ if(size>0){
+ printf(" %-15s %d\n","Object:", Object);
+ }
+}
+
+#define U_WMRF1_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRF2_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRF3_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRF4_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRF5_print U_WMRNOTIMPLEMENTED_print
+#define U_WMRF6_print U_WMRNOTIMPLEMENTED_print
+
+void U_WMRCREATEPALETTE_print(const char *contents){
+ U_PALETTE Palette;
+ const char *PalEntries;
+ int size = U_WMRCREATEPALETTE_get(contents, &Palette, &PalEntries);
+ if(size > 0){
+ printf(" Palette:"); palette_print(&Palette, PalEntries); printf("\n");
+
+ }
+}
+
+#define U_WMRF8_print U_WMRNOTIMPLEMENTED_print
+
+void U_WMRCREATEPATTERNBRUSH_print(const char *contents){
+ U_BITMAP16 Bm16;
+ int pasize;
+ int i;
+ const char *Pattern;
+
+ int size = U_WMRCREATEPATTERNBRUSH_get(contents, &Bm16, &pasize, &Pattern);
+ if(size > 0){
+ /* BM16 is truncated, but bitmap16_print does not get into the part that was omitted */
+ printf(" BitMap16: "); bitmap16_print(Bm16); printf("\n");
+ printf(" Pattern: ");
+ for(i=0;i<pasize;i++){
+ printf("%2.2X ",Pattern[i]);
+ }
+ printf("\n");
+ }
+}
+
+void U_WMRCREATEPENINDIRECT_print(const char *contents){
+ U_PEN pen;
+ int size = U_WMRCREATEPENINDIRECT_get(contents, &pen);
+ if(size > 0){
+ printf(" Pen:"); pen_print(pen); printf("\n");
+ }
+}
+
+void U_WMRCREATEFONTINDIRECT_print(const char *contents){
+ const char *font; /* Note, because of possible struct alignment issue have to use char * to reference the data */
+ int size = U_WMRCREATEFONTINDIRECT_get(contents, &font);
+ if(size > 0){
+ printf(" Font:");
+ font_print(font);
+ printf("\n");
+ }
+}
+
+void U_WMRCREATEBRUSHINDIRECT_print(const char *contents){
+ const char *brush; /* Note, because of possible struct alignment issue have to use char * to reference the data */
+ int size = U_WMRCREATEBRUSHINDIRECT_get(contents, &brush);
+ if(size > 0){
+ printf(" Brush:");
+ wlogbrush_print(brush);
+ printf("\n");
+ }
+}
+
+void U_WMRCREATEBITMAPINDIRECT_print(const char *contents){ /* in Wine, not in WMF PDF */
+ U_WMRNOTIMPLEMENTED_print(contents);
+}
+
+void U_WMRCREATEBITMAP_print(const char *contents){ /* in Wine, not in WMF PDF */
+ U_WMRNOTIMPLEMENTED_print(contents);
+}
+
+void U_WMRCREATEREGION_print(const char *contents){
+ const char *region; /* Note, because of possible struct alignment issue have to use char * to reference the data */
+ int size = U_WMRCREATEBRUSHINDIRECT_get(contents, &region);
+ if(size > 0){
+ printf(" Brush:");
+ printf(" Region: "); region_print(region); printf("\n");
+ }
+}
+
+//! \endcond
+
+/**
+ \brief Print any record in a wmf
+ \returns record length for a normal record, 0 for WMREOF, -1 for a bad record
+ \param contents pointer to a buffer holding all WMR records
+ \param blimit one byte past the last WMF record in memory.
+ \param recnum number of this record in contents
+ \param off offset to this record in contents
+*/
+int U_wmf_onerec_print(const char *contents, const char *blimit, int recnum, size_t off){
+
+
+ uint8_t iType;
+ size_t size;
+
+ contents += off;
+
+ /* Check that the record size is OK, abort if not.
+ Pointer math might wrap, so check both sides of the range */
+ size = U_WMRRECSAFE_get(contents, blimit);
+ if(!size)return(-1);
+
+ iType = *(uint8_t *)(contents + offsetof(U_METARECORD, iType ) );
+
+ uint32_t crc;
+#if U_BYTE_SWAP
+ //This is a Big Endian machine, WMF crc values must be calculated on Little Endian form
+ char *swapbuf=malloc(size);
+ if(!swapbuf)return(-1);
+ memcpy(swapbuf,contents,size);
+ U_wmf_endian(swapbuf,size,1,1); // BE to LE
+ crc=lu_crc32(swapbuf,size);
+ free(swapbuf);
+#else
+ crc=lu_crc32(contents,size);
+#endif
+ printf("%-30srecord:%5d type:%-4u offset:%8d rsize:%8u crc32:%8.8X\n",
+ U_wmr_names(iType), recnum, iType, (int) off, (int) size, crc);
+
+ switch (iType)
+ {
+ case U_WMR_EOF: U_WMREOF_print(contents); size=0; break;
+ case U_WMR_SETBKCOLOR: U_WMRSETBKCOLOR_print(contents); break;
+ case U_WMR_SETBKMODE: U_WMRSETBKMODE_print(contents); break;
+ case U_WMR_SETMAPMODE: U_WMRSETMAPMODE_print(contents); break;
+ case U_WMR_SETROP2: U_WMRSETROP2_print(contents); break;
+ case U_WMR_SETRELABS: U_WMRSETRELABS_print(contents); break;
+ case U_WMR_SETPOLYFILLMODE: U_WMRSETPOLYFILLMODE_print(contents); break;
+ case U_WMR_SETSTRETCHBLTMODE: U_WMRSETSTRETCHBLTMODE_print(contents); break;
+ case U_WMR_SETTEXTCHAREXTRA: U_WMRSETTEXTCHAREXTRA_print(contents); break;
+ case U_WMR_SETTEXTCOLOR: U_WMRSETTEXTCOLOR_print(contents); break;
+ case U_WMR_SETTEXTJUSTIFICATION: U_WMRSETTEXTJUSTIFICATION_print(contents); break;
+ case U_WMR_SETWINDOWORG: U_WMRSETWINDOWORG_print(contents); break;
+ case U_WMR_SETWINDOWEXT: U_WMRSETWINDOWEXT_print(contents); break;
+ case U_WMR_SETVIEWPORTORG: U_WMRSETVIEWPORTORG_print(contents); break;
+ case U_WMR_SETVIEWPORTEXT: U_WMRSETVIEWPORTEXT_print(contents); break;
+ case U_WMR_OFFSETWINDOWORG: U_WMROFFSETWINDOWORG_print(contents); break;
+ case U_WMR_SCALEWINDOWEXT: U_WMRSCALEWINDOWEXT_print(contents); break;
+ case U_WMR_OFFSETVIEWPORTORG: U_WMROFFSETVIEWPORTORG_print(contents); break;
+ case U_WMR_SCALEVIEWPORTEXT: U_WMRSCALEVIEWPORTEXT_print(contents); break;
+ case U_WMR_LINETO: U_WMRLINETO_print(contents); break;
+ case U_WMR_MOVETO: U_WMRMOVETO_print(contents); break;
+ case U_WMR_EXCLUDECLIPRECT: U_WMREXCLUDECLIPRECT_print(contents); break;
+ case U_WMR_INTERSECTCLIPRECT: U_WMRINTERSECTCLIPRECT_print(contents); break;
+ case U_WMR_ARC: U_WMRARC_print(contents); break;
+ case U_WMR_ELLIPSE: U_WMRELLIPSE_print(contents); break;
+ case U_WMR_FLOODFILL: U_WMRFLOODFILL_print(contents); break;
+ case U_WMR_PIE: U_WMRPIE_print(contents); break;
+ case U_WMR_RECTANGLE: U_WMRRECTANGLE_print(contents); break;
+ case U_WMR_ROUNDRECT: U_WMRROUNDRECT_print(contents); break;
+ case U_WMR_PATBLT: U_WMRPATBLT_print(contents); break;
+ case U_WMR_SAVEDC: U_WMRSAVEDC_print(contents); break;
+ case U_WMR_SETPIXEL: U_WMRSETPIXEL_print(contents); break;
+ case U_WMR_OFFSETCLIPRGN: U_WMROFFSETCLIPRGN_print(contents); break;
+ case U_WMR_TEXTOUT: U_WMRTEXTOUT_print(contents); break;
+ case U_WMR_BITBLT: U_WMRBITBLT_print(contents); break;
+ case U_WMR_STRETCHBLT: U_WMRSTRETCHBLT_print(contents); break;
+ case U_WMR_POLYGON: U_WMRPOLYGON_print(contents); break;
+ case U_WMR_POLYLINE: U_WMRPOLYLINE_print(contents); break;
+ case U_WMR_ESCAPE: U_WMRESCAPE_print(contents); break;
+ case U_WMR_RESTOREDC: U_WMRRESTOREDC_print(contents); break;
+ case U_WMR_FILLREGION: U_WMRFILLREGION_print(contents); break;
+ case U_WMR_FRAMEREGION: U_WMRFRAMEREGION_print(contents); break;
+ case U_WMR_INVERTREGION: U_WMRINVERTREGION_print(contents); break;
+ case U_WMR_PAINTREGION: U_WMRPAINTREGION_print(contents); break;
+ case U_WMR_SELECTCLIPREGION: U_WMRSELECTCLIPREGION_print(contents); break;
+ case U_WMR_SELECTOBJECT: U_WMRSELECTOBJECT_print(contents); break;
+ case U_WMR_SETTEXTALIGN: U_WMRSETTEXTALIGN_print(contents); break;
+ case U_WMR_DRAWTEXT: U_WMRDRAWTEXT_print(contents); break;
+ case U_WMR_CHORD: U_WMRCHORD_print(contents); break;
+ case U_WMR_SETMAPPERFLAGS: U_WMRSETMAPPERFLAGS_print(contents); break;
+ case U_WMR_EXTTEXTOUT: U_WMREXTTEXTOUT_print(contents); break;
+ case U_WMR_SETDIBTODEV: U_WMRSETDIBTODEV_print(contents); break;
+ case U_WMR_SELECTPALETTE: U_WMRSELECTPALETTE_print(contents); break;
+ case U_WMR_REALIZEPALETTE: U_WMRREALIZEPALETTE_print(contents); break;
+ case U_WMR_ANIMATEPALETTE: U_WMRANIMATEPALETTE_print(contents); break;
+ case U_WMR_SETPALENTRIES: U_WMRSETPALENTRIES_print(contents); break;
+ case U_WMR_POLYPOLYGON: U_WMRPOLYPOLYGON_print(contents); break;
+ case U_WMR_RESIZEPALETTE: U_WMRRESIZEPALETTE_print(contents); break;
+ case U_WMR_3A: U_WMR3A_print(contents); break;
+ case U_WMR_3B: U_WMR3B_print(contents); break;
+ case U_WMR_3C: U_WMR3C_print(contents); break;
+ case U_WMR_3D: U_WMR3D_print(contents); break;
+ case U_WMR_3E: U_WMR3E_print(contents); break;
+ case U_WMR_3F: U_WMR3F_print(contents); break;
+ case U_WMR_DIBBITBLT: U_WMRDIBBITBLT_print(contents); break;
+ case U_WMR_DIBSTRETCHBLT: U_WMRDIBSTRETCHBLT_print(contents); break;
+ case U_WMR_DIBCREATEPATTERNBRUSH: U_WMRDIBCREATEPATTERNBRUSH_print(contents); break;
+ case U_WMR_STRETCHDIB: U_WMRSTRETCHDIB_print(contents); break;
+ case U_WMR_44: U_WMR44_print(contents); break;
+ case U_WMR_45: U_WMR45_print(contents); break;
+ case U_WMR_46: U_WMR46_print(contents); break;
+ case U_WMR_47: U_WMR47_print(contents); break;
+ case U_WMR_EXTFLOODFILL: U_WMREXTFLOODFILL_print(contents); break;
+ case U_WMR_49: U_WMR49_print(contents); break;
+ case U_WMR_4A: U_WMR4A_print(contents); break;
+ case U_WMR_4B: U_WMR4B_print(contents); break;
+ case U_WMR_4C: U_WMR4C_print(contents); break;
+ case U_WMR_4D: U_WMR4D_print(contents); break;
+ case U_WMR_4E: U_WMR4E_print(contents); break;
+ case U_WMR_4F: U_WMR4F_print(contents); break;
+ case U_WMR_50: U_WMR50_print(contents); break;
+ case U_WMR_51: U_WMR51_print(contents); break;
+ case U_WMR_52: U_WMR52_print(contents); break;
+ case U_WMR_53: U_WMR53_print(contents); break;
+ case U_WMR_54: U_WMR54_print(contents); break;
+ case U_WMR_55: U_WMR55_print(contents); break;
+ case U_WMR_56: U_WMR56_print(contents); break;
+ case U_WMR_57: U_WMR57_print(contents); break;
+ case U_WMR_58: U_WMR58_print(contents); break;
+ case U_WMR_59: U_WMR59_print(contents); break;
+ case U_WMR_5A: U_WMR5A_print(contents); break;
+ case U_WMR_5B: U_WMR5B_print(contents); break;
+ case U_WMR_5C: U_WMR5C_print(contents); break;
+ case U_WMR_5D: U_WMR5D_print(contents); break;
+ case U_WMR_5E: U_WMR5E_print(contents); break;
+ case U_WMR_5F: U_WMR5F_print(contents); break;
+ case U_WMR_60: U_WMR60_print(contents); break;
+ case U_WMR_61: U_WMR61_print(contents); break;
+ case U_WMR_62: U_WMR62_print(contents); break;
+ case U_WMR_63: U_WMR63_print(contents); break;
+ case U_WMR_64: U_WMR64_print(contents); break;
+ case U_WMR_65: U_WMR65_print(contents); break;
+ case U_WMR_66: U_WMR66_print(contents); break;
+ case U_WMR_67: U_WMR67_print(contents); break;
+ case U_WMR_68: U_WMR68_print(contents); break;
+ case U_WMR_69: U_WMR69_print(contents); break;
+ case U_WMR_6A: U_WMR6A_print(contents); break;
+ case U_WMR_6B: U_WMR6B_print(contents); break;
+ case U_WMR_6C: U_WMR6C_print(contents); break;
+ case U_WMR_6D: U_WMR6D_print(contents); break;
+ case U_WMR_6E: U_WMR6E_print(contents); break;
+ case U_WMR_6F: U_WMR6F_print(contents); break;
+ case U_WMR_70: U_WMR70_print(contents); break;
+ case U_WMR_71: U_WMR71_print(contents); break;
+ case U_WMR_72: U_WMR72_print(contents); break;
+ case U_WMR_73: U_WMR73_print(contents); break;
+ case U_WMR_74: U_WMR74_print(contents); break;
+ case U_WMR_75: U_WMR75_print(contents); break;
+ case U_WMR_76: U_WMR76_print(contents); break;
+ case U_WMR_77: U_WMR77_print(contents); break;
+ case U_WMR_78: U_WMR78_print(contents); break;
+ case U_WMR_79: U_WMR79_print(contents); break;
+ case U_WMR_7A: U_WMR7A_print(contents); break;
+ case U_WMR_7B: U_WMR7B_print(contents); break;
+ case U_WMR_7C: U_WMR7C_print(contents); break;
+ case U_WMR_7D: U_WMR7D_print(contents); break;
+ case U_WMR_7E: U_WMR7E_print(contents); break;
+ case U_WMR_7F: U_WMR7F_print(contents); break;
+ case U_WMR_80: U_WMR80_print(contents); break;
+ case U_WMR_81: U_WMR81_print(contents); break;
+ case U_WMR_82: U_WMR82_print(contents); break;
+ case U_WMR_83: U_WMR83_print(contents); break;
+ case U_WMR_84: U_WMR84_print(contents); break;
+ case U_WMR_85: U_WMR85_print(contents); break;
+ case U_WMR_86: U_WMR86_print(contents); break;
+ case U_WMR_87: U_WMR87_print(contents); break;
+ case U_WMR_88: U_WMR88_print(contents); break;
+ case U_WMR_89: U_WMR89_print(contents); break;
+ case U_WMR_8A: U_WMR8A_print(contents); break;
+ case U_WMR_8B: U_WMR8B_print(contents); break;
+ case U_WMR_8C: U_WMR8C_print(contents); break;
+ case U_WMR_8D: U_WMR8D_print(contents); break;
+ case U_WMR_8E: U_WMR8E_print(contents); break;
+ case U_WMR_8F: U_WMR8F_print(contents); break;
+ case U_WMR_90: U_WMR90_print(contents); break;
+ case U_WMR_91: U_WMR91_print(contents); break;
+ case U_WMR_92: U_WMR92_print(contents); break;
+ case U_WMR_93: U_WMR93_print(contents); break;
+ case U_WMR_94: U_WMR94_print(contents); break;
+ case U_WMR_95: U_WMR95_print(contents); break;
+ case U_WMR_96: U_WMR96_print(contents); break;
+ case U_WMR_97: U_WMR97_print(contents); break;
+ case U_WMR_98: U_WMR98_print(contents); break;
+ case U_WMR_99: U_WMR99_print(contents); break;
+ case U_WMR_9A: U_WMR9A_print(contents); break;
+ case U_WMR_9B: U_WMR9B_print(contents); break;
+ case U_WMR_9C: U_WMR9C_print(contents); break;
+ case U_WMR_9D: U_WMR9D_print(contents); break;
+ case U_WMR_9E: U_WMR9E_print(contents); break;
+ case U_WMR_9F: U_WMR9F_print(contents); break;
+ case U_WMR_A0: U_WMRA0_print(contents); break;
+ case U_WMR_A1: U_WMRA1_print(contents); break;
+ case U_WMR_A2: U_WMRA2_print(contents); break;
+ case U_WMR_A3: U_WMRA3_print(contents); break;
+ case U_WMR_A4: U_WMRA4_print(contents); break;
+ case U_WMR_A5: U_WMRA5_print(contents); break;
+ case U_WMR_A6: U_WMRA6_print(contents); break;
+ case U_WMR_A7: U_WMRA7_print(contents); break;
+ case U_WMR_A8: U_WMRA8_print(contents); break;
+ case U_WMR_A9: U_WMRA9_print(contents); break;
+ case U_WMR_AA: U_WMRAA_print(contents); break;
+ case U_WMR_AB: U_WMRAB_print(contents); break;
+ case U_WMR_AC: U_WMRAC_print(contents); break;
+ case U_WMR_AD: U_WMRAD_print(contents); break;
+ case U_WMR_AE: U_WMRAE_print(contents); break;
+ case U_WMR_AF: U_WMRAF_print(contents); break;
+ case U_WMR_B0: U_WMRB0_print(contents); break;
+ case U_WMR_B1: U_WMRB1_print(contents); break;
+ case U_WMR_B2: U_WMRB2_print(contents); break;
+ case U_WMR_B3: U_WMRB3_print(contents); break;
+ case U_WMR_B4: U_WMRB4_print(contents); break;
+ case U_WMR_B5: U_WMRB5_print(contents); break;
+ case U_WMR_B6: U_WMRB6_print(contents); break;
+ case U_WMR_B7: U_WMRB7_print(contents); break;
+ case U_WMR_B8: U_WMRB8_print(contents); break;
+ case U_WMR_B9: U_WMRB9_print(contents); break;
+ case U_WMR_BA: U_WMRBA_print(contents); break;
+ case U_WMR_BB: U_WMRBB_print(contents); break;
+ case U_WMR_BC: U_WMRBC_print(contents); break;
+ case U_WMR_BD: U_WMRBD_print(contents); break;
+ case U_WMR_BE: U_WMRBE_print(contents); break;
+ case U_WMR_BF: U_WMRBF_print(contents); break;
+ case U_WMR_C0: U_WMRC0_print(contents); break;
+ case U_WMR_C1: U_WMRC1_print(contents); break;
+ case U_WMR_C2: U_WMRC2_print(contents); break;
+ case U_WMR_C3: U_WMRC3_print(contents); break;
+ case U_WMR_C4: U_WMRC4_print(contents); break;
+ case U_WMR_C5: U_WMRC5_print(contents); break;
+ case U_WMR_C6: U_WMRC6_print(contents); break;
+ case U_WMR_C7: U_WMRC7_print(contents); break;
+ case U_WMR_C8: U_WMRC8_print(contents); break;
+ case U_WMR_C9: U_WMRC9_print(contents); break;
+ case U_WMR_CA: U_WMRCA_print(contents); break;
+ case U_WMR_CB: U_WMRCB_print(contents); break;
+ case U_WMR_CC: U_WMRCC_print(contents); break;
+ case U_WMR_CD: U_WMRCD_print(contents); break;
+ case U_WMR_CE: U_WMRCE_print(contents); break;
+ case U_WMR_CF: U_WMRCF_print(contents); break;
+ case U_WMR_D0: U_WMRD0_print(contents); break;
+ case U_WMR_D1: U_WMRD1_print(contents); break;
+ case U_WMR_D2: U_WMRD2_print(contents); break;
+ case U_WMR_D3: U_WMRD3_print(contents); break;
+ case U_WMR_D4: U_WMRD4_print(contents); break;
+ case U_WMR_D5: U_WMRD5_print(contents); break;
+ case U_WMR_D6: U_WMRD6_print(contents); break;
+ case U_WMR_D7: U_WMRD7_print(contents); break;
+ case U_WMR_D8: U_WMRD8_print(contents); break;
+ case U_WMR_D9: U_WMRD9_print(contents); break;
+ case U_WMR_DA: U_WMRDA_print(contents); break;
+ case U_WMR_DB: U_WMRDB_print(contents); break;
+ case U_WMR_DC: U_WMRDC_print(contents); break;
+ case U_WMR_DD: U_WMRDD_print(contents); break;
+ case U_WMR_DE: U_WMRDE_print(contents); break;
+ case U_WMR_DF: U_WMRDF_print(contents); break;
+ case U_WMR_E0: U_WMRE0_print(contents); break;
+ case U_WMR_E1: U_WMRE1_print(contents); break;
+ case U_WMR_E2: U_WMRE2_print(contents); break;
+ case U_WMR_E3: U_WMRE3_print(contents); break;
+ case U_WMR_E4: U_WMRE4_print(contents); break;
+ case U_WMR_E5: U_WMRE5_print(contents); break;
+ case U_WMR_E6: U_WMRE6_print(contents); break;
+ case U_WMR_E7: U_WMRE7_print(contents); break;
+ case U_WMR_E8: U_WMRE8_print(contents); break;
+ case U_WMR_E9: U_WMRE9_print(contents); break;
+ case U_WMR_EA: U_WMREA_print(contents); break;
+ case U_WMR_EB: U_WMREB_print(contents); break;
+ case U_WMR_EC: U_WMREC_print(contents); break;
+ case U_WMR_ED: U_WMRED_print(contents); break;
+ case U_WMR_EE: U_WMREE_print(contents); break;
+ case U_WMR_EF: U_WMREF_print(contents); break;
+ case U_WMR_DELETEOBJECT: U_WMRDELETEOBJECT_print(contents); break;
+ case U_WMR_F1: U_WMRF1_print(contents); break;
+ case U_WMR_F2: U_WMRF2_print(contents); break;
+ case U_WMR_F3: U_WMRF3_print(contents); break;
+ case U_WMR_F4: U_WMRF4_print(contents); break;
+ case U_WMR_F5: U_WMRF5_print(contents); break;
+ case U_WMR_F6: U_WMRF6_print(contents); break;
+ case U_WMR_CREATEPALETTE: U_WMRCREATEPALETTE_print(contents); break;
+ case U_WMR_F8: U_WMRF8_print(contents); break;
+ case U_WMR_CREATEPATTERNBRUSH: U_WMRCREATEPATTERNBRUSH_print(contents); break;
+ case U_WMR_CREATEPENINDIRECT: U_WMRCREATEPENINDIRECT_print(contents); break;
+ case U_WMR_CREATEFONTINDIRECT: U_WMRCREATEFONTINDIRECT_print(contents); break;
+ case U_WMR_CREATEBRUSHINDIRECT: U_WMRCREATEBRUSHINDIRECT_print(contents); break;
+ case U_WMR_CREATEBITMAPINDIRECT: U_WMRCREATEBITMAPINDIRECT_print(contents); break;
+ case U_WMR_CREATEBITMAP: U_WMRCREATEBITMAP_print(contents); break;
+ case U_WMR_CREATEREGION: U_WMRCREATEREGION_print(contents); break;
+ default: U_WMRNOTIMPLEMENTED_print(contents); break;
+ } //end of switch
+ return(size);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/3rdparty/libuemf/uwmf_print.h b/src/3rdparty/libuemf/uwmf_print.h
new file mode 100644
index 0000000..54dfe9c
--- /dev/null
+++ b/src/3rdparty/libuemf/uwmf_print.h
@@ -0,0 +1,52 @@
+/**
+ @file uwmf_print.h
+
+ @brief Prototypes for functions for printing records from WMF files.
+*/
+
+/*
+File: uwmf_print.h
+Version: 0.0.2
+Date: 14-FEB-2013
+Author: David Mathog, Biology Division, Caltech
+email: mathog@caltech.edu
+Copyright: 2012 David Mathog and California Institute of Technology (Caltech)
+*/
+
+#ifndef _UWMF_PRINT_
+#define _UWMF_PRINT_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "uwmf.h"
+#include "uemf_print.h"
+
+//! \cond
+/* prototypes for objects used in WMR records (other than those defined in uemf_print.h) */
+void brush_print(U_BRUSH b);
+void font_print(const char *font);
+void pltntry_print(U_PLTNTRY pny);
+void palette_print(const U_PALETTE *p, const char *PalEntries);
+void pen_print(U_PEN p);
+void rect16_ltrb_print(U_RECT16 rect);
+void rect16_brtl_print(U_RECT16 rect);
+void region_print(const char *region);
+void bitmap16_print(U_BITMAP16 b);
+void bitmapcoreheader_print(U_BITMAPCOREHEADER ch);
+void logbrushw_print(U_WLOGBRUSH lb);
+void polypolygon_print(uint16_t nPolys, const uint16_t *aPolyCounts, const char *Points);
+void scan_print(U_SCAN sc);
+void dibheader_print(const char *dh, const char *blimit);
+
+/* prototypes for WMF records */
+int wmfheader_print(const char *contents, const char *blimit);
+void U_WMRNOTIMPLEMENTED_print(const char *contents);
+int U_wmf_onerec_print(const char *contents, const char *blimit, int recnum, size_t off);
+//! \endcond
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UWMF_PRINT_ */